commit 9b1c0e006f20091f28f3f468cfcab1feb51286bd Author: Neo2003 Date: Thu Oct 2 16:23:55 2008 -0500 [svn] * Proper SVN structure --HG-- branch : trunk diff --git a/6700-670 b/6700-670 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 00000000000..72936186406 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,20 @@ +The AUTHORS file: + +This file should collect a trace of all the legal paperwork that you have +exchanged with contributors for your particular package. This information is +very useful for registering the copyright of your package. The file might +have an introductory blurb similar to this one: + + Authors of PACKAGE + + The following contributions warranted legal paper exchanges + with [the Free Software Foundation | Your Name]. + Also see files ChangeLog and THANKS + +Then, list who the contributors are and what files they have worked on. +Indicate whether they created the file, or whether they modified it. For +example: + + Random J. Hacker: + entire files -> foo1.c , foo2.c , foo3.c + modifications -> foo4.c , foo5.c diff --git a/COPYING b/COPYING new file mode 100644 index 00000000000..d60c31a97a5 --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + 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 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 00000000000..089396b03e7 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,595 @@ +MaNGOS 0.12 (??? ??? 2008) http://www.mangosproject.org/trac/milestone/0.12 + + MaNGOS 0.12 - Codename "???" - adds further improvements to the + server core as well as to the majority of game classes and the game content + database. + + ==== Game Features ==== + + ==== Server Features ==== + + ==== Statistics ==== + * Fixed Bugs: ??? + * Total number of changes: ??? + + The complete list of closed tickets can be found here: + http://www.mangosproject.org/trac/query?status=closed&milestone=0.12 + +MaNGOS 0.11 (Jul 22 2008) http://www.mangosproject.org/trac/milestone/0.11 + + MaNGOS 0.11 - adds further improvements to the + server core as well as to the majority of game classes and the game content + database. + + ==== Game Features ==== + + * Added: Support for show possible blocked damage, armor penetration, negative stats and other data in client. + * Added: Support for show aura charges in client. + * Added: Support for spell casting delay at damage dependence from casting partly interrupts amount, apply interrupts in spell direct damage case also. + * Added: Support for form requirement check for item/itemset casts at equip. Correctly cast at equip and cast/remove at form switch. + * Added: Support for correct speed bonus stacking. + * Added: Support for instant honor updating. + * Added: Support for cap experience received from high level creatures. + * Added: Support mining/herbalism mode for skinning of special creatures. + * Added: Support for more battleground types, many improvements in battlegrounds work. + * Added: Support for quests work with player title rewards, check for shareable quests base at quest flags. + * Added: Support for quest rewarding with mail send after specific delay with possible items sent. + * Added: Support for boss +3 target dependent level for attack rolls and chances. + * Added: Support for dodge chance calculations depends from agility and level (use dbc based values) instead wrong hardcoded values. + * Added: Support for defense/weapon skills maxed in PvP fight. + * Added: Support for bilinear interpolation use for height calculation between existed map point data for better ground height selection for point. + * Added: Support for corpse reclaim delay dependence from character death count in last period. + * Added: Support for creatures movement flags storing in DB and setup from scripts, also store extra flags to mark creatures that can't parry/block/counterattack or not provide xp at kill. + * Added: Support for offhand expertize. + * Added: Support for generation of pet passive auras by DBC data. + * Improved: Re-Implemented group/friend/enemy/pet area auras. + * Improved: Finished fill spell_affect DB table allow have related spells correct working. Now only required update table at client switch. + * Improved: Allow DoTs/HoTs ticks from dead caster if its not required caster alive state. + * Improved: Better spell targeting selection code. + * Improved: Removed outdated honor diminishing return support. + * Improved: Fixed well known unexpected sit at stun bug. + * Improved: More correct show and work with faction reputation. + * Improved: Finish update to expected level dependent mana/health stats data for player's classes. + * Improved: Better creature corpse despawn time selection. Corpse instant despawn after skinning. + * Improved: Better check in front spell target requirement. + * Improved: Show parry/dodge/block/crit calculation in client for same level creature enemy. + * Improved: Correctly show item random property in all cases, including random property with suffix factor, in inspect and in equipped state at other player. + * Improved: Use correct way to check binding items and check enchants apply in trade slot. + * Improved: Rewritten mana regen calculation, also implement creature in combat mana regeneration delay. + * Improved: Fixed long time existed problem with unexpected auto start melee attack after spell casting. + * Improved: Re-implemented diminishing returns system. + * Improved: Re-implemented fear movement. + * Improved: Rewritten distract/dispel/spell steal effects. + * Improved: Updated pet name generation data in DB. + * Improved: Better work combat enter/leave system in PvP/PvE cases. + * Improved: Many items and item set effects start work. + * plus lots of fixes for auras, effects, spells, talents, and more. + + ==== Server Features ==== + + * Added: New sql/tools directory for useful SQL queries for check and restore DB integrity. + * Added: Own counter for HIGHGUID_PET low guids. Use it for pets. This let have lot more range for pet guids, and then more creature guid for instances spawns/totems. + * Added: Replace existed random generators by Mersenne Twister random number generator. + * Added: Support for Russian, Spanish Mexico, traditional and simplified Chinese clients to ad.exe. + * Added: Support for using the failed_logins field in the account table. Support IP/account temporary ban at max allowed failed logins for account. + * Added: Support for --enable-doxygen to enable doc generation at configure use at Unix/Linux. + * Added: Anti-freeze system. + * Added: AD.EXE now also extracts DBC files. It also now searches for patch files dynamically. + * Improved: Updated MySQL client libs to 5.0.56. + * Improved: Better checking DB data at server loading. + * Improved: Apply reserver names check to pet/charter names also. + * Improved: Move hardcoded base fishing skill for zone from code to new DB table. + * Improved: Removed `spell_learn_skill` and `PlayerCreateInfo_skill` tables, use DBC data instead. + * Improved: Many improvements in Gamemaster chat commands. + * Improved: Many improvements in config options. + * Improved: Better scripting support (DB base and C++ based scripts). + + ==== Statistics ==== + * Fixed Bugs: 194 + * Total number of changes: 708 + + The complete list of closed tickets can be found here: + http://www.mangosproject.org/trac/query?status=closed&milestone=0.11 + +MaNGOS 0.10 (Apr 18 2008) http://www.mangosproject.org/trac/milestone/0.10 + + MaNGOS 0.10 - adds further improvements to the + server core as well as to the majority of game classes and the game content + database. + + ==== Game Features ==== + + * Added: Implement talent inspecting. + * Added: Implement unique equipped items support, including gems. + * Added: Check instances where mount using allowed. Still need implement in-building check. + * Added: Implement master looter loot mode. + * Added: Implement quest related lootable gameobject activating only for characters with active quest. + * Added: Implement multi-map taxi flights, allow teleport to instances/battleground in taxi flight time. + * Added: Allow equip 2hand weapon in case swap with equipped mainhand/offhand weapon pair. + * Added: Implement player confirmation request at player summon attempt. + * Added: Implement support items with limited lifetime. + * Added: Implement chance additional items crafting with appropriate profession specialization. + * Added: Implement FFA PvP zones and FFA PvP server type. + * Added: Implement Guild Banks. + * Added: Implement expertise and better rating work. + * Added: Implement dialog status show for gameobject like yellow exclamation signs above gameobject if quest available. + * Added: Implement money requirement show for gossip box open. + * Added: Apply reputation discounts to trainer spell prices. + * Added: Implement death at fall to void/textures. + * Added: Support dead by default creatures. + * Added: Implemented work some nice items like "safe" teleport items. + * Added: Implement correct stacking elixirs/flasks. + * Added: Implement Fishing hole gameobjects work. + * Added: Implement support correctly sitting at chairs with different height and slots. + * Added: Implement normalized weapon damage use where it expected. + * Improved: Limit player money amount by 214748g 36s 46c. + * Improved: Allow join to LFG channel if character registered in LFG tool. + * Improved: Better detection and calculation in fall damage. + * Improved: Update XP generation for high levels and use coefficients dependent from new/old continents position. + * Improved: Better immunity/resisted/interrupting spell work. + * Improved: Better check area/zone/map/mapset limited spells at cast and zone leave. + * Improved: Fixed long time existed problems with client crash at group member using transports. + * Improved: Add/update lot spell_affect/spell_proc_event tables content that let work many talents, spells, and item effects. + * Improved: Better mail system work, use it for problematic items at character loading, and sending honor marks if need. + * Improved: Use correct coefficients for damage/healing spell bonuses for many spells. + * Improved: Restore work weather system. + * Improved: More correct spell affects stacking at target, and spell icons stacking in spellbook. + * Improved: More correct work explicit target positive aura rank auto-selection and implemented area auras rank auto-selection. + * Improved: Correct work permanent skill bonuses. + * Improved: Prevent lost money at unexpected double pay for learned spell with lags. + * Improved: More correct show for other players character state under different spell affects and in time spell casting. + * Improved: More correct random item enchantment bonuses selection and work code. + * Improved: Better battlegrounds work. + * Improved: Implement default open doors/pushed buttons support. + * plus lots of fixes for auras, effects, spells, talents, and more. + + ==== Server Features ==== + + * Added: broken spells check at use and loading. + * Added: Implement pid file support. + * Added: Extract and include svn revision version data in binaries at build. + * Added: Implement binding socket to specific network interface (IP address) instead all interfaces using new config option. + * Added: Implement support 64-bit binaries building at Windows. + * Added: Enable the LARGEADDRESSAWARE flag for Visual Studio 2003 mangosd and realmd projects. + * Improved: Allow Gamemasters see any creature/gameobject including invisible/stealth, allow select unselectable units. + * Improved: Many server-side check for casts (while shapeshifted, other caster and target reqirents) to prevent cheating. + * Improved: better loot system implementation including more loot conditions support and simplify loot managment for DB creators. + * Improved: better DB content error reporting at server load.` + * Improved: Many improvements in Gamemaster chat commands. + * Improved: Update sockets library to v.2.2.9 version. + * Improved: More arena support but not full yet. + * Improved: Less amount data sent to clients, including in spell casting time. + * Improved: Fixed/finish PostgreSql support. + * Improved: Better scripting support (DB base and C++ based scripts). + + ==== Statistics ==== + * Fixed Bugs: 784 + * Total number of changes: 804 + + The complete list of closed tickets can be found here: + http://www.mangosproject.org/trac/query?status=closed&milestone=0.10 + +MaNGOS 0.9 (Dec 14 2007) http://www.mangosproject.org/trac/milestone/0.9 + + MaNGOS 0.9 - Codename "Flight Master" - adds further improvements to the + server core as well as to the majority of game classes and the game content + database. + + ==== Game Features ==== + * Added: support for recipe discovery, + * Added: support for allowing use of an item only in a specific map or area, + * Added: support for free-for-all quest/non-quest loot items, additional loot conditions, + * Improved: a more correct implementation of XP gain (level dependent) when in a group, + * Improved: fixed creature killed from DoTs but remaining stuck with 1/3 health, + * Improved: spell and melee crit chance now calculated from DBC data and combat rating coefficients, + * Improved: a more correct implementation of mana/health regeneration calculation, including quick health regeneration in a polymorphed state, + * Improved: better support for quests with multiple speakto goals, less dependent on DB for quest flag calculation, + * Improved: more functionality added to battlegrounds, including correctly showing battleground scores, + * Improved: a more correct implementation of reputation gain for other factions from the same team, + * Improved: better support for simple database scripts (quest-start/end, buttons, spells) + * plus lots of fixes for auras, effects, spells, talents, and more. + + ==== Server Features ==== + * Added: support for running mangosd/realmd as Windows services, + * Added: support for auto-generation of mangosd/realmd crash reports (Windows version only), + * Added: support for Visual Studio 2008 Express and Pro, + * Added: support for new Char.log for basic character operations, including save dump of character data on deletion, and logging client IP, + * Added: support for players queue at login, + * Improved: better DB content error reporting at server load, + * Improved: division of Mangos DataBase to MangosDB(WorldDB) and CharactersDB. + * Improved: better support for older autoconf / automake versions, + * Improved: existing chat and console commands for server gamemasters/administrators, and added new commands. + + ==== Statistics ==== + * Fixed Bugs: 161 + * Total number of changes: 228 + + The complete list of closed tickets can be found here: + http://www.mangosproject.org/trac/query?status=closed&milestone=0.9 + +MaNGOS 0.8 (Oct 16, 2007) http://www.mangosproject.org/trac/milestone/0.8 + + MaNGOS 0.8 - Codename "Innkeeper" - adds further improvements to the + server core as well as to the majority of game classes and the game content + database. + + Important License Change Notice: MaNGOS still is licensed under the terms + of the GPL v2, but we now have added an exception to officially allow our + users to link MaNGOS against the OpenSSL libraries. + + ==== Game Features ==== + * Added: a new threat manager was introduced, + * Added: log more GM activities, + * Added: many new features for creatures and game objects working, + * Added: support for client build 6898, aka version 2.1.3, + * Added: support for custom creature equipment and display, + * Added: support for daily quests, + * Added: support for different fishing loot in sub-zones, + * Added: support for gender specific models, + * Added: support for instance specific scripts and data, + * Added: support for localization of names, texts, etc., + * Added: support for multiple battleground instances, + * Added: support for scripted game object buttons, + * Improved: battlegrounds should be mostly working, only a few issues left, + * Improved: dungeon system has seen a few improvements, + * Improved: formulas for most aspects of the game, + * Improved: many player level up values have been corrected, + * Improved: pet and demon handling has seen a lot of improvements, + * Improved: properly divide loot and reputation in groups, + * Rewritten: battleground queue system, + * Rewritten: invisibility detection, + * plus lots of fixes for auras, effects, spells, talents, and more. + + ==== Server Features ==== + * Added: support for database transactions, + * Added: support for height maps -- named vmaps -- to tackle the LOS issue, + * Added: support for OpenBSD and FreeBSD building, + * Fixed: lots of memory leaks closed, + * Fixed: Numerous bug fixes to the core, + * Improved: database queries adding performance boosts here and there, + + ==== Statistics ==== + * Fixed Bugs: 528 + * Total number of changes: 558 + + The complete list of closed tickets can be found here: + http://www.mangosproject.org/trac/query?status=closed&milestone=0.8 + +MaNGOS 0.7 (Jul 9, 2007) http://www.mangosproject.org/trac/milestone/0.7 + + MaNGOS 0.7 - Codename "Eye of the Storm" -adds further improvements to the + server core as well as to the majority of game classes and the game content + database. + +==== Game Features ==== + * Fixed: random item enchantment display in the auction/mail/group loot dialogs. The item properties are also properly applied to the items at creation. + * Added: support for opening gameobjects/items using their specific keys. Implemented key requirements for entering instances. + * Added: a threat based aggro system along with threat bonuses from spells. + * Implemented many additional spell effects and auras. The spell system is one step closer to completeness. + * Improved: creature/player hostility checks using more accurate faction hostility data. Hostility is checked when casting spells including area-of-effect spells. + * Fixed: parry/dodge related code. + * Improved rage generation formula on blocked attacks/armor reduction etc. + * Fixed: creature movement problems after creature stun/roots and creature orientation in some cases. + * Fixed: some small problems in the player inventory system. + * Added: support for all resurrection methods for various classes. Resurrection from corpse is also implemented. + * Fixed: showing cooldown for items and spells, server side check and saving to the database is also implemented. + * Added: support for gift creation. + * Improved: the pet system and more improvements will follow in next release. + * Added: keyring support. + * Improved: many features related to raids/groups. + * Added: support for in game guild creation. Guild system can be considered finished. Arena team creation is also partly implemented. + * Added: target immunity. The targetable flag and the creature type limitation for spell targeting, which is now check when creating the target list, allows area spells against specific creature types like undeads/demons to work. + * Added: support for diminishing duration of stun/fear/etc effects. + * Rewrote: pet stable code along with improvements and bug fixes. + * Added: support for who list filters. + * Added: the instance system. + * Fixed: the weather system, now common weather is shown for all players in the same zone. + * Improved: the mail system and implemented the delay for mails containing items. + * Added: an initial version of the battleground system. One type of battleground is mostly done, still needs more work. + * Added: the jewelry profession, prospecting and support for inserting gems in sockets including meta gems bonuses. + * Added: support for multi-mining veins. + * Added: support for auto-renaming of characters on login at the request of GMs. + * Added: a new, more correct visibility system, invisibility is also implemented correctly now. + * Improved: durability cost calculation. + + ==== Server Features ==== + * Added: full support for 2.0.x client branch. + * Added/improved: many GM-commands. + * Added: many checks for DB data at server load to simplify detecting problems and DB development. + * Moved: many data stored in code to the DB and cached most static DB data at server load to speed up runtime access to it. + * Added: support for saving next spawn time for creatures/GOs which is now used it at grid/server load. + * Improved: the script system allowing more item/creature/GO scripts with more features to be written easily. + * Added: size checking for all packets received from the to prevent crashes at wrong data. Many other received data check were also added to prevent cheating. + * Improved: the compatibility with 64-bit platforms. + * Added: support for account password encryption in the DB to increase secure security. + * Added: support for a log directory and the date info is now added to log name. + * Updated: the network library to a recent version. + * Fixed: many memory leaks and crases sources. + * Added: DBC locale support that can be set from mangosd.conf. + + ==== Statistics ==== + * Fixed Bugs: 390 + * Total number of changes: 923 + + The complete list of closed tickets can be found here: + http://www.mangosproject.org/trac/query?status=closed&milestone=0.7 + +MaNGOS 0.6 (Jan 29, 2007) http://www.mangosproject.org/trac/milestone/0.6 + + MaNGOS 0.6 - Codename "Black Dragonflight" - adds further improvements to the + server core as well as to the majority of game classes and the game content + database. + + ==== Game Features ==== + * Creature and game object respawning has finally been fixed and is considered finished. + * Many improvements to decrease time for saving player data, and transaction support for save operations has been added. + * Many item fixes for using / equipping/ enhancing function (some errors still remain and have to be resolved). + * All professions work now (many fixes have been implemented, you may now enjoy fishing). + * Mail and auction house system has been rewritten, finally should work as it supposed to be. + * Spell system has received a HUGE number of improvements, and should feel much better. (Still many problems are left to be fixed, most notable include procflag spell casting, also many effects and auras are not implemented yet). + * Pet-stable implemented. Many improvements in hunter and warlock pet system (Problems with pet casting exists, various other minor bugs too). + * Rest system can be considered finished. + * Quest system has been rewritten (some problems remain unresolved). + * Implemented PvP system, and support PvE and PvP realm types. + * Duel system has been rewritten and can be considered complete (minor bugs still remain: e.g. characters sometimes may be killed in duels by channeled spells, or after duels finished by pets still attacking). + * Guild system improvements, including guild charter, guild master, and guild tabard work. (Some bugs reported about losing tabard style, etc). + * Some taxi system fixes and improvements. Switched to use DBC only data for taxi system work. + * Group related code has been rewritten, and extended to support raid groups. + * Loot code improvements and implementing group loot modes (except master loot mode). + * Correct implementation for creature skinning has been added. + * Unlearning talents, and unlearning spells with first rank received from unlearned talent implemented. + * Transports (ships/zeppelins) system implemented (still have some synchronization problems). + * Many fixes in combat system (Still have many problems). + * Enchanting in trade slot implemented as last not implemented part of trade system. Many other fixes. + * Rogue stealth for other players implemented and many fixes in druid forms. + + ==== Server Features ==== + * Full support for 1.12.x client branch has been implemented. + * Many GM-commands added and improved including GM mode state and GM invisibility. + * Many cheating preventing checks added and code rewrites. + * DB-based scripting support added for quest emote scripts and spell event scripts. + * Many improvements in less client-server data amount transferring. + + ==== Statistics ==== + * Fixed Bugs: 306 + * Total number of changes: 874 + + The complete list of closed tickets can be found here: + http://www.mangosproject.org/trac/query?status=closed&milestone=0.6 + +MaNGOS 0.5 (Sep 20, 2006) http://www.mangosproject.org/trac/milestone/0.5 + + MaNGOS 0.5 - Codename "Stable Master" - adds further improvements to the + server core as well as to the majority of game classes and the game content + database. + + Most noteable changes include cleaning up the database backend, adding proper + support for game clients of version 1.10.2, and closing lots of threading and + memory related bugs. Cross-platform support has been improved as well, MaNGOS + should build and run on FreeBSD as well. + + Feature-wise, support for pets, totems, more spells, talents, etc. have been + added, as well as lots of quest related features. + + ==== Statistics ==== + * Fixed Bugs: 544 + * Total number of changes: 1828. + + The complete list of closed tickets can be found here: + http://www.mangosproject.org/trac/query?status=closed&milestone=0.5 + +MaNGOS 0.1 (Dec 04, 2005) http://www.mangosproject.org/trac/milestone/0.1 + + MaNGOS 0.1 - Codename "Lightbringer" -adds further improvements to the server + core as well as to the majority of game classes and the game content database. + A complete list of all updated items follows below: + + === Game Features === + * Add all AI files to the build process on Windows + * Added: Better item information updates. + * Added: Check on death for invalid duel status. + * Added: Client now shows full Creature information. + * Added: Creature::_RealtimSetCreatureInfo procedure which only sets changed values for realtime usage. + * Added: DEBUG_LOG for logging debug messages. Works with --debug-info switch on Linux and debug build on Windows. + * Added: Extra information for NPC and item information transmissions. + * Added: GM command .modify spell spellflatID,val,mark. + * Added: Guild structures, creation, saving data to DB. + * Added: Initial support for binding heart stones to a location. + * Added: Initial support for Guilds. Loading from DB, class, creation and management functions, plus some opcodes supported. + * Added: Initial support for item stacks. + * Added item page text display for detailed item info. + * Added: Level 3 command for Guild creation. + * Added: Linux Makefiles will now install mangosd.conf to sysconfdir when running "make install" after build. + * Added pragma's to disable stupid compiler warnings. Code now compiles cleanly. + * Added: Random generation of damage values for weapons based on their level. + * Added: RandomMovementGenerator. Template not yet implemented. + * Added SharedDefines.h (and updated some enums with more values). + * Added: Sheath code. + * Added: Some DB cleaning tools, hard-coded damage can be removed now. + * Added: some movement related classes. + * Added: SQL tables for guilds. + * Added: Support for additional spells. + * Added support for AIM system ( Artificial Intelligence and Movement ). + * Added: Support for client 1.8.3. + * Added support for Guild System, still has some bugs, about 85% done. + * Added support for Honor System, initial support is done, calculations need love. + * Added support for IP logging of players. + * Added: Support for page texts. + * Added: Support for QuestAreaPoints. + * Added support for reputation. + * Added: Support for tutorials. + * added the opcode name in the world.log for bether cheking + * Added: Weapon damage genrator now adds extra damage types for some items. + * Add Tools,DBC Editer,you can use it to edit all .dbc File, + * AI delivery + * Fix duel flag object position + * Fixed and sped up the players array code. + * Fixed: Armor settings. + * Fixed: Bug fixes for crash and other stuff. + * Fixed: Character bug on login closed. + * Fixed character creation bug + * Fixed: Commented wrong lines in last commit. Now correct ones commented. + * Fixed: Creation of item spells. + * Fixed: Creature::SaveToDB() code fixed. I messed it up while trying to sort out NPC corpse issue. Now back to normal. + * Fixed dead NPC issue. + * Fixed: Double Jump bug fixed with a temporary solution. + * Fixed: Fixed duplicate inclusion of Opcodes.cpp and Opcodes_1_7_x.cpp in game and mangosd directory for VC7 build. + * Fixed: Friendly NPCs attacking. + * Fixed Game Objects, now signs other objects all display. + * fixed gametickets at last,added error handling,character can have only 1 gmticket + * Fixed: Handle the bad data for guid and LOW/HIGH GUID. + * Fixed: Intel C++ VC project now compiles. + * Fixed: Item query code fixed. Item now display most stats (90%). + * Fixed: ItemQuery opcode. This prevents a crash when talking to some vendors. + * Fixed: Minor fixes for Creatures health, added some comments. + * Fixed: NPC texts. + * Fixed: One of the lines in ObjectAccessor.cpp wa removed by accident in changeset #356, causing nearby creatures not roaming, thus not attacking for aggressors. + * Fixed: Proper comparison for maxhealth. + * Fixed: Release build for 1.8 and default Grid ON + * Fixed: Resolve dead NPCs, maxhealth setting. + * Fixed Skill check for equiping Items. + * Fixed: Small fix for Windows build in ObjectAccessor::Update(const uint32 &diff). + * Fixed: Talent modifiers. + * Fixed: Talent percent work. + * Fixed: Vendors now load and display items. + * Fix: now the player can only equip item, if have the proper skill + * Fix two player in the same zone cores. Fix mem leaks in 1.8 mask deletion. And fix core dump for npc handler due to GUI only takes lower part. + * Function _ApplyItemMods() is protected... then i created a public function ApplyItemMods() that calls it... Object Oriented Project, guys! + * Function SetStanding() has been created. Now needs to put it on places where the standing of the reputation is increased. + * Initial delivery of the AI framework.. + * Major CPU usage improvements with grid system disabled. + * msg of ignore list fixed + * Now Faction.dbc is being loaded. + * Progress bar code enhanced. + * Put back compression. Apparently the core problem of two players is NOT solved cuz I can still replicate it. + * Removed: All ENABLE_GRID_SYSTEM defines removed. + * Removed: Some operation out of Creature::Updated. Resolve dead NPCs. + * Reputation: first step. List of factions has been created. Some opcodes are working now. + * Reputation: second step. _LoadReputation, _SaveReputation, LoadReputationFromDBC functions have been created. Now all reputation factions are into factions list. + * Reputation System is now fixed. All functions are fixed. Load and save to DB are fine. The file reputation.sql has been updated. + * Reputation table has been created... update your Data Base! + * Resolved: Outstanding issues in phase 2 of grid system, still some left. + * Small reputation table sql fix for compatability. Remove latin character requirement. + * Started adding Enchant spell code. + * Started writing local items cache. (disabled) + * Still working on reputation... now FactionTemplate.dbc is loaded. + * Trainer code fixed. Items now disappear when you learn them. + * Trainer code update. + * Updated: Added guild sql files to Linux Makefile. + * Updated: Adjusted Item Query code. + * Updated: AtWar flag will now bet set for hostile fractions by LoadReputationFromDBC function. + * Updated: Changed transmission of item information. + * Updated: Creature display updates. + * Updated: Deliver Grid system phase 2 for VC7. The Grid System (TGS) completed. + * Updated: Display nicer statistics on daemon startup. + * Updated: FactionTemplate now hashed. + * Updated Game Objects. Looting works, loot template missing, support for Herbs, Mines, Locks missing. + * Updated: Item text pages now display additional information. + * Updated mail support. Now fully works. + * Updated: More debug cleanings. + * Updated: More grid optimizations. + * Updated: only updated creatures/objects near adjacent cell of where player stands. Also intersection of cell between player should update once. + * Updated: On Quest completion your faction reputation will increase properly. + * Updated: Quest and NPC text loading modified to suit the new tables. + * Updated: Quest code will now read the Creature_ID from the table. + * Updated: Removed some obsolete code. + * Updated: Rewrote urand() procedure to fix conflicted SVN. + * Updated: _SetCreatureTemplate() must be run in an update. When set on creation, it has no effect. + * Updated: Spell time recution talents now fully work. + * Updated: The Grid System (TGS) is now on by default. Not support grid off. Next, (1) deliver phase 2 stuff and (2) remove ifdef and ALL old classes. + * Updated: TRUNCATE is faster than DELETE + + === Server Features === + * Added CLI interface for server. Needs to be enabled on compile-time. + * Reorganized Spell System, separated effects to a diferent file, for better fixing. + + ==== Statistics ==== + * Fixed Bugs: #14, #17, #20, #22, #23, #24, #25, #26 + * Total number of changes: 193. + + The complete list of closed tickets can be found here: + http://www.mangosproject.org/trac/query?status=closed&milestone=0.1 + +MaNGOS 0.0.3 (Nov 15, 2005) http://www.mangosproject.org/trac/milestone/0.0.3 + + MaNGOS 0.0.3 - Codename "Mango Carpet" - was mainly a bug fix release, which + never was published on the web, and just marks a point in development where + a damn lot of bugs had been fixed, but we still felt the need for further work + to be done before a release could be pushed to the world. + +MaNGOS 0.0.2 (Oct 31, 2005) http://www.mangosproject.org/trac/milestone/0.0.2 + + MaNGOS 0.0.2 - Codename "Library" - adds another bunch of improvements, bug + fixes and major enhancements to the overall functionality of the daemon. A + complete list of all updated items follows below: + + ==== Game Features ==== + * Added support for area exploration. + * Added support for duels. + * Added support for ticket system. + * Added support for trading. + * Added support for NPC movement when there are no waypoints defined. + * Added support for NPC gossip, now handling options, and providing default options. + * Added attack code for creatures. + * Added default data for realm list. + * Fixed character logout. Players can only log out when not in combat. + * Fixed friends and ignore lists. + * Fixed game objects to have proper sizes. + * Fixed item swapping. + * Fixed player factions. + * Fixed vendors. They now work without requiring gossip texts defined, as long as they have objects to sell. + * Updated command descriptions to be more meaningful. + * Updated default data for player creation. Actions, items, skills and spells moved to database. + + ==== Server Features ==== + * Added support for building with Intel C++ compiler on Windows. + * Added support for building with debug info on Linux. Use --with-debug-info switch to include debug info. + * Added support for building with 1.8.x protocol as default protocol. Use the 1.8.x build configurations in Visual Studio or --enable-18x switch on Linux. + * Added support for building with 1.7.x protocol. Use the 1.7.x build configurations in Visual Studio or --enable-17x switch on Linux. + * Added support for internal httpd server added for those not running Apache. --enable-httpd-integrated will add it. Windows solution available. + * Added support for displaying progress bars for daemon startup loading. + * Added support for on demand Grid Loading/Unloading system, which is disabled by default. + * Added core application framework. + * Added support for console commands (setgm,ban,create,info) + * Added command line switch -c for pointing to a custom configuration file. By default file from _MANGOSD_CONFIG (defined in src/mangosd/Master.h.in) will be used. + * Fixed ZThread build process. + * Fixed segmentation fault on zone map test due to access of array out of bound. Also, change m_ZoneIDmap to use bitset instead of the 4 bytes bool. + * Fixed memory leak problems. The creation of new TYPE[] must delete with [] for correctness otherwise n-1 members are leaked. + + ==== Statistics ==== + * Fixed Bugs: #4, #7, #12, #13, #16, #18, #19 + * Total number of changes: 225. + + The complete list of closed tickets can be found here: + http://www.mangosproject.org/trac/query?status=closed&milestone=0.0.2 + +MaNGOS 0.0.1 (Sept 13, 2005) http://www.mangosproject.org/trac/milestone/0.0.1 + + MaNGOS 0.0.1 - Codename "Endeavour" - contains a great number of new features, + improvements and bug fixes. The following list contains all of them: + + * NPC gossips now hash by Guid instead of ID. ID is meaningless and we should revisit its usage. + * Fixed client crash issue. GameObject still not interactive. Flags issues. + * Introduced new gameobjecttemplate table as well new map files. + * Added SCP-to-SQL converter to contrib/scp-to-sql/. + * MySQL 4.0 branch now is minimum requirement. + * Server causes client to core on unintialized memory. Also, remove some debug statement which causes problem when the DB is large + * Creature loot now reads from the creatureloot table. Use a new algorithm to select loot items that mimic the probabilities assigned in each item. + * Fixed configuration file, added proper settings for packet logging. + * Added default data for player creation and command help. + * Added GM command: .addspw #entry-id. Spawns a creature from creaturetemplate table by given #entry-id. + * Server randomly cores if DBC file failed to load. Fixes by intializing all DBC class internal variables. + * Daemon version and path to daemon configuration now set by build system on compile time. + * Allow connections from client release 4544 + * Update solution and project files for latest Visual Studio .NET 2005 Beta 2 release. + * Fixed compiler error for gcc 4.0 or higher. Calling templated base class methods has to be explicit from 4.0 or higher on. + * Added contrib/ subdirectory for third-party tools. + * Applied MaNGOS code indention schema. + * Initial code checked into repository. + + ==== Statistics ==== + * Fixed Bugs: #2, #3, #9, #10, #11 + * Total number of changes: 53. + + The complete list of closed tickets can be found here: + http://www.mangosproject.org/trac/query?status=closed&milestone=0.0.1 diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 00000000000..39271894923 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,58 @@ +# Copyright (C) 2005-2008 MaNGOS +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## Process this file with automake to produce Makefile.in + +## Sub-directories to parse +SUBDIRS = dep doc sql src + +## Additional files to include when running 'make dist' +# Win32 project workspace for Visual Studio .NET 2003 +EXTRA_DIST = \ + win/mangosdVC71.sln \ + win/VC71/framework.vcproj \ + win/VC71/game.vcproj \ + win/VC71/TrinityCore.vcproj \ + win/VC71/TrinityRealm.vcproj \ + win/VC71/shared.vcproj \ + win/VC71/zlib.vcproj \ + win/VC71/g3dlite.vcproj \ + win/VC71/zthread.vcproj + +# Win32 project workspace for Visual Studio .NET 2005 +EXTRA_DIST += \ + win/mangosdVC80.sln \ + win/VC80/framework.vcproj \ + win/VC80/game.vcproj \ + win/VC80/TrinityCore.vcproj \ + win/VC80/TrinityRealm.vcproj \ + win/VC80/shared.vcproj \ + win/VC80/zlib.vcproj \ + win/VC80/g3dlite.vcproj \ + win/VC80/zthread.vcproj + +# Win32 project workspace for Visual Studio .NET 2008 +EXTRA_DIST += \ + win/mangosdVC90.sln \ + win/VC90/framework.vcproj \ + win/VC90/game.vcproj \ + win/VC90/TrinityCore.vcproj \ + win/VC90/TrinityRealm.vcproj \ + win/VC90/shared.vcproj \ + win/VC90/zlib.vcproj \ + win/VC90/g3dlite.vcproj \ + win/VC90/zthread.vcproj + diff --git a/NEWS b/NEWS new file mode 100644 index 00000000000..421c0e68c7f --- /dev/null +++ b/NEWS @@ -0,0 +1,107 @@ += MaNGOS -- History of visible changes = + +Copyright (c) 2005-2008 MaNGOS project + +See the COPYING file for copying conditions. + +Visit our project website for documentation, and more: +http://www.mangosproject.org/ + +Visit our forums for support: +http://www.mangosproject.org/forum/ + +Please submit bug reports at: +http://www.mangosproject.org/trac/ + +Version 0.12 + * Under discussion. + * Upgrade to client version 2.4.3 (build 8606). + +Version 0.11 + * Lots of improvements in the spell system. + * Now use Mersenne Twister random number generator. + * MySQL client libs updated to 5.0.56. + * Upgrade to client version 2.4.2 (build 8278). + +Version 0.10 + * master looter lot mode, + * FFA PvP zones and FFA PvP server type support, + * Guild Banks, + * unique equipped items support, including gems, + * talent inspecting, + * PostgreSql support, + * sockets library updated to v.2.2.9 version, + * 64-bit binaries building at Windows, + * Upgrade to client version 2.3.0 (build 7561). + +Version 0.9 + * recipes discovery system support, + * more auras, effects, spells, and talents working, + * players queue at login support, + * mangosd/realmd as Windows services support, + * autogeneration mangosd/realmd crash reports (Windows only), + * Visual Studio 2008 Express and Pro support, + * division Mangos DataBase to MangosDB(WorldDB) and CharactersDB. + * Upgrade to client version 2.2.3 (build 7359). + +Version 0.8 + * battleground support, + * gender specific creatures, + * game objects triggering more scripts, + * more auras, effects, spells, and talents working, + * dungeon specific data, + * localization support for data, + * vmaps for line of sight handling, + * build support for OpenBSD and FreeBSD, + * Upgrade to client version 2.1.3 (build 6898). + +Version 0.7, Codename "Eye of the Storm" + * Full rewrite of the GNU autotools based build system, in order to + smooth and clean up the build process. + * Full rewrite of the Windows build system, allowing MaNGOS to be built + from Visual C++ 2003 Toolkit, Visual C++ 2003, Visual C++ 2005. + * Upgrade to client version 2.0.12 (build 6546). + +Version 0.6, Codename "Black Dragonflight" + * MaNGOS development moved to http://sourceforge.net/projects/mangos/ + * A lots of speed improvements to data handling and data transfer have been + completed. + * Mail, auction house, profession, creature, and game object systems have seen + a lot of improvements and can be considered feature complete. Some minor bugs + still are left. + * Rest system has been finished. + * Initial pet stable support has been added. + * PvP and duel system have seen lots of improvements + * Guilds are not just a myth anymore. Coming closer to full guild support. + * Taxi and transport system is close to a fully working system. + * A lot more has been added. + +Version 0.5, Codename "Stable Master" + * Core stability improvements, lots of threading and memory usage related + bugs have been resolved. + * MySQL Database backend has been cleaned up. + * Proper support for game clients of version 1.10.2 has been added. + * Support for auras, pets, spells, talents, totems, etc. has been added + or improved. + * Cross-platform issues have been resolved, MaNGOS should now build on + more platforms, including FreeBSD. + +Version 0.1, Codename "Lightbringer" + * AI system + * Grid system + * Lots a game features working. + * Lovely optimizations for the beloved server. + +Version 0.0.3, Codename "Mango Carpet" + * Interim release, not gone public. + +Version 0.0.2, Codename "Library" + * Most data conversions working. + * Database cleanup. + * More features working. + * Many bugs fixed. + +Version 0.0.1, Codename "Endeavour" + * Data converter added. + * Build system improvements. + * Bug fixing and code cleaning. diff --git a/README b/README new file mode 100644 index 00000000000..1e50c0337e0 --- /dev/null +++ b/README @@ -0,0 +1,57 @@ += MaNGOS -- README = + +Copyright (C) 2005-2008 MaNGOS project + + MaNGOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + In addition, as a special exception, the MaNGOS project + gives permission to link the code of its release of MaNGOS with the + OpenSSL project's "OpenSSL" library (or with modified versions of it + that use the same license as the "OpenSSL" library), and distribute + the linked executables. You must obey the GNU General Public License + in all respects for all of the code used other than "OpenSSL". If you + modify this file, you may extend this exception to your version of the + file, but you are not obligated to do so. If you do not wish to do + so, delete this exception statement from your version. + +Comments are welcome. + + - theluda + +== Welcome to MaNGOS == + +MaNGOS (the Massive Network Game Object Server) is an Open Source reference +implementation for a MMORPG server system. Please see the file COPYING for +license details. + +For further information on the MaNGOS project, please visit our project web +site at + +Documenation on various development related topics can be found in the doc/ +subdirectory, including Doxygen-generated API documentation. + +The required SQL files for creating the database backend are included in the +sql/ subdirectory. In case you are upgrading from an older MaNGOS release, +make sure you as well take a look at the SQL files in the sql/updates/ sub- +directory. + +In order to build and install MaNGOS under Linux, follow the instructions +described in the INSTALL file. + +In case you have checked out MaNGOS from the SubVersion repository, please run + +$ autoreconf --install --force + +prior to building, as you may otherwise not be able to run a build. diff --git a/THANKS b/THANKS new file mode 100644 index 00000000000..e3b5c4607c9 --- /dev/null +++ b/THANKS @@ -0,0 +1,37 @@ +The THANKS file: + +All distributions should contain a `THANKS' file containing a two column list +of the contributors, one per line, alphabetically sorted. The left column gives +the contributor's name, while the right column gives the last known good email +address for this contributor. This list should be introduced with a wording +similar to this one: + + MaNGOS THANKS file + + MaNGOS has originally been written by Team Python and WoW Daemon Team. Many + people further contributed to MaNGOS by reporting problems, suggesting various + improvements or submitting actual code. + + Here is a list of these people. Help me keep it complete and exempt of errors. + + Special thanks should also go out to the WowwoW team. We have gained help from + them many times in the creation of this project. Keep up the good work guys. + + Thanks should also go out to the Ludmilla team, who are also providing the + community with a great server. We have not gained too much help from them, + but we have recieved some. + +The easiest policy with this file is to thank everyone who contributes to the +project, without judging the value of the contribution. + +Unlike `AUTHORS', the `THANKS' file is not maintained for legal reasons. It is +maintained to thank all the contributors that helped you out in your project. +The `AUTHORS' file can not be used for this purpose because certain +contributions, like bug reports or ideas and suggestions do not require legal +paper exchanges. + +You can also decide to send some kind of special greeting when you initially +add a name to your `THANKS' file. The mere presense of a name in `THANKS' is +then a flag to you that the initial greeting has been sent. + +TBD diff --git a/bcpp.cfg b/bcpp.cfg new file mode 100644 index 00000000000..f567d7f5d90 --- /dev/null +++ b/bcpp.cfg @@ -0,0 +1,109 @@ +; This file contains configuration parameters that are used +; within the bcpp program. + +; There are two types of parameter types : Boolean, and Integer. +; Boolean types can have only two valid values [On, Yes, or Off, No]. +; Integer types can have a valid range of 0 - 5000. + +;------------------------------------------------------------------------ +; This parameter specifies how many lines separate between two +; functions. +;------------------------------------------------------------------------ +function_spacing = 1 ; Integer + +;------------------------------------------------------------------------ +; Specifies whether to use tabs in indenting code. +;------------------------------------------------------------------------ +use_tabs = no ; Boolean + +;------------------------------------------------------------------------ +; Specifies how many spaces to indent. This parameter is also used +; for tab indenting, as 1 tab may be worth 8 spaces if so desired. +; This parameter is used to position comments in TAB mode, and expanding +; of tabs within code! +;------------------------------------------------------------------------ +indent_spacing = 4 ; Integer + +;------------------------------------------------------------------------ +; Specifies whether to indent preprocessor controls to match the code +;------------------------------------------------------------------------ +indent_preprocessor = yes ; Boolean + +;------------------------------------------------------------------------ +; Specifies whether to indent embedded SQL statements +;------------------------------------------------------------------------ +indent_exec_sql = yes ; Boolean + +;------------------------------------------------------------------------ +; Defines at what start position comments that have code on the +; same line to be placed. +;------------------------------------------------------------------------ +comments_with_code = 60 ; Integer + +;------------------------------------------------------------------------ +; Defines at what start position comments with no code start. +;------------------------------------------------------------------------ +comments_with_nocode = 0 ; Integer + +;------------------------------------------------------------------------ +; Set this option to ON turns off setting indentation position of parameter +; "comments_with_nocode". Indentation is then set according to code +; position. +;------------------------------------------------------------------------ +leave_comments_nocode = On ; Boolean + +;------------------------------------------------------------------------ +; Use this option is used to change non-ascii (non-printable) chars to +; octal notation if they lie within quotes. Either +; Ascii_Chars_Only, XOR Leave_Graphic_Chars parameters need to be set +; as a True value for this parameter to take effect. +;------------------------------------------------------------------------ +NonAscii_Quotes_to_Octal = yes ; Boolean + +;------------------------------------------------------------------------ +; Setting this parameter to yes will strip non-printable characters +; from the source files, but leave any character that are IBM +; graphics alone. Any non-printable characters that lie within +; quotes will be transformed into octal/character notation, if +; NonAscii_Quotes_To_Octal parameter is set to True. +;------------------------------------------------------------------------ +; leave_graphic_chars = yes ; Boolean + +;------------------------------------------------------------------------ +; Setting this parameter to yes will strip any non-printable, +; non-ascii characters from the input file. Any non-printable +; octal/character notation if NonAscii_Quotes_To_Octal is set to +; True. Comment out this parameter if you are using +; Leave_Graphic_Chars parameter, as this parameter will override +; it. +;------------------------------------------------------------------------ +ascii_chars_only = no ; Boolean + +;------------------------------------------------------------------------ +; This parameter will place open braces on a new line after it's +; associated code if set on/yes. Else the brace will be place on +; next above line if possible, with it's code. +;------------------------------------------------------------------------ +place_brace_on_new_line = yes ; Boolean + +;------------------------------------------------------------------------ +; This parameter will stop output from the program corrupting output +; that may exit from the program via the standard output. +; If this parameter is set to off/no then no output is generated from +; the program, unless an error is encountered +;------------------------------------------------------------------------ +program_output = yes ; Boolean + +;------------------------------------------------------------------------ +; Specifies what the internal memory requirements will be in size of the +; line processing buffer. This essentially is used only for open brace +; relocation in kernighan/ritchie style. +;------------------------------------------------------------------------ +Queue_Buffer = 100 ; Integer + +;------------------------------------------------------------------------ +; If this option is set to true then the input file will be backup into a +; another file with a ".bac" extension added to the end of the file +; name. +;------------------------------------------------------------------------ +Backup_File = yes ; Boolean diff --git a/configure.ac b/configure.ac new file mode 100644 index 00000000000..7ff4ee43e09 --- /dev/null +++ b/configure.ac @@ -0,0 +1,281 @@ +# Copyright (C) 2005-2008 MaNGOS project +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +## Process this file with autoconf to produce a configure script. + +## Prelude, basic settings for Autoconf +# PACKAGE: mangos +# VERSION: 0.12.0 (trunk) +# BUG-REPORT-ADDRESS: mangos-devs@lists.sourceforge.net +AC_INIT( [trinitycore], [0.0.1], [devs@trinitycore.org]) + +AC_CONFIG_SRCDIR([src/shared/Base.cpp]) + +## Prelude, basic settings for Automake +# Turn on all warnings and error messages, and enforce GNU +# standards for the package. +AM_INIT_AUTOMAKE([-Wall -Werror]) +AM_MAINTAINER_MODE + +## Prevent the configure script from continuing any further if +# configuration is being performed in the top-level directory. +# The idea is to prevent this ,because some maintainers tend +# to break "off src dir" builds. +if test "$srcdir" = "." && test "$enable_maintainer_mode" != "yes"; then + AC_MSG_ERROR( + [ + Please configure and build in a directory other than the + top-level source directory. This is needed because a lot + of maintainers tend to break "off src dir" builds. This + is kinda real ensurance they wont do it. + + For example, try the following from the top-level source + directory: + + mkdir objdir + cd objdir + ../configure + make + + This will create a build space in the directory `objdir' and + start a build in that directory. + + If however you realy want to build in src dir, + then use --enable-maintainer-mode switch. + ]) +fi + +## Disable building of static libraries by default +AC_DISABLE_STATIC + +## Check for required dependencies. + +## Check for a valid build environment. +# Valid equals having: +# - a C++ compiler compliant with the ISO98 C++ specification. +# - a working library tool for creating convenience libraries. +# - a working linker for creating static and shared libraries. +AC_PROG_CC +AC_PROG_CXX +AC_PROG_LIBTOOL +AC_PROG_INSTALL +AM_PROG_CC_C_O + +# Check if enable scripts +AC_ARG_ENABLE([scripts], AC_HELP_STRING([--enable-scripts], [Enable TrinityScripts (default: yes) ]), [], [enable_scripts=yes]) + +AM_CONDITIONAL([USE_TSCRIPTS], [test X$enable_scripts = Xyes]) + +# Check for doxygen +AC_ARG_ENABLE(doxygen, AC_HELP_STRING([--enable-doxygen], [turn on generating documentation])) + +enable_doxygen_support=no + +if test "x$enable_doxygen" = "xyes"; +then + AC_PATH_PROG(DOXYGEN, doxygen, no) + if test "x$DOXYGEN" = "xno"; then + AC_MSG_ERROR([You need to install the doxygen package]) + fi + enable_doxygen_support=yes +fi +AM_CONDITIONAL(DOXYGEN_ENABLED, test x$enable_doxygen_support = xyes) + +## Check for required libraries. +AC_CHECK_LIB( pthread, pthread_create, [], + [LDFLAGS="-pthread $LDFLAGS" + AC_TRY_LINK([char pthread_create();], + pthread_create();, + [], [AC_MSG_ERROR([Missing pthread])]) + ]) +AC_CHECK_LIB( z, compress, [ZLIB=-lz],[AC_MSG_ERROR([Missing zlib])] ) +AC_CHECK_LIB( compat, ftime, [COMPATLIB=-lcompat] ) +AC_CHECK_LIB( crypto, SHA1_Init, [SSLLIB=-lssl], [AC_MSG_ERROR([Missing openssl])]) + +AC_ARG_WITH(postgresql, +[ --with-postgresql Use PostgreSQL as a backend (default: no)], +[case "${withval}" in + yes) DO_POSTGRESQL=yes ;; + no) DO_POSTGRESQL=no ;; + maybe) DO_POSTGRESQL=maybe ;; + *) AC_MSG_ERROR(Bad value ${withval} for --with-postgresql) ;; + esac], +[DO_POSTGRESQL=no]) + +AC_ARG_WITH(mysql, +[ --with-mysql Use MySQL as a backend (default: yes)], +[case "${withval}" in + yes) DO_MYSQL=yes ;; + no) DO_MYSQL=no ;; + maybe) DO_MYSQL=maybe ;; + *) AC_MSG_ERROR(Bad value ${withval} for --with-mysql) ;; + esac], +[DO_MYSQL=yes]) + +# here Postgre +AC_MSG_CHECKING(whether to build/link POSTGRESQL) +if test "x$DO_POSTGRESQL" = "xyes"; then +DO_MYSQL=no +POSTGRE_INCLUDES="-I/usr/include/postgresql $POSTGRE_INCLUDES" +POSTGRE_LIBS="-L/usr/lib/postresql -lpq -lz -lpthread -lcrypt -lnsl -lm -lpthread -L/usr/lib -lssl -lcrypto $POSTGRE_LIBS " +CXXFLAGS="-DDO_POSTGRESQL $CXXFLAGS" +fi +AC_MSG_RESULT($DO_POSTGRESQL) + +# here mysql +AC_MSG_CHECKING(whether to build/link MYSQL) +if test "x$DO_MYSQL" = "xyes"; then +AC_MSG_RESULT($DO_MYSQL) +AC_PATH_PROGS(MYSQL_CONFIG, mysql_config, mysql_config, $PATH) + if test -x "$MYSQL_CONFIG" + then + # MySQL v4 uses --include while v3 uses --cflags + MYSQL_INCLUDES="`$MYSQL_CONFIG --include`" || \ + MYSQL_INCLUDES="`$MYSQL_CONFIG --cflags`" + MYSQL_LIBS="`$MYSQL_CONFIG --libs_r`" + CXXFLAGS="-DDO_MYSQL $CXXFLAGS" + fi +else +AC_MSG_RESULT($DO_MYSQL) +fi + +## Check for options +# Include debug info in library? +AC_MSG_CHECKING(whether to include debug info in library) +MANGOSD_DEBUG_INFO=no +AC_ARG_WITH(debug-info, +[ +Debugging options: + + --with-debug-info Include debug info in library], +[ + if test "$withval" = "yes" ; then + CFLAGS="-g -DMANGOS_DEBUG $CFLAGS" + CXXFLAGS="-g -DMANGOS_DEBUG $CXXFLAGS" + MANGOSD_DEBUG_INFO=yes + elif test "$withval" != "no" ; then + AC_MSG_ERROR(Please choose yes or no) + fi +]) +AC_MSG_RESULT($MANGOSD_DEBUG_INFO) + + +# Enable CLI console? +AC_MSG_CHECKING(whether cli console is enabled) +MANGOSD_ENABLE_CLI=no +AC_ARG_ENABLE(cli, +[ --enable-cli Turn on command console system], +[ + if test "$enableval" = "yes" ; then + CFLAGS="-DENABLE_CLI $CFLAGS" + CXXFLAGS="-DENABLE_CLI $CXXFLAGS" + MANGOSD_ENABLE_CLI=yes + elif test "$withval" != "no" ; then + AC_MSG_ERROR(Please choose yes or no) + fi +]) +AC_MSG_RESULT($MANGOSD_ENABLE_CLI) + +# Enable remote console? +AC_MSG_CHECKING(whether remote console is enabled) +MANGOSD_ENABLE_RA=no +AC_ARG_ENABLE(ra, +[ --enable-ra Turn on remote console system], +[ + if test "$enableval" = "yes" ; then + CFLAGS="-DENABLE_RA $CFLAGS" + CXXFLAGS="-DENABLE_RA $CXXFLAGS" + MANGOSD_ENABLE_RA=yes + elif test "$withval" != "no" ; then + AC_MSG_ERROR(Please choose yes or no) + fi +]) +AC_MSG_RESULT($MANGOSD_ENABLE_RA) + +## Check for required header files. +AC_HEADER_STDC +AC_HEADER_DIRENT +AC_CHECK_HEADERS([ arpa/inet.h fcntl.h limits.h locale.h malloc.h netdb.h netinet/in.h stddef.h stdint.h stdlib.h string.h strings.h sys/ioctl.h sys/param.h sys/socket.h sys/timeb.h sys/time.h termios.h unistd.h ]) + +AC_CHECK_HEADERS([pthread.h]) +AC_CHECK_HEADERS([openssl/md5.h openssl/rand.h openssl/ssl.h openssl/sha.h openssl/bn.h]) +AC_CHECK_HEADERS([mysql.h mysql/mysql.h]) +AC_CHECK_HEADERS([libpq-fe.h]) +AC_CHECK_HEADERS([zlib.h]) + +## Check for typedefs, structures, and compiler characteristics. +AC_HEADER_STDBOOL +AC_C_CONST +AC_C_INLINE +AC_TYPE_SIZE_T +AC_HEADER_TIME +AC_STRUCT_TM +AC_TYPE_UINT64_T +AC_C_VOLATILE +AC_CHECK_TYPES([ptrdiff_t]) + +## Check for required library functions. +AC_FUNC_CLOSEDIR_VOID +AC_FUNC_ERROR_AT_LINE +AC_FUNC_MALLOC +AC_FUNC_MEMCMP +AC_FUNC_REALLOC +AC_FUNC_SELECT_ARGTYPES +AC_TYPE_SIGNAL +AC_FUNC_VPRINTF +AC_CHECK_FUNCS([atexit ftime gethostbyaddr gethostbyname gethostname gettimeofday memmove memset pow realpath select socket sqrt strchr strdup strerror strstr]) + +## Export defined variables +AC_SUBST(ZLIB) +AC_SUBST(COMPATLIB) +AC_SUBST(SSLLIB) +AC_SUBST(MYSQL_INCLUDES) +AC_SUBST(MYSQL_LIBS) +AC_SUBST(POSTGRE_INCLUDES) +AC_SUBST(POSTGRE_LIBS) +AC_SUBST(DOXYGEN) +AC_SUBST(MANGOSD_DEBUG_INFO) +AC_SUBST(MANGOSD_ENABLE_CLI) +AC_SUBST(MANGOSD_ENABLE_RA) + +## Set output files. +AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_FILES([ + dep/include/Makefile + dep/lib/Makefile + dep/src/Makefile + dep/src/g3dlite/Makefile + dep/src/sockets/Makefile + dep/src/zlib/Makefile + dep/src/zthread/Makefile + dep/Makefile + doc/Doxyfile + doc/Makefile + Makefile + sql/Makefile + sql/tools/Makefile + sql/updates/Makefile + src/Makefile + src/framework/Makefile + src/shared/Makefile + src/shared/vmap/Makefile + src/game/Makefile + src/trinityrealm/Makefile + src/trinitycore/Makefile + src/bindings/Makefile + src/bindings/scripts/Makefile + src/bindings/interface/Makefile +]) + +## Disabled Makefiles, until they are ready for a successful make and +# make dist run. + +## Output files. +AC_OUTPUT diff --git a/contrib/Makefile.am b/contrib/Makefile.am new file mode 100644 index 00000000000..52a046b5378 --- /dev/null +++ b/contrib/Makefile.am @@ -0,0 +1,23 @@ +# Copyright (C) 2005-2008 MaNGOS +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## Process this file with automake to produce Makefile.in + +## Sub-directories to parse +SUBDIRS = extractor + +## Additional files to include when running 'make dist' +# Nothing yet. diff --git a/contrib/dbcEditer/BcdEditer.ini b/contrib/dbcEditer/BcdEditer.ini new file mode 100644 index 00000000000..99284e8b967 --- /dev/null +++ b/contrib/dbcEditer/BcdEditer.ini @@ -0,0 +1,34 @@ +[TaxiNodes.dbc] +ColType2=0 +ColType3=1 +ColType4=1 +[SpellRange.dbc] +ColType2=0 +ColType3=0 +ColType1=0 +[Talent.dbc] +ColType1=0 +ColType5=0 +ColType4=0 +[test.dbc] +ColType1=0 +ColType3=1 +ColType2=0 +[TalentTab.dbc] +ColType15=2 +[TalentTab_new.dbc] +ColType15=2 +[SpellIcon.dbc] +ColType2=0 +ColType1=0 +[FactionGroup.dbc] +ColType12=0 +ColType3=2 +ColType2=0 +ColType8=0 +[gtRegenMPPerSpt.dbc] +ColType1=1 +[gtOCTRegenMP.dbc] +ColType1=1 +[gtOCTRegenHP.dbc] +ColType1=1 diff --git a/contrib/dbcEditer/SearchFrm.cpp b/contrib/dbcEditer/SearchFrm.cpp new file mode 100644 index 00000000000..59e198dfb8a --- /dev/null +++ b/contrib/dbcEditer/SearchFrm.cpp @@ -0,0 +1,26 @@ +//--------------------------------------------------------------------------- + +#include +#pragma hdrstop + +#include "SearchFrm.h" +//--------------------------------------------------------------------------- +#pragma package(smart_init) +#pragma resource "*.dfm" +TFrmSearch *FrmSearch; +//--------------------------------------------------------------------------- +__fastcall TFrmSearch::TFrmSearch(TComponent* Owner) + : TForm(Owner) +{ +} +//--------------------------------------------------------------------------- +void __fastcall TFrmSearch::btOkClick(TObject *Sender) +{ + ModalResult = mrOk; +} +//--------------------------------------------------------------------------- +void __fastcall TFrmSearch::btCancelClick(TObject *Sender) +{ + ModalResult = mrCancel; +} +//--------------------------------------------------------------------------- diff --git a/contrib/dbcEditer/SearchFrm.ddp b/contrib/dbcEditer/SearchFrm.ddp new file mode 100644 index 00000000000..cdc0ee8c2b5 Binary files /dev/null and b/contrib/dbcEditer/SearchFrm.ddp differ diff --git a/contrib/dbcEditer/SearchFrm.dfm b/contrib/dbcEditer/SearchFrm.dfm new file mode 100644 index 00000000000..134c881cbfb --- /dev/null +++ b/contrib/dbcEditer/SearchFrm.dfm @@ -0,0 +1,63 @@ +object FrmSearch: TFrmSearch + Left = 261 + Top = 194 + Width = 324 + Height = 215 + Caption = 'Seach F3 Seach Next' + Color = clBtnFace + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'MS Sans Serif' + Font.Style = [] + OldCreateOrder = False + PixelsPerInch = 96 + TextHeight = 13 + object lbseach: TLabel + Left = 48 + Top = 16 + Width = 57 + Height = 17 + AutoSize = False + Caption = 'Input:' + end + object rgSI: TRadioGroup + Left = 64 + Top = 40 + Width = 185 + Height = 97 + Caption = 'Seach Dir' + ItemIndex = 1 + Items.Strings = ( + 'Seach up' + 'Seach down' + 'Seach up Current rol' + 'Seach down Current rol') + TabOrder = 0 + end + object edSeach: TEdit + Left = 120 + Top = 16 + Width = 121 + Height = 21 + TabOrder = 1 + end + object btOk: TButton + Left = 64 + Top = 152 + Width = 75 + Height = 25 + Caption = 'Ok' + TabOrder = 2 + OnClick = btOkClick + end + object btCancel: TButton + Left = 176 + Top = 152 + Width = 75 + Height = 25 + Caption = 'Cancel' + TabOrder = 3 + OnClick = btCancelClick + end +end diff --git a/contrib/dbcEditer/SearchFrm.h b/contrib/dbcEditer/SearchFrm.h new file mode 100644 index 00000000000..246d7e68204 --- /dev/null +++ b/contrib/dbcEditer/SearchFrm.h @@ -0,0 +1,29 @@ +//--------------------------------------------------------------------------- + +#ifndef SearchFrmH +#define SearchFrmH +//--------------------------------------------------------------------------- +#include +#include +#include +#include +#include +//--------------------------------------------------------------------------- +class TFrmSearch : public TForm +{ +__published: // IDE-managed Components + TRadioGroup *rgSI; + TEdit *edSeach; + TLabel *lbseach; + TButton *btOk; + TButton *btCancel; + void __fastcall btOkClick(TObject *Sender); + void __fastcall btCancelClick(TObject *Sender); +private: // User declarations +public: // User declarations + __fastcall TFrmSearch(TComponent* Owner); +}; +//--------------------------------------------------------------------------- +extern PACKAGE TFrmSearch *FrmSearch; +//--------------------------------------------------------------------------- +#endif diff --git a/contrib/dbcEditer/TitleFrm.cpp b/contrib/dbcEditer/TitleFrm.cpp new file mode 100644 index 00000000000..a26e93ce5ec --- /dev/null +++ b/contrib/dbcEditer/TitleFrm.cpp @@ -0,0 +1,26 @@ +//--------------------------------------------------------------------------- + +#include +#pragma hdrstop + +#include "TitleFrm.h" +//--------------------------------------------------------------------------- +#pragma package(smart_init) +#pragma resource "*.dfm" +TFrmTitle *FrmTitle; +//--------------------------------------------------------------------------- +__fastcall TFrmTitle::TFrmTitle(TComponent* Owner) + : TForm(Owner) +{ +} +//--------------------------------------------------------------------------- +void __fastcall TFrmTitle::Button1Click(TObject *Sender) +{ + ModalResult = mrOk; +} +//--------------------------------------------------------------------------- +void __fastcall TFrmTitle::Button2Click(TObject *Sender) +{ + ModalResult = mrCancel; +} +//--------------------------------------------------------------------------- diff --git a/contrib/dbcEditer/TitleFrm.ddp b/contrib/dbcEditer/TitleFrm.ddp new file mode 100644 index 00000000000..cdc0ee8c2b5 Binary files /dev/null and b/contrib/dbcEditer/TitleFrm.ddp differ diff --git a/contrib/dbcEditer/TitleFrm.dfm b/contrib/dbcEditer/TitleFrm.dfm new file mode 100644 index 00000000000..3f472d59bcf --- /dev/null +++ b/contrib/dbcEditer/TitleFrm.dfm @@ -0,0 +1,51 @@ +object FrmTitle: TFrmTitle + Left = 328 + Top = 252 + Width = 235 + Height = 112 + BorderIcons = [biSystemMenu] + Caption = 'Col Title' + Color = clBtnFace + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'MS Sans Serif' + Font.Style = [] + OldCreateOrder = False + Position = poDesktopCenter + PixelsPerInch = 96 + TextHeight = 13 + object Label1: TLabel + Left = 8 + Top = 24 + Width = 65 + Height = 13 + AutoSize = False + Caption = 'Title:' + end + object edTitle: TEdit + Left = 80 + Top = 16 + Width = 121 + Height = 21 + TabOrder = 0 + end + object Button1: TButton + Left = 24 + Top = 48 + Width = 75 + Height = 25 + Caption = 'Ok' + TabOrder = 1 + OnClick = Button1Click + end + object Button2: TButton + Left = 136 + Top = 48 + Width = 75 + Height = 25 + Caption = 'Cancel' + TabOrder = 2 + OnClick = Button2Click + end +end diff --git a/contrib/dbcEditer/TitleFrm.h b/contrib/dbcEditer/TitleFrm.h new file mode 100644 index 00000000000..2316d8fec96 --- /dev/null +++ b/contrib/dbcEditer/TitleFrm.h @@ -0,0 +1,27 @@ +//--------------------------------------------------------------------------- + +#ifndef TitleFrmH +#define TitleFrmH +//--------------------------------------------------------------------------- +#include +#include +#include +#include +//--------------------------------------------------------------------------- +class TFrmTitle : public TForm +{ +__published: // IDE-managed Components + TLabel *Label1; + TEdit *edTitle; + TButton *Button1; + TButton *Button2; + void __fastcall Button1Click(TObject *Sender); + void __fastcall Button2Click(TObject *Sender); +private: // User declarations +public: // User declarations + __fastcall TFrmTitle(TComponent* Owner); +}; +//--------------------------------------------------------------------------- +extern PACKAGE TFrmTitle *FrmTitle; +//--------------------------------------------------------------------------- +#endif diff --git a/contrib/dbcEditer/bin/BcdEditer.ini b/contrib/dbcEditer/bin/BcdEditer.ini new file mode 100644 index 00000000000..100029b418e --- /dev/null +++ b/contrib/dbcEditer/bin/BcdEditer.ini @@ -0,0 +1,313 @@ +[FactionGroup.dbc] +ColType3=2 +[Spell.dbc] +ColTitle1=Id +ColTitle2=Category +ColTitle3=castUI +ColTitle4=Dispel +ColTitle5=Mechanic +ColTitle6=Attributes +ColTitle7=AttributesEx; +ColTitle8=AttributesEx2; +ColTitle9=AttributesEx3; +ColTitle10=AttributesEx4; +ColTitle11=AttributesEx5; +ColTitle12=AttributesEx6; +ColTitle13=Stances; +ColTitle14=StancesNot; +ColTitle15=Targets; +ColTitle16=TargetCreatureType; +ColTitle17=RequiresSpellFocus; +ColTitle18=FacingCasterFlags; +ColTitle19=CasterAuraState; +ColTitle20=TargetAuraState; +ColTitle21=CasterAuraStateNot; +ColTitle22=TargetAuraStateNot; +ColTitle23=CastingTimeIndex; +ColTitle24=RecoveryTime; +ColTitle25=CategoryRecoveryTime; +ColTitle26=InterruptFlags; +ColTitle27=AuraInterruptFlags; +ColTitle28=ChannelInterruptFlags; +ColTitle29=procFlags; +ColTitle30=procChance; +ColTitle31=procCharges; +ColTitle32=maxLevel; +ColTitle33=baseLevel; +ColTitle34=spellLevel; +ColTitle35=DurationIndex; +ColTitle36=powerType; +ColTitle37=manaCost; +ColTitle38=manaCostPerlevel; +ColTitle39=manaPerSecond; +ColTitle40=manaPerSecondPerLevel; +ColTitle41=rangeIndex; +ColTitle42=floatspeed; +ColTitle43=modalNextSpell;//38 +ColTitle44=StackAmount; +ColTitle45=Totem1 +ColTitle46=Totem2 +ColTitle47=Reagent +ColTitle48=Reagent2 +ColTitle49=Reagent3 +ColTitle50=Reagent4 +ColTitle51=Reagent5 +ColTitle52=Reagent6 +ColTitle53=Reagent7 +ColTitle54=Reagent8 +ColTitle55=ReagentCount1 +ColTitle56=ReagentCount2 +ColTitle57=ReagentCount3 +ColTitle58=ReagentCount4 +ColTitle59=ReagentCount5 +ColTitle60=ReagentCount6 +ColTitle61=ReagentCount7 +ColTitle62=ReagentCount8 + +ColTitle63=EqpItemClass +ColTitle64=EquipItemSubClassMask +ColTitle65=ItemInventoryTypeMask +ColTitle66=Effect +ColTitle67=Effect2 +ColTitle68=Effect3 +ColTitle69=EffectDieSides1 +ColTitle70=EffectDieSides2 +ColTitle71=EffectDieSides3 +ColTitle72=EffectBaseDice1 +ColTitle73=EffectBaseDice2 +ColTitle74=EffectBaseDice3 +ColTitle75=EffectDicePerLevel1 +ColTitle76=EffectDicePerLevel2 +ColTitle77=EffectDicePerLevel3 +ColTitle78=EffectRealPointsPerLevel1 +ColTitle79=EffectRealPointsPerLevel2 +ColTitle80=EffectRealPointsPerLevel3 +ColTitle81=BasePoints1 +ColTitle82=BasePoints2 +ColTitle83=BasePoints3 +ColTitle84=EffectMechanic1 +ColTitle85=EffectMechanic2 +ColTitle86=EffectMechanic3 + + +ColTitle87=ImplicTargA1 +ColTitle88=ImplicTargA2 +ColTitle89=ImplicTargA3 +ColTitle90=ImplicTargB1 +ColTitle91=ImplicTargB2 +ColTitle92=ImplicTargB3 +ColTitle93=RadiusIndex1 +ColTitle94=RadiusIndex2 +ColTitle95=RadiusIndex3 +ColTitle96=ApplyAuraName1 +ColTitle97=ApplyAuraName2 +ColTitle98=ApplyAuraName3 +ColTitle99=Amplitude1 +ColTitle100=Amplitude2 +ColTitle101=Amplitude3 +ColTitle102=MultiVal1 +ColTitle103=MultiVal2 +ColTitle104=MultiVal3 +ColTitle105=ChainTarg1 +ColTitle106=ChainTarg2 +ColTitle107=ChainTarg3 +ColTitle108=EffectItemType1 +ColTitle109=EffectItemType2 +ColTitle110=EffectItemType3 +ColTitle111=EffectMiscVal1 +ColTitle112=EffectMiscVal2 +ColTitle113=EffectMiscVal3 +ColTitle114=EffectMiscValB1 +ColTitle115=EffectMiscValB2 +ColTitle116=EffectMiscValB3 +ColTitle117=EffectTriggerSpell1 +ColTitle118=EffectTriggerSpell2 +ColTitle119=EffectTriggerSpell3 +ColTitle120=EffectPointsPerComboPoint1 +ColTitle121=EffectPointsPerComboPoint2 +ColTitle122=EffectPointsPerComboPoint3 +ColTitle123=SpellVisual +ColTitle125=SpellIconID +ColTitle126=activeIconID +ColTitle127=spellPriority +ColTitle128=SpellName1 +ColTitle129=SpellName2 +ColTitle130=SpellName3 +ColTitle131=SpellName4 +ColTitle132=SpellName5 +ColTitle133=SpellName6 +ColTitle134=SpellName7 +ColTitle135=SpellName8 +ColTitle136=SpellName9 +ColTitle137=SpellName10 +ColTitle138=SpellName11 +ColTitle139=SpellName12 +ColTitle140=SpellName13 +ColTitle141=SpellName14 +ColTitle142=SpellName15 +ColTitle143=SpellName16 +ColTitle144=SpellNameFlag +ColTitle145=Rank1 +ColTitle146=Rank2 +ColTitle147=Rank3 +ColTitle148=Rank4 +ColTitle149=Rank5 +ColTitle150=Rank6 +ColTitle151=Rank7 +ColTitle152=Rank8 +ColTitle153=Rank9 +ColTitle154=Rank10 +ColTitle155=Rank11 +ColTitle156=Rank12 +ColTitle157=Rank13 +ColTitle158=Rank14 +ColTitle159=Rank15 +ColTitle160=Rank16 +ColTitle161=RankFlags +ColTitle162=Description1 +ColTitle163=Description2 +ColTitle164=Description3 +ColTitle165=Description4 +ColTitle166=Description5 +ColTitle167=Description6 +ColTitle168=Description7 +ColTitle169=Description8 +ColTitle170=Description9 +ColTitle171=Description10 +ColTitle172=Description11 +ColTitle173=Description12 +ColTitle174=Description13 +ColTitle175=Description14 +ColTitle176=Description15 +ColTitle177=Description16 +ColTitle178=DescriptionFlags +ColTitle179=ToolTip1 +ColTitle180=ToolTip2 +ColTitle181=ToolTip3 +ColTitle182=ToolTip4 +ColTitle183=ToolTip5 +ColTitle184=ToolTip6 +ColTitle185=ToolTip7 +ColTitle186=ToolTip8 +ColTitle187=ToolTip9 +ColTitle188=ToolTip10 +ColTitle189=ToolTip11 +ColTitle190=ToolTip12 +ColTitle191=ToolTip13 +ColTitle192=ToolTip14 +ColTitle193=ToolTip15 +ColTitle194=ToolTip16 +ColTitle195=ToolTipFlags +ColTitle196=ManaCostPercentage +ColTitle197=StartRecoveryCategory +ColTitle198=StartRecoveryTime +ColTitle199=MaxTargetLevel +ColTitle200=SpellFamilyName +ColTitle201=SpellFamilyFlags1 +ColTitle202=SpellFamilyFlags2 +ColTitle203=MaxAffectedTargets +ColTitle204=DmgClass +ColTitle205=PreventionType +ColTitle206=StanceBarOrder +ColTitle207=DmgMultiplier1 +ColTitle208=DmgMultiplier2 +ColTitle209=DmgMultiplier3 +ColTitle210=MinFactionId +ColTitle211=MinReputation +ColTitle212=RequiredAuraVision +ColTitle213=TotemCategory1 +ColTitle214=TotemCategory2 +ColTitle215=AreaId +ColTitle216=SchoolMask +ColType102=1 +ColType103=1 +ColType104=1 +ColType128=2 +ColType129=2 +ColType130=2 +ColType131=2 +ColType132=2 +ColType133=2 +ColType134=2 +ColType135=2 +ColType136=2 +ColType137=2 +ColType138=2 +ColType139=2 +ColType140=2 +ColType141=2 +ColType142=2 +ColType143=2 +ColType145=2 +ColType146=2 +ColType147=2 +ColType148=2 +ColType149=2 +ColType150=2 +ColType151=2 +ColType152=2 +ColType153=2 +ColType154=2 +ColType155=2 +ColType157=2 +ColType156=2 +ColType158=2 +ColType159=2 +ColType160=2 +ColType162=2 +ColType163=2 +ColType164=2 +ColType165=2 +ColType166=2 +ColType167=2 +ColType168=2 +ColType169=2 +ColType170=2 +ColType171=2 +ColType172=2 +ColType173=2 +ColType174=2 +ColType175=2 +ColType176=2 +ColType177=2 +ColType179=2 +ColType180=2 +ColType181=2 +ColType182=2 +ColType183=2 +ColType184=2 +ColType185=2 +ColType186=2 +ColType187=2 +ColType188=2 +ColType189=2 +ColType190=2 +ColType191=2 +ColType192=2 +ColType193=2 +ColType194=2 +ColType208=1 +ColType209=1 +ColType207=1 +[Map.dbc] +ColType2=2 +ColType8=0 +[AreaTrigger.dbc] +ColTitle3=x +ColTitle4=y +ColTitle5=z +ColTitle1=id +ColTitle2=map +ColType3=1 +ColType4=1 +ColType5=1 +ColType6=1 +ColType7=1 +ColType8=1 +ColType9=1 +ColType10=1 +ColTitle6=radius +ColTitle7=box x +ColTitle8=box y +ColTitle9=box z +ColTitle10=box orientation diff --git a/contrib/dbcEditer/bin/bcbsmp60.bpl b/contrib/dbcEditer/bin/bcbsmp60.bpl new file mode 100644 index 00000000000..32ebe0d1dee Binary files /dev/null and b/contrib/dbcEditer/bin/bcbsmp60.bpl differ diff --git a/contrib/dbcEditer/bin/borlndmm.dll b/contrib/dbcEditer/bin/borlndmm.dll new file mode 100644 index 00000000000..5a8eec327d6 Binary files /dev/null and b/contrib/dbcEditer/bin/borlndmm.dll differ diff --git a/contrib/dbcEditer/bin/cc3260mt.dll b/contrib/dbcEditer/bin/cc3260mt.dll new file mode 100644 index 00000000000..fef4636a1e0 Binary files /dev/null and b/contrib/dbcEditer/bin/cc3260mt.dll differ diff --git a/contrib/dbcEditer/bin/dclusr60.bpl b/contrib/dbcEditer/bin/dclusr60.bpl new file mode 100644 index 00000000000..002a741f61d Binary files /dev/null and b/contrib/dbcEditer/bin/dclusr60.bpl differ diff --git a/contrib/dbcEditer/bin/indy60.bpl b/contrib/dbcEditer/bin/indy60.bpl new file mode 100644 index 00000000000..f3cb7d6ca09 Binary files /dev/null and b/contrib/dbcEditer/bin/indy60.bpl differ diff --git a/contrib/dbcEditer/bin/pjDbcEditer.exe b/contrib/dbcEditer/bin/pjDbcEditer.exe new file mode 100644 index 00000000000..9b11ec74614 Binary files /dev/null and b/contrib/dbcEditer/bin/pjDbcEditer.exe differ diff --git a/contrib/dbcEditer/bin/rtl60.bpl b/contrib/dbcEditer/bin/rtl60.bpl new file mode 100644 index 00000000000..96a55c64d52 Binary files /dev/null and b/contrib/dbcEditer/bin/rtl60.bpl differ diff --git a/contrib/dbcEditer/bin/update.txt b/contrib/dbcEditer/bin/update.txt new file mode 100644 index 00000000000..e3d39c92859 --- /dev/null +++ b/contrib/dbcEditer/bin/update.txt @@ -0,0 +1,11 @@ +1.4°æ¸üР+ 1.ÐÞÕýÍ˳öʱÓÐʱÍ˲»³öµÄbug + 2.¼ÓÈë¿É²éÕҵŦÄÜ + 3.¼ÓÈëÁÐÇл»ÀàÐͺóÁ¢¼´Ë¢Ð + 4.¼ÓÈë¿ÉÒÔµ±Ç°µ¥Ôª¸ñдÈë´ò¿ªÎļþµÄ¹¦ÄÜ + 5.¼ÓÈëÿһÁеĿí¶È¿Éµ÷Õû + 6.¼ÓÈëÖ§³ÖÎı¾ÏÔʾ£¬µ«²»ÄÜÐ޸ģ¬Îı¾ÐÞ¸Äºó²»»á´æÈë + +1.41°æ + 1.¿ÉÒԹ̶¨ºÍÈ¡ÏûµÚÒ»ÁУ¬ÒÔ·½±ã²é¿´Spell ID + 2.¿ÉÒÔÐд棬Áд棬ÐÐÇ壬ÁÐÇ壬µ÷ÓüÆËãÆ÷ \ No newline at end of file diff --git a/contrib/dbcEditer/bin/vcl60.bpl b/contrib/dbcEditer/bin/vcl60.bpl new file mode 100644 index 00000000000..0f0cc71ce36 Binary files /dev/null and b/contrib/dbcEditer/bin/vcl60.bpl differ diff --git a/contrib/dbcEditer/bin/vclx60.bpl b/contrib/dbcEditer/bin/vclx60.bpl new file mode 100644 index 00000000000..6fe6ac6f535 Binary files /dev/null and b/contrib/dbcEditer/bin/vclx60.bpl differ diff --git a/contrib/dbcEditer/dbcedit.cpp b/contrib/dbcEditer/dbcedit.cpp new file mode 100644 index 00000000000..2812a3f7071 --- /dev/null +++ b/contrib/dbcEditer/dbcedit.cpp @@ -0,0 +1,769 @@ +//--------------------------------------------------------------------------- + +#include +#pragma hdrstop + +#include "dbcedit.h" +#include "stdio.h" +#include "IdGlobal.hpp" +#include +#include "TitleFrm.h" +#include +#include "thOpenSource.h" +#include "SearchFrm.h" +//#include "SysUtils.hpp" + + +//--------------------------------------------------------------------------- +#pragma package(smart_init) +#pragma resource "*.dfm" +TFrmMain *FrmMain; +//--------------------------------------------------------------------------- +__fastcall TFrmMain::TFrmMain(TComponent* Owner) + : TForm(Owner) +{ + OpenOk=false; + Term=false; +} +//--------------------------------------------------------------------------- + +void __fastcall TFrmMain::btOpenClick(TObject *Sender) +{ + if(OpenDialog1->Execute()){ + if (FileExists(OpenDialog1->FileName)){ + OpenOk=false; + if(thOpen){ + thOpen->Terminate(); + } + thOpen = new thOpenFile(false); + //thOpen->Priority = tpTimeCritical; + pnFileName->Caption = OpenDialog1->FileName; + }else{ + OpenOk=false; + pnFileName->Caption = ""; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TFrmMain::btSaveClick(TObject *Sender) +{ + //CurrentOpenFile; + if(OpenOk){ + SaveToFile(CurrentOpenFile.c_str()); + }else{ + ShowMessage("Îļþδ´ò¿ªÍê³É£¡"); + } +} +//--------------------------------------------------------------------------- + +void TFrmMain::SaveToFile(const char * pszFileName) +{ + char szFileName[255]; + FILE *stream; + + + + + fnsplit(pszFileName, 0, 0, szFileName, 0); + strcat(szFileName, "_new.dbc"); + + + AnsiString NewFileName=ExtractFilePath(Application->ExeName)+szFileName;//=pszFileName; + int iFileHandle; //Îļþ¾ä±ú + AnsiString iniSetFile=ExtractFilePath(Application->ExeName)+"BcdEditer.ini"; + AnsiString SectionName=ExtractFileName(CurrentOpenFile); + + DWORD w; + + CopyFileTo(pszFileName,NewFileName); + + iFileHandle = FileOpen(NewFileName, fmOpenRead|fmOpenWrite);//´ò¿ªÎļþ + + if ((stream = fopen(CurrentOpenFile.c_str(), "r+")) + == NULL) + { + ShowMessage("´ò¿ªÎļþ³ö´í"); + return; + } + + + int iVal; + float fVal; + bool isFloat; + int ColType; + + FileSeek(iFileHandle,0x14,0); + TIniFile *ini; + ini = new TIniFile( iniSetFile ); + + for(int i=1; iRowCount; i++) + { + for(int j=1; jColCount; j++) + { + if(j==1){ //ID + iVal=StrToInt(sgEdit->Cells[j][i]); + FileWrite(iFileHandle, &iVal, 4); + }else{ + + //ColType= ini->ReadInteger(SectionName,"ColType"+IntToStr(j-1),0); + //thOpen->ColType[10000]; + + switch (thOpen->ColType[j]) + { + case 0: //ÕûÐÍ + iVal=StrToFloat(sgEdit->Cells[j][i]); + FileWrite(iFileHandle, &iVal, 4); + break; + case 1: //¸¡µã + fVal=StrToFloat(sgEdit->Cells[j][i]); + FileWrite(iFileHandle, &fVal, 4); + break; + case 2: //Îı¾ + fseek(stream, 0x14+(i*(sgEdit->ColCount-1)+(j-1))*4, 0); + fread(&iVal, 4, 1, stream); + FileWrite(iFileHandle, &iVal, 4); + break; + default: //ÕûÐÍ + iVal=StrToFloat(sgEdit->Cells[j][i]); + FileWrite(iFileHandle, &iVal, 4); + } + } + } + } + FileClose(iFileHandle); + fclose(stream); + + delete ini; + ShowMessage("Save To File:"+NewFileName); +} +void __fastcall TFrmMain::btIntTypeClick(TObject *Sender) +{ +if(OpenOk==true){ + AnsiString iniSetFile=ExtractFilePath(Application->ExeName)+"BcdEditer.ini"; + AnsiString SectionName=ExtractFileName(CurrentOpenFile); + TIniFile *ini; + ini = new TIniFile( iniSetFile ); + ini->WriteInteger(SectionName,"ColType"+IntToStr(sgEdit->Col),0); + delete ini; + thOpen->ColType[sgEdit->Col]=0; + //ÖØÐ´ò¿ª¶ÔÓ¦ÁеÄÖµ + //OpenFileCol(AnsiString FileName,int ColType); + OpenFileCol(CurrentOpenFile,sgEdit->Col,0); +} +} +//--------------------------------------------------------------------------- + + +void __fastcall TFrmMain::btFloatTypeClick(TObject *Sender) +{ +if(OpenOk==true){ + AnsiString iniSetFile=ExtractFilePath(Application->ExeName)+"BcdEditer.ini"; + AnsiString SectionName=ExtractFileName(CurrentOpenFile); + TIniFile *ini; + ini = new TIniFile( iniSetFile ); + ini->WriteInteger(SectionName,"ColType"+IntToStr(sgEdit->Col),1); + delete ini; + thOpen->ColType[sgEdit->Col]=1; + OpenFileCol(CurrentOpenFile,sgEdit->Col,1); +} +} +//--------------------------------------------------------------------------- + +void __fastcall TFrmMain::PopupMenu1Popup(TObject *Sender) +{ +if(OpenOk==true){ + AnsiString iniSetFile=ExtractFilePath(Application->ExeName)+"BcdEditer.ini"; + AnsiString SectionName=ExtractFileName(CurrentOpenFile); + int ColType; + TIniFile *ini; + ini = new TIniFile( iniSetFile ); + ColType=ini->ReadInteger(SectionName,"ColType"+IntToStr(sgEdit->Col),0); + delete ini; + switch (ColType) + { + case 0: + btIntType->Checked=true; + btFloatType->Checked=false; + btTxtType->Checked=false; + break; + case 1: + btIntType->Checked=false; + btFloatType->Checked=true; + btTxtType->Checked=false; + break; + case 2: + btIntType->Checked=false; + btFloatType->Checked=false; + btTxtType->Checked=true; + break; + default: + btIntType->Checked=true; + btFloatType->Checked=false; + } +} +} +//--------------------------------------------------------------------------- + +void __fastcall TFrmMain::N1Click(TObject *Sender) +{ + AnsiString iniSetFile=ExtractFilePath(Application->ExeName)+"BcdEditer.ini"; + AnsiString SectionName=ExtractFileName(CurrentOpenFile); + int ColType; + FrmTitle->edTitle->Text=sgEdit->Cells[sgEdit->Col][0]; + if(FrmTitle->ShowModal()==mrOk){ + TIniFile *ini; + ini = new TIniFile( iniSetFile ); + ini->WriteString(SectionName,"ColTitle"+IntToStr(sgEdit->Col),FrmTitle->edTitle->Text); + delete ini; + sgEdit->Cells[sgEdit->Col][0]=FrmTitle->edTitle->Text; + } +} +//--------------------------------------------------------------------------- + + + +void __fastcall TFrmMain::FormDestroy(TObject *Sender) +{ + if(thOpen){ + thOpen->Terminate(); + SleepEx(200,0); + } +} +//--------------------------------------------------------------------------- + +void __fastcall TFrmMain::ToolButton1Click(TObject *Sender) +{ + bool SeFlag=true; + if(FrmSearch->ShowModal()==mrOk){ + switch (FrmSearch->rgSI->ItemIndex) + { + case 0: //ÏòÉÏÕÒ; + for(int i=sgEdit->ColCount*sgEdit->Row+sgEdit->Col-1;i>sgEdit->ColCount;i--){ + if(i%sgEdit->ColCount!=0){ + if( 0==CompareStr(sgEdit->Cells[i-sgEdit->ColCount*(i/sgEdit->ColCount)][i/sgEdit->ColCount], + FrmSearch->edSeach->Text)){ //ÕÒµ½ÁË + sgEdit->Col=i-sgEdit->ColCount*i/sgEdit->ColCount; + sgEdit->Row=i/sgEdit->ColCount; + SeFlag=false; + break; + } + } + } + if(SeFlag) ShowMessage("Seach Top£¬Find Nothing."); + break; + case 1: //ÏòÏÂÕÒ; + for(int i=sgEdit->ColCount*sgEdit->Row+sgEdit->Col+1;iColCount*sgEdit->RowCount;i++){ + if(i%sgEdit->ColCount!=0){ + if( 0==CompareStr(sgEdit->Cells[i-sgEdit->ColCount*(i/sgEdit->ColCount)][i/sgEdit->ColCount], + FrmSearch->edSeach->Text)){ //ÕÒµ½ÁË + sgEdit->Col=i-sgEdit->ColCount*(i/sgEdit->ColCount); + sgEdit->Row=i/sgEdit->ColCount; + SeFlag=false; + break; + } + } + } + if(SeFlag) ShowMessage("Seach End£¬Find Nothing"); + break; + case 2: //µ±Ç°ÁÐÏòÉÏÕÒ; + for(int i=sgEdit->Row;i>1;i--){ + if( 0==CompareStr(sgEdit->Cells[sgEdit->Col][i], + FrmSearch->edSeach->Text)){ //ÕÒµ½ÁË + sgEdit->Row=i; + SeFlag=false; + break; + } + } + if(SeFlag) ShowMessage("Seach col top£¬Find Nothing"); + break; + case 3: //µ±Ç°ÁÐÏòÏÂÕÒ; + for(int i=sgEdit->Row;iRowCount;i++){ + if( 0==CompareStr(sgEdit->Cells[sgEdit->Col][i], + FrmSearch->edSeach->Text)){ //ÕÒµ½ÁË + sgEdit->Row=i; + SeFlag=false; + break; + } + } + if(SeFlag) ShowMessage("Seach col end£¬Find Nothing."); + break; + } + } +} +//--------------------------------------------------------------------------- + +void __fastcall TFrmMain::sgEditKeyDown(TObject *Sender, WORD &Key, + TShiftState Shift) +{ + + bool SeFlag=true; + if(Key==VK_F3){ + switch (FrmSearch->rgSI->ItemIndex) + { + case 0: //ÏòÉÏÕÒ; + for(int i=sgEdit->ColCount*sgEdit->Row+sgEdit->Col-1;i>sgEdit->ColCount;i--){ + if(i%sgEdit->ColCount!=0){ + if( 0==CompareStr(sgEdit->Cells[i-sgEdit->ColCount*(i/sgEdit->ColCount)][i/sgEdit->ColCount], + FrmSearch->edSeach->Text)){ //ÕÒµ½ÁË + sgEdit->Col=i-sgEdit->ColCount*i/sgEdit->ColCount; + sgEdit->Row=i/sgEdit->ColCount; + SeFlag=false; + break; + } + } + } + if(SeFlag) ShowMessage("Seach Top£¬Find Nothing."); + break; + case 1: //ÏòÏÂÕÒ; + for(int i=sgEdit->ColCount*sgEdit->Row+sgEdit->Col+1;iColCount*sgEdit->RowCount;i++){ + if(i%sgEdit->ColCount!=0){ + if( 0==CompareStr(sgEdit->Cells[i-sgEdit->ColCount*(i/sgEdit->ColCount)][i/sgEdit->ColCount], + FrmSearch->edSeach->Text)){ //ÕÒµ½ÁË + sgEdit->Col=i-sgEdit->ColCount*(i/sgEdit->ColCount); + sgEdit->Row=i/sgEdit->ColCount; + SeFlag=false; + break; + } + } + } + if(SeFlag) ShowMessage("Seach End£¬Find Nothing."); + break; + case 2: //µ±Ç°ÁÐÏòÉÏÕÒ; + for(int i=sgEdit->Row;i>1;i--){ + if( 0==CompareStr(sgEdit->Cells[sgEdit->Col][i], + FrmSearch->edSeach->Text)){ //ÕÒµ½ÁË + sgEdit->Row=i; + SeFlag=false; + break; + } + } + if(SeFlag) ShowMessage("Seach col Top£¬Find Nothing."); + break; + case 3: //µ±Ç°ÁÐÏòÏÂÕÒ; + for(int i=sgEdit->Row;iRowCount;i++){ + if( 0==CompareStr(sgEdit->Cells[sgEdit->Col][i], + FrmSearch->edSeach->Text)){ //ÕÒµ½ÁË + sgEdit->Row=i; + SeFlag=false; + break; + } + } + if(SeFlag) ShowMessage("Seach col end£¬Find Nothing."); + break; + } + } +} +//--------------------------------------------------------------------------- + +void __fastcall TFrmMain::sgEditSelectCell(TObject *Sender, int ACol, + int ARow, bool &CanSelect) +{ +// +} +//--------------------------------------------------------------------------- +void __fastcall TFrmMain::OpenFileCol(AnsiString FileName,int ColIndex,int ColType) +{ + int iFileHandle; //Îļþ¾ä±ú + char Txtbuf[255]; + int iVal; + float fVal; + FILE *stream; + long curpos, length; + DWORD dwRows, dwCols, dwRowLen, dwTextLen; + + DWORD dwTextStartPos; + char* pTextPtr ; + + + if ((stream = fopen(FileName.c_str(), "r+")) + == NULL) + { + ShowMessage("Open File Error"); + return; + } + + curpos = ftell(stream); + fseek(stream, 0L, SEEK_END); + length = ftell(stream); + + + switch (ColType) + { + case 0: //ÕûÐÍÖµ Int + for(int i=0;iRowCount-1;i++){ + fseek(stream, 0x14+(i*(sgEdit->ColCount-1)+(ColIndex-1))*4, 0); + fread(&iVal, 4, 1, stream); + sgEdit->Cells[ColIndex][i+1]=IntToStr(iVal); + } + break; + case 1: //¸¡µãÖµ Float + for(int i=0;iRowCount-1;i++){ + fseek(stream, 0x14+(i*(sgEdit->ColCount-1)+(ColIndex-1))*4, 0); + fread(&fVal, 4, 1, stream); + sgEdit->Cells[ColIndex][i+1]=FloatToStr(fVal); + } + break; + case 2: //Îı¾ Text + fseek(stream,0x4,0); + fread(&iVal, 4, 1, stream); + dwRows= iVal; + fread(&iVal, 4, 1, stream); + dwCols = iVal; + fread(&iVal, 4, 1, stream); + dwRowLen = iVal; + fread(&iVal, 4, 1, stream); + dwTextLen = iVal; + + dwTextStartPos = dwRows*dwRowLen+20; + for(int i=0;iRowCount-1;i++){ + fseek(stream, 0x14+(i*(sgEdit->ColCount-1)+(ColIndex-1))*4, 0); + fread(&iVal, 4, 1, stream); + sgEdit->Cells[ColIndex][i+1]=IntToStr(iVal); + if(dwTextStartPos + iVal < length){ + fseek(stream,dwTextStartPos + iVal,0); + fread(Txtbuf, 1, 255, stream); + //pTextPtr = pBuff + dwTextStartPos + lTemp; + sgEdit->Cells[ColIndex][i+1]=Txtbuf; + }else{ + sgEdit->Cells[ColIndex][i+1]="This Col Not Text!"; + } + } + break; + } + fclose(stream); +} +void __fastcall TFrmMain::Timer1Timer(TObject *Sender) +{ + if(OpenOk){ + lbOpState->Caption = "Open File Ok."; + }else{ + lbOpState->Caption = "Open Now....."; + } +} +//--------------------------------------------------------------------------- +//µ±Ç°¸ñ×ÓдÈëÐÞ¸ÄÎļþÖÐ +void __fastcall TFrmMain::N4Click(TObject *Sender) +{ + if(!thOpen) return; + + int iFileHandle; //Îļþ¾ä±ú + char buf[4]; + int iVal; + float fVal; + FILE *stream; +/* + if ((stream = fopen(CurrentOpenFile.c_str(), "r+")) + == NULL) + { + ShowMessage("´ò¿ªÎļþ³ö´í"); + return; + } +*/ + iFileHandle = FileOpen(CurrentOpenFile, fmOpenRead|fmOpenWrite);//´ò¿ªÎļþ + + switch (thOpen->ColType[sgEdit->Col]) + { + case 0: //ÕûÐÍÖµ + //for(int i=0;iRowCount-1;i++){ + /* + fseek(stream, 0x14+((sgEdit->Row-1)*(sgEdit->ColCount-1)+(sgEdit->Col-1))*4, 0); + iVal=StrToInt(sgEdit->Cells[sgEdit->Col][sgEdit->Row]); + memcpy(buf, &iVal, 4); + for(int i=0;i<4;i++) + fwrite(buf+i, 1, 1, stream); + */ + iVal=StrToInt(sgEdit->Cells[sgEdit->Col][sgEdit->Row]); + memcpy(buf, &iVal, 4); + FileSeek(iFileHandle,0x14+((sgEdit->Row-1)*(sgEdit->ColCount-1)+(sgEdit->Col-1))*4,0); + FileWrite(iFileHandle,buf,4); + //} + break; + case 1: //¸¡µãÖµ + //fseek(stream, 0x14+((sgEdit->Row-1)*(sgEdit->ColCount-1)+(sgEdit->Col-1))*4, 0); + //fVal=StrToFloat(sgEdit->Cells[sgEdit->Col][sgEdit->Row]); + //fwrite(&fVal, 4, 1, stream); + fVal=StrToFloat(sgEdit->Cells[sgEdit->Col][sgEdit->Row]); + memcpy(buf, &fVal, 4); + FileSeek(iFileHandle,0x14+((sgEdit->Row-1)*(sgEdit->ColCount-1)+(sgEdit->Col-1))*4,0); + FileWrite(iFileHandle,buf,4); + break; + case 2: //Îı¾²»Ð´Èë + break; + } + + // fclose(stream); + FileClose(iFileHandle); +} +//--------------------------------------------------------------------------- + +void __fastcall TFrmMain::btTxtTypeClick(TObject *Sender) +{ +if(OpenOk==true){ + AnsiString iniSetFile=ExtractFilePath(Application->ExeName)+"BcdEditer.ini"; + AnsiString SectionName=ExtractFileName(CurrentOpenFile); + TIniFile *ini; + ini = new TIniFile( iniSetFile ); + ini->WriteInteger(SectionName,"ColType"+IntToStr(sgEdit->Col),2); + delete ini; + thOpen->ColType[sgEdit->Col]=2; + OpenFileCol(CurrentOpenFile,sgEdit->Col,2); +} +} +//--------------------------------------------------------------------------- + +void __fastcall TFrmMain::ToolButton3Click(TObject *Sender) +{ + int OldCol; + int OldRow; + OldRow=sgEdit->Row; + OldCol=sgEdit->Col; + if(sgEdit->FixedCols==1){ + sgEdit->FixedCols =2; + if(OldCol!=1) + sgEdit->Col=OldCol; + sgEdit->Row=OldRow; + }else{ + sgEdit->FixedCols =1; + sgEdit->Row=OldRow; + if(OldCol!=2) + sgEdit->Col=OldCol; + } +} +//--------------------------------------------------------------------------- + +void __fastcall TFrmMain::btRowSaveClick(TObject *Sender) +{ +if(OpenOk==false) return; + + int iFileHandle; //Îļþ¾ä±ú + char Txtbuf[255]; + int iVal; + char buf[4]; + float fVal; + FILE *stream; + long curpos, length; + DWORD dwRows, dwCols, dwRowLen, dwTextLen; + + DWORD dwTextStartPos; + char* pTextPtr ; + + + //if ((stream = fopen(CurrentOpenFile.c_str(), "r+")) + // == NULL) + //{ + // ShowMessage("´ò¿ªÎļþ³ö´í"); + // return; + //} + + //curpos = ftell(stream); + //fseek(stream, 0L, SEEK_END); + //length = ftell(stream); + iFileHandle = FileOpen(CurrentOpenFile, fmOpenRead|fmOpenWrite);//´ò¿ªÎļþ + +for(int i=0;iColCount-1;i++){ + switch (thOpen->ColType[i]) + { + case 0: //ÕûÐÍÖµ sgEdit->Row + //fseek(stream, 0x14+((sgEdit->Row-1)*(sgEdit->ColCount-1)+i)*4, 0); + //iVal=StrToInt(sgEdit->Cells[i+1][sgEdit->Row]); + //fwrite(&iVal, 4, 1, stream); + iVal=StrToInt(sgEdit->Cells[i+1][sgEdit->Row]); + memcpy(buf, &iVal, 4); + FileSeek(iFileHandle,0x14+((sgEdit->Row-1)*(sgEdit->ColCount-1)+i)*4,0); + FileWrite(iFileHandle,buf,4); + break; + case 1: //¸¡µãÖµ + //fseek(stream, 0x14+((sgEdit->Row-1)*(sgEdit->ColCount-1)+i)*4, 0); + //fVal=StrToFloat(sgEdit->Cells[i+1][sgEdit->Row]); + //fwrite(&fVal, 4, 1, stream); + fVal=StrToFloat(sgEdit->Cells[i+1][sgEdit->Row]); + memcpy(buf, &fVal, 4); + FileSeek(iFileHandle,0x14+((sgEdit->Row-1)*(sgEdit->ColCount-1)+i)*4,0); + FileWrite(iFileHandle,buf,4); + break; + case 2: //Îı¾ ²»´æ + break; + } +} + //fclose(stream); + FileClose(iFileHandle); + ShowMessage("The "+IntToStr(sgEdit->Row)+" Row Write Ok!"); +} +//--------------------------------------------------------------------------- + +void __fastcall TFrmMain::btColSaveClick(TObject *Sender) +{ +if(OpenOk==false) return; + + int iFileHandle; //Îļþ¾ä±ú + char Txtbuf[255]; + int iVal; + char buf[4]; + float fVal; + FILE *stream; + long curpos, length; + DWORD dwRows, dwCols, dwRowLen, dwTextLen; + + DWORD dwTextStartPos; + char* pTextPtr ; + + iFileHandle = FileOpen(CurrentOpenFile, fmOpenRead|fmOpenWrite);//´ò¿ªÎļþ + + //if ((stream = fopen(CurrentOpenFile.c_str(), "r+")) + // == NULL) + //{ + // ShowMessage("´ò¿ªÎļþ³ö´í"); + // return; + //} + + //curpos = ftell(stream); + //fseek(stream, 0L, SEEK_END); + //length = ftell(stream); + + + switch (thOpen->ColType[sgEdit->Col]) + { + case 0: //ÕûÐÍÖµ + for(int i=0;iRowCount-1;i++){ + //fseek(stream, 0x14+(i*(sgEdit->ColCount-1)+(sgEdit->Col-1))*4, 0); + //iVal=StrToInt(sgEdit->Cells[sgEdit->Col][i+1]); + //fwrite(&iVal, 4, 1, stream); + iVal=StrToInt(sgEdit->Cells[sgEdit->Col][i+1]); + memcpy(buf, &iVal, 4); + FileSeek(iFileHandle,0x14+(i*(sgEdit->ColCount-1)+(sgEdit->Col-1))*4,0); + FileWrite(iFileHandle,buf,4); + } + break; + case 1: //¸¡µãÖµ + for(int i=0;iRowCount-1;i++){ + //fseek(stream, 0x14+(i*(sgEdit->ColCount-1)+(sgEdit->Col-1))*4, 0); + //fVal=StrToFloat(sgEdit->Cells[sgEdit->Col][i+1]); + //fwrite(&fVal, 4, 1, stream); + fVal=StrToFloat(sgEdit->Cells[sgEdit->Col][i+1]); + memcpy(buf, &fVal, 4); + FileSeek(iFileHandle,0x14+(i*(sgEdit->ColCount-1)+(sgEdit->Col-1))*4,0); + FileWrite(iFileHandle,buf,4); + } + break; + case 2: //Îı¾ ²»´æ + break; + } + //fclose(stream); + + FileClose(iFileHandle); + ShowMessage("The "+IntToStr(sgEdit->Col)+"Col Write Ok!"); +} +//--------------------------------------------------------------------------- + +void __fastcall TFrmMain::btRowClearClick(TObject *Sender) +{ +if(OpenOk==false) return; + + int iFileHandle; //Îļþ¾ä±ú + char Txtbuf[255]; + int iVal; + float fVal; + FILE *stream; + long curpos, length; + DWORD dwRows, dwCols, dwRowLen, dwTextLen; + + DWORD dwTextStartPos; + char* pTextPtr ; + + + if ((stream = fopen(CurrentOpenFile.c_str(), "r+")) + == NULL) + { + ShowMessage("Open File Error!"); + return; + } + + curpos = ftell(stream); + fseek(stream, 0L, SEEK_END); + length = ftell(stream); + +for(int i=1;iColCount-1;i++){ + switch (thOpen->ColType[i]) + { + case 0: //ÕûÐÍÖµ sgEdit->Row + //fseek(stream, 0x14+(sgEdit->Row*(sgEdit->ColCount-1)+i)*4, 0); + //iVal=StrToInt(sgEdit->Cells[i+1][sgEdit->Row]); + //fwrite(&iVal, 4, 1, stream); + sgEdit->Cells[i+1][sgEdit->Row]="0"; + break; + case 1: //¸¡µãÖµ + //fseek(stream, 0x14+(sgEdit->Row*(sgEdit->ColCount-1)+i)*4, 0); + //fVal=StrToFloat(sgEdit->Cells[i+1][sgEdit->Row]); + //fwrite(&fVal, 4, 1, stream); + sgEdit->Cells[i+1][sgEdit->Row]="0"; + break; + case 2: //Îı¾ ²»´æ + break; + } +} + fclose(stream); +} +//--------------------------------------------------------------------------- + +void __fastcall TFrmMain::btColClearClick(TObject *Sender) +{ +if(OpenOk==false) return; + + int iFileHandle; //Îļþ¾ä±ú + char Txtbuf[255]; + int iVal; + float fVal; + FILE *stream; + long curpos, length; + DWORD dwRows, dwCols, dwRowLen, dwTextLen; + + DWORD dwTextStartPos; + char* pTextPtr ; + + + if ((stream = fopen(CurrentOpenFile.c_str(), "r+")) + == NULL) + { + ShowMessage("Open File Error!"); + return; + } + + curpos = ftell(stream); + fseek(stream, 0L, SEEK_END); + length = ftell(stream); + + + switch (thOpen->ColType[sgEdit->Col]) + { + case 0: //ÕûÐÍÖµ + for(int i=0;iRowCount-1;i++){ + //fseek(stream, 0x14+(i*(sgEdit->ColCount-1)+(ColIndex-1))*4, 0); + //iVal=StrToInt(sgEdit->Cells[ColIndex][i+1]); + //fwrite(&iVal, 4, 1, stream); + sgEdit->Cells[sgEdit->Col][i+1]="0"; + } + break; + case 1: //¸¡µãÖµ + for(int i=0;iRowCount-1;i++){ + //fseek(stream, 0x14+(i*(sgEdit->ColCount-1)+(ColIndex-1))*4, 0); + //fVal=StrToFloat(sgEdit->Cells[ColIndex][i+1]); + //fwrite(&fVal, 4, 1, stream); + sgEdit->Cells[sgEdit->Col][i+1]="0"; + } + break; + case 2: //Îı¾ ²»´æ + break; + } + fclose(stream); +} +//--------------------------------------------------------------------------- + +void __fastcall TFrmMain::ToolButton4Click(TObject *Sender) +{ + AnsiString Cmd; + Cmd = "calc.exe"; + WinExec(Cmd.c_str(), SW_SHOWNORMAL); +} +//--------------------------------------------------------------------------- + + diff --git a/contrib/dbcEditer/dbcedit.ddp b/contrib/dbcEditer/dbcedit.ddp new file mode 100644 index 00000000000..cdc0ee8c2b5 Binary files /dev/null and b/contrib/dbcEditer/dbcedit.ddp differ diff --git a/contrib/dbcEditer/dbcedit.dfm b/contrib/dbcEditer/dbcedit.dfm new file mode 100644 index 00000000000..24bf375ab74 --- /dev/null +++ b/contrib/dbcEditer/dbcedit.dfm @@ -0,0 +1,1259 @@ +object FrmMain: TFrmMain + Left = 162 + Top = 122 + Width = 544 + Height = 375 + Caption = 'Dbc Editer v1.4.2 Vendy QQ:11177905' + Color = clBtnFace + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'MS Sans Serif' + Font.Style = [] + OldCreateOrder = False + OnDestroy = FormDestroy + PixelsPerInch = 96 + TextHeight = 13 + object Panel1: TPanel + Left = 0 + Top = 33 + Width = 536 + Height = 315 + Align = alClient + Caption = 'Panel1' + TabOrder = 0 + object sgEdit: TStringGrid + Left = 1 + Top = 1 + Width = 534 + Height = 287 + Align = alClient + Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goDrawFocusSelected, goRowSizing, goColSizing, goEditing] + PopupMenu = PopupMenu1 + TabOrder = 0 + OnKeyDown = sgEditKeyDown + OnSelectCell = sgEditSelectCell + end + object pnFileName: TPanel + Left = 1 + Top = 288 + Width = 534 + Height = 26 + Align = alBottom + Alignment = taLeftJustify + Caption = 'pnFileName' + Font.Charset = DEFAULT_CHARSET + Font.Color = clRed + Font.Height = -11 + Font.Name = 'MS Sans Serif' + Font.Style = [fsBold] + ParentFont = False + TabOrder = 1 + object lbOpState: TLabel + Left = 444 + Top = 1 + Width = 89 + Height = 24 + Align = alRight + AutoSize = False + Caption = #25171#24320#25991#20214#29366#24577 + end + end + end + object CoolBar1: TCoolBar + Left = 0 + Top = 0 + Width = 536 + Height = 33 + Bands = < + item + Control = ToolBar1 + ImageIndex = -1 + Width = 532 + end> + object ToolBar1: TToolBar + Left = 9 + Top = 0 + Width = 519 + Height = 25 + Caption = 'ToolBar1' + Images = ImageList1 + TabOrder = 0 + object btOpen: TToolButton + Left = 0 + Top = 2 + Caption = 'btOpen' + ImageIndex = 7 + OnClick = btOpenClick + end + object btSave: TToolButton + Left = 23 + Top = 2 + Caption = 'btSave' + Enabled = False + Grouped = True + ImageIndex = 8 + OnClick = btSaveClick + end + object ToolButton2: TToolButton + Left = 46 + Top = 2 + Width = 8 + Caption = 'ToolButton2' + ImageIndex = 10 + Style = tbsSeparator + end + object ToolButton1: TToolButton + Left = 54 + Top = 2 + Caption = 'ToolButton1' + ImageIndex = 9 + OnClick = ToolButton1Click + end + object ToolButton3: TToolButton + Left = 77 + Top = 2 + Caption = 'ToolButton3' + ImageIndex = 10 + OnClick = ToolButton3Click + end + object ToolButton5: TToolButton + Left = 100 + Top = 2 + Width = 8 + Caption = 'ToolButton5' + ImageIndex = 12 + Style = tbsSeparator + end + object ToolButton4: TToolButton + Left = 108 + Top = 2 + Caption = 'ToolButton4' + ImageIndex = 11 + OnClick = ToolButton4Click + end + end + end + object OpenDialog1: TOpenDialog + Filter = '.dbc|*.dbc' + Left = 216 + Top = 96 + end + object PopupMenu1: TPopupMenu + OnPopup = PopupMenu1Popup + Left = 264 + Top = 96 + object N1: TMenuItem + Caption = 'Set Current Col Title' + OnClick = N1Click + end + object N2: TMenuItem + Caption = 'Set Current Col Type' + object btIntType: TMenuItem + Caption = 'INT' + OnClick = btIntTypeClick + end + object btFloatType: TMenuItem + Caption = 'FLOAT' + OnClick = btFloatTypeClick + end + object btTxtType: TMenuItem + Caption = 'TEXT' + OnClick = btTxtTypeClick + end + end + object N4: TMenuItem + Caption = 'Write Current Grid' + OnClick = N4Click + end + object btRowSave: TMenuItem + Caption = 'Write Current Row' + OnClick = btRowSaveClick + end + object btColSave: TMenuItem + Caption = 'Write Current Col' + OnClick = btColSaveClick + end + object btRowClear: TMenuItem + Caption = 'Clear Current Row' + OnClick = btRowClearClick + end + object btColClear: TMenuItem + Caption = 'Clear Current Col' + OnClick = btColClearClick + end + end + object ImageList1: TImageList + Left = 352 + Top = 112 + Bitmap = { + 494C010118001D00040010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600 + 0000000000003600000028000000400000008000000001002000000000000080 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000800000008000000080000000800000008000000080000000800000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000FF000000FF00FFFFFF00FFFFFF00FFFFFF000000FF000000FF000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000008000 + 000080000000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF008000 + 000080000000000000000000000000000000000000000000000000000000FFFF + FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF00FFFF + FF00000000000000000000000000000000000000000000000000000000000000 + 000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF + 000000FF00000000000000000000000000000000000000000000000000000000 + 00000000FF0080808000000000000000000000000000000000000000FF008080 + 8000000000000000000000000000000000000000000000000000800000008000 + 000080000000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF008000 + 0000800000008000000000000000000000000000000000000000FFFFFF000000 + FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000 + FF00FFFFFF000000000000000000000000000000000000000000000000000000 + 000000FF00000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000FF00808080000000000000000000000000000000FF00808080000000 + 0000000000000000000000000000000000000000000080000000800000008000 + 0000800000008000000080000000FFFFFF00FFFFFF00FFFFFF00800000008000 + 00008000000080000000000000000000000000000000FFFFFF000000FF000000 + FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000 + FF000000FF00FFFFFF0000000000000000000000000000000000000000000000 + 000000FF00000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000FF008080800000000000000000000000FF0080808000000000000000 + 0000000000000000000000000000000000000000000080000000800000008000 + 0000800000008000000080000000FFFFFF00FFFFFF00FFFFFF00800000008000 + 0000800000008000000080000000000000000000FF000000FF000000FF000000 + FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000 + FF000000FF000000FF000000FF00000000000000000000000000000000000000 + 000000FF00000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000FF0080808000000000000000FF008080800000000000000000000000 + 0000000000000000000000000000000000008000000080000000800000008000 + 0000800000008000000080000000FFFFFF00FFFFFF00FFFFFF00800000008000 + 0000800000008000000080000000000000000000FF000000FF000000FF000000 + FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000 + FF000000FF000000FF000000FF00000000000000000000000000000000000000 + 000000FF00000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000FF00808080000000FF00808080000000000000000000000000000000 + 0000000000000000000000000000000000008000000080000000800000008000 + 0000800000008000000080000000FFFFFF00FFFFFF00FFFFFF00800000008000 + 000080000000800000008000000000000000FFFFFF000000FF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF000000FF00FFFFFF00000000000000000000000000000000000000 + 000000FF00000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000FF000000FF000000FF000000FF000000FF000000FF000000FF008080 + 8000000000000000000000000000000000008000000080000000800000008000 + 0000800000008000000080000000FFFFFF00FFFFFF00FFFFFF00800000008000 + 000080000000800000008000000000000000FFFFFF000000FF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF000000FF00FFFFFF00000000000000000000000000000000000000 + 000000FF00000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000FF0080808000808080008080800080808000808080000000FF008080 + 8000000000000000000000000000000000008000000080000000800000008000 + 0000800000008000000080000000FFFFFF00FFFFFF00FFFFFF00800000008000 + 000080000000800000008000000000000000FFFFFF000000FF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF000000FF00FFFFFF00000000000000000000000000000000000000 + 000000FF00000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000FF0080808000000000000000000000000000000000000000FF008080 + 8000000000000000000000000000000000000000000080000000800000008000 + 000080000000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00800000008000 + 0000800000008000000080000000000000000000FF000000FF000000FF000000 + FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000 + FF000000FF000000FF000000FF00000000000000000000000000000000000000 + 000000FF00000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000FF00808080000000000000000000000000000000FF000000FF008080 + 8000000000000000000000000000000000000000000080000000800000008000 + 0000800000008000000080000000800000008000000080000000800000008000 + 0000800000008000000080000000000000000000FF000000FF000000FF000000 + FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000 + FF000000FF000000FF000000FF00000000000000000000000000000000000000 + 000000FF00000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000FF000000FF000000FF000000FF000000FF00808080000000 + 0000000000000000000000000000000000000000000080000000800000008000 + 00008000000080000000FFFFFF00FFFFFF00FFFFFF0080000000800000008000 + 00008000000080000000000000000000000000000000FFFFFF000000FF000000 + FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000 + FF000000FF00FFFFFF0000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000008080800080808000808080008080800080808000000000000000 + 0000000000000000000000000000000000000000000000000000800000008000 + 00008000000080000000FFFFFF00FFFFFF00FFFFFF00FFFFFF00800000008000 + 0000800000000000000000000000000000000000000000000000FFFFFF000000 + FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000 + FF00FFFFFF000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000008000 + 00008000000080000000FFFFFF00FFFFFF00FFFFFF0080000000800000008000 + 000000000000000000000000000000000000000000000000000000000000FFFF + FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF00FFFF + FF00000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000080000000800000008000000080000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000FF000000FF00FFFFFF00FFFFFF00FFFFFF000000FF000000FF000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000080000000800000008000000080000000800000008000 + 0000800000008000000080000000800000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000080000000800000008000 + 0000800000008000000080000000800000008000000080000000800000008000 + 0000800000008000000000000000000000000000000000000000000000000000 + 0000000000000000000080000000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00800000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000080000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF0080000000FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF008000000000000000000000000000000000000000000000000000 + 0000000000000000000080000000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00800000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000080000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF0080000000FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF008000000000000000000000000000000000000000000000000000 + 0000000000000000000080000000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00800000000000000000000000000000000000 + 000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF + 000000FF00000000000000000000000000000000000000000000000000000000 + 000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF + 000000FF00000000000000000000000000000000000080000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF0080000000FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF008000000000000000000000000000000000000000000000008000 + 0000800000008000000080000000800000008000000080000000800000008000 + 0000800000008000000080000000800000000000000000000000000000000000 + 000000FF00000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000FF00000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000080000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF0080000000FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF008000000000000000000000000000000000000000000000008000 + 0000FFFFFF00FFFFFF0080000000800000008000000080000000800000008000 + 00008000000080000000FFFFFF00800000000000000000000000000000000000 + 000000FF00000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000FF00000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000080000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF0080000000FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF008000000000000000000000000000000000000000000000008000 + 0000FFFFFF00FFFFFF0080000000800000008000000080000000800000008000 + 0000800000008000000080000000800000000000000000000000000000000000 + 000000FF00000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000FF00000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000080000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF0080000000FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF008000000000000000000000000000000000000000000000008000 + 0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00800000000000000000000000000000000000000000000000000000000000 + 000000FF00000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000FF00000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000080000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF0080000000FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF008000000000000000000000000000000080000000800000008000 + 0000800000008000000080000000800000008000000080000000800000008000 + 0000800000000000000000000000000000000000000000000000000000000000 + 000000FF00000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000FF00000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000080000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF0080000000FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF008000000000000000000000000000000080000000FFFFFF008000 + 000080000000800000008000000080000000800000008000000080000000FFFF + FF00800000000000000000000000000000000000000000000000000000000000 + 000000FF00000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000FF00000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000080000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF0080000000FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF008000000000000000000000000000000080000000FFFFFF008000 + 0000800000008000000080000000800000008000000080000000800000008000 + 0000800000000000000000000000000000000000000000000000000000000000 + 000000FF00000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000FF00000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000080000000800000008000 + 0000800000008000000080000000800000008000000080000000800000008000 + 0000800000008000000000000000000000000000000080000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00800000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000FF00000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000FF00000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000080000000800000008000 + 00008000000080000000FFFFFF00800000008000000080000000800000008000 + 0000FFFFFF008000000000000000000000000000000080000000800000008000 + 0000800000008000000080000000800000008000000080000000800000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000FF00000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000FF00000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000080000000800000008000 + 0000800000008000000080000000800000008000000080000000800000008000 + 0000800000008000000000000000000000000000000080000000800000008000 + 00008000000080000000800000008000000080000000FFFFFF00800000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000080000000800000008000 + 0000800000008000000080000000800000008000000080000000800000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000800000008000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000008000 + 0000C0C0C0008000000080000000000000000000000000000000000000000000 + 0000000000000000000000000000000000008000000080000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000080000000800000008000 + 0000800000008000000080000000800000008000000080000000800000008000 + 0000800000008000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000000000000000000080000000C0C0 + C000800000008000000080000000000000000000000000000000000000000000 + 0000000000000000000000000000800000008000000080000000000000000000 + 0000000000000000000000000000000000000000000000000000C0C0C000C0C0 + C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C0000000 + 0000C0C0C0000000000000000000000000000000000080000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF008000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000080000000C0C0C0008000 + 0000800000008000000000000000000000000000000000000000000000000000 + 0000000000000000000080000000800000008000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000C0C0C00000000000000000000000000080000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF008000000000000000000000000000000000000000000000000000 + 00000000000000000000000000000000000080000000C0C0C000800000008000 + 000080000000000000000000000000000000000000000000000080808000C0C0 + C000FFFFFF008080800000000000800000000000000000000000000000000000 + 00000000800000000000000000000000000000000000C0C0C000C0C0C000C0C0 + C000C0C0C000C0C0C000C0C0C00000FFFF0000FFFF0000FFFF00C0C0C000C0C0 + C000000000000000000000000000000000000000000080000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF008000000000000000000000000000000000000000000000000000 + 0000C0C0C000C0C0C000C0C0C000FFFFFF008080800080000000800000008000 + 0000000000000000000000000000000000000000000080808000C0C0C000C0C0 + C000C0C0C000FFFFFF0080808000000000000000000000000000000000000000 + 80000000800000000000000000000000000000000000C0C0C000C0C0C000C0C0 + C000C0C0C000C0C0C000C0C0C000808080008080800080808000C0C0C000C0C0 + C00000000000C0C0C00000000000000000000000000080000000800000008000 + 0000800000008000000080000000800000008000000080000000800000008000 + 000080000000800000000000000000000000000000000000000080808000C0C0 + C000C0C0C000C0C0C000C0C0C000C0C0C000FFFFFF0080808000000000000000 + 00000000000000000000000000000000000000000000C0C0C000C0C0C000C0C0 + C000C0C0C000C0C0C000FFFFFF00000000000000000000000000000080000000 + 8000000080000000800000008000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000C0C0C000C0C0C000000000000000000080000000800000008000 + 0000800000008000000080000000800000008000000080000000800000008000 + 0000FFFFFF008000000000000000000000000000000000000000C0C0C000C0C0 + C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000FFFFFF00000000000000 + 00000000000000000000000000000000000000000000C0C0C000FFFFFF00FFFF + 0000C0C0C000C0C0C000C0C0C000000000000000000000000000000000000000 + 80000000800000000000000000000000800000000000C0C0C000C0C0C000C0C0 + C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C0000000 + 0000C0C0C00000000000C0C0C000000000000000000080000000800000008000 + 0000800000008000000080000000800000008000000080000000800000008000 + 00008000000080000000000000000000000000000000C0C0C000C0C0C000C0C0 + C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C0000000 + 0000000000000000000000000000000000000000000080808000FFFFFF00FFFF + FF00C0C0C000C0C0C00080808000000000000000000000000000000000000000 + 0000000080000000000000000000000080000000000000000000000000000000 + 000000000000000000000000000000000000000000000000000000000000C0C0 + C00000000000C0C0C00000000000000000000000000080000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF0080000000000000000000000000000000C0C0C000C0C0C000C0C0 + C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C0000000 + 000000000000000000000000000000000000000000000000000080808000C0C0 + C000C0C0C0008080800000000000000000000000000000000000000000000000 + 000000000000000000000000000000008000000000000000000000000000FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000 + 0000C0C0C00000000000C0C0C000000000000000000080000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF0080000000000000000000000000000000C0C0C000FFFFFF00FFFF + 0000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C0000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000008000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000FFFFFF000000000000000000000000000000000000000000FFFFFF000000 + 0000000000000000000000000000000000000000000080000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF0080000000000000000000000000000000C0C0C000FFFFFF00FFFF + 0000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C0000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000008000000000000000 + 0000000080000000000000000000000000000000000000000000000000000000 + 0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00000000000000000000000000000000000000000080000000800000008000 + 0000800000008000000080000000800000008000000080000000800000008000 + 0000800000008000000000000000000000000000000000000000FFFFFF00FFFF + FF00FFFF0000FFFF0000C0C0C000C0C0C000C0C0C000C0C0C000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000008000000000000000 + 0000000080000000800000000000000000000000000000000000000000000000 + 000000000000FFFFFF000000000000000000000000000000000000000000FFFF + FF00000000000000000000000000000000000000000080000000800000008000 + 0000800000008000000080000000800000008000000080000000800000008000 + 0000FFFFFF00800000000000000000000000000000000000000080808000FFFF + FF00FFFFFF00FFFFFF00C0C0C000C0C0C000C0C0C00080808000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000080000000 + 8000000080000000800000008000000000000000000000000000000000000000 + 000000000000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF000000000000000000000000000000000080000000800000008000 + 0000800000008000000080000000800000008000000080000000800000008000 + 0000800000008000000000000000000000000000000000000000000000000000 + 0000C0C0C000C0C0C000C0C0C000C0C0C0000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000080000000800000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000080000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000008080000080 + 8000000000000000000000000000000000000000000000000000C0C0C000C0C0 + C0000000000000808000000000000000000000000000FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000 + 00000000000000000000000000000000000000000000FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000008080000080 + 8000000000000000000000000000000000000000000000000000C0C0C000C0C0 + C0000000000000808000000000000000000000000000FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000000000000000000000000000 + 00000000000000000000000000000000000000000000FFFFFF00000000000000 + 0000FFFFFF000000000000000000000000000000000000000000FFFFFF000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000800000008000 + 0000800000000000000000000000000000000000000000000000008080000080 + 8000000000000000000000000000000000000000000000000000C0C0C000C0C0 + C0000000000000808000000000000000000000000000FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF000000000080808000C0C0C000C0C0C0008080 + 80000000000000000000000000000000000000000000FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000800000008000 + 0000800000000000000000000000000000000000000000000000008080000080 + 8000000000000000000000000000000000000000000000000000000000000000 + 00000000000000808000000000000000000000000000FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF000000000080808000C0C0C000C0C0C000FFFF00008080 + 80008080800000000000000000000000000000000000FFFFFF00000000000000 + 0000FFFFFF000000000000000000000000000000000000000000FFFFFF000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000008080000080 + 8000008080000080800000808000008080000080800000808000008080000080 + 80000080800000808000000000000000000000000000FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF0000000000C0C0C000C0C0C000C0C0C000C0C0C0008080 + 8000C0C0C00000000000000000000000000000000000FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000800000008000 + 0000800000000000000000000000000000000000000000000000008080000080 + 8000000000000000000000000000000000000000000000000000000000000000 + 00000080800000808000000000000000000000000000FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF0000000000C0C0C000FFFF0000C0C0C000C0C0C0008080 + 8000C0C0C00000000000000000000000000000000000FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0000000000FFFFFF00FFFFFF000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000800000008000 + 0000800000000000000000000000000000000000000000000000008080000000 + 0000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0 + C0000000000000808000000000000000000000000000FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF000000000080808000FFFF0000FFFF0000C0C0C0008080 + 80008080800000000000000000000000000000000000FFFFFF00000000000000 + 0000FFFFFF00FFFFFF00FFFFFF0000000000C0C0C00000000000FFFFFF000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000008000 + 0000800000008000000000000000000000000000000000000000008080000000 + 0000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0 + C0000000000000808000000000000000000000000000FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF000000000080808000C0C0C000C0C0C0008080 + 80000000000000000000000000000000000000000000FFFFFF0000000000C0C0 + C00000000000FFFFFF0000000000C0C0C00000000000C0C0C000000000000000 + 0000000000000000000080000000800000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000800000008000000080000000000000000000000000000000008080000000 + 0000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0 + C0000000000000808000000000000000000000000000FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000000000000000000000000000 + 00000000000000000000000000000000000000000000FFFFFF00FFFFFF000000 + 0000C0C0C00000000000C0C0C00000000000C0C0C00000000000C0C0C000C0C0 + C000C0C0C0000000000080000000800000000000000000000000000000000000 + 0000000000000000000000000000800000008000000080000000000000000000 + 0000000000008000000080000000800000000000000000000000008080000000 + 0000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0 + C0000000000000808000000000000000000000000000FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000C0C0C00000000000C0C0C00000000000C0C0C000C0C0C000C0C0 + C000C0C0C000C0C0C00080000000800000000000000000000000000000000000 + 0000000000000000000000000000800000008000000080000000000000000000 + 0000000000008000000080000000800000000000000000000000008080000000 + 0000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0 + C0000000000000000000000000000000000000000000FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000C0C0C00000000000C0C0C000C0C0C000C0C0C000C0C0 + C000C0C0C000C0C0C00080000000800000000000000000000000000000000000 + 0000000000000000000000000000800000008000000080000000000000000000 + 0000000000008000000080000000800000000000000000000000008080000000 + 0000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0 + C00000000000C0C0C000000000000000000000000000FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0000000000C0C0C000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000C0C0C000C0C0C000C0C0C000C0C0C000C0C0 + C000C0C0C0000000000080000000800000000000000000000000000000000000 + 0000000000000000000000000000000000008000000080000000800000008000 + 0000800000008000000080000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000000000000000000000000FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000080000000800000000000000000000000000000000000 + 0000000000000000000000000000000000000000000080000000800000008000 + 0000800000008000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000000000000000000000000000FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00000000000000000000000000000000000000000000000000008080000080 + 8000008080000080800000808000008080000080800000808000008080000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000000000000000000000000000FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00000000000000000000000000000000000000000000FFFF00000000000080 + 8000008080000080800000808000008080000080800000808000008080000080 + 8000000000000000000000000000000000000000000000000000000000008000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000000000000000000000000000FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF000000000000000000000000000000000000000000FFFFFF0000FFFF000000 + 0000008080000080800000808000008080000080800000808000008080000080 + 8000008080000000000000000000000000000000000000000000000000008000 + 0000000000000000000000000000000000000000000080000000800000008000 + 0000800000008000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000000000000000000000000000FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00000000000000000000000000000000000000000000FFFF00FFFFFF0000FF + FF00000000000080800000808000008080000080800000808000008080000080 + 8000008080000080800000000000000000000000000000000000800000000000 + 0000000000000000000000000000000000000000000000000000800000008000 + 0000800000008000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000000000000000000000000000FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF000000000000000000000000000000000000000000FFFFFF0000FFFF00FFFF + FF0000FFFF000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000800000000000 + 0000000000000000000000000000000000000000000000000000000000008000 + 0000800000008000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000000000000000000000000000FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00000000000000000000000000000000000000000000FFFF00FFFFFF0000FF + FF00FFFFFF0000FFFF00FFFFFF0000FFFF00FFFFFF0000FFFF00000000000000 + 0000000000000000000000000000000000000000000000000000800000000000 + 0000000000000000000000000000000000000000000000000000800000000000 + 0000800000008000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000000000000000000000000000FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF000000000000000000000000000000000000000000FFFFFF0000FFFF00FFFF + FF0000FFFF00FFFFFF0000FFFF00FFFFFF0000FFFF00FFFFFF00000000000000 + 0000000000000000000000000000000000000000000000000000000000008000 + 0000000000000000000000000000000000008000000080000000000000000000 + 0000000000008000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000000000000000000000000000FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00000000000000000000000000000000000000000000FFFF00FFFFFF0000FF + FF00000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000800000008000000080000000800000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000000000000000000000000000FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000000000000000000000000000FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0000000000FFFFFF000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000000000000000000000000000FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000008000000080000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000080000000800000008000000080000000800000008000 + 0000800000008000000080000000800000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000800000000000000000000000800000000000000000000000800000008000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000800000008000000080000000800000008000 + 0000800000008000000080000000800000000000000000000000000000000000 + 0000000000000000000080000000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00800000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000800000000000000000000000800000000000000080000000000000000000 + 0000800000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000080000000FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00800000000000000080808000008080008080 + 8000008080008080800080000000FFFFFF000000000000000000000000000000 + 00000000000000000000FFFFFF00800000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000800000000000000000000000800000000000000080000000000000000000 + 0000800000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000080000000FFFFFF0000000000000000000000 + 00000000000000000000FFFFFF00800000000000000000808000808080000080 + 8000808080000080800080000000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00800000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000008000000080000000800000000000000080000000000000000000 + 0000800000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000080000000FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00800000000000000080808000008080008080 + 8000008080008080800080000000FFFFFF00000000000000000000000000FFFF + FF00800000008000000080000000800000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000800000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000800000000000000080000000800000008000 + 0000000000000000000000000000000000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF0080000000FFFFFF0000000000000000000000 + 00000000000000000000FFFFFF00800000000000000000808000808080000080 + 8000808080000080800080000000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF0080000000FFFFFF0080000000000000000000000000000000800000008000 + 0000800000008000000080000000000000000000000000000000000000000000 + 0000800000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000800000000000000080000000000000000000 + 0000000000000000000000000000000000000000000000000000FFFFFF000000 + 000000000000000000000000000080000000FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00800000000000000080808000008080008080 + 8000008080008080800080000000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00800000008000000000000000000000000000000000000000800000008000 + 0000800000008000000000000000000000000000000000000000000000000000 + 0000000000008000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF0080000000FFFFFF000000000000000000FFFF + FF00800000008000000080000000800000000000000000808000808080000080 + 8000808080000080800080000000800000008000000080000000800000008000 + 0000800000000000000000000000000000000000000000000000800000008000 + 0000800000000000000000000000000000000000000000000000000000000000 + 0000000000008000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000FFFFFF000000 + 000000000000000000000000000080000000FFFFFF00FFFFFF00FFFFFF00FFFF + FF0080000000FFFFFF0080000000000000000000000080808000008080008080 + 8000008080008080800000808000808080000080800080808000008080008080 + 8000008080000000000000000000000000000000000000000000800000008000 + 0000000000008000000000000000000000000000000000000000000000000000 + 0000000000008000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF0080000000FFFFFF00FFFFFF00FFFFFF00FFFF + FF00800000008000000000000000000000000000000000808000808080000000 + 0000000000000000000000000000000000000000000000000000000000008080 + 8000808080000000000000000000000000000000000000000000800000000000 + 0000000000000000000080000000800000000000000000000000000000000000 + 0000800000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000FFFFFF000000 + 000000000000FFFFFF0000000000800000008000000080000000800000008000 + 0000800000000000000000000000000000000000000080808000808080000000 + 0000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000000000008080 + 8000008080000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000008000000080000000800000008000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF0000000000FFFFFF000000000000000000000000000000 + 0000000000000000000000000000000000000000000000808000808080000080 + 80000000000000FFFF00000000000000000000FFFF0000000000808080000080 + 8000808080000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF0000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000FFFF0000FFFF000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000424D3E000000000000003E000000 + 2800000040000000800000000100010000000000000400000000000000000000 + 000000000000000000000000FFFFFF0000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000000000000FFF7FFFFFC3FFFFFFFFBFFFFE00FF01F + E001FFFFC007E00FE003F3CF8003C007E7F7F39F80018003E7C3F33F00010001 + E7EFF27F00000001E7F7F0FF00000001E7FBF00F00000001E7C3F00F00000001 + E77FF3CF00010001E77FF38F00010001A37FF81F80018003C6BFF83FC003C007 + EDDFFFFFE007E00FFFFFFFFFF01FF01FFFFFFC00FFF7FFF78003FC00FFFBFFFB + 8003FC00E001E0018003FC00E003E0038003E000E7F7E7F78003E000E7DDE707 + 8003E000E7EBE7BF8003E007E7F7E7DF80038007E7EBE70F80038007E75DE7FF + 80038007E77FE5DF8003801FE77FE6BF8003801FA37FA37F8003801FC6BFC6BF + FFFF801FEDDFEDDFFFFFFFFFFFFFFFFFFFF3FFFFFFFFFFFFFFE1FF3FC0078003 + FFC1FE3F80038003FF83C07F00018003F00780F700018003C00F00E700018003 + 801F00C100008003801F00E600008003000F00F680008003000F81FEC0008003 + 000FC3BFE0018003000FFFB7E0078003801FFFB3F0078003801FFFC1F0038003 + C03FFFF3F803FFFFF0FFFFF7FFFFFFFFFFFFFFFFFFFFFFFFC001000C000FF9FF + 80010008000FF9FF80010001000FF3C780010003000F73C780010003000F27FF + 80010003000F07C780010003000F00C780010003000F01E380010007000403F1 + 8001000F000006388001000F00000E388001000FF8001E388001001FFC003F01 + 8001003FFE047F83FFFF007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFEFFDC007001FFFFFC7FFC007000FFFFFC3FBC0070007EFFFE3F7C0070003 + EF83F1E7C0070001DFC3F8CFC0070000DFE3FC1FC007001FDFD3FE3FC007001F + EF3BFC1FC007001FF0FFF8CFC0078FF1FFFFE1E7C00FFFF9FFFFC3F3C01FFF75 + FFFFC7FDC03FFF8FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9FFFFFFFC00FFFF + F6CFFE008000FFFFF6B7FE000000FFFFF6B7FE000000FFFFF8B780000000FFF7 + FE8F80000001C1F7FE3F80000003C3FBFF7F80000003C7FBFE3F80010003CBFB + FEBF80030003DCF7FC9F80070003FF0FFDDF807F0003FFFFFDDF80FF8007FFFF + FDDF81FFF87FFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000 + 000000000000} + end + object Timer1: TTimer + Interval = 300 + OnTimer = Timer1Timer + Left = 440 + Top = 48 + end +end diff --git a/contrib/dbcEditer/dbcedit.h b/contrib/dbcEditer/dbcedit.h new file mode 100644 index 00000000000..a603768ea38 --- /dev/null +++ b/contrib/dbcEditer/dbcedit.h @@ -0,0 +1,105 @@ +//--------------------------------------------------------------------------- + +#ifndef dbceditH +#define dbceditH +//--------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "thOpenSource.h" + +union TypePtr +{ + long* l; + DWORD* dw; + WORD* w; + char* c; + void* p; + float* f; + + TypePtr(void* in) :p(in) + { + } +}; + +#define TAG(x) (DWORD)( (((DWORD)x&0x0000ff00)<<8)+(((DWORD)x&0x000000ff)<<24)+(((DWORD)x&0x00ff0000)>>8)+(((DWORD)x&0xff000000)>>24) ) + + +//--------------------------------------------------------------------------- +class TFrmMain : public TForm +{ +__published: // IDE-managed Components + TPanel *Panel1; + TCoolBar *CoolBar1; + TToolBar *ToolBar1; + TToolButton *btOpen; + TToolButton *btSave; + TStringGrid *sgEdit; + TOpenDialog *OpenDialog1; + TPopupMenu *PopupMenu1; + TMenuItem *N1; + TMenuItem *N2; + TMenuItem *btIntType; + TMenuItem *btFloatType; + TMenuItem *btTxtType; + TImageList *ImageList1; + TPanel *pnFileName; + TToolButton *ToolButton1; + TToolButton *ToolButton2; + TTimer *Timer1; + TLabel *lbOpState; + TMenuItem *N4; + TToolButton *ToolButton3; + TMenuItem *btRowSave; + TMenuItem *btColSave; + TMenuItem *btRowClear; + TMenuItem *btColClear; + TToolButton *ToolButton4; + TToolButton *ToolButton5; + void __fastcall btOpenClick(TObject *Sender); + void __fastcall btSaveClick(TObject *Sender); + void __fastcall btIntTypeClick(TObject *Sender); + void __fastcall btFloatTypeClick(TObject *Sender); + void __fastcall PopupMenu1Popup(TObject *Sender); + void __fastcall N1Click(TObject *Sender); + void __fastcall FormDestroy(TObject *Sender); + void __fastcall ToolButton1Click(TObject *Sender); + void __fastcall sgEditKeyDown(TObject *Sender, WORD &Key, + TShiftState Shift); + void __fastcall sgEditSelectCell(TObject *Sender, int ACol, + int ARow, bool &CanSelect); + void __fastcall Timer1Timer(TObject *Sender); + void __fastcall N4Click(TObject *Sender); + void __fastcall btTxtTypeClick(TObject *Sender); + void __fastcall ToolButton3Click(TObject *Sender); + void __fastcall btRowSaveClick(TObject *Sender); + void __fastcall btColSaveClick(TObject *Sender); + void __fastcall btRowClearClick(TObject *Sender); + void __fastcall btColClearClick(TObject *Sender); + void __fastcall ToolButton4Click(TObject *Sender); +private: // User declarations + + + thOpenFile *thOpen; + bool Term; + +public: // User declarations + bool OpenOk; + + AnsiString CurrentOpenFile; + __fastcall TFrmMain(TComponent* Owner); + void SaveToFile(const char * pszFileName); + void __fastcall OpenFileCol(AnsiString FileName,int ColIndex,int ColType); +}; +//--------------------------------------------------------------------------- +extern PACKAGE TFrmMain *FrmMain; +//--------------------------------------------------------------------------- +#endif diff --git a/contrib/dbcEditer/pjDbcEditer.bpr b/contrib/dbcEditer/pjDbcEditer.bpr new file mode 100644 index 00000000000..43795ce5c28 --- /dev/null +++ b/contrib/dbcEditer/pjDbcEditer.bpr @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=2052 +CodePage=936 + +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= + +[Debugging] +DebugSourceDirs=$(BCB)\source\vcl + +[Parameters] +RunParams= +Launcher= +UseLauncher=0 +DebugCWD= +HostApplication= +RemoteHost= +RemotePath= +RemoteLauncher= +RemoteCWD= +RemoteDebug=0 + +[Compiler] +ShowInfoMsgs=0 +LinkDebugVcl=0 +LinkCGLIB=0 + +[CORBA] +AddServerUnit=1 +AddClientUnit=1 +PrecompiledHeaders=1 + +[Language] +ActiveLang= +ProjectLang= +RootDir= + + \ No newline at end of file diff --git a/contrib/dbcEditer/pjDbcEditer.cpp b/contrib/dbcEditer/pjDbcEditer.cpp new file mode 100644 index 00000000000..db3a8bde81f --- /dev/null +++ b/contrib/dbcEditer/pjDbcEditer.cpp @@ -0,0 +1,37 @@ +//--------------------------------------------------------------------------- + +#include +#pragma hdrstop +//--------------------------------------------------------------------------- +USEFORM("dbcedit.cpp", FrmMain); +USEFORM("TitleFrm.cpp", FrmTitle); +USEFORM("SearchFrm.cpp", FrmSearch); +//--------------------------------------------------------------------------- +WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) +{ + try + { + Application->Initialize(); + Application->CreateForm(__classid(TFrmMain), &FrmMain); + Application->CreateForm(__classid(TFrmTitle), &FrmTitle); + Application->CreateForm(__classid(TFrmSearch), &FrmSearch); + Application->Run(); + } + catch (Exception &exception) + { + Application->ShowException(&exception); + } + catch (...) + { + try + { + throw Exception(""); + } + catch (Exception &exception) + { + Application->ShowException(&exception); + } + } + return 0; +} +//--------------------------------------------------------------------------- diff --git a/contrib/dbcEditer/pjDbcEditer.exe b/contrib/dbcEditer/pjDbcEditer.exe new file mode 100644 index 00000000000..9b11ec74614 Binary files /dev/null and b/contrib/dbcEditer/pjDbcEditer.exe differ diff --git a/contrib/dbcEditer/pjDbcEditer.res b/contrib/dbcEditer/pjDbcEditer.res new file mode 100644 index 00000000000..d1c532760e1 Binary files /dev/null and b/contrib/dbcEditer/pjDbcEditer.res differ diff --git a/contrib/dbcEditer/pjDbcEditer.tds b/contrib/dbcEditer/pjDbcEditer.tds new file mode 100644 index 00000000000..1995524a297 Binary files /dev/null and b/contrib/dbcEditer/pjDbcEditer.tds differ diff --git a/contrib/dbcEditer/thOpenSource.cpp b/contrib/dbcEditer/thOpenSource.cpp new file mode 100644 index 00000000000..7df4debfe31 --- /dev/null +++ b/contrib/dbcEditer/thOpenSource.cpp @@ -0,0 +1,182 @@ +//--------------------------------------------------------------------------- + +#include +#pragma hdrstop + +#include "thOpenSource.h" +#include "dbcedit.h" +#include "stdio.h" +#include +#include +#include +#pragma package(smart_init) +//--------------------------------------------------------------------------- + +// Important: Methods and properties of objects in VCL can only be +// used in a method called using Synchronize, for example: +// +// Synchronize(UpdateCaption); +// +// where UpdateCaption could look like: +// +// void __fastcall thOpenFile::UpdateCaption() +// { +// Form1->Caption = "Updated in a thread"; +// } +//--------------------------------------------------------------------------- + +__fastcall thOpenFile::thOpenFile(bool CreateSuspended) + : TThread(CreateSuspended) +{ + +} +//--------------------------------------------------------------------------- +void __fastcall thOpenFile::Execute() +{ + //---- Place thread code here ---- + //if(!Terminated){ + // FrmMain->LoadAndModify(FrmMain->OpenDialog1->FileName.c_str()); + // FrmMain->OpenOk=true; + //} + thEnd=false; + RunOpen(); + FrmMain->OpenOk=true; + thEnd=true; + +} +//--------------------------------------------------------------------------- +void __fastcall thOpenFile::RunOpen() +{ + LoadAndModify(FrmMain->OpenDialog1->FileName.c_str()); + //OpenOk=true; +} + +void thOpenFile::ReadAndModifyFromBuff(char *pBuff, DWORD dwSize, const char* pszFileName) +{ + char szErrorMsg[MAX_PATH]; + char szNewFileName[MAX_PATH]; + DWORD w; + TIniFile *ini; + + + TypePtr p(pBuff); + if('WDBC' != TAG(*p.dw)) + { + _snprintf(szErrorMsg, 512, "[%s]Not Wow's dbc file!", pszFileName); + ShowMessage(szErrorMsg); + return; + } + p.dw++; + + DWORD dwRows, dwCols, dwRowLen, dwTextLen; + dwRows = *p.dw++; + dwCols = *p.dw++; + dwRowLen = *p.dw++; + dwTextLen = *p.dw++; + + FrmMain->sgEdit->RowCount = dwRows+1; + FrmMain->sgEdit->ColCount = dwCols+1; + + for(int i=0; isgEdit->RowCount; i++){ + FrmMain->sgEdit->Cells[0][i]=IntToStr(i); + if(Terminated) return; + } + //É趨ÁбêÌâ + AnsiString iniSetFile=ExtractFilePath(Application->ExeName)+"BcdEditer.ini"; + AnsiString SectionName=ExtractFileName(FrmMain->CurrentOpenFile); + + ini = new TIniFile( iniSetFile ); + for(int j=0; jsgEdit->ColCount; j++){ + FrmMain->sgEdit->Cells[j][0]= ini->ReadString(SectionName,"ColTitle"+IntToStr(j),IntToStr(j)); + //sgEdit->Cells[j][0]=IntToStr(j); + ColType[j]=ini->ReadInteger(SectionName,"ColType"+IntToStr(j),0); + if(Terminated) return; + } + delete ini; + + //int *ColType = new int[dwCols]; + + DWORD dwTextStartPos = dwRows*dwRowLen+20; + char* pTextPtr = pBuff + dwTextStartPos; + char pszTemp[MAX_PATH]; + float fTemp; + long lTemp; + DWORD i, j; + BOOL* pbString = new BOOL[dwRows*dwCols]; + float newTmp; + //int ColType; + + ini = new TIniFile( iniSetFile ); + + for(i=0; isgEdit->Cells[j+1][i+1]=IntToStr(lTemp); + else{ + + //ColType= ini->ReadInteger(SectionName,"ColType"+IntToStr(j),0); + + switch (ColType[j+1]) + { + case 0: //ÕûÐÍ + FrmMain->sgEdit->Cells[j+1][i+1]=IntToStr(lTemp); + break; + case 1: //¸¡µã + FrmMain->sgEdit->Cells[j+1][i+1]=FloatToStr(fTemp); + break; + case 2: //Îı¾ Îı¾ÀàÐÍÖ»ÄÜ¿´£¬²»Äܱ༭ + if(dwTextStartPos + lTemp < dwSize){ + pTextPtr = pBuff + dwTextStartPos + lTemp; + FrmMain->sgEdit->Cells[j+1][i+1]=pTextPtr; + }else{ + FrmMain->sgEdit->Cells[j+1][i+1]="¸ÃÁв»ÊÇÎı¾"; + } + break; + default: //ÕûÐÍ + FrmMain->sgEdit->Cells[j+1][i+1]=IntToStr(lTemp); + } + } + p.c += 4; + } + } + + delete [] pbString; + //delete [] ColType; + delete ini; + +} + +void thOpenFile::LoadAndModify(const char * pszFileName) +{ + HANDLE hFile = NULL; + hFile = CreateFile(pszFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); + if(hFile == INVALID_HANDLE_VALUE)return; + + DWORD r = 0, nFileSize = 0; + nFileSize = GetFileSize(hFile, NULL); + char* pTmpBuf = new char[nFileSize]; + if(pTmpBuf==NULL) + { + CloseHandle(hFile); + return; + } + ReadFile(hFile, pTmpBuf, nFileSize, &r, NULL); + + FrmMain->CurrentOpenFile=pszFileName; + FrmMain->btSave->Enabled=true; + + ReadAndModifyFromBuff(pTmpBuf, nFileSize, pszFileName); + + //SAFE_DELETE_ARRAY(pTmpBuf); + delete [] pTmpBuf; + CloseHandle(hFile); + +} diff --git a/contrib/dbcEditer/thOpenSource.h b/contrib/dbcEditer/thOpenSource.h new file mode 100644 index 00000000000..edf6bd064f2 --- /dev/null +++ b/contrib/dbcEditer/thOpenSource.h @@ -0,0 +1,24 @@ +//--------------------------------------------------------------------------- + +#ifndef thOpenSourceH +#define thOpenSourceH +//--------------------------------------------------------------------------- +#include +//--------------------------------------------------------------------------- +class thOpenFile : public TThread +{ +private: +protected: + void __fastcall Execute(); + void __fastcall RunOpen(); +public: + bool thEnd; + int ColType[10000]; + + __fastcall thOpenFile(bool CreateSuspended); + void LoadAndModify(const char * pszFileName); + void ReadAndModifyFromBuff(char *pBuff, DWORD dwSize, const char* pszFileName); + +}; +//--------------------------------------------------------------------------- +#endif diff --git a/contrib/dbcformat/DBC Store.exe b/contrib/dbcformat/DBC Store.exe new file mode 100644 index 00000000000..f0e0014956a Binary files /dev/null and b/contrib/dbcformat/DBC Store.exe differ diff --git a/contrib/dbcformat/dbc.desc b/contrib/dbcformat/dbc.desc new file mode 100644 index 00000000000..470108cab5f --- /dev/null +++ b/contrib/dbcformat/dbc.desc @@ -0,0 +1,241 @@ +ENTRY ItemSetEntry + +UNUSED INDEX setid +UNUSED STR setname +UNKNOWN[7] +UNUSED UINT flags//, const +UNUSED UINT required_item_id[8] +UNKNOWN[48] +UINT spells[8] +UINT items_to_triggerspell[8] //items_to_triggerspell[0] -- for spells[0] +UINT required_skill_id//only 2 items sets have requirements +UINT required_skill_value + +ENDENTRY + + +ENTRY TalentEntry + + INDEX TalentID + UINT TalentTree + UNKNOWN [2] + UINT RankID[5] + UNKNOWN[12] + +ENDENTRY + + +ENTRY emoteentry + + INDEX Id + UNUSED STR name + UINT textid + UNUSED UINT textid2 + UNUSED UINT textid3 + UNUSED UINT textid4 + UNKNOWN + UNUSED UINT textid5 + UNKNOWN + UNUSED UINT textid6 + UNKNOWN[9] + +ENDENTRY + +ENTRY SpellEntry + + INDEX Id + UINT School + UNKNOWN [2] + UINT Category + UNKNOWN + UINT Attributes + UINT AttributesEx + UNKNOWN [3] + UINT Targets + UINT TargetCreatureType + UINT RequiresSpellFocus + UNKNOWN + UINT CasterAuraState + UINT CastingTimeIndex + UINT RecoveryTime + UINT CategoryRecoveryTime + UINT InterruptFlags + UINT AuraInterruptFlags + UINT ChannelInterruptFlags + UINT procFlags + UINT procChance + UINT procCharges + UINT maxLevel + UINT baseLevel + UINT spellLevel + UINT DurationIndex + UINT powerType + UINT manaCost + UINT manaCostPerlevel + UINT manaPerSecond + UINT manaPerSecondPerLevel + UINT rangeIndex + FLOAT speed + UINT modalNextSpell + UNKNOWN + UINT Totem[2] + UINT Reagent[8] + UINT ReagentCount[8] + UINT EquippedItemClass + UINT EquippedItemSubClass + UINT Effect[3] // 59 - 61 + UINT EffectDieSides[3] + UINT EffectBaseDice[3] + FLOAT EffectDicePerLevel[3] + FLOAT EffectRealPointsPerLevel[3] + INT EffectBasePoints[3] // 74 - 76 + UNKNOWN [3] + UINT EffectImplicitTargetA[3] // 80 - 82 + UINT EffectImplicitTargetB[3] // 83 - 85 + UINT EffectRadiusIndex[3] + UINT EffectApplyAuraName[3] // 89 - 91 + UINT EffectAmplitude[3] + UINT Effectunknown[3] + UINT EffectChainTarget[3] + UINT EffectItemType[3] + UINT EffectMiscValue[3] // 104 - 106 + UINT EffectTriggerSpell[3] + FLOAT EffectPointsPerComboPoint[3] + UINT SpellVisual + UNKNOWN + UINT SpellIconID + UINT activeIconID + UINT spellPriority + UNUSED STR Name + UNUSED STR NameAlt1 + UNUSED STR NameAlt2 + UNUSED STR NameAlt3 + UNUSED STR NameAlt4 + UNUSED STR NameAlt5 + UNUSED STR NameAlt6 + UNUSED STR NameAlt7 + UNUSED STR NameFlags + UINT Rank + UINT RankAlt1 + UINT RankAlt2 + UINT RankAlt3 + UINT RankAlt4 + UINT RankAlt5 + UINT RankAlt6 + UINT RankAlt7 + UINT RankFlags + UNUSED STR Description + UNUSED STR DescriptionAlt1 + UNUSED STR DescriptionAlt2 + UNUSED STR DescriptionAlt3 + UNUSED STR DescriptionAlt4 + UNUSED STR DescriptionAlt5 + UNUSED STR DescriptionAlt6 + UNUSED STR DescriptionAlt7 + UNUSED UINT DescriptionFlags + UNUSED STR BuffDescription + UNUSED STR BuffDescriptionAlt1 + UNUSED STR BuffDescriptionAlt2 + UNUSED STR BuffDescriptionAlt3 + UNUSED STR BuffDescriptionAlt4 + UNUSED STR BuffDescriptionAlt5 + UNUSED STR BuffDescriptionAlt6 + UNUSED STR BuffDescriptionAlt7 + UINT ManaCostPercentage + UINT StartRecoveryCategory + UINT StartRecoveryTime + UINT field156 //nice name + UNKNOWN[2] + UINT SpellFamilyName + UNKNOWN[11] +ENDENTRY + +ENTRY SpellCastTime + INDEX ID + UINT CastTime + UNKNOWN[2] +ENDENTRY + +ENTRY SpellRadius + INDEX ID + FLOAT Radius + UNKNOWN + FLOAT Radius2 +ENDENTRY + +ENTRY SpellRange + INDEX ID + FLOAT minRange + FLOAT maxRange + UNKNOWN[18] + UNKNOWN//some flag +ENDENTRY + +ENTRY SpellDuration + INDEX ID + UINT Duration1 + UINT Duration2 + UINT Duration3 +ENDENTRY + +ENTRY AreaTableEntry + + UINT ID + UNUSED UINT map + UINT zone + INDEX exploreFlag + UNKNOWN[6] + UINT area_level + UNUSED STR name + UNKNOWN[9] + +ENDENTRY + + +ENTRY FactionEntry + INDEX ID + INT reputationListID + + UNKNOWN[7] + UINT something1 + UINT something2 + UINT something3 + UINT something4 + UINT something5 + UINT something6 + UINT something7 + UINT something8 + UINT something9 + UINT faction + + UNUSED STR name + UNKNOWN[17] + +ENDENTRY + + +ENTRY FactionTemplateEntry + INDEX ID + UINT faction + UNKNOWN + UINT fightsupport + UINT friendly + UINT hostile + UNKNOWN[8] +ENDENTRY + + +ENTRY ItemDisplayTemplateEntry + + UINT ID + UNUSED STR modelFile + UNKNOWN + UNUSED STR imageFile + UNKNOWN + UNUSED STR invImageFile + UNKNOWN[5] + UINT seed + UNKNOWN [10] + UINT randomPropertyID + +ENDENTRY diff --git a/contrib/extractor/Makefile b/contrib/extractor/Makefile new file mode 100644 index 00000000000..64153634c88 --- /dev/null +++ b/contrib/extractor/Makefile @@ -0,0 +1,470 @@ +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + + +# Copyright (C) 2005,2006 MaNGOS +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +SOURCES = $(ad_SOURCES) + +srcdir = . +top_srcdir = . + +pkgdatadir = $(datadir)/mangos +pkglibdir = $(libdir)/mangos +pkgincludedir = $(includedir)/mangos +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = /usr/bin/ginstall -c +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = i686-pc-linux-gnu +host_triplet = i686-pc-linux-gnu +bin_PROGRAMS = ad$(EXEEXT) +subdir = contrib/extractor +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +PROGRAMS = $(bin_PROGRAMS) +am_ad_OBJECTS = System.$(OBJEXT) adt.$(OBJEXT) dbcfile.$(OBJEXT) \ + mpq_libmpq.$(OBJEXT) +ad_OBJECTS = $(am_ad_OBJECTS) +ad_DEPENDENCIES = +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(ad_SOURCES) +DIST_SOURCES = $(ad_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = +ALLOCA = +AMDEP_FALSE = # +AMDEP_TRUE = +AMTAR = ${SHELL} /home/wow/MaNGOS/trunk/missing --run tar +AR = ar +AUTOCONF = ${SHELL} /home/wow/MaNGOS/trunk/missing --run autoconf +AUTOHEADER = ${SHELL} /home/wow/MaNGOS/trunk/missing --run autoheader +AUTOMAKE = ${SHELL} /home/wow/MaNGOS/trunk/missing --run automake-1.9 +AWK = gawk +CC = gcc +CCDEPMODE = depmode=gcc3 +CFLAGS = -g -O3 +COMPILER_OPTIONS = -g -O3 +CPP = gcc -E +CPPFLAGS = +CXX = g++ +CXXCPP = g++ -E +CXXDEPMODE = depmode=gcc3 +CXXFLAGS = -g -O3 +CYGPATH_W = echo +DEFS = -DHAVE_CONFIG_H +DEPDIR = .deps +ECHO = echo +ECHO_C = +ECHO_N = -n +ECHO_T = +EGREP = grep -E +EXEEXT = +EXTRA_COMPILER_OPTIONS = +EXTRA_LINKER_OPTIONS = +F77 = +FFLAGS = +INCLUDES = -I$(srcdir) +INSTALL_DATA = ${INSTALL} -m 644 +INSTALL_PROGRAM = ${INSTALL} +INSTALL_SCRIPT = ${INSTALL} +INSTALL_STRIP_PROGRAM = ${SHELL} $(install_sh) -c -s +LDFLAGS = +LIBOBJS = +LIBS = -lz -lpthread +LIBTOOL = $(SHELL) $(top_builddir)/libtool +LINKER_OPTIONS = -static +LN_S = ln -s +LTLIBOBJS = +LT_AGE = 2 +LT_CURRENT = 2 +LT_RELEASE = 2.3.2 +LT_REVISION = 3 +MAINT = # +MAINTAINER_MODE_FALSE = +MAINTAINER_MODE_TRUE = # +MAKEINFO = +MANGOSD_CONFIG = /home/wow/server/etc/mangosd.conf +MANGOSD_CONFIGDIR = /home/wow/server/etc +MANGOSD_DATA = /home/wow/server/share/mangos +OBJEXT = o +PACKAGE = mangos +PACKAGE_BUGREPORT = http://www.mangosproject.org/ +PACKAGE_NAME = MaNGOS +PACKAGE_STRING = MaNGOS 0.2-SVN +PACKAGE_TARNAME = mangos +PACKAGE_VERSION = 0.2-SVN +PATH_SEPARATOR = : +RANLIB = ranlib +SET_MAKE = +SHELL = /bin/sh +STRIP = strip +VERSION = 0.2-SVN +ac_ct_AR = ar +ac_ct_CC = gcc +ac_ct_CXX = g++ +ac_ct_F77 = +ac_ct_RANLIB = ranlib +ac_ct_STRIP = strip +am__fastdepCC_FALSE = # +am__fastdepCC_TRUE = +am__fastdepCXX_FALSE = # +am__fastdepCXX_TRUE = +am__include = include +am__leading_dot = . +am__quote = +am__tar = ${AMTAR} chof - "$$tardir" +am__untar = ${AMTAR} xf - +bindir = ${exec_prefix}/bin +build = i686-pc-linux-gnu +build_alias = +build_cpu = i686 +build_os = linux-gnu +build_vendor = pc +datadir = ${prefix}/share +exec_prefix = ${prefix} +host = i686-pc-linux-gnu +host_alias = +host_cpu = i686 +host_os = linux-gnu +host_vendor = pc +includedir = ${prefix}/include +infodir = ${prefix}/info +install_sh = /home/wow/MaNGOS/trunk/install-sh +libdir = ${exec_prefix}/lib +libexecdir = ${exec_prefix}/libexec +localstatedir = ${prefix}/var +mandir = ${prefix}/man +mkdir_p = mkdir -p -- +oldincludedir = /usr/include +prefix = /home/wow/server +program_transform_name = s,x,x, +sbindir = ${exec_prefix}/sbin +sharedstatedir = ${prefix}/com + +# use our configured sysconfdir +sysconfdir = /home/wow/server/etc +target_alias = +ad_SOURCES = \ + System.cpp \ + adt.h \ + adt.cpp \ + dbcfile.cpp \ + dbcfile.h \ + mpq_libmpq.cpp \ + mpq_libmpq.h + +ad_LDADD = libmpq/libmpq.a +add_LDFLAGS = -L$(srcdir) -L$(srcdir)/libmpq + +all: create-dir all-am + +.SUFFIXES: +.SUFFIXES: .cpp .lo .o .obj + +.PRECIOUS: Makefile + +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)" + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + || test -f $$p1 \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ + rm -f "$(DESTDIR)$(bindir)/$$f"; \ + done + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f $$p $$f"; \ + rm -f $$p $$f ; \ + done +ad$(EXEEXT): $(ad_OBJECTS) $(ad_DEPENDENCIES) + @rm -f ad$(EXEEXT) + $(CXXLINK) $(ad_LDFLAGS) $(ad_OBJECTS) $(ad_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.cpp.o: + if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ + then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +# source='$<' object='$@' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: + if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ + then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +# source='$<' object='$@' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.lo: + if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ + then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +# source='$<' object='$@' libtool=yes \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + -rm .deps/* + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS); +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: install-binPROGRAMS + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-info-am + +create-dir: + mkdir -p ".deps" + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic clean-libtool ctags distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-binPROGRAMS install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am \ + uninstall-binPROGRAMS uninstall-info-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/contrib/extractor/Makefile.am b/contrib/extractor/Makefile.am new file mode 100644 index 00000000000..b84617069a1 --- /dev/null +++ b/contrib/extractor/Makefile.am @@ -0,0 +1,10 @@ +# The top-level input Makefile for mpq-tools + +# Any directories which should be built and installed. +SUBDIRS = libmpq + +# The directories which are part of the distribution. +DIST_SUBDIRS = $(SUBDIRS) + +EXTRA_DIST = \ + README.linux diff --git a/contrib/extractor/README.linux b/contrib/extractor/README.linux new file mode 100644 index 00000000000..e1ebdb8bb2e --- /dev/null +++ b/contrib/extractor/README.linux @@ -0,0 +1,13 @@ +Linux instructions +------------------ + +1. Configure and build MaNGOS. +2. cd contrib/map_extractor/libmpq/ +3. make +4. cd .. +5. make +6. run ad + +if there are any problems create folder named .deps in contrib/map_extractor/ +it is old bug from first extractor and i am too lasy to fix it :) + diff --git a/contrib/extractor/System.cpp b/contrib/extractor/System.cpp new file mode 100644 index 00000000000..090fc557ed7 --- /dev/null +++ b/contrib/extractor/System.cpp @@ -0,0 +1,320 @@ +#define _CRT_SECURE_NO_DEPRECATE + +#include +#include +#include + +#ifdef WIN32 +#include "direct.h" +#else +#include +#endif + +#include "dbcfile.h" +#include "mpq_libmpq.h" + +extern unsigned int iRes; +extern ArchiveSet gOpenArchives; + +bool ConvertADT(char*,char*); + +typedef struct{ + char name[64]; + unsigned int id; +}map_id; + +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned int uint32; + +map_id * map_ids; +uint16 * areas; +char output_path[128]="."; +char input_path[128]="."; + +enum Extract +{ + EXTRACT_MAP = 1, + EXTRACT_DBC = 2 +}; +int extract = EXTRACT_MAP | EXTRACT_DBC; + +static char* const langs[]={"deDE", "enGB", "enUS", "esES", "frFR", "koKR", "zhCN", "zhTW", "enCN", "enTW", "esMX", "ruRU" }; +#define LANG_COUNT 12 + +#define ADT_RES 64 + +void CreateDir( const std::string& Path ) +{ + #ifdef WIN32 + _mkdir( Path.c_str()); + #else + mkdir( Path.c_str(), 0777 ); + #endif +} + +bool FileExists( const char* FileName ) +{ + if( FILE* fp = fopen( FileName, "rb" ) ) + { + fclose( fp ); + return true; + } + + return false; +} + +void Usage(char* prg) +{ + printf("Usage:\n%s -[var] [value]\n-i set input path\n-o set output path\n-r set resolution\n-e extract only MAP(1)/DBC(2) - standard: both(3)\nExample: %s -r 256 -i \"c:\\games\\game\"", + prg,prg); + exit(1); +} + +void HandleArgs(int argc, char * arg[]) +{ + for(int c=1;c 0 && extract < 4)) + Usage(arg[0]); + } + else + Usage(arg[0]); + break; + } + } +} + +uint32 ReadMapDBC() +{ + printf("Read Map.dbc file... "); + DBCFile dbc("DBFilesClient\\Map.dbc"); + dbc.open(); + + uint32 map_count=dbc.getRecordCount(); + map_ids=new map_id[map_count]; + for(unsigned int x=0;x dbcfiles; + + // get DBC file list + for(ArchiveSet::iterator i = gOpenArchives.begin(); i != gOpenArchives.end();++i) + { + vector files = (*i)->GetFileList(); + for (vector::iterator iter = files.begin(); iter != files.end(); ++iter) + if (iter->rfind(".dbc") == iter->length() - strlen(".dbc")) + dbcfiles.insert(*iter); + } + + std::string path = output_path; + path += "/dbc/"; + CreateDir(path); + + // extract DBCs + int count = 0; + for (set::iterator iter = dbcfiles.begin(); iter != dbcfiles.end(); ++iter) + { + string filename = output_path; + filename += "/dbc/"; + filename += (iter->c_str() + strlen("DBFilesClient\\")); + + //cout << filename << endl; + + FILE *output=fopen(filename.c_str(),"wb"); + if(!output) + { + printf("Can't create the output file '%s'\n",filename.c_str()); + continue; + } + MPQFile m(iter->c_str()); + if(!m.isEof()) + fwrite(m.getPointer(),1,m.getSize(),output); + + fclose(output); + ++count; + } + printf("Extracted %u DBC files\n", count); +} + +int GetLocale() +{ + for (int i = 0; i < LANG_COUNT; i++) + { + char tmp1[512]; + sprintf(tmp1, "%s/Data/%s/locale-%s.MPQ", input_path, langs[i], langs[i]); + if (FileExists(tmp1)) + { + printf("Detected locale: %s\n", langs[i]); + return i; + } + } + + printf("Could not detect locale.\n"); + return -1; +} + +void LoadMPQFiles(int const locale) +{ + char filename[512]; + + sprintf(filename,"%s/Data/%s/locale-%s.MPQ",input_path,langs[locale],langs[locale]); + new MPQArchive(filename); + + for(int i = 1; i < 5; ++i) + { + char ext[3] = ""; + if(i > 1) + sprintf(ext, "-%i", i); + + sprintf(filename,"%s/Data/%s/patch-%s%s.MPQ",input_path,langs[locale],langs[locale],ext); + if(!FileExists(filename)) + break; + new MPQArchive(filename); + } + + //need those files only if extract maps + if(extract & EXTRACT_MAP) + { + sprintf(filename,"%s/Data/common.MPQ",input_path); + new MPQArchive(filename); + sprintf(filename,"%s/Data/expansion.MPQ",input_path); + new MPQArchive(filename); + + for(int i = 1; i < 5; ++i) + { + char ext[3] = ""; + if(i > 1) + sprintf(ext, "-%i", i); + + sprintf(filename,"%s/Data/patch%s.MPQ",input_path,ext); + if(!FileExists(filename)) + break; + new MPQArchive(filename); + } + } +} + +int main(int argc, char * arg[]) +{ + printf("Map & DBC Extractor\n"); + printf("===================\n"); + + HandleArgs(argc, arg); + + int const locale = GetLocale(); + if(locale < 0) + return 1; + + LoadMPQFiles(locale); + + if(extract & EXTRACT_DBC) + ExtractDBCFiles(); + + if(extract & EXTRACT_MAP) + ExtractMapsFromMpq(); + + //Close MPQs + for(ArchiveSet::iterator i = gOpenArchives.begin(); i != gOpenArchives.end();++i) + (*i)->close(); + gOpenArchives.clear(); + + return 0; +} diff --git a/contrib/extractor/VC71_AD.sln b/contrib/extractor/VC71_AD.sln new file mode 100644 index 00000000000..f914661b1a1 --- /dev/null +++ b/contrib/extractor/VC71_AD.sln @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ad", "VC71_ad.vcproj", "{D7552D4F-408F-4F8E-859B-366659150CF4}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D7552D4F-408F-4F8E-859B-366659150CF4}.Debug|Win32.ActiveCfg = Debug|Win32 + {D7552D4F-408F-4F8E-859B-366659150CF4}.Debug|Win32.Build.0 = Debug|Win32 + {D7552D4F-408F-4F8E-859B-366659150CF4}.Release|Win32.ActiveCfg = Release|Win32 + {D7552D4F-408F-4F8E-859B-366659150CF4}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/contrib/extractor/VC71_ad.vcproj b/contrib/extractor/VC71_ad.vcproj new file mode 100644 index 00000000000..b1154138251 --- /dev/null +++ b/contrib/extractor/VC71_ad.vcproj @@ -0,0 +1,316 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/contrib/extractor/VC80_AD.sln b/contrib/extractor/VC80_AD.sln new file mode 100644 index 00000000000..1c46986e858 --- /dev/null +++ b/contrib/extractor/VC80_AD.sln @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ad", "VC80_ad.vcproj", "{D7552D4F-408F-4F8E-859B-366659150CF4}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D7552D4F-408F-4F8E-859B-366659150CF4}.Debug|Win32.ActiveCfg = Debug|Win32 + {D7552D4F-408F-4F8E-859B-366659150CF4}.Debug|Win32.Build.0 = Debug|Win32 + {D7552D4F-408F-4F8E-859B-366659150CF4}.Release|Win32.ActiveCfg = Release|Win32 + {D7552D4F-408F-4F8E-859B-366659150CF4}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/contrib/extractor/VC80_ad.vcproj b/contrib/extractor/VC80_ad.vcproj new file mode 100644 index 00000000000..ddf423c4bde --- /dev/null +++ b/contrib/extractor/VC80_ad.vcproj @@ -0,0 +1,339 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/contrib/extractor/VC90_AD.sln b/contrib/extractor/VC90_AD.sln new file mode 100644 index 00000000000..68dd66e1f7f --- /dev/null +++ b/contrib/extractor/VC90_AD.sln @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ad", "VC90_ad.vcproj", "{D7552D4F-408F-4F8E-859B-366659150CF4}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D7552D4F-408F-4F8E-859B-366659150CF4}.Debug|Win32.ActiveCfg = Debug|Win32 + {D7552D4F-408F-4F8E-859B-366659150CF4}.Debug|Win32.Build.0 = Debug|Win32 + {D7552D4F-408F-4F8E-859B-366659150CF4}.Release|Win32.ActiveCfg = Release|Win32 + {D7552D4F-408F-4F8E-859B-366659150CF4}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/contrib/extractor/VC90_ad.vcproj b/contrib/extractor/VC90_ad.vcproj new file mode 100644 index 00000000000..148c33643c3 --- /dev/null +++ b/contrib/extractor/VC90_ad.vcproj @@ -0,0 +1,315 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/contrib/extractor/ad b/contrib/extractor/ad new file mode 100644 index 00000000000..564eceaaa5f Binary files /dev/null and b/contrib/extractor/ad differ diff --git a/contrib/extractor/ad.exe b/contrib/extractor/ad.exe new file mode 100644 index 00000000000..e9606e8e0eb Binary files /dev/null and b/contrib/extractor/ad.exe differ diff --git a/contrib/extractor/adt.cpp b/contrib/extractor/adt.cpp new file mode 100644 index 00000000000..26adaa28537 --- /dev/null +++ b/contrib/extractor/adt.cpp @@ -0,0 +1,501 @@ +#define _CRT_SECURE_NO_DEPRECATE + +#ifdef WIN32 +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "adt.h" +#include "mpq_libmpq.h" + +//#include +unsigned int iRes=256; +extern uint16*areas; + +vec wmoc; + +Cell * cell; +uint32 wmo_count; +mcell *mcells; + +int holetab_h[4] = {0x1111, 0x2222, 0x4444, 0x8888}; +int holetab_v[4] = {0x000F, 0x00F0, 0x0F00, 0xF000}; + +bool LoadADT(char* filename) +{ + size_t size; + MPQFile mf(filename); + + if(mf.isEof()) + { + //printf("No such file.\n"); + return false; + } + mcells=new mcell; + + wmoc.x =65*TILESIZE; + wmoc.z =65*TILESIZE; + + size_t mcnk_offsets[256], mcnk_sizes[256]; + + wmo_count=0; + bool found=false; + //uint32 fs=mf.getSize()-3; + //while (mf.getPos()ch[i][j])); + } + + /* + for(uint32 t=0;t3) testi = 3; + if(testj>3) testj = 3; + return (holes & holetab_h[testi] & holetab_v[testj])!=0; +} + +inline +void LoadMapChunk(MPQFile & mf, chunk*_chunk) +{ + float h; + uint32 fourcc; + uint32 size; + MapChunkHeader header; + + mf.seekRelative(4); + mf.read(&size, 4); + + size_t lastpos = mf.getPos() + size; + mf.read(&header, 0x80); + _chunk->area_id =header.areaid ; + _chunk->flag =0; + + float xbase = header.xpos; + float ybase = header.ypos; + float zbase = header.zpos; + zbase = TILESIZE*32-zbase; + xbase = TILESIZE*32-xbase; + if(wmoc.x >xbase)wmoc.x =xbase; + if(wmoc.z >zbase)wmoc.z =zbase; + int chunkflags = header.flags; + float zmin=999999999.0f; + float zmax=-999999999.0f; + //must be there, bl!zz uses some crazy format + int nTextures; + while (mf.getPos() < lastpos) + { + mf.read(&fourcc,4); + mf.read(&size, 4); + //if(size!=580) + // printf("\n sz=%d",size); + size_t nextpos = mf.getPos() + size; + if(fourcc==0x4d435654) // MCVT + { + for (int j=0; j<17; j++) + for (int i=0; i<((j%2)?8:9); i++) + { + mf.read(&h,4); + float z=h+ybase; + if (j%2) + { + if(isHole(header.holes,i,j)) + _chunk->v8[i][j/2] = -1000; + else + _chunk->v8[i][j/2] = z; + } + else + { + if(isHole(header.holes,i,j)) + _chunk->v9[i][j/2] = -1000; + else + _chunk->v9[i][j/2] = z; + } + + if(z>zmax)zmax=z; + //if(zwaterlevel[i][j]=-999999; // no liquid/water + } + else + { + float maxheight; + mf.read(&maxheight, 4); + + for(int j=0;j<9;j++) + for(int i=0;i<9;i++) + { + mf.read(&h, 4); + mf.read(&h, 4); + if(h > maxheight) + _chunk->waterlevel[i][j]=-999999; + else + _chunk->waterlevel[i][j]=h; + } + + if(chunkflags & 4 || chunkflags & 8) + _chunk->flag |=1; + if(chunkflags & 16) + _chunk->flag |=2; + + } + break; + } + else if (fourcc==0x4d434c59) // MCLY + { + // texture info + nTextures = (int)size; + } + else if (fourcc==0x4d43414c) // MCAL + { + if (nTextures<=0) + continue; + } + + mf.seek(nextpos); + } +} + +double solve (vec *v,vec *p) +{ + double a = v[0].y *(v[1].z - v[2].z) + v[1].y *(v[2].z - v[0].z) + v[2].y *(v[0].z - v[1].z); + double b = v[0].z *(v[1].x - v[2].x) + v[1].z *(v[2].x - v[0].x) + v[2].z *(v[0].x - v[1].x); + double c = v[0].x *(v[1].y - v[2].y) + v[1].x *(v[2].y - v[0].y) + v[2].x *(v[0].y - v[1].y); + double d = v[0].x *(v[1].y*v[2].z - v[2].y*v[1].z) + v[1].x* (v[2].y*v[0].z - v[0].y*v[2].z) + v[2].x* (v[0].y*v[1].z - v[1].y*v[0].z); + //-d + + //plane equation ax+by+cz+d=0 + return ((a*p->x+c*p->z-d)/b); +} + +inline +double GetZ(double x,double z) +{ + vec v[3]; + vec p; + + //bool inWMO=false; + + //if(!inWMO) + { + //find out quadrant + int xc=(int)(x/UNITSIZE); + int zc=(int)(z/UNITSIZE); + if(xc>127)xc=127; + if(zc>127)zc=127; + + double lx=x-xc*UNITSIZE; + double lz=z-zc*UNITSIZE; + p.x=lx; + p.z=lz; + + v[0].x=UNITSIZE/2; + v[0].y =cell->v8[xc][zc]; + v[0].z=UNITSIZE/2; + + if(lx>lz) + { + v[1].x=UNITSIZE; + v[1].y =cell->v9[xc+1][zc]; + v[1].z=0; + } + else + { + v[1].x=0.0; + v[1].y =cell->v9[xc][zc+1]; + v[1].z=UNITSIZE; + } + + if(lz>UNITSIZE-lx) + { + v[2].x=UNITSIZE; + v[2].y =cell->v9[xc+1][zc+1]; + v[2].z=UNITSIZE; + } + else + { + v[2].x=0; + v[2].y=cell->v9[xc][zc]; + v[2].z=0; + } + + return -solve(v,&p); + } +} + +inline +void TransformWaterData() +{ + cell= new Cell; + + for(int x=0;x<128;x++) + for(int y=0;y<128;y++) + cell->v9[x][y] = mcells->ch[x/8][y/8].waterlevel[x%8][y%8]; + + //and the last 1 + cell->v9[128][128] = mcells->ch[15][15].waterlevel[8][8]; +} + +inline +void TransformData() +{ + cell= new Cell; + + for(int x=0;x<128;x++) + { + for(int y=0;y<128;y++) + { + cell->v8[x][y] = (float)mcells->ch[x/8][y/8].v8[x%8][y%8]; + cell->v9[x][y] = (float)mcells->ch[x/8][y/8].v9[x%8][y%8]; + } + + //extra 1 point on bounds + cell->v9[x][128] = (float)mcells->ch[x/8][15].v9[x%8][8]; + //x==y + cell->v9[128][x] = (float)mcells->ch[15][x/8].v9[8][x%8]; + + } + + //and the last 1 + cell->v9[128][128] = (float)mcells->ch[15][15].v9[8][8]; + + delete mcells; +} + +const char MAP_MAGIC[] = "MAP_2.00"; + +bool ConvertADT(char * filename,char * filename2) +{ + //if(!strstr(filename,"oth_32_48"))return false; + if(!LoadADT(filename)) + return false; + + FILE *output=fopen(filename2,"wb"); + if(!output) + { + printf("Can't create the output file '%s'\n",filename2); + return false; + } + + // write magic header + fwrite(MAP_MAGIC,1,8,output); + + for(unsigned int x=0;x<16;x++) + { + for(unsigned int y=0;y<16;y++) + { + if(mcells->ch[y][x].area_id && mcells->ch[y][x].area_id < 0x102D) + { + if(areas[mcells->ch[y][x].area_id]==0xffff) + printf("\nCan't find area flag for areaid %u.\n",mcells->ch[y][x].area_id); + + fwrite(&areas[mcells->ch[y][x].area_id],1,2,output); + } + else + { + uint16 flag=0xffff; + fwrite(&flag,1,2,output); + } + } + } + + for(unsigned int x=0;x<16;x++) + for(unsigned int y=0;y<16;y++) + fwrite(&mcells->ch[y][x].flag,1,1,output); + + TransformWaterData(); + + for(unsigned int x=0;x<128;x++) + for(unsigned int y=0;y<128;y++) + fwrite(&cell->v9[y][x],1,sizeof(float),output); + + delete cell; + TransformData(); + + for(unsigned int x=0;x::iterator it = wmos.begin(); it != wmos.end(); ++it) + wmomanager.delbyname(*it); + + wmos.clear(); + wmois.clear(); + + for (std::vector::iterator it = wmomodel.begin(); it != wmomodel.end(); ++it) + { + it->tr.clear(); + + } + //printf("\n %d \n",in); + wmomodel.clear(); + //polygons.clear();*/ + return true; +} diff --git a/contrib/extractor/adt.h b/contrib/extractor/adt.h new file mode 100644 index 00000000000..6e079461a66 --- /dev/null +++ b/contrib/extractor/adt.h @@ -0,0 +1,54 @@ +#ifndef ADT_H +#define ADT_H + +#define TILESIZE (533.33333f) +#define CHUNKSIZE ((TILESIZE) / 16.0f) +#define UNITSIZE (CHUNKSIZE / 8.0f) + +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned int uint32; +class Liquid; +typedef struct { +float x; +float y; +float z; +}svec; + +typedef struct { +double x; +double y; +double z; +}vec; + +typedef struct{ + vec v[3]; +}triangle; + +typedef struct{ +float v9[16*8+1][16*8+1]; +float v8[16*8][16*8]; +}Cell; + +typedef struct{ +double v9[9][9]; +double v8[8][8]; +uint16 area_id; +//Liquid *lq; +float waterlevel[9][9]; +uint8 flag; +}chunk; + +class WMO; +class WMOManager; +void fixname(std::string &name); + +typedef struct +{ +chunk ch[16][16]; +}mcell; +class MPQFile; +void LoadMapChunk(MPQFile &,chunk*); +bool LoadWMO(char* filename); +#endif + diff --git a/contrib/extractor/dbcfile.cpp b/contrib/extractor/dbcfile.cpp new file mode 100644 index 00000000000..acfb35482ff --- /dev/null +++ b/contrib/extractor/dbcfile.cpp @@ -0,0 +1,69 @@ +#define _CRT_SECURE_NO_DEPRECATE + +#include "dbcfile.h" +#include "mpq_libmpq.h" + +DBCFile::DBCFile(const std::string &filename): + filename(filename), + data(0) +{ + +} +void DBCFile::open() +{ + MPQFile f(filename.c_str()); + char header[4]; + unsigned int na,nb,es,ss; + + f.read(header,4); // Number of records + assert(header[0]=='W' && header[1]=='D' && header[2]=='B' && header[3] == 'C'); + f.read(&na,4); // Number of records + f.read(&nb,4); // Number of fields + f.read(&es,4); // Size of a record + f.read(&ss,4); // String size + + recordSize = es; + recordCount = na; + fieldCount = nb; + stringSize = ss; + assert(fieldCount*4 == recordSize); + + data = new unsigned char[recordSize*recordCount+stringSize]; + stringTable = data + recordSize*recordCount; + f.read(data,recordSize*recordCount+stringSize); + f.close(); +} +DBCFile::~DBCFile() +{ + delete [] data; +} + +DBCFile::Record DBCFile::getRecord(size_t id) +{ + assert(data); + return Record(*this, data + id*recordSize); +} + +size_t DBCFile::getMaxId() +{ + assert(data); + + size_t maxId = 0; + for(size_t i = 0; i < getRecordCount(); ++i) + { + if(maxId < getRecord(i).getUInt(0)) + maxId = getRecord(i).getUInt(0); + } + return maxId; +} + +DBCFile::Iterator DBCFile::begin() +{ + assert(data); + return Iterator(*this, data); +} +DBCFile::Iterator DBCFile::end() +{ + assert(data); + return Iterator(*this, stringTable); +} diff --git a/contrib/extractor/dbcfile.h b/contrib/extractor/dbcfile.h new file mode 100644 index 00000000000..521ca67423c --- /dev/null +++ b/contrib/extractor/dbcfile.h @@ -0,0 +1,118 @@ +#ifndef DBCFILE_H +#define DBCFILE_H +#include +#include + +class DBCFile +{ +public: + DBCFile(const std::string &filename); + ~DBCFile(); + + // Open database. It must be openened before it can be used. + void open(); + + // Database exceptions + class Exception + { + public: + Exception(const std::string &message): message(message) + { } + virtual ~Exception() + { } + const std::string &getMessage() {return message;} + private: + std::string message; + }; + class NotFound: public Exception + { + public: + NotFound(): Exception("Key was not found") + { } + }; + // Iteration over database + class Iterator; + class Record + { + public: + float getFloat(size_t field) const + { + assert(field < file.fieldCount); + return *reinterpret_cast(offset+field*4); + } + unsigned int getUInt(size_t field) const + { + assert(field < file.fieldCount); + return *reinterpret_cast(offset+field*4); + } + int getInt(size_t field) const + { + assert(field < file.fieldCount); + return *reinterpret_cast(offset+field*4); + } + const char *getString(size_t field) const + { + assert(field < file.fieldCount); + size_t stringOffset = getUInt(field); + assert(stringOffset < file.stringSize); + return reinterpret_cast(file.stringTable + stringOffset); + } + private: + Record(DBCFile &file, unsigned char *offset): file(file), offset(offset) {} + unsigned char *offset; + DBCFile &file; + + friend class DBCFile; + friend class DBCFile::Iterator; + }; + /** Iterator that iterates over records + */ + class Iterator + { + public: + Iterator(DBCFile &file, unsigned char *offset): + record(file, offset) {} + /// Advance (prefix only) + Iterator & operator++() { + record.offset += record.file.recordSize; + return *this; + } + /// Return address of current instance + Record const & operator*() const { return record; } + const Record* operator->() const { + return &record; + } + /// Comparison + bool operator==(const Iterator &b) const + { + return record.offset == b.record.offset; + } + bool operator!=(const Iterator &b) const + { + return record.offset != b.record.offset; + } + private: + Record record; + }; + + // Get record by id + Record getRecord(size_t id); + /// Get begin iterator over records + Iterator begin(); + /// Get begin iterator over records + Iterator end(); + /// Trivial + size_t getRecordCount() const { return recordCount;} + size_t getFieldCount() const { return fieldCount; } + size_t getMaxId(); +private: + std::string filename; + size_t recordSize; + size_t recordCount; + size_t fieldCount; + size_t stringSize; + unsigned char *data; + unsigned char *stringTable; +}; + +#endif diff --git a/contrib/extractor/debug/zlib.lib b/contrib/extractor/debug/zlib.lib new file mode 100644 index 00000000000..ffd7d9a2605 Binary files /dev/null and b/contrib/extractor/debug/zlib.lib differ diff --git a/contrib/extractor/libmpq/Makefile b/contrib/extractor/libmpq/Makefile new file mode 100644 index 00000000000..eb1965e29f1 --- /dev/null +++ b/contrib/extractor/libmpq/Makefile @@ -0,0 +1,17 @@ +CC = g++ +AR = ar +objects = common.o explode.o extract.o huffman.o wave.o mpq.o parser.o +zlib_objects = ../../../dep/src/zlib/*.o #adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o zutil.o inflate.o inftrees.o inffast.o + +all: libmpq.a libmpq.so + +clean: + rm -f libmpq.a libmpq.so *.o + +libmpq.a: $(objects) $(zlib_objects) + $(AR) cru $@ $+ +libmpq.so: $(objects) $(zlib_objects) + $(CC) -fPIC -o $@ $+ + +%.o:%.cpp + $(CC) -I../ -c $+ diff --git a/contrib/extractor/libmpq/Makefile.am b/contrib/extractor/libmpq/Makefile.am new file mode 100644 index 00000000000..192bd1369ef --- /dev/null +++ b/contrib/extractor/libmpq/Makefile.am @@ -0,0 +1,23 @@ +# The input Makefile for the main mpq-tools + +lib_LTLIBRARIES = libmpq.la +noinst_HEADERS = explode.h huffman.h wave.h common.h + +# The directory where the include files will be installed. +libmpq_includedir = $(includedir)/libmpq + +# Which header files to install. +libmpq_include_HEADERS = mpq.h + +libmpq_la_SOURCES = $(GENERAL_SRCS) +libmpq_la_LDFLAGS = -release $(LIBMPQ_VERSION) +libmpq_la_LIBADD = @Z_LIBS@ + +GENERAL_SRCS = \ + common.c \ + huffman.c \ + extract.c \ + explode.c \ + mpq.c \ + parser.c \ + wave.c diff --git a/contrib/extractor/libmpq/common.cpp b/contrib/extractor/libmpq/common.cpp new file mode 100644 index 00000000000..7b902087540 --- /dev/null +++ b/contrib/extractor/libmpq/common.cpp @@ -0,0 +1,801 @@ +/* + * common.c -- shared functions used by mpq-tools. + * + * Copyright (C) 2003 Maik Broemme + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id: common.c,v 1.12 2004/02/12 00:42:54 mbroemme Exp $ + */ +#define _CRT_SECURE_NO_DEPRECATE +//#include +#include +//#include +#include +#include +#include +#include "mpq.h" +#include "common.h" +#include + +/* + * This function decrypts a MPQ block. + */ +int libmpq_decrypt_block(mpq_archive *mpq_a, unsigned int *block, unsigned int length, unsigned int seed1) { + unsigned int seed2 = 0xEEEEEEEE; + unsigned int ch; + + /* Round to unsigned int's */ + length >>= 2; + while (length-- > 0) { + seed2 += mpq_a->buf[0x400 + (seed1 & 0xFF)]; + ch = *block ^ (seed1 + seed2); + seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B); + seed2 = ch + seed2 + (seed2 << 5) + 3; + *block++ = ch; + } + return LIBMPQ_TOOLS_SUCCESS; +} + +/* + * This function decrypts the hashtable for the + * file informations. + */ +int libmpq_decrypt_hashtable(mpq_archive *mpq_a, unsigned char *pbKey) { + unsigned int seed1 = 0x7FED7FED; + unsigned int seed2 = 0xEEEEEEEE; + unsigned int ch; /* One key character */ + unsigned int *pdwTable = (unsigned int *)(mpq_a->hashtable); + unsigned int length = mpq_a->header->hashtablesize * 4; + + /* Prepare seeds */ + while (*pbKey != 0) { + ch = toupper(*pbKey++); + seed1 = mpq_a->buf[0x300 + ch] ^ (seed1 + seed2); + seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3; + } + + /* Decrypt it */ + seed2 = 0xEEEEEEEE; + while (length-- > 0) { + seed2 += mpq_a->buf[0x400 + (seed1 & 0xFF)]; + ch = *pdwTable ^ (seed1 + seed2); + seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B); + seed2 = ch + seed2 + (seed2 << 5) + 3; + *pdwTable++ = ch; + } + return LIBMPQ_TOOLS_SUCCESS; +} + +/* + * This function decrypts the blocktable. + */ +int libmpq_decrypt_blocktable(mpq_archive *mpq_a, unsigned char *pbKey) { + unsigned int seed1 = 0x7FED7FED; + unsigned int seed2 = 0xEEEEEEEE; + unsigned int ch; /* One key character */ + unsigned int *pdwTable = (unsigned int *)(mpq_a->blocktable); + unsigned int length = mpq_a->header->blocktablesize * 4; + + /* Prepare seeds */ + while(*pbKey != 0) { + ch = toupper(*pbKey++); + seed1 = mpq_a->buf[0x300 + ch] ^ (seed1 + seed2); + seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3; + } + + /* Decrypt it */ + seed2 = 0xEEEEEEEE; + while(length-- > 0) { + seed2 += mpq_a->buf[0x400 + (seed1 & 0xFF)]; + ch = *pdwTable ^ (seed1 + seed2); + seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B); + seed2 = ch + seed2 + (seed2 << 5) + 3; + *pdwTable++ = ch; + } + return LIBMPQ_TOOLS_SUCCESS; +} + +int libmpq_read_listfile(mpq_archive *mpq_a, FILE *fp) { + int mpq_size; + int mpq_ht_size; + int mpq_bt_size; + int mpq_blocksize; + int mpq_files; + int mpq_csize; + int mpq_fsize; + int entries; + char listdb_version[10]; + char libmpq_version[10]; + int listdb_temp_version = 0; + int libmpq_temp_version = 0; + + /* first check header and version */ + if (libmpq_conf_get_value(fp, "LIBMPQ_VERSION", mpq_a->mpq_l->mpq_version, LIBMPQ_CONF_TYPE_CHAR, sizeof(mpq_a->mpq_l->mpq_version))) { + return LIBMPQ_CONF_EFILE_CORRUPT; + } else { + + /* copy to temp buffer for removing . characters */ + sprintf(listdb_version, (char *)mpq_a->mpq_l->mpq_version); + + /* remove . characters from listfile version */ + libmpq_conf_delete_char(listdb_version, "."); + + /* get libmpq version */ + sprintf(libmpq_version, "%i%i%i",LIBMPQ_MAJOR_VERSION, LIBMPQ_MINOR_VERSION, LIBMPQ_PATCH_VERSION); + + /* convert to number */ + listdb_temp_version = atoi(listdb_version); + libmpq_temp_version = atoi(libmpq_version); + + /* check if installed libmpq version is valid for listfile version */ + if ((libmpq_temp_version < listdb_temp_version) || (libmpq_temp_version == 0) || (listdb_temp_version == 0)) { + return LIBMPQ_CONF_EFILE_VERSION; + } + } + + /* check listfile header, the following entries must be set */ + if (libmpq_conf_get_value(fp, "MPQ_SIZE", &mpq_size, LIBMPQ_CONF_TYPE_INT, 0)) { + return LIBMPQ_CONF_EFILE_CORRUPT; + } + if (libmpq_conf_get_value(fp, "MPQ_HASHTABLE_SIZE", &mpq_ht_size, LIBMPQ_CONF_TYPE_INT, 0)) { + return LIBMPQ_CONF_EFILE_CORRUPT; + } + if (libmpq_conf_get_value(fp, "MPQ_BLOCKTABLE_SIZE", &mpq_bt_size, LIBMPQ_CONF_TYPE_INT, 0)) { + return LIBMPQ_CONF_EFILE_CORRUPT; + } + if (libmpq_conf_get_value(fp, "MPQ_BLOCKSIZE", &mpq_blocksize, LIBMPQ_CONF_TYPE_INT, 0)) { + return LIBMPQ_CONF_EFILE_CORRUPT; + } + if (libmpq_conf_get_value(fp, "MPQ_FILES", &mpq_files, LIBMPQ_CONF_TYPE_INT, 0)) { + return LIBMPQ_CONF_EFILE_CORRUPT; + } + if (libmpq_conf_get_value(fp, "MPQ_COMPRESSED_SIZE", &mpq_csize, LIBMPQ_CONF_TYPE_INT, 0)) { + return LIBMPQ_CONF_EFILE_CORRUPT; + } + if (libmpq_conf_get_value(fp, "MPQ_UNCOMPRESSED_SIZE", &mpq_fsize, LIBMPQ_CONF_TYPE_INT, 0)) { + return LIBMPQ_CONF_EFILE_CORRUPT; + } + if (libmpq_conf_get_value(fp, "MPQ_NAME", mpq_a->mpq_l->mpq_name, LIBMPQ_CONF_TYPE_CHAR, PATH_MAX)) { + return LIBMPQ_CONF_EFILE_CORRUPT; + } + if (libmpq_conf_get_value(fp, "MPQ_TYPE", mpq_a->mpq_l->mpq_type, LIBMPQ_CONF_TYPE_CHAR, sizeof(mpq_a->mpq_l->mpq_type))) { + return LIBMPQ_CONF_EFILE_CORRUPT; + } + + /* these are optional parameters, if they are empty we set the struct members empty */ + libmpq_conf_get_value(fp, "MPQ_GAME", mpq_a->mpq_l->mpq_game, LIBMPQ_CONF_TYPE_CHAR, sizeof(mpq_a->mpq_l->mpq_game)); + libmpq_conf_get_value(fp, "MPQ_GAME_VERSION", mpq_a->mpq_l->mpq_game_version, LIBMPQ_CONF_TYPE_CHAR, sizeof(mpq_a->mpq_l->mpq_game_version)); + + /* check if we found a valid listfile for the given archive */ + if (mpq_a->header->hashtablesize == mpq_ht_size && mpq_a->header->blocktablesize == mpq_bt_size && mpq_a->blocksize == mpq_blocksize && libmpq_archive_info(mpq_a, LIBMPQ_MPQ_ARCHIVE_SIZE) == mpq_size && libmpq_archive_info(mpq_a, LIBMPQ_MPQ_NUMFILES) == mpq_files && libmpq_archive_info(mpq_a, LIBMPQ_MPQ_COMPRESSED_SIZE) == mpq_csize && libmpq_archive_info(mpq_a, LIBMPQ_MPQ_UNCOMPRESSED_SIZE) == mpq_fsize) { + + /* check if the filelist is correct */ + if (!libmpq_conf_get_array(fp, "FILE_NAMES", (char ***)&mpq_a->mpq_l->mpq_files, &entries)) { + + /* we have a corrupt filelist, so return */ + return LIBMPQ_CONF_EFILE_LIST_CORRUPT; + } else { + + /* now check if filelist entries matches number of files in the archive. */ + if (entries != libmpq_archive_info(mpq_a, LIBMPQ_MPQ_NUMFILES)) { + libmpq_free_listfile((char **)mpq_a->mpq_l->mpq_files); + mpq_a->mpq_l->mpq_files = NULL; + return LIBMPQ_CONF_EFILE_LIST_CORRUPT; + } + } + } + + return LIBMPQ_TOOLS_SUCCESS; +} + +/* + * This function frees up the space reserved by libmpq_get_listfile() + */ +int libmpq_free_listfile(char **filelist) { + int i = 0; + while (filelist[i]) { + free(filelist[i++]); + } + free(filelist); + + return LIBMPQ_TOOLS_SUCCESS; +} + +/* + * This function reads the directory and the subdirectories + * of the listfile database and adds a entry to the lisfile + * array. + */ +/*int libmpq_detect_listfile_rec(char path[PATH_MAX], char ***filelist, int *fl_count, int *fl_size) { + char nextpath[PATH_MAX]; + DIR *dp = opendir(path); + FILE *fp; + struct dirent *entry; + struct stat statbuf; + char buf[LIBMPQ_CONF_BUFSIZE]; + + if (dp == NULL) { + return LIBMPQ_CONF_EOPEN_DIR; + } else { + while ((entry = readdir(dp)) != NULL) { + if (strncmp(entry->d_name, ".", 1) == 0 || strncmp(entry->d_name, "..", 2) == 0) { + continue; + } + if (strnlen(path, PATH_MAX) + strnlen(entry->d_name, PATH_MAX) + 2 > sizeof nextpath) { + continue; + } + + snprintf(nextpath, PATH_MAX, "%s/%s", path, entry->d_name); + + // check if file extension matches listdb file extension + if (strncmp(&entry->d_name[strlen(entry->d_name) - strlen(LIBMPQ_CONF_EXT)], LIBMPQ_CONF_EXT, strlen(LIBMPQ_CONF_EXT)) == 0) { + + // check if it is really a listdb file + if ((fp = fopen(nextpath, "r")) != NULL ) { + while (fgets(buf, LIBMPQ_CONF_BUFSIZE, fp) != NULL) { + char *line; + + buf[strlen(buf) - 1] = '\0'; + + // skip whitespace + for (line = buf; isspace(*line); line++) { + continue; + } + + // skip empty line + if (line[0] == '\0') { + continue; + } + + // skip comments + if (line[0] == '#') { + continue; + } + + //search for listdb header; dirty but works :) + if (!strncasecmp(line, LIBMPQ_CONF_HEADER, strlen(LIBMPQ_CONF_HEADER))) { + + // set the next filelist entry to a copy of the file path + (*filelist)[(*fl_count)++] = strdup(nextpath); + + // increase the array size + if ((*fl_count) == (*fl_size)) { + (*filelist) = realloc((*filelist), ((*fl_size) + LIBMPQ_CONF_FL_INCREMENT) * sizeof(char *)); + (*fl_size) += LIBMPQ_CONF_FL_INCREMENT; + } + + // header found so we could stop reading the file. + break; + } + } + fclose(fp); + } + } + + if (stat(nextpath, &statbuf) < 0) { + continue; + } + + // if entry ia a subdirectory, read it + if (S_ISDIR(statbuf.st_mode)) { + libmpq_detect_listfile_rec(nextpath, filelist, fl_count, fl_size); + } + } + closedir(dp); + } + + return LIBMPQ_TOOLS_SUCCESS; +} +*/ + +/* + * This functions tries to get file decryption key. The trick comes from block + * positions which are stored at the begin of each compressed file. We know the + * file size, that means we know number of blocks that means we know the first + * int value in block position. And if we know encrypted and decrypted value, + * we can find the decryption key. + */ +int libmpq_detect_fileseed(mpq_archive *mpq_a, unsigned int *block, unsigned int decrypted) { + unsigned int saveseed1; + unsigned int temp = *block ^ decrypted; /* temp = seed1 + seed2 */ + int i = 0; + temp -= 0xEEEEEEEE; /* temp = seed1 + mpq_a->buf[0x400 + (seed1 & 0xFF)] */ + + for (i = 0; i < 0x100; i++) { /* Try all 255 possibilities */ + unsigned int seed1; + unsigned int seed2 = 0xEEEEEEEE; + unsigned int ch; + + /* Try the first unsigned int's (We exactly know the value) */ + seed1 = temp - mpq_a->buf[0x400 + i]; + seed2 += mpq_a->buf[0x400 + (seed1 & 0xFF)]; + ch = block[0] ^ (seed1 + seed2); + + if (ch != decrypted) { + continue; + } + + /* Add 1 because we are decrypting block positions */ + saveseed1 = seed1 + 1; + + /* + * If OK, continue and test the second value. We don't know exactly the value, + * but we know that the second one has lower 16 bits set to zero + * (no compressed block is larger than 0xFFFF bytes) + */ + seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B); + seed2 = ch + seed2 + (seed2 << 5) + 3; + seed2 += mpq_a->buf[0x400 + (seed1 & 0xFF)]; + ch = block[1] ^ (seed1 + seed2); + if ((ch & 0xFFFF0000) == 0) { + return saveseed1; + } + } + return LIBMPQ_TOOLS_SUCCESS; +} + +/* + * This function initialize the decryption buffer + */ +int libmpq_init_buffer(mpq_archive *mpq_a) { + unsigned int seed = 0x00100001; + unsigned int index1 = 0; + unsigned int index2 = 0; + int i; + + memset(mpq_a->buf, 0, sizeof(mpq_a->buf)); + + /* Initialize the decryption buffer. */ + for (index1 = 0; index1 < 0x100; index1++) { + for(index2 = index1, i = 0; i < 5; i++, index2 += 0x100) { + unsigned int temp1, temp2; + seed = (seed * 125 + 3) % 0x2AAAAB; + temp1 = (seed & 0xFFFF) << 0x10; + + seed = (seed * 125 + 3) % 0x2AAAAB; + temp2 = (seed & 0xFFFF); + + mpq_a->buf[index2] = (temp1 | temp2); + } + } + return LIBMPQ_TOOLS_SUCCESS; +} + +/* + * This functions fills the mpq_hash structure with the + * hashtable found in the MPQ file. The hashtable will + * be decrypted for later use. + */ +int libmpq_read_hashtable(mpq_archive *mpq_a) { + unsigned int bytes = 0; + int rb = 0; + + /* + * Allocate memory. Note that the block table should be as large as the + * hash table. (for later file additions) + */ + mpq_a->hashtable = (mpq_hash *)malloc(sizeof(mpq_hash) * mpq_a->header->hashtablesize); + + if (!mpq_a->hashtable) { + return LIBMPQ_EALLOCMEM; + } + + /* Read the hash table into the buffer */ + bytes = mpq_a->header->hashtablesize * sizeof(mpq_hash); + + #ifdef WIN32 + _lseeki64(mpq_a->fd, mpq_a->header->hashtablepos, SEEK_SET); + #else + lseek64(mpq_a->fd, mpq_a->header->hashtablepos, SEEK_SET); + #endif + + rb = _read(mpq_a->fd, mpq_a->hashtable, bytes); + if (rb != bytes) { + return LIBMPQ_EFILE_CORRUPT; + } + + /* Decrypt hash table and check if it is correctly decrypted */ + mpq_hash *mpq_h_end = mpq_a->hashtable + mpq_a->header->hashtablesize; + mpq_hash *mpq_h = NULL; + + libmpq_decrypt_hashtable(mpq_a, (unsigned char *)"(hash table)"); + + /* Check hash table if is correctly decrypted */ + for (mpq_h = mpq_a->hashtable; mpq_h < mpq_h_end; mpq_h++) { + if (mpq_h->locale != 0xFFFFFFFF && (mpq_h->locale & 0xFFFF0000) != 0) { + return LIBMPQ_EFILE_FORMAT; + } + + /* Remember the highest block table entry */ + if (mpq_h->blockindex < LIBMPQ_HASH_ENTRY_DELETED && mpq_h->blockindex > 0) { + mpq_a->maxblockindex = mpq_h->blockindex; + } + } + + return LIBMPQ_TOOLS_SUCCESS; +} + +/* + * This functions fills the mpq_block structure with the + * blocktable found in the MPQ file. The blocktable will + * be decrypted for later use. + * + * NOTICE: Some MPQs have decrypted block table, e.g. + * cracked Diablo versions. + */ +int libmpq_read_blocktable(mpq_archive *mpq_a) { + unsigned int bytes = 0; + int rb = 0; + + /* + * Allocate memory. Note that the block table should be as large as the + * hash table. (for later file additions) + */ + mpq_a->blocktable = (mpq_block *)malloc(sizeof(mpq_block) * mpq_a->header->hashtablesize); + mpq_a->blockbuf = (unsigned char *)malloc(mpq_a->blocksize); + + if (!mpq_a->blocktable || !mpq_a->blockbuf) { + return LIBMPQ_EALLOCMEM; + } + + /* Read the block table into the buffer */ + bytes = mpq_a->header->blocktablesize * sizeof(mpq_block); + memset(mpq_a->blocktable, 0, mpq_a->header->blocktablesize * sizeof(mpq_block)); + + #ifdef WIN32 + _lseeki64(mpq_a->fd, mpq_a->header->blocktablepos, SEEK_SET); + #else + lseek64(mpq_a->fd, mpq_a->header->blocktablepos, SEEK_SET); + #endif + + rb = _read(mpq_a->fd, mpq_a->blocktable, bytes); + if (rb != bytes) { + return LIBMPQ_EFILE_CORRUPT; + } + + /* + * Decrypt block table. Some MPQs don't have encrypted block table, + * e.g. cracked Diablo version. We have to check if block table is + * already decrypted + */ + mpq_block *mpq_b_end = mpq_a->blocktable + mpq_a->maxblockindex + 1; + mpq_block *mpq_b = NULL; + unsigned int archivesize = mpq_a->header->archivesize + mpq_a->mpqpos; + + if (mpq_a->header->offset != mpq_a->blocktable->filepos) { + libmpq_decrypt_blocktable(mpq_a, (unsigned char *)"(block table)"); + } + for (mpq_b = mpq_a->blocktable; mpq_b < mpq_b_end; mpq_b++) { + if (mpq_b->filepos > archivesize || mpq_b->csize > archivesize) { + if ((mpq_a->flags & LIBMPQ_FLAG_PROTECTED) == 0) { + return LIBMPQ_EFILE_FORMAT; + } + } + mpq_b->filepos += mpq_a->mpqpos; + } + + return LIBMPQ_TOOLS_SUCCESS; +} + +int libmpq_file_read_block(mpq_archive *mpq_a, mpq_file *mpq_f, unsigned int blockpos, char *buffer, unsigned int blockbytes) { + unsigned char *tempbuf = NULL; /* Buffer for reading compressed data from the file */ + unsigned int readpos; /* Reading position from the file */ + unsigned int toread = 0; /* Number of bytes to read */ + unsigned int blocknum; /* Block number (needed for decrypt) */ + unsigned int bytesread = 0; /* Total number of bytes read */ + unsigned int nblocks; /* Number of blocks to load */ + unsigned int i; + + /* Test parameters. Block position and block size must be block-aligned, block size nonzero */ + if ((blockpos & (mpq_a->blocksize - 1)) || blockbytes == 0) { + return 0; + } + + /* Check the end of file */ + if ((blockpos + blockbytes) > mpq_f->mpq_b->fsize) { + blockbytes = mpq_f->mpq_b->fsize - blockpos; + } + blocknum = blockpos / mpq_a->blocksize; + nblocks = blockbytes / mpq_a->blocksize; + if (blockbytes % mpq_a->blocksize) { + nblocks++; + } + + /* If file has variable block positions, we have to load them */ + if ((mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) && mpq_f->blockposloaded == FALSE) { + unsigned int nread; + + if (mpq_f->mpq_b->filepos != mpq_a->filepos) { + #ifdef WIN32 + _lseeki64(mpq_a->fd, mpq_f->mpq_b->filepos, SEEK_SET); + #else + lseek64(mpq_a->fd, mpq_f->mpq_b->filepos, SEEK_SET); + + #endif + } + + /* Read block positions from begin of file. */ + nread = (mpq_f->nblocks + 1) * sizeof(int); + nread = _read(mpq_a->fd, mpq_f->blockpos, nread); + + /* + * If the archive is protected some way, perform additional check + * Sometimes, the file appears not to be encrypted, but it is. + */ + /*if (mpq_f->blockpos[0] != nread) { + mpq_f->mpq_b->flags |= LIBMPQ_FILE_ENCRYPTED; + }*/ + + if ((mpq_f->mpq_b->flags & LIBMPQ_FILE_HAS_METADATA) == 0) { + if (mpq_f->blockpos[0] != nread) { + mpq_f->mpq_b->flags |= LIBMPQ_FILE_ENCRYPTED; + } + } + + /* Decrypt loaded block positions if necessary */ + if (mpq_f->mpq_b->flags & LIBMPQ_FILE_ENCRYPTED) { + + /* If we don't know the file seed, try to find it. */ + if (mpq_f->seed == 0) { + mpq_f->seed = libmpq_detect_fileseed(mpq_a, mpq_f->blockpos, nread); + } + + /* If we don't know the file seed, sorry but we cannot extract the file. */ + if (mpq_f->seed == 0) { + return 0; + } + + /* Decrypt block positions */ + libmpq_decrypt_block(mpq_a, mpq_f->blockpos, nread, mpq_f->seed - 1); + + /* + * Check if the block positions are correctly decrypted + * I don't know why, but sometimes it will result invalid + * block positions on some files. + */ + if (mpq_f->blockpos[0] != nread) { + + /* Try once again to detect file seed and decrypt the blocks */ + + #ifdef WIN32 + _lseeki64(mpq_a->fd, mpq_f->mpq_b->filepos, SEEK_SET); + #else + lseek64(mpq_a->fd, mpq_f->mpq_b->filepos, SEEK_SET); + #endif + + nread = _read(mpq_a->fd, mpq_f->blockpos, (mpq_f->nblocks + 1) * sizeof(int)); + mpq_f->seed = libmpq_detect_fileseed(mpq_a, mpq_f->blockpos, nread); + libmpq_decrypt_block(mpq_a, mpq_f->blockpos, nread, mpq_f->seed - 1); + + /* Check if the block positions are correctly decrypted. */ + if (mpq_f->blockpos[0] != nread) { + return 0; + } + } + } + + /* Update mpq_f's variables */ + mpq_f->blockposloaded = TRUE; + mpq_a->filepos = mpq_f->mpq_b->filepos + nread; + } + + /* Get file position and number of bytes to read */ + readpos = blockpos; + toread = blockbytes; + + if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) { + readpos = mpq_f->blockpos[blocknum]; + toread = mpq_f->blockpos[blocknum + nblocks] - readpos; + } + + readpos += mpq_f->mpq_b->filepos; + + /* Get work buffer for store read data */ + if ((tempbuf = (unsigned char *)malloc(toread)) == NULL) { + /* Hmmm... We should add a better error handling here :) */ + return 0; + } + + /* Set file pointer, if necessary. */ + if (mpq_a->filepos != readpos) { + + #ifdef WIN32 + mpq_a->filepos = _lseeki64(mpq_a->fd, readpos, SEEK_SET); + #else + mpq_a->filepos = lseek64(mpq_a->fd, readpos, SEEK_SET); + #endif + + } + + /* 15018F87 - Read all requested blocks. */ + bytesread = _read(mpq_a->fd, tempbuf, toread); + mpq_a->filepos = readpos + bytesread; + + /* Block processing part. */ + unsigned int blockstart = 0; /* Index of block start in work buffer. */ + unsigned int blocksize = min(blockbytes, mpq_a->blocksize); + unsigned int index = blocknum; /* Current block index. */ + bytesread = 0; /* Clear read byte counter */ + + /* Walk through all blocks. */ + for (i = 0; i < nblocks; i++, index++) { + int outlength = mpq_a->blocksize; + + /* Get current block length */ + if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) { + blocksize = mpq_f->blockpos[index + 1] - mpq_f->blockpos[index]; + } + + /* If block is encrypted, we have to decrypt it. */ + if (mpq_f->mpq_b->flags & LIBMPQ_FILE_ENCRYPTED) { + if (mpq_f->seed == 0) { + return 0; + } + libmpq_decrypt_block(mpq_a, (unsigned int *)&tempbuf[blockstart], blocksize, mpq_f->seed + index); + } + + /* + * If the block is really compressed, recompress it. + * WARNING: Some block may not be compressed, it can + * only be determined by comparing uncompressed and + * compressed size! + */ + if (blocksize < blockbytes) { + + /* Is the file compressed with PKWARE Data Compression Library? */ + if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESS_PKWARE) { + libmpq_pkzip_decompress(buffer, &outlength, (char *)&tempbuf[blockstart], blocksize); + } + + /* + * Is it a file compressed by Blizzard's multiple compression ? + * Note that Storm.dll v 1.0.9 distributed with Warcraft III + * passes the full path name of the opened archive as the new + * last parameter. + */ + if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESS_MULTI) { + libmpq_multi_decompress(buffer, &outlength, (char *)&tempbuf[blockstart], blocksize); + } + bytesread += outlength; + buffer += outlength; + } else { + memcpy(buffer, tempbuf, blocksize); + bytesread += blocksize; + buffer += blocksize; + } + blockstart += blocksize; + } + + /* Delete input buffer, if necessary. */ + free(tempbuf); + + return bytesread; +} + +int libmpq_file_read_file(mpq_archive *mpq_a, mpq_file *mpq_f, unsigned int filepos, char *buffer, unsigned int toread) { + unsigned int bytesread = 0; /* Number of bytes read from the file */ + unsigned int blockpos; /* Position in the file aligned to the whole blocks */ + unsigned int loaded = 0; + + /* File position is greater or equal to file size? */ + if (filepos >= mpq_f->mpq_b->fsize) { + return 0; + } + + /* If to few bytes in the file remaining, cut them */ + if ((mpq_f->mpq_b->fsize - filepos) < toread) { + toread = (mpq_f->mpq_b->fsize - filepos); + } + + /* Block position in the file */ + blockpos = filepos & ~(mpq_a->blocksize - 1); + + /* + * Load the first block, if noncomplete. It may be loaded in the cache buffer. + * We have to check if this block is loaded. If not, load it. + */ + if ((filepos % mpq_a->blocksize) != 0) { + /* Number of bytes remaining in the buffer */ + unsigned int tocopy; + unsigned int loaded = mpq_a->blocksize; + + /* Check if data are loaded in the cache */ + if (mpq_f->accessed == FALSE || blockpos != mpq_a->blockpos) { + + /* Load one MPQ block into archive buffer */ + loaded = libmpq_file_read_block(mpq_a, mpq_f, blockpos, (char *)mpq_a->blockbuf, mpq_a->blocksize); + if (loaded == 0) { + return 0; + } + + /* Save lastly accessed file and block position for later use */ + mpq_f->accessed = TRUE; + mpq_a->blockpos = blockpos; + mpq_a->bufpos = filepos % mpq_a->blocksize; + } + tocopy = loaded - mpq_a->bufpos; + if (tocopy > toread) { + tocopy = toread; + } + + /* Copy data from block buffer into target buffer */ + memcpy(buffer, mpq_a->blockbuf + mpq_a->bufpos, tocopy); + + /* Update pointers */ + toread -= tocopy; + bytesread += tocopy; + buffer += tocopy; + blockpos += mpq_a->blocksize; + mpq_a->bufpos += tocopy; + + /* If all, return. */ + if (toread == 0) { + return bytesread; + } + } + + /* Load the whole ("middle") blocks only if there are more or equal one block */ + if (toread > mpq_a->blocksize) { + unsigned int blockbytes = toread & ~(mpq_a->blocksize - 1); + loaded = libmpq_file_read_block(mpq_a, mpq_f, blockpos, buffer, blockbytes); + if (loaded == 0) { + return 0; + } + + /* Update pointers */ + toread -= loaded; + bytesread += loaded; + buffer += loaded; + blockpos += loaded; + + /* If all, return. */ + if (toread == 0) { + return bytesread; + } + } + + /* Load the terminating block */ + if (toread > 0) { + unsigned int tocopy = mpq_a->blocksize; + + /* Check if data are loaded in the cache */ + if (mpq_f->accessed == FALSE || blockpos != mpq_a->blockpos) { + + /* Load one MPQ block into archive buffer */ + tocopy = libmpq_file_read_block(mpq_a, mpq_f, blockpos, (char *)mpq_a->blockbuf, mpq_a->blocksize); + if (tocopy == 0) { + return 0; + } + + /* Save lastly accessed file and block position for later use */ + mpq_f->accessed = TRUE; + mpq_a->blockpos = blockpos; + } + mpq_a->bufpos = 0; + + /* Check number of bytes read */ + if (tocopy > toread) { + tocopy = toread; + } + + memcpy(buffer, mpq_a->blockbuf, tocopy); + bytesread += tocopy; + mpq_a->bufpos = tocopy; + } + + /* Return what we've read */ + return bytesread; +} diff --git a/contrib/extractor/libmpq/common.h b/contrib/extractor/libmpq/common.h new file mode 100644 index 00000000000..ad2c0f101fa --- /dev/null +++ b/contrib/extractor/libmpq/common.h @@ -0,0 +1,66 @@ +/* + * common.h -- defines and structs used by the config files. + * + * Copyright (C) 2003 Maik Broemme + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id: common.h,v 1.4 2004/02/12 00:41:55 mbroemme Exp $ + */ + +#define LIBMPQ_CONF_FL_INCREMENT 512 /* i hope we did not need more :) */ +#define LIBMPQ_CONF_EXT ".conf" /* listdb file seems to be valid with this extension */ +#define LIBMPQ_CONF_HEADER "LIBMPQ_VERSION" /* listdb file must include this entry to be valid */ +#define LIBMPQ_CONF_BUFSIZE 4096 /* maximum number of bytes a line in the file could contain */ + +#define LIBMPQ_CONF_TYPE_CHAR 1 /* value in config file is from type char */ +#define LIBMPQ_CONF_TYPE_INT 2 /* value in config file is from type int */ + +#define LIBMPQ_CONF_EOPEN_DIR -1 /* error on open directory */ +#define LIBMPQ_CONF_EVALUE_NOT_FOUND -2 /* value for the option was not found */ + +#if defined( __GNUC__ ) + #include + #include + + #define _lseek lseek + #define _read read + #define _open open + #define _write write + #define _close close + #define _strdup strdup + + #ifndef O_BINARY + #define O_BINARY 0 + #endif +#else + #include +#endif + +#ifndef min + #define min(a, b) ((a < b) ? a : b) +#endif + +int libmpq_init_buffer(mpq_archive *mpq_a); +int libmpq_read_hashtable(mpq_archive *mpq_a); +int libmpq_read_blocktable(mpq_archive *mpq_a); +int libmpq_file_read_file(mpq_archive *mpq_a, mpq_file *mpq_f, unsigned int filepos, char *buffer, unsigned int toread); +int libmpq_read_listfile(mpq_archive *mpq_a, FILE *fp); + +int libmpq_conf_get_value(FILE *fp, char *search_value, void *return_value, int type, int size); +char *libmpq_conf_delete_char(char *buf, char *chars); +int libmpq_conf_get_array(FILE *fp, char *search_value, char ***filelist, int *entries); +int libmpq_free_listfile(char **filelist); +int libmpq_read_listfile(mpq_archive *mpq_a, FILE *fp); diff --git a/contrib/extractor/libmpq/explode.cpp b/contrib/extractor/libmpq/explode.cpp new file mode 100644 index 00000000000..bcf9e7857a2 --- /dev/null +++ b/contrib/extractor/libmpq/explode.cpp @@ -0,0 +1,428 @@ +/* + * explode.c -- explode function of PKWARE data compression library. + * + * Copyright (C) 2003 Maik Broemme + * + * This source was adepted from the C++ version of pkware.cpp included + * in stormlib. The C++ version belongs to the following authors, + * + * Ladislav Zezula + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include + +#include "mpq.h" +#include "explode.h" + +/* Tables */ +static unsigned char pkzip_dist_bits[] = { + 0x02, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 +}; + +static unsigned char pkzip_dist_code[] = { + 0x03, 0x0D, 0x05, 0x19, 0x09, 0x11, 0x01, 0x3E, 0x1E, 0x2E, 0x0E, 0x36, 0x16, 0x26, 0x06, 0x3A, + 0x1A, 0x2A, 0x0A, 0x32, 0x12, 0x22, 0x42, 0x02, 0x7C, 0x3C, 0x5C, 0x1C, 0x6C, 0x2C, 0x4C, 0x0C, + 0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04, 0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08, + 0xF0, 0x70, 0xB0, 0x30, 0xD0, 0x50, 0x90, 0x10, 0xE0, 0x60, 0xA0, 0x20, 0xC0, 0x40, 0x80, 0x00 +}; + +static unsigned char pkzip_clen_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 +}; + +static unsigned short pkzip_len_base[] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x000A, 0x000E, 0x0016, 0x0026, 0x0046, 0x0086, 0x0106 +}; + +static unsigned char pkzip_slen_bits[] = { + 0x03, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07 +}; + +static unsigned char pkzip_len_code[] = { + 0x05, 0x03, 0x01, 0x06, 0x0A, 0x02, 0x0C, 0x14, 0x04, 0x18, 0x08, 0x30, 0x10, 0x20, 0x40, 0x00 +}; + +static unsigned char pkzip_bits_asc[] = { + 0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x08, 0x07, 0x0C, 0x0C, 0x07, 0x0C, 0x0C, + 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, + 0x04, 0x0A, 0x08, 0x0C, 0x0A, 0x0C, 0x0A, 0x08, 0x07, 0x07, 0x08, 0x09, 0x07, 0x06, 0x07, 0x08, + 0x07, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x07, 0x07, 0x08, 0x08, 0x0C, 0x0B, 0x07, 0x09, 0x0B, + 0x0C, 0x06, 0x07, 0x06, 0x06, 0x05, 0x07, 0x08, 0x08, 0x06, 0x0B, 0x09, 0x06, 0x07, 0x06, 0x06, + 0x07, 0x0B, 0x06, 0x06, 0x06, 0x07, 0x09, 0x08, 0x09, 0x09, 0x0B, 0x08, 0x0B, 0x09, 0x0C, 0x08, + 0x0C, 0x05, 0x06, 0x06, 0x06, 0x05, 0x06, 0x06, 0x06, 0x05, 0x0B, 0x07, 0x05, 0x06, 0x05, 0x05, + 0x06, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x08, 0x07, 0x08, 0x08, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C, + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, + 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, + 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, + 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, + 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, + 0x0D, 0x0D, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D +}; + +static unsigned short pkzip_code_asc[] = { + 0x0490, 0x0FE0, 0x07E0, 0x0BE0, 0x03E0, 0x0DE0, 0x05E0, 0x09E0, + 0x01E0, 0x00B8, 0x0062, 0x0EE0, 0x06E0, 0x0022, 0x0AE0, 0x02E0, + 0x0CE0, 0x04E0, 0x08E0, 0x00E0, 0x0F60, 0x0760, 0x0B60, 0x0360, + 0x0D60, 0x0560, 0x1240, 0x0960, 0x0160, 0x0E60, 0x0660, 0x0A60, + 0x000F, 0x0250, 0x0038, 0x0260, 0x0050, 0x0C60, 0x0390, 0x00D8, + 0x0042, 0x0002, 0x0058, 0x01B0, 0x007C, 0x0029, 0x003C, 0x0098, + 0x005C, 0x0009, 0x001C, 0x006C, 0x002C, 0x004C, 0x0018, 0x000C, + 0x0074, 0x00E8, 0x0068, 0x0460, 0x0090, 0x0034, 0x00B0, 0x0710, + 0x0860, 0x0031, 0x0054, 0x0011, 0x0021, 0x0017, 0x0014, 0x00A8, + 0x0028, 0x0001, 0x0310, 0x0130, 0x003E, 0x0064, 0x001E, 0x002E, + 0x0024, 0x0510, 0x000E, 0x0036, 0x0016, 0x0044, 0x0030, 0x00C8, + 0x01D0, 0x00D0, 0x0110, 0x0048, 0x0610, 0x0150, 0x0060, 0x0088, + 0x0FA0, 0x0007, 0x0026, 0x0006, 0x003A, 0x001B, 0x001A, 0x002A, + 0x000A, 0x000B, 0x0210, 0x0004, 0x0013, 0x0032, 0x0003, 0x001D, + 0x0012, 0x0190, 0x000D, 0x0015, 0x0005, 0x0019, 0x0008, 0x0078, + 0x00F0, 0x0070, 0x0290, 0x0410, 0x0010, 0x07A0, 0x0BA0, 0x03A0, + 0x0240, 0x1C40, 0x0C40, 0x1440, 0x0440, 0x1840, 0x0840, 0x1040, + 0x0040, 0x1F80, 0x0F80, 0x1780, 0x0780, 0x1B80, 0x0B80, 0x1380, + 0x0380, 0x1D80, 0x0D80, 0x1580, 0x0580, 0x1980, 0x0980, 0x1180, + 0x0180, 0x1E80, 0x0E80, 0x1680, 0x0680, 0x1A80, 0x0A80, 0x1280, + 0x0280, 0x1C80, 0x0C80, 0x1480, 0x0480, 0x1880, 0x0880, 0x1080, + 0x0080, 0x1F00, 0x0F00, 0x1700, 0x0700, 0x1B00, 0x0B00, 0x1300, + 0x0DA0, 0x05A0, 0x09A0, 0x01A0, 0x0EA0, 0x06A0, 0x0AA0, 0x02A0, + 0x0CA0, 0x04A0, 0x08A0, 0x00A0, 0x0F20, 0x0720, 0x0B20, 0x0320, + 0x0D20, 0x0520, 0x0920, 0x0120, 0x0E20, 0x0620, 0x0A20, 0x0220, + 0x0C20, 0x0420, 0x0820, 0x0020, 0x0FC0, 0x07C0, 0x0BC0, 0x03C0, + 0x0DC0, 0x05C0, 0x09C0, 0x01C0, 0x0EC0, 0x06C0, 0x0AC0, 0x02C0, + 0x0CC0, 0x04C0, 0x08C0, 0x00C0, 0x0F40, 0x0740, 0x0B40, 0x0340, + 0x0300, 0x0D40, 0x1D00, 0x0D00, 0x1500, 0x0540, 0x0500, 0x1900, + 0x0900, 0x0940, 0x1100, 0x0100, 0x1E00, 0x0E00, 0x0140, 0x1600, + 0x0600, 0x1A00, 0x0E40, 0x0640, 0x0A40, 0x0A00, 0x1200, 0x0200, + 0x1C00, 0x0C00, 0x1400, 0x0400, 0x1800, 0x0800, 0x1000, 0x0000 +}; + +/* Local variables */ +static char copyright[] = "PKWARE Data Compression Library for Win32\r\n" + "Copyright 1989-1995 PKWARE Inc. All Rights Reserved\r\n" + "Patent No. 5,051,745\r\n" + "PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off.\r\n" + "Version 1.11\r\n"; + +/* Local functions */ +static void libmpq_pkzip_gen_decode_tabs(long count, unsigned char *bits, unsigned char *code, unsigned char *buf2) { + long i; + + for (i = count-1; i >= 0; i--) { /* EBX - count */ + unsigned long idx1 = code[i]; + unsigned long idx2 = 1 << bits[i]; + do { + buf2[idx1] = (unsigned char)i; + idx1 += idx2; + } while (idx1 < 0x100); + } +} + +static void libmpq_pkzip_gen_asc_tabs(pkzip_data_cmp *mpq_pkzip) { + unsigned short *code_asc = &pkzip_code_asc[0xFF]; + unsigned long acc, add; + unsigned short count; + + for (count = 0x00FF; code_asc >= pkzip_code_asc; code_asc--, count--) { + unsigned char *bits_asc = mpq_pkzip->bits_asc + count; + unsigned char bits_tmp = *bits_asc; + + if (bits_tmp <= 8) { + add = (1 << bits_tmp); + acc = *code_asc; + do { + mpq_pkzip->offs_2c34[acc] = (unsigned char)count; + acc += add; + } while (acc < 0x100); + } else { + if ((acc = (*code_asc & 0xFF)) != 0) { + mpq_pkzip->offs_2c34[acc] = 0xFF; + if (*code_asc & 0x3F) { + bits_tmp -= 4; + *bits_asc = bits_tmp; + add = (1 << bits_tmp); + acc = *code_asc >> 4; + do { + mpq_pkzip->offs_2d34[acc] = (unsigned char)count; + acc += add; + } while (acc < 0x100); + } else { + bits_tmp -= 6; + *bits_asc = bits_tmp; + add = (1 << bits_tmp); + acc = *code_asc >> 6; + do { + mpq_pkzip->offs_2e34[acc] = (unsigned char)count; + acc += add; + } while (acc < 0x80); + } + } else { + bits_tmp -= 8; + *bits_asc = bits_tmp; + add = (1 << bits_tmp); + acc = *code_asc >> 8; + do { + mpq_pkzip->offs_2eb4[acc] = (unsigned char)count; + acc += add; + } while (acc < 0x100); + } + } + } +} + +/* + * Skips given number of bits in bit buffer. Result is stored in mpq_pkzip->bit_buf + * If no data in input buffer, returns true + */ +static int libmpq_pkzip_skip_bits(pkzip_data_cmp *mpq_pkzip, unsigned long bits) { + /* If number of bits required is less than number of (bits in the buffer) ? */ + if (bits <= mpq_pkzip->extra_bits) { + mpq_pkzip->extra_bits -= bits; + mpq_pkzip->bit_buf >>= bits; + return 0; + } + + /* Load input buffer if necessary */ + mpq_pkzip->bit_buf >>= mpq_pkzip->extra_bits; + if (mpq_pkzip->in_pos == mpq_pkzip->in_bytes) { + mpq_pkzip->in_pos = sizeof(mpq_pkzip->in_buf); + if ((mpq_pkzip->in_bytes = mpq_pkzip->read_buf((char *)mpq_pkzip->in_buf, &mpq_pkzip->in_pos, mpq_pkzip->param)) == 0) { + return 1; + } + mpq_pkzip->in_pos = 0; + } + + /* Update bit buffer */ + mpq_pkzip->bit_buf |= (mpq_pkzip->in_buf[mpq_pkzip->in_pos++] << 8); + mpq_pkzip->bit_buf >>= (bits - mpq_pkzip->extra_bits); + mpq_pkzip->extra_bits = (mpq_pkzip->extra_bits - bits) + 8; + return 0; +} + +/* + * Decompress the imploded data using coded literals. + * Returns: 0x000 - 0x0FF : One byte from compressed file. + * 0x100 - 0x305 : Copy previous block (0x100 = 1 byte) + * 0x306 : Out of buffer (?) + */ +static unsigned long libmpq_pkzip_explode_lit(pkzip_data_cmp *mpq_pkzip) { + unsigned long bits; /* Number of bits to skip */ + unsigned long value; /* Position in buffers */ + + /* Test the current bit in byte buffer. If is not set, simply return the next byte. */ + if (mpq_pkzip->bit_buf & 1) { + + /* Skip current bit in the buffer. */ + if (libmpq_pkzip_skip_bits(mpq_pkzip, 1)) { + return 0x306; + } + + /* The next bits are position in buffers. */ + value = mpq_pkzip->pos2[(mpq_pkzip->bit_buf & 0xFF)]; + + /* Get number of bits to skip */ + if (libmpq_pkzip_skip_bits(mpq_pkzip, mpq_pkzip->slen_bits[value])) { + return 0x306; + } + if ((bits = mpq_pkzip->clen_bits[value]) != 0) { + unsigned long val2 = mpq_pkzip->bit_buf & ((1 << bits) - 1); + if (libmpq_pkzip_skip_bits(mpq_pkzip, bits)) { + if ((value + val2) != 0x10E) { + return 0x306; + } + } + value = mpq_pkzip->len_base[value] + val2; + } + return value + 0x100; /* Return number of bytes to repeat */ + } + + /* Skip one bit */ + if (libmpq_pkzip_skip_bits(mpq_pkzip, 1)) { + return 0x306; + } + + /* If the binary compression type, read 8 bits and return them as one byte. */ + if (mpq_pkzip->cmp_type == LIBMPQ_PKZIP_CMP_BINARY) { + value = mpq_pkzip->bit_buf & 0xFF; + if (libmpq_pkzip_skip_bits(mpq_pkzip, 8)) { + return 0x306; + } + return value; + } + + /* When ASCII compression ... */ + if (mpq_pkzip->bit_buf & 0xFF) { + value = mpq_pkzip->offs_2c34[mpq_pkzip->bit_buf & 0xFF]; + if (value == 0xFF) { + if (mpq_pkzip->bit_buf & 0x3F) { + if (libmpq_pkzip_skip_bits(mpq_pkzip, 4)) { + return 0x306; + } + value = mpq_pkzip->offs_2d34[mpq_pkzip->bit_buf & 0xFF]; + } else { + if (libmpq_pkzip_skip_bits(mpq_pkzip, 6)) { + return 0x306; + } + value = mpq_pkzip->offs_2e34[mpq_pkzip->bit_buf & 0x7F]; + } + } + } else { + if (libmpq_pkzip_skip_bits(mpq_pkzip, 8)) { + return 0x306; + } + value = mpq_pkzip->offs_2eb4[mpq_pkzip->bit_buf & 0xFF]; + } + return libmpq_pkzip_skip_bits(mpq_pkzip, mpq_pkzip->bits_asc[value]) ? 0x306 : value; +} + +/* + * Retrieves the number of bytes to move back. + */ +static unsigned long libmpq_pkzip_explode_dist(pkzip_data_cmp *mpq_pkzip, unsigned long length) { + unsigned long pos = mpq_pkzip->pos1[(mpq_pkzip->bit_buf & 0xFF)]; + unsigned long skip = mpq_pkzip->dist_bits[pos]; /* Number of bits to skip */ + + /* Skip the appropriate number of bits */ + if (libmpq_pkzip_skip_bits(mpq_pkzip, skip) == 1) { + return 0; + } + if (length == 2) { + pos = (pos << 2) | (mpq_pkzip->bit_buf & 0x03); + if (libmpq_pkzip_skip_bits(mpq_pkzip, 2) == 1) { + return 0; + } + } else { + pos = (pos << mpq_pkzip->dsize_bits) | (mpq_pkzip->bit_buf & mpq_pkzip->dsize_mask); + + /* Skip the bits */ + if (libmpq_pkzip_skip_bits(mpq_pkzip, mpq_pkzip->dsize_bits) == 1) { + return 0; + } + } + return pos + 1; +} + +static unsigned long libmpq_pkzip_expand(pkzip_data_cmp *mpq_pkzip) { + unsigned int copy_bytes; /* Number of bytes to copy */ + unsigned long one_byte; /* One byte from compressed file */ + unsigned long result; + + mpq_pkzip->out_pos = 0x1000; /* Initialize output buffer position */ + + /* If end of data or error, terminate decompress */ + while ((result = one_byte = libmpq_pkzip_explode_lit(mpq_pkzip)) < 0x305) { + + /* If one byte is greater than 0x100, means "Repeat n - 0xFE bytes" */ + if (one_byte >= 0x100) { + unsigned char *source; /* ECX */ + unsigned char *target; /* EDX */ + unsigned long copy_length = one_byte - 0xFE; + unsigned long move_back; + + /* Get length of data to copy */ + if ((move_back = libmpq_pkzip_explode_dist(mpq_pkzip, copy_length)) == 0) { + result = 0x306; + break; + } + + /* Target and source pointer */ + target = &mpq_pkzip->out_buf[mpq_pkzip->out_pos]; + source = target - move_back; + mpq_pkzip->out_pos += copy_length; + while (copy_length-- > 0) { + *target++ = *source++; + } + } else { + mpq_pkzip->out_buf[mpq_pkzip->out_pos++] = (unsigned char)one_byte; + } + + /* + * If number of extracted bytes has reached 1/2 of output buffer, + * flush output buffer. + */ + if (mpq_pkzip->out_pos >= 0x2000) { + + /* Copy decompressed data into user buffer. */ + copy_bytes = 0x1000; + mpq_pkzip->write_buf((char *)&mpq_pkzip->out_buf[0x1000], ©_bytes, mpq_pkzip->param); + + /* If there are some data left, keep them alive */ + memcpy(mpq_pkzip->out_buf, &mpq_pkzip->out_buf[0x1000], mpq_pkzip->out_pos - 0x1000); + mpq_pkzip->out_pos -= 0x1000; + } + } + copy_bytes = mpq_pkzip->out_pos - 0x1000; + mpq_pkzip->write_buf((char *)&mpq_pkzip->out_buf[0x1000], ©_bytes, mpq_pkzip->param); + return result; +} + +/* + * Main exploding function. + */ +unsigned int libmpq_pkzip_explode( + unsigned int (*read_buf)(char *buf, unsigned int *size, void *param), + void (*write_buf)(char *buf, unsigned int *size, void *param), + char *work_buf, + void *param) { + + pkzip_data_cmp *mpq_pkzip = (pkzip_data_cmp *)work_buf; + + /* Set the whole work buffer to zeros */ + memset(mpq_pkzip, 0, sizeof(pkzip_data_cmp)); + + /* Initialize work struct and load compressed data */ + mpq_pkzip->read_buf = read_buf; + mpq_pkzip->write_buf = write_buf; + mpq_pkzip->param = param; + mpq_pkzip->in_pos = sizeof(mpq_pkzip->in_buf); + mpq_pkzip->in_bytes = mpq_pkzip->read_buf((char *)mpq_pkzip->in_buf, &mpq_pkzip->in_pos, mpq_pkzip->param); + if (mpq_pkzip->in_bytes <= 4) { + return LIBMPQ_PKZIP_CMP_BAD_DATA; + } + mpq_pkzip->cmp_type = mpq_pkzip->in_buf[0]; /* Get the compression type */ + mpq_pkzip->dsize_bits = mpq_pkzip->in_buf[1]; /* Get the dictionary size */ + mpq_pkzip->bit_buf = mpq_pkzip->in_buf[2]; /* Initialize 16-bit bit buffer */ + mpq_pkzip->extra_bits = 0; /* Extra (over 8) bits */ + mpq_pkzip->in_pos = 3; /* Position in input buffer */ + + /* Test for the valid dictionary size */ + if (4 > mpq_pkzip->dsize_bits || mpq_pkzip->dsize_bits > 6) { + return LIBMPQ_PKZIP_CMP_INV_DICTSIZE; + } + mpq_pkzip->dsize_mask = 0xFFFF >> (0x10 - mpq_pkzip->dsize_bits); /* Shifted by 'sar' instruction */ + if (mpq_pkzip->cmp_type != LIBMPQ_PKZIP_CMP_BINARY) { + if (mpq_pkzip->cmp_type != LIBMPQ_PKZIP_CMP_ASCII) { + return LIBMPQ_PKZIP_CMP_INV_MODE; + } + memcpy(mpq_pkzip->bits_asc, pkzip_bits_asc, sizeof(mpq_pkzip->bits_asc)); + libmpq_pkzip_gen_asc_tabs(mpq_pkzip); + } + memcpy(mpq_pkzip->slen_bits, pkzip_slen_bits, sizeof(mpq_pkzip->slen_bits)); + libmpq_pkzip_gen_decode_tabs(0x10, mpq_pkzip->slen_bits, pkzip_len_code, mpq_pkzip->pos2); + memcpy(mpq_pkzip->clen_bits, pkzip_clen_bits, sizeof(mpq_pkzip->clen_bits)); + memcpy(mpq_pkzip->len_base, pkzip_len_base, sizeof(mpq_pkzip->len_base)); + memcpy(mpq_pkzip->dist_bits, pkzip_dist_bits, sizeof(mpq_pkzip->dist_bits)); + libmpq_pkzip_gen_decode_tabs(0x40, mpq_pkzip->dist_bits, pkzip_dist_code, mpq_pkzip->pos1); + if (libmpq_pkzip_expand(mpq_pkzip) != 0x306) { + return LIBMPQ_PKZIP_CMP_NO_ERROR; + } + return LIBMPQ_PKZIP_CMP_ABORT; +} diff --git a/contrib/extractor/libmpq/explode.h b/contrib/extractor/libmpq/explode.h new file mode 100644 index 00000000000..1f916f778ae --- /dev/null +++ b/contrib/extractor/libmpq/explode.h @@ -0,0 +1,86 @@ +/* + * explode.h -- header file for PKWARE data decompression library + * used by mpq-tools. + * + * Copyright (C) 2003 Maik Broemme + * + * This source was adepted from the C++ version of pklib.h included + * in stormlib. The C++ version belongs to the following authors, + * + * Ladislav Zezula + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _EXPLODE_H +#define _EXPLODE_H + +#define LIBMPQ_PKZIP_EXP_BUFFER_SIZE 12596 /* Size of decompress buffer */ +#define LIBMPQ_PKZIP_CMP_BINARY 0 /* Binary compression */ +#define LIBMPQ_PKZIP_CMP_ASCII 1 /* Ascii compression */ +#define LIBMPQ_PKZIP_CMP_NO_ERROR 0 +#define LIBMPQ_PKZIP_CMP_INV_DICTSIZE 1 +#define LIBMPQ_PKZIP_CMP_INV_MODE 2 +#define LIBMPQ_PKZIP_CMP_BAD_DATA 3 +#define LIBMPQ_PKZIP_CMP_ABORT 4 + +/* Compression structure (size: 12596 bytes on x86-32) */ +typedef struct { + unsigned long offs0000; /* 0000 */ + unsigned long cmp_type; /* 0004 - Compression type (LIBMPQ_PZIP_CMP_BINARY or LIBMPQ_PKZIP_CMP_ASCII) */ + unsigned long out_pos; /* 0008 - Position in output buffer */ + unsigned long dsize_bits; /* 000C - Dict size (4, 5, 6 for 0x400, 0x800, 0x1000) */ + unsigned long dsize_mask; /* 0010 - Dict size bitmask (0x0F, 0x1F, 0x3F for 0x400, 0x800, 0x1000) */ + unsigned long bit_buf; /* 0014 - 16-bit buffer for processing input data */ + unsigned long extra_bits; /* 0018 - Number of extra (above 8) bits in bit buffer */ + unsigned int in_pos; /* 001C - Position in in_buf */ + unsigned long in_bytes; /* 0020 - Number of bytes in input buffer */ + void *param; /* 0024 - Custom parameter */ + unsigned int (*read_buf)(char *buf, unsigned int *size, void *param); /* 0028 */ + void (*write_buf)(char *buf, unsigned int *size, void *param); /* 002C */ + unsigned char out_buf[0x2000]; /* 0030 - Output circle buffer. Starting position is 0x1000 */ + unsigned char offs_2030[0x204]; /* 2030 - ??? */ + unsigned char in_buf[0x800]; /* 2234 - Buffer for data to be decompressed */ + unsigned char pos1[0x100]; /* 2A34 - Positions in buffers */ + unsigned char pos2[0x100]; /* 2B34 - Positions in buffers */ + unsigned char offs_2c34[0x100]; /* 2C34 - Buffer for */ + unsigned char offs_2d34[0x100]; /* 2D34 - Buffer for */ + unsigned char offs_2e34[0x80]; /* 2EB4 - Buffer for */ + unsigned char offs_2eb4[0x100]; /* 2EB4 - Buffer for */ + unsigned char bits_asc[0x100]; /* 2FB4 - Buffer for */ + unsigned char dist_bits[0x40]; /* 30B4 - Numbers of bytes to skip copied block length */ + unsigned char slen_bits[0x10]; /* 30F4 - Numbers of bits for skip copied block length */ + unsigned char clen_bits[0x10]; /* 3104 - Number of valid bits for copied block */ + unsigned short len_base[0x10]; /* 3114 - Buffer for */ +} pkzip_data_cmp; +// __attribute__ ((packed)) pkzip_data_cmp; + +typedef struct { + char *in_buf; /* Pointer to input data buffer */ + unsigned int in_pos; /* Current offset in input data buffer */ + int in_bytes; /* Number of bytes in the input buffer */ + char *out_buf; /* Pointer to output data buffer */ + unsigned int out_pos; /* Position in the output buffer */ + int max_out; /* Maximum number of bytes in the output buffer */ +} pkzip_data; + +extern unsigned int libmpq_pkzip_explode( + unsigned int (*read_buf)(char *buf, unsigned int *size, void *param), + void (*write_buf)(char *buf, unsigned int *size, void *param), + char *work_buf, + void *param +); + +#endif /* _EXPLODE_H */ diff --git a/contrib/extractor/libmpq/extract.cpp b/contrib/extractor/libmpq/extract.cpp new file mode 100644 index 00000000000..41472b3c426 --- /dev/null +++ b/contrib/extractor/libmpq/extract.cpp @@ -0,0 +1,262 @@ +/* + * extract.c -- global extracting function for all known file compressions + * in a MPQ archive. + * + * Copyright (C) 2003 Maik Broemme + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#define HAVE_LIBZ +#ifdef HAVE_LIBZ +#include +#endif + +#include "mpq.h" +#include "explode.h" +#include "huffman.h" + +#include "wave.h" + +/* + * Support functions for PKWARE data compression library. + * + * Function loads data from the input buffer. Used by mpq_pkzip + * "implode" and "explode" function as user-defined callback. + * Returns number of bytes loaded. + * + * char * buf - Pointer to a buffer where to store loaded data + * unsigned int * size - Max. number of bytes to read + * void * param - Custom pointer, parameter of implode/explode + */ +static unsigned int libmpq_pkzip_read_input_data(char *buf, unsigned int *size, void *param) { + pkzip_data *info = (pkzip_data *)param; + unsigned int max_avail = (info->in_bytes - info->in_pos); + unsigned int to_read = *size; + + /* Check the case when not enough data available */ + if (to_read > max_avail) { + to_read = max_avail; + } + + /* Load data and increment offsets */ + memcpy(buf, info->in_buf + info->in_pos, to_read); + info->in_pos += to_read; + + return to_read; +} + +/* + * Support functions for PKWARE data compression library. + * + * Function for store output data. Used by mpq_pkzip "implode" and + * "explode" as user-defined callback. + * + * char * buf - Pointer to data to be written + * unsigned int * size - Number of bytes to write + * void * param - Custom pointer, parameter of implode/explode + */ +static void libmpq_pkzip_write_output_data(char *buf, unsigned int *size, void *param) { + pkzip_data *info = (pkzip_data *)param; + unsigned int max_write = (info->max_out - info->out_pos); + unsigned int to_write = *size; + + /* Check the case when not enough space in the output buffer */ + if (to_write > max_write) { + to_write = max_write; + } + + /* Write output data and increments offsets */ + memcpy(info->out_buf + info->out_pos, buf, to_write); + info->out_pos += to_write; +} + +int libmpq_pkzip_decompress(char *out_buf, int *out_length, char *in_buf, int in_length) { + pkzip_data info; /* Data information */ + char *work_buf = (char *)malloc(LIBMPQ_PKZIP_EXP_BUFFER_SIZE); /* mpq_pkzip work buffer */ + + /* Fill data information structure */ + info.in_buf = in_buf; + info.in_pos = 0; + info.in_bytes = in_length; + info.out_buf = out_buf; + info.out_pos = 0; + info.max_out = *out_length; + + /* Do the decompression */ + libmpq_pkzip_explode(libmpq_pkzip_read_input_data, libmpq_pkzip_write_output_data, work_buf, &info); + *out_length = info.out_pos; + free(work_buf); + return 0; +} + +int libmpq_wave_decompress_mono(char *out_buf, int *out_length, char *in_buf, int in_length) { + *out_length = libmpq_wave_decompress((unsigned char *)out_buf, *out_length, (unsigned char *)in_buf, in_length, 1); + return 1; +} + +int libmpq_wave_decompress_stereo(char *out_buf, int *out_length, char *in_buf, int in_length) { + *out_length = libmpq_wave_decompress((unsigned char *)out_buf, *out_length, (unsigned char *)in_buf, in_length, 2); + return 1; +} + +int libmpq_zlib_decompress(char *out_buf, int *out_length, char *in_buf, int in_length) { +#ifdef HAVE_LIBZ + z_stream z; /* Stream information for zlib */ + int result; + + /* Fill the stream structure for zlib */ + z.next_in = (Bytef *)in_buf; + z.avail_in = (uInt)in_length; + z.total_in = in_length; + z.next_out = (Bytef *)out_buf; + z.avail_out = *out_length; + z.total_out = 0; + z.zalloc = NULL; + z.zfree = NULL; + + /* Initialize the decompression structure. Storm.dll uses zlib version 1.1.3 */ + if ((result = inflateInit(&z)) == 0) { + + /* Call zlib to decompress the data */ + result = inflate(&z, Z_FINISH); + *out_length = z.total_out; + inflateEnd(&z); + } + return result; +#else + memset(out_buf, '0', *out_length); + return 0; +#endif +} + +/* + * Huffmann decompression routine. The in_length parameter is not used, but needs + * to be specified due to compatibility reasons. + * + * 1500F5F0 + */ +int libmpq_huff_decompress(char *out_buf, int *out_length, char *in_buf, int in_length) { + struct huffman_tree *ht = (huffman_tree *)malloc(sizeof(struct huffman_tree)); + struct huffman_input_stream *is = (huffman_input_stream *)malloc(sizeof(struct huffman_input_stream)); + struct huffman_tree_item *hi = (huffman_tree_item *)malloc(sizeof(struct huffman_tree_item)); + memset(ht, 0, sizeof(struct huffman_tree)); + memset(is, 0, sizeof(struct huffman_input_stream)); + memset(hi, 0, sizeof(struct huffman_tree_item)); + + /* Initialize input stream */ + is->bit_buf = *(unsigned long *)in_buf; + in_buf += sizeof(unsigned long); + is->in_buf = (unsigned char *)in_buf; + is->bits = 32; + + /* Initialize the Huffmann tree for decompression */ + libmpq_huff_init_tree(ht, hi, LIBMPQ_HUFF_DECOMPRESS); + + *out_length = libmpq_huff_do_decompress(ht, is, (unsigned char *)out_buf, *out_length); + + free(hi); + free(is); + free(ht); + return 0; +} + +int libmpq_multi_decompress(char *out_buf, int *pout_length, char *in_buf, int in_length) { + char *temp_buf = NULL; /* Temporary storage for decompressed data */ + char *work_buf = NULL; /* Where to store decompressed data */ + int out_length = *pout_length; /* For storage number of output bytes */ + unsigned fDecompressions1; /* Decompressions applied to the block */ + unsigned fDecompressions2; /* Just another copy of decompressions applied to the block */ + int count = 0; /* Counter for every use */ + int entries = (sizeof(dcmp_table) / sizeof(decompress_table)); + int i; + + /* If the input length is the same as output, do nothing. */ + if (in_length == out_length) { + if (in_buf == out_buf) { + return 1; + } + memcpy(out_buf, in_buf, in_length); + return 1; + } + + /* Get applied compression types and decrement data length */ + fDecompressions1 = fDecompressions2 = (unsigned char)*in_buf++; + in_length--; + + /* Search decompression table type and get all types of compression */ + for (i = 0; i < entries; i++) { + /* We have to apply this decompression? */ + if (fDecompressions1 & dcmp_table[i].mask) { + count++; + } + + /* Clear this flag from temporary variable. */ + fDecompressions2 &= ~dcmp_table[i].mask; + } + + /* + * Check if there is some method unhandled + * (E.g. compressed by future versions) + */ + if (fDecompressions2 != 0) { + printf("Unknown Compression\n"); + return 0; + } + + /* If there is more than only one compression, we have to allocate extra buffer */ + if (count >= 2) { + temp_buf = (char *)malloc(out_length); + } + + /* Apply all decompressions */ + for (i = 0, count = 0; i < entries; i++) { + + /* If not used this kind of compression, skip the loop */ + if (fDecompressions1 & dcmp_table[i].mask) { + + /* If odd case, use target buffer for output, otherwise use allocated tempbuf */ + work_buf = (count++ & 1) ? temp_buf : out_buf; + out_length = *pout_length; + + /* Decompress buffer using corresponding function */ + dcmp_table[i].decompress(work_buf, &out_length, in_buf, in_length); + + /* Move output length to src length for next compression */ + in_length = out_length; + in_buf = work_buf; + } + } + + /* If output buffer is not the same like target buffer, we have to copy data */ + if (work_buf != out_buf) { + memcpy(out_buf, in_buf, out_length); + } + *pout_length = out_length; + + /* Delete temporary buffer, if necessary */ + if (temp_buf != NULL) { + free(temp_buf); + } + return 1; +} diff --git a/contrib/extractor/libmpq/huffman.cpp b/contrib/extractor/libmpq/huffman.cpp new file mode 100644 index 00000000000..b63eee43e42 --- /dev/null +++ b/contrib/extractor/libmpq/huffman.cpp @@ -0,0 +1,833 @@ +/* + * huffman.c -- functions do decompress files in MPQ files which + * uses a modified huffman version. + * + * Copyright (C) 2003 Maik Broemme + * + * Differences between C++ and C version: + * + * - Removed the object oriented stuff. + * - Replaced the goto things with some better C code. + * + * This source was adepted from the C++ version of huffman.cpp included + * in stormlib. The C++ version belongs to the following authors, + * + * Ladislav Zezula + * ShadowFlare + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#include +#include + +#include "mpq.h" +#include "huffman.h" + +unsigned char table1502A630[] = { + + /* Data for compression type 0x00 */ + 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, + + /* Data for compression type 0x01 */ + 0x54, 0x16, 0x16, 0x0D, 0x0C, 0x08, 0x06, 0x05, 0x06, 0x05, 0x06, 0x03, 0x04, 0x04, 0x03, 0x05, + 0x0E, 0x0B, 0x14, 0x13, 0x13, 0x09, 0x0B, 0x06, 0x05, 0x04, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02, + 0x0D, 0x07, 0x09, 0x06, 0x06, 0x04, 0x03, 0x02, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, + 0x09, 0x06, 0x04, 0x04, 0x04, 0x04, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x04, + 0x08, 0x03, 0x04, 0x07, 0x09, 0x05, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, + 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, + 0x06, 0x0A, 0x08, 0x08, 0x06, 0x07, 0x04, 0x03, 0x04, 0x04, 0x02, 0x02, 0x04, 0x02, 0x03, 0x03, + 0x04, 0x03, 0x07, 0x07, 0x09, 0x06, 0x04, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x0A, 0x02, 0x02, 0x03, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x06, 0x03, 0x05, 0x02, 0x03, + 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x03, 0x01, 0x01, 0x01, + 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x04, 0x04, 0x04, 0x07, 0x09, 0x08, 0x0C, 0x02, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x03, + 0x04, 0x01, 0x02, 0x04, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, + 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x06, 0x4B, + 0x00, 0x00, + + /* Data for compression type 0x02 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x27, 0x00, 0x00, 0x23, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x06, 0x0E, 0x10, 0x04, + 0x06, 0x08, 0x05, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 0x01, 0x01, 0x02, 0x01, 0x01, + 0x01, 0x04, 0x02, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01, 0x04, 0x01, 0x01, 0x02, 0x03, 0x03, 0x02, + 0x03, 0x01, 0x03, 0x06, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x01, 0x01, + 0x01, 0x29, 0x07, 0x16, 0x12, 0x40, 0x0A, 0x0A, 0x11, 0x25, 0x01, 0x03, 0x17, 0x10, 0x26, 0x2A, + 0x10, 0x01, 0x23, 0x23, 0x2F, 0x10, 0x06, 0x07, 0x02, 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + + /* Data for compression type 0x03 */ + 0xFF, 0x0B, 0x07, 0x05, 0x0B, 0x02, 0x02, 0x02, 0x06, 0x02, 0x02, 0x01, 0x04, 0x02, 0x01, 0x03, + 0x09, 0x01, 0x01, 0x01, 0x03, 0x04, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, + 0x05, 0x01, 0x01, 0x01, 0x0D, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x0A, 0x04, 0x02, 0x01, 0x06, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, + 0x05, 0x02, 0x03, 0x04, 0x03, 0x03, 0x03, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x03, 0x03, + 0x01, 0x03, 0x01, 0x01, 0x02, 0x05, 0x01, 0x01, 0x04, 0x03, 0x05, 0x01, 0x03, 0x01, 0x03, 0x03, + 0x02, 0x01, 0x04, 0x03, 0x0A, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x01, 0x0A, 0x02, 0x05, 0x01, 0x01, 0x02, 0x07, 0x02, 0x17, 0x01, 0x05, 0x01, 0x01, + 0x0E, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x06, 0x02, 0x01, 0x04, 0x05, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x11, + 0x00, 0x00, + + /* Data for compression type 0x04 */ + 0xFF, 0xFB, 0x98, 0x9A, 0x84, 0x85, 0x63, 0x64, 0x3E, 0x3E, 0x22, 0x22, 0x13, 0x13, 0x18, 0x17, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + + /* Data for compression type 0x05 */ + 0xFF, 0xF1, 0x9D, 0x9E, 0x9A, 0x9B, 0x9A, 0x97, 0x93, 0x93, 0x8C, 0x8E, 0x86, 0x88, 0x80, 0x82, + 0x7C, 0x7C, 0x72, 0x73, 0x69, 0x6B, 0x5F, 0x60, 0x55, 0x56, 0x4A, 0x4B, 0x40, 0x41, 0x37, 0x37, + 0x2F, 0x2F, 0x27, 0x27, 0x21, 0x21, 0x1B, 0x1C, 0x17, 0x17, 0x13, 0x13, 0x10, 0x10, 0x0D, 0x0D, + 0x0B, 0x0B, 0x09, 0x09, 0x08, 0x08, 0x07, 0x07, 0x06, 0x05, 0x05, 0x04, 0x04, 0x04, 0x19, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + + /* Data for compression type 0x06 */ + 0xC3, 0xCB, 0xF5, 0x41, 0xFF, 0x7B, 0xF7, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xBF, 0xCC, 0xF2, 0x40, 0xFD, 0x7C, 0xF7, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7A, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + + /* Data for compression type 0x07 */ + 0xC3, 0xD9, 0xEF, 0x3D, 0xF9, 0x7C, 0xE9, 0x1E, 0xFD, 0xAB, 0xF1, 0x2C, 0xFC, 0x5B, 0xFE, 0x17, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xBD, 0xD9, 0xEC, 0x3D, 0xF5, 0x7D, 0xE8, 0x1D, 0xFB, 0xAE, 0xF0, 0x2C, 0xFB, 0x5C, 0xFF, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x70, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + + /* Data for compression type 0x08 */ + 0xBA, 0xC5, 0xDA, 0x33, 0xE3, 0x6D, 0xD8, 0x18, 0xE5, 0x94, 0xDA, 0x23, 0xDF, 0x4A, 0xD1, 0x10, + 0xEE, 0xAF, 0xE4, 0x2C, 0xEA, 0x5A, 0xDE, 0x15, 0xF4, 0x87, 0xE9, 0x21, 0xF6, 0x43, 0xFC, 0x12, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xB0, 0xC7, 0xD8, 0x33, 0xE3, 0x6B, 0xD6, 0x18, 0xE7, 0x95, 0xD8, 0x23, 0xDB, 0x49, 0xD0, 0x11, + 0xE9, 0xB2, 0xE2, 0x2B, 0xE8, 0x5C, 0xDD, 0x15, 0xF1, 0x87, 0xE7, 0x20, 0xF7, 0x44, 0xFF, 0x13, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x5F, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 +}; + +/* Gets previous Huffman tree item (?) */ +struct huffman_tree_item *libmpq_huff_get_prev_item(struct huffman_tree_item *hi, long value) { + if (PTR_INT(hi->prev) < 0) { + return PTR_NOT(hi->prev); + } + if (value < 0) { + value = hi - hi->next->prev; + } + return hi->prev + value; +} + +/* 1500BC90 */ +static void libmpq_huff_remove_item(struct huffman_tree_item *hi) { + struct huffman_tree_item *temp; /* EDX */ + + if (hi->next != NULL) { + temp = hi->prev; + if (PTR_INT(temp) <= 0) { + temp = PTR_NOT(temp); + } else { + temp += (hi - hi->next->prev); + } + temp->next = hi->next; + hi->next->prev = hi->prev; + hi->next = hi->prev = NULL; + } +} + +static void libmpq_huff_insert_item(struct huffman_tree_item **p_item, struct huffman_tree_item *item, unsigned long where, struct huffman_tree_item *item2) { + struct huffman_tree_item *next = item->next; /* EDI - next to the first item */ + struct huffman_tree_item *prev = item->prev; /* ESI - prev to the first item */ + struct huffman_tree_item *prev2; /* Pointer to previous item */ + long next2; /* Pointer to the next item */ + + /* The same code like in mpq_huff_remove_item(); */ + if (next != 0) { /* If the first item already has next one */ + if (PTR_INT(prev) < 0) { + prev = PTR_NOT(prev); + } else { + prev += (item - next->prev); + } + + /* + * 150083C1 + * Remove the item from the tree + */ + prev->next = next; + next->prev = prev; + + /* Invalidate 'prev' and 'next' pointer */ + item->next = 0; + item->prev = 0; + } + + if (item2 == NULL) { /* EDX - If the second item is not entered, */ + item2 = PTR_PTR(&p_item[1]); /* take the first tree item */ + } + + switch (where) { + case SWITCH_ITEMS: /* Switch the two items */ + item->next = item2->next; /* item2->next (Pointer to pointer to first) */ + item->prev = item2->next->prev; + item2->next->prev = item; + item2->next = item; /* Set the first item */ + return; + case INSERT_ITEM: /* Insert as the last item */ + item->next = item2; /* Set next item (or pointer to pointer to first item) */ + item->prev = item2->prev; /* Set prev item (or last item in the tree) */ + next2 = PTR_INT(p_item[0]); /* Usually NULL */ + prev2 = item2->prev; /* Prev item to the second (or last tree item) */ + if (PTR_INT(prev2) < 0) { + prev2 = PTR_NOT(prev); + prev2->next = item; + item2->prev = item; /* Next after last item */ + return; + } + if (next2 < 0) { + next2 = item2 - item2->next->prev; + } + prev2 += next2; + prev2->next = item; + item2->prev = item; /* Set the next/last item */ + return; + default: + return; + } +} + +/* Builds Huffman tree. Called with the first 8 bits loaded from input stream. */ +static void libmpq_huff_build_tree(struct huffman_tree *ht, unsigned int cmp_type) { + unsigned long max_byte; /* [ESP+10] - The greatest character found in table */ + unsigned char *byte_array; /* [ESP+1C] - Pointer to unsigned char in table1502A630 */ + unsigned long i; /* egcs in linux doesn't like multiple for loops without an explicit i */ + unsigned int found; /* Thats needed to replace the goto stuff from original source :) */ + struct huffman_tree_item **p_item; /* [ESP+14] - Pointer to Huffman tree item pointer array */ + struct huffman_tree_item *child1; + + /* Loop while pointer has a negative value. */ + while (PTR_INT(ht->last) > 0) { /* ESI - Last entry */ + struct huffman_tree_item *temp; /* EAX */ + + if (ht->last->next != NULL) { /* ESI->next */ + libmpq_huff_remove_item(ht->last); + } + ht->item3058 = PTR_PTR(&ht->item3054);/* [EDI+4] */ + ht->last->prev = ht->item3058; /* EAX */ + temp = libmpq_huff_get_prev_item(PTR_PTR(&ht->item3054), PTR_INT(&ht->item3050)); + temp->next = ht->last; + ht->item3054 = ht->last; + } + + /* Clear all pointers in huffman tree item array. */ + memset(ht->items306C, 0, sizeof(ht->items306C)); + + max_byte = 0; /* Greatest character found init to zero. */ + p_item = (struct huffman_tree_item **)&ht->items306C; /* Pointer to current entry in huffman tree item pointer array */ + + /* Ensure we have low 8 bits only */ + cmp_type &= 0xFF; + byte_array = table1502A630 + cmp_type * 258; /* EDI also */ + + for (i = 0; i < 0x100; i++, p_item++) { + struct huffman_tree_item *item = ht->item3058; /* Item to be created */ + struct huffman_tree_item *p_item3 = ht->item3058; + unsigned char one_byte = byte_array[i]; + + /* Skip all the bytes which are zero. */ + if (byte_array[i] == 0) { + continue; + } + + /* If not valid pointer, take the first available item in the array. */ + if (PTR_INT(item) <= 0) { + item = &ht->items0008[ht->items++]; + } + + /* Insert this item as the top of the tree. */ + libmpq_huff_insert_item(&ht->item305C, item, SWITCH_ITEMS, NULL); + + item->parent = NULL; /* Invalidate child and parent */ + item->child = NULL; + *p_item = item; /* Store pointer into pointer array */ + + item->dcmp_byte = i; /* Store counter */ + item->byte_value = one_byte; /* Store byte value */ + if (one_byte >= max_byte) { + max_byte = one_byte; + continue; + } + + /* Find the first item which has byte value greater than current one byte */ + found = 0; + if (PTR_INT((p_item3 = ht->last)) > 0) {/* EDI - Pointer to the last item */ + + /* 15006AF7 */ + if (p_item3 != NULL) { + do { /* 15006AFB */ + if (p_item3->byte_value >= one_byte) { + found = 1; + break; + } + p_item3 = p_item3->prev; + } while (PTR_INT(p_item3) > 0); + } + } + + if (found == 0) { + p_item3 = NULL; + } + + /* 15006B09 */ + if (item->next != NULL) { + libmpq_huff_remove_item(item); + } + + /* 15006B15 */ + if (p_item3 == NULL) { + p_item3 = PTR_PTR(&ht->first); + } + + /* 15006B1F */ + item->next = p_item3->next; + item->prev = p_item3->next->prev; + p_item3->next->prev = item; + p_item3->next = item; + } + + /* 15006B4A */ + for (; i < 0x102; i++) { + struct huffman_tree_item **p_item2 = &ht->items306C[i]; /* EDI */ + + /* 15006B59 */ + struct huffman_tree_item *item2 = ht->item3058; /* ESI */ + if (PTR_INT(item2) <= 0) { + item2 = &ht->items0008[ht->items++]; + } + libmpq_huff_insert_item(&ht->item305C, item2, INSERT_ITEM, NULL); + + /* 15006B89 */ + item2->dcmp_byte = i; + item2->byte_value = 1; + item2->parent = NULL; + item2->child = NULL; + *p_item2++ = item2; + } + + /* 15006BAA */ + if (PTR_INT((child1 = ht->last)) > 0) { /* EDI - last item (first child to item */ + struct huffman_tree_item *child2; /* EBP */ + struct huffman_tree_item *item; /* ESI */ + + /* 15006BB8 */ + while (PTR_INT((child2 = child1->prev)) > 0) { + if (PTR_INT((item = ht->item3058)) <= 0) { + item = &ht->items0008[ht->items++]; + } + /* 15006BE3 */ + libmpq_huff_insert_item(&ht->item305C, item, SWITCH_ITEMS, NULL); + + /* 15006BF3 */ + item->parent = NULL; + item->child = NULL; + + /* + * EDX = child2->byte_value + child1->byte_value; + * EAX = child1->byte_value; + * ECX = max_byte; The greatest character (0xFF usually) + */ + item->byte_value = child1->byte_value + child2->byte_value; /* 0x02 */ + item->child = child1; /* Prev item in the */ + child1->parent = item; + child2->parent = item; + + /* EAX = item->byte_value; */ + if (item->byte_value >= max_byte) { + max_byte = item->byte_value; + } else { + struct huffman_tree_item *p_item2 = child2->prev; /* EDI */ + found = 0; + if (PTR_INT(p_item2) > 0) { + + /* 15006C2D */ + do { + if (p_item2->byte_value >= item->byte_value) { + found = 1; + break; + } + p_item2 = p_item2->prev; + } while (PTR_INT(p_item2) > 0); + } + if (found == 0) { + p_item2 = NULL; + } + if (item->next != 0) { + struct huffman_tree_item *temp4 = libmpq_huff_get_prev_item(item, -1); + temp4->next = item->next; /* The first item changed */ + item->next->prev = item->prev; /* First->prev changed to negative value */ + item->next = NULL; + item->prev = NULL; + } + + /* 15006C62 */ + if (p_item2 == NULL) { + p_item2 = PTR_PTR(&ht->first); + } + item->next = p_item2->next; /* Set item with 0x100 byte value */ + item->prev = p_item2->next->prev; /* Set item with 0x17 byte value */ + p_item2->next->prev = item; /* Changed prev of item with */ + p_item2->next = item; + } + + /* 15006C7B */ + if (PTR_INT((child1 = child2->prev)) <= 0) { + break; + } + } + } + + /* 15006C88 */ + ht->offs0004 = 1; +} + +/* Gets the whole byte from the input stream. */ +static unsigned long libmpq_huff_get_8bits(struct huffman_input_stream *is) { + unsigned long one_byte; + + if (is->bits <= 8) { + is->bit_buf |= *(unsigned short *)is->in_buf << is->bits; + is->in_buf += sizeof(unsigned short); + is->bits += 16; + } + + one_byte = (is->bit_buf & 0xFF); + is->bit_buf >>= 8; + is->bits -= 8; + + return one_byte; +} + +/* Gets 7 bits from the stream. */ +static unsigned long libmpq_huff_get_7bits(struct huffman_input_stream *is) { + if (is->bits <= 7) { + is->bit_buf |= *(unsigned short *)is->in_buf << is->bits; + is->in_buf += sizeof(unsigned short); + is->bits += 16; + } + + /* Get 7 bits from input stream. */ + return (is->bit_buf & 0x7F); +} + +/* Gets one bit from input stream. */ +unsigned long libmpq_huff_get_bit(struct huffman_input_stream *is) { + unsigned long bit = (is->bit_buf & 1); + + is->bit_buf >>= 1; + if (--is->bits == 0) { + is->bit_buf = *(unsigned long *)is->in_buf; + is->in_buf += sizeof(unsigned long); + is->bits = 32; + } + return bit; +} + +static struct huffman_tree_item *libmpq_huff_call1500E740(struct huffman_tree *ht, unsigned int value) { + struct huffman_tree_item *p_item1 = ht->item3058; /* EDX */ + struct huffman_tree_item *p_item2; /* EAX */ + struct huffman_tree_item *p_next; + struct huffman_tree_item *p_prev; + struct huffman_tree_item **pp_item; + + if (PTR_INT(p_item1) <= 0 || (p_item2 = p_item1) == NULL) { + if((p_item2 = &ht->items0008[ht->items++]) != NULL) { + p_item1 = p_item2; + } else { + p_item1 = ht->first; + } + } else { + p_item1 = p_item2; + } + + p_next = p_item1->next; + if (p_next != NULL) { + p_prev = p_item1->prev; + if (PTR_INT(p_prev) <= 0) { + p_prev = PTR_NOT(p_prev); + } else { + p_prev += (p_item1 - p_item1->next->prev); + } + + p_prev->next = p_next; + p_next->prev = p_prev; + p_item1->next = NULL; + p_item1->prev = NULL; + } + pp_item = &ht->first; /* ESI */ + if (value > 1) { + + /* ECX = ht->first->next; */ + p_item1->next = *pp_item; + p_item1->prev = (*pp_item)->prev; + + (*pp_item)->prev = p_item2; + *pp_item = p_item1; + + p_item2->parent = NULL; + p_item2->child = NULL; + } else { + p_item1->next = (struct huffman_tree_item *)pp_item; + p_item1->prev = pp_item[1]; + /* EDI = ht->item305C; */ + p_prev = pp_item[1]; /* ECX */ + if (p_prev <= 0) { + p_prev = PTR_NOT(p_prev); + p_prev->next = p_item1; + p_prev->prev = p_item2; + + p_item2->parent = NULL; + p_item2->child = NULL; + } else { + if (PTR_INT(ht->item305C) < 0) { + p_prev += (struct huffman_tree_item *)pp_item - (*pp_item)->prev; + } else { + p_prev += PTR_INT(ht->item305C); + } + + p_prev->next = p_item1; + pp_item[1] = p_item2; + p_item2->parent = NULL; + p_item2->child = NULL; + } + } + return p_item2; +} + +static void libmpq_huff_call1500E820(struct huffman_tree *ht, struct huffman_tree_item *p_item) { + struct huffman_tree_item *p_item1; /* EDI */ + struct huffman_tree_item *p_item2 = NULL; /* EAX */ + struct huffman_tree_item *p_item3; /* EDX */ + struct huffman_tree_item *p_prev; /* EBX */ + + for (; p_item != NULL; p_item = p_item->parent) { + p_item->byte_value++; + + for (p_item1 = p_item; ; p_item1 = p_prev) { + p_prev = p_item1->prev; + if (PTR_INT(p_prev) <= 0) { + p_prev = NULL; + break; + } + if (p_prev->byte_value >= p_item->byte_value) { + break; + } + } + + if (p_item1 == p_item) { + continue; + } + + if (p_item1->next != NULL) { + p_item2 = libmpq_huff_get_prev_item(p_item1, -1); + p_item2->next = p_item1->next; + p_item1->next->prev = p_item1->prev; + p_item1->next = NULL; + p_item1->prev = NULL; + } + p_item2 = p_item->next; + p_item1->next = p_item2; + p_item1->prev = p_item2->prev; + p_item2->prev = p_item1; + p_item->next = p_item1; + if ((p_item2 = p_item1) != NULL) { + p_item2 = libmpq_huff_get_prev_item(p_item, -1); + p_item2->next = p_item->next; + p_item->next->prev = p_item->prev; + p_item->next = NULL; + p_item->prev = NULL; + } + + if (p_prev == NULL) { + p_prev = PTR_PTR(&ht->first); + } + p_item2 = p_prev->next; + p_item->next = p_item2; + p_item->prev = p_item2->prev; + p_item2->prev = p_item; + p_prev->next = p_item; + + p_item3 = p_item1->parent->child; + p_item2 = p_item->parent; + if (p_item2->child == p_item) { + p_item2->child = p_item1; + } + + if (p_item3 == p_item1) { + p_item1->parent->child = p_item; + } + + p_item2 = p_item->parent; + p_item->parent = p_item1->parent; + p_item1->parent = p_item2; + ht->offs0004++; + } +} + +int libmpq_huff_do_decompress(struct huffman_tree *ht, struct huffman_input_stream *is, unsigned char *out_buf, unsigned int out_length) { + unsigned int n8bits; /* 8 bits loaded from input stream */ + unsigned int n7bits; /* 7 bits loaded from input stream */ + unsigned int found; /* Thats needed to replace the goto stuff from original source :) */ + unsigned int dcmp_byte = 0; + unsigned long bit_count; + struct huffman_decompress *qd; + unsigned int has_qd; /* Can we use quick decompression? */ + struct huffman_tree_item *p_item1; + struct huffman_tree_item *p_item2; + unsigned char *out_pos = out_buf; + + /* Test the output length. Must not be non zero. */ + if (out_length == 0) { + return 0; + } + + /* Get the compression type from the input stream. */ + n8bits = libmpq_huff_get_8bits(is); + + /* Build the Huffman tree */ + libmpq_huff_build_tree(ht, n8bits); + ht->cmp0 = (n8bits == 0) ? TRUE : FALSE; + + for(;;) { + n7bits = libmpq_huff_get_7bits(is); /* Get 7 bits from input stream */ + + /* + * Try to use quick decompression. Check huffman_decompress array for corresponding item. + * If found, use the result byte instead. + */ + qd = &ht->qd3474[n7bits]; + + /* If there is a quick-pass possible (ebx) */ + has_qd = (qd->offs00 >= ht->offs0004) ? TRUE : FALSE; + + /* If we can use quick decompress, use it. */ + if (has_qd) { + found = 0; + if (qd->bits > 7) { + is->bit_buf >>= 7; + is->bits -= 7; + p_item1 = qd->p_item; + found = 1; + } + if (found == 0) { + is->bit_buf >>= qd->bits; + is->bits -= qd->bits; + dcmp_byte = qd->dcmp_byte; + } + } else { + found = 1; + p_item1 = ht->first->next->prev; + if (PTR_INT(p_item1) <= 0) { + p_item1 = NULL; + } + } + + if (found == 1) { + bit_count = 0; + p_item2 = NULL; + do { + p_item1 = p_item1->child; /* Move down by one level */ + if (libmpq_huff_get_bit(is)) { /* If current bit is set, move to previous */ + p_item1 = p_item1->prev; + } + if (++bit_count == 7) { /* If we are at 7th bit, save current huffman tree item. */ + p_item2 = p_item1; + } + } while (p_item1->child != NULL); /* Walk until tree has no deeper level */ + + if (has_qd == FALSE) { + if (bit_count > 7) { + qd->offs00 = ht->offs0004; + qd->bits = bit_count; + qd->p_item = p_item2; + } else { + unsigned long index = n7bits & (0xFFFFFFFF >> (32 - bit_count)); + unsigned long add = (1 << bit_count); + + for (qd = &ht->qd3474[index]; index <= 0x7F; index += add, qd += add) { + qd->offs00 = ht->offs0004; + qd->bits = bit_count; + qd->dcmp_byte = p_item1->dcmp_byte; + } + } + } + dcmp_byte = p_item1->dcmp_byte; + } + + if (dcmp_byte == 0x101) { /* Huffman tree needs to be modified */ + n8bits = libmpq_huff_get_8bits(is); + p_item1 = (ht->last <= 0) ? NULL : ht->last; + + p_item2 = libmpq_huff_call1500E740(ht, 1); + p_item2->parent = p_item1; + p_item2->dcmp_byte = p_item1->dcmp_byte; + p_item2->byte_value = p_item1->byte_value; + ht->items306C[p_item2->dcmp_byte] = p_item2; + + p_item2 = libmpq_huff_call1500E740(ht, 1); + p_item2->parent = p_item1; + p_item2->dcmp_byte = n8bits; + p_item2->byte_value = 0; + ht->items306C[p_item2->dcmp_byte] = p_item2; + + p_item1->child = p_item2; + libmpq_huff_call1500E820(ht, p_item2); + if (ht->cmp0 == 0) { + libmpq_huff_call1500E820(ht, ht->items306C[n8bits]); + } + dcmp_byte = n8bits; + } + + if (dcmp_byte == 0x100) { + break; + } + + *out_pos++ = (unsigned char)dcmp_byte; + if (--out_length == 0) { + break; + } + if (ht->cmp0) { + libmpq_huff_call1500E820(ht, ht->items306C[dcmp_byte]); + } + } + return (out_pos - out_buf); +} + +int libmpq_huff_init_tree(struct huffman_tree *ht, struct huffman_tree_item *hi, unsigned int cmp) { + int count; + + /* Clear links for all the items in the tree */ + for (hi = ht->items0008, count = 0x203; count != 0; hi++, count--) { + hi->next = hi->prev = NULL; + } + + ht->item3050 = NULL; + ht->item3054 = PTR_PTR(&ht->item3054); + ht->item3058 = PTR_NOT(ht->item3054); + + ht->item305C = NULL; + ht->first = PTR_PTR(&ht->first); + ht->last = PTR_NOT(ht->first); + + ht->offs0004 = 1; + ht->items = 0; + + /* Clear all huffman_decompress items. Do this only if preparing for decompression */ + if (cmp == LIBMPQ_HUFF_DECOMPRESS) { + for (count = 0; count < sizeof(ht->qd3474) / sizeof(struct huffman_decompress); count++) { + ht->qd3474[count].offs00 = 0; + } + } + + return 0; +} diff --git a/contrib/extractor/libmpq/huffman.h b/contrib/extractor/libmpq/huffman.h new file mode 100644 index 00000000000..1f8eae54eb4 --- /dev/null +++ b/contrib/extractor/libmpq/huffman.h @@ -0,0 +1,105 @@ +/* + * huffman.h -- structures used for huffman compression. + * + * Copyright (C) 2003 Maik Broemme + * + * This source was adepted from the C++ version of huffman.h included + * in stormlib. The C++ version belongs to the following authors, + * + * Ladislav Zezula + * ShadowFlare + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _HUFFMAN_H +#define _HUFFMAN_H + +#define PTR_NOT(ptr) (struct huffman_tree_item *)(~(unsigned long)(ptr)) +#define PTR_PTR(ptr) ((struct huffman_tree_item *)(ptr)) +#define PTR_INT(ptr) (long)(ptr) + +#define INSERT_ITEM 1 +#define SWITCH_ITEMS 2 /* Switch the item1 and item2 */ + +/* + * Input stream for Huffmann decompression + */ +struct huffman_input_stream { + unsigned char *in_buf; /* 00 - Input data */ + unsigned long bit_buf; /* 04 - Input bit buffer */ + unsigned int bits; /* 08 - Number of bits remaining in 'byte' */ +}; + +/* + * Huffmann tree item. + */ +struct huffman_tree_item { + struct huffman_tree_item *next; /* 00 - Pointer to next huffman_tree_item */ + struct huffman_tree_item *prev; /* 04 - Pointer to prev huffman_tree_item (< 0 if none) */ + unsigned long dcmp_byte; /* 08 - Index of this item in item pointer array, decompressed byte value */ + unsigned long byte_value; /* 0C - Some byte value */ + struct huffman_tree_item *parent; /* 10 - Pointer to parent huffman_tree_item (NULL if none) */ + struct huffman_tree_item *child; /* 14 - Pointer to child huffman_tree_item */ +}; + +/* + * Structure used for quick decompress. The 'bits' contains + * number of bits and dcmp_byte contains result decompressed byte + * value. After each walk through Huffman tree are filled all entries + * which are multiplies of number of bits loaded from input stream. + * These entries contain number of bits and result value. At the next + * 7 bits is tested this structure first. If corresponding entry found, + * decompression routine will not walk through Huffman tree and + * directly stores output byte to output stream. + */ +struct huffman_decompress { + unsigned long offs00; /* 00 - 1 if resolved */ + unsigned long bits; /* 04 - Bit count */ + union { + unsigned long dcmp_byte; /* 08 - Byte value for decompress (if bitCount <= 7) */ + struct huffman_tree_item *p_item; /* 08 - THTreeItem (if number of bits is greater than 7 */ + }; +}; + +/* + * Structure for Huffman tree. + */ +struct huffman_tree { + unsigned long cmp0; /* 0000 - 1 if compression type 0 */ + unsigned long offs0004; /* 0004 - Some flag */ + + struct huffman_tree_item items0008[0x203]; /* 0008 - huffman tree items */ + + /* Sometimes used as huffman tree item */ + struct huffman_tree_item *item3050; /* 3050 - Always NULL (?) */ + struct huffman_tree_item *item3054; /* 3054 - Pointer to huffman_tree_item */ + struct huffman_tree_item *item3058; /* 3058 - Pointer to huffman_tree_item (< 0 if invalid) */ + + /* Sometimes used as huffman tree item */ + struct huffman_tree_item *item305C; /* 305C - Usually NULL */ + struct huffman_tree_item *first; /* 3060 - Pointer to top (first) Huffman tree item */ + struct huffman_tree_item *last; /* 3064 - Pointer to bottom (last) Huffman tree item (< 0 if invalid) */ + unsigned long items; /* 3068 - Number of used huffman tree items */ + + struct huffman_tree_item *items306C[0x102]; /* 306C - huffman_tree_item pointer array */ + struct huffman_decompress qd3474[0x80]; /* 3474 - Array for quick decompression */ + + //unsigned char table1502A630[]; /* Some table to make struct size flexible */ +}; + +int libmpq_huff_init_tree(struct huffman_tree *ht, struct huffman_tree_item *hi, unsigned int cmp); +int libmpq_huff_do_decompress(struct huffman_tree *ht, struct huffman_input_stream *is, unsigned char *out_buf, unsigned int out_length); +#endif /* _HUFFMAN_H */ diff --git a/contrib/extractor/libmpq/mpq.cpp b/contrib/extractor/libmpq/mpq.cpp new file mode 100644 index 00000000000..dda89a3b989 --- /dev/null +++ b/contrib/extractor/libmpq/mpq.cpp @@ -0,0 +1,626 @@ +/* + * mpq.c -- functions for developers using libmpq. + * + * Copyright (C) 2003 Maik Broemme + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id: mpq.c,v 1.6 2004/02/12 00:49:00 mbroemme Exp $ + */ +#define _CRT_SECURE_NO_DEPRECATE + +#include +#include +//#include +//#include +#include +#include +#include +#include "mpq.h" +#include "common.h" + +/* + * This function returns version information. + * format: MAJOR.MINOR.PATCH + */ +char *libmpq_version() { + static char version[10]; + sprintf(version, "%i.%i.%i", LIBMPQ_MAJOR_VERSION, LIBMPQ_MINOR_VERSION, LIBMPQ_PATCH_VERSION); + return version; +} + +/* + * This function reads a file and verify if it is a legit MPQ archive + * or not. Then it fills the mpq_header structure and reads the hash + * table. + */ +int libmpq_archive_open(mpq_archive *mpq_a, unsigned char *mpq_filename) { + int fd = 0; + int rb = 0; + int ncnt = FALSE; + struct stat fileinfo; + + /* allocate memory */ + mpq_a->mpq_l = (mpq_list *)malloc(sizeof(mpq_list)); + memset(mpq_a->mpq_l, 0, sizeof(mpq_list)); + mpq_a->header = (mpq_header *)malloc(sizeof(mpq_header)); + memset(mpq_a->header, 0, sizeof(mpq_header)); + + /* Check if file exists and is readable */ + fd = _open((char *)mpq_filename, O_RDONLY | O_BINARY); + if (fd == LIBMPQ_EFILE) { + return LIBMPQ_EFILE; + } + + /* fill the structures with informations */ + strcpy((char *)mpq_a->filename, (char *)mpq_filename); + libmpq_init_buffer(mpq_a); + mpq_a->fd = fd; + mpq_a->header->id = 0; + mpq_a->maxblockindex = 0; + mpq_a->mpq_l->mpq_files = NULL; + + mpq_a->mpqpos = 0; //k + + while (!ncnt) { + mpq_a->header->id = 0; + #ifdef WIN32 + _lseeki64(mpq_a->fd, mpq_a->mpqpos, SEEK_SET); + #else + lseek64(mpq_a->fd, mpq_a->mpqpos, SEEK_SET); + #endif + rb = _read(mpq_a->fd, mpq_a->header, sizeof(mpq_header)); + + /* if different number of bytes read, break the loop */ + if (rb != sizeof(mpq_header)) { + return LIBMPQ_EFILE_FORMAT; + } + + /* special offset for protected MPQs */ + if (mpq_a->header->offset == LIBMPQ_HEADER_W3M) { + mpq_a->flags |= LIBMPQ_FLAG_PROTECTED; + mpq_a->header->offset = sizeof(mpq_header); + } + + /* if valid signature has been found, break the loop */ + if (mpq_a->header->id == LIBMPQ_ID_MPQ) { + ncnt = true; + } + /*if (mpq_a->header->id == LIBMPQ_ID_MPQ && + mpq_a->header->offset == sizeof(mpq_header) && + mpq_a->header->hashtablepos < mpq_a->header->archivesize && + mpq_a->header->blocktablepos < mpq_a->header->archivesize) { + ncnt = TRUE; + }*/ + + /* move to the next possible offset */ + if (!ncnt) { + mpq_a->mpqpos += 0x200; + } + } + + /* get the right positions of the hash table and the block table. */ + mpq_a->blocksize = (0x200 << mpq_a->header->blocksize); + fstat(mpq_a->fd, &fileinfo); + + /* Normal MPQs must have position of */ + /*if (mpq_a->header->hashtablepos + mpq_a->mpqpos < fileinfo.st_size && + mpq_a->header->blocktablepos + mpq_a->mpqpos < fileinfo.st_size) { + mpq_a->header->hashtablepos += mpq_a->mpqpos; + mpq_a->header->blocktablepos += mpq_a->mpqpos; + } else { + return LIBMPQ_EFILE_FORMAT; + }*/ + + /* Try to read and decrypt the hashtable */ + if (libmpq_read_hashtable(mpq_a) != 0) { + return LIBMPQ_EHASHTABLE; + } + + /* Try to read and decrypt the blocktable */ + if (libmpq_read_blocktable(mpq_a) != 0) { + return LIBMPQ_EBLOCKTABLE; + } + + return LIBMPQ_TOOLS_SUCCESS; +} + +/* + * This function closes the file descriptor opened by + * mpq_open_archive(); and frees the decryption buffer. + */ +int libmpq_archive_close(mpq_archive *mpq_a) { + memset(mpq_a->buf, 0, sizeof(mpq_a->buf)); + + /* free the allocated memory. */ + free(mpq_a->header); + free(mpq_a->mpq_l); + + /* Check if file descriptor is valid. */ + if ((_close(mpq_a->fd)) == LIBMPQ_EFILE) { + return LIBMPQ_EFILE; + } + + return LIBMPQ_TOOLS_SUCCESS; +} + +/* + * This function returns the value for the given infotype. + * If an error occurs something < 0 is returned. + */ +int libmpq_archive_info(mpq_archive *mpq_a, unsigned int infotype) { + unsigned int filecount = 0; + unsigned int fsize = 0; + unsigned int csize = 0; + mpq_block *mpq_b_end = mpq_a->blocktable + mpq_a->header->blocktablesize; + mpq_block *mpq_b = NULL; + + switch (infotype) { + case LIBMPQ_MPQ_ARCHIVE_SIZE: + return mpq_a->header->archivesize; + case LIBMPQ_MPQ_HASHTABLE_SIZE: + return mpq_a->header->hashtablesize; + case LIBMPQ_MPQ_BLOCKTABLE_SIZE: + return mpq_a->header->blocktablesize; + case LIBMPQ_MPQ_BLOCKSIZE: + return mpq_a->blocksize; + case LIBMPQ_MPQ_NUMFILES: + for (mpq_b = mpq_a->blocktable; mpq_b < mpq_b_end; mpq_b++) { + filecount++; + } + return filecount; + case LIBMPQ_MPQ_COMPRESSED_SIZE: + for (mpq_b = mpq_a->blocktable; mpq_b < mpq_b_end; mpq_b++) { + csize += mpq_b->csize; + } + return csize; + case LIBMPQ_MPQ_UNCOMPRESSED_SIZE: + for (mpq_b = mpq_a->blocktable; mpq_b < mpq_b_end; mpq_b++) { + fsize += mpq_b->fsize; + } + return fsize; + default: + return LIBMPQ_TOOLS_SUCCESS; + } +} + +/* + * This function returns some useful file information. + */ +int libmpq_file_info(mpq_archive *mpq_a, unsigned int infotype, const int number) { + int blockindex = number; //-1; + int i = 0; + mpq_block *mpq_b = NULL; + mpq_hash *mpq_h = NULL; + + /* check if given number is not out of range */ + if (number < 1 || number > mpq_a->header->blocktablesize) { + return LIBMPQ_EINV_RANGE; + } + + /* search for correct hashtable */ + /*for (i = 0; i < mpq_a->header->hashtablesize; i++) { + if ((number - 1) == (mpq_a->hashtable[i]).blockindex) { + blockindex = (mpq_a->hashtable[i]).blockindex; + mpq_h = &(mpq_a->hashtable[i]); + break; + } + }*/ + + /* check if file was found */ + /*if (blockindex == -1 || blockindex > mpq_a->header->blocktablesize) { + return LIBMPQ_EFILE_NOT_FOUND; + }*/ + + /* check if sizes are correct */ + mpq_b = mpq_a->blocktable + blockindex; + if (mpq_b->filepos > (mpq_a->header->archivesize + mpq_a->mpqpos) || mpq_b->csize > mpq_a->header->archivesize) { + return LIBMPQ_EFILE_CORRUPT; + } + + /* check if file exists */ + if ((mpq_b->flags & LIBMPQ_FILE_EXISTS) == 0) { + return LIBMPQ_EFILE_NOT_FOUND; + } + + switch (infotype) { + case LIBMPQ_FILE_COMPRESSED_SIZE: + return mpq_b->csize; + case LIBMPQ_FILE_UNCOMPRESSED_SIZE: + return mpq_b->fsize; + case LIBMPQ_FILE_COMPRESSION_TYPE: + if (mpq_b->flags & LIBMPQ_FILE_COMPRESS_PKWARE) { + return LIBMPQ_FILE_COMPRESS_PKWARE; + } + if (mpq_b->flags & LIBMPQ_FILE_COMPRESS_MULTI) { + return LIBMPQ_FILE_COMPRESS_MULTI; + } + default: + return LIBMPQ_TOOLS_SUCCESS; + } +} + +/* + * This function searches the listfile for the filename. + * On success it returns the filename, otherwiese a name + * like file000001.xxx and if number is out of range it + * returns NULL. + */ +char *libmpq_file_name(mpq_archive *mpq_a, const int number) { + static char tempfile[PATH_MAX]; + + /* check if we are in the range of available files. */ + if (number > libmpq_archive_info(mpq_a, LIBMPQ_MPQ_NUMFILES) || number < 1) { + return NULL; + } + + /* this is safe because we built a fallback filelist, if something was wrong. */ + sprintf(tempfile, (char *)mpq_a->mpq_l->mpq_files[number - 1], number); + + return tempfile; +} + +/* + * This function returns the number to the given + * filename. + */ +int libmpq_file_number(mpq_archive *mpq_a, const char *name) { + int i; + char tempfile[PATH_MAX]; + + for (i = 0; mpq_a->mpq_l->mpq_files[i]; i++) { + sprintf(tempfile, (char *)mpq_a->mpq_l->mpq_files[i], i + 1); + if (strncmp(tempfile, name, strlen(name)) == 0) { + + /* if file found return the number */ + return i + 1; + } + } + + /* if no matching entry found return LIBMPQ_EFILE_NOT_FOUND */ + return LIBMPQ_EFILE_NOT_FOUND; +} + +/* + * This function verifies if a given file (by number + * or name) is in the opened mpq archive. On success + * it returns 0, otherwise LIBMPQ_EFILE_NOT_FOUND. + */ +int libmpq_file_check(mpq_archive *mpq_a, void *file, int type) { + int found = 0; + int i; + char tempfile[PATH_MAX]; + + switch (type) { + case LIBMPQ_FILE_TYPE_INT: + + /* check if we are in the range of available files. */ + if (*(int *)file > libmpq_archive_info(mpq_a, LIBMPQ_MPQ_NUMFILES) || *(int *)file < 1) { + return LIBMPQ_EFILE_NOT_FOUND; + } else { + return LIBMPQ_TOOLS_SUCCESS; + } + case LIBMPQ_FILE_TYPE_CHAR: + for (i = 0; mpq_a->mpq_l->mpq_files[i]; i++) { + sprintf(tempfile, (char *)mpq_a->mpq_l->mpq_files[i], i); + if (strncmp(tempfile, (char *)file, strlen((char *)file)) == 0) { + + /* if file found break */ + found = 1; + break; + } + } + + /* if a file was found return 0 */ + if (found == 1) { + return LIBMPQ_TOOLS_SUCCESS; + } else { + return LIBMPQ_EFILE_NOT_FOUND; + } + default: + return LIBMPQ_TOOLS_SUCCESS; + } +} + +/* + * This function extracts a file from a MPQ archive + * by the given number. + */ +int libmpq_file_extract(mpq_archive *mpq_a, const int number, const char *filename) { + int blockindex = number; //-1; + int fd = 0; + int i = 0; + char buffer[0x1000]; + //char tempfile[PATH_MAX]; + unsigned int transferred = 1; + mpq_file *mpq_f = NULL; + mpq_block *mpq_b = NULL; + mpq_hash *mpq_h = NULL; + +/* if (number < 1 || number > mpq_a->header->blocktablesize) { + return LIBMPQ_EINV_RANGE; + }*/ +/* + sprintf(tempfile, libmpq_file_name(mpq_a, number)); +*/ + /* check if mpq_f->filename could be written here. */ + fd = _open(filename, O_RDWR|O_CREAT|O_TRUNC, 0644); + if (fd == LIBMPQ_EFILE) { + return LIBMPQ_EFILE; + } + + /* search for correct hashtable */ + /*for (i = 0; i < mpq_a->header->hashtablesize; i++) { + if ((number - 1) == (mpq_a->hashtable[i]).blockindex) { + blockindex = (mpq_a->hashtable[i]).blockindex; + mpq_h = &(mpq_a->hashtable[i]); + break; + } + }*/ + + /* check if file was found */ + if (blockindex == -1 || blockindex > mpq_a->header->blocktablesize) { + return LIBMPQ_EFILE_NOT_FOUND; + } + + /* check if sizes are correct */ + mpq_b = mpq_a->blocktable + blockindex; + if (mpq_b->filepos > (mpq_a->header->archivesize + mpq_a->mpqpos) || mpq_b->csize > mpq_a->header->archivesize) { + return LIBMPQ_EFILE_CORRUPT; + } + + /* check if file exists */ + if ((mpq_b->flags & LIBMPQ_FILE_EXISTS) == 0) { + return LIBMPQ_EFILE_NOT_FOUND; + } + + /* allocate memory for file structure */ + mpq_f = (mpq_file *)malloc(sizeof(mpq_file)); + if (!mpq_f) { + return LIBMPQ_EALLOCMEM; + } + + /* initialize file structure */ + memset(mpq_f, 0, sizeof(mpq_file)); + mpq_f->fd = fd; + mpq_f->mpq_b = mpq_b; + mpq_f->nblocks = (mpq_f->mpq_b->fsize + mpq_a->blocksize - 1) / mpq_a->blocksize; + mpq_f->mpq_h = mpq_h; + mpq_f->accessed = FALSE; + mpq_f->blockposloaded = FALSE; + sprintf((char *)mpq_f->filename, filename); + + /* allocate buffers for decompression. */ + if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) { + + /* + * Allocate buffer for block positions. At the begin of file are stored + * unsigned ints holding positions of each block relative from begin of + * file in the archive. + */ + if ((mpq_f->blockpos = (unsigned int *)malloc(sizeof(int) * mpq_f->nblocks + 1)) == NULL) { + return LIBMPQ_EALLOCMEM; + } + } + + while (transferred > 0) { + transferred = libmpq_file_read_file(mpq_a, mpq_f, mpq_f->filepos, buffer, sizeof(buffer)); + if (transferred == 0) { + break; + } else { + mpq_f->accessed = TRUE; + mpq_f->filepos += transferred; + } + + transferred = _write(mpq_f->fd, buffer, transferred); + if (transferred == 0) { + break; + } + } + + _close(fd); + + /* freeing the file structure */ + free(mpq_f); + return LIBMPQ_TOOLS_SUCCESS; +} + +/* + * This function tries to get the filenames for the hashes. It uses + * an internal listfile database and gets the correct listfile from + * some specific archive informations. + */ + +int libmpq_listfile_open(mpq_archive *mpq_a, char file[PATH_MAX]) { + FILE *fp; + //char **filelist; + int i = 0; + //int fl_count; + //int fl_size; + int fl_count_fb; + int fl_size_fb; + int result = LIBMPQ_TOOLS_SUCCESS; + struct stat statbuf; + + /* get file status */ + if (stat(file, &statbuf) < 0) { + result = LIBMPQ_CONF_EFILE_NOT_FOUND; + } + + /* check if file is a filename or directory */ + /*if (S_ISDIR(statbuf.st_mode)) { + + // allocate memory for the file list + filelist = (char **)malloc(LIBMPQ_CONF_FL_INCREMENT * sizeof(char *)); + fl_count = 0; + fl_size = LIBMPQ_CONF_FL_INCREMENT; + + // check if it is a valid listfile + if (libmpq_detect_listfile_rec(file, &filelist, &fl_count, &fl_size)) { + filelist == NULL; + } + + filelist[fl_count] = NULL; + + // return if no listfile was found + if (filelist == NULL) { + result = LIBMPQ_CONF_EFILE_NOT_FOUND; + } + + for (i = 0; filelist[i]; i++) { + if ((fp = fopen(filelist[i], "r")) != NULL ) { + result = libmpq_read_listfile(mpq_a, fp); + fclose(fp); + } + } + + // freeing the listfile struct + libmpq_free_listfile(filelist); + }*/ + + /* if file is a regular file use it */ + //if (S_ISREG(statbuf.st_mode)) { + + /* if specific listfile was forced. */ + if ((fp = fopen(file, "r")) != NULL ) { + result = libmpq_read_listfile(mpq_a, fp); + fclose(fp); + } else { + result = LIBMPQ_CONF_EFILE_OPEN; + } + //} + + /* if error occured we need to create a fallback filelist. */ + if (mpq_a->mpq_l->mpq_files == NULL) { + + /* allocate memory for the file list */ + mpq_a->mpq_l->mpq_files = (unsigned char **)malloc(LIBMPQ_CONF_FL_INCREMENT * sizeof(char *)); + fl_count_fb = 0; + fl_size_fb = LIBMPQ_CONF_FL_INCREMENT; + + for (i = 0; i < libmpq_archive_info(mpq_a, LIBMPQ_MPQ_NUMFILES); i++) { + + /* set the next filelist entry to a copy of the file */ + mpq_a->mpq_l->mpq_files[fl_count_fb++] = (unsigned char *)_strdup("file%06lu.xxx"); + + /* increase the array size */ + if (fl_count_fb == fl_size_fb) { + mpq_a->mpq_l->mpq_files = (unsigned char **)realloc(mpq_a->mpq_l->mpq_files, (fl_size_fb + LIBMPQ_CONF_FL_INCREMENT) * sizeof(char *)); + fl_size_fb += LIBMPQ_CONF_FL_INCREMENT; + } + } + mpq_a->mpq_l->mpq_files[fl_count_fb] = NULL; + + /* if no error occurs and no listfile was assigned, we think there was no matching listfile. */ + if (result == 0) { + result = LIBMPQ_CONF_EFILE_NOT_FOUND; + } + } + + return result; +} + +/* + * This function frees the allocated memory for the listfile. + */ +int libmpq_listfile_close(mpq_archive *mpq_a) { + int i = 0; + + /* safety check if we really have a filelist. */ + if (mpq_a->mpq_l->mpq_files != NULL) { + /* freeing the filelist */ + while (mpq_a->mpq_l->mpq_files[i]) { + free(mpq_a->mpq_l->mpq_files[i++]); + } + free(mpq_a->mpq_l->mpq_files); + } + return 0; +} + +int libmpq_file_getdata(mpq_archive *mpq_a, mpq_hash mpq_h, const int number, unsigned char *dest) { + int blockindex = number; //-1; + int i = 0; + mpq_file *mpq_f = NULL; + mpq_block *mpq_b = NULL; + int success = 0; + + /*if (number < 1 || number > mpq_a->header->blocktablesize) { + return LIBMPQ_EINV_RANGE; + }*/ + + /* search for correct hashtable */ + /*for (i = 0; i < mpq_a->header->hashtablesize; i++) { + if ((number - 1) == (mpq_a->hashtable[i]).blockindex) { + blockindex = (mpq_a->hashtable[i]).blockindex; + mpq_h = &(mpq_a->hashtable[i]); + break; + } + }*/ + + /* check if file was found */ + if (blockindex == -1 || blockindex > mpq_a->header->blocktablesize) { + return LIBMPQ_EFILE_NOT_FOUND; + } + + /* check if sizes are correct */ + mpq_b = mpq_a->blocktable + blockindex; + if (mpq_b->filepos > (mpq_a->header->archivesize + mpq_a->mpqpos) || mpq_b->csize > mpq_a->header->archivesize) { + return LIBMPQ_EFILE_CORRUPT; + } + + /* check if file exists */ + if ((mpq_b->flags & LIBMPQ_FILE_EXISTS) == 0) { + return LIBMPQ_EFILE_NOT_FOUND; + } + + /* allocate memory for file structure */ + mpq_f = (mpq_file*)malloc(sizeof(mpq_file)); + if (!mpq_f) { + return LIBMPQ_EALLOCMEM; + } + + /* initialize file structure */ + memset(mpq_f, 0, sizeof(mpq_file)); + mpq_f->mpq_b = mpq_b; + mpq_f->nblocks = (mpq_f->mpq_b->fsize + mpq_a->blocksize - 1) / mpq_a->blocksize; + mpq_f->mpq_h = &mpq_h; + mpq_f->accessed = FALSE; + mpq_f->blockposloaded = FALSE; + + /* allocate buffers for decompression. */ + if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) { + + /* + * Allocate buffer for block positions. At the begin of file are stored + * unsigned ints holding positions of each block relative from begin of + * file in the archive. + */ + if ((mpq_f->blockpos = (unsigned int*)malloc(sizeof(int) * (mpq_f->nblocks + 1))) == NULL) { + return LIBMPQ_EALLOCMEM; + } + } + + if(libmpq_file_read_file(mpq_a, mpq_f, 0, (char*)dest, mpq_b->fsize) == mpq_b->fsize) + success = 1; + + if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) { + // Free buffer for block positions + + free(mpq_f->blockpos); + } + /* freeing the file structure */ + free(mpq_f); + return success?LIBMPQ_TOOLS_SUCCESS:LIBMPQ_EFILE_CORRUPT; +} diff --git a/contrib/extractor/libmpq/mpq.h b/contrib/extractor/libmpq/mpq.h new file mode 100644 index 00000000000..0a136f95f30 --- /dev/null +++ b/contrib/extractor/libmpq/mpq.h @@ -0,0 +1,225 @@ +/* + * mpq.h -- some default types and defines. + * + * Copyright (C) 2003 Maik Broemme + * + * This source was adepted from the C++ version of StormLib.h and + * StormPort.h included in stormlib. The C++ version belongs to + * the following authors, + * + * Ladislav Zezula + * Marko Friedemann + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id: mpq.h,v 1.8 2004/02/12 00:45:50 mbroemme Exp $ + */ + +#ifndef _MPQ_H +#define _MPQ_H + +#include + +#ifndef PATH_MAX + #define PATH_MAX 260 +#endif + + +#define LIBMPQ_MAJOR_VERSION 0 /* Major version number... maybe sometimes we reach version 1 :) */ +#define LIBMPQ_MINOR_VERSION 3 /* Minor version number - increased only for small changes */ +#define LIBMPQ_PATCH_VERSION 0 /* Patchlevel - changed on bugfixes etc... */ + +#define LIBMPQ_TOOLS_SUCCESS 0 /* return value for all functions which success */ +#define LIBMPQ_TOOLS_BUFSIZE 0x500 /* buffer size for the decryption engine */ + +#define LIBMPQ_EFILE -1 /* error on file operation */ +#define LIBMPQ_EFILE_FORMAT -2 /* bad file format */ +#define LIBMPQ_EFILE_CORRUPT -3 /* file corrupt */ +#define LIBMPQ_EFILE_NOT_FOUND -4 /* file in archive not found */ +#define LIBMPQ_EFILE_READ -5 /* Read error in archive */ +#define LIBMPQ_EALLOCMEM -6 /* maybe not enough memory? :) */ +#define LIBMPQ_EFREEMEM -7 /* can not free memory */ +#define LIBMPQ_EINV_RANGE -8 /* Given filenumber is out of range */ +#define LIBMPQ_EHASHTABLE -9 /* error in reading hashtable */ +#define LIBMPQ_EBLOCKTABLE -10 /* error in reading blocktable */ + +#define LIBMPQ_ID_MPQ 0x1A51504D /* MPQ archive header ID ('MPQ\x1A') */ +#define LIBMPQ_HEADER_W3M 0x6D9E4B86 /* special value used by W3M Map Protector */ +#define LIBMPQ_FLAG_PROTECTED 0x00000002 /* Set on protected MPQs (like W3M maps) */ +#define LIBMPQ_HASH_ENTRY_DELETED 0xFFFFFFFE /* Block index for deleted hash entry */ + +#define LIBMPQ_FILE_COMPRESS_PKWARE 0x00000100 /* Compression made by PKWARE Data Compression Library */ +#define LIBMPQ_FILE_COMPRESS_MULTI 0x00000200 /* Multiple compressions */ +#define LIBMPQ_FILE_COMPRESSED 0x0000FF00 /* File is compressed */ +#define LIBMPQ_FILE_EXISTS 0x80000000 /* Set if file exists, reset when the file was deleted */ +#define LIBMPQ_FILE_ENCRYPTED 0x00010000 /* Indicates whether file is encrypted */ +#define LIBMPQ_FILE_HAS_METADATA 0x04000000 + +#define LIBMPQ_FILE_COMPRESSED_SIZE 1 /* MPQ compressed filesize of given file */ +#define LIBMPQ_FILE_UNCOMPRESSED_SIZE 2 /* MPQ uncompressed filesize of given file */ +#define LIBMPQ_FILE_COMPRESSION_TYPE 3 /* MPQ compression type of given file */ +#define LIBMPQ_FILE_TYPE_INT 4 /* file is given by number */ +#define LIBMPQ_FILE_TYPE_CHAR 5 /* file is given by name */ + +#define LIBMPQ_MPQ_ARCHIVE_SIZE 1 /* MPQ archive size */ +#define LIBMPQ_MPQ_HASHTABLE_SIZE 2 /* MPQ archive hashtable size */ +#define LIBMPQ_MPQ_BLOCKTABLE_SIZE 3 /* MPQ archive blocktable size */ +#define LIBMPQ_MPQ_BLOCKSIZE 4 /* MPQ archive blocksize */ +#define LIBMPQ_MPQ_NUMFILES 5 /* Number of files in the MPQ archive */ +#define LIBMPQ_MPQ_COMPRESSED_SIZE 6 /* Compressed archive size */ +#define LIBMPQ_MPQ_UNCOMPRESSED_SIZE 7 /* Uncompressed archive size */ + +#define LIBMPQ_HUFF_DECOMPRESS 0 /* Defines that we want to decompress using huffman trees. */ + +#define LIBMPQ_CONF_EFILE_OPEN -1 /* error if a specific listfile was forced and could not be opened. */ +#define LIBMPQ_CONF_EFILE_CORRUPT -2 /* listfile seems to be corrupt */ +#define LIBMPQ_CONF_EFILE_LIST_CORRUPT -3 /* listfile seems correct, but filelist is broken */ +#define LIBMPQ_CONF_EFILE_NOT_FOUND -4 /* error if no matching listfile found */ +#define LIBMPQ_CONF_EFILE_VERSION -5 /* libmpq version does not match required listfile version */ + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + +/* +#ifndef min +#define min(a, b) ((a < b) ? a : b) +#endif +*/ + +typedef unsigned int mpq_buffer[LIBMPQ_TOOLS_BUFSIZE]; +typedef int (*DECOMPRESS)(char *, int *, char *, int); +typedef struct { + unsigned long mask; /* Decompression bit */ + DECOMPRESS decompress; /* Decompression function */ +} decompress_table; + +/* MPQ file header */ +typedef struct { + unsigned int id; /* The 0x1A51504D ('MPQ\x1A') signature */ + unsigned int offset; /* Offset of the first file (Relative to MPQ start) */ + unsigned int archivesize; /* Size of MPQ archive */ + unsigned short offsetsc; /* 0000 for SC and BW */ + unsigned short blocksize; /* Size of file block is (0x200 << blockSize) */ + unsigned int hashtablepos; /* File position of hashTable */ + unsigned int blocktablepos; /* File position of blockTable. Each entry has 16 bytes */ + unsigned int hashtablesize; /* Number of entries in hash table */ + unsigned int blocktablesize; /* Number of entries in the block table */ +} mpq_header; +//} __attribute__ ((packed)) mpq_header; + + +/* Hash entry. All files in the archive are searched by their hashes. */ +typedef struct { + unsigned int name1; /* The first two unsigned ints */ + unsigned int name2; /* are the encrypted file name */ + unsigned int locale; /* Locale information. */ + unsigned int blockindex; /* Index to file description block */ +} mpq_hash; + +/* File description block contains informations about the file */ +typedef struct { + unsigned int filepos; /* Block file starting position in the archive */ + unsigned int csize; /* Compressed file size */ + unsigned int fsize; /* Uncompressed file size */ + unsigned int flags; /* Flags */ +} mpq_block; + +/* File handle structure used since Diablo 1.00 (0x38 bytes) */ +typedef struct { + unsigned char filename[PATH_MAX]; /* filename of the actual file in the archive */ + int fd; /* File handle */ + unsigned int seed; /* Seed used for file decrypt */ + unsigned int filepos; /* Current file position */ + unsigned int offset; + unsigned int nblocks; /* Number of blocks in the file (incl. the last noncomplete one) */ + unsigned int *blockpos; /* Position of each file block (only for compressed files) */ + int blockposloaded; /* TRUE if block positions loaded */ + unsigned int offset2; /* (Number of bytes somewhere ?) */ + mpq_hash *mpq_h; /* Hash table entry */ + mpq_block *mpq_b; /* File block pointer */ + + /* Non-Storm.dll members */ + + unsigned int accessed; /* Was something from the file already read? */ +} mpq_file; + +/* List handle structure */ +typedef struct { + unsigned char mpq_version[10]; /* libmpq version required by the listfile */ + unsigned char mpq_name[PATH_MAX]; /* mpq archive name without full path */ + unsigned char mpq_type[20]; /* mpq archive type */ + unsigned char mpq_game[40]; /* blizzard title the file matches */ + unsigned char mpq_game_version[10]; /* game version */ + unsigned char **mpq_files; /* filelist */ +} mpq_list; + +/* Archive handle structure used since Diablo 1.00 */ +typedef struct { + unsigned char filename[PATH_MAX]; /* Opened archive file name */ + int fd; /* File handle */ + unsigned int blockpos; /* Position of loaded block in the file */ + unsigned int blocksize; /* Size of file block */ + unsigned char *blockbuf; /* Buffer (cache) for file block */ + unsigned int bufpos; /* Position in block buffer */ + unsigned int mpqpos; /* MPQ archive position in the file */ + unsigned int filepos; /* Current file pointer */ + unsigned int openfiles; /* Number of open files + 1 */ + mpq_buffer buf; /* MPQ buffer */ + mpq_header *header; /* MPQ file header */ + mpq_hash *hashtable; /* Hash table */ + mpq_block *blocktable; /* Block table */ + + /* Non-Storm.dll members */ + + mpq_list *mpq_l; /* Handle to file list from database */ + + unsigned int flags; /* See LIBMPQ_TOOLS_FLAG_XXXXX */ + unsigned int maxblockindex; /* The highest block table entry */ +} mpq_archive; + +extern char *libmpq_version(); +extern int libmpq_archive_open(mpq_archive *mpq_a, unsigned char *mpq_filename); +extern int libmpq_archive_close(mpq_archive *mpq_a); +extern int libmpq_archive_info(mpq_archive *mpq_a, unsigned int infotype); +//extern int libmpq_file_extract(mpq_archive *mpq_a, const int number); +extern int libmpq_file_info(mpq_archive *mpq_a, unsigned int infotype, const int number); +extern char *libmpq_file_name(mpq_archive *mpq_a, const int number); +extern int libmpq_file_number(mpq_archive *mpq_a, const char *name); +extern int libmpq_file_check(mpq_archive *mpq_a, void *file, int type); +extern int libmpq_listfile_open(mpq_archive *mpq_a, char file[PATH_MAX]); +extern int libmpq_listfile_close(mpq_archive *mpq_a); + +extern int libmpq_pkzip_decompress(char *out_buf, int *out_length, char *in_buf, int in_length); +extern int libmpq_zlib_decompress(char *out_buf, int *out_length, char *in_buf, int in_length); +extern int libmpq_huff_decompress(char *out_buf, int *out_length, char *in_buf, int in_length); +extern int libmpq_wave_decompress_stereo(char *out_buf, int *out_length, char *in_buf, int in_length); +extern int libmpq_wave_decompress_mono(char *out_buf, int *out_length, char *in_buf, int in_length); +extern int libmpq_multi_decompress(char *out_buf, int *pout_length, char *in_buf, int in_length); + +static decompress_table dcmp_table[] = { + {0x08, libmpq_pkzip_decompress}, /* Decompression with Pkware Data Compression Library */ + {0x02, libmpq_zlib_decompress}, /* Decompression with the "zlib" library */ + {0x01, libmpq_huff_decompress}, /* Huffmann decompression */ + {0x80, libmpq_wave_decompress_stereo}, /* WAVE decompression for stereo waves */ + {0x40, libmpq_wave_decompress_mono} /* WAVE decompression for mono waves */ +}; + +int libmpq_file_extract(mpq_archive *mpq_a, const int number, const char *filename); +int libmpq_file_getdata(mpq_archive *mpq_a, mpq_hash mpq_h, const int number, unsigned char *dest); +#endif /* _MPQ_H */ diff --git a/contrib/extractor/libmpq/parser.cpp b/contrib/extractor/libmpq/parser.cpp new file mode 100644 index 00000000000..b7a70400f5a --- /dev/null +++ b/contrib/extractor/libmpq/parser.cpp @@ -0,0 +1,294 @@ +/* + * parser.c -- functions used to parse list or config file. + * + * Copyright (C) 2003 Maik Broemme + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id: parser.c,v 1.5 2004/02/12 00:47:53 mbroemme Exp $ + */ +#define _CRT_SECURE_NO_DEPRECATE + +#include +#include +#include +#include "mpq.h" +#include "common.h" +#include + +/* + * This function deletes the specified characters, but leaves + * escape sequences unaffected. This means that " would be + * deleted but \" would not. + */ +char *libmpq_conf_delete_char(char *buf, char *chars) { + static char *temp; + char ch; + + temp = buf; + + /* strip out special chars like " */ + while (temp = strpbrk(temp, chars)) { + ch = temp[0]; + memmove(&temp[0], &temp[1], strlen(temp)); + if (ch == '\\') { + temp++; + } + } + + return buf; +} + +/* + * This function parses a line for the value to the given option. It + * return 1 on success and the byte array or 0 and null. + */ +int libmpq_conf_parse_line(char *line, char *search_value, char *return_value, int size) { + int level = 0; + int found = 0; + int i = 0; + int pos = 0; + + /* search value */ + while (*(++line)) { + + /* check for spaces */ + if (!isspace(*line) && level == 1) { + + /* we found our value so break */ + found = 1; + break; + } + + /* check for '=' so the value follows as next parameter */ + if (*line == '=' && level == 0) { + level = 1; + } + } + + /* now search for comment in this line */ + for (i = 0; i < strlen(line); i++) { + if (line[i] == '#') { + pos = i - 1; + break; + } + } + + /* now set end of byte array behind value, but only if comment was found */ + if (pos != 0) { + for (i = pos; i >= 0; i--) { + if (line[i] != ' ' && line[i] != '\t') { + line[i + 1] = '\0'; + break; + } + } + } + + /* now check if line has trailing spaces */ + for (i = strlen(line); i >= 0; i--) { + if (line[i] != ' ' && line[i] != '\t') { + line[i + 1] = '\0'; + break; + } + } + + /* now check if value is quoted with "" and if there is a char behind. */ + for (i = strlen(line); i >= 0; i--) { + if (line[i] == '"') { + line[i + 1] = '\0'; + break; + } + } + + /* return the values */ + strncpy(return_value, line, size); + return found; +} + +/* + * This function returns the value for a given option in the + * listdb or config file. On success it returns 1, otherwise 0. + */ +int libmpq_conf_get_value(FILE *fp, char *search_value, void *return_value, int type, int size) { + char buf[LIBMPQ_CONF_BUFSIZE]; + int found = 0; + int result = LIBMPQ_TOOLS_SUCCESS; + + while (fgets(buf, LIBMPQ_CONF_BUFSIZE, fp) != NULL) { + char *line; + + buf[strlen(buf) - 1] = '\0'; + + /* skip whitespace */ + for (line = buf; isspace(*line); line++) { + continue; + } + + /* skip empty line */ + if (line[0] == '\0') { + continue; + } + + /* skip comments */ + if (line[0] == '#') { + continue; + } + + /* process the line */ + //if (!strncasecmp(line, search_value, strlen(search_value))) { + if (!strcmp(line, search_value)) { + found = libmpq_conf_parse_line(line, search_value, line, LIBMPQ_CONF_BUFSIZE); + if (found == 1) { + libmpq_conf_delete_char(line, "\"\\"); + + switch (type) { + case LIBMPQ_CONF_TYPE_INT: + + /* if it is no valid number it is safe to return 0 */ + *(int *)return_value = atoi(line); + break; + default: + strncpy((char *)return_value, line, size); + break; + } + + /* value found, so rewind stream */ + break; + } + } + } + + /* if value was not found */ + if (found == 0) { + switch (type) { + case LIBMPQ_CONF_TYPE_INT: + *(int *)return_value = 0; + result = LIBMPQ_CONF_EVALUE_NOT_FOUND; + break; + default: + strncpy((char *)return_value, "", size); + result = LIBMPQ_CONF_EVALUE_NOT_FOUND; + break; + } + } + fseek(fp, 0L, SEEK_SET); + + return result; +} + +/* + * This function returns a pointer to a byte array, with all values + * found in the config file. As second value it returns th number of + * entries in the byte array. On success it returns 1, otherwise 0. + */ +int libmpq_conf_get_array(FILE *fp, char *search_value, char ***filelist, int *entries) { + char buf[LIBMPQ_CONF_BUFSIZE]; + char temp[LIBMPQ_CONF_BUFSIZE]; + int level = 0; + int array_start = 0; + int array_end = 0; + int fl_count; + int fl_size; + int found = 0; + int i = 0; + + *entries = 0; + + /* allocate memory for the file list */ + (*filelist) = (char **)malloc(LIBMPQ_CONF_FL_INCREMENT * sizeof(char *)); + fl_count = 0; + fl_size = LIBMPQ_CONF_FL_INCREMENT; + + while (fgets(buf, LIBMPQ_CONF_BUFSIZE, fp) != NULL) { + char *line; + + buf[strlen(buf) - 1] = '\0'; + + /* skip whitespace */ + for (line = buf; isspace(*line); line++) { + continue; + } + + /* skip empty line */ + if (line[0] == '\0') { + continue; + } + + /* skip comments */ + if (line[0] == '#') { + continue; + } + + /* check for array end ) */ + if (*line == ')') { + array_end = 1; + break; + } + + /* process entries between () */ + if (array_start == 1 && array_end == 0) { + + /* add dummy option to use with libmpq_conf_parse_line() */ + strncpy(temp, "MPQ_BUFFER = ", LIBMPQ_CONF_BUFSIZE); + strncat(temp, line, LIBMPQ_CONF_BUFSIZE); + found = libmpq_conf_parse_line(temp, "MPQ_BUFFER", temp, LIBMPQ_CONF_BUFSIZE); + + if (found == 1) { + libmpq_conf_delete_char(temp, "\"\\"); + + /* set the next filelist entry to a copy of the file */ + (*filelist)[fl_count++] = _strdup(temp); + + /* increase the array size */ + if (fl_count == fl_size) { + (*filelist) = (char **)realloc((*filelist), (fl_size + LIBMPQ_CONF_FL_INCREMENT) * sizeof(char *)); + fl_size += LIBMPQ_CONF_FL_INCREMENT; + } + + /* increase number of entries */ + (*entries)++; + } + } + + /* process the line and search array start */ + //if (!strncasecmp(line, search_value, strlen(search_value))) { + if (!strcmp(line, search_value)) { + + /* search value */ + while (*(++line)) { + + /* check for array start ( */ + if (*line == '(' && level == 1) { + + /* we found our value so break */ + array_start = 1; + break; + } + + /* check for '=' so the value follows as next parameter */ + if (*line == '=' && level == 0) { + level = 1; + } + } + } + } + + /* we got all files, so rewind stream */ + fseek(fp, 0L, SEEK_SET); + + (*filelist)[fl_count] = NULL; + + return found; +} diff --git a/contrib/extractor/libmpq/wave.cpp b/contrib/extractor/libmpq/wave.cpp new file mode 100644 index 00000000000..8edc1f7fa41 --- /dev/null +++ b/contrib/extractor/libmpq/wave.cpp @@ -0,0 +1,185 @@ +/* + * wave.c -- this file contains decompression methods used by Storm.dll + * to decompress wave files. + * + * Copyright (C) 2003 Maik Broemme + * + * This source was adepted from the C++ version of wave.cpp included + * in stormlib. The C++ version belongs to the following authors, + * + * Ladislav Zezula + * Tom Amigo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "wave.h" + +/* Tables necessary dor decompression */ +static unsigned long wave_table_1503f120[] = { + 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000004, 0xFFFFFFFF, 0x00000002, 0xFFFFFFFF, 0x00000006, + 0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0x00000005, 0xFFFFFFFF, 0x00000003, 0xFFFFFFFF, 0x00000007, + 0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0x00000005, 0xFFFFFFFF, 0x00000003, 0xFFFFFFFF, 0x00000007, + 0xFFFFFFFF, 0x00000002, 0xFFFFFFFF, 0x00000004, 0xFFFFFFFF, 0x00000006, 0xFFFFFFFF, 0x00000008 +}; + +static unsigned long wave_table_1503f1a0[] = { + 0x00000007, 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, + 0x00000010, 0x00000011, 0x00000013, 0x00000015, 0x00000017, 0x00000019, 0x0000001C, 0x0000001F, + 0x00000022, 0x00000025, 0x00000029, 0x0000002D, 0x00000032, 0x00000037, 0x0000003C, 0x00000042, + 0x00000049, 0x00000050, 0x00000058, 0x00000061, 0x0000006B, 0x00000076, 0x00000082, 0x0000008F, + 0x0000009D, 0x000000AD, 0x000000BE, 0x000000D1, 0x000000E6, 0x000000FD, 0x00000117, 0x00000133, + 0x00000151, 0x00000173, 0x00000198, 0x000001C1, 0x000001EE, 0x00000220, 0x00000256, 0x00000292, + 0x000002D4, 0x0000031C, 0x0000036C, 0x000003C3, 0x00000424, 0x0000048E, 0x00000502, 0x00000583, + 0x00000610, 0x000006AB, 0x00000756, 0x00000812, 0x000008E0, 0x000009C3, 0x00000ABD, 0x00000BD0, + 0x00000CFF, 0x00000E4C, 0x00000FBA, 0x0000114C, 0x00001307, 0x000014EE, 0x00001706, 0x00001954, + 0x00001BDC, 0x00001EA5, 0x000021B6, 0x00002515, 0x000028CA, 0x00002CDF, 0x0000315B, 0x0000364B, + 0x00003BB9, 0x000041B2, 0x00004844, 0x00004F7E, 0x00005771, 0x0000602F, 0x000069CE, 0x00007462, + 0x00007FFF +}; + +/* + * Decompress a wave file, mono or stereo + * + * Offset: 1500F230 + */ +int libmpq_wave_decompress(unsigned char *out_buf, int out_length, unsigned char *in_buf, int in_length, int channels) { + byte_and_short out; + byte_and_short in; + unsigned char *in_end = in_buf + in_length; /* End on input buffer */ + unsigned long index; + long nr_array1[2]; + long nr_array2[2]; + int count = 0; + + out.pb = out_buf; + in.pb = in_buf; + nr_array1[0] = 0x2C; + nr_array1[1] = 0x2C; + in.pw++; + + /* 15007AD7 */ + for (count = 0; count < channels; count++) { + long temp; + temp = *(short *)in.pw++; + nr_array2[count] = temp; + if (out_length < 2) { + return out.pb - out_buf; + } + *out.pw++ = (unsigned short)temp; + out_length -= 2; + } + index = channels - 1; + while (in.pb < in_end) { + unsigned char one_byte = *in.pb++; + if (channels == 2) { + index = (index == 0) ? 1 : 0; + } + + /* + * Get one byte from input buffer + * 15007B25 + */ + if (one_byte & 0x80) { + /* 15007B32 */ + switch(one_byte & 0x7F) { + case 0: /* 15007B8E */ + if (nr_array1[index] != 0) { + nr_array1[index]--; + } + if (out_length < 2) { + break; + } + *out.pw++ = (unsigned short)nr_array2[index]; + out_length -= 2; + continue; + case 1: /* 15007B72 */ + nr_array1[index] += 8; /* EBX also */ + if (nr_array1[index] > 0x58) { + nr_array1[index] = 0x58; + } + if (channels == 2) { + index = (index == 0) ? 1 : 0; + } + continue; + case 2: + continue; + default: + nr_array1[index] -= 8; + if (nr_array1[index] < 0) { + nr_array1[index] = 0; + } + if (channels != 2) { + continue; + } + index = (index == 0) ? 1 : 0; + continue; + } + } else { + unsigned long temp1 = wave_table_1503f1a0[nr_array1[index]]; /* EDI */ + unsigned long temp2 = temp1 >> in_buf[1]; /* ESI */ + long temp3 = nr_array2[index]; /* ECX */ + if (one_byte & 0x01) { /* EBX = one_byte */ + temp2 += (temp1 >> 0); + } + if (one_byte & 0x02) { + temp2 += (temp1 >> 1); + } + if (one_byte & 0x04) { + temp2 += (temp1 >> 2); + } + if (one_byte & 0x08) { + temp2 += (temp1 >> 3); + } + if (one_byte & 0x10) { + temp2 += (temp1 >> 4); + } + if (one_byte & 0x20) { + temp2 += (temp1 >> 5); + } + if(one_byte & 0x40) { + temp3 -= temp2; + if (temp3 <= (long)0xFFFF8000) { + temp3 = (long)0xFFFF8000; + } + } else { + temp3 += temp2; + if (temp3 >= 0x7FFF) { + temp3 = 0x7FFF; + } + } + nr_array2[index] = temp3; + if (out_length < 2) { + break; + } + + temp2 = nr_array1[index]; + one_byte &= 0x1F; + *out.pw++ = (unsigned short)temp3; + out_length -= 2; + temp2 += wave_table_1503f120[one_byte]; + nr_array1[index] = temp2; + + if (nr_array1[index] < 0) { + nr_array1[index] = 0; + } else { + if (nr_array1[index] > 0x58) { + nr_array1[index] = 0x58; + } + } + } + } + return (out.pb - out_buf); +} diff --git a/contrib/extractor/libmpq/wave.h b/contrib/extractor/libmpq/wave.h new file mode 100644 index 00000000000..8920880a04f --- /dev/null +++ b/contrib/extractor/libmpq/wave.h @@ -0,0 +1,37 @@ +/* + * wave.h -- header file for WAVe unplode functions used by mpq-tools. + * + * Copyright (C) 2003 Maik Broemme + * + * This source was adepted from the C++ version of wave.h included + * in stormlib. The C++ version belongs to the following authors, + * + * Ladislav Zezula + * Tom Amigo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _WAVE_H +#define _WAVE_H + +typedef union { + unsigned short *pw; + unsigned char *pb; +} byte_and_short; + +int libmpq_wave_decompress(unsigned char *out_buf, int out_length, unsigned char *in_buf, int in_length, int channels); + +#endif /* _WAVE_H */ diff --git a/contrib/extractor/libmpq/zconf.h b/contrib/extractor/libmpq/zconf.h new file mode 100644 index 00000000000..3cea897eda7 --- /dev/null +++ b/contrib/extractor/libmpq/zconf.h @@ -0,0 +1,323 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflatePrime z_deflatePrime +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table + +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) +# define WIN32 +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +#define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/contrib/extractor/libmpq/zlib.h b/contrib/extractor/libmpq/zlib.h new file mode 100644 index 00000000000..92edf96ff3e --- /dev/null +++ b/contrib/extractor/libmpq/zlib.h @@ -0,0 +1,1200 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.1, November 17th, 2003 + + Copyright (C) 1995-2003 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.1" +#define ZLIB_VERNUM 0x1210 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by the in-memory functions is the zlib + format, which is a zlib wrapper documented in RFC 1950, wrapped around a + deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + This library does not provide any functions to write gzip files in memory. + However such functions could be easily written using zlib's deflate function, + the documentation in the gzip RFC, and the examples in gzio.c. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: ascii or binary */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_ASCII 1 +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + the compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + the value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update data_type if it can make a good guess about + the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, + Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() stop + if and when it get to the next deflate block boundary. When decoding the zlib + or gzip format, this will cause inflate() to return immediately after the + header and before the first block. When doing a raw inflate, inflate() will + go ahead and process the first block, and will return when it gets to the end + of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 + if inflate() is currently decoding the last block in the deflate stream, + plus 128 if inflate() returned immediately after decoding an end-of-block + code or decoding the complete header up to just before the first byte of the + deflate stream. The end-of-block will not be indicated until all of the + uncompressed data from that block has been written to strm->next_out. The + number of unused bits may in general be greater than seven, except when + bit 7 of data_type is set, in which case the number of unused bits will be + less than eight. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster approach + may be used for the single inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm-adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() will decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically. Any information + contained in the gzip header is not retained, so applications that need that + information should instead use raw inflate, see inflateInit2() below, or + inflateBack() and perform their own processing of the gzip header and + trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may then + call inflateSync() to look for a good compression block if a partial recovery + of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), + no header crc, and the operating system will be set to 255 (unknown). + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as + Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy + parameter only affects the compression ratio but not the correctness of the + compressed output even if it is not set appropriately. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() + or deflateInit2(). This would be used to allocate an output buffer + for deflation in a single pass, and so would be called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the + bits leftover from a previous deflate stream when appending to it. As such, + this function can only be used for raw deflate, and must be used before the + first deflate() call after a deflateInit2() or deflateReset(). bits must be + less than or equal to 16, and that many of the least significant bits of + value will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative + memLevel). msg is set to null if there is no error message. inflateInit2 + does not perform any decompression apart from reading the zlib header if + present: this will be done by inflate(). (So next_in and avail_in may be + modified, but next_out and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate + if this call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by this call of + inflate. The compressor and decompressor must use exactly the same + dictionary (see deflateSetDictionary). + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_stream FAR *strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not + be allocated, or Z_VERSION_ERROR if the version of the library does not + match the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_stream FAR *strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free + the allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects + only the raw deflate stream to decompress. This is different from the + normal behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format + error in the deflate stream (in which case strm->msg is set to indicate the + nature of the error), or Z_STREAM_ERROR if the stream was not properly + initialized. In the case of Z_BUF_ERROR, an input or output error can be + distinguished using strm->next_in which will be Z_NULL only if in() returned + an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to + out() returning non-zero. (in() will always be called before out(), so + strm->next_in is assured to be defined if out() returns non-zero.) Note + that inflateBack() cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_stream FAR *strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least the value returned + by compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before + a compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h", or 'R' for run-length encoding + as in "wb1R". (See the description of deflateInit2 for more information + about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). The number of + uncompressed bytes written is limited to 4095. The caller should assure that + this limit is not exceeded. If it is exceeded, then gzprintf() will return + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read again later. + Only one character of push-back is allowed. gzungetc() returns the + character pushed, or -1 on failure. gzungetc() will fail if a + character has been pushed but not read yet, or if c is -1. The pushed + character will be discarded if the stream is repositioned with gzseek() + or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); + +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running crc with the bytes buf[0..len-1] and return the updated + crc. If buf is NULL, this function returns the required initial value + for the crc. Pre- and post-conditioning (one's complement) is performed + within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_stream FAR *strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int err)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/contrib/extractor/mpq_libmpq.cpp b/contrib/extractor/mpq_libmpq.cpp new file mode 100644 index 00000000000..98d114c572f --- /dev/null +++ b/contrib/extractor/mpq_libmpq.cpp @@ -0,0 +1,133 @@ +#include "mpq_libmpq.h" +#include + +ArchiveSet gOpenArchives; + +MPQArchive::MPQArchive(const char* filename) +{ + int result = libmpq_archive_open(&mpq_a, (unsigned char*)filename); + printf("Opening %s\n", filename); + if(result) { + switch(result) { + case LIBMPQ_EFILE : /* error on file operation */ + printf("Error opening archive '%s': File operation Error\n", filename); + break; + case LIBMPQ_EFILE_FORMAT : /* bad file format */ + printf("Error opening archive '%s': Bad file format\n", filename); + break; + case LIBMPQ_EFILE_CORRUPT : /* file corrupt */ + printf("Error opening archive '%s': File corrupt\n", filename); + break; + case LIBMPQ_EFILE_NOT_FOUND : /* file in archive not found */ + printf("Error opening archive '%s': File in archive not found\n", filename); + break; + case LIBMPQ_EFILE_READ : /* Read error in archive */ + printf("Error opening archive '%s': Read error in archive\n", filename); + break; + case LIBMPQ_EALLOCMEM : /* maybe not enough memory? :) */ + printf("Error opening archive '%s': Maybe not enough memory\n", filename); + break; + case LIBMPQ_EFREEMEM : /* can not free memory */ + printf("Error opening archive '%s': Cannot free memory\n", filename); + break; + case LIBMPQ_EINV_RANGE : /* Given filenumber is out of range */ + printf("Error opening archive '%s': Given filenumber is out of range\n", filename); + break; + case LIBMPQ_EHASHTABLE : /* error in reading hashtable */ + printf("Error opening archive '%s': Error in reading hashtable\n", filename); + break; + case LIBMPQ_EBLOCKTABLE : /* error in reading blocktable */ + printf("Error opening archive '%s': Error in reading blocktable\n", filename); + break; + default: + printf("Error opening archive '%s': Unknown error\n", filename); + break; + } + return; + } + gOpenArchives.push_front(this); +} + +void MPQArchive::close() +{ + //gOpenArchives.erase(erase(&mpq_a); + libmpq_archive_close(&mpq_a); +} + +MPQFile::MPQFile(const char* filename): + eof(false), + buffer(0), + pointer(0), + size(0) +{ + for(ArchiveSet::iterator i=gOpenArchives.begin(); i!=gOpenArchives.end();++i) + { + mpq_archive &mpq_a = (*i)->mpq_a; + + mpq_hash hash = (*i)->GetHashEntry(filename); + uint32 blockindex = hash.blockindex; + + if ((blockindex == 0xFFFFFFFF) || (blockindex == 0)) { + continue; //file not found + } + + int fileno = blockindex; + + //int fileno = libmpq_file_number(&mpq_a, filename); + //if(fileno == LIBMPQ_EFILE_NOT_FOUND) + // continue; + + // Found! + size = libmpq_file_info(&mpq_a, LIBMPQ_FILE_UNCOMPRESSED_SIZE, fileno); + // HACK: in patch.mpq some files don't want to open and give 1 for filesize + if (size<=1) { + eof = true; + buffer = 0; + return; + } + buffer = new char[size]; + + //libmpq_file_getdata + libmpq_file_getdata(&mpq_a, hash, fileno, (unsigned char*)buffer); + return; + + } + eof = true; + buffer = 0; +} + +size_t MPQFile::read(void* dest, size_t bytes) +{ + if (eof) return 0; + + size_t rpos = pointer + bytes; + if (rpos > size) { + bytes = size - pointer; + eof = true; + } + + memcpy(dest, &(buffer[pointer]), bytes); + + pointer = rpos; + + return bytes; +} + +void MPQFile::seek(int offset) +{ + pointer = offset; + eof = (pointer >= size); +} + +void MPQFile::seekRelative(int offset) +{ + pointer += offset; + eof = (pointer >= size); +} + +void MPQFile::close() +{ + if (buffer) delete[] buffer; + buffer = 0; + eof = true; +} diff --git a/contrib/extractor/mpq_libmpq.h b/contrib/extractor/mpq_libmpq.h new file mode 100644 index 00000000000..542e7b21d17 --- /dev/null +++ b/contrib/extractor/mpq_libmpq.h @@ -0,0 +1,124 @@ +#define _CRT_SECURE_NO_DEPRECATE +#define _CRT_SECURE_NO_WARNINGS + +#ifndef MPQ_H +#define MPQ_H + +#include "libmpq/mpq.h" +#include +#include +#include +#include +#include + +using namespace std; + +typedef unsigned int uint32; +class MPQArchive +{ + +public: + mpq_archive mpq_a; + + MPQArchive(const char* filename); + void close(); + + uint32 HashString(const char* Input, uint32 Offset) { + uint32 seed1 = 0x7fed7fed; + uint32 seed2 = 0xeeeeeeee; + + for (uint32 i = 0; i < strlen(Input); i++) { + uint32 val = toupper(Input[i]); + seed1 = mpq_a.buf[Offset + val] ^ (seed1 + seed2); + seed2 = val + seed1 + seed2 + (seed2 << 5) + 3; + } + + return seed1; + } + mpq_hash GetHashEntry(const char* Filename) { + uint32 index = HashString(Filename, 0); + index &= mpq_a.header->hashtablesize - 1; + uint32 name1 = HashString(Filename, 0x100); + uint32 name2 = HashString(Filename, 0x200); + + for(uint32 i = index; i < mpq_a.header->hashtablesize; ++i) { + mpq_hash hash = mpq_a.hashtable[i]; + if (hash.name1 == name1 && hash.name2 == name2) return hash; + } + + mpq_hash nullhash; + nullhash.blockindex = 0xFFFFFFFF; + return nullhash; + } + + vector GetFileList() { + vector filelist; + + mpq_hash hash = GetHashEntry("(listfile)"); + uint32 blockindex = hash.blockindex; + + if ((blockindex == 0xFFFFFFFF) || (blockindex == 0)) + return filelist; + + uint32 size = libmpq_file_info(&mpq_a, LIBMPQ_FILE_UNCOMPRESSED_SIZE, blockindex); + char *buffer = new char[size]; + + libmpq_file_getdata(&mpq_a, hash, blockindex, (unsigned char*)buffer); + + char seps[] = "\n"; + char *token; + + token = strtok( buffer, seps ); + uint32 counter = 0; + while ((token != NULL) && (counter < size)) { + //cout << token << endl; + token[strlen(token) - 1] = 0; + string s = token; + filelist.push_back(s); + counter += strlen(token) + 2; + token = strtok(NULL, seps); + } + + delete buffer; + return filelist; + } +}; +typedef std::deque ArchiveSet; + +class MPQFile +{ + //MPQHANDLE handle; + bool eof; + char *buffer; + size_t pointer,size; + + // disable copying + MPQFile(const MPQFile &f) {} + void operator=(const MPQFile &f) {} + +public: + MPQFile(const char* filename); // filenames are not case sensitive + ~MPQFile() { close(); } + size_t read(void* dest, size_t bytes); + size_t getSize() { return size; } + size_t getPos() { return pointer; } + char* getBuffer() { return buffer; } + char* getPointer() { return buffer + pointer; } + bool isEof() { return eof; } + void seek(int offset); + void seekRelative(int offset); + void close(); +}; + +inline void flipcc(char *fcc) +{ + char t; + t=fcc[0]; + fcc[0]=fcc[3]; + fcc[3]=t; + t=fcc[1]; + fcc[1]=fcc[2]; + fcc[2]=t; +} + +#endif diff --git a/contrib/extractor/release/zlib.lib b/contrib/extractor/release/zlib.lib new file mode 100644 index 00000000000..42dded3ce23 Binary files /dev/null and b/contrib/extractor/release/zlib.lib differ diff --git a/contrib/vmap_assembler/VC71/vmap_assembler.vcproj b/contrib/vmap_assembler/VC71/vmap_assembler.vcproj new file mode 100644 index 00000000000..aaaeb4dfc3c --- /dev/null +++ b/contrib/vmap_assembler/VC71/vmap_assembler.vcproj @@ -0,0 +1,322 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/contrib/vmap_assembler/VC80/vmap_assembler.vcproj b/contrib/vmap_assembler/VC80/vmap_assembler.vcproj new file mode 100644 index 00000000000..3b3a58a05aa --- /dev/null +++ b/contrib/vmap_assembler/VC80/vmap_assembler.vcproj @@ -0,0 +1,456 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/contrib/vmap_assembler/splitConfig.txt b/contrib/vmap_assembler/splitConfig.txt new file mode 100644 index 00000000000..de8fd67bdc4 --- /dev/null +++ b/contrib/vmap_assembler/splitConfig.txt @@ -0,0 +1,17 @@ +# list of map names + +509 #AhnQiraj +469 #BlackwingLair +189 #MonasteryInstances +030 #PVPZone01 +037 #PVPZone02 +033 #Shadowfang +533 #Stratholme Raid +209 #TanarisInstance +309 #Zul'gurub +560 #HillsbradPast +534 #HyjalPast +532 #Karazahn +543 #HellfireRampart +568 #ZulAman +564 #BlackTemple diff --git a/contrib/vmap_assembler/vmap_assembler.cpp b/contrib/vmap_assembler/vmap_assembler.cpp new file mode 100644 index 00000000000..233d4ba3c28 --- /dev/null +++ b/contrib/vmap_assembler/vmap_assembler.cpp @@ -0,0 +1,118 @@ +#include +#include +#include + +#include "TileAssembler.h" + +//======================================================= +// remove last return or LF and tailing SPACE +// remove all char after a # + +void chompAndTrim(std::string& str) +{ + for(unsigned int i=0;i0) { + char lc = str[str.length()-1]; + if(lc == '\r' || lc == '\n' || lc == ' ') { + str = str.substr(0,str.length()-1); + } else { + break; + } + } +} + +//======================================================= +/** +This callback method is called for each model found in the dir file. +return true if it should be included in the vmap +*/ +bool modelNameFilter(char *pName) +{ +#if 0 + bool result; + result = !Wildcard::wildcardfit("*bush[0-9]*", pName); + if(result) result = !Wildcard::wildcardfit("*shrub[0-9]*", pName); + if(result) result = !Wildcard::wildcardfit("*_Bushes_*", pName); + if(result) result = !Wildcard::wildcardfit("*_Bush_*", pName); + if(!result) { + printf("%s",pName); + } +#endif + return true; +} + +//======================================================= +/** +File contains map names that should be split into tiles +A '#' at the beginning of a line defines a comment +*/ + +bool readConfigFile(char *pConffile, VMAP::TileAssembler* pTa) +{ + bool result = false; + char buffer[501]; + FILE *cf = fopen(pConffile, "rb"); + if(cf) { + while(fgets(buffer, 500, cf)) { + std::string name = std::string(buffer); + size_t pos = name.find_first_not_of(' '); + name = name.substr(pos); + chompAndTrim(name); // just to be sure + if(name[0] != '#' && name.size() >0) { // comment? + unsigned int mapId = atoi(name.c_str()); + pTa->addWorldAreaMapId(mapId); + } + } + fclose(cf); + result = true; + } + return(result); +} +//======================================================= +int main(int argc, char* argv[]) +{ + if(argc == 3 || argc == 4) + { + bool ok = true; + char *src = argv[1]; + char *dest = argv[2]; + char *conffile = NULL; + if(argc >= 4) { + conffile = argv[3]; + } + VMAP::TileAssembler* ta = new VMAP::TileAssembler(std::string(src), std::string(dest)); + ta->setModelNameFilterMethod(modelNameFilter); + + /* + All the names in the list are considered to be world maps or huge instances. + These maps will be spilt into tiles in the vmap assemble process + */ + if(conffile != NULL) { + ok = readConfigFile(conffile, ta); + if(!ok) { + printf("Can not open file config file: %s\n", conffile); + } + } + if(ok) { ok = ta->convertWorld(); } + if(ok) { + printf("Ok, all done\n"); + } else { + printf("exit with errors\n"); + return 1; + } + delete ta; + } + else + { + printf("\nusage: %s [config file name]\n", argv[0]); + return 1; + } + return 0; +} diff --git a/contrib/vmap_assembler/vmap_assemblerVC71.sln b/contrib/vmap_assembler/vmap_assemblerVC71.sln new file mode 100644 index 00000000000..8fc03541941 --- /dev/null +++ b/contrib/vmap_assembler/vmap_assemblerVC71.sln @@ -0,0 +1,23 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vmap_assembler", "VC71\vmap_assembler.vcproj", "{572FFF74-480C-4472-8ABF-81733BB4049D}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectDependencies) = postSolution + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {572FFF74-480C-4472-8ABF-81733BB4049D}.Debug.ActiveCfg = Debug|Win32 + {572FFF74-480C-4472-8ABF-81733BB4049D}.Debug.Build.0 = Debug|Win32 + {572FFF74-480C-4472-8ABF-81733BB4049D}.Release.ActiveCfg = Release|Win32 + {572FFF74-480C-4472-8ABF-81733BB4049D}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/contrib/vmap_assembler/vmap_assemblerVC80.sln b/contrib/vmap_assembler/vmap_assemblerVC80.sln new file mode 100644 index 00000000000..66489bd0a79 --- /dev/null +++ b/contrib/vmap_assembler/vmap_assemblerVC80.sln @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual C++ Express 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vmap_assembler", "VC80\vmap_assembler.vcproj", "{572FFF74-480C-4472-8ABF-81733BB4049D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {572FFF74-480C-4472-8ABF-81733BB4049D}.Debug|Win32.ActiveCfg = Debug|Win32 + {572FFF74-480C-4472-8ABF-81733BB4049D}.Debug|Win32.Build.0 = Debug|Win32 + {572FFF74-480C-4472-8ABF-81733BB4049D}.Release|Win32.ActiveCfg = Release|Win32 + {572FFF74-480C-4472-8ABF-81733BB4049D}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/contrib/vmap_debugger/G3D/AABSPTree.h b/contrib/vmap_debugger/G3D/AABSPTree.h new file mode 100644 index 00000000000..543f06a881e --- /dev/null +++ b/contrib/vmap_debugger/G3D/AABSPTree.h @@ -0,0 +1,1620 @@ +/** + @file AABSPTree.h + + @maintainer Morgan McGuire, matrix@graphics3d.com + + @created 2004-01-11 + @edited 2007-02-16 + + Copyright 2000-2007, Morgan McGuire. + All rights reserved. + + */ + +#ifndef G3D_AABSPTREE_H +#define G3D_AABSPTREE_H + +#include "VMapTools.h" + +#include "G3D/platform.h" +#include "G3D/Array.h" +#include "G3D/Table.h" +#include "G3D/Vector3.h" +#include "G3D/AABox.h" +#include "G3D/Sphere.h" +#include "G3D/Box.h" +#include "G3D/Triangle.h" +#include "G3D/Ray.h" +#include "G3D/GCamera.h" +#if 0 +#include "G3D/BinaryInput.h" +#include "G3D/BinaryOutput.h" +#endif +#include "G3D/CollisionDetection.h" +#include "G3D/GCamera.h" +#include + +// If defined, in debug mode the tree is checked for consistency +// as a way of detecting corruption due to implementation bugs +// #define VERIFY_TREE + +inline void getBounds(const G3D::Vector3& v, G3D::AABox& out) { + out = G3D::AABox(v); +} + + +inline void getBounds(const G3D::AABox& a, G3D::AABox& out) { + out = a; +} + +inline void getBounds(const G3D::Sphere& s, G3D::AABox& out) { + s.getBounds(out); +} + + +inline void getBounds(const G3D::Box& b, G3D::AABox& out) { + b.getBounds(out); +} + + +inline void getBounds(const G3D::Triangle& t, G3D::AABox& out) { + t.getBounds(out); +} + + + +inline void getBounds(const G3D::Vector3* v, G3D::AABox& out) { + out = G3D::AABox(*v); +} + + +inline void getBounds(const G3D::AABox* a, G3D::AABox& out) { + getBounds(*a, out); +} + +inline void getBounds(const G3D::Sphere* s, G3D::AABox& out) { + s->getBounds(out); +} + + +inline void getBounds(const G3D::Box* b, G3D::AABox& out) { + b->getBounds(out); +} + +inline void getBounds(const G3D::Triangle* t, G3D::AABox& out) { + t->getBounds(out); +} +namespace G3D { + namespace _internal { + + /** + Wraps a pointer value so that it can be treated as the instance itself; + convenient for inserting pointers into a Table but using the + object equality instead of pointer equality. + */ + template + class Indirector { + public: + Type* handle; + + inline Indirector(Type* h) : handle(h) {} + + inline Indirector() : handle(NULL) {} + + /** Returns true iff the values referenced by the handles are equivalent. */ + inline bool operator==(const Indirector& m) { + return *handle == *(m.handle); + } + + inline bool operator==(const Type& m) { + return *handle == m; + } + + inline size_t hashCode() const { + return handle->hashCode(); + } + }; + } // namespace internal +} // namespace G3D + +template +struct GHashCode > +{ + size_t operator()(const G3D::_internal::Indirector& key) const { return key.hashCode(); } +}; + +namespace G3D { + +/** + A set that supports spatial queries using an axis-aligned + BSP tree for speed. + + AABSPTree allows you to quickly find objects in 3D that lie within + a box or along a ray. For large sets of objects it is much faster + than testing each object for a collision. + + AABSPTree is as powerful as but more general than a Quad Tree, Oct + Tree, or KD Tree, but less general than an unconstrained BSP tree + (which is much slower to create). + + Internally, objects + are arranged into an axis-aligned BSP-tree according to their + axis-aligned bounds. This increases the cost of insertion to + O(log n) but allows fast overlap queries. + + Template Parameters +
The template parameter T must be one for which + the following functions are all overloaded: + +

void ::getBounds(const T&, G3D::AABox&); +

bool ::operator==(const T&, const T&); +
unsigned int ::hashCode(const T&); +
T::T(); (public constructor of no arguments) + + G3D provides these for common classes like G3D::Vector3 and G3D::Sphere. + If you use a custom class, or a pointer to a custom class, you will need + to define those functions. + + Moving %Set Members +
It is important that objects do not move without updating the + AABSPTree. If the axis-aligned bounds of an object are about + to change, AABSPTree::remove it before they change and + AABSPTree::insert it again afterward. For objects + where the hashCode and == operator are invariant with respect + to the 3D position, + you can use the AABSPTree::update method as a shortcut to + insert/remove an object in one step after it has moved. + + + Note: Do not mutate any value once it has been inserted into AABSPTree. Values + are copied interally. All AABSPTree iterators convert to pointers to constant + values to reinforce this. + + If you want to mutate the objects you intend to store in a AABSPTree + simply insert pointers to your objects instead of the objects + themselves, and ensure that the above operations are defined. (And + actually, because values are copied, if your values are large you may + want to insert pointers anyway, to save space and make the balance + operation faster.) + + Dimensions + Although designed as a 3D-data structure, you can use the AABSPTree + for data distributed along 2 or 1 axes by simply returning bounds + that are always zero along one or more dimensions. + +*/ +namespace _AABSPTree { + + /** Wrapper for a value that includes a cache of its bounds. + Except for the test value used in a set-query operation, there + is only ever one instance of the handle associated with any + value and the memberTable and Nodes maintain pointers to that + heap-allocated value. + */ + template + class Handle { + public: + /** The bounds of each object are constrained to AABox::maxFinite */ + AABox bounds; + + /** Center of bounds. We cache this value to avoid recomputing it + during the median sort, and because MSVC 6 std::sort goes into + an infinite loop if we compute the midpoint on the fly (possibly + a floating point roundoff issue, where B() {} + + inline Handle(const TValue& v) : value(v) { + getBounds(v, bounds); + bounds = bounds.intersect(AABox::maxFinite()); + center = bounds.center(); + } + + inline bool operator==(const Handle& other) const { + return (*value).operator==(*other.value); + } + + inline size_t hashCode() const { + return value->hashCode(); + } + }; + + template<> + class Handle { + public: + /** The bounds of each object are constrained to AABox::maxFinite */ + AABox bounds; + + /** Center of bounds. We cache this value to avoid recomputing it + during the median sort, and because MSVC 6 std::sort goes into + an infinite loop if we compute the midpoint on the fly (possibly + a floating point roundoff issue, where B() {} + + inline Handle(const Triangle& v) : value(v) { + getBounds(v, bounds); + bounds = bounds.intersect(AABox::maxFinite()); + center = bounds.center(); + } + + inline bool operator==(const Handle& other) const { + return value.operator==(other.value); + } + + inline size_t hashCode() const { + return value.hashCode(); + } + }; +} + +template class AABSPTree { +protected: +public: + + + /** Returns the bounds of the sub array. Used by makeNode. */ + static AABox computeBounds( + const Array<_AABSPTree::Handle*>& point, + int beginIndex, + int endIndex) { + + Vector3 lo = Vector3::inf(); + Vector3 hi = -lo; + + for (int p = beginIndex; p <= endIndex; ++p) { + lo = lo.min(point[p]->bounds.low()); + hi = hi.max(point[p]->bounds.high()); + } + + return AABox(lo, hi); + } + + /** Compares centers */ + class CenterComparator { + public: + Vector3::Axis sortAxis; + + CenterComparator(Vector3::Axis a) : sortAxis(a) {} + + inline int operator()(_AABSPTree::Handle* A, const _AABSPTree::Handle* B) const { + float a = A->center[sortAxis]; + float b = B->center[sortAxis]; + + if (a < b) { + return 1; + } else if (a > b) { + return -1; + } else { + return 0; + } + } + }; + + + /** Compares bounds for strict >, <, or overlap*/ + class BoundsComparator { + public: + Vector3::Axis sortAxis; + + BoundsComparator(Vector3::Axis a) : sortAxis(a) {} + + inline int operator()(_AABSPTree::Handle* A, const _AABSPTree::Handle* B) const { + const AABox& a = A->bounds; + const AABox& b = B->bounds; + + if (a.high()[sortAxis] < b.low()[sortAxis]) { + return 1; + } else if (a.low()[sortAxis] > b.high()[sortAxis]) { + return -1; + } else { + return 0; + } + } + }; + + + /** Compares bounds to the sort location */ + class Comparator { + public: + Vector3::Axis sortAxis; + float sortLocation; + + Comparator(Vector3::Axis a, float l) : sortAxis(a), sortLocation(l) {} + + inline int operator()(_AABSPTree::Handle* ignore, const _AABSPTree::Handle* handle) const { + const AABox& box = handle->bounds; + debugAssert(ignore == NULL); + + if (box.high()[sortAxis] < sortLocation) { + // Box is strictly below the sort location + return -1; + } else if (box.low()[sortAxis] > sortLocation) { + // Box is strictly above the sort location + return 1; + } else { + // Box overlaps the sort location + return 0; + } + } + }; + + // Using System::malloc with this class provided no speed improvement. + class Node { + public: + + /** Spatial bounds on all values at this node and its children, based purely on + the parent's splitting planes. May be infinite. */ + AABox splitBounds; + + Vector3::Axis splitAxis; + + /** Location along the specified axis */ + float splitLocation; + + /** child[0] contains all values strictly + smaller than splitLocation along splitAxis. + + child[1] contains all values strictly + larger. + + Both may be NULL if there are not enough + values to bother recursing. + */ + Node* child[2]; + + /** Array of values at this node (i.e., values + straddling the split plane + all values if + this is a leaf node). + + This is an array of pointers because that minimizes + data movement during tree building, which accounts + for about 15% of the time cost of tree building. + */ + Array<_AABSPTree::Handle * > valueArray; + + /** For each object in the value array, a copy of its bounds. + Packing these into an array at the node level + instead putting them in the valueArray improves + cache coherence, which is about a 3x performance + increase when performing intersection computations. + */ + Array boundsArray; + + /** Creates node with NULL children */ + Node() { + splitAxis = Vector3::X_AXIS; + splitLocation = 0; + splitBounds = AABox(-Vector3::inf(), Vector3::inf()); + for (int i = 0; i < 2; ++i) { + child[i] = NULL; + } + } + + /** + Doesn't clone children. + */ + Node(const Node& other) : valueArray(other.valueArray), boundsArray(other.boundsArray) { + splitAxis = other.splitAxis; + splitLocation = other.splitLocation; + splitBounds = other.splitBounds; + for (int i = 0; i < 2; ++i) { + child[i] = NULL; + } + } + + /** Copies the specified subarray of pt into point, NULLs the children. + Assumes a second pass will set splitBounds. */ + Node(const Array<_AABSPTree::Handle * >& pt) : valueArray(pt) { + splitAxis = Vector3::X_AXIS; + splitLocation = 0; + for (int i = 0; i < 2; ++i) { + child[i] = NULL; + } + + boundsArray.resize(valueArray.size()); + for (int i = 0; i < valueArray.size(); ++i) { + boundsArray[i] = valueArray[i]->bounds; + } + } + + /** Deletes the children (but not the values) */ + ~Node() { + for (int i = 0; i < 2; ++i) { + delete child[i]; + } + } + + /** Returns true if this node is a leaf (no children) */ + inline bool isLeaf() const { + return (child[0] == NULL) && (child[1] == NULL); + } + + + /** + Recursively appends all handles and children's handles + to the array. + */ + void getHandles(Array<_AABSPTree::Handle * >& handleArray) const { + handleArray.append(valueArray); + for (int i = 0; i < 2; ++i) { + if (child[i] != NULL) { + child[i]->getHandles(handleArray); + } + } + } + + void verifyNode(const Vector3& lo, const Vector3& hi) { + // debugPrintf("Verifying: split %d @ %f [%f, %f, %f], [%f, %f, %f]\n", + // splitAxis, splitLocation, lo.x, lo.y, lo.z, hi.x, hi.y, hi.z); + + debugAssert(lo == splitBounds.low()); + debugAssert(hi == splitBounds.high()); + + for (int i = 0; i < valueArray.length(); ++i) { + const AABox& b = valueArray[i]->bounds; + debugAssert(b == boundsArray[i]); + + for(int axis = 0; axis < 3; ++axis) { + debugAssert(b.low()[axis] <= b.high()[axis]); + debugAssert(b.low()[axis] >= lo[axis]); + debugAssert(b.high()[axis] <= hi[axis]); + } + } + + if (child[0] || child[1]) { + debugAssert(lo[splitAxis] < splitLocation); + debugAssert(hi[splitAxis] > splitLocation); + } + + Vector3 newLo = lo; + newLo[splitAxis] = splitLocation; + Vector3 newHi = hi; + newHi[splitAxis] = splitLocation; + + if (child[0] != NULL) { + child[0]->verifyNode(lo, newHi); + } + + if (child[1] != NULL) { + child[1]->verifyNode(newLo, hi); + } + } + +#if 0 + /** + Stores the locations of the splitting planes (the structure but not the content) + so that the tree can be quickly rebuilt from a previous configuration without + calling balance. + */ + static void serializeStructure(const Node* n, BinaryOutput& bo) { + if (n == NULL) { + bo.writeUInt8(0); + } else { + bo.writeUInt8(1); + n->splitBounds.serialize(bo); + serialize(n->splitAxis, bo); + bo.writeFloat32(n->splitLocation); + for (int c = 0; c < 2; ++c) { + serializeStructure(n->child[c], bo); + } + } + } + + /** Clears the member table */ + static Node* deserializeStructure(BinaryInput& bi) { + if (bi.readUInt8() == 0) { + return NULL; + } else { + Node* n = new Node(); + n->splitBounds.deserialize(bi); + deserialize(n->splitAxis, bi); + n->splitLocation = bi.readFloat32(); + for (int c = 0; c < 2; ++c) { + n->child[c] = deserializeStructure(bi); + } + } + } +#endif + /** Returns the deepest node that completely contains bounds. */ + Node* findDeepestContainingNode(const AABox& bounds) { + + // See which side of the splitting plane the bounds are on + if (bounds.high()[splitAxis] < splitLocation) { + // Bounds are on the low side. Recurse into the child + // if it exists. + if (child[0] != NULL) { + return child[0]->findDeepestContainingNode(bounds); + } + } else if (bounds.low()[splitAxis] > splitLocation) { + // Bounds are on the high side, recurse into the child + // if it exists. + if (child[1] != NULL) { + return child[1]->findDeepestContainingNode(bounds); + } + } + + // There was no containing child, so this node is the + // deepest containing node. + return this; + } + + + /** Appends all members that intersect the box. + If useSphere is true, members that pass the box test + face a second test against the sphere. */ + void getIntersectingMembers( + const AABox& box, + const Sphere& sphere, + Array& members, + bool useSphere) const { + + // Test all values at this node + for (int v = 0; v < boundsArray.size(); ++v) { + const AABox& bounds = boundsArray[v]; + if (bounds.intersects(box) && + (! useSphere || bounds.intersects(sphere))) { + members.append(valueArray[v]->value); + } + } + + // If the left child overlaps the box, recurse into it + if ((child[0] != NULL) && (box.low()[splitAxis] < splitLocation)) { + child[0]->getIntersectingMembers(box, sphere, members, useSphere); + } + + // If the right child overlaps the box, recurse into it + if ((child[1] != NULL) && (box.high()[splitAxis] > splitLocation)) { + child[1]->getIntersectingMembers(box, sphere, members, useSphere); + } + } + + /** + Recurse through the tree, assigning splitBounds fields. + */ + void assignSplitBounds(const AABox& myBounds) { + splitBounds = myBounds; + + AABox childBounds[2]; + myBounds.split(splitAxis, splitLocation, childBounds[0], childBounds[1]); + +# if defined(G3D_DEBUG) && defined(VERIFY_TREE) + // Verify the split + for (int v = 0; v < boundsArray.size(); ++v) { + const AABox& bounds = boundsArray[v]; + debugAssert(myBounds.contains(bounds)); + } +# endif + + for (int c = 0; c < 2; ++c) { + if (child[c]) { + child[c]->assignSplitBounds(childBounds[c]); + } + } + } + + /** Returns true if the ray intersects this node */ + bool intersects(const Ray& ray, float distance) const { + // See if the ray will ever hit this node or its children + Vector3 location; + bool alreadyInsideBounds = false; + bool rayWillHitBounds = + VMAP::MyCollisionDetection::collisionLocationForMovingPointFixedAABox( + ray.origin, ray.direction, splitBounds, location, alreadyInsideBounds); + + bool canHitThisNode = (alreadyInsideBounds || + (rayWillHitBounds && ((location - ray.origin).squaredLength() < square(distance)))); + + return canHitThisNode; + } + + template + void intersectRay( + const Ray& ray, + RayCallback& intersectCallback, + float& distance, + bool pStopAtFirstHit, + bool intersectCallbackIsFast) const { + float enterDistance = distance; + + if (! intersects(ray, distance)) { + // The ray doesn't hit this node, so it can't hit the children of the node. + return; + } + + // Test for intersection against every object at this node. + for (int v = 0; v < valueArray.size(); ++v) { + bool canHitThisObject = true; + + if (! intersectCallbackIsFast) { + // See if + Vector3 location; + const AABox& bounds = boundsArray[v]; + bool alreadyInsideBounds = false; + bool rayWillHitBounds = + VMAP::MyCollisionDetection::collisionLocationForMovingPointFixedAABox( + ray.origin, ray.direction, bounds, location, alreadyInsideBounds); + + canHitThisObject = (alreadyInsideBounds || + (rayWillHitBounds && ((location - ray.origin).squaredLength() < square(distance)))); + } + + if (canHitThisObject) { + // It is possible that this ray hits this object. Look for the intersection using the + // callback. + const T& value = valueArray[v]->value; + intersectCallback(ray, value, pStopAtFirstHit, distance); + } + if(pStopAtFirstHit && distance < enterDistance) + return; + } + + // There are three cases to consider next: + // + // 1. the ray can start on one side of the splitting plane and never enter the other, + // 2. the ray can start on one side and enter the other, and + // 3. the ray can travel exactly down the splitting plane + + enum {NONE = -1}; + int firstChild = NONE; + int secondChild = NONE; + + if (ray.origin[splitAxis] < splitLocation) { + + // The ray starts on the small side + firstChild = 0; + + if (ray.direction[splitAxis] > 0) { + // The ray will eventually reach the other side + secondChild = 1; + } + + } else if (ray.origin[splitAxis] > splitLocation) { + + // The ray starts on the large side + firstChild = 1; + + if (ray.direction[splitAxis] < 0) { + secondChild = 0; + } + } else { + // The ray starts on the splitting plane + if (ray.direction[splitAxis] < 0) { + // ...and goes to the small side + firstChild = 0; + } else if (ray.direction[splitAxis] > 0) { + // ...and goes to the large side + firstChild = 1; + } + } + + // Test on the side closer to the ray origin. + if ((firstChild != NONE) && child[firstChild]) { + child[firstChild]->intersectRay(ray, intersectCallback, distance, pStopAtFirstHit, intersectCallbackIsFast); + if(pStopAtFirstHit && distance < enterDistance) + return; + } + + if (ray.direction[splitAxis] != 0) { + // See if there was an intersection before hitting the splitting plane. + // If so, there is no need to look on the far side and recursion terminates. + float distanceToSplittingPlane = (splitLocation - ray.origin[splitAxis]) / ray.direction[splitAxis]; + if (distanceToSplittingPlane > distance) { + // We aren't going to hit anything else before hitting the splitting plane, + // so don't bother looking on the far side of the splitting plane at the other + // child. + return; + } + } + + // Test on the side farther from the ray origin. + if ((secondChild != NONE) && child[secondChild]) { + child[secondChild]->intersectRay(ray, intersectCallback, distance, pStopAtFirstHit, intersectCallbackIsFast); + } + + } + }; + + + /** + Recursively subdivides the subarray. + + Clears the source array as soon as it is no longer needed. + + Call assignSplitBounds() on the root node after making a tree. + */ + Node* makeNode( + Array<_AABSPTree::Handle * >& source, + int valuesPerNode, + int numMeanSplits, + Array<_AABSPTree::Handle * >& temp) { + + Node* node = NULL; + + if (source.size() <= valuesPerNode) { + // Make a new leaf node + node = new Node(source); + + // Set the pointers in the memberTable + for (int i = 0; i < source.size(); ++i) { + memberTable.set(Member(source[i]), node); + } + source.clear(); + + } else { + // Make a new internal node + node = new Node(); + + const AABox bounds = computeBounds(source, 0, source.size() - 1); + const Vector3 extent = bounds.high() - bounds.low(); + + Vector3::Axis splitAxis = extent.primaryAxis(); + + float splitLocation; + + // Arrays for holding the children + Array<_AABSPTree::Handle * > lt, gt; + + if (numMeanSplits <= 0) { + + source.medianPartition(lt, node->valueArray, gt, temp, CenterComparator(splitAxis)); + + // Choose the split location to be the center of whatever fell in the center + splitLocation = node->valueArray[0]->center[splitAxis]; + + // Some of the elements in the lt or gt array might really overlap the split location. + // Move them as needed. + for (int i = 0; i < lt.size(); ++i) { + const AABox& bounds = lt[i]->bounds; + if ((bounds.low()[splitAxis] <= splitLocation) && (bounds.high()[splitAxis] >= splitLocation)) { + node->valueArray.append(lt[i]); + // Remove this element and process the new one that + // is swapped in in its place. + lt.fastRemove(i); --i; + } + } + + for (int i = 0; i < gt.size(); ++i) { + const AABox& bounds = gt[i]->bounds; + if ((bounds.low()[splitAxis] <= splitLocation) && (bounds.high()[splitAxis] >= splitLocation)) { + node->valueArray.append(gt[i]); + // Remove this element and process the new one that + // is swapped in in its place. + gt.fastRemove(i); --i; + } + } + + if ((node->valueArray.size() > (source.size() / 2)) && + (source.size() > 6)) { + // This was a bad partition; we ended up putting the splitting plane right in the middle of most of the + // objects. We could try to split on a different axis, or use a different partition (e.g., the extents mean, + // or geometric mean). This implementation falls back on the extents mean, since that case is already handled + // below. + numMeanSplits = 1; + } + } + + // Note: numMeanSplits may have been increased by the code in the previous case above in order to + // force a re-partition. + + if (numMeanSplits > 0) { + // Split along the mean + splitLocation = (bounds.high()[splitAxis] + + bounds.low()[splitAxis]) / 2.0; + + source.partition(NULL, lt, node->valueArray, gt, Comparator(splitAxis, splitLocation)); + + // The Comparator ensures that elements are strictly on the correct side of the split + } + + +# if defined(G3D_DEBUG) && defined(VERIFY_TREE) + debugAssert(lt.size() + node->valueArray.size() + gt.size() == source.size()); + // Verify that all objects ended up on the correct side of the split. + // (i.e., make sure that the Array partition was correct) + for (int i = 0; i < lt.size(); ++i) { + const AABox& bounds = lt[i]->bounds; + debugAssert(bounds.high()[splitAxis] < splitLocation); + } + + for (int i = 0; i < gt.size(); ++i) { + const AABox& bounds = gt[i]->bounds; + debugAssert(bounds.low()[splitAxis] > splitLocation); + } + + for (int i = 0; i < node->valueArray.size(); ++i) { + const AABox& bounds = node->valueArray[i]->bounds; + debugAssert(bounds.high()[splitAxis] >= splitLocation); + debugAssert(bounds.low()[splitAxis] <= splitLocation); + } +# endif + + // The source array is no longer needed + source.clear(); + + node->splitAxis = splitAxis; + node->splitLocation = splitLocation; + + // Update the bounds array and member table + node->boundsArray.resize(node->valueArray.size()); + for (int i = 0; i < node->valueArray.size(); ++i) { + _AABSPTree::Handle * v = node->valueArray[i]; + node->boundsArray[i] = v->bounds; + memberTable.set(Member(v), node); + } + + if (lt.size() > 0) { + node->child[0] = makeNode(lt, valuesPerNode, numMeanSplits - 1, temp); + } + + if (gt.size() > 0) { + node->child[1] = makeNode(gt, valuesPerNode, numMeanSplits - 1, temp); + } + + } + + return node; + } + + /** + Recursively clone the passed in node tree, setting + pointers for members in the memberTable as appropriate. + called by the assignment operator. + */ + Node* cloneTree(Node* src) { + Node* dst = new Node(*src); + + // Make back pointers + for (int i = 0; i < dst->valueArray.size(); ++i) { + memberTable.set(Member(dst->valueArray[i]), dst); + } + + // Clone children + for (int i = 0; i < 2; ++i) { + if (src->child[i] != NULL) { + dst->child[i] = cloneTree(src->child[i]); + } + } + + return dst; + } + + /** + Wrapper for a Handle; used to create a memberTable that acts like Table but + stores only Handle* internally to avoid memory copies. + */ + typedef _internal::Indirector<_AABSPTree::Handle > Member; + + typedef Table MemberTable; + + /** Maps members to the node containing them */ + MemberTable memberTable; + + Node* root; + +public: + + /** To construct a balanced tree, insert the elements and then call + AABSPTree::balance(). */ + AABSPTree() : root(NULL) {} + + + AABSPTree(const AABSPTree& src) : root(NULL) { + *this = src; + } + + + AABSPTree& operator=(const AABSPTree& src) { + delete root; + // Clone tree takes care of filling out the memberTable. + root = cloneTree(src.root); + return *this; + } + + + ~AABSPTree() { + clear(); + } + + /** + Throws out all elements of the set. + */ + void clear() { + typedef typename Table<_internal::Indirector<_AABSPTree::Handle >, Node* >::Iterator It; + + // Delete all handles stored in the member table + It cur = memberTable.begin(); + It end = memberTable.end(); + while (cur != end) { + delete cur->key.handle; + cur->key.handle = NULL; + ++cur; + } + memberTable.clear(); + + // Delete the tree structure itself + delete root; + root = NULL; + } + + size_t size() const { + return memberTable.size(); + } + + /** + Inserts an object into the set if it is not + already present. O(log n) time. Does not + cause the tree to be balanced. + */ + void insert(const T& value) { + if (contains(value)) { + // Already in the set + return; + } + + _AABSPTree::Handle* h = new _AABSPTree::Handle(value); + + if (root == NULL) { + // This is the first node; create a root node + root = new Node(); + } + + Node* node = root->findDeepestContainingNode(h->bounds); + + // Insert into the node + node->valueArray.append(h); + node->boundsArray.append(h->bounds); + + // Insert into the node table + Member m(h); + memberTable.set(m, node); + } + + /** Inserts each elements in the array in turn. If the tree + begins empty (no structure and no elements), this is faster + than inserting each element in turn. You still need to balance + the tree at the end.*/ + void insert(const Array& valueArray) { + if (root == NULL) { + // Optimized case for an empty tree; don't bother + // searching or reallocating the root node's valueArray + // as we incrementally insert. + root = new Node(); + root->valueArray.resize(valueArray.size()); + root->boundsArray.resize(root->valueArray.size()); + for (int i = 0; i < valueArray.size(); ++i) { + // Insert in opposite order so that we have the exact same + // data structure as if we inserted each (i.e., order is reversed + // from array). + _AABSPTree::Handle* h = new _AABSPTree::Handle(valueArray[i]); + int j = valueArray.size() - i - 1; + root->valueArray[j] = h; + root->boundsArray[j] = h->bounds; + memberTable.set(Member(h), root); + } + + } else { + // Insert at appropriate tree depth. + for (int i = 0; i < valueArray.size(); ++i) { + insert(valueArray[i]); + } + } + } + + + /** + Returns true if this object is in the set, otherwise + returns false. O(1) time. + */ + bool contains(const T& value) { + // Temporarily create a handle and member + _AABSPTree::Handle h(value); + return memberTable.containsKey(Member(&h)); + } + + + /** + Removes an object from the set in O(1) time. + It is an error to remove members that are not already + present. May unbalance the tree. + + Removing an element never causes a node (split plane) to be removed... + nodes are only changed when the tree is rebalanced. This behavior + is desirable because it allows the split planes to be serialized, + and then deserialized into an empty tree which can be repopulated. + */ + void remove(const T& value) { + debugAssertM(contains(value), + "Tried to remove an element from a " + "AABSPTree that was not present"); + + // Get the list of elements at the node + _AABSPTree::Handle h(value); + Member m(&h); + + Array<_AABSPTree::Handle * >& list = memberTable[m]->valueArray; + + _AABSPTree::Handle* ptr = NULL; + + // Find the element and remove it + for (int i = list.length() - 1; i >= 0; --i) { + if (list[i]->value == value) { + // This was the element. Grab the pointer so that + // we can delete it below + ptr = list[i]; + + // Remove the handle from the node + list.fastRemove(i); + + // Remove the corresponding bounds + memberTable[m]->boundsArray.fastRemove(i); + break; + } + } + + // Remove the member + memberTable.remove(m); + + // Delete the handle data structure + delete ptr; + ptr = NULL; + } + + + /** + If the element is in the set, it is removed. + The element is then inserted. + + This is useful when the == and hashCode methods + on T are independent of the bounds. In + that case, you may call update(v) to insert an + element for the first time and call update(v) + again every time it moves to keep the tree + up to date. + */ + void update(const T& value) { + if (contains(value)) { + remove(value); + } + insert(value); + } + + + /** + Rebalances the tree (slow). Call when objects + have moved substantially from their original positions + (which unbalances the tree and causes the spatial + queries to be slow). + + @param valuesPerNode Maximum number of elements to put at + a node. + + @param numMeanSplits numMeanSplits = 0 gives a + fully axis aligned BSP-tree, where the balance operation attempts to balance + the tree so that every splitting plane has an equal number of left + and right children (i.e. it is a median split along that axis). + This tends to maximize average performance. + + You can override this behavior by + setting a number of mean (average) splits. numMeanSplits = MAX_INT + creates a full oct-tree, which tends to optimize peak performance at the expense of + average performance. It tends to have better clustering behavior when + members are not uniformly distributed. + */ + void balance(int valuesPerNode = 5, int numMeanSplits = 3) { + if (root == NULL) { + // Tree is empty + return; + } + + // Get all handles and delete the old tree structure + Node* oldRoot = root; + for (int c = 0; c < 2; ++c) { + if (root->child[c] != NULL) { + root->child[c]->getHandles(root->valueArray); + + // Delete the child; this will delete all structure below it + delete root->child[c]; + root->child[c] = NULL; + } + } + + Array<_AABSPTree::Handle * > temp; + // Make a new root. Work with a copy of the value array because + // makeNode clears the source array as it progresses + Array<_AABSPTree::Handle * > copy(oldRoot->valueArray); + root = makeNode(copy, valuesPerNode, numMeanSplits, temp); + + // Throw away the old root node + delete oldRoot; + oldRoot = NULL; + + // Walk the tree, assigning splitBounds. We start with unbounded + // space. This will override the current member table. + root->assignSplitBounds(AABox::maxFinite()); + +# ifdef _DEBUG + // Ensure that the balanced tree is till correct + root->verifyNode(Vector3::minFinite(), Vector3::maxFinite()); +# endif + } + +protected: + + /** + @param parentMask The mask that this node returned from culledBy. + */ + static void getIntersectingMembers( + const Array& plane, + Array& members, + Node* node, + uint32 parentMask) { + + int dummy; + + if (parentMask == 0) { + // None of these planes can cull anything + for (int v = node->valueArray.size() - 1; v >= 0; --v) { + members.append(node->valueArray[v]->value); + } + + // Iterate through child nodes + for (int c = 0; c < 2; ++c) { + if (node->child[c]) { + getIntersectingMembers(plane, members, node->child[c], 0); + } + } + } else { + + // Test values at this node against remaining planes + for (int v = node->boundsArray.size() - 1; v >= 0; --v) { + if (! node->boundsArray[v].culledBy(plane, dummy, parentMask)) { + members.append(node->valueArray[v]->value); + } + } + + uint32 childMask = 0xFFFFFF; + + // Iterate through child nodes + for (int c = 0; c < 2; ++c) { + if (node->child[c] && + ! node->child[c]->splitBounds.culledBy(plane, dummy, parentMask, childMask)) { + // This node was not culled + getIntersectingMembers(plane, members, node->child[c], childMask); + } + } + } + } + +public: + + /** + Returns all members inside the set of planes. + @param members The results are appended to this array. + */ + void getIntersectingMembers(const Array& plane, Array& members) const { + if (root == NULL) { + return; + } + + getIntersectingMembers(plane, members, root, 0xFFFFFF); + } + + /** + Typically used to find all visible + objects inside the view frustum (see also GCamera::getClipPlanes)... i.e. all objects + not culled by frustum. + + Example: +
+        Array  visible;
+        tree.getIntersectingMembers(camera.frustum(), visible);
+        // ... Draw all objects in the visible array.
+      
+ @param members The results are appended to this array. + */ + void getIntersectingMembers(const GCamera::Frustum& frustum, Array& members) const { + Array plane; + + for (int i = 0; i < frustum.faceArray.size(); ++i) { + plane.append(frustum.faceArray[i].plane); + } + + getIntersectingMembers(plane, members); + } + + /** + C++ STL style iterator variable. See beginBoxIntersection(). + The iterator overloads the -> (dereference) operator, so this + acts like a pointer to the current member. + */ + // This iterator turns Node::getIntersectingMembers into a + // coroutine. It first translates that method from recursive to + // stack based, then captures the system state (analogous to a Scheme + // continuation) after each element is appended to the member array, + // and allowing the computation to be restarted. + class BoxIntersectionIterator { + private: + friend class AABSPTree; + + /** True if this is the "end" iterator instance */ + bool isEnd; + + /** The box that we're testing against. */ + AABox box; + + /** Node that we're currently looking at. Undefined if isEnd + is true. */ + Node* node; + + /** Nodes waiting to be processed */ + // We could use backpointers within the tree and careful + // state management to avoid ever storing the stack-- but + // it is much easier this way and only inefficient if the + // caller uses post increment (which they shouldn't!). + Array stack; + + /** The next index of current->valueArray to return. + Undefined when isEnd is true.*/ + int nextValueArrayIndex; + + BoxIntersectionIterator() : isEnd(true) {} + + BoxIntersectionIterator(const AABox& b, const Node* root) : + isEnd(root == NULL), box(b), + node(const_cast(root)), nextValueArrayIndex(-1) { + + // We intentionally start at the "-1" index of the current + // node so we can use the preincrement operator to move + // ourselves to element 0 instead of repeating all of the + // code from the preincrement method. Note that this might + // cause us to become the "end" instance. + ++(*this); + } + + public: + + inline bool operator!=(const BoxIntersectionIterator& other) const { + return ! (*this == other); + } + + bool operator==(const BoxIntersectionIterator& other) const { + if (isEnd) { + return other.isEnd; + } else if (other.isEnd) { + return false; + } else { + // Two non-end iterators; see if they match. This is kind of + // silly; users shouldn't call == on iterators in general unless + // one of them is the end iterator. + if ((box != other.box) || (node != other.node) || + (nextValueArrayIndex != other.nextValueArrayIndex) || + (stack.length() != other.stack.length())) { + return false; + } + + // See if the stacks are the same + for (int i = 0; i < stack.length(); ++i) { + if (stack[i] != other.stack[i]) { + return false; + } + } + + // We failed to find a difference; they must be the same + return true; + } + } + + /** + Pre increment. + */ + BoxIntersectionIterator& operator++() { + ++nextValueArrayIndex; + + bool foundIntersection = false; + while (! isEnd && ! foundIntersection) { + + // Search for the next node if we've exhausted this one + while ((! isEnd) && (nextValueArrayIndex >= node->valueArray.length())) { + // If we entered this loop, then the iterator has exhausted the elements at + // node (possibly because it just switched to a child node with no members). + // This loop continues until it finds a node with members or reaches + // the end of the whole intersection search. + + // If the right child overlaps the box, push it onto the stack for + // processing. + if ((node->child[1] != NULL) && + (box.high()[node->splitAxis] > node->splitLocation)) { + stack.push(node->child[1]); + } + + // If the left child overlaps the box, push it onto the stack for + // processing. + if ((node->child[0] != NULL) && + (box.low()[node->splitAxis] < node->splitLocation)) { + stack.push(node->child[0]); + } + + if (stack.length() > 0) { + // Go on to the next node (which may be either one of the ones we + // just pushed, or one from farther back the tree). + node = stack.pop(); + nextValueArrayIndex = 0; + } else { + // That was the last node; we're done iterating + isEnd = true; + } + } + + // Search for the next intersection at this node until we run out of children + while (! isEnd && ! foundIntersection && (nextValueArrayIndex < node->valueArray.length())) { + if (box.intersects(node->boundsArray[nextValueArrayIndex])) { + foundIntersection = true; + } else { + ++nextValueArrayIndex; + // If we exhaust this node, we'll loop around the master loop + // to find a new node. + } + } + } + + return *this; + } + + private: + /** + Post increment (much slower than preincrement!). Intentionally overloaded to preclude accidentally slow code. + */ + BoxIntersectionIterator operator++(int); + /*{ + BoxIntersectionIterator old = *this; + ++this; + return old; + }*/ + + public: + + /** Overloaded dereference operator so the iterator can masquerade as a pointer + to a member */ + const T& operator*() const { + alwaysAssertM(! isEnd, "Can't dereference the end element of an iterator"); + return node->valueArray[nextValueArrayIndex]->value; + } + + /** Overloaded dereference operator so the iterator can masquerade as a pointer + to a member */ + T const * operator->() const { + alwaysAssertM(! isEnd, "Can't dereference the end element of an iterator"); + return &(stack.last()->valueArray[nextValueArrayIndex]->value); + } + + /** Overloaded cast operator so the iterator can masquerade as a pointer + to a member */ + operator T*() const { + alwaysAssertM(! isEnd, "Can't dereference the end element of an iterator"); + return &(stack.last()->valueArray[nextValueArrayIndex]->value); + } + }; + + + /** + Iterates through the members that intersect the box + */ + BoxIntersectionIterator beginBoxIntersection(const AABox& box) const { + return BoxIntersectionIterator(box, root); + } + + BoxIntersectionIterator endBoxIntersection() const { + // The "end" iterator instance + return BoxIntersectionIterator(); + } + + /** + Appends all members whose bounds intersect the box. + See also AABSPTree::beginBoxIntersection. + */ + void getIntersectingMembers(const AABox& box, Array& members) const { + if (root == NULL) { + return; + } + root->getIntersectingMembers(box, Sphere(Vector3::zero(), 0), members, false); + } + + + /** + Invoke a callback for every member along a ray until the closest intersection is found. + + @param callback either a function or an instance of a class with an overloaded operator() of the form: + + void callback(const Ray& ray, const T& object, float& distance). If the ray hits the object + before travelling distance distance, updates distance with the new distance to + the intersection, otherwise leaves it unmodified. A common example is: + +
+            class Entity {
+            public:
+
+                void intersect(const Ray& ray, float& maxDist, Vector3& outLocation, Vector3& outNormal) {
+                    float d = maxDist;
+
+                    // ... search for intersection distance d
+
+                    if ((d > 0) && (d < maxDist)) {
+                        // Intersection occured
+                        maxDist = d;
+                        outLocation = ...;
+                        outNormal = ...;
+                    }
+                }
+            };
+
+            // Finds the surface normal and location of the first intersection with the scene
+            class Intersection {
+            public:
+                Entity*     closestEntity;
+                Vector3     hitLocation;
+                Vector3     hitNormal;
+
+                void operator()(const Ray& ray, const Entity* entity, float& distance) {
+                    entity->intersect(ray, distance, hitLocation, hitNormal);
+                }
+            };
+
+            AABSPTree scene;
+
+            Intersection intersection;
+            float distance = inf();
+            scene.intersectRay(camera.worldRay(x, y), intersection, distance);
+          
+ + + @param distance When the method is invoked, this is the maximum distance that the tree should search for an intersection. + On return, this is set to the distance to the first intersection encountered. + + @param intersectCallbackIsFast If false, each object's bounds are tested before the intersectCallback is invoked. + If the intersect callback runs at the same speed or faster than AABox-ray intersection, set this to true. + */ + template + void intersectRay( + const Ray& ray, + RayCallback& intersectCallback, + float& distance, + bool pStopAtFirstHit, + bool intersectCallbackIsFast = false) const { + + root->intersectRay(ray, intersectCallback, distance, pStopAtFirstHit, intersectCallbackIsFast); + + } + + + /** + @param members The results are appended to this array. + */ + void getIntersectingMembers(const Sphere& sphere, Array& members) const { + if (root == NULL) { + return; + } + + AABox box; + sphere.getBounds(box); + root->getIntersectingMembers(box, sphere, members, true); + + } +#if 0 + /** + Stores the locations of the splitting planes (the structure but not the content) + so that the tree can be quickly rebuilt from a previous configuration without + calling balance. + */ + void serializeStructure(BinaryOutput& bo) const { + Node::serializeStructure(root, bo); + } + + /** Clears the member table */ + void deserializeStructure(BinaryInput& bi) { + clear(); + root = Node::deserializeStructure(bi); + } +#endif + /** + Returns an array of all members of the set. See also AABSPTree::begin. + */ + void getMembers(Array& members) const { + Array temp; + memberTable.getKeys(temp); + for (int i = 0; i < temp.size(); ++i) { + members.append(temp[i].handle->value); + } + } + + + /** + C++ STL style iterator variable. See begin(). + Overloads the -> (dereference) operator, so this acts like a pointer + to the current member. + */ + class Iterator { + private: + friend class AABSPTree; + + // Note: this is a Table iterator, we are currently defining + // Set iterator + typename Table::Iterator it; + + Iterator(const typename Table::Iterator& it) : it(it) {} + + public: + + inline bool operator!=(const Iterator& other) const { + return !(*this == other); + } + + bool operator==(const Iterator& other) const { + return it == other.it; + } + + /** + Pre increment. + */ + Iterator& operator++() { + ++it; + return *this; + } + + private: + /** + Post increment (slower than preincrement). Intentionally unimplemented to prevent slow code. + */ + Iterator operator++(int);/* { + Iterator old = *this; + ++(*this); + return old; + }*/ + public: + + const T& operator*() const { + return it->key.handle->value; + } + + T* operator->() const { + return &(it->key.handle->value); + } + + operator T*() const { + return &(it->key.handle->value); + } + }; + + + /** + C++ STL style iterator method. Returns the first member. + Use preincrement (++entry) to get to the next element (iteration + order is arbitrary). + Do not modify the set while iterating. + */ + Iterator begin() const { + return Iterator(memberTable.begin()); + } + + + /** + C++ STL style iterator method. Returns one after the last iterator + element. + */ + Iterator end() const { + return Iterator(memberTable.end()); + } +}; + +} + +#endif + + + diff --git a/contrib/vmap_debugger/ModelContainerView.cpp b/contrib/vmap_debugger/ModelContainerView.cpp new file mode 100644 index 00000000000..c29666c0bca --- /dev/null +++ b/contrib/vmap_debugger/ModelContainerView.cpp @@ -0,0 +1,570 @@ +#include "ModelContainerView.h" + +namespace VMAP +{ + char* gDataDir = NULL; + char* gLogFile = NULL; + //========================================== + + ModelContainerView::ModelContainerView(const G3D::GApp::Settings& settings) : GApp(settings) { + i_App = this; + + iCommandFileRW.setFileName(gLogFile); + iCurrCmdIndex = 0; + iVMapManager = new VMapManager(); + iDrawLine = false; + + iVARAreaRef = VARArea::create(1024*1024*60); + iVARAreaRef2 = VARArea::create(1024*1024*2); + iInstanceId = -1; + iPosSent = false; + + } + //=================================================== + + ModelContainerView::~ModelContainerView(void) + { + Array keys = iTriVarTable.getKeys(); + Array::ConstIterator i = keys.begin(); + while(i != keys.end()) { + VAR* var = iTriVarTable.get(*i); + delete var; + ++i; + } + } + + //=================================================== + + void ModelContainerView::cleanup() { + } + + //=================================================== + Vector3 getViewPos(const ModelContainer* mc, unsigned int pModelNr = 0) { + if(mc->getNSubModel() < pModelNr) { + pModelNr = mc->getNSubModel(); + } + const SubModel sm = mc->getSubModel(pModelNr); + return (sm.getAABoxBounds().low()); + } + + void ModelContainerView::init() { + } + + //========================================== + + void fillSubModelArary(const ModelContainer* pModelContainer, const TreeNode *root, Array& array, Vector3& pLo, Vector3& pHi) { + Vector3 lo = Vector3(inf(), inf(), inf()); + Vector3 hi = Vector3(-inf(), -inf(), -inf()); + + for(int i=0; i< root->getNValues(); i++) { + SubModel sm = pModelContainer->getSubModel(root->getStartPosition() + i); + lo = lo.min(sm.getAABoxBounds().low()); + hi = hi.max(sm.getAABoxBounds().high()); + array.append(sm); + } + + if(root->getChild((TreeNode *) &pModelContainer->getTreeNode(0), 0)) { + fillSubModelArary(pModelContainer, root->getChild((TreeNode *)&pModelContainer->getTreeNode(0), 0), array, lo, hi); + } + if(root->getChild((TreeNode *)&pModelContainer->getTreeNode(0), 1)) { + fillSubModelArary(pModelContainer, root->getChild((TreeNode *)&pModelContainer->getTreeNode(0), 1), array, lo, hi); + } + + float dist1 = (hi -lo).magnitude(); + AABox b; + root->getBounds(b); + float dist2 = (b.high() -b.low()).magnitude(); + if(dist1 > dist2) { + // error + int xxx = 0; + } + + } + + //========================================== + void ModelContainerView::addModelContainer(const std::string& pName,const ModelContainer* pModelContainer) { + // VARArea::UsageHint::WRITE_EVERY_FEW_FRAMES + + int offset=0; + + Array iIndexArray; + Array iGlobArray; + + Array SMArray; + Vector3 lo, hi; + fillSubModelArary(pModelContainer, &pModelContainer->getTreeNode(0), SMArray,lo,hi); + + + for(int i=0; i vArray; + Array iArray; + fillVertexAndIndexArrays(sm, vArray, iArray); + + for(int j=0;jgBoxArray; + ArraygTriArray; + int gCount1 = 0, gCount2 = 0 , gCount3 = 0, gCount4 = 0; + bool myfound=false; + + //=================================================== + + void ModelContainerView::onInit() { + // Called before the application loop beings. Load data here and + // not in the constructor so that common exceptions will be + // automatically caught. + iSky = Sky::fromFile("../../data/sky/"); + + iSkyParameters = SkyParameters(G3D::toSeconds(11, 00, 00, AM)); + iLighting = Lighting::fromSky(iSky, iSkyParameters, Color3::white()); + + // This simple demo has no shadowing, so make all lights unshadowed + iLighting->lightArray.append(iLighting->shadowedLightArray); + iLighting->shadowedLightArray.clear(); + + // Example debug GUI: + //debugPane->addCheckBox("Use explicit checking", &explicitCheck); + debugWindow->setVisible(true); + + toneMap->setEnabled(false); + } + + void ModelContainerView::onGraphics(RenderDevice* rd, Array &posed3D, Array &posed2D) { + Array opaque, transparent; + LightingRef localLighting = toneMap->prepareLighting(iLighting); + SkyParameters localSky = toneMap->prepareSkyParameters(iSkyParameters); + + + toneMap->beginFrame(rd); + rd->setProjectionAndCameraMatrix(defaultCamera); + + rd->setColorClearValue(Color3::black()); + rd->clear(); + //iSky->render(rd, localSky); + + // Setup lighting + rd->enableLighting(); + //rd->setLight(0, localLighting->lightArray[0]); + //rd->setAmbientLightColor(localLighting->ambientAverage()); + + GLight light =GLight::directional(defaultController.pointer()->position() + defaultController.pointer()->lookVector()*2,Color3::white()); + rd->setLight(0,light); + + rd->setColor(Color3::blue()); + + Array keys = iTriVarTable.getKeys(); + Array::ConstIterator i = keys.begin(); + while(i != keys.end()) { + VAR* var = iTriVarTable.get(*i); + Array indexArray = iTriIndexTable.get(*i); + + rd->beginIndexedPrimitives(); + rd->setVertexArray(*var); + rd->sendIndices(RenderDevice::LINES, indexArray); + rd->endIndexedPrimitives(); + ++i; + } + for(int i=0; i 0) + { + rd->setColor(Color3::red()); + rd->beginIndexedPrimitives(); + rd->setVertexArray(iTriDebugVar); + rd->sendIndices(RenderDevice::LINES, iTriDebugArray); + rd->endIndexedPrimitives(); + } + } + //-------- + if(iDrawLine) { + Draw::lineSegment(LineSegment::fromTwoPoints(iPos1, iPos2), rd, iColor, 3); + + if(myfound) { + //Draw::lineSegment(LineSegment::fromTwoPoints(p1, p2), rd, iColor, 3); + //Draw::lineSegment(LineSegment::fromTwoPoints(p2, p3), rd, iColor, 3); + //Draw::lineSegment(LineSegment::fromTwoPoints(p3, p1), rd, iColor, 3); + Draw::sphere(Sphere(p4,0.5),rd, iColor); + //Draw::sphere(Sphere(p5,0.5),rd, Color3::green()); + } + } + + + // Always render the posed models passed in or the Developer Window and + // other Widget features will not appear. + if (posed3D.size() > 0) { + Vector3 lookVector = renderDevice->getCameraToWorldMatrix().lookVector(); + PosedModel::sort(posed3D, lookVector, opaque, transparent); + + for (int i = 0; i < opaque.size(); ++i) { + opaque[i]->render(renderDevice); + } + + for (int i = 0; i < transparent.size(); ++i) { + transparent[i]->render(renderDevice); + } + } + + rd->disableLighting(); + + toneMap->endFrame(rd); + PosedModel2D::sortAndRender(rd, posed2D); + } + + //=================================================== + + void ModelContainerView::fillRenderArray(const SubModel& pSm, Array &pArray, const TreeNode* pTreeNode) { + for(int i=0;igetNValues(); i++) { + pArray.append(pSm.getTriangles()[i+pTreeNode->getStartPosition()]); + } + + if(pTreeNode->getChild(pSm.getTreeNodes(), 0) != 0) { + fillRenderArray(pSm, pArray, pTreeNode->getChild(pSm.getTreeNodes(), 0)); + } + + if(pTreeNode->getChild(pSm.getTreeNodes(), 1) != 0) { + fillRenderArray(pSm, pArray, pTreeNode->getChild(pSm.getTreeNodes(), 1)); + } + } + + //=================================================== + + void ModelContainerView::fillVertexAndIndexArrays(const SubModel& pSm, Array& vArray, Array& iArray) { + Array tbarray; + + fillRenderArray(pSm, tbarray, &pSm.getTreeNode(0)); + MeshBuilder builder; + int len = tbarray.size(); + int count = 0; + for(int i=0;igetInstanceMapTree(pMapId); + std::string dirFileName = iVMapManager->getDirFileName(pMapId); + if(!mt->hasDirFile(dirFileName)) { + dirFileName = iVMapManager->getDirFileName(pMapId, x, y); + } + showMap(mt,dirFileName); + iInstanceId = pMapId; + } + + //==================================================================== + + bool ModelContainerView::loadAndShowTile(int pMapId, int x, int y) { + char buffer[500]; + sprintf(buffer, "%s/vmaps",gDataDir); + bool result = false; + //if(pMapId == 1) return true; //+++ + int val = iVMapManager->loadMap(buffer,(unsigned int) pMapId, x,y); + if(val == VMAP_LOAD_RESULT_OK) { + result = true; + showMap(pMapId,x,y); + } else { + printf("Unable to load %s\n", buffer); + } + return(result); + } + + //======================================================================= + + void ModelContainerView::showMap(MapTree* mt, std::string dirFileName) { + if(mt->hasDirFile(dirFileName)) { + FilesInDir filesInDir = mt->getDirFiles(dirFileName); + if(filesInDir.getRefCount() == 1) { + Array fileNames = filesInDir.getFiles(); + for(int i=0; igetModelContainer(name); + //if(mc->getNSubModel() == 791) { + addModelContainer(name, mc); + //} + } + } + } + } + + //======================================================================= + + bool ModelContainerView::loadAndShowTile(int pMapId) { + char buffer[500]; + sprintf(buffer, "%s/vmaps",gDataDir); + bool result = false; + int val = iVMapManager->loadMap(buffer, (unsigned int) pMapId,-1,-1); + if(val == VMAP_LOAD_RESULT_OK) { + result = true; + MapTree* mt = iVMapManager->getInstanceMapTree(pMapId); + std::string dirFileName = iVMapManager->getDirFileName(pMapId); + iTriVarTable = Table(); + iTriIndexTable = Table >(); // reset table + iInstanceId = pMapId; + showMap(mt,dirFileName); + } + return(result); + } + + //==================================================================== + + void ModelContainerView::processCommand() { + iDrawLine = false; + if(iCurrCmdIndex < iCmdArray.size()) { + bool cmdfound = false; + while(!cmdfound && (iCurrCmdIndex < iCmdArray.size())) { + Command c = iCmdArray[iCurrCmdIndex]; + if(c.getType() == LOAD_TILE) { + iPrevLoadCommands.push_back(c); + if(iPosSent) { + if(loadAndShowTile(c.getInt(2), c.getInt(0), c.getInt(1))) { + printf("load tile mapId=%d, %d, %d\n", c.getInt(2), c.getInt(0), c.getInt(1)); + } else { + printf("ERROR: unable to load tile mapId= %d, %d, %d\n", c.getInt(2), c.getInt(0), c.getInt(1)); + } + cmdfound = true; + } else { + printf("ignore load tile mapId=%d, %d, %d\n", c.getInt(2), c.getInt(0), c.getInt(1)); + } + } else if(c.getType() == LOAD_INSTANCE) { + if(loadAndShowTile(c.getInt(0))) { + printf("load instance %d\n", c.getInt(0)); + } + cmdfound = true; + } else if(c.getType() == UNLOAD_TILE) { + /* + iVMapManager->unloadMap(c.getInt(2), c.getInt(0), c.getInt(1)); + printf("unload tile %d, %d\n", c.getInt(0), c.getInt(1)); + + std::string dirFileName = iVMapManager->getDirFileName(iVMapManager->getMapIdNames(c.getInt(2)).iMapGroupName.c_str(), c.getInt(0), c.getInt(1)); + MapTree* mt = iVMapManager->getInstanceMapTree(c.getInt(2)); + if(mt->hasDirFile(dirFileName)) { + Array fileNames = mt->getDirFiles(dirFileName).getFiles(); + for(int i=0; igetModelContainer(name); + removeModelContainer(name, mc); + } + } + */ + } else if(c.getType() == SET_POS) { + if(!iPosSent) { + int count = 3; + while(iPrevLoadCommands.size() > 0 && count>0) { + Command lc = iPrevLoadCommands.last(); + iPrevLoadCommands.pop_back(); + // first time, load the last map needed + if(loadAndShowTile(lc.getInt(2), lc.getInt(0), lc.getInt(1))) { + printf("load tile mapid=%d, %d, %d\n", lc.getInt(2), lc.getInt(0), lc.getInt(1)); + } else { + printf("ERROR: unable to load tile mapid=%d, %d, %d\n", lc.getInt(2), lc.getInt(0), lc.getInt(1)); + } + --count; + } + } + iPosSent = true; + defaultCamera.setPosition(Vector3(c.getVector(0).x,c.getVector(0).y+3, c.getVector(0).z)); + defaultController.pointer()->setPosition(Vector3(c.getVector(0).x,c.getVector(0).y+3, c.getVector(0).z)); + printf("set pos to %f, %f, %f\n",c.getVector(0).x, c.getVector(0).y, c.getVector(0).z ); + cmdfound = true; + } else if(c.getType() == TEST_VIS) { + printf("TEST line of sight\n"); + iDrawLine = true; + iPos1 = iVMapManager->convertPositionToInternalRep(c.getVector(0).x, c.getVector(0).y, c.getVector(0).z); + iPos2 = iVMapManager->convertPositionToInternalRep(c.getVector(1).x, c.getVector(1).y, c.getVector(1).z); + if(c.getInt(0) != 0) { + iColor = Color3::green(); + } else { + iColor = Color3::red(); + } + cmdfound = true; +/* + { + // draw debug-lines + int count = 0; + for(int i=0; ikeyPressed(GKey::fromString("l"))) { //load + iCmdArray = Array(); + iCommandFileRW.getNewCommands(iCmdArray); + iCurrCmdIndex = 0; + processCommand(); + } + + if(ui->keyPressed(GKey::fromString("r"))) { //restart + iCurrCmdIndex = 0; + } + + if(ui->keyPressed(GKey::fromString("1"))) { //inc count1 + gCount1++; + } + + if(ui->keyPressed(GKey::fromString("h"))) { //inc count1 +#if 0 + i_App->defaultController.getPosition(); + Vector3 pos = i_App->defaultController.getPosition(); + Vector3 pos2 = convertPositionToMangosRep(pos.x, pos.y, pos.z); + //Vector3 pos3 = iVMapManager->convertPositionToInternalRep(pos2.x, pos2.y, pos2.z); + //pos3 = iVMapManager->convertPositionToInternalRep(pos2.x, pos2.y, pos2.z); + + float hight = iVMapManager->getHeight(iInstanceId, pos2.x, pos2.y, pos2.z); + printf("Hight = %f\n",hight); +#endif + } + + + if(ui->keyPressed(GKey::fromString("2"))) { //dec count1 + gCount1--; + if(gCount1 < 0) + gCount1 = 0; + } + + if(ui->keyPressed(GKey::fromString("z"))) { //zero pos + i_App->defaultCamera.setPosition(Vector3(0,0,0)); + printf("set pos to 0, 0, 0\n"); + } + + + if(ui->keyPressed(GKey::fromString("c"))) { //restart + if(iCurrCmdIndex > 0) { + if(iCmdArray[iCurrCmdIndex-1].getType() == TEST_VIS) { + Vector3 p1 = iCmdArray[iCurrCmdIndex-1].getVector(0); + Vector3 p2 = iCmdArray[iCurrCmdIndex-1].getVector(1); + bool result; + int mapId = iCmdArray[iCurrCmdIndex-1].getInt(1); + gCount3 = gCount2 = 0;// debug counter + gBoxArray = Array(); + result = iVMapManager->isInLineOfSight(mapId, p1.x,p1.y,p1.z,p2.x,p2.y,p2.z); + printf("recalc last line of light: result = %d\n", result); + } + } + } + + + if(ui->keyPressed(GKey::LEFT_MOUSE)) { + if( iCurrCmdIndex>0) { + --iCurrCmdIndex; + printf("restart last command\n"); + processCommand(); + } + } + + if(ui->keyPressed(GKey::MIDDLE_MOUSE)) { + processCommand(); + } + + } + //========================================== + + void ModelContainerView::setViewPosition(const Vector3& pPosition) { + //i_App->defaultController.setPosition(pPosition); + i_App->defaultCamera.setPosition(pPosition); + } + + //========================================== + //========================================== +} +G3D_START_AT_MAIN(); +int main(int argc, char** argv) { + if(argc == 3) { + VMAP::gDataDir = argv[1]; + VMAP::gLogFile = argv[2]; + + G3D::GApp::Settings settings; + settings.window.width = 1024; + settings.window.height = 768; + //settings.useDeveloperTools = true; + + VMAP::ModelContainerView modelContainerView(settings); + modelContainerView.run(); + } else { + printf("%s \n",argv[0]); + } +} diff --git a/contrib/vmap_debugger/ModelContainerView.h b/contrib/vmap_debugger/ModelContainerView.h new file mode 100644 index 00000000000..28d992a0c16 --- /dev/null +++ b/contrib/vmap_debugger/ModelContainerView.h @@ -0,0 +1,89 @@ +#ifndef _MODELCONTAINERVIEW_H +#define _MODELCONTAINERVIEW_H + +#include +#include +#include "ModelContainer.h" +#include "DebugCmdLogger.h" +#include "vmapmanager.h" + + + + +namespace VMAP +{ + //========================================== + + + //========================================== + + class ModelContainerView : + public G3D::GApp + { + private: + SkyRef iSky; + LightingRef iLighting; + SkyParameters iSkyParameters; + + VARAreaRef iVARAreaRef; + Table iTriVarTable; + Table > iTriIndexTable; + + VARAreaRef iVARAreaRef2; + VAR iTriDebugVar; + Array iVTriDebugArray; + Array iTriDebugArray; + + //Array iLineIndexArray; + + GApp* i_App; + CommandFileRW iCommandFileRW; + Array iCmdArray; + int iCurrCmdIndex; + + VMapManager* iVMapManager; + + Vector3 iPos1; + Vector3 iPos2; + Color3 iColor; + bool iDrawLine; + int iInstanceId; + bool iPosSent; + Array iPrevLoadCommands; + private: + Vector3 convertPositionToMangosRep(float x, float y, float z) const; + + public: + ModelContainerView(const G3D::GApp::Settings& settings); + + ~ModelContainerView(void); + + void addModelContainer(const std::string& pName,const ModelContainer* pModelContainer); + void removeModelContainer(const std::string& pName, const ModelContainer* pModelContainer); + void setViewPosition(const Vector3& pPosition); + + void onGraphics(RenderDevice* rd, Array &posed3D, Array &posed2D); + virtual void onInit(); + void init(); + void cleanup(); + void onUserInput(UserInput* ui); + + void fillRenderArray(const SubModel& pSm,Array &pArray, const TreeNode* pTreeNode); + void fillVertexAndIndexArrays(const SubModel& pSm, Array& vArray, Array& iArray); + + bool loadAndShowTile(int pMapId, int x, int y); + void showMap(int pMapId, int x, int y); + + void showMap(MapTree* mt, std::string dirFileName); + bool loadAndShowTile(int pMapId); + + + void processCommand(); + + }; + + //========================================== + //========================================== +} + +#endif diff --git a/contrib/vmap_debugger/VC8/Release/vmapdebugger.exe b/contrib/vmap_debugger/VC8/Release/vmapdebugger.exe new file mode 100644 index 00000000000..c61082e496e Binary files /dev/null and b/contrib/vmap_debugger/VC8/Release/vmapdebugger.exe differ diff --git a/contrib/vmap_debugger/VC8/vmapdebugger.vcproj b/contrib/vmap_debugger/VC8/vmapdebugger.vcproj new file mode 100644 index 00000000000..100ee1eca5e --- /dev/null +++ b/contrib/vmap_debugger/VC8/vmapdebugger.vcproj @@ -0,0 +1,308 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/contrib/vmap_debugger/bin/vmapdebugger.exe b/contrib/vmap_debugger/bin/vmapdebugger.exe new file mode 100644 index 00000000000..c61082e496e Binary files /dev/null and b/contrib/vmap_debugger/bin/vmapdebugger.exe differ diff --git a/contrib/vmap_debugger/readme.txt b/contrib/vmap_debugger/readme.txt new file mode 100644 index 00000000000..b97715ab080 --- /dev/null +++ b/contrib/vmap_debugger/readme.txt @@ -0,0 +1,121 @@ +Here you find a visual debugging tool. With that you can check it yourself. You need to compile it +yourself or just use the precompiled version. The precompiled version should not need any +additional libraries. If you try to compile it yourself you need G3D library 7.00 and +SDL 1.2.8 or higher. + +There is NO “how to compile support”.... You will manage it, if you need to... + +What does it do? + +The program analyses the content of the vmapcmd.log file created by [b] mangosd compiled +in debug mode [/b] with vmap support. The commands written to disk are read and the result +is displayed in a graphical view. This view shows a wire frame model of the loaded vmaps +and you can move in these maps. Furthermore you can see witch line of sight query where +performed and its result. You are able to perform the ling of sight query again and will see, if +the current version of the vmap source compiled against the debugger, produces the same +result. This last function is useful for debugging the line of sight code. + +The little program is a real hack, but is fits is purpose. + +How to use it: + +[b]Logging[b] +You will need to set _VMAP_LOG_DEBUG when compiling core in debug mode to get this log. +If mangos is compiled in debug mode it will then write the vmapcmd.log file. The file does only +contain the information which vmaps are loaded. I addition to that the file need the +information where your character currently in standing in the maps. This position information +has to be inserted manually. To do that I modified the .announce command to send the +position of the current character to the log file (modification is in the attached patch). + +The line of sight query is only stored in the log file if you enable this kind of logging. This is +done by performing the modified .gm off command. Enabling line of sight and moving your +character a bit will log the queries and there results. Don’t do this for log, it will produce lots +of data, which is hard to analyze later. + +The modified command .gm on will stop the logging of the line of sight calculation. + +What do you have to do for logging? +1. Apply the patch to mangos to modify your .announce, .gmoff and .gmon commands +2. Compile mangos in debug mode +3. Go to the position where you suspect a problem +4. Use .gmon to be sure you will not be attacked when you login +5. Save, Logoff and stop mangosd +6. Delete the vmapcmd.log from the mangos dir. The logger will append to that file. +7. Start mangos +8. Login with your character +9. Send your position to the log file. Do this with the .announce command (.announce +foo) +10. Type .gmoff enabling the line of sight logging +11. Move a bit to get the attention of the mobs +12. Type .gmon to stop the logging + +[b]Analysing the log file[/b] +1. Start the vmap debugger with the path to the mangos data dir and the full path (name) of +the log file +2. The debugger is controlled by single keys and the mouse. Here is a list of key commands. +The result is displayed at the console: + +l – (small L) Load the next block off logging data into the command queue and process the +first command from the queue. When the end is reached a message “end reached” is display at +the console. If you reached the you can press l again. Sending .gm on sets an end mark to the +file. You have to load the next logging block after each .gmon command. + +r – Reload the last command block + +mouse middle click – process the next command from the queue + +mouse left click – reprocess the last command from the queue + +c – recalculate the last line of sight command and send the result to the console + +w,s,a,d – move within the 3D view + +ESC – exit + +TAB – release/grep the mouse + +[b]How to test the included example with the precompiled version with the included +vmapcmd.log file:[b] + +open your console +move to the contrib\vmap_debugger\bin directory +run: vmapdebugger.exe vmapcmd.log +Wait until the block screen is open and arrange the console and the screen, so you can see +both +Press: l (small L not one) +click middle +click middle +click middle + +Now you should see the wire frame model of scholo and the green line of sight line in the +display. The green line means the test was performed and you are seen. A red line means you +are not seen. Move around a bit with the mouse and the w,s,a,d keys. + +Press c +Press ESC + +[b]Problems with your gfx.card[/b] +Maybe the program does not woth with your graphics card. In this case you have dad luck. +One think might help, if not .... I do not know...: + +Here I take 60 MB Ram from Gfx-Card [b]VARArea::create(1024*1024*60)[/b]. That +might cause problems on your system. + +[code] + ModelContainerView::ModelContainerView(GApp* pApp) : GApplet(pApp) { + i_App = pApp; + + iCommandFileRW.setFileName(gLogFile); + iCurrCmdIndex = 0; + iVMapManager = new VMapManager(); + iDrawLine = false; + + iVARAreaRef = VARArea::create(1024*1024*60); + iInstanceId = -1; + + } +[/code] + +This should give all of you who, are interested the chance to check the content and behavior +of the vmaps. + diff --git a/contrib/vmap_debugger/vmapdebugger_VC8.sln b/contrib/vmap_debugger/vmapdebugger_VC8.sln new file mode 100644 index 00000000000..7a6d347deb1 --- /dev/null +++ b/contrib/vmap_debugger/vmapdebugger_VC8.sln @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vmapdebugger", "VC8\vmapdebugger.vcproj", "{0F6BDF3C-9B6F-45A0-A443-E26E31C8A015}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0F6BDF3C-9B6F-45A0-A443-E26E31C8A015}.Debug|Win32.ActiveCfg = Debug|Win32 + {0F6BDF3C-9B6F-45A0-A443-E26E31C8A015}.Debug|Win32.Build.0 = Debug|Win32 + {0F6BDF3C-9B6F-45A0-A443-E26E31C8A015}.Release|Win32.ActiveCfg = Release|Win32 + {0F6BDF3C-9B6F-45A0-A443-E26E31C8A015}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/contrib/vmap_extract_assembler_bin/make vmaps.bat b/contrib/vmap_extract_assembler_bin/make vmaps.bat new file mode 100644 index 00000000000..bd7e5ca5b25 --- /dev/null +++ b/contrib/vmap_extract_assembler_bin/make vmaps.bat @@ -0,0 +1,46 @@ +@echo off +cls +echo. +echo Welcome to the vmaps extractor and assembler +echo. +echo You need 2GB of free space in disk, CTRL+C to stop process +echo Hit Enter to start . . . +pause>nul +cls +echo. +echo. +echo. +IF EXIST buildings\dir (ECHO The buildings folder already exist do you want to delete it? +echo If YES hit Enter to continue if no CLOSE the program now! . . . +pause>nul +DEL /S /Q buildings) +vmapextract_v2.exe +cls +echo. +echo. +echo. +IF NOT %ERRORLEVEL% LEQ 1 (echo The vmap extract tool finalized with errors. +echo Hit Enter to continue . . . +pause>nul) +cls +echo. +echo. +echo. +echo Vmaps extracted check log.txt for errors, now it's time to assemble the vmaps press any key to continue . . . +pause>nul +md vmaps +vmap_assembler.exe buildings vmaps splitConfig.txt +cls +echo. +echo. +echo. +IF NOT %ERRORLEVEL% LEQ 1 (echo The vmap assembler tool finalized with errors. +echo Hit Enter to continue . . . +pause>nul) +cls +echo. +echo. +echo. +echo Process done! copy vmaps folder to the MaNGOS main directory +echo Press any key to exit . . . +pause>nul \ No newline at end of file diff --git a/contrib/vmap_extract_assembler_bin/makevmaps_SIMPLE.bat b/contrib/vmap_extract_assembler_bin/makevmaps_SIMPLE.bat new file mode 100644 index 00000000000..bf01c24edc6 --- /dev/null +++ b/contrib/vmap_extract_assembler_bin/makevmaps_SIMPLE.bat @@ -0,0 +1,5 @@ +vmapextract_v2.exe +md vmaps +vmap_assembler.exe buildings vmaps splitConfig.txt + +pause \ No newline at end of file diff --git a/contrib/vmap_extract_assembler_bin/readme.txt b/contrib/vmap_extract_assembler_bin/readme.txt new file mode 100644 index 00000000000..85abfb237be --- /dev/null +++ b/contrib/vmap_extract_assembler_bin/readme.txt @@ -0,0 +1,4 @@ +execute make vmaps.bat to make vmaps step by sep +execute makevmaps_SIMPLE.bat to so it in one step no quesions final screen [recommended] + +put vmaps folder in mangos main folder to enable LOS [Line Of Sight] \ No newline at end of file diff --git a/contrib/vmap_extract_assembler_bin/splitConfig.txt b/contrib/vmap_extract_assembler_bin/splitConfig.txt new file mode 100644 index 00000000000..de8fd67bdc4 --- /dev/null +++ b/contrib/vmap_extract_assembler_bin/splitConfig.txt @@ -0,0 +1,17 @@ +# list of map names + +509 #AhnQiraj +469 #BlackwingLair +189 #MonasteryInstances +030 #PVPZone01 +037 #PVPZone02 +033 #Shadowfang +533 #Stratholme Raid +209 #TanarisInstance +309 #Zul'gurub +560 #HillsbradPast +534 #HyjalPast +532 #Karazahn +543 #HellfireRampart +568 #ZulAman +564 #BlackTemple diff --git a/contrib/vmap_extract_assembler_bin/vmap_assembler.exe b/contrib/vmap_extract_assembler_bin/vmap_assembler.exe new file mode 100644 index 00000000000..5cb08f770aa Binary files /dev/null and b/contrib/vmap_extract_assembler_bin/vmap_assembler.exe differ diff --git a/contrib/vmap_extract_assembler_bin/vmapextract_v2.exe b/contrib/vmap_extract_assembler_bin/vmapextract_v2.exe new file mode 100644 index 00000000000..c38b6e64f64 Binary files /dev/null and b/contrib/vmap_extract_assembler_bin/vmapextract_v2.exe differ diff --git a/contrib/vmap_extractor_v2/doc/The MoPaQ File Format.txt b/contrib/vmap_extractor_v2/doc/The MoPaQ File Format.txt new file mode 100644 index 00000000000..ce8d8f70166 --- /dev/null +++ b/contrib/vmap_extractor_v2/doc/The MoPaQ File Format.txt @@ -0,0 +1,318 @@ +THE MOPAQ ARCHIVE FORMAT +v0.9 (Thursday, June 30, 2005) +by Justin Olbrantz(Quantam) + +Distribution and reproduction of this specification are allowed without limitation, as long as it is not altered. Quoting +in other works is freely allowed, as long as the source and author of the quote is stated. + +TABLE OF CONTENTS +1. Introduction to the MoPaQ Format +2. The MoPaQ Format + 2.1 General Archive Layout + 2.2 Archive Header + 2.3 Block Table + 2.4 Hash Table + 2.5 File Data + 2.6 Listfile + 2.7 Extended Attributes + 2.8 Weak (Old) Digital Signature + 2.9 Strong (New) Digital Signature +3. Algorithm Source Code + 3.1 Encryption/Decryption + 3.2 Hashing + 3.3 Conversion of FILETIME and time_t + +1. INTRODUCTION TO THE MOPAQ FORMAT +The MoPaQ (or MPQ) format is an archive file format designed by Mike O'Brien (hence the name Mike O'brien PaCK) at Blizzard +Entertainment. The format has been used in all Blizzard games since (and including) Diablo. It is heavily optimized to be +a read-only game archive format, and excels at this role. + +The Blizzard MoPaQ-reading functions are contained in the Storm module, which my be either statically or dynamically linked. +The Blizzard MoPaQ-writing functions are contained in the MPQAPI module, which is always statically linked. + +2. THE MOPAQ FORMAT +All numbers in the MoPaQ format are in little endian. Data types are listed either as int (integer, the number of bits specified), +byte (8 bits), and char (bytes which contain ASCII characters). All sizes and offsets are in bytes, unless specified otherwise. +Structure members are listed in the following general form: +offset from the beginning of the structure: data type(array size) member name : member description + +2.1 GENERAL ARCHIVE LAYOUT +- Archive Header +- File Data +- File Data - Special Files +- Hash Table +- Block Table +- Strong Digital signature + +This is the usual archive format, and is not absolutely essential. Some archives have been observed placing the hash table +and file table after the archive header, and before the file data. + +2.2 ARCHIVE HEADER +00h: char(4) Magic : Indicates that the file is a MoPaQ archive. Must be ASCII "MPQ" 1Ah. +04h: int32 HeaderSize : Size of the archive header. Should be 32. +08h: int32 ArchiveSize : Size of the whole archive, including the header. Does not include the strong digital signature, if present. +This size is used, among other things, for determining the region to hash in computing the digital signature. +0Ch: int16 Unknown : Unknown +0Eh: int8 SectorSizeShift : Power of two exponent specifying the number of 512-byte disk sectors in each logical sector +in the archive. The size of each logical sector the archive is 512 * 2^SectorSizeShift. Bugs in the Storm library dictate +that this should always be 3 (4096 byte sectors). +10h: int32 HashTableOffset : Offset to the beginning of the hash table, relative to the beginning of the archive. +14h: int32 BlockTableOffset : Offset to the beginning of the block table, relative to the beginning of the archive. +18h: int32 HashTableEntries : Number of entries in the hash table. Must be a power of two, and must be less than 2^16. +1Ch: int32 BlockTableEntries : Number of entries in the block table. + +The archive header is the first structure in the archive, at archive offset 0, but the archive does not need to be at offset +0 of the containing file. The offset of the archive in the file is referred to here as ArchiveOffset. If the archive is not +at the beginning of the file, it must begin at a disk sector boundary (512 bytes). Early versions of Storm require that the +archive be at the end of the containing file (ArchiveOffset + ArchiveSize = file size), but this is not required in newer +versions (due to the strong digital signature not being considered a part of the archive). + +2.3 BLOCK TABLE +The block table contains entries for each region in the archive. Regions may be either files or empty space, which may be +overwritten by new files (typically this space is from deleted file data). The block table is encrypted, using the hash +of "(block table)" as the key. Each entry is structured as follows: + +00h: int32 BlockOffset : Offset of the beginning of the block, relative to the beginning of the archive. Meaningless if the block size is 0. +04h: int32 BlockSize : Size of the block in the archive. +08h: int32 FileSize : Size of the file data stored in the block. Only valid if the block is a file, otherwise meaningless, and should be 0. If the file is compressed, this is the size of the uncompressed file data. +0Ch: int32 Flags : Bit mask of the flags for the block. The following values are conclusively identified: + 80000000h: Block is a file, and follows the file data format; otherwise, block is free space, and may be overwritten. If the block is not a file, all other flags should be cleared. + 01000000h: File is stored as a single unit, rather than split into sectors. + 00020000h: The file's encryption key is adjusted by the block offset and file size (explained in detail in the File Data section). File must be encrypted. + 00010000h: File is encrypted. + 00000200h: File is compressed. Mutually exclusive to file imploded. + 00000100h: File is imploded. Mutually exclusive to file compressed. + +2.4 HASH TABLE +Instead of storing file names, for quick access MoPaQs use a fixed, power of two-size hash table of files in the archive. A file is uniquely identified by its file path, its language, and its platform. The home entry for a file in the hash table is computed as a hash of the file path. In the event of a collision (the home entry is occupied by another file), progressive overflow is used, and the file is placed in the next available hash table entry. Searches for a desired file in the hash table proceed from the home entry for the file until either the file is found, the entire hash table is searched, or an empty hash table entry (FileBlockIndex of FFFFFFFFh) is encountered. The hash table is encrypted using the hash of "(hash table)" as the key. Each entry is structured as follows: + +00h: int32 FilePathHashA : The hash of the file path, using method A. +04h: int32 FilePathHashB : The hash of the file path, using method B. +08h: int16 Language : The language of the file. This is a Windows LANGID data type, and uses the same values. 0 indicates the default language (American English), or that the file is language-neutral. +0Ah: int8 Platform : The platform the file is used for. 0 indicates the default platform. No other values have been observed. +0Ch: int32 FileBlockIndex : If the hash table entry is valid, this is the index into the block table of the file. Otherwise, one of the following two values: + FFFFFFFFh: Hash table entry is empty, and has always been empty. Terminates searches for a given file. + FFFFFFFEh: Hash table entry is empty, but was valid at some point (in other words, the file was deleted). Does not terminate searches for a given file. + +2.5 FILE DATA +00h: int32(SectorsInFile + 1) SectorOffsetTable : Offsets to the start of each sector's data, relative to the beginning of the file data. Not present if this information is calculatable (see details below). +immediately following SectorOffsetTable: SectorData : Data of each sector in the file, packed end to end (see details below). + +Normally, file data is split up into sectors, for simple streaming. All sectors, save for the last, will contain as many bytes of file data as specified in the archive header's SectorSizeShift; the last sector may be smaller than this, depending on the size of the file data. This sector size is the size of the raw file data; if the file is compressed, the compressed sector will be smaller or the same size as the uncompressed sector size. Individual sectors in a compressed file may be stored uncompressed; this occurs if and only if the sector could not be compressed by the algorithm used (if the compressed sector size was greater than or equal to the size of the raw data), and is indicated by the sector's compressed size in SectorOffsetTable being equal to the uncompressed size of the sector (which may be calculated from the FileSize). + +If the sector is compressed (but not imploded), a bit mask byte of the compression algorithm(s) used to compress the sector is appended to the beginning of the compressed sector data. This additional byte counts towards the total size of the sector; if the size of the sector (including this byte) exceeds or matches the uncompressed size of the sector data, the sector will be stored uncompressed, and this byte omitted. Multiple compression algorithms may be used on the same sector; in this case, successive compression occurs in the order the algorithms are listed below, and decompression occurs in the opposite order. For implimentations of all of these algorithms, see StormLib. + 40h: IMA ADPCM mono + 80h: IMA ADPCM stereo + 01h: Huffman encoded + 02h: Deflated (see ZLib) + 08h: Imploded (see PKWare Data Compression Library) + 10h: BZip2 compressed (see BZip2) + +If the file is stored as a single unit (indicated in the file's Flags), there is effectively only a single sector, which +contains the entire file. + +If the file is encrypted, each sector (after compression and appendage of the compression type byte, if applicable) +is encrypted with the file's key. The base key for a file is determined by a hash of the file name stripped of the +directory (i.e. the key for a file named "directory\file" would be computed as the hash of "file"). If this key is +adjusted, as indicated in the file's Flags, the final key is calculated as ((base key + BlockOffset - ArchiveOffset) +XOR FileSize) (StormLib - an open-source implementation of the MoPaQ reading and writing functions, +by Ladislav Zezula - incorrectly uses an AND in place of the XOR). Each sector is encrypted using the key + the +0-based index of the sector in the file. The SectorOffsetTable, if present, is encrypted using the key - 1. + +The SectorOffsetTable is omitted when the sizes and offsets of all sectors in the file are calculatable from the FileSize. +This can happen in several circumstances. If the file is not compressed/imploded, then the size and offset of all sectors +is known, based on the archive's SectorSizeShift. If the file is stored as a single unit compressed/imploded, then the +SectorOffsetTable is omitted, as the single file "sector" corresponds to BlockSize and FileSize, as mentioned previously. +Note that the SectorOffsetTable will always be present if the file is compressed/imploded and the file is not stored as +a single unit, even if there is only a single sector in the file (the size of the file is less than or equal to the +archive's sector size). + +2.6 LISTFILE +The listfile is a very simple extension to the MoPaQ format that contains the file paths of (most) files in the archive. +The languages and platforms of the files are not stored in the listfile. The listfile is contained in the file "(listfile)", +and is simply a non-Unix-style text file with one file path on each line, lines terminated with the bytes 0Dh 0Ah. The file +"(listfile)" may not be listed in the listfile. + +2.7 EXTENDED ATTRIBUTES +The extended attributes are optional file attributes for files in the block table. These attributes were added at times after +the MoPaQ format was already finalized, and it is not necessary for every archive to have all (or any) of the extended attributes. +If an archive contains a given attribute, there will be an instance of that attribute for every block in the block table, although +the attribute will be meaningless if the block is not a file. The order of the attributes for blocks correspond to the order of the +blocks in the block table, and are of the same number. The attributes are stored in parallel arrays in the "(attributes)" file, +in the archive. The attributes corresponding to this file need not be valid (and logically cannot be). Unlike all the other +structures in the MoPaQ format, entries in the extended attributes are NOT guaranteed to be aligned. Also note that in some +archives, malicious zeroing of the attributes has been observed, perhaps with the intent of breaking archive viewers. This +file is structured as follows: + +00h: int32 Version : Specifies the extended attributes format version. For now, must be 100. +04h: int32 AttributesPresent : Bit mask of the extended attributes present in the archive: + 00000001h: File CRC32s. + 00000002h: File timestamps. + 00000004h: File MD5s. +08h: int32(BlockTableEntries) CRC32s : CRC32s of the (uncompressed) file data for each block in the archive. Omitted if the +archive does not have CRC32s. immediately after CRC32s: FILETIME(BlockTableEntries) Timestamps : Timestamps for each block +in the archive. The format is that of the Windows FILETIME structure. Omitted if the archive does not have timestamps. +immediately after Timestamps: MD5(BlockTableEntries) MD5s : MD5s of the (uncompressed) file data for each block in the archive. +Omitted if the archive does not have MD5s. + +2.8 WEAK DIGITAL SIGNATURE +The weak digital signature is a digital signature using Microsoft CryptoAPI. It is an implimentation of the RSASSA-PKCS1-v1_5 +digital signature protocol, using the MD5 hashing algorithm and a 512-bit (weak) RSA key (for more information about this +protocol, see the RSA Labs PKCS1 specification). The public key and exponent are stored in a resource in Storm. The signature +is stored uncompressed, unencrypted in the file "(signature)" in the archive. The archive is hashed from the beginning of the +archive (ArchiveOffset in the containing file) to the end of the archive (the length indicated by ArchiveSize); the signature +file is added to the archive before signing, and the space occupied by the file is considered to be all binary 0s during +signing/verification. This file is structured as follows: + +00h: int32 Unknown : Must be 0. +04h: int32 Unknown : must be 0. +08h: int512 Signature : The digital signature. Like all other numbers in the MoPaQ format, this is stored in little-endian order. + +2.9 STRONG DIGITAL SIGNATURE +The strong digital signature uses a simple proprietary implementation of RSA signing, using the SHA-1 hashing algorithm and +a 2048-bit (strong) RSA key. The default public key and exponent are stored in Storm, but other keys may be used as well. +The strong digital signature is stored immediately after the archive, in the containing file; the entire archive (ArchiveSize +bytes, starting at ArchiveOffset in the containing file) is hashed as a single block. The signature has the following format: + +00h: char(4) Magic : Indicates the presence of a digital signature. Must be "NGIS" ("SIGN" backwards). +04h: int2048 Signature : The digital signature, stored in little-endian format. + +When the Signature field is decrypted with the public key and exponent, and the result stored in little-endian order, it is structured as follows: + +00h: byte Padding : Must be 0Bh. +01h: byte(235) Padding : Must be BBh. +ECh: byte(20) SHA-1 : SHA-1 hash of the archive, in standard SHA-1 format. + +3. ALGORITHM SOURCE CODE +3.1 ENCRYPTION/DECRYPTION +I believe this was derived at some point from code in StormLib. Assumes the long type to be 32 bits, and the machine to be little endian order. + +unsigned long dwCryptTable[0x500]; + +void InitializeCryptTable() +{ + unsigned long seed = 0x00100001; + unsigned long index1 = 0; + unsigned long index2 = 0; + int i; + + for (index1 = 0; index1 < 0x100; index1++) + { + for (index2 = index1, i = 0; i < 5; i++, index2 += 0x100) + { + unsigned long temp1, temp2; + + seed = (seed * 125 + 3) % 0x2AAAAB; + temp1 = (seed & 0xFFFF) << 0x10; + + seed = (seed * 125 + 3) % 0x2AAAAB; + temp2 = (seed & 0xFFFF); + + dwCryptTable[index2] = (temp1 | temp2); + } + } +} + +void EncryptData(void *lpbyBuffer, unsigned long dwLength, unsigned long dwKey) +{ + unsigned long *lpdwBuffer = (unsigned long *)lpbyBuffer; + unsigned long seed = 0xEEEEEEEE; + unsigned long ch; + + assert(lpbyBuffer); + + dwLength /= sizeof(unsigned long); + + while(dwLength-- > 0) + { + seed += dwCryptTable[0x400 + (dwKey & 0xFF)]; + ch = *lpdwBuffer ^ (dwKey + seed); + + dwKey = ((~dwKey << 0x15) + 0x11111111) | (dwKey >> 0x0B); + seed = *lpdwBuffer + seed + (seed << 5) + 3; + + *lpdwBuffer++ = ch; + } +} + +void DecryptData(void *lpbyBuffer, unsigned long dwLength, unsigned long dwKey) +{ + unsigned long *lpdwBuffer = (unsigned long *)lpbyBuffer; + unsigned long seed = 0xEEEEEEEE; + unsigned long ch; + + assert(lpbyBuffer); + + dwLength /= sizeof(unsigned long); + + while(dwLength-- > 0) + { + seed += dwCryptTable[0x400 + (dwKey & 0xFF)]; + ch = *lpdwBuffer ^ (dwKey + seed); + + dwKey = ((~dwKey << 0x15) + 0x11111111) | (dwKey >> 0x0B); + seed = ch + seed + (seed << 5) + 3; + + *lpdwBuffer++ = ch; + } +} + +3.2 HASHING +Based on code from StormLib. + +// Different types of hashes to make with HashString +#define MPQ_HASH_TABLE_OFFSET 0 +#define MPQ_HASH_NAME_A 1 +#define MPQ_HASH_NAME_B 2 +#define MPQ_HASH_FILE_KEY 3 + +unsigned long HashString(const char *lpszString, unsigned long dwHashType) +{ + unsigned long seed1 = 0x7FED7FED; + unsigned long seed2 = 0xEEEEEEEE; + int ch; + + while (*lpszString != 0) + { + ch = toupper(*lpszString++); + + seed1 = dwCryptTable[(dwHashType * 0xFF) + ch] ^ (seed1 + seed2); + seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3; + } + return seed1; +} + +3.3 CONVERSION OF FILETIME AND time_t + +#define EPOCH_OFFSET 116444736000000000ULL // Number of 100 ns units between 01/01/1601 and 01/01/1970 + +bool GetTimeFromFileTime(FILETIME &fileTime, time_t &time) +{ + // The FILETIME represents a 64-bit integer: the number of 100 ns units since January 1, 1601 + unsigned long long nTime = ((unsigned long long)fileTime.dwHighDateTime << 32) + fileTime.dwLowDateTime; + + if (nTime < EPOCH_OFFSET) + return false; + + nTime -= EPOCH_OFFSET; // Convert the time base from 01/01/1601 to 01/01/1970 + nTime /= 10000000ULL; // Convert 100 ns to sec + + time = (time_t)nTime; + + // Test for overflow (FILETIME is 64 bits, time_t is 32 bits) + if ((nTime - (unsigned long long)time) > 0) + return false; + + return true; +} + +void GetFileTimeFromTime(time_t &time, FILETIME &fileTime) +{ + unsigned long long nTime = (unsigned long long)time; + + nTime *= 10000000ULL; + nTime += EPOCH_OFFSET; + + fileTime.dwLowDateTime = (DWORD)nTime; + fileTime.dwHighDateTime = (DWORD)(nTime >> 32); +} diff --git a/contrib/vmap_extractor_v2/doc/The_MoPaQ_File_Format.txt b/contrib/vmap_extractor_v2/doc/The_MoPaQ_File_Format.txt new file mode 100644 index 00000000000..6a21eca5472 --- /dev/null +++ b/contrib/vmap_extractor_v2/doc/The_MoPaQ_File_Format.txt @@ -0,0 +1,421 @@ +THE MOPAQ ARCHIVE FORMAT +v1.0 (Friday, September 1, 2006) +by Justin Olbrantz(Quantam) + +Distribution and reproduction of this specification are allowed without limitation, as long as it is not altered. Quotation in other works is freely allowed, as long as the source and author of the quote are stated. + +TABLE OF CONTENTS +1. Introduction to the MoPaQ Format +2. The MoPaQ Format + 2.1 General Archive Layout + 2.2 Archive Header + 2.3 Block Table + 2.4 Extended Block Table + 2.5 Hash Table + 2.6 File Data + 2.7 Listfile + 2.8 Extended Attributes + 2.9 Weak (Old) Digital Signature + 2.10 Strong (New) Digital Signature +3. Algorithm Source Code + 3.1 Encryption/Decryption + 3.2 Hashing and File Key Computation + 3.3 Finding Files + 3.4 Deleting Files + 3.5 Conversion of FILETIME and time_t + 3.6 Forming a 64-bit Large Archive Offset from 32-bit and 16-bit Components +4. Revision History + +1. INTRODUCTION TO THE MOPAQ FORMAT +The MoPaQ (or MPQ) format is an archive file format designed by Mike O'Brien (hence the name Mike O'brien PaCK) at Blizzard Entertainment. The format has been used in all Blizzard games since (and including) Diablo. It is heavily optimized to be a read-only game archive format, and excels at this role. + +The Blizzard MoPaQ-reading functions are contained in the Storm module, which my be either statically or dynamically linked. The Blizzard MoPaQ-writing functions are contained in the MPQAPI module, which is always statically linked. + +StormLib - mentioned several times in this specification - is an open-source MoPaQ reading and writing library written by Ladislav Zezula (no affiliation with Blizzard Entertainment). While it's a bit dated, and does not support all of the newer MoPaQ features, it contains source code to the more exotic compression methods used by MoPaQ, such as the PKWare implode algorithm, MoPaQ's huffman compression algorithm, and the IMA ADPCM compression used by MoPaQ. + +2. THE MOPAQ FORMAT +All numbers in the MoPaQ format are in little endian byte order; signed numbers use the two's complement system. Data types are listed either as int (integer, the number of bits specified), byte (8 bits), or char (bytes which contain ASCII characters). All sizes and offsets are in bytes, unless specified otherwise. Structure members are listed in the following general form: +offset from the beginning of the structure: data type(array size) member name : member description + +2.1 GENERAL ARCHIVE LAYOUT +- Archive Header +- File Data +- File Data - Special Files +- Hash Table +- Block Table +- Extended Block Table +- Strong Digital signature + +This is the usual archive format, but it is not mandatory. Some archives have been observed placing the hash table and file table after the archive header, and before the file data. + +2.2 ARCHIVE HEADER +00h: char(4) Magic : Indicates that the file is a MoPaQ archive. Must be ASCII "MPQ" 1Ah. +04h: int32 HeaderSize : Size of the archive header. +08h: int32 ArchiveSize : Size of the whole archive, including the header. Does not include the strong digital signature, if present. This size is used, among other things, for determining the region to hash in computing the digital signature. This field is deprecated in the Burning Crusade MoPaQ format, and the size of the archive is calculated as the size from the beginning of the archive to the end of the hash table, block table, or extended block table (whichever is largest). +0Ch: int16 FormatVersion : MoPaQ format version. MPQAPI will not open archives where this is negative. Known versions: + 0000h: Original format. HeaderSize should be 20h, and large archives are not supported. + 0001h: Burning Crusade format. Header size should be 2Ch, and large archives are supported. +0Eh: int8 SectorSizeShift : Power of two exponent specifying the number of 512-byte disk sectors in each logical sector in the archive. The size of each logical sector in the archive is 512 * 2^SectorSizeShift. Bugs in the Storm library dictate that this should always be 3 (4096 byte sectors). +10h: int32 HashTableOffset : Offset to the beginning of the hash table, relative to the beginning of the archive. +14h: int32 BlockTableOffset : Offset to the beginning of the block table, relative to the beginning of the archive. +18h: int32 HashTableEntries : Number of entries in the hash table. Must be a power of two, and must be less than 2^16 for the original MoPaQ format, or less than 2^20 for the Burning Crusade format. +1Ch: int32 BlockTableEntries : Number of entries in the block table. +Fields only present in the Burning Crusade format and later: +20h: int64 ExtendedBlockTableOffset : Offset to the beginning of the extended block table, relative to the beginning of the archive. +28h: int16 HashTableOffsetHigh : High 16 bits of the hash table offset for large archives. +2Ah: int16 BlockTableOffsetHigh : High 16 bits of the block table offset for large archives. + +The archive header is the first structure in the archive, at archive offset 0; however, the archive does not need to be at offset 0 of the containing file. The offset of the archive in the file is referred to here as ArchiveOffset. If the archive is not at the beginning of the file, it must begin at a disk sector boundary (512 bytes). Early versions of Storm require that the archive be at the end of the containing file (ArchiveOffset + ArchiveSize = file size), but this is not required in newer versions (due to the strong digital signature not being considered a part of the archive). + +2.3 BLOCK TABLE +The block table contains entries for each region in the archive. Regions may be either files, empty space, which may be overwritten by new files (typically this space is from deleted file data), or unused block table entries. Empty space entries should have BlockOffset and BlockSize nonzero, and FileSize and Flags zero; unused block table entries should have BlockSize, FileSize, and Flags zero. The block table is encrypted, using the hash of "(block table)" as the key. Each entry is structured as follows: + +00h: int32 BlockOffset : Offset of the beginning of the block, relative to the beginning of the archive. +04h: int32 BlockSize : Size of the block in the archive. +08h: int32 FileSize : Size of the file data stored in the block. Only valid if the block is a file; otherwise meaningless, and should be 0. If the file is compressed, this is the size of the uncompressed file data. +0Ch: int32 Flags : Bit mask of the flags for the block. The following values are conclusively identified: + 80000000h: Block is a file, and follows the file data format; otherwise, block is free space or unused. If the block is not a file, all other flags should be cleared, and FileSize should be 0. + 01000000h: File is stored as a single unit, rather than split into sectors. + 00020000h: The file's encryption key is adjusted by the block offset and file size (explained in detail in the File Data section). File must be encrypted. + 00010000h: File is encrypted. + 00000200h: File is compressed. File cannot be imploded. + 00000100h: File is imploded. File cannot be compressed. + +2.4 EXTENDED BLOCK TABLE +The extended block table was added to support archives larger than 4 gigabytes (2^32 bytes). The table contains the upper bits of the archive offsets for each block in the block table. It is simply an array of int16s, which become bits 32-47 of the archive offsets for each block, with bits 48-63 being zero. Individual blocks in the archive are still limited to 4 gigabytes in size. This table is only present in Burning Crusade format archives that exceed 4 gigabytes size. + +As of the Burning Crusade Friends and Family beta, this table is not encrypted. + +2.5 HASH TABLE +Instead of storing file names, for quick access MoPaQs use a fixed, power of two-size hash table of files in the archive. A file is uniquely identified by its file path, its language, and its platform. The home entry for a file in the hash table is computed as a hash of the file path. In the event of a collision (the home entry is occupied by another file), progressive overflow is used, and the file is placed in the next available hash table entry. Searches for a desired file in the hash table proceed from the home entry for the file until either the file is found, the entire hash table is searched, or an empty hash table entry (FileBlockIndex of FFFFFFFFh) is encountered. The hash table is encrypted using the hash of "(hash table)" as the key. Each entry is structured as follows: + +00h: int32 FilePathHashA : The hash of the file path, using method A. +04h: int32 FilePathHashB : The hash of the file path, using method B. +08h: int16 Language : The language of the file. This is a Windows LANGID data type, and uses the same values. 0 indicates the default language (American English), or that the file is language-neutral. +0Ah: int8 Platform : The platform the file is used for. 0 indicates the default platform. No other values have been observed. +0Ch: int32 FileBlockIndex : If the hash table entry is valid, this is the index into the block table of the file. Otherwise, one of the following two values: + FFFFFFFFh: Hash table entry is empty, and has always been empty. Terminates searches for a given file. + FFFFFFFEh: Hash table entry is empty, but was valid at some point (in other words, the file was deleted). Does not terminate searches for a given file. + +2.6 FILE DATA +The data for each file is composed of the following structure: +00h: int32(SectorsInFile + 1) SectorOffsetTable : Offsets to the start of each sector, relative to the beginning of the file data. The last entry contains the file size, making it possible to easily calculate the size of any given sector. This table is not present if this information can be calculated (see details below). +immediately following SectorOffsetTable: SECTOR Sectors(SectorsInFile) : Data of each sector in the file, packed end to end (see details below). + +Normally, file data is split up into sectors, for simple streaming. All sectors, save for the last, will contain as many bytes of file data as specified in the archive header's SectorSizeShift; the last sector may contain less than this, depending on the size of the entire file's data. If the file is compressed or imploded, the sector will be smaller or the same size as the file data it contains. Individual sectors in a compressed or imploded file may be stored uncompressed; this occurs if and only if the file data the sector contains could not be compressed by the algorithm(s) used (if the compressed sector size was greater than or equal to the size of the file data), and is indicated by the sector's size in SectorOffsetTable being equal to the size of the file data in the sector (which may be calculated from the FileSize). + +The format of each sector depends on the kind of sector it is. Uncompressed sectors are simply the the raw file data contained in the sector. Imploded sectors are the raw compressed data following compression with the implode algorithm (these sectors can only be in imploded files). Compressed sectors (only found in compressed - not imploded - files) are compressed with one or more compression algorithms, and have the following structure: +00h: byte CompressionMask : Mask of the compression types applied to this sector. If multiple compression types are used, they are applied in the order listed below, and decompression is performed in the opposite order. This byte counts towards the total sector size, meaning that the sector will be stored uncompressed if the data cannot be compressed by at least two bytes; as well, this byte is encrypted with the sector data, if applicable. The following compression types are defined (for implementations of these algorithms, see StormLib): + 40h: IMA ADPCM mono + 80h: IMA ADPCM stereo + 01h: Huffman encoded + 02h: Deflated (see ZLib) + 08h: Imploded (see PKWare Data Compression Library) + 10h: BZip2 compressed (see BZip2) +01h: byte(SectorSize - 1) SectorData : The compressed data for the sector. + +If the file is stored as a single unit (indicated in the file's Flags), there is effectively only a single sector, which contains the entire file data. + +If the file is encrypted, each sector (after compression/implosion, if applicable) is encrypted with the file's key. The base key for a file is determined by a hash of the file name stripped of the directory (i.e. the key for a file named "directory\file" would be computed as the hash of "file"). If this key is adjusted, as indicated in the file's Flags, the final key is calculated as ((base key + BlockOffset - ArchiveOffset) XOR FileSize) (StormLib incorrectly uses an AND in place of the XOR). Each sector is encrypted using the key + the 0-based index of the sector in the file. The SectorOffsetTable, if present, is encrypted using the key - 1. + +The SectorOffsetTable is omitted when the sizes and offsets of all sectors in the file are calculatable from the FileSize. This can happen in several circumstances. If the file is not compressed/imploded, then the size and offset of all sectors is known, based on the archive's SectorSizeShift. If the file is stored as a single unit compressed/imploded, then the SectorOffsetTable is omitted, as the single file "sector" corresponds to BlockSize and FileSize, as mentioned previously. However, the SectorOffsetTable will be present if the file is compressed/imploded and the file is not stored as a single unit, even if there is only a single sector in the file (the size of the file is less than or equal to the archive's sector size). + +2.7 LISTFILE +The listfile is a very simple extension to the MoPaQ format that contains the file paths of (most) files in the archive. The languages and platforms of the files are not stored in the listfile. The listfile is contained in the file "(listfile)" (default language and platform), and is simply a text file with file paths separated by ';', 0Dh, 0Ah, or some combination of these. The file "(listfile)" may not be listed in the listfile. + +2.8 EXTENDED ATTRIBUTES +The extended attributes are optional file attributes for files in the block table. These attributes were added at times after the MoPaQ format was already finalized, and it is not necessary for every archive to have all (or any) of the extended attributes. If an archive contains a given attribute, there will be an instance of that attribute for every block in the block table, although the attribute will be meaningless if the block is not a file. The order of the attributes for blocks correspond to the order of the blocks in the block table, and are of the same number. The attributes are stored in parallel arrays in the "(attributes)" file (default language and platform), in the archive. The attributes corresponding to this file need not be valid (and logically cannot be). Unlike all the other structures in the MoPaQ format, entries in the extended attributes are NOT guaranteed to be aligned. Also note that in some archives, malicious zeroing of the attributes has been observed, perhaps with the intent of breaking archive viewers. This file is structured as follows: + +00h: int32 Version : Specifies the extended attributes format version. For now, must be 100. +04h: int32 AttributesPresent : Bit mask of the extended attributes present in the archive: + 00000001h: File CRC32s. + 00000002h: File timestamps. + 00000004h: File MD5s. +08h: int32(BlockTableEntries) CRC32s : CRC32s of the (uncompressed) file data for each block in the archive. Omitted if the archive does not have CRC32s. +immediately after CRC32s: FILETIME(BlockTableEntries) Timestamps : Timestamps for each block in the archive. The format is that of the Windows FILETIME structure. Omitted if the archive does not have timestamps. +immediately after Timestamps: MD5(BlockTableEntries) MD5s : MD5s of the (uncompressed) file data for each block in the archive. Omitted if the archive does not have MD5s. + +2.9 WEAK DIGITAL SIGNATURE +The weak digital signature is a digital signature using Microsoft CryptoAPI. It is an implimentation of the RSASSA-PKCS1-v1_5 digital signature protocol, using the MD5 hashing algorithm and a 512-bit (weak) RSA key (for more information about this protocol, see the RSA Labs PKCS1 specification). The public key and exponent are stored in a resource in Storm, the private key is stored in a separate file, whose filename is passed to MPQAPI (the private key is not stored in MPQAPI). The signature is stored uncompressed, unencrypted in the file "(signature)" (default language and platform) in the archive. The archive is hashed from the beginning of the archive (ArchiveOffset in the containing file) to the end of the archive (the length indicated by ArchiveSize, or calculated in the Burning Crusade MoPaQ format); the signature file is added to the archive before signing, and the space occupied by the file is considered to be all binary 0s during signing/verification. This file is structured as follows: + +00h: int32 Unknown : Must be 0. +04h: int32 Unknown : Must be 0. +08h: int512 Signature : The digital signature. Like all other numbers in the MoPaQ format, this is stored in little-endian order. The structure of this, when decrypted, follows the RSASSA-PKCS1-v1_5 specification; this format is rather icky to work with (I wrote a program to verify this signature using nothing but an MD5 function and huge integer functions; it wasn't pleasant), and best left to an encryption library such as Cryto++. + +2.10 STRONG DIGITAL SIGNATURE +The strong digital signature uses a simple proprietary implementation of RSA signing, using the SHA-1 hashing algorithm and a 2048-bit (strong) RSA key. The default public key and exponent are stored in Storm, but other keys may be used as well. The strong digital signature is stored immediately after the archive, in the containing file; the entire archive (ArchiveSize bytes, starting at ArchiveOffset in the containing file) is hashed as a single block. The signature has the following format: + +00h: char(4) Magic : Indicates the presence of a digital signature. Must be "NGIS" ("SIGN" backwards). +04h: int2048 Signature : The digital signature, stored in little-endian format. + +When the Signature field is decrypted with the public key and exponent, and the resulting large integer is stored in little-endian order, it is structured as follows: + +00h: byte Padding : Must be 0Bh. +01h: byte(235) Padding : Must be BBh. +ECh: byte(20) SHA-1 : SHA-1 hash of the archive, in standard SHA-1 byte order. + +3. ALGORITHM SOURCE CODE +All of the sample code here assumes little endian machine byte order, that the short type is 16 bits, that the long type is 32 bits, and that the long long type is 64 bits. Adjustments must be made if these assumptions are not correct on a given platform. All code not credited otherwise was written by myself in the writing of this specification. + +3.1 ENCRYPTION/DECRYPTION +Based on code from StormLib. + +unsigned long dwCryptTable[0x500]; + +// The encryption and hashing functions use a number table in their procedures. This table must be initialized before the functions are called the first time. +void InitializeCryptTable() +{ + unsigned long seed = 0x00100001; + unsigned long index1 = 0; + unsigned long index2 = 0; + int i; + + for (index1 = 0; index1 < 0x100; index1++) + { + for (index2 = index1, i = 0; i < 5; i++, index2 += 0x100) + { + unsigned long temp1, temp2; + + seed = (seed * 125 + 3) % 0x2AAAAB; + temp1 = (seed & 0xFFFF) << 0x10; + + seed = (seed * 125 + 3) % 0x2AAAAB; + temp2 = (seed & 0xFFFF); + + dwCryptTable[index2] = (temp1 | temp2); + } + } +} + +void EncryptData(void *lpbyBuffer, unsigned long dwLength, unsigned long dwKey) +{ + assert(lpbyBuffer); + + unsigned long *lpdwBuffer = (unsigned long *)lpbyBuffer; + unsigned long seed = 0xEEEEEEEE; + unsigned long ch; + + dwLength /= sizeof(unsigned long); + + while(dwLength-- > 0) + { + seed += dwCryptTable[0x400 + (dwKey & 0xFF)]; + ch = *lpdwBuffer ^ (dwKey + seed); + + dwKey = ((~dwKey << 0x15) + 0x11111111) | (dwKey >> 0x0B); + seed = *lpdwBuffer + seed + (seed << 5) + 3; + + *lpdwBuffer++ = ch; + } +} + +void DecryptData(void *lpbyBuffer, unsigned long dwLength, unsigned long dwKey) +{ + assert(lpbyBuffer); + + unsigned long *lpdwBuffer = (unsigned long *)lpbyBuffer; + unsigned long seed = 0xEEEEEEEEL; + unsigned long ch; + + dwLength /= sizeof(unsigned long); + + while(dwLength-- > 0) + { + seed += dwCryptTable[0x400 + (dwKey & 0xFF)]; + ch = *lpdwBuffer ^ (dwKey + seed); + + dwKey = ((~dwKey << 0x15) + 0x11111111L) | (dwKey >> 0x0B); + seed = ch + seed + (seed << 5) + 3; + + *lpdwBuffer++ = ch; + } +} + +3.2 HASHING AND FILE KEY COMPUTATION +These functions may have been derived from StormLib code at some point in the very distant past. It was so long ago that I don't remember for certain. + +// Different types of hashes to make with HashString +#define MPQ_HASH_TABLE_OFFSET 0 +#define MPQ_HASH_NAME_A 1 +#define MPQ_HASH_NAME_B 2 +#define MPQ_HASH_FILE_KEY 3 + +// Based on code from StormLib. +unsigned long HashString(const char *lpszString, unsigned long dwHashType) +{ + assert(lpszString); + assert(dwHashType <= MPQ_HASH_FILE_KEY); + + unsigned long seed1 = 0x7FED7FEDL; + unsigned long seed2 = 0xEEEEEEEEL; + int ch; + + while (*lpszString != 0) + { + ch = toupper(*lpszString++); + + seed1 = dwCryptTable[(dwHashType * 0x100) + ch] ^ (seed1 + seed2); + seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3; + } + return seed1; +} + +#define BLOCK_OFFSET_ADJUSTED_KEY 0x00020000L + +unsigned long ComputeFileKey(const char *lpszFilePath, const BlockTableEntry &blockEntry, unsigned long nArchiveOffset) +{ + assert(lpszFilePath); + + // Find the file name part of the path + const char *lpszFileName = strrchr(lpszFilePath, '\\'); + if (lpszFileName) + lpszFileName++; // Skip the \ + else + lpszFileName = lpszFilePath; + + // Hash the name to get the base key + unsigned long nFileKey = HashString(lpszFileName, MPQ_HASH_FILE_KEY); + + // Offset-adjust the key if necessary + if (blockEntry.Flags & BLOCK_OFFSET_ADJUSTED_KEY) + nFileKey = (nFileKey + blockEntry.BlockOffset) ^ blockEntry.FileSize; + + return nFileKey; +} + +3.3 FINDING FILES + +#define MPQ_HASH_ENTRY_EMPTY 0xFFFFFFFFL +#define MPQ_HASH_ENTRY_DELETED 0xFFFFFFFEL + +bool FindFileInHashTable(const HashTableEntry *lpHashTable, unsigned long nHashTableSize, const char *lpszFilePath, unsigned short nLang, unsigned char nPlatform, unsigned long &iFileHashEntry) +{ + assert(lpHashTable); + assert(nHashTableSize); + assert(lpszFilePath); + + // Find the home entry in the hash table for the file + unsigned long iInitEntry = HashString(lpszFilePath, MPQ_HASH_TABLE_OFFSET) & (nHashTableSize - 1); + + // Is there anything there at all? + if (lpHashTable[iInitEntry].FileBlockIndex == MPQ_HASH_ENTRY_EMPTY) + return false; + + // Compute the hashes to compare the hash table entry against + unsigned long nNameHashA = HashString(lpszFilePath, MPQ_HASH_NAME_A), + nNameHashB = HashString(lpszFilePath, MPQ_HASH_NAME_B), + iCurEntry = iInitEntry; + + // Check each entry in the hash table till a termination point is reached + do + { + if (lpHashTable[iCurEntry].FileBlockIndex != MPQ_HASH_ENTRY_DELETED) + { + if (lpHashTable[iCurEntry].FilePathHashA == nNameHashA + && lpHashTable[iCurEntry].FilePathHashB == nNameHashB + && lpHashTable[iCurEntry].Language == nLang + && lpHashTable[iCurEntry].Platform == nPlatform) + { + iFileHashEntry = iCurEntry; + + return true; + } + } + + iCurEntry = (iCurEntry + 1) & (nHashTableSize - 1); + } while (iCurEntry != iInitEntry && lpHashTable[iCurEntry].FileBlockIndex != MPQ_HASH_ENTRY_EMPTY); + + return false; +} + +3.4 DELETING FILES + +bool DeleteFile(HashTableEntry *lpHashTable, unsigned long nHashTableSize, BlockTableEntry *lpBlockTable, const char *lpszFilePath, unsigned short nLang, unsigned char nPlatform) +{ + assert(lpHashTable); + assert(nHashTableSize); + assert(lpBlockTable); + + // Find the file in the hash table + unsigned long iFileHashEntry; + + if (!FindFileInHashTable(lpHashTable, nHashTableSize, lpszFilePath, nLang, nPlatform, iFileHashEntry)) + return false; + + // Get the block table index before we nuke the hash table entry + unsigned long iFileBlockEntry = lpHashTable[iFileHashEntry].FileBlockIndex; + + // Delete the file's entry in the hash table + memset(&lpHashTable[iFileHashEntry], 0xFF, sizeof(HashTableEntry)); + + // If the next entry is empty, mark this one as empty; otherwise, mark this as deleted. + if (lpHashTable[(iFileHashEntry + 1) & (nHashTableSize - 1)].FileBlockIndex == MPQ_HASH_ENTRY_EMPTY) + lpHashTable[iFileHashEntry].FileBlockIndex = MPQ_HASH_ENTRY_EMPTY; + else + lpHashTable[iFileHashEntry].FileBlockIndex = MPQ_HASH_ENTRY_DELETED; + + // If the block occupies space, mark the block as free space; otherwise, clear the block table entry. + if (lpBlockTable[iFileBlockEntry].BlockSize > 0) + { + lpBlockTable[iFileBlockEntry].FileSize = 0; + lpBlockTable[iFileBlockEntry].Flags = 0; + } + else + memset(&lpBlockTable[iFileBlockEntry], 0, sizeof(BlockTableEntry); + + return true; +} + +3.5 CONVERSION OF FILETIME AND time_t +This code assumes that the base ("zero") date for time_t is 01/01/1970. This is true on Windows, Unix System V systems, and Mac OS X. It is unknown whether this is true on all other platforms. You'll need to research this yourself, if you plan on porting it somewhere else. + +#define EPOCH_OFFSET 116444736000000000ULL // Number of 100 ns units between 01/01/1601 and 01/01/1970 + +bool GetTimeFromFileTime(const FILETIME &fileTime, time_t &time) +{ + // The FILETIME represents a 64-bit integer: the number of 100 ns units since January 1, 1601 + unsigned long long nTime = ((unsigned long long)fileTime.dwHighDateTime << 32) + fileTime.dwLowDateTime; + + if (nTime < EPOCH_OFFSET) + return false; + + nTime -= EPOCH_OFFSET; // Convert the time base from 01/01/1601 to 01/01/1970 + nTime /= 10000000ULL; // Convert 100 ns to sec + + time = (time_t)nTime; + + // Test for overflow (FILETIME is 64 bits, time_t is 32 bits) + if ((nTime - (unsigned long long)time) > 0) + return false; + + return true; +} + +void GetFileTimeFromTime(const time_t &time, FILETIME &fileTime) +{ + unsigned long long nTime = (unsigned long long)time; + + nTime *= 10000000ULL; + nTime += EPOCH_OFFSET; + + fileTime.dwLowDateTime = (DWORD)nTime; + fileTime.dwHighDateTime = (DWORD)(nTime >> 32); +} + +3.6 FORMING A 64-BIT LARGE ARCHIVE OFFSET FROM 32-BIT AND 16-BIT COMPONENTS +unsigned long long MakeLargeArchiveOffset(unsigned long nOffsetLow, unsigned short nOffsetHigh) +{ + return ((unsigned long long)nOffsetHigh << 32) + (unsigned long long)nOffsetLow; +} + +4. REVISION HISTORY +1.0 + - Updated to include most of the changes found in the Burning Crusade Friends and Family beta + +0.91. + - Updated several structure member descriptions + - Listed the full set of characters that can separate list file entries + - Noted that (attributes), (listfile), and (signature) use the default language and platform codes + - Redid part of the file data specs to clarify the format of sectors + - Enhanced descriptions of the different kinds of block table entries + - Added ComputeFileKey, FindFileInHashTable, and DeleteFile source \ No newline at end of file diff --git a/contrib/vmap_extractor_v2/stormdll/StormDll.cpp b/contrib/vmap_extractor_v2/stormdll/StormDll.cpp new file mode 100644 index 00000000000..2031180c7e3 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormdll/StormDll.cpp @@ -0,0 +1,117 @@ +/*****************************************************************************/ +/* Storm.cpp Copyright (c) Ladislav Zezula 2003 */ +/*---------------------------------------------------------------------------*/ +/* This is just a dummy module for building import library for Storm.dll */ +/*---------------------------------------------------------------------------*/ +/* Date Ver Who Comment */ +/* -------- ---- --- ------- */ +/* 11.04.03 1.00 Lad The first version of Storm.cpp */ +/*****************************************************************************/ + +#include + +#define BUILDING_STORM_CPP +#define STORM_ALTERNATE_NAMES +#include "StormDll.h" + +BOOL WINAPI SFILE(OpenArchive)(LPCSTR lpFileName, DWORD dwPriority, DWORD dwFlags, HANDLE *hMPQ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +BOOL WINAPI SFILE(CloseArchive)(HANDLE hMPQ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +BOOL WINAPI SFILE(GetArchiveName)(HANDLE hMPQ, LPCSTR lpBuffer, DWORD dwBufferLength) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +BOOL WINAPI SFILE(OpenFile)(LPCSTR lpFileName, HANDLE *hFile) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +BOOL WINAPI SFILE(OpenFileEx)(HANDLE hMPQ, LPCSTR lpFileName, DWORD dwSearchScope, HANDLE *hFile) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +BOOL WINAPI SFILE(CloseFile)(HANDLE hFile) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +DWORD WINAPI SFILE(GetFileSize)(HANDLE hFile, LPDWORD lpFileSizeHigh) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +BOOL WINAPI SFILE(GetFileArchive)(HANDLE hFile, HANDLE *hMPQ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +BOOL WINAPI SFILE(GetFileName)(HANDLE hFile, LPCSTR lpBuffer, DWORD dwBufferLength) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +DWORD WINAPI SFILE(SetFilePointer)(HANDLE hFile, long lDistanceToMove, PLONG lplDistanceToMoveHigh, DWORD dwMoveMethod) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +BOOL WINAPI SFILE(ReadFile)(HANDLE hFile,LPVOID lpBuffer,DWORD nNumberOfBytesToRead,LPDWORD lpNumberOfBytesRead,LPOVERLAPPED lpOverlapped) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +LCID WINAPI SFILE(SetLocale)(LCID nNewLocale) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +BOOL WINAPI SFILE(GetBasePath)(LPCSTR lpBuffer, DWORD dwBufferLength) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +BOOL WINAPI SFILE(SetBasePath)(LPCSTR lpNewBasePath) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +BOOL WINAPI SFILE(Destroy)() +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +BOOL WINAPI SCOMP(Compress)(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int uCmp, int uCmpType, int nCmpLevel) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +BOOL WINAPI SCOMP(Decompress)(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} diff --git a/contrib/vmap_extractor_v2/stormdll/StormDll.def b/contrib/vmap_extractor_v2/stormdll/StormDll.def new file mode 100644 index 00000000000..8de88f5db3d --- /dev/null +++ b/contrib/vmap_extractor_v2/stormdll/StormDll.def @@ -0,0 +1,25 @@ +; Storm definition file with alternate Storm.dll names +LIBRARY "Storm" + +EXPORTS + StormCloseArchive @252 ; 0x0FC + StormCloseFile @253 ; 0x0FD + StormDestroy @262 ; 0x106 + StormGetFileArchive @264 ; 0x108 + StormGetFileSize @265 ; 0x109 + StormOpenArchive @266 ; 0x10A + StormOpenFile @267 ; 0x10B + StormOpenFileEx @268 ; 0x10C + StormReadFile @269 ; 0x10D + StormSetBasePath @270 ; 0x10E + StormSetFilePointer @271 ; 0x10F + StormSetLocale @272 ; 0x110 + StormGetBasePath @273 ; 0x111 + StormGetArchiveName @275 ; 0x113 + StormGetFileName @276 ; 0x114 + +; StormSetLastError @465 ; 0x + + StormCompress @551 ; 0x227 + StormDecompress @552 ; 0x228 + \ No newline at end of file diff --git a/contrib/vmap_extractor_v2/stormdll/StormDll.h b/contrib/vmap_extractor_v2/stormdll/StormDll.h new file mode 100644 index 00000000000..6d67820a22f --- /dev/null +++ b/contrib/vmap_extractor_v2/stormdll/StormDll.h @@ -0,0 +1,67 @@ +/*****************************************************************************/ +/* Storm.h Copyright Justin Olbrantz(Quantam) 2000 */ +/*---------------------------------------------------------------------------*/ +/* Storm Interface Library v1.0 for Windows */ +/* */ +/* Author : Justin Olbrantz(Quantam) */ +/* E-mail : omega@dragonfire.net */ +/* WWW : www.campaigncreations.com/starcraft/mpq2k/inside_mopaq/ */ +/*---------------------------------------------------------------------------*/ +/* Date Ver Who Comment */ +/* -------- ---- --- ------- */ +/* xx.xx.00 1.00 Qua The first version of Storm.h */ +/* 11.04.03 1.00 Lad Added some functions */ +/*****************************************************************************/ + +// We need the Windows data types for the Storm prototypes +#include + +#ifndef __STORM_H__ +#define __STORM_H__ + +// Somethimes is necessary to change the function names so they +// will not conflict with other MPQ tools. +#ifdef STORM_ALTERNATE_NAMES + #define SFILE(Name) Storm##Name + #define SCOMP(Name) Storm##Name +#else + #define SFILE(Name) SFile##Name + #define SCOMP(Name) SComp##Name +#endif + + +// Just in case anyone is still using C out there +#ifdef __cplusplus +extern "C" { +#endif + +// Storm file function prototypes +BOOL WINAPI SFILE(OpenArchive)(LPCSTR lpFileName, DWORD dwPriority, DWORD dwFlags, HANDLE *hMPQ); +BOOL WINAPI SFILE(CloseArchive)(HANDLE hMPQ); +BOOL WINAPI SFILE(GetArchiveName)(HANDLE hMPQ, LPCSTR lpBuffer, DWORD dwBufferLength); +BOOL WINAPI SFILE(OpenFile)(LPCSTR lpFileName, HANDLE *hFile); +BOOL WINAPI SFILE(OpenFileEx)(HANDLE hMPQ, LPCSTR lpFileName, DWORD dwSearchScope, HANDLE *hFile); +BOOL WINAPI SFILE(CloseFile)(HANDLE hFile); +DWORD WINAPI SFILE(GetFileSize)(HANDLE hFile, LPDWORD lpFileSizeHigh); +BOOL WINAPI SFILE(GetFileArchive)(HANDLE hFile, HANDLE *hMPQ); +BOOL WINAPI SFILE(GetFileName)(HANDLE hFile, LPCSTR lpBuffer, DWORD dwBufferLength); +DWORD WINAPI SFILE(SetFilePointer)(HANDLE hFile, long lDistanceToMove, PLONG lplDistanceToMoveHigh, DWORD dwMoveMethod); +BOOL WINAPI SFILE(ReadFile)(HANDLE hFile,LPVOID lpBuffer,DWORD nNumberOfBytesToRead,LPDWORD lpNumberOfBytesRead,LPOVERLAPPED lpOverlapped); +LCID WINAPI SFILE(SetLocale)(LCID nNewLocale); +BOOL WINAPI SFILE(GetBasePath)(LPCSTR lpBuffer, DWORD dwBufferLength); +BOOL WINAPI SFILE(SetBasePath)(LPCSTR lpNewBasePath); + +// Storm (de)compression functions +BOOL WINAPI SCOMP(Compress) (char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int uCmp, int uCmpType, int nCmpLevel); +BOOL WINAPI SCOMP(Decompress)(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength); + + +#if defined(_MSC_VER) && !defined(BUILDING_STORM_CPP) +#pragma comment(lib, "Storm.lib") // Force linking Storm.lib and thus Storm.dll +#endif + +#ifdef __cplusplus +} +#endif + +#endif // __STORM_H__ diff --git a/contrib/vmap_extractor_v2/stormlib/GfxDecode.cpp b/contrib/vmap_extractor_v2/stormlib/GfxDecode.cpp new file mode 100644 index 00000000000..665e5d38e49 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/GfxDecode.cpp @@ -0,0 +1,697 @@ +/*********************************************************************** +* +* Description: GfxDecode -- functions for reading Diablo's GFX files +* Author: Marko Friedemann +* Created at: Son Jan 27 15:20:43 CET 2002 +* Computer: hangloose.flachland-chemnitz.de +* System: Linux 2.4.16 on i686 +* +* Copyright (c) 2002 BMX-Chemnitz.DE All rights reserved. +* +* --------------------------------------------------------------------- +* included are functions for getting: +* - the framecount of .CEL-files -> celGetFrameCount() +* - single frames of .CEL-files -> celGetFrameData() +* - the framecount of .CL2-files -> cl2GetFrameCount() +* - single directions of .CL2-files (all frames) -> cl2GetDirData() +* - single .PCX-files (256 color; v2, v5) -> pcxGetData() +***********************************************************************/ + +#include +#include +#include + +#include "StormLib.h" + +#define TRANS_COL 256 + +using std::cerr; +using std::vector; + +/****** RAMP stuff ***************************************************** + * for a more detailed description/explanation see below + ***********************************************************************/ +// two variations: one/two ramp(s) +static const uint16_t c_2RampSize = 544; // the frame size +static const uint16_t c_1RampSize = 800; // the frame size + +// ramps (both variations) can be either left or right +static const uint16_t c_RampOffsetLeft[17] = { + 0, // __ + 8, // + 8 note that this __-- + 24, // + 16 "drawing" is __-- + 48, // + 24 upside down! __-- this area + 80, // + 32 __-- is always + 120, // + 40 __-- colored + 168, // + 48 __-- + 224, // + 56 __-- lower ramp ends here (+30 == 254) + 288, // + 64 --__ upper ramp might be missing + 348, // + 60 | --__ + 400, // + 52 | --__ this area + 444, // + 44 | --__ is always + 480, // + 36 | --__ colored + 508, // + 28 | either trans- --__ + 528, // + 20 | parent or colored --__ + 540, // + 12 | --__ +2 Pixels = 544 + 542 // + 2 | this last one doesn't exist, it's those^ 2 pixels +}; + +static const uint16_t c_RampOffsetRight[17] = { + 2, // __ before this, there are 2 Pixels + 14, // + 12 --__ 4^2 - 2 + 34, // + 20 --__ 6^2 - 2 + 62, // + 28 this area --__ 8^2 - 2 + 98, // + 36 is always --__ 10^2 - 2 pattern anyone? ;) + 142, // + 44 colored --__ + 194, // + 52 --__ + 254, // + 60 lower ramp ends here --__ (-30 == 224) + 318, // + 64 upper ramp might be missing __-- + 374, // + 56 __-- | + 422, // + 48 this area __-- | note that this + 462, // + 40 is always __-- | "drawing" + 494, // + 32 colored __-- eiter trans- | is upside down! + 518, // + 24 __-- parent or colored | + 534, // + 16 __-- | + 542, // + 8 __-- +2 Startpixels = 544 | + 542 // + 0 this last one doesn't exist, it | would be EOF +}; + +/****** FrameBuffer class ********************************************** + * holds buffers and size information of the actual target image + * purpose: buffer management and avoidance of ugly globals + **********************************************************************/ +class FrameBuf +{ + protected: + vector vecData; + uint8_t *pCurrRow; + uint8_t *pPalette; + uint16_t uRows; + uint16_t *upYSize; + uint16_t *upMaxX; + public: + uint16_t uCols; + uint16_t uXSize; + uint16_t uMaxBlock; + uint16_t uFrameNum; + bool bHasBlocks; + bool bHasRamps; + FrameBuf( + uint8_t *pPal=NULL, uint16_t frame=0, uint16_t xsize=0, + uint16_t *pysize=NULL, uint16_t *pmaxx=NULL, uint16_t maxblock=0) + { + pCurrRow = new uint8_t[4*xsize]; + pPalette = pPal; + uCols = 0; + uRows = 0; + uXSize = xsize; + uFrameNum = frame; + uMaxBlock = maxblock; + upYSize = pysize; + upMaxX = pmaxx; + bHasBlocks= false; + bHasRamps = false; + } + ~FrameBuf() + { + delete[] pCurrRow; + for (vector ::iterator vi=vecData.begin(); vi!=vecData.end(); vi++) + delete[] *vi; + vecData.clear(); + } + void addLine() + { + ++uRows; + uCols = 0; + vecData.push_back(pCurrRow); + pCurrRow = new uint8_t[4*uXSize]; + } + void addPixel(uint16_t uColorNum) + { + if (uColorNum > TRANS_COL) { + cerr << "\n*** there seemed to be an error, illegal color index " << uColorNum; + cerr << "\n +++ at (" << uCols << "," << uRows << "), see for yourself *** \n\n"; + uColorNum = TRANS_COL; // sane setting to avoid segfaults + } + + memcpy(pCurrRow + 4*uCols, pPalette + 4*uColorNum, 4*sizeof(uint8_t)); + if (++uCols == uXSize) + addLine(); + else if ((uColorNum != TRANS_COL) && (upMaxX != NULL) && (uCols > *upMaxX)) + *upMaxX = uCols; + } + // used to return the actual image data + uint8_t *getData() + { + uint16_t i; + vector ::reverse_iterator vri; + // allocate a buffer to hold the actual image size + uint8_t *tmp = new uint8_t[4*uXSize*uRows]; + + // the lines are upside down inside the vector, use reverse iterator + for (i=0, vri=vecData.rbegin(); vri!=vecData.rend(); vri++, i++) + memcpy(tmp+4*uXSize*i, *vri, 4*uXSize*sizeof(uint8_t)); + + *upYSize = uRows; // set height + + if (uCols > 0) { + cerr << "\n*** there seemed to be an error (last line does not match boundary, " << uCols << " pixels left)"; + cerr << "\n +++ this is often caused by specifying an invalid width, see for yourself *** \n\n"; + } + + return tmp; + } +}; + +uint16_t WINAPI celGetFrameCount(uint8_t *pFileBuf) +{ + uint32_t tmp; + memcpy(&tmp, pFileBuf, sizeof(uint32_t)); + return (uint16_t)tmp; +} + +/***** Block Decoder *************************************************** + * one of three possible decoding techniques necessary for .cel + * possible block contents are either colored (in that case the + * appropriate number of pixels are read) or transparent pixels + * there are neither ramps nor plain pixels allowed here + ***********************************************************************/ +uint8_t *celDecodeBlocks(uint8_t *pFileBuf, FrameBuf *pFrame, uint32_t *framestart) +{ + uint32_t uFilePos=framestart[pFrame->uFrameNum]; + uint8_t cRead=0, i=0; + + if (!pFrame->bHasBlocks) // sanity check + return NULL; + + while (uFilePos < framestart[pFrame->uFrameNum+1]) { + cRead = pFileBuf[uFilePos++]; + + if ((uFilePos == framestart[pFrame->uFrameNum]+1)) + // TODO: what is this 0x0A 0x00 stuff all about? + if ((cRead == 0x0A) && (pFileBuf[uFilePos] == 0x00)) { + uFilePos += 9; + cRead = pFileBuf[uFilePos++]; + } + + if (cRead > 0x7F) + // transparent block (complement, 256-val) + for (i=0; i<256-cRead; i++) + pFrame->addPixel(TRANS_COL); + else if (cRead < pFrame->uMaxBlock + 1) + // pixel block (block size pixels to be read!) + for (i=0; iaddPixel(pFileBuf[uFilePos++]); + else + cerr << "\n*** block mode: illegal block (> max_size) ***\n\n"; + } + return pFrame->getData(); +} + +/***** Ramp Decoder **************************************************** + * the second of three possible decoding techniques necessary for .cel + * each block save the first/last is enclosed by two 0x00 pairs + * those blocks affect _TWO_ rows with one being 2 colored pixels shorter + * the first/last "block" affects only one row + ***********************************************************************/ +uint8_t *celDecodeRamps(uint8_t *pFileBuf, FrameBuf *pFrame, uint32_t *framestart, bool bLeft) +{ + uint32_t uFrameLen = framestart[pFrame->uFrameNum+1]-framestart[pFrame->uFrameNum]; + uint32_t uFilePos=0; + uint16_t uBlockLen=0, i=0, j=0; + bool bFirstLonger=false; + + if (!pFrame->bHasRamps) // sanity check + return NULL; + + if (pFrame->uXSize != 32) // only used in that case + return NULL; + + if (!bLeft) { // get first two pixels for right side ramps + pFrame->addPixel(pFileBuf[framestart[pFrame->uFrameNum]]); + pFrame->addPixel(pFileBuf[framestart[pFrame->uFrameNum]+1]); + } + + // do all the ramp blocks + for (i=0; i<(uFrameLen == c_2RampSize ? 15 : 7); i++) { + uBlockLen = (bLeft ? (c_RampOffsetLeft[i+1] - c_RampOffsetLeft[i]) : (c_RampOffsetRight[i+1] - c_RampOffsetRight[i])); + uFilePos = framestart[pFrame->uFrameNum] + (bLeft ? c_RampOffsetLeft[i] : c_RampOffsetRight[i]) + 2; + bFirstLonger = (i>(bLeft ? 7 : 6)); + if (bLeft) { + // OK, first line, starting with transparency + for (j=0; juXSize - uBlockLen/2 + (bFirstLonger ? 0 : 2); j++) + pFrame->addPixel(TRANS_COL); + // fill it up with the pixel block + for (j=0; jaddPixel(pFileBuf[uFilePos++]); + // second line, starting again with transparency + for (j=0; juXSize - uBlockLen/2 + (bFirstLonger ? 2 : 0); j++) + pFrame->addPixel(TRANS_COL); + // fill the second line with the remaining pixels + for (j=0; jaddPixel(pFileBuf[uFilePos++]); + } else { + if (pFrame->uCols != 0) // fill current line with trans (if not empty) + for (j=pFrame->uXSize - pFrame->uCols; j>0; j--) + pFrame->addPixel(TRANS_COL); + // OK, insert the first pixels into a new line + for (j=0; jaddPixel(pFileBuf[uFilePos++]); + // fill the line with transparency + for (j=0; juXSize - uBlockLen/2 + (bFirstLonger ? 0 : 2); j++) + pFrame->addPixel(TRANS_COL); + // start a second line with the remaining pixels + for (j=0; jaddPixel(pFileBuf[uFilePos++]); + } + } + + // now read the last 0x00 pair and fill up + uBlockLen = (uFrameLen == c_2RampSize ? 30 : 2); // one or two ramps? + uFilePos = framestart[pFrame->uFrameNum] + (bLeft ? c_RampOffsetLeft[i] : c_RampOffsetRight[i]) + 2; + // the transparency for the last (single) 0x00 pair + for (j=0; jaddPixel(TRANS_COL); + if (bLeft) { // left side only: the remaining line + for (j=0; juXSize - uBlockLen; j++) + pFrame->addPixel(pFileBuf[uFilePos++]); + } + + // now the rest of the file (plain) + while (uFilePos < framestart[pFrame->uFrameNum+1]) + pFrame->addPixel(pFileBuf[uFilePos++]); + + // the uppermost line is emtpy when 2 ramps are used + if (uFrameLen == c_2RampSize) + for (j=0; juXSize; j++) + pFrame->addPixel(TRANS_COL); + + return pFrame->getData(); +} + +/***** celGetFrameData ************************************************* + * decode .cel data for given frame and xsize + * Args: + * *vpFileBuf the buffer containing the filecontent + * *palette the palette (4 bytes for each of the 257 entries) + * 256 colors are needed + 1 for alpha + * uXSize this information must be given + * uFrameNume the frame to get + * *uYSize the actual value is returned therein + * *uMaxX this can be used (if != NULL) to get the column + * of the rightmost nontransparent pixel (useable + * eg for fonts) + * + * Returns: an array containing 4 Bytes (RGBA) for each pixel + * + * --------------------------------------------------------------- + * Comments: dirty hack, started from scratch @ 2000-10-11 + * cleanly rewritten during incorporation into ladiks StormLib + * status: structured hack ;) + * + * It took me approx. 6 days to understand the format basics (hex viewer) + * For this I had a little help from a dos tool ("ddecode", from + * www.cowlevel.com, binary only, no sources) which, however, gave + * me the general idea what the pictures are actually supposed to look like. + * + * The fine adjustments, however, took quite some time and a little luck. + * After I had written to various people (mickyk and ladik), which could + * not help me, but wished best luck (thanks, btw, it helped ;)), I tried + * some reverse engineering which was not succesful in the end. + * + * I then had incidentally a new idea of what could be going on @ 2002-01-23. + * It just came to my mind that I could retry some actual painting in + * reverse order (had done that before to no avail) and when looking closer + * at it I realized the "ramp" stuff. This really is the trickiest part and + * it took me some eight days to implement it without breaking the other + * parts of the code. Very odd format indeed. + * + * TODO: learn what 0x0A 0x00 means + **********************************************************************/ +uint8_t * WINAPI celGetFrameData(uint8_t *pFileBuf, uint8_t *palette, uint16_t uXSize, uint16_t uFrameNum, uint16_t *uYSize, uint16_t *uMaxX) +{ + FrameBuf *pFrame; + uint32_t *framestart=NULL, frames=0, uFilePos=0; + uint16_t i, tmpWord=0; + uint8_t cRead=0, *data; + + memcpy(&frames, pFileBuf, sizeof(uint32_t)); + uFilePos += sizeof(uint32_t); + + if (pFileBuf == NULL) { + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + + if (palette == NULL) { + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + + if (uFrameNum > frames-1) { + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + + if (uYSize == NULL) { + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + + // in case we want to know the rightmost pixels column (usable eg. for fonts) + if (uMaxX != NULL) + *uMaxX = 0; + + // get the frame offsets + framestart = new uint32_t[frames+1]; + for (i=0; ibHasRamps = (i==(uFrameLen == c_2RampSize ? 16 : 8)); + if (!pFrame->bHasRamps) { // only one can apply + for (i=0; i<(uFrameLen == c_2RampSize ? 16 : 8); i++) { + memcpy(&tmpWord, pFileBuf+framestart[uFrameNum]+c_RampOffsetRight[i], sizeof(uint16_t)); + if (tmpWord != 0) + break; + } + pFrame->bHasRamps = (i==(uFrameLen == c_2RampSize ? 16 : 8)); // bRampsLeft stays false in this case + } + + if (pFrame->bHasRamps) { // decode ramps and be off (if appropriate) + data = celDecodeRamps(pFileBuf, pFrame, framestart, bRampsLeft); + delete pFrame; + delete[] framestart; + return data; + } + } + + /*********** block detection *************************************** + * 0x0A as start byte seems to be sufficient (though I still dunno + * what the trailing 10 bytes mean); in any other case we act as if + * blocks were to be used and check afterwards if the image looks + * OK (that is, the last line has no pixels in it) + ******************************************************************/ + + cRead = pFileBuf[framestart[uFrameNum]]; + if (cRead == 0x0A) // sufficient + pFrame->bHasBlocks = true; + // if width == 32 && framelen == 32*32, assume plain + else if ((uXSize != 32) || (uFrameLen != 32*32)) { // check needed + uFilePos=framestart[uFrameNum]; + i=0; + // rush through the frame + while (uFilePos < framestart[uFrameNum+1]) { + cRead = pFileBuf[uFilePos++]; + + // transparency blocks + while (cRead > 0x7F) { + i += 256-cRead; + i %= uXSize; + if (uFilePos < framestart[uFrameNum+1]) + cRead = pFileBuf[uFilePos++]; + else + cRead = 0; + } + + // colored pixel block + if (uFilePos < framestart[uFrameNum+1]) { + if (cRead < pFrame->uMaxBlock + 1) { + i+=cRead; + i%=uXSize; + uFilePos+=cRead; + } else { + // when the value is out of valid blockrange + i=1; // trigger error (1%uXSize != 0) + break; + } + } + } + if (i%uXSize == 0) // looks as if we got it right + pFrame->bHasBlocks=true; + } + + if (pFrame->bHasBlocks) { // use block decoder if appropriate + data = celDecodeBlocks(pFileBuf, pFrame, framestart); + delete pFrame; + delete[] framestart; + return data; + } + + // plain mode (#3), read each color index and write the pixel + uFilePos=framestart[uFrameNum]; + while (uFilePos < framestart[uFrameNum+1]) + pFrame->addPixel(pFileBuf[uFilePos++]); + + // cleanup, return image data and height + data = pFrame->getData(); + delete pFrame; + delete[] framestart; + return data; +} + +uint16_t WINAPI cl2GetFrameCount(uint8_t *pFileBuf) +{ + uint32_t tmp; + memcpy(&tmp, pFileBuf, sizeof(uint32_t)); + memcpy(&tmp, pFileBuf+tmp, sizeof(uint32_t)); + return (uint16_t)tmp; +} + +/***** cl2GetDirData *************************************************** + * decodes all frames of a .cl2 for given direction and xsize + * Args: + * *pFileBuf the buffer containing the filecontent + * *palette the palette (4 bytes for each of the 257 entries) + * 256 colors are needed + 1 for alpha + * uXSize this information must be given + * uDirNum the direction to get the frames from + * *uYSize the actual height is returned herein + * + * Returns: arrays containing 4 Bytes (RGBA) for each pixel + * where is read at runtime and handed back via *uFrames + * + * --------------------------------------------------------------- + * Comments: dirty hack, started from scratch @ 2000-10-12 + * + * The format basics are similar to .cel, with the main difference + * that the values read have reverse interpretation. In .cel a value + * greater than 0x7F means transparency, while in .cl2 this means + * color and vice-versa. .cl2 has the additional understanding + * of blocks of the same color (0x80 .. 0xBF) where the one color is + * written multiple times. + * + * .cl2 only uses the block scheme, so there is no detection + * necessary in order to get it right. The only thing still unknown + * is that 0x0A 0x00 stuff... + * + * TODO: learn what 0x0A 0x00 means + ***********************************************************************/ +BYTE ** WINAPI cl2GetDirData(BYTE *pFileBuf, BYTE *palette, WORD uXSize, WORD uDirNum, WORD *uYSize) +{ + FrameBuf *pFrame; + uint32_t frames=0, *framestart=NULL, uFilePos=0; + uint16_t i, fc; + uint8_t cRead=0, **data=NULL; + + if (pFileBuf == NULL) { + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + + if (palette == NULL) { + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + + if (uDirNum > 7) { + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + + if (uYSize == NULL) { + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + + // get direction offsets + uint32_t dirstart[8]; + for (i=0; i<8; i++) { + memcpy(&dirstart[i], pFileBuf+uFilePos, sizeof(uint32_t)); + uFilePos += sizeof(uint32_t); + } + + uFilePos = dirstart[uDirNum]; + + memcpy(&frames, pFileBuf+uFilePos, sizeof(uint32_t)); + uFilePos += sizeof(uint32_t); + + data = new uint8_t*[frames]; + + // get frame offsets + framestart = new uint32_t[frames+1]; + for (i=0; iaddPixel(TRANS_COL); + } else if (cRead < 0xC0) { + // read the next byte and write it <0xBF - cRead> times + for (i=0; i<0xBF - cRead; i++) + pFrame->addPixel(pFileBuf[uFilePos]); + ++uFilePos; + } else // cRead > 0xBF + // read a block of the given size and write it + for (i=0; i < 256-cRead; i++) + pFrame->addPixel(pFileBuf[uFilePos++]); + } + + // got the frame data, save it + data[fc] = pFrame->getData(); + delete pFrame; + } + + delete[] framestart; + return data; +} + +/****** pcxGetData ***************************************************** + * decodes pcx files (256 color, as in diablo mpq) + * Args: + * *pFileBuf the buffer containing the filecontent + * uFileSize the size of the file buffer + * uTransColor the palette entry to be transparent + * *uXSize the actual width is returned herein + * *uYSize the actual height is returned herein + * + * Returns: an array containing 4 Bytes (RGBA) for each pixel + * + * --------------------------------------------------------------- + * Comments: format info and pseudocode taken from: + * Klaus Holtorf, "Das Handbuch der Grafikformate" + * ISBN 3-7723-6393-8 + ***********************************************************************/ +BYTE * WINAPI pcxGetData(BYTE *pFileBuf, DWORD uFileSize, BYTE uTransColor, WORD *uXSize, WORD *uYSize) +{ + uint32_t uFilePos=0; + uint32_t uDataRead=0; // potentially big! (logo.pcx: 550 * 216 * 15 = 1,782,000) + uint16_t i=0; + uint8_t *data, *palette; + uint8_t uColorNum=0, uCount=0; + + struct pcx_header_t { + uint8_t id; + uint8_t version; + uint8_t compressed; + uint8_t bpp; + uint16_t x0; + uint16_t y0; + uint16_t x1; + uint16_t y1; + uint16_t xdpi; + uint16_t ydpi; + uint8_t pal[16][3]; + uint8_t reserved; + uint8_t layers; + uint16_t rowbytes; + uint16_t colortype; + uint8_t pad[58]; + } pcxHeader; + + if (pFileBuf == NULL) { + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + + if (uXSize == NULL) { + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + + if (uYSize == NULL) { + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + + // get image information + memcpy(&pcxHeader, pFileBuf, sizeof(struct pcx_header_t)); + *uXSize = (pcxHeader.x1 - pcxHeader.x0 + 1); + *uYSize = (pcxHeader.y1 - pcxHeader.y0 + 1); + + if ((pcxHeader.version != 2) && (pcxHeader.version != 5)) { + cerr << "cannot handle pcx v" << pcxHeader.version << "\n"; + return NULL; + } + + // get palette + palette = new uint8_t[256*4]; + if (pFileBuf[uFileSize - 768 - 1] != 0x0C) { + cerr << "palette error at " << uFileSize - 768 - 1 << "\n"; + return NULL; + } + for (i=0; i<256; i++) { + memcpy(palette+i*4, pFileBuf+uFileSize-768+i*3, 3*sizeof(uint8_t)); + palette[i*4+3] = 0xFF; + } + memset(palette+uTransColor*4, 0, 4*sizeof(uint8_t)); // transparent black + + // start right after the header + uFilePos = sizeof(struct pcx_header_t); + data = new uint8_t[*uXSize * *uYSize * 4]; + while (uDataRead < (uint32_t)(*uXSize * *uYSize)) { + // decompress + uColorNum = pFileBuf[uFilePos++]; + if ((pcxHeader.compressed) && (uColorNum > 0xBF)) { + uCount = (uColorNum & 0x3F); + uColorNum = pFileBuf[uFilePos++]; + } else + uCount = 1; + + // draw count pixels with color val + for (i=0; i +# Created at: Mon Jan 29 18:26:01 CEST 2001 +# Computer: whiplash.flachland-chemnitz.de +# System: Linux 2.4.0 on i686 +# +# Copyright (c) 2001 BMX-Chemnitz.DE All rights reserved. +# +##################################################################### ### + +FILES.cpp = SCommon.cpp SCompression.cpp SFileCompactArchive.cpp \ + SFileCreateArchiveEx.cpp SFileExtractFile.cpp SFileFindFile.cpp \ + SListFile.cpp SFileOpenArchive.cpp SFileOpenFileEx.cpp SFileReadFile.cpp \ + StormPortLinux.cpp wave/wave.cpp huffman/huff.cpp \ + pklib/crc32.cpp pklib/explode.cpp pklib/implode.cpp +FILES.o = $(FILES.cpp:.cpp=.o) + +LIB = libStorm.so + +CXX = g++ +CFLAGS = -Wall -s -D__SYS_ZLIB +I_FLAGS = +LDFLAGS = -lz -lbz2 + +all: $(LIB) + +$(LIB): $(FILES.o) + $(LD) -shared $(LDFLAGS) -o $(LIB) $(FILES.o) + +%.o: %.cpp + $(CXX) $(CFLAGS) -c $< -o $@ + +clean: + $(RM) $(FILES.o) $(LIB) + +new: clean all + +mrproper: clean + $(RM) Makefile.deps + +mrnew: mrproper new + +install: $(LIB) + install $(I_FLAGS) $(LIB) /usr/local/lib + mkdir -p /usr/local/include/StormLib + cp Storm.h /usr/local/include/StormLib + cp StormPort.h /usr/local/include/StormLib + ldconfig + +deps: + $(CXX) -MM $(CFLAGS) $(FILES.cpp) > Makefile.deps + +-include Makefile.deps + +.PHONY: all clean new mrpoper mrnew install deps diff --git a/contrib/vmap_extractor_v2/stormlib/SCommon.cpp b/contrib/vmap_extractor_v2/stormlib/SCommon.cpp new file mode 100644 index 00000000000..393310f675d --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/SCommon.cpp @@ -0,0 +1,1074 @@ +/*****************************************************************************/ +/* SCommon.cpp Copyright (c) Ladislav Zezula 2003 */ +/*---------------------------------------------------------------------------*/ +/* Common functions for StormLib, used by all SFile*** modules */ +/*---------------------------------------------------------------------------*/ +/* Date Ver Who Comment */ +/* -------- ---- --- ------- */ +/* 24.03.03 1.00 Lad The first version of SFileCommon.cpp */ +/* 19.11.03 1.01 Dan Big endian handling */ +/* 12.06.04 1.01 Lad Renamed to SCommon.cpp */ +/*****************************************************************************/ + +#define __STORMLIB_SELF__ +#include "StormLib.h" +#include "SCommon.h" + +char StormLibCopyright[] = "StormLib v 4.50 Copyright Ladislav Zezula 1998-2003"; + +//----------------------------------------------------------------------------- +// The buffer for decryption engine. + +TMPQArchive * pFirstOpen = NULL; // The first member of MPQ archives chain +LCID lcLocale = LANG_NEUTRAL; // File locale +USHORT wPlatform = 0; // File platform + +//----------------------------------------------------------------------------- +// Compression types + +// +// Data compressions +// +// Can be combination of MPQ_COMPRESSION_PKWARE, MPQ_COMPRESSION_BZIP2 +// and MPQ_COMPRESSION_ZLIB. Some newer compressions are not supported +// by older games. The table of supported compressions is here: +// +// MPQ_COMPRESSION_PKWARE - All games since Diablo I +// MPQ_COMPRESSION_ZLIB - Games since Starcraft +// MPQ_COMPRESSION_BZIP2 - Games since World of Warcraft +// + +static int nDataCmp = MPQ_COMPRESSION_ZLIB; + +// +// WAVE compressions by quality level +// + +static int uWaveCmpLevel[] = {-1, 4, 2}; +static int uWaveCmpType[] = {MPQ_COMPRESSION_PKWARE, 0x81, 0x81}; + +//----------------------------------------------------------------------------- +// Storm buffer functions + +// Buffer for the decryption engine +#define STORM_BUFFER_SIZE 0x500 +static DWORD StormBuffer[STORM_BUFFER_SIZE]; +static BOOL bStormBufferCreated = FALSE; + +int PrepareStormBuffer() +{ + DWORD dwSeed = 0x00100001; + DWORD index1 = 0; + DWORD index2 = 0; + int i; + + // Initialize the decryption buffer. + // Do nothing if already done. + if(bStormBufferCreated == FALSE) + { + for(index1 = 0; index1 < 0x100; index1++) + { + for(index2 = index1, i = 0; i < 5; i++, index2 += 0x100) + { + DWORD temp1, temp2; + + dwSeed = (dwSeed * 125 + 3) % 0x2AAAAB; + temp1 = (dwSeed & 0xFFFF) << 0x10; + + dwSeed = (dwSeed * 125 + 3) % 0x2AAAAB; + temp2 = (dwSeed & 0xFFFF); + + StormBuffer[index2] = (temp1 | temp2); + } + } + bStormBufferCreated = TRUE; + } + return ERROR_SUCCESS; +} + +//----------------------------------------------------------------------------- +// Encrypting and decrypting hash table + +void EncryptHashTable(DWORD * pdwTable, BYTE * pbKey, DWORD dwLength) +{ + DWORD dwSeed1 = 0x7FED7FED; + DWORD dwSeed2 = 0xEEEEEEEE; + DWORD ch; // One key character + + // Prepare seeds + while(*pbKey != 0) + { + ch = toupper(*pbKey++); + + dwSeed1 = StormBuffer[0x300 + ch] ^ (dwSeed1 + dwSeed2); + dwSeed2 = ch + dwSeed1 + dwSeed2 + (dwSeed2 << 5) + 3; + } + + // Encrypt it + dwSeed2 = 0xEEEEEEEE; + while(dwLength-- > 0) + { + dwSeed2 += StormBuffer[0x400 + (dwSeed1 & 0xFF)]; + ch = *pdwTable; + *pdwTable++ = ch ^ (dwSeed1 + dwSeed2); + + dwSeed1 = ((~dwSeed1 << 0x15) + 0x11111111) | (dwSeed1 >> 0x0B); + dwSeed2 = ch + dwSeed2 + (dwSeed2 << 5) + 3; + } +} + +void DecryptHashTable(DWORD * pdwTable, BYTE * pbKey, DWORD dwLength) +{ + DWORD dwSeed1 = 0x7FED7FED; + DWORD dwSeed2 = 0xEEEEEEEE; + DWORD ch; // One key character + + // Prepare seeds + while(*pbKey != 0) + { + ch = toupper(*pbKey++); + + dwSeed1 = StormBuffer[0x300 + ch] ^ (dwSeed1 + dwSeed2); + dwSeed2 = ch + dwSeed1 + dwSeed2 + (dwSeed2 << 5) + 3; + } + + // Decrypt it + dwSeed2 = 0xEEEEEEEE; + while(dwLength-- > 0) + { + dwSeed2 += StormBuffer[0x400 + (dwSeed1 & 0xFF)]; + ch = *pdwTable ^ (dwSeed1 + dwSeed2); + + dwSeed1 = ((~dwSeed1 << 0x15) + 0x11111111) | (dwSeed1 >> 0x0B); + dwSeed2 = ch + dwSeed2 + (dwSeed2 << 5) + 3; + *pdwTable++ = ch; + } +} + +//----------------------------------------------------------------------------- +// Encrypting and decrypting block table + +void EncryptBlockTable(DWORD * pdwTable, BYTE * pbKey, DWORD dwLength) +{ + DWORD dwSeed1 = 0x7FED7FED; + DWORD dwSeed2 = 0xEEEEEEEE; + DWORD ch; // One key character + + // Prepare seeds + while(*pbKey != 0) + { + ch = toupper(*pbKey++); + + dwSeed1 = StormBuffer[0x300 + ch] ^ (dwSeed1 + dwSeed2); + dwSeed2 = ch + dwSeed1 + dwSeed2 + (dwSeed2 << 5) + 3; + } + + // Decrypt it + dwSeed2 = 0xEEEEEEEE; + while(dwLength-- > 0) + { + dwSeed2 += StormBuffer[0x400 + (dwSeed1 & 0xFF)]; + ch = *pdwTable; + *pdwTable++ = ch ^ (dwSeed1 + dwSeed2); + + dwSeed1 = ((~dwSeed1 << 0x15) + 0x11111111) | (dwSeed1 >> 0x0B); + dwSeed2 = ch + dwSeed2 + (dwSeed2 << 5) + 3; + } +} + +void DecryptBlockTable(DWORD * pdwTable, BYTE * pbKey, DWORD dwLength) +{ + DWORD dwSeed1 = 0x7FED7FED; + DWORD dwSeed2 = 0xEEEEEEEE; + DWORD ch; // One key character + + // Prepare seeds + while(*pbKey != 0) + { + ch = toupper(*pbKey++); + + dwSeed1 = StormBuffer[0x300 + ch] ^ (dwSeed1 + dwSeed2); + dwSeed2 = ch + dwSeed1 + dwSeed2 + (dwSeed2 << 5) + 3; + } + + // Encrypt it + dwSeed2 = 0xEEEEEEEE; + while(dwLength-- > 0) + { + dwSeed2 += StormBuffer[0x400 + (dwSeed1 & 0xFF)]; + ch = *pdwTable ^ (dwSeed1 + dwSeed2); + + dwSeed1 = ((~dwSeed1 << 0x15) + 0x11111111) | (dwSeed1 >> 0x0B); + dwSeed2 = ch + dwSeed2 + (dwSeed2 << 5) + 3; + *pdwTable++ = ch; + } +} + +//----------------------------------------------------------------------------- +// Functions tries to get file decryption key. The trick comes from block +// positions which are stored at the begin of each compressed file. We know the +// file size, that means we know number of blocks that means we know the first +// DWORD value in block position. And if we know encrypted and decrypted value, +// we can find the decryption key !!! +// +// hf - MPQ file handle +// block - DWORD array of block positions +// ch - Decrypted value of the first block pos + +DWORD DetectFileSeed(DWORD * block, DWORD decrypted) +{ + DWORD saveSeed1; + DWORD temp = *block ^ decrypted; // temp = seed1 + seed2 + temp -= 0xEEEEEEEE; // temp = seed1 + StormBuffer[0x400 + (seed1 & 0xFF)] + + for(int i = 0; i < 0x100; i++) // Try all 255 possibilities + { + DWORD seed1; + DWORD seed2 = 0xEEEEEEEE; + DWORD ch; + + // Try the first DWORD (We exactly know the value) + seed1 = temp - StormBuffer[0x400 + i]; + seed2 += StormBuffer[0x400 + (seed1 & 0xFF)]; + ch = block[0] ^ (seed1 + seed2); + + if(ch != decrypted) + continue; + + // Add 1 because we are decrypting block positions + saveSeed1 = seed1 + 1; + + // If OK, continue and test the second value. We don't know exactly the value, + // but we know that the second one has lower 16 bits set to zero + // (no compressed block is larger than 0xFFFF bytes) + seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B); + seed2 = ch + seed2 + (seed2 << 5) + 3; + + seed2 += StormBuffer[0x400 + (seed1 & 0xFF)]; + ch = block[1] ^ (seed1 + seed2); + + if((ch & 0xFFFF0000) == 0) + return saveSeed1; + } + return 0; +} + +// Function tries to detect file seed. It expectes at least two uncompressed bytes +DWORD DetectFileSeed2(DWORD * pdwBlock, UINT nDwords, ...) +{ + va_list argList; + DWORD dwDecrypted[0x10]; + DWORD saveSeed1; + DWORD dwTemp; + DWORD i, j; + + // We need at least two DWORDS to detect the seed + if(nDwords < 0x02 || nDwords > 0x10) + return 0; + + va_start(argList, nDwords); + for(i = 0; i < nDwords; i++) + dwDecrypted[i] = va_arg(argList, DWORD); + va_end(argList); + + dwTemp = (*pdwBlock ^ dwDecrypted[0]) - 0xEEEEEEEE; + for(i = 0; i < 0x100; i++) // Try all 255 possibilities + { + DWORD seed1; + DWORD seed2 = 0xEEEEEEEE; + DWORD ch; + + // Try the first DWORD + seed1 = dwTemp - StormBuffer[0x400 + i]; + seed2 += StormBuffer[0x400 + (seed1 & 0xFF)]; + ch = pdwBlock[0] ^ (seed1 + seed2); + + if(ch != dwDecrypted[0]) + continue; + + saveSeed1 = seed1; + + // If OK, continue and test all bytes. + for(j = 1; j < nDwords; j++) + { + seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B); + seed2 = ch + seed2 + (seed2 << 5) + 3; + + seed2 += StormBuffer[0x400 + (seed1 & 0xFF)]; + ch = pdwBlock[j] ^ (seed1 + seed2); + + if(ch == dwDecrypted[j] && j == nDwords - 1) + return saveSeed1; + } + } + return 0; +} + + +//----------------------------------------------------------------------------- +// Encrypting and decrypting MPQ blocks + +void EncryptMPQBlock(DWORD * block, DWORD dwLength, DWORD dwSeed1) +{ + DWORD dwSeed2 = 0xEEEEEEEE; + DWORD ch; + + // Round to DWORDs + dwLength >>= 2; + + while(dwLength-- > 0) + { + dwSeed2 += StormBuffer[0x400 + (dwSeed1 & 0xFF)]; + ch = *block; + *block++ = ch ^ (dwSeed1 + dwSeed2); + + dwSeed1 = ((~dwSeed1 << 0x15) + 0x11111111) | (dwSeed1 >> 0x0B); + dwSeed2 = ch + dwSeed2 + (dwSeed2 << 5) + 3; + } +} + +void DecryptMPQBlock(DWORD * block, DWORD dwLength, DWORD dwSeed1) +{ + DWORD dwSeed2 = 0xEEEEEEEE; + DWORD ch; + + // Round to DWORDs + dwLength >>= 2; + + while(dwLength-- > 0) + { + dwSeed2 += StormBuffer[0x400 + (dwSeed1 & 0xFF)]; + ch = *block ^ (dwSeed1 + dwSeed2); + + dwSeed1 = ((~dwSeed1 << 0x15) + 0x11111111) | (dwSeed1 >> 0x0B); + dwSeed2 = ch + dwSeed2 + (dwSeed2 << 5) + 3; + *block++ = ch; + } +} + + +DWORD DecryptHashIndex(TMPQArchive * ha, const char * szFileName) +{ + BYTE * pbKey = (BYTE *)szFileName; + DWORD dwSeed1 = 0x7FED7FED; + DWORD dwSeed2 = 0xEEEEEEEE; + DWORD ch; + + while(*pbKey != 0) + { + ch = toupper(*pbKey++); + + dwSeed1 = StormBuffer[0x000 + ch] ^ (dwSeed1 + dwSeed2); + dwSeed2 = ch + dwSeed1 + dwSeed2 + (dwSeed2 << 5) + 3; + } + return (dwSeed1 & (ha->pHeader->dwHashTableSize - 1)); +} + +DWORD DecryptName1(const char * szFileName) +{ + BYTE * pbKey = (BYTE *)szFileName; + DWORD dwSeed1 = 0x7FED7FED; + DWORD dwSeed2 = 0xEEEEEEEE; + DWORD ch; + + while(*pbKey != 0) + { + ch = toupper(*pbKey++); + + dwSeed1 = StormBuffer[0x100 + ch] ^ (dwSeed1 + dwSeed2); + dwSeed2 = ch + dwSeed1 + dwSeed2 + (dwSeed2 << 5) + 3; + } + return dwSeed1; +} + +DWORD DecryptName2(const char * szFileName) +{ + BYTE * pbKey = (BYTE *)szFileName; + DWORD dwSeed1 = 0x7FED7FED; + DWORD dwSeed2 = 0xEEEEEEEE; + int ch; + + while(*pbKey != 0) + { + ch = toupper(*pbKey++); + + dwSeed1 = StormBuffer[0x200 + ch] ^ (dwSeed1 + dwSeed2); + dwSeed2 = ch + dwSeed1 + dwSeed2 + (dwSeed2 << 5) + 3; + } + return dwSeed1; +} + +DWORD DecryptFileSeed(const char * szFileName) +{ + BYTE * pbKey = (BYTE *)szFileName; + DWORD dwSeed1 = 0x7FED7FED; // EBX + DWORD dwSeed2 = 0xEEEEEEEE; // ESI + DWORD ch; + + while(*pbKey != 0) + { + ch = toupper(*pbKey++); // ECX + + dwSeed1 = StormBuffer[0x300 + ch] ^ (dwSeed1 + dwSeed2); + dwSeed2 = ch + dwSeed1 + dwSeed2 + (dwSeed2 << 5) + 3; + } + return dwSeed1; +} + +TMPQHash * GetHashEntry(TMPQArchive * ha, const char * szFileName) +{ + TMPQHash * pHashEnd = ha->pHashTable + ha->pHeader->dwHashTableSize; + TMPQHash * pHash0; // File hash entry (start) + TMPQHash * pHash; // File hash entry (current) + DWORD dwIndex = (DWORD)(DWORD_PTR)szFileName; + DWORD dwName1; + DWORD dwName2; + + // If filename is given by index, we have to search all hash entries for the right index. + if(dwIndex <= ha->pHeader->dwBlockTableSize) + { + // Pass all the hash entries and find the + for(pHash = ha->pHashTable; pHash < pHashEnd; pHash++) + { + if(pHash->dwBlockIndex == dwIndex) + return pHash; + } + return NULL; + } + + // Decrypt name and block index + dwIndex = DecryptHashIndex(ha, szFileName); + dwName1 = DecryptName1(szFileName); + dwName2 = DecryptName2(szFileName); + pHash = pHash0 = ha->pHashTable + dwIndex; + + // Look for hash index + while(pHash->dwBlockIndex != HASH_ENTRY_FREE) + { + if(pHash->dwName1 == dwName1 && pHash->dwName2 == dwName2 && pHash->dwBlockIndex != HASH_ENTRY_DELETED) + return pHash; + + // Move to the next hash entry + if(++pHash >= pHashEnd) + pHash = ha->pHashTable; + if(pHash == pHash0) + break; + } + + // File was not found + return NULL; +} + +// Retrieves the locale-specific hash entry +TMPQHash * GetHashEntryEx(TMPQArchive * ha, const char * szFileName, LCID lcLocale) +{ + TMPQHash * pHashEnd = ha->pHashTable + ha->pHeader->dwHashTableSize; + TMPQHash * pHash0 = NULL; // Language-neutral hash entry + TMPQHash * pHashX = NULL; // Language-speficic + TMPQHash * pHash = GetHashEntry(ha, szFileName); + + if(pHash != NULL) + { + TMPQHash * pHashStart = pHash; + DWORD dwName1 = pHash->dwName1; + DWORD dwName2 = pHash->dwName2; + + while(pHash->dwBlockIndex != HASH_ENTRY_FREE) + { + if(pHash->dwName1 == dwName1 && pHash->dwName2 == dwName2) + { + if(pHash->lcLocale == LANG_NEUTRAL) + pHash0 = pHash; + if(pHash->lcLocale == lcLocale) + pHashX = pHash; + + // If both found, break the loop + if(pHash0 != NULL && pHashX != NULL) + break; + } + + if(++pHash >= pHashEnd) + pHash = ha->pHashTable; + if(pHash == pHashStart) + return NULL; + } + + if(lcLocale != LANG_NEUTRAL && pHashX != NULL) + return pHashX; + if(pHash0 != NULL) + return pHash0; + return NULL; + } + + return pHash; +} + +// Encrypts file name and gets the hash entry +// Returns the hash pointer, which is always within the allocated array +TMPQHash * FindFreeHashEntry(TMPQArchive * ha, const char * szFileName) +{ + TMPQHash * pHashEnd = ha->pHashTable + ha->pHeader->dwHashTableSize; + TMPQHash * pHash0; // File hash entry (search start) + TMPQHash * pHash; // File hash entry + DWORD dwIndex = DecryptHashIndex(ha, szFileName); + DWORD dwName1 = DecryptName1(szFileName); + DWORD dwName2 = DecryptName2(szFileName); + DWORD dwBlockIndex = 0xFFFFFFFF; + + // Save the starting hash position + pHash = pHash0 = ha->pHashTable + dwIndex; + + // Look for the first free hash entry. Can be also a deleted entry + while(pHash->dwBlockIndex < HASH_ENTRY_DELETED) + { + if(++pHash >= pHashEnd) + pHash = ha->pHashTable; + if(pHash == pHash0) + return NULL; + } + + // Fill the hash entry with the informations about the file name + pHash->dwName1 = dwName1; + pHash->dwName2 = dwName2; + pHash->lcLocale = (USHORT)lcLocale; + pHash->wPlatform = wPlatform; + + // Now we have to find a free block entry + for(dwIndex = 0; dwIndex < ha->pHeader->dwBlockTableSize; dwIndex++) + { + TMPQBlock * pBlock = ha->pBlockTable + dwIndex; + + if((pBlock->dwFlags & MPQ_FILE_EXISTS) == 0) + { + dwBlockIndex = dwIndex; + break; + } + } + + // If no free block entry found, we have to use the index + // at the end of the current block table + if(dwBlockIndex == 0xFFFFFFFF) + dwBlockIndex = ha->pHeader->dwBlockTableSize; + pHash->dwBlockIndex = dwBlockIndex; + return pHash; +} + +//----------------------------------------------------------------------------- +// Checking for valid archive handle and valid file handle + +BOOL IsValidMpqHandle(TMPQArchive * ha) +{ + if(ha == NULL || IsBadReadPtr(ha, sizeof(TMPQArchive))) + return FALSE; + if(ha->pHeader == NULL || IsBadReadPtr(ha->pHeader, sizeof(TMPQHeader))) + return FALSE; + + return (ha->pHeader->dwID == ID_MPQ); +} + +BOOL IsValidFileHandle(TMPQFile * hf) +{ + if(hf == NULL || IsBadReadPtr(hf, sizeof(TMPQFile))) + return FALSE; + + if(hf->hFile != INVALID_HANDLE_VALUE) + return TRUE; + + return IsValidMpqHandle(hf->ha); +} + +// This function writes a local file into the MPQ archive. +// Returns 0 if OK, otherwise error code. +// TODO: Test for archives > 4GB +int AddFileToArchive( + TMPQArchive * ha, + HANDLE hFile, + const char * szArchivedName, + DWORD dwFlags, + DWORD dwQuality, + int nFileType, + BOOL * pbReplaced) +{ + LARGE_INTEGER RelativePos = {0}; + LARGE_INTEGER FilePos = {0}; + LARGE_INTEGER TempPos; + TMPQBlockEx * pBlockEx = NULL; // Entry in the extended block table + TMPQBlock * pBlock = NULL; // Entry in the block table + TMPQHash * pHash = NULL; // Entry in the hash table + DWORD * pdwBlockPos = NULL; // Block position table (compressed files only) + BYTE * pbFileData = NULL; // Uncompressed (source) data + BYTE * pbCompressed = NULL; // Compressed (target) data + BYTE * pbToWrite = NULL; // Data to write to the file + DWORD dwBlockPosLen = 0; // Length of the block table positions + DWORD dwTransferred = 0; // Number of bytes written into archive file + DWORD dwFileSize = 0; // Size of the file to add + DWORD dwSeed1 = 0; // Encryption seed + DWORD nBlocks = 0; // Number of file blocks + DWORD nBlock = 0; // Index of the currently written block + BOOL bReplaced = FALSE; // TRUE if replaced, FALSE if added + int nCmpFirst = nDataCmp; // Compression for the first data block + int nCmpNext = nDataCmp; // Compression for the next data blocks + int nCmp = nDataCmp; // Current compression + int nCmpLevel = -1; // Compression level + int nError = ERROR_SUCCESS; + + // Set the correct compression types + if(dwFlags & MPQ_FILE_COMPRESS_PKWARE) + nCmpFirst = nCmpNext = MPQ_COMPRESSION_PKWARE; + + if(dwFlags & MPQ_FILE_COMPRESS_MULTI) + { + if(nFileType == SFILE_TYPE_DATA) + nCmpFirst = nCmpNext = nDataCmp; + + if(nFileType == SFILE_TYPE_WAVE) + { + nCmpNext = uWaveCmpType[dwQuality]; + nCmpLevel = uWaveCmpLevel[dwQuality]; + } + } + + // Check if the file already exists in the archive + if(nError == ERROR_SUCCESS) + { + if((pHash = GetHashEntryEx(ha, szArchivedName, lcLocale)) != NULL) + { + if(pHash->lcLocale == lcLocale) + { + if((dwFlags & MPQ_FILE_REPLACEEXISTING) == 0) + { + nError = ERROR_ALREADY_EXISTS; + pHash = NULL; + } + else + bReplaced = TRUE; + } + else + pHash = NULL; + } + + if(nError == ERROR_SUCCESS && pHash == NULL) + { + pHash = FindFreeHashEntry(ha, szArchivedName); + if(pHash == NULL) + nError = ERROR_HANDLE_DISK_FULL; + } + } + + // Get the block table entry for the file + if(nError == ERROR_SUCCESS) + { + DWORD dwFileSizeHigh = 0; + + // Get the size of the added file + dwFileSize = GetFileSize(hFile, &dwFileSizeHigh); + if(dwFileSizeHigh != 0) + nError = ERROR_PARAMETER_QUOTA_EXCEEDED; + + // Fix the flags, if the file is too small + if(dwFileSize < 0x04) + dwFlags &= ~(MPQ_FILE_ENCRYPTED | MPQ_FILE_FIXSEED); + if(dwFileSize < 0x20) + dwFlags &= ~MPQ_FILE_COMPRESSED; + + if(pHash->dwBlockIndex == HASH_ENTRY_FREE) + pHash->dwBlockIndex = ha->pHeader->dwBlockTableSize; + + // The block table index cannot be larger than hash table size + if(pHash->dwBlockIndex >= ha->pHeader->dwHashTableSize) + nError = ERROR_HANDLE_DISK_FULL; + } + + // The file will be stored after the end of the last archived file + // (i.e. at old position of archived file + if(nError == ERROR_SUCCESS) + { + TMPQBlock * pBlockEnd = ha->pBlockTable + ha->pHeader->dwBlockTableSize; + const char * szTemp = strrchr(szArchivedName, '\\'); + + // Get the position of the first file + RelativePos.QuadPart = ha->pHeader->dwHeaderSize; + + // Find the position of the last file. It has to be after the last archived file + // (Do not use the dwArchiveSize here, because it may or may not + // include the hash table at the end of the file + pBlockEx = ha->pExtBlockTable; + for(pBlock = ha->pBlockTable; pBlock < pBlockEnd; pBlock++, pBlockEx++) + { + if(pBlock->dwFlags & MPQ_FILE_EXISTS) + { + TempPos.HighPart = pBlockEx->wFilePosHigh; + TempPos.LowPart = pBlock->dwFilePos; + TempPos.QuadPart += pBlock->dwCSize; + + if(TempPos.QuadPart > RelativePos.QuadPart) + RelativePos = TempPos; + } + } + + // When format V1, we cannot exceed 4 GB + if(ha->pHeader->wFormatVersion == MPQ_FORMAT_VERSION_1) + { + TempPos.QuadPart = ha->MpqPos.QuadPart + RelativePos.QuadPart; + TempPos.QuadPart += ha->pHeader->dwHashTableSize * sizeof(TMPQHash); + TempPos.QuadPart += ha->pHeader->dwBlockTableSize * sizeof(TMPQBlock); + TempPos.QuadPart += dwFileSize; + + if(TempPos.HighPart != 0) + nError = ERROR_DISK_FULL; + } + + // Get pointers to both block entries of the file + pBlockEx = ha->pExtBlockTable + pHash->dwBlockIndex; + pBlock = ha->pBlockTable + pHash->dwBlockIndex; + + // Save the file size info + pBlockEx->wFilePosHigh = (USHORT)RelativePos.HighPart; + pBlock->dwFilePos = RelativePos.LowPart; + pBlock->dwFSize = GetFileSize(hFile, NULL); + pBlock->dwFlags = dwFlags | MPQ_FILE_EXISTS; + + // Create seed1 for file encryption + if(szTemp != NULL) + szArchivedName = szTemp + 1; + + if(dwFlags & MPQ_FILE_ENCRYPTED) + { + dwSeed1 = DecryptFileSeed(szArchivedName); + + if(dwFlags & MPQ_FILE_FIXSEED) + dwSeed1 = (dwSeed1 + pBlock->dwFilePos) ^ pBlock->dwFSize; + } + } + + // Allocate buffer for the input data + if(nError == ERROR_SUCCESS) + { + nBlocks = (pBlock->dwFSize / ha->dwBlockSize) + 1; + if(pBlock->dwFSize % ha->dwBlockSize) + nBlocks++; + + pBlock->dwCSize = 0; + if((pbFileData = ALLOCMEM(BYTE, ha->dwBlockSize)) == NULL) + nError = ERROR_NOT_ENOUGH_MEMORY; + pbToWrite = pbFileData; + } + + // Allocate buffers for the compressed data + if(nError == ERROR_SUCCESS && (dwFlags & MPQ_FILE_COMPRESSED)) + { + pdwBlockPos = ALLOCMEM(DWORD, nBlocks + 1); + pbCompressed = ALLOCMEM(BYTE, ha->dwBlockSize * 2); + if(pdwBlockPos == NULL || pbCompressed == NULL) + nError = ERROR_NOT_ENOUGH_MEMORY; + pbToWrite = pbCompressed; + } + + // Set the file position to the point where the file will be stored + if(nError == ERROR_SUCCESS) + { + // Set the file pointer to file data position + FilePos.QuadPart = ha->MpqPos.QuadPart + RelativePos.QuadPart; + if(FilePos.QuadPart != ha->FilePointer.QuadPart) + { + SetFilePointer(ha->hFile, FilePos.LowPart, &FilePos.HighPart, FILE_BEGIN); + ha->FilePointer = FilePos; + } + } + + // Write block positions (if the file will be compressed) + if(nError == ERROR_SUCCESS && (dwFlags & MPQ_FILE_COMPRESSED)) + { + dwBlockPosLen = nBlocks * sizeof(DWORD); + if(dwFlags & MPQ_FILE_HAS_EXTRA) + dwBlockPosLen += sizeof(DWORD); + + memset(pdwBlockPos, 0, dwBlockPosLen); + pdwBlockPos[0] = dwBlockPosLen; + + // Write the block positions + BSWAP_ARRAY32_UNSIGNED((DWORD *)pdwBlockPos, nBlocks); + WriteFile(ha->hFile, pdwBlockPos, dwBlockPosLen, &dwTransferred, NULL); + BSWAP_ARRAY32_UNSIGNED((DWORD *)pdwBlockPos, nBlocks); + + if(dwTransferred == dwBlockPosLen) + pBlock->dwCSize += dwBlockPosLen; + else + nError = GetLastError(); + + // Update the current position in the file + ha->HashTablePos.QuadPart = FilePos.QuadPart + dwTransferred; + } + + // Write all file blocks + if(nError == ERROR_SUCCESS) + { + nCmp = nCmpFirst; + + SetFilePointer(hFile, 0, NULL, FILE_BEGIN); + for(nBlock = 0; nBlock < nBlocks-1; nBlock++) + { + DWORD dwInLength = ha->dwBlockSize; + DWORD dwOutLength = ha->dwBlockSize; + + // Load the block from the file + ReadFile(hFile, pbFileData, ha->dwBlockSize, &dwInLength, NULL); + if(dwInLength == 0) + break; + + // Compress the block, if necessary + dwOutLength = dwInLength; + if(pBlock->dwFlags & MPQ_FILE_COMPRESSED) + { + // Should be enough for compression + int nOutLength = ha->dwBlockSize * 2; + int nCmpType = 0; + + if(pBlock->dwFlags & MPQ_FILE_COMPRESS_PKWARE) + Compress_pklib((char *)pbCompressed, &nOutLength, (char *)pbFileData, dwInLength, &nCmpType, 0); + + if(pBlock->dwFlags & MPQ_FILE_COMPRESS_MULTI) + SCompCompress((char *)pbCompressed, &nOutLength, (char *)pbFileData, dwInLength, nCmp, 0, nCmpLevel); + + // The compressed block size must NOT be the same or greater like + // the original block size. If yes, do not compress the block + // and store the data as-is. + if(nOutLength >= (int)dwInLength) + { + memcpy(pbCompressed, pbFileData, dwInLength); + nOutLength = dwInLength; + } + + // Update block positions + dwOutLength = nOutLength; + pdwBlockPos[nBlock+1] = pdwBlockPos[nBlock] + dwOutLength; + nCmp = nCmpNext; + } + + // Encrypt the block, if necessary + if(pBlock->dwFlags & MPQ_FILE_ENCRYPTED) + { + BSWAP_ARRAY32_UNSIGNED((DWORD *)pbToWrite, dwOutLength / sizeof(DWORD)); + EncryptMPQBlock((DWORD *)pbToWrite, dwOutLength, dwSeed1 + nBlock); + BSWAP_ARRAY32_UNSIGNED((DWORD *)pbToWrite, dwOutLength / sizeof(DWORD)); + } + + // Write the block + WriteFile(ha->hFile, pbToWrite, dwOutLength, &dwTransferred, NULL); + if(dwTransferred != dwOutLength) + { + nError = ERROR_DISK_FULL; + break; + } + + // Update the hash table position and the compressed file size + ha->HashTablePos.QuadPart += dwTransferred; + pBlock->dwCSize += dwOutLength; + } + } + + // Now save the block positions + if(nError == ERROR_SUCCESS && (pBlock->dwFlags & MPQ_FILE_COMPRESSED)) + { + if(dwFlags & MPQ_FILE_HAS_EXTRA) + pdwBlockPos[nBlocks] = pdwBlockPos[nBlocks-1]; + + // If file is encrypted, block positions are also encrypted + if(dwFlags & MPQ_FILE_ENCRYPTED) + EncryptMPQBlock(pdwBlockPos, dwBlockPosLen, dwSeed1 - 1); + + // Set the position back to the block table + SetFilePointer(ha->hFile, FilePos.LowPart, &FilePos.HighPart, FILE_BEGIN); + + // Write block positions to the archive + BSWAP_ARRAY32_UNSIGNED((DWORD *)pdwBlockPos, nBlocks); + WriteFile(ha->hFile, pdwBlockPos, dwBlockPosLen, &dwTransferred, NULL); + if(dwTransferred != dwBlockPosLen) + nError = ERROR_DISK_FULL; + + ha->FilePointer.QuadPart = ha->FilePointer.QuadPart + dwTransferred; + } + + // If success, we have to change the settings + // in MPQ header. If failed, we have to clean hash entry + if(nError == ERROR_SUCCESS) + { + ha->pLastFile = NULL; + ha->dwBlockPos = 0; + ha->dwBuffPos = 0; + ha->dwFlags |= MPQ_FLAG_CHANGED; + + // Add new entry to the block table (if needed) + if(pHash->dwBlockIndex >= ha->pHeader->dwBlockTableSize) + ha->pHeader->dwBlockTableSize++; + + // Hash table size in the TMPQArchive is already set at this point + RelativePos.QuadPart = ha->HashTablePos.QuadPart - ha->MpqPos.QuadPart; + ha->pHeader->dwHashTablePos = RelativePos.LowPart; + ha->pHeader->wHashTablePosHigh = (USHORT)RelativePos.HighPart; + + // Update block table pos + RelativePos.QuadPart += (ha->pHeader->dwHashTableSize * sizeof(TMPQHash)); + ha->pHeader->wBlockTablePosHigh = (USHORT)RelativePos.HighPart; + ha->pHeader->dwBlockTablePos = RelativePos.LowPart; + ha->BlockTablePos.QuadPart = RelativePos.QuadPart + ha->MpqPos.QuadPart; + + // If the archive size exceeded 4GB, we have to use extended block table pos + RelativePos.QuadPart += (ha->pHeader->dwBlockTableSize * sizeof(TMPQBlock)); + if(RelativePos.HighPart != 0) + { + ha->pHeader->ExtBlockTablePos = RelativePos; + ha->ExtBlockTablePos.QuadPart = RelativePos.QuadPart + ha->MpqPos.QuadPart; + + RelativePos.QuadPart += (ha->pHeader->dwBlockTableSize * sizeof(TMPQBlockEx)); + } + + // Update archive size (only valid for version V1) + ha->MpqSize = RelativePos; + ha->pHeader->dwArchiveSize = ha->MpqSize.LowPart; + } + else + { + // Clear the hash table entry + if(pHash != NULL) + memset(pHash, 0xFF, sizeof(TMPQHash)); + } + + // Cleanup + if(pbCompressed != NULL) + FREEMEM(pbCompressed); + if(pdwBlockPos != NULL) + FREEMEM(pdwBlockPos); + if(pbFileData != NULL) + FREEMEM(pbFileData); + if(pbReplaced != NULL) + *pbReplaced = bReplaced; + return nError; +} + +int SetDataCompression(int nDataCompression) +{ + nDataCmp = nDataCompression; + return 0; +} + +// This method saves MPQ header, hash table and block table. +// TODO: Test for archives > 4GB +int SaveMPQTables(TMPQArchive * ha) +{ + BYTE * pbBuffer = NULL; + DWORD dwBytes; + DWORD dwWritten; + DWORD dwBuffSize = max(ha->pHeader->dwHashTableSize, ha->pHeader->dwBlockTableSize); + int nError = ERROR_SUCCESS; + + // Allocate buffer for encrypted tables + if(nError == ERROR_SUCCESS) + { + // Allocate temporary buffer for tables encryption + pbBuffer = ALLOCMEM(BYTE, sizeof(TMPQHash) * dwBuffSize); + if(pbBuffer == NULL) + nError = ERROR_NOT_ENOUGH_MEMORY; + } + + // Write the MPQ Header + if(nError == ERROR_SUCCESS) + { + DWORD dwHeaderSize = ha->pHeader->dwHeaderSize; + + // Write the MPQ header + SetFilePointer(ha->hFile, ha->MpqPos.LowPart, &ha->MpqPos.HighPart, FILE_BEGIN); + + // Convert to little endian for file save + BSWAP_TMPQHEADER(ha->pHeader); + WriteFile(ha->hFile, ha->pHeader, dwHeaderSize, &dwWritten, NULL); + BSWAP_TMPQHEADER(ha->pHeader); + + if(dwWritten != ha->pHeader->dwHeaderSize) + nError = ERROR_DISK_FULL; + } + + // Write the hash table + if(nError == ERROR_SUCCESS) + { + // Copy the hash table to temporary buffer + dwBytes = ha->pHeader->dwHashTableSize * sizeof(TMPQHash); + memcpy(pbBuffer, ha->pHashTable, dwBytes); + + // Convert to little endian for file save + EncryptHashTable((DWORD *)pbBuffer, (BYTE *)"(hash table)", dwBytes >> 2); + BSWAP_ARRAY32_UNSIGNED((DWORD *)pbBuffer, dwBytes / sizeof(DWORD)); + + // Set the file pointer to the offset of the hash table and write it + SetFilePointer(ha->hFile, ha->HashTablePos.LowPart, (PLONG)&ha->HashTablePos.HighPart, FILE_BEGIN); + WriteFile(ha->hFile, pbBuffer, dwBytes, &dwWritten, NULL); + if(dwWritten != dwBytes) + nError = ERROR_DISK_FULL; + } + + // Write the block table + if(nError == ERROR_SUCCESS) + { + // Copy the block table to temporary buffer + dwBytes = ha->pHeader->dwBlockTableSize * sizeof(TMPQBlock); + memcpy(pbBuffer, ha->pBlockTable, dwBytes); + + // Encrypt the block table and write it to the file + EncryptBlockTable((DWORD *)pbBuffer, (BYTE *)"(block table)", dwBytes >> 2); + + // Convert to little endian for file save + BSWAP_ARRAY32_UNSIGNED((DWORD *)pbBuffer, dwBytes / sizeof(DWORD)); + WriteFile(ha->hFile, pbBuffer, dwBytes, &dwWritten, NULL); + if(dwWritten != dwBytes) + nError = ERROR_DISK_FULL; + } + + // Write the extended block table + if(nError == ERROR_SUCCESS && ha->pHeader->ExtBlockTablePos.QuadPart != 0) + { + // We expect format V2 or newer in this case + assert(ha->pHeader->wFormatVersion >= MPQ_FORMAT_VERSION_2); + + // Copy the block table to temporary buffer + dwBytes = ha->pHeader->dwBlockTableSize * sizeof(TMPQBlockEx); + memcpy(pbBuffer, ha->pExtBlockTable, dwBytes); + + // Convert to little endian for file save + BSWAP_ARRAY16_UNSIGNED((USHORT *)pbBuffer, dwBytes / sizeof(USHORT)); + WriteFile(ha->hFile, pbBuffer, dwBytes, &dwWritten, NULL); + if(dwWritten != dwBytes) + nError = ERROR_DISK_FULL; + } + + + // Set end of file here + if(nError == ERROR_SUCCESS) + { + SetEndOfFile(ha->hFile); + } + + // Cleanup and exit + if(pbBuffer != NULL) + FREEMEM(pbBuffer); + return nError; +} + +// Frees the MPQ archive +// TODO: Test for archives > 4GB +void FreeMPQArchive(TMPQArchive *& ha) +{ + if(ha != NULL) + { + FREEMEM(ha->pbBlockBuffer); + FREEMEM(ha->pBlockTable); + FREEMEM(ha->pExtBlockTable); + FREEMEM(ha->pHashTable); + if(ha->pListFile != NULL) + SListFileFreeListFile(ha); + + if(ha->hFile != INVALID_HANDLE_VALUE) + CloseHandle(ha->hFile); + FREEMEM(ha); + ha = NULL; + } +} diff --git a/contrib/vmap_extractor_v2/stormlib/SCommon.h b/contrib/vmap_extractor_v2/stormlib/SCommon.h new file mode 100644 index 00000000000..b53be0ae2a8 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/SCommon.h @@ -0,0 +1,88 @@ +/*****************************************************************************/ +/* SCommon.h Copyright (c) Ladislav Zezula 2003 */ +/*---------------------------------------------------------------------------*/ +/* Common functions for encryption/decryption from Storm.dll. Included by */ +/* SFile*** functions, do not include and do not use this file directly */ +/*---------------------------------------------------------------------------*/ +/* Date Ver Who Comment */ +/* -------- ---- --- ------- */ +/* 24.03.03 1.00 Lad The first version of SFileCommon.h */ +/* 12.06.04 1.00 Lad Renamed to SCommon.h */ +/*****************************************************************************/ + +#ifndef __SCOMMON_H__ +#define __SCOMMON_H__ + +//----------------------------------------------------------------------------- +// StormLib private defines + +#define SFILE_TYPE_DATA 0 // Process the file as data file +#define SFILE_TYPE_WAVE 1 // Process the file as WAVe file + +//----------------------------------------------------------------------------- +// External variables + +extern TMPQArchive * pFirstOpen; +extern LCID lcLocale; + +//----------------------------------------------------------------------------- +// Encryption and decryption functions + +int PrepareStormBuffer(); + +void EncryptHashTable(DWORD * pdwTable, BYTE * pbKey, DWORD dwLength); +void DecryptHashTable(DWORD * pdwTable, BYTE * pbKey, DWORD dwLength); +TMPQHash * FindFreeHashEntry(TMPQArchive * ha, const char * szFileName); + +void EncryptBlockTable(DWORD * pdwTable, BYTE * pbKey, DWORD dwLength); +void DecryptBlockTable(DWORD * pdwTable, BYTE * pbKey, DWORD dwLength); + +DWORD DetectFileSeed(DWORD * block, DWORD decrypted); +DWORD DetectFileSeed2(DWORD * block, UINT nDwords, ...); +void EncryptMPQBlock(DWORD * pdwBlock, DWORD dwLength, DWORD dwSeed1); +void DecryptMPQBlock(DWORD * pdwBlock, DWORD dwLength, DWORD dwSeed1); + +DWORD DecryptHashIndex(TMPQArchive * ha, const char * szFileName); +DWORD DecryptName1 (const char * szFileName); +DWORD DecryptName2 (const char * szFileName); +DWORD DecryptFileSeed (const char * szFileName); + +TMPQHash * GetHashEntry (TMPQArchive * ha, const char * szFileName); +TMPQHash * GetHashEntryEx(TMPQArchive * ha, const char * szFileName, LCID lcLocale); + +//----------------------------------------------------------------------------- +// Compression and decompression functions + +int Compress_pklib (char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * pCmpType, int nCmpLevel); +int Decompress_pklib(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength); + +//----------------------------------------------------------------------------- +// Checking functions + +BOOL IsValidMpqHandle(TMPQArchive * ha); +BOOL IsValidFileHandle(TMPQFile * hf); + +//----------------------------------------------------------------------------- +// Other functions + +BOOL SFileOpenArchiveEx(const char * szMpqName, DWORD dwPriority, DWORD dwFlags, HANDLE * phMPQ, DWORD dwAccessMode = GENERIC_READ); +int AddFileToArchive(TMPQArchive * ha, HANDLE hFile, const char * szArchivedName, DWORD dwFlags, DWORD dwQuality, int nFileType, BOOL * pbReplaced); +int SetDataCompression(int nDataCompression); +int SaveMPQTables(TMPQArchive * ha); +void FreeMPQArchive(TMPQArchive *& ha); + +BOOL CheckWildCard(const char * szString, const char * szWildCard); + +//----------------------------------------------------------------------------- +// Listfile functions + +int SListFileCreateListFile(TMPQArchive * ha); +int SListFileAddNode(TMPQArchive * ha, const char * szAddedFile); +int SListFileRemoveNode(TMPQArchive * ha, const char * szFileName); +int SListFileRenameNode(TMPQArchive * ha, const char * szOldFileName, const char * szNewFileName); +int SListFileFreeListFile(TMPQArchive * ha); + +int SListFileSaveToMpq(TMPQArchive * ha); + +#endif // __SCOMMON_H__ + diff --git a/contrib/vmap_extractor_v2/stormlib/SCompression.cpp b/contrib/vmap_extractor_v2/stormlib/SCompression.cpp new file mode 100644 index 00000000000..612ef2cc262 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/SCompression.cpp @@ -0,0 +1,715 @@ +/*****************************************************************************/ +/* SCompression.cpp Copyright (c) Ladislav Zezula 2003 */ +/*---------------------------------------------------------------------------*/ +/* This module serves as a bridge between StormLib code and (de)compression */ +/* functions. All (de)compression calls go (and should only go) through this */ +/* module. No system headers should be included in this module to prevent */ +/* compile-time problems. */ +/*---------------------------------------------------------------------------*/ +/* Date Ver Who Comment */ +/* -------- ---- --- ------- */ +/* 01.04.03 1.00 Lad The first version of SCompression.cpp */ +/* 19.11.03 1.01 Dan Big endian handling */ +/*****************************************************************************/ + +#define __STORMLIB_SELF__ +#include "StormLib.h" +#include "SCommon.h" + +#include + +// Include functions from Pkware Data Compression Library +#include "pklib/pklib.h" + +// Include functions from zlib +#ifndef __SYS_ZLIB +#include "zlib/zlib.h" // Include functions from zlib +#else +#include // If zlib is available on system, use this instead +#endif + +// Include functions from Huffmann compression +#include "huffman/huff.h" + +// Include functions from WAVe compression +#include "wave/wave.h" + +// Include functions from BZip2 compression library +#ifndef __SYS_BZLIB +#include "bzip2/bzlib.h" // Include functions from bzlib +#else +#include // If bzlib is available on system, use this instead +#endif + +//----------------------------------------------------------------------------- +// Local structures + +// Information about the input and output buffers for pklib +typedef struct +{ + char * pInBuff; // Pointer to input data buffer + int nInPos; // Current offset in input data buffer + int nInBytes; // Number of bytes in the input buffer + char * pOutBuff; // Pointer to output data buffer + int nOutPos; // Position in the output buffer + int nMaxOut; // Maximum number of bytes in the output buffer +} TDataInfo; + +// Table of compression functions +typedef int (*COMPRESS)(char *, int *, char *, int, int *, int); +typedef struct +{ + unsigned long dwMask; // Compression mask + COMPRESS Compress; // Compression function +} TCompressTable; + +// Table of decompression functions +typedef int (*DECOMPRESS)(char *, int *, char *, int); +typedef struct +{ + unsigned long dwMask; // Decompression bit + DECOMPRESS Decompress; // Decompression function +} TDecompressTable; + + +/*****************************************************************************/ +/* */ +/* Support functions for Pkware Data Compression Library */ +/* */ +/*****************************************************************************/ + +// Function loads data from the input buffer. Used by Pklib's "implode" +// and "explode" function as user-defined callback +// Returns number of bytes loaded +// +// char * buf - Pointer to a buffer where to store loaded data +// unsigned int * size - Max. number of bytes to read +// void * param - Custom pointer, parameter of implode/explode + +static unsigned int ReadInputData(char * buf, unsigned int * size, void * param) +{ + TDataInfo * pInfo = (TDataInfo *)param; + unsigned int nMaxAvail = (pInfo->nInBytes - pInfo->nInPos); + unsigned int nToRead = *size; + + // Check the case when not enough data available + if(nToRead > nMaxAvail) + nToRead = nMaxAvail; + + // Load data and increment offsets + memcpy(buf, pInfo->pInBuff + pInfo->nInPos, nToRead); + pInfo->nInPos += nToRead; + + return nToRead; +} + +// Function for store output data. Used by Pklib's "implode" and "explode" +// as user-defined callback +// +// char * buf - Pointer to data to be written +// unsigned int * size - Number of bytes to write +// void * param - Custom pointer, parameter of implode/explode + +static void WriteOutputData(char * buf, unsigned int * size, void * param) +{ + TDataInfo * pInfo = (TDataInfo *)param; + unsigned int nMaxWrite = (pInfo->nMaxOut - pInfo->nOutPos); + unsigned int nToWrite = *size; + + // Check the case when not enough space in the output buffer + if(nToWrite > nMaxWrite) + nToWrite = nMaxWrite; + + // Write output data and increments offsets + memcpy(pInfo->pOutBuff + pInfo->nOutPos, buf, nToWrite); + pInfo->nOutPos += nToWrite; +} + +/*****************************************************************************/ +/* */ +/* "80" is IMA ADPCM stereo (de)compression */ +/* "40" is IMA ADPCM mono (de)compression */ +/* */ +/*****************************************************************************/ + +int Compress_wave_mono(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * pCmpType, int nCmpLevel) +{ + // Prepare the compression level for the next compression + // (After us, the Huffmann compression will be called) + if(0 < nCmpLevel && nCmpLevel <= 2) + { + nCmpLevel = 4; + *pCmpType = 6; + } + else if(nCmpLevel == 3) + { + nCmpLevel = 6; + *pCmpType = 8; + } + else + { + nCmpLevel = 5; + *pCmpType = 7; + } + *pdwOutLength = CompressWave((unsigned char *)pbOutBuffer, *pdwOutLength, (short *)pbInBuffer, dwInLength, 1, nCmpLevel); + return 0; +} + +int Decompress_wave_mono(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength) +{ + *pdwOutLength = DecompressWave((unsigned char *)pbOutBuffer, *pdwOutLength, (unsigned char *)pbInBuffer, dwInLength, 1); + return 1; +} + +int Compress_wave_stereo(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * pCmpType, int nCmpLevel) +{ + // Prepare the compression type for the next compression + // (After us, the Huffmann compression will be called) + if(0 < nCmpLevel && nCmpLevel <= 2) + { + nCmpLevel = 4; + *pCmpType = 6; + } + else if(nCmpLevel == 3) + { + nCmpLevel = 6; + *pCmpType = 8; + } + else + { + nCmpLevel = 5; + *pCmpType = 7; + } + *pdwOutLength = CompressWave((unsigned char *)pbOutBuffer, *pdwOutLength, (short *)pbInBuffer, dwInLength, 2, nCmpLevel); + return 0; +} + +int Decompress_wave_stereo(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength) +{ + *pdwOutLength = DecompressWave((unsigned char *)pbOutBuffer, *pdwOutLength, (unsigned char *)pbInBuffer, dwInLength, 2); + return 1; +} + +/*****************************************************************************/ +/* */ +/* The "01" (de)compression is the Huffman (de)compression */ +/* */ +/*****************************************************************************/ + +// 1500F4C0 +int Compress_huff(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * pCmpType, int /* nCmpLevel */) +{ + THuffmannTree ht; // Huffmann tree for compression + TOutputStream os; // Output stream + + // Initialize output stream + os.pbOutBuffer = (unsigned char *)pbOutBuffer; + os.dwOutSize = *pdwOutLength; + os.pbOutPos = (unsigned char *)pbOutBuffer; + os.dwBitBuff = 0; + os.nBits = 0; + + // Initialize the Huffmann tree for compression + ht.InitTree(true); + + *pdwOutLength = ht.DoCompression(&os, (unsigned char *)pbInBuffer, dwInLength, *pCmpType); + + // The following code is not necessary to run, because it has no + // effect on the output data. It only clears the huffmann tree, but when + // the tree is on the stack, who cares ? +// ht.UninitTree(); + return 0; +} + +// 1500F5F0 +int Decompress_huff(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int /* dwInLength */) +{ + THuffmannTree ht; + TInputStream is; + + // Initialize input stream +// is.pbInBuffer = (unsigned char *)pbInBuffer; + is.dwBitBuff = BSWAP_INT32_UNSIGNED(*(unsigned long *)pbInBuffer); + pbInBuffer += sizeof(unsigned long); + is.pbInBuffer = (unsigned char *)pbInBuffer; + is.nBits = 32; + + // Initialize the Huffmann tree for compression + ht.InitTree(false); + *pdwOutLength = ht.DoDecompression((unsigned char *)pbOutBuffer, *pdwOutLength, &is); + + // The following code is not necessary to run, because it has no + // effect on the output data. It only clears the huffmann tree, but when + // the tree is on the stack, who cares ? +// ht.UninitTree(); + return 0; +} + +/*****************************************************************************/ +/* */ +/* The "02" (de)compression is the ZLIB (de)compression */ +/* */ +/*****************************************************************************/ + +int Compress_zlib(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * /* pCmpType */, int /* nCmpLevel */) +{ + z_stream z; // Stream information for zlib + int nResult; + + // Fill the stream structure for zlib + z.next_in = (Bytef *)pbInBuffer; + z.avail_in = (uInt)dwInLength; + z.total_in = dwInLength; + z.next_out = (Bytef *)pbOutBuffer; + z.avail_out = *pdwOutLength; + z.total_out = 0; + z.zalloc = NULL; + z.zfree = NULL; + + // Initialize the compression structure. Storm.dll uses zlib version 1.1.3 + *pdwOutLength = 0; + if((nResult = deflateInit(&z, Z_DEFAULT_COMPRESSION)) == 0) + { + // Call zlib to compress the data + nResult = deflate(&z, Z_FINISH); + + if(nResult == Z_OK || nResult == Z_STREAM_END) + *pdwOutLength = z.total_out; + + deflateEnd(&z); + } + return nResult; +} + +int Decompress_zlib(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength) +{ + z_stream z; // Stream information for zlib + int nResult; + + // Fill the stream structure for zlib + z.next_in = (Bytef *)pbInBuffer; + z.avail_in = (uInt)dwInLength; + z.total_in = dwInLength; + z.next_out = (Bytef *)pbOutBuffer; + z.avail_out = *pdwOutLength; + z.total_out = 0; + z.zalloc = NULL; + z.zfree = NULL; + + // Initialize the decompression structure. Storm.dll uses zlib version 1.1.3 + if((nResult = inflateInit(&z)) == 0) + { + // Call zlib to decompress the data + nResult = inflate(&z, Z_FINISH); + *pdwOutLength = z.total_out; + inflateEnd(&z); + } + return nResult; +} + +/*****************************************************************************/ +/* */ +/* The "08" (de)compression is the Pkware DCL (de)compression */ +/* */ +/*****************************************************************************/ + +int Compress_pklib(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * pCmpType, int /* nCmpLevel */) +{ + TDataInfo Info; // Data information + char * work_buf = ALLOCMEM(char, CMP_BUFFER_SIZE);// Pklib's work buffer + unsigned int dict_size; // Dictionary size + unsigned int ctype; // Compression type + + // Fill data information structure + Info.pInBuff = pbInBuffer; + Info.nInPos = 0; + Info.nInBytes = dwInLength; + Info.pOutBuff = pbOutBuffer; + Info.nOutPos = 0; + Info.nMaxOut = *pdwOutLength; + + // Set the compression type and dictionary size + ctype = (*pCmpType == 2) ? CMP_ASCII : CMP_BINARY; + if (dwInLength < 0x600) + dict_size = 0x400; + else if(0x600 <= dwInLength && dwInLength < 0xC00) + dict_size = 0x800; + else + dict_size = 0x1000; + + // Do the compression + implode(ReadInputData, WriteOutputData, work_buf, &Info, &ctype, &dict_size); + *pdwOutLength = Info.nOutPos; + FREEMEM(work_buf); + return 0; +} + +int Decompress_pklib(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength) +{ + TDataInfo Info; // Data information + char * work_buf = ALLOCMEM(char, EXP_BUFFER_SIZE);// Pklib's work buffer + + // Fill data information structure + Info.pInBuff = pbInBuffer; + Info.nInPos = 0; + Info.nInBytes = dwInLength; + Info.pOutBuff = pbOutBuffer; + Info.nOutPos = 0; + Info.nMaxOut = *pdwOutLength; + + // Do the decompression + explode(ReadInputData, WriteOutputData, work_buf, &Info); + + // Fix: If PKLIB is unable to decompress the data, they are uncompressed + if(Info.nOutPos == 0) + { + Info.nOutPos = min(*pdwOutLength, dwInLength); + memcpy(pbOutBuffer, pbInBuffer, Info.nOutPos); + } + + *pdwOutLength = Info.nOutPos; + FREEMEM(work_buf); + return 0; +} + +/*****************************************************************************/ +/* */ +/* The "10" (de)compression is the Bzip2 (de)compression */ +/* */ +/*****************************************************************************/ + +int Compress_bzip2(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * pCmpType, int nCmpLevel) +{ + bz_stream strm; + int blockSize100k; + int workFactor = 30; + + // Keep compiler happy + nCmpLevel = nCmpLevel; + + // Initialize the BZLIB compression + strm.bzalloc = NULL; + strm.bzfree = NULL; + + // Adjust the block size + blockSize100k = *pCmpType; + if(blockSize100k < 1 || blockSize100k > 9) + blockSize100k = 9; + + // Blizzard uses 9 as blockSize100k, (0 as workFactor) + if(BZ2_bzCompressInit(&strm, blockSize100k, 0, workFactor) == 0) + { + strm.next_in = pbInBuffer; + strm.avail_in = dwInLength; + strm.next_out = pbOutBuffer; + strm.avail_out = *pdwOutLength; + + // Perform the compression + while(BZ2_bzCompress(&strm, (strm.avail_in != 0) ? BZ_RUN : BZ_FINISH) != BZ_STREAM_END); + + // Put the stream into idle state + BZ2_bzCompressEnd(&strm); + *pdwOutLength = strm.total_out_lo32; + } + else + { + *pdwOutLength = 0; + } + + return 0; +} + +int Decompress_bzip2(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength) +{ + bz_stream strm; + + // Initialize the BZLIB decompression + strm.bzalloc = NULL; + strm.bzfree = NULL; + if(BZ2_bzDecompressInit(&strm, 0, 0) == 0) + { + strm.next_in = pbInBuffer; + strm.avail_in = dwInLength; + strm.next_out = pbOutBuffer; + strm.avail_out = *pdwOutLength; + + // Perform the decompression + while(BZ2_bzDecompress(&strm) != BZ_STREAM_END); + + // Put the stream into idle state + BZ2_bzDecompressEnd(&strm); + *pdwOutLength = strm.total_out_lo32; + } + else + { + // Set zero output length + *pdwOutLength = 0; + } + + return 0; +} + +/*****************************************************************************/ +/* */ +/* SCompCompress */ +/* */ +/*****************************************************************************/ + +// This table contains compress functions which can be applied to +// uncompressed blocks. Each bit set means the corresponding +// compression method/function must be applied. +// +// WAVes compression Data compression +// ------------------ ------------------- +// 1st block - 0x08 0x08 (D, HF, W2, SC, D2) +// Rest blocks - 0x81 0x02 (W3) + +static TCompressTable cmp_table[] = +{ + {MPQ_COMPRESSION_WAVE_MONO, Compress_wave_mono}, // IMA ADPCM mono compression + {MPQ_COMPRESSION_WAVE_STEREO, Compress_wave_stereo}, // IMA ADPCM stereo compression + {MPQ_COMPRESSION_HUFFMANN, Compress_huff}, // Huffmann compression + {MPQ_COMPRESSION_ZLIB, Compress_zlib}, // Compression with the "zlib" library + {MPQ_COMPRESSION_PKWARE, Compress_pklib}, // Compression with Pkware DCL + {MPQ_COMPRESSION_BZIP2, Compress_bzip2} // Compression Bzip2 library +}; + +int WINAPI SCompCompress(char * pbCompressed, int * pdwOutLength, char * pbUncompressed, int dwInLength, + int uCompressions, int nCmpType, int nCmpLevel) +{ + char * pbTempBuff = NULL; // Temporary storage for decompressed data + char * pbOutput = pbCompressed; // Current output buffer + char * pbInput; // Current input buffer + int uCompressions2; + int dwCompressCount = 0; + int dwDoneCount = 0; + int dwOutSize = 0; + int dwInSize = dwInLength; + int dwEntries = (sizeof(cmp_table) / sizeof(TCompressTable)); + int nResult = 1; + int i; + + // Check for valid parameters + if(!pdwOutLength || *pdwOutLength < dwInLength || !pbCompressed || !pbUncompressed) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + // Count the compressions + for(i = 0, uCompressions2 = uCompressions; i < dwEntries; i++) + { + if(uCompressions & cmp_table[i].dwMask) + dwCompressCount++; + + uCompressions2 &= ~cmp_table[i].dwMask; + } + + // If a compression remains, do nothing + if(uCompressions2 != 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + // If more that one compression, allocate intermediate buffer + if(dwCompressCount >= 2) + pbTempBuff = ALLOCMEM(char, *pdwOutLength + 1); + + // Perform the compressions + pbInput = pbUncompressed; + dwInSize = dwInLength; + for(i = 0, uCompressions2 = uCompressions; i < dwEntries; i++) + { + if(uCompressions2 & cmp_table[i].dwMask) + { + // Set the right output buffer + dwCompressCount--; + pbOutput = (dwCompressCount & 1) ? pbTempBuff : pbCompressed; + + // Perform the partial compression + dwOutSize = *pdwOutLength - 1; + + cmp_table[i].Compress(pbOutput + 1, &dwOutSize, pbInput, dwInSize, &nCmpType, nCmpLevel); + if(dwOutSize == 0) + { + SetLastError(ERROR_GEN_FAILURE); + *pdwOutLength = 0; + nResult = 0; + break; + } + + // If the compression failed, copy the block instead + if(dwOutSize >= dwInSize - 1) + { + if(dwDoneCount > 0) + pbOutput++; + + memcpy(pbOutput, pbInput, dwInSize); + pbInput = pbOutput; + uCompressions &= ~cmp_table[i].dwMask; + dwOutSize = dwInSize; + } + else + { + pbInput = pbOutput + 1; + dwInSize = dwOutSize; + dwDoneCount++; + } + } + } + + // Copy the compressed data to the correct output buffer + if(nResult != 0) + { + if(uCompressions && (dwInSize + 1) < *pdwOutLength) + { + if(pbOutput != pbCompressed && pbOutput != pbCompressed + 1) + memcpy(pbCompressed, pbOutput, dwInSize); + *pbCompressed = (char)uCompressions; + *pdwOutLength = dwInSize + 1; + } + else + { + memmove(pbCompressed, pbUncompressed, dwInSize); + *pdwOutLength = dwInSize; + } + } + + // Cleanup and return + if(pbTempBuff != NULL) + FREEMEM(pbTempBuff); + return nResult; +} + +/*****************************************************************************/ +/* */ +/* SCompDecompress */ +/* */ +/*****************************************************************************/ + +// This table contains decompress functions which can be applied to +// uncompressed blocks. The compression mask is stored in the first byte +// of compressed block +static TDecompressTable dcmp_table[] = +{ + {MPQ_COMPRESSION_BZIP2, Decompress_bzip2}, // Decompression with Bzip2 library + {MPQ_COMPRESSION_PKWARE, Decompress_pklib}, // Decompression with Pkware Data Compression Library + {MPQ_COMPRESSION_ZLIB, Decompress_zlib}, // Decompression with the "zlib" library + {MPQ_COMPRESSION_HUFFMANN, Decompress_huff}, // Huffmann decompression + {MPQ_COMPRESSION_WAVE_STEREO, Decompress_wave_stereo}, // IMA ADPCM stereo decompression + {MPQ_COMPRESSION_WAVE_MONO, Decompress_wave_mono} // IMA ADPCM mono decompression +}; + +int WINAPI SCompDecompress(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength) +{ + char * pbTempBuff = NULL; // Temporary storage for decompressed data + char * pbWorkBuff = NULL; // Where to store decompressed data + int dwOutLength = *pdwOutLength; // For storage number of output bytes + unsigned fDecompressions1; // Decompressions applied to the block + unsigned fDecompressions2; // Just another copy of decompressions applied to the block + int dwCount = 0; // Counter for every use + int dwEntries = (sizeof(dcmp_table) / sizeof(TDecompressTable)); + int nResult = 1; + int i; + + // If the input length is the same as output, do nothing. + if(dwInLength == dwOutLength) + { + if(pbInBuffer == pbOutBuffer) + return 1; + + memcpy(pbOutBuffer, pbInBuffer, dwInLength); + *pdwOutLength = dwInLength; + return 1; + } + + // Get applied compression types and decrement data length + fDecompressions1 = fDecompressions2 = (unsigned char)*pbInBuffer++; + dwInLength--; + + // Search decompression table type and get all types of compression + for(i = 0; i < dwEntries; i++) + { + // We have to apply this decompression ? + if(fDecompressions1 & dcmp_table[i].dwMask) + dwCount++; + + // Clear this flag from temporary variable. + fDecompressions2 &= ~dcmp_table[i].dwMask; + } + + // Check if there is some method unhandled + // (E.g. compressed by future versions) + if(fDecompressions2 != 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + // If there is more than only one compression, we have to allocate extra buffer + if(dwCount >= 2) + pbTempBuff = ALLOCMEM(char, dwOutLength); + + // Apply all decompressions + for(i = 0, dwCount = 0; i < dwEntries; i++) + { + // If not used this kind of compression, skip the loop + if(fDecompressions1 & dcmp_table[i].dwMask) + { + // If odd case, use target buffer for output, otherwise use allocated tempbuffer + pbWorkBuff = (dwCount++ & 1) ? pbTempBuff : pbOutBuffer; + dwOutLength = *pdwOutLength; + + // Decompress buffer using corresponding function + dcmp_table[i].Decompress(pbWorkBuff, &dwOutLength, pbInBuffer, dwInLength); + if(dwOutLength == 0) + { + SetLastError(ERROR_GEN_FAILURE); + nResult = 0; + break; + } + + // Move output length to src length for next compression + dwInLength = dwOutLength; + pbInBuffer = pbWorkBuff; + } + } + + // If output buffer is not the same like target buffer, we have to copy data + if(nResult != 0) + { + if(pbWorkBuff != pbOutBuffer) + memcpy(pbOutBuffer, pbInBuffer, dwOutLength); + + } + + // Delete temporary buffer, if necessary + if(pbTempBuff != NULL) + FREEMEM(pbTempBuff); + + *pdwOutLength = dwOutLength; + return nResult; +} + +/*****************************************************************************/ +/* */ +/* SCompSetDataCompression */ +/* */ +/*****************************************************************************/ + +int WINAPI SCompSetDataCompression(int nDataCompression) +{ + int nValidMask = (MPQ_COMPRESSION_ZLIB | MPQ_COMPRESSION_PKWARE | MPQ_COMPRESSION_BZIP2); + + if((nDataCompression & nValidMask) != nDataCompression) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + SetDataCompression(nDataCompression); + return TRUE; +} + + diff --git a/contrib/vmap_extractor_v2/stormlib/SFileCompactArchive.cpp b/contrib/vmap_extractor_v2/stormlib/SFileCompactArchive.cpp new file mode 100644 index 00000000000..9510b15ae1f --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/SFileCompactArchive.cpp @@ -0,0 +1,691 @@ +/*****************************************************************************/ +/* SFileCompactArchive.cpp Copyright (c) Ladislav Zezula 2003 */ +/*---------------------------------------------------------------------------*/ +/* Archive compacting function */ +/*---------------------------------------------------------------------------*/ +/* Date Ver Who Comment */ +/* -------- ---- --- ------- */ +/* 14.04.03 1.00 Lad Splitted from SFileCreateArchiveEx.cpp */ +/* 19.11.03 1.01 Dan Big endian handling */ +/*****************************************************************************/ + +#define __STORMLIB_SELF__ +#include "StormLib.h" +#include "SCommon.h" + +/*****************************************************************************/ +/* Local structures */ +/*****************************************************************************/ + +/*****************************************************************************/ +/* Local variables */ +/*****************************************************************************/ + +static COMPACTCB CompactCB = NULL; +static void * lpUserData = NULL; + +/*****************************************************************************/ +/* Local functions */ +/*****************************************************************************/ + +// Creates a copy of hash table +static TMPQHash * CopyHashTable(TMPQArchive * ha) +{ + TMPQHash * pHashTableCopy = ALLOCMEM(TMPQHash, ha->pHeader->dwHashTableSize); + + if(pHashTableCopy != NULL) + memcpy(pHashTableCopy, ha->pHashTable, sizeof(TMPQHash) * ha->pHeader->dwHashTableSize); + + return pHashTableCopy; +} + +// TODO: Test for archives > 4GB +static int CheckIfAllFilesKnown(TMPQArchive * ha, const char * szListFile, DWORD * pFileSeeds) +{ + TMPQHash * pHashTableCopy = NULL; // Copy of the hash table + TMPQHash * pHash; + TMPQHash * pHashEnd = NULL; // End of the hash table + DWORD dwFileCount = 0; + int nError = ERROR_SUCCESS; + + // First of all, create a copy of hash table + if(nError == ERROR_SUCCESS) + { + if((pHashTableCopy = CopyHashTable(ha)) == NULL) + nError = ERROR_NOT_ENOUGH_MEMORY; + pHashEnd = pHashTableCopy + ha->pHeader->dwHashTableSize; + + // Notify the user + if(CompactCB != NULL) + CompactCB(lpUserData, CCB_CHECKING_FILES, 0, ha->pHeader->dwBlockTableSize); + } + + // Now check all the files from the filelist + if(nError == ERROR_SUCCESS) + { + SFILE_FIND_DATA wf; + HANDLE hFind = SFileFindFirstFile((HANDLE)ha, "*", &wf, szListFile); + BOOL bResult = TRUE; + + // Do while some files have been found + while(hFind != NULL && bResult) + { + TMPQHash * pHash = GetHashEntry(ha, wf.cFileName); + + // If the hash table entry has been found, find it's position + // in the hash table copy + if(pHash != NULL) + { + pHash = pHashTableCopy + (pHash - ha->pHashTable); + if(pHash->dwName1 != (DWORD)-1 && pHash->dwName2 != (DWORD)-1) + { + TMPQBlock * pBlock = ha->pBlockTable + pHash->dwBlockIndex; + DWORD dwSeed = 0; + + // Resolve the file seed. Use plain file name for it + if(pBlock->dwFlags & MPQ_FILE_ENCRYPTED) + { + char * szFileName = strrchr(wf.cFileName, '\\'); + + if(szFileName == NULL) + szFileName = wf.cFileName; + else + szFileName++; + + dwSeed = DecryptFileSeed(szFileName); + if(pBlock->dwFlags & MPQ_FILE_FIXSEED) + dwSeed = (dwSeed + pBlock->dwFilePos) ^ pBlock->dwFSize; + } + pFileSeeds[pHash->dwBlockIndex] = dwSeed; + + pHash->dwName1 = 0xFFFFFFFF; + pHash->dwName2 = 0xFFFFFFFF; + pHash->lcLocale = 0xFFFF; + pHash->wPlatform = 0xFFFF; + pHash->dwBlockIndex = 0xFFFFFFFF; + } + } + // Notify the user + if(CompactCB != NULL) + CompactCB(lpUserData, CCB_CHECKING_FILES, ++dwFileCount, ha->pHeader->dwBlockTableSize); + + // Find the next file in the archive + bResult = SFileFindNextFile(hFind, &wf); + } + + if(hFind != NULL) + SFileFindClose(hFind); + } + + // When the filelist checking is complete, parse the hash table copy and find the + if(nError == ERROR_SUCCESS) + { + // Notify the user about checking hash table + dwFileCount = 0; + if(CompactCB != NULL) + CompactCB(lpUserData, CCB_CHECKING_HASH_TABLE, dwFileCount, ha->pHeader->dwBlockTableSize); + + for(pHash = pHashTableCopy; pHash < pHashEnd; pHash++) + { + // If there is an unresolved entry, try to detect its seed. If it fails, + // we cannot complete the work + if(pHash->dwName1 != (DWORD)-1 && pHash->dwName2 != (DWORD)-1) + { + HANDLE hFile = NULL; + DWORD dwFlags = 0; + DWORD dwSeed = 0; + + if(SFileOpenFileEx((HANDLE)ha, (char *)(DWORD_PTR)pHash->dwBlockIndex, 0, &hFile)) + { + TMPQFile * hf = (TMPQFile *)hFile; + dwFlags = hf->pBlock->dwFlags; + dwSeed = hf->dwSeed1; + SFileCloseFile(hFile); + } + + // If the file is encrypted, we have to check + // If we can apply the file decryption seed + if(dwFlags & MPQ_FILE_ENCRYPTED && dwSeed == 0) + { + nError = ERROR_CAN_NOT_COMPLETE; + break; + } + + // Remember the seed + pFileSeeds[pHash->dwBlockIndex] = dwSeed; + + // Notify the user + if(CompactCB != NULL) + CompactCB(lpUserData, CCB_CHECKING_HASH_TABLE, ++dwFileCount, ha->pHeader->dwBlockTableSize); + } + } + } + + // Delete the copy of hash table + if(pHashTableCopy != NULL) + FREEMEM(pHashTableCopy); + return nError; +} + +// Copies all file blocks into another archive. +// TODO: Test for archives > 4GB +static int CopyMpqFileBlocks( + HANDLE hFile, + TMPQArchive * ha, + TMPQBlockEx * pBlockEx, + TMPQBlock * pBlock, + DWORD dwSeed) +{ + LARGE_INTEGER FilePos = {0}; + DWORD * pdwBlockPos2 = NULL; // File block positions to be written to target file + DWORD * pdwBlockPos = NULL; // File block positions (unencrypted) + BYTE * pbBlock = NULL; // Buffer for the file block + DWORD dwTransferred; // Number of bytes transferred + DWORD dwCSize = 0; // Compressed file size + DWORD dwBytes = 0; // Number of bytes + DWORD dwSeed1 = 0; // File seed used for decryption + DWORD dwSeed2 = 0; // File seed used for encryption + DWORD nBlocks = 0; // Number of file blocks + DWORD nBlock = 0; // Currently processed file block + int nError = ERROR_SUCCESS; + + // When file length is zero, do nothing + if(pBlock->dwFSize == 0) + return ERROR_SUCCESS; + + // Calculate number of blocks in the file + if(nError == ERROR_SUCCESS) + { + nBlocks = pBlock->dwFSize / ha->dwBlockSize; + if(pBlock->dwFSize % ha->dwBlockSize) + nBlocks++; + pbBlock = ALLOCMEM(BYTE, ha->dwBlockSize); + if(pbBlock == NULL) + nError = ERROR_NOT_ENOUGH_MEMORY; + } + + // Set the position to the begin of the file within archive + if(nError == ERROR_SUCCESS) + { + FilePos.HighPart = pBlockEx->wFilePosHigh; + FilePos.LowPart = pBlock->dwFilePos; + FilePos.QuadPart += ha->MpqPos.QuadPart; + if(SetFilePointer(ha->hFile, FilePos.LowPart, &FilePos.HighPart, FILE_BEGIN) != FilePos.LowPart) + nError = GetLastError(); + } + + // Remember the position in the destination file + if(nError == ERROR_SUCCESS) + { + FilePos.HighPart = 0; + FilePos.LowPart = SetFilePointer(hFile, 0, &FilePos.HighPart, FILE_CURRENT); + } + + // Resolve decryption seeds. The 'dwSeed' parameter is the decryption + // seed for the file. + if(nError == ERROR_SUCCESS && (pBlock->dwFlags & MPQ_FILE_ENCRYPTED)) + { + dwSeed1 = dwSeed; + if(pBlock->dwFlags & MPQ_FILE_FIXSEED) + dwSeed = (dwSeed1 ^ pBlock->dwFSize) - pBlock->dwFilePos; + + dwSeed2 = dwSeed; + if(pBlock->dwFlags & MPQ_FILE_FIXSEED) + dwSeed2 = (dwSeed + (DWORD)(FilePos.QuadPart - ha->MpqPos.QuadPart)) ^ pBlock->dwFSize; + } + + // Load the file positions from the archive and save it to the target file + // (only if the file is compressed) + if(pBlock->dwFlags & MPQ_FILE_COMPRESSED) + { + // Allocate buffers + if(nError == ERROR_SUCCESS) + { + pdwBlockPos = ALLOCMEM(DWORD, nBlocks + 2); + pdwBlockPos2 = ALLOCMEM(DWORD, nBlocks + 2); + + if(pdwBlockPos == NULL || pdwBlockPos2 == NULL) + nError = ERROR_NOT_ENOUGH_MEMORY; + } + + // Load the block positions + if(nError == ERROR_SUCCESS) + { + dwBytes = (nBlocks + 1) * sizeof(DWORD); + if(pBlock->dwFlags & MPQ_FILE_HAS_EXTRA) + dwBytes += sizeof(DWORD); + + ReadFile(ha->hFile, pdwBlockPos, dwBytes, &dwTransferred, NULL); + if(dwTransferred != dwBytes) + nError = ERROR_FILE_CORRUPT; + } + + // Re-encrypt the block table positions + if(nError == ERROR_SUCCESS) + { + BSWAP_ARRAY32_UNSIGNED(pdwBlockPos, dwBytes / sizeof(DWORD)); + if(pBlock->dwFlags & MPQ_FILE_ENCRYPTED) + { + DecryptMPQBlock(pdwBlockPos, dwBytes, dwSeed1 - 1); + if(pdwBlockPos[0] != dwBytes) + nError = ERROR_FILE_CORRUPT; + + memcpy(pdwBlockPos2, pdwBlockPos, dwBytes); + EncryptMPQBlock(pdwBlockPos2, dwBytes, dwSeed2 - 1); + } + else + { + memcpy(pdwBlockPos2, pdwBlockPos, dwBytes); + } + BSWAP_ARRAY32_UNSIGNED(pdwBlockPos2, dwBytes / sizeof(DWORD)); + } + + // Write to the target file + if(nError == ERROR_SUCCESS) + { + WriteFile(hFile, pdwBlockPos2, dwBytes, &dwTransferred, NULL); + dwCSize += dwTransferred; + if(dwTransferred != dwBytes) + nError = ERROR_DISK_FULL; + } + } + + // Now we have to copy all file block. We will do it without + // recompression, because re-compression is not necessary in this case + if(nError == ERROR_SUCCESS) + { + for(nBlock = 0; nBlock < nBlocks; nBlock++) + { + // Fix: The last block must not be exactly the size of one block. + dwBytes = ha->dwBlockSize; + if(nBlock == nBlocks - 1) + { + dwBytes = pBlock->dwFSize - (ha->dwBlockSize * (nBlocks - 1)); + } + + if(pBlock->dwFlags & MPQ_FILE_COMPRESSED) + dwBytes = pdwBlockPos[nBlock+1] - pdwBlockPos[nBlock]; + + // Read the file block + ReadFile(ha->hFile, pbBlock, dwBytes, &dwTransferred, NULL); + if(dwTransferred != dwBytes) + { + nError = ERROR_FILE_CORRUPT; + break; + } + + // If necessary, re-encrypt the block + // Note: Recompression is not necessary here. Unlike encryption, + // the compression does not depend on the position of the file in MPQ. + if((pBlock->dwFlags & MPQ_FILE_ENCRYPTED) && dwSeed1 != dwSeed2) + { + BSWAP_ARRAY32_UNSIGNED((DWORD *)pbBlock, dwBytes/sizeof(DWORD)); + DecryptMPQBlock((DWORD *)pbBlock, dwBytes, dwSeed1 + nBlock); + EncryptMPQBlock((DWORD *)pbBlock, dwBytes, dwSeed2 + nBlock); + BSWAP_ARRAY32_UNSIGNED((DWORD *)pbBlock, dwBytes/sizeof(DWORD)); + } + + // Now write the block back to the file + WriteFile(hFile, pbBlock, dwBytes, &dwTransferred, NULL); + dwCSize += dwTransferred; + if(dwTransferred != dwBytes) + { + nError = ERROR_DISK_FULL; + break; + } + } + } + + // Copy the file extras, if any + // These extras does not seem to be encrypted, and their purpose is unknown + if(nError == ERROR_SUCCESS && (pBlock->dwFlags & MPQ_FILE_HAS_EXTRA)) + { + dwBytes = pdwBlockPos[nBlocks + 1] - pdwBlockPos[nBlocks]; + if(dwBytes != 0) + { + ReadFile(ha->hFile, pbBlock, dwBytes, &dwTransferred, NULL); + if(dwTransferred == dwBytes) + { + WriteFile(hFile, pbBlock, dwBytes, &dwTransferred, NULL); + dwCSize += dwTransferred; + if(dwTransferred != dwBytes) + nError = ERROR_DISK_FULL; + } + else + { + nError = ERROR_FILE_CORRUPT; + } + } + } + + // Update file position in the block table + if(nError == ERROR_SUCCESS) + { + // At this point, number of bytes written should be exactly + // the same like the compressed file size. If it isn't, there's something wrong + // (maybe new archive version ?) + assert(dwCSize == pBlock->dwCSize); + + // Update file pos in the block table + FilePos.QuadPart -= ha->MpqPos.QuadPart; + pBlockEx->wFilePosHigh = (USHORT)FilePos.HighPart; + pBlock->dwFilePos = FilePos.LowPart; + } + + // Cleanup and return + if(pdwBlockPos2 != NULL) + FREEMEM(pdwBlockPos2); + if(pdwBlockPos != NULL) + FREEMEM(pdwBlockPos); + if(pbBlock != NULL) + FREEMEM(pbBlock); + return nError; +} + + +static int CopyNonMpqData( + HANDLE hSrcFile, + HANDLE hTrgFile, + LARGE_INTEGER & DataSizeToCopy) +{ + LARGE_INTEGER DataSize = DataSizeToCopy; + DWORD dwTransferred; + DWORD dwToRead; + char DataBuffer[0x1000]; + int nError = ERROR_SUCCESS; + + while(DataSize.QuadPart > 0) + { + // Get the proper size of data + dwToRead = sizeof(DataBuffer); + if(DataSize.HighPart == 0 && DataSize.LowPart < dwToRead) + dwToRead = DataSize.LowPart; + + // Read the source file + ReadFile(hSrcFile, DataBuffer, dwToRead, &dwTransferred, NULL); + if(dwTransferred != dwToRead) + { + nError = ERROR_CAN_NOT_COMPLETE; + break; + } + + // Write to the target file + WriteFile(hTrgFile, DataBuffer, dwToRead, &dwTransferred, NULL); + if(dwTransferred != dwToRead) + { + nError = ERROR_DISK_FULL; + break; + } + + // Decrement the number of data to be copied + DataSize.QuadPart -= dwTransferred; + } + + return ERROR_SUCCESS; +} + +// TODO: Test for archives > 4GB +static int CopyMpqFiles(HANDLE hFile, TMPQArchive * ha, DWORD * pFileSeeds) +{ + TMPQBlockEx * pBlockEx; + TMPQBlock * pBlock; + DWORD dwSeed1; + DWORD dwIndex; + int nError = ERROR_SUCCESS; + + // Walk through all files and write them to the destination MPQ archive + for(dwIndex = 0; dwIndex < ha->pHeader->dwBlockTableSize; dwIndex++) + { + pBlockEx = ha->pExtBlockTable + dwIndex; + pBlock = ha->pBlockTable + dwIndex; + dwSeed1 = pFileSeeds[dwIndex]; + + // Notify the caller about work + if(CompactCB != NULL) + CompactCB(lpUserData, CCB_COMPACTING_FILES, dwIndex, ha->pHeader->dwBlockTableSize); + +// if(dwIndex == 0x1B9) +// DebugBreak(); + + // Copy all the file blocks + // Debug: Break at (dwIndex == 5973) + if(pBlock->dwFlags & MPQ_FILE_EXISTS) + { + nError = CopyMpqFileBlocks(hFile, ha, pBlockEx, pBlock, dwSeed1); + if(nError != ERROR_SUCCESS) + break; + } + } + + // Cleanup and exit + return nError; +} + + +/*****************************************************************************/ +/* Public functions */ +/*****************************************************************************/ + +BOOL WINAPI SFileSetCompactCallback(HANDLE /* hMPQ */, COMPACTCB aCompactCB, void * lpData) +{ + CompactCB = aCompactCB; + lpUserData = lpData; + return TRUE; +} + +//----------------------------------------------------------------------------- +// Archive compacting (incomplete) + +// TODO: Test for archives > 4GB +BOOL WINAPI SFileCompactArchive(HANDLE hMPQ, const char * szListFile, BOOL /* bReserved */) +{ + TMPQArchive * ha = (TMPQArchive *)hMPQ; + HANDLE hFile = INVALID_HANDLE_VALUE; + DWORD * pFileSeeds = NULL; + char szTempFile[MAX_PATH] = ""; + char * szTemp = NULL; + DWORD dwTransferred; + int nError = ERROR_SUCCESS; + + // Test the valid parameters + if(!IsValidMpqHandle(ha)) + nError = ERROR_INVALID_PARAMETER; + + // Create the table with file seeds + if(nError == ERROR_SUCCESS) + { + if((pFileSeeds = ALLOCMEM(DWORD, ha->pHeader->dwBlockTableSize)) != NULL) + memset(pFileSeeds, 0, sizeof(DWORD) * ha->pHeader->dwBlockTableSize); + else + nError = ERROR_NOT_ENOUGH_MEMORY; + } + + // First of all, we have to check of we are able to decrypt all files. + // If not, sorry, but the archive cannot be compacted. + if(nError == ERROR_SUCCESS) + nError = CheckIfAllFilesKnown(ha, szListFile, pFileSeeds); + + // Get the temporary file name and create it + if(nError == ERROR_SUCCESS) + { + if(CompactCB != NULL) + CompactCB(lpUserData, CCB_COPYING_NON_MPQ_DATA, 0, 0); + + strcpy(szTempFile, ha->szFileName); + if((szTemp = strrchr(szTempFile, '.')) != NULL) + strcpy(szTemp + 1, "mp_"); + else + strcat(szTempFile, "_"); + + hFile = CreateFile(szTempFile, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL); + if(hFile == INVALID_HANDLE_VALUE) + nError = GetLastError(); + } + + // Write the data before MPQ header (if any) + if(nError == ERROR_SUCCESS && ha->MpqPos.QuadPart > 0) + { + SetFilePointer(ha->hFile, 0, NULL, FILE_BEGIN); + if(ha->pShunt != NULL) + nError = CopyNonMpqData(ha->hFile, hFile, ha->ShuntPos); + else + nError = CopyNonMpqData(ha->hFile, hFile, ha->MpqPos); + } + + // Write the MPQ shunt (if any) + if(nError == ERROR_SUCCESS && ha->pShunt != NULL) + { + BSWAP_TMPQSHUNT(ha->pShunt); + WriteFile(hFile, ha->pShunt, sizeof(TMPQShunt), &dwTransferred, NULL); + BSWAP_TMPQSHUNT(ha->pShunt); + + if(dwTransferred != sizeof(TMPQShunt)) + nError = ERROR_DISK_FULL; + } + + // Write the data between MPQ shunt and the MPQ header (if any) + if(nError == ERROR_SUCCESS && ha->pShunt != NULL) + { + LARGE_INTEGER BytesToCopy; + + BytesToCopy.QuadPart = ha->MpqPos.QuadPart - (ha->ShuntPos.QuadPart + sizeof(TMPQShunt)); + nError = CopyNonMpqData(ha->hFile, hFile, BytesToCopy); + } + + // Write the MPQ header + if(nError == ERROR_SUCCESS) + { + BSWAP_TMPQHEADER(ha->pHeader); + WriteFile(hFile, ha->pHeader, ha->pHeader->dwHeaderSize, &dwTransferred, NULL); + BSWAP_TMPQHEADER(ha->pHeader); + if(dwTransferred != ha->pHeader->dwHeaderSize) + nError = ERROR_DISK_FULL; + } + + // Write the data between the header and between the first file + // For this, we have to determine where the first file begins + if(nError == ERROR_SUCCESS) + { + LARGE_INTEGER FirstFilePos; + LARGE_INTEGER TempPos; + TMPQBlockEx * pBlockEx = ha->pExtBlockTable; + TMPQBlock * pBlockEnd = ha->pBlockTable + ha->pHeader->dwBlockTableSize; + TMPQBlock * pBlock = ha->pBlockTable; + + // Maximum file position + FirstFilePos.HighPart = 0x7FFFFFFF; + FirstFilePos.LowPart = 0xFFFFFFFF; + + // Find the block with the least position in the MPQ + while(pBlock < pBlockEnd) + { + TempPos.HighPart = pBlockEx->wFilePosHigh; + TempPos.LowPart = pBlock->dwFilePos; + if(TempPos.QuadPart < FirstFilePos.QuadPart) + FirstFilePos = TempPos; + + pBlockEx++; + pBlock++; + } + + // Set the position in the source file right after the file header + TempPos.QuadPart = ha->MpqPos.QuadPart + ha->pHeader->dwHeaderSize; + SetFilePointer(ha->hFile, TempPos.LowPart, &TempPos.HighPart, FILE_BEGIN); + + // Get the number of bytes to copy + FirstFilePos.QuadPart -= ha->pHeader->dwHeaderSize; + nError = CopyNonMpqData(ha->hFile, hFile, FirstFilePos); + } + + // Now write all file blocks. + if(nError == ERROR_SUCCESS) + nError = CopyMpqFiles(hFile, ha, pFileSeeds); + + // Now we need to update the tables positions + // (but only if the tables are at the end of the file) + if(nError == ERROR_SUCCESS) + { + LARGE_INTEGER RelativePos; + LARGE_INTEGER FilePos = {0}; + + // Set the hash table position + FilePos.LowPart = SetFilePointer(hFile, 0, &FilePos.HighPart, FILE_CURRENT); + RelativePos.QuadPart = FilePos.QuadPart - ha->MpqPos.QuadPart; + ha->pHeader->wHashTablePosHigh = (USHORT)RelativePos.HighPart; + ha->pHeader->dwHashTablePos = RelativePos.LowPart; + ha->HashTablePos = FilePos; + + // Set the block table position + RelativePos.QuadPart += ha->pHeader->dwHashTableSize * sizeof(TMPQHash); + FilePos.QuadPart += ha->pHeader->dwHashTableSize * sizeof(TMPQHash); + ha->pHeader->wBlockTablePosHigh = (USHORT)RelativePos.HighPart; + ha->pHeader->dwBlockTablePos = RelativePos.LowPart; + ha->BlockTablePos = FilePos; + + // Set the extended block table position + RelativePos.QuadPart += ha->pHeader->dwBlockTableSize * sizeof(TMPQBlock); + FilePos.QuadPart += ha->pHeader->dwBlockTableSize * sizeof(TMPQBlock); + if(ha->ExtBlockTablePos.QuadPart != 0) + { + ha->pHeader->ExtBlockTablePos = RelativePos; + ha->ExtBlockTablePos = FilePos; + + RelativePos.QuadPart += ha->pHeader->dwBlockTableSize * sizeof(TMPQBlockEx); + FilePos.QuadPart += ha->pHeader->dwBlockTableSize * sizeof(TMPQBlockEx); + } + + // Set the archive size + ha->pHeader->dwArchiveSize = RelativePos.LowPart; + ha->MpqSize = RelativePos; + } + + // If succeeded, update the tables in the file + if(nError == ERROR_SUCCESS) + { + CloseHandle(ha->hFile); + ha->FilePointer.QuadPart = 0; + ha->hFile = hFile; + hFile = INVALID_HANDLE_VALUE; + nError = SaveMPQTables(ha); + } + + // If all succeeded, switch the archives + if(nError == ERROR_SUCCESS) + { + if(CompactCB != NULL) + CompactCB(lpUserData, CCB_CLOSING_ARCHIVE, 0, 0); + + if(!DeleteFile(ha->szFileName) || // Delete the old archive + !CloseHandle(ha->hFile) || // Close the new archive + !MoveFile(szTempFile, ha->szFileName)) // Rename the temporary archive + nError = GetLastError(); + } + + // Now open the freshly renamed archive file + if(nError == ERROR_SUCCESS) + { + ha->hFile = CreateFile(ha->szFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if(ha->hFile == INVALID_HANDLE_VALUE) + nError = GetLastError(); + } + + // Invalidate the positions of the archive + if(nError == ERROR_SUCCESS) + { + ha->FilePointer.QuadPart = 0; + ha->pLastFile = NULL; + ha->dwBlockPos = 0; + ha->dwBuffPos = 0; + } + + // Cleanup and return + if(hFile != INVALID_HANDLE_VALUE) + CloseHandle(hFile); + if(pFileSeeds != NULL) + FREEMEM(pFileSeeds); + if(nError != ERROR_SUCCESS) + SetLastError(nError); + DeleteFile(szTempFile); + CompactCB = NULL; + return (nError == ERROR_SUCCESS); +} diff --git a/contrib/vmap_extractor_v2/stormlib/SFileCreateArchiveEx.cpp b/contrib/vmap_extractor_v2/stormlib/SFileCreateArchiveEx.cpp new file mode 100644 index 00000000000..2410920fc93 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/SFileCreateArchiveEx.cpp @@ -0,0 +1,530 @@ +/*****************************************************************************/ +/* SFileCreateArchiveEx.cpp Copyright (c) Ladislav Zezula 2003 */ +/*---------------------------------------------------------------------------*/ +/* MPQ Editing functions */ +/*---------------------------------------------------------------------------*/ +/* Date Ver Who Comment */ +/* -------- ---- --- ------- */ +/* 24.03.03 1.00 Lad Splitted from SFileOpenArchive.cpp */ +/*****************************************************************************/ + +#define __STORMLIB_SELF__ +#include "StormLib.h" +#include "SCommon.h" + +//----------------------------------------------------------------------------- +// Defines + +#define DEFAULT_BLOCK_SIZE 3 // Default size of the block + +//----------------------------------------------------------------------------- +// Local tables + +static DWORD PowersOfTwo[] = +{ + 0x0000002, 0x0000004, 0x0000008, + 0x0000010, 0x0000020, 0x0000040, 0x0000080, + 0x0000100, 0x0000200, 0x0000400, 0x0000800, + 0x0001000, 0x0002000, 0x0004000, 0x0008000, + 0x0010000, 0x0020000, 0x0040000, 0x0080000, + 0x0000000 +}; + +/*****************************************************************************/ +/* Public functions */ +/*****************************************************************************/ + +//----------------------------------------------------------------------------- +// Opens or creates a (new) MPQ archive. +// +// szMpqName - Name of the archive to be created. +// +// dwCreationDisposition: +// +// Value Archive exists Archive doesn't exist +// ---------- --------------------- --------------------- +// CREATE_NEW Fails Creates new archive +// CREATE_ALWAYS Overwrites existing Creates new archive +// OPEN_EXISTING Opens the archive Fails +// OPEN_ALWAYS Opens the archive Creates new archive +// +// The above mentioned values can be combined with the following flags: +// +// MPQ_CREATE_ARCHIVE_V1 - Creates MPQ archive version 1 +// MPQ_CREATE_ARCHIVE_V2 - Creates MPQ archive version 2 +// +// dwHashTableSize - Size of the hash table (only if creating a new archive). +// Must be between 2^4 (= 16) and 2^18 (= 262 144) +// +// phMpq - Receives handle to the archive +// + +// TODO: Test for archives > 4GB +BOOL WINAPI SFileCreateArchiveEx(const char * szMpqName, DWORD dwCreationDisposition, DWORD dwHashTableSize, HANDLE * phMPQ) +{ + LARGE_INTEGER MpqPos = {0}; // Position of MPQ header in the file + TMPQArchive * ha = NULL; // MPQ archive handle + HANDLE hFile = INVALID_HANDLE_VALUE; // File handle + DWORD dwTransferred = 0; // Number of bytes written into the archive + USHORT wFormatVersion; + BOOL bFileExists = FALSE; + int nIndex = 0; + int nError = ERROR_SUCCESS; + + // Pre-initialize the result value + if(phMPQ != NULL) + *phMPQ = NULL; + + // Check the parameters, if they are valid + if(szMpqName == NULL || *szMpqName == 0 || phMPQ == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + // Check the value of dwCreationDisposition against file existence + bFileExists = (GetFileAttributes(szMpqName) != 0xFFFFFFFF); + + // Extract format version from the "dwCreationDisposition" + wFormatVersion = (USHORT)(dwCreationDisposition >> 0x10); + dwCreationDisposition &= 0x0000FFFF; + + // If the file exists and open required, do it. + if(bFileExists && (dwCreationDisposition == OPEN_EXISTING || dwCreationDisposition == OPEN_ALWAYS)) + { + // Try to open the archive normal way. If it fails, it means that + // the file exist, but it is not a MPQ archive. + if(SFileOpenArchiveEx(szMpqName, 0, 0, phMPQ, GENERIC_READ | GENERIC_WRITE)) + return TRUE; + } + + // Two error cases + if(dwCreationDisposition == CREATE_NEW && bFileExists) + { + SetLastError(ERROR_ALREADY_EXISTS); + return FALSE; + } + if(dwCreationDisposition == OPEN_EXISTING && bFileExists == FALSE) + { + SetLastError(ERROR_FILE_NOT_FOUND); + return FALSE; + } + + // At this point, we have to create the archive. If the file exists, + // we will convert it to MPQ archive. + // Check the value of hash table size. It has to be a power of two + // and must be between HASH_TABLE_SIZE_MIN and HASH_TABLE_SIZE_MAX + if(dwHashTableSize < HASH_TABLE_SIZE_MIN) + dwHashTableSize = HASH_TABLE_SIZE_MIN; + if(dwHashTableSize > HASH_TABLE_SIZE_MAX) + dwHashTableSize = HASH_TABLE_SIZE_MAX; + + // Round the hash table size up to the nearest power of two + for(nIndex = 0; PowersOfTwo[nIndex] != 0; nIndex++) + { + if(dwHashTableSize <= PowersOfTwo[nIndex]) + { + dwHashTableSize = PowersOfTwo[nIndex]; + break; + } + } + + // Prepare the buffer for decryption engine + if(nError == ERROR_SUCCESS) + nError = PrepareStormBuffer(); + + // Get the position where the MPQ header will begin. + if(nError == ERROR_SUCCESS) + { + hFile = CreateFile(szMpqName, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ, + NULL, + dwCreationDisposition, + 0, + NULL); + if(hFile == INVALID_HANDLE_VALUE) + nError = GetLastError(); + } + + // Retrieve the file size and round it up to 0x200 bytes + if(nError == ERROR_SUCCESS) + { + MpqPos.LowPart = GetFileSize(hFile, (LPDWORD)&MpqPos.HighPart); + MpqPos.QuadPart += 0x1FF; + MpqPos.LowPart &= 0xFFFFFE00; + + if(wFormatVersion == MPQ_FORMAT_VERSION_1 && MpqPos.HighPart != 0) + nError = ERROR_DISK_FULL; + if(wFormatVersion == MPQ_FORMAT_VERSION_2 && MpqPos.HighPart > 0x0000FFFF) + nError = ERROR_DISK_FULL; + } + + // Move to the end of the file (i.e. begin of the MPQ) + if(nError == ERROR_SUCCESS) + { + if(SetFilePointer(hFile, MpqPos.LowPart, &MpqPos.HighPart, FILE_BEGIN) == 0xFFFFFFFF) + nError = GetLastError(); + } + + // Set the new end of the file to the MPQ header position + if(nError == ERROR_SUCCESS) + { + if(!SetEndOfFile(hFile)) + nError = GetLastError(); + } + + // Create the archive handle + if(nError == ERROR_SUCCESS) + { + if((ha = ALLOCMEM(TMPQArchive, 1)) == NULL) + nError = ERROR_NOT_ENOUGH_MEMORY; + } + + // Fill the MPQ archive handle structure and create the header, + // block buffer, hash table and block table + if(nError == ERROR_SUCCESS) + { + memset(ha, 0, sizeof(TMPQArchive)); + strcpy(ha->szFileName, szMpqName); + ha->hFile = hFile; + ha->dwBlockSize = 0x200 << DEFAULT_BLOCK_SIZE; + ha->MpqPos = MpqPos; + ha->FilePointer = MpqPos; + ha->pHeader = &ha->Header; + ha->pHashTable = ALLOCMEM(TMPQHash, dwHashTableSize); + ha->pBlockTable = ALLOCMEM(TMPQBlock, dwHashTableSize); + ha->pExtBlockTable = ALLOCMEM(TMPQBlockEx, dwHashTableSize); + ha->pbBlockBuffer = ALLOCMEM(BYTE, ha->dwBlockSize); + ha->pListFile = NULL; + ha->dwFlags |= MPQ_FLAG_CHANGED; + + if(!ha->pHashTable || !ha->pBlockTable || !ha->pExtBlockTable || !ha->pbBlockBuffer) + nError = GetLastError(); + hFile = INVALID_HANDLE_VALUE; + } + + // Fill the MPQ header and all buffers + if(nError == ERROR_SUCCESS) + { + LARGE_INTEGER TempPos; + TMPQHeader2 * pHeader = ha->pHeader; + DWORD dwHeaderSize = (wFormatVersion == MPQ_FORMAT_VERSION_2) ? sizeof(TMPQHeader2) : sizeof(TMPQHeader); + + memset(pHeader, 0, sizeof(TMPQHeader2)); + pHeader->dwID = ID_MPQ; + pHeader->dwHeaderSize = dwHeaderSize; + pHeader->dwArchiveSize = pHeader->dwHeaderSize + dwHashTableSize * sizeof(TMPQHash); + pHeader->wFormatVersion = wFormatVersion; + pHeader->wBlockSize = 3; // 0x1000 bytes per block + pHeader->dwHashTableSize = dwHashTableSize; + + // Set proper hash table positions + ha->HashTablePos.QuadPart = ha->MpqPos.QuadPart + pHeader->dwHeaderSize; + ha->pHeader->dwHashTablePos = pHeader->dwHeaderSize; + ha->pHeader->wHashTablePosHigh = 0; + + // Set proper block table positions + ha->BlockTablePos.QuadPart = ha->HashTablePos.QuadPart + + (ha->pHeader->dwHashTableSize * sizeof(TMPQHash)); + TempPos.QuadPart = ha->BlockTablePos.QuadPart - ha->MpqPos.QuadPart; + ha->pHeader->dwBlockTablePos = TempPos.LowPart; + ha->pHeader->wBlockTablePosHigh = (USHORT)TempPos.HighPart; + + // For now, we set extended block table positioon top zero unless we add enough + // files to cause the archive size exceed 4 GB + ha->ExtBlockTablePos.QuadPart = 0; + + // Clear all tables + memset(ha->pBlockTable, 0, sizeof(TMPQBlock) * dwHashTableSize); + memset(ha->pExtBlockTable, 0, sizeof(TMPQBlockEx) * dwHashTableSize); + memset(ha->pHashTable, 0xFF, sizeof(TMPQHash) * dwHashTableSize); + } + + // Write the MPQ header to the file + if(nError == ERROR_SUCCESS) + { + DWORD dwHeaderSize = ha->pHeader->dwHeaderSize; + + BSWAP_TMPQHEADER(ha->pHeader); + WriteFile(ha->hFile, ha->pHeader, dwHeaderSize, &dwTransferred, NULL); + BSWAP_TMPQHEADER(ha->pHeader); + + if(dwTransferred != ha->pHeader->dwHeaderSize) + nError = ERROR_DISK_FULL; + + ha->FilePointer.QuadPart = ha->MpqPos.QuadPart + dwTransferred; + ha->MpqSize.QuadPart += dwTransferred; + } + + // Create the internal listfile + if(nError == ERROR_SUCCESS) + nError = SListFileCreateListFile(ha); + + // Try to add the internal listfile + if(nError == ERROR_SUCCESS) + SFileAddListFile((HANDLE)ha, NULL); + + // Cleanup : If an error, delete all buffers and return + if(nError != ERROR_SUCCESS) + { + FreeMPQArchive(ha); + if(hFile != INVALID_HANDLE_VALUE) + CloseHandle(hFile); + SetLastError(nError); + } + + // Return the values + *phMPQ = (HANDLE)ha; + return (nError == ERROR_SUCCESS); +} + +//----------------------------------------------------------------------------- +// Changes locale ID of a file + +// TODO: Test for archives > 4GB +BOOL WINAPI SFileSetFileLocale(HANDLE hFile, LCID lcNewLocale) +{ + TMPQFile * hf = (TMPQFile *)hFile; + + // Invalid handle => do nothing + if(IsValidFileHandle(hf) == FALSE || IsValidMpqHandle(hf->ha) == FALSE) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + // If the file has not been open for writing, do nothing. + if(hf->ha->pListFile == NULL) + return ERROR_ACCESS_DENIED; + + hf->pHash->lcLocale = (USHORT)lcNewLocale; + hf->ha->dwFlags |= MPQ_FLAG_CHANGED; + return TRUE; +} + +//----------------------------------------------------------------------------- +// Adds a file into the archive + +// TODO: Test for archives > 4GB +BOOL WINAPI SFileAddFileEx(HANDLE hMPQ, const char * szFileName, const char * szArchivedName, DWORD dwFlags, DWORD dwQuality, int nFileType) +{ + TMPQArchive * ha = (TMPQArchive *)hMPQ; + HANDLE hFile = INVALID_HANDLE_VALUE; + BOOL bReplaced = FALSE; // TRUE if replacing file in the archive + int nError = ERROR_SUCCESS; + + if(nError == ERROR_SUCCESS) + { + // Check valid parameters + if(IsValidMpqHandle(ha) == FALSE || szFileName == NULL || *szFileName == 0 || szArchivedName == NULL || *szArchivedName == 0) + nError = ERROR_INVALID_PARAMETER; + + // Check the values of dwFlags + if((dwFlags & MPQ_FILE_COMPRESS_PKWARE) && (dwFlags & MPQ_FILE_COMPRESS_MULTI)) + nError = ERROR_INVALID_PARAMETER; + } + + // If anyone is trying to add listfile, and the archive already has a listfile, + // deny the operation, but return success. + if(nError == ERROR_SUCCESS) + { + if(ha->pListFile != NULL && !_stricmp(szFileName, LISTFILE_NAME)) + return ERROR_SUCCESS; + } + + // Open added file + if(nError == ERROR_SUCCESS) + { + hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, NULL); + if(hFile == INVALID_HANDLE_VALUE) + nError = GetLastError(); + } + + if(nError == ERROR_SUCCESS) + nError = AddFileToArchive(ha, hFile, szArchivedName, dwFlags, dwQuality, nFileType, &bReplaced); + + // Add the file into listfile also + if(nError == ERROR_SUCCESS && bReplaced == FALSE) + nError = SListFileAddNode(ha, szArchivedName); + + // Cleanup and exit + if(hFile != INVALID_HANDLE_VALUE) + CloseHandle(hFile); + if(nError != ERROR_SUCCESS) + SetLastError(nError); + return (nError == ERROR_SUCCESS); +} + +// Adds a data file into the archive +// TODO: Test for archives > 4GB +BOOL WINAPI SFileAddFile(HANDLE hMPQ, const char * szFileName, const char * szArchivedName, DWORD dwFlags) +{ + return SFileAddFileEx(hMPQ, szFileName, szArchivedName, dwFlags, 0, SFILE_TYPE_DATA); +} + +// Adds a WAVE file into the archive +// TODO: Test for archives > 4GB +BOOL WINAPI SFileAddWave(HANDLE hMPQ, const char * szFileName, const char * szArchivedName, DWORD dwFlags, DWORD dwQuality) +{ + return SFileAddFileEx(hMPQ, szFileName, szArchivedName, dwFlags, dwQuality, SFILE_TYPE_WAVE); +} + +//----------------------------------------------------------------------------- +// BOOL SFileRemoveFile(HANDLE hMPQ, char * szFileName) +// +// This function removes a file from the archive. The file content +// remains there, only the entries in the hash table and in the block +// table are updated. + +// TODO: Test for archives > 4GB +BOOL WINAPI SFileRemoveFile(HANDLE hMPQ, const char * szFileName, DWORD dwSearchScope) +{ + TMPQArchive * ha = (TMPQArchive *)hMPQ; + TMPQBlockEx * pBlockEx = NULL; // Block entry of deleted file + TMPQBlock * pBlock = NULL; // Block entry of deleted file + TMPQHash * pHash = NULL; // Hash entry of deleted file + DWORD dwBlockIndex = 0; + int nError = ERROR_SUCCESS; + + // Check the parameters + if(nError == ERROR_SUCCESS) + { + if(IsValidMpqHandle(ha) == FALSE) + nError = ERROR_INVALID_PARAMETER; + if(dwSearchScope != SFILE_OPEN_BY_INDEX && *szFileName == 0) + nError = ERROR_INVALID_PARAMETER; + } + + // Do not allow to remove listfile + if(nError == ERROR_SUCCESS) + { + if(dwSearchScope != SFILE_OPEN_BY_INDEX && !_stricmp(szFileName, LISTFILE_NAME)) + nError = ERROR_ACCESS_DENIED; + } + + // Get hash entry belonging to this file + if(nError == ERROR_SUCCESS) + { + if((pHash = GetHashEntryEx(ha, (char *)szFileName, lcLocale)) == NULL) + nError = ERROR_FILE_NOT_FOUND; + } + + // If index was not found, or is greater than number of files, exit. + if(nError == ERROR_SUCCESS) + { + if((dwBlockIndex = pHash->dwBlockIndex) > ha->pHeader->dwBlockTableSize) + nError = ERROR_FILE_NOT_FOUND; + } + + // Get block and test if the file is not already deleted + if(nError == ERROR_SUCCESS) + { + pBlockEx = ha->pExtBlockTable + dwBlockIndex; + pBlock = ha->pBlockTable + dwBlockIndex; + if((pBlock->dwFlags & MPQ_FILE_EXISTS) == 0) + nError = ERROR_FILE_NOT_FOUND; + } + + // Now invalidate the block entry and the hash entry. Do not make any + // relocations and file copying, use SFileCompactArchive for it. + if(nError == ERROR_SUCCESS) + { + pBlockEx->wFilePosHigh = 0; + pBlock->dwFilePos = 0; + pBlock->dwFSize = 0; + pBlock->dwCSize = 0; + pBlock->dwFlags = 0; + pHash->dwName1 = 0xFFFFFFFF; + pHash->dwName2 = 0xFFFFFFFF; + pHash->lcLocale = 0xFFFF; + pHash->wPlatform = 0xFFFF; + pHash->dwBlockIndex = HASH_ENTRY_DELETED; + + // Update MPQ archive + ha->dwFlags |= MPQ_FLAG_CHANGED; + } + + // Remove the file from the list file + if(nError == ERROR_SUCCESS && lcLocale == LANG_NEUTRAL) + nError = SListFileRemoveNode(ha, szFileName); + + // Resolve error and exit + if(nError != ERROR_SUCCESS) + SetLastError(nError); + return (nError == ERROR_SUCCESS); +} + +// Renames the file within the archive. +// TODO: Test for archives > 4GB +BOOL WINAPI SFileRenameFile(HANDLE hMPQ, const char * szFileName, const char * szNewFileName) +{ + TMPQArchive * ha = (TMPQArchive *)hMPQ; + TMPQHash * pOldHash = NULL; // Hash entry for the original file + TMPQHash * pNewHash = NULL; // Hash entry for the renamed file + DWORD dwBlockIndex = 0; + int nError = ERROR_SUCCESS; + + // Test the valid parameters + if(nError == ERROR_SUCCESS) + { + if(hMPQ == NULL || szNewFileName == NULL || *szNewFileName == 0) + nError = ERROR_INVALID_PARAMETER; + if(szFileName == NULL || *szFileName == 0) + nError = ERROR_INVALID_PARAMETER; + } + + // Do not allow to rename listfile + if(nError == ERROR_SUCCESS) + { + if(!_stricmp(szFileName, LISTFILE_NAME)) + nError = ERROR_ACCESS_DENIED; + } + + // Test if the file already exists in the archive + if(nError == ERROR_SUCCESS) + { + if((pNewHash = GetHashEntryEx(ha, szNewFileName, lcLocale)) != NULL) + nError = ERROR_ALREADY_EXISTS; + } + + // Get the hash table entry for the original file + if(nError == ERROR_SUCCESS) + { + if((pOldHash = GetHashEntryEx(ha, szFileName, lcLocale)) == NULL) + nError = ERROR_FILE_NOT_FOUND; + } + + // Get the hash table entry for the renamed file + if(nError == ERROR_SUCCESS) + { + // Save block table index and remove the hash table entry + dwBlockIndex = pOldHash->dwBlockIndex; + pOldHash->dwName1 = 0xFFFFFFFF; + pOldHash->dwName2 = 0xFFFFFFFF; + pOldHash->lcLocale = 0xFFFF; + pOldHash->wPlatform = 0xFFFF; + pOldHash->dwBlockIndex = HASH_ENTRY_DELETED; + + if((pNewHash = FindFreeHashEntry(ha, szNewFileName)) == NULL) + nError = ERROR_CAN_NOT_COMPLETE; + } + + // Save the block index and clear the hash entry + if(nError == ERROR_SUCCESS) + { + // Copy the block table index + pNewHash->dwBlockIndex = dwBlockIndex; + ha->dwFlags |= MPQ_FLAG_CHANGED; + } + + // Rename the file in the list file + if(nError == ERROR_SUCCESS) + nError = SListFileRenameNode(ha, szFileName, szNewFileName); + + // Resolve error and return + if(nError != ERROR_SUCCESS) + SetLastError(nError); + return (nError == ERROR_SUCCESS); +} + diff --git a/contrib/vmap_extractor_v2/stormlib/SFileExtractFile.cpp b/contrib/vmap_extractor_v2/stormlib/SFileExtractFile.cpp new file mode 100644 index 00000000000..7f16cde0171 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/SFileExtractFile.cpp @@ -0,0 +1,63 @@ +/*****************************************************************************/ +/* SFileExtractFile.cpp Copyright (c) Ladislav Zezula 2003 */ +/*---------------------------------------------------------------------------*/ +/* Simple extracting utility */ +/*---------------------------------------------------------------------------*/ +/* Date Ver Who Comment */ +/* -------- ---- --- ------- */ +/* 20.06.03 1.00 Lad The first version of SFileExtractFile.cpp */ +/*****************************************************************************/ + +#define __STORMLIB_SELF__ +#include "StormLib.h" +#include "SCommon.h" + +// TODO: Test for archives > 4GB +BOOL WINAPI SFileExtractFile(HANDLE hMpq, const char * szToExtract, const char * szExtracted) +{ + HANDLE hLocalFile = INVALID_HANDLE_VALUE; + HANDLE hMpqFile = NULL; + int nError = ERROR_SUCCESS; + + // Create the local file + if(nError == ERROR_SUCCESS) + { + hLocalFile = CreateFile(szExtracted, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL); + if(hLocalFile == INVALID_HANDLE_VALUE) + nError = GetLastError(); + } + + // Open the MPQ file + if(nError == ERROR_SUCCESS) + { + if(!SFileOpenFileEx(hMpq, szToExtract, 0, &hMpqFile)) + nError = GetLastError(); + } + + // Copy the file's content + if(nError == ERROR_SUCCESS) + { + char szBuffer[0x1000]; + DWORD dwTransferred = 1; + + while(dwTransferred > 0) + { + SFileReadFile(hMpqFile, szBuffer, sizeof(szBuffer), &dwTransferred, NULL); + if(dwTransferred == 0) + break; + + WriteFile(hLocalFile, szBuffer, dwTransferred, &dwTransferred, NULL); + if(dwTransferred == 0) + break; + } + } + + // Close the files + if(hMpqFile != NULL) + SFileCloseFile(hMpqFile); + if(hLocalFile != INVALID_HANDLE_VALUE) + CloseHandle(hLocalFile); + if(nError != ERROR_SUCCESS) + SetLastError(nError); + return (BOOL)(nError == ERROR_SUCCESS); +} diff --git a/contrib/vmap_extractor_v2/stormlib/SFileFindFile.cpp b/contrib/vmap_extractor_v2/stormlib/SFileFindFile.cpp new file mode 100644 index 00000000000..41dbeba900c --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/SFileFindFile.cpp @@ -0,0 +1,291 @@ +/*****************************************************************************/ +/* SFileFindFile.cpp Copyright (c) Ladislav Zezula 2003 */ +/*---------------------------------------------------------------------------*/ +/* A module for file searching within MPQs */ +/*---------------------------------------------------------------------------*/ +/* Date Ver Who Comment */ +/* -------- ---- --- ------- */ +/* 25.03.03 1.00 Lad The first version of SFileFindFile.cpp */ +/*****************************************************************************/ + +#define __STORMLIB_SELF__ +#include "StormLib.h" +#include "SCommon.h" + +//----------------------------------------------------------------------------- +// Defines + +#define LISTFILE_CACHE_SIZE 0x1000 + +//----------------------------------------------------------------------------- +// Local functions + +static BOOL IsValidSearchHandle(TMPQSearch * hs) +{ + if(hs == NULL || IsBadReadPtr(hs, sizeof(TMPQSearch))) + return FALSE; + + if(!IsValidMpqHandle(hs->ha)) + return FALSE; + + return TRUE; +} + +// This function compares a string with a wildcard search string. +// returns TRUE, when the string matches with the wildcard. +BOOL CheckWildCard(const char * szString, const char * szWildCard) +{ + char * szTemp; // Temporary helper pointer + int nResult = 0; // For memcmp return values + int nMustNotMatch = 0; // Number of following chars int szString, + // which must not match with szWildCard + int nMustMatch = 0; // Number of the following characters, + // which must match + + // When the string is empty, it does not match with every wildcard + if(*szString == 0) + return FALSE; + + // When the mask is empty, it matches to every wildcard + if(szWildCard == NULL || *szWildCard == 0) + return FALSE; + + // Do normal test + for(;;) + { + switch(*szWildCard) + { + case '*': // Means "every number of characters" + // Skip all asterisks + while(*szWildCard == '*') + szWildCard++; + + // When no more characters in wildcard, it means that the strings match + if(*szWildCard == 0) + return TRUE; + + // The next N characters must not agree + nMustNotMatch |= 0x70000000; + break; + + case '?': // Means "One or no character" + while(*szWildCard == '?') + { + nMustNotMatch++; + szWildCard++; + } + break; + + default: + // If the two characters match + if(toupper(*szString) == toupper(*szWildCard)) + { + // When end of string, they agree + if(*szString == 0) + return TRUE; + + nMustNotMatch = 0; + szWildCard++; + szString++; + break; + } + + // If the next character must match, the string does not match + if(nMustNotMatch == 0) + return FALSE; + + // Count the characters which must match after characters + // that must not match + szTemp = (char *)szWildCard; + nMustMatch = 0; + while(*szTemp != 0 && *szTemp != '*' && *szTemp != '?') + { + nMustMatch++; + szTemp++; + } + + // Now skip characters from szString up to number of chars + // that must not match + nResult = -1; + while(nMustNotMatch > 0 && *szString != 0) + { + if((nResult = _strnicmp(szString, szWildCard, nMustMatch)) == 0) + break; + + szString++; + nMustNotMatch--; + } + + // Make one more comparison + if(nMustNotMatch == 0) + nResult = _strnicmp(szString, szWildCard, nMustMatch); + + // If a match has been found, continue the search + if(nResult == 0) + { + nMustNotMatch = 0; + szWildCard += nMustMatch; + szString += nMustMatch; + break; + } + return FALSE; + } + } +} + +// Performs one MPQ search +// TODO: Test for archives > 4GB +static int DoMPQSearch(TMPQSearch * hs, SFILE_FIND_DATA * lpFindFileData) +{ + TMPQArchive * ha = hs->ha; + TFileNode * pNode; + TMPQHash * pHashEnd = ha->pHashTable + ha->pHeader->dwHashTableSize; + TMPQHash * pHash = ha->pHashTable + hs->dwNextIndex; + + // Do until some file found or no more files + while(pHash < pHashEnd) + { + pNode = ha->pListFile[hs->dwNextIndex++]; + + // If this entry is free, do nothing + if(pHash->dwBlockIndex < HASH_ENTRY_FREE && (DWORD_PTR)pNode < HASH_ENTRY_FREE) + { + // Check the file name. + if(CheckWildCard(pNode->szFileName, hs->szSearchMask)) + { + TMPQBlock * pBlock = ha->pBlockTable + pHash->dwBlockIndex; + + lpFindFileData->lcLocale = pHash->lcLocale; + lpFindFileData->dwFileSize = pBlock->dwFSize; + lpFindFileData->dwFileFlags = pBlock->dwFlags; + lpFindFileData->dwBlockIndex = pHash->dwBlockIndex; + lpFindFileData->dwCompSize = pBlock->dwCSize; + + // Fill the file name and plain file name + strcpy(lpFindFileData->cFileName, pNode->szFileName); + lpFindFileData->szPlainName = strrchr(lpFindFileData->cFileName, '\\'); + if(lpFindFileData->szPlainName == NULL) + lpFindFileData->szPlainName = lpFindFileData->cFileName; + else + lpFindFileData->szPlainName++; + + // Fill the next entry + return ERROR_SUCCESS; + } + } + + pHash++; + } + + // No more files found, return error + return ERROR_NO_MORE_FILES; +} + +// TODO: Test for archives > 4GB +static void FreeMPQSearch(TMPQSearch *& hs) +{ + if(hs != NULL) + { + FREEMEM(hs); + hs = NULL; + } +} + +//----------------------------------------------------------------------------- +// Public functions + +// TODO: Test for archives > 4GB +HANDLE WINAPI SFileFindFirstFile(HANDLE hMPQ, const char * szMask, SFILE_FIND_DATA * lpFindFileData, const char * szListFile) +{ + TMPQArchive * ha = (TMPQArchive *)hMPQ; + TMPQSearch * hs = NULL; // Search object handle + size_t nSize = 0; + int nError = ERROR_SUCCESS; + + // Check for the valid parameters + if(nError == ERROR_SUCCESS) + { + if(!IsValidMpqHandle(ha)) + nError = ERROR_INVALID_PARAMETER; + + if(szMask == NULL || lpFindFileData == NULL) + nError = ERROR_INVALID_PARAMETER; + + if(szListFile == NULL && !IsValidMpqHandle(ha)) + nError = ERROR_INVALID_PARAMETER; + } + + // Include the listfile into the MPQ's internal listfile + // Note that if the listfile name is NULL, do nothing because the + // internal listfile is always included. + if(nError == ERROR_SUCCESS && szListFile != NULL) + nError = SFileAddListFile((HANDLE)ha, szListFile); + + // Allocate the structure for MPQ search + if(nError == ERROR_SUCCESS) + { + nSize = sizeof(TMPQSearch) + strlen(szMask) + 1; + if((hs = (TMPQSearch *)ALLOCMEM(char, nSize)) == NULL) + nError = ERROR_NOT_ENOUGH_MEMORY; + } + + // Perform the first search + if(nError == ERROR_SUCCESS) + { + memset(hs, 0, sizeof(TMPQSearch)); + hs->ha = ha; + hs->dwNextIndex = 0; + strcpy(hs->szSearchMask, szMask); + nError = DoMPQSearch(hs, lpFindFileData); + } + + // Cleanup + if(nError != ERROR_SUCCESS) + { + FreeMPQSearch(hs); + SetLastError(nError); + } + + // Return the result value + return (HANDLE)hs; +} + +// TODO: Test for archives > 4GB +BOOL WINAPI SFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData) +{ + TMPQSearch * hs = (TMPQSearch *)hFind; + int nError = ERROR_SUCCESS; + + // Check the parameters + if(nError == ERROR_SUCCESS) + { + if(!IsValidSearchHandle(hs) || lpFindFileData == NULL) + nError = ERROR_INVALID_PARAMETER; + } + + if(nError == ERROR_SUCCESS) + nError = DoMPQSearch(hs, lpFindFileData); + + if(nError != ERROR_SUCCESS) + { + SetLastError(nError); + return FALSE; + } + return TRUE; +} + +// TODO: Test for archives > 4GB +BOOL WINAPI SFileFindClose(HANDLE hFind) +{ + TMPQSearch * hs = (TMPQSearch *)hFind; + + // Check the parameters + if(!IsValidSearchHandle(hs)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + FreeMPQSearch(hs); + return TRUE; +} diff --git a/contrib/vmap_extractor_v2/stormlib/SFileOpenArchive.cpp b/contrib/vmap_extractor_v2/stormlib/SFileOpenArchive.cpp new file mode 100644 index 00000000000..cadb4e023a2 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/SFileOpenArchive.cpp @@ -0,0 +1,497 @@ +/*****************************************************************************/ +/* SFileOpenArchive.cpp Copyright Ladislav Zezula 1999 */ +/* */ +/* Author : Ladislav Zezula */ +/* E-mail : ladik@zezula.net */ +/* WWW : www.zezula.net */ +/*---------------------------------------------------------------------------*/ +/* Archive functions of Storm.dll */ +/*---------------------------------------------------------------------------*/ +/* Date Ver Who Comment */ +/* -------- ---- --- ------- */ +/* xx.xx.xx 1.00 Lad The first version of SFileOpenArchive.cpp */ +/* 19.11.03 1.01 Dan Big endian handling */ +/*****************************************************************************/ + +#define __STORMLIB_SELF__ +#include "StormLib.h" +#include "SCommon.h" + +/*****************************************************************************/ +/* Local functions */ +/*****************************************************************************/ + +static BOOL IsAviFile(TMPQHeader * pHeader) +{ + DWORD * AviHdr = (DWORD *)pHeader; + + // Test for 'RIFF', 'AVI ' or 'LIST' + return (AviHdr[0] == 'FFIR' && AviHdr[2] == ' IVA' && AviHdr[3] == 'TSIL'); +} + +// This function gets the right positions of the hash table and the block table. +// TODO: Test for archives > 4GB +static int RelocateMpqTablePositions(TMPQArchive * ha) +{ + TMPQHeader2 * pHeader = ha->pHeader; + LARGE_INTEGER FileSize; + LARGE_INTEGER TempSize; + + // Get the size of the file + FileSize.LowPart = GetFileSize(ha->hFile, (LPDWORD)&FileSize.HighPart); + + // Set the proper hash table position + ha->HashTablePos.HighPart = pHeader->wHashTablePosHigh; + ha->HashTablePos.LowPart = pHeader->dwHashTablePos; + ha->HashTablePos.QuadPart += ha->MpqPos.QuadPart; + if(ha->HashTablePos.QuadPart > FileSize.QuadPart) + return ERROR_BAD_FORMAT; + + // Set the proper block table position + ha->BlockTablePos.HighPart = pHeader->wBlockTablePosHigh; + ha->BlockTablePos.LowPart = pHeader->dwBlockTablePos; + ha->BlockTablePos.QuadPart += ha->MpqPos.QuadPart; + if(ha->BlockTablePos.QuadPart > FileSize.QuadPart) + return ERROR_BAD_FORMAT; + + // Set the proper position of the extended block table + if(pHeader->ExtBlockTablePos.QuadPart != 0) + { + ha->ExtBlockTablePos = pHeader->ExtBlockTablePos; + ha->ExtBlockTablePos.QuadPart += ha->MpqPos.QuadPart; + if(ha->ExtBlockTablePos.QuadPart > FileSize.QuadPart) + return ERROR_BAD_FORMAT; + } + + // Size of MPQ archive is computed as the biggest of + // (EndOfBlockTable, EndOfHashTable, EndOfExtBlockTable) + TempSize.QuadPart = ha->HashTablePos.QuadPart + (pHeader->dwHashTableSize * sizeof(TMPQHash)); + if(TempSize.QuadPart > ha->MpqSize.QuadPart) + ha->MpqSize = TempSize; + TempSize.QuadPart = ha->BlockTablePos.QuadPart + (pHeader->dwBlockTableSize * sizeof(TMPQBlock)); + if(TempSize.QuadPart > ha->MpqSize.QuadPart) + ha->MpqSize = TempSize; + TempSize.QuadPart = ha->ExtBlockTablePos.QuadPart + (pHeader->dwBlockTableSize * sizeof(TMPQBlockEx)); + if(TempSize.QuadPart > ha->MpqSize.QuadPart) + ha->MpqSize = TempSize; + + // MPQ size does not include the bytes before MPQ header + ha->MpqSize.QuadPart -= ha->MpqPos.QuadPart; + return ERROR_SUCCESS; +} + + +/*****************************************************************************/ +/* Public functions */ +/*****************************************************************************/ + +//----------------------------------------------------------------------------- +// SFileGetLocale and SFileSetLocale +// Set the locale for all neewly opened archives and files + +LCID WINAPI SFileGetLocale() +{ + return lcLocale; +} + +LCID WINAPI SFileSetLocale(LCID lcNewLocale) +{ + lcLocale = lcNewLocale; + return lcLocale; +} + +//----------------------------------------------------------------------------- +// SFileOpenArchiveEx (not a public function !!!) +// +// szFileName - MPQ archive file name to open +// dwPriority - When SFileOpenFileEx called, this contains the search priority for searched archives +// dwFlags - If contains MPQ_OPEN_NO_LISTFILE, then the internal list file will not be used. +// phMPQ - Pointer to store open archive handle + +BOOL SFileOpenArchiveEx( + const char * szMpqName, + DWORD dwPriority, + DWORD dwFlags, + HANDLE * phMPQ, + DWORD dwAccessMode) +{ + LARGE_INTEGER TempPos; + TMPQArchive * ha = NULL; // Archive handle + HANDLE hFile = INVALID_HANDLE_VALUE;// Opened archive file handle + DWORD dwMaxBlockIndex = 0; // Maximum value of block entry + DWORD dwBlockTableSize = 0; // Block table size. + DWORD dwTransferred; // Number of bytes read + DWORD dwBytes = 0; // Number of bytes to read + int nError = ERROR_SUCCESS; + + // Check the right parameters + if(nError == ERROR_SUCCESS) + { + if(szMpqName == NULL || *szMpqName == 0 || phMPQ == NULL) + nError = ERROR_INVALID_PARAMETER; + } + + // Ensure that StormBuffer is allocated + if(nError == ERROR_SUCCESS) + nError = PrepareStormBuffer(); + + // Open the MPQ archive file + if(nError == ERROR_SUCCESS) + { + hFile = CreateFile(szMpqName, dwAccessMode, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if(hFile == INVALID_HANDLE_VALUE) + nError = GetLastError(); + } + + // Allocate the MPQhandle + if(nError == ERROR_SUCCESS) + { + if((ha = ALLOCMEM(TMPQArchive, 1)) == NULL) + nError = ERROR_NOT_ENOUGH_MEMORY; + } + + // Initialize handle structure and allocate structure for MPQ header + if(nError == ERROR_SUCCESS) + { + memset(ha, 0, sizeof(TMPQArchive)); + strncpy(ha->szFileName, szMpqName, strlen(szMpqName)); + ha->hFile = hFile; + ha->dwPriority = dwPriority; + ha->pHeader = &ha->Header; + ha->pListFile = NULL; + hFile = INVALID_HANDLE_VALUE; + } + + // Find the offset of MPQ header within the file + if(nError == ERROR_SUCCESS) + { + LARGE_INTEGER SearchPos = {0}; + LARGE_INTEGER MpqPos = {0}; + DWORD dwHeaderID; + + for(;;) + { + // Invalidate the MPQ ID and read the eventual header + SetFilePointer(ha->hFile, MpqPos.LowPart, &MpqPos.HighPart, FILE_BEGIN); + ReadFile(ha->hFile, ha->pHeader, sizeof(TMPQHeader2), &dwTransferred, NULL); + dwHeaderID = BSWAP_INT32_UNSIGNED(ha->pHeader->dwID); + + // Special check : Some MPQs are actually AVI files, only with + // changed extension. + if(MpqPos.QuadPart == 0 && IsAviFile(ha->pHeader)) + { + nError = ERROR_AVI_FILE; + break; + } + + // If different number of bytes read, break the loop + if(dwTransferred != sizeof(TMPQHeader2)) + { + nError = ERROR_BAD_FORMAT; + break; + } + + // If there is the MPQ shunt signature, process it + if(dwHeaderID == ID_MPQ_SHUNT && ha->pShunt == NULL) + { + // Fill the shunt header + ha->ShuntPos = MpqPos; + ha->pShunt = &ha->Shunt; + memcpy(ha->pShunt, ha->pHeader, sizeof(TMPQShunt)); + BSWAP_TMPQSHUNT(ha->pShunt); + + // Set the MPQ pos and repeat the search + MpqPos.QuadPart = SearchPos.QuadPart + ha->pShunt->dwHeaderPos; + continue; + } + + // There must be MPQ header signature + if(dwHeaderID == ID_MPQ) + { + BSWAP_TMPQHEADER(ha->pHeader); + + // Save the position where the MPQ header has been found + ha->MpqPos = MpqPos; + + // If valid signature has been found, break the loop + if(ha->pHeader->wFormatVersion == MPQ_FORMAT_VERSION_1) + { + // W3M Map Protectors set some garbage value into the "dwHeaderSize" + // field of MPQ header. This value is apparently ignored by Storm.dll + if(ha->pHeader->dwHeaderSize != sizeof(TMPQHeader) && + ha->pHeader->dwHeaderSize != sizeof(TMPQHeader2)) + { + ha->dwFlags |= MPQ_FLAG_PROTECTED; + ha->pHeader->dwHeaderSize = sizeof(TMPQHeader); + } + + if(ha->pHeader->dwHashTablePos < ha->pHeader->dwArchiveSize && + ha->pHeader->dwBlockTablePos < ha->pHeader->dwArchiveSize) + { + break; + } + } + + if(ha->pHeader->wFormatVersion == MPQ_FORMAT_VERSION_2) + { + break; + } + + nError = ERROR_NOT_SUPPORTED; + break; + } + + // If a MPQ shunt already has been found, + // and no MPQ header was at potision pointed by the shunt, + // then the archive is corrupt + if(ha->pShunt != NULL) + { + nError = ERROR_BAD_FORMAT; + break; + } + + // Move to the next possible offset + SearchPos.QuadPart += 0x200; + MpqPos = SearchPos; + } + } + + // Relocate tables position + if(nError == ERROR_SUCCESS) + { + // Clear the fields not supported in older formats + if(ha->pHeader->wFormatVersion < MPQ_FORMAT_VERSION_2) + { + ha->pHeader->ExtBlockTablePos.QuadPart = 0; + ha->pHeader->wBlockTablePosHigh = 0; + ha->pHeader->wHashTablePosHigh = 0; + } + + ha->dwBlockSize = (0x200 << ha->pHeader->wBlockSize); + nError = RelocateMpqTablePositions(ha); + } + + // Allocate buffers + if(nError == ERROR_SUCCESS) + { + // + // Note that the block table should be as large as the hash table + // (For later file additions). + // + // I have found a MPQ which has the block table larger than + // the hash table. We should avoid buffer overruns caused by that. + // + dwBlockTableSize = max(ha->pHeader->dwHashTableSize, ha->pHeader->dwBlockTableSize); + + ha->pHashTable = ALLOCMEM(TMPQHash, ha->pHeader->dwHashTableSize); + ha->pBlockTable = ALLOCMEM(TMPQBlock, dwBlockTableSize); + ha->pExtBlockTable = ALLOCMEM(TMPQBlockEx, dwBlockTableSize); + ha->pbBlockBuffer = ALLOCMEM(BYTE, ha->dwBlockSize); + + if(!ha->pHashTable || !ha->pBlockTable || !ha->pExtBlockTable || !ha->pbBlockBuffer) + nError = ERROR_NOT_ENOUGH_MEMORY; + } + + // Read the hash table into memory + if(nError == ERROR_SUCCESS) + { + dwBytes = ha->pHeader->dwHashTableSize * sizeof(TMPQHash); + SetFilePointer(ha->hFile, ha->HashTablePos.LowPart, &ha->HashTablePos.HighPart, FILE_BEGIN); + ReadFile(ha->hFile, ha->pHashTable, dwBytes, &dwTransferred, NULL); + + if(dwTransferred != dwBytes) + nError = ERROR_FILE_CORRUPT; + } + + // Decrypt hash table and check if it is correctly decrypted + if(nError == ERROR_SUCCESS) + { + TMPQHash * pHashEnd = ha->pHashTable + ha->pHeader->dwHashTableSize; + TMPQHash * pHash; + + // We have to convert the hash table from LittleEndian + BSWAP_ARRAY32_UNSIGNED((DWORD *)ha->pHashTable, (dwBytes / sizeof(DWORD))); + DecryptHashTable((DWORD *)ha->pHashTable, (BYTE *)"(hash table)", (ha->pHeader->dwHashTableSize * 4)); + + // Check hash table if is correctly decrypted + for(pHash = ha->pHashTable; pHash < pHashEnd; pHash++) + { + // Note: Some MPQs from World of Warcraft have wPlatform set to 0x0100. + + // If not free or deleted hash entry, check for valid values + if(pHash->dwBlockIndex < HASH_ENTRY_DELETED) + { + // The block index should not be larger than size of the block table + if(pHash->dwBlockIndex > ha->pHeader->dwBlockTableSize) + { + nError = ERROR_BAD_FORMAT; + break; + } + + // Remember the highest block table entry + if(pHash->dwBlockIndex > dwMaxBlockIndex) + dwMaxBlockIndex = pHash->dwBlockIndex; + } + } + } + + // Now, read the block table + if(nError == ERROR_SUCCESS) + { + memset(ha->pBlockTable, 0, dwBlockTableSize * sizeof(TMPQBlock)); + + dwBytes = ha->pHeader->dwBlockTableSize * sizeof(TMPQBlock); + SetFilePointer(ha->hFile, ha->BlockTablePos.LowPart, &ha->BlockTablePos.HighPart, FILE_BEGIN); + ReadFile(ha->hFile, ha->pBlockTable, dwBytes, &dwTransferred, NULL); + + // We have to convert every DWORD in ha->block from LittleEndian + BSWAP_ARRAY32_UNSIGNED((DWORD *)ha->pBlockTable, dwBytes / sizeof(DWORD)); + + if(dwTransferred != dwBytes) + nError = ERROR_FILE_CORRUPT; + } + + // Decrypt block table. + // Some MPQs don't have Decrypted block table, e.g. cracked Diablo version + // We have to check if block table is really encrypted + if(nError == ERROR_SUCCESS) + { + TMPQBlock * pBlockEnd = ha->pBlockTable + ha->pHeader->dwBlockTableSize; + TMPQBlock * pBlock = ha->pBlockTable; + BOOL bBlockTableEncrypted = FALSE; + + // Verify all blocks entries in the table + // The loop usually stops at the first entry + while(pBlock < pBlockEnd) + { + // The lower 8 bits of the MPQ flags are always zero. + // Note that this may change in next MPQ versions + if(pBlock->dwFlags & 0x000000FF) + { + bBlockTableEncrypted = TRUE; + break; + } + + // Move to the next block table entry + pBlock++; + } + + if(bBlockTableEncrypted) + { + DecryptBlockTable((DWORD *)ha->pBlockTable, + (BYTE *)"(block table)", + (ha->pHeader->dwBlockTableSize * 4)); + } + } + + // Now, read the extended block table. + // For V1 archives, we still will maintain the extended block table + // (it will be filled with zeros) + // TODO: Test with >4GB + if(nError == ERROR_SUCCESS) + { + memset(ha->pExtBlockTable, 0, dwBlockTableSize * sizeof(TMPQBlockEx)); + + if(ha->pHeader->ExtBlockTablePos.QuadPart != 0) + { + dwBytes = ha->pHeader->dwBlockTableSize * sizeof(TMPQBlockEx); + SetFilePointer(ha->hFile, + ha->ExtBlockTablePos.LowPart, + &ha->ExtBlockTablePos.HighPart, + FILE_BEGIN); + ReadFile(ha->hFile, ha->pExtBlockTable, dwBytes, &dwTransferred, NULL); + + // We have to convert every DWORD in ha->block from LittleEndian + BSWAP_ARRAY16_UNSIGNED((USHORT *)ha->pExtBlockTable, dwBytes / sizeof(USHORT)); + + // The extended block table is not encrypted (so far) + if(dwTransferred != dwBytes) + nError = ERROR_FILE_CORRUPT; + } + } + + // Verify the both block tables (If the MPQ file is not protected) + if(nError == ERROR_SUCCESS && (ha->dwFlags & MPQ_FLAG_PROTECTED) == 0) + { + TMPQBlockEx * pBlockEx = ha->pExtBlockTable; + TMPQBlock * pBlockEnd = ha->pBlockTable + dwMaxBlockIndex + 1; + TMPQBlock * pBlock = ha->pBlockTable; + + // If the MPQ file is not protected, + // we will check if all sizes in the block table is correct. + // Note that we will not relocate the block table (change from previous versions) + for(; pBlock < pBlockEnd; pBlock++, pBlockEx++) + { + if(pBlock->dwFlags & MPQ_FILE_EXISTS) + { + // Get the 64-bit file position + TempPos.HighPart = pBlockEx->wFilePosHigh; + TempPos.LowPart = pBlock->dwFilePos; + + if(TempPos.QuadPart > ha->MpqSize.QuadPart || pBlock->dwCSize > ha->MpqSize.QuadPart) + { + nError = ERROR_BAD_FORMAT; + break; + } + } + } + } + + // If the user didn't specified otherwise, + // include the internal listfile to the TMPQArchive structure + if((dwFlags & MPQ_OPEN_NO_LISTFILE) == 0) + { + if(nError == ERROR_SUCCESS) + SListFileCreateListFile(ha); + + // Add the internal listfile + if(nError == ERROR_SUCCESS) + SFileAddListFile((HANDLE)ha, NULL); + } + + // Cleanup and exit + if(nError != ERROR_SUCCESS) + { + FreeMPQArchive(ha); + if(hFile != INVALID_HANDLE_VALUE) + CloseHandle(hFile); + SetLastError(nError); + } + else + { + if(pFirstOpen == NULL) + pFirstOpen = ha; + } + *phMPQ = ha; + return (nError == ERROR_SUCCESS); +} + +BOOL WINAPI SFileOpenArchive(const char * szMpqName, DWORD dwPriority, DWORD dwFlags, HANDLE * phMPQ) +{ + return SFileOpenArchiveEx(szMpqName, dwPriority, dwFlags, phMPQ, GENERIC_READ); +} + +//----------------------------------------------------------------------------- +// BOOL SFileCloseArchive(HANDLE hMPQ); +// + +// TODO: Test for archives > 4GB +BOOL WINAPI SFileCloseArchive(HANDLE hMPQ) +{ + TMPQArchive * ha = (TMPQArchive *)hMPQ; + + if(!IsValidMpqHandle(ha)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if(ha->dwFlags & MPQ_FLAG_CHANGED) + { + SListFileSaveToMpq(ha); + SaveMPQTables(ha); + } + FreeMPQArchive(ha); + return TRUE; +} + diff --git a/contrib/vmap_extractor_v2/stormlib/SFileOpenFileEx.cpp b/contrib/vmap_extractor_v2/stormlib/SFileOpenFileEx.cpp new file mode 100644 index 00000000000..dae312144eb --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/SFileOpenFileEx.cpp @@ -0,0 +1,403 @@ +/*****************************************************************************/ +/* SFileOpenFileEx.cpp Copyright (c) Ladislav Zezula 2003 */ +/*---------------------------------------------------------------------------*/ +/* Description : */ +/*---------------------------------------------------------------------------*/ +/* Date Ver Who Comment */ +/* -------- ---- --- ------- */ +/* xx.xx.99 1.00 Lad The first version of SFileOpenFileEx.cpp */ +/*****************************************************************************/ + +#define __STORMLIB_SELF__ +#include "StormLib.h" +#include "SCommon.h" + +/*****************************************************************************/ +/* Local functions */ +/*****************************************************************************/ + +// TODO: Test for archives > 4GB +static BOOL OpenLocalFile(const char * szFileName, HANDLE * phFile) +{ + TMPQFile * hf = NULL; + HANDLE hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); + + if(hFile != INVALID_HANDLE_VALUE) + { + // Allocate and initialize file handle + size_t nHandleSize = sizeof(TMPQFile) + strlen(szFileName); + if((hf = (TMPQFile *)ALLOCMEM(char, nHandleSize)) != NULL) + { + memset(hf, 0, nHandleSize); + strcpy(hf->szFileName, szFileName); + hf->hFile = hFile; + *phFile = hf; + return TRUE; + } + else + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + } + *phFile = NULL; + return FALSE; +} + +// TODO: Test for archives > 4GB +static void FreeMPQFile(TMPQFile *& hf) +{ + if(hf != NULL) + { + if(hf->hFile != INVALID_HANDLE_VALUE) + CloseHandle(hf->hFile); + if(hf->pdwBlockPos != NULL) + FREEMEM(hf->pdwBlockPos); + if(hf->pbFileBuffer != NULL) + FREEMEM(hf->pbFileBuffer); + FREEMEM(hf); + hf = NULL; + } +} + +/*****************************************************************************/ +/* Public functions */ +/*****************************************************************************/ + +//----------------------------------------------------------------------------- +// SFileEnumLocales enums all locale versions within MPQ. +// Functions fills all available language identifiers on a file into the buffer +// pointed by plcLocales. There must be enough entries to copy the localed, +// otherwise the function returns ERROR_INSUFFICIENT_BUFFER. + +// TODO: Test for archives > 4GB +int WINAPI SFileEnumLocales( + HANDLE hMPQ, + const char * szFileName, + LCID * plcLocales, + DWORD * pdwMaxLocales, + DWORD dwSearchScope) +{ + TMPQArchive * ha = (TMPQArchive *)hMPQ; + TMPQHash * pHash = NULL; + TMPQHash * pHashEnd = NULL; + DWORD dwLocales = 0; + int nError = ERROR_SUCCESS; + + // Test the parameters + if(nError == ERROR_SUCCESS) + { + if(!IsValidMpqHandle(ha) || pdwMaxLocales == NULL) + nError = ERROR_INVALID_PARAMETER; + if(dwSearchScope == SFILE_OPEN_BY_INDEX && (DWORD_PTR)szFileName > ha->pHeader->dwBlockTableSize) + nError = ERROR_INVALID_PARAMETER; + if(dwSearchScope != SFILE_OPEN_BY_INDEX && *szFileName == 0) + nError = ERROR_INVALID_PARAMETER; + } + + // Retrieve the hash entry for the required file + if(nError == ERROR_SUCCESS) + { + pHashEnd = ha->pHashTable + ha->pHeader->dwHashTableSize; + + if(dwSearchScope == SFILE_OPEN_BY_INDEX) + { + for(pHash = ha->pHashTable; pHash < pHashEnd; pHash++) + { + if(pHash->dwBlockIndex == (DWORD_PTR)szFileName) + break; + } + if(pHash == pHashEnd) + pHash = NULL; + } + else + pHash = GetHashEntry(ha, szFileName); + } + + // If the file was not found, sorry + if(nError == ERROR_SUCCESS) + { + if(pHash == NULL) + nError = ERROR_FILE_NOT_FOUND; + } + + // Count the entries which correspond to the same file name + if(nError == ERROR_SUCCESS) + { + TMPQHash * pSaveHash = pHash; + DWORD dwName1 = pHash->dwName1; + DWORD dwName2 = pHash->dwName2; + + // For nameless access, return 1 locale always + if(dwSearchScope == SFILE_OPEN_BY_INDEX) + dwLocales++; + else + { + while(pHash < pHashEnd && pHash->dwName1 == dwName1 && pHash->dwName2 == dwName2) + { + dwLocales++; + pHash++; + } + } + + pHash = pSaveHash; + } + + // Test if there is enough space to copy the locales + if(nError == ERROR_SUCCESS) + { + DWORD dwMaxLocales = *pdwMaxLocales; + + *pdwMaxLocales = dwLocales; + if(dwMaxLocales < dwLocales) + nError = ERROR_INSUFFICIENT_BUFFER; + } + + // Fill all the locales + if(nError == ERROR_SUCCESS) + { + for(DWORD i = 0; i < dwLocales; i++, pHash++) + *plcLocales++ = (LCID)pHash->lcLocale; + } + return nError; +} + +//----------------------------------------------------------------------------- +// SFileHasFile +// +// hMPQ - Handle of opened MPQ archive +// szFileName - Name of file to look for + +// TODO: Test for archives > 4GB +BOOL WINAPI SFileHasFile(HANDLE hMPQ, char * szFileName) +{ + TMPQArchive * ha = (TMPQArchive *)hMPQ; + int nError = ERROR_SUCCESS; + + if(nError == ERROR_SUCCESS) + { + if(ha == NULL) + nError = ERROR_INVALID_PARAMETER; + if(*szFileName == 0) + nError = ERROR_INVALID_PARAMETER; + } + + // Prepare the file opening + if(nError == ERROR_SUCCESS) + { + if(GetHashEntryEx(ha, szFileName, lcLocale) == NULL) + { + nError = ERROR_FILE_NOT_FOUND; + } + } + + // Cleanup + if(nError != ERROR_SUCCESS) + { + SetLastError(nError); + } + + return (nError == ERROR_SUCCESS); +} + + +//----------------------------------------------------------------------------- +// SFileOpenFileEx +// +// hMPQ - Handle of opened MPQ archive +// szFileName - Name of file to open +// dwSearchScope - Where to search +// phFile - Pointer to store opened file handle + +// TODO: Test for archives > 4GB +BOOL WINAPI SFileOpenFileEx(HANDLE hMPQ, const char * szFileName, DWORD dwSearchScope, HANDLE * phFile) +{ + LARGE_INTEGER FilePos; + TMPQArchive * ha = (TMPQArchive *)hMPQ; + TMPQFile * hf = NULL; + TMPQHash * pHash = NULL; // Hash table index + TMPQBlock * pBlock = NULL; // File block + TMPQBlockEx * pBlockEx = NULL; + DWORD dwHashIndex = 0; // Hash table index + DWORD dwBlockIndex = (DWORD)-1; // Found table index + size_t nHandleSize = 0; // Memory space necessary to allocate TMPQHandle + int nError = ERROR_SUCCESS; + +#ifdef _DEBUG + // Due to increasing numbers of files in MPQs, I had to change the behavior + // of opening by file index. Now, the SFILE_OPEN_BY_INDEX value of dwSearchScope + // must be entered. This check will allow to find code places that are incompatible + // with the new behavior. + if(dwSearchScope != SFILE_OPEN_BY_INDEX && szFileName != NULL) + { + assert((DWORD_PTR)szFileName > 0x10000); + } +#endif + + if(nError == ERROR_SUCCESS) + { + if(ha == NULL && dwSearchScope == SFILE_OPEN_FROM_MPQ) + nError = ERROR_INVALID_PARAMETER; + if(phFile == NULL) + nError = ERROR_INVALID_PARAMETER; + if(dwSearchScope == SFILE_OPEN_BY_INDEX && (DWORD_PTR)szFileName > ha->pHeader->dwBlockTableSize) + nError = ERROR_INVALID_PARAMETER; + if(dwSearchScope != SFILE_OPEN_BY_INDEX && (szFileName == NULL || *szFileName == 0)) + nError = ERROR_INVALID_PARAMETER; + } + + // Prepare the file opening + if(nError == ERROR_SUCCESS) + { + // When the file is given by number, ... + if(dwSearchScope == SFILE_OPEN_BY_INDEX) + { + TMPQHash * pHashEnd = ha->pHashTable + ha->pHeader->dwHashTableSize; + + // Set handle size to be sizeof(TMPQFile) + length of FileXXXXXXXX.xxx + nHandleSize = sizeof(TMPQFile) + 20; + for(pHash = ha->pHashTable; pHash < pHashEnd; pHash++) + { + if((DWORD_PTR)szFileName == pHash->dwBlockIndex) + { + dwHashIndex = (DWORD)(pHash - ha->pHashTable); + dwBlockIndex = pHash->dwBlockIndex; + break; + } + } + } + else + { + // If we have to open a disk file + if(dwSearchScope == SFILE_OPEN_LOCAL_FILE) + return OpenLocalFile(szFileName, phFile); + + nHandleSize = sizeof(TMPQFile) + strlen(szFileName); + if((pHash = GetHashEntryEx(ha, szFileName, lcLocale)) != NULL) + { + dwHashIndex = (DWORD)(pHash - ha->pHashTable); + dwBlockIndex = pHash->dwBlockIndex; + } + } + } + + // Get block index from file name and test it + if(nError == ERROR_SUCCESS) + { + // If index was not found, or is greater than number of files, exit. + if(dwBlockIndex == (DWORD)-1 || dwBlockIndex > ha->pHeader->dwBlockTableSize) + nError = ERROR_FILE_NOT_FOUND; + } + + // Get block and test if the file was not already deleted. + if(nError == ERROR_SUCCESS) + { + // Get both block tables and file position + pBlockEx = ha->pExtBlockTable + dwBlockIndex; + pBlock = ha->pBlockTable + dwBlockIndex; + FilePos.HighPart = pBlockEx->wFilePosHigh; + FilePos.LowPart = pBlock->dwFilePos; + + if(FilePos.QuadPart > ha->MpqSize.QuadPart || + pBlock->dwCSize > ha->MpqSize.QuadPart) + nError = ERROR_FILE_CORRUPT; + if((pBlock->dwFlags & MPQ_FILE_EXISTS) == 0) + nError = ERROR_FILE_NOT_FOUND; + if(pBlock->dwFlags & ~MPQ_FILE_VALID_FLAGS) + nError = ERROR_NOT_SUPPORTED; + } + + // Allocate file handle + if(nError == ERROR_SUCCESS) + { + if((hf = (TMPQFile *)ALLOCMEM(char, nHandleSize)) == NULL) + nError = ERROR_NOT_ENOUGH_MEMORY; + } + + // Initialize file handle + if(nError == ERROR_SUCCESS) + { + memset(hf, 0, nHandleSize); + hf->hFile = INVALID_HANDLE_VALUE; + hf->ha = ha; + hf->pBlockEx = pBlockEx; + hf->pBlock = pBlock; + hf->nBlocks = (hf->pBlock->dwFSize + ha->dwBlockSize - 1) / ha->dwBlockSize; + hf->pHash = pHash; + + hf->MpqFilePos.HighPart = pBlockEx->wFilePosHigh; + hf->MpqFilePos.LowPart = pBlock->dwFilePos; + hf->MpqFilePos.QuadPart += ha->MpqPos.QuadPart; + + hf->dwHashIndex = dwHashIndex; + hf->dwFileIndex = dwBlockIndex; + + // Allocate buffers for decompression. + if(hf->pBlock->dwFlags & MPQ_FILE_COMPRESSED) + { + // Allocate buffer for block positions. At the begin of file are stored + // DWORDs holding positions of each block relative from begin of file in the archive + // As for newer MPQs, there may be one additional entry in the block table + // (if the MPQ_FILE_HAS_EXTRA flag is set). + // Allocate the buffer to include this DWORD as well + + if((hf->pdwBlockPos = ALLOCMEM(DWORD, hf->nBlocks + 2)) == NULL) + nError = ERROR_NOT_ENOUGH_MEMORY; + } + + // Decrypt file seed. Cannot be used if the file is given by index + if(dwSearchScope != SFILE_OPEN_BY_INDEX) + { + if(hf->pBlock->dwFlags & MPQ_FILE_ENCRYPTED) + { + const char * szTemp = strrchr(szFileName, '\\'); + + strcpy(hf->szFileName, szFileName); + if(szTemp != NULL) + szFileName = szTemp + 1; + hf->dwSeed1 = DecryptFileSeed((char *)szFileName); + + if(hf->pBlock->dwFlags & MPQ_FILE_FIXSEED) + { + hf->dwSeed1 = (hf->dwSeed1 + hf->pBlock->dwFilePos) ^ hf->pBlock->dwFSize; + } + } + } + else + { + // If the file is encrypted and not compressed, we cannot detect the file seed + if(SFileGetFileName(hf, hf->szFileName) == FALSE) + nError = GetLastError(); + } + } + + // Cleanup + if(nError != ERROR_SUCCESS) + { + FreeMPQFile(hf); + SetLastError(nError); + } + + *phFile = hf; + return (nError == ERROR_SUCCESS); +} + +//----------------------------------------------------------------------------- +// BOOL SFileCloseFile(HANDLE hFile); + +// TODO: Test for archives > 4GB +BOOL WINAPI SFileCloseFile(HANDLE hFile) +{ + TMPQFile * hf = (TMPQFile *)hFile; + + if(!IsValidFileHandle(hf)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + // Set the last accessed file in the archive + if(hf->ha != NULL) + hf->ha->pLastFile = NULL; + + // Free the structure + FreeMPQFile(hf); + return TRUE; +} diff --git a/contrib/vmap_extractor_v2/stormlib/SFileReadFile.cpp b/contrib/vmap_extractor_v2/stormlib/SFileReadFile.cpp new file mode 100644 index 00000000000..27fd1e0f085 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/SFileReadFile.cpp @@ -0,0 +1,826 @@ +/*****************************************************************************/ +/* SFileReadFile.cpp Copyright (c) Ladislav Zezula 2003 */ +/*---------------------------------------------------------------------------*/ +/* Description : */ +/*---------------------------------------------------------------------------*/ +/* Date Ver Who Comment */ +/* -------- ---- --- ------- */ +/* xx.xx.99 1.00 Lad The first version of SFileReadFile.cpp */ +/* 24.03.99 1.00 Lad Added the SFileGetFileInfo function */ +/*****************************************************************************/ + +#define __STORMLIB_SELF__ +#include "StormLib.h" +#include "SCommon.h" + +//----------------------------------------------------------------------------- +// Defines + +#define ID_WAVE 0x46464952 // Signature of WAVes for name breaking +#define ID_EXE 0x00005A4D // Signature of executable files + +//----------------------------------------------------------------------------- +// Local structures + +struct TID2Ext +{ + DWORD dwID; + char * szExt; +}; + +//----------------------------------------------------------------------------- +// ReadMPQBlock +// +// hf - MPQ File handle. +// dwBlockPos - Position of block in the file (relative to file begin) +// buffer - Pointer to target buffer to store blocks. +// dwBlockSize - Number of bytes to read. Must be multiplier of block size. +// +// Returns number of bytes read. + +// TODO: Test for archives > 4GB +static DWORD WINAPI ReadMPQBlocks(TMPQFile * hf, DWORD dwBlockPos, BYTE * buffer, DWORD blockBytes) +{ + LARGE_INTEGER FilePos; + TMPQArchive * ha = hf->ha; // Archive handle + BYTE * tempBuffer = NULL; // Buffer for reading compressed data from the file + DWORD dwFilePos = dwBlockPos; // Reading position from the file + DWORD dwToRead; // Number of bytes to read + DWORD blockNum; // Block number (needed for decrypt) + DWORD dwBytesRead = 0; // Total number of bytes read + DWORD bytesRemain = 0; // Number of data bytes remaining up to the end of the file + DWORD nBlocks; // Number of blocks to load + DWORD i; + + // Test parameters. Block position and block size must be block-aligned, block size nonzero + if((dwBlockPos & (ha->dwBlockSize - 1)) || blockBytes == 0) + return 0; + + // Check the end of file + if((dwBlockPos + blockBytes) > hf->pBlock->dwFSize) + blockBytes = hf->pBlock->dwFSize - dwBlockPos; + + bytesRemain = hf->pBlock->dwFSize - dwBlockPos; + blockNum = dwBlockPos / ha->dwBlockSize; + nBlocks = blockBytes / ha->dwBlockSize; + if(blockBytes % ha->dwBlockSize) + nBlocks++; + + // If file has variable block positions, we have to load them + if((hf->pBlock->dwFlags & MPQ_FILE_COMPRESSED) && hf->bBlockPosLoaded == FALSE) + { + // Move file pointer to the begin of the file in the MPQ + if(hf->MpqFilePos.QuadPart != ha->FilePointer.QuadPart) + { + SetFilePointer(ha->hFile, hf->MpqFilePos.LowPart, &hf->MpqFilePos.HighPart, FILE_BEGIN); + } + + // Read block positions from begin of file. + dwToRead = (hf->nBlocks+1) * sizeof(DWORD); + if(hf->pBlock->dwFlags & MPQ_FILE_HAS_EXTRA) + dwToRead += sizeof(DWORD); + + // Read the block pos table and convert the buffer to little endian + ReadFile(ha->hFile, hf->pdwBlockPos, dwToRead, &dwBytesRead, NULL); + BSWAP_ARRAY32_UNSIGNED(hf->pdwBlockPos, (hf->nBlocks+1)); + + // + // If the archive if protected some way, perform additional check + // Sometimes, the file appears not to be encrypted, but it is. + // + // Note: In WoW 1.10+, there's a new flag. With this flag present, + // there's one additional entry in the block table. + // + + if(hf->pdwBlockPos[0] != dwBytesRead) + hf->pBlock->dwFlags |= MPQ_FILE_ENCRYPTED; + + // Decrypt loaded block positions if necessary + if(hf->pBlock->dwFlags & MPQ_FILE_ENCRYPTED) + { + // If we don't know the file seed, try to find it. + if(hf->dwSeed1 == 0) + hf->dwSeed1 = DetectFileSeed(hf->pdwBlockPos, dwBytesRead); + + // If we don't know the file seed, sorry but we cannot extract the file. + if(hf->dwSeed1 == 0) + return 0; + + // Decrypt block positions + DecryptMPQBlock(hf->pdwBlockPos, dwBytesRead, hf->dwSeed1 - 1); + + // Check if the block positions are correctly decrypted + // I don't know why, but sometimes it will result invalid block positions on some files + if(hf->pdwBlockPos[0] != dwBytesRead) + { + // Try once again to detect file seed and decrypt the blocks + // TODO: Test with >4GB + SetFilePointer(ha->hFile, hf->MpqFilePos.LowPart, &hf->MpqFilePos.HighPart, FILE_BEGIN); + ReadFile(ha->hFile, hf->pdwBlockPos, dwToRead, &dwBytesRead, NULL); + + BSWAP_ARRAY32_UNSIGNED(hf->pdwBlockPos, (hf->nBlocks+1)); + hf->dwSeed1 = DetectFileSeed(hf->pdwBlockPos, dwBytesRead); + DecryptMPQBlock(hf->pdwBlockPos, dwBytesRead, hf->dwSeed1 - 1); + + // Check if the block positions are correctly decrypted + if(hf->pdwBlockPos[0] != dwBytesRead) + return 0; + } + } + + // Update hf's variables + ha->FilePointer.QuadPart = hf->MpqFilePos.QuadPart + dwBytesRead; + hf->bBlockPosLoaded = TRUE; + } + + // Get file position and number of bytes to read + dwFilePos = dwBlockPos; + dwToRead = blockBytes; + if(hf->pBlock->dwFlags & MPQ_FILE_COMPRESSED) + { + dwFilePos = hf->pdwBlockPos[blockNum]; + dwToRead = hf->pdwBlockPos[blockNum + nBlocks] - dwFilePos; + } + FilePos.QuadPart = hf->MpqFilePos.QuadPart + dwFilePos; + + // Get work buffer for store read data + tempBuffer = buffer; + if(hf->pBlock->dwFlags & MPQ_FILE_COMPRESSED) + { + if((tempBuffer = ALLOCMEM(BYTE, dwToRead)) == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + } + + // Set file pointer, if necessary + if(ha->FilePointer.QuadPart != FilePos.QuadPart) + { + SetFilePointer(ha->hFile, FilePos.LowPart, &FilePos.HighPart, FILE_BEGIN); + } + + // 15018F87 : Read all requested blocks + ReadFile(ha->hFile, tempBuffer, dwToRead, &dwBytesRead, NULL); + ha->FilePointer.QuadPart = FilePos.QuadPart + dwBytesRead; + + // Block processing part. + DWORD blockStart = 0; // Index of block start in work buffer + DWORD blockSize = min(blockBytes, ha->dwBlockSize); + DWORD index = blockNum; // Current block index + + dwBytesRead = 0; // Clear read byte counter + + // Walk through all blocks + for(i = 0; i < nBlocks; i++, index++) + { + BYTE * inputBuffer = tempBuffer + blockStart; + int outLength = ha->dwBlockSize; + + if(bytesRemain < (DWORD)outLength) + outLength = bytesRemain; + + // Get current block length + if(hf->pBlock->dwFlags & MPQ_FILE_COMPRESSED) + blockSize = hf->pdwBlockPos[index+1] - hf->pdwBlockPos[index]; + + // If block is encrypted, we have to decrypt it. + if(hf->pBlock->dwFlags & MPQ_FILE_ENCRYPTED) + { + BSWAP_ARRAY32_UNSIGNED((DWORD *)inputBuffer, blockSize / sizeof(DWORD)); + + // If we don't know the seed, try to decode it as WAVE file + if(hf->dwSeed1 == 0) + hf->dwSeed1 = DetectFileSeed2((DWORD *)inputBuffer, 3, ID_WAVE, hf->pBlock->dwFSize - 8, 0x45564157); + + // Let's try MSVC's standard EXE or header + if(hf->dwSeed1 == 0) + hf->dwSeed1 = DetectFileSeed2((DWORD *)inputBuffer, 2, 0x00905A4D, 0x00000003); + + if(hf->dwSeed1 == 0) + return 0; + + DecryptMPQBlock((DWORD *)inputBuffer, blockSize, hf->dwSeed1 + index); + BSWAP_ARRAY32_UNSIGNED((DWORD *)inputBuffer, blockSize / sizeof(DWORD)); + } + + // If the block is really compressed, decompress it. + // WARNING : Some block may not be compressed, it can be determined only + // by comparing uncompressed and compressed size !!! + if(blockSize < (DWORD)outLength) + { + // Is the file compressed with PKWARE Data Compression Library ? + if(hf->pBlock->dwFlags & MPQ_FILE_COMPRESS_PKWARE) + Decompress_pklib((char *)buffer, &outLength, (char *)inputBuffer, (int)blockSize); + + // Is it a file compressed by Blizzard's multiple compression ? + // Note that Storm.dll v 1.0.9 distributed with Warcraft III + // passes the full path name of the opened archive as the new last parameter + if(hf->pBlock->dwFlags & MPQ_FILE_COMPRESS_MULTI) + SCompDecompress((char *)buffer, &outLength, (char *)inputBuffer, (int)blockSize); + dwBytesRead += outLength; + buffer += outLength; + } + else + { + if(buffer != inputBuffer) + memcpy(buffer, inputBuffer, blockSize); + + dwBytesRead += blockSize; + buffer += blockSize; + } + blockStart += blockSize; + bytesRemain -= outLength; + } + + // Delete input buffer, if necessary + if(hf->pBlock->dwFlags & MPQ_FILE_COMPRESSED) + FREEMEM(tempBuffer); + + return dwBytesRead; +} + +// When this function is called, it is already ensured that the parameters are valid +// (e.g. the "dwToRead + dwFilePos" is not greater than the file size) +// TODO: Test for archives > 4GB +static DWORD WINAPI ReadMPQFileSingleUnit(TMPQFile * hf, DWORD dwFilePos, BYTE * pbBuffer, DWORD dwToRead) +{ + TMPQArchive * ha = hf->ha; + DWORD dwBytesRead = 0; + + if(ha->FilePointer.QuadPart != hf->MpqFilePos.QuadPart) + { + SetFilePointer(ha->hFile, hf->MpqFilePos.LowPart, &hf->MpqFilePos.HighPart, FILE_BEGIN); + ha->FilePointer = hf->MpqFilePos; + } + + // If the file is really compressed, decompress it. + // Otherwise, read the data as-is to the caller. + if(hf->pBlock->dwCSize < hf->pBlock->dwFSize) + { + if(hf->pbFileBuffer == NULL) + { + BYTE * inputBuffer = NULL; + int outputBufferSize = (int)hf->pBlock->dwFSize; + int inputBufferSize = (int)hf->pBlock->dwCSize; + + hf->pbFileBuffer = ALLOCMEM(BYTE, outputBufferSize); + inputBuffer = ALLOCMEM(BYTE, inputBufferSize); + if(inputBuffer != NULL && hf->pbFileBuffer != NULL) + { + // Read the compressed file data + ReadFile(ha->hFile, inputBuffer, inputBufferSize, &dwBytesRead, NULL); + + // Is the file compressed with PKWARE Data Compression Library ? + if(hf->pBlock->dwFlags & MPQ_FILE_COMPRESS_PKWARE) + Decompress_pklib((char *)hf->pbFileBuffer, &outputBufferSize, (char *)inputBuffer, (int)inputBufferSize); + + // Is it a file compressed by Blizzard's multiple compression ? + // Note that Storm.dll v 1.0.9 distributed with Warcraft III + // passes the full path name of the opened archive as the new last parameter + if(hf->pBlock->dwFlags & MPQ_FILE_COMPRESS_MULTI) + SCompDecompress((char *)hf->pbFileBuffer, &outputBufferSize, (char *)inputBuffer, (int)inputBufferSize); + } + + // Free the temporary buffer + if(inputBuffer != NULL) + FREEMEM(inputBuffer); + } + + // Copy the file data, if any there + if(hf->pbFileBuffer != NULL) + { + memcpy(pbBuffer, hf->pbFileBuffer + dwFilePos, dwToRead); + dwBytesRead += dwToRead; + } + } + else + { + // Read the uncompressed file data + ReadFile(ha->hFile, pbBuffer, dwToRead, &dwBytesRead, NULL); + dwBytesRead = (int)dwBytesRead; + } + + return (DWORD)dwBytesRead; +} + + +//----------------------------------------------------------------------------- +// ReadMPQFile + +// TODO: Test for archives > 4GB +static DWORD WINAPI ReadMPQFile(TMPQFile * hf, DWORD dwFilePos, BYTE * pbBuffer, DWORD dwToRead) +{ + TMPQArchive * ha = hf->ha; + TMPQBlock * pBlock = hf->pBlock; // Pointer to file block + DWORD dwBytesRead = 0; // Number of bytes read from the file + DWORD dwBlockPos; // Position in the file aligned to the whole blocks + DWORD dwLoaded; + + // File position is greater or equal to file size ? + if(dwFilePos >= pBlock->dwFSize) + return dwBytesRead; + + // If too few bytes in the file remaining, cut them + if((pBlock->dwFSize - dwFilePos) < dwToRead) + dwToRead = (pBlock->dwFSize - dwFilePos); + + // If the file is stored as single unit, handle it separately + if(pBlock->dwFlags & MPQ_FILE_SINGLE_UNIT) + return ReadMPQFileSingleUnit(hf, dwFilePos, pbBuffer, dwToRead); + + // Block position in the file + dwBlockPos = dwFilePos & ~(ha->dwBlockSize - 1); // Position in the block + + // Load the first block, if incomplete. It may be loaded in the cache buffer. + // We have to check if this block is loaded. If not, load it. + if((dwFilePos % ha->dwBlockSize) != 0) + { + // Number of bytes remaining in the buffer + DWORD dwToCopy; + DWORD dwLoaded = ha->dwBlockSize; + + // Check if data are loaded in the cache + if(hf != ha->pLastFile || dwBlockPos != ha->dwBlockPos) + { + // Load one MPQ block into archive buffer + dwLoaded = ReadMPQBlocks(hf, dwBlockPos, ha->pbBlockBuffer, ha->dwBlockSize); + if(dwLoaded == 0) + return (DWORD)-1; + + // Save lastly accessed file and block position for later use + ha->pLastFile = hf; + ha->dwBlockPos = dwBlockPos; + ha->dwBuffPos = dwFilePos % ha->dwBlockSize; + } + dwToCopy = dwLoaded - ha->dwBuffPos; + if(dwToCopy > dwToRead) + dwToCopy = dwToRead; + + // Copy data from block buffer into target buffer + memcpy(pbBuffer, ha->pbBlockBuffer + ha->dwBuffPos, dwToCopy); + + // Update pointers + dwToRead -= dwToCopy; + dwBytesRead += dwToCopy; + pbBuffer += dwToCopy; + dwBlockPos += ha->dwBlockSize; + ha->dwBuffPos += dwToCopy; + + // If all, return. + if(dwToRead == 0) + return dwBytesRead; + } + + // Load the whole ("middle") blocks only if there are more or equal one block + if(dwToRead > ha->dwBlockSize) + { + DWORD dwBlockBytes = dwToRead & ~(ha->dwBlockSize - 1); + + dwLoaded = ReadMPQBlocks(hf, dwBlockPos, pbBuffer, dwBlockBytes); + if(dwLoaded == 0) + return (DWORD)-1; + + // Update pointers + dwToRead -= dwLoaded; + dwBytesRead += dwLoaded; + pbBuffer += dwLoaded; + dwBlockPos += dwLoaded; + + // If all, return. + if(dwToRead == 0) + return dwBytesRead; + } + + // Load the terminating block + if(dwToRead > 0) + { + DWORD dwToCopy = ha->dwBlockSize; + + // Check if data are loaded in the cache + if(hf != ha->pLastFile || dwBlockPos != ha->dwBlockPos) + { + // Load one MPQ block into archive buffer + dwToCopy = ReadMPQBlocks(hf, dwBlockPos, ha->pbBlockBuffer, ha->dwBlockSize); + if(dwToCopy == 0) + return (DWORD)-1; + + // Save lastly accessed file and block position for later use + ha->pLastFile = hf; + ha->dwBlockPos = dwBlockPos; + } + ha->dwBuffPos = 0; + + // Check number of bytes read + if(dwToCopy > dwToRead) + dwToCopy = dwToRead; + + memcpy(pbBuffer, ha->pbBlockBuffer, dwToCopy); + dwBytesRead += dwToCopy; + ha->dwBuffPos = dwToCopy; + } + + // Return what we've read + return dwBytesRead; +} + +//----------------------------------------------------------------------------- +// SFileReadFile + +// TODO: Test for archives > 4GB +BOOL WINAPI SFileReadFile(HANDLE hFile, VOID * lpBuffer, DWORD dwToRead, DWORD * pdwRead, LPOVERLAPPED lpOverlapped) +{ + TMPQFile * hf = (TMPQFile *)hFile; + DWORD dwBytes = 0; // Number of bytes (for everything) + int nError = ERROR_SUCCESS; + + // Zero the number of bytes read + if(pdwRead != NULL) + *pdwRead = 0; + + // Check valid parameters + if(nError == ERROR_SUCCESS) + { + if(hf == NULL || lpBuffer == NULL) + nError = ERROR_INVALID_PARAMETER; + } + + // If direct access to the file, use Win32 for reading + if(nError == ERROR_SUCCESS && hf->hFile != INVALID_HANDLE_VALUE) + { + DWORD dwTransferred; + + ReadFile(hf->hFile, lpBuffer, dwToRead, &dwTransferred, lpOverlapped); + if(dwTransferred < dwToRead) + { + SetLastError(ERROR_HANDLE_EOF); + return FALSE; + } + + if(pdwRead != NULL) + *pdwRead = dwTransferred; + return TRUE; + } + + // Read all the bytes available in the buffer (If any) + if(nError == ERROR_SUCCESS) + { + if(dwToRead > 0) + { + dwBytes = ReadMPQFile(hf, hf->dwFilePos, (BYTE *)lpBuffer, dwToRead); + if(dwBytes == (DWORD)-1) + { + SetLastError(ERROR_CAN_NOT_COMPLETE); + return FALSE; + } + hf->ha->pLastFile = hf; + hf->dwFilePos += dwBytes; + } + if(pdwRead != NULL) + *pdwRead = dwBytes; + } + + // Check number of bytes read. If not OK, return FALSE. + if(dwBytes < dwToRead) + { + SetLastError(ERROR_HANDLE_EOF); + return FALSE; + } + return TRUE; +} + +//----------------------------------------------------------------------------- +// SFileGetFilePos +// +// Returns position of archive file in the archive (relative to begin of file) + +// TODO: Test for archives > 4GB +DWORD WINAPI SFileGetFilePos(HANDLE hFile, DWORD * pdwFilePosHigh) +{ + TMPQFile * hf = (TMPQFile *)hFile; + + if(pdwFilePosHigh != NULL) + *pdwFilePosHigh = 0; + + if(hf == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return (DWORD)-1; + } + + // If opened as plain file, ... + if(hf->hFile != INVALID_HANDLE_VALUE) + return 0; + + // If opened from archive, return file size + if(pdwFilePosHigh != NULL) + *pdwFilePosHigh = hf->MpqFilePos.HighPart; + return hf->MpqFilePos.LowPart; +} + +//----------------------------------------------------------------------------- +// SFileGetFileSize + +// TODO: Test for archives > 4GB +DWORD WINAPI SFileGetFileSize(HANDLE hFile, DWORD * pdwFileSizeHigh) +{ + TMPQFile * hf = (TMPQFile *)hFile; + + if(pdwFileSizeHigh != NULL) + *pdwFileSizeHigh = 0; + + if(hf == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return (DWORD)-1; + } + + // If opened as plain file, ... + if(hf->hFile != INVALID_HANDLE_VALUE) + return GetFileSize(hf->hFile, pdwFileSizeHigh); + + // If opened from archive, return file size + return hf->pBlock->dwFSize; +} + +// TODO: Test for archives > 4GB +DWORD WINAPI SFileSetFilePointer(HANDLE hFile, LONG lFilePos, LONG * pdwFilePosHigh, DWORD dwMethod) +{ + TMPQArchive * ha; + TMPQFile * hf = (TMPQFile *)hFile; + + if(hf == NULL || (pdwFilePosHigh != NULL && *pdwFilePosHigh != 0)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return (DWORD)-1; + } + + // If opened as plain file, call Win32 API + if(hf->hFile != INVALID_HANDLE_VALUE) + return SetFilePointer(hf->hFile, lFilePos, pdwFilePosHigh, dwMethod); + ha = hf->ha; + + switch(dwMethod) + { + case FILE_BEGIN: + // Cannot set pointer before begin of file + if(-lFilePos > (LONG)hf->dwFilePos) + hf->dwFilePos = 0; + else + hf->dwFilePos = lFilePos; + break; + + case FILE_CURRENT: + // Cannot set pointer before begin of file + if(-lFilePos > (LONG)hf->dwFilePos) + hf->dwFilePos = 0; + else + hf->dwFilePos += lFilePos; + break; + + case FILE_END: + // Cannot set file position before begin of file + if(-lFilePos >= (LONG)hf->pBlock->dwFSize) + hf->dwFilePos = 0; + else + hf->dwFilePos = hf->pBlock->dwFSize + lFilePos; + break; + + default: + return ERROR_INVALID_PARAMETER; + } + + if(hf == ha->pLastFile && (hf->dwFilePos & ~(ha->dwBlockSize - 1)) == ha->dwBlockPos) + ha->dwBuffPos = hf->dwFilePos & (ha->dwBlockSize - 1); + else + { + ha->pLastFile = NULL; + ha->dwBuffPos = 0; + } + + return hf->dwFilePos; +} + +//----------------------------------------------------------------------------- +// Tries to retrieve the file name + +static TID2Ext id2ext[] = +{ + {0x1A51504D, "mpq"}, // MPQ archive header ID ('MPQ\x1A') + {0x46464952, "wav"}, // WAVE header 'RIFF' + {0x324B4D53, "smk"}, // Old "Smacker Video" files 'SMK2' + {0x694B4942, "bik"}, // Bink video files (new) + {0x0801050A, "pcx"}, // PCX images used in Diablo I + {0x544E4F46, "fnt"}, // Font files used in Diablo II + {0x6D74683C, "html"}, // HTML ' 4GB +BOOL WINAPI SFileGetFileName(HANDLE hFile, char * szFileName) +{ + TMPQFile * hf = (TMPQFile *)hFile; // MPQ File handle + char * szExt = "xxx"; // Default extension + DWORD dwFirstBytes[2]; // The first 4 bytes of the file + DWORD dwFilePos; // Saved file position + int nError = ERROR_SUCCESS; + int i; + + // Pre-zero the output buffer + if(szFileName != NULL) + *szFileName = 0; + + // Check valid parameters + if(nError == ERROR_SUCCESS) + { + if(hf == NULL || szFileName == NULL) + nError = ERROR_INVALID_PARAMETER; + } + + // If the file name is already filled, return it. + if(nError == ERROR_SUCCESS && *hf->szFileName != 0) + { + if(szFileName != hf->szFileName) + strcpy(szFileName, hf->szFileName); + return TRUE; + } + + if(nError == ERROR_SUCCESS) + { + if(hf->dwFileIndex == (DWORD)-1) + nError = ERROR_CAN_NOT_COMPLETE; + } + + // Read the first 8 bytes from the file + if(nError == ERROR_SUCCESS) + { + dwFirstBytes[0] = dwFirstBytes[1] = 0; + dwFilePos = SFileSetFilePointer(hf, 0, NULL, FILE_CURRENT); + if(!SFileReadFile(hFile, &dwFirstBytes, sizeof(dwFirstBytes), NULL)) + nError = GetLastError(); + BSWAP_ARRAY32_UNSIGNED(dwFirstBytes, sizeof(dwFirstBytes) / sizeof(DWORD)); + SFileSetFilePointer(hf, dwFilePos, NULL, FILE_BEGIN); + } + + if(nError == ERROR_SUCCESS) + { + if((dwFirstBytes[0] & 0x0000FFFF) == ID_EXE) + szExt = "exe"; + else if(dwFirstBytes[0] == 0x00000006 && dwFirstBytes[1] == 0x00000001) + szExt = "dc6"; + else + { + for(i = 0; id2ext[i].szExt != NULL; i++) + { + if(id2ext[i].dwID == dwFirstBytes[0]) + { + szExt = id2ext[i].szExt; + break; + } + } + } + + // Create the file name + sprintf(hf->szFileName, "File%08lu.%s", hf->dwFileIndex, szExt); + if(szFileName != hf->szFileName) + strcpy(szFileName, hf->szFileName); + } + return (nError == ERROR_SUCCESS); +} + +//----------------------------------------------------------------------------- +// Retrieves an information about an archive or about a file within the archive +// +// hMpqOrFile - Handle to an MPQ archive or to a file +// dwInfoType - Information to obtain + +// TODO: Test for archives > 4GB +DWORD_PTR WINAPI SFileGetFileInfo(HANDLE hMpqOrFile, DWORD dwInfoType) +{ + TMPQArchive * ha = (TMPQArchive *)hMpqOrFile; + TMPQFile * hf = (TMPQFile *)hMpqOrFile; + TMPQBlock * pBlockEnd; + TMPQBlock * pBlock; + DWORD dwFileCount = 0; + DWORD dwSeed; + + switch(dwInfoType) + { + case SFILE_INFO_ARCHIVE_SIZE: + if(IsValidMpqHandle(ha)) + return ha->pHeader->dwArchiveSize; + break; + + case SFILE_INFO_HASH_TABLE_SIZE: // Size of the hash table + if(IsValidMpqHandle(ha)) + return ha->pHeader->dwHashTableSize; + break; + + case SFILE_INFO_BLOCK_TABLE_SIZE: // Size of the hash table + if(IsValidMpqHandle(ha)) + return ha->pHeader->dwBlockTableSize; + break; + + case SFILE_INFO_BLOCK_SIZE: + if(IsValidMpqHandle(ha)) + return ha->dwBlockSize; + break; + + case SFILE_INFO_HASH_TABLE: + if(IsValidMpqHandle(ha)) + return (DWORD_PTR)ha->pHashTable; + break; + + case SFILE_INFO_BLOCK_TABLE: + if(IsValidMpqHandle(ha)) + return (DWORD_PTR)ha->pBlockTable; + break; + + case SFILE_INFO_NUM_FILES: + if(IsValidMpqHandle(ha)) + { + pBlockEnd = ha->pBlockTable + ha->pHeader->dwBlockTableSize; + for(pBlock = ha->pBlockTable; pBlock < pBlockEnd; pBlock++) + { + if(pBlock->dwFlags & MPQ_FILE_EXISTS) + dwFileCount++; + } + return dwFileCount; + } + break; + + case SFILE_INFO_HASH_INDEX: + if(IsValidFileHandle(hf)) + return hf->dwHashIndex; + break; + + case SFILE_INFO_CODENAME1: + if(IsValidFileHandle(hf)) + return hf->pHash->dwName1; + break; + + case SFILE_INFO_CODENAME2: + if(IsValidFileHandle(hf)) + return hf->pHash->dwName2; + break; + + case SFILE_INFO_LOCALEID: + if(IsValidFileHandle(hf)) + return hf->pHash->lcLocale; + break; + + case SFILE_INFO_BLOCKINDEX: + if(IsValidFileHandle(hf)) + return hf->dwFileIndex; + break; + + case SFILE_INFO_FILE_SIZE: + if(IsValidFileHandle(hf)) + return hf->pBlock->dwFSize; + break; + + case SFILE_INFO_COMPRESSED_SIZE: + if(IsValidFileHandle(hf)) + return hf->pBlock->dwCSize; + break; + + case SFILE_INFO_FLAGS: + if(IsValidFileHandle(hf)) + return hf->pBlock->dwFlags; + break; + + case SFILE_INFO_POSITION: + if(IsValidFileHandle(hf)) + return hf->pBlock->dwFilePos; + break; + + case SFILE_INFO_SEED: + if(IsValidFileHandle(hf)) + return hf->dwSeed1; + break; + + case SFILE_INFO_SEED_UNFIXED: + if(IsValidFileHandle(hf)) + { + dwSeed = hf->dwSeed1; + if(hf->pBlock->dwFlags & MPQ_FILE_FIXSEED) + dwSeed = (dwSeed ^ hf->pBlock->dwFSize) - (DWORD)(hf->MpqFilePos.QuadPart - hf->ha->MpqPos.QuadPart); + return dwSeed; + } + break; + } + + // Unknown parameter or invalid handle + SetLastError(ERROR_INVALID_PARAMETER); + return 0xFFFFFFFF; +} diff --git a/contrib/vmap_extractor_v2/stormlib/SListFile.cpp b/contrib/vmap_extractor_v2/stormlib/SListFile.cpp new file mode 100644 index 00000000000..c3723d17dcd --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/SListFile.cpp @@ -0,0 +1,561 @@ +/*****************************************************************************/ +/* SListFile.cpp Copyright (c) Ladislav Zezula 2004 */ +/*---------------------------------------------------------------------------*/ +/* Description: */ +/*---------------------------------------------------------------------------*/ +/* Date Ver Who Comment */ +/* -------- ---- --- ------- */ +/* 12.06.04 1.00 Lad The first version of SListFile.cpp */ +/*****************************************************************************/ + +#define __STORMLIB_SELF__ +#include "StormLib.h" +#include "SCommon.h" +#include + +//----------------------------------------------------------------------------- +// Listfile entry structure + +#define LISTFILE_CACHE_SIZE 0x1000 // Size of one cache element +#define NO_MORE_CHARACTERS 256 +#define HASH_TABLE_SIZE 31 // Initial hash table size (should be a prime number) + +// TODO: Check on x64 !!! +#define LISTFILE_ENTRY_DELETED (DWORD_PTR)(-2) +#define LISTFILE_ENTRY_FREE (DWORD_PTR)(-1) + +struct TListFileCache +{ + HANDLE hFile; // Stormlib file handle + char * szMask; // File mask + DWORD dwFileSize; // Total size of the cached file + DWORD dwBuffSize; // File of the cache + DWORD dwFilePos; // Position of the cache in the file + BYTE * pBegin; // The begin of the listfile cache + BYTE * pPos; + BYTE * pEnd; // The last character in the file cache + + BYTE Buffer[1]; // Listfile cache itself +}; + +//----------------------------------------------------------------------------- +// Local functions (cache) + +// Reloads the cache. Returns number of characters +// that has been loaded into the cache. +static int ReloadCache(TListFileCache * pCache) +{ + // Check if there is enough characters in the cache + // If not, we have to reload the next block + if(pCache->pPos >= pCache->pEnd) + { + // If the cache is already at the end, do nothing more + if((pCache->dwFilePos + pCache->dwBuffSize) >= pCache->dwFileSize) + return 0; + + pCache->dwFilePos += pCache->dwBuffSize; + SFileReadFile(pCache->hFile, pCache->Buffer, pCache->dwBuffSize, &pCache->dwBuffSize, NULL); + if(pCache->dwBuffSize == 0) + return 0; + + // Set the buffer pointers + pCache->pBegin = + pCache->pPos = &pCache->Buffer[0]; + pCache->pEnd = pCache->pBegin + pCache->dwBuffSize; + } + + return pCache->dwBuffSize; +} + +static size_t ReadLine(TListFileCache * pCache, char * szLine, int nMaxChars) +{ + char * szLineBegin = szLine; + char * szLineEnd = szLine + nMaxChars - 1; + +__BeginLoading: + + // Skip newlines, spaces, tabs and another non-printable stuff + while(pCache->pPos < pCache->pEnd && *pCache->pPos <= 0x20) + pCache->pPos++; + + // Copy the remaining characters + while(pCache->pPos < pCache->pEnd && szLine < szLineEnd) + { + // If we have found a newline, stop loading + if(*pCache->pPos == 0x0D || *pCache->pPos == 0x0A) + break; + + *szLine++ = *pCache->pPos++; + } + + // If we now need to reload the cache, do it + if(pCache->pPos == pCache->pEnd) + { + if(ReloadCache(pCache) > 0) + goto __BeginLoading; + } + + *szLine = 0; + return (szLine - szLineBegin); +} + +//----------------------------------------------------------------------------- +// Local functions (listfile nodes) + +// This function creates the name for the listfile. +// the file will be created under unique name in the temporary directory +static void GetListFileName(TMPQArchive * /* ha */, char * szListFile) +{ + char szTemp[MAX_PATH]; + + // Create temporary file name int TEMP directory + GetTempPath(sizeof(szTemp)-1, szTemp); + GetTempFileName(szTemp, LISTFILE_NAME, 0, szListFile); +} + +// Creates new listfile. The listfile is an array of TListFileNode +// structures. The size of the array is the same like the hash table size, +// the ordering is the same too (listfile item index is the same like +// the index in the MPQ hash table) + +int SListFileCreateListFile(TMPQArchive * ha) +{ + DWORD dwItems = ha->pHeader->dwHashTableSize; + + // The listfile should be NULL now + assert(ha->pListFile == NULL); + + ha->pListFile = ALLOCMEM(TFileNode *, dwItems); + if(ha->pListFile == NULL) + return ERROR_NOT_ENOUGH_MEMORY; + + memset(ha->pListFile, 0xFF, dwItems * sizeof(TFileNode *)); + return ERROR_SUCCESS; +} + +// Adds a filename into the listfile. If the file name is already there, +// does nothing. +int SListFileAddNode(TMPQArchive * ha, const char * szFileName) +{ + TFileNode * pNode = NULL; + TMPQHash * pHashEnd = ha->pHashTable + ha->pHeader->dwHashTableSize; + TMPQHash * pHash0 = GetHashEntry(ha, szFileName); + TMPQHash * pHash = pHash0; + DWORD dwHashIndex = 0; + size_t nLength; // File name lentgth + DWORD dwName1; + DWORD dwName2; + + // If the file does not exist within the MPQ, do nothing + if(pHash == NULL) + return ERROR_SUCCESS; + + // If the listfile entry already exists, do nothing + dwHashIndex = (DWORD)(pHash - ha->pHashTable); + dwName1 = pHash->dwName1; + dwName2 = pHash->dwName2; + if((DWORD_PTR)ha->pListFile[dwHashIndex] <= LISTFILE_ENTRY_DELETED) + return ERROR_SUCCESS; + + // Create the listfile node and insert it into the listfile table + nLength = strlen(szFileName); + pNode = (TFileNode *)ALLOCMEM(char, sizeof(TFileNode) + nLength); + pNode->dwRefCount = 0; + pNode->nLength = nLength; + strcpy(pNode->szFileName, szFileName); + + // Fill the nodes for all language versions + while(pHash->dwBlockIndex < LISTFILE_ENTRY_DELETED) + { + if(pHash->dwName1 == dwName1 && pHash->dwName2 == dwName2) + { + pNode->dwRefCount++; + ha->pListFile[pHash - ha->pHashTable] = pNode; + } + + if(++pHash >= pHashEnd) + pHash = ha->pHashTable; + if(pHash == pHash0) + break; + } + + return ERROR_SUCCESS; +} + +// Removes a filename from the listfile. +// If the name is not there, does nothing +int SListFileRemoveNode(TMPQArchive * ha, const char * szFileName) +{ + TFileNode * pNode = NULL; + TMPQHash * pHash = GetHashEntry(ha, szFileName); + size_t nHashIndex = 0; + + if(pHash != NULL) + { + nHashIndex = pHash - ha->pHashTable; + pNode = ha->pListFile[nHashIndex]; + ha->pListFile[nHashIndex] = (TFileNode *)LISTFILE_ENTRY_DELETED; + + // If the reference count has reached zero, do nothing + if(--pNode->dwRefCount == 0) + FREEMEM(pNode); + } + return ERROR_SUCCESS; +} + + +// Renames a node. We will not deal with the renaming, we'll simply +// remove the old node and insert the new one. +// TODO: Test for archives > 4GB +int SListFileRenameNode(TMPQArchive * ha, const char * szOldFileName, const char * szNewFileName) +{ + SListFileRemoveNode(ha, szOldFileName); + return SListFileAddNode(ha, szNewFileName); +} + +// TODO: Test for archives > 4GB +int SListFileFreeListFile(TMPQArchive * ha) +{ + if(ha->pListFile != NULL) + { + for(DWORD i = 0; i < ha->pHeader->dwHashTableSize; i++) + { + TFileNode * pNode = ha->pListFile[i]; + + if((DWORD_PTR)pNode < LISTFILE_ENTRY_FREE) + { + if(--pNode->dwRefCount == 0) + { + FREEMEM(pNode); + ha->pListFile[i] = (TFileNode *)LISTFILE_ENTRY_FREE; + } + } + } + + FREEMEM(ha->pListFile); + ha->pListFile = NULL; + } + + return ERROR_SUCCESS; +} + +// Saves the whole listfile into the MPQ. +// TODO: Test for archives > 4GB +int SListFileSaveToMpq(TMPQArchive * ha) +{ + TFileNode * pNode = NULL; + TMPQHash * pHashEnd = NULL; + TMPQHash * pHash0 = NULL; + TMPQHash * pHash = NULL; + HANDLE hFile = INVALID_HANDLE_VALUE; + char szListFile[MAX_PATH]; + char szBuffer[MAX_PATH+4]; + DWORD dwTransferred; + size_t nLength = 0; + DWORD dwName1 = 0; + DWORD dwName2 = 0; + LCID lcSave = lcLocale; + int nError = ERROR_SUCCESS; + + // If no listfile, do nothing + if(ha->pListFile == NULL) + return ERROR_SUCCESS; + + // Create the local listfile + if(nError == ERROR_SUCCESS) + { + GetListFileName(ha, szListFile); + hFile = CreateFile(szListFile, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL); + if(hFile == INVALID_HANDLE_VALUE) + nError = GetLastError(); + } + + // Find the hash entry corresponding to listfile + pHashEnd = ha->pHashTable + ha->pHeader->dwHashTableSize; + pHash0 = pHash = GetHashEntry(ha, 0); + if(pHash == NULL) + pHash0 = pHash = ha->pHashTable; + + // Save the file + if(nError == ERROR_SUCCESS) + { + for(;;) + { + if(pHash->dwName1 != dwName1 && pHash->dwName2 != dwName2 && pHash->dwBlockIndex < LISTFILE_ENTRY_DELETED) + { + dwName1 = pHash->dwName1; + dwName2 = pHash->dwName2; + pNode = ha->pListFile[pHash - ha->pHashTable]; + + if((DWORD_PTR)pNode < LISTFILE_ENTRY_DELETED) + { + memcpy(szBuffer, pNode->szFileName, pNode->nLength); + szBuffer[pNode->nLength + 0] = 0x0D; + szBuffer[pNode->nLength + 1] = 0x0A; + WriteFile(hFile, szBuffer, (DWORD)(pNode->nLength + 2), &dwTransferred, NULL); + } + } + + if(++pHash >= pHashEnd) + pHash = ha->pHashTable; + if(pHash == pHash0) + break; + } + + // Write the listfile name (if not already there) + if(GetHashEntry(ha, LISTFILE_NAME) == NULL) + { + nLength = strlen(LISTFILE_NAME); + memcpy(szBuffer, LISTFILE_NAME, nLength); + szBuffer[nLength + 0] = 0x0D; + szBuffer[nLength + 1] = 0x0A; + WriteFile(hFile, szBuffer, (DWORD)(nLength + 2), &dwTransferred, NULL); + } + + // Add the listfile into the archive. + SFileSetLocale(LANG_NEUTRAL); + nError = AddFileToArchive(ha, hFile, LISTFILE_NAME, MPQ_FILE_COMPRESS_PKWARE | MPQ_FILE_ENCRYPTED | MPQ_FILE_REPLACEEXISTING, 0, SFILE_TYPE_DATA, NULL); + } + + // Close the temporary file. This will delete it too. + if(hFile != INVALID_HANDLE_VALUE) + CloseHandle(hFile); + + lcLocale = lcSave; + return nError; +} + +//----------------------------------------------------------------------------- +// File functions + +// Adds a listfile into the MPQ archive. +// Note that the function does not remove the +// TODO: Test for archives > 4GB +int WINAPI SFileAddListFile(HANDLE hMpq, const char * szListFile) +{ + TListFileCache * pCache = NULL; + TMPQArchive * ha = (TMPQArchive *)hMpq; + HANDLE hListFile = NULL; + char szFileName[MAX_PATH + 1]; + DWORD dwSearchScope = SFILE_OPEN_LOCAL_FILE; + DWORD dwCacheSize = 0; + DWORD dwFileSize = 0; + size_t nLength = 0; + int nError = ERROR_SUCCESS; + + // If the szListFile is NULL, it means we have to open internal listfile + if(szListFile == NULL) + { + szListFile = LISTFILE_NAME; + dwSearchScope = SFILE_OPEN_FROM_MPQ; + } + + // Open the local/internal listfile + if(nError == ERROR_SUCCESS) + { + if(!SFileOpenFileEx((HANDLE)ha, szListFile, dwSearchScope, &hListFile)) + nError = GetLastError(); + } + + if(nError == ERROR_SUCCESS) + { + dwCacheSize = + dwFileSize = SFileGetFileSize(hListFile, NULL); + + // Try to allocate memory for the complete file. If it fails, + // load the part of the file + pCache = (TListFileCache *)ALLOCMEM(char, (sizeof(TListFileCache) + dwCacheSize)); + if(pCache == NULL) + { + dwCacheSize = LISTFILE_CACHE_SIZE; + pCache = (TListFileCache *)ALLOCMEM(char, sizeof(TListFileCache) + dwCacheSize); + } + + if(pCache == NULL) + nError = ERROR_NOT_ENOUGH_MEMORY; + } + + if(nError == ERROR_SUCCESS) + { + // Initialize the file cache + memset(pCache, 0, sizeof(TListFileCache)); + pCache->hFile = hListFile; + pCache->dwFileSize = dwFileSize; + pCache->dwBuffSize = dwCacheSize; + pCache->dwFilePos = 0; + + // Fill the cache + SFileReadFile(hListFile, pCache->Buffer, pCache->dwBuffSize, &pCache->dwBuffSize, NULL); + + // Initialize the pointers + pCache->pBegin = + pCache->pPos = &pCache->Buffer[0]; + pCache->pEnd = pCache->pBegin + pCache->dwBuffSize; + + // Load the node tree + while((nLength = ReadLine(pCache, szFileName, sizeof(szFileName) - 1)) > 0) + SListFileAddNode(ha, szFileName); + + // Add well-known names + // Sometimes, they are not in listfile, but they exist in the archive + SListFileAddNode(ha, LISTFILE_NAME); + SListFileAddNode(ha, SIGNATURE_NAME); + SListFileAddNode(ha, ATTRIBUTES_NAME); + } + + // Cleanup & exit + if(pCache != NULL) + SListFileFindClose((HANDLE)pCache); + return nError; +} + +//----------------------------------------------------------------------------- +// Passing through the listfile + +// TODO: Test for archives > 4GB +HANDLE SListFileFindFirstFile(HANDLE hMpq, const char * szListFile, const char * szMask, SFILE_FIND_DATA * lpFindFileData) +{ + TListFileCache * pCache = NULL; + TMPQArchive * ha = (TMPQArchive *)hMpq; + HANDLE hListFile = NULL; + DWORD dwSearchScope = SFILE_OPEN_LOCAL_FILE; + DWORD dwCacheSize = 0; + DWORD dwFileSize = 0; + size_t nLength = 0; + int nError = ERROR_SUCCESS; + + // Initialize the structure with zeros + memset(lpFindFileData, 0, sizeof(SFILE_FIND_DATA)); + + // If the szListFile is NULL, it means we have to open internal listfile + if(szListFile == NULL) + { + szListFile = LISTFILE_NAME; + dwSearchScope = SFILE_OPEN_FROM_MPQ; + } + + // Open the local/internal listfile + if(nError == ERROR_SUCCESS) + { + if(!SFileOpenFileEx((HANDLE)ha, szListFile, dwSearchScope, &hListFile)) + nError = GetLastError(); + } + + if(nError == ERROR_SUCCESS) + { + dwCacheSize = + dwFileSize = SFileGetFileSize(hListFile, NULL); + + // Try to allocate memory for the complete file. If it fails, + // load the part of the file + pCache = (TListFileCache *)ALLOCMEM(char, sizeof(TListFileCache) + dwCacheSize); + if(pCache == NULL) + { + dwCacheSize = LISTFILE_CACHE_SIZE; + pCache = (TListFileCache *)ALLOCMEM(char, sizeof(TListFileCache) + dwCacheSize); + } + + if(pCache == NULL) + nError = ERROR_NOT_ENOUGH_MEMORY; + } + + if(nError == ERROR_SUCCESS) + { + // Initialize the file cache + memset(pCache, 0, sizeof(TListFileCache)); + pCache->hFile = hListFile; + pCache->dwFileSize = dwFileSize; + pCache->dwBuffSize = dwCacheSize; + pCache->dwFilePos = 0; + if(szMask != NULL) + { + pCache->szMask = ALLOCMEM(char, strlen(szMask) + 1); + strcpy(pCache->szMask, szMask); + } + + // Fill the cache + SFileReadFile(hListFile, pCache->Buffer, pCache->dwBuffSize, &pCache->dwBuffSize, NULL); + + // Initialize the pointers + pCache->pBegin = + pCache->pPos = &pCache->Buffer[0]; + pCache->pEnd = pCache->pBegin + pCache->dwBuffSize; + + for(;;) + { + // Read the (next) line + nLength = ReadLine(pCache, lpFindFileData->cFileName, sizeof(lpFindFileData->cFileName)); + if(nLength == 0) + { + nError = ERROR_NO_MORE_FILES; + break; + } + + // If some mask entered, check it + if(CheckWildCard(lpFindFileData->cFileName, pCache->szMask)) + break; + } + } + + // Cleanup & exit + if(nError != ERROR_SUCCESS) + { + memset(lpFindFileData, 0, sizeof(SFILE_FIND_DATA)); + SListFileFindClose((HANDLE)pCache); + pCache = NULL; + + SetLastError(nError); + } + return (HANDLE)pCache; +} + +// TODO: Test for archives > 4GB +BOOL SListFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData) +{ + TListFileCache * pCache = (TListFileCache *)hFind; + size_t nLength; + BOOL bResult = FALSE; + int nError = ERROR_SUCCESS; + + for(;;) + { + // Read the (next) line + nLength = ReadLine(pCache, lpFindFileData->cFileName, sizeof(lpFindFileData->cFileName)); + if(nLength == 0) + { + nError = ERROR_NO_MORE_FILES; + break; + } + + // If some mask entered, check it + if(CheckWildCard(lpFindFileData->cFileName, pCache->szMask)) + { + bResult = TRUE; + break; + } + } + + if(nError != ERROR_SUCCESS) + SetLastError(nError); + return bResult; +} + +// TODO: Test for archives > 4GB +BOOL SListFileFindClose(HANDLE hFind) +{ + TListFileCache * pCache = (TListFileCache *)hFind; + + if(pCache != NULL) + { + if(pCache->hFile != NULL) + SFileCloseFile(pCache->hFile); + if(pCache->szMask != NULL) + FREEMEM(pCache->szMask); + + FREEMEM(pCache); + return TRUE; + } + + return FALSE; +} + diff --git a/contrib/vmap_extractor_v2/stormlib/StormDll.h b/contrib/vmap_extractor_v2/stormlib/StormDll.h new file mode 100644 index 00000000000..6d67820a22f --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/StormDll.h @@ -0,0 +1,67 @@ +/*****************************************************************************/ +/* Storm.h Copyright Justin Olbrantz(Quantam) 2000 */ +/*---------------------------------------------------------------------------*/ +/* Storm Interface Library v1.0 for Windows */ +/* */ +/* Author : Justin Olbrantz(Quantam) */ +/* E-mail : omega@dragonfire.net */ +/* WWW : www.campaigncreations.com/starcraft/mpq2k/inside_mopaq/ */ +/*---------------------------------------------------------------------------*/ +/* Date Ver Who Comment */ +/* -------- ---- --- ------- */ +/* xx.xx.00 1.00 Qua The first version of Storm.h */ +/* 11.04.03 1.00 Lad Added some functions */ +/*****************************************************************************/ + +// We need the Windows data types for the Storm prototypes +#include + +#ifndef __STORM_H__ +#define __STORM_H__ + +// Somethimes is necessary to change the function names so they +// will not conflict with other MPQ tools. +#ifdef STORM_ALTERNATE_NAMES + #define SFILE(Name) Storm##Name + #define SCOMP(Name) Storm##Name +#else + #define SFILE(Name) SFile##Name + #define SCOMP(Name) SComp##Name +#endif + + +// Just in case anyone is still using C out there +#ifdef __cplusplus +extern "C" { +#endif + +// Storm file function prototypes +BOOL WINAPI SFILE(OpenArchive)(LPCSTR lpFileName, DWORD dwPriority, DWORD dwFlags, HANDLE *hMPQ); +BOOL WINAPI SFILE(CloseArchive)(HANDLE hMPQ); +BOOL WINAPI SFILE(GetArchiveName)(HANDLE hMPQ, LPCSTR lpBuffer, DWORD dwBufferLength); +BOOL WINAPI SFILE(OpenFile)(LPCSTR lpFileName, HANDLE *hFile); +BOOL WINAPI SFILE(OpenFileEx)(HANDLE hMPQ, LPCSTR lpFileName, DWORD dwSearchScope, HANDLE *hFile); +BOOL WINAPI SFILE(CloseFile)(HANDLE hFile); +DWORD WINAPI SFILE(GetFileSize)(HANDLE hFile, LPDWORD lpFileSizeHigh); +BOOL WINAPI SFILE(GetFileArchive)(HANDLE hFile, HANDLE *hMPQ); +BOOL WINAPI SFILE(GetFileName)(HANDLE hFile, LPCSTR lpBuffer, DWORD dwBufferLength); +DWORD WINAPI SFILE(SetFilePointer)(HANDLE hFile, long lDistanceToMove, PLONG lplDistanceToMoveHigh, DWORD dwMoveMethod); +BOOL WINAPI SFILE(ReadFile)(HANDLE hFile,LPVOID lpBuffer,DWORD nNumberOfBytesToRead,LPDWORD lpNumberOfBytesRead,LPOVERLAPPED lpOverlapped); +LCID WINAPI SFILE(SetLocale)(LCID nNewLocale); +BOOL WINAPI SFILE(GetBasePath)(LPCSTR lpBuffer, DWORD dwBufferLength); +BOOL WINAPI SFILE(SetBasePath)(LPCSTR lpNewBasePath); + +// Storm (de)compression functions +BOOL WINAPI SCOMP(Compress) (char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int uCmp, int uCmpType, int nCmpLevel); +BOOL WINAPI SCOMP(Decompress)(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength); + + +#if defined(_MSC_VER) && !defined(BUILDING_STORM_CPP) +#pragma comment(lib, "Storm.lib") // Force linking Storm.lib and thus Storm.dll +#endif + +#ifdef __cplusplus +} +#endif + +#endif // __STORM_H__ diff --git a/contrib/vmap_extractor_v2/stormlib/StormLib.h b/contrib/vmap_extractor_v2/stormlib/StormLib.h new file mode 100644 index 00000000000..eeb8daa6468 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/StormLib.h @@ -0,0 +1,579 @@ +/*****************************************************************************/ +/* StormLib.h Copyright (c) Ladislav Zezula 1999-2005 */ +/*---------------------------------------------------------------------------*/ +/* StormLib library v 5.00 */ +/* */ +/* Author : Ladislav Zezula */ +/* E-mail : ladik@zezula.net */ +/* WWW : http://www.zezula.net */ +/*---------------------------------------------------------------------------*/ +/* Date Ver Who Comment */ +/* -------- ---- --- ------- */ +/* xx.xx.99 1.00 Lad Created */ +/* 24.03.03 2.50 Lad Version 2.50 */ +/* 02.04.03 3.00 Lad Version 3.00 with compression */ +/* 11.04.03 3.01 Lad Renamed to StormLib.h for compatibility with */ +/* original headers for Storm.dll */ +/* 10.05.03 3.02 Lad Added Pkware DCL compression */ +/* 26.05.03 4.00 Lad Completed all compressions */ +/* 18.06.03 4.01 Lad Added SFileSetFileLocale */ +/* Added SFileExtractFile */ +/* 26.07.03 4.02 Lad Implemented nameless rename and delete */ +/* 26.07.03 4.03 Lad Added support for protected MPQs */ +/* 28.08.03 4.10 Lad Fixed bugs that caused StormLib incorrectly work */ +/* with Diablo I savegames and with files having full */ +/* hash table */ +/* 08.12.03 4.11 DCH Fixed bug in reading file block larger than 0x1000 */ +/* on certain files. */ +/* Fixed bug in AddFile with MPQ_FILE_REPLACE_EXISTING */ +/* (Thanx Daniel Chiamarello, dchiamarello@madvawes.com)*/ +/* 21.12.03 4.50 Lad Completed port for Mac */ +/* Fixed bug in compacting (if fsize is mul of 0x1000) */ +/* Fixed bug in SCompCompress */ +/* 27.05.04 4.51 Lad Changed memory management from new/delete to our */ +/* own macros */ +/* 22.06.04 4.60 Lad Optimized search. Support for multiple listfiles. */ +/* 30.09.04 4.61 Lad Fixed some bugs (Aaargh !!!) */ +/* Correctly works if HashTableSize > BlockTableSize */ +/* 29.12.04 4.70 Lad Fixed compatibility problem with MPQs from WoW */ +/* 14.07.05 5.00 Lad Added the BZLIB compression support */ +/* Added suport of files stored as single unit */ +/* 17.04.06 5.01 Lad Converted to MS Visual Studio 8.0 */ +/* Fixed issue with protected Warcraft 3 protected maps */ +/* 15.05.06 5.02 Lad Fixed issue with WoW 1.10+ */ +/* 07.09.06 5.10 Lad Fixed processing files longer than 2GB */ +/* 22.11.06 6.00 Lad Support for MPQ archives V2 */ +/*****************************************************************************/ + +#ifndef __STORMLIB_H_ +#define __STORMLIB_H_ + +#include "StormPort.h" + +//----------------------------------------------------------------------------- +// Use the apropriate library +// +// The library type is encoded in the library name as the following +// StormLibXYZ.lib +// +// X - D for Debug version, R for Release version +// Y - A for ANSI version, U for Unicode version (Unicode version does not exist yet) +// Z - S for static C library, D for multithreaded DLL C-library +// + +#if defined(_MSC_VER) && !defined (__STORMLIB_SELF__) + #ifdef _DEBUG // DEBUG VERSIONS + #ifdef _DLL + #pragma comment(lib, "StormLibDAD.lib") // Debug Ansi Dynamic version + #else + #pragma comment(lib, "StormLibDAS.lib") // Debug Ansi Static version + #endif + #else // RELEASE VERSIONS + #ifdef _DLL + #pragma comment(lib, "StormLibRAD.lib") // Release Ansi Dynamic version + #else + #pragma comment(lib, "StormLibRAS.lib") // Release Ansi Static version + #endif + #endif +#endif + +//----------------------------------------------------------------------------- +// Defines + +#define ID_MPQ 0x1A51504D // MPQ archive header ID ('MPQ\x1A') +#define ID_MPQ_SHUNT 0x1B51504D // MPQ shunt entry ('MPQ\x1B') + +#define ERROR_AVI_FILE 10000 // No MPQ file, but AVI file. + +// Values for SFileCreateArchiveEx +#define HASH_TABLE_SIZE_MIN 0x00002 +#define HASH_TABLE_SIZE_MAX 0x40000 + +#define HASH_ENTRY_DELETED 0xFFFFFFFE // Block index for deleted hash entry +#define HASH_ENTRY_FREE 0xFFFFFFFF // Block index for free hash entry + +// Values for SFileOpenArchive +#define SFILE_OPEN_HARD_DISK_FILE 2 // Open the archive on HDD +#define SFILE_OPEN_CDROM_FILE 3 // Open the archive only if it is on CDROM + +// Values for SFileOpenFile +#define SFILE_OPEN_FROM_MPQ 0 // Open the file from the MPQ archive +#define SFILE_OPEN_BY_INDEX 1 // The 'szFileName' parameter is actually the file index +#define SFILE_OPEN_LOCAL_FILE (DWORD)-1 // Open the file from the MPQ archive + +// Flags for TMPQArchive::dwFlags +#define MPQ_FLAG_CHANGED 0x00000001 // If set, the MPQ has been changed +#define MPQ_FLAG_PROTECTED 0x00000002 // Set on protected MPQs (like W3M maps) + +// Flags for SFileAddFile +#define MPQ_FILE_COMPRESS_PKWARE 0x00000100 // Compression made by PKWARE Data Compression Library +#define MPQ_FILE_COMPRESS_MULTI 0x00000200 // Multiple compressions +#define MPQ_FILE_COMPRESSED 0x0000FF00 // File is compressed +#define MPQ_FILE_ENCRYPTED 0x00010000 // Indicates whether file is encrypted +#define MPQ_FILE_FIXSEED 0x00020000 // File decrypt seed has to be fixed +#define MPQ_FILE_SINGLE_UNIT 0x01000000 // File is stored as a single unit, rather than split into sectors (Thx, Quantam) +#define MPQ_FILE_DUMMY_FILE 0x02000000 // The file is only 1 byte long and its name is a hash +#define MPQ_FILE_HAS_EXTRA 0x04000000 // The file has extra data appended after regular data. + // Must be with compressed files only +#define MPQ_FILE_EXISTS 0x80000000 // Set if file exists, reset when the file was deleted +#define MPQ_FILE_REPLACEEXISTING 0x80000000 // Replace when the file exist (SFileAddFile) + +#define MPQ_FILE_VALID_FLAGS (MPQ_FILE_COMPRESS_PKWARE | \ + MPQ_FILE_COMPRESS_MULTI | \ + MPQ_FILE_ENCRYPTED | \ + MPQ_FILE_FIXSEED | \ + MPQ_FILE_SINGLE_UNIT | \ + MPQ_FILE_DUMMY_FILE | \ + MPQ_FILE_HAS_EXTRA | \ + MPQ_FILE_EXISTS) + +// Compression types for multilpe compressions +#define MPQ_COMPRESSION_HUFFMANN 0x01 // Huffmann compression (used on WAVE files only) +#define MPQ_COMPRESSION_ZLIB 0x02 // ZLIB compression +#define MPQ_COMPRESSION_PKWARE 0x08 // PKWARE DCL compression +#define MPQ_COMPRESSION_BZIP2 0x10 // BZIP2 compression +#define MPQ_COMPRESSION_WAVE_MONO 0x40 // +#define MPQ_COMPRESSION_WAVE_STEREO 0x80 // + + +// Constants for SFileAddWave +#define MPQ_WAVE_QUALITY_HIGH 0 // Best quality, the worst compression +#define MPQ_WAVE_QUALITY_MEDIUM 1 // Medium quality, medium compression +#define MPQ_WAVE_QUALITY_LOW 2 // Low quality, the best compression + +// Constants for SFileGetFileInfo +#define SFILE_INFO_ARCHIVE_SIZE 1 // MPQ size (value from header) +#define SFILE_INFO_HASH_TABLE_SIZE 2 // Size of hash table, in entries +#define SFILE_INFO_BLOCK_TABLE_SIZE 3 // Number of entries in the block table +#define SFILE_INFO_BLOCK_SIZE 4 // Size of file block (in bytes) +#define SFILE_INFO_HASH_TABLE 5 // Pointer to Hash table (TMPQHash *) +#define SFILE_INFO_BLOCK_TABLE 6 // Pointer to Block Table (TMPQBlock *) +#define SFILE_INFO_NUM_FILES 7 // Real number of files within archive +//------ +#define SFILE_INFO_HASH_INDEX 8 // Hash index of file in MPQ +#define SFILE_INFO_CODENAME1 9 // The first codename of the file +#define SFILE_INFO_CODENAME2 10 // The second codename of the file +#define SFILE_INFO_LOCALEID 11 // Locale ID of file in MPQ +#define SFILE_INFO_BLOCKINDEX 12 // Index to Block Table +#define SFILE_INFO_FILE_SIZE 13 // Original file size +#define SFILE_INFO_COMPRESSED_SIZE 14 // Compressed file size +#define SFILE_INFO_FLAGS 15 // File flags +#define SFILE_INFO_POSITION 16 // File position within archive +#define SFILE_INFO_SEED 17 // File decryption seed +#define SFILE_INFO_SEED_UNFIXED 18 // Decryption seed not fixed to file pos and size + +// Values for compact callback +#define CCB_CHECKING_FILES 1 // Checking archive (dwParam1 = current, dwParam2 = total) +#define CCB_CHECKING_HASH_TABLE 2 // Checking hash table (dwParam1 = current, dwParam2 = total) +#define CCB_COPYING_NON_MPQ_DATA 3 // Copying non-MPQ data: No params used +#define CCB_COMPACTING_FILES 4 // Compacting archive (dwParam1 = current, dwParam2 = total) +#define CCB_CLOSING_ARCHIVE 5 // Closing archive: No params used + +#define LISTFILE_NAME "(listfile)" // Name of internal listfile +#define SIGNATURE_NAME "(signature)" // Name of internal signature +#define ATTRIBUTES_NAME "(attributes)" // Name of internal attributes file + +#define STORMLIB_VERSION (0x0600) // Current version of StormLib + +#define MPQ_FORMAT_VERSION_1 0 // Up to The Burning Crusade +#define MPQ_FORMAT_VERSION_2 1 // The Burning Crusade and newer, + +// Flags for SFileOpenArchiveEx +#define MPQ_OPEN_NO_LISTFILE 0x00000001 // Don't add the internal listfile + +// supports archives with size > 4 GB +// Additional flags for SFileCreateArchiveEx +#define MPQ_CREATE_ARCHIVE_V1 0x00000000 // Creates archive with size up to 4GB +#define MPQ_CREATE_ARCHIVE_V2 0x00010000 // Creates archive larger than 4 GB + +//----------------------------------------------------------------------------- +// Structures + +#if (defined(WIN32) || defined(WIN64)) +#include +#else +#pragma pack(1) +#endif + +struct TMPQFile; + +struct TMPQShunt +{ + // The ID_MPQ_SHUNT ('MPQ\x1B') signature + DWORD dwID; + + DWORD dwUnknown; + + // Position of the MPQ header, relative to the begin of the shunt + DWORD dwHeaderPos; +}; + + +// MPQ file header +struct TMPQHeader +{ + // The ID_MPQ ('MPQ\x1A') signature + DWORD dwID; + + // Size of the archive header + DWORD dwHeaderSize; + + // Size of MPQ archive + // This field is deprecated in the Burning Crusade MoPaQ format, and the size of the archive + // is calculated as the size from the beginning of the archive to the end of the hash table, + // block table, or extended block table (whichever is largest). + DWORD dwArchiveSize; + + // 0 = Original format + // 1 = Extended format (The Burning Crusade and newer) + USHORT wFormatVersion; + + // Power of two exponent specifying the number of 512-byte disk sectors in each logical sector + // in the archive. The size of each logical sector in the archive is 512 * 2^SectorSizeShift. + // Bugs in the Storm library dictate that this should always be 3 (4096 byte sectors). + USHORT wBlockSize; + + // Offset to the beginning of the hash table, relative to the beginning of the archive. + DWORD dwHashTablePos; + + // Offset to the beginning of the block table, relative to the beginning of the archive. + DWORD dwBlockTablePos; + + // Number of entries in the hash table. Must be a power of two, and must be less than 2^16 for + // the original MoPaQ format, or less than 2^20 for the Burning Crusade format. + DWORD dwHashTableSize; + + // Number of entries in the block table + DWORD dwBlockTableSize; +}; + + +// Extended MPQ file header. Valid only if wFormatVersion is 1 or higher +struct TMPQHeader2 : public TMPQHeader +{ + // Offset to the beginning of the extended block table, relative to the beginning of the archive. + LARGE_INTEGER ExtBlockTablePos; + + // High 16 bits of the hash table offset for large archives. + USHORT wHashTablePosHigh; + + // High 16 bits of the block table offset for large archives. + USHORT wBlockTablePosHigh; +}; + + +// Hash entry. All files in the archive are searched by their hashes. +struct TMPQHash +{ + // The hash of the file path, using method A. + DWORD dwName1; + + // The hash of the file path, using method B. + DWORD dwName2; + +#ifdef PLATFORM_LITTLE_ENDIAN + + // The language of the file. This is a Windows LANGID data type, and uses the same values. + // 0 indicates the default language (American English), or that the file is language-neutral. + USHORT lcLocale; + + // The platform the file is used for. 0 indicates the default platform. + // No other values have been observed. + USHORT wPlatform; + +#else + + USHORT wPlatform; + USHORT lcLocale; + +#endif + + // If the hash table entry is valid, this is the index into the block table of the file. + // Otherwise, one of the following two values: + // - FFFFFFFFh: Hash table entry is empty, and has always been empty. + // Terminates searches for a given file. + // - FFFFFFFEh: Hash table entry is empty, but was valid at some point (a deleted file). + // Does not terminate searches for a given file. + DWORD dwBlockIndex; +}; + + +// File description block contains informations about the file +struct TMPQBlock +{ + // Offset of the beginning of the block, relative to the beginning of the archive. + DWORD dwFilePos; + + // Compressed file size + DWORD dwCSize; + + // Only valid if the block is a file; otherwise meaningless, and should be 0. + // If the file is compressed, this is the size of the uncompressed file data. + DWORD dwFSize; + + // Flags for the file. See MPQ_FILE_XXXX constants + DWORD dwFlags; +}; + + +// The extended block table was added to support archives larger than 4 gigabytes (2^32 bytes). +// The table contains the upper bits of the archive offsets for each block in the block table. +// It is simply an array of int16s, which become bits 32-47 of the archive offsets for each block, +// with bits 48-63 being zero. Individual blocks in the archive are still limited to 4 gigabytes +// in size. This table is only present in Burning Crusade format archives that exceed 4 gigabytes size. +struct TMPQBlockEx +{ + USHORT wFilePosHigh; +}; + + +struct TFileNode +{ + DWORD dwRefCount; // Number of references + // There can be more files that have the same name. + // (e.g. multiple language files). We don't want to + // have an entry for each of them, so the entries will be referenced. + // When a number of node references reaches zero, + // the node will be deleted + + size_t nLength; // File name length + char szFileName[1]; // File name, variable length +}; + +#if (defined(WIN32) || defined(WIN64)) +#include +#else +#pragma options align=reset +#endif + +// Archive handle structure. Note that it does not agree with Storm.dll's structure. +struct TMPQArchive +{ +// TMPQArchive * pNext; // Next archive (used by Storm.dll only) +// TMPQArchive * pPrev; // Previous archive (used by Storm.dll only) + char szFileName[MAX_PATH]; // Opened archive file name + HANDLE hFile; // File handle + DWORD dwPriority; // Priority of the archive + LARGE_INTEGER ShuntPos; // Position of MPQShunt (only valid if a shunt is present) + LARGE_INTEGER MpqPos; // MPQ position in the file, relative to the begin of the file + LARGE_INTEGER MpqSize; // Size of MPQ archive + LARGE_INTEGER HashTablePos; // Offset of the hast table in the MPQ, relative to the begin of the file + LARGE_INTEGER BlockTablePos; // Offset of the hast table in the MPQ, relative to the begin + LARGE_INTEGER ExtBlockTablePos; // Offset of the extended block table, relative to the begin + LARGE_INTEGER FilePointer; // Current position in the file (relative to begin of the file) + + TMPQFile * pLastFile; // Recently read file + DWORD dwBlockPos; // Position of loaded block in the file + DWORD dwBlockSize; // Size of file block + BYTE * pbBlockBuffer; // Buffer (cache) for file block + DWORD dwBuffPos; // Position in block buffer + TMPQShunt * pShunt; // MPQ shunt (NULL if not present in the file) + TMPQHeader2 * pHeader; // MPQ file header + TMPQHash * pHashTable; // Hash table + TMPQBlock * pBlockTable; // Block table + TMPQBlockEx * pExtBlockTable; // Extended block table + + TMPQShunt Shunt; // MPQ shunt. Valid only when ID_MPQ_SHUNT has been found + TMPQHeader2 Header; // MPQ header + + // Non-Storm.dll members + TFileNode ** pListFile; // File name array +// HANDLE hListFile; // Handle to temporary listfile (when open with write access) + DWORD dwFlags; // See MPQ_FLAG_XXXXX +// BOOL bChanged; // TRUE if the archive was changed since open. +// BOOL bProtected; // TRUE if the archive is protected by somehow +}; + + +// File handle structure. Note that it does not agree with Storm.dll structures +struct TMPQFile +{ + HANDLE hFile; // File handle + TMPQArchive * ha; // Archive handle + TMPQHash * pHash; // Hash table entry + TMPQBlockEx * pBlockEx; // Pointer to extended file block entry + TMPQBlock * pBlock; // File block pointer + DWORD dwSeed1; // Seed used for file decrypt + DWORD dwFilePos; // Current file position + LARGE_INTEGER MpqFilePos; // Position of the file data in MPQ archive + // (relative to file begin) + + DWORD * pdwBlockPos; // Position of each file block (only for compressed files) + DWORD nBlocks; // Number of blocks in the file (incl. the last noncomplete one) + BOOL bBlockPosLoaded; // TRUE if block positions loaded + BYTE * pbFileBuffer; // Decompressed file (for single unit files, size is the uncompressed file size) + + DWORD dwHashIndex; // Index to Hash table + DWORD dwFileIndex; // Index to Block table + char szFileName[1]; // File name (variable length) +}; + + +// Used by searching in MPQ archives +struct TMPQSearch +{ + TMPQArchive * ha; // Handle to MPQ, where the search runs + DWORD dwNextIndex; // The next searched hash index + DWORD dwName1; // Lastly found Name1 + DWORD dwName2; // Lastly found Name2 + char szSearchMask[1]; // Search mask (variable length) +}; + + +struct SFILE_FIND_DATA +{ + char cFileName[MAX_PATH]; // Full name of the found file + char * szPlainName; // Pointer to file part + LCID lcLocale; // Locale version + DWORD dwFileSize; // File size in bytes + DWORD dwFileFlags; // File flags (compressed or encrypted) + DWORD dwBlockIndex; // Block index for the file + DWORD dwCompSize; // Compressed file size +}; + +//----------------------------------------------------------------------------- +// Memory management +// +// We use our own macros for allocating/freeing memory. If you want +// to redefine them, please keep the following rules +// +// - The memory allocation must return NULL if not enough memory +// (i.e not to throw exception) +// - It is not necessary to fill the allocated block with zeros +// - Memory freeing function must not test the pointer to NULL. +// + + +__inline void * DebugMalloc(char * szFile, int nLine, int nSize) +{ + void * ptr = malloc(nSize + 100); + char * plain; + + plain = strrchr(szFile, '\\'); + if(plain == NULL) + plain = strrchr(szFile, '/'); + if(plain == NULL) + plain = szFile; + +#if _MSC_VER > 0x1300 + sprintf_s((char *)ptr, nSize+100, "%s(%u)", plain, nLine); +#else + sprintf((char *)ptr, "%s(%u)", plain, nLine); +#endif + + return (char *)ptr + 100; +} + + +__inline void DebugFree(void * ptr) +{ + free((char *)ptr - 100); +} + + +#ifndef ALLOCMEM + #define ALLOCMEM(type, nitems) (type *)malloc((nitems) * sizeof(type)) + #define FREEMEM(ptr) free(ptr) +#endif + +//#define ALLOCMEM(type, nitems) (type *)DebugMalloc(__FILE__, __LINE__, (nitems) * sizeof(type)) +//#define FREEMEM(ptr) DebugFree(ptr) + +//----------------------------------------------------------------------------- +// Functions in StormLib - compatible with Storm.dll + +// Typedefs for functions exported by Storm.dll +typedef LCID (WINAPI * SFILESETLOCALE)(LCID); +typedef BOOL (WINAPI * SFILEOPENARCHIVE)(const char *, DWORD, DWORD, HANDLE *); +typedef BOOL (WINAPI * SFILECLOSEARCHIVE)(HANDLE); +typedef BOOL (WINAPI * SFILEOPENFILEEX)(HANDLE, const char *, DWORD, HANDLE *); +typedef BOOL (WINAPI * SFILECLOSEFILE)(HANDLE); +typedef DWORD (WINAPI * SFILEGETFILESIZE)(HANDLE, DWORD *); +typedef DWORD (WINAPI * SFILESETFILEPOINTER)(HANDLE, LONG, LONG *, DWORD); +typedef BOOL (WINAPI * SFILEREADFILE)(HANDLE, VOID *, DWORD, DWORD *, LPOVERLAPPED); + +// Archive opening/closing +LCID WINAPI SFileSetLocale(LCID lcNewLocale); +LCID WINAPI SFileGetLocale(); +BOOL WINAPI SFileOpenArchive(const char * szMpqName, DWORD dwPriority, DWORD dwFlags, HANDLE * phMPQ); +BOOL WINAPI SFileCloseArchive(HANDLE hMPQ); + +// File opening/closing +BOOL WINAPI SFileOpenFileEx(HANDLE hMPQ, const char * szFileName, DWORD dwSearchScope, HANDLE * phFile); +BOOL WINAPI SFileCloseFile(HANDLE hFile); + +// File I/O +DWORD WINAPI SFileGetFilePos(HANDLE hFile, DWORD * pdwFilePosHigh = NULL); +DWORD WINAPI SFileGetFileSize(HANDLE hFile, DWORD * pdwFileSizeHigh = NULL); +DWORD WINAPI SFileSetFilePointer(HANDLE hFile, LONG lFilePos, LONG * pdwFilePosHigh, DWORD dwMethod); +BOOL WINAPI SFileReadFile(HANDLE hFile, VOID * lpBuffer, DWORD dwToRead, DWORD * pdwRead = NULL, LPOVERLAPPED lpOverlapped = NULL); + +BOOL WINAPI SFileExtractFile(HANDLE hMpq, const char * szToExtract, const char * szExtracted); + +// Adds another listfile into MPQ. The currently added listfile(s) remain, +// so you can use this API to combining more listfiles. +// Note that this function is internally called by SFileFindFirstFile +int WINAPI SFileAddListFile(HANDLE hMpq, const char * szListFile); + +//----------------------------------------------------------------------------- +// Functions in StormLib - not implemented in Storm.dll + +// Archive creating and editing +BOOL WINAPI SFileCreateArchiveEx(const char * szMpqName, DWORD dwCreationDisposition, DWORD dwHashTableSize, HANDLE * phMPQ); +BOOL WINAPI SFileAddFile(HANDLE hMPQ, const char * szFileName, const char * szArchivedName, DWORD dwFlags); +BOOL WINAPI SFileAddWave(HANDLE hMPQ, const char * szFileName, const char * szArchivedName, DWORD dwFlags, DWORD dwQuality); +BOOL WINAPI SFileRemoveFile(HANDLE hMPQ, const char * szFileName, DWORD dwSearchScope = SFILE_OPEN_BY_INDEX); +BOOL WINAPI SFileRenameFile(HANDLE hMPQ, const char * szOldFileName, const char * szNewFileName); +BOOL WINAPI SFileSetFileLocale(HANDLE hFile, LCID lcNewLocale); + +// Retrieving info about the file +BOOL WINAPI SFileHasFile(HANDLE hMPQ, char * szFileName); +BOOL WINAPI SFileGetFileName(HANDLE hFile, char * szFileName); +DWORD_PTR WINAPI SFileGetFileInfo(HANDLE hMpqOrFile, DWORD dwInfoType); + +// File search +// Note that the SFileFindFirstFileEx has been removed. Use SListFileFindFirst/Next +HANDLE WINAPI SFileFindFirstFile(HANDLE hMPQ, const char * szMask, SFILE_FIND_DATA * lpFindFileData, const char * szListFile); +BOOL WINAPI SFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData); +BOOL WINAPI SFileFindClose(HANDLE hFind); + +// Listfile search +HANDLE SListFileFindFirstFile(HANDLE hMpq, const char * szListFile, const char * szMask, SFILE_FIND_DATA * lpFindFileData); +BOOL SListFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData); +BOOL SListFileFindClose(HANDLE hFind); + +// Archive compacting +typedef void (WINAPI * COMPACTCB)(void * lpUserData, DWORD dwWorkType, DWORD dwParam1, DWORD dwParam2); +BOOL WINAPI SFileSetCompactCallback(HANDLE hMPQ, COMPACTCB CompactCB, void * lpData); +BOOL WINAPI SFileCompactArchive(HANDLE hMPQ, const char * szListFile = NULL, BOOL bReserved = 0); + +// Locale support +int WINAPI SFileEnumLocales(HANDLE hMPQ, const char * szFileName, LCID * plcLocales, DWORD * pdwMaxLocales, DWORD dwSearchScope = SFILE_OPEN_BY_INDEX); + +// (De)compression +int WINAPI SCompCompress (char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int uCompressions, int nCmpType, int nCmpLevel); +int WINAPI SCompDecompress (char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength); + +// Sets the default data compression for files added to MPQ, +// if MPQ_FILE_COMPRESS_MULTI has been specified in call to SFileAddFile +int WINAPI SCompSetDataCompression(int nDataCompression); + +//----------------------------------------------------------------------------- +// Functions from Storm.dll. They use slightly different names for keeping +// possibility to use them together with StormLib (StormXXX instead of SFileXXX) + +#ifdef __LINK_STORM_DLL__ + #define STORM_ALTERNATE_NAMES // Force Storm.h to use alternate fnc names + #include "StormDll.h" +#endif // __LINK_STORM_DLL__ + +//----------------------------------------------------------------------------- +// GFX decode functions. See GfxDecode.cpp for details and description + +USHORT WINAPI celGetFrameCount(BYTE * fileBuf); +BYTE * WINAPI celGetFrameData(BYTE *fileBuf, BYTE *palette, USHORT xsize, USHORT frame, USHORT *ysize, USHORT *maxX=NULL); +USHORT WINAPI cl2GetFrameCount(BYTE *fileBuf); +BYTE ** WINAPI cl2GetDirData(BYTE *fileBuf, BYTE *palette, USHORT xsize, USHORT dir, USHORT *ysize); +BYTE * WINAPI pcxGetData(BYTE *filebuf, DWORD filesize, BYTE transcol, USHORT *xsize, USHORT *ysize); + +#endif // __STORMLIB_H_ diff --git a/contrib/vmap_extractor_v2/stormlib/StormPort.h b/contrib/vmap_extractor_v2/stormlib/StormPort.h new file mode 100644 index 00000000000..4cb8d84bd57 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/StormPort.h @@ -0,0 +1,278 @@ +/*****************************************************************************/ +/* StormPort.h Copyright (c) Marko Friedemann 2001 */ +/*---------------------------------------------------------------------------*/ +/* Portability module for the StormLib library. Contains a wrapper symbols */ +/* to make the compilation under Linux work */ +/* */ +/* Author: Marko Friedemann */ +/* Created at: Mon Jan 29 18:26:01 CEST 2001 */ +/* Computer: whiplash.flachland-chemnitz.de */ +/* System: Linux 2.4.0 on i686 */ +/* */ +/* Author: Sam Wilkins */ +/* System: Mac OS X and port to big endian processor */ +/* */ +/*---------------------------------------------------------------------------*/ +/* Date Ver Who Comment */ +/* -------- ---- --- ------- */ +/* 29.01.01 1.00 Mar Created */ +/* 24.03.03 1.01 Lad Some cosmetic changes */ +/* 12.11.03 1.02 Dan Macintosh compatibility */ +/* 24.07.04 1.03 Sam Mac OS X compatibility */ +/* 22.11.06 1.04 Sam Mac OS X compatibility (for StormLib 6.0) */ +/* 31.12.06 1.05 XPinguin Full GNU/Linux compatibility */ +/*****************************************************************************/ + +#ifndef __STORMPORT_H__ +#define __STORMPORT_H__ + +// Defines for Windows +#if !defined(PLATFORM_DEFINED) && (defined(WIN32) || defined(WIN64)) + + // In MSVC 8.0, there are some functions declared as deprecated. + #if _MSC_VER >= 1400 + #define _CRT_SECURE_NO_DEPRECATE + #define _CRT_NON_CONFORMING_SWPRINTFS + #endif + + #include + #include + #include + #define PLATFORM_LITTLE_ENDIAN 1 + + #ifdef WIN64 + #define PLATFORM_64BIT + #else + #define PLATFORM_32BIT + #endif + + #define PLATFORM_DEFINED // The platform is known now + +#endif + +// Defines for Mac Carbon +#if !defined(PLATFORM_DEFINED) && defined(__APPLE__) // Mac Carbon API + + // Macintosh using Carbon + #include // Mac OS X + #define _stricmp strcasecmp // Case insensitive strcmp has a different name on this platform. + #define _strnicmp strncasecmp + + typedef void * LPCSTR; + typedef unsigned long * LPDWORD; + typedef long * PLONG; + typedef void * LPVOID; + typedef unsigned int UINT; + + #define PKEXPORT + #define __SYS_ZLIB + #define __SYS_BZLIB + #define LANG_NEUTRAL 0 + + #if defined(__BIG_ENDIAN__) + #define PLATFORM_LITTLE_ENDIAN 0 + #else + #define PLATFORM_LITTLE_ENDIAN 1 // Apple is now making Macs with Intel CPUs + #endif + #define PLATFORM_DEFINED // The platform is known now + +#endif + +// Assumption: we are not on Windows nor Macintosh, so this must be linux *grin* +// Ladik : Why the hell Linux does not use some OS-dependent #define ? +#if !defined(PLATFORM_DEFINED) + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #define PLATFORM_LITTLE_ENDIAN 1 + #define PLATFORM_DEFINED + #define LANG_NEUTRAL 0 + +#endif /* not __powerc */ + + +#if !defined(WIN32) && !defined(WIN64) + + // Typedefs for ANSI C + typedef unsigned char BYTE; + typedef short SHORT; + typedef unsigned short WORD; + typedef unsigned short USHORT; + typedef long LONG; + typedef unsigned long DWORD; + typedef unsigned long DWORD_PTR; + typedef long LONG_PTR; + typedef long long LONGLONG; +#ifndef __OBJC__ + #define BOOL bool +#endif + typedef void * HANDLE; + typedef void * LPOVERLAPPED; // Unsupported on Linux + typedef char TCHAR; + typedef unsigned long LCID; + + typedef void * LPCSTR; + typedef unsigned long * LPDWORD; + typedef long * PLONG; + typedef void * LPVOID; + typedef unsigned int UINT; + + typedef struct _FILETIME + { + DWORD dwLowDateTime; + DWORD dwHighDateTime; + } + FILETIME, *PFILETIME; + + typedef union _LARGE_INTEGER + { + #if PLATFORM_LITTLE_ENDIAN + struct + { + DWORD LowPart; + LONG HighPart; + }; + #else + struct + { + LONG HighPart; + DWORD LowPart; + }; + #endif + LONGLONG QuadPart; + } + LARGE_INTEGER, *PLARGE_INTEGER; + + // Some Windows-specific defines + #ifndef MAX_PATH + #define MAX_PATH 1024 + #endif + + #ifndef TRUE + #define TRUE true + #endif + + #ifndef FALSE + #define FALSE false + #endif + + #define VOID void + #define WINAPI + + #define FILE_BEGIN SEEK_SET + #define FILE_CURRENT SEEK_CUR + #define FILE_END SEEK_END + + #define CREATE_NEW 1 + #define CREATE_ALWAYS 2 + #define OPEN_EXISTING 3 + #define OPEN_ALWAYS 4 + + #define FILE_SHARE_READ 0x00000001L + #define GENERIC_WRITE 0x40000000 + #define GENERIC_READ 0x80000000 + + #define FILE_FLAG_DELETE_ON_CLOSE 1 // Sam: Added these two defines so it would compile. + #define FILE_FLAG_SEQUENTIAL_SCAN 2 + + #define ERROR_SUCCESS 0 + #define ERROR_INVALID_FUNCTION 1 + #define ERROR_FILE_NOT_FOUND 2 + #define ERROR_ACCESS_DENIED 5 + #define ERROR_NOT_ENOUGH_MEMORY 8 + #define ERROR_BAD_FORMAT 11 + #define ERROR_NO_MORE_FILES 18 + #define ERROR_GEN_FAILURE 31 + #define ERROR_HANDLE_EOF 38 + #define ERROR_HANDLE_DISK_FULL 39 + #define ERROR_NOT_SUPPORTED 50 + #define ERROR_INVALID_PARAMETER 87 + #define ERROR_DISK_FULL 112 + #define ERROR_CALL_NOT_IMPLEMENTED 120 + #define ERROR_ALREADY_EXISTS 183 + #define ERROR_CAN_NOT_COMPLETE 1003 + #define ERROR_PARAMETER_QUOTA_EXCEEDED 1283 + #define ERROR_FILE_CORRUPT 1392 + #define ERROR_INSUFFICIENT_BUFFER 4999 + + #define INVALID_HANDLE_VALUE ((HANDLE) -1) + + #ifndef min + #define min(a, b) ((a < b) ? a : b) + #endif + + #ifndef max + #define max(a, b) ((a > b) ? a : b) + #endif + + #define _stricmp strcasecmp + #define _strnicmp strncasecmp + + extern int globalerr; + + void SetLastError(int err); + int GetLastError(); + char *ErrString(int err); + + // Emulation of functions for file I/O available in Win32 + HANDLE CreateFile(const char * lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, void * lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); + BOOL CloseHandle(HANDLE hObject); + + DWORD GetFileSize(HANDLE hFile, DWORD * lpFileSizeHigh); + DWORD SetFilePointer(HANDLE, LONG lDistanceToMove, LONG * lpDistanceToMoveHigh, DWORD dwMoveMethod); + BOOL SetEndOfFile(HANDLE hFile); + + BOOL ReadFile(HANDLE hFile, void * lpBuffer, DWORD nNumberOfBytesToRead, DWORD * lpNumberOfBytesRead, void * lpOverLapped); + BOOL WriteFile(HANDLE hFile, const void * lpBuffer, DWORD nNumberOfBytesToWrite, DWORD * lpNumberOfBytesWritten, void * lpOverLapped); + + BOOL IsBadReadPtr(const void * ptr, int size); + DWORD GetFileAttributes(const char * szileName); + + BOOL DeleteFile(const char * lpFileName); + BOOL MoveFile(const char * lpFromFileName, const char * lpToFileName); + void GetTempPath(DWORD szTempLength, char * szTemp); + void GetTempFileName(const char * lpTempFolderPath, const char * lpFileName, DWORD something, char * szLFName); + + #define strnicmp strncasecmp + +#endif // !WIN32 + +#if PLATFORM_LITTLE_ENDIAN + #define BSWAP_INT16_UNSIGNED(a) (a) + #define BSWAP_INT16_SIGNED(a) (a) + #define BSWAP_INT32_UNSIGNED(a) (a) + #define BSWAP_INT32_SIGNED(a) (a) + #define BSWAP_ARRAY16_UNSIGNED(a,b) {} + #define BSWAP_ARRAY32_UNSIGNED(a,b) {} + #define BSWAP_TMPQSHUNT(a) {} + #define BSWAP_TMPQHEADER(a) {} +#else + extern unsigned short SwapUShort(unsigned short); + extern unsigned long SwapULong(unsigned long); + extern short SwapShort(unsigned short); + extern long SwapLong(unsigned long); + extern void ConvertUnsignedLongBuffer(unsigned long *buffer, unsigned long nbLongs); + extern void ConvertUnsignedShortBuffer(unsigned short *buffer, unsigned long nbShorts); + extern void ConvertTMPQShunt(void *shunt); + extern void ConvertTMPQHeader(void *header); + #define BSWAP_INT16_UNSIGNED(a) SwapUShort((a)) + #define BSWAP_INT32_UNSIGNED(a) SwapULong((a)) + #define BSWAP_INT16_SIGNED(a) SwapShort((a)) + #define BSWAP_INT32_SIGNED(a) SwapLong((a)) + #define BSWAP_ARRAY16_UNSIGNED(a,b) ConvertUnsignedShortBuffer((a),(b)) + #define BSWAP_ARRAY32_UNSIGNED(a,b) ConvertUnsignedLongBuffer((a),(b)) + #define BSWAP_TMPQSHUNT(a) ConvertTMPQShunt((a)) + #define BSWAP_TMPQHEADER(a) ConvertTMPQHeader((a)) +#endif + +#endif // __STORMPORT_H__ diff --git a/contrib/vmap_extractor_v2/stormlib/StormPortLinux.cpp b/contrib/vmap_extractor_v2/stormlib/StormPortLinux.cpp new file mode 100644 index 00000000000..0cd827fde9f --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/StormPortLinux.cpp @@ -0,0 +1,168 @@ +/******************************************************************** +* +* Description: implementation for StormLib - linux port +* intended to be used in GLdiablo +* +* ----> StormLib was originally developed for Windows by +* Ladislav Zezula (www.zezula.net), and he did +* a _great_ job! Thanks Ladislav! +* +* this is currently a quick and dirty hack to get it working +* don't expect beauty and/or miracles :) +* +* these are function wraps to execute Windows API calls +* as native Macintosh file calls (open/close/read/write/...) +* +* continue you work: added some wrapping functions for GNU/Linux by XPinguin +* +* Author: Marko Friedemann +* Created at: Mon Jan 29 19:01:37 CEST 2001 +* Computer: whiplash.flachland-chemnitz.de +* System: Linux 2.4.0 on i686 +* +* Copyright (c) 2001 BMX-Chemnitz.DE All rights reserved. +* +********************************************************************/ + +#ifndef _WIN32 +#include "StormPort.h" + +int globalerr; + +void SetLastError(int err) +{ + globalerr = err; +} + +int GetLastError() +{ + return(globalerr); +} + +char *ErrString(int err) +{ + switch (err) { + case ERROR_INVALID_FUNCTION: + return "function not implemented"; + case ERROR_FILE_NOT_FOUND: + return "file not found"; + case ERROR_ACCESS_DENIED: + return "access denied"; + case ERROR_NOT_ENOUGH_MEMORY: + return "not enough memory"; + case ERROR_BAD_FORMAT: + return "bad format"; + case ERROR_NO_MORE_FILES: + return "no more files"; + case ERROR_HANDLE_EOF: + return "access beyound EOF"; + case ERROR_HANDLE_DISK_FULL: + return "no space left on device"; + case ERROR_INVALID_PARAMETER: + return "invalid parameter"; + case ERROR_DISK_FULL: + return "no space left on device"; + case ERROR_ALREADY_EXISTS: + return "file exists"; + case ERROR_CAN_NOT_COMPLETE: + return "operation cannot be completed"; + default: + return "unknown error"; + } +} + +HANDLE CreateFile(const char *sFileName, DWORD ulMode, DWORD ulSharing, void *pSecAttrib, DWORD ulCreation, DWORD ulFlags, HANDLE hFile) +{ + switch (ulCreation) { + case OPEN_EXISTING: + return (HANDLE)open(sFileName, O_RDONLY | O_LARGEFILE); + case OPEN_ALWAYS: + return (HANDLE)open(sFileName, O_RDWR | O_CREAT); + case CREATE_NEW: + return (HANDLE)open(sFileName, O_RDWR | O_CREAT | O_TRUNC); + default: + return INVALID_HANDLE_VALUE; + } +} + +BOOL CloseHandle(HANDLE hFile) +{ + return (close((int)hFile) == 0); +} + +DWORD GetFileSize(HANDLE hFile, DWORD *ulOffSetHigh) +{ + if ((hFile == NULL) || (hFile == INVALID_HANDLE_VALUE)) + return 0xffffffff; + + struct stat fileinfo; + fstat((int)hFile, &fileinfo); + + return fileinfo.st_size; +} + +DWORD SetFilePointer(HANDLE hFile, LONG lOffSetLow, LONG *pOffSetHigh, DWORD ulMethod) +{ + return lseek64((int)hFile, (off64_t)(*pOffSetHigh) << 32 | (DWORD)lOffSetLow, ulMethod); +} + +BOOL SetEndOfFile(HANDLE hFile) +{ + return (ftruncate((int)hFile, lseek((int)hFile, 0, SEEK_CUR)) == 0); +} + +BOOL ReadFile(HANDLE hFile, void *pBuffer, DWORD ulLen, DWORD *ulRead, void *pOverLapped) +{ + ssize_t count; + if ((count = read((int)hFile, pBuffer, ulLen)) == -1) { + *ulRead = 0; + return false; + } + *ulRead = count; + return true; +} + +BOOL WriteFile(HANDLE hFile, const void *pBuffer, DWORD ulLen, DWORD *ulWritten, void *pOverLapped) +{ + ssize_t count; + if ((count = write((int)hFile, pBuffer, ulLen)) == -1) { + *ulWritten = 0; + return false; + } + *ulWritten = count; + return true; +} + +// Check if a memory block is accessible for reading +BOOL IsBadReadPtr(const void * ptr, int size) +{ + return FALSE; +} + +// Returns attributes of a file +DWORD GetFileAttributes(const char * szFileName) +{ + return 0; +} + +void GetTempPath(DWORD szTempLength, char * szTemp) +{ + strncpy(szTemp, P_tmpdir, szTempLength); +} + +void GetTempFileName(const char * lpTempFolderPath, const char * lpFileName, DWORD something, char * szLFName) +{ + strcpy(szLFName, tempnam(lpTempFolderPath, lpFileName)); +} + +BOOL DeleteFile(const char *lpFileName) +{ + return (BOOL)remove(lpFileName); +} + +BOOL MoveFile(const char *lpExistingFileName, const char *lpNewFileName) +{ + return rename(lpExistingFileName, lpNewFileName); +} + +#endif diff --git a/contrib/vmap_extractor_v2/stormlib/StormPortMac.cpp b/contrib/vmap_extractor_v2/stormlib/StormPortMac.cpp new file mode 100644 index 00000000000..26f67872a14 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/StormPortMac.cpp @@ -0,0 +1,762 @@ +/******************************************************************** +* +* Description: implementation for StormLib - Macintosh port +* +* these are function wraps to execute Windows API calls +* as native Macintosh file calls (open/close/read/write/...) +* requires Mac OS X +* +* Derived from Marko Friedemann +* StormPort.cpp for Linux +* +* Author: Daniel Chiaramello +* +* Carbonized by: Sam Wilkins +* +********************************************************************/ + +#ifndef _WIN32 || _WIN64 +#include "StormPort.h" +#include "StormLib.h" + +// FUNCTIONS EXTRACTED FROM MOREFILE PACKAGE!!! +// FEEL FREE TO REMOVE THEM AND TO ADD THE ORIGINAL ONES! + +/***************************************************************************** +* BEGIN OF MOREFILES COPY-PASTE +*****************************************************************************/ + +#ifdef __USEPRAGMAINTERNAL + #ifdef __MWERKS__ + #pragma internal on + #endif +#endif + +union TLongAnd4Bytes +{ + unsigned char bytes[4]; + unsigned long uvalue; + signed long svalue; +}; + + +static OSErr FSGetFullPath(const FSRef *ref, UInt8 *fullPath, UInt32 fullPathLength) +{ + OSErr result; + + result = FSRefMakePath(ref, fullPath, fullPathLength); + + return result; +} + +static OSErr FSLocationFromFullPath(const void *fullPath, FSRef *ref) +{ + OSErr result; + + result = FSPathMakeRef((UInt8 *)fullPath, ref, NULL); // Create an FSRef from the path + return result; +} + +/*****************************************************************************/ + +/*****************************************************************************/ + +static OSErr FSCreateCompat(const FSRef *parentRef, OSType creator, OSType fileType, const UniChar *fileName, + UniCharCount nameLength, FSRef *ref) +{ + FSCatalogInfo theCatInfo; + OSErr theErr; + ((FileInfo *)&theCatInfo.finderInfo)->fileCreator = creator; + ((FileInfo *)&theCatInfo.finderInfo)->fileType = fileType; + ((FileInfo *)&theCatInfo.finderInfo)->finderFlags = 0; + SetPt(&((FileInfo *)&theCatInfo.finderInfo)->location, 0, 0); + ((FileInfo *)&theCatInfo.finderInfo)->reservedField = 0; + + theErr = FSCreateFileUnicode(parentRef, nameLength, fileName, kFSCatInfoFinderInfo, &theCatInfo, ref, NULL); + return theErr; +} + + +/*****************************************************************************/ + +static OSErr FSOpenDFCompat(FSRef *ref, char permission, short *refNum) +{ + HFSUniStr255 forkName; + OSErr theErr; + Boolean isFolder, wasChanged; + + theErr = FSResolveAliasFile(ref, TRUE, &isFolder, &wasChanged); + if (theErr != noErr) + return theErr; + + FSGetDataForkName(&forkName); + theErr = FSOpenFork(ref, forkName.length, forkName.unicode, permission, refNum); + return theErr; +} + +/***************************************************************************** +* END OF MOREFILES COPY-PASTE +*****************************************************************************/ + +#pragma mark - + +int globalerr; + +/******************************************************************** +* SwapLong +********************************************************************/ + +unsigned long SwapULong(unsigned long data) +{ + // Apple provided function + uint32_t result; + + __asm__("lwbrx %0,0,%1" : "=r" (result) : "r" (&data), "m" (data)); + return result; + +/* + TLongAnd4Bytes Work; + unsigned char * value_as_4bytes = (unsigned char *)&value; + + Work.bytes[0] = value_as_4bytes[3]; + Work.bytes[1] = value_as_4bytes[2]; + Work.bytes[2] = value_as_4bytes[1]; + Work.bytes[3] = value_as_4bytes[0]; + + return Work.uvalue; +*/ +} + +long SwapLong(unsigned long data) +{ + // Apple provided function + uint32_t result; + + __asm__("lwbrx %0,0,%1" : "=r" (result) : "r" (&data), "m" (data)); + return (long)result; + +/* + TLongAnd4Bytes Work; + unsigned char * value_as_4bytes = (unsigned char *)&value; + + Work.bytes[0] = value_as_4bytes[3]; + Work.bytes[1] = value_as_4bytes[2]; + Work.bytes[2] = value_as_4bytes[1]; + Work.bytes[3] = value_as_4bytes[0]; + + return Work.svalue; +*/ +} + +/******************************************************************** +* SwapShort +********************************************************************/ +unsigned short SwapUShort(unsigned short data) +{ + // Apple provided function + uint16_t result; + __asm__("lhbrx %0,0,%1" : "=r" (result) : "r" (&data), "m" (data)); + return result; +} + +short SwapShort(unsigned short data) +{ + // Apple provided function + uint16_t result; + __asm__("lhbrx %0,0,%1" : "=r" (result) : "r" (&data), "m" (data)); + return (short)result; +} + +/******************************************************************** +* ConvertUnsignedLongBuffer +********************************************************************/ +void ConvertUnsignedLongBuffer(unsigned long *buffer, unsigned long nbLongs) +{ + while (nbLongs-- > 0) + { + *buffer = SwapLong(*buffer); + buffer++; + } +} + +/******************************************************************** +* ConvertUnsignedShortBuffer +********************************************************************/ +void ConvertUnsignedShortBuffer(unsigned short *buffer, unsigned long nbShorts) +{ + while (nbShorts-- > 0) + { + *buffer = SwapShort(*buffer); + buffer++; + } +} + +/******************************************************************** +* ConvertTMPQShunt +********************************************************************/ +void ConvertTMPQShunt(void *shunt) +{ + TMPQShunt * theShunt = (TMPQShunt *)shunt; + + theShunt->dwID = SwapULong(theShunt->dwID); + theShunt->dwUnknown = SwapULong(theShunt->dwUnknown); + theShunt->dwHeaderPos = SwapULong(theShunt->dwHeaderPos); +} + +/******************************************************************** +* ConvertTMPQHeader +********************************************************************/ +void ConvertTMPQHeader(void *header) +{ + TMPQHeader2 * theHeader = (TMPQHeader2 *)header; + + theHeader->dwID = SwapULong(theHeader->dwID); + theHeader->dwHeaderSize = SwapULong(theHeader->dwHeaderSize); + theHeader->dwArchiveSize = SwapULong(theHeader->dwArchiveSize); + theHeader->wFormatVersion = SwapUShort(theHeader->wFormatVersion); + theHeader->wBlockSize = SwapUShort(theHeader->wBlockSize); + theHeader->dwHashTablePos = SwapULong(theHeader->dwHashTablePos); + theHeader->dwBlockTablePos = SwapULong(theHeader->dwBlockTablePos); + theHeader->dwHashTableSize = SwapULong(theHeader->dwHashTableSize); + theHeader->dwBlockTableSize = SwapULong(theHeader->dwBlockTableSize); + + if(theHeader->wFormatVersion >= MPQ_FORMAT_VERSION_2) + { + DWORD dwTemp = theHeader->ExtBlockTablePos.LowPart; + theHeader->ExtBlockTablePos.LowPart = theHeader->ExtBlockTablePos.HighPart; + theHeader->ExtBlockTablePos.HighPart = dwTemp; + theHeader->ExtBlockTablePos.LowPart = SwapULong(theHeader->ExtBlockTablePos.LowPart); + theHeader->ExtBlockTablePos.HighPart = SwapULong(theHeader->ExtBlockTablePos.HighPart); + theHeader->wHashTablePosHigh = SwapUShort(theHeader->wHashTablePosHigh); + theHeader->wBlockTablePosHigh = SwapUShort(theHeader->wBlockTablePosHigh); + } +} + +/******************************************************************** +* ConvertTMPQHash +********************************************************************/ +void ConvertHashTable(void *hashtable, DWORD nHashEntries) +{ + TMPQHash * theHash = (TMPQHash *)hashtable; + USHORT lcLocale; + + for(DWORD i = 0; i < nHashEntries; i++, theHash++) + { + lcLocale = theHash->lcLocale; + theHash->lcLocale = theHash->wPlatform; + theHash->wPlatform = lcLocale; + } +} + +#pragma mark - + +/******************************************************************** +* SetLastError +********************************************************************/ +void SetLastError(int err) +{ + globalerr = err; +} + +/******************************************************************** +* GetLastError +********************************************************************/ +int GetLastError() +{ + return globalerr; +} + +/******************************************************************** +* ErrString +********************************************************************/ +char *ErrString(int err) +{ + switch (err) + { + case ERROR_INVALID_FUNCTION: + return "function not implemented"; + case ERROR_FILE_NOT_FOUND: + return "file not found"; + case ERROR_ACCESS_DENIED: + return "access denied"; + case ERROR_NOT_ENOUGH_MEMORY: + return "not enough memory"; + case ERROR_BAD_FORMAT: + return "bad format"; + case ERROR_NO_MORE_FILES: + return "no more files"; + case ERROR_HANDLE_EOF: + return "access beyound EOF"; + case ERROR_HANDLE_DISK_FULL: + return "no space left on device"; + case ERROR_INVALID_PARAMETER: + return "invalid parameter"; + case ERROR_DISK_FULL: + return "no space left on device"; + case ERROR_ALREADY_EXISTS: + return "file exists"; + case ERROR_CAN_NOT_COMPLETE: + return "operation cannot be completed"; + case ERROR_INSUFFICIENT_BUFFER: + return "insufficient buffer"; + default: + return "unknown error"; + } +} + +#pragma mark - + +/******************************************************************** +* GetTempPath - returns a '/' or ':'-terminated path +* szTempLength: length for path +* szTemp: file path +********************************************************************/ +void GetTempPath(DWORD szTempLength, char * szTemp) // I think I'll change this to use FSRefs. +{ + FSRef theFSRef; + OSErr theErr = FSFindFolder(kOnAppropriateDisk, kTemporaryFolderType, kCreateFolder, &theFSRef); + if (theErr == noErr) + { + theErr = FSGetFullPath(&theFSRef, (UInt8 *)szTemp, MAX_PATH); + if (theErr != noErr) + szTemp[0] = '\0'; + } + else + szTemp[0] = '\0'; + strcat(szTemp, "/"); + + SetLastError(theErr); +} + +/******************************************************************** +* GetTempFileName +* lpTempFolderPath: the temporary folder path, terminated by "/" +* lpFileName: a file name base +* something: unknown +* szLFName: the final path, built from the path, the file name and a random pattern +********************************************************************/ +void GetTempFileName(const char * lpTempFolderPath, const char * lpFileName, DWORD something, char * szLFName) +{ +#pragma unused (something) + char tmp[2] = "A"; + + while (true) + { + HANDLE fHandle; + + strcpy(szLFName, lpTempFolderPath); + strcat(szLFName, lpFileName); + strcat(szLFName, tmp); + + if ((fHandle = CreateFile(szLFName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) + // OK we found it! + break; + CloseHandle(fHandle); + tmp[0]++; + } +} + +/******************************************************************** +* DeleteFile +* lpFileName: file path +********************************************************************/ +BOOL DeleteFile(const char * lpFileName) +{ + OSErr theErr; + FSRef theFileRef; + + theErr = FSLocationFromFullPath(lpFileName, &theFileRef); + if (theErr != noErr) + { + SetLastError(theErr); + return FALSE; + } + + theErr = FSDeleteObject(&theFileRef); + + SetLastError(theErr); + + return theErr == noErr; +} + +/******************************************************************** +* MoveFile +* lpFromFileName: old file path +* lpToFileName: new file path +********************************************************************/ +BOOL MoveFile(const char * lpFromFileName, const char * lpToFileName) +{ + OSErr theErr; + FSRef fromFileRef; + FSRef toFileRef; + FSRef parentFolderRef; + + // Get the path to the old file + theErr = FSLocationFromFullPath(lpFromFileName, &fromFileRef); + if (theErr != noErr) + { + SetLastError(theErr); + return false; + } + + // Get the path to the new folder for the file + char folderName[strlen(lpToFileName)]; + CFStringRef folderPathCFString = CFStringCreateWithCString(NULL, lpToFileName, kCFStringEncodingUTF8); + CFURLRef fileURL = CFURLCreateWithFileSystemPath(NULL, folderPathCFString, kCFURLPOSIXPathStyle, FALSE); + CFURLRef folderURL = CFURLCreateCopyDeletingLastPathComponent(NULL, fileURL); + CFURLGetFileSystemRepresentation(folderURL, TRUE, (UInt8 *)folderName, strlen(lpToFileName)); + theErr = FSLocationFromFullPath(folderName, &parentFolderRef); + CFRelease(fileURL); + CFRelease(folderURL); + CFRelease(folderPathCFString); + + // Move the old file + theErr = FSMoveObject(&fromFileRef, &parentFolderRef, &toFileRef); + if (theErr != noErr) + { + SetLastError(theErr); + return false; + } + + // Get a CFString for the new file name + CFStringRef newFileNameCFString = CFStringCreateWithCString(NULL, lpToFileName, kCFStringEncodingUTF8); + fileURL = CFURLCreateWithFileSystemPath(NULL, newFileNameCFString, kCFURLPOSIXPathStyle, FALSE); + CFRelease(newFileNameCFString); + newFileNameCFString = CFURLCopyLastPathComponent(fileURL); + CFRelease(fileURL); + + // Convert CFString to Unicode and rename the file + UniChar unicodeFileName[256]; + CFStringGetCharacters(newFileNameCFString, CFRangeMake(0, CFStringGetLength(newFileNameCFString)), + unicodeFileName); + theErr = FSRenameUnicode(&toFileRef, CFStringGetLength(newFileNameCFString), unicodeFileName, + kTextEncodingUnknown, NULL); + if (theErr != noErr) + { + SetLastError(theErr); + CFRelease(newFileNameCFString); + return false; + } + + CFRelease(newFileNameCFString); + + SetLastError(theErr); + return true; +} + +/******************************************************************** +* CreateFile +* ulMode: GENERIC_READ | GENERIC_WRITE +* ulSharing: FILE_SHARE_READ +* pSecAttrib: NULL +* ulCreation: OPEN_EXISTING, OPEN_ALWAYS, CREATE_NEW +* ulFlags: 0 +* hFile: NULL +********************************************************************/ +HANDLE CreateFile( const char *sFileName, /* file name */ + DWORD ulMode, /* access mode */ + DWORD ulSharing, /* share mode */ + void *pSecAttrib, /* SD */ + DWORD ulCreation, /* how to create */ + DWORD ulFlags, /* file attributes */ + HANDLE hFile ) /* handle to template file */ +{ +#pragma unused (ulSharing, pSecAttrib, ulFlags, hFile) + + OSErr theErr; + FSRef theFileRef; + FSRef theParentRef; + short fileRef; + char permission; + static OSType gCreator; + static OSType gType; + + theErr = FSLocationFromFullPath(sFileName, &theFileRef); + if (theErr == fnfErr) + { // Create the FSRef for the parent directory. + memset(&theFileRef, 0, sizeof(FSRef)); + UInt8 folderName[MAX_PATH]; + CFStringRef folderPathCFString = CFStringCreateWithCString(NULL, sFileName, kCFStringEncodingUTF8); + CFURLRef fileURL = CFURLCreateWithFileSystemPath(NULL, folderPathCFString, kCFURLPOSIXPathStyle, FALSE); + CFURLRef folderURL = CFURLCreateCopyDeletingLastPathComponent(NULL, fileURL); + CFURLGetFileSystemRepresentation(folderURL, TRUE, folderName, MAX_PATH); + theErr = FSLocationFromFullPath(folderName, &theParentRef); + CFRelease(fileURL); + CFRelease(folderURL); + CFRelease(folderPathCFString); + } + if (theErr != noErr) + { + SetLastError(theErr); + if (ulCreation == OPEN_EXISTING || theErr != fnfErr) + return INVALID_HANDLE_VALUE; + } + + if (ulCreation != OPEN_EXISTING) + { /* We create the file */ + UniChar unicodeFileName[256]; + CFStringRef filePathCFString = CFStringCreateWithCString(NULL, sFileName, kCFStringEncodingUTF8); + CFURLRef fileURL = CFURLCreateWithFileSystemPath(NULL, filePathCFString, kCFURLPOSIXPathStyle, FALSE); + CFStringRef fileNameCFString = CFURLCopyLastPathComponent(fileURL); + CFStringGetCharacters(fileNameCFString, CFRangeMake(0, CFStringGetLength(fileNameCFString)), + unicodeFileName); + theErr = FSCreateCompat(&theParentRef, gCreator, gType, unicodeFileName, + CFStringGetLength(fileNameCFString), &theFileRef); + CFRelease(fileNameCFString); + CFRelease(filePathCFString); + CFRelease(fileURL); + if (theErr != noErr) + { + SetLastError(theErr); + return INVALID_HANDLE_VALUE; + } + } + + if (ulMode == GENERIC_READ) + permission = fsRdPerm; + else + { + if (ulMode == GENERIC_WRITE) + permission = fsWrPerm; + else + permission = fsRdWrPerm; + } + theErr = FSOpenDFCompat(&theFileRef, permission, &fileRef); + + SetLastError(theErr); + + if (theErr == noErr) + return (HANDLE)(int)fileRef; + else + return INVALID_HANDLE_VALUE; +} + +/******************************************************************** +* CloseHandle +********************************************************************/ +BOOL CloseHandle( HANDLE hFile ) /* handle to object */ +{ + OSErr theErr; + + if ((hFile == NULL) || (hFile == INVALID_HANDLE_VALUE)) + return FALSE; + + theErr = FSCloseFork((short)(int)hFile); + + SetLastError(theErr); + + return theErr != noErr; +} + +/******************************************************************** +* GetFileSize +********************************************************************/ +DWORD GetFileSize( HANDLE hFile, /* handle to file */ + DWORD *ulOffSetHigh ) /* high-order word of file size */ +{ + SInt64 fileLength; + OSErr theErr; + + if ((hFile == NULL) || (hFile == INVALID_HANDLE_VALUE)) + { + SetLastError(theErr); + return -1u; + } + + theErr = FSGetForkSize((short)(int)hFile, &fileLength); + if (theErr != noErr) + { + SetLastError(theErr); + return -1u; + } + + if (ulOffSetHigh != NULL) + *ulOffSetHigh = fileLength >> 32; + + SetLastError(theErr); + + return fileLength; +} + +/******************************************************************** +* SetFilePointer +* pOffSetHigh: NULL +* ulMethod: FILE_BEGIN, FILE_CURRENT +********************************************************************/ +DWORD SetFilePointer( HANDLE hFile, /* handle to file */ + LONG lOffSetLow, /* bytes to move pointer */ + LONG *pOffSetHigh, /* bytes to move pointer */ + DWORD ulMethod ) /* starting point */ +{ + OSErr theErr; + + if (ulMethod == FILE_CURRENT) + { + SInt64 bytesToMove; + + if (pOffSetHigh != NULL) + bytesToMove = ((SInt64)*pOffSetHigh << 32) + lOffSetLow; + else + bytesToMove = lOffSetLow; + + SInt64 newPos; + + theErr = FSSetForkPosition((short)(int)hFile, fsFromMark, bytesToMove); + if (theErr != noErr) + { + SetLastError(theErr); + return -1u; + } + + theErr = FSGetForkPosition((short)(int)hFile, &newPos); + if (theErr != noErr) + { + SetLastError(theErr); + return -1u; + } + + if (pOffSetHigh != NULL) + *pOffSetHigh = newPos >> 32; + + SetLastError(theErr); + return newPos; + } + else if (ulMethod == FILE_BEGIN) + { + SInt64 bytesToMove; + + if (pOffSetHigh != NULL) + bytesToMove = ((SInt64)*pOffSetHigh << 32) + lOffSetLow; + else + bytesToMove = lOffSetLow; + + theErr = FSSetForkPosition((short)(int)hFile, fsFromStart, bytesToMove); + if (theErr != noErr) + { + SetLastError(theErr); + return -1u; + } + + SetLastError(theErr); + return lOffSetLow; + } + else + { + SInt64 bytesToMove; + + if (pOffSetHigh != NULL) + bytesToMove = ((SInt64)*pOffSetHigh << 32) + lOffSetLow; + else + bytesToMove = lOffSetLow; + + SInt64 newPos; + + theErr = FSSetForkPosition((short)(int)hFile, fsFromLEOF, bytesToMove); + if (theErr != noErr) + { + SetLastError(theErr); + return -1u; + } + + theErr = FSGetForkPosition((short)(int)hFile, &newPos); + if (theErr != noErr) + { + SetLastError(theErr); + return -1u; + } + + if (pOffSetHigh != NULL) + *pOffSetHigh = newPos >> 32; + + SetLastError(theErr); + return newPos; + } +} + +/******************************************************************** +* SetEndOfFile +********************************************************************/ +BOOL SetEndOfFile( HANDLE hFile ) /* handle to file */ +{ + OSErr theErr; + + theErr = FSSetForkSize((short)(int)hFile, fsAtMark, 0); + + SetLastError(theErr); + + return theErr == noErr; +} + +/******************************************************************** +* ReadFile +* pOverLapped: NULL +********************************************************************/ +BOOL ReadFile( HANDLE hFile, /* handle to file */ + void *pBuffer, /* data buffer */ + DWORD ulLen, /* number of bytes to read */ + DWORD *ulRead, /* number of bytes read */ + void *pOverLapped ) /* overlapped buffer */ +{ +#pragma unused (pOverLapped) + + ByteCount nbCharsRead; + OSErr theErr; + + nbCharsRead = ulLen; + theErr = FSReadFork((short)(int)hFile, fsAtMark, 0, nbCharsRead, pBuffer, &nbCharsRead); + *ulRead = nbCharsRead; + + SetLastError(theErr); + + return theErr == noErr; +} + +/******************************************************************** +* WriteFile +* pOverLapped: NULL +********************************************************************/ +BOOL WriteFile( HANDLE hFile, /* handle to file */ + const void *pBuffer, /* data buffer */ + DWORD ulLen, /* number of bytes to write */ + DWORD *ulWritten, /* number of bytes written */ + void *pOverLapped ) /* overlapped buffer */ +{ +#pragma unused (pOverLapped) + + ByteCount nbCharsToWrite; + OSErr theErr; + + nbCharsToWrite = ulLen; + theErr = FSWriteFork((short)(int)hFile, fsAtMark, 0, nbCharsToWrite, pBuffer, &nbCharsToWrite); + *ulWritten = nbCharsToWrite; + + SetLastError(theErr); + + return theErr == noErr; +} + +// Check if a memory block is accessible for reading. It's probably too +// hard to check on Mac, so sorry, we'll just have to crash +BOOL IsBadReadPtr(const void * ptr, int size) +{ +#pragma unused (ptr, size) + + return FALSE; +} + +// Returns attributes of a file. Actually, it doesn't, it just checks if +// the file exists, since that's all StormLib uses it for +DWORD GetFileAttributes(const char * szFileName) +{ + FSRef theRef; + OSErr theErr; + + theErr = FSLocationFromFullPath(szFileName, &theRef); + + if (theErr != noErr) + return -1u; + else + return 0; +} + +#endif diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/CHANGES b/contrib/vmap_extractor_v2/stormlib/bzip2/CHANGES new file mode 100644 index 00000000000..e31b03a0118 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/bzip2/CHANGES @@ -0,0 +1,275 @@ + + +0.9.0 +~~~~~ +First version. + + +0.9.0a +~~~~~~ +Removed 'ranlib' from Makefile, since most modern Unix-es +don't need it, or even know about it. + + +0.9.0b +~~~~~~ +Fixed a problem with error reporting in bzip2.c. This does not effect +the library in any way. Problem is: versions 0.9.0 and 0.9.0a (of the +program proper) compress and decompress correctly, but give misleading +error messages (internal panics) when an I/O error occurs, instead of +reporting the problem correctly. This shouldn't give any data loss +(as far as I can see), but is confusing. + +Made the inline declarations disappear for non-GCC compilers. + + +0.9.0c +~~~~~~ +Fixed some problems in the library pertaining to some boundary cases. +This makes the library behave more correctly in those situations. The +fixes apply only to features (calls and parameters) not used by +bzip2.c, so the non-fixedness of them in previous versions has no +effect on reliability of bzip2.c. + +In bzlib.c: + * made zero-length BZ_FLUSH work correctly in bzCompress(). + * fixed bzWrite/bzRead to ignore zero-length requests. + * fixed bzread to correctly handle read requests after EOF. + * wrong parameter order in call to bzDecompressInit in + bzBuffToBuffDecompress. Fixed. + +In compress.c: + * changed setting of nGroups in sendMTFValues() so as to + do a bit better on small files. This _does_ effect + bzip2.c. + + +0.9.5a +~~~~~~ +Major change: add a fallback sorting algorithm (blocksort.c) +to give reasonable behaviour even for very repetitive inputs. +Nuked --repetitive-best and --repetitive-fast since they are +no longer useful. + +Minor changes: mostly a whole bunch of small changes/ +bugfixes in the driver (bzip2.c). Changes pertaining to the +user interface are: + + allow decompression of symlink'd files to stdout + decompress/test files even without .bz2 extension + give more accurate error messages for I/O errors + when compressing/decompressing to stdout, don't catch control-C + read flags from BZIP2 and BZIP environment variables + decline to break hard links to a file unless forced with -f + allow -c flag even with no filenames + preserve file ownerships as far as possible + make -s -1 give the expected block size (100k) + add a flag -q --quiet to suppress nonessential warnings + stop decoding flags after --, so files beginning in - can be handled + resolved inconsistent naming: bzcat or bz2cat ? + bzip2 --help now returns 0 + +Programming-level changes are: + + fixed syntax error in GET_LL4 for Borland C++ 5.02 + let bzBuffToBuffDecompress return BZ_DATA_ERROR{_MAGIC} + fix overshoot of mode-string end in bzopen_or_bzdopen + wrapped bzlib.h in #ifdef __cplusplus ... extern "C" { ... } + close file handles under all error conditions + added minor mods so it compiles with DJGPP out of the box + fixed Makefile so it doesn't give problems with BSD make + fix uninitialised memory reads in dlltest.c + +0.9.5b +~~~~~~ +Open stdin/stdout in binary mode for DJGPP. + +0.9.5c +~~~~~~ +Changed BZ_N_OVERSHOOT to be ... + 2 instead of ... + 1. The + 1 +version could cause the sorted order to be wrong in some extremely +obscure cases. Also changed setting of quadrant in blocksort.c. + +0.9.5d +~~~~~~ +The only functional change is to make bzlibVersion() in the library +return the correct string. This has no effect whatsoever on the +functioning of the bzip2 program or library. Added a couple of casts +so the library compiles without warnings at level 3 in MS Visual +Studio 6.0. Included a Y2K statement in the file Y2K_INFO. All other +changes are minor documentation changes. + +1.0 +~~~ +Several minor bugfixes and enhancements: + +* Large file support. The library uses 64-bit counters to + count the volume of data passing through it. bzip2.c + is now compiled with -D_FILE_OFFSET_BITS=64 to get large + file support from the C library. -v correctly prints out + file sizes greater than 4 gigabytes. All these changes have + been made without assuming a 64-bit platform or a C compiler + which supports 64-bit ints, so, except for the C library + aspect, they are fully portable. + +* Decompression robustness. The library/program should be + robust to any corruption of compressed data, detecting and + handling _all_ corruption, instead of merely relying on + the CRCs. What this means is that the program should + never crash, given corrupted data, and the library should + always return BZ_DATA_ERROR. + +* Fixed an obscure race-condition bug only ever observed on + Solaris, in which, if you were very unlucky and issued + control-C at exactly the wrong time, both input and output + files would be deleted. + +* Don't run out of file handles on test/decompression when + large numbers of files have invalid magic numbers. + +* Avoid library namespace pollution. Prefix all exported + symbols with BZ2_. + +* Minor sorting enhancements from my DCC2000 paper. + +* Advance the version number to 1.0, so as to counteract the + (false-in-this-case) impression some people have that programs + with version numbers less than 1.0 are in some way, experimental, + pre-release versions. + +* Create an initial Makefile-libbz2_so to build a shared library. + Yes, I know I should really use libtool et al ... + +* Make the program exit with 2 instead of 0 when decompression + fails due to a bad magic number (ie, an invalid bzip2 header). + Also exit with 1 (as the manual claims :-) whenever a diagnostic + message would have been printed AND the corresponding operation + is aborted, for example + bzip2: Output file xx already exists. + When a diagnostic message is printed but the operation is not + aborted, for example + bzip2: Can't guess original name for wurble -- using wurble.out + then the exit value 0 is returned, unless some other problem is + also detected. + + I think it corresponds more closely to what the manual claims now. + + +1.0.1 +~~~~~ +* Modified dlltest.c so it uses the new BZ2_ naming scheme. +* Modified makefile-msc to fix minor build probs on Win2k. +* Updated README.COMPILATION.PROBLEMS. + +There are no functionality changes or bug fixes relative to version +1.0.0. This is just a documentation update + a fix for minor Win32 +build problems. For almost everyone, upgrading from 1.0.0 to 1.0.1 is +utterly pointless. Don't bother. + + +1.0.2 +~~~~~ +A bug fix release, addressing various minor issues which have appeared +in the 18 or so months since 1.0.1 was released. Most of the fixes +are to do with file-handling or documentation bugs. To the best of my +knowledge, there have been no data-loss-causing bugs reported in the +compression/decompression engine of 1.0.0 or 1.0.1. + +Note that this release does not improve the rather crude build system +for Unix platforms. The general plan here is to autoconfiscate/ +libtoolise 1.0.2 soon after release, and release the result as 1.1.0 +or perhaps 1.2.0. That, however, is still just a plan at this point. + +Here are the changes in 1.0.2. Bug-reporters and/or patch-senders in +parentheses. + +* Fix an infinite segfault loop in 1.0.1 when a directory is + encountered in -f (force) mode. + (Trond Eivind Glomsrod, Nicholas Nethercote, Volker Schmidt) + +* Avoid double fclose() of output file on certain I/O error paths. + (Solar Designer) + +* Don't fail with internal error 1007 when fed a long stream (> 48MB) + of byte 251. Also print useful message suggesting that 1007s may be + caused by bad memory. + (noticed by Juan Pedro Vallejo, fixed by me) + +* Fix uninitialised variable silly bug in demo prog dlltest.c. + (Jorj Bauer) + +* Remove 512-MB limitation on recovered file size for bzip2recover + on selected platforms which support 64-bit ints. At the moment + all GCC supported platforms, and Win32. + (me, Alson van der Meulen) + +* Hard-code header byte values, to give correct operation on platforms + using EBCDIC as their native character set (IBM's OS/390). + (Leland Lucius) + +* Copy file access times correctly. + (Marty Leisner) + +* Add distclean and check targets to Makefile. + (Michael Carmack) + +* Parameterise use of ar and ranlib in Makefile. Also add $(LDFLAGS). + (Rich Ireland, Bo Thorsen) + +* Pass -p (create parent dirs as needed) to mkdir during make install. + (Jeremy Fusco) + +* Dereference symlinks when copying file permissions in -f mode. + (Volker Schmidt) + +* Majorly simplify implementation of uInt64_qrm10. + (Bo Lindbergh) + +* Check the input file still exists before deleting the output one, + when aborting in cleanUpAndFail(). + (Joerg Prante, Robert Linden, Matthias Krings) + +Also a bunch of patches courtesy of Philippe Troin, the Debian maintainer +of bzip2: + +* Wrapper scripts (with manpages): bzdiff, bzgrep, bzmore. + +* Spelling changes and minor enhancements in bzip2.1. + +* Avoid race condition between creating the output file and setting its + interim permissions safely, by using fopen_output_safely(). + No changes to bzip2recover since there is no issue with file + permissions there. + +* do not print senseless report with -v when compressing an empty + file. + +* bzcat -f works on non-bzip2 files. + +* do not try to escape shell meta-characters on unix (the shell takes + care of these). + +* added --fast and --best aliases for -1 -9 for gzip compatibility. + + +1.0.3 (15 Feb 05) +~~~~~~~~~~~~~~~~~ +Fixes some minor bugs since the last version, 1.0.2. + +* Further robustification against corrupted compressed data. + There are currently no known bitstreams which can cause the + decompressor to crash, loop or access memory which does not + belong to it. If you are using bzip2 or the library to + decompress bitstreams from untrusted sources, an upgrade + to 1.0.3 is recommended. + +* The documentation has been converted to XML, from which html + and pdf can be derived. + +* Various minor bugs in the documentation have been fixed. + +* Fixes for various compilation warnings with newer versions of + gcc, and on 64-bit platforms. + +* The BZ_NO_STDIO cpp symbol was not properly observed in 1.0.2. + This has been fixed. diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/LICENSE b/contrib/vmap_extractor_v2/stormlib/bzip2/LICENSE new file mode 100644 index 00000000000..e60845b4dcc --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/bzip2/LICENSE @@ -0,0 +1,40 @@ + +This program, "bzip2", the associated library "libbzip2", and all +documentation, are copyright (C) 1996-2005 Julian R Seward. All +rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + +3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + +4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Julian Seward, Cambridge, UK. +jseward@acm.org +bzip2/libbzip2 version 1.0.3 of 15 February 2005 + diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/Makefile b/contrib/vmap_extractor_v2/stormlib/bzip2/Makefile new file mode 100644 index 00000000000..eea329a626e --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/bzip2/Makefile @@ -0,0 +1,205 @@ + +SHELL=/bin/sh + +# To assist in cross-compiling +CC=gcc +AR=ar +RANLIB=ranlib +LDFLAGS= + +BIGFILES=-D_FILE_OFFSET_BITS=64 +CFLAGS=-Wall -Winline -O -g $(BIGFILES) + +# Where you want it installed when you do 'make install' +PREFIX=/usr + + +OBJS= blocksort.o \ + huffman.o \ + crctable.o \ + randtable.o \ + compress.o \ + decompress.o \ + bzlib.o + +all: libbz2.a bzip2 bzip2recover test + +bzip2: libbz2.a bzip2.o + $(CC) $(CFLAGS) $(LDFLAGS) -o bzip2 bzip2.o -L. -lbz2 + +bzip2recover: bzip2recover.o + $(CC) $(CFLAGS) $(LDFLAGS) -o bzip2recover bzip2recover.o + +libbz2.a: $(OBJS) + rm -f libbz2.a + $(AR) cq libbz2.a $(OBJS) + @if ( test -f $(RANLIB) -o -f /usr/bin/ranlib -o \ + -f /bin/ranlib -o -f /usr/ccs/bin/ranlib ) ; then \ + echo $(RANLIB) libbz2.a ; \ + $(RANLIB) libbz2.a ; \ + fi + +check: test +test: bzip2 + @cat words1 + ./bzip2 -1 < sample1.ref > sample1.rb2 + ./bzip2 -2 < sample2.ref > sample2.rb2 + ./bzip2 -3 < sample3.ref > sample3.rb2 + ./bzip2 -d < sample1.bz2 > sample1.tst + ./bzip2 -d < sample2.bz2 > sample2.tst + ./bzip2 -ds < sample3.bz2 > sample3.tst + cmp sample1.bz2 sample1.rb2 + cmp sample2.bz2 sample2.rb2 + cmp sample3.bz2 sample3.rb2 + cmp sample1.tst sample1.ref + cmp sample2.tst sample2.ref + cmp sample3.tst sample3.ref + @cat words3 + +install: bzip2 bzip2recover + if ( test ! -d $(PREFIX)/bin ) ; then mkdir -p $(PREFIX)/bin ; fi + if ( test ! -d $(PREFIX)/lib ) ; then mkdir -p $(PREFIX)/lib ; fi + if ( test ! -d $(PREFIX)/man ) ; then mkdir -p $(PREFIX)/man ; fi + if ( test ! -d $(PREFIX)/man/man1 ) ; then mkdir -p $(PREFIX)/man/man1 ; fi + if ( test ! -d $(PREFIX)/include ) ; then mkdir -p $(PREFIX)/include ; fi + cp -f bzip2 $(PREFIX)/bin/bzip2 + cp -f bzip2 $(PREFIX)/bin/bunzip2 + cp -f bzip2 $(PREFIX)/bin/bzcat + cp -f bzip2recover $(PREFIX)/bin/bzip2recover + chmod a+x $(PREFIX)/bin/bzip2 + chmod a+x $(PREFIX)/bin/bunzip2 + chmod a+x $(PREFIX)/bin/bzcat + chmod a+x $(PREFIX)/bin/bzip2recover + cp -f bzip2.1 $(PREFIX)/man/man1 + chmod a+r $(PREFIX)/man/man1/bzip2.1 + cp -f bzlib.h $(PREFIX)/include + chmod a+r $(PREFIX)/include/bzlib.h + cp -f libbz2.a $(PREFIX)/lib + chmod a+r $(PREFIX)/lib/libbz2.a + cp -f bzgrep $(PREFIX)/bin/bzgrep + ln $(PREFIX)/bin/bzgrep $(PREFIX)/bin/bzegrep + ln $(PREFIX)/bin/bzgrep $(PREFIX)/bin/bzfgrep + chmod a+x $(PREFIX)/bin/bzgrep + cp -f bzmore $(PREFIX)/bin/bzmore + ln $(PREFIX)/bin/bzmore $(PREFIX)/bin/bzless + chmod a+x $(PREFIX)/bin/bzmore + cp -f bzdiff $(PREFIX)/bin/bzdiff + ln $(PREFIX)/bin/bzdiff $(PREFIX)/bin/bzcmp + chmod a+x $(PREFIX)/bin/bzdiff + cp -f bzgrep.1 bzmore.1 bzdiff.1 $(PREFIX)/man/man1 + chmod a+r $(PREFIX)/man/man1/bzgrep.1 + chmod a+r $(PREFIX)/man/man1/bzmore.1 + chmod a+r $(PREFIX)/man/man1/bzdiff.1 + echo ".so man1/bzgrep.1" > $(PREFIX)/man/man1/bzegrep.1 + echo ".so man1/bzgrep.1" > $(PREFIX)/man/man1/bzfgrep.1 + echo ".so man1/bzmore.1" > $(PREFIX)/man/man1/bzless.1 + echo ".so man1/bzdiff.1" > $(PREFIX)/man/man1/bzcmp.1 + +clean: + rm -f *.o libbz2.a bzip2 bzip2recover \ + sample1.rb2 sample2.rb2 sample3.rb2 \ + sample1.tst sample2.tst sample3.tst + +blocksort.o: blocksort.c + @cat words0 + $(CC) $(CFLAGS) -c blocksort.c +huffman.o: huffman.c + $(CC) $(CFLAGS) -c huffman.c +crctable.o: crctable.c + $(CC) $(CFLAGS) -c crctable.c +randtable.o: randtable.c + $(CC) $(CFLAGS) -c randtable.c +compress.o: compress.c + $(CC) $(CFLAGS) -c compress.c +decompress.o: decompress.c + $(CC) $(CFLAGS) -c decompress.c +bzlib.o: bzlib.c + $(CC) $(CFLAGS) -c bzlib.c +bzip2.o: bzip2.c + $(CC) $(CFLAGS) -c bzip2.c +bzip2recover.o: bzip2recover.c + $(CC) $(CFLAGS) -c bzip2recover.c + + +distclean: clean + rm -f manual.ps manual.html manual.pdf + +DISTNAME=bzip2-1.0.3 +dist: check manual + rm -f $(DISTNAME) + ln -sf . $(DISTNAME) + tar cvf $(DISTNAME).tar \ + $(DISTNAME)/blocksort.c \ + $(DISTNAME)/huffman.c \ + $(DISTNAME)/crctable.c \ + $(DISTNAME)/randtable.c \ + $(DISTNAME)/compress.c \ + $(DISTNAME)/decompress.c \ + $(DISTNAME)/bzlib.c \ + $(DISTNAME)/bzip2.c \ + $(DISTNAME)/bzip2recover.c \ + $(DISTNAME)/bzlib.h \ + $(DISTNAME)/bzlib_private.h \ + $(DISTNAME)/Makefile \ + $(DISTNAME)/LICENSE \ + $(DISTNAME)/bzip2.1 \ + $(DISTNAME)/bzip2.1.preformatted \ + $(DISTNAME)/bzip2.txt \ + $(DISTNAME)/words0 \ + $(DISTNAME)/words1 \ + $(DISTNAME)/words2 \ + $(DISTNAME)/words3 \ + $(DISTNAME)/sample1.ref \ + $(DISTNAME)/sample2.ref \ + $(DISTNAME)/sample3.ref \ + $(DISTNAME)/sample1.bz2 \ + $(DISTNAME)/sample2.bz2 \ + $(DISTNAME)/sample3.bz2 \ + $(DISTNAME)/dlltest.c \ + $(DISTNAME)/manual.html \ + $(DISTNAME)/manual.pdf \ + $(DISTNAME)/manual.ps \ + $(DISTNAME)/README \ + $(DISTNAME)/README.COMPILATION.PROBLEMS \ + $(DISTNAME)/README.XML.STUFF \ + $(DISTNAME)/CHANGES \ + $(DISTNAME)/libbz2.def \ + $(DISTNAME)/libbz2.dsp \ + $(DISTNAME)/dlltest.dsp \ + $(DISTNAME)/makefile.msc \ + $(DISTNAME)/Y2K_INFO \ + $(DISTNAME)/unzcrash.c \ + $(DISTNAME)/spewG.c \ + $(DISTNAME)/mk251.c \ + $(DISTNAME)/bzdiff \ + $(DISTNAME)/bzdiff.1 \ + $(DISTNAME)/bzmore \ + $(DISTNAME)/bzmore.1 \ + $(DISTNAME)/bzgrep \ + $(DISTNAME)/bzgrep.1 \ + $(DISTNAME)/Makefile-libbz2_so \ + $(DISTNAME)/bz-common.xsl \ + $(DISTNAME)/bz-fo.xsl \ + $(DISTNAME)/bz-html.xsl \ + $(DISTNAME)/bzip.css \ + $(DISTNAME)/entities.xml \ + $(DISTNAME)/manual.xml \ + $(DISTNAME)/format.pl \ + $(DISTNAME)/xmlproc.sh + gzip -v $(DISTNAME).tar + +# For rebuilding the manual from sources on my SuSE 9.1 box + +MANUAL_SRCS= bz-common.xsl bz-fo.xsl bz-html.xsl bzip.css \ + entities.xml manual.xml + +manual: manual.html manual.ps manual.pdf + +manual.ps: $(MANUAL_SRCS) + ./xmlproc.sh -ps manual.xml + +manual.pdf: $(MANUAL_SRCS) + ./xmlproc.sh -pdf manual.xml + +manual.html: $(MANUAL_SRCS) + ./xmlproc.sh -html manual.xml diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/Makefile-libbz2_so b/contrib/vmap_extractor_v2/stormlib/bzip2/Makefile-libbz2_so new file mode 100644 index 00000000000..458c5a135e7 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/bzip2/Makefile-libbz2_so @@ -0,0 +1,44 @@ + +# This Makefile builds a shared version of the library, +# libbz2.so.1.0.3, with soname libbz2.so.1.0, +# at least on x86-Linux (RedHat 7.2), +# with gcc-2.96 20000731 (Red Hat Linux 7.1 2.96-98). +# Please see the README file for some +# important info about building the library like this. + +SHELL=/bin/sh +CC=gcc +BIGFILES=-D_FILE_OFFSET_BITS=64 +CFLAGS=-fpic -fPIC -Wall -Winline -O -g + +OBJS= blocksort.o \ + huffman.o \ + crctable.o \ + randtable.o \ + compress.o \ + decompress.o \ + bzlib.o + +all: $(OBJS) + $(CC) -shared -Wl,-soname -Wl,libbz2.so.1.0 -o libbz2.so.1.0.3 $(OBJS) + $(CC) $(CFLAGS) -o bzip2-shared bzip2.c libbz2.so.1.0.3 + rm -f libbz2.so.1.0 + ln -s libbz2.so.1.0.3 libbz2.so.1.0 + +clean: + rm -f $(OBJS) bzip2.o libbz2.so.1.0.3 libbz2.so.1.0 bzip2-shared + +blocksort.o: blocksort.c + $(CC) $(CFLAGS) -c blocksort.c +huffman.o: huffman.c + $(CC) $(CFLAGS) -c huffman.c +crctable.o: crctable.c + $(CC) $(CFLAGS) -c crctable.c +randtable.o: randtable.c + $(CC) $(CFLAGS) -c randtable.c +compress.o: compress.c + $(CC) $(CFLAGS) -c compress.c +decompress.o: decompress.c + $(CC) $(CFLAGS) -c decompress.c +bzlib.o: bzlib.c + $(CC) $(CFLAGS) -c bzlib.c diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/README b/contrib/vmap_extractor_v2/stormlib/bzip2/README new file mode 100644 index 00000000000..1aff4487e8c --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/bzip2/README @@ -0,0 +1,185 @@ + +This is the README for bzip2, a block-sorting file compressor, version +1.0.3. This version is fully compatible with the previous public +releases, versions 0.1pl2, 0.9.0, 0.9.5, 1.0.0, 1.0.1 and 1.0.2. + +bzip2-1.0.3 is distributed under a BSD-style license. For details, +see the file LICENSE. + +Complete documentation is available in Postscript form (manual.ps), +PDF (manual.pdf) or html (manual.html). A plain-text version of the +manual page is available as bzip2.txt. A statement about Y2K issues +is now included in the file Y2K_INFO. + + +HOW TO BUILD -- UNIX + +Type `make'. This builds the library libbz2.a and then the +programs bzip2 and bzip2recover. Six self-tests are run. +If the self-tests complete ok, carry on to installation: + +To install in /usr/bin, /usr/lib, /usr/man and /usr/include, type + make install +To install somewhere else, eg, /xxx/yyy/{bin,lib,man,include}, type + make install PREFIX=/xxx/yyy +If you are (justifiably) paranoid and want to see what 'make install' +is going to do, you can first do + make -n install or + make -n install PREFIX=/xxx/yyy respectively. +The -n instructs make to show the commands it would execute, but +not actually execute them. + + +HOW TO BUILD -- UNIX, shared library libbz2.so. + +Do 'make -f Makefile-libbz2_so'. This Makefile seems to work for +Linux-ELF (RedHat 7.2 on an x86 box), with gcc. I make no claims +that it works for any other platform, though I suspect it probably +will work for most platforms employing both ELF and gcc. + +bzip2-shared, a client of the shared library, is also built, but not +self-tested. So I suggest you also build using the normal Makefile, +since that conducts a self-test. A second reason to prefer the +version statically linked to the library is that, on x86 platforms, +building shared objects makes a valuable register (%ebx) unavailable +to gcc, resulting in a slowdown of 10%-20%, at least for bzip2. + +Important note for people upgrading .so's from 0.9.0/0.9.5 to version +1.0.X. All the functions in the library have been renamed, from (eg) +bzCompress to BZ2_bzCompress, to avoid namespace pollution. +Unfortunately this means that the libbz2.so created by +Makefile-libbz2_so will not work with any program which used an older +version of the library. Sorry. I do encourage library clients to +make the effort to upgrade to use version 1.0, since it is both faster +and more robust than previous versions. + + +HOW TO BUILD -- Windows 95, NT, DOS, Mac, etc. + +It's difficult for me to support compilation on all these platforms. +My approach is to collect binaries for these platforms, and put them +on the master web page (http://sources.redhat.com/bzip2). Look there. +However (FWIW), bzip2-1.0.X is very standard ANSI C and should compile +unmodified with MS Visual C. If you have difficulties building, you +might want to read README.COMPILATION.PROBLEMS. + +At least using MS Visual C++ 6, you can build from the unmodified +sources by issuing, in a command shell: + nmake -f makefile.msc +(you may need to first run the MSVC-provided script VCVARS32.BAT + so as to set up paths to the MSVC tools correctly). + + +VALIDATION + +Correct operation, in the sense that a compressed file can always be +decompressed to reproduce the original, is obviously of paramount +importance. To validate bzip2, I used a modified version of Mark +Nelson's churn program. Churn is an automated test driver which +recursively traverses a directory structure, using bzip2 to compress +and then decompress each file it encounters, and checking that the +decompressed data is the same as the original. + + + +Please read and be aware of the following: + +WARNING: + + This program (attempts to) compress data by performing several + non-trivial transformations on it. Unless you are 100% familiar + with *all* the algorithms contained herein, and with the + consequences of modifying them, you should NOT meddle with the + compression or decompression machinery. Incorrect changes can and + very likely *will* lead to disastrous loss of data. + + +DISCLAIMER: + + I TAKE NO RESPONSIBILITY FOR ANY LOSS OF DATA ARISING FROM THE + USE OF THIS PROGRAM, HOWSOEVER CAUSED. + + Every compression of a file implies an assumption that the + compressed file can be decompressed to reproduce the original. + Great efforts in design, coding and testing have been made to + ensure that this program works correctly. However, the complexity + of the algorithms, and, in particular, the presence of various + special cases in the code which occur with very low but non-zero + probability make it impossible to rule out the possibility of bugs + remaining in the program. DO NOT COMPRESS ANY DATA WITH THIS + PROGRAM UNLESS YOU ARE PREPARED TO ACCEPT THE POSSIBILITY, HOWEVER + SMALL, THAT THE DATA WILL NOT BE RECOVERABLE. + + That is not to say this program is inherently unreliable. Indeed, + I very much hope the opposite is true. bzip2 has been carefully + constructed and extensively tested. + + +PATENTS: + + To the best of my knowledge, bzip2 does not use any patented + algorithms. However, I do not have the resources to carry out + a patent search. Therefore I cannot give any guarantee of the + above statement. + +End of legalities. + + +WHAT'S NEW IN 0.9.0 (as compared to 0.1pl2) ? + + * Approx 10% faster compression, 30% faster decompression + * -t (test mode) is a lot quicker + * Can decompress concatenated compressed files + * Programming interface, so programs can directly read/write .bz2 files + * Less restrictive (BSD-style) licensing + * Flag handling more compatible with GNU gzip + * Much more documentation, i.e., a proper user manual + * Hopefully, improved portability (at least of the library) + +WHAT'S NEW IN 0.9.5 ? + + * Compression speed is much less sensitive to the input + data than in previous versions. Specifically, the very + slow performance caused by repetitive data is fixed. + * Many small improvements in file and flag handling. + * A Y2K statement. + +WHAT'S NEW IN 1.0.0 ? + + See the CHANGES file. + +WHAT'S NEW IN 1.0.2 ? + + See the CHANGES file. + +WHAT'S NEW IN 1.0.3 ? + + See the CHANGES file. + + +I hope you find bzip2 useful. Feel free to contact me at + jseward@bzip.org +if you have any suggestions or queries. Many people mailed me with +comments, suggestions and patches after the releases of bzip-0.15, +bzip-0.21, and bzip2 versions 0.1pl2, 0.9.0, 0.9.5, 1.0.0, 1.0.1 and +1.0.2, and the changes in bzip2 are largely a result of this feedback. +I thank you for your comments. + +At least for the time being, bzip2's "home" is (or can be reached via) +http://www.bzip.org + +Julian Seward +jseward@bzip.org + +Cambridge, UK. + +18 July 1996 (version 0.15) +25 August 1996 (version 0.21) + 7 August 1997 (bzip2, version 0.1) +29 August 1997 (bzip2, version 0.1pl2) +23 August 1998 (bzip2, version 0.9.0) + 8 June 1999 (bzip2, version 0.9.5) + 4 Sept 1999 (bzip2, version 0.9.5d) + 5 May 2000 (bzip2, version 1.0pre8) +30 December 2001 (bzip2, version 1.0.2pre1) +15 February 2005 (bzip2, version 1.0.3) diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/README.COMPILATION.PROBLEMS b/contrib/vmap_extractor_v2/stormlib/bzip2/README.COMPILATION.PROBLEMS new file mode 100644 index 00000000000..f1bc396b765 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/bzip2/README.COMPILATION.PROBLEMS @@ -0,0 +1,39 @@ + +bzip2-1.0.3 should compile without problems on the vast majority of +platforms. Using the supplied Makefile, I've built and tested it +myself for x86-linux and x86_64-linux. With makefile.msc, Visual C++ +6.0 and nmake, you can build a native Win32 version too. Large file +support seems to work correctly on at least alpha-tru64unix and +x86-cygwin32 (on Windows 2000). + +When I say "large file" I mean a file of size 2,147,483,648 (2^31) +bytes or above. Many older OSs can't handle files above this size, +but many newer ones can. Large files are pretty huge -- most files +you'll encounter are not Large Files. + +Earlier versions of bzip2 (0.1, 0.9.0, 0.9.5) compiled on a wide +variety of platforms without difficulty, and I hope this version will +continue in that tradition. However, in order to support large files, +I've had to include the define -D_FILE_OFFSET_BITS=64 in the Makefile. +This can cause problems. + +The technique of adding -D_FILE_OFFSET_BITS=64 to get large file +support is, as far as I know, the Recommended Way to get correct large +file support. For more details, see the Large File Support +Specification, published by the Large File Summit, at + http://ftp.sas.com/standards/large.file + +As a general comment, if you get compilation errors which you think +are related to large file support, try removing the above define from +the Makefile, ie, delete the line + BIGFILES=-D_FILE_OFFSET_BITS=64 +from the Makefile, and do 'make clean ; make'. This will give you a +version of bzip2 without large file support, which, for most +applications, is probably not a problem. + +Alternatively, try some of the platform-specific hints listed below. + +You can use the spewG.c program to generate huge files to test bzip2's +large file support, if you are feeling paranoid. Be aware though that +any compilation problems which affect bzip2 will also affect spewG.c, +alas. diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/README.XML.STUFF b/contrib/vmap_extractor_v2/stormlib/bzip2/README.XML.STUFF new file mode 100644 index 00000000000..0ff209f4466 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/bzip2/README.XML.STUFF @@ -0,0 +1,31 @@ +The script xmlproc.sh takes an xml file as input, +and processes it to create .pdf, .html or .ps output. +It uses format.pl, a perl script to format
 blocks nicely,
+ and add CDATA tags so writers do not have to use eg. < 
+
+The file "entities.xml" must be edited to reflect current
+version, year, etc.
+
+
+Usage:
+
+  xmlproc.sh -v manual.xml
+  Validates an xml file to ensure no dtd-compliance errors
+
+  xmlproc.sh -html manual.xml
+  Output: manual.html
+
+  xmlproc.sh -pdf manual.xml
+  Output: manual.pdf
+
+  xmlproc.sh -ps manual.xml
+  Output: manual.ps
+
+
+Notum bene: 
+- pdfxmltex barfs if given a filename with an underscore in it
+
+- xmltex won't work yet - there's a bug in passivetex
+    which we are all waiting for Sebastian to fix.
+  So we are going the xml -> pdf -> ps route for the time being,
+    using pdfxmltex.
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/Y2K_INFO b/contrib/vmap_extractor_v2/stormlib/bzip2/Y2K_INFO
new file mode 100644
index 00000000000..55fd56a2edb
--- /dev/null
+++ b/contrib/vmap_extractor_v2/stormlib/bzip2/Y2K_INFO
@@ -0,0 +1,34 @@
+
+Y2K status of bzip2 and libbzip2, versions 0.1, 0.9.0 and 0.9.5
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Informally speaking:
+   bzip2 is a compression program built on top of libbzip2, 
+   a library which does the real work of compression and 
+   decompression.  As far as I am aware, libbzip2 does not have 
+   any date-related code at all.
+
+   bzip2 itself copies dates from source to destination files 
+   when compressing or decompressing, using the 'stat' and 'utime' 
+   UNIX system calls.  It doesn't examine, manipulate or store the 
+   dates in any way.  So as far as I can see, there shouldn't be any 
+   problem with bzip2 providing 'stat' and 'utime' work correctly 
+   on your system.
+
+   On non-unix platforms (those for which BZ_UNIX in bzip2.c is
+   not set to 1), bzip2 doesn't even do the date copying.
+
+   Overall, informally speaking, I don't think bzip2 or libbzip2 
+   have a Y2K problem.
+
+Formally speaking:
+   I am not prepared to offer you any assurance whatsoever 
+   regarding Y2K issues in my software.  You alone assume the 
+   entire risk of using the software.  The disclaimer of liability 
+   in the LICENSE file in the bzip2 source distribution continues 
+   to apply on this issue as with every other issue pertaining 
+   to the software.
+
+Julian Seward
+Cambridge, UK
+25 August 1999
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/blocksort.c b/contrib/vmap_extractor_v2/stormlib/bzip2/blocksort.c
new file mode 100644
index 00000000000..33ec9f5dcb0
--- /dev/null
+++ b/contrib/vmap_extractor_v2/stormlib/bzip2/blocksort.c
@@ -0,0 +1,1141 @@
+
+/*-------------------------------------------------------------*/
+/*--- Block sorting machinery                               ---*/
+/*---                                           blocksort.c ---*/
+/*-------------------------------------------------------------*/
+
+/*--
+  This file is a part of bzip2 and/or libbzip2, a program and
+  library for lossless, block-sorting data compression.
+
+  Copyright (C) 1996-2005 Julian R Seward.  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+  2. The origin of this software must not be misrepresented; you must 
+     not claim that you wrote the original software.  If you use this 
+     software in a product, an acknowledgment in the product 
+     documentation would be appreciated but is not required.
+
+  3. Altered source versions must be plainly marked as such, and must
+     not be misrepresented as being the original software.
+
+  4. The name of the author may not be used to endorse or promote 
+     products derived from this software without specific prior written 
+     permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  Julian Seward, Cambridge, UK.
+  jseward@bzip.org
+  bzip2/libbzip2 version 1.0 of 21 March 2000
+
+  This program is based on (at least) the work of:
+     Mike Burrows
+     David Wheeler
+     Peter Fenwick
+     Alistair Moffat
+     Radford Neal
+     Ian H. Witten
+     Robert Sedgewick
+     Jon L. Bentley
+
+  For more information on these sources, see the manual.
+
+  To get some idea how the block sorting algorithms in this file 
+  work, read my paper 
+     On the Performance of BWT Sorting Algorithms
+  in Proceedings of the IEEE Data Compression Conference 2000,
+  Snowbird, Utah, USA, 27-30 March 2000.  The main sort in this
+  file implements the algorithm called  cache  in the paper.
+--*/
+
+
+#include "bzlib_private.h"
+
+/*---------------------------------------------*/
+/*--- Fallback O(N log(N)^2) sorting        ---*/
+/*--- algorithm, for repetitive blocks      ---*/
+/*---------------------------------------------*/
+
+/*---------------------------------------------*/
+static 
+__inline__
+void fallbackSimpleSort ( UInt32* fmap, 
+                          UInt32* eclass, 
+                          Int32   lo, 
+                          Int32   hi )
+{
+   Int32 i, j, tmp;
+   UInt32 ec_tmp;
+
+   if (lo == hi) return;
+
+   if (hi - lo > 3) {
+      for ( i = hi-4; i >= lo; i-- ) {
+         tmp = fmap[i];
+         ec_tmp = eclass[tmp];
+         for ( j = i+4; j <= hi && ec_tmp > eclass[fmap[j]]; j += 4 )
+            fmap[j-4] = fmap[j];
+         fmap[j-4] = tmp;
+      }
+   }
+
+   for ( i = hi-1; i >= lo; i-- ) {
+      tmp = fmap[i];
+      ec_tmp = eclass[tmp];
+      for ( j = i+1; j <= hi && ec_tmp > eclass[fmap[j]]; j++ )
+         fmap[j-1] = fmap[j];
+      fmap[j-1] = tmp;
+   }
+}
+
+
+/*---------------------------------------------*/
+#define fswap(zz1, zz2) \
+   { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
+
+#define fvswap(zzp1, zzp2, zzn)       \
+{                                     \
+   Int32 yyp1 = (zzp1);               \
+   Int32 yyp2 = (zzp2);               \
+   Int32 yyn  = (zzn);                \
+   while (yyn > 0) {                  \
+      fswap(fmap[yyp1], fmap[yyp2]);  \
+      yyp1++; yyp2++; yyn--;          \
+   }                                  \
+}
+
+
+#define fmin(a,b) ((a) < (b)) ? (a) : (b)
+
+#define fpush(lz,hz) { stackLo[sp] = lz; \
+                       stackHi[sp] = hz; \
+                       sp++; }
+
+#define fpop(lz,hz) { sp--;              \
+                      lz = stackLo[sp];  \
+                      hz = stackHi[sp]; }
+
+#define FALLBACK_QSORT_SMALL_THRESH 10
+#define FALLBACK_QSORT_STACK_SIZE   100
+
+
+static
+void fallbackQSort3 ( UInt32* fmap, 
+                      UInt32* eclass,
+                      Int32   loSt, 
+                      Int32   hiSt )
+{
+   Int32 unLo, unHi, ltLo, gtHi, n, m;
+   Int32 sp, lo, hi;
+   UInt32 med, r, r3;
+   Int32 stackLo[FALLBACK_QSORT_STACK_SIZE];
+   Int32 stackHi[FALLBACK_QSORT_STACK_SIZE];
+
+   r = 0;
+
+   sp = 0;
+   fpush ( loSt, hiSt );
+
+   while (sp > 0) {
+
+      AssertH ( sp < FALLBACK_QSORT_STACK_SIZE, 1004 );
+
+      fpop ( lo, hi );
+      if (hi - lo < FALLBACK_QSORT_SMALL_THRESH) {
+         fallbackSimpleSort ( fmap, eclass, lo, hi );
+         continue;
+      }
+
+      /* Random partitioning.  Median of 3 sometimes fails to
+         avoid bad cases.  Median of 9 seems to help but 
+         looks rather expensive.  This too seems to work but
+         is cheaper.  Guidance for the magic constants 
+         7621 and 32768 is taken from Sedgewick's algorithms
+         book, chapter 35.
+      */
+      r = ((r * 7621) + 1) % 32768;
+      r3 = r % 3;
+      if (r3 == 0) med = eclass[fmap[lo]]; else
+      if (r3 == 1) med = eclass[fmap[(lo+hi)>>1]]; else
+                   med = eclass[fmap[hi]];
+
+      unLo = ltLo = lo;
+      unHi = gtHi = hi;
+
+      while (1) {
+         while (1) {
+            if (unLo > unHi) break;
+            n = (Int32)eclass[fmap[unLo]] - (Int32)med;
+            if (n == 0) { 
+               fswap(fmap[unLo], fmap[ltLo]); 
+               ltLo++; unLo++; 
+               continue; 
+            };
+            if (n > 0) break;
+            unLo++;
+         }
+         while (1) {
+            if (unLo > unHi) break;
+            n = (Int32)eclass[fmap[unHi]] - (Int32)med;
+            if (n == 0) { 
+               fswap(fmap[unHi], fmap[gtHi]); 
+               gtHi--; unHi--; 
+               continue; 
+            };
+            if (n < 0) break;
+            unHi--;
+         }
+         if (unLo > unHi) break;
+         fswap(fmap[unLo], fmap[unHi]); unLo++; unHi--;
+      }
+
+      AssertD ( unHi == unLo-1, "fallbackQSort3(2)" );
+
+      if (gtHi < ltLo) continue;
+
+      n = fmin(ltLo-lo, unLo-ltLo); fvswap(lo, unLo-n, n);
+      m = fmin(hi-gtHi, gtHi-unHi); fvswap(unLo, hi-m+1, m);
+
+      n = lo + unLo - ltLo - 1;
+      m = hi - (gtHi - unHi) + 1;
+
+      if (n - lo > hi - m) {
+         fpush ( lo, n );
+         fpush ( m, hi );
+      } else {
+         fpush ( m, hi );
+         fpush ( lo, n );
+      }
+   }
+}
+
+#undef fmin
+#undef fpush
+#undef fpop
+#undef fswap
+#undef fvswap
+#undef FALLBACK_QSORT_SMALL_THRESH
+#undef FALLBACK_QSORT_STACK_SIZE
+
+
+/*---------------------------------------------*/
+/* Pre:
+      nblock > 0
+      eclass exists for [0 .. nblock-1]
+      ((UChar*)eclass) [0 .. nblock-1] holds block
+      ptr exists for [0 .. nblock-1]
+
+   Post:
+      ((UChar*)eclass) [0 .. nblock-1] holds block
+      All other areas of eclass destroyed
+      fmap [0 .. nblock-1] holds sorted order
+      bhtab [ 0 .. 2+(nblock/32) ] destroyed
+*/
+
+#define       SET_BH(zz)  bhtab[(zz) >> 5] |= (1 << ((zz) & 31))
+#define     CLEAR_BH(zz)  bhtab[(zz) >> 5] &= ~(1 << ((zz) & 31))
+#define     ISSET_BH(zz)  (bhtab[(zz) >> 5] & (1 << ((zz) & 31)))
+#define      WORD_BH(zz)  bhtab[(zz) >> 5]
+#define UNALIGNED_BH(zz)  ((zz) & 0x01f)
+
+static
+void fallbackSort ( UInt32* fmap, 
+                    UInt32* eclass, 
+                    UInt32* bhtab,
+                    Int32   nblock,
+                    Int32   verb )
+{
+   Int32 ftab[257];
+   Int32 ftabCopy[256];
+   Int32 H, i, j, k, l, r, cc, cc1;
+   Int32 nNotDone;
+   Int32 nBhtab;
+   UChar* eclass8 = (UChar*)eclass;
+
+   /*--
+      Initial 1-char radix sort to generate
+      initial fmap and initial BH bits.
+   --*/
+   if (verb >= 4)
+      VPrintf0 ( "        bucket sorting ...\n" );
+   for (i = 0; i < 257;    i++) ftab[i] = 0;
+   for (i = 0; i < nblock; i++) ftab[eclass8[i]]++;
+   for (i = 0; i < 256;    i++) ftabCopy[i] = ftab[i];
+   for (i = 1; i < 257;    i++) ftab[i] += ftab[i-1];
+
+   for (i = 0; i < nblock; i++) {
+      j = eclass8[i];
+      k = ftab[j] - 1;
+      ftab[j] = k;
+      fmap[k] = i;
+   }
+
+   nBhtab = 2 + (nblock / 32);
+   for (i = 0; i < nBhtab; i++) bhtab[i] = 0;
+   for (i = 0; i < 256; i++) SET_BH(ftab[i]);
+
+   /*--
+      Inductively refine the buckets.  Kind-of an
+      "exponential radix sort" (!), inspired by the
+      Manber-Myers suffix array construction algorithm.
+   --*/
+
+   /*-- set sentinel bits for block-end detection --*/
+   for (i = 0; i < 32; i++) { 
+      SET_BH(nblock + 2*i);
+      CLEAR_BH(nblock + 2*i + 1);
+   }
+
+   /*-- the log(N) loop --*/
+   H = 1;
+   while (1) {
+
+      if (verb >= 4) 
+         VPrintf1 ( "        depth %6d has ", H );
+
+      j = 0;
+      for (i = 0; i < nblock; i++) {
+         if (ISSET_BH(i)) j = i;
+         k = fmap[i] - H; if (k < 0) k += nblock;
+         eclass[k] = j;
+      }
+
+      nNotDone = 0;
+      r = -1;
+      while (1) {
+
+	 /*-- find the next non-singleton bucket --*/
+         k = r + 1;
+         while (ISSET_BH(k) && UNALIGNED_BH(k)) k++;
+         if (ISSET_BH(k)) {
+            while (WORD_BH(k) == 0xffffffff) k += 32;
+            while (ISSET_BH(k)) k++;
+         }
+         l = k - 1;
+         if (l >= nblock) break;
+         while (!ISSET_BH(k) && UNALIGNED_BH(k)) k++;
+         if (!ISSET_BH(k)) {
+            while (WORD_BH(k) == 0x00000000) k += 32;
+            while (!ISSET_BH(k)) k++;
+         }
+         r = k - 1;
+         if (r >= nblock) break;
+
+         /*-- now [l, r] bracket current bucket --*/
+         if (r > l) {
+            nNotDone += (r - l + 1);
+            fallbackQSort3 ( fmap, eclass, l, r );
+
+            /*-- scan bucket and generate header bits-- */
+            cc = -1;
+            for (i = l; i <= r; i++) {
+               cc1 = eclass[fmap[i]];
+               if (cc != cc1) { SET_BH(i); cc = cc1; };
+            }
+         }
+      }
+
+      if (verb >= 4) 
+         VPrintf1 ( "%6d unresolved strings\n", nNotDone );
+
+      H *= 2;
+      if (H > nblock || nNotDone == 0) break;
+   }
+
+   /*-- 
+      Reconstruct the original block in
+      eclass8 [0 .. nblock-1], since the
+      previous phase destroyed it.
+   --*/
+   if (verb >= 4)
+      VPrintf0 ( "        reconstructing block ...\n" );
+   j = 0;
+   for (i = 0; i < nblock; i++) {
+      while (ftabCopy[j] == 0) j++;
+      ftabCopy[j]--;
+      eclass8[fmap[i]] = (UChar)j;
+   }
+   AssertH ( j < 256, 1005 );
+}
+
+#undef       SET_BH
+#undef     CLEAR_BH
+#undef     ISSET_BH
+#undef      WORD_BH
+#undef UNALIGNED_BH
+
+
+/*---------------------------------------------*/
+/*--- The main, O(N^2 log(N)) sorting       ---*/
+/*--- algorithm.  Faster for "normal"       ---*/
+/*--- non-repetitive blocks.                ---*/
+/*---------------------------------------------*/
+
+/*---------------------------------------------*/
+static
+__inline__
+Bool mainGtU ( UInt32  i1, 
+               UInt32  i2,
+               UChar*  block, 
+               UInt16* quadrant,
+               UInt32  nblock,
+               Int32*  budget )
+{
+   Int32  k;
+   UChar  c1, c2;
+   UInt16 s1, s2;
+
+   AssertD ( i1 != i2, "mainGtU" );
+   /* 1 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 2 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 3 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 4 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 5 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 6 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 7 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 8 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 9 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 10 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 11 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 12 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+
+   k = nblock + 8;
+
+   do {
+      /* 1 */
+      c1 = block[i1]; c2 = block[i2];
+      if (c1 != c2) return (c1 > c2);
+      s1 = quadrant[i1]; s2 = quadrant[i2];
+      if (s1 != s2) return (s1 > s2);
+      i1++; i2++;
+      /* 2 */
+      c1 = block[i1]; c2 = block[i2];
+      if (c1 != c2) return (c1 > c2);
+      s1 = quadrant[i1]; s2 = quadrant[i2];
+      if (s1 != s2) return (s1 > s2);
+      i1++; i2++;
+      /* 3 */
+      c1 = block[i1]; c2 = block[i2];
+      if (c1 != c2) return (c1 > c2);
+      s1 = quadrant[i1]; s2 = quadrant[i2];
+      if (s1 != s2) return (s1 > s2);
+      i1++; i2++;
+      /* 4 */
+      c1 = block[i1]; c2 = block[i2];
+      if (c1 != c2) return (c1 > c2);
+      s1 = quadrant[i1]; s2 = quadrant[i2];
+      if (s1 != s2) return (s1 > s2);
+      i1++; i2++;
+      /* 5 */
+      c1 = block[i1]; c2 = block[i2];
+      if (c1 != c2) return (c1 > c2);
+      s1 = quadrant[i1]; s2 = quadrant[i2];
+      if (s1 != s2) return (s1 > s2);
+      i1++; i2++;
+      /* 6 */
+      c1 = block[i1]; c2 = block[i2];
+      if (c1 != c2) return (c1 > c2);
+      s1 = quadrant[i1]; s2 = quadrant[i2];
+      if (s1 != s2) return (s1 > s2);
+      i1++; i2++;
+      /* 7 */
+      c1 = block[i1]; c2 = block[i2];
+      if (c1 != c2) return (c1 > c2);
+      s1 = quadrant[i1]; s2 = quadrant[i2];
+      if (s1 != s2) return (s1 > s2);
+      i1++; i2++;
+      /* 8 */
+      c1 = block[i1]; c2 = block[i2];
+      if (c1 != c2) return (c1 > c2);
+      s1 = quadrant[i1]; s2 = quadrant[i2];
+      if (s1 != s2) return (s1 > s2);
+      i1++; i2++;
+
+      if (i1 >= nblock) i1 -= nblock;
+      if (i2 >= nblock) i2 -= nblock;
+
+      k -= 8;
+      (*budget)--;
+   }
+      while (k >= 0);
+
+   return False;
+}
+
+
+/*---------------------------------------------*/
+/*--
+   Knuth's increments seem to work better
+   than Incerpi-Sedgewick here.  Possibly
+   because the number of elems to sort is
+   usually small, typically <= 20.
+--*/
+static
+Int32 incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280,
+                   9841, 29524, 88573, 265720,
+                   797161, 2391484 };
+
+static
+void mainSimpleSort ( UInt32* ptr,
+                      UChar*  block,
+                      UInt16* quadrant,
+                      Int32   nblock,
+                      Int32   lo, 
+                      Int32   hi, 
+                      Int32   d,
+                      Int32*  budget )
+{
+   Int32 i, j, h, bigN, hp;
+   UInt32 v;
+
+   bigN = hi - lo + 1;
+   if (bigN < 2) return;
+
+   hp = 0;
+   while (incs[hp] < bigN) hp++;
+   hp--;
+
+   for (; hp >= 0; hp--) {
+      h = incs[hp];
+
+      i = lo + h;
+      while (True) {
+
+         /*-- copy 1 --*/
+         if (i > hi) break;
+         v = ptr[i];
+         j = i;
+         while ( mainGtU ( 
+                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
+                 ) ) {
+            ptr[j] = ptr[j-h];
+            j = j - h;
+            if (j <= (lo + h - 1)) break;
+         }
+         ptr[j] = v;
+         i++;
+
+         /*-- copy 2 --*/
+         if (i > hi) break;
+         v = ptr[i];
+         j = i;
+         while ( mainGtU ( 
+                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
+                 ) ) {
+            ptr[j] = ptr[j-h];
+            j = j - h;
+            if (j <= (lo + h - 1)) break;
+         }
+         ptr[j] = v;
+         i++;
+
+         /*-- copy 3 --*/
+         if (i > hi) break;
+         v = ptr[i];
+         j = i;
+         while ( mainGtU ( 
+                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
+                 ) ) {
+            ptr[j] = ptr[j-h];
+            j = j - h;
+            if (j <= (lo + h - 1)) break;
+         }
+         ptr[j] = v;
+         i++;
+
+         if (*budget < 0) return;
+      }
+   }
+}
+
+
+/*---------------------------------------------*/
+/*--
+   The following is an implementation of
+   an elegant 3-way quicksort for strings,
+   described in a paper "Fast Algorithms for
+   Sorting and Searching Strings", by Robert
+   Sedgewick and Jon L. Bentley.
+--*/
+
+#define mswap(zz1, zz2) \
+   { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
+
+#define mvswap(zzp1, zzp2, zzn)       \
+{                                     \
+   Int32 yyp1 = (zzp1);               \
+   Int32 yyp2 = (zzp2);               \
+   Int32 yyn  = (zzn);                \
+   while (yyn > 0) {                  \
+      mswap(ptr[yyp1], ptr[yyp2]);    \
+      yyp1++; yyp2++; yyn--;          \
+   }                                  \
+}
+
+static 
+__inline__
+UChar mmed3 ( UChar a, UChar b, UChar c )
+{
+   UChar t;
+   if (a > b) { t = a; a = b; b = t; };
+   if (b > c) { 
+      b = c;
+      if (a > b) b = a;
+   }
+   return b;
+}
+
+#define mmin(a,b) ((a) < (b)) ? (a) : (b)
+
+#define mpush(lz,hz,dz) { stackLo[sp] = lz; \
+                          stackHi[sp] = hz; \
+                          stackD [sp] = dz; \
+                          sp++; }
+
+#define mpop(lz,hz,dz) { sp--;             \
+                         lz = stackLo[sp]; \
+                         hz = stackHi[sp]; \
+                         dz = stackD [sp]; }
+
+
+#define mnextsize(az) (nextHi[az]-nextLo[az])
+
+#define mnextswap(az,bz)                                        \
+   { Int32 tz;                                                  \
+     tz = nextLo[az]; nextLo[az] = nextLo[bz]; nextLo[bz] = tz; \
+     tz = nextHi[az]; nextHi[az] = nextHi[bz]; nextHi[bz] = tz; \
+     tz = nextD [az]; nextD [az] = nextD [bz]; nextD [bz] = tz; }
+
+
+#define MAIN_QSORT_SMALL_THRESH 20
+#define MAIN_QSORT_DEPTH_THRESH (BZ_N_RADIX + BZ_N_QSORT)
+#define MAIN_QSORT_STACK_SIZE 100
+
+static
+void mainQSort3 ( UInt32* ptr,
+                  UChar*  block,
+                  UInt16* quadrant,
+                  Int32   nblock,
+                  Int32   loSt, 
+                  Int32   hiSt, 
+                  Int32   dSt,
+                  Int32*  budget )
+{
+   Int32 unLo, unHi, ltLo, gtHi, n, m, med;
+   Int32 sp, lo, hi, d;
+
+   Int32 stackLo[MAIN_QSORT_STACK_SIZE];
+   Int32 stackHi[MAIN_QSORT_STACK_SIZE];
+   Int32 stackD [MAIN_QSORT_STACK_SIZE];
+
+   Int32 nextLo[3];
+   Int32 nextHi[3];
+   Int32 nextD [3];
+
+   sp = 0;
+   mpush ( loSt, hiSt, dSt );
+
+   while (sp > 0) {
+
+      AssertH ( sp < MAIN_QSORT_STACK_SIZE, 1001 );
+
+      mpop ( lo, hi, d );
+      if (hi - lo < MAIN_QSORT_SMALL_THRESH || 
+          d > MAIN_QSORT_DEPTH_THRESH) {
+         mainSimpleSort ( ptr, block, quadrant, nblock, lo, hi, d, budget );
+         if (*budget < 0) return;
+         continue;
+      }
+
+      med = (Int32) 
+            mmed3 ( block[ptr[ lo         ]+d],
+                    block[ptr[ hi         ]+d],
+                    block[ptr[ (lo+hi)>>1 ]+d] );
+
+      unLo = ltLo = lo;
+      unHi = gtHi = hi;
+
+      while (True) {
+         while (True) {
+            if (unLo > unHi) break;
+            n = ((Int32)block[ptr[unLo]+d]) - med;
+            if (n == 0) { 
+               mswap(ptr[unLo], ptr[ltLo]); 
+               ltLo++; unLo++; continue; 
+            };
+            if (n >  0) break;
+            unLo++;
+         }
+         while (True) {
+            if (unLo > unHi) break;
+            n = ((Int32)block[ptr[unHi]+d]) - med;
+            if (n == 0) { 
+               mswap(ptr[unHi], ptr[gtHi]); 
+               gtHi--; unHi--; continue; 
+            };
+            if (n <  0) break;
+            unHi--;
+         }
+         if (unLo > unHi) break;
+         mswap(ptr[unLo], ptr[unHi]); unLo++; unHi--;
+      }
+
+      AssertD ( unHi == unLo-1, "mainQSort3(2)" );
+
+      if (gtHi < ltLo) {
+         mpush(lo, hi, d+1 );
+         continue;
+      }
+
+      n = mmin(ltLo-lo, unLo-ltLo); mvswap(lo, unLo-n, n);
+      m = mmin(hi-gtHi, gtHi-unHi); mvswap(unLo, hi-m+1, m);
+
+      n = lo + unLo - ltLo - 1;
+      m = hi - (gtHi - unHi) + 1;
+
+      nextLo[0] = lo;  nextHi[0] = n;   nextD[0] = d;
+      nextLo[1] = m;   nextHi[1] = hi;  nextD[1] = d;
+      nextLo[2] = n+1; nextHi[2] = m-1; nextD[2] = d+1;
+
+      if (mnextsize(0) < mnextsize(1)) mnextswap(0,1);
+      if (mnextsize(1) < mnextsize(2)) mnextswap(1,2);
+      if (mnextsize(0) < mnextsize(1)) mnextswap(0,1);
+
+      AssertD (mnextsize(0) >= mnextsize(1), "mainQSort3(8)" );
+      AssertD (mnextsize(1) >= mnextsize(2), "mainQSort3(9)" );
+
+      mpush (nextLo[0], nextHi[0], nextD[0]);
+      mpush (nextLo[1], nextHi[1], nextD[1]);
+      mpush (nextLo[2], nextHi[2], nextD[2]);
+   }
+}
+
+#undef mswap
+#undef mvswap
+#undef mpush
+#undef mpop
+#undef mmin
+#undef mnextsize
+#undef mnextswap
+#undef MAIN_QSORT_SMALL_THRESH
+#undef MAIN_QSORT_DEPTH_THRESH
+#undef MAIN_QSORT_STACK_SIZE
+
+
+/*---------------------------------------------*/
+/* Pre:
+      nblock > N_OVERSHOOT
+      block32 exists for [0 .. nblock-1 +N_OVERSHOOT]
+      ((UChar*)block32) [0 .. nblock-1] holds block
+      ptr exists for [0 .. nblock-1]
+
+   Post:
+      ((UChar*)block32) [0 .. nblock-1] holds block
+      All other areas of block32 destroyed
+      ftab [0 .. 65536 ] destroyed
+      ptr [0 .. nblock-1] holds sorted order
+      if (*budget < 0), sorting was abandoned
+*/
+
+#define BIGFREQ(b) (ftab[((b)+1) << 8] - ftab[(b) << 8])
+#define SETMASK (1 << 21)
+#define CLEARMASK (~(SETMASK))
+
+static
+void mainSort ( UInt32* ptr, 
+                UChar*  block,
+                UInt16* quadrant, 
+                UInt32* ftab,
+                Int32   nblock,
+                Int32   verb,
+                Int32*  budget )
+{
+   Int32  i, j, k, ss, sb;
+   Int32  runningOrder[256];
+   Bool   bigDone[256];
+   Int32  copyStart[256];
+   Int32  copyEnd  [256];
+   UChar  c1;
+   Int32  numQSorted;
+   UInt16 s;
+   if (verb >= 4) VPrintf0 ( "        main sort initialise ...\n" );
+
+   /*-- set up the 2-byte frequency table --*/
+   for (i = 65536; i >= 0; i--) ftab[i] = 0;
+
+   j = block[0] << 8;
+   i = nblock-1;
+   for (; i >= 3; i -= 4) {
+      quadrant[i] = 0;
+      j = (j >> 8) | ( ((UInt16)block[i]) << 8);
+      ftab[j]++;
+      quadrant[i-1] = 0;
+      j = (j >> 8) | ( ((UInt16)block[i-1]) << 8);
+      ftab[j]++;
+      quadrant[i-2] = 0;
+      j = (j >> 8) | ( ((UInt16)block[i-2]) << 8);
+      ftab[j]++;
+      quadrant[i-3] = 0;
+      j = (j >> 8) | ( ((UInt16)block[i-3]) << 8);
+      ftab[j]++;
+   }
+   for (; i >= 0; i--) {
+      quadrant[i] = 0;
+      j = (j >> 8) | ( ((UInt16)block[i]) << 8);
+      ftab[j]++;
+   }
+
+   /*-- (emphasises close relationship of block & quadrant) --*/
+   for (i = 0; i < BZ_N_OVERSHOOT; i++) {
+      block   [nblock+i] = block[i];
+      quadrant[nblock+i] = 0;
+   }
+
+   if (verb >= 4) VPrintf0 ( "        bucket sorting ...\n" );
+
+   /*-- Complete the initial radix sort --*/
+   for (i = 1; i <= 65536; i++) ftab[i] += ftab[i-1];
+
+   s = block[0] << 8;
+   i = nblock-1;
+   for (; i >= 3; i -= 4) {
+      s = (s >> 8) | (block[i] << 8);
+      j = ftab[s] -1;
+      ftab[s] = j;
+      ptr[j] = i;
+      s = (s >> 8) | (block[i-1] << 8);
+      j = ftab[s] -1;
+      ftab[s] = j;
+      ptr[j] = i-1;
+      s = (s >> 8) | (block[i-2] << 8);
+      j = ftab[s] -1;
+      ftab[s] = j;
+      ptr[j] = i-2;
+      s = (s >> 8) | (block[i-3] << 8);
+      j = ftab[s] -1;
+      ftab[s] = j;
+      ptr[j] = i-3;
+   }
+   for (; i >= 0; i--) {
+      s = (s >> 8) | (block[i] << 8);
+      j = ftab[s] -1;
+      ftab[s] = j;
+      ptr[j] = i;
+   }
+
+   /*--
+      Now ftab contains the first loc of every small bucket.
+      Calculate the running order, from smallest to largest
+      big bucket.
+   --*/
+   for (i = 0; i <= 255; i++) {
+      bigDone     [i] = False;
+      runningOrder[i] = i;
+   }
+
+   {
+      Int32 vv;
+      Int32 h = 1;
+      do h = 3 * h + 1; while (h <= 256);
+      do {
+         h = h / 3;
+         for (i = h; i <= 255; i++) {
+            vv = runningOrder[i];
+            j = i;
+            while ( BIGFREQ(runningOrder[j-h]) > BIGFREQ(vv) ) {
+               runningOrder[j] = runningOrder[j-h];
+               j = j - h;
+               if (j <= (h - 1)) goto zero;
+            }
+            zero:
+            runningOrder[j] = vv;
+         }
+      } while (h != 1);
+   }
+
+   /*--
+      The main sorting loop.
+   --*/
+
+   numQSorted = 0;
+
+   for (i = 0; i <= 255; i++) {
+
+      /*--
+         Process big buckets, starting with the least full.
+         Basically this is a 3-step process in which we call
+         mainQSort3 to sort the small buckets [ss, j], but
+         also make a big effort to avoid the calls if we can.
+      --*/
+      ss = runningOrder[i];
+
+      /*--
+         Step 1:
+         Complete the big bucket [ss] by quicksorting
+         any unsorted small buckets [ss, j], for j != ss.  
+         Hopefully previous pointer-scanning phases have already
+         completed many of the small buckets [ss, j], so
+         we don't have to sort them at all.
+      --*/
+      for (j = 0; j <= 255; j++) {
+         if (j != ss) {
+            sb = (ss << 8) + j;
+            if ( ! (ftab[sb] & SETMASK) ) {
+               Int32 lo = ftab[sb]   & CLEARMASK;
+               Int32 hi = (ftab[sb+1] & CLEARMASK) - 1;
+               if (hi > lo) {
+                  if (verb >= 4)
+                     VPrintf4 ( "        qsort [0x%x, 0x%x]   "
+                                "done %d   this %d\n",
+                                ss, j, numQSorted, hi - lo + 1 );
+                  mainQSort3 ( 
+                     ptr, block, quadrant, nblock, 
+                     lo, hi, BZ_N_RADIX, budget 
+                  );   
+                  numQSorted += (hi - lo + 1);
+                  if (*budget < 0) return;
+               }
+            }
+            ftab[sb] |= SETMASK;
+         }
+      }
+
+      AssertH ( !bigDone[ss], 1006 );
+
+      /*--
+         Step 2:
+         Now scan this big bucket [ss] so as to synthesise the
+         sorted order for small buckets [t, ss] for all t,
+         including, magically, the bucket [ss,ss] too.
+         This will avoid doing Real Work in subsequent Step 1's.
+      --*/
+      {
+         for (j = 0; j <= 255; j++) {
+            copyStart[j] =  ftab[(j << 8) + ss]     & CLEARMASK;
+            copyEnd  [j] = (ftab[(j << 8) + ss + 1] & CLEARMASK) - 1;
+         }
+         for (j = ftab[ss << 8] & CLEARMASK; j < copyStart[ss]; j++) {
+            k = ptr[j]-1; if (k < 0) k += nblock;
+            c1 = block[k];
+            if (!bigDone[c1])
+               ptr[ copyStart[c1]++ ] = k;
+         }
+         for (j = (ftab[(ss+1) << 8] & CLEARMASK) - 1; j > copyEnd[ss]; j--) {
+            k = ptr[j]-1; if (k < 0) k += nblock;
+            c1 = block[k];
+            if (!bigDone[c1]) 
+               ptr[ copyEnd[c1]-- ] = k;
+         }
+      }
+
+      AssertH ( (copyStart[ss]-1 == copyEnd[ss])
+                || 
+                /* Extremely rare case missing in bzip2-1.0.0 and 1.0.1.
+                   Necessity for this case is demonstrated by compressing 
+                   a sequence of approximately 48.5 million of character 
+                   251; 1.0.0/1.0.1 will then die here. */
+                (copyStart[ss] == 0 && copyEnd[ss] == nblock-1),
+                1007 )
+
+      for (j = 0; j <= 255; j++) ftab[(j << 8) + ss] |= SETMASK;
+
+      /*--
+         Step 3:
+         The [ss] big bucket is now done.  Record this fact,
+         and update the quadrant descriptors.  Remember to
+         update quadrants in the overshoot area too, if
+         necessary.  The "if (i < 255)" test merely skips
+         this updating for the last bucket processed, since
+         updating for the last bucket is pointless.
+
+         The quadrant array provides a way to incrementally
+         cache sort orderings, as they appear, so as to 
+         make subsequent comparisons in fullGtU() complete
+         faster.  For repetitive blocks this makes a big
+         difference (but not big enough to be able to avoid
+         the fallback sorting mechanism, exponential radix sort).
+
+         The precise meaning is: at all times:
+
+            for 0 <= i < nblock and 0 <= j <= nblock
+
+            if block[i] != block[j], 
+
+               then the relative values of quadrant[i] and 
+                    quadrant[j] are meaningless.
+
+               else {
+                  if quadrant[i] < quadrant[j]
+                     then the string starting at i lexicographically
+                     precedes the string starting at j
+
+                  else if quadrant[i] > quadrant[j]
+                     then the string starting at j lexicographically
+                     precedes the string starting at i
+
+                  else
+                     the relative ordering of the strings starting
+                     at i and j has not yet been determined.
+               }
+      --*/
+      bigDone[ss] = True;
+
+      if (i < 255) {
+         Int32 bbStart  = ftab[ss << 8] & CLEARMASK;
+         Int32 bbSize   = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart;
+         Int32 shifts   = 0;
+
+         while ((bbSize >> shifts) > 65534) shifts++;
+
+         for (j = bbSize-1; j >= 0; j--) {
+            Int32 a2update     = ptr[bbStart + j];
+            UInt16 qVal        = (UInt16)(j >> shifts);
+            quadrant[a2update] = qVal;
+            if (a2update < BZ_N_OVERSHOOT)
+               quadrant[a2update + nblock] = qVal;
+         }
+         AssertH ( ((bbSize-1) >> shifts) <= 65535, 1002 );
+      }
+
+   }
+
+   if (verb >= 4)
+      VPrintf3 ( "        %d pointers, %d sorted, %d scanned\n",
+                 nblock, numQSorted, nblock - numQSorted );
+}
+
+#undef BIGFREQ
+#undef SETMASK
+#undef CLEARMASK
+
+
+/*---------------------------------------------*/
+/* Pre:
+      nblock > 0
+      arr2 exists for [0 .. nblock-1 +N_OVERSHOOT]
+      ((UChar*)arr2)  [0 .. nblock-1] holds block
+      arr1 exists for [0 .. nblock-1]
+
+   Post:
+      ((UChar*)arr2) [0 .. nblock-1] holds block
+      All other areas of block destroyed
+      ftab [ 0 .. 65536 ] destroyed
+      arr1 [0 .. nblock-1] holds sorted order
+*/
+void BZ2_blockSort ( EState* s )
+{
+   UInt32* ptr    = s->ptr; 
+   UChar*  block  = s->block;
+   UInt32* ftab   = s->ftab;
+   Int32   nblock = s->nblock;
+   Int32   verb   = s->verbosity;
+   Int32   wfact  = s->workFactor;
+   UInt16* quadrant;
+   Int32   budget;
+   Int32   budgetInit;
+   Int32   i;
+
+   if (nblock < 10000) {
+      fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb );
+   } else {
+      /* Calculate the location for quadrant, remembering to get
+         the alignment right.  Assumes that &(block[0]) is at least
+         2-byte aligned -- this should be ok since block is really
+         the first section of arr2.
+      */
+      i = nblock+BZ_N_OVERSHOOT;
+      if (i & 1) i++;
+      quadrant = (UInt16*)(&(block[i]));
+
+      /* (wfact-1) / 3 puts the default-factor-30
+         transition point at very roughly the same place as 
+         with v0.1 and v0.9.0.  
+         Not that it particularly matters any more, since the
+         resulting compressed stream is now the same regardless
+         of whether or not we use the main sort or fallback sort.
+      */
+      if (wfact < 1  ) wfact = 1;
+      if (wfact > 100) wfact = 100;
+      budgetInit = nblock * ((wfact-1) / 3);
+      budget = budgetInit;
+
+      mainSort ( ptr, block, quadrant, ftab, nblock, verb, &budget );
+      if (verb >= 3) 
+         VPrintf3 ( "      %d work, %d block, ratio %5.2f\n",
+                    budgetInit - budget,
+                    nblock, 
+                    (float)(budgetInit - budget) /
+                    (float)(nblock==0 ? 1 : nblock) ); 
+      if (budget < 0) {
+         if (verb >= 2) 
+            VPrintf0 ( "    too repetitive; using fallback"
+                       " sorting algorithm\n" );
+         fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb );
+      }
+   }
+
+   s->origPtr = -1;
+   for (i = 0; i < s->nblock; i++)
+      if (ptr[i] == 0)
+         { s->origPtr = i; break; };
+
+   AssertH( s->origPtr != -1, 1003 );
+}
+
+
+/*-------------------------------------------------------------*/
+/*--- end                                       blocksort.c ---*/
+/*-------------------------------------------------------------*/
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/bz-common.xsl b/contrib/vmap_extractor_v2/stormlib/bzip2/bz-common.xsl
new file mode 100644
index 00000000000..66fcd6fe0b6
--- /dev/null
+++ b/contrib/vmap_extractor_v2/stormlib/bzip2/bz-common.xsl
@@ -0,0 +1,39 @@
+ 
+
+
+
+ 
+
+
+
+ 
+ 
+   
+    
+      
+     
+  
+
+
+
+
+set       toc,title
+book      toc,title,figure,table,example,equation
+chapter   toc,title
+section   toc
+sect1     toc
+sect2     toc
+sect3     toc
+sect4     nop
+sect5     nop
+qandaset  toc
+qandadiv  nop
+appendix  toc,title
+article/appendix  nop
+article   toc,title
+preface   toc,title
+reference toc,title
+
+
+
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/bz-fo.xsl b/contrib/vmap_extractor_v2/stormlib/bzip2/bz-fo.xsl
new file mode 100644
index 00000000000..7f2a7674f04
--- /dev/null
+++ b/contrib/vmap_extractor_v2/stormlib/bzip2/bz-fo.xsl
@@ -0,0 +1,257 @@
+ 
+
+
+
+
+
+
+
+
+
+
+
+
+      
+     
+   
+
+
+
+
+ 
+
+
+
+
+
+
+  
+
+
+
+
+  blue
+
+
+
+
+  
+    
+  
+
+
+
+  
+    
+  
+
+
+
+
+  
+  
+  
+    
+      
+    
+  
+  
+    
+      
+        
+          
+          
+          
+        
+      
+    
+    
+          
+    
+  
+  
+    
+      
+        
+      
+    
+    
+      
+        
+      
+    
+  
+
+
+
+
+  
+  
+  
+    
+      
+        
+      
+    
+    
+          
+    
+  
+  
+    
+      
+        
+      
+    
+    
+      
+        
+      
+    
+  
+
+
+
+
+
+  
+    
+  
+    
+  
+  
+    
+      
+    
+  
+
+
+
+
+
+  
+  
+  
+  
+    
+      0pt
+    
+  
+  
+    
+      
+      
+      
+        
+          
+            baseline
+             
+               
+            
+          
+          
+            baseline
+            
+              
+                
+                
+                
+                
+              
+            
+          
+        
+      
+    
+  
+  
+  
+    
+      
+    
+    
+      
+    
+    
+      
+    
+  
+
+
+
+
+
+  
+  
+  
+  
+    
+      0pt
+    
+  
+  
+    
+      
+        
+        
+        
+      
+      
+      
+      
+        
+          
+            baseline
+            
+               
+            
+          
+          
+            baseline
+            
+              
+                
+                
+                
+                
+              
+            
+          
+        
+      
+    
+  
+  
+  
+    
+      
+    
+    
+      
+    
+    
+      
+    
+  
+
+
+
+
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/bz-html.xsl b/contrib/vmap_extractor_v2/stormlib/bzip2/bz-html.xsl
new file mode 100644
index 00000000000..1785fffbc95
--- /dev/null
+++ b/contrib/vmap_extractor_v2/stormlib/bzip2/bz-html.xsl
@@ -0,0 +1,20 @@
+ 
+ ]>
+
+
+
+
+
+
+
+
+
+
+  
+  
+
+
+
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/bzdiff b/contrib/vmap_extractor_v2/stormlib/bzip2/bzdiff
new file mode 100644
index 00000000000..3c2eb859fca
--- /dev/null
+++ b/contrib/vmap_extractor_v2/stormlib/bzip2/bzdiff
@@ -0,0 +1,76 @@
+#!/bin/sh
+# sh is buggy on RS/6000 AIX 3.2. Replace above line with #!/bin/ksh
+
+# Bzcmp/diff wrapped for bzip2, 
+# adapted from zdiff by Philippe Troin  for Debian GNU/Linux.
+
+# Bzcmp and bzdiff are used to invoke the cmp or the  diff  pro-
+# gram  on compressed files.  All options specified are passed
+# directly to cmp or diff.  If only 1 file is specified,  then
+# the  files  compared  are file1 and an uncompressed file1.gz.
+# If two files are specified, then they are  uncompressed  (if
+# necessary) and fed to cmp or diff.  The exit status from cmp
+# or diff is preserved.
+
+PATH="/usr/bin:$PATH"; export PATH
+prog=`echo $0 | sed 's|.*/||'`
+case "$prog" in
+  *cmp) comp=${CMP-cmp}   ;;
+  *)    comp=${DIFF-diff} ;;
+esac
+
+OPTIONS=
+FILES=
+for ARG
+do
+    case "$ARG" in
+    -*)	OPTIONS="$OPTIONS $ARG";;
+     *)	if test -f "$ARG"; then
+            FILES="$FILES $ARG"
+        else
+            echo "${prog}: $ARG not found or not a regular file"
+	    exit 1
+        fi ;;
+    esac
+done
+if test -z "$FILES"; then
+	echo "Usage: $prog [${comp}_options] file [file]"
+	exit 1
+fi
+tmp=`tempfile -d /tmp -p bz` || {
+      echo 'cannot create a temporary file' >&2
+      exit 1
+}
+set $FILES
+if test $# -eq 1; then
+	FILE=`echo "$1" | sed 's/.bz2$//'`
+	bzip2 -cd "$FILE.bz2" | $comp $OPTIONS - "$FILE"
+	STAT="$?"
+
+elif test $# -eq 2; then
+	case "$1" in
+        *.bz2)
+                case "$2" in
+	        *.bz2)
+			F=`echo "$2" | sed 's|.*/||;s|.bz2$||'`
+                        bzip2 -cdfq "$2" > $tmp
+                        bzip2 -cdfq "$1" | $comp $OPTIONS - $tmp
+                        STAT="$?"
+			/bin/rm -f $tmp;;
+
+                *)      bzip2 -cdfq "$1" | $comp $OPTIONS - "$2"
+                        STAT="$?";;
+                esac;;
+        *)      case "$2" in
+	        *.bz2)
+                        bzip2 -cdfq "$2" | $comp $OPTIONS "$1" -
+                        STAT="$?";;
+                *)      $comp $OPTIONS "$1" "$2"
+                        STAT="$?";;
+                esac;;
+	esac
+        exit "$STAT"
+else
+	echo "Usage: $prog [${comp}_options] file [file]"
+	exit 1
+fi
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/bzdiff.1 b/contrib/vmap_extractor_v2/stormlib/bzip2/bzdiff.1
new file mode 100644
index 00000000000..adb7a8e724e
--- /dev/null
+++ b/contrib/vmap_extractor_v2/stormlib/bzip2/bzdiff.1
@@ -0,0 +1,47 @@
+\"Shamelessly copied from zmore.1 by Philippe Troin 
+\"for Debian GNU/Linux
+.TH BZDIFF 1
+.SH NAME
+bzcmp, bzdiff \- compare bzip2 compressed files
+.SH SYNOPSIS
+.B bzcmp
+[ cmp_options ] file1
+[ file2 ]
+.br
+.B bzdiff
+[ diff_options ] file1
+[ file2 ]
+.SH DESCRIPTION
+.I  Bzcmp
+and 
+.I bzdiff
+are used to invoke the
+.I cmp
+or the
+.I diff
+program on bzip2 compressed files.  All options specified are passed
+directly to
+.I cmp
+or
+.IR diff "."
+If only 1 file is specified, then the files compared are
+.I file1
+and an uncompressed
+.IR file1 ".bz2."
+If two files are specified, then they are uncompressed if necessary and fed to
+.I cmp
+or
+.IR diff "."
+The exit status from 
+.I cmp
+or
+.I diff
+is preserved.
+.SH "SEE ALSO"
+cmp(1), diff(1), bzmore(1), bzless(1), bzgrep(1), bzip2(1)
+.SH BUGS
+Messages from the
+.I cmp
+or
+.I diff
+programs refer to temporary filenames instead of those specified.
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/bzgrep b/contrib/vmap_extractor_v2/stormlib/bzip2/bzgrep
new file mode 100644
index 00000000000..dbfc00e8dbe
--- /dev/null
+++ b/contrib/vmap_extractor_v2/stormlib/bzip2/bzgrep
@@ -0,0 +1,71 @@
+#!/bin/sh
+
+# Bzgrep wrapped for bzip2, 
+# adapted from zgrep by Philippe Troin  for Debian GNU/Linux.
+## zgrep notice:
+## zgrep -- a wrapper around a grep program that decompresses files as needed
+## Adapted from a version sent by Charles Levert 
+
+PATH="/usr/bin:$PATH"; export PATH
+
+prog=`echo $0 | sed 's|.*/||'`
+case "$prog" in
+	*egrep)	grep=${EGREP-egrep}	;;
+	*fgrep)	grep=${FGREP-fgrep}	;;
+	*)	grep=${GREP-grep}	;;
+esac
+pat=""
+while test $# -ne 0; do
+  case "$1" in
+  -e | -f) opt="$opt $1"; shift; pat="$1"
+           if test "$grep" = grep; then  # grep is buggy with -e on SVR4
+             grep=egrep
+           fi;;
+  -A | -B) opt="$opt $1 $2"; shift;;
+  -*)	   opt="$opt $1";;
+   *)      if test -z "$pat"; then
+	     pat="$1"
+	   else
+	     break;
+           fi;;
+  esac
+  shift
+done
+
+if test -z "$pat"; then
+  echo "grep through bzip2 files"
+  echo "usage: $prog [grep_options] pattern [files]"
+  exit 1
+fi
+
+list=0
+silent=0
+op=`echo "$opt" | sed -e 's/ //g' -e 's/-//g'`
+case "$op" in
+  *l*) list=1
+esac
+case "$op" in
+  *h*) silent=1
+esac
+
+if test $# -eq 0; then
+  bzip2 -cdfq | $grep $opt "$pat"
+  exit $?
+fi
+
+res=0
+for i do
+  if test -f "$i"; then :; else if test -f "$i.bz2"; then i="$i.bz2"; fi; fi
+  if test $list -eq 1; then
+    bzip2 -cdfq "$i" | $grep $opt "$pat" 2>&1 > /dev/null && echo $i
+    r=$?
+  elif test $# -eq 1 -o $silent -eq 1; then
+    bzip2 -cdfq "$i" | $grep $opt "$pat"
+    r=$?
+  else
+    bzip2 -cdfq "$i" | $grep $opt "$pat" | sed "s|^|${i}:|"
+    r=$?
+  fi
+  test "$r" -ne 0 && res="$r"
+done
+exit $res
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/bzgrep.1 b/contrib/vmap_extractor_v2/stormlib/bzip2/bzgrep.1
new file mode 100644
index 00000000000..930af8c7fcb
--- /dev/null
+++ b/contrib/vmap_extractor_v2/stormlib/bzip2/bzgrep.1
@@ -0,0 +1,56 @@
+\"Shamelessly copied from zmore.1 by Philippe Troin 
+\"for Debian GNU/Linux
+.TH BZGREP 1
+.SH NAME
+bzgrep, bzfgrep, bzegrep \- search possibly bzip2 compressed files for a regular expression
+.SH SYNOPSIS
+.B bzgrep
+[ grep_options ]
+.BI  [\ -e\ ] " pattern"
+.IR filename ".\|.\|."
+.br
+.B bzegrep
+[ egrep_options ]
+.BI  [\ -e\ ] " pattern"
+.IR filename ".\|.\|."
+.br
+.B bzfgrep
+[ fgrep_options ]
+.BI  [\ -e\ ] " pattern"
+.IR filename ".\|.\|."
+.SH DESCRIPTION
+.IR  Bzgrep
+is used to invoke the
+.I grep
+on bzip2-compressed files. All options specified are passed directly to
+.I grep.
+If no file is specified, then the standard input is decompressed
+if necessary and fed to grep.
+Otherwise the given files are uncompressed if necessary and fed to
+.I grep.
+.PP
+If
+.I bzgrep
+is invoked as
+.I bzegrep
+or
+.I bzfgrep
+then
+.I egrep
+or
+.I fgrep
+is used instead of
+.I grep.
+If the GREP environment variable is set,
+.I bzgrep
+uses it as the
+.I grep
+program to be invoked. For example:
+
+    for sh:  GREP=fgrep  bzgrep string files
+    for csh: (setenv GREP fgrep; bzgrep string files)
+.SH AUTHOR
+Charles Levert (charles@comm.polymtl.ca). Adapted to bzip2 by Philippe
+Troin  for Debian GNU/Linux.
+.SH "SEE ALSO"
+grep(1), egrep(1), fgrep(1), bzdiff(1), bzmore(1), bzless(1), bzip2(1)
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/bzip.css b/contrib/vmap_extractor_v2/stormlib/bzip2/bzip.css
new file mode 100644
index 00000000000..43193d8db0b
--- /dev/null
+++ b/contrib/vmap_extractor_v2/stormlib/bzip2/bzip.css
@@ -0,0 +1,74 @@
+/* Colours:
+#74240f  dark brown      h1, h2, h3, h4
+#336699  medium blue     links
+#339999  turquoise       link hover colour
+#202020  almost black    general text
+#761596  purple          md5sum text
+#626262  dark gray       pre border
+#eeeeee  very light gray pre background
+#f2f2f9  very light blue nav table background
+#3366cc  medium blue     nav table border
+*/
+
+a, a:link, a:visited, a:active { color: #336699; }
+a:hover { color: #339999; }
+
+body { font: 80%/126% sans-serif; }
+h1, h2, h3, h4 { color: #74240f; }
+
+dt { color: #336699; font-weight: bold }
+dd { 
+ margin-left: 1.5em; 
+ padding-bottom: 0.8em;
+}
+
+/* -- ruler -- */
+div.hr_blue { 
+  height:  3px; 
+  background:#ffffff url("/images/hr_blue.png") repeat-x; }
+div.hr_blue hr { display:none; }
+
+/* release styles */
+#release p { margin-top: 0.4em; }
+#release .md5sum { color: #761596; }
+
+
+/* ------ styles for docs|manuals|howto ------ */
+/* -- lists -- */
+ul  { 
+ margin:     0px 4px 16px 16px;
+ padding:    0px;
+ list-style: url("/images/li-blue.png"); 
+}
+ul li { 
+ margin-bottom: 10px;
+}
+ul ul	{ 
+ list-style-type:  none; 
+ list-style-image: none; 
+ margin-left:      0px; 
+}
+
+/* header / footer nav tables */
+table.nav {
+ border:     solid 1px #3366cc;
+ background: #f2f2f9;
+ background-color: #f2f2f9;
+ margin-bottom: 0.5em;
+}
+/* don't have underlined links in chunked nav menus */
+table.nav a { text-decoration: none; }
+table.nav a:hover { text-decoration: underline; }
+table.nav td { font-size: 85%; }
+
+code, tt, pre { font-size: 120%; }
+code, tt { color: #761596; }
+
+div.literallayout, pre.programlisting, pre.screen {
+ color:      #000000;
+ padding:    0.5em;
+ background: #eeeeee;
+ border:     1px solid #626262;
+ background-color: #eeeeee;
+ margin: 4px 0px 4px 0px; 
+}
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/bzip2.1 b/contrib/vmap_extractor_v2/stormlib/bzip2/bzip2.1
new file mode 100644
index 00000000000..d2c06615683
--- /dev/null
+++ b/contrib/vmap_extractor_v2/stormlib/bzip2/bzip2.1
@@ -0,0 +1,454 @@
+.PU
+.TH bzip2 1
+.SH NAME
+bzip2, bunzip2 \- a block-sorting file compressor, v1.0.3
+.br
+bzcat \- decompresses files to stdout
+.br
+bzip2recover \- recovers data from damaged bzip2 files
+
+.SH SYNOPSIS
+.ll +8
+.B bzip2
+.RB [ " \-cdfkqstvzVL123456789 " ]
+[
+.I "filenames \&..."
+]
+.ll -8
+.br
+.B bunzip2
+.RB [ " \-fkvsVL " ]
+[ 
+.I "filenames \&..."
+]
+.br
+.B bzcat
+.RB [ " \-s " ]
+[ 
+.I "filenames \&..."
+]
+.br
+.B bzip2recover
+.I "filename"
+
+.SH DESCRIPTION
+.I bzip2
+compresses files using the Burrows-Wheeler block sorting
+text compression algorithm, and Huffman coding.  Compression is
+generally considerably better than that achieved by more conventional
+LZ77/LZ78-based compressors, and approaches the performance of the PPM
+family of statistical compressors.
+
+The command-line options are deliberately very similar to 
+those of 
+.I GNU gzip, 
+but they are not identical.
+
+.I bzip2
+expects a list of file names to accompany the
+command-line flags.  Each file is replaced by a compressed version of
+itself, with the name "original_name.bz2".  
+Each compressed file
+has the same modification date, permissions, and, when possible,
+ownership as the corresponding original, so that these properties can
+be correctly restored at decompression time.  File name handling is
+naive in the sense that there is no mechanism for preserving original
+file names, permissions, ownerships or dates in filesystems which lack
+these concepts, or have serious file name length restrictions, such as
+MS-DOS.
+
+.I bzip2
+and
+.I bunzip2
+will by default not overwrite existing
+files.  If you want this to happen, specify the \-f flag.
+
+If no file names are specified,
+.I bzip2
+compresses from standard
+input to standard output.  In this case,
+.I bzip2
+will decline to
+write compressed output to a terminal, as this would be entirely
+incomprehensible and therefore pointless.
+
+.I bunzip2
+(or
+.I bzip2 \-d) 
+decompresses all
+specified files.  Files which were not created by 
+.I bzip2
+will be detected and ignored, and a warning issued.  
+.I bzip2
+attempts to guess the filename for the decompressed file 
+from that of the compressed file as follows:
+
+       filename.bz2    becomes   filename
+       filename.bz     becomes   filename
+       filename.tbz2   becomes   filename.tar
+       filename.tbz    becomes   filename.tar
+       anyothername    becomes   anyothername.out
+
+If the file does not end in one of the recognised endings, 
+.I .bz2, 
+.I .bz, 
+.I .tbz2
+or
+.I .tbz, 
+.I bzip2 
+complains that it cannot
+guess the name of the original file, and uses the original name
+with
+.I .out
+appended.
+
+As with compression, supplying no
+filenames causes decompression from 
+standard input to standard output.
+
+.I bunzip2 
+will correctly decompress a file which is the
+concatenation of two or more compressed files.  The result is the
+concatenation of the corresponding uncompressed files.  Integrity
+testing (\-t) 
+of concatenated 
+compressed files is also supported.
+
+You can also compress or decompress files to the standard output by
+giving the \-c flag.  Multiple files may be compressed and
+decompressed like this.  The resulting outputs are fed sequentially to
+stdout.  Compression of multiple files 
+in this manner generates a stream
+containing multiple compressed file representations.  Such a stream
+can be decompressed correctly only by
+.I bzip2 
+version 0.9.0 or
+later.  Earlier versions of
+.I bzip2
+will stop after decompressing
+the first file in the stream.
+
+.I bzcat
+(or
+.I bzip2 -dc) 
+decompresses all specified files to
+the standard output.
+
+.I bzip2
+will read arguments from the environment variables
+.I BZIP2
+and
+.I BZIP,
+in that order, and will process them
+before any arguments read from the command line.  This gives a 
+convenient way to supply default arguments.
+
+Compression is always performed, even if the compressed 
+file is slightly
+larger than the original.  Files of less than about one hundred bytes
+tend to get larger, since the compression mechanism has a constant
+overhead in the region of 50 bytes.  Random data (including the output
+of most file compressors) is coded at about 8.05 bits per byte, giving
+an expansion of around 0.5%.
+
+As a self-check for your protection, 
+.I 
+bzip2
+uses 32-bit CRCs to
+make sure that the decompressed version of a file is identical to the
+original.  This guards against corruption of the compressed data, and
+against undetected bugs in
+.I bzip2
+(hopefully very unlikely).  The
+chances of data corruption going undetected is microscopic, about one
+chance in four billion for each file processed.  Be aware, though, that
+the check occurs upon decompression, so it can only tell you that
+something is wrong.  It can't help you 
+recover the original uncompressed
+data.  You can use 
+.I bzip2recover
+to try to recover data from
+damaged files.
+
+Return values: 0 for a normal exit, 1 for environmental problems (file
+not found, invalid flags, I/O errors, &c), 2 to indicate a corrupt
+compressed file, 3 for an internal consistency error (eg, bug) which
+caused
+.I bzip2
+to panic.
+
+.SH OPTIONS
+.TP
+.B \-c --stdout
+Compress or decompress to standard output.
+.TP
+.B \-d --decompress
+Force decompression.  
+.I bzip2, 
+.I bunzip2 
+and
+.I bzcat 
+are
+really the same program, and the decision about what actions to take is
+done on the basis of which name is used.  This flag overrides that
+mechanism, and forces 
+.I bzip2
+to decompress.
+.TP
+.B \-z --compress
+The complement to \-d: forces compression, regardless of the
+invocation name.
+.TP
+.B \-t --test
+Check integrity of the specified file(s), but don't decompress them.
+This really performs a trial decompression and throws away the result.
+.TP
+.B \-f --force
+Force overwrite of output files.  Normally,
+.I bzip2 
+will not overwrite
+existing output files.  Also forces 
+.I bzip2 
+to break hard links
+to files, which it otherwise wouldn't do.
+
+bzip2 normally declines to decompress files which don't have the
+correct magic header bytes.  If forced (-f), however, it will pass
+such files through unmodified.  This is how GNU gzip behaves.
+.TP
+.B \-k --keep
+Keep (don't delete) input files during compression
+or decompression.
+.TP
+.B \-s --small
+Reduce memory usage, for compression, decompression and testing.  Files
+are decompressed and tested using a modified algorithm which only
+requires 2.5 bytes per block byte.  This means any file can be
+decompressed in 2300k of memory, albeit at about half the normal speed.
+
+During compression, \-s selects a block size of 200k, which limits
+memory use to around the same figure, at the expense of your compression
+ratio.  In short, if your machine is low on memory (8 megabytes or
+less), use \-s for everything.  See MEMORY MANAGEMENT below.
+.TP
+.B \-q --quiet
+Suppress non-essential warning messages.  Messages pertaining to
+I/O errors and other critical events will not be suppressed.
+.TP
+.B \-v --verbose
+Verbose mode -- show the compression ratio for each file processed.
+Further \-v's increase the verbosity level, spewing out lots of
+information which is primarily of interest for diagnostic purposes.
+.TP
+.B \-L --license -V --version
+Display the software version, license terms and conditions.
+.TP
+.B \-1 (or \-\-fast) to \-9 (or \-\-best)
+Set the block size to 100 k, 200 k ..  900 k when compressing.  Has no
+effect when decompressing.  See MEMORY MANAGEMENT below.
+The \-\-fast and \-\-best aliases are primarily for GNU gzip 
+compatibility.  In particular, \-\-fast doesn't make things
+significantly faster.  
+And \-\-best merely selects the default behaviour.
+.TP
+.B \--
+Treats all subsequent arguments as file names, even if they start
+with a dash.  This is so you can handle files with names beginning
+with a dash, for example: bzip2 \-- \-myfilename.
+.TP
+.B \--repetitive-fast --repetitive-best
+These flags are redundant in versions 0.9.5 and above.  They provided
+some coarse control over the behaviour of the sorting algorithm in
+earlier versions, which was sometimes useful.  0.9.5 and above have an
+improved algorithm which renders these flags irrelevant.
+
+.SH MEMORY MANAGEMENT
+.I bzip2 
+compresses large files in blocks.  The block size affects
+both the compression ratio achieved, and the amount of memory needed for
+compression and decompression.  The flags \-1 through \-9
+specify the block size to be 100,000 bytes through 900,000 bytes (the
+default) respectively.  At decompression time, the block size used for
+compression is read from the header of the compressed file, and
+.I bunzip2
+then allocates itself just enough memory to decompress
+the file.  Since block sizes are stored in compressed files, it follows
+that the flags \-1 to \-9 are irrelevant to and so ignored
+during decompression.
+
+Compression and decompression requirements, 
+in bytes, can be estimated as:
+
+       Compression:   400k + ( 8 x block size )
+
+       Decompression: 100k + ( 4 x block size ), or
+                      100k + ( 2.5 x block size )
+
+Larger block sizes give rapidly diminishing marginal returns.  Most of
+the compression comes from the first two or three hundred k of block
+size, a fact worth bearing in mind when using
+.I bzip2
+on small machines.
+It is also important to appreciate that the decompression memory
+requirement is set at compression time by the choice of block size.
+
+For files compressed with the default 900k block size,
+.I bunzip2
+will require about 3700 kbytes to decompress.  To support decompression
+of any file on a 4 megabyte machine, 
+.I bunzip2
+has an option to
+decompress using approximately half this amount of memory, about 2300
+kbytes.  Decompression speed is also halved, so you should use this
+option only where necessary.  The relevant flag is -s.
+
+In general, try and use the largest block size memory constraints allow,
+since that maximises the compression achieved.  Compression and
+decompression speed are virtually unaffected by block size.
+
+Another significant point applies to files which fit in a single block
+-- that means most files you'd encounter using a large block size.  The
+amount of real memory touched is proportional to the size of the file,
+since the file is smaller than a block.  For example, compressing a file
+20,000 bytes long with the flag -9 will cause the compressor to
+allocate around 7600k of memory, but only touch 400k + 20000 * 8 = 560
+kbytes of it.  Similarly, the decompressor will allocate 3700k but only
+touch 100k + 20000 * 4 = 180 kbytes.
+
+Here is a table which summarises the maximum memory usage for different
+block sizes.  Also recorded is the total compressed size for 14 files of
+the Calgary Text Compression Corpus totalling 3,141,622 bytes.  This
+column gives some feel for how compression varies with block size.
+These figures tend to understate the advantage of larger block sizes for
+larger files, since the Corpus is dominated by smaller files.
+
+           Compress   Decompress   Decompress   Corpus
+    Flag     usage      usage       -s usage     Size
+
+     -1      1200k       500k         350k      914704
+     -2      2000k       900k         600k      877703
+     -3      2800k      1300k         850k      860338
+     -4      3600k      1700k        1100k      846899
+     -5      4400k      2100k        1350k      845160
+     -6      5200k      2500k        1600k      838626
+     -7      6100k      2900k        1850k      834096
+     -8      6800k      3300k        2100k      828642
+     -9      7600k      3700k        2350k      828642
+
+.SH RECOVERING DATA FROM DAMAGED FILES
+.I bzip2
+compresses files in blocks, usually 900kbytes long.  Each
+block is handled independently.  If a media or transmission error causes
+a multi-block .bz2
+file to become damaged, it may be possible to
+recover data from the undamaged blocks in the file.
+
+The compressed representation of each block is delimited by a 48-bit
+pattern, which makes it possible to find the block boundaries with
+reasonable certainty.  Each block also carries its own 32-bit CRC, so
+damaged blocks can be distinguished from undamaged ones.
+
+.I bzip2recover
+is a simple program whose purpose is to search for
+blocks in .bz2 files, and write each block out into its own .bz2 
+file.  You can then use
+.I bzip2 
+\-t
+to test the
+integrity of the resulting files, and decompress those which are
+undamaged.
+
+.I bzip2recover
+takes a single argument, the name of the damaged file, 
+and writes a number of files "rec00001file.bz2",
+"rec00002file.bz2", etc, containing the  extracted  blocks.
+The  output  filenames  are  designed  so  that the use of
+wildcards in subsequent processing -- for example,  
+"bzip2 -dc  rec*file.bz2 > recovered_data" -- processes the files in
+the correct order.
+
+.I bzip2recover
+should be of most use dealing with large .bz2
+files,  as  these will contain many blocks.  It is clearly
+futile to use it on damaged single-block  files,  since  a
+damaged  block  cannot  be recovered.  If you wish to minimise 
+any potential data loss through media  or  transmission errors, 
+you might consider compressing with a smaller
+block size.
+
+.SH PERFORMANCE NOTES
+The sorting phase of compression gathers together similar strings in the
+file.  Because of this, files containing very long runs of repeated
+symbols, like "aabaabaabaab ..."  (repeated several hundred times) may
+compress more slowly than normal.  Versions 0.9.5 and above fare much
+better than previous versions in this respect.  The ratio between
+worst-case and average-case compression time is in the region of 10:1.
+For previous versions, this figure was more like 100:1.  You can use the
+\-vvvv option to monitor progress in great detail, if you want.
+
+Decompression speed is unaffected by these phenomena.
+
+.I bzip2
+usually allocates several megabytes of memory to operate
+in, and then charges all over it in a fairly random fashion.  This means
+that performance, both for compressing and decompressing, is largely
+determined by the speed at which your machine can service cache misses.
+Because of this, small changes to the code to reduce the miss rate have
+been observed to give disproportionately large performance improvements.
+I imagine 
+.I bzip2
+will perform best on machines with very large caches.
+
+.SH CAVEATS
+I/O error messages are not as helpful as they could be.
+.I bzip2
+tries hard to detect I/O errors and exit cleanly, but the details of
+what the problem is sometimes seem rather misleading.
+
+This manual page pertains to version 1.0.3 of
+.I bzip2.  
+Compressed data created by this version is entirely forwards and
+backwards compatible with the previous public releases, versions
+0.1pl2, 0.9.0, 0.9.5, 1.0.0, 1.0.1 and 1.0.2, but with the following
+exception: 0.9.0 and above can correctly decompress multiple
+concatenated compressed files.  0.1pl2 cannot do this; it will stop
+after decompressing just the first file in the stream.
+
+.I bzip2recover
+versions prior to 1.0.2 used 32-bit integers to represent
+bit positions in compressed files, so they could not handle compressed
+files more than 512 megabytes long.  Versions 1.0.2 and above use
+64-bit ints on some platforms which support them (GNU supported
+targets, and Windows).  To establish whether or not bzip2recover was
+built with such a limitation, run it without arguments.  In any event
+you can build yourself an unlimited version if you can recompile it
+with MaybeUInt64 set to be an unsigned 64-bit integer.
+
+
+
+.SH AUTHOR
+Julian Seward, jsewardbzip.org.
+
+http://www.bzip.org
+
+The ideas embodied in
+.I bzip2
+are due to (at least) the following
+people: Michael Burrows and David Wheeler (for the block sorting
+transformation), David Wheeler (again, for the Huffman coder), Peter
+Fenwick (for the structured coding model in the original
+.I bzip,
+and many refinements), and Alistair Moffat, Radford Neal and Ian Witten
+(for the arithmetic coder in the original
+.I bzip).  
+I am much
+indebted for their help, support and advice.  See the manual in the
+source distribution for pointers to sources of documentation.  Christian
+von Roques encouraged me to look for faster sorting algorithms, so as to
+speed up compression.  Bela Lubkin encouraged me to improve the
+worst-case compression performance.  
+Donna Robinson XMLised the documentation.
+The bz* scripts are derived from those of GNU gzip.
+Many people sent patches, helped
+with portability problems, lent machines, gave advice and were generally
+helpful.
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/bzip2.1.preformatted b/contrib/vmap_extractor_v2/stormlib/bzip2/bzip2.1.preformatted
new file mode 100644
index 00000000000..129ca835c9c
--- /dev/null
+++ b/contrib/vmap_extractor_v2/stormlib/bzip2/bzip2.1.preformatted
@@ -0,0 +1,399 @@
+bzip2(1)                                                 bzip2(1)
+
+
+
+NNAAMMEE
+       bzip2, bunzip2 − a blockâ€sorting file compressor, v1.0.3
+       bzcat − decompresses files to stdout
+       bzip2recover − recovers data from damaged bzip2 files
+
+
+SSYYNNOOPPSSIISS
+       bbzziipp22 [ −−ccddffkkqqssttvvzzVVLL112233445566778899 ] [ _f_i_l_e_n_a_m_e_s _._._.  ]
+       bbuunnzziipp22 [ −−ffkkvvssVVLL ] [ _f_i_l_e_n_a_m_e_s _._._.  ]
+       bbzzccaatt [ −−ss ] [ _f_i_l_e_n_a_m_e_s _._._.  ]
+       bbzziipp22rreeccoovveerr _f_i_l_e_n_a_m_e
+
+
+DDEESSCCRRIIPPTTIIOONN
+       _b_z_i_p_2  compresses  files  using  the Burrowsâ€Wheeler block
+       sorting text compression algorithm,  and  Huffman  coding.
+       Compression  is  generally  considerably  better than that
+       achieved by more conventional LZ77/LZ78â€based compressors,
+       and  approaches  the performance of the PPM family of sta­
+       tistical compressors.
+
+       The commandâ€line options are deliberately very similar  to
+       those of _G_N_U _g_z_i_p_, but they are not identical.
+
+       _b_z_i_p_2  expects  a list of file names to accompany the com­
+       mandâ€line flags.  Each file is replaced  by  a  compressed
+       version  of  itself,  with  the  name "original_name.bz2".
+       Each compressed file has the same modification date,  per­
+       missions, and, when possible, ownership as the correspond­
+       ing original, so that these properties  can  be  correctly
+       restored  at  decompression  time.   File name handling is
+       naive in the sense that there is no mechanism for preserv­
+       ing  original file names, permissions, ownerships or dates
+       in filesystems which lack these concepts, or have  serious
+       file name length restrictions, such as MSâ€DOS.
+
+       _b_z_i_p_2  and  _b_u_n_z_i_p_2 will by default not overwrite existing
+       files.  If you want this to happen, specify the −f flag.
+
+       If no file names  are  specified,  _b_z_i_p_2  compresses  from
+       standard  input  to  standard output.  In this case, _b_z_i_p_2
+       will decline to write compressed output to a terminal,  as
+       this  would  be  entirely  incomprehensible  and therefore
+       pointless.
+
+       _b_u_n_z_i_p_2 (or _b_z_i_p_2 _−_d_) decompresses  all  specified  files.
+       Files which were not created by _b_z_i_p_2 will be detected and
+       ignored, and a warning issued.  _b_z_i_p_2  attempts  to  guess
+       the  filename  for  the decompressed file from that of the
+       compressed file as follows:
+
+              filename.bz2    becomes   filename
+              filename.bz     becomes   filename
+              filename.tbz2   becomes   filename.tar
+              filename.tbz    becomes   filename.tar
+              anyothername    becomes   anyothername.out
+
+       If the file does not end in one of the recognised endings,
+       _._b_z_2_,  _._b_z_,  _._t_b_z_2 or _._t_b_z_, _b_z_i_p_2 complains that it cannot
+       guess the name of the original file, and uses the original
+       name with _._o_u_t appended.
+
+       As  with compression, supplying no filenames causes decom­
+       pression from standard input to standard output.
+
+       _b_u_n_z_i_p_2 will correctly decompress a file which is the con­
+       catenation of two or more compressed files.  The result is
+       the concatenation of the corresponding uncompressed files.
+       Integrity testing (−t) of concatenated compressed files is
+       also supported.
+
+       You can also compress or decompress files to the  standard
+       output  by giving the −c flag.  Multiple files may be com­
+       pressed and decompressed like this.  The resulting outputs
+       are  fed  sequentially to stdout.  Compression of multiple
+       files in this manner generates a stream containing  multi­
+       ple compressed file representations.  Such a stream can be
+       decompressed correctly only  by  _b_z_i_p_2  version  0.9.0  or
+       later.   Earlier  versions of _b_z_i_p_2 will stop after decom­
+       pressing the first file in the stream.
+
+       _b_z_c_a_t (or _b_z_i_p_2 _â€_d_c_) decompresses all specified  files  to
+       the standard output.
+
+       _b_z_i_p_2  will  read arguments from the environment variables
+       _B_Z_I_P_2 and _B_Z_I_P_, in  that  order,  and  will  process  them
+       before  any  arguments  read  from the command line.  This
+       gives a convenient way to supply default arguments.
+
+       Compression is always performed, even  if  the  compressed
+       file  is slightly larger than the original.  Files of less
+       than about one hundred bytes tend to get larger, since the
+       compression  mechanism  has  a  constant  overhead  in the
+       region of 50 bytes.  Random data (including the output  of
+       most  file  compressors)  is  coded at about 8.05 bits per
+       byte, giving an expansion of around 0.5%.
+
+       As a selfâ€check for your  protection,  _b_z_i_p_2  uses  32â€bit
+       CRCs  to make sure that the decompressed version of a file
+       is identical to the original.  This guards against corrup­
+       tion  of  the compressed data, and against undetected bugs
+       in _b_z_i_p_2 (hopefully very unlikely).  The chances  of  data
+       corruption  going  undetected  is  microscopic,  about one
+       chance in four billion for each file processed.  Be aware,
+       though,  that  the  check occurs upon decompression, so it
+       can only tell you that something is wrong.  It can’t  help
+       you  recover  the original uncompressed data.  You can use
+       _b_z_i_p_2_r_e_c_o_v_e_r to try to recover data from damaged files.
+
+       Return values: 0 for a normal exit,  1  for  environmental
+       problems  (file not found, invalid flags, I/O errors, &c),
+       2 to indicate a corrupt compressed file, 3 for an internal
+       consistency error (eg, bug) which caused _b_z_i_p_2 to panic.
+
+
+OOPPTTIIOONNSS
+       −−cc â€â€â€â€ssttddoouutt
+              Compress or decompress to standard output.
+
+       −−dd â€â€â€â€ddeeccoommpprreessss
+              Force  decompression.  _b_z_i_p_2_, _b_u_n_z_i_p_2 and _b_z_c_a_t are
+              really the same program,  and  the  decision  about
+              what  actions to take is done on the basis of which
+              name is used.  This flag overrides that  mechanism,
+              and forces _b_z_i_p_2 to decompress.
+
+       −−zz â€â€â€â€ccoommpprreessss
+              The   complement   to   −d:   forces   compression,
+              regardless of the invocation name.
+
+       −−tt â€â€â€â€tteesstt
+              Check integrity of the specified file(s), but don’t
+              decompress  them.   This  really  performs  a trial
+              decompression and throws away the result.
+
+       −−ff â€â€â€â€ffoorrccee
+              Force overwrite of output files.   Normally,  _b_z_i_p_2
+              will  not  overwrite  existing  output files.  Also
+              forces _b_z_i_p_2 to break hard links to files, which it
+              otherwise wouldn’t do.
+
+              bzip2  normally  declines to decompress files which
+              don’t have the  correct  magic  header  bytes.   If
+              forced  (â€f),  however,  it  will  pass  such files
+              through unmodified.  This is how GNU gzip  behaves.
+
+       −−kk â€â€â€â€kkeeeepp
+              Keep  (don’t delete) input files during compression
+              or decompression.
+
+       −−ss â€â€â€â€ssmmaallll
+              Reduce memory usage, for compression, decompression
+              and  testing.   Files  are  decompressed and tested
+              using a modified algorithm which only requires  2.5
+              bytes  per  block byte.  This means any file can be
+              decompressed in 2300k of memory,  albeit  at  about
+              half the normal speed.
+
+              During  compression,  −s  selects  a  block size of
+              200k, which limits memory use to  around  the  same
+              figure,  at  the expense of your compression ratio.
+              In short, if your  machine  is  low  on  memory  (8
+              megabytes  or  less),  use  −s for everything.  See
+              MEMORY MANAGEMENT below.
+
+       −−qq â€â€â€â€qquuiieett
+              Suppress nonâ€essential warning messages.   Messages
+              pertaining  to I/O errors and other critical events
+              will not be suppressed.
+
+       −−vv â€â€â€â€vveerrbboossee
+              Verbose mode â€â€ show the compression ratio for each
+              file  processed.   Further  −v’s  increase the ver­
+              bosity level, spewing out lots of information which
+              is primarily of interest for diagnostic purposes.
+
+       −−LL â€â€â€â€lliicceennssee â€â€VV â€â€â€â€vveerrssiioonn
+              Display  the  software  version,  license terms and
+              conditions.
+
+       −−11 ((oorr −−−−ffaasstt)) ttoo −−99 ((oorr −−−−bbeesstt))
+              Set the block size to 100 k, 200 k ..  900  k  when
+              compressing.   Has  no  effect  when decompressing.
+              See MEMORY MANAGEMENT below.  The −−fast and −−best
+              aliases  are  primarily for GNU gzip compatibility.
+              In particular, −−fast doesn’t make things  signifi­
+              cantly  faster.   And  −−best  merely  selects  the
+              default behaviour.
+
+       −−     Treats all subsequent arguments as file names, even
+              if they start with a dash.  This is so you can han­
+              dle files with names beginning  with  a  dash,  for
+              example: bzip2 −†−myfilename.
+
+       −−â€â€rreeppeettiittiivveeâ€â€ffaasstt â€â€â€â€rreeppeettiittiivveeâ€â€bbeesstt
+              These  flags  are  redundant  in versions 0.9.5 and
+              above.  They provided some coarse control over  the
+              behaviour  of the sorting algorithm in earlier ver­
+              sions, which was sometimes useful.  0.9.5 and above
+              have  an  improved  algorithm  which  renders these
+              flags irrelevant.
+
+
+MMEEMMOORRYY MMAANNAAGGEEMMEENNTT
+       _b_z_i_p_2 compresses large files in blocks.   The  block  size
+       affects  both  the  compression  ratio  achieved,  and the
+       amount of memory needed for compression and decompression.
+       The  flags  −1  through  −9  specify  the block size to be
+       100,000 bytes through 900,000 bytes (the default)  respec­
+       tively.   At  decompression  time, the block size used for
+       compression is read from  the  header  of  the  compressed
+       file, and _b_u_n_z_i_p_2 then allocates itself just enough memory
+       to decompress the file.  Since block sizes are  stored  in
+       compressed  files,  it follows that the flags −1 to −9 are
+       irrelevant to and so ignored during decompression.
+
+       Compression and decompression requirements, in bytes,  can
+       be estimated as:
+
+              Compression:   400k + ( 8 x block size )
+
+              Decompression: 100k + ( 4 x block size ), or
+                             100k + ( 2.5 x block size )
+
+       Larger  block  sizes  give  rapidly  diminishing  marginal
+       returns.  Most of the compression comes from the first two
+       or  three hundred k of block size, a fact worth bearing in
+       mind when using _b_z_i_p_2  on  small  machines.   It  is  also
+       important  to  appreciate  that  the  decompression memory
+       requirement is set at compression time by  the  choice  of
+       block size.
+
+       For  files  compressed  with  the default 900k block size,
+       _b_u_n_z_i_p_2 will require about 3700 kbytes to decompress.   To
+       support decompression of any file on a 4 megabyte machine,
+       _b_u_n_z_i_p_2 has an option to  decompress  using  approximately
+       half this amount of memory, about 2300 kbytes.  Decompres­
+       sion speed is also halved, so you should use  this  option
+       only where necessary.  The relevant flag is â€s.
+
+       In general, try and use the largest block size memory con­
+       straints  allow,  since  that  maximises  the  compression
+       achieved.   Compression and decompression speed are virtu­
+       ally unaffected by block size.
+
+       Another significant point applies to files which fit in  a
+       single  block  â€â€  that  means  most files you’d encounter
+       using a large block  size.   The  amount  of  real  memory
+       touched is proportional to the size of the file, since the
+       file is smaller than a block.  For example, compressing  a
+       file  20,000  bytes  long  with the flag â€9 will cause the
+       compressor to allocate around 7600k of  memory,  but  only
+       touch 400k + 20000 * 8 = 560 kbytes of it.  Similarly, the
+       decompressor will allocate 3700k but  only  touch  100k  +
+       20000 * 4 = 180 kbytes.
+
+       Here  is a table which summarises the maximum memory usage
+       for different block sizes.  Also  recorded  is  the  total
+       compressed  size for 14 files of the Calgary Text Compres­
+       sion Corpus totalling 3,141,622 bytes.  This column  gives
+       some  feel  for  how  compression  varies with block size.
+       These figures tend to understate the advantage  of  larger
+       block  sizes  for  larger files, since the Corpus is domi­
+       nated by smaller files.
+
+                  Compress   Decompress   Decompress   Corpus
+           Flag     usage      usage       â€s usage     Size
+
+            â€1      1200k       500k         350k      914704
+            â€2      2000k       900k         600k      877703
+            â€3      2800k      1300k         850k      860338
+            â€4      3600k      1700k        1100k      846899
+            â€5      4400k      2100k        1350k      845160
+            â€6      5200k      2500k        1600k      838626
+            â€7      6100k      2900k        1850k      834096
+            â€8      6800k      3300k        2100k      828642
+            â€9      7600k      3700k        2350k      828642
+
+
+RREECCOOVVEERRIINNGG DDAATTAA FFRROOMM DDAAMMAAGGEEDD FFIILLEESS
+       _b_z_i_p_2 compresses files in blocks, usually 900kbytes  long.
+       Each block is handled independently.  If a media or trans­
+       mission error causes a multiâ€block  .bz2  file  to  become
+       damaged,  it  may  be  possible  to  recover data from the
+       undamaged blocks in the file.
+
+       The compressed representation of each block  is  delimited
+       by  a  48â€bit pattern, which makes it possible to find the
+       block boundaries with reasonable  certainty.   Each  block
+       also  carries its own 32â€bit CRC, so damaged blocks can be
+       distinguished from undamaged ones.
+
+       _b_z_i_p_2_r_e_c_o_v_e_r is a  simple  program  whose  purpose  is  to
+       search  for blocks in .bz2 files, and write each block out
+       into its own .bz2 file.  You can then use _b_z_i_p_2 −t to test
+       the integrity of the resulting files, and decompress those
+       which are undamaged.
+
+       _b_z_i_p_2_r_e_c_o_v_e_r takes a single argument, the name of the dam­
+       aged    file,    and    writes    a    number   of   files
+       "rec00001file.bz2",  "rec00002file.bz2",  etc,  containing
+       the   extracted   blocks.   The   output   filenames   are
+       designed  so  that the use of wildcards in subsequent pro­
+       cessing  â€â€ for example, "bzip2 â€dc  rec*file.bz2 > recov­
+       ered_data" â€â€ processes the files in the correct order.
+
+       _b_z_i_p_2_r_e_c_o_v_e_r should be of most use dealing with large .bz2
+       files,  as  these will contain many blocks.  It is clearly
+       futile to use it on damaged singleâ€block  files,  since  a
+       damaged  block  cannot  be recovered.  If you wish to min­
+       imise any potential data loss through media  or  transmis­
+       sion errors, you might consider compressing with a smaller
+       block size.
+
+
+PPEERRFFOORRMMAANNCCEE NNOOTTEESS
+       The sorting phase of compression gathers together  similar
+       strings  in  the  file.  Because of this, files containing
+       very long runs of  repeated  symbols,  like  "aabaabaabaab
+       ..."   (repeated  several hundred times) may compress more
+       slowly than normal.  Versions 0.9.5 and  above  fare  much
+       better  than previous versions in this respect.  The ratio
+       between worstâ€case and averageâ€case compression time is in
+       the  region  of  10:1.  For previous versions, this figure
+       was more like 100:1.  You can use the −vvvv option to mon­
+       itor progress in great detail, if you want.
+
+       Decompression speed is unaffected by these phenomena.
+
+       _b_z_i_p_2  usually  allocates  several  megabytes of memory to
+       operate in, and then charges all over it in a fairly  ran­
+       dom  fashion.   This means that performance, both for com­
+       pressing and decompressing, is largely determined  by  the
+       speed  at  which  your  machine  can service cache misses.
+       Because of this, small changes to the code to  reduce  the
+       miss  rate  have  been observed to give disproportionately
+       large performance improvements.  I imagine _b_z_i_p_2 will per­
+       form best on machines with very large caches.
+
+
+CCAAVVEEAATTSS
+       I/O  error  messages  are not as helpful as they could be.
+       _b_z_i_p_2 tries hard to detect I/O errors  and  exit  cleanly,
+       but  the  details  of  what  the problem is sometimes seem
+       rather misleading.
+
+       This manual page pertains to version 1.0.3 of _b_z_i_p_2_.  Com­
+       pressed  data created by this version is entirely forwards
+       and  backwards  compatible  with   the   previous   public
+       releases,  versions 0.1pl2, 0.9.0, 0.9.5, 1.0.0, 1.0.1 and
+       1.0.2, but with the following exception: 0.9.0  and  above
+       can  correctly decompress multiple concatenated compressed
+       files.  0.1pl2 cannot do this; it will stop  after  decom­
+       pressing just the first file in the stream.
+
+       _b_z_i_p_2_r_e_c_o_v_e_r  versions prior to 1.0.2 used 32â€bit integers
+       to represent bit positions in compressed  files,  so  they
+       could  not handle compressed files more than 512 megabytes
+       long.  Versions 1.0.2 and above use 64â€bit  ints  on  some
+       platforms  which  support them (GNU supported targets, and
+       Windows).  To establish whether or  not  bzip2recover  was
+       built  with  such  a limitation, run it without arguments.
+       In any event you can build yourself an  unlimited  version
+       if  you  can  recompile  it  with MaybeUInt64 set to be an
+       unsigned 64â€bit integer.
+
+
+
+
+AAUUTTHHOORR
+       Julian Seward, jsewardbzip.org.
+
+       http://www.bzip.org
+
+       The ideas embodied in _b_z_i_p_2 are due to (at least) the fol­
+       lowing  people: Michael Burrows and David Wheeler (for the
+       block sorting transformation), David Wheeler  (again,  for
+       the Huffman coder), Peter Fenwick (for the structured cod­
+       ing model in the original _b_z_i_p_, and many refinements), and
+       Alistair  Moffat,  Radford  Neal  and  Ian Witten (for the
+       arithmetic  coder  in  the  original  _b_z_i_p_)_.   I  am  much
+       indebted for their help, support and advice.  See the man­
+       ual in the source distribution for pointers to sources  of
+       documentation.  Christian von Roques encouraged me to look
+       for faster sorting algorithms, so as to speed up  compres­
+       sion.  Bela Lubkin encouraged me to improve the worstâ€case
+       compression performance.  Donna Robinson XMLised the docu­
+       mentation.   The bz* scripts are derived from those of GNU
+       gzip.  Many people sent patches, helped  with  portability
+       problems,  lent  machines,  gave advice and were generally
+       helpful.
+
+
+
+                                                         bzip2(1)
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/bzip2.c b/contrib/vmap_extractor_v2/stormlib/bzip2/bzip2.c
new file mode 100644
index 00000000000..79f87a51986
--- /dev/null
+++ b/contrib/vmap_extractor_v2/stormlib/bzip2/bzip2.c
@@ -0,0 +1,2107 @@
+
+/*-----------------------------------------------------------*/
+/*--- A block-sorting, lossless compressor        bzip2.c ---*/
+/*-----------------------------------------------------------*/
+
+/*--
+  This file is a part of bzip2 and/or libbzip2, a program and
+  library for lossless, block-sorting data compression.
+
+  Copyright (C) 1996-2005 Julian R Seward.  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+  2. The origin of this software must not be misrepresented; you must 
+     not claim that you wrote the original software.  If you use this 
+     software in a product, an acknowledgment in the product 
+     documentation would be appreciated but is not required.
+
+  3. Altered source versions must be plainly marked as such, and must
+     not be misrepresented as being the original software.
+
+  4. The name of the author may not be used to endorse or promote 
+     products derived from this software without specific prior written 
+     permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  Julian Seward, Cambridge, UK.
+  jseward@bzip.org
+  bzip2/libbzip2 version 1.0 of 21 March 2000
+
+  This program is based on (at least) the work of:
+     Mike Burrows
+     David Wheeler
+     Peter Fenwick
+     Alistair Moffat
+     Radford Neal
+     Ian H. Witten
+     Robert Sedgewick
+     Jon L. Bentley
+
+  For more information on these sources, see the manual.
+--*/
+
+
+/*----------------------------------------------------*/
+/*--- IMPORTANT                                    ---*/
+/*----------------------------------------------------*/
+
+/*--
+   WARNING:
+      This program and library (attempts to) compress data by 
+      performing several non-trivial transformations on it.  
+      Unless you are 100% familiar with *all* the algorithms 
+      contained herein, and with the consequences of modifying them, 
+      you should NOT meddle with the compression or decompression 
+      machinery.  Incorrect changes can and very likely *will* 
+      lead to disasterous loss of data.
+
+   DISCLAIMER:
+      I TAKE NO RESPONSIBILITY FOR ANY LOSS OF DATA ARISING FROM THE
+      USE OF THIS PROGRAM, HOWSOEVER CAUSED.
+
+      Every compression of a file implies an assumption that the
+      compressed file can be decompressed to reproduce the original.
+      Great efforts in design, coding and testing have been made to
+      ensure that this program works correctly.  However, the
+      complexity of the algorithms, and, in particular, the presence
+      of various special cases in the code which occur with very low
+      but non-zero probability make it impossible to rule out the
+      possibility of bugs remaining in the program.  DO NOT COMPRESS
+      ANY DATA WITH THIS PROGRAM AND/OR LIBRARY UNLESS YOU ARE PREPARED 
+      TO ACCEPT THE POSSIBILITY, HOWEVER SMALL, THAT THE DATA WILL 
+      NOT BE RECOVERABLE.
+
+      That is not to say this program is inherently unreliable.
+      Indeed, I very much hope the opposite is true.  bzip2/libbzip2
+      has been carefully constructed and extensively tested.
+
+   PATENTS:
+      To the best of my knowledge, bzip2/libbzip2 does not use any 
+      patented algorithms.  However, I do not have the resources 
+      available to carry out a full patent search.  Therefore I cannot 
+      give any guarantee of the above statement.
+--*/
+
+
+
+/*----------------------------------------------------*/
+/*--- and now for something much more pleasant :-) ---*/
+/*----------------------------------------------------*/
+
+/*---------------------------------------------*/
+/*--
+  Place a 1 beside your platform, and 0 elsewhere.
+--*/
+
+/*--
+  Generic 32-bit Unix.
+  Also works on 64-bit Unix boxes.
+  This is the default.
+--*/
+#define BZ_UNIX      1
+
+/*--
+  Win32, as seen by Jacob Navia's excellent
+  port of (Chris Fraser & David Hanson)'s excellent
+  lcc compiler.  Or with MS Visual C.
+  This is selected automatically if compiled by a compiler which
+  defines _WIN32, not including the Cygwin GCC.
+--*/
+#define BZ_LCCWIN32  0
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#undef  BZ_LCCWIN32
+#define BZ_LCCWIN32 1
+#undef  BZ_UNIX
+#define BZ_UNIX 0
+#endif
+
+
+/*---------------------------------------------*/
+/*--
+  Some stuff for all platforms.
+--*/
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "bzlib.h"
+
+#define ERROR_IF_EOF(i)       { if ((i) == EOF)  ioError(); }
+#define ERROR_IF_NOT_ZERO(i)  { if ((i) != 0)    ioError(); }
+#define ERROR_IF_MINUS_ONE(i) { if ((i) == (-1)) ioError(); }
+
+
+/*---------------------------------------------*/
+/*--
+   Platform-specific stuff.
+--*/
+
+#if BZ_UNIX
+#   include 
+#   include 
+#   include 
+#   include 
+#   include 
+#   include 
+
+#   define PATH_SEP    '/'
+#   define MY_LSTAT    lstat
+#   define MY_STAT     stat
+#   define MY_S_ISREG  S_ISREG
+#   define MY_S_ISDIR  S_ISDIR
+
+#   define APPEND_FILESPEC(root, name) \
+      root=snocString((root), (name))
+
+#   define APPEND_FLAG(root, name) \
+      root=snocString((root), (name))
+
+#   define SET_BINARY_MODE(fd) /**/
+
+#   ifdef __GNUC__
+#      define NORETURN __attribute__ ((noreturn))
+#   else
+#      define NORETURN /**/
+#   endif
+
+#   ifdef __DJGPP__
+#     include 
+#     include 
+#     undef MY_LSTAT
+#     undef MY_STAT
+#     define MY_LSTAT stat
+#     define MY_STAT stat
+#     undef SET_BINARY_MODE
+#     define SET_BINARY_MODE(fd)                        \
+        do {                                            \
+           int retVal = setmode ( fileno ( fd ),        \
+                                  O_BINARY );           \
+           ERROR_IF_MINUS_ONE ( retVal );               \
+        } while ( 0 )
+#   endif
+
+#   ifdef __CYGWIN__
+#     include 
+#     include 
+#     undef SET_BINARY_MODE
+#     define SET_BINARY_MODE(fd)                        \
+        do {                                            \
+           int retVal = setmode ( fileno ( fd ),        \
+                                  O_BINARY );           \
+           ERROR_IF_MINUS_ONE ( retVal );               \
+        } while ( 0 )
+#   endif
+#endif /* BZ_UNIX */
+
+
+
+#if BZ_LCCWIN32
+#   include 
+#   include 
+#   include 
+
+#   define NORETURN       /**/
+#   define PATH_SEP       '\\'
+#   define MY_LSTAT       _stat
+#   define MY_STAT        _stat
+#   define MY_S_ISREG(x)  ((x) & _S_IFREG)
+#   define MY_S_ISDIR(x)  ((x) & _S_IFDIR)
+
+#   define APPEND_FLAG(root, name) \
+      root=snocString((root), (name))
+
+#   define APPEND_FILESPEC(root, name)                \
+      root = snocString ((root), (name))
+
+#   define SET_BINARY_MODE(fd)                        \
+      do {                                            \
+         int retVal = setmode ( fileno ( fd ),        \
+                                O_BINARY );           \
+         ERROR_IF_MINUS_ONE ( retVal );               \
+      } while ( 0 )
+
+#endif /* BZ_LCCWIN32 */
+
+
+/*---------------------------------------------*/
+/*--
+  Some more stuff for all platforms :-)
+--*/
+
+typedef char            Char;
+typedef unsigned char   Bool;
+typedef unsigned char   UChar;
+typedef int             Int32;
+typedef unsigned int    UInt32;
+typedef short           Int16;
+typedef unsigned short  UInt16;
+                                       
+#define True  ((Bool)1)
+#define False ((Bool)0)
+
+/*--
+  IntNative is your platform's `native' int size.
+  Only here to avoid probs with 64-bit platforms.
+--*/
+typedef int IntNative;
+
+
+/*---------------------------------------------------*/
+/*--- Misc (file handling) data decls             ---*/
+/*---------------------------------------------------*/
+
+Int32   verbosity;
+Bool    keepInputFiles, smallMode, deleteOutputOnInterrupt;
+Bool    forceOverwrite, testFailsExist, unzFailsExist, noisy;
+Int32   numFileNames, numFilesProcessed, blockSize100k;
+Int32   exitValue;
+
+/*-- source modes; F==file, I==stdin, O==stdout --*/
+#define SM_I2O           1
+#define SM_F2O           2
+#define SM_F2F           3
+
+/*-- operation modes --*/
+#define OM_Z             1
+#define OM_UNZ           2
+#define OM_TEST          3
+
+Int32   opMode;
+Int32   srcMode;
+
+#define FILE_NAME_LEN 1034
+
+Int32   longestFileName;
+Char    inName [FILE_NAME_LEN];
+Char    outName[FILE_NAME_LEN];
+Char    tmpName[FILE_NAME_LEN];
+Char    *progName;
+Char    progNameReally[FILE_NAME_LEN];
+FILE    *outputHandleJustInCase;
+Int32   workFactor;
+
+static void    panic                 ( Char* )   NORETURN;
+static void    ioError               ( void )    NORETURN;
+static void    outOfMemory           ( void )    NORETURN;
+static void    configError           ( void )    NORETURN;
+static void    crcError              ( void )    NORETURN;
+static void    cleanUpAndFail        ( Int32 )   NORETURN;
+static void    compressedStreamEOF   ( void )    NORETURN;
+
+static void    copyFileName ( Char*, Char* );
+static void*   myMalloc     ( Int32 );
+
+
+
+/*---------------------------------------------------*/
+/*--- An implementation of 64-bit ints.  Sigh.    ---*/
+/*--- Roll on widespread deployment of ANSI C9X ! ---*/
+/*---------------------------------------------------*/
+
+typedef
+   struct { UChar b[8]; } 
+   UInt64;
+
+
+static
+void uInt64_from_UInt32s ( UInt64* n, UInt32 lo32, UInt32 hi32 )
+{
+   n->b[7] = (UChar)((hi32 >> 24) & 0xFF);
+   n->b[6] = (UChar)((hi32 >> 16) & 0xFF);
+   n->b[5] = (UChar)((hi32 >> 8)  & 0xFF);
+   n->b[4] = (UChar) (hi32        & 0xFF);
+   n->b[3] = (UChar)((lo32 >> 24) & 0xFF);
+   n->b[2] = (UChar)((lo32 >> 16) & 0xFF);
+   n->b[1] = (UChar)((lo32 >> 8)  & 0xFF);
+   n->b[0] = (UChar) (lo32        & 0xFF);
+}
+
+
+static
+double uInt64_to_double ( UInt64* n )
+{
+   Int32  i;
+   double base = 1.0;
+   double sum  = 0.0;
+   for (i = 0; i < 8; i++) {
+      sum  += base * (double)(n->b[i]);
+      base *= 256.0;
+   }
+   return sum;
+}
+
+
+static
+Bool uInt64_isZero ( UInt64* n )
+{
+   Int32 i;
+   for (i = 0; i < 8; i++)
+      if (n->b[i] != 0) return 0;
+   return 1;
+}
+
+
+/* Divide *n by 10, and return the remainder.  */
+static 
+Int32 uInt64_qrm10 ( UInt64* n )
+{
+   UInt32 rem, tmp;
+   Int32  i;
+   rem = 0;
+   for (i = 7; i >= 0; i--) {
+      tmp = rem * 256 + n->b[i];
+      n->b[i] = tmp / 10;
+      rem = tmp % 10;
+   }
+   return rem;
+}
+
+
+/* ... and the Whole Entire Point of all this UInt64 stuff is
+   so that we can supply the following function.
+*/
+static
+void uInt64_toAscii ( char* outbuf, UInt64* n )
+{
+   Int32  i, q;
+   UChar  buf[32];
+   Int32  nBuf   = 0;
+   UInt64 n_copy = *n;
+   do {
+      q = uInt64_qrm10 ( &n_copy );
+      buf[nBuf] = q + '0';
+      nBuf++;
+   } while (!uInt64_isZero(&n_copy));
+   outbuf[nBuf] = 0;
+   for (i = 0; i < nBuf; i++) 
+      outbuf[i] = buf[nBuf-i-1];
+}
+
+
+/*---------------------------------------------------*/
+/*--- Processing of complete files and streams    ---*/
+/*---------------------------------------------------*/
+
+/*---------------------------------------------*/
+static 
+Bool myfeof ( FILE* f )
+{
+   Int32 c = fgetc ( f );
+   if (c == EOF) return True;
+   ungetc ( c, f );
+   return False;
+}
+
+
+/*---------------------------------------------*/
+static 
+void compressStream ( FILE *stream, FILE *zStream )
+{
+   BZFILE* bzf = NULL;
+   UChar   ibuf[5000];
+   Int32   nIbuf;
+   UInt32  nbytes_in_lo32, nbytes_in_hi32;
+   UInt32  nbytes_out_lo32, nbytes_out_hi32;
+   Int32   bzerr, bzerr_dummy, ret;
+
+   SET_BINARY_MODE(stream);
+   SET_BINARY_MODE(zStream);
+
+   if (ferror(stream)) goto errhandler_io;
+   if (ferror(zStream)) goto errhandler_io;
+
+   bzf = BZ2_bzWriteOpen ( &bzerr, zStream, 
+                           blockSize100k, verbosity, workFactor );   
+   if (bzerr != BZ_OK) goto errhandler;
+
+   if (verbosity >= 2) fprintf ( stderr, "\n" );
+
+   while (True) {
+
+      if (myfeof(stream)) break;
+      nIbuf = fread ( ibuf, sizeof(UChar), 5000, stream );
+      if (ferror(stream)) goto errhandler_io;
+      if (nIbuf > 0) BZ2_bzWrite ( &bzerr, bzf, (void*)ibuf, nIbuf );
+      if (bzerr != BZ_OK) goto errhandler;
+
+   }
+
+   BZ2_bzWriteClose64 ( &bzerr, bzf, 0, 
+                        &nbytes_in_lo32, &nbytes_in_hi32,
+                        &nbytes_out_lo32, &nbytes_out_hi32 );
+   if (bzerr != BZ_OK) goto errhandler;
+
+   if (ferror(zStream)) goto errhandler_io;
+   ret = fflush ( zStream );
+   if (ret == EOF) goto errhandler_io;
+   if (zStream != stdout) {
+      ret = fclose ( zStream );
+      outputHandleJustInCase = NULL;
+      if (ret == EOF) goto errhandler_io;
+   }
+   outputHandleJustInCase = NULL;
+   if (ferror(stream)) goto errhandler_io;
+   ret = fclose ( stream );
+   if (ret == EOF) goto errhandler_io;
+
+   if (verbosity >= 1) {
+      if (nbytes_in_lo32 == 0 && nbytes_in_hi32 == 0) {
+	 fprintf ( stderr, " no data compressed.\n");
+      } else {
+	 Char   buf_nin[32], buf_nout[32];
+	 UInt64 nbytes_in,   nbytes_out;
+	 double nbytes_in_d, nbytes_out_d;
+	 uInt64_from_UInt32s ( &nbytes_in, 
+			       nbytes_in_lo32, nbytes_in_hi32 );
+	 uInt64_from_UInt32s ( &nbytes_out, 
+			       nbytes_out_lo32, nbytes_out_hi32 );
+	 nbytes_in_d  = uInt64_to_double ( &nbytes_in );
+	 nbytes_out_d = uInt64_to_double ( &nbytes_out );
+	 uInt64_toAscii ( buf_nin, &nbytes_in );
+	 uInt64_toAscii ( buf_nout, &nbytes_out );
+	 fprintf ( stderr, "%6.3f:1, %6.3f bits/byte, "
+		   "%5.2f%% saved, %s in, %s out.\n",
+		   nbytes_in_d / nbytes_out_d,
+		   (8.0 * nbytes_out_d) / nbytes_in_d,
+		   100.0 * (1.0 - nbytes_out_d / nbytes_in_d),
+		   buf_nin,
+		   buf_nout
+		 );
+      }
+   }
+
+   return;
+
+   errhandler:
+   BZ2_bzWriteClose64 ( &bzerr_dummy, bzf, 1, 
+                        &nbytes_in_lo32, &nbytes_in_hi32,
+                        &nbytes_out_lo32, &nbytes_out_hi32 );
+   switch (bzerr) {
+      case BZ_CONFIG_ERROR:
+         configError(); break;
+      case BZ_MEM_ERROR:
+         outOfMemory (); break;
+      case BZ_IO_ERROR:
+         errhandler_io:
+         ioError(); break;
+      default:
+         panic ( "compress:unexpected error" );
+   }
+
+   panic ( "compress:end" );
+   /*notreached*/
+}
+
+
+
+/*---------------------------------------------*/
+static 
+Bool uncompressStream ( FILE *zStream, FILE *stream )
+{
+   BZFILE* bzf = NULL;
+   Int32   bzerr, bzerr_dummy, ret, nread, streamNo, i;
+   UChar   obuf[5000];
+   UChar   unused[BZ_MAX_UNUSED];
+   Int32   nUnused;
+   void*   unusedTmpV;
+   UChar*  unusedTmp;
+
+   nUnused = 0;
+   streamNo = 0;
+
+   SET_BINARY_MODE(stream);
+   SET_BINARY_MODE(zStream);
+
+   if (ferror(stream)) goto errhandler_io;
+   if (ferror(zStream)) goto errhandler_io;
+
+   while (True) {
+
+      bzf = BZ2_bzReadOpen ( 
+               &bzerr, zStream, verbosity, 
+               (int)smallMode, unused, nUnused
+            );
+      if (bzf == NULL || bzerr != BZ_OK) goto errhandler;
+      streamNo++;
+
+      while (bzerr == BZ_OK) {
+         nread = BZ2_bzRead ( &bzerr, bzf, obuf, 5000 );
+         if (bzerr == BZ_DATA_ERROR_MAGIC) goto trycat;
+         if ((bzerr == BZ_OK || bzerr == BZ_STREAM_END) && nread > 0)
+            fwrite ( obuf, sizeof(UChar), nread, stream );
+         if (ferror(stream)) goto errhandler_io;
+      }
+      if (bzerr != BZ_STREAM_END) goto errhandler;
+
+      BZ2_bzReadGetUnused ( &bzerr, bzf, &unusedTmpV, &nUnused );
+      if (bzerr != BZ_OK) panic ( "decompress:bzReadGetUnused" );
+
+      unusedTmp = (UChar*)unusedTmpV;
+      for (i = 0; i < nUnused; i++) unused[i] = unusedTmp[i];
+
+      BZ2_bzReadClose ( &bzerr, bzf );
+      if (bzerr != BZ_OK) panic ( "decompress:bzReadGetUnused" );
+
+      if (nUnused == 0 && myfeof(zStream)) break;
+   }
+
+   closeok:
+   if (ferror(zStream)) goto errhandler_io;
+   ret = fclose ( zStream );
+   if (ret == EOF) goto errhandler_io;
+
+   if (ferror(stream)) goto errhandler_io;
+   ret = fflush ( stream );
+   if (ret != 0) goto errhandler_io;
+   if (stream != stdout) {
+      ret = fclose ( stream );
+      outputHandleJustInCase = NULL;
+      if (ret == EOF) goto errhandler_io;
+   }
+   outputHandleJustInCase = NULL;
+   if (verbosity >= 2) fprintf ( stderr, "\n    " );
+   return True;
+
+   trycat: 
+   if (forceOverwrite) {
+      rewind(zStream);
+      while (True) {
+      	 if (myfeof(zStream)) break;
+      	 nread = fread ( obuf, sizeof(UChar), 5000, zStream );
+      	 if (ferror(zStream)) goto errhandler_io;
+      	 if (nread > 0) fwrite ( obuf, sizeof(UChar), nread, stream );
+      	 if (ferror(stream)) goto errhandler_io;
+      }
+      goto closeok;
+   }
+  
+   errhandler:
+   BZ2_bzReadClose ( &bzerr_dummy, bzf );
+   switch (bzerr) {
+      case BZ_CONFIG_ERROR:
+         configError(); break;
+      case BZ_IO_ERROR:
+         errhandler_io:
+         ioError(); break;
+      case BZ_DATA_ERROR:
+         crcError();
+      case BZ_MEM_ERROR:
+         outOfMemory();
+      case BZ_UNEXPECTED_EOF:
+         compressedStreamEOF();
+      case BZ_DATA_ERROR_MAGIC:
+         if (zStream != stdin) fclose(zStream);
+         if (stream != stdout) fclose(stream);
+         if (streamNo == 1) {
+            return False;
+         } else {
+            if (noisy)
+            fprintf ( stderr, 
+                      "\n%s: %s: trailing garbage after EOF ignored\n",
+                      progName, inName );
+            return True;       
+         }
+      default:
+         panic ( "decompress:unexpected error" );
+   }
+
+   panic ( "decompress:end" );
+   return True; /*notreached*/
+}
+
+
+/*---------------------------------------------*/
+static 
+Bool testStream ( FILE *zStream )
+{
+   BZFILE* bzf = NULL;
+   Int32   bzerr, bzerr_dummy, ret, nread, streamNo, i;
+   UChar   obuf[5000];
+   UChar   unused[BZ_MAX_UNUSED];
+   Int32   nUnused;
+   void*   unusedTmpV;
+   UChar*  unusedTmp;
+
+   nUnused = 0;
+   streamNo = 0;
+
+   SET_BINARY_MODE(zStream);
+   if (ferror(zStream)) goto errhandler_io;
+
+   while (True) {
+
+      bzf = BZ2_bzReadOpen ( 
+               &bzerr, zStream, verbosity, 
+               (int)smallMode, unused, nUnused
+            );
+      if (bzf == NULL || bzerr != BZ_OK) goto errhandler;
+      streamNo++;
+
+      while (bzerr == BZ_OK) {
+         nread = BZ2_bzRead ( &bzerr, bzf, obuf, 5000 );
+         if (bzerr == BZ_DATA_ERROR_MAGIC) goto errhandler;
+      }
+      if (bzerr != BZ_STREAM_END) goto errhandler;
+
+      BZ2_bzReadGetUnused ( &bzerr, bzf, &unusedTmpV, &nUnused );
+      if (bzerr != BZ_OK) panic ( "test:bzReadGetUnused" );
+
+      unusedTmp = (UChar*)unusedTmpV;
+      for (i = 0; i < nUnused; i++) unused[i] = unusedTmp[i];
+
+      BZ2_bzReadClose ( &bzerr, bzf );
+      if (bzerr != BZ_OK) panic ( "test:bzReadGetUnused" );
+      if (nUnused == 0 && myfeof(zStream)) break;
+
+   }
+
+   if (ferror(zStream)) goto errhandler_io;
+   ret = fclose ( zStream );
+   if (ret == EOF) goto errhandler_io;
+
+   if (verbosity >= 2) fprintf ( stderr, "\n    " );
+   return True;
+
+   errhandler:
+   BZ2_bzReadClose ( &bzerr_dummy, bzf );
+   if (verbosity == 0) 
+      fprintf ( stderr, "%s: %s: ", progName, inName );
+   switch (bzerr) {
+      case BZ_CONFIG_ERROR:
+         configError(); break;
+      case BZ_IO_ERROR:
+         errhandler_io:
+         ioError(); break;
+      case BZ_DATA_ERROR:
+         fprintf ( stderr,
+                   "data integrity (CRC) error in data\n" );
+         return False;
+      case BZ_MEM_ERROR:
+         outOfMemory();
+      case BZ_UNEXPECTED_EOF:
+         fprintf ( stderr,
+                   "file ends unexpectedly\n" );
+         return False;
+      case BZ_DATA_ERROR_MAGIC:
+         if (zStream != stdin) fclose(zStream);
+         if (streamNo == 1) {
+          fprintf ( stderr, 
+                    "bad magic number (file not created by bzip2)\n" );
+            return False;
+         } else {
+            if (noisy)
+            fprintf ( stderr, 
+                      "trailing garbage after EOF ignored\n" );
+            return True;       
+         }
+      default:
+         panic ( "test:unexpected error" );
+   }
+
+   panic ( "test:end" );
+   return True; /*notreached*/
+}
+
+
+/*---------------------------------------------------*/
+/*--- Error [non-] handling grunge                ---*/
+/*---------------------------------------------------*/
+
+/*---------------------------------------------*/
+static
+void setExit ( Int32 v )
+{
+   if (v > exitValue) exitValue = v;
+}
+
+
+/*---------------------------------------------*/
+static 
+void cadvise ( void )
+{
+   if (noisy)
+   fprintf (
+      stderr,
+      "\nIt is possible that the compressed file(s) have become corrupted.\n"
+        "You can use the -tvv option to test integrity of such files.\n\n"
+        "You can use the `bzip2recover' program to attempt to recover\n"
+        "data from undamaged sections of corrupted files.\n\n"
+    );
+}
+
+
+/*---------------------------------------------*/
+static 
+void showFileNames ( void )
+{
+   if (noisy)
+   fprintf (
+      stderr,
+      "\tInput file = %s, output file = %s\n",
+      inName, outName 
+   );
+}
+
+
+/*---------------------------------------------*/
+static 
+void cleanUpAndFail ( Int32 ec )
+{
+   IntNative      retVal;
+   struct MY_STAT statBuf;
+
+   if ( srcMode == SM_F2F 
+        && opMode != OM_TEST
+        && deleteOutputOnInterrupt ) {
+
+      /* Check whether input file still exists.  Delete output file
+         only if input exists to avoid loss of data.  Joerg Prante, 5
+         January 2002.  (JRS 06-Jan-2002: other changes in 1.0.2 mean
+         this is less likely to happen.  But to be ultra-paranoid, we
+         do the check anyway.)  */
+      retVal = MY_STAT ( inName, &statBuf );
+      if (retVal == 0) {
+         if (noisy)
+            fprintf ( stderr, 
+                      "%s: Deleting output file %s, if it exists.\n",
+                      progName, outName );
+         if (outputHandleJustInCase != NULL)
+            fclose ( outputHandleJustInCase );
+         retVal = remove ( outName );
+         if (retVal != 0)
+            fprintf ( stderr,
+                      "%s: WARNING: deletion of output file "
+                      "(apparently) failed.\n",
+                      progName );
+      } else {
+         fprintf ( stderr,
+                   "%s: WARNING: deletion of output file suppressed\n",
+                    progName );
+         fprintf ( stderr,
+                   "%s:    since input file no longer exists.  Output file\n",
+                   progName );
+         fprintf ( stderr,
+                   "%s:    `%s' may be incomplete.\n",
+                   progName, outName );
+         fprintf ( stderr, 
+                   "%s:    I suggest doing an integrity test (bzip2 -tv)"
+                   " of it.\n",
+                   progName );
+      }
+   }
+
+   if (noisy && numFileNames > 0 && numFilesProcessed < numFileNames) {
+      fprintf ( stderr, 
+                "%s: WARNING: some files have not been processed:\n"
+                "%s:    %d specified on command line, %d not processed yet.\n\n",
+                progName, progName,
+                numFileNames, numFileNames - numFilesProcessed );
+   }
+   setExit(ec);
+   exit(exitValue);
+}
+
+
+/*---------------------------------------------*/
+static 
+void panic ( Char* s )
+{
+   fprintf ( stderr,
+             "\n%s: PANIC -- internal consistency error:\n"
+             "\t%s\n"
+             "\tThis is a BUG.  Please report it to me at:\n"
+             "\tjseward@bzip.org\n",
+             progName, s );
+   showFileNames();
+   cleanUpAndFail( 3 );
+}
+
+
+/*---------------------------------------------*/
+static 
+void crcError ( void )
+{
+   fprintf ( stderr,
+             "\n%s: Data integrity error when decompressing.\n",
+             progName );
+   showFileNames();
+   cadvise();
+   cleanUpAndFail( 2 );
+}
+
+
+/*---------------------------------------------*/
+static 
+void compressedStreamEOF ( void )
+{
+  if (noisy) {
+    fprintf ( stderr,
+	      "\n%s: Compressed file ends unexpectedly;\n\t"
+	      "perhaps it is corrupted?  *Possible* reason follows.\n",
+	      progName );
+    perror ( progName );
+    showFileNames();
+    cadvise();
+  }
+  cleanUpAndFail( 2 );
+}
+
+
+/*---------------------------------------------*/
+static 
+void ioError ( void )
+{
+   fprintf ( stderr,
+             "\n%s: I/O or other error, bailing out.  "
+             "Possible reason follows.\n",
+             progName );
+   perror ( progName );
+   showFileNames();
+   cleanUpAndFail( 1 );
+}
+
+
+/*---------------------------------------------*/
+static 
+void mySignalCatcher ( IntNative n )
+{
+   fprintf ( stderr,
+             "\n%s: Control-C or similar caught, quitting.\n",
+             progName );
+   cleanUpAndFail(1);
+}
+
+
+/*---------------------------------------------*/
+static 
+void mySIGSEGVorSIGBUScatcher ( IntNative n )
+{
+   if (opMode == OM_Z)
+      fprintf ( 
+      stderr,
+      "\n%s: Caught a SIGSEGV or SIGBUS whilst compressing.\n"
+      "\n"
+      "   Possible causes are (most likely first):\n"
+      "   (1) This computer has unreliable memory or cache hardware\n"
+      "       (a surprisingly common problem; try a different machine.)\n"
+      "   (2) A bug in the compiler used to create this executable\n"
+      "       (unlikely, if you didn't compile bzip2 yourself.)\n"
+      "   (3) A real bug in bzip2 -- I hope this should never be the case.\n"
+      "   The user's manual, Section 4.3, has more info on (1) and (2).\n"
+      "   \n"
+      "   If you suspect this is a bug in bzip2, or are unsure about (1)\n"
+      "   or (2), feel free to report it to me at: jseward@bzip.org.\n"
+      "   Section 4.3 of the user's manual describes the info a useful\n"
+      "   bug report should have.  If the manual is available on your\n"
+      "   system, please try and read it before mailing me.  If you don't\n"
+      "   have the manual or can't be bothered to read it, mail me anyway.\n"
+      "\n",
+      progName );
+      else
+      fprintf ( 
+      stderr,
+      "\n%s: Caught a SIGSEGV or SIGBUS whilst decompressing.\n"
+      "\n"
+      "   Possible causes are (most likely first):\n"
+      "   (1) The compressed data is corrupted, and bzip2's usual checks\n"
+      "       failed to detect this.  Try bzip2 -tvv my_file.bz2.\n"
+      "   (2) This computer has unreliable memory or cache hardware\n"
+      "       (a surprisingly common problem; try a different machine.)\n"
+      "   (3) A bug in the compiler used to create this executable\n"
+      "       (unlikely, if you didn't compile bzip2 yourself.)\n"
+      "   (4) A real bug in bzip2 -- I hope this should never be the case.\n"
+      "   The user's manual, Section 4.3, has more info on (2) and (3).\n"
+      "   \n"
+      "   If you suspect this is a bug in bzip2, or are unsure about (2)\n"
+      "   or (3), feel free to report it to me at: jseward@bzip.org.\n"
+      "   Section 4.3 of the user's manual describes the info a useful\n"
+      "   bug report should have.  If the manual is available on your\n"
+      "   system, please try and read it before mailing me.  If you don't\n"
+      "   have the manual or can't be bothered to read it, mail me anyway.\n"
+      "\n",
+      progName );
+
+   showFileNames();
+   if (opMode == OM_Z)
+      cleanUpAndFail( 3 ); else
+      { cadvise(); cleanUpAndFail( 2 ); }
+}
+
+
+/*---------------------------------------------*/
+static 
+void outOfMemory ( void )
+{
+   fprintf ( stderr,
+             "\n%s: couldn't allocate enough memory\n",
+             progName );
+   showFileNames();
+   cleanUpAndFail(1);
+}
+
+
+/*---------------------------------------------*/
+static 
+void configError ( void )
+{
+   fprintf ( stderr,
+             "bzip2: I'm not configured correctly for this platform!\n"
+             "\tI require Int32, Int16 and Char to have sizes\n"
+             "\tof 4, 2 and 1 bytes to run properly, and they don't.\n"
+             "\tProbably you can fix this by defining them correctly,\n"
+             "\tand recompiling.  Bye!\n" );
+   setExit(3);
+   exit(exitValue);
+}
+
+
+/*---------------------------------------------------*/
+/*--- The main driver machinery                   ---*/
+/*---------------------------------------------------*/
+
+/* All rather crufty.  The main problem is that input files
+   are stat()d multiple times before use.  This should be
+   cleaned up. 
+*/
+
+/*---------------------------------------------*/
+static 
+void pad ( Char *s )
+{
+   Int32 i;
+   if ( (Int32)strlen(s) >= longestFileName ) return;
+   for (i = 1; i <= longestFileName - (Int32)strlen(s); i++)
+      fprintf ( stderr, " " );
+}
+
+
+/*---------------------------------------------*/
+static 
+void copyFileName ( Char* to, Char* from ) 
+{
+   if ( strlen(from) > FILE_NAME_LEN-10 )  {
+      fprintf (
+         stderr,
+         "bzip2: file name\n`%s'\n"
+         "is suspiciously (more than %d chars) long.\n"
+         "Try using a reasonable file name instead.  Sorry! :-)\n",
+         from, FILE_NAME_LEN-10
+      );
+      setExit(1);
+      exit(exitValue);
+   }
+
+  strncpy(to,from,FILE_NAME_LEN-10);
+  to[FILE_NAME_LEN-10]='\0';
+}
+
+
+/*---------------------------------------------*/
+static 
+Bool fileExists ( Char* name )
+{
+   FILE *tmp   = fopen ( name, "rb" );
+   Bool exists = (tmp != NULL);
+   if (tmp != NULL) fclose ( tmp );
+   return exists;
+}
+
+
+/*---------------------------------------------*/
+/* Open an output file safely with O_EXCL and good permissions.
+   This avoids a race condition in versions < 1.0.2, in which
+   the file was first opened and then had its interim permissions
+   set safely.  We instead use open() to create the file with
+   the interim permissions required. (--- --- rw-).
+
+   For non-Unix platforms, if we are not worrying about
+   security issues, simple this simply behaves like fopen.
+*/
+FILE* fopen_output_safely ( Char* name, const char* mode )
+{
+#  if BZ_UNIX
+   FILE*     fp;
+   IntNative fh;
+   fh = open(name, O_WRONLY|O_CREAT|O_EXCL, S_IWUSR|S_IRUSR);
+   if (fh == -1) return NULL;
+   fp = fdopen(fh, mode);
+   if (fp == NULL) close(fh);
+   return fp;
+#  else
+   return fopen(name, mode);
+#  endif
+}
+
+
+/*---------------------------------------------*/
+/*--
+  if in doubt, return True
+--*/
+static 
+Bool notAStandardFile ( Char* name )
+{
+   IntNative      i;
+   struct MY_STAT statBuf;
+
+   i = MY_LSTAT ( name, &statBuf );
+   if (i != 0) return True;
+   if (MY_S_ISREG(statBuf.st_mode)) return False;
+   return True;
+}
+
+
+/*---------------------------------------------*/
+/*--
+  rac 11/21/98 see if file has hard links to it
+--*/
+static 
+Int32 countHardLinks ( Char* name )
+{  
+   IntNative      i;
+   struct MY_STAT statBuf;
+
+   i = MY_LSTAT ( name, &statBuf );
+   if (i != 0) return 0;
+   return (statBuf.st_nlink - 1);
+}
+
+
+/*---------------------------------------------*/
+/* Copy modification date, access date, permissions and owner from the
+   source to destination file.  We have to copy this meta-info off
+   into fileMetaInfo before starting to compress / decompress it,
+   because doing it afterwards means we get the wrong access time.
+
+   To complicate matters, in compress() and decompress() below, the
+   sequence of tests preceding the call to saveInputFileMetaInfo()
+   involves calling fileExists(), which in turn establishes its result
+   by attempting to fopen() the file, and if successful, immediately
+   fclose()ing it again.  So we have to assume that the fopen() call
+   does not cause the access time field to be updated.
+
+   Reading of the man page for stat() (man 2 stat) on RedHat 7.2 seems
+   to imply that merely doing open() will not affect the access time.
+   Therefore we merely need to hope that the C library only does
+   open() as a result of fopen(), and not any kind of read()-ahead
+   cleverness.
+
+   It sounds pretty fragile to me.  Whether this carries across
+   robustly to arbitrary Unix-like platforms (or even works robustly
+   on this one, RedHat 7.2) is unknown to me.  Nevertheless ...  
+*/
+#if BZ_UNIX
+static 
+struct MY_STAT fileMetaInfo;
+#endif
+
+static 
+void saveInputFileMetaInfo ( Char *srcName )
+{
+#  if BZ_UNIX
+   IntNative retVal;
+   /* Note use of stat here, not lstat. */
+   retVal = MY_STAT( srcName, &fileMetaInfo );
+   ERROR_IF_NOT_ZERO ( retVal );
+#  endif
+}
+
+
+static 
+void applySavedMetaInfoToOutputFile ( Char *dstName )
+{
+#  if BZ_UNIX
+   IntNative      retVal;
+   struct utimbuf uTimBuf;
+
+   uTimBuf.actime = fileMetaInfo.st_atime;
+   uTimBuf.modtime = fileMetaInfo.st_mtime;
+
+   retVal = chmod ( dstName, fileMetaInfo.st_mode );
+   ERROR_IF_NOT_ZERO ( retVal );
+
+   retVal = utime ( dstName, &uTimBuf );
+   ERROR_IF_NOT_ZERO ( retVal );
+
+   retVal = chown ( dstName, fileMetaInfo.st_uid, fileMetaInfo.st_gid );
+   /* chown() will in many cases return with EPERM, which can
+      be safely ignored.
+   */
+#  endif
+}
+
+
+/*---------------------------------------------*/
+static 
+Bool containsDubiousChars ( Char* name )
+{
+#  if BZ_UNIX
+   /* On unix, files can contain any characters and the file expansion
+    * is performed by the shell.
+    */
+   return False;
+#  else /* ! BZ_UNIX */
+   /* On non-unix (Win* platforms), wildcard characters are not allowed in 
+    * filenames.
+    */
+   for (; *name != '\0'; name++)
+      if (*name == '?' || *name == '*') return True;
+   return False;
+#  endif /* BZ_UNIX */
+}
+
+
+/*---------------------------------------------*/
+#define BZ_N_SUFFIX_PAIRS 4
+
+Char* zSuffix[BZ_N_SUFFIX_PAIRS] 
+   = { ".bz2", ".bz", ".tbz2", ".tbz" };
+Char* unzSuffix[BZ_N_SUFFIX_PAIRS] 
+   = { "", "", ".tar", ".tar" };
+
+static 
+Bool hasSuffix ( Char* s, Char* suffix )
+{
+   Int32 ns = strlen(s);
+   Int32 nx = strlen(suffix);
+   if (ns < nx) return False;
+   if (strcmp(s + ns - nx, suffix) == 0) return True;
+   return False;
+}
+
+static 
+Bool mapSuffix ( Char* name, 
+                 Char* oldSuffix, Char* newSuffix )
+{
+   if (!hasSuffix(name,oldSuffix)) return False;
+   name[strlen(name)-strlen(oldSuffix)] = 0;
+   strcat ( name, newSuffix );
+   return True;
+}
+
+
+/*---------------------------------------------*/
+static 
+void compress ( Char *name )
+{
+   FILE  *inStr;
+   FILE  *outStr;
+   Int32 n, i;
+   struct MY_STAT statBuf;
+
+   deleteOutputOnInterrupt = False;
+
+   if (name == NULL && srcMode != SM_I2O)
+      panic ( "compress: bad modes\n" );
+
+   switch (srcMode) {
+      case SM_I2O: 
+         copyFileName ( inName, "(stdin)" );
+         copyFileName ( outName, "(stdout)" ); 
+         break;
+      case SM_F2F: 
+         copyFileName ( inName, name );
+         copyFileName ( outName, name );
+         strcat ( outName, ".bz2" ); 
+         break;
+      case SM_F2O: 
+         copyFileName ( inName, name );
+         copyFileName ( outName, "(stdout)" ); 
+         break;
+   }
+
+   if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) {
+      if (noisy)
+      fprintf ( stderr, "%s: There are no files matching `%s'.\n",
+                progName, inName );
+      setExit(1);
+      return;
+   }
+   if ( srcMode != SM_I2O && !fileExists ( inName ) ) {
+      fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
+                progName, inName, strerror(errno) );
+      setExit(1);
+      return;
+   }
+   for (i = 0; i < BZ_N_SUFFIX_PAIRS; i++) {
+      if (hasSuffix(inName, zSuffix[i])) {
+         if (noisy)
+         fprintf ( stderr, 
+                   "%s: Input file %s already has %s suffix.\n",
+                   progName, inName, zSuffix[i] );
+         setExit(1);
+         return;
+      }
+   }
+   if ( srcMode == SM_F2F || srcMode == SM_F2O ) {
+      MY_STAT(inName, &statBuf);
+      if ( MY_S_ISDIR(statBuf.st_mode) ) {
+         fprintf( stderr,
+                  "%s: Input file %s is a directory.\n",
+                  progName,inName);
+         setExit(1);
+         return;
+      }
+   }
+   if ( srcMode == SM_F2F && !forceOverwrite && notAStandardFile ( inName )) {
+      if (noisy)
+      fprintf ( stderr, "%s: Input file %s is not a normal file.\n",
+                progName, inName );
+      setExit(1);
+      return;
+   }
+   if ( srcMode == SM_F2F && fileExists ( outName ) ) {
+      if (forceOverwrite) {
+	 remove(outName);
+      } else {
+	 fprintf ( stderr, "%s: Output file %s already exists.\n",
+		   progName, outName );
+	 setExit(1);
+	 return;
+      }
+   }
+   if ( srcMode == SM_F2F && !forceOverwrite &&
+        (n=countHardLinks ( inName )) > 0) {
+      fprintf ( stderr, "%s: Input file %s has %d other link%s.\n",
+                progName, inName, n, n > 1 ? "s" : "" );
+      setExit(1);
+      return;
+   }
+
+   if ( srcMode == SM_F2F ) {
+      /* Save the file's meta-info before we open it.  Doing it later
+         means we mess up the access times. */
+      saveInputFileMetaInfo ( inName );
+   }
+
+   switch ( srcMode ) {
+
+      case SM_I2O:
+         inStr = stdin;
+         outStr = stdout;
+         if ( isatty ( fileno ( stdout ) ) ) {
+            fprintf ( stderr,
+                      "%s: I won't write compressed data to a terminal.\n",
+                      progName );
+            fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
+                              progName, progName );
+            setExit(1);
+            return;
+         };
+         break;
+
+      case SM_F2O:
+         inStr = fopen ( inName, "rb" );
+         outStr = stdout;
+         if ( isatty ( fileno ( stdout ) ) ) {
+            fprintf ( stderr,
+                      "%s: I won't write compressed data to a terminal.\n",
+                      progName );
+            fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
+                              progName, progName );
+            if ( inStr != NULL ) fclose ( inStr );
+            setExit(1);
+            return;
+         };
+         if ( inStr == NULL ) {
+            fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
+                      progName, inName, strerror(errno) );
+            setExit(1);
+            return;
+         };
+         break;
+
+      case SM_F2F:
+         inStr = fopen ( inName, "rb" );
+         outStr = fopen_output_safely ( outName, "wb" );
+         if ( outStr == NULL) {
+            fprintf ( stderr, "%s: Can't create output file %s: %s.\n",
+                      progName, outName, strerror(errno) );
+            if ( inStr != NULL ) fclose ( inStr );
+            setExit(1);
+            return;
+         }
+         if ( inStr == NULL ) {
+            fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
+                      progName, inName, strerror(errno) );
+            if ( outStr != NULL ) fclose ( outStr );
+            setExit(1);
+            return;
+         };
+         break;
+
+      default:
+         panic ( "compress: bad srcMode" );
+         break;
+   }
+
+   if (verbosity >= 1) {
+      fprintf ( stderr,  "  %s: ", inName );
+      pad ( inName );
+      fflush ( stderr );
+   }
+
+   /*--- Now the input and output handles are sane.  Do the Biz. ---*/
+   outputHandleJustInCase = outStr;
+   deleteOutputOnInterrupt = True;
+   compressStream ( inStr, outStr );
+   outputHandleJustInCase = NULL;
+
+   /*--- If there was an I/O error, we won't get here. ---*/
+   if ( srcMode == SM_F2F ) {
+      applySavedMetaInfoToOutputFile ( outName );
+      deleteOutputOnInterrupt = False;
+      if ( !keepInputFiles ) {
+         IntNative retVal = remove ( inName );
+         ERROR_IF_NOT_ZERO ( retVal );
+      }
+   }
+
+   deleteOutputOnInterrupt = False;
+}
+
+
+/*---------------------------------------------*/
+static 
+void uncompress ( Char *name )
+{
+   FILE  *inStr;
+   FILE  *outStr;
+   Int32 n, i;
+   Bool  magicNumberOK;
+   Bool  cantGuess;
+   struct MY_STAT statBuf;
+
+   deleteOutputOnInterrupt = False;
+
+   if (name == NULL && srcMode != SM_I2O)
+      panic ( "uncompress: bad modes\n" );
+
+   cantGuess = False;
+   switch (srcMode) {
+      case SM_I2O: 
+         copyFileName ( inName, "(stdin)" );
+         copyFileName ( outName, "(stdout)" ); 
+         break;
+      case SM_F2F: 
+         copyFileName ( inName, name );
+         copyFileName ( outName, name );
+         for (i = 0; i < BZ_N_SUFFIX_PAIRS; i++)
+            if (mapSuffix(outName,zSuffix[i],unzSuffix[i]))
+               goto zzz; 
+         cantGuess = True;
+         strcat ( outName, ".out" );
+         break;
+      case SM_F2O: 
+         copyFileName ( inName, name );
+         copyFileName ( outName, "(stdout)" ); 
+         break;
+   }
+
+   zzz:
+   if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) {
+      if (noisy)
+      fprintf ( stderr, "%s: There are no files matching `%s'.\n",
+                progName, inName );
+      setExit(1);
+      return;
+   }
+   if ( srcMode != SM_I2O && !fileExists ( inName ) ) {
+      fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
+                progName, inName, strerror(errno) );
+      setExit(1);
+      return;
+   }
+   if ( srcMode == SM_F2F || srcMode == SM_F2O ) {
+      MY_STAT(inName, &statBuf);
+      if ( MY_S_ISDIR(statBuf.st_mode) ) {
+         fprintf( stderr,
+                  "%s: Input file %s is a directory.\n",
+                  progName,inName);
+         setExit(1);
+         return;
+      }
+   }
+   if ( srcMode == SM_F2F && !forceOverwrite && notAStandardFile ( inName )) {
+      if (noisy)
+      fprintf ( stderr, "%s: Input file %s is not a normal file.\n",
+                progName, inName );
+      setExit(1);
+      return;
+   }
+   if ( /* srcMode == SM_F2F implied && */ cantGuess ) {
+      if (noisy)
+      fprintf ( stderr, 
+                "%s: Can't guess original name for %s -- using %s\n",
+                progName, inName, outName );
+      /* just a warning, no return */
+   }   
+   if ( srcMode == SM_F2F && fileExists ( outName ) ) {
+      if (forceOverwrite) {
+	remove(outName);
+      } else {
+        fprintf ( stderr, "%s: Output file %s already exists.\n",
+                  progName, outName );
+        setExit(1);
+        return;
+      }
+   }
+   if ( srcMode == SM_F2F && !forceOverwrite &&
+        (n=countHardLinks ( inName ) ) > 0) {
+      fprintf ( stderr, "%s: Input file %s has %d other link%s.\n",
+                progName, inName, n, n > 1 ? "s" : "" );
+      setExit(1);
+      return;
+   }
+
+   if ( srcMode == SM_F2F ) {
+      /* Save the file's meta-info before we open it.  Doing it later
+         means we mess up the access times. */
+      saveInputFileMetaInfo ( inName );
+   }
+
+   switch ( srcMode ) {
+
+      case SM_I2O:
+         inStr = stdin;
+         outStr = stdout;
+         if ( isatty ( fileno ( stdin ) ) ) {
+            fprintf ( stderr,
+                      "%s: I won't read compressed data from a terminal.\n",
+                      progName );
+            fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
+                              progName, progName );
+            setExit(1);
+            return;
+         };
+         break;
+
+      case SM_F2O:
+         inStr = fopen ( inName, "rb" );
+         outStr = stdout;
+         if ( inStr == NULL ) {
+            fprintf ( stderr, "%s: Can't open input file %s:%s.\n",
+                      progName, inName, strerror(errno) );
+            if ( inStr != NULL ) fclose ( inStr );
+            setExit(1);
+            return;
+         };
+         break;
+
+      case SM_F2F:
+         inStr = fopen ( inName, "rb" );
+         outStr = fopen_output_safely ( outName, "wb" );
+         if ( outStr == NULL) {
+            fprintf ( stderr, "%s: Can't create output file %s: %s.\n",
+                      progName, outName, strerror(errno) );
+            if ( inStr != NULL ) fclose ( inStr );
+            setExit(1);
+            return;
+         }
+         if ( inStr == NULL ) {
+            fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
+                      progName, inName, strerror(errno) );
+            if ( outStr != NULL ) fclose ( outStr );
+            setExit(1);
+            return;
+         };
+         break;
+
+      default:
+         panic ( "uncompress: bad srcMode" );
+         break;
+   }
+
+   if (verbosity >= 1) {
+      fprintf ( stderr, "  %s: ", inName );
+      pad ( inName );
+      fflush ( stderr );
+   }
+
+   /*--- Now the input and output handles are sane.  Do the Biz. ---*/
+   outputHandleJustInCase = outStr;
+   deleteOutputOnInterrupt = True;
+   magicNumberOK = uncompressStream ( inStr, outStr );
+   outputHandleJustInCase = NULL;
+
+   /*--- If there was an I/O error, we won't get here. ---*/
+   if ( magicNumberOK ) {
+      if ( srcMode == SM_F2F ) {
+         applySavedMetaInfoToOutputFile ( outName );
+         deleteOutputOnInterrupt = False;
+         if ( !keepInputFiles ) {
+            IntNative retVal = remove ( inName );
+            ERROR_IF_NOT_ZERO ( retVal );
+         }
+      }
+   } else {
+      unzFailsExist = True;
+      deleteOutputOnInterrupt = False;
+      if ( srcMode == SM_F2F ) {
+         IntNative retVal = remove ( outName );
+         ERROR_IF_NOT_ZERO ( retVal );
+      }
+   }
+   deleteOutputOnInterrupt = False;
+
+   if ( magicNumberOK ) {
+      if (verbosity >= 1)
+         fprintf ( stderr, "done\n" );
+   } else {
+      setExit(2);
+      if (verbosity >= 1)
+         fprintf ( stderr, "not a bzip2 file.\n" ); else
+         fprintf ( stderr,
+                   "%s: %s is not a bzip2 file.\n",
+                   progName, inName );
+   }
+
+}
+
+
+/*---------------------------------------------*/
+static 
+void testf ( Char *name )
+{
+   FILE *inStr;
+   Bool allOK;
+   struct MY_STAT statBuf;
+
+   deleteOutputOnInterrupt = False;
+
+   if (name == NULL && srcMode != SM_I2O)
+      panic ( "testf: bad modes\n" );
+
+   copyFileName ( outName, "(none)" );
+   switch (srcMode) {
+      case SM_I2O: copyFileName ( inName, "(stdin)" ); break;
+      case SM_F2F: copyFileName ( inName, name ); break;
+      case SM_F2O: copyFileName ( inName, name ); break;
+   }
+
+   if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) {
+      if (noisy)
+      fprintf ( stderr, "%s: There are no files matching `%s'.\n",
+                progName, inName );
+      setExit(1);
+      return;
+   }
+   if ( srcMode != SM_I2O && !fileExists ( inName ) ) {
+      fprintf ( stderr, "%s: Can't open input %s: %s.\n",
+                progName, inName, strerror(errno) );
+      setExit(1);
+      return;
+   }
+   if ( srcMode != SM_I2O ) {
+      MY_STAT(inName, &statBuf);
+      if ( MY_S_ISDIR(statBuf.st_mode) ) {
+         fprintf( stderr,
+                  "%s: Input file %s is a directory.\n",
+                  progName,inName);
+         setExit(1);
+         return;
+      }
+   }
+
+   switch ( srcMode ) {
+
+      case SM_I2O:
+         if ( isatty ( fileno ( stdin ) ) ) {
+            fprintf ( stderr,
+                      "%s: I won't read compressed data from a terminal.\n",
+                      progName );
+            fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
+                              progName, progName );
+            setExit(1);
+            return;
+         };
+         inStr = stdin;
+         break;
+
+      case SM_F2O: case SM_F2F:
+         inStr = fopen ( inName, "rb" );
+         if ( inStr == NULL ) {
+            fprintf ( stderr, "%s: Can't open input file %s:%s.\n",
+                      progName, inName, strerror(errno) );
+            setExit(1);
+            return;
+         };
+         break;
+
+      default:
+         panic ( "testf: bad srcMode" );
+         break;
+   }
+
+   if (verbosity >= 1) {
+      fprintf ( stderr, "  %s: ", inName );
+      pad ( inName );
+      fflush ( stderr );
+   }
+
+   /*--- Now the input handle is sane.  Do the Biz. ---*/
+   outputHandleJustInCase = NULL;
+   allOK = testStream ( inStr );
+
+   if (allOK && verbosity >= 1) fprintf ( stderr, "ok\n" );
+   if (!allOK) testFailsExist = True;
+}
+
+
+/*---------------------------------------------*/
+static 
+void license ( void )
+{
+   fprintf ( stderr,
+
+    "bzip2, a block-sorting file compressor.  "
+    "Version %s.\n"
+    "   \n"
+    "   Copyright (C) 1996-2005 by Julian Seward.\n"
+    "   \n"
+    "   This program is free software; you can redistribute it and/or modify\n"
+    "   it under the terms set out in the LICENSE file, which is included\n"
+    "   in the bzip2-1.0 source distribution.\n"
+    "   \n"
+    "   This program is distributed in the hope that it will be useful,\n"
+    "   but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+    "   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
+    "   LICENSE file for more details.\n"
+    "   \n",
+    BZ2_bzlibVersion()
+   );
+}
+
+
+/*---------------------------------------------*/
+static 
+void usage ( Char *fullProgName )
+{
+   fprintf (
+      stderr,
+      "bzip2, a block-sorting file compressor.  "
+      "Version %s.\n"
+      "\n   usage: %s [flags and input files in any order]\n"
+      "\n"
+      "   -h --help           print this message\n"
+      "   -d --decompress     force decompression\n"
+      "   -z --compress       force compression\n"
+      "   -k --keep           keep (don't delete) input files\n"
+      "   -f --force          overwrite existing output files\n"
+      "   -t --test           test compressed file integrity\n"
+      "   -c --stdout         output to standard out\n"
+      "   -q --quiet          suppress noncritical error messages\n"
+      "   -v --verbose        be verbose (a 2nd -v gives more)\n"
+      "   -L --license        display software version & license\n"
+      "   -V --version        display software version & license\n"
+      "   -s --small          use less memory (at most 2500k)\n"
+      "   -1 .. -9            set block size to 100k .. 900k\n"
+      "   --fast              alias for -1\n"
+      "   --best              alias for -9\n"
+      "\n"
+      "   If invoked as `bzip2', default action is to compress.\n"
+      "              as `bunzip2',  default action is to decompress.\n"
+      "              as `bzcat', default action is to decompress to stdout.\n"
+      "\n"
+      "   If no file names are given, bzip2 compresses or decompresses\n"
+      "   from standard input to standard output.  You can combine\n"
+      "   short flags, so `-v -4' means the same as -v4 or -4v, &c.\n"
+#     if BZ_UNIX
+      "\n"
+#     endif
+      ,
+
+      BZ2_bzlibVersion(),
+      fullProgName
+   );
+}
+
+
+/*---------------------------------------------*/
+static 
+void redundant ( Char* flag )
+{
+   fprintf ( 
+      stderr, 
+      "%s: %s is redundant in versions 0.9.5 and above\n",
+      progName, flag );
+}
+
+
+/*---------------------------------------------*/
+/*--
+  All the garbage from here to main() is purely to
+  implement a linked list of command-line arguments,
+  into which main() copies argv[1 .. argc-1].
+
+  The purpose of this exercise is to facilitate 
+  the expansion of wildcard characters * and ? in 
+  filenames for OSs which don't know how to do it
+  themselves, like MSDOS, Windows 95 and NT.
+
+  The actual Dirty Work is done by the platform-
+  specific macro APPEND_FILESPEC.
+--*/
+
+typedef
+   struct zzzz {
+      Char        *name;
+      struct zzzz *link;
+   }
+   Cell;
+
+
+/*---------------------------------------------*/
+static 
+void *myMalloc ( Int32 n )
+{
+   void* p;
+
+   p = malloc ( (size_t)n );
+   if (p == NULL) outOfMemory ();
+   return p;
+}
+
+
+/*---------------------------------------------*/
+static 
+Cell *mkCell ( void )
+{
+   Cell *c;
+
+   c = (Cell*) myMalloc ( sizeof ( Cell ) );
+   c->name = NULL;
+   c->link = NULL;
+   return c;
+}
+
+
+/*---------------------------------------------*/
+static 
+Cell *snocString ( Cell *root, Char *name )
+{
+   if (root == NULL) {
+      Cell *tmp = mkCell();
+      tmp->name = (Char*) myMalloc ( 5 + strlen(name) );
+      strcpy ( tmp->name, name );
+      return tmp;
+   } else {
+      Cell *tmp = root;
+      while (tmp->link != NULL) tmp = tmp->link;
+      tmp->link = snocString ( tmp->link, name );
+      return root;
+   }
+}
+
+
+/*---------------------------------------------*/
+static 
+void addFlagsFromEnvVar ( Cell** argList, Char* varName ) 
+{
+   Int32 i, j, k;
+   Char *envbase, *p;
+
+   envbase = getenv(varName);
+   if (envbase != NULL) {
+      p = envbase;
+      i = 0;
+      while (True) {
+         if (p[i] == 0) break;
+         p += i;
+         i = 0;
+         while (isspace((Int32)(p[0]))) p++;
+         while (p[i] != 0 && !isspace((Int32)(p[i]))) i++;
+         if (i > 0) {
+            k = i; if (k > FILE_NAME_LEN-10) k = FILE_NAME_LEN-10;
+            for (j = 0; j < k; j++) tmpName[j] = p[j];
+            tmpName[k] = 0;
+            APPEND_FLAG(*argList, tmpName);
+         }
+      }
+   }
+}
+
+
+/*---------------------------------------------*/
+#define ISFLAG(s) (strcmp(aa->name, (s))==0)
+
+IntNative main ( IntNative argc, Char *argv[] )
+{
+   Int32  i, j;
+   Char   *tmp;
+   Cell   *argList;
+   Cell   *aa;
+   Bool   decode;
+
+   /*-- Be really really really paranoid :-) --*/
+   if (sizeof(Int32) != 4 || sizeof(UInt32) != 4  ||
+       sizeof(Int16) != 2 || sizeof(UInt16) != 2  ||
+       sizeof(Char)  != 1 || sizeof(UChar)  != 1)
+      configError();
+
+   /*-- Initialise --*/
+   outputHandleJustInCase  = NULL;
+   smallMode               = False;
+   keepInputFiles          = False;
+   forceOverwrite          = False;
+   noisy                   = True;
+   verbosity               = 0;
+   blockSize100k           = 9;
+   testFailsExist          = False;
+   unzFailsExist           = False;
+   numFileNames            = 0;
+   numFilesProcessed       = 0;
+   workFactor              = 30;
+   deleteOutputOnInterrupt = False;
+   exitValue               = 0;
+   i = j = 0; /* avoid bogus warning from egcs-1.1.X */
+
+   /*-- Set up signal handlers for mem access errors --*/
+   signal (SIGSEGV, mySIGSEGVorSIGBUScatcher);
+#  if BZ_UNIX
+#  ifndef __DJGPP__
+   signal (SIGBUS,  mySIGSEGVorSIGBUScatcher);
+#  endif
+#  endif
+
+   copyFileName ( inName,  "(none)" );
+   copyFileName ( outName, "(none)" );
+
+   copyFileName ( progNameReally, argv[0] );
+   progName = &progNameReally[0];
+   for (tmp = &progNameReally[0]; *tmp != '\0'; tmp++)
+      if (*tmp == PATH_SEP) progName = tmp + 1;
+
+
+   /*-- Copy flags from env var BZIP2, and 
+        expand filename wildcards in arg list.
+   --*/
+   argList = NULL;
+   addFlagsFromEnvVar ( &argList,  "BZIP2" );
+   addFlagsFromEnvVar ( &argList,  "BZIP" );
+   for (i = 1; i <= argc-1; i++)
+      APPEND_FILESPEC(argList, argv[i]);
+
+
+   /*-- Find the length of the longest filename --*/
+   longestFileName = 7;
+   numFileNames    = 0;
+   decode          = True;
+   for (aa = argList; aa != NULL; aa = aa->link) {
+      if (ISFLAG("--")) { decode = False; continue; }
+      if (aa->name[0] == '-' && decode) continue;
+      numFileNames++;
+      if (longestFileName < (Int32)strlen(aa->name) )
+         longestFileName = (Int32)strlen(aa->name);
+   }
+
+
+   /*-- Determine source modes; flag handling may change this too. --*/
+   if (numFileNames == 0)
+      srcMode = SM_I2O; else srcMode = SM_F2F;
+
+
+   /*-- Determine what to do (compress/uncompress/test/cat). --*/
+   /*-- Note that subsequent flag handling may change this. --*/
+   opMode = OM_Z;
+
+   if ( (strstr ( progName, "unzip" ) != 0) ||
+        (strstr ( progName, "UNZIP" ) != 0) )
+      opMode = OM_UNZ;
+
+   if ( (strstr ( progName, "z2cat" ) != 0) ||
+        (strstr ( progName, "Z2CAT" ) != 0) ||
+        (strstr ( progName, "zcat" ) != 0)  ||
+        (strstr ( progName, "ZCAT" ) != 0) )  {
+      opMode = OM_UNZ;
+      srcMode = (numFileNames == 0) ? SM_I2O : SM_F2O;
+   }
+
+
+   /*-- Look at the flags. --*/
+   for (aa = argList; aa != NULL; aa = aa->link) {
+      if (ISFLAG("--")) break;
+      if (aa->name[0] == '-' && aa->name[1] != '-') {
+         for (j = 1; aa->name[j] != '\0'; j++) {
+            switch (aa->name[j]) {
+               case 'c': srcMode          = SM_F2O; break;
+               case 'd': opMode           = OM_UNZ; break;
+               case 'z': opMode           = OM_Z; break;
+               case 'f': forceOverwrite   = True; break;
+               case 't': opMode           = OM_TEST; break;
+               case 'k': keepInputFiles   = True; break;
+               case 's': smallMode        = True; break;
+               case 'q': noisy            = False; break;
+               case '1': blockSize100k    = 1; break;
+               case '2': blockSize100k    = 2; break;
+               case '3': blockSize100k    = 3; break;
+               case '4': blockSize100k    = 4; break;
+               case '5': blockSize100k    = 5; break;
+               case '6': blockSize100k    = 6; break;
+               case '7': blockSize100k    = 7; break;
+               case '8': blockSize100k    = 8; break;
+               case '9': blockSize100k    = 9; break;
+               case 'V':
+               case 'L': license();            break;
+               case 'v': verbosity++; break;
+               case 'h': usage ( progName );
+                         exit ( 0 );
+                         break;
+               default:  fprintf ( stderr, "%s: Bad flag `%s'\n",
+                                   progName, aa->name );
+                         usage ( progName );
+                         exit ( 1 );
+                         break;
+            }
+         }
+      }
+   }
+   
+   /*-- And again ... --*/
+   for (aa = argList; aa != NULL; aa = aa->link) {
+      if (ISFLAG("--")) break;
+      if (ISFLAG("--stdout"))            srcMode          = SM_F2O;  else
+      if (ISFLAG("--decompress"))        opMode           = OM_UNZ;  else
+      if (ISFLAG("--compress"))          opMode           = OM_Z;    else
+      if (ISFLAG("--force"))             forceOverwrite   = True;    else
+      if (ISFLAG("--test"))              opMode           = OM_TEST; else
+      if (ISFLAG("--keep"))              keepInputFiles   = True;    else
+      if (ISFLAG("--small"))             smallMode        = True;    else
+      if (ISFLAG("--quiet"))             noisy            = False;   else
+      if (ISFLAG("--version"))           license();                  else
+      if (ISFLAG("--license"))           license();                  else
+      if (ISFLAG("--exponential"))       workFactor = 1;             else 
+      if (ISFLAG("--repetitive-best"))   redundant(aa->name);        else
+      if (ISFLAG("--repetitive-fast"))   redundant(aa->name);        else
+      if (ISFLAG("--fast"))              blockSize100k = 1;          else
+      if (ISFLAG("--best"))              blockSize100k = 9;          else
+      if (ISFLAG("--verbose"))           verbosity++;                else
+      if (ISFLAG("--help"))              { usage ( progName ); exit ( 0 ); }
+         else
+         if (strncmp ( aa->name, "--", 2) == 0) {
+            fprintf ( stderr, "%s: Bad flag `%s'\n", progName, aa->name );
+            usage ( progName );
+            exit ( 1 );
+         }
+   }
+
+   if (verbosity > 4) verbosity = 4;
+   if (opMode == OM_Z && smallMode && blockSize100k > 2) 
+      blockSize100k = 2;
+
+   if (opMode == OM_TEST && srcMode == SM_F2O) {
+      fprintf ( stderr, "%s: -c and -t cannot be used together.\n",
+                progName );
+      exit ( 1 );
+   }
+
+   if (srcMode == SM_F2O && numFileNames == 0)
+      srcMode = SM_I2O;
+
+   if (opMode != OM_Z) blockSize100k = 0;
+
+   if (srcMode == SM_F2F) {
+      signal (SIGINT,  mySignalCatcher);
+      signal (SIGTERM, mySignalCatcher);
+#     if BZ_UNIX
+      signal (SIGHUP,  mySignalCatcher);
+#     endif
+   }
+
+   if (opMode == OM_Z) {
+     if (srcMode == SM_I2O) {
+        compress ( NULL );
+     } else {
+        decode = True;
+        for (aa = argList; aa != NULL; aa = aa->link) {
+           if (ISFLAG("--")) { decode = False; continue; }
+           if (aa->name[0] == '-' && decode) continue;
+           numFilesProcessed++;
+           compress ( aa->name );
+        }
+     }
+   } 
+   else
+
+   if (opMode == OM_UNZ) {
+      unzFailsExist = False;
+      if (srcMode == SM_I2O) {
+         uncompress ( NULL );
+      } else {
+         decode = True;
+         for (aa = argList; aa != NULL; aa = aa->link) {
+            if (ISFLAG("--")) { decode = False; continue; }
+            if (aa->name[0] == '-' && decode) continue;
+            numFilesProcessed++;
+            uncompress ( aa->name );
+         }      
+      }
+      if (unzFailsExist) { 
+         setExit(2); 
+         exit(exitValue);
+      }
+   } 
+
+   else {
+      testFailsExist = False;
+      if (srcMode == SM_I2O) {
+         testf ( NULL );
+      } else {
+         decode = True;
+         for (aa = argList; aa != NULL; aa = aa->link) {
+	    if (ISFLAG("--")) { decode = False; continue; }
+            if (aa->name[0] == '-' && decode) continue;
+            numFilesProcessed++;
+            testf ( aa->name );
+	 }
+      }
+      if (testFailsExist && noisy) {
+         fprintf ( stderr,
+           "\n"
+           "You can use the `bzip2recover' program to attempt to recover\n"
+           "data from undamaged sections of corrupted files.\n\n"
+         );
+         setExit(2);
+         exit(exitValue);
+      }
+   }
+
+   /* Free the argument list memory to mollify leak detectors 
+      (eg) Purify, Checker.  Serves no other useful purpose.
+   */
+   aa = argList;
+   while (aa != NULL) {
+      Cell* aa2 = aa->link;
+      if (aa->name != NULL) free(aa->name);
+      free(aa);
+      aa = aa2;
+   }
+
+   return exitValue;
+}
+
+
+/*-----------------------------------------------------------*/
+/*--- end                                         bzip2.c ---*/
+/*-----------------------------------------------------------*/
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/bzip2.txt b/contrib/vmap_extractor_v2/stormlib/bzip2/bzip2.txt
new file mode 100644
index 00000000000..bf895b6cb8a
--- /dev/null
+++ b/contrib/vmap_extractor_v2/stormlib/bzip2/bzip2.txt
@@ -0,0 +1,391 @@
+
+NAME
+       bzip2, bunzip2 - a block-sorting file compressor, v1.0.3
+       bzcat - decompresses files to stdout
+       bzip2recover - recovers data from damaged bzip2 files
+
+
+SYNOPSIS
+       bzip2 [ -cdfkqstvzVL123456789 ] [ filenames ...  ]
+       bunzip2 [ -fkvsVL ] [ filenames ...  ]
+       bzcat [ -s ] [ filenames ...  ]
+       bzip2recover filename
+
+
+DESCRIPTION
+       bzip2  compresses  files  using  the Burrows-Wheeler block
+       sorting text compression algorithm,  and  Huffman  coding.
+       Compression  is  generally  considerably  better than that
+       achieved by more conventional LZ77/LZ78-based compressors,
+       and  approaches  the performance of the PPM family of sta-
+       tistical compressors.
+
+       The command-line options are deliberately very similar  to
+       those of GNU gzip, but they are not identical.
+
+       bzip2  expects  a list of file names to accompany the com-
+       mand-line flags.  Each file is replaced  by  a  compressed
+       version  of  itself,  with  the  name "original_name.bz2".
+       Each compressed file has the same modification date,  per-
+       missions, and, when possible, ownership as the correspond-
+       ing original, so that these properties  can  be  correctly
+       restored  at  decompression  time.   File name handling is
+       naive in the sense that there is no mechanism for preserv-
+       ing  original file names, permissions, ownerships or dates
+       in filesystems which lack these concepts, or have  serious
+       file name length restrictions, such as MS-DOS.
+
+       bzip2  and  bunzip2 will by default not overwrite existing
+       files.  If you want this to happen, specify the -f flag.
+
+       If no file names  are  specified,  bzip2  compresses  from
+       standard  input  to  standard output.  In this case, bzip2
+       will decline to write compressed output to a terminal,  as
+       this  would  be  entirely  incomprehensible  and therefore
+       pointless.
+
+       bunzip2 (or bzip2 -d) decompresses  all  specified  files.
+       Files which were not created by bzip2 will be detected and
+       ignored, and a warning issued.  bzip2  attempts  to  guess
+       the  filename  for  the decompressed file from that of the
+       compressed file as follows:
+
+              filename.bz2    becomes   filename
+              filename.bz     becomes   filename
+              filename.tbz2   becomes   filename.tar
+              filename.tbz    becomes   filename.tar
+              anyothername    becomes   anyothername.out
+
+       If the file does not end in one of the recognised endings,
+       .bz2,  .bz,  .tbz2 or .tbz, bzip2 complains that it cannot
+       guess the name of the original file, and uses the original
+       name with .out appended.
+
+       As  with compression, supplying no filenames causes decom-
+       pression from standard input to standard output.
+
+       bunzip2 will correctly decompress a file which is the con-
+       catenation of two or more compressed files.  The result is
+       the concatenation of the corresponding uncompressed files.
+       Integrity testing (-t) of concatenated compressed files is
+       also supported.
+
+       You can also compress or decompress files to the  standard
+       output  by giving the -c flag.  Multiple files may be com-
+       pressed and decompressed like this.  The resulting outputs
+       are  fed  sequentially to stdout.  Compression of multiple
+       files in this manner generates a stream containing  multi-
+       ple compressed file representations.  Such a stream can be
+       decompressed correctly only  by  bzip2  version  0.9.0  or
+       later.   Earlier  versions of bzip2 will stop after decom-
+       pressing the first file in the stream.
+
+       bzcat (or bzip2 -dc) decompresses all specified  files  to
+       the standard output.
+
+       bzip2  will  read arguments from the environment variables
+       BZIP2 and BZIP, in  that  order,  and  will  process  them
+       before  any  arguments  read  from the command line.  This
+       gives a convenient way to supply default arguments.
+
+       Compression is always performed, even  if  the  compressed
+       file  is slightly larger than the original.  Files of less
+       than about one hundred bytes tend to get larger, since the
+       compression  mechanism  has  a  constant  overhead  in the
+       region of 50 bytes.  Random data (including the output  of
+       most  file  compressors)  is  coded at about 8.05 bits per
+       byte, giving an expansion of around 0.5%.
+
+       As a self-check for your  protection,  bzip2  uses  32-bit
+       CRCs  to make sure that the decompressed version of a file
+       is identical to the original.  This guards against corrup-
+       tion  of  the compressed data, and against undetected bugs
+       in bzip2 (hopefully very unlikely).  The chances  of  data
+       corruption  going  undetected  is  microscopic,  about one
+       chance in four billion for each file processed.  Be aware,
+       though,  that  the  check occurs upon decompression, so it
+       can only tell you that something is wrong.  It can't  help
+       you  recover  the original uncompressed data.  You can use
+       bzip2recover to try to recover data from damaged files.
+
+       Return values: 0 for a normal exit,  1  for  environmental
+       problems  (file not found, invalid flags, I/O errors, &c),
+       2 to indicate a corrupt compressed file, 3 for an internal
+       consistency error (eg, bug) which caused bzip2 to panic.
+
+
+OPTIONS
+       -c --stdout
+              Compress or decompress to standard output.
+
+       -d --decompress
+              Force  decompression.  bzip2, bunzip2 and bzcat are
+              really the same program,  and  the  decision  about
+              what  actions to take is done on the basis of which
+              name is used.  This flag overrides that  mechanism,
+              and forces bzip2 to decompress.
+
+       -z --compress
+              The   complement   to   -d:   forces   compression,
+              regardless of the invocation name.
+
+       -t --test
+              Check integrity of the specified file(s), but don't
+              decompress  them.   This  really  performs  a trial
+              decompression and throws away the result.
+
+       -f --force
+              Force overwrite of output files.   Normally,  bzip2
+              will  not  overwrite  existing  output files.  Also
+              forces bzip2 to break hard links to files, which it
+              otherwise wouldn't do.
+
+              bzip2  normally  declines to decompress files which
+              don't have the  correct  magic  header  bytes.   If
+              forced  (-f),  however,  it  will  pass  such files
+              through unmodified.  This is how GNU gzip  behaves.
+
+       -k --keep
+              Keep  (don't delete) input files during compression
+              or decompression.
+
+       -s --small
+              Reduce memory usage, for compression, decompression
+              and  testing.   Files  are  decompressed and tested
+              using a modified algorithm which only requires  2.5
+              bytes  per  block byte.  This means any file can be
+              decompressed in 2300k of memory,  albeit  at  about
+              half the normal speed.
+
+              During  compression,  -s  selects  a  block size of
+              200k, which limits memory use to  around  the  same
+              figure,  at  the expense of your compression ratio.
+              In short, if your  machine  is  low  on  memory  (8
+              megabytes  or  less),  use  -s for everything.  See
+              MEMORY MANAGEMENT below.
+
+       -q --quiet
+              Suppress non-essential warning messages.   Messages
+              pertaining  to I/O errors and other critical events
+              will not be suppressed.
+
+       -v --verbose
+              Verbose mode -- show the compression ratio for each
+              file  processed.   Further  -v's  increase the ver-
+              bosity level, spewing out lots of information which
+              is primarily of interest for diagnostic purposes.
+
+       -L --license -V --version
+              Display  the  software  version,  license terms and
+              conditions.
+
+       -1 (or --fast) to -9 (or --best)
+              Set the block size to 100 k, 200 k ..  900  k  when
+              compressing.   Has  no  effect  when decompressing.
+              See MEMORY MANAGEMENT below.  The --fast and --best
+              aliases  are  primarily for GNU gzip compatibility.
+              In particular, --fast doesn't make things  signifi-
+              cantly  faster.   And  --best  merely  selects  the
+              default behaviour.
+
+       --     Treats all subsequent arguments as file names, even
+              if they start with a dash.  This is so you can han-
+              dle files with names beginning  with  a  dash,  for
+              example: bzip2 -- -myfilename.
+
+       --repetitive-fast --repetitive-best
+              These  flags  are  redundant  in versions 0.9.5 and
+              above.  They provided some coarse control over  the
+              behaviour  of the sorting algorithm in earlier ver-
+              sions, which was sometimes useful.  0.9.5 and above
+              have  an  improved  algorithm  which  renders these
+              flags irrelevant.
+
+
+MEMORY MANAGEMENT
+       bzip2 compresses large files in blocks.   The  block  size
+       affects  both  the  compression  ratio  achieved,  and the
+       amount of memory needed for compression and decompression.
+       The  flags  -1  through  -9  specify  the block size to be
+       100,000 bytes through 900,000 bytes (the default)  respec-
+       tively.   At  decompression  time, the block size used for
+       compression is read from  the  header  of  the  compressed
+       file, and bunzip2 then allocates itself just enough memory
+       to decompress the file.  Since block sizes are  stored  in
+       compressed  files,  it follows that the flags -1 to -9 are
+       irrelevant to and so ignored during decompression.
+
+       Compression and decompression requirements, in bytes,  can
+       be estimated as:
+
+              Compression:   400k + ( 8 x block size )
+
+              Decompression: 100k + ( 4 x block size ), or
+                             100k + ( 2.5 x block size )
+
+       Larger  block  sizes  give  rapidly  diminishing  marginal
+       returns.  Most of the compression comes from the first two
+       or  three hundred k of block size, a fact worth bearing in
+       mind when using bzip2  on  small  machines.   It  is  also
+       important  to  appreciate  that  the  decompression memory
+       requirement is set at compression time by  the  choice  of
+       block size.
+
+       For  files  compressed  with  the default 900k block size,
+       bunzip2 will require about 3700 kbytes to decompress.   To
+       support decompression of any file on a 4 megabyte machine,
+       bunzip2 has an option to  decompress  using  approximately
+       half this amount of memory, about 2300 kbytes.  Decompres-
+       sion speed is also halved, so you should use  this  option
+       only where necessary.  The relevant flag is -s.
+
+       In general, try and use the largest block size memory con-
+       straints  allow,  since  that  maximises  the  compression
+       achieved.   Compression and decompression speed are virtu-
+       ally unaffected by block size.
+
+       Another significant point applies to files which fit in  a
+       single  block  --  that  means  most files you'd encounter
+       using a large block  size.   The  amount  of  real  memory
+       touched is proportional to the size of the file, since the
+       file is smaller than a block.  For example, compressing  a
+       file  20,000  bytes  long  with the flag -9 will cause the
+       compressor to allocate around 7600k of  memory,  but  only
+       touch 400k + 20000 * 8 = 560 kbytes of it.  Similarly, the
+       decompressor will allocate 3700k but  only  touch  100k  +
+       20000 * 4 = 180 kbytes.
+
+       Here  is a table which summarises the maximum memory usage
+       for different block sizes.  Also  recorded  is  the  total
+       compressed  size for 14 files of the Calgary Text Compres-
+       sion Corpus totalling 3,141,622 bytes.  This column  gives
+       some  feel  for  how  compression  varies with block size.
+       These figures tend to understate the advantage  of  larger
+       block  sizes  for  larger files, since the Corpus is domi-
+       nated by smaller files.
+
+                  Compress   Decompress   Decompress   Corpus
+           Flag     usage      usage       -s usage     Size
+
+            -1      1200k       500k         350k      914704
+            -2      2000k       900k         600k      877703
+            -3      2800k      1300k         850k      860338
+            -4      3600k      1700k        1100k      846899
+            -5      4400k      2100k        1350k      845160
+            -6      5200k      2500k        1600k      838626
+            -7      6100k      2900k        1850k      834096
+            -8      6800k      3300k        2100k      828642
+            -9      7600k      3700k        2350k      828642
+
+
+RECOVERING DATA FROM DAMAGED FILES
+       bzip2 compresses files in blocks, usually 900kbytes  long.
+       Each block is handled independently.  If a media or trans-
+       mission error causes a multi-block  .bz2  file  to  become
+       damaged,  it  may  be  possible  to  recover data from the
+       undamaged blocks in the file.
+
+       The compressed representation of each block  is  delimited
+       by  a  48-bit pattern, which makes it possible to find the
+       block boundaries with reasonable  certainty.   Each  block
+       also  carries its own 32-bit CRC, so damaged blocks can be
+       distinguished from undamaged ones.
+
+       bzip2recover is a  simple  program  whose  purpose  is  to
+       search  for blocks in .bz2 files, and write each block out
+       into its own .bz2 file.  You can then use bzip2 -t to test
+       the integrity of the resulting files, and decompress those
+       which are undamaged.
+
+       bzip2recover takes a single argument, the name of the dam-
+       aged    file,    and    writes    a    number   of   files
+       "rec00001file.bz2",  "rec00002file.bz2",  etc,  containing
+       the   extracted   blocks.   The   output   filenames   are
+       designed  so  that the use of wildcards in subsequent pro-
+       cessing  -- for example, "bzip2 -dc  rec*file.bz2 > recov-
+       ered_data" -- processes the files in the correct order.
+
+       bzip2recover should be of most use dealing with large .bz2
+       files,  as  these will contain many blocks.  It is clearly
+       futile to use it on damaged single-block  files,  since  a
+       damaged  block  cannot  be recovered.  If you wish to min-
+       imise any potential data loss through media  or  transmis-
+       sion errors, you might consider compressing with a smaller
+       block size.
+
+
+PERFORMANCE NOTES
+       The sorting phase of compression gathers together  similar
+       strings  in  the  file.  Because of this, files containing
+       very long runs of  repeated  symbols,  like  "aabaabaabaab
+       ..."   (repeated  several hundred times) may compress more
+       slowly than normal.  Versions 0.9.5 and  above  fare  much
+       better  than previous versions in this respect.  The ratio
+       between worst-case and average-case compression time is in
+       the  region  of  10:1.  For previous versions, this figure
+       was more like 100:1.  You can use the -vvvv option to mon-
+       itor progress in great detail, if you want.
+
+       Decompression speed is unaffected by these phenomena.
+
+       bzip2  usually  allocates  several  megabytes of memory to
+       operate in, and then charges all over it in a fairly  ran-
+       dom  fashion.   This means that performance, both for com-
+       pressing and decompressing, is largely determined  by  the
+       speed  at  which  your  machine  can service cache misses.
+       Because of this, small changes to the code to  reduce  the
+       miss  rate  have  been observed to give disproportionately
+       large performance improvements.  I imagine bzip2 will per-
+       form best on machines with very large caches.
+
+
+CAVEATS
+       I/O  error  messages  are not as helpful as they could be.
+       bzip2 tries hard to detect I/O errors  and  exit  cleanly,
+       but  the  details  of  what  the problem is sometimes seem
+       rather misleading.
+
+       This manual page pertains to version 1.0.3 of bzip2.  Com-
+       pressed  data created by this version is entirely forwards
+       and  backwards  compatible  with   the   previous   public
+       releases,  versions 0.1pl2, 0.9.0, 0.9.5, 1.0.0, 1.0.1 and
+       1.0.2, but with the following exception: 0.9.0  and  above
+       can  correctly decompress multiple concatenated compressed
+       files.  0.1pl2 cannot do this; it will stop  after  decom-
+       pressing just the first file in the stream.
+
+       bzip2recover  versions prior to 1.0.2 used 32-bit integers
+       to represent bit positions in compressed  files,  so  they
+       could  not handle compressed files more than 512 megabytes
+       long.  Versions 1.0.2 and above use 64-bit  ints  on  some
+       platforms  which  support them (GNU supported targets, and
+       Windows).  To establish whether or  not  bzip2recover  was
+       built  with  such  a limitation, run it without arguments.
+       In any event you can build yourself an  unlimited  version
+       if  you  can  recompile  it  with MaybeUInt64 set to be an
+       unsigned 64-bit integer.
+
+
+AUTHOR
+       Julian Seward, jsewardbzip.org.
+
+       http://www.bzip.org
+
+       The ideas embodied in bzip2 are due to (at least) the fol-
+       lowing  people: Michael Burrows and David Wheeler (for the
+       block sorting transformation), David Wheeler  (again,  for
+       the Huffman coder), Peter Fenwick (for the structured cod-
+       ing model in the original bzip, and many refinements), and
+       Alistair  Moffat,  Radford  Neal  and  Ian Witten (for the
+       arithmetic  coder  in  the  original  bzip).   I  am  much
+       indebted for their help, support and advice.  See the man-
+       ual in the source distribution for pointers to sources  of
+       documentation.  Christian von Roques encouraged me to look
+       for faster sorting algorithms, so as to speed up  compres-
+       sion.  Bela Lubkin encouraged me to improve the worst-case
+       compression performance.  Donna Robinson XMLised the docu-
+       mentation.   The bz* scripts are derived from those of GNU
+       gzip.  Many people sent patches, helped  with  portability
+       problems,  lent  machines,  gave advice and were generally
+       helpful.
+
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/bzip2recover.c b/contrib/vmap_extractor_v2/stormlib/bzip2/bzip2recover.c
new file mode 100644
index 00000000000..5cd405dd4cb
--- /dev/null
+++ b/contrib/vmap_extractor_v2/stormlib/bzip2/bzip2recover.c
@@ -0,0 +1,546 @@
+
+/*-----------------------------------------------------------*/
+/*--- Block recoverer program for bzip2                   ---*/
+/*---                                      bzip2recover.c ---*/
+/*-----------------------------------------------------------*/
+
+/*--
+  This program is bzip2recover, a program to attempt data 
+  salvage from damaged files created by the accompanying
+  bzip2-1.0.3 program.
+
+  Copyright (C) 1996-2005 Julian R Seward.  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+  2. The origin of this software must not be misrepresented; you must 
+     not claim that you wrote the original software.  If you use this 
+     software in a product, an acknowledgment in the product 
+     documentation would be appreciated but is not required.
+
+  3. Altered source versions must be plainly marked as such, and must
+     not be misrepresented as being the original software.
+
+  4. The name of the author may not be used to endorse or promote 
+     products derived from this software without specific prior written 
+     permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  Julian Seward, Cambridge, UK.
+  jseward@bzip.org
+  bzip2/libbzip2 version 1.0.3 of 15 February 2005
+--*/
+
+/*--
+  This program is a complete hack and should be rewritten
+  properly.  It isn't very complicated.
+--*/
+
+#include 
+#include 
+#include 
+#include 
+
+
+/* This program records bit locations in the file to be recovered.
+   That means that if 64-bit ints are not supported, we will not
+   be able to recover .bz2 files over 512MB (2^32 bits) long.
+   On GNU supported platforms, we take advantage of the 64-bit
+   int support to circumvent this problem.  Ditto MSVC.
+
+   This change occurred in version 1.0.2; all prior versions have
+   the 512MB limitation.
+*/
+#ifdef __GNUC__
+   typedef  unsigned long long int  MaybeUInt64;
+#  define MaybeUInt64_FMT "%Lu"
+#else
+#ifdef _MSC_VER
+   typedef  unsigned __int64  MaybeUInt64;
+#  define MaybeUInt64_FMT "%I64u"
+#else
+   typedef  unsigned int   MaybeUInt64;
+#  define MaybeUInt64_FMT "%u"
+#endif
+#endif
+
+typedef  unsigned int   UInt32;
+typedef  int            Int32;
+typedef  unsigned char  UChar;
+typedef  char           Char;
+typedef  unsigned char  Bool;
+#define True    ((Bool)1)
+#define False   ((Bool)0)
+
+
+#define BZ_MAX_FILENAME 2000
+
+Char inFileName[BZ_MAX_FILENAME];
+Char outFileName[BZ_MAX_FILENAME];
+Char progName[BZ_MAX_FILENAME];
+
+MaybeUInt64 bytesOut = 0;
+MaybeUInt64 bytesIn  = 0;
+
+
+/*---------------------------------------------------*/
+/*--- Header bytes                                ---*/
+/*---------------------------------------------------*/
+
+#define BZ_HDR_B 0x42                         /* 'B' */
+#define BZ_HDR_Z 0x5a                         /* 'Z' */
+#define BZ_HDR_h 0x68                         /* 'h' */
+#define BZ_HDR_0 0x30                         /* '0' */
+ 
+
+/*---------------------------------------------------*/
+/*--- I/O errors                                  ---*/
+/*---------------------------------------------------*/
+
+/*---------------------------------------------*/
+void readError ( void )
+{
+   fprintf ( stderr,
+             "%s: I/O error reading `%s', possible reason follows.\n",
+            progName, inFileName );
+   perror ( progName );
+   fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n",
+             progName );
+   exit ( 1 );
+}
+
+
+/*---------------------------------------------*/
+void writeError ( void )
+{
+   fprintf ( stderr,
+             "%s: I/O error reading `%s', possible reason follows.\n",
+            progName, inFileName );
+   perror ( progName );
+   fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n",
+             progName );
+   exit ( 1 );
+}
+
+
+/*---------------------------------------------*/
+void mallocFail ( Int32 n )
+{
+   fprintf ( stderr,
+             "%s: malloc failed on request for %d bytes.\n",
+            progName, n );
+   fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n",
+             progName );
+   exit ( 1 );
+}
+
+
+/*---------------------------------------------*/
+void tooManyBlocks ( Int32 max_handled_blocks )
+{
+   fprintf ( stderr,
+             "%s: `%s' appears to contain more than %d blocks\n",
+            progName, inFileName, max_handled_blocks );
+   fprintf ( stderr,
+             "%s: and cannot be handled.  To fix, increase\n",
+             progName );
+   fprintf ( stderr, 
+             "%s: BZ_MAX_HANDLED_BLOCKS in bzip2recover.c, and recompile.\n",
+             progName );
+   exit ( 1 );
+}
+
+
+
+/*---------------------------------------------------*/
+/*--- Bit stream I/O                              ---*/
+/*---------------------------------------------------*/
+
+typedef
+   struct {
+      FILE*  handle;
+      Int32  buffer;
+      Int32  buffLive;
+      Char   mode;
+   }
+   BitStream;
+
+
+/*---------------------------------------------*/
+BitStream* bsOpenReadStream ( FILE* stream )
+{
+   BitStream *bs = malloc ( sizeof(BitStream) );
+   if (bs == NULL) mallocFail ( sizeof(BitStream) );
+   bs->handle = stream;
+   bs->buffer = 0;
+   bs->buffLive = 0;
+   bs->mode = 'r';
+   return bs;
+}
+
+
+/*---------------------------------------------*/
+BitStream* bsOpenWriteStream ( FILE* stream )
+{
+   BitStream *bs = malloc ( sizeof(BitStream) );
+   if (bs == NULL) mallocFail ( sizeof(BitStream) );
+   bs->handle = stream;
+   bs->buffer = 0;
+   bs->buffLive = 0;
+   bs->mode = 'w';
+   return bs;
+}
+
+
+/*---------------------------------------------*/
+void bsPutBit ( BitStream* bs, Int32 bit )
+{
+   if (bs->buffLive == 8) {
+      Int32 retVal = putc ( (UChar) bs->buffer, bs->handle );
+      if (retVal == EOF) writeError();
+      bytesOut++;
+      bs->buffLive = 1;
+      bs->buffer = bit & 0x1;
+   } else {
+      bs->buffer = ( (bs->buffer << 1) | (bit & 0x1) );
+      bs->buffLive++;
+   };
+}
+
+
+/*---------------------------------------------*/
+/*--
+   Returns 0 or 1, or 2 to indicate EOF.
+--*/
+Int32 bsGetBit ( BitStream* bs )
+{
+   if (bs->buffLive > 0) {
+      bs->buffLive --;
+      return ( ((bs->buffer) >> (bs->buffLive)) & 0x1 );
+   } else {
+      Int32 retVal = getc ( bs->handle );
+      if ( retVal == EOF ) {
+         if (errno != 0) readError();
+         return 2;
+      }
+      bs->buffLive = 7;
+      bs->buffer = retVal;
+      return ( ((bs->buffer) >> 7) & 0x1 );
+   }
+}
+
+
+/*---------------------------------------------*/
+void bsClose ( BitStream* bs )
+{
+   Int32 retVal;
+
+   if ( bs->mode == 'w' ) {
+      while ( bs->buffLive < 8 ) {
+         bs->buffLive++;
+         bs->buffer <<= 1;
+      };
+      retVal = putc ( (UChar) (bs->buffer), bs->handle );
+      if (retVal == EOF) writeError();
+      bytesOut++;
+      retVal = fflush ( bs->handle );
+      if (retVal == EOF) writeError();
+   }
+   retVal = fclose ( bs->handle );
+   if (retVal == EOF) {
+      if (bs->mode == 'w') writeError(); else readError();
+   }
+   free ( bs );
+}
+
+
+/*---------------------------------------------*/
+void bsPutUChar ( BitStream* bs, UChar c )
+{
+   Int32 i;
+   for (i = 7; i >= 0; i--)
+      bsPutBit ( bs, (((UInt32) c) >> i) & 0x1 );
+}
+
+
+/*---------------------------------------------*/
+void bsPutUInt32 ( BitStream* bs, UInt32 c )
+{
+   Int32 i;
+
+   for (i = 31; i >= 0; i--)
+      bsPutBit ( bs, (c >> i) & 0x1 );
+}
+
+
+/*---------------------------------------------*/
+Bool endsInBz2 ( Char* name )
+{
+   Int32 n = strlen ( name );
+   if (n <= 4) return False;
+   return
+      (name[n-4] == '.' &&
+       name[n-3] == 'b' &&
+       name[n-2] == 'z' &&
+       name[n-1] == '2');
+}
+
+
+/*---------------------------------------------------*/
+/*---                                             ---*/
+/*---------------------------------------------------*/
+
+/* This logic isn't really right when it comes to Cygwin. */
+#ifdef _WIN32
+#  define  BZ_SPLIT_SYM  '\\'  /* path splitter on Windows platform */
+#else
+#  define  BZ_SPLIT_SYM  '/'   /* path splitter on Unix platform */
+#endif
+
+#define BLOCK_HEADER_HI  0x00003141UL
+#define BLOCK_HEADER_LO  0x59265359UL
+
+#define BLOCK_ENDMARK_HI 0x00001772UL
+#define BLOCK_ENDMARK_LO 0x45385090UL
+
+/* Increase if necessary.  However, a .bz2 file with > 50000 blocks
+   would have an uncompressed size of at least 40GB, so the chances
+   are low you'll need to up this.
+*/
+#define BZ_MAX_HANDLED_BLOCKS 50000
+
+MaybeUInt64 bStart [BZ_MAX_HANDLED_BLOCKS];
+MaybeUInt64 bEnd   [BZ_MAX_HANDLED_BLOCKS];
+MaybeUInt64 rbStart[BZ_MAX_HANDLED_BLOCKS];
+MaybeUInt64 rbEnd  [BZ_MAX_HANDLED_BLOCKS];
+
+Int32 main ( Int32 argc, Char** argv )
+{
+   FILE*       inFile;
+   FILE*       outFile;
+   BitStream*  bsIn, *bsWr;
+   Int32       b, wrBlock, currBlock, rbCtr;
+   MaybeUInt64 bitsRead;
+
+   UInt32      buffHi, buffLo, blockCRC;
+   Char*       p;
+
+   strcpy ( progName, argv[0] );
+   inFileName[0] = outFileName[0] = 0;
+
+   fprintf ( stderr, 
+             "bzip2recover 1.0.3: extracts blocks from damaged .bz2 files.\n" );
+
+   if (argc != 2) {
+      fprintf ( stderr, "%s: usage is `%s damaged_file_name'.\n",
+                        progName, progName );
+      switch (sizeof(MaybeUInt64)) {
+         case 8:
+            fprintf(stderr, 
+                    "\trestrictions on size of recovered file: None\n");
+            break;
+         case 4:
+            fprintf(stderr, 
+                    "\trestrictions on size of recovered file: 512 MB\n");
+            fprintf(stderr, 
+                    "\tto circumvent, recompile with MaybeUInt64 as an\n"
+                    "\tunsigned 64-bit int.\n");
+            break;
+         default:
+            fprintf(stderr, 
+                    "\tsizeof(MaybeUInt64) is not 4 or 8 -- "
+                    "configuration error.\n");
+            break;
+      }
+      exit(1);
+   }
+
+   if (strlen(argv[1]) >= BZ_MAX_FILENAME-20) {
+      fprintf ( stderr, 
+                "%s: supplied filename is suspiciously (>= %d chars) long.  Bye!\n",
+                progName, (int)strlen(argv[1]) );
+      exit(1);
+   }
+
+   strcpy ( inFileName, argv[1] );
+
+   inFile = fopen ( inFileName, "rb" );
+   if (inFile == NULL) {
+      fprintf ( stderr, "%s: can't read `%s'\n", progName, inFileName );
+      exit(1);
+   }
+
+   bsIn = bsOpenReadStream ( inFile );
+   fprintf ( stderr, "%s: searching for block boundaries ...\n", progName );
+
+   bitsRead = 0;
+   buffHi = buffLo = 0;
+   currBlock = 0;
+   bStart[currBlock] = 0;
+
+   rbCtr = 0;
+
+   while (True) {
+      b = bsGetBit ( bsIn );
+      bitsRead++;
+      if (b == 2) {
+         if (bitsRead >= bStart[currBlock] &&
+            (bitsRead - bStart[currBlock]) >= 40) {
+            bEnd[currBlock] = bitsRead-1;
+            if (currBlock > 0)
+               fprintf ( stderr, "   block %d runs from " MaybeUInt64_FMT 
+                                 " to " MaybeUInt64_FMT " (incomplete)\n",
+                         currBlock,  bStart[currBlock], bEnd[currBlock] );
+         } else
+            currBlock--;
+         break;
+      }
+      buffHi = (buffHi << 1) | (buffLo >> 31);
+      buffLo = (buffLo << 1) | (b & 1);
+      if ( ( (buffHi & 0x0000ffff) == BLOCK_HEADER_HI 
+             && buffLo == BLOCK_HEADER_LO)
+           || 
+           ( (buffHi & 0x0000ffff) == BLOCK_ENDMARK_HI 
+             && buffLo == BLOCK_ENDMARK_LO)
+         ) {
+         if (bitsRead > 49) {
+            bEnd[currBlock] = bitsRead-49;
+         } else {
+            bEnd[currBlock] = 0;
+         }
+         if (currBlock > 0 &&
+	     (bEnd[currBlock] - bStart[currBlock]) >= 130) {
+            fprintf ( stderr, "   block %d runs from " MaybeUInt64_FMT 
+                              " to " MaybeUInt64_FMT "\n",
+                      rbCtr+1,  bStart[currBlock], bEnd[currBlock] );
+            rbStart[rbCtr] = bStart[currBlock];
+            rbEnd[rbCtr] = bEnd[currBlock];
+            rbCtr++;
+         }
+         if (currBlock >= BZ_MAX_HANDLED_BLOCKS)
+            tooManyBlocks(BZ_MAX_HANDLED_BLOCKS);
+         currBlock++;
+
+         bStart[currBlock] = bitsRead;
+      }
+   }
+
+   bsClose ( bsIn );
+
+   /*-- identified blocks run from 1 to rbCtr inclusive. --*/
+
+   if (rbCtr < 1) {
+      fprintf ( stderr,
+                "%s: sorry, I couldn't find any block boundaries.\n",
+                progName );
+      exit(1);
+   };
+
+   fprintf ( stderr, "%s: splitting into blocks\n", progName );
+
+   inFile = fopen ( inFileName, "rb" );
+   if (inFile == NULL) {
+      fprintf ( stderr, "%s: can't open `%s'\n", progName, inFileName );
+      exit(1);
+   }
+   bsIn = bsOpenReadStream ( inFile );
+
+   /*-- placate gcc's dataflow analyser --*/
+   blockCRC = 0; bsWr = 0;
+
+   bitsRead = 0;
+   outFile = NULL;
+   wrBlock = 0;
+   while (True) {
+      b = bsGetBit(bsIn);
+      if (b == 2) break;
+      buffHi = (buffHi << 1) | (buffLo >> 31);
+      buffLo = (buffLo << 1) | (b & 1);
+      if (bitsRead == 47+rbStart[wrBlock]) 
+         blockCRC = (buffHi << 16) | (buffLo >> 16);
+
+      if (outFile != NULL && bitsRead >= rbStart[wrBlock]
+                          && bitsRead <= rbEnd[wrBlock]) {
+         bsPutBit ( bsWr, b );
+      }
+
+      bitsRead++;
+
+      if (bitsRead == rbEnd[wrBlock]+1) {
+         if (outFile != NULL) {
+            bsPutUChar ( bsWr, 0x17 ); bsPutUChar ( bsWr, 0x72 );
+            bsPutUChar ( bsWr, 0x45 ); bsPutUChar ( bsWr, 0x38 );
+            bsPutUChar ( bsWr, 0x50 ); bsPutUChar ( bsWr, 0x90 );
+            bsPutUInt32 ( bsWr, blockCRC );
+            bsClose ( bsWr );
+         }
+         if (wrBlock >= rbCtr) break;
+         wrBlock++;
+      } else
+      if (bitsRead == rbStart[wrBlock]) {
+         /* Create the output file name, correctly handling leading paths. 
+            (31.10.2001 by Sergey E. Kusikov) */
+         Char* split;
+         Int32 ofs, k;
+         for (k = 0; k < BZ_MAX_FILENAME; k++) 
+            outFileName[k] = 0;
+         strcpy (outFileName, inFileName);
+         split = strrchr (outFileName, BZ_SPLIT_SYM);
+         if (split == NULL) {
+            split = outFileName;
+         } else {
+            ++split;
+	 }
+	 /* Now split points to the start of the basename. */
+         ofs  = split - outFileName;
+         sprintf (split, "rec%5d", wrBlock+1);
+         for (p = split; *p != 0; p++) if (*p == ' ') *p = '0';
+         strcat (outFileName, inFileName + ofs);
+
+         if ( !endsInBz2(outFileName)) strcat ( outFileName, ".bz2" );
+
+         fprintf ( stderr, "   writing block %d to `%s' ...\n",
+                           wrBlock+1, outFileName );
+
+         outFile = fopen ( outFileName, "wb" );
+         if (outFile == NULL) {
+            fprintf ( stderr, "%s: can't write `%s'\n",
+                      progName, outFileName );
+            exit(1);
+         }
+         bsWr = bsOpenWriteStream ( outFile );
+         bsPutUChar ( bsWr, BZ_HDR_B );    
+         bsPutUChar ( bsWr, BZ_HDR_Z );    
+         bsPutUChar ( bsWr, BZ_HDR_h );    
+         bsPutUChar ( bsWr, BZ_HDR_0 + 9 );
+         bsPutUChar ( bsWr, 0x31 ); bsPutUChar ( bsWr, 0x41 );
+         bsPutUChar ( bsWr, 0x59 ); bsPutUChar ( bsWr, 0x26 );
+         bsPutUChar ( bsWr, 0x53 ); bsPutUChar ( bsWr, 0x59 );
+      }
+   }
+
+   fprintf ( stderr, "%s: finished\n", progName );
+   return 0;
+}
+
+
+
+/*-----------------------------------------------------------*/
+/*--- end                                  bzip2recover.c ---*/
+/*-----------------------------------------------------------*/
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/bzlib.c b/contrib/vmap_extractor_v2/stormlib/bzip2/bzlib.c
new file mode 100644
index 00000000000..195f51a7840
--- /dev/null
+++ b/contrib/vmap_extractor_v2/stormlib/bzip2/bzlib.c
@@ -0,0 +1,1617 @@
+
+/*-------------------------------------------------------------*/
+/*--- Library top-level functions.                          ---*/
+/*---                                               bzlib.c ---*/
+/*-------------------------------------------------------------*/
+
+/*--
+  This file is a part of bzip2 and/or libbzip2, a program and
+  library for lossless, block-sorting data compression.
+
+  Copyright (C) 1996-2005 Julian R Seward.  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+  2. The origin of this software must not be misrepresented; you must 
+     not claim that you wrote the original software.  If you use this 
+     software in a product, an acknowledgment in the product 
+     documentation would be appreciated but is not required.
+
+  3. Altered source versions must be plainly marked as such, and must
+     not be misrepresented as being the original software.
+
+  4. The name of the author may not be used to endorse or promote 
+     products derived from this software without specific prior written 
+     permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  Julian Seward, Cambridge, UK.
+  jseward@bzip.org
+  bzip2/libbzip2 version 1.0 of 21 March 2000
+
+  This program is based on (at least) the work of:
+     Mike Burrows
+     David Wheeler
+     Peter Fenwick
+     Alistair Moffat
+     Radford Neal
+     Ian H. Witten
+     Robert Sedgewick
+     Jon L. Bentley
+
+  For more information on these sources, see the manual.
+--*/
+
+/*--
+   CHANGES
+   ~~~~~~~
+   0.9.0 -- original version.
+
+   0.9.0a/b -- no changes in this file.
+
+   0.9.0c
+      * made zero-length BZ_FLUSH work correctly in bzCompress().
+      * fixed bzWrite/bzRead to ignore zero-length requests.
+      * fixed bzread to correctly handle read requests after EOF.
+      * wrong parameter order in call to bzDecompressInit in
+        bzBuffToBuffDecompress.  Fixed.
+--*/
+
+#define _CRT_SECURE_NO_DEPRECATE
+#include "bzlib_private.h"
+
+
+/*---------------------------------------------------*/
+/*--- Compression stuff                           ---*/
+/*---------------------------------------------------*/
+
+
+/*---------------------------------------------------*/
+#ifndef BZ_NO_STDIO
+void BZ2_bz__AssertH__fail ( int errcode )
+{
+   fprintf(stderr, 
+      "\n\nbzip2/libbzip2: internal error number %d.\n"
+      "This is a bug in bzip2/libbzip2, %s.\n"
+      "Please report it to me at: jseward@bzip.org.  If this happened\n"
+      "when you were using some program which uses libbzip2 as a\n"
+      "component, you should also report this bug to the author(s)\n"
+      "of that program.  Please make an effort to report this bug;\n"
+      "timely and accurate bug reports eventually lead to higher\n"
+      "quality software.  Thanks.  Julian Seward, 15 February 2005.\n\n",
+      errcode,
+      BZ2_bzlibVersion()
+   );
+
+   if (errcode == 1007) {
+   fprintf(stderr,
+      "\n*** A special note about internal error number 1007 ***\n"
+      "\n"
+      "Experience suggests that a common cause of i.e. 1007\n"
+      "is unreliable memory or other hardware.  The 1007 assertion\n"
+      "just happens to cross-check the results of huge numbers of\n"
+      "memory reads/writes, and so acts (unintendedly) as a stress\n"
+      "test of your memory system.\n"
+      "\n"
+      "I suggest the following: try compressing the file again,\n"
+      "possibly monitoring progress in detail with the -vv flag.\n"
+      "\n"
+      "* If the error cannot be reproduced, and/or happens at different\n"
+      "  points in compression, you may have a flaky memory system.\n"
+      "  Try a memory-test program.  I have used Memtest86\n"
+      "  (www.memtest86.com).  At the time of writing it is free (GPLd).\n"
+      "  Memtest86 tests memory much more thorougly than your BIOSs\n"
+      "  power-on test, and may find failures that the BIOS doesn't.\n"
+      "\n"
+      "* If the error can be repeatably reproduced, this is a bug in\n"
+      "  bzip2, and I would very much like to hear about it.  Please\n"
+      "  let me know, and, ideally, save a copy of the file causing the\n"
+      "  problem -- without which I will be unable to investigate it.\n"
+      "\n"
+   );
+   }
+
+   exit(3);
+}
+#endif
+
+
+/*---------------------------------------------------*/
+static
+int bz_config_ok ( void )
+{
+   if (sizeof(int)   != 4) return 0;
+   if (sizeof(short) != 2) return 0;
+   if (sizeof(char)  != 1) return 0;
+   return 1;
+}
+
+
+/*---------------------------------------------------*/
+static
+void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
+{
+   void* v = malloc ( items * size );
+   return v;
+}
+
+static
+void default_bzfree ( void* opaque, void* addr )
+{
+   if (addr != NULL) free ( addr );
+}
+
+
+/*---------------------------------------------------*/
+static
+void prepare_new_block ( EState* s )
+{
+   Int32 i;
+   s->nblock = 0;
+   s->numZ = 0;
+   s->state_out_pos = 0;
+   BZ_INITIALISE_CRC ( s->blockCRC );
+   for (i = 0; i < 256; i++) s->inUse[i] = False;
+   s->blockNo++;
+}
+
+
+/*---------------------------------------------------*/
+static
+void init_RL ( EState* s )
+{
+   s->state_in_ch  = 256;
+   s->state_in_len = 0;
+}
+
+
+static
+Bool isempty_RL ( EState* s )
+{
+   if (s->state_in_ch < 256 && s->state_in_len > 0)
+      return False; else
+      return True;
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzCompressInit) 
+                    ( bz_stream* strm, 
+                     int        blockSize100k,
+                     int        verbosity,
+                     int        workFactor )
+{
+   Int32   n;
+   EState* s;
+
+   if (!bz_config_ok()) return BZ_CONFIG_ERROR;
+
+   if (strm == NULL || 
+       blockSize100k < 1 || blockSize100k > 9 ||
+       workFactor < 0 || workFactor > 250)
+     return BZ_PARAM_ERROR;
+
+   if (workFactor == 0) workFactor = 30;
+   if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
+   if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
+
+   s = BZALLOC( sizeof(EState) );
+   if (s == NULL) return BZ_MEM_ERROR;
+   s->strm = strm;
+
+   s->arr1 = NULL;
+   s->arr2 = NULL;
+   s->ftab = NULL;
+
+   n       = 100000 * blockSize100k;
+   s->arr1 = BZALLOC( n                  * sizeof(UInt32) );
+   s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
+   s->ftab = BZALLOC( 65537              * sizeof(UInt32) );
+
+   if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
+      if (s->arr1 != NULL) BZFREE(s->arr1);
+      if (s->arr2 != NULL) BZFREE(s->arr2);
+      if (s->ftab != NULL) BZFREE(s->ftab);
+      if (s       != NULL) BZFREE(s);
+      return BZ_MEM_ERROR;
+   }
+
+   s->blockNo           = 0;
+   s->state             = BZ_S_INPUT;
+   s->mode              = BZ_M_RUNNING;
+   s->combinedCRC       = 0;
+   s->blockSize100k     = blockSize100k;
+   s->nblockMAX         = 100000 * blockSize100k - 19;
+   s->verbosity         = verbosity;
+   s->workFactor        = workFactor;
+
+   s->block             = (UChar*)s->arr2;
+   s->mtfv              = (UInt16*)s->arr1;
+   s->zbits             = NULL;
+   s->ptr               = (UInt32*)s->arr1;
+
+   strm->state          = s;
+   strm->total_in_lo32  = 0;
+   strm->total_in_hi32  = 0;
+   strm->total_out_lo32 = 0;
+   strm->total_out_hi32 = 0;
+   init_RL ( s );
+   prepare_new_block ( s );
+   return BZ_OK;
+}
+
+
+/*---------------------------------------------------*/
+static
+void add_pair_to_block ( EState* s )
+{
+   Int32 i;
+   UChar ch = (UChar)(s->state_in_ch);
+   for (i = 0; i < s->state_in_len; i++) {
+      BZ_UPDATE_CRC( s->blockCRC, ch );
+   }
+   s->inUse[s->state_in_ch] = True;
+   switch (s->state_in_len) {
+      case 1:
+         s->block[s->nblock] = (UChar)ch; s->nblock++;
+         break;
+      case 2:
+         s->block[s->nblock] = (UChar)ch; s->nblock++;
+         s->block[s->nblock] = (UChar)ch; s->nblock++;
+         break;
+      case 3:
+         s->block[s->nblock] = (UChar)ch; s->nblock++;
+         s->block[s->nblock] = (UChar)ch; s->nblock++;
+         s->block[s->nblock] = (UChar)ch; s->nblock++;
+         break;
+      default:
+         s->inUse[s->state_in_len-4] = True;
+         s->block[s->nblock] = (UChar)ch; s->nblock++;
+         s->block[s->nblock] = (UChar)ch; s->nblock++;
+         s->block[s->nblock] = (UChar)ch; s->nblock++;
+         s->block[s->nblock] = (UChar)ch; s->nblock++;
+         s->block[s->nblock] = ((UChar)(s->state_in_len-4));
+         s->nblock++;
+         break;
+   }
+}
+
+
+/*---------------------------------------------------*/
+static
+void flush_RL ( EState* s )
+{
+   if (s->state_in_ch < 256) add_pair_to_block ( s );
+   init_RL ( s );
+}
+
+
+/*---------------------------------------------------*/
+#define ADD_CHAR_TO_BLOCK(zs,zchh0)               \
+{                                                 \
+   UInt32 zchh = (UInt32)(zchh0);                 \
+   /*-- fast track the common case --*/           \
+   if (zchh != zs->state_in_ch &&                 \
+       zs->state_in_len == 1) {                   \
+      UChar ch = (UChar)(zs->state_in_ch);        \
+      BZ_UPDATE_CRC( zs->blockCRC, ch );          \
+      zs->inUse[zs->state_in_ch] = True;          \
+      zs->block[zs->nblock] = (UChar)ch;          \
+      zs->nblock++;                               \
+      zs->state_in_ch = zchh;                     \
+   }                                              \
+   else                                           \
+   /*-- general, uncommon cases --*/              \
+   if (zchh != zs->state_in_ch ||                 \
+      zs->state_in_len == 255) {                  \
+      if (zs->state_in_ch < 256)                  \
+         add_pair_to_block ( zs );                \
+      zs->state_in_ch = zchh;                     \
+      zs->state_in_len = 1;                       \
+   } else {                                       \
+      zs->state_in_len++;                         \
+   }                                              \
+}
+
+
+/*---------------------------------------------------*/
+static
+Bool copy_input_until_stop ( EState* s )
+{
+   Bool progress_in = False;
+
+   if (s->mode == BZ_M_RUNNING) {
+
+      /*-- fast track the common case --*/
+      while (True) {
+         /*-- block full? --*/
+         if (s->nblock >= s->nblockMAX) break;
+         /*-- no input? --*/
+         if (s->strm->avail_in == 0) break;
+         progress_in = True;
+         ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); 
+         s->strm->next_in++;
+         s->strm->avail_in--;
+         s->strm->total_in_lo32++;
+         if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
+      }
+
+   } else {
+
+      /*-- general, uncommon case --*/
+      while (True) {
+         /*-- block full? --*/
+         if (s->nblock >= s->nblockMAX) break;
+         /*-- no input? --*/
+         if (s->strm->avail_in == 0) break;
+         /*-- flush/finish end? --*/
+         if (s->avail_in_expect == 0) break;
+         progress_in = True;
+         ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); 
+         s->strm->next_in++;
+         s->strm->avail_in--;
+         s->strm->total_in_lo32++;
+         if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
+         s->avail_in_expect--;
+      }
+   }
+   return progress_in;
+}
+
+
+/*---------------------------------------------------*/
+static
+Bool copy_output_until_stop ( EState* s )
+{
+   Bool progress_out = False;
+
+   while (True) {
+
+      /*-- no output space? --*/
+      if (s->strm->avail_out == 0) break;
+
+      /*-- block done? --*/
+      if (s->state_out_pos >= s->numZ) break;
+
+      progress_out = True;
+      *(s->strm->next_out) = s->zbits[s->state_out_pos];
+      s->state_out_pos++;
+      s->strm->avail_out--;
+      s->strm->next_out++;
+      s->strm->total_out_lo32++;
+      if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
+   }
+
+   return progress_out;
+}
+
+
+/*---------------------------------------------------*/
+static
+Bool handle_compress ( bz_stream* strm )
+{
+   Bool progress_in  = False;
+   Bool progress_out = False;
+   EState* s = strm->state;
+   
+   while (True) {
+
+      if (s->state == BZ_S_OUTPUT) {
+         progress_out |= copy_output_until_stop ( s );
+         if (s->state_out_pos < s->numZ) break;
+         if (s->mode == BZ_M_FINISHING && 
+             s->avail_in_expect == 0 &&
+             isempty_RL(s)) break;
+         prepare_new_block ( s );
+         s->state = BZ_S_INPUT;
+         if (s->mode == BZ_M_FLUSHING && 
+             s->avail_in_expect == 0 &&
+             isempty_RL(s)) break;
+      }
+
+      if (s->state == BZ_S_INPUT) {
+         progress_in |= copy_input_until_stop ( s );
+         if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
+            flush_RL ( s );
+            BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
+            s->state = BZ_S_OUTPUT;
+         }
+         else
+         if (s->nblock >= s->nblockMAX) {
+            BZ2_compressBlock ( s, False );
+            s->state = BZ_S_OUTPUT;
+         }
+         else
+         if (s->strm->avail_in == 0) {
+            break;
+         }
+      }
+
+   }
+
+   return progress_in || progress_out;
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
+{
+   Bool progress;
+   EState* s;
+   if (strm == NULL) return BZ_PARAM_ERROR;
+   s = strm->state;
+   if (s == NULL) return BZ_PARAM_ERROR;
+   if (s->strm != strm) return BZ_PARAM_ERROR;
+
+   preswitch:
+   switch (s->mode) {
+
+      case BZ_M_IDLE:
+         return BZ_SEQUENCE_ERROR;
+
+      case BZ_M_RUNNING:
+         if (action == BZ_RUN) {
+            progress = handle_compress ( strm );
+            return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
+         } 
+         else
+	 if (action == BZ_FLUSH) {
+            s->avail_in_expect = strm->avail_in;
+            s->mode = BZ_M_FLUSHING;
+            goto preswitch;
+         }
+         else
+         if (action == BZ_FINISH) {
+            s->avail_in_expect = strm->avail_in;
+            s->mode = BZ_M_FINISHING;
+            goto preswitch;
+         }
+         else 
+            return BZ_PARAM_ERROR;
+
+      case BZ_M_FLUSHING:
+         if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
+         if (s->avail_in_expect != s->strm->avail_in) 
+            return BZ_SEQUENCE_ERROR;
+         progress = handle_compress ( strm );
+         if (s->avail_in_expect > 0 || !isempty_RL(s) ||
+             s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
+         s->mode = BZ_M_RUNNING;
+         return BZ_RUN_OK;
+
+      case BZ_M_FINISHING:
+         if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
+         if (s->avail_in_expect != s->strm->avail_in) 
+            return BZ_SEQUENCE_ERROR;
+         progress = handle_compress ( strm );
+         if (!progress) return BZ_SEQUENCE_ERROR;
+         if (s->avail_in_expect > 0 || !isempty_RL(s) ||
+             s->state_out_pos < s->numZ) return BZ_FINISH_OK;
+         s->mode = BZ_M_IDLE;
+         return BZ_STREAM_END;
+   }
+   return BZ_OK; /*--not reached--*/
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzCompressEnd)  ( bz_stream *strm )
+{
+   EState* s;
+   if (strm == NULL) return BZ_PARAM_ERROR;
+   s = strm->state;
+   if (s == NULL) return BZ_PARAM_ERROR;
+   if (s->strm != strm) return BZ_PARAM_ERROR;
+
+   if (s->arr1 != NULL) BZFREE(s->arr1);
+   if (s->arr2 != NULL) BZFREE(s->arr2);
+   if (s->ftab != NULL) BZFREE(s->ftab);
+   BZFREE(strm->state);
+
+   strm->state = NULL;   
+
+   return BZ_OK;
+}
+
+
+/*---------------------------------------------------*/
+/*--- Decompression stuff                         ---*/
+/*---------------------------------------------------*/
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzDecompressInit) 
+                     ( bz_stream* strm, 
+                       int        verbosity,
+                       int        small )
+{
+   DState* s;
+
+   if (!bz_config_ok()) return BZ_CONFIG_ERROR;
+
+   if (strm == NULL) return BZ_PARAM_ERROR;
+   if (small != 0 && small != 1) return BZ_PARAM_ERROR;
+   if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
+
+   if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
+   if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
+
+   s = BZALLOC( sizeof(DState) );
+   if (s == NULL) return BZ_MEM_ERROR;
+   s->strm                  = strm;
+   strm->state              = s;
+   s->state                 = BZ_X_MAGIC_1;
+   s->bsLive                = 0;
+   s->bsBuff                = 0;
+   s->calculatedCombinedCRC = 0;
+   strm->total_in_lo32      = 0;
+   strm->total_in_hi32      = 0;
+   strm->total_out_lo32     = 0;
+   strm->total_out_hi32     = 0;
+   s->smallDecompress       = (Bool)small;
+   s->ll4                   = NULL;
+   s->ll16                  = NULL;
+   s->tt                    = NULL;
+   s->currBlockNo           = 0;
+   s->verbosity             = verbosity;
+
+   return BZ_OK;
+}
+
+
+/*---------------------------------------------------*/
+/* Return  True iff data corruption is discovered.
+   Returns False if there is no problem.
+*/
+static
+Bool unRLE_obuf_to_output_FAST ( DState* s )
+{
+   UChar k1;
+
+   if (s->blockRandomised) {
+
+      while (True) {
+         /* try to finish existing run */
+         while (True) {
+            if (s->strm->avail_out == 0) return False;
+            if (s->state_out_len == 0) break;
+            *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
+            BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
+            s->state_out_len--;
+            s->strm->next_out++;
+            s->strm->avail_out--;
+            s->strm->total_out_lo32++;
+            if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
+         }
+
+         /* can a new run be started? */
+         if (s->nblock_used == s->save_nblock+1) return False;
+               
+         /* Only caused by corrupt data stream? */
+         if (s->nblock_used > s->save_nblock+1)
+            return True;
+   
+         s->state_out_len = 1;
+         s->state_out_ch = s->k0;
+         BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 
+         k1 ^= BZ_RAND_MASK; s->nblock_used++;
+         if (s->nblock_used == s->save_nblock+1) continue;
+         if (k1 != s->k0) { s->k0 = k1; continue; };
+   
+         s->state_out_len = 2;
+         BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 
+         k1 ^= BZ_RAND_MASK; s->nblock_used++;
+         if (s->nblock_used == s->save_nblock+1) continue;
+         if (k1 != s->k0) { s->k0 = k1; continue; };
+   
+         s->state_out_len = 3;
+         BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 
+         k1 ^= BZ_RAND_MASK; s->nblock_used++;
+         if (s->nblock_used == s->save_nblock+1) continue;
+         if (k1 != s->k0) { s->k0 = k1; continue; };
+   
+         BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 
+         k1 ^= BZ_RAND_MASK; s->nblock_used++;
+         s->state_out_len = ((Int32)k1) + 4;
+         BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK; 
+         s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
+      }
+
+   } else {
+
+      /* restore */
+      UInt32        c_calculatedBlockCRC = s->calculatedBlockCRC;
+      UChar         c_state_out_ch       = s->state_out_ch;
+      Int32         c_state_out_len      = s->state_out_len;
+      Int32         c_nblock_used        = s->nblock_used;
+      Int32         c_k0                 = s->k0;
+      UInt32*       c_tt                 = s->tt;
+      UInt32        c_tPos               = s->tPos;
+      char*         cs_next_out          = s->strm->next_out;
+      unsigned int  cs_avail_out         = s->strm->avail_out;
+      /* end restore */
+
+      UInt32       avail_out_INIT = cs_avail_out;
+      Int32        s_save_nblockPP = s->save_nblock+1;
+      unsigned int total_out_lo32_old;
+
+      while (True) {
+
+         /* try to finish existing run */
+         if (c_state_out_len > 0) {
+            while (True) {
+               if (cs_avail_out == 0) goto return_notr;
+               if (c_state_out_len == 1) break;
+               *( (UChar*)(cs_next_out) ) = c_state_out_ch;
+               BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
+               c_state_out_len--;
+               cs_next_out++;
+               cs_avail_out--;
+            }
+            s_state_out_len_eq_one:
+            {
+               if (cs_avail_out == 0) { 
+                  c_state_out_len = 1; goto return_notr;
+               };
+               *( (UChar*)(cs_next_out) ) = c_state_out_ch;
+               BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
+               cs_next_out++;
+               cs_avail_out--;
+            }
+         }   
+         /* Only caused by corrupt data stream? */
+         if (c_nblock_used > s_save_nblockPP)
+            return True;
+
+         /* can a new run be started? */
+         if (c_nblock_used == s_save_nblockPP) {
+            c_state_out_len = 0; goto return_notr;
+         };   
+         c_state_out_ch = c_k0;
+         BZ_GET_FAST_C(k1); c_nblock_used++;
+         if (k1 != c_k0) { 
+            c_k0 = k1; goto s_state_out_len_eq_one; 
+         };
+         if (c_nblock_used == s_save_nblockPP) 
+            goto s_state_out_len_eq_one;
+   
+         c_state_out_len = 2;
+         BZ_GET_FAST_C(k1); c_nblock_used++;
+         if (c_nblock_used == s_save_nblockPP) continue;
+         if (k1 != c_k0) { c_k0 = k1; continue; };
+   
+         c_state_out_len = 3;
+         BZ_GET_FAST_C(k1); c_nblock_used++;
+         if (c_nblock_used == s_save_nblockPP) continue;
+         if (k1 != c_k0) { c_k0 = k1; continue; };
+   
+         BZ_GET_FAST_C(k1); c_nblock_used++;
+         c_state_out_len = ((Int32)k1) + 4;
+         BZ_GET_FAST_C(c_k0); c_nblock_used++;
+      }
+
+      return_notr:
+      total_out_lo32_old = s->strm->total_out_lo32;
+      s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
+      if (s->strm->total_out_lo32 < total_out_lo32_old)
+         s->strm->total_out_hi32++;
+
+      /* save */
+      s->calculatedBlockCRC = c_calculatedBlockCRC;
+      s->state_out_ch       = c_state_out_ch;
+      s->state_out_len      = c_state_out_len;
+      s->nblock_used        = c_nblock_used;
+      s->k0                 = c_k0;
+      s->tt                 = c_tt;
+      s->tPos               = c_tPos;
+      s->strm->next_out     = cs_next_out;
+      s->strm->avail_out    = cs_avail_out;
+      /* end save */
+   }
+   return False;
+}
+
+
+
+/*---------------------------------------------------*/
+__inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
+{
+   Int32 nb, na, mid;
+   nb = 0;
+   na = 256;
+   do {
+      mid = (nb + na) >> 1;
+      if (indx >= cftab[mid]) nb = mid; else na = mid;
+   }
+   while (na - nb != 1);
+   return nb;
+}
+
+
+/*---------------------------------------------------*/
+/* Return  True iff data corruption is discovered.
+   Returns False if there is no problem.
+*/
+static
+Bool unRLE_obuf_to_output_SMALL ( DState* s )
+{
+   UChar k1;
+
+   if (s->blockRandomised) {
+
+      while (True) {
+         /* try to finish existing run */
+         while (True) {
+            if (s->strm->avail_out == 0) return False;
+            if (s->state_out_len == 0) break;
+            *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
+            BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
+            s->state_out_len--;
+            s->strm->next_out++;
+            s->strm->avail_out--;
+            s->strm->total_out_lo32++;
+            if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
+         }
+   
+         /* can a new run be started? */
+         if (s->nblock_used == s->save_nblock+1) return False;
+
+         /* Only caused by corrupt data stream? */
+         if (s->nblock_used > s->save_nblock+1)
+            return True;
+   
+         s->state_out_len = 1;
+         s->state_out_ch = s->k0;
+         BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 
+         k1 ^= BZ_RAND_MASK; s->nblock_used++;
+         if (s->nblock_used == s->save_nblock+1) continue;
+         if (k1 != s->k0) { s->k0 = k1; continue; };
+   
+         s->state_out_len = 2;
+         BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 
+         k1 ^= BZ_RAND_MASK; s->nblock_used++;
+         if (s->nblock_used == s->save_nblock+1) continue;
+         if (k1 != s->k0) { s->k0 = k1; continue; };
+   
+         s->state_out_len = 3;
+         BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 
+         k1 ^= BZ_RAND_MASK; s->nblock_used++;
+         if (s->nblock_used == s->save_nblock+1) continue;
+         if (k1 != s->k0) { s->k0 = k1; continue; };
+   
+         BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 
+         k1 ^= BZ_RAND_MASK; s->nblock_used++;
+         s->state_out_len = ((Int32)k1) + 4;
+         BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK; 
+         s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
+      }
+
+   } else {
+
+      while (True) {
+         /* try to finish existing run */
+         while (True) {
+            if (s->strm->avail_out == 0) return False;
+            if (s->state_out_len == 0) break;
+            *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
+            BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
+            s->state_out_len--;
+            s->strm->next_out++;
+            s->strm->avail_out--;
+            s->strm->total_out_lo32++;
+            if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
+         }
+   
+         /* can a new run be started? */
+         if (s->nblock_used == s->save_nblock+1) return False;
+
+         /* Only caused by corrupt data stream? */
+         if (s->nblock_used > s->save_nblock+1)
+            return True;
+   
+         s->state_out_len = 1;
+         s->state_out_ch = s->k0;
+         BZ_GET_SMALL(k1); s->nblock_used++;
+         if (s->nblock_used == s->save_nblock+1) continue;
+         if (k1 != s->k0) { s->k0 = k1; continue; };
+   
+         s->state_out_len = 2;
+         BZ_GET_SMALL(k1); s->nblock_used++;
+         if (s->nblock_used == s->save_nblock+1) continue;
+         if (k1 != s->k0) { s->k0 = k1; continue; };
+   
+         s->state_out_len = 3;
+         BZ_GET_SMALL(k1); s->nblock_used++;
+         if (s->nblock_used == s->save_nblock+1) continue;
+         if (k1 != s->k0) { s->k0 = k1; continue; };
+   
+         BZ_GET_SMALL(k1); s->nblock_used++;
+         s->state_out_len = ((Int32)k1) + 4;
+         BZ_GET_SMALL(s->k0); s->nblock_used++;
+      }
+
+   }
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
+{
+   Bool    corrupt;
+   DState* s;
+   if (strm == NULL) return BZ_PARAM_ERROR;
+   s = strm->state;
+   if (s == NULL) return BZ_PARAM_ERROR;
+   if (s->strm != strm) return BZ_PARAM_ERROR;
+
+   while (True) {
+      if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
+      if (s->state == BZ_X_OUTPUT) {
+         if (s->smallDecompress)
+            corrupt = unRLE_obuf_to_output_SMALL ( s ); else
+            corrupt = unRLE_obuf_to_output_FAST  ( s );
+         if (corrupt) return BZ_DATA_ERROR;
+         if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
+            BZ_FINALISE_CRC ( s->calculatedBlockCRC );
+            if (s->verbosity >= 3) 
+               VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC, 
+                          s->calculatedBlockCRC );
+            if (s->verbosity >= 2) VPrintf0 ( "]" );
+            if (s->calculatedBlockCRC != s->storedBlockCRC)
+               return BZ_DATA_ERROR;
+            s->calculatedCombinedCRC 
+               = (s->calculatedCombinedCRC << 1) | 
+                    (s->calculatedCombinedCRC >> 31);
+            s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
+            s->state = BZ_X_BLKHDR_1;
+         } else {
+            return BZ_OK;
+         }
+      }
+      if (s->state >= BZ_X_MAGIC_1) {
+         Int32 r = BZ2_decompress ( s );
+         if (r == BZ_STREAM_END) {
+            if (s->verbosity >= 3)
+               VPrintf2 ( "\n    combined CRCs: stored = 0x%08x, computed = 0x%08x", 
+                          s->storedCombinedCRC, s->calculatedCombinedCRC );
+            if (s->calculatedCombinedCRC != s->storedCombinedCRC)
+               return BZ_DATA_ERROR;
+            return r;
+         }
+         if (s->state != BZ_X_OUTPUT) return r;
+      }
+   }
+
+   AssertH ( 0, 6001 );
+
+   return 0;  /*NOTREACHED*/
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzDecompressEnd)  ( bz_stream *strm )
+{
+   DState* s;
+   if (strm == NULL) return BZ_PARAM_ERROR;
+   s = strm->state;
+   if (s == NULL) return BZ_PARAM_ERROR;
+   if (s->strm != strm) return BZ_PARAM_ERROR;
+
+   if (s->tt   != NULL) BZFREE(s->tt);
+   if (s->ll16 != NULL) BZFREE(s->ll16);
+   if (s->ll4  != NULL) BZFREE(s->ll4);
+
+   BZFREE(strm->state);
+   strm->state = NULL;
+
+   return BZ_OK;
+}
+
+
+#ifndef BZ_NO_STDIO
+/*---------------------------------------------------*/
+/*--- File I/O stuff                              ---*/
+/*---------------------------------------------------*/
+
+#define BZ_SETERR(eee)                    \
+{                                         \
+   if (bzerror != NULL) *bzerror = eee;   \
+   if (bzf != NULL) bzf->lastErr = eee;   \
+}
+
+typedef 
+   struct {
+      FILE*     handle;
+      Char      buf[BZ_MAX_UNUSED];
+      Int32     bufN;
+      Bool      writing;
+      bz_stream strm;
+      Int32     lastErr;
+      Bool      initialisedOk;
+   }
+   bzFile;
+
+
+/*---------------------------------------------*/
+static Bool myfeof ( FILE* f )
+{
+   Int32 c = fgetc ( f );
+   if (c == EOF) return True;
+   ungetc ( c, f );
+   return False;
+}
+
+
+/*---------------------------------------------------*/
+BZFILE* BZ_API(BZ2_bzWriteOpen) 
+                    ( int*  bzerror,      
+                      FILE* f, 
+                      int   blockSize100k, 
+                      int   verbosity,
+                      int   workFactor )
+{
+   Int32   ret;
+   bzFile* bzf = NULL;
+
+   BZ_SETERR(BZ_OK);
+
+   if (f == NULL ||
+       (blockSize100k < 1 || blockSize100k > 9) ||
+       (workFactor < 0 || workFactor > 250) ||
+       (verbosity < 0 || verbosity > 4))
+      { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
+
+   if (ferror(f))
+      { BZ_SETERR(BZ_IO_ERROR); return NULL; };
+
+   bzf = malloc ( sizeof(bzFile) );
+   if (bzf == NULL)
+      { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
+
+   BZ_SETERR(BZ_OK);
+   bzf->initialisedOk = False;
+   bzf->bufN          = 0;
+   bzf->handle        = f;
+   bzf->writing       = True;
+   bzf->strm.bzalloc  = NULL;
+   bzf->strm.bzfree   = NULL;
+   bzf->strm.opaque   = NULL;
+
+   if (workFactor == 0) workFactor = 30;
+   ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k, 
+                              verbosity, workFactor );
+   if (ret != BZ_OK)
+      { BZ_SETERR(ret); free(bzf); return NULL; };
+
+   bzf->strm.avail_in = 0;
+   bzf->initialisedOk = True;
+   return bzf;   
+}
+
+
+
+/*---------------------------------------------------*/
+void BZ_API(BZ2_bzWrite)
+             ( int*    bzerror, 
+               BZFILE* b, 
+               void*   buf, 
+               int     len )
+{
+   Int32 n, n2, ret;
+   bzFile* bzf = (bzFile*)b;
+
+   BZ_SETERR(BZ_OK);
+   if (bzf == NULL || buf == NULL || len < 0)
+      { BZ_SETERR(BZ_PARAM_ERROR); return; };
+   if (!(bzf->writing))
+      { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
+   if (ferror(bzf->handle))
+      { BZ_SETERR(BZ_IO_ERROR); return; };
+
+   if (len == 0)
+      { BZ_SETERR(BZ_OK); return; };
+
+   bzf->strm.avail_in = len;
+   bzf->strm.next_in  = buf;
+
+   while (True) {
+      bzf->strm.avail_out = BZ_MAX_UNUSED;
+      bzf->strm.next_out = bzf->buf;
+      ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
+      if (ret != BZ_RUN_OK)
+         { BZ_SETERR(ret); return; };
+
+      if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
+         n = BZ_MAX_UNUSED - bzf->strm.avail_out;
+         n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), 
+                       n, bzf->handle );
+         if (n != n2 || ferror(bzf->handle))
+            { BZ_SETERR(BZ_IO_ERROR); return; };
+      }
+
+      if (bzf->strm.avail_in == 0)
+         { BZ_SETERR(BZ_OK); return; };
+   }
+}
+
+
+/*---------------------------------------------------*/
+void BZ_API(BZ2_bzWriteClose)
+                  ( int*          bzerror, 
+                    BZFILE*       b, 
+                    int           abandon,
+                    unsigned int* nbytes_in,
+                    unsigned int* nbytes_out )
+{
+   BZ2_bzWriteClose64 ( bzerror, b, abandon, 
+                        nbytes_in, NULL, nbytes_out, NULL );
+}
+
+
+void BZ_API(BZ2_bzWriteClose64)
+                  ( int*          bzerror, 
+                    BZFILE*       b, 
+                    int           abandon,
+                    unsigned int* nbytes_in_lo32,
+                    unsigned int* nbytes_in_hi32,
+                    unsigned int* nbytes_out_lo32,
+                    unsigned int* nbytes_out_hi32 )
+{
+   Int32   n, n2, ret;
+   bzFile* bzf = (bzFile*)b;
+
+   if (bzf == NULL)
+      { BZ_SETERR(BZ_OK); return; };
+   if (!(bzf->writing))
+      { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
+   if (ferror(bzf->handle))
+      { BZ_SETERR(BZ_IO_ERROR); return; };
+
+   if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
+   if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
+   if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
+   if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
+
+   if ((!abandon) && bzf->lastErr == BZ_OK) {
+      while (True) {
+         bzf->strm.avail_out = BZ_MAX_UNUSED;
+         bzf->strm.next_out = bzf->buf;
+         ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
+         if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
+            { BZ_SETERR(ret); return; };
+
+         if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
+            n = BZ_MAX_UNUSED - bzf->strm.avail_out;
+            n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), 
+                          n, bzf->handle );
+            if (n != n2 || ferror(bzf->handle))
+               { BZ_SETERR(BZ_IO_ERROR); return; };
+         }
+
+         if (ret == BZ_STREAM_END) break;
+      }
+   }
+
+   if ( !abandon && !ferror ( bzf->handle ) ) {
+      fflush ( bzf->handle );
+      if (ferror(bzf->handle))
+         { BZ_SETERR(BZ_IO_ERROR); return; };
+   }
+
+   if (nbytes_in_lo32 != NULL)
+      *nbytes_in_lo32 = bzf->strm.total_in_lo32;
+   if (nbytes_in_hi32 != NULL)
+      *nbytes_in_hi32 = bzf->strm.total_in_hi32;
+   if (nbytes_out_lo32 != NULL)
+      *nbytes_out_lo32 = bzf->strm.total_out_lo32;
+   if (nbytes_out_hi32 != NULL)
+      *nbytes_out_hi32 = bzf->strm.total_out_hi32;
+
+   BZ_SETERR(BZ_OK);
+   BZ2_bzCompressEnd ( &(bzf->strm) );
+   free ( bzf );
+}
+
+
+/*---------------------------------------------------*/
+BZFILE* BZ_API(BZ2_bzReadOpen) 
+                   ( int*  bzerror, 
+                     FILE* f, 
+                     int   verbosity,
+                     int   small,
+                     void* unused,
+                     int   nUnused )
+{
+   bzFile* bzf = NULL;
+   int     ret;
+
+   BZ_SETERR(BZ_OK);
+
+   if (f == NULL || 
+       (small != 0 && small != 1) ||
+       (verbosity < 0 || verbosity > 4) ||
+       (unused == NULL && nUnused != 0) ||
+       (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
+      { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
+
+   if (ferror(f))
+      { BZ_SETERR(BZ_IO_ERROR); return NULL; };
+
+   bzf = malloc ( sizeof(bzFile) );
+   if (bzf == NULL) 
+      { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
+
+   BZ_SETERR(BZ_OK);
+
+   bzf->initialisedOk = False;
+   bzf->handle        = f;
+   bzf->bufN          = 0;
+   bzf->writing       = False;
+   bzf->strm.bzalloc  = NULL;
+   bzf->strm.bzfree   = NULL;
+   bzf->strm.opaque   = NULL;
+   
+   while (nUnused > 0) {
+      bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
+      unused = ((void*)( 1 + ((UChar*)(unused))  ));
+      nUnused--;
+   }
+
+   ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
+   if (ret != BZ_OK)
+      { BZ_SETERR(ret); free(bzf); return NULL; };
+
+   bzf->strm.avail_in = bzf->bufN;
+   bzf->strm.next_in  = bzf->buf;
+
+   bzf->initialisedOk = True;
+   return bzf;   
+}
+
+
+/*---------------------------------------------------*/
+void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
+{
+   bzFile* bzf = (bzFile*)b;
+
+   BZ_SETERR(BZ_OK);
+   if (bzf == NULL)
+      { BZ_SETERR(BZ_OK); return; };
+
+   if (bzf->writing)
+      { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
+
+   if (bzf->initialisedOk)
+      (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
+   free ( bzf );
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzRead) 
+           ( int*    bzerror, 
+             BZFILE* b, 
+             void*   buf, 
+             int     len )
+{
+   Int32   n, ret;
+   bzFile* bzf = (bzFile*)b;
+
+   BZ_SETERR(BZ_OK);
+
+   if (bzf == NULL || buf == NULL || len < 0)
+      { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
+
+   if (bzf->writing)
+      { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
+
+   if (len == 0)
+      { BZ_SETERR(BZ_OK); return 0; };
+
+   bzf->strm.avail_out = len;
+   bzf->strm.next_out = buf;
+
+   while (True) {
+
+      if (ferror(bzf->handle)) 
+         { BZ_SETERR(BZ_IO_ERROR); return 0; };
+
+      if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
+         n = fread ( bzf->buf, sizeof(UChar), 
+                     BZ_MAX_UNUSED, bzf->handle );
+         if (ferror(bzf->handle))
+            { BZ_SETERR(BZ_IO_ERROR); return 0; };
+         bzf->bufN = n;
+         bzf->strm.avail_in = bzf->bufN;
+         bzf->strm.next_in = bzf->buf;
+      }
+
+      ret = BZ2_bzDecompress ( &(bzf->strm) );
+
+      if (ret != BZ_OK && ret != BZ_STREAM_END)
+         { BZ_SETERR(ret); return 0; };
+
+      if (ret == BZ_OK && myfeof(bzf->handle) && 
+          bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
+         { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
+
+      if (ret == BZ_STREAM_END)
+         { BZ_SETERR(BZ_STREAM_END);
+           return len - bzf->strm.avail_out; };
+      if (bzf->strm.avail_out == 0)
+         { BZ_SETERR(BZ_OK); return len; };
+      
+   }
+
+   return 0; /*not reached*/
+}
+
+
+/*---------------------------------------------------*/
+void BZ_API(BZ2_bzReadGetUnused) 
+                     ( int*    bzerror, 
+                       BZFILE* b, 
+                       void**  unused, 
+                       int*    nUnused )
+{
+   bzFile* bzf = (bzFile*)b;
+   if (bzf == NULL)
+      { BZ_SETERR(BZ_PARAM_ERROR); return; };
+   if (bzf->lastErr != BZ_STREAM_END)
+      { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
+   if (unused == NULL || nUnused == NULL)
+      { BZ_SETERR(BZ_PARAM_ERROR); return; };
+
+   BZ_SETERR(BZ_OK);
+   *nUnused = bzf->strm.avail_in;
+   *unused = bzf->strm.next_in;
+}
+#endif
+
+
+/*---------------------------------------------------*/
+/*--- Misc convenience stuff                      ---*/
+/*---------------------------------------------------*/
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzBuffToBuffCompress) 
+                         ( char*         dest, 
+                           unsigned int* destLen,
+                           char*         source, 
+                           unsigned int  sourceLen,
+                           int           blockSize100k, 
+                           int           verbosity, 
+                           int           workFactor )
+{
+   bz_stream strm;
+   int ret;
+
+   if (dest == NULL || destLen == NULL || 
+       source == NULL ||
+       blockSize100k < 1 || blockSize100k > 9 ||
+       verbosity < 0 || verbosity > 4 ||
+       workFactor < 0 || workFactor > 250) 
+      return BZ_PARAM_ERROR;
+
+   if (workFactor == 0) workFactor = 30;
+   strm.bzalloc = NULL;
+   strm.bzfree = NULL;
+   strm.opaque = NULL;
+   ret = BZ2_bzCompressInit ( &strm, blockSize100k, 
+                              verbosity, workFactor );
+   if (ret != BZ_OK) return ret;
+
+   strm.next_in = source;
+   strm.next_out = dest;
+   strm.avail_in = sourceLen;
+   strm.avail_out = *destLen;
+
+   ret = BZ2_bzCompress ( &strm, BZ_FINISH );
+   if (ret == BZ_FINISH_OK) goto output_overflow;
+   if (ret != BZ_STREAM_END) goto errhandler;
+
+   /* normal termination */
+   *destLen -= strm.avail_out;   
+   BZ2_bzCompressEnd ( &strm );
+   return BZ_OK;
+
+   output_overflow:
+   BZ2_bzCompressEnd ( &strm );
+   return BZ_OUTBUFF_FULL;
+
+   errhandler:
+   BZ2_bzCompressEnd ( &strm );
+   return ret;
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzBuffToBuffDecompress) 
+                           ( char*         dest, 
+                             unsigned int* destLen,
+                             char*         source, 
+                             unsigned int  sourceLen,
+                             int           small,
+                             int           verbosity )
+{
+   bz_stream strm;
+   int ret;
+
+   if (dest == NULL || destLen == NULL || 
+       source == NULL ||
+       (small != 0 && small != 1) ||
+       verbosity < 0 || verbosity > 4) 
+          return BZ_PARAM_ERROR;
+
+   strm.bzalloc = NULL;
+   strm.bzfree = NULL;
+   strm.opaque = NULL;
+   ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
+   if (ret != BZ_OK) return ret;
+
+   strm.next_in = source;
+   strm.next_out = dest;
+   strm.avail_in = sourceLen;
+   strm.avail_out = *destLen;
+
+   ret = BZ2_bzDecompress ( &strm );
+   if (ret == BZ_OK) goto output_overflow_or_eof;
+   if (ret != BZ_STREAM_END) goto errhandler;
+
+   /* normal termination */
+   *destLen -= strm.avail_out;
+   BZ2_bzDecompressEnd ( &strm );
+   return BZ_OK;
+
+   output_overflow_or_eof:
+   if (strm.avail_out > 0) {
+      BZ2_bzDecompressEnd ( &strm );
+      return BZ_UNEXPECTED_EOF;
+   } else {
+      BZ2_bzDecompressEnd ( &strm );
+      return BZ_OUTBUFF_FULL;
+   };      
+
+   errhandler:
+   BZ2_bzDecompressEnd ( &strm );
+   return ret; 
+}
+
+
+/*---------------------------------------------------*/
+/*--
+   Code contributed by Yoshioka Tsuneo
+   (QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp),
+   to support better zlib compatibility.
+   This code is not _officially_ part of libbzip2 (yet);
+   I haven't tested it, documented it, or considered the
+   threading-safeness of it.
+   If this code breaks, please contact both Yoshioka and me.
+--*/
+/*---------------------------------------------------*/
+
+/*---------------------------------------------------*/
+/*--
+   return version like "0.9.0c".
+--*/
+const char * BZ_API(BZ2_bzlibVersion)(void)
+{
+   return BZ_VERSION;
+}
+
+
+#ifndef BZ_NO_STDIO
+/*---------------------------------------------------*/
+
+#if defined(_WIN32) || defined(OS2) || defined(MSDOS)
+#   include 
+#   include 
+#   define SET_BINARY_MODE(file) _setmode(_fileno(file),O_BINARY)
+#else
+#   define SET_BINARY_MODE(file)
+#endif
+static
+BZFILE * bzopen_or_bzdopen
+               ( const char *path,   /* no use when bzdopen */
+                 int fd,             /* no use when bzdopen */
+                 const char *mode,
+                 int open_mode)      /* bzopen: 0, bzdopen:1 */
+{
+   int    bzerr;
+   char   unused[BZ_MAX_UNUSED];
+   int    blockSize100k = 9;
+   int    writing       = 0;
+   char   mode2[10]     = "";
+   FILE   *fp           = NULL;
+   BZFILE *bzfp         = NULL;
+   int    verbosity     = 0;
+   int    workFactor    = 30;
+   int    smallMode     = 0;
+   int    nUnused       = 0; 
+
+   if (mode == NULL) return NULL;
+   while (*mode) {
+      switch (*mode) {
+      case 'r':
+         writing = 0; break;
+      case 'w':
+         writing = 1; break;
+      case 's':
+         smallMode = 1; break;
+      default:
+         if (isdigit((int)(*mode))) {
+            blockSize100k = *mode-BZ_HDR_0;
+         }
+      }
+      mode++;
+   }
+   strcat(mode2, writing ? "w" : "r" );
+   strcat(mode2,"b");   /* binary mode */
+
+   if (open_mode==0) {
+      if (path==NULL || strcmp(path,"")==0) {
+        fp = (writing ? stdout : stdin);
+        SET_BINARY_MODE(fp);
+      } else {
+        fp = fopen(path,mode2);
+      }
+   } else {
+#ifdef BZ_STRICT_ANSI
+      fp = NULL;
+#else
+      fp = _fdopen(fd,mode2);
+#endif
+   }
+   if (fp == NULL) return NULL;
+
+   if (writing) {
+      /* Guard against total chaos and anarchy -- JRS */
+      if (blockSize100k < 1) blockSize100k = 1;
+      if (blockSize100k > 9) blockSize100k = 9; 
+      bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
+                             verbosity,workFactor);
+   } else {
+      bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
+                            unused,nUnused);
+   }
+   if (bzfp == NULL) {
+      if (fp != stdin && fp != stdout) fclose(fp);
+      return NULL;
+   }
+   return bzfp;
+}
+
+
+/*---------------------------------------------------*/
+/*--
+   open file for read or write.
+      ex) bzopen("file","w9")
+      case path="" or NULL => use stdin or stdout.
+--*/
+BZFILE * BZ_API(BZ2_bzopen)
+               ( const char *path,
+                 const char *mode )
+{
+   return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
+}
+
+
+/*---------------------------------------------------*/
+BZFILE * BZ_API(BZ2_bzdopen)
+               ( int fd,
+                 const char *mode )
+{
+   return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
+{
+   int bzerr, nread;
+   if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
+   nread = BZ2_bzRead(&bzerr,b,buf,len);
+   if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
+      return nread;
+   } else {
+      return -1;
+   }
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
+{
+   int bzerr;
+
+   BZ2_bzWrite(&bzerr,b,buf,len);
+   if(bzerr == BZ_OK){
+      return len;
+   }else{
+      return -1;
+   }
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzflush) (BZFILE *b)
+{
+   /* do nothing now... */
+   return 0;
+}
+
+
+/*---------------------------------------------------*/
+void BZ_API(BZ2_bzclose) (BZFILE* b)
+{
+   int bzerr;
+   FILE *fp = ((bzFile *)b)->handle;
+   
+   if (b==NULL) {return;}
+   if(((bzFile*)b)->writing){
+      BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
+      if(bzerr != BZ_OK){
+         BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
+      }
+   }else{
+      BZ2_bzReadClose(&bzerr,b);
+   }
+   if(fp!=stdin && fp!=stdout){
+      fclose(fp);
+   }
+}
+
+
+/*---------------------------------------------------*/
+/*--
+   return last error code 
+--*/
+static char *bzerrorstrings[] = {
+       "OK"
+      ,"SEQUENCE_ERROR"
+      ,"PARAM_ERROR"
+      ,"MEM_ERROR"
+      ,"DATA_ERROR"
+      ,"DATA_ERROR_MAGIC"
+      ,"IO_ERROR"
+      ,"UNEXPECTED_EOF"
+      ,"OUTBUFF_FULL"
+      ,"CONFIG_ERROR"
+      ,"???"   /* for future */
+      ,"???"   /* for future */
+      ,"???"   /* for future */
+      ,"???"   /* for future */
+      ,"???"   /* for future */
+      ,"???"   /* for future */
+};
+
+
+const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
+{
+   int err = ((bzFile *)b)->lastErr;
+
+   if(err>0) err = 0;
+   *errnum = err;
+   return bzerrorstrings[err*-1];
+}
+#endif
+
+
+/*-------------------------------------------------------------*/
+/*--- end                                           bzlib.c ---*/
+/*-------------------------------------------------------------*/
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/bzlib.h b/contrib/vmap_extractor_v2/stormlib/bzip2/bzlib.h
new file mode 100644
index 00000000000..323724394a2
--- /dev/null
+++ b/contrib/vmap_extractor_v2/stormlib/bzip2/bzlib.h
@@ -0,0 +1,323 @@
+
+/*-------------------------------------------------------------*/
+/*--- Public header file for the library.                   ---*/
+/*---                                               bzlib.h ---*/
+/*-------------------------------------------------------------*/
+
+/*--
+  This file is a part of bzip2 and/or libbzip2, a program and
+  library for lossless, block-sorting data compression.
+
+  Copyright (C) 1996-2005 Julian R Seward.  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+  2. The origin of this software must not be misrepresented; you must 
+     not claim that you wrote the original software.  If you use this 
+     software in a product, an acknowledgment in the product 
+     documentation would be appreciated but is not required.
+
+  3. Altered source versions must be plainly marked as such, and must
+     not be misrepresented as being the original software.
+
+  4. The name of the author may not be used to endorse or promote 
+     products derived from this software without specific prior written 
+     permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  Julian Seward, Cambridge, UK.
+  jseward@bzip.org
+  bzip2/libbzip2 version 1.0 of 21 March 2000
+
+  This program is based on (at least) the work of:
+     Mike Burrows
+     David Wheeler
+     Peter Fenwick
+     Alistair Moffat
+     Radford Neal
+     Ian H. Witten
+     Robert Sedgewick
+     Jon L. Bentley
+
+  For more information on these sources, see the manual.
+--*/
+
+
+#ifndef _BZLIB_H
+#define _BZLIB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define BZ_RUN               0
+#define BZ_FLUSH             1
+#define BZ_FINISH            2
+
+#define BZ_OK                0
+#define BZ_RUN_OK            1
+#define BZ_FLUSH_OK          2
+#define BZ_FINISH_OK         3
+#define BZ_STREAM_END        4
+#define BZ_SEQUENCE_ERROR    (-1)
+#define BZ_PARAM_ERROR       (-2)
+#define BZ_MEM_ERROR         (-3)
+#define BZ_DATA_ERROR        (-4)
+#define BZ_DATA_ERROR_MAGIC  (-5)
+#define BZ_IO_ERROR          (-6)
+#define BZ_UNEXPECTED_EOF    (-7)
+#define BZ_OUTBUFF_FULL      (-8)
+#define BZ_CONFIG_ERROR      (-9)
+
+typedef 
+   struct {
+      char *next_in;
+      unsigned int avail_in;
+      unsigned int total_in_lo32;
+      unsigned int total_in_hi32;
+
+      char *next_out;
+      unsigned int avail_out;
+      unsigned int total_out_lo32;
+      unsigned int total_out_hi32;
+
+      void *state;
+
+      void *(*bzalloc)(void *,int,int);
+      void (*bzfree)(void *,void *);
+      void *opaque;
+   } 
+   bz_stream;
+
+
+#ifndef BZ_IMPORT
+#define BZ_EXPORT
+#endif
+
+#ifndef BZ_NO_STDIO
+/* Need a definitition for FILE */
+#include 
+#endif
+
+#ifdef _WIN32
+#   include 
+#   ifdef small
+      /* windows.h define small to char */
+#      undef small
+#   endif
+#   ifdef BZ_EXPORT
+#   define BZ_API(func) WINAPI func
+#   define BZ_EXTERN extern
+#   else
+   /* import windows dll dynamically */
+#   define BZ_API(func) (WINAPI * func)
+#   define BZ_EXTERN
+#   endif
+#else
+#   define BZ_API(func) func
+#   define BZ_EXTERN extern
+#endif
+
+
+/*-- Core (low-level) library functions --*/
+
+BZ_EXTERN int BZ_API(BZ2_bzCompressInit) ( 
+      bz_stream* strm, 
+      int        blockSize100k, 
+      int        verbosity, 
+      int        workFactor 
+   );
+
+BZ_EXTERN int BZ_API(BZ2_bzCompress) ( 
+      bz_stream* strm, 
+      int action 
+   );
+
+BZ_EXTERN int BZ_API(BZ2_bzCompressEnd) ( 
+      bz_stream* strm 
+   );
+
+BZ_EXTERN int BZ_API(BZ2_bzDecompressInit) ( 
+      bz_stream *strm, 
+      int       verbosity, 
+      int       small
+   );
+
+BZ_EXTERN int BZ_API(BZ2_bzDecompress) ( 
+      bz_stream* strm 
+   );
+
+BZ_EXTERN int BZ_API(BZ2_bzDecompressEnd) ( 
+      bz_stream *strm 
+   );
+
+
+
+/*-- High(er) level library functions --*/
+
+#ifndef BZ_NO_STDIO
+#define BZ_MAX_UNUSED 5000
+
+typedef void BZFILE;
+
+BZ_EXTERN BZFILE* BZ_API(BZ2_bzReadOpen) ( 
+      int*  bzerror,   
+      FILE* f, 
+      int   verbosity, 
+      int   small,
+      void* unused,    
+      int   nUnused 
+   );
+
+BZ_EXTERN void BZ_API(BZ2_bzReadClose) ( 
+      int*    bzerror, 
+      BZFILE* b 
+   );
+
+BZ_EXTERN void BZ_API(BZ2_bzReadGetUnused) ( 
+      int*    bzerror, 
+      BZFILE* b, 
+      void**  unused,  
+      int*    nUnused 
+   );
+
+BZ_EXTERN int BZ_API(BZ2_bzRead) ( 
+      int*    bzerror, 
+      BZFILE* b, 
+      void*   buf, 
+      int     len 
+   );
+
+BZ_EXTERN BZFILE* BZ_API(BZ2_bzWriteOpen) ( 
+      int*  bzerror,      
+      FILE* f, 
+      int   blockSize100k, 
+      int   verbosity, 
+      int   workFactor 
+   );
+
+BZ_EXTERN void BZ_API(BZ2_bzWrite) ( 
+      int*    bzerror, 
+      BZFILE* b, 
+      void*   buf, 
+      int     len 
+   );
+
+BZ_EXTERN void BZ_API(BZ2_bzWriteClose) ( 
+      int*          bzerror, 
+      BZFILE*       b, 
+      int           abandon, 
+      unsigned int* nbytes_in, 
+      unsigned int* nbytes_out 
+   );
+
+BZ_EXTERN void BZ_API(BZ2_bzWriteClose64) ( 
+      int*          bzerror, 
+      BZFILE*       b, 
+      int           abandon, 
+      unsigned int* nbytes_in_lo32, 
+      unsigned int* nbytes_in_hi32, 
+      unsigned int* nbytes_out_lo32, 
+      unsigned int* nbytes_out_hi32
+   );
+#endif
+
+
+/*-- Utility functions --*/
+
+BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffCompress) ( 
+      char*         dest, 
+      unsigned int* destLen,
+      char*         source, 
+      unsigned int  sourceLen,
+      int           blockSize100k, 
+      int           verbosity, 
+      int           workFactor 
+   );
+
+BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffDecompress) ( 
+      char*         dest, 
+      unsigned int* destLen,
+      char*         source, 
+      unsigned int  sourceLen,
+      int           small, 
+      int           verbosity 
+   );
+
+
+/*--
+   Code contributed by Yoshioka Tsuneo
+   (QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp),
+   to support better zlib compatibility.
+   This code is not _officially_ part of libbzip2 (yet);
+   I haven't tested it, documented it, or considered the
+   threading-safeness of it.
+   If this code breaks, please contact both Yoshioka and me.
+--*/
+
+BZ_EXTERN const char * BZ_API(BZ2_bzlibVersion) (
+      void
+   );
+
+#ifndef BZ_NO_STDIO
+BZ_EXTERN BZFILE * BZ_API(BZ2_bzopen) (
+      const char *path,
+      const char *mode
+   );
+
+BZ_EXTERN BZFILE * BZ_API(BZ2_bzdopen) (
+      int        fd,
+      const char *mode
+   );
+         
+BZ_EXTERN int BZ_API(BZ2_bzread) (
+      BZFILE* b, 
+      void* buf, 
+      int len 
+   );
+
+BZ_EXTERN int BZ_API(BZ2_bzwrite) (
+      BZFILE* b, 
+      void*   buf, 
+      int     len 
+   );
+
+BZ_EXTERN int BZ_API(BZ2_bzflush) (
+      BZFILE* b
+   );
+
+BZ_EXTERN void BZ_API(BZ2_bzclose) (
+      BZFILE* b
+   );
+
+BZ_EXTERN const char * BZ_API(BZ2_bzerror) (
+      BZFILE *b, 
+      int    *errnum
+   );
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/*-------------------------------------------------------------*/
+/*--- end                                           bzlib.h ---*/
+/*-------------------------------------------------------------*/
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/bzlib_private.h b/contrib/vmap_extractor_v2/stormlib/bzip2/bzlib_private.h
new file mode 100644
index 00000000000..ca76fe62b3b
--- /dev/null
+++ b/contrib/vmap_extractor_v2/stormlib/bzip2/bzlib_private.h
@@ -0,0 +1,537 @@
+
+/*-------------------------------------------------------------*/
+/*--- Private header file for the library.                  ---*/
+/*---                                       bzlib_private.h ---*/
+/*-------------------------------------------------------------*/
+
+/*--
+  This file is a part of bzip2 and/or libbzip2, a program and
+  library for lossless, block-sorting data compression.
+
+  Copyright (C) 1996-2005 Julian R Seward.  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+  2. The origin of this software must not be misrepresented; you must 
+     not claim that you wrote the original software.  If you use this 
+     software in a product, an acknowledgment in the product 
+     documentation would be appreciated but is not required.
+
+  3. Altered source versions must be plainly marked as such, and must
+     not be misrepresented as being the original software.
+
+  4. The name of the author may not be used to endorse or promote 
+     products derived from this software without specific prior written 
+     permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  Julian Seward, Cambridge, UK.
+  jseward@bzip.org
+  bzip2/libbzip2 version 1.0 of 21 March 2000
+
+  This program is based on (at least) the work of:
+     Mike Burrows
+     David Wheeler
+     Peter Fenwick
+     Alistair Moffat
+     Radford Neal
+     Ian H. Witten
+     Robert Sedgewick
+     Jon L. Bentley
+
+  For more information on these sources, see the manual.
+--*/
+
+
+#ifndef _BZLIB_PRIVATE_H
+#define _BZLIB_PRIVATE_H
+
+#include 
+
+#ifndef BZ_NO_STDIO
+#include 
+#include 
+#include 
+#endif
+
+#include "bzlib.h"
+
+
+
+/*-- General stuff. --*/
+
+#define BZ_VERSION  "1.0.3, 15-Feb-2005"
+
+typedef char            Char;
+typedef unsigned char   Bool;
+typedef unsigned char   UChar;
+typedef int             Int32;
+typedef unsigned int    UInt32;
+typedef short           Int16;
+typedef unsigned short  UInt16;
+
+#define True  ((Bool)1)
+#define False ((Bool)0)
+
+#ifndef __GNUC__
+#define __inline__  /* */
+#endif 
+
+#ifndef BZ_NO_STDIO
+extern void BZ2_bz__AssertH__fail ( int errcode );
+#define AssertH(cond,errcode) \
+   { if (!(cond)) BZ2_bz__AssertH__fail ( errcode ); }
+#if BZ_DEBUG
+#define AssertD(cond,msg) \
+   { if (!(cond)) {       \
+      fprintf ( stderr,   \
+        "\n\nlibbzip2(debug build): internal error\n\t%s\n", msg );\
+      exit(1); \
+   }}
+#else
+#define AssertD(cond,msg) /* */
+#endif
+#define VPrintf0(zf) \
+   fprintf(stderr,zf)
+#define VPrintf1(zf,za1) \
+   fprintf(stderr,zf,za1)
+#define VPrintf2(zf,za1,za2) \
+   fprintf(stderr,zf,za1,za2)
+#define VPrintf3(zf,za1,za2,za3) \
+   fprintf(stderr,zf,za1,za2,za3)
+#define VPrintf4(zf,za1,za2,za3,za4) \
+   fprintf(stderr,zf,za1,za2,za3,za4)
+#define VPrintf5(zf,za1,za2,za3,za4,za5) \
+   fprintf(stderr,zf,za1,za2,za3,za4,za5)
+#else
+extern void bz_internal_error ( int errcode );
+#define AssertH(cond,errcode) \
+   { if (!(cond)) bz_internal_error ( errcode ); }
+#define AssertD(cond,msg) /* */
+#define VPrintf0(zf) /* */
+#define VPrintf1(zf,za1) /* */
+#define VPrintf2(zf,za1,za2) /* */
+#define VPrintf3(zf,za1,za2,za3) /* */
+#define VPrintf4(zf,za1,za2,za3,za4) /* */
+#define VPrintf5(zf,za1,za2,za3,za4,za5) /* */
+#endif
+
+
+#define BZALLOC(nnn) (strm->bzalloc)(strm->opaque,(nnn),1)
+#define BZFREE(ppp)  (strm->bzfree)(strm->opaque,(ppp))
+
+
+/*-- Header bytes. --*/
+
+#define BZ_HDR_B 0x42   /* 'B' */
+#define BZ_HDR_Z 0x5a   /* 'Z' */
+#define BZ_HDR_h 0x68   /* 'h' */
+#define BZ_HDR_0 0x30   /* '0' */
+  
+/*-- Constants for the back end. --*/
+
+#define BZ_MAX_ALPHA_SIZE 258
+#define BZ_MAX_CODE_LEN    23
+
+#define BZ_RUNA 0
+#define BZ_RUNB 1
+
+#define BZ_N_GROUPS 6
+#define BZ_G_SIZE   50
+#define BZ_N_ITERS  4
+
+#define BZ_MAX_SELECTORS (2 + (900000 / BZ_G_SIZE))
+
+
+
+/*-- Stuff for randomising repetitive blocks. --*/
+
+extern Int32 BZ2_rNums[512];
+
+#define BZ_RAND_DECLS                          \
+   Int32 rNToGo;                               \
+   Int32 rTPos                                 \
+
+#define BZ_RAND_INIT_MASK                      \
+   s->rNToGo = 0;                              \
+   s->rTPos  = 0                               \
+
+#define BZ_RAND_MASK ((s->rNToGo == 1) ? 1 : 0)
+
+#define BZ_RAND_UPD_MASK                       \
+   if (s->rNToGo == 0) {                       \
+      s->rNToGo = BZ2_rNums[s->rTPos];         \
+      s->rTPos++;                              \
+      if (s->rTPos == 512) s->rTPos = 0;       \
+   }                                           \
+   s->rNToGo--;
+
+
+
+/*-- Stuff for doing CRCs. --*/
+
+extern UInt32 BZ2_crc32Table[256];
+
+#define BZ_INITIALISE_CRC(crcVar)              \
+{                                              \
+   crcVar = 0xffffffffL;                       \
+}
+
+#define BZ_FINALISE_CRC(crcVar)                \
+{                                              \
+   crcVar = ~(crcVar);                         \
+}
+
+#define BZ_UPDATE_CRC(crcVar,cha)              \
+{                                              \
+   crcVar = (crcVar << 8) ^                    \
+            BZ2_crc32Table[(crcVar >> 24) ^    \
+                           ((UChar)cha)];      \
+}
+
+
+
+/*-- States and modes for compression. --*/
+
+#define BZ_M_IDLE      1
+#define BZ_M_RUNNING   2
+#define BZ_M_FLUSHING  3
+#define BZ_M_FINISHING 4
+
+#define BZ_S_OUTPUT    1
+#define BZ_S_INPUT     2
+
+#define BZ_N_RADIX 2
+#define BZ_N_QSORT 12
+#define BZ_N_SHELL 18
+#define BZ_N_OVERSHOOT (BZ_N_RADIX + BZ_N_QSORT + BZ_N_SHELL + 2)
+
+
+
+
+/*-- Structure holding all the compression-side stuff. --*/
+
+typedef
+   struct {
+      /* pointer back to the struct bz_stream */
+      bz_stream* strm;
+
+      /* mode this stream is in, and whether inputting */
+      /* or outputting data */
+      Int32    mode;
+      Int32    state;
+
+      /* remembers avail_in when flush/finish requested */
+      UInt32   avail_in_expect;
+
+      /* for doing the block sorting */
+      UInt32*  arr1;
+      UInt32*  arr2;
+      UInt32*  ftab;
+      Int32    origPtr;
+
+      /* aliases for arr1 and arr2 */
+      UInt32*  ptr;
+      UChar*   block;
+      UInt16*  mtfv;
+      UChar*   zbits;
+
+      /* for deciding when to use the fallback sorting algorithm */
+      Int32    workFactor;
+
+      /* run-length-encoding of the input */
+      UInt32   state_in_ch;
+      Int32    state_in_len;
+      BZ_RAND_DECLS;
+
+      /* input and output limits and current posns */
+      Int32    nblock;
+      Int32    nblockMAX;
+      Int32    numZ;
+      Int32    state_out_pos;
+
+      /* map of bytes used in block */
+      Int32    nInUse;
+      Bool     inUse[256];
+      UChar    unseqToSeq[256];
+
+      /* the buffer for bit stream creation */
+      UInt32   bsBuff;
+      Int32    bsLive;
+
+      /* block and combined CRCs */
+      UInt32   blockCRC;
+      UInt32   combinedCRC;
+
+      /* misc administratium */
+      Int32    verbosity;
+      Int32    blockNo;
+      Int32    blockSize100k;
+
+      /* stuff for coding the MTF values */
+      Int32    nMTF;
+      Int32    mtfFreq    [BZ_MAX_ALPHA_SIZE];
+      UChar    selector   [BZ_MAX_SELECTORS];
+      UChar    selectorMtf[BZ_MAX_SELECTORS];
+
+      UChar    len     [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+      Int32    code    [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+      Int32    rfreq   [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+      /* second dimension: only 3 needed; 4 makes index calculations faster */
+      UInt32   len_pack[BZ_MAX_ALPHA_SIZE][4];
+
+   }
+   EState;
+
+
+
+/*-- externs for compression. --*/
+
+extern void 
+BZ2_blockSort ( EState* );
+
+extern void 
+BZ2_compressBlock ( EState*, Bool );
+
+extern void 
+BZ2_bsInitWrite ( EState* );
+
+extern void 
+BZ2_hbAssignCodes ( Int32*, UChar*, Int32, Int32, Int32 );
+
+extern void 
+BZ2_hbMakeCodeLengths ( UChar*, Int32*, Int32, Int32 );
+
+
+
+/*-- states for decompression. --*/
+
+#define BZ_X_IDLE        1
+#define BZ_X_OUTPUT      2
+
+#define BZ_X_MAGIC_1     10
+#define BZ_X_MAGIC_2     11
+#define BZ_X_MAGIC_3     12
+#define BZ_X_MAGIC_4     13
+#define BZ_X_BLKHDR_1    14
+#define BZ_X_BLKHDR_2    15
+#define BZ_X_BLKHDR_3    16
+#define BZ_X_BLKHDR_4    17
+#define BZ_X_BLKHDR_5    18
+#define BZ_X_BLKHDR_6    19
+#define BZ_X_BCRC_1      20
+#define BZ_X_BCRC_2      21
+#define BZ_X_BCRC_3      22
+#define BZ_X_BCRC_4      23
+#define BZ_X_RANDBIT     24
+#define BZ_X_ORIGPTR_1   25
+#define BZ_X_ORIGPTR_2   26
+#define BZ_X_ORIGPTR_3   27
+#define BZ_X_MAPPING_1   28
+#define BZ_X_MAPPING_2   29
+#define BZ_X_SELECTOR_1  30
+#define BZ_X_SELECTOR_2  31
+#define BZ_X_SELECTOR_3  32
+#define BZ_X_CODING_1    33
+#define BZ_X_CODING_2    34
+#define BZ_X_CODING_3    35
+#define BZ_X_MTF_1       36
+#define BZ_X_MTF_2       37
+#define BZ_X_MTF_3       38
+#define BZ_X_MTF_4       39
+#define BZ_X_MTF_5       40
+#define BZ_X_MTF_6       41
+#define BZ_X_ENDHDR_2    42
+#define BZ_X_ENDHDR_3    43
+#define BZ_X_ENDHDR_4    44
+#define BZ_X_ENDHDR_5    45
+#define BZ_X_ENDHDR_6    46
+#define BZ_X_CCRC_1      47
+#define BZ_X_CCRC_2      48
+#define BZ_X_CCRC_3      49
+#define BZ_X_CCRC_4      50
+
+
+
+/*-- Constants for the fast MTF decoder. --*/
+
+#define MTFA_SIZE 4096
+#define MTFL_SIZE 16
+
+
+
+/*-- Structure holding all the decompression-side stuff. --*/
+
+typedef
+   struct {
+      /* pointer back to the struct bz_stream */
+      bz_stream* strm;
+
+      /* state indicator for this stream */
+      Int32    state;
+
+      /* for doing the final run-length decoding */
+      UChar    state_out_ch;
+      Int32    state_out_len;
+      Bool     blockRandomised;
+      BZ_RAND_DECLS;
+
+      /* the buffer for bit stream reading */
+      UInt32   bsBuff;
+      Int32    bsLive;
+
+      /* misc administratium */
+      Int32    blockSize100k;
+      Bool     smallDecompress;
+      Int32    currBlockNo;
+      Int32    verbosity;
+
+      /* for undoing the Burrows-Wheeler transform */
+      Int32    origPtr;
+      UInt32   tPos;
+      Int32    k0;
+      Int32    unzftab[256];
+      Int32    nblock_used;
+      Int32    cftab[257];
+      Int32    cftabCopy[257];
+
+      /* for undoing the Burrows-Wheeler transform (FAST) */
+      UInt32   *tt;
+
+      /* for undoing the Burrows-Wheeler transform (SMALL) */
+      UInt16   *ll16;
+      UChar    *ll4;
+
+      /* stored and calculated CRCs */
+      UInt32   storedBlockCRC;
+      UInt32   storedCombinedCRC;
+      UInt32   calculatedBlockCRC;
+      UInt32   calculatedCombinedCRC;
+
+      /* map of bytes used in block */
+      Int32    nInUse;
+      Bool     inUse[256];
+      Bool     inUse16[16];
+      UChar    seqToUnseq[256];
+
+      /* for decoding the MTF values */
+      UChar    mtfa   [MTFA_SIZE];
+      Int32    mtfbase[256 / MTFL_SIZE];
+      UChar    selector   [BZ_MAX_SELECTORS];
+      UChar    selectorMtf[BZ_MAX_SELECTORS];
+      UChar    len  [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+
+      Int32    limit  [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+      Int32    base   [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+      Int32    perm   [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+      Int32    minLens[BZ_N_GROUPS];
+
+      /* save area for scalars in the main decompress code */
+      Int32    save_i;
+      Int32    save_j;
+      Int32    save_t;
+      Int32    save_alphaSize;
+      Int32    save_nGroups;
+      Int32    save_nSelectors;
+      Int32    save_EOB;
+      Int32    save_groupNo;
+      Int32    save_groupPos;
+      Int32    save_nextSym;
+      Int32    save_nblockMAX;
+      Int32    save_nblock;
+      Int32    save_es;
+      Int32    save_N;
+      Int32    save_curr;
+      Int32    save_zt;
+      Int32    save_zn; 
+      Int32    save_zvec;
+      Int32    save_zj;
+      Int32    save_gSel;
+      Int32    save_gMinlen;
+      Int32*   save_gLimit;
+      Int32*   save_gBase;
+      Int32*   save_gPerm;
+
+   }
+   DState;
+
+
+
+/*-- Macros for decompression. --*/
+
+#define BZ_GET_FAST(cccc)                     \
+    s->tPos = s->tt[s->tPos];                 \
+    cccc = (UChar)(s->tPos & 0xff);           \
+    s->tPos >>= 8;
+
+#define BZ_GET_FAST_C(cccc)                   \
+    c_tPos = c_tt[c_tPos];                    \
+    cccc = (UChar)(c_tPos & 0xff);            \
+    c_tPos >>= 8;
+
+#define SET_LL4(i,n)                                          \
+   { if (((i) & 0x1) == 0)                                    \
+        s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0xf0) | (n); else    \
+        s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0x0f) | ((n) << 4);  \
+   }
+
+#define GET_LL4(i)                             \
+   ((((UInt32)(s->ll4[(i) >> 1])) >> (((i) << 2) & 0x4)) & 0xF)
+
+#define SET_LL(i,n)                          \
+   { s->ll16[i] = (UInt16)(n & 0x0000ffff);  \
+     SET_LL4(i, n >> 16);                    \
+   }
+
+#define GET_LL(i) \
+   (((UInt32)s->ll16[i]) | (GET_LL4(i) << 16))
+
+#define BZ_GET_SMALL(cccc)                            \
+      cccc = BZ2_indexIntoF ( s->tPos, s->cftab );    \
+      s->tPos = GET_LL(s->tPos);
+
+
+/*-- externs for decompression. --*/
+
+extern Int32 
+BZ2_indexIntoF ( Int32, Int32* );
+
+extern Int32 
+BZ2_decompress ( DState* );
+
+extern void 
+BZ2_hbCreateDecodeTables ( Int32*, Int32*, Int32*, UChar*,
+                           Int32,  Int32, Int32 );
+
+
+#endif
+
+
+/*-- BZ_NO_STDIO seems to make NULL disappear on some platforms. --*/
+
+#ifdef BZ_NO_STDIO
+#ifndef NULL
+#define NULL 0
+#endif
+#endif
+
+
+/*-------------------------------------------------------------*/
+/*--- end                                   bzlib_private.h ---*/
+/*-------------------------------------------------------------*/
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/bzmore b/contrib/vmap_extractor_v2/stormlib/bzip2/bzmore
new file mode 100644
index 00000000000..d3140434049
--- /dev/null
+++ b/contrib/vmap_extractor_v2/stormlib/bzip2/bzmore
@@ -0,0 +1,61 @@
+#!/bin/sh
+
+# Bzmore wrapped for bzip2, 
+# adapted from zmore by Philippe Troin  for Debian GNU/Linux.
+
+PATH="/usr/bin:$PATH"; export PATH
+
+prog=`echo $0 | sed 's|.*/||'`
+case "$prog" in
+	*less)	more=less	;;
+	*)	more=more       ;;
+esac
+
+if test "`echo -n a`" = "-n a"; then
+  # looks like a SysV system:
+  n1=''; n2='\c'
+else
+  n1='-n'; n2=''
+fi
+oldtty=`stty -g 2>/dev/null`
+if stty -cbreak 2>/dev/null; then
+  cb='cbreak'; ncb='-cbreak'
+else
+  # 'stty min 1' resets eof to ^a on both SunOS and SysV!
+  cb='min 1 -icanon'; ncb='icanon eof ^d'
+fi
+if test $? -eq 0 -a -n "$oldtty"; then
+   trap 'stty $oldtty 2>/dev/null; exit' 0 2 3 5 10 13 15
+else
+   trap 'stty $ncb echo 2>/dev/null; exit' 0 2 3 5 10 13 15
+fi
+
+if test $# = 0; then
+    if test -t 0; then
+	echo usage: $prog files...
+    else
+	bzip2 -cdfq | eval $more
+    fi
+else
+    FIRST=1
+    for FILE
+    do
+	if test $FIRST -eq 0; then
+		echo $n1 "--More--(Next file: $FILE)$n2"
+		stty $cb -echo 2>/dev/null
+		ANS=`dd bs=1 count=1 2>/dev/null` 
+		stty $ncb echo 2>/dev/null
+		echo " "
+		if test "$ANS" = 'e' -o "$ANS" = 'q'; then
+			exit
+		fi
+	fi
+	if test "$ANS" != 's'; then
+		echo "------> $FILE <------"
+		bzip2 -cdfq "$FILE" | eval $more
+	fi
+	if test -t; then
+		FIRST=0
+	fi
+    done
+fi
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/bzmore.1 b/contrib/vmap_extractor_v2/stormlib/bzip2/bzmore.1
new file mode 100644
index 00000000000..b437d3b031f
--- /dev/null
+++ b/contrib/vmap_extractor_v2/stormlib/bzip2/bzmore.1
@@ -0,0 +1,152 @@
+.\"Shamelessly copied from zmore.1 by Philippe Troin 
+.\"for Debian GNU/Linux
+.TH BZMORE 1
+.SH NAME
+bzmore, bzless \- file perusal filter for crt viewing of bzip2 compressed text
+.SH SYNOPSIS
+.B bzmore
+[ name ...  ]
+.br
+.B bzless
+[ name ...  ]
+.SH NOTE
+In the following description,
+.I bzless
+and
+.I less
+can be used interchangeably with
+.I bzmore
+and
+.I more.
+.SH DESCRIPTION
+.I  Bzmore
+is a filter which allows examination of compressed or plain text files
+one screenful at a time on a soft-copy terminal.
+.I bzmore
+works on files compressed with
+.I bzip2
+and also on uncompressed files.
+If a file does not exist,
+.I bzmore
+looks for a file of the same name with the addition of a .bz2 suffix.
+.PP
+.I Bzmore
+normally pauses after each screenful, printing --More--
+at the bottom of the screen.
+If the user then types a carriage return, one more line is displayed.
+If the user hits a space,
+another screenful is displayed.  Other possibilities are enumerated later.
+.PP
+.I Bzmore
+looks in the file
+.I /etc/termcap
+to determine terminal characteristics,
+and to determine the default window size.
+On a terminal capable of displaying 24 lines,
+the default window size is 22 lines.
+Other sequences which may be typed when
+.I bzmore
+pauses, and their effects, are as follows (\fIi\fP is an optional integer
+argument, defaulting to 1) :
+.PP
+.IP \fIi\|\fP
+display
+.I i
+more lines, (or another screenful if no argument is given)
+.PP
+.IP ^D
+display 11 more lines (a ``scroll'').
+If
+.I i
+is given, then the scroll size is set to \fIi\|\fP.
+.PP
+.IP d
+same as ^D (control-D)
+.PP
+.IP \fIi\|\fPz
+same as typing a space except that \fIi\|\fP, if present, becomes the new
+window size.  Note that the window size reverts back to the default at the
+end of the current file.
+.PP
+.IP \fIi\|\fPs
+skip \fIi\|\fP lines and print a screenful of lines
+.PP
+.IP \fIi\|\fPf
+skip \fIi\fP screenfuls and print a screenful of lines
+.PP
+.IP "q or Q"
+quit reading the current file; go on to the next (if any)
+.PP
+.IP "e or q"
+When the prompt --More--(Next file: 
+.IR file )
+is printed, this command causes bzmore to exit.
+.PP
+.IP s
+When the prompt --More--(Next file: 
+.IR file )
+is printed, this command causes bzmore to skip the next file and continue.
+.PP 
+.IP =
+Display the current line number.
+.PP
+.IP \fIi\|\fP/expr
+search for the \fIi\|\fP-th occurrence of the regular expression \fIexpr.\fP
+If the pattern is not found,
+.I bzmore
+goes on to the next file (if any).
+Otherwise, a screenful is displayed, starting two lines before the place
+where the expression was found.
+The user's erase and kill characters may be used to edit the regular
+expression.
+Erasing back past the first column cancels the search command.
+.PP
+.IP \fIi\|\fPn
+search for the \fIi\|\fP-th occurrence of the last regular expression entered.
+.PP
+.IP !command
+invoke a shell with \fIcommand\|\fP. 
+The character `!' in "command" are replaced with the
+previous shell command.  The sequence "\\!" is replaced by "!".
+.PP
+.IP ":q or :Q"
+quit reading the current file; go on to the next (if any)
+(same as q or Q).
+.PP
+.IP .
+(dot) repeat the previous command.
+.PP
+The commands take effect immediately, i.e., it is not necessary to
+type a carriage return.
+Up to the time when the command character itself is given,
+the user may hit the line kill character to cancel the numerical
+argument being formed.
+In addition, the user may hit the erase character to redisplay the
+--More-- message.
+.PP
+At any time when output is being sent to the terminal, the user can
+hit the quit key (normally control\-\\).
+.I Bzmore
+will stop sending output, and will display the usual --More--
+prompt.
+The user may then enter one of the above commands in the normal manner.
+Unfortunately, some output is lost when this is done, due to the
+fact that any characters waiting in the terminal's output queue
+are flushed when the quit signal occurs.
+.PP
+The terminal is set to
+.I noecho
+mode by this program so that the output can be continuous.
+What you type will thus not show on your terminal, except for the / and !
+commands.
+.PP
+If the standard output is not a teletype, then
+.I bzmore
+acts just like
+.I bzcat,
+except that a header is printed before each file.
+.SH FILES
+.DT
+/etc/termcap		Terminal data base
+.SH "SEE ALSO"
+more(1), less(1), bzip2(1), bzdiff(1), bzgrep(1)
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/compress.c b/contrib/vmap_extractor_v2/stormlib/bzip2/compress.c
new file mode 100644
index 00000000000..7e0c29155ab
--- /dev/null
+++ b/contrib/vmap_extractor_v2/stormlib/bzip2/compress.c
@@ -0,0 +1,716 @@
+
+/*-------------------------------------------------------------*/
+/*--- Compression machinery (not incl block sorting)        ---*/
+/*---                                            compress.c ---*/
+/*-------------------------------------------------------------*/
+
+/*--
+  This file is a part of bzip2 and/or libbzip2, a program and
+  library for lossless, block-sorting data compression.
+
+  Copyright (C) 1996-2005 Julian R Seward.  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+  2. The origin of this software must not be misrepresented; you must 
+     not claim that you wrote the original software.  If you use this 
+     software in a product, an acknowledgment in the product 
+     documentation would be appreciated but is not required.
+
+  3. Altered source versions must be plainly marked as such, and must
+     not be misrepresented as being the original software.
+
+  4. The name of the author may not be used to endorse or promote 
+     products derived from this software without specific prior written 
+     permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  Julian Seward, Cambridge, UK.
+  jseward@bzip.org
+  bzip2/libbzip2 version 1.0 of 21 March 2000
+
+  This program is based on (at least) the work of:
+     Mike Burrows
+     David Wheeler
+     Peter Fenwick
+     Alistair Moffat
+     Radford Neal
+     Ian H. Witten
+     Robert Sedgewick
+     Jon L. Bentley
+
+  For more information on these sources, see the manual.
+--*/
+
+/*--
+   CHANGES
+   ~~~~~~~
+   0.9.0 -- original version.
+
+   0.9.0a/b -- no changes in this file.
+
+   0.9.0c
+      * changed setting of nGroups in sendMTFValues() so as to 
+        do a bit better on small files
+--*/
+
+#include "bzlib_private.h"
+
+
+/*---------------------------------------------------*/
+/*--- Bit stream I/O                              ---*/
+/*---------------------------------------------------*/
+
+/*---------------------------------------------------*/
+void BZ2_bsInitWrite ( EState* s )
+{
+   s->bsLive = 0;
+   s->bsBuff = 0;
+}
+
+
+/*---------------------------------------------------*/
+static
+void bsFinishWrite ( EState* s )
+{
+   while (s->bsLive > 0) {
+      s->zbits[s->numZ] = (UChar)(s->bsBuff >> 24);
+      s->numZ++;
+      s->bsBuff <<= 8;
+      s->bsLive -= 8;
+   }
+}
+
+
+/*---------------------------------------------------*/
+#define bsNEEDW(nz)                           \
+{                                             \
+   while (s->bsLive >= 8) {                   \
+      s->zbits[s->numZ]                       \
+         = (UChar)(s->bsBuff >> 24);          \
+      s->numZ++;                              \
+      s->bsBuff <<= 8;                        \
+      s->bsLive -= 8;                         \
+   }                                          \
+}
+
+
+/*---------------------------------------------------*/
+static
+__inline__
+void bsW ( EState* s, Int32 n, UInt32 v )
+{
+   bsNEEDW ( n );
+   s->bsBuff |= (v << (32 - s->bsLive - n));
+   s->bsLive += n;
+}
+
+
+/*---------------------------------------------------*/
+static
+void bsPutUInt32 ( EState* s, UInt32 u )
+{
+   bsW ( s, 8, (u >> 24) & 0xffL );
+   bsW ( s, 8, (u >> 16) & 0xffL );
+   bsW ( s, 8, (u >>  8) & 0xffL );
+   bsW ( s, 8,  u        & 0xffL );
+}
+
+
+/*---------------------------------------------------*/
+static
+void bsPutUChar ( EState* s, UChar c )
+{
+   bsW( s, 8, (UInt32)c );
+}
+
+
+/*---------------------------------------------------*/
+/*--- The back end proper                         ---*/
+/*---------------------------------------------------*/
+
+/*---------------------------------------------------*/
+static
+void makeMaps_e ( EState* s )
+{
+   Int32 i;
+   s->nInUse = 0;
+   for (i = 0; i < 256; i++)
+      if (s->inUse[i]) {
+         s->unseqToSeq[i] = s->nInUse;
+         s->nInUse++;
+      }
+}
+
+
+/*---------------------------------------------------*/
+static
+void generateMTFValues ( EState* s )
+{
+   UChar   yy[256];
+   Int32   i, j;
+   Int32   zPend;
+   Int32   wr;
+   Int32   EOB;
+
+   /* 
+      After sorting (eg, here),
+         s->arr1 [ 0 .. s->nblock-1 ] holds sorted order,
+         and
+         ((UChar*)s->arr2) [ 0 .. s->nblock-1 ] 
+         holds the original block data.
+
+      The first thing to do is generate the MTF values,
+      and put them in
+         ((UInt16*)s->arr1) [ 0 .. s->nblock-1 ].
+      Because there are strictly fewer or equal MTF values
+      than block values, ptr values in this area are overwritten
+      with MTF values only when they are no longer needed.
+
+      The final compressed bitstream is generated into the
+      area starting at
+         (UChar*) (&((UChar*)s->arr2)[s->nblock])
+
+      These storage aliases are set up in bzCompressInit(),
+      except for the last one, which is arranged in 
+      compressBlock().
+   */
+   UInt32* ptr   = s->ptr;
+   UChar* block  = s->block;
+   UInt16* mtfv  = s->mtfv;
+
+   makeMaps_e ( s );
+   EOB = s->nInUse+1;
+
+   for (i = 0; i <= EOB; i++) s->mtfFreq[i] = 0;
+
+   wr = 0;
+   zPend = 0;
+   for (i = 0; i < s->nInUse; i++) yy[i] = (UChar) i;
+
+   for (i = 0; i < s->nblock; i++) {
+      UChar ll_i;
+      AssertD ( wr <= i, "generateMTFValues(1)" );
+      j = ptr[i]-1; if (j < 0) j += s->nblock;
+      ll_i = s->unseqToSeq[block[j]];
+      AssertD ( ll_i < s->nInUse, "generateMTFValues(2a)" );
+
+      if (yy[0] == ll_i) { 
+         zPend++;
+      } else {
+
+         if (zPend > 0) {
+            zPend--;
+            while (True) {
+               if (zPend & 1) {
+                  mtfv[wr] = BZ_RUNB; wr++; 
+                  s->mtfFreq[BZ_RUNB]++; 
+               } else {
+                  mtfv[wr] = BZ_RUNA; wr++; 
+                  s->mtfFreq[BZ_RUNA]++; 
+               }
+               if (zPend < 2) break;
+               zPend = (zPend - 2) / 2;
+            };
+            zPend = 0;
+         }
+         {
+            register UChar  rtmp;
+            register UChar* ryy_j;
+            register UChar  rll_i;
+            rtmp  = yy[1];
+            yy[1] = yy[0];
+            ryy_j = &(yy[1]);
+            rll_i = ll_i;
+            while ( rll_i != rtmp ) {
+               register UChar rtmp2;
+               ryy_j++;
+               rtmp2  = rtmp;
+               rtmp   = *ryy_j;
+               *ryy_j = rtmp2;
+            };
+            yy[0] = rtmp;
+            j = ryy_j - &(yy[0]);
+            mtfv[wr] = j+1; wr++; s->mtfFreq[j+1]++;
+         }
+
+      }
+   }
+
+   if (zPend > 0) {
+      zPend--;
+      while (True) {
+         if (zPend & 1) {
+            mtfv[wr] = BZ_RUNB; wr++; 
+            s->mtfFreq[BZ_RUNB]++; 
+         } else {
+            mtfv[wr] = BZ_RUNA; wr++; 
+            s->mtfFreq[BZ_RUNA]++; 
+         }
+         if (zPend < 2) break;
+         zPend = (zPend - 2) / 2;
+      };
+      zPend = 0;
+   }
+
+   mtfv[wr] = EOB; wr++; s->mtfFreq[EOB]++;
+
+   s->nMTF = wr;
+}
+
+
+/*---------------------------------------------------*/
+#define BZ_LESSER_ICOST  0
+#define BZ_GREATER_ICOST 15
+
+static
+void sendMTFValues ( EState* s )
+{
+   Int32 v, t, i, j, gs, ge, totc, bt, bc, iter;
+   Int32 nSelectors, alphaSize, minLen, maxLen, selCtr;
+   Int32 nGroups, nBytes;
+
+   /*--
+   UChar  len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+   is a global since the decoder also needs it.
+
+   Int32  code[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+   Int32  rfreq[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+   are also globals only used in this proc.
+   Made global to keep stack frame size small.
+   --*/
+
+
+   UInt16 cost[BZ_N_GROUPS];
+   Int32  fave[BZ_N_GROUPS];
+
+   UInt16* mtfv = s->mtfv;
+
+   if (s->verbosity >= 3)
+      VPrintf3( "      %d in block, %d after MTF & 1-2 coding, "
+                "%d+2 syms in use\n", 
+                s->nblock, s->nMTF, s->nInUse );
+
+   alphaSize = s->nInUse+2;
+   for (t = 0; t < BZ_N_GROUPS; t++)
+      for (v = 0; v < alphaSize; v++)
+         s->len[t][v] = BZ_GREATER_ICOST;
+
+   /*--- Decide how many coding tables to use ---*/
+   AssertH ( s->nMTF > 0, 3001 );
+   if (s->nMTF < 200)  nGroups = 2; else
+   if (s->nMTF < 600)  nGroups = 3; else
+   if (s->nMTF < 1200) nGroups = 4; else
+   if (s->nMTF < 2400) nGroups = 5; else
+                       nGroups = 6;
+
+   /*--- Generate an initial set of coding tables ---*/
+   { 
+      Int32 nPart, remF, tFreq, aFreq;
+
+      nPart = nGroups;
+      remF  = s->nMTF;
+      gs = 0;
+      while (nPart > 0) {
+         tFreq = remF / nPart;
+         ge = gs-1;
+         aFreq = 0;
+         while (aFreq < tFreq && ge < alphaSize-1) {
+            ge++;
+            aFreq += s->mtfFreq[ge];
+         }
+
+         if (ge > gs 
+             && nPart != nGroups && nPart != 1 
+             && ((nGroups-nPart) % 2 == 1)) {
+            aFreq -= s->mtfFreq[ge];
+            ge--;
+         }
+
+         if (s->verbosity >= 3)
+            VPrintf5( "      initial group %d, [%d .. %d], "
+                      "has %d syms (%4.1f%%)\n",
+                      nPart, gs, ge, aFreq, 
+                      (100.0 * (float)aFreq) / (float)(s->nMTF) );
+ 
+         for (v = 0; v < alphaSize; v++)
+            if (v >= gs && v <= ge) 
+               s->len[nPart-1][v] = BZ_LESSER_ICOST; else
+               s->len[nPart-1][v] = BZ_GREATER_ICOST;
+ 
+         nPart--;
+         gs = ge+1;
+         remF -= aFreq;
+      }
+   }
+
+   /*--- 
+      Iterate up to BZ_N_ITERS times to improve the tables.
+   ---*/
+   for (iter = 0; iter < BZ_N_ITERS; iter++) {
+
+      for (t = 0; t < nGroups; t++) fave[t] = 0;
+
+      for (t = 0; t < nGroups; t++)
+         for (v = 0; v < alphaSize; v++)
+            s->rfreq[t][v] = 0;
+
+      /*---
+        Set up an auxiliary length table which is used to fast-track
+	the common case (nGroups == 6). 
+      ---*/
+      if (nGroups == 6) {
+         for (v = 0; v < alphaSize; v++) {
+            s->len_pack[v][0] = (s->len[1][v] << 16) | s->len[0][v];
+            s->len_pack[v][1] = (s->len[3][v] << 16) | s->len[2][v];
+            s->len_pack[v][2] = (s->len[5][v] << 16) | s->len[4][v];
+	 }
+      }
+
+      nSelectors = 0;
+      totc = 0;
+      gs = 0;
+      while (True) {
+
+         /*--- Set group start & end marks. --*/
+         if (gs >= s->nMTF) break;
+         ge = gs + BZ_G_SIZE - 1; 
+         if (ge >= s->nMTF) ge = s->nMTF-1;
+
+         /*-- 
+            Calculate the cost of this group as coded
+            by each of the coding tables.
+         --*/
+         for (t = 0; t < nGroups; t++) cost[t] = 0;
+
+         if (nGroups == 6 && 50 == ge-gs+1) {
+            /*--- fast track the common case ---*/
+            register UInt32 cost01, cost23, cost45;
+            register UInt16 icv;
+            cost01 = cost23 = cost45 = 0;
+
+#           define BZ_ITER(nn)                \
+               icv = mtfv[gs+(nn)];           \
+               cost01 += s->len_pack[icv][0]; \
+               cost23 += s->len_pack[icv][1]; \
+               cost45 += s->len_pack[icv][2]; \
+
+            BZ_ITER(0);  BZ_ITER(1);  BZ_ITER(2);  BZ_ITER(3);  BZ_ITER(4);
+            BZ_ITER(5);  BZ_ITER(6);  BZ_ITER(7);  BZ_ITER(8);  BZ_ITER(9);
+            BZ_ITER(10); BZ_ITER(11); BZ_ITER(12); BZ_ITER(13); BZ_ITER(14);
+            BZ_ITER(15); BZ_ITER(16); BZ_ITER(17); BZ_ITER(18); BZ_ITER(19);
+            BZ_ITER(20); BZ_ITER(21); BZ_ITER(22); BZ_ITER(23); BZ_ITER(24);
+            BZ_ITER(25); BZ_ITER(26); BZ_ITER(27); BZ_ITER(28); BZ_ITER(29);
+            BZ_ITER(30); BZ_ITER(31); BZ_ITER(32); BZ_ITER(33); BZ_ITER(34);
+            BZ_ITER(35); BZ_ITER(36); BZ_ITER(37); BZ_ITER(38); BZ_ITER(39);
+            BZ_ITER(40); BZ_ITER(41); BZ_ITER(42); BZ_ITER(43); BZ_ITER(44);
+            BZ_ITER(45); BZ_ITER(46); BZ_ITER(47); BZ_ITER(48); BZ_ITER(49);
+
+#           undef BZ_ITER
+
+            cost[0] = cost01 & 0xffff; cost[1] = cost01 >> 16;
+            cost[2] = cost23 & 0xffff; cost[3] = cost23 >> 16;
+            cost[4] = cost45 & 0xffff; cost[5] = cost45 >> 16;
+
+         } else {
+	    /*--- slow version which correctly handles all situations ---*/
+            for (i = gs; i <= ge; i++) { 
+               UInt16 icv = mtfv[i];
+               for (t = 0; t < nGroups; t++) cost[t] += s->len[t][icv];
+            }
+         }
+ 
+         /*-- 
+            Find the coding table which is best for this group,
+            and record its identity in the selector table.
+         --*/
+         bc = 999999999; bt = -1;
+         for (t = 0; t < nGroups; t++)
+            if (cost[t] < bc) { bc = cost[t]; bt = t; };
+         totc += bc;
+         fave[bt]++;
+         s->selector[nSelectors] = bt;
+         nSelectors++;
+
+         /*-- 
+            Increment the symbol frequencies for the selected table.
+          --*/
+         if (nGroups == 6 && 50 == ge-gs+1) {
+            /*--- fast track the common case ---*/
+
+#           define BZ_ITUR(nn) s->rfreq[bt][ mtfv[gs+(nn)] ]++
+
+            BZ_ITUR(0);  BZ_ITUR(1);  BZ_ITUR(2);  BZ_ITUR(3);  BZ_ITUR(4);
+            BZ_ITUR(5);  BZ_ITUR(6);  BZ_ITUR(7);  BZ_ITUR(8);  BZ_ITUR(9);
+            BZ_ITUR(10); BZ_ITUR(11); BZ_ITUR(12); BZ_ITUR(13); BZ_ITUR(14);
+            BZ_ITUR(15); BZ_ITUR(16); BZ_ITUR(17); BZ_ITUR(18); BZ_ITUR(19);
+            BZ_ITUR(20); BZ_ITUR(21); BZ_ITUR(22); BZ_ITUR(23); BZ_ITUR(24);
+            BZ_ITUR(25); BZ_ITUR(26); BZ_ITUR(27); BZ_ITUR(28); BZ_ITUR(29);
+            BZ_ITUR(30); BZ_ITUR(31); BZ_ITUR(32); BZ_ITUR(33); BZ_ITUR(34);
+            BZ_ITUR(35); BZ_ITUR(36); BZ_ITUR(37); BZ_ITUR(38); BZ_ITUR(39);
+            BZ_ITUR(40); BZ_ITUR(41); BZ_ITUR(42); BZ_ITUR(43); BZ_ITUR(44);
+            BZ_ITUR(45); BZ_ITUR(46); BZ_ITUR(47); BZ_ITUR(48); BZ_ITUR(49);
+
+#           undef BZ_ITUR
+
+         } else {
+	    /*--- slow version which correctly handles all situations ---*/
+            for (i = gs; i <= ge; i++)
+               s->rfreq[bt][ mtfv[i] ]++;
+         }
+
+         gs = ge+1;
+      }
+      if (s->verbosity >= 3) {
+         VPrintf2 ( "      pass %d: size is %d, grp uses are ", 
+                   iter+1, totc/8 );
+         for (t = 0; t < nGroups; t++)
+            VPrintf1 ( "%d ", fave[t] );
+         VPrintf0 ( "\n" );
+      }
+
+      /*--
+        Recompute the tables based on the accumulated frequencies.
+      --*/
+      /* maxLen was changed from 20 to 17 in bzip2-1.0.3.  See 
+         comment in huffman.c for details. */
+      for (t = 0; t < nGroups; t++)
+         BZ2_hbMakeCodeLengths ( &(s->len[t][0]), &(s->rfreq[t][0]), 
+                                 alphaSize, 17 /*20*/ );
+   }
+
+
+   AssertH( nGroups < 8, 3002 );
+   AssertH( nSelectors < 32768 &&
+            nSelectors <= (2 + (900000 / BZ_G_SIZE)),
+            3003 );
+
+
+   /*--- Compute MTF values for the selectors. ---*/
+   {
+      UChar pos[BZ_N_GROUPS], ll_i, tmp2, tmp;
+      for (i = 0; i < nGroups; i++) pos[i] = i;
+      for (i = 0; i < nSelectors; i++) {
+         ll_i = s->selector[i];
+         j = 0;
+         tmp = pos[j];
+         while ( ll_i != tmp ) {
+            j++;
+            tmp2 = tmp;
+            tmp = pos[j];
+            pos[j] = tmp2;
+         };
+         pos[0] = tmp;
+         s->selectorMtf[i] = j;
+      }
+   };
+
+   /*--- Assign actual codes for the tables. --*/
+   for (t = 0; t < nGroups; t++) {
+      minLen = 32;
+      maxLen = 0;
+      for (i = 0; i < alphaSize; i++) {
+         if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
+         if (s->len[t][i] < minLen) minLen = s->len[t][i];
+      }
+      AssertH ( !(maxLen > 17 /*20*/ ), 3004 );
+      AssertH ( !(minLen < 1),  3005 );
+      BZ2_hbAssignCodes ( &(s->code[t][0]), &(s->len[t][0]), 
+                          minLen, maxLen, alphaSize );
+   }
+
+   /*--- Transmit the mapping table. ---*/
+   { 
+      Bool inUse16[16];
+      for (i = 0; i < 16; i++) {
+          inUse16[i] = False;
+          for (j = 0; j < 16; j++)
+             if (s->inUse[i * 16 + j]) inUse16[i] = True;
+      }
+     
+      nBytes = s->numZ;
+      for (i = 0; i < 16; i++)
+         if (inUse16[i]) bsW(s,1,1); else bsW(s,1,0);
+
+      for (i = 0; i < 16; i++)
+         if (inUse16[i])
+            for (j = 0; j < 16; j++) {
+               if (s->inUse[i * 16 + j]) bsW(s,1,1); else bsW(s,1,0);
+            }
+
+      if (s->verbosity >= 3) 
+         VPrintf1( "      bytes: mapping %d, ", s->numZ-nBytes );
+   }
+
+   /*--- Now the selectors. ---*/
+   nBytes = s->numZ;
+   bsW ( s, 3, nGroups );
+   bsW ( s, 15, nSelectors );
+   for (i = 0; i < nSelectors; i++) { 
+      for (j = 0; j < s->selectorMtf[i]; j++) bsW(s,1,1);
+      bsW(s,1,0);
+   }
+   if (s->verbosity >= 3)
+      VPrintf1( "selectors %d, ", s->numZ-nBytes );
+
+   /*--- Now the coding tables. ---*/
+   nBytes = s->numZ;
+
+   for (t = 0; t < nGroups; t++) {
+      Int32 curr = s->len[t][0];
+      bsW ( s, 5, curr );
+      for (i = 0; i < alphaSize; i++) {
+         while (curr < s->len[t][i]) { bsW(s,2,2); curr++; /* 10 */ };
+         while (curr > s->len[t][i]) { bsW(s,2,3); curr--; /* 11 */ };
+         bsW ( s, 1, 0 );
+      }
+   }
+
+   if (s->verbosity >= 3)
+      VPrintf1 ( "code lengths %d, ", s->numZ-nBytes );
+
+   /*--- And finally, the block data proper ---*/
+   nBytes = s->numZ;
+   selCtr = 0;
+   gs = 0;
+   while (True) {
+      if (gs >= s->nMTF) break;
+      ge = gs + BZ_G_SIZE - 1; 
+      if (ge >= s->nMTF) ge = s->nMTF-1;
+      AssertH ( s->selector[selCtr] < nGroups, 3006 );
+
+      if (nGroups == 6 && 50 == ge-gs+1) {
+            /*--- fast track the common case ---*/
+            UInt16 mtfv_i;
+            UChar* s_len_sel_selCtr 
+               = &(s->len[s->selector[selCtr]][0]);
+            Int32* s_code_sel_selCtr
+               = &(s->code[s->selector[selCtr]][0]);
+
+#           define BZ_ITAH(nn)                      \
+               mtfv_i = mtfv[gs+(nn)];              \
+               bsW ( s,                             \
+                     s_len_sel_selCtr[mtfv_i],      \
+                     s_code_sel_selCtr[mtfv_i] )
+
+            BZ_ITAH(0);  BZ_ITAH(1);  BZ_ITAH(2);  BZ_ITAH(3);  BZ_ITAH(4);
+            BZ_ITAH(5);  BZ_ITAH(6);  BZ_ITAH(7);  BZ_ITAH(8);  BZ_ITAH(9);
+            BZ_ITAH(10); BZ_ITAH(11); BZ_ITAH(12); BZ_ITAH(13); BZ_ITAH(14);
+            BZ_ITAH(15); BZ_ITAH(16); BZ_ITAH(17); BZ_ITAH(18); BZ_ITAH(19);
+            BZ_ITAH(20); BZ_ITAH(21); BZ_ITAH(22); BZ_ITAH(23); BZ_ITAH(24);
+            BZ_ITAH(25); BZ_ITAH(26); BZ_ITAH(27); BZ_ITAH(28); BZ_ITAH(29);
+            BZ_ITAH(30); BZ_ITAH(31); BZ_ITAH(32); BZ_ITAH(33); BZ_ITAH(34);
+            BZ_ITAH(35); BZ_ITAH(36); BZ_ITAH(37); BZ_ITAH(38); BZ_ITAH(39);
+            BZ_ITAH(40); BZ_ITAH(41); BZ_ITAH(42); BZ_ITAH(43); BZ_ITAH(44);
+            BZ_ITAH(45); BZ_ITAH(46); BZ_ITAH(47); BZ_ITAH(48); BZ_ITAH(49);
+
+#           undef BZ_ITAH
+
+      } else {
+	 /*--- slow version which correctly handles all situations ---*/
+         for (i = gs; i <= ge; i++) {
+            bsW ( s, 
+                  s->len  [s->selector[selCtr]] [mtfv[i]],
+                  s->code [s->selector[selCtr]] [mtfv[i]] );
+         }
+      }
+
+
+      gs = ge+1;
+      selCtr++;
+   }
+   AssertH( selCtr == nSelectors, 3007 );
+
+   if (s->verbosity >= 3)
+      VPrintf1( "codes %d\n", s->numZ-nBytes );
+}
+
+
+/*---------------------------------------------------*/
+void BZ2_compressBlock ( EState* s, Bool is_last_block )
+{
+   if (s->nblock > 0) {
+
+      BZ_FINALISE_CRC ( s->blockCRC );
+      s->combinedCRC = (s->combinedCRC << 1) | (s->combinedCRC >> 31);
+      s->combinedCRC ^= s->blockCRC;
+      if (s->blockNo > 1) s->numZ = 0;
+
+      if (s->verbosity >= 2)
+         VPrintf4( "    block %d: crc = 0x%08x, "
+                   "combined CRC = 0x%08x, size = %d\n",
+                   s->blockNo, s->blockCRC, s->combinedCRC, s->nblock );
+
+      BZ2_blockSort ( s );
+   }
+
+   s->zbits = (UChar*) (&((UChar*)s->arr2)[s->nblock]);
+
+   /*-- If this is the first block, create the stream header. --*/
+   if (s->blockNo == 1) {
+      BZ2_bsInitWrite ( s );
+      bsPutUChar ( s, BZ_HDR_B );
+      bsPutUChar ( s, BZ_HDR_Z );
+      bsPutUChar ( s, BZ_HDR_h );
+      bsPutUChar ( s, (UChar)(BZ_HDR_0 + s->blockSize100k) );
+   }
+
+   if (s->nblock > 0) {
+
+      bsPutUChar ( s, 0x31 ); bsPutUChar ( s, 0x41 );
+      bsPutUChar ( s, 0x59 ); bsPutUChar ( s, 0x26 );
+      bsPutUChar ( s, 0x53 ); bsPutUChar ( s, 0x59 );
+
+      /*-- Now the block's CRC, so it is in a known place. --*/
+      bsPutUInt32 ( s, s->blockCRC );
+
+      /*-- 
+         Now a single bit indicating (non-)randomisation. 
+         As of version 0.9.5, we use a better sorting algorithm
+         which makes randomisation unnecessary.  So always set
+         the randomised bit to 'no'.  Of course, the decoder
+         still needs to be able to handle randomised blocks
+         so as to maintain backwards compatibility with
+         older versions of bzip2.
+      --*/
+      bsW(s,1,0);
+
+      bsW ( s, 24, s->origPtr );
+      generateMTFValues ( s );
+      sendMTFValues ( s );
+   }
+
+
+   /*-- If this is the last block, add the stream trailer. --*/
+   if (is_last_block) {
+
+      bsPutUChar ( s, 0x17 ); bsPutUChar ( s, 0x72 );
+      bsPutUChar ( s, 0x45 ); bsPutUChar ( s, 0x38 );
+      bsPutUChar ( s, 0x50 ); bsPutUChar ( s, 0x90 );
+      bsPutUInt32 ( s, s->combinedCRC );
+      if (s->verbosity >= 2)
+         VPrintf1( "    final combined CRC = 0x%08x\n   ", s->combinedCRC );
+      bsFinishWrite ( s );
+   }
+}
+
+
+/*-------------------------------------------------------------*/
+/*--- end                                        compress.c ---*/
+/*-------------------------------------------------------------*/
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/crctable.c b/contrib/vmap_extractor_v2/stormlib/bzip2/crctable.c
new file mode 100644
index 00000000000..b6dadfc62f2
--- /dev/null
+++ b/contrib/vmap_extractor_v2/stormlib/bzip2/crctable.c
@@ -0,0 +1,144 @@
+
+/*-------------------------------------------------------------*/
+/*--- Table for doing CRCs                                  ---*/
+/*---                                            crctable.c ---*/
+/*-------------------------------------------------------------*/
+
+/*--
+  This file is a part of bzip2 and/or libbzip2, a program and
+  library for lossless, block-sorting data compression.
+
+  Copyright (C) 1996-2005 Julian R Seward.  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+  2. The origin of this software must not be misrepresented; you must 
+     not claim that you wrote the original software.  If you use this 
+     software in a product, an acknowledgment in the product 
+     documentation would be appreciated but is not required.
+
+  3. Altered source versions must be plainly marked as such, and must
+     not be misrepresented as being the original software.
+
+  4. The name of the author may not be used to endorse or promote 
+     products derived from this software without specific prior written 
+     permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  Julian Seward, Cambridge, UK.
+  jseward@bzip.org
+  bzip2/libbzip2 version 1.0 of 21 March 2000
+
+  This program is based on (at least) the work of:
+     Mike Burrows
+     David Wheeler
+     Peter Fenwick
+     Alistair Moffat
+     Radford Neal
+     Ian H. Witten
+     Robert Sedgewick
+     Jon L. Bentley
+
+  For more information on these sources, see the manual.
+--*/
+
+
+#include "bzlib_private.h"
+
+/*--
+  I think this is an implementation of the AUTODIN-II,
+  Ethernet & FDDI 32-bit CRC standard.  Vaguely derived
+  from code by Rob Warnock, in Section 51 of the
+  comp.compression FAQ.
+--*/
+
+UInt32 BZ2_crc32Table[256] = {
+
+   /*-- Ugly, innit? --*/
+
+   0x00000000L, 0x04c11db7L, 0x09823b6eL, 0x0d4326d9L,
+   0x130476dcL, 0x17c56b6bL, 0x1a864db2L, 0x1e475005L,
+   0x2608edb8L, 0x22c9f00fL, 0x2f8ad6d6L, 0x2b4bcb61L,
+   0x350c9b64L, 0x31cd86d3L, 0x3c8ea00aL, 0x384fbdbdL,
+   0x4c11db70L, 0x48d0c6c7L, 0x4593e01eL, 0x4152fda9L,
+   0x5f15adacL, 0x5bd4b01bL, 0x569796c2L, 0x52568b75L,
+   0x6a1936c8L, 0x6ed82b7fL, 0x639b0da6L, 0x675a1011L,
+   0x791d4014L, 0x7ddc5da3L, 0x709f7b7aL, 0x745e66cdL,
+   0x9823b6e0L, 0x9ce2ab57L, 0x91a18d8eL, 0x95609039L,
+   0x8b27c03cL, 0x8fe6dd8bL, 0x82a5fb52L, 0x8664e6e5L,
+   0xbe2b5b58L, 0xbaea46efL, 0xb7a96036L, 0xb3687d81L,
+   0xad2f2d84L, 0xa9ee3033L, 0xa4ad16eaL, 0xa06c0b5dL,
+   0xd4326d90L, 0xd0f37027L, 0xddb056feL, 0xd9714b49L,
+   0xc7361b4cL, 0xc3f706fbL, 0xceb42022L, 0xca753d95L,
+   0xf23a8028L, 0xf6fb9d9fL, 0xfbb8bb46L, 0xff79a6f1L,
+   0xe13ef6f4L, 0xe5ffeb43L, 0xe8bccd9aL, 0xec7dd02dL,
+   0x34867077L, 0x30476dc0L, 0x3d044b19L, 0x39c556aeL,
+   0x278206abL, 0x23431b1cL, 0x2e003dc5L, 0x2ac12072L,
+   0x128e9dcfL, 0x164f8078L, 0x1b0ca6a1L, 0x1fcdbb16L,
+   0x018aeb13L, 0x054bf6a4L, 0x0808d07dL, 0x0cc9cdcaL,
+   0x7897ab07L, 0x7c56b6b0L, 0x71159069L, 0x75d48ddeL,
+   0x6b93dddbL, 0x6f52c06cL, 0x6211e6b5L, 0x66d0fb02L,
+   0x5e9f46bfL, 0x5a5e5b08L, 0x571d7dd1L, 0x53dc6066L,
+   0x4d9b3063L, 0x495a2dd4L, 0x44190b0dL, 0x40d816baL,
+   0xaca5c697L, 0xa864db20L, 0xa527fdf9L, 0xa1e6e04eL,
+   0xbfa1b04bL, 0xbb60adfcL, 0xb6238b25L, 0xb2e29692L,
+   0x8aad2b2fL, 0x8e6c3698L, 0x832f1041L, 0x87ee0df6L,
+   0x99a95df3L, 0x9d684044L, 0x902b669dL, 0x94ea7b2aL,
+   0xe0b41de7L, 0xe4750050L, 0xe9362689L, 0xedf73b3eL,
+   0xf3b06b3bL, 0xf771768cL, 0xfa325055L, 0xfef34de2L,
+   0xc6bcf05fL, 0xc27dede8L, 0xcf3ecb31L, 0xcbffd686L,
+   0xd5b88683L, 0xd1799b34L, 0xdc3abdedL, 0xd8fba05aL,
+   0x690ce0eeL, 0x6dcdfd59L, 0x608edb80L, 0x644fc637L,
+   0x7a089632L, 0x7ec98b85L, 0x738aad5cL, 0x774bb0ebL,
+   0x4f040d56L, 0x4bc510e1L, 0x46863638L, 0x42472b8fL,
+   0x5c007b8aL, 0x58c1663dL, 0x558240e4L, 0x51435d53L,
+   0x251d3b9eL, 0x21dc2629L, 0x2c9f00f0L, 0x285e1d47L,
+   0x36194d42L, 0x32d850f5L, 0x3f9b762cL, 0x3b5a6b9bL,
+   0x0315d626L, 0x07d4cb91L, 0x0a97ed48L, 0x0e56f0ffL,
+   0x1011a0faL, 0x14d0bd4dL, 0x19939b94L, 0x1d528623L,
+   0xf12f560eL, 0xf5ee4bb9L, 0xf8ad6d60L, 0xfc6c70d7L,
+   0xe22b20d2L, 0xe6ea3d65L, 0xeba91bbcL, 0xef68060bL,
+   0xd727bbb6L, 0xd3e6a601L, 0xdea580d8L, 0xda649d6fL,
+   0xc423cd6aL, 0xc0e2d0ddL, 0xcda1f604L, 0xc960ebb3L,
+   0xbd3e8d7eL, 0xb9ff90c9L, 0xb4bcb610L, 0xb07daba7L,
+   0xae3afba2L, 0xaafbe615L, 0xa7b8c0ccL, 0xa379dd7bL,
+   0x9b3660c6L, 0x9ff77d71L, 0x92b45ba8L, 0x9675461fL,
+   0x8832161aL, 0x8cf30badL, 0x81b02d74L, 0x857130c3L,
+   0x5d8a9099L, 0x594b8d2eL, 0x5408abf7L, 0x50c9b640L,
+   0x4e8ee645L, 0x4a4ffbf2L, 0x470cdd2bL, 0x43cdc09cL,
+   0x7b827d21L, 0x7f436096L, 0x7200464fL, 0x76c15bf8L,
+   0x68860bfdL, 0x6c47164aL, 0x61043093L, 0x65c52d24L,
+   0x119b4be9L, 0x155a565eL, 0x18197087L, 0x1cd86d30L,
+   0x029f3d35L, 0x065e2082L, 0x0b1d065bL, 0x0fdc1becL,
+   0x3793a651L, 0x3352bbe6L, 0x3e119d3fL, 0x3ad08088L,
+   0x2497d08dL, 0x2056cd3aL, 0x2d15ebe3L, 0x29d4f654L,
+   0xc5a92679L, 0xc1683bceL, 0xcc2b1d17L, 0xc8ea00a0L,
+   0xd6ad50a5L, 0xd26c4d12L, 0xdf2f6bcbL, 0xdbee767cL,
+   0xe3a1cbc1L, 0xe760d676L, 0xea23f0afL, 0xeee2ed18L,
+   0xf0a5bd1dL, 0xf464a0aaL, 0xf9278673L, 0xfde69bc4L,
+   0x89b8fd09L, 0x8d79e0beL, 0x803ac667L, 0x84fbdbd0L,
+   0x9abc8bd5L, 0x9e7d9662L, 0x933eb0bbL, 0x97ffad0cL,
+   0xafb010b1L, 0xab710d06L, 0xa6322bdfL, 0xa2f33668L,
+   0xbcb4666dL, 0xb8757bdaL, 0xb5365d03L, 0xb1f740b4L
+};
+
+
+/*-------------------------------------------------------------*/
+/*--- end                                        crctable.c ---*/
+/*-------------------------------------------------------------*/
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/decompress.c b/contrib/vmap_extractor_v2/stormlib/bzip2/decompress.c
new file mode 100644
index 00000000000..81c3d2cc3f4
--- /dev/null
+++ b/contrib/vmap_extractor_v2/stormlib/bzip2/decompress.c
@@ -0,0 +1,666 @@
+
+/*-------------------------------------------------------------*/
+/*--- Decompression machinery                               ---*/
+/*---                                          decompress.c ---*/
+/*-------------------------------------------------------------*/
+
+/*--
+  This file is a part of bzip2 and/or libbzip2, a program and
+  library for lossless, block-sorting data compression.
+
+  Copyright (C) 1996-2005 Julian R Seward.  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+  2. The origin of this software must not be misrepresented; you must 
+     not claim that you wrote the original software.  If you use this 
+     software in a product, an acknowledgment in the product 
+     documentation would be appreciated but is not required.
+
+  3. Altered source versions must be plainly marked as such, and must
+     not be misrepresented as being the original software.
+
+  4. The name of the author may not be used to endorse or promote 
+     products derived from this software without specific prior written 
+     permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  Julian Seward, Cambridge, UK.
+  jseward@bzip.org
+  bzip2/libbzip2 version 1.0 of 21 March 2000
+
+  This program is based on (at least) the work of:
+     Mike Burrows
+     David Wheeler
+     Peter Fenwick
+     Alistair Moffat
+     Radford Neal
+     Ian H. Witten
+     Robert Sedgewick
+     Jon L. Bentley
+
+  For more information on these sources, see the manual.
+--*/
+
+
+#include "bzlib_private.h"
+
+
+/*---------------------------------------------------*/
+static
+void makeMaps_d ( DState* s )
+{
+   Int32 i;
+   s->nInUse = 0;
+   for (i = 0; i < 256; i++)
+      if (s->inUse[i]) {
+         s->seqToUnseq[s->nInUse] = i;
+         s->nInUse++;
+      }
+}
+
+
+/*---------------------------------------------------*/
+#define RETURN(rrr)                               \
+   { retVal = rrr; goto save_state_and_return; };
+
+#define GET_BITS(lll,vvv,nnn)                     \
+   case lll: s->state = lll;                      \
+   while (True) {                                 \
+      if (s->bsLive >= nnn) {                     \
+         UInt32 v;                                \
+         v = (s->bsBuff >>                        \
+             (s->bsLive-nnn)) & ((1 << nnn)-1);   \
+         s->bsLive -= nnn;                        \
+         vvv = v;                                 \
+         break;                                   \
+      }                                           \
+      if (s->strm->avail_in == 0) RETURN(BZ_OK);  \
+      s->bsBuff                                   \
+         = (s->bsBuff << 8) |                     \
+           ((UInt32)                              \
+              (*((UChar*)(s->strm->next_in))));   \
+      s->bsLive += 8;                             \
+      s->strm->next_in++;                         \
+      s->strm->avail_in--;                        \
+      s->strm->total_in_lo32++;                   \
+      if (s->strm->total_in_lo32 == 0)            \
+         s->strm->total_in_hi32++;                \
+   }
+
+#define GET_UCHAR(lll,uuu)                        \
+   GET_BITS(lll,uuu,8)
+
+#define GET_BIT(lll,uuu)                          \
+   GET_BITS(lll,uuu,1)
+
+/*---------------------------------------------------*/
+#define GET_MTF_VAL(label1,label2,lval)           \
+{                                                 \
+   if (groupPos == 0) {                           \
+      groupNo++;                                  \
+      if (groupNo >= nSelectors)                  \
+         RETURN(BZ_DATA_ERROR);                   \
+      groupPos = BZ_G_SIZE;                       \
+      gSel = s->selector[groupNo];                \
+      gMinlen = s->minLens[gSel];                 \
+      gLimit = &(s->limit[gSel][0]);              \
+      gPerm = &(s->perm[gSel][0]);                \
+      gBase = &(s->base[gSel][0]);                \
+   }                                              \
+   groupPos--;                                    \
+   zn = gMinlen;                                  \
+   GET_BITS(label1, zvec, zn);                    \
+   while (1) {                                    \
+      if (zn > 20 /* the longest code */)         \
+         RETURN(BZ_DATA_ERROR);                   \
+      if (zvec <= gLimit[zn]) break;              \
+      zn++;                                       \
+      GET_BIT(label2, zj);                        \
+      zvec = (zvec << 1) | zj;                    \
+   };                                             \
+   if (zvec - gBase[zn] < 0                       \
+       || zvec - gBase[zn] >= BZ_MAX_ALPHA_SIZE)  \
+      RETURN(BZ_DATA_ERROR);                      \
+   lval = gPerm[zvec - gBase[zn]];                \
+}
+
+
+/*---------------------------------------------------*/
+Int32 BZ2_decompress ( DState* s )
+{
+   UChar      uc;
+   Int32      retVal;
+   Int32      minLen, maxLen;
+   bz_stream* strm = s->strm;
+
+   /* stuff that needs to be saved/restored */
+   Int32  i;
+   Int32  j;
+   Int32  t;
+   Int32  alphaSize;
+   Int32  nGroups;
+   Int32  nSelectors;
+   Int32  EOB;
+   Int32  groupNo;
+   Int32  groupPos;
+   Int32  nextSym;
+   Int32  nblockMAX;
+   Int32  nblock;
+   Int32  es;
+   Int32  N;
+   Int32  curr;
+   Int32  zt;
+   Int32  zn; 
+   Int32  zvec;
+   Int32  zj;
+   Int32  gSel;
+   Int32  gMinlen;
+   Int32* gLimit;
+   Int32* gBase;
+   Int32* gPerm;
+
+   if (s->state == BZ_X_MAGIC_1) {
+      /*initialise the save area*/
+      s->save_i           = 0;
+      s->save_j           = 0;
+      s->save_t           = 0;
+      s->save_alphaSize   = 0;
+      s->save_nGroups     = 0;
+      s->save_nSelectors  = 0;
+      s->save_EOB         = 0;
+      s->save_groupNo     = 0;
+      s->save_groupPos    = 0;
+      s->save_nextSym     = 0;
+      s->save_nblockMAX   = 0;
+      s->save_nblock      = 0;
+      s->save_es          = 0;
+      s->save_N           = 0;
+      s->save_curr        = 0;
+      s->save_zt          = 0;
+      s->save_zn          = 0;
+      s->save_zvec        = 0;
+      s->save_zj          = 0;
+      s->save_gSel        = 0;
+      s->save_gMinlen     = 0;
+      s->save_gLimit      = NULL;
+      s->save_gBase       = NULL;
+      s->save_gPerm       = NULL;
+   }
+
+   /*restore from the save area*/
+   i           = s->save_i;
+   j           = s->save_j;
+   t           = s->save_t;
+   alphaSize   = s->save_alphaSize;
+   nGroups     = s->save_nGroups;
+   nSelectors  = s->save_nSelectors;
+   EOB         = s->save_EOB;
+   groupNo     = s->save_groupNo;
+   groupPos    = s->save_groupPos;
+   nextSym     = s->save_nextSym;
+   nblockMAX   = s->save_nblockMAX;
+   nblock      = s->save_nblock;
+   es          = s->save_es;
+   N           = s->save_N;
+   curr        = s->save_curr;
+   zt          = s->save_zt;
+   zn          = s->save_zn; 
+   zvec        = s->save_zvec;
+   zj          = s->save_zj;
+   gSel        = s->save_gSel;
+   gMinlen     = s->save_gMinlen;
+   gLimit      = s->save_gLimit;
+   gBase       = s->save_gBase;
+   gPerm       = s->save_gPerm;
+
+   retVal = BZ_OK;
+
+   switch (s->state) {
+
+      GET_UCHAR(BZ_X_MAGIC_1, uc);
+      if (uc != BZ_HDR_B) RETURN(BZ_DATA_ERROR_MAGIC);
+
+      GET_UCHAR(BZ_X_MAGIC_2, uc);
+      if (uc != BZ_HDR_Z) RETURN(BZ_DATA_ERROR_MAGIC);
+
+      GET_UCHAR(BZ_X_MAGIC_3, uc)
+      if (uc != BZ_HDR_h) RETURN(BZ_DATA_ERROR_MAGIC);
+
+      GET_BITS(BZ_X_MAGIC_4, s->blockSize100k, 8)
+      if (s->blockSize100k < (BZ_HDR_0 + 1) || 
+          s->blockSize100k > (BZ_HDR_0 + 9)) RETURN(BZ_DATA_ERROR_MAGIC);
+      s->blockSize100k -= BZ_HDR_0;
+
+      if (s->smallDecompress) {
+         s->ll16 = BZALLOC( s->blockSize100k * 100000 * sizeof(UInt16) );
+         s->ll4  = BZALLOC( 
+                      ((1 + s->blockSize100k * 100000) >> 1) * sizeof(UChar) 
+                   );
+         if (s->ll16 == NULL || s->ll4 == NULL) RETURN(BZ_MEM_ERROR);
+      } else {
+         s->tt  = BZALLOC( s->blockSize100k * 100000 * sizeof(Int32) );
+         if (s->tt == NULL) RETURN(BZ_MEM_ERROR);
+      }
+
+      GET_UCHAR(BZ_X_BLKHDR_1, uc);
+
+      if (uc == 0x17) goto endhdr_2;
+      if (uc != 0x31) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_BLKHDR_2, uc);
+      if (uc != 0x41) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_BLKHDR_3, uc);
+      if (uc != 0x59) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_BLKHDR_4, uc);
+      if (uc != 0x26) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_BLKHDR_5, uc);
+      if (uc != 0x53) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_BLKHDR_6, uc);
+      if (uc != 0x59) RETURN(BZ_DATA_ERROR);
+
+      s->currBlockNo++;
+      if (s->verbosity >= 2)
+         VPrintf1 ( "\n    [%d: huff+mtf ", s->currBlockNo );
+ 
+      s->storedBlockCRC = 0;
+      GET_UCHAR(BZ_X_BCRC_1, uc);
+      s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
+      GET_UCHAR(BZ_X_BCRC_2, uc);
+      s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
+      GET_UCHAR(BZ_X_BCRC_3, uc);
+      s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
+      GET_UCHAR(BZ_X_BCRC_4, uc);
+      s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
+
+      GET_BITS(BZ_X_RANDBIT, s->blockRandomised, 1);
+
+      s->origPtr = 0;
+      GET_UCHAR(BZ_X_ORIGPTR_1, uc);
+      s->origPtr = (s->origPtr << 8) | ((Int32)uc);
+      GET_UCHAR(BZ_X_ORIGPTR_2, uc);
+      s->origPtr = (s->origPtr << 8) | ((Int32)uc);
+      GET_UCHAR(BZ_X_ORIGPTR_3, uc);
+      s->origPtr = (s->origPtr << 8) | ((Int32)uc);
+
+      if (s->origPtr < 0)
+         RETURN(BZ_DATA_ERROR);
+      if (s->origPtr > 10 + 100000*s->blockSize100k) 
+         RETURN(BZ_DATA_ERROR);
+
+      /*--- Receive the mapping table ---*/
+      for (i = 0; i < 16; i++) {
+         GET_BIT(BZ_X_MAPPING_1, uc);
+         if (uc == 1) 
+            s->inUse16[i] = True; else 
+            s->inUse16[i] = False;
+      }
+
+      for (i = 0; i < 256; i++) s->inUse[i] = False;
+
+      for (i = 0; i < 16; i++)
+         if (s->inUse16[i])
+            for (j = 0; j < 16; j++) {
+               GET_BIT(BZ_X_MAPPING_2, uc);
+               if (uc == 1) s->inUse[i * 16 + j] = True;
+            }
+      makeMaps_d ( s );
+      if (s->nInUse == 0) RETURN(BZ_DATA_ERROR);
+      alphaSize = s->nInUse+2;
+
+      /*--- Now the selectors ---*/
+      GET_BITS(BZ_X_SELECTOR_1, nGroups, 3);
+      if (nGroups < 2 || nGroups > 6) RETURN(BZ_DATA_ERROR);
+      GET_BITS(BZ_X_SELECTOR_2, nSelectors, 15);
+      if (nSelectors < 1) RETURN(BZ_DATA_ERROR);
+      for (i = 0; i < nSelectors; i++) {
+         j = 0;
+         while (True) {
+            GET_BIT(BZ_X_SELECTOR_3, uc);
+            if (uc == 0) break;
+            j++;
+            if (j >= nGroups) RETURN(BZ_DATA_ERROR);
+         }
+         s->selectorMtf[i] = j;
+      }
+
+      /*--- Undo the MTF values for the selectors. ---*/
+      {
+         UChar pos[BZ_N_GROUPS], tmp, v;
+         for (v = 0; v < nGroups; v++) pos[v] = v;
+   
+         for (i = 0; i < nSelectors; i++) {
+            v = s->selectorMtf[i];
+            tmp = pos[v];
+            while (v > 0) { pos[v] = pos[v-1]; v--; }
+            pos[0] = tmp;
+            s->selector[i] = tmp;
+         }
+      }
+
+      /*--- Now the coding tables ---*/
+      for (t = 0; t < nGroups; t++) {
+         GET_BITS(BZ_X_CODING_1, curr, 5);
+         for (i = 0; i < alphaSize; i++) {
+            while (True) {
+               if (curr < 1 || curr > 20) RETURN(BZ_DATA_ERROR);
+               GET_BIT(BZ_X_CODING_2, uc);
+               if (uc == 0) break;
+               GET_BIT(BZ_X_CODING_3, uc);
+               if (uc == 0) curr++; else curr--;
+            }
+            s->len[t][i] = curr;
+         }
+      }
+
+      /*--- Create the Huffman decoding tables ---*/
+      for (t = 0; t < nGroups; t++) {
+         minLen = 32;
+         maxLen = 0;
+         for (i = 0; i < alphaSize; i++) {
+            if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
+            if (s->len[t][i] < minLen) minLen = s->len[t][i];
+         }
+         BZ2_hbCreateDecodeTables ( 
+            &(s->limit[t][0]), 
+            &(s->base[t][0]), 
+            &(s->perm[t][0]), 
+            &(s->len[t][0]),
+            minLen, maxLen, alphaSize
+         );
+         s->minLens[t] = minLen;
+      }
+
+      /*--- Now the MTF values ---*/
+
+      EOB      = s->nInUse+1;
+      nblockMAX = 100000 * s->blockSize100k;
+      groupNo  = -1;
+      groupPos = 0;
+
+      for (i = 0; i <= 255; i++) s->unzftab[i] = 0;
+
+      /*-- MTF init --*/
+      {
+         Int32 ii, jj, kk;
+         kk = MTFA_SIZE-1;
+         for (ii = 256 / MTFL_SIZE - 1; ii >= 0; ii--) {
+            for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
+               s->mtfa[kk] = (UChar)(ii * MTFL_SIZE + jj);
+               kk--;
+            }
+            s->mtfbase[ii] = kk + 1;
+         }
+      }
+      /*-- end MTF init --*/
+
+      nblock = 0;
+      GET_MTF_VAL(BZ_X_MTF_1, BZ_X_MTF_2, nextSym);
+
+      while (True) {
+
+         if (nextSym == EOB) break;
+
+         if (nextSym == BZ_RUNA || nextSym == BZ_RUNB) {
+
+            es = -1;
+            N = 1;
+            do {
+               if (nextSym == BZ_RUNA) es = es + (0+1) * N; else
+               if (nextSym == BZ_RUNB) es = es + (1+1) * N;
+               N = N * 2;
+               GET_MTF_VAL(BZ_X_MTF_3, BZ_X_MTF_4, nextSym);
+            }
+               while (nextSym == BZ_RUNA || nextSym == BZ_RUNB);
+
+            es++;
+            uc = s->seqToUnseq[ s->mtfa[s->mtfbase[0]] ];
+            s->unzftab[uc] += es;
+
+            if (s->smallDecompress)
+               while (es > 0) {
+                  if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
+                  s->ll16[nblock] = (UInt16)uc;
+                  nblock++;
+                  es--;
+               }
+            else
+               while (es > 0) {
+                  if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
+                  s->tt[nblock] = (UInt32)uc;
+                  nblock++;
+                  es--;
+               };
+
+            continue;
+
+         } else {
+
+            if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
+
+            /*-- uc = MTF ( nextSym-1 ) --*/
+            {
+               Int32 ii, jj, kk, pp, lno, off;
+               UInt32 nn;
+               nn = (UInt32)(nextSym - 1);
+
+               if (nn < MTFL_SIZE) {
+                  /* avoid general-case expense */
+                  pp = s->mtfbase[0];
+                  uc = s->mtfa[pp+nn];
+                  while (nn > 3) {
+                     Int32 z = pp+nn;
+                     s->mtfa[(z)  ] = s->mtfa[(z)-1];
+                     s->mtfa[(z)-1] = s->mtfa[(z)-2];
+                     s->mtfa[(z)-2] = s->mtfa[(z)-3];
+                     s->mtfa[(z)-3] = s->mtfa[(z)-4];
+                     nn -= 4;
+                  }
+                  while (nn > 0) { 
+                     s->mtfa[(pp+nn)] = s->mtfa[(pp+nn)-1]; nn--; 
+                  };
+                  s->mtfa[pp] = uc;
+               } else { 
+                  /* general case */
+                  lno = nn / MTFL_SIZE;
+                  off = nn % MTFL_SIZE;
+                  pp = s->mtfbase[lno] + off;
+                  uc = s->mtfa[pp];
+                  while (pp > s->mtfbase[lno]) { 
+                     s->mtfa[pp] = s->mtfa[pp-1]; pp--; 
+                  };
+                  s->mtfbase[lno]++;
+                  while (lno > 0) {
+                     s->mtfbase[lno]--;
+                     s->mtfa[s->mtfbase[lno]] 
+                        = s->mtfa[s->mtfbase[lno-1] + MTFL_SIZE - 1];
+                     lno--;
+                  }
+                  s->mtfbase[0]--;
+                  s->mtfa[s->mtfbase[0]] = uc;
+                  if (s->mtfbase[0] == 0) {
+                     kk = MTFA_SIZE-1;
+                     for (ii = 256 / MTFL_SIZE-1; ii >= 0; ii--) {
+                        for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
+                           s->mtfa[kk] = s->mtfa[s->mtfbase[ii] + jj];
+                           kk--;
+                        }
+                        s->mtfbase[ii] = kk + 1;
+                     }
+                  }
+               }
+            }
+            /*-- end uc = MTF ( nextSym-1 ) --*/
+
+            s->unzftab[s->seqToUnseq[uc]]++;
+            if (s->smallDecompress)
+               s->ll16[nblock] = (UInt16)(s->seqToUnseq[uc]); else
+               s->tt[nblock]   = (UInt32)(s->seqToUnseq[uc]);
+            nblock++;
+
+            GET_MTF_VAL(BZ_X_MTF_5, BZ_X_MTF_6, nextSym);
+            continue;
+         }
+      }
+
+      /* Now we know what nblock is, we can do a better sanity
+         check on s->origPtr.
+      */
+      if (s->origPtr < 0 || s->origPtr >= nblock)
+         RETURN(BZ_DATA_ERROR);
+
+      /*-- Set up cftab to facilitate generation of T^(-1) --*/
+      s->cftab[0] = 0;
+      for (i = 1; i <= 256; i++) s->cftab[i] = s->unzftab[i-1];
+      for (i = 1; i <= 256; i++) s->cftab[i] += s->cftab[i-1];
+      for (i = 0; i <= 256; i++) {
+         if (s->cftab[i] < 0 || s->cftab[i] > nblock) {
+            /* s->cftab[i] can legitimately be == nblock */
+            RETURN(BZ_DATA_ERROR);
+         }
+      }
+
+      s->state_out_len = 0;
+      s->state_out_ch  = 0;
+      BZ_INITIALISE_CRC ( s->calculatedBlockCRC );
+      s->state = BZ_X_OUTPUT;
+      if (s->verbosity >= 2) VPrintf0 ( "rt+rld" );
+
+      if (s->smallDecompress) {
+
+         /*-- Make a copy of cftab, used in generation of T --*/
+         for (i = 0; i <= 256; i++) s->cftabCopy[i] = s->cftab[i];
+
+         /*-- compute the T vector --*/
+         for (i = 0; i < nblock; i++) {
+            uc = (UChar)(s->ll16[i]);
+            SET_LL(i, s->cftabCopy[uc]);
+            s->cftabCopy[uc]++;
+         }
+
+         /*-- Compute T^(-1) by pointer reversal on T --*/
+         i = s->origPtr;
+         j = GET_LL(i);
+         do {
+            Int32 tmp = GET_LL(j);
+            SET_LL(j, i);
+            i = j;
+            j = tmp;
+         }
+            while (i != s->origPtr);
+
+         s->tPos = s->origPtr;
+         s->nblock_used = 0;
+         if (s->blockRandomised) {
+            BZ_RAND_INIT_MASK;
+            BZ_GET_SMALL(s->k0); s->nblock_used++;
+            BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK; 
+         } else {
+            BZ_GET_SMALL(s->k0); s->nblock_used++;
+         }
+
+      } else {
+
+         /*-- compute the T^(-1) vector --*/
+         for (i = 0; i < nblock; i++) {
+            uc = (UChar)(s->tt[i] & 0xff);
+            s->tt[s->cftab[uc]] |= (i << 8);
+            s->cftab[uc]++;
+         }
+
+         s->tPos = s->tt[s->origPtr] >> 8;
+         s->nblock_used = 0;
+         if (s->blockRandomised) {
+            BZ_RAND_INIT_MASK;
+            BZ_GET_FAST(s->k0); s->nblock_used++;
+            BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK; 
+         } else {
+            BZ_GET_FAST(s->k0); s->nblock_used++;
+         }
+
+      }
+
+      RETURN(BZ_OK);
+
+
+
+    endhdr_2:
+
+      GET_UCHAR(BZ_X_ENDHDR_2, uc);
+      if (uc != 0x72) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_ENDHDR_3, uc);
+      if (uc != 0x45) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_ENDHDR_4, uc);
+      if (uc != 0x38) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_ENDHDR_5, uc);
+      if (uc != 0x50) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_ENDHDR_6, uc);
+      if (uc != 0x90) RETURN(BZ_DATA_ERROR);
+
+      s->storedCombinedCRC = 0;
+      GET_UCHAR(BZ_X_CCRC_1, uc);
+      s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
+      GET_UCHAR(BZ_X_CCRC_2, uc);
+      s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
+      GET_UCHAR(BZ_X_CCRC_3, uc);
+      s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
+      GET_UCHAR(BZ_X_CCRC_4, uc);
+      s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
+
+      s->state = BZ_X_IDLE;
+      RETURN(BZ_STREAM_END);
+
+      default: AssertH ( False, 4001 );
+   }
+
+   AssertH ( False, 4002 );
+
+   save_state_and_return:
+
+   s->save_i           = i;
+   s->save_j           = j;
+   s->save_t           = t;
+   s->save_alphaSize   = alphaSize;
+   s->save_nGroups     = nGroups;
+   s->save_nSelectors  = nSelectors;
+   s->save_EOB         = EOB;
+   s->save_groupNo     = groupNo;
+   s->save_groupPos    = groupPos;
+   s->save_nextSym     = nextSym;
+   s->save_nblockMAX   = nblockMAX;
+   s->save_nblock      = nblock;
+   s->save_es          = es;
+   s->save_N           = N;
+   s->save_curr        = curr;
+   s->save_zt          = zt;
+   s->save_zn          = zn;
+   s->save_zvec        = zvec;
+   s->save_zj          = zj;
+   s->save_gSel        = gSel;
+   s->save_gMinlen     = gMinlen;
+   s->save_gLimit      = gLimit;
+   s->save_gBase       = gBase;
+   s->save_gPerm       = gPerm;
+
+   return retVal;   
+}
+
+
+/*-------------------------------------------------------------*/
+/*--- end                                      decompress.c ---*/
+/*-------------------------------------------------------------*/
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/dlltest.c b/contrib/vmap_extractor_v2/stormlib/bzip2/dlltest.c
new file mode 100644
index 00000000000..eb86bb61a59
--- /dev/null
+++ b/contrib/vmap_extractor_v2/stormlib/bzip2/dlltest.c
@@ -0,0 +1,176 @@
+/*
+   minibz2
+      libbz2.dll test program.
+      by Yoshioka Tsuneo(QWF00133@nifty.ne.jp/tsuneo-y@is.aist-nara.ac.jp)
+      This file is Public Domain.
+      welcome any email to me.
+
+   usage: minibz2 [-d] [-{1,2,..9}] [[srcfilename] destfilename]
+*/
+
+#define BZ_IMPORT
+#include 
+#include 
+#include "bzlib.h"
+#ifdef _WIN32
+#include 
+#endif
+
+
+#ifdef _WIN32
+
+#define BZ2_LIBNAME "libbz2-1.0.2.DLL" 
+
+#include 
+static int BZ2DLLLoaded = 0;
+static HINSTANCE BZ2DLLhLib;
+int BZ2DLLLoadLibrary(void)
+{
+   HINSTANCE hLib;
+
+   if(BZ2DLLLoaded==1){return 0;}
+   hLib=LoadLibrary(BZ2_LIBNAME);
+   if(hLib == NULL){
+      fprintf(stderr,"Can't load %s\n",BZ2_LIBNAME);
+      return -1;
+   }
+   BZ2_bzlibVersion=GetProcAddress(hLib,"BZ2_bzlibVersion");
+   BZ2_bzopen=GetProcAddress(hLib,"BZ2_bzopen");
+   BZ2_bzdopen=GetProcAddress(hLib,"BZ2_bzdopen");
+   BZ2_bzread=GetProcAddress(hLib,"BZ2_bzread");
+   BZ2_bzwrite=GetProcAddress(hLib,"BZ2_bzwrite");
+   BZ2_bzflush=GetProcAddress(hLib,"BZ2_bzflush");
+   BZ2_bzclose=GetProcAddress(hLib,"BZ2_bzclose");
+   BZ2_bzerror=GetProcAddress(hLib,"BZ2_bzerror");
+
+   if (!BZ2_bzlibVersion || !BZ2_bzopen || !BZ2_bzdopen
+       || !BZ2_bzread || !BZ2_bzwrite || !BZ2_bzflush
+       || !BZ2_bzclose || !BZ2_bzerror) {
+      fprintf(stderr,"GetProcAddress failed.\n");
+      return -1;
+   }
+   BZ2DLLLoaded=1;
+   BZ2DLLhLib=hLib;
+   return 0;
+
+}
+int BZ2DLLFreeLibrary(void)
+{
+   if(BZ2DLLLoaded==0){return 0;}
+   FreeLibrary(BZ2DLLhLib);
+   BZ2DLLLoaded=0;
+}
+#endif /* WIN32 */
+
+void usage(void)
+{
+   puts("usage: minibz2 [-d] [-{1,2,..9}] [[srcfilename] destfilename]");
+}
+
+int main(int argc,char *argv[])
+{
+   int decompress = 0;
+   int level = 9;
+   char *fn_r = NULL;
+   char *fn_w = NULL;
+
+#ifdef _WIN32
+   if(BZ2DLLLoadLibrary()<0){
+      fprintf(stderr,"Loading of %s failed.  Giving up.\n", BZ2_LIBNAME);
+      exit(1);
+   }
+   printf("Loading of %s succeeded.  Library version is %s.\n",
+          BZ2_LIBNAME, BZ2_bzlibVersion() );
+#endif
+   while(++argv,--argc){
+      if(**argv =='-' || **argv=='/'){
+         char *p;
+
+         for(p=*argv+1;*p;p++){
+            if(*p=='d'){
+               decompress = 1;
+            }else if('1'<=*p && *p<='9'){
+               level = *p - '0';
+            }else{
+               usage();
+               exit(1);
+            }
+         }
+      }else{
+         break;
+      }
+   }
+   if(argc>=1){
+      fn_r = *argv;
+      argc--;argv++;
+   }else{
+      fn_r = NULL;
+   }
+   if(argc>=1){
+      fn_w = *argv;
+      argc--;argv++;
+   }else{
+      fn_w = NULL;
+   }
+   {
+      int len;
+      char buff[0x1000];
+      char mode[10];
+
+      if(decompress){
+         BZFILE *BZ2fp_r = NULL;
+         FILE *fp_w = NULL;
+
+         if(fn_w){
+            if((fp_w = fopen(fn_w,"wb"))==NULL){
+               printf("can't open [%s]\n",fn_w);
+               perror("reason:");
+               exit(1);
+            }
+         }else{
+            fp_w = stdout;
+         }
+         if((fn_r == NULL && (BZ2fp_r = BZ2_bzdopen(fileno(stdin),"rb"))==NULL)
+            || (fn_r != NULL && (BZ2fp_r = BZ2_bzopen(fn_r,"rb"))==NULL)){
+            printf("can't bz2openstream\n");
+            exit(1);
+         }
+         while((len=BZ2_bzread(BZ2fp_r,buff,0x1000))>0){
+            fwrite(buff,1,len,fp_w);
+         }
+         BZ2_bzclose(BZ2fp_r);
+         if(fp_w != stdout) fclose(fp_w);
+      }else{
+         BZFILE *BZ2fp_w = NULL;
+         FILE *fp_r = NULL;
+
+         if(fn_r){
+            if((fp_r = fopen(fn_r,"rb"))==NULL){
+               printf("can't open [%s]\n",fn_r);
+               perror("reason:");
+               exit(1);
+            }
+         }else{
+            fp_r = stdin;
+         }
+         mode[0]='w';
+         mode[1] = '0' + level;
+         mode[2] = '\0';
+
+         if((fn_w == NULL && (BZ2fp_w = BZ2_bzdopen(fileno(stdout),mode))==NULL)
+            || (fn_w !=NULL && (BZ2fp_w = BZ2_bzopen(fn_w,mode))==NULL)){
+            printf("can't bz2openstream\n");
+            exit(1);
+         }
+         while((len=fread(buff,1,0x1000,fp_r))>0){
+            BZ2_bzwrite(BZ2fp_w,buff,len);
+         }
+         BZ2_bzclose(BZ2fp_w);
+         if(fp_r!=stdin)fclose(fp_r);
+      }
+   }
+#ifdef _WIN32
+   BZ2DLLFreeLibrary();
+#endif
+   return 0;
+}
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/dlltest.dsp b/contrib/vmap_extractor_v2/stormlib/bzip2/dlltest.dsp
new file mode 100644
index 00000000000..04819a49563
--- /dev/null
+++ b/contrib/vmap_extractor_v2/stormlib/bzip2/dlltest.dsp
@@ -0,0 +1,93 @@
+# Microsoft Developer Studio Project File - Name="dlltest" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** •ÒW‚µ‚È‚¢‚Å‚­‚¾‚³‚¢ **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=dlltest - Win32 Debug
+!MESSAGE ‚±‚ê‚Í—LŒø‚ÈÒ²¸Ì§²Ù‚ł͂ ‚è‚Ü‚¹‚ñB ‚±‚ÌÌßÛ¼Þª¸Ä‚ðËÞÙÄÞ‚·‚邽‚ß‚É‚Í NMAKE ‚ðŽg—p‚µ‚Ä‚­‚¾‚³‚¢B
+!MESSAGE [Ò²¸Ì§²Ù‚Ì´¸½Îß°Ä] ºÏÝÄÞ‚ðŽg—p‚µ‚ÄŽÀs‚µ‚Ä‚­‚¾‚³‚¢
+!MESSAGE 
+!MESSAGE NMAKE /f "dlltest.mak".
+!MESSAGE 
+!MESSAGE NMAKE ‚ÌŽÀsŽž‚É\¬‚ðŽw’è‚Å‚«‚Ü‚·
+!MESSAGE ºÏÝÄÞ ×²Ýã‚ÅϸۂÌÝ’è‚ð’è‹`‚µ‚Ü‚·B—á:
+!MESSAGE 
+!MESSAGE NMAKE /f "dlltest.mak" CFG="dlltest - Win32 Debug"
+!MESSAGE 
+!MESSAGE ‘I‘ð‰Â”\‚ÈËÞÙÄÞ Ó°ÄÞ:
+!MESSAGE 
+!MESSAGE "dlltest - Win32 Release" ("Win32 (x86) Console Application" —p)
+!MESSAGE "dlltest - Win32 Debug" ("Win32 (x86) Console Application" —p)
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "dlltest - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x411 /d "NDEBUG"
+# ADD RSC /l 0x411 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"minibz2.exe"
+
+!ELSEIF  "$(CFG)" == "dlltest - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "dlltest_"
+# PROP BASE Intermediate_Dir "dlltest_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "dlltest_"
+# PROP Intermediate_Dir "dlltest_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x411 /d "_DEBUG"
+# ADD RSC /l 0x411 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"minibz2.exe" /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "dlltest - Win32 Release"
+# Name "dlltest - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\bzlib.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\dlltest.c
+# End Source File
+# End Target
+# End Project
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/entities.xml b/contrib/vmap_extractor_v2/stormlib/bzip2/entities.xml
new file mode 100644
index 00000000000..6d0975fdbf6
--- /dev/null
+++ b/contrib/vmap_extractor_v2/stormlib/bzip2/entities.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/format.pl b/contrib/vmap_extractor_v2/stormlib/bzip2/format.pl
new file mode 100644
index 00000000000..8ab47acd384
--- /dev/null
+++ b/contrib/vmap_extractor_v2/stormlib/bzip2/format.pl
@@ -0,0 +1,53 @@
+#!/usr/bin/perl -w
+use strict;
+
+# get command line values:
+if ( $#ARGV !=1 ) {
+    die "Usage:  $0 xml_infile xml_outfile\n";
+}
+
+my $infile = shift;
+# check infile exists
+die "Can't find file \"$infile\""
+  unless -f $infile;
+# check we can read infile
+if (! -r $infile) {
+    die "Can't read input $infile\n";
+}
+# check we can open infile
+open( INFILE,"<$infile" ) or 
+    die "Can't input $infile $!";
+
+#my $outfile = 'fmt-manual.xml';
+my $outfile = shift;
+#print "Infile: $infile, Outfile: $outfile\n";
+# check we can write to outfile
+open( OUTFILE,">$outfile" ) or 
+    die "Can't output $outfile $! for writing";
+
+my ($prev, $curr, $str);
+$prev = ''; $curr = '';
+while (  ) {
+
+		print OUTFILE $prev;
+    $prev = $curr;
+    $curr = $_;
+    $str = '';
+
+    if ( $prev =~ /$|$/ ) {
+        chomp $prev;
+        $curr = join( '', $prev, "|<\/screen>/ ) {
+        chomp $prev;
+        $curr = join( '', $prev, "]]>", $curr );
+				$prev = '';
+        next;
+    }
+}
+print OUTFILE $curr;
+close INFILE;
+close OUTFILE;
+exit;
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/huffman.c b/contrib/vmap_extractor_v2/stormlib/bzip2/huffman.c
new file mode 100644
index 00000000000..5bf190be9a1
--- /dev/null
+++ b/contrib/vmap_extractor_v2/stormlib/bzip2/huffman.c
@@ -0,0 +1,245 @@
+
+/*-------------------------------------------------------------*/
+/*--- Huffman coding low-level stuff                        ---*/
+/*---                                             huffman.c ---*/
+/*-------------------------------------------------------------*/
+
+/*--
+  This file is a part of bzip2 and/or libbzip2, a program and
+  library for lossless, block-sorting data compression.
+
+  Copyright (C) 1996-2005 Julian R Seward.  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+  2. The origin of this software must not be misrepresented; you must 
+     not claim that you wrote the original software.  If you use this 
+     software in a product, an acknowledgment in the product 
+     documentation would be appreciated but is not required.
+
+  3. Altered source versions must be plainly marked as such, and must
+     not be misrepresented as being the original software.
+
+  4. The name of the author may not be used to endorse or promote 
+     products derived from this software without specific prior written 
+     permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  Julian Seward, Cambridge, UK.
+  jseward@bzip.org
+  bzip2/libbzip2 version 1.0 of 21 March 2000
+
+  This program is based on (at least) the work of:
+     Mike Burrows
+     David Wheeler
+     Peter Fenwick
+     Alistair Moffat
+     Radford Neal
+     Ian H. Witten
+     Robert Sedgewick
+     Jon L. Bentley
+
+  For more information on these sources, see the manual.
+--*/
+
+
+#include "bzlib_private.h"
+
+/*---------------------------------------------------*/
+#define WEIGHTOF(zz0)  ((zz0) & 0xffffff00)
+#define DEPTHOF(zz1)   ((zz1) & 0x000000ff)
+#define MYMAX(zz2,zz3) ((zz2) > (zz3) ? (zz2) : (zz3))
+
+#define ADDWEIGHTS(zw1,zw2)                           \
+   (WEIGHTOF(zw1)+WEIGHTOF(zw2)) |                    \
+   (1 + MYMAX(DEPTHOF(zw1),DEPTHOF(zw2)))
+
+#define UPHEAP(z)                                     \
+{                                                     \
+   Int32 zz, tmp;                                     \
+   zz = z; tmp = heap[zz];                            \
+   while (weight[tmp] < weight[heap[zz >> 1]]) {      \
+      heap[zz] = heap[zz >> 1];                       \
+      zz >>= 1;                                       \
+   }                                                  \
+   heap[zz] = tmp;                                    \
+}
+
+#define DOWNHEAP(z)                                   \
+{                                                     \
+   Int32 zz, yy, tmp;                                 \
+   zz = z; tmp = heap[zz];                            \
+   while (True) {                                     \
+      yy = zz << 1;                                   \
+      if (yy > nHeap) break;                          \
+      if (yy < nHeap &&                               \
+          weight[heap[yy+1]] < weight[heap[yy]])      \
+         yy++;                                        \
+      if (weight[tmp] < weight[heap[yy]]) break;      \
+      heap[zz] = heap[yy];                            \
+      zz = yy;                                        \
+   }                                                  \
+   heap[zz] = tmp;                                    \
+}
+
+
+/*---------------------------------------------------*/
+void BZ2_hbMakeCodeLengths ( UChar *len, 
+                             Int32 *freq,
+                             Int32 alphaSize,
+                             Int32 maxLen )
+{
+   /*--
+      Nodes and heap entries run from 1.  Entry 0
+      for both the heap and nodes is a sentinel.
+   --*/
+   Int32 nNodes, nHeap, n1, n2, i, j, k;
+   Bool  tooLong;
+
+   Int32 heap   [ BZ_MAX_ALPHA_SIZE + 2 ];
+   Int32 weight [ BZ_MAX_ALPHA_SIZE * 2 ];
+   Int32 parent [ BZ_MAX_ALPHA_SIZE * 2 ]; 
+
+   for (i = 0; i < alphaSize; i++)
+      weight[i+1] = (freq[i] == 0 ? 1 : freq[i]) << 8;
+
+   while (True) {
+
+      nNodes = alphaSize;
+      nHeap = 0;
+
+      heap[0] = 0;
+      weight[0] = 0;
+      parent[0] = -2;
+
+      for (i = 1; i <= alphaSize; i++) {
+         parent[i] = -1;
+         nHeap++;
+         heap[nHeap] = i;
+         UPHEAP(nHeap);
+      }
+
+      AssertH( nHeap < (BZ_MAX_ALPHA_SIZE+2), 2001 );
+   
+      while (nHeap > 1) {
+         n1 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1);
+         n2 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1);
+         nNodes++;
+         parent[n1] = parent[n2] = nNodes;
+         weight[nNodes] = ADDWEIGHTS(weight[n1], weight[n2]);
+         parent[nNodes] = -1;
+         nHeap++;
+         heap[nHeap] = nNodes;
+         UPHEAP(nHeap);
+      }
+
+      AssertH( nNodes < (BZ_MAX_ALPHA_SIZE * 2), 2002 );
+
+      tooLong = False;
+      for (i = 1; i <= alphaSize; i++) {
+         j = 0;
+         k = i;
+         while (parent[k] >= 0) { k = parent[k]; j++; }
+         len[i-1] = j;
+         if (j > maxLen) tooLong = True;
+      }
+      
+      if (! tooLong) break;
+
+      /* 17 Oct 04: keep-going condition for the following loop used
+         to be 'i < alphaSize', which missed the last element,
+         theoretically leading to the possibility of the compressor
+         looping.  However, this count-scaling step is only needed if
+         one of the generated Huffman code words is longer than
+         maxLen, which up to and including version 1.0.2 was 20 bits,
+         which is extremely unlikely.  In version 1.0.3 maxLen was
+         changed to 17 bits, which has minimal effect on compression
+         ratio, but does mean this scaling step is used from time to
+         time, enough to verify that it works.
+
+         This means that bzip2-1.0.3 and later will only produce
+         Huffman codes with a maximum length of 17 bits.  However, in
+         order to preserve backwards compatibility with bitstreams
+         produced by versions pre-1.0.3, the decompressor must still
+         handle lengths of up to 20. */
+
+      for (i = 1; i <= alphaSize; i++) {
+         j = weight[i] >> 8;
+         j = 1 + (j / 2);
+         weight[i] = j << 8;
+      }
+   }
+}
+
+
+/*---------------------------------------------------*/
+void BZ2_hbAssignCodes ( Int32 *code,
+                         UChar *length,
+                         Int32 minLen,
+                         Int32 maxLen,
+                         Int32 alphaSize )
+{
+   Int32 n, vec, i;
+
+   vec = 0;
+   for (n = minLen; n <= maxLen; n++) {
+      for (i = 0; i < alphaSize; i++)
+         if (length[i] == n) { code[i] = vec; vec++; };
+      vec <<= 1;
+   }
+}
+
+
+/*---------------------------------------------------*/
+void BZ2_hbCreateDecodeTables ( Int32 *limit,
+                                Int32 *base,
+                                Int32 *perm,
+                                UChar *length,
+                                Int32 minLen,
+                                Int32 maxLen,
+                                Int32 alphaSize )
+{
+   Int32 pp, i, j, vec;
+
+   pp = 0;
+   for (i = minLen; i <= maxLen; i++)
+      for (j = 0; j < alphaSize; j++)
+         if (length[j] == i) { perm[pp] = j; pp++; };
+
+   for (i = 0; i < BZ_MAX_CODE_LEN; i++) base[i] = 0;
+   for (i = 0; i < alphaSize; i++) base[length[i]+1]++;
+
+   for (i = 1; i < BZ_MAX_CODE_LEN; i++) base[i] += base[i-1];
+
+   for (i = 0; i < BZ_MAX_CODE_LEN; i++) limit[i] = 0;
+   vec = 0;
+
+   for (i = minLen; i <= maxLen; i++) {
+      vec += (base[i+1] - base[i]);
+      limit[i] = vec-1;
+      vec <<= 1;
+   }
+   for (i = minLen + 1; i <= maxLen; i++)
+      base[i] = ((limit[i-1] + 1) << 1) - base[i];
+}
+
+
+/*-------------------------------------------------------------*/
+/*--- end                                         huffman.c ---*/
+/*-------------------------------------------------------------*/
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/libbz2.def b/contrib/vmap_extractor_v2/stormlib/bzip2/libbz2.def
new file mode 100644
index 00000000000..4f83fcc6102
--- /dev/null
+++ b/contrib/vmap_extractor_v2/stormlib/bzip2/libbz2.def
@@ -0,0 +1,27 @@
+LIBRARY			LIBBZ2
+DESCRIPTION		"libbzip2: library for data compression"
+EXPORTS
+	BZ2_bzCompressInit
+	BZ2_bzCompress
+	BZ2_bzCompressEnd
+	BZ2_bzDecompressInit
+	BZ2_bzDecompress
+	BZ2_bzDecompressEnd
+	BZ2_bzReadOpen
+	BZ2_bzReadClose
+	BZ2_bzReadGetUnused
+	BZ2_bzRead
+	BZ2_bzWriteOpen
+	BZ2_bzWrite
+	BZ2_bzWriteClose
+	BZ2_bzWriteClose64
+	BZ2_bzBuffToBuffCompress
+	BZ2_bzBuffToBuffDecompress
+	BZ2_bzlibVersion
+	BZ2_bzopen
+	BZ2_bzdopen
+	BZ2_bzread
+	BZ2_bzwrite
+	BZ2_bzflush
+	BZ2_bzclose
+	BZ2_bzerror
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/libbz2.dsp b/contrib/vmap_extractor_v2/stormlib/bzip2/libbz2.dsp
new file mode 100644
index 00000000000..06c1d376251
--- /dev/null
+++ b/contrib/vmap_extractor_v2/stormlib/bzip2/libbz2.dsp
@@ -0,0 +1,130 @@
+# Microsoft Developer Studio Project File - Name="libbz2" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** •ÒW‚µ‚È‚¢‚Å‚­‚¾‚³‚¢ **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=libbz2 - Win32 Debug
+!MESSAGE ‚±‚ê‚Í—LŒø‚ÈÒ²¸Ì§²Ù‚ł͂ ‚è‚Ü‚¹‚ñB ‚±‚ÌÌßÛ¼Þª¸Ä‚ðËÞÙÄÞ‚·‚邽‚ß‚É‚Í NMAKE ‚ðŽg—p‚µ‚Ä‚­‚¾‚³‚¢B
+!MESSAGE [Ò²¸Ì§²Ù‚Ì´¸½Îß°Ä] ºÏÝÄÞ‚ðŽg—p‚µ‚ÄŽÀs‚µ‚Ä‚­‚¾‚³‚¢
+!MESSAGE 
+!MESSAGE NMAKE /f "libbz2.mak".
+!MESSAGE 
+!MESSAGE NMAKE ‚ÌŽÀsŽž‚É\¬‚ðŽw’è‚Å‚«‚Ü‚·
+!MESSAGE ºÏÝÄÞ ×²Ýã‚ÅϸۂÌÝ’è‚ð’è‹`‚µ‚Ü‚·B—á:
+!MESSAGE 
+!MESSAGE NMAKE /f "libbz2.mak" CFG="libbz2 - Win32 Debug"
+!MESSAGE 
+!MESSAGE ‘I‘ð‰Â”\‚ÈËÞÙÄÞ Ó°ÄÞ:
+!MESSAGE 
+!MESSAGE "libbz2 - Win32 Release" ("Win32 (x86) Dynamic-Link Library" —p)
+!MESSAGE "libbz2 - Win32 Debug" ("Win32 (x86) Dynamic-Link Library" —p)
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "libbz2 - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x411 /d "NDEBUG"
+# ADD RSC /l 0x411 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 /out:"libbz2.dll"
+
+!ELSEIF  "$(CFG)" == "libbz2 - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x411 /d "_DEBUG"
+# ADD RSC /l 0x411 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:"libbz2.dll" /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "libbz2 - Win32 Release"
+# Name "libbz2 - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\blocksort.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bzlib.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bzlib.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\bzlib_private.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\compress.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\crctable.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\decompress.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\huffman.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\libbz2.def
+# End Source File
+# Begin Source File
+
+SOURCE=.\randtable.c
+# End Source File
+# End Target
+# End Project
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/makefile.msc b/contrib/vmap_extractor_v2/stormlib/bzip2/makefile.msc
new file mode 100644
index 00000000000..6a628a753a0
--- /dev/null
+++ b/contrib/vmap_extractor_v2/stormlib/bzip2/makefile.msc
@@ -0,0 +1,63 @@
+# Makefile for Microsoft Visual C++ 6.0
+# usage: nmake -f makefile.msc
+# K.M. Syring (syring@gsf.de)
+# Fixed up by JRS for bzip2-0.9.5d release.
+
+CC=cl
+CFLAGS= -DWIN32 -MD -Ox -D_FILE_OFFSET_BITS=64 -nologo
+
+OBJS= blocksort.obj  \
+      huffman.obj    \
+      crctable.obj   \
+      randtable.obj  \
+      compress.obj   \
+      decompress.obj \
+      bzlib.obj
+
+all: lib bzip2 test
+
+bzip2: lib
+	$(CC) $(CFLAGS) -o bzip2 bzip2.c libbz2.lib setargv.obj
+	$(CC) $(CFLAGS) -o bzip2recover bzip2recover.c
+
+lib: $(OBJS)
+	lib /out:libbz2.lib $(OBJS)
+
+test: bzip2
+	type words1
+	.\\bzip2 -1  < sample1.ref > sample1.rb2
+	.\\bzip2 -2  < sample2.ref > sample2.rb2
+	.\\bzip2 -3  < sample3.ref > sample3.rb2
+	.\\bzip2 -d  < sample1.bz2 > sample1.tst
+	.\\bzip2 -d  < sample2.bz2 > sample2.tst
+	.\\bzip2 -ds < sample3.bz2 > sample3.tst
+	@echo All six of the fc's should find no differences.
+	@echo If fc finds an error on sample3.bz2, this could be
+	@echo because WinZip's 'TAR file smart CR/LF conversion'
+	@echo is too clever for its own good.  Disable this option.
+	@echo The correct size for sample3.ref is 120,244.  If it
+	@echo is 150,251, WinZip has messed it up.
+	fc sample1.bz2 sample1.rb2 
+	fc sample2.bz2 sample2.rb2
+	fc sample3.bz2 sample3.rb2
+	fc sample1.tst sample1.ref
+	fc sample2.tst sample2.ref
+	fc sample3.tst sample3.ref
+
+
+
+clean: 
+	del *.obj
+	del libbz2.lib 
+	del bzip2.exe
+	del bzip2recover.exe
+	del sample1.rb2 
+	del sample2.rb2 
+	del sample3.rb2
+	del sample1.tst 
+	del sample2.tst
+	del sample3.tst
+
+.c.obj: 
+	$(CC) $(CFLAGS) -c $*.c -o $*.obj
+
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/manual.html b/contrib/vmap_extractor_v2/stormlib/bzip2/manual.html
new file mode 100644
index 00000000000..b28cc79a8c6
--- /dev/null
+++ b/contrib/vmap_extractor_v2/stormlib/bzip2/manual.html
@@ -0,0 +1,2687 @@
+
+
+
+bzip2 and libbzip2, version 1.0.3
+
+
+
+
+
+
+

+bzip2 and libbzip2, version 1.0.3

+

A program and library for data compression

+
+

+Julian Seward +

+
http://www.bzip.org
+
+

Version 1.0.3 of 15 February 2005

+
+
+

This program, bzip2, the + associated library libbzip2, and + all documentation, are copyright © 1996-2005 Julian Seward. + All rights reserved.

+

Redistribution and use in source and binary forms, with + or without modification, are permitted provided that the + following conditions are met:

+
    +
  • Redistributions of source code must retain the + above copyright notice, this list of conditions and the + following disclaimer.

  • +
  • The origin of this software must not be + misrepresented; you must not claim that you wrote the original + software. If you use this software in a product, an + acknowledgment in the product documentation would be + appreciated but is not required.

  • +
  • Altered source versions must be plainly marked + as such, and must not be misrepresented as being the original + software.

  • +
  • The name of the author may not be used to + endorse or promote products derived from this software without + specific prior written permission.

  • +
+

THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE.

+

PATENTS: To the best of my knowledge, + bzip2 and + libbzip2 do not use any patented + algorithms. However, I do not have the resources to carry + out a patent search. Therefore I cannot give any guarantee of + the above statement. +

+
+
+
+
+
+ +
+
+

+1. Introduction

+
+
+

bzip2 compresses files +using the Burrows-Wheeler block-sorting text compression +algorithm, and Huffman coding. Compression is generally +considerably better than that achieved by more conventional +LZ77/LZ78-based compressors, and approaches the performance of +the PPM family of statistical compressors.

+

bzip2 is built on top of +libbzip2, a flexible library for +handling compressed data in the +bzip2 format. This manual +describes both how to use the program and how to work with the +library interface. Most of the manual is devoted to this +library, not the program, which is good news if your interest is +only in the program.

+
    +
  • How to use bzip2 describes how to use + bzip2; this is the only part + you need to read if you just want to know how to operate the + program.

  • +
  • Programming with libbzip2 describes the + programming interfaces in detail, and

  • +
  • Miscellanea records some + miscellaneous notes which I thought ought to be recorded + somewhere.

  • +
+
+
+
+

+2. How to use bzip2

+
+
+ +

This chapter contains a copy of the +bzip2 man page, and nothing +else.

+
+
+

+2.1. NAME

+
+
+
    +
  • bzip2, + bunzip2 - a block-sorting file + compressor, v1.0.3

  • +
  • bzcat - + decompresses files to stdout

  • +
  • bzip2recover - + recovers data from damaged bzip2 files

  • +
+
+
+
+

+2.2. SYNOPSIS

+
+
+
    +
  • bzip2 [ + -cdfkqstvzVL123456789 ] [ filenames ... ]

  • +
  • bunzip2 [ + -fkvsVL ] [ filenames ... ]

  • +
  • bzcat [ -s ] [ + filenames ... ]

  • +
  • bzip2recover + filename

  • +
+
+
+
+

+2.3. DESCRIPTION

+
+
+

bzip2 compresses files +using the Burrows-Wheeler block sorting text compression +algorithm, and Huffman coding. Compression is generally +considerably better than that achieved by more conventional +LZ77/LZ78-based compressors, and approaches the performance of +the PPM family of statistical compressors.

+

The command-line options are deliberately very similar to +those of GNU gzip, but they are +not identical.

+

bzip2 expects a list of +file names to accompany the command-line flags. Each file is +replaced by a compressed version of itself, with the name +original_name.bz2. Each +compressed file has the same modification date, permissions, and, +when possible, ownership as the corresponding original, so that +these properties can be correctly restored at decompression time. +File name handling is naive in the sense that there is no +mechanism for preserving original file names, permissions, +ownerships or dates in filesystems which lack these concepts, or +have serious file name length restrictions, such as +MS-DOS.

+

bzip2 and +bunzip2 will by default not +overwrite existing files. If you want this to happen, specify +the -f flag.

+

If no file names are specified, +bzip2 compresses from standard +input to standard output. In this case, +bzip2 will decline to write +compressed output to a terminal, as this would be entirely +incomprehensible and therefore pointless.

+

bunzip2 (or +bzip2 -d) decompresses all +specified files. Files which were not created by +bzip2 will be detected and +ignored, and a warning issued. +bzip2 attempts to guess the +filename for the decompressed file from that of the compressed +file as follows:

+
    +
  • filename.bz2 + becomes + filename

  • +
  • filename.bz + becomes + filename

  • +
  • filename.tbz2 + becomes + filename.tar

  • +
  • filename.tbz + becomes + filename.tar

  • +
  • anyothername + becomes + anyothername.out

  • +
+

If the file does not end in one of the recognised endings, +.bz2, +.bz, +.tbz2 or +.tbz, +bzip2 complains that it cannot +guess the name of the original file, and uses the original name +with .out appended.

+

As with compression, supplying no filenames causes +decompression from standard input to standard output.

+

bunzip2 will correctly +decompress a file which is the concatenation of two or more +compressed files. The result is the concatenation of the +corresponding uncompressed files. Integrity testing +(-t) of concatenated compressed +files is also supported.

+

You can also compress or decompress files to the standard +output by giving the -c flag. +Multiple files may be compressed and decompressed like this. The +resulting outputs are fed sequentially to stdout. Compression of +multiple files in this manner generates a stream containing +multiple compressed file representations. Such a stream can be +decompressed correctly only by +bzip2 version 0.9.0 or later. +Earlier versions of bzip2 will +stop after decompressing the first file in the stream.

+

bzcat (or +bzip2 -dc) decompresses all +specified files to the standard output.

+

bzip2 will read arguments +from the environment variables +BZIP2 and +BZIP, in that order, and will +process them before any arguments read from the command line. +This gives a convenient way to supply default arguments.

+

Compression is always performed, even if the compressed +file is slightly larger than the original. Files of less than +about one hundred bytes tend to get larger, since the compression +mechanism has a constant overhead in the region of 50 bytes. +Random data (including the output of most file compressors) is +coded at about 8.05 bits per byte, giving an expansion of around +0.5%.

+

As a self-check for your protection, +bzip2 uses 32-bit CRCs to make +sure that the decompressed version of a file is identical to the +original. This guards against corruption of the compressed data, +and against undetected bugs in +bzip2 (hopefully very unlikely). +The chances of data corruption going undetected is microscopic, +about one chance in four billion for each file processed. Be +aware, though, that the check occurs upon decompression, so it +can only tell you that something is wrong. It can't help you +recover the original uncompressed data. You can use +bzip2recover to try to recover +data from damaged files.

+

Return values: 0 for a normal exit, 1 for environmental +problems (file not found, invalid flags, I/O errors, etc.), 2 +to indicate a corrupt compressed file, 3 for an internal +consistency error (eg, bug) which caused +bzip2 to panic.

+
+
+
+

+2.4. OPTIONS

+
+
+
+
-c --stdout
+

Compress or decompress to standard + output.

+
-d --decompress
+

Force decompression. + bzip2, + bunzip2 and + bzcat are really the same + program, and the decision about what actions to take is done on + the basis of which name is used. This flag overrides that + mechanism, and forces bzip2 to decompress.

+
-z --compress
+

The complement to + -d: forces compression, + regardless of the invokation name.

+
-t --test
+

Check integrity of the specified file(s), but + don't decompress them. This really performs a trial + decompression and throws away the result.

+
-f --force
+
+

Force overwrite of output files. Normally, + bzip2 will not overwrite + existing output files. Also forces + bzip2 to break hard links to + files, which it otherwise wouldn't do.

+

bzip2 normally declines + to decompress files which don't have the correct magic header + bytes. If forced (-f), + however, it will pass such files through unmodified. This is + how GNU gzip behaves.

+
+
-k --keep
+

Keep (don't delete) input files during + compression or decompression.

+
-s --small
+
+

Reduce memory usage, for compression, + decompression and testing. Files are decompressed and tested + using a modified algorithm which only requires 2.5 bytes per + block byte. This means any file can be decompressed in 2300k + of memory, albeit at about half the normal speed.

+

During compression, -s + selects a block size of 200k, which limits memory use to around + the same figure, at the expense of your compression ratio. In + short, if your machine is low on memory (8 megabytes or less), + use -s for everything. See + MEMORY MANAGEMENT below.

+
+
-q --quiet
+

Suppress non-essential warning messages. + Messages pertaining to I/O errors and other critical events + will not be suppressed.

+
-v --verbose
+

Verbose mode -- show the compression ratio for + each file processed. Further + -v's increase the verbosity + level, spewing out lots of information which is primarily of + interest for diagnostic purposes.

+
-L --license -V --version
+

Display the software version, license terms and + conditions.

+
-1 (or + --fast) to + -9 (or + -best)
+

Set the block size to 100 k, 200 k ... 900 k + when compressing. Has no effect when decompressing. See MEMORY MANAGEMENT below. The + --fast and + --best aliases are primarily + for GNU gzip compatibility. + In particular, --fast doesn't + make things significantly faster. And + --best merely selects the + default behaviour.

+
--
+

Treats all subsequent arguments as file names, + even if they start with a dash. This is so you can handle + files with names beginning with a dash, for example: + bzip2 -- + -myfilename.

+
+--repetitive-fast, --repetitive-best, +
+

These flags are redundant in versions 0.9.5 and + above. They provided some coarse control over the behaviour of + the sorting algorithm in earlier versions, which was sometimes + useful. 0.9.5 and above have an improved algorithm which + renders these flags irrelevant.

+
+
+
+
+

+2.5. MEMORY MANAGEMENT

+
+
+

bzip2 compresses large +files in blocks. The block size affects both the compression +ratio achieved, and the amount of memory needed for compression +and decompression. The flags -1 +through -9 specify the block +size to be 100,000 bytes through 900,000 bytes (the default) +respectively. At decompression time, the block size used for +compression is read from the header of the compressed file, and +bunzip2 then allocates itself +just enough memory to decompress the file. Since block sizes are +stored in compressed files, it follows that the flags +-1 to +-9 are irrelevant to and so +ignored during decompression.

+

Compression and decompression requirements, in bytes, can be +estimated as:

+
Compression:   400k + ( 8 x block size )
+
+Decompression: 100k + ( 4 x block size ), or
+               100k + ( 2.5 x block size )
+

Larger block sizes give rapidly diminishing marginal +returns. Most of the compression comes from the first two or +three hundred k of block size, a fact worth bearing in mind when +using bzip2 on small machines. +It is also important to appreciate that the decompression memory +requirement is set at compression time by the choice of block +size.

+

For files compressed with the default 900k block size, +bunzip2 will require about 3700 +kbytes to decompress. To support decompression of any file on a +4 megabyte machine, bunzip2 has +an option to decompress using approximately half this amount of +memory, about 2300 kbytes. Decompression speed is also halved, +so you should use this option only where necessary. The relevant +flag is -s.

+

In general, try and use the largest block size memory +constraints allow, since that maximises the compression achieved. +Compression and decompression speed are virtually unaffected by +block size.

+

Another significant point applies to files which fit in a +single block -- that means most files you'd encounter using a +large block size. The amount of real memory touched is +proportional to the size of the file, since the file is smaller +than a block. For example, compressing a file 20,000 bytes long +with the flag -9 will cause the +compressor to allocate around 7600k of memory, but only touch +400k + 20000 * 8 = 560 kbytes of it. Similarly, the decompressor +will allocate 3700k but only touch 100k + 20000 * 4 = 180 +kbytes.

+

Here is a table which summarises the maximum memory usage +for different block sizes. Also recorded is the total compressed +size for 14 files of the Calgary Text Compression Corpus +totalling 3,141,622 bytes. This column gives some feel for how +compression varies with block size. These figures tend to +understate the advantage of larger block sizes for larger files, +since the Corpus is dominated by smaller files.

+
        Compress   Decompress   Decompress   Corpus
+Flag     usage      usage       -s usage     Size
+
+ -1      1200k       500k         350k      914704
+ -2      2000k       900k         600k      877703
+ -3      2800k      1300k         850k      860338
+ -4      3600k      1700k        1100k      846899
+ -5      4400k      2100k        1350k      845160
+ -6      5200k      2500k        1600k      838626
+ -7      6100k      2900k        1850k      834096
+ -8      6800k      3300k        2100k      828642
+ -9      7600k      3700k        2350k      828642
+
+
+
+

+2.6. RECOVERING DATA FROM DAMAGED FILES

+
+
+

bzip2 compresses files in +blocks, usually 900kbytes long. Each block is handled +independently. If a media or transmission error causes a +multi-block .bz2 file to become +damaged, it may be possible to recover data from the undamaged +blocks in the file.

+

The compressed representation of each block is delimited by +a 48-bit pattern, which makes it possible to find the block +boundaries with reasonable certainty. Each block also carries +its own 32-bit CRC, so damaged blocks can be distinguished from +undamaged ones.

+

bzip2recover is a simple +program whose purpose is to search for blocks in +.bz2 files, and write each block +out into its own .bz2 file. You +can then use bzip2 -t to test +the integrity of the resulting files, and decompress those which +are undamaged.

+

bzip2recover takes a +single argument, the name of the damaged file, and writes a +number of files rec0001file.bz2, +rec0002file.bz2, etc, containing +the extracted blocks. The output filenames are designed so that +the use of wildcards in subsequent processing -- for example, +bzip2 -dc rec*file.bz2 > +recovered_data -- lists the files in the correct +order.

+

bzip2recover should be of +most use dealing with large .bz2 +files, as these will contain many blocks. It is clearly futile +to use it on damaged single-block files, since a damaged block +cannot be recovered. If you wish to minimise any potential data +loss through media or transmission errors, you might consider +compressing with a smaller block size.

+
+
+
+

+2.7. PERFORMANCE NOTES

+
+
+

The sorting phase of compression gathers together similar +strings in the file. Because of this, files containing very long +runs of repeated symbols, like "aabaabaabaab ..." (repeated +several hundred times) may compress more slowly than normal. +Versions 0.9.5 and above fare much better than previous versions +in this respect. The ratio between worst-case and average-case +compression time is in the region of 10:1. For previous +versions, this figure was more like 100:1. You can use the +-vvvv option to monitor progress +in great detail, if you want.

+

Decompression speed is unaffected by these +phenomena.

+

bzip2 usually allocates +several megabytes of memory to operate in, and then charges all +over it in a fairly random fashion. This means that performance, +both for compressing and decompressing, is largely determined by +the speed at which your machine can service cache misses. +Because of this, small changes to the code to reduce the miss +rate have been observed to give disproportionately large +performance improvements. I imagine +bzip2 will perform best on +machines with very large caches.

+
+
+
+

+2.8. CAVEATS

+
+
+

I/O error messages are not as helpful as they could be. +bzip2 tries hard to detect I/O +errors and exit cleanly, but the details of what the problem is +sometimes seem rather misleading.

+

This manual page pertains to version 1.0.3 of +bzip2. Compressed data created +by this version is entirely forwards and backwards compatible +with the previous public releases, versions 0.1pl2, 0.9.0 and +0.9.5, 1.0.0, 1.0.1 and 1.0.2, but with the following exception: 0.9.0 +and above can correctly decompress multiple concatenated +compressed files. 0.1pl2 cannot do this; it will stop after +decompressing just the first file in the stream.

+

bzip2recover versions +prior to 1.0.2 used 32-bit integers to represent bit positions in +compressed files, so it could not handle compressed files more +than 512 megabytes long. Versions 1.0.2 and above use 64-bit ints +on some platforms which support them (GNU supported targets, and +Windows). To establish whether or not +bzip2recover was built with such +a limitation, run it without arguments. In any event you can +build yourself an unlimited version if you can recompile it with +MaybeUInt64 set to be an +unsigned 64-bit integer.

+
+
+
+

+2.9. AUTHOR

+
+
+

Julian Seward, +jseward@bzip.org

+

The ideas embodied in +bzip2 are due to (at least) the +following people: Michael Burrows and David Wheeler (for the +block sorting transformation), David Wheeler (again, for the +Huffman coder), Peter Fenwick (for the structured coding model in +the original bzip, and many +refinements), and Alistair Moffat, Radford Neal and Ian Witten +(for the arithmetic coder in the original +bzip). I am much indebted for +their help, support and advice. See the manual in the source +distribution for pointers to sources of documentation. Christian +von Roques encouraged me to look for faster sorting algorithms, +so as to speed up compression. Bela Lubkin encouraged me to +improve the worst-case compression performance. +Donna Robinson XMLised the documentation. +Many people sent +patches, helped with portability problems, lent machines, gave +advice and were generally helpful.

+
+
+
+
+

+3.  +Programming with libbzip2 +

+
+
+ +

This chapter describes the programming interface to +libbzip2.

+

For general background information, particularly about +memory use and performance aspects, you'd be well advised to read +How to use bzip2 as well.

+
+
+

+3.1. Top-level structure

+
+
+

libbzip2 is a flexible +library for compressing and decompressing data in the +bzip2 data format. Although +packaged as a single entity, it helps to regard the library as +three separate parts: the low level interface, and the high level +interface, and some utility functions.

+

The structure of +libbzip2's interfaces is similar +to that of Jean-loup Gailly's and Mark Adler's excellent +zlib library.

+

All externally visible symbols have names beginning +BZ2_. This is new in version +1.0. The intention is to minimise pollution of the namespaces of +library clients.

+

To use any part of the library, you need to +#include <bzlib.h> +into your sources.

+
+
+

+3.1.1. Low-level summary

+
+
+

This interface provides services for compressing and +decompressing data in memory. There's no provision for dealing +with files, streams or any other I/O mechanisms, just straight +memory-to-memory work. In fact, this part of the library can be +compiled without inclusion of +stdio.h, which may be helpful +for embedded applications.

+

The low-level part of the library has no global variables +and is therefore thread-safe.

+

Six routines make up the low level interface: +BZ2_bzCompressInit, +BZ2_bzCompress, and +BZ2_bzCompressEnd for +compression, and a corresponding trio +BZ2_bzDecompressInit, +BZ2_bzDecompress and +BZ2_bzDecompressEnd for +decompression. The *Init +functions allocate memory for compression/decompression and do +other initialisations, whilst the +*End functions close down +operations and release memory.

+

The real work is done by +BZ2_bzCompress and +BZ2_bzDecompress. These +compress and decompress data from a user-supplied input buffer to +a user-supplied output buffer. These buffers can be any size; +arbitrary quantities of data are handled by making repeated calls +to these functions. This is a flexible mechanism allowing a +consumer-pull style of activity, or producer-push, or a mixture +of both.

+
+
+
+

+3.1.2. High-level summary

+
+
+

This interface provides some handy wrappers around the +low-level interface to facilitate reading and writing +bzip2 format files +(.bz2 files). The routines +provide hooks to facilitate reading files in which the +bzip2 data stream is embedded +within some larger-scale file structure, or where there are +multiple bzip2 data streams +concatenated end-to-end.

+

For reading files, +BZ2_bzReadOpen, +BZ2_bzRead, +BZ2_bzReadClose and +BZ2_bzReadGetUnused are +supplied. For writing files, +BZ2_bzWriteOpen, +BZ2_bzWrite and +BZ2_bzWriteFinish are +available.

+

As with the low-level library, no global variables are used +so the library is per se thread-safe. However, if I/O errors +occur whilst reading or writing the underlying compressed files, +you may have to consult errno to +determine the cause of the error. In that case, you'd need a C +library which correctly supports +errno in a multithreaded +environment.

+

To make the library a little simpler and more portable, +BZ2_bzReadOpen and +BZ2_bzWriteOpen require you to +pass them file handles (FILE*s) +which have previously been opened for reading or writing +respectively. That avoids portability problems associated with +file operations and file attributes, whilst not being much of an +imposition on the programmer.

+
+
+
+

+3.1.3. Utility functions summary

+
+
+

For very simple needs, +BZ2_bzBuffToBuffCompress and +BZ2_bzBuffToBuffDecompress are +provided. These compress data in memory from one buffer to +another buffer in a single function call. You should assess +whether these functions fulfill your memory-to-memory +compression/decompression requirements before investing effort in +understanding the more general but more complex low-level +interface.

+

Yoshioka Tsuneo +(QWF00133@niftyserve.or.jp / +tsuneo-y@is.aist-nara.ac.jp) has +contributed some functions to give better +zlib compatibility. These +functions are BZ2_bzopen, +BZ2_bzread, +BZ2_bzwrite, +BZ2_bzflush, +BZ2_bzclose, +BZ2_bzerror and +BZ2_bzlibVersion. You may find +these functions more convenient for simple file reading and +writing, than those in the high-level interface. These functions +are not (yet) officially part of the library, and are minimally +documented here. If they break, you get to keep all the pieces. +I hope to document them properly when time permits.

+

Yoshioka also contributed modifications to allow the +library to be built as a Windows DLL.

+
+
+
+
+

+3.2. Error handling

+
+
+

The library is designed to recover cleanly in all +situations, including the worst-case situation of decompressing +random data. I'm not 100% sure that it can always do this, so +you might want to add a signal handler to catch segmentation +violations during decompression if you are feeling especially +paranoid. I would be interested in hearing more about the +robustness of the library to corrupted compressed data.

+

Version 1.0.3 more robust in this respect than any +previous version. Investigations with Valgrind (a tool for detecting +problems with memory management) indicate +that, at least for the few files I tested, all single-bit errors +in the decompressed data are caught properly, with no +segmentation faults, no uses of uninitialised data, no out of +range reads or writes, and no infinite looping in the decompressor. +So it's certainly pretty robust, although +I wouldn't claim it to be totally bombproof.

+

The file bzlib.h contains +all definitions needed to use the library. In particular, you +should definitely not include +bzlib_private.h.

+

In bzlib.h, the various +return values are defined. The following list is not intended as +an exhaustive description of the circumstances in which a given +value may be returned -- those descriptions are given later. +Rather, it is intended to convey the rough meaning of each return +value. The first five actions are normal and not intended to +denote an error situation.

+
+
BZ_OK
+

The requested action was completed + successfully.

+
BZ_RUN_OK, BZ_FLUSH_OK, + BZ_FINISH_OK
+

In + BZ2_bzCompress, the requested + flush/finish/nothing-special action was completed + successfully.

+
BZ_STREAM_END
+

Compression of data was completed, or the + logical stream end was detected during + decompression.

+
+

The following return values indicate an error of some +kind.

+
+
BZ_CONFIG_ERROR
+

Indicates that the library has been improperly + compiled on your platform -- a major configuration error. + Specifically, it means that + sizeof(char), + sizeof(short) and + sizeof(int) are not 1, 2 and + 4 respectively, as they should be. Note that the library + should still work properly on 64-bit platforms which follow + the LP64 programming model -- that is, where + sizeof(long) and + sizeof(void*) are 8. Under + LP64, sizeof(int) is still 4, + so libbzip2, which doesn't + use the long type, is + OK.

+
BZ_SEQUENCE_ERROR
+

When using the library, it is important to call + the functions in the correct sequence and with data structures + (buffers etc) in the correct states. + libbzip2 checks as much as it + can to ensure this is happening, and returns + BZ_SEQUENCE_ERROR if not. + Code which complies precisely with the function semantics, as + detailed below, should never receive this value; such an event + denotes buggy code which you should + investigate.

+
BZ_PARAM_ERROR
+

Returned when a parameter to a function call is + out of range or otherwise manifestly incorrect. As with + BZ_SEQUENCE_ERROR, this + denotes a bug in the client code. The distinction between + BZ_PARAM_ERROR and + BZ_SEQUENCE_ERROR is a bit + hazy, but still worth making.

+
BZ_MEM_ERROR
+

Returned when a request to allocate memory + failed. Note that the quantity of memory needed to decompress + a stream cannot be determined until the stream's header has + been read. So + BZ2_bzDecompress and + BZ2_bzRead may return + BZ_MEM_ERROR even though some + of the compressed data has been read. The same is not true + for compression; once + BZ2_bzCompressInit or + BZ2_bzWriteOpen have + successfully completed, + BZ_MEM_ERROR cannot + occur.

+
BZ_DATA_ERROR
+

Returned when a data integrity error is + detected during decompression. Most importantly, this means + when stored and computed CRCs for the data do not match. This + value is also returned upon detection of any other anomaly in + the compressed data.

+
BZ_DATA_ERROR_MAGIC
+

As a special case of + BZ_DATA_ERROR, it is + sometimes useful to know when the compressed stream does not + start with the correct magic bytes ('B' 'Z' + 'h').

+
BZ_IO_ERROR
+

Returned by + BZ2_bzRead and + BZ2_bzWrite when there is an + error reading or writing in the compressed file, and by + BZ2_bzReadOpen and + BZ2_bzWriteOpen for attempts + to use a file for which the error indicator (viz, + ferror(f)) is set. On + receipt of BZ_IO_ERROR, the + caller should consult errno + and/or perror to acquire + operating-system specific information about the + problem.

+
BZ_UNEXPECTED_EOF
+

Returned by + BZ2_bzRead when the + compressed file finishes before the logical end of stream is + detected.

+
BZ_OUTBUFF_FULL
+

Returned by + BZ2_bzBuffToBuffCompress and + BZ2_bzBuffToBuffDecompress to + indicate that the output data will not fit into the output + buffer provided.

+
+
+
+
+

+3.3. Low-level interface

+
+
+
+
+

+3.3.1. BZ2_bzCompressInit

+
+
+
typedef struct {
+  char *next_in;
+  unsigned int avail_in;
+  unsigned int total_in_lo32;
+  unsigned int total_in_hi32;
+
+  char *next_out;
+  unsigned int avail_out;
+  unsigned int total_out_lo32;
+  unsigned int total_out_hi32;
+
+  void *state;
+
+  void *(*bzalloc)(void *,int,int);
+  void (*bzfree)(void *,void *);
+  void *opaque;
+} bz_stream;
+
+int BZ2_bzCompressInit ( bz_stream *strm, 
+                         int blockSize100k, 
+                         int verbosity,
+                         int workFactor );
+

Prepares for compression. The +bz_stream structure holds all +data pertaining to the compression activity. A +bz_stream structure should be +allocated and initialised prior to the call. The fields of +bz_stream comprise the entirety +of the user-visible data. state +is a pointer to the private data structures required for +compression.

+

Custom memory allocators are supported, via fields +bzalloc, +bzfree, and +opaque. The value +opaque is passed to as the first +argument to all calls to bzalloc +and bzfree, but is otherwise +ignored by the library. The call bzalloc ( +opaque, n, m ) is expected to return a pointer +p to n * +m bytes of memory, and bzfree ( +opaque, p ) should free that memory.

+

If you don't want to use a custom memory allocator, set +bzalloc, +bzfree and +opaque to +NULL, and the library will then +use the standard malloc / +free routines.

+

Before calling +BZ2_bzCompressInit, fields +bzalloc, +bzfree and +opaque should be filled +appropriately, as just described. Upon return, the internal +state will have been allocated and initialised, and +total_in_lo32, +total_in_hi32, +total_out_lo32 and +total_out_hi32 will have been +set to zero. These four fields are used by the library to inform +the caller of the total amount of data passed into and out of the +library, respectively. You should not try to change them. As of +version 1.0, 64-bit counts are maintained, even on 32-bit +platforms, using the _hi32 +fields to store the upper 32 bits of the count. So, for example, +the total amount of data in is (total_in_hi32 +<< 32) + total_in_lo32.

+

Parameter blockSize100k +specifies the block size to be used for compression. It should +be a value between 1 and 9 inclusive, and the actual block size +used is 100000 x this figure. 9 gives the best compression but +takes most memory.

+

Parameter verbosity should +be set to a number between 0 and 4 inclusive. 0 is silent, and +greater numbers give increasingly verbose monitoring/debugging +output. If the library has been compiled with +-DBZ_NO_STDIO, no such output +will appear for any verbosity setting.

+

Parameter workFactor +controls how the compression phase behaves when presented with +worst case, highly repetitive, input data. If compression runs +into difficulties caused by repetitive data, the library switches +from the standard sorting algorithm to a fallback algorithm. The +fallback is slower than the standard algorithm by perhaps a +factor of three, but always behaves reasonably, no matter how bad +the input.

+

Lower values of workFactor +reduce the amount of effort the standard algorithm will expend +before resorting to the fallback. You should set this parameter +carefully; too low, and many inputs will be handled by the +fallback algorithm and so compress rather slowly, too high, and +your average-to-worst case compression times can become very +large. The default value of 30 gives reasonable behaviour over a +wide range of circumstances.

+

Allowable values range from 0 to 250 inclusive. 0 is a +special case, equivalent to using the default value of 30.

+

Note that the compressed output generated is the same +regardless of whether or not the fallback algorithm is +used.

+

Be aware also that this parameter may disappear entirely in +future versions of the library. In principle it should be +possible to devise a good way to automatically choose which +algorithm to use. Such a mechanism would render the parameter +obsolete.

+

Possible return values:

+
BZ_CONFIG_ERROR
+  if the library has been mis-compiled
+BZ_PARAM_ERROR
+  if strm is NULL 
+  or blockSize < 1 or blockSize > 9
+  or verbosity < 0 or verbosity > 4
+  or workFactor < 0 or workFactor > 250
+BZ_MEM_ERROR 
+  if not enough memory is available
+BZ_OK 
+  otherwise
+

Allowable next actions:

+
BZ2_bzCompress
+  if BZ_OK is returned
+  no specific action needed in case of error
+
+
+
+

+3.3.2. BZ2_bzCompress

+
+
+
int BZ2_bzCompress ( bz_stream *strm, int action );
+

Provides more input and/or output buffer space for the +library. The caller maintains input and output buffers, and +calls BZ2_bzCompress to transfer +data between them.

+

Before each call to +BZ2_bzCompress, +next_in should point at the data +to be compressed, and avail_in +should indicate how many bytes the library may read. +BZ2_bzCompress updates +next_in, +avail_in and +total_in to reflect the number +of bytes it has read.

+

Similarly, next_out should +point to a buffer in which the compressed data is to be placed, +with avail_out indicating how +much output space is available. +BZ2_bzCompress updates +next_out, +avail_out and +total_out to reflect the number +of bytes output.

+

You may provide and remove as little or as much data as you +like on each call of +BZ2_bzCompress. In the limit, +it is acceptable to supply and remove data one byte at a time, +although this would be terribly inefficient. You should always +ensure that at least one byte of output space is available at +each call.

+

A second purpose of +BZ2_bzCompress is to request a +change of mode of the compressed stream.

+

Conceptually, a compressed stream can be in one of four +states: IDLE, RUNNING, FLUSHING and FINISHING. Before +initialisation +(BZ2_bzCompressInit) and after +termination (BZ2_bzCompressEnd), +a stream is regarded as IDLE.

+

Upon initialisation +(BZ2_bzCompressInit), the stream +is placed in the RUNNING state. Subsequent calls to +BZ2_bzCompress should pass +BZ_RUN as the requested action; +other actions are illegal and will result in +BZ_SEQUENCE_ERROR.

+

At some point, the calling program will have provided all +the input data it wants to. It will then want to finish up -- in +effect, asking the library to process any data it might have +buffered internally. In this state, +BZ2_bzCompress will no longer +attempt to read data from +next_in, but it will want to +write data to next_out. Because +the output buffer supplied by the user can be arbitrarily small, +the finishing-up operation cannot necessarily be done with a +single call of +BZ2_bzCompress.

+

Instead, the calling program passes +BZ_FINISH as an action to +BZ2_bzCompress. This changes +the stream's state to FINISHING. Any remaining input (ie, +next_in[0 .. avail_in-1]) is +compressed and transferred to the output buffer. To do this, +BZ2_bzCompress must be called +repeatedly until all the output has been consumed. At that +point, BZ2_bzCompress returns +BZ_STREAM_END, and the stream's +state is set back to IDLE. +BZ2_bzCompressEnd should then be +called.

+

Just to make sure the calling program does not cheat, the +library makes a note of avail_in +at the time of the first call to +BZ2_bzCompress which has +BZ_FINISH as an action (ie, at +the time the program has announced its intention to not supply +any more input). By comparing this value with that of +avail_in over subsequent calls +to BZ2_bzCompress, the library +can detect any attempts to slip in more data to compress. Any +calls for which this is detected will return +BZ_SEQUENCE_ERROR. This +indicates a programming mistake which should be corrected.

+

Instead of asking to finish, the calling program may ask +BZ2_bzCompress to take all the +remaining input, compress it and terminate the current +(Burrows-Wheeler) compression block. This could be useful for +error control purposes. The mechanism is analogous to that for +finishing: call BZ2_bzCompress +with an action of BZ_FLUSH, +remove output data, and persist with the +BZ_FLUSH action until the value +BZ_RUN is returned. As with +finishing, BZ2_bzCompress +detects any attempt to provide more input data once the flush has +begun.

+

Once the flush is complete, the stream returns to the +normal RUNNING state.

+

This all sounds pretty complex, but isn't really. Here's a +table which shows which actions are allowable in each state, what +action will be taken, what the next state is, and what the +non-error return values are. Note that you can't explicitly ask +what state the stream is in, but nor do you need to -- it can be +inferred from the values returned by +BZ2_bzCompress.

+
IDLE/any
+  Illegal.  IDLE state only exists after BZ2_bzCompressEnd or
+  before BZ2_bzCompressInit.
+  Return value = BZ_SEQUENCE_ERROR
+
+RUNNING/BZ_RUN
+  Compress from next_in to next_out as much as possible.
+  Next state = RUNNING
+  Return value = BZ_RUN_OK
+
+RUNNING/BZ_FLUSH
+  Remember current value of next_in. Compress from next_in
+  to next_out as much as possible, but do not accept any more input.
+  Next state = FLUSHING
+  Return value = BZ_FLUSH_OK
+
+RUNNING/BZ_FINISH
+  Remember current value of next_in. Compress from next_in
+  to next_out as much as possible, but do not accept any more input.
+  Next state = FINISHING
+  Return value = BZ_FINISH_OK
+
+FLUSHING/BZ_FLUSH
+  Compress from next_in to next_out as much as possible, 
+  but do not accept any more input.
+  If all the existing input has been used up and all compressed
+  output has been removed
+    Next state = RUNNING; Return value = BZ_RUN_OK
+  else
+    Next state = FLUSHING; Return value = BZ_FLUSH_OK
+
+FLUSHING/other     
+  Illegal.
+  Return value = BZ_SEQUENCE_ERROR
+
+FINISHING/BZ_FINISH
+  Compress from next_in to next_out as much as possible,
+  but to not accept any more input.  
+  If all the existing input has been used up and all compressed
+  output has been removed
+    Next state = IDLE; Return value = BZ_STREAM_END
+  else
+    Next state = FINISHING; Return value = BZ_FINISHING
+
+FINISHING/other
+  Illegal.
+  Return value = BZ_SEQUENCE_ERROR
+

That still looks complicated? Well, fair enough. The +usual sequence of calls for compressing a load of data is:

+
    +
  1. Get started with + BZ2_bzCompressInit.

  2. +
  3. Shovel data in and shlurp out its compressed form + using zero or more calls of + BZ2_bzCompress with action = + BZ_RUN.

  4. +
  5. Finish up. Repeatedly call + BZ2_bzCompress with action = + BZ_FINISH, copying out the + compressed output, until + BZ_STREAM_END is + returned.

  6. +
  7. Close up and go home. Call + BZ2_bzCompressEnd.

  8. +
+

If the data you want to compress fits into your input +buffer all at once, you can skip the calls of +BZ2_bzCompress ( ..., BZ_RUN ) +and just do the BZ2_bzCompress ( ..., BZ_FINISH +) calls.

+

All required memory is allocated by +BZ2_bzCompressInit. The +compression library can accept any data at all (obviously). So +you shouldn't get any error return values from the +BZ2_bzCompress calls. If you +do, they will be +BZ_SEQUENCE_ERROR, and indicate +a bug in your programming.

+

Trivial other possible return values:

+
BZ_PARAM_ERROR
+  if strm is NULL, or strm->s is NULL
+
+
+
+

+3.3.3. BZ2_bzCompressEnd

+
+
+
int BZ2_bzCompressEnd ( bz_stream *strm );
+

Releases all memory associated with a compression +stream.

+

Possible return values:

+
BZ_PARAM_ERROR  if strm is NULL or strm->s is NULL
+BZ_OK           otherwise
+
+
+
+

+3.3.4. BZ2_bzDecompressInit

+
+
+
int BZ2_bzDecompressInit ( bz_stream *strm, int verbosity, int small );
+

Prepares for decompression. As with +BZ2_bzCompressInit, a +bz_stream record should be +allocated and initialised before the call. Fields +bzalloc, +bzfree and +opaque should be set if a custom +memory allocator is required, or made +NULL for the normal +malloc / +free routines. Upon return, the +internal state will have been initialised, and +total_in and +total_out will be zero.

+

For the meaning of parameter +verbosity, see +BZ2_bzCompressInit.

+

If small is nonzero, the +library will use an alternative decompression algorithm which +uses less memory but at the cost of decompressing more slowly +(roughly speaking, half the speed, but the maximum memory +requirement drops to around 2300k). See How to use bzip2 +for more information on memory management.

+

Note that the amount of memory needed to decompress a +stream cannot be determined until the stream's header has been +read, so even if +BZ2_bzDecompressInit succeeds, a +subsequent BZ2_bzDecompress +could fail with +BZ_MEM_ERROR.

+

Possible return values:

+
BZ_CONFIG_ERROR
+  if the library has been mis-compiled
+BZ_PARAM_ERROR
+  if ( small != 0 && small != 1 )
+  or (verbosity <; 0 || verbosity > 4)
+BZ_MEM_ERROR
+  if insufficient memory is available
+

Allowable next actions:

+
BZ2_bzDecompress
+  if BZ_OK was returned
+  no specific action required in case of error
+
+
+
+

+3.3.5. BZ2_bzDecompress

+
+
+
int BZ2_bzDecompress ( bz_stream *strm );
+

Provides more input and/out output buffer space for the +library. The caller maintains input and output buffers, and uses +BZ2_bzDecompress to transfer +data between them.

+

Before each call to +BZ2_bzDecompress, +next_in should point at the +compressed data, and avail_in +should indicate how many bytes the library may read. +BZ2_bzDecompress updates +next_in, +avail_in and +total_in to reflect the number +of bytes it has read.

+

Similarly, next_out should +point to a buffer in which the uncompressed output is to be +placed, with avail_out +indicating how much output space is available. +BZ2_bzCompress updates +next_out, +avail_out and +total_out to reflect the number +of bytes output.

+

You may provide and remove as little or as much data as you +like on each call of +BZ2_bzDecompress. In the limit, +it is acceptable to supply and remove data one byte at a time, +although this would be terribly inefficient. You should always +ensure that at least one byte of output space is available at +each call.

+

Use of BZ2_bzDecompress is +simpler than +BZ2_bzCompress.

+

You should provide input and remove output as described +above, and repeatedly call +BZ2_bzDecompress until +BZ_STREAM_END is returned. +Appearance of BZ_STREAM_END +denotes that BZ2_bzDecompress +has detected the logical end of the compressed stream. +BZ2_bzDecompress will not +produce BZ_STREAM_END until all +output data has been placed into the output buffer, so once +BZ_STREAM_END appears, you are +guaranteed to have available all the decompressed output, and +BZ2_bzDecompressEnd can safely +be called.

+

If case of an error return value, you should call +BZ2_bzDecompressEnd to clean up +and release memory.

+

Possible return values:

+
BZ_PARAM_ERROR
+  if strm is NULL or strm->s is NULL
+  or strm->avail_out < 1
+BZ_DATA_ERROR
+  if a data integrity error is detected in the compressed stream
+BZ_DATA_ERROR_MAGIC
+  if the compressed stream doesn't begin with the right magic bytes
+BZ_MEM_ERROR
+  if there wasn't enough memory available
+BZ_STREAM_END
+  if the logical end of the data stream was detected and all
+  output in has been consumed, eg s-->avail_out > 0
+BZ_OK
+  otherwise
+

Allowable next actions:

+
BZ2_bzDecompress
+  if BZ_OK was returned
+BZ2_bzDecompressEnd
+  otherwise
+
+
+
+

+3.3.6. BZ2_bzDecompressEnd

+
+
+
int BZ2_bzDecompressEnd ( bz_stream *strm );
+

Releases all memory associated with a decompression +stream.

+

Possible return values:

+
BZ_PARAM_ERROR
+  if strm is NULL or strm->s is NULL
+BZ_OK
+  otherwise
+

Allowable next actions:

+
  None.
+
+
+
+
+

+3.4. High-level interface

+
+
+

This interface provides functions for reading and writing +bzip2 format files. First, some +general points.

+
    +
  • All of the functions take an + int* first argument, + bzerror. After each call, + bzerror should be consulted + first to determine the outcome of the call. If + bzerror is + BZ_OK, the call completed + successfully, and only then should the return value of the + function (if any) be consulted. If + bzerror is + BZ_IO_ERROR, there was an + error reading/writing the underlying compressed file, and you + should then consult errno / + perror to determine the cause + of the difficulty. bzerror + may also be set to various other values; precise details are + given on a per-function basis below.

  • +
  • If bzerror indicates + an error (ie, anything except + BZ_OK and + BZ_STREAM_END), you should + immediately call + BZ2_bzReadClose (or + BZ2_bzWriteClose, depending on + whether you are attempting to read or to write) to free up all + resources associated with the stream. Once an error has been + indicated, behaviour of all calls except + BZ2_bzReadClose + (BZ2_bzWriteClose) is + undefined. The implication is that (1) + bzerror should be checked + after each call, and (2) if + bzerror indicates an error, + BZ2_bzReadClose + (BZ2_bzWriteClose) should then + be called to clean up.

  • +
  • The FILE* arguments + passed to BZ2_bzReadOpen / + BZ2_bzWriteOpen should be set + to binary mode. Most Unix systems will do this by default, but + other platforms, including Windows and Mac, will not. If you + omit this, you may encounter problems when moving code to new + platforms.

  • +
  • Memory allocation requests are handled by + malloc / + free. At present there is no + facility for user-defined memory allocators in the file I/O + functions (could easily be added, though).

  • +
+
+
+

+3.4.1. BZ2_bzReadOpen

+
+
+
typedef void BZFILE;
+
+BZFILE *BZ2_bzReadOpen( int *bzerror, FILE *f, 
+                        int verbosity, int small,
+                        void *unused, int nUnused );
+

Prepare to read compressed data from file handle +f. +f should refer to a file which +has been opened for reading, and for which the error indicator +(ferror(f))is not set. If +small is 1, the library will try +to decompress using less memory, at the expense of speed.

+

For reasons explained below, +BZ2_bzRead will decompress the +nUnused bytes starting at +unused, before starting to read +from the file f. At most +BZ_MAX_UNUSED bytes may be +supplied like this. If this facility is not required, you should +pass NULL and +0 for +unused and +nUnused respectively.

+

For the meaning of parameters +small and +verbosity, see +BZ2_bzDecompressInit.

+

The amount of memory needed to decompress a file cannot be +determined until the file's header has been read. So it is +possible that BZ2_bzReadOpen +returns BZ_OK but a subsequent +call of BZ2_bzRead will return +BZ_MEM_ERROR.

+

Possible assignments to +bzerror:

+
BZ_CONFIG_ERROR
+  if the library has been mis-compiled
+BZ_PARAM_ERROR
+  if f is NULL
+  or small is neither 0 nor 1
+  or ( unused == NULL && nUnused != 0 )
+  or ( unused != NULL && !(0 <= nUnused <= BZ_MAX_UNUSED) )
+BZ_IO_ERROR
+  if ferror(f) is nonzero
+BZ_MEM_ERROR
+  if insufficient memory is available
+BZ_OK
+  otherwise.
+

Possible return values:

+
Pointer to an abstract BZFILE
+  if bzerror is BZ_OK
+NULL
+  otherwise
+

Allowable next actions:

+
BZ2_bzRead
+  if bzerror is BZ_OK
+BZ2_bzClose
+  otherwise
+
+
+
+

+3.4.2. BZ2_bzRead

+
+
+
int BZ2_bzRead ( int *bzerror, BZFILE *b, void *buf, int len );
+

Reads up to len +(uncompressed) bytes from the compressed file +b into the buffer +buf. If the read was +successful, bzerror is set to +BZ_OK and the number of bytes +read is returned. If the logical end-of-stream was detected, +bzerror will be set to +BZ_STREAM_END, and the number of +bytes read is returned. All other +bzerror values denote an +error.

+

BZ2_bzRead will supply +len bytes, unless the logical +stream end is detected or an error occurs. Because of this, it +is possible to detect the stream end by observing when the number +of bytes returned is less than the number requested. +Nevertheless, this is regarded as inadvisable; you should instead +check bzerror after every call +and watch out for +BZ_STREAM_END.

+

Internally, BZ2_bzRead +copies data from the compressed file in chunks of size +BZ_MAX_UNUSED bytes before +decompressing it. If the file contains more bytes than strictly +needed to reach the logical end-of-stream, +BZ2_bzRead will almost certainly +read some of the trailing data before signalling +BZ_SEQUENCE_END. To collect the +read but unused data once +BZ_SEQUENCE_END has appeared, +call BZ2_bzReadGetUnused +immediately before +BZ2_bzReadClose.

+

Possible assignments to +bzerror:

+
BZ_PARAM_ERROR
+  if b is NULL or buf is NULL or len < 0
+BZ_SEQUENCE_ERROR
+  if b was opened with BZ2_bzWriteOpen
+BZ_IO_ERROR
+  if there is an error reading from the compressed file
+BZ_UNEXPECTED_EOF
+  if the compressed file ended before 
+  the logical end-of-stream was detected
+BZ_DATA_ERROR
+  if a data integrity error was detected in the compressed stream
+BZ_DATA_ERROR_MAGIC
+  if the stream does not begin with the requisite header bytes 
+  (ie, is not a bzip2 data file).  This is really 
+  a special case of BZ_DATA_ERROR.
+BZ_MEM_ERROR
+  if insufficient memory was available
+BZ_STREAM_END
+  if the logical end of stream was detected.
+BZ_OK
+  otherwise.
+

Possible return values:

+
number of bytes read
+  if bzerror is BZ_OK or BZ_STREAM_END
+undefined
+  otherwise
+

Allowable next actions:

+
collect data from buf, then BZ2_bzRead or BZ2_bzReadClose
+  if bzerror is BZ_OK
+collect data from buf, then BZ2_bzReadClose or BZ2_bzReadGetUnused
+  if bzerror is BZ_SEQUENCE_END
+BZ2_bzReadClose
+  otherwise
+
+
+
+

+3.4.3. BZ2_bzReadGetUnused

+
+
+
void BZ2_bzReadGetUnused( int* bzerror, BZFILE *b, 
+                          void** unused, int* nUnused );
+

Returns data which was read from the compressed file but +was not needed to get to the logical end-of-stream. +*unused is set to the address of +the data, and *nUnused to the +number of bytes. *nUnused will +be set to a value between 0 and +BZ_MAX_UNUSED inclusive.

+

This function may only be called once +BZ2_bzRead has signalled +BZ_STREAM_END but before +BZ2_bzReadClose.

+

Possible assignments to +bzerror:

+
BZ_PARAM_ERROR
+  if b is NULL
+  or unused is NULL or nUnused is NULL
+BZ_SEQUENCE_ERROR
+  if BZ_STREAM_END has not been signalled
+  or if b was opened with BZ2_bzWriteOpen
+BZ_OK
+  otherwise
+

Allowable next actions:

+
BZ2_bzReadClose
+
+
+
+

+3.4.4. BZ2_bzReadClose

+
+
+
void BZ2_bzReadClose ( int *bzerror, BZFILE *b );
+

Releases all memory pertaining to the compressed file +b. +BZ2_bzReadClose does not call +fclose on the underlying file +handle, so you should do that yourself if appropriate. +BZ2_bzReadClose should be called +to clean up after all error situations.

+

Possible assignments to +bzerror:

+
BZ_SEQUENCE_ERROR
+  if b was opened with BZ2_bzOpenWrite
+BZ_OK
+  otherwise
+

Allowable next actions:

+
none
+
+
+
+

+3.4.5. BZ2_bzWriteOpen

+
+
+
BZFILE *BZ2_bzWriteOpen( int *bzerror, FILE *f, 
+                         int blockSize100k, int verbosity,
+                         int workFactor );
+

Prepare to write compressed data to file handle +f. +f should refer to a file which +has been opened for writing, and for which the error indicator +(ferror(f))is not set.

+

For the meaning of parameters +blockSize100k, +verbosity and +workFactor, see +BZ2_bzCompressInit.

+

All required memory is allocated at this stage, so if the +call completes successfully, +BZ_MEM_ERROR cannot be signalled +by a subsequent call to +BZ2_bzWrite.

+

Possible assignments to +bzerror:

+
BZ_CONFIG_ERROR
+  if the library has been mis-compiled
+BZ_PARAM_ERROR
+  if f is NULL
+  or blockSize100k < 1 or blockSize100k > 9
+BZ_IO_ERROR
+  if ferror(f) is nonzero
+BZ_MEM_ERROR
+  if insufficient memory is available
+BZ_OK
+  otherwise
+

Possible return values:

+
Pointer to an abstract BZFILE
+  if bzerror is BZ_OK
+NULL
+  otherwise
+

Allowable next actions:

+
BZ2_bzWrite
+  if bzerror is BZ_OK
+  (you could go directly to BZ2_bzWriteClose, but this would be pretty pointless)
+BZ2_bzWriteClose
+  otherwise
+
+
+
+

+3.4.6. BZ2_bzWrite

+
+
+
void BZ2_bzWrite ( int *bzerror, BZFILE *b, void *buf, int len );
+

Absorbs len bytes from the +buffer buf, eventually to be +compressed and written to the file.

+

Possible assignments to +bzerror:

+
BZ_PARAM_ERROR
+  if b is NULL or buf is NULL or len < 0
+BZ_SEQUENCE_ERROR
+  if b was opened with BZ2_bzReadOpen
+BZ_IO_ERROR
+  if there is an error writing the compressed file.
+BZ_OK
+  otherwise
+
+
+
+

+3.4.7. BZ2_bzWriteClose

+
+
+
void BZ2_bzWriteClose( int *bzerror, BZFILE* f,
+                       int abandon,
+                       unsigned int* nbytes_in,
+                       unsigned int* nbytes_out );
+
+void BZ2_bzWriteClose64( int *bzerror, BZFILE* f,
+                         int abandon,
+                         unsigned int* nbytes_in_lo32,
+                         unsigned int* nbytes_in_hi32,
+                         unsigned int* nbytes_out_lo32,
+                         unsigned int* nbytes_out_hi32 );
+

Compresses and flushes to the compressed file all data so +far supplied by BZ2_bzWrite. +The logical end-of-stream markers are also written, so subsequent +calls to BZ2_bzWrite are +illegal. All memory associated with the compressed file +b is released. +fflush is called on the +compressed file, but it is not +fclose'd.

+

If BZ2_bzWriteClose is +called to clean up after an error, the only action is to release +the memory. The library records the error codes issued by +previous calls, so this situation will be detected automatically. +There is no attempt to complete the compression operation, nor to +fflush the compressed file. You +can force this behaviour to happen even in the case of no error, +by passing a nonzero value to +abandon.

+

If nbytes_in is non-null, +*nbytes_in will be set to be the +total volume of uncompressed data handled. Similarly, +nbytes_out will be set to the +total volume of compressed data written. For compatibility with +older versions of the library, +BZ2_bzWriteClose only yields the +lower 32 bits of these counts. Use +BZ2_bzWriteClose64 if you want +the full 64 bit counts. These two functions are otherwise +absolutely identical.

+

Possible assignments to +bzerror:

+
BZ_SEQUENCE_ERROR
+  if b was opened with BZ2_bzReadOpen
+BZ_IO_ERROR
+  if there is an error writing the compressed file
+BZ_OK
+  otherwise
+
+
+
+

+3.4.8. Handling embedded compressed data streams

+
+
+

The high-level library facilitates use of +bzip2 data streams which form +some part of a surrounding, larger data stream.

+
    +
  • For writing, the library takes an open file handle, + writes compressed data to it, + fflushes it but does not + fclose it. The calling + application can write its own data before and after the + compressed data stream, using that same file handle.

  • +
  • Reading is more complex, and the facilities are not as + general as they could be since generality is hard to reconcile + with efficiency. BZ2_bzRead + reads from the compressed file in blocks of size + BZ_MAX_UNUSED bytes, and in + doing so probably will overshoot the logical end of compressed + stream. To recover this data once decompression has ended, + call BZ2_bzReadGetUnused after + the last call of BZ2_bzRead + (the one returning + BZ_STREAM_END) but before + calling + BZ2_bzReadClose.

  • +
+

This mechanism makes it easy to decompress multiple +bzip2 streams placed end-to-end. +As the end of one stream, when +BZ2_bzRead returns +BZ_STREAM_END, call +BZ2_bzReadGetUnused to collect +the unused data (copy it into your own buffer somewhere). That +data forms the start of the next compressed stream. To start +uncompressing that next stream, call +BZ2_bzReadOpen again, feeding in +the unused data via the unused / +nUnused parameters. Keep doing +this until BZ_STREAM_END return +coincides with the physical end of file +(feof(f)). In this situation +BZ2_bzReadGetUnused will of +course return no data.

+

This should give some feel for how the high-level interface +can be used. If you require extra flexibility, you'll have to +bite the bullet and get to grips with the low-level +interface.

+
+
+
+

+3.4.9. Standard file-reading/writing code

+
+
+

Here's how you'd write data to a compressed file:

+
FILE*   f;
+BZFILE* b;
+int     nBuf;
+char    buf[ /* whatever size you like */ ];
+int     bzerror;
+int     nWritten;
+
+f = fopen ( "myfile.bz2", "w" );
+if ( !f ) {
+ /* handle error */
+}
+b = BZ2_bzWriteOpen( &bzerror, f, 9 );
+if (bzerror != BZ_OK) {
+ BZ2_bzWriteClose ( b );
+ /* handle error */
+}
+
+while ( /* condition */ ) {
+ /* get data to write into buf, and set nBuf appropriately */
+ nWritten = BZ2_bzWrite ( &bzerror, b, buf, nBuf );
+ if (bzerror == BZ_IO_ERROR) { 
+   BZ2_bzWriteClose ( &bzerror, b );
+   /* handle error */
+ }
+}
+
+BZ2_bzWriteClose( &bzerror, b );
+if (bzerror == BZ_IO_ERROR) {
+ /* handle error */
+}
+

And to read from a compressed file:

+
FILE*   f;
+BZFILE* b;
+int     nBuf;
+char    buf[ /* whatever size you like */ ];
+int     bzerror;
+int     nWritten;
+
+f = fopen ( "myfile.bz2", "r" );
+if ( !f ) {
+  /* handle error */
+}
+b = BZ2_bzReadOpen ( &bzerror, f, 0, NULL, 0 );
+if ( bzerror != BZ_OK ) {
+  BZ2_bzReadClose ( &bzerror, b );
+  /* handle error */
+}
+
+bzerror = BZ_OK;
+while ( bzerror == BZ_OK && /* arbitrary other conditions */) {
+  nBuf = BZ2_bzRead ( &bzerror, b, buf, /* size of buf */ );
+  if ( bzerror == BZ_OK ) {
+    /* do something with buf[0 .. nBuf-1] */
+  }
+}
+if ( bzerror != BZ_STREAM_END ) {
+   BZ2_bzReadClose ( &bzerror, b );
+   /* handle error */
+} else {
+   BZ2_bzReadClose ( &bzerror );
+}
+
+
+
+
+

+3.5. Utility functions

+
+
+
+
+

+3.5.1. BZ2_bzBuffToBuffCompress

+
+
+
int BZ2_bzBuffToBuffCompress( char*         dest,
+                              unsigned int* destLen,
+                              char*         source,
+                              unsigned int  sourceLen,
+                              int           blockSize100k,
+                              int           verbosity,
+                              int           workFactor );
+

Attempts to compress the data in source[0 +.. sourceLen-1] into the destination buffer, +dest[0 .. *destLen-1]. If the +destination buffer is big enough, +*destLen is set to the size of +the compressed data, and BZ_OK +is returned. If the compressed data won't fit, +*destLen is unchanged, and +BZ_OUTBUFF_FULL is +returned.

+

Compression in this manner is a one-shot event, done with a +single call to this function. The resulting compressed data is a +complete bzip2 format data +stream. There is no mechanism for making additional calls to +provide extra input data. If you want that kind of mechanism, +use the low-level interface.

+

For the meaning of parameters +blockSize100k, +verbosity and +workFactor, see +BZ2_bzCompressInit.

+

To guarantee that the compressed data will fit in its +buffer, allocate an output buffer of size 1% larger than the +uncompressed data, plus six hundred extra bytes.

+

BZ2_bzBuffToBuffDecompress +will not write data at or beyond +dest[*destLen], even in case of +buffer overflow.

+

Possible return values:

+
BZ_CONFIG_ERROR
+  if the library has been mis-compiled
+BZ_PARAM_ERROR
+  if dest is NULL or destLen is NULL
+  or blockSize100k < 1 or blockSize100k > 9
+  or verbosity < 0 or verbosity > 4
+  or workFactor < 0 or workFactor > 250
+BZ_MEM_ERROR
+  if insufficient memory is available 
+BZ_OUTBUFF_FULL
+  if the size of the compressed data exceeds *destLen
+BZ_OK
+  otherwise
+
+
+
+

+3.5.2. BZ2_bzBuffToBuffDecompress

+
+
+
int BZ2_bzBuffToBuffDecompress( char*         dest,
+                                unsigned int* destLen,
+                                char*         source,
+                                unsigned int  sourceLen,
+                                int           small,
+                                int           verbosity );
+

Attempts to decompress the data in source[0 +.. sourceLen-1] into the destination buffer, +dest[0 .. *destLen-1]. If the +destination buffer is big enough, +*destLen is set to the size of +the uncompressed data, and BZ_OK +is returned. If the compressed data won't fit, +*destLen is unchanged, and +BZ_OUTBUFF_FULL is +returned.

+

source is assumed to hold +a complete bzip2 format data +stream. +BZ2_bzBuffToBuffDecompress tries +to decompress the entirety of the stream into the output +buffer.

+

For the meaning of parameters +small and +verbosity, see +BZ2_bzDecompressInit.

+

Because the compression ratio of the compressed data cannot +be known in advance, there is no easy way to guarantee that the +output buffer will be big enough. You may of course make +arrangements in your code to record the size of the uncompressed +data, but such a mechanism is beyond the scope of this +library.

+

BZ2_bzBuffToBuffDecompress +will not write data at or beyond +dest[*destLen], even in case of +buffer overflow.

+

Possible return values:

+
BZ_CONFIG_ERROR
+  if the library has been mis-compiled
+BZ_PARAM_ERROR
+  if dest is NULL or destLen is NULL
+  or small != 0 && small != 1
+  or verbosity < 0 or verbosity > 4
+BZ_MEM_ERROR
+  if insufficient memory is available 
+BZ_OUTBUFF_FULL
+  if the size of the compressed data exceeds *destLen
+BZ_DATA_ERROR
+  if a data integrity error was detected in the compressed data
+BZ_DATA_ERROR_MAGIC
+  if the compressed data doesn't begin with the right magic bytes
+BZ_UNEXPECTED_EOF
+  if the compressed data ends unexpectedly
+BZ_OK
+  otherwise
+
+
+
+
+

+3.6. zlib compatibility functions

+
+
+

Yoshioka Tsuneo has contributed some functions to give +better zlib compatibility. +These functions are BZ2_bzopen, +BZ2_bzread, +BZ2_bzwrite, +BZ2_bzflush, +BZ2_bzclose, +BZ2_bzerror and +BZ2_bzlibVersion. These +functions are not (yet) officially part of the library. If they +break, you get to keep all the pieces. Nevertheless, I think +they work ok.

+
typedef void BZFILE;
+
+const char * BZ2_bzlibVersion ( void );
+

Returns a string indicating the library version.

+
BZFILE * BZ2_bzopen  ( const char *path, const char *mode );
+BZFILE * BZ2_bzdopen ( int        fd,    const char *mode );
+

Opens a .bz2 file for +reading or writing, using either its name or a pre-existing file +descriptor. Analogous to fopen +and fdopen.

+
int BZ2_bzread  ( BZFILE* b, void* buf, int len );
+int BZ2_bzwrite ( BZFILE* b, void* buf, int len );
+

Reads/writes data from/to a previously opened +BZFILE. Analogous to +fread and +fwrite.

+
int  BZ2_bzflush ( BZFILE* b );
+void BZ2_bzclose ( BZFILE* b );
+

Flushes/closes a BZFILE. +BZ2_bzflush doesn't actually do +anything. Analogous to fflush +and fclose.

+
const char * BZ2_bzerror ( BZFILE *b, int *errnum )
+

Returns a string describing the more recent error status of +b, and also sets +*errnum to its numerical +value.

+
+
+
+

+3.7. Using the library in a stdio-free environment

+
+
+
+
+

+3.7.1. Getting rid of stdio

+
+
+

In a deeply embedded application, you might want to use +just the memory-to-memory functions. You can do this +conveniently by compiling the library with preprocessor symbol +BZ_NO_STDIO defined. Doing this +gives you a library containing only the following eight +functions:

+

BZ2_bzCompressInit, +BZ2_bzCompress, +BZ2_bzCompressEnd +BZ2_bzDecompressInit, +BZ2_bzDecompress, +BZ2_bzDecompressEnd +BZ2_bzBuffToBuffCompress, +BZ2_bzBuffToBuffDecompress

+

When compiled like this, all functions will ignore +verbosity settings.

+
+
+
+

+3.7.2. Critical error handling

+
+
+

libbzip2 contains a number +of internal assertion checks which should, needless to say, never +be activated. Nevertheless, if an assertion should fail, +behaviour depends on whether or not the library was compiled with +BZ_NO_STDIO set.

+

For a normal compile, an assertion failure yields the +message:

+
+

bzip2/libbzip2: internal error number N.

+

This is a bug in bzip2/libbzip2, 1.0.3 of 15 February 2005. +Please report it to me at: jseward@bzip.org. If this happened +when you were using some program which uses libbzip2 as a +component, you should also report this bug to the author(s) +of that program. Please make an effort to report this bug; +timely and accurate bug reports eventually lead to higher +quality software. Thanks. Julian Seward, 15 February 2005. +

+
+

where N is some error code +number. If N == 1007, it also +prints some extra text advising the reader that unreliable memory +is often associated with internal error 1007. (This is a +frequently-observed-phenomenon with versions 1.0.0/1.0.1).

+

exit(3) is then +called.

+

For a stdio-free library, +assertion failures result in a call to a function declared +as:

+
extern void bz_internal_error ( int errcode );
+

The relevant code is passed as a parameter. You should +supply such a function.

+

In either case, once an assertion failure has occurred, any +bz_stream records involved can +be regarded as invalid. You should not attempt to resume normal +operation with them.

+

You may, of course, change critical error handling to suit +your needs. As I said above, critical errors indicate bugs in +the library and should not occur. All "normal" error situations +are indicated via error return codes from functions, and can be +recovered from.

+
+
+
+
+

+3.8. Making a Windows DLL

+
+
+

Everything related to Windows has been contributed by +Yoshioka Tsuneo +(QWF00133@niftyserve.or.jp / +tsuneo-y@is.aist-nara.ac.jp), so +you should send your queries to him (but perhaps Cc: me, +jseward@bzip.org).

+

My vague understanding of what to do is: using Visual C++ +5.0, open the project file +libbz2.dsp, and build. That's +all.

+

If you can't open the project file for some reason, make a +new one, naming these files: +blocksort.c, +bzlib.c, +compress.c, +crctable.c, +decompress.c, +huffman.c, +randtable.c and +libbz2.def. You will also need +to name the header files bzlib.h +and bzlib_private.h.

+

If you don't use VC++, you may need to define the +proprocessor symbol +_WIN32.

+

Finally, dlltest.c is a +sample program using the DLL. It has a project file, +dlltest.dsp.

+

If you just want a makefile for Visual C, have a look at +makefile.msc.

+

Be aware that if you compile +bzip2 itself on Win32, you must +set BZ_UNIX to 0 and +BZ_LCCWIN32 to 1, in the file +bzip2.c, before compiling. +Otherwise the resulting binary won't work correctly.

+

I haven't tried any of this stuff myself, but it all looks +plausible.

+
+
+
+
+

+4. Miscellanea

+
+
+ +

These are just some random thoughts of mine. Your mileage +may vary.

+
+
+

+4.1. Limitations of the compressed file format

+
+
+

bzip2-1.0.X, +0.9.5 and +0.9.0 use exactly the same file +format as the original version, +bzip2-0.1. This decision was +made in the interests of stability. Creating yet another +incompatible compressed file format would create further +confusion and disruption for users.

+

Nevertheless, this is not a painless decision. Development +work since the release of +bzip2-0.1 in August 1997 has +shown complexities in the file format which slow down +decompression and, in retrospect, are unnecessary. These +are:

+
    +
  • The run-length encoder, which is the first of the + compression transformations, is entirely irrelevant. The + original purpose was to protect the sorting algorithm from the + very worst case input: a string of repeated symbols. But + algorithm steps Q6a and Q6b in the original Burrows-Wheeler + technical report (SRC-124) show how repeats can be handled + without difficulty in block sorting.

  • +
  • +

    The randomisation mechanism doesn't really need to be + there. Udi Manber and Gene Myers published a suffix array + construction algorithm a few years back, which can be employed + to sort any block, no matter how repetitive, in O(N log N) + time. Subsequent work by Kunihiko Sadakane has produced a + derivative O(N (log N)^2) algorithm which usually outperforms + the Manber-Myers algorithm.

    +

    I could have changed to Sadakane's algorithm, but I find + it to be slower than bzip2's + existing algorithm for most inputs, and the randomisation + mechanism protects adequately against bad cases. I didn't + think it was a good tradeoff to make. Partly this is due to + the fact that I was not flooded with email complaints about + bzip2-0.1's performance on + repetitive data, so perhaps it isn't a problem for real + inputs.

    +

    Probably the best long-term solution, and the one I have + incorporated into 0.9.5 and above, is to use the existing + sorting algorithm initially, and fall back to a O(N (log N)^2) + algorithm if the standard algorithm gets into + difficulties.

    +
  • +
  • The compressed file format was never designed to be + handled by a library, and I have had to jump though some hoops + to produce an efficient implementation of decompression. It's + a bit hairy. Try passing + decompress.c through the C + preprocessor and you'll see what I mean. Much of this + complexity could have been avoided if the compressed size of + each block of data was recorded in the data stream.

  • +
  • An Adler-32 checksum, rather than a CRC32 checksum, + would be faster to compute.

  • +
+

It would be fair to say that the +bzip2 format was frozen before I +properly and fully understood the performance consequences of +doing so.

+

Improvements which I was able to incorporate into 0.9.0, +despite using the same file format, are:

+
    +
  • Single array implementation of the inverse BWT. This + significantly speeds up decompression, presumably because it + reduces the number of cache misses.

  • +
  • Faster inverse MTF transform for large MTF values. + The new implementation is based on the notion of sliding blocks + of values.

  • +
  • bzip2-0.9.0 now reads + and writes files with fread + and fwrite; version 0.1 used + putc and + getc. Duh! Well, you live + and learn.

  • +
+

Further ahead, it would be nice to be able to do random +access into files. This will require some careful design of +compressed file formats.

+
+
+
+

+4.2. Portability issues

+
+
+

After some consideration, I have decided not to use GNU +autoconf to configure 0.9.5 or +1.0.

+

autoconf, admirable and +wonderful though it is, mainly assists with portability problems +between Unix-like platforms. But +bzip2 doesn't have much in the +way of portability problems on Unix; most of the difficulties +appear when porting to the Mac, or to Microsoft's operating +systems. autoconf doesn't help +in those cases, and brings in a whole load of new +complexity.

+

Most people should be able to compile the library and +program under Unix straight out-of-the-box, so to speak, +especially if you have a version of GNU C available.

+

There are a couple of +__inline__ directives in the +code. GNU C (gcc) should be +able to handle them. If you're not using GNU C, your C compiler +shouldn't see them at all. If your compiler does, for some +reason, see them and doesn't like them, just +#define +__inline__ to be +/* */. One easy way to do this +is to compile with the flag +-D__inline__=, which should be +understood by most Unix compilers.

+

If you still have difficulties, try compiling with the +macro BZ_STRICT_ANSI defined. +This should enable you to build the library in a strictly ANSI +compliant environment. Building the program itself like this is +dangerous and not supported, since you remove +bzip2's checks against +compressing directories, symbolic links, devices, and other +not-really-a-file entities. This could cause filesystem +corruption!

+

One other thing: if you create a +bzip2 binary for public distribution, +please consider linking it statically (gcc +-static). This avoids all sorts of library-version +issues that others may encounter later on.

+

If you build bzip2 on +Win32, you must set BZ_UNIX to 0 +and BZ_LCCWIN32 to 1, in the +file bzip2.c, before compiling. +Otherwise the resulting binary won't work correctly.

+
+
+
+

+4.3. Reporting bugs

+
+
+

I tried pretty hard to make sure +bzip2 is bug free, both by +design and by testing. Hopefully you'll never need to read this +section for real.

+

Nevertheless, if bzip2 dies +with a segmentation fault, a bus error or an internal assertion +failure, it will ask you to email me a bug report. Experience from +years of feedback of bzip2 users indicates that almost all these +problems can be traced to either compiler bugs or hardware +problems.

+
    +
  • +

    Recompile the program with no optimisation, and + see if it works. And/or try a different compiler. I heard all + sorts of stories about various flavours of GNU C (and other + compilers) generating bad code for + bzip2, and I've run across two + such examples myself.

    +

    2.7.X versions of GNU C are known to generate bad code + from time to time, at high optimisation levels. If you get + problems, try using the flags + -O2 + -fomit-frame-pointer + -fno-strength-reduce. You + should specifically not use + -funroll-loops.

    +

    You may notice that the Makefile runs six tests as part + of the build process. If the program passes all of these, it's + a pretty good (but not 100%) indication that the compiler has + done its job correctly.

    +
  • +
  • +

    If bzip2 + crashes randomly, and the crashes are not repeatable, you may + have a flaky memory subsystem. + bzip2 really hammers your + memory hierarchy, and if it's a bit marginal, you may get these + problems. Ditto if your disk or I/O subsystem is slowly + failing. Yup, this really does happen.

    +

    Try using a different machine of the same type, and see + if you can repeat the problem.

    +
  • +
  • This isn't really a bug, but ... If + bzip2 tells you your file is + corrupted on decompression, and you obtained the file via FTP, + there is a possibility that you forgot to tell FTP to do a + binary mode transfer. That absolutely will cause the file to + be non-decompressible. You'll have to transfer it + again.

  • +
+

If you've incorporated +libbzip2 into your own program +and are getting problems, please, please, please, check that the +parameters you are passing in calls to the library, are correct, +and in accordance with what the documentation says is allowable. +I have tried to make the library robust against such problems, +but I'm sure I haven't succeeded.

+

Finally, if the above comments don't help, you'll have to +send me a bug report. Now, it's just amazing how many people +will send me a bug report saying something like:

+
bzip2 crashed with segmentation fault on my machine
+

and absolutely nothing else. Needless to say, a such a +report is totally, utterly, completely and +comprehensively 100% useless; a waste of your time, my time, and +net bandwidth. With no details at all, there's no way +I can possibly begin to figure out what the problem is.

+

The rules of the game are: facts, facts, facts. Don't omit +them because "oh, they won't be relevant". At the bare +minimum:

+
Machine type.  Operating system version.  
+Exact version of bzip2 (do bzip2 -V).  
+Exact version of the compiler used.  
+Flags passed to the compiler.
+

However, the most important single thing that will help me +is the file that you were trying to compress or decompress at the +time the problem happened. Without that, my ability to do +anything more than speculate about the cause, is limited.

+
+
+
+

+4.4. Did you get the right package?

+
+
+

bzip2 is a resource hog. +It soaks up large amounts of CPU cycles and memory. Also, it +gives very large latencies. In the worst case, you can feed many +megabytes of uncompressed data into the library before getting +any compressed output, so this probably rules out applications +requiring interactive behaviour.

+

These aren't faults of my implementation, I hope, but more +an intrinsic property of the Burrows-Wheeler transform +(unfortunately). Maybe this isn't what you want.

+

If you want a compressor and/or library which is faster, +uses less memory but gets pretty good compression, and has +minimal latency, consider Jean-loup Gailly's and Mark Adler's +work, zlib-1.2.1 and +gzip-1.2.4. Look for them at +http://www.zlib.org and +http://www.gzip.org +respectively.

+

For something faster and lighter still, you might try Markus F +X J Oberhumer's LZO real-time +compression/decompression library, at +http://www.oberhumer.com/opensource.

+
+
+
+

+4.5. Further Reading

+
+
+

bzip2 is not research +work, in the sense that it doesn't present any new ideas. +Rather, it's an engineering exercise based on existing +ideas.

+

Four documents describe essentially all the ideas behind +bzip2:

+

Michael Burrows and D. J. Wheeler:
+  "A block-sorting lossless data compression algorithm"
+   10th May 1994. 
+   Digital SRC Research Report 124.
+   ftp://ftp.digital.com/pub/DEC/SRC/research-reports/SRC-124.ps.gz
+   If you have trouble finding it, try searching at the
+   New Zealand Digital Library, http://www.nzdl.org.
+
+Daniel S. Hirschberg and Debra A. LeLewer
+  "Efficient Decoding of Prefix Codes"
+   Communications of the ACM, April 1990, Vol 33, Number 4.
+   You might be able to get an electronic copy of this
+   from the ACM Digital Library.
+
+David J. Wheeler
+   Program bred3.c and accompanying document bred3.ps.
+   This contains the idea behind the multi-table Huffman coding scheme.
+   ftp://ftp.cl.cam.ac.uk/users/djw3/
+
+Jon L. Bentley and Robert Sedgewick
+  "Fast Algorithms for Sorting and Searching Strings"
+   Available from Sedgewick's web page,
+   www.cs.princeton.edu/~rs
+

+

The following paper gives valuable additional insights into +the algorithm, but is not immediately the basis of any code used +in bzip2.

+

Peter Fenwick:
+   Block Sorting Text Compression
+   Proceedings of the 19th Australasian Computer Science Conference,
+     Melbourne, Australia.  Jan 31 - Feb 2, 1996.
+   ftp://ftp.cs.auckland.ac.nz/pub/peter-f/ACSC96paper.ps

+

Kunihiko Sadakane's sorting algorithm, mentioned above, is +available from:

+

http://naomi.is.s.u-tokyo.ac.jp/~sada/papers/Sada98b.ps.gz
+

+

The Manber-Myers suffix array construction algorithm is +described in a paper available from:

+

http://www.cs.arizona.edu/people/gene/PAPERS/suffix.ps
+

+

Finally, the following papers document some +investigations I made into the performance of sorting +and decompression algorithms:

+

Julian Seward
+   On the Performance of BWT Sorting Algorithms
+   Proceedings of the IEEE Data Compression Conference 2000
+     Snowbird, Utah.  28-30 March 2000.
+
+Julian Seward
+   Space-time Tradeoffs in the Inverse B-W Transform
+   Proceedings of the IEEE Data Compression Conference 2001
+     Snowbird, Utah.  27-29 March 2001.
+

+
+
+
+ diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/manual.pdf b/contrib/vmap_extractor_v2/stormlib/bzip2/manual.pdf new file mode 100644 index 00000000000..394b8092565 Binary files /dev/null and b/contrib/vmap_extractor_v2/stormlib/bzip2/manual.pdf differ diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/manual.ps b/contrib/vmap_extractor_v2/stormlib/bzip2/manual.ps new file mode 100644 index 00000000000..03831d194c8 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/bzip2/manual.ps @@ -0,0 +1,68244 @@ +%!PS-Adobe-3.0 +%%Creator: xpdf/pdftops 3.00 +%%LanguageLevel: 2 +%%DocumentSuppliedResources: (atend) +%%DocumentMedia: plain 612 792 0 () () +%%BoundingBox: 0 0 612 792 +%%Pages: 38 +%%EndComments +%%BeginDefaults +%%PageMedia: plain +%%EndDefaults +%%BeginProlog +%%BeginResource: procset xpdf 3.00 0 +/xpdf 75 dict def xpdf begin +% PDF special state +/pdfDictSize 15 def +/pdfSetup { + 3 1 roll 2 array astore + /setpagedevice where { + pop 3 dict begin + /PageSize exch def + /ImagingBBox null def + /Policies 1 dict dup begin /PageSize 3 def end def + { /Duplex true def } if + currentdict end setpagedevice + } { + pop pop + } ifelse +} def +/pdfStartPage { + pdfDictSize dict begin + /pdfFill [0] def + /pdfStroke [0] def + /pdfLastFill false def + /pdfLastStroke false def + /pdfTextMat [1 0 0 1 0 0] def + /pdfFontSize 0 def + /pdfCharSpacing 0 def + /pdfTextRender 0 def + /pdfTextRise 0 def + /pdfWordSpacing 0 def + /pdfHorizScaling 1 def + /pdfTextClipPath [] def +} def +/pdfEndPage { end } def +% separation convention operators +/findcmykcustomcolor where { + pop +}{ + /findcmykcustomcolor { 5 array astore } def +} ifelse +/setcustomcolor where { + pop +}{ + /setcustomcolor { + exch + [ exch /Separation exch dup 4 get exch /DeviceCMYK exch + 0 4 getinterval cvx + [ exch /dup load exch { mul exch dup } /forall load + /pop load dup ] cvx + ] setcolorspace setcolor + } def +} ifelse +/customcolorimage where { + pop +}{ + /customcolorimage { + gsave + [ exch /Separation exch dup 4 get exch /DeviceCMYK exch + 0 4 getinterval + [ exch /dup load exch { mul exch dup } /forall load + /pop load dup ] cvx + ] setcolorspace + 10 dict begin + /ImageType 1 def + /DataSource exch def + /ImageMatrix exch def + /BitsPerComponent exch def + /Height exch def + /Width exch def + /Decode [1 0] def + currentdict end + image + grestore + } def +} ifelse +% PDF color state +/sCol { + pdfLastStroke not { + pdfStroke aload length + dup 1 eq { + pop setgray + }{ + dup 3 eq { + pop setrgbcolor + }{ + 4 eq { + setcmykcolor + }{ + findcmykcustomcolor exch setcustomcolor + } ifelse + } ifelse + } ifelse + /pdfLastStroke true def /pdfLastFill false def + } if +} def +/fCol { + pdfLastFill not { + pdfFill aload length + dup 1 eq { + pop setgray + }{ + dup 3 eq { + pop setrgbcolor + }{ + 4 eq { + setcmykcolor + }{ + findcmykcustomcolor exch setcustomcolor + } ifelse + } ifelse + } ifelse + /pdfLastFill true def /pdfLastStroke false def + } if +} def +% build a font +/pdfMakeFont { + 4 3 roll findfont + 4 2 roll matrix scale makefont + dup length dict begin + { 1 index /FID ne { def } { pop pop } ifelse } forall + /Encoding exch def + currentdict + end + definefont pop +} def +/pdfMakeFont16 { + exch findfont + dup length dict begin + { 1 index /FID ne { def } { pop pop } ifelse } forall + /WMode exch def + currentdict + end + definefont pop +} def +/pdfMakeFont16L3 { + 1 index /CIDFont resourcestatus { + pop pop 1 index /CIDFont findresource /CIDFontType known + } { + false + } ifelse + { + 0 eq { /Identity-H } { /Identity-V } ifelse + exch 1 array astore composefont pop + } { + pdfMakeFont16 + } ifelse +} def +% graphics state operators +/q { gsave pdfDictSize dict begin } def +/Q { end grestore } def +/cm { concat } def +/d { setdash } def +/i { setflat } def +/j { setlinejoin } def +/J { setlinecap } def +/M { setmiterlimit } def +/w { setlinewidth } def +% color operators +/g { dup 1 array astore /pdfFill exch def setgray + /pdfLastFill true def /pdfLastStroke false def } def +/G { dup 1 array astore /pdfStroke exch def setgray + /pdfLastStroke true def /pdfLastFill false def } def +/rg { 3 copy 3 array astore /pdfFill exch def setrgbcolor + /pdfLastFill true def /pdfLastStroke false def } def +/RG { 3 copy 3 array astore /pdfStroke exch def setrgbcolor + /pdfLastStroke true def /pdfLastFill false def } def +/k { 4 copy 4 array astore /pdfFill exch def setcmykcolor + /pdfLastFill true def /pdfLastStroke false def } def +/K { 4 copy 4 array astore /pdfStroke exch def setcmykcolor + /pdfLastStroke true def /pdfLastFill false def } def +/ck { 6 copy 6 array astore /pdfFill exch def + findcmykcustomcolor exch setcustomcolor + /pdfLastFill true def /pdfLastStroke false def } def +/CK { 6 copy 6 array astore /pdfStroke exch def + findcmykcustomcolor exch setcustomcolor + /pdfLastStroke true def /pdfLastFill false def } def +% path segment operators +/m { moveto } def +/l { lineto } def +/c { curveto } def +/re { 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto + neg 0 rlineto closepath } def +/h { closepath } def +% path painting operators +/S { sCol stroke } def +/Sf { fCol stroke } def +/f { fCol fill } def +/f* { fCol eofill } def +% clipping operators +/W { clip newpath } def +/W* { eoclip newpath } def +% text state operators +/Tc { /pdfCharSpacing exch def } def +/Tf { dup /pdfFontSize exch def + dup pdfHorizScaling mul exch matrix scale + pdfTextMat matrix concatmatrix dup 4 0 put dup 5 0 put + exch findfont exch makefont setfont } def +/Tr { /pdfTextRender exch def } def +/Ts { /pdfTextRise exch def } def +/Tw { /pdfWordSpacing exch def } def +/Tz { /pdfHorizScaling exch def } def +% text positioning operators +/Td { pdfTextMat transform moveto } def +/Tm { /pdfTextMat exch def } def +% text string operators +/cshow where { + pop + /cshow2 { + dup { + pop pop + 1 string dup 0 3 index put 3 index exec + } exch cshow + pop pop + } def +}{ + /cshow2 { + currentfont /FontType get 0 eq { + 0 2 2 index length 1 sub { + 2 copy get exch 1 add 2 index exch get + 2 copy exch 256 mul add + 2 string dup 0 6 5 roll put dup 1 5 4 roll put + 3 index exec + } for + } { + dup { + 1 string dup 0 3 index put 3 index exec + } forall + } ifelse + pop pop + } def +} ifelse +/awcp { + exch { + false charpath + 5 index 5 index rmoveto + 6 index eq { 7 index 7 index rmoveto } if + } exch cshow2 + 6 {pop} repeat +} def +/Tj { + fCol + 1 index stringwidth pdfTextMat idtransform pop + sub 1 index length dup 0 ne { div } { pop pop 0 } ifelse + pdfWordSpacing pdfHorizScaling mul 0 pdfTextMat dtransform 32 + 4 3 roll pdfCharSpacing pdfHorizScaling mul add 0 + pdfTextMat dtransform + 6 5 roll Tj1 +} def +/Tj16 { + fCol + 2 index stringwidth pdfTextMat idtransform pop + sub exch div + pdfWordSpacing pdfHorizScaling mul 0 pdfTextMat dtransform 32 + 4 3 roll pdfCharSpacing pdfHorizScaling mul add 0 + pdfTextMat dtransform + 6 5 roll Tj1 +} def +/Tj16V { + fCol + 2 index stringwidth pdfTextMat idtransform exch pop + sub exch div + 0 pdfWordSpacing pdfTextMat dtransform 32 + 4 3 roll pdfCharSpacing add 0 exch + pdfTextMat dtransform + 6 5 roll Tj1 +} def +/Tj1 { + 0 pdfTextRise pdfTextMat dtransform rmoveto + currentpoint 8 2 roll + pdfTextRender 1 and 0 eq { + 6 copy awidthshow + } if + pdfTextRender 3 and dup 1 eq exch 2 eq or { + 7 index 7 index moveto + 6 copy + currentfont /FontType get 3 eq { fCol } { sCol } ifelse + false awcp currentpoint stroke moveto + } if + pdfTextRender 4 and 0 ne { + 8 6 roll moveto + false awcp + /pdfTextClipPath [ pdfTextClipPath aload pop + {/moveto cvx} + {/lineto cvx} + {/curveto cvx} + {/closepath cvx} + pathforall ] def + currentpoint newpath moveto + } { + 8 {pop} repeat + } ifelse + 0 pdfTextRise neg pdfTextMat dtransform rmoveto +} def +/TJm { pdfFontSize 0.001 mul mul neg 0 + pdfTextMat dtransform rmoveto } def +/TJmV { pdfFontSize 0.001 mul mul neg 0 exch + pdfTextMat dtransform rmoveto } def +/Tclip { pdfTextClipPath cvx exec clip newpath + /pdfTextClipPath [] def } def +% Level 2 image operators +/pdfImBuf 100 string def +/pdfIm { + image + { currentfile pdfImBuf readline + not { pop exit } if + (%-EOD-) eq { exit } if } loop +} def +/pdfImSep { + findcmykcustomcolor exch + dup /Width get /pdfImBuf1 exch string def + dup /Decode get aload pop 1 index sub /pdfImDecodeRange exch def + /pdfImDecodeLow exch def + begin Width Height BitsPerComponent ImageMatrix DataSource end + /pdfImData exch def + { pdfImData pdfImBuf1 readstring pop + 0 1 2 index length 1 sub { + 1 index exch 2 copy get + pdfImDecodeRange mul 255 div pdfImDecodeLow add round cvi + 255 exch sub put + } for } + 6 5 roll customcolorimage + { currentfile pdfImBuf readline + not { pop exit } if + (%-EOD-) eq { exit } if } loop +} def +/pdfImM { + fCol imagemask + { currentfile pdfImBuf readline + not { pop exit } if + (%-EOD-) eq { exit } if } loop +} def +end +%%EndResource +%%EndProlog +%%BeginSetup +xpdf begin +/F121_0 /Helvetica-Bold 1 1 +[ /.notdef/dotaccent/fi/fl/fraction/hungarumlaut/Lslash/lslash + /ogonek/ring/.notdef/breve/minus/.notdef/Zcaron/zcaron + /caron/dotlessi/dotlessj/ff/ffi/ffl/.notdef/.notdef + /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/grave/quotesingle + /space/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright + /parenleft/parenright/asterisk/plus/comma/hyphen/period/slash + /zero/one/two/three/four/five/six/seven + /eight/nine/colon/semicolon/less/equal/greater/question + /at/A/B/C/D/E/F/G + /H/I/J/K/L/M/N/O + /P/Q/R/S/T/U/V/W + /X/Y/Z/bracketleft/backslash/bracketright/asciicircum/underscore + /quoteleft/a/b/c/d/e/f/g + /h/i/j/k/l/m/n/o + /p/q/r/s/t/u/v/w + /x/y/z/braceleft/bar/braceright/asciitilde/.notdef + /Euro/.notdef/quotesinglbase/florin/quotedblbase/ellipsis/dagger/daggerdbl + /circumflex/perthousand/Scaron/guilsinglleft/OE/.notdef/.notdef/.notdef + /.notdef/.notdef/.notdef/quotedblleft/quotedblright/bullet/endash/emdash + /tilde/trademark/scaron/guilsinglright/oe/.notdef/.notdef/Ydieresis + /.notdef/exclamdown/cent/sterling/currency/yen/brokenbar/section + /dieresis/copyright/ordfeminine/guillemotleft/logicalnot/hyphen/registered/macron + /degree/plusminus/twosuperior/threesuperior/acute/mu/paragraph/periodcentered + /cedilla/onesuperior/ordmasculine/guillemotright/onequarter/onehalf/threequarters/questiondown + /Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE/Ccedilla + /Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex/Idieresis + /Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis/multiply + /Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls + /agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla + /egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis + /eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide + /oslash/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis] +pdfMakeFont +/F128_0 /Times-Roman 1 1 +[ /.notdef/dotaccent/fi/fl/fraction/hungarumlaut/Lslash/lslash + /ogonek/ring/.notdef/breve/minus/.notdef/Zcaron/zcaron + /caron/dotlessi/dotlessj/ff/ffi/ffl/.notdef/.notdef + /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/grave/quotesingle + /space/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright + /parenleft/parenright/asterisk/plus/comma/hyphen/period/slash + /zero/one/two/three/four/five/six/seven + /eight/nine/colon/semicolon/less/equal/greater/question + /at/A/B/C/D/E/F/G + /H/I/J/K/L/M/N/O + /P/Q/R/S/T/U/V/W + /X/Y/Z/bracketleft/backslash/bracketright/asciicircum/underscore + /quoteleft/a/b/c/d/e/f/g + /h/i/j/k/l/m/n/o + /p/q/r/s/t/u/v/w + /x/y/z/braceleft/bar/braceright/asciitilde/.notdef + /Euro/.notdef/quotesinglbase/florin/quotedblbase/ellipsis/dagger/daggerdbl + /circumflex/perthousand/Scaron/guilsinglleft/OE/.notdef/.notdef/.notdef + /.notdef/.notdef/.notdef/quotedblleft/quotedblright/bullet/endash/emdash + /tilde/trademark/scaron/guilsinglright/oe/.notdef/.notdef/Ydieresis + /.notdef/exclamdown/cent/sterling/currency/yen/brokenbar/section + /dieresis/copyright/ordfeminine/guillemotleft/logicalnot/hyphen/registered/macron + /degree/plusminus/twosuperior/threesuperior/acute/mu/paragraph/periodcentered + /cedilla/onesuperior/ordmasculine/guillemotright/onequarter/onehalf/threequarters/questiondown + /Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE/Ccedilla + /Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex/Idieresis + /Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis/multiply + /Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls + /agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla + /egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis + /eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide + /oslash/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis] +pdfMakeFont +/F130_0 /Courier 1 1 +[ /.notdef/dotaccent/fi/fl/fraction/hungarumlaut/Lslash/lslash + /ogonek/ring/.notdef/breve/minus/.notdef/Zcaron/zcaron + /caron/dotlessi/dotlessj/ff/ffi/ffl/.notdef/.notdef + /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/grave/quotesingle + /space/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright + /parenleft/parenright/asterisk/plus/comma/hyphen/period/slash + /zero/one/two/three/four/five/six/seven + /eight/nine/colon/semicolon/less/equal/greater/question + /at/A/B/C/D/E/F/G + /H/I/J/K/L/M/N/O + /P/Q/R/S/T/U/V/W + /X/Y/Z/bracketleft/backslash/bracketright/asciicircum/underscore + /quoteleft/a/b/c/d/e/f/g + /h/i/j/k/l/m/n/o + /p/q/r/s/t/u/v/w + /x/y/z/braceleft/bar/braceright/asciitilde/.notdef + /Euro/.notdef/quotesinglbase/florin/quotedblbase/ellipsis/dagger/daggerdbl + /circumflex/perthousand/Scaron/guilsinglleft/OE/.notdef/.notdef/.notdef + /.notdef/.notdef/.notdef/quotedblleft/quotedblright/bullet/endash/emdash + /tilde/trademark/scaron/guilsinglright/oe/.notdef/.notdef/Ydieresis + /.notdef/exclamdown/cent/sterling/currency/yen/brokenbar/section + /dieresis/copyright/ordfeminine/guillemotleft/logicalnot/hyphen/registered/macron + /degree/plusminus/twosuperior/threesuperior/acute/mu/paragraph/periodcentered + /cedilla/onesuperior/ordmasculine/guillemotright/onequarter/onehalf/threequarters/questiondown + /Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE/Ccedilla + /Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex/Idieresis + /Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis/multiply + /Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls + /agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla + /egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis + /eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide + /oslash/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis] +pdfMakeFont +%%BeginResource: font CJBHNS+CMMI10 +%!PS-AdobeFont-1.1: CMMI10 1.100 +%%CreationDate: 1996 Jul 23 07:53:57 +% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. +11 dict begin +/FontInfo 7 dict dup begin +/version (1.100) readonly def +/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def +/FullName (CMMI10) readonly def +/FamilyName (Computer Modern) readonly def +/Weight (Medium) readonly def +/ItalicAngle -14.04 def +/isFixedPitch false def +end readonly def +/FontName /CJBHNS+CMMI10 def +/PaintType 0 def +/FontType 1 def +/FontMatrix [0.001 0 0 0.001 0 0] readonly def +/Encoding 256 array +0 1 255 {1 index exch /.notdef put} for +dup 45 /arrowhookright put +dup 58 /period put +readonly def +/FontBBox{-32 -250 1048 750}readonly def +/UniqueID 5087385 def +currentdict end +currentfile eexec +d9d66f633b846a97b686a97e45a3d0aa0529731c99a784ccbe85b4993b2eebde +3b12d472b7cf54651ef21185116a69ab1096ed4bad2f646635e019b6417cc77b +532f85d811c70d1429a19a5307ef63eb5c5e02c89fc6c20f6d9d89e7d91fe470 +b72befda23f5df76be05af4ce93137a219ed8a04a9d7d6fdf37e6b7fcde0d90b +986423e5960a5d9fbb4c956556e8df90cbfaec476fa36fd9a5c8175c9af513fe +d919c2ddd26bdc0d99398b9f4d03d5993dfc0930297866e1cd0a319b6b1fd958 +9e394a533a081c36d456a09920001a3d2199583eb9b84b4dee08e3d12939e321 +990cd249827d9648574955f61baaa11263a91b6c3d47a5190165b0c25abf6d3e +6ec187e4b05182126bb0d0323d943170b795255260f9fd25f2248d04f45dfbfb +def7ff8b19bfef637b210018ae02572b389b3f76282beb29cc301905d388c721 +59616893e774413f48de0b408bc66dce3fe17cb9f84d205839d58014d6a88823 +d9320ae93af96d97a02c4d5a2bb2b8c7925c4578003959c46e3ce1a2f0eac4bf +8b9b325e46435bde60bc54d72bc8acb5c0a34413ac87045dc7b84646a324b808 +6fd8e34217213e131c3b1510415ce45420688ed9c1d27890ec68bd7c1235faf9 +1dab3a369dd2fc3be5cf9655c7b7eda7361d7e05e5831b6b8e2eec542a7b38ee +03be4bac6079d038acb3c7c916279764547c2d51976baba94ba9866d79f13909 +95aa39b0f03103a07cbdf441b8c5669f729020af284b7ff52a29c6255fcaacf1 +74109050fba2602e72593fbcbfc26e726ee4aef97b7632bc4f5f353b5c67fed2 +3ea752a4a57b8f7feff1d7341d895f0a3a0be1d8e3391970457a967eff84f6d8 +47750b1145b8cc5bd96ee7aa99ddc9e06939e383bda41175233d58ad263ebf19 +afc0e2f840512d321166547b306c592b8a01e1fa2564b9a26dac14256414e4c8 +42616728d918c74d13c349f4186ec7b9708b86467425a6fdb3a396562f7ee4d8 +40b43621744cf8a23a6e532649b66c2a0002dd04f8f39618e4f572819dd34837 +b5a08e643fdca1505af6a1fa3ddfd1fa758013caed8acddbbb334d664dff5b53 +95601766777978d01677b8d19e1b10a078432d2884bb42d1f224976325883657 +05acb022d1e9cb556e37af91917c78e98229e3a4dbf03ae741998542977ad6df +1760fc1f1a479464922afda2cba7961e9da696b71205e19c542c97f25419c43c +fa1a042ba0cf5622ffbd3e775d0d564135d99b9ffba011eebc4066b003ce2f88 +825936d7393d05d3804601cee9d123120fdf73624a9d4e361a28e998acec53f8 +7a62a0aee33be2e96542534a8af24497d1c377cd7f723767b44857d94c6cda7a +c3d6f0087fa36655dd2b81eaecb31fe4f4a2fb1ea9fbe8b83d35826ac93fbb4f +2bee014f41f8f276510cf5ce35c3954e8cafc521d0c3ab80ea8c7fc29427a1d4 +42d6f6c1800919e58de9ae12304d718ad80febbb412da54153469cd51a288628 +ad109baa77981525b3d9b0efe593537fcbb8520d38cccbd5db171a0385a432c1 +3030303030303030 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +cleartomark +%%EndResource +/F143_0 /CJBHNS+CMMI10 1 1 +[ /Gamma/Delta/Theta/Lambda/Xi/Pi/Sigma/Upsilon + /Phi/Psi/Omega/alpha/beta/gamma/delta/epsilon1 + /zeta/eta/theta/iota/kappa/lambda/mu/nu + /xi/pi/rho/sigma/tau/upsilon/phi/chi + /psi/omega/epsilon/theta1/pi1/rho1/sigma1/phi1 + /arrowlefttophalf/arrowleftbothalf/arrowrighttophalf/arrowrightbothalf/arrowhookleft/arrowhookright/triangleright/triangleleft + /zerooldstyle/oneoldstyle/twooldstyle/threeoldstyle/fouroldstyle/fiveoldstyle/sixoldstyle/sevenoldstyle + /eightoldstyle/nineoldstyle/period/comma/less/slash/greater/star + /partialdiff/A/B/C/D/E/F/G + /H/I/J/K/L/M/N/O + /P/Q/R/S/T/U/V/W + /X/Y/Z/flat/natural/sharp/slurbelow/slurabove + /lscript/a/b/c/d/e/f/g + /h/i/j/k/l/m/n/o + /p/q/r/s/t/u/v/w + /x/y/z/dotlessi/dotlessj/weierstrass/vector/tie + /psi/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef + /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef + /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef + /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef + /space/Gamma/Delta/Theta/Lambda/Xi/Pi/Sigma + /Upsilon/Phi/Psi/.notdef/.notdef/Omega/alpha/beta + /gamma/delta/epsilon1/zeta/eta/theta/iota/kappa + /lambda/mu/nu/xi/pi/rho/sigma/tau + /upsilon/phi/chi/psi/tie/.notdef/.notdef/.notdef + /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef + /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef + /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef + /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef + /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef + /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef + /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef] +pdfMakeFont +/F387_0 /Courier-Bold 1 1 +[ /.notdef/dotaccent/fi/fl/fraction/hungarumlaut/Lslash/lslash + /ogonek/ring/.notdef/breve/minus/.notdef/Zcaron/zcaron + /caron/dotlessi/dotlessj/ff/ffi/ffl/.notdef/.notdef + /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/grave/quotesingle + /space/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright + /parenleft/parenright/asterisk/plus/comma/hyphen/period/slash + /zero/one/two/three/four/five/six/seven + /eight/nine/colon/semicolon/less/equal/greater/question + /at/A/B/C/D/E/F/G + /H/I/J/K/L/M/N/O + /P/Q/R/S/T/U/V/W + /X/Y/Z/bracketleft/backslash/bracketright/asciicircum/underscore + /quoteleft/a/b/c/d/e/f/g + /h/i/j/k/l/m/n/o + /p/q/r/s/t/u/v/w + /x/y/z/braceleft/bar/braceright/asciitilde/.notdef + /Euro/.notdef/quotesinglbase/florin/quotedblbase/ellipsis/dagger/daggerdbl + /circumflex/perthousand/Scaron/guilsinglleft/OE/.notdef/.notdef/.notdef + /.notdef/.notdef/.notdef/quotedblleft/quotedblright/bullet/endash/emdash + /tilde/trademark/scaron/guilsinglright/oe/.notdef/.notdef/Ydieresis + /.notdef/exclamdown/cent/sterling/currency/yen/brokenbar/section + /dieresis/copyright/ordfeminine/guillemotleft/logicalnot/hyphen/registered/macron + /degree/plusminus/twosuperior/threesuperior/acute/mu/paragraph/periodcentered + /cedilla/onesuperior/ordmasculine/guillemotright/onequarter/onehalf/threequarters/questiondown + /Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE/Ccedilla + /Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex/Idieresis + /Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis/multiply + /Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls + /agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla + /egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis + /eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide + /oslash/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis] +pdfMakeFont +%%BeginResource: font RBGKEI+CMSY10 +%!PS-AdobeFont-1.1: CMSY10 1.0 +%%CreationDate: 1991 Aug 15 07:20:57 +% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. +11 dict begin +/FontInfo 7 dict dup begin +/version (1.0) readonly def +/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def +/FullName (CMSY10) readonly def +/FamilyName (Computer Modern) readonly def +/Weight (Medium) readonly def +/ItalicAngle -14.035 def +/isFixedPitch false def +end readonly def +/FontName /RBGKEI+CMSY10 def +/PaintType 0 def +/FontType 1 def +/FontMatrix [0.001 0 0 0.001 0 0] readonly def +/Encoding 256 array +0 1 255 {1 index exch /.notdef put} for +dup 32 /arrowleft put +readonly def +/FontBBox{-29 -960 1116 775}readonly def +/UniqueID 5000820 def +currentdict end +currentfile eexec +d9d66f633b846a97b686a97e45a3d0aa052f09f9c8ade9d907c058b87e9b6964 +7d53359e51216774a4eaa1e2b58ec3176bd1184a633b951372b4198d4e8c5ef4 +a213acb58aa0a658908035bf2ed8531779838a960dfe2b27ea49c37156989c85 +e21b3abf72e39a89232cd9f4237fc80c9e64e8425aa3bef7ded60b122a52922a +221a37d9a807dd01161779dde7d31ff2b87f97c73d63eecdda4c49501773468a +27d1663e0b62f461f6e40a5d6676d1d12b51e641c1d4e8e2771864fc104f8cbf +5b78ec1d88228725f1c453a678f58a7e1b7bd7ca700717d288eb8da1f57c4f09 +0abf1d42c5ddd0c384c7e22f8f8047be1d4c1cc8e33368fb1ac82b4e96146730 +de3302b2e6b819cb6ae455b1af3187ffe8071aa57ef8a6616b9cb7941d44ec7a +71a7bb3df755178d7d2e4bb69859efa4bbc30bd6bb1531133fd4d9438ff99f09 +4ecc068a324d75b5f696b8688eeb2f17e5ed34ccd6d047a4e3806d000c199d7c +515db70a8d4f6146fe068dc1e5de8bc5703711da090312ba3fc00a08c453c609 +c627a8bd98d9e826f964721e92bbdc978e88eea0a9c14802ebcc41f810428fa8 +b9972032a01769a7c72d1a65276f414deedaf1d22be23f4705bf5ef31b6a3b69 +0c896320f09e9875b50220a5bdbbd57c041b5ea97f421685a7256b0d9755edbe +d05190dabf1c3dbf558258163c8231d89167a816bba55fb1f14ad04320ae381d +f783a9eacee8ae5c1838775fe2380bdd1f3afcccc96d2a2dfc999b52a6689c51 +af82b8d63205b339103134dac7e3c45e6693940276041bb07ebdb9b729e8ef0d +ee8bf450fa42551be65217fea902e28decc09580b504f0f52f1e8fc5ce7ac28d +c4e47f908fdaeba23827a97a0aa741aa7708f7bbfec6fa69cc4f7c3bd4303030 +3030303030 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +cleartomark +%%EndResource +/F559_0 /RBGKEI+CMSY10 1 1 +[ /minus/periodcentered/multiply/asteriskmath/divide/diamondmath/plusminus/minusplus + /circleplus/circleminus/circlemultiply/circledivide/circledot/circlecopyrt/openbullet/bullet + /equivasymptotic/equivalence/reflexsubset/reflexsuperset/lessequal/greaterequal/precedesequal/followsequal + /similar/approxequal/propersubset/propersuperset/lessmuch/greatermuch/precedes/follows + /arrowleft/arrowright/arrowup/arrowdown/arrowboth/arrownortheast/arrowsoutheast/similarequal + /arrowdblleft/arrowdblright/arrowdblup/arrowdbldown/arrowdblboth/arrownorthwest/arrowsouthwest/proportional + /prime/infinity/element/owner/triangle/triangleinv/negationslash/mapsto + /universal/existential/logicalnot/emptyset/Rfractur/Ifractur/latticetop/perpendicular + /aleph/A/B/C/D/E/F/G + /H/I/J/K/L/M/N/O + /P/Q/R/S/T/U/V/W + /X/Y/Z/union/intersection/unionmulti/logicaland/logicalor + /turnstileleft/turnstileright/floorleft/floorright/ceilingleft/ceilingright/braceleft/braceright + /angbracketleft/angbracketright/bar/bardbl/arrowbothv/arrowdblbothv/backslash/wreathproduct + /radical/coproduct/nabla/integral/unionsq/intersectionsq/subsetsqequal/supersetsqequal + /section/dagger/daggerdbl/paragraph/club/diamond/heart/spade + /arrowleft/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef + /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef + /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef + /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef + /.notdef/minus/periodcentered/multiply/asteriskmath/divide/diamondmath/plusminus + /minusplus/circleplus/circleminus/.notdef/.notdef/circlemultiply/circledivide/circledot + /circlecopyrt/openbullet/bullet/equivasymptotic/equivalence/reflexsubset/reflexsuperset/lessequal + /greaterequal/precedesequal/followsequal/similar/approxequal/propersubset/propersuperset/lessmuch + /greatermuch/precedes/follows/arrowleft/spade/.notdef/.notdef/.notdef + /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef + /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef + /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef + /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef + /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef + /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef + /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef] +pdfMakeFont +/F631_0 /Times-Italic 1 1 +[ /.notdef/dotaccent/fi/fl/fraction/hungarumlaut/Lslash/lslash + /ogonek/ring/.notdef/breve/minus/.notdef/Zcaron/zcaron + /caron/dotlessi/dotlessj/ff/ffi/ffl/.notdef/.notdef + /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/grave/quotesingle + /space/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright + /parenleft/parenright/asterisk/plus/comma/hyphen/period/slash + /zero/one/two/three/four/five/six/seven + /eight/nine/colon/semicolon/less/equal/greater/question + /at/A/B/C/D/E/F/G + /H/I/J/K/L/M/N/O + /P/Q/R/S/T/U/V/W + /X/Y/Z/bracketleft/backslash/bracketright/asciicircum/underscore + /quoteleft/a/b/c/d/e/f/g + /h/i/j/k/l/m/n/o + /p/q/r/s/t/u/v/w + /x/y/z/braceleft/bar/braceright/asciitilde/.notdef + /Euro/.notdef/quotesinglbase/florin/quotedblbase/ellipsis/dagger/daggerdbl + /circumflex/perthousand/Scaron/guilsinglleft/OE/.notdef/.notdef/.notdef + /.notdef/.notdef/.notdef/quotedblleft/quotedblright/bullet/endash/emdash + /tilde/trademark/scaron/guilsinglright/oe/.notdef/.notdef/Ydieresis + /.notdef/exclamdown/cent/sterling/currency/yen/brokenbar/section + /dieresis/copyright/ordfeminine/guillemotleft/logicalnot/hyphen/registered/macron + /degree/plusminus/twosuperior/threesuperior/acute/mu/paragraph/periodcentered + /cedilla/onesuperior/ordmasculine/guillemotright/onequarter/onehalf/threequarters/questiondown + /Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE/Ccedilla + /Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex/Idieresis + /Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis/multiply + /Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls + /agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla + /egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis + /eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide + /oslash/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis] +pdfMakeFont +612 792 false pdfSetup +%%EndSetup +%%Page: 1 1 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 756] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 463.018 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -468 -36] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -720] cm +[1 0 0 1 0 0] Tm +0 0 Td +117.435 701.916 Td +/F121_0 24.79 Tf +(bzip2) 63.3632 Tj +-278 TJm +(and) 44.0766 Tj +-278 TJm +(libbzip2,) 99.1848 Tj +-278 TJm +(ver) 37.2098 Tj +15 TJm +(sion) 50.9682 Tj +-278 TJm +(1.0.3) 55.133 Tj +[1 0 0 1 72 696.784] cm +0 g +0 G +0 g +0 G +[1 0 0 1 0 -15.494] cm +0 g +0 G +[1 0 0 1 -72 -681.29] cm +[1 0 0 1 0 0] Tm +0 0 Td +90.493 661.631 Td +/F121_0 20.659 Tf +(A) 14.9158 Tj +-278 TJm +(pr) 20.659 Tj +20 TJm +(ogram) 63.1339 Tj +-278 TJm +(and) 36.7317 Tj +-278 TJm +(librar) 51.6682 Tj +-10 TJm +(y) 11.4864 Tj +-278 TJm +(f) 6.87945 Tj +20 TJm +(or) 20.659 Tj +-278 TJm +(data) 42.4749 Tj +-277 TJm +(compression) 128.582 Tj +[1 0 0 1 72 657.035] cm +0 g +0 G +[1 0 0 1 0 -144] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -513.035] cm +[1 0 0 1 0 0] Tm +0 0 Td +207.676 503.285 Td +/F121_0 11.955 Tf +(J) 6.64698 Tj +20 TJm +(ulian) 27.903 Tj +-278 TJm +(Se) 14.621 Tj +15 TJm +(war) 20.5985 Tj +20 TJm +(d,) 10.628 Tj +-278 TJm +(http://www) 61.102 Tj +40 TJm +(.bzip.or) 42.512 Tj +15 TJm +(g) 7.30451 Tj +[1 0 0 1 72 500.625] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -435.825] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 463.018 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 2 2 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 140.398 0] cm +0 g +0 G +[1 0 0 1 -140.398 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -13.948] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -468 -21.554] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -720] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 709.534 Td +/F121_0 14.346 Tf +(bzip2) 36.6684 Tj +-489 TJm +(and) 25.5072 Tj +-488 TJm +(libbzip2,) 57.3983 Tj +-542 TJm +(ver) 21.5333 Tj +15 TJm +(sion) 29.4954 Tj +-489 TJm +(1.0.3:) 36.6827 Tj +-765 TJm +(A) 10.3578 Tj +-488 TJm +(pr) 14.346 Tj +20 TJm +(ogram) 43.8414 Tj +-489 TJm +(and) 25.5072 Tj +-489 TJm +(librar) 35.8793 Tj +-10 TJm +(y) 7.97638 Tj +-489 TJm +(f) 4.77722 Tj +20 TJm +(or) 14.346 Tj +-488 TJm +(data) 29.4954 Tj +72 692.319 Td +(compression) 89.2895 Tj +[1 0 0 1 72 689.349] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -689.349] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 680.364 Td +/F128_0 9.963 Tf +(by) 9.963 Tj +-250 TJm +(Julian) 23.8016 Tj +-250 TJm +(Se) 9.963 Tj +25 TJm +(w) 7.19329 Tj +10 TJm +(ard) 12.7228 Tj +[1 0 0 1 72 678.207] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -678.207] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 668.409 Td +/F128_0 9.963 Tf +(Cop) 16.6083 Tj +10 TJm +(yright) 23.8016 Tj +[1 0 0 1 114.799 668.409] cm +0 g +0 G +[1 0 0 1 -114.799 -668.409] cm +[1 0 0 1 0 0] Tm +0 0 Td +114.799 668.409 Td +/F128_0 9.963 Tf +(\251) 7.57188 Tj +[1 0 0 1 122.371 668.409] cm +0 g +0 G +[1 0 0 1 -122.371 -668.409] cm +[1 0 0 1 0 0] Tm +0 0 Td +124.861 668.409 Td +/F128_0 9.963 Tf +(1996-2005) 43.1697 Tj +-250 TJm +(Julian) 23.8016 Tj +-250 TJm +(Se) 9.963 Tj +25 TJm +(w) 7.19329 Tj +10 TJm +(ard) 12.7228 Tj +[1 0 0 1 72 666.252] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -7.97] cm +0 g +0 G +[1 0 0 1 -72 -658.282] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 650.874 Td +/F128_0 7.97 Tf +(This) 14.1707 Tj +-250 TJm +(program,) 28.9949 Tj +[1 0 0 1 119.151 650.874] cm +0 g +0 G +[1 0 0 1 -119.151 -650.874] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.151 650.874 Td +/F130_0 7.97 Tf +(bzip2) 23.91 Tj +[1 0 0 1 143.061 650.874] cm +0 g +0 G +[1 0 0 1 -143.061 -650.874] cm +[1 0 0 1 0 0] Tm +0 0 Td +143.061 650.874 Td +/F128_0 7.97 Tf +(,) 1.9925 Tj +-250 TJm +(the) 9.73934 Tj +-250 TJm +(associated) 32.7567 Tj +-250 TJm +(library) 21.248 Tj +[1 0 0 1 216.768 650.874] cm +0 g +0 G +[1 0 0 1 -216.768 -650.874] cm +[1 0 0 1 0 0] Tm +0 0 Td +216.768 650.874 Td +/F130_0 7.97 Tf +(libbzip2) 38.256 Tj +[1 0 0 1 255.024 650.874] cm +0 g +0 G +[1 0 0 1 -255.024 -650.874] cm +[1 0 0 1 0 0] Tm +0 0 Td +255.024 650.874 Td +/F128_0 7.97 Tf +(,) 1.9925 Tj +-250 TJm +(and) 11.5087 Tj +-250 TJm +(all) 7.97 Tj +-250 TJm +(documentation,) 49.3662 Tj +-250 TJm +(are) 9.73137 Tj +-250 TJm +(cop) 11.5087 Tj +10 TJm +(yright) 19.0403 Tj +-250 TJm +(\251) 6.0572 Tj +-250 TJm +(1996-2005) 34.534 Tj +-250 TJm +(Julian) 19.0403 Tj +-250 TJm +(Se) 7.97 Tj +25 TJm +(w) 5.75434 Tj +10 TJm +(ard.) 12.1702 Tj +-310 TJm +(All) 10.1857 Tj +-250 TJm +(rights) 18.1557 Tj +-250 TJm +(reserv) 19.4707 Tj +15 TJm +(ed.) 9.51618 Tj +[1 0 0 1 72 649.149] cm +0 g +0 G +[1 0 0 1 0 -7.97] cm +0 g +0 G +[1 0 0 1 -72 -641.179] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 633.34 Td +/F128_0 7.97 Tf +(Redistrib) 29.226 Tj +20 TJm +(ution) 16.3863 Tj +-250 TJm +(and) 11.5087 Tj +-250 TJm +(use) 10.624 Tj +-250 TJm +(in) 6.20066 Tj +-250 TJm +(source) 20.8017 Tj +-250 TJm +(and) 11.5087 Tj +-250 TJm +(binary) 20.3634 Tj +-250 TJm +(forms,) 20.5865 Tj +-250 TJm +(with) 14.1707 Tj +-250 TJm +(or) 6.63901 Tj +-250 TJm +(without) 24.3563 Tj +-250 TJm +(modi\002cation,) 42.2888 Tj +-250 TJm +(are) 9.73137 Tj +-250 TJm +(permitted) 30.549 Tj +-250 TJm +(pro) 10.624 Tj +15 TJm +(vided) 17.7093 Tj +-250 TJm +(that) 11.955 Tj +-250 TJm +(the) 9.73934 Tj +-250 TJm +(follo) 15.0553 Tj +25 TJm +(wing) 15.94 Tj +-250 TJm +(conditions) 33.211 Tj +-250 TJm +(are) 9.73137 Tj +-250 TJm +(met:) 14.1707 Tj +[1 0 0 1 72 631.615] cm +0 g +0 G +[1 0 0 1 0 -23.779] cm +0 g +0 G +[1 0 0 1 5.579 0] cm +0 g +0 G +[1 0 0 1 -77.579 -607.836] cm +[1 0 0 1 0 0] Tm +0 0 Td +77.579 607.836 Td +/F128_0 7.97 Tf +(\225) 2.7895 Tj +[1 0 0 1 80.369 607.836] cm +0 g +0 G +[1 0 0 1 1.992 0] cm +0 g +0 G +[1 0 0 1 1.594 0] cm +0 g +0 G +[1 0 0 1 -83.955 -607.836] cm +[1 0 0 1 0 0] Tm +0 0 Td +83.955 607.836 Td +/F128_0 7.97 Tf +(Redistrib) 29.226 Tj +20 TJm +(utions) 19.4867 Tj +-250 TJm +(of) 6.63901 Tj +-250 TJm +(source) 20.8017 Tj +-250 TJm +(code) 15.0474 Tj +-250 TJm +(must) 15.5017 Tj +-250 TJm +(retain) 18.1477 Tj +-250 TJm +(the) 9.73934 Tj +-250 TJm +(abo) 11.5087 Tj +15 TJm +(v) 3.985 Tj +15 TJm +(e) 3.53868 Tj +-250 TJm +(cop) 11.5087 Tj +10 TJm +(yright) 19.0403 Tj +-250 TJm +(notice,) 21.4712 Tj +-250 TJm +(this) 11.5167 Tj +-250 TJm +(list) 9.74731 Tj +-250 TJm +(of) 6.63901 Tj +-250 TJm +(conditions) 33.211 Tj +-250 TJm +(and) 11.5087 Tj +-250 TJm +(the) 9.73934 Tj +-250 TJm +(follo) 15.0553 Tj +25 TJm +(wing) 15.94 Tj +-250 TJm +(disclaimer) 33.203 Tj +55 TJm +(.) 1.9925 Tj +[1 0 0 1 470.908 607.836] cm +0 g +0 G +[1 0 0 1 -398.908 -17.534] cm +0 g +0 G +[1 0 0 1 5.579 0] cm +0 g +0 G +[1 0 0 1 -77.579 -590.302] cm +[1 0 0 1 0 0] Tm +0 0 Td +77.579 590.302 Td +/F128_0 7.97 Tf +(\225) 2.7895 Tj +[1 0 0 1 80.369 590.302] cm +0 g +0 G +[1 0 0 1 1.992 0] cm +0 g +0 G +[1 0 0 1 1.594 0] cm +0 g +0 G +[1 0 0 1 -83.955 -590.302] cm +[1 0 0 1 0 0] Tm +0 0 Td +83.955 590.302 Td +/F128_0 7.97 Tf +(The) 12.3933 Tj +-270 TJm +(origin) 19.0403 Tj +-270 TJm +(of) 6.63901 Tj +-270 TJm +(this) 11.5167 Tj +-270 TJm +(softw) 17.7093 Tj +10 TJm +(are) 9.73137 Tj +-270 TJm +(must) 15.5017 Tj +-270 TJm +(not) 10.1857 Tj +-270 TJm +(be) 7.52368 Tj +-270 TJm +(misrepresented;) 50.466 Tj +-280 TJm +(you) 11.955 Tj +-270 TJm +(must) 15.5017 Tj +-270 TJm +(not) 10.1857 Tj +-270 TJm +(claim) 17.7093 Tj +-270 TJm +(that) 11.955 Tj +-270 TJm +(you) 11.955 Tj +-270 TJm +(wrote) 18.1477 Tj +-270 TJm +(the) 9.73934 Tj +-270 TJm +(original) 24.7947 Tj +-270 TJm +(softw) 17.7093 Tj +10 TJm +(are.) 11.7239 Tj +-739 TJm +(If) 5.30802 Tj +-270 TJm +(you) 11.955 Tj +-270 TJm +(use) 10.624 Tj +-270 TJm +(this) 11.5167 Tj +-270 TJm +(softw) 17.7093 Tj +10 TJm +(are) 9.73137 Tj +-270 TJm +(in) 6.20066 Tj +-270 TJm +(a) 3.53868 Tj +83.955 580.738 Td +(product,) 26.3409 Tj +-250 TJm +(an) 7.52368 Tj +-250 TJm +(ackno) 19.0324 Tj +25 TJm +(wledgment) 35.4187 Tj +-250 TJm +(in) 6.20066 Tj +-250 TJm +(the) 9.73934 Tj +-250 TJm +(product) 24.3484 Tj +-250 TJm +(documentation) 47.3737 Tj +-250 TJm +(w) 5.75434 Tj +10 TJm +(ould) 14.1707 Tj +-250 TJm +(be) 7.52368 Tj +-250 TJm +(appreciated) 36.7337 Tj +-250 TJm +(b) 3.985 Tj +20 TJm +(ut) 6.20066 Tj +-250 TJm +(is) 5.31599 Tj +-250 TJm +(not) 10.1857 Tj +-250 TJm +(required.) 28.5485 Tj +[1 0 0 1 403.817 580.738] cm +0 g +0 G +[1 0 0 1 -331.817 -17.535] cm +0 g +0 G +[1 0 0 1 5.579 0] cm +0 g +0 G +[1 0 0 1 -77.579 -563.203] cm +[1 0 0 1 0 0] Tm +0 0 Td +77.579 563.203 Td +/F128_0 7.97 Tf +(\225) 2.7895 Tj +[1 0 0 1 80.369 563.203] cm +0 g +0 G +[1 0 0 1 1.992 0] cm +0 g +0 G +[1 0 0 1 1.594 0] cm +0 g +0 G +[1 0 0 1 -83.955 -563.203] cm +[1 0 0 1 0 0] Tm +0 0 Td +83.955 563.203 Td +/F128_0 7.97 Tf +(Altered) 23.902 Tj +-250 TJm +(source) 20.8017 Tj +-250 TJm +(v) 3.985 Tj +15 TJm +(ersions) 22.579 Tj +-250 TJm +(must) 15.5017 Tj +-250 TJm +(be) 7.52368 Tj +-250 TJm +(plainly) 22.1407 Tj +-250 TJm +(mark) 16.3783 Tj +10 TJm +(ed) 7.52368 Tj +-250 TJm +(as) 6.63901 Tj +-250 TJm +(such,) 16.6015 Tj +-250 TJm +(and) 11.5087 Tj +-250 TJm +(must) 15.5017 Tj +-250 TJm +(not) 10.1857 Tj +-250 TJm +(be) 7.52368 Tj +-250 TJm +(misrepresented) 48.2504 Tj +-250 TJm +(as) 6.63901 Tj +-250 TJm +(being) 17.7093 Tj +-250 TJm +(the) 9.73934 Tj +-250 TJm +(original) 24.7947 Tj +-250 TJm +(softw) 17.7093 Tj +10 TJm +(are.) 11.7239 Tj +[1 0 0 1 464.405 563.203] cm +0 g +0 G +[1 0 0 1 -392.405 -17.534] cm +0 g +0 G +[1 0 0 1 5.579 0] cm +0 g +0 G +[1 0 0 1 -77.579 -545.669] cm +[1 0 0 1 0 0] Tm +0 0 Td +77.579 545.669 Td +/F128_0 7.97 Tf +(\225) 2.7895 Tj +[1 0 0 1 80.369 545.669] cm +0 g +0 G +[1 0 0 1 1.992 0] cm +0 g +0 G +[1 0 0 1 1.594 0] cm +0 g +0 G +[1 0 0 1 -83.955 -545.669] cm +[1 0 0 1 0 0] Tm +0 0 Td +83.955 545.669 Td +/F128_0 7.97 Tf +(The) 12.3933 Tj +-250 TJm +(name) 17.263 Tj +-250 TJm +(of) 6.63901 Tj +-250 TJm +(the) 9.73934 Tj +-250 TJm +(author) 20.3634 Tj +-250 TJm +(may) 13.7243 Tj +-250 TJm +(not) 10.1857 Tj +-250 TJm +(be) 7.52368 Tj +-250 TJm +(used) 14.609 Tj +-250 TJm +(to) 6.20066 Tj +-250 TJm +(endorse) 24.7867 Tj +-250 TJm +(or) 6.63901 Tj +-250 TJm +(promote) 26.564 Tj +-250 TJm +(products) 27.4487 Tj +-250 TJm +(deri) 12.3933 Tj +25 TJm +(v) 3.985 Tj +15 TJm +(ed) 7.52368 Tj +-250 TJm +(from) 15.4937 Tj +-250 TJm +(this) 11.5167 Tj +-250 TJm +(softw) 17.7093 Tj +10 TJm +(are) 9.73137 Tj +-250 TJm +(without) 24.3563 Tj +-250 TJm +(speci\002c) 24.3483 Tj +-250 TJm +(prior) 15.4937 Tj +-250 TJm +(written) 22.579 Tj +-250 TJm +(permission.) 36.9728 Tj +[1 0 0 1 533.577 545.669] cm +0 g +0 G +[1 0 0 1 -461.577 -9.696] cm +0 g +0 G +[1 0 0 1 -72 -535.973] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 528.135 Td +/F128_0 7.97 Tf +(THIS) 17.7093 Tj +-259 TJm +(SOFTW) 27.0103 Tj +120 TJm +(ARE) 15.94 Tj +-259 TJm +(IS) 7.08533 Tj +-258 TJm +(PR) 9.74731 Tj +40 TJm +(O) 5.75434 Tj +50 TJm +(VIDED) 24.7867 Tj +-259 TJm +(BY) 11.0703 Tj +-259 TJm +(THE) 15.4937 Tj +-259 TJm +(A) 5.75434 Tj +55 TJm +(UTHOR) 27.4487 Tj +-258 TJm +("AS) 13.4374 Tj +-259 TJm +(IS") 10.3371 Tj +-259 TJm +(AND) 17.263 Tj +-259 TJm +(ANY) 17.263 Tj +-258 TJm +(EXPRESS) 34.1036 Tj +-259 TJm +(OR) 11.0703 Tj +-259 TJm +(IMPLIED) 32.3184 Tj +-259 TJm +(W) 7.52368 Tj +120 TJm +(ARRANTIES,) 46.7122 Tj +-259 TJm +(INCLUDING,) 46.2579 Tj +-258 TJm +(B) 5.31599 Tj +10 TJm +(UT) 10.624 Tj +-259 TJm +(NO) 11.5087 Tj +40 TJm +(T) 4.86967 Tj +72 518.571 Td +(LIMITED) 32.7567 Tj +-303 TJm +(T) 4.86967 Tj +18 TJm +(O,) 7.74684 Tj +-303 TJm +(THE) 15.4937 Tj +-304 TJm +(IMPLIED) 32.3184 Tj +-303 TJm +(W) 7.52368 Tj +120 TJm +(ARRANTIES) 44.7197 Tj +-303 TJm +(OF) 10.1857 Tj +-303 TJm +(MERCHANT) 44.7197 Tj +93 TJm +(ABILITY) 31.872 Tj +-304 TJm +(AND) 17.263 Tj +-303 TJm +(FITNESS) 31.4417 Tj +-303 TJm +(FOR) 15.5017 Tj +-303 TJm +(A) 5.75434 Tj +-303 TJm +(P) 4.43132 Tj +92 TJm +(AR) 11.0703 Tj +60 TJm +(TICULAR) 34.534 Tj +-304 TJm +(PURPOSE) 34.9883 Tj +-303 TJm +(ARE) 15.94 Tj +-303 TJm +(DISCLAI-) 34.0877 Tj +72 509.007 Td +(MED.) 19.7018 Tj +-653 TJm +(IN) 8.40835 Tj +-326 TJm +(NO) 11.5087 Tj +-327 TJm +(EVENT) 26.1177 Tj +-326 TJm +(SHALL) 25.6793 Tj +-326 TJm +(THE) 15.4937 Tj +-327 TJm +(A) 5.75434 Tj +55 TJm +(UTHOR) 27.4487 Tj +-326 TJm +(BE) 10.1857 Tj +-327 TJm +(LIABLE) 28.3333 Tj +-326 TJm +(FOR) 15.5017 Tj +-326 TJm +(ANY) 17.263 Tj +-327 TJm +(DIRECT) 28.7797 Tj +74 TJm +(,) 1.9925 Tj +-326 TJm +(INDIRECT) 37.188 Tj +74 TJm +(,) 1.9925 Tj +-327 TJm +(INCIDENT) 37.6264 Tj +93 TJm +(AL,) 12.6165 Tj +-326 TJm +(SPECIAL,) 34.3188 Tj +-327 TJm +(EXEMPLAR) 42.9503 Tj +65 TJm +(Y) 5.75434 Tj +129 TJm +(,) 1.9925 Tj +-326 TJm +(OR) 11.0703 Tj +72 499.442 Td +(CONSEQ) 31.88 Tj +10 TJm +(UENTIAL) 34.526 Tj +-218 TJm +(D) 5.75434 Tj +40 TJm +(AMA) 18.594 Tj +40 TJm +(GES) 15.0553 Tj +-218 TJm +(\(INCLUDING,) 48.9119 Tj +-218 TJm +(B) 5.31599 Tj +10 TJm +(UT) 10.624 Tj +-218 TJm +(NO) 11.5087 Tj +40 TJm +(T) 4.86967 Tj +-218 TJm +(LIMITED) 32.7567 Tj +-219 TJm +(T) 4.86967 Tj +18 TJm +(O,) 7.74684 Tj +-218 TJm +(PR) 9.74731 Tj +40 TJm +(OCUREMENT) 49.5893 Tj +-218 TJm +(OF) 10.1857 Tj +-218 TJm +(SUBSTITUTE) 47.82 Tj +-218 TJm +(GOODS) 27.4487 Tj +-218 TJm +(OR) 11.0703 Tj +-218 TJm +(SER) 14.617 Tj +80 TJm +(VICES;) 25.241 Tj +-218 TJm +(LOSS) 19.4867 Tj +72 489.878 Td +(OF) 10.1857 Tj +-207 TJm +(USE,) 17.0478 Tj +-207 TJm +(D) 5.75434 Tj +40 TJm +(A) 5.75434 Tj +111 TJm +(T) 4.86967 Tj +93 TJm +(A,) 7.74684 Tj +-208 TJm +(OR) 11.0703 Tj +-207 TJm +(PR) 9.74731 Tj +40 TJm +(OFITS;) 24.3563 Tj +-207 TJm +(OR) 11.0703 Tj +-207 TJm +(B) 5.31599 Tj +10 TJm +(USINESS) 32.3263 Tj +-207 TJm +(INTERR) 28.7797 Tj +40 TJm +(UPTION\)) 31.872 Tj +-208 TJm +(HO) 11.5087 Tj +35 TJm +(WEVER) 28.3333 Tj +-207 TJm +(CA) 11.0703 Tj +55 TJm +(USED) 20.8097 Tj +-207 TJm +(AND) 17.263 Tj +-207 TJm +(ON) 11.5087 Tj +-207 TJm +(ANY) 17.263 Tj +-207 TJm +(THEOR) 26.564 Tj +65 TJm +(Y) 5.75434 Tj +-208 TJm +(OF) 10.1857 Tj +-207 TJm +(LIABILITY) 39.3957 Tj +129 TJm +(,) 1.9925 Tj +-207 TJm +(WHETHER) 38.9574 Tj +72 480.314 Td +(IN) 8.40835 Tj +-205 TJm +(CONTRA) 32.7647 Tj +40 TJm +(CT) 10.1857 Tj +74 TJm +(,) 1.9925 Tj +-205 TJm +(STRICT) 27.4567 Tj +-204 TJm +(LIABILITY) 39.3957 Tj +129 TJm +(,) 1.9925 Tj +-205 TJm +(OR) 11.0703 Tj +-205 TJm +(T) 4.86967 Tj +18 TJm +(OR) 11.0703 Tj +60 TJm +(T) 4.86967 Tj +-205 TJm +(\(INCLUDING) 46.9194 Tj +-204 TJm +(NEGLIGENCE) 50.466 Tj +-205 TJm +(OR) 11.0703 Tj +-205 TJm +(O) 5.75434 Tj +40 TJm +(THER) 20.8097 Tj +55 TJm +(WISE\)) 22.1327 Tj +-205 TJm +(ARISING) 32.3184 Tj +-205 TJm +(IN) 8.40835 Tj +-204 TJm +(ANY) 17.263 Tj +-205 TJm +(W) 7.52368 Tj +120 TJm +(A) 5.75434 Tj +105 TJm +(Y) 5.75434 Tj +-205 TJm +(OUT) 16.3783 Tj +-205 TJm +(OF) 10.1857 Tj +-204 TJm +(THE) 15.4937 Tj +-205 TJm +(USE) 15.0553 Tj +72 470.75 Td +(OF) 10.1857 Tj +-250 TJm +(THIS) 17.7093 Tj +-250 TJm +(SOFTW) 27.0103 Tj +120 TJm +(ARE,) 17.9325 Tj +-250 TJm +(EVEN) 21.248 Tj +-250 TJm +(IF) 7.08533 Tj +-250 TJm +(AD) 11.5087 Tj +40 TJm +(VISED) 23.4637 Tj +-250 TJm +(OF) 10.1857 Tj +-250 TJm +(THE) 15.4937 Tj +-250 TJm +(POSSIBILITY) 47.82 Tj +-250 TJm +(OF) 10.1857 Tj +-250 TJm +(SUCH) 21.256 Tj +-250 TJm +(D) 5.75434 Tj +40 TJm +(AMA) 18.594 Tj +40 TJm +(GE.) 12.6165 Tj +[1 0 0 1 72 469.598] cm +0 g +0 G +[1 0 0 1 0 -7.97] cm +0 g +0 G +[1 0 0 1 -72 -461.628] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 453.216 Td +/F128_0 7.97 Tf +(P) 4.43132 Tj +92 TJm +(A) 5.75434 Tj +111 TJm +(TENTS:) 27.0103 Tj +-296 TJm +(T) 4.86967 Tj +80 TJm +(o) 3.985 Tj +-295 TJm +(the) 9.73934 Tj +-296 TJm +(best) 12.8397 Tj +-295 TJm +(of) 6.63901 Tj +-296 TJm +(my) 10.1857 Tj +-295 TJm +(kno) 11.955 Tj +25 TJm +(wledge,) 25.0099 Tj +[1 0 0 1 208.544 453.216] cm +0 g +0 G +[1 0 0 1 -208.544 -453.216] cm +[1 0 0 1 0 0] Tm +0 0 Td +208.544 453.216 Td +/F130_0 7.97 Tf +(bzip2) 23.91 Tj +[1 0 0 1 232.454 453.216] cm +0 g +0 G +[1 0 0 1 -232.454 -453.216] cm +[1 0 0 1 0 0] Tm +0 0 Td +234.81 453.216 Td +/F128_0 7.97 Tf +(and) 11.5087 Tj +[1 0 0 1 248.674 453.216] cm +0 g +0 G +[1 0 0 1 -248.674 -453.216] cm +[1 0 0 1 0 0] Tm +0 0 Td +248.674 453.216 Td +/F130_0 7.97 Tf +(libbzip2) 38.256 Tj +[1 0 0 1 286.931 453.216] cm +0 g +0 G +[1 0 0 1 -286.931 -453.216] cm +[1 0 0 1 0 0] Tm +0 0 Td +289.286 453.216 Td +/F128_0 7.97 Tf +(do) 7.97 Tj +-296 TJm +(not) 10.1857 Tj +-295 TJm +(use) 10.624 Tj +-296 TJm +(an) 7.52368 Tj +15 TJm +(y) 3.985 Tj +-295 TJm +(patented) 27.0024 Tj +-296 TJm +(algorithms.) 36.0882 Tj +-893 TJm +(Ho) 9.73934 Tj +25 TJm +(we) 9.29302 Tj +25 TJm +(v) 3.985 Tj +15 TJm +(er) 6.19269 Tj +40 TJm +(,) 1.9925 Tj +-307 TJm +(I) 2.65401 Tj +-295 TJm +(do) 7.97 Tj +-296 TJm +(not) 10.1857 Tj +-296 TJm +(ha) 7.52368 Tj +20 TJm +(v) 3.985 Tj +15 TJm +(e) 3.53868 Tj +-295 TJm +(the) 9.73934 Tj +-296 TJm +(resources) 30.0947 Tj +-295 TJm +(to) 6.20066 Tj +72 443.652 Td +(carry) 16.3704 Tj +-250 TJm +(out) 10.1857 Tj +-250 TJm +(a) 3.53868 Tj +-250 TJm +(patent) 19.4787 Tj +-250 TJm +(search.) 22.3479 Tj +-620 TJm +(Therefore) 31.4177 Tj +-250 TJm +(I) 2.65401 Tj +-250 TJm +(cannot) 21.248 Tj +-250 TJm +(gi) 6.20066 Tj +25 TJm +(v) 3.985 Tj +15 TJm +(e) 3.53868 Tj +-250 TJm +(an) 7.52368 Tj +15 TJm +(y) 3.985 Tj +-250 TJm +(guarantee) 30.9794 Tj +-250 TJm +(of) 6.63901 Tj +-250 TJm +(the) 9.73934 Tj +-250 TJm +(abo) 11.5087 Tj +15 TJm +(v) 3.985 Tj +15 TJm +(e) 3.53868 Tj +-250 TJm +(statement.) 32.5415 Tj +[1 0 0 1 72 441.926] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -391.074] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 46.799 0] cm +0 g +0 G +[1 0 0 1 -46.799 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 3 3 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 140.398 0] cm +0 g +0 G +[1 0 0 1 -140.398 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -13.948] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -468 -21.554] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -720] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 707.441 Td +/F121_0 17.215 Tf +(T) 10.5184 Tj +80 TJm +(ab) 20.0899 Tj +10 TJm +(le) 14.3573 Tj +-278 TJm +(of) 16.251 Tj +-278 TJm +(Contents) 74.5926 Tj +[1 0 0 1 72 698.619] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -11.741] cm +0 g +0 G +[1 0 0 1 -72 -686.878] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 686.878 Td +/F128_0 9.963 Tf +(1.) 7.47225 Tj +-310 TJm +(Introduction) 49.2571 Tj +[1 0 0 1 131.815 686.878] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -136.797 -686.878] cm +[1 0 0 1 0 0] Tm +0 0 Td +145.733 686.878 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 511.108 686.878] cm +0 g +0 G +[1 0 0 1 -511.108 -686.878] cm +[1 0 0 1 0 0] Tm +0 0 Td +511.108 686.878 Td +/F128_0 9.963 Tf +(1) 4.9815 Tj +[1 0 0 1 516.09 686.878] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -0.099] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -11.856] cm +0 g +0 G +[1 0 0 1 -72 -674.923] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 674.923 Td +/F128_0 9.963 Tf +(2.) 7.47225 Tj +-310 TJm +(Ho) 12.1748 Tj +25 TJm +(w) 7.19329 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(use) 13.2807 Tj +-250 TJm +(bzip2) 22.1378 Tj +[1 0 0 1 152.318 674.923] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -157.3 -674.923] cm +[1 0 0 1 0 0] Tm +0 0 Td +167.054 674.923 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 511.108 674.923] cm +0 g +0 G +[1 0 0 1 -511.108 -674.923] cm +[1 0 0 1 0 0] Tm +0 0 Td +511.108 674.923 Td +/F128_0 9.963 Tf +(2) 4.9815 Tj +[1 0 0 1 516.09 674.923] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 23.91 -9.798] cm +0 g +0 G +[1 0 0 1 -95.91 -662.968] cm +[1 0 0 1 0 0] Tm +0 0 Td +95.91 662.968 Td +/F128_0 9.963 Tf +(2.1.) 14.9445 Tj +-310 TJm +(N) 7.19329 Tj +35 TJm +(AME) 22.1378 Tj +[1 0 0 1 142.924 662.968] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -147.905 -662.968] cm +[1 0 0 1 0 0] Tm +0 0 Td +157.929 662.968 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 511.108 662.968] cm +0 g +0 G +[1 0 0 1 -511.108 -662.968] cm +[1 0 0 1 0 0] Tm +0 0 Td +511.108 662.968 Td +/F128_0 9.963 Tf +(2) 4.9815 Tj +[1 0 0 1 516.09 662.968] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -0.099] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 23.91 -11.856] cm +0 g +0 G +[1 0 0 1 -95.91 -651.013] cm +[1 0 0 1 0 0] Tm +0 0 Td +95.91 651.013 Td +/F128_0 9.963 Tf +(2.2.) 14.9445 Tj +-310 TJm +(SYNOPSIS) 47.0552 Tj +[1 0 0 1 160.996 651.013] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -165.977 -651.013] cm +[1 0 0 1 0 0] Tm +0 0 Td +175.821 651.013 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 511.108 651.013] cm +0 g +0 G +[1 0 0 1 -511.108 -651.013] cm +[1 0 0 1 0 0] Tm +0 0 Td +511.108 651.013 Td +/F128_0 9.963 Tf +(2) 4.9815 Tj +[1 0 0 1 516.09 651.013] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -0.1] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 23.91 -11.855] cm +0 g +0 G +[1 0 0 1 -95.91 -639.058] cm +[1 0 0 1 0 0] Tm +0 0 Td +95.91 639.058 Td +/F128_0 9.963 Tf +(2.3.) 14.9445 Tj +-310 TJm +(DESCRIPTION) 64.7595 Tj +[1 0 0 1 178.699 639.058] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -183.681 -639.058] cm +[1 0 0 1 0 0] Tm +0 0 Td +193.528 639.058 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 511.108 639.058] cm +0 g +0 G +[1 0 0 1 -511.108 -639.058] cm +[1 0 0 1 0 0] Tm +0 0 Td +511.108 639.058 Td +/F128_0 9.963 Tf +(3) 4.9815 Tj +[1 0 0 1 516.09 639.058] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -0.1] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 23.91 -11.855] cm +0 g +0 G +[1 0 0 1 -95.91 -627.103] cm +[1 0 0 1 0 0] Tm +0 0 Td +95.91 627.103 Td +/F128_0 9.963 Tf +(2.4.) 14.9445 Tj +-310 TJm +(OPTIONS) 42.0638 Tj +[1 0 0 1 156.005 627.103] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -160.986 -627.103] cm +[1 0 0 1 0 0] Tm +0 0 Td +171.111 627.103 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 511.108 627.103] cm +0 g +0 G +[1 0 0 1 -511.108 -627.103] cm +[1 0 0 1 0 0] Tm +0 0 Td +511.108 627.103 Td +/F128_0 9.963 Tf +(4) 4.9815 Tj +[1 0 0 1 516.09 627.103] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -0.1] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 23.91 -11.856] cm +0 g +0 G +[1 0 0 1 -95.91 -615.147] cm +[1 0 0 1 0 0] Tm +0 0 Td +95.91 615.147 Td +/F128_0 9.963 Tf +(2.5.) 14.9445 Tj +-310 TJm +(MEMOR) 37.6402 Tj +65 TJm +(Y) 7.19329 Tj +-250 TJm +(MAN) 23.2437 Tj +35 TJm +(A) 7.19329 Tj +40 TJm +(GEMENT) 41.5059 Tj +[1 0 0 1 231.81 615.147] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -236.791 -615.147] cm +[1 0 0 1 0 0] Tm +0 0 Td +246.65 615.147 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 511.108 615.147] cm +0 g +0 G +[1 0 0 1 -511.108 -615.147] cm +[1 0 0 1 0 0] Tm +0 0 Td +511.108 615.147 Td +/F128_0 9.963 Tf +(5) 4.9815 Tj +[1 0 0 1 516.09 615.147] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -0.099] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 23.91 -11.856] cm +0 g +0 G +[1 0 0 1 -95.91 -603.192] cm +[1 0 0 1 0 0] Tm +0 0 Td +95.91 603.192 Td +/F128_0 9.963 Tf +(2.6.) 14.9445 Tj +-310 TJm +(RECO) 26.5713 Tj +50 TJm +(VERING) 37.6303 Tj +-250 TJm +(D) 7.19329 Tj +40 TJm +(A) 7.19329 Tj +111 TJm +(T) 6.08739 Tj +93 TJm +(A) 7.19329 Tj +-250 TJm +(FR) 12.1847 Tj +40 TJm +(OM) 16.0504 Tj +-249 TJm +(D) 7.19329 Tj +40 TJm +(AMA) 23.2437 Tj +40 TJm +(GED) 20.474 Tj +-250 TJm +(FILES) 26.5713 Tj +[1 0 0 1 317.359 603.192] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -322.34 -603.192] cm +[1 0 0 1 0 0] Tm +0 0 Td +331.489 603.192 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 511.108 603.192] cm +0 g +0 G +[1 0 0 1 -511.108 -603.192] cm +[1 0 0 1 0 0] Tm +0 0 Td +511.108 603.192 Td +/F128_0 9.963 Tf +(6) 4.9815 Tj +[1 0 0 1 516.09 603.192] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -0.099] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 23.91 -11.856] cm +0 g +0 G +[1 0 0 1 -95.91 -591.237] cm +[1 0 0 1 0 0] Tm +0 0 Td +95.91 591.237 Td +/F128_0 9.963 Tf +(2.7.) 14.9445 Tj +-310 TJm +(PERFORMANCE) 73.6266 Tj +-250 TJm +(NO) 14.3866 Tj +40 TJm +(TES) 17.7142 Tj +[1 0 0 1 221.758 591.237] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -226.739 -591.237] cm +[1 0 0 1 0 0] Tm +0 0 Td +237.196 591.237 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 511.108 591.237] cm +0 g +0 G +[1 0 0 1 -511.108 -591.237] cm +[1 0 0 1 0 0] Tm +0 0 Td +511.108 591.237 Td +/F128_0 9.963 Tf +(6) 4.9815 Tj +[1 0 0 1 516.09 591.237] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -0.099] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 23.91 -11.856] cm +0 g +0 G +[1 0 0 1 -95.91 -579.282] cm +[1 0 0 1 0 0] Tm +0 0 Td +95.91 579.282 Td +/F128_0 9.963 Tf +(2.8.) 14.9445 Tj +-310 TJm +(CA) 13.8386 Tj +135 TJm +(VEA) 20.474 Tj +111 TJm +(TS) 11.6268 Tj +[1 0 0 1 157.429 579.282] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -162.411 -579.282] cm +[1 0 0 1 0 0] Tm +0 0 Td +171.824 579.282 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 511.108 579.282] cm +0 g +0 G +[1 0 0 1 -511.108 -579.282] cm +[1 0 0 1 0 0] Tm +0 0 Td +511.108 579.282 Td +/F128_0 9.963 Tf +(7) 4.9815 Tj +[1 0 0 1 516.09 579.282] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -0.1] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 23.91 -11.855] cm +0 g +0 G +[1 0 0 1 -95.91 -567.327] cm +[1 0 0 1 0 0] Tm +0 0 Td +95.91 567.327 Td +/F128_0 9.963 Tf +(2.9.) 14.9445 Tj +-310 TJm +(A) 7.19329 Tj +55 TJm +(UTHOR) 34.3126 Tj +[1 0 0 1 154.899 567.327] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -159.88 -567.327] cm +[1 0 0 1 0 0] Tm +0 0 Td +168.345 567.327 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 511.108 567.327] cm +0 g +0 G +[1 0 0 1 -511.108 -567.327] cm +[1 0 0 1 0 0] Tm +0 0 Td +511.108 567.327 Td +/F128_0 9.963 Tf +(7) 4.9815 Tj +[1 0 0 1 516.09 567.327] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -0.219] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -11.736] cm +0 g +0 G +[1 0 0 1 -72 -555.372] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 555.372 Td +/F128_0 9.963 Tf +(3.) 7.47225 Tj +-310 TJm +(Programming) 54.7965 Tj +-250 TJm +(with) 17.7142 Tj +-250 TJm +(libbzip) 27.6772 Tj +1 TJm +(2) 4.9815 Tj +[1 0 0 1 195.197 555.372] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -200.178 -555.372] cm +[1 0 0 1 0 0] Tm +0 0 Td +210.633 555.372 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 511.108 555.372] cm +0 g +0 G +[1 0 0 1 -511.108 -555.372] cm +[1 0 0 1 0 0] Tm +0 0 Td +511.108 555.372 Td +/F128_0 9.963 Tf +(8) 4.9815 Tj +[1 0 0 1 516.09 555.372] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 23.91 -9.799] cm +0 g +0 G +[1 0 0 1 -95.91 -543.416] cm +[1 0 0 1 0 0] Tm +0 0 Td +95.91 543.416 Td +/F128_0 9.963 Tf +(3.1.) 14.9445 Tj +-310 TJm +(T) 6.08739 Tj +80 TJm +(op-le) 20.474 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(el) 7.19329 Tj +-250 TJm +(structure) 34.8605 Tj +[1 0 0 1 188.831 543.416] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -193.812 -543.416] cm +[1 0 0 1 0 0] Tm +0 0 Td +203.022 543.416 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 511.108 543.416] cm +0 g +0 G +[1 0 0 1 -511.108 -543.416] cm +[1 0 0 1 0 0] Tm +0 0 Td +511.108 543.416 Td +/F128_0 9.963 Tf +(8) 4.9815 Tj +[1 0 0 1 516.09 543.416] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.156] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -9.799] cm +0 g +0 G +[1 0 0 1 -119.821 -531.461] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 531.461 Td +/F128_0 9.963 Tf +(3.1.1.) 22.4168 Tj +-310 TJm +(Lo) 11.0689 Tj +25 TJm +(w-le) 17.7043 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(el) 7.19329 Tj +-250 TJm +(summary) 37.0823 Tj +[1 0 0 1 225.195 531.461] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -230.176 -531.461] cm +[1 0 0 1 0 0] Tm +0 0 Td +238.915 531.461 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 511.108 531.461] cm +0 g +0 G +[1 0 0 1 -511.108 -531.461] cm +[1 0 0 1 0 0] Tm +0 0 Td +511.108 531.461 Td +/F128_0 9.963 Tf +(9) 4.9815 Tj +[1 0 0 1 516.09 531.461] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -9.798] cm +0 g +0 G +[1 0 0 1 -119.821 -519.506] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 519.506 Td +/F128_0 9.963 Tf +(3.1.2.) 22.4168 Tj +-310 TJm +(High-le) 30.437 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(el) 7.19329 Tj +-250 TJm +(summary) 37.0823 Tj +[1 0 0 1 227.107 519.506] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -232.089 -519.506] cm +[1 0 0 1 0 0] Tm +0 0 Td +242.085 519.506 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 511.108 519.506] cm +0 g +0 G +[1 0 0 1 -511.108 -519.506] cm +[1 0 0 1 0 0] Tm +0 0 Td +511.108 519.506 Td +/F128_0 9.963 Tf +(9) 4.9815 Tj +[1 0 0 1 516.09 519.506] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -9.798] cm +0 g +0 G +[1 0 0 1 -119.821 -507.551] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 507.551 Td +/F128_0 9.963 Tf +(3.1.3.) 22.4168 Tj +-310 TJm +(Utility) 26.0234 Tj +-250 TJm +(functions) 37.0823 Tj +-250 TJm +(sum) 16.6083 Tj +1 TJm +(mary) 20.474 Tj +[1 0 0 1 250.489 507.551] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -255.471 -507.551] cm +[1 0 0 1 0 0] Tm +0 0 Td +264.846 507.551 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 511.108 507.551] cm +0 g +0 G +[1 0 0 1 -511.108 -507.551] cm +[1 0 0 1 0 0] Tm +0 0 Td +511.108 507.551 Td +/F128_0 9.963 Tf +(9) 4.9815 Tj +[1 0 0 1 516.09 507.551] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 23.91 -9.798] cm +0 g +0 G +[1 0 0 1 -95.91 -495.596] cm +[1 0 0 1 0 0] Tm +0 0 Td +95.91 495.596 Td +/F128_0 9.963 Tf +(3.2.) 14.9445 Tj +-310 TJm +(Error) 21.0219 Tj +-250 TJm +(handling) 34.8705 Tj +[1 0 0 1 172.323 495.596] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -177.305 -495.596] cm +[1 0 0 1 0 0] Tm +0 0 Td +185.636 495.596 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 495.596] cm +0 g +0 G +[1 0 0 1 -506.127 -495.596] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 495.596 Td +/F128_0 9.963 Tf +(10) 9.963 Tj +[1 0 0 1 516.09 495.596] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 23.91 -9.798] cm +0 g +0 G +[1 0 0 1 -95.91 -483.641] cm +[1 0 0 1 0 0] Tm +0 0 Td +95.91 483.641 Td +/F128_0 9.963 Tf +(3.3.) 14.9445 Tj +-310 TJm +(Lo) 11.0689 Tj +25 TJm +(w-le) 17.7043 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(el) 7.19329 Tj +-250 TJm +(interf) 21.5799 Tj +10 TJm +(ace) 13.2707 Tj +[1 0 0 1 191.481 483.641] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -196.462 -483.641] cm +[1 0 0 1 0 0] Tm +0 0 Td +206.284 483.641 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 483.641] cm +0 g +0 G +[1 0 0 1 -506.127 -483.641] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 483.641 Td +/F128_0 9.963 Tf +(11) 9.963 Tj +[1 0 0 1 516.09 483.641] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -0.1] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -11.856] cm +0 g +0 G +[1 0 0 1 -119.821 -471.685] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 471.685 Td +/F128_0 9.963 Tf +(3.3.1.) 22.4168 Tj +-310 TJm +(BZ2_bzCompressInit) 85.7914 Tj +[1 0 0 1 231.112 471.685] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -236.094 -471.685] cm +[1 0 0 1 0 0] Tm +0 0 Td +246.025 471.685 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 471.685] cm +0 g +0 G +[1 0 0 1 -506.127 -471.685] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 471.685 Td +/F128_0 9.963 Tf +(11) 9.963 Tj +[1 0 0 1 516.09 471.685] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.156] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -9.799] cm +0 g +0 G +[1 0 0 1 -119.821 -459.73] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 459.73 Td +/F128_0 9.963 Tf +(3.3.2.) 22.4168 Tj +-310 TJm +(BZ2_bzCompress) 71.9528 Tj +[1 0 0 1 217.275 459.73] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -222.256 -459.73] cm +[1 0 0 1 0 0] Tm +0 0 Td +232.464 459.73 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 459.73] cm +0 g +0 G +[1 0 0 1 -506.127 -459.73] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 459.73 Td +/F128_0 9.963 Tf +(13) 9.963 Tj +[1 0 0 1 516.09 459.73] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -9.798] cm +0 g +0 G +[1 0 0 1 -119.821 -447.775] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 447.775 Td +/F128_0 9.963 Tf +(3.3.3.) 22.4168 Tj +-310 TJm +(BZ2_bzCompressEnd) 88.0032 Tj +[1 0 0 1 233.324 447.775] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -238.306 -447.775] cm +[1 0 0 1 0 0] Tm +0 0 Td +247.131 447.775 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 447.775] cm +0 g +0 G +[1 0 0 1 -506.127 -447.775] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 447.775 Td +/F128_0 9.963 Tf +(16) 9.963 Tj +[1 0 0 1 516.09 447.775] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -9.798] cm +0 g +0 G +[1 0 0 1 -119.821 -435.82] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 435.82 Td +/F128_0 9.963 Tf +(3.3.4.) 22.4168 Tj +-310 TJm +(BZ2_bzDecompressIni) 92.4168 Tj +1 TJm +(t) 2.76971 Tj +[1 0 0 1 240.507 435.82] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -245.488 -435.82] cm +[1 0 0 1 0 0] Tm +0 0 Td +255.15 435.82 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 435.82] cm +0 g +0 G +[1 0 0 1 -506.127 -435.82] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 435.82 Td +/F128_0 9.963 Tf +(16) 9.963 Tj +[1 0 0 1 516.09 435.82] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -9.798] cm +0 g +0 G +[1 0 0 1 -119.821 -423.865] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 423.865 Td +/F128_0 9.963 Tf +(3.3.5.) 22.4168 Tj +-310 TJm +(BZ2_bzDecompress) 81.3479 Tj +[1 0 0 1 226.669 423.865] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -231.651 -423.865] cm +[1 0 0 1 0 0] Tm +0 0 Td +241.589 423.865 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 423.865] cm +0 g +0 G +[1 0 0 1 -506.127 -423.865] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 423.865 Td +/F128_0 9.963 Tf +(17) 9.963 Tj +[1 0 0 1 516.09 423.865] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -9.798] cm +0 g +0 G +[1 0 0 1 -119.821 -411.91] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 411.91 Td +/F128_0 9.963 Tf +(3.3.6.) 22.4168 Tj +-310 TJm +(BZ2_bzDecompressEn) 92.4168 Tj +1 TJm +(d) 4.9815 Tj +[1 0 0 1 242.719 411.91] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -247.7 -411.91] cm +[1 0 0 1 0 0] Tm +0 0 Td +256.256 411.91 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 411.91] cm +0 g +0 G +[1 0 0 1 -506.127 -411.91] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 411.91 Td +/F128_0 9.963 Tf +(18) 9.963 Tj +[1 0 0 1 516.09 411.91] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 23.91 -9.799] cm +0 g +0 G +[1 0 0 1 -95.91 -399.954] cm +[1 0 0 1 0 0] Tm +0 0 Td +95.91 399.954 Td +/F128_0 9.963 Tf +(3.4.) 14.9445 Tj +-310 TJm +(High-le) 30.437 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(el) 7.19329 Tj +-250 TJm +(interf) 21.5799 Tj +10 TJm +(ace) 13.2707 Tj +[1 0 0 1 193.394 399.954] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -198.375 -399.954] cm +[1 0 0 1 0 0] Tm +0 0 Td +207.24 399.954 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 399.954] cm +0 g +0 G +[1 0 0 1 -506.127 -399.954] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 399.954 Td +/F128_0 9.963 Tf +(18) 9.963 Tj +[1 0 0 1 516.09 399.954] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.156] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -9.799] cm +0 g +0 G +[1 0 0 1 -119.821 -387.999] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 387.999 Td +/F128_0 9.963 Tf +(3.4.1.) 22.4168 Tj +-310 TJm +(BZ2_bzReadOpen) 74.1546 Tj +[1 0 0 1 219.477 387.999] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -224.458 -387.999] cm +[1 0 0 1 0 0] Tm +0 0 Td +233.565 387.999 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 387.999] cm +0 g +0 G +[1 0 0 1 -506.127 -387.999] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 387.999 Td +/F128_0 9.963 Tf +(19) 9.963 Tj +[1 0 0 1 516.09 387.999] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -9.798] cm +0 g +0 G +[1 0 0 1 -119.821 -376.044] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 376.044 Td +/F128_0 9.963 Tf +(3.4.2.) 22.4168 Tj +-310 TJm +(BZ2_bzRead) 52.5748 Tj +[1 0 0 1 197.898 376.044] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -202.879 -376.044] cm +[1 0 0 1 0 0] Tm +0 0 Td +211.706 376.044 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 376.044] cm +0 g +0 G +[1 0 0 1 -506.127 -376.044] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 376.044 Td +/F128_0 9.963 Tf +(20) 9.963 Tj +[1 0 0 1 516.09 376.044] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -1.18] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -10.775] cm +0 g +0 G +[1 0 0 1 -119.821 -364.089] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 364.089 Td +/F128_0 9.963 Tf +(3.4.3.) 22.4168 Tj +-310 TJm +(BZ2_bzReadGetUnuse) 92.4168 Tj +1 TJm +(d) 4.9815 Tj +[1 0 0 1 242.719 364.089] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -247.7 -364.089] cm +[1 0 0 1 0 0] Tm +0 0 Td +256.256 364.089 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 364.089] cm +0 g +0 G +[1 0 0 1 -506.127 -364.089] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 364.089 Td +/F128_0 9.963 Tf +(21) 9.963 Tj +[1 0 0 1 516.09 364.089] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -1.181] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -10.774] cm +0 g +0 G +[1 0 0 1 -119.821 -352.134] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 352.134 Td +/F128_0 9.963 Tf +(3.4.4.) 22.4168 Tj +-310 TJm +(BZ2_bzReadClose) 75.2705 Tj +[1 0 0 1 220.592 352.134] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -225.573 -352.134] cm +[1 0 0 1 0 0] Tm +0 0 Td +234.123 352.134 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 352.134] cm +0 g +0 G +[1 0 0 1 -506.127 -352.134] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 352.134 Td +/F128_0 9.963 Tf +(22) 9.963 Tj +[1 0 0 1 516.09 352.134] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -1.181] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -10.774] cm +0 g +0 G +[1 0 0 1 -119.821 -340.179] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 340.179 Td +/F128_0 9.963 Tf +(3.4.5.) 22.4168 Tj +-310 TJm +(BZ2_bzWriteOpen) 76.3664 Tj +[1 0 0 1 221.688 340.179] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -226.669 -340.179] cm +[1 0 0 1 0 0] Tm +0 0 Td +236.885 340.179 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 340.179] cm +0 g +0 G +[1 0 0 1 -506.127 -340.179] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 340.179 Td +/F128_0 9.963 Tf +(22) 9.963 Tj +[1 0 0 1 516.09 340.179] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -9.799] cm +0 g +0 G +[1 0 0 1 -119.821 -328.223] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 328.223 Td +/F128_0 9.963 Tf +(3.4.6.) 22.4168 Tj +-310 TJm +(BZ2_bzWrite) 54.7865 Tj +[1 0 0 1 200.109 328.223] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -205.09 -328.223] cm +[1 0 0 1 0 0] Tm +0 0 Td +215.026 328.223 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 328.223] cm +0 g +0 G +[1 0 0 1 -506.127 -328.223] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 328.223 Td +/F128_0 9.963 Tf +(23) 9.963 Tj +[1 0 0 1 516.09 328.223] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -1.18] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -10.775] cm +0 g +0 G +[1 0 0 1 -119.821 -316.268] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 316.268 Td +/F128_0 9.963 Tf +(3.4.7.) 22.4168 Tj +-310 TJm +(BZ2_bzWriteClose) 77.4823 Tj +[1 0 0 1 222.804 316.268] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -227.785 -316.268] cm +[1 0 0 1 0 0] Tm +0 0 Td +237.443 316.268 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 316.268] cm +0 g +0 G +[1 0 0 1 -506.127 -316.268] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 316.268 Td +/F128_0 9.963 Tf +(23) 9.963 Tj +[1 0 0 1 516.09 316.268] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -1.18] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -10.775] cm +0 g +0 G +[1 0 0 1 -119.821 -304.313] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 304.313 Td +/F128_0 9.963 Tf +(3.4.8.) 22.4168 Tj +-310 TJm +(Handling) 37.0823 Tj +-250 TJm +(embedded) 40.9479 Tj +-250 TJm +(com) 17.1563 Tj +1 TJm +(pressed) 29.879 Tj +-250 TJm +(data) 16.5984 Tj +-250 TJm +(streams) 30.437 Tj +[1 0 0 1 327.38 304.313] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -332.362 -304.313] cm +[1 0 0 1 0 0] Tm +0 0 Td +342.865 304.313 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 304.313] cm +0 g +0 G +[1 0 0 1 -506.127 -304.313] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 304.313 Td +/F128_0 9.963 Tf +(24) 9.963 Tj +[1 0 0 1 516.09 304.313] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -9.798] cm +0 g +0 G +[1 0 0 1 -119.821 -292.358] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 292.358 Td +/F128_0 9.963 Tf +(3.4.9.) 22.4168 Tj +-310 TJm +(Standard) 35.4185 Tj +-250 TJm +(\002le-reading/) 48.6991 Tj +1 TJm +(writing) 28.7831 Tj +-250 TJm +(code) 18.8101 Tj +[1 0 0 1 282.011 292.358] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -286.992 -292.358] cm +[1 0 0 1 0 0] Tm +0 0 Td +295.827 292.358 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 292.358] cm +0 g +0 G +[1 0 0 1 -506.127 -292.358] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 292.358 Td +/F128_0 9.963 Tf +(25) 9.963 Tj +[1 0 0 1 516.09 292.358] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 23.91 -9.798] cm +0 g +0 G +[1 0 0 1 -95.91 -280.403] cm +[1 0 0 1 0 0] Tm +0 0 Td +95.91 280.403 Td +/F128_0 9.963 Tf +(3.5.) 14.9445 Tj +-310 TJm +(Utility) 26.0234 Tj +-250 TJm +(functions) 37.0823 Tj +[1 0 0 1 179.536 280.403] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -184.517 -280.403] cm +[1 0 0 1 0 0] Tm +0 0 Td +193.67 280.403 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 280.403] cm +0 g +0 G +[1 0 0 1 -506.127 -280.403] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 280.403 Td +/F128_0 9.963 Tf +(26) 9.963 Tj +[1 0 0 1 516.09 280.403] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -9.798] cm +0 g +0 G +[1 0 0 1 -119.821 -268.448] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 268.448 Td +/F128_0 9.963 Tf +(3.5.1.) 22.4168 Tj +-310 TJm +(BZ2_bzBuf) 47.0453 Tj +25 TJm +(fT) 9.40507 Tj +80 TJm +(oBuf) 19.926 Tj +25 TJm +(fCom) 22.6957 Tj +1 TJm +(press) 20.474 Tj +[1 0 0 1 263.571 268.448] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -268.552 -268.448] cm +[1 0 0 1 0 0] Tm +0 0 Td +277.751 268.448 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 268.448] cm +0 g +0 G +[1 0 0 1 -506.127 -268.448] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 268.448 Td +/F128_0 9.963 Tf +(26) 9.963 Tj +[1 0 0 1 516.09 268.448] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -9.799] cm +0 g +0 G +[1 0 0 1 -119.821 -256.492] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 256.492 Td +/F128_0 9.963 Tf +(3.5.2.) 22.4168 Tj +-310 TJm +(BZ2_bzBuf) 47.0453 Tj +25 TJm +(fT) 9.40507 Tj +80 TJm +(oBuf) 19.926 Tj +25 TJm +(fDeco) 24.3396 Tj +1 TJm +(mpress) 28.2252 Tj +[1 0 0 1 272.965 256.492] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -277.947 -256.492] cm +[1 0 0 1 0 0] Tm +0 0 Td +286.876 256.492 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 256.492] cm +0 g +0 G +[1 0 0 1 -506.127 -256.492] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 256.492 Td +/F128_0 9.963 Tf +(27) 9.963 Tj +[1 0 0 1 516.09 256.492] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.156] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 23.91 -9.799] cm +0 g +0 G +[1 0 0 1 -95.91 -244.537] cm +[1 0 0 1 0 0] Tm +0 0 Td +95.91 244.537 Td +/F128_0 9.963 Tf +(3.6.) 14.9445 Tj +-310 TJm +(zlib) 14.9445 Tj +-250 TJm +(compatibility) 53.1426 Tj +-250 TJm +(functio) 28.2252 Tj +1 TJm +(ns) 8.85711 Tj +[1 0 0 1 224.088 244.537] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -229.069 -244.537] cm +[1 0 0 1 0 0] Tm +0 0 Td +238.085 244.537 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 244.537] cm +0 g +0 G +[1 0 0 1 -506.127 -244.537] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 244.537 Td +/F128_0 9.963 Tf +(28) 9.963 Tj +[1 0 0 1 516.09 244.537] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 23.91 -9.798] cm +0 g +0 G +[1 0 0 1 -95.91 -232.582] cm +[1 0 0 1 0 0] Tm +0 0 Td +95.91 232.582 Td +/F128_0 9.963 Tf +(3.7.) 14.9445 Tj +-310 TJm +(Using) 23.8016 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(library) 26.5614 Tj +-250 TJm +(in) 7.75121 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(stdio) 19.378 Tj +1 TJm +(-free) 18.8002 Tj +-250 TJm +(en) 9.40507 Tj +40 TJm +(vironment) 40.9579 Tj +[1 0 0 1 291.734 232.582] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -296.715 -232.582] cm +[1 0 0 1 0 0] Tm +0 0 Td +305.116 232.582 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 232.582] cm +0 g +0 G +[1 0 0 1 -506.127 -232.582] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 232.582 Td +/F128_0 9.963 Tf +(28) 9.963 Tj +[1 0 0 1 516.09 232.582] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -9.798] cm +0 g +0 G +[1 0 0 1 -119.821 -220.627] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 220.627 Td +/F128_0 9.963 Tf +(3.7.1.) 22.4168 Tj +-310 TJm +(Getting) 29.889 Tj +-250 TJm +(rid) 11.0689 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(stdio) 19.378 Tj +[1 0 0 1 221.429 220.627] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -226.41 -220.627] cm +[1 0 0 1 0 0] Tm +0 0 Td +236.755 220.627 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 220.627] cm +0 g +0 G +[1 0 0 1 -506.127 -220.627] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 220.627 Td +/F128_0 9.963 Tf +(29) 9.963 Tj +[1 0 0 1 516.09 220.627] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -9.798] cm +0 g +0 G +[1 0 0 1 -119.821 -208.672] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 208.672 Td +/F128_0 9.963 Tf +(3.7.2.) 22.4168 Tj +-310 TJm +(Critical) 29.889 Tj +-250 TJm +(error) 19.3581 Tj +-250 TJm +(handlin) 29.889 Tj +1 TJm +(g) 4.9815 Tj +[1 0 0 1 234.42 208.672] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -239.401 -208.672] cm +[1 0 0 1 0 0] Tm +0 0 Td +249.892 208.672 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 208.672] cm +0 g +0 G +[1 0 0 1 -506.127 -208.672] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 208.672 Td +/F128_0 9.963 Tf +(29) 9.963 Tj +[1 0 0 1 516.09 208.672] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 23.91 -9.798] cm +0 g +0 G +[1 0 0 1 -95.91 -196.717] cm +[1 0 0 1 0 0] Tm +0 0 Td +95.91 196.717 Td +/F128_0 9.963 Tf +(3.8.) 14.9445 Tj +-310 TJm +(Making) 30.9949 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(W) 9.40507 Tj +40 TJm +(indo) 17.7142 Tj +25 TJm +(ws) 11.0689 Tj +-250 TJm +(DLL) 19.3681 Tj +[1 0 0 1 213.738 196.717] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -218.719 -196.717] cm +[1 0 0 1 0 0] Tm +0 0 Td +228.482 196.717 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 196.717] cm +0 g +0 G +[1 0 0 1 -506.127 -196.717] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 196.717 Td +/F128_0 9.963 Tf +(29) 9.963 Tj +[1 0 0 1 516.09 196.717] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.799] cm +0 g +0 G +[1 0 0 1 -72 -184.761] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 184.761 Td +/F128_0 9.963 Tf +(4.) 7.47225 Tj +-310 TJm +(Miscellanea) 48.1412 Tj +[1 0 0 1 130.699 184.761] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -135.68 -184.761] cm +[1 0 0 1 0 0] Tm +0 0 Td +144.898 184.761 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 184.761] cm +0 g +0 G +[1 0 0 1 -506.127 -184.761] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 184.761 Td +/F128_0 9.963 Tf +(31) 9.963 Tj +[1 0 0 1 516.09 184.761] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -0.099] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 23.91 -11.856] cm +0 g +0 G +[1 0 0 1 -95.91 -172.806] cm +[1 0 0 1 0 0] Tm +0 0 Td +95.91 172.806 Td +/F128_0 9.963 Tf +(4.1.) 14.9445 Tj +-310 TJm +(Limitations) 45.9494 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(compre) 29.879 Tj +1 TJm +(ssed) 17.1563 Tj +-250 TJm +(\002le) 12.7327 Tj +-250 TJm +(format) 26.5614 Tj +[1 0 0 1 279.141 172.806] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -284.122 -172.806] cm +[1 0 0 1 0 0] Tm +0 0 Td +294.392 172.806 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 172.806] cm +0 g +0 G +[1 0 0 1 -506.127 -172.806] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 172.806 Td +/F128_0 9.963 Tf +(31) 9.963 Tj +[1 0 0 1 516.09 172.806] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 23.91 -9.798] cm +0 g +0 G +[1 0 0 1 -95.91 -160.851] cm +[1 0 0 1 0 0] Tm +0 0 Td +95.91 160.851 Td +/F128_0 9.963 Tf +(4.2.) 14.9445 Tj +-310 TJm +(Portability) 42.0737 Tj +-250 TJm +(issues) 23.8016 Tj +[1 0 0 1 182.305 160.851] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -187.286 -160.851] cm +[1 0 0 1 0 0] Tm +0 0 Td +197.268 160.851 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 160.851] cm +0 g +0 G +[1 0 0 1 -506.127 -160.851] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 160.851 Td +/F128_0 9.963 Tf +(32) 9.963 Tj +[1 0 0 1 516.09 160.851] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 23.91 -9.798] cm +0 g +0 G +[1 0 0 1 -95.91 -148.896] cm +[1 0 0 1 0 0] Tm +0 0 Td +95.91 148.896 Td +/F128_0 9.963 Tf +(4.3.) 14.9445 Tj +-310 TJm +(Reporting) 39.852 Tj +-250 TJm +(b) 4.9815 Tj +20 TJm +(ugs) 13.8386 Tj +[1 0 0 1 174.904 148.896] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -179.885 -148.896] cm +[1 0 0 1 0 0] Tm +0 0 Td +189.14 148.896 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 148.896] cm +0 g +0 G +[1 0 0 1 -506.127 -148.896] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 148.896 Td +/F128_0 9.963 Tf +(32) 9.963 Tj +[1 0 0 1 516.09 148.896] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 23.91 -9.798] cm +0 g +0 G +[1 0 0 1 -95.91 -136.941] cm +[1 0 0 1 0 0] Tm +0 0 Td +95.91 136.941 Td +/F128_0 9.963 Tf +(4.4.) 14.9445 Tj +-310 TJm +(Did) 14.9445 Tj +-250 TJm +(you) 14.9445 Tj +-250 TJm +(get) 12.1748 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(right) 18.8201 Tj +-250 TJm +(packag) 28.2152 Tj +1 TJm +(e?) 8.84714 Tj +[1 0 0 1 236.512 136.941] cm +0 g +0 G +[1 0 0 1 3.088 0] cm +0 g +0 G +[1 0 0 1 3.089 0] cm +0 g +0 G +[1 0 0 1 -242.689 -136.941] cm +[1 0 0 1 0 0] Tm +0 0 Td +254.348 136.941 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 136.941] cm +0 g +0 G +[1 0 0 1 -506.127 -136.941] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 136.941 Td +/F128_0 9.963 Tf +(33) 9.963 Tj +[1 0 0 1 516.09 136.941] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 23.91 -9.798] cm +0 g +0 G +[1 0 0 1 -95.91 -124.986] cm +[1 0 0 1 0 0] Tm +0 0 Td +95.91 124.986 Td +/F128_0 9.963 Tf +(4.5.) 14.9445 Tj +-310 TJm +(Further) 29.3311 Tj +-250 TJm +(Reading) 33.2067 Tj +[1 0 0 1 178.968 124.986] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -183.95 -124.986] cm +[1 0 0 1 0 0] Tm +0 0 Td +193.386 124.986 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 124.986] cm +0 g +0 G +[1 0 0 1 -506.127 -124.986] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 124.986 Td +/F128_0 9.963 Tf +(34) 9.963 Tj +[1 0 0 1 516.09 124.986] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 0 -62.014] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.754] cm +0 g +0 G +0 g +0 G +[1 0 0 1 41.399 -6.754] cm +0 g +0 G +[1 0 0 1 -494.668 -50.852] cm +[1 0 0 1 0 0] Tm +0 0 Td +536.068 50.852 Td +/F128_0 9.963 Tf +(iii) 8.30914 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 4 4 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 140.398 0] cm +0 g +0 G +[1 0 0 1 -140.398 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -13.948] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -468 -21.554] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -720] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 701.916 Td +/F121_0 24.79 Tf +(1.) 20.6749 Tj +-278 TJm +(Intr) 39.9367 Tj +20 TJm +(oduction) 104.663 Tj +[1 0 0 1 72 701.606] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -691.643] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 679.998 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 101.888 679.998] cm +0 g +0 G +[1 0 0 1 -101.888 -679.998] cm +[1 0 0 1 0 0] Tm +0 0 Td +104.507 679.998 Td +/F128_0 9.963 Tf +(compresses) 45.9294 Tj +-263 TJm +(\002les) 16.6083 Tj +-262 TJm +(using) 21.5898 Tj +-263 TJm +(the) 12.1748 Tj +-263 TJm +(Burro) 23.2437 Tj +25 TJm +(ws-Wheeler) 48.1313 Tj +-263 TJm +(block-sor) 37.6303 Tj +1 TJm +(ting) 15.5024 Tj +-263 TJm +(te) 7.19329 Tj +15 TJm +(xt) 7.75121 Tj +-263 TJm +(compression) 50.363 Tj +-263 TJm +(algorithm,) 41.2369 Tj +-266 TJm +(and) 14.3866 Tj +-263 TJm +(H) 7.19329 Tj +1 TJm +(uf) 8.29918 Tj +25 TJm +(fman) 20.474 Tj +-263 TJm +(coding.) 29.61 Tj +72 668.043 Td +(Compression) 52.5847 Tj +-203 TJm +(is) 6.64532 Tj +-203 TJm +(generally) 37.0723 Tj +-204 TJm +(c) 4.42357 Tj +1 TJm +(onsiderably) 46.4874 Tj +-204 TJm +(better) 22.6858 Tj +-203 TJm +(than) 17.1563 Tj +-203 TJm +(that) 14.9445 Tj +-203 TJm +(achie) 21.0219 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(ed) 9.40507 Tj +-203 TJm +(by) 9.963 Tj +-204 TJm +(more) 20.474 Tj +-203 TJm +(con) 14.3866 Tj +40 TJm +(v) 4.9815 Tj +15 TJm +(entional) 32.1008 Tj +-203 TJm +(LZ77/LZ78-based) 73.0487 Tj +-203 TJm +(compressors,) 52.2958 Tj +72 656.087 Td +(and) 14.3866 Tj +-250 TJm +(approaches) 44.8136 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(performan) 41.4959 Tj +1 TJm +(ce) 8.84714 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(PPM) 19.936 Tj +-250 TJm +(f) 3.31768 Tj +10 TJm +(amily) 22.6957 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(statistical) 37.6402 Tj +-250 TJm +(compressors.) 52.2958 Tj +[1 0 0 1 72 653.931] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -643.968] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 634.17 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 101.888 634.17] cm +0 g +0 G +[1 0 0 1 -101.888 -634.17] cm +[1 0 0 1 0 0] Tm +0 0 Td +105.074 634.17 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-320 TJm +(b) 4.9815 Tj +20 TJm +(uilt) 13.2906 Tj +-319 TJm +(on) 9.963 Tj +-320 TJm +(top) 12.7327 Tj +-320 TJm +(of) 8.29918 Tj +[1 0 0 1 176.712 634.17] cm +0 g +0 G +[1 0 0 1 -176.712 -634.17] cm +[1 0 0 1 0 0] Tm +0 0 Td +176.712 634.17 Td +/F130_0 9.963 Tf +(libbzip2) 47.8224 Tj +[1 0 0 1 224.533 634.17] cm +0 g +0 G +[1 0 0 1 -224.533 -634.17] cm +[1 0 0 1 0 0] Tm +0 0 Td +224.533 634.17 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-337 TJm +(a) 4.42357 Tj +-320 TJm +(\003e) 9.963 Tj +15 TJm +(xible) 19.926 Tj +-319 TJm +(library) 26.5614 Tj +-320 TJm +(for) 11.6169 Tj +-320 TJm +(handling) 34.8705 Tj +-319 TJm +(compressed) 47.0353 Tj +-320 TJm +(data) 16.5984 Tj +-320 TJm +(in) 7.75121 Tj +-319 TJm +(the) 12.1748 Tj +[1 0 0 1 449.816 634.17] cm +0 g +0 G +[1 0 0 1 -449.816 -634.17] cm +[1 0 0 1 0 0] Tm +0 0 Td +449.816 634.17 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 479.704 634.17] cm +0 g +0 G +[1 0 0 1 -479.704 -634.17] cm +[1 0 0 1 0 0] Tm +0 0 Td +482.889 634.17 Td +/F128_0 9.963 Tf +(format.) 29.0521 Tj +-1038 TJm +(This) 17.7142 Tj +72 622.214 Td +(manual) 29.3311 Tj +-316 TJm +(describes) 37.0723 Tj +-316 TJm +(both) 17.7142 Tj +-316 TJm +(ho) 9.963 Tj +25 TJm +(w) 7.19329 Tj +-316 TJm +(to) 7.75121 Tj +-316 TJm +(use) 13.2807 Tj +-317 TJm +(the) 12.1748 Tj +-316 TJm +(program) 33.7546 Tj +-316 TJm +(and) 14.3866 Tj +-316 TJm +(ho) 9.963 Tj +25 TJm +(w) 7.19329 Tj +-316 TJm +(to) 7.75121 Tj +-316 TJm +(w) 7.19329 Tj +10 TJm +(ork) 13.2807 Tj +-316 TJm +(with) 17.7142 Tj +-316 TJm +(the) 12.1748 Tj +-316 TJm +(library) 26.5614 Tj +-317 TJm +(int) 10.5209 Tj +1 TJm +(erf) 11.0589 Tj +10 TJm +(ace.) 15.7615 Tj +-1018 TJm +(M) 8.85711 Tj +1 TJm +(ost) 11.6268 Tj +-317 TJm +(of) 8.29918 Tj +-316 TJm +(the) 12.1748 Tj +-316 TJm +(manual) 29.3311 Tj +-316 TJm +(is) 6.64532 Tj +72 610.259 Td +(de) 9.40507 Tj +25 TJm +(v) 4.9815 Tj +20 TJm +(oted) 17.1563 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(this) 14.3965 Tj +-250 TJm +(library) 26.5614 Tj +65 TJm +(,) 2.49075 Tj +-250 TJm +(not) 12.7327 Tj +-250 TJm +(the) 12.1748 Tj +-249 TJm +(program,) 36.2454 Tj +-250 TJm +(which) 24.3496 Tj +-250 TJm +(is) 6.64532 Tj +-250 TJm +(good) 19.926 Tj +-250 TJm +(ne) 9.40507 Tj +25 TJm +(ws) 11.0689 Tj +-250 TJm +(if) 6.08739 Tj +-250 TJm +(your) 18.2622 Tj +-250 TJm +(interest) 29.3311 Tj +-250 TJm +(is) 6.64532 Tj +-250 TJm +(only) 17.7142 Tj +-250 TJm +(in) 7.75121 Tj +-250 TJm +(th) 7.75121 Tj +1 TJm +(e) 4.42357 Tj +-250 TJm +(program.) 36.2454 Tj +[1 0 0 1 72 608.102] cm +0 g +0 G +[1 0 0 1 0 -29.723] cm +0 g +0 G +[1 0 0 1 6.974 0] cm +0 g +0 G +[1 0 0 1 -78.974 -578.379] cm +[1 0 0 1 0 0] Tm +0 0 Td +78.974 578.379 Td +/F128_0 9.963 Tf +(\225) 3.48705 Tj +[1 0 0 1 82.461 578.379] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 1.993 0] cm +0 g +0 G +0 0 1 rg +0 0 1 RG +[1 0 0 1 -86.944 -578.379] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 578.379 Td +/F128_0 9.963 Tf +(Ho) 12.1748 Tj +25 TJm +(w) 7.19329 Tj +-259 TJm +(to) 7.75121 Tj +-260 TJm +(use) 13.2807 Tj +-259 TJm +(bzip2) 22.1378 Tj +[1 0 0 1 156.985 578.379] cm +0 g +0 G +0 0 1 rg +0 0 1 RG +0 0 1 rg +0 0 1 RG +[1 0 0 1 -156.985 -578.379] cm +[1 0 0 1 0 0] Tm +0 0 Td +159.57 578.379 Td +/F128_0 9.963 Tf +([2]) 11.6169 Tj +[1 0 0 1 171.186 578.379] cm +0 0 1 rg +0 0 1 RG +0 g +0 G +[1 0 0 1 -171.186 -578.379] cm +[1 0 0 1 0 0] Tm +0 0 Td +173.771 578.379 Td +/F128_0 9.963 Tf +(describes) 37.0723 Tj +-259 TJm +(ho) 9.963 Tj +25 TJm +(w) 7.19329 Tj +-260 TJm +(to) 7.75121 Tj +-259 TJm +(use) 13.2807 Tj +[1 0 0 1 259.119 578.379] cm +0 g +0 G +[1 0 0 1 -259.119 -578.379] cm +[1 0 0 1 0 0] Tm +0 0 Td +259.119 578.379 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 289.007 578.379] cm +0 g +0 G +[1 0 0 1 -289.007 -578.379] cm +[1 0 0 1 0 0] Tm +0 0 Td +289.007 578.379 Td +/F128_0 9.963 Tf +(;) 2.76971 Tj +-264 TJm +(this) 14.3965 Tj +-260 TJm +(i) 2.76971 Tj +1 TJm +(s) 3.87561 Tj +-260 TJm +(the) 12.1748 Tj +-259 TJm +(only) 17.7142 Tj +-260 TJm +(part) 15.4925 Tj +-259 TJm +(you) 14.9445 Tj +-259 TJm +(need) 18.8101 Tj +-260 TJm +(to) 7.75121 Tj +-259 TJm +(read) 17.1463 Tj +-260 TJm +(if) 6.08739 Tj +-259 TJm +(you) 14.9445 Tj +-259 TJm +(just) 14.3965 Tj +-260 TJm +(w) 7.19329 Tj +10 TJm +(ant) 12.1748 Tj +-259 TJm +(to) 7.75121 Tj +-260 TJm +(kno) 14.9445 Tj +25 TJm +(w) 7.19329 Tj +86.944 566.424 Td +(ho) 9.963 Tj +25 TJm +(w) 7.19329 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(operate) 29.3211 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(program.) 36.2454 Tj +[1 0 0 1 199.302 566.424] cm +0 g +0 G +[1 0 0 1 -127.302 -21.918] cm +0 g +0 G +[1 0 0 1 6.974 0] cm +0 g +0 G +[1 0 0 1 -78.974 -544.506] cm +[1 0 0 1 0 0] Tm +0 0 Td +78.974 544.506 Td +/F128_0 9.963 Tf +(\225) 3.48705 Tj +[1 0 0 1 82.461 544.506] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 1.993 0] cm +0 g +0 G +0 0 1 rg +0 0 1 RG +[1 0 0 1 -86.944 -544.506] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 544.506 Td +/F128_0 9.963 Tf +(Programming) 54.7965 Tj +-250 TJm +(with) 17.7142 Tj +-250 TJm +(libbzip2) 32.6587 Tj +[1 0 0 1 197.09 544.506] cm +0 g +0 G +0 0 1 rg +0 0 1 RG +0 0 1 rg +0 0 1 RG +[1 0 0 1 -197.09 -544.506] cm +[1 0 0 1 0 0] Tm +0 0 Td +199.58 544.506 Td +/F128_0 9.963 Tf +([8]) 11.6169 Tj +[1 0 0 1 211.197 544.506] cm +0 0 1 rg +0 0 1 RG +0 g +0 G +[1 0 0 1 -211.197 -544.506] cm +[1 0 0 1 0 0] Tm +0 0 Td +213.687 544.506 Td +/F128_0 9.963 Tf +(describes) 37.0723 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(programming) 54.2386 Tj +-250 TJm +(int) 10.5209 Tj +1 TJm +(erf) 11.0589 Tj +10 TJm +(aces) 17.1463 Tj +-250 TJm +(in) 7.75121 Tj +-250 TJm +(detail,) 24.6285 Tj +-250 TJm +(and) 14.3866 Tj +[1 0 0 1 417.501 544.506] cm +0 g +0 G +[1 0 0 1 -345.501 -21.918] cm +0 g +0 G +[1 0 0 1 6.974 0] cm +0 g +0 G +[1 0 0 1 -78.974 -522.588] cm +[1 0 0 1 0 0] Tm +0 0 Td +78.974 522.588 Td +/F128_0 9.963 Tf +(\225) 3.48705 Tj +[1 0 0 1 82.461 522.588] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 1.993 0] cm +0 g +0 G +0 0 1 rg +0 0 1 RG +[1 0 0 1 -86.944 -522.588] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 522.588 Td +/F128_0 9.963 Tf +(Miscellanea) 48.1412 Tj +[1 0 0 1 135.083 522.588] cm +0 g +0 G +0 0 1 rg +0 0 1 RG +0 0 1 rg +0 0 1 RG +[1 0 0 1 -135.083 -522.588] cm +[1 0 0 1 0 0] Tm +0 0 Td +137.573 522.588 Td +/F128_0 9.963 Tf +([31]) 16.5984 Tj +[1 0 0 1 154.171 522.588] cm +0 0 1 rg +0 0 1 RG +0 g +0 G +[1 0 0 1 -154.171 -522.588] cm +[1 0 0 1 0 0] Tm +0 0 Td +156.662 522.588 Td +/F128_0 9.963 Tf +(records) 29.3211 Tj +-250 TJm +(some) 21.0319 Tj +-250 TJm +(miscellane) 42.6118 Tj +1 TJm +(ous) 13.8386 Tj +-250 TJm +(notes) 21.0319 Tj +-250 TJm +(which) 24.3496 Tj +-250 TJm +(I) 3.31768 Tj +-250 TJm +(thought) 30.4469 Tj +-250 TJm +(ought) 22.6957 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(be) 9.40507 Tj +-250 TJm +(recorded) 34.8506 Tj +-250 TJm +(some) 21.0319 Tj +25 TJm +(where.) 26.8304 Tj +[1 0 0 1 492.31 522.588] cm +0 g +0 G +[1 0 0 1 -420.31 -471.736] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.754] cm +0 g +0 G +0 g +0 G +[1 0 0 1 43.063 -6.754] cm +0 g +0 G +[1 0 0 1 -496.332 -50.852] cm +[1 0 0 1 0 0] Tm +0 0 Td +539.395 50.852 Td +/F128_0 9.963 Tf +(1) 4.9815 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 5 5 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 140.398 0] cm +0 g +0 G +[1 0 0 1 -140.398 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -13.948] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -468 -21.554] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -720] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 701.916 Td +/F121_0 24.79 Tf +(2.) 20.6749 Tj +-278 TJm +(Ho) 33.0451 Tj +15 TJm +(w) 19.2866 Tj +-278 TJm +(to) 23.4018 Tj +-278 TJm +(use) 42.7132 Tj +-278 TJm +(bzip2) 63.3632 Tj +[1 0 0 1 72 696.784] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -14.944] cm +0 g +0 G +[1 0 0 1 -72 -671.877] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 656.35 Td +/F121_0 17.215 Tf +(T) 10.5184 Tj +80 TJm +(ab) 20.0899 Tj +10 TJm +(le) 14.3573 Tj +-278 TJm +(of) 16.251 Tj +-278 TJm +(Contents) 74.5926 Tj +[1 0 0 1 72 647.528] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -11.74] cm +0 g +0 G +[1 0 0 1 -72 -635.788] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 635.788 Td +/F128_0 9.963 Tf +(2.1.) 14.9445 Tj +-310 TJm +(N) 7.19329 Tj +35 TJm +(AME) 22.1378 Tj +[1 0 0 1 119.013 635.788] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -123.995 -635.788] cm +[1 0 0 1 0 0] Tm +0 0 Td +132.691 635.788 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 511.108 635.788] cm +0 g +0 G +[1 0 0 1 -511.108 -635.788] cm +[1 0 0 1 0 0] Tm +0 0 Td +511.108 635.788 Td +/F128_0 9.963 Tf +(2) 4.9815 Tj +[1 0 0 1 516.09 635.788] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -0.1] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -11.856] cm +0 g +0 G +[1 0 0 1 -72 -623.832] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 623.832 Td +/F128_0 9.963 Tf +(2.2.) 14.9445 Tj +-310 TJm +(SYNOPSIS) 47.0552 Tj +[1 0 0 1 137.086 623.832] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -142.067 -623.832] cm +[1 0 0 1 0 0] Tm +0 0 Td +150.582 623.832 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 511.108 623.832] cm +0 g +0 G +[1 0 0 1 -511.108 -623.832] cm +[1 0 0 1 0 0] Tm +0 0 Td +511.108 623.832 Td +/F128_0 9.963 Tf +(2) 4.9815 Tj +[1 0 0 1 516.09 623.832] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -0.099] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -11.856] cm +0 g +0 G +[1 0 0 1 -72 -611.877] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 611.877 Td +/F128_0 9.963 Tf +(2.3.) 14.9445 Tj +-310 TJm +(DESCRIPTION) 64.7595 Tj +[1 0 0 1 154.789 611.877] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -159.77 -611.877] cm +[1 0 0 1 0 0] Tm +0 0 Td +168.29 611.877 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 511.108 611.877] cm +0 g +0 G +[1 0 0 1 -511.108 -611.877] cm +[1 0 0 1 0 0] Tm +0 0 Td +511.108 611.877 Td +/F128_0 9.963 Tf +(3) 4.9815 Tj +[1 0 0 1 516.09 611.877] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -0.099] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -11.856] cm +0 g +0 G +[1 0 0 1 -72 -599.922] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 599.922 Td +/F128_0 9.963 Tf +(2.4.) 14.9445 Tj +-310 TJm +(OPTIONS) 42.0638 Tj +[1 0 0 1 132.094 599.922] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -137.076 -599.922] cm +[1 0 0 1 0 0] Tm +0 0 Td +145.873 599.922 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 511.108 599.922] cm +0 g +0 G +[1 0 0 1 -511.108 -599.922] cm +[1 0 0 1 0 0] Tm +0 0 Td +511.108 599.922 Td +/F128_0 9.963 Tf +(4) 4.9815 Tj +[1 0 0 1 516.09 599.922] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -0.1] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -11.855] cm +0 g +0 G +[1 0 0 1 -72 -587.967] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 587.967 Td +/F128_0 9.963 Tf +(2.5.) 14.9445 Tj +-310 TJm +(MEMOR) 37.6402 Tj +65 TJm +(Y) 7.19329 Tj +-250 TJm +(MAN) 23.2437 Tj +35 TJm +(A) 7.19329 Tj +40 TJm +(GEMENT) 41.5059 Tj +[1 0 0 1 207.9 587.967] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -212.881 -587.967] cm +[1 0 0 1 0 0] Tm +0 0 Td +221.412 587.967 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 511.108 587.967] cm +0 g +0 G +[1 0 0 1 -511.108 -587.967] cm +[1 0 0 1 0 0] Tm +0 0 Td +511.108 587.967 Td +/F128_0 9.963 Tf +(5) 4.9815 Tj +[1 0 0 1 516.09 587.967] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -0.1] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -11.855] cm +0 g +0 G +[1 0 0 1 -72 -576.012] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 576.012 Td +/F128_0 9.963 Tf +(2.6.) 14.9445 Tj +-310 TJm +(RECO) 26.5713 Tj +50 TJm +(VERING) 37.6303 Tj +-250 TJm +(D) 7.19329 Tj +40 TJm +(A) 7.19329 Tj +111 TJm +(T) 6.08739 Tj +93 TJm +(A) 7.19329 Tj +-250 TJm +(FR) 12.1847 Tj +40 TJm +(OM) 16.0504 Tj +-249 TJm +(D) 7.19329 Tj +40 TJm +(AMA) 23.2437 Tj +40 TJm +(GED) 20.474 Tj +-250 TJm +(FILES) 26.5713 Tj +[1 0 0 1 293.449 576.012] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -298.43 -576.012] cm +[1 0 0 1 0 0] Tm +0 0 Td +308.464 576.012 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 511.108 576.012] cm +0 g +0 G +[1 0 0 1 -511.108 -576.012] cm +[1 0 0 1 0 0] Tm +0 0 Td +511.108 576.012 Td +/F128_0 9.963 Tf +(6) 4.9815 Tj +[1 0 0 1 516.09 576.012] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -0.1] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -11.855] cm +0 g +0 G +[1 0 0 1 -72 -564.057] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 564.057 Td +/F128_0 9.963 Tf +(2.7.) 14.9445 Tj +-310 TJm +(PERFORMANCE) 73.6266 Tj +-250 TJm +(NO) 14.3866 Tj +40 TJm +(TES) 17.7142 Tj +[1 0 0 1 197.847 564.057] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -202.829 -564.057] cm +[1 0 0 1 0 0] Tm +0 0 Td +211.958 564.057 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 511.108 564.057] cm +0 g +0 G +[1 0 0 1 -511.108 -564.057] cm +[1 0 0 1 0 0] Tm +0 0 Td +511.108 564.057 Td +/F128_0 9.963 Tf +(6) 4.9815 Tj +[1 0 0 1 516.09 564.057] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -0.1] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -11.856] cm +0 g +0 G +[1 0 0 1 -72 -552.101] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 552.101 Td +/F128_0 9.963 Tf +(2.8.) 14.9445 Tj +-310 TJm +(CA) 13.8386 Tj +135 TJm +(VEA) 20.474 Tj +111 TJm +(TS) 11.6268 Tj +[1 0 0 1 133.519 552.101] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -138.5 -552.101] cm +[1 0 0 1 0 0] Tm +0 0 Td +148.799 552.101 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 511.108 552.101] cm +0 g +0 G +[1 0 0 1 -511.108 -552.101] cm +[1 0 0 1 0 0] Tm +0 0 Td +511.108 552.101 Td +/F128_0 9.963 Tf +(7) 4.9815 Tj +[1 0 0 1 516.09 552.101] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -0.099] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -11.856] cm +0 g +0 G +[1 0 0 1 -72 -540.146] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 540.146 Td +/F128_0 9.963 Tf +(2.9.) 14.9445 Tj +-310 TJm +(A) 7.19329 Tj +55 TJm +(UTHOR) 34.3126 Tj +[1 0 0 1 130.989 540.146] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -135.97 -540.146] cm +[1 0 0 1 0 0] Tm +0 0 Td +145.32 540.146 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 511.108 540.146] cm +0 g +0 G +[1 0 0 1 -511.108 -540.146] cm +[1 0 0 1 0 0] Tm +0 0 Td +511.108 540.146 Td +/F128_0 9.963 Tf +(7) 4.9815 Tj +[1 0 0 1 516.09 540.146] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -0.219] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -520.002] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 508.266 Td +/F128_0 9.963 Tf +(This) 17.7142 Tj +-250 TJm +(chapter) 29.3211 Tj +-250 TJm +(contains) 33.2067 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(cop) 14.3866 Tj +10 TJm +(y) 4.9815 Tj +-249 TJm +(of) 8.29918 Tj +-250 TJm +(the) 12.1748 Tj +[1 0 0 1 213.837 508.266] cm +0 g +0 G +[1 0 0 1 -213.837 -508.266] cm +[1 0 0 1 0 0] Tm +0 0 Td +213.837 508.266 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 243.725 508.266] cm +0 g +0 G +[1 0 0 1 -243.725 -508.266] cm +[1 0 0 1 0 0] Tm +0 0 Td +246.215 508.266 Td +/F128_0 9.963 Tf +(man) 17.1563 Tj +-250 TJm +(page,) 21.3009 Tj +-250 TJm +(and) 14.3866 Tj +-250 TJm +(nothing) 30.4469 Tj +-250 TJm +(else.) 17.9832 Tj +[1 0 0 1 72 506.109] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -496.146] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 473.513 Td +/F121_0 20.659 Tf +(2.1.) 34.4592 Tj +-278 TJm +(NAME) 60.8201 Tj +[1 0 0 1 72 473.513] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -31.881] cm +0 g +0 G +[1 0 0 1 6.974 0] cm +0 g +0 G +[1 0 0 1 -78.974 -441.632] cm +[1 0 0 1 0 0] Tm +0 0 Td +78.974 441.632 Td +/F128_0 9.963 Tf +(\225) 3.48705 Tj +[1 0 0 1 82.461 441.632] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 1.993 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -86.944 -441.632] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 441.632 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 116.832 441.632] cm +0 g +0 G +[1 0 0 1 -116.832 -441.632] cm +[1 0 0 1 0 0] Tm +0 0 Td +116.832 441.632 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 121.813 441.632] cm +0 g +0 G +[1 0 0 1 -121.813 -441.632] cm +[1 0 0 1 0 0] Tm +0 0 Td +121.813 441.632 Td +/F130_0 9.963 Tf +(bunzip2) 41.8446 Tj +[1 0 0 1 163.656 441.632] cm +0 g +0 G +[1 0 0 1 -163.656 -441.632] cm +[1 0 0 1 0 0] Tm +0 0 Td +166.147 441.632 Td +/F128_0 9.963 Tf +(-) 3.31768 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(block-sorting) 53.1327 Tj +-250 TJm +(\002le) 12.7327 Tj +-250 TJm +(compre) 29.879 Tj +1 TJm +(ssor) 16.0504 Tj +40 TJm +(,) 2.49075 Tj +-250 TJm +(v1.0.3) 24.9075 Tj +[1 0 0 1 325.129 441.632] cm +0 g +0 G +[1 0 0 1 -253.129 -21.917] cm +0 g +0 G +[1 0 0 1 6.974 0] cm +0 g +0 G +[1 0 0 1 -78.974 -419.715] cm +[1 0 0 1 0 0] Tm +0 0 Td +78.974 419.715 Td +/F128_0 9.963 Tf +(\225) 3.48705 Tj +[1 0 0 1 82.461 419.715] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 1.993 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -86.944 -419.715] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 419.715 Td +/F130_0 9.963 Tf +(bzcat) 29.889 Tj +[1 0 0 1 116.832 419.715] cm +0 g +0 G +[1 0 0 1 -116.832 -419.715] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.323 419.715 Td +/F128_0 9.963 Tf +(-) 3.31768 Tj +-250 TJm +(decompresses) 55.3345 Tj +-250 TJm +(\002les) 16.6083 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(st) 6.64532 Tj +1 TJm +(dout) 17.7142 Tj +[1 0 0 1 236.651 419.715] cm +0 g +0 G +[1 0 0 1 -164.651 -21.918] cm +0 g +0 G +[1 0 0 1 6.974 0] cm +0 g +0 G +[1 0 0 1 -78.974 -397.797] cm +[1 0 0 1 0 0] Tm +0 0 Td +78.974 397.797 Td +/F128_0 9.963 Tf +(\225) 3.48705 Tj +[1 0 0 1 82.461 397.797] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 1.993 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -86.944 -397.797] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 397.797 Td +/F130_0 9.963 Tf +(bzip2recover) 71.7336 Tj +[1 0 0 1 158.675 397.797] cm +0 g +0 G +[1 0 0 1 -158.675 -397.797] cm +[1 0 0 1 0 0] Tm +0 0 Td +161.166 397.797 Td +/F128_0 9.963 Tf +(-) 3.31768 Tj +-250 TJm +(reco) 17.1463 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(ers) 11.6169 Tj +-250 TJm +(data) 16.5984 Tj +-250 TJm +(from) 19.3681 Tj +-250 TJm +(damage) 30.9849 Tj +1 TJm +(d) 4.9815 Tj +-250 TJm +(bzip2) 22.1378 Tj +-250 TJm +(\002les) 16.6083 Tj +[1 0 0 1 323.545 397.797] cm +0 g +0 G +[1 0 0 1 -251.545 -12.12] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -375.715] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 353.081 Td +/F121_0 20.659 Tf +(2.2.) 34.4592 Tj +-278 TJm +(SYNOPSIS) 105.629 Tj +[1 0 0 1 72 352.823] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -31.622] cm +0 g +0 G +[1 0 0 1 6.974 0] cm +0 g +0 G +[1 0 0 1 -78.974 -321.201] cm +[1 0 0 1 0 0] Tm +0 0 Td +78.974 321.201 Td +/F128_0 9.963 Tf +(\225) 3.48705 Tj +[1 0 0 1 82.461 321.201] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 1.993 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -86.944 -321.201] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 321.201 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 116.832 321.201] cm +0 g +0 G +[1 0 0 1 -116.832 -321.201] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.323 321.201 Td +/F128_0 9.963 Tf +([) 3.31768 Tj +-250 TJm +(-cdfkqstvzVL123456789) 100.168 Tj +-250 TJm +(]) 3.31768 Tj +-250 TJm +([) 3.31768 Tj +-249 TJm +(\002lenames) 38.1882 Tj +-250 TJm +(...) 7.47225 Tj +-620 TJm +(]) 3.31768 Tj +[1 0 0 1 297.045 321.201] cm +0 g +0 G +[1 0 0 1 -225.045 -21.918] cm +0 g +0 G +[1 0 0 1 6.974 0] cm +0 g +0 G +[1 0 0 1 -78.974 -299.283] cm +[1 0 0 1 0 0] Tm +0 0 Td +78.974 299.283 Td +/F128_0 9.963 Tf +(\225) 3.48705 Tj +[1 0 0 1 82.461 299.283] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 1.993 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -86.944 -299.283] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 299.283 Td +/F130_0 9.963 Tf +(bunzip2) 41.8446 Tj +[1 0 0 1 128.787 299.283] cm +0 g +0 G +[1 0 0 1 -128.787 -299.283] cm +[1 0 0 1 0 0] Tm +0 0 Td +131.278 299.283 Td +/F128_0 9.963 Tf +([) 3.31768 Tj +-250 TJm +(-fkvsVL) 33.7546 Tj +-250 TJm +(]) 3.31768 Tj +-250 TJm +([) 3.31768 Tj +-250 TJm +(\002lenames) 38.1882 Tj +-250 TJm +(...) 7.47225 Tj +-620 TJm +(]) 3.31768 Tj +[1 0 0 1 242.589 299.283] cm +0 g +0 G +[1 0 0 1 -170.589 -21.918] cm +0 g +0 G +[1 0 0 1 6.974 0] cm +0 g +0 G +[1 0 0 1 -78.974 -277.365] cm +[1 0 0 1 0 0] Tm +0 0 Td +78.974 277.365 Td +/F128_0 9.963 Tf +(\225) 3.48705 Tj +[1 0 0 1 82.461 277.365] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 1.993 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -86.944 -277.365] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 277.365 Td +/F130_0 9.963 Tf +(bzcat) 29.889 Tj +[1 0 0 1 116.832 277.365] cm +0 g +0 G +[1 0 0 1 -116.832 -277.365] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.323 277.365 Td +/F128_0 9.963 Tf +([) 3.31768 Tj +-250 TJm +(-s) 7.19329 Tj +-250 TJm +(]) 3.31768 Tj +-250 TJm +([) 3.31768 Tj +-250 TJm +(\002lenames) 38.1882 Tj +-250 TJm +(...) 7.47225 Tj +-620 TJm +(]) 3.31768 Tj +[1 0 0 1 204.074 277.365] cm +0 g +0 G +[1 0 0 1 -132.074 -21.918] cm +0 g +0 G +[1 0 0 1 6.974 0] cm +0 g +0 G +[1 0 0 1 -78.974 -255.447] cm +[1 0 0 1 0 0] Tm +0 0 Td +78.974 255.447 Td +/F128_0 9.963 Tf +(\225) 3.48705 Tj +[1 0 0 1 82.461 255.447] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 1.993 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -86.944 -255.447] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 255.447 Td +/F130_0 9.963 Tf +(bzip2recover) 71.7336 Tj +[1 0 0 1 158.675 255.447] cm +0 g +0 G +[1 0 0 1 -158.675 -255.447] cm +[1 0 0 1 0 0] Tm +0 0 Td +161.166 255.447 Td +/F128_0 9.963 Tf +(\002lename) 34.3126 Tj +[1 0 0 1 195.477 255.447] cm +0 g +0 G +[1 0 0 1 -123.477 -204.595] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.754] cm +0 g +0 G +0 g +0 G +[1 0 0 1 43.063 -6.754] cm +0 g +0 G +[1 0 0 1 -496.332 -50.852] cm +[1 0 0 1 0 0] Tm +0 0 Td +539.395 50.852 Td +/F128_0 9.963 Tf +(2) 4.9815 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 6 6 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 -8.911] cm +0 g +0 G +[1 0 0 1 0 8.911] cm +0 g +0 G +0 g +0 G +[1 0 0 1 105.519 -6.755] cm +0 g +0 G +[1 0 0 1 -371.59 -749.245] cm +[1 0 0 1 0 0] Tm +0 0 Td +477.109 749.245 Td +/F128_0 9.963 Tf +(Ho) 12.1748 Tj +25 TJm +(w) 7.19329 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(use) 13.2807 Tj +-250 TJm +(bzip2) 22.1378 Tj +[1 0 0 1 266.071 747.089] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -5.037] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -468 -21.554] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -720] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 704.93 Td +/F121_0 20.659 Tf +(2.3.) 34.4592 Tj +-278 TJm +(DESCRIPTION) 141.184 Tj +[1 0 0 1 72 704.672] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -694.709] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 683.012 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 101.888 683.012] cm +0 g +0 G +[1 0 0 1 -101.888 -683.012] cm +[1 0 0 1 0 0] Tm +0 0 Td +104.56 683.012 Td +/F128_0 9.963 Tf +(compresses) 45.9294 Tj +-268 TJm +(\002les) 16.6083 Tj +-268 TJm +(using) 21.5898 Tj +-268 TJm +(the) 12.1748 Tj +-268 TJm +(Burro) 23.2437 Tj +25 TJm +(ws-Wheeler) 48.1313 Tj +-268 TJm +(block) 22.1378 Tj +-268 TJm +(sorting) 27.6772 Tj +-268 TJm +(te) 7.19329 Tj +15 TJm +(xt) 7.75121 Tj +-268 TJm +(compression) 50.363 Tj +-268 TJm +(algorithm,) 41.2369 Tj +-273 TJm +(and) 14.3866 Tj +-268 TJm +(Huf) 15.4925 Tj +25 TJm +(fman) 20.474 Tj +-268 TJm +(coding.) 29.61 Tj +72 671.057 Td +(Compression) 52.5847 Tj +-203 TJm +(is) 6.64532 Tj +-203 TJm +(generally) 37.0723 Tj +-204 TJm +(c) 4.42357 Tj +1 TJm +(onsiderably) 46.4874 Tj +-204 TJm +(better) 22.6858 Tj +-203 TJm +(than) 17.1563 Tj +-203 TJm +(that) 14.9445 Tj +-203 TJm +(achie) 21.0219 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(ed) 9.40507 Tj +-203 TJm +(by) 9.963 Tj +-204 TJm +(more) 20.474 Tj +-203 TJm +(con) 14.3866 Tj +40 TJm +(v) 4.9815 Tj +15 TJm +(entional) 32.1008 Tj +-203 TJm +(LZ77/LZ78-based) 73.0487 Tj +-203 TJm +(compressors,) 52.2958 Tj +72 659.101 Td +(and) 14.3866 Tj +-250 TJm +(approaches) 44.8136 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(performan) 41.4959 Tj +1 TJm +(ce) 8.84714 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(PPM) 19.936 Tj +-250 TJm +(f) 3.31768 Tj +10 TJm +(amily) 22.6957 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(statistical) 37.6402 Tj +-250 TJm +(compressors.) 52.2958 Tj +[1 0 0 1 72 656.945] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -646.982] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 637.184 Td +/F128_0 9.963 Tf +(The) 15.4925 Tj +-250 TJm +(command-line) 57.5563 Tj +-250 TJm +(options) 29.341 Tj +-250 TJm +(ar) 7.74125 Tj +1 TJm +(e) 4.42357 Tj +-250 TJm +(deliberately) 47.0353 Tj +-250 TJm +(v) 4.9815 Tj +15 TJm +(ery) 12.7228 Tj +-250 TJm +(similar) 27.6772 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(those) 21.0319 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(GNU) 21.5799 Tj +[1 0 0 1 364.869 637.184] cm +0 g +0 G +[1 0 0 1 -364.869 -637.184] cm +[1 0 0 1 0 0] Tm +0 0 Td +364.869 637.184 Td +/F130_0 9.963 Tf +(gzip) 23.9112 Tj +[1 0 0 1 388.779 637.184] cm +0 g +0 G +[1 0 0 1 -388.779 -637.184] cm +[1 0 0 1 0 0] Tm +0 0 Td +388.779 637.184 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-250 TJm +(b) 4.9815 Tj +20 TJm +(ut) 7.75121 Tj +-250 TJm +(the) 12.1748 Tj +15 TJm +(y) 4.9815 Tj +-250 TJm +(are) 12.1648 Tj +-250 TJm +(not) 12.7327 Tj +-250 TJm +(identical.) 36.8033 Tj +[1 0 0 1 72 635.027] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -625.064] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 615.266 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 101.888 615.266] cm +0 g +0 G +[1 0 0 1 -101.888 -615.266] cm +[1 0 0 1 0 0] Tm +0 0 Td +105.175 615.266 Td +/F128_0 9.963 Tf +(e) 4.42357 Tj +15 TJm +(xpects) 25.4555 Tj +-330 TJm +(a) 4.42357 Tj +-330 TJm +(list) 12.1847 Tj +-329 TJm +(of) 8.29918 Tj +-330 TJm +(\002le) 12.7327 Tj +-330 TJm +(names) 25.4555 Tj +-330 TJm +(to) 7.75121 Tj +-330 TJm +(accompan) 40.39 Tj +15 TJm +(y) 4.9815 Tj +-329 TJm +(the) 12.1748 Tj +-330 TJm +(command-line) 57.5563 Tj +-330 TJm +(\003ags.) 21.3109 Tj +-1099 TJm +(Each) 19.916 Tj +-330 TJm +(\002le) 12.7327 Tj +-330 TJm +(is) 6.64532 Tj +-330 TJm +(replaced) 33.7447 Tj +-330 TJm +(by) 9.963 Tj +-329 TJm +(a) 4.42357 Tj +-330 TJm +(compressed) 47.0353 Tj +72 603.311 Td +(v) 4.9815 Tj +15 TJm +(ersion) 24.3496 Tj +-348 TJm +(of) 8.29918 Tj +-349 TJm +(itself,) 22.4168 Tj +-373 TJm +(with) 17.7142 Tj +-349 TJm +(the) 12.1748 Tj +-348 TJm +(name) 21.5799 Tj +[1 0 0 1 204.444 603.311] cm +0 g +0 G +[1 0 0 1 -204.444 -603.311] cm +[1 0 0 1 0 0] Tm +0 0 Td +204.444 603.311 Td +/F130_0 9.963 Tf +(original_name.bz2) 101.623 Tj +[1 0 0 1 306.063 603.311] cm +0 g +0 G +[1 0 0 1 -306.063 -603.311] cm +[1 0 0 1 0 0] Tm +0 0 Td +306.063 603.311 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +-1211 TJm +(Each) 19.916 Tj +-349 TJm +(compressed) 47.0353 Tj +-348 TJm +(\002le) 12.7327 Tj +-349 TJm +(has) 13.2807 Tj +-348 TJm +(the) 12.1748 Tj +-349 TJm +(same) 20.474 Tj +-348 TJm +(modi\002cation) 50.3729 Tj +-349 TJm +(date,) 19.0891 Tj +72 591.356 Td +(permissions,) 50.094 Tj +-344 TJm +(and,) 16.8773 Tj +-344 TJm +(when) 21.5799 Tj +-325 TJm +(possible,) 35.1495 Tj +-344 TJm +(o) 4.9815 Tj +25 TJm +(w) 7.19329 Tj +1 TJm +(nership) 29.3311 Tj +-326 TJm +(as) 8.29918 Tj +-325 TJm +(the) 12.1748 Tj +-325 TJm +(corresponding) 56.9983 Tj +-325 TJm +(original,) 33.4856 Tj +-344 TJm +(so) 8.85711 Tj +-325 TJm +(that) 14.9445 Tj +-325 TJm +(these) 20.474 Tj +-325 TJm +(properties) 39.842 Tj +-325 TJm +(can) 13.8286 Tj +-325 TJm +(be) 9.40507 Tj +-325 TJm +(correctly) 35.4085 Tj +72 579.4 Td +(restored) 32.0908 Tj +-308 TJm +(at) 7.19329 Tj +-307 TJm +(decompression) 59.768 Tj +-308 TJm +(time.) 20.205 Tj +-483 TJm +(File) 15.5024 Tj +-308 TJm +(name) 21.5799 Tj +-308 TJm +(handling) 34.8705 Tj +-308 TJm +(is) 6.64532 Tj +-307 TJm +(nai) 12.1748 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-308 TJm +(in) 7.75121 Tj +-308 TJm +(the) 12.1748 Tj +-308 TJm +(sense) 21.5799 Tj +-308 TJm +(that) 14.9445 Tj +-307 TJm +(there) 19.916 Tj +-308 TJm +(is) 6.64532 Tj +-308 TJm +(no) 9.963 Tj +-308 TJm +(mechanism) 45.3815 Tj +-307 TJm +(for) 11.6169 Tj +-308 TJm +(preserving) 42.0538 Tj +72 567.445 Td +(original) 30.9949 Tj +-334 TJm +(\002le) 12.7327 Tj +-333 TJm +(names,) 27.9462 Tj +-355 TJm +(permissi) 33.7646 Tj +1 TJm +(ons,) 16.3294 Tj +-355 TJm +(o) 4.9815 Tj +25 TJm +(wnerships) 40.4 Tj +-334 TJm +(or) 8.29918 Tj +-333 TJm +(dates) 20.474 Tj +-334 TJm +(in) 7.75121 Tj +-333 TJm +(\002lesystems) 44.2855 Tj +-334 TJm +(which) 24.3496 Tj +-333 TJm +(lack) 16.5984 Tj +-334 TJm +(these) 20.474 Tj +-334 TJm +(concepts,) 37.3513 Tj +-354 TJm +(or) 8.29918 Tj +-334 TJm +(ha) 9.40507 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-333 TJm +(serious) 28.2252 Tj +-334 TJm +(\002le) 12.7327 Tj +72 555.49 Td +(name) 21.5799 Tj +-250 TJm +(length) 24.9075 Tj +-250 TJm +(restrictions,) 46.7663 Tj +-250 TJm +(su) 8.85711 Tj +1 TJm +(ch) 9.40507 Tj +-250 TJm +(as) 8.29918 Tj +-250 TJm +(MS-DOS.) 40.131 Tj +[1 0 0 1 72 553.333] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -543.371] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 533.572 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 101.888 533.572] cm +0 g +0 G +[1 0 0 1 -101.888 -533.572] cm +[1 0 0 1 0 0] Tm +0 0 Td +104.379 533.572 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 121.255 533.572] cm +0 g +0 G +[1 0 0 1 -121.255 -533.572] cm +[1 0 0 1 0 0] Tm +0 0 Td +121.255 533.572 Td +/F130_0 9.963 Tf +(bunzip2) 41.8446 Tj +[1 0 0 1 163.098 533.572] cm +0 g +0 G +[1 0 0 1 -163.098 -533.572] cm +[1 0 0 1 0 0] Tm +0 0 Td +165.589 533.572 Td +/F128_0 9.963 Tf +(will) 15.5024 Tj +-250 TJm +(by) 9.963 Tj +-250 TJm +(def) 12.7228 Tj +10 TJm +(ault) 14.9445 Tj +-250 TJm +(not) 12.7327 Tj +-250 TJm +(o) 4.9815 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(erwrite) 28.2152 Tj +-250 TJm +(e) 4.42357 Tj +16 TJm +(xisting) 27.1292 Tj +-250 TJm +(\002les.) 19.0991 Tj +-620 TJm +(If) 6.63536 Tj +-250 TJm +(you) 14.9445 Tj +-250 TJm +(w) 7.19329 Tj +10 TJm +(ant) 12.1748 Tj +-250 TJm +(this) 14.3965 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(happen,) 31.2639 Tj +-250 TJm +(specify) 28.7731 Tj +-250 TJm +(the) 12.1748 Tj +[1 0 0 1 495.977 533.572] cm +0 g +0 G +[1 0 0 1 -495.977 -533.572] cm +[1 0 0 1 0 0] Tm +0 0 Td +495.977 533.572 Td +/F130_0 9.963 Tf +(-f) 11.9556 Tj +[1 0 0 1 507.932 533.572] cm +0 g +0 G +[1 0 0 1 -507.932 -533.572] cm +[1 0 0 1 0 0] Tm +0 0 Td +510.423 533.572 Td +/F128_0 9.963 Tf +(\003ag.) 17.4353 Tj +[1 0 0 1 72 531.415] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -521.453] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 511.654 Td +/F128_0 9.963 Tf +(If) 6.63536 Tj +-284 TJm +(no) 9.963 Tj +-285 TJm +(\002) 5.53943 Tj +1 TJm +(le) 7.19329 Tj +-285 TJm +(names) 25.4555 Tj +-284 TJm +(are) 12.1648 Tj +-284 TJm +(speci\002ed,) 37.9092 Tj +[1 0 0 1 193.935 511.654] cm +0 g +0 G +[1 0 0 1 -193.935 -511.654] cm +[1 0 0 1 0 0] Tm +0 0 Td +193.935 511.654 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 223.823 511.654] cm +0 g +0 G +[1 0 0 1 -223.823 -511.654] cm +[1 0 0 1 0 0] Tm +0 0 Td +226.655 511.654 Td +/F128_0 9.963 Tf +(compresses) 45.9294 Tj +-284 TJm +(from) 19.3681 Tj +-284 TJm +(standard) 33.7546 Tj +-284 TJm +(input) 20.4839 Tj +-285 TJm +(to) 7.75121 Tj +-284 TJm +(standard) 33.7546 Tj +-284 TJm +(output.) 27.9562 Tj +-826 TJm +(In) 8.29918 Tj +-284 TJm +(this) 14.3965 Tj +-284 TJm +(case,) 19.6371 Tj +[1 0 0 1 491.778 511.654] cm +0 g +0 G +[1 0 0 1 -491.778 -511.654] cm +[1 0 0 1 0 0] Tm +0 0 Td +491.778 511.654 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 521.666 511.654] cm +0 g +0 G +[1 0 0 1 -521.666 -511.654] cm +[1 0 0 1 0 0] Tm +0 0 Td +524.498 511.654 Td +/F128_0 9.963 Tf +(will) 15.5024 Tj +72 499.699 Td +(decline) 28.7731 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(write) 20.474 Tj +-250 TJm +(compressed) 47.0353 Tj +-249 TJm +(output) 25.4654 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(terminal,) 35.6974 Tj +-250 TJm +(as) 8.29918 Tj +-250 TJm +(this) 14.3965 Tj +-250 TJm +(w) 7.19329 Tj +10 TJm +(ould) 17.7142 Tj +-250 TJm +(be) 9.40507 Tj +-250 TJm +(entirely) 30.437 Tj +-250 TJm +(incompre) 37.6303 Tj +1 TJm +(hensible) 33.2067 Tj +-250 TJm +(and) 14.3866 Tj +-250 TJm +(therefore) 35.9565 Tj +-250 TJm +(pointless.) 37.9192 Tj +[1 0 0 1 72 497.542] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -487.58] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 477.781 Td +/F130_0 9.963 Tf +(bunzip2) 41.8446 Tj +[1 0 0 1 113.843 477.781] cm +0 g +0 G +[1 0 0 1 -113.843 -477.781] cm +[1 0 0 1 0 0] Tm +0 0 Td +116.176 477.781 Td +/F128_0 9.963 Tf +(\(or) 11.6169 Tj +[1 0 0 1 130.125 477.781] cm +0 g +0 G +[1 0 0 1 -130.125 -477.781] cm +[1 0 0 1 0 0] Tm +0 0 Td +130.125 477.781 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +-600 TJm +(-d) 11.9556 Tj +[1 0 0 1 177.946 477.781] cm +0 g +0 G +[1 0 0 1 -177.946 -477.781] cm +[1 0 0 1 0 0] Tm +0 0 Td +177.946 477.781 Td +/F128_0 9.963 Tf +(\)) 3.31768 Tj +-234 TJm +(decompresses) 55.3345 Tj +-234 TJm +(all) 9.963 Tj +-234 TJm +(speci\002ed) 35.4185 Tj +-234 TJm +(\002les.) 19.0991 Tj +-609 TJm +(Files) 19.378 Tj +-234 TJm +(which) 24.3496 Tj +-235 TJm +(we) 11.6169 Tj +1 TJm +(re) 7.74125 Tj +-235 TJm +(not) 12.7327 Tj +-234 TJm +(created) 28.7632 Tj +-234 TJm +(by) 9.963 Tj +[1 0 0 1 445.012 477.781] cm +0 g +0 G +[1 0 0 1 -445.012 -477.781] cm +[1 0 0 1 0 0] Tm +0 0 Td +445.012 477.781 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 474.9 477.781] cm +0 g +0 G +[1 0 0 1 -474.9 -477.781] cm +[1 0 0 1 0 0] Tm +0 0 Td +477.233 477.781 Td +/F128_0 9.963 Tf +(will) 15.5024 Tj +-234 TJm +(be) 9.40507 Tj +-234 TJm +(detected) 33.1967 Tj +72 465.826 Td +(and) 14.3866 Tj +-279 TJm +(ignored,) 32.9277 Tj +-287 TJm +(and) 14.3866 Tj +-280 TJm +(a) 4.42357 Tj +-279 TJm +(w) 7.19329 Tj +10 TJm +(arning) 25.4555 Tj +-279 TJm +(issued.) 27.3983 Tj +[1 0 0 1 216.033 465.826] cm +0 g +0 G +[1 0 0 1 -216.033 -465.826] cm +[1 0 0 1 0 0] Tm +0 0 Td +216.033 465.826 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 245.921 465.826] cm +0 g +0 G +[1 0 0 1 -245.921 -465.826] cm +[1 0 0 1 0 0] Tm +0 0 Td +248.705 465.826 Td +/F128_0 9.963 Tf +(attempts) 33.7646 Tj +-279 TJm +(to) 7.75121 Tj +-280 TJm +(guess) 22.1378 Tj +-279 TJm +(the) 12.1748 Tj +-280 TJm +(\002lenam) 29.889 Tj +1 TJm +(e) 4.42357 Tj +-280 TJm +(for) 11.6169 Tj +-279 TJm +(the) 12.1748 Tj +-280 TJm +(decompressed) 56.4404 Tj +-279 TJm +(\002le) 12.7327 Tj +-280 TJm +(fr) 6.63536 Tj +1 TJm +(om) 12.7327 Tj +-280 TJm +(that) 14.9445 Tj +-279 TJm +(of) 8.29918 Tj +-280 TJm +(the) 12.1748 Tj +72 453.871 Td +(compressed) 47.0353 Tj +-250 TJm +(\002le) 12.7327 Tj +-250 TJm +(as) 8.29918 Tj +-250 TJm +(follo) 18.8201 Tj +25 TJm +(ws:) 13.8386 Tj +[1 0 0 1 72 451.714] cm +0 g +0 G +[1 0 0 1 0 -29.723] cm +0 g +0 G +[1 0 0 1 6.974 0] cm +0 g +0 G +[1 0 0 1 -78.974 -421.991] cm +[1 0 0 1 0 0] Tm +0 0 Td +78.974 421.991 Td +/F128_0 9.963 Tf +(\225) 3.48705 Tj +[1 0 0 1 82.461 421.991] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 1.993 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -86.944 -421.991] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 421.991 Td +/F130_0 9.963 Tf +(filename.bz2) 71.7336 Tj +[1 0 0 1 164.653 421.991] cm +0 g +0 G +[1 0 0 1 -164.653 -421.991] cm +[1 0 0 1 0 0] Tm +0 0 Td +167.143 421.991 Td +/F128_0 9.963 Tf +(becomes) 34.8605 Tj +[1 0 0 1 204.493 421.991] cm +0 g +0 G +[1 0 0 1 -204.493 -421.991] cm +[1 0 0 1 0 0] Tm +0 0 Td +204.493 421.991 Td +/F130_0 9.963 Tf +(filename) 47.8224 Tj +[1 0 0 1 252.313 421.991] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -180.313 -21.918] cm +0 g +0 G +[1 0 0 1 6.974 0] cm +0 g +0 G +[1 0 0 1 -78.974 -400.073] cm +[1 0 0 1 0 0] Tm +0 0 Td +78.974 400.073 Td +/F128_0 9.963 Tf +(\225) 3.48705 Tj +[1 0 0 1 82.461 400.073] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 1.993 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -86.944 -400.073] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 400.073 Td +/F130_0 9.963 Tf +(filename.bz) 65.7558 Tj +[1 0 0 1 158.675 400.073] cm +0 g +0 G +[1 0 0 1 -158.675 -400.073] cm +[1 0 0 1 0 0] Tm +0 0 Td +161.166 400.073 Td +/F128_0 9.963 Tf +(becomes) 34.8605 Tj +[1 0 0 1 198.515 400.073] cm +0 g +0 G +[1 0 0 1 -198.515 -400.073] cm +[1 0 0 1 0 0] Tm +0 0 Td +198.515 400.073 Td +/F130_0 9.963 Tf +(filename) 47.8224 Tj +[1 0 0 1 246.336 400.073] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -174.336 -21.918] cm +0 g +0 G +[1 0 0 1 6.974 0] cm +0 g +0 G +[1 0 0 1 -78.974 -378.155] cm +[1 0 0 1 0 0] Tm +0 0 Td +78.974 378.155 Td +/F128_0 9.963 Tf +(\225) 3.48705 Tj +[1 0 0 1 82.461 378.155] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 1.993 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -86.944 -378.155] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 378.155 Td +/F130_0 9.963 Tf +(filename.tbz2) 77.7114 Tj +[1 0 0 1 164.653 378.155] cm +0 g +0 G +[1 0 0 1 -164.653 -378.155] cm +[1 0 0 1 0 0] Tm +0 0 Td +167.143 378.155 Td +/F128_0 9.963 Tf +(becomes) 34.8605 Tj +[1 0 0 1 204.493 378.155] cm +0 g +0 G +[1 0 0 1 -204.493 -378.155] cm +[1 0 0 1 0 0] Tm +0 0 Td +204.493 378.155 Td +/F130_0 9.963 Tf +(filename.tar) 71.7336 Tj +[1 0 0 1 276.224 378.155] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -204.224 -21.918] cm +0 g +0 G +[1 0 0 1 6.974 0] cm +0 g +0 G +[1 0 0 1 -78.974 -356.237] cm +[1 0 0 1 0 0] Tm +0 0 Td +78.974 356.237 Td +/F128_0 9.963 Tf +(\225) 3.48705 Tj +[1 0 0 1 82.461 356.237] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 1.993 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -86.944 -356.237] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 356.237 Td +/F130_0 9.963 Tf +(filename.tbz) 71.7336 Tj +[1 0 0 1 164.653 356.237] cm +0 g +0 G +[1 0 0 1 -164.653 -356.237] cm +[1 0 0 1 0 0] Tm +0 0 Td +167.143 356.237 Td +/F128_0 9.963 Tf +(becomes) 34.8605 Tj +[1 0 0 1 204.493 356.237] cm +0 g +0 G +[1 0 0 1 -204.493 -356.237] cm +[1 0 0 1 0 0] Tm +0 0 Td +204.493 356.237 Td +/F130_0 9.963 Tf +(filename.tar) 71.7336 Tj +[1 0 0 1 276.224 356.237] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -204.224 -21.918] cm +0 g +0 G +[1 0 0 1 6.974 0] cm +0 g +0 G +[1 0 0 1 -78.974 -334.319] cm +[1 0 0 1 0 0] Tm +0 0 Td +78.974 334.319 Td +/F128_0 9.963 Tf +(\225) 3.48705 Tj +[1 0 0 1 82.461 334.319] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 1.992 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -86.944 -334.319] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 334.319 Td +/F130_0 9.963 Tf +(anyothername) 71.7336 Tj +[1 0 0 1 164.653 334.319] cm +0 g +0 G +[1 0 0 1 -164.653 -334.319] cm +[1 0 0 1 0 0] Tm +0 0 Td +167.143 334.319 Td +/F128_0 9.963 Tf +(becomes) 34.8605 Tj +[1 0 0 1 204.493 334.319] cm +0 g +0 G +[1 0 0 1 -204.493 -334.319] cm +[1 0 0 1 0 0] Tm +0 0 Td +204.493 334.319 Td +/F130_0 9.963 Tf +(anyothername.out) 95.6448 Tj +[1 0 0 1 300.134 334.319] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -228.134 -11.526] cm +0 g +0 G +[1 0 0 1 -72 -322.793] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 312.402 Td +/F128_0 9.963 Tf +(If) 6.63536 Tj +-342 TJm +(the) 12.1748 Tj +-342 TJm +(\002le) 12.7327 Tj +-342 TJm +(does) 18.2622 Tj +-342 TJm +(not) 12.7327 Tj +-342 TJm +(end) 14.3866 Tj +-342 TJm +(in) 7.75121 Tj +-342 TJm +(one) 14.3866 Tj +-343 TJm +(of) 8.29918 Tj +-342 TJm +(the) 12.1748 Tj +-342 TJm +(recognised) 43.1597 Tj +-342 TJm +(endings,) 33.4856 Tj +[1 0 0 1 309.305 312.402] cm +0 g +0 G +[1 0 0 1 -309.305 -312.402] cm +[1 0 0 1 0 0] Tm +0 0 Td +309.305 312.402 Td +/F130_0 9.963 Tf +(.bz2) 23.9112 Tj +[1 0 0 1 333.215 312.402] cm +0 g +0 G +[1 0 0 1 -333.215 -312.402] cm +[1 0 0 1 0 0] Tm +0 0 Td +333.215 312.402 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 339.344 312.402] cm +0 g +0 G +[1 0 0 1 -339.344 -312.402] cm +[1 0 0 1 0 0] Tm +0 0 Td +339.344 312.402 Td +/F130_0 9.963 Tf +(.bz) 17.9334 Tj +[1 0 0 1 357.276 312.402] cm +0 g +0 G +[1 0 0 1 -357.276 -312.402] cm +[1 0 0 1 0 0] Tm +0 0 Td +357.276 312.402 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 363.405 312.402] cm +0 g +0 G +[1 0 0 1 -363.405 -312.402] cm +[1 0 0 1 0 0] Tm +0 0 Td +363.405 312.402 Td +/F130_0 9.963 Tf +(.tbz2) 29.889 Tj +[1 0 0 1 393.293 312.402] cm +0 g +0 G +[1 0 0 1 -393.293 -312.402] cm +[1 0 0 1 0 0] Tm +0 0 Td +396.702 312.402 Td +/F128_0 9.963 Tf +(or) 8.29918 Tj +[1 0 0 1 408.409 312.402] cm +0 g +0 G +[1 0 0 1 -408.409 -312.402] cm +[1 0 0 1 0 0] Tm +0 0 Td +408.409 312.402 Td +/F130_0 9.963 Tf +(.tbz) 23.9112 Tj +[1 0 0 1 432.319 312.402] cm +0 g +0 G +[1 0 0 1 -432.319 -312.402] cm +[1 0 0 1 0 0] Tm +0 0 Td +432.319 312.402 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 438.448 312.402] cm +0 g +0 G +[1 0 0 1 -438.448 -312.402] cm +[1 0 0 1 0 0] Tm +0 0 Td +438.448 312.402 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 468.336 312.402] cm +0 g +0 G +[1 0 0 1 -468.336 -312.402] cm +[1 0 0 1 0 0] Tm +0 0 Td +471.744 312.402 Td +/F128_0 9.963 Tf +(complains) 40.9579 Tj +-342 TJm +(that) 14.9445 Tj +-342 TJm +(it) 5.53943 Tj +72 300.446 Td +(cannot) 26.5614 Tj +-250 TJm +(guess) 22.1378 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(name) 21.5799 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(the) 12.1748 Tj +-249 TJm +(original) 30.9949 Tj +-250 TJm +(\002le,) 15.2235 Tj +-250 TJm +(and) 14.3866 Tj +-250 TJm +(uses) 17.1563 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(original) 30.9949 Tj +-250 TJm +(name) 21.5799 Tj +-250 TJm +(with) 17.7142 Tj +[1 0 0 1 370.009 300.446] cm +0 g +0 G +[1 0 0 1 -370.009 -300.446] cm +[1 0 0 1 0 0] Tm +0 0 Td +370.009 300.446 Td +/F130_0 9.963 Tf +(.out) 23.9112 Tj +[1 0 0 1 393.92 300.446] cm +0 g +0 G +[1 0 0 1 -393.92 -300.446] cm +[1 0 0 1 0 0] Tm +0 0 Td +396.41 300.446 Td +/F128_0 9.963 Tf +(appended.) 40.669 Tj +[1 0 0 1 72 298.29] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -288.327] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 278.529 Td +/F128_0 9.963 Tf +(As) 11.0689 Tj +-250 TJm +(with) 17.7142 Tj +-250 TJm +(compression,) 52.8537 Tj +-250 TJm +(supply) 26.5713 Tj +1 TJm +(ing) 12.7327 Tj +-250 TJm +(no) 9.963 Tj +-250 TJm +(\002lenames) 38.1882 Tj +-250 TJm +(causes) 26.0034 Tj +-250 TJm +(decompression) 59.768 Tj +-250 TJm +(from) 19.3681 Tj +-250 TJm +(standard) 33.7546 Tj +-250 TJm +(inp) 12.7327 Tj +1 TJm +(ut) 7.75121 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(standard) 33.7546 Tj +-250 TJm +(output.) 27.9562 Tj +[1 0 0 1 72 276.372] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -266.409] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 256.611 Td +/F130_0 9.963 Tf +(bunzip2) 41.8446 Tj +[1 0 0 1 113.843 256.611] cm +0 g +0 G +[1 0 0 1 -113.843 -256.611] cm +[1 0 0 1 0 0] Tm +0 0 Td +116.409 256.611 Td +/F128_0 9.963 Tf +(will) 15.5024 Tj +-257 TJm +(correctly) 35.4085 Tj +-258 TJm +(decompress) 47.0353 Tj +-257 TJm +(a) 4.42357 Tj +-258 TJm +(\002l) 8.30914 Tj +1 TJm +(e) 4.42357 Tj +-258 TJm +(which) 24.3496 Tj +-257 TJm +(is) 6.64532 Tj +-258 TJm +(the) 12.1748 Tj +-257 TJm +(concatenation) 55.3345 Tj +-258 TJm +(of) 8.29918 Tj +-257 TJm +(tw) 9.963 Tj +10 TJm +(o) 4.9815 Tj +-257 TJm +(or) 8.29918 Tj +-258 TJm +(more) 20.474 Tj +-257 TJm +(compressed) 47.0353 Tj +-258 TJm +(\002les.) 19.0991 Tj +-665 TJm +(The) 15.4925 Tj +-257 TJm +(result) 22.1378 Tj +-258 TJm +(is) 6.64532 Tj +72 244.656 Td +(the) 12.1748 Tj +-239 TJm +(concatena) 39.8321 Tj +1 TJm +(tion) 15.5024 Tj +-239 TJm +(of) 8.29918 Tj +-239 TJm +(the) 12.1748 Tj +-238 TJm +(corresponding) 56.9983 Tj +-239 TJm +(uncompressed) 56.9983 Tj +-238 TJm +(\002les.) 19.0991 Tj +-613 TJm +(Inte) 15.4925 Tj +15 TJm +(grity) 18.8201 Tj +-238 TJm +(testing) 26.5713 Tj +-239 TJm +(\() 3.31768 Tj +[1 0 0 1 382.247 244.656] cm +0 g +0 G +[1 0 0 1 -382.247 -244.656] cm +[1 0 0 1 0 0] Tm +0 0 Td +382.247 244.656 Td +/F130_0 9.963 Tf +(-t) 11.9556 Tj +[1 0 0 1 394.202 244.656] cm +0 g +0 G +[1 0 0 1 -394.202 -244.656] cm +[1 0 0 1 0 0] Tm +0 0 Td +394.202 244.656 Td +/F128_0 9.963 Tf +(\)) 3.31768 Tj +-239 TJm +(of) 8.29918 Tj +-238 TJm +(concatenated) 52.0069 Tj +-239 TJm +(compressed) 47.0353 Tj +-238 TJm +(\002les) 16.6083 Tj +-239 TJm +(is) 6.64532 Tj +72 232.7 Td +(also) 16.0504 Tj +-250 TJm +(supported.) 41.7848 Tj +[1 0 0 1 72 230.544] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -220.581] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 210.783 Td +/F128_0 9.963 Tf +(Y) 7.19329 Tj +110 TJm +(ou) 9.963 Tj +-399 TJm +(can) 13.8286 Tj +-399 TJm +(also) 16.0504 Tj +-399 TJm +(compress) 37.6303 Tj +-399 TJm +(or) 8.29918 Tj +-399 TJm +(decompress) 47.0353 Tj +-399 TJm +(\002les) 16.6083 Tj +-399 TJm +(to) 7.75121 Tj +-399 TJm +(the) 12.1748 Tj +-399 TJm +(standard) 33.7546 Tj +-399 TJm +(output) 25.4654 Tj +-399 TJm +(by) 9.963 Tj +-399 TJm +(gi) 7.75121 Tj +25 TJm +(ving) 17.7142 Tj +-399 TJm +(the) 12.1748 Tj +[1 0 0 1 409.67 210.783] cm +0 g +0 G +[1 0 0 1 -409.67 -210.783] cm +[1 0 0 1 0 0] Tm +0 0 Td +409.67 210.783 Td +/F130_0 9.963 Tf +(-c) 11.9556 Tj +[1 0 0 1 421.625 210.783] cm +0 g +0 G +[1 0 0 1 -421.625 -210.783] cm +[1 0 0 1 0 0] Tm +0 0 Td +425.602 210.783 Td +/F128_0 9.963 Tf +(\003ag.) 17.4353 Tj +-757 TJm +(Multiple) 34.3225 Tj +-399 TJm +(\002les) 16.6083 Tj +-399 TJm +(may) 17.1563 Tj +-399 TJm +(be) 9.40507 Tj +72 198.828 Td +(compressed) 47.0353 Tj +-367 TJm +(and) 14.3866 Tj +-367 TJm +(dec) 13.8286 Tj +1 TJm +(ompressed) 42.6118 Tj +-367 TJm +(lik) 10.5209 Tj +10 TJm +(e) 4.42357 Tj +-367 TJm +(this.) 16.8873 Tj +-1321 TJm +(The) 15.4925 Tj +-367 TJm +(resulting) 34.8705 Tj +-367 TJm +(outputs) 29.341 Tj +-367 TJm +(are) 12.1648 Tj +-367 TJm +(fed) 12.7228 Tj +-366 TJm +(sequentially) 48.1512 Tj +-367 TJm +(to) 7.75121 Tj +-367 TJm +(stdout.) 26.8503 Tj +-1321 TJm +(Compression) 52.5847 Tj +-367 TJm +(of) 8.29918 Tj +72 186.872 Td +(multiple) 33.2166 Tj +-289 TJm +(\002les) 16.6083 Tj +-289 TJm +(in) 7.75121 Tj +-288 TJm +(this) 14.3965 Tj +-289 TJm +(manner) 29.879 Tj +-289 TJm +(generates) 37.6203 Tj +-289 TJm +(a) 4.42357 Tj +-289 TJm +(stre) 14.3866 Tj +1 TJm +(am) 12.1748 Tj +-289 TJm +(containing) 42.0638 Tj +-289 TJm +(multiple) 33.2166 Tj +-289 TJm +(compressed) 47.0353 Tj +-288 TJm +(\002le) 12.7327 Tj +-289 TJm +(representations.) 62.8068 Tj +-853 TJm +(Such) 19.926 Tj +-289 TJm +(a) 4.42357 Tj +-289 TJm +(stream) 26.5614 Tj +72 174.917 Td +(can) 13.8286 Tj +-391 TJm +(be) 9.40507 Tj +-391 TJm +(dec) 13.8286 Tj +1 TJm +(ompressed) 42.6118 Tj +-391 TJm +(correctly) 35.4085 Tj +-391 TJm +(only) 17.7142 Tj +-391 TJm +(by) 9.963 Tj +[1 0 0 1 238.116 174.917] cm +0 g +0 G +[1 0 0 1 -238.116 -174.917] cm +[1 0 0 1 0 0] Tm +0 0 Td +238.116 174.917 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 268.004 174.917] cm +0 g +0 G +[1 0 0 1 -268.004 -174.917] cm +[1 0 0 1 0 0] Tm +0 0 Td +271.897 174.917 Td +/F128_0 9.963 Tf +(v) 4.9815 Tj +15 TJm +(ersion) 24.3496 Tj +-391 TJm +(0.9.0) 19.926 Tj +-391 TJm +(o) 4.9815 Tj +1 TJm +(r) 3.31768 Tj +-391 TJm +(later) 17.7043 Tj +55 TJm +(.) 2.49075 Tj +-733 TJm +(Earlier) 27.1093 Tj +-390 TJm +(v) 4.9815 Tj +15 TJm +(ersions) 28.2252 Tj +-391 TJm +(of) 8.29918 Tj +[1 0 0 1 448.071 174.917] cm +0 g +0 G +[1 0 0 1 -448.071 -174.917] cm +[1 0 0 1 0 0] Tm +0 0 Td +448.071 174.917 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 477.959 174.917] cm +0 g +0 G +[1 0 0 1 -477.959 -174.917] cm +[1 0 0 1 0 0] Tm +0 0 Td +481.852 174.917 Td +/F128_0 9.963 Tf +(will) 15.5024 Tj +-391 TJm +(stop) 16.6083 Tj +-391 TJm +(a) 4.42357 Tj +1 TJm +(fter) 13.8286 Tj +72 162.962 Td +(decompressing) 59.768 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(\002rst) 15.5024 Tj +-250 TJm +(\002le) 12.7327 Tj +-249 TJm +(in) 7.75121 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(stream.) 29.0521 Tj +[1 0 0 1 72 160.805] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -150.843] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 141.044 Td +/F130_0 9.963 Tf +(bzcat) 29.889 Tj +[1 0 0 1 101.888 141.044] cm +0 g +0 G +[1 0 0 1 -101.888 -141.044] cm +[1 0 0 1 0 0] Tm +0 0 Td +104.379 141.044 Td +/F128_0 9.963 Tf +(\(or) 11.6169 Tj +[1 0 0 1 118.486 141.044] cm +0 g +0 G +[1 0 0 1 -118.486 -141.044] cm +[1 0 0 1 0 0] Tm +0 0 Td +118.486 141.044 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +-600 TJm +(-dc) 17.9334 Tj +[1 0 0 1 172.284 141.044] cm +0 g +0 G +[1 0 0 1 -172.284 -141.044] cm +[1 0 0 1 0 0] Tm +0 0 Td +172.284 141.044 Td +/F128_0 9.963 Tf +(\)) 3.31768 Tj +-250 TJm +(decompresses) 55.3345 Tj +-250 TJm +(all) 9.963 Tj +-250 TJm +(speci\002e) 30.437 Tj +1 TJm +(d) 4.9815 Tj +-250 TJm +(\002les) 16.6083 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(standard) 33.7546 Tj +-250 TJm +(output.) 27.9562 Tj +[1 0 0 1 72 138.887] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -128.925] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 119.126 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 101.888 119.126] cm +0 g +0 G +[1 0 0 1 -101.888 -119.126] cm +[1 0 0 1 0 0] Tm +0 0 Td +104.866 119.126 Td +/F128_0 9.963 Tf +(will) 15.5024 Tj +-299 TJm +(read) 17.1463 Tj +-299 TJm +(ar) 7.74125 Tj +18 TJm +(gument) 29.889 Tj +1 TJm +(s) 3.87561 Tj +-299 TJm +(from) 19.3681 Tj +-299 TJm +(the) 12.1748 Tj +-299 TJm +(en) 9.40507 Tj +40 TJm +(vironment) 40.9579 Tj +-299 TJm +(v) 4.9815 Tj +25 TJm +(ariables) 30.9849 Tj +[1 0 0 1 316.903 119.126] cm +0 g +0 G +[1 0 0 1 -316.903 -119.126] cm +[1 0 0 1 0 0] Tm +0 0 Td +316.903 119.126 Td +/F130_0 9.963 Tf +(BZIP2) 29.889 Tj +[1 0 0 1 346.791 119.126] cm +0 g +0 G +[1 0 0 1 -346.791 -119.126] cm +[1 0 0 1 0 0] Tm +0 0 Td +349.769 119.126 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 367.133 119.126] cm +0 g +0 G +[1 0 0 1 -367.133 -119.126] cm +[1 0 0 1 0 0] Tm +0 0 Td +367.133 119.126 Td +/F130_0 9.963 Tf +(BZIP) 23.9112 Tj +[1 0 0 1 391.043 119.126] cm +0 g +0 G +[1 0 0 1 -391.043 -119.126] cm +[1 0 0 1 0 0] Tm +0 0 Td +391.043 119.126 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-299 TJm +(in) 7.75121 Tj +-299 TJm +(that) 14.9445 Tj +-299 TJm +(order) 21.0219 Tj +40 TJm +(,) 2.49075 Tj +-311 TJm +(and) 14.3866 Tj +-299 TJm +(wil) 12.7327 Tj +1 TJm +(l) 2.76971 Tj +-299 TJm +(process) 29.879 Tj +-299 TJm +(them) 19.926 Tj +72 107.171 Td +(before) 25.4455 Tj +-250 TJm +(an) 9.40507 Tj +15 TJm +(y) 4.9815 Tj +-250 TJm +(ar) 7.74125 Tj +18 TJm +(guments) 33.7646 Tj +-250 TJm +(read) 17.1463 Tj +-250 TJm +(from) 19.3681 Tj +-249 TJm +(the) 12.1748 Tj +-250 TJm +(command) 39.2941 Tj +-250 TJm +(line.) 17.4353 Tj +-310 TJm +(This) 17.7142 Tj +-250 TJm +(gi) 7.75121 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(es) 8.29918 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(con) 14.3866 Tj +40 TJm +(v) 4.9815 Tj +15 TJm +(enient) 24.3496 Tj +-250 TJm +(w) 7.19329 Tj +10 TJm +(ay) 9.40507 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(supply) 26.5713 Tj +-250 TJm +(d) 4.9815 Tj +1 TJm +(ef) 7.74125 Tj +10 TJm +(ault) 14.9445 Tj +-250 TJm +(ar) 7.74125 Tj +18 TJm +(guments.) 36.2554 Tj +[1 0 0 1 72 105.014] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -95.052] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 85.253 Td +/F128_0 9.963 Tf +(Compression) 52.5847 Tj +-294 TJm +(is) 6.64532 Tj +-294 TJm +(al) 7.19329 Tj +10 TJm +(w) 7.19329 Tj +10 TJm +(ays) 13.2807 Tj +-293 TJm +(performed,) 43.9866 Tj +-305 TJm +(e) 4.42357 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(en) 9.40507 Tj +-294 TJm +(if) 6.08739 Tj +-294 TJm +(the) 12.1748 Tj +-294 TJm +(compressed) 47.0353 Tj +-294 TJm +(\002le) 12.7327 Tj +-294 TJm +(i) 2.76971 Tj +1 TJm +(s) 3.87561 Tj +-294 TJm +(slightly) 29.899 Tj +-294 TJm +(lar) 10.511 Tj +18 TJm +(ger) 12.7228 Tj +-294 TJm +(than) 17.1563 Tj +-294 TJm +(the) 12.1748 Tj +-294 TJm +(original.) 33.4856 Tj +-883 TJm +(Files) 19.378 Tj +-294 TJm +(of) 8.29918 Tj +-294 TJm +(less) 14.9445 Tj +-294 TJm +(than) 17.1563 Tj +72 73.298 Td +(about) 22.1378 Tj +-246 TJm +(one) 14.3866 Tj +-245 TJm +(hundred) 32.6488 Tj +-246 TJm +(bytes) 21.0319 Tj +-246 TJm +(tend) 17.1563 Tj +-245 TJm +(to) 7.75121 Tj +-246 TJm +(get) 12.1748 Tj +-246 TJm +(lar) 10.511 Tj +18 TJm +(ger) 12.7228 Tj +40 TJm +(,) 2.49075 Tj +-246 TJm +(since) 20.474 Tj +-246 TJm +(the) 12.1748 Tj +-246 TJm +(compression) 50.363 Tj +-245 TJm +(mechanism) 45.3815 Tj +-246 TJm +(has) 13.2807 Tj +-246 TJm +(a) 4.42357 Tj +-246 TJm +(c) 4.42357 Tj +1 TJm +(onstant) 28.7831 Tj +-246 TJm +(o) 4.9815 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(erhead) 26.5514 Tj +-246 TJm +(in) 7.75121 Tj +-246 TJm +(th) 7.75121 Tj +1 TJm +(e) 4.42357 Tj +-246 TJm +(re) 7.74125 Tj +15 TJm +(gion) 17.7142 Tj +-246 TJm +(of) 8.29918 Tj +[1 0 0 1 72 50.852] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.854] cm +0 g +0 G +0 g +0 G +[1 0 0 1 43.063 -6.755] cm +0 g +0 G +[1 0 0 1 -496.332 -50.951] cm +[1 0 0 1 0 0] Tm +0 0 Td +539.395 50.951 Td +/F128_0 9.963 Tf +(3) 4.9815 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 7 7 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 -8.911] cm +0 g +0 G +[1 0 0 1 0 8.911] cm +0 g +0 G +0 g +0 G +[1 0 0 1 105.519 -6.755] cm +0 g +0 G +[1 0 0 1 -371.59 -749.245] cm +[1 0 0 1 0 0] Tm +0 0 Td +477.109 749.245 Td +/F128_0 9.963 Tf +(Ho) 12.1748 Tj +25 TJm +(w) 7.19329 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(use) 13.2807 Tj +-250 TJm +(bzip2) 22.1378 Tj +[1 0 0 1 266.071 747.089] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -5.037] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -540 -741.554] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 710.037 Td +/F128_0 9.963 Tf +(50) 9.963 Tj +-264 TJm +(bytes.) 23.5226 Tj +-351 TJm +(Random) 33.7646 Tj +-263 TJm +(data) 16.5984 Tj +-264 TJm +(\(including) 40.9579 Tj +-263 TJm +(the) 12.1748 Tj +-264 TJm +(output) 25.4654 Tj +-264 TJm +(of) 8.29918 Tj +-263 TJm +(most) 19.378 Tj +-264 TJm +(\002le) 12.7327 Tj +-263 TJm +(compressors\)) 53.1227 Tj +-264 TJm +(is) 6.64532 Tj +-264 TJm +(coded) 23.7916 Tj +-263 TJm +(at) 7.19329 Tj +-264 TJm +(about) 22.1378 Tj +-263 TJm +(8.05) 17.4353 Tj +-264 TJm +(bits) 14.3965 Tj +-264 TJm +(per) 12.7228 Tj +-263 TJm +(byte,) 19.647 Tj +-267 TJm +(gi) 7.75121 Tj +25 TJm +(ving) 17.7142 Tj +-264 TJm +(an) 9.40507 Tj +72 698.082 Td +(e) 4.42357 Tj +15 TJm +(xpansion) 35.9764 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(around) 27.6673 Tj +-250 TJm +(0.5%.) 23.2437 Tj +[1 0 0 1 72 695.925] cm +0 g +0 G +[1 0 0 1 0 -9.844] cm +0 g +0 G +[1 0 0 1 -72 -686.081] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 676.283 Td +/F128_0 9.963 Tf +(As) 11.0689 Tj +-268 TJm +(a) 4.42357 Tj +-268 TJm +(self-check) 40.938 Tj +-268 TJm +(for) 11.6169 Tj +-269 TJm +(yo) 9.963 Tj +1 TJm +(ur) 8.29918 Tj +-269 TJm +(protection) 40.4 Tj +1 TJm +(,) 2.49075 Tj +[1 0 0 1 217.273 676.283] cm +0 g +0 G +[1 0 0 1 -217.273 -676.283] cm +[1 0 0 1 0 0] Tm +0 0 Td +217.273 676.283 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 247.161 676.283] cm +0 g +0 G +[1 0 0 1 -247.161 -676.283] cm +[1 0 0 1 0 0] Tm +0 0 Td +249.833 676.283 Td +/F128_0 9.963 Tf +(uses) 17.1563 Tj +-268 TJm +(32-bit) 23.8016 Tj +-268 TJm +(CRCs) 23.8116 Tj +-268 TJm +(to) 7.75121 Tj +-268 TJm +(mak) 17.1563 Tj +10 TJm +(e) 4.42357 Tj +-269 TJm +(sure) 16.5984 Tj +-268 TJm +(that) 14.9445 Tj +-268 TJm +(the) 12.1748 Tj +-268 TJm +(decompressed) 56.4404 Tj +-268 TJm +(v) 4.9815 Tj +15 TJm +(ersion) 24.3496 Tj +-268 TJm +(of) 8.29918 Tj +-268 TJm +(a) 4.42357 Tj +-268 TJm +(\002le) 12.7327 Tj +-269 TJm +(is) 6.64532 Tj +72 664.328 Td +(identical) 34.3126 Tj +-199 TJm +(to) 7.75121 Tj +-200 TJm +(the) 12.1748 Tj +-199 TJm +(original.) 33.4856 Tj +-587 TJm +(This) 17.7142 Tj +-199 TJm +(guards) 26.5614 Tj +-200 TJm +(ag) 9.40507 Tj +5 TJm +(ainst) 18.8201 Tj +-199 TJm +(corruption) 41.5059 Tj +-200 TJm +(of) 8.29918 Tj +-199 TJm +(the) 12.1748 Tj +-200 TJm +(compre) 29.879 Tj +1 TJm +(ssed) 17.1563 Tj +-200 TJm +(data,) 19.0891 Tj +-210 TJm +(and) 14.3866 Tj +-199 TJm +(ag) 9.40507 Tj +5 TJm +(ainst) 18.8201 Tj +-200 TJm +(unde) 19.3681 Tj +1 TJm +(tected) 23.7916 Tj +-200 TJm +(b) 4.9815 Tj +20 TJm +(ugs) 13.8386 Tj +-199 TJm +(in) 7.75121 Tj +[1 0 0 1 510.112 664.328] cm +0 g +0 G +[1 0 0 1 -510.112 -664.328] cm +[1 0 0 1 0 0] Tm +0 0 Td +510.112 664.328 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 540 664.328] cm +0 g +0 G +[1 0 0 1 -540 -664.328] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 652.373 Td +/F128_0 9.963 Tf +(\(hopefully) 41.5059 Tj +-275 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +1 TJm +(ry) 8.29918 Tj +-275 TJm +(unlik) 20.4839 Tj +10 TJm +(ely\).) 17.9832 Tj +-384 TJm +(The) 15.4925 Tj +-275 TJm +(chances) 31.5329 Tj +-274 TJm +(of) 8.29918 Tj +-275 TJm +(data) 16.5984 Tj +-275 TJm +(corr) 16.0404 Tj +1 TJm +(uption) 25.4654 Tj +-275 TJm +(going) 22.6957 Tj +-275 TJm +(undetected) 43.1597 Tj +-274 TJm +(is) 6.64532 Tj +-275 TJm +(microscopic,) 51.1899 Tj +-280 TJm +(about) 22.1378 Tj +-275 TJm +(one) 14.3866 Tj +-275 TJm +(chance) 27.6573 Tj +-274 TJm +(in) 7.75121 Tj +-275 TJm +(four) 16.5984 Tj +72 640.417 Td +(billion) 26.0234 Tj +-279 TJm +(for) 11.6169 Tj +-279 TJm +(each) 18.2522 Tj +-279 TJm +(\002le) 12.7327 Tj +-279 TJm +(processed.) 41.7749 Tj +-795 TJm +(Be) 11.0689 Tj +-279 TJm +(a) 4.42357 Tj +15 TJm +(w) 7.19329 Tj +10 TJm +(are,) 14.6556 Tj +-287 TJm +(thou) 17.7142 Tj +1 TJm +(gh,) 12.4538 Tj +-287 TJm +(that) 14.9445 Tj +-279 TJm +(the) 12.1748 Tj +-279 TJm +(check) 23.2337 Tj +-279 TJm +(occurs) 26.0034 Tj +-279 TJm +(upon) 19.926 Tj +-279 TJm +(decompression,) 62.2588 Tj +-286 TJm +(so) 8.85711 Tj +-280 TJm +(it) 5.53943 Tj +-279 TJm +(can) 13.8286 Tj +-279 TJm +(only) 17.7142 Tj +-279 TJm +(tell) 12.7327 Tj +-279 TJm +(you) 14.9445 Tj +72 628.462 Td +(that) 14.9445 Tj +-237 TJm +(something) 41.5158 Tj +-236 TJm +(is) 6.64532 Tj +-237 TJm +(wrong.) 27.9462 Tj +-611 TJm +(It) 6.08739 Tj +-237 TJm +(can') 17.1463 Tj +18 TJm +(t) 2.76971 Tj +-236 TJm +(help) 17.1563 Tj +-237 TJm +(you) 14.9445 Tj +-237 TJm +(reco) 17.1463 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(er) 7.74125 Tj +-236 TJm +(the) 12.1748 Tj +-237 TJm +(original) 30.9949 Tj +-237 TJm +(uncompressed) 56.9983 Tj +-236 TJm +(data.) 19.0891 Tj +-611 TJm +(Y) 7.19329 Tj +110 TJm +(ou) 9.963 Tj +-237 TJm +(can) 13.8286 Tj +-237 TJm +(use) 13.2807 Tj +[1 0 0 1 458.159 628.462] cm +0 g +0 G +[1 0 0 1 -458.159 -628.462] cm +[1 0 0 1 0 0] Tm +0 0 Td +458.159 628.462 Td +/F130_0 9.963 Tf +(bzip2recover) 71.7336 Tj +[1 0 0 1 529.89 628.462] cm +0 g +0 G +[1 0 0 1 -529.89 -628.462] cm +[1 0 0 1 0 0] Tm +0 0 Td +532.249 628.462 Td +/F128_0 9.963 Tf +(to) 7.75121 Tj +72 616.507 Td +(try) 11.0689 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(reco) 17.1463 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(er) 7.74125 Tj +-250 TJm +(data) 16.5984 Tj +-250 TJm +(from) 19.3681 Tj +-250 TJm +(damag) 26.5614 Tj +1 TJm +(ed) 9.40507 Tj +-250 TJm +(\002les.) 19.0991 Tj +[1 0 0 1 72 614.35] cm +0 g +0 G +[1 0 0 1 0 -9.844] cm +0 g +0 G +[1 0 0 1 -72 -604.506] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 594.708 Td +/F128_0 9.963 Tf +(Return) 27.1193 Tj +-298 TJm +(v) 4.9815 Tj +25 TJm +(alues:) 23.2437 Tj +-406 TJm +(0) 4.9815 Tj +-298 TJm +(f) 3.31768 Tj +1 TJm +(or) 8.29918 Tj +-298 TJm +(a) 4.42357 Tj +-298 TJm +(normal) 28.2252 Tj +-298 TJm +(e) 4.42357 Tj +15 TJm +(xit,) 13.0117 Tj +-310 TJm +(1) 4.9815 Tj +-298 TJm +(for) 11.6169 Tj +-298 TJm +(en) 9.40507 Tj +40 TJm +(vironmental) 48.1512 Tj +-298 TJm +(p) 4.9815 Tj +1 TJm +(roblems) 32.1008 Tj +-298 TJm +(\(\002le) 16.0504 Tj +-298 TJm +(not) 12.7327 Tj +-298 TJm +(found,) 25.7344 Tj +-310 TJm +(in) 7.75121 Tj +40 TJm +(v) 4.9815 Tj +25 TJm +(alid) 14.9445 Tj +-298 TJm +(\003ags,) 21.3109 Tj +-310 TJm +(I/O) 13.2807 Tj +-297 TJm +(errors,) 25.7245 Tj +-310 TJm +(etc.\),) 19.916 Tj +-310 TJm +(2) 4.9815 Tj +-298 TJm +(to) 7.75121 Tj +72 582.753 Td +(indicate) 31.5429 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(corrupt) 28.7731 Tj +-250 TJm +(compresse) 42.0538 Tj +1 TJm +(d) 4.9815 Tj +-250 TJm +(\002le,) 15.2235 Tj +-250 TJm +(3) 4.9815 Tj +-250 TJm +(for) 11.6169 Tj +-250 TJm +(an) 9.40507 Tj +-250 TJm +(internal) 30.437 Tj +-250 TJm +(consistenc) 41.5059 Tj +15 TJm +(y) 4.9815 Tj +-250 TJm +(error) 19.3581 Tj +-250 TJm +(\(e) 7.74125 Tj +15 TJm +(g,) 7.47225 Tj +-250 TJm +(b) 4.9815 Tj +20 TJm +(ug\)) 13.2807 Tj +-250 TJm +(which) 24.3496 Tj +-250 TJm +(ca) 8.84714 Tj +1 TJm +(used) 18.2622 Tj +[1 0 0 1 443.065 582.753] cm +0 g +0 G +[1 0 0 1 -443.065 -582.753] cm +[1 0 0 1 0 0] Tm +0 0 Td +443.065 582.753 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 472.953 582.753] cm +0 g +0 G +[1 0 0 1 -472.953 -582.753] cm +[1 0 0 1 0 0] Tm +0 0 Td +475.444 582.753 Td +/F128_0 9.963 Tf +(to) 7.75121 Tj +-250 TJm +(panic.) 24.0706 Tj +[1 0 0 1 72 580.596] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.844] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -570.752] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 548.118 Td +/F121_0 20.659 Tf +(2.4.) 34.4592 Tj +-278 TJm +(OPTIONS) 92.9862 Tj +[1 0 0 1 72 547.86] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.844] cm +0 g +0 G +[1 0 0 1 0 -9.844] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -528.172] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 516.475 Td +/F130_0 9.963 Tf +(-c) 11.9556 Tj +-600 TJm +(--stdout) 47.8224 Tj +[1 0 0 1 137.753 516.475] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -68.244 -0.209] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -516.266] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 504.52 Td +/F128_0 9.963 Tf +(Compress) 39.852 Tj +-250 TJm +(or) 8.29918 Tj +-250 TJm +(decompress) 47.0353 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(s) 3.87561 Tj +1 TJm +(tandard) 29.879 Tj +-250 TJm +(output.) 27.9562 Tj +[1 0 0 1 72 502.363] cm +0 g +0 G +0 g +0 G +[1 0 0 1 0 -3.866] cm +0 g +0 G +[1 0 0 1 0 -9.845] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -488.652] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 478.854 Td +/F130_0 9.963 Tf +(-d) 11.9556 Tj +-600 TJm +(--decompress) 71.7336 Tj +[1 0 0 1 161.664 478.854] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -92.154 -1.564] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -477.29] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 466.899 Td +/F128_0 9.963 Tf +(F) 5.53943 Tj +15 TJm +(orce) 17.1463 Tj +-296 TJm +(decompression.) 62.2588 Tj +[1 0 0 1 200.214 466.899] cm +0 g +0 G +[1 0 0 1 -200.214 -466.899] cm +[1 0 0 1 0 0] Tm +0 0 Td +200.214 466.899 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 230.102 466.899] cm +0 g +0 G +[1 0 0 1 -230.102 -466.899] cm +[1 0 0 1 0 0] Tm +0 0 Td +230.102 466.899 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 235.659 466.899] cm +0 g +0 G +[1 0 0 1 -235.659 -466.899] cm +[1 0 0 1 0 0] Tm +0 0 Td +235.659 466.899 Td +/F130_0 9.963 Tf +(bunzip2) 41.8446 Tj +[1 0 0 1 277.502 466.899] cm +0 g +0 G +[1 0 0 1 -277.502 -466.899] cm +[1 0 0 1 0 0] Tm +0 0 Td +280.454 466.899 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 297.791 466.899] cm +0 g +0 G +[1 0 0 1 -297.791 -466.899] cm +[1 0 0 1 0 0] Tm +0 0 Td +297.791 466.899 Td +/F130_0 9.963 Tf +(bzcat) 29.889 Tj +[1 0 0 1 327.679 466.899] cm +0 g +0 G +[1 0 0 1 -327.679 -466.899] cm +[1 0 0 1 0 0] Tm +0 0 Td +330.631 466.899 Td +/F128_0 9.963 Tf +(are) 12.1648 Tj +-296 TJm +(really) 22.6858 Tj +-296 TJm +(the) 12.1748 Tj +-296 TJm +(same) 20.474 Tj +-297 TJm +(program) 33.7546 Tj +1 TJm +(,) 2.49075 Tj +-308 TJm +(and) 14.3866 Tj +-297 TJm +(t) 2.76971 Tj +1 TJm +(he) 9.40507 Tj +-297 TJm +(decision) 33.2067 Tj +-296 TJm +(about) 22.1378 Tj +108 454.944 Td +(what) 19.3681 Tj +-303 TJm +(actions) 28.2252 Tj +-303 TJm +(to) 7.75121 Tj +-303 TJm +(tak) 12.1748 Tj +10 TJm +(e) 4.42357 Tj +-303 TJm +(is) 6.64532 Tj +-303 TJm +(done) 19.3681 Tj +-303 TJm +(on) 9.963 Tj +-303 TJm +(the) 12.1748 Tj +-303 TJm +(basis) 19.926 Tj +-303 TJm +(of) 8.29918 Tj +-303 TJm +(which) 24.3496 Tj +-303 TJm +(name) 21.5799 Tj +-303 TJm +(is) 6.64532 Tj +-303 TJm +(used.) 20.7529 Tj +-939 TJm +(T) 6.08739 Tj +1 TJm +(his) 11.6268 Tj +-304 TJm +(\003) 5.53943 Tj +1 TJm +(ag) 9.40507 Tj +-304 TJm +(o) 4.9815 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +1 TJm +(rrides) 22.6858 Tj +-303 TJm +(that) 14.9445 Tj +-303 TJm +(mechanism,) 47.8722 Tj +-317 TJm +(and) 14.3866 Tj +108 442.989 Td +(forces) 24.3396 Tj +-250 TJm +(bzip2) 22.1378 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(decompress.) 49.5261 Tj +[1 0 0 1 72 440.832] cm +0 g +0 G +0 g +0 G +[1 0 0 1 0 -3.867] cm +0 g +0 G +[1 0 0 1 0 -9.844] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -427.121] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 417.323 Td +/F130_0 9.963 Tf +(-z) 11.9556 Tj +-600 TJm +(--compress) 59.778 Tj +[1 0 0 1 149.709 417.323] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -80.199 -1.564] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -415.759] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 405.368 Td +/F128_0 9.963 Tf +(The) 15.4925 Tj +-250 TJm +(complement) 49.2571 Tj +-250 TJm +(to) 7.75121 Tj +[1 0 0 1 187.969 405.368] cm +0 g +0 G +[1 0 0 1 -187.969 -405.368] cm +[1 0 0 1 0 0] Tm +0 0 Td +187.969 405.368 Td +/F130_0 9.963 Tf +(-d) 11.9556 Tj +[1 0 0 1 199.924 405.368] cm +0 g +0 G +[1 0 0 1 -199.924 -405.368] cm +[1 0 0 1 0 0] Tm +0 0 Td +199.924 405.368 Td +/F128_0 9.963 Tf +(:) 2.76971 Tj +-310 TJm +(forces) 24.3396 Tj +-250 TJm +(compression,) 52.8537 Tj +-250 TJm +(re) 7.74125 Tj +15 TJm +(g) 4.9815 Tj +5 TJm +(ardles) 23.7916 Tj +1 TJm +(s) 3.87561 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(in) 7.75121 Tj +40 TJm +(v) 4.9815 Tj +20 TJm +(okation) 29.889 Tj +-250 TJm +(name.) 24.0706 Tj +[1 0 0 1 72 403.211] cm +0 g +0 G +0 g +0 G +[1 0 0 1 0 -3.867] cm +0 g +0 G +[1 0 0 1 0 -9.844] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -389.5] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 379.702 Td +/F130_0 9.963 Tf +(-t) 11.9556 Tj +-600 TJm +(--test) 35.8668 Tj +[1 0 0 1 125.798 379.702] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -56.289 -0.209] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -379.493] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 367.747 Td +/F128_0 9.963 Tf +(Check) 25.4555 Tj +-270 TJm +(inte) 14.9445 Tj +15 TJm +(grity) 18.8201 Tj +-271 TJm +(of) 8.29918 Tj +-270 TJm +(the) 12.1748 Tj +-270 TJm +(speci\002ed) 35.4185 Tj +-271 TJm +(\002) 5.53943 Tj +1 TJm +(le\(s\),) 20.195 Tj +-276 TJm +(b) 4.9815 Tj +20 TJm +(ut) 7.75121 Tj +-270 TJm +(don') 18.2622 Tj +18 TJm +(t) 2.76971 Tj +-271 TJm +(decom) 26.5614 Tj +1 TJm +(press) 20.474 Tj +-271 TJm +(them.) 22.4168 Tj +-742 TJm +(This) 17.7142 Tj +-270 TJm +(really) 22.6858 Tj +-271 TJm +(performs) 35.9664 Tj +-270 TJm +(a) 4.42357 Tj +-270 TJm +(trial) 16.0504 Tj +-271 TJm +(decompres-) 46.4774 Tj +108 355.792 Td +(sion) 16.6083 Tj +-250 TJm +(and) 14.3866 Tj +-250 TJm +(thro) 16.0504 Tj +25 TJm +(ws) 11.0689 Tj +-250 TJm +(a) 4.42357 Tj +15 TJm +(w) 7.19329 Tj +10 TJm +(ay) 9.40507 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(resul) 19.3681 Tj +1 TJm +(t.) 5.26046 Tj +[1 0 0 1 72 353.635] cm +0 g +0 G +0 g +0 G +[1 0 0 1 0 -3.867] cm +0 g +0 G +[1 0 0 1 0 -9.844] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -339.924] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 330.126 Td +/F130_0 9.963 Tf +(-f) 11.9556 Tj +-600 TJm +(--force) 41.8446 Tj +[1 0 0 1 131.776 330.126] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -62.266 -0.209] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -329.917] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 318.171 Td +/F128_0 9.963 Tf +(F) 5.53943 Tj +15 TJm +(orce) 17.1463 Tj +-338 TJm +(o) 4.9815 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(erwrite) 28.2152 Tj +-338 TJm +(of) 8.29918 Tj +-339 TJm +(output) 25.4654 Tj +-338 TJm +(\002les.) 19.0991 Tj +-1149 TJm +(Normally) 38.1882 Tj +65 TJm +(,) 2.49075 Tj +[1 0 0 1 289.831 318.171] cm +0 g +0 G +[1 0 0 1 -289.831 -318.171] cm +[1 0 0 1 0 0] Tm +0 0 Td +289.831 318.171 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 319.719 318.171] cm +0 g +0 G +[1 0 0 1 -319.719 -318.171] cm +[1 0 0 1 0 0] Tm +0 0 Td +323.089 318.171 Td +/F128_0 9.963 Tf +(will) 15.5024 Tj +-338 TJm +(not) 12.7327 Tj +-338 TJm +(o) 4.9815 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(erwrite) 28.2152 Tj +-339 TJm +(e) 4.42357 Tj +15 TJm +(xisti) 17.1662 Tj +1 TJm +(ng) 9.963 Tj +-339 TJm +(output) 25.4654 Tj +-338 TJm +(\002les.) 19.0991 Tj +-1150 TJm +(Also) 18.8201 Tj +-338 TJm +(forces) 24.3396 Tj +[1 0 0 1 108 306.216] cm +0 g +0 G +[1 0 0 1 -108 -306.216] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 306.216 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 137.888 306.216] cm +0 g +0 G +[1 0 0 1 -137.888 -306.216] cm +[1 0 0 1 0 0] Tm +0 0 Td +140.379 306.216 Td +/F128_0 9.963 Tf +(to) 7.75121 Tj +-250 TJm +(break) 22.1278 Tj +-250 TJm +(hard) 17.7043 Tj +-250 TJm +(links) 19.378 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(\002les) 16.6083 Tj +1 TJm +(,) 2.49075 Tj +-250 TJm +(which) 24.3496 Tj +-250 TJm +(it) 5.53943 Tj +-250 TJm +(otherwise) 38.7361 Tj +-250 TJm +(w) 7.19329 Tj +10 TJm +(ouldn') 26.0134 Tj +18 TJm +(t) 2.76971 Tj +-250 TJm +(do.) 12.4538 Tj +[1 0 0 1 72 304.652] cm +0 g +0 G +[1 0 0 1 0 -9.845] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -294.807] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 284.416 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 137.888 284.416] cm +0 g +0 G +[1 0 0 1 -137.888 -284.416] cm +[1 0 0 1 0 0] Tm +0 0 Td +141.211 284.416 Td +/F128_0 9.963 Tf +(normally) 35.9764 Tj +-333 TJm +(declines) 32.6488 Tj +-334 TJm +(to) 7.75121 Tj +-333 TJm +(decompress) 47.0353 Tj +-334 TJm +(\002les) 16.6083 Tj +-333 TJm +(which) 24.3496 Tj +-333 TJm +(don') 18.2622 Tj +18 TJm +(t) 2.76971 Tj +-334 TJm +(ha) 9.40507 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-333 TJm +(the) 12.1748 Tj +-334 TJm +(correct) 27.6573 Tj +-333 TJm +(magic) 24.3496 Tj +-334 TJm +(header) 26.5514 Tj +-333 TJm +(bytes.) 23.5226 Tj +-561 TJm +(If) 6.63536 Tj +-333 TJm +(forced) 25.4455 Tj +108 272.461 Td +(\() 3.31768 Tj +[1 0 0 1 111.317 272.461] cm +0 g +0 G +[1 0 0 1 -111.317 -272.461] cm +[1 0 0 1 0 0] Tm +0 0 Td +111.317 272.461 Td +/F130_0 9.963 Tf +(-f) 11.9556 Tj +[1 0 0 1 123.273 272.461] cm +0 g +0 G +[1 0 0 1 -123.273 -272.461] cm +[1 0 0 1 0 0] Tm +0 0 Td +123.273 272.461 Td +/F128_0 9.963 Tf +(\),) 5.80843 Tj +-250 TJm +(ho) 9.963 Tj +25 TJm +(we) 11.6169 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(er) 7.74125 Tj +40 TJm +(,) 2.49075 Tj +-250 TJm +(it) 5.53943 Tj +-250 TJm +(will) 15.5024 Tj +-250 TJm +(pass) 17.1563 Tj +-250 TJm +(such) 18.2622 Tj +-249 TJm +(\002les) 16.6083 Tj +-250 TJm +(through) 30.9949 Tj +-250 TJm +(unmodi\002ed.) 47.8822 Tj +-310 TJm +(This) 17.7142 Tj +-250 TJm +(is) 6.64532 Tj +-250 TJm +(ho) 9.963 Tj +25 TJm +(w) 7.19329 Tj +-250 TJm +(GNU) 21.5799 Tj +[1 0 0 1 412.585 272.461] cm +0 g +0 G +[1 0 0 1 -412.585 -272.461] cm +[1 0 0 1 0 0] Tm +0 0 Td +412.585 272.461 Td +/F130_0 9.963 Tf +(gzip) 23.9112 Tj +[1 0 0 1 436.496 272.461] cm +0 g +0 G +[1 0 0 1 -436.496 -272.461] cm +[1 0 0 1 0 0] Tm +0 0 Td +438.986 272.461 Td +/F128_0 9.963 Tf +(beha) 18.8101 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(es.) 10.7899 Tj +[1 0 0 1 72 270.304] cm +0 g +0 G +0 g +0 G +[1 0 0 1 0 -3.866] cm +0 g +0 G +[1 0 0 1 0 -9.844] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -256.594] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 246.795 Td +/F130_0 9.963 Tf +(-k) 11.9556 Tj +-600 TJm +(--keep) 35.8668 Tj +[1 0 0 1 125.798 246.795] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -56.289 -1.564] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -245.231] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 234.84 Td +/F128_0 9.963 Tf +(K) 7.19329 Tj +25 TJm +(eep) 13.8286 Tj +-250 TJm +(\(don') 21.5799 Tj +18 TJm +(t) 2.76971 Tj +-250 TJm +(delete\)) 27.1093 Tj +-250 TJm +(input) 20.4839 Tj +-250 TJm +(\002le) 12.7327 Tj +1 TJm +(s) 3.87561 Tj +-250 TJm +(during) 26.0134 Tj +-250 TJm +(compression) 50.363 Tj +-250 TJm +(or) 8.29918 Tj +-250 TJm +(decompression.) 62.2588 Tj +[1 0 0 1 72 232.683] cm +0 g +0 G +0 g +0 G +[1 0 0 1 0 -3.866] cm +0 g +0 G +[1 0 0 1 0 -9.844] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -218.973] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 209.175 Td +/F130_0 9.963 Tf +(-s) 11.9556 Tj +-600 TJm +(--small) 41.8446 Tj +[1 0 0 1 131.776 209.175] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -62.266 -0.21] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -208.965] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 197.219 Td +/F128_0 9.963 Tf +(Reduce) 29.879 Tj +-347 TJm +(memory) 33.2067 Tj +-346 TJm +(usage,) 25.1765 Tj +-371 TJm +(for) 11.6169 Tj +-347 TJm +(compression,) 52.8537 Tj +-371 TJm +(decompression) 59.768 Tj +-346 TJm +(and) 14.3866 Tj +-347 TJm +(testing.) 29.0621 Tj +-1201 TJm +(Files) 19.378 Tj +-347 TJm +(are) 12.1648 Tj +-346 TJm +(decompressed) 56.4404 Tj +-347 TJm +(and) 14.3866 Tj +-347 TJm +(tested) 23.2437 Tj +108 185.264 Td +(using) 21.5898 Tj +-388 TJm +(a) 4.42357 Tj +-388 TJm +(modi\002ed) 35.4284 Tj +-388 TJm +(algorithm) 38.7461 Tj +-388 TJm +(which) 24.3496 Tj +-388 TJm +(only) 17.7142 Tj +-388 TJm +(requires) 32.0908 Tj +-388 TJm +(2.5) 12.4538 Tj +-388 TJm +(bytes) 21.0319 Tj +-388 TJm +(per) 12.7228 Tj +-388 TJm +(block) 22.1378 Tj +-388 TJm +(byte.) 19.647 Tj +-1449 TJm +(This) 17.7142 Tj +-388 TJm +(means) 25.4555 Tj +-388 TJm +(an) 9.40507 Tj +15 TJm +(y) 4.9815 Tj +-388 TJm +(\002le) 12.7327 Tj +-388 TJm +(can) 13.8286 Tj +-389 TJm +(be) 9.40507 Tj +108 173.309 Td +(decompressed) 56.4404 Tj +-250 TJm +(in) 7.75121 Tj +-250 TJm +(2300k) 24.9075 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(mem) 19.926 Tj +1 TJm +(ory) 13.2807 Tj +65 TJm +(,) 2.49075 Tj +-250 TJm +(albeit) 22.1378 Tj +-250 TJm +(at) 7.19329 Tj +-250 TJm +(about) 22.1378 Tj +-250 TJm +(half) 15.4925 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(normal) 28.2252 Tj +-250 TJm +(speed.) 25.1765 Tj +[1 0 0 1 72 171.152] cm +0 g +0 G +[1 0 0 1 0 -9.844] cm +0 g +0 G +[1 0 0 1 -72 -161.308] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 151.51 Td +/F128_0 9.963 Tf +(During) 28.2252 Tj +-251 TJm +(compression,) 52.8537 Tj +[1 0 0 1 194.09 151.51] cm +0 g +0 G +[1 0 0 1 -194.09 -151.51] cm +[1 0 0 1 0 0] Tm +0 0 Td +194.09 151.51 Td +/F130_0 9.963 Tf +(-s) 11.9556 Tj +[1 0 0 1 206.046 151.51] cm +0 g +0 G +[1 0 0 1 -206.046 -151.51] cm +[1 0 0 1 0 0] Tm +0 0 Td +208.551 151.51 Td +/F128_0 9.963 Tf +(selects) 26.5614 Tj +-251 TJm +(a) 4.42357 Tj +-252 TJm +(block) 22.1378 Tj +-251 TJm +(size) 15.4925 Tj +-252 TJm +(of) 8.29918 Tj +-251 TJm +(200k,) 22.4168 Tj +-252 TJm +(which) 24.3496 Tj +-251 TJm +(limits) 22.7057 Tj +-252 TJm +(memory) 33.2067 Tj +-251 TJm +(use) 13.2807 Tj +-252 TJm +(to) 7.75121 Tj +-251 TJm +(around) 27.6673 Tj +-251 TJm +(the) 12.1748 Tj +-252 TJm +(same) 20.474 Tj +-251 TJm +(\002gure,) 25.7344 Tj +-252 TJm +(at) 7.19329 Tj +108 139.555 Td +(the) 12.1748 Tj +-287 TJm +(e) 4.42357 Tj +15 TJm +(xpense) 27.6673 Tj +-287 TJm +(of) 8.29918 Tj +-287 TJm +(your) 18.2622 Tj +-287 TJm +(compression) 50.363 Tj +-287 TJm +(ratio.) 20.7529 Tj +-843 TJm +(In) 8.29918 Tj +-287 TJm +(short,) 22.4168 Tj +-297 TJm +(if) 6.08739 Tj +-287 TJm +(your) 18.2622 Tj +-287 TJm +(machine) 33.7546 Tj +-287 TJm +(is) 6.64532 Tj +-287 TJm +(lo) 7.75121 Tj +25 TJm +(w) 7.19329 Tj +-287 TJm +(on) 9.963 Tj +-287 TJm +(memory) 33.2067 Tj +-287 TJm +(\(8) 8.29918 Tj +-288 TJm +(m) 7.75121 Tj +1 TJm +(e) 4.42357 Tj +15 TJm +(g) 4.9815 Tj +5 TJm +(abytes) 25.4555 Tj +-288 TJm +(or) 8.29918 Tj +-287 TJm +(less\),) 20.7529 Tj +108 127.599 Td +(use) 13.2807 Tj +[1 0 0 1 123.771 127.599] cm +0 g +0 G +[1 0 0 1 -123.771 -127.599] cm +[1 0 0 1 0 0] Tm +0 0 Td +123.771 127.599 Td +/F130_0 9.963 Tf +(-s) 11.9556 Tj +[1 0 0 1 135.726 127.599] cm +0 g +0 G +[1 0 0 1 -135.726 -127.599] cm +[1 0 0 1 0 0] Tm +0 0 Td +138.217 127.599 Td +/F128_0 9.963 Tf +(for) 11.6169 Tj +-250 TJm +(e) 4.42357 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(erything.) 35.6974 Tj +-620 TJm +(See) 14.3866 Tj +[1 0 0 1 220.079 127.599] cm +0 0 1 rg +0 0 1 RG +[1 0 0 1 -220.079 -127.599] cm +[1 0 0 1 0 0] Tm +0 0 Td +220.079 127.599 Td +/F128_0 9.963 Tf +(MEMOR) 37.6402 Tj +65 TJm +(Y) 7.19329 Tj +-250 TJm +(MAN) 23.2437 Tj +35 TJm +(A) 7.19329 Tj +40 TJm +(GEMENT) 41.5059 Tj +[1 0 0 1 337.946 127.599] cm +0 g +0 G +0 0 1 rg +0 0 1 RG +0 0 1 rg +0 0 1 RG +[1 0 0 1 -337.946 -127.599] cm +[1 0 0 1 0 0] Tm +0 0 Td +340.437 127.599 Td +/F128_0 9.963 Tf +([5]) 11.6169 Tj +[1 0 0 1 352.053 127.599] cm +0 0 1 rg +0 0 1 RG +0 g +0 G +[1 0 0 1 -352.053 -127.599] cm +[1 0 0 1 0 0] Tm +0 0 Td +354.544 127.599 Td +/F128_0 9.963 Tf +(belo) 17.1563 Tj +25 TJm +(w) 7.19329 Tj +65 TJm +(.) 2.49075 Tj +[1 0 0 1 72 125.443] cm +0 g +0 G +0 g +0 G +[1 0 0 1 0 -3.867] cm +0 g +0 G +[1 0 0 1 0 -9.844] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -111.732] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 101.934 Td +/F130_0 9.963 Tf +(-q) 11.9556 Tj +-600 TJm +(--quiet) 41.8446 Tj +[1 0 0 1 131.776 101.934] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -62.266 -1.564] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -100.37] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 89.979 Td +/F128_0 9.963 Tf +(Suppress) 35.9764 Tj +-221 TJm +(non-) 18.2622 Tj +1 TJm +(essential) 34.3126 Tj +-221 TJm +(w) 7.19329 Tj +10 TJm +(arning) 25.4555 Tj +-221 TJm +(mess) 19.926 Tj +1 TJm +(ages.) 20.195 Tj +-301 TJm +(Messa) 25.4555 Tj +1 TJm +(ges) 13.2807 Tj +-221 TJm +(pertaining) 40.4 Tj +-221 TJm +(to) 7.75121 Tj +-220 TJm +(I/O) 13.2807 Tj +-221 TJm +(errors) 23.2337 Tj +-221 TJm +(and) 14.3866 Tj +-220 TJm +(other) 20.474 Tj +-221 TJm +(critical) 27.6673 Tj +-220 TJm +(e) 4.42357 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(ents) 16.0504 Tj +-221 TJm +(will) 15.5024 Tj +-221 TJm +(not) 12.7327 Tj +108 78.023 Td +(be) 9.40507 Tj +-250 TJm +(suppressed.) 46.2084 Tj +[1 0 0 1 72 75.867] cm +0 g +0 G +0 g +0 G +[1 0 0 1 0 -3.867] cm +0 g +0 G +[1 0 0 1 0 -21.148] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.754] cm +0 g +0 G +0 g +0 G +[1 0 0 1 43.063 -6.754] cm +0 g +0 G +[1 0 0 1 -496.332 -50.852] cm +[1 0 0 1 0 0] Tm +0 0 Td +539.395 50.852 Td +/F128_0 9.963 Tf +(4) 4.9815 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 8 8 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 -8.911] cm +0 g +0 G +[1 0 0 1 0 8.911] cm +0 g +0 G +0 g +0 G +[1 0 0 1 105.519 -6.755] cm +0 g +0 G +[1 0 0 1 -371.59 -749.245] cm +[1 0 0 1 0 0] Tm +0 0 Td +477.109 749.245 Td +/F128_0 9.963 Tf +(Ho) 12.1748 Tj +25 TJm +(w) 7.19329 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(use) 13.2807 Tj +-250 TJm +(bzip2) 22.1378 Tj +[1 0 0 1 266.071 747.089] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -5.037] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -468 -21.554] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -720] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 710.037 Td +/F130_0 9.963 Tf +(-v) 11.9556 Tj +-600 TJm +(--verbose) 53.8002 Tj +[1 0 0 1 143.731 710.037] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -74.222 -0.209] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -709.828] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 698.082 Td +/F128_0 9.963 Tf +(V) 7.19329 Tj +111 TJm +(erbose) 26.0034 Tj +-322 TJm +(mode) 22.1378 Tj +-323 TJm +(--) 6.63536 Tj +-323 TJm +(sho) 13.8386 Tj +25 TJm +(w) 7.19329 Tj +-322 TJm +(the) 12.1748 Tj +-323 TJm +(compres) 33.7546 Tj +1 TJm +(sion) 16.6083 Tj +-323 TJm +(ratio) 18.2622 Tj +-323 TJm +(for) 11.6169 Tj +-322 TJm +(each) 18.2522 Tj +-323 TJm +(\002le) 12.7327 Tj +-322 TJm +(processed.) 41.7749 Tj +-1056 TJm +(Further) 29.3311 Tj +[1 0 0 1 430.015 698.082] cm +0 g +0 G +[1 0 0 1 -430.015 -698.082] cm +[1 0 0 1 0 0] Tm +0 0 Td +430.015 698.082 Td +/F130_0 9.963 Tf +(-v) 11.9556 Tj +[1 0 0 1 441.97 698.082] cm +0 g +0 G +[1 0 0 1 -441.97 -698.082] cm +[1 0 0 1 0 0] Tm +0 0 Td +441.97 698.082 Td +/F128_0 9.963 Tf +(') 3.31768 Tj +55 TJm +(s) 3.87561 Tj +-323 TJm +(incre) 19.916 Tj +1 TJm +(ase) 12.7228 Tj +-323 TJm +(the) 12.1748 Tj +-323 TJm +(v) 4.9815 Tj +15 TJm +(erbos) 21.5799 Tj +1 TJm +(ity) 10.5209 Tj +108 686.127 Td +(le) 7.19329 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(el,) 9.68404 Tj +-250 TJm +(spe) 13.2807 Tj +25 TJm +(wing) 19.926 Tj +-250 TJm +(out) 12.7327 Tj +-250 TJm +(lots) 14.3965 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(info) 16.0504 Tj +1 TJm +(rmation) 30.9949 Tj +-250 TJm +(which) 24.3496 Tj +-250 TJm +(is) 6.64532 Tj +-250 TJm +(primarily) 37.0823 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(interest) 29.3311 Tj +-250 TJm +(for) 11.6169 Tj +-250 TJm +(diagnostic) 40.9579 Tj +-250 TJm +(pu) 9.963 Tj +1 TJm +(rposes.) 27.9462 Tj +[1 0 0 1 72 683.97] cm +0 g +0 G +0 g +0 G +[1 0 0 1 0 -3.985] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -670.023] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 660.224 Td +/F130_0 9.963 Tf +(-L) 11.9556 Tj +-600 TJm +(--license) 53.8002 Tj +-600 TJm +(-V) 11.9556 Tj +-600 TJm +(--version) 53.8002 Tj +[1 0 0 1 221.44 660.224] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -151.93 -0.209] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -660.015] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 648.269 Td +/F128_0 9.963 Tf +(Display) 30.9949 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(softw) 22.1378 Tj +10 TJm +(are) 12.1648 Tj +-250 TJm +(v) 4.9815 Tj +15 TJm +(ersion) 24.3496 Tj +1 TJm +(,) 2.49075 Tj +-250 TJm +(license) 27.6673 Tj +-250 TJm +(terms) 22.1378 Tj +-250 TJm +(and) 14.3866 Tj +-250 TJm +(conditions.) 44.0066 Tj +[1 0 0 1 72 646.112] cm +0 g +0 G +0 g +0 G +[1 0 0 1 0 -3.985] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -632.165] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 622.366 Td +/F130_0 9.963 Tf +(-1) 11.9556 Tj +[1 0 0 1 83.955 622.366] cm +0 g +0 G +[1 0 0 1 -83.955 -622.366] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.446 622.366 Td +/F128_0 9.963 Tf +(\(or) 11.6169 Tj +[1 0 0 1 100.553 622.366] cm +0 g +0 G +[1 0 0 1 -100.553 -622.366] cm +[1 0 0 1 0 0] Tm +0 0 Td +100.553 622.366 Td +/F130_0 9.963 Tf +(--fast) 35.8668 Tj +[1 0 0 1 136.418 622.366] cm +0 g +0 G +[1 0 0 1 -136.418 -622.366] cm +[1 0 0 1 0 0] Tm +0 0 Td +136.418 622.366 Td +/F128_0 9.963 Tf +(\)) 3.31768 Tj +-250 TJm +(to) 7.75121 Tj +[1 0 0 1 152.468 622.366] cm +0 g +0 G +[1 0 0 1 -152.468 -622.366] cm +[1 0 0 1 0 0] Tm +0 0 Td +152.468 622.366 Td +/F130_0 9.963 Tf +(-9) 11.9556 Tj +[1 0 0 1 164.423 622.366] cm +0 g +0 G +[1 0 0 1 -164.423 -622.366] cm +[1 0 0 1 0 0] Tm +0 0 Td +166.914 622.366 Td +/F128_0 9.963 Tf +(\(or) 11.6169 Tj +[1 0 0 1 181.021 622.366] cm +0 g +0 G +[1 0 0 1 -181.021 -622.366] cm +[1 0 0 1 0 0] Tm +0 0 Td +181.021 622.366 Td +/F130_0 9.963 Tf +(-best) 29.889 Tj +[1 0 0 1 210.909 622.366] cm +0 g +0 G +[1 0 0 1 -210.909 -622.366] cm +[1 0 0 1 0 0] Tm +0 0 Td +210.909 622.366 Td +/F128_0 9.963 Tf +(\)) 3.31768 Tj +[1 0 0 1 214.226 622.366] cm +0 g +0 G +[1 0 0 1 -142.226 -1.783] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -620.583] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 610.411 Td +/F128_0 9.963 Tf +(Set) 12.7327 Tj +-288 TJm +(the) 12.1748 Tj +-288 TJm +(block) 22.1378 Tj +-289 TJm +(size) 15.4925 Tj +-288 TJm +(to) 7.75121 Tj +-288 TJm +(100) 14.9445 Tj +-288 TJm +(k,) 7.47225 Tj +-298 TJm +(200) 14.9445 Tj +-288 TJm +(k) 4.9815 Tj +-289 TJm +(...) 7.47225 Tj +-849 TJm +(900) 14.9445 Tj +-288 TJm +(k) 4.9815 Tj +-289 TJm +(when) 21.5799 Tj +-288 TJm +(compressing.) 52.8537 Tj +-849 TJm +(Has) 15.4925 Tj +-289 TJm +(no) 9.963 Tj +-288 TJm +(ef) 7.74125 Tj +25 TJm +(fect) 14.9345 Tj +-288 TJm +(when) 21.5799 Tj +-288 TJm +(decompressing.) 62.2588 Tj +-850 TJm +(See) 14.3866 Tj +[1 0 0 1 108 598.456] cm +0 0 1 rg +0 0 1 RG +[1 0 0 1 -108 -598.456] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 598.456 Td +/F128_0 9.963 Tf +(MEMOR) 37.6402 Tj +65 TJm +(Y) 7.19329 Tj +-297 TJm +(MAN) 23.2437 Tj +35 TJm +(A) 7.19329 Tj +40 TJm +(GEMENT) 41.5059 Tj +[1 0 0 1 226.338 598.456] cm +0 g +0 G +0 0 1 rg +0 0 1 RG +0 0 1 rg +0 0 1 RG +[1 0 0 1 -226.338 -598.456] cm +[1 0 0 1 0 0] Tm +0 0 Td +229.3 598.456 Td +/F128_0 9.963 Tf +([5]) 11.6169 Tj +[1 0 0 1 240.916 598.456] cm +0 0 1 rg +0 0 1 RG +0 g +0 G +[1 0 0 1 -240.916 -598.456] cm +[1 0 0 1 0 0] Tm +0 0 Td +243.878 598.456 Td +/F128_0 9.963 Tf +(belo) 17.1563 Tj +25 TJm +(w) 7.19329 Tj +65 TJm +(.) 2.49075 Tj +-904 TJm +(The) 15.4925 Tj +[1 0 0 1 297.278 598.456] cm +0 g +0 G +[1 0 0 1 -297.278 -598.456] cm +[1 0 0 1 0 0] Tm +0 0 Td +297.278 598.456 Td +/F130_0 9.963 Tf +(--fast) 35.8668 Tj +[1 0 0 1 333.144 598.456] cm +0 g +0 G +[1 0 0 1 -333.144 -598.456] cm +[1 0 0 1 0 0] Tm +0 0 Td +336.106 598.456 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 353.454 598.456] cm +0 g +0 G +[1 0 0 1 -353.454 -598.456] cm +[1 0 0 1 0 0] Tm +0 0 Td +353.454 598.456 Td +/F130_0 9.963 Tf +(--best) 35.8668 Tj +[1 0 0 1 389.319 598.456] cm +0 g +0 G +[1 0 0 1 -389.319 -598.456] cm +[1 0 0 1 0 0] Tm +0 0 Td +392.281 598.456 Td +/F128_0 9.963 Tf +(aliases) 26.5614 Tj +-297 TJm +(are) 12.1648 Tj +-297 TJm +(primarily) 37.0823 Tj +-297 TJm +(for) 11.6169 Tj +-298 TJm +(GNU) 21.5799 Tj +[1 0 0 1 516.09 598.456] cm +0 g +0 G +[1 0 0 1 -516.09 -598.456] cm +[1 0 0 1 0 0] Tm +0 0 Td +516.09 598.456 Td +/F130_0 9.963 Tf +(gzip) 23.9112 Tj +[1 0 0 1 540 598.456] cm +0 g +0 G +[1 0 0 1 -540 -598.456] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 586.501 Td +/F128_0 9.963 Tf +(compatibility) 53.1426 Tj +65 TJm +(.) 2.49075 Tj +-356 TJm +(In) 8.29918 Tj +-265 TJm +(particular) 38.1782 Tj +40 TJm +(,) 2.49075 Tj +[1 0 0 1 220.423 586.501] cm +0 g +0 G +[1 0 0 1 -220.423 -586.501] cm +[1 0 0 1 0 0] Tm +0 0 Td +220.423 586.501 Td +/F130_0 9.963 Tf +(--fast) 35.8668 Tj +[1 0 0 1 256.288 586.501] cm +0 g +0 G +[1 0 0 1 -256.288 -586.501] cm +[1 0 0 1 0 0] Tm +0 0 Td +258.932 586.501 Td +/F128_0 9.963 Tf +(doesn') 26.5614 Tj +18 TJm +(t) 2.76971 Tj +-265 TJm +(mak) 17.1563 Tj +10 TJm +(e) 4.42357 Tj +-265 TJm +(things) 24.3595 Tj +-266 TJm +(signi\002can) 38.7461 Tj +1 TJm +(tly) 10.5209 Tj +-266 TJm +(f) 3.31768 Tj +10 TJm +(aster) 18.8101 Tj +55 TJm +(.) 2.49075 Tj +-712 TJm +(And) 17.1563 Tj +[1 0 0 1 444.622 586.501] cm +0 g +0 G +[1 0 0 1 -444.622 -586.501] cm +[1 0 0 1 0 0] Tm +0 0 Td +444.622 586.501 Td +/F130_0 9.963 Tf +(--best) 35.8668 Tj +[1 0 0 1 480.487 586.501] cm +0 g +0 G +[1 0 0 1 -480.487 -586.501] cm +[1 0 0 1 0 0] Tm +0 0 Td +483.131 586.501 Td +/F128_0 9.963 Tf +(merely) 27.6673 Tj +-265 TJm +(selects) 26.5614 Tj +108 574.546 Td +(the) 12.1748 Tj +-250 TJm +(def) 12.7228 Tj +10 TJm +(ault) 14.9445 Tj +-250 TJm +(beha) 18.8101 Tj +20 TJm +(viour) 21.0319 Tj +55 TJm +(.) 2.49075 Tj +[1 0 0 1 72 574.446] cm +0 g +0 G +0 g +0 G +[1 0 0 1 0 -3.985] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -560.498] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 548.643 Td +/F130_0 9.963 Tf +(--) 11.9556 Tj +[1 0 0 1 83.955 548.643] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -14.446 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -548.643] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 536.688 Td +/F128_0 9.963 Tf +(T) 6.08739 Tj +35 TJm +(reats) 18.8101 Tj +-261 TJm +(all) 9.963 Tj +-260 TJm +(subsequent) 44.2756 Tj +-261 TJm +(ar) 7.74125 Tj +18 TJm +(guments) 33.7646 Tj +-261 TJm +(as) 8.29918 Tj +-260 TJm +(\002le) 12.7327 Tj +-261 TJm +(names,) 27.9462 Tj +-263 TJm +(e) 4.42357 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(en) 9.40507 Tj +-261 TJm +(if) 6.08739 Tj +-261 TJm +(the) 12.1748 Tj +15 TJm +(y) 4.9815 Tj +-261 TJm +(sta) 11.0689 Tj +1 TJm +(rt) 6.08739 Tj +-261 TJm +(with) 17.7142 Tj +-261 TJm +(a) 4.42357 Tj +-261 TJm +(dash.) 20.7529 Tj +-684 TJm +(This) 17.7142 Tj +-261 TJm +(is) 6.64532 Tj +-261 TJm +(so) 8.85711 Tj +-261 TJm +(yo) 9.963 Tj +1 TJm +(u) 4.9815 Tj +-261 TJm +(can) 13.8286 Tj +-261 TJm +(handle) 26.5614 Tj +-261 TJm +(\002les) 16.6083 Tj +108 524.732 Td +(with) 17.7142 Tj +-250 TJm +(names) 25.4555 Tj +-250 TJm +(be) 9.40507 Tj +15 TJm +(ginning) 30.4469 Tj +-250 TJm +(with) 17.7142 Tj +-250 TJm +(a) 4.42357 Tj +-249 TJm +(dash,) 20.7529 Tj +-250 TJm +(for) 11.6169 Tj +-250 TJm +(e) 4.42357 Tj +15 TJm +(xample:) 32.1008 Tj +[1 0 0 1 302.27 524.732] cm +0 g +0 G +[1 0 0 1 -302.27 -524.732] cm +[1 0 0 1 0 0] Tm +0 0 Td +302.27 524.732 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +-600 TJm +(--) 11.9556 Tj +-600 TJm +(-myfilename) 65.7558 Tj +[1 0 0 1 421.821 524.732] cm +0 g +0 G +[1 0 0 1 -421.821 -524.732] cm +[1 0 0 1 0 0] Tm +0 0 Td +421.821 524.732 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 72 522.576] cm +0 g +0 G +0 g +0 G +[1 0 0 1 0 -3.985] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -508.628] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 498.83 Td +/F130_0 9.963 Tf +(--repetitive-fast) 101.623 Tj +[1 0 0 1 173.619 498.83] cm +0 g +0 G +[1 0 0 1 -173.619 -498.83] cm +[1 0 0 1 0 0] Tm +0 0 Td +173.619 498.83 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 178.6 498.83] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -181.091 -498.83] cm +[1 0 0 1 0 0] Tm +0 0 Td +181.091 498.83 Td +/F130_0 9.963 Tf +(--repetitive-best) 101.623 Tj +[1 0 0 1 282.71 498.83] cm +0 g +0 G +[1 0 0 1 -282.71 -498.83] cm +[1 0 0 1 0 0] Tm +0 0 Td +282.71 498.83 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 287.691 498.83] cm +0 g +0 G +[1 0 0 1 -215.691 -1.564] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -497.266] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 486.874 Td +/F128_0 9.963 Tf +(These) 23.7916 Tj +-207 TJm +(\003ags) 18.8201 Tj +-206 TJm +(are) 12.1648 Tj +-207 TJm +(redundant) 39.842 Tj +-206 TJm +(in) 7.75121 Tj +-207 TJm +(v) 4.9815 Tj +15 TJm +(ersions) 28.2252 Tj +-206 TJm +(0.9.5) 19.926 Tj +-207 TJm +(and) 14.3866 Tj +-207 TJm +(abo) 14.3866 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(e.) 6.91432 Tj +-591 TJm +(The) 15.4925 Tj +15 TJm +(y) 4.9815 Tj +-206 TJm +(pro) 13.2807 Tj +15 TJm +(vided) 22.1378 Tj +-207 TJm +(some) 21.0319 Tj +-206 TJm +(coarse) 25.4455 Tj +-207 TJm +(control) 28.2252 Tj +-206 TJm +(o) 4.9815 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(er) 7.74125 Tj +-207 TJm +(the) 12.1748 Tj +-207 TJm +(beha) 18.8101 Tj +20 TJm +(viour) 21.0319 Tj +108 474.919 Td +(of) 8.29918 Tj +-250 TJm +(the) 12.1748 Tj +-251 TJm +(sorti) 17.7142 Tj +1 TJm +(ng) 9.963 Tj +-251 TJm +(algorithm) 38.7461 Tj +-250 TJm +(in) 7.75121 Tj +-250 TJm +(earlier) 25.4455 Tj +-250 TJm +(v) 4.9815 Tj +15 TJm +(ersions,) 30.7159 Tj +-251 TJm +(which) 24.3496 Tj +-250 TJm +(w) 7.19329 Tj +10 TJm +(as) 8.29918 Tj +-250 TJm +(sometimes) 42.6217 Tj +-250 TJm +(useful.) 26.8403 Tj +-622 TJm +(0.9.5) 19.926 Tj +-251 TJm +(and) 14.3866 Tj +-250 TJm +(abo) 14.3866 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-250 TJm +(ha) 9.40507 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-250 TJm +(an) 9.40507 Tj +-251 TJm +(impro) 23.8016 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(ed) 9.40507 Tj +108 462.964 Td +(algorithm) 38.7461 Tj +-250 TJm +(which) 24.3496 Tj +-250 TJm +(renders) 29.3211 Tj +-250 TJm +(thes) 16.0504 Tj +1 TJm +(e) 4.42357 Tj +-250 TJm +(\003ags) 18.8201 Tj +-250 TJm +(irrele) 21.0219 Tj +25 TJm +(v) 4.9815 Tj +25 TJm +(ant.) 14.6655 Tj +[1 0 0 1 72 460.807] cm +0 g +0 G +0 g +0 G +[1 0 0 1 0 -3.985] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -436.897] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 414.264 Td +/F121_0 20.659 Tf +(2.5.) 34.4592 Tj +-278 TJm +(MEMOR) 79.1859 Tj +50 TJm +(Y) 13.7796 Tj +-278 TJm +(MANA) 61.9563 Tj +50 TJm +(GEMENT) 88.3792 Tj +[1 0 0 1 72 414.006] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -404.043] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 392.346 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 101.888 392.346] cm +0 g +0 G +[1 0 0 1 -101.888 -392.346] cm +[1 0 0 1 0 0] Tm +0 0 Td +104.454 392.346 Td +/F128_0 9.963 Tf +(compresses) 45.9294 Tj +-257 TJm +(lar) 10.511 Tj +18 TJm +(ge) 9.40507 Tj +-258 TJm +(\002les) 16.6083 Tj +-257 TJm +(in) 7.75121 Tj +-258 TJm +(blocks.) 28.5041 Tj +-665 TJm +(The) 15.4925 Tj +-258 TJm +(block) 22.1378 Tj +-257 TJm +(size) 15.4925 Tj +-258 TJm +(af) 7.74125 Tj +25 TJm +(fects) 18.8101 Tj +-257 TJm +(both) 17.7142 Tj +-258 TJm +(the) 12.1748 Tj +-257 TJm +(compression) 50.363 Tj +-258 TJm +(ratio) 18.2622 Tj +-257 TJm +(achie) 21.0219 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(ed,) 11.8958 Tj +-260 TJm +(an) 9.40507 Tj +1 TJm +(d) 4.9815 Tj +-258 TJm +(the) 12.1748 Tj +-258 TJm +(amoun) 27.1193 Tj +1 TJm +(t) 2.76971 Tj +72 380.391 Td +(of) 8.29918 Tj +-215 TJm +(memory) 33.2067 Tj +-215 TJm +(needed) 28.2152 Tj +-214 TJm +(for) 11.6169 Tj +-215 TJm +(compression) 50.363 Tj +-215 TJm +(and) 14.3866 Tj +-215 TJm +(decompressi) 49.805 Tj +1 TJm +(on.) 12.4538 Tj +-597 TJm +(The) 15.4925 Tj +-215 TJm +(\003ags) 18.8201 Tj +[1 0 0 1 337.719 380.391] cm +0 g +0 G +[1 0 0 1 -337.719 -380.391] cm +[1 0 0 1 0 0] Tm +0 0 Td +337.719 380.391 Td +/F130_0 9.963 Tf +(-1) 11.9556 Tj +[1 0 0 1 349.674 380.391] cm +0 g +0 G +[1 0 0 1 -349.674 -380.391] cm +[1 0 0 1 0 0] Tm +0 0 Td +351.815 380.391 Td +/F128_0 9.963 Tf +(through) 30.9949 Tj +[1 0 0 1 384.95 380.391] cm +0 g +0 G +[1 0 0 1 -384.95 -380.391] cm +[1 0 0 1 0 0] Tm +0 0 Td +384.95 380.391 Td +/F130_0 9.963 Tf +(-9) 11.9556 Tj +[1 0 0 1 396.905 380.391] cm +0 g +0 G +[1 0 0 1 -396.905 -380.391] cm +[1 0 0 1 0 0] Tm +0 0 Td +399.046 380.391 Td +/F128_0 9.963 Tf +(specify) 28.7731 Tj +-215 TJm +(the) 12.1748 Tj +-215 TJm +(block) 22.1378 Tj +-214 TJm +(size) 15.4925 Tj +-215 TJm +(to) 7.75121 Tj +-215 TJm +(be) 9.40507 Tj +-215 TJm +(100,000) 32.3798 Tj +72 368.435 Td +(bytes) 21.0319 Tj +-278 TJm +(throug) 26.0134 Tj +1 TJm +(h) 4.9815 Tj +-278 TJm +(900,000) 32.3798 Tj +-278 TJm +(bytes) 21.0319 Tj +-277 TJm +(\(the) 15.4925 Tj +-278 TJm +(def) 12.7228 Tj +10 TJm +(ault\)) 18.2622 Tj +-278 TJm +(r) 3.31768 Tj +1 TJm +(especti) 27.6673 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(ely) 12.1748 Tj +65 TJm +(.) 2.49075 Tj +-786 TJm +(At) 9.963 Tj +-278 TJm +(decompression) 59.768 Tj +-278 TJm +(tim) 13.2906 Tj +1 TJm +(e,) 6.91432 Tj +-285 TJm +(the) 12.1748 Tj +-278 TJm +(block) 22.1378 Tj +-277 TJm +(size) 15.4925 Tj +-278 TJm +(used) 18.2622 Tj +-278 TJm +(f) 3.31768 Tj +1 TJm +(or) 8.29918 Tj +-278 TJm +(compression) 50.363 Tj +72 356.48 Td +(is) 6.64532 Tj +-242 TJm +(read) 17.1463 Tj +-243 TJm +(from) 19.3681 Tj +-242 TJm +(the) 12.1748 Tj +-243 TJm +(header) 26.5514 Tj +-242 TJm +(of) 8.29918 Tj +-243 TJm +(the) 12.1748 Tj +-242 TJm +(compressed) 47.0353 Tj +-242 TJm +(\002le,) 15.2235 Tj +-244 TJm +(and) 14.3866 Tj +[1 0 0 1 275.174 356.48] cm +0 g +0 G +[1 0 0 1 -275.174 -356.48] cm +[1 0 0 1 0 0] Tm +0 0 Td +275.174 356.48 Td +/F130_0 9.963 Tf +(bunzip2) 41.8446 Tj +[1 0 0 1 317.017 356.48] cm +0 g +0 G +[1 0 0 1 -317.017 -356.48] cm +[1 0 0 1 0 0] Tm +0 0 Td +319.433 356.48 Td +/F128_0 9.963 Tf +(then) 17.1563 Tj +-242 TJm +(allocates) 34.8605 Tj +-243 TJm +(itself) 19.926 Tj +-242 TJm +(just) 14.3965 Tj +-243 TJm +(enough) 29.3311 Tj +-242 TJm +(memory) 33.2067 Tj +-242 TJm +(to) 7.75121 Tj +-243 TJm +(decompress) 47.0353 Tj +72 344.525 Td +(the) 12.1748 Tj +-303 TJm +(\002le.) 15.2235 Tj +-940 TJm +(Since) 22.1378 Tj +-303 TJm +(block) 22.1378 Tj +-303 TJm +(sizes) 19.3681 Tj +-304 TJm +(are) 12.1648 Tj +-303 TJm +(stored) 24.3496 Tj +-303 TJm +(in) 7.75121 Tj +-303 TJm +(compressed) 47.0353 Tj +-304 TJm +(\002) 5.53943 Tj +1 TJm +(les,) 13.5596 Tj +-317 TJm +(it) 5.53943 Tj +-303 TJm +(follo) 18.8201 Tj +25 TJm +(ws) 11.0689 Tj +-304 TJm +(t) 2.76971 Tj +1 TJm +(hat) 12.1748 Tj +-304 TJm +(the) 12.1748 Tj +-303 TJm +(\003ags) 18.8201 Tj +[1 0 0 1 406.35 344.525] cm +0 g +0 G +[1 0 0 1 -406.35 -344.525] cm +[1 0 0 1 0 0] Tm +0 0 Td +406.35 344.525 Td +/F130_0 9.963 Tf +(-1) 11.9556 Tj +[1 0 0 1 418.305 344.525] cm +0 g +0 G +[1 0 0 1 -418.305 -344.525] cm +[1 0 0 1 0 0] Tm +0 0 Td +421.327 344.525 Td +/F128_0 9.963 Tf +(to) 7.75121 Tj +[1 0 0 1 432.1 344.525] cm +0 g +0 G +[1 0 0 1 -432.1 -344.525] cm +[1 0 0 1 0 0] Tm +0 0 Td +432.1 344.525 Td +/F130_0 9.963 Tf +(-9) 11.9556 Tj +[1 0 0 1 444.055 344.525] cm +0 g +0 G +[1 0 0 1 -444.055 -344.525] cm +[1 0 0 1 0 0] Tm +0 0 Td +447.077 344.525 Td +/F128_0 9.963 Tf +(are) 12.1648 Tj +-303 TJm +(irrele) 21.0219 Tj +25 TJm +(v) 4.9815 Tj +25 TJm +(ant) 12.1748 Tj +-303 TJm +(to) 7.75121 Tj +-304 TJm +(and) 14.3866 Tj +-303 TJm +(so) 8.85711 Tj +72 332.57 Td +(ignored) 30.437 Tj +-250 TJm +(during) 26.0134 Tj +-250 TJm +(decompression) 59.768 Tj +1 TJm +(.) 2.49075 Tj +[1 0 0 1 72 330.413] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -320.451] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 310.652 Td +/F128_0 9.963 Tf +(Compression) 52.5847 Tj +-250 TJm +(and) 14.3866 Tj +-250 TJm +(decompress) 47.0353 Tj +1 TJm +(ion) 12.7327 Tj +-250 TJm +(requirements,) 54.5076 Tj +-250 TJm +(in) 7.75121 Tj +-250 TJm +(bytes,) 23.5226 Tj +-250 TJm +(can) 13.8286 Tj +-250 TJm +(be) 9.40507 Tj +-250 TJm +(estimated) 38.1882 Tj +-250 TJm +(as:) 11.0689 Tj +[1 0 0 1 72 308.495] cm +0 g +0 G +[1 0 0 1 0 -60.772] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 59.776 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 56.189] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -299.13] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 299.13 Td +/F130_0 9.963 Tf +(Compression:) 71.7336 Tj +-1278 TJm +(400k) 23.9112 Tj +-426 TJm +(+) 5.9778 Tj +-426 TJm +(\() 5.9778 Tj +-425 TJm +(8) 5.9778 Tj +-426 TJm +(x) 5.9778 Tj +-426 TJm +(block) 29.889 Tj +-426 TJm +(size) 23.9112 Tj +-426 TJm +(\)) 5.9778 Tj +90 275.22 Td +(Decompression:) 83.6892 Tj +-426 TJm +(100k) 23.9112 Tj +-426 TJm +(+) 5.9778 Tj +-426 TJm +(\() 5.9778 Tj +-425 TJm +(4) 5.9778 Tj +-426 TJm +(x) 5.9778 Tj +-426 TJm +(block) 29.889 Tj +-426 TJm +(size) 23.9112 Tj +-426 TJm +(\),) 11.9556 Tj +-426 TJm +(or) 11.9556 Tj +153.66 263.265 Td +(100k) 23.9112 Tj +-426 TJm +(+) 5.9778 Tj +-426 TJm +(\() 5.9778 Tj +-426 TJm +(2.5) 17.9334 Tj +-426 TJm +(x) 5.9778 Tj +-426 TJm +(block) 29.889 Tj +-426 TJm +(s) 5.9778 Tj +1 TJm +(ize) 17.9334 Tj +-426 TJm +(\)) 5.9778 Tj +[1 0 0 1 72 247.723] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.549] cm +0 g +0 G +[1 0 0 1 -72 -237.761] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 225.805 Td +/F128_0 9.963 Tf +(Lar) 13.8286 Tj +18 TJm +(ger) 12.7228 Tj +-292 TJm +(block) 22.1378 Tj +-291 TJm +(sizes) 19.3681 Tj +-292 TJm +(gi) 7.75121 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-292 TJm +(rapidly) 28.2252 Tj +-291 TJm +(diminishing) 47.6132 Tj +-292 TJm +(mar) 15.4925 Tj +18 TJm +(ginal) 19.926 Tj +-291 TJm +(returns.) 30.158 Tj +-871 TJm +(Most) 20.4839 Tj +-292 TJm +(of) 8.29918 Tj +-291 TJm +(the) 12.1748 Tj +-292 TJm +(compression) 50.363 Tj +-292 TJm +(com) 17.1563 Tj +1 TJm +(es) 8.29918 Tj +-292 TJm +(from) 19.3681 Tj +-292 TJm +(the) 12.1748 Tj +-292 TJm +(\002rst) 15.5024 Tj +-291 TJm +(tw) 9.963 Tj +10 TJm +(o) 4.9815 Tj +-292 TJm +(or) 8.29918 Tj +72 213.85 Td +(three) 19.916 Tj +-232 TJm +(hundred) 32.6488 Tj +-232 TJm +(k) 4.9815 Tj +-232 TJm +(o) 4.9815 Tj +1 TJm +(f) 3.31768 Tj +-232 TJm +(block) 22.1378 Tj +-232 TJm +(size,) 17.9832 Tj +-236 TJm +(a) 4.42357 Tj +-232 TJm +(f) 3.31768 Tj +10 TJm +(a) 4.42357 Tj +1 TJm +(ct) 7.19329 Tj +-232 TJm +(w) 7.19329 Tj +10 TJm +(orth) 16.0504 Tj +-232 TJm +(bearing) 29.879 Tj +-232 TJm +(in) 7.75121 Tj +-232 TJm +(mind) 20.4839 Tj +-232 TJm +(when) 21.5799 Tj +-231 TJm +(using) 21.5898 Tj +[1 0 0 1 354.025 213.85] cm +0 g +0 G +[1 0 0 1 -354.025 -213.85] cm +[1 0 0 1 0 0] Tm +0 0 Td +354.025 213.85 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 383.913 213.85] cm +0 g +0 G +[1 0 0 1 -383.913 -213.85] cm +[1 0 0 1 0 0] Tm +0 0 Td +386.223 213.85 Td +/F128_0 9.963 Tf +(on) 9.963 Tj +-232 TJm +(small) 21.5898 Tj +-232 TJm +(machines.) 40.121 Tj +-303 TJm +(It) 6.08739 Tj +-232 TJm +(is) 6.64532 Tj +-232 TJm +(also) 16.0504 Tj +-232 TJm +(important) 38.7461 Tj +72 201.895 Td +(to) 7.75121 Tj +-250 TJm +(appreciate) 40.938 Tj +-250 TJm +(that) 14.9445 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(decom) 26.5614 Tj +1 TJm +(pression) 33.2067 Tj +-250 TJm +(memory) 33.2067 Tj +-250 TJm +(requirement) 48.1412 Tj +-250 TJm +(is) 6.64532 Tj +-250 TJm +(set) 11.0689 Tj +-250 TJm +(at) 7.19329 Tj +-250 TJm +(compression) 50.363 Tj +-250 TJm +(ti) 5.53943 Tj +1 TJm +(me) 12.1748 Tj +-250 TJm +(by) 9.963 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(choice) 26.0034 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(block) 22.1378 Tj +-250 TJm +(size.) 17.9832 Tj +[1 0 0 1 72 199.738] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -189.776] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 179.977 Td +/F128_0 9.963 Tf +(F) 5.53943 Tj +15 TJm +(or) 8.29918 Tj +-388 TJm +(\002les) 16.6083 Tj +-389 TJm +(compressed) 47.0353 Tj +-388 TJm +(with) 17.7142 Tj +-388 TJm +(the) 12.1748 Tj +-389 TJm +(def) 12.7228 Tj +10 TJm +(ault) 14.9445 Tj +-388 TJm +(900k) 19.926 Tj +-388 TJm +(block) 22.1378 Tj +-389 TJm +(size,) 17.9832 Tj +[1 0 0 1 302.002 179.977] cm +0 g +0 G +[1 0 0 1 -302.002 -179.977] cm +[1 0 0 1 0 0] Tm +0 0 Td +302.002 179.977 Td +/F130_0 9.963 Tf +(bunzip2) 41.8446 Tj +[1 0 0 1 343.845 179.977] cm +0 g +0 G +[1 0 0 1 -343.845 -179.977] cm +[1 0 0 1 0 0] Tm +0 0 Td +347.716 179.977 Td +/F128_0 9.963 Tf +(will) 15.5024 Tj +-388 TJm +(require) 28.2152 Tj +-389 TJm +(about) 22.1378 Tj +-388 TJm +(3700) 19.926 Tj +-388 TJm +(kbytes) 26.0134 Tj +-389 TJm +(to) 7.75121 Tj +-388 TJm +(decompress.) 49.5261 Tj +72 168.022 Td +(T) 6.08739 Tj +80 TJm +(o) 4.9815 Tj +-424 TJm +(support) 29.889 Tj +-424 TJm +(decompression) 59.768 Tj +-424 TJm +(of) 8.29918 Tj +-425 TJm +(an) 9.40507 Tj +15 TJm +(y) 4.9815 Tj +-424 TJm +(\002le) 12.7327 Tj +-424 TJm +(on) 9.963 Tj +-424 TJm +(a) 4.42357 Tj +-425 TJm +(4) 4.9815 Tj +-424 TJm +(me) 12.1748 Tj +15 TJm +(g) 4.9815 Tj +5 TJm +(abyte) 21.5799 Tj +-424 TJm +(machine,) 36.2454 Tj +[1 0 0 1 348.272 168.022] cm +0 g +0 G +[1 0 0 1 -348.272 -168.022] cm +[1 0 0 1 0 0] Tm +0 0 Td +348.272 168.022 Td +/F130_0 9.963 Tf +(bunzip2) 41.8446 Tj +[1 0 0 1 390.115 168.022] cm +0 g +0 G +[1 0 0 1 -390.115 -168.022] cm +[1 0 0 1 0 0] Tm +0 0 Td +394.342 168.022 Td +/F128_0 9.963 Tf +(has) 13.2807 Tj +-424 TJm +(an) 9.40507 Tj +-424 TJm +(option) 25.4654 Tj +-425 TJm +(to) 7.75121 Tj +-424 TJm +(decompress) 47.0353 Tj +-424 TJm +(using) 21.5898 Tj +72 156.067 Td +(approximately) 57.5563 Tj +-281 TJm +(ha) 9.40507 Tj +1 TJm +(lf) 6.08739 Tj +-281 TJm +(this) 14.3965 Tj +-281 TJm +(amount) 29.889 Tj +-281 TJm +(of) 8.29918 Tj +-280 TJm +(memory) 33.2067 Tj +65 TJm +(,) 2.49075 Tj +-289 TJm +(about) 22.1378 Tj +-280 TJm +(2300) 19.926 Tj +-281 TJm +(kbytes.) 28.5041 Tj +-805 TJm +(Decom) 28.7731 Tj +1 TJm +(pression) 33.2067 Tj +-281 TJm +(speed) 22.6858 Tj +-281 TJm +(is) 6.64532 Tj +-281 TJm +(a) 4.42357 Tj +1 TJm +(lso) 11.6268 Tj +-281 TJm +(halv) 17.1563 Tj +15 TJm +(ed,) 11.8958 Tj +-289 TJm +(so) 8.85711 Tj +-280 TJm +(you) 14.9445 Tj +-281 TJm +(should) 26.5713 Tj +72 144.112 Td +(use) 13.2807 Tj +-250 TJm +(this) 14.3965 Tj +-250 TJm +(option) 25.4654 Tj +-250 TJm +(only) 17.7142 Tj +-250 TJm +(where) 24.3396 Tj +-250 TJm +(nec) 13.8286 Tj +1 TJm +(essary) 24.8975 Tj +65 TJm +(.) 2.49075 Tj +-620 TJm +(The) 15.4925 Tj +-250 TJm +(rele) 14.9345 Tj +25 TJm +(v) 4.9815 Tj +25 TJm +(ant) 12.1748 Tj +-250 TJm +(\003ag) 14.9445 Tj +-250 TJm +(is) 6.64532 Tj +[1 0 0 1 305.024 144.112] cm +0 g +0 G +[1 0 0 1 -305.024 -144.112] cm +[1 0 0 1 0 0] Tm +0 0 Td +305.024 144.112 Td +/F130_0 9.963 Tf +(-s) 11.9556 Tj +[1 0 0 1 316.979 144.112] cm +0 g +0 G +[1 0 0 1 -316.979 -144.112] cm +[1 0 0 1 0 0] Tm +0 0 Td +316.979 144.112 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 72 141.955] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -131.992] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 122.194 Td +/F128_0 9.963 Tf +(In) 8.29918 Tj +-204 TJm +(general,) 31.8119 Tj +-214 TJm +(try) 11.0689 Tj +-204 TJm +(and) 14.3866 Tj +-204 TJm +(use) 13.2807 Tj +-205 TJm +(the) 12.1748 Tj +-204 TJm +(lar) 10.511 Tj +18 TJm +(gest) 16.0504 Tj +-204 TJm +(block) 22.1378 Tj +-205 TJm +(size) 15.4925 Tj +-204 TJm +(memory) 33.2067 Tj +-204 TJm +(constraints) 43.1697 Tj +-204 TJm +(allo) 14.9445 Tj +25 TJm +(w) 7.19329 Tj +65 TJm +(,) 2.49075 Tj +-214 TJm +(since) 20.474 Tj +-204 TJm +(that) 14.9445 Tj +-204 TJm +(maximises) 42.6217 Tj +-205 TJm +(the) 12.1748 Tj +-204 TJm +(compression) 50.363 Tj +-204 TJm +(achie) 21.0219 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(ed.) 11.8958 Tj +72 110.239 Td +(Compression) 52.5847 Tj +-250 TJm +(and) 14.3866 Tj +-250 TJm +(decompress) 47.0353 Tj +1 TJm +(ion) 12.7327 Tj +-250 TJm +(speed) 22.6858 Tj +-250 TJm +(are) 12.1648 Tj +-250 TJm +(virtually) 33.7646 Tj +-250 TJm +(unaf) 17.7043 Tj +25 TJm +(fected) 24.3396 Tj +-250 TJm +(by) 9.963 Tj +-250 TJm +(block) 22.1378 Tj +-250 TJm +(size.) 17.9832 Tj +[1 0 0 1 72 108.082] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -98.119] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 88.321 Td +/F128_0 9.963 Tf +(Another) 32.6488 Tj +-296 TJm +(signi\002cant) 41.5158 Tj +-295 TJm +(point) 20.4839 Tj +-296 TJm +(applies) 28.2252 Tj +-296 TJm +(to) 7.75121 Tj +-296 TJm +(\002les) 16.6083 Tj +-295 TJm +(which) 24.3496 Tj +-296 TJm +(\002t) 8.30914 Tj +-296 TJm +(in) 7.75121 Tj +-296 TJm +(a) 4.42357 Tj +-296 TJm +(s) 3.87561 Tj +1 TJm +(ingle) 19.926 Tj +-296 TJm +(block) 22.1378 Tj +-296 TJm +(--) 6.63536 Tj +-296 TJm +(that) 14.9445 Tj +-296 TJm +(mea) 16.5984 Tj +1 TJm +(ns) 8.85711 Tj +-296 TJm +(most) 19.378 Tj +-296 TJm +(\002les) 16.6083 Tj +-296 TJm +(you') 18.2622 Tj +50 TJm +(d) 4.9815 Tj +-296 TJm +(enc) 13.8286 Tj +1 TJm +(ounter) 25.4555 Tj +-296 TJm +(using) 21.5898 Tj +-296 TJm +(a) 4.42357 Tj +72 76.366 Td +(lar) 10.511 Tj +18 TJm +(ge) 9.40507 Tj +-290 TJm +(block) 22.1378 Tj +-290 TJm +(size) 15.4925 Tj +1 TJm +(.) 2.49075 Tj +-860 TJm +(The) 15.4925 Tj +-290 TJm +(amou) 22.1378 Tj +1 TJm +(nt) 7.75121 Tj +-290 TJm +(of) 8.29918 Tj +-290 TJm +(real) 14.9345 Tj +-290 TJm +(memory) 33.2067 Tj +-290 TJm +(touched) 31.5429 Tj +-289 TJm +(is) 6.64532 Tj +-290 TJm +(proportional) 49.2571 Tj +-290 TJm +(to) 7.75121 Tj +-290 TJm +(the) 12.1748 Tj +-290 TJm +(size) 15.4925 Tj +-289 TJm +(of) 8.29918 Tj +-290 TJm +(the) 12.1748 Tj +-290 TJm +(\002le,) 15.2235 Tj +-300 TJm +(since) 20.474 Tj +-290 TJm +(the) 12.1748 Tj +-289 TJm +(\002le) 12.7327 Tj +-290 TJm +(is) 6.64532 Tj +-290 TJm +(smaller) 29.3311 Tj +[1 0 0 1 72 50.852] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.854] cm +0 g +0 G +0 g +0 G +[1 0 0 1 43.063 -6.755] cm +0 g +0 G +[1 0 0 1 -496.332 -50.951] cm +[1 0 0 1 0 0] Tm +0 0 Td +539.395 50.951 Td +/F128_0 9.963 Tf +(5) 4.9815 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 9 9 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 -8.911] cm +0 g +0 G +[1 0 0 1 0 8.911] cm +0 g +0 G +0 g +0 G +[1 0 0 1 105.519 -6.755] cm +0 g +0 G +[1 0 0 1 -371.59 -749.245] cm +[1 0 0 1 0 0] Tm +0 0 Td +477.109 749.245 Td +/F128_0 9.963 Tf +(Ho) 12.1748 Tj +25 TJm +(w) 7.19329 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(use) 13.2807 Tj +-250 TJm +(bzip2) 22.1378 Tj +[1 0 0 1 266.071 747.089] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -5.037] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -540 -741.554] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 710.037 Td +/F128_0 9.963 Tf +(than) 17.1563 Tj +-362 TJm +(a) 4.42357 Tj +-362 TJm +(block.) 24.6285 Tj +-1292 TJm +(F) 5.53943 Tj +15 TJm +(or) 8.29918 Tj +-362 TJm +(e) 4.42357 Tj +15 TJm +(xample,) 31.8218 Tj +-390 TJm +(compressing) 50.363 Tj +-362 TJm +(a) 4.42357 Tj +-362 TJm +(\002le) 12.7327 Tj +-362 TJm +(20,000) 27.3983 Tj +-362 TJm +(bytes) 21.0319 Tj +-362 TJm +(long) 17.7142 Tj +-362 TJm +(with) 17.7142 Tj +-362 TJm +(the) 12.1748 Tj +-362 TJm +(\003ag) 14.9445 Tj +[1 0 0 1 406.528 710.037] cm +0 g +0 G +[1 0 0 1 -406.528 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +406.528 710.037 Td +/F130_0 9.963 Tf +(-9) 11.9556 Tj +[1 0 0 1 418.483 710.037] cm +0 g +0 G +[1 0 0 1 -418.483 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +422.091 710.037 Td +/F128_0 9.963 Tf +(will) 15.5024 Tj +-362 TJm +(cause) 22.1278 Tj +-362 TJm +(the) 12.1748 Tj +-362 TJm +(compressor) 45.9294 Tj +-362 TJm +(to) 7.75121 Tj +72 698.082 Td +(allocate) 30.9849 Tj +-271 TJm +(around) 27.6673 Tj +-272 TJm +(7600k) 24.9075 Tj +-271 TJm +(of) 8.29918 Tj +-272 TJm +(m) 7.75121 Tj +1 TJm +(emory) 25.4555 Tj +65 TJm +(,) 2.49075 Tj +-277 TJm +(b) 4.9815 Tj +20 TJm +(ut) 7.75121 Tj +-272 TJm +(only) 17.7142 Tj +-271 TJm +(touch) 22.1378 Tj +-271 TJm +(400k) 19.926 Tj +-272 TJm +(+) 5.61913 Tj +-271 TJm +(20000) 24.9075 Tj +-272 TJm +(*) 4.9815 Tj +-271 TJm +(8) 4.9815 Tj +-272 TJm +(=) 5.61913 Tj +-271 TJm +(560) 14.9445 Tj +-271 TJm +(kbytes) 26.0134 Tj +-272 TJm +(of) 8.29918 Tj +-271 TJm +(it.) 8.03018 Tj +-749 TJm +(Similarly) 37.0922 Tj +65 TJm +(,) 2.49075 Tj +-277 TJm +(the) 12.1748 Tj +-271 TJm +(decompressor) 55.3345 Tj +72 686.127 Td +(will) 15.5024 Tj +-250 TJm +(allocate) 30.9849 Tj +-250 TJm +(3700k) 24.9075 Tj +-250 TJm +(b) 4.9815 Tj +20 TJm +(ut) 7.75121 Tj +-250 TJm +(only) 17.7142 Tj +-250 TJm +(t) 2.76971 Tj +1 TJm +(ouch) 19.3681 Tj +-250 TJm +(100k) 19.926 Tj +-250 TJm +(+) 5.61913 Tj +-250 TJm +(20000) 24.9075 Tj +-250 TJm +(*) 4.9815 Tj +-250 TJm +(4) 4.9815 Tj +-250 TJm +(=) 5.61913 Tj +-250 TJm +(180) 14.9445 Tj +-250 TJm +(kbytes.) 28.5041 Tj +[1 0 0 1 72 683.97] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -674.008] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 664.209 Td +/F128_0 9.963 Tf +(Here) 19.3581 Tj +-293 TJm +(is) 6.64532 Tj +-294 TJm +(a) 4.42357 Tj +-293 TJm +(table) 19.3681 Tj +-294 TJm +(which) 24.3496 Tj +-293 TJm +(summarises) 47.0453 Tj +-293 TJm +(the) 12.1748 Tj +-294 TJm +(maximu) 32.6587 Tj +1 TJm +(m) 7.75121 Tj +-294 TJm +(memory) 33.2067 Tj +-293 TJm +(usage) 22.6858 Tj +-294 TJm +(for) 11.6169 Tj +-293 TJm +(dif) 11.0689 Tj +25 TJm +(ferent) 23.2337 Tj +-293 TJm +(block) 22.1378 Tj +-294 TJm +(sizes.) 21.8588 Tj +-880 TJm +(Also) 18.8201 Tj +-294 TJm +(recorded) 34.8506 Tj +-293 TJm +(is) 6.64532 Tj +-294 TJm +(the) 12.1748 Tj +-293 TJm +(total) 17.7142 Tj +72 652.254 Td +(compressed) 47.0353 Tj +-289 TJm +(size) 15.4925 Tj +-289 TJm +(for) 11.6169 Tj +-289 TJm +(14) 9.963 Tj +-289 TJm +(\002les) 16.6083 Tj +-289 TJm +(of) 8.29918 Tj +-289 TJm +(the) 12.1748 Tj +-289 TJm +(Calg) 18.8201 Tj +5 TJm +(ary) 12.7228 Tj +-289 TJm +(T) 6.08739 Tj +70 TJm +(e) 4.42357 Tj +15 TJm +(xt) 7.75121 Tj +-289 TJm +(Compression) 52.5847 Tj +-289 TJm +(Corpus) 28.7831 Tj +-289 TJm +(totalling) 33.2166 Tj +-289 TJm +(3,141,622) 39.852 Tj +-289 TJm +(bytes.) 23.5226 Tj +-855 TJm +(This) 17.7142 Tj +-289 TJm +(column) 29.889 Tj +-289 TJm +(gi) 7.75121 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(es) 8.29918 Tj +72 640.299 Td +(some) 21.0319 Tj +-253 TJm +(feel) 14.9345 Tj +-253 TJm +(for) 11.6169 Tj +-253 TJm +(ho) 9.963 Tj +25 TJm +(w) 7.19329 Tj +-253 TJm +(compression) 50.363 Tj +-253 TJm +(v) 4.9815 Tj +25 TJm +(aries) 18.8101 Tj +-253 TJm +(with) 17.7142 Tj +-253 TJm +(bl) 7.75121 Tj +1 TJm +(ock) 14.3866 Tj +-253 TJm +(size.) 17.9832 Tj +-639 TJm +(These) 23.7916 Tj +-253 TJm +(\002g) 10.5209 Tj +1 TJm +(ures) 16.5984 Tj +-253 TJm +(tend) 17.1563 Tj +-253 TJm +(to) 7.75121 Tj +-253 TJm +(understate) 40.9479 Tj +-253 TJm +(the) 12.1748 Tj +-253 TJm +(adv) 14.3866 Tj +25 TJm +(antage) 26.0034 Tj +-253 TJm +(of) 8.29918 Tj +-253 TJm +(lar) 10.511 Tj +18 TJm +(ger) 12.7228 Tj +-253 TJm +(block) 22.1378 Tj +72 628.344 Td +(sizes) 19.3681 Tj +-250 TJm +(for) 11.6169 Tj +-250 TJm +(lar) 10.511 Tj +18 TJm +(ger) 12.7228 Tj +-250 TJm +(\002les,) 19.0991 Tj +-250 TJm +(since) 20.474 Tj +-250 TJm +(t) 2.76971 Tj +1 TJm +(he) 9.40507 Tj +-250 TJm +(Corpus) 28.7831 Tj +-250 TJm +(is) 6.64532 Tj +-250 TJm +(dominated) 42.0638 Tj +-250 TJm +(by) 9.963 Tj +-250 TJm +(smaller) 29.3311 Tj +-250 TJm +(\002les.) 19.0991 Tj +[1 0 0 1 72 626.187] cm +0 g +0 G +[1 0 0 1 0 -156.414] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 155.417 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 151.831] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -616.822] cm +[1 0 0 1 0 0] Tm +0 0 Td +123.952 616.822 Td +/F130_0 9.963 Tf +(Compress) 47.8224 Tj +-1278 TJm +(Decompress) 59.778 Tj +-1277 TJm +(Decompress) 59.778 Tj +-1278 TJm +(Corpus) 35.8668 Tj +90 604.867 Td +(Flag) 23.9112 Tj +-2130 TJm +(usage) 29.889 Tj +-2556 TJm +(us) 11.9556 Tj +1 TJm +(age) 17.9334 Tj +-2982 TJm +(-s) 11.9556 Tj +-426 TJm +(usage) 29.889 Tj +-2130 TJm +(Size) 23.9112 Tj +94.244 580.957 Td +(-1) 11.9556 Tj +-2556 TJm +(1200k) 29.889 Tj +-2982 TJm +(50) 11.9556 Tj +1 TJm +(0k) 11.9556 Tj +-3834 TJm +(350k) 23.9112 Tj +-2556 TJm +(914704) 35.8668 Tj +94.244 569.001 Td +(-2) 11.9556 Tj +-2556 TJm +(2000k) 29.889 Tj +-2982 TJm +(90) 11.9556 Tj +1 TJm +(0k) 11.9556 Tj +-3834 TJm +(600k) 23.9112 Tj +-2556 TJm +(877703) 35.8668 Tj +94.244 557.046 Td +(-3) 11.9556 Tj +-2556 TJm +(2800k) 29.889 Tj +-2556 TJm +(130) 17.9334 Tj +1 TJm +(0k) 11.9556 Tj +-3834 TJm +(850k) 23.9112 Tj +-2556 TJm +(860338) 35.8668 Tj +94.244 545.091 Td +(-4) 11.9556 Tj +-2556 TJm +(3600k) 29.889 Tj +-2556 TJm +(170) 17.9334 Tj +1 TJm +(0k) 11.9556 Tj +-3408 TJm +(1100k) 29.889 Tj +-2556 TJm +(846899) 35.8668 Tj +94.244 533.136 Td +(-5) 11.9556 Tj +-2556 TJm +(4400k) 29.889 Tj +-2556 TJm +(210) 17.9334 Tj +1 TJm +(0k) 11.9556 Tj +-3408 TJm +(1350k) 29.889 Tj +-2556 TJm +(845160) 35.8668 Tj +94.244 521.181 Td +(-6) 11.9556 Tj +-2556 TJm +(5200k) 29.889 Tj +-2556 TJm +(250) 17.9334 Tj +1 TJm +(0k) 11.9556 Tj +-3408 TJm +(1600k) 29.889 Tj +-2556 TJm +(838626) 35.8668 Tj +94.244 509.225 Td +(-7) 11.9556 Tj +-2556 TJm +(6100k) 29.889 Tj +-2556 TJm +(290) 17.9334 Tj +1 TJm +(0k) 11.9556 Tj +-3408 TJm +(1850k) 29.889 Tj +-2556 TJm +(834096) 35.8668 Tj +94.244 497.27 Td +(-8) 11.9556 Tj +-2556 TJm +(6800k) 29.889 Tj +-2556 TJm +(330) 17.9334 Tj +1 TJm +(0k) 11.9556 Tj +-3408 TJm +(2100k) 29.889 Tj +-2556 TJm +(828642) 35.8668 Tj +94.244 485.315 Td +(-9) 11.9556 Tj +-2556 TJm +(7600k) 29.889 Tj +-2556 TJm +(370) 17.9334 Tj +1 TJm +(0k) 11.9556 Tj +-3408 TJm +(2350k) 29.889 Tj +-2556 TJm +(828642) 35.8668 Tj +[1 0 0 1 72 469.773] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -3.587] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -459.811] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 435.021 Td +/F121_0 20.659 Tf +(2.6.) 34.4592 Tj +-939 TJm +(RECO) 59.6839 Tj +50 TJm +(VERING) 79.2066 Tj +-939 TJm +(D) 14.9158 Tj +40 TJm +(A) 14.9158 Tj +90 TJm +(T) 12.6226 Tj +90 TJm +(A) 14.9158 Tj +-939 TJm +(FR) 27.5384 Tj +20 TJm +(OM) 33.2816 Tj +-939 TJm +(D) 14.9158 Tj +40 TJm +(AMA) 47.0405 Tj +50 TJm +(GED) 44.7681 Tj +72 410.23 Td +(FILES) 58.5476 Tj +[1 0 0 1 72 409.972] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -400.01] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 388.313 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 101.888 388.313] cm +0 g +0 G +[1 0 0 1 -101.888 -388.313] cm +[1 0 0 1 0 0] Tm +0 0 Td +105.138 388.313 Td +/F128_0 9.963 Tf +(compresses) 45.9294 Tj +-326 TJm +(\002les) 16.6083 Tj +-326 TJm +(in) 7.75121 Tj +-326 TJm +(blocks,) 28.5041 Tj +-345 TJm +(usually) 28.7831 Tj +-326 TJm +(900kbytes) 40.9579 Tj +-326 TJm +(long.) 20.205 Tj +-1077 TJm +(Each) 19.916 Tj +-326 TJm +(block) 22.1378 Tj +-326 TJm +(is) 6.64532 Tj +-327 TJm +(handle) 26.5614 Tj +1 TJm +(d) 4.9815 Tj +-327 TJm +(independe) 40.9479 Tj +1 TJm +(ntly) 15.5024 Tj +65 TJm +(.) 2.49075 Tj +-1077 TJm +(If) 6.63536 Tj +-327 TJm +(a) 4.42357 Tj +-326 TJm +(media) 24.3496 Tj +-326 TJm +(or) 8.29918 Tj +72 376.357 Td +(transmission) 50.3729 Tj +-318 TJm +(error) 19.3581 Tj +-319 TJm +(causes) 26.0034 Tj +-318 TJm +(a) 4.42357 Tj +-319 TJm +(multi-block) 46.4973 Tj +[1 0 0 1 234.519 376.357] cm +0 g +0 G +[1 0 0 1 -234.519 -376.357] cm +[1 0 0 1 0 0] Tm +0 0 Td +234.519 376.357 Td +/F130_0 9.963 Tf +(.bz2) 23.9112 Tj +[1 0 0 1 258.429 376.357] cm +0 g +0 G +[1 0 0 1 -258.429 -376.357] cm +[1 0 0 1 0 0] Tm +0 0 Td +261.603 376.357 Td +/F128_0 9.963 Tf +(\002le) 12.7327 Tj +-319 TJm +(to) 7.75121 Tj +-318 TJm +(become) 30.9849 Tj +-319 TJm +(da) 9.40507 Tj +1 TJm +(maged,) 29.0521 Tj +-336 TJm +(it) 5.53943 Tj +-319 TJm +(may) 17.1563 Tj +-318 TJm +(be) 9.40507 Tj +-319 TJm +(possible) 32.6587 Tj +-318 TJm +(to) 7.75121 Tj +-319 TJm +(reco) 17.1463 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(er) 7.74125 Tj +-318 TJm +(data) 16.5984 Tj +-319 TJm +(from) 19.3681 Tj +-318 TJm +(the) 12.1748 Tj +72 364.402 Td +(undamaged) 45.9294 Tj +-250 TJm +(blocks) 26.0134 Tj +-250 TJm +(in) 7.75121 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(\002le.) 15.2235 Tj +[1 0 0 1 72 362.245] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -352.283] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 342.484 Td +/F128_0 9.963 Tf +(The) 15.4925 Tj +-358 TJm +(com) 17.1563 Tj +1 TJm +(pressed) 29.879 Tj +-358 TJm +(representation) 56.4404 Tj +-357 TJm +(of) 8.29918 Tj +-358 TJm +(each) 18.2522 Tj +-357 TJm +(block) 22.1378 Tj +-358 TJm +(is) 6.64532 Tj +-357 TJm +(delimited) 37.6402 Tj +-358 TJm +(by) 9.963 Tj +-357 TJm +(a) 4.42357 Tj +-358 TJm +(48-bit) 23.8016 Tj +-357 TJm +(pattern,) 30.158 Tj +-385 TJm +(which) 24.3496 Tj +-357 TJm +(mak) 17.1563 Tj +10 TJm +(es) 8.29918 Tj +-358 TJm +(it) 5.53943 Tj +-357 TJm +(possible) 32.6587 Tj +-358 TJm +(to) 7.75121 Tj +-357 TJm +(\002nd) 15.5024 Tj +-358 TJm +(the) 12.1748 Tj +72 330.529 Td +(block) 22.1378 Tj +-286 TJm +(boundaries) 43.7176 Tj +-285 TJm +(with) 17.7142 Tj +-286 TJm +(reasonable) 42.6018 Tj +-285 TJm +(certainty) 34.8605 Tj +65 TJm +(.) 2.49075 Tj +-835 TJm +(Each) 19.916 Tj +-286 TJm +(block) 22.1378 Tj +-285 TJm +(also) 16.0504 Tj +-286 TJm +(carries) 26.5514 Tj +-286 TJm +(its) 9.41504 Tj +-285 TJm +(o) 4.9815 Tj +25 TJm +(wn) 12.1748 Tj +-286 TJm +(32-bit) 23.8016 Tj +-286 TJm +(CRC,) 22.4267 Tj +-285 TJm +(so) 8.85711 Tj +-286 TJm +(damaged) 35.9664 Tj +-286 TJm +(blocks) 26.0134 Tj +-285 TJm +(can) 13.8286 Tj +-286 TJm +(be) 9.40507 Tj +72 318.574 Td +(distinguished) 53.1426 Tj +-250 TJm +(from) 19.3681 Tj +-250 TJm +(undamage) 40.9479 Tj +1 TJm +(d) 4.9815 Tj +-250 TJm +(ones.) 20.7529 Tj +[1 0 0 1 72 316.417] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -306.455] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 296.656 Td +/F130_0 9.963 Tf +(bzip2recover) 71.7336 Tj +[1 0 0 1 143.731 296.656] cm +0 g +0 G +[1 0 0 1 -143.731 -296.656] cm +[1 0 0 1 0 0] Tm +0 0 Td +146.448 296.656 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-273 TJm +(a) 4.42357 Tj +-272 TJm +(simple) 26.5713 Tj +-273 TJm +(program) 33.7546 Tj +-272 TJm +(whose) 25.4555 Tj +-273 TJm +(purpose) 31.5429 Tj +-273 TJm +(i) 2.76971 Tj +1 TJm +(s) 3.87561 Tj +-273 TJm +(to) 7.75121 Tj +-273 TJm +(search) 25.4455 Tj +-272 TJm +(for) 11.6169 Tj +-273 TJm +(blocks) 26.0134 Tj +-273 TJm +(in) 7.75121 Tj +[1 0 0 1 392.655 296.656] cm +0 g +0 G +[1 0 0 1 -392.655 -296.656] cm +[1 0 0 1 0 0] Tm +0 0 Td +392.655 296.656 Td +/F130_0 9.963 Tf +(.bz2) 23.9112 Tj +[1 0 0 1 416.566 296.656] cm +0 g +0 G +[1 0 0 1 -416.566 -296.656] cm +[1 0 0 1 0 0] Tm +0 0 Td +419.282 296.656 Td +/F128_0 9.963 Tf +(\002les,) 19.0991 Tj +-278 TJm +(and) 14.3866 Tj +-273 TJm +(write) 20.474 Tj +-273 TJm +(e) 4.42357 Tj +1 TJm +(ach) 13.8286 Tj +-273 TJm +(block) 22.1378 Tj +-273 TJm +(out) 12.7327 Tj +72 284.701 Td +(into) 15.5024 Tj +-254 TJm +(its) 9.41504 Tj +-255 TJm +(o) 4.9815 Tj +25 TJm +(wn) 12.1748 Tj +[1 0 0 1 121.429 284.701] cm +0 g +0 G +[1 0 0 1 -121.429 -284.701] cm +[1 0 0 1 0 0] Tm +0 0 Td +121.429 284.701 Td +/F130_0 9.963 Tf +(.bz2) 23.9112 Tj +[1 0 0 1 145.34 284.701] cm +0 g +0 G +[1 0 0 1 -145.34 -284.701] cm +[1 0 0 1 0 0] Tm +0 0 Td +147.875 284.701 Td +/F128_0 9.963 Tf +(\002le.) 15.2235 Tj +-647 TJm +(Y) 7.19329 Tj +110 TJm +(ou) 9.963 Tj +-254 TJm +(can) 13.8286 Tj +-255 TJm +(then) 17.1563 Tj +-254 TJm +(use) 13.2807 Tj +[1 0 0 1 240.01 284.701] cm +0 g +0 G +[1 0 0 1 -240.01 -284.701] cm +[1 0 0 1 0 0] Tm +0 0 Td +240.01 284.701 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +-600 TJm +(-t) 11.9556 Tj +[1 0 0 1 287.831 284.701] cm +0 g +0 G +[1 0 0 1 -287.831 -284.701] cm +[1 0 0 1 0 0] Tm +0 0 Td +290.367 284.701 Td +/F128_0 9.963 Tf +(to) 7.75121 Tj +-254 TJm +(test) 13.8386 Tj +-255 TJm +(the) 12.1748 Tj +-254 TJm +(inte) 14.9445 Tj +15 TJm +(grity) 18.8201 Tj +-255 TJm +(of) 8.29918 Tj +-254 TJm +(the) 12.1748 Tj +-255 TJm +(res) 11.6169 Tj +1 TJm +(ulting) 23.2536 Tj +-255 TJm +(\002les,) 19.0991 Tj +-255 TJm +(and) 14.3866 Tj +-255 TJm +(decompress) 47.0353 Tj +-254 TJm +(those) 21.0319 Tj +72 272.746 Td +(which) 24.3496 Tj +-250 TJm +(are) 12.1648 Tj +-250 TJm +(undamaged.) 48.4202 Tj +[1 0 0 1 72 270.589] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -260.626] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 250.828 Td +/F130_0 9.963 Tf +(bzip2recover) 71.7336 Tj +[1 0 0 1 143.731 250.828] cm +0 g +0 G +[1 0 0 1 -143.731 -250.828] cm +[1 0 0 1 0 0] Tm +0 0 Td +150.099 250.828 Td +/F128_0 9.963 Tf +(tak) 12.1748 Tj +10 TJm +(es) 8.29918 Tj +-639 TJm +(a) 4.42357 Tj +-639 TJm +(single) 23.8016 Tj +-639 TJm +(ar) 7.74125 Tj +18 TJm +(gument,) 32.3798 Tj +-736 TJm +(the) 12.1748 Tj +-639 TJm +(name) 21.5799 Tj +-639 TJm +(of) 8.29918 Tj +-639 TJm +(the) 12.1748 Tj +-640 TJm +(da) 9.40507 Tj +1 TJm +(maged) 26.5614 Tj +-640 TJm +(\002) 5.53943 Tj +1 TJm +(le,) 9.68404 Tj +-737 TJm +(and) 14.3866 Tj +-639 TJm +(writes) 24.3496 Tj +-639 TJm +(a) 4.42357 Tj +-639 TJm +(number) 30.437 Tj +-639 TJm +(of) 8.29918 Tj +-639 TJm +(\002les) 16.6083 Tj +[1 0 0 1 72 238.873] cm +0 g +0 G +[1 0 0 1 -72 -238.873] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 238.873 Td +/F130_0 9.963 Tf +(rec0001file.bz2) 89.667 Tj +[1 0 0 1 161.664 238.873] cm +0 g +0 G +[1 0 0 1 -161.664 -238.873] cm +[1 0 0 1 0 0] Tm +0 0 Td +161.664 238.873 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 169.072 238.873] cm +0 g +0 G +[1 0 0 1 -169.072 -238.873] cm +[1 0 0 1 0 0] Tm +0 0 Td +169.072 238.873 Td +/F130_0 9.963 Tf +(rec0002file.bz2) 89.667 Tj +[1 0 0 1 258.736 238.873] cm +0 g +0 G +[1 0 0 1 -258.736 -238.873] cm +[1 0 0 1 0 0] Tm +0 0 Td +258.736 238.873 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-494 TJm +(etc,) 14.1076 Tj +-493 TJm +(containing) 42.0638 Tj +-445 TJm +(the) 12.1748 Tj +-445 TJm +(e) 4.42357 Tj +15 TJm +(xtracted) 32.0908 Tj +-444 TJm +(blocks.) 28.5041 Tj +-1790 TJm +(The) 15.4925 Tj +-444 TJm +(output) 25.4654 Tj +-445 TJm +(\002lenames) 38.1882 Tj +-445 TJm +(are) 12.1648 Tj +72 226.918 Td +(designed) 35.4185 Tj +-337 TJm +(so) 8.85711 Tj +-337 TJm +(that) 14.9445 Tj +-336 TJm +(the) 12.1748 Tj +-337 TJm +(use) 13.2807 Tj +-337 TJm +(of) 8.29918 Tj +-337 TJm +(wildcards) 38.7361 Tj +-337 TJm +(in) 7.75121 Tj +-337 TJm +(subsequent) 44.2756 Tj +-336 TJm +(processing) 42.6118 Tj +-337 TJm +(--) 6.63536 Tj +-337 TJm +(for) 11.6169 Tj +-337 TJm +(e) 4.42357 Tj +15 TJm +(xample,) 31.8218 Tj +[1 0 0 1 396.538 226.918] cm +0 g +0 G +[1 0 0 1 -396.538 -226.918] cm +[1 0 0 1 0 0] Tm +0 0 Td +396.538 226.918 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +-600 TJm +(-dc) 17.9334 Tj +-600 TJm +(rec*file.bz2) 71.7336 Tj +-600 TJm +(>) 5.9778 Tj +72 214.963 Td +(recovered_data) 83.6892 Tj +[1 0 0 1 155.686 214.963] cm +0 g +0 G +[1 0 0 1 -155.686 -214.963] cm +[1 0 0 1 0 0] Tm +0 0 Td +158.177 214.963 Td +/F128_0 9.963 Tf +(--) 6.63536 Tj +-250 TJm +(lists) 16.0604 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(\002les) 16.6083 Tj +-250 TJm +(in) 7.75121 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(corr) 16.0404 Tj +1 TJm +(ect) 11.6169 Tj +-250 TJm +(order) 21.0219 Tj +55 TJm +(.) 2.49075 Tj +[1 0 0 1 72 213.797] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -203.834] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 193.045 Td +/F130_0 9.963 Tf +(bzip2recover) 71.7336 Tj +[1 0 0 1 143.731 193.045] cm +0 g +0 G +[1 0 0 1 -143.731 -193.045] cm +[1 0 0 1 0 0] Tm +0 0 Td +145.93 193.045 Td +/F128_0 9.963 Tf +(should) 26.5713 Tj +-221 TJm +(be) 9.40507 Tj +-220 TJm +(of) 8.29918 Tj +-221 TJm +(most) 19.378 Tj +-220 TJm +(use) 13.2807 Tj +-221 TJm +(dealing) 29.3311 Tj +-221 TJm +(with) 17.7142 Tj +-220 TJm +(lar) 10.511 Tj +18 TJm +(ge) 9.40507 Tj +[1 0 0 1 307.229 193.045] cm +0 g +0 G +[1 0 0 1 -307.229 -193.045] cm +[1 0 0 1 0 0] Tm +0 0 Td +307.229 193.045 Td +/F130_0 9.963 Tf +(.bz2) 23.9112 Tj +[1 0 0 1 331.14 193.045] cm +0 g +0 G +[1 0 0 1 -331.14 -193.045] cm +[1 0 0 1 0 0] Tm +0 0 Td +333.338 193.045 Td +/F128_0 9.963 Tf +(\002les,) 19.0991 Tj +-226 TJm +(as) 8.29918 Tj +-221 TJm +(these) 20.474 Tj +-221 TJm +(will) 15.5024 Tj +-220 TJm +(contain) 29.3311 Tj +-221 TJm +(man) 17.1563 Tj +15 TJm +(y) 4.9815 Tj +-221 TJm +(b) 4.9815 Tj +1 TJm +(locks.) 23.5226 Tj +-601 TJm +(It) 6.08739 Tj +-220 TJm +(is) 6.64532 Tj +-221 TJm +(clearly) 27.1093 Tj +72 181.09 Td +(futile) 21.0319 Tj +-289 TJm +(to) 7.75121 Tj +-289 TJm +(use) 13.2807 Tj +-289 TJm +(it) 5.53943 Tj +-289 TJm +(on) 9.963 Tj +-289 TJm +(damaged) 35.9664 Tj +-289 TJm +(single-block) 49.2571 Tj +-289 TJm +(\002les,) 19.0991 Tj +-299 TJm +(since) 20.474 Tj +-289 TJm +(a) 4.42357 Tj +-289 TJm +(damaged) 35.9664 Tj +-289 TJm +(block) 22.1378 Tj +-289 TJm +(cannot) 26.5614 Tj +-289 TJm +(be) 9.40507 Tj +-289 TJm +(reco) 17.1463 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(ered) 17.1463 Tj +1 TJm +(.) 2.49075 Tj +-855 TJm +(If) 6.63536 Tj +-289 TJm +(you) 14.9445 Tj +-289 TJm +(wish) 18.8201 Tj +-289 TJm +(to) 7.75121 Tj +-289 TJm +(minimise) 37.0922 Tj +72 169.134 Td +(an) 9.40507 Tj +15 TJm +(y) 4.9815 Tj +-320 TJm +(potential) 34.8705 Tj +-319 TJm +(data) 16.5984 Tj +-320 TJm +(loss) 15.5024 Tj +-320 TJm +(through) 30.9949 Tj +-319 TJm +(media) 24.3496 Tj +-320 TJm +(or) 8.29918 Tj +-320 TJm +(transmission) 50.3729 Tj +-319 TJm +(errors,) 25.7245 Tj +-337 TJm +(you) 14.9445 Tj +-320 TJm +(might) 23.2536 Tj +-320 TJm +(consider) 33.7546 Tj +-319 TJm +(compressing) 50.363 Tj +-320 TJm +(with) 17.7142 Tj +-320 TJm +(a) 4.42357 Tj +-319 TJm +(smaller) 29.3311 Tj +-320 TJm +(block) 22.1378 Tj +72 157.179 Td +(size.) 17.9832 Tj +[1 0 0 1 72 157.08] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -147.117] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 122.426 Td +/F121_0 20.659 Tf +(2.7.) 34.4592 Tj +-278 TJm +(PERFORMANCE) 161.822 Tj +-278 TJm +(NO) 30.9885 Tj +40 TJm +(TES) 40.1818 Tj +[1 0 0 1 72 122.168] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -112.206] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 100.509 Td +/F128_0 9.963 Tf +(The) 15.4925 Tj +-304 TJm +(sorting) 27.6772 Tj +-305 TJm +(phase) 22.6858 Tj +-304 TJm +(of) 8.29918 Tj +-305 TJm +(compression) 50.363 Tj +-304 TJm +(g) 4.9815 Tj +5 TJm +(athers) 23.7916 Tj +-305 TJm +(together) 32.6488 Tj +-304 TJm +(similar) 27.6772 Tj +-304 TJm +(strings) 26.5713 Tj +-305 TJm +(in) 7.75121 Tj +-304 TJm +(the) 12.1748 Tj +-305 TJm +(\002le.) 15.2235 Tj +-947 TJm +(Because) 33.1967 Tj +-305 TJm +(of) 8.29918 Tj +-304 TJm +(this,) 16.8873 Tj +-318 TJm +(\002les) 16.6083 Tj +-305 TJm +(contai) 24.3496 Tj +1 TJm +(ning) 17.7142 Tj +-305 TJm +(v) 4.9815 Tj +15 TJm +(ery) 12.7228 Tj +72 88.553 Td +(long) 17.7142 Tj +-286 TJm +(run) 13.2807 Tj +1 TJm +(s) 3.87561 Tj +-286 TJm +(of) 8.29918 Tj +-286 TJm +(repeated) 33.7447 Tj +-285 TJm +(symbols,) 35.7074 Tj +-295 TJm +(l) 2.76971 Tj +1 TJm +(ik) 7.75121 Tj +10 TJm +(e) 4.42357 Tj +-286 TJm +("aabaabaabaab) 59.3795 Tj +-285 TJm +(...") 11.5372 Tj +-572 TJm +(\(repea) 24.8876 Tj +1 TJm +(ted) 12.1748 Tj +-286 TJm +(se) 8.29918 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(eral) 14.9345 Tj +-286 TJm +(hun) 14.9445 Tj +1 TJm +(dred) 17.7043 Tj +-286 TJm +(times\)) 24.9075 Tj +-286 TJm +(m) 7.75121 Tj +1 TJm +(ay) 9.40507 Tj +-286 TJm +(compress) 37.6303 Tj +-286 TJm +(m) 7.75121 Tj +1 TJm +(ore) 12.7228 Tj +-286 TJm +(slo) 11.6268 Tj +25 TJm +(wly) 14.9445 Tj +72 76.598 Td +(than) 17.1563 Tj +-321 TJm +(normal.) 30.7159 Tj +-525 TJm +(V) 7.19329 Tj +111 TJm +(ersions) 28.2252 Tj +-321 TJm +(0.9.5) 19.926 Tj +-322 TJm +(and) 14.3866 Tj +-322 TJm +(a) 4.42357 Tj +1 TJm +(bo) 9.963 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-322 TJm +(f) 3.31768 Tj +10 TJm +(are) 12.1648 Tj +-321 TJm +(much) 22.1378 Tj +-322 TJm +(better) 22.6858 Tj +-321 TJm +(than) 17.1563 Tj +-322 TJm +(pre) 12.7228 Tj +25 TJm +(vious) 21.5898 Tj +-321 TJm +(v) 4.9815 Tj +15 TJm +(ersions) 28.2252 Tj +-322 TJm +(in) 7.75121 Tj +-321 TJm +(this) 14.3965 Tj +-322 TJm +(respect.) 30.706 Tj +-1049 TJm +(The) 15.4925 Tj +-322 TJm +(ratio) 18.2622 Tj +-321 TJm +(between) 33.1967 Tj +[1 0 0 1 72 50.852] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.854] cm +0 g +0 G +0 g +0 G +[1 0 0 1 43.063 -6.755] cm +0 g +0 G +[1 0 0 1 -496.332 -50.951] cm +[1 0 0 1 0 0] Tm +0 0 Td +539.395 50.951 Td +/F128_0 9.963 Tf +(6) 4.9815 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 10 10 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 -8.911] cm +0 g +0 G +[1 0 0 1 0 8.911] cm +0 g +0 G +0 g +0 G +[1 0 0 1 105.519 -6.755] cm +0 g +0 G +[1 0 0 1 -371.59 -749.245] cm +[1 0 0 1 0 0] Tm +0 0 Td +477.109 749.245 Td +/F128_0 9.963 Tf +(Ho) 12.1748 Tj +25 TJm +(w) 7.19329 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(use) 13.2807 Tj +-250 TJm +(bzip2) 22.1378 Tj +[1 0 0 1 266.071 747.089] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -5.037] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -540 -741.554] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 710.037 Td +/F128_0 9.963 Tf +(w) 7.19329 Tj +10 TJm +(orst-case) 35.4085 Tj +-289 TJm +(and) 14.3866 Tj +-290 TJm +(a) 4.42357 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(erage-c) 29.3111 Tj +1 TJm +(ase) 12.7228 Tj +-290 TJm +(compression) 50.363 Tj +-289 TJm +(time) 17.7142 Tj +-289 TJm +(is) 6.64532 Tj +-290 TJm +(in) 7.75121 Tj +-289 TJm +(the) 12.1748 Tj +-290 TJm +(re) 7.74125 Tj +15 TJm +(gion) 17.7142 Tj +-289 TJm +(of) 8.29918 Tj +-289 TJm +(10:1.) 20.205 Tj +-857 TJm +(F) 5.53943 Tj +15 TJm +(or) 8.29918 Tj +-289 TJm +(pre) 12.7228 Tj +25 TJm +(vious) 21.5898 Tj +-290 TJm +(v) 4.9815 Tj +15 TJm +(ersions,) 30.7159 Tj +-299 TJm +(this) 14.3965 Tj +-289 TJm +(\002gure) 23.2437 Tj +-290 TJm +(w) 7.19329 Tj +10 TJm +(as) 8.29918 Tj +-289 TJm +(more) 20.474 Tj +72 698.082 Td +(lik) 10.5209 Tj +10 TJm +(e) 4.42357 Tj +-250 TJm +(100:1.) 25.1865 Tj +-620 TJm +(Y) 7.19329 Tj +110 TJm +(ou) 9.963 Tj +-250 TJm +(can) 13.8286 Tj +-250 TJm +(use) 13.2807 Tj +-250 TJm +(the) 12.1748 Tj +[1 0 0 1 186.002 698.082] cm +0 g +0 G +[1 0 0 1 -186.002 -698.082] cm +[1 0 0 1 0 0] Tm +0 0 Td +186.002 698.082 Td +/F130_0 9.963 Tf +(-vvvv) 29.889 Tj +[1 0 0 1 215.89 698.082] cm +0 g +0 G +[1 0 0 1 -215.89 -698.082] cm +[1 0 0 1 0 0] Tm +0 0 Td +218.38 698.082 Td +/F128_0 9.963 Tf +(option) 25.4654 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(monitor) 31.5528 Tj +-250 TJm +(progress) 33.7546 Tj +-250 TJm +(in) 7.75121 Tj +-250 TJm +(g) 4.9815 Tj +1 TJm +(reat) 14.9345 Tj +-250 TJm +(detail,) 24.6285 Tj +-250 TJm +(if) 6.08739 Tj +-250 TJm +(you) 14.9445 Tj +-250 TJm +(w) 7.19329 Tj +10 TJm +(ant.) 14.6655 Tj +[1 0 0 1 72 695.925] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -685.963] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 676.164 Td +/F128_0 9.963 Tf +(Decompression) 61.9798 Tj +-250 TJm +(speed) 22.6858 Tj +-250 TJm +(is) 6.64532 Tj +-250 TJm +(unaf) 17.7043 Tj +26 TJm +(fected) 24.3396 Tj +-250 TJm +(by) 9.963 Tj +-250 TJm +(these) 20.474 Tj +-250 TJm +(phenomena.) 48.4202 Tj +[1 0 0 1 72 674.008] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -664.045] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 654.247 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 101.888 654.247] cm +0 g +0 G +[1 0 0 1 -101.888 -654.247] cm +[1 0 0 1 0 0] Tm +0 0 Td +104.863 654.247 Td +/F128_0 9.963 Tf +(usually) 28.7831 Tj +-298 TJm +(allocates) 34.8605 Tj +-299 TJm +(se) 8.29918 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(eral) 14.9345 Tj +-298 TJm +(me) 12.1748 Tj +15 TJm +(g) 4.9815 Tj +5 TJm +(abytes) 25.4555 Tj +-299 TJm +(of) 8.29918 Tj +-298 TJm +(memory) 33.2067 Tj +-299 TJm +(to) 7.75121 Tj +-298 TJm +(operate) 29.3211 Tj +-299 TJm +(in,) 10.242 Tj +-311 TJm +(and) 14.3866 Tj +-298 TJm +(then) 17.1563 Tj +-299 TJm +(char) 17.1463 Tj +18 TJm +(ges) 13.2807 Tj +-298 TJm +(all) 9.963 Tj +-299 TJm +(o) 4.9815 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(er) 7.74125 Tj +-298 TJm +(it) 5.53943 Tj +-299 TJm +(in) 7.75121 Tj +-298 TJm +(a) 4.42357 Tj +-299 TJm +(f) 3.31768 Tj +10 TJm +(airly) 18.2622 Tj +-299 TJm +(r) 3.31768 Tj +1 TJm +(andom) 27.1193 Tj +72 642.291 Td +(f) 3.31768 Tj +10 TJm +(ashion.) 28.5041 Tj +-743 TJm +(This) 17.7142 Tj +-270 TJm +(means) 25.4555 Tj +-271 TJm +(t) 2.76971 Tj +1 TJm +(hat) 12.1748 Tj +-271 TJm +(performance,) 52.8338 Tj +-275 TJm +(both) 17.7142 Tj +-271 TJm +(for) 11.6169 Tj +-270 TJm +(compressing) 50.363 Tj +-270 TJm +(and) 14.3866 Tj +-271 TJm +(decompressing,) 62.2588 Tj +-275 TJm +(is) 6.64532 Tj +-271 TJm +(la) 7.19329 Tj +1 TJm +(r) 3.31768 Tj +18 TJm +(gely) 17.1563 Tj +-271 TJm +(determined) 44.8235 Tj +-270 TJm +(by) 9.963 Tj +-271 TJm +(the) 12.1748 Tj +-270 TJm +(speed) 22.6858 Tj +72 630.336 Td +(at) 7.19329 Tj +-294 TJm +(which) 24.3496 Tj +-294 TJm +(your) 18.2622 Tj +-294 TJm +(machine) 33.7546 Tj +-294 TJm +(can) 13.8286 Tj +-294 TJm +(service) 28.2152 Tj +-294 TJm +(cache) 22.6758 Tj +-294 TJm +(misses.) 29.0621 Tj +-442 TJm +(Because) 33.1967 Tj +-294 TJm +(of) 8.29918 Tj +-295 TJm +(t) 2.76971 Tj +1 TJm +(his,) 14.1176 Tj +-306 TJm +(smal) 18.8201 Tj +1 TJm +(l) 2.76971 Tj +-295 TJm +(chang) 23.7916 Tj +1 TJm +(es) 8.29918 Tj +-295 TJm +(to) 7.75121 Tj +-294 TJm +(the) 12.1748 Tj +-294 TJm +(code) 18.8101 Tj +-294 TJm +(to) 7.75121 Tj +-294 TJm +(reduce) 26.5514 Tj +-294 TJm +(the) 12.1748 Tj +-294 TJm +(miss) 18.2721 Tj +-294 TJm +(rate) 14.9345 Tj +72 618.381 Td +(ha) 9.40507 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-253 TJm +(been) 18.8101 Tj +-253 TJm +(observ) 26.5614 Tj +15 TJm +(ed) 9.40507 Tj +-253 TJm +(to) 7.75121 Tj +-253 TJm +(gi) 7.75121 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-253 TJm +(disproportionately) 73.0587 Tj +-253 TJm +(la) 7.19329 Tj +1 TJm +(r) 3.31768 Tj +18 TJm +(ge) 9.40507 Tj +-253 TJm +(performance) 50.343 Tj +-253 TJm +(impro) 23.8016 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(ements.) 30.7159 Tj +-638 TJm +(I) 3.31768 Tj +-253 TJm +(imagine) 32.1008 Tj +[1 0 0 1 438.909 618.381] cm +0 g +0 G +[1 0 0 1 -438.909 -618.381] cm +[1 0 0 1 0 0] Tm +0 0 Td +438.909 618.381 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 468.797 618.381] cm +0 g +0 G +[1 0 0 1 -468.797 -618.381] cm +[1 0 0 1 0 0] Tm +0 0 Td +471.318 618.381 Td +/F128_0 9.963 Tf +(will) 15.5024 Tj +-253 TJm +(perform) 32.0908 Tj +-253 TJm +(best) 16.0504 Tj +72 606.426 Td +(on) 9.963 Tj +-250 TJm +(machines) 37.6303 Tj +-250 TJm +(with) 17.7142 Tj +-250 TJm +(v) 4.9815 Tj +15 TJm +(ery) 12.7228 Tj +-250 TJm +(lar) 10.511 Tj +18 TJm +(ge) 9.40507 Tj +-250 TJm +(c) 4.42357 Tj +1 TJm +(aches.) 24.6186 Tj +[1 0 0 1 72 604.269] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -594.306] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 571.673 Td +/F121_0 20.659 Tf +(2.8.) 34.4592 Tj +-278 TJm +(CA) 29.8316 Tj +80 TJm +(VEA) 42.4749 Tj +90 TJm +(TS) 26.4022 Tj +[1 0 0 1 72 571.415] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -561.452] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 549.755 Td +/F128_0 9.963 Tf +(I/O) 13.2807 Tj +-268 TJm +(error) 19.3581 Tj +-267 TJm +(messages) 37.6303 Tj +-268 TJm +(are) 12.1648 Tj +-267 TJm +(not) 12.7327 Tj +-268 TJm +(as) 8.29918 Tj +-268 TJm +(helpful) 28.2252 Tj +-267 TJm +(as) 8.29918 Tj +-268 TJm +(the) 12.1748 Tj +15 TJm +(y) 4.9815 Tj +-268 TJm +(could) 22.1378 Tj +-267 TJm +(be.) 11.8958 Tj +[1 0 0 1 293.313 549.755] cm +0 g +0 G +[1 0 0 1 -293.313 -549.755] cm +[1 0 0 1 0 0] Tm +0 0 Td +293.313 549.755 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 323.201 549.755] cm +0 g +0 G +[1 0 0 1 -323.201 -549.755] cm +[1 0 0 1 0 0] Tm +0 0 Td +325.868 549.755 Td +/F128_0 9.963 Tf +(tries) 17.1563 Tj +-268 TJm +(hard) 17.7043 Tj +-267 TJm +(to) 7.75121 Tj +-268 TJm +(detect) 23.7916 Tj +-268 TJm +(I/O) 13.2807 Tj +-267 TJm +(errors) 23.2337 Tj +-268 TJm +(and) 14.3866 Tj +-267 TJm +(e) 4.42357 Tj +15 TJm +(xit) 10.5209 Tj +-268 TJm +(cleanly) 28.7731 Tj +65 TJm +(,) 2.49075 Tj +-272 TJm +(b) 4.9815 Tj +20 TJm +(ut) 7.75121 Tj +-268 TJm +(the) 12.1748 Tj +72 537.8 Td +(details) 26.0134 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(what) 19.3681 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(problem) 33.2067 Tj +-249 TJm +(is) 6.64532 Tj +-250 TJm +(sometimes) 42.6217 Tj +-250 TJm +(seem) 20.474 Tj +-250 TJm +(rather) 23.2337 Tj +-250 TJm +(misleading.) 46.2184 Tj +[1 0 0 1 72 535.643] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -525.681] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 515.882 Td +/F128_0 9.963 Tf +(This) 17.7142 Tj +-280 TJm +(manu) 22.1378 Tj +1 TJm +(al) 7.19329 Tj +-280 TJm +(page) 18.8101 Tj +-280 TJm +(pertains) 31.5429 Tj +-279 TJm +(to) 7.75121 Tj +-280 TJm +(v) 4.9815 Tj +15 TJm +(ersion) 24.3496 Tj +-279 TJm +(1.0.3) 19.926 Tj +-280 TJm +(of) 8.29918 Tj +[1 0 0 1 256.84 515.882] cm +0 g +0 G +[1 0 0 1 -256.84 -515.882] cm +[1 0 0 1 0 0] Tm +0 0 Td +256.84 515.882 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 286.727 515.882] cm +0 g +0 G +[1 0 0 1 -286.727 -515.882] cm +[1 0 0 1 0 0] Tm +0 0 Td +286.727 515.882 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +-798 TJm +(Compressed) 49.2571 Tj +-280 TJm +(da) 9.40507 Tj +1 TJm +(ta) 7.19329 Tj +-280 TJm +(created) 28.7632 Tj +-280 TJm +(by) 9.963 Tj +-279 TJm +(this) 14.3965 Tj +-280 TJm +(v) 4.9815 Tj +15 TJm +(ersion) 24.3496 Tj +-279 TJm +(is) 6.64532 Tj +-280 TJm +(entirely) 30.437 Tj +-280 TJm +(forw) 18.8101 Tj +11 TJm +(ards) 16.5984 Tj +72 503.927 Td +(and) 14.3866 Tj +-294 TJm +(backw) 26.0034 Tj +10 TJm +(ards) 16.5984 Tj +-294 TJm +(compatible) 44.2756 Tj +-295 TJm +(wit) 12.7327 Tj +1 TJm +(h) 4.9815 Tj +-295 TJm +(the) 12.1748 Tj +-294 TJm +(pre) 12.7228 Tj +25 TJm +(vious) 21.5898 Tj +-294 TJm +(public) 24.9075 Tj +-294 TJm +(releases,) 34.0236 Tj +-306 TJm +(v) 4.9815 Tj +15 TJm +(ersions) 28.2252 Tj +-294 TJm +(0.1pl2,) 27.6772 Tj +-305 TJm +(0.9.0) 19.926 Tj +-294 TJm +(and) 14.3866 Tj +-295 TJm +(0.9.5,) 22.4168 Tj +-305 TJm +(1.0.0,) 22.4168 Tj +-305 TJm +(1.0.1) 19.926 Tj +-295 TJm +(and) 14.3866 Tj +-294 TJm +(1.0.2,) 22.4168 Tj +72 491.972 Td +(b) 4.9815 Tj +20 TJm +(ut) 7.75121 Tj +-282 TJm +(with) 17.7142 Tj +-283 TJm +(the) 12.1748 Tj +-282 TJm +(follo) 18.8201 Tj +25 TJm +(wing) 19.926 Tj +-282 TJm +(e) 4.42357 Tj +15 TJm +(xception:) 37.0823 Tj +-375 TJm +(0.9.0) 19.926 Tj +-282 TJm +(and) 14.3866 Tj +-282 TJm +(abo) 14.3866 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-283 TJm +(can) 13.8286 Tj +-282 TJm +(correctly) 35.4085 Tj +-282 TJm +(decompress) 47.0353 Tj +-282 TJm +(multiple) 33.2166 Tj +-283 TJm +(concatena) 39.8321 Tj +1 TJm +(ted) 12.1748 Tj +-283 TJm +(compressed) 47.0353 Tj +-282 TJm +(\002les.) 19.0991 Tj +72 480.017 Td +(0.1pl2) 25.1865 Tj +-250 TJm +(cannot) 26.5614 Tj +-250 TJm +(do) 9.963 Tj +-250 TJm +(this;) 17.1662 Tj +-250 TJm +(it) 5.53943 Tj +-250 TJm +(will) 15.5024 Tj +-249 TJm +(stop) 16.6083 Tj +-250 TJm +(after) 18.2522 Tj +-250 TJm +(decompressing) 59.768 Tj +-250 TJm +(just) 14.3965 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(\002rst) 15.5024 Tj +-250 TJm +(\002le) 12.7327 Tj +-250 TJm +(in) 7.75121 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(strea) 18.8101 Tj +1 TJm +(m.) 10.242 Tj +[1 0 0 1 72 477.86] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -467.897] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 458.099 Td +/F130_0 9.963 Tf +(bzip2recover) 71.7336 Tj +[1 0 0 1 143.731 458.099] cm +0 g +0 G +[1 0 0 1 -143.731 -458.099] cm +[1 0 0 1 0 0] Tm +0 0 Td +146.174 458.099 Td +/F128_0 9.963 Tf +(v) 4.9815 Tj +15 TJm +(ersions) 28.2252 Tj +-245 TJm +(prior) 19.3681 Tj +-245 TJm +(to) 7.75121 Tj +-245 TJm +(1.0.2) 19.926 Tj +-245 TJm +(used) 18.2622 Tj +-245 TJm +(32-bit) 23.8016 Tj +-245 TJm +(inte) 14.9445 Tj +15 TJm +(gers) 16.5984 Tj +-245 TJm +(to) 7.75121 Tj +-246 TJm +(repre) 20.464 Tj +1 TJm +(sent) 16.0504 Tj +-246 TJm +(bit) 10.5209 Tj +-245 TJm +(positions) 35.9864 Tj +-245 TJm +(in) 7.75121 Tj +-245 TJm +(compressed) 47.0353 Tj +-245 TJm +(\002les,) 19.0991 Tj +-246 TJm +(so) 8.85711 Tj +-245 TJm +(it) 5.53943 Tj +-245 TJm +(could) 22.1378 Tj +72 446.144 Td +(not) 12.7327 Tj +-383 TJm +(handle) 26.5614 Tj +-384 TJm +(compressed) 47.0353 Tj +-383 TJm +(\002les) 16.6083 Tj +-384 TJm +(more) 20.474 Tj +-383 TJm +(than) 17.1563 Tj +-384 TJm +(51) 9.963 Tj +1 TJm +(2) 4.9815 Tj +-384 TJm +(me) 12.1748 Tj +15 TJm +(g) 4.9815 Tj +5 TJm +(abytes) 25.4555 Tj +-383 TJm +(long.) 20.205 Tj +-1421 TJm +(V) 7.19329 Tj +111 TJm +(ersions) 28.2252 Tj +-384 TJm +(1.0.2) 19.926 Tj +-383 TJm +(and) 14.3866 Tj +-384 TJm +(abo) 14.3866 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-383 TJm +(use) 13.2807 Tj +-384 TJm +(64-bit) 23.8016 Tj +-383 TJm +(ints) 14.3965 Tj +-384 TJm +(on) 9.963 Tj +-383 TJm +(some) 21.0319 Tj +72 434.189 Td +(platforms) 38.1882 Tj +-245 TJm +(which) 24.3496 Tj +-246 TJm +(su) 8.85711 Tj +1 TJm +(pport) 21.0319 Tj +-246 TJm +(them) 19.926 Tj +-245 TJm +(\(GNU) 24.8975 Tj +-245 TJm +(supported) 39.2941 Tj +-246 TJm +(tar) 10.511 Tj +18 TJm +(gets,) 18.5411 Tj +-246 TJm +(and) 14.3866 Tj +-245 TJm +(W) 9.40507 Tj +40 TJm +(indo) 17.7142 Tj +25 TJm +(ws\).) 16.8773 Tj +-309 TJm +(T) 6.08739 Tj +80 TJm +(o) 4.9815 Tj +-245 TJm +(establish) 34.8705 Tj +-245 TJm +(whether) 32.0908 Tj +-245 TJm +(or) 8.29918 Tj +-246 TJm +(not) 12.7327 Tj +[1 0 0 1 468.269 434.189] cm +0 g +0 G +[1 0 0 1 -468.269 -434.189] cm +[1 0 0 1 0 0] Tm +0 0 Td +468.269 434.189 Td +/F130_0 9.963 Tf +(bzip2recover) 71.7336 Tj +[1 0 0 1 540 434.189] cm +0 g +0 G +[1 0 0 1 -540 -434.189] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 422.233 Td +/F128_0 9.963 Tf +(w) 7.19329 Tj +10 TJm +(as) 8.29918 Tj +-255 TJm +(b) 4.9815 Tj +20 TJm +(uilt) 13.2906 Tj +-255 TJm +(with) 17.7142 Tj +-255 TJm +(such) 18.2622 Tj +-255 TJm +(a) 4.42357 Tj +-255 TJm +(limitation,) 41.2468 Tj +-256 TJm +(run) 13.2807 Tj +-255 TJm +(it) 5.53943 Tj +-255 TJm +(without) 30.4469 Tj +-255 TJm +(ar) 7.74125 Tj +18 TJm +(guments.) 36.2554 Tj +-325 TJm +(In) 8.29918 Tj +-255 TJm +(an) 9.40507 Tj +15 TJm +(y) 4.9815 Tj +-255 TJm +(e) 4.42357 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(en) 9.40507 Tj +1 TJm +(t) 2.76971 Tj +-255 TJm +(you) 14.9445 Tj +-255 TJm +(can) 13.8286 Tj +-255 TJm +(b) 4.9815 Tj +20 TJm +(uild) 15.5024 Tj +-255 TJm +(yourself) 32.6488 Tj +-255 TJm +(an) 9.40507 Tj +-255 TJm +(unlimited) 38.1981 Tj +-255 TJm +(v) 4.9815 Tj +15 TJm +(ersion) 24.3496 Tj +-255 TJm +(if) 6.08739 Tj +72 410.278 Td +(you) 14.9445 Tj +-250 TJm +(can) 13.8286 Tj +-250 TJm +(recompile) 39.842 Tj +-250 TJm +(it) 5.53943 Tj +-250 TJm +(with) 17.7142 Tj +[1 0 0 1 176.318 410.278] cm +0 g +0 G +[1 0 0 1 -176.318 -410.278] cm +[1 0 0 1 0 0] Tm +0 0 Td +176.318 410.278 Td +/F130_0 9.963 Tf +(MaybeUInt64) 65.7558 Tj +[1 0 0 1 242.071 410.278] cm +0 g +0 G +[1 0 0 1 -242.071 -410.278] cm +[1 0 0 1 0 0] Tm +0 0 Td +244.562 410.278 Td +/F128_0 9.963 Tf +(set) 11.0689 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(be) 9.40507 Tj +-250 TJm +(an) 9.40507 Tj +-250 TJm +(unsigned) 35.9764 Tj +-250 TJm +(64-bit) 23.8016 Tj +-249 TJm +(inte) 14.9445 Tj +15 TJm +(ger) 12.7228 Tj +55 TJm +(.) 2.49075 Tj +[1 0 0 1 72 408.121] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -398.159] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 375.525 Td +/F121_0 20.659 Tf +(2.9.) 34.4592 Tj +-278 TJm +(A) 14.9158 Tj +50 TJm +(UTHOR) 73.4427 Tj +[1 0 0 1 72 375.267] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -365.305] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 353.608 Td +/F128_0 9.963 Tf +(Julian) 23.8016 Tj +-250 TJm +(Se) 9.963 Tj +25 TJm +(w) 7.19329 Tj +10 TJm +(ard,) 15.2135 Tj +[1 0 0 1 132.801 353.608] cm +0 g +0 G +[1 0 0 1 -132.801 -353.608] cm +[1 0 0 1 0 0] Tm +0 0 Td +132.801 353.608 Td +/F130_0 9.963 Tf +(jseward@bzip.org) 95.6448 Tj +[1 0 0 1 228.443 353.608] cm +0 g +0 G +[1 0 0 1 -156.443 -1.564] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -342.081] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 331.69 Td +/F128_0 9.963 Tf +(The) 15.4925 Tj +-299 TJm +(ideas) 20.474 Tj +-300 TJm +(embodied) 39.2941 Tj +-299 TJm +(in) 7.75121 Tj +[1 0 0 1 166.942 331.69] cm +0 g +0 G +[1 0 0 1 -166.942 -331.69] cm +[1 0 0 1 0 0] Tm +0 0 Td +166.942 331.69 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 196.83 331.69] cm +0 g +0 G +[1 0 0 1 -196.83 -331.69] cm +[1 0 0 1 0 0] Tm +0 0 Td +199.813 331.69 Td +/F128_0 9.963 Tf +(are) 12.1648 Tj +-299 TJm +(due) 14.3866 Tj +-300 TJm +(to) 7.75121 Tj +-299 TJm +(\(at) 10.511 Tj +-300 TJm +(least\)) 21.5799 Tj +-299 TJm +(the) 12.1748 Tj +-299 TJm +(follo) 18.8201 Tj +25 TJm +(wing) 19.926 Tj +-300 TJm +(people:) 29.3311 Tj +-408 TJm +(Michael) 32.6488 Tj +-300 TJm +(Burro) 23.2437 Tj +25 TJm +(ws) 11.0689 Tj +-299 TJm +(and) 14.3866 Tj +-300 TJm +(D) 7.19329 Tj +1 TJm +(a) 4.42357 Tj +20 TJm +(vid) 12.7327 Tj +-300 TJm +(Wheeler) 33.7447 Tj +-299 TJm +(\(for) 14.9345 Tj +72 319.735 Td +(the) 12.1748 Tj +-312 TJm +(block) 22.1378 Tj +-313 TJm +(s) 3.87561 Tj +1 TJm +(orting) 23.8016 Tj +-313 TJm +(transformati) 48.6991 Tj +1 TJm +(on\),) 15.7714 Tj +-328 TJm +(Da) 11.6169 Tj +20 TJm +(vid) 12.7327 Tj +-313 TJm +(Whee) 23.2337 Tj +1 TJm +(ler) 10.511 Tj +-313 TJm +(\(ag) 12.7228 Tj +5 TJm +(ain,) 14.6655 Tj +-328 TJm +(for) 11.6169 Tj +-312 TJm +(the) 12.1748 Tj +-312 TJm +(Huf) 15.4925 Tj +25 TJm +(fman) 20.474 Tj +-312 TJm +(coder\),) 27.9363 Tj +-328 TJm +(Peter) 20.474 Tj +-312 TJm +(Fenwick) 34.3126 Tj +-313 TJm +(\(for) 14.9345 Tj +-312 TJm +(the) 12.1748 Tj +-312 TJm +(structured) 39.842 Tj +72 307.779 Td +(coding) 27.1193 Tj +-325 TJm +(model) 24.9075 Tj +-326 TJm +(in) 7.75121 Tj +-325 TJm +(the) 12.1748 Tj +-326 TJm +(origin) 23.8016 Tj +1 TJm +(al) 7.19329 Tj +[1 0 0 1 191.156 307.779] cm +0 g +0 G +[1 0 0 1 -191.156 -307.779] cm +[1 0 0 1 0 0] Tm +0 0 Td +191.156 307.779 Td +/F130_0 9.963 Tf +(bzip) 23.9112 Tj +[1 0 0 1 215.067 307.779] cm +0 g +0 G +[1 0 0 1 -215.067 -307.779] cm +[1 0 0 1 0 0] Tm +0 0 Td +215.067 307.779 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-344 TJm +(and) 14.3866 Tj +-326 TJm +(man) 17.1563 Tj +15 TJm +(y) 4.9815 Tj +-325 TJm +(re\002nements\),) 52.2958 Tj +-344 TJm +(and) 14.3866 Tj +-326 TJm +(Alistair) 29.889 Tj +-325 TJm +(Mof) 17.1563 Tj +25 TJm +(f) 3.31768 Tj +10 TJm +(at,) 9.68404 Tj +-344 TJm +(Radford) 32.6488 Tj +-326 TJm +(Ne) 11.6169 Tj +1 TJm +(al) 7.19329 Tj +-326 TJm +(and) 14.3866 Tj +-325 TJm +(Ian) 12.7228 Tj +-326 TJm +(W) 9.40507 Tj +40 TJm +(itten) 17.7142 Tj +-325 TJm +(\(for) 14.9345 Tj +72 295.824 Td +(the) 12.1748 Tj +-277 TJm +(arithmetic) 40.4 Tj +-277 TJm +(coder) 22.1278 Tj +-276 TJm +(in) 7.75121 Tj +-277 TJm +(the) 12.1748 Tj +-277 TJm +(original) 30.9949 Tj +[1 0 0 1 214.171 295.824] cm +0 g +0 G +[1 0 0 1 -214.171 -295.824] cm +[1 0 0 1 0 0] Tm +0 0 Td +214.171 295.824 Td +/F130_0 9.963 Tf +(bzip) 23.9112 Tj +[1 0 0 1 238.082 295.824] cm +0 g +0 G +[1 0 0 1 -238.082 -295.824] cm +[1 0 0 1 0 0] Tm +0 0 Td +238.082 295.824 Td +/F128_0 9.963 Tf +(\).) 5.80843 Tj +-782 TJm +(I) 3.31768 Tj +-276 TJm +(am) 12.1748 Tj +-277 TJm +(much) 22.1378 Tj +-277 TJm +(indebted) 34.3126 Tj +-277 TJm +(for) 11.6169 Tj +-277 TJm +(their) 18.2622 Tj +-277 TJm +(help,) 19.647 Tj +-283 TJm +(support) 29.889 Tj +-277 TJm +(and) 14.3866 Tj +-277 TJm +(advice.) 28.4942 Tj +-781 TJm +(See) 14.3866 Tj +-277 TJm +(the) 12.1748 Tj +-277 TJm +(manual) 29.3311 Tj +72 283.869 Td +(in) 7.75121 Tj +-330 TJm +(the) 12.1748 Tj +-330 TJm +(source) 26.0034 Tj +-329 TJm +(distrib) 25.4654 Tj +20 TJm +(ution) 20.4839 Tj +-330 TJm +(for) 11.6169 Tj +-330 TJm +(pointers) 32.1008 Tj +-330 TJm +(to) 7.75121 Tj +-330 TJm +(sour) 17.1563 Tj +1 TJm +(ces) 12.7228 Tj +-330 TJm +(of) 8.29918 Tj +-330 TJm +(documentation.) 61.7108 Tj +-1099 TJm +(Christian) 36.5343 Tj +-330 TJm +(v) 4.9815 Tj +20 TJm +(on) 9.963 Tj +-330 TJm +(Roques) 29.889 Tj +-330 TJm +(encou) 23.7916 Tj +1 TJm +(raged) 22.1278 Tj +-330 TJm +(me) 12.1748 Tj +-330 TJm +(to) 7.75121 Tj +-330 TJm +(look) 17.7142 Tj +72 271.914 Td +(for) 11.6169 Tj +-271 TJm +(f) 3.31768 Tj +10 TJm +(aster) 18.8101 Tj +-271 TJm +(sorting) 27.6772 Tj +-271 TJm +(algorithms,) 45.1125 Tj +-276 TJm +(so) 8.85711 Tj +-271 TJm +(as) 8.29918 Tj +-271 TJm +(to) 7.75121 Tj +-271 TJm +(speed) 22.6858 Tj +-271 TJm +(up) 9.963 Tj +-271 TJm +(compression.) 52.8537 Tj +-746 TJm +(Bela) 18.2622 Tj +-271 TJm +(Lubkin) 28.7831 Tj +-271 TJm +(encouraged) 45.9195 Tj +-271 TJm +(me) 12.1748 Tj +-271 TJm +(to) 7.75121 Tj +-271 TJm +(impro) 23.8016 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-271 TJm +(the) 12.1748 Tj +-271 TJm +(w) 7.19329 Tj +10 TJm +(orst-case) 35.4085 Tj +72 259.959 Td +(compression) 50.363 Tj +-340 TJm +(performan) 41.4959 Tj +1 TJm +(ce.) 11.3379 Tj +-580 TJm +(Donna) 26.5614 Tj +-340 TJm +(Robinson) 38.1981 Tj +-340 TJm +(XMLise) 33.2067 Tj +1 TJm +(d) 4.9815 Tj +-340 TJm +(the) 12.1748 Tj +-340 TJm +(documentation.) 61.7108 Tj +-580 TJm +(Man) 18.2622 Tj +15 TJm +(y) 4.9815 Tj +-339 TJm +(people) 26.5614 Tj +-340 TJm +(sent) 16.0504 Tj +-340 TJm +(patches,) 32.3698 Tj +-362 TJm +(helped) 26.5614 Tj +-340 TJm +(with) 17.7142 Tj +72 248.004 Td +(portability) 41.5158 Tj +-250 TJm +(problems,) 39.573 Tj +-250 TJm +(lent) 14.9445 Tj +-250 TJm +(m) 7.75121 Tj +1 TJm +(achines,) 32.3698 Tj +-250 TJm +(g) 4.9815 Tj +5 TJm +(a) 4.42357 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-250 TJm +(advice) 26.0034 Tj +-250 TJm +(and) 14.3866 Tj +-250 TJm +(were) 19.3581 Tj +-250 TJm +(generally) 37.0723 Tj +-250 TJm +(helpful.) 30.7159 Tj +[1 0 0 1 72 245.847] cm +0 g +0 G +0 g +0 G +[1 0 0 1 0 -194.995] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.585] cm +0 g +0 G +0 g +0 G +[1 0 0 1 43.063 -6.486] cm +0 g +0 G +[1 0 0 1 -496.332 -50.951] cm +[1 0 0 1 0 0] Tm +0 0 Td +539.395 50.951 Td +/F128_0 9.963 Tf +(7) 4.9815 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 11 11 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 4.384 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 141.644 0] cm +0 g +0 G +[1 0 0 1 -141.644 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -13.948] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -15.037 0] cm +0 g +0 G +[1 0 0 1 -468 -21.554] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -720] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 701.916 Td +/F121_0 24.79 Tf +(3.) 20.6749 Tj +-556 TJm +(Pr) 26.1782 Tj +20 TJm +(ogramming) 134.982 Tj +-278 TJm +(with) 49.58 Tj +[1 0 0 1 330.484 701.916] cm +0 g +0 G +[1 0 0 1 -330.484 -701.916] cm +[1 0 0 1 0 0] Tm +0 0 Td +330.484 701.916 Td +/F387_0 24.79 Tf +(libbzip2) 118.992 Tj +[1 0 0 1 449.477 701.916] cm +0 g +0 G +[1 0 0 1 -377.477 -5.516] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -14.944] cm +0 g +0 G +[1 0 0 1 -72 -671.493] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 656.35 Td +/F121_0 17.215 Tf +(T) 10.5184 Tj +80 TJm +(ab) 20.0899 Tj +10 TJm +(le) 14.3573 Tj +-278 TJm +(of) 16.251 Tj +-278 TJm +(Contents) 74.5926 Tj +[1 0 0 1 72 647.528] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -11.74] cm +0 g +0 G +[1 0 0 1 -72 -635.788] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 635.788 Td +/F128_0 9.963 Tf +(3.1.) 14.9445 Tj +-310 TJm +(T) 6.08739 Tj +80 TJm +(op-le) 20.474 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(el) 7.19329 Tj +-250 TJm +(structure) 34.8605 Tj +[1 0 0 1 164.921 635.788] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -169.902 -635.788] cm +[1 0 0 1 0 0] Tm +0 0 Td +179.997 635.788 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 511.108 635.788] cm +0 g +0 G +[1 0 0 1 -511.108 -635.788] cm +[1 0 0 1 0 0] Tm +0 0 Td +511.108 635.788 Td +/F128_0 9.963 Tf +(8) 4.9815 Tj +[1 0 0 1 516.09 635.788] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -9.799] cm +0 g +0 G +[1 0 0 1 -119.821 -623.832] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 623.832 Td +/F128_0 9.963 Tf +(3.1.1.) 22.4168 Tj +-310 TJm +(Lo) 11.0689 Tj +25 TJm +(w-le) 17.7043 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(el) 7.19329 Tj +-250 TJm +(summary) 37.0823 Tj +[1 0 0 1 225.195 623.832] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -230.176 -623.832] cm +[1 0 0 1 0 0] Tm +0 0 Td +238.915 623.832 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 511.108 623.832] cm +0 g +0 G +[1 0 0 1 -511.108 -623.832] cm +[1 0 0 1 0 0] Tm +0 0 Td +511.108 623.832 Td +/F128_0 9.963 Tf +(9) 4.9815 Tj +[1 0 0 1 516.09 623.832] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.156] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -9.799] cm +0 g +0 G +[1 0 0 1 -119.821 -611.877] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 611.877 Td +/F128_0 9.963 Tf +(3.1.2.) 22.4168 Tj +-310 TJm +(High-le) 30.437 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(el) 7.19329 Tj +-250 TJm +(summary) 37.0823 Tj +[1 0 0 1 227.107 611.877] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -232.089 -611.877] cm +[1 0 0 1 0 0] Tm +0 0 Td +242.085 611.877 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 511.108 611.877] cm +0 g +0 G +[1 0 0 1 -511.108 -611.877] cm +[1 0 0 1 0 0] Tm +0 0 Td +511.108 611.877 Td +/F128_0 9.963 Tf +(9) 4.9815 Tj +[1 0 0 1 516.09 611.877] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -9.798] cm +0 g +0 G +[1 0 0 1 -119.821 -599.922] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 599.922 Td +/F128_0 9.963 Tf +(3.1.3.) 22.4168 Tj +-310 TJm +(Utility) 26.0234 Tj +-250 TJm +(functions) 37.0823 Tj +-250 TJm +(sum) 16.6083 Tj +1 TJm +(mary) 20.474 Tj +[1 0 0 1 250.489 599.922] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -255.471 -599.922] cm +[1 0 0 1 0 0] Tm +0 0 Td +264.846 599.922 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 511.108 599.922] cm +0 g +0 G +[1 0 0 1 -511.108 -599.922] cm +[1 0 0 1 0 0] Tm +0 0 Td +511.108 599.922 Td +/F128_0 9.963 Tf +(9) 4.9815 Tj +[1 0 0 1 516.09 599.922] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.798] cm +0 g +0 G +[1 0 0 1 -72 -587.967] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 587.967 Td +/F128_0 9.963 Tf +(3.2.) 14.9445 Tj +-310 TJm +(Error) 21.0219 Tj +-250 TJm +(handling) 34.8705 Tj +[1 0 0 1 148.413 587.967] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -153.394 -587.967] cm +[1 0 0 1 0 0] Tm +0 0 Td +162.611 587.967 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 587.967] cm +0 g +0 G +[1 0 0 1 -506.127 -587.967] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 587.967 Td +/F128_0 9.963 Tf +(10) 9.963 Tj +[1 0 0 1 516.09 587.967] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.798] cm +0 g +0 G +[1 0 0 1 -72 -576.012] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 576.012 Td +/F128_0 9.963 Tf +(3.3.) 14.9445 Tj +-310 TJm +(Lo) 11.0689 Tj +25 TJm +(w-le) 17.7043 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(el) 7.19329 Tj +-250 TJm +(interf) 21.5799 Tj +10 TJm +(ace) 13.2707 Tj +[1 0 0 1 167.571 576.012] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -172.552 -576.012] cm +[1 0 0 1 0 0] Tm +0 0 Td +181.045 576.012 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 576.012] cm +0 g +0 G +[1 0 0 1 -506.127 -576.012] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 576.012 Td +/F128_0 9.963 Tf +(11) 9.963 Tj +[1 0 0 1 516.09 576.012] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -0.1] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -11.855] cm +0 g +0 G +[1 0 0 1 -119.821 -564.057] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 564.057 Td +/F128_0 9.963 Tf +(3.3.1.) 22.4168 Tj +-310 TJm +(BZ2_bzCompressInit) 85.7914 Tj +[1 0 0 1 231.112 564.057] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -236.094 -564.057] cm +[1 0 0 1 0 0] Tm +0 0 Td +246.025 564.057 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 564.057] cm +0 g +0 G +[1 0 0 1 -506.127 -564.057] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 564.057 Td +/F128_0 9.963 Tf +(11) 9.963 Tj +[1 0 0 1 516.09 564.057] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -9.799] cm +0 g +0 G +[1 0 0 1 -119.821 -552.101] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 552.101 Td +/F128_0 9.963 Tf +(3.3.2.) 22.4168 Tj +-310 TJm +(BZ2_bzCompress) 71.9528 Tj +[1 0 0 1 217.275 552.101] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -222.256 -552.101] cm +[1 0 0 1 0 0] Tm +0 0 Td +232.464 552.101 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 552.101] cm +0 g +0 G +[1 0 0 1 -506.127 -552.101] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 552.101 Td +/F128_0 9.963 Tf +(13) 9.963 Tj +[1 0 0 1 516.09 552.101] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.156] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -9.799] cm +0 g +0 G +[1 0 0 1 -119.821 -540.146] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 540.146 Td +/F128_0 9.963 Tf +(3.3.3.) 22.4168 Tj +-310 TJm +(BZ2_bzCompressEnd) 88.0032 Tj +[1 0 0 1 233.324 540.146] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -238.306 -540.146] cm +[1 0 0 1 0 0] Tm +0 0 Td +247.131 540.146 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 540.146] cm +0 g +0 G +[1 0 0 1 -506.127 -540.146] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 540.146 Td +/F128_0 9.963 Tf +(16) 9.963 Tj +[1 0 0 1 516.09 540.146] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -9.798] cm +0 g +0 G +[1 0 0 1 -119.821 -528.191] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 528.191 Td +/F128_0 9.963 Tf +(3.3.4.) 22.4168 Tj +-310 TJm +(BZ2_bzDecompressIni) 92.4168 Tj +1 TJm +(t) 2.76971 Tj +[1 0 0 1 240.507 528.191] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -245.488 -528.191] cm +[1 0 0 1 0 0] Tm +0 0 Td +255.15 528.191 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 528.191] cm +0 g +0 G +[1 0 0 1 -506.127 -528.191] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 528.191 Td +/F128_0 9.963 Tf +(16) 9.963 Tj +[1 0 0 1 516.09 528.191] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -9.798] cm +0 g +0 G +[1 0 0 1 -119.821 -516.236] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 516.236 Td +/F128_0 9.963 Tf +(3.3.5.) 22.4168 Tj +-310 TJm +(BZ2_bzDecompress) 81.3479 Tj +[1 0 0 1 226.669 516.236] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -231.651 -516.236] cm +[1 0 0 1 0 0] Tm +0 0 Td +241.589 516.236 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 516.236] cm +0 g +0 G +[1 0 0 1 -506.127 -516.236] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 516.236 Td +/F128_0 9.963 Tf +(17) 9.963 Tj +[1 0 0 1 516.09 516.236] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -9.798] cm +0 g +0 G +[1 0 0 1 -119.821 -504.281] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 504.281 Td +/F128_0 9.963 Tf +(3.3.6.) 22.4168 Tj +-310 TJm +(BZ2_bzDecompressEn) 92.4168 Tj +1 TJm +(d) 4.9815 Tj +[1 0 0 1 242.719 504.281] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -247.7 -504.281] cm +[1 0 0 1 0 0] Tm +0 0 Td +256.256 504.281 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 504.281] cm +0 g +0 G +[1 0 0 1 -506.127 -504.281] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 504.281 Td +/F128_0 9.963 Tf +(18) 9.963 Tj +[1 0 0 1 516.09 504.281] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.798] cm +0 g +0 G +[1 0 0 1 -72 -492.326] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 492.326 Td +/F128_0 9.963 Tf +(3.4.) 14.9445 Tj +-310 TJm +(High-le) 30.437 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(el) 7.19329 Tj +-250 TJm +(interf) 21.5799 Tj +10 TJm +(ace) 13.2707 Tj +[1 0 0 1 169.483 492.326] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -174.465 -492.326] cm +[1 0 0 1 0 0] Tm +0 0 Td +184.216 492.326 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 492.326] cm +0 g +0 G +[1 0 0 1 -506.127 -492.326] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 492.326 Td +/F128_0 9.963 Tf +(18) 9.963 Tj +[1 0 0 1 516.09 492.326] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -9.799] cm +0 g +0 G +[1 0 0 1 -119.821 -480.37] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 480.37 Td +/F128_0 9.963 Tf +(3.4.1.) 22.4168 Tj +-310 TJm +(BZ2_bzReadOpen) 74.1546 Tj +[1 0 0 1 219.476 480.37] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -224.458 -480.37] cm +[1 0 0 1 0 0] Tm +0 0 Td +233.565 480.37 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 480.37] cm +0 g +0 G +[1 0 0 1 -506.127 -480.37] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 480.37 Td +/F128_0 9.963 Tf +(19) 9.963 Tj +[1 0 0 1 516.09 480.37] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.156] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -9.799] cm +0 g +0 G +[1 0 0 1 -119.821 -468.415] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 468.415 Td +/F128_0 9.963 Tf +(3.4.2.) 22.4168 Tj +-310 TJm +(BZ2_bzRead) 52.5748 Tj +[1 0 0 1 197.898 468.415] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -202.879 -468.415] cm +[1 0 0 1 0 0] Tm +0 0 Td +211.706 468.415 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 468.415] cm +0 g +0 G +[1 0 0 1 -506.127 -468.415] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 468.415 Td +/F128_0 9.963 Tf +(20) 9.963 Tj +[1 0 0 1 516.09 468.415] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -1.18] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -10.775] cm +0 g +0 G +[1 0 0 1 -119.821 -456.46] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 456.46 Td +/F128_0 9.963 Tf +(3.4.3.) 22.4168 Tj +-310 TJm +(BZ2_bzReadGetUnuse) 92.4168 Tj +1 TJm +(d) 4.9815 Tj +[1 0 0 1 242.719 456.46] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -247.7 -456.46] cm +[1 0 0 1 0 0] Tm +0 0 Td +256.256 456.46 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 456.46] cm +0 g +0 G +[1 0 0 1 -506.127 -456.46] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 456.46 Td +/F128_0 9.963 Tf +(21) 9.963 Tj +[1 0 0 1 516.09 456.46] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -1.181] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -10.774] cm +0 g +0 G +[1 0 0 1 -119.821 -444.505] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 444.505 Td +/F128_0 9.963 Tf +(3.4.4.) 22.4168 Tj +-310 TJm +(BZ2_bzReadClose) 75.2705 Tj +[1 0 0 1 220.592 444.505] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -225.573 -444.505] cm +[1 0 0 1 0 0] Tm +0 0 Td +234.123 444.505 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 444.505] cm +0 g +0 G +[1 0 0 1 -506.127 -444.505] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 444.505 Td +/F128_0 9.963 Tf +(22) 9.963 Tj +[1 0 0 1 516.09 444.505] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -1.181] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -10.774] cm +0 g +0 G +[1 0 0 1 -119.821 -432.55] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 432.55 Td +/F128_0 9.963 Tf +(3.4.5.) 22.4168 Tj +-310 TJm +(BZ2_bzWriteOpen) 76.3664 Tj +[1 0 0 1 221.688 432.55] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -226.669 -432.55] cm +[1 0 0 1 0 0] Tm +0 0 Td +236.885 432.55 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 432.55] cm +0 g +0 G +[1 0 0 1 -506.127 -432.55] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 432.55 Td +/F128_0 9.963 Tf +(22) 9.963 Tj +[1 0 0 1 516.09 432.55] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -9.798] cm +0 g +0 G +[1 0 0 1 -119.821 -420.595] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 420.595 Td +/F128_0 9.963 Tf +(3.4.6.) 22.4168 Tj +-310 TJm +(BZ2_bzWrite) 54.7865 Tj +[1 0 0 1 200.109 420.595] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -205.09 -420.595] cm +[1 0 0 1 0 0] Tm +0 0 Td +215.026 420.595 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 420.595] cm +0 g +0 G +[1 0 0 1 -506.127 -420.595] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 420.595 Td +/F128_0 9.963 Tf +(23) 9.963 Tj +[1 0 0 1 516.09 420.595] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -1.181] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -10.775] cm +0 g +0 G +[1 0 0 1 -119.821 -408.639] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 408.639 Td +/F128_0 9.963 Tf +(3.4.7.) 22.4168 Tj +-310 TJm +(BZ2_bzWriteClose) 77.4823 Tj +[1 0 0 1 222.804 408.639] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -227.785 -408.639] cm +[1 0 0 1 0 0] Tm +0 0 Td +237.443 408.639 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 408.639] cm +0 g +0 G +[1 0 0 1 -506.127 -408.639] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 408.639 Td +/F128_0 9.963 Tf +(23) 9.963 Tj +[1 0 0 1 516.09 408.639] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -1.18] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -10.775] cm +0 g +0 G +[1 0 0 1 -119.821 -396.684] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 396.684 Td +/F128_0 9.963 Tf +(3.4.8.) 22.4168 Tj +-310 TJm +(Handling) 37.0823 Tj +-250 TJm +(embedded) 40.9479 Tj +-250 TJm +(com) 17.1563 Tj +1 TJm +(pressed) 29.879 Tj +-250 TJm +(data) 16.5984 Tj +-250 TJm +(streams) 30.437 Tj +[1 0 0 1 327.38 396.684] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -332.362 -396.684] cm +[1 0 0 1 0 0] Tm +0 0 Td +342.865 396.684 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 396.684] cm +0 g +0 G +[1 0 0 1 -506.127 -396.684] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 396.684 Td +/F128_0 9.963 Tf +(24) 9.963 Tj +[1 0 0 1 516.09 396.684] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -9.798] cm +0 g +0 G +[1 0 0 1 -119.821 -384.729] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 384.729 Td +/F128_0 9.963 Tf +(3.4.9.) 22.4168 Tj +-310 TJm +(Standard) 35.4185 Tj +-250 TJm +(\002le-reading/) 48.6991 Tj +1 TJm +(writing) 28.7831 Tj +-250 TJm +(code) 18.8101 Tj +[1 0 0 1 282.011 384.729] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -286.992 -384.729] cm +[1 0 0 1 0 0] Tm +0 0 Td +295.827 384.729 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 384.729] cm +0 g +0 G +[1 0 0 1 -506.127 -384.729] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 384.729 Td +/F128_0 9.963 Tf +(25) 9.963 Tj +[1 0 0 1 516.09 384.729] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.798] cm +0 g +0 G +[1 0 0 1 -72 -372.774] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 372.774 Td +/F128_0 9.963 Tf +(3.5.) 14.9445 Tj +-310 TJm +(Utility) 26.0234 Tj +-250 TJm +(functions) 37.0823 Tj +[1 0 0 1 155.625 372.774] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -160.607 -372.774] cm +[1 0 0 1 0 0] Tm +0 0 Td +170.645 372.774 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 372.774] cm +0 g +0 G +[1 0 0 1 -506.127 -372.774] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 372.774 Td +/F128_0 9.963 Tf +(26) 9.963 Tj +[1 0 0 1 516.09 372.774] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -9.798] cm +0 g +0 G +[1 0 0 1 -119.821 -360.819] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 360.819 Td +/F128_0 9.963 Tf +(3.5.1.) 22.4168 Tj +-310 TJm +(BZ2_bzBuf) 47.0453 Tj +25 TJm +(fT) 9.40507 Tj +80 TJm +(oBuf) 19.926 Tj +25 TJm +(fCom) 22.6957 Tj +1 TJm +(press) 20.474 Tj +[1 0 0 1 263.571 360.819] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -268.552 -360.819] cm +[1 0 0 1 0 0] Tm +0 0 Td +277.751 360.819 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 360.819] cm +0 g +0 G +[1 0 0 1 -506.127 -360.819] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 360.819 Td +/F128_0 9.963 Tf +(26) 9.963 Tj +[1 0 0 1 516.09 360.819] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -9.798] cm +0 g +0 G +[1 0 0 1 -119.821 -348.864] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 348.864 Td +/F128_0 9.963 Tf +(3.5.2.) 22.4168 Tj +-310 TJm +(BZ2_bzBuf) 47.0453 Tj +25 TJm +(fT) 9.40507 Tj +80 TJm +(oBuf) 19.926 Tj +25 TJm +(fDeco) 24.3396 Tj +1 TJm +(mpress) 28.2252 Tj +[1 0 0 1 272.965 348.864] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -277.947 -348.864] cm +[1 0 0 1 0 0] Tm +0 0 Td +286.876 348.864 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 348.864] cm +0 g +0 G +[1 0 0 1 -506.127 -348.864] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 348.864 Td +/F128_0 9.963 Tf +(27) 9.963 Tj +[1 0 0 1 516.09 348.864] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.799] cm +0 g +0 G +[1 0 0 1 -72 -336.908] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 336.908 Td +/F128_0 9.963 Tf +(3.6.) 14.9445 Tj +-310 TJm +(zlib) 14.9445 Tj +-250 TJm +(compatibility) 53.1426 Tj +-250 TJm +(funct) 20.474 Tj +1 TJm +(ions) 16.6083 Tj +[1 0 0 1 200.178 336.908] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -205.159 -336.908] cm +[1 0 0 1 0 0] Tm +0 0 Td +215.06 336.908 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 336.908] cm +0 g +0 G +[1 0 0 1 -506.127 -336.908] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 336.908 Td +/F128_0 9.963 Tf +(28) 9.963 Tj +[1 0 0 1 516.09 336.908] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.156] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.799] cm +0 g +0 G +[1 0 0 1 -72 -324.953] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 324.953 Td +/F128_0 9.963 Tf +(3.7.) 14.9445 Tj +-310 TJm +(Using) 23.8016 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(library) 26.5614 Tj +-250 TJm +(in) 7.75121 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(std) 11.6268 Tj +1 TJm +(io-free) 26.5514 Tj +-250 TJm +(en) 9.40507 Tj +40 TJm +(vironment) 40.9579 Tj +[1 0 0 1 267.824 324.953] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -272.805 -324.953] cm +[1 0 0 1 0 0] Tm +0 0 Td +282.092 324.953 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 324.953] cm +0 g +0 G +[1 0 0 1 -506.127 -324.953] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 324.953 Td +/F128_0 9.963 Tf +(28) 9.963 Tj +[1 0 0 1 516.09 324.953] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -9.798] cm +0 g +0 G +[1 0 0 1 -119.821 -312.998] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 312.998 Td +/F128_0 9.963 Tf +(3.7.1.) 22.4168 Tj +-310 TJm +(Getting) 29.889 Tj +-250 TJm +(rid) 11.0689 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(stdio) 19.378 Tj +[1 0 0 1 221.429 312.998] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -226.41 -312.998] cm +[1 0 0 1 0 0] Tm +0 0 Td +236.755 312.998 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 312.998] cm +0 g +0 G +[1 0 0 1 -506.127 -312.998] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 312.998 Td +/F128_0 9.963 Tf +(29) 9.963 Tj +[1 0 0 1 516.09 312.998] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 47.821 -9.798] cm +0 g +0 G +[1 0 0 1 -119.821 -301.043] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 301.043 Td +/F128_0 9.963 Tf +(3.7.2.) 22.4168 Tj +-310 TJm +(Critical) 29.889 Tj +-250 TJm +(error) 19.3581 Tj +-250 TJm +(handlin) 29.889 Tj +1 TJm +(g) 4.9815 Tj +[1 0 0 1 234.42 301.043] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -239.401 -301.043] cm +[1 0 0 1 0 0] Tm +0 0 Td +249.892 301.043 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 301.043] cm +0 g +0 G +[1 0 0 1 -506.127 -301.043] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 301.043 Td +/F128_0 9.963 Tf +(29) 9.963 Tj +[1 0 0 1 516.09 301.043] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.798] cm +0 g +0 G +[1 0 0 1 -72 -289.088] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 289.088 Td +/F128_0 9.963 Tf +(3.8.) 14.9445 Tj +-310 TJm +(Making) 30.9949 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(W) 9.40507 Tj +40 TJm +(indo) 17.7142 Tj +25 TJm +(ws) 11.0689 Tj +-250 TJm +(DLL) 19.3681 Tj +[1 0 0 1 189.827 289.088] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -194.809 -289.088] cm +[1 0 0 1 0 0] Tm +0 0 Td +203.243 289.088 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 289.088] cm +0 g +0 G +[1 0 0 1 -506.127 -289.088] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 289.088 Td +/F128_0 9.963 Tf +(29) 9.963 Tj +[1 0 0 1 516.09 289.088] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -267.006] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 257.207 Td +/F128_0 9.963 Tf +(This) 17.7142 Tj +-250 TJm +(chapter) 29.3211 Tj +-250 TJm +(describes) 37.0723 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(pr) 8.29918 Tj +1 TJm +(ogramming) 45.9394 Tj +-250 TJm +(interf) 21.5799 Tj +10 TJm +(ace) 13.2707 Tj +-250 TJm +(to) 7.75121 Tj +[1 0 0 1 282.448 257.207] cm +0 g +0 G +[1 0 0 1 -282.448 -257.207] cm +[1 0 0 1 0 0] Tm +0 0 Td +282.448 257.207 Td +/F130_0 9.963 Tf +(libbzip2) 47.8224 Tj +[1 0 0 1 330.269 257.207] cm +0 g +0 G +[1 0 0 1 -330.269 -257.207] cm +[1 0 0 1 0 0] Tm +0 0 Td +330.269 257.207 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 72 255.05] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -245.088] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 235.289 Td +/F128_0 9.963 Tf +(F) 5.53943 Tj +15 TJm +(or) 8.29918 Tj +-273 TJm +(general) 29.3211 Tj +-272 TJm +(background) 47.0353 Tj +-273 TJm +(informati) 37.0823 Tj +1 TJm +(on,) 12.4538 Tj +-279 TJm +(particularly) 45.9294 Tj +-272 TJm +(about) 22.1378 Tj +-273 TJm +(memory) 33.2067 Tj +-272 TJm +(use) 13.2807 Tj +-273 TJm +(and) 14.3866 Tj +-273 TJm +(perfor) 24.3396 Tj +1 TJm +(mance) 26.0034 Tj +-273 TJm +(aspects,) 31.2639 Tj +-278 TJm +(you') 18.2622 Tj +50 TJm +(d) 4.9815 Tj +-273 TJm +(be) 9.40507 Tj +-272 TJm +(well) 17.1563 Tj +-273 TJm +(advised) 30.437 Tj +72 223.334 Td +(to) 7.75121 Tj +-250 TJm +(read) 17.1463 Tj +[1 0 0 1 101.878 223.334] cm +0 0 1 rg +0 0 1 RG +[1 0 0 1 -101.878 -223.334] cm +[1 0 0 1 0 0] Tm +0 0 Td +101.878 223.334 Td +/F128_0 9.963 Tf +(Ho) 12.1748 Tj +25 TJm +(w) 7.19329 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(use) 13.2807 Tj +-250 TJm +(bzip2) 22.1378 Tj +[1 0 0 1 171.636 223.334] cm +0 g +0 G +0 0 1 rg +0 0 1 RG +0 0 1 rg +0 0 1 RG +[1 0 0 1 -171.636 -223.334] cm +[1 0 0 1 0 0] Tm +0 0 Td +174.126 223.334 Td +/F128_0 9.963 Tf +([2]) 11.6169 Tj +[1 0 0 1 185.743 223.334] cm +0 0 1 rg +0 0 1 RG +0 g +0 G +[1 0 0 1 -185.743 -223.334] cm +[1 0 0 1 0 0] Tm +0 0 Td +188.233 223.334 Td +/F128_0 9.963 Tf +(as) 8.29918 Tj +-250 TJm +(well.) 19.647 Tj +[1 0 0 1 72 221.177] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -211.215] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 188.581 Td +/F121_0 20.659 Tf +(3.1.) 34.4592 Tj +-278 TJm +(T) 12.6226 Tj +80 TJm +(op-le) 49.3544 Tj +15 TJm +(vel) 28.716 Tj +-278 TJm +(structure) 89.5361 Tj +[1 0 0 1 72 184.305] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -174.343] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 166.664 Td +/F130_0 9.963 Tf +(libbzip2) 47.8224 Tj +[1 0 0 1 119.821 166.664] cm +0 g +0 G +[1 0 0 1 -119.821 -166.664] cm +[1 0 0 1 0 0] Tm +0 0 Td +123.608 166.664 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-380 TJm +(a) 4.42357 Tj +-380 TJm +(\003e) 9.963 Tj +15 TJm +(xible) 19.926 Tj +-380 TJm +(library) 26.5614 Tj +-380 TJm +(for) 11.6169 Tj +-381 TJm +(com) 17.1563 Tj +1 TJm +(pressing) 33.2067 Tj +-381 TJm +(an) 9.40507 Tj +1 TJm +(d) 4.9815 Tj +-381 TJm +(decompre) 39.2841 Tj +1 TJm +(ssing) 20.4839 Tj +-381 TJm +(data) 16.5984 Tj +-380 TJm +(in) 7.75121 Tj +-380 TJm +(the) 12.1748 Tj +[1 0 0 1 405.291 166.664] cm +0 g +0 G +[1 0 0 1 -405.291 -166.664] cm +[1 0 0 1 0 0] Tm +0 0 Td +405.291 166.664 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 435.179 166.664] cm +0 g +0 G +[1 0 0 1 -435.179 -166.664] cm +[1 0 0 1 0 0] Tm +0 0 Td +438.966 166.664 Td +/F128_0 9.963 Tf +(data) 16.5984 Tj +-380 TJm +(format.) 29.0521 Tj +-1401 TJm +(Although) 37.6402 Tj +72 154.708 Td +(packaged) 37.6203 Tj +-285 TJm +(as) 8.29918 Tj +-284 TJm +(a) 4.42357 Tj +-285 TJm +(single) 23.8016 Tj +-284 TJm +(entity) 22.6957 Tj +65 TJm +(,) 2.49075 Tj +-294 TJm +(it) 5.53943 Tj +-284 TJm +(helps) 21.0319 Tj +-285 TJm +(to) 7.75121 Tj +-285 TJm +(re) 7.74125 Tj +15 TJm +(g) 4.9815 Tj +5 TJm +(ard) 12.7228 Tj +-284 TJm +(the) 12.1748 Tj +-285 TJm +(library) 26.5614 Tj +-285 TJm +(a) 4.42357 Tj +1 TJm +(s) 3.87561 Tj +-285 TJm +(three) 19.916 Tj +-285 TJm +(separate) 32.6388 Tj +-284 TJm +(parts:) 22.1378 Tj +-380 TJm +(the) 12.1748 Tj +-284 TJm +(lo) 7.75121 Tj +25 TJm +(w) 7.19329 Tj +-285 TJm +(le) 7.19329 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(el) 7.19329 Tj +-285 TJm +(i) 2.76971 Tj +1 TJm +(nterf) 18.8101 Tj +10 TJm +(ace,) 15.7615 Tj +-294 TJm +(and) 14.3866 Tj +-284 TJm +(the) 12.1748 Tj +-285 TJm +(high) 17.7142 Tj +72 142.753 Td +(le) 7.19329 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(el) 7.19329 Tj +-250 TJm +(interf) 21.5799 Tj +10 TJm +(ace,) 15.7615 Tj +-250 TJm +(and) 14.3866 Tj +-250 TJm +(some) 21.0319 Tj +-250 TJm +(uti) 10.5209 Tj +1 TJm +(lity) 13.2906 Tj +-250 TJm +(functions.) 39.573 Tj +[1 0 0 1 72 140.596] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -130.634] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 120.835 Td +/F128_0 9.963 Tf +(The) 15.4925 Tj +-349 TJm +(structure) 34.8605 Tj +-349 TJm +(of) 8.29918 Tj +[1 0 0 1 141.082 120.835] cm +0 g +0 G +[1 0 0 1 -141.082 -120.835] cm +[1 0 0 1 0 0] Tm +0 0 Td +141.082 120.835 Td +/F130_0 9.963 Tf +(libbzip2) 47.8224 Tj +[1 0 0 1 188.903 120.835] cm +0 g +0 G +[1 0 0 1 -188.903 -120.835] cm +[1 0 0 1 0 0] Tm +0 0 Td +188.903 120.835 Td +/F128_0 9.963 Tf +(') 3.31768 Tj +55 TJm +(s) 3.87561 Tj +-349 TJm +(interf) 21.5799 Tj +10 TJm +(aces) 17.1463 Tj +-349 TJm +(is) 6.64532 Tj +-349 TJm +(similar) 27.6772 Tj +-349 TJm +(to) 7.75121 Tj +-349 TJm +(that) 14.9445 Tj +-349 TJm +(of) 8.29918 Tj +-349 TJm +(Jean-loup) 38.7361 Tj +-349 TJm +(Gailly') 28.2252 Tj +55 TJm +(s) 3.87561 Tj +-349 TJm +(an) 9.40507 Tj +1 TJm +(d) 4.9815 Tj +-350 TJm +(M) 8.85711 Tj +1 TJm +(ark) 12.7228 Tj +-349 TJm +(Adler') 26.0034 Tj +55 TJm +(s) 3.87561 Tj +-349 TJm +(e) 4.42357 Tj +15 TJm +(xcellent) 31.5429 Tj +[1 0 0 1 516.09 120.835] cm +0 g +0 G +[1 0 0 1 -516.09 -120.835] cm +[1 0 0 1 0 0] Tm +0 0 Td +516.09 120.835 Td +/F130_0 9.963 Tf +(zlib) 23.9112 Tj +[1 0 0 1 540 120.835] cm +0 g +0 G +[1 0 0 1 -540 -120.835] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 108.88 Td +/F128_0 9.963 Tf +(library) 26.5614 Tj +65 TJm +(.) 2.49075 Tj +[1 0 0 1 72 106.723] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -96.761] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 86.962 Td +/F128_0 9.963 Tf +(All) 12.7327 Tj +-242 TJm +(e) 4.42357 Tj +15 TJm +(xternally) 35.4185 Tj +-241 TJm +(visible) 26.5713 Tj +-242 TJm +(symbols) 33.2166 Tj +-242 TJm +(ha) 9.40507 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-241 TJm +(names) 25.4555 Tj +-242 TJm +(be) 9.40507 Tj +15 TJm +(ginning) 30.4469 Tj +[1 0 0 1 284.687 86.962] cm +0 g +0 G +[1 0 0 1 -284.687 -86.962] cm +[1 0 0 1 0 0] Tm +0 0 Td +284.687 86.962 Td +/F130_0 9.963 Tf +(BZ2_) 23.9112 Tj +[1 0 0 1 308.597 86.962] cm +0 g +0 G +[1 0 0 1 -308.597 -86.962] cm +[1 0 0 1 0 0] Tm +0 0 Td +308.597 86.962 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +-615 TJm +(T) 6.08739 Tj +1 TJm +(his) 11.6268 Tj +-242 TJm +(is) 6.64532 Tj +-242 TJm +(ne) 9.40507 Tj +25 TJm +(w) 7.19329 Tj +-242 TJm +(in) 7.75121 Tj +-241 TJm +(v) 4.9815 Tj +15 TJm +(ersion) 24.3496 Tj +-242 TJm +(1.0.) 14.9445 Tj +-615 TJm +(The) 15.4925 Tj +-241 TJm +(intention) 35.4284 Tj +-242 TJm +(is) 6.64532 Tj +-242 TJm +(to) 7.75121 Tj +-241 TJm +(minimise) 37.0922 Tj +72 75.007 Td +(pollution) 35.9864 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(namespaces) 47.5833 Tj +-249 TJm +(of) 8.29918 Tj +-250 TJm +(library) 26.5614 Tj +-250 TJm +(clients.) 28.5041 Tj +[1 0 0 1 72 72.85] cm +0 g +0 G +[1 0 0 1 0 -21.998] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 4.384 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 0 6.854] cm +0 g +0 G +0 g +0 G +[1 0 0 1 43.064 -6.755] cm +0 g +0 G +[1 0 0 1 -498.225 -50.951] cm +[1 0 0 1 0 0] Tm +0 0 Td +541.288 50.951 Td +/F128_0 9.963 Tf +(8) 4.9815 Tj +[1 0 0 1 455.161 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.599 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -15.037 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 12 12 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 4.384 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 -8.911] cm +0 g +0 G +[1 0 0 1 0 8.911] cm +0 g +0 G +0 g +0 G +[1 0 0 1 84.08 -6.755] cm +0 g +0 G +[1 0 0 1 -352.044 -749.245] cm +[1 0 0 1 0 0] Tm +0 0 Td +436.124 749.245 Td +/F128_0 9.963 Tf +(Programming) 54.7965 Tj +-250 TJm +(with) 17.7142 Tj +-250 TJm +(libbzip) 27.6772 Tj +1 TJm +(2) 4.9815 Tj +[1 0 0 1 267.964 747.089] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -5.037] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -15.037 0] cm +0 g +0 G +[1 0 0 1 -468 -21.554] cm +0 g +0 G +[1 0 0 1 -72 -720] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 710.037 Td +/F128_0 9.963 Tf +(T) 6.08739 Tj +80 TJm +(o) 4.9815 Tj +-250 TJm +(use) 13.2807 Tj +-250 TJm +(an) 9.40507 Tj +15 TJm +(y) 4.9815 Tj +-250 TJm +(part) 15.4925 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(library) 26.5614 Tj +65 TJm +(,) 2.49075 Tj +-250 TJm +(yo) 9.963 Tj +1 TJm +(u) 4.9815 Tj +-250 TJm +(need) 18.8101 Tj +-250 TJm +(to) 7.75121 Tj +[1 0 0 1 240.567 710.037] cm +0 g +0 G +[1 0 0 1 -240.567 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +240.567 710.037 Td +/F130_0 9.963 Tf +(#include) 47.8224 Tj +-600 TJm +() 53.8002 Tj +[1 0 0 1 348.163 710.037] cm +0 g +0 G +[1 0 0 1 -348.163 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +350.654 710.037 Td +/F128_0 9.963 Tf +(into) 15.5024 Tj +-250 TJm +(your) 18.2622 Tj +-250 TJm +(sources.) 32.3698 Tj +[1 0 0 1 72 707.881] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -697.918] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 679.416 Td +/F121_0 17.215 Tf +(3.1.1.) 43.0719 Tj +-278 TJm +(Lo) 21.0367 Tj +15 TJm +(w-le) 33.4832 Tj +15 TJm +(vel) 23.9289 Tj +-278 TJm +(summar) 66.9664 Tj +-10 TJm +(y) 9.57154 Tj +[1 0 0 1 72 675.853] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -665.89] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 657.498 Td +/F128_0 9.963 Tf +(This) 17.7142 Tj +-212 TJm +(interf) 21.5799 Tj +10 TJm +(ace) 13.2707 Tj +-212 TJm +(pro) 13.2807 Tj +15 TJm +(vides) 21.0319 Tj +-211 TJm +(services) 32.0908 Tj +-212 TJm +(for) 11.6169 Tj +-212 TJm +(compressing) 50.363 Tj +-212 TJm +(and) 14.3866 Tj +-212 TJm +(decompressi) 49.805 Tj +1 TJm +(ng) 9.963 Tj +-212 TJm +(data) 16.5984 Tj +-212 TJm +(in) 7.75121 Tj +-212 TJm +(memory) 33.2067 Tj +65 TJm +(.) 2.49075 Tj +-595 TJm +(There') 26.5514 Tj +55 TJm +(s) 3.87561 Tj +-211 TJm +(no) 9.963 Tj +-212 TJm +(pro) 13.2807 Tj +15 TJm +(vision) 24.3595 Tj +-212 TJm +(for) 11.6169 Tj +-212 TJm +(dealing) 29.3311 Tj +72 645.543 Td +(with) 17.7142 Tj +-213 TJm +(\002les,) 19.0991 Tj +-220 TJm +(streams) 30.437 Tj +-213 TJm +(or) 8.29918 Tj +-213 TJm +(an) 9.40507 Tj +15 TJm +(y) 4.9815 Tj +-213 TJm +(other) 20.474 Tj +-213 TJm +(I/O) 13.2807 Tj +-213 TJm +(mechanisms,) 51.7478 Tj +-220 TJm +(just) 14.3965 Tj +-213 TJm +(straight) 29.889 Tj +-213 TJm +(memory-to-memory) 80.7999 Tj +-213 TJm +(w) 7.19329 Tj +10 TJm +(ork.) 15.7714 Tj +-595 TJm +(In) 8.29918 Tj +-213 TJm +(f) 3.31768 Tj +10 TJm +(act,) 14.1076 Tj +-220 TJm +(this) 14.3965 Tj +-213 TJm +(part) 15.4925 Tj +-213 TJm +(of) 8.29918 Tj +-213 TJm +(the) 12.1748 Tj +-213 TJm +(library) 26.5614 Tj +72 633.588 Td +(can) 13.8286 Tj +-250 TJm +(be) 9.40507 Tj +-250 TJm +(compiled) 37.0823 Tj +-250 TJm +(without) 30.4469 Tj +-250 TJm +(incl) 14.9445 Tj +1 TJm +(usion) 21.5898 Tj +-250 TJm +(of) 8.29918 Tj +[1 0 0 1 222.534 633.588] cm +0 g +0 G +[1 0 0 1 -222.534 -633.588] cm +[1 0 0 1 0 0] Tm +0 0 Td +222.534 633.588 Td +/F130_0 9.963 Tf +(stdio.h) 41.8446 Tj +[1 0 0 1 264.377 633.588] cm +0 g +0 G +[1 0 0 1 -264.377 -633.588] cm +[1 0 0 1 0 0] Tm +0 0 Td +264.377 633.588 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-250 TJm +(which) 24.3496 Tj +-250 TJm +(may) 17.1563 Tj +-250 TJm +(be) 9.40507 Tj +-250 TJm +(helpful) 28.2252 Tj +-250 TJm +(for) 11.6169 Tj +-250 TJm +(emb) 17.1563 Tj +1 TJm +(edded) 23.7916 Tj +-250 TJm +(applications.) 50.6419 Tj +[1 0 0 1 72 631.431] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -621.469] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 611.67 Td +/F128_0 9.963 Tf +(The) 15.4925 Tj +-250 TJm +(lo) 7.75121 Tj +25 TJm +(w-le) 17.7043 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(el) 7.19329 Tj +-250 TJm +(part) 15.4925 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(libra) 18.2622 Tj +1 TJm +(ry) 8.29918 Tj +-250 TJm +(has) 13.2807 Tj +-250 TJm +(no) 9.963 Tj +-250 TJm +(global) 24.9075 Tj +-250 TJm +(v) 4.9815 Tj +25 TJm +(ariables) 30.9849 Tj +-250 TJm +(and) 14.3866 Tj +-250 TJm +(is) 6.64532 Tj +-250 TJm +(therefore) 35.9565 Tj +-250 TJm +(thread-safe.) 46.7464 Tj +[1 0 0 1 72 609.513] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -599.551] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 589.752 Td +/F128_0 9.963 Tf +(Six) 13.2906 Tj +-875 TJm +(routines) 32.1008 Tj +-876 TJm +(mak) 17.1563 Tj +10 TJm +(e) 4.42357 Tj +-875 TJm +(up) 9.963 Tj +-875 TJm +(the) 12.1748 Tj +-876 TJm +(lo) 7.75121 Tj +25 TJm +(w) 7.19329 Tj +-875 TJm +(le) 7.19329 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(el) 7.19329 Tj +-875 TJm +(interf) 21.5799 Tj +10 TJm +(ace:) 16.0404 Tj +[1 0 0 1 308.791 589.752] cm +0 g +0 G +[1 0 0 1 -308.791 -589.752] cm +[1 0 0 1 0 0] Tm +0 0 Td +308.791 589.752 Td +/F130_0 9.963 Tf +(BZ2_bzCompressInit) 107.6 Tj +[1 0 0 1 416.387 589.752] cm +0 g +0 G +[1 0 0 1 -416.387 -589.752] cm +[1 0 0 1 0 0] Tm +0 0 Td +416.387 589.752 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 429.158 589.752] cm +0 g +0 G +[1 0 0 1 -429.158 -589.752] cm +[1 0 0 1 0 0] Tm +0 0 Td +429.158 589.752 Td +/F130_0 9.963 Tf +(BZ2_bzCompress) 83.6892 Tj +[1 0 0 1 512.844 589.752] cm +0 g +0 G +[1 0 0 1 -512.844 -589.752] cm +[1 0 0 1 0 0] Tm +0 0 Td +512.844 589.752 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-1032 TJm +(and) 14.3866 Tj +[1 0 0 1 72 577.797] cm +0 g +0 G +[1 0 0 1 -72 -577.797] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 577.797 Td +/F130_0 9.963 Tf +(BZ2_bzCompressEnd) 101.623 Tj +[1 0 0 1 173.619 577.797] cm +0 g +0 G +[1 0 0 1 -173.619 -577.797] cm +[1 0 0 1 0 0] Tm +0 0 Td +186.15 577.797 Td +/F128_0 9.963 Tf +(for) 11.6169 Tj +-1258 TJm +(compression,) 52.8537 Tj +-1509 TJm +(and) 14.3866 Tj +-1258 TJm +(a) 4.42357 Tj +-1258 TJm +(correspond) 44.2656 Tj +1 TJm +(ing) 12.7327 Tj +-1258 TJm +(trio) 13.8386 Tj +[1 0 0 1 417.958 577.797] cm +0 g +0 G +[1 0 0 1 -417.958 -577.797] cm +[1 0 0 1 0 0] Tm +0 0 Td +417.958 577.797 Td +/F130_0 9.963 Tf +(BZ2_bzDecompressInit) 119.556 Tj +[1 0 0 1 537.509 577.797] cm +0 g +0 G +[1 0 0 1 -537.509 -577.797] cm +[1 0 0 1 0 0] Tm +0 0 Td +537.509 577.797 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 72 565.842] cm +0 g +0 G +[1 0 0 1 -72 -565.842] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 565.842 Td +/F130_0 9.963 Tf +(BZ2_bzDecompress) 95.6448 Tj +[1 0 0 1 167.641 565.842] cm +0 g +0 G +[1 0 0 1 -167.641 -565.842] cm +[1 0 0 1 0 0] Tm +0 0 Td +172.707 565.842 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 192.158 565.842] cm +0 g +0 G +[1 0 0 1 -192.158 -565.842] cm +[1 0 0 1 0 0] Tm +0 0 Td +192.158 565.842 Td +/F130_0 9.963 Tf +(BZ2_bzDecompressEnd) 113.578 Tj +[1 0 0 1 305.732 565.842] cm +0 g +0 G +[1 0 0 1 -305.732 -565.842] cm +[1 0 0 1 0 0] Tm +0 0 Td +310.798 565.842 Td +/F128_0 9.963 Tf +(for) 11.6169 Tj +-508 TJm +(decompression.) 62.2588 Tj +-2171 TJm +(The) 15.4925 Tj +[1 0 0 1 431.918 565.842] cm +0 g +0 G +[1 0 0 1 -431.918 -565.842] cm +[1 0 0 1 0 0] Tm +0 0 Td +431.918 565.842 Td +/F130_0 9.963 Tf +(*Init) 29.889 Tj +[1 0 0 1 461.805 565.842] cm +0 g +0 G +[1 0 0 1 -461.805 -565.842] cm +[1 0 0 1 0 0] Tm +0 0 Td +466.871 565.842 Td +/F128_0 9.963 Tf +(functions) 37.0823 Tj +-508 TJm +(allocate) 30.9849 Tj +72 553.887 Td +(memory) 33.2067 Tj +-574 TJm +(f) 3.31768 Tj +1 TJm +(or) 8.29918 Tj +-574 TJm +(compression/decompression) 112.901 Tj +-573 TJm +(and) 14.3866 Tj +-574 TJm +(do) 9.963 Tj +-573 TJm +(other) 20.474 Tj +-574 TJm +(initialisations,) 56.1913 Tj +-654 TJm +(whilst) 24.3595 Tj +-574 TJm +(the) 12.1748 Tj +[1 0 0 1 419.503 553.887] cm +0 g +0 G +[1 0 0 1 -419.503 -553.887] cm +[1 0 0 1 0 0] Tm +0 0 Td +419.503 553.887 Td +/F130_0 9.963 Tf +(*End) 23.9112 Tj +[1 0 0 1 443.413 553.887] cm +0 g +0 G +[1 0 0 1 -443.413 -553.887] cm +[1 0 0 1 0 0] Tm +0 0 Td +449.128 553.887 Td +/F128_0 9.963 Tf +(functions) 37.0823 Tj +-573 TJm +(close) 20.474 Tj +-574 TJm +(do) 9.963 Tj +25 TJm +(wn) 12.1748 Tj +72 541.932 Td +(operations) 41.5059 Tj +-250 TJm +(and) 14.3866 Tj +-250 TJm +(release) 27.6573 Tj +-250 TJm +(mem) 19.926 Tj +1 TJm +(ory) 13.2807 Tj +65 TJm +(.) 2.49075 Tj +[1 0 0 1 72 539.775] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -529.812] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 520.014 Td +/F128_0 9.963 Tf +(The) 15.4925 Tj +-303 TJm +(real) 14.9345 Tj +-303 TJm +(w) 7.19329 Tj +10 TJm +(ork) 13.2807 Tj +-303 TJm +(is) 6.64532 Tj +-303 TJm +(done) 19.3681 Tj +-303 TJm +(by) 9.963 Tj +[1 0 0 1 176.892 520.014] cm +0 g +0 G +[1 0 0 1 -176.892 -520.014] cm +[1 0 0 1 0 0] Tm +0 0 Td +176.892 520.014 Td +/F130_0 9.963 Tf +(BZ2_bzCompress) 83.6892 Tj +[1 0 0 1 260.578 520.014] cm +0 g +0 G +[1 0 0 1 -260.578 -520.014] cm +[1 0 0 1 0 0] Tm +0 0 Td +263.598 520.014 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 281.003 520.014] cm +0 g +0 G +[1 0 0 1 -281.003 -520.014] cm +[1 0 0 1 0 0] Tm +0 0 Td +281.003 520.014 Td +/F130_0 9.963 Tf +(BZ2_bzDecompress) 95.6448 Tj +[1 0 0 1 376.645 520.014] cm +0 g +0 G +[1 0 0 1 -376.645 -520.014] cm +[1 0 0 1 0 0] Tm +0 0 Td +376.645 520.014 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +-938 TJm +(These) 23.7916 Tj +-303 TJm +(compress) 37.6303 Tj +-303 TJm +(and) 14.3866 Tj +-303 TJm +(decompress) 47.0353 Tj +-303 TJm +(data) 16.5984 Tj +72 508.059 Td +(from) 19.3681 Tj +-205 TJm +(a) 4.42357 Tj +-205 TJm +(user) 16.5984 Tj +20 TJm +(-supplied) 37.0823 Tj +-205 TJm +(input) 20.4839 Tj +-205 TJm +(b) 4.9815 Tj +20 TJm +(uf) 8.29918 Tj +25 TJm +(fer) 11.0589 Tj +-205 TJm +(to) 7.75121 Tj +-205 TJm +(a) 4.42357 Tj +-206 TJm +(use) 13.2807 Tj +1 TJm +(r) 3.31768 Tj +20 TJm +(-supplied) 37.0823 Tj +-205 TJm +(output) 25.4654 Tj +-206 TJm +(b) 4.9815 Tj +20 TJm +(u) 4.9815 Tj +1 TJm +(f) 3.31768 Tj +25 TJm +(fer) 11.0589 Tj +55 TJm +(.) 2.49075 Tj +-591 TJm +(T) 6.08739 Tj +1 TJm +(hese) 17.7043 Tj +-206 TJm +(b) 4.9815 Tj +20 TJm +(uf) 8.29918 Tj +25 TJm +(fer) 11.0589 Tj +1 TJm +(s) 3.87561 Tj +-206 TJm +(can) 13.8286 Tj +-205 TJm +(be) 9.40507 Tj +-205 TJm +(an) 9.40507 Tj +15 TJm +(y) 4.9815 Tj +-205 TJm +(size;) 18.2622 Tj +-220 TJm +(arbitrary) 34.3026 Tj +-205 TJm +(quantities) 38.7461 Tj +-205 TJm +(of) 8.29918 Tj +72 496.104 Td +(data) 16.5984 Tj +-258 TJm +(are) 12.1648 Tj +-258 TJm +(handl) 22.1378 Tj +1 TJm +(ed) 9.40507 Tj +-258 TJm +(by) 9.963 Tj +-258 TJm +(making) 29.889 Tj +-258 TJm +(repeated) 33.7447 Tj +-258 TJm +(cal) 11.6169 Tj +1 TJm +(ls) 6.64532 Tj +-258 TJm +(to) 7.75121 Tj +-258 TJm +(these) 20.474 Tj +-258 TJm +(functions.) 39.573 Tj +-667 TJm +(This) 17.7142 Tj +-258 TJm +(is) 6.64532 Tj +-257 TJm +(a) 4.42357 Tj +-258 TJm +(\003e) 9.963 Tj +15 TJm +(xible) 19.926 Tj +-258 TJm +(mechanism) 45.3815 Tj +-258 TJm +(allo) 14.9445 Tj +25 TJm +(wing) 19.926 Tj +-257 TJm +(a) 4.42357 Tj +-258 TJm +(consumer) 38.7361 Tj +20 TJm +(-pull) 18.8201 Tj +72 484.148 Td +(style) 18.8201 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(acti) 14.3866 Tj +25 TJm +(vity) 15.5024 Tj +65 TJm +(,) 2.49075 Tj +-250 TJm +(or) 8.29918 Tj +-250 TJm +(producer) 35.4085 Tj +20 TJm +(-p) 8.29918 Tj +1 TJm +(ush,) 16.3294 Tj +-250 TJm +(or) 8.29918 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(mixture) 30.9949 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(both.) 20.205 Tj +[1 0 0 1 72 481.992] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -472.029] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 453.527 Td +/F121_0 17.215 Tf +(3.1.2.) 43.0719 Tj +-278 TJm +(High-le) 58.3416 Tj +15 TJm +(vel) 23.9289 Tj +-278 TJm +(summar) 66.9664 Tj +-10 TJm +(y) 9.57154 Tj +[1 0 0 1 72 449.697] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -439.734] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 431.609 Td +/F128_0 9.963 Tf +(This) 17.7142 Tj +-284 TJm +(interf) 21.5799 Tj +10 TJm +(ace) 13.2707 Tj +-284 TJm +(pro) 13.2807 Tj +15 TJm +(vides) 21.0319 Tj +-284 TJm +(some) 21.0319 Tj +-284 TJm +(handy) 24.3496 Tj +-284 TJm +(wrappers) 36.5144 Tj +-284 TJm +(around) 27.6673 Tj +-284 TJm +(the) 12.1748 Tj +-285 TJm +(lo) 7.75121 Tj +25 TJm +(w-l) 13.2807 Tj +1 TJm +(e) 4.42357 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(el) 7.19329 Tj +-285 TJm +(interf) 21.5799 Tj +10 TJm +(a) 4.42357 Tj +1 TJm +(ce) 8.84714 Tj +-285 TJm +(to) 7.75121 Tj +-284 TJm +(f) 3.31768 Tj +10 TJm +(acilitate) 31.5429 Tj +-284 TJm +(reading) 29.879 Tj +-284 TJm +(and) 14.3866 Tj +-284 TJm +(writing) 28.7831 Tj +[1 0 0 1 510.112 431.609] cm +0 g +0 G +[1 0 0 1 -510.112 -431.609] cm +[1 0 0 1 0 0] Tm +0 0 Td +510.112 431.609 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 540 431.609] cm +0 g +0 G +[1 0 0 1 -540 -431.609] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 419.654 Td +/F128_0 9.963 Tf +(format) 26.5614 Tj +-346 TJm +(\002les) 16.6083 Tj +-347 TJm +(\() 3.31768 Tj +[1 0 0 1 125.391 419.654] cm +0 g +0 G +[1 0 0 1 -125.391 -419.654] cm +[1 0 0 1 0 0] Tm +0 0 Td +125.391 419.654 Td +/F130_0 9.963 Tf +(.bz2) 23.9112 Tj +[1 0 0 1 149.301 419.654] cm +0 g +0 G +[1 0 0 1 -149.301 -419.654] cm +[1 0 0 1 0 0] Tm +0 0 Td +152.754 419.654 Td +/F128_0 9.963 Tf +(\002les\).) 22.4168 Tj +-1199 TJm +(The) 15.4925 Tj +-347 TJm +(routines) 32.1008 Tj +-346 TJm +(pro) 13.2807 Tj +15 TJm +(vide) 17.1563 Tj +-347 TJm +(hooks) 23.8016 Tj +-346 TJm +(to) 7.75121 Tj +-347 TJm +(f) 3.31768 Tj +10 TJm +(acilitate) 31.5429 Tj +-346 TJm +(reading) 29.879 Tj +-347 TJm +(\002les) 16.6083 Tj +-346 TJm +(in) 7.75121 Tj +-347 TJm +(which) 24.3496 Tj +-346 TJm +(the) 12.1748 Tj +[1 0 0 1 460.049 419.654] cm +0 g +0 G +[1 0 0 1 -460.049 -419.654] cm +[1 0 0 1 0 0] Tm +0 0 Td +460.049 419.654 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 489.937 419.654] cm +0 g +0 G +[1 0 0 1 -489.937 -419.654] cm +[1 0 0 1 0 0] Tm +0 0 Td +493.39 419.654 Td +/F128_0 9.963 Tf +(data) 16.5984 Tj +-346 TJm +(stream) 26.5614 Tj +72 407.699 Td +(is) 6.64532 Tj +-339 TJm +(embedded) 40.9479 Tj +-339 TJm +(within) 25.4654 Tj +-339 TJm +(some) 21.0319 Tj +-339 TJm +(lar) 10.511 Tj +18 TJm +(ger) 12.7228 Tj +20 TJm +(-scale) 23.2337 Tj +-339 TJm +(\002le) 12.7327 Tj +-339 TJm +(st) 6.64532 Tj +1 TJm +(ructure,) 30.706 Tj +-362 TJm +(or) 8.29918 Tj +-339 TJm +(where) 24.3396 Tj +-339 TJm +(there) 19.916 Tj +-339 TJm +(are) 12.1648 Tj +-339 TJm +(m) 7.75121 Tj +1 TJm +(ultiple) 25.4654 Tj +[1 0 0 1 400.941 407.699] cm +0 g +0 G +[1 0 0 1 -400.941 -407.699] cm +[1 0 0 1 0 0] Tm +0 0 Td +400.941 407.699 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 430.829 407.699] cm +0 g +0 G +[1 0 0 1 -430.829 -407.699] cm +[1 0 0 1 0 0] Tm +0 0 Td +434.207 407.699 Td +/F128_0 9.963 Tf +(data) 16.5984 Tj +-339 TJm +(streams) 30.437 Tj +-339 TJm +(concatenated) 52.0069 Tj +72 395.744 Td +(end-to-end.) 45.6505 Tj +[1 0 0 1 72 395.644] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -385.682] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 373.826 Td +/F128_0 9.963 Tf +(F) 5.53943 Tj +15 TJm +(or) 8.29918 Tj +-332 TJm +(reading) 29.879 Tj +-333 TJm +(\002) 5.53943 Tj +1 TJm +(les,) 13.5596 Tj +[1 0 0 1 144.803 373.826] cm +0 g +0 G +[1 0 0 1 -144.803 -373.826] cm +[1 0 0 1 0 0] Tm +0 0 Td +144.803 373.826 Td +/F130_0 9.963 Tf +(BZ2_bzReadOpen) 83.6892 Tj +[1 0 0 1 228.489 373.826] cm +0 g +0 G +[1 0 0 1 -228.489 -373.826] cm +[1 0 0 1 0 0] Tm +0 0 Td +228.489 373.826 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 234.496 373.826] cm +0 g +0 G +[1 0 0 1 -234.496 -373.826] cm +[1 0 0 1 0 0] Tm +0 0 Td +234.496 373.826 Td +/F130_0 9.963 Tf +(BZ2_bzRead) 59.778 Tj +[1 0 0 1 294.272 373.826] cm +0 g +0 G +[1 0 0 1 -294.272 -373.826] cm +[1 0 0 1 0 0] Tm +0 0 Td +294.272 373.826 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 300.279 373.826] cm +0 g +0 G +[1 0 0 1 -300.279 -373.826] cm +[1 0 0 1 0 0] Tm +0 0 Td +300.279 373.826 Td +/F130_0 9.963 Tf +(BZ2_bzReadClose) 89.667 Tj +[1 0 0 1 389.942 373.826] cm +0 g +0 G +[1 0 0 1 -389.942 -373.826] cm +[1 0 0 1 0 0] Tm +0 0 Td +393.253 373.826 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 410.951 373.826] cm +0 g +0 G +[1 0 0 1 -410.951 -373.826] cm +[1 0 0 1 0 0] Tm +0 0 Td +410.951 373.826 Td +/F130_0 9.963 Tf +(BZ2_bzReadGetUnused) 113.578 Tj +[1 0 0 1 524.525 373.826] cm +0 g +0 G +[1 0 0 1 -524.525 -373.826] cm +[1 0 0 1 0 0] Tm +0 0 Td +527.836 373.826 Td +/F128_0 9.963 Tf +(are) 12.1648 Tj +72 361.871 Td +(supplied.) 36.2554 Tj +-620 TJm +(F) 5.53943 Tj +15 TJm +(or) 8.29918 Tj +-250 TJm +(writing) 28.7831 Tj +-250 TJm +(\002les,) 19.0991 Tj +[1 0 0 1 183.471 361.871] cm +0 g +0 G +[1 0 0 1 -183.471 -361.871] cm +[1 0 0 1 0 0] Tm +0 0 Td +183.471 361.871 Td +/F130_0 9.963 Tf +(BZ2_bzWriteOpen) 89.667 Tj +[1 0 0 1 273.135 361.871] cm +0 g +0 G +[1 0 0 1 -273.135 -361.871] cm +[1 0 0 1 0 0] Tm +0 0 Td +273.135 361.871 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 278.116 361.871] cm +0 g +0 G +[1 0 0 1 -278.116 -361.871] cm +[1 0 0 1 0 0] Tm +0 0 Td +278.116 361.871 Td +/F130_0 9.963 Tf +(BZ2_bzWrite) 65.7558 Tj +[1 0 0 1 343.869 361.871] cm +0 g +0 G +[1 0 0 1 -343.869 -361.871] cm +[1 0 0 1 0 0] Tm +0 0 Td +346.36 361.871 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 363.237 361.871] cm +0 g +0 G +[1 0 0 1 -363.237 -361.871] cm +[1 0 0 1 0 0] Tm +0 0 Td +363.237 361.871 Td +/F130_0 9.963 Tf +(BZ2_bzWriteFinish) 101.623 Tj +[1 0 0 1 464.856 361.871] cm +0 g +0 G +[1 0 0 1 -464.856 -361.871] cm +[1 0 0 1 0 0] Tm +0 0 Td +467.346 361.871 Td +/F128_0 9.963 Tf +(are) 12.1648 Tj +-250 TJm +(a) 4.42357 Tj +20 TJm +(v) 4.9815 Tj +25 TJm +(ailable.) 29.0521 Tj +[1 0 0 1 72 359.714] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -349.752] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 339.953 Td +/F128_0 9.963 Tf +(As) 11.0689 Tj +-374 TJm +(with) 17.7142 Tj +-374 TJm +(the) 12.1748 Tj +-374 TJm +(lo) 7.75121 Tj +25 TJm +(w-le) 17.7043 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(el) 7.19329 Tj +-374 TJm +(library) 26.5614 Tj +65 TJm +(,) 2.49075 Tj +-406 TJm +(n) 4.9815 Tj +1 TJm +(o) 4.9815 Tj +-375 TJm +(global) 24.9075 Tj +-374 TJm +(v) 4.9815 Tj +25 TJm +(ariables) 30.9849 Tj +-374 TJm +(are) 12.1648 Tj +-374 TJm +(used) 18.2622 Tj +-374 TJm +(so) 8.85711 Tj +-374 TJm +(the) 12.1748 Tj +-374 TJm +(library) 26.5614 Tj +-374 TJm +(is) 6.64532 Tj +-374 TJm +(per) 12.7228 Tj +-375 TJm +(se) 8.29918 Tj +-374 TJm +(thread-safe.) 46.7464 Tj +-1365 TJm +(Ho) 12.1748 Tj +25 TJm +(we) 11.6169 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(er) 7.74125 Tj +40 TJm +(,) 2.49075 Tj +-405 TJm +(if) 6.08739 Tj +-374 TJm +(I/O) 13.2807 Tj +72 327.998 Td +(errors) 23.2337 Tj +-267 TJm +(occur) 22.1278 Tj +-267 TJm +(whilst) 24.3595 Tj +-267 TJm +(reading) 29.879 Tj +-267 TJm +(or) 8.29918 Tj +-267 TJm +(writing) 28.7831 Tj +-267 TJm +(the) 12.1748 Tj +-267 TJm +(underlying) 43.1697 Tj +-267 TJm +(compressed) 47.0353 Tj +-267 TJm +(\002les,) 19.0991 Tj +-271 TJm +(you) 14.9445 Tj +-267 TJm +(may) 17.1563 Tj +-267 TJm +(ha) 9.40507 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-267 TJm +(to) 7.75121 Tj +-267 TJm +(consult) 28.7831 Tj +[1 0 0 1 457.199 327.998] cm +0 g +0 G +[1 0 0 1 -457.199 -327.998] cm +[1 0 0 1 0 0] Tm +0 0 Td +457.199 327.998 Td +/F130_0 9.963 Tf +(errno) 29.889 Tj +[1 0 0 1 487.087 327.998] cm +0 g +0 G +[1 0 0 1 -487.087 -327.998] cm +[1 0 0 1 0 0] Tm +0 0 Td +489.748 327.998 Td +/F128_0 9.963 Tf +(to) 7.75121 Tj +-267 TJm +(determine) 39.842 Tj +72 316.043 Td +(the) 12.1748 Tj +-366 TJm +(cau) 13.8286 Tj +1 TJm +(se) 8.29918 Tj +-366 TJm +(of) 8.29918 Tj +-366 TJm +(the) 12.1748 Tj +-365 TJm +(error) 19.3581 Tj +55 TJm +(.) 2.49075 Tj +-1314 TJm +(In) 8.29918 Tj +-365 TJm +(that) 14.9445 Tj +-366 TJm +(case,) 19.6371 Tj +-394 TJm +(you') 18.2622 Tj +50 TJm +(d) 4.9815 Tj +-366 TJm +(need) 18.8101 Tj +-365 TJm +(a) 4.42357 Tj +-366 TJm +(C) 6.64532 Tj +-366 TJm +(lib) 10.5209 Tj +1 TJm +(rary) 16.0404 Tj +-366 TJm +(which) 24.3496 Tj +-366 TJm +(corr) 16.0404 Tj +1 TJm +(ectly) 19.3681 Tj +-366 TJm +(supports) 33.7646 Tj +[1 0 0 1 431.668 316.043] cm +0 g +0 G +[1 0 0 1 -431.668 -316.043] cm +[1 0 0 1 0 0] Tm +0 0 Td +431.668 316.043 Td +/F130_0 9.963 Tf +(errno) 29.889 Tj +[1 0 0 1 461.556 316.043] cm +0 g +0 G +[1 0 0 1 -461.556 -316.043] cm +[1 0 0 1 0 0] Tm +0 0 Td +465.199 316.043 Td +/F128_0 9.963 Tf +(in) 7.75121 Tj +-366 TJm +(a) 4.42357 Tj +-365 TJm +(multithreaded) 55.3445 Tj +72 304.088 Td +(en) 9.40507 Tj +40 TJm +(vironment.) 43.4486 Tj +[1 0 0 1 72 303.988] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -294.025] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 282.17 Td +/F128_0 9.963 Tf +(T) 6.08739 Tj +80 TJm +(o) 4.9815 Tj +-243 TJm +(mak) 17.1563 Tj +10 TJm +(e) 4.42357 Tj +-242 TJm +(the) 12.1748 Tj +-243 TJm +(library) 26.5614 Tj +-243 TJm +(a) 4.42357 Tj +-242 TJm +(little) 18.2721 Tj +-243 TJm +(simpler) 29.889 Tj +-243 TJm +(and) 14.3866 Tj +-242 TJm +(more) 20.474 Tj +-243 TJm +(portable,) 35.1395 Tj +[1 0 0 1 289.263 282.17] cm +0 g +0 G +[1 0 0 1 -289.263 -282.17] cm +[1 0 0 1 0 0] Tm +0 0 Td +289.263 282.17 Td +/F130_0 9.963 Tf +(BZ2_bzReadOpen) 83.6892 Tj +[1 0 0 1 372.949 282.17] cm +0 g +0 G +[1 0 0 1 -372.949 -282.17] cm +[1 0 0 1 0 0] Tm +0 0 Td +375.368 282.17 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 392.172 282.17] cm +0 g +0 G +[1 0 0 1 -392.172 -282.17] cm +[1 0 0 1 0 0] Tm +0 0 Td +392.172 282.17 Td +/F130_0 9.963 Tf +(BZ2_bzWriteOpen) 89.667 Tj +[1 0 0 1 481.836 282.17] cm +0 g +0 G +[1 0 0 1 -481.836 -282.17] cm +[1 0 0 1 0 0] Tm +0 0 Td +484.254 282.17 Td +/F128_0 9.963 Tf +(require) 28.2152 Tj +-243 TJm +(you) 14.9445 Tj +-242 TJm +(to) 7.75121 Tj +72 270.215 Td +(pass) 17.1563 Tj +-247 TJm +(them) 19.926 Tj +-247 TJm +(\002le) 12.7327 Tj +-248 TJm +(handles) 30.437 Tj +-247 TJm +(\() 3.31768 Tj +[1 0 0 1 165.421 270.215] cm +0 g +0 G +[1 0 0 1 -165.421 -270.215] cm +[1 0 0 1 0 0] Tm +0 0 Td +165.421 270.215 Td +/F130_0 9.963 Tf +(FILE*) 29.889 Tj +[1 0 0 1 195.309 270.215] cm +0 g +0 G +[1 0 0 1 -195.309 -270.215] cm +[1 0 0 1 0 0] Tm +0 0 Td +195.309 270.215 Td +/F128_0 9.963 Tf +(s\)) 7.19329 Tj +-247 TJm +(which) 24.3496 Tj +-247 TJm +(ha) 9.40507 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-248 TJm +(pre) 12.7228 Tj +25 TJm +(viously) 29.341 Tj +-247 TJm +(been) 18.8101 Tj +-247 TJm +(opened) 28.7731 Tj +-247 TJm +(for) 11.6169 Tj +-247 TJm +(reading) 29.879 Tj +-248 TJm +(or) 8.29918 Tj +-247 TJm +(writing) 28.7831 Tj +-247 TJm +(respecti) 30.9849 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(ely) 12.1748 Tj +65 TJm +(.) 2.49075 Tj +-618 TJm +(That) 18.2622 Tj +-247 TJm +(a) 4.42357 Tj +20 TJm +(v) 4.9815 Tj +20 TJm +(oids) 16.6083 Tj +72 258.26 Td +(portability) 41.5158 Tj +-272 TJm +(problems) 37.0823 Tj +-272 TJm +(associated) 40.9479 Tj +-273 TJm +(wi) 9.963 Tj +1 TJm +(th) 7.75121 Tj +-273 TJm +(\002le) 12.7327 Tj +-272 TJm +(operations) 41.5059 Tj +-272 TJm +(and) 14.3866 Tj +-273 TJm +(\002le) 12.7327 Tj +-272 TJm +(attrib) 21.0319 Tj +20 TJm +(utes,) 18.5411 Tj +-278 TJm +(whilst) 24.3595 Tj +-272 TJm +(not) 12.7327 Tj +-272 TJm +(being) 22.1378 Tj +-273 TJm +(mu) 12.7327 Tj +1 TJm +(ch) 9.40507 Tj +-273 TJm +(of) 8.29918 Tj +-272 TJm +(an) 9.40507 Tj +-272 TJm +(imposition) 42.6317 Tj +-273 TJm +(on) 9.963 Tj +-272 TJm +(the) 12.1748 Tj +72 246.304 Td +(programmer) 49.2471 Tj +55 TJm +(.) 2.49075 Tj +[1 0 0 1 72 244.148] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -234.185] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 215.683 Td +/F121_0 17.215 Tf +(3.1.3.) 43.0719 Tj +-278 TJm +(Utility) 47.8233 Tj +-278 TJm +(functions) 77.4675 Tj +-278 TJm +(summar) 66.9664 Tj +-10 TJm +(y) 9.57154 Tj +[1 0 0 1 72 212.12] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -202.157] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 193.765 Td +/F128_0 9.963 Tf +(F) 5.53943 Tj +15 TJm +(or) 8.29918 Tj +-273 TJm +(v) 4.9815 Tj +15 TJm +(ery) 12.7228 Tj +-273 TJm +(simple) 26.5713 Tj +-273 TJm +(needs,) 25.1765 Tj +[1 0 0 1 165.929 193.765] cm +0 g +0 G +[1 0 0 1 -165.929 -193.765] cm +[1 0 0 1 0 0] Tm +0 0 Td +165.929 193.765 Td +/F130_0 9.963 Tf +(BZ2_bzBuffToBuffCompress) 143.467 Tj +[1 0 0 1 309.391 193.765] cm +0 g +0 G +[1 0 0 1 -309.391 -193.765] cm +[1 0 0 1 0 0] Tm +0 0 Td +312.112 193.765 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 329.219 193.765] cm +0 g +0 G +[1 0 0 1 -329.219 -193.765] cm +[1 0 0 1 0 0] Tm +0 0 Td +329.219 193.765 Td +/F130_0 9.963 Tf +(BZ2_bzBuffToBuffDecompre) 143.467 Tj +1 TJm +(ss) 11.9556 Tj +[1 0 0 1 484.636 193.765] cm +0 g +0 G +[1 0 0 1 -484.636 -193.765] cm +[1 0 0 1 0 0] Tm +0 0 Td +487.357 193.765 Td +/F128_0 9.963 Tf +(are) 12.1648 Tj +-273 TJm +(pro) 13.2807 Tj +15 TJm +(vided.) 24.6285 Tj +72 181.81 Td +(These) 23.7916 Tj +-373 TJm +(compress) 37.6303 Tj +-374 TJm +(data) 16.5984 Tj +-373 TJm +(in) 7.75121 Tj +-374 TJm +(memory) 33.2067 Tj +-373 TJm +(from) 19.3681 Tj +-374 TJm +(one) 14.3866 Tj +-373 TJm +(b) 4.9815 Tj +20 TJm +(uf) 8.29918 Tj +25 TJm +(fer) 11.0589 Tj +-374 TJm +(to) 7.75121 Tj +-373 TJm +(another) 29.879 Tj +-374 TJm +(b) 4.9815 Tj +20 TJm +(uf) 8.29918 Tj +25 TJm +(fe) 7.74125 Tj +1 TJm +(r) 3.31768 Tj +-374 TJm +(in) 7.75121 Tj +-374 TJm +(a) 4.42357 Tj +-373 TJm +(single) 23.8016 Tj +-373 TJm +(function) 33.2067 Tj +-374 TJm +(call.) 16.8773 Tj +-1361 TJm +(Y) 7.19329 Tj +110 TJm +(ou) 9.963 Tj +-374 TJm +(should) 26.5713 Tj +-373 TJm +(assess) 24.3496 Tj +72 169.855 Td +(whether) 32.0908 Tj +-344 TJm +(t) 2.76971 Tj +1 TJm +(hese) 17.7043 Tj +-344 TJm +(functions) 37.0823 Tj +-344 TJm +(ful\002) 16.6083 Tj +1 TJm +(ll) 5.53943 Tj +-344 TJm +(your) 18.2622 Tj +-344 TJm +(memory-to) 44.2756 Tj +1 TJm +(-memory) 36.5244 Tj +-344 TJm +(compression/decompressio) 107.919 Tj +1 TJm +(n) 4.9815 Tj +-344 TJm +(requirements) 52.0168 Tj +-344 TJm +(be) 9.40507 Tj +1 TJm +(fore) 16.0404 Tj +-344 TJm +(in) 7.75121 Tj +40 TJm +(v) 4.9815 Tj +15 TJm +(esting) 23.8016 Tj +72 157.9 Td +(ef) 7.74125 Tj +25 TJm +(fort) 14.3866 Tj +-250 TJm +(in) 7.75121 Tj +-250 TJm +(understanding) 56.4504 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(m) 7.75121 Tj +1 TJm +(ore) 12.7228 Tj +-250 TJm +(general) 29.3211 Tj +-250 TJm +(b) 4.9815 Tj +20 TJm +(ut) 7.75121 Tj +-250 TJm +(more) 20.474 Tj +-250 TJm +(comple) 29.3311 Tj +15 TJm +(x) 4.9815 Tj +-250 TJm +(lo) 7.75121 Tj +25 TJm +(w-le) 17.7043 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(el) 7.19329 Tj +-250 TJm +(interf) 21.5799 Tj +10 TJm +(ace.) 15.7615 Tj +[1 0 0 1 72 155.743] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -145.78] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 135.982 Td +/F128_0 9.963 Tf +(Y) 7.19329 Tj +110 TJm +(oshioka) 30.9949 Tj +-531 TJm +(Tsuneo) 29.3311 Tj +-531 TJm +(\() 3.31768 Tj +[1 0 0 1 152.317 135.982] cm +0 g +0 G +[1 0 0 1 -152.317 -135.982] cm +[1 0 0 1 0 0] Tm +0 0 Td +152.317 135.982 Td +/F130_0 9.963 Tf +(QWF00133@niftyserve.or.jp) 149.445 Tj +[1 0 0 1 301.757 135.982] cm +0 g +0 G +[1 0 0 1 -301.757 -135.982] cm +[1 0 0 1 0 0] Tm +0 0 Td +307.046 135.982 Td +/F128_0 9.963 Tf +(/) 2.76971 Tj +[1 0 0 1 315.105 135.982] cm +0 g +0 G +[1 0 0 1 -315.105 -135.982] cm +[1 0 0 1 0 0] Tm +0 0 Td +315.105 135.982 Td +/F130_0 9.963 Tf +(tsuneo-y@is.aist-nara.ac.j) 155.423 Tj +1 TJm +(p) 5.9778 Tj +[1 0 0 1 476.5 135.982] cm +0 g +0 G +[1 0 0 1 -476.5 -135.982] cm +[1 0 0 1 0 0] Tm +0 0 Td +476.5 135.982 Td +/F128_0 9.963 Tf +(\)) 3.31768 Tj +-531 TJm +(has) 13.2807 Tj +-531 TJm +(contrib) 28.2252 Tj +20 TJm +(u-) 8.29918 Tj +72 124.027 Td +(ted) 12.1748 Tj +-486 TJm +(s) 3.87561 Tj +1 TJm +(ome) 17.1563 Tj +-486 TJm +(functions) 37.0823 Tj +-485 TJm +(to) 7.75121 Tj +-486 TJm +(gi) 7.75121 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-485 TJm +(better) 22.6858 Tj +[1 0 0 1 218.504 124.027] cm +0 g +0 G +[1 0 0 1 -218.504 -124.027] cm +[1 0 0 1 0 0] Tm +0 0 Td +218.504 124.027 Td +/F130_0 9.963 Tf +(zlib) 23.9112 Tj +[1 0 0 1 242.415 124.027] cm +0 g +0 G +[1 0 0 1 -242.415 -124.027] cm +[1 0 0 1 0 0] Tm +0 0 Td +247.252 124.027 Td +/F128_0 9.963 Tf +(compatibility) 53.1426 Tj +65 TJm +(.) 2.49075 Tj +-2033 TJm +(These) 23.7916 Tj +-486 TJm +(functions) 37.0823 Tj +-485 TJm +(are) 12.1648 Tj +[1 0 0 1 410.043 124.027] cm +0 g +0 G +[1 0 0 1 -410.043 -124.027] cm +[1 0 0 1 0 0] Tm +0 0 Td +410.043 124.027 Td +/F130_0 9.963 Tf +(BZ2_bzopen) 59.778 Tj +[1 0 0 1 469.818 124.027] cm +0 g +0 G +[1 0 0 1 -469.818 -124.027] cm +[1 0 0 1 0 0] Tm +0 0 Td +469.818 124.027 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 477.734 124.027] cm +0 g +0 G +[1 0 0 1 -477.734 -124.027] cm +[1 0 0 1 0 0] Tm +0 0 Td +477.734 124.027 Td +/F130_0 9.963 Tf +(BZ2_bzread) 59.778 Tj +[1 0 0 1 537.509 124.027] cm +0 g +0 G +[1 0 0 1 -537.509 -124.027] cm +[1 0 0 1 0 0] Tm +0 0 Td +537.509 124.027 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 72 112.072] cm +0 g +0 G +[1 0 0 1 -72 -112.072] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 112.072 Td +/F130_0 9.963 Tf +(BZ2_bzwrite) 65.7558 Tj +[1 0 0 1 137.753 112.072] cm +0 g +0 G +[1 0 0 1 -137.753 -112.072] cm +[1 0 0 1 0 0] Tm +0 0 Td +137.753 112.072 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 143.886 112.072] cm +0 g +0 G +[1 0 0 1 -143.886 -112.072] cm +[1 0 0 1 0 0] Tm +0 0 Td +143.886 112.072 Td +/F130_0 9.963 Tf +(BZ2_bzflush) 65.7558 Tj +[1 0 0 1 209.64 112.072] cm +0 g +0 G +[1 0 0 1 -209.64 -112.072] cm +[1 0 0 1 0 0] Tm +0 0 Td +209.64 112.072 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 215.773 112.072] cm +0 g +0 G +[1 0 0 1 -215.773 -112.072] cm +[1 0 0 1 0 0] Tm +0 0 Td +215.773 112.072 Td +/F130_0 9.963 Tf +(BZ2_bzclose) 65.7558 Tj +[1 0 0 1 281.526 112.072] cm +0 g +0 G +[1 0 0 1 -281.526 -112.072] cm +[1 0 0 1 0 0] Tm +0 0 Td +281.526 112.072 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 287.659 112.072] cm +0 g +0 G +[1 0 0 1 -287.659 -112.072] cm +[1 0 0 1 0 0] Tm +0 0 Td +287.659 112.072 Td +/F130_0 9.963 Tf +(BZ2_bzerror) 65.7558 Tj +[1 0 0 1 353.413 112.072] cm +0 g +0 G +[1 0 0 1 -353.413 -112.072] cm +[1 0 0 1 0 0] Tm +0 0 Td +356.824 112.072 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 374.622 112.072] cm +0 g +0 G +[1 0 0 1 -374.622 -112.072] cm +[1 0 0 1 0 0] Tm +0 0 Td +374.622 112.072 Td +/F130_0 9.963 Tf +(BZ2_bzlibVersion) 95.6448 Tj +[1 0 0 1 470.264 112.072] cm +0 g +0 G +[1 0 0 1 -470.264 -112.072] cm +[1 0 0 1 0 0] Tm +0 0 Td +470.264 112.072 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +-1175 TJm +(Y) 7.19329 Tj +110 TJm +(ou) 9.963 Tj +-342 TJm +(may) 17.1563 Tj +-343 TJm +(\002nd) 15.5024 Tj +72 100.117 Td +(these) 20.474 Tj +-333 TJm +(functions) 37.0823 Tj +-334 TJm +(more) 20.474 Tj +-333 TJm +(con) 14.3866 Tj +40 TJm +(v) 4.9815 Tj +15 TJm +(enient) 24.3496 Tj +-333 TJm +(for) 11.6169 Tj +-334 TJm +(simple) 26.5713 Tj +-333 TJm +(\002le) 12.7327 Tj +-334 TJm +(r) 3.31768 Tj +1 TJm +(eading) 26.5614 Tj +-334 TJm +(and) 14.3866 Tj +-333 TJm +(writing,) 31.2739 Tj +-354 TJm +(than) 17.1563 Tj +-334 TJm +(those) 21.0319 Tj +-333 TJm +(in) 7.75121 Tj +-334 TJm +(the) 12.1748 Tj +-333 TJm +(high-le) 28.2252 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(el) 7.19329 Tj +-333 TJm +(interf) 21.5799 Tj +10 TJm +(ace.) 15.7615 Tj +-1121 TJm +(These) 23.7916 Tj +72 88.161 Td +(functions) 37.0823 Tj +-229 TJm +(are) 12.1648 Tj +-228 TJm +(not) 12.7327 Tj +-229 TJm +(\(yet\)) 18.8101 Tj +-229 TJm +(of) 8.29918 Tj +25 TJm +(\002cially) 27.6772 Tj +-229 TJm +(pa) 9.40507 Tj +1 TJm +(rt) 6.08739 Tj +-229 TJm +(of) 8.29918 Tj +-229 TJm +(the) 12.1748 Tj +-229 TJm +(library) 26.5614 Tj +65 TJm +(,) 2.49075 Tj +-233 TJm +(and) 14.3866 Tj +-228 TJm +(are) 12.1648 Tj +-229 TJm +(minimally) 40.9679 Tj +-229 TJm +(documented) 48.6991 Tj +-228 TJm +(here.) 19.6371 Tj +-606 TJm +(If) 6.63536 Tj +-229 TJm +(the) 12.1748 Tj +15 TJm +(y) 4.9815 Tj +-229 TJm +(break,) 24.6186 Tj +-233 TJm +(you) 14.9445 Tj +-228 TJm +(get) 12.1748 Tj +-229 TJm +(to) 7.75121 Tj +-229 TJm +(k) 4.9815 Tj +10 TJm +(eep) 13.8286 Tj +72 76.206 Td +(all) 9.963 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(pieces.) 27.3883 Tj +-310 TJm +(I) 3.31768 Tj +-250 TJm +(hope) 19.3681 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(docum) 27.1193 Tj +1 TJm +(ent) 12.1748 Tj +-250 TJm +(them) 19.926 Tj +-250 TJm +(properly) 33.7546 Tj +-250 TJm +(when) 21.5799 Tj +-250 TJm +(time) 17.7142 Tj +-250 TJm +(permits.) 32.3798 Tj +[1 0 0 1 72 74.049] cm +0 g +0 G +[1 0 0 1 0 -23.197] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 4.384 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 0 6.974] cm +0 g +0 G +0 g +0 G +[1 0 0 1 43.064 -6.755] cm +0 g +0 G +[1 0 0 1 -498.225 -51.071] cm +[1 0 0 1 0 0] Tm +0 0 Td +541.288 51.071 Td +/F128_0 9.963 Tf +(9) 4.9815 Tj +[1 0 0 1 455.161 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.599 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -15.037 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 13 13 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 -8.911] cm +0 g +0 G +[1 0 0 1 0 8.911] cm +0 g +0 G +0 g +0 G +[1 0 0 1 84.08 -6.755] cm +0 g +0 G +[1 0 0 1 -350.151 -749.245] cm +[1 0 0 1 0 0] Tm +0 0 Td +434.231 749.245 Td +/F128_0 9.963 Tf +(Programming) 54.7965 Tj +-250 TJm +(with) 17.7142 Tj +-250 TJm +(libbzip2) 32.6587 Tj +[1 0 0 1 266.071 747.089] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -5.037] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -468 -21.554] cm +0 g +0 G +[1 0 0 1 -72 -720] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 710.037 Td +/F128_0 9.963 Tf +(Y) 7.19329 Tj +110 TJm +(oshioka) 30.9949 Tj +-250 TJm +(also) 16.0504 Tj +-250 TJm +(contrib) 28.2252 Tj +20 TJm +(uted) 17.1563 Tj +-250 TJm +(mo) 12.7327 Tj +1 TJm +(di\002cations) 41.5158 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(allo) 14.9445 Tj +25 TJm +(w) 7.19329 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(library) 26.5614 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(be) 9.40507 Tj +-250 TJm +(b) 4.9815 Tj +20 TJm +(uilt) 13.2906 Tj +-250 TJm +(as) 8.29918 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(W) 9.40507 Tj +40 TJm +(indo) 17.7142 Tj +25 TJm +(ws) 11.0689 Tj +-250 TJm +(D) 7.19329 Tj +1 TJm +(LL.) 14.6655 Tj +[1 0 0 1 72 707.881] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.744] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -698.137] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 675.504 Td +/F121_0 20.659 Tf +(3.2.) 34.4592 Tj +-278 TJm +(Err) 29.8523 Tj +20 TJm +(or) 20.659 Tj +-278 TJm +(handling) 86.0861 Tj +[1 0 0 1 72 670.907] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.743] cm +0 g +0 G +[1 0 0 1 -72 -661.164] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 653.805 Td +/F128_0 9.963 Tf +(The) 15.4925 Tj +-214 TJm +(library) 26.5614 Tj +-215 TJm +(is) 6.64532 Tj +-214 TJm +(designed) 35.4185 Tj +-215 TJm +(to) 7.75121 Tj +-214 TJm +(reco) 17.1463 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(er) 7.74125 Tj +-214 TJm +(cleanly) 28.7731 Tj +-215 TJm +(in) 7.75121 Tj +-214 TJm +(all) 9.963 Tj +-215 TJm +(situati) 24.3595 Tj +1 TJm +(ons,) 16.3294 Tj +-222 TJm +(including) 37.6402 Tj +-214 TJm +(the) 12.1748 Tj +-215 TJm +(w) 7.19329 Tj +10 TJm +(orst-case) 35.4085 Tj +-214 TJm +(situation) 34.3225 Tj +-214 TJm +(of) 8.29918 Tj +-215 TJm +(decompressing) 59.768 Tj +-214 TJm +(random) 30.437 Tj +72 641.85 Td +(data.) 19.0891 Tj +-764 TJm +(I'm) 14.3866 Tj +-274 TJm +(not) 12.7327 Tj +-274 TJm +(100%) 23.2437 Tj +-274 TJm +(sure) 16.5984 Tj +-274 TJm +(that) 14.9445 Tj +-274 TJm +(it) 5.53943 Tj +-274 TJm +(can) 13.8286 Tj +-274 TJm +(al) 7.19329 Tj +10 TJm +(w) 7.19329 Tj +10 TJm +(ays) 13.2807 Tj +-274 TJm +(do) 9.963 Tj +-274 TJm +(this,) 16.8873 Tj +-280 TJm +(so) 8.85711 Tj +-274 TJm +(you) 14.9445 Tj +-274 TJm +(might) 23.2536 Tj +-274 TJm +(w) 7.19329 Tj +10 TJm +(ant) 12.1748 Tj +-274 TJm +(to) 7.75121 Tj +-274 TJm +(add) 14.3866 Tj +-274 TJm +(a) 4.42357 Tj +-274 TJm +(signal) 23.8016 Tj +-274 TJm +(handler) 29.879 Tj +-274 TJm +(to) 7.75121 Tj +-274 TJm +(catch) 21.0219 Tj +-274 TJm +(se) 8.29918 Tj +15 TJm +(gmentation) 44.8335 Tj +72 629.895 Td +(violations) 39.304 Tj +-273 TJm +(during) 26.0134 Tj +-273 TJm +(decompression) 59.768 Tj +-273 TJm +(if) 6.08739 Tj +-273 TJm +(you) 14.9445 Tj +-273 TJm +(are) 12.1648 Tj +-273 TJm +(feeling) 27.6673 Tj +-273 TJm +(especially) 39.842 Tj +-273 TJm +(paranoid.) 37.3513 Tj +-758 TJm +(I) 3.31768 Tj +-273 TJm +(w) 7.19329 Tj +10 TJm +(ould) 17.7142 Tj +-273 TJm +(be) 9.40507 Tj +-273 TJm +(interested) 38.7361 Tj +-273 TJm +(in) 7.75121 Tj +-273 TJm +(hearing) 29.879 Tj +-273 TJm +(more) 20.474 Tj +-273 TJm +(about) 22.1378 Tj +72 617.939 Td +(the) 12.1748 Tj +-250 TJm +(rob) 13.2807 Tj +20 TJm +(ustness) 28.7831 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(library) 26.5614 Tj +-250 TJm +(t) 2.76971 Tj +1 TJm +(o) 4.9815 Tj +-250 TJm +(corrupted) 38.1782 Tj +-250 TJm +(compressed) 47.0353 Tj +-250 TJm +(data.) 19.0891 Tj +[1 0 0 1 72 615.783] cm +0 g +0 G +[1 0 0 1 0 -9.744] cm +0 g +0 G +[1 0 0 1 -72 -606.039] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 596.241 Td +/F128_0 9.963 Tf +(V) 7.19329 Tj +111 TJm +(ersion) 24.3496 Tj +-251 TJm +(1.0.3) 19.926 Tj +-251 TJm +(more) 20.474 Tj +-251 TJm +(rob) 13.2807 Tj +20 TJm +(ust) 11.6268 Tj +-251 TJm +(in) 7.75121 Tj +-251 TJm +(this) 14.3965 Tj +-251 TJm +(respect) 28.2152 Tj +-251 TJm +(than) 17.1563 Tj +-251 TJm +(an) 9.40507 Tj +15 TJm +(y) 4.9815 Tj +-251 TJm +(pre) 12.7228 Tj +25 TJm +(vious) 21.5898 Tj +-251 TJm +(v) 4.9815 Tj +15 TJm +(ersion.) 26.8403 Tj +-626 TJm +(In) 8.29918 Tj +40 TJm +(v) 4.9815 Tj +15 TJm +(estig) 18.8201 Tj +5 TJm +(ations) 23.8016 Tj +-251 TJm +(with) 17.7142 Tj +-251 TJm +(V) 7.19329 Tj +111 TJm +(algrind) 28.2252 Tj +-251 TJm +(\(a) 7.74125 Tj +-251 TJm +(tool) 15.5024 Tj +-251 TJm +(for) 11.6169 Tj +-251 TJm +(detecting) 36.5244 Tj +72 584.285 Td +(problems) 37.0823 Tj +-421 TJm +(with) 17.7142 Tj +-422 TJm +(memory) 33.2067 Tj +-421 TJm +(management\)) 54.2286 Tj +-422 TJm +(indicat) 27.1193 Tj +1 TJm +(e) 4.42357 Tj +-422 TJm +(that,) 17.4353 Tj +-464 TJm +(at) 7.19329 Tj +-422 TJm +(least) 18.2622 Tj +-421 TJm +(for) 11.6169 Tj +-422 TJm +(the) 12.1748 Tj +-421 TJm +(fe) 7.74125 Tj +25 TJm +(w) 7.19329 Tj +-422 TJm +(\002les) 16.6083 Tj +-421 TJm +(I) 3.31768 Tj +-422 TJm +(tested,) 25.7344 Tj +-464 TJm +(all) 9.963 Tj +-422 TJm +(single) 23.8016 Tj +1 TJm +(-bit) 13.8386 Tj +-422 TJm +(errors) 23.2337 Tj +-421 TJm +(in) 7.75121 Tj +-422 TJm +(the) 12.1748 Tj +72 572.33 Td +(decompressed) 56.4404 Tj +-342 TJm +(d) 4.9815 Tj +1 TJm +(ata) 11.6169 Tj +-342 TJm +(are) 12.1648 Tj +-342 TJm +(caught) 26.5614 Tj +-342 TJm +(pro) 13.2807 Tj +1 TJm +(perly) 20.474 Tj +65 TJm +(,) 2.49075 Tj +-365 TJm +(with) 17.7142 Tj +-342 TJm +(no) 9.963 Tj +-342 TJm +(s) 3.87561 Tj +1 TJm +(e) 4.42357 Tj +15 TJm +(gmentation) 44.8335 Tj +-342 TJm +(f) 3.31768 Tj +10 TJm +(aults,) 21.3109 Tj +-365 TJm +(no) 9.963 Tj +-341 TJm +(uses) 17.1563 Tj +-342 TJm +(of) 8.29918 Tj +-342 TJm +(uninitialise) 44.2855 Tj +1 TJm +(d) 4.9815 Tj +-342 TJm +(data,) 19.0891 Tj +-365 TJm +(no) 9.963 Tj +-342 TJm +(out) 12.7327 Tj +-341 TJm +(of) 8.29918 Tj +-342 TJm +(range) 22.1278 Tj +72 560.375 Td +(reads) 21.0219 Tj +-260 TJm +(or) 8.29918 Tj +-261 TJm +(writes,) 26.8403 Tj +-263 TJm +(and) 14.3866 Tj +-261 TJm +(no) 9.963 Tj +-260 TJm +(in\002nite) 28.2351 Tj +-261 TJm +(looping) 30.4469 Tj +-260 TJm +(in) 7.75121 Tj +-261 TJm +(the) 12.1748 Tj +-260 TJm +(decompressor) 55.3345 Tj +55 TJm +(.) 2.49075 Tj +-342 TJm +(So) 10.5209 Tj +-260 TJm +(it') 8.85711 Tj +55 TJm +(s) 3.87561 Tj +-261 TJm +(certainly) 34.8605 Tj +-260 TJm +(pretty) 23.2437 Tj +-261 TJm +(rob) 13.2807 Tj +21 TJm +(ust,) 14.1176 Tj +-264 TJm +(although) 34.8705 Tj +-260 TJm +(I) 3.31768 Tj +-261 TJm +(w) 7.19329 Tj +10 TJm +(ouldn') 26.0134 Tj +18 TJm +(t) 2.76971 Tj +-260 TJm +(claim) 22.1378 Tj +72 548.42 Td +(it) 5.53943 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(be) 9.40507 Tj +-250 TJm +(totally) 25.4654 Tj +-250 TJm +(bombproof.) 46.7663 Tj +[1 0 0 1 72 546.263] cm +0 g +0 G +[1 0 0 1 0 -9.743] cm +0 g +0 G +[1 0 0 1 -72 -536.52] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 526.721 Td +/F128_0 9.963 Tf +(The) 15.4925 Tj +-282 TJm +(\002le) 12.7327 Tj +[1 0 0 1 105.84 526.721] cm +0 g +0 G +[1 0 0 1 -105.84 -526.721] cm +[1 0 0 1 0 0] Tm +0 0 Td +105.84 526.721 Td +/F130_0 9.963 Tf +(bzlib.h) 41.8446 Tj +[1 0 0 1 147.683 526.721] cm +0 g +0 G +[1 0 0 1 -147.683 -526.721] cm +[1 0 0 1 0 0] Tm +0 0 Td +150.491 526.721 Td +/F128_0 9.963 Tf +(contains) 33.2067 Tj +-282 TJm +(all) 9.963 Tj +-282 TJm +(d) 4.9815 Tj +1 TJm +(e\002nitions) 37.0922 Tj +-282 TJm +(needed) 28.2152 Tj +-282 TJm +(to) 7.75121 Tj +-282 TJm +(use) 13.2807 Tj +-282 TJm +(t) 2.76971 Tj +1 TJm +(he) 9.40507 Tj +-282 TJm +(library) 26.5614 Tj +65 TJm +(.) 2.49075 Tj +-811 TJm +(In) 8.29918 Tj +-282 TJm +(particular) 38.1782 Tj +40 TJm +(,) 2.49075 Tj +-290 TJm +(you) 14.9445 Tj +-282 TJm +(shou) 18.8201 Tj +1 TJm +(ld) 7.75121 Tj +-282 TJm +(de\002nitely) 37.6402 Tj +-282 TJm +(not) 12.7327 Tj +-282 TJm +(include) 29.3311 Tj +[1 0 0 1 72 514.766] cm +0 g +0 G +[1 0 0 1 -72 -514.766] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 514.766 Td +/F130_0 9.963 Tf +(bzlib_private.h) 89.667 Tj +[1 0 0 1 161.664 514.766] cm +0 g +0 G +[1 0 0 1 -161.664 -514.766] cm +[1 0 0 1 0 0] Tm +0 0 Td +161.664 514.766 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 72 513.202] cm +0 g +0 G +[1 0 0 1 0 -9.744] cm +0 g +0 G +[1 0 0 1 -72 -503.458] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 493.067 Td +/F128_0 9.963 Tf +(In) 8.29918 Tj +[1 0 0 1 82.807 493.067] cm +0 g +0 G +[1 0 0 1 -82.807 -493.067] cm +[1 0 0 1 0 0] Tm +0 0 Td +82.807 493.067 Td +/F130_0 9.963 Tf +(bzlib.h) 41.8446 Tj +[1 0 0 1 124.651 493.067] cm +0 g +0 G +[1 0 0 1 -124.651 -493.067] cm +[1 0 0 1 0 0] Tm +0 0 Td +124.651 493.067 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-252 TJm +(the) 12.1748 Tj +-252 TJm +(v) 4.9815 Tj +25 TJm +(arious) 24.3496 Tj +-252 TJm +(return) 23.7916 Tj +-251 TJm +(v) 4.9815 Tj +25 TJm +(alues) 20.474 Tj +-252 TJm +(are) 12.1648 Tj +-252 TJm +(de\002ned.) 31.8218 Tj +-630 TJm +(The) 15.4925 Tj +-252 TJm +(follo) 18.8201 Tj +25 TJm +(wing) 19.926 Tj +-252 TJm +(list) 12.1847 Tj +-251 TJm +(is) 6.64532 Tj +-252 TJm +(not) 12.7327 Tj +-252 TJm +(intended) 34.3126 Tj +-252 TJm +(as) 8.29918 Tj +-251 TJm +(an) 9.40507 Tj +-252 TJm +(e) 4.42357 Tj +15 TJm +(xhausti) 28.7831 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-252 TJm +(description) 44.2756 Tj +-251 TJm +(of) 8.29918 Tj +72 481.112 Td +(the) 12.1748 Tj +-236 TJm +(circumstances) 56.4404 Tj +-236 TJm +(in) 7.75121 Tj +-236 TJm +(which) 24.3496 Tj +-236 TJm +(a) 4.42357 Tj +-236 TJm +(gi) 7.75121 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(en) 9.40507 Tj +-237 TJm +(v) 4.9815 Tj +25 TJm +(alue) 16.5984 Tj +-236 TJm +(may) 17.1563 Tj +-236 TJm +(be) 9.40507 Tj +-236 TJm +(returned) 33.1967 Tj +-236 TJm +(--) 6.63536 Tj +-236 TJm +(those) 21.0319 Tj +-236 TJm +(descriptions) 48.1512 Tj +-236 TJm +(are) 12.1648 Tj +-236 TJm +(gi) 7.75121 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(en) 9.40507 Tj +-236 TJm +(later) 17.7043 Tj +55 TJm +(.) 2.49075 Tj +-306 TJm +(Rather) 26.5614 Tj +40 TJm +(,) 2.49075 Tj +-239 TJm +(it) 5.53943 Tj +-236 TJm +(is) 6.64532 Tj +-236 TJm +(intended) 34.3126 Tj +-236 TJm +(to) 7.75121 Tj +72 469.157 Td +(con) 14.3866 Tj +40 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +15 TJm +(y) 4.9815 Tj +-266 TJm +(t) 2.76971 Tj +1 TJm +(he) 9.40507 Tj +-266 TJm +(rough) 23.2437 Tj +-266 TJm +(me) 12.1748 Tj +1 TJm +(aning) 22.1378 Tj +-266 TJm +(of) 8.29918 Tj +-266 TJm +(ea) 8.84714 Tj +1 TJm +(ch) 9.40507 Tj +-266 TJm +(return) 23.7916 Tj +-266 TJm +(v) 4.9815 Tj +26 TJm +(alue.) 19.0891 Tj +-714 TJm +(The) 15.4925 Tj +-265 TJm +(\002rst) 15.5024 Tj +-266 TJm +(\002) 5.53943 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-266 TJm +(a) 4.42357 Tj +1 TJm +(ctions) 23.8016 Tj +-266 TJm +(are) 12.1648 Tj +-265 TJm +(normal) 28.2252 Tj +-266 TJm +(and) 14.3866 Tj +-265 TJm +(not) 12.7327 Tj +-266 TJm +(intended) 34.3126 Tj +-265 TJm +(to) 7.75121 Tj +-266 TJm +(denote) 26.5614 Tj +-265 TJm +(an) 9.40507 Tj +-266 TJm +(error) 19.3581 Tj +72 457.202 Td +(situation.) 36.8133 Tj +[1 0 0 1 72 457.102] cm +0 g +0 G +[1 0 0 1 0 -9.743] cm +0 g +0 G +[1 0 0 1 0 -9.744] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -437.615] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 425.759 Td +/F130_0 9.963 Tf +(BZ_OK) 29.889 Tj +[1 0 0 1 101.888 425.759] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -32.379 -1.165] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -424.594] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 413.804 Td +/F128_0 9.963 Tf +(The) 15.4925 Tj +-250 TJm +(requested) 38.1782 Tj +-250 TJm +(action) 24.3496 Tj +-250 TJm +(w) 7.19329 Tj +10 TJm +(as) 8.29918 Tj +-250 TJm +(com) 17.1563 Tj +1 TJm +(pleted) 24.3496 Tj +-250 TJm +(successfully) 48.6991 Tj +65 TJm +(.) 2.49075 Tj +[1 0 0 1 72 411.647] cm +0 g +0 G +0 g +0 G +[1 0 0 1 0 -3.765] cm +0 g +0 G +[1 0 0 1 0 -9.744] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -398.138] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 388.34 Td +/F130_0 9.963 Tf +(BZ_RUN_OK,) 59.778 Tj +-600 TJm +(BZ_FLUSH_OK,) 71.7336 Tj +-600 TJm +(BZ) 11.9556 Tj +1 TJm +(_FINISH_OK) 59.778 Tj +[1 0 0 1 287.193 388.34] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -217.684 -1.166] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -387.174] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 376.384 Td +/F128_0 9.963 Tf +(In) 8.29918 Tj +[1 0 0 1 118.789 376.384] cm +0 g +0 G +[1 0 0 1 -118.789 -376.384] cm +[1 0 0 1 0 0] Tm +0 0 Td +118.789 376.384 Td +/F130_0 9.963 Tf +(BZ2_bzCompress) 83.6892 Tj +[1 0 0 1 202.476 376.384] cm +0 g +0 G +[1 0 0 1 -202.476 -376.384] cm +[1 0 0 1 0 0] Tm +0 0 Td +202.476 376.384 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(requested) 38.1782 Tj +-250 TJm +(\003ush/\002nish/) 47.0652 Tj +1 TJm +(nothing-special) 61.4319 Tj +-250 TJm +(action) 24.3496 Tj +-250 TJm +(w) 7.19329 Tj +10 TJm +(as) 8.29918 Tj +-250 TJm +(completed) 41.5059 Tj +-250 TJm +(successfully) 48.6991 Tj +65 TJm +(.) 2.49075 Tj +[1 0 0 1 72 374.228] cm +0 g +0 G +0 g +0 G +[1 0 0 1 0 -3.766] cm +0 g +0 G +[1 0 0 1 0 -9.744] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -360.718] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 350.92 Td +/F130_0 9.963 Tf +(BZ_STREAM_END) 77.7114 Tj +[1 0 0 1 149.709 350.92] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -80.199 -1.166] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -349.754] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 338.965 Td +/F128_0 9.963 Tf +(Compression) 52.5847 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(data) 16.5984 Tj +-250 TJm +(w) 7.19329 Tj +10 TJm +(as) 8.29918 Tj +-250 TJm +(com) 17.1563 Tj +1 TJm +(pleted,) 26.8403 Tj +-250 TJm +(or) 8.29918 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(logical) 27.1193 Tj +-250 TJm +(stream) 26.5614 Tj +-250 TJm +(end) 14.3866 Tj +-250 TJm +(w) 7.19329 Tj +10 TJm +(as) 8.29918 Tj +-250 TJm +(detected) 33.1967 Tj +-250 TJm +(during) 26.0134 Tj +-250 TJm +(de) 9.40507 Tj +1 TJm +(compression.) 52.8537 Tj +[1 0 0 1 72 336.808] cm +0 g +0 G +0 g +0 G +[1 0 0 1 0 -3.766] cm +0 g +0 G +[1 0 0 1 0 -9.744] cm +0 g +0 G +[1 0 0 1 0 -9.743] cm +0 g +0 G +[1 0 0 1 -72 -313.555] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 303.756 Td +/F128_0 9.963 Tf +(The) 15.4925 Tj +-250 TJm +(follo) 18.8201 Tj +25 TJm +(wing) 19.926 Tj +-250 TJm +(return) 23.7916 Tj +-250 TJm +(v) 4.9815 Tj +25 TJm +(alues) 20.474 Tj +-250 TJm +(i) 2.76971 Tj +1 TJm +(ndicate) 28.7731 Tj +-250 TJm +(an) 9.40507 Tj +-250 TJm +(error) 19.3581 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(some) 21.0319 Tj +-250 TJm +(kind.) 20.205 Tj +[1 0 0 1 72 301.6] cm +0 g +0 G +[1 0 0 1 0 -9.744] cm +0 g +0 G +[1 0 0 1 0 -9.744] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -282.112] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 272.314 Td +/F130_0 9.963 Tf +(BZ_CONFIG_ERROR) 89.667 Tj +[1 0 0 1 161.664 272.314] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -92.154 -1.165] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -271.149] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 260.359 Td +/F128_0 9.963 Tf +(Indicates) 35.9664 Tj +-386 TJm +(that) 14.9445 Tj +-385 TJm +(the) 12.1748 Tj +-386 TJm +(library) 26.5614 Tj +-386 TJm +(has) 13.2807 Tj +-385 TJm +(been) 18.8101 Tj +-386 TJm +(improperly) 44.2756 Tj +-385 TJm +(compiled) 37.0823 Tj +-386 TJm +(on) 9.963 Tj +-386 TJm +(your) 18.2622 Tj +-385 TJm +(platform) 34.3126 Tj +-386 TJm +(--) 6.63536 Tj +-386 TJm +(a) 4.42357 Tj +-385 TJm +(major) 23.2437 Tj +-386 TJm +(con\002guration) 53.1327 Tj +-386 TJm +(error) 19.3581 Tj +55 TJm +(.) 2.49075 Tj +108 248.404 Td +(Speci\002cally) 47.0453 Tj +65 TJm +(,) 2.49075 Tj +-481 TJm +(it) 5.53943 Tj +-435 TJm +(means) 25.4555 Tj +-434 TJm +(that) 14.9445 Tj +[1 0 0 1 220.614 248.404] cm +0 g +0 G +[1 0 0 1 -220.614 -248.404] cm +[1 0 0 1 0 0] Tm +0 0 Td +220.614 248.404 Td +/F130_0 9.963 Tf +(sizeof\(char\)) 71.7336 Tj +[1 0 0 1 292.345 248.404] cm +0 g +0 G +[1 0 0 1 -292.345 -248.404] cm +[1 0 0 1 0 0] Tm +0 0 Td +292.345 248.404 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 299.628 248.404] cm +0 g +0 G +[1 0 0 1 -299.628 -248.404] cm +[1 0 0 1 0 0] Tm +0 0 Td +299.628 248.404 Td +/F130_0 9.963 Tf +(sizeof\(short\)) 77.7114 Tj +[1 0 0 1 377.337 248.404] cm +0 g +0 G +[1 0 0 1 -377.337 -248.404] cm +[1 0 0 1 0 0] Tm +0 0 Td +381.669 248.404 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 400.388 248.404] cm +0 g +0 G +[1 0 0 1 -400.388 -248.404] cm +[1 0 0 1 0 0] Tm +0 0 Td +400.388 248.404 Td +/F130_0 9.963 Tf +(sizeof\(int\)) 65.7558 Tj +[1 0 0 1 466.141 248.404] cm +0 g +0 G +[1 0 0 1 -466.141 -248.404] cm +[1 0 0 1 0 0] Tm +0 0 Td +470.474 248.404 Td +/F128_0 9.963 Tf +(are) 12.1648 Tj +-435 TJm +(not) 12.7327 Tj +-435 TJm +(1,) 7.47225 Tj +-481 TJm +(2) 4.9815 Tj +-434 TJm +(and) 14.3866 Tj +108 236.449 Td +(4) 4.9815 Tj +-389 TJm +(respecti) 30.9849 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(ely) 12.1748 Tj +65 TJm +(,) 2.49075 Tj +-424 TJm +(as) 8.29918 Tj +-389 TJm +(the) 12.1748 Tj +15 TJm +(y) 4.9815 Tj +-389 TJm +(should) 26.5713 Tj +-390 TJm +(be.) 11.8958 Tj +-1455 TJm +(Note) 19.3681 Tj +-389 TJm +(that) 14.9445 Tj +-389 TJm +(the) 12.1748 Tj +-390 TJm +(library) 26.5614 Tj +-389 TJm +(should) 26.5713 Tj +-389 TJm +(still) 14.9545 Tj +-389 TJm +(w) 7.19329 Tj +10 TJm +(ork) 13.2807 Tj +-389 TJm +(properly) 33.7546 Tj +-389 TJm +(on) 9.963 Tj +-390 TJm +(64-bi) 21.0319 Tj +1 TJm +(t) 2.76971 Tj +-390 TJm +(platforms) 38.1882 Tj +108 224.493 Td +(which) 24.3496 Tj +-292 TJm +(follo) 18.8201 Tj +25 TJm +(w) 7.19329 Tj +-292 TJm +(the) 12.1748 Tj +-292 TJm +(LP64) 21.5898 Tj +-292 TJm +(programming) 54.2386 Tj +-292 TJm +(model) 24.9075 Tj +-292 TJm +(--) 6.63536 Tj +-292 TJm +(that) 14.9445 Tj +-292 TJm +(is,) 9.13607 Tj +-303 TJm +(where) 24.3396 Tj +[1 0 0 1 355.279 224.493] cm +0 g +0 G +[1 0 0 1 -355.279 -224.493] cm +[1 0 0 1 0 0] Tm +0 0 Td +355.279 224.493 Td +/F130_0 9.963 Tf +(sizeof\(long\)) 71.7336 Tj +[1 0 0 1 427.01 224.493] cm +0 g +0 G +[1 0 0 1 -427.01 -224.493] cm +[1 0 0 1 0 0] Tm +0 0 Td +429.92 224.493 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 447.217 224.493] cm +0 g +0 G +[1 0 0 1 -447.217 -224.493] cm +[1 0 0 1 0 0] Tm +0 0 Td +447.217 224.493 Td +/F130_0 9.963 Tf +(sizeof\(void*\)) 77.7114 Tj +[1 0 0 1 524.925 224.493] cm +0 g +0 G +[1 0 0 1 -524.925 -224.493] cm +[1 0 0 1 0 0] Tm +0 0 Td +527.836 224.493 Td +/F128_0 9.963 Tf +(are) 12.1648 Tj +108 212.538 Td +(8.) 7.47225 Tj +-620 TJm +(Under) 24.8975 Tj +-250 TJm +(LP64,) 24.0806 Tj +[1 0 0 1 175.606 212.538] cm +0 g +0 G +[1 0 0 1 -175.606 -212.538] cm +[1 0 0 1 0 0] Tm +0 0 Td +175.606 212.538 Td +/F130_0 9.963 Tf +(sizeof\(int\)) 65.7558 Tj +[1 0 0 1 241.36 212.538] cm +0 g +0 G +[1 0 0 1 -241.36 -212.538] cm +[1 0 0 1 0 0] Tm +0 0 Td +243.85 212.538 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-250 TJm +(still) 14.9545 Tj +-250 TJm +(4,) 7.47225 Tj +-250 TJm +(so) 8.85711 Tj +[1 0 0 1 291.74 212.538] cm +0 g +0 G +[1 0 0 1 -291.74 -212.538] cm +[1 0 0 1 0 0] Tm +0 0 Td +291.74 212.538 Td +/F130_0 9.963 Tf +(libbzip2) 47.8224 Tj +[1 0 0 1 339.561 212.538] cm +0 g +0 G +[1 0 0 1 -339.561 -212.538] cm +[1 0 0 1 0 0] Tm +0 0 Td +339.561 212.538 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-250 TJm +(which) 24.3496 Tj +-250 TJm +(doesn') 26.5614 Tj +18 TJm +(t) 2.76971 Tj +-250 TJm +(use) 13.2807 Tj +-250 TJm +(the) 12.1748 Tj +[1 0 0 1 433.458 212.538] cm +0 g +0 G +[1 0 0 1 -433.458 -212.538] cm +[1 0 0 1 0 0] Tm +0 0 Td +433.458 212.538 Td +/F130_0 9.963 Tf +(long) 23.9112 Tj +[1 0 0 1 457.368 212.538] cm +0 g +0 G +[1 0 0 1 -457.368 -212.538] cm +[1 0 0 1 0 0] Tm +0 0 Td +459.859 212.538 Td +/F128_0 9.963 Tf +(type,) 19.647 Tj +-250 TJm +(is) 6.64532 Tj +-250 TJm +(OK.) 16.8773 Tj +[1 0 0 1 72 210.381] cm +0 g +0 G +0 g +0 G +[1 0 0 1 0 -3.765] cm +0 g +0 G +[1 0 0 1 0 -9.744] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -196.872] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 187.074 Td +/F130_0 9.963 Tf +(BZ_SEQUENCE_ERROR) 101.623 Tj +[1 0 0 1 173.619 187.074] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -104.11 -1.42] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -185.654] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 175.118 Td +/F128_0 9.963 Tf +(When) 23.7916 Tj +-290 TJm +(using) 21.5898 Tj +-291 TJm +(the) 12.1748 Tj +-290 TJm +(library) 26.5614 Tj +65 TJm +(,) 2.49075 Tj +-301 TJm +(it) 5.53943 Tj +-290 TJm +(is) 6.64532 Tj +-291 TJm +(important) 38.7461 Tj +-290 TJm +(to) 7.75121 Tj +-291 TJm +(ca) 8.84714 Tj +1 TJm +(ll) 5.53943 Tj +-291 TJm +(the) 12.1748 Tj +-290 TJm +(functions) 37.0823 Tj +-291 TJm +(in) 7.75121 Tj +-290 TJm +(the) 12.1748 Tj +-291 TJm +(correct) 27.6573 Tj +-290 TJm +(sequence) 36.5144 Tj +-290 TJm +(and) 14.3866 Tj +-291 TJm +(with) 17.7142 Tj +-290 TJm +(data) 16.5984 Tj +-291 TJm +(structures) 38.7361 Tj +108 163.163 Td +(\(b) 8.29918 Tj +20 TJm +(uf) 8.29918 Tj +25 TJm +(fers) 14.9345 Tj +-205 TJm +(etc\)) 14.9345 Tj +-206 TJm +(in) 7.75121 Tj +-206 TJm +(the) 12.1748 Tj +-205 TJm +(correct) 27.6573 Tj +-206 TJm +(states.) 24.6285 Tj +[1 0 0 1 239.409 163.163] cm +0 g +0 G +[1 0 0 1 -239.409 -163.163] cm +[1 0 0 1 0 0] Tm +0 0 Td +239.409 163.163 Td +/F130_0 9.963 Tf +(libbzip2) 47.8224 Tj +[1 0 0 1 287.23 163.163] cm +0 g +0 G +[1 0 0 1 -287.23 -163.163] cm +[1 0 0 1 0 0] Tm +0 0 Td +289.278 163.163 Td +/F128_0 9.963 Tf +(checks) 27.1093 Tj +-206 TJm +(as) 8.29918 Tj +-205 TJm +(much) 22.1378 Tj +-206 TJm +(as) 8.29918 Tj +-205 TJm +(it) 5.53943 Tj +-206 TJm +(can) 13.8286 Tj +-205 TJm +(to) 7.75121 Tj +-206 TJm +(ensure) 26.0034 Tj +-205 TJm +(this) 14.3965 Tj +-206 TJm +(is) 6.64532 Tj +-206 TJm +(happeni) 31.5429 Tj +1 TJm +(ng,) 12.4538 Tj +-215 TJm +(and) 14.3866 Tj +-206 TJm +(re) 7.74125 Tj +1 TJm +(turns) 19.926 Tj +[1 0 0 1 108 151.208] cm +0 g +0 G +[1 0 0 1 -108 -151.208] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 151.208 Td +/F130_0 9.963 Tf +(BZ_SEQUENCE_ERROR) 101.623 Tj +[1 0 0 1 209.619 151.208] cm +0 g +0 G +[1 0 0 1 -209.619 -151.208] cm +[1 0 0 1 0 0] Tm +0 0 Td +213.27 151.208 Td +/F128_0 9.963 Tf +(if) 6.08739 Tj +-367 TJm +(not) 12.7327 Tj +1 TJm +(.) 2.49075 Tj +-660 TJm +(Code) 21.0319 Tj +-367 TJm +(which) 24.3496 Tj +-366 TJm +(complies) 35.9764 Tj +-367 TJm +(precisel) 30.9849 Tj +1 TJm +(y) 4.9815 Tj +-367 TJm +(with) 17.7142 Tj +-367 TJm +(the) 12.1748 Tj +-366 TJm +(function) 33.2067 Tj +-367 TJm +(s) 3.87561 Tj +1 TJm +(emantics,) 37.9092 Tj +-396 TJm +(as) 8.29918 Tj +-367 TJm +(deta) 16.5984 Tj +1 TJm +(iled) 14.9445 Tj +108 139.253 Td +(belo) 17.1563 Tj +25 TJm +(w) 7.19329 Tj +65 TJm +(,) 2.49075 Tj +-250 TJm +(should) 26.5713 Tj +-250 TJm +(ne) 9.40507 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(er) 7.74125 Tj +-250 TJm +(recei) 19.3581 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-250 TJm +(this) 14.3965 Tj +-249 TJm +(v) 4.9815 Tj +25 TJm +(alue;) 19.3681 Tj +-250 TJm +(such) 18.2622 Tj +-250 TJm +(an) 9.40507 Tj +-250 TJm +(e) 4.42357 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(ent) 12.1748 Tj +-250 TJm +(denotes) 30.437 Tj +-250 TJm +(b) 4.9815 Tj +20 TJm +(uggy) 19.926 Tj +-250 TJm +(code) 18.8101 Tj +-250 TJm +(which) 24.3496 Tj +-250 TJm +(you) 14.9445 Tj +-250 TJm +(should) 26.5713 Tj +-250 TJm +(i) 2.76971 Tj +1 TJm +(n) 4.9815 Tj +40 TJm +(v) 4.9815 Tj +15 TJm +(estig) 18.8201 Tj +5 TJm +(ate.) 14.1076 Tj +[1 0 0 1 72 137.096] cm +0 g +0 G +0 g +0 G +[1 0 0 1 0 -3.766] cm +0 g +0 G +[1 0 0 1 0 -9.743] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -123.587] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 113.788 Td +/F130_0 9.963 Tf +(BZ_PARAM_ERROR) 83.6892 Tj +[1 0 0 1 155.686 113.788] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -86.177 -1.165] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -112.623] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 101.833 Td +/F128_0 9.963 Tf +(Returned) 36.5244 Tj +-434 TJm +(when) 21.5799 Tj +-434 TJm +(a) 4.42357 Tj +-433 TJm +(parameter) 39.8321 Tj +-434 TJm +(to) 7.75121 Tj +-434 TJm +(a) 4.42357 Tj +-434 TJm +(function) 33.2067 Tj +-434 TJm +(call) 14.3866 Tj +-434 TJm +(is) 6.64532 Tj +-433 TJm +(out) 12.7327 Tj +-434 TJm +(of) 8.29918 Tj +-434 TJm +(range) 22.1278 Tj +-434 TJm +(or) 8.29918 Tj +-434 TJm +(otherwise) 38.7361 Tj +-434 TJm +(man) 17.1563 Tj +1 TJm +(ifestly) 24.9075 Tj +-434 TJm +(incorrect.) 37.8993 Tj +-1724 TJm +(As) 11.0689 Tj +108 89.878 Td +(with) 17.7142 Tj +[1 0 0 1 131.644 89.878] cm +0 g +0 G +[1 0 0 1 -131.644 -89.878] cm +[1 0 0 1 0 0] Tm +0 0 Td +131.644 89.878 Td +/F130_0 9.963 Tf +(BZ_SEQUENCE_ERROR) 101.623 Tj +[1 0 0 1 233.263 89.878] cm +0 g +0 G +[1 0 0 1 -233.263 -89.878] cm +[1 0 0 1 0 0] Tm +0 0 Td +233.263 89.878 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-595 TJm +(this) 14.3965 Tj +-596 TJm +(d) 4.9815 Tj +1 TJm +(enotes) 25.4555 Tj +-596 TJm +(a) 4.42357 Tj +-595 TJm +(b) 4.9815 Tj +20 TJm +(ug) 9.963 Tj +-595 TJm +(in) 7.75121 Tj +-595 TJm +(the) 12.1748 Tj +-596 TJm +(client) 22.1378 Tj +-595 TJm +(code.) 21.3009 Tj +-2692 TJm +(T) 6.08739 Tj +1 TJm +(he) 9.40507 Tj +-596 TJm +(distinction) 42.0737 Tj +-595 TJm +(between) 33.1967 Tj +[1 0 0 1 108 77.923] cm +0 g +0 G +[1 0 0 1 -108 -77.923] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 77.923 Td +/F130_0 9.963 Tf +(BZ_PARAM_ERROR) 83.6892 Tj +[1 0 0 1 191.686 77.923] cm +0 g +0 G +[1 0 0 1 -191.686 -77.923] cm +[1 0 0 1 0 0] Tm +0 0 Td +194.177 77.923 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 211.053 77.923] cm +0 g +0 G +[1 0 0 1 -211.053 -77.923] cm +[1 0 0 1 0 0] Tm +0 0 Td +211.053 77.923 Td +/F130_0 9.963 Tf +(BZ_SEQUENCE_ERROR) 101.623 Tj +[1 0 0 1 312.672 77.923] cm +0 g +0 G +[1 0 0 1 -312.672 -77.923] cm +[1 0 0 1 0 0] Tm +0 0 Td +315.163 77.923 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(bit) 10.5209 Tj +-250 TJm +(hazy) 18.8101 Tj +65 TJm +(,) 2.49075 Tj +-250 TJm +(b) 4.9815 Tj +20 TJm +(ut) 7.75121 Tj +-250 TJm +(still) 14.9545 Tj +-250 TJm +(w) 7.19329 Tj +10 TJm +(orth) 16.0504 Tj +-250 TJm +(m) 7.75121 Tj +1 TJm +(aking.) 24.6285 Tj +[1 0 0 1 72 75.766] cm +0 g +0 G +0 g +0 G +[1 0 0 1 0 -3.766] cm +0 g +0 G +[1 0 0 1 0 -21.148] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.854] cm +0 g +0 G +0 g +0 G +[1 0 0 1 40.572 -6.755] cm +0 g +0 G +[1 0 0 1 -493.841 -50.951] cm +[1 0 0 1 0 0] Tm +0 0 Td +534.414 50.951 Td +/F128_0 9.963 Tf +(10) 9.963 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 14 14 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 -8.911] cm +0 g +0 G +[1 0 0 1 0 8.911] cm +0 g +0 G +0 g +0 G +[1 0 0 1 84.08 -6.755] cm +0 g +0 G +[1 0 0 1 -350.151 -749.245] cm +[1 0 0 1 0 0] Tm +0 0 Td +434.231 749.245 Td +/F128_0 9.963 Tf +(Programming) 54.7965 Tj +-250 TJm +(with) 17.7142 Tj +-250 TJm +(libbzip2) 32.6587 Tj +[1 0 0 1 266.071 747.089] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -5.037] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -468 -21.554] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -720] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 710.037 Td +/F130_0 9.963 Tf +(BZ_MEM_ERROR) 71.7336 Tj +[1 0 0 1 143.731 710.037] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -74.222 -1.165] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -708.872] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 698.082 Td +/F128_0 9.963 Tf +(Returned) 36.5244 Tj +-227 TJm +(when) 21.5799 Tj +-228 TJm +(a) 4.42357 Tj +-228 TJm +(reque) 22.1278 Tj +1 TJm +(st) 6.64532 Tj +-228 TJm +(to) 7.75121 Tj +-228 TJm +(allocate) 30.9849 Tj +-227 TJm +(memory) 33.2067 Tj +-228 TJm +(f) 3.31768 Tj +10 TJm +(aile) 14.3866 Tj +1 TJm +(d.) 7.47225 Tj +-606 TJm +(N) 7.19329 Tj +1 TJm +(ote) 12.1748 Tj +-228 TJm +(that) 14.9445 Tj +-228 TJm +(the) 12.1748 Tj +-227 TJm +(quantity) 32.6587 Tj +-228 TJm +(of) 8.29918 Tj +-227 TJm +(memory) 33.2067 Tj +-228 TJm +(needed) 28.2152 Tj +-227 TJm +(to) 7.75121 Tj +-228 TJm +(decompress) 47.0353 Tj +108 686.127 Td +(a) 4.42357 Tj +-351 TJm +(stream) 26.5614 Tj +-352 TJm +(cannot) 26.5614 Tj +-351 TJm +(be) 9.40507 Tj +-351 TJm +(determined) 44.8235 Tj +-352 TJm +(until) 18.2721 Tj +-351 TJm +(the) 12.1748 Tj +-351 TJm +(stream') 29.879 Tj +55 TJm +(s) 3.87561 Tj +-352 TJm +(heade) 23.2337 Tj +1 TJm +(r) 3.31768 Tj +-352 TJm +(has) 13.2807 Tj +-351 TJm +(been) 18.8101 Tj +-352 TJm +(read.) 19.6371 Tj +-1228 TJm +(So) 10.5209 Tj +[1 0 0 1 426.471 686.127] cm +0 g +0 G +[1 0 0 1 -426.471 -686.127] cm +[1 0 0 1 0 0] Tm +0 0 Td +426.471 686.127 Td +/F130_0 9.963 Tf +(BZ2_bzDecompress) 95.6448 Tj +[1 0 0 1 522.113 686.127] cm +0 g +0 G +[1 0 0 1 -522.113 -686.127] cm +[1 0 0 1 0 0] Tm +0 0 Td +525.614 686.127 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 108 674.172] cm +0 g +0 G +[1 0 0 1 -108 -674.172] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 674.172 Td +/F130_0 9.963 Tf +(BZ2_bzRead) 59.778 Tj +[1 0 0 1 167.776 674.172] cm +0 g +0 G +[1 0 0 1 -167.776 -674.172] cm +[1 0 0 1 0 0] Tm +0 0 Td +172.13 674.172 Td +/F128_0 9.963 Tf +(may) 17.1563 Tj +-437 TJm +(return) 23.7916 Tj +[1 0 0 1 221.784 674.172] cm +0 g +0 G +[1 0 0 1 -221.784 -674.172] cm +[1 0 0 1 0 0] Tm +0 0 Td +221.784 674.172 Td +/F130_0 9.963 Tf +(BZ_MEM_ERROR) 71.7336 Tj +[1 0 0 1 293.515 674.172] cm +0 g +0 G +[1 0 0 1 -293.515 -674.172] cm +[1 0 0 1 0 0] Tm +0 0 Td +297.867 674.172 Td +/F128_0 9.963 Tf +(e) 4.42357 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(en) 9.40507 Tj +-437 TJm +(though) 27.6772 Tj +-437 TJm +(some) 21.0319 Tj +-437 TJm +(of) 8.29918 Tj +-437 TJm +(the) 12.1748 Tj +-437 TJm +(compressed) 47.0353 Tj +-437 TJm +(da) 9.40507 Tj +1 TJm +(ta) 7.19329 Tj +-437 TJm +(has) 13.2807 Tj +-437 TJm +(been) 18.8101 Tj +-437 TJm +(read.) 19.6371 Tj +108 662.217 Td +(The) 15.4925 Tj +-479 TJm +(sam) 16.0504 Tj +1 TJm +(e) 4.42357 Tj +-479 TJm +(is) 6.64532 Tj +-479 TJm +(not) 12.7327 Tj +-478 TJm +(true) 15.4925 Tj +-479 TJm +(for) 11.6169 Tj +-478 TJm +(compression;) 53.1327 Tj +-593 TJm +(once) 18.8101 Tj +[1 0 0 1 301.675 662.217] cm +0 g +0 G +[1 0 0 1 -301.675 -662.217] cm +[1 0 0 1 0 0] Tm +0 0 Td +301.675 662.217 Td +/F130_0 9.963 Tf +(BZ2_bzCompressInit) 107.6 Tj +[1 0 0 1 409.272 662.217] cm +0 g +0 G +[1 0 0 1 -409.272 -662.217] cm +[1 0 0 1 0 0] Tm +0 0 Td +414.04 662.217 Td +/F128_0 9.963 Tf +(or) 8.29918 Tj +[1 0 0 1 427.107 662.217] cm +0 g +0 G +[1 0 0 1 -427.107 -662.217] cm +[1 0 0 1 0 0] Tm +0 0 Td +427.107 662.217 Td +/F130_0 9.963 Tf +(BZ2_bzWriteOpen) 89.667 Tj +[1 0 0 1 516.771 662.217] cm +0 g +0 G +[1 0 0 1 -516.771 -662.217] cm +[1 0 0 1 0 0] Tm +0 0 Td +521.539 662.217 Td +/F128_0 9.963 Tf +(ha) 9.40507 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +108 650.262 Td +(successfully) 48.6991 Tj +-250 TJm +(completed,) 43.9966 Tj +[1 0 0 1 205.672 650.262] cm +0 g +0 G +[1 0 0 1 -205.672 -650.262] cm +[1 0 0 1 0 0] Tm +0 0 Td +205.672 650.262 Td +/F130_0 9.963 Tf +(BZ_MEM_ERROR) 71.7336 Tj +[1 0 0 1 277.403 650.262] cm +0 g +0 G +[1 0 0 1 -277.403 -650.262] cm +[1 0 0 1 0 0] Tm +0 0 Td +279.894 650.262 Td +/F128_0 9.963 Tf +(cannot) 26.5614 Tj +-250 TJm +(occur) 22.1278 Tj +55 TJm +(.) 2.49075 Tj +[1 0 0 1 72 648.105] cm +0 g +0 G +0 g +0 G +[1 0 0 1 0 -3.985] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -634.157] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 624.359 Td +/F130_0 9.963 Tf +(BZ_DATA_ERROR) 77.7114 Tj +[1 0 0 1 149.709 624.359] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -80.199 -1.166] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -623.193] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 612.404 Td +/F128_0 9.963 Tf +(Returned) 36.5244 Tj +-265 TJm +(when) 21.5799 Tj +-266 TJm +(a) 4.42357 Tj +-266 TJm +(da) 9.40507 Tj +1 TJm +(ta) 7.19329 Tj +-266 TJm +(inte) 14.9445 Tj +15 TJm +(grity) 18.8201 Tj +-265 TJm +(error) 19.3581 Tj +-266 TJm +(is) 6.64532 Tj +-266 TJm +(dete) 16.5984 Tj +1 TJm +(cted) 16.5984 Tj +-266 TJm +(during) 26.0134 Tj +-266 TJm +(d) 4.9815 Tj +1 TJm +(ecompression.) 57.2773 Tj +-714 TJm +(Most) 20.4839 Tj +-265 TJm +(importantly) 46.4973 Tj +65 TJm +(,) 2.49075 Tj +-270 TJm +(this) 14.3965 Tj +-265 TJm +(means) 25.4555 Tj +-266 TJm +(when) 21.5799 Tj +108 600.448 Td +(stored) 24.3496 Tj +-222 TJm +(and) 14.3866 Tj +-222 TJm +(computed) 39.2941 Tj +-222 TJm +(CRCs) 23.8116 Tj +-223 TJm +(for) 11.6169 Tj +-222 TJm +(the) 12.1748 Tj +-222 TJm +(data) 16.5984 Tj +-222 TJm +(do) 9.963 Tj +-222 TJm +(not) 12.7327 Tj +-223 TJm +(match.) 26.8403 Tj +-601 TJm +(This) 17.7142 Tj +-222 TJm +(v) 4.9815 Tj +25 TJm +(alue) 16.5984 Tj +-222 TJm +(is) 6.64532 Tj +-223 TJm +(also) 16.0504 Tj +-222 TJm +(returned) 33.1967 Tj +-222 TJm +(upon) 19.926 Tj +-222 TJm +(detection) 36.5244 Tj +-222 TJm +(of) 8.29918 Tj +-222 TJm +(an) 9.40507 Tj +15 TJm +(y) 4.9815 Tj +-223 TJm +(other) 20.474 Tj +108 588.493 Td +(anomaly) 34.3126 Tj +-250 TJm +(in) 7.75121 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(compressed) 47.0353 Tj +-250 TJm +(d) 4.9815 Tj +1 TJm +(ata.) 14.1076 Tj +[1 0 0 1 72 586.336] cm +0 g +0 G +0 g +0 G +[1 0 0 1 0 -3.985] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -572.389] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 562.59 Td +/F130_0 9.963 Tf +(BZ_DATA_ERROR_MAGIC) 113.578 Tj +[1 0 0 1 185.574 562.59] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -116.065 -1.165] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -561.425] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 550.635 Td +/F128_0 9.963 Tf +(As) 11.0689 Tj +-306 TJm +(a) 4.42357 Tj +-306 TJm +(special) 27.6673 Tj +-306 TJm +(case) 17.1463 Tj +-306 TJm +(of) 8.29918 Tj +[1 0 0 1 191.852 550.635] cm +0 g +0 G +[1 0 0 1 -191.852 -550.635] cm +[1 0 0 1 0 0] Tm +0 0 Td +191.852 550.635 Td +/F130_0 9.963 Tf +(BZ_DATA_ERROR) 77.7114 Tj +[1 0 0 1 269.561 550.635] cm +0 g +0 G +[1 0 0 1 -269.561 -550.635] cm +[1 0 0 1 0 0] Tm +0 0 Td +269.561 550.635 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-306 TJm +(it) 5.53943 Tj +-306 TJm +(is) 6.64532 Tj +-306 TJm +(sometimes) 42.6217 Tj +-306 TJm +(useful) 24.3496 Tj +-306 TJm +(to) 7.75121 Tj +-306 TJm +(kno) 14.9445 Tj +25 TJm +(w) 7.19329 Tj +-306 TJm +(when) 21.5799 Tj +-306 TJm +(the) 12.1748 Tj +-307 TJm +(com) 17.1563 Tj +1 TJm +(pressed) 29.879 Tj +-306 TJm +(stream) 26.5614 Tj +-306 TJm +(does) 18.2622 Tj +108 538.68 Td +(not) 12.7327 Tj +-250 TJm +(start) 17.1563 Tj +-250 TJm +(with) 17.7142 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(correct) 27.6573 Tj +-250 TJm +(m) 7.75121 Tj +1 TJm +(agic) 16.5984 Tj +-250 TJm +(bytes) 21.0319 Tj +-250 TJm +(\() 3.31768 Tj +[1 0 0 1 261.562 538.68] cm +0 g +0 G +[1 0 0 1 -261.562 -538.68] cm +[1 0 0 1 0 0] Tm +0 0 Td +261.562 538.68 Td +/F130_0 9.963 Tf +('B') 17.9334 Tj +-600 TJm +('Z') 17.9334 Tj +-600 TJm +('h') 17.9334 Tj +[1 0 0 1 327.316 538.68] cm +0 g +0 G +[1 0 0 1 -327.316 -538.68] cm +[1 0 0 1 0 0] Tm +0 0 Td +327.316 538.68 Td +/F128_0 9.963 Tf +(\).) 5.80843 Tj +[1 0 0 1 72 536.523] cm +0 g +0 G +0 g +0 G +[1 0 0 1 0 -3.985] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -522.576] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 512.777 Td +/F130_0 9.963 Tf +(BZ_IO_ERROR) 65.7558 Tj +[1 0 0 1 137.753 512.777] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -68.244 -1.165] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -511.612] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 500.822 Td +/F128_0 9.963 Tf +(Returned) 36.5244 Tj +-233 TJm +(by) 9.963 Tj +[1 0 0 1 159.123 500.822] cm +0 g +0 G +[1 0 0 1 -159.123 -500.822] cm +[1 0 0 1 0 0] Tm +0 0 Td +159.123 500.822 Td +/F130_0 9.963 Tf +(BZ2_bzRead) 59.778 Tj +[1 0 0 1 218.899 500.822] cm +0 g +0 G +[1 0 0 1 -218.899 -500.822] cm +[1 0 0 1 0 0] Tm +0 0 Td +221.218 500.822 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 237.922 500.822] cm +0 g +0 G +[1 0 0 1 -237.922 -500.822] cm +[1 0 0 1 0 0] Tm +0 0 Td +237.922 500.822 Td +/F130_0 9.963 Tf +(BZ2_bzWrite) 65.7558 Tj +[1 0 0 1 303.676 500.822] cm +0 g +0 G +[1 0 0 1 -303.676 -500.822] cm +[1 0 0 1 0 0] Tm +0 0 Td +305.995 500.822 Td +/F128_0 9.963 Tf +(when) 21.5799 Tj +-233 TJm +(there) 19.916 Tj +-232 TJm +(is) 6.64532 Tj +-233 TJm +(an) 9.40507 Tj +-233 TJm +(error) 19.3581 Tj +-232 TJm +(reading) 29.879 Tj +-233 TJm +(or) 8.29918 Tj +-233 TJm +(writing) 28.7831 Tj +-232 TJm +(in) 7.75121 Tj +-233 TJm +(the) 12.1748 Tj +-233 TJm +(compress) 37.6303 Tj +1 TJm +(ed) 9.40507 Tj +108 488.867 Td +(\002le,) 15.2235 Tj +-384 TJm +(and) 14.3866 Tj +-357 TJm +(by) 9.963 Tj +[1 0 0 1 158.511 488.867] cm +0 g +0 G +[1 0 0 1 -158.511 -488.867] cm +[1 0 0 1 0 0] Tm +0 0 Td +158.511 488.867 Td +/F130_0 9.963 Tf +(BZ2_bzReadOpen) 83.6892 Tj +[1 0 0 1 242.197 488.867] cm +0 g +0 G +[1 0 0 1 -242.197 -488.867] cm +[1 0 0 1 0 0] Tm +0 0 Td +245.755 488.867 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 263.698 488.867] cm +0 g +0 G +[1 0 0 1 -263.698 -488.867] cm +[1 0 0 1 0 0] Tm +0 0 Td +263.698 488.867 Td +/F130_0 9.963 Tf +(BZ2_bzWriteOpen) 89.667 Tj +[1 0 0 1 353.362 488.867] cm +0 g +0 G +[1 0 0 1 -353.362 -488.867] cm +[1 0 0 1 0 0] Tm +0 0 Td +356.92 488.867 Td +/F128_0 9.963 Tf +(for) 11.6169 Tj +-357 TJm +(attempts) 33.7646 Tj +-357 TJm +(to) 7.75121 Tj +-357 TJm +(use) 13.2807 Tj +-357 TJm +(a) 4.42357 Tj +-357 TJm +(\002le) 12.7327 Tj +-357 TJm +(for) 11.6169 Tj +-357 TJm +(which) 24.3496 Tj +-357 TJm +(the) 12.1748 Tj +-357 TJm +(error) 19.3581 Tj +108 476.912 Td +(indicator) 35.4185 Tj +-260 TJm +(\(viz,) 17.9832 Tj +[1 0 0 1 166.603 476.912] cm +0 g +0 G +[1 0 0 1 -166.603 -476.912] cm +[1 0 0 1 0 0] Tm +0 0 Td +166.603 476.912 Td +/F130_0 9.963 Tf +(ferror\(f\)) 53.8002 Tj +[1 0 0 1 220.401 476.912] cm +0 g +0 G +[1 0 0 1 -220.401 -476.912] cm +[1 0 0 1 0 0] Tm +0 0 Td +220.401 476.912 Td +/F128_0 9.963 Tf +(\)) 3.31768 Tj +-260 TJm +(is) 6.64532 Tj +-260 TJm +(set.) 13.5596 Tj +-679 TJm +(On) 12.1748 Tj +-260 TJm +(receipt) 27.1093 Tj +-260 TJm +(of) 8.29918 Tj +[1 0 0 1 311.223 476.912] cm +0 g +0 G +[1 0 0 1 -311.223 -476.912] cm +[1 0 0 1 0 0] Tm +0 0 Td +311.223 476.912 Td +/F130_0 9.963 Tf +(BZ_IO_ERROR) 65.7558 Tj +[1 0 0 1 376.976 476.912] cm +0 g +0 G +[1 0 0 1 -376.976 -476.912] cm +[1 0 0 1 0 0] Tm +0 0 Td +376.976 476.912 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-260 TJm +(the) 12.1748 Tj +-260 TJm +(caller) 22.1278 Tj +-260 TJm +(should) 26.5713 Tj +-259 TJm +(consult) 28.7831 Tj +[1 0 0 1 482.068 476.912] cm +0 g +0 G +[1 0 0 1 -482.068 -476.912] cm +[1 0 0 1 0 0] Tm +0 0 Td +482.068 476.912 Td +/F130_0 9.963 Tf +(errno) 29.889 Tj +[1 0 0 1 511.956 476.912] cm +0 g +0 G +[1 0 0 1 -511.956 -476.912] cm +[1 0 0 1 0 0] Tm +0 0 Td +514.546 476.912 Td +/F128_0 9.963 Tf +(and/or) 25.4555 Tj +[1 0 0 1 108 464.957] cm +0 g +0 G +[1 0 0 1 -108 -464.957] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 464.957 Td +/F130_0 9.963 Tf +(perror) 35.8668 Tj +[1 0 0 1 143.865 464.957] cm +0 g +0 G +[1 0 0 1 -143.865 -464.957] cm +[1 0 0 1 0 0] Tm +0 0 Td +146.356 464.957 Td +/F128_0 9.963 Tf +(to) 7.75121 Tj +-250 TJm +(acquire) 29.3211 Tj +-250 TJm +(operating-system) 68.6251 Tj +-249 TJm +(speci\002c) 30.437 Tj +-250 TJm +(information) 47.0453 Tj +-250 TJm +(about) 22.1378 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(problem.) 35.6974 Tj +[1 0 0 1 72 462.8] cm +0 g +0 G +0 g +0 G +[1 0 0 1 0 -3.985] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -448.852] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 439.054 Td +/F130_0 9.963 Tf +(BZ_UNEXPECTED_EOF) 101.623 Tj +[1 0 0 1 173.619 439.054] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -104.11 -1.166] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -437.888] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 427.099 Td +/F128_0 9.963 Tf +(Returned) 36.5244 Tj +-250 TJm +(by) 9.963 Tj +[1 0 0 1 159.467 427.099] cm +0 g +0 G +[1 0 0 1 -159.467 -427.099] cm +[1 0 0 1 0 0] Tm +0 0 Td +159.467 427.099 Td +/F130_0 9.963 Tf +(BZ2_bzRead) 59.778 Tj +[1 0 0 1 219.242 427.099] cm +0 g +0 G +[1 0 0 1 -219.242 -427.099] cm +[1 0 0 1 0 0] Tm +0 0 Td +221.733 427.099 Td +/F128_0 9.963 Tf +(when) 21.5799 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(compressed) 47.0353 Tj +-250 TJm +(\002le) 12.7327 Tj +-250 TJm +(\002nis) 17.1662 Tj +1 TJm +(hes) 13.2807 Tj +-250 TJm +(before) 25.4455 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(logical) 27.1193 Tj +-250 TJm +(end) 14.3866 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(stream) 26.5614 Tj +-250 TJm +(is) 6.64532 Tj +-250 TJm +(detected.) 35.6875 Tj +[1 0 0 1 72 424.942] cm +0 g +0 G +0 g +0 G +[1 0 0 1 0 -3.985] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -410.994] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 401.196 Td +/F130_0 9.963 Tf +(BZ_OUTBUFF_FULL) 89.667 Tj +[1 0 0 1 161.664 401.196] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -92.154 -1.166] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -400.03] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 389.241 Td +/F128_0 9.963 Tf +(Returned) 36.5244 Tj +-258 TJm +(by) 9.963 Tj +[1 0 0 1 159.632 389.241] cm +0 g +0 G +[1 0 0 1 -159.632 -389.241] cm +[1 0 0 1 0 0] Tm +0 0 Td +159.632 389.241 Td +/F130_0 9.963 Tf +(BZ2_bzBuffToBuffCompress) 143.467 Tj +[1 0 0 1 303.094 389.241] cm +0 g +0 G +[1 0 0 1 -303.094 -389.241] cm +[1 0 0 1 0 0] Tm +0 0 Td +305.667 389.241 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 322.627 389.241] cm +0 g +0 G +[1 0 0 1 -322.627 -389.241] cm +[1 0 0 1 0 0] Tm +0 0 Td +322.627 389.241 Td +/F130_0 9.963 Tf +(BZ2_bzBuffToBuffDecompres) 149.445 Tj +1 TJm +(s) 5.9778 Tj +[1 0 0 1 478.044 389.241] cm +0 g +0 G +[1 0 0 1 -478.044 -389.241] cm +[1 0 0 1 0 0] Tm +0 0 Td +480.617 389.241 Td +/F128_0 9.963 Tf +(to) 7.75121 Tj +-258 TJm +(indicate) 31.5429 Tj +-258 TJm +(that) 14.9445 Tj +108 377.285 Td +(the) 12.1748 Tj +-250 TJm +(output) 25.4654 Tj +-250 TJm +(data) 16.5984 Tj +-250 TJm +(will) 15.5024 Tj +-250 TJm +(not) 12.7327 Tj +-250 TJm +(\002t) 8.30914 Tj +-250 TJm +(in) 7.75121 Tj +1 TJm +(to) 7.75121 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(output) 25.4654 Tj +-250 TJm +(b) 4.9815 Tj +20 TJm +(uf) 8.29918 Tj +25 TJm +(fer) 11.0589 Tj +-250 TJm +(pro) 13.2807 Tj +15 TJm +(vided.) 24.6285 Tj +[1 0 0 1 72 375.129] cm +0 g +0 G +0 g +0 G +[1 0 0 1 0 -3.985] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -351.218] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 328.585 Td +/F121_0 20.659 Tf +(3.3.) 34.4592 Tj +-278 TJm +(Lo) 25.2453 Tj +15 TJm +(w-le) 40.1818 Tj +15 TJm +(vel) 28.716 Tj +-278 TJm +(interface) 86.1067 Tj +[1 0 0 1 72 328.327] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -318.364] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 297.964 Td +/F121_0 17.215 Tf +(3.3.1.) 43.0719 Tj +[1 0 0 1 119.858 297.964] cm +0 g +0 G +[1 0 0 1 -119.858 -297.964] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.858 297.964 Td +/F387_0 17.215 Tf +(BZ2_bzCompressInit) 185.922 Tj +[1 0 0 1 305.785 297.964] cm +0 g +0 G +[1 0 0 1 -233.785 -2.333] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -244.779] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.754] cm +0 g +0 G +0 g +0 G +[1 0 0 1 40.572 -6.754] cm +0 g +0 G +[1 0 0 1 -493.841 -50.852] cm +[1 0 0 1 0 0] Tm +0 0 Td +534.414 50.852 Td +/F128_0 9.963 Tf +(11) 9.963 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 15 15 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 -8.911] cm +0 g +0 G +[1 0 0 1 0 8.911] cm +0 g +0 G +0 g +0 G +[1 0 0 1 84.08 -6.755] cm +0 g +0 G +[1 0 0 1 -350.151 -749.245] cm +[1 0 0 1 0 0] Tm +0 0 Td +434.231 749.245 Td +/F128_0 9.963 Tf +(Programming) 54.7965 Tj +-250 TJm +(with) 17.7142 Tj +-250 TJm +(libbzip2) 32.6587 Tj +[1 0 0 1 266.071 747.089] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -5.037] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -468 -296.523] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 274.969 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 271.382] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -711.631] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 711.631 Td +/F130_0 9.963 Tf +(typedef) 41.8446 Tj +-426 TJm +(struct) 35.8668 Tj +-426 TJm +({) 5.9778 Tj +98.488 699.676 Td +(char) 23.9112 Tj +-426 TJm +(*next_in;) 53.8002 Tj +98.488 687.721 Td +(unsigned) 47.8224 Tj +-426 TJm +(int) 17.9334 Tj +-426 TJm +(avail_in;) 53.8002 Tj +98.488 675.766 Td +(unsigned) 47.8224 Tj +-426 TJm +(int) 17.9334 Tj +-426 TJm +(total_in_lo3) 71.7336 Tj +1 TJm +(2;) 11.9556 Tj +98.488 663.811 Td +(unsigned) 47.8224 Tj +-426 TJm +(int) 17.9334 Tj +-426 TJm +(total_in_hi3) 71.7336 Tj +1 TJm +(2;) 11.9556 Tj +98.488 639.9 Td +(char) 23.9112 Tj +-426 TJm +(*next_out;) 59.778 Tj +98.488 627.945 Td +(unsigned) 47.8224 Tj +-426 TJm +(int) 17.9334 Tj +-426 TJm +(avail_out;) 59.778 Tj +98.488 615.99 Td +(unsigned) 47.8224 Tj +-426 TJm +(int) 17.9334 Tj +-426 TJm +(total_out_lo) 71.7336 Tj +1 TJm +(32;) 17.9334 Tj +98.488 604.035 Td +(unsigned) 47.8224 Tj +-426 TJm +(int) 17.9334 Tj +-426 TJm +(total_out_hi) 71.7336 Tj +1 TJm +(32;) 17.9334 Tj +98.488 580.124 Td +(void) 23.9112 Tj +-426 TJm +(*state;) 41.8446 Tj +98.488 556.214 Td +(void) 23.9112 Tj +-426 TJm +(*\(*bzalloc\)\(void) 95.6448 Tj +-426 TJm +(*,i) 17.9334 Tj +1 TJm +(nt,int\);) 47.8224 Tj +98.488 544.259 Td +(void) 23.9112 Tj +-426 TJm +(\(*bzfree\)\(void) 83.6892 Tj +-426 TJm +(*,voi) 29.889 Tj +1 TJm +(d) 5.9778 Tj +-426 TJm +(*\);) 17.9334 Tj +98.488 532.304 Td +(void) 23.9112 Tj +-426 TJm +(*opaque;) 47.8224 Tj +90 520.349 Td +(}) 5.9778 Tj +-426 TJm +(bz_stream;) 59.778 Tj +90 496.438 Td +(int) 17.9334 Tj +-426 TJm +(BZ2_bzCompressInit) 107.6 Tj +-426 TJm +(\() 5.9778 Tj +-425 TJm +(bz_stream) 53.8002 Tj +-426 TJm +(*strm,) 35.8668 Tj +196.099 484.483 Td +(int) 17.9334 Tj +-426 TJm +(blockSize100k,) 83.6892 Tj +196.099 472.528 Td +(int) 17.9334 Tj +-426 TJm +(verbosity,) 59.778 Tj +196.099 460.573 Td +(int) 17.9334 Tj +-426 TJm +(workFactor) 59.778 Tj +-426 TJm +(\);) 11.9556 Tj +[1 0 0 1 72 445.031] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.55] cm +0 g +0 G +[1 0 0 1 -72 -435.068] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 423.113 Td +/F128_0 9.963 Tf +(Prepares) 34.3026 Tj +-356 TJm +(for) 11.6169 Tj +-356 TJm +(compressi) 40.4 Tj +1 TJm +(on.) 12.4538 Tj +-1256 TJm +(The) 15.4925 Tj +[1 0 0 1 209.409 423.113] cm +0 g +0 G +[1 0 0 1 -209.409 -423.113] cm +[1 0 0 1 0 0] Tm +0 0 Td +209.409 423.113 Td +/F130_0 9.963 Tf +(bz_stream) 53.8002 Tj +[1 0 0 1 263.208 423.113] cm +0 g +0 G +[1 0 0 1 -263.208 -423.113] cm +[1 0 0 1 0 0] Tm +0 0 Td +266.754 423.113 Td +/F128_0 9.963 Tf +(structure) 34.8605 Tj +-356 TJm +(holds) 21.5898 Tj +-356 TJm +(all) 9.963 Tj +-356 TJm +(d) 4.9815 Tj +1 TJm +(ata) 11.6169 Tj +-356 TJm +(pertaining) 40.4 Tj +-356 TJm +(to) 7.75121 Tj +-356 TJm +(the) 12.1748 Tj +-356 TJm +(compression) 50.363 Tj +-356 TJm +(acti) 14.3866 Tj +25 TJm +(vit) 10.5209 Tj +1 TJm +(y) 4.9815 Tj +65 TJm +(.) 2.49075 Tj +-1256 TJm +(A) 7.19329 Tj +[1 0 0 1 72 411.158] cm +0 g +0 G +[1 0 0 1 -72 -411.158] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 411.158 Td +/F130_0 9.963 Tf +(bz_stream) 53.8002 Tj +[1 0 0 1 125.798 411.158] cm +0 g +0 G +[1 0 0 1 -125.798 -411.158] cm +[1 0 0 1 0 0] Tm +0 0 Td +128.581 411.158 Td +/F128_0 9.963 Tf +(structure) 34.8605 Tj +-279 TJm +(should) 26.5713 Tj +-279 TJm +(be) 9.40507 Tj +-280 TJm +(allocate) 30.9849 Tj +1 TJm +(d) 4.9815 Tj +-280 TJm +(and) 14.3866 Tj +-279 TJm +(initialised) 39.304 Tj +-279 TJm +(prior) 19.3681 Tj +-279 TJm +(to) 7.75121 Tj +-280 TJm +(the) 12.1748 Tj +-279 TJm +(call.) 16.8773 Tj +-796 TJm +(The) 15.4925 Tj +-279 TJm +(\002elds) 21.5898 Tj +-279 TJm +(of) 8.29918 Tj +[1 0 0 1 431.939 411.158] cm +0 g +0 G +[1 0 0 1 -431.939 -411.158] cm +[1 0 0 1 0 0] Tm +0 0 Td +431.939 411.158 Td +/F130_0 9.963 Tf +(bz_stream) 53.8002 Tj +[1 0 0 1 485.738 411.158] cm +0 g +0 G +[1 0 0 1 -485.738 -411.158] cm +[1 0 0 1 0 0] Tm +0 0 Td +488.52 411.158 Td +/F128_0 9.963 Tf +(comprise) 36.5244 Tj +-279 TJm +(the) 12.1748 Tj +72 399.203 Td +(entirety) 30.437 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(user) 16.5984 Tj +20 TJm +(-visible) 29.889 Tj +-250 TJm +(d) 4.9815 Tj +1 TJm +(ata.) 14.1076 Tj +[1 0 0 1 204.422 399.203] cm +0 g +0 G +[1 0 0 1 -204.422 -399.203] cm +[1 0 0 1 0 0] Tm +0 0 Td +204.422 399.203 Td +/F130_0 9.963 Tf +(state) 29.889 Tj +[1 0 0 1 234.31 399.203] cm +0 g +0 G +[1 0 0 1 -234.31 -399.203] cm +[1 0 0 1 0 0] Tm +0 0 Td +236.8 399.203 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(pointer) 28.2252 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(pri) 11.0689 Tj +25 TJm +(v) 4.9815 Tj +25 TJm +(ate) 11.6169 Tj +-250 TJm +(data) 16.5984 Tj +-249 TJm +(structures) 38.7361 Tj +-250 TJm +(required) 33.1967 Tj +-250 TJm +(for) 11.6169 Tj +-250 TJm +(compression.) 52.8537 Tj +[1 0 0 1 72 397.046] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -387.084] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 377.285 Td +/F128_0 9.963 Tf +(Custom) 31.0049 Tj +-372 TJm +(memory) 33.2067 Tj +-372 TJm +(allocators) 38.7361 Tj +-372 TJm +(are) 12.1648 Tj +-372 TJm +(supported,) 41.7848 Tj +-402 TJm +(via) 12.1748 Tj +-372 TJm +(\002elds) 21.5898 Tj +[1 0 0 1 288.908 377.285] cm +0 g +0 G +[1 0 0 1 -288.908 -377.285] cm +[1 0 0 1 0 0] Tm +0 0 Td +288.908 377.285 Td +/F130_0 9.963 Tf +(bzalloc) 41.8446 Tj +[1 0 0 1 330.751 377.285] cm +0 g +0 G +[1 0 0 1 -330.751 -377.285] cm +[1 0 0 1 0 0] Tm +0 0 Td +330.751 377.285 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 337.253 377.285] cm +0 g +0 G +[1 0 0 1 -337.253 -377.285] cm +[1 0 0 1 0 0] Tm +0 0 Td +337.253 377.285 Td +/F130_0 9.963 Tf +(bzfree) 35.8668 Tj +[1 0 0 1 373.118 377.285] cm +0 g +0 G +[1 0 0 1 -373.118 -377.285] cm +[1 0 0 1 0 0] Tm +0 0 Td +373.118 377.285 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-403 TJm +(and) 14.3866 Tj +[1 0 0 1 397.714 377.285] cm +0 g +0 G +[1 0 0 1 -397.714 -377.285] cm +[1 0 0 1 0 0] Tm +0 0 Td +397.714 377.285 Td +/F130_0 9.963 Tf +(opaque) 35.8668 Tj +[1 0 0 1 433.579 377.285] cm +0 g +0 G +[1 0 0 1 -433.579 -377.285] cm +[1 0 0 1 0 0] Tm +0 0 Td +433.579 377.285 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +-1353 TJm +(The) 15.4925 Tj +-372 TJm +(v) 4.9815 Tj +25 TJm +(alue) 16.5984 Tj +[1 0 0 1 493.782 377.285] cm +0 g +0 G +[1 0 0 1 -493.782 -377.285] cm +[1 0 0 1 0 0] Tm +0 0 Td +493.782 377.285 Td +/F130_0 9.963 Tf +(opaque) 35.8668 Tj +[1 0 0 1 529.648 377.285] cm +0 g +0 G +[1 0 0 1 -529.648 -377.285] cm +[1 0 0 1 0 0] Tm +0 0 Td +533.355 377.285 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +72 365.33 Td +(passed) 26.5614 Tj +-306 TJm +(to) 7.75121 Tj +-306 TJm +(as) 8.29918 Tj +-306 TJm +(the) 12.1748 Tj +-306 TJm +(\002) 5.53943 Tj +1 TJm +(rst) 9.963 Tj +-306 TJm +(ar) 7.74125 Tj +18 TJm +(gument) 29.889 Tj +-306 TJm +(to) 7.75121 Tj +-306 TJm +(all) 9.963 Tj +-306 TJm +(calls) 18.2622 Tj +-306 TJm +(to) 7.75121 Tj +[1 0 0 1 253.941 365.33] cm +0 g +0 G +[1 0 0 1 -253.941 -365.33] cm +[1 0 0 1 0 0] Tm +0 0 Td +253.941 365.33 Td +/F130_0 9.963 Tf +(bzalloc) 41.8446 Tj +[1 0 0 1 295.784 365.33] cm +0 g +0 G +[1 0 0 1 -295.784 -365.33] cm +[1 0 0 1 0 0] Tm +0 0 Td +298.832 365.33 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 316.266 365.33] cm +0 g +0 G +[1 0 0 1 -316.266 -365.33] cm +[1 0 0 1 0 0] Tm +0 0 Td +316.266 365.33 Td +/F130_0 9.963 Tf +(bzfree) 35.8668 Tj +[1 0 0 1 352.132 365.33] cm +0 g +0 G +[1 0 0 1 -352.132 -365.33] cm +[1 0 0 1 0 0] Tm +0 0 Td +352.132 365.33 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-320 TJm +(b) 4.9815 Tj +20 TJm +(ut) 7.75121 Tj +-306 TJm +(is) 6.64532 Tj +-306 TJm +(otherwise) 38.7361 Tj +-305 TJm +(ignored) 30.437 Tj +-306 TJm +(by) 9.963 Tj +-306 TJm +(the) 12.1748 Tj +-306 TJm +(library) 26.5614 Tj +65 TJm +(.) 2.49075 Tj +-956 TJm +(The) 15.4925 Tj +72 353.375 Td +(call) 14.3866 Tj +[1 0 0 1 89.431 353.375] cm +0 g +0 G +[1 0 0 1 -89.431 -353.375] cm +[1 0 0 1 0 0] Tm +0 0 Td +89.431 353.375 Td +/F130_0 9.963 Tf +(bzalloc) 41.8446 Tj +-600 TJm +(\() 5.9778 Tj +-600 TJm +(opaque,) 41.8446 Tj +-600 TJm +(n,) 11.9556 Tj +-600 TJm +(m) 5.9778 Tj +-600 TJm +(\)) 5.9778 Tj +[1 0 0 1 232.893 353.375] cm +0 g +0 G +[1 0 0 1 -232.893 -353.375] cm +[1 0 0 1 0 0] Tm +0 0 Td +235.938 353.375 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-306 TJm +(e) 4.42357 Tj +15 TJm +(xpect) 21.5799 Tj +1 TJm +(ed) 9.40507 Tj +-306 TJm +(to) 7.75121 Tj +-306 TJm +(return) 23.7916 Tj +-305 TJm +(a) 4.42357 Tj +-306 TJm +(pointer) 28.2252 Tj +[1 0 0 1 360.3 353.375] cm +0 g +0 G +[1 0 0 1 -360.3 -353.375] cm +[1 0 0 1 0 0] Tm +0 0 Td +360.3 353.375 Td +/F130_0 9.963 Tf +(p) 5.9778 Tj +[1 0 0 1 366.277 353.375] cm +0 g +0 G +[1 0 0 1 -366.277 -353.375] cm +[1 0 0 1 0 0] Tm +0 0 Td +369.322 353.375 Td +/F128_0 9.963 Tf +(to) 7.75121 Tj +[1 0 0 1 380.118 353.375] cm +0 g +0 G +[1 0 0 1 -380.118 -353.375] cm +[1 0 0 1 0 0] Tm +0 0 Td +380.118 353.375 Td +/F130_0 9.963 Tf +(n) 5.9778 Tj +-600 TJm +(*) 5.9778 Tj +-600 TJm +(m) 5.9778 Tj +[1 0 0 1 410.006 353.375] cm +0 g +0 G +[1 0 0 1 -410.006 -353.375] cm +[1 0 0 1 0 0] Tm +0 0 Td +413.051 353.375 Td +/F128_0 9.963 Tf +(bytes) 21.0319 Tj +-306 TJm +(of) 8.29918 Tj +-305 TJm +(memory) 33.2067 Tj +65 TJm +(,) 2.49075 Tj +-320 TJm +(and) 14.3866 Tj +[1 0 0 1 504.135 353.375] cm +0 g +0 G +[1 0 0 1 -504.135 -353.375] cm +[1 0 0 1 0 0] Tm +0 0 Td +504.135 353.375 Td +/F130_0 9.963 Tf +(bzfree) 35.8668 Tj +72 341.42 Td +(\() 5.9778 Tj +-600 TJm +(opaque,) 41.8446 Tj +-600 TJm +(p) 5.9778 Tj +-600 TJm +(\)) 5.9778 Tj +[1 0 0 1 149.709 341.42] cm +0 g +0 G +[1 0 0 1 -149.709 -341.42] cm +[1 0 0 1 0 0] Tm +0 0 Td +152.199 341.42 Td +/F128_0 9.963 Tf +(should) 26.5713 Tj +-250 TJm +(free) 15.4825 Tj +-250 TJm +(that) 14.9445 Tj +-250 TJm +(memory) 33.2067 Tj +65 TJm +(.) 2.49075 Tj +[1 0 0 1 72 339.263] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -329.3] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 319.502 Td +/F128_0 9.963 Tf +(If) 6.63536 Tj +-280 TJm +(you) 14.9445 Tj +-280 TJm +(don') 18.2622 Tj +18 TJm +(t) 2.76971 Tj +-279 TJm +(w) 7.19329 Tj +10 TJm +(ant) 12.1748 Tj +-280 TJm +(to) 7.75121 Tj +-280 TJm +(use) 13.2807 Tj +-280 TJm +(a) 4.42357 Tj +-279 TJm +(custom) 28.7831 Tj +-280 TJm +(memory) 33.2067 Tj +-280 TJm +(allocator) 34.8605 Tj +40 TJm +(,) 2.49075 Tj +-287 TJm +(set) 11.0689 Tj +[1 0 0 1 299.9 319.502] cm +0 g +0 G +[1 0 0 1 -299.9 -319.502] cm +[1 0 0 1 0 0] Tm +0 0 Td +299.9 319.502 Td +/F130_0 9.963 Tf +(bzalloc) 41.8446 Tj +[1 0 0 1 341.743 319.502] cm +0 g +0 G +[1 0 0 1 -341.743 -319.502] cm +[1 0 0 1 0 0] Tm +0 0 Td +341.743 319.502 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 347.096 319.502] cm +0 g +0 G +[1 0 0 1 -347.096 -319.502] cm +[1 0 0 1 0 0] Tm +0 0 Td +347.096 319.502 Td +/F130_0 9.963 Tf +(bzfree) 35.8668 Tj +[1 0 0 1 382.961 319.502] cm +0 g +0 G +[1 0 0 1 -382.961 -319.502] cm +[1 0 0 1 0 0] Tm +0 0 Td +385.749 319.502 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 402.923 319.502] cm +0 g +0 G +[1 0 0 1 -402.923 -319.502] cm +[1 0 0 1 0 0] Tm +0 0 Td +402.923 319.502 Td +/F130_0 9.963 Tf +(opaque) 35.8668 Tj +[1 0 0 1 438.788 319.502] cm +0 g +0 G +[1 0 0 1 -438.788 -319.502] cm +[1 0 0 1 0 0] Tm +0 0 Td +441.576 319.502 Td +/F128_0 9.963 Tf +(to) 7.75121 Tj +[1 0 0 1 452.115 319.502] cm +0 g +0 G +[1 0 0 1 -452.115 -319.502] cm +[1 0 0 1 0 0] Tm +0 0 Td +452.115 319.502 Td +/F130_0 9.963 Tf +(NULL) 23.9112 Tj +[1 0 0 1 476.025 319.502] cm +0 g +0 G +[1 0 0 1 -476.025 -319.502] cm +[1 0 0 1 0 0] Tm +0 0 Td +476.025 319.502 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-280 TJm +(and) 14.3866 Tj +-280 TJm +(the) 12.1748 Tj +-279 TJm +(library) 26.5614 Tj +72 307.547 Td +(will) 15.5024 Tj +-250 TJm +(then) 17.1563 Tj +-250 TJm +(use) 13.2807 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(standard) 33.7546 Tj +[1 0 0 1 176.318 307.547] cm +0 g +0 G +[1 0 0 1 -176.318 -307.547] cm +[1 0 0 1 0 0] Tm +0 0 Td +176.318 307.547 Td +/F130_0 9.963 Tf +(malloc) 35.8668 Tj +[1 0 0 1 212.183 307.547] cm +0 g +0 G +[1 0 0 1 -212.183 -307.547] cm +[1 0 0 1 0 0] Tm +0 0 Td +214.674 307.547 Td +/F128_0 9.963 Tf +(/) 2.76971 Tj +[1 0 0 1 219.934 307.547] cm +0 g +0 G +[1 0 0 1 -219.934 -307.547] cm +[1 0 0 1 0 0] Tm +0 0 Td +219.934 307.547 Td +/F130_0 9.963 Tf +(free) 23.9112 Tj +[1 0 0 1 243.844 307.547] cm +0 g +0 G +[1 0 0 1 -243.844 -307.547] cm +[1 0 0 1 0 0] Tm +0 0 Td +246.335 307.547 Td +/F128_0 9.963 Tf +(routines.) 34.5915 Tj +[1 0 0 1 72 307.338] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -297.375] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 285.629 Td +/F128_0 9.963 Tf +(Before) 27.1093 Tj +-362 TJm +(calling) 27.1193 Tj +[1 0 0 1 133.438 285.629] cm +0 g +0 G +[1 0 0 1 -133.438 -285.629] cm +[1 0 0 1 0 0] Tm +0 0 Td +133.438 285.629 Td +/F130_0 9.963 Tf +(BZ2_bzCompressInit) 107.6 Tj +[1 0 0 1 241.035 285.629] cm +0 g +0 G +[1 0 0 1 -241.035 -285.629] cm +[1 0 0 1 0 0] Tm +0 0 Td +241.035 285.629 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-390 TJm +(\002elds) 21.5898 Tj +[1 0 0 1 272.606 285.629] cm +0 g +0 G +[1 0 0 1 -272.606 -285.629] cm +[1 0 0 1 0 0] Tm +0 0 Td +272.606 285.629 Td +/F130_0 9.963 Tf +(bzalloc) 41.8446 Tj +[1 0 0 1 314.449 285.629] cm +0 g +0 G +[1 0 0 1 -314.449 -285.629] cm +[1 0 0 1 0 0] Tm +0 0 Td +314.449 285.629 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 320.825 285.629] cm +0 g +0 G +[1 0 0 1 -320.825 -285.629] cm +[1 0 0 1 0 0] Tm +0 0 Td +320.825 285.629 Td +/F130_0 9.963 Tf +(bzfree) 35.8668 Tj +[1 0 0 1 356.69 285.629] cm +0 g +0 G +[1 0 0 1 -356.69 -285.629] cm +[1 0 0 1 0 0] Tm +0 0 Td +360.296 285.629 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 378.288 285.629] cm +0 g +0 G +[1 0 0 1 -378.288 -285.629] cm +[1 0 0 1 0 0] Tm +0 0 Td +378.288 285.629 Td +/F130_0 9.963 Tf +(opaque) 35.8668 Tj +[1 0 0 1 414.154 285.629] cm +0 g +0 G +[1 0 0 1 -414.154 -285.629] cm +[1 0 0 1 0 0] Tm +0 0 Td +417.76 285.629 Td +/F128_0 9.963 Tf +(should) 26.5713 Tj +-362 TJm +(be) 9.40507 Tj +-362 TJm +(\002lled) 20.4839 Tj +-362 TJm +(appropriat) 40.9479 Tj +1 TJm +(ely) 12.1748 Tj +65 TJm +(,) 2.49075 Tj +72 273.674 Td +(as) 8.29918 Tj +-322 TJm +(just) 14.3965 Tj +-323 TJm +(described.) 40.669 Tj +-1055 TJm +(U) 7.19329 Tj +1 TJm +(pon) 14.9445 Tj +-323 TJm +(return,) 26.2824 Tj +-340 TJm +(the) 12.1748 Tj +-323 TJm +(internal) 30.437 Tj +-322 TJm +(state) 18.2622 Tj +-322 TJm +(will) 15.5024 Tj +-323 TJm +(ha) 9.40507 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-322 TJm +(been) 18.8101 Tj +-323 TJm +(allocated) 35.9664 Tj +-322 TJm +(and) 14.3866 Tj +-322 TJm +(initialised,) 41.7948 Tj +-341 TJm +(and) 14.3866 Tj +[1 0 0 1 459.801 273.674] cm +0 g +0 G +[1 0 0 1 -459.801 -273.674] cm +[1 0 0 1 0 0] Tm +0 0 Td +459.801 273.674 Td +/F130_0 9.963 Tf +(total_in_lo32) 77.7114 Tj +[1 0 0 1 537.509 273.674] cm +0 g +0 G +[1 0 0 1 -537.509 -273.674] cm +[1 0 0 1 0 0] Tm +0 0 Td +537.509 273.674 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 72 261.719] cm +0 g +0 G +[1 0 0 1 -72 -261.719] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 261.719 Td +/F130_0 9.963 Tf +(total_in_hi32) 77.7114 Tj +[1 0 0 1 149.709 261.719] cm +0 g +0 G +[1 0 0 1 -149.709 -261.719] cm +[1 0 0 1 0 0] Tm +0 0 Td +149.709 261.719 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 155.006 261.719] cm +0 g +0 G +[1 0 0 1 -155.006 -261.719] cm +[1 0 0 1 0 0] Tm +0 0 Td +155.006 261.719 Td +/F130_0 9.963 Tf +(total_out_lo32) 83.6892 Tj +[1 0 0 1 238.692 261.719] cm +0 g +0 G +[1 0 0 1 -238.692 -261.719] cm +[1 0 0 1 0 0] Tm +0 0 Td +241.435 261.719 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 258.564 261.719] cm +0 g +0 G +[1 0 0 1 -258.564 -261.719] cm +[1 0 0 1 0 0] Tm +0 0 Td +258.564 261.719 Td +/F130_0 9.963 Tf +(total_out_hi32) 83.6892 Tj +[1 0 0 1 342.25 261.719] cm +0 g +0 G +[1 0 0 1 -342.25 -261.719] cm +[1 0 0 1 0 0] Tm +0 0 Td +344.994 261.719 Td +/F128_0 9.963 Tf +(will) 15.5024 Tj +-275 TJm +(ha) 9.40507 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-276 TJm +(b) 4.9815 Tj +1 TJm +(een) 13.8286 Tj +-276 TJm +(set) 11.0689 Tj +-275 TJm +(to) 7.75121 Tj +-275 TJm +(zero.) 19.6371 Tj +-772 TJm +(These) 23.7916 Tj +-276 TJm +(four) 16.5984 Tj +-275 TJm +(\002elds) 21.5898 Tj +-275 TJm +(are) 12.1648 Tj +72 249.763 Td +(used) 18.2622 Tj +-339 TJm +(by) 9.963 Tj +-340 TJm +(the) 12.1748 Tj +-339 TJm +(library) 26.5614 Tj +-340 TJm +(to) 7.75121 Tj +-339 TJm +(inform) 27.1193 Tj +-340 TJm +(the) 12.1748 Tj +-339 TJm +(caller) 22.1278 Tj +-340 TJm +(of) 8.29918 Tj +-339 TJm +(the) 12.1748 Tj +-340 TJm +(total) 17.7142 Tj +-339 TJm +(amount) 29.889 Tj +-340 TJm +(of) 8.29918 Tj +-339 TJm +(data) 16.5984 Tj +-339 TJm +(passed) 26.5614 Tj +-340 TJm +(into) 15.5024 Tj +-339 TJm +(and) 14.3866 Tj +-340 TJm +(out) 12.7327 Tj +-339 TJm +(of) 8.29918 Tj +-340 TJm +(the) 12.1748 Tj +-339 TJm +(library) 26.5614 Tj +65 TJm +(,) 2.49075 Tj +-362 TJm +(respecti) 30.9849 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(ely) 12.1748 Tj +65 TJm +(.) 2.49075 Tj +72 237.808 Td +(Y) 7.19329 Tj +110 TJm +(ou) 9.963 Tj +-376 TJm +(should) 26.5713 Tj +-377 TJm +(not) 12.7327 Tj +-376 TJm +(try) 11.0689 Tj +-376 TJm +(to) 7.75121 Tj +-377 TJm +(c) 4.42357 Tj +1 TJm +(hange) 23.7916 Tj +-377 TJm +(them.) 22.4168 Tj +-1378 TJm +(As) 11.0689 Tj +-376 TJm +(of) 8.29918 Tj +-377 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +1 TJm +(rsion) 19.926 Tj +-377 TJm +(1.0,) 14.9445 Tj +-408 TJm +(64-bit) 23.8016 Tj +-376 TJm +(counts) 26.0134 Tj +-376 TJm +(are) 12.1648 Tj +-376 TJm +(maintained,) 46.7663 Tj +-408 TJm +(e) 4.42357 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(en) 9.40507 Tj +-377 TJm +(on) 9.963 Tj +-376 TJm +(32-bit) 23.8016 Tj +-376 TJm +(platforms,) 40.6789 Tj +72 225.853 Td +(using) 21.5898 Tj +-371 TJm +(the) 12.1748 Tj +[1 0 0 1 113.148 225.853] cm +0 g +0 G +[1 0 0 1 -113.148 -225.853] cm +[1 0 0 1 0 0] Tm +0 0 Td +113.148 225.853 Td +/F130_0 9.963 Tf +(_hi32) 29.889 Tj +[1 0 0 1 143.036 225.853] cm +0 g +0 G +[1 0 0 1 -143.036 -225.853] cm +[1 0 0 1 0 0] Tm +0 0 Td +146.729 225.853 Td +/F128_0 9.963 Tf +(\002elds) 21.5898 Tj +-371 TJm +(to) 7.75121 Tj +-370 TJm +(store) 19.3681 Tj +-371 TJm +(the) 12.1748 Tj +-370 TJm +(upper) 22.6858 Tj +-371 TJm +(32) 9.963 Tj +-370 TJm +(bits) 14.3965 Tj +-371 TJm +(of) 8.29918 Tj +-371 TJm +(the) 12.1748 Tj +-370 TJm +(count.) 24.6285 Tj +-1344 TJm +(So,) 13.0117 Tj +-401 TJm +(for) 11.6169 Tj +-370 TJm +(e) 4.42357 Tj +15 TJm +(xample,) 31.8218 Tj +-401 TJm +(the) 12.1748 Tj +-370 TJm +(total) 17.7142 Tj +-371 TJm +(amount) 29.889 Tj +-371 TJm +(of) 8.29918 Tj +-370 TJm +(data) 16.5984 Tj +-371 TJm +(in) 7.75121 Tj +-370 TJm +(is) 6.64532 Tj +[1 0 0 1 72 213.898] cm +0 g +0 G +[1 0 0 1 -72 -213.898] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 213.898 Td +/F130_0 9.963 Tf +(\(total_in_hi32) 83.6892 Tj +-600 TJm +(<<) 11.9556 Tj +-600 TJm +(32\)) 17.9334 Tj +-600 TJm +(+) 5.9778 Tj +-600 TJm +(to) 11.9556 Tj +1 TJm +(tal_in_lo32) 65.7558 Tj +[1 0 0 1 293.171 213.898] cm +0 g +0 G +[1 0 0 1 -293.171 -213.898] cm +[1 0 0 1 0 0] Tm +0 0 Td +293.171 213.898 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 72 212.732] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -202.77] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 191.98 Td +/F128_0 9.963 Tf +(P) 5.53943 Tj +15 TJm +(arameter) 34.8506 Tj +[1 0 0 1 115.367 191.98] cm +0 g +0 G +[1 0 0 1 -115.367 -191.98] cm +[1 0 0 1 0 0] Tm +0 0 Td +115.367 191.98 Td +/F130_0 9.963 Tf +(blockSize100k) 77.7114 Tj +[1 0 0 1 193.076 191.98] cm +0 g +0 G +[1 0 0 1 -193.076 -191.98] cm +[1 0 0 1 0 0] Tm +0 0 Td +196.205 191.98 Td +/F128_0 9.963 Tf +(speci\002es) 34.3126 Tj +-314 TJm +(the) 12.1748 Tj +-314 TJm +(block) 22.1378 Tj +-314 TJm +(size) 15.4925 Tj +-314 TJm +(to) 7.75121 Tj +-314 TJm +(be) 9.40507 Tj +-314 TJm +(used) 18.2622 Tj +-314 TJm +(for) 11.6169 Tj +-314 TJm +(comp) 22.1378 Tj +1 TJm +(ression.) 30.7159 Tj +-1005 TJm +(It) 6.08739 Tj +-314 TJm +(sh) 8.85711 Tj +1 TJm +(ould) 17.7142 Tj +-314 TJm +(be) 9.40507 Tj +-314 TJm +(a) 4.42357 Tj +-314 TJm +(v) 4.9815 Tj +25 TJm +(alue) 16.5984 Tj +-314 TJm +(between) 33.1967 Tj +-314 TJm +(1) 4.9815 Tj +72 180.025 Td +(and) 14.3866 Tj +-289 TJm +(9) 4.9815 Tj +-289 TJm +(inclusi) 26.5713 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(e,) 6.91432 Tj +-299 TJm +(and) 14.3866 Tj +-289 TJm +(the) 12.1748 Tj +-289 TJm +(actua) 21.0219 Tj +1 TJm +(l) 2.76971 Tj +-290 TJm +(b) 4.9815 Tj +1 TJm +(lock) 17.1563 Tj +-289 TJm +(size) 15.4925 Tj +-289 TJm +(used) 18.2622 Tj +-289 TJm +(is) 6.64532 Tj +-289 TJm +(100000) 29.889 Tj +-289 TJm +(x) 4.9815 Tj +-289 TJm +(this) 14.3965 Tj +-289 TJm +(\002gure.) 25.7344 Tj +-854 TJm +(9) 4.9815 Tj +-289 TJm +(gi) 7.75121 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(es) 8.29918 Tj +-289 TJm +(the) 12.1748 Tj +-289 TJm +(best) 16.0504 Tj +-289 TJm +(compression) 50.363 Tj +-289 TJm +(b) 4.9815 Tj +20 TJm +(ut) 7.75121 Tj +-289 TJm +(tak) 12.1748 Tj +10 TJm +(es) 8.29918 Tj +-289 TJm +(most) 19.378 Tj +72 168.07 Td +(memory) 33.2067 Tj +65 TJm +(.) 2.49075 Tj +[1 0 0 1 72 165.913] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -155.95] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 146.152 Td +/F128_0 9.963 Tf +(P) 5.53943 Tj +15 TJm +(arameter) 34.8506 Tj +[1 0 0 1 115.095 146.152] cm +0 g +0 G +[1 0 0 1 -115.095 -146.152] cm +[1 0 0 1 0 0] Tm +0 0 Td +115.095 146.152 Td +/F130_0 9.963 Tf +(verbosity) 53.8002 Tj +[1 0 0 1 168.894 146.152] cm +0 g +0 G +[1 0 0 1 -168.894 -146.152] cm +[1 0 0 1 0 0] Tm +0 0 Td +171.75 146.152 Td +/F128_0 9.963 Tf +(should) 26.5713 Tj +-287 TJm +(be) 9.40507 Tj +-286 TJm +(set) 11.0689 Tj +-287 TJm +(to) 7.75121 Tj +-287 TJm +(a) 4.42357 Tj +-286 TJm +(number) 30.437 Tj +-287 TJm +(between) 33.1967 Tj +-287 TJm +(0) 4.9815 Tj +-286 TJm +(and) 14.3866 Tj +-287 TJm +(4) 4.9815 Tj +-287 TJm +(inclusi) 26.5713 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(e.) 6.91432 Tj +-840 TJm +(0) 4.9815 Tj +-287 TJm +(is) 6.64532 Tj +-286 TJm +(silent,) 24.0806 Tj +-296 TJm +(and) 14.3866 Tj +-287 TJm +(greater) 27.6573 Tj +-286 TJm +(numbers) 34.3126 Tj +-287 TJm +(gi) 7.75121 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +72 134.197 Td +(increasingly) 48.6991 Tj +-342 TJm +(v) 4.9815 Tj +15 TJm +(erbose) 26.0034 Tj +-342 TJm +(monitoring/deb) 61.4418 Tj +20 TJm +(ugging) 27.6772 Tj +-342 TJm +(output.) 27.9562 Tj +-1173 TJm +(If) 6.63536 Tj +-342 TJm +(the) 12.1748 Tj +-342 TJm +(library) 26.5614 Tj +-342 TJm +(has) 13.2807 Tj +-342 TJm +(been) 18.8101 Tj +-342 TJm +(compiled) 37.0823 Tj +-342 TJm +(with) 17.7142 Tj +[1 0 0 1 446.429 134.197] cm +0 g +0 G +[1 0 0 1 -446.429 -134.197] cm +[1 0 0 1 0 0] Tm +0 0 Td +446.429 134.197 Td +/F130_0 9.963 Tf +(-DBZ_NO_STDIO) 77.7114 Tj +[1 0 0 1 524.138 134.197] cm +0 g +0 G +[1 0 0 1 -524.138 -134.197] cm +[1 0 0 1 0 0] Tm +0 0 Td +524.138 134.197 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-342 TJm +(no) 9.963 Tj +72 122.242 Td +(such) 18.2622 Tj +-250 TJm +(output) 25.4654 Tj +-250 TJm +(will) 15.5024 Tj +-250 TJm +(appear) 26.5514 Tj +-250 TJm +(for) 11.6169 Tj +-250 TJm +(an) 9.40507 Tj +15 TJm +(y) 4.9815 Tj +-249 TJm +(v) 4.9815 Tj +15 TJm +(erbosity) 32.1008 Tj +-250 TJm +(setting.) 29.0621 Tj +[1 0 0 1 72 120.085] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -110.122] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 100.324 Td +/F128_0 9.963 Tf +(P) 5.53943 Tj +15 TJm +(arameter) 34.8506 Tj +[1 0 0 1 116.619 100.324] cm +0 g +0 G +[1 0 0 1 -116.619 -100.324] cm +[1 0 0 1 0 0] Tm +0 0 Td +116.619 100.324 Td +/F130_0 9.963 Tf +(workFactor) 59.778 Tj +[1 0 0 1 176.395 100.324] cm +0 g +0 G +[1 0 0 1 -176.395 -100.324] cm +[1 0 0 1 0 0] Tm +0 0 Td +180.775 100.324 Td +/F128_0 9.963 Tf +(controls) 32.1008 Tj +-439 TJm +(ho) 9.963 Tj +25 TJm +(w) 7.19329 Tj +-440 TJm +(the) 12.1748 Tj +-440 TJm +(compr) 25.4555 Tj +1 TJm +(ession) 24.9075 Tj +-440 TJm +(phase) 22.6858 Tj +-440 TJm +(be) 9.40507 Tj +1 TJm +(ha) 9.40507 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(es) 8.29918 Tj +-440 TJm +(when) 21.5799 Tj +-440 TJm +(presen) 26.0034 Tj +1 TJm +(ted) 12.1748 Tj +-440 TJm +(with) 17.7142 Tj +-440 TJm +(w) 7.19329 Tj +10 TJm +(orst) 14.9445 Tj +-439 TJm +(case,) 19.6371 Tj +-487 TJm +(highly) 25.4654 Tj +72 88.369 Td +(repetiti) 28.2252 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(e,) 6.91432 Tj +-432 TJm +(input) 20.4839 Tj +-396 TJm +(data.) 19.0891 Tj +-1497 TJm +(If) 6.63536 Tj +-396 TJm +(compression) 50.363 Tj +-396 TJm +(runs) 17.1563 Tj +-396 TJm +(into) 15.5024 Tj +-396 TJm +(dif) 11.0689 Tj +25 TJm +(\002culties) 31.5528 Tj +-396 TJm +(caused) 27.1093 Tj +-396 TJm +(by) 9.963 Tj +-396 TJm +(repetiti) 28.2252 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-396 TJm +(data,) 19.0891 Tj +-432 TJm +(the) 12.1748 Tj +-396 TJm +(library) 26.5614 Tj +-396 TJm +(switches) 34.3126 Tj +-396 TJm +(from) 19.3681 Tj +[1 0 0 1 72 50.852] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.754] cm +0 g +0 G +0 g +0 G +[1 0 0 1 40.572 -6.754] cm +0 g +0 G +[1 0 0 1 -493.841 -50.852] cm +[1 0 0 1 0 0] Tm +0 0 Td +534.414 50.852 Td +/F128_0 9.963 Tf +(12) 9.963 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 16 16 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 -8.911] cm +0 g +0 G +[1 0 0 1 0 8.911] cm +0 g +0 G +0 g +0 G +[1 0 0 1 84.08 -6.755] cm +0 g +0 G +[1 0 0 1 -350.151 -749.245] cm +[1 0 0 1 0 0] Tm +0 0 Td +434.231 749.245 Td +/F128_0 9.963 Tf +(Programming) 54.7965 Tj +-250 TJm +(with) 17.7142 Tj +-250 TJm +(libbzip2) 32.6587 Tj +[1 0 0 1 266.071 747.089] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -5.037] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -540 -741.554] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 710.037 Td +/F128_0 9.963 Tf +(the) 12.1748 Tj +-255 TJm +(stan) 16.0504 Tj +1 TJm +(dard) 17.7043 Tj +-255 TJm +(sorting) 27.6772 Tj +-255 TJm +(alg) 12.1748 Tj +1 TJm +(orithm) 26.5713 Tj +-255 TJm +(to) 7.75121 Tj +-255 TJm +(a) 4.42357 Tj +-254 TJm +(f) 3.31768 Tj +10 TJm +(allback) 28.7731 Tj +-255 TJm +(algorithm) 38.7461 Tj +1 TJm +(.) 2.49075 Tj +-648 TJm +(The) 15.4925 Tj +-255 TJm +(f) 3.31768 Tj +10 TJm +(allback) 28.7731 Tj +-254 TJm +(is) 6.64532 Tj +-255 TJm +(slo) 11.6268 Tj +25 TJm +(wer) 14.9345 Tj +-254 TJm +(than) 17.1563 Tj +-255 TJm +(the) 12.1748 Tj +-255 TJm +(st) 6.64532 Tj +1 TJm +(andard) 27.1093 Tj +-255 TJm +(algorithm) 38.7461 Tj +-254 TJm +(by) 9.963 Tj +-255 TJm +(perhaps) 30.9849 Tj +72 698.082 Td +(a) 4.42357 Tj +-250 TJm +(f) 3.31768 Tj +10 TJm +(actor) 19.916 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(three,) 22.4068 Tj +-250 TJm +(b) 4.9815 Tj +20 TJm +(ut) 7.75121 Tj +-250 TJm +(al) 7.19329 Tj +10 TJm +(w) 7.19329 Tj +10 TJm +(ays) 13.2807 Tj +-250 TJm +(b) 4.9815 Tj +1 TJm +(eha) 13.8286 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(es) 8.29918 Tj +-250 TJm +(reasonably) 43.1597 Tj +65 TJm +(,) 2.49075 Tj +-250 TJm +(no) 9.963 Tj +-250 TJm +(matter) 25.4555 Tj +-250 TJm +(ho) 9.963 Tj +25 TJm +(w) 7.19329 Tj +-250 TJm +(bad) 14.3866 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(input.) 22.9747 Tj +[1 0 0 1 72 695.925] cm +0 g +0 G +[1 0 0 1 0 -9.961] cm +0 g +0 G +[1 0 0 1 -72 -685.964] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 676.165 Td +/F128_0 9.963 Tf +(Lo) 11.0689 Tj +25 TJm +(wer) 14.9345 Tj +-240 TJm +(v) 4.9815 Tj +25 TJm +(alue) 16.5984 Tj +1 TJm +(s) 3.87561 Tj +-240 TJm +(of) 8.29918 Tj +[1 0 0 1 138.421 676.165] cm +0 g +0 G +[1 0 0 1 -138.421 -676.165] cm +[1 0 0 1 0 0] Tm +0 0 Td +138.421 676.165 Td +/F130_0 9.963 Tf +(workFactor) 59.778 Tj +[1 0 0 1 198.197 676.165] cm +0 g +0 G +[1 0 0 1 -198.197 -676.165] cm +[1 0 0 1 0 0] Tm +0 0 Td +200.585 676.165 Td +/F128_0 9.963 Tf +(reduce) 26.5514 Tj +-240 TJm +(the) 12.1748 Tj +-239 TJm +(amount) 29.889 Tj +-240 TJm +(of) 8.29918 Tj +-239 TJm +(ef) 7.74125 Tj +25 TJm +(fort) 14.3866 Tj +-240 TJm +(the) 12.1748 Tj +-240 TJm +(standard) 33.7546 Tj +-239 TJm +(algorithm) 38.7461 Tj +-240 TJm +(will) 15.5024 Tj +-239 TJm +(e) 4.42357 Tj +15 TJm +(xpend) 24.3496 Tj +-240 TJm +(before) 25.4455 Tj +-240 TJm +(re) 7.74125 Tj +1 TJm +(sorting) 27.6772 Tj +-240 TJm +(to) 7.75121 Tj +-240 TJm +(the) 12.1748 Tj +72 664.21 Td +(f) 3.31768 Tj +10 TJm +(allback.) 31.2639 Tj +-618 TJm +(Y) 7.19329 Tj +110 TJm +(ou) 9.963 Tj +-248 TJm +(should) 26.5713 Tj +-247 TJm +(set) 11.0689 Tj +-248 TJm +(this) 14.3965 Tj +-247 TJm +(parameter) 39.8321 Tj +-247 TJm +(carefully;) 38.1782 Tj +-249 TJm +(too) 12.7327 Tj +-247 TJm +(lo) 7.75121 Tj +25 TJm +(w) 7.19329 Tj +65 TJm +(,) 2.49075 Tj +-248 TJm +(and) 14.3866 Tj +-247 TJm +(man) 17.1563 Tj +15 TJm +(y) 4.9815 Tj +-248 TJm +(inputs) 24.3595 Tj +-247 TJm +(will) 15.5024 Tj +-248 TJm +(be) 9.40507 Tj +-247 TJm +(handled) 31.5429 Tj +-248 TJm +(by) 9.963 Tj +-247 TJm +(the) 12.1748 Tj +-248 TJm +(f) 3.31768 Tj +10 TJm +(allback) 28.7731 Tj +-247 TJm +(algorithm) 38.7461 Tj +72 652.255 Td +(and) 14.3866 Tj +-308 TJm +(so) 8.85711 Tj +-308 TJm +(compress) 37.6303 Tj +-308 TJm +(rather) 23.2337 Tj +-308 TJm +(slo) 11.6268 Tj +25 TJm +(wly) 14.9445 Tj +65 TJm +(,) 2.49075 Tj +-323 TJm +(too) 12.7327 Tj +-308 TJm +(high,) 20.205 Tj +-323 TJm +(and) 14.3866 Tj +-308 TJm +(your) 18.2622 Tj +-308 TJm +(a) 4.42357 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(erage-to-w) 43.1498 Tj +10 TJm +(orst) 14.9445 Tj +-308 TJm +(case) 17.1463 Tj +-308 TJm +(compression) 50.363 Tj +-308 TJm +(times) 21.5898 Tj +-308 TJm +(can) 13.8286 Tj +-308 TJm +(become) 30.9849 Tj +-308 TJm +(v) 4.9815 Tj +15 TJm +(ery) 12.7228 Tj +-308 TJm +(lar) 10.511 Tj +18 TJm +(ge.) 11.8958 Tj +72 640.3 Td +(The) 15.4925 Tj +-250 TJm +(def) 12.7228 Tj +10 TJm +(ault) 14.9445 Tj +-250 TJm +(v) 4.9815 Tj +25 TJm +(alue) 16.5984 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(30) 9.963 Tj +-250 TJm +(gi) 7.75121 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(es) 8.29918 Tj +-250 TJm +(re) 7.74125 Tj +1 TJm +(asonable) 34.8605 Tj +-250 TJm +(beha) 18.8101 Tj +20 TJm +(viour) 21.0319 Tj +-250 TJm +(o) 4.9815 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(er) 7.74125 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(wide) 19.3681 Tj +-250 TJm +(range) 22.1278 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(circumstances.) 58.9311 Tj +[1 0 0 1 72 638.143] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -628.181] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 618.383 Td +/F128_0 9.963 Tf +(Allo) 17.7142 Tj +25 TJm +(w) 7.19329 Tj +10 TJm +(able) 16.5984 Tj +-250 TJm +(v) 4.9815 Tj +25 TJm +(alues) 20.474 Tj +-250 TJm +(range) 22.1278 Tj +-250 TJm +(from) 19.3681 Tj +-249 TJm +(0) 4.9815 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(250) 14.9445 Tj +-250 TJm +(inclusi) 26.5713 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(e.) 6.91432 Tj +-620 TJm +(0) 4.9815 Tj +-250 TJm +(is) 6.64532 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(special) 27.6673 Tj +-250 TJm +(case,) 19.6371 Tj +-250 TJm +(equi) 17.1563 Tj +25 TJm +(v) 4.9815 Tj +25 TJm +(alent) 19.3681 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(usi) 11.6268 Tj +1 TJm +(ng) 9.963 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(def) 12.7228 Tj +10 TJm +(ault) 14.9445 Tj +-250 TJm +(v) 4.9815 Tj +25 TJm +(alue) 16.5984 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(30.) 12.4538 Tj +[1 0 0 1 72 616.226] cm +0 g +0 G +[1 0 0 1 0 -9.961] cm +0 g +0 G +[1 0 0 1 -72 -606.265] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 596.466 Td +/F128_0 9.963 Tf +(Note) 19.3681 Tj +-250 TJm +(that) 14.9445 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(compressed) 47.0353 Tj +-250 TJm +(out) 12.7327 Tj +1 TJm +(put) 12.7327 Tj +-250 TJm +(generated) 38.7262 Tj +-250 TJm +(is) 6.64532 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(same) 20.474 Tj +-250 TJm +(re) 7.74125 Tj +15 TJm +(g) 4.9815 Tj +5 TJm +(ardless) 27.6673 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(whether) 32.0908 Tj +-250 TJm +(or) 8.29918 Tj +-250 TJm +(not) 12.7327 Tj +-250 TJm +(the) 12.1748 Tj +-249 TJm +(f) 3.31768 Tj +10 TJm +(allback) 28.7731 Tj +-250 TJm +(algorithm) 38.7461 Tj +-250 TJm +(is) 6.64532 Tj +-250 TJm +(used.) 20.7529 Tj +[1 0 0 1 72 594.309] cm +0 g +0 G +[1 0 0 1 0 -9.961] cm +0 g +0 G +[1 0 0 1 -72 -584.348] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 574.549 Td +/F128_0 9.963 Tf +(Be) 11.0689 Tj +-303 TJm +(a) 4.42357 Tj +15 TJm +(w) 7.19329 Tj +10 TJm +(are) 12.1648 Tj +-303 TJm +(also) 16.0504 Tj +-303 TJm +(that) 14.9445 Tj +-303 TJm +(this) 14.3965 Tj +-303 TJm +(parameter) 39.8321 Tj +-303 TJm +(may) 17.1563 Tj +-303 TJm +(disappear) 38.1782 Tj +-303 TJm +(entirely) 30.437 Tj +-303 TJm +(in) 7.75121 Tj +-303 TJm +(future) 23.7916 Tj +-303 TJm +(v) 4.9815 Tj +15 TJm +(ersions) 28.2252 Tj +-303 TJm +(of) 8.29918 Tj +-303 TJm +(the) 12.1748 Tj +-303 TJm +(library) 26.5614 Tj +65 TJm +(.) 2.49075 Tj +-939 TJm +(In) 8.29918 Tj +-303 TJm +(principle) 35.4185 Tj +-303 TJm +(it) 5.53943 Tj +-303 TJm +(should) 26.5713 Tj +-303 TJm +(be) 9.40507 Tj +72 562.594 Td +(possible) 32.6587 Tj +-270 TJm +(to) 7.75121 Tj +-270 TJm +(de) 9.40507 Tj +25 TJm +(vise) 16.0504 Tj +-270 TJm +(a) 4.42357 Tj +-270 TJm +(good) 19.926 Tj +-270 TJm +(w) 7.19329 Tj +10 TJm +(ay) 9.40507 Tj +-270 TJm +(to) 7.75121 Tj +-270 TJm +(automatically) 54.2386 Tj +-270 TJm +(choose) 27.6673 Tj +-270 TJm +(which) 24.3496 Tj +-270 TJm +(algorithm) 38.7461 Tj +-270 TJm +(to) 7.75121 Tj +-270 TJm +(use.) 15.7714 Tj +-740 TJm +(Such) 19.926 Tj +-270 TJm +(a) 4.42357 Tj +-270 TJm +(mechanism) 45.3815 Tj +-270 TJm +(w) 7.19329 Tj +10 TJm +(ould) 17.7142 Tj +-270 TJm +(render) 25.4455 Tj +-270 TJm +(the) 12.1748 Tj +72 550.639 Td +(parameter) 39.8321 Tj +-250 TJm +(obsolete.) 35.6974 Tj +[1 0 0 1 72 548.482] cm +0 g +0 G +[1 0 0 1 0 -9.961] cm +0 g +0 G +[1 0 0 1 -72 -538.521] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 528.722 Td +/F128_0 9.963 Tf +(Possible) 33.2166 Tj +-250 TJm +(return) 23.7916 Tj +-250 TJm +(v) 4.9815 Tj +25 TJm +(alues:) 23.2437 Tj +[1 0 0 1 72 528.623] cm +0 g +0 G +[1 0 0 1 0 -144.458] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 143.462 re +f +Q +0 g +0 G +[1 0 0 1 0 3.586] cm +0 g +0 G +[1 0 0 1 0 139.876] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -519.258] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 519.258 Td +/F130_0 9.963 Tf +(BZ_CONFIG_ERROR) 89.667 Tj +98.488 507.303 Td +(if) 11.9556 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(library) 41.8446 Tj +-426 TJm +(has) 17.9334 Tj +-426 TJm +(been) 23.9112 Tj +-425 TJm +(mis-compiled) 71.7336 Tj +90 495.348 Td +(BZ_PARAM_ERROR) 83.6892 Tj +98.488 483.392 Td +(if) 11.9556 Tj +-426 TJm +(strm) 23.9112 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(NULL) 23.9112 Tj +98.488 471.437 Td +(or) 11.9556 Tj +-426 TJm +(blockSize) 53.8002 Tj +-426 TJm +(<) 5.9778 Tj +-426 TJm +(1) 5.9778 Tj +-426 TJm +(or) 11.9556 Tj +-426 TJm +(bloc) 23.9112 Tj +1 TJm +(kSize) 29.889 Tj +-426 TJm +(>) 5.9778 Tj +-426 TJm +(9) 5.9778 Tj +98.488 459.482 Td +(or) 11.9556 Tj +-426 TJm +(verbosity) 53.8002 Tj +-426 TJm +(<) 5.9778 Tj +-426 TJm +(0) 5.9778 Tj +-426 TJm +(or) 11.9556 Tj +-426 TJm +(verb) 23.9112 Tj +1 TJm +(osity) 29.889 Tj +-426 TJm +(>) 5.9778 Tj +-426 TJm +(4) 5.9778 Tj +98.488 447.527 Td +(or) 11.9556 Tj +-426 TJm +(workFactor) 59.778 Tj +-426 TJm +(<) 5.9778 Tj +-426 TJm +(0) 5.9778 Tj +-426 TJm +(or) 11.9556 Tj +-426 TJm +(wor) 17.9334 Tj +1 TJm +(kFactor) 41.8446 Tj +-426 TJm +(>) 5.9778 Tj +-426 TJm +(250) 17.9334 Tj +90 435.572 Td +(BZ_MEM_ERROR) 71.7336 Tj +98.488 423.617 Td +(if) 11.9556 Tj +-426 TJm +(not) 17.9334 Tj +-426 TJm +(enough) 35.8668 Tj +-426 TJm +(memory) 35.8668 Tj +-426 TJm +(is) 11.9556 Tj +-425 TJm +(available) 53.8002 Tj +90 411.661 Td +(BZ_OK) 29.889 Tj +98.488 399.706 Td +(otherwise) 53.8002 Tj +[1 0 0 1 72 384.165] cm +0 g +0 G +[1 0 0 1 468 3.586] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.548] cm +0 g +0 G +[1 0 0 1 -72 -374.203] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 362.248 Td +/F128_0 9.963 Tf +(Allo) 17.7142 Tj +25 TJm +(w) 7.19329 Tj +10 TJm +(able) 16.5984 Tj +-250 TJm +(ne) 9.40507 Tj +15 TJm +(xt) 7.75121 Tj +-250 TJm +(actions:) 30.9949 Tj +[1 0 0 1 72 362.148] cm +0 g +0 G +[1 0 0 1 0 -48.817] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 47.821 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 44.234] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -352.783] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 352.783 Td +/F130_0 9.963 Tf +(BZ2_bzCompress) 83.6892 Tj +98.488 340.828 Td +(if) 11.9556 Tj +-426 TJm +(BZ_OK) 29.889 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(returned) 47.8224 Tj +98.488 328.873 Td +(no) 11.9556 Tj +-426 TJm +(specific) 47.8224 Tj +-426 TJm +(action) 35.8668 Tj +-426 TJm +(needed) 35.8668 Tj +-425 TJm +(in) 11.9556 Tj +-426 TJm +(case) 23.9112 Tj +-426 TJm +(of) 11.9556 Tj +-426 TJm +(error) 29.889 Tj +[1 0 0 1 72 313.331] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -3.587] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.961] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -303.37] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 282.711 Td +/F121_0 17.215 Tf +(3.3.2.) 43.0719 Tj +[1 0 0 1 119.858 282.711] cm +0 g +0 G +[1 0 0 1 -119.858 -282.711] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.858 282.711 Td +/F387_0 17.215 Tf +(BZ2_bzCompress) 144.606 Tj +[1 0 0 1 264.468 282.711] cm +0 g +0 G +[1 0 0 1 -192.468 -2.333] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -24.906] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 23.91 re +f +Q +0 g +0 G +[1 0 0 1 0 3.586] cm +0 g +0 G +[1 0 0 1 0 20.324] cm +0 g +0 G +[1 0 0 1 18 -8.368] cm +0 g +0 G +[1 0 0 1 -90 -271.014] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 271.014 Td +/F130_0 9.963 Tf +(int) 17.9334 Tj +-426 TJm +(BZ2_bzCompress) 83.6892 Tj +-426 TJm +(\() 5.9778 Tj +-426 TJm +(bz_s) 23.9112 Tj +1 TJm +(tream) 29.889 Tj +-426 TJm +(*strm,) 35.8668 Tj +-426 TJm +(int) 17.9334 Tj +-426 TJm +(action) 35.8668 Tj +-426 TJm +(\);) 11.9556 Tj +[1 0 0 1 72 255.472] cm +0 g +0 G +[1 0 0 1 468 3.586] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.548] cm +0 g +0 G +[1 0 0 1 -72 -245.51] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 233.555 Td +/F128_0 9.963 Tf +(Pro) 13.8386 Tj +15 TJm +(vides) 21.0319 Tj +-222 TJm +(mor) 16.0504 Tj +1 TJm +(e) 4.42357 Tj +-222 TJm +(input) 20.4839 Tj +-222 TJm +(and/or) 25.4555 Tj +-221 TJm +(output) 25.4654 Tj +-222 TJm +(b) 4.9815 Tj +20 TJm +(uf) 8.29918 Tj +25 TJm +(fer) 11.0589 Tj +-222 TJm +(space) 22.1278 Tj +-221 TJm +(for) 11.6169 Tj +-222 TJm +(the) 12.1748 Tj +-222 TJm +(li) 5.53943 Tj +1 TJm +(brary) 21.0219 Tj +65 TJm +(.) 2.49075 Tj +-602 TJm +(T) 6.08739 Tj +1 TJm +(he) 9.40507 Tj +-222 TJm +(caller) 22.1278 Tj +-222 TJm +(maintains) 38.7461 Tj +-221 TJm +(input) 20.4839 Tj +-222 TJm +(and) 14.3866 Tj +-222 TJm +(ou) 9.963 Tj +1 TJm +(tput) 15.5024 Tj +-222 TJm +(b) 4.9815 Tj +20 TJm +(uf) 8.29918 Tj +25 TJm +(fers,) 17.4253 Tj +-227 TJm +(and) 14.3866 Tj +-222 TJm +(calls) 18.2622 Tj +[1 0 0 1 72 221.6] cm +0 g +0 G +[1 0 0 1 -72 -221.6] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 221.6 Td +/F130_0 9.963 Tf +(BZ2_bzCompress) 83.6892 Tj +[1 0 0 1 155.686 221.6] cm +0 g +0 G +[1 0 0 1 -155.686 -221.6] cm +[1 0 0 1 0 0] Tm +0 0 Td +158.177 221.6 Td +/F128_0 9.963 Tf +(to) 7.75121 Tj +-250 TJm +(transfer) 30.427 Tj +-250 TJm +(data) 16.5984 Tj +-250 TJm +(between) 33.1967 Tj +-250 TJm +(the) 12.1748 Tj +1 TJm +(m.) 10.242 Tj +[1 0 0 1 72 220.036] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -210.074] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 199.683 Td +/F128_0 9.963 Tf +(Before) 27.1093 Tj +-212 TJm +(each) 18.2522 Tj +-213 TJm +(call) 14.3866 Tj +-212 TJm +(to) 7.75121 Tj +[1 0 0 1 147.961 199.683] cm +0 g +0 G +[1 0 0 1 -147.961 -199.683] cm +[1 0 0 1 0 0] Tm +0 0 Td +147.961 199.683 Td +/F130_0 9.963 Tf +(BZ2_bzCompress) 83.6892 Tj +[1 0 0 1 231.647 199.683] cm +0 g +0 G +[1 0 0 1 -231.647 -199.683] cm +[1 0 0 1 0 0] Tm +0 0 Td +231.647 199.683 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 236.329 199.683] cm +0 g +0 G +[1 0 0 1 -236.329 -199.683] cm +[1 0 0 1 0 0] Tm +0 0 Td +236.329 199.683 Td +/F130_0 9.963 Tf +(next_in) 41.8446 Tj +[1 0 0 1 278.172 199.683] cm +0 g +0 G +[1 0 0 1 -278.172 -199.683] cm +[1 0 0 1 0 0] Tm +0 0 Td +280.289 199.683 Td +/F128_0 9.963 Tf +(should) 26.5713 Tj +-212 TJm +(point) 20.4839 Tj +-213 TJm +(at) 7.19329 Tj +-212 TJm +(the) 12.1748 Tj +-212 TJm +(data) 16.5984 Tj +-213 TJm +(to) 7.75121 Tj +-212 TJm +(be) 9.40507 Tj +-212 TJm +(compressed,) 49.5261 Tj +-220 TJm +(and) 14.3866 Tj +[1 0 0 1 463.493 199.683] cm +0 g +0 G +[1 0 0 1 -463.493 -199.683] cm +[1 0 0 1 0 0] Tm +0 0 Td +463.493 199.683 Td +/F130_0 9.963 Tf +(avail_in) 47.8224 Tj +[1 0 0 1 511.314 199.683] cm +0 g +0 G +[1 0 0 1 -511.314 -199.683] cm +[1 0 0 1 0 0] Tm +0 0 Td +513.43 199.683 Td +/F128_0 9.963 Tf +(should) 26.5713 Tj +72 187.728 Td +(indicate) 31.5429 Tj +-246 TJm +(ho) 9.963 Tj +25 TJm +(w) 7.19329 Tj +-246 TJm +(man) 17.1563 Tj +15 TJm +(y) 4.9815 Tj +-246 TJm +(bytes) 21.0319 Tj +-247 TJm +(the) 12.1748 Tj +-246 TJm +(library) 26.5614 Tj +-246 TJm +(may) 17.1563 Tj +-246 TJm +(read.) 19.6371 Tj +[1 0 0 1 259.242 187.728] cm +0 g +0 G +[1 0 0 1 -259.242 -187.728] cm +[1 0 0 1 0 0] Tm +0 0 Td +259.242 187.728 Td +/F130_0 9.963 Tf +(BZ2_bzCompress) 83.6892 Tj +[1 0 0 1 342.929 187.728] cm +0 g +0 G +[1 0 0 1 -342.929 -187.728] cm +[1 0 0 1 0 0] Tm +0 0 Td +345.382 187.728 Td +/F128_0 9.963 Tf +(updates) 30.437 Tj +[1 0 0 1 378.271 187.728] cm +0 g +0 G +[1 0 0 1 -378.271 -187.728] cm +[1 0 0 1 0 0] Tm +0 0 Td +378.271 187.728 Td +/F130_0 9.963 Tf +(next_in) 41.8446 Tj +[1 0 0 1 420.114 187.728] cm +0 g +0 G +[1 0 0 1 -420.114 -187.728] cm +[1 0 0 1 0 0] Tm +0 0 Td +420.114 187.728 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 425.066 187.728] cm +0 g +0 G +[1 0 0 1 -425.066 -187.728] cm +[1 0 0 1 0 0] Tm +0 0 Td +425.066 187.728 Td +/F130_0 9.963 Tf +(avail_in) 47.8224 Tj +[1 0 0 1 472.886 187.728] cm +0 g +0 G +[1 0 0 1 -472.886 -187.728] cm +[1 0 0 1 0 0] Tm +0 0 Td +475.34 187.728 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 492.179 187.728] cm +0 g +0 G +[1 0 0 1 -492.179 -187.728] cm +[1 0 0 1 0 0] Tm +0 0 Td +492.179 187.728 Td +/F130_0 9.963 Tf +(total_in) 47.8224 Tj +[1 0 0 1 540 187.728] cm +0 g +0 G +[1 0 0 1 -540 -187.728] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 175.773 Td +/F128_0 9.963 Tf +(to) 7.75121 Tj +-250 TJm +(re\003ect) 24.8975 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(number) 30.437 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(bytes) 21.0319 Tj +-249 TJm +(it) 5.53943 Tj +-250 TJm +(has) 13.2807 Tj +-250 TJm +(read.) 19.6371 Tj +[1 0 0 1 72 173.616] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -163.654] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 153.856 Td +/F128_0 9.963 Tf +(Similarly) 37.0922 Tj +65 TJm +(,) 2.49075 Tj +[1 0 0 1 113.148 153.856] cm +0 g +0 G +[1 0 0 1 -113.148 -153.856] cm +[1 0 0 1 0 0] Tm +0 0 Td +113.148 153.856 Td +/F130_0 9.963 Tf +(next_out) 47.8224 Tj +[1 0 0 1 160.968 153.856] cm +0 g +0 G +[1 0 0 1 -160.968 -153.856] cm +[1 0 0 1 0 0] Tm +0 0 Td +163.114 153.856 Td +/F128_0 9.963 Tf +(should) 26.5713 Tj +-215 TJm +(point) 20.4839 Tj +-215 TJm +(to) 7.75121 Tj +-216 TJm +(a) 4.42357 Tj +-215 TJm +(b) 4.9815 Tj +20 TJm +(uf) 8.29918 Tj +25 TJm +(fer) 11.0589 Tj +-215 TJm +(in) 7.75121 Tj +-216 TJm +(whi) 14.9445 Tj +1 TJm +(ch) 9.40507 Tj +-216 TJm +(the) 12.1748 Tj +-215 TJm +(compressed) 47.0353 Tj +-215 TJm +(data) 16.5984 Tj +-215 TJm +(is) 6.64532 Tj +-216 TJm +(to) 7.75121 Tj +-215 TJm +(be) 9.40507 Tj +-215 TJm +(placed,) 28.4942 Tj +-222 TJm +(with) 17.7142 Tj +[1 0 0 1 456.391 153.856] cm +0 g +0 G +[1 0 0 1 -456.391 -153.856] cm +[1 0 0 1 0 0] Tm +0 0 Td +456.391 153.856 Td +/F130_0 9.963 Tf +(avail_out) 53.8002 Tj +[1 0 0 1 510.189 153.856] cm +0 g +0 G +[1 0 0 1 -510.189 -153.856] cm +[1 0 0 1 0 0] Tm +0 0 Td +512.334 153.856 Td +/F128_0 9.963 Tf +(indica-) 27.6673 Tj +72 141.901 Td +(ting) 15.5024 Tj +-280 TJm +(ho) 9.963 Tj +25 TJm +(w) 7.19329 Tj +-281 TJm +(muc) 17.1563 Tj +1 TJm +(h) 4.9815 Tj +-281 TJm +(output) 25.4654 Tj +-280 TJm +(space) 22.1278 Tj +-280 TJm +(is) 6.64532 Tj +-281 TJm +(a) 4.42357 Tj +20 TJm +(v) 4.9815 Tj +25 TJm +(ailabl) 22.1378 Tj +1 TJm +(e.) 6.91432 Tj +[1 0 0 1 239.543 141.901] cm +0 g +0 G +[1 0 0 1 -239.543 -141.901] cm +[1 0 0 1 0 0] Tm +0 0 Td +239.543 141.901 Td +/F130_0 9.963 Tf +(BZ2_bzCompress) 83.6892 Tj +[1 0 0 1 323.229 141.901] cm +0 g +0 G +[1 0 0 1 -323.229 -141.901] cm +[1 0 0 1 0 0] Tm +0 0 Td +326.022 141.901 Td +/F128_0 9.963 Tf +(updates) 30.437 Tj +[1 0 0 1 359.251 141.901] cm +0 g +0 G +[1 0 0 1 -359.251 -141.901] cm +[1 0 0 1 0 0] Tm +0 0 Td +359.251 141.901 Td +/F130_0 9.963 Tf +(next_out) 47.8224 Tj +[1 0 0 1 407.072 141.901] cm +0 g +0 G +[1 0 0 1 -407.072 -141.901] cm +[1 0 0 1 0 0] Tm +0 0 Td +407.072 141.901 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 412.431 141.901] cm +0 g +0 G +[1 0 0 1 -412.431 -141.901] cm +[1 0 0 1 0 0] Tm +0 0 Td +412.431 141.901 Td +/F130_0 9.963 Tf +(avail_out) 53.8002 Tj +[1 0 0 1 466.229 141.901] cm +0 g +0 G +[1 0 0 1 -466.229 -141.901] cm +[1 0 0 1 0 0] Tm +0 0 Td +469.023 141.901 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 486.202 141.901] cm +0 g +0 G +[1 0 0 1 -486.202 -141.901] cm +[1 0 0 1 0 0] Tm +0 0 Td +486.202 141.901 Td +/F130_0 9.963 Tf +(total_out) 53.8002 Tj +[1 0 0 1 540 141.901] cm +0 g +0 G +[1 0 0 1 -540 -141.901] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 129.946 Td +/F128_0 9.963 Tf +(to) 7.75121 Tj +-250 TJm +(re\003ect) 24.8975 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(number) 30.437 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(bytes) 21.0319 Tj +-249 TJm +(output.) 27.9562 Tj +[1 0 0 1 72 127.789] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -117.827] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 108.029 Td +/F128_0 9.963 Tf +(Y) 7.19329 Tj +110 TJm +(ou) 9.963 Tj +-272 TJm +(may) 17.1563 Tj +-272 TJm +(pro) 13.2807 Tj +15 TJm +(vide) 17.1563 Tj +-272 TJm +(and) 14.3866 Tj +-271 TJm +(remo) 20.474 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-272 TJm +(as) 8.29918 Tj +-272 TJm +(little) 18.2721 Tj +-272 TJm +(or) 8.29918 Tj +-272 TJm +(as) 8.29918 Tj +-272 TJm +(much) 22.1378 Tj +-272 TJm +(data) 16.5984 Tj +-272 TJm +(as) 8.29918 Tj +-271 TJm +(you) 14.9445 Tj +-272 TJm +(lik) 10.5209 Tj +10 TJm +(e) 4.42357 Tj +-272 TJm +(on) 9.963 Tj +-272 TJm +(each) 18.2522 Tj +-272 TJm +(call) 14.3866 Tj +-272 TJm +(of) 8.29918 Tj +[1 0 0 1 399.123 108.029] cm +0 g +0 G +[1 0 0 1 -399.123 -108.029] cm +[1 0 0 1 0 0] Tm +0 0 Td +399.123 108.029 Td +/F130_0 9.963 Tf +(BZ2_bzCompress) 83.6892 Tj +[1 0 0 1 482.809 108.029] cm +0 g +0 G +[1 0 0 1 -482.809 -108.029] cm +[1 0 0 1 0 0] Tm +0 0 Td +482.809 108.029 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +-752 TJm +(In) 8.29918 Tj +-272 TJm +(the) 12.1748 Tj +-271 TJm +(limit,) 21.3208 Tj +72 96.074 Td +(it) 5.53943 Tj +-266 TJm +(is) 6.64532 Tj +-265 TJm +(acceptable) 42.0439 Tj +-266 TJm +(to) 7.75121 Tj +-266 TJm +(su) 8.85711 Tj +1 TJm +(pply) 17.7142 Tj +-266 TJm +(and) 14.3866 Tj +-266 TJm +(remo) 20.474 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-265 TJm +(data) 16.5984 Tj +-266 TJm +(one) 14.3866 Tj +-266 TJm +(byte) 17.1563 Tj +-265 TJm +(at) 7.19329 Tj +-266 TJm +(a) 4.42357 Tj +-266 TJm +(time,) 20.205 Tj +-269 TJm +(although) 34.8705 Tj +-266 TJm +(this) 14.3965 Tj +-265 TJm +(w) 7.19329 Tj +10 TJm +(ould) 17.7142 Tj +-266 TJm +(be) 9.40507 Tj +-266 TJm +(terribly) 29.3311 Tj +-265 TJm +(inef) 15.4925 Tj +25 TJm +(\002cient.) 27.3983 Tj +-714 TJm +(Y) 7.19329 Tj +110 TJm +(ou) 9.963 Tj +-266 TJm +(should) 26.5713 Tj +72 84.118 Td +(al) 7.19329 Tj +10 TJm +(w) 7.19329 Tj +10 TJm +(ays) 13.2807 Tj +-250 TJm +(ensure) 26.0034 Tj +-250 TJm +(that) 14.9445 Tj +-250 TJm +(at) 7.19329 Tj +-250 TJm +(least) 18.2622 Tj +-249 TJm +(one) 14.3866 Tj +-250 TJm +(byte) 17.1563 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(output) 25.4654 Tj +-250 TJm +(space) 22.1278 Tj +-250 TJm +(is) 6.64532 Tj +-250 TJm +(a) 4.42357 Tj +20 TJm +(v) 4.9815 Tj +25 TJm +(ailable) 26.5614 Tj +-250 TJm +(at) 7.19329 Tj +-250 TJm +(each) 18.2522 Tj +-250 TJm +(call.) 16.8773 Tj +[1 0 0 1 72 81.962] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 0 -21.148] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.854] cm +0 g +0 G +0 g +0 G +[1 0 0 1 40.572 -6.755] cm +0 g +0 G +[1 0 0 1 -493.841 -50.951] cm +[1 0 0 1 0 0] Tm +0 0 Td +534.414 50.951 Td +/F128_0 9.963 Tf +(13) 9.963 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 17 17 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 -8.911] cm +0 g +0 G +[1 0 0 1 0 8.911] cm +0 g +0 G +0 g +0 G +[1 0 0 1 84.08 -6.755] cm +0 g +0 G +[1 0 0 1 -350.151 -749.245] cm +[1 0 0 1 0 0] Tm +0 0 Td +434.231 749.245 Td +/F128_0 9.963 Tf +(Programming) 54.7965 Tj +-250 TJm +(with) 17.7142 Tj +-250 TJm +(libbzip2) 32.6587 Tj +[1 0 0 1 266.071 747.089] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -5.037] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -540 -741.554] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 710.037 Td +/F128_0 9.963 Tf +(A) 7.19329 Tj +-250 TJm +(second) 27.6673 Tj +-250 TJm +(purpose) 31.5429 Tj +-250 TJm +(of) 8.29918 Tj +[1 0 0 1 156.662 710.037] cm +0 g +0 G +[1 0 0 1 -156.662 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +156.662 710.037 Td +/F130_0 9.963 Tf +(BZ2_bzCompress) 83.6892 Tj +[1 0 0 1 240.348 710.037] cm +0 g +0 G +[1 0 0 1 -240.348 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +242.839 710.037 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(request) 28.7731 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(change) 28.2152 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(mod) 17.7142 Tj +1 TJm +(e) 4.42357 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(compressed) 47.0353 Tj +-250 TJm +(stream.) 29.0521 Tj +[1 0 0 1 72 707.881] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -697.918] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 688.12 Td +/F128_0 9.963 Tf +(Conceptually) 53.1327 Tj +65 TJm +(,) 2.49075 Tj +-217 TJm +(a) 4.42357 Tj +-209 TJm +(compressed) 47.0353 Tj +-209 TJm +(stream) 26.5614 Tj +-210 TJm +(can) 13.8286 Tj +-209 TJm +(be) 9.40507 Tj +-209 TJm +(in) 7.75121 Tj +-209 TJm +(one) 14.3866 Tj +-209 TJm +(of) 8.29918 Tj +-210 TJm +(four) 16.5984 Tj +-209 TJm +(states:) 24.9075 Tj +-289 TJm +(IDLE,) 25.1765 Tj +-209 TJm +(R) 6.64532 Tj +40 TJm +(UNNING,) 41.7749 Tj +-209 TJm +(FLUSHING) 49.2571 Tj +-209 TJm +(and) 14.3866 Tj +-210 TJm +(FINISHING) 49.805 Tj +1 TJm +(.) 2.49075 Tj +-419 TJm +(Be-) 14.3866 Tj +72 676.164 Td +(fore) 16.0404 Tj +-264 TJm +(initialis) 29.899 Tj +1 TJm +(ation) 19.926 Tj +-264 TJm +(\() 3.31768 Tj +[1 0 0 1 146.434 676.164] cm +0 g +0 G +[1 0 0 1 -146.434 -676.164] cm +[1 0 0 1 0 0] Tm +0 0 Td +146.434 676.164 Td +/F130_0 9.963 Tf +(BZ2_bzCompressInit) 107.6 Tj +[1 0 0 1 254.031 676.164] cm +0 g +0 G +[1 0 0 1 -254.031 -676.164] cm +[1 0 0 1 0 0] Tm +0 0 Td +254.031 676.164 Td +/F128_0 9.963 Tf +(\)) 3.31768 Tj +-264 TJm +(and) 14.3866 Tj +-263 TJm +(after) 18.2522 Tj +-264 TJm +(termination) 45.9394 Tj +-264 TJm +(\() 3.31768 Tj +[1 0 0 1 349.75 676.164] cm +0 g +0 G +[1 0 0 1 -349.75 -676.164] cm +[1 0 0 1 0 0] Tm +0 0 Td +349.75 676.164 Td +/F130_0 9.963 Tf +(BZ2_bzCompressEnd) 101.623 Tj +[1 0 0 1 451.369 676.164] cm +0 g +0 G +[1 0 0 1 -451.369 -676.164] cm +[1 0 0 1 0 0] Tm +0 0 Td +451.369 676.164 Td +/F128_0 9.963 Tf +(\),) 5.80843 Tj +-267 TJm +(a) 4.42357 Tj +-264 TJm +(stream) 26.5614 Tj +-263 TJm +(is) 6.64532 Tj +-264 TJm +(re) 7.74125 Tj +15 TJm +(g) 4.9815 Tj +5 TJm +(arded) 22.1278 Tj +72 664.209 Td +(as) 8.29918 Tj +-250 TJm +(IDLE.) 25.1765 Tj +[1 0 0 1 72 664.11] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -654.147] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 642.291 Td +/F128_0 9.963 Tf +(Upon) 22.1378 Tj +-389 TJm +(initialisation) 49.825 Tj +-389 TJm +(\() 3.31768 Tj +[1 0 0 1 155.036 642.291] cm +0 g +0 G +[1 0 0 1 -155.036 -642.291] cm +[1 0 0 1 0 0] Tm +0 0 Td +155.036 642.291 Td +/F130_0 9.963 Tf +(BZ2_bzCompressInit) 107.6 Tj +[1 0 0 1 262.632 642.291] cm +0 g +0 G +[1 0 0 1 -262.632 -642.291] cm +[1 0 0 1 0 0] Tm +0 0 Td +262.632 642.291 Td +/F128_0 9.963 Tf +(\),) 5.80843 Tj +-424 TJm +(the) 12.1748 Tj +-390 TJm +(stream) 26.5614 Tj +-389 TJm +(is) 6.64532 Tj +-389 TJm +(placed) 26.0034 Tj +-390 TJm +(in) 7.75121 Tj +-389 TJm +(the) 12.1748 Tj +-389 TJm +(R) 6.64532 Tj +40 TJm +(UNNING) 39.2841 Tj +-389 TJm +(state.) 20.7529 Tj +-1457 TJm +(Subsequent) 45.9394 Tj +-389 TJm +(calls) 18.2622 Tj +72 630.336 Td +(to) 7.75121 Tj +[1 0 0 1 83.818 630.336] cm +0 g +0 G +[1 0 0 1 -83.818 -630.336] cm +[1 0 0 1 0 0] Tm +0 0 Td +83.818 630.336 Td +/F130_0 9.963 Tf +(BZ2_bzCompress) 83.6892 Tj +[1 0 0 1 167.504 630.336] cm +0 g +0 G +[1 0 0 1 -167.504 -630.336] cm +[1 0 0 1 0 0] Tm +0 0 Td +171.571 630.336 Td +/F128_0 9.963 Tf +(should) 26.5713 Tj +-408 TJm +(pass) 17.1563 Tj +[1 0 0 1 223.431 630.336] cm +0 g +0 G +[1 0 0 1 -223.431 -630.336] cm +[1 0 0 1 0 0] Tm +0 0 Td +223.431 630.336 Td +/F130_0 9.963 Tf +(BZ_RUN) 35.8668 Tj +[1 0 0 1 259.297 630.336] cm +0 g +0 G +[1 0 0 1 -259.297 -630.336] cm +[1 0 0 1 0 0] Tm +0 0 Td +263.362 630.336 Td +/F128_0 9.963 Tf +(as) 8.29918 Tj +-408 TJm +(the) 12.1748 Tj +-408 TJm +(requested) 38.1782 Tj +-408 TJm +(action;) 27.1193 Tj +-488 TJm +(other) 20.474 Tj +-408 TJm +(actions) 28.2252 Tj +-408 TJm +(are) 12.1648 Tj +-408 TJm +(ille) 12.7327 Tj +15 TJm +(g) 4.9815 Tj +5 TJm +(al) 7.19329 Tj +-408 TJm +(and) 14.3866 Tj +-408 TJm +(will) 15.5024 Tj +-409 TJm +(re) 7.74125 Tj +1 TJm +(sult) 14.3965 Tj +-409 TJm +(in) 7.75121 Tj +[1 0 0 1 72 618.381] cm +0 g +0 G +[1 0 0 1 -72 -618.381] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 618.381 Td +/F130_0 9.963 Tf +(BZ_SEQUENCE_ERROR) 101.623 Tj +[1 0 0 1 173.619 618.381] cm +0 g +0 G +[1 0 0 1 -173.619 -618.381] cm +[1 0 0 1 0 0] Tm +0 0 Td +173.619 618.381 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 72 616.961] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -606.999] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 596.463 Td +/F128_0 9.963 Tf +(At) 9.963 Tj +-279 TJm +(some) 21.0319 Tj +-279 TJm +(point,) 22.9747 Tj +-286 TJm +(the) 12.1748 Tj +-279 TJm +(call) 14.3866 Tj +1 TJm +(ing) 12.7327 Tj +-279 TJm +(program) 33.7546 Tj +-279 TJm +(will) 15.5024 Tj +-279 TJm +(ha) 9.40507 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-279 TJm +(pro) 13.2807 Tj +15 TJm +(vided) 22.1378 Tj +-279 TJm +(all) 9.963 Tj +-278 TJm +(the) 12.1748 Tj +-279 TJm +(input) 20.4839 Tj +-279 TJm +(data) 16.5984 Tj +-279 TJm +(it) 5.53943 Tj +-279 TJm +(w) 7.19329 Tj +10 TJm +(ants) 16.0504 Tj +-279 TJm +(to.) 10.242 Tj +-793 TJm +(It) 6.08739 Tj +-279 TJm +(will) 15.5024 Tj +-279 TJm +(then) 17.1563 Tj +-279 TJm +(w) 7.19329 Tj +10 TJm +(ant) 12.1748 Tj +-278 TJm +(to) 7.75121 Tj +-279 TJm +(\002nish) 22.1477 Tj +-279 TJm +(up) 9.963 Tj +-279 TJm +(--) 6.63536 Tj +72 584.508 Td +(in) 7.75121 Tj +-287 TJm +(ef) 7.74125 Tj +25 TJm +(fect,) 17.4253 Tj +-297 TJm +(asking) 26.0134 Tj +-287 TJm +(the) 12.1748 Tj +-288 TJm +(library) 26.5614 Tj +-287 TJm +(to) 7.75121 Tj +-287 TJm +(process) 29.879 Tj +-288 TJm +(an) 9.40507 Tj +15 TJm +(y) 4.9815 Tj +-287 TJm +(data) 16.5984 Tj +-287 TJm +(it) 5.53943 Tj +-288 TJm +(might) 23.2536 Tj +-287 TJm +(ha) 9.40507 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-287 TJm +(b) 4.9815 Tj +20 TJm +(uf) 8.29918 Tj +25 TJm +(fered) 20.464 Tj +-288 TJm +(inte) 14.9445 Tj +1 TJm +(rnally) 23.2437 Tj +65 TJm +(.) 2.49075 Tj +-845 TJm +(In) 8.29918 Tj +-287 TJm +(this) 14.3965 Tj +-288 TJm +(sta) 11.0689 Tj +1 TJm +(te,) 9.68404 Tj +[1 0 0 1 456.314 584.508] cm +0 g +0 G +[1 0 0 1 -456.314 -584.508] cm +[1 0 0 1 0 0] Tm +0 0 Td +456.314 584.508 Td +/F130_0 9.963 Tf +(BZ2_bzCompress) 83.6892 Tj +[1 0 0 1 540 584.508] cm +0 g +0 G +[1 0 0 1 -540 -584.508] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 572.553 Td +/F128_0 9.963 Tf +(will) 15.5024 Tj +-258 TJm +(no) 9.963 Tj +-257 TJm +(longer) 25.4555 Tj +-258 TJm +(attempt) 29.889 Tj +-257 TJm +(to) 7.75121 Tj +-258 TJm +(read) 17.1463 Tj +-258 TJm +(data) 16.5984 Tj +-257 TJm +(from) 19.3681 Tj +[1 0 0 1 234.207 572.553] cm +0 g +0 G +[1 0 0 1 -234.207 -572.553] cm +[1 0 0 1 0 0] Tm +0 0 Td +234.207 572.553 Td +/F130_0 9.963 Tf +(next_in) 41.8446 Tj +[1 0 0 1 276.051 572.553] cm +0 g +0 G +[1 0 0 1 -276.051 -572.553] cm +[1 0 0 1 0 0] Tm +0 0 Td +276.051 572.553 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-260 TJm +(b) 4.9815 Tj +20 TJm +(ut) 7.75121 Tj +-257 TJm +(it) 5.53943 Tj +-258 TJm +(will) 15.5024 Tj +-258 TJm +(w) 7.19329 Tj +10 TJm +(an) 9.40507 Tj +1 TJm +(t) 2.76971 Tj +-258 TJm +(to) 7.75121 Tj +-258 TJm +(write) 20.474 Tj +-257 TJm +(data) 16.5984 Tj +-258 TJm +(to) 7.75121 Tj +[1 0 0 1 407.082 572.553] cm +0 g +0 G +[1 0 0 1 -407.082 -572.553] cm +[1 0 0 1 0 0] Tm +0 0 Td +407.082 572.553 Td +/F130_0 9.963 Tf +(next_out) 47.8224 Tj +[1 0 0 1 454.902 572.553] cm +0 g +0 G +[1 0 0 1 -454.902 -572.553] cm +[1 0 0 1 0 0] Tm +0 0 Td +454.902 572.553 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +-666 TJm +(Because) 33.1967 Tj +-258 TJm +(the) 12.1748 Tj +-258 TJm +(ou) 9.963 Tj +1 TJm +(tput) 15.5024 Tj +72 560.598 Td +(b) 4.9815 Tj +20 TJm +(uf) 8.29918 Tj +25 TJm +(fer) 11.0589 Tj +-228 TJm +(supplied) 33.7646 Tj +-228 TJm +(by) 9.963 Tj +-228 TJm +(the) 12.1748 Tj +-228 TJm +(user) 16.5984 Tj +-229 TJm +(can) 13.8286 Tj +-228 TJm +(be) 9.40507 Tj +-228 TJm +(arbitrarily) 39.842 Tj +-228 TJm +(small,) 24.0806 Tj +-232 TJm +(the) 12.1748 Tj +-228 TJm +(\002nishing-up) 48.1611 Tj +-228 TJm +(operation) 37.6303 Tj +-228 TJm +(cannot) 26.5614 Tj +-229 TJm +(n) 4.9815 Tj +1 TJm +(ecessarily) 39.2841 Tj +-228 TJm +(be) 9.40507 Tj +-229 TJm +(done) 19.3681 Tj +-228 TJm +(with) 17.7142 Tj +-228 TJm +(a) 4.42357 Tj +-228 TJm +(single) 23.8016 Tj +72 548.643 Td +(call) 14.3866 Tj +-250 TJm +(of) 8.29918 Tj +[1 0 0 1 99.666 548.643] cm +0 g +0 G +[1 0 0 1 -99.666 -548.643] cm +[1 0 0 1 0 0] Tm +0 0 Td +99.666 548.643 Td +/F130_0 9.963 Tf +(BZ2_bzCompress) 83.6892 Tj +[1 0 0 1 183.352 548.643] cm +0 g +0 G +[1 0 0 1 -183.352 -548.643] cm +[1 0 0 1 0 0] Tm +0 0 Td +183.352 548.643 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 72 547.079] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -537.116] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 526.725 Td +/F128_0 9.963 Tf +(Instead,) 31.2639 Tj +-346 TJm +(the) 12.1748 Tj +-327 TJm +(ca) 8.84714 Tj +1 TJm +(lling) 18.2721 Tj +-327 TJm +(program) 33.7546 Tj +-327 TJm +(passes) 25.4555 Tj +[1 0 0 1 218.231 526.725] cm +0 g +0 G +[1 0 0 1 -218.231 -526.725] cm +[1 0 0 1 0 0] Tm +0 0 Td +218.231 526.725 Td +/F130_0 9.963 Tf +(BZ_FINISH) 53.8002 Tj +[1 0 0 1 272.029 526.725] cm +0 g +0 G +[1 0 0 1 -272.029 -526.725] cm +[1 0 0 1 0 0] Tm +0 0 Td +275.284 526.725 Td +/F128_0 9.963 Tf +(as) 8.29918 Tj +-327 TJm +(an) 9.40507 Tj +-326 TJm +(action) 24.3496 Tj +-327 TJm +(to) 7.75121 Tj +[1 0 0 1 338.109 526.725] cm +0 g +0 G +[1 0 0 1 -338.109 -526.725] cm +[1 0 0 1 0 0] Tm +0 0 Td +338.109 526.725 Td +/F130_0 9.963 Tf +(BZ2_bzCompress) 83.6892 Tj +[1 0 0 1 421.795 526.725] cm +0 g +0 G +[1 0 0 1 -421.795 -526.725] cm +[1 0 0 1 0 0] Tm +0 0 Td +421.795 526.725 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +-1081 TJm +(This) 17.7142 Tj +-326 TJm +(changes) 32.0908 Tj +-327 TJm +(the) 12.1748 Tj +-327 TJm +(strea) 18.8101 Tj +1 TJm +(m') 11.0689 Tj +55 TJm +(s) 3.87561 Tj +72 514.77 Td +(state) 18.2622 Tj +-290 TJm +(to) 7.75121 Tj +-291 TJm +(FINISHING.) 52.2958 Tj +-581 TJm +(An) 12.1748 Tj +15 TJm +(y) 4.9815 Tj +-290 TJm +(remaining) 40.4 Tj +-291 TJm +(input) 20.4839 Tj +-290 TJm +(\(ie,) 13.0017 Tj +[1 0 0 1 264.452 514.77] cm +0 g +0 G +[1 0 0 1 -264.452 -514.77] cm +[1 0 0 1 0 0] Tm +0 0 Td +264.452 514.77 Td +/F130_0 9.963 Tf +(next_in[0) 53.8002 Tj +-600 TJm +(..) 11.9556 Tj +-1200 TJm +(avail_in-1]) 65.7558 Tj +[1 0 0 1 413.892 514.77] cm +0 g +0 G +[1 0 0 1 -413.892 -514.77] cm +[1 0 0 1 0 0] Tm +0 0 Td +413.892 514.77 Td +/F128_0 9.963 Tf +(\)) 3.31768 Tj +-291 TJm +(is) 6.64532 Tj +-290 TJm +(compressed) 47.0353 Tj +-290 TJm +(and) 14.3866 Tj +-291 TJm +(transferred) 43.1498 Tj +72 502.814 Td +(to) 7.75121 Tj +-421 TJm +(the) 12.1748 Tj +-421 TJm +(output) 25.4654 Tj +-421 TJm +(b) 4.9815 Tj +20 TJm +(uf) 8.29918 Tj +25 TJm +(fer) 11.0589 Tj +55 TJm +(.) 2.49075 Tj +-1646 TJm +(T) 6.08739 Tj +80 TJm +(o) 4.9815 Tj +-421 TJm +(do) 9.963 Tj +-421 TJm +(this,) 16.8873 Tj +[1 0 0 1 222.339 502.814] cm +0 g +0 G +[1 0 0 1 -222.339 -502.814] cm +[1 0 0 1 0 0] Tm +0 0 Td +222.339 502.814 Td +/F130_0 9.963 Tf +(BZ2_bzCompress) 83.6892 Tj +[1 0 0 1 306.025 502.814] cm +0 g +0 G +[1 0 0 1 -306.025 -502.814] cm +[1 0 0 1 0 0] Tm +0 0 Td +310.22 502.814 Td +/F128_0 9.963 Tf +(must) 19.378 Tj +-421 TJm +(be) 9.40507 Tj +-421 TJm +(called) 23.7916 Tj +-421 TJm +(repeatedly) 41.4959 Tj +-421 TJm +(until) 18.2721 Tj +-421 TJm +(all) 9.963 Tj +-421 TJm +(the) 12.1748 Tj +-421 TJm +(outp) 17.7142 Tj +1 TJm +(ut) 7.75121 Tj +-421 TJm +(has) 13.2807 Tj +-421 TJm +(been) 18.8101 Tj +72 490.859 Td +(consumed.) 42.8907 Tj +-1396 TJm +(At) 9.963 Tj +-380 TJm +(that) 14.9445 Tj +-379 TJm +(point,) 22.9747 Tj +[1 0 0 1 188.346 490.859] cm +0 g +0 G +[1 0 0 1 -188.346 -490.859] cm +[1 0 0 1 0 0] Tm +0 0 Td +188.346 490.859 Td +/F130_0 9.963 Tf +(BZ2_bzCompress) 83.6892 Tj +[1 0 0 1 272.033 490.859] cm +0 g +0 G +[1 0 0 1 -272.033 -490.859] cm +[1 0 0 1 0 0] Tm +0 0 Td +275.813 490.859 Td +/F128_0 9.963 Tf +(returns) 27.6673 Tj +[1 0 0 1 307.259 490.859] cm +0 g +0 G +[1 0 0 1 -307.259 -490.859] cm +[1 0 0 1 0 0] Tm +0 0 Td +307.259 490.859 Td +/F130_0 9.963 Tf +(BZ_STREAM_END) 77.7114 Tj +[1 0 0 1 384.968 490.859] cm +0 g +0 G +[1 0 0 1 -384.968 -490.859] cm +[1 0 0 1 0 0] Tm +0 0 Td +384.968 490.859 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-379 TJm +(and) 14.3866 Tj +-380 TJm +(the) 12.1748 Tj +-379 TJm +(stream') 29.879 Tj +55 TJm +(s) 3.87561 Tj +-379 TJm +(state) 18.2622 Tj +-380 TJm +(is) 6.64532 Tj +-379 TJm +(set) 11.0689 Tj +-379 TJm +(back) 18.8101 Tj +-380 TJm +(to) 7.75121 Tj +72 478.904 Td +(IDLE.) 25.1765 Tj +[1 0 0 1 99.666 478.904] cm +0 g +0 G +[1 0 0 1 -99.666 -478.904] cm +[1 0 0 1 0 0] Tm +0 0 Td +99.666 478.904 Td +/F130_0 9.963 Tf +(BZ2_bzCompressEnd) 101.623 Tj +[1 0 0 1 201.285 478.904] cm +0 g +0 G +[1 0 0 1 -201.285 -478.904] cm +[1 0 0 1 0 0] Tm +0 0 Td +203.776 478.904 Td +/F128_0 9.963 Tf +(should) 26.5713 Tj +-250 TJm +(then) 17.1563 Tj +-250 TJm +(be) 9.40507 Tj +-250 TJm +(called.) 26.2824 Tj +[1 0 0 1 72 477.34] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -467.377] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 456.986 Td +/F128_0 9.963 Tf +(Just) 15.5024 Tj +-380 TJm +(to) 7.75121 Tj +-379 TJm +(mak) 17.1563 Tj +10 TJm +(e) 4.42357 Tj +-380 TJm +(sure) 16.5984 Tj +-380 TJm +(the) 12.1748 Tj +-380 TJm +(c) 4.42357 Tj +1 TJm +(alling) 22.6957 Tj +-380 TJm +(program) 33.7546 Tj +-380 TJm +(does) 18.2622 Tj +-379 TJm +(not) 12.7327 Tj +-380 TJm +(cheat,) 23.5127 Tj +-412 TJm +(the) 12.1748 Tj +-380 TJm +(library) 26.5614 Tj +-380 TJm +(mak) 17.1563 Tj +10 TJm +(es) 8.29918 Tj +-379 TJm +(a) 4.42357 Tj +-380 TJm +(note) 17.1563 Tj +-380 TJm +(of) 8.29918 Tj +[1 0 0 1 415.708 456.986] cm +0 g +0 G +[1 0 0 1 -415.708 -456.986] cm +[1 0 0 1 0 0] Tm +0 0 Td +415.708 456.986 Td +/F130_0 9.963 Tf +(avail_in) 47.8224 Tj +[1 0 0 1 463.528 456.986] cm +0 g +0 G +[1 0 0 1 -463.528 -456.986] cm +[1 0 0 1 0 0] Tm +0 0 Td +467.312 456.986 Td +/F128_0 9.963 Tf +(at) 7.19329 Tj +-380 TJm +(the) 12.1748 Tj +-379 TJm +(time) 17.7142 Tj +-380 TJm +(of) 8.29918 Tj +-380 TJm +(the) 12.1748 Tj +72 445.031 Td +(\002rst) 15.5024 Tj +-286 TJm +(call) 14.3866 Tj +-285 TJm +(to) 7.75121 Tj +[1 0 0 1 118.179 445.031] cm +0 g +0 G +[1 0 0 1 -118.179 -445.031] cm +[1 0 0 1 0 0] Tm +0 0 Td +118.179 445.031 Td +/F130_0 9.963 Tf +(BZ2_bzCompress) 83.6892 Tj +[1 0 0 1 201.866 445.031] cm +0 g +0 G +[1 0 0 1 -201.866 -445.031] cm +[1 0 0 1 0 0] Tm +0 0 Td +204.713 445.031 Td +/F128_0 9.963 Tf +(which) 24.3496 Tj +-286 TJm +(has) 13.2807 Tj +[1 0 0 1 248.035 445.031] cm +0 g +0 G +[1 0 0 1 -248.035 -445.031] cm +[1 0 0 1 0 0] Tm +0 0 Td +248.035 445.031 Td +/F130_0 9.963 Tf +(BZ_FINISH) 53.8002 Tj +[1 0 0 1 301.834 445.031] cm +0 g +0 G +[1 0 0 1 -301.834 -445.031] cm +[1 0 0 1 0 0] Tm +0 0 Td +304.68 445.031 Td +/F128_0 9.963 Tf +(as) 8.29918 Tj +-286 TJm +(an) 9.40507 Tj +-285 TJm +(action) 24.3496 Tj +-286 TJm +(\(ie,) 13.0017 Tj +-295 TJm +(at) 7.19329 Tj +-285 TJm +(the) 12.1748 Tj +-286 TJm +(time) 17.7142 Tj +-286 TJm +(the) 12.1748 Tj +-286 TJm +(progr) 21.5799 Tj +1 TJm +(am) 12.1748 Tj +-286 TJm +(has) 13.2807 Tj +-286 TJm +(announced) 43.1597 Tj +-286 TJm +(i) 2.76971 Tj +1 TJm +(ts) 6.64532 Tj +72 433.076 Td +(intention) 35.4284 Tj +-292 TJm +(to) 7.75121 Tj +-291 TJm +(not) 12.7327 Tj +-292 TJm +(supply) 26.5713 Tj +-292 TJm +(an) 9.40507 Tj +15 TJm +(y) 4.9815 Tj +-291 TJm +(more) 20.474 Tj +-292 TJm +(input\).) 26.2924 Tj +-871 TJm +(By) 11.6268 Tj +-291 TJm +(comparing) 42.6118 Tj +-292 TJm +(this) 14.3965 Tj +-292 TJm +(v) 4.9815 Tj +25 TJm +(alue) 16.5984 Tj +-291 TJm +(with) 17.7142 Tj +-292 TJm +(that) 14.9445 Tj +-292 TJm +(of) 8.29918 Tj +[1 0 0 1 392.861 433.076] cm +0 g +0 G +[1 0 0 1 -392.861 -433.076] cm +[1 0 0 1 0 0] Tm +0 0 Td +392.861 433.076 Td +/F130_0 9.963 Tf +(avail_in) 47.8224 Tj +[1 0 0 1 440.682 433.076] cm +0 g +0 G +[1 0 0 1 -440.682 -433.076] cm +[1 0 0 1 0 0] Tm +0 0 Td +443.589 433.076 Td +/F128_0 9.963 Tf +(o) 4.9815 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(er) 7.74125 Tj +-292 TJm +(subsequent) 44.2756 Tj +-291 TJm +(calls) 18.2622 Tj +-292 TJm +(to) 7.75121 Tj +[1 0 0 1 72 421.121] cm +0 g +0 G +[1 0 0 1 -72 -421.121] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 421.121 Td +/F130_0 9.963 Tf +(BZ2_bzCompress) 83.6892 Tj +[1 0 0 1 155.686 421.121] cm +0 g +0 G +[1 0 0 1 -155.686 -421.121] cm +[1 0 0 1 0 0] Tm +0 0 Td +155.686 421.121 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-247 TJm +(the) 12.1748 Tj +-247 TJm +(libra) 18.2622 Tj +1 TJm +(ry) 8.29918 Tj +-247 TJm +(can) 13.8286 Tj +-246 TJm +(detect) 23.7916 Tj +-247 TJm +(an) 9.40507 Tj +15 TJm +(y) 4.9815 Tj +-246 TJm +(attempts) 33.7646 Tj +-246 TJm +(to) 7.75121 Tj +-247 TJm +(slip) 14.3965 Tj +-246 TJm +(in) 7.75121 Tj +-247 TJm +(more) 20.474 Tj +-246 TJm +(data) 16.5984 Tj +-246 TJm +(to) 7.75121 Tj +-247 TJm +(compress.) 40.121 Tj +-617 TJm +(An) 12.1748 Tj +15 TJm +(y) 4.9815 Tj +-247 TJm +(calls) 18.2622 Tj +-246 TJm +(for) 11.6169 Tj +-246 TJm +(which) 24.3496 Tj +-247 TJm +(this) 14.3965 Tj +-246 TJm +(is) 6.64532 Tj +72 409.166 Td +(detected) 33.1967 Tj +-250 TJm +(will) 15.5024 Tj +-250 TJm +(return) 23.7916 Tj +[1 0 0 1 151.959 409.166] cm +0 g +0 G +[1 0 0 1 -151.959 -409.166] cm +[1 0 0 1 0 0] Tm +0 0 Td +151.959 409.166 Td +/F130_0 9.963 Tf +(BZ_SEQUENCE_ERROR) 101.623 Tj +[1 0 0 1 253.578 409.166] cm +0 g +0 G +[1 0 0 1 -253.578 -409.166] cm +[1 0 0 1 0 0] Tm +0 0 Td +253.578 409.166 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +-500 TJm +(This) 17.7142 Tj +-250 TJm +(indicates) 35.4185 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(programm) 41.5059 Tj +1 TJm +(ing) 12.7327 Tj +-250 TJm +(mistak) 26.5713 Tj +10 TJm +(e) 4.42357 Tj +-250 TJm +(which) 24.3496 Tj +-250 TJm +(should) 26.5713 Tj +-250 TJm +(be) 9.40507 Tj +-250 TJm +(corrected.) 39.5531 Tj +[1 0 0 1 72 407.009] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -397.046] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 387.248 Td +/F128_0 9.963 Tf +(Instead) 28.7731 Tj +-223 TJm +(of) 8.29918 Tj +-224 TJm +(asking) 26.0134 Tj +-224 TJm +(to) 7.75121 Tj +-223 TJm +(\002nish,) 24.6385 Tj +-229 TJm +(the) 12.1748 Tj +-223 TJm +(calling) 27.1193 Tj +-224 TJm +(program) 33.7546 Tj +-223 TJm +(may) 17.1563 Tj +-224 TJm +(ask) 13.2807 Tj +[1 0 0 1 293.282 387.248] cm +0 g +0 G +[1 0 0 1 -293.282 -387.248] cm +[1 0 0 1 0 0] Tm +0 0 Td +293.282 387.248 Td +/F130_0 9.963 Tf +(BZ2_bzCompress) 83.6892 Tj +[1 0 0 1 376.968 387.248] cm +0 g +0 G +[1 0 0 1 -376.968 -387.248] cm +[1 0 0 1 0 0] Tm +0 0 Td +379.196 387.248 Td +/F128_0 9.963 Tf +(to) 7.75121 Tj +-224 TJm +(ta) 7.19329 Tj +1 TJm +(k) 4.9815 Tj +10 TJm +(e) 4.42357 Tj +-224 TJm +(all) 9.963 Tj +-224 TJm +(the) 12.1748 Tj +-223 TJm +(remaining) 40.4 Tj +-224 TJm +(inp) 12.7327 Tj +1 TJm +(ut,) 10.242 Tj +-229 TJm +(compress) 37.6303 Tj +72 375.293 Td +(it) 5.53943 Tj +-278 TJm +(and) 14.3866 Tj +-278 TJm +(terminate) 37.6303 Tj +-277 TJm +(the) 12.1748 Tj +-278 TJm +(current) 28.2152 Tj +-278 TJm +(\(Burro) 26.5614 Tj +25 TJm +(ws-Wheeler\)) 51.4489 Tj +-278 TJm +(co) 9.40507 Tj +1 TJm +(mpression) 40.9579 Tj +-278 TJm +(block.) 24.6285 Tj +-787 TJm +(This) 17.7142 Tj +-278 TJm +(could) 22.1378 Tj +-278 TJm +(be) 9.40507 Tj +-278 TJm +(useful) 24.3496 Tj +-278 TJm +(for) 11.6169 Tj +-278 TJm +(e) 4.42357 Tj +1 TJm +(rror) 14.9345 Tj +-278 TJm +(control) 28.2252 Tj +-278 TJm +(purposes.) 37.9092 Tj +72 363.337 Td +(The) 15.4925 Tj +-328 TJm +(mechanism) 45.3815 Tj +-328 TJm +(is) 6.64532 Tj +-328 TJm +(analogous) 40.4 Tj +-328 TJm +(to) 7.75121 Tj +-328 TJm +(that) 14.9445 Tj +-328 TJm +(for) 11.6169 Tj +-328 TJm +(\002nishing) 34.8805 Tj +1 TJm +(:) 2.76971 Tj +-467 TJm +(cal) 11.6169 Tj +1 TJm +(l) 2.76971 Tj +[1 0 0 1 297.049 363.337] cm +0 g +0 G +[1 0 0 1 -297.049 -363.337] cm +[1 0 0 1 0 0] Tm +0 0 Td +297.049 363.337 Td +/F130_0 9.963 Tf +(BZ2_bzCompress) 83.6892 Tj +[1 0 0 1 380.735 363.337] cm +0 g +0 G +[1 0 0 1 -380.735 -363.337] cm +[1 0 0 1 0 0] Tm +0 0 Td +384.003 363.337 Td +/F128_0 9.963 Tf +(with) 17.7142 Tj +-328 TJm +(an) 9.40507 Tj +-328 TJm +(action) 24.3496 Tj +-328 TJm +(of) 8.29918 Tj +[1 0 0 1 456.841 363.337] cm +0 g +0 G +[1 0 0 1 -456.841 -363.337] cm +[1 0 0 1 0 0] Tm +0 0 Td +456.841 363.337 Td +/F130_0 9.963 Tf +(BZ_FLUSH) 47.8224 Tj +[1 0 0 1 504.662 363.337] cm +0 g +0 G +[1 0 0 1 -504.662 -363.337] cm +[1 0 0 1 0 0] Tm +0 0 Td +504.662 363.337 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-328 TJm +(remo) 20.474 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +72 351.382 Td +(output) 25.4654 Tj +-445 TJm +(data,) 19.0891 Tj +-494 TJm +(and) 14.3866 Tj +-445 TJm +(persist) 26.0134 Tj +-445 TJm +(with) 17.7142 Tj +-446 TJm +(the) 12.1748 Tj +[1 0 0 1 213.94 351.382] cm +0 g +0 G +[1 0 0 1 -213.94 -351.382] cm +[1 0 0 1 0 0] Tm +0 0 Td +213.94 351.382 Td +/F130_0 9.963 Tf +(BZ_FLUSH) 47.8224 Tj +[1 0 0 1 261.761 351.382] cm +0 g +0 G +[1 0 0 1 -261.761 -351.382] cm +[1 0 0 1 0 0] Tm +0 0 Td +266.195 351.382 Td +/F128_0 9.963 Tf +(action) 24.3496 Tj +-445 TJm +(until) 18.2721 Tj +-445 TJm +(the) 12.1748 Tj +-445 TJm +(v) 4.9815 Tj +25 TJm +(alue) 16.5984 Tj +[1 0 0 1 360.062 351.382] cm +0 g +0 G +[1 0 0 1 -360.062 -351.382] cm +[1 0 0 1 0 0] Tm +0 0 Td +360.062 351.382 Td +/F130_0 9.963 Tf +(BZ_RUN) 35.8668 Tj +[1 0 0 1 395.928 351.382] cm +0 g +0 G +[1 0 0 1 -395.928 -351.382] cm +[1 0 0 1 0 0] Tm +0 0 Td +400.362 351.382 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-445 TJm +(returned.) 35.6875 Tj +-1792 TJm +(A) 7.19329 Tj +1 TJm +(s) 3.87561 Tj +-446 TJm +(with) 17.7142 Tj +-445 TJm +(\002nishing,) 37.3712 Tj +[1 0 0 1 72 339.427] cm +0 g +0 G +[1 0 0 1 -72 -339.427] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 339.427 Td +/F130_0 9.963 Tf +(BZ2_bzCompress) 83.6892 Tj +[1 0 0 1 155.686 339.427] cm +0 g +0 G +[1 0 0 1 -155.686 -339.427] cm +[1 0 0 1 0 0] Tm +0 0 Td +158.177 339.427 Td +/F128_0 9.963 Tf +(detects) 27.6673 Tj +-250 TJm +(an) 9.40507 Tj +15 TJm +(y) 4.9815 Tj +-250 TJm +(attempt) 29.889 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(pro) 13.2807 Tj +15 TJm +(vi) 7.75121 Tj +1 TJm +(de) 9.40507 Tj +-250 TJm +(more) 20.474 Tj +-250 TJm +(input) 20.4839 Tj +-250 TJm +(data) 16.5984 Tj +-250 TJm +(once) 18.8101 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(\003ush) 19.378 Tj +-250 TJm +(has) 13.2807 Tj +-250 TJm +(be) 9.40507 Tj +15 TJm +(gun.) 17.4353 Tj +[1 0 0 1 72 337.27] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -327.308] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 317.509 Td +/F128_0 9.963 Tf +(Once) 21.0219 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(\003ush) 19.378 Tj +-250 TJm +(is) 6.64532 Tj +-250 TJm +(complete,) 39.0151 Tj +-250 TJm +(t) 2.76971 Tj +1 TJm +(he) 9.40507 Tj +-250 TJm +(stream) 26.5614 Tj +-250 TJm +(returns) 27.6673 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(normal) 28.2252 Tj +-250 TJm +(R) 6.64532 Tj +40 TJm +(UNNING) 39.2841 Tj +-250 TJm +(state.) 20.7529 Tj +[1 0 0 1 72 315.353] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -305.39] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 295.592 Td +/F128_0 9.963 Tf +(This) 17.7142 Tj +-344 TJm +(all) 9.963 Tj +-343 TJm +(sounds) 27.6772 Tj +-344 TJm +(pretty) 23.2437 Tj +-344 TJm +(comple) 29.3311 Tj +15 TJm +(x) 4.9815 Tj +1 TJm +(,) 2.49075 Tj +-368 TJm +(b) 4.9815 Tj +20 TJm +(ut) 7.75121 Tj +-343 TJm +(isn') 14.9445 Tj +18 TJm +(t) 2.76971 Tj +-344 TJm +(really) 22.6858 Tj +65 TJm +(.) 2.49075 Tj +-1182 TJm +(Here') 22.6758 Tj +55 TJm +(s) 3.87561 Tj +-344 TJm +(a) 4.42357 Tj +-344 TJm +(table) 19.3681 Tj +-343 TJm +(which) 24.3496 Tj +-344 TJm +(sho) 13.8386 Tj +25 TJm +(ws) 11.0689 Tj +-344 TJm +(which) 24.3496 Tj +-343 TJm +(actions) 28.2252 Tj +-344 TJm +(are) 12.1648 Tj +-344 TJm +(allo) 14.9445 Tj +25 TJm +(w) 7.19329 Tj +10 TJm +(able) 16.5984 Tj +-343 TJm +(in) 7.75121 Tj +-344 TJm +(each) 18.2522 Tj +72 283.636 Td +(state,) 20.7529 Tj +-281 TJm +(wh) 12.1748 Tj +1 TJm +(at) 7.19329 Tj +-275 TJm +(action) 24.3496 Tj +-274 TJm +(will) 15.5024 Tj +-275 TJm +(be) 9.40507 Tj +-274 TJm +(tak) 12.1748 Tj +10 TJm +(en,) 11.8958 Tj +-281 TJm +(what) 19.3681 Tj +-274 TJm +(the) 12.1748 Tj +-275 TJm +(ne) 9.40507 Tj +15 TJm +(xt) 7.75121 Tj +-274 TJm +(state) 18.2622 Tj +-275 TJm +(is) 6.64532 Tj +1 TJm +(,) 2.49075 Tj +-281 TJm +(and) 14.3866 Tj +-275 TJm +(what) 19.3681 Tj +-274 TJm +(the) 12.1748 Tj +-274 TJm +(non-error) 37.6203 Tj +-275 TJm +(return) 23.7916 Tj +-274 TJm +(v) 4.9815 Tj +25 TJm +(alues) 20.474 Tj +-275 TJm +(are.) 14.6556 Tj +-767 TJm +(Note) 19.3681 Tj +-274 TJm +(that) 14.9445 Tj +-275 TJm +(you) 14.9445 Tj +-274 TJm +(can') 17.1463 Tj +18 TJm +(t) 2.76971 Tj +72 271.681 Td +(e) 4.42357 Tj +15 TJm +(xplicitly) 33.2166 Tj +-347 TJm +(ask) 13.2807 Tj +-348 TJm +(what) 19.3681 Tj +-347 TJm +(state) 18.2622 Tj +-347 TJm +(the) 12.1748 Tj +-348 TJm +(stream) 26.5614 Tj +-347 TJm +(is) 6.64532 Tj +-347 TJm +(in,) 10.242 Tj +-372 TJm +(b) 4.9815 Tj +20 TJm +(ut) 7.75121 Tj +-348 TJm +(nor) 13.2807 Tj +-347 TJm +(do) 9.963 Tj +-347 TJm +(you) 14.9445 Tj +-348 TJm +(need) 18.8101 Tj +-347 TJm +(to) 7.75121 Tj +-348 TJm +(--) 6.63536 Tj +-347 TJm +(it) 5.53943 Tj +-347 TJm +(can) 13.8286 Tj +-348 TJm +(be) 9.40507 Tj +-347 TJm +(inferred) 31.5329 Tj +-348 TJm +(from) 19.3681 Tj +-347 TJm +(the) 12.1748 Tj +-347 TJm +(v) 4.9815 Tj +25 TJm +(alues) 20.474 Tj +-348 TJm +(returned) 33.1967 Tj +-347 TJm +(by) 9.963 Tj +[1 0 0 1 72 259.726] cm +0 g +0 G +[1 0 0 1 -72 -259.726] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 259.726 Td +/F130_0 9.963 Tf +(BZ2_bzCompress) 83.6892 Tj +[1 0 0 1 155.686 259.726] cm +0 g +0 G +[1 0 0 1 -155.686 -259.726] cm +[1 0 0 1 0 0] Tm +0 0 Td +155.686 259.726 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 72 258.162] cm +0 g +0 G +[1 0 0 1 0 -207.31] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.754] cm +0 g +0 G +0 g +0 G +[1 0 0 1 40.572 -6.754] cm +0 g +0 G +[1 0 0 1 -493.841 -50.852] cm +[1 0 0 1 0 0] Tm +0 0 Td +534.414 50.852 Td +/F128_0 9.963 Tf +(14) 9.963 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 18 18 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 -8.911] cm +0 g +0 G +[1 0 0 1 0 8.911] cm +0 g +0 G +0 g +0 G +[1 0 0 1 84.08 -6.755] cm +0 g +0 G +[1 0 0 1 -350.151 -749.245] cm +[1 0 0 1 0 0] Tm +0 0 Td +434.231 749.245 Td +/F128_0 9.963 Tf +(Programming) 54.7965 Tj +-250 TJm +(with) 17.7142 Tj +-250 TJm +(libbzip2) 32.6587 Tj +[1 0 0 1 266.071 747.089] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -5.037] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -468 -595.402] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 573.848 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 570.261] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -711.631] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 711.631 Td +/F130_0 9.963 Tf +(IDLE/any) 47.8224 Tj +98.488 699.676 Td +(Illegal.) 47.8224 Tj +-852 TJm +(IDLE) 23.9112 Tj +-426 TJm +(state) 29.889 Tj +-426 TJm +(onl) 17.9334 Tj +1 TJm +(y) 5.9778 Tj +-426 TJm +(exists) 35.8668 Tj +-426 TJm +(after) 29.889 Tj +-426 TJm +(BZ2_bzCompressEnd) 101.623 Tj +-426 TJm +(or) 11.9556 Tj +98.488 687.721 Td +(before) 35.8668 Tj +-426 TJm +(BZ2_bzCompressInit) 107.6 Tj +1 TJm +(.) 5.9778 Tj +98.488 675.766 Td +(Return) 35.8668 Tj +-426 TJm +(value) 29.889 Tj +-426 TJm +(=) 5.9778 Tj +-426 TJm +(BZ_SEQUENC) 59.778 Tj +1 TJm +(E_ERROR) 41.8446 Tj +90 651.856 Td +(RUNNING/BZ_RUN) 83.6892 Tj +98.488 639.9 Td +(Compress) 47.8224 Tj +-426 TJm +(from) 23.9112 Tj +-426 TJm +(next_in) 41.8446 Tj +-426 TJm +(to) 11.9556 Tj +-425 TJm +(next_out) 47.8224 Tj +-426 TJm +(as) 11.9556 Tj +-426 TJm +(much) 23.9112 Tj +-426 TJm +(as) 11.9556 Tj +-426 TJm +(possible.) 53.8002 Tj +98.488 627.945 Td +(Next) 23.9112 Tj +-426 TJm +(state) 29.889 Tj +-426 TJm +(=) 5.9778 Tj +-426 TJm +(RUNNING) 41.8446 Tj +98.488 615.99 Td +(Return) 35.8668 Tj +-426 TJm +(value) 29.889 Tj +-426 TJm +(=) 5.9778 Tj +-426 TJm +(BZ_RUN_OK) 53.8002 Tj +90 592.08 Td +(RUNNING/BZ_FLUSH) 95.6448 Tj +98.488 580.124 Td +(Remember) 47.8224 Tj +-426 TJm +(current) 41.8446 Tj +-426 TJm +(value) 29.889 Tj +-426 TJm +(of) 11.9556 Tj +-425 TJm +(next_in.) 47.8224 Tj +-426 TJm +(Compress) 47.8224 Tj +-426 TJm +(from) 23.9112 Tj +-426 TJm +(next_in) 41.8446 Tj +98.488 568.169 Td +(to) 11.9556 Tj +-426 TJm +(next_out) 47.8224 Tj +-426 TJm +(as) 11.9556 Tj +-426 TJm +(much) 23.9112 Tj +-426 TJm +(as) 11.9556 Tj +-426 TJm +(p) 5.9778 Tj +1 TJm +(ossible,) 47.8224 Tj +-426 TJm +(but) 17.9334 Tj +-426 TJm +(do) 11.9556 Tj +-426 TJm +(not) 17.9334 Tj +-426 TJm +(accept) 35.8668 Tj +-426 TJm +(any) 17.9334 Tj +-426 TJm +(more) 23.9112 Tj +-426 TJm +(input.) 35.8668 Tj +98.488 556.214 Td +(Next) 23.9112 Tj +-426 TJm +(state) 29.889 Tj +-426 TJm +(=) 5.9778 Tj +-426 TJm +(FLUSHING) 47.8224 Tj +98.488 544.259 Td +(Return) 35.8668 Tj +-426 TJm +(value) 29.889 Tj +-426 TJm +(=) 5.9778 Tj +-426 TJm +(BZ_FLUSH_O) 59.778 Tj +1 TJm +(K) 5.9778 Tj +90 520.349 Td +(RUNNING/BZ_FINISH) 101.623 Tj +98.488 508.393 Td +(Remember) 47.8224 Tj +-426 TJm +(current) 41.8446 Tj +-426 TJm +(value) 29.889 Tj +-426 TJm +(of) 11.9556 Tj +-425 TJm +(next_in.) 47.8224 Tj +-426 TJm +(Compress) 47.8224 Tj +-426 TJm +(from) 23.9112 Tj +-426 TJm +(next_in) 41.8446 Tj +98.488 496.438 Td +(to) 11.9556 Tj +-426 TJm +(next_out) 47.8224 Tj +-426 TJm +(as) 11.9556 Tj +-426 TJm +(much) 23.9112 Tj +-426 TJm +(as) 11.9556 Tj +-426 TJm +(p) 5.9778 Tj +1 TJm +(ossible,) 47.8224 Tj +-426 TJm +(but) 17.9334 Tj +-426 TJm +(do) 11.9556 Tj +-426 TJm +(not) 17.9334 Tj +-426 TJm +(accept) 35.8668 Tj +-426 TJm +(any) 17.9334 Tj +-426 TJm +(more) 23.9112 Tj +-426 TJm +(input.) 35.8668 Tj +98.488 484.483 Td +(Next) 23.9112 Tj +-426 TJm +(state) 29.889 Tj +-426 TJm +(=) 5.9778 Tj +-426 TJm +(FINISHING) 53.8002 Tj +98.488 472.528 Td +(Return) 35.8668 Tj +-426 TJm +(value) 29.889 Tj +-426 TJm +(=) 5.9778 Tj +-426 TJm +(BZ_FINISH_) 59.778 Tj +1 TJm +(OK) 11.9556 Tj +90 448.618 Td +(FLUSHING/BZ_FLUSH) 101.623 Tj +98.488 436.662 Td +(Compress) 47.8224 Tj +-426 TJm +(from) 23.9112 Tj +-426 TJm +(next_in) 41.8446 Tj +-426 TJm +(to) 11.9556 Tj +-425 TJm +(next_out) 47.8224 Tj +-426 TJm +(as) 11.9556 Tj +-426 TJm +(much) 23.9112 Tj +-426 TJm +(as) 11.9556 Tj +-426 TJm +(possible,) 53.8002 Tj +98.488 424.707 Td +(but) 17.9334 Tj +-426 TJm +(do) 11.9556 Tj +-426 TJm +(not) 17.9334 Tj +-426 TJm +(accept) 35.8668 Tj +-426 TJm +(any) 17.9334 Tj +-426 TJm +(mo) 11.9556 Tj +1 TJm +(re) 11.9556 Tj +-426 TJm +(input.) 35.8668 Tj +98.488 412.752 Td +(If) 11.9556 Tj +-426 TJm +(all) 17.9334 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(existing) 47.8224 Tj +-426 TJm +(inpu) 23.9112 Tj +1 TJm +(t) 5.9778 Tj +-426 TJm +(has) 17.9334 Tj +-426 TJm +(been) 23.9112 Tj +-426 TJm +(used) 23.9112 Tj +-426 TJm +(up) 11.9556 Tj +-426 TJm +(and) 17.9334 Tj +-426 TJm +(all) 17.9334 Tj +-426 TJm +(compressed) 59.778 Tj +98.488 400.797 Td +(output) 35.8668 Tj +-426 TJm +(has) 17.9334 Tj +-426 TJm +(been) 23.9112 Tj +-426 TJm +(removed) 41.8446 Tj +106.976 388.842 Td +(Next) 23.9112 Tj +-426 TJm +(state) 29.889 Tj +-426 TJm +(=) 5.9778 Tj +-426 TJm +(RUNNING;) 47.8224 Tj +-426 TJm +(Re) 11.9556 Tj +1 TJm +(turn) 23.9112 Tj +-426 TJm +(value) 29.889 Tj +-426 TJm +(=) 5.9778 Tj +-426 TJm +(BZ_RUN_OK) 53.8002 Tj +98.488 376.887 Td +(else) 23.9112 Tj +106.976 364.931 Td +(Next) 23.9112 Tj +-426 TJm +(state) 29.889 Tj +-426 TJm +(=) 5.9778 Tj +-426 TJm +(FLUSHING;) 53.8002 Tj +-426 TJm +(R) 5.9778 Tj +1 TJm +(eturn) 29.889 Tj +-426 TJm +(value) 29.889 Tj +-426 TJm +(=) 5.9778 Tj +-426 TJm +(BZ_FLUSH_OK) 65.7558 Tj +90 341.021 Td +(FLUSHING/other) 83.6892 Tj +98.488 329.066 Td +(Illegal.) 47.8224 Tj +98.488 317.111 Td +(Return) 35.8668 Tj +-426 TJm +(value) 29.889 Tj +-426 TJm +(=) 5.9778 Tj +-426 TJm +(BZ_SEQUENC) 59.778 Tj +1 TJm +(E_ERROR) 41.8446 Tj +90 293.2 Td +(FINISHING/BZ_FINISH) 113.578 Tj +98.488 281.245 Td +(Compress) 47.8224 Tj +-426 TJm +(from) 23.9112 Tj +-426 TJm +(next_in) 41.8446 Tj +-426 TJm +(to) 11.9556 Tj +-425 TJm +(next_out) 47.8224 Tj +-426 TJm +(as) 11.9556 Tj +-426 TJm +(much) 23.9112 Tj +-426 TJm +(as) 11.9556 Tj +-426 TJm +(possible,) 53.8002 Tj +98.488 269.29 Td +(but) 17.9334 Tj +-426 TJm +(to) 11.9556 Tj +-426 TJm +(not) 17.9334 Tj +-426 TJm +(accept) 35.8668 Tj +-426 TJm +(any) 17.9334 Tj +-426 TJm +(mo) 11.9556 Tj +1 TJm +(re) 11.9556 Tj +-426 TJm +(input.) 35.8668 Tj +98.488 257.335 Td +(If) 11.9556 Tj +-426 TJm +(all) 17.9334 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(existing) 47.8224 Tj +-426 TJm +(inpu) 23.9112 Tj +1 TJm +(t) 5.9778 Tj +-426 TJm +(has) 17.9334 Tj +-426 TJm +(been) 23.9112 Tj +-426 TJm +(used) 23.9112 Tj +-426 TJm +(up) 11.9556 Tj +-426 TJm +(and) 17.9334 Tj +-426 TJm +(all) 17.9334 Tj +-426 TJm +(compressed) 59.778 Tj +98.488 245.38 Td +(output) 35.8668 Tj +-426 TJm +(has) 17.9334 Tj +-426 TJm +(been) 23.9112 Tj +-426 TJm +(removed) 41.8446 Tj +106.976 233.424 Td +(Next) 23.9112 Tj +-426 TJm +(state) 29.889 Tj +-426 TJm +(=) 5.9778 Tj +-426 TJm +(IDLE;) 29.889 Tj +-426 TJm +(Retur) 29.889 Tj +1 TJm +(n) 5.9778 Tj +-426 TJm +(value) 29.889 Tj +-426 TJm +(=) 5.9778 Tj +-426 TJm +(BZ_STREAM_END) 77.7114 Tj +98.488 221.469 Td +(else) 23.9112 Tj +106.976 209.514 Td +(Next) 23.9112 Tj +-426 TJm +(state) 29.889 Tj +-426 TJm +(=) 5.9778 Tj +-426 TJm +(FINISHING;) 59.778 Tj +-425 TJm +(Return) 35.8668 Tj +-426 TJm +(value) 29.889 Tj +-426 TJm +(=) 5.9778 Tj +-426 TJm +(BZ_FINISHING) 71.7336 Tj +90 185.604 Td +(FINISHING/other) 89.667 Tj +98.488 173.649 Td +(Illegal.) 47.8224 Tj +98.488 161.693 Td +(Return) 35.8668 Tj +-426 TJm +(value) 29.889 Tj +-426 TJm +(=) 5.9778 Tj +-426 TJm +(BZ_SEQUENC) 59.778 Tj +1 TJm +(E_ERROR) 41.8446 Tj +[1 0 0 1 72 146.152] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.55] cm +0 g +0 G +[1 0 0 1 -72 -136.189] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 124.234 Td +/F128_0 9.963 Tf +(That) 18.2622 Tj +-250 TJm +(still) 14.9545 Tj +-250 TJm +(looks) 21.5898 Tj +-250 TJm +(complicate) 43.7176 Tj +1 TJm +(d?) 9.40507 Tj +-620 TJm +(W) 9.40507 Tj +80 TJm +(ell,) 12.4538 Tj +-250 TJm +(f) 3.31768 Tj +10 TJm +(air) 10.511 Tj +-250 TJm +(enough.) 31.8218 Tj +-620 TJm +(The) 15.4925 Tj +-250 TJm +(usual) 21.0319 Tj +-250 TJm +(sequence) 36.5144 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(calls) 18.2622 Tj +-250 TJm +(for) 11.6169 Tj +-250 TJm +(com) 17.1563 Tj +1 TJm +(pressing) 33.2067 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(load) 17.1563 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(data) 16.5984 Tj +-250 TJm +(is:) 9.41504 Tj +[1 0 0 1 72 122.077] cm +0 g +0 G +[1 0 0 1 0 -29.723] cm +0 g +0 G +[1 0 0 1 7.372 0] cm +0 g +0 G +[1 0 0 1 -79.372 -92.354] cm +[1 0 0 1 0 0] Tm +0 0 Td +79.372 92.354 Td +/F128_0 9.963 Tf +(1.) 7.47225 Tj +[1 0 0 1 86.844 92.354] cm +0 g +0 G +[1 0 0 1 3.089 0] cm +0 g +0 G +[1 0 0 1 1.992 0] cm +0 g +0 G +[1 0 0 1 -91.925 -92.354] cm +[1 0 0 1 0 0] Tm +0 0 Td +91.925 92.354 Td +/F128_0 9.963 Tf +(Get) 14.3866 Tj +-250 TJm +(started) 26.5614 Tj +-250 TJm +(with) 17.7142 Tj +[1 0 0 1 158.056 92.354] cm +0 g +0 G +[1 0 0 1 -158.056 -92.354] cm +[1 0 0 1 0 0] Tm +0 0 Td +158.056 92.354 Td +/F130_0 9.963 Tf +(BZ2_bzCompressInit) 107.6 Tj +[1 0 0 1 265.653 92.354] cm +0 g +0 G +[1 0 0 1 -265.653 -92.354] cm +[1 0 0 1 0 0] Tm +0 0 Td +265.653 92.354 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 268.144 92.354] cm +0 g +0 G +[1 0 0 1 -196.144 -41.502] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.854] cm +0 g +0 G +0 g +0 G +[1 0 0 1 40.572 -6.755] cm +0 g +0 G +[1 0 0 1 -493.841 -50.951] cm +[1 0 0 1 0 0] Tm +0 0 Td +534.414 50.951 Td +/F128_0 9.963 Tf +(15) 9.963 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 19 19 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 -8.911] cm +0 g +0 G +[1 0 0 1 0 8.911] cm +0 g +0 G +0 g +0 G +[1 0 0 1 84.08 -6.755] cm +0 g +0 G +[1 0 0 1 -350.151 -749.245] cm +[1 0 0 1 0 0] Tm +0 0 Td +434.231 749.245 Td +/F128_0 9.963 Tf +(Programming) 54.7965 Tj +-250 TJm +(with) 17.7142 Tj +-250 TJm +(libbzip2) 32.6587 Tj +[1 0 0 1 266.071 747.089] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -5.037] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -468 -31.517] cm +0 g +0 G +[1 0 0 1 7.372 0] cm +0 g +0 G +[1 0 0 1 -79.372 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +79.372 710.037 Td +/F128_0 9.963 Tf +(2.) 7.47225 Tj +[1 0 0 1 86.844 710.037] cm +0 g +0 G +[1 0 0 1 3.089 0] cm +0 g +0 G +[1 0 0 1 1.992 0] cm +0 g +0 G +[1 0 0 1 -91.925 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +91.925 710.037 Td +/F128_0 9.963 Tf +(Sho) 15.5024 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(el) 7.19329 Tj +-240 TJm +(data) 16.5984 Tj +-240 TJm +(in) 7.75121 Tj +-240 TJm +(and) 14.3866 Tj +-241 TJm +(shlur) 19.926 Tj +1 TJm +(p) 4.9815 Tj +-241 TJm +(out) 12.7327 Tj +-240 TJm +(its) 9.41504 Tj +-240 TJm +(compressed) 47.0353 Tj +-240 TJm +(form) 19.3681 Tj +-240 TJm +(using) 21.5898 Tj +-240 TJm +(zero) 17.1463 Tj +-240 TJm +(or) 8.29918 Tj +-241 TJm +(m) 7.75121 Tj +1 TJm +(ore) 12.7228 Tj +-241 TJm +(calls) 18.2622 Tj +-240 TJm +(of) 8.29918 Tj +[1 0 0 1 401.454 710.037] cm +0 g +0 G +[1 0 0 1 -401.454 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +401.454 710.037 Td +/F130_0 9.963 Tf +(BZ2_bzCompress) 83.6892 Tj +[1 0 0 1 485.14 710.037] cm +0 g +0 G +[1 0 0 1 -485.14 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +487.533 710.037 Td +/F128_0 9.963 Tf +(with) 17.7142 Tj +-240 TJm +(action) 24.3496 Tj +-240 TJm +(=) 5.61913 Tj +[1 0 0 1 91.925 698.082] cm +0 g +0 G +[1 0 0 1 -91.925 -698.082] cm +[1 0 0 1 0 0] Tm +0 0 Td +91.925 698.082 Td +/F130_0 9.963 Tf +(BZ_RUN) 35.8668 Tj +[1 0 0 1 127.791 698.082] cm +0 g +0 G +[1 0 0 1 -127.791 -698.082] cm +[1 0 0 1 0 0] Tm +0 0 Td +127.791 698.082 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 130.281 698.082] cm +0 g +0 G +[1 0 0 1 -58.281 -21.918] cm +0 g +0 G +[1 0 0 1 7.372 0] cm +0 g +0 G +[1 0 0 1 -79.372 -676.164] cm +[1 0 0 1 0 0] Tm +0 0 Td +79.372 676.164 Td +/F128_0 9.963 Tf +(3.) 7.47225 Tj +[1 0 0 1 86.844 676.164] cm +0 g +0 G +[1 0 0 1 3.089 0] cm +0 g +0 G +[1 0 0 1 1.992 0] cm +0 g +0 G +[1 0 0 1 -91.925 -676.164] cm +[1 0 0 1 0 0] Tm +0 0 Td +91.925 676.164 Td +/F128_0 9.963 Tf +(Finish) 24.9175 Tj +-242 TJm +(up) 9.963 Tj +1 TJm +(.) 2.49075 Tj +-308 TJm +(Repeatedl) 39.842 Tj +1 TJm +(y) 4.9815 Tj +-242 TJm +(call) 14.3866 Tj +[1 0 0 1 198.784 676.164] cm +0 g +0 G +[1 0 0 1 -198.784 -676.164] cm +[1 0 0 1 0 0] Tm +0 0 Td +198.784 676.164 Td +/F130_0 9.963 Tf +(BZ2_bzCompress) 83.6892 Tj +[1 0 0 1 282.471 676.164] cm +0 g +0 G +[1 0 0 1 -282.471 -676.164] cm +[1 0 0 1 0 0] Tm +0 0 Td +284.878 676.164 Td +/F128_0 9.963 Tf +(with) 17.7142 Tj +-242 TJm +(ac) 8.84714 Tj +1 TJm +(tion) 15.5024 Tj +-242 TJm +(=) 5.61913 Tj +[1 0 0 1 339.78 676.164] cm +0 g +0 G +[1 0 0 1 -339.78 -676.164] cm +[1 0 0 1 0 0] Tm +0 0 Td +339.78 676.164 Td +/F130_0 9.963 Tf +(BZ_FINISH) 53.8002 Tj +[1 0 0 1 393.579 676.164] cm +0 g +0 G +[1 0 0 1 -393.579 -676.164] cm +[1 0 0 1 0 0] Tm +0 0 Td +393.579 676.164 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-242 TJm +(cop) 14.3866 Tj +10 TJm +(yi) 7.75121 Tj +1 TJm +(ng) 9.963 Tj +-242 TJm +(out) 12.7327 Tj +-242 TJm +(the) 12.1748 Tj +-241 TJm +(compressed) 47.0353 Tj +-242 TJm +(output,) 27.9562 Tj +91.925 664.209 Td +(until) 18.2721 Tj +[1 0 0 1 112.687 664.209] cm +0 g +0 G +[1 0 0 1 -112.687 -664.209] cm +[1 0 0 1 0 0] Tm +0 0 Td +112.687 664.209 Td +/F130_0 9.963 Tf +(BZ_STREAM_END) 77.7114 Tj +[1 0 0 1 190.396 664.209] cm +0 g +0 G +[1 0 0 1 -190.396 -664.209] cm +[1 0 0 1 0 0] Tm +0 0 Td +192.886 664.209 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-250 TJm +(returned.) 35.6875 Tj +[1 0 0 1 237.708 664.209] cm +0 g +0 G +[1 0 0 1 -165.708 -21.918] cm +0 g +0 G +[1 0 0 1 7.372 0] cm +0 g +0 G +[1 0 0 1 -79.372 -642.291] cm +[1 0 0 1 0 0] Tm +0 0 Td +79.372 642.291 Td +/F128_0 9.963 Tf +(4.) 7.47225 Tj +[1 0 0 1 86.844 642.291] cm +0 g +0 G +[1 0 0 1 3.089 0] cm +0 g +0 G +[1 0 0 1 1.992 0] cm +0 g +0 G +[1 0 0 1 -91.925 -642.291] cm +[1 0 0 1 0 0] Tm +0 0 Td +91.925 642.291 Td +/F128_0 9.963 Tf +(Close) 22.6957 Tj +-250 TJm +(up) 9.963 Tj +-250 TJm +(and) 14.3866 Tj +-250 TJm +(go) 9.963 Tj +-250 TJm +(home.) 24.6285 Tj +-620 TJm +(Call) 16.6083 Tj +[1 0 0 1 208.796 642.291] cm +0 g +0 G +[1 0 0 1 -208.796 -642.291] cm +[1 0 0 1 0 0] Tm +0 0 Td +208.796 642.291 Td +/F130_0 9.963 Tf +(BZ2_bzCompressEnd) 101.623 Tj +[1 0 0 1 310.415 642.291] cm +0 g +0 G +[1 0 0 1 -310.415 -642.291] cm +[1 0 0 1 0 0] Tm +0 0 Td +310.415 642.291 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 312.906 642.291] cm +0 g +0 G +[1 0 0 1 -240.906 -12.119] cm +0 g +0 G +[1 0 0 1 -72 -630.172] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 620.374 Td +/F128_0 9.963 Tf +(If) 6.63536 Tj +-269 TJm +(the) 12.1748 Tj +-270 TJm +(data) 16.5984 Tj +-269 TJm +(you) 14.9445 Tj +-270 TJm +(w) 7.19329 Tj +10 TJm +(ant) 12.1748 Tj +-269 TJm +(to) 7.75121 Tj +-269 TJm +(compress) 37.6303 Tj +-270 TJm +(\002ts) 12.1847 Tj +-269 TJm +(into) 15.5024 Tj +-270 TJm +(you) 14.9445 Tj +1 TJm +(r) 3.31768 Tj +-270 TJm +(input) 20.4839 Tj +-269 TJm +(b) 4.9815 Tj +20 TJm +(uf) 8.29918 Tj +25 TJm +(fer) 11.0589 Tj +-270 TJm +(all) 9.963 Tj +-269 TJm +(at) 7.19329 Tj +-270 TJm +(on) 9.963 Tj +1 TJm +(ce,) 11.3379 Tj +-275 TJm +(you) 14.9445 Tj +-269 TJm +(can) 13.8286 Tj +-270 TJm +(skip) 16.6083 Tj +-269 TJm +(the) 12.1748 Tj +-269 TJm +(calls) 18.2622 Tj +-270 TJm +(of) 8.29918 Tj +[1 0 0 1 456.314 620.374] cm +0 g +0 G +[1 0 0 1 -456.314 -620.374] cm +[1 0 0 1 0 0] Tm +0 0 Td +456.314 620.374 Td +/F130_0 9.963 Tf +(BZ2_bzCompress) 83.6892 Tj +72 608.418 Td +(\() 5.9778 Tj +-600 TJm +(...,) 23.9112 Tj +-600 TJm +(BZ_RUN) 35.8668 Tj +-600 TJm +(\)) 5.9778 Tj +[1 0 0 1 161.664 608.418] cm +0 g +0 G +[1 0 0 1 -161.664 -608.418] cm +[1 0 0 1 0 0] Tm +0 0 Td +164.154 608.418 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +-250 TJm +(just) 14.3965 Tj +-250 TJm +(do) 9.963 Tj +-250 TJm +(the) 12.1748 Tj +[1 0 0 1 225.036 608.418] cm +0 g +0 G +[1 0 0 1 -225.036 -608.418] cm +[1 0 0 1 0 0] Tm +0 0 Td +225.036 608.418 Td +/F130_0 9.963 Tf +(BZ2_bzCompress) 83.6892 Tj +-600 TJm +(\() 5.9778 Tj +-600 TJm +(...,) 23.9112 Tj +-600 TJm +(B) 5.9778 Tj +1 TJm +(Z_FINISH) 47.8224 Tj +-600 TJm +(\)) 5.9778 Tj +[1 0 0 1 422.296 608.418] cm +0 g +0 G +[1 0 0 1 -422.296 -608.418] cm +[1 0 0 1 0 0] Tm +0 0 Td +424.786 608.418 Td +/F128_0 9.963 Tf +(calls.) 20.7529 Tj +[1 0 0 1 72 606.262] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -596.299] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 586.501 Td +/F128_0 9.963 Tf +(All) 12.7327 Tj +-277 TJm +(required) 33.1967 Tj +-278 TJm +(memory) 33.2067 Tj +-277 TJm +(is) 6.64532 Tj +-278 TJm +(allocated) 35.9664 Tj +-277 TJm +(by) 9.963 Tj +[1 0 0 1 220.295 586.501] cm +0 g +0 G +[1 0 0 1 -220.295 -586.501] cm +[1 0 0 1 0 0] Tm +0 0 Td +220.295 586.501 Td +/F130_0 9.963 Tf +(BZ2_bzCompressInit) 107.6 Tj +[1 0 0 1 327.891 586.501] cm +0 g +0 G +[1 0 0 1 -327.891 -586.501] cm +[1 0 0 1 0 0] Tm +0 0 Td +327.891 586.501 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +-785 TJm +(The) 15.4925 Tj +-278 TJm +(compression) 50.363 Tj +-277 TJm +(library) 26.5614 Tj +-277 TJm +(can) 13.8286 Tj +-278 TJm +(accept) 25.4455 Tj +-277 TJm +(an) 9.40507 Tj +15 TJm +(y) 4.9815 Tj +-278 TJm +(data) 16.5984 Tj +-277 TJm +(at) 7.19329 Tj +-278 TJm +(all) 9.963 Tj +72 574.545 Td +(\(ob) 13.2807 Tj +15 TJm +(viously\).) 35.1495 Tj +-612 TJm +(So) 10.5209 Tj +-237 TJm +(you) 14.9445 Tj +-238 TJm +(shouldn') 34.8705 Tj +18 TJm +(t) 2.76971 Tj +-238 TJm +(ge) 9.40507 Tj +1 TJm +(t) 2.76971 Tj +-238 TJm +(an) 9.40507 Tj +15 TJm +(y) 4.9815 Tj +-238 TJm +(error) 19.3581 Tj +-238 TJm +(r) 3.31768 Tj +1 TJm +(eturn) 20.474 Tj +-238 TJm +(v) 4.9815 Tj +25 TJm +(alues) 20.474 Tj +-238 TJm +(from) 19.3681 Tj +-237 TJm +(the) 12.1748 Tj +[1 0 0 1 339.287 574.545] cm +0 g +0 G +[1 0 0 1 -339.287 -574.545] cm +[1 0 0 1 0 0] Tm +0 0 Td +339.287 574.545 Td +/F130_0 9.963 Tf +(BZ2_bzCompress) 83.6892 Tj +[1 0 0 1 422.973 574.545] cm +0 g +0 G +[1 0 0 1 -422.973 -574.545] cm +[1 0 0 1 0 0] Tm +0 0 Td +425.342 574.545 Td +/F128_0 9.963 Tf +(calls.) 20.7529 Tj +-612 TJm +(If) 6.63536 Tj +-237 TJm +(you) 14.9445 Tj +-238 TJm +(do,) 12.4538 Tj +-240 TJm +(the) 12.1748 Tj +15 TJm +(y) 4.9815 Tj +-238 TJm +(will) 15.5024 Tj +-237 TJm +(be) 9.40507 Tj +[1 0 0 1 72 562.59] cm +0 g +0 G +[1 0 0 1 -72 -562.59] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 562.59 Td +/F130_0 9.963 Tf +(BZ_SEQUENCE_ERROR) 101.623 Tj +[1 0 0 1 173.619 562.59] cm +0 g +0 G +[1 0 0 1 -173.619 -562.59] cm +[1 0 0 1 0 0] Tm +0 0 Td +173.619 562.59 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-250 TJm +(and) 14.3866 Tj +-250 TJm +(indicate) 31.5429 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(b) 4.9815 Tj +20 TJm +(ug) 9.963 Tj +-250 TJm +(in) 7.75121 Tj +-250 TJm +(your) 18.2622 Tj +-250 TJm +(prog) 18.2622 Tj +1 TJm +(ramming.) 38.4671 Tj +[1 0 0 1 72 560.433] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -550.471] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 540.672 Td +/F128_0 9.963 Tf +(T) 6.08739 Tj +35 TJm +(ri) 6.08739 Tj +25 TJm +(vial) 14.9445 Tj +-250 TJm +(other) 20.474 Tj +-250 TJm +(possible) 32.6587 Tj +-250 TJm +(return) 23.7916 Tj +-249 TJm +(v) 4.9815 Tj +25 TJm +(alues:) 23.2437 Tj +[1 0 0 1 72 538.516] cm +0 g +0 G +[1 0 0 1 0 -36.862] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 35.866 re +f +Q +0 g +0 G +[1 0 0 1 0 3.586] cm +0 g +0 G +[1 0 0 1 0 32.279] cm +0 g +0 G +[1 0 0 1 18 -8.368] cm +0 g +0 G +[1 0 0 1 -90 -529.151] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 529.151 Td +/F130_0 9.963 Tf +(BZ_PARAM_ERROR) 83.6892 Tj +98.488 517.196 Td +(if) 11.9556 Tj +-426 TJm +(strm) 23.9112 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(NULL,) 29.889 Tj +-426 TJm +(or) 11.9556 Tj +-426 TJm +(strm) 23.9112 Tj +1 TJm +(->s) 17.9334 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(NULL) 23.9112 Tj +[1 0 0 1 72 501.654] cm +0 g +0 G +[1 0 0 1 468 3.586] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -3.586] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -491.691] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 471.033 Td +/F121_0 17.215 Tf +(3.3.3.) 43.0719 Tj +[1 0 0 1 119.858 471.033] cm +0 g +0 G +[1 0 0 1 -119.858 -471.033] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.858 471.033 Td +/F387_0 17.215 Tf +(BZ2_bzCompressEnd) 175.593 Tj +[1 0 0 1 295.455 471.033] cm +0 g +0 G +[1 0 0 1 -223.455 -2.333] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -24.907] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 23.91 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 20.324] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -459.335] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 459.335 Td +/F130_0 9.963 Tf +(int) 17.9334 Tj +-426 TJm +(BZ2_bzCompressEnd) 101.623 Tj +-426 TJm +(\() 5.9778 Tj +-426 TJm +(b) 5.9778 Tj +1 TJm +(z_stream) 47.8224 Tj +-426 TJm +(*strm) 29.889 Tj +-426 TJm +(\);) 11.9556 Tj +[1 0 0 1 72 443.793] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.549] cm +0 g +0 G +[1 0 0 1 -72 -433.831] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 421.876 Td +/F128_0 9.963 Tf +(Releases) 34.8605 Tj +-250 TJm +(all) 9.963 Tj +-250 TJm +(memory) 33.2067 Tj +-250 TJm +(assoc) 21.5799 Tj +1 TJm +(iated) 19.3681 Tj +-250 TJm +(with) 17.7142 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(compression) 50.363 Tj +-250 TJm +(stream.) 29.0521 Tj +[1 0 0 1 72 419.719] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -409.756] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 399.958 Td +/F128_0 9.963 Tf +(Possible) 33.2166 Tj +-250 TJm +(return) 23.7916 Tj +-250 TJm +(v) 4.9815 Tj +25 TJm +(alues:) 23.2437 Tj +[1 0 0 1 72 399.858] cm +0 g +0 G +[1 0 0 1 0 -36.861] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 35.866 re +f +Q +0 g +0 G +[1 0 0 1 0 3.586] cm +0 g +0 G +[1 0 0 1 0 32.279] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -390.493] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 390.493 Td +/F130_0 9.963 Tf +(BZ_PARAM_ERROR) 83.6892 Tj +-852 TJm +(if) 11.9556 Tj +-426 TJm +(strm) 23.9112 Tj +-425 TJm +(is) 11.9556 Tj +-426 TJm +(NULL) 23.9112 Tj +-426 TJm +(or) 11.9556 Tj +-426 TJm +(strm->s) 41.8446 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(NULL) 23.9112 Tj +90 378.538 Td +(BZ_OK) 29.889 Tj +-4686 TJm +(otherw) 35.8668 Tj +1 TJm +(ise) 17.9334 Tj +[1 0 0 1 72 362.997] cm +0 g +0 G +[1 0 0 1 468 3.586] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -3.586] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -353.034] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 332.375 Td +/F121_0 17.215 Tf +(3.3.4.) 43.0719 Tj +[1 0 0 1 119.858 332.375] cm +0 g +0 G +[1 0 0 1 -119.858 -332.375] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.858 332.375 Td +/F387_0 17.215 Tf +(BZ2_bzDecompressInit) 206.58 Tj +[1 0 0 1 326.443 332.375] cm +0 g +0 G +[1 0 0 1 -254.443 -2.332] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -24.907] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 23.91 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 20.323] cm +0 g +0 G +[1 0 0 1 18 -8.368] cm +0 g +0 G +[1 0 0 1 -90 -320.678] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 320.678 Td +/F130_0 9.963 Tf +(int) 17.9334 Tj +-426 TJm +(BZ2_bzDecompressInit) 119.556 Tj +-425 TJm +(\() 5.9778 Tj +-426 TJm +(bz_stream) 53.8002 Tj +-426 TJm +(*strm,) 35.8668 Tj +-426 TJm +(int) 17.9334 Tj +-426 TJm +(verbosity,) 59.778 Tj +-426 TJm +(int) 17.9334 Tj +-426 TJm +(small) 29.889 Tj +-426 TJm +(\);) 11.9556 Tj +[1 0 0 1 72 305.136] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.55] cm +0 g +0 G +[1 0 0 1 -72 -295.173] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 283.218 Td +/F128_0 9.963 Tf +(Prepares) 34.3026 Tj +-351 TJm +(for) 11.6169 Tj +-351 TJm +(decompression.) 62.2588 Tj +-1227 TJm +(As) 11.0689 Tj +-351 TJm +(with) 17.7142 Tj +[1 0 0 1 235.177 283.218] cm +0 g +0 G +[1 0 0 1 -235.177 -283.218] cm +[1 0 0 1 0 0] Tm +0 0 Td +235.177 283.218 Td +/F130_0 9.963 Tf +(BZ2_bzCompressInit) 107.6 Tj +[1 0 0 1 342.773 283.218] cm +0 g +0 G +[1 0 0 1 -342.773 -283.218] cm +[1 0 0 1 0 0] Tm +0 0 Td +342.773 283.218 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-377 TJm +(a) 4.42357 Tj +[1 0 0 1 356.937 283.218] cm +0 g +0 G +[1 0 0 1 -356.937 -283.218] cm +[1 0 0 1 0 0] Tm +0 0 Td +356.937 283.218 Td +/F130_0 9.963 Tf +(bz_stream) 53.8002 Tj +[1 0 0 1 410.736 283.218] cm +0 g +0 G +[1 0 0 1 -410.736 -283.218] cm +[1 0 0 1 0 0] Tm +0 0 Td +414.234 283.218 Td +/F128_0 9.963 Tf +(record) 25.4455 Tj +-351 TJm +(should) 26.5713 Tj +-351 TJm +(be) 9.40507 Tj +-351 TJm +(allocated) 35.9664 Tj +-351 TJm +(and) 14.3866 Tj +72 271.263 Td +(initialised) 39.304 Tj +-305 TJm +(before) 25.4455 Tj +-306 TJm +(the) 12.1748 Tj +-305 TJm +(call.) 16.8773 Tj +-954 TJm +(Fields) 24.3595 Tj +[1 0 0 1 211.833 271.263] cm +0 g +0 G +[1 0 0 1 -211.833 -271.263] cm +[1 0 0 1 0 0] Tm +0 0 Td +211.833 271.263 Td +/F130_0 9.963 Tf +(bzalloc) 41.8446 Tj +[1 0 0 1 253.676 271.263] cm +0 g +0 G +[1 0 0 1 -253.676 -271.263] cm +[1 0 0 1 0 0] Tm +0 0 Td +253.676 271.263 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 259.35 271.263] cm +0 g +0 G +[1 0 0 1 -259.35 -271.263] cm +[1 0 0 1 0 0] Tm +0 0 Td +259.35 271.263 Td +/F130_0 9.963 Tf +(bzfree) 35.8668 Tj +[1 0 0 1 295.215 271.263] cm +0 g +0 G +[1 0 0 1 -295.215 -271.263] cm +[1 0 0 1 0 0] Tm +0 0 Td +298.26 271.263 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 315.69 271.263] cm +0 g +0 G +[1 0 0 1 -315.69 -271.263] cm +[1 0 0 1 0 0] Tm +0 0 Td +315.69 271.263 Td +/F130_0 9.963 Tf +(opaque) 35.8668 Tj +[1 0 0 1 351.556 271.263] cm +0 g +0 G +[1 0 0 1 -351.556 -271.263] cm +[1 0 0 1 0 0] Tm +0 0 Td +354.6 271.263 Td +/F128_0 9.963 Tf +(should) 26.5713 Tj +-305 TJm +(be) 9.40507 Tj +-306 TJm +(set) 11.0689 Tj +-306 TJm +(if) 6.08739 Tj +-305 TJm +(a) 4.42357 Tj +-306 TJm +(custom) 28.7831 Tj +-305 TJm +(memory) 33.2067 Tj +-306 TJm +(al) 7.19329 Tj +1 TJm +(locator) 27.6673 Tj +-306 TJm +(is) 6.64532 Tj +72 259.308 Td +(required,) 35.6875 Tj +-350 TJm +(or) 8.29918 Tj +-330 TJm +(made) 21.5799 Tj +[1 0 0 1 147.635 259.308] cm +0 g +0 G +[1 0 0 1 -147.635 -259.308] cm +[1 0 0 1 0 0] Tm +0 0 Td +147.635 259.308 Td +/F130_0 9.963 Tf +(NULL) 23.9112 Tj +[1 0 0 1 171.546 259.308] cm +0 g +0 G +[1 0 0 1 -171.546 -259.308] cm +[1 0 0 1 0 0] Tm +0 0 Td +174.836 259.308 Td +/F128_0 9.963 Tf +(for) 11.6169 Tj +-330 TJm +(the) 12.1748 Tj +-330 TJm +(normal) 28.2252 Tj +[1 0 0 1 236.722 259.308] cm +0 g +0 G +[1 0 0 1 -236.722 -259.308] cm +[1 0 0 1 0 0] Tm +0 0 Td +236.722 259.308 Td +/F130_0 9.963 Tf +(malloc) 35.8668 Tj +[1 0 0 1 272.587 259.308] cm +0 g +0 G +[1 0 0 1 -272.587 -259.308] cm +[1 0 0 1 0 0] Tm +0 0 Td +275.878 259.308 Td +/F128_0 9.963 Tf +(/) 2.76971 Tj +[1 0 0 1 281.938 259.308] cm +0 g +0 G +[1 0 0 1 -281.938 -259.308] cm +[1 0 0 1 0 0] Tm +0 0 Td +281.938 259.308 Td +/F130_0 9.963 Tf +(free) 23.9112 Tj +[1 0 0 1 305.848 259.308] cm +0 g +0 G +[1 0 0 1 -305.848 -259.308] cm +[1 0 0 1 0 0] Tm +0 0 Td +309.139 259.308 Td +/F128_0 9.963 Tf +(routines.) 34.5915 Tj +-1102 TJm +(Upo) 17.1563 Tj +1 TJm +(n) 4.9815 Tj +-331 TJm +(return,) 26.2824 Tj +-350 TJm +(the) 12.1748 Tj +-330 TJm +(internal) 30.437 Tj +-330 TJm +(state) 18.2622 Tj +-331 TJm +(wi) 9.963 Tj +1 TJm +(ll) 5.53943 Tj +-331 TJm +(ha) 9.40507 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-330 TJm +(been) 18.8101 Tj +72 247.353 Td +(initialised,) 41.7948 Tj +-250 TJm +(and) 14.3866 Tj +[1 0 0 1 133.16 247.353] cm +0 g +0 G +[1 0 0 1 -133.16 -247.353] cm +[1 0 0 1 0 0] Tm +0 0 Td +133.16 247.353 Td +/F130_0 9.963 Tf +(total_in) 47.8224 Tj +[1 0 0 1 180.98 247.353] cm +0 g +0 G +[1 0 0 1 -180.98 -247.353] cm +[1 0 0 1 0 0] Tm +0 0 Td +183.471 247.353 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 200.348 247.353] cm +0 g +0 G +[1 0 0 1 -200.348 -247.353] cm +[1 0 0 1 0 0] Tm +0 0 Td +200.348 247.353 Td +/F130_0 9.963 Tf +(total_out) 53.8002 Tj +[1 0 0 1 254.146 247.353] cm +0 g +0 G +[1 0 0 1 -254.146 -247.353] cm +[1 0 0 1 0 0] Tm +0 0 Td +256.637 247.353 Td +/F128_0 9.963 Tf +(will) 15.5024 Tj +-250 TJm +(be) 9.40507 Tj +-250 TJm +(zero.) 19.6371 Tj +[1 0 0 1 72 245.913] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -235.951] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 225.435 Td +/F128_0 9.963 Tf +(F) 5.53943 Tj +15 TJm +(or) 8.29918 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(meaning) 34.3126 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(parameter) 39.8321 Tj +[1 0 0 1 192.756 225.435] cm +0 g +0 G +[1 0 0 1 -192.756 -225.435] cm +[1 0 0 1 0 0] Tm +0 0 Td +192.756 225.435 Td +/F130_0 9.963 Tf +(verbosity) 53.8002 Tj +[1 0 0 1 246.554 225.435] cm +0 g +0 G +[1 0 0 1 -246.554 -225.435] cm +[1 0 0 1 0 0] Tm +0 0 Td +246.554 225.435 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-250 TJm +(see) 12.7228 Tj +[1 0 0 1 266.748 225.435] cm +0 g +0 G +[1 0 0 1 -266.748 -225.435] cm +[1 0 0 1 0 0] Tm +0 0 Td +266.748 225.435 Td +/F130_0 9.963 Tf +(BZ2_bzCompressInit) 107.6 Tj +[1 0 0 1 374.345 225.435] cm +0 g +0 G +[1 0 0 1 -374.345 -225.435] cm +[1 0 0 1 0 0] Tm +0 0 Td +374.345 225.435 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 72 223.278] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -213.316] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 203.517 Td +/F128_0 9.963 Tf +(If) 6.63536 Tj +[1 0 0 1 81.497 203.517] cm +0 g +0 G +[1 0 0 1 -81.497 -203.517] cm +[1 0 0 1 0 0] Tm +0 0 Td +81.497 203.517 Td +/F130_0 9.963 Tf +(small) 29.889 Tj +[1 0 0 1 111.385 203.517] cm +0 g +0 G +[1 0 0 1 -111.385 -203.517] cm +[1 0 0 1 0 0] Tm +0 0 Td +114.248 203.517 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-287 TJm +(nonzero,) 34.5816 Tj +-297 TJm +(the) 12.1748 Tj +-287 TJm +(library) 26.5614 Tj +-287 TJm +(will) 15.5024 Tj +-287 TJm +(use) 13.2807 Tj +-288 TJm +(an) 9.40507 Tj +-287 TJm +(alternati) 32.6488 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-287 TJm +(decompression) 59.768 Tj +-287 TJm +(algorithm) 38.7461 Tj +-287 TJm +(which) 24.3496 Tj +-287 TJm +(uses) 17.1563 Tj +-288 TJm +(less) 14.9445 Tj +-287 TJm +(memory) 33.2067 Tj +-287 TJm +(b) 4.9815 Tj +20 TJm +(ut) 7.75121 Tj +-287 TJm +(at) 7.19329 Tj +-287 TJm +(the) 12.1748 Tj +72 191.562 Td +(cost) 16.0504 Tj +-289 TJm +(of) 8.29918 Tj +-290 TJm +(deco) 18.8101 Tj +1 TJm +(mpressing) 40.9579 Tj +-290 TJm +(more) 20.474 Tj +-289 TJm +(slo) 11.6268 Tj +25 TJm +(wly) 14.9445 Tj +-289 TJm +(\(roughly) 34.3126 Tj +-289 TJm +(speaking,) 37.9092 Tj +-299 TJm +(half) 15.4925 Tj +-290 TJm +(the) 12.1748 Tj +-289 TJm +(speed,) 25.1765 Tj +-299 TJm +(b) 4.9815 Tj +20 TJm +(ut) 7.75121 Tj +-289 TJm +(the) 12.1748 Tj +-290 TJm +(m) 7.75121 Tj +1 TJm +(aximum) 32.6587 Tj +-290 TJm +(memory) 33.2067 Tj +-289 TJm +(requirement) 48.1412 Tj +-289 TJm +(drops) 22.1378 Tj +72 179.607 Td +(to) 7.75121 Tj +-250 TJm +(around) 27.6673 Tj +-250 TJm +(2300k\).) 30.7159 Tj +-620 TJm +(See) 14.3866 Tj +[1 0 0 1 166.166 179.607] cm +0 0 1 rg +0 0 1 RG +[1 0 0 1 -166.166 -179.607] cm +[1 0 0 1 0 0] Tm +0 0 Td +166.166 179.607 Td +/F128_0 9.963 Tf +(Ho) 12.1748 Tj +25 TJm +(w) 7.19329 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(use) 13.2807 Tj +-250 TJm +(bzip2) 22.1378 Tj +[1 0 0 1 235.924 179.607] cm +0 g +0 G +0 0 1 rg +0 0 1 RG +0 0 1 rg +0 0 1 RG +[1 0 0 1 -235.924 -179.607] cm +[1 0 0 1 0 0] Tm +0 0 Td +238.415 179.607 Td +/F128_0 9.963 Tf +([2]) 11.6169 Tj +[1 0 0 1 250.031 179.607] cm +0 0 1 rg +0 0 1 RG +0 g +0 G +[1 0 0 1 -250.031 -179.607] cm +[1 0 0 1 0 0] Tm +0 0 Td +252.522 179.607 Td +/F128_0 9.963 Tf +(for) 11.6169 Tj +-250 TJm +(more) 20.474 Tj +-250 TJm +(information) 47.0453 Tj +-250 TJm +(on) 9.963 Tj +-250 TJm +(mem) 19.926 Tj +1 TJm +(ory) 13.2807 Tj +-250 TJm +(management.) 53.4017 Tj +[1 0 0 1 72 177.45] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -167.487] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 157.689 Td +/F128_0 9.963 Tf +(Note) 19.3681 Tj +-289 TJm +(that) 14.9445 Tj +-289 TJm +(the) 12.1748 Tj +-290 TJm +(amou) 22.1378 Tj +1 TJm +(nt) 7.75121 Tj +-290 TJm +(of) 8.29918 Tj +-289 TJm +(memory) 33.2067 Tj +-289 TJm +(needed) 28.2152 Tj +-289 TJm +(to) 7.75121 Tj +-289 TJm +(decompress) 47.0353 Tj +-290 TJm +(a) 4.42357 Tj +-289 TJm +(stream) 26.5614 Tj +-289 TJm +(cannot) 26.5614 Tj +-289 TJm +(be) 9.40507 Tj +-289 TJm +(determined) 44.8235 Tj +-289 TJm +(until) 18.2721 Tj +-290 TJm +(t) 2.76971 Tj +1 TJm +(he) 9.40507 Tj +-290 TJm +(stream') 29.879 Tj +55 TJm +(s) 3.87561 Tj +-289 TJm +(header) 26.5514 Tj +-289 TJm +(has) 13.2807 Tj +72 145.734 Td +(been) 18.8101 Tj +-342 TJm +(read,) 19.6371 Tj +-365 TJm +(so) 8.85711 Tj +-343 TJm +(e) 4.42357 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(en) 9.40507 Tj +-342 TJm +(if) 6.08739 Tj +[1 0 0 1 161.081 145.734] cm +0 g +0 G +[1 0 0 1 -161.081 -145.734] cm +[1 0 0 1 0 0] Tm +0 0 Td +161.081 145.734 Td +/F130_0 9.963 Tf +(BZ2_bzDecompressInit) 119.556 Tj +[1 0 0 1 280.633 145.734] cm +0 g +0 G +[1 0 0 1 -280.633 -145.734] cm +[1 0 0 1 0 0] Tm +0 0 Td +284.043 145.734 Td +/F128_0 9.963 Tf +(succeeds,) 37.8993 Tj +-365 TJm +(a) 4.42357 Tj +-342 TJm +(subsequent) 44.2756 Tj +[1 0 0 1 381.098 145.734] cm +0 g +0 G +[1 0 0 1 -381.098 -145.734] cm +[1 0 0 1 0 0] Tm +0 0 Td +381.098 145.734 Td +/F130_0 9.963 Tf +(BZ2_bzDecompress) 95.6448 Tj +[1 0 0 1 476.739 145.734] cm +0 g +0 G +[1 0 0 1 -476.739 -145.734] cm +[1 0 0 1 0 0] Tm +0 0 Td +480.149 145.734 Td +/F128_0 9.963 Tf +(could) 22.1378 Tj +-342 TJm +(f) 3.31768 Tj +10 TJm +(ail) 9.963 Tj +-342 TJm +(with) 17.7142 Tj +[1 0 0 1 72 133.779] cm +0 g +0 G +[1 0 0 1 -72 -133.779] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 133.779 Td +/F130_0 9.963 Tf +(BZ_MEM_ERROR) 71.7336 Tj +[1 0 0 1 143.731 133.779] cm +0 g +0 G +[1 0 0 1 -143.731 -133.779] cm +[1 0 0 1 0 0] Tm +0 0 Td +143.731 133.779 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 72 132.613] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -122.651] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 111.861 Td +/F128_0 9.963 Tf +(Possible) 33.2166 Tj +-250 TJm +(return) 23.7916 Tj +-250 TJm +(v) 4.9815 Tj +25 TJm +(alues:) 23.2437 Tj +[1 0 0 1 72 111.761] cm +0 g +0 G +[1 0 0 1 0 -60.909] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.854] cm +0 g +0 G +0 g +0 G +[1 0 0 1 40.572 -6.755] cm +0 g +0 G +[1 0 0 1 -493.841 -50.951] cm +[1 0 0 1 0 0] Tm +0 0 Td +534.414 50.951 Td +/F128_0 9.963 Tf +(16) 9.963 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 20 20 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 -8.911] cm +0 g +0 G +[1 0 0 1 0 8.911] cm +0 g +0 G +0 g +0 G +[1 0 0 1 84.08 -6.755] cm +0 g +0 G +[1 0 0 1 -350.151 -749.245] cm +[1 0 0 1 0 0] Tm +0 0 Td +434.231 749.245 Td +/F128_0 9.963 Tf +(Programming) 54.7965 Tj +-250 TJm +(with) 17.7142 Tj +-250 TJm +(libbzip2) 32.6587 Tj +[1 0 0 1 266.071 747.089] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -5.037] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -468 -117.195] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 95.641 re +f +Q +0 g +0 G +[1 0 0 1 0 3.586] cm +0 g +0 G +[1 0 0 1 0 92.055] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -711.631] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 711.631 Td +/F130_0 9.963 Tf +(BZ_CONFIG_ERROR) 89.667 Tj +98.488 699.676 Td +(if) 11.9556 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(library) 41.8446 Tj +-426 TJm +(has) 17.9334 Tj +-426 TJm +(been) 23.9112 Tj +-425 TJm +(mis-compiled) 71.7336 Tj +90 687.721 Td +(BZ_PARAM_ERROR) 83.6892 Tj +98.488 675.766 Td +(if) 11.9556 Tj +-426 TJm +(\() 5.9778 Tj +-426 TJm +(small) 29.889 Tj +-426 TJm +(!=) 11.9556 Tj +-426 TJm +(0) 5.9778 Tj +-426 TJm +(&&) 11.9556 Tj +-426 TJm +(small) 29.889 Tj +-425 TJm +(!=) 11.9556 Tj +-426 TJm +(1) 5.9778 Tj +-426 TJm +(\)) 5.9778 Tj +98.488 663.811 Td +(or) 11.9556 Tj +-426 TJm +(\(verbosity) 59.778 Tj +-426 TJm +(<;) 11.9556 Tj +-426 TJm +(0) 5.9778 Tj +-426 TJm +(||) 11.9556 Tj +-426 TJm +(ve) 11.9556 Tj +1 TJm +(rbosity) 41.8446 Tj +-426 TJm +(>) 5.9778 Tj +-426 TJm +(4\)) 11.9556 Tj +90 651.856 Td +(BZ_MEM_ERROR) 71.7336 Tj +98.488 639.9 Td +(if) 11.9556 Tj +-426 TJm +(insufficient) 71.7336 Tj +-426 TJm +(memory) 35.8668 Tj +-426 TJm +(is) 11.9556 Tj +-425 TJm +(available) 53.8002 Tj +[1 0 0 1 72 624.359] cm +0 g +0 G +[1 0 0 1 468 3.586] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.549] cm +0 g +0 G +[1 0 0 1 -72 -614.396] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 602.441 Td +/F128_0 9.963 Tf +(Allo) 17.7142 Tj +25 TJm +(w) 7.19329 Tj +10 TJm +(able) 16.5984 Tj +-250 TJm +(ne) 9.40507 Tj +15 TJm +(xt) 7.75121 Tj +-250 TJm +(actions:) 30.9949 Tj +[1 0 0 1 72 602.341] cm +0 g +0 G +[1 0 0 1 0 -48.817] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 47.821 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 44.234] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -592.976] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 592.976 Td +/F130_0 9.963 Tf +(BZ2_bzDecompress) 95.6448 Tj +98.488 581.021 Td +(if) 11.9556 Tj +-426 TJm +(BZ_OK) 29.889 Tj +-426 TJm +(was) 17.9334 Tj +-426 TJm +(returned) 47.8224 Tj +98.488 569.066 Td +(no) 11.9556 Tj +-426 TJm +(specific) 47.8224 Tj +-426 TJm +(action) 35.8668 Tj +-426 TJm +(requir) 35.8668 Tj +1 TJm +(ed) 11.9556 Tj +-426 TJm +(in) 11.9556 Tj +-426 TJm +(case) 23.9112 Tj +-426 TJm +(of) 11.9556 Tj +-426 TJm +(error) 29.889 Tj +[1 0 0 1 72 553.524] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -3.587] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -543.562] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 522.903 Td +/F121_0 17.215 Tf +(3.3.5.) 43.0719 Tj +[1 0 0 1 119.858 522.903] cm +0 g +0 G +[1 0 0 1 -119.858 -522.903] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.858 522.903 Td +/F387_0 17.215 Tf +(BZ2_bzDecompress) 165.264 Tj +[1 0 0 1 285.126 522.903] cm +0 g +0 G +[1 0 0 1 -213.126 -2.332] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -24.907] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 23.91 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 20.323] cm +0 g +0 G +[1 0 0 1 18 -8.368] cm +0 g +0 G +[1 0 0 1 -90 -511.206] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 511.206 Td +/F130_0 9.963 Tf +(int) 17.9334 Tj +-426 TJm +(BZ2_bzDecompress) 95.6448 Tj +-426 TJm +(\() 5.9778 Tj +-426 TJm +(bz) 11.9556 Tj +1 TJm +(_stream) 41.8446 Tj +-426 TJm +(*strm) 29.889 Tj +-426 TJm +(\);) 11.9556 Tj +[1 0 0 1 72 495.664] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.55] cm +0 g +0 G +[1 0 0 1 -72 -485.701] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 473.746 Td +/F128_0 9.963 Tf +(Pro) 13.8386 Tj +15 TJm +(vides) 21.0319 Tj +-301 TJm +(more) 20.474 Tj +-302 TJm +(inpu) 17.7142 Tj +1 TJm +(t) 2.76971 Tj +-302 TJm +(and/out) 29.889 Tj +-301 TJm +(output) 25.4654 Tj +-301 TJm +(b) 4.9815 Tj +20 TJm +(uf) 8.29918 Tj +25 TJm +(fer) 11.0589 Tj +-302 TJm +(space) 22.1278 Tj +-301 TJm +(for) 11.6169 Tj +-301 TJm +(the) 12.1748 Tj +-302 TJm +(library) 26.5614 Tj +65 TJm +(.) 2.49075 Tj +-928 TJm +(The) 15.4925 Tj +-301 TJm +(caller) 22.1278 Tj +-302 TJm +(maintains) 38.7461 Tj +-301 TJm +(input) 20.4839 Tj +-301 TJm +(and) 14.3866 Tj +-302 TJm +(out) 12.7327 Tj +1 TJm +(put) 12.7327 Tj +-302 TJm +(b) 4.9815 Tj +20 TJm +(uf) 8.29918 Tj +25 TJm +(fers,) 17.4253 Tj +-314 TJm +(and) 14.3866 Tj +72 461.791 Td +(uses) 17.1563 Tj +[1 0 0 1 91.646 461.791] cm +0 g +0 G +[1 0 0 1 -91.646 -461.791] cm +[1 0 0 1 0 0] Tm +0 0 Td +91.646 461.791 Td +/F130_0 9.963 Tf +(BZ2_bzDecompress) 95.6448 Tj +[1 0 0 1 187.287 461.791] cm +0 g +0 G +[1 0 0 1 -187.287 -461.791] cm +[1 0 0 1 0 0] Tm +0 0 Td +189.778 461.791 Td +/F128_0 9.963 Tf +(to) 7.75121 Tj +-250 TJm +(transfer) 30.427 Tj +-250 TJm +(data) 16.5984 Tj +-250 TJm +(between) 33.1967 Tj +-250 TJm +(them) 19.926 Tj +1 TJm +(.) 2.49075 Tj +[1 0 0 1 72 460.227] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -450.264] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 439.873 Td +/F128_0 9.963 Tf +(Before) 27.1093 Tj +-498 TJm +(each) 18.2522 Tj +-498 TJm +(call) 14.3866 Tj +-499 TJm +(to) 7.75121 Tj +[1 0 0 1 159.356 439.873] cm +0 g +0 G +[1 0 0 1 -159.356 -439.873] cm +[1 0 0 1 0 0] Tm +0 0 Td +159.356 439.873 Td +/F130_0 9.963 Tf +(BZ2_bzDecompress) 95.6448 Tj +[1 0 0 1 254.997 439.873] cm +0 g +0 G +[1 0 0 1 -254.997 -439.873] cm +[1 0 0 1 0 0] Tm +0 0 Td +254.997 439.873 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 263.071 439.873] cm +0 g +0 G +[1 0 0 1 -263.071 -439.873] cm +[1 0 0 1 0 0] Tm +0 0 Td +263.071 439.873 Td +/F130_0 9.963 Tf +(next_in) 41.8446 Tj +[1 0 0 1 304.914 439.873] cm +0 g +0 G +[1 0 0 1 -304.914 -439.873] cm +[1 0 0 1 0 0] Tm +0 0 Td +309.879 439.873 Td +/F128_0 9.963 Tf +(should) 26.5713 Tj +-498 TJm +(point) 20.4839 Tj +-498 TJm +(at) 7.19329 Tj +-499 TJm +(the) 12.1748 Tj +-498 TJm +(compressed) 47.0353 Tj +-498 TJm +(data,) 19.0891 Tj +-560 TJm +(and) 14.3866 Tj +[1 0 0 1 492.179 439.873] cm +0 g +0 G +[1 0 0 1 -492.179 -439.873] cm +[1 0 0 1 0 0] Tm +0 0 Td +492.179 439.873 Td +/F130_0 9.963 Tf +(avail_in) 47.8224 Tj +[1 0 0 1 540 439.873] cm +0 g +0 G +[1 0 0 1 -540 -439.873] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 427.918 Td +/F128_0 9.963 Tf +(should) 26.5713 Tj +-308 TJm +(indicate) 31.5429 Tj +-308 TJm +(ho) 9.963 Tj +25 TJm +(w) 7.19329 Tj +-308 TJm +(man) 17.1563 Tj +15 TJm +(y) 4.9815 Tj +-308 TJm +(bytes) 21.0319 Tj +-308 TJm +(the) 12.1748 Tj +-309 TJm +(library) 26.5614 Tj +-308 TJm +(may) 17.1563 Tj +-308 TJm +(read.) 19.6371 Tj +[1 0 0 1 294.955 427.918] cm +0 g +0 G +[1 0 0 1 -294.955 -427.918] cm +[1 0 0 1 0 0] Tm +0 0 Td +294.955 427.918 Td +/F130_0 9.963 Tf +(BZ2_bzDecompress) 95.6448 Tj +[1 0 0 1 390.597 427.918] cm +0 g +0 G +[1 0 0 1 -390.597 -427.918] cm +[1 0 0 1 0 0] Tm +0 0 Td +393.667 427.918 Td +/F128_0 9.963 Tf +(updates) 30.437 Tj +[1 0 0 1 427.173 427.918] cm +0 g +0 G +[1 0 0 1 -427.173 -427.918] cm +[1 0 0 1 0 0] Tm +0 0 Td +427.173 427.918 Td +/F130_0 9.963 Tf +(next_in) 41.8446 Tj +[1 0 0 1 469.016 427.918] cm +0 g +0 G +[1 0 0 1 -469.016 -427.918] cm +[1 0 0 1 0 0] Tm +0 0 Td +469.016 427.918 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 474.723 427.918] cm +0 g +0 G +[1 0 0 1 -474.723 -427.918] cm +[1 0 0 1 0 0] Tm +0 0 Td +474.723 427.918 Td +/F130_0 9.963 Tf +(avail_in) 47.8224 Tj +[1 0 0 1 522.543 427.918] cm +0 g +0 G +[1 0 0 1 -522.543 -427.918] cm +[1 0 0 1 0 0] Tm +0 0 Td +525.614 427.918 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 72 415.963] cm +0 g +0 G +[1 0 0 1 -72 -415.963] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 415.963 Td +/F130_0 9.963 Tf +(total_in) 47.8224 Tj +[1 0 0 1 119.821 415.963] cm +0 g +0 G +[1 0 0 1 -119.821 -415.963] cm +[1 0 0 1 0 0] Tm +0 0 Td +122.311 415.963 Td +/F128_0 9.963 Tf +(to) 7.75121 Tj +-250 TJm +(re\003ect) 24.8975 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(number) 30.437 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(bytes) 21.0319 Tj +-250 TJm +(i) 2.76971 Tj +1 TJm +(t) 2.76971 Tj +-250 TJm +(has) 13.2807 Tj +-250 TJm +(read.) 19.6371 Tj +[1 0 0 1 72 413.806] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -403.843] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 394.045 Td +/F128_0 9.963 Tf +(Similarly) 37.0922 Tj +65 TJm +(,) 2.49075 Tj +[1 0 0 1 113.799 394.045] cm +0 g +0 G +[1 0 0 1 -113.799 -394.045] cm +[1 0 0 1 0 0] Tm +0 0 Td +113.799 394.045 Td +/F130_0 9.963 Tf +(next_out) 47.8224 Tj +[1 0 0 1 161.62 394.045] cm +0 g +0 G +[1 0 0 1 -161.62 -394.045] cm +[1 0 0 1 0 0] Tm +0 0 Td +164.41 394.045 Td +/F128_0 9.963 Tf +(should) 26.5713 Tj +-280 TJm +(point) 20.4839 Tj +-280 TJm +(to) 7.75121 Tj +-280 TJm +(a) 4.42357 Tj +-280 TJm +(b) 4.9815 Tj +20 TJm +(uf) 8.29918 Tj +25 TJm +(fer) 11.0589 Tj +-280 TJm +(in) 7.75121 Tj +-280 TJm +(which) 24.3496 Tj +-280 TJm +(the) 12.1748 Tj +-280 TJm +(uncompressed) 56.9983 Tj +-280 TJm +(output) 25.4654 Tj +-280 TJm +(is) 6.64532 Tj +-280 TJm +(to) 7.75121 Tj +-280 TJm +(be) 9.40507 Tj +-280 TJm +(placed,) 28.4942 Tj +-288 TJm +(with) 17.7142 Tj +[1 0 0 1 486.202 394.045] cm +0 g +0 G +[1 0 0 1 -486.202 -394.045] cm +[1 0 0 1 0 0] Tm +0 0 Td +486.202 394.045 Td +/F130_0 9.963 Tf +(avail_out) 53.8002 Tj +[1 0 0 1 540 394.045] cm +0 g +0 G +[1 0 0 1 -540 -394.045] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 382.09 Td +/F128_0 9.963 Tf +(indicating) 39.852 Tj +-524 TJm +(ho) 9.963 Tj +25 TJm +(w) 7.19329 Tj +-525 TJm +(much) 22.1378 Tj +-524 TJm +(output) 25.4654 Tj +-525 TJm +(space) 22.1278 Tj +-524 TJm +(is) 6.64532 Tj +-525 TJm +(a) 4.42357 Tj +20 TJm +(v) 4.9815 Tj +25 TJm +(ailable.) 29.0521 Tj +[1 0 0 1 285.792 382.09] cm +0 g +0 G +[1 0 0 1 -285.792 -382.09] cm +[1 0 0 1 0 0] Tm +0 0 Td +285.792 382.09 Td +/F130_0 9.963 Tf +(BZ2_bzCompress) 83.6892 Tj +[1 0 0 1 369.478 382.09] cm +0 g +0 G +[1 0 0 1 -369.478 -382.09] cm +[1 0 0 1 0 0] Tm +0 0 Td +374.705 382.09 Td +/F128_0 9.963 Tf +(updates) 30.437 Tj +[1 0 0 1 410.367 382.09] cm +0 g +0 G +[1 0 0 1 -410.367 -382.09] cm +[1 0 0 1 0 0] Tm +0 0 Td +410.367 382.09 Td +/F130_0 9.963 Tf +(next_out) 47.8224 Tj +[1 0 0 1 458.188 382.09] cm +0 g +0 G +[1 0 0 1 -458.188 -382.09] cm +[1 0 0 1 0 0] Tm +0 0 Td +458.188 382.09 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 466.589 382.09] cm +0 g +0 G +[1 0 0 1 -466.589 -382.09] cm +[1 0 0 1 0 0] Tm +0 0 Td +466.589 382.09 Td +/F130_0 9.963 Tf +(avail_out) 53.8002 Tj +[1 0 0 1 520.387 382.09] cm +0 g +0 G +[1 0 0 1 -520.387 -382.09] cm +[1 0 0 1 0 0] Tm +0 0 Td +525.614 382.09 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 72 370.135] cm +0 g +0 G +[1 0 0 1 -72 -370.135] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 370.135 Td +/F130_0 9.963 Tf +(total_out) 53.8002 Tj +[1 0 0 1 125.798 370.135] cm +0 g +0 G +[1 0 0 1 -125.798 -370.135] cm +[1 0 0 1 0 0] Tm +0 0 Td +128.289 370.135 Td +/F128_0 9.963 Tf +(to) 7.75121 Tj +-250 TJm +(re\003ect) 24.8975 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(number) 30.437 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(bytes) 21.0319 Tj +-249 TJm +(output.) 27.9562 Tj +[1 0 0 1 72 367.978] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -358.015] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 348.217 Td +/F128_0 9.963 Tf +(Y) 7.19329 Tj +110 TJm +(ou) 9.963 Tj +-320 TJm +(may) 17.1563 Tj +-321 TJm +(pro) 13.2807 Tj +15 TJm +(vide) 17.1563 Tj +-320 TJm +(and) 14.3866 Tj +-320 TJm +(remo) 20.474 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-321 TJm +(as) 8.29918 Tj +-320 TJm +(little) 18.2721 Tj +-320 TJm +(or) 8.29918 Tj +-321 TJm +(as) 8.29918 Tj +-320 TJm +(much) 22.1378 Tj +-320 TJm +(data) 16.5984 Tj +-321 TJm +(as) 8.29918 Tj +-320 TJm +(you) 14.9445 Tj +-321 TJm +(lik) 10.5209 Tj +11 TJm +(e) 4.42357 Tj +-321 TJm +(on) 9.963 Tj +-320 TJm +(each) 18.2522 Tj +-321 TJm +(call) 14.3866 Tj +-320 TJm +(of) 8.29918 Tj +[1 0 0 1 407.816 348.217] cm +0 g +0 G +[1 0 0 1 -407.816 -348.217] cm +[1 0 0 1 0 0] Tm +0 0 Td +407.816 348.217 Td +/F130_0 9.963 Tf +(BZ2_bzDecompress) 95.6448 Tj +[1 0 0 1 503.457 348.217] cm +0 g +0 G +[1 0 0 1 -503.457 -348.217] cm +[1 0 0 1 0 0] Tm +0 0 Td +503.457 348.217 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +-1043 TJm +(In) 8.29918 Tj +-320 TJm +(the) 12.1748 Tj +72 336.262 Td +(limit,) 21.3208 Tj +-295 TJm +(it) 5.53943 Tj +-286 TJm +(is) 6.64532 Tj +-287 TJm +(ac) 8.84714 Tj +1 TJm +(ceptable) 33.1967 Tj +-287 TJm +(to) 7.75121 Tj +-286 TJm +(supply) 26.5713 Tj +-286 TJm +(and) 14.3866 Tj +-286 TJm +(remo) 20.474 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-286 TJm +(data) 16.5984 Tj +-286 TJm +(one) 14.3866 Tj +-286 TJm +(byte) 17.1563 Tj +-287 TJm +(at) 7.19329 Tj +-286 TJm +(a) 4.42357 Tj +-286 TJm +(time,) 20.205 Tj +-295 TJm +(although) 34.8705 Tj +-286 TJm +(this) 14.3965 Tj +-286 TJm +(w) 7.19329 Tj +10 TJm +(ould) 17.7142 Tj +-287 TJm +(be) 9.40507 Tj +-286 TJm +(terribly) 29.3311 Tj +-286 TJm +(inef) 15.4925 Tj +25 TJm +(\002cient.) 27.3983 Tj +-837 TJm +(Y) 7.19329 Tj +110 TJm +(ou) 9.963 Tj +72 324.307 Td +(should) 26.5713 Tj +-250 TJm +(al) 7.19329 Tj +10 TJm +(w) 7.19329 Tj +10 TJm +(ays) 13.2807 Tj +-250 TJm +(ensure) 26.0034 Tj +-250 TJm +(that) 14.9445 Tj +-250 TJm +(at) 7.19329 Tj +-249 TJm +(least) 18.2622 Tj +-250 TJm +(one) 14.3866 Tj +-250 TJm +(byte) 17.1563 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(output) 25.4654 Tj +-250 TJm +(space) 22.1278 Tj +-250 TJm +(is) 6.64532 Tj +-250 TJm +(a) 4.42357 Tj +20 TJm +(v) 4.9815 Tj +25 TJm +(ailable) 26.5614 Tj +-250 TJm +(at) 7.19329 Tj +-250 TJm +(each) 18.2522 Tj +-250 TJm +(call.) 16.8773 Tj +[1 0 0 1 72 322.15] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -312.187] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 302.389 Td +/F128_0 9.963 Tf +(Use) 15.4925 Tj +-250 TJm +(of) 8.29918 Tj +[1 0 0 1 100.772 302.389] cm +0 g +0 G +[1 0 0 1 -100.772 -302.389] cm +[1 0 0 1 0 0] Tm +0 0 Td +100.772 302.389 Td +/F130_0 9.963 Tf +(BZ2_bzDecompress) 95.6448 Tj +[1 0 0 1 196.413 302.389] cm +0 g +0 G +[1 0 0 1 -196.413 -302.389] cm +[1 0 0 1 0 0] Tm +0 0 Td +198.904 302.389 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-250 TJm +(simpler) 29.889 Tj +-250 TJm +(than) 17.1563 Tj +[1 0 0 1 260.064 302.389] cm +0 g +0 G +[1 0 0 1 -260.064 -302.389] cm +[1 0 0 1 0 0] Tm +0 0 Td +260.064 302.389 Td +/F130_0 9.963 Tf +(BZ2_bzCompress) 83.6892 Tj +[1 0 0 1 343.75 302.389] cm +0 g +0 G +[1 0 0 1 -343.75 -302.389] cm +[1 0 0 1 0 0] Tm +0 0 Td +343.75 302.389 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 72 300.232] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -290.269] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 280.471 Td +/F128_0 9.963 Tf +(Y) 7.19329 Tj +110 TJm +(ou) 9.963 Tj +-346 TJm +(should) 26.5713 Tj +-346 TJm +(pro) 13.2807 Tj +15 TJm +(vide) 17.1563 Tj +-346 TJm +(input) 20.4839 Tj +-347 TJm +(and) 14.3866 Tj +-346 TJm +(remo) 20.474 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-346 TJm +(output) 25.4654 Tj +-346 TJm +(as) 8.29918 Tj +-346 TJm +(described) 38.1782 Tj +-346 TJm +(abo) 14.3866 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(e,) 6.91432 Tj +-371 TJm +(and) 14.3866 Tj +-346 TJm +(repeatedly) 41.4959 Tj +-346 TJm +(call) 14.3866 Tj +[1 0 0 1 422.638 280.471] cm +0 g +0 G +[1 0 0 1 -422.638 -280.471] cm +[1 0 0 1 0 0] Tm +0 0 Td +422.638 280.471 Td +/F130_0 9.963 Tf +(BZ2_bzDecompress) 95.6448 Tj +[1 0 0 1 518.279 280.471] cm +0 g +0 G +[1 0 0 1 -518.279 -280.471] cm +[1 0 0 1 0 0] Tm +0 0 Td +521.729 280.471 Td +/F128_0 9.963 Tf +(until) 18.2721 Tj +[1 0 0 1 72 268.516] cm +0 g +0 G +[1 0 0 1 -72 -268.516] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 268.516 Td +/F130_0 9.963 Tf +(BZ_STREAM_END) 77.7114 Tj +[1 0 0 1 149.709 268.516] cm +0 g +0 G +[1 0 0 1 -149.709 -268.516] cm +[1 0 0 1 0 0] Tm +0 0 Td +152.314 268.516 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-262 TJm +(ret) 10.511 Tj +1 TJm +(urned.) 25.1765 Tj +-345 TJm +(Appearance) 47.5733 Tj +-261 TJm +(of) 8.29918 Tj +[1 0 0 1 261.767 268.516] cm +0 g +0 G +[1 0 0 1 -261.767 -268.516] cm +[1 0 0 1 0 0] Tm +0 0 Td +261.767 268.516 Td +/F130_0 9.963 Tf +(BZ_STREAM_END) 77.7114 Tj +[1 0 0 1 339.475 268.516] cm +0 g +0 G +[1 0 0 1 -339.475 -268.516] cm +[1 0 0 1 0 0] Tm +0 0 Td +342.081 268.516 Td +/F128_0 9.963 Tf +(denotes) 30.437 Tj +-261 TJm +(that) 14.9445 Tj +[1 0 0 1 392.672 268.516] cm +0 g +0 G +[1 0 0 1 -392.672 -268.516] cm +[1 0 0 1 0 0] Tm +0 0 Td +392.672 268.516 Td +/F130_0 9.963 Tf +(BZ2_bzDecompress) 95.6448 Tj +[1 0 0 1 488.313 268.516] cm +0 g +0 G +[1 0 0 1 -488.313 -268.516] cm +[1 0 0 1 0 0] Tm +0 0 Td +490.919 268.516 Td +/F128_0 9.963 Tf +(has) 13.2807 Tj +-261 TJm +(detected) 33.1967 Tj +72 256.561 Td +(the) 12.1748 Tj +-212 TJm +(logical) 27.1193 Tj +-211 TJm +(end) 14.3866 Tj +-212 TJm +(of) 8.29918 Tj +-212 TJm +(the) 12.1748 Tj +-212 TJm +(compressed) 47.0353 Tj +-211 TJm +(stream.) 29.0521 Tj +[1 0 0 1 237.858 256.561] cm +0 g +0 G +[1 0 0 1 -237.858 -256.561] cm +[1 0 0 1 0 0] Tm +0 0 Td +237.858 256.561 Td +/F130_0 9.963 Tf +(BZ2_bzDecompress) 95.6448 Tj +[1 0 0 1 333.499 256.561] cm +0 g +0 G +[1 0 0 1 -333.499 -256.561] cm +[1 0 0 1 0 0] Tm +0 0 Td +335.609 256.561 Td +/F128_0 9.963 Tf +(will) 15.5024 Tj +-212 TJm +(not) 12.7327 Tj +-212 TJm +(pr) 8.29918 Tj +1 TJm +(oduce) 23.7916 Tj +[1 0 0 1 402.263 256.561] cm +0 g +0 G +[1 0 0 1 -402.263 -256.561] cm +[1 0 0 1 0 0] Tm +0 0 Td +402.263 256.561 Td +/F130_0 9.963 Tf +(BZ_STREAM_END) 77.7114 Tj +[1 0 0 1 479.972 256.561] cm +0 g +0 G +[1 0 0 1 -479.972 -256.561] cm +[1 0 0 1 0 0] Tm +0 0 Td +482.082 256.561 Td +/F128_0 9.963 Tf +(until) 18.2721 Tj +-212 TJm +(all) 9.963 Tj +-211 TJm +(output) 25.4654 Tj +72 244.605 Td +(data) 16.5984 Tj +-256 TJm +(has) 13.2807 Tj +-255 TJm +(been) 18.8101 Tj +-256 TJm +(placed) 26.0034 Tj +-256 TJm +(into) 15.5024 Tj +-256 TJm +(the) 12.1748 Tj +-255 TJm +(output) 25.4654 Tj +-256 TJm +(b) 4.9815 Tj +20 TJm +(uf) 8.29918 Tj +25 TJm +(fer) 11.0589 Tj +40 TJm +(,) 2.49075 Tj +-257 TJm +(so) 8.85711 Tj +-256 TJm +(once) 18.8101 Tj +[1 0 0 1 278.979 244.605] cm +0 g +0 G +[1 0 0 1 -278.979 -244.605] cm +[1 0 0 1 0 0] Tm +0 0 Td +278.979 244.605 Td +/F130_0 9.963 Tf +(BZ_STREAM_END) 77.7114 Tj +[1 0 0 1 356.687 244.605] cm +0 g +0 G +[1 0 0 1 -356.687 -244.605] cm +[1 0 0 1 0 0] Tm +0 0 Td +359.236 244.605 Td +/F128_0 9.963 Tf +(appears,) 32.9178 Tj +-257 TJm +(you) 14.9445 Tj +-256 TJm +(are) 12.1648 Tj +-256 TJm +(guaran) 27.1093 Tj +1 TJm +(teed) 16.5984 Tj +-256 TJm +(to) 7.75121 Tj +-256 TJm +(ha) 9.40507 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-256 TJm +(a) 4.42357 Tj +20 TJm +(v) 4.9815 Tj +25 TJm +(ailable) 26.5614 Tj +72 232.65 Td +(all) 9.963 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(decompressed) 56.4404 Tj +-250 TJm +(output,) 27.9562 Tj +-249 TJm +(and) 14.3866 Tj +[1 0 0 1 205.369 232.65] cm +0 g +0 G +[1 0 0 1 -205.369 -232.65] cm +[1 0 0 1 0 0] Tm +0 0 Td +205.369 232.65 Td +/F130_0 9.963 Tf +(BZ2_bzDecompressEnd) 113.578 Tj +[1 0 0 1 318.943 232.65] cm +0 g +0 G +[1 0 0 1 -318.943 -232.65] cm +[1 0 0 1 0 0] Tm +0 0 Td +321.433 232.65 Td +/F128_0 9.963 Tf +(can) 13.8286 Tj +-250 TJm +(safely) 23.7916 Tj +-250 TJm +(be) 9.40507 Tj +-250 TJm +(called.) 26.2824 Tj +[1 0 0 1 72 230.493] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -220.531] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 210.732 Td +/F128_0 9.963 Tf +(If) 6.63536 Tj +-250 TJm +(case) 17.1463 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(an) 9.40507 Tj +-250 TJm +(error) 19.3581 Tj +-250 TJm +(return) 23.7916 Tj +-250 TJm +(v) 4.9815 Tj +25 TJm +(alue) 16.5984 Tj +1 TJm +(,) 2.49075 Tj +-250 TJm +(you) 14.9445 Tj +-250 TJm +(should) 26.5713 Tj +-250 TJm +(call) 14.3866 Tj +[1 0 0 1 261.259 210.732] cm +0 g +0 G +[1 0 0 1 -261.259 -210.732] cm +[1 0 0 1 0 0] Tm +0 0 Td +261.259 210.732 Td +/F130_0 9.963 Tf +(BZ2_bzDecompressEnd) 113.578 Tj +[1 0 0 1 374.833 210.732] cm +0 g +0 G +[1 0 0 1 -374.833 -210.732] cm +[1 0 0 1 0 0] Tm +0 0 Td +377.323 210.732 Td +/F128_0 9.963 Tf +(to) 7.75121 Tj +-250 TJm +(clean) 21.0219 Tj +-250 TJm +(up) 9.963 Tj +-250 TJm +(and) 14.3866 Tj +-250 TJm +(release) 27.6573 Tj +-250 TJm +(memor) 28.2252 Tj +1 TJm +(y) 4.9815 Tj +65 TJm +(.) 2.49075 Tj +[1 0 0 1 72 208.576] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -198.613] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 188.815 Td +/F128_0 9.963 Tf +(Possible) 33.2166 Tj +-250 TJm +(return) 23.7916 Tj +-250 TJm +(v) 4.9815 Tj +25 TJm +(alues:) 23.2437 Tj +[1 0 0 1 72 188.715] cm +0 g +0 G +[1 0 0 1 0 -137.863] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.854] cm +0 g +0 G +0 g +0 G +[1 0 0 1 40.572 -6.755] cm +0 g +0 G +[1 0 0 1 -493.841 -50.951] cm +[1 0 0 1 0 0] Tm +0 0 Td +534.414 50.951 Td +/F128_0 9.963 Tf +(17) 9.963 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 21 21 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 -8.911] cm +0 g +0 G +[1 0 0 1 0 8.911] cm +0 g +0 G +0 g +0 G +[1 0 0 1 84.08 -6.755] cm +0 g +0 G +[1 0 0 1 -350.151 -749.245] cm +[1 0 0 1 0 0] Tm +0 0 Td +434.231 749.245 Td +/F128_0 9.963 Tf +(Programming) 54.7965 Tj +-250 TJm +(with) 17.7142 Tj +-250 TJm +(libbzip2) 32.6587 Tj +[1 0 0 1 266.071 747.089] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -5.037] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -468 -200.882] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 179.328 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 175.741] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -711.631] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 711.631 Td +/F130_0 9.963 Tf +(BZ_PARAM_ERROR) 83.6892 Tj +98.488 699.676 Td +(if) 11.9556 Tj +-426 TJm +(strm) 23.9112 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(NULL) 23.9112 Tj +-426 TJm +(or) 11.9556 Tj +-426 TJm +(strm-) 29.889 Tj +1 TJm +(>s) 11.9556 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(NULL) 23.9112 Tj +98.488 687.721 Td +(or) 11.9556 Tj +-426 TJm +(strm->avail_out) 89.667 Tj +-426 TJm +(<) 5.9778 Tj +-426 TJm +(1) 5.9778 Tj +90 675.766 Td +(BZ_DATA_ERROR) 77.7114 Tj +98.488 663.811 Td +(if) 11.9556 Tj +-426 TJm +(a) 5.9778 Tj +-426 TJm +(data) 23.9112 Tj +-426 TJm +(integrity) 53.8002 Tj +-426 TJm +(erro) 23.9112 Tj +1 TJm +(r) 5.9778 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(detected) 47.8224 Tj +-426 TJm +(in) 11.9556 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(compressed) 59.778 Tj +-426 TJm +(stream) 35.8668 Tj +90 651.856 Td +(BZ_DATA_ERROR_MAGIC) 113.578 Tj +98.488 639.9 Td +(if) 11.9556 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(compressed) 59.778 Tj +-426 TJm +(stream) 35.8668 Tj +-425 TJm +(doesn't) 41.8446 Tj +-426 TJm +(begin) 29.889 Tj +-426 TJm +(with) 23.9112 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(right) 29.889 Tj +-426 TJm +(magic) 29.889 Tj +-426 TJm +(bytes) 29.889 Tj +90 627.945 Td +(BZ_MEM_ERROR) 71.7336 Tj +98.488 615.99 Td +(if) 11.9556 Tj +-426 TJm +(there) 29.889 Tj +-426 TJm +(wasn't) 35.8668 Tj +-426 TJm +(enough) 35.8668 Tj +-426 TJm +(m) 5.9778 Tj +1 TJm +(emory) 29.889 Tj +-426 TJm +(available) 53.8002 Tj +90 604.035 Td +(BZ_STREAM_END) 77.7114 Tj +98.488 592.08 Td +(if) 11.9556 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(logical) 41.8446 Tj +-426 TJm +(end) 17.9334 Tj +-426 TJm +(of) 11.9556 Tj +-426 TJm +(th) 11.9556 Tj +1 TJm +(e) 5.9778 Tj +-426 TJm +(data) 23.9112 Tj +-426 TJm +(stream) 35.8668 Tj +-426 TJm +(was) 17.9334 Tj +-426 TJm +(detected) 47.8224 Tj +-426 TJm +(and) 17.9334 Tj +-426 TJm +(all) 17.9334 Tj +98.488 580.124 Td +(output) 35.8668 Tj +-426 TJm +(in) 11.9556 Tj +-426 TJm +(has) 17.9334 Tj +-426 TJm +(been) 23.9112 Tj +-426 TJm +(consu) 29.889 Tj +1 TJm +(med,) 23.9112 Tj +-426 TJm +(eg) 11.9556 Tj +-426 TJm +(s-->avail_out) 77.7114 Tj +-426 TJm +(>) 5.9778 Tj +-426 TJm +(0) 5.9778 Tj +90 568.169 Td +(BZ_OK) 29.889 Tj +98.488 556.214 Td +(otherwise) 53.8002 Tj +[1 0 0 1 72 540.672] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.549] cm +0 g +0 G +[1 0 0 1 -72 -530.71] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 518.755 Td +/F128_0 9.963 Tf +(Allo) 17.7142 Tj +25 TJm +(w) 7.19329 Tj +10 TJm +(able) 16.5984 Tj +-250 TJm +(ne) 9.40507 Tj +15 TJm +(xt) 7.75121 Tj +-250 TJm +(actions:) 30.9949 Tj +[1 0 0 1 72 518.655] cm +0 g +0 G +[1 0 0 1 0 -60.772] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 59.776 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 56.189] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -509.29] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 509.29 Td +/F130_0 9.963 Tf +(BZ2_bzDecompress) 95.6448 Tj +98.488 497.335 Td +(if) 11.9556 Tj +-426 TJm +(BZ_OK) 29.889 Tj +-426 TJm +(was) 17.9334 Tj +-426 TJm +(returned) 47.8224 Tj +90 485.38 Td +(BZ2_bzDecompressEnd) 113.578 Tj +98.488 473.425 Td +(otherwise) 53.8002 Tj +[1 0 0 1 72 457.883] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -3.587] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -447.92] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 427.262 Td +/F121_0 17.215 Tf +(3.3.6.) 43.0719 Tj +[1 0 0 1 119.858 427.262] cm +0 g +0 G +[1 0 0 1 -119.858 -427.262] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.858 427.262 Td +/F387_0 17.215 Tf +(BZ2_bzDecompressEnd) 196.251 Tj +[1 0 0 1 316.114 427.262] cm +0 g +0 G +[1 0 0 1 -244.114 -2.333] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -24.906] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 23.91 re +f +Q +0 g +0 G +[1 0 0 1 0 3.586] cm +0 g +0 G +[1 0 0 1 0 20.324] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -415.564] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 415.564 Td +/F130_0 9.963 Tf +(int) 17.9334 Tj +-426 TJm +(BZ2_bzDecompressEnd) 113.578 Tj +-426 TJm +(\() 5.9778 Tj +-425 TJm +(bz_stream) 53.8002 Tj +-426 TJm +(*strm) 29.889 Tj +-426 TJm +(\);) 11.9556 Tj +[1 0 0 1 72 400.023] cm +0 g +0 G +[1 0 0 1 468 3.586] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.549] cm +0 g +0 G +[1 0 0 1 -72 -390.06] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 378.105 Td +/F128_0 9.963 Tf +(Releases) 34.8605 Tj +-250 TJm +(all) 9.963 Tj +-250 TJm +(memory) 33.2067 Tj +-250 TJm +(assoc) 21.5799 Tj +1 TJm +(iated) 19.3681 Tj +-250 TJm +(with) 17.7142 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(decompression) 59.768 Tj +-250 TJm +(stream.) 29.0521 Tj +[1 0 0 1 72 375.948] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -365.985] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 356.187 Td +/F128_0 9.963 Tf +(Possible) 33.2166 Tj +-250 TJm +(return) 23.7916 Tj +-250 TJm +(v) 4.9815 Tj +25 TJm +(alues:) 23.2437 Tj +[1 0 0 1 72 356.087] cm +0 g +0 G +[1 0 0 1 0 -60.772] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 59.776 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 56.189] cm +0 g +0 G +[1 0 0 1 18 -8.368] cm +0 g +0 G +[1 0 0 1 -90 -346.723] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 346.723 Td +/F130_0 9.963 Tf +(BZ_PARAM_ERROR) 83.6892 Tj +98.488 334.767 Td +(if) 11.9556 Tj +-426 TJm +(strm) 23.9112 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(NULL) 23.9112 Tj +-426 TJm +(or) 11.9556 Tj +-426 TJm +(strm-) 29.889 Tj +1 TJm +(>s) 11.9556 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(NULL) 23.9112 Tj +90 322.812 Td +(BZ_OK) 29.889 Tj +98.488 310.857 Td +(otherwise) 53.8002 Tj +[1 0 0 1 72 295.315] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.549] cm +0 g +0 G +[1 0 0 1 -72 -285.353] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 273.398 Td +/F128_0 9.963 Tf +(Allo) 17.7142 Tj +25 TJm +(w) 7.19329 Tj +10 TJm +(able) 16.5984 Tj +-250 TJm +(ne) 9.40507 Tj +15 TJm +(xt) 7.75121 Tj +-250 TJm +(actions:) 30.9949 Tj +[1 0 0 1 72 273.298] cm +0 g +0 G +[1 0 0 1 0 -24.907] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 23.91 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 20.324] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -263.933] cm +[1 0 0 1 0 0] Tm +0 0 Td +98.488 263.933 Td +/F130_0 9.963 Tf +(None.) 29.889 Tj +[1 0 0 1 72 248.391] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -3.587] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -238.429] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 213.639 Td +/F121_0 20.659 Tf +(3.4.) 34.4592 Tj +-278 TJm +(High-le) 70.0134 Tj +15 TJm +(vel) 28.716 Tj +-278 TJm +(interface) 86.1067 Tj +[1 0 0 1 72 209.042] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -199.08] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 191.721 Td +/F128_0 9.963 Tf +(This) 17.7142 Tj +-250 TJm +(interf) 21.5799 Tj +10 TJm +(ace) 13.2707 Tj +-250 TJm +(pro) 13.2807 Tj +15 TJm +(vides) 21.0319 Tj +-250 TJm +(funct) 20.474 Tj +1 TJm +(ions) 16.6083 Tj +-250 TJm +(for) 11.6169 Tj +-250 TJm +(reading) 29.879 Tj +-250 TJm +(and) 14.3866 Tj +-250 TJm +(writing) 28.7831 Tj +[1 0 0 1 300.292 191.721] cm +0 g +0 G +[1 0 0 1 -300.292 -191.721] cm +[1 0 0 1 0 0] Tm +0 0 Td +300.292 191.721 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 330.18 191.721] cm +0 g +0 G +[1 0 0 1 -330.18 -191.721] cm +[1 0 0 1 0 0] Tm +0 0 Td +332.67 191.721 Td +/F128_0 9.963 Tf +(format) 26.5614 Tj +-250 TJm +(\002les.) 19.0991 Tj +-620 TJm +(First,) 20.7629 Tj +-250 TJm +(some) 21.0319 Tj +-250 TJm +(gen) 14.3866 Tj +1 TJm +(eral) 14.9345 Tj +-250 TJm +(points.) 26.8503 Tj +[1 0 0 1 72 189.564] cm +0 g +0 G +[1 0 0 1 0 -29.724] cm +0 g +0 G +[1 0 0 1 6.974 0] cm +0 g +0 G +[1 0 0 1 -78.974 -159.84] cm +[1 0 0 1 0 0] Tm +0 0 Td +78.974 159.84 Td +/F128_0 9.963 Tf +(\225) 3.48705 Tj +[1 0 0 1 82.461 159.84] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 1.993 0] cm +0 g +0 G +[1 0 0 1 -86.944 -159.84] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 159.84 Td +/F128_0 9.963 Tf +(All) 12.7327 Tj +-332 TJm +(of) 8.29918 Tj +-331 TJm +(the) 12.1748 Tj +-332 TJm +(functions) 37.0823 Tj +-331 TJm +(tak) 12.1748 Tj +10 TJm +(e) 4.42357 Tj +-332 TJm +(an) 9.40507 Tj +[1 0 0 1 202.958 159.84] cm +0 g +0 G +[1 0 0 1 -202.958 -159.84] cm +[1 0 0 1 0 0] Tm +0 0 Td +202.958 159.84 Td +/F130_0 9.963 Tf +(int*) 23.9112 Tj +[1 0 0 1 226.868 159.84] cm +0 g +0 G +[1 0 0 1 -226.868 -159.84] cm +[1 0 0 1 0 0] Tm +0 0 Td +230.172 159.84 Td +/F128_0 9.963 Tf +(\002rst) 15.5024 Tj +-332 TJm +(ar) 7.74125 Tj +18 TJm +(gume) 22.1378 Tj +1 TJm +(nt,) 10.242 Tj +[1 0 0 1 292.426 159.84] cm +0 g +0 G +[1 0 0 1 -292.426 -159.84] cm +[1 0 0 1 0 0] Tm +0 0 Td +292.426 159.84 Td +/F130_0 9.963 Tf +(bzerror) 41.8446 Tj +[1 0 0 1 334.269 159.84] cm +0 g +0 G +[1 0 0 1 -334.269 -159.84] cm +[1 0 0 1 0 0] Tm +0 0 Td +334.269 159.84 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +-1110 TJm +(After) 21.0219 Tj +-331 TJm +(each) 18.2522 Tj +-332 TJm +(call,) 16.8773 Tj +[1 0 0 1 414.083 159.84] cm +0 g +0 G +[1 0 0 1 -414.083 -159.84] cm +[1 0 0 1 0 0] Tm +0 0 Td +414.083 159.84 Td +/F130_0 9.963 Tf +(bzerror) 41.8446 Tj +[1 0 0 1 455.926 159.84] cm +0 g +0 G +[1 0 0 1 -455.926 -159.84] cm +[1 0 0 1 0 0] Tm +0 0 Td +459.23 159.84 Td +/F128_0 9.963 Tf +(should) 26.5713 Tj +-332 TJm +(be) 9.40507 Tj +-331 TJm +(consulted) 38.1882 Tj +86.944 147.885 Td +(\002rst) 15.5024 Tj +-349 TJm +(to) 7.75121 Tj +-348 TJm +(determine) 39.842 Tj +-349 TJm +(the) 12.1748 Tj +-349 TJm +(outcome) 34.3126 Tj +-348 TJm +(of) 8.29918 Tj +-349 TJm +(the) 12.1748 Tj +-349 TJm +(call.) 16.8773 Tj +-1212 TJm +(If) 6.63536 Tj +[1 0 0 1 280.386 147.885] cm +0 g +0 G +[1 0 0 1 -280.386 -147.885] cm +[1 0 0 1 0 0] Tm +0 0 Td +280.386 147.885 Td +/F130_0 9.963 Tf +(bzerror) 41.8446 Tj +[1 0 0 1 322.229 147.885] cm +0 g +0 G +[1 0 0 1 -322.229 -147.885] cm +[1 0 0 1 0 0] Tm +0 0 Td +325.704 147.885 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +[1 0 0 1 335.823 147.885] cm +0 g +0 G +[1 0 0 1 -335.823 -147.885] cm +[1 0 0 1 0 0] Tm +0 0 Td +335.823 147.885 Td +/F130_0 9.963 Tf +(BZ_OK) 29.889 Tj +[1 0 0 1 365.711 147.885] cm +0 g +0 G +[1 0 0 1 -365.711 -147.885] cm +[1 0 0 1 0 0] Tm +0 0 Td +365.711 147.885 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-349 TJm +(the) 12.1748 Tj +-349 TJm +(c) 4.42357 Tj +1 TJm +(all) 9.963 Tj +-349 TJm +(completed) 41.5059 Tj +-349 TJm +(successfully) 48.6991 Tj +65 TJm +(,) 2.49075 Tj +-373 TJm +(and) 14.3866 Tj +-349 TJm +(only) 17.7142 Tj +86.944 135.93 Td +(then) 17.1563 Tj +-271 TJm +(s) 3.87561 Tj +1 TJm +(hould) 22.6957 Tj +-271 TJm +(the) 12.1748 Tj +-271 TJm +(re) 7.74125 Tj +1 TJm +(turn) 16.0504 Tj +-271 TJm +(v) 4.9815 Tj +25 TJm +(alue) 16.5984 Tj +-271 TJm +(o) 4.9815 Tj +1 TJm +(f) 3.31768 Tj +-271 TJm +(the) 12.1748 Tj +-271 TJm +(functi) 23.2437 Tj +1 TJm +(on) 9.963 Tj +-271 TJm +(\(if) 9.40507 Tj +-271 TJm +(an) 9.40507 Tj +15 TJm +(y\)) 8.29918 Tj +-270 TJm +(be) 9.40507 Tj +-271 TJm +(consulted.) 40.6789 Tj +-743 TJm +(If) 6.63536 Tj +[1 0 0 1 365.077 135.93] cm +0 g +0 G +[1 0 0 1 -365.077 -135.93] cm +[1 0 0 1 0 0] Tm +0 0 Td +365.077 135.93 Td +/F130_0 9.963 Tf +(bzerror) 41.8446 Tj +[1 0 0 1 406.92 135.93] cm +0 g +0 G +[1 0 0 1 -406.92 -135.93] cm +[1 0 0 1 0 0] Tm +0 0 Td +409.616 135.93 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +[1 0 0 1 418.956 135.93] cm +0 g +0 G +[1 0 0 1 -418.956 -135.93] cm +[1 0 0 1 0 0] Tm +0 0 Td +418.956 135.93 Td +/F130_0 9.963 Tf +(BZ_IO_ERROR) 65.7558 Tj +[1 0 0 1 484.71 135.93] cm +0 g +0 G +[1 0 0 1 -484.71 -135.93] cm +[1 0 0 1 0 0] Tm +0 0 Td +484.71 135.93 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-271 TJm +(ther) 15.4925 Tj +1 TJm +(e) 4.42357 Tj +-271 TJm +(w) 7.19329 Tj +10 TJm +(as) 8.29918 Tj +-271 TJm +(an) 9.40507 Tj +86.944 123.975 Td +(error) 19.3581 Tj +-246 TJm +(read) 17.1463 Tj +1 TJm +(ing/writing) 44.2855 Tj +-246 TJm +(the) 12.1748 Tj +-246 TJm +(und) 14.9445 Tj +1 TJm +(erlying) 28.2252 Tj +-246 TJm +(compressed) 47.0353 Tj +-245 TJm +(\002le,) 15.2235 Tj +-247 TJm +(and) 14.3866 Tj +-246 TJm +(you) 14.9445 Tj +-245 TJm +(should) 26.5713 Tj +-246 TJm +(then) 17.1563 Tj +-245 TJm +(consult) 28.7831 Tj +[1 0 0 1 414.096 123.975] cm +0 g +0 G +[1 0 0 1 -414.096 -123.975] cm +[1 0 0 1 0 0] Tm +0 0 Td +414.096 123.975 Td +/F130_0 9.963 Tf +(errno) 29.889 Tj +[1 0 0 1 443.984 123.975] cm +0 g +0 G +[1 0 0 1 -443.984 -123.975] cm +[1 0 0 1 0 0] Tm +0 0 Td +446.432 123.975 Td +/F128_0 9.963 Tf +(/) 2.76971 Tj +[1 0 0 1 451.649 123.975] cm +0 g +0 G +[1 0 0 1 -451.649 -123.975] cm +[1 0 0 1 0 0] Tm +0 0 Td +451.649 123.975 Td +/F130_0 9.963 Tf +(perror) 35.8668 Tj +[1 0 0 1 487.514 123.975] cm +0 g +0 G +[1 0 0 1 -487.514 -123.975] cm +[1 0 0 1 0 0] Tm +0 0 Td +489.962 123.975 Td +/F128_0 9.963 Tf +(to) 7.75121 Tj +-246 TJm +(deter) 19.916 Tj +1 TJm +(mine) 19.926 Tj +86.944 112.02 Td +(the) 12.1748 Tj +-356 TJm +(cause) 22.1278 Tj +-355 TJm +(of) 8.29918 Tj +-356 TJm +(the) 12.1748 Tj +-356 TJm +(dif) 11.0689 Tj +25 TJm +(\002culty) 25.4654 Tj +65 TJm +(.) 2.49075 Tj +[1 0 0 1 206.528 112.02] cm +0 g +0 G +[1 0 0 1 -206.528 -112.02] cm +[1 0 0 1 0 0] Tm +0 0 Td +206.528 112.02 Td +/F130_0 9.963 Tf +(bzerror) 41.8446 Tj +[1 0 0 1 248.371 112.02] cm +0 g +0 G +[1 0 0 1 -248.371 -112.02] cm +[1 0 0 1 0 0] Tm +0 0 Td +251.916 112.02 Td +/F128_0 9.963 Tf +(may) 17.1563 Tj +-356 TJm +(also) 16.0504 Tj +-355 TJm +(be) 9.40507 Tj +-356 TJm +(set) 11.0689 Tj +-356 TJm +(to) 7.75121 Tj +-356 TJm +(v) 4.9815 Tj +25 TJm +(arious) 24.3496 Tj +-355 TJm +(other) 20.474 Tj +-356 TJm +(v) 4.9815 Tj +25 TJm +(alues;) 23.2437 Tj +-409 TJm +(precise) 28.2152 Tj +-356 TJm +(d) 4.9815 Tj +1 TJm +(etails) 21.0319 Tj +-356 TJm +(are) 12.1648 Tj +-356 TJm +(gi) 7.75121 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(en) 9.40507 Tj +-356 TJm +(on) 9.963 Tj +-355 TJm +(a) 4.42357 Tj +86.944 100.064 Td +(per) 12.7228 Tj +20 TJm +(-function) 36.5244 Tj +-250 TJm +(basis) 19.926 Tj +-250 TJm +(belo) 17.1563 Tj +25 TJm +(w) 7.19329 Tj +65 TJm +(.) 2.49075 Tj +[1 0 0 1 186.838 100.064] cm +0 g +0 G +[1 0 0 1 -114.838 -49.212] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.854] cm +0 g +0 G +0 g +0 G +[1 0 0 1 40.572 -6.755] cm +0 g +0 G +[1 0 0 1 -493.841 -50.951] cm +[1 0 0 1 0 0] Tm +0 0 Td +534.414 50.951 Td +/F128_0 9.963 Tf +(18) 9.963 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 22 22 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 -8.911] cm +0 g +0 G +[1 0 0 1 0 8.911] cm +0 g +0 G +0 g +0 G +[1 0 0 1 84.08 -6.755] cm +0 g +0 G +[1 0 0 1 -350.151 -749.245] cm +[1 0 0 1 0 0] Tm +0 0 Td +434.231 749.245 Td +/F128_0 9.963 Tf +(Programming) 54.7965 Tj +-250 TJm +(with) 17.7142 Tj +-250 TJm +(libbzip2) 32.6587 Tj +[1 0 0 1 266.071 747.089] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -5.037] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -468 -31.517] cm +0 g +0 G +[1 0 0 1 6.974 0] cm +0 g +0 G +[1 0 0 1 -78.974 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +78.974 710.037 Td +/F128_0 9.963 Tf +(\225) 3.48705 Tj +[1 0 0 1 82.461 710.037] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 1.993 0] cm +0 g +0 G +[1 0 0 1 -86.944 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 710.037 Td +/F128_0 9.963 Tf +(If) 6.63536 Tj +[1 0 0 1 95.958 710.037] cm +0 g +0 G +[1 0 0 1 -95.958 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +95.958 710.037 Td +/F130_0 9.963 Tf +(bzerror) 41.8446 Tj +[1 0 0 1 137.801 710.037] cm +0 g +0 G +[1 0 0 1 -137.801 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +140.179 710.037 Td +/F128_0 9.963 Tf +(indicates) 35.4185 Tj +-239 TJm +(an) 9.40507 Tj +-238 TJm +(error) 19.3581 Tj +-239 TJm +(\(ie,) 13.0017 Tj +-241 TJm +(an) 9.40507 Tj +15 TJm +(ything) 25.4654 Tj +-239 TJm +(e) 4.42357 Tj +15 TJm +(x) 4.9815 Tj +1 TJm +(cept) 16.5984 Tj +[1 0 0 1 292.225 710.037] cm +0 g +0 G +[1 0 0 1 -292.225 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +292.225 710.037 Td +/F130_0 9.963 Tf +(BZ_OK) 29.889 Tj +[1 0 0 1 322.113 710.037] cm +0 g +0 G +[1 0 0 1 -322.113 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +324.492 710.037 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 341.257 710.037] cm +0 g +0 G +[1 0 0 1 -341.257 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +341.257 710.037 Td +/F130_0 9.963 Tf +(BZ_STREAM_END) 77.7114 Tj +[1 0 0 1 418.965 710.037] cm +0 g +0 G +[1 0 0 1 -418.965 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +418.965 710.037 Td +/F128_0 9.963 Tf +(\),) 5.80843 Tj +-239 TJm +(you) 14.9445 Tj +-238 TJm +(should) 26.5713 Tj +-239 TJm +(immediately) 49.815 Tj +-239 TJm +(cal) 11.6169 Tj +1 TJm +(l) 2.76971 Tj +[1 0 0 1 86.944 698.082] cm +0 g +0 G +[1 0 0 1 -86.944 -698.082] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 698.082 Td +/F130_0 9.963 Tf +(BZ2_bzReadClose) 89.667 Tj +[1 0 0 1 176.608 698.082] cm +0 g +0 G +[1 0 0 1 -176.608 -698.082] cm +[1 0 0 1 0 0] Tm +0 0 Td +179.343 698.082 Td +/F128_0 9.963 Tf +(\(or) 11.6169 Tj +[1 0 0 1 193.695 698.082] cm +0 g +0 G +[1 0 0 1 -193.695 -698.082] cm +[1 0 0 1 0 0] Tm +0 0 Td +193.695 698.082 Td +/F130_0 9.963 Tf +(BZ2_bzWriteClose) 95.6448 Tj +[1 0 0 1 289.337 698.082] cm +0 g +0 G +[1 0 0 1 -289.337 -698.082] cm +[1 0 0 1 0 0] Tm +0 0 Td +289.337 698.082 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-281 TJm +(depending) 41.5059 Tj +-274 TJm +(on) 9.963 Tj +-275 TJm +(whethe) 28.7731 Tj +1 TJm +(r) 3.31768 Tj +-275 TJm +(you) 14.9445 Tj +-275 TJm +(are) 12.1648 Tj +-274 TJm +(attempting) 42.6217 Tj +-274 TJm +(to) 7.75121 Tj +-275 TJm +(read) 17.1463 Tj +-274 TJm +(or) 8.29918 Tj +-275 TJm +(to) 7.75121 Tj +-275 TJm +(writ) 16.0504 Tj +1 TJm +(e\)) 7.74125 Tj +86.944 686.127 Td +(to) 7.75121 Tj +-242 TJm +(free) 15.4825 Tj +-241 TJm +(up) 9.963 Tj +-242 TJm +(all) 9.963 Tj +-242 TJm +(resources) 37.6203 Tj +-241 TJm +(associated) 40.9479 Tj +-242 TJm +(with) 17.7142 Tj +-242 TJm +(the) 12.1748 Tj +-241 TJm +(stream.) 29.0521 Tj +-615 TJm +(Once) 21.0219 Tj +-241 TJm +(an) 9.40507 Tj +-242 TJm +(error) 19.3581 Tj +-242 TJm +(has) 13.2807 Tj +-241 TJm +(been) 18.8101 Tj +-242 TJm +(indicated,) 39.0151 Tj +-243 TJm +(beha) 18.8101 Tj +20 TJm +(viour) 21.0319 Tj +-242 TJm +(of) 8.29918 Tj +-242 TJm +(all) 9.963 Tj +-241 TJm +(calls) 18.2622 Tj +-242 TJm +(e) 4.42357 Tj +15 TJm +(xcept) 21.5799 Tj +[1 0 0 1 86.944 674.172] cm +0 g +0 G +[1 0 0 1 -86.944 -674.172] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 674.172 Td +/F130_0 9.963 Tf +(BZ2_bzReadClose) 89.667 Tj +[1 0 0 1 176.608 674.172] cm +0 g +0 G +[1 0 0 1 -176.608 -674.172] cm +[1 0 0 1 0 0] Tm +0 0 Td +179.705 674.172 Td +/F128_0 9.963 Tf +(\() 3.31768 Tj +[1 0 0 1 183.022 674.172] cm +0 g +0 G +[1 0 0 1 -183.022 -674.172] cm +[1 0 0 1 0 0] Tm +0 0 Td +183.022 674.172 Td +/F130_0 9.963 Tf +(BZ2_bzWriteClose) 95.6448 Tj +[1 0 0 1 278.664 674.172] cm +0 g +0 G +[1 0 0 1 -278.664 -674.172] cm +[1 0 0 1 0 0] Tm +0 0 Td +278.664 674.172 Td +/F128_0 9.963 Tf +(\)) 3.31768 Tj +-311 TJm +(is) 6.64532 Tj +-311 TJm +(unde\002) 24.9075 Tj +1 TJm +(ned.) 16.8773 Tj +-986 TJm +(Th) 11.0689 Tj +1 TJm +(e) 4.42357 Tj +-311 TJm +(implication) 45.3914 Tj +-311 TJm +(is) 6.64532 Tj +-311 TJm +(that) 14.9445 Tj +-311 TJm +(\(1) 8.29918 Tj +1 TJm +(\)) 3.31768 Tj +[1 0 0 1 455.988 674.172] cm +0 g +0 G +[1 0 0 1 -455.988 -674.172] cm +[1 0 0 1 0 0] Tm +0 0 Td +455.988 674.172 Td +/F130_0 9.963 Tf +(bzerror) 41.8446 Tj +[1 0 0 1 497.831 674.172] cm +0 g +0 G +[1 0 0 1 -497.831 -674.172] cm +[1 0 0 1 0 0] Tm +0 0 Td +500.928 674.172 Td +/F128_0 9.963 Tf +(should) 26.5713 Tj +-311 TJm +(be) 9.40507 Tj +86.944 662.217 Td +(check) 23.2337 Tj +10 TJm +(ed) 9.40507 Tj +-291 TJm +(after) 18.2522 Tj +-291 TJm +(each) 18.2522 Tj +-291 TJm +(call,) 16.8773 Tj +-301 TJm +(and) 14.3866 Tj +-291 TJm +(\(2\)) 11.6169 Tj +-291 TJm +(if) 6.08739 Tj +[1 0 0 1 225.347 662.217] cm +0 g +0 G +[1 0 0 1 -225.347 -662.217] cm +[1 0 0 1 0 0] Tm +0 0 Td +225.347 662.217 Td +/F130_0 9.963 Tf +(bzerror) 41.8446 Tj +[1 0 0 1 267.19 662.217] cm +0 g +0 G +[1 0 0 1 -267.19 -662.217] cm +[1 0 0 1 0 0] Tm +0 0 Td +270.09 662.217 Td +/F128_0 9.963 Tf +(indicates) 35.4185 Tj +-291 TJm +(an) 9.40507 Tj +-291 TJm +(error) 19.3581 Tj +40 TJm +(,) 2.49075 Tj +[1 0 0 1 345.161 662.217] cm +0 g +0 G +[1 0 0 1 -345.161 -662.217] cm +[1 0 0 1 0 0] Tm +0 0 Td +345.161 662.217 Td +/F130_0 9.963 Tf +(BZ2_bzReadClose) 89.667 Tj +[1 0 0 1 434.824 662.217] cm +0 g +0 G +[1 0 0 1 -434.824 -662.217] cm +[1 0 0 1 0 0] Tm +0 0 Td +437.724 662.217 Td +/F128_0 9.963 Tf +(\() 3.31768 Tj +[1 0 0 1 441.041 662.217] cm +0 g +0 G +[1 0 0 1 -441.041 -662.217] cm +[1 0 0 1 0 0] Tm +0 0 Td +441.041 662.217 Td +/F130_0 9.963 Tf +(BZ2_bzWriteClose) 95.6448 Tj +[1 0 0 1 536.682 662.217] cm +0 g +0 G +[1 0 0 1 -536.682 -662.217] cm +[1 0 0 1 0 0] Tm +0 0 Td +536.682 662.217 Td +/F128_0 9.963 Tf +(\)) 3.31768 Tj +86.944 650.262 Td +(should) 26.5713 Tj +-250 TJm +(then) 17.1563 Tj +-250 TJm +(be) 9.40507 Tj +-250 TJm +(called) 23.7916 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(clea) 16.0404 Tj +1 TJm +(n) 4.9815 Tj +-250 TJm +(up.) 12.4538 Tj +[1 0 0 1 220.034 650.262] cm +0 g +0 G +[1 0 0 1 -148.034 -21.918] cm +0 g +0 G +[1 0 0 1 6.974 0] cm +0 g +0 G +[1 0 0 1 -78.974 -628.344] cm +[1 0 0 1 0 0] Tm +0 0 Td +78.974 628.344 Td +/F128_0 9.963 Tf +(\225) 3.48705 Tj +[1 0 0 1 82.461 628.344] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 1.993 0] cm +0 g +0 G +[1 0 0 1 -86.944 -628.344] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 628.344 Td +/F128_0 9.963 Tf +(The) 15.4925 Tj +[1 0 0 1 106.362 628.344] cm +0 g +0 G +[1 0 0 1 -106.362 -628.344] cm +[1 0 0 1 0 0] Tm +0 0 Td +106.362 628.344 Td +/F130_0 9.963 Tf +(FILE*) 29.889 Tj +[1 0 0 1 136.25 628.344] cm +0 g +0 G +[1 0 0 1 -136.25 -628.344] cm +[1 0 0 1 0 0] Tm +0 0 Td +140.177 628.344 Td +/F128_0 9.963 Tf +(ar) 7.74125 Tj +18 TJm +(guments) 33.7646 Tj +-394 TJm +(passed) 26.5614 Tj +-394 TJm +(to) 7.75121 Tj +[1 0 0 1 227.592 628.344] cm +0 g +0 G +[1 0 0 1 -227.592 -628.344] cm +[1 0 0 1 0 0] Tm +0 0 Td +227.592 628.344 Td +/F130_0 9.963 Tf +(BZ2_bzReadOpen) 83.6892 Tj +[1 0 0 1 311.278 628.344] cm +0 g +0 G +[1 0 0 1 -311.278 -628.344] cm +[1 0 0 1 0 0] Tm +0 0 Td +315.205 628.344 Td +/F128_0 9.963 Tf +(/) 2.76971 Tj +[1 0 0 1 321.901 628.344] cm +0 g +0 G +[1 0 0 1 -321.901 -628.344] cm +[1 0 0 1 0 0] Tm +0 0 Td +321.901 628.344 Td +/F130_0 9.963 Tf +(BZ2_bzWriteOpen) 89.667 Tj +[1 0 0 1 411.565 628.344] cm +0 g +0 G +[1 0 0 1 -411.565 -628.344] cm +[1 0 0 1 0 0] Tm +0 0 Td +415.491 628.344 Td +/F128_0 9.963 Tf +(should) 26.5713 Tj +-394 TJm +(be) 9.40507 Tj +-394 TJm +(set) 11.0689 Tj +-394 TJm +(to) 7.75121 Tj +-394 TJm +(binary) 25.4555 Tj +-394 TJm +(mode.) 24.6285 Tj +86.944 616.389 Td +(Most) 20.4839 Tj +-229 TJm +(Unix) 19.926 Tj +-229 TJm +(s) 3.87561 Tj +1 TJm +(ystems) 27.6772 Tj +-229 TJm +(will) 15.5024 Tj +-229 TJm +(do) 9.963 Tj +-229 TJm +(this) 14.3965 Tj +-229 TJm +(by) 9.963 Tj +-228 TJm +(def) 12.7228 Tj +10 TJm +(ault,) 17.4353 Tj +-233 TJm +(b) 4.9815 Tj +20 TJm +(ut) 7.75121 Tj +-229 TJm +(other) 20.474 Tj +-229 TJm +(platforms,) 40.6789 Tj +-233 TJm +(including) 37.6402 Tj +-228 TJm +(W) 9.40507 Tj +40 TJm +(indo) 17.7142 Tj +25 TJm +(ws) 11.0689 Tj +-229 TJm +(and) 14.3866 Tj +-229 TJm +(Mac,) 20.195 Tj +-233 TJm +(will) 15.5024 Tj +-229 TJm +(not.) 15.2235 Tj +-605 TJm +(If) 6.63536 Tj +-229 TJm +(you) 14.9445 Tj +-229 TJm +(omit) 18.2721 Tj +86.944 604.433 Td +(this,) 16.8873 Tj +-250 TJm +(you) 14.9445 Tj +-250 TJm +(may) 17.1563 Tj +-250 TJm +(encounter) 39.2841 Tj +-250 TJm +(probl) 21.0319 Tj +1 TJm +(ems) 16.0504 Tj +-250 TJm +(when) 21.5799 Tj +-250 TJm +(mo) 12.7327 Tj +15 TJm +(ving) 17.7142 Tj +-250 TJm +(code) 18.8101 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(ne) 9.40507 Tj +25 TJm +(w) 7.19329 Tj +-250 TJm +(platforms.) 40.6789 Tj +[1 0 0 1 372.66 604.433] cm +0 g +0 G +[1 0 0 1 -300.66 -21.917] cm +0 g +0 G +[1 0 0 1 6.974 0] cm +0 g +0 G +[1 0 0 1 -78.974 -582.516] cm +[1 0 0 1 0 0] Tm +0 0 Td +78.974 582.516 Td +/F128_0 9.963 Tf +(\225) 3.48705 Tj +[1 0 0 1 82.461 582.516] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 1.993 0] cm +0 g +0 G +[1 0 0 1 -86.944 -582.516] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 582.516 Td +/F128_0 9.963 Tf +(Memory) 34.3126 Tj +-348 TJm +(allocation) 39.2941 Tj +-348 TJm +(requests) 32.6488 Tj +-348 TJm +(are) 12.1648 Tj +-348 TJm +(handled) 31.5429 Tj +-348 TJm +(by) 9.963 Tj +[1 0 0 1 267.67 582.516] cm +0 g +0 G +[1 0 0 1 -267.67 -582.516] cm +[1 0 0 1 0 0] Tm +0 0 Td +267.67 582.516 Td +/F130_0 9.963 Tf +(malloc) 35.8668 Tj +[1 0 0 1 303.535 582.516] cm +0 g +0 G +[1 0 0 1 -303.535 -582.516] cm +[1 0 0 1 0 0] Tm +0 0 Td +307.003 582.516 Td +/F128_0 9.963 Tf +(/) 2.76971 Tj +[1 0 0 1 313.241 582.516] cm +0 g +0 G +[1 0 0 1 -313.241 -582.516] cm +[1 0 0 1 0 0] Tm +0 0 Td +313.241 582.516 Td +/F130_0 9.963 Tf +(free) 23.9112 Tj +[1 0 0 1 337.151 582.516] cm +0 g +0 G +[1 0 0 1 -337.151 -582.516] cm +[1 0 0 1 0 0] Tm +0 0 Td +337.151 582.516 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +-1208 TJm +(At) 9.963 Tj +-349 TJm +(pr) 8.29918 Tj +1 TJm +(esent) 20.474 Tj +-348 TJm +(there) 19.916 Tj +-348 TJm +(is) 6.64532 Tj +-348 TJm +(no) 9.963 Tj +-349 TJm +(f) 3.31768 Tj +10 TJm +(a) 4.42357 Tj +1 TJm +(cility) 20.4839 Tj +-348 TJm +(for) 11.6169 Tj +-348 TJm +(user) 16.5984 Tj +20 TJm +(-de\002ned) 32.6488 Tj +86.944 570.56 Td +(memory) 33.2067 Tj +-250 TJm +(allocators) 38.7361 Tj +-250 TJm +(in) 7.75121 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(\002l) 8.30914 Tj +1 TJm +(e) 4.42357 Tj +-250 TJm +(I/O) 13.2807 Tj +-250 TJm +(functions) 37.0823 Tj +-250 TJm +(\(could) 25.4555 Tj +-250 TJm +(easily) 23.2437 Tj +-250 TJm +(be) 9.40507 Tj +-250 TJm +(added,) 26.2824 Tj +-250 TJm +(though\).) 33.4856 Tj +[1 0 0 1 387.165 570.56] cm +0 g +0 G +[1 0 0 1 -315.165 -12.119] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -548.478] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 529.977 Td +/F121_0 17.215 Tf +(3.4.1.) 43.0719 Tj +[1 0 0 1 119.858 529.977] cm +0 g +0 G +[1 0 0 1 -119.858 -529.977] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.858 529.977 Td +/F387_0 17.215 Tf +(BZ2_bzReadOpen) 144.606 Tj +[1 0 0 1 264.468 529.977] cm +0 g +0 G +[1 0 0 1 -192.468 -2.333] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -72.727] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 71.731 re +f +Q +0 g +0 G +[1 0 0 1 0 3.586] cm +0 g +0 G +[1 0 0 1 0 68.145] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -518.279] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 518.279 Td +/F130_0 9.963 Tf +(typedef) 41.8446 Tj +-426 TJm +(void) 23.9112 Tj +-426 TJm +(BZFILE;) 41.8446 Tj +90 494.369 Td +(BZFILE) 35.8668 Tj +-426 TJm +(*BZ2_bzReadOpen\() 95.6448 Tj +-426 TJm +(i) 5.9778 Tj +1 TJm +(nt) 11.9556 Tj +-426 TJm +(*bzerror,) 53.8002 Tj +-426 TJm +(FILE) 23.9112 Tj +-426 TJm +(*f,) 17.9334 Tj +191.855 482.414 Td +(int) 17.9334 Tj +-426 TJm +(verbosity,) 59.778 Tj +-426 TJm +(int) 17.9334 Tj +-426 TJm +(small,) 35.8668 Tj +191.855 470.458 Td +(void) 23.9112 Tj +-426 TJm +(*unused,) 47.8224 Tj +-426 TJm +(int) 17.9334 Tj +-426 TJm +(nUnused) 41.8446 Tj +-425 TJm +(\);) 11.9556 Tj +[1 0 0 1 72 454.917] cm +0 g +0 G +[1 0 0 1 468 3.586] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.549] cm +0 g +0 G +[1 0 0 1 -72 -444.954] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 432.999 Td +/F128_0 9.963 Tf +(Prepare) 30.427 Tj +-290 TJm +(t) 2.76971 Tj +1 TJm +(o) 4.9815 Tj +-290 TJm +(read) 17.1463 Tj +-290 TJm +(compresse) 42.0538 Tj +1 TJm +(d) 4.9815 Tj +-290 TJm +(data) 16.5984 Tj +-290 TJm +(from) 19.3681 Tj +-289 TJm +(\002le) 12.7327 Tj +-290 TJm +(handle) 26.5614 Tj +[1 0 0 1 272.697 432.999] cm +0 g +0 G +[1 0 0 1 -272.697 -432.999] cm +[1 0 0 1 0 0] Tm +0 0 Td +272.697 432.999 Td +/F130_0 9.963 Tf +(f) 5.9778 Tj +[1 0 0 1 278.675 432.999] cm +0 g +0 G +[1 0 0 1 -278.675 -432.999] cm +[1 0 0 1 0 0] Tm +0 0 Td +278.675 432.999 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 285.439 432.999] cm +0 g +0 G +[1 0 0 1 -285.439 -432.999] cm +[1 0 0 1 0 0] Tm +0 0 Td +285.439 432.999 Td +/F130_0 9.963 Tf +(f) 5.9778 Tj +[1 0 0 1 291.417 432.999] cm +0 g +0 G +[1 0 0 1 -291.417 -432.999] cm +[1 0 0 1 0 0] Tm +0 0 Td +294.302 432.999 Td +/F128_0 9.963 Tf +(should) 26.5713 Tj +-290 TJm +(refer) 18.8002 Tj +-289 TJm +(to) 7.75121 Tj +-290 TJm +(a) 4.42357 Tj +-289 TJm +(\002le) 12.7327 Tj +-290 TJm +(which) 24.3496 Tj +-289 TJm +(has) 13.2807 Tj +-290 TJm +(been) 18.8101 Tj +-290 TJm +(opened) 28.7731 Tj +-289 TJm +(for) 11.6169 Tj +-290 TJm +(reading,) 32.3698 Tj +-299 TJm +(and) 14.3866 Tj +72 421.044 Td +(for) 11.6169 Tj +-306 TJm +(which) 24.3496 Tj +-305 TJm +(the) 12.1748 Tj +-306 TJm +(error) 19.3581 Tj +-305 TJm +(indicator) 35.4185 Tj +-306 TJm +(\() 3.31768 Tj +[1 0 0 1 193.457 421.044] cm +0 g +0 G +[1 0 0 1 -193.457 -421.044] cm +[1 0 0 1 0 0] Tm +0 0 Td +193.457 421.044 Td +/F130_0 9.963 Tf +(ferror\(f\)) 53.8002 Tj +[1 0 0 1 247.255 421.044] cm +0 g +0 G +[1 0 0 1 -247.255 -421.044] cm +[1 0 0 1 0 0] Tm +0 0 Td +247.255 421.044 Td +/F128_0 9.963 Tf +(\)is) 9.963 Tj +-306 TJm +(not) 12.7327 Tj +-305 TJm +(set.) 13.5596 Tj +-954 TJm +(If) 6.63536 Tj +[1 0 0 1 308.784 421.044] cm +0 g +0 G +[1 0 0 1 -308.784 -421.044] cm +[1 0 0 1 0 0] Tm +0 0 Td +308.784 421.044 Td +/F130_0 9.963 Tf +(small) 29.889 Tj +[1 0 0 1 338.672 421.044] cm +0 g +0 G +[1 0 0 1 -338.672 -421.044] cm +[1 0 0 1 0 0] Tm +0 0 Td +341.717 421.044 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-306 TJm +(1,) 7.47225 Tj +-319 TJm +(the) 12.1748 Tj +-306 TJm +(library) 26.5614 Tj +-305 TJm +(will) 15.5024 Tj +-306 TJm +(try) 11.0689 Tj +-305 TJm +(to) 7.75121 Tj +-306 TJm +(decompress) 47.0353 Tj +-306 TJm +(us) 8.85711 Tj +1 TJm +(ing) 12.7327 Tj +-306 TJm +(less) 14.9445 Tj +72 409.089 Td +(memory) 33.2067 Tj +65 TJm +(,) 2.49075 Tj +-250 TJm +(at) 7.19329 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(e) 4.42357 Tj +15 TJm +(xpense) 27.6673 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(spee) 17.7043 Tj +1 TJm +(d.) 7.47225 Tj +[1 0 0 1 72 406.932] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -396.969] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 387.171 Td +/F128_0 9.963 Tf +(F) 5.53943 Tj +15 TJm +(or) 8.29918 Tj +-227 TJm +(reasons) 29.879 Tj +-227 TJm +(e) 4.42357 Tj +15 TJm +(xplained) 34.3126 Tj +-227 TJm +(belo) 17.1563 Tj +25 TJm +(w) 7.19329 Tj +65 TJm +(,) 2.49075 Tj +[1 0 0 1 189.193 387.171] cm +0 g +0 G +[1 0 0 1 -189.193 -387.171] cm +[1 0 0 1 0 0] Tm +0 0 Td +189.193 387.171 Td +/F130_0 9.963 Tf +(BZ2_bzRead) 59.778 Tj +[1 0 0 1 248.969 387.171] cm +0 g +0 G +[1 0 0 1 -248.969 -387.171] cm +[1 0 0 1 0 0] Tm +0 0 Td +251.232 387.171 Td +/F128_0 9.963 Tf +(will) 15.5024 Tj +-227 TJm +(decompress) 47.0353 Tj +-227 TJm +(the) 12.1748 Tj +[1 0 0 1 332.732 387.171] cm +0 g +0 G +[1 0 0 1 -332.732 -387.171] cm +[1 0 0 1 0 0] Tm +0 0 Td +332.732 387.171 Td +/F130_0 9.963 Tf +(nUnused) 41.8446 Tj +[1 0 0 1 374.575 387.171] cm +0 g +0 G +[1 0 0 1 -374.575 -387.171] cm +[1 0 0 1 0 0] Tm +0 0 Td +376.838 387.171 Td +/F128_0 9.963 Tf +(bytes) 21.0319 Tj +-227 TJm +(starting) 29.889 Tj +-227 TJm +(at) 7.19329 Tj +[1 0 0 1 441.74 387.171] cm +0 g +0 G +[1 0 0 1 -441.74 -387.171] cm +[1 0 0 1 0 0] Tm +0 0 Td +441.74 387.171 Td +/F130_0 9.963 Tf +(unused) 35.8668 Tj +[1 0 0 1 477.605 387.171] cm +0 g +0 G +[1 0 0 1 -477.605 -387.171] cm +[1 0 0 1 0 0] Tm +0 0 Td +477.605 387.171 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-232 TJm +(before) 25.4455 Tj +-227 TJm +(starting) 29.889 Tj +72 375.216 Td +(to) 7.75121 Tj +-279 TJm +(read) 17.1463 Tj +-280 TJm +(from) 19.3681 Tj +-279 TJm +(the) 12.1748 Tj +-280 TJm +(\002le) 12.7327 Tj +[1 0 0 1 155.094 375.216] cm +0 g +0 G +[1 0 0 1 -155.094 -375.216] cm +[1 0 0 1 0 0] Tm +0 0 Td +155.094 375.216 Td +/F130_0 9.963 Tf +(f) 5.9778 Tj +[1 0 0 1 161.072 375.216] cm +0 g +0 G +[1 0 0 1 -161.072 -375.216] cm +[1 0 0 1 0 0] Tm +0 0 Td +161.072 375.216 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +-797 TJm +(At) 9.963 Tj +-280 TJm +(most) 19.378 Tj +[1 0 0 1 206.414 375.216] cm +0 g +0 G +[1 0 0 1 -206.414 -375.216] cm +[1 0 0 1 0 0] Tm +0 0 Td +206.414 375.216 Td +/F130_0 9.963 Tf +(BZ_MAX_UNUSED) 77.7114 Tj +[1 0 0 1 284.122 375.216] cm +0 g +0 G +[1 0 0 1 -284.122 -375.216] cm +[1 0 0 1 0 0] Tm +0 0 Td +286.907 375.216 Td +/F128_0 9.963 Tf +(bytes) 21.0319 Tj +-279 TJm +(may) 17.1563 Tj +-280 TJm +(be) 9.40507 Tj +-279 TJm +(supplied) 33.7646 Tj +-280 TJm +(lik) 10.5209 Tj +10 TJm +(e) 4.42357 Tj +-279 TJm +(this.) 16.8873 Tj +-797 TJm +(If) 6.63536 Tj +-280 TJm +(this) 14.3965 Tj +-279 TJm +(f) 3.31768 Tj +10 TJm +(acility) 24.9075 Tj +-280 TJm +(is) 6.64532 Tj +-279 TJm +(not) 12.7327 Tj +-280 TJm +(re) 7.74125 Tj +1 TJm +(quired,) 27.9462 Tj +72 363.26 Td +(you) 14.9445 Tj +-250 TJm +(should) 26.5713 Tj +-250 TJm +(pass) 17.1563 Tj +[1 0 0 1 138.141 363.26] cm +0 g +0 G +[1 0 0 1 -138.141 -363.26] cm +[1 0 0 1 0 0] Tm +0 0 Td +138.141 363.26 Td +/F130_0 9.963 Tf +(NULL) 23.9112 Tj +[1 0 0 1 162.052 363.26] cm +0 g +0 G +[1 0 0 1 -162.052 -363.26] cm +[1 0 0 1 0 0] Tm +0 0 Td +164.542 363.26 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 181.419 363.26] cm +0 g +0 G +[1 0 0 1 -181.419 -363.26] cm +[1 0 0 1 0 0] Tm +0 0 Td +181.419 363.26 Td +/F130_0 9.963 Tf +(0) 5.9778 Tj +[1 0 0 1 187.397 363.26] cm +0 g +0 G +[1 0 0 1 -187.397 -363.26] cm +[1 0 0 1 0 0] Tm +0 0 Td +189.887 363.26 Td +/F128_0 9.963 Tf +(for) 11.6169 Tj +[1 0 0 1 203.994 363.26] cm +0 g +0 G +[1 0 0 1 -203.994 -363.26] cm +[1 0 0 1 0 0] Tm +0 0 Td +203.994 363.26 Td +/F130_0 9.963 Tf +(unused) 35.8668 Tj +[1 0 0 1 239.86 363.26] cm +0 g +0 G +[1 0 0 1 -239.86 -363.26] cm +[1 0 0 1 0 0] Tm +0 0 Td +242.351 363.26 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +-250 TJm +(n) 4.9815 Tj +[1 0 0 1 264.209 363.26] cm +0 g +0 G +[1 0 0 1 -264.209 -363.26] cm +[1 0 0 1 0 0] Tm +0 0 Td +264.209 363.26 Td +/F130_0 9.963 Tf +(Unused) 35.8668 Tj +[1 0 0 1 300.074 363.26] cm +0 g +0 G +[1 0 0 1 -300.074 -363.26] cm +[1 0 0 1 0 0] Tm +0 0 Td +302.565 363.26 Td +/F128_0 9.963 Tf +(respecti) 30.9849 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(ely) 12.1748 Tj +65 TJm +(.) 2.49075 Tj +[1 0 0 1 72 361.104] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -351.141] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 341.343 Td +/F128_0 9.963 Tf +(F) 5.53943 Tj +15 TJm +(or) 8.29918 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(meaning) 34.3126 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(parameter) 39.8321 Tj +1 TJm +(s) 3.87561 Tj +[1 0 0 1 196.631 341.343] cm +0 g +0 G +[1 0 0 1 -196.631 -341.343] cm +[1 0 0 1 0 0] Tm +0 0 Td +196.631 341.343 Td +/F130_0 9.963 Tf +(small) 29.889 Tj +[1 0 0 1 226.519 341.343] cm +0 g +0 G +[1 0 0 1 -226.519 -341.343] cm +[1 0 0 1 0 0] Tm +0 0 Td +229.01 341.343 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 245.887 341.343] cm +0 g +0 G +[1 0 0 1 -245.887 -341.343] cm +[1 0 0 1 0 0] Tm +0 0 Td +245.887 341.343 Td +/F130_0 9.963 Tf +(verbosity) 53.8002 Tj +[1 0 0 1 299.685 341.343] cm +0 g +0 G +[1 0 0 1 -299.685 -341.343] cm +[1 0 0 1 0 0] Tm +0 0 Td +299.685 341.343 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-250 TJm +(see) 12.7228 Tj +[1 0 0 1 319.879 341.343] cm +0 g +0 G +[1 0 0 1 -319.879 -341.343] cm +[1 0 0 1 0 0] Tm +0 0 Td +319.879 341.343 Td +/F130_0 9.963 Tf +(BZ2_bzDecompressInit) 119.556 Tj +[1 0 0 1 439.431 341.343] cm +0 g +0 G +[1 0 0 1 -439.431 -341.343] cm +[1 0 0 1 0 0] Tm +0 0 Td +439.431 341.343 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 72 339.186] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -329.223] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 319.425 Td +/F128_0 9.963 Tf +(The) 15.4925 Tj +-402 TJm +(amount) 29.889 Tj +-402 TJm +(of) 8.29918 Tj +-402 TJm +(mem) 19.926 Tj +1 TJm +(ory) 13.2807 Tj +-402 TJm +(needed) 28.2152 Tj +-402 TJm +(to) 7.75121 Tj +-402 TJm +(decompress) 47.0353 Tj +-402 TJm +(a) 4.42357 Tj +-402 TJm +(\002le) 12.7327 Tj +-402 TJm +(c) 4.42357 Tj +1 TJm +(annot) 22.1378 Tj +-402 TJm +(be) 9.40507 Tj +-402 TJm +(determined) 44.8235 Tj +-402 TJm +(until) 18.2721 Tj +-402 TJm +(the) 12.1748 Tj +-402 TJm +(\002le') 16.0504 Tj +55 TJm +(s) 3.87561 Tj +-401 TJm +(header) 26.5514 Tj +-402 TJm +(has) 13.2807 Tj +-402 TJm +(been) 18.8101 Tj +-402 TJm +(read.) 19.6371 Tj +72 307.47 Td +(So) 10.5209 Tj +-492 TJm +(it) 5.53943 Tj +-491 TJm +(is) 6.64532 Tj +-492 TJm +(possible) 32.6587 Tj +-491 TJm +(that) 14.9445 Tj +[1 0 0 1 166.797 307.47] cm +0 g +0 G +[1 0 0 1 -166.797 -307.47] cm +[1 0 0 1 0 0] Tm +0 0 Td +166.797 307.47 Td +/F130_0 9.963 Tf +(BZ2_bzReadOpen) 83.6892 Tj +[1 0 0 1 250.483 307.47] cm +0 g +0 G +[1 0 0 1 -250.483 -307.47] cm +[1 0 0 1 0 0] Tm +0 0 Td +255.381 307.47 Td +/F128_0 9.963 Tf +(returns) 27.6673 Tj +[1 0 0 1 287.945 307.47] cm +0 g +0 G +[1 0 0 1 -287.945 -307.47] cm +[1 0 0 1 0 0] Tm +0 0 Td +287.945 307.47 Td +/F130_0 9.963 Tf +(BZ_OK) 29.889 Tj +[1 0 0 1 317.833 307.47] cm +0 g +0 G +[1 0 0 1 -317.833 -307.47] cm +[1 0 0 1 0 0] Tm +0 0 Td +322.729 307.47 Td +/F128_0 9.963 Tf +(b) 4.9815 Tj +20 TJm +(ut) 7.75121 Tj +-492 TJm +(a) 4.42357 Tj +-491 TJm +(subsequent) 44.2756 Tj +-492 TJm +(call) 14.3866 Tj +-491 TJm +(of) 8.29918 Tj +[1 0 0 1 431.135 307.47] cm +0 g +0 G +[1 0 0 1 -431.135 -307.47] cm +[1 0 0 1 0 0] Tm +0 0 Td +431.135 307.47 Td +/F130_0 9.963 Tf +(BZ2_bzRead) 59.778 Tj +[1 0 0 1 490.911 307.47] cm +0 g +0 G +[1 0 0 1 -490.911 -307.47] cm +[1 0 0 1 0 0] Tm +0 0 Td +495.81 307.47 Td +/F128_0 9.963 Tf +(will) 15.5024 Tj +-492 TJm +(re) 7.74125 Tj +1 TJm +(turn) 16.0504 Tj +[1 0 0 1 72 295.514] cm +0 g +0 G +[1 0 0 1 -72 -295.514] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 295.514 Td +/F130_0 9.963 Tf +(BZ_MEM_ERROR) 71.7336 Tj +[1 0 0 1 143.731 295.514] cm +0 g +0 G +[1 0 0 1 -143.731 -295.514] cm +[1 0 0 1 0 0] Tm +0 0 Td +143.731 295.514 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 72 294.349] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -284.386] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 273.597 Td +/F128_0 9.963 Tf +(Possible) 33.2166 Tj +-250 TJm +(assignments) 48.7091 Tj +-250 TJm +(to) 7.75121 Tj +[1 0 0 1 169.144 273.597] cm +0 g +0 G +[1 0 0 1 -169.144 -273.597] cm +[1 0 0 1 0 0] Tm +0 0 Td +169.144 273.597 Td +/F130_0 9.963 Tf +(bzerror) 41.8446 Tj +[1 0 0 1 210.987 273.597] cm +0 g +0 G +[1 0 0 1 -210.987 -273.597] cm +[1 0 0 1 0 0] Tm +0 0 Td +210.987 273.597 Td +/F128_0 9.963 Tf +(:) 2.76971 Tj +[1 0 0 1 72 271.44] cm +0 g +0 G +[1 0 0 1 0 -168.369] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 167.372 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 163.786] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -262.075] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 262.075 Td +/F130_0 9.963 Tf +(BZ_CONFIG_ERROR) 89.667 Tj +98.488 250.12 Td +(if) 11.9556 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(library) 41.8446 Tj +-426 TJm +(has) 17.9334 Tj +-426 TJm +(been) 23.9112 Tj +-425 TJm +(mis-compiled) 71.7336 Tj +90 238.165 Td +(BZ_PARAM_ERROR) 83.6892 Tj +98.488 226.209 Td +(if) 11.9556 Tj +-426 TJm +(f) 5.9778 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(NULL) 23.9112 Tj +98.488 214.254 Td +(or) 11.9556 Tj +-426 TJm +(small) 29.889 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(neither) 41.8446 Tj +-426 TJm +(0) 5.9778 Tj +-426 TJm +(no) 11.9556 Tj +1 TJm +(r) 5.9778 Tj +-426 TJm +(1) 5.9778 Tj +98.488 202.299 Td +(or) 11.9556 Tj +-426 TJm +(\() 5.9778 Tj +-426 TJm +(unused) 35.8668 Tj +-426 TJm +(==) 11.9556 Tj +-426 TJm +(NULL) 23.9112 Tj +-426 TJm +(&&) 11.9556 Tj +-426 TJm +(n) 5.9778 Tj +1 TJm +(Unused) 35.8668 Tj +-426 TJm +(!=) 11.9556 Tj +-426 TJm +(0) 5.9778 Tj +-426 TJm +(\)) 5.9778 Tj +98.488 190.344 Td +(or) 11.9556 Tj +-426 TJm +(\() 5.9778 Tj +-426 TJm +(unused) 35.8668 Tj +-426 TJm +(!=) 11.9556 Tj +-426 TJm +(NULL) 23.9112 Tj +-426 TJm +(&&) 11.9556 Tj +-426 TJm +(!) 5.9778 Tj +1 TJm +(\(0) 11.9556 Tj +-426 TJm +(<=) 11.9556 Tj +-426 TJm +(nUnused) 41.8446 Tj +-426 TJm +(<=) 11.9556 Tj +-426 TJm +(BZ_MAX_UNUSED\)) 83.6892 Tj +-426 TJm +(\)) 5.9778 Tj +90 178.389 Td +(BZ_IO_ERROR) 65.7558 Tj +98.488 166.434 Td +(if) 11.9556 Tj +-426 TJm +(ferror\(f\)) 53.8002 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(nonzero) 41.8446 Tj +90 154.478 Td +(BZ_MEM_ERROR) 71.7336 Tj +98.488 142.523 Td +(if) 11.9556 Tj +-426 TJm +(insufficient) 71.7336 Tj +-426 TJm +(memory) 35.8668 Tj +-426 TJm +(is) 11.9556 Tj +-425 TJm +(available) 53.8002 Tj +90 130.568 Td +(BZ_OK) 29.889 Tj +98.488 118.613 Td +(otherwise.) 59.778 Tj +[1 0 0 1 72 103.071] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.549] cm +0 g +0 G +[1 0 0 1 -72 -93.109] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 81.153 Td +/F128_0 9.963 Tf +(Possible) 33.2166 Tj +-250 TJm +(return) 23.7916 Tj +-250 TJm +(v) 4.9815 Tj +25 TJm +(alues:) 23.2437 Tj +[1 0 0 1 72 81.054] cm +0 g +0 G +[1 0 0 1 0 -30.202] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.974] cm +0 g +0 G +0 g +0 G +[1 0 0 1 40.572 -6.755] cm +0 g +0 G +[1 0 0 1 -493.841 -51.071] cm +[1 0 0 1 0 0] Tm +0 0 Td +534.414 51.071 Td +/F128_0 9.963 Tf +(19) 9.963 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 23 23 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 -8.911] cm +0 g +0 G +[1 0 0 1 0 8.911] cm +0 g +0 G +0 g +0 G +[1 0 0 1 84.08 -6.755] cm +0 g +0 G +[1 0 0 1 -350.151 -749.245] cm +[1 0 0 1 0 0] Tm +0 0 Td +434.231 749.245 Td +/F128_0 9.963 Tf +(Programming) 54.7965 Tj +-250 TJm +(with) 17.7142 Tj +-250 TJm +(libbzip2) 32.6587 Tj +[1 0 0 1 266.071 747.089] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -5.037] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -468 -81.33] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 59.776 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 56.189] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -711.631] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 711.631 Td +/F130_0 9.963 Tf +(Pointer) 41.8446 Tj +-426 TJm +(to) 11.9556 Tj +-426 TJm +(an) 11.9556 Tj +-426 TJm +(abstract) 47.8224 Tj +-426 TJm +(B) 5.9778 Tj +1 TJm +(ZFILE) 29.889 Tj +98.488 699.676 Td +(if) 11.9556 Tj +-426 TJm +(bzerror) 41.8446 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(BZ_OK) 29.889 Tj +90 687.721 Td +(NULL) 23.9112 Tj +98.488 675.766 Td +(otherwise) 53.8002 Tj +[1 0 0 1 72 660.224] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.55] cm +0 g +0 G +[1 0 0 1 -72 -650.261] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 638.306 Td +/F128_0 9.963 Tf +(Allo) 17.7142 Tj +25 TJm +(w) 7.19329 Tj +10 TJm +(able) 16.5984 Tj +-250 TJm +(ne) 9.40507 Tj +15 TJm +(xt) 7.75121 Tj +-250 TJm +(actions:) 30.9949 Tj +[1 0 0 1 72 638.207] cm +0 g +0 G +[1 0 0 1 0 -60.772] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 59.776 re +f +Q +0 g +0 G +[1 0 0 1 0 3.586] cm +0 g +0 G +[1 0 0 1 0 56.19] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -628.842] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 628.842 Td +/F130_0 9.963 Tf +(BZ2_bzRead) 59.778 Tj +98.488 616.887 Td +(if) 11.9556 Tj +-426 TJm +(bzerror) 41.8446 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(BZ_OK) 29.889 Tj +90 604.932 Td +(BZ2_bzClose) 65.7558 Tj +98.488 592.976 Td +(otherwise) 53.8002 Tj +[1 0 0 1 72 577.435] cm +0 g +0 G +[1 0 0 1 468 3.586] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -3.586] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -567.472] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 546.814 Td +/F121_0 17.215 Tf +(3.4.2.) 43.0719 Tj +[1 0 0 1 119.858 546.814] cm +0 g +0 G +[1 0 0 1 -119.858 -546.814] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.858 546.814 Td +/F387_0 17.215 Tf +(BZ2_bzRead) 103.29 Tj +[1 0 0 1 223.151 546.814] cm +0 g +0 G +[1 0 0 1 -151.151 -2.333] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -24.907] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 23.91 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 20.324] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -535.116] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 535.116 Td +/F130_0 9.963 Tf +(int) 17.9334 Tj +-426 TJm +(BZ2_bzRead) 59.778 Tj +-426 TJm +(\() 5.9778 Tj +-426 TJm +(int) 17.9334 Tj +-426 TJm +(*bz) 17.9334 Tj +1 TJm +(error,) 35.8668 Tj +-426 TJm +(BZFILE) 35.8668 Tj +-426 TJm +(*b,) 17.9334 Tj +-426 TJm +(void) 23.9112 Tj +-426 TJm +(*buf,) 29.889 Tj +-426 TJm +(int) 17.9334 Tj +-426 TJm +(len) 17.9334 Tj +-426 TJm +(\);) 11.9556 Tj +[1 0 0 1 72 519.574] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.549] cm +0 g +0 G +[1 0 0 1 -72 -509.612] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 497.656 Td +/F128_0 9.963 Tf +(Reads) 24.3496 Tj +-284 TJm +(up) 9.963 Tj +-285 TJm +(to) 7.75121 Tj +[1 0 0 1 122.569 497.656] cm +0 g +0 G +[1 0 0 1 -122.569 -497.656] cm +[1 0 0 1 0 0] Tm +0 0 Td +122.569 497.656 Td +/F130_0 9.963 Tf +(len) 17.9334 Tj +[1 0 0 1 140.501 497.656] cm +0 g +0 G +[1 0 0 1 -140.501 -497.656] cm +[1 0 0 1 0 0] Tm +0 0 Td +143.337 497.656 Td +/F128_0 9.963 Tf +(\(uncompressed\)) 63.6337 Tj +-284 TJm +(bytes) 21.0319 Tj +-285 TJm +(from) 19.3681 Tj +-284 TJm +(the) 12.1748 Tj +-285 TJm +(compressed) 47.0353 Tj +-284 TJm +(\002le) 12.7327 Tj +[1 0 0 1 336.319 497.656] cm +0 g +0 G +[1 0 0 1 -336.319 -497.656] cm +[1 0 0 1 0 0] Tm +0 0 Td +336.319 497.656 Td +/F130_0 9.963 Tf +(b) 5.9778 Tj +[1 0 0 1 342.296 497.656] cm +0 g +0 G +[1 0 0 1 -342.296 -497.656] cm +[1 0 0 1 0 0] Tm +0 0 Td +345.132 497.656 Td +/F128_0 9.963 Tf +(into) 15.5024 Tj +-285 TJm +(t) 2.76971 Tj +1 TJm +(he) 9.40507 Tj +-285 TJm +(b) 4.9815 Tj +20 TJm +(uf) 8.29918 Tj +25 TJm +(fer) 11.0589 Tj +[1 0 0 1 405.205 497.656] cm +0 g +0 G +[1 0 0 1 -405.205 -497.656] cm +[1 0 0 1 0 0] Tm +0 0 Td +405.205 497.656 Td +/F130_0 9.963 Tf +(buf) 17.9334 Tj +[1 0 0 1 423.137 497.656] cm +0 g +0 G +[1 0 0 1 -423.137 -497.656] cm +[1 0 0 1 0 0] Tm +0 0 Td +423.137 497.656 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +-828 TJm +(If) 6.63536 Tj +-284 TJm +(the) 12.1748 Tj +-285 TJm +(read) 17.1463 Tj +-284 TJm +(w) 7.19329 Tj +10 TJm +(as) 8.29918 Tj +-285 TJm +(successful,) 43.4387 Tj +[1 0 0 1 72 485.701] cm +0 g +0 G +[1 0 0 1 -72 -485.701] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 485.701 Td +/F130_0 9.963 Tf +(bzerror) 41.8446 Tj +[1 0 0 1 113.843 485.701] cm +0 g +0 G +[1 0 0 1 -113.843 -485.701] cm +[1 0 0 1 0 0] Tm +0 0 Td +117.36 485.701 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-353 TJm +(set) 11.0689 Tj +-353 TJm +(to) 7.75121 Tj +[1 0 0 1 153.374 485.701] cm +0 g +0 G +[1 0 0 1 -153.374 -485.701] cm +[1 0 0 1 0 0] Tm +0 0 Td +153.374 485.701 Td +/F130_0 9.963 Tf +(BZ_OK) 29.889 Tj +[1 0 0 1 183.262 485.701] cm +0 g +0 G +[1 0 0 1 -183.262 -485.701] cm +[1 0 0 1 0 0] Tm +0 0 Td +186.778 485.701 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +-353 TJm +(the) 12.1748 Tj +-353 TJm +(number) 30.437 Tj +-353 TJm +(of) 8.29918 Tj +-353 TJm +(bytes) 21.0319 Tj +-353 TJm +(read) 17.1463 Tj +-352 TJm +(is) 6.64532 Tj +-353 TJm +(returned.) 35.6875 Tj +-1238 TJm +(If) 6.63536 Tj +-353 TJm +(the) 12.1748 Tj +-353 TJm +(logical) 27.1193 Tj +-353 TJm +(end-of-stream) 55.8825 Tj +-353 TJm +(w) 7.19329 Tj +10 TJm +(as) 8.29918 Tj +-353 TJm +(detecte) 28.2152 Tj +1 TJm +(d,) 7.47225 Tj +[1 0 0 1 72 473.746] cm +0 g +0 G +[1 0 0 1 -72 -473.746] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 473.746 Td +/F130_0 9.963 Tf +(bzerror) 41.8446 Tj +[1 0 0 1 113.843 473.746] cm +0 g +0 G +[1 0 0 1 -113.843 -473.746] cm +[1 0 0 1 0 0] Tm +0 0 Td +116.795 473.746 Td +/F128_0 9.963 Tf +(will) 15.5024 Tj +-296 TJm +(be) 9.40507 Tj +-296 TJm +(set) 11.0689 Tj +-297 TJm +(to) 7.75121 Tj +[1 0 0 1 172.328 473.746] cm +0 g +0 G +[1 0 0 1 -172.328 -473.746] cm +[1 0 0 1 0 0] Tm +0 0 Td +172.328 473.746 Td +/F130_0 9.963 Tf +(BZ_STREAM_END) 77.7114 Tj +[1 0 0 1 250.037 473.746] cm +0 g +0 G +[1 0 0 1 -250.037 -473.746] cm +[1 0 0 1 0 0] Tm +0 0 Td +250.037 473.746 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-296 TJm +(and) 14.3866 Tj +-297 TJm +(th) 7.75121 Tj +1 TJm +(e) 4.42357 Tj +-297 TJm +(number) 30.437 Tj +-296 TJm +(of) 8.29918 Tj +-296 TJm +(bytes) 21.0319 Tj +-296 TJm +(read) 17.1463 Tj +-297 TJm +(is) 6.64532 Tj +-296 TJm +(returned.) 35.6875 Tj +-898 TJm +(All) 12.7327 Tj +-296 TJm +(other) 20.474 Tj +[1 0 0 1 470 473.746] cm +0 g +0 G +[1 0 0 1 -470 -473.746] cm +[1 0 0 1 0 0] Tm +0 0 Td +470 473.746 Td +/F130_0 9.963 Tf +(bzerror) 41.8446 Tj +[1 0 0 1 511.843 473.746] cm +0 g +0 G +[1 0 0 1 -511.843 -473.746] cm +[1 0 0 1 0 0] Tm +0 0 Td +514.795 473.746 Td +/F128_0 9.963 Tf +(v) 4.9815 Tj +25 TJm +(alues) 20.474 Tj +72 461.791 Td +(denote) 26.5614 Tj +-250 TJm +(an) 9.40507 Tj +-250 TJm +(error) 19.3581 Tj +55 TJm +(.) 2.49075 Tj +[1 0 0 1 72 461.691] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -451.729] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 439.873 Td +/F130_0 9.963 Tf +(BZ2_bzRead) 59.778 Tj +[1 0 0 1 131.776 439.873] cm +0 g +0 G +[1 0 0 1 -131.776 -439.873] cm +[1 0 0 1 0 0] Tm +0 0 Td +134.224 439.873 Td +/F128_0 9.963 Tf +(will) 15.5024 Tj +-246 TJm +(supply) 26.5713 Tj +[1 0 0 1 181.193 439.873] cm +0 g +0 G +[1 0 0 1 -181.193 -439.873] cm +[1 0 0 1 0 0] Tm +0 0 Td +181.193 439.873 Td +/F130_0 9.963 Tf +(len) 17.9334 Tj +[1 0 0 1 199.126 439.873] cm +0 g +0 G +[1 0 0 1 -199.126 -439.873] cm +[1 0 0 1 0 0] Tm +0 0 Td +201.575 439.873 Td +/F128_0 9.963 Tf +(bytes,) 23.5226 Tj +-246 TJm +(unless) 24.9075 Tj +-246 TJm +(the) 12.1748 Tj +-246 TJm +(logical) 27.1193 Tj +-245 TJm +(stream) 26.5614 Tj +-246 TJm +(end) 14.3866 Tj +-246 TJm +(is) 6.64532 Tj +-246 TJm +(detec) 21.0219 Tj +1 TJm +(ted) 12.1748 Tj +-246 TJm +(or) 8.29918 Tj +-246 TJm +(an) 9.40507 Tj +-246 TJm +(error) 19.3581 Tj +-245 TJm +(occurs.) 28.4942 Tj +-617 TJm +(Because) 33.1967 Tj +-246 TJm +(of) 8.29918 Tj +-246 TJm +(this,) 16.8873 Tj +-246 TJm +(it) 5.53943 Tj +72 427.918 Td +(is) 6.64532 Tj +-231 TJm +(possible) 32.6587 Tj +-231 TJm +(to) 7.75121 Tj +-231 TJm +(detect) 23.7916 Tj +-231 TJm +(the) 12.1748 Tj +-231 TJm +(stream) 26.5614 Tj +-231 TJm +(end) 14.3866 Tj +-231 TJm +(by) 9.963 Tj +-231 TJm +(observing) 39.2941 Tj +-231 TJm +(when) 21.5799 Tj +-231 TJm +(the) 12.1748 Tj +-231 TJm +(number) 30.437 Tj +-231 TJm +(of) 8.29918 Tj +-231 TJm +(bytes) 21.0319 Tj +-231 TJm +(returned) 33.1967 Tj +-231 TJm +(is) 6.64532 Tj +-231 TJm +(less) 14.9445 Tj +-231 TJm +(than) 17.1563 Tj +-231 TJm +(the) 12.1748 Tj +-231 TJm +(number) 30.437 Tj +-231 TJm +(requested.) 40.669 Tj +72 415.963 Td +(Ne) 11.6169 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(ertheless,) 37.3513 Tj +-309 TJm +(this) 14.3965 Tj +-297 TJm +(is) 6.64532 Tj +-297 TJm +(re) 7.74125 Tj +15 TJm +(g) 4.9815 Tj +5 TJm +(arded) 22.1278 Tj +-298 TJm +(as) 8.29918 Tj +-297 TJm +(inadvisable;) 48.1512 Tj +-321 TJm +(you) 14.9445 Tj +-297 TJm +(should) 26.5713 Tj +-297 TJm +(instead) 28.2252 Tj +-297 TJm +(check) 23.2337 Tj +[1 0 0 1 360.631 415.963] cm +0 g +0 G +[1 0 0 1 -360.631 -415.963] cm +[1 0 0 1 0 0] Tm +0 0 Td +360.631 415.963 Td +/F130_0 9.963 Tf +(bzerror) 41.8446 Tj +[1 0 0 1 402.475 415.963] cm +0 g +0 G +[1 0 0 1 -402.475 -415.963] cm +[1 0 0 1 0 0] Tm +0 0 Td +405.437 415.963 Td +/F128_0 9.963 Tf +(after) 18.2522 Tj +-297 TJm +(e) 4.42357 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(ery) 12.7228 Tj +-297 TJm +(call) 14.3866 Tj +-298 TJm +(and) 14.3866 Tj +-297 TJm +(w) 7.19329 Tj +10 TJm +(atch) 16.5984 Tj +-297 TJm +(out) 12.7327 Tj +-297 TJm +(for) 11.6169 Tj +[1 0 0 1 72 404.008] cm +0 g +0 G +[1 0 0 1 -72 -404.008] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 404.008 Td +/F130_0 9.963 Tf +(BZ_STREAM_END) 77.7114 Tj +[1 0 0 1 149.709 404.008] cm +0 g +0 G +[1 0 0 1 -149.709 -404.008] cm +[1 0 0 1 0 0] Tm +0 0 Td +149.709 404.008 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 72 402.842] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -392.879] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 382.09 Td +/F128_0 9.963 Tf +(Internally) 38.7361 Tj +65 TJm +(,) 2.49075 Tj +[1 0 0 1 117.541 382.09] cm +0 g +0 G +[1 0 0 1 -117.541 -382.09] cm +[1 0 0 1 0 0] Tm +0 0 Td +117.541 382.09 Td +/F130_0 9.963 Tf +(BZ2_bzRead) 59.778 Tj +[1 0 0 1 177.317 382.09] cm +0 g +0 G +[1 0 0 1 -177.317 -382.09] cm +[1 0 0 1 0 0] Tm +0 0 Td +181.786 382.09 Td +/F128_0 9.963 Tf +(copies) 25.4555 Tj +-448 TJm +(data) 16.5984 Tj +-449 TJm +(from) 19.3681 Tj +-448 TJm +(the) 12.1748 Tj +-449 TJm +(compressed) 47.0353 Tj +-448 TJm +(\002le) 12.7327 Tj +-449 TJm +(in) 7.75121 Tj +-448 TJm +(chunks) 28.2252 Tj +-449 TJm +(of) 8.29918 Tj +-448 TJm +(size) 15.4925 Tj +[1 0 0 1 419.602 382.09] cm +0 g +0 G +[1 0 0 1 -419.602 -382.09] cm +[1 0 0 1 0 0] Tm +0 0 Td +419.602 382.09 Td +/F130_0 9.963 Tf +(BZ_MAX_UNUSED) 77.7114 Tj +[1 0 0 1 497.311 382.09] cm +0 g +0 G +[1 0 0 1 -497.311 -382.09] cm +[1 0 0 1 0 0] Tm +0 0 Td +501.778 382.09 Td +/F128_0 9.963 Tf +(bytes) 21.0319 Tj +-448 TJm +(be-) 12.7228 Tj +72 370.135 Td +(fore) 16.0404 Tj +-414 TJm +(decompressing) 59.768 Tj +-414 TJm +(it.) 8.03018 Tj +-1605 TJm +(If) 6.63536 Tj +-414 TJm +(the) 12.1748 Tj +-414 TJm +(\002le) 12.7327 Tj +-414 TJm +(contains) 33.2067 Tj +-414 TJm +(more) 20.474 Tj +-415 TJm +(by) 9.963 Tj +1 TJm +(tes) 11.0689 Tj +-415 TJm +(than) 17.1563 Tj +-414 TJm +(strictly) 27.6772 Tj +-414 TJm +(needed) 28.2152 Tj +-414 TJm +(to) 7.75121 Tj +-414 TJm +(reach) 21.5699 Tj +-414 TJm +(the) 12.1748 Tj +-414 TJm +(logical) 27.1193 Tj +-414 TJm +(end-of-stream,) 58.3732 Tj +[1 0 0 1 72 358.18] cm +0 g +0 G +[1 0 0 1 -72 -358.18] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 358.18 Td +/F130_0 9.963 Tf +(BZ2_bzRead) 59.778 Tj +[1 0 0 1 131.776 358.18] cm +0 g +0 G +[1 0 0 1 -131.776 -358.18] cm +[1 0 0 1 0 0] Tm +0 0 Td +134.749 358.18 Td +/F128_0 9.963 Tf +(will) 15.5024 Tj +-298 TJm +(almost) 26.5713 Tj +-299 TJm +(certainly) 34.8605 Tj +-298 TJm +(read) 17.1463 Tj +-298 TJm +(some) 21.0319 Tj +-299 TJm +(of) 8.29918 Tj +-298 TJm +(the) 12.1748 Tj +-299 TJm +(t) 2.76971 Tj +1 TJm +(railing) 26.0134 Tj +-299 TJm +(data) 16.5984 Tj +-298 TJm +(before) 25.4455 Tj +-299 TJm +(s) 3.87561 Tj +1 TJm +(ignalling) 35.4284 Tj +[1 0 0 1 413.162 358.18] cm +0 g +0 G +[1 0 0 1 -413.162 -358.18] cm +[1 0 0 1 0 0] Tm +0 0 Td +413.162 358.18 Td +/F130_0 9.963 Tf +(BZ_SEQUENCE_END) 89.667 Tj +[1 0 0 1 502.826 358.18] cm +0 g +0 G +[1 0 0 1 -502.826 -358.18] cm +[1 0 0 1 0 0] Tm +0 0 Td +502.826 358.18 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +-597 TJm +(T) 6.08739 Tj +80 TJm +(o) 4.9815 Tj +-298 TJm +(col-) 15.4925 Tj +72 346.224 Td +(lect) 14.3866 Tj +-242 TJm +(the) 12.1748 Tj +-242 TJm +(read) 17.1463 Tj +-242 TJm +(b) 4.9815 Tj +20 TJm +(ut) 7.75121 Tj +-242 TJm +(unused) 28.2252 Tj +-243 TJm +(d) 4.9815 Tj +1 TJm +(ata) 11.6169 Tj +-243 TJm +(once) 18.8101 Tj +[1 0 0 1 208.759 346.224] cm +0 g +0 G +[1 0 0 1 -208.759 -346.224] cm +[1 0 0 1 0 0] Tm +0 0 Td +208.759 346.224 Td +/F130_0 9.963 Tf +(BZ_SEQUENCE_END) 89.667 Tj +[1 0 0 1 298.423 346.224] cm +0 g +0 G +[1 0 0 1 -298.423 -346.224] cm +[1 0 0 1 0 0] Tm +0 0 Td +300.835 346.224 Td +/F128_0 9.963 Tf +(has) 13.2807 Tj +-242 TJm +(appeared,) 38.4472 Tj +-244 TJm +(call) 14.3866 Tj +[1 0 0 1 374.201 346.224] cm +0 g +0 G +[1 0 0 1 -374.201 -346.224] cm +[1 0 0 1 0 0] Tm +0 0 Td +374.201 346.224 Td +/F130_0 9.963 Tf +(BZ2_bzReadGetUnused) 113.578 Tj +[1 0 0 1 487.775 346.224] cm +0 g +0 G +[1 0 0 1 -487.775 -346.224] cm +[1 0 0 1 0 0] Tm +0 0 Td +490.188 346.224 Td +/F128_0 9.963 Tf +(immediately) 49.815 Tj +72 334.269 Td +(before) 25.4455 Tj +[1 0 0 1 99.935 334.269] cm +0 g +0 G +[1 0 0 1 -99.935 -334.269] cm +[1 0 0 1 0 0] Tm +0 0 Td +99.935 334.269 Td +/F130_0 9.963 Tf +(BZ2_bzReadClose) 89.667 Tj +[1 0 0 1 189.599 334.269] cm +0 g +0 G +[1 0 0 1 -189.599 -334.269] cm +[1 0 0 1 0 0] Tm +0 0 Td +189.599 334.269 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 72 333.104] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -323.141] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 312.351 Td +/F128_0 9.963 Tf +(Possible) 33.2166 Tj +-250 TJm +(assignments) 48.7091 Tj +-250 TJm +(to) 7.75121 Tj +[1 0 0 1 169.144 312.351] cm +0 g +0 G +[1 0 0 1 -169.144 -312.351] cm +[1 0 0 1 0 0] Tm +0 0 Td +169.144 312.351 Td +/F130_0 9.963 Tf +(bzerror) 41.8446 Tj +[1 0 0 1 210.987 312.351] cm +0 g +0 G +[1 0 0 1 -210.987 -312.351] cm +[1 0 0 1 0 0] Tm +0 0 Td +210.987 312.351 Td +/F128_0 9.963 Tf +(:) 2.76971 Tj +[1 0 0 1 72 310.195] cm +0 g +0 G +[1 0 0 1 0 -259.343] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.854] cm +0 g +0 G +0 g +0 G +[1 0 0 1 40.572 -6.755] cm +0 g +0 G +[1 0 0 1 -493.841 -50.951] cm +[1 0 0 1 0 0] Tm +0 0 Td +534.414 50.951 Td +/F128_0 9.963 Tf +(20) 9.963 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 24 24 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 -8.911] cm +0 g +0 G +[1 0 0 1 0 8.911] cm +0 g +0 G +0 g +0 G +[1 0 0 1 84.08 -6.755] cm +0 g +0 G +[1 0 0 1 -350.151 -749.245] cm +[1 0 0 1 0 0] Tm +0 0 Td +434.231 749.245 Td +/F128_0 9.963 Tf +(Programming) 54.7965 Tj +-250 TJm +(with) 17.7142 Tj +-250 TJm +(libbzip2) 32.6587 Tj +[1 0 0 1 266.071 747.089] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -5.037] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -468 -284.568] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 263.014 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 259.427] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -711.631] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 711.631 Td +/F130_0 9.963 Tf +(BZ_PARAM_ERROR) 83.6892 Tj +98.488 699.676 Td +(if) 11.9556 Tj +-426 TJm +(b) 5.9778 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(NULL) 23.9112 Tj +-426 TJm +(or) 11.9556 Tj +-426 TJm +(buf) 17.9334 Tj +-426 TJm +(is) 11.9556 Tj +-425 TJm +(NULL) 23.9112 Tj +-426 TJm +(or) 11.9556 Tj +-426 TJm +(len) 17.9334 Tj +-426 TJm +(<) 5.9778 Tj +-426 TJm +(0) 5.9778 Tj +90 687.721 Td +(BZ_SEQUENCE_ERROR) 101.623 Tj +98.488 675.766 Td +(if) 11.9556 Tj +-426 TJm +(b) 5.9778 Tj +-426 TJm +(was) 17.9334 Tj +-426 TJm +(opened) 35.8668 Tj +-426 TJm +(with) 23.9112 Tj +-426 TJm +(BZ2) 17.9334 Tj +1 TJm +(_bzWriteOpen) 71.7336 Tj +90 663.811 Td +(BZ_IO_ERROR) 65.7558 Tj +98.488 651.856 Td +(if) 11.9556 Tj +-426 TJm +(there) 29.889 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(an) 11.9556 Tj +-426 TJm +(error) 29.889 Tj +-426 TJm +(rea) 17.9334 Tj +1 TJm +(ding) 23.9112 Tj +-426 TJm +(from) 23.9112 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(compressed) 59.778 Tj +-426 TJm +(file) 23.9112 Tj +90 639.9 Td +(BZ_UNEXPECTED_EOF) 101.623 Tj +98.488 627.945 Td +(if) 11.9556 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(compressed) 59.778 Tj +-426 TJm +(file) 23.9112 Tj +-426 TJm +(e) 5.9778 Tj +1 TJm +(nded) 23.9112 Tj +-426 TJm +(before) 35.8668 Tj +98.488 615.99 Td +(the) 17.9334 Tj +-426 TJm +(logical) 41.8446 Tj +-426 TJm +(end-of-stream) 77.7114 Tj +-425 TJm +(was) 17.9334 Tj +-426 TJm +(detected) 47.8224 Tj +90 604.035 Td +(BZ_DATA_ERROR) 77.7114 Tj +98.488 592.08 Td +(if) 11.9556 Tj +-426 TJm +(a) 5.9778 Tj +-426 TJm +(data) 23.9112 Tj +-426 TJm +(integrity) 53.8002 Tj +-426 TJm +(erro) 23.9112 Tj +1 TJm +(r) 5.9778 Tj +-426 TJm +(was) 17.9334 Tj +-426 TJm +(detected) 47.8224 Tj +-426 TJm +(in) 11.9556 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(compressed) 59.778 Tj +-426 TJm +(stream) 35.8668 Tj +90 580.124 Td +(BZ_DATA_ERROR_MAGIC) 113.578 Tj +98.488 568.169 Td +(if) 11.9556 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(stream) 35.8668 Tj +-426 TJm +(does) 23.9112 Tj +-426 TJm +(not) 17.9334 Tj +-426 TJm +(b) 5.9778 Tj +1 TJm +(egin) 23.9112 Tj +-426 TJm +(with) 23.9112 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(requisite) 53.8002 Tj +-426 TJm +(header) 35.8668 Tj +-426 TJm +(bytes) 29.889 Tj +98.488 556.214 Td +(\(ie,) 23.9112 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(not) 17.9334 Tj +-426 TJm +(a) 5.9778 Tj +-426 TJm +(bzip2) 29.889 Tj +-426 TJm +(data) 23.9112 Tj +-425 TJm +(file\).) 35.8668 Tj +-852 TJm +(This) 23.9112 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(really) 35.8668 Tj +98.488 544.259 Td +(a) 5.9778 Tj +-426 TJm +(special) 41.8446 Tj +-426 TJm +(case) 23.9112 Tj +-426 TJm +(of) 11.9556 Tj +-426 TJm +(BZ_DAT) 35.8668 Tj +1 TJm +(A_ERROR.) 47.8224 Tj +90 532.304 Td +(BZ_MEM_ERROR) 71.7336 Tj +98.488 520.349 Td +(if) 11.9556 Tj +-426 TJm +(insufficient) 71.7336 Tj +-426 TJm +(memory) 35.8668 Tj +-426 TJm +(wa) 11.9556 Tj +1 TJm +(s) 5.9778 Tj +-426 TJm +(available) 53.8002 Tj +90 508.393 Td +(BZ_STREAM_END) 77.7114 Tj +98.488 496.438 Td +(if) 11.9556 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(logical) 41.8446 Tj +-426 TJm +(end) 17.9334 Tj +-426 TJm +(of) 11.9556 Tj +-426 TJm +(st) 11.9556 Tj +1 TJm +(ream) 23.9112 Tj +-426 TJm +(was) 17.9334 Tj +-426 TJm +(detected.) 53.8002 Tj +90 484.483 Td +(BZ_OK) 29.889 Tj +98.488 472.528 Td +(otherwise.) 59.778 Tj +[1 0 0 1 72 456.986] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.549] cm +0 g +0 G +[1 0 0 1 -72 -447.024] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 435.068 Td +/F128_0 9.963 Tf +(Possible) 33.2166 Tj +-250 TJm +(return) 23.7916 Tj +-250 TJm +(v) 4.9815 Tj +25 TJm +(alues:) 23.2437 Tj +[1 0 0 1 72 434.969] cm +0 g +0 G +[1 0 0 1 0 -60.772] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 59.776 re +f +Q +0 g +0 G +[1 0 0 1 0 3.586] cm +0 g +0 G +[1 0 0 1 0 56.19] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -425.604] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 425.604 Td +/F130_0 9.963 Tf +(number) 35.8668 Tj +-426 TJm +(of) 11.9556 Tj +-426 TJm +(bytes) 29.889 Tj +-426 TJm +(read) 23.9112 Tj +98.488 413.649 Td +(if) 11.9556 Tj +-426 TJm +(bzerror) 41.8446 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(BZ_OK) 29.889 Tj +-426 TJm +(or) 11.9556 Tj +-426 TJm +(B) 5.9778 Tj +1 TJm +(Z_STREAM_END) 71.7336 Tj +90 401.694 Td +(undefined) 53.8002 Tj +98.488 389.739 Td +(otherwise) 53.8002 Tj +[1 0 0 1 72 374.197] cm +0 g +0 G +[1 0 0 1 468 3.586] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.549] cm +0 g +0 G +[1 0 0 1 -72 -364.234] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 352.279 Td +/F128_0 9.963 Tf +(Allo) 17.7142 Tj +25 TJm +(w) 7.19329 Tj +10 TJm +(able) 16.5984 Tj +-250 TJm +(ne) 9.40507 Tj +15 TJm +(xt) 7.75121 Tj +-250 TJm +(actions:) 30.9949 Tj +[1 0 0 1 72 352.179] cm +0 g +0 G +[1 0 0 1 0 -84.682] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 83.686 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 80.099] cm +0 g +0 G +[1 0 0 1 18 -8.368] cm +0 g +0 G +[1 0 0 1 -90 -342.815] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 342.815 Td +/F130_0 9.963 Tf +(collect) 41.8446 Tj +-426 TJm +(data) 23.9112 Tj +-426 TJm +(from) 23.9112 Tj +-426 TJm +(buf,) 23.9112 Tj +-426 TJm +(t) 5.9778 Tj +1 TJm +(hen) 17.9334 Tj +-426 TJm +(BZ2_bzRead) 59.778 Tj +-426 TJm +(or) 11.9556 Tj +-426 TJm +(BZ2_bzReadClose) 89.667 Tj +98.488 330.859 Td +(if) 11.9556 Tj +-426 TJm +(bzerror) 41.8446 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(BZ_OK) 29.889 Tj +90 318.904 Td +(collect) 41.8446 Tj +-426 TJm +(data) 23.9112 Tj +-426 TJm +(from) 23.9112 Tj +-426 TJm +(buf,) 23.9112 Tj +-426 TJm +(t) 5.9778 Tj +1 TJm +(hen) 17.9334 Tj +-426 TJm +(BZ2_bzReadClose) 89.667 Tj +-426 TJm +(or) 11.9556 Tj +-426 TJm +(BZ2_bzReadGetUnused) 113.578 Tj +98.488 306.949 Td +(if) 11.9556 Tj +-426 TJm +(bzerror) 41.8446 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(BZ_SEQUENCE) 65.7558 Tj +1 TJm +(_END) 23.9112 Tj +90 294.994 Td +(BZ2_bzReadClose) 89.667 Tj +98.488 283.039 Td +(otherwise) 53.8002 Tj +[1 0 0 1 72 267.497] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -3.587] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -257.534] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 236.876 Td +/F121_0 17.215 Tf +(3.4.3.) 43.0719 Tj +[1 0 0 1 119.858 236.876] cm +0 g +0 G +[1 0 0 1 -119.858 -236.876] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.858 236.876 Td +/F387_0 17.215 Tf +(BZ2_bzReadGetUnused) 196.251 Tj +[1 0 0 1 316.114 236.876] cm +0 g +0 G +[1 0 0 1 -244.114 -2.333] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -36.862] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 35.866 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 32.279] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -225.178] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 225.178 Td +/F130_0 9.963 Tf +(void) 23.9112 Tj +-426 TJm +(BZ2_bzReadGetUnused\() 119.556 Tj +-425 TJm +(int*) 23.9112 Tj +-426 TJm +(bzerror,) 47.8224 Tj +-426 TJm +(BZFILE) 35.8668 Tj +-426 TJm +(*b,) 17.9334 Tj +200.343 213.223 Td +(void**) 35.8668 Tj +-426 TJm +(unused,) 41.8446 Tj +-426 TJm +(int*) 23.9112 Tj +-426 TJm +(nUnuse) 35.8668 Tj +1 TJm +(d) 5.9778 Tj +-426 TJm +(\);) 11.9556 Tj +[1 0 0 1 72 197.681] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.549] cm +0 g +0 G +[1 0 0 1 -72 -187.719] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 175.764 Td +/F128_0 9.963 Tf +(Returns) 30.9949 Tj +-435 TJm +(data) 16.5984 Tj +-435 TJm +(which) 24.3496 Tj +-435 TJm +(w) 7.19329 Tj +10 TJm +(as) 8.29918 Tj +-435 TJm +(rea) 12.1648 Tj +1 TJm +(d) 4.9815 Tj +-435 TJm +(from) 19.3681 Tj +-435 TJm +(the) 12.1748 Tj +-435 TJm +(compressed) 47.0353 Tj +-435 TJm +(\002le) 12.7327 Tj +-435 TJm +(b) 4.9815 Tj +20 TJm +(ut) 7.75121 Tj +-435 TJm +(w) 7.19329 Tj +10 TJm +(as) 8.29918 Tj +-435 TJm +(not) 12.7327 Tj +-435 TJm +(needed) 28.2152 Tj +-435 TJm +(to) 7.75121 Tj +-435 TJm +(get) 12.1748 Tj +-434 TJm +(to) 7.75121 Tj +-435 TJm +(the) 12.1748 Tj +-435 TJm +(logical) 27.1193 Tj +-435 TJm +(end-of-stream.) 58.3732 Tj +[1 0 0 1 72 163.808] cm +0 g +0 G +[1 0 0 1 -72 -163.808] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 163.808 Td +/F130_0 9.963 Tf +(*unused) 41.8446 Tj +[1 0 0 1 113.843 163.808] cm +0 g +0 G +[1 0 0 1 -113.843 -163.808] cm +[1 0 0 1 0 0] Tm +0 0 Td +117.2 163.808 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-337 TJm +(set) 11.0689 Tj +-337 TJm +(to) 7.75121 Tj +-337 TJm +(the) 12.1748 Tj +-336 TJm +(address) 29.879 Tj +-337 TJm +(of) 8.29918 Tj +-337 TJm +(the) 12.1748 Tj +-337 TJm +(data,) 19.0891 Tj +-359 TJm +(a) 4.42357 Tj +1 TJm +(nd) 9.963 Tj +[1 0 0 1 269.089 163.808] cm +0 g +0 G +[1 0 0 1 -269.089 -163.808] cm +[1 0 0 1 0 0] Tm +0 0 Td +269.089 163.808 Td +/F130_0 9.963 Tf +(*nUnused) 47.8224 Tj +[1 0 0 1 316.91 163.808] cm +0 g +0 G +[1 0 0 1 -316.91 -163.808] cm +[1 0 0 1 0 0] Tm +0 0 Td +320.267 163.808 Td +/F128_0 9.963 Tf +(to) 7.75121 Tj +-337 TJm +(the) 12.1748 Tj +-337 TJm +(number) 30.437 Tj +-337 TJm +(o) 4.9815 Tj +1 TJm +(f) 3.31768 Tj +-337 TJm +(bytes.) 23.5226 Tj +[1 0 0 1 427.247 163.808] cm +0 g +0 G +[1 0 0 1 -427.247 -163.808] cm +[1 0 0 1 0 0] Tm +0 0 Td +427.247 163.808 Td +/F130_0 9.963 Tf +(*nUnused) 47.8224 Tj +[1 0 0 1 475.068 163.808] cm +0 g +0 G +[1 0 0 1 -475.068 -163.808] cm +[1 0 0 1 0 0] Tm +0 0 Td +478.425 163.808 Td +/F128_0 9.963 Tf +(will) 15.5024 Tj +-337 TJm +(be) 9.40507 Tj +-337 TJm +(set) 11.0689 Tj +-337 TJm +(to) 7.75121 Tj +-336 TJm +(a) 4.42357 Tj +72 151.853 Td +(v) 4.9815 Tj +25 TJm +(alue) 16.5984 Tj +-250 TJm +(between) 33.1967 Tj +[1 0 0 1 131.506 151.853] cm +0 g +0 G +[1 0 0 1 -131.506 -151.853] cm +[1 0 0 1 0 0] Tm +0 0 Td +131.506 151.853 Td +/F130_0 9.963 Tf +(0) 5.9778 Tj +[1 0 0 1 137.484 151.853] cm +0 g +0 G +[1 0 0 1 -137.484 -151.853] cm +[1 0 0 1 0 0] Tm +0 0 Td +139.975 151.853 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 156.851 151.853] cm +0 g +0 G +[1 0 0 1 -156.851 -151.853] cm +[1 0 0 1 0 0] Tm +0 0 Td +156.851 151.853 Td +/F130_0 9.963 Tf +(BZ_MAX_UNUSED) 77.7114 Tj +[1 0 0 1 234.56 151.853] cm +0 g +0 G +[1 0 0 1 -234.56 -151.853] cm +[1 0 0 1 0 0] Tm +0 0 Td +237.05 151.853 Td +/F128_0 9.963 Tf +(inclusi) 26.5713 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(e.) 6.91432 Tj +[1 0 0 1 72 150.688] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -140.725] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 129.936 Td +/F128_0 9.963 Tf +(This) 17.7142 Tj +-882 TJm +(function) 33.2067 Tj +-883 TJm +(may) 17.1563 Tj +-882 TJm +(only) 17.7142 Tj +-882 TJm +(be) 9.40507 Tj +-883 TJm +(called) 23.7916 Tj +-882 TJm +(once) 18.8101 Tj +[1 0 0 1 271.332 129.936] cm +0 g +0 G +[1 0 0 1 -271.332 -129.936] cm +[1 0 0 1 0 0] Tm +0 0 Td +271.332 129.936 Td +/F130_0 9.963 Tf +(BZ2_bzRead) 59.778 Tj +[1 0 0 1 331.108 129.936] cm +0 g +0 G +[1 0 0 1 -331.108 -129.936] cm +[1 0 0 1 0 0] Tm +0 0 Td +339.9 129.936 Td +/F128_0 9.963 Tf +(has) 13.2807 Tj +-882 TJm +(signalled) 35.9764 Tj +[1 0 0 1 406.737 129.936] cm +0 g +0 G +[1 0 0 1 -406.737 -129.936] cm +[1 0 0 1 0 0] Tm +0 0 Td +406.737 129.936 Td +/F130_0 9.963 Tf +(BZ_STREAM_END) 77.7114 Tj +[1 0 0 1 484.446 129.936] cm +0 g +0 G +[1 0 0 1 -484.446 -129.936] cm +[1 0 0 1 0 0] Tm +0 0 Td +493.231 129.936 Td +/F128_0 9.963 Tf +(b) 4.9815 Tj +20 TJm +(ut) 7.75121 Tj +-882 TJm +(before) 25.4455 Tj +[1 0 0 1 72 117.98] cm +0 g +0 G +[1 0 0 1 -72 -117.98] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 117.98 Td +/F130_0 9.963 Tf +(BZ2_bzReadClose) 89.667 Tj +[1 0 0 1 161.664 117.98] cm +0 g +0 G +[1 0 0 1 -161.664 -117.98] cm +[1 0 0 1 0 0] Tm +0 0 Td +161.664 117.98 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 72 116.815] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -106.852] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 96.063 Td +/F128_0 9.963 Tf +(Possible) 33.2166 Tj +-250 TJm +(assignments) 48.7091 Tj +-250 TJm +(to) 7.75121 Tj +[1 0 0 1 169.144 96.063] cm +0 g +0 G +[1 0 0 1 -169.144 -96.063] cm +[1 0 0 1 0 0] Tm +0 0 Td +169.144 96.063 Td +/F130_0 9.963 Tf +(bzerror) 41.8446 Tj +[1 0 0 1 210.987 96.063] cm +0 g +0 G +[1 0 0 1 -210.987 -96.063] cm +[1 0 0 1 0 0] Tm +0 0 Td +210.987 96.063 Td +/F128_0 9.963 Tf +(:) 2.76971 Tj +[1 0 0 1 72 93.906] cm +0 g +0 G +[1 0 0 1 0 -43.054] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.754] cm +0 g +0 G +0 g +0 G +[1 0 0 1 40.572 -6.754] cm +0 g +0 G +[1 0 0 1 -493.841 -50.852] cm +[1 0 0 1 0 0] Tm +0 0 Td +534.414 50.852 Td +/F128_0 9.963 Tf +(21) 9.963 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 25 25 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 -8.911] cm +0 g +0 G +[1 0 0 1 0 8.911] cm +0 g +0 G +0 g +0 G +[1 0 0 1 84.08 -6.755] cm +0 g +0 G +[1 0 0 1 -350.151 -749.245] cm +[1 0 0 1 0 0] Tm +0 0 Td +434.231 749.245 Td +/F128_0 9.963 Tf +(Programming) 54.7965 Tj +-250 TJm +(with) 17.7142 Tj +-250 TJm +(libbzip2) 32.6587 Tj +[1 0 0 1 266.071 747.089] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -5.037] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -468 -129.151] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 107.597 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 104.01] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -711.631] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 711.631 Td +/F130_0 9.963 Tf +(BZ_PARAM_ERROR) 83.6892 Tj +98.488 699.676 Td +(if) 11.9556 Tj +-426 TJm +(b) 5.9778 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(NULL) 23.9112 Tj +98.488 687.721 Td +(or) 11.9556 Tj +-426 TJm +(unused) 35.8668 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(NULL) 23.9112 Tj +-426 TJm +(or) 11.9556 Tj +-426 TJm +(nUn) 17.9334 Tj +1 TJm +(used) 23.9112 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(NULL) 23.9112 Tj +90 675.766 Td +(BZ_SEQUENCE_ERROR) 101.623 Tj +98.488 663.811 Td +(if) 11.9556 Tj +-426 TJm +(BZ_STREAM_END) 77.7114 Tj +-426 TJm +(has) 17.9334 Tj +-426 TJm +(not) 17.9334 Tj +-425 TJm +(been) 23.9112 Tj +-426 TJm +(signalled) 53.8002 Tj +98.488 651.856 Td +(or) 11.9556 Tj +-426 TJm +(if) 11.9556 Tj +-426 TJm +(b) 5.9778 Tj +-426 TJm +(was) 17.9334 Tj +-426 TJm +(opened) 35.8668 Tj +-426 TJm +(with) 23.9112 Tj +-425 TJm +(BZ2_bzWriteOpen) 89.667 Tj +90 639.9 Td +(BZ_OK) 29.889 Tj +98.488 627.945 Td +(otherwise) 53.8002 Tj +[1 0 0 1 72 612.403] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.549] cm +0 g +0 G +[1 0 0 1 -72 -602.441] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 590.486 Td +/F128_0 9.963 Tf +(Allo) 17.7142 Tj +25 TJm +(w) 7.19329 Tj +10 TJm +(able) 16.5984 Tj +-250 TJm +(ne) 9.40507 Tj +15 TJm +(xt) 7.75121 Tj +-250 TJm +(actions:) 30.9949 Tj +[1 0 0 1 72 590.386] cm +0 g +0 G +[1 0 0 1 0 -24.906] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 23.91 re +f +Q +0 g +0 G +[1 0 0 1 0 3.586] cm +0 g +0 G +[1 0 0 1 0 20.324] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -581.021] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 581.021 Td +/F130_0 9.963 Tf +(BZ2_bzReadClose) 89.667 Tj +[1 0 0 1 72 565.48] cm +0 g +0 G +[1 0 0 1 468 3.586] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -3.586] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -555.517] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 534.858 Td +/F121_0 17.215 Tf +(3.4.4.) 43.0719 Tj +[1 0 0 1 119.858 534.858] cm +0 g +0 G +[1 0 0 1 -119.858 -534.858] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.858 534.858 Td +/F387_0 17.215 Tf +(BZ2_bzReadClose) 154.935 Tj +[1 0 0 1 274.797 534.858] cm +0 g +0 G +[1 0 0 1 -202.797 -2.332] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -24.907] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 23.91 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 20.323] cm +0 g +0 G +[1 0 0 1 18 -8.368] cm +0 g +0 G +[1 0 0 1 -90 -523.161] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 523.161 Td +/F130_0 9.963 Tf +(void) 23.9112 Tj +-426 TJm +(BZ2_bzReadClose) 89.667 Tj +-426 TJm +(\() 5.9778 Tj +-426 TJm +(in) 11.9556 Tj +1 TJm +(t) 5.9778 Tj +-426 TJm +(*bzerror,) 53.8002 Tj +-426 TJm +(BZFILE) 35.8668 Tj +-426 TJm +(*b) 11.9556 Tj +-426 TJm +(\);) 11.9556 Tj +[1 0 0 1 72 507.619] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.55] cm +0 g +0 G +[1 0 0 1 -72 -497.656] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 485.701 Td +/F128_0 9.963 Tf +(Releases) 34.8605 Tj +-429 TJm +(all) 9.963 Tj +-430 TJm +(memory) 33.2067 Tj +-429 TJm +(pertaining) 40.4 Tj +-430 TJm +(to) 7.75121 Tj +-429 TJm +(the) 12.1748 Tj +-430 TJm +(compressed) 47.0353 Tj +-429 TJm +(\002le) 12.7327 Tj +[1 0 0 1 304.352 485.701] cm +0 g +0 G +[1 0 0 1 -304.352 -485.701] cm +[1 0 0 1 0 0] Tm +0 0 Td +304.352 485.701 Td +/F130_0 9.963 Tf +(b) 5.9778 Tj +[1 0 0 1 310.33 485.701] cm +0 g +0 G +[1 0 0 1 -310.33 -485.701] cm +[1 0 0 1 0 0] Tm +0 0 Td +310.33 485.701 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 321.276 485.701] cm +0 g +0 G +[1 0 0 1 -321.276 -485.701] cm +[1 0 0 1 0 0] Tm +0 0 Td +321.276 485.701 Td +/F130_0 9.963 Tf +(BZ2_bzReadClose) 89.667 Tj +[1 0 0 1 410.94 485.701] cm +0 g +0 G +[1 0 0 1 -410.94 -485.701] cm +[1 0 0 1 0 0] Tm +0 0 Td +415.22 485.701 Td +/F128_0 9.963 Tf +(does) 18.2622 Tj +-429 TJm +(not) 12.7327 Tj +-430 TJm +(call) 14.3866 Tj +[1 0 0 1 473.438 485.701] cm +0 g +0 G +[1 0 0 1 -473.438 -485.701] cm +[1 0 0 1 0 0] Tm +0 0 Td +473.438 485.701 Td +/F130_0 9.963 Tf +(fclose) 35.8668 Tj +[1 0 0 1 509.304 485.701] cm +0 g +0 G +[1 0 0 1 -509.304 -485.701] cm +[1 0 0 1 0 0] Tm +0 0 Td +513.583 485.701 Td +/F128_0 9.963 Tf +(on) 9.963 Tj +-430 TJm +(the) 12.1748 Tj +72 473.746 Td +(underlying) 43.1697 Tj +-264 TJm +(\002le) 12.7327 Tj +-264 TJm +(hand) 19.3681 Tj +1 TJm +(le,) 9.68404 Tj +-268 TJm +(so) 8.85711 Tj +-264 TJm +(you) 14.9445 Tj +-264 TJm +(sh) 8.85711 Tj +1 TJm +(ould) 17.7142 Tj +-264 TJm +(do) 9.963 Tj +-264 TJm +(that) 14.9445 Tj +-264 TJm +(yourself) 32.6488 Tj +-264 TJm +(if) 6.08739 Tj +-264 TJm +(appropri) 33.7546 Tj +1 TJm +(ate.) 14.1076 Tj +[1 0 0 1 348.653 473.746] cm +0 g +0 G +[1 0 0 1 -348.653 -473.746] cm +[1 0 0 1 0 0] Tm +0 0 Td +348.653 473.746 Td +/F130_0 9.963 Tf +(BZ2_bzReadClose) 89.667 Tj +[1 0 0 1 438.317 473.746] cm +0 g +0 G +[1 0 0 1 -438.317 -473.746] cm +[1 0 0 1 0 0] Tm +0 0 Td +440.946 473.746 Td +/F128_0 9.963 Tf +(should) 26.5713 Tj +-264 TJm +(be) 9.40507 Tj +-264 TJm +(called) 23.7916 Tj +-263 TJm +(to) 7.75121 Tj +-264 TJm +(clean) 21.0219 Tj +72 461.791 Td +(up) 9.963 Tj +-250 TJm +(after) 18.2522 Tj +-250 TJm +(all) 9.963 Tj +-250 TJm +(error) 19.3581 Tj +-250 TJm +(situations.) 40.6889 Tj +[1 0 0 1 72 459.634] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -449.671] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 439.873 Td +/F128_0 9.963 Tf +(Possible) 33.2166 Tj +-250 TJm +(assignments) 48.7091 Tj +-250 TJm +(to) 7.75121 Tj +[1 0 0 1 169.144 439.873] cm +0 g +0 G +[1 0 0 1 -169.144 -439.873] cm +[1 0 0 1 0 0] Tm +0 0 Td +169.144 439.873 Td +/F130_0 9.963 Tf +(bzerror) 41.8446 Tj +[1 0 0 1 210.987 439.873] cm +0 g +0 G +[1 0 0 1 -210.987 -439.873] cm +[1 0 0 1 0 0] Tm +0 0 Td +210.987 439.873 Td +/F128_0 9.963 Tf +(:) 2.76971 Tj +[1 0 0 1 72 437.716] cm +0 g +0 G +[1 0 0 1 0 -60.772] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 59.776 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 56.189] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -428.351] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 428.351 Td +/F130_0 9.963 Tf +(BZ_SEQUENCE_ERROR) 101.623 Tj +98.488 416.396 Td +(if) 11.9556 Tj +-426 TJm +(b) 5.9778 Tj +-426 TJm +(was) 17.9334 Tj +-426 TJm +(opened) 35.8668 Tj +-426 TJm +(with) 23.9112 Tj +-426 TJm +(BZ2) 17.9334 Tj +1 TJm +(_bzOpenWrite) 71.7336 Tj +90 404.441 Td +(BZ_OK) 29.889 Tj +98.488 392.486 Td +(otherwise) 53.8002 Tj +[1 0 0 1 72 376.944] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.549] cm +0 g +0 G +[1 0 0 1 -72 -366.982] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 355.026 Td +/F128_0 9.963 Tf +(Allo) 17.7142 Tj +25 TJm +(w) 7.19329 Tj +10 TJm +(able) 16.5984 Tj +-250 TJm +(ne) 9.40507 Tj +15 TJm +(xt) 7.75121 Tj +-250 TJm +(actions:) 30.9949 Tj +[1 0 0 1 72 354.927] cm +0 g +0 G +[1 0 0 1 0 -24.907] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 23.91 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 20.324] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -345.562] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 345.562 Td +/F130_0 9.963 Tf +(none) 23.9112 Tj +[1 0 0 1 72 330.02] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -3.587] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -320.058] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 299.399 Td +/F121_0 17.215 Tf +(3.4.5.) 43.0719 Tj +[1 0 0 1 119.858 299.399] cm +0 g +0 G +[1 0 0 1 -119.858 -299.399] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.858 299.399 Td +/F387_0 17.215 Tf +(BZ2_bzWriteOpen) 154.935 Tj +[1 0 0 1 274.797 299.399] cm +0 g +0 G +[1 0 0 1 -202.797 -2.333] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -48.817] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 47.821 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 44.234] cm +0 g +0 G +[1 0 0 1 18 -8.368] cm +0 g +0 G +[1 0 0 1 -90 -287.702] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 287.702 Td +/F130_0 9.963 Tf +(BZFILE) 35.8668 Tj +-426 TJm +(*BZ2_bzWriteOpen\() 101.623 Tj +-425 TJm +(int) 17.9334 Tj +-426 TJm +(*bzerror,) 53.8002 Tj +-426 TJm +(FILE) 23.9112 Tj +-426 TJm +(*f,) 17.9334 Tj +196.099 275.746 Td +(int) 17.9334 Tj +-426 TJm +(blockSize100k,) 83.6892 Tj +-426 TJm +(int) 17.9334 Tj +-426 TJm +(ver) 17.9334 Tj +1 TJm +(bosity,) 41.8446 Tj +196.099 263.791 Td +(int) 17.9334 Tj +-426 TJm +(workFactor) 59.778 Tj +-426 TJm +(\);) 11.9556 Tj +[1 0 0 1 72 248.249] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.549] cm +0 g +0 G +[1 0 0 1 -72 -238.287] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 226.332 Td +/F128_0 9.963 Tf +(Prepare) 30.427 Tj +-268 TJm +(to) 7.75121 Tj +-269 TJm +(write) 20.474 Tj +-268 TJm +(compressed) 47.0353 Tj +-268 TJm +(data) 16.5984 Tj +-269 TJm +(to) 7.75121 Tj +-268 TJm +(\002le) 12.7327 Tj +-269 TJm +(hand) 19.3681 Tj +1 TJm +(le) 7.19329 Tj +[1 0 0 1 262.72 226.332] cm +0 g +0 G +[1 0 0 1 -262.72 -226.332] cm +[1 0 0 1 0 0] Tm +0 0 Td +262.72 226.332 Td +/F130_0 9.963 Tf +(f) 5.9778 Tj +[1 0 0 1 268.698 226.332] cm +0 g +0 G +[1 0 0 1 -268.698 -226.332] cm +[1 0 0 1 0 0] Tm +0 0 Td +268.698 226.332 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 274.829 226.332] cm +0 g +0 G +[1 0 0 1 -274.829 -226.332] cm +[1 0 0 1 0 0] Tm +0 0 Td +274.829 226.332 Td +/F130_0 9.963 Tf +(f) 5.9778 Tj +[1 0 0 1 280.807 226.332] cm +0 g +0 G +[1 0 0 1 -280.807 -226.332] cm +[1 0 0 1 0 0] Tm +0 0 Td +283.481 226.332 Td +/F128_0 9.963 Tf +(should) 26.5713 Tj +-268 TJm +(refer) 18.8002 Tj +-269 TJm +(to) 7.75121 Tj +-268 TJm +(a) 4.42357 Tj +-269 TJm +(\002le) 12.7327 Tj +-268 TJm +(which) 24.3496 Tj +-268 TJm +(has) 13.2807 Tj +-269 TJm +(been) 18.8101 Tj +-268 TJm +(opened) 28.7731 Tj +-269 TJm +(f) 3.31768 Tj +1 TJm +(or) 8.29918 Tj +-269 TJm +(writing,) 31.2739 Tj +-273 TJm +(and) 14.3866 Tj +-268 TJm +(for) 11.6169 Tj +72 214.377 Td +(which) 24.3496 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(error) 19.3581 Tj +-250 TJm +(indicator) 35.4185 Tj +-250 TJm +(\() 3.31768 Tj +[1 0 0 1 176.577 214.377] cm +0 g +0 G +[1 0 0 1 -176.577 -214.377] cm +[1 0 0 1 0 0] Tm +0 0 Td +176.577 214.377 Td +/F130_0 9.963 Tf +(ferror\(f\)) 53.8002 Tj +[1 0 0 1 230.375 214.377] cm +0 g +0 G +[1 0 0 1 -230.375 -214.377] cm +[1 0 0 1 0 0] Tm +0 0 Td +230.375 214.377 Td +/F128_0 9.963 Tf +(\)is) 9.963 Tj +-250 TJm +(not) 12.7327 Tj +-250 TJm +(set.) 13.5596 Tj +[1 0 0 1 72 212.593] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -202.631] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 192.459 Td +/F128_0 9.963 Tf +(F) 5.53943 Tj +15 TJm +(or) 8.29918 Tj +-223 TJm +(the) 12.1748 Tj +-224 TJm +(meaning) 34.3126 Tj +-223 TJm +(of) 8.29918 Tj +-223 TJm +(parameters) 43.7077 Tj +[1 0 0 1 195.306 192.459] cm +0 g +0 G +[1 0 0 1 -195.306 -192.459] cm +[1 0 0 1 0 0] Tm +0 0 Td +195.306 192.459 Td +/F130_0 9.963 Tf +(blockSize100k) 77.7114 Tj +[1 0 0 1 273.015 192.459] cm +0 g +0 G +[1 0 0 1 -273.015 -192.459] cm +[1 0 0 1 0 0] Tm +0 0 Td +273.015 192.459 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 277.784 192.459] cm +0 g +0 G +[1 0 0 1 -277.784 -192.459] cm +[1 0 0 1 0 0] Tm +0 0 Td +277.784 192.459 Td +/F130_0 9.963 Tf +(verbosity) 53.8002 Tj +[1 0 0 1 331.583 192.459] cm +0 g +0 G +[1 0 0 1 -331.583 -192.459] cm +[1 0 0 1 0 0] Tm +0 0 Td +333.808 192.459 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 350.42 192.459] cm +0 g +0 G +[1 0 0 1 -350.42 -192.459] cm +[1 0 0 1 0 0] Tm +0 0 Td +350.42 192.459 Td +/F130_0 9.963 Tf +(workFactor) 59.778 Tj +[1 0 0 1 410.196 192.459] cm +0 g +0 G +[1 0 0 1 -410.196 -192.459] cm +[1 0 0 1 0 0] Tm +0 0 Td +410.196 192.459 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-229 TJm +(see) 12.7228 Tj +[1 0 0 1 429.913 192.459] cm +0 g +0 G +[1 0 0 1 -429.913 -192.459] cm +[1 0 0 1 0 0] Tm +0 0 Td +429.913 192.459 Td +/F130_0 9.963 Tf +(BZ2_bzCompressInit) 107.6 Tj +[1 0 0 1 537.509 192.459] cm +0 g +0 G +[1 0 0 1 -537.509 -192.459] cm +[1 0 0 1 0 0] Tm +0 0 Td +537.509 192.459 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 72 190.302] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -180.339] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 170.541 Td +/F128_0 9.963 Tf +(All) 12.7327 Tj +-382 TJm +(required) 33.1967 Tj +-382 TJm +(memory) 33.2067 Tj +-382 TJm +(is) 6.64532 Tj +-382 TJm +(allocated) 35.9664 Tj +-382 TJm +(at) 7.19329 Tj +-382 TJm +(this) 14.3965 Tj +-382 TJm +(stage,) 22.9647 Tj +-415 TJm +(so) 8.85711 Tj +-382 TJm +(if) 6.08739 Tj +-382 TJm +(the) 12.1748 Tj +-382 TJm +(call) 14.3866 Tj +-382 TJm +(completes) 40.4 Tj +-382 TJm +(successfully) 48.6991 Tj +65 TJm +(,) 2.49075 Tj +[1 0 0 1 424.692 170.541] cm +0 g +0 G +[1 0 0 1 -424.692 -170.541] cm +[1 0 0 1 0 0] Tm +0 0 Td +424.692 170.541 Td +/F130_0 9.963 Tf +(BZ_MEM_ERROR) 71.7336 Tj +[1 0 0 1 496.423 170.541] cm +0 g +0 G +[1 0 0 1 -496.423 -170.541] cm +[1 0 0 1 0 0] Tm +0 0 Td +500.228 170.541 Td +/F128_0 9.963 Tf +(cannot) 26.5614 Tj +-382 TJm +(be) 9.40507 Tj +72 158.586 Td +(signalled) 35.9764 Tj +-250 TJm +(by) 9.963 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(subsequent) 44.2756 Tj +-250 TJm +(cal) 11.6169 Tj +1 TJm +(l) 2.76971 Tj +-250 TJm +(to) 7.75121 Tj +[1 0 0 1 203.715 158.586] cm +0 g +0 G +[1 0 0 1 -203.715 -158.586] cm +[1 0 0 1 0 0] Tm +0 0 Td +203.715 158.586 Td +/F130_0 9.963 Tf +(BZ2_bzWrite) 65.7558 Tj +[1 0 0 1 269.468 158.586] cm +0 g +0 G +[1 0 0 1 -269.468 -158.586] cm +[1 0 0 1 0 0] Tm +0 0 Td +269.468 158.586 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 72 156.429] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -146.466] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 136.668 Td +/F128_0 9.963 Tf +(Possible) 33.2166 Tj +-250 TJm +(assignments) 48.7091 Tj +-250 TJm +(to) 7.75121 Tj +[1 0 0 1 169.144 136.668] cm +0 g +0 G +[1 0 0 1 -169.144 -136.668] cm +[1 0 0 1 0 0] Tm +0 0 Td +169.144 136.668 Td +/F130_0 9.963 Tf +(bzerror) 41.8446 Tj +[1 0 0 1 210.987 136.668] cm +0 g +0 G +[1 0 0 1 -210.987 -136.668] cm +[1 0 0 1 0 0] Tm +0 0 Td +210.987 136.668 Td +/F128_0 9.963 Tf +(:) 2.76971 Tj +[1 0 0 1 72 134.511] cm +0 g +0 G +[1 0 0 1 0 -83.659] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.754] cm +0 g +0 G +0 g +0 G +[1 0 0 1 40.572 -6.754] cm +0 g +0 G +[1 0 0 1 -493.841 -50.852] cm +[1 0 0 1 0 0] Tm +0 0 Td +534.414 50.852 Td +/F128_0 9.963 Tf +(22) 9.963 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 26 26 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 -8.911] cm +0 g +0 G +[1 0 0 1 0 8.911] cm +0 g +0 G +0 g +0 G +[1 0 0 1 84.08 -6.755] cm +0 g +0 G +[1 0 0 1 -350.151 -749.245] cm +[1 0 0 1 0 0] Tm +0 0 Td +434.231 749.245 Td +/F128_0 9.963 Tf +(Programming) 54.7965 Tj +-250 TJm +(with) 17.7142 Tj +-250 TJm +(libbzip2) 32.6587 Tj +[1 0 0 1 266.071 747.089] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -5.037] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -468 -165.016] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 143.462 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 139.875] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -711.631] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 711.631 Td +/F130_0 9.963 Tf +(BZ_CONFIG_ERROR) 89.667 Tj +98.488 699.676 Td +(if) 11.9556 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(library) 41.8446 Tj +-426 TJm +(has) 17.9334 Tj +-426 TJm +(been) 23.9112 Tj +-425 TJm +(mis-compiled) 71.7336 Tj +90 687.721 Td +(BZ_PARAM_ERROR) 83.6892 Tj +98.488 675.766 Td +(if) 11.9556 Tj +-426 TJm +(f) 5.9778 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(NULL) 23.9112 Tj +98.488 663.811 Td +(or) 11.9556 Tj +-426 TJm +(blockSize100k) 77.7114 Tj +-426 TJm +(<) 5.9778 Tj +-426 TJm +(1) 5.9778 Tj +-426 TJm +(or) 11.9556 Tj +-425 TJm +(blockSize100k) 77.7114 Tj +-426 TJm +(>) 5.9778 Tj +-426 TJm +(9) 5.9778 Tj +90 651.856 Td +(BZ_IO_ERROR) 65.7558 Tj +98.488 639.9 Td +(if) 11.9556 Tj +-426 TJm +(ferror\(f\)) 53.8002 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(nonzero) 41.8446 Tj +90 627.945 Td +(BZ_MEM_ERROR) 71.7336 Tj +98.488 615.99 Td +(if) 11.9556 Tj +-426 TJm +(insufficient) 71.7336 Tj +-426 TJm +(memory) 35.8668 Tj +-426 TJm +(is) 11.9556 Tj +-425 TJm +(available) 53.8002 Tj +90 604.035 Td +(BZ_OK) 29.889 Tj +98.488 592.08 Td +(otherwise) 53.8002 Tj +[1 0 0 1 72 576.538] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.55] cm +0 g +0 G +[1 0 0 1 -72 -566.575] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 554.62 Td +/F128_0 9.963 Tf +(Possible) 33.2166 Tj +-250 TJm +(return) 23.7916 Tj +-250 TJm +(v) 4.9815 Tj +25 TJm +(alues:) 23.2437 Tj +[1 0 0 1 72 554.521] cm +0 g +0 G +[1 0 0 1 0 -60.772] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 59.776 re +f +Q +0 g +0 G +[1 0 0 1 0 3.586] cm +0 g +0 G +[1 0 0 1 0 56.189] cm +0 g +0 G +[1 0 0 1 18 -8.368] cm +0 g +0 G +[1 0 0 1 -90 -545.156] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 545.156 Td +/F130_0 9.963 Tf +(Pointer) 41.8446 Tj +-426 TJm +(to) 11.9556 Tj +-426 TJm +(an) 11.9556 Tj +-426 TJm +(abstract) 47.8224 Tj +-426 TJm +(B) 5.9778 Tj +1 TJm +(ZFILE) 29.889 Tj +98.488 533.201 Td +(if) 11.9556 Tj +-426 TJm +(bzerror) 41.8446 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(BZ_OK) 29.889 Tj +90 521.245 Td +(NULL) 23.9112 Tj +98.488 509.29 Td +(otherwise) 53.8002 Tj +[1 0 0 1 72 493.749] cm +0 g +0 G +[1 0 0 1 468 3.586] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.549] cm +0 g +0 G +[1 0 0 1 -72 -483.786] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 471.831 Td +/F128_0 9.963 Tf +(Allo) 17.7142 Tj +25 TJm +(w) 7.19329 Tj +10 TJm +(able) 16.5984 Tj +-250 TJm +(ne) 9.40507 Tj +15 TJm +(xt) 7.75121 Tj +-250 TJm +(actions:) 30.9949 Tj +[1 0 0 1 72 471.731] cm +0 g +0 G +[1 0 0 1 0 -84.682] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 83.686 re +f +Q +0 g +0 G +[1 0 0 1 0 3.586] cm +0 g +0 G +[1 0 0 1 0 80.1] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -462.366] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 462.366 Td +/F130_0 9.963 Tf +(BZ2_bzWrite) 65.7558 Tj +98.488 450.411 Td +(if) 11.9556 Tj +-426 TJm +(bzerror) 41.8446 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(BZ_OK) 29.889 Tj +98.488 438.456 Td +(\(you) 23.9112 Tj +-426 TJm +(could) 29.889 Tj +-426 TJm +(go) 11.9556 Tj +-426 TJm +(directly) 47.8224 Tj +-426 TJm +(t) 5.9778 Tj +1 TJm +(o) 5.9778 Tj +-426 TJm +(BZ2_bzWriteClose,) 101.623 Tj +-426 TJm +(but) 17.9334 Tj +-426 TJm +(this) 23.9112 Tj +-426 TJm +(would) 29.889 Tj +-426 TJm +(be) 11.9556 Tj +-426 TJm +(pretty) 35.8668 Tj +485.506 434.212 Td +/F559_0 9.963 Tf +( ) 9.963 Tj +493.808 434.212 Td +/F143_0 9.963 Tf +(-) 2.76971 Tj +90 426.501 Td +/F130_0 9.963 Tf +(pointless\)) 59.778 Tj +90 414.546 Td +(BZ2_bzWriteClose) 95.6448 Tj +98.488 402.59 Td +(otherwise) 53.8002 Tj +[1 0 0 1 72 387.049] cm +0 g +0 G +[1 0 0 1 468 3.586] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -3.586] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -377.086] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 356.428 Td +/F121_0 17.215 Tf +(3.4.6.) 43.0719 Tj +[1 0 0 1 119.858 356.428] cm +0 g +0 G +[1 0 0 1 -119.858 -356.428] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.858 356.428 Td +/F387_0 17.215 Tf +(BZ2_bzWrite) 113.619 Tj +[1 0 0 1 233.48 356.428] cm +0 g +0 G +[1 0 0 1 -161.48 -2.333] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -24.907] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 23.91 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 20.324] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -344.73] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 344.73 Td +/F130_0 9.963 Tf +(void) 23.9112 Tj +-426 TJm +(BZ2_bzWrite) 65.7558 Tj +-426 TJm +(\() 5.9778 Tj +-426 TJm +(int) 17.9334 Tj +-426 TJm +(*) 5.9778 Tj +1 TJm +(bzerror,) 47.8224 Tj +-426 TJm +(BZFILE) 35.8668 Tj +-426 TJm +(*b,) 17.9334 Tj +-426 TJm +(void) 23.9112 Tj +-426 TJm +(*buf,) 29.889 Tj +-426 TJm +(int) 17.9334 Tj +-426 TJm +(len) 17.9334 Tj +-426 TJm +(\);) 11.9556 Tj +[1 0 0 1 72 329.188] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.549] cm +0 g +0 G +[1 0 0 1 -72 -319.226] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 307.271 Td +/F128_0 9.963 Tf +(Absorbs) 33.2067 Tj +[1 0 0 1 107.696 307.271] cm +0 g +0 G +[1 0 0 1 -107.696 -307.271] cm +[1 0 0 1 0 0] Tm +0 0 Td +107.696 307.271 Td +/F130_0 9.963 Tf +(len) 17.9334 Tj +[1 0 0 1 125.629 307.271] cm +0 g +0 G +[1 0 0 1 -125.629 -307.271] cm +[1 0 0 1 0 0] Tm +0 0 Td +128.119 307.271 Td +/F128_0 9.963 Tf +(bytes) 21.0319 Tj +-250 TJm +(from) 19.3681 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(b) 4.9815 Tj +20 TJm +(uf) 8.29918 Tj +25 TJm +(fer) 11.0589 Tj +[1 0 0 1 214.544 307.271] cm +0 g +0 G +[1 0 0 1 -214.544 -307.271] cm +[1 0 0 1 0 0] Tm +0 0 Td +214.544 307.271 Td +/F130_0 9.963 Tf +(buf) 17.9334 Tj +[1 0 0 1 232.477 307.271] cm +0 g +0 G +[1 0 0 1 -232.477 -307.271] cm +[1 0 0 1 0 0] Tm +0 0 Td +232.477 307.271 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-250 TJm +(e) 4.42357 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(entually) 32.1008 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(be) 9.40507 Tj +-250 TJm +(compressed) 47.0353 Tj +-249 TJm +(and) 14.3866 Tj +-250 TJm +(written) 28.2252 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(\002le.) 15.2235 Tj +[1 0 0 1 72 305.114] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -295.151] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 285.353 Td +/F128_0 9.963 Tf +(Possible) 33.2166 Tj +-250 TJm +(assignments) 48.7091 Tj +-250 TJm +(to) 7.75121 Tj +[1 0 0 1 169.144 285.353] cm +0 g +0 G +[1 0 0 1 -169.144 -285.353] cm +[1 0 0 1 0 0] Tm +0 0 Td +169.144 285.353 Td +/F130_0 9.963 Tf +(bzerror) 41.8446 Tj +[1 0 0 1 210.987 285.353] cm +0 g +0 G +[1 0 0 1 -210.987 -285.353] cm +[1 0 0 1 0 0] Tm +0 0 Td +210.987 285.353 Td +/F128_0 9.963 Tf +(:) 2.76971 Tj +[1 0 0 1 72 283.196] cm +0 g +0 G +[1 0 0 1 0 -108.593] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 107.597 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 104.01] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -273.831] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 273.831 Td +/F130_0 9.963 Tf +(BZ_PARAM_ERROR) 83.6892 Tj +98.488 261.876 Td +(if) 11.9556 Tj +-426 TJm +(b) 5.9778 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(NULL) 23.9112 Tj +-426 TJm +(or) 11.9556 Tj +-426 TJm +(buf) 17.9334 Tj +-426 TJm +(is) 11.9556 Tj +-425 TJm +(NULL) 23.9112 Tj +-426 TJm +(or) 11.9556 Tj +-426 TJm +(len) 17.9334 Tj +-426 TJm +(<) 5.9778 Tj +-426 TJm +(0) 5.9778 Tj +90 249.921 Td +(BZ_SEQUENCE_ERROR) 101.623 Tj +98.488 237.966 Td +(if) 11.9556 Tj +-426 TJm +(b) 5.9778 Tj +-426 TJm +(was) 17.9334 Tj +-426 TJm +(opened) 35.8668 Tj +-426 TJm +(with) 23.9112 Tj +-426 TJm +(BZ2) 17.9334 Tj +1 TJm +(_bzReadOpen) 65.7558 Tj +90 226.01 Td +(BZ_IO_ERROR) 65.7558 Tj +98.488 214.055 Td +(if) 11.9556 Tj +-426 TJm +(there) 29.889 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(an) 11.9556 Tj +-426 TJm +(error) 29.889 Tj +-426 TJm +(wri) 17.9334 Tj +1 TJm +(ting) 23.9112 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(compressed) 59.778 Tj +-426 TJm +(file.) 29.889 Tj +90 202.1 Td +(BZ_OK) 29.889 Tj +98.488 190.145 Td +(otherwise) 53.8002 Tj +[1 0 0 1 72 174.603] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -3.587] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -164.64] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 143.982 Td +/F121_0 17.215 Tf +(3.4.7.) 43.0719 Tj +[1 0 0 1 119.858 143.982] cm +0 g +0 G +[1 0 0 1 -119.858 -143.982] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.858 143.982 Td +/F387_0 17.215 Tf +(BZ2_bzWriteClose) 165.264 Tj +[1 0 0 1 285.126 143.982] cm +0 g +0 G +[1 0 0 1 -213.126 -2.333] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -90.797] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.854] cm +0 g +0 G +0 g +0 G +[1 0 0 1 40.572 -6.755] cm +0 g +0 G +[1 0 0 1 -493.841 -50.951] cm +[1 0 0 1 0 0] Tm +0 0 Td +534.414 50.951 Td +/F128_0 9.963 Tf +(23) 9.963 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 27 27 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 -8.911] cm +0 g +0 G +[1 0 0 1 0 8.911] cm +0 g +0 G +0 g +0 G +[1 0 0 1 84.08 -6.755] cm +0 g +0 G +[1 0 0 1 -350.151 -749.245] cm +[1 0 0 1 0 0] Tm +0 0 Td +434.231 749.245 Td +/F128_0 9.963 Tf +(Programming) 54.7965 Tj +-250 TJm +(with) 17.7142 Tj +-250 TJm +(libbzip2) 32.6587 Tj +[1 0 0 1 266.071 747.089] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -5.037] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -468 -165.016] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 143.462 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 139.875] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -711.631] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 711.631 Td +/F130_0 9.963 Tf +(void) 23.9112 Tj +-426 TJm +(BZ2_bzWriteClose\() 101.623 Tj +-426 TJm +(in) 11.9556 Tj +1 TJm +(t) 5.9778 Tj +-426 TJm +(*bzerror,) 53.8002 Tj +-426 TJm +(BZFILE*) 41.8446 Tj +-426 TJm +(f,) 11.9556 Tj +187.611 699.676 Td +(int) 17.9334 Tj +-426 TJm +(abandon,) 47.8224 Tj +187.611 687.721 Td +(unsigned) 47.8224 Tj +-426 TJm +(int*) 23.9112 Tj +-426 TJm +(nbytes_in,) 59.778 Tj +187.611 675.766 Td +(unsigned) 47.8224 Tj +-426 TJm +(int*) 23.9112 Tj +-426 TJm +(nbytes_out) 59.778 Tj +-426 TJm +(\);) 11.9556 Tj +90 651.856 Td +(void) 23.9112 Tj +-426 TJm +(BZ2_bzWriteClose64\() 113.578 Tj +-425 TJm +(int) 17.9334 Tj +-426 TJm +(*bzerror,) 53.8002 Tj +-426 TJm +(BZFILE*) 41.8446 Tj +-426 TJm +(f,) 11.9556 Tj +196.099 639.9 Td +(int) 17.9334 Tj +-426 TJm +(abandon,) 47.8224 Tj +196.099 627.945 Td +(unsigned) 47.8224 Tj +-426 TJm +(int*) 23.9112 Tj +-426 TJm +(nbytes_in_lo3) 77.7114 Tj +1 TJm +(2,) 11.9556 Tj +196.099 615.99 Td +(unsigned) 47.8224 Tj +-426 TJm +(int*) 23.9112 Tj +-426 TJm +(nbytes_in_hi3) 77.7114 Tj +1 TJm +(2,) 11.9556 Tj +196.099 604.035 Td +(unsigned) 47.8224 Tj +-426 TJm +(int*) 23.9112 Tj +-426 TJm +(nbytes_out_lo) 77.7114 Tj +1 TJm +(32,) 17.9334 Tj +196.099 592.08 Td +(unsigned) 47.8224 Tj +-426 TJm +(int*) 23.9112 Tj +-426 TJm +(nbytes_out_hi) 77.7114 Tj +1 TJm +(32) 11.9556 Tj +-426 TJm +(\);) 11.9556 Tj +[1 0 0 1 72 576.538] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.55] cm +0 g +0 G +[1 0 0 1 -72 -566.575] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 554.62 Td +/F128_0 9.963 Tf +(Compresses) 48.1512 Tj +-402 TJm +(and) 14.3866 Tj +-403 TJm +(\003ushes) 27.6772 Tj +-403 TJm +(to) 7.75121 Tj +-402 TJm +(the) 12.1748 Tj +-403 TJm +(compressed) 47.0353 Tj +-402 TJm +(\002le) 12.7327 Tj +-403 TJm +(all) 9.963 Tj +-402 TJm +(data) 16.5984 Tj +-403 TJm +(so) 8.85711 Tj +-403 TJm +(f) 3.31768 Tj +11 TJm +(ar) 7.74125 Tj +-403 TJm +(supplied) 33.7646 Tj +-403 TJm +(by) 9.963 Tj +[1 0 0 1 384.152 554.62] cm +0 g +0 G +[1 0 0 1 -384.152 -554.62] cm +[1 0 0 1 0 0] Tm +0 0 Td +384.152 554.62 Td +/F130_0 9.963 Tf +(BZ2_bzWrite) 65.7558 Tj +[1 0 0 1 449.906 554.62] cm +0 g +0 G +[1 0 0 1 -449.906 -554.62] cm +[1 0 0 1 0 0] Tm +0 0 Td +449.906 554.62 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +-768 TJm +(The) 15.4925 Tj +-402 TJm +(logical) 27.1193 Tj +-403 TJm +(end-of-) 29.3211 Tj +72 542.665 Td +(stream) 26.5614 Tj +-352 TJm +(mark) 20.474 Tj +10 TJm +(ers) 11.6169 Tj +-352 TJm +(are) 12.1648 Tj +-352 TJm +(also) 16.0504 Tj +-352 TJm +(written,) 30.7159 Tj +-378 TJm +(so) 8.85711 Tj +-352 TJm +(subsequent) 44.2756 Tj +-352 TJm +(calls) 18.2622 Tj +-352 TJm +(to) 7.75121 Tj +[1 0 0 1 300.456 542.665] cm +0 g +0 G +[1 0 0 1 -300.456 -542.665] cm +[1 0 0 1 0 0] Tm +0 0 Td +300.456 542.665 Td +/F130_0 9.963 Tf +(BZ2_bzWrite) 65.7558 Tj +[1 0 0 1 366.209 542.665] cm +0 g +0 G +[1 0 0 1 -366.209 -542.665] cm +[1 0 0 1 0 0] Tm +0 0 Td +369.718 542.665 Td +/F128_0 9.963 Tf +(are) 12.1648 Tj +-352 TJm +(ille) 12.7327 Tj +15 TJm +(g) 4.9815 Tj +5 TJm +(al.) 9.68404 Tj +-1233 TJm +(All) 12.7327 Tj +-352 TJm +(memory) 33.2067 Tj +-353 TJm +(ass) 12.1748 Tj +1 TJm +(ociated) 28.7731 Tj +-353 TJm +(wit) 12.7327 Tj +1 TJm +(h) 4.9815 Tj +72 530.71 Td +(the) 12.1748 Tj +-250 TJm +(compressed) 47.0353 Tj +-250 TJm +(\002le) 12.7327 Tj +[1 0 0 1 151.411 530.71] cm +0 g +0 G +[1 0 0 1 -151.411 -530.71] cm +[1 0 0 1 0 0] Tm +0 0 Td +151.411 530.71 Td +/F130_0 9.963 Tf +(b) 5.9778 Tj +[1 0 0 1 157.389 530.71] cm +0 g +0 G +[1 0 0 1 -157.389 -530.71] cm +[1 0 0 1 0 0] Tm +0 0 Td +159.88 530.71 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-250 TJm +(released.) 35.1295 Tj +[1 0 0 1 207.231 530.71] cm +0 g +0 G +[1 0 0 1 -207.231 -530.71] cm +[1 0 0 1 0 0] Tm +0 0 Td +207.231 530.71 Td +/F130_0 9.963 Tf +(fflush) 35.8668 Tj +[1 0 0 1 243.097 530.71] cm +0 g +0 G +[1 0 0 1 -243.097 -530.71] cm +[1 0 0 1 0 0] Tm +0 0 Td +245.587 530.71 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-250 TJm +(called) 23.7916 Tj +-250 TJm +(on) 9.963 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(compressed) 47.0353 Tj +-250 TJm +(\002l) 8.30914 Tj +1 TJm +(e,) 6.91432 Tj +-250 TJm +(b) 4.9815 Tj +20 TJm +(ut) 7.75121 Tj +-250 TJm +(it) 5.53943 Tj +-250 TJm +(is) 6.64532 Tj +-250 TJm +(not) 12.7327 Tj +[1 0 0 1 422.771 530.71] cm +0 g +0 G +[1 0 0 1 -422.771 -530.71] cm +[1 0 0 1 0 0] Tm +0 0 Td +422.771 530.71 Td +/F130_0 9.963 Tf +(fclose) 35.8668 Tj +[1 0 0 1 458.636 530.71] cm +0 g +0 G +[1 0 0 1 -458.636 -530.71] cm +[1 0 0 1 0 0] Tm +0 0 Td +458.636 530.71 Td +/F128_0 9.963 Tf +(') 3.31768 Tj +50 TJm +(d.) 7.47225 Tj +[1 0 0 1 72 528.553] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -518.59] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 508.792 Td +/F128_0 9.963 Tf +(If) 6.63536 Tj +[1 0 0 1 81.574 508.792] cm +0 g +0 G +[1 0 0 1 -81.574 -508.792] cm +[1 0 0 1 0 0] Tm +0 0 Td +81.574 508.792 Td +/F130_0 9.963 Tf +(BZ2_bzWriteClose) 95.6448 Tj +[1 0 0 1 177.216 508.792] cm +0 g +0 G +[1 0 0 1 -177.216 -508.792] cm +[1 0 0 1 0 0] Tm +0 0 Td +180.155 508.792 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-295 TJm +(called) 23.7916 Tj +-295 TJm +(to) 7.75121 Tj +-295 TJm +(clean) 21.0219 Tj +-295 TJm +(up) 9.963 Tj +-295 TJm +(after) 18.2522 Tj +-295 TJm +(an) 9.40507 Tj +-295 TJm +(error) 19.3581 Tj +40 TJm +(,) 2.49075 Tj +-306 TJm +(the) 12.1748 Tj +-295 TJm +(only) 17.7142 Tj +-295 TJm +(action) 24.3496 Tj +-295 TJm +(is) 6.64532 Tj +-295 TJm +(to) 7.75121 Tj +-295 TJm +(relea) 19.3581 Tj +1 TJm +(se) 8.29918 Tj +-295 TJm +(the) 12.1748 Tj +-295 TJm +(memory) 33.2067 Tj +65 TJm +(.) 2.49075 Tj +-890 TJm +(The) 15.4925 Tj +-295 TJm +(library) 26.5614 Tj +72 496.837 Td +(records) 29.3211 Tj +-289 TJm +(the) 12.1748 Tj +-289 TJm +(error) 19.3581 Tj +-289 TJm +(codes) 22.6858 Tj +-289 TJm +(issued) 24.9075 Tj +-289 TJm +(by) 9.963 Tj +-289 TJm +(p) 4.9815 Tj +1 TJm +(re) 7.74125 Tj +25 TJm +(vious) 21.5898 Tj +-289 TJm +(calls,) 20.7529 Tj +-299 TJm +(so) 8.85711 Tj +-289 TJm +(this) 14.3965 Tj +-289 TJm +(situation) 34.3225 Tj +-289 TJm +(will) 15.5024 Tj +-289 TJm +(be) 9.40507 Tj +-289 TJm +(detecte) 28.2152 Tj +1 TJm +(d) 4.9815 Tj +-289 TJm +(automatically) 54.2386 Tj +65 TJm +(.) 2.49075 Tj +-427 TJm +(There) 23.2337 Tj +-289 TJm +(is) 6.64532 Tj +-289 TJm +(no) 9.963 Tj +-289 TJm +(attempt) 29.889 Tj +72 484.882 Td +(to) 7.75121 Tj +-263 TJm +(comple) 29.3311 Tj +1 TJm +(te) 7.19329 Tj +-263 TJm +(the) 12.1748 Tj +-263 TJm +(compression) 50.363 Tj +-262 TJm +(operation,) 40.121 Tj +-266 TJm +(nor) 13.2807 Tj +-262 TJm +(to) 7.75121 Tj +[1 0 0 1 258.308 484.882] cm +0 g +0 G +[1 0 0 1 -258.308 -484.882] cm +[1 0 0 1 0 0] Tm +0 0 Td +258.308 484.882 Td +/F130_0 9.963 Tf +(fflush) 35.8668 Tj +[1 0 0 1 294.173 484.882] cm +0 g +0 G +[1 0 0 1 -294.173 -484.882] cm +[1 0 0 1 0 0] Tm +0 0 Td +296.79 484.882 Td +/F128_0 9.963 Tf +(the) 12.1748 Tj +-263 TJm +(compres) 33.7546 Tj +1 TJm +(sed) 13.2807 Tj +-263 TJm +(\002le.) 15.2235 Tj +-696 TJm +(Y) 7.19329 Tj +110 TJm +(ou) 9.963 Tj +-263 TJm +(can) 13.8286 Tj +-262 TJm +(force) 20.464 Tj +-263 TJm +(this) 14.3965 Tj +-262 TJm +(beha) 18.8101 Tj +20 TJm +(viour) 21.0319 Tj +-263 TJm +(to) 7.75121 Tj +-262 TJm +(happen) 28.7731 Tj +72 472.927 Td +(e) 4.42357 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(en) 9.40507 Tj +-250 TJm +(in) 7.75121 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(case) 17.1463 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(no) 9.963 Tj +-250 TJm +(error) 19.3581 Tj +40 TJm +(,) 2.49075 Tj +-250 TJm +(by) 9.963 Tj +-250 TJm +(p) 4.9815 Tj +1 TJm +(assing) 24.9075 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(nonzero) 32.0908 Tj +-250 TJm +(v) 4.9815 Tj +25 TJm +(alue) 16.5984 Tj +-250 TJm +(to) 7.75121 Tj +[1 0 0 1 305.015 472.927] cm +0 g +0 G +[1 0 0 1 -305.015 -472.927] cm +[1 0 0 1 0 0] Tm +0 0 Td +305.015 472.927 Td +/F130_0 9.963 Tf +(abandon) 41.8446 Tj +[1 0 0 1 346.858 472.927] cm +0 g +0 G +[1 0 0 1 -346.858 -472.927] cm +[1 0 0 1 0 0] Tm +0 0 Td +346.858 472.927 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 72 470.77] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -460.807] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 451.009 Td +/F128_0 9.963 Tf +(If) 6.63536 Tj +[1 0 0 1 80.597 451.009] cm +0 g +0 G +[1 0 0 1 -80.597 -451.009] cm +[1 0 0 1 0 0] Tm +0 0 Td +80.597 451.009 Td +/F130_0 9.963 Tf +(nbytes_in) 53.8002 Tj +[1 0 0 1 134.396 451.009] cm +0 g +0 G +[1 0 0 1 -134.396 -451.009] cm +[1 0 0 1 0 0] Tm +0 0 Td +136.358 451.009 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-197 TJm +(non-null,) 36.2554 Tj +[1 0 0 1 183.287 451.009] cm +0 g +0 G +[1 0 0 1 -183.287 -451.009] cm +[1 0 0 1 0 0] Tm +0 0 Td +183.287 451.009 Td +/F130_0 9.963 Tf +(*nbytes_in) 59.778 Tj +[1 0 0 1 243.063 451.009] cm +0 g +0 G +[1 0 0 1 -243.063 -451.009] cm +[1 0 0 1 0 0] Tm +0 0 Td +245.025 451.009 Td +/F128_0 9.963 Tf +(will) 15.5024 Tj +-197 TJm +(be) 9.40507 Tj +-197 TJm +(set) 11.0689 Tj +-197 TJm +(to) 7.75121 Tj +-197 TJm +(be) 9.40507 Tj +-197 TJm +(the) 12.1748 Tj +-197 TJm +(tot) 10.5209 Tj +1 TJm +(al) 7.19329 Tj +-197 TJm +(v) 4.9815 Tj +20 TJm +(olume) 24.9075 Tj +-197 TJm +(of) 8.29918 Tj +-197 TJm +(uncompressed) 56.9983 Tj +-197 TJm +(data) 16.5984 Tj +-197 TJm +(handled.) 34.0336 Tj +-584 TJm +(Similarly) 37.0922 Tj +65 TJm +(,) 2.49075 Tj +[1 0 0 1 72 439.054] cm +0 g +0 G +[1 0 0 1 -72 -439.054] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 439.054 Td +/F130_0 9.963 Tf +(nbytes_out) 59.778 Tj +[1 0 0 1 131.776 439.054] cm +0 g +0 G +[1 0 0 1 -131.776 -439.054] cm +[1 0 0 1 0 0] Tm +0 0 Td +134.716 439.054 Td +/F128_0 9.963 Tf +(will) 15.5024 Tj +-295 TJm +(be) 9.40507 Tj +-295 TJm +(set) 11.0689 Tj +-295 TJm +(to) 7.75121 Tj +-295 TJm +(the) 12.1748 Tj +-295 TJm +(total) 17.7142 Tj +-295 TJm +(v) 4.9815 Tj +20 TJm +(olume) 24.9075 Tj +-295 TJm +(of) 8.29918 Tj +-295 TJm +(compressed) 47.0353 Tj +-295 TJm +(data) 16.5984 Tj +-295 TJm +(written.) 30.7159 Tj +-890 TJm +(F) 5.53943 Tj +15 TJm +(or) 8.29918 Tj +-295 TJm +(compatibility) 53.1426 Tj +-295 TJm +(with) 17.7142 Tj +-295 TJm +(older) 20.474 Tj +-295 TJm +(v) 4.9815 Tj +15 TJm +(ersions) 28.2252 Tj +-295 TJm +(of) 8.29918 Tj +72 427.098 Td +(the) 12.1748 Tj +-283 TJm +(library) 26.5614 Tj +65 TJm +(,) 2.49075 Tj +[1 0 0 1 118.294 427.098] cm +0 g +0 G +[1 0 0 1 -118.294 -427.098] cm +[1 0 0 1 0 0] Tm +0 0 Td +118.294 427.098 Td +/F130_0 9.963 Tf +(BZ2_bzWriteClose) 95.6448 Tj +[1 0 0 1 213.936 427.098] cm +0 g +0 G +[1 0 0 1 -213.936 -427.098] cm +[1 0 0 1 0 0] Tm +0 0 Td +216.753 427.098 Td +/F128_0 9.963 Tf +(only) 17.7142 Tj +-283 TJm +(yields) 23.8016 Tj +-282 TJm +(the) 12.1748 Tj +-283 TJm +(lo) 7.75121 Tj +25 TJm +(wer) 14.9345 Tj +-283 TJm +(32) 9.963 Tj +-283 TJm +(bits) 14.3965 Tj +-282 TJm +(of) 8.29918 Tj +-283 TJm +(these) 20.474 Tj +-283 TJm +(counts.) 28.5041 Tj +-817 TJm +(Use) 15.4925 Tj +[1 0 0 1 423.499 427.098] cm +0 g +0 G +[1 0 0 1 -423.499 -427.098] cm +[1 0 0 1 0 0] Tm +0 0 Td +423.499 427.098 Td +/F130_0 9.963 Tf +(BZ2_bzWriteClose64) 107.6 Tj +[1 0 0 1 531.095 427.098] cm +0 g +0 G +[1 0 0 1 -531.095 -427.098] cm +[1 0 0 1 0 0] Tm +0 0 Td +533.913 427.098 Td +/F128_0 9.963 Tf +(if) 6.08739 Tj +72 415.143 Td +(you) 14.9445 Tj +-250 TJm +(w) 7.19329 Tj +10 TJm +(ant) 12.1748 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(full) 13.8386 Tj +-250 TJm +(64) 9.963 Tj +-250 TJm +(bit) 10.5209 Tj +-250 TJm +(counts) 26.0134 Tj +1 TJm +(.) 2.49075 Tj +-620 TJm +(These) 23.7916 Tj +-250 TJm +(tw) 9.963 Tj +10 TJm +(o) 4.9815 Tj +-250 TJm +(functions) 37.0823 Tj +-250 TJm +(are) 12.1648 Tj +-250 TJm +(otherwise) 38.7361 Tj +-250 TJm +(absolutely) 40.9579 Tj +-250 TJm +(identic) 27.1193 Tj +1 TJm +(al.) 9.68404 Tj +[1 0 0 1 72 412.986] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -403.024] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 393.225 Td +/F128_0 9.963 Tf +(Possible) 33.2166 Tj +-250 TJm +(assignments) 48.7091 Tj +-250 TJm +(to) 7.75121 Tj +[1 0 0 1 169.144 393.225] cm +0 g +0 G +[1 0 0 1 -169.144 -393.225] cm +[1 0 0 1 0 0] Tm +0 0 Td +169.144 393.225 Td +/F130_0 9.963 Tf +(bzerror) 41.8446 Tj +[1 0 0 1 210.987 393.225] cm +0 g +0 G +[1 0 0 1 -210.987 -393.225] cm +[1 0 0 1 0 0] Tm +0 0 Td +210.987 393.225 Td +/F128_0 9.963 Tf +(:) 2.76971 Tj +[1 0 0 1 72 391.069] cm +0 g +0 G +[1 0 0 1 0 -84.683] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 83.686 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 80.099] cm +0 g +0 G +[1 0 0 1 18 -8.368] cm +0 g +0 G +[1 0 0 1 -90 -381.704] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 381.704 Td +/F130_0 9.963 Tf +(BZ_SEQUENCE_ERROR) 101.623 Tj +98.488 369.749 Td +(if) 11.9556 Tj +-426 TJm +(b) 5.9778 Tj +-426 TJm +(was) 17.9334 Tj +-426 TJm +(opened) 35.8668 Tj +-426 TJm +(with) 23.9112 Tj +-426 TJm +(BZ2) 17.9334 Tj +1 TJm +(_bzReadOpen) 65.7558 Tj +90 357.793 Td +(BZ_IO_ERROR) 65.7558 Tj +98.488 345.838 Td +(if) 11.9556 Tj +-426 TJm +(there) 29.889 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(an) 11.9556 Tj +-426 TJm +(error) 29.889 Tj +-426 TJm +(wri) 17.9334 Tj +1 TJm +(ting) 23.9112 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(compressed) 59.778 Tj +-426 TJm +(file) 23.9112 Tj +90 333.883 Td +(BZ_OK) 29.889 Tj +98.488 321.928 Td +(otherwise) 53.8002 Tj +[1 0 0 1 72 306.386] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -3.587] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -296.423] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 275.765 Td +/F121_0 17.215 Tf +(3.4.8.) 43.0719 Tj +-278 TJm +(Handling) 73.6458 Tj +-278 TJm +(embed) 55.4839 Tj +10 TJm +(ded) 30.6083 Tj +-278 TJm +(compressed) 101.414 Tj +-278 TJm +(data) 35.394 Tj +-278 TJm +(streams) 66.0195 Tj +[1 0 0 1 72 271.935] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -261.972] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 253.847 Td +/F128_0 9.963 Tf +(The) 15.4925 Tj +-203 TJm +(high-le) 28.2252 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(el) 7.19329 Tj +-203 TJm +(library) 26.5614 Tj +-203 TJm +(f) 3.31768 Tj +10 TJm +(acilitates) 35.4185 Tj +-203 TJm +(use) 13.2807 Tj +-203 TJm +(of) 8.29918 Tj +[1 0 0 1 226.404 253.847] cm +0 g +0 G +[1 0 0 1 -226.404 -253.847] cm +[1 0 0 1 0 0] Tm +0 0 Td +226.404 253.847 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 256.292 253.847] cm +0 g +0 G +[1 0 0 1 -256.292 -253.847] cm +[1 0 0 1 0 0] Tm +0 0 Td +258.316 253.847 Td +/F128_0 9.963 Tf +(data) 16.5984 Tj +-203 TJm +(streams) 30.437 Tj +-203 TJm +(which) 24.3496 Tj +-203 TJm +(form) 19.3681 Tj +-203 TJm +(some) 21.0319 Tj +-203 TJm +(part) 15.4925 Tj +-203 TJm +(of) 8.29918 Tj +-203 TJm +(a) 4.42357 Tj +-203 TJm +(surrounding,) 50.6419 Tj +-212 TJm +(lar) 10.511 Tj +18 TJm +(ger) 12.7228 Tj +-203 TJm +(data) 16.5984 Tj +-203 TJm +(stream.) 29.0521 Tj +[1 0 0 1 72 251.69] cm +0 g +0 G +[1 0 0 1 0 -29.723] cm +0 g +0 G +[1 0 0 1 6.974 0] cm +0 g +0 G +[1 0 0 1 -78.974 -221.967] cm +[1 0 0 1 0 0] Tm +0 0 Td +78.974 221.967 Td +/F128_0 9.963 Tf +(\225) 3.48705 Tj +[1 0 0 1 82.461 221.967] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 1.993 0] cm +0 g +0 G +[1 0 0 1 -86.944 -221.967] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 221.967 Td +/F128_0 9.963 Tf +(F) 5.53943 Tj +15 TJm +(or) 8.29918 Tj +-240 TJm +(writing,) 31.2739 Tj +-243 TJm +(the) 12.1748 Tj +-240 TJm +(library) 26.5614 Tj +-240 TJm +(tak) 12.1748 Tj +10 TJm +(es) 8.29918 Tj +-241 TJm +(an) 9.40507 Tj +-240 TJm +(open) 19.3681 Tj +-241 TJm +(\002le) 12.7327 Tj +-240 TJm +(handle,) 29.0521 Tj +-242 TJm +(writes) 24.3496 Tj +-241 TJm +(compress) 37.6303 Tj +1 TJm +(ed) 9.40507 Tj +-241 TJm +(data) 16.5984 Tj +-240 TJm +(to) 7.75121 Tj +-241 TJm +(it,) 8.03018 Tj +[1 0 0 1 398.926 221.967] cm +0 g +0 G +[1 0 0 1 -398.926 -221.967] cm +[1 0 0 1 0 0] Tm +0 0 Td +398.926 221.967 Td +/F130_0 9.963 Tf +(fflush) 35.8668 Tj +[1 0 0 1 434.791 221.967] cm +0 g +0 G +[1 0 0 1 -434.791 -221.967] cm +[1 0 0 1 0 0] Tm +0 0 Td +434.791 221.967 Td +/F128_0 9.963 Tf +(es) 8.29918 Tj +-240 TJm +(it) 5.53943 Tj +-241 TJm +(b) 4.9815 Tj +20 TJm +(ut) 7.75121 Tj +-240 TJm +(does) 18.2622 Tj +-241 TJm +(not) 12.7327 Tj +[1 0 0 1 504.135 221.967] cm +0 g +0 G +[1 0 0 1 -504.135 -221.967] cm +[1 0 0 1 0 0] Tm +0 0 Td +504.135 221.967 Td +/F130_0 9.963 Tf +(fclose) 35.8668 Tj +[1 0 0 1 540 221.967] cm +0 g +0 G +[1 0 0 1 -540 -221.967] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 210.012 Td +/F128_0 9.963 Tf +(it.) 8.03018 Tj +-610 TJm +(The) 15.4925 Tj +-235 TJm +(calling) 27.1193 Tj +-235 TJm +(application) 44.2756 Tj +-234 TJm +(can) 13.8286 Tj +-235 TJm +(write) 20.474 Tj +-235 TJm +(its) 9.41504 Tj +-235 TJm +(o) 4.9815 Tj +25 TJm +(wn) 12.1748 Tj +-235 TJm +(data) 16.5984 Tj +-235 TJm +(before) 25.4455 Tj +-235 TJm +(and) 14.3866 Tj +-235 TJm +(after) 18.2522 Tj +-235 TJm +(the) 12.1748 Tj +-235 TJm +(compressed) 47.0353 Tj +-235 TJm +(dat) 12.1748 Tj +1 TJm +(a) 4.42357 Tj +-235 TJm +(stream,) 29.0521 Tj +-238 TJm +(using) 21.5898 Tj +-235 TJm +(that) 14.9445 Tj +-235 TJm +(same) 20.474 Tj +-235 TJm +(\002le) 12.7327 Tj +86.944 198.056 Td +(handle.) 29.0521 Tj +[1 0 0 1 115.995 198.056] cm +0 g +0 G +[1 0 0 1 -43.995 -21.917] cm +0 g +0 G +[1 0 0 1 6.974 0] cm +0 g +0 G +[1 0 0 1 -78.974 -176.139] cm +[1 0 0 1 0 0] Tm +0 0 Td +78.974 176.139 Td +/F128_0 9.963 Tf +(\225) 3.48705 Tj +[1 0 0 1 82.461 176.139] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 1.993 0] cm +0 g +0 G +[1 0 0 1 -86.944 -176.139] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 176.139 Td +/F128_0 9.963 Tf +(Reading) 33.2067 Tj +-236 TJm +(is) 6.64532 Tj +-236 TJm +(m) 7.75121 Tj +1 TJm +(ore) 12.7228 Tj +-236 TJm +(comple) 29.3311 Tj +15 TJm +(x,) 7.47225 Tj +-239 TJm +(and) 14.3866 Tj +-236 TJm +(the) 12.1748 Tj +-235 TJm +(f) 3.31768 Tj +10 TJm +(acilities) 30.9949 Tj +-236 TJm +(are) 12.1648 Tj +-236 TJm +(not) 12.7327 Tj +-236 TJm +(as) 8.29918 Tj +-235 TJm +(general) 29.3211 Tj +-236 TJm +(as) 8.29918 Tj +-236 TJm +(the) 12.1748 Tj +15 TJm +(y) 4.9815 Tj +-236 TJm +(could) 22.1378 Tj +-236 TJm +(b) 4.9815 Tj +1 TJm +(e) 4.42357 Tj +-236 TJm +(since) 20.474 Tj +-236 TJm +(generality) 39.842 Tj +-236 TJm +(is) 6.64532 Tj +-236 TJm +(har) 12.7228 Tj +1 TJm +(d) 4.9815 Tj +-236 TJm +(to) 7.75121 Tj +-236 TJm +(reconcile) 36.5144 Tj +86.944 164.183 Td +(with) 17.7142 Tj +-404 TJm +(ef) 7.74125 Tj +25 TJm +(\002cienc) 26.5614 Tj +15 TJm +(y) 4.9815 Tj +65 TJm +(.) 2.49075 Tj +[1 0 0 1 164.811 164.183] cm +0 g +0 G +[1 0 0 1 -164.811 -164.183] cm +[1 0 0 1 0 0] Tm +0 0 Td +164.811 164.183 Td +/F130_0 9.963 Tf +(BZ2_bzRead) 59.778 Tj +[1 0 0 1 224.587 164.183] cm +0 g +0 G +[1 0 0 1 -224.587 -164.183] cm +[1 0 0 1 0 0] Tm +0 0 Td +228.614 164.183 Td +/F128_0 9.963 Tf +(reads) 21.0219 Tj +-404 TJm +(from) 19.3681 Tj +-404 TJm +(the) 12.1748 Tj +-405 TJm +(com) 17.1563 Tj +1 TJm +(pressed) 29.879 Tj +-405 TJm +(\002le) 12.7327 Tj +-404 TJm +(in) 7.75121 Tj +-404 TJm +(blocks) 26.0134 Tj +-404 TJm +(of) 8.29918 Tj +-404 TJm +(size) 15.4925 Tj +[1 0 0 1 434.744 164.183] cm +0 g +0 G +[1 0 0 1 -434.744 -164.183] cm +[1 0 0 1 0 0] Tm +0 0 Td +434.744 164.183 Td +/F130_0 9.963 Tf +(BZ_MAX_UNUSED) 77.7114 Tj +[1 0 0 1 512.452 164.183] cm +0 g +0 G +[1 0 0 1 -512.452 -164.183] cm +[1 0 0 1 0 0] Tm +0 0 Td +516.479 164.183 Td +/F128_0 9.963 Tf +(bytes,) 23.5226 Tj +86.944 152.228 Td +(and) 14.3866 Tj +-413 TJm +(in) 7.75121 Tj +-413 TJm +(doing) 22.6957 Tj +-413 TJm +(so) 8.85711 Tj +-413 TJm +(probably) 35.4185 Tj +-413 TJm +(wi) 9.963 Tj +1 TJm +(ll) 5.53943 Tj +-413 TJm +(o) 4.9815 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(ershoot) 29.3311 Tj +-413 TJm +(the) 12.1748 Tj +-413 TJm +(logical) 27.1193 Tj +-413 TJm +(end) 14.3866 Tj +-413 TJm +(of) 8.29918 Tj +-413 TJm +(compressed) 47.0353 Tj +-413 TJm +(stream.) 29.0521 Tj +-1597 TJm +(T) 6.08739 Tj +80 TJm +(o) 4.9815 Tj +-413 TJm +(reco) 17.1463 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(er) 7.74125 Tj +-413 TJm +(this) 14.3965 Tj +-413 TJm +(data) 16.5984 Tj +-413 TJm +(once) 18.8101 Tj +86.944 140.273 Td +(decompression) 59.768 Tj +-252 TJm +(has) 13.2807 Tj +-252 TJm +(ended,) 26.2824 Tj +-252 TJm +(call) 14.3866 Tj +[1 0 0 1 210.705 140.273] cm +0 g +0 G +[1 0 0 1 -210.705 -140.273] cm +[1 0 0 1 0 0] Tm +0 0 Td +210.705 140.273 Td +/F130_0 9.963 Tf +(BZ2_bzReadGetUnused) 113.578 Tj +[1 0 0 1 324.279 140.273] cm +0 g +0 G +[1 0 0 1 -324.279 -140.273] cm +[1 0 0 1 0 0] Tm +0 0 Td +326.789 140.273 Td +/F128_0 9.963 Tf +(after) 18.2522 Tj +-252 TJm +(the) 12.1748 Tj +-252 TJm +(last) 13.8386 Tj +-252 TJm +(call) 14.3866 Tj +-252 TJm +(of) 8.29918 Tj +[1 0 0 1 406.291 140.273] cm +0 g +0 G +[1 0 0 1 -406.291 -140.273] cm +[1 0 0 1 0 0] Tm +0 0 Td +406.291 140.273 Td +/F130_0 9.963 Tf +(BZ2_bzRead) 59.778 Tj +[1 0 0 1 466.067 140.273] cm +0 g +0 G +[1 0 0 1 -466.067 -140.273] cm +[1 0 0 1 0 0] Tm +0 0 Td +468.578 140.273 Td +/F128_0 9.963 Tf +(\(the) 15.4925 Tj +-252 TJm +(one) 14.3866 Tj +-252 TJm +(returning) 36.5244 Tj +[1 0 0 1 86.944 128.318] cm +0 g +0 G +[1 0 0 1 -86.944 -128.318] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 128.318 Td +/F130_0 9.963 Tf +(BZ_STREAM_END) 77.7114 Tj +[1 0 0 1 164.653 128.318] cm +0 g +0 G +[1 0 0 1 -164.653 -128.318] cm +[1 0 0 1 0 0] Tm +0 0 Td +164.653 128.318 Td +/F128_0 9.963 Tf +(\)) 3.31768 Tj +-250 TJm +(b) 4.9815 Tj +20 TJm +(ut) 7.75121 Tj +-250 TJm +(before) 25.4455 Tj +-250 TJm +(calling) 27.1193 Tj +[1 0 0 1 243.028 128.318] cm +0 g +0 G +[1 0 0 1 -243.028 -128.318] cm +[1 0 0 1 0 0] Tm +0 0 Td +243.028 128.318 Td +/F130_0 9.963 Tf +(BZ2_bzReadClose) 89.667 Tj +[1 0 0 1 332.692 128.318] cm +0 g +0 G +[1 0 0 1 -332.692 -128.318] cm +[1 0 0 1 0 0] Tm +0 0 Td +332.692 128.318 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 335.182 128.318] cm +0 g +0 G +[1 0 0 1 -263.182 -77.466] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.754] cm +0 g +0 G +0 g +0 G +[1 0 0 1 40.572 -6.754] cm +0 g +0 G +[1 0 0 1 -493.841 -50.852] cm +[1 0 0 1 0 0] Tm +0 0 Td +534.414 50.852 Td +/F128_0 9.963 Tf +(24) 9.963 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 28 28 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 -8.911] cm +0 g +0 G +[1 0 0 1 0 8.911] cm +0 g +0 G +0 g +0 G +[1 0 0 1 84.08 -6.755] cm +0 g +0 G +[1 0 0 1 -350.151 -749.245] cm +[1 0 0 1 0 0] Tm +0 0 Td +434.231 749.245 Td +/F128_0 9.963 Tf +(Programming) 54.7965 Tj +-250 TJm +(with) 17.7142 Tj +-250 TJm +(libbzip2) 32.6587 Tj +[1 0 0 1 266.071 747.089] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -5.037] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -468 -21.554] cm +0 g +0 G +[1 0 0 1 -72 -720] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 710.037 Td +/F128_0 9.963 Tf +(This) 17.7142 Tj +-271 TJm +(mechanism) 45.3815 Tj +-271 TJm +(mak) 17.1563 Tj +10 TJm +(es) 8.29918 Tj +-272 TJm +(i) 2.76971 Tj +1 TJm +(t) 2.76971 Tj +-272 TJm +(easy) 17.7043 Tj +-271 TJm +(to) 7.75121 Tj +-271 TJm +(decompress) 47.0353 Tj +-271 TJm +(multiple) 33.2166 Tj +[1 0 0 1 293.313 710.037] cm +0 g +0 G +[1 0 0 1 -293.313 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +293.313 710.037 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 323.2 710.037] cm +0 g +0 G +[1 0 0 1 -323.2 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +325.903 710.037 Td +/F128_0 9.963 Tf +(streams) 30.437 Tj +-271 TJm +(placed) 26.0034 Tj +-271 TJm +(end-to-end.) 45.6505 Tj +-374 TJm +(As) 11.0689 Tj +-271 TJm +(the) 12.1748 Tj +-272 TJm +(end) 14.3866 Tj +-271 TJm +(of) 8.29918 Tj +-271 TJm +(one) 14.3866 Tj +-271 TJm +(stream,) 29.0521 Tj +72 698.082 Td +(when) 21.5799 Tj +[1 0 0 1 96.195 698.082] cm +0 g +0 G +[1 0 0 1 -96.195 -698.082] cm +[1 0 0 1 0 0] Tm +0 0 Td +96.195 698.082 Td +/F130_0 9.963 Tf +(BZ2_bzRead) 59.778 Tj +[1 0 0 1 155.971 698.082] cm +0 g +0 G +[1 0 0 1 -155.971 -698.082] cm +[1 0 0 1 0 0] Tm +0 0 Td +158.586 698.082 Td +/F128_0 9.963 Tf +(returns) 27.6673 Tj +[1 0 0 1 188.868 698.082] cm +0 g +0 G +[1 0 0 1 -188.868 -698.082] cm +[1 0 0 1 0 0] Tm +0 0 Td +188.868 698.082 Td +/F130_0 9.963 Tf +(BZ_STREAM_END) 77.7114 Tj +[1 0 0 1 266.577 698.082] cm +0 g +0 G +[1 0 0 1 -266.577 -698.082] cm +[1 0 0 1 0 0] Tm +0 0 Td +266.577 698.082 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-263 TJm +(c) 4.42357 Tj +1 TJm +(all) 9.963 Tj +[1 0 0 1 288.685 698.082] cm +0 g +0 G +[1 0 0 1 -288.685 -698.082] cm +[1 0 0 1 0 0] Tm +0 0 Td +288.685 698.082 Td +/F130_0 9.963 Tf +(BZ2_bzReadGetUnused) 113.578 Tj +[1 0 0 1 402.259 698.082] cm +0 g +0 G +[1 0 0 1 -402.259 -698.082] cm +[1 0 0 1 0 0] Tm +0 0 Td +404.875 698.082 Td +/F128_0 9.963 Tf +(to) 7.75121 Tj +-262 TJm +(collect) 26.5614 Tj +-263 TJm +(the) 12.1748 Tj +-262 TJm +(unused) 28.2252 Tj +-263 TJm +(data) 16.5984 Tj +-262 TJm +(\(cop) 17.7043 Tj +10 TJm +(y) 4.9815 Tj +-263 TJm +(it) 5.53943 Tj +72 686.127 Td +(into) 15.5024 Tj +-265 TJm +(your) 18.2622 Tj +-265 TJm +(o) 4.9815 Tj +25 TJm +(wn) 12.1748 Tj +-265 TJm +(b) 4.9815 Tj +20 TJm +(uf) 8.29918 Tj +25 TJm +(fer) 11.0589 Tj +-265 TJm +(some) 21.0319 Tj +25 TJm +(where\).) 30.148 Tj +-710 TJm +(That) 18.2622 Tj +-265 TJm +(data) 16.5984 Tj +-265 TJm +(forms) 23.2437 Tj +-265 TJm +(the) 12.1748 Tj +-265 TJm +(start) 17.1563 Tj +-265 TJm +(of) 8.29918 Tj +-265 TJm +(the) 12.1748 Tj +-265 TJm +(ne) 9.40507 Tj +15 TJm +(xt) 7.75121 Tj +-265 TJm +(compressed) 47.0353 Tj +-265 TJm +(stream.) 29.0521 Tj +-710 TJm +(T) 6.08739 Tj +80 TJm +(o) 4.9815 Tj +-265 TJm +(start) 17.1563 Tj +-265 TJm +(uncompressing) 60.326 Tj +72 674.172 Td +(that) 14.9445 Tj +-246 TJm +(ne) 9.40507 Tj +15 TJm +(xt) 7.75121 Tj +-246 TJm +(stream,) 29.0521 Tj +-247 TJm +(call) 14.3866 Tj +[1 0 0 1 157.205 674.172] cm +0 g +0 G +[1 0 0 1 -157.205 -674.172] cm +[1 0 0 1 0 0] Tm +0 0 Td +157.205 674.172 Td +/F130_0 9.963 Tf +(BZ2_bzReadOpen) 83.6892 Tj +[1 0 0 1 240.891 674.172] cm +0 g +0 G +[1 0 0 1 -240.891 -674.172] cm +[1 0 0 1 0 0] Tm +0 0 Td +243.344 674.172 Td +/F128_0 9.963 Tf +(ag) 9.40507 Tj +5 TJm +(ain,) 14.6655 Tj +-247 TJm +(feeding) 29.879 Tj +-246 TJm +(in) 7.75121 Tj +-246 TJm +(the) 12.1748 Tj +-246 TJm +(unused) 28.2252 Tj +-246 TJm +(data) 16.5984 Tj +-246 TJm +(via) 12.1748 Tj +-247 TJm +(the) 12.1748 Tj +[1 0 0 1 405.967 674.172] cm +0 g +0 G +[1 0 0 1 -405.967 -674.172] cm +[1 0 0 1 0 0] Tm +0 0 Td +405.967 674.172 Td +/F130_0 9.963 Tf +(unused) 35.8668 Tj +[1 0 0 1 441.833 674.172] cm +0 g +0 G +[1 0 0 1 -441.833 -674.172] cm +[1 0 0 1 0 0] Tm +0 0 Td +444.286 674.172 Td +/F128_0 9.963 Tf +(/) 2.76971 Tj +[1 0 0 1 449.508 674.172] cm +0 g +0 G +[1 0 0 1 -449.508 -674.172] cm +[1 0 0 1 0 0] Tm +0 0 Td +449.508 674.172 Td +/F130_0 9.963 Tf +(nUnused) 41.8446 Tj +[1 0 0 1 491.351 674.172] cm +0 g +0 G +[1 0 0 1 -491.351 -674.172] cm +[1 0 0 1 0 0] Tm +0 0 Td +493.804 674.172 Td +/F128_0 9.963 Tf +(parameters.) 46.1984 Tj +72 662.217 Td +(K) 7.19329 Tj +25 TJm +(eep) 13.8286 Tj +-263 TJm +(doing) 22.6957 Tj +-263 TJm +(this) 14.3965 Tj +-263 TJm +(until) 18.2721 Tj +[1 0 0 1 158.622 662.217] cm +0 g +0 G +[1 0 0 1 -158.622 -662.217] cm +[1 0 0 1 0 0] Tm +0 0 Td +158.622 662.217 Td +/F130_0 9.963 Tf +(BZ_STREAM_END) 77.7114 Tj +[1 0 0 1 236.33 662.217] cm +0 g +0 G +[1 0 0 1 -236.33 -662.217] cm +[1 0 0 1 0 0] Tm +0 0 Td +238.952 662.217 Td +/F128_0 9.963 Tf +(return) 23.7916 Tj +-263 TJm +(coincides) 37.6303 Tj +-263 TJm +(with) 17.7142 Tj +-263 TJm +(the) 12.1748 Tj +-263 TJm +(ph) 9.963 Tj +5 TJm +(ysical) 23.2437 Tj +-263 TJm +(end) 14.3866 Tj +-263 TJm +(of) 8.29918 Tj +-264 TJm +(\002le) 12.7327 Tj +-263 TJm +(\() 3.31768 Tj +[1 0 0 1 423.125 662.217] cm +0 g +0 G +[1 0 0 1 -423.125 -662.217] cm +[1 0 0 1 0 0] Tm +0 0 Td +423.125 662.217 Td +/F130_0 9.963 Tf +(feof\(f\)) 41.8446 Tj +[1 0 0 1 464.968 662.217] cm +0 g +0 G +[1 0 0 1 -464.968 -662.217] cm +[1 0 0 1 0 0] Tm +0 0 Td +464.968 662.217 Td +/F128_0 9.963 Tf +(\).) 5.80843 Tj +-699 TJm +(In) 8.29918 Tj +-263 TJm +(this) 14.3965 Tj +-263 TJm +(situation) 34.3225 Tj +[1 0 0 1 72 650.262] cm +0 g +0 G +[1 0 0 1 -72 -650.262] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 650.262 Td +/F130_0 9.963 Tf +(BZ2_bzReadGetUnused) 113.578 Tj +[1 0 0 1 185.574 650.262] cm +0 g +0 G +[1 0 0 1 -185.574 -650.262] cm +[1 0 0 1 0 0] Tm +0 0 Td +188.065 650.262 Td +/F128_0 9.963 Tf +(will) 15.5024 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(course) 26.0034 Tj +-250 TJm +(return) 23.7916 Tj +-250 TJm +(no) 9.963 Tj +-250 TJm +(data) 16.5984 Tj +1 TJm +(.) 2.49075 Tj +[1 0 0 1 72 649.096] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -639.133] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 628.344 Td +/F128_0 9.963 Tf +(This) 17.7142 Tj +-240 TJm +(should) 26.5713 Tj +-241 TJm +(gi) 7.75121 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-240 TJm +(some) 21.0319 Tj +-240 TJm +(feel) 14.9345 Tj +-241 TJm +(for) 11.6169 Tj +-240 TJm +(ho) 9.963 Tj +25 TJm +(w) 7.19329 Tj +-240 TJm +(the) 12.1748 Tj +-241 TJm +(high-le) 28.2252 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(el) 7.19329 Tj +-240 TJm +(interf) 21.5799 Tj +10 TJm +(ace) 13.2707 Tj +-240 TJm +(can) 13.8286 Tj +-241 TJm +(be) 9.40507 Tj +-240 TJm +(used.) 20.7529 Tj +-614 TJm +(If) 6.63536 Tj +-240 TJm +(you) 14.9445 Tj +-240 TJm +(require) 28.2152 Tj +-241 TJm +(e) 4.42357 Tj +15 TJm +(xtra) 15.4925 Tj +-240 TJm +(\003e) 9.963 Tj +15 TJm +(xibility) 28.7931 Tj +65 TJm +(,) 2.49075 Tj +-242 TJm +(you') 18.2622 Tj +10 TJm +(ll) 5.53943 Tj +-241 TJm +(ha) 9.40507 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-240 TJm +(to) 7.75121 Tj +72 616.389 Td +(bite) 14.9445 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(b) 4.9815 Tj +20 TJm +(ullet) 17.7142 Tj +-250 TJm +(and) 14.3866 Tj +-250 TJm +(get) 12.1748 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(grip) 16.0504 Tj +1 TJm +(s) 3.87561 Tj +-250 TJm +(with) 17.7142 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(lo) 7.75121 Tj +25 TJm +(w-le) 17.7043 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(el) 7.19329 Tj +-250 TJm +(interf) 21.5799 Tj +10 TJm +(ace.) 15.7615 Tj +[1 0 0 1 72 614.232] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -604.269] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 585.767 Td +/F121_0 17.215 Tf +(3.4.9.) 43.0719 Tj +-278 TJm +(Standar) 64.0914 Tj +20 TJm +(d) 10.5184 Tj +-278 TJm +(\002le-reading/writing) 154.005 Tj +-278 TJm +(code) 40.1798 Tj +[1 0 0 1 72 581.937] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -571.974] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 563.85 Td +/F128_0 9.963 Tf +(Here') 22.6758 Tj +55 TJm +(s) 3.87561 Tj +-250 TJm +(ho) 9.963 Tj +25 TJm +(w) 7.19329 Tj +-250 TJm +(you') 18.2622 Tj +50 TJm +(d) 4.9815 Tj +-250 TJm +(write) 20.474 Tj +-250 TJm +(data) 16.5984 Tj +-250 TJm +(to) 7.75121 Tj +-249 TJm +(a) 4.42357 Tj +-250 TJm +(compressed) 47.0353 Tj +-250 TJm +(\002le:) 15.5024 Tj +[1 0 0 1 72 561.693] cm +0 g +0 G +[1 0 0 1 0 -371.607] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 370.61 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 367.023] cm +0 g +0 G +[1 0 0 1 18 -8.368] cm +0 g +0 G +[1 0 0 1 -90 -552.328] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 552.328 Td +/F130_0 9.963 Tf +(FILE*) 29.889 Tj +-1278 TJm +(f;) 11.9556 Tj +90 540.373 Td +(BZFILE*) 41.8446 Tj +-426 TJm +(b;) 11.9556 Tj +90 528.418 Td +(int) 17.9334 Tj +-2130 TJm +(nBuf;) 29.889 Tj +90 516.462 Td +(char) 23.9112 Tj +-1704 TJm +(buf[) 23.9112 Tj +-426 TJm +(/*) 11.9556 Tj +-426 TJm +(whatever) 47.8224 Tj +-425 TJm +(size) 23.9112 Tj +-426 TJm +(you) 17.9334 Tj +-426 TJm +(like) 23.9112 Tj +-426 TJm +(*/) 11.9556 Tj +-426 TJm +(];) 11.9556 Tj +90 504.507 Td +(int) 17.9334 Tj +-2130 TJm +(bzerror;) 47.8224 Tj +90 492.552 Td +(int) 17.9334 Tj +-2130 TJm +(nWritten;) 53.8002 Tj +90 468.642 Td +(f) 5.9778 Tj +-426 TJm +(=) 5.9778 Tj +-426 TJm +(fopen) 29.889 Tj +-426 TJm +(\() 5.9778 Tj +-426 TJm +("myfile.bz2") 71.7336 Tj +1 TJm +(,) 5.9778 Tj +-426 TJm +("w") 17.9334 Tj +-426 TJm +(\);) 11.9556 Tj +90 456.687 Td +(if) 11.9556 Tj +-426 TJm +(\() 5.9778 Tj +-426 TJm +(!f) 11.9556 Tj +-426 TJm +(\)) 5.9778 Tj +-426 TJm +({) 5.9778 Tj +94.244 444.731 Td +(/*) 11.9556 Tj +-426 TJm +(handle) 35.8668 Tj +-426 TJm +(error) 29.889 Tj +-426 TJm +(*/) 11.9556 Tj +90 432.776 Td +(}) 5.9778 Tj +90 420.821 Td +(b) 5.9778 Tj +-426 TJm +(=) 5.9778 Tj +-426 TJm +(BZ2_bzWriteOpen\() 95.6448 Tj +-426 TJm +(&bze) 23.9112 Tj +1 TJm +(rror,) 29.889 Tj +-426 TJm +(f,) 11.9556 Tj +-426 TJm +(9) 5.9778 Tj +-426 TJm +(\);) 11.9556 Tj +90 408.866 Td +(if) 11.9556 Tj +-426 TJm +(\(bzerror) 47.8224 Tj +-426 TJm +(!=) 11.9556 Tj +-426 TJm +(BZ_OK\)) 35.8668 Tj +-426 TJm +({) 5.9778 Tj +94.244 396.911 Td +(BZ2_bzWriteClose) 95.6448 Tj +-426 TJm +(\() 5.9778 Tj +-426 TJm +(b) 5.9778 Tj +-426 TJm +(\);) 11.9556 Tj +94.244 384.955 Td +(/*) 11.9556 Tj +-426 TJm +(handle) 35.8668 Tj +-426 TJm +(error) 29.889 Tj +-426 TJm +(*/) 11.9556 Tj +90 373 Td +(}) 5.9778 Tj +90 349.09 Td +(while) 29.889 Tj +-426 TJm +(\() 5.9778 Tj +-426 TJm +(/*) 11.9556 Tj +-426 TJm +(condition) 53.8002 Tj +-426 TJm +(*/) 11.9556 Tj +-425 TJm +(\)) 5.9778 Tj +-426 TJm +({) 5.9778 Tj +94.244 337.135 Td +(/*) 11.9556 Tj +-426 TJm +(get) 17.9334 Tj +-426 TJm +(data) 23.9112 Tj +-426 TJm +(to) 11.9556 Tj +-426 TJm +(write) 29.889 Tj +-426 TJm +(int) 17.9334 Tj +1 TJm +(o) 5.9778 Tj +-426 TJm +(buf,) 23.9112 Tj +-426 TJm +(and) 17.9334 Tj +-426 TJm +(set) 17.9334 Tj +-426 TJm +(nBuf) 23.9112 Tj +-426 TJm +(appropriately) 77.7114 Tj +-426 TJm +(*/) 11.9556 Tj +94.244 325.18 Td +(nWritten) 47.8224 Tj +-426 TJm +(=) 5.9778 Tj +-426 TJm +(BZ2_bzWrite) 65.7558 Tj +-426 TJm +(\() 5.9778 Tj +-425 TJm +(&bzerror,) 53.8002 Tj +-426 TJm +(b,) 11.9556 Tj +-426 TJm +(buf,) 23.9112 Tj +-426 TJm +(nBuf) 23.9112 Tj +-426 TJm +(\);) 11.9556 Tj +94.244 313.224 Td +(if) 11.9556 Tj +-426 TJm +(\(bzerror) 47.8224 Tj +-426 TJm +(==) 11.9556 Tj +-426 TJm +(BZ_IO_ERRO) 59.778 Tj +1 TJm +(R\)) 11.9556 Tj +-426 TJm +({) 5.9778 Tj +102.732 301.269 Td +(BZ2_bzWriteClose) 95.6448 Tj +-426 TJm +(\() 5.9778 Tj +-426 TJm +(&bzerr) 35.8668 Tj +1 TJm +(or,) 17.9334 Tj +-426 TJm +(b) 5.9778 Tj +-426 TJm +(\);) 11.9556 Tj +102.732 289.314 Td +(/*) 11.9556 Tj +-426 TJm +(handle) 35.8668 Tj +-426 TJm +(error) 29.889 Tj +-426 TJm +(*/) 11.9556 Tj +94.244 277.359 Td +(}) 5.9778 Tj +90 265.404 Td +(}) 5.9778 Tj +90 241.493 Td +(BZ2_bzWriteClose\() 101.623 Tj +-426 TJm +(&bzerro) 41.8446 Tj +1 TJm +(r,) 11.9556 Tj +-426 TJm +(b) 5.9778 Tj +-426 TJm +(\);) 11.9556 Tj +90 229.538 Td +(if) 11.9556 Tj +-426 TJm +(\(bzerror) 47.8224 Tj +-426 TJm +(==) 11.9556 Tj +-426 TJm +(BZ_IO_ERRO) 59.778 Tj +1 TJm +(R\)) 11.9556 Tj +-426 TJm +({) 5.9778 Tj +94.244 217.583 Td +(/*) 11.9556 Tj +-426 TJm +(handle) 35.8668 Tj +-426 TJm +(error) 29.889 Tj +-426 TJm +(*/) 11.9556 Tj +90 205.628 Td +(}) 5.9778 Tj +[1 0 0 1 72 190.086] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.549] cm +0 g +0 G +[1 0 0 1 -72 -180.124] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 168.168 Td +/F128_0 9.963 Tf +(And) 17.1563 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(read) 17.1463 Tj +-250 TJm +(from) 19.3681 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(compresse) 42.0538 Tj +1 TJm +(d) 4.9815 Tj +-250 TJm +(\002le:) 15.5024 Tj +[1 0 0 1 72 166.012] cm +0 g +0 G +[1 0 0 1 0 -115.16] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.854] cm +0 g +0 G +0 g +0 G +[1 0 0 1 40.572 -6.755] cm +0 g +0 G +[1 0 0 1 -493.841 -50.951] cm +[1 0 0 1 0 0] Tm +0 0 Td +534.414 50.951 Td +/F128_0 9.963 Tf +(25) 9.963 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 29 29 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 -8.911] cm +0 g +0 G +[1 0 0 1 0 8.911] cm +0 g +0 G +0 g +0 G +[1 0 0 1 84.08 -6.755] cm +0 g +0 G +[1 0 0 1 -350.151 -749.245] cm +[1 0 0 1 0 0] Tm +0 0 Td +434.231 749.245 Td +/F128_0 9.963 Tf +(Programming) 54.7965 Tj +-250 TJm +(with) 17.7142 Tj +-250 TJm +(libbzip2) 32.6587 Tj +[1 0 0 1 266.071 747.089] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -5.037] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -468 -392.164] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 370.61 re +f +Q +0 g +0 G +[1 0 0 1 0 3.586] cm +0 g +0 G +[1 0 0 1 0 367.024] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -711.631] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 711.631 Td +/F130_0 9.963 Tf +(FILE*) 29.889 Tj +-1278 TJm +(f;) 11.9556 Tj +90 699.676 Td +(BZFILE*) 41.8446 Tj +-426 TJm +(b;) 11.9556 Tj +90 687.721 Td +(int) 17.9334 Tj +-2130 TJm +(nBuf;) 29.889 Tj +90 675.766 Td +(char) 23.9112 Tj +-1704 TJm +(buf[) 23.9112 Tj +-426 TJm +(/*) 11.9556 Tj +-426 TJm +(whatever) 47.8224 Tj +-425 TJm +(size) 23.9112 Tj +-426 TJm +(you) 17.9334 Tj +-426 TJm +(like) 23.9112 Tj +-426 TJm +(*/) 11.9556 Tj +-426 TJm +(];) 11.9556 Tj +90 663.811 Td +(int) 17.9334 Tj +-2130 TJm +(bzerror;) 47.8224 Tj +90 651.856 Td +(int) 17.9334 Tj +-2130 TJm +(nWritten;) 53.8002 Tj +90 627.945 Td +(f) 5.9778 Tj +-426 TJm +(=) 5.9778 Tj +-426 TJm +(fopen) 29.889 Tj +-426 TJm +(\() 5.9778 Tj +-426 TJm +("myfile.bz2") 71.7336 Tj +1 TJm +(,) 5.9778 Tj +-426 TJm +("r") 17.9334 Tj +-426 TJm +(\);) 11.9556 Tj +90 615.99 Td +(if) 11.9556 Tj +-426 TJm +(\() 5.9778 Tj +-426 TJm +(!f) 11.9556 Tj +-426 TJm +(\)) 5.9778 Tj +-426 TJm +({) 5.9778 Tj +98.488 604.035 Td +(/*) 11.9556 Tj +-426 TJm +(handle) 35.8668 Tj +-426 TJm +(error) 29.889 Tj +-426 TJm +(*/) 11.9556 Tj +90 592.08 Td +(}) 5.9778 Tj +90 580.125 Td +(b) 5.9778 Tj +-426 TJm +(=) 5.9778 Tj +-426 TJm +(BZ2_bzReadOpen) 83.6892 Tj +-426 TJm +(\() 5.9778 Tj +-426 TJm +(&bz) 17.9334 Tj +1 TJm +(error,) 35.8668 Tj +-426 TJm +(f,) 11.9556 Tj +-426 TJm +(0,) 11.9556 Tj +-426 TJm +(NULL,) 29.889 Tj +-426 TJm +(0) 5.9778 Tj +-426 TJm +(\);) 11.9556 Tj +90 568.169 Td +(if) 11.9556 Tj +-426 TJm +(\() 5.9778 Tj +-426 TJm +(bzerror) 41.8446 Tj +-426 TJm +(!=) 11.9556 Tj +-426 TJm +(BZ_OK) 29.889 Tj +-426 TJm +(\)) 5.9778 Tj +-425 TJm +({) 5.9778 Tj +98.488 556.214 Td +(BZ2_bzReadClose) 89.667 Tj +-426 TJm +(\() 5.9778 Tj +-426 TJm +(&bzerro) 41.8446 Tj +1 TJm +(r,) 11.9556 Tj +-426 TJm +(b) 5.9778 Tj +-426 TJm +(\);) 11.9556 Tj +98.488 544.259 Td +(/*) 11.9556 Tj +-426 TJm +(handle) 35.8668 Tj +-426 TJm +(error) 29.889 Tj +-426 TJm +(*/) 11.9556 Tj +90 532.304 Td +(}) 5.9778 Tj +90 508.393 Td +(bzerror) 41.8446 Tj +-426 TJm +(=) 5.9778 Tj +-426 TJm +(BZ_OK;) 35.8668 Tj +90 496.438 Td +(while) 29.889 Tj +-426 TJm +(\() 5.9778 Tj +-426 TJm +(bzerror) 41.8446 Tj +-426 TJm +(==) 11.9556 Tj +-426 TJm +(BZ_OK) 29.889 Tj +-425 TJm +(&&) 11.9556 Tj +-426 TJm +(/*) 11.9556 Tj +-426 TJm +(arbitrary) 53.8002 Tj +-426 TJm +(other) 29.889 Tj +-426 TJm +(conditions) 59.778 Tj +-426 TJm +(*/\)) 17.9334 Tj +-426 TJm +({) 5.9778 Tj +98.488 484.483 Td +(nBuf) 23.9112 Tj +-426 TJm +(=) 5.9778 Tj +-426 TJm +(BZ2_bzRead) 59.778 Tj +-426 TJm +(\() 5.9778 Tj +-426 TJm +(&bze) 23.9112 Tj +1 TJm +(rror,) 29.889 Tj +-426 TJm +(b,) 11.9556 Tj +-426 TJm +(buf,) 23.9112 Tj +-426 TJm +(/*) 11.9556 Tj +-426 TJm +(size) 23.9112 Tj +-426 TJm +(of) 11.9556 Tj +-426 TJm +(buf) 17.9334 Tj +-426 TJm +(*/) 11.9556 Tj +-426 TJm +(\);) 11.9556 Tj +98.488 472.528 Td +(if) 11.9556 Tj +-426 TJm +(\() 5.9778 Tj +-426 TJm +(bzerror) 41.8446 Tj +-426 TJm +(==) 11.9556 Tj +-426 TJm +(BZ_OK) 29.889 Tj +-426 TJm +(\)) 5.9778 Tj +-425 TJm +({) 5.9778 Tj +106.976 460.573 Td +(/*) 11.9556 Tj +-426 TJm +(do) 11.9556 Tj +-426 TJm +(something) 53.8002 Tj +-426 TJm +(with) 23.9112 Tj +-426 TJm +(buf) 17.9334 Tj +1 TJm +([0) 11.9556 Tj +-426 TJm +(..) 11.9556 Tj +-426 TJm +(nBuf-1]) 41.8446 Tj +-426 TJm +(*/) 11.9556 Tj +98.488 448.618 Td +(}) 5.9778 Tj +90 436.662 Td +(}) 5.9778 Tj +90 424.707 Td +(if) 11.9556 Tj +-426 TJm +(\() 5.9778 Tj +-426 TJm +(bzerror) 41.8446 Tj +-426 TJm +(!=) 11.9556 Tj +-426 TJm +(BZ_STREAM) 53.8002 Tj +1 TJm +(_END) 23.9112 Tj +-426 TJm +(\)) 5.9778 Tj +-426 TJm +({) 5.9778 Tj +102.732 412.752 Td +(BZ2_bzReadClose) 89.667 Tj +-426 TJm +(\() 5.9778 Tj +-426 TJm +(&bzerro) 41.8446 Tj +1 TJm +(r,) 11.9556 Tj +-426 TJm +(b) 5.9778 Tj +-426 TJm +(\);) 11.9556 Tj +102.732 400.797 Td +(/*) 11.9556 Tj +-426 TJm +(handle) 35.8668 Tj +-426 TJm +(error) 29.889 Tj +-426 TJm +(*/) 11.9556 Tj +90 388.842 Td +(}) 5.9778 Tj +-426 TJm +(else) 23.9112 Tj +-426 TJm +({) 5.9778 Tj +102.732 376.887 Td +(BZ2_bzReadClose) 89.667 Tj +-426 TJm +(\() 5.9778 Tj +-426 TJm +(&bzerro) 41.8446 Tj +1 TJm +(r) 5.9778 Tj +-426 TJm +(\);) 11.9556 Tj +90 364.931 Td +(}) 5.9778 Tj +[1 0 0 1 72 349.39] cm +0 g +0 G +[1 0 0 1 468 3.586] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -3.586] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -339.427] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 314.637 Td +/F121_0 20.659 Tf +(3.5.) 34.4592 Tj +-278 TJm +(Utility) 57.3907 Tj +-278 TJm +(functions) 92.9655 Tj +[1 0 0 1 72 310.361] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -300.398] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 284.016 Td +/F121_0 17.215 Tf +(3.5.1.) 43.0719 Tj +[1 0 0 1 119.858 284.016] cm +0 g +0 G +[1 0 0 1 -119.858 -284.016] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.858 284.016 Td +/F387_0 17.215 Tf +(BZ2_bzBuffToBuffCompress) 247.896 Tj +[1 0 0 1 367.76 284.016] cm +0 g +0 G +[1 0 0 1 -295.76 -2.333] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -96.638] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 95.641 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 92.055] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -272.318] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 272.318 Td +/F130_0 9.963 Tf +(int) 17.9334 Tj +-426 TJm +(BZ2_bzBuffToBuffCompr) 125.534 Tj +1 TJm +(ess\() 23.9112 Tj +-426 TJm +(char*) 29.889 Tj +-3834 TJm +(dest,) 29.889 Tj +217.319 260.363 Td +(unsigned) 47.8224 Tj +-426 TJm +(int*) 23.9112 Tj +-426 TJm +(destLen,) 47.8224 Tj +217.319 248.408 Td +(char*) 29.889 Tj +-3834 TJm +(source,) 41.8446 Tj +217.319 236.453 Td +(unsigned) 47.8224 Tj +-426 TJm +(int) 17.9334 Tj +-852 TJm +(sourceLen,) 59.778 Tj +217.319 224.498 Td +(int) 17.9334 Tj +-4686 TJm +(blockSize) 53.8002 Tj +1 TJm +(100k,) 29.889 Tj +217.319 212.542 Td +(int) 17.9334 Tj +-4686 TJm +(verbosity) 53.8002 Tj +1 TJm +(,) 5.9778 Tj +217.319 200.587 Td +(int) 17.9334 Tj +-4686 TJm +(workFacto) 53.8002 Tj +1 TJm +(r) 5.9778 Tj +-426 TJm +(\);) 11.9556 Tj +[1 0 0 1 72 185.045] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.549] cm +0 g +0 G +[1 0 0 1 -72 -175.083] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 163.128 Td +/F128_0 9.963 Tf +(Attempts) 36.5343 Tj +-442 TJm +(to) 7.75121 Tj +-442 TJm +(compress) 37.6303 Tj +-442 TJm +(the) 12.1748 Tj +-442 TJm +(data) 16.5984 Tj +-443 TJm +(in) 7.75121 Tj +[1 0 0 1 216.87 163.128] cm +0 g +0 G +[1 0 0 1 -216.87 -163.128] cm +[1 0 0 1 0 0] Tm +0 0 Td +216.87 163.128 Td +/F130_0 9.963 Tf +(source[0) 47.8224 Tj +-600 TJm +(..) 11.9556 Tj +-1200 TJm +(sourceLen-1]) 71.7336 Tj +[1 0 0 1 366.309 163.128] cm +0 g +0 G +[1 0 0 1 -366.309 -163.128] cm +[1 0 0 1 0 0] Tm +0 0 Td +370.715 163.128 Td +/F128_0 9.963 Tf +(into) 15.5024 Tj +-442 TJm +(the) 12.1748 Tj +-442 TJm +(destination) 43.7276 Tj +-442 TJm +(b) 4.9815 Tj +20 TJm +(uf) 8.29918 Tj +25 TJm +(fer) 11.0589 Tj +40 TJm +(,) 2.49075 Tj +[1 0 0 1 486.202 163.128] cm +0 g +0 G +[1 0 0 1 -486.202 -163.128] cm +[1 0 0 1 0 0] Tm +0 0 Td +486.202 163.128 Td +/F130_0 9.963 Tf +(dest[0) 35.8668 Tj +-600 TJm +(..) 11.9556 Tj +72 151.173 Td +(*destLen-1]) 65.7558 Tj +[1 0 0 1 137.753 151.173] cm +0 g +0 G +[1 0 0 1 -137.753 -151.173] cm +[1 0 0 1 0 0] Tm +0 0 Td +137.753 151.173 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +-1393 TJm +(If) 6.63536 Tj +-379 TJm +(the) 12.1748 Tj +-379 TJm +(destinat) 30.9949 Tj +1 TJm +(ion) 12.7327 Tj +-379 TJm +(b) 4.9815 Tj +20 TJm +(uf) 8.29918 Tj +25 TJm +(fer) 11.0589 Tj +-379 TJm +(is) 6.64532 Tj +-379 TJm +(big) 12.7327 Tj +-379 TJm +(enoug) 24.3496 Tj +1 TJm +(h,) 7.47225 Tj +[1 0 0 1 318.487 151.173] cm +0 g +0 G +[1 0 0 1 -318.487 -151.173] cm +[1 0 0 1 0 0] Tm +0 0 Td +318.487 151.173 Td +/F130_0 9.963 Tf +(*destLen) 47.8224 Tj +[1 0 0 1 366.307 151.173] cm +0 g +0 G +[1 0 0 1 -366.307 -151.173] cm +[1 0 0 1 0 0] Tm +0 0 Td +370.082 151.173 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-379 TJm +(set) 11.0689 Tj +-379 TJm +(t) 2.76971 Tj +1 TJm +(o) 4.9815 Tj +-379 TJm +(the) 12.1748 Tj +-379 TJm +(size) 15.4925 Tj +-379 TJm +(of) 8.29918 Tj +-379 TJm +(the) 12.1748 Tj +-378 TJm +(compressed) 47.0353 Tj +-379 TJm +(data,) 19.0891 Tj +72 139.217 Td +(and) 14.3866 Tj +[1 0 0 1 89.527 139.217] cm +0 g +0 G +[1 0 0 1 -89.527 -139.217] cm +[1 0 0 1 0 0] Tm +0 0 Td +89.527 139.217 Td +/F130_0 9.963 Tf +(BZ_OK) 29.889 Tj +[1 0 0 1 119.415 139.217] cm +0 g +0 G +[1 0 0 1 -119.415 -139.217] cm +[1 0 0 1 0 0] Tm +0 0 Td +122.556 139.217 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-315 TJm +(returned.) 35.6875 Tj +-1012 TJm +(If) 6.63536 Tj +-315 TJm +(the) 12.1748 Tj +-315 TJm +(compressed) 47.0353 Tj +-316 TJm +(da) 9.40507 Tj +1 TJm +(ta) 7.19329 Tj +-316 TJm +(w) 7.19329 Tj +10 TJm +(on') 13.2807 Tj +18 TJm +(t) 2.76971 Tj +-315 TJm +(\002t,) 10.7999 Tj +[1 0 0 1 313.323 139.217] cm +0 g +0 G +[1 0 0 1 -313.323 -139.217] cm +[1 0 0 1 0 0] Tm +0 0 Td +313.323 139.217 Td +/F130_0 9.963 Tf +(*destLen) 47.8224 Tj +[1 0 0 1 361.143 139.217] cm +0 g +0 G +[1 0 0 1 -361.143 -139.217] cm +[1 0 0 1 0 0] Tm +0 0 Td +364.285 139.217 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-315 TJm +(unchanged,) 45.6505 Tj +-332 TJm +(and) 14.3866 Tj +[1 0 0 1 440.551 139.217] cm +0 g +0 G +[1 0 0 1 -440.551 -139.217] cm +[1 0 0 1 0 0] Tm +0 0 Td +440.551 139.217 Td +/F130_0 9.963 Tf +(BZ_OUTBUFF_FULL) 89.667 Tj +[1 0 0 1 530.214 139.217] cm +0 g +0 G +[1 0 0 1 -530.214 -139.217] cm +[1 0 0 1 0 0] Tm +0 0 Td +533.355 139.217 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +72 127.262 Td +(returned.) 35.6875 Tj +[1 0 0 1 72 127.163] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -117.2] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 105.344 Td +/F128_0 9.963 Tf +(Compression) 52.5847 Tj +-297 TJm +(in) 7.75121 Tj +-297 TJm +(this) 14.3965 Tj +-297 TJm +(manner) 29.879 Tj +-297 TJm +(is) 6.64532 Tj +-297 TJm +(a) 4.42357 Tj +-297 TJm +(one-shot) 34.3126 Tj +-297 TJm +(e) 4.42357 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(ent,) 14.6655 Tj +-308 TJm +(done) 19.3681 Tj +-297 TJm +(with) 17.7142 Tj +-297 TJm +(a) 4.42357 Tj +-297 TJm +(single) 23.8016 Tj +-297 TJm +(call) 14.3866 Tj +-297 TJm +(to) 7.75121 Tj +-297 TJm +(this) 14.3965 Tj +-297 TJm +(function.) 35.6974 Tj +-902 TJm +(The) 15.4925 Tj +-297 TJm +(resulting) 34.8705 Tj +-297 TJm +(compressed) 47.0353 Tj +72 93.389 Td +(data) 16.5984 Tj +-296 TJm +(is) 6.64532 Tj +-296 TJm +(a) 4.42357 Tj +-296 TJm +(complete) 36.5244 Tj +[1 0 0 1 147.987 93.389] cm +0 g +0 G +[1 0 0 1 -147.987 -93.389] cm +[1 0 0 1 0 0] Tm +0 0 Td +147.987 93.389 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 177.875 93.389] cm +0 g +0 G +[1 0 0 1 -177.875 -93.389] cm +[1 0 0 1 0 0] Tm +0 0 Td +180.825 93.389 Td +/F128_0 9.963 Tf +(format) 26.5614 Tj +-296 TJm +(data) 16.5984 Tj +-296 TJm +(stream.) 29.0521 Tj +-896 TJm +(There) 23.2337 Tj +-296 TJm +(is) 6.64532 Tj +-296 TJm +(no) 9.963 Tj +-296 TJm +(mechanism) 45.3815 Tj +-296 TJm +(for) 11.6169 Tj +-296 TJm +(making) 29.889 Tj +-296 TJm +(additional) 39.852 Tj +-296 TJm +(calls) 18.2622 Tj +-296 TJm +(to) 7.75121 Tj +-296 TJm +(pro) 13.2807 Tj +15 TJm +(vide) 17.1563 Tj +-296 TJm +(e) 4.42357 Tj +15 TJm +(xtra) 15.4925 Tj +72 81.434 Td +(input) 20.4839 Tj +-250 TJm +(data.) 19.0891 Tj +-620 TJm +(If) 6.63536 Tj +-250 TJm +(you) 14.9445 Tj +-250 TJm +(w) 7.19329 Tj +10 TJm +(ant) 12.1748 Tj +-250 TJm +(that) 14.9445 Tj +-250 TJm +(k) 4.9815 Tj +1 TJm +(ind) 12.7327 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(mechanism,) 47.8722 Tj +-250 TJm +(use) 13.2807 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(lo) 7.75121 Tj +25 TJm +(w-le) 17.7043 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(el) 7.19329 Tj +-250 TJm +(interf) 21.5799 Tj +10 TJm +(ace.) 15.7615 Tj +[1 0 0 1 72 79.277] cm +0 g +0 G +[1 0 0 1 0 -28.425] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.854] cm +0 g +0 G +0 g +0 G +[1 0 0 1 40.572 -6.755] cm +0 g +0 G +[1 0 0 1 -493.841 -50.951] cm +[1 0 0 1 0 0] Tm +0 0 Td +534.414 50.951 Td +/F128_0 9.963 Tf +(26) 9.963 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 30 30 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 -8.911] cm +0 g +0 G +[1 0 0 1 0 8.911] cm +0 g +0 G +0 g +0 G +[1 0 0 1 84.08 -6.755] cm +0 g +0 G +[1 0 0 1 -350.151 -749.245] cm +[1 0 0 1 0 0] Tm +0 0 Td +434.231 749.245 Td +/F128_0 9.963 Tf +(Programming) 54.7965 Tj +-250 TJm +(with) 17.7142 Tj +-250 TJm +(libbzip2) 32.6587 Tj +[1 0 0 1 266.071 747.089] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -5.037] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -468 -21.554] cm +0 g +0 G +[1 0 0 1 -72 -720] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 710.037 Td +/F128_0 9.963 Tf +(F) 5.53943 Tj +15 TJm +(or) 8.29918 Tj +-223 TJm +(the) 12.1748 Tj +-224 TJm +(meaning) 34.3126 Tj +-223 TJm +(of) 8.29918 Tj +-223 TJm +(parameters) 43.7077 Tj +[1 0 0 1 195.306 710.037] cm +0 g +0 G +[1 0 0 1 -195.306 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +195.306 710.037 Td +/F130_0 9.963 Tf +(blockSize100k) 77.7114 Tj +[1 0 0 1 273.015 710.037] cm +0 g +0 G +[1 0 0 1 -273.015 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +273.015 710.037 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 277.784 710.037] cm +0 g +0 G +[1 0 0 1 -277.784 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +277.784 710.037 Td +/F130_0 9.963 Tf +(verbosity) 53.8002 Tj +[1 0 0 1 331.583 710.037] cm +0 g +0 G +[1 0 0 1 -331.583 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +333.808 710.037 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 350.42 710.037] cm +0 g +0 G +[1 0 0 1 -350.42 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +350.42 710.037 Td +/F130_0 9.963 Tf +(workFactor) 59.778 Tj +[1 0 0 1 410.196 710.037] cm +0 g +0 G +[1 0 0 1 -410.196 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +410.196 710.037 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-229 TJm +(see) 12.7228 Tj +[1 0 0 1 429.913 710.037] cm +0 g +0 G +[1 0 0 1 -429.913 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +429.913 710.037 Td +/F130_0 9.963 Tf +(BZ2_bzCompressInit) 107.6 Tj +[1 0 0 1 537.509 710.037] cm +0 g +0 G +[1 0 0 1 -537.509 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +537.509 710.037 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 72 707.881] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -697.918] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 688.12 Td +/F128_0 9.963 Tf +(T) 6.08739 Tj +80 TJm +(o) 4.9815 Tj +-410 TJm +(guarantee) 38.7262 Tj +-410 TJm +(that) 14.9445 Tj +-410 TJm +(the) 12.1748 Tj +-410 TJm +(compressed) 47.0353 Tj +-410 TJm +(data) 16.5984 Tj +-410 TJm +(will) 15.5024 Tj +-410 TJm +(\002) 5.53943 Tj +1 TJm +(t) 2.76971 Tj +-411 TJm +(i) 2.76971 Tj +1 TJm +(n) 4.9815 Tj +-411 TJm +(i) 2.76971 Tj +1 TJm +(ts) 6.64532 Tj +-410 TJm +(b) 4.9815 Tj +20 TJm +(uf) 8.29918 Tj +25 TJm +(fer) 11.0589 Tj +40 TJm +(,) 2.49075 Tj +-450 TJm +(allocate) 30.9849 Tj +-410 TJm +(an) 9.40507 Tj +-410 TJm +(output) 25.4654 Tj +-410 TJm +(b) 4.9815 Tj +20 TJm +(uf) 8.29918 Tj +25 TJm +(fer) 11.0589 Tj +-410 TJm +(of) 8.29918 Tj +-410 TJm +(size) 15.4925 Tj +-410 TJm +(1%) 13.2807 Tj +-410 TJm +(lar) 10.511 Tj +18 TJm +(ger) 12.7228 Tj +-410 TJm +(than) 17.1563 Tj +-410 TJm +(the) 12.1748 Tj +72 676.164 Td +(uncompressed) 56.9983 Tj +-250 TJm +(data,) 19.0891 Tj +-250 TJm +(plus) 16.6083 Tj +-250 TJm +(six) 11.6268 Tj +-249 TJm +(hundred) 32.6488 Tj +-250 TJm +(e) 4.42357 Tj +15 TJm +(xtra) 15.4925 Tj +-250 TJm +(bytes.) 23.5226 Tj +[1 0 0 1 72 674.008] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -664.045] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 654.247 Td +/F130_0 9.963 Tf +(BZ2_bzBuffToBuffDecompress) 155.423 Tj +[1 0 0 1 227.417 654.247] cm +0 g +0 G +[1 0 0 1 -227.417 -654.247] cm +[1 0 0 1 0 0] Tm +0 0 Td +230.553 654.247 Td +/F128_0 9.963 Tf +(will) 15.5024 Tj +-315 TJm +(not) 12.7327 Tj +-314 TJm +(write) 20.474 Tj +-315 TJm +(data) 16.5984 Tj +-315 TJm +(at) 7.19329 Tj +-315 TJm +(or) 8.29918 Tj +-314 TJm +(be) 9.40507 Tj +15 TJm +(yond) 19.926 Tj +[1 0 0 1 362.484 654.247] cm +0 g +0 G +[1 0 0 1 -362.484 -654.247] cm +[1 0 0 1 0 0] Tm +0 0 Td +362.484 654.247 Td +/F130_0 9.963 Tf +(dest[*destLen]) 83.6892 Tj +[1 0 0 1 446.17 654.247] cm +0 g +0 G +[1 0 0 1 -446.17 -654.247] cm +[1 0 0 1 0 0] Tm +0 0 Td +446.17 654.247 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-331 TJm +(e) 4.42357 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(en) 9.40507 Tj +-315 TJm +(in) 7.75121 Tj +-314 TJm +(case) 17.1463 Tj +-315 TJm +(of) 8.29918 Tj +-315 TJm +(b) 4.9815 Tj +20 TJm +(uf) 8.29918 Tj +25 TJm +(fer) 11.0589 Tj +72 642.291 Td +(o) 4.9815 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(er\003o) 18.2622 Tj +25 TJm +(w) 7.19329 Tj +65 TJm +(.) 2.49075 Tj +[1 0 0 1 72 642.192] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -632.229] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 620.374 Td +/F128_0 9.963 Tf +(Possible) 33.2166 Tj +-250 TJm +(return) 23.7916 Tj +-250 TJm +(v) 4.9815 Tj +25 TJm +(alues:) 23.2437 Tj +[1 0 0 1 72 620.274] cm +0 g +0 G +[1 0 0 1 0 -168.369] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 167.372 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 163.786] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -610.909] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 610.909 Td +/F130_0 9.963 Tf +(BZ_CONFIG_ERROR) 89.667 Tj +98.488 598.954 Td +(if) 11.9556 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(library) 41.8446 Tj +-426 TJm +(has) 17.9334 Tj +-426 TJm +(been) 23.9112 Tj +-425 TJm +(mis-compiled) 71.7336 Tj +90 586.999 Td +(BZ_PARAM_ERROR) 83.6892 Tj +98.488 575.044 Td +(if) 11.9556 Tj +-426 TJm +(dest) 23.9112 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(NULL) 23.9112 Tj +-426 TJm +(or) 11.9556 Tj +-426 TJm +(destL) 29.889 Tj +1 TJm +(en) 11.9556 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(NULL) 23.9112 Tj +98.488 563.088 Td +(or) 11.9556 Tj +-426 TJm +(blockSize100k) 77.7114 Tj +-426 TJm +(<) 5.9778 Tj +-426 TJm +(1) 5.9778 Tj +-426 TJm +(or) 11.9556 Tj +-425 TJm +(blockSize100k) 77.7114 Tj +-426 TJm +(>) 5.9778 Tj +-426 TJm +(9) 5.9778 Tj +98.488 551.133 Td +(or) 11.9556 Tj +-426 TJm +(verbosity) 53.8002 Tj +-426 TJm +(<) 5.9778 Tj +-426 TJm +(0) 5.9778 Tj +-426 TJm +(or) 11.9556 Tj +-426 TJm +(verb) 23.9112 Tj +1 TJm +(osity) 29.889 Tj +-426 TJm +(>) 5.9778 Tj +-426 TJm +(4) 5.9778 Tj +98.488 539.178 Td +(or) 11.9556 Tj +-426 TJm +(workFactor) 59.778 Tj +-426 TJm +(<) 5.9778 Tj +-426 TJm +(0) 5.9778 Tj +-426 TJm +(or) 11.9556 Tj +-426 TJm +(wor) 17.9334 Tj +1 TJm +(kFactor) 41.8446 Tj +-426 TJm +(>) 5.9778 Tj +-426 TJm +(250) 17.9334 Tj +90 527.223 Td +(BZ_MEM_ERROR) 71.7336 Tj +98.488 515.268 Td +(if) 11.9556 Tj +-426 TJm +(insufficient) 71.7336 Tj +-426 TJm +(memory) 35.8668 Tj +-426 TJm +(is) 11.9556 Tj +-425 TJm +(available) 53.8002 Tj +90 503.313 Td +(BZ_OUTBUFF_FULL) 89.667 Tj +98.488 491.357 Td +(if) 11.9556 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(size) 23.9112 Tj +-426 TJm +(of) 11.9556 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(compr) 29.889 Tj +1 TJm +(essed) 29.889 Tj +-426 TJm +(data) 23.9112 Tj +-426 TJm +(exceeds) 41.8446 Tj +-426 TJm +(*destLen) 47.8224 Tj +90 479.402 Td +(BZ_OK) 29.889 Tj +98.488 467.447 Td +(otherwise) 53.8002 Tj +[1 0 0 1 72 451.905] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -3.587] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -441.943] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 421.284 Td +/F121_0 17.215 Tf +(3.5.2.) 43.0719 Tj +[1 0 0 1 119.858 421.284] cm +0 g +0 G +[1 0 0 1 -119.858 -421.284] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.858 421.284 Td +/F387_0 17.215 Tf +(BZ2_bzBuffToBuffDecompress) 268.554 Tj +[1 0 0 1 388.419 421.284] cm +0 g +0 G +[1 0 0 1 -316.419 -2.332] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -84.683] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 83.686 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 80.099] cm +0 g +0 G +[1 0 0 1 18 -8.368] cm +0 g +0 G +[1 0 0 1 -90 -409.587] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 409.587 Td +/F130_0 9.963 Tf +(int) 17.9334 Tj +-426 TJm +(BZ2_bzBuffToBuffDecom) 125.534 Tj +1 TJm +(press\() 35.8668 Tj +-426 TJm +(char*) 29.889 Tj +-3834 TJm +(dest,) 29.889 Tj +225.807 397.632 Td +(unsigned) 47.8224 Tj +-426 TJm +(int*) 23.9112 Tj +-426 TJm +(destLen,) 47.8224 Tj +225.807 385.676 Td +(char*) 29.889 Tj +-3834 TJm +(source,) 41.8446 Tj +225.807 373.721 Td +(unsigned) 47.8224 Tj +-426 TJm +(int) 17.9334 Tj +-852 TJm +(sourceLen,) 59.778 Tj +225.807 361.766 Td +(int) 17.9334 Tj +-4686 TJm +(small,) 35.8668 Tj +225.807 349.811 Td +(int) 17.9334 Tj +-4686 TJm +(verbosity) 53.8002 Tj +-425 TJm +(\);) 11.9556 Tj +[1 0 0 1 72 334.269] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.549] cm +0 g +0 G +[1 0 0 1 -72 -324.307] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 312.351 Td +/F128_0 9.963 Tf +(Attempts) 36.5343 Tj +-358 TJm +(to) 7.75121 Tj +-358 TJm +(decompress) 47.0353 Tj +-359 TJm +(the) 12.1748 Tj +-358 TJm +(data) 16.5984 Tj +-358 TJm +(in) 7.75121 Tj +[1 0 0 1 221.259 312.351] cm +0 g +0 G +[1 0 0 1 -221.259 -312.351] cm +[1 0 0 1 0 0] Tm +0 0 Td +221.259 312.351 Td +/F130_0 9.963 Tf +(source[0) 47.8224 Tj +-600 TJm +(..) 11.9556 Tj +-1200 TJm +(sourceLen-1) 65.7558 Tj +1 TJm +(]) 5.9778 Tj +[1 0 0 1 370.698 312.351] cm +0 g +0 G +[1 0 0 1 -370.698 -312.351] cm +[1 0 0 1 0 0] Tm +0 0 Td +374.268 312.351 Td +/F128_0 9.963 Tf +(into) 15.5024 Tj +-358 TJm +(the) 12.1748 Tj +-359 TJm +(des) 13.2807 Tj +1 TJm +(tination) 30.4469 Tj +-359 TJm +(b) 4.9815 Tj +20 TJm +(uf) 8.29918 Tj +25 TJm +(fer) 11.0589 Tj +40 TJm +(,) 2.49075 Tj +[1 0 0 1 486.202 312.351] cm +0 g +0 G +[1 0 0 1 -486.202 -312.351] cm +[1 0 0 1 0 0] Tm +0 0 Td +486.202 312.351 Td +/F130_0 9.963 Tf +(dest[0) 35.8668 Tj +-600 TJm +(..) 11.9556 Tj +72 300.396 Td +(*destLen-1]) 65.7558 Tj +[1 0 0 1 137.753 300.396] cm +0 g +0 G +[1 0 0 1 -137.753 -300.396] cm +[1 0 0 1 0 0] Tm +0 0 Td +137.753 300.396 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +-1123 TJm +(If) 6.63536 Tj +-334 TJm +(the) 12.1748 Tj +-334 TJm +(destination) 43.7276 Tj +-334 TJm +(b) 4.9815 Tj +20 TJm +(uf) 8.29918 Tj +25 TJm +(fer) 11.0589 Tj +-334 TJm +(is) 6.64532 Tj +-333 TJm +(big) 12.7327 Tj +-334 TJm +(enough,) 31.8218 Tj +[1 0 0 1 312.554 300.396] cm +0 g +0 G +[1 0 0 1 -312.554 -300.396] cm +[1 0 0 1 0 0] Tm +0 0 Td +312.554 300.396 Td +/F130_0 9.963 Tf +(*destLen) 47.8224 Tj +[1 0 0 1 360.374 300.396] cm +0 g +0 G +[1 0 0 1 -360.374 -300.396] cm +[1 0 0 1 0 0] Tm +0 0 Td +363.701 300.396 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-334 TJm +(set) 11.0689 Tj +-334 TJm +(to) 7.75121 Tj +-334 TJm +(th) 7.75121 Tj +1 TJm +(e) 4.42357 Tj +-334 TJm +(size) 15.4925 Tj +-334 TJm +(of) 8.29918 Tj +-334 TJm +(the) 12.1748 Tj +-334 TJm +(uncompressed) 56.9983 Tj +-334 TJm +(d) 4.9815 Tj +1 TJm +(ata,) 14.1076 Tj +72 288.441 Td +(and) 14.3866 Tj +[1 0 0 1 89.527 288.441] cm +0 g +0 G +[1 0 0 1 -89.527 -288.441] cm +[1 0 0 1 0 0] Tm +0 0 Td +89.527 288.441 Td +/F130_0 9.963 Tf +(BZ_OK) 29.889 Tj +[1 0 0 1 119.415 288.441] cm +0 g +0 G +[1 0 0 1 -119.415 -288.441] cm +[1 0 0 1 0 0] Tm +0 0 Td +122.556 288.441 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-315 TJm +(returned.) 35.6875 Tj +-1012 TJm +(If) 6.63536 Tj +-315 TJm +(the) 12.1748 Tj +-315 TJm +(compressed) 47.0353 Tj +-316 TJm +(da) 9.40507 Tj +1 TJm +(ta) 7.19329 Tj +-316 TJm +(w) 7.19329 Tj +10 TJm +(on') 13.2807 Tj +18 TJm +(t) 2.76971 Tj +-315 TJm +(\002t,) 10.7999 Tj +[1 0 0 1 313.323 288.441] cm +0 g +0 G +[1 0 0 1 -313.323 -288.441] cm +[1 0 0 1 0 0] Tm +0 0 Td +313.323 288.441 Td +/F130_0 9.963 Tf +(*destLen) 47.8224 Tj +[1 0 0 1 361.143 288.441] cm +0 g +0 G +[1 0 0 1 -361.143 -288.441] cm +[1 0 0 1 0 0] Tm +0 0 Td +364.285 288.441 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-315 TJm +(unchanged,) 45.6505 Tj +-332 TJm +(and) 14.3866 Tj +[1 0 0 1 440.551 288.441] cm +0 g +0 G +[1 0 0 1 -440.551 -288.441] cm +[1 0 0 1 0 0] Tm +0 0 Td +440.551 288.441 Td +/F130_0 9.963 Tf +(BZ_OUTBUFF_FULL) 89.667 Tj +[1 0 0 1 530.214 288.441] cm +0 g +0 G +[1 0 0 1 -530.214 -288.441] cm +[1 0 0 1 0 0] Tm +0 0 Td +533.355 288.441 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +72 276.486 Td +(returned.) 35.6875 Tj +[1 0 0 1 72 276.386] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -266.424] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 254.568 Td +/F130_0 9.963 Tf +(source) 35.8668 Tj +[1 0 0 1 107.865 254.568] cm +0 g +0 G +[1 0 0 1 -107.865 -254.568] cm +[1 0 0 1 0 0] Tm +0 0 Td +110.981 254.568 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-313 TJm +(assumed) 34.3126 Tj +-312 TJm +(to) 7.75121 Tj +-313 TJm +(hold) 17.7142 Tj +-313 TJm +(a) 4.42357 Tj +-312 TJm +(complete) 36.5244 Tj +[1 0 0 1 237.04 254.568] cm +0 g +0 G +[1 0 0 1 -237.04 -254.568] cm +[1 0 0 1 0 0] Tm +0 0 Td +237.04 254.568 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 266.928 254.568] cm +0 g +0 G +[1 0 0 1 -266.928 -254.568] cm +[1 0 0 1 0 0] Tm +0 0 Td +270.044 254.568 Td +/F128_0 9.963 Tf +(format) 26.5614 Tj +-313 TJm +(dat) 12.1748 Tj +1 TJm +(a) 4.42357 Tj +-313 TJm +(stream.) 29.0521 Tj +[1 0 0 1 353.446 254.568] cm +0 g +0 G +[1 0 0 1 -353.446 -254.568] cm +[1 0 0 1 0 0] Tm +0 0 Td +353.446 254.568 Td +/F130_0 9.963 Tf +(BZ2_bzBuffToBuffDecompres) 149.445 Tj +1 TJm +(s) 5.9778 Tj +[1 0 0 1 508.863 254.568] cm +0 g +0 G +[1 0 0 1 -508.863 -254.568] cm +[1 0 0 1 0 0] Tm +0 0 Td +511.979 254.568 Td +/F128_0 9.963 Tf +(tries) 17.1563 Tj +-313 TJm +(to) 7.75121 Tj +72 242.613 Td +(decompress) 47.0353 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(entirety) 30.437 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(t) 2.76971 Tj +1 TJm +(he) 9.40507 Tj +-250 TJm +(stream) 26.5614 Tj +-250 TJm +(into) 15.5024 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(output) 25.4654 Tj +-250 TJm +(b) 4.9815 Tj +20 TJm +(uf) 8.29918 Tj +25 TJm +(fer) 11.0589 Tj +55 TJm +(.) 2.49075 Tj +[1 0 0 1 72 240.456] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -230.493] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 220.695 Td +/F128_0 9.963 Tf +(F) 5.53943 Tj +15 TJm +(or) 8.29918 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(meaning) 34.3126 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(parameter) 39.8321 Tj +1 TJm +(s) 3.87561 Tj +[1 0 0 1 196.631 220.695] cm +0 g +0 G +[1 0 0 1 -196.631 -220.695] cm +[1 0 0 1 0 0] Tm +0 0 Td +196.631 220.695 Td +/F130_0 9.963 Tf +(small) 29.889 Tj +[1 0 0 1 226.519 220.695] cm +0 g +0 G +[1 0 0 1 -226.519 -220.695] cm +[1 0 0 1 0 0] Tm +0 0 Td +229.01 220.695 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 245.887 220.695] cm +0 g +0 G +[1 0 0 1 -245.887 -220.695] cm +[1 0 0 1 0 0] Tm +0 0 Td +245.887 220.695 Td +/F130_0 9.963 Tf +(verbosity) 53.8002 Tj +[1 0 0 1 299.685 220.695] cm +0 g +0 G +[1 0 0 1 -299.685 -220.695] cm +[1 0 0 1 0 0] Tm +0 0 Td +299.685 220.695 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-250 TJm +(see) 12.7228 Tj +[1 0 0 1 319.879 220.695] cm +0 g +0 G +[1 0 0 1 -319.879 -220.695] cm +[1 0 0 1 0 0] Tm +0 0 Td +319.879 220.695 Td +/F130_0 9.963 Tf +(BZ2_bzDecompressInit) 119.556 Tj +[1 0 0 1 439.431 220.695] cm +0 g +0 G +[1 0 0 1 -439.431 -220.695] cm +[1 0 0 1 0 0] Tm +0 0 Td +439.431 220.695 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 72 218.538] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -208.576] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 198.777 Td +/F128_0 9.963 Tf +(Because) 33.1967 Tj +-249 TJm +(the) 12.1748 Tj +-250 TJm +(compression) 50.363 Tj +-249 TJm +(ratio) 18.2622 Tj +-250 TJm +(of) 8.29918 Tj +-249 TJm +(the) 12.1748 Tj +-250 TJm +(compressed) 47.0353 Tj +-249 TJm +(data) 16.5984 Tj +-250 TJm +(canno) 23.7916 Tj +1 TJm +(t) 2.76971 Tj +-250 TJm +(be) 9.40507 Tj +-250 TJm +(kno) 14.9445 Tj +25 TJm +(w) 7.19329 Tj +1 TJm +(n) 4.9815 Tj +-250 TJm +(in) 7.75121 Tj +-250 TJm +(adv) 14.3866 Tj +25 TJm +(a) 4.42357 Tj +1 TJm +(nce,) 16.3194 Tj +-250 TJm +(there) 19.916 Tj +-250 TJm +(is) 6.64532 Tj +-249 TJm +(no) 9.963 Tj +-250 TJm +(easy) 17.7043 Tj +-249 TJm +(w) 7.19329 Tj +10 TJm +(ay) 9.40507 Tj +-250 TJm +(to) 7.75121 Tj +-249 TJm +(guarantee) 38.7262 Tj +72 186.822 Td +(that) 14.9445 Tj +-286 TJm +(the) 12.1748 Tj +-287 TJm +(output) 25.4654 Tj +-286 TJm +(b) 4.9815 Tj +20 TJm +(uf) 8.29918 Tj +25 TJm +(fer) 11.0589 Tj +-286 TJm +(will) 15.5024 Tj +-287 TJm +(be) 9.40507 Tj +-286 TJm +(big) 12.7327 Tj +-286 TJm +(enough.) 31.8218 Tj +-839 TJm +(Y) 7.19329 Tj +110 TJm +(ou) 9.963 Tj +-286 TJm +(may) 17.1563 Tj +-286 TJm +(of) 8.29918 Tj +-287 TJm +(course) 26.0034 Tj +-286 TJm +(mak) 17.1563 Tj +10 TJm +(e) 4.42357 Tj +-286 TJm +(arrangements) 53.6707 Tj +-287 TJm +(in) 7.75121 Tj +-286 TJm +(your) 18.2622 Tj +-286 TJm +(code) 18.8101 Tj +-287 TJm +(to) 7.75121 Tj +-286 TJm +(record) 25.4455 Tj +-286 TJm +(the) 12.1748 Tj +-287 TJm +(size) 15.4925 Tj +-286 TJm +(of) 8.29918 Tj +72 174.867 Td +(the) 12.1748 Tj +-250 TJm +(uncompressed) 56.9983 Tj +-250 TJm +(data,) 19.0891 Tj +-250 TJm +(b) 4.9815 Tj +20 TJm +(ut) 7.75121 Tj +-250 TJm +(su) 8.85711 Tj +1 TJm +(ch) 9.40507 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(mechanism) 45.3815 Tj +-250 TJm +(is) 6.64532 Tj +-250 TJm +(be) 9.40507 Tj +15 TJm +(yond) 19.926 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(scope) 22.6858 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(this) 14.3965 Tj +-250 TJm +(library) 26.5614 Tj +65 TJm +(.) 2.49075 Tj +[1 0 0 1 72 172.71] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -162.747] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 152.949 Td +/F130_0 9.963 Tf +(BZ2_bzBuffToBuffDecompress) 155.423 Tj +[1 0 0 1 227.417 152.949] cm +0 g +0 G +[1 0 0 1 -227.417 -152.949] cm +[1 0 0 1 0 0] Tm +0 0 Td +230.553 152.949 Td +/F128_0 9.963 Tf +(will) 15.5024 Tj +-315 TJm +(not) 12.7327 Tj +-314 TJm +(write) 20.474 Tj +-315 TJm +(data) 16.5984 Tj +-315 TJm +(at) 7.19329 Tj +-315 TJm +(or) 8.29918 Tj +-314 TJm +(be) 9.40507 Tj +15 TJm +(yond) 19.926 Tj +[1 0 0 1 362.484 152.949] cm +0 g +0 G +[1 0 0 1 -362.484 -152.949] cm +[1 0 0 1 0 0] Tm +0 0 Td +362.484 152.949 Td +/F130_0 9.963 Tf +(dest[*destLen]) 83.6892 Tj +[1 0 0 1 446.17 152.949] cm +0 g +0 G +[1 0 0 1 -446.17 -152.949] cm +[1 0 0 1 0 0] Tm +0 0 Td +446.17 152.949 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-331 TJm +(e) 4.42357 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(en) 9.40507 Tj +-315 TJm +(in) 7.75121 Tj +-314 TJm +(case) 17.1463 Tj +-315 TJm +(of) 8.29918 Tj +-315 TJm +(b) 4.9815 Tj +20 TJm +(uf) 8.29918 Tj +25 TJm +(fer) 11.0589 Tj +72 140.994 Td +(o) 4.9815 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(er\003o) 18.2622 Tj +25 TJm +(w) 7.19329 Tj +65 TJm +(.) 2.49075 Tj +[1 0 0 1 72 140.894] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -130.932] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 119.076 Td +/F128_0 9.963 Tf +(Possible) 33.2166 Tj +-250 TJm +(return) 23.7916 Tj +-250 TJm +(v) 4.9815 Tj +25 TJm +(alues:) 23.2437 Tj +[1 0 0 1 72 118.977] cm +0 g +0 G +[1 0 0 1 0 -68.125] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.854] cm +0 g +0 G +0 g +0 G +[1 0 0 1 40.572 -6.755] cm +0 g +0 G +[1 0 0 1 -493.841 -50.951] cm +[1 0 0 1 0 0] Tm +0 0 Td +534.414 50.951 Td +/F128_0 9.963 Tf +(27) 9.963 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 31 31 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 4.384 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 -8.911] cm +0 g +0 G +[1 0 0 1 0 8.911] cm +0 g +0 G +0 g +0 G +[1 0 0 1 84.08 -6.755] cm +0 g +0 G +[1 0 0 1 -352.044 -749.245] cm +[1 0 0 1 0 0] Tm +0 0 Td +436.124 749.245 Td +/F128_0 9.963 Tf +(Programming) 54.7965 Tj +-250 TJm +(with) 17.7142 Tj +-250 TJm +(libbzip) 27.6772 Tj +1 TJm +(2) 4.9815 Tj +[1 0 0 1 267.964 747.089] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -5.037] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -15.037 0] cm +0 g +0 G +[1 0 0 1 -468 -248.702] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 227.148 re +f +Q +0 g +0 G +[1 0 0 1 0 3.586] cm +0 g +0 G +[1 0 0 1 0 223.562] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -711.631] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 711.631 Td +/F130_0 9.963 Tf +(BZ_CONFIG_ERROR) 89.667 Tj +98.488 699.676 Td +(if) 11.9556 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(library) 41.8446 Tj +-426 TJm +(has) 17.9334 Tj +-426 TJm +(been) 23.9112 Tj +-425 TJm +(mis-compiled) 71.7336 Tj +90 687.721 Td +(BZ_PARAM_ERROR) 83.6892 Tj +98.488 675.766 Td +(if) 11.9556 Tj +-426 TJm +(dest) 23.9112 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(NULL) 23.9112 Tj +-426 TJm +(or) 11.9556 Tj +-426 TJm +(destL) 29.889 Tj +1 TJm +(en) 11.9556 Tj +-426 TJm +(is) 11.9556 Tj +-426 TJm +(NULL) 23.9112 Tj +98.488 663.811 Td +(or) 11.9556 Tj +-426 TJm +(small) 29.889 Tj +-426 TJm +(!=) 11.9556 Tj +-426 TJm +(0) 5.9778 Tj +-426 TJm +(&&) 11.9556 Tj +-426 TJm +(small) 29.889 Tj +-426 TJm +(!) 5.9778 Tj +1 TJm +(=) 5.9778 Tj +-426 TJm +(1) 5.9778 Tj +98.488 651.856 Td +(or) 11.9556 Tj +-426 TJm +(verbosity) 53.8002 Tj +-426 TJm +(<) 5.9778 Tj +-426 TJm +(0) 5.9778 Tj +-426 TJm +(or) 11.9556 Tj +-426 TJm +(verb) 23.9112 Tj +1 TJm +(osity) 29.889 Tj +-426 TJm +(>) 5.9778 Tj +-426 TJm +(4) 5.9778 Tj +90 639.9 Td +(BZ_MEM_ERROR) 71.7336 Tj +98.488 627.945 Td +(if) 11.9556 Tj +-426 TJm +(insufficient) 71.7336 Tj +-426 TJm +(memory) 35.8668 Tj +-426 TJm +(is) 11.9556 Tj +-425 TJm +(available) 53.8002 Tj +90 615.99 Td +(BZ_OUTBUFF_FULL) 89.667 Tj +98.488 604.035 Td +(if) 11.9556 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(size) 23.9112 Tj +-426 TJm +(of) 11.9556 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(compr) 29.889 Tj +1 TJm +(essed) 29.889 Tj +-426 TJm +(data) 23.9112 Tj +-426 TJm +(exceeds) 41.8446 Tj +-426 TJm +(*destLen) 47.8224 Tj +90 592.08 Td +(BZ_DATA_ERROR) 77.7114 Tj +98.488 580.124 Td +(if) 11.9556 Tj +-426 TJm +(a) 5.9778 Tj +-426 TJm +(data) 23.9112 Tj +-426 TJm +(integrity) 53.8002 Tj +-426 TJm +(erro) 23.9112 Tj +1 TJm +(r) 5.9778 Tj +-426 TJm +(was) 17.9334 Tj +-426 TJm +(detected) 47.8224 Tj +-426 TJm +(in) 11.9556 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(compressed) 59.778 Tj +-426 TJm +(data) 23.9112 Tj +90 568.169 Td +(BZ_DATA_ERROR_MAGIC) 113.578 Tj +98.488 556.214 Td +(if) 11.9556 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(compressed) 59.778 Tj +-426 TJm +(data) 23.9112 Tj +-426 TJm +(d) 5.9778 Tj +1 TJm +(oesn't) 35.8668 Tj +-426 TJm +(begin) 29.889 Tj +-426 TJm +(with) 23.9112 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(right) 29.889 Tj +-426 TJm +(magic) 29.889 Tj +-426 TJm +(bytes) 29.889 Tj +90 544.259 Td +(BZ_UNEXPECTED_EOF) 101.623 Tj +98.488 532.304 Td +(if) 11.9556 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(compressed) 59.778 Tj +-426 TJm +(data) 23.9112 Tj +-426 TJm +(e) 5.9778 Tj +1 TJm +(nds) 17.9334 Tj +-426 TJm +(unexpectedly) 71.7336 Tj +90 520.349 Td +(BZ_OK) 29.889 Tj +98.488 508.393 Td +(otherwise) 53.8002 Tj +[1 0 0 1 72 492.852] cm +0 g +0 G +[1 0 0 1 468 3.586] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -3.586] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -482.889] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 458.099 Td +/F121_0 20.659 Tf +(3.6.) 34.4592 Tj +[1 0 0 1 112.201 458.099] cm +0 g +0 G +[1 0 0 1 -112.201 -458.099] cm +[1 0 0 1 0 0] Tm +0 0 Td +112.201 458.099 Td +/F387_0 20.659 Tf +(zlib) 49.5816 Tj +[1 0 0 1 161.781 458.099] cm +0 g +0 G +[1 0 0 1 -161.781 -458.099] cm +[1 0 0 1 0 0] Tm +0 0 Td +167.524 458.099 Td +/F121_0 20.659 Tf +(compatibility) 127.425 Tj +-278 TJm +(functions) 92.9655 Tj +[1 0 0 1 72 453.823] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -443.86] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 436.181 Td +/F128_0 9.963 Tf +(Y) 7.19329 Tj +110 TJm +(oshioka) 30.9949 Tj +-604 TJm +(Tsuneo) 29.3311 Tj +-604 TJm +(has) 13.2807 Tj +-604 TJm +(contrib) 28.2252 Tj +20 TJm +(uted) 17.1563 Tj +-604 TJm +(some) 21.0319 Tj +-604 TJm +(funct) 20.474 Tj +1 TJm +(ions) 16.6083 Tj +-604 TJm +(to) 7.75121 Tj +-604 TJm +(gi) 7.75121 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-604 TJm +(better) 22.6858 Tj +[1 0 0 1 356.347 436.181] cm +0 g +0 G +[1 0 0 1 -356.347 -436.181] cm +[1 0 0 1 0 0] Tm +0 0 Td +356.347 436.181 Td +/F130_0 9.963 Tf +(zlib) 23.9112 Tj +[1 0 0 1 380.257 436.181] cm +0 g +0 G +[1 0 0 1 -380.257 -436.181] cm +[1 0 0 1 0 0] Tm +0 0 Td +386.275 436.181 Td +/F128_0 9.963 Tf +(compatibility) 53.1426 Tj +65 TJm +(.) 2.49075 Tj +-1372 TJm +(These) 23.7916 Tj +-604 TJm +(functions) 37.0823 Tj +-604 TJm +(are) 12.1648 Tj +[1 0 0 1 72 424.226] cm +0 g +0 G +[1 0 0 1 -72 -424.226] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 424.226 Td +/F130_0 9.963 Tf +(BZ2_bzopen) 59.778 Tj +[1 0 0 1 131.776 424.226] cm +0 g +0 G +[1 0 0 1 -131.776 -424.226] cm +[1 0 0 1 0 0] Tm +0 0 Td +131.776 424.226 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 144.283 424.226] cm +0 g +0 G +[1 0 0 1 -144.283 -424.226] cm +[1 0 0 1 0 0] Tm +0 0 Td +144.283 424.226 Td +/F130_0 9.963 Tf +(BZ2_bzread) 59.778 Tj +[1 0 0 1 204.059 424.226] cm +0 g +0 G +[1 0 0 1 -204.059 -424.226] cm +[1 0 0 1 0 0] Tm +0 0 Td +204.059 424.226 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 216.567 424.226] cm +0 g +0 G +[1 0 0 1 -216.567 -424.226] cm +[1 0 0 1 0 0] Tm +0 0 Td +216.567 424.226 Td +/F130_0 9.963 Tf +(BZ2_bzwrite) 65.7558 Tj +[1 0 0 1 282.32 424.226] cm +0 g +0 G +[1 0 0 1 -282.32 -424.226] cm +[1 0 0 1 0 0] Tm +0 0 Td +282.32 424.226 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 294.827 424.226] cm +0 g +0 G +[1 0 0 1 -294.827 -424.226] cm +[1 0 0 1 0 0] Tm +0 0 Td +294.827 424.226 Td +/F130_0 9.963 Tf +(BZ2_bzflush) 65.7558 Tj +[1 0 0 1 360.581 424.226] cm +0 g +0 G +[1 0 0 1 -360.581 -424.226] cm +[1 0 0 1 0 0] Tm +0 0 Td +360.581 424.226 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 373.088 424.226] cm +0 g +0 G +[1 0 0 1 -373.088 -424.226] cm +[1 0 0 1 0 0] Tm +0 0 Td +373.088 424.226 Td +/F130_0 9.963 Tf +(BZ2_bzclose) 65.7558 Tj +[1 0 0 1 438.842 424.226] cm +0 g +0 G +[1 0 0 1 -438.842 -424.226] cm +[1 0 0 1 0 0] Tm +0 0 Td +438.842 424.226 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 451.349 424.226] cm +0 g +0 G +[1 0 0 1 -451.349 -424.226] cm +[1 0 0 1 0 0] Tm +0 0 Td +451.349 424.226 Td +/F130_0 9.963 Tf +(BZ2_bzerror) 65.7558 Tj +[1 0 0 1 517.102 424.226] cm +0 g +0 G +[1 0 0 1 -517.102 -424.226] cm +[1 0 0 1 0 0] Tm +0 0 Td +525.614 424.226 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 72 412.271] cm +0 g +0 G +[1 0 0 1 -72 -412.271] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 412.271 Td +/F130_0 9.963 Tf +(BZ2_bzlibVersion) 95.6448 Tj +[1 0 0 1 167.641 412.271] cm +0 g +0 G +[1 0 0 1 -167.641 -412.271] cm +[1 0 0 1 0 0] Tm +0 0 Td +167.641 412.271 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +-1419 TJm +(These) 23.7916 Tj +-384 TJm +(functi) 23.2437 Tj +1 TJm +(ons) 13.8386 Tj +-384 TJm +(are) 12.1648 Tj +-383 TJm +(not) 12.7327 Tj +-383 TJm +(\(yet\)) 18.8101 Tj +-383 TJm +(of) 8.29918 Tj +25 TJm +(\002cially) 27.6772 Tj +-383 TJm +(part) 15.4925 Tj +-383 TJm +(of) 8.29918 Tj +-384 TJm +(the) 12.1748 Tj +-383 TJm +(library) 26.5614 Tj +65 TJm +(.) 2.49075 Tj +-1419 TJm +(If) 6.63536 Tj +-383 TJm +(the) 12.1748 Tj +15 TJm +(y) 4.9815 Tj +-383 TJm +(break,) 24.6186 Tj +-417 TJm +(you) 14.9445 Tj +-383 TJm +(get) 12.1748 Tj +-383 TJm +(to) 7.75121 Tj +72 400.316 Td +(k) 4.9815 Tj +10 TJm +(eep) 13.8286 Tj +-250 TJm +(all) 9.963 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(pieces.) 27.3883 Tj +-620 TJm +(Ne) 11.6169 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(erth) 15.4925 Tj +1 TJm +(eless,) 21.8588 Tj +-250 TJm +(I) 3.31768 Tj +-250 TJm +(think) 20.4839 Tj +-250 TJm +(the) 12.1748 Tj +15 TJm +(y) 4.9815 Tj +-250 TJm +(w) 7.19329 Tj +10 TJm +(ork) 13.2807 Tj +-250 TJm +(ok.) 12.4538 Tj +[1 0 0 1 72 398.159] cm +0 g +0 G +[1 0 0 1 0 -48.817] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 47.821 re +f +Q +0 g +0 G +[1 0 0 1 0 3.586] cm +0 g +0 G +[1 0 0 1 0 44.235] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -388.794] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 388.794 Td +/F130_0 9.963 Tf +(typedef) 41.8446 Tj +-426 TJm +(void) 23.9112 Tj +-426 TJm +(BZFILE;) 41.8446 Tj +90 364.884 Td +(const) 29.889 Tj +-426 TJm +(char) 23.9112 Tj +-426 TJm +(*) 5.9778 Tj +-426 TJm +(BZ2_bzlibVer) 71.7336 Tj +1 TJm +(sion) 23.9112 Tj +-426 TJm +(\() 5.9778 Tj +-426 TJm +(void) 23.9112 Tj +-426 TJm +(\);) 11.9556 Tj +[1 0 0 1 72 349.342] cm +0 g +0 G +[1 0 0 1 468 3.586] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.549] cm +0 g +0 G +[1 0 0 1 -72 -339.379] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 327.424 Td +/F128_0 9.963 Tf +(Returns) 30.9949 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(string) 22.6957 Tj +-250 TJm +(indicating) 39.852 Tj +-250 TJm +(t) 2.76971 Tj +1 TJm +(he) 9.40507 Tj +-250 TJm +(library) 26.5614 Tj +-250 TJm +(v) 4.9815 Tj +15 TJm +(ersion.) 26.8403 Tj +[1 0 0 1 72 325.267] cm +0 g +0 G +[1 0 0 1 0 -36.862] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 35.866 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 32.279] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -315.902] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 315.902 Td +/F130_0 9.963 Tf +(BZFILE) 35.8668 Tj +-426 TJm +(*) 5.9778 Tj +-426 TJm +(BZ2_bzopen) 59.778 Tj +-852 TJm +(\() 5.9778 Tj +-426 TJm +(c) 5.9778 Tj +1 TJm +(onst) 23.9112 Tj +-426 TJm +(char) 23.9112 Tj +-426 TJm +(*path,) 35.8668 Tj +-426 TJm +(const) 29.889 Tj +-426 TJm +(char) 23.9112 Tj +-426 TJm +(*mode) 29.889 Tj +-426 TJm +(\);) 11.9556 Tj +90 303.947 Td +(BZFILE) 35.8668 Tj +-426 TJm +(*) 5.9778 Tj +-426 TJm +(BZ2_bzdopen) 65.7558 Tj +-426 TJm +(\() 5.9778 Tj +-426 TJm +(i) 5.9778 Tj +1 TJm +(nt) 11.9556 Tj +-3408 TJm +(fd,) 17.9334 Tj +-1704 TJm +(const) 29.889 Tj +-426 TJm +(char) 23.9112 Tj +-426 TJm +(*mode) 29.889 Tj +-426 TJm +(\);) 11.9556 Tj +[1 0 0 1 72 288.405] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.549] cm +0 g +0 G +[1 0 0 1 -72 -278.443] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 266.488 Td +/F128_0 9.963 Tf +(Opens) 25.4555 Tj +-243 TJm +(a) 4.42357 Tj +[1 0 0 1 106.713 266.488] cm +0 g +0 G +[1 0 0 1 -106.713 -266.488] cm +[1 0 0 1 0 0] Tm +0 0 Td +106.713 266.488 Td +/F130_0 9.963 Tf +(.bz2) 23.9112 Tj +[1 0 0 1 130.624 266.488] cm +0 g +0 G +[1 0 0 1 -130.624 -266.488] cm +[1 0 0 1 0 0] Tm +0 0 Td +133.041 266.488 Td +/F128_0 9.963 Tf +(\002le) 12.7327 Tj +-243 TJm +(for) 11.6169 Tj +-242 TJm +(reading) 29.879 Tj +-243 TJm +(or) 8.29918 Tj +-242 TJm +(writing,) 31.2739 Tj +-244 TJm +(using) 21.5898 Tj +-243 TJm +(either) 22.6858 Tj +-243 TJm +(its) 9.41504 Tj +-242 TJm +(name) 21.5799 Tj +-243 TJm +(or) 8.29918 Tj +-242 TJm +(a) 4.42357 Tj +-243 TJm +(pre-e) 20.464 Tj +15 TJm +(xisting) 27.1292 Tj +-243 TJm +(\002le) 12.7327 Tj +-242 TJm +(descriptor) 39.842 Tj +55 TJm +(.) 2.49075 Tj +-615 TJm +(Analogous) 43.1697 Tj +-243 TJm +(to) 7.75121 Tj +[1 0 0 1 510.112 266.488] cm +0 g +0 G +[1 0 0 1 -510.112 -266.488] cm +[1 0 0 1 0 0] Tm +0 0 Td +510.112 266.488 Td +/F130_0 9.963 Tf +(fopen) 29.889 Tj +[1 0 0 1 540 266.488] cm +0 g +0 G +[1 0 0 1 -540 -266.488] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 254.532 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 88.877 254.532] cm +0 g +0 G +[1 0 0 1 -88.877 -254.532] cm +[1 0 0 1 0 0] Tm +0 0 Td +88.877 254.532 Td +/F130_0 9.963 Tf +(fdopen) 35.8668 Tj +[1 0 0 1 124.742 254.532] cm +0 g +0 G +[1 0 0 1 -124.742 -254.532] cm +[1 0 0 1 0 0] Tm +0 0 Td +124.742 254.532 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 72 252.968] cm +0 g +0 G +[1 0 0 1 0 -36.861] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 35.866 re +f +Q +0 g +0 G +[1 0 0 1 0 3.586] cm +0 g +0 G +[1 0 0 1 0 32.279] cm +0 g +0 G +[1 0 0 1 18 -8.368] cm +0 g +0 G +[1 0 0 1 -90 -243.604] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 243.604 Td +/F130_0 9.963 Tf +(int) 17.9334 Tj +-426 TJm +(BZ2_bzread) 59.778 Tj +-852 TJm +(\() 5.9778 Tj +-426 TJm +(BZFILE) 35.8668 Tj +1 TJm +(*) 5.9778 Tj +-426 TJm +(b,) 11.9556 Tj +-426 TJm +(void*) 29.889 Tj +-426 TJm +(buf,) 23.9112 Tj +-426 TJm +(int) 17.9334 Tj +-426 TJm +(len) 17.9334 Tj +-426 TJm +(\);) 11.9556 Tj +90 231.648 Td +(int) 17.9334 Tj +-426 TJm +(BZ2_bzwrite) 65.7558 Tj +-426 TJm +(\() 5.9778 Tj +-426 TJm +(BZFILE*) 41.8446 Tj +-425 TJm +(b,) 11.9556 Tj +-426 TJm +(void*) 29.889 Tj +-426 TJm +(buf,) 23.9112 Tj +-426 TJm +(int) 17.9334 Tj +-426 TJm +(len) 17.9334 Tj +-426 TJm +(\);) 11.9556 Tj +[1 0 0 1 72 216.107] cm +0 g +0 G +[1 0 0 1 468 3.586] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.549] cm +0 g +0 G +[1 0 0 1 -72 -206.144] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 194.189 Td +/F128_0 9.963 Tf +(Reads/writes) 51.4689 Tj +-250 TJm +(data) 16.5984 Tj +-250 TJm +(from/to) 29.889 Tj +-249 TJm +(a) 4.42357 Tj +-250 TJm +(pre) 12.7228 Tj +25 TJm +(viously) 29.341 Tj +-250 TJm +(opened) 28.7731 Tj +[1 0 0 1 259.903 194.189] cm +0 g +0 G +[1 0 0 1 -259.903 -194.189] cm +[1 0 0 1 0 0] Tm +0 0 Td +259.903 194.189 Td +/F130_0 9.963 Tf +(BZFILE) 35.8668 Tj +[1 0 0 1 295.769 194.189] cm +0 g +0 G +[1 0 0 1 -295.769 -194.189] cm +[1 0 0 1 0 0] Tm +0 0 Td +295.769 194.189 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +-500 TJm +(Analogous) 43.1697 Tj +-250 TJm +(to) 7.75121 Tj +[1 0 0 1 359.141 194.189] cm +0 g +0 G +[1 0 0 1 -359.141 -194.189] cm +[1 0 0 1 0 0] Tm +0 0 Td +359.141 194.189 Td +/F130_0 9.963 Tf +(fread) 29.889 Tj +[1 0 0 1 389.029 194.189] cm +0 g +0 G +[1 0 0 1 -389.029 -194.189] cm +[1 0 0 1 0 0] Tm +0 0 Td +391.519 194.189 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 408.396 194.189] cm +0 g +0 G +[1 0 0 1 -408.396 -194.189] cm +[1 0 0 1 0 0] Tm +0 0 Td +408.396 194.189 Td +/F130_0 9.963 Tf +(fwrite) 35.8668 Tj +[1 0 0 1 444.261 194.189] cm +0 g +0 G +[1 0 0 1 -444.261 -194.189] cm +[1 0 0 1 0 0] Tm +0 0 Td +444.261 194.189 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 72 192.032] cm +0 g +0 G +[1 0 0 1 0 -36.862] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 35.866 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 32.279] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -182.667] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 182.667 Td +/F130_0 9.963 Tf +(int) 17.9334 Tj +-852 TJm +(BZ2_bzflush) 65.7558 Tj +-426 TJm +(\() 5.9778 Tj +-426 TJm +(BZFIL) 29.889 Tj +1 TJm +(E*) 11.9556 Tj +-426 TJm +(b) 5.9778 Tj +-426 TJm +(\);) 11.9556 Tj +90 170.712 Td +(void) 23.9112 Tj +-426 TJm +(BZ2_bzclose) 65.7558 Tj +-426 TJm +(\() 5.9778 Tj +-426 TJm +(BZFILE) 35.8668 Tj +1 TJm +(*) 5.9778 Tj +-426 TJm +(b) 5.9778 Tj +-426 TJm +(\);) 11.9556 Tj +[1 0 0 1 72 155.17] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.549] cm +0 g +0 G +[1 0 0 1 -72 -145.208] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 133.252 Td +/F128_0 9.963 Tf +(Flushes/closes) 57.5662 Tj +-250 TJm +(a) 4.42357 Tj +[1 0 0 1 138.968 133.252] cm +0 g +0 G +[1 0 0 1 -138.968 -133.252] cm +[1 0 0 1 0 0] Tm +0 0 Td +138.968 133.252 Td +/F130_0 9.963 Tf +(BZFILE) 35.8668 Tj +[1 0 0 1 174.833 133.252] cm +0 g +0 G +[1 0 0 1 -174.833 -133.252] cm +[1 0 0 1 0 0] Tm +0 0 Td +174.833 133.252 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 179.815 133.252] cm +0 g +0 G +[1 0 0 1 -179.815 -133.252] cm +[1 0 0 1 0 0] Tm +0 0 Td +179.815 133.252 Td +/F130_0 9.963 Tf +(BZ2_bzflush) 65.7558 Tj +[1 0 0 1 245.568 133.252] cm +0 g +0 G +[1 0 0 1 -245.568 -133.252] cm +[1 0 0 1 0 0] Tm +0 0 Td +248.059 133.252 Td +/F128_0 9.963 Tf +(doesn') 26.5614 Tj +18 TJm +(t) 2.76971 Tj +-250 TJm +(actually) 31.5429 Tj +-250 TJm +(do) 9.963 Tj +-250 TJm +(an) 9.40507 Tj +15 TJm +(ything.) 27.9562 Tj +-619 TJm +(Analogous) 43.1697 Tj +-250 TJm +(to) 7.75121 Tj +[1 0 0 1 425.472 133.252] cm +0 g +0 G +[1 0 0 1 -425.472 -133.252] cm +[1 0 0 1 0 0] Tm +0 0 Td +425.472 133.252 Td +/F130_0 9.963 Tf +(fflush) 35.8668 Tj +[1 0 0 1 461.338 133.252] cm +0 g +0 G +[1 0 0 1 -461.338 -133.252] cm +[1 0 0 1 0 0] Tm +0 0 Td +463.828 133.252 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 480.705 133.252] cm +0 g +0 G +[1 0 0 1 -480.705 -133.252] cm +[1 0 0 1 0 0] Tm +0 0 Td +480.705 133.252 Td +/F130_0 9.963 Tf +(fclose) 35.8668 Tj +[1 0 0 1 516.57 133.252] cm +0 g +0 G +[1 0 0 1 -516.57 -133.252] cm +[1 0 0 1 0 0] Tm +0 0 Td +516.57 133.252 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 72 131.096] cm +0 g +0 G +[1 0 0 1 0 -24.907] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 23.91 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 20.323] cm +0 g +0 G +[1 0 0 1 18 -8.368] cm +0 g +0 G +[1 0 0 1 -90 -121.731] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 121.731 Td +/F130_0 9.963 Tf +(const) 29.889 Tj +-426 TJm +(char) 23.9112 Tj +-426 TJm +(*) 5.9778 Tj +-426 TJm +(BZ2_bzerror) 65.7558 Tj +-425 TJm +(\() 5.9778 Tj +-426 TJm +(BZFILE) 35.8668 Tj +-426 TJm +(*b,) 17.9334 Tj +-426 TJm +(int) 17.9334 Tj +-426 TJm +(*errnum) 41.8446 Tj +-426 TJm +(\)) 5.9778 Tj +[1 0 0 1 72 106.189] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.55] cm +0 g +0 G +[1 0 0 1 -72 -96.226] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 84.271 Td +/F128_0 9.963 Tf +(Returns) 30.9949 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(string) 22.6957 Tj +-250 TJm +(describing) 41.5059 Tj +-250 TJm +(t) 2.76971 Tj +1 TJm +(he) 9.40507 Tj +-250 TJm +(more) 20.474 Tj +-250 TJm +(recent) 24.3396 Tj +-250 TJm +(error) 19.3581 Tj +-250 TJm +(status) 22.6957 Tj +-250 TJm +(of) 8.29918 Tj +[1 0 0 1 303.858 84.271] cm +0 g +0 G +[1 0 0 1 -303.858 -84.271] cm +[1 0 0 1 0 0] Tm +0 0 Td +303.858 84.271 Td +/F130_0 9.963 Tf +(b) 5.9778 Tj +[1 0 0 1 309.835 84.271] cm +0 g +0 G +[1 0 0 1 -309.835 -84.271] cm +[1 0 0 1 0 0] Tm +0 0 Td +309.835 84.271 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-250 TJm +(and) 14.3866 Tj +-250 TJm +(also) 16.0504 Tj +-250 TJm +(sets) 14.9445 Tj +[1 0 0 1 367.668 84.271] cm +0 g +0 G +[1 0 0 1 -367.668 -84.271] cm +[1 0 0 1 0 0] Tm +0 0 Td +367.668 84.271 Td +/F130_0 9.963 Tf +(*errnum) 41.8446 Tj +[1 0 0 1 409.511 84.271] cm +0 g +0 G +[1 0 0 1 -409.511 -84.271] cm +[1 0 0 1 0 0] Tm +0 0 Td +412.002 84.271 Td +/F128_0 9.963 Tf +(to) 7.75121 Tj +-250 TJm +(its) 9.41504 Tj +-250 TJm +(numerical) 39.842 Tj +-250 TJm +(v) 4.9815 Tj +25 TJm +(alue.) 19.0891 Tj +[1 0 0 1 72 82.114] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +0 g +0 G +[1 0 0 1 0 -21.3] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 4.384 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 0 6.854] cm +0 g +0 G +0 g +0 G +[1 0 0 1 40.573 -6.755] cm +0 g +0 G +[1 0 0 1 -495.734 -50.951] cm +[1 0 0 1 0 0] Tm +0 0 Td +536.307 50.951 Td +/F128_0 9.963 Tf +(28) 9.963 Tj +[1 0 0 1 455.161 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.599 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -15.037 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 32 32 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 -8.911] cm +0 g +0 G +[1 0 0 1 0 8.911] cm +0 g +0 G +0 g +0 G +[1 0 0 1 84.08 -6.755] cm +0 g +0 G +[1 0 0 1 -350.151 -749.245] cm +[1 0 0 1 0 0] Tm +0 0 Td +434.231 749.245 Td +/F128_0 9.963 Tf +(Programming) 54.7965 Tj +-250 TJm +(with) 17.7142 Tj +-250 TJm +(libbzip2) 32.6587 Tj +[1 0 0 1 266.071 747.089] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -5.037] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -540 -741.554] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 704.93 Td +/F121_0 20.659 Tf +(3.7.) 34.4592 Tj +-449 TJm +(Using) 57.3907 Tj +-449 TJm +(the) 30.9885 Tj +-449 TJm +(librar) 51.6682 Tj +-10 TJm +(y) 11.4864 Tj +-449 TJm +(in) 18.3659 Tj +-450 TJm +(a) 11.4864 Tj +[1 0 0 1 343.721 704.93] cm +0 g +0 G +[1 0 0 1 -343.721 -704.93] cm +[1 0 0 1 0 0] Tm +0 0 Td +343.721 704.93 Td +/F387_0 20.659 Tf +(stdio) 61.977 Tj +[1 0 0 1 405.696 704.93] cm +0 g +0 G +[1 0 0 1 -405.696 -704.93] cm +[1 0 0 1 0 0] Tm +0 0 Td +405.696 704.93 Td +/F121_0 20.659 Tf +(-free) 44.7681 Tj +-449 TJm +(en) 24.1091 Tj +40 TJm +(vir) 25.266 Tj +20 TJm +(on-) 32.1247 Tj +72 680.139 Td +(ment) 49.3544 Tj +[1 0 0 1 72 679.881] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -669.919] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 649.518 Td +/F121_0 17.215 Tf +(3.7.1.) 43.0719 Tj +-278 TJm +(Getting) 60.2525 Tj +-278 TJm +(rid) 22.0008 Tj +-278 TJm +(of) 16.251 Tj +[1 0 0 1 232.721 649.518] cm +0 g +0 G +[1 0 0 1 -232.721 -649.518] cm +[1 0 0 1 0 0] Tm +0 0 Td +232.721 649.518 Td +/F387_0 17.215 Tf +(stdio) 51.645 Tj +[1 0 0 1 284.367 649.518] cm +0 g +0 G +[1 0 0 1 -212.367 -3.83] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -635.725] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 627.6 Td +/F128_0 9.963 Tf +(In) 8.29918 Tj +-319 TJm +(a) 4.42357 Tj +-319 TJm +(deeply) 26.5614 Tj +-319 TJm +(embedded) 40.9479 Tj +-319 TJm +(application,) 46.7663 Tj +-336 TJm +(you) 14.9445 Tj +-319 TJm +(might) 23.2536 Tj +-319 TJm +(w) 7.19329 Tj +10 TJm +(ant) 12.1748 Tj +-319 TJm +(to) 7.75121 Tj +-319 TJm +(use) 13.2807 Tj +-319 TJm +(just) 14.3965 Tj +-319 TJm +(t) 2.76971 Tj +1 TJm +(he) 9.40507 Tj +-319 TJm +(memory-to-memory) 80.7999 Tj +-319 TJm +(functions.) 39.573 Tj +-1034 TJm +(Y) 7.19329 Tj +110 TJm +(ou) 9.963 Tj +-319 TJm +(can) 13.8286 Tj +-319 TJm +(do) 9.963 Tj +-319 TJm +(this) 14.3965 Tj +72 615.645 Td +(con) 14.3866 Tj +40 TJm +(v) 4.9815 Tj +15 TJm +(eniently) 32.1008 Tj +-327 TJm +(by) 9.963 Tj +-327 TJm +(compiling) 40.4099 Tj +-327 TJm +(the) 12.1748 Tj +-327 TJm +(library) 26.5614 Tj +-327 TJm +(with) 17.7142 Tj +-327 TJm +(preprocessor) 50.901 Tj +-327 TJm +(symbol) 29.341 Tj +[1 0 0 1 336.045 615.645] cm +0 g +0 G +[1 0 0 1 -336.045 -615.645] cm +[1 0 0 1 0 0] Tm +0 0 Td +336.045 615.645 Td +/F130_0 9.963 Tf +(BZ_NO_STDIO) 65.7558 Tj +[1 0 0 1 401.799 615.645] cm +0 g +0 G +[1 0 0 1 -401.799 -615.645] cm +[1 0 0 1 0 0] Tm +0 0 Td +405.057 615.645 Td +/F128_0 9.963 Tf +(de\002ned.) 31.8218 Tj +-1082 TJm +(Doing) 24.9075 Tj +-327 TJm +(this) 14.3965 Tj +-327 TJm +(gi) 7.75121 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(es) 8.29918 Tj +-327 TJm +(you) 14.9445 Tj +-327 TJm +(a) 4.42357 Tj +72 603.69 Td +(library) 26.5614 Tj +-250 TJm +(containing) 42.0638 Tj +-250 TJm +(only) 17.7142 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(fo) 8.29918 Tj +1 TJm +(llo) 10.5209 Tj +25 TJm +(wing) 19.926 Tj +-250 TJm +(eight) 19.926 Tj +-250 TJm +(functions:) 39.852 Tj +[1 0 0 1 72 601.533] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -591.571] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 581.772 Td +/F130_0 9.963 Tf +(BZ2_bzCompressInit) 107.6 Tj +[1 0 0 1 179.597 581.772] cm +0 g +0 G +[1 0 0 1 -179.597 -581.772] cm +[1 0 0 1 0 0] Tm +0 0 Td +179.597 581.772 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 199.079 581.772] cm +0 g +0 G +[1 0 0 1 -199.079 -581.772] cm +[1 0 0 1 0 0] Tm +0 0 Td +199.079 581.772 Td +/F130_0 9.963 Tf +(BZ2_bzCompress) 83.6892 Tj +[1 0 0 1 282.765 581.772] cm +0 g +0 G +[1 0 0 1 -282.765 -581.772] cm +[1 0 0 1 0 0] Tm +0 0 Td +282.765 581.772 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 302.247 581.772] cm +0 g +0 G +[1 0 0 1 -302.247 -581.772] cm +[1 0 0 1 0 0] Tm +0 0 Td +302.247 581.772 Td +/F130_0 9.963 Tf +(BZ2_bzCompressEnd) 101.623 Tj +[1 0 0 1 403.866 581.772] cm +0 g +0 G +[1 0 0 1 14.092 0] cm +0 g +0 G +[1 0 0 1 -417.958 -581.772] cm +[1 0 0 1 0 0] Tm +0 0 Td +417.958 581.772 Td +/F130_0 9.963 Tf +(BZ2_bzDecompressInit) 119.556 Tj +[1 0 0 1 537.509 581.772] cm +0 g +0 G +[1 0 0 1 -537.509 -581.772] cm +[1 0 0 1 0 0] Tm +0 0 Td +537.509 581.772 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 72 569.817] cm +0 g +0 G +[1 0 0 1 -72 -569.817] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 569.817 Td +/F130_0 9.963 Tf +(BZ2_bzDecompress) 95.6448 Tj +[1 0 0 1 167.641 569.817] cm +0 g +0 G +[1 0 0 1 -167.641 -569.817] cm +[1 0 0 1 0 0] Tm +0 0 Td +167.641 569.817 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 172.144 569.817] cm +0 g +0 G +[1 0 0 1 -172.144 -569.817] cm +[1 0 0 1 0 0] Tm +0 0 Td +172.144 569.817 Td +/F130_0 9.963 Tf +(BZ2_bzDecompressEnd) 113.578 Tj +[1 0 0 1 285.719 569.817] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 -287.612 -569.817] cm +[1 0 0 1 0 0] Tm +0 0 Td +287.612 569.817 Td +/F130_0 9.963 Tf +(BZ2_bzBuffToBuffCompres) 137.489 Tj +1 TJm +(s) 5.9778 Tj +[1 0 0 1 431.074 569.817] cm +0 g +0 G +[1 0 0 1 -431.074 -569.817] cm +[1 0 0 1 0 0] Tm +0 0 Td +431.074 569.817 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 435.577 569.817] cm +0 g +0 G +[1 0 0 1 -435.577 -569.817] cm +[1 0 0 1 0 0] Tm +0 0 Td +435.577 569.817 Td +/F130_0 9.963 Tf +(BZ2_bzBuffToBuffDecompre) 143.467 Tj +1 TJm +(ss) 11.9556 Tj +[1 0 0 1 590.994 569.817] cm +0 g +0 G +[1 0 0 1 -518.994 -1.564] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -558.29] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 547.899 Td +/F128_0 9.963 Tf +(When) 23.7916 Tj +-250 TJm +(compiled) 37.0823 Tj +-250 TJm +(lik) 10.5209 Tj +10 TJm +(e) 4.42357 Tj +-250 TJm +(this,) 16.8873 Tj +-250 TJm +(all) 9.963 Tj +-249 TJm +(functions) 37.0823 Tj +-250 TJm +(will) 15.5024 Tj +-250 TJm +(ignore) 25.4555 Tj +[1 0 0 1 272.526 547.899] cm +0 g +0 G +[1 0 0 1 -272.526 -547.899] cm +[1 0 0 1 0 0] Tm +0 0 Td +272.526 547.899 Td +/F130_0 9.963 Tf +(verbosity) 53.8002 Tj +[1 0 0 1 326.324 547.899] cm +0 g +0 G +[1 0 0 1 -326.324 -547.899] cm +[1 0 0 1 0 0] Tm +0 0 Td +328.815 547.899 Td +/F128_0 9.963 Tf +(settings.) 32.9377 Tj +[1 0 0 1 72 545.742] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -535.78] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 517.278 Td +/F121_0 17.215 Tf +(3.7.2.) 43.0719 Tj +-278 TJm +(Critical) 58.3589 Tj +-278 TJm +(err) 22.9648 Tj +20 TJm +(or) 17.215 Tj +-278 TJm +(handling) 71.7349 Tj +[1 0 0 1 72 513.448] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -503.485] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 495.36 Td +/F130_0 9.963 Tf +(libbzip2) 47.8224 Tj +[1 0 0 1 119.821 495.36] cm +0 g +0 G +[1 0 0 1 -119.821 -495.36] cm +[1 0 0 1 0 0] Tm +0 0 Td +124.529 495.36 Td +/F128_0 9.963 Tf +(contains) 33.2067 Tj +-472 TJm +(a) 4.42357 Tj +-473 TJm +(number) 30.437 Tj +-472 TJm +(of) 8.29918 Tj +-473 TJm +(internal) 30.437 Tj +-472 TJm +(assertion) 35.4185 Tj +-473 TJm +(checks) 27.1093 Tj +-472 TJm +(which) 24.3496 Tj +-473 TJm +(sho) 13.8386 Tj +1 TJm +(uld,) 15.2235 Tj +-529 TJm +(needles) 29.879 Tj +1 TJm +(s) 3.87561 Tj +-473 TJm +(to) 7.75121 Tj +-473 TJm +(sa) 8.29918 Tj +1 TJm +(y) 4.9815 Tj +65 TJm +(,) 2.49075 Tj +-529 TJm +(ne) 9.40507 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(er) 7.74125 Tj +-472 TJm +(be) 9.40507 Tj +-473 TJm +(acti) 14.3866 Tj +25 TJm +(v) 4.9815 Tj +25 TJm +(ated.) 19.0891 Tj +72 483.405 Td +(Ne) 11.6169 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(ertheless,) 37.3513 Tj +-532 TJm +(if) 6.08739 Tj +-476 TJm +(an) 9.40507 Tj +-476 TJm +(assertion) 35.4185 Tj +-476 TJm +(should) 26.5713 Tj +-476 TJm +(f) 3.31768 Tj +10 TJm +(ail,) 12.4538 Tj +-533 TJm +(beha) 18.8101 Tj +21 TJm +(viour) 21.0319 Tj +-476 TJm +(depends) 32.6488 Tj +-476 TJm +(on) 9.963 Tj +-476 TJm +(whether) 32.0908 Tj +-476 TJm +(or) 8.29918 Tj +-476 TJm +(not) 12.7327 Tj +-476 TJm +(the) 12.1748 Tj +-476 TJm +(library) 26.5614 Tj +-476 TJm +(w) 7.19329 Tj +10 TJm +(as) 8.29918 Tj +-476 TJm +(compiled) 37.0823 Tj +-476 TJm +(with) 17.7142 Tj +[1 0 0 1 72 471.45] cm +0 g +0 G +[1 0 0 1 -72 -471.45] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 471.45 Td +/F130_0 9.963 Tf +(BZ_NO_STDIO) 65.7558 Tj +[1 0 0 1 137.753 471.45] cm +0 g +0 G +[1 0 0 1 -137.753 -471.45] cm +[1 0 0 1 0 0] Tm +0 0 Td +140.244 471.45 Td +/F128_0 9.963 Tf +(set.) 13.5596 Tj +[1 0 0 1 72 470.284] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -460.322] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 449.532 Td +/F128_0 9.963 Tf +(F) 5.53943 Tj +15 TJm +(or) 8.29918 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(normal) 28.2252 Tj +-250 TJm +(compile,) 34.5915 Tj +-250 TJm +(an) 9.40507 Tj +-250 TJm +(asse) 16.5984 Tj +1 TJm +(rtion) 18.8201 Tj +-250 TJm +(f) 3.31768 Tj +10 TJm +(ailure) 22.6858 Tj +-250 TJm +(yields) 23.8016 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(message:) 36.5244 Tj +[1 0 0 1 72 447.375] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -437.413] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 427.614 Td +/F128_0 9.963 Tf +(bzip2/libbzip2:) 60.3359 Tj +-310 TJm +(internal) 30.437 Tj +-250 TJm +(err) 11.0589 Tj +1 TJm +(or) 8.29918 Tj +-250 TJm +(number) 30.437 Tj +-250 TJm +(N.) 9.68404 Tj +[1 0 0 1 72 425.458] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -415.495] cm +[1 0 0 1 0 0] Tm +0 0 Td +108 405.697 Td +/F128_0 9.963 Tf +(This) 17.7142 Tj +-475 TJm +(is) 6.64532 Tj +-476 TJm +(a) 4.42357 Tj +-476 TJm +(b) 4.9815 Tj +20 TJm +(u) 4.9815 Tj +1 TJm +(g) 4.9815 Tj +-476 TJm +(in) 7.75121 Tj +-476 TJm +(bzi) 12.1748 Tj +1 TJm +(p2/libbzip2,) 47.8822 Tj +-532 TJm +(1.0.3) 19.926 Tj +-476 TJm +(of) 8.29918 Tj +-475 TJm +(15) 9.963 Tj +-476 TJm +(February) 35.9664 Tj +-475 TJm +(2005.) 22.4168 Tj +-987 TJm +(Please) 25.4555 Tj +-475 TJm +(report) 23.7916 Tj +-476 TJm +(it) 5.53943 Tj +-475 TJm +(to) 7.75121 Tj +-476 TJm +(me) 12.1748 Tj +-475 TJm +(at:) 9.963 Tj +-761 TJm +(jse-) 14.3866 Tj +108 393.741 Td +(w) 7.19329 Tj +10 TJm +(ard@bzip.or) 49.8449 Tj +18 TJm +(g.) 7.47225 Tj +-1091 TJm +(If) 6.63536 Tj +-329 TJm +(this) 14.3965 Tj +-328 TJm +(happened) 38.1782 Tj +-329 TJm +(wh) 12.1748 Tj +1 TJm +(en) 9.40507 Tj +-329 TJm +(you) 14.9445 Tj +-329 TJm +(w) 7.19329 Tj +1 TJm +(ere) 12.1648 Tj +-329 TJm +(using) 21.5898 Tj +-328 TJm +(some) 21.0319 Tj +-329 TJm +(program) 33.7546 Tj +-328 TJm +(which) 24.3496 Tj +-329 TJm +(uses) 17.1563 Tj +-328 TJm +(libbzip2) 32.6587 Tj +-329 TJm +(as) 8.29918 Tj +-328 TJm +(a) 4.42357 Tj +108 381.786 Td +(component,) 46.7663 Tj +-323 TJm +(you) 14.9445 Tj +-309 TJm +(should) 26.5713 Tj +-308 TJm +(also) 16.0504 Tj +-309 TJm +(report) 23.7916 Tj +-309 TJm +(this) 14.3965 Tj +-308 TJm +(b) 4.9815 Tj +20 TJm +(ug) 9.963 Tj +-309 TJm +(to) 7.75121 Tj +-309 TJm +(the) 12.1748 Tj +-308 TJm +(author\(s\)) 35.9664 Tj +-309 TJm +(of) 8.29918 Tj +-309 TJm +(tha) 12.1748 Tj +1 TJm +(t) 2.76971 Tj +-309 TJm +(program.) 36.2454 Tj +-972 TJm +(Please) 25.4555 Tj +-309 TJm +(mak) 17.1563 Tj +10 TJm +(e) 4.42357 Tj +-309 TJm +(an) 9.40507 Tj +-308 TJm +(ef-) 11.0589 Tj +108 369.831 Td +(fort) 14.3866 Tj +-315 TJm +(to) 7.75121 Tj +-315 TJm +(report) 23.7916 Tj +-316 TJm +(this) 14.3965 Tj +-315 TJm +(b) 4.9815 Tj +20 TJm +(ug;) 12.7327 Tj +-348 TJm +(timely) 25.4654 Tj +-315 TJm +(and) 14.3866 Tj +-315 TJm +(accurate) 33.1868 Tj +-315 TJm +(b) 4.9815 Tj +20 TJm +(ug) 9.963 Tj +-315 TJm +(reports) 27.6673 Tj +-316 TJm +(e) 4.42357 Tj +26 TJm +(v) 4.9815 Tj +15 TJm +(entually) 32.1008 Tj +-316 TJm +(lead) 16.5984 Tj +-315 TJm +(to) 7.75121 Tj +-315 TJm +(higher) 25.4555 Tj +-315 TJm +(quality) 27.6772 Tj +-315 TJm +(softw) 22.1378 Tj +10 TJm +(are.) 14.6556 Tj +108 357.876 Td +(Thanks.) 31.8218 Tj +-620 TJm +(Julian) 23.8016 Tj +-250 TJm +(Se) 9.963 Tj +25 TJm +(w) 7.19329 Tj +10 TJm +(ard,) 15.2135 Tj +-250 TJm +(15) 9.963 Tj +-250 TJm +(Fe) 9.963 Tj +1 TJm +(bruary) 26.0034 Tj +-250 TJm +(2005.) 22.4168 Tj +[1 0 0 1 72 355.719] cm +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -335.794] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 325.995 Td +/F128_0 9.963 Tf +(where) 24.3396 Tj +[1 0 0 1 98.831 325.995] cm +0 g +0 G +[1 0 0 1 -98.831 -325.995] cm +[1 0 0 1 0 0] Tm +0 0 Td +98.831 325.995 Td +/F130_0 9.963 Tf +(N) 5.9778 Tj +[1 0 0 1 104.809 325.995] cm +0 g +0 G +[1 0 0 1 -104.809 -325.995] cm +[1 0 0 1 0 0] Tm +0 0 Td +107.301 325.995 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-250 TJm +(some) 21.0319 Tj +-250 TJm +(error) 19.3581 Tj +-250 TJm +(code) 18.8101 Tj +-251 TJm +(nu) 9.963 Tj +1 TJm +(mber) 20.474 Tj +55 TJm +(.) 2.49075 Tj +-622 TJm +(If) 6.63536 Tj +[1 0 0 1 230.81 325.995] cm +0 g +0 G +[1 0 0 1 -230.81 -325.995] cm +[1 0 0 1 0 0] Tm +0 0 Td +230.81 325.995 Td +/F130_0 9.963 Tf +(N) 5.9778 Tj +-600 TJm +(==) 11.9556 Tj +-600 TJm +(1007) 23.9112 Tj +[1 0 0 1 284.608 325.995] cm +0 g +0 G +[1 0 0 1 -284.608 -325.995] cm +[1 0 0 1 0 0] Tm +0 0 Td +284.608 325.995 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-250 TJm +(it) 5.53943 Tj +-250 TJm +(also) 16.0504 Tj +-250 TJm +(prints) 22.6957 Tj +-251 TJm +(som) 16.6083 Tj +1 TJm +(e) 4.42357 Tj +-251 TJm +(e) 4.42357 Tj +15 TJm +(xtra) 15.4925 Tj +-250 TJm +(te) 7.19329 Tj +15 TJm +(xt) 7.75121 Tj +-250 TJm +(advising) 33.7646 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(reader) 24.8876 Tj +-250 TJm +(that) 14.9445 Tj +-250 TJm +(unreliable) 39.842 Tj +72 314.04 Td +(memory) 33.2067 Tj +-425 TJm +(i) 2.76971 Tj +1 TJm +(s) 3.87561 Tj +-425 TJm +(often) 20.474 Tj +-425 TJm +(associate) 35.9664 Tj +1 TJm +(d) 4.9815 Tj +-425 TJm +(with) 17.7142 Tj +-425 TJm +(internal) 30.437 Tj +-424 TJm +(error) 19.3581 Tj +-425 TJm +(1007.) 22.4168 Tj +-834 TJm +(\(This) 21.0319 Tj +-424 TJm +(is) 6.64532 Tj +-425 TJm +(a) 4.42357 Tj +-424 TJm +(frequently-observ) 70.827 Tj +15 TJm +(ed-phenomenon) 64.1916 Tj +-425 TJm +(w) 7.19329 Tj +1 TJm +(ith) 10.5209 Tj +-425 TJm +(v) 4.9815 Tj +15 TJm +(ersions) 28.2252 Tj +72 302.085 Td +(1.0.0/1.0.1\).) 48.4301 Tj +[1 0 0 1 72 300.302] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -290.339] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 280.167 Td +/F130_0 9.963 Tf +(exit\(3\)) 41.8446 Tj +[1 0 0 1 113.843 280.167] cm +0 g +0 G +[1 0 0 1 -113.843 -280.167] cm +[1 0 0 1 0 0] Tm +0 0 Td +116.334 280.167 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-250 TJm +(then) 17.1563 Tj +-250 TJm +(called.) 26.2824 Tj +[1 0 0 1 72 279.002] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -269.039] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 258.25 Td +/F128_0 9.963 Tf +(F) 5.53943 Tj +15 TJm +(or) 8.29918 Tj +-250 TJm +(a) 4.42357 Tj +[1 0 0 1 95.093 258.25] cm +0 g +0 G +[1 0 0 1 -95.093 -258.25] cm +[1 0 0 1 0 0] Tm +0 0 Td +95.093 258.25 Td +/F130_0 9.963 Tf +(stdio) 29.889 Tj +[1 0 0 1 124.981 258.25] cm +0 g +0 G +[1 0 0 1 -124.981 -258.25] cm +[1 0 0 1 0 0] Tm +0 0 Td +124.981 258.25 Td +/F128_0 9.963 Tf +(-free) 18.8002 Tj +-250 TJm +(library) 26.5614 Tj +65 TJm +(,) 2.49075 Tj +-250 TJm +(assertion) 35.4185 Tj +-250 TJm +(f) 3.31768 Tj +10 TJm +(ailure) 22.6858 Tj +1 TJm +(s) 3.87561 Tj +-250 TJm +(result) 22.1378 Tj +-250 TJm +(in) 7.75121 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(call) 14.3866 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(function) 33.2067 Tj +-250 TJm +(declared) 33.7447 Tj +-250 TJm +(as:) 11.0689 Tj +[1 0 0 1 72 256.093] cm +0 g +0 G +[1 0 0 1 0 -24.907] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 23.91 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 20.323] cm +0 g +0 G +[1 0 0 1 18 -8.368] cm +0 g +0 G +[1 0 0 1 -90 -246.728] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 246.728 Td +/F130_0 9.963 Tf +(extern) 35.8668 Tj +-426 TJm +(void) 23.9112 Tj +-426 TJm +(bz_internal_e) 77.7114 Tj +1 TJm +(rror) 23.9112 Tj +-426 TJm +(\() 5.9778 Tj +-426 TJm +(int) 17.9334 Tj +-426 TJm +(errcode) 41.8446 Tj +-426 TJm +(\);) 11.9556 Tj +[1 0 0 1 72 231.186] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.55] cm +0 g +0 G +[1 0 0 1 -72 -221.223] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 209.268 Td +/F128_0 9.963 Tf +(The) 15.4925 Tj +-250 TJm +(rele) 14.9345 Tj +25 TJm +(v) 4.9815 Tj +25 TJm +(ant) 12.1748 Tj +-250 TJm +(code) 18.8101 Tj +-250 TJm +(is) 6.64532 Tj +-250 TJm +(passed) 26.5614 Tj +-250 TJm +(a) 4.42357 Tj +1 TJm +(s) 3.87561 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(parameter) 39.8321 Tj +55 TJm +(.) 2.49075 Tj +-620 TJm +(Y) 7.19329 Tj +110 TJm +(ou) 9.963 Tj +-250 TJm +(should) 26.5713 Tj +-250 TJm +(supply) 26.5713 Tj +-250 TJm +(such) 18.2622 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(function.) 35.6974 Tj +[1 0 0 1 72 207.111] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -197.149] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 187.35 Td +/F128_0 9.963 Tf +(In) 8.29918 Tj +-294 TJm +(either) 22.6858 Tj +-294 TJm +(case,) 19.6371 Tj +-305 TJm +(once) 18.8101 Tj +-295 TJm +(an) 9.40507 Tj +-294 TJm +(assertion) 35.4185 Tj +-294 TJm +(f) 3.31768 Tj +10 TJm +(ailure) 22.6858 Tj +-294 TJm +(has) 13.2807 Tj +-294 TJm +(occurred,) 37.3413 Tj +-305 TJm +(an) 9.40507 Tj +15 TJm +(y) 4.9815 Tj +[1 0 0 1 306.541 187.35] cm +0 g +0 G +[1 0 0 1 -306.541 -187.35] cm +[1 0 0 1 0 0] Tm +0 0 Td +306.541 187.35 Td +/F130_0 9.963 Tf +(bz_stream) 53.8002 Tj +[1 0 0 1 360.34 187.35] cm +0 g +0 G +[1 0 0 1 -360.34 -187.35] cm +[1 0 0 1 0 0] Tm +0 0 Td +363.271 187.35 Td +/F128_0 9.963 Tf +(records) 29.3211 Tj +-294 TJm +(in) 7.75121 Tj +40 TJm +(v) 4.9815 Tj +20 TJm +(olv) 12.7327 Tj +15 TJm +(ed) 9.40507 Tj +-294 TJm +(can) 13.8286 Tj +-294 TJm +(be) 9.40507 Tj +-294 TJm +(re) 7.74125 Tj +15 TJm +(g) 4.9815 Tj +5 TJm +(arded) 22.1278 Tj +-295 TJm +(as) 8.29918 Tj +-294 TJm +(in) 7.75121 Tj +40 TJm +(v) 4.9815 Tj +25 TJm +(alid.) 17.4353 Tj +72 175.395 Td +(Y) 7.19329 Tj +110 TJm +(ou) 9.963 Tj +-250 TJm +(should) 26.5713 Tj +-250 TJm +(not) 12.7327 Tj +-250 TJm +(attempt) 29.889 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(res) 11.6169 Tj +1 TJm +(ume) 17.1563 Tj +-250 TJm +(normal) 28.2252 Tj +-250 TJm +(operation) 37.6303 Tj +-250 TJm +(with) 17.7142 Tj +-250 TJm +(them.) 22.4168 Tj +[1 0 0 1 72 173.238] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -163.276] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 153.477 Td +/F128_0 9.963 Tf +(Y) 7.19329 Tj +110 TJm +(ou) 9.963 Tj +-299 TJm +(m) 7.75121 Tj +1 TJm +(ay) 9.40507 Tj +65 TJm +(,) 2.49075 Tj +-311 TJm +(of) 8.29918 Tj +-299 TJm +(course,) 28.4942 Tj +-310 TJm +(change) 28.2152 Tj +-299 TJm +(critical) 27.6673 Tj +-298 TJm +(error) 19.3581 Tj +-299 TJm +(ha) 9.40507 Tj +1 TJm +(ndling) 25.4654 Tj +-299 TJm +(to) 7.75121 Tj +-298 TJm +(suit) 14.3965 Tj +-299 TJm +(your) 18.2622 Tj +-298 TJm +(needs.) 25.1765 Tj +-912 TJm +(As) 11.0689 Tj +-298 TJm +(I) 3.31768 Tj +-299 TJm +(said) 16.0504 Tj +-298 TJm +(abo) 14.3866 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(e,) 6.91432 Tj +-311 TJm +(critical) 27.6673 Tj +-298 TJm +(errors) 23.2337 Tj +-299 TJm +(indic) 19.926 Tj +1 TJm +(ate) 11.6169 Tj +-299 TJm +(b) 4.9815 Tj +20 TJm +(ugs) 13.8386 Tj +72 141.522 Td +(in) 7.75121 Tj +-263 TJm +(the) 12.1748 Tj +-263 TJm +(library) 26.5614 Tj +-263 TJm +(and) 14.3866 Tj +-263 TJm +(s) 3.87561 Tj +1 TJm +(hould) 22.6957 Tj +-263 TJm +(not) 12.7327 Tj +-263 TJm +(occur) 22.1278 Tj +55 TJm +(.) 2.49075 Tj +-698 TJm +(All) 12.7327 Tj +-263 TJm +("normal") 36.355 Tj +-263 TJm +(er) 7.74125 Tj +1 TJm +(ror) 11.6169 Tj +-263 TJm +(situations) 38.1981 Tj +-263 TJm +(are) 12.1648 Tj +-263 TJm +(indicated) 36.5244 Tj +-263 TJm +(via) 12.1748 Tj +-263 TJm +(error) 19.3581 Tj +-263 TJm +(retu) 15.4925 Tj +1 TJm +(rn) 8.29918 Tj +-263 TJm +(codes) 22.6858 Tj +-263 TJm +(from) 19.3681 Tj +-263 TJm +(functions,) 39.573 Tj +72 129.567 Td +(and) 14.3866 Tj +-250 TJm +(can) 13.8286 Tj +-250 TJm +(be) 9.40507 Tj +-250 TJm +(reco) 17.1463 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(ered) 17.1463 Tj +-250 TJm +(from.) 21.8588 Tj +[1 0 0 1 72 129.468] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -119.505] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 94.814 Td +/F121_0 20.659 Tf +(3.8.) 34.4592 Tj +-278 TJm +(Making) 71.1703 Tj +-278 TJm +(a) 11.4864 Tj +-278 TJm +(Windo) 63.1132 Tj +15 TJm +(ws) 27.5591 Tj +-278 TJm +(DLL) 40.1611 Tj +[1 0 0 1 72 90.218] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 0 -29.403] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.974] cm +0 g +0 G +0 g +0 G +[1 0 0 1 40.572 -6.755] cm +0 g +0 G +[1 0 0 1 -493.841 -51.071] cm +[1 0 0 1 0 0] Tm +0 0 Td +534.414 51.071 Td +/F128_0 9.963 Tf +(29) 9.963 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 33 33 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 -8.911] cm +0 g +0 G +[1 0 0 1 0 8.911] cm +0 g +0 G +0 g +0 G +[1 0 0 1 84.08 -6.755] cm +0 g +0 G +[1 0 0 1 -350.151 -749.245] cm +[1 0 0 1 0 0] Tm +0 0 Td +434.231 749.245 Td +/F128_0 9.963 Tf +(Programming) 54.7965 Tj +-250 TJm +(with) 17.7142 Tj +-250 TJm +(libbzip2) 32.6587 Tj +[1 0 0 1 266.071 747.089] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -5.037] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -540 -741.554] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 710.037 Td +/F128_0 9.963 Tf +(Ev) 11.0689 Tj +15 TJm +(erything) 33.2067 Tj +-452 TJm +(related) 27.1093 Tj +-452 TJm +(to) 7.75121 Tj +-453 TJm +(W) 9.40507 Tj +40 TJm +(indo) 17.7142 Tj +25 TJm +(ws) 11.0689 Tj +-452 TJm +(has) 13.2807 Tj +-452 TJm +(been) 18.8101 Tj +-453 TJm +(c) 4.42357 Tj +1 TJm +(ontrib) 23.8016 Tj +20 TJm +(uted) 17.1563 Tj +-453 TJm +(by) 9.963 Tj +-452 TJm +(Y) 7.19329 Tj +110 TJm +(oshioka) 30.9949 Tj +-452 TJm +(Tsuneo) 29.3311 Tj +-452 TJm +(\() 3.31768 Tj +[1 0 0 1 390.56 710.037] cm +0 g +0 G +[1 0 0 1 -390.56 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +390.56 710.037 Td +/F130_0 9.963 Tf +(QWF00133@niftyserve.or.jp) 149.445 Tj +[1 0 0 1 540 710.037] cm +0 g +0 G +[1 0 0 1 -540 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 698.082 Td +/F128_0 9.963 Tf +(/) 2.76971 Tj +[1 0 0 1 80.825 698.082] cm +0 g +0 G +[1 0 0 1 -80.825 -698.082] cm +[1 0 0 1 0 0] Tm +0 0 Td +80.825 698.082 Td +/F130_0 9.963 Tf +(tsuneo-y@is.aist-nara.ac.) 149.445 Tj +1 TJm +(jp) 11.9556 Tj +[1 0 0 1 242.22 698.082] cm +0 g +0 G +[1 0 0 1 -242.22 -698.082] cm +[1 0 0 1 0 0] Tm +0 0 Td +242.22 698.082 Td +/F128_0 9.963 Tf +(\),) 5.80843 Tj +-697 TJm +(so) 8.85711 Tj +-608 TJm +(you) 14.9445 Tj +-608 TJm +(should) 26.5713 Tj +-607 TJm +(send) 18.2622 Tj +-608 TJm +(your) 18.2622 Tj +-608 TJm +(queries) 28.7731 Tj +-607 TJm +(to) 7.75121 Tj +-608 TJm +(him) 15.5024 Tj +-608 TJm +(\(b) 8.29918 Tj +20 TJm +(ut) 7.75121 Tj +-608 TJm +(perha) 22.1278 Tj +1 TJm +(ps) 8.85711 Tj +-608 TJm +(Cc:) 13.8386 Tj +-1026 TJm +(me,) 14.6655 Tj +[1 0 0 1 72 686.127] cm +0 g +0 G +[1 0 0 1 -72 -686.127] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 686.127 Td +/F130_0 9.963 Tf +(jseward@bzip.org) 95.6448 Tj +[1 0 0 1 167.641 686.127] cm +0 g +0 G +[1 0 0 1 -167.641 -686.127] cm +[1 0 0 1 0 0] Tm +0 0 Td +167.641 686.127 Td +/F128_0 9.963 Tf +(\).) 5.80843 Tj +[1 0 0 1 72 684.344] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -674.381] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 664.209 Td +/F128_0 9.963 Tf +(My) 13.8386 Tj +-367 TJm +(v) 4.9815 Tj +25 TJm +(ague) 18.8101 Tj +-367 TJm +(understanding) 56.4504 Tj +-367 TJm +(of) 8.29918 Tj +-367 TJm +(what) 19.3681 Tj +-367 TJm +(to) 7.75121 Tj +-367 TJm +(do) 9.963 Tj +-367 TJm +(is:) 9.41504 Tj +-544 TJm +(using) 21.5898 Tj +-367 TJm +(V) 7.19329 Tj +60 TJm +(isual) 18.8201 Tj +-367 TJm +(C++) 17.8836 Tj +-367 TJm +(5.0,) 14.9445 Tj +-397 TJm +(open) 19.3681 Tj +-367 TJm +(the) 12.1748 Tj +-367 TJm +(project) 27.6673 Tj +-367 TJm +(\002le) 12.7327 Tj +[1 0 0 1 432.966 664.209] cm +0 g +0 G +[1 0 0 1 -432.966 -664.209] cm +[1 0 0 1 0 0] Tm +0 0 Td +432.966 664.209 Td +/F130_0 9.963 Tf +(libbz2.dsp) 59.778 Tj +[1 0 0 1 492.742 664.209] cm +0 g +0 G +[1 0 0 1 -492.742 -664.209] cm +[1 0 0 1 0 0] Tm +0 0 Td +492.742 664.209 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-396 TJm +(and) 14.3866 Tj +-367 TJm +(b) 4.9815 Tj +20 TJm +(uild.) 17.9932 Tj +72 652.254 Td +(That') 21.5799 Tj +55 TJm +(s) 3.87561 Tj +-250 TJm +(all.) 12.4538 Tj +[1 0 0 1 72 652.155] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -642.192] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 630.336 Td +/F128_0 9.963 Tf +(If) 6.63536 Tj +-284 TJm +(you) 14.9445 Tj +-284 TJm +(can') 17.1463 Tj +18 TJm +(t) 2.76971 Tj +-284 TJm +(open) 19.3681 Tj +-285 TJm +(the) 12.1748 Tj +-284 TJm +(project) 27.6673 Tj +-284 TJm +(\002le) 12.7327 Tj +-284 TJm +(for) 11.6169 Tj +-284 TJm +(some) 21.0319 Tj +-284 TJm +(reason,) 28.4942 Tj +-293 TJm +(mak) 17.1563 Tj +10 TJm +(e) 4.42357 Tj +-284 TJm +(a) 4.42357 Tj +-284 TJm +(ne) 9.40507 Tj +25 TJm +(w) 7.19329 Tj +-284 TJm +(one,) 16.8773 Tj +-293 TJm +(naming) 29.889 Tj +-284 TJm +(these) 20.474 Tj +-284 TJm +(\002les:) 19.378 Tj +[1 0 0 1 424.505 630.336] cm +0 g +0 G +[1 0 0 1 -424.505 -630.336] cm +[1 0 0 1 0 0] Tm +0 0 Td +424.505 630.336 Td +/F130_0 9.963 Tf +(blocksort.c) 65.7558 Tj +[1 0 0 1 490.259 630.336] cm +0 g +0 G +[1 0 0 1 -490.259 -630.336] cm +[1 0 0 1 0 0] Tm +0 0 Td +490.259 630.336 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 495.666 630.336] cm +0 g +0 G +[1 0 0 1 -495.666 -630.336] cm +[1 0 0 1 0 0] Tm +0 0 Td +495.666 630.336 Td +/F130_0 9.963 Tf +(bzlib.c) 41.8446 Tj +[1 0 0 1 537.509 630.336] cm +0 g +0 G +[1 0 0 1 -537.509 -630.336] cm +[1 0 0 1 0 0] Tm +0 0 Td +537.509 630.336 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 72 618.381] cm +0 g +0 G +[1 0 0 1 -72 -618.381] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 618.381 Td +/F130_0 9.963 Tf +(compress.c) 59.778 Tj +[1 0 0 1 131.776 618.381] cm +0 g +0 G +[1 0 0 1 -131.776 -618.381] cm +[1 0 0 1 0 0] Tm +0 0 Td +131.776 618.381 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 136.436 618.381] cm +0 g +0 G +[1 0 0 1 -136.436 -618.381] cm +[1 0 0 1 0 0] Tm +0 0 Td +136.436 618.381 Td +/F130_0 9.963 Tf +(crctable.c) 59.778 Tj +[1 0 0 1 196.211 618.381] cm +0 g +0 G +[1 0 0 1 -196.211 -618.381] cm +[1 0 0 1 0 0] Tm +0 0 Td +196.211 618.381 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 200.871 618.381] cm +0 g +0 G +[1 0 0 1 -200.871 -618.381] cm +[1 0 0 1 0 0] Tm +0 0 Td +200.871 618.381 Td +/F130_0 9.963 Tf +(decompress.c) 71.7336 Tj +[1 0 0 1 272.602 618.381] cm +0 g +0 G +[1 0 0 1 -272.602 -618.381] cm +[1 0 0 1 0 0] Tm +0 0 Td +272.602 618.381 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 277.262 618.381] cm +0 g +0 G +[1 0 0 1 -277.262 -618.381] cm +[1 0 0 1 0 0] Tm +0 0 Td +277.262 618.381 Td +/F130_0 9.963 Tf +(huffman.c) 53.8002 Tj +[1 0 0 1 331.06 618.381] cm +0 g +0 G +[1 0 0 1 -331.06 -618.381] cm +[1 0 0 1 0 0] Tm +0 0 Td +331.06 618.381 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 335.72 618.381] cm +0 g +0 G +[1 0 0 1 -335.72 -618.381] cm +[1 0 0 1 0 0] Tm +0 0 Td +335.72 618.381 Td +/F130_0 9.963 Tf +(randtable.c) 65.7558 Tj +[1 0 0 1 401.473 618.381] cm +0 g +0 G +[1 0 0 1 -401.473 -618.381] cm +[1 0 0 1 0 0] Tm +0 0 Td +403.562 618.381 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 420.037 618.381] cm +0 g +0 G +[1 0 0 1 -420.037 -618.381] cm +[1 0 0 1 0 0] Tm +0 0 Td +420.037 618.381 Td +/F130_0 9.963 Tf +(libbz2.def) 59.778 Tj +[1 0 0 1 479.812 618.381] cm +0 g +0 G +[1 0 0 1 -479.812 -618.381] cm +[1 0 0 1 0 0] Tm +0 0 Td +479.812 618.381 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +-593 TJm +(Y) 7.19329 Tj +110 TJm +(ou) 9.963 Tj +-210 TJm +(will) 15.5024 Tj +-209 TJm +(also) 16.0504 Tj +72 606.426 Td +(need) 18.8101 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(name) 21.5799 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(header) 26.5514 Tj +-250 TJm +(\002les) 16.6083 Tj +[1 0 0 1 190.415 606.426] cm +0 g +0 G +[1 0 0 1 -190.415 -606.426] cm +[1 0 0 1 0 0] Tm +0 0 Td +190.415 606.426 Td +/F130_0 9.963 Tf +(bzlib.h) 41.8446 Tj +[1 0 0 1 232.258 606.426] cm +0 g +0 G +[1 0 0 1 -232.258 -606.426] cm +[1 0 0 1 0 0] Tm +0 0 Td +234.749 606.426 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 251.625 606.426] cm +0 g +0 G +[1 0 0 1 -251.625 -606.426] cm +[1 0 0 1 0 0] Tm +0 0 Td +251.625 606.426 Td +/F130_0 9.963 Tf +(bzlib_private.h) 89.667 Tj +[1 0 0 1 341.289 606.426] cm +0 g +0 G +[1 0 0 1 -341.289 -606.426] cm +[1 0 0 1 0 0] Tm +0 0 Td +341.289 606.426 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 72 604.862] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -594.899] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 584.508 Td +/F128_0 9.963 Tf +(If) 6.63536 Tj +-250 TJm +(you) 14.9445 Tj +-250 TJm +(don') 18.2622 Tj +18 TJm +(t) 2.76971 Tj +-250 TJm +(use) 13.2807 Tj +-250 TJm +(VC++,) 27.5676 Tj +-250 TJm +(you) 14.9445 Tj +-250 TJm +(ma) 12.1748 Tj +1 TJm +(y) 4.9815 Tj +-250 TJm +(need) 18.8101 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(de\002ne) 24.3496 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(proprocessor) 51.4589 Tj +-250 TJm +(symbol) 29.341 Tj +[1 0 0 1 363.634 584.508] cm +0 g +0 G +[1 0 0 1 -363.634 -584.508] cm +[1 0 0 1 0 0] Tm +0 0 Td +363.634 584.508 Td +/F130_0 9.963 Tf +(_WIN32) 35.8668 Tj +[1 0 0 1 399.5 584.508] cm +0 g +0 G +[1 0 0 1 -399.5 -584.508] cm +[1 0 0 1 0 0] Tm +0 0 Td +399.5 584.508 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 72 582.351] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -572.389] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 562.59 Td +/F128_0 9.963 Tf +(Finally) 28.2351 Tj +65 TJm +(,) 2.49075 Tj +[1 0 0 1 104.568 562.59] cm +0 g +0 G +[1 0 0 1 -104.568 -562.59] cm +[1 0 0 1 0 0] Tm +0 0 Td +104.568 562.59 Td +/F130_0 9.963 Tf +(dlltest.c) 53.8002 Tj +[1 0 0 1 158.366 562.59] cm +0 g +0 G +[1 0 0 1 -158.366 -562.59] cm +[1 0 0 1 0 0] Tm +0 0 Td +160.856 562.59 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(sample) 28.2252 Tj +-250 TJm +(program) 33.7546 Tj +-250 TJm +(using) 21.5898 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(D) 7.19329 Tj +1 TJm +(LL.) 14.6655 Tj +-500 TJm +(It) 6.08739 Tj +-250 TJm +(has) 13.2807 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(project) 27.6673 Tj +-250 TJm +(\002le,) 15.2235 Tj +[1 0 0 1 388.58 562.59] cm +0 g +0 G +[1 0 0 1 -388.58 -562.59] cm +[1 0 0 1 0 0] Tm +0 0 Td +388.58 562.59 Td +/F130_0 9.963 Tf +(dlltest.dsp) 65.7558 Tj +[1 0 0 1 454.333 562.59] cm +0 g +0 G +[1 0 0 1 -454.333 -562.59] cm +[1 0 0 1 0 0] Tm +0 0 Td +454.333 562.59 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 72 560.433] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -550.471] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 540.672 Td +/F128_0 9.963 Tf +(If) 6.63536 Tj +-250 TJm +(you) 14.9445 Tj +-250 TJm +(just) 14.3965 Tj +-250 TJm +(w) 7.19329 Tj +10 TJm +(ant) 12.1748 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(mak) 17.1563 Tj +10 TJm +(e\002le) 17.1563 Tj +-250 TJm +(fo) 8.29918 Tj +1 TJm +(r) 3.31768 Tj +-250 TJm +(V) 7.19329 Tj +60 TJm +(isual) 18.8201 Tj +-250 TJm +(C,) 9.13607 Tj +-250 TJm +(ha) 9.40507 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(look) 17.7142 Tj +-250 TJm +(at) 7.19329 Tj +[1 0 0 1 292.212 540.672] cm +0 g +0 G +[1 0 0 1 -292.212 -540.672] cm +[1 0 0 1 0 0] Tm +0 0 Td +292.212 540.672 Td +/F130_0 9.963 Tf +(makefile.msc) 71.7336 Tj +[1 0 0 1 363.943 540.672] cm +0 g +0 G +[1 0 0 1 -363.943 -540.672] cm +[1 0 0 1 0 0] Tm +0 0 Td +363.943 540.672 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 72 538.516] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -528.553] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 518.755 Td +/F128_0 9.963 Tf +(Be) 11.0689 Tj +-291 TJm +(a) 4.42357 Tj +15 TJm +(w) 7.19329 Tj +10 TJm +(are) 12.1648 Tj +-291 TJm +(that) 14.9445 Tj +-291 TJm +(if) 6.08739 Tj +-291 TJm +(you) 14.9445 Tj +-291 TJm +(compile) 32.1008 Tj +[1 0 0 1 192.07 518.755] cm +0 g +0 G +[1 0 0 1 -192.07 -518.755] cm +[1 0 0 1 0 0] Tm +0 0 Td +192.07 518.755 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 221.957 518.755] cm +0 g +0 G +[1 0 0 1 -221.957 -518.755] cm +[1 0 0 1 0 0] Tm +0 0 Td +224.857 518.755 Td +/F128_0 9.963 Tf +(itself) 19.926 Tj +-291 TJm +(on) 9.963 Tj +-291 TJm +(W) 9.40507 Tj +40 TJm +(in32,) 20.205 Tj +-301 TJm +(you) 14.9445 Tj +-291 TJm +(must) 19.378 Tj +-291 TJm +(set) 11.0689 Tj +[1 0 0 1 346.842 518.755] cm +0 g +0 G +[1 0 0 1 -346.842 -518.755] cm +[1 0 0 1 0 0] Tm +0 0 Td +346.842 518.755 Td +/F130_0 9.963 Tf +(BZ_UNIX) 41.8446 Tj +[1 0 0 1 388.685 518.755] cm +0 g +0 G +[1 0 0 1 -388.685 -518.755] cm +[1 0 0 1 0 0] Tm +0 0 Td +391.584 518.755 Td +/F128_0 9.963 Tf +(to) 7.75121 Tj +-291 TJm +(0) 4.9815 Tj +-291 TJm +(and) 14.3866 Tj +[1 0 0 1 427.399 518.755] cm +0 g +0 G +[1 0 0 1 -427.399 -518.755] cm +[1 0 0 1 0 0] Tm +0 0 Td +427.399 518.755 Td +/F130_0 9.963 Tf +(BZ_LCCWIN32) 65.7558 Tj +[1 0 0 1 493.153 518.755] cm +0 g +0 G +[1 0 0 1 -493.153 -518.755] cm +[1 0 0 1 0 0] Tm +0 0 Td +496.052 518.755 Td +/F128_0 9.963 Tf +(to) 7.75121 Tj +-291 TJm +(1,) 7.47225 Tj +-301 TJm +(in) 7.75121 Tj +-291 TJm +(the) 12.1748 Tj +72 506.8 Td +(\002le) 12.7327 Tj +[1 0 0 1 87.223 506.799] cm +0 g +0 G +[1 0 0 1 -87.223 -506.799] cm +[1 0 0 1 0 0] Tm +0 0 Td +87.223 506.799 Td +/F130_0 9.963 Tf +(bzip2.c) 41.8446 Tj +[1 0 0 1 129.066 506.799] cm +0 g +0 G +[1 0 0 1 -129.066 -506.799] cm +[1 0 0 1 0 0] Tm +0 0 Td +129.066 506.799 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-250 TJm +(before) 25.4455 Tj +-250 TJm +(compiling.) 42.9007 Tj +-310 TJm +(Otherwi) 32.6488 Tj +1 TJm +(se) 8.29918 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(resulting) 34.8705 Tj +-250 TJm +(binary) 25.4555 Tj +-250 TJm +(w) 7.19329 Tj +10 TJm +(on') 13.2807 Tj +18 TJm +(t) 2.76971 Tj +-250 TJm +(w) 7.19329 Tj +10 TJm +(ork) 13.2807 Tj +-250 TJm +(correctly) 35.4085 Tj +65 TJm +(.) 2.49075 Tj +[1 0 0 1 72 504.643] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -494.68] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 484.882 Td +/F128_0 9.963 Tf +(I) 3.31768 Tj +-250 TJm +(ha) 9.40507 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(en') 12.7228 Tj +18 TJm +(t) 2.76971 Tj +-250 TJm +(tried) 18.2622 Tj +-250 TJm +(an) 9.40507 Tj +15 TJm +(y) 4.9815 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(this) 14.3965 Tj +-250 TJm +(stuf) 14.9445 Tj +25 TJm +(f) 3.31768 Tj +-249 TJm +(myself,) 29.61 Tj +-250 TJm +(b) 4.9815 Tj +20 TJm +(ut) 7.75121 Tj +-250 TJm +(it) 5.53943 Tj +-250 TJm +(all) 9.963 Tj +-250 TJm +(looks) 21.5898 Tj +-250 TJm +(plausible.) 38.4671 Tj +[1 0 0 1 72 482.725] cm +0 g +0 G +0 g +0 G +[1 0 0 1 0 -431.873] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.854] cm +0 g +0 G +0 g +0 G +[1 0 0 1 40.572 -6.755] cm +0 g +0 G +[1 0 0 1 -493.841 -50.951] cm +[1 0 0 1 0 0] Tm +0 0 Td +534.414 50.951 Td +/F128_0 9.963 Tf +(30) 9.963 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 34 34 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 140.398 0] cm +0 g +0 G +[1 0 0 1 -140.398 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -13.948] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -468 -21.554] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -720] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 701.916 Td +/F121_0 24.79 Tf +(4.) 20.6749 Tj +-278 TJm +(Miscellanea) 139.171 Tj +[1 0 0 1 72 701.606] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.135] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -14.116] cm +0 g +0 G +[1 0 0 1 -72 -678.355] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 658.006 Td +/F121_0 17.215 Tf +(T) 10.5184 Tj +80 TJm +(ab) 20.0899 Tj +10 TJm +(le) 14.3573 Tj +-278 TJm +(of) 16.251 Tj +-278 TJm +(Contents) 74.5926 Tj +[1 0 0 1 72 649.183] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -11.74] cm +0 g +0 G +[1 0 0 1 -72 -637.443] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 637.443 Td +/F128_0 9.963 Tf +(4.1.) 14.9445 Tj +-310 TJm +(Limitations) 45.9494 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(comp) 22.1378 Tj +1 TJm +(ressed) 24.8975 Tj +-250 TJm +(\002le) 12.7327 Tj +-250 TJm +(format) 26.5614 Tj +[1 0 0 1 255.231 637.443] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -260.212 -637.443] cm +[1 0 0 1 0 0] Tm +0 0 Td +269.154 637.443 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 637.443] cm +0 g +0 G +[1 0 0 1 -506.127 -637.443] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 637.443 Td +/F128_0 9.963 Tf +(31) 9.963 Tj +[1 0 0 1 516.09 637.443] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.798] cm +0 g +0 G +[1 0 0 1 -72 -625.488] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 625.488 Td +/F128_0 9.963 Tf +(4.2.) 14.9445 Tj +-310 TJm +(Portability) 42.0737 Tj +-250 TJm +(issues) 23.8016 Tj +[1 0 0 1 158.395 625.488] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -163.376 -625.488] cm +[1 0 0 1 0 0] Tm +0 0 Td +172.03 625.488 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 625.488] cm +0 g +0 G +[1 0 0 1 -506.127 -625.488] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 625.488 Td +/F128_0 9.963 Tf +(32) 9.963 Tj +[1 0 0 1 516.09 625.488] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.798] cm +0 g +0 G +[1 0 0 1 -72 -613.533] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 613.533 Td +/F128_0 9.963 Tf +(4.3.) 14.9445 Tj +-310 TJm +(Reporting) 39.852 Tj +-250 TJm +(b) 4.9815 Tj +20 TJm +(ugs) 13.8386 Tj +[1 0 0 1 150.993 613.533] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 -155.975 -613.533] cm +[1 0 0 1 0 0] Tm +0 0 Td +166.115 613.533 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 613.533] cm +0 g +0 G +[1 0 0 1 -506.127 -613.533] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 613.533 Td +/F128_0 9.963 Tf +(32) 9.963 Tj +[1 0 0 1 516.09 613.533] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.798] cm +0 g +0 G +[1 0 0 1 -72 -601.578] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 601.578 Td +/F128_0 9.963 Tf +(4.4.) 14.9445 Tj +-310 TJm +(Did) 14.9445 Tj +-250 TJm +(you) 14.9445 Tj +-250 TJm +(get) 12.1748 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(right) 18.8201 Tj +-250 TJm +(packa) 23.2337 Tj +1 TJm +(ge?) 13.8286 Tj +[1 0 0 1 212.602 601.578] cm +0 g +0 G +[1 0 0 1 3.088 0] cm +0 g +0 G +[1 0 0 1 3.088 0] cm +0 g +0 G +[1 0 0 1 -218.778 -601.578] cm +[1 0 0 1 0 0] Tm +0 0 Td +229.109 601.578 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 601.578] cm +0 g +0 G +[1 0 0 1 -506.127 -601.578] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 601.578 Td +/F128_0 9.963 Tf +(33) 9.963 Tj +[1 0 0 1 516.09 601.578] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.798] cm +0 g +0 G +[1 0 0 1 -72 -589.623] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 589.623 Td +/F128_0 9.963 Tf +(4.5.) 14.9445 Tj +-310 TJm +(Further) 29.3311 Tj +-250 TJm +(Reading) 33.2067 Tj +[1 0 0 1 155.058 589.623] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 -160.039 -589.623] cm +[1 0 0 1 0 0] Tm +0 0 Td +170.361 589.623 Td +/F143_0 9.963 Tf +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +-166 TJm +(:) 2.76971 Tj +-167 TJm +(:) 2.76971 Tj +[1 0 0 1 506.127 589.623] cm +0 g +0 G +[1 0 0 1 -506.127 -589.623] cm +[1 0 0 1 0 0] Tm +0 0 Td +506.127 589.623 Td +/F128_0 9.963 Tf +(34) 9.963 Tj +[1 0 0 1 516.09 589.623] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -444.09 -2.157] cm +0 g +0 G +[1 0 0 1 0 -9.135] cm +0 g +0 G +[1 0 0 1 0 -9.631] cm +0 g +0 G +[1 0 0 1 -72 -568.7] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 558.901 Td +/F128_0 9.963 Tf +(These) 23.7916 Tj +-250 TJm +(are) 12.1648 Tj +-250 TJm +(just) 14.3965 Tj +-250 TJm +(some) 21.0319 Tj +-250 TJm +(random) 30.437 Tj +-249 TJm +(thoughts) 34.3225 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(mine.) 22.4168 Tj +-620 TJm +(Y) 7.19329 Tj +110 TJm +(our) 13.2807 Tj +-250 TJm +(mileage) 31.5429 Tj +-250 TJm +(may) 17.1563 Tj +-250 TJm +(v) 4.9815 Tj +25 TJm +(ary) 12.7228 Tj +65 TJm +(.) 2.49075 Tj +[1 0 0 1 72 556.744] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.631] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -547.113] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 524.48 Td +/F121_0 20.659 Tf +(4.1.) 34.4592 Tj +-278 TJm +(Limitations) 110.195 Tj +-278 TJm +(of) 19.5021 Tj +-278 TJm +(the) 30.9885 Tj +-278 TJm +(compres) 86.1067 Tj +1 TJm +(sed) 35.5955 Tj +-278 TJm +(\002le) 29.8523 Tj +-278 TJm +(f) 6.87945 Tj +20 TJm +(ormat) 57.3907 Tj +[1 0 0 1 72 520.203] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.631] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -510.572] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 502.893 Td +/F130_0 9.963 Tf +(bzip2-1.0.X) 65.7558 Tj +[1 0 0 1 137.753 502.893] cm +0 g +0 G +[1 0 0 1 -137.753 -502.893] cm +[1 0 0 1 0 0] Tm +0 0 Td +137.753 502.893 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +[1 0 0 1 143.405 502.893] cm +0 g +0 G +[1 0 0 1 -143.405 -502.893] cm +[1 0 0 1 0 0] Tm +0 0 Td +143.405 502.893 Td +/F130_0 9.963 Tf +(0.9.5) 29.889 Tj +[1 0 0 1 173.293 502.893] cm +0 g +0 G +[1 0 0 1 -173.293 -502.893] cm +[1 0 0 1 0 0] Tm +0 0 Td +176.453 502.893 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 194 502.893] cm +0 g +0 G +[1 0 0 1 -194 -502.893] cm +[1 0 0 1 0 0] Tm +0 0 Td +194 502.893 Td +/F130_0 9.963 Tf +(0.9.0) 29.889 Tj +[1 0 0 1 223.888 502.893] cm +0 g +0 G +[1 0 0 1 -223.888 -502.893] cm +[1 0 0 1 0 0] Tm +0 0 Td +227.048 502.893 Td +/F128_0 9.963 Tf +(use) 13.2807 Tj +-317 TJm +(e) 4.42357 Tj +15 TJm +(xactly) 24.3496 Tj +-317 TJm +(the) 12.1748 Tj +-318 TJm +(s) 3.87561 Tj +1 TJm +(ame) 16.5984 Tj +-318 TJm +(\002le) 12.7327 Tj +-317 TJm +(format) 26.5614 Tj +-317 TJm +(as) 8.29918 Tj +-317 TJm +(the) 12.1748 Tj +-317 TJm +(original) 30.9949 Tj +-317 TJm +(v) 4.9815 Tj +15 TJm +(ersion,) 26.8403 Tj +[1 0 0 1 455.801 502.893] cm +0 g +0 G +[1 0 0 1 -455.801 -502.893] cm +[1 0 0 1 0 0] Tm +0 0 Td +455.801 502.893 Td +/F130_0 9.963 Tf +(bzip2-0.1) 53.8002 Tj +[1 0 0 1 509.599 502.893] cm +0 g +0 G +[1 0 0 1 -509.599 -502.893] cm +[1 0 0 1 0 0] Tm +0 0 Td +509.599 502.893 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +-1023 TJm +(This) 17.7142 Tj +72 490.938 Td +(decision) 33.2067 Tj +-222 TJm +(w) 7.19329 Tj +10 TJm +(as) 8.29918 Tj +-221 TJm +(made) 21.5799 Tj +-222 TJm +(in) 7.75121 Tj +-222 TJm +(the) 12.1748 Tj +-222 TJm +(interests) 33.2067 Tj +-221 TJm +(of) 8.29918 Tj +-222 TJm +(stability) 32.1107 Tj +65 TJm +(.) 2.49075 Tj +-601 TJm +(Creating) 34.3126 Tj +-222 TJm +(yet) 12.1748 Tj +-222 TJm +(another) 29.879 Tj +-222 TJm +(inc) 12.1748 Tj +1 TJm +(ompatible) 39.852 Tj +-222 TJm +(compressed) 47.0353 Tj +-222 TJm +(\002le) 12.7327 Tj +-222 TJm +(form) 19.3681 Tj +1 TJm +(at) 7.19329 Tj +-222 TJm +(w) 7.19329 Tj +10 TJm +(ould) 17.7142 Tj +-222 TJm +(create) 23.7817 Tj +72 478.983 Td +(further) 27.1093 Tj +-250 TJm +(confusion) 39.2941 Tj +-250 TJm +(and) 14.3866 Tj +-250 TJm +(disrupti) 30.4469 Tj +1 TJm +(on) 9.963 Tj +-250 TJm +(for) 11.6169 Tj +-250 TJm +(users.) 22.9647 Tj +[1 0 0 1 72 476.826] cm +0 g +0 G +[1 0 0 1 0 -9.632] cm +0 g +0 G +[1 0 0 1 -72 -467.194] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 457.396 Td +/F128_0 9.963 Tf +(Ne) 11.6169 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(ertheless,) 37.3513 Tj +-233 TJm +(this) 14.3965 Tj +-230 TJm +(is) 6.64532 Tj +-229 TJm +(not) 12.7327 Tj +-230 TJm +(a) 4.42357 Tj +-229 TJm +(painless) 32.1008 Tj +-230 TJm +(decisio) 28.2252 Tj +1 TJm +(n.) 7.47225 Tj +-607 TJm +(De) 11.6169 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(elopment) 37.0823 Tj +-229 TJm +(w) 7.19329 Tj +10 TJm +(ork) 13.2807 Tj +-230 TJm +(si) 6.64532 Tj +1 TJm +(nce) 13.8286 Tj +-230 TJm +(the) 12.1748 Tj +-229 TJm +(release) 27.6573 Tj +-230 TJm +(of) 8.29918 Tj +[1 0 0 1 407.317 457.396] cm +0 g +0 G +[1 0 0 1 -407.317 -457.396] cm +[1 0 0 1 0 0] Tm +0 0 Td +407.317 457.396 Td +/F130_0 9.963 Tf +(bzip2-0.1) 53.8002 Tj +[1 0 0 1 461.115 457.396] cm +0 g +0 G +[1 0 0 1 -461.115 -457.396] cm +[1 0 0 1 0 0] Tm +0 0 Td +463.402 457.396 Td +/F128_0 9.963 Tf +(in) 7.75121 Tj +-229 TJm +(August) 28.7831 Tj +-230 TJm +(1997) 19.926 Tj +-229 TJm +(has) 13.2807 Tj +72 445.441 Td +(sho) 13.8386 Tj +25 TJm +(wn) 12.1748 Tj +-226 TJm +(comple) 29.3311 Tj +15 TJm +(xities) 21.5898 Tj +-225 TJm +(in) 7.75121 Tj +-226 TJm +(the) 12.1748 Tj +-226 TJm +(\002le) 12.7327 Tj +-226 TJm +(forma) 23.7916 Tj +1 TJm +(t) 2.76971 Tj +-226 TJm +(which) 24.3496 Tj +-226 TJm +(slo) 11.6268 Tj +25 TJm +(w) 7.19329 Tj +-226 TJm +(do) 9.963 Tj +25 TJm +(wn) 12.1748 Tj +-225 TJm +(decompression) 59.768 Tj +-226 TJm +(and,) 16.8773 Tj +-231 TJm +(in) 7.75121 Tj +-225 TJm +(retrospect,) 41.7749 Tj +-231 TJm +(are) 12.1648 Tj +-226 TJm +(unnecess) 35.9664 Tj +1 TJm +(ary) 12.7228 Tj +65 TJm +(.) 2.49075 Tj +-604 TJm +(These) 23.7916 Tj +-226 TJm +(are:) 14.9345 Tj +[1 0 0 1 72 443.284] cm +0 g +0 G +[1 0 0 1 0 -29.062] cm +0 g +0 G +[1 0 0 1 6.974 0] cm +0 g +0 G +[1 0 0 1 -78.974 -414.222] cm +[1 0 0 1 0 0] Tm +0 0 Td +78.974 414.222 Td +/F128_0 9.963 Tf +(\225) 3.48705 Tj +[1 0 0 1 82.461 414.222] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 1.993 0] cm +0 g +0 G +[1 0 0 1 -86.944 -414.222] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 414.222 Td +/F128_0 9.963 Tf +(The) 15.4925 Tj +-265 TJm +(run-length) 41.5059 Tj +-265 TJm +(encoder) 31.5329 Tj +40 TJm +(,) 2.49075 Tj +-269 TJm +(which) 24.3496 Tj +-266 TJm +(is) 6.64532 Tj +-265 TJm +(the) 12.1748 Tj +-265 TJm +(\002rst) 15.5024 Tj +-265 TJm +(of) 8.29918 Tj +-266 TJm +(the) 12.1748 Tj +-265 TJm +(compression) 50.363 Tj +-265 TJm +(transformations,) 65.0285 Tj +-269 TJm +(is) 6.64532 Tj +-265 TJm +(entirely) 30.437 Tj +-265 TJm +(irrele) 21.0219 Tj +25 TJm +(v) 4.9815 Tj +25 TJm +(ant.) 14.6655 Tj +-712 TJm +(The) 15.4925 Tj +-265 TJm +(original) 30.9949 Tj +86.944 402.267 Td +(purpose) 31.5429 Tj +-301 TJm +(w) 7.19329 Tj +10 TJm +(as) 8.29918 Tj +-301 TJm +(to) 7.75121 Tj +-301 TJm +(protect) 27.6673 Tj +-301 TJm +(the) 12.1748 Tj +-301 TJm +(sorting) 27.6772 Tj +-301 TJm +(algorit) 26.0134 Tj +1 TJm +(hm) 12.7327 Tj +-301 TJm +(from) 19.3681 Tj +-301 TJm +(the) 12.1748 Tj +-301 TJm +(v) 4.9815 Tj +15 TJm +(ery) 12.7228 Tj +-301 TJm +(w) 7.19329 Tj +10 TJm +(orst) 14.9445 Tj +-301 TJm +(case) 17.1463 Tj +-301 TJm +(input:) 23.2536 Tj +-412 TJm +(a) 4.42357 Tj +-301 TJm +(string) 22.6957 Tj +-301 TJm +(of) 8.29918 Tj +-301 TJm +(repeated) 33.7447 Tj +-301 TJm +(symbols.) 35.7074 Tj +-926 TJm +(But) 14.3965 Tj +86.944 390.312 Td +(algorithm) 38.7461 Tj +-274 TJm +(steps) 19.926 Tj +-274 TJm +(Q6a) 16.5984 Tj +-275 TJm +(and) 14.3866 Tj +-274 TJm +(Q6b) 17.1563 Tj +-274 TJm +(in) 7.75121 Tj +-274 TJm +(the) 12.1748 Tj +-275 TJm +(original) 30.9949 Tj +-274 TJm +(Burro) 23.2437 Tj +25 TJm +(ws-Wheeler) 48.1313 Tj +-274 TJm +(technical) 35.9664 Tj +-274 TJm +(report) 23.7916 Tj +-274 TJm +(\(SRC-124\)) 43.7276 Tj +-274 TJm +(sho) 13.8386 Tj +25 TJm +(w) 7.19329 Tj +-275 TJm +(ho) 9.963 Tj +25 TJm +(w) 7.19329 Tj +-274 TJm +(repeats) 28.2152 Tj +-274 TJm +(can) 13.8286 Tj +86.944 378.357 Td +(be) 9.40507 Tj +-250 TJm +(handled) 31.5429 Tj +-250 TJm +(without) 30.4469 Tj +-250 TJm +(dif) 11.0689 Tj +25 TJm +(\002culty) 25.4654 Tj +-249 TJm +(in) 7.75121 Tj +-250 TJm +(block) 22.1378 Tj +-250 TJm +(sorting.) 30.168 Tj +[1 0 0 1 269.617 378.357] cm +0 g +0 G +[1 0 0 1 -197.617 -21.587] cm +0 g +0 G +[1 0 0 1 6.974 0] cm +0 g +0 G +[1 0 0 1 -78.974 -356.77] cm +[1 0 0 1 0 0] Tm +0 0 Td +78.974 356.77 Td +/F128_0 9.963 Tf +(\225) 3.48705 Tj +[1 0 0 1 82.461 356.77] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 1.993 0] cm +0 g +0 G +[1 0 0 1 -86.944 -356.77] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 356.77 Td +/F128_0 9.963 Tf +(The) 15.4925 Tj +-293 TJm +(randomisation) 57.0083 Tj +-293 TJm +(mechanism) 45.3815 Tj +-293 TJm +(doesn') 26.5614 Tj +18 TJm +(t) 2.76971 Tj +-293 TJm +(really) 22.6858 Tj +-293 TJm +(need) 18.8101 Tj +-293 TJm +(to) 7.75121 Tj +-293 TJm +(be) 9.40507 Tj +-293 TJm +(there.) 22.4068 Tj +-879 TJm +(Udi) 14.9445 Tj +-294 TJm +(Man) 18.2622 Tj +1 TJm +(ber) 12.7228 Tj +-294 TJm +(and) 14.3866 Tj +-293 TJm +(Gene) 21.0219 Tj +-293 TJm +(Myers) 25.4555 Tj +-293 TJm +(published) 38.7461 Tj +-293 TJm +(a) 4.42357 Tj +-293 TJm +(suf) 12.1748 Tj +25 TJm +(\002x) 10.5209 Tj +86.944 344.815 Td +(array) 20.464 Tj +-238 TJm +(construction) 49.2571 Tj +-238 TJm +(algorithm) 38.7461 Tj +-239 TJm +(a) 4.42357 Tj +-238 TJm +(fe) 7.74125 Tj +25 TJm +(w) 7.19329 Tj +-238 TJm +(years) 21.0219 Tj +-238 TJm +(back,) 21.3009 Tj +-241 TJm +(which) 24.3496 Tj +-238 TJm +(can) 13.8286 Tj +-238 TJm +(be) 9.40507 Tj +-239 TJm +(emplo) 24.9075 Tj +10 TJm +(yed) 14.3866 Tj +-238 TJm +(to) 7.75121 Tj +-238 TJm +(sort) 14.9445 Tj +-239 TJm +(a) 4.42357 Tj +1 TJm +(n) 4.9815 Tj +15 TJm +(y) 4.9815 Tj +-239 TJm +(block,) 24.6285 Tj +-240 TJm +(no) 9.963 Tj +-239 TJm +(matter) 25.4555 Tj +-238 TJm +(ho) 9.963 Tj +25 TJm +(w) 7.19329 Tj +-238 TJm +(repetiti) 28.2252 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(e,) 6.91432 Tj +86.944 332.86 Td +(in) 7.75121 Tj +-229 TJm +(O\(N) 17.7043 Tj +-230 TJm +(log) 12.7327 Tj +-229 TJm +(N\)) 10.511 Tj +-230 TJm +(time.) 20.205 Tj +-606 TJm +(Subsequent) 45.9394 Tj +-229 TJm +(w) 7.19329 Tj +10 TJm +(ork) 13.2807 Tj +-229 TJm +(by) 9.963 Tj +-230 TJm +(K) 7.19329 Tj +15 TJm +(unihik) 25.4654 Tj +10 TJm +(o) 4.9815 Tj +-229 TJm +(Sadakane) 38.1782 Tj +-230 TJm +(ha) 9.40507 Tj +1 TJm +(s) 3.87561 Tj +-230 TJm +(produced) 37.0723 Tj +-229 TJm +(a) 4.42357 Tj +-230 TJm +(deri) 15.4925 Tj +25 TJm +(v) 4.9815 Tj +25 TJm +(ati) 9.963 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-229 TJm +(O\(N) 17.7043 Tj +-229 TJm +(\(log) 16.0504 Tj +-230 TJm +(N\)^2\)) 23.4828 Tj +-229 TJm +(algorithm) 38.7461 Tj +86.944 320.905 Td +(which) 24.3496 Tj +-250 TJm +(usually) 28.7831 Tj +-250 TJm +(outperforms) 48.6991 Tj +-250 TJm +(th) 7.75121 Tj +1 TJm +(e) 4.42357 Tj +-250 TJm +(Manber) 30.9849 Tj +20 TJm +(-Myers) 28.7731 Tj +-250 TJm +(algorithm.) 41.2369 Tj +[1 0 0 1 314.189 320.905] cm +0 g +0 G +[1 0 0 1 -242.189 -11.789] cm +0 g +0 G +[1 0 0 1 -72 -309.116] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 299.318 Td +/F128_0 9.963 Tf +(I) 3.31768 Tj +-248 TJm +(could) 22.1378 Tj +-248 TJm +(ha) 9.40507 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-248 TJm +(changed) 33.1967 Tj +-248 TJm +(to) 7.75121 Tj +-248 TJm +(Sadakane') 41.4959 Tj +55 TJm +(s) 3.87561 Tj +-248 TJm +(algor) 20.474 Tj +1 TJm +(ithm,) 20.7629 Tj +-249 TJm +(b) 4.9815 Tj +20 TJm +(ut) 7.75121 Tj +-248 TJm +(I) 3.31768 Tj +-248 TJm +(\002nd) 15.5024 Tj +-248 TJm +(it) 5.53943 Tj +-248 TJm +(to) 7.75121 Tj +-248 TJm +(be) 9.40507 Tj +-248 TJm +(slo) 11.6268 Tj +25 TJm +(wer) 14.9345 Tj +-248 TJm +(than) 17.1563 Tj +[1 0 0 1 392.444 299.318] cm +0 g +0 G +[1 0 0 1 -392.444 -299.318] cm +[1 0 0 1 0 0] Tm +0 0 Td +392.444 299.318 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 422.332 299.318] cm +0 g +0 G +[1 0 0 1 -422.332 -299.318] cm +[1 0 0 1 0 0] Tm +0 0 Td +422.332 299.318 Td +/F128_0 9.963 Tf +(') 3.31768 Tj +55 TJm +(s) 3.87561 Tj +-248 TJm +(e) 4.42357 Tj +15 TJm +(xisting) 27.1292 Tj +-248 TJm +(algorithm) 38.7461 Tj +-248 TJm +(for) 11.6169 Tj +-248 TJm +(most) 19.378 Tj +86.944 287.363 Td +(inputs,) 26.8503 Tj +-369 TJm +(and) 14.3866 Tj +-346 TJm +(the) 12.1748 Tj +-346 TJm +(randomis) 37.0823 Tj +1 TJm +(ation) 19.926 Tj +-346 TJm +(mechanism) 45.3815 Tj +-346 TJm +(p) 4.9815 Tj +1 TJm +(rotects) 26.5614 Tj +-346 TJm +(adequately) 43.1597 Tj +-345 TJm +(ag) 9.40507 Tj +5 TJm +(ainst) 18.8201 Tj +-346 TJm +(bad) 14.3866 Tj +-346 TJm +(cases) 21.0219 Tj +1 TJm +(.) 2.49075 Tj +-1194 TJm +(I) 3.31768 Tj +-346 TJm +(didn') 21.0319 Tj +18 TJm +(t) 2.76971 Tj +-346 TJm +(think) 20.4839 Tj +-345 TJm +(it) 5.53943 Tj +-346 TJm +(w) 7.19329 Tj +10 TJm +(as) 8.29918 Tj +-345 TJm +(a) 4.42357 Tj +-346 TJm +(good) 19.926 Tj +86.944 275.408 Td +(tradeof) 28.2152 Tj +25 TJm +(f) 3.31768 Tj +-261 TJm +(to) 7.75121 Tj +-262 TJm +(mak) 17.1563 Tj +10 TJm +(e.) 6.91432 Tj +-690 TJm +(P) 5.53943 Tj +15 TJm +(artly) 18.2622 Tj +-261 TJm +(this) 14.3965 Tj +-262 TJm +(is) 6.64532 Tj +-261 TJm +(due) 14.3866 Tj +-262 TJm +(to) 7.75121 Tj +-261 TJm +(the) 12.1748 Tj +-262 TJm +(f) 3.31768 Tj +10 TJm +(act) 11.6169 Tj +-261 TJm +(that) 14.9445 Tj +-262 TJm +(I) 3.31768 Tj +-262 TJm +(w) 7.19329 Tj +10 TJm +(as) 8.29918 Tj +-261 TJm +(not) 12.7327 Tj +-262 TJm +(\003ooded) 29.889 Tj +-261 TJm +(with) 17.7142 Tj +-262 TJm +(email) 22.1378 Tj +-261 TJm +(complaints) 43.7276 Tj +-262 TJm +(about) 22.1378 Tj +[1 0 0 1 479.557 275.408] cm +0 g +0 G +[1 0 0 1 -479.557 -275.408] cm +[1 0 0 1 0 0] Tm +0 0 Td +479.557 275.408 Td +/F130_0 9.963 Tf +(bzip2-0.1) 53.8002 Tj +[1 0 0 1 533.355 275.408] cm +0 g +0 G +[1 0 0 1 -533.355 -275.408] cm +[1 0 0 1 0 0] Tm +0 0 Td +533.355 275.408 Td +/F128_0 9.963 Tf +(') 3.31768 Tj +55 TJm +(s) 3.87561 Tj +86.944 263.453 Td +(performance) 50.343 Tj +-250 TJm +(on) 9.963 Tj +-250 TJm +(repetiti) 28.2252 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-250 TJm +(dat) 12.1748 Tj +1 TJm +(a,) 6.91432 Tj +-250 TJm +(so) 8.85711 Tj +-250 TJm +(perhaps) 30.9849 Tj +-250 TJm +(it) 5.53943 Tj +-250 TJm +(isn') 14.9445 Tj +18 TJm +(t) 2.76971 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(problem) 33.2067 Tj +-250 TJm +(for) 11.6169 Tj +-250 TJm +(real) 14.9345 Tj +-250 TJm +(inputs.) 26.8503 Tj +[1 0 0 1 72 261.296] cm +0 g +0 G +[1 0 0 1 0 -9.632] cm +0 g +0 G +[1 0 0 1 -72 -251.664] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 241.866 Td +/F128_0 9.963 Tf +(Probably) 35.9764 Tj +-289 TJm +(the) 12.1748 Tj +-288 TJm +(best) 16.0504 Tj +-289 TJm +(long-term) 39.2941 Tj +-288 TJm +(solution,) 34.6015 Tj +-299 TJm +(and) 14.3866 Tj +-288 TJm +(the) 12.1748 Tj +-289 TJm +(one) 14.3866 Tj +-289 TJm +(I) 3.31768 Tj +-288 TJm +(ha) 9.40507 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-289 TJm +(incorporated) 50.353 Tj +-288 TJm +(into) 15.5024 Tj +-289 TJm +(0.9.5) 19.926 Tj +-289 TJm +(and) 14.3866 Tj +-288 TJm +(abo) 14.3866 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(e,) 6.91432 Tj +-298 TJm +(is) 6.64532 Tj +-289 TJm +(to) 7.75121 Tj +-289 TJm +(use) 13.2807 Tj +-288 TJm +(the) 12.1748 Tj +-289 TJm +(e) 4.42357 Tj +15 TJm +(xisting) 27.1292 Tj +86.944 229.911 Td +(sorting) 27.6772 Tj +-451 TJm +(algorithm) 38.7461 Tj +-451 TJm +(initially) 31.0049 Tj +65 TJm +(,) 2.49075 Tj +-502 TJm +(and) 14.3866 Tj +-451 TJm +(f) 3.31768 Tj +10 TJm +(all) 9.963 Tj +-452 TJm +(back) 18.8101 Tj +-451 TJm +(to) 7.75121 Tj +-451 TJm +(a) 4.42357 Tj +-452 TJm +(O\(N) 17.7043 Tj +-451 TJm +(\(log) 16.0504 Tj +-451 TJm +(N\)^2\)) 23.4828 Tj +-451 TJm +(algorithm) 38.7461 Tj +-452 TJm +(if) 6.08739 Tj +-451 TJm +(the) 12.1748 Tj +-451 TJm +(standard) 33.7546 Tj +-452 TJm +(al) 7.19329 Tj +1 TJm +(gorithm) 31.5528 Tj +-452 TJm +(gets) 16.0504 Tj +-451 TJm +(into) 15.5024 Tj +86.944 217.956 Td +(dif) 11.0689 Tj +25 TJm +(\002culties.) 34.0436 Tj +[1 0 0 1 72 217.856] cm +0 g +0 G +[1 0 0 1 0 -21.487] cm +0 g +0 G +[1 0 0 1 6.974 0] cm +0 g +0 G +[1 0 0 1 -78.974 -196.369] cm +[1 0 0 1 0 0] Tm +0 0 Td +78.974 196.369 Td +/F128_0 9.963 Tf +(\225) 3.48705 Tj +[1 0 0 1 82.461 196.369] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 1.993 0] cm +0 g +0 G +[1 0 0 1 -86.944 -196.369] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 196.369 Td +/F128_0 9.963 Tf +(The) 15.4925 Tj +-299 TJm +(compressed) 47.0353 Tj +-299 TJm +(\002le) 12.7327 Tj +-299 TJm +(format) 26.5614 Tj +-299 TJm +(w) 7.19329 Tj +10 TJm +(as) 8.29918 Tj +-299 TJm +(ne) 9.40507 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(er) 7.74125 Tj +-299 TJm +(designed) 35.4185 Tj +-299 TJm +(to) 7.75121 Tj +-299 TJm +(be) 9.40507 Tj +-299 TJm +(handled) 31.5429 Tj +-299 TJm +(by) 9.963 Tj +-299 TJm +(a) 4.42357 Tj +-299 TJm +(library) 26.5614 Tj +65 TJm +(,) 2.49075 Tj +-312 TJm +(and) 14.3866 Tj +-299 TJm +(I) 3.31768 Tj +-299 TJm +(ha) 9.40507 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-299 TJm +(had) 14.3866 Tj +-299 TJm +(to) 7.75121 Tj +-299 TJm +(jump) 20.4839 Tj +-299 TJm +(though) 27.6772 Tj +-299 TJm +(some) 21.0319 Tj +86.944 184.414 Td +(hoops) 23.8016 Tj +-278 TJm +(to) 7.75121 Tj +-277 TJm +(produce) 32.0908 Tj +-278 TJm +(an) 9.40507 Tj +-277 TJm +(ef) 7.74125 Tj +25 TJm +(\002cient) 24.9075 Tj +-278 TJm +(implementation) 62.5477 Tj +-277 TJm +(of) 8.29918 Tj +-278 TJm +(decompression.) 62.2588 Tj +-786 TJm +(It') 9.40507 Tj +55 TJm +(s) 3.87561 Tj +-278 TJm +(a) 4.42357 Tj +-277 TJm +(bit) 10.5209 Tj +-278 TJm +(hairy) 20.474 Tj +65 TJm +(.) 2.49075 Tj +-786 TJm +(T) 6.08739 Tj +35 TJm +(ry) 8.29918 Tj +-278 TJm +(passing) 29.889 Tj +[1 0 0 1 468.269 184.414] cm +0 g +0 G +[1 0 0 1 -468.269 -184.414] cm +[1 0 0 1 0 0] Tm +0 0 Td +468.269 184.414 Td +/F130_0 9.963 Tf +(decompress.c) 71.7336 Tj +[1 0 0 1 540 184.414] cm +0 g +0 G +[1 0 0 1 -540 -184.414] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 172.459 Td +/F128_0 9.963 Tf +(through) 30.9949 Tj +-268 TJm +(the) 12.1748 Tj +-268 TJm +(C) 6.64532 Tj +-268 TJm +(preprocessor) 50.901 Tj +-268 TJm +(and) 14.3866 Tj +-268 TJm +(you') 18.2622 Tj +10 TJm +(ll) 5.53943 Tj +-268 TJm +(see) 12.7228 Tj +-268 TJm +(what) 19.3681 Tj +-268 TJm +(I) 3.31768 Tj +-269 TJm +(mea) 16.5984 Tj +1 TJm +(n.) 7.47225 Tj +-729 TJm +(Much) 23.2437 Tj +-268 TJm +(of) 8.29918 Tj +-269 TJm +(this) 14.3965 Tj +-268 TJm +(comple) 29.3311 Tj +15 TJm +(xit) 10.5209 Tj +1 TJm +(y) 4.9815 Tj +-269 TJm +(could) 22.1378 Tj +-268 TJm +(ha) 9.40507 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-268 TJm +(been) 18.8101 Tj +-268 TJm +(a) 4.42357 Tj +20 TJm +(v) 4.9815 Tj +20 TJm +(oided) 22.1378 Tj +-268 TJm +(if) 6.08739 Tj +-268 TJm +(the) 12.1748 Tj +86.944 160.503 Td +(compressed) 47.0353 Tj +-250 TJm +(size) 15.4925 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(each) 18.2522 Tj +-250 TJm +(bloc) 17.1563 Tj +1 TJm +(k) 4.9815 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(data) 16.5984 Tj +-250 TJm +(w) 7.19329 Tj +10 TJm +(as) 8.29918 Tj +-250 TJm +(recorded) 34.8506 Tj +-250 TJm +(in) 7.75121 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(data) 16.5984 Tj +-250 TJm +(stream.) 29.0521 Tj +[1 0 0 1 368.754 160.503] cm +0 g +0 G +[1 0 0 1 -296.754 -21.586] cm +0 g +0 G +[1 0 0 1 6.974 0] cm +0 g +0 G +[1 0 0 1 -78.974 -138.917] cm +[1 0 0 1 0 0] Tm +0 0 Td +78.974 138.917 Td +/F128_0 9.963 Tf +(\225) 3.48705 Tj +[1 0 0 1 82.461 138.917] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 1.993 0] cm +0 g +0 G +[1 0 0 1 -86.944 -138.917] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 138.917 Td +/F128_0 9.963 Tf +(An) 12.1748 Tj +-250 TJm +(Adler) 22.6858 Tj +20 TJm +(-32) 13.2807 Tj +-250 TJm +(checksum,) 42.3328 Tj +-250 TJm +(rather) 23.2337 Tj +-249 TJm +(than) 17.1563 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(CRC32) 29.899 Tj +-250 TJm +(checksum,) 42.3328 Tj +-250 TJm +(w) 7.19329 Tj +10 TJm +(ould) 17.7142 Tj +-250 TJm +(be) 9.40507 Tj +-250 TJm +(f) 3.31768 Tj +10 TJm +(aster) 18.8101 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(compute.) 36.8033 Tj +[1 0 0 1 424.934 138.917] cm +0 g +0 G +[1 0 0 1 -352.934 -11.789] cm +0 g +0 G +[1 0 0 1 -72 -127.128] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 117.33 Td +/F128_0 9.963 Tf +(It) 6.08739 Tj +-349 TJm +(w) 7.19329 Tj +10 TJm +(ould) 17.7142 Tj +-349 TJm +(be) 9.40507 Tj +-348 TJm +(f) 3.31768 Tj +10 TJm +(air) 10.511 Tj +-349 TJm +(to) 7.75121 Tj +-349 TJm +(say) 13.2807 Tj +-349 TJm +(that) 14.9445 Tj +-348 TJm +(the) 12.1748 Tj +[1 0 0 1 201.979 117.33] cm +0 g +0 G +[1 0 0 1 -201.979 -117.33] cm +[1 0 0 1 0 0] Tm +0 0 Td +201.979 117.33 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 231.867 117.33] cm +0 g +0 G +[1 0 0 1 -231.867 -117.33] cm +[1 0 0 1 0 0] Tm +0 0 Td +235.342 117.33 Td +/F128_0 9.963 Tf +(format) 26.5614 Tj +-349 TJm +(w) 7.19329 Tj +10 TJm +(as) 8.29918 Tj +-348 TJm +(frozen) 25.4455 Tj +-349 TJm +(before) 25.4455 Tj +-349 TJm +(I) 3.31768 Tj +-349 TJm +(properl) 28.7731 Tj +1 TJm +(y) 4.9815 Tj +-349 TJm +(and) 14.3866 Tj +-349 TJm +(fully) 18.8201 Tj +-349 TJm +(understood) 44.2756 Tj +-348 TJm +(the) 12.1748 Tj +-349 TJm +(performance) 50.343 Tj +72 105.375 Td +(consequences) 54.7766 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(doing) 22.6957 Tj +-250 TJm +(so.) 11.3479 Tj +[1 0 0 1 72 103.218] cm +0 g +0 G +[1 0 0 1 0 -9.631] cm +0 g +0 G +[1 0 0 1 -72 -93.587] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 83.788 Td +/F128_0 9.963 Tf +(Impro) 24.3496 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(ements) 28.2252 Tj +-250 TJm +(which) 24.3496 Tj +-250 TJm +(I) 3.31768 Tj +-250 TJm +(w) 7.19329 Tj +10 TJm +(as) 8.29918 Tj +-250 TJm +(abl) 12.1748 Tj +1 TJm +(e) 4.42357 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(incorporate) 45.3715 Tj +-250 TJm +(into) 15.5024 Tj +-250 TJm +(0.9.0,) 22.4168 Tj +-250 TJm +(despite) 28.2252 Tj +-250 TJm +(using) 21.5898 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(same) 20.474 Tj +-250 TJm +(\002le) 12.7327 Tj +-250 TJm +(for) 11.6169 Tj +1 TJm +(mat,) 17.4353 Tj +-250 TJm +(are:) 14.9345 Tj +[1 0 0 1 72 81.631] cm +0 g +0 G +[1 0 0 1 0 -30.779] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.854] cm +0 g +0 G +0 g +0 G +[1 0 0 1 40.572 -6.755] cm +0 g +0 G +[1 0 0 1 -493.841 -50.951] cm +[1 0 0 1 0 0] Tm +0 0 Td +534.414 50.951 Td +/F128_0 9.963 Tf +(31) 9.963 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 35 35 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 -6.854] cm +0 g +0 G +[1 0 0 1 0 6.854] cm +0 g +0 G +0 g +0 G +[1 0 0 1 116.329 -6.755] cm +0 g +0 G +[1 0 0 1 -382.4 -749.245] cm +[1 0 0 1 0 0] Tm +0 0 Td +498.728 749.245 Td +/F128_0 9.963 Tf +(Miscellanea) 48.1412 Tj +[1 0 0 1 266.071 749.146] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -7.094] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -468 -31.517] cm +0 g +0 G +[1 0 0 1 6.974 0] cm +0 g +0 G +[1 0 0 1 -78.974 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +78.974 710.037 Td +/F128_0 9.963 Tf +(\225) 3.48705 Tj +[1 0 0 1 82.461 710.037] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 1.993 0] cm +0 g +0 G +[1 0 0 1 -86.944 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 710.037 Td +/F128_0 9.963 Tf +(Single) 25.4654 Tj +-202 TJm +(ar) 7.74125 Tj +1 TJm +(ray) 12.7228 Tj +-202 TJm +(implementation) 62.5477 Tj +-201 TJm +(of) 8.29918 Tj +-202 TJm +(the) 12.1748 Tj +-202 TJm +(in) 7.75121 Tj +40 TJm +(v) 4.9815 Tj +15 TJm +(erse) 16.0404 Tj +-201 TJm +(BWT) 22.1378 Tj +74 TJm +(.) 2.49075 Tj +-403 TJm +(This) 17.7142 Tj +-202 TJm +(signi\002cantly) 49.267 Tj +-201 TJm +(speeds) 26.5614 Tj +-202 TJm +(up) 9.963 Tj +-202 TJm +(decom) 26.5614 Tj +1 TJm +(pression,) 35.6974 Tj +-212 TJm +(presuma) 33.7546 Tj +1 TJm +(bly) 12.7327 Tj +-202 TJm +(because) 31.5329 Tj +86.944 698.082 Td +(it) 5.53943 Tj +-250 TJm +(reduces) 30.427 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(number) 30.437 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(cach) 18.2522 Tj +1 TJm +(e) 4.42357 Tj +-250 TJm +(misses.) 29.0621 Tj +[1 0 0 1 240.496 698.082] cm +0 g +0 G +[1 0 0 1 -168.496 -21.918] cm +0 g +0 G +[1 0 0 1 6.974 0] cm +0 g +0 G +[1 0 0 1 -78.974 -676.164] cm +[1 0 0 1 0 0] Tm +0 0 Td +78.974 676.164 Td +/F128_0 9.963 Tf +(\225) 3.48705 Tj +[1 0 0 1 82.461 676.164] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 1.993 0] cm +0 g +0 G +[1 0 0 1 -86.944 -676.164] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 676.164 Td +/F128_0 9.963 Tf +(F) 5.53943 Tj +15 TJm +(aster) 18.8101 Tj +-314 TJm +(in) 7.75121 Tj +40 TJm +(v) 4.9815 Tj +15 TJm +(erse) 16.0404 Tj +-315 TJm +(MTF) 20.4839 Tj +-314 TJm +(transform) 38.7361 Tj +-314 TJm +(for) 11.6169 Tj +-315 TJm +(lar) 10.511 Tj +18 TJm +(ge) 9.40507 Tj +-314 TJm +(MTF) 20.4839 Tj +-314 TJm +(v) 4.9815 Tj +25 TJm +(alues.) 22.9647 Tj +-504 TJm +(The) 15.4925 Tj +-314 TJm +(ne) 9.40507 Tj +25 TJm +(w) 7.19329 Tj +-315 TJm +(i) 2.76971 Tj +1 TJm +(mplementation) 59.778 Tj +-315 TJm +(is) 6.64532 Tj +-314 TJm +(based) 22.6858 Tj +-314 TJm +(on) 9.963 Tj +-315 TJm +(the) 12.1748 Tj +-314 TJm +(notion) 25.4654 Tj +-315 TJm +(of) 8.29918 Tj +-314 TJm +(sliding) 27.1292 Tj +86.944 664.209 Td +(blocks) 26.0134 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(v) 4.9815 Tj +25 TJm +(alues.) 22.9647 Tj +[1 0 0 1 153.932 664.209] cm +0 g +0 G +[1 0 0 1 -81.932 -21.918] cm +0 g +0 G +[1 0 0 1 6.974 0] cm +0 g +0 G +[1 0 0 1 -78.974 -642.291] cm +[1 0 0 1 0 0] Tm +0 0 Td +78.974 642.291 Td +/F128_0 9.963 Tf +(\225) 3.48705 Tj +[1 0 0 1 82.461 642.291] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 1.993 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -86.944 -642.291] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 642.291 Td +/F130_0 9.963 Tf +(bzip2-0.9.0) 65.7558 Tj +[1 0 0 1 152.697 642.291] cm +0 g +0 G +[1 0 0 1 -152.697 -642.291] cm +[1 0 0 1 0 0] Tm +0 0 Td +155.412 642.291 Td +/F128_0 9.963 Tf +(no) 9.963 Tj +25 TJm +(w) 7.19329 Tj +-272 TJm +(reads) 21.0219 Tj +-273 TJm +(and) 14.3866 Tj +-272 TJm +(writes) 24.3496 Tj +-272 TJm +(\002les) 16.6083 Tj +-273 TJm +(with) 17.7142 Tj +[1 0 0 1 282.68 642.291] cm +0 g +0 G +[1 0 0 1 -282.68 -642.291] cm +[1 0 0 1 0 0] Tm +0 0 Td +282.68 642.291 Td +/F130_0 9.963 Tf +(fread) 29.889 Tj +[1 0 0 1 312.568 642.291] cm +0 g +0 G +[1 0 0 1 -312.568 -642.291] cm +[1 0 0 1 0 0] Tm +0 0 Td +315.282 642.291 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 332.383 642.291] cm +0 g +0 G +[1 0 0 1 -332.383 -642.291] cm +[1 0 0 1 0 0] Tm +0 0 Td +332.383 642.291 Td +/F130_0 9.963 Tf +(fwrite) 35.8668 Tj +[1 0 0 1 368.248 642.291] cm +0 g +0 G +[1 0 0 1 -368.248 -642.291] cm +[1 0 0 1 0 0] Tm +0 0 Td +368.248 642.291 Td +/F128_0 9.963 Tf +(;) 2.76971 Tj +-284 TJm +(v) 4.9815 Tj +15 TJm +(ersion) 24.3496 Tj +-272 TJm +(0.1) 12.4538 Tj +-272 TJm +(used) 18.2622 Tj +[1 0 0 1 441.882 642.291] cm +0 g +0 G +[1 0 0 1 -441.882 -642.291] cm +[1 0 0 1 0 0] Tm +0 0 Td +441.882 642.291 Td +/F130_0 9.963 Tf +(putc) 23.9112 Tj +[1 0 0 1 465.792 642.291] cm +0 g +0 G +[1 0 0 1 -465.792 -642.291] cm +[1 0 0 1 0 0] Tm +0 0 Td +468.507 642.291 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 485.607 642.291] cm +0 g +0 G +[1 0 0 1 -485.607 -642.291] cm +[1 0 0 1 0 0] Tm +0 0 Td +485.607 642.291 Td +/F130_0 9.963 Tf +(getc) 23.9112 Tj +[1 0 0 1 509.517 642.291] cm +0 g +0 G +[1 0 0 1 -509.517 -642.291] cm +[1 0 0 1 0 0] Tm +0 0 Td +509.517 642.291 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +-755 TJm +(Duh!) 20.474 Tj +86.944 630.336 Td +(W) 9.40507 Tj +80 TJm +(ell,) 12.4538 Tj +-250 TJm +(you) 14.9445 Tj +-250 TJm +(li) 5.53943 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-250 TJm +(and) 14.3866 Tj +-250 TJm +(learn.) 22.4068 Tj +[1 0 0 1 184.248 630.336] cm +0 g +0 G +[1 0 0 1 -112.248 -12.119] cm +0 g +0 G +[1 0 0 1 -72 -618.217] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 608.418 Td +/F128_0 9.963 Tf +(Further) 29.3311 Tj +-304 TJm +(ahead,) 25.7245 Tj +-318 TJm +(it) 5.53943 Tj +-305 TJm +(w) 7.19329 Tj +10 TJm +(ould) 17.7142 Tj +-304 TJm +(be) 9.40507 Tj +-304 TJm +(nice) 16.5984 Tj +-305 TJm +(to) 7.75121 Tj +-304 TJm +(be) 9.40507 Tj +-304 TJm +(able) 16.5984 Tj +-305 TJm +(to) 7.75121 Tj +-304 TJm +(do) 9.963 Tj +-305 TJm +(random) 30.437 Tj +-304 TJm +(access) 25.4455 Tj +-304 TJm +(into) 15.5024 Tj +-305 TJm +(\002l) 8.30914 Tj +1 TJm +(es.) 10.7899 Tj +-947 TJm +(This) 17.7142 Tj +-304 TJm +(will) 15.5024 Tj +-305 TJm +(require) 28.2152 Tj +-304 TJm +(some) 21.0319 Tj +-304 TJm +(careful) 27.6573 Tj +-305 TJm +(design) 26.0134 Tj +-304 TJm +(of) 8.29918 Tj +72 596.463 Td +(compressed) 47.0353 Tj +-250 TJm +(\002le) 12.7327 Tj +-250 TJm +(formats.) 32.9277 Tj +[1 0 0 1 72 594.306] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -584.344] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 561.71 Td +/F121_0 20.659 Tf +(4.2.) 34.4592 Tj +-278 TJm +(P) 13.7796 Tj +40 TJm +(or) 20.659 Tj +-20 TJm +(tability) 66.584 Tj +-278 TJm +(issues) 64.3115 Tj +[1 0 0 1 72 557.434] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -547.472] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 539.793 Td +/F128_0 9.963 Tf +(After) 21.0219 Tj +-250 TJm +(some) 21.0319 Tj +-250 TJm +(consideration,) 56.1714 Tj +-250 TJm +(I) 3.31768 Tj +-250 TJm +(h) 4.9815 Tj +1 TJm +(a) 4.42357 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-250 TJm +(decided) 30.9849 Tj +-250 TJm +(not) 12.7327 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(use) 13.2807 Tj +-250 TJm +(GNU) 21.5799 Tj +[1 0 0 1 303.231 539.793] cm +0 g +0 G +[1 0 0 1 -303.231 -539.793] cm +[1 0 0 1 0 0] Tm +0 0 Td +303.231 539.793 Td +/F130_0 9.963 Tf +(autoconf) 47.8224 Tj +[1 0 0 1 351.052 539.793] cm +0 g +0 G +[1 0 0 1 -351.052 -539.793] cm +[1 0 0 1 0 0] Tm +0 0 Td +353.542 539.793 Td +/F128_0 9.963 Tf +(to) 7.75121 Tj +-250 TJm +(con\002gure) 37.6303 Tj +-250 TJm +(0.9.5) 19.926 Tj +-250 TJm +(or) 8.29918 Tj +-250 TJm +(1.0.) 14.9445 Tj +[1 0 0 1 72 537.636] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -527.673] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 517.875 Td +/F130_0 9.963 Tf +(autoconf) 47.8224 Tj +[1 0 0 1 119.821 517.875] cm +0 g +0 G +[1 0 0 1 -119.821 -517.875] cm +[1 0 0 1 0 0] Tm +0 0 Td +119.821 517.875 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-502 TJm +(admirable) 39.842 Tj +-452 TJm +(and) 14.3866 Tj +-452 TJm +(w) 7.19329 Tj +10 TJm +(onderful) 33.7546 Tj +-452 TJm +(though) 27.6772 Tj +-451 TJm +(it) 5.53943 Tj +-452 TJm +(is,) 9.13607 Tj +-503 TJm +(mainly) 27.6772 Tj +-451 TJm +(assists) 25.4654 Tj +-452 TJm +(with) 17.7142 Tj +-452 TJm +(portability) 41.5158 Tj +-452 TJm +(problems) 37.0823 Tj +-451 TJm +(between) 33.1967 Tj +-452 TJm +(Unix-lik) 33.7646 Tj +10 TJm +(e) 4.42357 Tj +72 505.92 Td +(platforms.) 40.6789 Tj +-1398 TJm +(But) 14.3965 Tj +[1 0 0 1 144.784 505.92] cm +0 g +0 G +[1 0 0 1 -144.784 -505.92] cm +[1 0 0 1 0 0] Tm +0 0 Td +144.784 505.92 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 174.672 505.92] cm +0 g +0 G +[1 0 0 1 -174.672 -505.92] cm +[1 0 0 1 0 0] Tm +0 0 Td +178.455 505.92 Td +/F128_0 9.963 Tf +(doesn') 26.5614 Tj +18 TJm +(t) 2.76971 Tj +-380 TJm +(ha) 9.40507 Tj +20 TJm +(v) 4.9815 Tj +16 TJm +(e) 4.42357 Tj +-380 TJm +(much) 22.1378 Tj +-380 TJm +(in) 7.75121 Tj +-379 TJm +(the) 12.1748 Tj +-380 TJm +(w) 7.19329 Tj +10 TJm +(ay) 9.40507 Tj +-380 TJm +(of) 8.29918 Tj +-379 TJm +(portability) 41.5158 Tj +-380 TJm +(problems) 37.0823 Tj +-379 TJm +(on) 9.963 Tj +-380 TJm +(Unix;) 22.6957 Tj +-444 TJm +(most) 19.378 Tj +-380 TJm +(of) 8.29918 Tj +-379 TJm +(the) 12.1748 Tj +-380 TJm +(dif) 11.0689 Tj +25 TJm +(\002culties) 31.5528 Tj +72 493.964 Td +(appear) 26.5514 Tj +-297 TJm +(when) 21.5799 Tj +-296 TJm +(porting) 28.7831 Tj +-297 TJm +(to) 7.75121 Tj +-297 TJm +(the) 12.1748 Tj +-296 TJm +(Mac,) 20.195 Tj +-309 TJm +(or) 8.29918 Tj +-296 TJm +(to) 7.75121 Tj +-297 TJm +(Microsoft') 42.6118 Tj +55 TJm +(s) 3.87561 Tj +-297 TJm +(oper) 17.7043 Tj +1 TJm +(ating) 19.926 Tj +-297 TJm +(systems.) 34.0436 Tj +[1 0 0 1 361.339 493.964] cm +0 g +0 G +[1 0 0 1 -361.339 -493.964] cm +[1 0 0 1 0 0] Tm +0 0 Td +361.339 493.964 Td +/F130_0 9.963 Tf +(autoconf) 47.8224 Tj +[1 0 0 1 409.16 493.964] cm +0 g +0 G +[1 0 0 1 -409.16 -493.964] cm +[1 0 0 1 0 0] Tm +0 0 Td +412.116 493.964 Td +/F128_0 9.963 Tf +(doesn') 26.5614 Tj +18 TJm +(t) 2.76971 Tj +-297 TJm +(help) 17.1563 Tj +-296 TJm +(in) 7.75121 Tj +-297 TJm +(those) 21.0319 Tj +-297 TJm +(cases,) 23.5127 Tj +-308 TJm +(and) 14.3866 Tj +72 482.009 Td +(brings) 24.9075 Tj +-250 TJm +(in) 7.75121 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(whole) 24.3496 Tj +-250 TJm +(load) 17.1563 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(ne) 9.40507 Tj +25 TJm +(w) 7.19329 Tj +-250 TJm +(c) 4.42357 Tj +1 TJm +(omple) 24.9075 Tj +15 TJm +(xity) 15.5024 Tj +65 TJm +(.) 2.49075 Tj +[1 0 0 1 72 479.852] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -469.89] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 460.091 Td +/F128_0 9.963 Tf +(Most) 20.4839 Tj +-392 TJm +(people) 26.5614 Tj +-392 TJm +(should) 26.5713 Tj +-392 TJm +(be) 9.40507 Tj +-393 TJm +(able) 16.5984 Tj +-392 TJm +(to) 7.75121 Tj +-392 TJm +(compile) 32.1008 Tj +-392 TJm +(the) 12.1748 Tj +-392 TJm +(library) 26.5614 Tj +-392 TJm +(and) 14.3866 Tj +-393 TJm +(prog) 18.2622 Tj +1 TJm +(ram) 15.4925 Tj +-393 TJm +(under) 22.6858 Tj +-392 TJm +(Unix) 19.926 Tj +-392 TJm +(straight) 29.889 Tj +-392 TJm +(out-of-the-box,) 60.595 Tj +-428 TJm +(so) 8.85711 Tj +-392 TJm +(to) 7.75121 Tj +-392 TJm +(speak,) 25.1765 Tj +72 448.136 Td +(especially) 39.842 Tj +-250 TJm +(if) 6.08739 Tj +-250 TJm +(you) 14.9445 Tj +-250 TJm +(ha) 9.40507 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(v) 4.9815 Tj +15 TJm +(ersio) 19.3681 Tj +1 TJm +(n) 4.9815 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(GNU) 21.5799 Tj +-250 TJm +(C) 6.64532 Tj +-250 TJm +(a) 4.42357 Tj +20 TJm +(v) 4.9815 Tj +25 TJm +(ailable.) 29.0521 Tj +[1 0 0 1 72 445.979] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -436.017] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 426.218 Td +/F128_0 9.963 Tf +(There) 23.2337 Tj +-258 TJm +(are) 12.1648 Tj +-259 TJm +(a) 4.42357 Tj +-259 TJm +(coupl) 22.1378 Tj +1 TJm +(e) 4.42357 Tj +-259 TJm +(of) 8.29918 Tj +[1 0 0 1 159.561 426.218] cm +0 g +0 G +[1 0 0 1 -159.561 -426.218] cm +[1 0 0 1 0 0] Tm +0 0 Td +159.561 426.218 Td +/F130_0 9.963 Tf +(__inline__) 59.778 Tj +[1 0 0 1 219.337 426.218] cm +0 g +0 G +[1 0 0 1 -219.337 -426.218] cm +[1 0 0 1 0 0] Tm +0 0 Td +221.913 426.218 Td +/F128_0 9.963 Tf +(directi) 25.4555 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(es) 8.29918 Tj +-258 TJm +(in) 7.75121 Tj +-259 TJm +(the) 12.1748 Tj +-258 TJm +(code.) 21.3009 Tj +-672 TJm +(GNU) 21.5799 Tj +-258 TJm +(C) 6.64532 Tj +-259 TJm +(\() 3.31768 Tj +[1 0 0 1 352.587 426.218] cm +0 g +0 G +[1 0 0 1 -352.587 -426.218] cm +[1 0 0 1 0 0] Tm +0 0 Td +352.587 426.218 Td +/F130_0 9.963 Tf +(gcc) 17.9334 Tj +[1 0 0 1 370.52 426.218] cm +0 g +0 G +[1 0 0 1 -370.52 -426.218] cm +[1 0 0 1 0 0] Tm +0 0 Td +370.52 426.218 Td +/F128_0 9.963 Tf +(\)) 3.31768 Tj +-259 TJm +(sho) 13.8386 Tj +1 TJm +(uld) 12.7327 Tj +-259 TJm +(be) 9.40507 Tj +-259 TJm +(able) 16.5984 Tj +-258 TJm +(to) 7.75121 Tj +-259 TJm +(handle) 26.5614 Tj +-258 TJm +(them.) 22.4168 Tj +-672 TJm +(If) 6.63536 Tj +-258 TJm +(you') 18.2622 Tj +50 TJm +(re) 7.74125 Tj +72 414.263 Td +(not) 12.7327 Tj +-279 TJm +(using) 21.5898 Tj +-279 TJm +(GNU) 21.5799 Tj +-279 TJm +(C,) 9.13607 Tj +-279 TJm +(your) 18.2622 Tj +-279 TJm +(C) 6.64532 Tj +-279 TJm +(compile) 32.1008 Tj +1 TJm +(r) 3.31768 Tj +-279 TJm +(shouldn') 34.8705 Tj +18 TJm +(t) 2.76971 Tj +-279 TJm +(see) 12.7228 Tj +-279 TJm +(them) 19.926 Tj +-279 TJm +(at) 7.19329 Tj +-279 TJm +(all.) 12.4538 Tj +-794 TJm +(If) 6.63536 Tj +-279 TJm +(your) 18.2622 Tj +-279 TJm +(compiler) 35.4185 Tj +-279 TJm +(does,) 20.7529 Tj +-286 TJm +(for) 11.6169 Tj +-279 TJm +(some) 21.0319 Tj +-279 TJm +(reason,) 28.4942 Tj +-286 TJm +(see) 12.7228 Tj +-279 TJm +(them) 19.926 Tj +-279 TJm +(and) 14.3866 Tj +72 402.308 Td +(doesn') 26.5614 Tj +18 TJm +(t) 2.76971 Tj +-283 TJm +(lik) 10.5209 Tj +10 TJm +(e) 4.42357 Tj +-283 TJm +(them,) 22.4168 Tj +-291 TJm +(just) 14.3965 Tj +[1 0 0 1 164.167 402.308] cm +0 g +0 G +[1 0 0 1 -164.167 -402.308] cm +[1 0 0 1 0 0] Tm +0 0 Td +164.167 402.308 Td +/F130_0 9.963 Tf +(#define) 41.8446 Tj +[1 0 0 1 206.01 402.308] cm +0 g +0 G +[1 0 0 1 2.819 0] cm +0 g +0 G +[1 0 0 1 -208.829 -402.308] cm +[1 0 0 1 0 0] Tm +0 0 Td +208.829 402.308 Td +/F130_0 9.963 Tf +(__inline__) 59.778 Tj +[1 0 0 1 268.605 402.308] cm +0 g +0 G +[1 0 0 1 -268.605 -402.308] cm +[1 0 0 1 0 0] Tm +0 0 Td +271.425 402.308 Td +/F128_0 9.963 Tf +(to) 7.75121 Tj +-283 TJm +(be) 9.40507 Tj +[1 0 0 1 294.22 402.308] cm +0 g +0 G +[1 0 0 1 -294.22 -402.308] cm +[1 0 0 1 0 0] Tm +0 0 Td +294.22 402.308 Td +/F130_0 9.963 Tf +(/*) 11.9556 Tj +-600 TJm +(*/) 11.9556 Tj +[1 0 0 1 324.108 402.308] cm +0 g +0 G +[1 0 0 1 -324.108 -402.308] cm +[1 0 0 1 0 0] Tm +0 0 Td +324.108 402.308 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +-818 TJm +(One) 16.5984 Tj +-283 TJm +(easy) 17.7043 Tj +-283 TJm +(w) 7.19329 Tj +10 TJm +(ay) 9.40507 Tj +-283 TJm +(to) 7.75121 Tj +-283 TJm +(do) 9.963 Tj +-283 TJm +(this) 14.3965 Tj +-283 TJm +(is) 6.64532 Tj +-283 TJm +(to) 7.75121 Tj +-283 TJm +(compile) 32.1008 Tj +-283 TJm +(with) 17.7142 Tj +-283 TJm +(th) 7.75121 Tj +1 TJm +(e) 4.42357 Tj +-283 TJm +(\003ag) 14.9445 Tj +[1 0 0 1 72 390.353] cm +0 g +0 G +[1 0 0 1 -72 -390.353] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 390.353 Td +/F130_0 9.963 Tf +(-D__inline__=) 77.7114 Tj +[1 0 0 1 149.709 390.353] cm +0 g +0 G +[1 0 0 1 -149.709 -390.353] cm +[1 0 0 1 0 0] Tm +0 0 Td +149.709 390.353 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-250 TJm +(which) 24.3496 Tj +-250 TJm +(should) 26.5713 Tj +-250 TJm +(be) 9.40507 Tj +-250 TJm +(understood) 44.2756 Tj +-249 TJm +(by) 9.963 Tj +-250 TJm +(most) 19.378 Tj +-250 TJm +(Unix) 19.926 Tj +-250 TJm +(compilers.) 41.7848 Tj +[1 0 0 1 72 388.196] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -378.234] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 368.435 Td +/F128_0 9.963 Tf +(If) 6.63536 Tj +-321 TJm +(you) 14.9445 Tj +-321 TJm +(still) 14.9545 Tj +-321 TJm +(ha) 9.40507 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-322 TJm +(dif) 11.0689 Tj +25 TJm +(\002cul) 17.7142 Tj +1 TJm +(ties,) 16.3294 Tj +-339 TJm +(try) 11.0689 Tj +-322 TJm +(compi) 24.9075 Tj +1 TJm +(ling) 15.5024 Tj +-322 TJm +(with) 17.7142 Tj +-321 TJm +(the) 12.1748 Tj +-321 TJm +(macro) 24.8975 Tj +[1 0 0 1 310.295 368.435] cm +0 g +0 G +[1 0 0 1 -310.295 -368.435] cm +[1 0 0 1 0 0] Tm +0 0 Td +310.295 368.435 Td +/F130_0 9.963 Tf +(BZ_STRICT_ANSI) 83.6892 Tj +[1 0 0 1 393.981 368.435] cm +0 g +0 G +[1 0 0 1 -393.981 -368.435] cm +[1 0 0 1 0 0] Tm +0 0 Td +397.18 368.435 Td +/F128_0 9.963 Tf +(de\002ned.) 31.8218 Tj +-524 TJm +(This) 17.7142 Tj +-321 TJm +(should) 26.5713 Tj +-321 TJm +(enable) 26.0034 Tj +-321 TJm +(you) 14.9445 Tj +-321 TJm +(to) 7.75121 Tj +72 356.48 Td +(b) 4.9815 Tj +20 TJm +(uild) 15.5024 Tj +-321 TJm +(the) 12.1748 Tj +-321 TJm +(library) 26.5614 Tj +-321 TJm +(in) 7.75121 Tj +-322 TJm +(a) 4.42357 Tj +-321 TJm +(strictly) 27.6772 Tj +-321 TJm +(ANSI) 23.2437 Tj +-321 TJm +(compliant) 39.852 Tj +-321 TJm +(en) 9.40507 Tj +40 TJm +(vironment.) 43.4486 Tj +-1047 TJm +(Building) 34.8805 Tj +-321 TJm +(the) 12.1748 Tj +-321 TJm +(program) 33.7546 Tj +-321 TJm +(itself) 19.926 Tj +-321 TJm +(lik) 10.5209 Tj +10 TJm +(e) 4.42357 Tj +-322 TJm +(this) 14.3965 Tj +-321 TJm +(is) 6.64532 Tj +-321 TJm +(dangerous) 40.9479 Tj +-321 TJm +(and) 14.3866 Tj +72 344.525 Td +(not) 12.7327 Tj +-260 TJm +(supported,) 41.7848 Tj +-263 TJm +(since) 20.474 Tj +-260 TJm +(you) 14.9445 Tj +-260 TJm +(remo) 20.474 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +[1 0 0 1 204.498 344.525] cm +0 g +0 G +[1 0 0 1 -204.498 -344.525] cm +[1 0 0 1 0 0] Tm +0 0 Td +204.498 344.525 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 234.385 344.525] cm +0 g +0 G +[1 0 0 1 -234.385 -344.525] cm +[1 0 0 1 0 0] Tm +0 0 Td +234.385 344.525 Td +/F128_0 9.963 Tf +(') 3.31768 Tj +55 TJm +(s) 3.87561 Tj +-260 TJm +(checks) 27.1093 Tj +-260 TJm +(ag) 9.40507 Tj +5 TJm +(ainst) 18.8201 Tj +-260 TJm +(compressing) 50.363 Tj +-260 TJm +(directories,) 44.5446 Tj +-263 TJm +(symbolic) 36.5343 Tj +-260 TJm +(links,) 21.8688 Tj +-262 TJm +(de) 9.40507 Tj +25 TJm +(vices,) 22.9647 Tj +-263 TJm +(and) 14.3866 Tj +-260 TJm +(other) 20.474 Tj +72 332.57 Td +(not-really-a-\002le) 62.5278 Tj +-250 TJm +(entities.) 31.2739 Tj +-619 TJm +(This) 17.7142 Tj +-250 TJm +(could) 22.1378 Tj +-250 TJm +(cause) 22.1278 Tj +-250 TJm +(\002lesystem) 40.4099 Tj +-250 TJm +(corruption!) 44.8235 Tj +[1 0 0 1 72 330.413] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -320.45] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 310.652 Td +/F128_0 9.963 Tf +(One) 16.5984 Tj +-392 TJm +(othe) 17.1563 Tj +1 TJm +(r) 3.31768 Tj +-392 TJm +(thing:) 23.2536 Tj +-593 TJm +(if) 6.08739 Tj +-392 TJm +(you) 14.9445 Tj +-391 TJm +(create) 23.7817 Tj +-392 TJm +(a) 4.42357 Tj +[1 0 0 1 210.879 310.652] cm +0 g +0 G +[1 0 0 1 -210.879 -310.652] cm +[1 0 0 1 0 0] Tm +0 0 Td +210.879 310.652 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 240.767 310.652] cm +0 g +0 G +[1 0 0 1 -240.767 -310.652] cm +[1 0 0 1 0 0] Tm +0 0 Td +244.669 310.652 Td +/F128_0 9.963 Tf +(binary) 25.4555 Tj +-392 TJm +(fo) 8.29918 Tj +1 TJm +(r) 3.31768 Tj +-392 TJm +(public) 24.9075 Tj +-392 TJm +(distrib) 25.4654 Tj +20 TJm +(u) 4.9815 Tj +1 TJm +(tion,) 17.9932 Tj +-427 TJm +(please) 24.8975 Tj +-392 TJm +(consider) 33.7546 Tj +-391 TJm +(linking) 28.2351 Tj +-392 TJm +(it) 5.53943 Tj +-392 TJm +(s) 3.87561 Tj +1 TJm +(tatically) 32.1008 Tj +-392 TJm +(\() 3.31768 Tj +[1 0 0 1 522.067 310.652] cm +0 g +0 G +[1 0 0 1 -522.067 -310.652] cm +[1 0 0 1 0 0] Tm +0 0 Td +522.067 310.652 Td +/F130_0 9.963 Tf +(gcc) 17.9334 Tj +72 298.697 Td +(-static) 41.8446 Tj +[1 0 0 1 113.843 298.697] cm +0 g +0 G +[1 0 0 1 -113.843 -298.697] cm +[1 0 0 1 0 0] Tm +0 0 Td +113.843 298.697 Td +/F128_0 9.963 Tf +(\).) 5.80843 Tj +-620 TJm +(This) 17.7142 Tj +-250 TJm +(a) 4.42357 Tj +20 TJm +(v) 4.9815 Tj +20 TJm +(oids) 16.6083 Tj +-250 TJm +(all) 9.963 Tj +-250 TJm +(sorts) 18.8201 Tj +-250 TJm +(of) 8.29918 Tj +-250 TJm +(lib) 10.5209 Tj +1 TJm +(rary-v) 24.3396 Tj +15 TJm +(ersion) 24.3496 Tj +-250 TJm +(issues) 23.8016 Tj +-250 TJm +(that) 14.9445 Tj +-250 TJm +(others) 24.3496 Tj +-250 TJm +(may) 17.1563 Tj +-250 TJm +(encounter) 39.2841 Tj +-250 TJm +(later) 17.7043 Tj +-250 TJm +(on.) 12.4538 Tj +[1 0 0 1 72 296.54] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -286.577] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 276.779 Td +/F128_0 9.963 Tf +(If) 6.63536 Tj +-296 TJm +(you) 14.9445 Tj +-296 TJm +(b) 4.9815 Tj +20 TJm +(uild) 15.5024 Tj +[1 0 0 1 122.708 276.779] cm +0 g +0 G +[1 0 0 1 -122.708 -276.779] cm +[1 0 0 1 0 0] Tm +0 0 Td +122.708 276.779 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 152.596 276.779] cm +0 g +0 G +[1 0 0 1 -152.596 -276.779] cm +[1 0 0 1 0 0] Tm +0 0 Td +155.545 276.779 Td +/F128_0 9.963 Tf +(on) 9.963 Tj +-296 TJm +(W) 9.40507 Tj +40 TJm +(in32,) 20.205 Tj +-307 TJm +(you) 14.9445 Tj +-296 TJm +(must) 19.378 Tj +-296 TJm +(set) 11.0689 Tj +[1 0 0 1 254.965 276.779] cm +0 g +0 G +[1 0 0 1 -254.965 -276.779] cm +[1 0 0 1 0 0] Tm +0 0 Td +254.965 276.779 Td +/F130_0 9.963 Tf +(BZ_UNIX) 41.8446 Tj +[1 0 0 1 296.808 276.779] cm +0 g +0 G +[1 0 0 1 -296.808 -276.779] cm +[1 0 0 1 0 0] Tm +0 0 Td +299.756 276.779 Td +/F128_0 9.963 Tf +(to) 7.75121 Tj +-296 TJm +(0) 4.9815 Tj +-296 TJm +(and) 14.3866 Tj +[1 0 0 1 335.72 276.779] cm +0 g +0 G +[1 0 0 1 -335.72 -276.779] cm +[1 0 0 1 0 0] Tm +0 0 Td +335.72 276.779 Td +/F130_0 9.963 Tf +(BZ_LCCWIN32) 65.7558 Tj +[1 0 0 1 401.473 276.779] cm +0 g +0 G +[1 0 0 1 -401.473 -276.779] cm +[1 0 0 1 0 0] Tm +0 0 Td +404.422 276.779 Td +/F128_0 9.963 Tf +(to) 7.75121 Tj +-296 TJm +(1,) 7.47225 Tj +-307 TJm +(in) 7.75121 Tj +-296 TJm +(the) 12.1748 Tj +-296 TJm +(\002le) 12.7327 Tj +[1 0 0 1 467.159 276.779] cm +0 g +0 G +[1 0 0 1 -467.159 -276.779] cm +[1 0 0 1 0 0] Tm +0 0 Td +467.159 276.779 Td +/F130_0 9.963 Tf +(bzip2.c) 41.8446 Tj +[1 0 0 1 509.002 276.779] cm +0 g +0 G +[1 0 0 1 -509.002 -276.779] cm +[1 0 0 1 0 0] Tm +0 0 Td +509.002 276.779 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-307 TJm +(before) 25.4455 Tj +72 264.824 Td +(compiling.) 42.9007 Tj +-310 TJm +(Otherwise) 40.9479 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(re) 7.74125 Tj +1 TJm +(sulting) 27.1292 Tj +-250 TJm +(binary) 25.4555 Tj +-250 TJm +(w) 7.19329 Tj +10 TJm +(on') 13.2807 Tj +18 TJm +(t) 2.76971 Tj +-250 TJm +(w) 7.19329 Tj +10 TJm +(ork) 13.2807 Tj +-250 TJm +(correctly) 35.4085 Tj +65 TJm +(.) 2.49075 Tj +[1 0 0 1 72 262.667] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -252.704] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 230.071 Td +/F121_0 20.659 Tf +(4.3.) 34.4592 Tj +-278 TJm +(Repor) 59.6839 Tj +-20 TJm +(ting) 37.8679 Tj +-278 TJm +(b) 12.6226 Tj +20 TJm +(ugs) 36.7317 Tj +[1 0 0 1 72 225.475] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -215.512] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 208.153 Td +/F128_0 9.963 Tf +(I) 3.31768 Tj +-228 TJm +(tried) 18.2622 Tj +-228 TJm +(pretty) 23.2437 Tj +-228 TJm +(hard) 17.7043 Tj +-228 TJm +(t) 2.76971 Tj +1 TJm +(o) 4.9815 Tj +-228 TJm +(mak) 17.1563 Tj +10 TJm +(e) 4.42357 Tj +-228 TJm +(sure) 16.5984 Tj +[1 0 0 1 196.25 208.153] cm +0 g +0 G +[1 0 0 1 -196.25 -208.153] cm +[1 0 0 1 0 0] Tm +0 0 Td +196.25 208.153 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 226.138 208.153] cm +0 g +0 G +[1 0 0 1 -226.138 -208.153] cm +[1 0 0 1 0 0] Tm +0 0 Td +228.409 208.153 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-228 TJm +(b) 4.9815 Tj +20 TJm +(ug) 9.963 Tj +-228 TJm +(free,) 17.9733 Tj +-232 TJm +(both) 17.7142 Tj +-228 TJm +(by) 9.963 Tj +-228 TJm +(design) 26.0134 Tj +-228 TJm +(and) 14.3866 Tj +-228 TJm +(by) 9.963 Tj +-228 TJm +(te) 7.19329 Tj +1 TJm +(sting.) 21.8688 Tj +-606 TJm +(Hopefully) 40.4 Tj +-227 TJm +(you') 18.2622 Tj +10 TJm +(ll) 5.53943 Tj +-228 TJm +(ne) 9.40507 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(er) 7.74125 Tj +-228 TJm +(need) 18.8101 Tj +-228 TJm +(to) 7.75121 Tj +-228 TJm +(read) 17.1463 Tj +72 196.198 Td +(this) 14.3965 Tj +-250 TJm +(section) 28.2252 Tj +-250 TJm +(for) 11.6169 Tj +-250 TJm +(real.) 17.4253 Tj +[1 0 0 1 72 196.098] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -186.136] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 174.28 Td +/F128_0 9.963 Tf +(Ne) 11.6169 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(ertheless,) 37.3513 Tj +-313 TJm +(if) 6.08739 Tj +[1 0 0 1 137.751 174.28] cm +0 g +0 G +[1 0 0 1 -137.751 -174.28] cm +[1 0 0 1 0 0] Tm +0 0 Td +137.751 174.28 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 167.639 174.28] cm +0 g +0 G +[1 0 0 1 -167.639 -174.28] cm +[1 0 0 1 0 0] Tm +0 0 Td +170.634 174.28 Td +/F128_0 9.963 Tf +(dies) 16.0504 Tj +-301 TJm +(w) 7.19329 Tj +1 TJm +(ith) 10.5209 Tj +-301 TJm +(a) 4.42357 Tj +-301 TJm +(se) 8.29918 Tj +15 TJm +(gm) 12.7327 Tj +1 TJm +(entation) 32.1008 Tj +-301 TJm +(f) 3.31768 Tj +10 TJm +(ault,) 17.4353 Tj +-313 TJm +(a) 4.42357 Tj +-301 TJm +(b) 4.9815 Tj +20 TJm +(us) 8.85711 Tj +-300 TJm +(error) 19.3581 Tj +-301 TJm +(or) 8.29918 Tj +-300 TJm +(an) 9.40507 Tj +-301 TJm +(internal) 30.437 Tj +-300 TJm +(assertion) 35.4185 Tj +-301 TJm +(f) 3.31768 Tj +10 TJm +(ailure,) 25.1765 Tj +-313 TJm +(it) 5.53943 Tj +-300 TJm +(will) 15.5024 Tj +-301 TJm +(ask) 13.2807 Tj +-300 TJm +(you) 14.9445 Tj +-301 TJm +(to) 7.75121 Tj +72 162.325 Td +(email) 22.1378 Tj +-242 TJm +(me) 12.1748 Tj +-243 TJm +(a) 4.42357 Tj +-242 TJm +(b) 4.9815 Tj +20 TJm +(ug) 9.963 Tj +-243 TJm +(r) 3.31768 Tj +1 TJm +(eport.) 22.9647 Tj +-615 TJm +(Experience) 44.8136 Tj +-243 TJm +(from) 19.3681 Tj +-242 TJm +(years) 21.0219 Tj +-242 TJm +(of) 8.29918 Tj +-243 TJm +(feedback) 35.9565 Tj +-242 TJm +(of) 8.29918 Tj +-242 TJm +(bzip2) 22.1378 Tj +-243 TJm +(users) 20.474 Tj +-242 TJm +(indicates) 35.4185 Tj +-242 TJm +(that) 14.9445 Tj +-243 TJm +(almost) 26.5713 Tj +-242 TJm +(all) 9.963 Tj +-242 TJm +(these) 20.474 Tj +-243 TJm +(problems) 37.0823 Tj +-242 TJm +(can) 13.8286 Tj +72 150.37 Td +(be) 9.40507 Tj +-250 TJm +(traced) 24.3396 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(either) 22.6858 Tj +-250 TJm +(compiler) 35.4185 Tj +-249 TJm +(b) 4.9815 Tj +20 TJm +(ugs) 13.8386 Tj +-250 TJm +(or) 8.29918 Tj +-250 TJm +(hardw) 24.8975 Tj +10 TJm +(are) 12.1648 Tj +-250 TJm +(problems.) 39.573 Tj +[1 0 0 1 72 148.213] cm +0 g +0 G +[1 0 0 1 0 -97.361] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.854] cm +0 g +0 G +0 g +0 G +[1 0 0 1 40.572 -6.755] cm +0 g +0 G +[1 0 0 1 -493.841 -50.951] cm +[1 0 0 1 0 0] Tm +0 0 Td +534.414 50.951 Td +/F128_0 9.963 Tf +(32) 9.963 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 36 36 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 -6.854] cm +0 g +0 G +[1 0 0 1 0 6.854] cm +0 g +0 G +0 g +0 G +[1 0 0 1 116.329 -6.755] cm +0 g +0 G +[1 0 0 1 -382.4 -749.245] cm +[1 0 0 1 0 0] Tm +0 0 Td +498.728 749.245 Td +/F128_0 9.963 Tf +(Miscellanea) 48.1412 Tj +[1 0 0 1 266.071 749.146] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -7.094] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -468 -31.517] cm +0 g +0 G +[1 0 0 1 6.974 0] cm +0 g +0 G +[1 0 0 1 -78.974 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +78.974 710.037 Td +/F128_0 9.963 Tf +(\225) 3.48705 Tj +[1 0 0 1 82.461 710.037] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 1.993 0] cm +0 g +0 G +[1 0 0 1 -86.944 -710.037] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 710.037 Td +/F128_0 9.963 Tf +(Recompile) 43.1697 Tj +-306 TJm +(the) 12.1748 Tj +-306 TJm +(program) 33.7546 Tj +-306 TJm +(with) 17.7142 Tj +-305 TJm +(no) 9.963 Tj +-306 TJm +(optimisation,) 52.3157 Tj +-320 TJm +(and) 14.3866 Tj +-306 TJm +(see) 12.7228 Tj +-306 TJm +(if) 6.08739 Tj +-306 TJm +(it) 5.53943 Tj +-306 TJm +(w) 7.19329 Tj +10 TJm +(orks.) 19.647 Tj +-956 TJm +(And/or) 28.2252 Tj +-306 TJm +(try) 11.0689 Tj +-306 TJm +(a) 4.42357 Tj +-306 TJm +(dif) 11.0689 Tj +25 TJm +(fe) 7.74125 Tj +1 TJm +(rent) 15.4925 Tj +-306 TJm +(compiler) 35.4185 Tj +55 TJm +(.) 2.49075 Tj +-956 TJm +(I) 3.31768 Tj +-306 TJm +(heard) 22.1278 Tj +-306 TJm +(all) 9.963 Tj +86.944 698.082 Td +(sorts) 18.8201 Tj +-282 TJm +(of) 8.29918 Tj +-282 TJm +(stories) 26.0134 Tj +-282 TJm +(about) 22.1378 Tj +-282 TJm +(v) 4.9815 Tj +25 TJm +(arious) 24.3496 Tj +-282 TJm +(\003a) 9.963 Tj +20 TJm +(v) 4.9815 Tj +20 TJm +(ours) 17.1563 Tj +-282 TJm +(of) 8.29918 Tj +-282 TJm +(GNU) 21.5799 Tj +-282 TJm +(C) 6.64532 Tj +-283 TJm +(\(a) 7.74125 Tj +1 TJm +(nd) 9.963 Tj +-283 TJm +(other) 20.474 Tj +-282 TJm +(compiler) 35.4185 Tj +1 TJm +(s\)) 7.19329 Tj +-283 TJm +(genera) 26.5514 Tj +1 TJm +(ting) 15.5024 Tj +-283 TJm +(bad) 14.3866 Tj +-282 TJm +(code) 18.8101 Tj +-282 TJm +(for) 11.6169 Tj +[1 0 0 1 472.141 698.082] cm +0 g +0 G +[1 0 0 1 -472.141 -698.082] cm +[1 0 0 1 0 0] Tm +0 0 Td +472.141 698.082 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 502.029 698.082] cm +0 g +0 G +[1 0 0 1 -502.029 -698.082] cm +[1 0 0 1 0 0] Tm +0 0 Td +502.029 698.082 Td +/F128_0 9.963 Tf +(,) 2.49075 Tj +-290 TJm +(and) 14.3866 Tj +-282 TJm +(I') 6.63536 Tj +50 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +86.944 686.127 Td +(run) 13.2807 Tj +-250 TJm +(across) 24.8975 Tj +-250 TJm +(tw) 9.963 Tj +10 TJm +(o) 4.9815 Tj +-250 TJm +(such) 18.2622 Tj +-250 TJm +(e) 4.42357 Tj +15 TJm +(xamples) 33.2067 Tj +-249 TJm +(myself.) 29.61 Tj +[1 0 0 1 237.767 686.127] cm +0 g +0 G +[1 0 0 1 -165.767 -12.119] cm +0 g +0 G +[1 0 0 1 -72 -674.008] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 664.209 Td +/F128_0 9.963 Tf +(2.7.X) 22.1378 Tj +-279 TJm +(v) 4.9815 Tj +15 TJm +(ersions) 28.2252 Tj +-280 TJm +(of) 8.29918 Tj +-279 TJm +(GNU) 21.5799 Tj +-280 TJm +(C) 6.64532 Tj +-279 TJm +(are) 12.1648 Tj +-280 TJm +(kno) 14.9445 Tj +25 TJm +(wn) 12.1748 Tj +-279 TJm +(to) 7.75121 Tj +-280 TJm +(generate) 33.7447 Tj +-279 TJm +(bad) 14.3866 Tj +-280 TJm +(code) 18.8101 Tj +-279 TJm +(from) 19.3681 Tj +-280 TJm +(time) 17.7142 Tj +-279 TJm +(to) 7.75121 Tj +-280 TJm +(time,) 20.205 Tj +-287 TJm +(at) 7.19329 Tj +-279 TJm +(high) 17.7142 Tj +-280 TJm +(optimisation) 49.825 Tj +-279 TJm +(le) 7.19329 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(els.) 13.5596 Tj +-797 TJm +(If) 6.63536 Tj +-280 TJm +(you) 14.9445 Tj +86.944 652.254 Td +(get) 12.1748 Tj +-295 TJm +(problems,) 39.573 Tj +-307 TJm +(try) 11.0689 Tj +-296 TJm +(u) 4.9815 Tj +1 TJm +(sing) 16.6083 Tj +-296 TJm +(the) 12.1748 Tj +-295 TJm +(\003ags) 18.8201 Tj +[1 0 0 1 220.116 652.254] cm +0 g +0 G +[1 0 0 1 -220.116 -652.254] cm +[1 0 0 1 0 0] Tm +0 0 Td +220.116 652.254 Td +/F130_0 9.963 Tf +(-O2) 17.9334 Tj +[1 0 0 1 238.049 652.254] cm +0 g +0 G +[1 0 0 1 2.944 0] cm +0 g +0 G +[1 0 0 1 -240.993 -652.254] cm +[1 0 0 1 0 0] Tm +0 0 Td +240.993 652.254 Td +/F130_0 9.963 Tf +(-fomit-frame-pointer) 119.556 Tj +[1 0 0 1 360.544 652.254] cm +0 g +0 G +[1 0 0 1 2.944 0] cm +0 g +0 G +[1 0 0 1 -363.488 -652.254] cm +[1 0 0 1 0 0] Tm +0 0 Td +363.488 652.254 Td +/F130_0 9.963 Tf +(-fno-strength-reduce) 119.556 Tj +[1 0 0 1 483.04 652.254] cm +0 g +0 G +[1 0 0 1 -483.04 -652.254] cm +[1 0 0 1 0 0] Tm +0 0 Td +483.04 652.254 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +-893 TJm +(Y) 7.19329 Tj +110 TJm +(ou) 9.963 Tj +-295 TJm +(should) 26.5713 Tj +86.944 640.299 Td +(speci\002cally) 45.3815 Tj +[1 0 0 1 134.814 640.299] cm +0 g +0 G +[1 0 0 1 -134.814 -640.299] cm +[1 0 0 1 0 0] Tm +0 0 Td +134.814 640.299 Td +/F631_0 9.963 Tf +(not) 12.7327 Tj +[1 0 0 1 147.546 640.299] cm +0 g +0 G +[1 0 0 1 -147.546 -640.299] cm +[1 0 0 1 0 0] Tm +0 0 Td +150.037 640.299 Td +/F128_0 9.963 Tf +(use) 13.2807 Tj +[1 0 0 1 165.807 640.299] cm +0 g +0 G +[1 0 0 1 -165.807 -640.299] cm +[1 0 0 1 0 0] Tm +0 0 Td +165.807 640.299 Td +/F130_0 9.963 Tf +(-funroll-loops) 83.6892 Tj +[1 0 0 1 249.493 640.299] cm +0 g +0 G +[1 0 0 1 -249.493 -640.299] cm +[1 0 0 1 0 0] Tm +0 0 Td +249.493 640.299 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +[1 0 0 1 72 638.142] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -628.179] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 618.381 Td +/F128_0 9.963 Tf +(Y) 7.19329 Tj +110 TJm +(ou) 9.963 Tj +-249 TJm +(may) 17.1563 Tj +-248 TJm +(notice) 24.3496 Tj +-249 TJm +(that) 14.9445 Tj +-249 TJm +(the) 12.1748 Tj +-249 TJm +(M) 8.85711 Tj +1 TJm +(ak) 9.40507 Tj +10 TJm +(e\002le) 17.1563 Tj +-249 TJm +(runs) 17.1563 Tj +-249 TJm +(six) 11.6268 Tj +-249 TJm +(test) 13.8386 Tj +1 TJm +(s) 3.87561 Tj +-249 TJm +(as) 8.29918 Tj +-249 TJm +(part) 15.4925 Tj +-249 TJm +(of) 8.29918 Tj +-248 TJm +(the) 12.1748 Tj +-249 TJm +(b) 4.9815 Tj +20 TJm +(uild) 15.5024 Tj +-249 TJm +(process.) 32.3698 Tj +-619 TJm +(If) 6.63536 Tj +-249 TJm +(the) 12.1748 Tj +-248 TJm +(program) 33.7546 Tj +-249 TJm +(passes) 25.4555 Tj +-249 TJm +(all) 9.963 Tj +-248 TJm +(of) 8.29918 Tj +-249 TJm +(these,) 22.9647 Tj +-249 TJm +(it') 8.85711 Tj +55 TJm +(s) 3.87561 Tj +86.944 606.426 Td +(a) 4.42357 Tj +-250 TJm +(pretty) 23.2437 Tj +-250 TJm +(good) 19.926 Tj +-250 TJm +(\(b) 8.29918 Tj +20 TJm +(ut) 7.75121 Tj +-250 TJm +(not) 12.7327 Tj +-250 TJm +(100%\)) 26.5614 Tj +-250 TJm +(in) 7.75121 Tj +1 TJm +(dication) 32.1008 Tj +-250 TJm +(that) 14.9445 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(compiler) 35.4185 Tj +-250 TJm +(has) 13.2807 Tj +-250 TJm +(done) 19.3681 Tj +-250 TJm +(its) 9.41504 Tj +-250 TJm +(job) 12.7327 Tj +-250 TJm +(correctly) 35.4085 Tj +65 TJm +(.) 2.49075 Tj +[1 0 0 1 72 604.269] cm +0 g +0 G +[1 0 0 1 0 -19.761] cm +0 g +0 G +[1 0 0 1 6.974 0] cm +0 g +0 G +[1 0 0 1 -78.974 -584.508] cm +[1 0 0 1 0 0] Tm +0 0 Td +78.974 584.508 Td +/F128_0 9.963 Tf +(\225) 3.48705 Tj +[1 0 0 1 82.461 584.508] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 1.993 0] cm +0 g +0 G +[1 0 0 1 -86.944 -584.508] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 584.508 Td +/F128_0 9.963 Tf +(If) 6.63536 Tj +[1 0 0 1 95.956 584.508] cm +0 g +0 G +[1 0 0 1 -95.956 -584.508] cm +[1 0 0 1 0 0] Tm +0 0 Td +95.956 584.508 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 125.844 584.508] cm +0 g +0 G +[1 0 0 1 -125.844 -584.508] cm +[1 0 0 1 0 0] Tm +0 0 Td +128.22 584.508 Td +/F128_0 9.963 Tf +(crashes) 29.3211 Tj +-238 TJm +(randomly) 38.1882 Tj +65 TJm +(,) 2.49075 Tj +-241 TJm +(and) 14.3866 Tj +-239 TJm +(the) 12.1748 Tj +-238 TJm +(crashes) 29.3211 Tj +-239 TJm +(are) 12.1648 Tj +-238 TJm +(not) 12.7327 Tj +-239 TJm +(repea) 21.5699 Tj +1 TJm +(table,) 21.8588 Tj +-241 TJm +(you) 14.9445 Tj +-239 TJm +(may) 17.1563 Tj +-238 TJm +(ha) 9.40507 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-239 TJm +(a) 4.42357 Tj +-238 TJm +(\003ak) 14.9445 Tj +15 TJm +(y) 4.9815 Tj +-239 TJm +(memory) 33.2067 Tj +-238 TJm +(subsystem.) 44.0066 Tj +[1 0 0 1 510.112 584.508] cm +0 g +0 G +[1 0 0 1 -510.112 -584.508] cm +[1 0 0 1 0 0] Tm +0 0 Td +510.112 584.508 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 540 584.508] cm +0 g +0 G +[1 0 0 1 -540 -584.508] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 572.553 Td +/F128_0 9.963 Tf +(really) 22.6858 Tj +-253 TJm +(hammers) 36.5244 Tj +-254 TJm +(your) 18.2622 Tj +-253 TJm +(memory) 33.2067 Tj +-254 TJm +(hierarch) 32.6388 Tj +5 TJm +(y) 4.9815 Tj +65 TJm +(,) 2.49075 Tj +-254 TJm +(and) 14.3866 Tj +-254 TJm +(if) 6.08739 Tj +-253 TJm +(it') 8.85711 Tj +55 TJm +(s) 3.87561 Tj +-254 TJm +(a) 4.42357 Tj +-253 TJm +(bit) 10.5209 Tj +-254 TJm +(mar) 15.4925 Tj +18 TJm +(ginal,) 22.4168 Tj +-254 TJm +(you) 14.9445 Tj +-254 TJm +(may) 17.1563 Tj +-253 TJm +(get) 12.1748 Tj +-254 TJm +(these) 20.474 Tj +-253 TJm +(problems.) 39.573 Tj +-642 TJm +(D) 7.19329 Tj +1 TJm +(itto) 13.2906 Tj +-254 TJm +(if) 6.08739 Tj +-254 TJm +(you) 14.9445 Tj +1 TJm +(r) 3.31768 Tj +-254 TJm +(disk) 16.6083 Tj +86.944 560.598 Td +(or) 8.29918 Tj +-250 TJm +(I/O) 13.2807 Tj +-250 TJm +(subsystem) 41.5158 Tj +-250 TJm +(is) 6.64532 Tj +-250 TJm +(slo) 11.6268 Tj +25 TJm +(wly) 14.9445 Tj +-249 TJm +(f) 3.31768 Tj +10 TJm +(ailing.) 25.1865 Tj +-620 TJm +(Y) 7.19329 Tj +111 TJm +(up,) 12.4538 Tj +-250 TJm +(this) 14.3965 Tj +-250 TJm +(really) 22.6858 Tj +-250 TJm +(does) 18.2622 Tj +-250 TJm +(happen.) 31.2639 Tj +[1 0 0 1 345.143 560.598] cm +0 g +0 G +[1 0 0 1 -273.143 -12.12] cm +0 g +0 G +[1 0 0 1 -72 -548.478] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 538.68 Td +/F128_0 9.963 Tf +(T) 6.08739 Tj +35 TJm +(ry) 8.29918 Tj +-250 TJm +(using) 21.5898 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(dif) 11.0689 Tj +25 TJm +(ferent) 23.2337 Tj +-250 TJm +(machine) 33.7546 Tj +-249 TJm +(of) 8.29918 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(same) 20.474 Tj +-250 TJm +(type,) 19.647 Tj +-250 TJm +(and) 14.3866 Tj +-250 TJm +(see) 12.7228 Tj +-250 TJm +(if) 6.08739 Tj +-250 TJm +(you) 14.9445 Tj +-250 TJm +(can) 13.8286 Tj +-250 TJm +(repeat) 24.3396 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(problem.) 35.6974 Tj +[1 0 0 1 72 536.523] cm +0 g +0 G +[1 0 0 1 0 -19.761] cm +0 g +0 G +[1 0 0 1 6.974 0] cm +0 g +0 G +[1 0 0 1 -78.974 -516.762] cm +[1 0 0 1 0 0] Tm +0 0 Td +78.974 516.762 Td +/F128_0 9.963 Tf +(\225) 3.48705 Tj +[1 0 0 1 82.461 516.762] cm +0 g +0 G +[1 0 0 1 2.49 0] cm +0 g +0 G +[1 0 0 1 1.993 0] cm +0 g +0 G +[1 0 0 1 -86.944 -516.762] cm +[1 0 0 1 0 0] Tm +0 0 Td +86.944 516.762 Td +/F128_0 9.963 Tf +(This) 17.7142 Tj +-229 TJm +(isn') 14.9445 Tj +18 TJm +(t) 2.76971 Tj +-230 TJm +(real) 14.9345 Tj +1 TJm +(ly) 7.75121 Tj +-230 TJm +(a) 4.42357 Tj +-229 TJm +(b) 4.9815 Tj +20 TJm +(ug,) 12.4538 Tj +-234 TJm +(b) 4.9815 Tj +20 TJm +(ut) 7.75121 Tj +-229 TJm +(...) 7.47225 Tj +-303 TJm +(If) 6.63536 Tj +[1 0 0 1 212.232 516.762] cm +0 g +0 G +[1 0 0 1 -212.232 -516.762] cm +[1 0 0 1 0 0] Tm +0 0 Td +212.232 516.762 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 242.12 516.762] cm +0 g +0 G +[1 0 0 1 -242.12 -516.762] cm +[1 0 0 1 0 0] Tm +0 0 Td +244.405 516.762 Td +/F128_0 9.963 Tf +(tells) 16.6083 Tj +-229 TJm +(you) 14.9445 Tj +-230 TJm +(your) 18.2622 Tj +-229 TJm +(\002le) 12.7327 Tj +-229 TJm +(is) 6.64532 Tj +-229 TJm +(corrupted) 38.1782 Tj +-230 TJm +(on) 9.963 Tj +-229 TJm +(decompression,) 62.2588 Tj +-233 TJm +(and) 14.3866 Tj +-230 TJm +(you) 14.9445 Tj +-229 TJm +(obtained) 34.3126 Tj +-229 TJm +(the) 12.1748 Tj +-229 TJm +(\002le) 12.7327 Tj +86.944 504.807 Td +(via) 12.1748 Tj +-262 TJm +(FTP) 17.1662 Tj +111 TJm +(,) 2.49075 Tj +-262 TJm +(there) 19.916 Tj +-263 TJm +(is) 6.64532 Tj +-262 TJm +(a) 4.42357 Tj +-262 TJm +(possibility) 41.5258 Tj +-262 TJm +(that) 14.9445 Tj +-263 TJm +(y) 4.9815 Tj +1 TJm +(ou) 9.963 Tj +-263 TJm +(for) 11.6169 Tj +18 TJm +(got) 12.7327 Tj +-262 TJm +(to) 7.75121 Tj +-262 TJm +(tell) 12.7327 Tj +-262 TJm +(FTP) 17.1662 Tj +-263 TJm +(to) 7.75121 Tj +-262 TJm +(do) 9.963 Tj +-262 TJm +(a) 4.42357 Tj +-262 TJm +(binary) 25.4555 Tj +-263 TJm +(mode) 22.1378 Tj +-262 TJm +(transfer) 30.427 Tj +55 TJm +(.) 2.49075 Tj +-694 TJm +(Th) 11.0689 Tj +1 TJm +(at) 7.19329 Tj +-263 TJm +(absolutely) 40.9579 Tj +-262 TJm +(will) 15.5024 Tj +-262 TJm +(cause) 22.1278 Tj +86.944 492.852 Td +(the) 12.1748 Tj +-250 TJm +(\002le) 12.7327 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(be) 9.40507 Tj +-250 TJm +(non-decompress) 65.2975 Tj +1 TJm +(ible.) 17.4353 Tj +-620 TJm +(Y) 7.19329 Tj +110 TJm +(ou') 13.2807 Tj +10 TJm +(ll) 5.53943 Tj +-250 TJm +(ha) 9.40507 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(transfer) 30.427 Tj +-250 TJm +(it) 5.53943 Tj +-250 TJm +(ag) 9.40507 Tj +5 TJm +(ain.) 14.6655 Tj +[1 0 0 1 351.34 492.852] cm +0 g +0 G +[1 0 0 1 -279.34 -12.12] cm +0 g +0 G +[1 0 0 1 -72 -480.732] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 470.934 Td +/F128_0 9.963 Tf +(If) 6.63536 Tj +-235 TJm +(you') 18.2622 Tj +50 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-235 TJm +(incorporated) 50.353 Tj +[1 0 0 1 163.036 470.934] cm +0 g +0 G +[1 0 0 1 -163.036 -470.934] cm +[1 0 0 1 0 0] Tm +0 0 Td +163.036 470.934 Td +/F130_0 9.963 Tf +(libbzip2) 47.8224 Tj +[1 0 0 1 210.856 470.934] cm +0 g +0 G +[1 0 0 1 -210.856 -470.934] cm +[1 0 0 1 0 0] Tm +0 0 Td +213.2 470.934 Td +/F128_0 9.963 Tf +(into) 15.5024 Tj +-235 TJm +(your) 18.2622 Tj +-235 TJm +(o) 4.9815 Tj +25 TJm +(wn) 12.1748 Tj +-236 TJm +(prog) 18.2622 Tj +1 TJm +(ram) 15.4925 Tj +-236 TJm +(and) 14.3866 Tj +-235 TJm +(are) 12.1648 Tj +-235 TJm +(getting) 27.6772 Tj +-235 TJm +(problems,) 39.573 Tj +-238 TJm +(please,) 27.3883 Tj +-238 TJm +(please,) 27.3883 Tj +-238 TJm +(please,) 27.3883 Tj +-238 TJm +(check) 23.2337 Tj +-236 TJm +(t) 2.76971 Tj +1 TJm +(hat) 12.1748 Tj +72 458.979 Td +(the) 12.1748 Tj +-242 TJm +(parameters) 43.7077 Tj +-242 TJm +(you) 14.9445 Tj +-243 TJm +(are) 12.1648 Tj +-242 TJm +(passing) 29.889 Tj +-242 TJm +(in) 7.75121 Tj +-243 TJm +(calls) 18.2622 Tj +-242 TJm +(to) 7.75121 Tj +-242 TJm +(the) 12.1748 Tj +-242 TJm +(library) 26.5614 Tj +65 TJm +(,) 2.49075 Tj +-244 TJm +(are) 12.1648 Tj +-243 TJm +(co) 9.40507 Tj +1 TJm +(rrect,) 20.743 Tj +-244 TJm +(and) 14.3866 Tj +-243 TJm +(in) 7.75121 Tj +-242 TJm +(accordance) 44.8036 Tj +-242 TJm +(with) 17.7142 Tj +-242 TJm +(what) 19.3681 Tj +-243 TJm +(the) 12.1748 Tj +-242 TJm +(documentation) 59.2201 Tj +-242 TJm +(says) 17.1563 Tj +72 447.024 Td +(is) 6.64532 Tj +-250 TJm +(allo) 14.9445 Tj +25 TJm +(w) 7.19329 Tj +10 TJm +(able.) 19.0891 Tj +-310 TJm +(I) 3.31768 Tj +-250 TJm +(ha) 9.40507 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-250 TJm +(tried) 18.2622 Tj +-250 TJm +(to) 7.75121 Tj +-250 TJm +(m) 7.75121 Tj +1 TJm +(ak) 9.40507 Tj +10 TJm +(e) 4.42357 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(library) 26.5614 Tj +-250 TJm +(rob) 13.2807 Tj +20 TJm +(ust) 11.6268 Tj +-250 TJm +(ag) 9.40507 Tj +5 TJm +(ainst) 18.8201 Tj +-250 TJm +(such) 18.2622 Tj +-250 TJm +(problems,) 39.573 Tj +-250 TJm +(b) 4.9815 Tj +20 TJm +(ut) 7.75121 Tj +-250 TJm +(I'm) 14.3866 Tj +-250 TJm +(sur) 12.1748 Tj +1 TJm +(e) 4.42357 Tj +-250 TJm +(I) 3.31768 Tj +-250 TJm +(ha) 9.40507 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(en') 12.7228 Tj +18 TJm +(t) 2.76971 Tj +-250 TJm +(succeeded.) 43.4287 Tj +[1 0 0 1 72 444.867] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -434.904] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 425.106 Td +/F128_0 9.963 Tf +(Finally) 28.2351 Tj +65 TJm +(,) 2.49075 Tj +-324 TJm +(if) 6.08739 Tj +-309 TJm +(the) 12.1748 Tj +-310 TJm +(abo) 14.3866 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-309 TJm +(comments) 40.9579 Tj +-309 TJm +(don') 18.2622 Tj +18 TJm +(t) 2.76971 Tj +-309 TJm +(help,) 19.647 Tj +-325 TJm +(you') 18.2622 Tj +11 TJm +(ll) 5.53943 Tj +-310 TJm +(ha) 9.40507 Tj +20 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-309 TJm +(to) 7.75121 Tj +-309 TJm +(send) 18.2622 Tj +-310 TJm +(me) 12.1748 Tj +-309 TJm +(a) 4.42357 Tj +-309 TJm +(b) 4.9815 Tj +20 TJm +(ug) 9.963 Tj +-310 TJm +(report.) 26.2824 Tj +-976 TJm +(No) 12.1748 Tj +25 TJm +(w) 7.19329 Tj +65 TJm +(,) 2.49075 Tj +-324 TJm +(it') 8.85711 Tj +55 TJm +(s) 3.87561 Tj +-309 TJm +(just) 14.3965 Tj +-309 TJm +(amazing) 33.7546 Tj +-310 TJm +(ho) 9.963 Tj +25 TJm +(w) 7.19329 Tj +-309 TJm +(man) 17.1563 Tj +15 TJm +(y) 4.9815 Tj +72 413.151 Td +(people) 26.5614 Tj +-250 TJm +(will) 15.5024 Tj +-250 TJm +(send) 18.2622 Tj +-250 TJm +(me) 12.1748 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(b) 4.9815 Tj +20 TJm +(ug) 9.963 Tj +-250 TJm +(rep) 12.7228 Tj +1 TJm +(ort) 11.0689 Tj +-250 TJm +(saying) 26.0134 Tj +-250 TJm +(something) 41.5158 Tj +-250 TJm +(lik) 10.5209 Tj +10 TJm +(e:) 7.19329 Tj +[1 0 0 1 72 410.994] cm +0 g +0 G +[1 0 0 1 0 -24.907] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 23.91 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 20.324] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -401.629] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 401.629 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +-426 TJm +(crashed) 41.8446 Tj +-426 TJm +(with) 23.9112 Tj +-426 TJm +(segmen) 35.8668 Tj +1 TJm +(tation) 35.8668 Tj +-426 TJm +(fault) 29.889 Tj +-426 TJm +(on) 11.9556 Tj +-426 TJm +(my) 11.9556 Tj +-426 TJm +(machine) 41.8446 Tj +[1 0 0 1 72 386.087] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.549] cm +0 g +0 G +[1 0 0 1 -72 -376.125] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 364.169 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +-241 TJm +(absolutely) 40.9579 Tj +-240 TJm +(nothing) 30.4469 Tj +-241 TJm +(else.) 17.9832 Tj +-614 TJm +(Needless) 35.9664 Tj +-241 TJm +(to) 7.75121 Tj +-240 TJm +(say) 13.2807 Tj +65 TJm +(,) 2.49075 Tj +-243 TJm +(a) 4.42357 Tj +-241 TJm +(such) 18.2622 Tj +-241 TJm +(a) 4.42357 Tj +-240 TJm +(report) 23.7916 Tj +-241 TJm +(is) 6.64532 Tj +[1 0 0 1 324.681 364.169] cm +0 g +0 G +[1 0 0 1 -324.681 -364.169] cm +[1 0 0 1 0 0] Tm +0 0 Td +324.681 364.169 Td +/F631_0 9.963 Tf +(totally) 25.4654 Tj +55 TJm +(,) 2.49075 Tj +-243 TJm +(u) 4.9815 Tj +1 TJm +(tterly) 21.0319 Tj +55 TJm +(,) 2.49075 Tj +-243 TJm +(completely) 43.1597 Tj +-241 TJm +(and) 14.9445 Tj +-240 TJm +(compr) 25.4555 Tj +37 TJm +(ehensively) 41.4959 Tj +-241 TJm +(100%) 23.2437 Tj +72 352.214 Td +(useless;) 31.5429 Tj +-257 TJm +(a) 4.9815 Tj +-255 TJm +(waste) 22.6957 Tj +-255 TJm +(of) 7.75121 Tj +-255 TJm +(your) 18.2622 Tj +-255 TJm +(time) 17.1563 Tj +10 TJm +(,) 2.49075 Tj +-256 TJm +(my) 11.6169 Tj +-255 TJm +(t) 2.76971 Tj +1 TJm +(ime) 14.3866 Tj +10 TJm +(,) 2.49075 Tj +-257 TJm +(and) 14.9445 Tj +-254 TJm +(net) 12.1748 Tj +-255 TJm +(bandwidth) 42.0737 Tj +[1 0 0 1 302.574 352.214] cm +0 g +0 G +[1 0 0 1 -302.574 -352.214] cm +[1 0 0 1 0 0] Tm +0 0 Td +302.574 352.214 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +-649 TJm +(W) 9.40507 Tj +40 TJm +(ith) 10.5209 Tj +-255 TJm +(no) 9.963 Tj +-255 TJm +(details) 26.0134 Tj +-255 TJm +(at) 7.19329 Tj +-255 TJm +(all,) 12.4538 Tj +-256 TJm +(there') 23.2337 Tj +55 TJm +(s) 3.87561 Tj +-255 TJm +(no) 9.963 Tj +-255 TJm +(w) 7.19329 Tj +10 TJm +(ay) 9.40507 Tj +-254 TJm +(I) 3.31768 Tj +-255 TJm +(can) 13.8286 Tj +-255 TJm +(possibly) 33.2166 Tj +-255 TJm +(be) 9.40507 Tj +15 TJm +(gin) 12.7327 Tj +72 340.259 Td +(to) 7.75121 Tj +-250 TJm +(\002gure) 23.2437 Tj +-250 TJm +(out) 12.7327 Tj +-250 TJm +(what) 19.3681 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(problem) 33.2067 Tj +-249 TJm +(is.) 9.13607 Tj +[1 0 0 1 72 338.102] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -328.14] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 318.341 Td +/F128_0 9.963 Tf +(The) 15.4925 Tj +-309 TJm +(rules) 19.3681 Tj +-309 TJm +(of) 8.29918 Tj +-309 TJm +(the) 12.1748 Tj +-309 TJm +(g) 4.9815 Tj +5 TJm +(ame) 16.5984 Tj +-309 TJm +(are:) 14.9345 Tj +-429 TJm +(f) 3.31768 Tj +10 TJm +(ac) 8.84714 Tj +1 TJm +(ts,) 9.13607 Tj +-324 TJm +(f) 3.31768 Tj +10 TJm +(acts,) 17.9832 Tj +-324 TJm +(f) 3.31768 Tj +10 TJm +(acts.) 17.9832 Tj +-975 TJm +(Don') 20.474 Tj +18 TJm +(t) 2.76971 Tj +-309 TJm +(omit) 18.2721 Tj +-309 TJm +(them) 19.926 Tj +-309 TJm +(because) 31.5329 Tj +-309 TJm +("oh,) 16.5187 Tj +-324 TJm +(the) 12.1748 Tj +15 TJm +(y) 4.9815 Tj +-309 TJm +(w) 7.19329 Tj +10 TJm +(on') 13.2807 Tj +18 TJm +(t) 2.76971 Tj +-309 TJm +(be) 9.40507 Tj +-309 TJm +(rele) 14.9345 Tj +25 TJm +(v) 4.9815 Tj +25 TJm +(ant".) 18.7304 Tj +-975 TJm +(At) 9.963 Tj +-309 TJm +(the) 12.1748 Tj +-309 TJm +(bare) 17.1463 Tj +72 306.386 Td +(minimum:) 41.5258 Tj +[1 0 0 1 72 306.287] cm +0 g +0 G +[1 0 0 1 0 -60.772] cm +0.949 0.949 0.97646 rg +0.949 0.949 0.97646 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 59.776 re +f +Q +0 g +0 G +[1 0 0 1 0 3.586] cm +0 g +0 G +[1 0 0 1 0 56.189] cm +0 g +0 G +[1 0 0 1 18 -8.368] cm +0 g +0 G +[1 0 0 1 -90 -296.922] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 296.922 Td +/F130_0 9.963 Tf +(Machine) 41.8446 Tj +-426 TJm +(type.) 29.889 Tj +-852 TJm +(Operating) 53.8002 Tj +-425 TJm +(system) 35.8668 Tj +-426 TJm +(version.) 47.8224 Tj +90 284.967 Td +(Exact) 29.889 Tj +-426 TJm +(version) 41.8446 Tj +-426 TJm +(of) 11.9556 Tj +-426 TJm +(bzip2) 29.889 Tj +-426 TJm +(\() 5.9778 Tj +1 TJm +(do) 11.9556 Tj +-426 TJm +(bzip2) 29.889 Tj +-426 TJm +(-V\).) 23.9112 Tj +90 273.011 Td +(Exact) 29.889 Tj +-426 TJm +(version) 41.8446 Tj +-426 TJm +(of) 11.9556 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(com) 17.9334 Tj +1 TJm +(piler) 29.889 Tj +-426 TJm +(used.) 29.889 Tj +90 261.056 Td +(Flags) 29.889 Tj +-426 TJm +(passed) 35.8668 Tj +-426 TJm +(to) 11.9556 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(comp) 23.9112 Tj +1 TJm +(iler.) 29.889 Tj +[1 0 0 1 72 245.514] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.549] cm +0 g +0 G +[1 0 0 1 -72 -235.552] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 223.597 Td +/F128_0 9.963 Tf +(Ho) 12.1748 Tj +25 TJm +(we) 11.6169 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(er) 7.74125 Tj +40 TJm +(,) 2.49075 Tj +-253 TJm +(the) 12.1748 Tj +-253 TJm +(most) 19.378 Tj +-253 TJm +(important) 38.7461 Tj +-252 TJm +(single) 23.8016 Tj +-253 TJm +(thing) 20.4839 Tj +-253 TJm +(that) 14.9445 Tj +-253 TJm +(will) 15.5024 Tj +-252 TJm +(help) 17.1563 Tj +-253 TJm +(me) 12.1748 Tj +-253 TJm +(is) 6.64532 Tj +-253 TJm +(the) 12.1748 Tj +-252 TJm +(\002le) 12.7327 Tj +-253 TJm +(that) 14.9445 Tj +-253 TJm +(you) 14.9445 Tj +-253 TJm +(we) 11.6169 Tj +1 TJm +(re) 7.74125 Tj +-253 TJm +(trying) 23.8016 Tj +-253 TJm +(to) 7.75121 Tj +-253 TJm +(compress) 37.6303 Tj +-252 TJm +(or) 8.29918 Tj +-253 TJm +(decompress) 47.0353 Tj +72 211.642 Td +(at) 7.19329 Tj +-304 TJm +(the) 12.1748 Tj +-305 TJm +(time) 17.7142 Tj +-304 TJm +(the) 12.1748 Tj +-304 TJm +(problem) 33.2067 Tj +-304 TJm +(happened.) 40.669 Tj +-946 TJm +(W) 9.40507 Tj +40 TJm +(ithout) 23.2536 Tj +-305 TJm +(that,) 17.4353 Tj +-317 TJm +(my) 12.7327 Tj +-305 TJm +(ability) 25.4654 Tj +-304 TJm +(to) 7.75121 Tj +-304 TJm +(do) 9.963 Tj +-305 TJm +(an) 9.40507 Tj +15 TJm +(ythin) 20.4839 Tj +1 TJm +(g) 4.9815 Tj +-305 TJm +(more) 20.474 Tj +-304 TJm +(than) 17.1563 Tj +-304 TJm +(speculate) 37.0723 Tj +-305 TJm +(abou) 19.3681 Tj +1 TJm +(t) 2.76971 Tj +-305 TJm +(the) 12.1748 Tj +-304 TJm +(cause,) 24.6186 Tj +-318 TJm +(is) 6.64532 Tj +72 199.686 Td +(limited.) 30.7259 Tj +[1 0 0 1 72 199.587] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -189.624] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 164.933 Td +/F121_0 20.659 Tf +(4.4.) 34.4592 Tj +-278 TJm +(Did) 33.2816 Tj +-278 TJm +(y) 11.4864 Tj +25 TJm +(ou) 25.2453 Tj +-278 TJm +(g) 12.6226 Tj +-10 TJm +(et) 18.3659 Tj +-278 TJm +(the) 30.9885 Tj +-278 TJm +(right) 45.9043 Tj +-278 TJm +(pac) 35.5955 Tj +20 TJm +(ka) 22.9728 Tj +11 TJm +(g) 12.6226 Tj +-10 TJm +(e?) 24.1091 Tj +[1 0 0 1 72 160.337] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -150.374] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 143.016 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 101.888 143.016] cm +0 g +0 G +[1 0 0 1 -101.888 -143.016] cm +[1 0 0 1 0 0] Tm +0 0 Td +104.603 143.016 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-272 TJm +(a) 4.42357 Tj +-273 TJm +(resource) 33.7447 Tj +-272 TJm +(hog.) 17.4353 Tj +-378 TJm +(It) 6.08739 Tj +-272 TJm +(soaks) 22.1378 Tj +-272 TJm +(up) 9.963 Tj +-273 TJm +(lar) 10.511 Tj +18 TJm +(ge) 9.40507 Tj +-272 TJm +(amounts) 33.7646 Tj +-273 TJm +(of) 8.29918 Tj +-272 TJm +(CPU) 19.378 Tj +-272 TJm +(c) 4.42357 Tj +15 TJm +(ycles) 20.474 Tj +-273 TJm +(and) 14.3866 Tj +-272 TJm +(memory) 33.2067 Tj +65 TJm +(.) 2.49075 Tj +-755 TJm +(Also,) 21.3109 Tj +-278 TJm +(it) 5.53943 Tj +-272 TJm +(gi) 7.75121 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(es) 8.29918 Tj +-273 TJm +(v) 4.9815 Tj +15 TJm +(ery) 12.7228 Tj +-272 TJm +(lar) 10.511 Tj +18 TJm +(ge) 9.40507 Tj +-273 TJm +(latencies.) 37.3513 Tj +72 131.061 Td +(In) 8.29918 Tj +-251 TJm +(the) 12.1748 Tj +-251 TJm +(w) 7.19329 Tj +10 TJm +(orst) 14.9445 Tj +-251 TJm +(case,) 19.6371 Tj +-251 TJm +(you) 14.9445 Tj +-251 TJm +(can) 13.8286 Tj +-251 TJm +(feed) 17.1463 Tj +-251 TJm +(man) 17.1563 Tj +15 TJm +(y) 4.9815 Tj +-251 TJm +(me) 12.1748 Tj +15 TJm +(g) 4.9815 Tj +5 TJm +(abytes) 25.4555 Tj +-251 TJm +(of) 8.29918 Tj +-251 TJm +(uncompressed) 56.9983 Tj +-251 TJm +(dat) 12.1748 Tj +1 TJm +(a) 4.42357 Tj +-251 TJm +(into) 15.5024 Tj +-251 TJm +(the) 12.1748 Tj +-251 TJm +(library) 26.5614 Tj +-251 TJm +(before) 25.4455 Tj +-251 TJm +(getting) 27.6772 Tj +-251 TJm +(an) 9.40507 Tj +15 TJm +(y) 4.9815 Tj +-251 TJm +(compressed) 47.0353 Tj +72 119.105 Td +(output,) 27.9562 Tj +-250 TJm +(so) 8.85711 Tj +-250 TJm +(this) 14.3965 Tj +-250 TJm +(probably) 35.4185 Tj +-250 TJm +(rules) 19.3681 Tj +-249 TJm +(out) 12.7327 Tj +-250 TJm +(applications) 48.1512 Tj +-250 TJm +(requiring) 36.5244 Tj +-250 TJm +(interacti) 32.6488 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +-250 TJm +(beha) 18.8101 Tj +20 TJm +(viour) 21.0319 Tj +55 TJm +(.) 2.49075 Tj +[1 0 0 1 72 116.949] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 -72 -106.986] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 97.188 Td +/F128_0 9.963 Tf +(These) 23.7916 Tj +-304 TJm +(aren') 20.464 Tj +18 TJm +(t) 2.76971 Tj +-304 TJm +(f) 3.31768 Tj +10 TJm +(aults) 18.8201 Tj +-304 TJm +(of) 8.29918 Tj +-304 TJm +(my) 12.7327 Tj +-304 TJm +(im) 10.5209 Tj +1 TJm +(plementation,) 54.5175 Tj +-318 TJm +(I) 3.31768 Tj +-304 TJm +(hope,) 21.8588 Tj +-317 TJm +(b) 4.9815 Tj +20 TJm +(ut) 7.75121 Tj +-304 TJm +(more) 20.474 Tj +-304 TJm +(an) 9.40507 Tj +-304 TJm +(intrinsic) 32.6587 Tj +-304 TJm +(property) 33.7546 Tj +-304 TJm +(of) 8.29918 Tj +-303 TJm +(the) 12.1748 Tj +-304 TJm +(Burro) 23.2437 Tj +25 TJm +(ws-Wheeler) 48.1313 Tj +-304 TJm +(transform) 38.7361 Tj +72 85.232 Td +(\(unfortunately\).) 62.8068 Tj +-620 TJm +(Maybe) 27.6673 Tj +-250 TJm +(this) 14.3965 Tj +-249 TJm +(isn') 14.9445 Tj +18 TJm +(t) 2.76971 Tj +-250 TJm +(what) 19.3681 Tj +-250 TJm +(you) 14.9445 Tj +-250 TJm +(w) 7.19329 Tj +10 TJm +(ant.) 14.6655 Tj +[1 0 0 1 72 83.076] cm +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +[1 0 0 1 0 -22.261] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.854] cm +0 g +0 G +0 g +0 G +[1 0 0 1 40.572 -6.755] cm +0 g +0 G +[1 0 0 1 -493.841 -50.951] cm +[1 0 0 1 0 0] Tm +0 0 Td +534.414 50.951 Td +/F128_0 9.963 Tf +(33) 9.963 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 37 37 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 -6.854] cm +0 g +0 G +[1 0 0 1 0 6.854] cm +0 g +0 G +0 g +0 G +[1 0 0 1 116.329 -6.755] cm +0 g +0 G +[1 0 0 1 -382.4 -749.245] cm +[1 0 0 1 0 0] Tm +0 0 Td +498.728 749.245 Td +/F128_0 9.963 Tf +(Miscellanea) 48.1412 Tj +[1 0 0 1 266.071 749.146] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -7.094] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -540 -741.554] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 710.037 Td +/F128_0 9.963 Tf +(If) 6.63536 Tj +-275 TJm +(you) 14.9445 Tj +-274 TJm +(w) 7.19329 Tj +10 TJm +(ant) 12.1748 Tj +-275 TJm +(a) 4.42357 Tj +-274 TJm +(compressor) 45.9294 Tj +-275 TJm +(and/or) 25.4555 Tj +-274 TJm +(library) 26.5614 Tj +-275 TJm +(which) 24.3496 Tj +-274 TJm +(is) 6.64532 Tj +-275 TJm +(f) 3.31768 Tj +10 TJm +(aster) 18.8101 Tj +40 TJm +(,) 2.49075 Tj +-280 TJm +(uses) 17.1563 Tj +-275 TJm +(less) 14.9445 Tj +-274 TJm +(memory) 33.2067 Tj +-275 TJm +(b) 4.9815 Tj +20 TJm +(ut) 7.75121 Tj +-274 TJm +(gets) 16.0504 Tj +-275 TJm +(pretty) 23.2437 Tj +-274 TJm +(good) 19.926 Tj +-275 TJm +(compression,) 52.8537 Tj +-280 TJm +(and) 14.3866 Tj +-275 TJm +(has) 13.2807 Tj +72 698.082 Td +(minimal) 33.2166 Tj +-288 TJm +(latenc) 23.7916 Tj +15 TJm +(y) 4.9815 Tj +65 TJm +(,) 2.49075 Tj +-297 TJm +(consider) 33.7546 Tj +-288 TJm +(Jean-lou) 33.7546 Tj +1 TJm +(p) 4.9815 Tj +-288 TJm +(Gailly') 28.2252 Tj +55 TJm +(s) 3.87561 Tj +-288 TJm +(and) 14.3866 Tj +-288 TJm +(Mark) 21.5799 Tj +-288 TJm +(Adler') 26.0034 Tj +55 TJm +(s) 3.87561 Tj +-287 TJm +(w) 7.19329 Tj +10 TJm +(ork,) 15.7714 Tj +[1 0 0 1 353.879 698.082] cm +0 g +0 G +[1 0 0 1 -353.879 -698.082] cm +[1 0 0 1 0 0] Tm +0 0 Td +353.879 698.082 Td +/F130_0 9.963 Tf +(zlib-1.2.1) 59.778 Tj +[1 0 0 1 413.655 698.082] cm +0 g +0 G +[1 0 0 1 -413.655 -698.082] cm +[1 0 0 1 0 0] Tm +0 0 Td +416.523 698.082 Td +/F128_0 9.963 Tf +(and) 14.3866 Tj +[1 0 0 1 433.777 698.082] cm +0 g +0 G +[1 0 0 1 -433.777 -698.082] cm +[1 0 0 1 0 0] Tm +0 0 Td +433.777 698.082 Td +/F130_0 9.963 Tf +(gzip-1.2.4) 59.778 Tj +[1 0 0 1 493.553 698.082] cm +0 g +0 G +[1 0 0 1 -493.553 -698.082] cm +[1 0 0 1 0 0] Tm +0 0 Td +493.553 698.082 Td +/F128_0 9.963 Tf +(.) 2.49075 Tj +-847 TJm +(Look) 21.0319 Tj +-288 TJm +(for) 11.6169 Tj +72 686.127 Td +(them) 19.926 Tj +-250 TJm +(at) 7.19329 Tj +-250 TJm +(http://www) 45.3914 Tj +65 TJm +(.zlib) 17.4353 Tj +40 TJm +(.or) 10.7899 Tj +18 TJm +(g) 4.9815 Tj +-250 TJm +(a) 4.42357 Tj +1 TJm +(nd) 9.963 Tj +-250 TJm +(http://www) 45.3914 Tj +65 TJm +(.gzip.or) 30.437 Tj +18 TJm +(g) 4.9815 Tj +-250 TJm +(respecti) 30.9849 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(ely) 12.1748 Tj +65 TJm +(.) 2.49075 Tj +[1 0 0 1 72 683.97] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -674.008] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 664.209 Td +/F128_0 9.963 Tf +(F) 5.53943 Tj +15 TJm +(or) 8.29918 Tj +-582 TJm +(something) 41.5158 Tj +-582 TJm +(f) 3.31768 Tj +10 TJm +(aster) 18.8101 Tj +-583 TJm +(and) 14.3866 Tj +-582 TJm +(lighter) 26.0134 Tj +-582 TJm +(still,) 17.4452 Tj +-665 TJm +(you) 14.9445 Tj +-583 TJm +(m) 7.75121 Tj +1 TJm +(ight) 15.5024 Tj +-583 TJm +(try) 11.0689 Tj +-582 TJm +(Markus) 30.437 Tj +-582 TJm +(F) 5.53943 Tj +-582 TJm +(X) 7.19329 Tj +-582 TJm +(J) 3.87561 Tj +-582 TJm +(Oberhumer') 48.6892 Tj +55 TJm +(s) 3.87561 Tj +[1 0 0 1 437.433 664.209] cm +0 g +0 G +[1 0 0 1 -437.433 -664.209] cm +[1 0 0 1 0 0] Tm +0 0 Td +437.433 664.209 Td +/F130_0 9.963 Tf +(LZO) 17.9334 Tj +[1 0 0 1 455.365 664.209] cm +0 g +0 G +[1 0 0 1 -455.365 -664.209] cm +[1 0 0 1 0 0] Tm +0 0 Td +461.164 664.209 Td +/F128_0 9.963 Tf +(real-time) 35.9664 Tj +-582 TJm +(compres-) 37.0723 Tj +72 652.254 Td +(sion/decompression) 79.1461 Tj +-250 TJm +(library) 26.5614 Tj +65 TJm +(,) 2.49075 Tj +-250 TJm +(a) 4.42357 Tj +1 TJm +(t) 2.76971 Tj +-250 TJm +(http://www) 45.3914 Tj +65 TJm +(.oberhumer) 45.6505 Tj +55 TJm +(.com/opensource.) 70.279 Tj +[1 0 0 1 72 650.097] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -640.135] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 617.501 Td +/F121_0 20.659 Tf +(4.5.) 34.4592 Tj +-278 TJm +(Fur) 33.2816 Tj +-20 TJm +(ther) 39.0249 Tj +-278 TJm +(Reading) 81.4998 Tj +[1 0 0 1 72 612.905] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 0 -9.963] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -72 -602.942] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 595.583 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 101.888 595.583] cm +0 g +0 G +[1 0 0 1 -101.888 -595.583] cm +[1 0 0 1 0 0] Tm +0 0 Td +104.923 595.583 Td +/F128_0 9.963 Tf +(is) 6.64532 Tj +-305 TJm +(n) 4.9815 Tj +1 TJm +(ot) 7.75121 Tj +-305 TJm +(research) 33.1868 Tj +-304 TJm +(w) 7.19329 Tj +10 TJm +(ork,) 15.7714 Tj +-319 TJm +(in) 7.75121 Tj +-304 TJm +(the) 12.1748 Tj +-305 TJm +(sense) 21.5799 Tj +-304 TJm +(that) 14.9445 Tj +-305 TJm +(it) 5.53943 Tj +-304 TJm +(doesn') 26.5614 Tj +18 TJm +(t) 2.76971 Tj +-305 TJm +(present) 28.7731 Tj +-304 TJm +(an) 9.40507 Tj +15 TJm +(y) 4.9815 Tj +-305 TJm +(ne) 9.40507 Tj +25 TJm +(w) 7.19329 Tj +-304 TJm +(ideas.) 22.9647 Tj +-474 TJm +(Rather) 26.5614 Tj +40 TJm +(,) 2.49075 Tj +-318 TJm +(it') 8.85711 Tj +55 TJm +(s) 3.87561 Tj +-305 TJm +(an) 9.40507 Tj +-304 TJm +(engineering) 47.0353 Tj +-305 TJm +(e) 4.42357 Tj +15 TJm +(x) 4.9815 Tj +15 TJm +(e) 4.42357 Tj +1 TJm +(rcise) 18.8101 Tj +72 583.628 Td +(based) 22.6858 Tj +-250 TJm +(on) 9.963 Tj +-250 TJm +(e) 4.42357 Tj +15 TJm +(xisting) 27.1292 Tj +-250 TJm +(ideas.) 22.9647 Tj +[1 0 0 1 72 581.471] cm +0 g +0 G +[1 0 0 1 0 -9.962] cm +0 g +0 G +[1 0 0 1 -72 -571.509] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 561.71 Td +/F128_0 9.963 Tf +(F) 5.53943 Tj +15 TJm +(our) 13.2807 Tj +-250 TJm +(documents) 43.1697 Tj +-250 TJm +(describe) 33.1967 Tj +-250 TJm +(esse) 16.5984 Tj +1 TJm +(ntially) 25.4654 Tj +-250 TJm +(all) 9.963 Tj +-250 TJm +(the) 12.1748 Tj +-250 TJm +(ideas) 20.474 Tj +-250 TJm +(behind) 27.1193 Tj +[1 0 0 1 298.747 561.71] cm +0 g +0 G +[1 0 0 1 -298.747 -561.71] cm +[1 0 0 1 0 0] Tm +0 0 Td +298.747 561.71 Td +/F130_0 9.963 Tf +(bzip2) 29.889 Tj +[1 0 0 1 328.635 561.71] cm +0 g +0 G +[1 0 0 1 -328.635 -561.71] cm +[1 0 0 1 0 0] Tm +0 0 Td +328.635 561.71 Td +/F128_0 9.963 Tf +(:) 2.76971 Tj +[1 0 0 1 72 559.554] cm +0 g +0 G +[1 0 0 1 0 -299.876] cm +0.9294 0.96861 0.95685 rg +0.9294 0.96861 0.95685 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 298.879 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 295.292] cm +0 g +0 G +[1 0 0 1 18 -8.368] cm +0 g +0 G +[1 0 0 1 -90 -550.189] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 550.189 Td +/F130_0 9.963 Tf +(Michael) 41.8446 Tj +-426 TJm +(Burrows) 41.8446 Tj +-426 TJm +(and) 17.9334 Tj +-426 TJm +(D.) 11.9556 Tj +-426 TJm +(J) 5.9778 Tj +1 TJm +(.) 5.9778 Tj +-426 TJm +(Wheeler:) 47.8224 Tj +98.488 538.234 Td +("A) 11.9556 Tj +-426 TJm +(block-sorting) 77.7114 Tj +-426 TJm +(lossless) 47.8224 Tj +-425 TJm +(data) 23.9112 Tj +-426 TJm +(compression) 65.7558 Tj +-426 TJm +(algorithm") 59.778 Tj +102.732 526.278 Td +(10th) 23.9112 Tj +-426 TJm +(May) 17.9334 Tj +-426 TJm +(1994.) 29.889 Tj +102.732 514.323 Td +(Digital) 41.8446 Tj +-426 TJm +(SRC) 17.9334 Tj +-426 TJm +(Research) 47.8224 Tj +-426 TJm +(Rep) 17.9334 Tj +1 TJm +(ort) 17.9334 Tj +-426 TJm +(124.) 23.9112 Tj +102.732 502.368 Td +(ftp://ftp.digital.com/pub) 149.445 Tj +1 TJm +(/DEC/SRC/research-reports/SRC-124.ps.gz) 233.134 Tj +102.732 490.413 Td +(If) 11.9556 Tj +-426 TJm +(you) 17.9334 Tj +-426 TJm +(have) 23.9112 Tj +-426 TJm +(trouble) 41.8446 Tj +-426 TJm +(find) 23.9112 Tj +1 TJm +(ing) 17.9334 Tj +-426 TJm +(it,) 17.9334 Tj +-426 TJm +(try) 17.9334 Tj +-426 TJm +(searching) 53.8002 Tj +-426 TJm +(at) 11.9556 Tj +-426 TJm +(the) 17.9334 Tj +102.732 478.458 Td +(New) 17.9334 Tj +-426 TJm +(Zealand) 41.8446 Tj +-426 TJm +(Digital) 41.8446 Tj +-426 TJm +(Libr) 23.9112 Tj +1 TJm +(ary,) 23.9112 Tj +-426 TJm +(http://www.nzdl.org.) 119.556 Tj +90 454.547 Td +(Daniel) 35.8668 Tj +-426 TJm +(S.) 11.9556 Tj +-426 TJm +(Hirschberg) 59.778 Tj +-426 TJm +(and) 17.9334 Tj +-425 TJm +(Debra) 29.889 Tj +-426 TJm +(A.) 11.9556 Tj +-426 TJm +(LeLewer) 41.8446 Tj +98.488 442.592 Td +("Efficient) 59.778 Tj +-426 TJm +(Decoding) 47.8224 Tj +-426 TJm +(of) 11.9556 Tj +-426 TJm +(Pr) 11.9556 Tj +1 TJm +(efix) 23.9112 Tj +-426 TJm +(Codes") 35.8668 Tj +102.732 430.637 Td +(Communications) 83.6892 Tj +-426 TJm +(of) 11.9556 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(ACM) 17.9334 Tj +1 TJm +(,) 5.9778 Tj +-426 TJm +(April) 29.889 Tj +-426 TJm +(1990,) 29.889 Tj +-426 TJm +(Vol) 17.9334 Tj +-426 TJm +(33,) 17.9334 Tj +-426 TJm +(Number) 35.8668 Tj +-426 TJm +(4.) 11.9556 Tj +102.732 418.682 Td +(You) 17.9334 Tj +-426 TJm +(might) 29.889 Tj +-426 TJm +(be) 11.9556 Tj +-426 TJm +(able) 23.9112 Tj +-426 TJm +(to) 11.9556 Tj +-426 TJm +(get) 17.9334 Tj +-425 TJm +(an) 11.9556 Tj +-426 TJm +(electronic) 59.778 Tj +-426 TJm +(copy) 23.9112 Tj +-426 TJm +(of) 11.9556 Tj +-426 TJm +(this) 23.9112 Tj +102.732 406.727 Td +(from) 23.9112 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(ACM) 17.9334 Tj +-426 TJm +(Digital) 41.8446 Tj +-426 TJm +(Lib) 17.9334 Tj +1 TJm +(rary.) 29.889 Tj +90 382.816 Td +(David) 29.889 Tj +-426 TJm +(J.) 11.9556 Tj +-426 TJm +(Wheeler) 41.8446 Tj +102.732 370.861 Td +(Program) 41.8446 Tj +-426 TJm +(bred3.c) 41.8446 Tj +-426 TJm +(and) 17.9334 Tj +-426 TJm +(accom) 29.889 Tj +1 TJm +(panying) 41.8446 Tj +-426 TJm +(document) 47.8224 Tj +-426 TJm +(bred3.ps.) 53.8002 Tj +102.732 358.906 Td +(This) 23.9112 Tj +-426 TJm +(contains) 47.8224 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(idea) 23.9112 Tj +-426 TJm +(b) 5.9778 Tj +1 TJm +(ehind) 29.889 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(multi-table) 65.7558 Tj +-426 TJm +(Huffman) 41.8446 Tj +-426 TJm +(coding) 35.8668 Tj +-426 TJm +(scheme.) 41.8446 Tj +102.732 346.951 Td +(ftp://ftp.cl.cam.ac.uk/us) 149.445 Tj +1 TJm +(ers/djw3/) 53.8002 Tj +90 323.04 Td +(Jon) 17.9334 Tj +-426 TJm +(L.) 11.9556 Tj +-426 TJm +(Bentley) 41.8446 Tj +-426 TJm +(and) 17.9334 Tj +-426 TJm +(Robert) 35.8668 Tj +-425 TJm +(Sedgewick) 53.8002 Tj +98.488 311.085 Td +("Fast) 29.889 Tj +-426 TJm +(Algorithms) 59.778 Tj +-426 TJm +(for) 17.9334 Tj +-426 TJm +(Sort) 23.9112 Tj +1 TJm +(ing) 17.9334 Tj +-426 TJm +(and) 17.9334 Tj +-426 TJm +(Searching) 53.8002 Tj +-426 TJm +(Strings") 47.8224 Tj +102.732 299.13 Td +(Available) 53.8002 Tj +-426 TJm +(from) 23.9112 Tj +-426 TJm +(Sedgewick') 59.778 Tj +1 TJm +(s) 5.9778 Tj +-426 TJm +(web) 17.9334 Tj +-426 TJm +(page,) 29.889 Tj +102.732 287.175 Td +(www.cs.princeton.edu/~rs) 143.467 Tj +[1 0 0 1 72 259.678] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.55] cm +0 g +0 G +[1 0 0 1 -72 -249.715] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 237.76 Td +/F128_0 9.963 Tf +(The) 15.4925 Tj +-239 TJm +(follo) 18.8201 Tj +26 TJm +(wing) 19.926 Tj +-239 TJm +(paper) 22.1278 Tj +-239 TJm +(gi) 7.75121 Tj +25 TJm +(v) 4.9815 Tj +15 TJm +(es) 8.29918 Tj +-238 TJm +(v) 4.9815 Tj +25 TJm +(aluable) 28.7731 Tj +-239 TJm +(additiona) 37.0823 Tj +1 TJm +(l) 2.76971 Tj +-239 TJm +(insights) 31.0049 Tj +-239 TJm +(into) 15.5024 Tj +-238 TJm +(the) 12.1748 Tj +-239 TJm +(algorithm,) 41.2369 Tj +-240 TJm +(b) 4.9815 Tj +20 TJm +(ut) 7.75121 Tj +-239 TJm +(is) 6.64532 Tj +-239 TJm +(not) 12.7327 Tj +-238 TJm +(immediately) 49.815 Tj +-239 TJm +(the) 12.1748 Tj +-238 TJm +(basis) 19.926 Tj +-239 TJm +(of) 8.29918 Tj +-238 TJm +(an) 9.40507 Tj +15 TJm +(y) 4.9815 Tj +-239 TJm +(code) 18.8101 Tj +72 225.805 Td +(used) 18.2622 Tj +-250 TJm +(in) 7.75121 Tj +-250 TJm +(bzip2.) 24.6285 Tj +[1 0 0 1 72 223.648] cm +0 g +0 G +[1 0 0 1 0 -72.727] cm +0.9294 0.96861 0.95685 rg +0.9294 0.96861 0.95685 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 71.731 re +f +Q +0 g +0 G +[1 0 0 1 0 3.587] cm +0 g +0 G +[1 0 0 1 0 68.144] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -214.283] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 214.283 Td +/F130_0 9.963 Tf +(Peter) 29.889 Tj +-426 TJm +(Fenwick:) 47.8224 Tj +102.732 202.328 Td +(Block) 29.889 Tj +-426 TJm +(Sorting) 41.8446 Tj +-426 TJm +(Text) 23.9112 Tj +-426 TJm +(Compr) 29.889 Tj +1 TJm +(ession) 35.8668 Tj +102.732 190.373 Td +(Proceedings) 65.7558 Tj +-426 TJm +(of) 11.9556 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(19th) 23.9112 Tj +-425 TJm +(Australasian) 71.7336 Tj +-426 TJm +(Computer) 47.8224 Tj +-426 TJm +(Science) 41.8446 Tj +-426 TJm +(Conference,) 65.7558 Tj +111.22 178.418 Td +(Melbourne,) 59.778 Tj +-426 TJm +(Australia.) 59.778 Tj +-852 TJm +(J) 5.9778 Tj +1 TJm +(an) 11.9556 Tj +-426 TJm +(31) 11.9556 Tj +-426 TJm +(-) 5.9778 Tj +-426 TJm +(Feb) 17.9334 Tj +-426 TJm +(2,) 11.9556 Tj +-426 TJm +(1996.) 29.889 Tj +102.732 166.463 Td +(ftp://ftp.cs.auckland.ac.) 149.445 Tj +1 TJm +(nz/pub/peter-f/ACSC96paper.ps) 173.356 Tj +[1 0 0 1 72 150.921] cm +0 g +0 G +[1 0 0 1 468 3.587] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.55] cm +0 g +0 G +[1 0 0 1 -72 -140.958] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 129.003 Td +/F128_0 9.963 Tf +(K) 7.19329 Tj +15 TJm +(unihik) 25.4654 Tj +10 TJm +(o) 4.9815 Tj +-250 TJm +(Sadakane') 41.4959 Tj +55 TJm +(s) 3.87561 Tj +-250 TJm +(sorting) 27.6772 Tj +-250 TJm +(al) 7.19329 Tj +1 TJm +(gorithm,) 34.0436 Tj +-250 TJm +(mentioned) 42.0638 Tj +-250 TJm +(abo) 14.3866 Tj +15 TJm +(v) 4.9815 Tj +15 TJm +(e,) 6.91432 Tj +-250 TJm +(is) 6.64532 Tj +-250 TJm +(a) 4.42357 Tj +20 TJm +(v) 4.9815 Tj +25 TJm +(ailable) 26.5614 Tj +-250 TJm +(from:) 22.1378 Tj +[1 0 0 1 72 126.846] cm +0 g +0 G +[1 0 0 1 0 -36.861] cm +0.9294 0.96861 0.95685 rg +0.9294 0.96861 0.95685 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 35.866 re +f +Q +0 g +0 G +[1 0 0 1 0 3.586] cm +0 g +0 G +[1 0 0 1 0 32.279] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -117.481] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 117.481 Td +/F130_0 9.963 Tf +(http://naomi.is.s.u-tokyo.) 155.423 Tj +1 TJm +(ac.jp/~sada/papers/Sada98b.ps.gz) 191.29 Tj +[1 0 0 1 72 89.985] cm +0 g +0 G +[1 0 0 1 468 3.586] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.549] cm +0 g +0 G +[1 0 0 1 0 -29.17] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.854] cm +0 g +0 G +0 g +0 G +[1 0 0 1 40.572 -6.755] cm +0 g +0 G +[1 0 0 1 -493.841 -50.951] cm +[1 0 0 1 0 0] Tm +0 0 Td +534.414 50.951 Td +/F128_0 9.963 Tf +(34) 9.963 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Page: 38 38 +%%BeginPageSetup +%%PageOrientation: Portrait +pdfStartPage +%%EndPageSetup +[] 0 d +1 i +0 j +0 J +10 M +1 w +0 g +0 G +q +[1 0 0 1 72 741.554] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 14.446] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 187.197 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.49 -6.854] cm +0 g +0 G +[1 0 0 1 0 6.854] cm +0 g +0 G +0 g +0 G +[1 0 0 1 116.329 -6.755] cm +0 g +0 G +[1 0 0 1 -382.4 -749.245] cm +[1 0 0 1 0 0] Tm +0 0 Td +498.728 749.245 Td +/F128_0 9.963 Tf +(Miscellanea) 48.1412 Tj +[1 0 0 1 266.071 749.146] cm +0 g +0 G +0 g +0 G +[1 0 0 1 280.796 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -472.974 -7.094] cm +0 g +0 G +[1 0 0 1 0 -0.498] cm +q +[] 0 d +0 J +0.498 w +0 0.249 m +475.465 0.249 l +S +Q +0 g +0 G +[1 0 0 1 479.251 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +[1 0 0 1 -540 -741.554] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 710.037 Td +/F128_0 9.963 Tf +(The) 15.4925 Tj +-250 TJm +(Manber) 30.9849 Tj +20 TJm +(-Myers) 28.7731 Tj +-250 TJm +(suf) 12.1748 Tj +25 TJm +(\002x) 10.5209 Tj +-250 TJm +(arra) 15.4825 Tj +1 TJm +(y) 4.9815 Tj +-250 TJm +(construction) 49.2571 Tj +-250 TJm +(algorithm) 38.7461 Tj +-250 TJm +(is) 6.64532 Tj +-250 TJm +(described) 38.1782 Tj +-250 TJm +(in) 7.75121 Tj +-250 TJm +(a) 4.42357 Tj +-250 TJm +(paper) 22.1278 Tj +-250 TJm +(a) 4.42357 Tj +20 TJm +(v) 4.9815 Tj +25 TJm +(ailabl) 22.1378 Tj +1 TJm +(e) 4.42357 Tj +-250 TJm +(from:) 22.1378 Tj +[1 0 0 1 72 707.881] cm +0 g +0 G +[1 0 0 1 0 -36.862] cm +0.9294 0.96861 0.95685 rg +0.9294 0.96861 0.95685 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 35.866 re +f +Q +0 g +0 G +[1 0 0 1 0 3.586] cm +0 g +0 G +[1 0 0 1 0 32.279] cm +0 g +0 G +[1 0 0 1 18 -8.368] cm +0 g +0 G +[1 0 0 1 -90 -698.516] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 698.516 Td +/F130_0 9.963 Tf +(http://www.cs.arizona.edu/) 155.423 Tj +1 TJm +(people/gene/PAPERS/suffix.ps) 167.378 Tj +[1 0 0 1 72 671.019] cm +0 g +0 G +[1 0 0 1 468 3.586] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -13.549] cm +0 g +0 G +[1 0 0 1 -72 -661.056] cm +[1 0 0 1 0 0] Tm +0 0 Td +72 649.101 Td +/F128_0 9.963 Tf +(Finally) 28.2351 Tj +65 TJm +(,) 2.49075 Tj +-227 TJm +(the) 12.1748 Tj +-221 TJm +(follo) 18.8201 Tj +25 TJm +(wing) 19.926 Tj +-221 TJm +(papers) 26.0034 Tj +-222 TJm +(docume) 31.5429 Tj +1 TJm +(nt) 7.75121 Tj +-222 TJm +(some) 21.0319 Tj +-221 TJm +(in) 7.75121 Tj +40 TJm +(v) 4.9815 Tj +15 TJm +(estig) 18.8201 Tj +5 TJm +(ations) 23.8016 Tj +-221 TJm +(I) 3.31768 Tj +-221 TJm +(made) 21.5799 Tj +-222 TJm +(into) 15.5024 Tj +-221 TJm +(the) 12.1748 Tj +-221 TJm +(performance) 50.343 Tj +-221 TJm +(of) 8.29918 Tj +-222 TJm +(sorting) 27.6772 Tj +-221 TJm +(and) 14.3866 Tj +-221 TJm +(decompression) 59.768 Tj +72 637.146 Td +(algorithms:) 45.3914 Tj +[1 0 0 1 72 634.989] cm +0 g +0 G +[1 0 0 1 0 -132.503] cm +0.9294 0.96861 0.95685 rg +0.9294 0.96861 0.95685 RG +q +[] 0 d +0 J +0 j +0 w +0 0 468 131.507 re +f +Q +0 g +0 G +[1 0 0 1 0 3.586] cm +0 g +0 G +[1 0 0 1 0 127.921] cm +0 g +0 G +[1 0 0 1 18 -8.369] cm +0 g +0 G +[1 0 0 1 -90 -625.624] cm +[1 0 0 1 0 0] Tm +0 0 Td +90 625.624 Td +/F130_0 9.963 Tf +(Julian) 35.8668 Tj +-426 TJm +(Seward) 35.8668 Tj +102.732 613.669 Td +(On) 11.9556 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(Performance) 65.7558 Tj +-426 TJm +(of) 11.9556 Tj +-426 TJm +(BW) 11.9556 Tj +1 TJm +(T) 5.9778 Tj +-426 TJm +(Sorting) 41.8446 Tj +-426 TJm +(Algorithms) 59.778 Tj +102.732 601.714 Td +(Proceedings) 65.7558 Tj +-426 TJm +(of) 11.9556 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(IEEE) 23.9112 Tj +-425 TJm +(Data) 23.9112 Tj +-426 TJm +(Compression) 65.7558 Tj +-426 TJm +(Conference) 59.778 Tj +-426 TJm +(2000) 23.9112 Tj +111.22 589.759 Td +(Snowbird,) 53.8002 Tj +-426 TJm +(Utah.) 29.889 Tj +-852 TJm +(28-30) 29.889 Tj +-426 TJm +(M) 5.9778 Tj +1 TJm +(arch) 23.9112 Tj +-426 TJm +(2000.) 29.889 Tj +90 565.848 Td +(Julian) 35.8668 Tj +-426 TJm +(Seward) 35.8668 Tj +102.732 553.893 Td +(Space-time) 59.778 Tj +-426 TJm +(Tradeoffs) 53.8002 Tj +-426 TJm +(in) 11.9556 Tj +-425 TJm +(the) 17.9334 Tj +-426 TJm +(Inverse) 41.8446 Tj +-426 TJm +(B-W) 17.9334 Tj +-426 TJm +(Transform) 53.8002 Tj +102.732 541.938 Td +(Proceedings) 65.7558 Tj +-426 TJm +(of) 11.9556 Tj +-426 TJm +(the) 17.9334 Tj +-426 TJm +(IEEE) 23.9112 Tj +-425 TJm +(Data) 23.9112 Tj +-426 TJm +(Compression) 65.7558 Tj +-426 TJm +(Conference) 59.778 Tj +-426 TJm +(2001) 23.9112 Tj +111.22 529.983 Td +(Snowbird,) 53.8002 Tj +-426 TJm +(Utah.) 29.889 Tj +-852 TJm +(27-29) 29.889 Tj +-426 TJm +(M) 5.9778 Tj +1 TJm +(arch) 23.9112 Tj +-426 TJm +(2001.) 29.889 Tj +[1 0 0 1 72 502.486] cm +0 g +0 G +[1 0 0 1 468 3.586] cm +0 g +0 G +0 g +0 G +[1 0 0 1 -468 -3.586] cm +0 g +0 G +[1 0 0 1 0 -451.634] cm +0 g +0 G +[1 0 0 1 1.893 0] cm +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +0 g +0 G +[1 0 0 1 374.394 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 2.491 0] cm +0 g +0 G +[1 0 0 1 0 6.854] cm +0 g +0 G +0 g +0 G +[1 0 0 1 40.572 -6.755] cm +0 g +0 G +[1 0 0 1 -493.841 -50.951] cm +[1 0 0 1 0 0] Tm +0 0 Td +534.414 50.951 Td +/F128_0 9.963 Tf +(35) 9.963 Tj +[1 0 0 1 453.269 50.852] cm +0 g +0 G +0 g +0 G +[1 0 0 1 93.598 0] cm +0 g +0 G +0 g +0 G +[1 0 0 1 6.277 0] cm +0 g +0 G +[1 0 0 1 -13.144 0] cm +0 g +0 G +Q +showpage +%%PageTrailer +pdfEndPage +%%Trailer +end +%%DocumentSuppliedResources: +%%+ font CJBHNS+CMMI10 +%%+ font RBGKEI+CMSY10 +%%EOF diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/manual.xml b/contrib/vmap_extractor_v2/stormlib/bzip2/manual.xml new file mode 100644 index 00000000000..1ab5bd71d9e --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/bzip2/manual.xml @@ -0,0 +1,2966 @@ + + + %common-ents; +]> + + + + + bzip2 and libbzip2, version 1.0.3 + A program and library for data compression + + &bz-lifespan; + Julian Seward + + Version &bz-version; of &bz-date; + + + + Julian + Seward + + &bz-url; + + + + + + + This program, bzip2, the + associated library libbzip2, and + all documentation, are copyright © &bz-lifespan; Julian Seward. + All rights reserved. + + Redistribution and use in source and binary forms, with + or without modification, are permitted provided that the + following conditions are met: + + + + Redistributions of source code must retain the + above copyright notice, this list of conditions and the + following disclaimer. + + The origin of this software must not be + misrepresented; you must not claim that you wrote the original + software. If you use this software in a product, an + acknowledgment in the product documentation would be + appreciated but is not required. + + Altered source versions must be plainly marked + as such, and must not be misrepresented as being the original + software. + + The name of the author may not be used to + endorse or promote products derived from this software without + specific prior written permission. + + + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. + + PATENTS: To the best of my knowledge, + bzip2 and + libbzip2 do not use any patented + algorithms. However, I do not have the resources to carry + out a patent search. Therefore I cannot give any guarantee of + the above statement. + + + + + + + + + +Introduction + +bzip2 compresses files +using the Burrows-Wheeler block-sorting text compression +algorithm, and Huffman coding. Compression is generally +considerably better than that achieved by more conventional +LZ77/LZ78-based compressors, and approaches the performance of +the PPM family of statistical compressors. + +bzip2 is built on top of +libbzip2, a flexible library for +handling compressed data in the +bzip2 format. This manual +describes both how to use the program and how to work with the +library interface. Most of the manual is devoted to this +library, not the program, which is good news if your interest is +only in the program. + + + + describes how to use + bzip2; this is the only part + you need to read if you just want to know how to operate the + program. + + describes the + programming interfaces in detail, and + + records some + miscellaneous notes which I thought ought to be recorded + somewhere. + + + + + + + +How to use bzip2 + +This chapter contains a copy of the +bzip2 man page, and nothing +else. + + +NAME + + + + bzip2, + bunzip2 - a block-sorting file + compressor, v1.0.3 + + bzcat - + decompresses files to stdout + + bzip2recover - + recovers data from damaged bzip2 files + + + + + + + +SYNOPSIS + + + + bzip2 [ + -cdfkqstvzVL123456789 ] [ filenames ... ] + + bunzip2 [ + -fkvsVL ] [ filenames ... ] + + bzcat [ -s ] [ + filenames ... ] + + bzip2recover + filename + + + + + + + +DESCRIPTION + +bzip2 compresses files +using the Burrows-Wheeler block sorting text compression +algorithm, and Huffman coding. Compression is generally +considerably better than that achieved by more conventional +LZ77/LZ78-based compressors, and approaches the performance of +the PPM family of statistical compressors. + +The command-line options are deliberately very similar to +those of GNU gzip, but they are +not identical. + +bzip2 expects a list of +file names to accompany the command-line flags. Each file is +replaced by a compressed version of itself, with the name +original_name.bz2. Each +compressed file has the same modification date, permissions, and, +when possible, ownership as the corresponding original, so that +these properties can be correctly restored at decompression time. +File name handling is naive in the sense that there is no +mechanism for preserving original file names, permissions, +ownerships or dates in filesystems which lack these concepts, or +have serious file name length restrictions, such as +MS-DOS. + +bzip2 and +bunzip2 will by default not +overwrite existing files. If you want this to happen, specify +the -f flag. + +If no file names are specified, +bzip2 compresses from standard +input to standard output. In this case, +bzip2 will decline to write +compressed output to a terminal, as this would be entirely +incomprehensible and therefore pointless. + +bunzip2 (or +bzip2 -d) decompresses all +specified files. Files which were not created by +bzip2 will be detected and +ignored, and a warning issued. +bzip2 attempts to guess the +filename for the decompressed file from that of the compressed +file as follows: + + + + filename.bz2 + becomes + filename + + filename.bz + becomes + filename + + filename.tbz2 + becomes + filename.tar + + filename.tbz + becomes + filename.tar + + anyothername + becomes + anyothername.out + + + +If the file does not end in one of the recognised endings, +.bz2, +.bz, +.tbz2 or +.tbz, +bzip2 complains that it cannot +guess the name of the original file, and uses the original name +with .out appended. + +As with compression, supplying no filenames causes +decompression from standard input to standard output. + +bunzip2 will correctly +decompress a file which is the concatenation of two or more +compressed files. The result is the concatenation of the +corresponding uncompressed files. Integrity testing +(-t) of concatenated compressed +files is also supported. + +You can also compress or decompress files to the standard +output by giving the -c flag. +Multiple files may be compressed and decompressed like this. The +resulting outputs are fed sequentially to stdout. Compression of +multiple files in this manner generates a stream containing +multiple compressed file representations. Such a stream can be +decompressed correctly only by +bzip2 version 0.9.0 or later. +Earlier versions of bzip2 will +stop after decompressing the first file in the stream. + +bzcat (or +bzip2 -dc) decompresses all +specified files to the standard output. + +bzip2 will read arguments +from the environment variables +BZIP2 and +BZIP, in that order, and will +process them before any arguments read from the command line. +This gives a convenient way to supply default arguments. + +Compression is always performed, even if the compressed +file is slightly larger than the original. Files of less than +about one hundred bytes tend to get larger, since the compression +mechanism has a constant overhead in the region of 50 bytes. +Random data (including the output of most file compressors) is +coded at about 8.05 bits per byte, giving an expansion of around +0.5%. + +As a self-check for your protection, +bzip2 uses 32-bit CRCs to make +sure that the decompressed version of a file is identical to the +original. This guards against corruption of the compressed data, +and against undetected bugs in +bzip2 (hopefully very unlikely). +The chances of data corruption going undetected is microscopic, +about one chance in four billion for each file processed. Be +aware, though, that the check occurs upon decompression, so it +can only tell you that something is wrong. It can't help you +recover the original uncompressed data. You can use +bzip2recover to try to recover +data from damaged files. + +Return values: 0 for a normal exit, 1 for environmental +problems (file not found, invalid flags, I/O errors, etc.), 2 +to indicate a corrupt compressed file, 3 for an internal +consistency error (eg, bug) which caused +bzip2 to panic. + + + + + +OPTIONS + + + + + -c --stdout + Compress or decompress to standard + output. + + + + -d --decompress + Force decompression. + bzip2, + bunzip2 and + bzcat are really the same + program, and the decision about what actions to take is done on + the basis of which name is used. This flag overrides that + mechanism, and forces bzip2 to decompress. + + + + -z --compress + The complement to + -d: forces compression, + regardless of the invokation name. + + + + -t --test + Check integrity of the specified file(s), but + don't decompress them. This really performs a trial + decompression and throws away the result. + + + + -f --force + Force overwrite of output files. Normally, + bzip2 will not overwrite + existing output files. Also forces + bzip2 to break hard links to + files, which it otherwise wouldn't do. + bzip2 normally declines + to decompress files which don't have the correct magic header + bytes. If forced (-f), + however, it will pass such files through unmodified. This is + how GNU gzip behaves. + + + + + -k --keep + Keep (don't delete) input files during + compression or decompression. + + + + -s --small + Reduce memory usage, for compression, + decompression and testing. Files are decompressed and tested + using a modified algorithm which only requires 2.5 bytes per + block byte. This means any file can be decompressed in 2300k + of memory, albeit at about half the normal speed. + During compression, -s + selects a block size of 200k, which limits memory use to around + the same figure, at the expense of your compression ratio. In + short, if your machine is low on memory (8 megabytes or less), + use -s for everything. See + below. + + + + -q --quiet + Suppress non-essential warning messages. + Messages pertaining to I/O errors and other critical events + will not be suppressed. + + + + -v --verbose + Verbose mode -- show the compression ratio for + each file processed. Further + -v's increase the verbosity + level, spewing out lots of information which is primarily of + interest for diagnostic purposes. + + + + -L --license -V --version + Display the software version, license terms and + conditions. + + + + -1 (or + --fast) to + -9 (or + -best) + Set the block size to 100 k, 200 k ... 900 k + when compressing. Has no effect when decompressing. See below. The + --fast and + --best aliases are primarily + for GNU gzip compatibility. + In particular, --fast doesn't + make things significantly faster. And + --best merely selects the + default behaviour. + + + + -- + Treats all subsequent arguments as file names, + even if they start with a dash. This is so you can handle + files with names beginning with a dash, for example: + bzip2 -- + -myfilename. + + + + --repetitive-fast + --repetitive-best + These flags are redundant in versions 0.9.5 and + above. They provided some coarse control over the behaviour of + the sorting algorithm in earlier versions, which was sometimes + useful. 0.9.5 and above have an improved algorithm which + renders these flags irrelevant. + + + + + + + + +MEMORY MANAGEMENT + +bzip2 compresses large +files in blocks. The block size affects both the compression +ratio achieved, and the amount of memory needed for compression +and decompression. The flags -1 +through -9 specify the block +size to be 100,000 bytes through 900,000 bytes (the default) +respectively. At decompression time, the block size used for +compression is read from the header of the compressed file, and +bunzip2 then allocates itself +just enough memory to decompress the file. Since block sizes are +stored in compressed files, it follows that the flags +-1 to +-9 are irrelevant to and so +ignored during decompression. + +Compression and decompression requirements, in bytes, can be +estimated as: + +Compression: 400k + ( 8 x block size ) + +Decompression: 100k + ( 4 x block size ), or + 100k + ( 2.5 x block size ) + + +Larger block sizes give rapidly diminishing marginal +returns. Most of the compression comes from the first two or +three hundred k of block size, a fact worth bearing in mind when +using bzip2 on small machines. +It is also important to appreciate that the decompression memory +requirement is set at compression time by the choice of block +size. + +For files compressed with the default 900k block size, +bunzip2 will require about 3700 +kbytes to decompress. To support decompression of any file on a +4 megabyte machine, bunzip2 has +an option to decompress using approximately half this amount of +memory, about 2300 kbytes. Decompression speed is also halved, +so you should use this option only where necessary. The relevant +flag is -s. + +In general, try and use the largest block size memory +constraints allow, since that maximises the compression achieved. +Compression and decompression speed are virtually unaffected by +block size. + +Another significant point applies to files which fit in a +single block -- that means most files you'd encounter using a +large block size. The amount of real memory touched is +proportional to the size of the file, since the file is smaller +than a block. For example, compressing a file 20,000 bytes long +with the flag -9 will cause the +compressor to allocate around 7600k of memory, but only touch +400k + 20000 * 8 = 560 kbytes of it. Similarly, the decompressor +will allocate 3700k but only touch 100k + 20000 * 4 = 180 +kbytes. + +Here is a table which summarises the maximum memory usage +for different block sizes. Also recorded is the total compressed +size for 14 files of the Calgary Text Compression Corpus +totalling 3,141,622 bytes. This column gives some feel for how +compression varies with block size. These figures tend to +understate the advantage of larger block sizes for larger files, +since the Corpus is dominated by smaller files. + + + Compress Decompress Decompress Corpus +Flag usage usage -s usage Size + + -1 1200k 500k 350k 914704 + -2 2000k 900k 600k 877703 + -3 2800k 1300k 850k 860338 + -4 3600k 1700k 1100k 846899 + -5 4400k 2100k 1350k 845160 + -6 5200k 2500k 1600k 838626 + -7 6100k 2900k 1850k 834096 + -8 6800k 3300k 2100k 828642 + -9 7600k 3700k 2350k 828642 + + + + + + +RECOVERING DATA FROM DAMAGED FILES + +bzip2 compresses files in +blocks, usually 900kbytes long. Each block is handled +independently. If a media or transmission error causes a +multi-block .bz2 file to become +damaged, it may be possible to recover data from the undamaged +blocks in the file. + +The compressed representation of each block is delimited by +a 48-bit pattern, which makes it possible to find the block +boundaries with reasonable certainty. Each block also carries +its own 32-bit CRC, so damaged blocks can be distinguished from +undamaged ones. + +bzip2recover is a simple +program whose purpose is to search for blocks in +.bz2 files, and write each block +out into its own .bz2 file. You +can then use bzip2 -t to test +the integrity of the resulting files, and decompress those which +are undamaged. + +bzip2recover takes a +single argument, the name of the damaged file, and writes a +number of files rec0001file.bz2, +rec0002file.bz2, etc, containing +the extracted blocks. The output filenames are designed so that +the use of wildcards in subsequent processing -- for example, +bzip2 -dc rec*file.bz2 > +recovered_data -- lists the files in the correct +order. + +bzip2recover should be of +most use dealing with large .bz2 +files, as these will contain many blocks. It is clearly futile +to use it on damaged single-block files, since a damaged block +cannot be recovered. If you wish to minimise any potential data +loss through media or transmission errors, you might consider +compressing with a smaller block size. + + + + + +PERFORMANCE NOTES + +The sorting phase of compression gathers together similar +strings in the file. Because of this, files containing very long +runs of repeated symbols, like "aabaabaabaab ..." (repeated +several hundred times) may compress more slowly than normal. +Versions 0.9.5 and above fare much better than previous versions +in this respect. The ratio between worst-case and average-case +compression time is in the region of 10:1. For previous +versions, this figure was more like 100:1. You can use the +-vvvv option to monitor progress +in great detail, if you want. + +Decompression speed is unaffected by these +phenomena. + +bzip2 usually allocates +several megabytes of memory to operate in, and then charges all +over it in a fairly random fashion. This means that performance, +both for compressing and decompressing, is largely determined by +the speed at which your machine can service cache misses. +Because of this, small changes to the code to reduce the miss +rate have been observed to give disproportionately large +performance improvements. I imagine +bzip2 will perform best on +machines with very large caches. + + + + + + +CAVEATS + +I/O error messages are not as helpful as they could be. +bzip2 tries hard to detect I/O +errors and exit cleanly, but the details of what the problem is +sometimes seem rather misleading. + +This manual page pertains to version &bz-version; of +bzip2. Compressed data created +by this version is entirely forwards and backwards compatible +with the previous public releases, versions 0.1pl2, 0.9.0 and +0.9.5, 1.0.0, 1.0.1 and 1.0.2, but with the following exception: 0.9.0 +and above can correctly decompress multiple concatenated +compressed files. 0.1pl2 cannot do this; it will stop after +decompressing just the first file in the stream. + +bzip2recover versions +prior to 1.0.2 used 32-bit integers to represent bit positions in +compressed files, so it could not handle compressed files more +than 512 megabytes long. Versions 1.0.2 and above use 64-bit ints +on some platforms which support them (GNU supported targets, and +Windows). To establish whether or not +bzip2recover was built with such +a limitation, run it without arguments. In any event you can +build yourself an unlimited version if you can recompile it with +MaybeUInt64 set to be an +unsigned 64-bit integer. + + + + + + +AUTHOR + +Julian Seward, +&bz-email; + +The ideas embodied in +bzip2 are due to (at least) the +following people: Michael Burrows and David Wheeler (for the +block sorting transformation), David Wheeler (again, for the +Huffman coder), Peter Fenwick (for the structured coding model in +the original bzip, and many +refinements), and Alistair Moffat, Radford Neal and Ian Witten +(for the arithmetic coder in the original +bzip). I am much indebted for +their help, support and advice. See the manual in the source +distribution for pointers to sources of documentation. Christian +von Roques encouraged me to look for faster sorting algorithms, +so as to speed up compression. Bela Lubkin encouraged me to +improve the worst-case compression performance. +Donna Robinson XMLised the documentation. +Many people sent +patches, helped with portability problems, lent machines, gave +advice and were generally helpful. + + + + + + + + + +Programming with <computeroutput>libbzip2</computeroutput> + + +This chapter describes the programming interface to +libbzip2. + +For general background information, particularly about +memory use and performance aspects, you'd be well advised to read + as well. + + + +Top-level structure + +libbzip2 is a flexible +library for compressing and decompressing data in the +bzip2 data format. Although +packaged as a single entity, it helps to regard the library as +three separate parts: the low level interface, and the high level +interface, and some utility functions. + +The structure of +libbzip2's interfaces is similar +to that of Jean-loup Gailly's and Mark Adler's excellent +zlib library. + +All externally visible symbols have names beginning +BZ2_. This is new in version +1.0. The intention is to minimise pollution of the namespaces of +library clients. + +To use any part of the library, you need to +#include <bzlib.h> +into your sources. + + + + +Low-level summary + +This interface provides services for compressing and +decompressing data in memory. There's no provision for dealing +with files, streams or any other I/O mechanisms, just straight +memory-to-memory work. In fact, this part of the library can be +compiled without inclusion of +stdio.h, which may be helpful +for embedded applications. + +The low-level part of the library has no global variables +and is therefore thread-safe. + +Six routines make up the low level interface: +BZ2_bzCompressInit, +BZ2_bzCompress, and +BZ2_bzCompressEnd for +compression, and a corresponding trio +BZ2_bzDecompressInit, +BZ2_bzDecompress and +BZ2_bzDecompressEnd for +decompression. The *Init +functions allocate memory for compression/decompression and do +other initialisations, whilst the +*End functions close down +operations and release memory. + +The real work is done by +BZ2_bzCompress and +BZ2_bzDecompress. These +compress and decompress data from a user-supplied input buffer to +a user-supplied output buffer. These buffers can be any size; +arbitrary quantities of data are handled by making repeated calls +to these functions. This is a flexible mechanism allowing a +consumer-pull style of activity, or producer-push, or a mixture +of both. + + + + + +High-level summary + +This interface provides some handy wrappers around the +low-level interface to facilitate reading and writing +bzip2 format files +(.bz2 files). The routines +provide hooks to facilitate reading files in which the +bzip2 data stream is embedded +within some larger-scale file structure, or where there are +multiple bzip2 data streams +concatenated end-to-end. + +For reading files, +BZ2_bzReadOpen, +BZ2_bzRead, +BZ2_bzReadClose and +BZ2_bzReadGetUnused are +supplied. For writing files, +BZ2_bzWriteOpen, +BZ2_bzWrite and +BZ2_bzWriteFinish are +available. + +As with the low-level library, no global variables are used +so the library is per se thread-safe. However, if I/O errors +occur whilst reading or writing the underlying compressed files, +you may have to consult errno to +determine the cause of the error. In that case, you'd need a C +library which correctly supports +errno in a multithreaded +environment. + +To make the library a little simpler and more portable, +BZ2_bzReadOpen and +BZ2_bzWriteOpen require you to +pass them file handles (FILE*s) +which have previously been opened for reading or writing +respectively. That avoids portability problems associated with +file operations and file attributes, whilst not being much of an +imposition on the programmer. + + + + + +Utility functions summary + +For very simple needs, +BZ2_bzBuffToBuffCompress and +BZ2_bzBuffToBuffDecompress are +provided. These compress data in memory from one buffer to +another buffer in a single function call. You should assess +whether these functions fulfill your memory-to-memory +compression/decompression requirements before investing effort in +understanding the more general but more complex low-level +interface. + +Yoshioka Tsuneo +(QWF00133@niftyserve.or.jp / +tsuneo-y@is.aist-nara.ac.jp) has +contributed some functions to give better +zlib compatibility. These +functions are BZ2_bzopen, +BZ2_bzread, +BZ2_bzwrite, +BZ2_bzflush, +BZ2_bzclose, +BZ2_bzerror and +BZ2_bzlibVersion. You may find +these functions more convenient for simple file reading and +writing, than those in the high-level interface. These functions +are not (yet) officially part of the library, and are minimally +documented here. If they break, you get to keep all the pieces. +I hope to document them properly when time permits. + +Yoshioka also contributed modifications to allow the +library to be built as a Windows DLL. + + + + + + + +Error handling + +The library is designed to recover cleanly in all +situations, including the worst-case situation of decompressing +random data. I'm not 100% sure that it can always do this, so +you might want to add a signal handler to catch segmentation +violations during decompression if you are feeling especially +paranoid. I would be interested in hearing more about the +robustness of the library to corrupted compressed data. + +Version 1.0.3 more robust in this respect than any +previous version. Investigations with Valgrind (a tool for detecting +problems with memory management) indicate +that, at least for the few files I tested, all single-bit errors +in the decompressed data are caught properly, with no +segmentation faults, no uses of uninitialised data, no out of +range reads or writes, and no infinite looping in the decompressor. +So it's certainly pretty robust, although +I wouldn't claim it to be totally bombproof. + +The file bzlib.h contains +all definitions needed to use the library. In particular, you +should definitely not include +bzlib_private.h. + +In bzlib.h, the various +return values are defined. The following list is not intended as +an exhaustive description of the circumstances in which a given +value may be returned -- those descriptions are given later. +Rather, it is intended to convey the rough meaning of each return +value. The first five actions are normal and not intended to +denote an error situation. + + + + + BZ_OK + The requested action was completed + successfully. + + + + BZ_RUN_OK, BZ_FLUSH_OK, + BZ_FINISH_OK + In + BZ2_bzCompress, the requested + flush/finish/nothing-special action was completed + successfully. + + + + BZ_STREAM_END + Compression of data was completed, or the + logical stream end was detected during + decompression. + + + + +The following return values indicate an error of some +kind. + + + + + BZ_CONFIG_ERROR + Indicates that the library has been improperly + compiled on your platform -- a major configuration error. + Specifically, it means that + sizeof(char), + sizeof(short) and + sizeof(int) are not 1, 2 and + 4 respectively, as they should be. Note that the library + should still work properly on 64-bit platforms which follow + the LP64 programming model -- that is, where + sizeof(long) and + sizeof(void*) are 8. Under + LP64, sizeof(int) is still 4, + so libbzip2, which doesn't + use the long type, is + OK. + + + + BZ_SEQUENCE_ERROR + When using the library, it is important to call + the functions in the correct sequence and with data structures + (buffers etc) in the correct states. + libbzip2 checks as much as it + can to ensure this is happening, and returns + BZ_SEQUENCE_ERROR if not. + Code which complies precisely with the function semantics, as + detailed below, should never receive this value; such an event + denotes buggy code which you should + investigate. + + + + BZ_PARAM_ERROR + Returned when a parameter to a function call is + out of range or otherwise manifestly incorrect. As with + BZ_SEQUENCE_ERROR, this + denotes a bug in the client code. The distinction between + BZ_PARAM_ERROR and + BZ_SEQUENCE_ERROR is a bit + hazy, but still worth making. + + + + BZ_MEM_ERROR + Returned when a request to allocate memory + failed. Note that the quantity of memory needed to decompress + a stream cannot be determined until the stream's header has + been read. So + BZ2_bzDecompress and + BZ2_bzRead may return + BZ_MEM_ERROR even though some + of the compressed data has been read. The same is not true + for compression; once + BZ2_bzCompressInit or + BZ2_bzWriteOpen have + successfully completed, + BZ_MEM_ERROR cannot + occur. + + + + BZ_DATA_ERROR + Returned when a data integrity error is + detected during decompression. Most importantly, this means + when stored and computed CRCs for the data do not match. This + value is also returned upon detection of any other anomaly in + the compressed data. + + + + BZ_DATA_ERROR_MAGIC + As a special case of + BZ_DATA_ERROR, it is + sometimes useful to know when the compressed stream does not + start with the correct magic bytes ('B' 'Z' + 'h'). + + + + BZ_IO_ERROR + Returned by + BZ2_bzRead and + BZ2_bzWrite when there is an + error reading or writing in the compressed file, and by + BZ2_bzReadOpen and + BZ2_bzWriteOpen for attempts + to use a file for which the error indicator (viz, + ferror(f)) is set. On + receipt of BZ_IO_ERROR, the + caller should consult errno + and/or perror to acquire + operating-system specific information about the + problem. + + + + BZ_UNEXPECTED_EOF + Returned by + BZ2_bzRead when the + compressed file finishes before the logical end of stream is + detected. + + + + BZ_OUTBUFF_FULL + Returned by + BZ2_bzBuffToBuffCompress and + BZ2_bzBuffToBuffDecompress to + indicate that the output data will not fit into the output + buffer provided. + + + + + + + + + +Low-level interface + + + +<computeroutput>BZ2_bzCompressInit</computeroutput> + + +typedef struct { + char *next_in; + unsigned int avail_in; + unsigned int total_in_lo32; + unsigned int total_in_hi32; + + char *next_out; + unsigned int avail_out; + unsigned int total_out_lo32; + unsigned int total_out_hi32; + + void *state; + + void *(*bzalloc)(void *,int,int); + void (*bzfree)(void *,void *); + void *opaque; +} bz_stream; + +int BZ2_bzCompressInit ( bz_stream *strm, + int blockSize100k, + int verbosity, + int workFactor ); + + +Prepares for compression. The +bz_stream structure holds all +data pertaining to the compression activity. A +bz_stream structure should be +allocated and initialised prior to the call. The fields of +bz_stream comprise the entirety +of the user-visible data. state +is a pointer to the private data structures required for +compression. + +Custom memory allocators are supported, via fields +bzalloc, +bzfree, and +opaque. The value +opaque is passed to as the first +argument to all calls to bzalloc +and bzfree, but is otherwise +ignored by the library. The call bzalloc ( +opaque, n, m ) is expected to return a pointer +p to n * +m bytes of memory, and bzfree ( +opaque, p ) should free that memory. + +If you don't want to use a custom memory allocator, set +bzalloc, +bzfree and +opaque to +NULL, and the library will then +use the standard malloc / +free routines. + +Before calling +BZ2_bzCompressInit, fields +bzalloc, +bzfree and +opaque should be filled +appropriately, as just described. Upon return, the internal +state will have been allocated and initialised, and +total_in_lo32, +total_in_hi32, +total_out_lo32 and +total_out_hi32 will have been +set to zero. These four fields are used by the library to inform +the caller of the total amount of data passed into and out of the +library, respectively. You should not try to change them. As of +version 1.0, 64-bit counts are maintained, even on 32-bit +platforms, using the _hi32 +fields to store the upper 32 bits of the count. So, for example, +the total amount of data in is (total_in_hi32 +<< 32) + total_in_lo32. + +Parameter blockSize100k +specifies the block size to be used for compression. It should +be a value between 1 and 9 inclusive, and the actual block size +used is 100000 x this figure. 9 gives the best compression but +takes most memory. + +Parameter verbosity should +be set to a number between 0 and 4 inclusive. 0 is silent, and +greater numbers give increasingly verbose monitoring/debugging +output. If the library has been compiled with +-DBZ_NO_STDIO, no such output +will appear for any verbosity setting. + +Parameter workFactor +controls how the compression phase behaves when presented with +worst case, highly repetitive, input data. If compression runs +into difficulties caused by repetitive data, the library switches +from the standard sorting algorithm to a fallback algorithm. The +fallback is slower than the standard algorithm by perhaps a +factor of three, but always behaves reasonably, no matter how bad +the input. + +Lower values of workFactor +reduce the amount of effort the standard algorithm will expend +before resorting to the fallback. You should set this parameter +carefully; too low, and many inputs will be handled by the +fallback algorithm and so compress rather slowly, too high, and +your average-to-worst case compression times can become very +large. The default value of 30 gives reasonable behaviour over a +wide range of circumstances. + +Allowable values range from 0 to 250 inclusive. 0 is a +special case, equivalent to using the default value of 30. + +Note that the compressed output generated is the same +regardless of whether or not the fallback algorithm is +used. + +Be aware also that this parameter may disappear entirely in +future versions of the library. In principle it should be +possible to devise a good way to automatically choose which +algorithm to use. Such a mechanism would render the parameter +obsolete. + +Possible return values: + + +BZ_CONFIG_ERROR + if the library has been mis-compiled +BZ_PARAM_ERROR + if strm is NULL + or blockSize < 1 or blockSize > 9 + or verbosity < 0 or verbosity > 4 + or workFactor < 0 or workFactor > 250 +BZ_MEM_ERROR + if not enough memory is available +BZ_OK + otherwise + + +Allowable next actions: + + +BZ2_bzCompress + if BZ_OK is returned + no specific action needed in case of error + + + + + + +<computeroutput>BZ2_bzCompress</computeroutput> + + +int BZ2_bzCompress ( bz_stream *strm, int action ); + + +Provides more input and/or output buffer space for the +library. The caller maintains input and output buffers, and +calls BZ2_bzCompress to transfer +data between them. + +Before each call to +BZ2_bzCompress, +next_in should point at the data +to be compressed, and avail_in +should indicate how many bytes the library may read. +BZ2_bzCompress updates +next_in, +avail_in and +total_in to reflect the number +of bytes it has read. + +Similarly, next_out should +point to a buffer in which the compressed data is to be placed, +with avail_out indicating how +much output space is available. +BZ2_bzCompress updates +next_out, +avail_out and +total_out to reflect the number +of bytes output. + +You may provide and remove as little or as much data as you +like on each call of +BZ2_bzCompress. In the limit, +it is acceptable to supply and remove data one byte at a time, +although this would be terribly inefficient. You should always +ensure that at least one byte of output space is available at +each call. + +A second purpose of +BZ2_bzCompress is to request a +change of mode of the compressed stream. + +Conceptually, a compressed stream can be in one of four +states: IDLE, RUNNING, FLUSHING and FINISHING. Before +initialisation +(BZ2_bzCompressInit) and after +termination (BZ2_bzCompressEnd), +a stream is regarded as IDLE. + +Upon initialisation +(BZ2_bzCompressInit), the stream +is placed in the RUNNING state. Subsequent calls to +BZ2_bzCompress should pass +BZ_RUN as the requested action; +other actions are illegal and will result in +BZ_SEQUENCE_ERROR. + +At some point, the calling program will have provided all +the input data it wants to. It will then want to finish up -- in +effect, asking the library to process any data it might have +buffered internally. In this state, +BZ2_bzCompress will no longer +attempt to read data from +next_in, but it will want to +write data to next_out. Because +the output buffer supplied by the user can be arbitrarily small, +the finishing-up operation cannot necessarily be done with a +single call of +BZ2_bzCompress. + +Instead, the calling program passes +BZ_FINISH as an action to +BZ2_bzCompress. This changes +the stream's state to FINISHING. Any remaining input (ie, +next_in[0 .. avail_in-1]) is +compressed and transferred to the output buffer. To do this, +BZ2_bzCompress must be called +repeatedly until all the output has been consumed. At that +point, BZ2_bzCompress returns +BZ_STREAM_END, and the stream's +state is set back to IDLE. +BZ2_bzCompressEnd should then be +called. + +Just to make sure the calling program does not cheat, the +library makes a note of avail_in +at the time of the first call to +BZ2_bzCompress which has +BZ_FINISH as an action (ie, at +the time the program has announced its intention to not supply +any more input). By comparing this value with that of +avail_in over subsequent calls +to BZ2_bzCompress, the library +can detect any attempts to slip in more data to compress. Any +calls for which this is detected will return +BZ_SEQUENCE_ERROR. This +indicates a programming mistake which should be corrected. + +Instead of asking to finish, the calling program may ask +BZ2_bzCompress to take all the +remaining input, compress it and terminate the current +(Burrows-Wheeler) compression block. This could be useful for +error control purposes. The mechanism is analogous to that for +finishing: call BZ2_bzCompress +with an action of BZ_FLUSH, +remove output data, and persist with the +BZ_FLUSH action until the value +BZ_RUN is returned. As with +finishing, BZ2_bzCompress +detects any attempt to provide more input data once the flush has +begun. + +Once the flush is complete, the stream returns to the +normal RUNNING state. + +This all sounds pretty complex, but isn't really. Here's a +table which shows which actions are allowable in each state, what +action will be taken, what the next state is, and what the +non-error return values are. Note that you can't explicitly ask +what state the stream is in, but nor do you need to -- it can be +inferred from the values returned by +BZ2_bzCompress. + + +IDLE/any + Illegal. IDLE state only exists after BZ2_bzCompressEnd or + before BZ2_bzCompressInit. + Return value = BZ_SEQUENCE_ERROR + +RUNNING/BZ_RUN + Compress from next_in to next_out as much as possible. + Next state = RUNNING + Return value = BZ_RUN_OK + +RUNNING/BZ_FLUSH + Remember current value of next_in. Compress from next_in + to next_out as much as possible, but do not accept any more input. + Next state = FLUSHING + Return value = BZ_FLUSH_OK + +RUNNING/BZ_FINISH + Remember current value of next_in. Compress from next_in + to next_out as much as possible, but do not accept any more input. + Next state = FINISHING + Return value = BZ_FINISH_OK + +FLUSHING/BZ_FLUSH + Compress from next_in to next_out as much as possible, + but do not accept any more input. + If all the existing input has been used up and all compressed + output has been removed + Next state = RUNNING; Return value = BZ_RUN_OK + else + Next state = FLUSHING; Return value = BZ_FLUSH_OK + +FLUSHING/other + Illegal. + Return value = BZ_SEQUENCE_ERROR + +FINISHING/BZ_FINISH + Compress from next_in to next_out as much as possible, + but to not accept any more input. + If all the existing input has been used up and all compressed + output has been removed + Next state = IDLE; Return value = BZ_STREAM_END + else + Next state = FINISHING; Return value = BZ_FINISHING + +FINISHING/other + Illegal. + Return value = BZ_SEQUENCE_ERROR + + + +That still looks complicated? Well, fair enough. The +usual sequence of calls for compressing a load of data is: + + + + Get started with + BZ2_bzCompressInit. + + Shovel data in and shlurp out its compressed form + using zero or more calls of + BZ2_bzCompress with action = + BZ_RUN. + + Finish up. Repeatedly call + BZ2_bzCompress with action = + BZ_FINISH, copying out the + compressed output, until + BZ_STREAM_END is + returned. Close up and go home. Call + BZ2_bzCompressEnd. + + + +If the data you want to compress fits into your input +buffer all at once, you can skip the calls of +BZ2_bzCompress ( ..., BZ_RUN ) +and just do the BZ2_bzCompress ( ..., BZ_FINISH +) calls. + +All required memory is allocated by +BZ2_bzCompressInit. The +compression library can accept any data at all (obviously). So +you shouldn't get any error return values from the +BZ2_bzCompress calls. If you +do, they will be +BZ_SEQUENCE_ERROR, and indicate +a bug in your programming. + +Trivial other possible return values: + + +BZ_PARAM_ERROR + if strm is NULL, or strm->s is NULL + + + + + + +<computeroutput>BZ2_bzCompressEnd</computeroutput> + + +int BZ2_bzCompressEnd ( bz_stream *strm ); + + +Releases all memory associated with a compression +stream. + +Possible return values: + + +BZ_PARAM_ERROR if strm is NULL or strm->s is NULL +BZ_OK otherwise + + + + + + +<computeroutput>BZ2_bzDecompressInit</computeroutput> + + +int BZ2_bzDecompressInit ( bz_stream *strm, int verbosity, int small ); + + +Prepares for decompression. As with +BZ2_bzCompressInit, a +bz_stream record should be +allocated and initialised before the call. Fields +bzalloc, +bzfree and +opaque should be set if a custom +memory allocator is required, or made +NULL for the normal +malloc / +free routines. Upon return, the +internal state will have been initialised, and +total_in and +total_out will be zero. + +For the meaning of parameter +verbosity, see +BZ2_bzCompressInit. + +If small is nonzero, the +library will use an alternative decompression algorithm which +uses less memory but at the cost of decompressing more slowly +(roughly speaking, half the speed, but the maximum memory +requirement drops to around 2300k). See +for more information on memory management. + +Note that the amount of memory needed to decompress a +stream cannot be determined until the stream's header has been +read, so even if +BZ2_bzDecompressInit succeeds, a +subsequent BZ2_bzDecompress +could fail with +BZ_MEM_ERROR. + +Possible return values: + + +BZ_CONFIG_ERROR + if the library has been mis-compiled +BZ_PARAM_ERROR + if ( small != 0 && small != 1 ) + or (verbosity <; 0 || verbosity > 4) +BZ_MEM_ERROR + if insufficient memory is available + + +Allowable next actions: + + +BZ2_bzDecompress + if BZ_OK was returned + no specific action required in case of error + + + + + + +<computeroutput>BZ2_bzDecompress</computeroutput> + + +int BZ2_bzDecompress ( bz_stream *strm ); + + +Provides more input and/out output buffer space for the +library. The caller maintains input and output buffers, and uses +BZ2_bzDecompress to transfer +data between them. + +Before each call to +BZ2_bzDecompress, +next_in should point at the +compressed data, and avail_in +should indicate how many bytes the library may read. +BZ2_bzDecompress updates +next_in, +avail_in and +total_in to reflect the number +of bytes it has read. + +Similarly, next_out should +point to a buffer in which the uncompressed output is to be +placed, with avail_out +indicating how much output space is available. +BZ2_bzCompress updates +next_out, +avail_out and +total_out to reflect the number +of bytes output. + +You may provide and remove as little or as much data as you +like on each call of +BZ2_bzDecompress. In the limit, +it is acceptable to supply and remove data one byte at a time, +although this would be terribly inefficient. You should always +ensure that at least one byte of output space is available at +each call. + +Use of BZ2_bzDecompress is +simpler than +BZ2_bzCompress. + +You should provide input and remove output as described +above, and repeatedly call +BZ2_bzDecompress until +BZ_STREAM_END is returned. +Appearance of BZ_STREAM_END +denotes that BZ2_bzDecompress +has detected the logical end of the compressed stream. +BZ2_bzDecompress will not +produce BZ_STREAM_END until all +output data has been placed into the output buffer, so once +BZ_STREAM_END appears, you are +guaranteed to have available all the decompressed output, and +BZ2_bzDecompressEnd can safely +be called. + +If case of an error return value, you should call +BZ2_bzDecompressEnd to clean up +and release memory. + +Possible return values: + + +BZ_PARAM_ERROR + if strm is NULL or strm->s is NULL + or strm->avail_out < 1 +BZ_DATA_ERROR + if a data integrity error is detected in the compressed stream +BZ_DATA_ERROR_MAGIC + if the compressed stream doesn't begin with the right magic bytes +BZ_MEM_ERROR + if there wasn't enough memory available +BZ_STREAM_END + if the logical end of the data stream was detected and all + output in has been consumed, eg s-->avail_out > 0 +BZ_OK + otherwise + + +Allowable next actions: + + +BZ2_bzDecompress + if BZ_OK was returned +BZ2_bzDecompressEnd + otherwise + + + + + + +<computeroutput>BZ2_bzDecompressEnd</computeroutput> + + +int BZ2_bzDecompressEnd ( bz_stream *strm ); + + +Releases all memory associated with a decompression +stream. + +Possible return values: + + +BZ_PARAM_ERROR + if strm is NULL or strm->s is NULL +BZ_OK + otherwise + + +Allowable next actions: + + + None. + + + + + + + + +High-level interface + +This interface provides functions for reading and writing +bzip2 format files. First, some +general points. + + + + All of the functions take an + int* first argument, + bzerror. After each call, + bzerror should be consulted + first to determine the outcome of the call. If + bzerror is + BZ_OK, the call completed + successfully, and only then should the return value of the + function (if any) be consulted. If + bzerror is + BZ_IO_ERROR, there was an + error reading/writing the underlying compressed file, and you + should then consult errno / + perror to determine the cause + of the difficulty. bzerror + may also be set to various other values; precise details are + given on a per-function basis below. + + If bzerror indicates + an error (ie, anything except + BZ_OK and + BZ_STREAM_END), you should + immediately call + BZ2_bzReadClose (or + BZ2_bzWriteClose, depending on + whether you are attempting to read or to write) to free up all + resources associated with the stream. Once an error has been + indicated, behaviour of all calls except + BZ2_bzReadClose + (BZ2_bzWriteClose) is + undefined. The implication is that (1) + bzerror should be checked + after each call, and (2) if + bzerror indicates an error, + BZ2_bzReadClose + (BZ2_bzWriteClose) should then + be called to clean up. + + The FILE* arguments + passed to BZ2_bzReadOpen / + BZ2_bzWriteOpen should be set + to binary mode. Most Unix systems will do this by default, but + other platforms, including Windows and Mac, will not. If you + omit this, you may encounter problems when moving code to new + platforms. + + Memory allocation requests are handled by + malloc / + free. At present there is no + facility for user-defined memory allocators in the file I/O + functions (could easily be added, though). + + + + + + +<computeroutput>BZ2_bzReadOpen</computeroutput> + + +typedef void BZFILE; + +BZFILE *BZ2_bzReadOpen( int *bzerror, FILE *f, + int verbosity, int small, + void *unused, int nUnused ); + + +Prepare to read compressed data from file handle +f. +f should refer to a file which +has been opened for reading, and for which the error indicator +(ferror(f))is not set. If +small is 1, the library will try +to decompress using less memory, at the expense of speed. + +For reasons explained below, +BZ2_bzRead will decompress the +nUnused bytes starting at +unused, before starting to read +from the file f. At most +BZ_MAX_UNUSED bytes may be +supplied like this. If this facility is not required, you should +pass NULL and +0 for +unused and +nUnused respectively. + +For the meaning of parameters +small and +verbosity, see +BZ2_bzDecompressInit. + +The amount of memory needed to decompress a file cannot be +determined until the file's header has been read. So it is +possible that BZ2_bzReadOpen +returns BZ_OK but a subsequent +call of BZ2_bzRead will return +BZ_MEM_ERROR. + +Possible assignments to +bzerror: + + +BZ_CONFIG_ERROR + if the library has been mis-compiled +BZ_PARAM_ERROR + if f is NULL + or small is neither 0 nor 1 + or ( unused == NULL && nUnused != 0 ) + or ( unused != NULL && !(0 <= nUnused <= BZ_MAX_UNUSED) ) +BZ_IO_ERROR + if ferror(f) is nonzero +BZ_MEM_ERROR + if insufficient memory is available +BZ_OK + otherwise. + + +Possible return values: + + +Pointer to an abstract BZFILE + if bzerror is BZ_OK +NULL + otherwise + + +Allowable next actions: + + +BZ2_bzRead + if bzerror is BZ_OK +BZ2_bzClose + otherwise + + + + + + +<computeroutput>BZ2_bzRead</computeroutput> + + +int BZ2_bzRead ( int *bzerror, BZFILE *b, void *buf, int len ); + + +Reads up to len +(uncompressed) bytes from the compressed file +b into the buffer +buf. If the read was +successful, bzerror is set to +BZ_OK and the number of bytes +read is returned. If the logical end-of-stream was detected, +bzerror will be set to +BZ_STREAM_END, and the number of +bytes read is returned. All other +bzerror values denote an +error. + +BZ2_bzRead will supply +len bytes, unless the logical +stream end is detected or an error occurs. Because of this, it +is possible to detect the stream end by observing when the number +of bytes returned is less than the number requested. +Nevertheless, this is regarded as inadvisable; you should instead +check bzerror after every call +and watch out for +BZ_STREAM_END. + +Internally, BZ2_bzRead +copies data from the compressed file in chunks of size +BZ_MAX_UNUSED bytes before +decompressing it. If the file contains more bytes than strictly +needed to reach the logical end-of-stream, +BZ2_bzRead will almost certainly +read some of the trailing data before signalling +BZ_SEQUENCE_END. To collect the +read but unused data once +BZ_SEQUENCE_END has appeared, +call BZ2_bzReadGetUnused +immediately before +BZ2_bzReadClose. + +Possible assignments to +bzerror: + + +BZ_PARAM_ERROR + if b is NULL or buf is NULL or len < 0 +BZ_SEQUENCE_ERROR + if b was opened with BZ2_bzWriteOpen +BZ_IO_ERROR + if there is an error reading from the compressed file +BZ_UNEXPECTED_EOF + if the compressed file ended before + the logical end-of-stream was detected +BZ_DATA_ERROR + if a data integrity error was detected in the compressed stream +BZ_DATA_ERROR_MAGIC + if the stream does not begin with the requisite header bytes + (ie, is not a bzip2 data file). This is really + a special case of BZ_DATA_ERROR. +BZ_MEM_ERROR + if insufficient memory was available +BZ_STREAM_END + if the logical end of stream was detected. +BZ_OK + otherwise. + + +Possible return values: + + +number of bytes read + if bzerror is BZ_OK or BZ_STREAM_END +undefined + otherwise + + +Allowable next actions: + + +collect data from buf, then BZ2_bzRead or BZ2_bzReadClose + if bzerror is BZ_OK +collect data from buf, then BZ2_bzReadClose or BZ2_bzReadGetUnused + if bzerror is BZ_SEQUENCE_END +BZ2_bzReadClose + otherwise + + + + + + +<computeroutput>BZ2_bzReadGetUnused</computeroutput> + + +void BZ2_bzReadGetUnused( int* bzerror, BZFILE *b, + void** unused, int* nUnused ); + + +Returns data which was read from the compressed file but +was not needed to get to the logical end-of-stream. +*unused is set to the address of +the data, and *nUnused to the +number of bytes. *nUnused will +be set to a value between 0 and +BZ_MAX_UNUSED inclusive. + +This function may only be called once +BZ2_bzRead has signalled +BZ_STREAM_END but before +BZ2_bzReadClose. + +Possible assignments to +bzerror: + + +BZ_PARAM_ERROR + if b is NULL + or unused is NULL or nUnused is NULL +BZ_SEQUENCE_ERROR + if BZ_STREAM_END has not been signalled + or if b was opened with BZ2_bzWriteOpen +BZ_OK + otherwise + + +Allowable next actions: + + +BZ2_bzReadClose + + + + + + +<computeroutput>BZ2_bzReadClose</computeroutput> + + +void BZ2_bzReadClose ( int *bzerror, BZFILE *b ); + + +Releases all memory pertaining to the compressed file +b. +BZ2_bzReadClose does not call +fclose on the underlying file +handle, so you should do that yourself if appropriate. +BZ2_bzReadClose should be called +to clean up after all error situations. + +Possible assignments to +bzerror: + + +BZ_SEQUENCE_ERROR + if b was opened with BZ2_bzOpenWrite +BZ_OK + otherwise + + +Allowable next actions: + + +none + + + + + + +<computeroutput>BZ2_bzWriteOpen</computeroutput> + + +BZFILE *BZ2_bzWriteOpen( int *bzerror, FILE *f, + int blockSize100k, int verbosity, + int workFactor ); + + +Prepare to write compressed data to file handle +f. +f should refer to a file which +has been opened for writing, and for which the error indicator +(ferror(f))is not set. + +For the meaning of parameters +blockSize100k, +verbosity and +workFactor, see +BZ2_bzCompressInit. + +All required memory is allocated at this stage, so if the +call completes successfully, +BZ_MEM_ERROR cannot be signalled +by a subsequent call to +BZ2_bzWrite. + +Possible assignments to +bzerror: + + +BZ_CONFIG_ERROR + if the library has been mis-compiled +BZ_PARAM_ERROR + if f is NULL + or blockSize100k < 1 or blockSize100k > 9 +BZ_IO_ERROR + if ferror(f) is nonzero +BZ_MEM_ERROR + if insufficient memory is available +BZ_OK + otherwise + + +Possible return values: + + +Pointer to an abstract BZFILE + if bzerror is BZ_OK +NULL + otherwise + + +Allowable next actions: + + +BZ2_bzWrite + if bzerror is BZ_OK + (you could go directly to BZ2_bzWriteClose, but this would be pretty pointless) +BZ2_bzWriteClose + otherwise + + + + + + +<computeroutput>BZ2_bzWrite</computeroutput> + + +void BZ2_bzWrite ( int *bzerror, BZFILE *b, void *buf, int len ); + + +Absorbs len bytes from the +buffer buf, eventually to be +compressed and written to the file. + +Possible assignments to +bzerror: + + +BZ_PARAM_ERROR + if b is NULL or buf is NULL or len < 0 +BZ_SEQUENCE_ERROR + if b was opened with BZ2_bzReadOpen +BZ_IO_ERROR + if there is an error writing the compressed file. +BZ_OK + otherwise + + + + + + +<computeroutput>BZ2_bzWriteClose</computeroutput> + + +void BZ2_bzWriteClose( int *bzerror, BZFILE* f, + int abandon, + unsigned int* nbytes_in, + unsigned int* nbytes_out ); + +void BZ2_bzWriteClose64( int *bzerror, BZFILE* f, + int abandon, + unsigned int* nbytes_in_lo32, + unsigned int* nbytes_in_hi32, + unsigned int* nbytes_out_lo32, + unsigned int* nbytes_out_hi32 ); + + +Compresses and flushes to the compressed file all data so +far supplied by BZ2_bzWrite. +The logical end-of-stream markers are also written, so subsequent +calls to BZ2_bzWrite are +illegal. All memory associated with the compressed file +b is released. +fflush is called on the +compressed file, but it is not +fclose'd. + +If BZ2_bzWriteClose is +called to clean up after an error, the only action is to release +the memory. The library records the error codes issued by +previous calls, so this situation will be detected automatically. +There is no attempt to complete the compression operation, nor to +fflush the compressed file. You +can force this behaviour to happen even in the case of no error, +by passing a nonzero value to +abandon. + +If nbytes_in is non-null, +*nbytes_in will be set to be the +total volume of uncompressed data handled. Similarly, +nbytes_out will be set to the +total volume of compressed data written. For compatibility with +older versions of the library, +BZ2_bzWriteClose only yields the +lower 32 bits of these counts. Use +BZ2_bzWriteClose64 if you want +the full 64 bit counts. These two functions are otherwise +absolutely identical. + +Possible assignments to +bzerror: + + +BZ_SEQUENCE_ERROR + if b was opened with BZ2_bzReadOpen +BZ_IO_ERROR + if there is an error writing the compressed file +BZ_OK + otherwise + + + + + + +Handling embedded compressed data streams + +The high-level library facilitates use of +bzip2 data streams which form +some part of a surrounding, larger data stream. + + + + For writing, the library takes an open file handle, + writes compressed data to it, + fflushes it but does not + fclose it. The calling + application can write its own data before and after the + compressed data stream, using that same file handle. + + Reading is more complex, and the facilities are not as + general as they could be since generality is hard to reconcile + with efficiency. BZ2_bzRead + reads from the compressed file in blocks of size + BZ_MAX_UNUSED bytes, and in + doing so probably will overshoot the logical end of compressed + stream. To recover this data once decompression has ended, + call BZ2_bzReadGetUnused after + the last call of BZ2_bzRead + (the one returning + BZ_STREAM_END) but before + calling + BZ2_bzReadClose. + + + +This mechanism makes it easy to decompress multiple +bzip2 streams placed end-to-end. +As the end of one stream, when +BZ2_bzRead returns +BZ_STREAM_END, call +BZ2_bzReadGetUnused to collect +the unused data (copy it into your own buffer somewhere). That +data forms the start of the next compressed stream. To start +uncompressing that next stream, call +BZ2_bzReadOpen again, feeding in +the unused data via the unused / +nUnused parameters. Keep doing +this until BZ_STREAM_END return +coincides with the physical end of file +(feof(f)). In this situation +BZ2_bzReadGetUnused will of +course return no data. + +This should give some feel for how the high-level interface +can be used. If you require extra flexibility, you'll have to +bite the bullet and get to grips with the low-level +interface. + + + + + +Standard file-reading/writing code + +Here's how you'd write data to a compressed file: + + +FILE* f; +BZFILE* b; +int nBuf; +char buf[ /* whatever size you like */ ]; +int bzerror; +int nWritten; + +f = fopen ( "myfile.bz2", "w" ); +if ( !f ) { + /* handle error */ +} +b = BZ2_bzWriteOpen( &bzerror, f, 9 ); +if (bzerror != BZ_OK) { + BZ2_bzWriteClose ( b ); + /* handle error */ +} + +while ( /* condition */ ) { + /* get data to write into buf, and set nBuf appropriately */ + nWritten = BZ2_bzWrite ( &bzerror, b, buf, nBuf ); + if (bzerror == BZ_IO_ERROR) { + BZ2_bzWriteClose ( &bzerror, b ); + /* handle error */ + } +} + +BZ2_bzWriteClose( &bzerror, b ); +if (bzerror == BZ_IO_ERROR) { + /* handle error */ +} + + +And to read from a compressed file: + + +FILE* f; +BZFILE* b; +int nBuf; +char buf[ /* whatever size you like */ ]; +int bzerror; +int nWritten; + +f = fopen ( "myfile.bz2", "r" ); +if ( !f ) { + /* handle error */ +} +b = BZ2_bzReadOpen ( &bzerror, f, 0, NULL, 0 ); +if ( bzerror != BZ_OK ) { + BZ2_bzReadClose ( &bzerror, b ); + /* handle error */ +} + +bzerror = BZ_OK; +while ( bzerror == BZ_OK && /* arbitrary other conditions */) { + nBuf = BZ2_bzRead ( &bzerror, b, buf, /* size of buf */ ); + if ( bzerror == BZ_OK ) { + /* do something with buf[0 .. nBuf-1] */ + } +} +if ( bzerror != BZ_STREAM_END ) { + BZ2_bzReadClose ( &bzerror, b ); + /* handle error */ +} else { + BZ2_bzReadClose ( &bzerror ); +} + + + + + + + + +Utility functions + + + +<computeroutput>BZ2_bzBuffToBuffCompress</computeroutput> + + +int BZ2_bzBuffToBuffCompress( char* dest, + unsigned int* destLen, + char* source, + unsigned int sourceLen, + int blockSize100k, + int verbosity, + int workFactor ); + + +Attempts to compress the data in source[0 +.. sourceLen-1] into the destination buffer, +dest[0 .. *destLen-1]. If the +destination buffer is big enough, +*destLen is set to the size of +the compressed data, and BZ_OK +is returned. If the compressed data won't fit, +*destLen is unchanged, and +BZ_OUTBUFF_FULL is +returned. + +Compression in this manner is a one-shot event, done with a +single call to this function. The resulting compressed data is a +complete bzip2 format data +stream. There is no mechanism for making additional calls to +provide extra input data. If you want that kind of mechanism, +use the low-level interface. + +For the meaning of parameters +blockSize100k, +verbosity and +workFactor, see +BZ2_bzCompressInit. + +To guarantee that the compressed data will fit in its +buffer, allocate an output buffer of size 1% larger than the +uncompressed data, plus six hundred extra bytes. + +BZ2_bzBuffToBuffDecompress +will not write data at or beyond +dest[*destLen], even in case of +buffer overflow. + +Possible return values: + + +BZ_CONFIG_ERROR + if the library has been mis-compiled +BZ_PARAM_ERROR + if dest is NULL or destLen is NULL + or blockSize100k < 1 or blockSize100k > 9 + or verbosity < 0 or verbosity > 4 + or workFactor < 0 or workFactor > 250 +BZ_MEM_ERROR + if insufficient memory is available +BZ_OUTBUFF_FULL + if the size of the compressed data exceeds *destLen +BZ_OK + otherwise + + + + + + +<computeroutput>BZ2_bzBuffToBuffDecompress</computeroutput> + + +int BZ2_bzBuffToBuffDecompress( char* dest, + unsigned int* destLen, + char* source, + unsigned int sourceLen, + int small, + int verbosity ); + + +Attempts to decompress the data in source[0 +.. sourceLen-1] into the destination buffer, +dest[0 .. *destLen-1]. If the +destination buffer is big enough, +*destLen is set to the size of +the uncompressed data, and BZ_OK +is returned. If the compressed data won't fit, +*destLen is unchanged, and +BZ_OUTBUFF_FULL is +returned. + +source is assumed to hold +a complete bzip2 format data +stream. +BZ2_bzBuffToBuffDecompress tries +to decompress the entirety of the stream into the output +buffer. + +For the meaning of parameters +small and +verbosity, see +BZ2_bzDecompressInit. + +Because the compression ratio of the compressed data cannot +be known in advance, there is no easy way to guarantee that the +output buffer will be big enough. You may of course make +arrangements in your code to record the size of the uncompressed +data, but such a mechanism is beyond the scope of this +library. + +BZ2_bzBuffToBuffDecompress +will not write data at or beyond +dest[*destLen], even in case of +buffer overflow. + +Possible return values: + + +BZ_CONFIG_ERROR + if the library has been mis-compiled +BZ_PARAM_ERROR + if dest is NULL or destLen is NULL + or small != 0 && small != 1 + or verbosity < 0 or verbosity > 4 +BZ_MEM_ERROR + if insufficient memory is available +BZ_OUTBUFF_FULL + if the size of the compressed data exceeds *destLen +BZ_DATA_ERROR + if a data integrity error was detected in the compressed data +BZ_DATA_ERROR_MAGIC + if the compressed data doesn't begin with the right magic bytes +BZ_UNEXPECTED_EOF + if the compressed data ends unexpectedly +BZ_OK + otherwise + + + + + + + + +<computeroutput>zlib</computeroutput> compatibility functions + +Yoshioka Tsuneo has contributed some functions to give +better zlib compatibility. +These functions are BZ2_bzopen, +BZ2_bzread, +BZ2_bzwrite, +BZ2_bzflush, +BZ2_bzclose, +BZ2_bzerror and +BZ2_bzlibVersion. These +functions are not (yet) officially part of the library. If they +break, you get to keep all the pieces. Nevertheless, I think +they work ok. + + +typedef void BZFILE; + +const char * BZ2_bzlibVersion ( void ); + + +Returns a string indicating the library version. + + +BZFILE * BZ2_bzopen ( const char *path, const char *mode ); +BZFILE * BZ2_bzdopen ( int fd, const char *mode ); + + +Opens a .bz2 file for +reading or writing, using either its name or a pre-existing file +descriptor. Analogous to fopen +and fdopen. + + +int BZ2_bzread ( BZFILE* b, void* buf, int len ); +int BZ2_bzwrite ( BZFILE* b, void* buf, int len ); + + +Reads/writes data from/to a previously opened +BZFILE. Analogous to +fread and +fwrite. + + +int BZ2_bzflush ( BZFILE* b ); +void BZ2_bzclose ( BZFILE* b ); + + +Flushes/closes a BZFILE. +BZ2_bzflush doesn't actually do +anything. Analogous to fflush +and fclose. + + +const char * BZ2_bzerror ( BZFILE *b, int *errnum ) + + +Returns a string describing the more recent error status of +b, and also sets +*errnum to its numerical +value. + + + + + +Using the library in a <computeroutput>stdio</computeroutput>-free environment + + + +Getting rid of <computeroutput>stdio</computeroutput> + +In a deeply embedded application, you might want to use +just the memory-to-memory functions. You can do this +conveniently by compiling the library with preprocessor symbol +BZ_NO_STDIO defined. Doing this +gives you a library containing only the following eight +functions: + +BZ2_bzCompressInit, +BZ2_bzCompress, +BZ2_bzCompressEnd +BZ2_bzDecompressInit, +BZ2_bzDecompress, +BZ2_bzDecompressEnd +BZ2_bzBuffToBuffCompress, +BZ2_bzBuffToBuffDecompress + +When compiled like this, all functions will ignore +verbosity settings. + + + + + +Critical error handling + +libbzip2 contains a number +of internal assertion checks which should, needless to say, never +be activated. Nevertheless, if an assertion should fail, +behaviour depends on whether or not the library was compiled with +BZ_NO_STDIO set. + +For a normal compile, an assertion failure yields the +message: + +
+bzip2/libbzip2: internal error number N. +This is a bug in bzip2/libbzip2, &bz-version; of &bz-date;. +Please report it to me at: &bz-email;. If this happened +when you were using some program which uses libbzip2 as a +component, you should also report this bug to the author(s) +of that program. Please make an effort to report this bug; +timely and accurate bug reports eventually lead to higher +quality software. Thanks. Julian Seward, &bz-date;. +
+ +where N is some error code +number. If N == 1007, it also +prints some extra text advising the reader that unreliable memory +is often associated with internal error 1007. (This is a +frequently-observed-phenomenon with versions 1.0.0/1.0.1). + +exit(3) is then +called. + +For a stdio-free library, +assertion failures result in a call to a function declared +as: + + +extern void bz_internal_error ( int errcode ); + + +The relevant code is passed as a parameter. You should +supply such a function. + +In either case, once an assertion failure has occurred, any +bz_stream records involved can +be regarded as invalid. You should not attempt to resume normal +operation with them. + +You may, of course, change critical error handling to suit +your needs. As I said above, critical errors indicate bugs in +the library and should not occur. All "normal" error situations +are indicated via error return codes from functions, and can be +recovered from. + +
+ +
+ + + +Making a Windows DLL + +Everything related to Windows has been contributed by +Yoshioka Tsuneo +(QWF00133@niftyserve.or.jp / +tsuneo-y@is.aist-nara.ac.jp), so +you should send your queries to him (but perhaps Cc: me, +&bz-email;). + +My vague understanding of what to do is: using Visual C++ +5.0, open the project file +libbz2.dsp, and build. That's +all. + +If you can't open the project file for some reason, make a +new one, naming these files: +blocksort.c, +bzlib.c, +compress.c, +crctable.c, +decompress.c, +huffman.c, +randtable.c and +libbz2.def. You will also need +to name the header files bzlib.h +and bzlib_private.h. + +If you don't use VC++, you may need to define the +proprocessor symbol +_WIN32. + +Finally, dlltest.c is a +sample program using the DLL. It has a project file, +dlltest.dsp. + +If you just want a makefile for Visual C, have a look at +makefile.msc. + +Be aware that if you compile +bzip2 itself on Win32, you must +set BZ_UNIX to 0 and +BZ_LCCWIN32 to 1, in the file +bzip2.c, before compiling. +Otherwise the resulting binary won't work correctly. + +I haven't tried any of this stuff myself, but it all looks +plausible. + + + +
+ + + + +Miscellanea + +These are just some random thoughts of mine. Your mileage +may vary. + + + +Limitations of the compressed file format + +bzip2-1.0.X, +0.9.5 and +0.9.0 use exactly the same file +format as the original version, +bzip2-0.1. This decision was +made in the interests of stability. Creating yet another +incompatible compressed file format would create further +confusion and disruption for users. + +Nevertheless, this is not a painless decision. Development +work since the release of +bzip2-0.1 in August 1997 has +shown complexities in the file format which slow down +decompression and, in retrospect, are unnecessary. These +are: + + + + The run-length encoder, which is the first of the + compression transformations, is entirely irrelevant. The + original purpose was to protect the sorting algorithm from the + very worst case input: a string of repeated symbols. But + algorithm steps Q6a and Q6b in the original Burrows-Wheeler + technical report (SRC-124) show how repeats can be handled + without difficulty in block sorting. + + The randomisation mechanism doesn't really need to be + there. Udi Manber and Gene Myers published a suffix array + construction algorithm a few years back, which can be employed + to sort any block, no matter how repetitive, in O(N log N) + time. Subsequent work by Kunihiko Sadakane has produced a + derivative O(N (log N)^2) algorithm which usually outperforms + the Manber-Myers algorithm. + + I could have changed to Sadakane's algorithm, but I find + it to be slower than bzip2's + existing algorithm for most inputs, and the randomisation + mechanism protects adequately against bad cases. I didn't + think it was a good tradeoff to make. Partly this is due to + the fact that I was not flooded with email complaints about + bzip2-0.1's performance on + repetitive data, so perhaps it isn't a problem for real + inputs. + + Probably the best long-term solution, and the one I have + incorporated into 0.9.5 and above, is to use the existing + sorting algorithm initially, and fall back to a O(N (log N)^2) + algorithm if the standard algorithm gets into + difficulties. + + The compressed file format was never designed to be + handled by a library, and I have had to jump though some hoops + to produce an efficient implementation of decompression. It's + a bit hairy. Try passing + decompress.c through the C + preprocessor and you'll see what I mean. Much of this + complexity could have been avoided if the compressed size of + each block of data was recorded in the data stream. + + An Adler-32 checksum, rather than a CRC32 checksum, + would be faster to compute. + + + +It would be fair to say that the +bzip2 format was frozen before I +properly and fully understood the performance consequences of +doing so. + +Improvements which I was able to incorporate into 0.9.0, +despite using the same file format, are: + + + + Single array implementation of the inverse BWT. This + significantly speeds up decompression, presumably because it + reduces the number of cache misses. + + Faster inverse MTF transform for large MTF values. + The new implementation is based on the notion of sliding blocks + of values. + + bzip2-0.9.0 now reads + and writes files with fread + and fwrite; version 0.1 used + putc and + getc. Duh! Well, you live + and learn. + + + +Further ahead, it would be nice to be able to do random +access into files. This will require some careful design of +compressed file formats. + + + + + +Portability issues + +After some consideration, I have decided not to use GNU +autoconf to configure 0.9.5 or +1.0. + +autoconf, admirable and +wonderful though it is, mainly assists with portability problems +between Unix-like platforms. But +bzip2 doesn't have much in the +way of portability problems on Unix; most of the difficulties +appear when porting to the Mac, or to Microsoft's operating +systems. autoconf doesn't help +in those cases, and brings in a whole load of new +complexity. + +Most people should be able to compile the library and +program under Unix straight out-of-the-box, so to speak, +especially if you have a version of GNU C available. + +There are a couple of +__inline__ directives in the +code. GNU C (gcc) should be +able to handle them. If you're not using GNU C, your C compiler +shouldn't see them at all. If your compiler does, for some +reason, see them and doesn't like them, just +#define +__inline__ to be +/* */. One easy way to do this +is to compile with the flag +-D__inline__=, which should be +understood by most Unix compilers. + +If you still have difficulties, try compiling with the +macro BZ_STRICT_ANSI defined. +This should enable you to build the library in a strictly ANSI +compliant environment. Building the program itself like this is +dangerous and not supported, since you remove +bzip2's checks against +compressing directories, symbolic links, devices, and other +not-really-a-file entities. This could cause filesystem +corruption! + +One other thing: if you create a +bzip2 binary for public distribution, +please consider linking it statically (gcc +-static). This avoids all sorts of library-version +issues that others may encounter later on. + +If you build bzip2 on +Win32, you must set BZ_UNIX to 0 +and BZ_LCCWIN32 to 1, in the +file bzip2.c, before compiling. +Otherwise the resulting binary won't work correctly. + + + + + +Reporting bugs + +I tried pretty hard to make sure +bzip2 is bug free, both by +design and by testing. Hopefully you'll never need to read this +section for real. + +Nevertheless, if bzip2 dies +with a segmentation fault, a bus error or an internal assertion +failure, it will ask you to email me a bug report. Experience from +years of feedback of bzip2 users indicates that almost all these +problems can be traced to either compiler bugs or hardware +problems. + + + + Recompile the program with no optimisation, and + see if it works. And/or try a different compiler. I heard all + sorts of stories about various flavours of GNU C (and other + compilers) generating bad code for + bzip2, and I've run across two + such examples myself. + + 2.7.X versions of GNU C are known to generate bad code + from time to time, at high optimisation levels. If you get + problems, try using the flags + -O2 + -fomit-frame-pointer + -fno-strength-reduce. You + should specifically not use + -funroll-loops. + + You may notice that the Makefile runs six tests as part + of the build process. If the program passes all of these, it's + a pretty good (but not 100%) indication that the compiler has + done its job correctly. + + If bzip2 + crashes randomly, and the crashes are not repeatable, you may + have a flaky memory subsystem. + bzip2 really hammers your + memory hierarchy, and if it's a bit marginal, you may get these + problems. Ditto if your disk or I/O subsystem is slowly + failing. Yup, this really does happen. + + Try using a different machine of the same type, and see + if you can repeat the problem. + + This isn't really a bug, but ... If + bzip2 tells you your file is + corrupted on decompression, and you obtained the file via FTP, + there is a possibility that you forgot to tell FTP to do a + binary mode transfer. That absolutely will cause the file to + be non-decompressible. You'll have to transfer it + again. + + + +If you've incorporated +libbzip2 into your own program +and are getting problems, please, please, please, check that the +parameters you are passing in calls to the library, are correct, +and in accordance with what the documentation says is allowable. +I have tried to make the library robust against such problems, +but I'm sure I haven't succeeded. + +Finally, if the above comments don't help, you'll have to +send me a bug report. Now, it's just amazing how many people +will send me a bug report saying something like: + + +bzip2 crashed with segmentation fault on my machine + + +and absolutely nothing else. Needless to say, a such a +report is totally, utterly, completely and +comprehensively 100% useless; a waste of your time, my time, and +net bandwidth. With no details at all, there's no way +I can possibly begin to figure out what the problem is. + +The rules of the game are: facts, facts, facts. Don't omit +them because "oh, they won't be relevant". At the bare +minimum: + + +Machine type. Operating system version. +Exact version of bzip2 (do bzip2 -V). +Exact version of the compiler used. +Flags passed to the compiler. + + +However, the most important single thing that will help me +is the file that you were trying to compress or decompress at the +time the problem happened. Without that, my ability to do +anything more than speculate about the cause, is limited. + + + + + +Did you get the right package? + +bzip2 is a resource hog. +It soaks up large amounts of CPU cycles and memory. Also, it +gives very large latencies. In the worst case, you can feed many +megabytes of uncompressed data into the library before getting +any compressed output, so this probably rules out applications +requiring interactive behaviour. + +These aren't faults of my implementation, I hope, but more +an intrinsic property of the Burrows-Wheeler transform +(unfortunately). Maybe this isn't what you want. + +If you want a compressor and/or library which is faster, +uses less memory but gets pretty good compression, and has +minimal latency, consider Jean-loup Gailly's and Mark Adler's +work, zlib-1.2.1 and +gzip-1.2.4. Look for them at +http://www.zlib.org and +http://www.gzip.org +respectively. + +For something faster and lighter still, you might try Markus F +X J Oberhumer's LZO real-time +compression/decompression library, at +http://www.oberhumer.com/opensource. + + + + + + +Further Reading + +bzip2 is not research +work, in the sense that it doesn't present any new ideas. +Rather, it's an engineering exercise based on existing +ideas. + +Four documents describe essentially all the ideas behind +bzip2: + +Michael Burrows and D. J. Wheeler: + "A block-sorting lossless data compression algorithm" + 10th May 1994. + Digital SRC Research Report 124. + ftp://ftp.digital.com/pub/DEC/SRC/research-reports/SRC-124.ps.gz + If you have trouble finding it, try searching at the + New Zealand Digital Library, http://www.nzdl.org. + +Daniel S. Hirschberg and Debra A. LeLewer + "Efficient Decoding of Prefix Codes" + Communications of the ACM, April 1990, Vol 33, Number 4. + You might be able to get an electronic copy of this + from the ACM Digital Library. + +David J. Wheeler + Program bred3.c and accompanying document bred3.ps. + This contains the idea behind the multi-table Huffman coding scheme. + ftp://ftp.cl.cam.ac.uk/users/djw3/ + +Jon L. Bentley and Robert Sedgewick + "Fast Algorithms for Sorting and Searching Strings" + Available from Sedgewick's web page, + www.cs.princeton.edu/~rs + + +The following paper gives valuable additional insights into +the algorithm, but is not immediately the basis of any code used +in bzip2. + +Peter Fenwick: + Block Sorting Text Compression + Proceedings of the 19th Australasian Computer Science Conference, + Melbourne, Australia. Jan 31 - Feb 2, 1996. + ftp://ftp.cs.auckland.ac.nz/pub/peter-f/ACSC96paper.ps + +Kunihiko Sadakane's sorting algorithm, mentioned above, is +available from: + +http://naomi.is.s.u-tokyo.ac.jp/~sada/papers/Sada98b.ps.gz + + +The Manber-Myers suffix array construction algorithm is +described in a paper available from: + +http://www.cs.arizona.edu/people/gene/PAPERS/suffix.ps + + +Finally, the following papers document some +investigations I made into the performance of sorting +and decompression algorithms: + +Julian Seward + On the Performance of BWT Sorting Algorithms + Proceedings of the IEEE Data Compression Conference 2000 + Snowbird, Utah. 28-30 March 2000. + +Julian Seward + Space-time Tradeoffs in the Inverse B-W Transform + Proceedings of the IEEE Data Compression Conference 2001 + Snowbird, Utah. 27-29 March 2001. + + + + + + +
diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/mk251.c b/contrib/vmap_extractor_v2/stormlib/bzip2/mk251.c new file mode 100644 index 00000000000..205778a84e6 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/bzip2/mk251.c @@ -0,0 +1,16 @@ + +/* Spew out a long sequence of the byte 251. When fed to bzip2 + versions 1.0.0 or 1.0.1, causes it to die with internal error + 1007 in blocksort.c. This assertion misses an extremely rare + case, which is fixed in this version (1.0.2) and above. +*/ + +#include + +int main () +{ + int i; + for (i = 0; i < 48500000 ; i++) + putchar(251); + return 0; +} diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/randtable.c b/contrib/vmap_extractor_v2/stormlib/bzip2/randtable.c new file mode 100644 index 00000000000..940462d693d --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/bzip2/randtable.c @@ -0,0 +1,124 @@ + +/*-------------------------------------------------------------*/ +/*--- Table for randomising repetitive blocks ---*/ +/*--- randtable.c ---*/ +/*-------------------------------------------------------------*/ + +/*-- + This file is a part of bzip2 and/or libbzip2, a program and + library for lossless, block-sorting data compression. + + Copyright (C) 1996-2005 Julian R Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Julian Seward, Cambridge, UK. + jseward@bzip.org + bzip2/libbzip2 version 1.0 of 21 March 2000 + + This program is based on (at least) the work of: + Mike Burrows + David Wheeler + Peter Fenwick + Alistair Moffat + Radford Neal + Ian H. Witten + Robert Sedgewick + Jon L. Bentley + + For more information on these sources, see the manual. +--*/ + + +#include "bzlib_private.h" + + +/*---------------------------------------------*/ +Int32 BZ2_rNums[512] = { + 619, 720, 127, 481, 931, 816, 813, 233, 566, 247, + 985, 724, 205, 454, 863, 491, 741, 242, 949, 214, + 733, 859, 335, 708, 621, 574, 73, 654, 730, 472, + 419, 436, 278, 496, 867, 210, 399, 680, 480, 51, + 878, 465, 811, 169, 869, 675, 611, 697, 867, 561, + 862, 687, 507, 283, 482, 129, 807, 591, 733, 623, + 150, 238, 59, 379, 684, 877, 625, 169, 643, 105, + 170, 607, 520, 932, 727, 476, 693, 425, 174, 647, + 73, 122, 335, 530, 442, 853, 695, 249, 445, 515, + 909, 545, 703, 919, 874, 474, 882, 500, 594, 612, + 641, 801, 220, 162, 819, 984, 589, 513, 495, 799, + 161, 604, 958, 533, 221, 400, 386, 867, 600, 782, + 382, 596, 414, 171, 516, 375, 682, 485, 911, 276, + 98, 553, 163, 354, 666, 933, 424, 341, 533, 870, + 227, 730, 475, 186, 263, 647, 537, 686, 600, 224, + 469, 68, 770, 919, 190, 373, 294, 822, 808, 206, + 184, 943, 795, 384, 383, 461, 404, 758, 839, 887, + 715, 67, 618, 276, 204, 918, 873, 777, 604, 560, + 951, 160, 578, 722, 79, 804, 96, 409, 713, 940, + 652, 934, 970, 447, 318, 353, 859, 672, 112, 785, + 645, 863, 803, 350, 139, 93, 354, 99, 820, 908, + 609, 772, 154, 274, 580, 184, 79, 626, 630, 742, + 653, 282, 762, 623, 680, 81, 927, 626, 789, 125, + 411, 521, 938, 300, 821, 78, 343, 175, 128, 250, + 170, 774, 972, 275, 999, 639, 495, 78, 352, 126, + 857, 956, 358, 619, 580, 124, 737, 594, 701, 612, + 669, 112, 134, 694, 363, 992, 809, 743, 168, 974, + 944, 375, 748, 52, 600, 747, 642, 182, 862, 81, + 344, 805, 988, 739, 511, 655, 814, 334, 249, 515, + 897, 955, 664, 981, 649, 113, 974, 459, 893, 228, + 433, 837, 553, 268, 926, 240, 102, 654, 459, 51, + 686, 754, 806, 760, 493, 403, 415, 394, 687, 700, + 946, 670, 656, 610, 738, 392, 760, 799, 887, 653, + 978, 321, 576, 617, 626, 502, 894, 679, 243, 440, + 680, 879, 194, 572, 640, 724, 926, 56, 204, 700, + 707, 151, 457, 449, 797, 195, 791, 558, 945, 679, + 297, 59, 87, 824, 713, 663, 412, 693, 342, 606, + 134, 108, 571, 364, 631, 212, 174, 643, 304, 329, + 343, 97, 430, 751, 497, 314, 983, 374, 822, 928, + 140, 206, 73, 263, 980, 736, 876, 478, 430, 305, + 170, 514, 364, 692, 829, 82, 855, 953, 676, 246, + 369, 970, 294, 750, 807, 827, 150, 790, 288, 923, + 804, 378, 215, 828, 592, 281, 565, 555, 710, 82, + 896, 831, 547, 261, 524, 462, 293, 465, 502, 56, + 661, 821, 976, 991, 658, 869, 905, 758, 745, 193, + 768, 550, 608, 933, 378, 286, 215, 979, 792, 961, + 61, 688, 793, 644, 986, 403, 106, 366, 905, 644, + 372, 567, 466, 434, 645, 210, 389, 550, 919, 135, + 780, 773, 635, 389, 707, 100, 626, 958, 165, 504, + 920, 176, 193, 713, 857, 265, 203, 50, 668, 108, + 645, 990, 626, 197, 510, 357, 358, 850, 858, 364, + 936, 638 +}; + + +/*-------------------------------------------------------------*/ +/*--- end randtable.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/sample1.bz2 b/contrib/vmap_extractor_v2/stormlib/bzip2/sample1.bz2 new file mode 100644 index 00000000000..18dea60043b Binary files /dev/null and b/contrib/vmap_extractor_v2/stormlib/bzip2/sample1.bz2 differ diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/sample1.ref b/contrib/vmap_extractor_v2/stormlib/bzip2/sample1.ref new file mode 100644 index 00000000000..a56e52b77f9 Binary files /dev/null and b/contrib/vmap_extractor_v2/stormlib/bzip2/sample1.ref differ diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/sample2.bz2 b/contrib/vmap_extractor_v2/stormlib/bzip2/sample2.bz2 new file mode 100644 index 00000000000..d5a6160ba20 Binary files /dev/null and b/contrib/vmap_extractor_v2/stormlib/bzip2/sample2.bz2 differ diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/sample2.ref b/contrib/vmap_extractor_v2/stormlib/bzip2/sample2.ref new file mode 100644 index 00000000000..34af95839a0 Binary files /dev/null and b/contrib/vmap_extractor_v2/stormlib/bzip2/sample2.ref differ diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/sample3.bz2 b/contrib/vmap_extractor_v2/stormlib/bzip2/sample3.bz2 new file mode 100644 index 00000000000..d90cff9208f Binary files /dev/null and b/contrib/vmap_extractor_v2/stormlib/bzip2/sample3.bz2 differ diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/sample3.ref b/contrib/vmap_extractor_v2/stormlib/bzip2/sample3.ref new file mode 100644 index 00000000000..775a2f68e21 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/bzip2/sample3.ref @@ -0,0 +1,30007 @@ +This file is exceedingly boring. If you find yourself +reading it, please (1) take it from me that you can safely +guess what the rest of the file says, and (2) seek professional +help. + +ps. there are no further sarcastic remarks in this file. + +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh +ugh diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/spewG.c b/contrib/vmap_extractor_v2/stormlib/bzip2/spewG.c new file mode 100644 index 00000000000..7934e765818 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/bzip2/spewG.c @@ -0,0 +1,39 @@ + +/* spew out a thoroughly gigantic file designed so that bzip2 + can compress it reasonably rapidly. This is to help test + support for large files (> 2GB) in a reasonable amount of time. + I suggest you use the undocumented --exponential option to + bzip2 when compressing the resulting file; this saves a bit of + time. Note: *don't* bother with --exponential when compressing + Real Files; it'll just waste a lot of CPU time :-) + (but is otherwise harmless). +*/ + +#define _FILE_OFFSET_BITS 64 + +#include +#include + +/* The number of megabytes of junk to spew out (roughly) */ +#define MEGABYTES 5000 + +#define N_BUF 1000000 +char buf[N_BUF]; + +int main ( int argc, char** argv ) +{ + int ii, kk, p; + srandom(1); + setbuffer ( stdout, buf, N_BUF ); + for (kk = 0; kk < MEGABYTES * 515; kk+=3) { + p = 25+random()%50; + for (ii = 0; ii < p; ii++) + printf ( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ); + for (ii = 0; ii < p-1; ii++) + printf ( "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" ); + for (ii = 0; ii < p+1; ii++) + printf ( "ccccccccccccccccccccccccccccccccccccc" ); + } + fflush(stdout); + return 0; +} diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/unzcrash.c b/contrib/vmap_extractor_v2/stormlib/bzip2/unzcrash.c new file mode 100644 index 00000000000..f0f17fcca53 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/bzip2/unzcrash.c @@ -0,0 +1,126 @@ + +/* A test program written to test robustness to decompression of + corrupted data. Usage is + unzcrash filename + and the program will read the specified file, compress it (in memory), + and then repeatedly decompress it, each time with a different bit of + the compressed data inverted, so as to test all possible one-bit errors. + This should not cause any invalid memory accesses. If it does, + I want to know about it! + + p.s. As you can see from the above description, the process is + incredibly slow. A file of size eg 5KB will cause it to run for + many hours. +*/ + +#include +#include +#include "bzlib.h" + +#define M_BLOCK 1000000 + +typedef unsigned char uchar; + +#define M_BLOCK_OUT (M_BLOCK + 1000000) +uchar inbuf[M_BLOCK]; +uchar outbuf[M_BLOCK_OUT]; +uchar zbuf[M_BLOCK + 600 + (M_BLOCK / 100)]; + +int nIn, nOut, nZ; + +static char *bzerrorstrings[] = { + "OK" + ,"SEQUENCE_ERROR" + ,"PARAM_ERROR" + ,"MEM_ERROR" + ,"DATA_ERROR" + ,"DATA_ERROR_MAGIC" + ,"IO_ERROR" + ,"UNEXPECTED_EOF" + ,"OUTBUFF_FULL" + ,"???" /* for future */ + ,"???" /* for future */ + ,"???" /* for future */ + ,"???" /* for future */ + ,"???" /* for future */ + ,"???" /* for future */ +}; + +void flip_bit ( int bit ) +{ + int byteno = bit / 8; + int bitno = bit % 8; + uchar mask = 1 << bitno; + //fprintf ( stderr, "(byte %d bit %d mask %d)", + // byteno, bitno, (int)mask ); + zbuf[byteno] ^= mask; +} + +int main ( int argc, char** argv ) +{ + FILE* f; + int r; + int bit; + int i; + + if (argc != 2) { + fprintf ( stderr, "usage: unzcrash filename\n" ); + return 1; + } + + f = fopen ( argv[1], "r" ); + if (!f) { + fprintf ( stderr, "unzcrash: can't open %s\n", argv[1] ); + return 1; + } + + nIn = fread ( inbuf, 1, M_BLOCK, f ); + fprintf ( stderr, "%d bytes read\n", nIn ); + + nZ = M_BLOCK; + r = BZ2_bzBuffToBuffCompress ( + zbuf, &nZ, inbuf, nIn, 9, 0, 30 ); + + assert (r == BZ_OK); + fprintf ( stderr, "%d after compression\n", nZ ); + + for (bit = 0; bit < nZ*8; bit++) { + fprintf ( stderr, "bit %d ", bit ); + flip_bit ( bit ); + nOut = M_BLOCK_OUT; + r = BZ2_bzBuffToBuffDecompress ( + outbuf, &nOut, zbuf, nZ, 0, 0 ); + fprintf ( stderr, " %d %s ", r, bzerrorstrings[-r] ); + + if (r != BZ_OK) { + fprintf ( stderr, "\n" ); + } else { + if (nOut != nIn) { + fprintf(stderr, "nIn/nOut mismatch %d %d\n", nIn, nOut ); + return 1; + } else { + for (i = 0; i < nOut; i++) + if (inbuf[i] != outbuf[i]) { + fprintf(stderr, "mismatch at %d\n", i ); + return 1; + } + if (i == nOut) fprintf(stderr, "really ok!\n" ); + } + } + + flip_bit ( bit ); + } + +#if 0 + assert (nOut == nIn); + for (i = 0; i < nOut; i++) { + if (inbuf[i] != outbuf[i]) { + fprintf ( stderr, "difference at %d !\n", i ); + return 1; + } + } +#endif + + fprintf ( stderr, "all ok\n" ); + return 0; +} diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/words0 b/contrib/vmap_extractor_v2/stormlib/bzip2/words0 new file mode 100644 index 00000000000..164a8ed287a --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/bzip2/words0 @@ -0,0 +1,5 @@ + +If compilation produces errors, or a large number of warnings, +please read README.COMPILATION.PROBLEMS -- you might be able to +adjust the flags in this Makefile to improve matters. + diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/words1 b/contrib/vmap_extractor_v2/stormlib/bzip2/words1 new file mode 100644 index 00000000000..2e83de9f083 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/bzip2/words1 @@ -0,0 +1,4 @@ + +Doing 6 tests (3 compress, 3 uncompress) ... +If there's a problem, things might stop at this point. + diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/words2 b/contrib/vmap_extractor_v2/stormlib/bzip2/words2 new file mode 100644 index 00000000000..203ee39c4c2 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/bzip2/words2 @@ -0,0 +1,5 @@ + +Checking test results. If any of the four "cmp"s which follow +report any differences, something is wrong. If you can't easily +figure out what, please let me know (jseward@acm.org). + diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/words3 b/contrib/vmap_extractor_v2/stormlib/bzip2/words3 new file mode 100644 index 00000000000..7a6b462443c --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/bzip2/words3 @@ -0,0 +1,23 @@ + +If you got this far and the "cmp"s didn't complain, it looks +like you're in business. + +To install in /usr/bin, /usr/lib, /usr/man and /usr/include, type + make install +To install somewhere else, eg, /xxx/yyy/{bin,lib,man,include}, type + make install PREFIX=/xxx/yyy +If you are (justifiably) paranoid and want to see what 'make install' +is going to do, you can first do + make -n install or + make -n install PREFIX=/xxx/yyy respectively. +The -n instructs make to show the commands it would execute, but +not actually execute them. + +Instructions for use are in the preformatted manual page, in the file +bzip2.txt. For more detailed documentation, read the full manual. +It is available in Postscript form (manual.ps), PDF form (manual.pdf), +and HTML form (manual_toc.html). + +You can also do "bzip2 --help" to see some helpful information. +"bzip2 -L" displays the software license. + diff --git a/contrib/vmap_extractor_v2/stormlib/bzip2/xmlproc.sh b/contrib/vmap_extractor_v2/stormlib/bzip2/xmlproc.sh new file mode 100644 index 00000000000..6fe4d5748bb --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/bzip2/xmlproc.sh @@ -0,0 +1,99 @@ +#!/bin/bash +# see the README in this directory for usage etc. + +usage() { + echo ''; + echo 'Usage: xmlproc.sh -[option] '; + echo 'Specify a target from:'; + echo '-v verify xml file conforms to dtd'; + echo '-html output in html format (single file)'; + echo '-ps output in postscript format'; + echo '-pdf output in pdf format'; + exit; +} + +if test $# -ne 2; then + usage +fi +# assign the variable for the output type +action=$1; shift +# assign the output filename +xmlfile=$1; shift +# and check user input it correct +if !(test -f $xmlfile); then + echo "No such file: $xmlfile"; + exit; +fi +# some other stuff we will use +OUT=output +xsl_fo=bz-fo.xsl +xsl_html=bz-html.xsl + +basename=$xmlfile +basename=${basename//'.xml'/''} + +fofile="${basename}.fo" +htmlfile="${basename}.html" +pdffile="${basename}.pdf" +psfile="${basename}.ps" +xmlfmtfile="${basename}.fmt" + +# first process the xmlfile with CDATA tags +./format.pl $xmlfile $xmlfmtfile +# so the shell knows where the catalogs live +export XML_CATALOG_FILES=/etc/xml/catalog + +# post-processing tidy up +cleanup() { + echo "Cleaning up: # $@" + while [ $# != 0 ] + do + arg=$1; shift; + echo " deleting $arg"; + rm $arg + done +} + +case $action in + -v) + flags='--noout --xinclude --noblanks --postvalid' + dtd='--dtdvalid http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd' + xmllint $flags $dtd $xmlfmtfile 2> $OUT + egrep 'error' $OUT + rm $OUT + ;; + + -html) + echo "Creating $htmlfile ..." + xsltproc --nonet --xinclude -o $htmlfile $xsl_html $xmlfmtfile + cleanup $xmlfmtfile + ;; + + -pdf) + echo "Creating $pdffile ..." + xsltproc --nonet --xinclude -o $fofile $xsl_fo $xmlfmtfile + pdfxmltex $fofile >$OUT $OUT $OUT $OUT $OUT $OUT $OUT $OUT $OUT 0x80000000) */ +/*****************************************************************************/ + +#include +#include + +#include "huff.h" + +// Special for Mac - we have to know if normal pointer greater or less +// than 0x80000000. This variable is used in the PTR_VALID and PTR_INVALID +// macros +static long mul = 1; + +#define PTR_VALID(ptr) (((LONG_PTR)(ptr) * mul) > 0) +#define PTR_INVALID(ptr) (((LONG_PTR)(ptr) * mul) < 0) +#define PTR_INVALID_OR_NULL(ptr) (((LONG_PTR)(ptr) * mul) <= 0) + + +//----------------------------------------------------------------------------- +// Methods of the THTreeItem struct + +// 1501DB70 +THTreeItem * THTreeItem::Call1501DB70(THTreeItem * pLast) +{ + if(pLast == NULL) + pLast = this + 1; + return pLast; +} + +// Gets previous Huffman tree item (?) +THTreeItem * THTreeItem::GetPrevItem(LONG_PTR value) +{ + if(PTR_INVALID(prev)) + return PTR_NOT(prev); + + if(value == -1 || PTR_INVALID(value)) + value = (long)(this - next->prev); + return prev + value; + +// OLD VERSION +// if(PTR_INT(value) < 0) +// value = PTR_INT((item - item->next->prev)); +// return (THTreeItem *)((char *)prev + value); +} + +// 1500F5E0 +void THTreeItem::ClearItemLinks() +{ + next = prev = NULL; +} + +// 1500BC90 +void THTreeItem::RemoveItem() +{ + THTreeItem * pTemp; // EDX + + if(next != NULL) + { + pTemp = prev; + + if(PTR_INVALID_OR_NULL(pTemp)) + pTemp = PTR_NOT(pTemp); + else + pTemp += (this - next->prev); + + pTemp->next = next; + next->prev = prev; + next = prev = NULL; + } +} + +/* +// OLD VERSION : Removes item from the tree (?) +static void RemoveItem(THTreeItem * item) +{ + THTreeItem * next = item->next; // ESI + THTreeItem * prev = item->prev; // EDX + + if(next == NULL) + return; + + if(PTR_INT(prev) < 0) + prev = PTR_NOT(prev); + else + // ??? usually item == next->prev, so what is it ? + prev = (THTreeItem *)((unsigned char *)prev + (unsigned long)((unsigned char *)item - (unsigned char *)(next->prev))); + + // Remove HTree item from the chain + prev->next = next; // Sets the 'first' pointer + next->prev = item->prev; + + // Invalidate pointers + item->next = NULL; + item->prev = NULL; +} +*/ + +//----------------------------------------------------------------------------- +// TOutputStream functions + +void TOutputStream::PutBits(unsigned long dwBuff, unsigned int nPutBits) +{ + dwBitBuff |= (dwBuff << nBits); + nBits += nPutBits; + + // Flush completed bytes + while(nBits >= 8) + { + if(dwOutSize != 0) + { + *pbOutPos++ = (unsigned char)dwBitBuff; + dwOutSize--; + } + + dwBitBuff >>= 8; + nBits -= 8; + } +} + +//----------------------------------------------------------------------------- +// TInputStream functions + +// Gets one bit from input stream +unsigned long TInputStream::GetBit() +{ + unsigned long dwBit = (dwBitBuff & 1); + + dwBitBuff >>= 1; + if(--nBits == 0) + { + dwBitBuff = BSWAP_INT32_UNSIGNED(*(unsigned long *)pbInBuffer); + pbInBuffer += sizeof(unsigned long); + nBits = 32; + } + return dwBit; +} + +// Gets 7 bits from the stream +unsigned long TInputStream::Get7Bits() +{ + if(nBits <= 7) + { + dwBitBuff |= BSWAP_INT16_UNSIGNED(*(unsigned short *)pbInBuffer) << nBits; + pbInBuffer += sizeof(unsigned short); + nBits += 16; + } + + // Get 7 bits from input stream + return (dwBitBuff & 0x7F); +} + +// Gets the whole byte from the input stream. +unsigned long TInputStream::Get8Bits() +{ + unsigned long dwOneByte; + + if(nBits <= 8) + { + dwBitBuff |= BSWAP_INT16_UNSIGNED(*(unsigned short *)pbInBuffer) << nBits; + pbInBuffer += sizeof(unsigned short); + nBits += 16; + } + + dwOneByte = (dwBitBuff & 0xFF); + dwBitBuff >>= 8; + nBits -= 8; + return dwOneByte; +} + +//----------------------------------------------------------------------------- +// Functions for huffmann tree items + +// Inserts item into the tree (?) +static void InsertItem(THTreeItem ** itemPtr, THTreeItem * item, unsigned long where, THTreeItem * item2) +{ + THTreeItem * next = item->next; // EDI - next to the first item + THTreeItem * prev = item->prev; // ESI - prev to the first item + THTreeItem * prev2; // Pointer to previous item + LONG_PTR next2; // Pointer to the next item + + // The same code like in RemoveItem(item); + if(next != 0) // If the first item already has next one + { + if(PTR_INVALID(prev)) + prev = PTR_NOT(prev); + else + prev += (item - next->prev); + + // 150083C1 + // Remove the item from the tree + prev->next = next; + next->prev = prev; + + // Invalidate 'prev' and 'next' pointer + item->next = 0; + item->prev = 0; + } + + if(item2 == NULL) // EDX - If the second item is not entered, + item2 = PTR_PTR(&itemPtr[1]); // take the first tree item + + switch(where) + { + case SWITCH_ITEMS : // Switch the two items + item->next = item2->next; // item2->next (Pointer to pointer to first) + item->prev = item2->next->prev; + item2->next->prev = item; + item2->next = item; // Set the first item + return; + + case INSERT_ITEM: // Insert as the last item + item->next = item2; // Set next item (or pointer to pointer to first item) + item->prev = item2->prev; // Set prev item (or last item in the tree) + + next2 = PTR_INT(itemPtr[0]);// Usually NULL + prev2 = item2->prev; // Prev item to the second (or last tree item) + + if(PTR_INVALID(prev2)) + { + prev2 = PTR_NOT(prev); + + prev2->next = item; + item2->prev = item; // Next after last item + return; + } + + if(PTR_INVALID(next2)) + next2 = (long)(item2 - item2->next->prev); +// next2 = (THTreeItem *)(unsigned long)((unsigned char *)item2 - (unsigned char *)(item2->next->prev)); + +// prev2 = (THTreeItem *)((char *)prev2 + (unsigned long)next2);// ??? + prev2 += next2; + prev2->next = item; + item2->prev = item; // Set the next/last item + return; + + default: + return; + } +} + +//----------------------------------------------------------------------------- +// THuffmannTree class functions + +THuffmannTree::THuffmannTree() +{ + // We have to check if the "this" pointer is less than zero + if((LONG_PTR)this < 0) + mul = -1; +} + +void THuffmannTree::InitTree(bool bCompression) +{ + THTreeItem * pItem; + unsigned int nCount; + + // Clear links for all the items in the tree + for(pItem = items0008, nCount = 0x203; nCount != 0; pItem++, nCount--) + pItem->ClearItemLinks(); + + pItem3050 = NULL; + pItem3054 = PTR_PTR(&pItem3054); + pItem3058 = PTR_NOT(pItem3054); + + pItem305C = NULL; + pFirst = PTR_PTR(&pFirst); + pLast = PTR_NOT(pFirst); + + offs0004 = 1; + nItems = 0; + + // Clear all TQDecompress items. Do this only if preparing for decompression + if(bCompression == false) + { + for(nCount = 0; nCount < sizeof(qd3474) / sizeof(TQDecompress); nCount++) + qd3474[nCount].offs00 = 0; + } +} + +// Builds Huffman tree. Called with the first 8 bits loaded from input stream +void THuffmannTree::BuildTree(unsigned int nCmpType) +{ + unsigned long maxByte; // [ESP+10] - The greatest character found in table + THTreeItem ** itemPtr; // [ESP+14] - Pointer to Huffman tree item pointer array + unsigned char * byteArray; // [ESP+1C] - Pointer to unsigned char in Table1502A630 + THTreeItem * child1; + unsigned long i; // egcs in linux doesn't like multiple for loops without an explicit i + + // Loop while pointer has a valid value + while(PTR_VALID(pLast)) // ESI - Last entry + { + THTreeItem * temp; // EAX + + if(pLast->next != NULL) // ESI->next + pLast->RemoveItem(); + // EDI = &offs3054 + pItem3058 = PTR_PTR(&pItem3054);// [EDI+4] + pLast->prev = pItem3058; // EAX + + temp = PTR_PTR(&pItem3054)->GetPrevItem(PTR_INT(&pItem3050)); + + temp->next = pLast; + pItem3054 = pLast; + } + + // Clear all pointers in HTree item array + memset(items306C, 0, sizeof(items306C)); + + maxByte = 0; // Greatest character found init to zero. + itemPtr = (THTreeItem **)&items306C; // Pointer to current entry in HTree item pointer array + + // Ensure we have low 8 bits only + nCmpType &= 0xFF; + byteArray = Table1502A630 + nCmpType * 258; // EDI also + + for(i = 0; i < 0x100; i++, itemPtr++) + { + THTreeItem * item = pItem3058; // Item to be created + THTreeItem * pItem3 = pItem3058; + unsigned char oneByte = byteArray[i]; + + // Skip all the bytes which are zero. + if(byteArray[i] == 0) + continue; + + // If not valid pointer, take the first available item in the array + if(PTR_INVALID_OR_NULL(item)) + item = &items0008[nItems++]; + + // Insert this item as the top of the tree + InsertItem(&pItem305C, item, SWITCH_ITEMS, NULL); + + item->parent = NULL; // Invalidate child and parent + item->child = NULL; + *itemPtr = item; // Store pointer into pointer array + + item->dcmpByte = i; // Store counter + item->byteValue = oneByte; // Store byte value + if(oneByte >= maxByte) + { + maxByte = oneByte; + continue; + } + + // Find the first item which has byte value greater than current one byte + if(PTR_VALID(pItem3 = pLast)) // EDI - Pointer to the last item + { + // 15006AF7 + if(pItem3 != NULL) + { + do // 15006AFB + { + if(pItem3->byteValue >= oneByte) + goto _15006B09; + pItem3 = pItem3->prev; + } + while(PTR_VALID(pItem3)); + } + } + pItem3 = NULL; + + // 15006B09 + _15006B09: + if(item->next != NULL) + item->RemoveItem(); + + // 15006B15 + if(pItem3 == NULL) + pItem3 = PTR_PTR(&pFirst); + + // 15006B1F + item->next = pItem3->next; + item->prev = pItem3->next->prev; + pItem3->next->prev = item; + pItem3->next = item; + } + + // 15006B4A + for(; i < 0x102; i++) + { + THTreeItem ** itemPtr = &items306C[i]; // EDI + + // 15006B59 + THTreeItem * item = pItem3058; // ESI + if(PTR_INVALID_OR_NULL(item)) + item = &items0008[nItems++]; + + InsertItem(&pItem305C, item, INSERT_ITEM, NULL); + + // 15006B89 + item->dcmpByte = i; + item->byteValue = 1; + item->parent = NULL; + item->child = NULL; + *itemPtr++ = item; + } + + // 15006BAA + if(PTR_VALID(child1 = pLast)) // EDI - last item (first child to item + { + THTreeItem * child2; // EBP + THTreeItem * item; // ESI + + // 15006BB8 + while(PTR_VALID(child2 = child1->prev)) + { + if(PTR_INVALID_OR_NULL(item = pItem3058)) + item = &items0008[nItems++]; + + // 15006BE3 + InsertItem(&pItem305C, item, SWITCH_ITEMS, NULL); + + // 15006BF3 + item->parent = NULL; + item->child = NULL; + + //EDX = child2->byteValue + child1->byteValue; + //EAX = child1->byteValue; + //ECX = maxByte; // The greatest character (0xFF usually) + + item->byteValue = child1->byteValue + child2->byteValue; // 0x02 + item->child = child1; // Prev item in the + child1->parent = item; + child2->parent = item; + + // EAX = item->byteValue; + if(item->byteValue >= maxByte) + maxByte = item->byteValue; + else + { + THTreeItem * pItem2 = child2->prev; // EDI + + // 15006C2D + while(PTR_VALID(pItem2)) + { + if(pItem2->byteValue >= item->byteValue) + goto _15006C3B; + pItem2 = pItem2->prev; + } + pItem2 = NULL; + + _15006C3B: + if(item->next != 0) + { + THTreeItem * temp4 = item->GetPrevItem(-1); + + temp4->next = item->next; // The first item changed + item->next->prev = item->prev; // First->prev changed to negative value + item->next = NULL; + item->prev = NULL; + } + + // 15006C62 + if(pItem2 == NULL) + pItem2 = PTR_PTR(&pFirst); + + item->next = pItem2->next; // Set item with 0x100 byte value + item->prev = pItem2->next->prev; // Set item with 0x17 byte value + pItem2->next->prev = item; // Changed prev of item with + pItem2->next = item; + } + + // 15006C7B + if(PTR_INVALID_OR_NULL(child1 = child2->prev)) + break; + } + } + // 15006C88 + offs0004 = 1; +} +/* +// Modifies Huffman tree. Adds new item and changes +void THuffmannTree::ModifyTree(unsigned long dwIndex) +{ + THTreeItem * pItem1 = pItem3058; // ESI + THTreeItem * pSaveLast = (PTR_INT(pLast) <= 0) ? NULL : pLast; // EBX + THTreeItem * temp; // EAX + + // Prepare the first item to insert to the tree + if(PTR_INT(pItem1) <= 0) + pItem1 = &items0008[nItems++]; + + // If item has any next item, remove it from the chain + if(pItem1->next != NULL) + { + THTreeItem * temp = pItem1->GetPrevItem(-1); // EAX + + temp->next = pItem1->next; + pItem1->next->prev = pItem1->prev; + pItem1->next = NULL; + pItem1->prev = NULL; + } + + pItem1->next = PTR_PTR(&pFirst); + pItem1->prev = pLast; + temp = pItem1->next->GetPrevItem(PTR_INT(pItem305C)); + + // 150068E9 + temp->next = pItem1; + pLast = pItem1; + + pItem1->parent = NULL; + pItem1->child = NULL; + + // 150068F6 + pItem1->dcmpByte = pSaveLast->dcmpByte; // Copy item index + pItem1->byteValue = pSaveLast->byteValue; // Copy item byte value + pItem1->parent = pSaveLast; // Set parent to last item + items306C[pSaveLast->dcmpByte] = pItem1; // Insert item into item pointer array + + // Prepare the second item to insert into the tree + if(PTR_INT((pItem1 = pItem3058)) <= 0) + pItem1 = &items0008[nItems++]; + + // 1500692E + if(pItem1->next != NULL) + { + temp = pItem1->GetPrevItem(-1); // EAX + + temp->next = pItem1->next; + pItem1->next->prev = pItem1->prev; + pItem1->next = NULL; + pItem1->prev = NULL; + } + // 1500694C + pItem1->next = PTR_PTR(&pFirst); + pItem1->prev = pLast; + temp = pItem1->next->GetPrevItem(PTR_INT(pItem305C)); + + // 15006968 + temp->next = pItem1; + pLast = pItem1; + + // 1500696E + pItem1->child = NULL; + pItem1->dcmpByte = dwIndex; + pItem1->byteValue = 0; + pItem1->parent = pSaveLast; + pSaveLast->child = pItem1; + items306C[dwIndex] = pItem1; + + do + { + THTreeItem * pItem2 = pItem1; + THTreeItem * pItem3; + unsigned long byteValue; + + // 15006993 + byteValue = ++pItem1->byteValue; + + // Pass through all previous which have its value greater than byteValue + while(PTR_INT((pItem3 = pItem2->prev)) > 0) // EBX + { + if(pItem3->byteValue >= byteValue) + goto _150069AE; + + pItem2 = pItem2->prev; + } + // 150069AC + pItem3 = NULL; + + _150069AE: + if(pItem2 == pItem1) + continue; + + // 150069B2 + // Switch pItem2 with item + InsertItem(&pItem305C, pItem2, SWITCH_ITEMS, pItem1); + InsertItem(&pItem305C, pItem1, SWITCH_ITEMS, pItem3); + + // 150069D0 + // Switch parents of pItem1 and pItem2 + temp = pItem2->parent->child; + if(pItem1 == pItem1->parent->child) + pItem1->parent->child = pItem2; + + if(pItem2 == temp) + pItem2->parent->child = pItem1; + + // 150069ED + // Switch parents of pItem1 and pItem3 + temp = pItem1->parent; + pItem1 ->parent = pItem2->parent; + pItem2->parent = temp; + offs0004++; + } + while(PTR_INT((pItem1 = pItem1->parent)) > 0); +} + +void THuffmannTree::UninitTree() +{ + while(PTR_INT(pLast) > 0) + { + pItem = pItem305C->Call1501DB70(pLast); + pItem->RemoveItem(); + } + + for(pItem = pFirst; PTR_INT(pItem3058) > 0; pItem = pItem3058) + pItem->RemoveItem(); + PTR_PTR(&pItem3054)->RemoveItem(); + + for(pItem = items0008 + 0x203, nCount = 0x203; nCount != 0; nCount--) + { + pItem--; + pItem->RemoveItem(); + pItem->RemoveItem(); + } +} +*/ + +THTreeItem * THuffmannTree::Call1500E740(unsigned int nValue) +{ + THTreeItem * pItem1 = pItem3058; // EDX + THTreeItem * pItem2; // EAX + THTreeItem * pNext; + THTreeItem * pPrev; + THTreeItem ** ppItem; + + if(PTR_INVALID_OR_NULL(pItem1) || (pItem2 = pItem1) == NULL) + { + if((pItem2 = &items0008[nItems++]) != NULL) + pItem1 = pItem2; + else + pItem1 = pFirst; + } + else + pItem1 = pItem2; + + pNext = pItem1->next; + if(pNext != NULL) + { + pPrev = pItem1->prev; + if(PTR_INVALID_OR_NULL(pPrev)) + pPrev = PTR_NOT(pPrev); + else + pPrev += (pItem1 - pItem1->next->prev); + + pPrev->next = pNext; + pNext->prev = pPrev; + pItem1->next = NULL; + pItem1->prev = NULL; + } + + ppItem = &pFirst; // esi + if(nValue > 1) + { + // ecx = pFirst->next; + pItem1->next = *ppItem; + pItem1->prev = (*ppItem)->prev; + + (*ppItem)->prev = pItem2; + *ppItem = pItem1; + + pItem2->parent = NULL; + pItem2->child = NULL; + } + else + { + pItem1->next = (THTreeItem *)ppItem; + pItem1->prev = ppItem[1]; + // edi = pItem305C; + pPrev = ppItem[1]; // ecx + if(PTR_INVALID_OR_NULL(pPrev)) + { + pPrev = PTR_NOT(pPrev); + pPrev->next = pItem1; + pPrev->prev = pItem2; + + pItem2->parent = NULL; + pItem2->child = NULL; + } + else + { + if(PTR_INVALID(pItem305C)) + pPrev += (THTreeItem *)ppItem - (*ppItem)->prev; + else + pPrev += PTR_INT(pItem305C); + + pPrev->next = pItem1; + ppItem[1] = pItem2; + pItem2->parent = NULL; + pItem2->child = NULL; + } + } + return pItem2; +} + +void THuffmannTree::Call1500E820(THTreeItem * pItem) +{ + THTreeItem * pItem1; // edi + THTreeItem * pItem2 = NULL; // eax + THTreeItem * pItem3; // edx + THTreeItem * pPrev; // ebx + + for(; pItem != NULL; pItem = pItem->parent) + { + pItem->byteValue++; + + for(pItem1 = pItem; ; pItem1 = pPrev) + { + pPrev = pItem1->prev; + if(PTR_INVALID_OR_NULL(pPrev)) + { + pPrev = NULL; + break; + } + + if(pPrev->byteValue >= pItem->byteValue) + break; + } + + if(pItem1 == pItem) + continue; + + if(pItem1->next != NULL) + { + pItem2 = pItem1->GetPrevItem(-1); + pItem2->next = pItem1->next; + pItem1->next->prev = pItem1->prev; + pItem1->next = NULL; + pItem1->prev = NULL; + } + + pItem2 = pItem->next; + pItem1->next = pItem2; + pItem1->prev = pItem2->prev; + pItem2->prev = pItem1; + pItem->next = pItem1; + if((pItem2 = pItem1) != NULL) + { + pItem2 = pItem->GetPrevItem(-1); + pItem2->next = pItem->next; + pItem->next->prev = pItem->prev; + pItem->next = NULL; + pItem->prev = NULL; + } + + if(pPrev == NULL) + pPrev = PTR_PTR(&pFirst); + + pItem2 = pPrev->next; + pItem->next = pItem2; + pItem->prev = pItem2->prev; + pItem2->prev = pItem; + pPrev->next = pItem; + + pItem3 = pItem1->parent->child; + pItem2 = pItem->parent; + if(pItem2->child == pItem) + pItem2->child = pItem1; + if(pItem3 == pItem1) + pItem1->parent->child = pItem; + + pItem2 = pItem->parent; + pItem->parent = pItem1->parent; + pItem1->parent = pItem2; + offs0004++; + } +} + +// 1500E920 +unsigned int THuffmannTree::DoCompression(TOutputStream * os, unsigned char * pbInBuffer, int nInLength, int nCmpType) +{ + THTreeItem * pItem1; + THTreeItem * pItem2; + THTreeItem * pItem3; + THTreeItem * pTemp; + unsigned long dwBitBuff; + unsigned int nBits; + unsigned int nBit; + + BuildTree(nCmpType); + bIsCmp0 = (nCmpType == 0); + + // Store the compression type into output buffer + os->dwBitBuff |= (nCmpType << os->nBits); + os->nBits += 8; + + // Flush completed bytes + while(os->nBits >= 8) + { + if(os->dwOutSize != 0) + { + *os->pbOutPos++ = (unsigned char)os->dwBitBuff; + os->dwOutSize--; + } + + os->dwBitBuff >>= 8; + os->nBits -= 8; + } + + for(; nInLength != 0; nInLength--) + { + unsigned char bOneByte = *pbInBuffer++; + + if((pItem1 = items306C[bOneByte]) == NULL) + { + pItem2 = items306C[0x101]; // ecx + pItem3 = pItem2->parent; // eax + dwBitBuff = 0; + nBits = 0; + + for(; pItem3 != NULL; pItem3 = pItem3->parent) + { + nBit = (pItem3->child != pItem2) ? 1 : 0; + dwBitBuff = (dwBitBuff << 1) | nBit; + nBits++; + pItem2 = pItem3; + } + os->PutBits(dwBitBuff, nBits); + + // Store the loaded byte into output stream + os->dwBitBuff |= (bOneByte << os->nBits); + os->nBits += 8; + + // Flush the whole byte(s) + while(os->nBits >= 8) + { + if(os->dwOutSize != 0) + { + *os->pbOutPos++ = (unsigned char)os->dwBitBuff; + os->dwOutSize--; + } + os->dwBitBuff >>= 8; + os->nBits -= 8; + } + + pItem1 = (PTR_INVALID_OR_NULL(pLast)) ? NULL : pLast; + pItem2 = Call1500E740(1); + pItem2->dcmpByte = pItem1->dcmpByte; + pItem2->byteValue = pItem1->byteValue; + pItem2->parent = pItem1; + items306C[pItem2->dcmpByte] = pItem2; + + pItem2 = Call1500E740(1); + pItem2->dcmpByte = bOneByte; + pItem2->byteValue = 0; + pItem2->parent = pItem1; + items306C[pItem2->dcmpByte] = pItem2; + pItem1->child = pItem2; + + Call1500E820(pItem2); + + if(bIsCmp0 != 0) + { + Call1500E820(items306C[bOneByte]); + continue; + } + + for(pItem1 = items306C[bOneByte]; pItem1 != NULL; pItem1 = pItem1->parent) + { + pItem1->byteValue++; + pItem2 = pItem1; + + for(;;) + { + pItem3 = pItem2->prev; + if(PTR_INVALID_OR_NULL(pItem3)) + { + pItem3 = NULL; + break; + } + if(pItem3->byteValue >= pItem1->byteValue) + break; + pItem2 = pItem3; + } + + if(pItem2 != pItem1) + { + InsertItem(&pItem305C, pItem2, SWITCH_ITEMS, pItem1); + InsertItem(&pItem305C, pItem1, SWITCH_ITEMS, pItem3); + + pItem3 = pItem2->parent->child; + if(pItem1->parent->child == pItem1) + pItem1->parent->child = pItem2; + + if(pItem3 == pItem2) + pItem2->parent->child = pItem1; + + pTemp = pItem1->parent; + pItem1->parent = pItem2->parent; + pItem2->parent = pTemp; + offs0004++; + } + } + } +// 1500EB62 + else + { + dwBitBuff = 0; + nBits = 0; + for(pItem2 = pItem1->parent; pItem2 != NULL; pItem2 = pItem2->parent) + { + nBit = (pItem2->child != pItem1) ? 1 : 0; + dwBitBuff = (dwBitBuff << 1) | nBit; + nBits++; + pItem1 = pItem2; + } + os->PutBits(dwBitBuff, nBits); + } + +// 1500EB98 + if(bIsCmp0 != 0) + Call1500E820(items306C[bOneByte]); // 1500EB9D +// 1500EBAF + } // for(; nInLength != 0; nInLength--) + +// 1500EBB8 + pItem1 = items306C[0x100]; + dwBitBuff = 0; + nBits = 0; + for(pItem2 = pItem1->parent; pItem2 != NULL; pItem2 = pItem2->parent) + { + nBit = (pItem2->child != pItem1) ? 1 : 0; + dwBitBuff = (dwBitBuff << 1) | nBit; + nBits++; + pItem1 = pItem2; + } + +// 1500EBE6 + os->PutBits(dwBitBuff, nBits); + +// 1500EBEF + // Flush the remaining bits + while(os->nBits != 0) + { + if(os->dwOutSize != 0) + { + *os->pbOutPos++ = (unsigned char)os->dwBitBuff; + os->dwOutSize--; + } + os->dwBitBuff >>= 8; + os->nBits -= ((os->nBits > 8) ? 8 : os->nBits); + } + + return (unsigned int)(os->pbOutPos - os->pbOutBuffer); +} + +// Decompression using Huffman tree (1500E450) +unsigned int THuffmannTree::DoDecompression(unsigned char * pbOutBuffer, unsigned int dwOutLength, TInputStream * is) +{ + TQDecompress * qd; + THTreeItem * pItem1; + THTreeItem * pItem2; + unsigned char * pbOutPos = pbOutBuffer; + unsigned long nBitCount; + unsigned int nDcmpByte = 0; + unsigned int n8Bits; // 8 bits loaded from input stream + unsigned int n7Bits; // 7 bits loaded from input stream + bool bHasQdEntry; + + // Test the output length. Must not be NULL. + if(dwOutLength == 0) + return 0; + + // Get the compression type from the input stream + n8Bits = is->Get8Bits(); + + // Build the Huffman tree + BuildTree(n8Bits); + bIsCmp0 = (n8Bits == 0) ? 1 : 0; + + for(;;) + { + n7Bits = is->Get7Bits(); // Get 7 bits from input stream + + // Try to use quick decompression. Check TQDecompress array for corresponding item. + // If found, ise the result byte instead. + qd = &qd3474[n7Bits]; + + // If there is a quick-pass possible (ebx) + bHasQdEntry = (qd->offs00 >= offs0004) ? true : false; + + // If we can use quick decompress, use it. + if(bHasQdEntry) + { + if(qd->nBits > 7) + { + is->dwBitBuff >>= 7; + is->nBits -= 7; + pItem1 = qd->pItem; + goto _1500E549; + } + is->dwBitBuff >>= qd->nBits; + is->nBits -= qd->nBits; + nDcmpByte = qd->dcmpByte; + } + else + { + pItem1 = pFirst->next->prev; + if(PTR_INVALID_OR_NULL(pItem1)) + pItem1 = NULL; +_1500E549: + nBitCount = 0; + pItem2 = NULL; + + do + { + pItem1 = pItem1->child; // Move down by one level + if(is->GetBit()) // If current bit is set, move to previous + pItem1 = pItem1->prev; + + if(++nBitCount == 7) // If we are at 7th bit, save current HTree item. + pItem2 = pItem1; + } + while(pItem1->child != NULL); // Walk until tree has no deeper level + + if(bHasQdEntry == false) + { + if(nBitCount > 7) + { + qd->offs00 = offs0004; + qd->nBits = nBitCount; + qd->pItem = pItem2; + } + else + { + unsigned long nIndex = n7Bits & (0xFFFFFFFF >> (32 - nBitCount)); + unsigned long nAdd = (1 << nBitCount); + + for(qd = &qd3474[nIndex]; nIndex <= 0x7F; nIndex += nAdd, qd += nAdd) + { + qd->offs00 = offs0004; + qd->nBits = nBitCount; + qd->dcmpByte = pItem1->dcmpByte; + } + } + } + nDcmpByte = pItem1->dcmpByte; + } + + if(nDcmpByte == 0x101) // Huffman tree needs to be modified + { + n8Bits = is->Get8Bits(); + pItem1 = (PTR_INVALID_OR_NULL(pLast)) ? NULL : pLast; + + pItem2 = Call1500E740(1); + pItem2->parent = pItem1; + pItem2->dcmpByte = pItem1->dcmpByte; + pItem2->byteValue = pItem1->byteValue; + items306C[pItem2->dcmpByte] = pItem2; + + pItem2 = Call1500E740(1); + pItem2->parent = pItem1; + pItem2->dcmpByte = n8Bits; + pItem2->byteValue = 0; + items306C[pItem2->dcmpByte] = pItem2; + + pItem1->child = pItem2; + Call1500E820(pItem2); + if(bIsCmp0 == 0) + Call1500E820(items306C[n8Bits]); + + nDcmpByte = n8Bits; + } + + if(nDcmpByte == 0x100) + break; + + *pbOutPos++ = (unsigned char)nDcmpByte; + if(--dwOutLength == 0) + break; + + if(bIsCmp0) + Call1500E820(items306C[nDcmpByte]); + } + + return (unsigned int)(pbOutPos - pbOutBuffer); +} + +/* OLD VERSION +unsigned int THuffmannTree::DoDecompression(unsigned char * pbOutBuffer, unsigned int dwOutLength, TInputStream * is) +{ + THTreeItem * pItem1; // Current item if walking HTree + unsigned long bitCount; // Bit counter if walking HTree + unsigned long oneByte; // 8 bits from bit stream/Pointer to target + unsigned char * outPtr; // Current pointer to output buffer + bool hasQDEntry; // true if entry for quick decompression if filled + THTreeItem * itemAt7 = NULL; // HTree item found at 7th bit + THTreeItem * temp; // For every use + unsigned long dcmpByte = 0; // Decompressed byte value + bool bFlag = 0; + + // Test the output length. Must not be NULL. + if(dwOutLength == 0) + return 0; + + // If too few bits in input bit buffer, we have to load next 16 bits + is->EnsureHasMoreThan8Bits(); + + // Get 8 bits from input stream + oneByte = is->Get8Bits(); + + // Build the Huffman tree + BuildTree(oneByte); + + bIsCmp0 = (oneByte == 0) ? 1 : 0; + outPtr = pbOutBuffer; // Copy pointer to output data + + for(;;) + { + TQDecompress * qd; // For quick decompress + unsigned long sevenBits = is->Get7Bits();// 7 bits from input stream + + // Try to use quick decompression. Check TQDecompress array for corresponding item. + // If found, ise the result byte instead. + qd = &qd3474[sevenBits]; + + // If there is a quick-pass possible + hasQDEntry = (qd->offs00 == offs0004) ? 1 : 0; + + // Start passing the Huffman tree. Set item to tree root item + pItem1 = pFirst; + + // If we can use quick decompress, use it. + bFlag = 1; + if(hasQDEntry == 1) + { + // Check the bit count is greater than 7, move item to 7 levels deeper + if((bitCount = qd->bitCount) > 7) + { + is->dwBitBuff >>= 7; + is->nBits -= 7; + pItem1 = qd->item; // Don't start with root item, but with some deeper-laying + } + else + { + // If OK, use their byte value + is->dwBitBuff >>= bitCount; + is->nBits -= bitCount; + dcmpByte = qd->dcmpByte; + bFlag = 0; + } + } + else + { + pItem1 = pFirst->next->prev; + if(PTR_INT(pItem1) <= 0) + pItem1 = NULL; + } + + if(bFlag == 1) + { + // Walk through Huffman Tree + bitCount = 0; // Clear bit counter + do + { + pItem1 = pItem1->child; + if(is->GetBit() != 0) // If current bit is set, move to previous + pItem1 = pItem1->prev; // item in current level + + if(++bitCount == 7) // If we are at 7th bit, store current HTree item. + itemAt7 = pItem1; // Store Huffman tree item + } + while(pItem1->child != NULL); // Walk until tree has no deeper level + + // If quick decompress entry is not filled yet, fill it. + if(hasQDEntry == 0) + { + if(bitCount > 7) // If we passed more than 7 bits, store bitCount and item + { + qd->offs00 = offs0004; // Value indicates that entry is resolved + qd->bitCount = bitCount; // Number of bits passed + qd->item = itemAt7; // Store item at 7th bit + } + // If we passed less than 7 bits, fill entry and bit count multipliers + else + { + unsigned long index = sevenBits & (0xFFFFFFFF >> (32 - bitCount)); // Index for quick-decompress entry + unsigned long addIndex = (1 << bitCount); // Add value for index + + qd = &qd3474[index]; + + do + { + qd->offs00 = offs0004; + qd->bitCount = bitCount; + qd->dcmpByte = pItem1->dcmpByte; + + index += addIndex; + qd += addIndex; + } + while(index <= 0x7F); + } + } + dcmpByte = pItem1->dcmpByte; + } + + if(dcmpByte == 0x101) // Huffman tree needs to be modified + { + // Check if there is enough bits in the buffer + is->EnsureHasMoreThan8Bits(); + + // Get 8 bits from the buffer + oneByte = is->Get8Bits(); + + // Modify Huffman tree + ModifyTree(oneByte); + + // Get lastly added tree item + pItem1 = items306C[oneByte]; + + if(bIsCmp0 == 0 && pItem1 != NULL) + { + // 15006F15 + do + { + THTreeItem * pItem2 = pItem1; + THTreeItem * pItem3; + unsigned long byteValue; + + byteValue = ++pItem1->byteValue; + + while(PTR_INT((pItem3 = pItem2->prev)) > 0) + { + if(pItem3->byteValue >= byteValue) + goto _15006F30; + + pItem2 = pItem2->prev; + } + pItem3 = NULL; + + _15006F30: + if(pItem2 == pItem1) + continue; + + InsertItem(&pItem305C, pItem2, SWITCH_ITEMS, pItem1); + InsertItem(&pItem305C, pItem1, SWITCH_ITEMS, pItem3); + + temp = pItem2->parent->child; + if(pItem1 == pItem1->parent->child) + pItem1->parent->child = pItem2; + + if(pItem2 == temp) + pItem2->parent->child = pItem1; + + // Switch parents of pItem1 and pItem3 + temp = pItem1->parent; + pItem1->parent = pItem2->parent; + pItem2->parent = temp; + offs0004++; + } + while(PTR_INT((pItem1 = pItem1->parent)) > 0); + } + dcmpByte = oneByte; + } + + if(dcmpByte != 0x100) // Not at the end of data ? + { + *outPtr++ = (unsigned char)dcmpByte; + if(--dwOutLength > 0) + { + if(bIsCmp0 != 0) + Call1500E820(items306C[pItem1->byteValue]); + } + else + break; + } + else + break; + } + return (unsigned long)(outPtr - pbOutBuffer); +} +*/ + +// Table for (de)compression. Every compression type has 258 entries +unsigned char THuffmannTree::Table1502A630[] = +{ + // Data for compression type 0x00 + 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, + + // Data for compression type 0x01 + 0x54, 0x16, 0x16, 0x0D, 0x0C, 0x08, 0x06, 0x05, 0x06, 0x05, 0x06, 0x03, 0x04, 0x04, 0x03, 0x05, + 0x0E, 0x0B, 0x14, 0x13, 0x13, 0x09, 0x0B, 0x06, 0x05, 0x04, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02, + 0x0D, 0x07, 0x09, 0x06, 0x06, 0x04, 0x03, 0x02, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, + 0x09, 0x06, 0x04, 0x04, 0x04, 0x04, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x04, + 0x08, 0x03, 0x04, 0x07, 0x09, 0x05, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, + 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, + 0x06, 0x0A, 0x08, 0x08, 0x06, 0x07, 0x04, 0x03, 0x04, 0x04, 0x02, 0x02, 0x04, 0x02, 0x03, 0x03, + 0x04, 0x03, 0x07, 0x07, 0x09, 0x06, 0x04, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x0A, 0x02, 0x02, 0x03, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x06, 0x03, 0x05, 0x02, 0x03, + 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x03, 0x01, 0x01, 0x01, + 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x04, 0x04, 0x04, 0x07, 0x09, 0x08, 0x0C, 0x02, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x03, + 0x04, 0x01, 0x02, 0x04, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, + 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x06, 0x4B, + 0x00, 0x00, + + // Data for compression type 0x02 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x27, 0x00, 0x00, 0x23, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x06, 0x0E, 0x10, 0x04, + 0x06, 0x08, 0x05, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 0x01, 0x01, 0x02, 0x01, 0x01, + 0x01, 0x04, 0x02, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01, 0x04, 0x01, 0x01, 0x02, 0x03, 0x03, 0x02, + 0x03, 0x01, 0x03, 0x06, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x01, 0x01, + 0x01, 0x29, 0x07, 0x16, 0x12, 0x40, 0x0A, 0x0A, 0x11, 0x25, 0x01, 0x03, 0x17, 0x10, 0x26, 0x2A, + 0x10, 0x01, 0x23, 0x23, 0x2F, 0x10, 0x06, 0x07, 0x02, 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + + // Data for compression type 0x03 + 0xFF, 0x0B, 0x07, 0x05, 0x0B, 0x02, 0x02, 0x02, 0x06, 0x02, 0x02, 0x01, 0x04, 0x02, 0x01, 0x03, + 0x09, 0x01, 0x01, 0x01, 0x03, 0x04, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, + 0x05, 0x01, 0x01, 0x01, 0x0D, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x0A, 0x04, 0x02, 0x01, 0x06, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, + 0x05, 0x02, 0x03, 0x04, 0x03, 0x03, 0x03, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x03, 0x03, + 0x01, 0x03, 0x01, 0x01, 0x02, 0x05, 0x01, 0x01, 0x04, 0x03, 0x05, 0x01, 0x03, 0x01, 0x03, 0x03, + 0x02, 0x01, 0x04, 0x03, 0x0A, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x01, 0x0A, 0x02, 0x05, 0x01, 0x01, 0x02, 0x07, 0x02, 0x17, 0x01, 0x05, 0x01, 0x01, + 0x0E, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x06, 0x02, 0x01, 0x04, 0x05, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x11, + 0x00, 0x00, + + // Data for compression type 0x04 + 0xFF, 0xFB, 0x98, 0x9A, 0x84, 0x85, 0x63, 0x64, 0x3E, 0x3E, 0x22, 0x22, 0x13, 0x13, 0x18, 0x17, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + + // Data for compression type 0x05 + 0xFF, 0xF1, 0x9D, 0x9E, 0x9A, 0x9B, 0x9A, 0x97, 0x93, 0x93, 0x8C, 0x8E, 0x86, 0x88, 0x80, 0x82, + 0x7C, 0x7C, 0x72, 0x73, 0x69, 0x6B, 0x5F, 0x60, 0x55, 0x56, 0x4A, 0x4B, 0x40, 0x41, 0x37, 0x37, + 0x2F, 0x2F, 0x27, 0x27, 0x21, 0x21, 0x1B, 0x1C, 0x17, 0x17, 0x13, 0x13, 0x10, 0x10, 0x0D, 0x0D, + 0x0B, 0x0B, 0x09, 0x09, 0x08, 0x08, 0x07, 0x07, 0x06, 0x05, 0x05, 0x04, 0x04, 0x04, 0x19, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + + // Data for compression type 0x06 + 0xC3, 0xCB, 0xF5, 0x41, 0xFF, 0x7B, 0xF7, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xBF, 0xCC, 0xF2, 0x40, 0xFD, 0x7C, 0xF7, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7A, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + + // Data for compression type 0x07 + 0xC3, 0xD9, 0xEF, 0x3D, 0xF9, 0x7C, 0xE9, 0x1E, 0xFD, 0xAB, 0xF1, 0x2C, 0xFC, 0x5B, 0xFE, 0x17, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xBD, 0xD9, 0xEC, 0x3D, 0xF5, 0x7D, 0xE8, 0x1D, 0xFB, 0xAE, 0xF0, 0x2C, 0xFB, 0x5C, 0xFF, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x70, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + + // Data for compression type 0x08 + 0xBA, 0xC5, 0xDA, 0x33, 0xE3, 0x6D, 0xD8, 0x18, 0xE5, 0x94, 0xDA, 0x23, 0xDF, 0x4A, 0xD1, 0x10, + 0xEE, 0xAF, 0xE4, 0x2C, 0xEA, 0x5A, 0xDE, 0x15, 0xF4, 0x87, 0xE9, 0x21, 0xF6, 0x43, 0xFC, 0x12, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xB0, 0xC7, 0xD8, 0x33, 0xE3, 0x6B, 0xD6, 0x18, 0xE7, 0x95, 0xD8, 0x23, 0xDB, 0x49, 0xD0, 0x11, + 0xE9, 0xB2, 0xE2, 0x2B, 0xE8, 0x5C, 0xDD, 0x15, 0xF1, 0x87, 0xE7, 0x20, 0xF7, 0x44, 0xFF, 0x13, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x5F, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 +}; \ No newline at end of file diff --git a/contrib/vmap_extractor_v2/stormlib/huffman/huff.h b/contrib/vmap_extractor_v2/stormlib/huffman/huff.h new file mode 100644 index 00000000000..f06aa771acd --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/huffman/huff.h @@ -0,0 +1,142 @@ +/*****************************************************************************/ +/* huffman.h Copyright (c) Ladislav Zezula 2003 */ +/*---------------------------------------------------------------------------*/ +/* Description : */ +/*---------------------------------------------------------------------------*/ +/* Date Ver Who Comment */ +/* -------- ---- --- ------- */ +/* xx.xx.xx 1.00 Lad The first version of huffman.h */ +/* 03.05.03 2.00 Lad Added compression */ +/* 08.12.03 2.01 Dan High-memory handling (> 0x80000000) */ +/*****************************************************************************/ + +#ifndef __HUFFMAN_H__ +#define __HUFFMAN_H__ + +#include "../StormPort.h" + +//----------------------------------------------------------------------------- +// Defines + +#define INSERT_ITEM 1 +#define SWITCH_ITEMS 2 // Switch the item1 and item2 + +#define PTR_NOT(ptr) (THTreeItem *)(~(DWORD_PTR)(ptr)) +#define PTR_PTR(ptr) ((THTreeItem *)(ptr)) +#define PTR_INT(ptr) (LONG_PTR)(ptr) + +#ifndef NULL +#define NULL 0 +#endif + +//----------------------------------------------------------------------------- +// Structures and classes + +// Input stream for Huffmann decompression +class TInputStream +{ + public: + + unsigned long GetBit(); + unsigned long Get7Bits(); + unsigned long Get8Bits(); + + unsigned char * pbInBuffer; // 00 - Input data + unsigned long dwBitBuff; // 04 - Input bit buffer + unsigned int nBits; // 08 - Number of bits remaining in 'dwValue' +}; + +// Output stream for Huffmann compression +class TOutputStream +{ + public: + + void PutBits(unsigned long dwBuff, unsigned int nPutBits); + + unsigned char * pbOutBuffer; // 00 : Output buffer + unsigned long dwOutSize; // 04 : Size of output buffer + unsigned char * pbOutPos; // 08 : Current output position + unsigned long dwBitBuff; // 0C : Bit buffer + unsigned long nBits; // 10 : Number of bits in the bit buffer +}; + +// Huffmann tree item (?) +struct THTreeItem +{ + public: + + THTreeItem * Call1501DB70(THTreeItem * pLast); + THTreeItem * GetPrevItem(LONG_PTR value); + void ClearItemLinks(); + void RemoveItem(); + + THTreeItem * next; // 00 - Pointer to next THTreeItem + THTreeItem * prev; // 04 - Pointer to prev THTreeItem (< 0 if none) + unsigned long dcmpByte; // 08 - Index of this item in item pointer array, decompressed byte value + unsigned long byteValue; // 0C - Some byte value + THTreeItem * parent; // 10 - Pointer to parent THTreeItem (NULL if none) + THTreeItem * child; // 14 - Pointer to child THTreeItem + int addressMultiplier; // -1 if object on negative address (>0x80000000), +1 if positive +}; + +// Structure used for quick decompress. The 'bitCount' contains number of bits +// and byte value contains result decompressed byte value. +// After each walk through Huffman tree are filled all entries which are +// multiplies of number of bits loaded from input stream. These entries +// contain number of bits and result value. At the next 7 bits is tested this +// structure first. If corresponding entry found, decompression routine will +// not walk through Huffman tree and directly stores output byte to output stream. +struct TQDecompress +{ + unsigned long offs00; // 00 - 1 if resolved + unsigned long nBits; // 04 - Bit count + union + { + unsigned long dcmpByte; // 08 - Byte value for decompress (if bitCount <= 7) + THTreeItem * pItem; // 08 - THTreeItem (if number of bits is greater than 7 + }; +}; + +// Structure for Huffman tree (Size 0x3674 bytes). Because I'm not expert +// for the decompression, I do not know actually if the class is really a Hufmann +// tree. If someone knows the decompression details, please let me know +class THuffmannTree +{ + public: + + THuffmannTree(); + void InitTree(bool bCompression); + void BuildTree(unsigned int nCmpType); +// void ModifyTree(unsigned long dwIndex); +// void UninitTree(); + +// void Call15007010(Bit32 dwInLength, THTreeItem * item); + THTreeItem * Call1500E740(unsigned int nValue); + void Call1500E820(THTreeItem * pItem); + unsigned int DoCompression(TOutputStream * os, unsigned char * pbInBuffer, int nInLength, int nCmpType); + unsigned int DoDecompression(unsigned char * pbOutBuffer, unsigned int dwOutLength, TInputStream * is); + + unsigned long bIsCmp0; // 0000 - 1 if compression type 0 + unsigned long offs0004; // 0004 - Some flag + THTreeItem items0008[0x203]; // 0008 - HTree items + + //- Sometimes used as HTree item ----------- + THTreeItem * pItem3050; // 3050 - Always NULL (?) + THTreeItem * pItem3054; // 3054 - Pointer to Huffman tree item + THTreeItem * pItem3058; // 3058 - Pointer to Huffman tree item (< 0 if invalid) + + //- Sometimes used as HTree item ----------- + THTreeItem * pItem305C; // 305C - Usually NULL + THTreeItem * pFirst; // 3060 - Pointer to top (first) Huffman tree item + THTreeItem * pLast; // 3064 - Pointer to bottom (last) Huffman tree item (< 0 if invalid) + unsigned long nItems; // 3068 - Number of used HTree items + + //------------------------------------------- + THTreeItem * items306C[0x102]; // 306C - THTreeItem pointer array + TQDecompress qd3474[0x80]; // 3474 - Array for quick decompression + int addressMultiplier; // -1 if object on negative address (>0x80000000), +1 if positive + + static unsigned char Table1502A630[];// Some table +}; + +#endif // __HUFFMAN_H__ diff --git a/contrib/vmap_extractor_v2/stormlib/pklib/crc32.c b/contrib/vmap_extractor_v2/stormlib/pklib/crc32.c new file mode 100644 index 00000000000..a7f52103be4 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/pklib/crc32.c @@ -0,0 +1,72 @@ +/*****************************************************************************/ +/* crc32.c Copyright (c) Ladislav Zezula 2003 */ +/*---------------------------------------------------------------------------*/ +/* Pkware Data Compression Library Version 1.11 */ +/* Dissassembled method crc32 - cdecl version */ +/*---------------------------------------------------------------------------*/ +/* Date Ver Who Comment */ +/* -------- ---- --- ------- */ +/* 09.04.03 1.00 Lad The first version of crc32.c */ +/* 02.05.03 1.00 Lad Stress test done */ +/*****************************************************************************/ + +#include "pklib.h" + +static char CopyRight[] = "PKWARE Data Compression Library for Win32\r\n" + "Copyright 1989-1995 PKWARE Inc. All Rights Reserved\r\n" + "Patent No. 5,051,745\r\n" + "PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off.\r\n" + "Version 1.11\r\n"; + +static unsigned long crc_table[] = +{ + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D +}; + + +unsigned long PKEXPORT crc32pk(char * buffer, unsigned int * psize, unsigned long * old_crc) +{ + unsigned int size = *psize; + unsigned long ch; + unsigned long crc_value = *old_crc; + + while(size-- != 0) + { + ch = *buffer++ ^ (char)crc_value; + crc_value >>= 8; + + crc_value = crc_table[ch & 0x0FF] ^ crc_value; + } + return crc_value; +} diff --git a/contrib/vmap_extractor_v2/stormlib/pklib/crc32_pk.c b/contrib/vmap_extractor_v2/stormlib/pklib/crc32_pk.c new file mode 100644 index 00000000000..a7f52103be4 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/pklib/crc32_pk.c @@ -0,0 +1,72 @@ +/*****************************************************************************/ +/* crc32.c Copyright (c) Ladislav Zezula 2003 */ +/*---------------------------------------------------------------------------*/ +/* Pkware Data Compression Library Version 1.11 */ +/* Dissassembled method crc32 - cdecl version */ +/*---------------------------------------------------------------------------*/ +/* Date Ver Who Comment */ +/* -------- ---- --- ------- */ +/* 09.04.03 1.00 Lad The first version of crc32.c */ +/* 02.05.03 1.00 Lad Stress test done */ +/*****************************************************************************/ + +#include "pklib.h" + +static char CopyRight[] = "PKWARE Data Compression Library for Win32\r\n" + "Copyright 1989-1995 PKWARE Inc. All Rights Reserved\r\n" + "Patent No. 5,051,745\r\n" + "PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off.\r\n" + "Version 1.11\r\n"; + +static unsigned long crc_table[] = +{ + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D +}; + + +unsigned long PKEXPORT crc32pk(char * buffer, unsigned int * psize, unsigned long * old_crc) +{ + unsigned int size = *psize; + unsigned long ch; + unsigned long crc_value = *old_crc; + + while(size-- != 0) + { + ch = *buffer++ ^ (char)crc_value; + crc_value >>= 8; + + crc_value = crc_table[ch & 0x0FF] ^ crc_value; + } + return crc_value; +} diff --git a/contrib/vmap_extractor_v2/stormlib/pklib/explode.c b/contrib/vmap_extractor_v2/stormlib/pklib/explode.c new file mode 100644 index 00000000000..a5b41e3dcf9 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/pklib/explode.c @@ -0,0 +1,480 @@ +/*****************************************************************************/ +/* explode.c Copyright (c) Ladislav Zezula 2003 */ +/*---------------------------------------------------------------------------*/ +/* Implode function of PKWARE Data Compression library */ +/*---------------------------------------------------------------------------*/ +/* Date Ver Who Comment */ +/* -------- ---- --- ------- */ +/* 11.03.03 1.00 Lad Splitted from Pkware.cpp */ +/* 08.04.03 1.01 Lad Renamed to explode.c to be compatible with pklib */ +/* 02.05.03 1.01 Lad Stress test done */ +/*****************************************************************************/ + +#include +#include + +#include "pklib.h" + +//----------------------------------------------------------------------------- +// Tables + +static unsigned char DistBits[] = +{ + 0x02, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 +}; + +static unsigned char DistCode[] = +{ + 0x03, 0x0D, 0x05, 0x19, 0x09, 0x11, 0x01, 0x3E, 0x1E, 0x2E, 0x0E, 0x36, 0x16, 0x26, 0x06, 0x3A, + 0x1A, 0x2A, 0x0A, 0x32, 0x12, 0x22, 0x42, 0x02, 0x7C, 0x3C, 0x5C, 0x1C, 0x6C, 0x2C, 0x4C, 0x0C, + 0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04, 0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08, + 0xF0, 0x70, 0xB0, 0x30, 0xD0, 0x50, 0x90, 0x10, 0xE0, 0x60, 0xA0, 0x20, 0xC0, 0x40, 0x80, 0x00 +}; + +static unsigned char ExLenBits[] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 +}; + +static unsigned short LenBase[] = +{ + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x000A, 0x000E, 0x0016, 0x0026, 0x0046, 0x0086, 0x0106 +}; + +static unsigned char LenBits[] = +{ + 0x03, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07 +}; + +static unsigned char LenCode[] = +{ + 0x05, 0x03, 0x01, 0x06, 0x0A, 0x02, 0x0C, 0x14, 0x04, 0x18, 0x08, 0x30, 0x10, 0x20, 0x40, 0x00 +}; + +static unsigned char ChBitsAsc[] = +{ + 0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x08, 0x07, 0x0C, 0x0C, 0x07, 0x0C, 0x0C, + 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, + 0x04, 0x0A, 0x08, 0x0C, 0x0A, 0x0C, 0x0A, 0x08, 0x07, 0x07, 0x08, 0x09, 0x07, 0x06, 0x07, 0x08, + 0x07, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x07, 0x07, 0x08, 0x08, 0x0C, 0x0B, 0x07, 0x09, 0x0B, + 0x0C, 0x06, 0x07, 0x06, 0x06, 0x05, 0x07, 0x08, 0x08, 0x06, 0x0B, 0x09, 0x06, 0x07, 0x06, 0x06, + 0x07, 0x0B, 0x06, 0x06, 0x06, 0x07, 0x09, 0x08, 0x09, 0x09, 0x0B, 0x08, 0x0B, 0x09, 0x0C, 0x08, + 0x0C, 0x05, 0x06, 0x06, 0x06, 0x05, 0x06, 0x06, 0x06, 0x05, 0x0B, 0x07, 0x05, 0x06, 0x05, 0x05, + 0x06, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x08, 0x07, 0x08, 0x08, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C, + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, + 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, + 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, + 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, + 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, + 0x0D, 0x0D, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D +}; + +static unsigned short ChCodeAsc[] = +{ + 0x0490, 0x0FE0, 0x07E0, 0x0BE0, 0x03E0, 0x0DE0, 0x05E0, 0x09E0, + 0x01E0, 0x00B8, 0x0062, 0x0EE0, 0x06E0, 0x0022, 0x0AE0, 0x02E0, + 0x0CE0, 0x04E0, 0x08E0, 0x00E0, 0x0F60, 0x0760, 0x0B60, 0x0360, + 0x0D60, 0x0560, 0x1240, 0x0960, 0x0160, 0x0E60, 0x0660, 0x0A60, + 0x000F, 0x0250, 0x0038, 0x0260, 0x0050, 0x0C60, 0x0390, 0x00D8, + 0x0042, 0x0002, 0x0058, 0x01B0, 0x007C, 0x0029, 0x003C, 0x0098, + 0x005C, 0x0009, 0x001C, 0x006C, 0x002C, 0x004C, 0x0018, 0x000C, + 0x0074, 0x00E8, 0x0068, 0x0460, 0x0090, 0x0034, 0x00B0, 0x0710, + 0x0860, 0x0031, 0x0054, 0x0011, 0x0021, 0x0017, 0x0014, 0x00A8, + 0x0028, 0x0001, 0x0310, 0x0130, 0x003E, 0x0064, 0x001E, 0x002E, + 0x0024, 0x0510, 0x000E, 0x0036, 0x0016, 0x0044, 0x0030, 0x00C8, + 0x01D0, 0x00D0, 0x0110, 0x0048, 0x0610, 0x0150, 0x0060, 0x0088, + 0x0FA0, 0x0007, 0x0026, 0x0006, 0x003A, 0x001B, 0x001A, 0x002A, + 0x000A, 0x000B, 0x0210, 0x0004, 0x0013, 0x0032, 0x0003, 0x001D, + 0x0012, 0x0190, 0x000D, 0x0015, 0x0005, 0x0019, 0x0008, 0x0078, + 0x00F0, 0x0070, 0x0290, 0x0410, 0x0010, 0x07A0, 0x0BA0, 0x03A0, + 0x0240, 0x1C40, 0x0C40, 0x1440, 0x0440, 0x1840, 0x0840, 0x1040, + 0x0040, 0x1F80, 0x0F80, 0x1780, 0x0780, 0x1B80, 0x0B80, 0x1380, + 0x0380, 0x1D80, 0x0D80, 0x1580, 0x0580, 0x1980, 0x0980, 0x1180, + 0x0180, 0x1E80, 0x0E80, 0x1680, 0x0680, 0x1A80, 0x0A80, 0x1280, + 0x0280, 0x1C80, 0x0C80, 0x1480, 0x0480, 0x1880, 0x0880, 0x1080, + 0x0080, 0x1F00, 0x0F00, 0x1700, 0x0700, 0x1B00, 0x0B00, 0x1300, + 0x0DA0, 0x05A0, 0x09A0, 0x01A0, 0x0EA0, 0x06A0, 0x0AA0, 0x02A0, + 0x0CA0, 0x04A0, 0x08A0, 0x00A0, 0x0F20, 0x0720, 0x0B20, 0x0320, + 0x0D20, 0x0520, 0x0920, 0x0120, 0x0E20, 0x0620, 0x0A20, 0x0220, + 0x0C20, 0x0420, 0x0820, 0x0020, 0x0FC0, 0x07C0, 0x0BC0, 0x03C0, + 0x0DC0, 0x05C0, 0x09C0, 0x01C0, 0x0EC0, 0x06C0, 0x0AC0, 0x02C0, + 0x0CC0, 0x04C0, 0x08C0, 0x00C0, 0x0F40, 0x0740, 0x0B40, 0x0340, + 0x0300, 0x0D40, 0x1D00, 0x0D00, 0x1500, 0x0540, 0x0500, 0x1900, + 0x0900, 0x0940, 0x1100, 0x0100, 0x1E00, 0x0E00, 0x0140, 0x1600, + 0x0600, 0x1A00, 0x0E40, 0x0640, 0x0A40, 0x0A00, 0x1200, 0x0200, + 0x1C00, 0x0C00, 0x1400, 0x0400, 0x1800, 0x0800, 0x1000, 0x0000 +}; + +//----------------------------------------------------------------------------- +// Local variables + +static char Copyright[] = "PKWARE Data Compression Library for Win32\r\n" + "Copyright 1989-1995 PKWARE Inc. All Rights Reserved\r\n" + "Patent No. 5,051,745\r\n" + "PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off.\r\n" + "Version 1.11\r\n"; + +//----------------------------------------------------------------------------- +// Local functions + +// Copies a block to another location +static void lmemcpy(void * trg, const void * src, size_t count) +{ + memcpy(trg, src, count); +} + +static void GenDecodeTabs(long count, unsigned char * bits, unsigned char * pCode, unsigned char * buffer2) +{ + long i; + + for(i = count-1; i >= 0; i--) // EBX - count + { + unsigned long idx1 = pCode[i]; + unsigned long idx2 = 1 << bits[i]; + + do + { + buffer2[idx1] = (unsigned char)i; + idx1 += idx2; + } + while(idx1 < 0x100); + } +} + +static void GenAscTabs(TDcmpStruct * pWork) +{ + unsigned short * pChCodeAsc = &ChCodeAsc[0xFF]; + unsigned long acc, add; + unsigned short count; + + for(count = 0x00FF; pChCodeAsc >= ChCodeAsc; pChCodeAsc--, count--) + { + unsigned char * pChBitsAsc = pWork->ChBitsAsc + count; + unsigned char bits_asc = *pChBitsAsc; + + if(bits_asc <= 8) + { + add = (1 << bits_asc); + acc = *pChCodeAsc; + + do + { + pWork->offs2C34[acc] = (unsigned char)count; + acc += add; + } + while(acc < 0x100); + } + else if((acc = (*pChCodeAsc & 0xFF)) != 0) + { + pWork->offs2C34[acc] = 0xFF; + + if(*pChCodeAsc & 0x3F) + { + bits_asc -= 4; + *pChBitsAsc = bits_asc; + + add = (1 << bits_asc); + acc = *pChCodeAsc >> 4; + do + { + pWork->offs2D34[acc] = (unsigned char)count; + acc += add; + } + while(acc < 0x100); + } + else + { + bits_asc -= 6; + *pChBitsAsc = bits_asc; + + add = (1 << bits_asc); + acc = *pChCodeAsc >> 6; + do + { + pWork->offs2E34[acc] = (unsigned char)count; + acc += add; + } + while(acc < 0x80); + } + } + else + { + bits_asc -= 8; + *pChBitsAsc = bits_asc; + + add = (1 << bits_asc); + acc = *pChCodeAsc >> 8; + do + { + pWork->offs2EB4[acc] = (unsigned char)count; + acc += add; + } + while(acc < 0x100); + } + } +} + +//----------------------------------------------------------------------------- +// Skips given number of bits in bit buffer. Result is stored in pWork->bit_buff +// If no data in input buffer, returns true + +static int WasteBits(TDcmpStruct * pWork, unsigned long nBits) +{ + // If number of bits required is less than number of (bits in the buffer) ? + if(nBits <= pWork->extra_bits) + { + pWork->extra_bits -= nBits; + pWork->bit_buff >>= nBits; + return 0; + } + + // Load input buffer if necessary + pWork->bit_buff >>= pWork->extra_bits; + if(pWork->in_pos == pWork->in_bytes) + { + pWork->in_pos = sizeof(pWork->in_buff); + if((pWork->in_bytes = pWork->read_buf((char *)pWork->in_buff, &pWork->in_pos, pWork->param)) == 0) + return 1; + pWork->in_pos = 0; + } + + // Update bit buffer + pWork->bit_buff |= (pWork->in_buff[pWork->in_pos++] << 8); + pWork->bit_buff >>= (nBits - pWork->extra_bits); + pWork->extra_bits = (pWork->extra_bits - nBits) + 8; + return 0; +} + +//----------------------------------------------------------------------------- +// Returns : 0x000 - 0x0FF : One byte from compressed file. +// 0x100 - 0x305 : Copy previous block (0x100 = 1 byte) +// 0x306 : Out of buffer (?) + +static unsigned long DecodeLit(TDcmpStruct * pWork) +{ + unsigned long nBits; // Number of bits to skip + unsigned long value; // Position in buffers + + // Test the current bit in byte buffer. If is not set, simply return the next byte. + if(pWork->bit_buff & 1) + { + // Skip current bit in the buffer + if(WasteBits(pWork, 1)) + return 0x306; + + // The next bits are position in buffers + value = pWork->position2[(pWork->bit_buff & 0xFF)]; + + // Get number of bits to skip + if(WasteBits(pWork, pWork->LenBits[value])) + return 0x306; + + if((nBits = pWork->ExLenBits[value]) != 0) + { + unsigned long val2 = pWork->bit_buff & ((1 << nBits) - 1); + + if(WasteBits(pWork, nBits)) + { + if((value + val2) != 0x10E) + return 0x306; + } + value = pWork->LenBase[value] + val2; + } + return value + 0x100; // Return number of bytes to repeat + } + + // Waste one bit + if(WasteBits(pWork, 1)) + return 0x306; + + // If the binary compression type, read 8 bits and return them as one byte. + if(pWork->ctype == CMP_BINARY) + { + value = pWork->bit_buff & 0xFF; + if(WasteBits(pWork, 8)) + return 0x306; + return value; + } + + // When ASCII compression ... + if(pWork->bit_buff & 0xFF) + { + value = pWork->offs2C34[pWork->bit_buff & 0xFF]; + + if(value == 0xFF) + { + if(pWork->bit_buff & 0x3F) + { + if(WasteBits(pWork, 4)) + return 0x306; + + value = pWork->offs2D34[pWork->bit_buff & 0xFF]; + } + else + { + if(WasteBits(pWork, 6)) + return 0x306; + + value = pWork->offs2E34[pWork->bit_buff & 0x7F]; + } + } + } + else + { + if(WasteBits(pWork, 8)) + return 0x306; + + value = pWork->offs2EB4[pWork->bit_buff & 0xFF]; + } + + return WasteBits(pWork, pWork->ChBitsAsc[value]) ? 0x306 : value; +} + +//----------------------------------------------------------------------------- +// Retrieves the number of bytes to move back + +static unsigned long DecodeDist(TDcmpStruct * pWork, unsigned long dwLength) +{ + unsigned long pos = pWork->position1[(pWork->bit_buff & 0xFF)]; + unsigned long nSkip = pWork->DistBits[pos]; // Number of bits to skip + + // Skip the appropriate number of bits + if(WasteBits(pWork, nSkip) == 1) + return 0; + + if(dwLength == 2) + { + pos = (pos << 2) | (pWork->bit_buff & 0x03); + + if(WasteBits(pWork, 2) == 1) + return 0; + } + else + { + pos = (pos << pWork->dsize_bits) | (pWork->bit_buff & pWork->dsize_mask); + + // Skip the bits + if(WasteBits(pWork, pWork->dsize_bits) == 1) + return 0; + } + return pos+1; +} + +static unsigned long Expand(TDcmpStruct * pWork) +{ + unsigned int copyBytes; // Number of bytes to copy + unsigned long oneByte; // One byte from compressed file + unsigned long dwResult; + + pWork->outputPos = 0x1000; // Initialize output buffer position + + // If end of data or error, terminate decompress + while((dwResult = oneByte = DecodeLit(pWork)) < 0x305) + { + // If one byte is greater than 0x100, means "Repeat n - 0xFE bytes" + if(oneByte >= 0x100) + { + unsigned char * source; // ECX + unsigned char * target; // EDX + unsigned long copyLength = oneByte - 0xFE; + unsigned long moveBack; + + // Get length of data to copy + if((moveBack = DecodeDist(pWork, copyLength)) == 0) + { + dwResult = 0x306; + break; + } + + // Target and source pointer + target = &pWork->out_buff[pWork->outputPos]; + source = target - moveBack; + pWork->outputPos += copyLength; + + while(copyLength-- > 0) + *target++ = *source++; + } + else + pWork->out_buff[pWork->outputPos++] = (unsigned char)oneByte; + + // If number of extracted bytes has reached 1/2 of output buffer, + // flush output buffer. + if(pWork->outputPos >= 0x2000) + { + // Copy decompressed data into user buffer + copyBytes = 0x1000; + pWork->write_buf((char *)&pWork->out_buff[0x1000], ©Bytes, pWork->param); + + // If there are some data left, keep them alive + lmemcpy(pWork->out_buff, &pWork->out_buff[0x1000], pWork->outputPos - 0x1000); + pWork->outputPos -= 0x1000; + } + } + + copyBytes = pWork->outputPos - 0x1000; + pWork->write_buf((char *)&pWork->out_buff[0x1000], ©Bytes, pWork->param); + return dwResult; +} + + +//----------------------------------------------------------------------------- +// Main exploding function. + +unsigned int explode( + unsigned int (*read_buf)(char *buf, unsigned int *size, void *param), + void (*write_buf)(char *buf, unsigned int *size, void *param), + char *work_buf, + void *param) +{ + TDcmpStruct * pWork = (TDcmpStruct *)work_buf; + + // Set the whole work buffer to zeros + memset(pWork, 0, sizeof(TDcmpStruct)); + + // Initialize work struct and load compressed data + pWork->read_buf = read_buf; + pWork->write_buf = write_buf; + pWork->param = param; + pWork->in_pos = sizeof(pWork->in_buff); + pWork->in_bytes = pWork->read_buf((char *)pWork->in_buff, &pWork->in_pos, pWork->param); + if(pWork->in_bytes <= 4) + return CMP_BAD_DATA; + + pWork->ctype = pWork->in_buff[0]; // Get the compression type + pWork->dsize_bits = pWork->in_buff[1]; // Get the dictionary size + pWork->bit_buff = pWork->in_buff[2]; // Initialize 16-bit bit buffer + pWork->extra_bits = 0; // Extra (over 8) bits + pWork->in_pos = 3; // Position in input buffer + + // Test for the valid dictionary size + if(4 > pWork->dsize_bits || pWork->dsize_bits > 6) + return CMP_INVALID_DICTSIZE; + + pWork->dsize_mask = 0xFFFF >> (0x10 - pWork->dsize_bits); // Shifted by 'sar' instruction + + if(pWork->ctype != CMP_BINARY) + { + if(pWork->ctype != CMP_ASCII) + return CMP_INVALID_MODE; + + lmemcpy(pWork->ChBitsAsc, ChBitsAsc, sizeof(pWork->ChBitsAsc)); + GenAscTabs(pWork); + } + + lmemcpy(pWork->LenBits, LenBits, sizeof(pWork->LenBits)); + GenDecodeTabs(0x10, pWork->LenBits, LenCode, pWork->position2); + lmemcpy(pWork->ExLenBits, ExLenBits, sizeof(pWork->ExLenBits)); + lmemcpy(pWork->LenBase, LenBase, sizeof(pWork->LenBase)); + lmemcpy(pWork->DistBits, DistBits, sizeof(pWork->DistBits)); + GenDecodeTabs(0x40, pWork->DistBits, DistCode, pWork->position1); + if(Expand(pWork) != 0x306) + return CMP_NO_ERROR; + + return CMP_ABORT; +} diff --git a/contrib/vmap_extractor_v2/stormlib/pklib/implode.c b/contrib/vmap_extractor_v2/stormlib/pklib/implode.c new file mode 100644 index 00000000000..68d5301cc8d --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/pklib/implode.c @@ -0,0 +1,674 @@ +/*****************************************************************************/ +/* implode.c Copyright (c) Ladislav Zezula 2003 */ +/*---------------------------------------------------------------------------*/ +/* Implode function of PKWARE Data Compression library */ +/*---------------------------------------------------------------------------*/ +/* Date Ver Who Comment */ +/* -------- ---- --- ------- */ +/* 11.04.03 1.00 Lad First version of implode.c */ +/* 02.05.03 1.00 Lad Stress test done */ +/*****************************************************************************/ + +#include +#include + +#include "pklib.h" + +#if ((1200 < _MSC_VER) && (_MSC_VER < 1400)) +#pragma optimize("", off) // Fucking Microsoft VS.NET 2003 compiler !!! + // (_MSC_VER=1310) +#endif + +//----------------------------------------------------------------------------- +// Defines + +#define DICT_OFFSET 0x204 +#define UNCMP_OFFSET (pWork->dsize_bytes + DICT_OFFSET) + +//----------------------------------------------------------------------------- +// Tables + +static unsigned char DistBits[] = +{ + 0x02, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 +}; + +static unsigned char DistCode[] = +{ + 0x03, 0x0D, 0x05, 0x19, 0x09, 0x11, 0x01, 0x3E, 0x1E, 0x2E, 0x0E, 0x36, 0x16, 0x26, 0x06, 0x3A, + 0x1A, 0x2A, 0x0A, 0x32, 0x12, 0x22, 0x42, 0x02, 0x7C, 0x3C, 0x5C, 0x1C, 0x6C, 0x2C, 0x4C, 0x0C, + 0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04, 0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08, + 0xF0, 0x70, 0xB0, 0x30, 0xD0, 0x50, 0x90, 0x10, 0xE0, 0x60, 0xA0, 0x20, 0xC0, 0x40, 0x80, 0x00 +}; + +static unsigned char ExLenBits[] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 +}; + +static unsigned char LenBits[] = +{ + 0x03, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07 +}; + +static unsigned char LenCode[] = +{ + 0x05, 0x03, 0x01, 0x06, 0x0A, 0x02, 0x0C, 0x14, 0x04, 0x18, 0x08, 0x30, 0x10, 0x20, 0x40, 0x00 +}; + +static unsigned char ChBitsAsc[] = +{ + 0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x08, 0x07, 0x0C, 0x0C, 0x07, 0x0C, 0x0C, + 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, + 0x04, 0x0A, 0x08, 0x0C, 0x0A, 0x0C, 0x0A, 0x08, 0x07, 0x07, 0x08, 0x09, 0x07, 0x06, 0x07, 0x08, + 0x07, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x07, 0x07, 0x08, 0x08, 0x0C, 0x0B, 0x07, 0x09, 0x0B, + 0x0C, 0x06, 0x07, 0x06, 0x06, 0x05, 0x07, 0x08, 0x08, 0x06, 0x0B, 0x09, 0x06, 0x07, 0x06, 0x06, + 0x07, 0x0B, 0x06, 0x06, 0x06, 0x07, 0x09, 0x08, 0x09, 0x09, 0x0B, 0x08, 0x0B, 0x09, 0x0C, 0x08, + 0x0C, 0x05, 0x06, 0x06, 0x06, 0x05, 0x06, 0x06, 0x06, 0x05, 0x0B, 0x07, 0x05, 0x06, 0x05, 0x05, + 0x06, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x08, 0x07, 0x08, 0x08, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C, + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, + 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, + 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, + 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, + 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, + 0x0D, 0x0D, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D +}; + +static unsigned short ChCodeAsc[] = +{ + 0x0490, 0x0FE0, 0x07E0, 0x0BE0, 0x03E0, 0x0DE0, 0x05E0, 0x09E0, + 0x01E0, 0x00B8, 0x0062, 0x0EE0, 0x06E0, 0x0022, 0x0AE0, 0x02E0, + 0x0CE0, 0x04E0, 0x08E0, 0x00E0, 0x0F60, 0x0760, 0x0B60, 0x0360, + 0x0D60, 0x0560, 0x1240, 0x0960, 0x0160, 0x0E60, 0x0660, 0x0A60, + 0x000F, 0x0250, 0x0038, 0x0260, 0x0050, 0x0C60, 0x0390, 0x00D8, + 0x0042, 0x0002, 0x0058, 0x01B0, 0x007C, 0x0029, 0x003C, 0x0098, + 0x005C, 0x0009, 0x001C, 0x006C, 0x002C, 0x004C, 0x0018, 0x000C, + 0x0074, 0x00E8, 0x0068, 0x0460, 0x0090, 0x0034, 0x00B0, 0x0710, + 0x0860, 0x0031, 0x0054, 0x0011, 0x0021, 0x0017, 0x0014, 0x00A8, + 0x0028, 0x0001, 0x0310, 0x0130, 0x003E, 0x0064, 0x001E, 0x002E, + 0x0024, 0x0510, 0x000E, 0x0036, 0x0016, 0x0044, 0x0030, 0x00C8, + 0x01D0, 0x00D0, 0x0110, 0x0048, 0x0610, 0x0150, 0x0060, 0x0088, + 0x0FA0, 0x0007, 0x0026, 0x0006, 0x003A, 0x001B, 0x001A, 0x002A, + 0x000A, 0x000B, 0x0210, 0x0004, 0x0013, 0x0032, 0x0003, 0x001D, + 0x0012, 0x0190, 0x000D, 0x0015, 0x0005, 0x0019, 0x0008, 0x0078, + 0x00F0, 0x0070, 0x0290, 0x0410, 0x0010, 0x07A0, 0x0BA0, 0x03A0, + 0x0240, 0x1C40, 0x0C40, 0x1440, 0x0440, 0x1840, 0x0840, 0x1040, + 0x0040, 0x1F80, 0x0F80, 0x1780, 0x0780, 0x1B80, 0x0B80, 0x1380, + 0x0380, 0x1D80, 0x0D80, 0x1580, 0x0580, 0x1980, 0x0980, 0x1180, + 0x0180, 0x1E80, 0x0E80, 0x1680, 0x0680, 0x1A80, 0x0A80, 0x1280, + 0x0280, 0x1C80, 0x0C80, 0x1480, 0x0480, 0x1880, 0x0880, 0x1080, + 0x0080, 0x1F00, 0x0F00, 0x1700, 0x0700, 0x1B00, 0x0B00, 0x1300, + 0x0DA0, 0x05A0, 0x09A0, 0x01A0, 0x0EA0, 0x06A0, 0x0AA0, 0x02A0, + 0x0CA0, 0x04A0, 0x08A0, 0x00A0, 0x0F20, 0x0720, 0x0B20, 0x0320, + 0x0D20, 0x0520, 0x0920, 0x0120, 0x0E20, 0x0620, 0x0A20, 0x0220, + 0x0C20, 0x0420, 0x0820, 0x0020, 0x0FC0, 0x07C0, 0x0BC0, 0x03C0, + 0x0DC0, 0x05C0, 0x09C0, 0x01C0, 0x0EC0, 0x06C0, 0x0AC0, 0x02C0, + 0x0CC0, 0x04C0, 0x08C0, 0x00C0, 0x0F40, 0x0740, 0x0B40, 0x0340, + 0x0300, 0x0D40, 0x1D00, 0x0D00, 0x1500, 0x0540, 0x0500, 0x1900, + 0x0900, 0x0940, 0x1100, 0x0100, 0x1E00, 0x0E00, 0x0140, 0x1600, + 0x0600, 0x1A00, 0x0E40, 0x0640, 0x0A40, 0x0A00, 0x1200, 0x0200, + 0x1C00, 0x0C00, 0x1400, 0x0400, 0x1800, 0x0800, 0x1000, 0x0000 +}; + +//----------------------------------------------------------------------------- +// Local variables + +static char Copyright[] = "PKWARE Data Compression Library for Win32\r\n" + "Copyright 1989-1995 PKWARE Inc. All Rights Reserved\r\n" + "Patent No. 5,051,745\r\n" + "PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off.\r\n" + "Version 1.11\r\n"; + +//----------------------------------------------------------------------------- +// Local functions + +// Fills memory block with a character +static void lmemset(void * buff, int c, size_t count) +{ + memset(buff, c, count); +} + +// Copies memory block to another location +static void lmemcpy(void * trg, const void * src, size_t count) +{ + memcpy(trg, src, count); +} + +static void SortBuffer(TCmpStruct * pWork, unsigned char * uncmp_data, unsigned char * work_end) +{ + unsigned short * pin0DC8; + unsigned char * puncmp; + unsigned long offs1, offs2; + unsigned long ndwords; + unsigned int add; + + // Fill 0x480 dwords (0x1200 bytes) + ndwords = (unsigned long)((pWork->out_buff - (char *)pWork->offs0DC8 + 1) >> 2); + if(ndwords <= 1) + ndwords = 1; + memset(pWork->offs0DC8, 0, ndwords << 2); + + for(puncmp = uncmp_data; work_end > puncmp; puncmp++) + pWork->offs0DC8[(puncmp[0] * 4) + (puncmp[1] * 5)]++; + + add = 0; + for(pin0DC8 = pWork->offs0DC8; pin0DC8 < &pWork->offs1FC8; pin0DC8++) + { + add += *pin0DC8; + *pin0DC8 = (unsigned short)add; + } + + for(work_end--; work_end >= uncmp_data; work_end--) + { + offs1 = (work_end[0] * 4) + (work_end[1] * 5); // EAX + offs2 = (unsigned long)(work_end - pWork->work_buff); // EDI + + pWork->offs0DC8[offs1]--; + pWork->offs49D0[pWork->offs0DC8[offs1]] = (unsigned short)offs2; + } +} + +static void FlushBuf(TCmpStruct * pWork) +{ + unsigned char save_ch1; + unsigned char save_ch2; + unsigned int size = 0x800; + + pWork->write_buf(pWork->out_buff, &size, pWork->param); + + save_ch1 = pWork->out_buff[0x800]; + save_ch2 = pWork->out_buff[pWork->out_bytes]; + pWork->out_bytes -= 0x800; + + lmemset(pWork->out_buff, 0, 0x802); + + if(pWork->out_bytes != 0) + pWork->out_buff[0] = save_ch1; + if(pWork->out_bits != 0) + pWork->out_buff[pWork->out_bytes] = save_ch2; +} + +static void OutputBits(TCmpStruct * pWork, unsigned int nbits, unsigned long bit_buff) +{ + unsigned int out_bits; + + // If more than 8 bits to output, do recursion + if(nbits > 8) + { + OutputBits(pWork, 8, bit_buff); + bit_buff >>= 8; + nbits -= 8; + } + + // Add bits to the last out byte in out_buff; + out_bits = pWork->out_bits; + pWork->out_buff[pWork->out_bytes] |= (unsigned char)(bit_buff << out_bits); + pWork->out_bits += nbits; + + // If 8 or more bits, increment number of bytes + if(pWork->out_bits > 8) + { + pWork->out_bytes++; + bit_buff >>= (8 - out_bits); + + pWork->out_buff[pWork->out_bytes] = (unsigned char)bit_buff; + pWork->out_bits &= 7; + } + else + { + pWork->out_bits &= 7; + if(pWork->out_bits == 0) + pWork->out_bytes++; + } + + // If there is enough compressed bytes, flush them + if(pWork->out_bytes >= 0x800) + FlushBuf(pWork); +} + +static unsigned long FindRep(TCmpStruct * pWork, unsigned char * srcbuff) +{ + unsigned short esp12; + unsigned char * esp14; + unsigned short esp18; + unsigned char * srcbuff2; + unsigned char esp20; + + unsigned char * srcbuff3; + unsigned short * pin0DC8; + unsigned char * pin27CC; + unsigned short * pin49D0; + unsigned long nreps = 1; // EAX + unsigned long ebx, esi; + unsigned short di; + + pin0DC8 = pWork->offs0DC8 + (srcbuff[0] * 4) + (srcbuff[1] * 5); + esi = (unsigned long)(srcbuff - pWork->dsize_bytes - pWork->work_buff + 1); + esp18 = *pin0DC8; + pin49D0 = pWork->offs49D0 + esp18; + + if(*pin49D0 < esi) + { + while(*pin49D0 < esi) + { + pin49D0++; + esp18++; + } + *pin0DC8 = esp18; + } +//--------------------------------------------------------------------------- + srcbuff2 = srcbuff - 1; + pin49D0 = pWork->offs49D0 + esp18; + pin27CC = pWork->work_buff + *pin49D0; + if(srcbuff2 <= pin27CC) + return 0; +//--------------------------------------------------------------------------- + srcbuff3 = srcbuff; + for(;;) + { + if(srcbuff3[nreps-1] == pin27CC[nreps-1] && *srcbuff3 == *pin27CC) + { + // + // The following code does not work when compiled with MSVC.NET 2003 + // optimizing compiler. We have to switch the optimizations off to make it work + // I found that in debug version (where the optimizations are off), the value + // of "pin27CC" gets incremented twice (once at below, once in the "for" loop) + // + + pin27CC++; + srcbuff3++; + + for(ebx = 2; ebx < DICT_OFFSET; ebx++) + { + pin27CC++; + srcbuff3++; + if(*pin27CC != *srcbuff3) + break; + } + + srcbuff3 = srcbuff; + if(ebx >= nreps) + { + pWork->offs0000 = (unsigned int)(srcbuff3 - pin27CC + ebx - 1); + if((nreps = ebx) > 10) + break; + } + } + + pin49D0++; + esp18++; + pin27CC = pWork->work_buff + *pin49D0; + + if(srcbuff2 > pin27CC) + continue; + + return (nreps >= 2) ? nreps : 0; + } +//--------------------------------------------------------------------------- + if(ebx == DICT_OFFSET) + { + pWork->offs0000--; + return ebx; + } +//--------------------------------------------------------------------------- + pin49D0 = pWork->offs49D0 + esp18; + if(pWork->work_buff + pin49D0[1] >= srcbuff2) + return nreps; +//--------------------------------------------------------------------------- + di = 0; + pWork->offs09BC[0] = 0xFFFF; + pWork->offs09BC[1] = di; + esp12 = 1; + + do + { + esi = di; + if(srcbuff[esp12] != srcbuff[esi]) + { + di = pWork->offs09BC[esi]; + if(di != 0xFFFF) + continue; + } + pWork->offs09BC[++esp12] = ++di; + } + while(esp12 < nreps); +//--------------------------------------------------------------------------- + esi = nreps; + pin27CC = pWork->work_buff + pin49D0[0] + nreps; + esp14 = pin27CC; + + for(;;) // 0040268B + { + esi = pWork->offs09BC[esi]; + if(esi == 0xFFFF) + esi = 0; + + pin49D0 = pWork->offs49D0 + esp18; + do + { + pin49D0++; + esp18++; + pin27CC = pWork->work_buff + pin49D0[0]; + if(pin27CC >= srcbuff2) + return nreps; + } + while(pin27CC + esi < esp14); +//--------------------------------------------------------------------------- + esp20 = srcbuff[nreps - 2]; + if(esp20 == pin27CC[nreps - 2]) + { + if(pin27CC + esi != esp14) + { + esp14 = pin27CC; + esi = 0; + } + } + else + { + pin49D0 = pWork->offs49D0 + esp18; + do + { + pin49D0++; + esp18++; + pin27CC = pWork->work_buff + pin49D0[0]; + if(pin27CC >= srcbuff2) + return nreps; + } + while(pin27CC[nreps - 2] != esp20 || pin27CC[0] != *srcbuff); + + esp14 = pin27CC + 2; + esi = 2; + } +//--------------------------------------------------------------------------- + for(; esp14[0] == srcbuff[esi]; esp14++) + { + if(++esi >= DICT_OFFSET) + break; + } + + if(esi < nreps) + continue; + pWork->offs0000 = (unsigned int)(srcbuff - pin27CC - 1); + if(esi <= nreps) + continue; + nreps = esi; + if(esi == DICT_OFFSET) + return nreps; + + do + { + if(srcbuff[esp12] != srcbuff[di]) + { + di = pWork->offs09BC[di]; + if(di != 0xFFFF) + continue; + } + pWork->offs09BC[++esp12] = ++di; + } + while(esp12 < esi); + } +} + +static void WriteCmpData(TCmpStruct * pWork) +{ + unsigned int nreps = 0; // ESP+10 : Number of repeats + unsigned char * uncmp_end; // ESP+14 : End of uncompressed data + unsigned int esp18 = 0; // ESP+18 : + unsigned int bytes_required; // ESP+1C : Number of bytes required to read + unsigned int esp20 = 0; // ESP+20 : + unsigned char * uncmp_begin = pWork->work_buff + UNCMP_OFFSET; // EDI + unsigned long nreps1; + unsigned long save_offs0000 = 0; + + // Store the compression type and dictionary size + pWork->out_buff[0] = (char)pWork->ctype; + pWork->out_buff[1] = (char)pWork->dsize_bits; + pWork->out_bytes = 2; + + // Reset output buffer to zero + lmemset(&pWork->out_buff[2], 0, sizeof(pWork->out_buff) - 2); + pWork->out_bits = 0; + + do + { + int total_loaded = 0; + + for(bytes_required = 0x1000; bytes_required != 0; ) + { + int loaded = pWork->read_buf((char *)pWork->work_buff + UNCMP_OFFSET + total_loaded, + &bytes_required, pWork->param); + + if(loaded == 0) + { + if(total_loaded == 0 && esp20 == 0) + goto __Exit; + esp18 = 1; + break; + } + else + { + total_loaded += loaded; + bytes_required -= loaded; + } + } + + uncmp_end = pWork->work_buff + pWork->dsize_bytes + total_loaded; + if(esp18 != 0) + uncmp_end += DICT_OFFSET; + + // + // Warning: Passing "uncmp_end + 1" to the SortBuffer function may cause + // the output to be unpredictable in Storm.dll's compression. Because Storm.dll + // does not pass the zeroed buffer to the "implode" function, the byte after + // uncmp_end contains random data. This causes difference within dictionary + // created in SortBuffer function and may also cause different compressed output. + // We always zero the data before compression, so this thing never occurs. + // Funny is that it is actually not a bug, because if we decompress the data back, + // we'll get the identical data with the original input. + // + switch(esp20) + { + case 0: + SortBuffer(pWork, uncmp_begin, uncmp_end + 1); + esp20++; + if(pWork->dsize_bytes != 0x1000) + esp20++; + break; + + case 1: + SortBuffer(pWork, uncmp_begin - pWork->dsize_bytes + DICT_OFFSET, uncmp_end + 1); + esp20++; + break; + + default: + SortBuffer(pWork, uncmp_begin - pWork->dsize_bytes, uncmp_end + 1); + break; + } + + while(uncmp_end > uncmp_begin) + { + nreps1 = FindRep(pWork, uncmp_begin); + while(nreps1 != 0) + { + if(nreps1 == 2 && pWork->offs0000 >= 0x100) + break; + + if(esp18 != 0 && uncmp_begin + nreps1 > uncmp_end) + goto _004022DB; + + if(nreps1 >= 8 || uncmp_begin + 1 >= uncmp_end) + goto _004022FF; + + save_offs0000 = pWork->offs0000; // ebp + nreps = nreps1; + nreps1 = FindRep(pWork, uncmp_begin + 1); + + if(nreps >= nreps1) + goto _004022F9; + + if(nreps + 1 >= nreps1 && save_offs0000 <= 0x80) + goto _004022F9; + + OutputBits(pWork, pWork->nChBits[*uncmp_begin], pWork->nChCodes[*uncmp_begin]); + uncmp_begin++; + } + +_0040222F: + OutputBits(pWork, pWork->nChBits[*uncmp_begin], pWork->nChCodes[*uncmp_begin]); + uncmp_begin++; +_00402252:; + } + + if(esp18 == 0) + { + uncmp_begin -= 0x1000; + lmemcpy(pWork->work_buff, pWork->work_buff + 0x1000, pWork->dsize_bytes + DICT_OFFSET); + } + } + while(esp18 == 0); + +__Exit: + OutputBits(pWork, pWork->nChBits[0x305], pWork->nChCodes[0x305]); + if(pWork->out_bits != 0) + pWork->out_bytes++; + pWork->write_buf(pWork->out_buff, &pWork->out_bytes, pWork->param); + return; + +_004022DB: + nreps1 = (unsigned long)(uncmp_end - uncmp_begin); + if(nreps1 < 2) + goto _0040222F; + + if(nreps1 != 2 || pWork->offs0000 < 0x100) + goto _004022FF; + goto _0040222F; + +_004022F9: + nreps1 = nreps; + pWork->offs0000 = save_offs0000; + +_004022FF: + OutputBits(pWork, pWork->nChBits[nreps1 + 0xFE], pWork->nChCodes[nreps1 + 0xFE]); + + if(nreps1 == 2) + { + OutputBits(pWork, pWork->dist_bits[pWork->offs0000 >> 2], + pWork->dist_codes[pWork->offs0000 >> 2]); + OutputBits(pWork, 2, pWork->offs0000 & 3); + } + else + { + OutputBits(pWork, pWork->dist_bits[pWork->offs0000 >> pWork->dsize_bits], + pWork->dist_codes[pWork->offs0000 >> pWork->dsize_bits]); + OutputBits(pWork, pWork->dsize_bits, pWork->dsize_mask & pWork->offs0000); + } + uncmp_begin += nreps1; + goto _00402252; +} + +//----------------------------------------------------------------------------- +// Main imploding function + +unsigned int PKEXPORT implode( + unsigned int (*read_buf)(char *buf, unsigned int *size, void *param), + void (*write_buf)(char *buf, unsigned int *size, void *param), + char *work_buf, + void *param, + unsigned int *type, + unsigned int *dsize) +{ + TCmpStruct * pWork = (TCmpStruct *)work_buf; + unsigned int nChCode; + unsigned int nCount; + unsigned int i; + + // Initialize the work buffer. This is not in the Pklib, + // but it seems to be a bug. Storm always pre-fills the data with zeros, + // and always compresses one block only. So the bug will not appear. + // But when a larger data block (size > 0x1000) is compressed, + // it may fail. + memset(pWork, 0, sizeof(TCmpStruct)); + + // Fill the work buffer information + pWork->read_buf = read_buf; + pWork->write_buf = write_buf; + pWork->dsize_bytes = *dsize; + pWork->ctype = *type; + pWork->param = param; + pWork->dsize_bits = 4; + pWork->dsize_mask = 0x0F; + + // Test dictionary size + switch(*dsize) + { + case 0x1000 : + pWork->dsize_bits++; + pWork->dsize_mask |= 0x20; + // No break here !!! + + case 0x0800 : + pWork->dsize_bits++; + pWork->dsize_mask |= 0x10; + // No break here !!! + + case 0x0400 : + break; + + default: + return CMP_INVALID_DICTSIZE; + } + + // Test the compression type + switch(*type) + { + case CMP_BINARY: // We will compress data with binary compression type + for(nChCode = 0, nCount = 0; nCount < 0x100; nCount++) + { + pWork->nChBits[nCount] = 9; + pWork->nChCodes[nCount] = (unsigned short)nChCode; + nChCode = (nChCode & 0x0000FFFF) + 2; + } + break; + + + case CMP_ASCII: // We will compress data with ASCII compression type + for(nCount = 0; nCount < 0x100; nCount++) + { + pWork->nChBits[nCount] = (unsigned char )(ChBitsAsc[nCount] + 1); + pWork->nChCodes[nCount] = (unsigned short)(ChCodeAsc[nCount] * 2); + } + break; + + default: + return CMP_INVALID_MODE; + } + + for(i = 0; i < 0x10; i++) + { + int nCount2 = 0; // EBX + + if((1 << ExLenBits[i]) == 0) + continue; + + do + { + pWork->nChBits[nCount] = (unsigned char)(ExLenBits[i] + LenBits[i] + 1); + pWork->nChCodes[nCount] = (unsigned short)((nCount2 << (LenBits[i] + 1)) | ((LenCode[i] & 0xFFFF00FF) * 2) | 1); + + nCount2++; + nCount++; + } + while((1 << ExLenBits[i]) > nCount2); + } + + // Copy the distance codes and distance bits and perform the compression + lmemcpy(&pWork->dist_codes, DistCode, sizeof(DistCode)); + lmemcpy(&pWork->dist_bits, DistBits, sizeof(DistBits)); + WriteCmpData(pWork); + return CMP_NO_ERROR; +} diff --git a/contrib/vmap_extractor_v2/stormlib/pklib/pklib.h b/contrib/vmap_extractor_v2/stormlib/pklib/pklib.h new file mode 100644 index 00000000000..881262e3839 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/pklib/pklib.h @@ -0,0 +1,137 @@ +/*****************************************************************************/ +/* pklib.h Copyright (c) Ladislav Zezula 2003 */ +/*---------------------------------------------------------------------------*/ +/* Header file for PKWARE Data Compression Library */ +/*---------------------------------------------------------------------------*/ +/* Date Ver Who Comment */ +/* -------- ---- --- ------- */ +/* 31.03.03 1.00 Lad The first version of pkware.h */ +/*****************************************************************************/ + +#ifndef __PKLIB_H__ +#define __PKLIB_H__ + +#include "../StormPort.h" + +//----------------------------------------------------------------------------- +// Defines + +#define CMP_BINARY 0 // Binary compression +#define CMP_ASCII 1 // Ascii compression + +#define CMP_NO_ERROR 0 +#define CMP_INVALID_DICTSIZE 1 +#define CMP_INVALID_MODE 2 +#define CMP_BAD_DATA 3 +#define CMP_ABORT 4 + +//----------------------------------------------------------------------------- +// Define calling convention + +#ifndef PKEXPORT +#define PKEXPORT //__cdecl // Use for normal __cdecl calling +#endif +//#define PKEXPORT __stdcall +//#define PKEXPORT __fastcall + +//----------------------------------------------------------------------------- +// Internal structures + +// Compression structure +typedef struct +{ + unsigned int offs0000; // 0000 : + unsigned int out_bytes; // 0004 : # bytes available in out_buff + unsigned int out_bits; // 0008 : # of bits available in the last out byte + unsigned int dsize_bits; // 000C : Dict size : 4=0x400, 5=0x800, 6=0x1000 + unsigned int dsize_mask; // 0010 : Dict size : 0x0F=0x400, 0x1F=0x800, 0x3F=0x1000 + unsigned int ctype; // 0014 : Compression type (Ascii or binary) + unsigned int dsize_bytes; // 0018 : Dictionary size in bytes + unsigned char dist_bits[0x40]; // 001C : Distance bits + unsigned char dist_codes[0x40]; // 005C : Distance codes + unsigned char nChBits[0x306]; // 009C : + unsigned short nChCodes[0x306]; // 03A2 : + unsigned short offs09AE; // 09AE : + + void * param; // 09B0 : User parameter + unsigned int (*read_buf)(char *buf, unsigned int *size, void *param); // 9B4 + void (*write_buf)(char *buf, unsigned int *size, void *param); // 9B8 + + unsigned short offs09BC[0x204]; // 09BC : + unsigned long offs0DC4; // 0DC4 : + unsigned short offs0DC8[0x900]; // 0DC8 : + unsigned short offs1FC8; // 1FC8 : + char out_buff[0x802]; // 1FCA : Output (compressed) data + unsigned char work_buff[0x2204]; // 27CC : Work buffer + // + DICT_OFFSET => Dictionary + // + UNCMP_OFFSET => Uncompressed data + unsigned short offs49D0[0x2000]; // 49D0 : +} TCmpStruct; + +#define CMP_BUFFER_SIZE sizeof(TCmpStruct) // Size of compression buffer + + +// Decompression structure +typedef struct +{ + unsigned long offs0000; // 0000 + unsigned long ctype; // 0004 - Compression type (CMP_BINARY or CMP_ASCII) + unsigned long outputPos; // 0008 - Position in output buffer + unsigned long dsize_bits; // 000C - Dict size (4, 5, 6 for 0x400, 0x800, 0x1000) + unsigned long dsize_mask; // 0010 - Dict size bitmask (0x0F, 0x1F, 0x3F for 0x400, 0x800, 0x1000) + unsigned long bit_buff; // 0014 - 16-bit buffer for processing input data + unsigned long extra_bits; // 0018 - Number of extra (above 8) bits in bit buffer + unsigned int in_pos; // 001C - Position in in_buff + unsigned long in_bytes; // 0020 - Number of bytes in input buffer + void * param; // 0024 - Custom parameter + unsigned int (*read_buf)(char *buf, unsigned int *size, void *param); // 0028 + void (*write_buf)(char *buf, unsigned int *size, void *param);// 002C + unsigned char out_buff[0x2000]; // 0030 - Output circle buffer. Starting position is 0x1000 + unsigned char offs2030[0x204]; // 2030 - ??? + unsigned char in_buff[0x800]; // 2234 - Buffer for data to be decompressed + unsigned char position1[0x100]; // 2A34 - Positions in buffers + unsigned char position2[0x100]; // 2B34 - Positions in buffers + unsigned char offs2C34[0x100]; // 2C34 - Buffer for + unsigned char offs2D34[0x100]; // 2D34 - Buffer for + unsigned char offs2E34[0x80]; // 2EB4 - Buffer for + unsigned char offs2EB4[0x100]; // 2EB4 - Buffer for + unsigned char ChBitsAsc[0x100]; // 2FB4 - Buffer for + unsigned char DistBits[0x40]; // 30B4 - Numbers of bytes to skip copied block length + unsigned char LenBits[0x10]; // 30F4 - Numbers of bits for skip copied block length + unsigned char ExLenBits[0x10]; // 3104 - Number of valid bits for copied block + unsigned short LenBase[0x10]; // 3114 - Buffer for +} TDcmpStruct; + +#define EXP_BUFFER_SIZE sizeof(TDcmpStruct) // Size of decompress buffer + +//----------------------------------------------------------------------------- +// Public functions + +#ifdef __cplusplus + extern "C" { +#endif + +unsigned int PKEXPORT implode( + unsigned int (*read_buf)(char *buf, unsigned int *size, void *param), + void (*write_buf)(char *buf, unsigned int *size, void *param), + char *work_buf, + void *param, + unsigned int *type, + unsigned int *dsize); + + +unsigned int PKEXPORT explode( + unsigned int (*read_buf)(char *buf, unsigned int *size, void *param), + void (*write_buf)(char *buf, unsigned int *size, void *param), + char *work_buf, + void *param); + +// The original name "crc32" was changed to "crc32pk" due +// to compatibility with zlib +unsigned long PKEXPORT crc32pk(char *buffer, unsigned int *size, unsigned long *old_crc); + +#ifdef __cplusplus + } // End of 'extern "C"' declaration +#endif + +#endif // __PKLIB_H__ diff --git a/contrib/vmap_extractor_v2/stormlib/wave/wave.cpp b/contrib/vmap_extractor_v2/stormlib/wave/wave.cpp new file mode 100644 index 00000000000..936525f4eae --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/wave/wave.cpp @@ -0,0 +1,356 @@ +/*****************************************************************************/ +/* wave.cpp Copyright (c) Ladislav Zezula 2003 */ +/*---------------------------------------------------------------------------*/ +/* This module contains decompression methods used by Storm.dll to decompress*/ +/* WAVe files. Thanks to Tom Amigo for releasing his sources. */ +/*---------------------------------------------------------------------------*/ +/* Date Ver Who Comment */ +/* -------- ---- --- ------- */ +/* 11.03.03 1.00 Lad Splitted from Pkware.cpp */ +/* 20.05.03 2.00 Lad Added compression */ +/* 19.11.03 2.01 Dan Big endian handling */ +/*****************************************************************************/ + +#include "wave.h" + +//------------------------------------------------------------------------------ +// Structures + +union TByteAndWordPtr +{ + short * pw; + unsigned char * pb; +}; + +union TWordAndByteArray +{ + short w; + unsigned char b[2]; +}; + +//----------------------------------------------------------------------------- +// Tables necessary dor decompression + +static long Table1503F120[] = +{ + 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000004, 0xFFFFFFFF, 0x00000002, 0xFFFFFFFF, 0x00000006, + 0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0x00000005, 0xFFFFFFFF, 0x00000003, 0xFFFFFFFF, 0x00000007, + 0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0x00000005, 0xFFFFFFFF, 0x00000003, 0xFFFFFFFF, 0x00000007, + 0xFFFFFFFF, 0x00000002, 0xFFFFFFFF, 0x00000004, 0xFFFFFFFF, 0x00000006, 0xFFFFFFFF, 0x00000008 +}; + +static long Table1503F1A0[] = +{ + 0x00000007, 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, + 0x00000010, 0x00000011, 0x00000013, 0x00000015, 0x00000017, 0x00000019, 0x0000001C, 0x0000001F, + 0x00000022, 0x00000025, 0x00000029, 0x0000002D, 0x00000032, 0x00000037, 0x0000003C, 0x00000042, + 0x00000049, 0x00000050, 0x00000058, 0x00000061, 0x0000006B, 0x00000076, 0x00000082, 0x0000008F, + 0x0000009D, 0x000000AD, 0x000000BE, 0x000000D1, 0x000000E6, 0x000000FD, 0x00000117, 0x00000133, + 0x00000151, 0x00000173, 0x00000198, 0x000001C1, 0x000001EE, 0x00000220, 0x00000256, 0x00000292, + 0x000002D4, 0x0000031C, 0x0000036C, 0x000003C3, 0x00000424, 0x0000048E, 0x00000502, 0x00000583, + 0x00000610, 0x000006AB, 0x00000756, 0x00000812, 0x000008E0, 0x000009C3, 0x00000ABD, 0x00000BD0, + 0x00000CFF, 0x00000E4C, 0x00000FBA, 0x0000114C, 0x00001307, 0x000014EE, 0x00001706, 0x00001954, + 0x00001BDC, 0x00001EA5, 0x000021B6, 0x00002515, 0x000028CA, 0x00002CDF, 0x0000315B, 0x0000364B, + 0x00003BB9, 0x000041B2, 0x00004844, 0x00004F7E, 0x00005771, 0x0000602F, 0x000069CE, 0x00007462, + 0x00007FFF +}; + +//---------------------------------------------------------------------------- +// CompressWave + +// 1500EF70 +int CompressWave(unsigned char * pbOutBuffer, int dwOutLength, short * pwInBuffer, int dwInLength, int nChannels, int nCmpLevel) +// ECX EDX +{ + TWordAndByteArray Wcmp; + TByteAndWordPtr out; // Pointer to the output buffer + long SInt32Array1[2]; + long SInt32Array2[2]; + long SInt32Array3[2]; + long nBytesRemains = dwOutLength; // Number of bytes remaining + long nWordsRemains; // Number of words remaining +// unsigned char * pbSaveOutBuffer; // Copy of output buffer (actually not used) + unsigned long dwBitBuff; + unsigned long dwStopBit; + unsigned long dwBit; + unsigned long ebx; + unsigned long esi; + long nTableValue; + long nOneWord; + long var_1C; + long var_2C; + int nLength; + int nIndex; + int nValue; + + // If less than 2 bytes remain, don't decompress anything +// pbSaveOutBuffer = pbOutBuffer; + out.pb = pbOutBuffer; + if(nBytesRemains < 2) + return 2; + + Wcmp.b[1] = (unsigned char)(nCmpLevel - 1); + Wcmp.b[0] = (unsigned char)0; + + *out.pw++ = BSWAP_INT16_SIGNED(Wcmp.w); + if((out.pb - pbOutBuffer + (nChannels * 2)) > nBytesRemains) + return (int)(out.pb - pbOutBuffer + (nChannels * 2)); + + SInt32Array1[0] = SInt32Array1[1] = 0x2C; + + for(int i = 0; i < nChannels; i++) + { + nOneWord = BSWAP_INT16_SIGNED(*pwInBuffer++); + *out.pw++ = BSWAP_INT16_SIGNED((short)nOneWord); + SInt32Array2[i] = nOneWord; + } + + // Weird. But it's there + nLength = dwInLength; + if(nLength < 0) // mov eax, dwInLength; cdq; sub eax, edx; + nLength++; + + nLength = (nLength / 2) - (int)(out.pb - pbOutBuffer); + nLength = (nLength < 0) ? 0 : nLength; + + nIndex = nChannels - 1; // edi + nWordsRemains = dwInLength / 2; // eax + + // ebx - nChannels + // ecx - pwOutPos + for(int chnl = nChannels; chnl < nWordsRemains; chnl++) + { + // 1500F030 + if((out.pb - pbOutBuffer + 2) > nBytesRemains) + return (int)(out.pb - pbOutBuffer + 2); + + // Switch index + if(nChannels == 2) + nIndex = (nIndex == 0) ? 1 : 0; + + // Load one word from the input stream + nOneWord = BSWAP_INT16_SIGNED(*pwInBuffer++); // ecx - nOneWord + SInt32Array3[nIndex] = nOneWord; + + // esi - SInt32Array2[nIndex] + // eax - nValue + nValue = nOneWord - SInt32Array2[nIndex]; + nValue = (nValue < 0) ? ((nValue ^ 0xFFFFFFFF) + 1) : nValue; + + ebx = (nOneWord >= SInt32Array2[nIndex]) ? 0 : 0x40; + + // esi - SInt32Array2[nIndex] + // edx - Table1503F1A0[SInt32Array2[nIndex]] + // edi - (Table1503F1A0[SInt32Array1[nIndex]] >> nCmpLevel) + nTableValue = Table1503F1A0[SInt32Array1[nIndex]]; + dwStopBit = (unsigned long)nCmpLevel; + + // edi - nIndex; + if(nValue < (nTableValue >> nCmpLevel)) + { + if(SInt32Array1[nIndex] != 0) + SInt32Array1[nIndex]--; + *out.pb++ = 0x80; + } + else + { + while(nValue > nTableValue * 2) + { + if(SInt32Array1[nIndex] >= 0x58 || nLength == 0) + break; + + SInt32Array1[nIndex] += 8; + if(SInt32Array1[nIndex] > 0x58) + SInt32Array1[nIndex] = 0x58; + + nTableValue = Table1503F1A0[SInt32Array1[nIndex]]; + *out.pb++ = 0x81; + nLength--; + } + + var_2C = nTableValue >> Wcmp.b[1]; + dwBitBuff = 0; + + esi = (1 << (dwStopBit - 2)); + dwStopBit = (esi <= 0x20) ? esi : 0x20; + + for(var_1C = 0, dwBit = 1; ; dwBit <<= 1) + { +// esi = var_1C + nTableValue; + if((var_1C + nTableValue) <= nValue) + { + var_1C += nTableValue; + dwBitBuff |= dwBit; + } + if(dwBit == dwStopBit) + break; + + nTableValue >>= 1; + } + + nValue = SInt32Array2[nIndex]; + if(ebx != 0) + { + nValue -= (var_1C + var_2C); + if(nValue < -32768) + nValue = -32768; + } + else + { + nValue += (var_1C + var_2C); + if(nValue > 32767) + nValue = 32767; + } + + SInt32Array2[nIndex] = nValue; + *out.pb++ = (unsigned char)(dwBitBuff | ebx); + nTableValue = Table1503F120[dwBitBuff & 0x1F]; + SInt32Array1[nIndex] = SInt32Array1[nIndex] + nTableValue; + if(SInt32Array1[nIndex] < 0) + SInt32Array1[nIndex] = 0; + else if(SInt32Array1[nIndex] > 0x58) + SInt32Array1[nIndex] = 0x58; + } + } + + return (int)(out.pb - pbOutBuffer); +} + +//---------------------------------------------------------------------------- +// DecompressWave + +// 1500F230 +int DecompressWave(unsigned char * pbOutBuffer, int dwOutLength, unsigned char * pbInBuffer, int dwInLength, int nChannels) +{ + TByteAndWordPtr out; // Output buffer + TByteAndWordPtr in; + unsigned char * pbInBufferEnd = (pbInBuffer + dwInLength); + long SInt32Array1[2]; + long SInt32Array2[2]; + long nOneWord; + int dwOutLengthCopy = dwOutLength; + int nIndex; + + SInt32Array1[0] = SInt32Array1[1] = 0x2C; + out.pb = pbOutBuffer; + in.pb = pbInBuffer; + in.pw++; + + // Fill the Uint32Array2 array by channel values. + for(int i = 0; i < nChannels; i++) + { + nOneWord = BSWAP_INT16_SIGNED(*in.pw++); + SInt32Array2[i] = nOneWord; + if(dwOutLengthCopy < 2) + return (int)(out.pb - pbOutBuffer); + + *out.pw++ = BSWAP_INT16_SIGNED((short)nOneWord); + dwOutLengthCopy -= sizeof(short); + } + + // Get the initial index + nIndex = nChannels - 1; + + // Perform the decompression + while(in.pb < pbInBufferEnd) + { + unsigned char nOneByte = *in.pb++; + + // Switch index + if(nChannels == 2) + nIndex = (nIndex == 0) ? 1 : 0; + + // 1500F2A2: Get one byte from input buffer + if(nOneByte & 0x80) + { + switch(nOneByte & 0x7F) + { + case 0: // 1500F315 + if(SInt32Array1[nIndex] != 0) + SInt32Array1[nIndex]--; + + if(dwOutLengthCopy < 2) + return (int)(out.pb - pbOutBuffer); + + *out.pw++ = BSWAP_INT16_SIGNED((unsigned short)SInt32Array2[nIndex]); + dwOutLength -= sizeof(unsigned short); + break; + + case 1: // 1500F2E8 + SInt32Array1[nIndex] += 8; + if(SInt32Array1[nIndex] > 0x58) + SInt32Array1[nIndex] = 0x58; + + if(nChannels == 2) + nIndex = (nIndex == 0) ? 1 : 0; + break; + + case 2: // 1500F41E + break; + + default: // 1500F2C4 + SInt32Array1[nIndex] -= 8; + if(SInt32Array1[nIndex] < 0) + SInt32Array1[nIndex] = 0; + + if(nChannels == 2) + nIndex = (nIndex == 0) ? 1 : 0; + break; + } + } + else + { + // 1500F349 + long temp1 = Table1503F1A0[SInt32Array1[nIndex]]; // EDI + long temp2 = temp1 >> pbInBuffer[1]; // ESI + long temp3 = SInt32Array2[nIndex]; // ECX + + if(nOneByte & 0x01) // EBX = nOneByte + temp2 += (temp1 >> 0); + + if(nOneByte & 0x02) + temp2 += (temp1 >> 1); + + if(nOneByte & 0x04) + temp2 += (temp1 >> 2); + + if(nOneByte & 0x08) + temp2 += (temp1 >> 3); + + if(nOneByte & 0x10) + temp2 += (temp1 >> 4); + + if(nOneByte & 0x20) + temp2 += (temp1 >> 5); + + if(nOneByte & 0x40) + { + temp3 = temp3 - temp2; + if(temp3 <= -32768) + temp3 = -32768; + } + else + { + temp3 = temp3 + temp2; + if(temp3 >= 32767) + temp3 = 32767; + } + + SInt32Array2[nIndex] = temp3; + if(dwOutLength < 2) + break; + + // Store the output 16-bit value + *out.pw++ = BSWAP_INT16_SIGNED((short)SInt32Array2[nIndex]); + dwOutLength -= 2; + + SInt32Array1[nIndex] += Table1503F120[nOneByte & 0x1F]; + + if(SInt32Array1[nIndex] < 0) + SInt32Array1[nIndex] = 0; + else if(SInt32Array1[nIndex] > 0x58) + SInt32Array1[nIndex] = 0x58; + } + } + return (int)(out.pb - pbOutBuffer); +} diff --git a/contrib/vmap_extractor_v2/stormlib/wave/wave.h b/contrib/vmap_extractor_v2/stormlib/wave/wave.h new file mode 100644 index 00000000000..81b5add9cfc --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/wave/wave.h @@ -0,0 +1,22 @@ +/*****************************************************************************/ +/* Wave.h Copyright (c) Ladislav Zezula 2003 */ +/*---------------------------------------------------------------------------*/ +/* Header file for WAVe unplode functions */ +/*---------------------------------------------------------------------------*/ +/* Date Ver Who Comment */ +/* -------- ---- --- ------- */ +/* 31.03.03 1.00 Lad The first version of Wave.h */ +/*****************************************************************************/ + +#ifndef __WAVE_H__ +#define __WAVE_H__ + +//----------------------------------------------------------------------------- +// Functions + +#include "../StormPort.h" + +int CompressWave (unsigned char * pbOutBuffer, int dwOutLength, short * pwInBuffer, int dwInLength, int nCmpType, int nChannels); +int DecompressWave(unsigned char * pbOutBuffer, int dwOutLength, unsigned char * pbInBuffer, int dwInLength, int nChannels); + +#endif // __WAVE_H__ diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/ChangeLog b/contrib/vmap_extractor_v2/stormlib/zlib/ChangeLog new file mode 100644 index 00000000000..bf2e3f925bc --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/ChangeLog @@ -0,0 +1,481 @@ + + ChangeLog file for zlib + +Changes in 1.1.4 (11 March 2002) +- ZFREE was repeated on same allocation on some error conditions. + This creates a security problem described in + http://www.zlib.org/advisory-2002-03-11.txt +- Returned incorrect error (Z_MEM_ERROR) on some invalid data +- Avoid accesses before window for invalid distances with inflate window + less than 32K. +- force windowBits > 8 to avoid a bug in the encoder for a window size + of 256 bytes. (A complete fix will be available in 1.1.5). + +Changes in 1.1.3 (9 July 1998) +- fix "an inflate input buffer bug that shows up on rare but persistent + occasions" (Mark) +- fix gzread and gztell for concatenated .gz files (Didier Le Botlan) +- fix gzseek(..., SEEK_SET) in write mode +- fix crc check after a gzeek (Frank Faubert) +- fix miniunzip when the last entry in a zip file is itself a zip file + (J Lillge) +- add contrib/asm586 and contrib/asm686 (Brian Raiter) + See http://www.muppetlabs.com/~breadbox/software/assembly.html +- add support for Delphi 3 in contrib/delphi (Bob Dellaca) +- add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti) +- do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren) +- use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks) +- added a FAQ file + +- Support gzdopen on Mac with Metrowerks (Jason Linhart) +- Do not redefine Byte on Mac (Brad Pettit & Jason Linhart) +- define SEEK_END too if SEEK_SET is not defined (Albert Chin-A-Young) +- avoid some warnings with Borland C (Tom Tanner) +- fix a problem in contrib/minizip/zip.c for 16-bit MSDOS (Gilles Vollant) +- emulate utime() for WIN32 in contrib/untgz (Gilles Vollant) +- allow several arguments to configure (Tim Mooney, Frodo Looijaard) +- use libdir and includedir in Makefile.in (Tim Mooney) +- support shared libraries on OSF1 V4 (Tim Mooney) +- remove so_locations in "make clean" (Tim Mooney) +- fix maketree.c compilation error (Glenn, Mark) +- Python interface to zlib now in Python 1.5 (Jeremy Hylton) +- new Makefile.riscos (Rich Walker) +- initialize static descriptors in trees.c for embedded targets (Nick Smith) +- use "foo-gz" in example.c for RISCOS and VMS (Nick Smith) +- add the OS/2 files in Makefile.in too (Andrew Zabolotny) +- fix fdopen and halloc macros for Microsoft C 6.0 (Tom Lane) +- fix maketree.c to allow clean compilation of inffixed.h (Mark) +- fix parameter check in deflateCopy (Gunther Nikl) +- cleanup trees.c, use compressed_len only in debug mode (Christian Spieler) +- Many portability patches by Christian Spieler: + . zutil.c, zutil.h: added "const" for zmem* + . Make_vms.com: fixed some typos + . Make_vms.com: msdos/Makefile.*: removed zutil.h from some dependency lists + . msdos/Makefile.msc: remove "default rtl link library" info from obj files + . msdos/Makefile.*: use model-dependent name for the built zlib library + . msdos/Makefile.emx, nt/Makefile.emx, nt/Makefile.gcc: + new makefiles, for emx (DOS/OS2), emx&rsxnt and mingw32 (Windows 9x / NT) +- use define instead of typedef for Bytef also for MSC small/medium (Tom Lane) +- replace __far with _far for better portability (Christian Spieler, Tom Lane) +- fix test for errno.h in configure (Tim Newsham) + +Changes in 1.1.2 (19 March 98) +- added contrib/minzip, mini zip and unzip based on zlib (Gilles Vollant) + See http://www.winimage.com/zLibDll/unzip.html +- preinitialize the inflate tables for fixed codes, to make the code + completely thread safe (Mark) +- some simplifications and slight speed-up to the inflate code (Mark) +- fix gzeof on non-compressed files (Allan Schrum) +- add -std1 option in configure for OSF1 to fix gzprintf (Martin Mokrejs) +- use default value of 4K for Z_BUFSIZE for 16-bit MSDOS (Tim Wegner + Glenn) +- added os2/Makefile.def and os2/zlib.def (Andrew Zabolotny) +- add shared lib support for UNIX_SV4.2MP (MATSUURA Takanori) +- do not wrap extern "C" around system includes (Tom Lane) +- mention zlib binding for TCL in README (Andreas Kupries) +- added amiga/Makefile.pup for Amiga powerUP SAS/C PPC (Andreas Kleinert) +- allow "make install prefix=..." even after configure (Glenn Randers-Pehrson) +- allow "configure --prefix $HOME" (Tim Mooney) +- remove warnings in example.c and gzio.c (Glenn Randers-Pehrson) +- move Makefile.sas to amiga/Makefile.sas + +Changes in 1.1.1 (27 Feb 98) +- fix macros _tr_tally_* in deflate.h for debug mode (Glenn Randers-Pehrson) +- remove block truncation heuristic which had very marginal effect for zlib + (smaller lit_bufsize than in gzip 1.2.4) and degraded a little the + compression ratio on some files. This also allows inlining _tr_tally for + matches in deflate_slow. +- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier) + +Changes in 1.1.0 (24 Feb 98) +- do not return STREAM_END prematurely in inflate (John Bowler) +- revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler) +- compile with -DFASTEST to get compression code optimized for speed only +- in minigzip, try mmap'ing the input file first (Miguel Albrecht) +- increase size of I/O buffers in minigzip.c and gzio.c (not a big gain + on Sun but significant on HP) + +- add a pointer to experimental unzip library in README (Gilles Vollant) +- initialize variable gcc in configure (Chris Herborth) + +Changes in 1.0.9 (17 Feb 1998) +- added gzputs and gzgets functions +- do not clear eof flag in gzseek (Mark Diekhans) +- fix gzseek for files in transparent mode (Mark Diekhans) +- do not assume that vsprintf returns the number of bytes written (Jens Krinke) +- replace EXPORT with ZEXPORT to avoid conflict with other programs +- added compress2 in zconf.h, zlib.def, zlib.dnt +- new asm code from Gilles Vollant in contrib/asm386 +- simplify the inflate code (Mark): + . Replace ZALLOC's in huft_build() with single ZALLOC in inflate_blocks_new() + . ZALLOC the length list in inflate_trees_fixed() instead of using stack + . ZALLOC the value area for huft_build() instead of using stack + . Simplify Z_FINISH check in inflate() + +- Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8 +- in inftrees.c, avoid cc -O bug on HP (Farshid Elahi) +- in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with + the declaration of FAR (Gilles VOllant) +- install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann) +- read_buf buf parameter of type Bytef* instead of charf* +- zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout) +- do not redeclare unlink in minigzip.c for WIN32 (John Bowler) +- fix check for presence of directories in "make install" (Ian Willis) + +Changes in 1.0.8 (27 Jan 1998) +- fixed offsets in contrib/asm386/gvmat32.asm (Gilles Vollant) +- fix gzgetc and gzputc for big endian systems (Markus Oberhumer) +- added compress2() to allow setting the compression level +- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong) +- use constant arrays for the static trees in trees.c instead of computing + them at run time (thanks to Ken Raeburn for this suggestion). To create + trees.h, compile with GEN_TREES_H and run "make test". +- check return code of example in "make test" and display result +- pass minigzip command line options to file_compress +- simplifying code of inflateSync to avoid gcc 2.8 bug + +- support CC="gcc -Wall" in configure -s (QingLong) +- avoid a flush caused by ftell in gzopen for write mode (Ken Raeburn) +- fix test for shared library support to avoid compiler warnings +- zlib.lib -> zlib.dll in msdos/zlib.rc (Gilles Vollant) +- check for TARGET_OS_MAC in addition to MACOS (Brad Pettit) +- do not use fdopen for Metrowerks on Mac (Brad Pettit)) +- add checks for gzputc and gzputc in example.c +- avoid warnings in gzio.c and deflate.c (Andreas Kleinert) +- use const for the CRC table (Ken Raeburn) +- fixed "make uninstall" for shared libraries +- use Tracev instead of Trace in infblock.c +- in example.c use correct compressed length for test_sync +- suppress +vnocompatwarnings in configure for HPUX (not always supported) + +Changes in 1.0.7 (20 Jan 1998) +- fix gzseek which was broken in write mode +- return error for gzseek to negative absolute position +- fix configure for Linux (Chun-Chung Chen) +- increase stack space for MSC (Tim Wegner) +- get_crc_table and inflateSyncPoint are EXPORTed (Gilles Vollant) +- define EXPORTVA for gzprintf (Gilles Vollant) +- added man page zlib.3 (Rick Rodgers) +- for contrib/untgz, fix makedir() and improve Makefile + +- check gzseek in write mode in example.c +- allocate extra buffer for seeks only if gzseek is actually called +- avoid signed/unsigned comparisons (Tim Wegner, Gilles Vollant) +- add inflateSyncPoint in zconf.h +- fix list of exported functions in nt/zlib.dnt and mdsos/zlib.def + +Changes in 1.0.6 (19 Jan 1998) +- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and + gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code) +- Fix a deflate bug occuring only with compression level 0 (thanks to + Andy Buckler for finding this one). +- In minigzip, pass transparently also the first byte for .Z files. +- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress() +- check Z_FINISH in inflate (thanks to Marc Schluper) +- Implement deflateCopy (thanks to Adam Costello) +- make static libraries by default in configure, add --shared option. +- move MSDOS or Windows specific files to directory msdos +- suppress the notion of partial flush to simplify the interface + (but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4) +- suppress history buffer provided by application to simplify the interface + (this feature was not implemented anyway in 1.0.4) +- next_in and avail_in must be initialized before calling inflateInit or + inflateInit2 +- add EXPORT in all exported functions (for Windows DLL) +- added Makefile.nt (thanks to Stephen Williams) +- added the unsupported "contrib" directory: + contrib/asm386/ by Gilles Vollant + 386 asm code replacing longest_match(). + contrib/iostream/ by Kevin Ruland + A C++ I/O streams interface to the zlib gz* functions + contrib/iostream2/ by Tyge Løvset + Another C++ I/O streams interface + contrib/untgz/ by "Pedro A. Aranda Guti\irrez" + A very simple tar.gz file extractor using zlib + contrib/visual-basic.txt by Carlos Rios + How to use compress(), uncompress() and the gz* functions from VB. +- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression + level) in minigzip (thanks to Tom Lane) + +- use const for rommable constants in deflate +- added test for gzseek and gztell in example.c +- add undocumented function inflateSyncPoint() (hack for Paul Mackerras) +- add undocumented function zError to convert error code to string + (for Tim Smithers) +- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code. +- Use default memcpy for Symantec MSDOS compiler. +- Add EXPORT keyword for check_func (needed for Windows DLL) +- add current directory to LD_LIBRARY_PATH for "make test" +- create also a link for libz.so.1 +- added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura) +- use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX) +- added -soname for Linux in configure (Chun-Chung Chen, +- assign numbers to the exported functions in zlib.def (for Windows DLL) +- add advice in zlib.h for best usage of deflateSetDictionary +- work around compiler bug on Atari (cast Z_NULL in call of s->checkfn) +- allow compilation with ANSI keywords only enabled for TurboC in large model +- avoid "versionString"[0] (Borland bug) +- add NEED_DUMMY_RETURN for Borland +- use variable z_verbose for tracing in debug mode (L. Peter Deutsch). +- allow compilation with CC +- defined STDC for OS/2 (David Charlap) +- limit external names to 8 chars for MVS (Thomas Lund) +- in minigzip.c, use static buffers only for 16-bit systems +- fix suffix check for "minigzip -d foo.gz" +- do not return an error for the 2nd of two consecutive gzflush() (Felix Lee) +- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau) +- added makelcc.bat for lcc-win32 (Tom St Denis) +- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe) +- Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion. +- check for unistd.h in configure (for off_t) +- remove useless check parameter in inflate_blocks_free +- avoid useless assignment of s->check to itself in inflate_blocks_new +- do not flush twice in gzclose (thanks to Ken Raeburn) +- rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h +- use NO_ERRNO_H instead of enumeration of operating systems with errno.h +- work around buggy fclose on pipes for HP/UX +- support zlib DLL with BORLAND C++ 5.0 (thanks to Glenn Randers-Pehrson) +- fix configure if CC is already equal to gcc + +Changes in 1.0.5 (3 Jan 98) +- Fix inflate to terminate gracefully when fed corrupted or invalid data +- Use const for rommable constants in inflate +- Eliminate memory leaks on error conditions in inflate +- Removed some vestigial code in inflate +- Update web address in README + +Changes in 1.0.4 (24 Jul 96) +- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF + bit, so the decompressor could decompress all the correct data but went + on to attempt decompressing extra garbage data. This affected minigzip too. +- zlibVersion and gzerror return const char* (needed for DLL) +- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno) +- use z_error only for DEBUG (avoid problem with DLLs) + +Changes in 1.0.3 (2 Jul 96) +- use z_streamp instead of z_stream *, which is now a far pointer in MSDOS + small and medium models; this makes the library incompatible with previous + versions for these models. (No effect in large model or on other systems.) +- return OK instead of BUF_ERROR if previous deflate call returned with + avail_out as zero but there is nothing to do +- added memcmp for non STDC compilers +- define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly) +- define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO) +- better check for 16-bit mode MSC (avoids problem with Symantec) + +Changes in 1.0.2 (23 May 96) +- added Windows DLL support +- added a function zlibVersion (for the DLL support) +- fixed declarations using Bytef in infutil.c (pb with MSDOS medium model) +- Bytef is define's instead of typedef'd only for Borland C +- avoid reading uninitialized memory in example.c +- mention in README that the zlib format is now RFC1950 +- updated Makefile.dj2 +- added algorithm.doc + +Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion] +- fix array overlay in deflate.c which sometimes caused bad compressed data +- fix inflate bug with empty stored block +- fix MSDOS medium model which was broken in 0.99 +- fix deflateParams() which could generated bad compressed data. +- Bytef is define'd instead of typedef'ed (work around Borland bug) +- added an INDEX file +- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32), + Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas) +- speed up adler32 for modern machines without auto-increment +- added -ansi for IRIX in configure +- static_init_done in trees.c is an int +- define unlink as delete for VMS +- fix configure for QNX +- add configure branch for SCO and HPUX +- avoid many warnings (unused variables, dead assignments, etc...) +- no fdopen for BeOS +- fix the Watcom fix for 32 bit mode (define FAR as empty) +- removed redefinition of Byte for MKWERKS +- work around an MWKERKS bug (incorrect merge of all .h files) + +Changes in 0.99 (27 Jan 96) +- allow preset dictionary shared between compressor and decompressor +- allow compression level 0 (no compression) +- add deflateParams in zlib.h: allow dynamic change of compression level + and compression strategy. +- test large buffers and deflateParams in example.c +- add optional "configure" to build zlib as a shared library +- suppress Makefile.qnx, use configure instead +- fixed deflate for 64-bit systems (detected on Cray) +- fixed inflate_blocks for 64-bit systems (detected on Alpha) +- declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2) +- always return Z_BUF_ERROR when deflate() has nothing to do +- deflateInit and inflateInit are now macros to allow version checking +- prefix all global functions and types with z_ with -DZ_PREFIX +- make falloc completely reentrant (inftrees.c) +- fixed very unlikely race condition in ct_static_init +- free in reverse order of allocation to help memory manager +- use zlib-1.0/* instead of zlib/* inside the tar.gz +- make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith + -Wconversion -Wstrict-prototypes -Wmissing-prototypes" +- allow gzread on concatenated .gz files +- deflateEnd now returns Z_DATA_ERROR if it was premature +- deflate is finally (?) fully deterministic (no matches beyond end of input) +- Document Z_SYNC_FLUSH +- add uninstall in Makefile +- Check for __cpluplus in zlib.h +- Better test in ct_align for partial flush +- avoid harmless warnings for Borland C++ +- initialize hash_head in deflate.c +- avoid warning on fdopen (gzio.c) for HP cc -Aa +- include stdlib.h for STDC compilers +- include errno.h for Cray +- ignore error if ranlib doesn't exist +- call ranlib twice for NeXTSTEP +- use exec_prefix instead of prefix for libz.a +- renamed ct_* as _tr_* to avoid conflict with applications +- clear z->msg in inflateInit2 before any error return +- initialize opaque in example.c, gzio.c, deflate.c and inflate.c +- fixed typo in zconf.h (_GNUC__ => __GNUC__) +- check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode) +- fix typo in Make_vms.com (f$trnlnm -> f$getsyi) +- in fcalloc, normalize pointer if size > 65520 bytes +- don't use special fcalloc for 32 bit Borland C++ +- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc... +- use Z_BINARY instead of BINARY +- document that gzclose after gzdopen will close the file +- allow "a" as mode in gzopen. +- fix error checking in gzread +- allow skipping .gz extra-field on pipes +- added reference to Perl interface in README +- put the crc table in FAR data (I dislike more and more the medium model :) +- added get_crc_table +- added a dimension to all arrays (Borland C can't count). +- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast +- guard against multiple inclusion of *.h (for precompiled header on Mac) +- Watcom C pretends to be Microsoft C small model even in 32 bit mode. +- don't use unsized arrays to avoid silly warnings by Visual C++: + warning C4746: 'inflate_mask' : unsized array treated as '__far' + (what's wrong with far data in far model?). +- define enum out of inflate_blocks_state to allow compilation with C++ + +Changes in 0.95 (16 Aug 95) +- fix MSDOS small and medium model (now easier to adapt to any compiler) +- inlined send_bits +- fix the final (:-) bug for deflate with flush (output was correct but + not completely flushed in rare occasions). +- default window size is same for compression and decompression + (it's now sufficient to set MAX_WBITS in zconf.h). +- voidp -> voidpf and voidnp -> voidp (for consistency with other + typedefs and because voidnp was not near in large model). + +Changes in 0.94 (13 Aug 95) +- support MSDOS medium model +- fix deflate with flush (could sometimes generate bad output) +- fix deflateReset (zlib header was incorrectly suppressed) +- added support for VMS +- allow a compression level in gzopen() +- gzflush now calls fflush +- For deflate with flush, flush even if no more input is provided. +- rename libgz.a as libz.a +- avoid complex expression in infcodes.c triggering Turbo C bug +- work around a problem with gcc on Alpha (in INSERT_STRING) +- don't use inline functions (problem with some gcc versions) +- allow renaming of Byte, uInt, etc... with #define. +- avoid warning about (unused) pointer before start of array in deflate.c +- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c +- avoid reserved word 'new' in trees.c + +Changes in 0.93 (25 June 95) +- temporarily disable inline functions +- make deflate deterministic +- give enough lookahead for PARTIAL_FLUSH +- Set binary mode for stdin/stdout in minigzip.c for OS/2 +- don't even use signed char in inflate (not portable enough) +- fix inflate memory leak for segmented architectures + +Changes in 0.92 (3 May 95) +- don't assume that char is signed (problem on SGI) +- Clear bit buffer when starting a stored block +- no memcpy on Pyramid +- suppressed inftest.c +- optimized fill_window, put longest_match inline for gcc +- optimized inflate on stored blocks. +- untabify all sources to simplify patches + +Changes in 0.91 (2 May 95) +- Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h +- Document the memory requirements in zconf.h +- added "make install" +- fix sync search logic in inflateSync +- deflate(Z_FULL_FLUSH) now works even if output buffer too short +- after inflateSync, don't scare people with just "lo world" +- added support for DJGPP + +Changes in 0.9 (1 May 95) +- don't assume that zalloc clears the allocated memory (the TurboC bug + was Mark's bug after all :) +- let again gzread copy uncompressed data unchanged (was working in 0.71) +- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented +- added a test of inflateSync in example.c +- moved MAX_WBITS to zconf.h because users might want to change that. +- document explicitly that zalloc(64K) on MSDOS must return a normalized + pointer (zero offset) +- added Makefiles for Microsoft C, Turbo C, Borland C++ +- faster crc32() + +Changes in 0.8 (29 April 95) +- added fast inflate (inffast.c) +- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this + is incompatible with previous versions of zlib which returned Z_OK. +- work around a TurboC compiler bug (bad code for b << 0, see infutil.h) + (actually that was not a compiler bug, see 0.81 above) +- gzread no longer reads one extra byte in certain cases +- In gzio destroy(), don't reference a freed structure +- avoid many warnings for MSDOS +- avoid the ERROR symbol which is used by MS Windows + +Changes in 0.71 (14 April 95) +- Fixed more MSDOS compilation problems :( There is still a bug with + TurboC large model. + +Changes in 0.7 (14 April 95) +- Added full inflate support. +- Simplified the crc32() interface. The pre- and post-conditioning + (one's complement) is now done inside crc32(). WARNING: this is + incompatible with previous versions; see zlib.h for the new usage. + +Changes in 0.61 (12 April 95) +- workaround for a bug in TurboC. example and minigzip now work on MSDOS. + +Changes in 0.6 (11 April 95) +- added minigzip.c +- added gzdopen to reopen a file descriptor as gzFile +- added transparent reading of non-gziped files in gzread. +- fixed bug in gzread (don't read crc as data) +- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose). +- don't allocate big arrays in the stack (for MSDOS) +- fix some MSDOS compilation problems + +Changes in 0.5: +- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but + not yet Z_FULL_FLUSH. +- support decompression but only in a single step (forced Z_FINISH) +- added opaque object for zalloc and zfree. +- added deflateReset and inflateReset +- added a variable zlib_version for consistency checking. +- renamed the 'filter' parameter of deflateInit2 as 'strategy'. + Added Z_FILTERED and Z_HUFFMAN_ONLY constants. + +Changes in 0.4: +- avoid "zip" everywhere, use zlib instead of ziplib. +- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush + if compression method == 8. +- added adler32 and crc32 +- renamed deflateOptions as deflateInit2, call one or the other but not both +- added the method parameter for deflateInit2. +- added inflateInit2 +- simplied considerably deflateInit and inflateInit by not supporting + user-provided history buffer. This is supported only in deflateInit2 + and inflateInit2. + +Changes in 0.3: +- prefix all macro names with Z_ +- use Z_FINISH instead of deflateEnd to finish compression. +- added Z_HUFFMAN_ONLY +- added gzerror() diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/FAQ b/contrib/vmap_extractor_v2/stormlib/zlib/FAQ new file mode 100644 index 00000000000..47a7d60c6de --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/FAQ @@ -0,0 +1,100 @@ + + Frequently Asked Questions about zlib + + +If your question is not there, please check the zlib home page +http://www.zlib.org which may have more recent information. +The lastest zlib FAQ is at http://www.gzip.org/zlib/zlib_faq.html + + + 1. Is zlib Y2K-compliant? + + Yes. zlib doesn't handle dates. + + 2. Where can I get a Windows DLL version? + + The zlib sources can be compiled without change to produce a DLL. If you + want a precompiled DLL, see http://www.winimage.com/zLibDll/ . Questions + about the zlib DLL should be sent to Gilles Vollant (info@winimage.com). + + 3. Where can I get a Visual Basic interface to zlib? + + See + * http://www.winimage.com/zLibDll/cmp-z-it.zip + * http://www.dogma.net/markn/articles/zlibtool/zlibtool.htm + * contrib/visual-basic.txt in the zlib distribution + + 4. compress() returns Z_BUF_ERROR + + Make sure that before the call of compress, the length of the compressed + buffer is equal to the total size of the compressed buffer and not + zero. For Visual Basic, check that this parameter is passed by reference + ("as any"), not by value ("as long"). + + 5. deflate() or inflate() returns Z_BUF_ERROR + + Before making the call, make sure that avail_in and avail_out are not + zero. When setting the parameter flush equal to Z_FINISH, also make sure + that avail_out is big enough to allow processing all pending input. + + 6. Where's the zlib documentation (man pages, etc.)? + + It's in zlib.h for the moment, and Francis S. Lin has converted it to a + web page zlib.html. Volunteers to transform this to Unix-style man pages, + please contact Jean-loup Gailly (jloup@gzip.org). Examples of zlib usage + are in the files example.c and minigzip.c. + + 7. Why don't you use GNU autoconf or libtool or ...? + + Because we would like to keep zlib as a very small and simple + package. zlib is rather portable and doesn't need much configuration. + + 8. I found a bug in zlib. + + Most of the time, such problems are due to an incorrect usage of + zlib. Please try to reproduce the problem with a small program and send + the corresponding source to us at zlib@gzip.org . Do not send + multi-megabyte data files without prior agreement. + + 9. Why do I get "undefined reference to gzputc"? + + If "make test" produces something like + + example.o(.text+0x154): undefined reference to `gzputc' + + check that you don't have old files libz.* in /usr/lib, /usr/local/lib or + /usr/X11R6/lib. Remove any old versions, then do "make install". + +10. I need a Delphi interface to zlib. + + See the directories contrib/delphi and contrib/delphi2 in the zlib + distribution. + +11. Can zlib handle .zip archives? + + See the directory contrib/minizip in the zlib distribution. + +12. Can zlib handle .Z files? + + No, sorry. You have to spawn an uncompress or gunzip subprocess, or adapt + the code of uncompress on your own. + +13. How can I make a Unix shared library? + + make clean + ./configure -s + make + +14. Why does "make test" fail on Mac OS X? + + Mac OS X already includes zlib as a shared library, and so -lz links the + shared library instead of the one that the "make" compiled. For zlib + 1.1.3, the two are incompatible due to different compile-time + options. Simply change the -lz in the Makefile to libz.a, and it will use + the compiled library instead of the shared one and the "make test" will + succeed. + +15. I have a question about OttoPDF + + We are not the authors of OttoPDF. The real author is on the OttoPDF web + site Joel Hainley jhainley@myndkryme.com. diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/INDEX b/contrib/vmap_extractor_v2/stormlib/zlib/INDEX new file mode 100644 index 00000000000..8a245766402 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/INDEX @@ -0,0 +1,86 @@ +ChangeLog history of changes +INDEX this file +FAQ Frequently Asked Questions about zlib +Make_vms.com script for Vax/VMS +Makefile makefile for Unix (generated by configure) +Makefile.in makefile for Unix (template for configure) +Makefile.riscos makefile for RISCOS +README guess what +algorithm.txt description of the (de)compression algorithm +configure configure script for Unix +descrip.mms makefile for Vax/VMS +zlib.3 mini man page for zlib (volunteers to write full + man pages from zlib.h welcome. write to jloup@gzip.org) + +amiga/Makefile.sas makefile for Amiga SAS/C +amiga/Makefile.pup makefile for Amiga powerUP SAS/C PPC + +msdos/Makefile.w32 makefile for Microsoft Visual C++ 32-bit +msdos/Makefile.b32 makefile for Borland C++ 32-bit +msdos/Makefile.bor makefile for Borland C/C++ 16-bit +msdos/Makefile.dj2 makefile for DJGPP 2.x +msdos/Makefile.emx makefile for EMX 0.9c (32-bit DOS/OS2) +msdos/Makefile.msc makefile for Microsoft C 16-bit +msdos/Makefile.tc makefile for Turbo C +msdos/Makefile.wat makefile for Watcom C +msdos/zlib.def definition file for Windows DLL +msdos/zlib.rc definition file for Windows DLL + +nt/Makefile.nt makefile for Windows NT +nt/zlib.dnt definition file for Windows NT DLL +nt/Makefile.emx makefile for EMX 0.9c/RSXNT 1.41 (Win32 Intel) +nt/Makefile.gcc makefile for Windows NT using GCC (mingw32) + + + zlib public header files (must be kept): +zconf.h +zlib.h + + private source files used to build the zlib library: +adler32.c +compress.c +crc32.c +deflate.c +deflate.h +gzio.c +infblock.c +infblock.h +infcodes.c +infcodes.h +inffast.c +inffast.h +inflate.c +inftrees.c +inftrees.h +infutil.c +infutil.h +maketree.c +trees.c +uncompr.c +zutil.c +zutil.h + + source files for sample programs: +example.c +minigzip.c + + unsupported contribution by third parties + +contrib/asm386/ by Gilles Vollant + 386 asm code replacing longest_match(). + +contrib/minizip/ by Gilles Vollant + Mini zip and unzip based on zlib + See http://www.winimage.com/zLibDll/unzip.html + +contrib/iostream/ by Kevin Ruland + A C++ I/O streams interface to the zlib gz* functions + +contrib/iostream2/ by Tyge Løvset + Another C++ I/O streams interface + +contrib/untgz/ by "Pedro A. Aranda Guti\irrez" + A very simple tar.gz extractor using zlib + +contrib/visual-basic.txt by Carlos Rios + How to use compress(), uncompress() and the gz* functions from VB. diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/Makefile b/contrib/vmap_extractor_v2/stormlib/zlib/Makefile new file mode 100644 index 00000000000..531562b2ef1 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/Makefile @@ -0,0 +1,175 @@ +# Makefile for zlib +# Copyright (C) 1995-2002 Jean-loup Gailly. +# For conditions of distribution and use, see copyright notice in zlib.h + +# To compile and test, type: +# ./configure; make test +# The call of configure is optional if you don't have special requirements +# If you wish to build zlib as a shared library, use: ./configure -s + +# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type: +# make install +# To install in $HOME instead of /usr/local, use: +# make install prefix=$HOME + +CC=cc + +CFLAGS=-O +#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 +#CFLAGS=-g -DDEBUG +#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ +# -Wstrict-prototypes -Wmissing-prototypes + +LDFLAGS=-L. -lz +LDSHARED=$(CC) +CPP=$(CC) -E + +VER=1.1.4 +LIBS=libz.a +SHAREDLIB=libz.so + +AR=ar rc +RANLIB=ranlib +TAR=tar +SHELL=/bin/sh + +prefix = /usr/local +exec_prefix = ${prefix} +libdir = ${exec_prefix}/lib +includedir = ${prefix}/include + +OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ + zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o + +OBJA = +# to use the asm code: make OBJA=match.o + +TEST_OBJS = example.o minigzip.o + +DISTFILES = README FAQ INDEX ChangeLog configure Make*[a-z0-9] *.[ch] *.mms \ + algorithm.txt zlib.3 zlib.html \ + msdos/Make*[a-z0-9] msdos/zlib.def msdos/zlib.rc \ + nt/Make*[a-z0-9] nt/zlib.dnt amiga/Make*.??? os2/M*.os2 os2/zlib.def \ + contrib/RE*.contrib contrib/*.txt contrib/asm386/*.asm contrib/asm386/*.c \ + contrib/asm386/*.bat contrib/asm386/zlibvc.d?? contrib/asm[56]86/*.?86 \ + contrib/asm[56]86/*.S contrib/iostream/*.cpp \ + contrib/iostream/*.h contrib/iostream2/*.h contrib/iostream2/*.cpp \ + contrib/untgz/Makefile contrib/untgz/*.c contrib/untgz/*.w32 \ + contrib/minizip/[CM]*[pe] contrib/minizip/*.[ch] contrib/minizip/*.[td]?? \ + contrib/delphi*/*.??? + +all: example minigzip + +test: all + @LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \ + echo hello world | ./minigzip | ./minigzip -d || \ + echo ' *** minigzip test FAILED ***' ; \ + if ./example; then \ + echo ' *** zlib test OK ***'; \ + else \ + echo ' *** zlib test FAILED ***'; \ + fi + +libz.a: $(OBJS) $(OBJA) + $(AR) $@ $(OBJS) $(OBJA) + -@ ($(RANLIB) $@ || true) >/dev/null 2>&1 + +match.o: match.S + $(CPP) match.S > _match.s + $(CC) -c _match.s + mv _match.o match.o + rm -f _match.s + +$(SHAREDLIB).$(VER): $(OBJS) + $(LDSHARED) -o $@ $(OBJS) + rm -f $(SHAREDLIB) $(SHAREDLIB).1 + ln -s $@ $(SHAREDLIB) + ln -s $@ $(SHAREDLIB).1 + +example: example.o $(LIBS) + $(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS) + +minigzip: minigzip.o $(LIBS) + $(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS) + +install: $(LIBS) + -@if [ ! -d $(includedir) ]; then mkdir $(includedir); fi + -@if [ ! -d $(libdir) ]; then mkdir $(libdir); fi + cp zlib.h zconf.h $(includedir) + chmod 644 $(includedir)/zlib.h $(includedir)/zconf.h + cp $(LIBS) $(libdir) + cd $(libdir); chmod 755 $(LIBS) + -@(cd $(libdir); $(RANLIB) libz.a || true) >/dev/null 2>&1 + cd $(libdir); if test -f $(SHAREDLIB).$(VER); then \ + rm -f $(SHAREDLIB) $(SHAREDLIB).1; \ + ln -s $(SHAREDLIB).$(VER) $(SHAREDLIB); \ + ln -s $(SHAREDLIB).$(VER) $(SHAREDLIB).1; \ + (ldconfig || true) >/dev/null 2>&1; \ + fi +# The ranlib in install is needed on NeXTSTEP which checks file times +# ldconfig is for Linux + +uninstall: + cd $(includedir); \ + v=$(VER); \ + if test -f zlib.h; then \ + v=`sed -n '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`; \ + rm -f zlib.h zconf.h; \ + fi; \ + cd $(libdir); rm -f libz.a; \ + if test -f $(SHAREDLIB).$$v; then \ + rm -f $(SHAREDLIB).$$v $(SHAREDLIB) $(SHAREDLIB).1; \ + fi + +clean: + rm -f *.o *~ example minigzip libz.a libz.so* foo.gz so_locations \ + _match.s maketree + +distclean: clean + +zip: + mv Makefile Makefile~; cp -p Makefile.in Makefile + rm -f test.c ztest*.c contrib/minizip/test.zip + v=`sed -n -e 's/\.//g' -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\ + zip -ul9 zlib$$v $(DISTFILES) + mv Makefile~ Makefile + +dist: + mv Makefile Makefile~; cp -p Makefile.in Makefile + rm -f test.c ztest*.c contrib/minizip/test.zip + d=zlib-`sed -n '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\ + rm -f $$d.tar.gz; \ + if test ! -d ../$$d; then rm -f ../$$d; ln -s `pwd` ../$$d; fi; \ + files=""; \ + for f in $(DISTFILES); do files="$$files $$d/$$f"; done; \ + cd ..; \ + GZIP=-9 $(TAR) chofz $$d/$$d.tar.gz $$files; \ + if test ! -d $$d; then rm -f $$d; fi + mv Makefile~ Makefile + +tags: + etags *.[ch] + +depend: + makedepend -- $(CFLAGS) -- *.[ch] + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +adler32.o: zlib.h zconf.h +compress.o: zlib.h zconf.h +crc32.o: zlib.h zconf.h +deflate.o: deflate.h zutil.h zlib.h zconf.h +example.o: zlib.h zconf.h +gzio.o: zutil.h zlib.h zconf.h +infblock.o: infblock.h inftrees.h infcodes.h infutil.h zutil.h zlib.h zconf.h +infcodes.o: zutil.h zlib.h zconf.h +infcodes.o: inftrees.h infblock.h infcodes.h infutil.h inffast.h +inffast.o: zutil.h zlib.h zconf.h inftrees.h +inffast.o: infblock.h infcodes.h infutil.h inffast.h +inflate.o: zutil.h zlib.h zconf.h infblock.h +inftrees.o: zutil.h zlib.h zconf.h inftrees.h +infutil.o: zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h +minigzip.o: zlib.h zconf.h +trees.o: deflate.h zutil.h zlib.h zconf.h trees.h +uncompr.o: zlib.h zconf.h +zutil.o: zutil.h zlib.h zconf.h diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/Makefile.in b/contrib/vmap_extractor_v2/stormlib/zlib/Makefile.in new file mode 100644 index 00000000000..531562b2ef1 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/Makefile.in @@ -0,0 +1,175 @@ +# Makefile for zlib +# Copyright (C) 1995-2002 Jean-loup Gailly. +# For conditions of distribution and use, see copyright notice in zlib.h + +# To compile and test, type: +# ./configure; make test +# The call of configure is optional if you don't have special requirements +# If you wish to build zlib as a shared library, use: ./configure -s + +# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type: +# make install +# To install in $HOME instead of /usr/local, use: +# make install prefix=$HOME + +CC=cc + +CFLAGS=-O +#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 +#CFLAGS=-g -DDEBUG +#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ +# -Wstrict-prototypes -Wmissing-prototypes + +LDFLAGS=-L. -lz +LDSHARED=$(CC) +CPP=$(CC) -E + +VER=1.1.4 +LIBS=libz.a +SHAREDLIB=libz.so + +AR=ar rc +RANLIB=ranlib +TAR=tar +SHELL=/bin/sh + +prefix = /usr/local +exec_prefix = ${prefix} +libdir = ${exec_prefix}/lib +includedir = ${prefix}/include + +OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ + zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o + +OBJA = +# to use the asm code: make OBJA=match.o + +TEST_OBJS = example.o minigzip.o + +DISTFILES = README FAQ INDEX ChangeLog configure Make*[a-z0-9] *.[ch] *.mms \ + algorithm.txt zlib.3 zlib.html \ + msdos/Make*[a-z0-9] msdos/zlib.def msdos/zlib.rc \ + nt/Make*[a-z0-9] nt/zlib.dnt amiga/Make*.??? os2/M*.os2 os2/zlib.def \ + contrib/RE*.contrib contrib/*.txt contrib/asm386/*.asm contrib/asm386/*.c \ + contrib/asm386/*.bat contrib/asm386/zlibvc.d?? contrib/asm[56]86/*.?86 \ + contrib/asm[56]86/*.S contrib/iostream/*.cpp \ + contrib/iostream/*.h contrib/iostream2/*.h contrib/iostream2/*.cpp \ + contrib/untgz/Makefile contrib/untgz/*.c contrib/untgz/*.w32 \ + contrib/minizip/[CM]*[pe] contrib/minizip/*.[ch] contrib/minizip/*.[td]?? \ + contrib/delphi*/*.??? + +all: example minigzip + +test: all + @LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \ + echo hello world | ./minigzip | ./minigzip -d || \ + echo ' *** minigzip test FAILED ***' ; \ + if ./example; then \ + echo ' *** zlib test OK ***'; \ + else \ + echo ' *** zlib test FAILED ***'; \ + fi + +libz.a: $(OBJS) $(OBJA) + $(AR) $@ $(OBJS) $(OBJA) + -@ ($(RANLIB) $@ || true) >/dev/null 2>&1 + +match.o: match.S + $(CPP) match.S > _match.s + $(CC) -c _match.s + mv _match.o match.o + rm -f _match.s + +$(SHAREDLIB).$(VER): $(OBJS) + $(LDSHARED) -o $@ $(OBJS) + rm -f $(SHAREDLIB) $(SHAREDLIB).1 + ln -s $@ $(SHAREDLIB) + ln -s $@ $(SHAREDLIB).1 + +example: example.o $(LIBS) + $(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS) + +minigzip: minigzip.o $(LIBS) + $(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS) + +install: $(LIBS) + -@if [ ! -d $(includedir) ]; then mkdir $(includedir); fi + -@if [ ! -d $(libdir) ]; then mkdir $(libdir); fi + cp zlib.h zconf.h $(includedir) + chmod 644 $(includedir)/zlib.h $(includedir)/zconf.h + cp $(LIBS) $(libdir) + cd $(libdir); chmod 755 $(LIBS) + -@(cd $(libdir); $(RANLIB) libz.a || true) >/dev/null 2>&1 + cd $(libdir); if test -f $(SHAREDLIB).$(VER); then \ + rm -f $(SHAREDLIB) $(SHAREDLIB).1; \ + ln -s $(SHAREDLIB).$(VER) $(SHAREDLIB); \ + ln -s $(SHAREDLIB).$(VER) $(SHAREDLIB).1; \ + (ldconfig || true) >/dev/null 2>&1; \ + fi +# The ranlib in install is needed on NeXTSTEP which checks file times +# ldconfig is for Linux + +uninstall: + cd $(includedir); \ + v=$(VER); \ + if test -f zlib.h; then \ + v=`sed -n '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`; \ + rm -f zlib.h zconf.h; \ + fi; \ + cd $(libdir); rm -f libz.a; \ + if test -f $(SHAREDLIB).$$v; then \ + rm -f $(SHAREDLIB).$$v $(SHAREDLIB) $(SHAREDLIB).1; \ + fi + +clean: + rm -f *.o *~ example minigzip libz.a libz.so* foo.gz so_locations \ + _match.s maketree + +distclean: clean + +zip: + mv Makefile Makefile~; cp -p Makefile.in Makefile + rm -f test.c ztest*.c contrib/minizip/test.zip + v=`sed -n -e 's/\.//g' -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\ + zip -ul9 zlib$$v $(DISTFILES) + mv Makefile~ Makefile + +dist: + mv Makefile Makefile~; cp -p Makefile.in Makefile + rm -f test.c ztest*.c contrib/minizip/test.zip + d=zlib-`sed -n '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\ + rm -f $$d.tar.gz; \ + if test ! -d ../$$d; then rm -f ../$$d; ln -s `pwd` ../$$d; fi; \ + files=""; \ + for f in $(DISTFILES); do files="$$files $$d/$$f"; done; \ + cd ..; \ + GZIP=-9 $(TAR) chofz $$d/$$d.tar.gz $$files; \ + if test ! -d $$d; then rm -f $$d; fi + mv Makefile~ Makefile + +tags: + etags *.[ch] + +depend: + makedepend -- $(CFLAGS) -- *.[ch] + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +adler32.o: zlib.h zconf.h +compress.o: zlib.h zconf.h +crc32.o: zlib.h zconf.h +deflate.o: deflate.h zutil.h zlib.h zconf.h +example.o: zlib.h zconf.h +gzio.o: zutil.h zlib.h zconf.h +infblock.o: infblock.h inftrees.h infcodes.h infutil.h zutil.h zlib.h zconf.h +infcodes.o: zutil.h zlib.h zconf.h +infcodes.o: inftrees.h infblock.h infcodes.h infutil.h inffast.h +inffast.o: zutil.h zlib.h zconf.h inftrees.h +inffast.o: infblock.h infcodes.h infutil.h inffast.h +inflate.o: zutil.h zlib.h zconf.h infblock.h +inftrees.o: zutil.h zlib.h zconf.h inftrees.h +infutil.o: zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h +minigzip.o: zlib.h zconf.h +trees.o: deflate.h zutil.h zlib.h zconf.h trees.h +uncompr.o: zlib.h zconf.h +zutil.o: zutil.h zlib.h zconf.h diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/Makefile.riscos b/contrib/vmap_extractor_v2/stormlib/zlib/Makefile.riscos new file mode 100644 index 00000000000..d97f4492370 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/Makefile.riscos @@ -0,0 +1,151 @@ +# Project: zlib_1_03 +# Patched for zlib 1.1.2 rw@shadow.org.uk 19980430 +# test works out-of-the-box, installs `somewhere' on demand + +# Toolflags: +CCflags = -c -depend !Depend -IC: -g -throwback -DRISCOS -fah +C++flags = -c -depend !Depend -IC: -throwback +Linkflags = -aif -c++ -o $@ +ObjAsmflags = -throwback -NoCache -depend !Depend +CMHGflags = +LibFileflags = -c -l -o $@ +Squeezeflags = -o $@ + +# change the line below to where _you_ want the library installed. +libdest = lib:zlib + +# Final targets: +@.lib: @.o.adler32 @.o.compress @.o.crc32 @.o.deflate @.o.gzio \ + @.o.infblock @.o.infcodes @.o.inffast @.o.inflate @.o.inftrees @.o.infutil @.o.trees \ + @.o.uncompr @.o.zutil + LibFile $(LibFileflags) @.o.adler32 @.o.compress @.o.crc32 @.o.deflate \ + @.o.gzio @.o.infblock @.o.infcodes @.o.inffast @.o.inflate @.o.inftrees @.o.infutil \ + @.o.trees @.o.uncompr @.o.zutil +test: @.minigzip @.example @.lib + @copy @.lib @.libc A~C~DF~L~N~P~Q~RS~TV + @echo running tests: hang on. + @/@.minigzip -f -9 libc + @/@.minigzip -d libc-gz + @/@.minigzip -f -1 libc + @/@.minigzip -d libc-gz + @/@.minigzip -h -9 libc + @/@.minigzip -d libc-gz + @/@.minigzip -h -1 libc + @/@.minigzip -d libc-gz + @/@.minigzip -9 libc + @/@.minigzip -d libc-gz + @/@.minigzip -1 libc + @/@.minigzip -d libc-gz + @diff @.lib @.libc + @echo that should have reported '@.lib and @.libc identical' if you have diff. + @/@.example @.fred @.fred + @echo that will have given lots of hello!'s. + +@.minigzip: @.o.minigzip @.lib C:o.Stubs + Link $(Linkflags) @.o.minigzip @.lib C:o.Stubs +@.example: @.o.example @.lib C:o.Stubs + Link $(Linkflags) @.o.example @.lib C:o.Stubs + +install: @.lib + cdir $(libdest) + cdir $(libdest).h + @copy @.h.zlib $(libdest).h.zlib A~C~DF~L~N~P~Q~RS~TV + @copy @.h.zconf $(libdest).h.zconf A~C~DF~L~N~P~Q~RS~TV + @copy @.lib $(libdest).lib A~C~DF~L~N~P~Q~RS~TV + @echo okay, installed zlib in $(libdest) + +clean:; remove @.minigzip + remove @.example + remove @.libc + -wipe @.o.* F~r~cV + remove @.fred + +# User-editable dependencies: +.c.o: + cc $(ccflags) -o $@ $< + +# Static dependencies: + +# Dynamic dependencies: +o.example: c.example +o.example: h.zlib +o.example: h.zconf +o.minigzip: c.minigzip +o.minigzip: h.zlib +o.minigzip: h.zconf +o.adler32: c.adler32 +o.adler32: h.zlib +o.adler32: h.zconf +o.compress: c.compress +o.compress: h.zlib +o.compress: h.zconf +o.crc32: c.crc32 +o.crc32: h.zlib +o.crc32: h.zconf +o.deflate: c.deflate +o.deflate: h.deflate +o.deflate: h.zutil +o.deflate: h.zlib +o.deflate: h.zconf +o.gzio: c.gzio +o.gzio: h.zutil +o.gzio: h.zlib +o.gzio: h.zconf +o.infblock: c.infblock +o.infblock: h.zutil +o.infblock: h.zlib +o.infblock: h.zconf +o.infblock: h.infblock +o.infblock: h.inftrees +o.infblock: h.infcodes +o.infblock: h.infutil +o.infcodes: c.infcodes +o.infcodes: h.zutil +o.infcodes: h.zlib +o.infcodes: h.zconf +o.infcodes: h.inftrees +o.infcodes: h.infblock +o.infcodes: h.infcodes +o.infcodes: h.infutil +o.infcodes: h.inffast +o.inffast: c.inffast +o.inffast: h.zutil +o.inffast: h.zlib +o.inffast: h.zconf +o.inffast: h.inftrees +o.inffast: h.infblock +o.inffast: h.infcodes +o.inffast: h.infutil +o.inffast: h.inffast +o.inflate: c.inflate +o.inflate: h.zutil +o.inflate: h.zlib +o.inflate: h.zconf +o.inflate: h.infblock +o.inftrees: c.inftrees +o.inftrees: h.zutil +o.inftrees: h.zlib +o.inftrees: h.zconf +o.inftrees: h.inftrees +o.inftrees: h.inffixed +o.infutil: c.infutil +o.infutil: h.zutil +o.infutil: h.zlib +o.infutil: h.zconf +o.infutil: h.infblock +o.infutil: h.inftrees +o.infutil: h.infcodes +o.infutil: h.infutil +o.trees: c.trees +o.trees: h.deflate +o.trees: h.zutil +o.trees: h.zlib +o.trees: h.zconf +o.trees: h.trees +o.uncompr: c.uncompr +o.uncompr: h.zlib +o.uncompr: h.zconf +o.zutil: c.zutil +o.zutil: h.zutil +o.zutil: h.zlib +o.zutil: h.zconf diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/README b/contrib/vmap_extractor_v2/stormlib/zlib/README new file mode 100644 index 00000000000..29d67146a9b --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/README @@ -0,0 +1,147 @@ +zlib 1.1.4 is a general purpose data compression library. All the code +is thread safe. The data format used by the zlib library +is described by RFCs (Request for Comments) 1950 to 1952 in the files +http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate +format) and rfc1952.txt (gzip format). These documents are also available in +other formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html + +All functions of the compression library are documented in the file zlib.h +(volunteer to write man pages welcome, contact jloup@gzip.org). A usage +example of the library is given in the file example.c which also tests that +the library is working correctly. Another example is given in the file +minigzip.c. The compression library itself is composed of all source files +except example.c and minigzip.c. + +To compile all files and run the test program, follow the instructions +given at the top of Makefile. In short "make test; make install" +should work for most machines. For Unix: "./configure; make test; make install" +For MSDOS, use one of the special makefiles such as Makefile.msc. +For VMS, use Make_vms.com or descrip.mms. + +Questions about zlib should be sent to , or to +Gilles Vollant for the Windows DLL version. +The zlib home page is http://www.zlib.org or http://www.gzip.org/zlib/ +Before reporting a problem, please check this site to verify that +you have the latest version of zlib; otherwise get the latest version and +check whether the problem still exists or not. + +PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html +before asking for help. + +Mark Nelson wrote an article about zlib for the Jan. 1997 +issue of Dr. Dobb's Journal; a copy of the article is available in +http://dogma.net/markn/articles/zlibtool/zlibtool.htm + +The changes made in version 1.1.4 are documented in the file ChangeLog. +The only changes made since 1.1.3 are bug corrections: + +- ZFREE was repeated on same allocation on some error conditions. + This creates a security problem described in + http://www.zlib.org/advisory-2002-03-11.txt +- Returned incorrect error (Z_MEM_ERROR) on some invalid data +- Avoid accesses before window for invalid distances with inflate window + less than 32K. +- force windowBits > 8 to avoid a bug in the encoder for a window size + of 256 bytes. (A complete fix will be available in 1.1.5). + +The beta version 1.1.5beta includes many more changes. A new official +version 1.1.5 will be released as soon as extensive testing has been +completed on it. + + +Unsupported third party contributions are provided in directory "contrib". + +A Java implementation of zlib is available in the Java Development Kit +http://www.javasoft.com/products/JDK/1.1/docs/api/Package-java.util.zip.html +See the zlib home page http://www.zlib.org for details. + +A Perl interface to zlib written by Paul Marquess +is in the CPAN (Comprehensive Perl Archive Network) sites +http://www.cpan.org/modules/by-module/Compress/ + +A Python interface to zlib written by A.M. Kuchling +is available in Python 1.5 and later versions, see +http://www.python.org/doc/lib/module-zlib.html + +A zlib binding for TCL written by Andreas Kupries +is availlable at http://www.westend.com/~kupries/doc/trf/man/man.html + +An experimental package to read and write files in .zip format, +written on top of zlib by Gilles Vollant , is +available at http://www.winimage.com/zLibDll/unzip.html +and also in the contrib/minizip directory of zlib. + + +Notes for some targets: + +- To build a Windows DLL version, include in a DLL project zlib.def, zlib.rc + and all .c files except example.c and minigzip.c; compile with -DZLIB_DLL + The zlib DLL support was initially done by Alessandro Iacopetti and is + now maintained by Gilles Vollant . Check the zlib DLL + home page at http://www.winimage.com/zLibDll + + From Visual Basic, you can call the DLL functions which do not take + a structure as argument: compress, uncompress and all gz* functions. + See contrib/visual-basic.txt for more information, or get + http://www.tcfb.com/dowseware/cmp-z-it.zip + +- For 64-bit Irix, deflate.c must be compiled without any optimization. + With -O, one libpng test fails. The test works in 32 bit mode (with + the -n32 compiler flag). The compiler bug has been reported to SGI. + +- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 + it works when compiled with cc. + +- on Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 + is necessary to get gzprintf working correctly. This is done by configure. + +- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works + with other compilers. Use "make test" to check your compiler. + +- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers. + +- For Turbo C the small model is supported only with reduced performance to + avoid any far allocation; it was tested with -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3 + +- For PalmOs, see http://www.cs.uit.no/~perm/PASTA/pilot/software.html + Per Harald Myrvang + + +Acknowledgments: + + The deflate format used by zlib was defined by Phil Katz. The deflate + and zlib specifications were written by L. Peter Deutsch. Thanks to all the + people who reported problems and suggested various improvements in zlib; + they are too numerous to cite here. + +Copyright notice: + + (C) 1995-2002 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +If you use the zlib library in a product, we would appreciate *not* +receiving lengthy legal documents to sign. The sources are provided +for free but without warranty of any kind. The library has been +entirely written by Jean-loup Gailly and Mark Adler; it does not +include third-party code. + +If you redistribute modified sources, we would appreciate that you include +in the file ChangeLog history information documenting your changes. diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/adler32.c b/contrib/vmap_extractor_v2/stormlib/zlib/adler32.c new file mode 100644 index 00000000000..fae88b65593 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/adler32.c @@ -0,0 +1,48 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zlib.h" + +#define BASE 65521L /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long s1 = adler & 0xffff; + unsigned long s2 = (adler >> 16) & 0xffff; + int k; + + if (buf == Z_NULL) return 1L; + + while (len > 0) { + k = len < NMAX ? len : NMAX; + len -= k; + while (k >= 16) { + DO16(buf); + buf += 16; + k -= 16; + } + if (k != 0) do { + s1 += *buf++; + s2 += s1; + } while (--k); + s1 %= BASE; + s2 %= BASE; + } + return (s2 << 16) | s1; +} diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/algorithm.txt b/contrib/vmap_extractor_v2/stormlib/zlib/algorithm.txt new file mode 100644 index 00000000000..cdc830b5deb --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/algorithm.txt @@ -0,0 +1,213 @@ +1. Compression algorithm (deflate) + +The deflation algorithm used by gzip (also zip and zlib) is a variation of +LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in +the input data. The second occurrence of a string is replaced by a +pointer to the previous string, in the form of a pair (distance, +length). Distances are limited to 32K bytes, and lengths are limited +to 258 bytes. When a string does not occur anywhere in the previous +32K bytes, it is emitted as a sequence of literal bytes. (In this +description, `string' must be taken as an arbitrary sequence of bytes, +and is not restricted to printable characters.) + +Literals or match lengths are compressed with one Huffman tree, and +match distances are compressed with another tree. The trees are stored +in a compact form at the start of each block. The blocks can have any +size (except that the compressed data for one block must fit in +available memory). A block is terminated when deflate() determines that +it would be useful to start another block with fresh trees. (This is +somewhat similar to the behavior of LZW-based _compress_.) + +Duplicated strings are found using a hash table. All input strings of +length 3 are inserted in the hash table. A hash index is computed for +the next 3 bytes. If the hash chain for this index is not empty, all +strings in the chain are compared with the current input string, and +the longest match is selected. + +The hash chains are searched starting with the most recent strings, to +favor small distances and thus take advantage of the Huffman encoding. +The hash chains are singly linked. There are no deletions from the +hash chains, the algorithm simply discards matches that are too old. + +To avoid a worst-case situation, very long hash chains are arbitrarily +truncated at a certain length, determined by a runtime option (level +parameter of deflateInit). So deflate() does not always find the longest +possible match but generally finds a match which is long enough. + +deflate() also defers the selection of matches with a lazy evaluation +mechanism. After a match of length N has been found, deflate() searches for +a longer match at the next input byte. If a longer match is found, the +previous match is truncated to a length of one (thus producing a single +literal byte) and the process of lazy evaluation begins again. Otherwise, +the original match is kept, and the next match search is attempted only N +steps later. + +The lazy match evaluation is also subject to a runtime parameter. If +the current match is long enough, deflate() reduces the search for a longer +match, thus speeding up the whole process. If compression ratio is more +important than speed, deflate() attempts a complete second search even if +the first match is already long enough. + +The lazy match evaluation is not performed for the fastest compression +modes (level parameter 1 to 3). For these fast modes, new strings +are inserted in the hash table only when no match was found, or +when the match is not too long. This degrades the compression ratio +but saves time since there are both fewer insertions and fewer searches. + + +2. Decompression algorithm (inflate) + +2.1 Introduction + +The real question is, given a Huffman tree, how to decode fast. The most +important realization is that shorter codes are much more common than +longer codes, so pay attention to decoding the short codes fast, and let +the long codes take longer to decode. + +inflate() sets up a first level table that covers some number of bits of +input less than the length of longest code. It gets that many bits from the +stream, and looks it up in the table. The table will tell if the next +code is that many bits or less and how many, and if it is, it will tell +the value, else it will point to the next level table for which inflate() +grabs more bits and tries to decode a longer code. + +How many bits to make the first lookup is a tradeoff between the time it +takes to decode and the time it takes to build the table. If building the +table took no time (and if you had infinite memory), then there would only +be a first level table to cover all the way to the longest code. However, +building the table ends up taking a lot longer for more bits since short +codes are replicated many times in such a table. What inflate() does is +simply to make the number of bits in the first table a variable, and set it +for the maximum speed. + +inflate() sends new trees relatively often, so it is possibly set for a +smaller first level table than an application that has only one tree for +all the data. For inflate, which has 286 possible codes for the +literal/length tree, the size of the first table is nine bits. Also the +distance trees have 30 possible values, and the size of the first table is +six bits. Note that for each of those cases, the table ended up one bit +longer than the ``average'' code length, i.e. the code length of an +approximately flat code which would be a little more than eight bits for +286 symbols and a little less than five bits for 30 symbols. It would be +interesting to see if optimizing the first level table for other +applications gave values within a bit or two of the flat code size. + + +2.2 More details on the inflate table lookup + +Ok, you want to know what this cleverly obfuscated inflate tree actually +looks like. You are correct that it's not a Huffman tree. It is simply a +lookup table for the first, let's say, nine bits of a Huffman symbol. The +symbol could be as short as one bit or as long as 15 bits. If a particular +symbol is shorter than nine bits, then that symbol's translation is duplicated +in all those entries that start with that symbol's bits. For example, if the +symbol is four bits, then it's duplicated 32 times in a nine-bit table. If a +symbol is nine bits long, it appears in the table once. + +If the symbol is longer than nine bits, then that entry in the table points +to another similar table for the remaining bits. Again, there are duplicated +entries as needed. The idea is that most of the time the symbol will be short +and there will only be one table look up. (That's whole idea behind data +compression in the first place.) For the less frequent long symbols, there +will be two lookups. If you had a compression method with really long +symbols, you could have as many levels of lookups as is efficient. For +inflate, two is enough. + +So a table entry either points to another table (in which case nine bits in +the above example are gobbled), or it contains the translation for the symbol +and the number of bits to gobble. Then you start again with the next +ungobbled bit. + +You may wonder: why not just have one lookup table for how ever many bits the +longest symbol is? The reason is that if you do that, you end up spending +more time filling in duplicate symbol entries than you do actually decoding. +At least for deflate's output that generates new trees every several 10's of +kbytes. You can imagine that filling in a 2^15 entry table for a 15-bit code +would take too long if you're only decoding several thousand symbols. At the +other extreme, you could make a new table for every bit in the code. In fact, +that's essentially a Huffman tree. But then you spend two much time +traversing the tree while decoding, even for short symbols. + +So the number of bits for the first lookup table is a trade of the time to +fill out the table vs. the time spent looking at the second level and above of +the table. + +Here is an example, scaled down: + +The code being decoded, with 10 symbols, from 1 to 6 bits long: + +A: 0 +B: 10 +C: 1100 +D: 11010 +E: 11011 +F: 11100 +G: 11101 +H: 11110 +I: 111110 +J: 111111 + +Let's make the first table three bits long (eight entries): + +000: A,1 +001: A,1 +010: A,1 +011: A,1 +100: B,2 +101: B,2 +110: -> table X (gobble 3 bits) +111: -> table Y (gobble 3 bits) + +Each entry is what the bits decode to and how many bits that is, i.e. how +many bits to gobble. Or the entry points to another table, with the number of +bits to gobble implicit in the size of the table. + +Table X is two bits long since the longest code starting with 110 is five bits +long: + +00: C,1 +01: C,1 +10: D,2 +11: E,2 + +Table Y is three bits long since the longest code starting with 111 is six +bits long: + +000: F,2 +001: F,2 +010: G,2 +011: G,2 +100: H,2 +101: H,2 +110: I,3 +111: J,3 + +So what we have here are three tables with a total of 20 entries that had to +be constructed. That's compared to 64 entries for a single table. Or +compared to 16 entries for a Huffman tree (six two entry tables and one four +entry table). Assuming that the code ideally represents the probability of +the symbols, it takes on the average 1.25 lookups per symbol. That's compared +to one lookup for the single table, or 1.66 lookups per symbol for the +Huffman tree. + +There, I think that gives you a picture of what's going on. For inflate, the +meaning of a particular symbol is often more than just a letter. It can be a +byte (a "literal"), or it can be either a length or a distance which +indicates a base value and a number of bits to fetch after the code that is +added to the base value. Or it might be the special end-of-block code. The +data structures created in inftrees.c try to encode all that information +compactly in the tables. + + +Jean-loup Gailly Mark Adler +jloup@gzip.org madler@alumni.caltech.edu + + +References: + +[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data +Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3, +pp. 337-343. + +``DEFLATE Compressed Data Format Specification'' available in +ftp://ds.internic.net/rfc/rfc1951.txt diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/amiga/Makefile.pup b/contrib/vmap_extractor_v2/stormlib/zlib/amiga/Makefile.pup new file mode 100644 index 00000000000..6cfad1dc04a --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/amiga/Makefile.pup @@ -0,0 +1,66 @@ +# Amiga powerUP (TM) Makefile +# makefile for libpng and SAS C V6.58/7.00 PPC compiler +# Copyright (C) 1998 by Andreas R. Kleinert + +CC = scppc +CFLAGS = NOSTKCHK NOSINT OPTIMIZE OPTGO OPTPEEP OPTINLOCAL OPTINL \ + OPTLOOP OPTRDEP=8 OPTDEP=8 OPTCOMP=8 +LIBNAME = libzip.a +AR = ppc-amigaos-ar +AR_FLAGS = cr +RANLIB = ppc-amigaos-ranlib +LDFLAGS = -r -o +LDLIBS = LIB:scppc.a +LN = ppc-amigaos-ld +RM = delete quiet + +OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ + zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o + +TEST_OBJS = example.o minigzip.o + +all: example minigzip + +test: all + example + echo hello world | minigzip | minigzip -d + +$(LIBNAME): $(OBJS) + $(AR) $(AR_FLAGS) $@ $(OBJS) + $(RANLIB) $@ + +example: example.o $(LIBNAME) + $(LN) $(LDFLAGS) example LIB:c_ppc.o example.o $(LIBNAME) $(LDLIBS) LIB:end.o + +minigzip: minigzip.o $(LIBNAME) + $(LN) $(LDFLAGS) minigzip LIB:c_ppc.o minigzip.o $(LIBNAME) $(LDLIBS) LIB:end.o + +clean: + $(RM) *.o example minigzip $(LIBNAME) foo.gz + +zip: + zip -ul9 zlib README ChangeLog Makefile Make????.??? Makefile.?? \ + descrip.mms *.[ch] + +tgz: + cd ..; tar cfz zlib/zlib.tgz zlib/README zlib/ChangeLog zlib/Makefile \ + zlib/Make????.??? zlib/Makefile.?? zlib/descrip.mms zlib/*.[ch] + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +adler32.o: zutil.h zlib.h zconf.h +compress.o: zlib.h zconf.h +crc32.o: zutil.h zlib.h zconf.h +deflate.o: deflate.h zutil.h zlib.h zconf.h +example.o: zlib.h zconf.h +gzio.o: zutil.h zlib.h zconf.h +infblock.o: zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h +infcodes.o: zutil.h zlib.h zconf.h inftrees.h infutil.h infcodes.h inffast.h +inffast.o: zutil.h zlib.h zconf.h inftrees.h infutil.h inffast.h +inflate.o: zutil.h zlib.h zconf.h infblock.h +inftrees.o: zutil.h zlib.h zconf.h inftrees.h +infutil.o: zutil.h zlib.h zconf.h inftrees.h infutil.h +minigzip.o: zlib.h zconf.h +trees.o: deflate.h zutil.h zlib.h zconf.h +uncompr.o: zlib.h zconf.h +zutil.o: zutil.h zlib.h zconf.h diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/amiga/Makefile.sas b/contrib/vmap_extractor_v2/stormlib/zlib/amiga/Makefile.sas new file mode 100644 index 00000000000..5323e821708 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/amiga/Makefile.sas @@ -0,0 +1,64 @@ +# SMakefile for zlib +# Modified from the standard UNIX Makefile Copyright Jean-loup Gailly +# Osma Ahvenlampi +# Amiga, SAS/C 6.56 & Smake + +CC=sc +CFLAGS=OPT +#CFLAGS=OPT CPU=68030 +#CFLAGS=DEBUG=LINE +LDFLAGS=LIB z.lib + +SCOPTIONS=OPTSCHED OPTINLINE OPTALIAS OPTTIME OPTINLOCAL STRMERGE \ + NOICONS PARMS=BOTH NOSTACKCHECK UTILLIB NOVERSION ERRORREXX + +OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ + zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o + +TEST_OBJS = example.o minigzip.o + +all: SCOPTIONS example minigzip + +test: all + `cd`/example + echo hello world | minigzip | minigzip -d + +install: z.lib + copy zlib.h zconf.h INCLUDE: clone + copy z.lib LIB: clone + +z.lib: $(OBJS) + oml z.lib r $(OBJS) + +example: example.o z.lib + $(CC) $(CFLAGS) LINK TO $@ example.o $(LDFLAGS) + +minigzip: minigzip.o z.lib + $(CC) $(CFLAGS) LINK TO $@ minigzip.o $(LDFLAGS) + +clean: + -delete force quiet *.o example minigzip z.lib foo.gz *.lnk SCOPTIONS + +SCOPTIONS: Smakefile + copy to $@ 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; +#endif + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = deflateInit(&stream, level); + if (err != Z_OK) return err; + + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + deflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = deflateEnd(&stream); + return err; +} + +/* =========================================================================== + */ +int ZEXPORT compress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/configure b/contrib/vmap_extractor_v2/stormlib/zlib/configure new file mode 100644 index 00000000000..e8942359bc1 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/configure @@ -0,0 +1,212 @@ +#!/bin/sh +# configure script for zlib. This script is needed only if +# you wish to build a shared library and your system supports them, +# of if you need special compiler, flags or install directory. +# Otherwise, you can just use directly "make test; make install" +# +# To create a shared library, use "configure --shared"; by default a static +# library is created. If the primitive shared library support provided here +# does not work, use ftp://prep.ai.mit.edu/pub/gnu/libtool-*.tar.gz +# +# To impose specific compiler or flags or install directory, use for example: +# prefix=$HOME CC=cc CFLAGS="-O4" ./configure +# or for csh/tcsh users: +# (setenv prefix $HOME; setenv CC cc; setenv CFLAGS "-O4"; ./configure) +# LDSHARED is the command to be used to create a shared library + +# Incorrect settings of CC or CFLAGS may prevent creating a shared library. +# If you have problems, try without defining CC and CFLAGS before reporting +# an error. + +LIBS=libz.a +SHAREDLIB=libz.so +VER=`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h` +AR=${AR-"ar rc"} +RANLIB=${RANLIB-"ranlib"} +prefix=${prefix-/usr/local} +exec_prefix=${exec_prefix-'${prefix}'} +libdir=${libdir-'${exec_prefix}/lib'} +includedir=${includedir-'${prefix}/include'} +shared_ext='.so' +shared=0 +gcc=0 +old_cc="$CC" +old_cflags="$CFLAGS" + +while test $# -ge 1 +do +case "$1" in + -h* | --h*) + echo 'usage:' + echo ' configure [--shared] [--prefix=PREFIX] [--exec_prefix=EXPREFIX]' + echo ' [--libdir=LIBDIR] [--includedir=INCLUDEDIR]' + exit 0;; + -p*=* | --p*=*) prefix=`echo $1 | sed 's/[-a-z_]*=//'`; shift;; + -e*=* | --e*=*) exec_prefix=`echo $1 | sed 's/[-a-z_]*=//'`; shift;; + -l*=* | --libdir=*) libdir=`echo $1 | sed 's/[-a-z_]*=//'`; shift;; + -i*=* | --includedir=*) includedir=`echo $1 | sed 's/[-a-z_]*=//'`;shift;; + -p* | --p*) prefix="$2"; shift; shift;; + -e* | --e*) exec_prefix="$2"; shift; shift;; + -l* | --l*) libdir="$2"; shift; shift;; + -i* | --i*) includedir="$2"; shift; shift;; + -s* | --s*) shared=1; shift;; + esac +done + +test=ztest$$ +cat > $test.c </dev/null; then + CC="$cc" + SFLAGS=${CFLAGS-"-fPIC -O3"} + CFLAGS="$cflags" + case `(uname -s || echo unknown) 2>/dev/null` in + Linux | linux) LDSHARED=${LDSHARED-"gcc -shared -Wl,-soname,libz.so.1"};; + *) LDSHARED=${LDSHARED-"gcc -shared"};; + esac +else + # find system name and corresponding cc options + CC=${CC-cc} + case `(uname -sr || echo unknown) 2>/dev/null` in + HP-UX*) SFLAGS=${CFLAGS-"-O +z"} + CFLAGS=${CFLAGS-"-O"} +# LDSHARED=${LDSHARED-"ld -b +vnocompatwarnings"} + LDSHARED=${LDSHARED-"ld -b"} + shared_ext='.sl' + SHAREDLIB='libz.sl';; + IRIX*) SFLAGS=${CFLAGS-"-ansi -O2 -rpath ."} + CFLAGS=${CFLAGS-"-ansi -O2"} + LDSHARED=${LDSHARED-"cc -shared"};; + OSF1\ V4*) SFLAGS=${CFLAGS-"-O -std1"} + CFLAGS=${CFLAGS-"-O -std1"} + LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,$SHAREDLIB -Wl,-msym -Wl,-rpath,$(libdir) -Wl,-set_version,${VER}:1.0"};; + OSF1*) SFLAGS=${CFLAGS-"-O -std1"} + CFLAGS=${CFLAGS-"-O -std1"} + LDSHARED=${LDSHARED-"cc -shared"};; + QNX*) SFLAGS=${CFLAGS-"-4 -O"} + CFLAGS=${CFLAGS-"-4 -O"} + LDSHARED=${LDSHARED-"cc"} + RANLIB=${RANLIB-"true"} + AR="cc -A";; + SCO_SV\ 3.2*) SFLAGS=${CFLAGS-"-O3 -dy -KPIC "} + CFLAGS=${CFLAGS-"-O3"} + LDSHARED=${LDSHARED-"cc -dy -KPIC -G"};; + SunOS\ 5*) SFLAGS=${CFLAGS-"-fast -xcg89 -KPIC -R."} + CFLAGS=${CFLAGS-"-fast -xcg89"} + LDSHARED=${LDSHARED-"cc -G"};; + SunOS\ 4*) SFLAGS=${CFLAGS-"-O2 -PIC"} + CFLAGS=${CFLAGS-"-O2"} + LDSHARED=${LDSHARED-"ld"};; + UNIX_System_V\ 4.2.0) + SFLAGS=${CFLAGS-"-KPIC -O"} + CFLAGS=${CFLAGS-"-O"} + LDSHARED=${LDSHARED-"cc -G"};; + UNIX_SV\ 4.2MP) + SFLAGS=${CFLAGS-"-Kconform_pic -O"} + CFLAGS=${CFLAGS-"-O"} + LDSHARED=${LDSHARED-"cc -G"};; + # send working options for other systems to support@gzip.org + *) SFLAGS=${CFLAGS-"-O"} + CFLAGS=${CFLAGS-"-O"} + LDSHARED=${LDSHARED-"cc -shared"};; + esac +fi + +if test $shared -eq 1; then + echo Checking for shared library support... + # we must test in two steps (cc then ld), required at least on SunOS 4.x + if test "`($CC -c $SFLAGS $test.c) 2>&1`" = "" && + test "`($LDSHARED -o $test$shared_ext $test.o) 2>&1`" = ""; then + CFLAGS="$SFLAGS" + LIBS="$SHAREDLIB.$VER" + echo Building shared library $SHAREDLIB.$VER with $CC. + elif test -z "$old_cc" -a -z "$old_cflags"; then + echo No shared library suppport. + shared=0; + else + echo 'No shared library suppport; try without defining CC and CFLAGS' + shared=0; + fi +fi +if test $shared -eq 0; then + LDSHARED="$CC" + echo Building static library $LIBS version $VER with $CC. +fi + +cat > $test.c < +int main() { return 0; } +EOF +if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then + CFLAGS="$CFLAGS -DHAVE_UNISTD_H" + echo "Checking for unistd.h... Yes." +else + echo "Checking for unistd.h... No." +fi + +cat > $test.c < +int main() { return 0; } +EOF +if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then + echo "Checking for errno.h... Yes." +else + echo "Checking for errno.h... No." + CFLAGS="$CFLAGS -DNO_ERRNO_H" +fi + +cat > $test.c < +#include +#include +caddr_t hello() { + return mmap((caddr_t)0, (off_t)0, PROT_READ, MAP_SHARED, 0, (off_t)0); +} +EOF +if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then + CFLAGS="$CFLAGS -DUSE_MMAP" + echo Checking for mmap support... Yes. +else + echo Checking for mmap support... No. +fi + +CPP=${CPP-"$CC -E"} +case $CFLAGS in + *ASMV*) + if test "`nm $test.o | grep _hello`" = ""; then + CPP="$CPP -DNO_UNDERLINE" + echo Checking for underline in external names... No. + else + echo Checking for underline in external names... Yes. + fi;; +esac + +rm -f $test.[co] $test$shared_ext + +# udpate Makefile +sed < Makefile.in " +/^CC *=/s%=.*%=$CC% +/^CFLAGS *=/s%=.*%=$CFLAGS% +/^CPP *=/s%=.*%=$CPP% +/^LDSHARED *=/s%=.*%=$LDSHARED% +/^LIBS *=/s%=.*%=$LIBS% +/^SHAREDLIB *=/s%=.*%=$SHAREDLIB% +/^AR *=/s%=.*%=$AR% +/^RANLIB *=/s%=.*%=$RANLIB% +/^VER *=/s%=.*%=$VER% +/^prefix *=/s%=.*%=$prefix% +/^exec_prefix *=/s%=.*%=$exec_prefix% +/^libdir *=/s%=.*%=$libdir% +/^includedir *=/s%=.*%=$includedir% +" > Makefile diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/README.contrib b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/README.contrib new file mode 100644 index 00000000000..7ad191cf598 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/README.contrib @@ -0,0 +1,34 @@ +All files under this contrib directory are UNSUPPORTED. There were +provided by users of zlib and were not tested by the authors of zlib. +Use at your own risk. Please contact the authors of the contributions +for help about these, not the zlib authors. Thanks. + + +asm386/ by Gilles Vollant + 386 asm code replacing longest_match(), for Visual C++ 4.2 and ML 6.11c + +asm586/ and asm686/ by Brian Raiter + asm code for Pentium and Pentium Pro + See http://www.muppetlabs.com/~breadbox/software/assembly.html + +delphi/ by Bob Dellaca + Support for Delphi + +delphi2/ by Davide Moretti + Another support for C++Builder and Delphi + +minizip/ by Gilles Vollant + Mini zip and unzip based on zlib + See http://www.winimage.com/zLibDll/unzip.html + +iostream/ by Kevin Ruland + A C++ I/O streams interface to the zlib gz* functions + +iostream2/ by Tyge Løvset + Another C++ I/O streams interface + +untgz/ by "Pedro A. Aranda Guti\irrez" + A very simple tar.gz file extractor using zlib + +visual-basic.txt by Carlos Rios + How to use compress(), uncompress() and the gz* functions from VB. diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/asm386/gvmat32.asm b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/asm386/gvmat32.asm new file mode 100644 index 00000000000..28d527f47f8 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/asm386/gvmat32.asm @@ -0,0 +1,559 @@ +; +; gvmat32.asm -- Asm portion of the optimized longest_match for 32 bits x86 +; Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant. +; File written by Gilles Vollant, by modifiying the longest_match +; from Jean-loup Gailly in deflate.c +; It need wmask == 0x7fff +; (assembly code is faster with a fixed wmask) +; +; For Visual C++ 4.2 and ML 6.11c (version in directory \MASM611C of Win95 DDK) +; I compile with : "ml /coff /Zi /c gvmat32.asm" +; + +;uInt longest_match_7fff(s, cur_match) +; deflate_state *s; +; IPos cur_match; /* current match */ + + NbStack equ 76 + cur_match equ dword ptr[esp+NbStack-0] + str_s equ dword ptr[esp+NbStack-4] +; 5 dword on top (ret,ebp,esi,edi,ebx) + adrret equ dword ptr[esp+NbStack-8] + pushebp equ dword ptr[esp+NbStack-12] + pushedi equ dword ptr[esp+NbStack-16] + pushesi equ dword ptr[esp+NbStack-20] + pushebx equ dword ptr[esp+NbStack-24] + + chain_length equ dword ptr [esp+NbStack-28] + limit equ dword ptr [esp+NbStack-32] + best_len equ dword ptr [esp+NbStack-36] + window equ dword ptr [esp+NbStack-40] + prev equ dword ptr [esp+NbStack-44] + scan_start equ word ptr [esp+NbStack-48] + wmask equ dword ptr [esp+NbStack-52] + match_start_ptr equ dword ptr [esp+NbStack-56] + nice_match equ dword ptr [esp+NbStack-60] + scan equ dword ptr [esp+NbStack-64] + + windowlen equ dword ptr [esp+NbStack-68] + match_start equ dword ptr [esp+NbStack-72] + strend equ dword ptr [esp+NbStack-76] + NbStackAdd equ (NbStack-24) + + .386p + + name gvmatch + .MODEL FLAT + + + +; all the +4 offsets are due to the addition of pending_buf_size (in zlib +; in the deflate_state structure since the asm code was first written +; (if you compile with zlib 1.0.4 or older, remove the +4). +; Note : these value are good with a 8 bytes boundary pack structure + dep_chain_length equ 70h+4 + dep_window equ 2ch+4 + dep_strstart equ 60h+4 + dep_prev_length equ 6ch+4 + dep_nice_match equ 84h+4 + dep_w_size equ 20h+4 + dep_prev equ 34h+4 + dep_w_mask equ 28h+4 + dep_good_match equ 80h+4 + dep_match_start equ 64h+4 + dep_lookahead equ 68h+4 + + +_TEXT segment + +IFDEF NOUNDERLINE + public longest_match_7fff +; public match_init +ELSE + public _longest_match_7fff +; public _match_init +ENDIF + + MAX_MATCH equ 258 + MIN_MATCH equ 3 + MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1) + + + +IFDEF NOUNDERLINE +;match_init proc near +; ret +;match_init endp +ELSE +;_match_init proc near +; ret +;_match_init endp +ENDIF + + +IFDEF NOUNDERLINE +longest_match_7fff proc near +ELSE +_longest_match_7fff proc near +ENDIF + + mov edx,[esp+4] + + + + push ebp + push edi + push esi + push ebx + + sub esp,NbStackAdd + +; initialize or check the variables used in match.asm. + mov ebp,edx + +; chain_length = s->max_chain_length +; if (prev_length>=good_match) chain_length >>= 2 + mov edx,[ebp+dep_chain_length] + mov ebx,[ebp+dep_prev_length] + cmp [ebp+dep_good_match],ebx + ja noshr + shr edx,2 +noshr: +; we increment chain_length because in the asm, the --chain_lenght is in the beginning of the loop + inc edx + mov edi,[ebp+dep_nice_match] + mov chain_length,edx + mov eax,[ebp+dep_lookahead] + cmp eax,edi +; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + jae nolookaheadnicematch + mov edi,eax +nolookaheadnicematch: +; best_len = s->prev_length + mov best_len,ebx + +; window = s->window + mov esi,[ebp+dep_window] + mov ecx,[ebp+dep_strstart] + mov window,esi + + mov nice_match,edi +; scan = window + strstart + add esi,ecx + mov scan,esi +; dx = *window + mov dx,word ptr [esi] +; bx = *(window+best_len-1) + mov bx,word ptr [esi+ebx-1] + add esi,MAX_MATCH-1 +; scan_start = *scan + mov scan_start,dx +; strend = scan + MAX_MATCH-1 + mov strend,esi +; bx = scan_end = *(window+best_len-1) + +; IPos limit = s->strstart > (IPos)MAX_DIST(s) ? +; s->strstart - (IPos)MAX_DIST(s) : NIL; + + mov esi,[ebp+dep_w_size] + sub esi,MIN_LOOKAHEAD +; here esi = MAX_DIST(s) + sub ecx,esi + ja nodist + xor ecx,ecx +nodist: + mov limit,ecx + +; prev = s->prev + mov edx,[ebp+dep_prev] + mov prev,edx + +; + mov edx,dword ptr [ebp+dep_match_start] + mov bp,scan_start + mov eax,cur_match + mov match_start,edx + + mov edx,window + mov edi,edx + add edi,best_len + mov esi,prev + dec edi +; windowlen = window + best_len -1 + mov windowlen,edi + + jmp beginloop2 + align 4 + +; here, in the loop +; eax = ax = cur_match +; ecx = limit +; bx = scan_end +; bp = scan_start +; edi = windowlen (window + best_len -1) +; esi = prev + + +;// here; chain_length <=16 +normalbeg0add16: + add chain_length,16 + jz exitloop +normalbeg0: + cmp word ptr[edi+eax],bx + je normalbeg2noroll +rcontlabnoroll: +; cur_match = prev[cur_match & wmask] + and eax,7fffh + mov ax,word ptr[esi+eax*2] +; if cur_match > limit, go to exitloop + cmp ecx,eax + jnb exitloop +; if --chain_length != 0, go to exitloop + dec chain_length + jnz normalbeg0 + jmp exitloop + +normalbeg2noroll: +; if (scan_start==*(cur_match+window)) goto normalbeg2 + cmp bp,word ptr[edx+eax] + jne rcontlabnoroll + jmp normalbeg2 + +contloop3: + mov edi,windowlen + +; cur_match = prev[cur_match & wmask] + and eax,7fffh + mov ax,word ptr[esi+eax*2] +; if cur_match > limit, go to exitloop + cmp ecx,eax +jnbexitloopshort1: + jnb exitloop +; if --chain_length != 0, go to exitloop + + +; begin the main loop +beginloop2: + sub chain_length,16+1 +; if chain_length <=16, don't use the unrolled loop + jna normalbeg0add16 + +do16: + cmp word ptr[edi+eax],bx + je normalbeg2dc0 + +maccn MACRO lab + and eax,7fffh + mov ax,word ptr[esi+eax*2] + cmp ecx,eax + jnb exitloop + cmp word ptr[edi+eax],bx + je lab + ENDM + +rcontloop0: + maccn normalbeg2dc1 + +rcontloop1: + maccn normalbeg2dc2 + +rcontloop2: + maccn normalbeg2dc3 + +rcontloop3: + maccn normalbeg2dc4 + +rcontloop4: + maccn normalbeg2dc5 + +rcontloop5: + maccn normalbeg2dc6 + +rcontloop6: + maccn normalbeg2dc7 + +rcontloop7: + maccn normalbeg2dc8 + +rcontloop8: + maccn normalbeg2dc9 + +rcontloop9: + maccn normalbeg2dc10 + +rcontloop10: + maccn short normalbeg2dc11 + +rcontloop11: + maccn short normalbeg2dc12 + +rcontloop12: + maccn short normalbeg2dc13 + +rcontloop13: + maccn short normalbeg2dc14 + +rcontloop14: + maccn short normalbeg2dc15 + +rcontloop15: + and eax,7fffh + mov ax,word ptr[esi+eax*2] + cmp ecx,eax + jnb exitloop + + sub chain_length,16 + ja do16 + jmp normalbeg0add16 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +normbeg MACRO rcontlab,valsub +; if we are here, we know that *(match+best_len-1) == scan_end + cmp bp,word ptr[edx+eax] +; if (match != scan_start) goto rcontlab + jne rcontlab +; calculate the good chain_length, and we'll compare scan and match string + add chain_length,16-valsub + jmp iseq + ENDM + + +normalbeg2dc11: + normbeg rcontloop11,11 + +normalbeg2dc12: + normbeg short rcontloop12,12 + +normalbeg2dc13: + normbeg short rcontloop13,13 + +normalbeg2dc14: + normbeg short rcontloop14,14 + +normalbeg2dc15: + normbeg short rcontloop15,15 + +normalbeg2dc10: + normbeg rcontloop10,10 + +normalbeg2dc9: + normbeg rcontloop9,9 + +normalbeg2dc8: + normbeg rcontloop8,8 + +normalbeg2dc7: + normbeg rcontloop7,7 + +normalbeg2dc6: + normbeg rcontloop6,6 + +normalbeg2dc5: + normbeg rcontloop5,5 + +normalbeg2dc4: + normbeg rcontloop4,4 + +normalbeg2dc3: + normbeg rcontloop3,3 + +normalbeg2dc2: + normbeg rcontloop2,2 + +normalbeg2dc1: + normbeg rcontloop1,1 + +normalbeg2dc0: + normbeg rcontloop0,0 + + +; we go in normalbeg2 because *(ushf*)(match+best_len-1) == scan_end + +normalbeg2: + mov edi,window + + cmp bp,word ptr[edi+eax] + jne contloop3 ; if *(ushf*)match != scan_start, continue + +iseq: +; if we are here, we know that *(match+best_len-1) == scan_end +; and (match == scan_start) + + mov edi,edx + mov esi,scan ; esi = scan + add edi,eax ; edi = window + cur_match = match + + mov edx,[esi+3] ; compare manually dword at match+3 + xor edx,[edi+3] ; and scan +3 + + jz begincompare ; if equal, go to long compare + +; we will determine the unmatch byte and calculate len (in esi) + or dl,dl + je eq1rr + mov esi,3 + jmp trfinval +eq1rr: + or dx,dx + je eq1 + + mov esi,4 + jmp trfinval +eq1: + and edx,0ffffffh + jz eq11 + mov esi,5 + jmp trfinval +eq11: + mov esi,6 + jmp trfinval + +begincompare: + ; here we now scan and match begin same + add edi,6 + add esi,6 + mov ecx,(MAX_MATCH-(2+4))/4 ; scan for at most MAX_MATCH bytes + repe cmpsd ; loop until mismatch + + je trfin ; go to trfin if not unmatch +; we determine the unmatch byte + sub esi,4 + mov edx,[edi-4] + xor edx,[esi] + + or dl,dl + jnz trfin + inc esi + + or dx,dx + jnz trfin + inc esi + + and edx,0ffffffh + jnz trfin + inc esi + +trfin: + sub esi,scan ; esi = len +trfinval: +; here we have finised compare, and esi contain len of equal string + cmp esi,best_len ; if len > best_len, go newbestlen + ja short newbestlen +; now we restore edx, ecx and esi, for the big loop + mov esi,prev + mov ecx,limit + mov edx,window + jmp contloop3 + +newbestlen: + mov best_len,esi ; len become best_len + + mov match_start,eax ; save new position as match_start + cmp esi,nice_match ; if best_len >= nice_match, exit + jae exitloop + mov ecx,scan + mov edx,window ; restore edx=window + add ecx,esi + add esi,edx + + dec esi + mov windowlen,esi ; windowlen = window + best_len-1 + mov bx,[ecx-1] ; bx = *(scan+best_len-1) = scan_end + +; now we restore ecx and esi, for the big loop : + mov esi,prev + mov ecx,limit + jmp contloop3 + +exitloop: +; exit : s->match_start=match_start + mov ebx,match_start + mov ebp,str_s + mov ecx,best_len + mov dword ptr [ebp+dep_match_start],ebx + mov eax,dword ptr [ebp+dep_lookahead] + cmp ecx,eax + ja minexlo + mov eax,ecx +minexlo: +; return min(best_len,s->lookahead) + +; restore stack and register ebx,esi,edi,ebp + add esp,NbStackAdd + + pop ebx + pop esi + pop edi + pop ebp + ret +InfoAuthor: +; please don't remove this string ! +; Your are free use gvmat32 in any fre or commercial apps if you don't remove the string in the binary! + db 0dh,0ah,"GVMat32 optimised assembly code written 1996-98 by Gilles Vollant",0dh,0ah + + + +IFDEF NOUNDERLINE +longest_match_7fff endp +ELSE +_longest_match_7fff endp +ENDIF + + +IFDEF NOUNDERLINE +cpudetect32 proc near +ELSE +_cpudetect32 proc near +ENDIF + + + pushfd ; push original EFLAGS + pop eax ; get original EFLAGS + mov ecx, eax ; save original EFLAGS + xor eax, 40000h ; flip AC bit in EFLAGS + push eax ; save new EFLAGS value on stack + popfd ; replace current EFLAGS value + pushfd ; get new EFLAGS + pop eax ; store new EFLAGS in EAX + xor eax, ecx ; can’t toggle AC bit, processor=80386 + jz end_cpu_is_386 ; jump if 80386 processor + push ecx + popfd ; restore AC bit in EFLAGS first + + pushfd + pushfd + pop ecx + + mov eax, ecx ; get original EFLAGS + xor eax, 200000h ; flip ID bit in EFLAGS + push eax ; save new EFLAGS value on stack + popfd ; replace current EFLAGS value + pushfd ; get new EFLAGS + pop eax ; store new EFLAGS in EAX + popfd ; restore original EFLAGS + xor eax, ecx ; can’t toggle ID bit, + je is_old_486 ; processor=old + + mov eax,1 + db 0fh,0a2h ;CPUID + +exitcpudetect: + ret + +end_cpu_is_386: + mov eax,0300h + jmp exitcpudetect + +is_old_486: + mov eax,0400h + jmp exitcpudetect + +IFDEF NOUNDERLINE +cpudetect32 endp +ELSE +_cpudetect32 endp +ENDIF + +_TEXT ends +end diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/asm386/gvmat32c.c b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/asm386/gvmat32c.c new file mode 100644 index 00000000000..d853bb7ce8a --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/asm386/gvmat32c.c @@ -0,0 +1,200 @@ +/* gvmat32.c -- C portion of the optimized longest_match for 32 bits x86 + * Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant. + * File written by Gilles Vollant, by modifiying the longest_match + * from Jean-loup Gailly in deflate.c + * it prepare all parameters and call the assembly longest_match_gvasm + * longest_match execute standard C code is wmask != 0x7fff + * (assembly code is faster with a fixed wmask) + * + */ + +#include "deflate.h" + +#undef FAR +#include + +#ifdef ASMV +#define NIL 0 + +#define UNALIGNED_OK + + +/* if your C compiler don't add underline before function name, + define ADD_UNDERLINE_ASMFUNC */ +#ifdef ADD_UNDERLINE_ASMFUNC +#define longest_match_7fff _longest_match_7fff +#endif + + + +void match_init() +{ +} + +unsigned long cpudetect32(); + +uInt longest_match_c( + deflate_state *s, + IPos cur_match); /* current match */ + + +uInt longest_match_7fff( + deflate_state *s, + IPos cur_match); /* current match */ + +uInt longest_match( + deflate_state *s, + IPos cur_match) /* current match */ +{ + static uInt iIsPPro=2; + + if ((s->w_mask == 0x7fff) && (iIsPPro==0)) + return longest_match_7fff(s,cur_match); + + if (iIsPPro==2) + iIsPPro = (((cpudetect32()/0x100)&0xf)>=6) ? 1 : 0; + + return longest_match_c(s,cur_match); +} + + + +uInt longest_match_c(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2: + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} + +#endif /* ASMV */ diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/asm386/mkgvmt32.bat b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/asm386/mkgvmt32.bat new file mode 100644 index 00000000000..6c5ffd7a024 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/asm386/mkgvmt32.bat @@ -0,0 +1 @@ +c:\masm611\bin\ml /coff /Zi /c /Flgvmat32.lst gvmat32.asm diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/asm386/zlibvc.def b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/asm386/zlibvc.def new file mode 100644 index 00000000000..7e9d60d55d9 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/asm386/zlibvc.def @@ -0,0 +1,74 @@ +LIBRARY "zlib" + +DESCRIPTION '"""zlib data compression library"""' + + +VERSION 1.11 + + +HEAPSIZE 1048576,8192 + +EXPORTS + adler32 @1 + compress @2 + crc32 @3 + deflate @4 + deflateCopy @5 + deflateEnd @6 + deflateInit2_ @7 + deflateInit_ @8 + deflateParams @9 + deflateReset @10 + deflateSetDictionary @11 + gzclose @12 + gzdopen @13 + gzerror @14 + gzflush @15 + gzopen @16 + gzread @17 + gzwrite @18 + inflate @19 + inflateEnd @20 + inflateInit2_ @21 + inflateInit_ @22 + inflateReset @23 + inflateSetDictionary @24 + inflateSync @25 + uncompress @26 + zlibVersion @27 + gzprintf @28 + gzputc @29 + gzgetc @30 + gzseek @31 + gzrewind @32 + gztell @33 + gzeof @34 + gzsetparams @35 + zError @36 + inflateSyncPoint @37 + get_crc_table @38 + compress2 @39 + gzputs @40 + gzgets @41 + + unzOpen @61 + unzClose @62 + unzGetGlobalInfo @63 + unzGetCurrentFileInfo @64 + unzGoToFirstFile @65 + unzGoToNextFile @66 + unzOpenCurrentFile @67 + unzReadCurrentFile @68 + unztell @70 + unzeof @71 + unzCloseCurrentFile @72 + unzGetGlobalComment @73 + unzStringFileNameCompare @74 + unzLocateFile @75 + unzGetLocalExtrafield @76 + + zipOpen @80 + zipOpenNewFileInZip @81 + zipWriteInFileInZip @82 + zipCloseFileInZip @83 + zipClose @84 diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/asm386/zlibvc.dsp b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/asm386/zlibvc.dsp new file mode 100644 index 00000000000..a70d4d4a6b0 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/asm386/zlibvc.dsp @@ -0,0 +1,651 @@ +# Microsoft Developer Studio Project File - Name="zlibvc" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 +# TARGTYPE "Win32 (ALPHA) Dynamic-Link Library" 0x0602 + +CFG=zlibvc - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "zlibvc.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "zlibvc.mak" CFG="zlibvc - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "zlibvc - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "zlibvc - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "zlibvc - Win32 ReleaseAxp" (based on\ + "Win32 (ALPHA) Dynamic-Link Library") +!MESSAGE "zlibvc - Win32 ReleaseWithoutAsm" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "zlibvc - Win32 ReleaseWithoutCrtdll" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir ".\Release" +# PROP BASE Intermediate_Dir ".\Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir ".\Release" +# PROP Intermediate_Dir ".\Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +CPP=cl.exe +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /D "ASMV" /FAcs /FR /FD /c +# SUBTRACT CPP /YX +MTL=midl.exe +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 +# ADD LINK32 gvmat32.obj kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\Release\zlib.dll" +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir ".\Debug" +# PROP BASE Intermediate_Dir ".\Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir ".\Debug" +# PROP Intermediate_Dir ".\Debug" +# PROP Target_Dir "" +CPP=cl.exe +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /FD /c +# SUBTRACT CPP /YX +MTL=midl.exe +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:".\Debug\zlib.dll" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "zlibvc__" +# PROP BASE Intermediate_Dir "zlibvc__" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "zlibvc__" +# PROP Intermediate_Dir "zlibvc__" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +MTL=midl.exe +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +CPP=cl.exe +# ADD BASE CPP /nologo /MT /Gt0 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /FAcs /FR /YX /FD /c +# ADD CPP /nologo /MT /Gt0 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /FAcs /FR /FD /c +# SUBTRACT CPP /YX +RSC=rc.exe +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 crtdll.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /map /machine:ALPHA /nodefaultlib /out:".\Release\zlib.dll" +# SUBTRACT BASE LINK32 /pdb:none +# ADD LINK32 crtdll.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /map /machine:ALPHA /nodefaultlib /out:"zlibvc__\zlib.dll" +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "zlibvc_0" +# PROP BASE Intermediate_Dir "zlibvc_0" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "zlibvc_0" +# PROP Intermediate_Dir "zlibvc_0" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +CPP=cl.exe +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /FAcs /FR /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /FAcs /FR /FD /c +# SUBTRACT CPP /YX +MTL=midl.exe +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\Release\zlib.dll" +# SUBTRACT BASE LINK32 /pdb:none +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\zlibvc_0\zlib.dll" +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "zlibvc_1" +# PROP BASE Intermediate_Dir "zlibvc_1" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "zlibvc_1" +# PROP Intermediate_Dir "zlibvc_1" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +CPP=cl.exe +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /D "ASMV" /FAcs /FR /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /D "ASMV" /FAcs /FR /FD /c +# SUBTRACT CPP /YX +MTL=midl.exe +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 gvmat32.obj kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\Release\zlib.dll" +# SUBTRACT BASE LINK32 /pdb:none +# ADD LINK32 gvmat32.obj kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\zlibvc_1\zlib.dll" +# SUBTRACT LINK32 /pdb:none + +!ENDIF + +# Begin Target + +# Name "zlibvc - Win32 Release" +# Name "zlibvc - Win32 Debug" +# Name "zlibvc - Win32 ReleaseAxp" +# Name "zlibvc - Win32 ReleaseWithoutAsm" +# Name "zlibvc - Win32 ReleaseWithoutCrtdll" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=.\adler32.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_ADLER=\ + ".\zconf.h"\ + ".\zlib.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\compress.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_COMPR=\ + ".\zconf.h"\ + ".\zlib.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\crc32.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_CRC32=\ + ".\zconf.h"\ + ".\zlib.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\deflate.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_DEFLA=\ + ".\deflate.h"\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\gvmat32c.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\gzio.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_GZIO_=\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\infblock.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_INFBL=\ + ".\infblock.h"\ + ".\infcodes.h"\ + ".\inftrees.h"\ + ".\infutil.h"\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\infcodes.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_INFCO=\ + ".\infblock.h"\ + ".\infcodes.h"\ + ".\inffast.h"\ + ".\inftrees.h"\ + ".\infutil.h"\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\inffast.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_INFFA=\ + ".\infblock.h"\ + ".\infcodes.h"\ + ".\inffast.h"\ + ".\inftrees.h"\ + ".\infutil.h"\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\inflate.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_INFLA=\ + ".\infblock.h"\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\inftrees.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_INFTR=\ + ".\inftrees.h"\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\infutil.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_INFUT=\ + ".\infblock.h"\ + ".\infcodes.h"\ + ".\inftrees.h"\ + ".\infutil.h"\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\trees.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_TREES=\ + ".\deflate.h"\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\uncompr.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_UNCOM=\ + ".\zconf.h"\ + ".\zlib.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\unzip.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\zip.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\zlib.rc +# End Source File +# Begin Source File + +SOURCE=.\zlibvc.def +# End Source File +# Begin Source File + +SOURCE=.\zutil.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_ZUTIL=\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\deflate.h +# End Source File +# Begin Source File + +SOURCE=.\infblock.h +# End Source File +# Begin Source File + +SOURCE=.\infcodes.h +# End Source File +# Begin Source File + +SOURCE=.\inffast.h +# End Source File +# Begin Source File + +SOURCE=.\inftrees.h +# End Source File +# Begin Source File + +SOURCE=.\infutil.h +# End Source File +# Begin Source File + +SOURCE=.\zconf.h +# End Source File +# Begin Source File + +SOURCE=.\zlib.h +# End Source File +# Begin Source File + +SOURCE=.\zutil.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/asm386/zlibvc.dsw b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/asm386/zlibvc.dsw new file mode 100644 index 00000000000..493cd870365 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/asm386/zlibvc.dsw @@ -0,0 +1,41 @@ +Microsoft Developer Studio Workspace File, Format Version 5.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "zlibstat"=.\zlibstat.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "zlibvc"=.\zlibvc.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/asm586/README.586 b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/asm586/README.586 new file mode 100644 index 00000000000..6bb78f32069 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/asm586/README.586 @@ -0,0 +1,43 @@ +This is a patched version of zlib modified to use +Pentium-optimized assembly code in the deflation algorithm. The files +changed/added by this patch are: + +README.586 +match.S + +The effectiveness of these modifications is a bit marginal, as the the +program's bottleneck seems to be mostly L1-cache contention, for which +there is no real way to work around without rewriting the basic +algorithm. The speedup on average is around 5-10% (which is generally +less than the amount of variance between subsequent executions). +However, when used at level 9 compression, the cache contention can +drop enough for the assembly version to achieve 10-20% speedup (and +sometimes more, depending on the amount of overall redundancy in the +files). Even here, though, cache contention can still be the limiting +factor, depending on the nature of the program using the zlib library. +This may also mean that better improvements will be seen on a Pentium +with MMX, which suffers much less from L1-cache contention, but I have +not yet verified this. + +Note that this code has been tailored for the Pentium in particular, +and will not perform well on the Pentium Pro (due to the use of a +partial register in the inner loop). + +If you are using an assembler other than GNU as, you will have to +translate match.S to use your assembler's syntax. (Have fun.) + +Brian Raiter +breadbox@muppetlabs.com +April, 1998 + + +Added for zlib 1.1.3: + +The patches come from +http://www.muppetlabs.com/~breadbox/software/assembly.html + +To compile zlib with this asm file, copy match.S to the zlib directory +then do: + +CFLAGS="-O3 -DASMV" ./configure +make OBJA=match.o diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/asm586/match.S b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/asm586/match.S new file mode 100644 index 00000000000..8f1614078f8 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/asm586/match.S @@ -0,0 +1,354 @@ +/* match.s -- Pentium-optimized version of longest_match() + * Written for zlib 1.1.2 + * Copyright (C) 1998 Brian Raiter + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License. + */ + +#ifndef NO_UNDERLINE +#define match_init _match_init +#define longest_match _longest_match +#endif + +#define MAX_MATCH (258) +#define MIN_MATCH (3) +#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1) +#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7) + +/* stack frame offsets */ + +#define wmask 0 /* local copy of s->wmask */ +#define window 4 /* local copy of s->window */ +#define windowbestlen 8 /* s->window + bestlen */ +#define chainlenscanend 12 /* high word: current chain len */ + /* low word: last bytes sought */ +#define scanstart 16 /* first two bytes of string */ +#define scanalign 20 /* dword-misalignment of string */ +#define nicematch 24 /* a good enough match size */ +#define bestlen 28 /* size of best match so far */ +#define scan 32 /* ptr to string wanting match */ + +#define LocalVarsSize (36) +/* saved ebx 36 */ +/* saved edi 40 */ +/* saved esi 44 */ +/* saved ebp 48 */ +/* return address 52 */ +#define deflatestate 56 /* the function arguments */ +#define curmatch 60 + +/* Offsets for fields in the deflate_state structure. These numbers + * are calculated from the definition of deflate_state, with the + * assumption that the compiler will dword-align the fields. (Thus, + * changing the definition of deflate_state could easily cause this + * program to crash horribly, without so much as a warning at + * compile time. Sigh.) + */ +#define dsWSize 36 +#define dsWMask 44 +#define dsWindow 48 +#define dsPrev 56 +#define dsMatchLen 88 +#define dsPrevMatch 92 +#define dsStrStart 100 +#define dsMatchStart 104 +#define dsLookahead 108 +#define dsPrevLen 112 +#define dsMaxChainLen 116 +#define dsGoodMatch 132 +#define dsNiceMatch 136 + + +.file "match.S" + +.globl match_init, longest_match + +.text + +/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */ + +longest_match: + +/* Save registers that the compiler may be using, and adjust %esp to */ +/* make room for our stack frame. */ + + pushl %ebp + pushl %edi + pushl %esi + pushl %ebx + subl $LocalVarsSize, %esp + +/* Retrieve the function arguments. %ecx will hold cur_match */ +/* throughout the entire function. %edx will hold the pointer to the */ +/* deflate_state structure during the function's setup (before */ +/* entering the main loop). */ + + movl deflatestate(%esp), %edx + movl curmatch(%esp), %ecx + +/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */ + + movl dsNiceMatch(%edx), %eax + movl dsLookahead(%edx), %ebx + cmpl %eax, %ebx + jl LookaheadLess + movl %eax, %ebx +LookaheadLess: movl %ebx, nicematch(%esp) + +/* register Bytef *scan = s->window + s->strstart; */ + + movl dsWindow(%edx), %esi + movl %esi, window(%esp) + movl dsStrStart(%edx), %ebp + lea (%esi,%ebp), %edi + movl %edi, scan(%esp) + +/* Determine how many bytes the scan ptr is off from being */ +/* dword-aligned. */ + + movl %edi, %eax + negl %eax + andl $3, %eax + movl %eax, scanalign(%esp) + +/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */ +/* s->strstart - (IPos)MAX_DIST(s) : NIL; */ + + movl dsWSize(%edx), %eax + subl $MIN_LOOKAHEAD, %eax + subl %eax, %ebp + jg LimitPositive + xorl %ebp, %ebp +LimitPositive: + +/* unsigned chain_length = s->max_chain_length; */ +/* if (s->prev_length >= s->good_match) { */ +/* chain_length >>= 2; */ +/* } */ + + movl dsPrevLen(%edx), %eax + movl dsGoodMatch(%edx), %ebx + cmpl %ebx, %eax + movl dsMaxChainLen(%edx), %ebx + jl LastMatchGood + shrl $2, %ebx +LastMatchGood: + +/* chainlen is decremented once beforehand so that the function can */ +/* use the sign flag instead of the zero flag for the exit test. */ +/* It is then shifted into the high word, to make room for the scanend */ +/* scanend value, which it will always accompany. */ + + decl %ebx + shll $16, %ebx + +/* int best_len = s->prev_length; */ + + movl dsPrevLen(%edx), %eax + movl %eax, bestlen(%esp) + +/* Store the sum of s->window + best_len in %esi locally, and in %esi. */ + + addl %eax, %esi + movl %esi, windowbestlen(%esp) + +/* register ush scan_start = *(ushf*)scan; */ +/* register ush scan_end = *(ushf*)(scan+best_len-1); */ + + movw (%edi), %bx + movw %bx, scanstart(%esp) + movw -1(%edi,%eax), %bx + movl %ebx, chainlenscanend(%esp) + +/* Posf *prev = s->prev; */ +/* uInt wmask = s->w_mask; */ + + movl dsPrev(%edx), %edi + movl dsWMask(%edx), %edx + mov %edx, wmask(%esp) + +/* Jump into the main loop. */ + + jmp LoopEntry + +.balign 16 + +/* do { + * match = s->window + cur_match; + * if (*(ushf*)(match+best_len-1) != scan_end || + * *(ushf*)match != scan_start) continue; + * [...] + * } while ((cur_match = prev[cur_match & wmask]) > limit + * && --chain_length != 0); + * + * Here is the inner loop of the function. The function will spend the + * majority of its time in this loop, and majority of that time will + * be spent in the first ten instructions. + * + * Within this loop: + * %ebx = chainlenscanend - i.e., ((chainlen << 16) | scanend) + * %ecx = curmatch + * %edx = curmatch & wmask + * %esi = windowbestlen - i.e., (window + bestlen) + * %edi = prev + * %ebp = limit + * + * Two optimization notes on the choice of instructions: + * + * The first instruction uses a 16-bit address, which costs an extra, + * unpairable cycle. This is cheaper than doing a 32-bit access and + * zeroing the high word, due to the 3-cycle misalignment penalty which + * would occur half the time. This also turns out to be cheaper than + * doing two separate 8-bit accesses, as the memory is so rarely in the + * L1 cache. + * + * The window buffer, however, apparently spends a lot of time in the + * cache, and so it is faster to retrieve the word at the end of the + * match string with two 8-bit loads. The instructions that test the + * word at the beginning of the match string, however, are executed + * much less frequently, and there it was cheaper to use 16-bit + * instructions, which avoided the necessity of saving off and + * subsequently reloading one of the other registers. + */ +LookupLoop: + /* 1 U & V */ + movw (%edi,%edx,2), %cx /* 2 U pipe */ + movl wmask(%esp), %edx /* 2 V pipe */ + cmpl %ebp, %ecx /* 3 U pipe */ + jbe LeaveNow /* 3 V pipe */ + subl $0x00010000, %ebx /* 4 U pipe */ + js LeaveNow /* 4 V pipe */ +LoopEntry: movb -1(%esi,%ecx), %al /* 5 U pipe */ + andl %ecx, %edx /* 5 V pipe */ + cmpb %bl, %al /* 6 U pipe */ + jnz LookupLoop /* 6 V pipe */ + movb (%esi,%ecx), %ah + cmpb %bh, %ah + jnz LookupLoop + movl window(%esp), %eax + movw (%eax,%ecx), %ax + cmpw scanstart(%esp), %ax + jnz LookupLoop + +/* Store the current value of chainlen. */ + + movl %ebx, chainlenscanend(%esp) + +/* Point %edi to the string under scrutiny, and %esi to the string we */ +/* are hoping to match it up with. In actuality, %esi and %edi are */ +/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */ +/* initialized to -(MAX_MATCH_8 - scanalign). */ + + movl window(%esp), %esi + movl scan(%esp), %edi + addl %ecx, %esi + movl scanalign(%esp), %eax + movl $(-MAX_MATCH_8), %edx + lea MAX_MATCH_8(%edi,%eax), %edi + lea MAX_MATCH_8(%esi,%eax), %esi + +/* Test the strings for equality, 8 bytes at a time. At the end, + * adjust %edx so that it is offset to the exact byte that mismatched. + * + * We already know at this point that the first three bytes of the + * strings match each other, and they can be safely passed over before + * starting the compare loop. So what this code does is skip over 0-3 + * bytes, as much as necessary in order to dword-align the %edi + * pointer. (%esi will still be misaligned three times out of four.) + * + * It should be confessed that this loop usually does not represent + * much of the total running time. Replacing it with a more + * straightforward "rep cmpsb" would not drastically degrade + * performance. + */ +LoopCmps: + movl (%esi,%edx), %eax + movl (%edi,%edx), %ebx + xorl %ebx, %eax + jnz LeaveLoopCmps + movl 4(%esi,%edx), %eax + movl 4(%edi,%edx), %ebx + xorl %ebx, %eax + jnz LeaveLoopCmps4 + addl $8, %edx + jnz LoopCmps + jmp LenMaximum +LeaveLoopCmps4: addl $4, %edx +LeaveLoopCmps: testl $0x0000FFFF, %eax + jnz LenLower + addl $2, %edx + shrl $16, %eax +LenLower: subb $1, %al + adcl $0, %edx + +/* Calculate the length of the match. If it is longer than MAX_MATCH, */ +/* then automatically accept it as the best possible match and leave. */ + + lea (%edi,%edx), %eax + movl scan(%esp), %edi + subl %edi, %eax + cmpl $MAX_MATCH, %eax + jge LenMaximum + +/* If the length of the match is not longer than the best match we */ +/* have so far, then forget it and return to the lookup loop. */ + + movl deflatestate(%esp), %edx + movl bestlen(%esp), %ebx + cmpl %ebx, %eax + jg LongerMatch + movl chainlenscanend(%esp), %ebx + movl windowbestlen(%esp), %esi + movl dsPrev(%edx), %edi + movl wmask(%esp), %edx + andl %ecx, %edx + jmp LookupLoop + +/* s->match_start = cur_match; */ +/* best_len = len; */ +/* if (len >= nice_match) break; */ +/* scan_end = *(ushf*)(scan+best_len-1); */ + +LongerMatch: movl nicematch(%esp), %ebx + movl %eax, bestlen(%esp) + movl %ecx, dsMatchStart(%edx) + cmpl %ebx, %eax + jge LeaveNow + movl window(%esp), %esi + addl %eax, %esi + movl %esi, windowbestlen(%esp) + movl chainlenscanend(%esp), %ebx + movw -1(%edi,%eax), %bx + movl dsPrev(%edx), %edi + movl %ebx, chainlenscanend(%esp) + movl wmask(%esp), %edx + andl %ecx, %edx + jmp LookupLoop + +/* Accept the current string, with the maximum possible length. */ + +LenMaximum: movl deflatestate(%esp), %edx + movl $MAX_MATCH, bestlen(%esp) + movl %ecx, dsMatchStart(%edx) + +/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */ +/* return s->lookahead; */ + +LeaveNow: + movl deflatestate(%esp), %edx + movl bestlen(%esp), %ebx + movl dsLookahead(%edx), %eax + cmpl %eax, %ebx + jg LookaheadRet + movl %ebx, %eax +LookaheadRet: + +/* Restore the stack and return from whence we came. */ + + addl $LocalVarsSize, %esp + popl %ebx + popl %esi + popl %edi + popl %ebp +match_init: ret diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/asm686/README.686 b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/asm686/README.686 new file mode 100644 index 00000000000..a593f23afd6 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/asm686/README.686 @@ -0,0 +1,34 @@ +This is a patched version of zlib, modified to use +Pentium-Pro-optimized assembly code in the deflation algorithm. The +files changed/added by this patch are: + +README.686 +match.S + +The speedup that this patch provides varies, depending on whether the +compiler used to build the original version of zlib falls afoul of the +PPro's speed traps. My own tests show a speedup of around 10-20% at +the default compression level, and 20-30% using -9, against a version +compiled using gcc 2.7.2.3. Your mileage may vary. + +Note that this code has been tailored for the PPro/PII in particular, +and will not perform particuarly well on a Pentium. + +If you are using an assembler other than GNU as, you will have to +translate match.S to use your assembler's syntax. (Have fun.) + +Brian Raiter +breadbox@muppetlabs.com +April, 1998 + + +Added for zlib 1.1.3: + +The patches come from +http://www.muppetlabs.com/~breadbox/software/assembly.html + +To compile zlib with this asm file, copy match.S to the zlib directory +then do: + +CFLAGS="-O3 -DASMV" ./configure +make OBJA=match.o diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/asm686/match.S b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/asm686/match.S new file mode 100644 index 00000000000..8e86c33c288 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/asm686/match.S @@ -0,0 +1,327 @@ +/* match.s -- Pentium-Pro-optimized version of longest_match() + * Written for zlib 1.1.2 + * Copyright (C) 1998 Brian Raiter + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License. + */ + +#ifndef NO_UNDERLINE +#define match_init _match_init +#define longest_match _longest_match +#endif + +#define MAX_MATCH (258) +#define MIN_MATCH (3) +#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1) +#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7) + +/* stack frame offsets */ + +#define chainlenwmask 0 /* high word: current chain len */ + /* low word: s->wmask */ +#define window 4 /* local copy of s->window */ +#define windowbestlen 8 /* s->window + bestlen */ +#define scanstart 16 /* first two bytes of string */ +#define scanend 12 /* last two bytes of string */ +#define scanalign 20 /* dword-misalignment of string */ +#define nicematch 24 /* a good enough match size */ +#define bestlen 28 /* size of best match so far */ +#define scan 32 /* ptr to string wanting match */ + +#define LocalVarsSize (36) +/* saved ebx 36 */ +/* saved edi 40 */ +/* saved esi 44 */ +/* saved ebp 48 */ +/* return address 52 */ +#define deflatestate 56 /* the function arguments */ +#define curmatch 60 + +/* Offsets for fields in the deflate_state structure. These numbers + * are calculated from the definition of deflate_state, with the + * assumption that the compiler will dword-align the fields. (Thus, + * changing the definition of deflate_state could easily cause this + * program to crash horribly, without so much as a warning at + * compile time. Sigh.) + */ +#define dsWSize 36 +#define dsWMask 44 +#define dsWindow 48 +#define dsPrev 56 +#define dsMatchLen 88 +#define dsPrevMatch 92 +#define dsStrStart 100 +#define dsMatchStart 104 +#define dsLookahead 108 +#define dsPrevLen 112 +#define dsMaxChainLen 116 +#define dsGoodMatch 132 +#define dsNiceMatch 136 + + +.file "match.S" + +.globl match_init, longest_match + +.text + +/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */ + +longest_match: + +/* Save registers that the compiler may be using, and adjust %esp to */ +/* make room for our stack frame. */ + + pushl %ebp + pushl %edi + pushl %esi + pushl %ebx + subl $LocalVarsSize, %esp + +/* Retrieve the function arguments. %ecx will hold cur_match */ +/* throughout the entire function. %edx will hold the pointer to the */ +/* deflate_state structure during the function's setup (before */ +/* entering the main loop). */ + + movl deflatestate(%esp), %edx + movl curmatch(%esp), %ecx + +/* uInt wmask = s->w_mask; */ +/* unsigned chain_length = s->max_chain_length; */ +/* if (s->prev_length >= s->good_match) { */ +/* chain_length >>= 2; */ +/* } */ + + movl dsPrevLen(%edx), %eax + movl dsGoodMatch(%edx), %ebx + cmpl %ebx, %eax + movl dsWMask(%edx), %eax + movl dsMaxChainLen(%edx), %ebx + jl LastMatchGood + shrl $2, %ebx +LastMatchGood: + +/* chainlen is decremented once beforehand so that the function can */ +/* use the sign flag instead of the zero flag for the exit test. */ +/* It is then shifted into the high word, to make room for the wmask */ +/* value, which it will always accompany. */ + + decl %ebx + shll $16, %ebx + orl %eax, %ebx + movl %ebx, chainlenwmask(%esp) + +/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */ + + movl dsNiceMatch(%edx), %eax + movl dsLookahead(%edx), %ebx + cmpl %eax, %ebx + jl LookaheadLess + movl %eax, %ebx +LookaheadLess: movl %ebx, nicematch(%esp) + +/* register Bytef *scan = s->window + s->strstart; */ + + movl dsWindow(%edx), %esi + movl %esi, window(%esp) + movl dsStrStart(%edx), %ebp + lea (%esi,%ebp), %edi + movl %edi, scan(%esp) + +/* Determine how many bytes the scan ptr is off from being */ +/* dword-aligned. */ + + movl %edi, %eax + negl %eax + andl $3, %eax + movl %eax, scanalign(%esp) + +/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */ +/* s->strstart - (IPos)MAX_DIST(s) : NIL; */ + + movl dsWSize(%edx), %eax + subl $MIN_LOOKAHEAD, %eax + subl %eax, %ebp + jg LimitPositive + xorl %ebp, %ebp +LimitPositive: + +/* int best_len = s->prev_length; */ + + movl dsPrevLen(%edx), %eax + movl %eax, bestlen(%esp) + +/* Store the sum of s->window + best_len in %esi locally, and in %esi. */ + + addl %eax, %esi + movl %esi, windowbestlen(%esp) + +/* register ush scan_start = *(ushf*)scan; */ +/* register ush scan_end = *(ushf*)(scan+best_len-1); */ +/* Posf *prev = s->prev; */ + + movzwl (%edi), %ebx + movl %ebx, scanstart(%esp) + movzwl -1(%edi,%eax), %ebx + movl %ebx, scanend(%esp) + movl dsPrev(%edx), %edi + +/* Jump into the main loop. */ + + movl chainlenwmask(%esp), %edx + jmp LoopEntry + +.balign 16 + +/* do { + * match = s->window + cur_match; + * if (*(ushf*)(match+best_len-1) != scan_end || + * *(ushf*)match != scan_start) continue; + * [...] + * } while ((cur_match = prev[cur_match & wmask]) > limit + * && --chain_length != 0); + * + * Here is the inner loop of the function. The function will spend the + * majority of its time in this loop, and majority of that time will + * be spent in the first ten instructions. + * + * Within this loop: + * %ebx = scanend + * %ecx = curmatch + * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) + * %esi = windowbestlen - i.e., (window + bestlen) + * %edi = prev + * %ebp = limit + */ +LookupLoop: + andl %edx, %ecx + movzwl (%edi,%ecx,2), %ecx + cmpl %ebp, %ecx + jbe LeaveNow + subl $0x00010000, %edx + js LeaveNow +LoopEntry: movzwl -1(%esi,%ecx), %eax + cmpl %ebx, %eax + jnz LookupLoop + movl window(%esp), %eax + movzwl (%eax,%ecx), %eax + cmpl scanstart(%esp), %eax + jnz LookupLoop + +/* Store the current value of chainlen. */ + + movl %edx, chainlenwmask(%esp) + +/* Point %edi to the string under scrutiny, and %esi to the string we */ +/* are hoping to match it up with. In actuality, %esi and %edi are */ +/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */ +/* initialized to -(MAX_MATCH_8 - scanalign). */ + + movl window(%esp), %esi + movl scan(%esp), %edi + addl %ecx, %esi + movl scanalign(%esp), %eax + movl $(-MAX_MATCH_8), %edx + lea MAX_MATCH_8(%edi,%eax), %edi + lea MAX_MATCH_8(%esi,%eax), %esi + +/* Test the strings for equality, 8 bytes at a time. At the end, + * adjust %edx so that it is offset to the exact byte that mismatched. + * + * We already know at this point that the first three bytes of the + * strings match each other, and they can be safely passed over before + * starting the compare loop. So what this code does is skip over 0-3 + * bytes, as much as necessary in order to dword-align the %edi + * pointer. (%esi will still be misaligned three times out of four.) + * + * It should be confessed that this loop usually does not represent + * much of the total running time. Replacing it with a more + * straightforward "rep cmpsb" would not drastically degrade + * performance. + */ +LoopCmps: + movl (%esi,%edx), %eax + xorl (%edi,%edx), %eax + jnz LeaveLoopCmps + movl 4(%esi,%edx), %eax + xorl 4(%edi,%edx), %eax + jnz LeaveLoopCmps4 + addl $8, %edx + jnz LoopCmps + jmp LenMaximum +LeaveLoopCmps4: addl $4, %edx +LeaveLoopCmps: testl $0x0000FFFF, %eax + jnz LenLower + addl $2, %edx + shrl $16, %eax +LenLower: subb $1, %al + adcl $0, %edx + +/* Calculate the length of the match. If it is longer than MAX_MATCH, */ +/* then automatically accept it as the best possible match and leave. */ + + lea (%edi,%edx), %eax + movl scan(%esp), %edi + subl %edi, %eax + cmpl $MAX_MATCH, %eax + jge LenMaximum + +/* If the length of the match is not longer than the best match we */ +/* have so far, then forget it and return to the lookup loop. */ + + movl deflatestate(%esp), %edx + movl bestlen(%esp), %ebx + cmpl %ebx, %eax + jg LongerMatch + movl windowbestlen(%esp), %esi + movl dsPrev(%edx), %edi + movl scanend(%esp), %ebx + movl chainlenwmask(%esp), %edx + jmp LookupLoop + +/* s->match_start = cur_match; */ +/* best_len = len; */ +/* if (len >= nice_match) break; */ +/* scan_end = *(ushf*)(scan+best_len-1); */ + +LongerMatch: movl nicematch(%esp), %ebx + movl %eax, bestlen(%esp) + movl %ecx, dsMatchStart(%edx) + cmpl %ebx, %eax + jge LeaveNow + movl window(%esp), %esi + addl %eax, %esi + movl %esi, windowbestlen(%esp) + movzwl -1(%edi,%eax), %ebx + movl dsPrev(%edx), %edi + movl %ebx, scanend(%esp) + movl chainlenwmask(%esp), %edx + jmp LookupLoop + +/* Accept the current string, with the maximum possible length. */ + +LenMaximum: movl deflatestate(%esp), %edx + movl $MAX_MATCH, bestlen(%esp) + movl %ecx, dsMatchStart(%edx) + +/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */ +/* return s->lookahead; */ + +LeaveNow: + movl deflatestate(%esp), %edx + movl bestlen(%esp), %ebx + movl dsLookahead(%edx), %eax + cmpl %eax, %ebx + jg LookaheadRet + movl %ebx, %eax +LookaheadRet: + +/* Restore the stack and return from whence we came. */ + + addl $LocalVarsSize, %esp + popl %ebx + popl %esi + popl %edi + popl %ebp +match_init: ret diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi/zlib.mak b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi/zlib.mak new file mode 100644 index 00000000000..ba557e2b977 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi/zlib.mak @@ -0,0 +1,36 @@ +# Makefile for zlib32bd.lib +# ------------- Borland C++ 4.5 ------------- + +# The (32-bit) zlib32bd.lib made with this makefile is intended for use +# in making the (32-bit) DLL, png32bd.dll. It uses the "stdcall" calling +# convention. + +CFLAGS= -ps -O2 -C -K -N- -k- -d -3 -r- -w-par -w-aus -WDE +CC=f:\bc45\bin\bcc32 +LIBFLAGS= /C +LIB=f:\bc45\bin\tlib +ZLIB=zlib32bd.lib + +.autodepend +.c.obj: + $(CC) -c $(CFLAGS) $< + +OBJ1=adler32.obj compress.obj crc32.obj deflate.obj gzio.obj infblock.obj +OBJ2=infcodes.obj inflate.obj inftrees.obj infutil.obj inffast.obj +OBJ3=trees.obj uncompr.obj zutil.obj +pOBJ1=+adler32.obj+compress.obj+crc32.obj+deflate.obj+gzio.obj+infblock.obj +pOBJ2=+infcodes.obj+inflate.obj+inftrees.obj+infutil.obj+inffast.obj +pOBJ3=+trees.obj+uncompr.obj+zutil.obj + +all: $(ZLIB) + +$(ZLIB): $(OBJ1) $(OBJ2) $(OBJ3) + @if exist $@ del $@ + $(LIB) @&&| +$@ $(LIBFLAGS) & +$(pOBJ1) & +$(pOBJ2) & +$(pOBJ3) +| + +# End of makefile for zlib32bd.lib diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi/zlibdef.pas b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi/zlibdef.pas new file mode 100644 index 00000000000..4f96b7d2c50 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi/zlibdef.pas @@ -0,0 +1,169 @@ +unit zlibdef; + +interface + +uses + Windows; + +const + ZLIB_VERSION = '1.1.3'; + +type + voidpf = Pointer; + int = Integer; + uInt = Cardinal; + pBytef = PChar; + uLong = Cardinal; + + alloc_func = function(opaque: voidpf; items, size: uInt): voidpf; + stdcall; + free_func = procedure(opaque, address: voidpf); + stdcall; + + internal_state = Pointer; + + z_streamp = ^z_stream; + z_stream = packed record + next_in: pBytef; // next input byte + avail_in: uInt; // number of bytes available at next_in + total_in: uLong; // total nb of input bytes read so far + + next_out: pBytef; // next output byte should be put there + avail_out: uInt; // remaining free space at next_out + total_out: uLong; // total nb of bytes output so far + + msg: PChar; // last error message, NULL if no error + state: internal_state; // not visible by applications + + zalloc: alloc_func; // used to allocate the internal state + zfree: free_func; // used to free the internal state + opaque: voidpf; // private data object passed to zalloc and zfree + + data_type: int; // best guess about the data type: ascii or binary + adler: uLong; // adler32 value of the uncompressed data + reserved: uLong; // reserved for future use + end; + +const + Z_NO_FLUSH = 0; + Z_SYNC_FLUSH = 2; + Z_FULL_FLUSH = 3; + Z_FINISH = 4; + + Z_OK = 0; + Z_STREAM_END = 1; + + Z_NO_COMPRESSION = 0; + Z_BEST_SPEED = 1; + Z_BEST_COMPRESSION = 9; + Z_DEFAULT_COMPRESSION = -1; + + Z_FILTERED = 1; + Z_HUFFMAN_ONLY = 2; + Z_DEFAULT_STRATEGY = 0; + + Z_BINARY = 0; + Z_ASCII = 1; + Z_UNKNOWN = 2; + + Z_DEFLATED = 8; + + MAX_MEM_LEVEL = 9; + +function adler32(adler: uLong; const buf: pBytef; len: uInt): uLong; + stdcall; +function crc32(crc: uLong; const buf: pBytef; len: uInt): uLong; + stdcall; +function deflate(strm: z_streamp; flush: int): int; + stdcall; +function deflateCopy(dest, source: z_streamp): int; + stdcall; +function deflateEnd(strm: z_streamp): int; + stdcall; +function deflateInit2_(strm: z_streamp; level, method, + windowBits, memLevel, strategy: int; + const version: PChar; stream_size: int): int; + stdcall; +function deflateInit_(strm: z_streamp; level: int; + const version: PChar; stream_size: int): int; + stdcall; +function deflateParams(strm: z_streamp; level, strategy: int): int; + stdcall; +function deflateReset(strm: z_streamp): int; + stdcall; +function deflateSetDictionary(strm: z_streamp; + const dictionary: pBytef; + dictLength: uInt): int; + stdcall; +function inflate(strm: z_streamp; flush: int): int; + stdcall; +function inflateEnd(strm: z_streamp): int; + stdcall; +function inflateInit2_(strm: z_streamp; windowBits: int; + const version: PChar; stream_size: int): int; + stdcall; +function inflateInit_(strm: z_streamp; const version: PChar; + stream_size: int): int; + stdcall; +function inflateReset(strm: z_streamp): int; + stdcall; +function inflateSetDictionary(strm: z_streamp; + const dictionary: pBytef; + dictLength: uInt): int; + stdcall; +function inflateSync(strm: z_streamp): int; + stdcall; + +function deflateInit(strm: z_streamp; level: int): int; +function deflateInit2(strm: z_streamp; level, method, windowBits, + memLevel, strategy: int): int; +function inflateInit(strm: z_streamp): int; +function inflateInit2(strm: z_streamp; windowBits: int): int; + +implementation + +function deflateInit(strm: z_streamp; level: int): int; +begin + Result := deflateInit_(strm, level, ZLIB_VERSION, sizeof(z_stream)); +end; + +function deflateInit2(strm: z_streamp; level, method, windowBits, + memLevel, strategy: int): int; +begin + Result := deflateInit2_(strm, level, method, windowBits, memLevel, + strategy, ZLIB_VERSION, sizeof(z_stream)); +end; + +function inflateInit(strm: z_streamp): int; +begin + Result := inflateInit_(strm, ZLIB_VERSION, sizeof(z_stream)); +end; + +function inflateInit2(strm: z_streamp; windowBits: int): int; +begin + Result := inflateInit2_(strm, windowBits, ZLIB_VERSION, + sizeof(z_stream)); +end; + +const + zlibDLL = 'png32bd.dll'; + +function adler32; external zlibDLL; +function crc32; external zlibDLL; +function deflate; external zlibDLL; +function deflateCopy; external zlibDLL; +function deflateEnd; external zlibDLL; +function deflateInit2_; external zlibDLL; +function deflateInit_; external zlibDLL; +function deflateParams; external zlibDLL; +function deflateReset; external zlibDLL; +function deflateSetDictionary; external zlibDLL; +function inflate; external zlibDLL; +function inflateEnd; external zlibDLL; +function inflateInit2_; external zlibDLL; +function inflateInit_; external zlibDLL; +function inflateReset; external zlibDLL; +function inflateSetDictionary; external zlibDLL; +function inflateSync; external zlibDLL; + +end. diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi2/d_zlib.bpr b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi2/d_zlib.bpr new file mode 100644 index 00000000000..78bb254088a --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi2/d_zlib.bpr @@ -0,0 +1,224 @@ +# --------------------------------------------------------------------------- +!if !$d(BCB) +BCB = $(MAKEDIR)\.. +!endif + +# --------------------------------------------------------------------------- +# IDE SECTION +# --------------------------------------------------------------------------- +# The following section of the project makefile is managed by the BCB IDE. +# It is recommended to use the IDE to change any of the values in this +# section. +# --------------------------------------------------------------------------- + +VERSION = BCB.03 +# --------------------------------------------------------------------------- +PROJECT = d_zlib.lib +OBJFILES = d_zlib.obj adler32.obj deflate.obj infblock.obj infcodes.obj inffast.obj \ + inflate.obj inftrees.obj infutil.obj trees.obj +RESFILES = +RESDEPEN = $(RESFILES) +LIBFILES = +LIBRARIES = VCL35.lib +SPARELIBS = VCL35.lib +DEFFILE = +PACKAGES = VCLX35.bpi VCL35.bpi VCLDB35.bpi VCLDBX35.bpi ibsmp35.bpi bcbsmp35.bpi \ + dclocx35.bpi QRPT35.bpi TEEUI35.bpi TEEDB35.bpi TEE35.bpi DSS35.bpi \ + NMFAST35.bpi INETDB35.bpi INET35.bpi VCLMID35.bpi +# --------------------------------------------------------------------------- +PATHCPP = .; +PATHASM = .; +PATHPAS = .; +PATHRC = .; +DEBUGLIBPATH = $(BCB)\lib\debug +RELEASELIBPATH = $(BCB)\lib\release +# --------------------------------------------------------------------------- +CFLAG1 = -O2 -Ve -d -k- -vi +CFLAG2 = -I$(BCB)\include;$(BCB)\include\vcl -H=$(BCB)\lib\vcl35.csm +CFLAG3 = -ff -pr -5 +PFLAGS = -U;$(DEBUGLIBPATH) -I$(BCB)\include;$(BCB)\include\vcl -H -W -$I- -v -JPHN -M +RFLAGS = -i$(BCB)\include;$(BCB)\include\vcl +AFLAGS = /i$(BCB)\include /i$(BCB)\include\vcl /mx /w2 /zn +LFLAGS = +IFLAGS = -g -Gn +# --------------------------------------------------------------------------- +ALLOBJ = c0w32.obj $(OBJFILES) +ALLRES = $(RESFILES) +ALLLIB = $(LIBFILES) $(LIBRARIES) import32.lib cp32mt.lib +# --------------------------------------------------------------------------- +!!ifdef IDEOPTIONS + +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1040 +CodePage=1252 + +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= + +[HistoryLists\hlIncludePath] +Count=2 +Item0=$(BCB)\include +Item1=$(BCB)\include;$(BCB)\include\vcl + +[HistoryLists\hlLibraryPath] +Count=1 +Item0=$(BCB)\lib\obj;$(BCB)\lib + +[HistoryLists\hlDebugSourcePath] +Count=1 +Item0=$(BCB)\source\vcl + +[Debugging] +DebugSourceDirs= + +[Parameters] +RunParams= +HostApplication= + +!endif + + --------------------------------------------------------------------------- +# MAKE SECTION +# --------------------------------------------------------------------------- +# This section of the project file is not used by the BCB IDE. It is for +# the benefit of building from the command-line using the MAKE utility. +# --------------------------------------------------------------------------- + +.autodepend +# --------------------------------------------------------------------------- +!if !$d(BCC32) +BCC32 = bcc32 +!endif + +!if !$d(DCC32) +DCC32 = dcc32 +!endif + +!if !$d(TASM32) +TASM32 = tasm32 +!endif + +!if !$d(LINKER) +LINKER = TLib +!endif + +!if !$d(BRCC32) +BRCC32 = brcc32 +!endif +# --------------------------------------------------------------------------- +!if $d(PATHCPP) +.PATH.CPP = $(PATHCPP) +.PATH.C = $(PATHCPP) +!endif + +!if $d(PATHPAS) +.PATH.PAS = $(PATHPAS) +!endif + +!if $d(PATHASM) +.PATH.ASM = $(PATHASM) +!endif + +!if $d(PATHRC) +.PATH.RC = $(PATHRC) +!endif +# --------------------------------------------------------------------------- +!ifdef IDEOPTIONS + +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1040 +CodePage=1252 + +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= + +[HistoryLists\hlIncludePath] +Count=2 +Item0=$(BCB)\include;$(BCB)\include\vcl +Item1=$(BCB)\include + +[HistoryLists\hlLibraryPath] +Count=1 +Item0=$(BCB)\lib\obj;$(BCB)\lib + +[HistoryLists\hlDebugSourcePath] +Count=1 +Item0=$(BCB)\source\vcl + +[Debugging] +DebugSourceDirs= + +[Parameters] +RunParams= +HostApplication= + +!endif + +$(PROJECT): $(OBJFILES) $(RESDEPEN) $(DEFFILE) + $(BCB)\BIN\$(LINKER) @&&! + $(LFLAGS) $(IFLAGS) + + $(ALLOBJ), + + $(PROJECT),, + + $(ALLLIB), + + $(DEFFILE), + + $(ALLRES) +! +# --------------------------------------------------------------------------- +.pas.hpp: + $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } + +.pas.obj: + $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } + +.cpp.obj: + $(BCB)\BIN\$(BCC32) $(CFLAG1) $(CFLAG2) $(CFLAG3) -n$(@D) {$< } + +.c.obj: + $(BCB)\BIN\$(BCC32) $(CFLAG1) $(CFLAG2) $(CFLAG3) -n$(@D) {$< } + +.asm.obj: + $(BCB)\BIN\$(TASM32) $(AFLAGS) $<, $@ + +.rc.res: + $(BCB)\BIN\$(BRCC32) $(RFLAGS) -fo$@ $< +# --------------------------------------------------------------------------- diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi2/d_zlib.cpp b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi2/d_zlib.cpp new file mode 100644 index 00000000000..f5dea59b762 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi2/d_zlib.cpp @@ -0,0 +1,17 @@ +#include +#pragma hdrstop +//--------------------------------------------------------------------------- +USEUNIT("adler32.c"); +USEUNIT("deflate.c"); +USEUNIT("infblock.c"); +USEUNIT("infcodes.c"); +USEUNIT("inffast.c"); +USEUNIT("inflate.c"); +USEUNIT("inftrees.c"); +USEUNIT("infutil.c"); +USEUNIT("trees.c"); +//--------------------------------------------------------------------------- +#define Library + +// To add a file to the library use the Project menu 'Add to Project'. + diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi2/readme.txt b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi2/readme.txt new file mode 100644 index 00000000000..cbd31620d87 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi2/readme.txt @@ -0,0 +1,17 @@ +These are files used to compile zlib under Borland C++ Builder 3. + +zlib.bpg is the main project group that can be loaded in the BCB IDE and +loads all other *.bpr projects + +zlib.bpr is a project used to create a static zlib.lib library with C calling +convention for functions. + +zlib32.bpr creates a zlib32.dll dynamic link library with Windows standard +calling convention. + +d_zlib.bpr creates a set of .obj files with register calling convention. +These files are used by zlib.pas to create a Delphi unit containing zlib. +The d_zlib.lib file generated isn't useful and can be deleted. + +zlib.cpp, zlib32.cpp and d_zlib.cpp are used by the above projects. + diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi2/zlib.bpg b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi2/zlib.bpg new file mode 100644 index 00000000000..b6c9acdf8c9 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi2/zlib.bpg @@ -0,0 +1,26 @@ +#------------------------------------------------------------------------------ +VERSION = BWS.01 +#------------------------------------------------------------------------------ +!ifndef ROOT +ROOT = $(MAKEDIR)\.. +!endif +#------------------------------------------------------------------------------ +MAKE = $(ROOT)\bin\make.exe -$(MAKEFLAGS) -f$** +DCC = $(ROOT)\bin\dcc32.exe $** +BRCC = $(ROOT)\bin\brcc32.exe $** +#------------------------------------------------------------------------------ +PROJECTS = zlib zlib32 d_zlib +#------------------------------------------------------------------------------ +default: $(PROJECTS) +#------------------------------------------------------------------------------ + +zlib: zlib.bpr + $(MAKE) + +zlib32: zlib32.bpr + $(MAKE) + +d_zlib: d_zlib.bpr + $(MAKE) + + diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi2/zlib.bpr b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi2/zlib.bpr new file mode 100644 index 00000000000..cf3945b2523 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi2/zlib.bpr @@ -0,0 +1,225 @@ +# --------------------------------------------------------------------------- +!if !$d(BCB) +BCB = $(MAKEDIR)\.. +!endif + +# --------------------------------------------------------------------------- +# IDE SECTION +# --------------------------------------------------------------------------- +# The following section of the project makefile is managed by the BCB IDE. +# It is recommended to use the IDE to change any of the values in this +# section. +# --------------------------------------------------------------------------- + +VERSION = BCB.03 +# --------------------------------------------------------------------------- +PROJECT = zlib.lib +OBJFILES = zlib.obj adler32.obj compress.obj crc32.obj deflate.obj gzio.obj infblock.obj \ + infcodes.obj inffast.obj inflate.obj inftrees.obj infutil.obj trees.obj \ + uncompr.obj zutil.obj +RESFILES = +RESDEPEN = $(RESFILES) +LIBFILES = +LIBRARIES = VCL35.lib +SPARELIBS = VCL35.lib +DEFFILE = +PACKAGES = VCLX35.bpi VCL35.bpi VCLDB35.bpi VCLDBX35.bpi ibsmp35.bpi bcbsmp35.bpi \ + dclocx35.bpi QRPT35.bpi TEEUI35.bpi TEEDB35.bpi TEE35.bpi DSS35.bpi \ + NMFAST35.bpi INETDB35.bpi INET35.bpi VCLMID35.bpi +# --------------------------------------------------------------------------- +PATHCPP = .; +PATHASM = .; +PATHPAS = .; +PATHRC = .; +DEBUGLIBPATH = $(BCB)\lib\debug +RELEASELIBPATH = $(BCB)\lib\release +# --------------------------------------------------------------------------- +CFLAG1 = -O2 -Ve -d -k- -vi +CFLAG2 = -I$(BCB)\include;$(BCB)\include\vcl -H=$(BCB)\lib\vcl35.csm +CFLAG3 = -ff -5 +PFLAGS = -U;$(DEBUGLIBPATH) -I$(BCB)\include;$(BCB)\include\vcl -H -W -$I- -v -JPHN -M +RFLAGS = -i$(BCB)\include;$(BCB)\include\vcl +AFLAGS = /i$(BCB)\include /i$(BCB)\include\vcl /mx /w2 /zn +LFLAGS = +IFLAGS = -g -Gn +# --------------------------------------------------------------------------- +ALLOBJ = c0w32.obj $(OBJFILES) +ALLRES = $(RESFILES) +ALLLIB = $(LIBFILES) $(LIBRARIES) import32.lib cp32mt.lib +# --------------------------------------------------------------------------- +!!ifdef IDEOPTIONS + +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1040 +CodePage=1252 + +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= + +[HistoryLists\hlIncludePath] +Count=2 +Item0=$(BCB)\include +Item1=$(BCB)\include;$(BCB)\include\vcl + +[HistoryLists\hlLibraryPath] +Count=1 +Item0=$(BCB)\lib\obj;$(BCB)\lib + +[HistoryLists\hlDebugSourcePath] +Count=1 +Item0=$(BCB)\source\vcl + +[Debugging] +DebugSourceDirs= + +[Parameters] +RunParams= +HostApplication= + +!endif + + --------------------------------------------------------------------------- +# MAKE SECTION +# --------------------------------------------------------------------------- +# This section of the project file is not used by the BCB IDE. It is for +# the benefit of building from the command-line using the MAKE utility. +# --------------------------------------------------------------------------- + +.autodepend +# --------------------------------------------------------------------------- +!if !$d(BCC32) +BCC32 = bcc32 +!endif + +!if !$d(DCC32) +DCC32 = dcc32 +!endif + +!if !$d(TASM32) +TASM32 = tasm32 +!endif + +!if !$d(LINKER) +LINKER = TLib +!endif + +!if !$d(BRCC32) +BRCC32 = brcc32 +!endif +# --------------------------------------------------------------------------- +!if $d(PATHCPP) +.PATH.CPP = $(PATHCPP) +.PATH.C = $(PATHCPP) +!endif + +!if $d(PATHPAS) +.PATH.PAS = $(PATHPAS) +!endif + +!if $d(PATHASM) +.PATH.ASM = $(PATHASM) +!endif + +!if $d(PATHRC) +.PATH.RC = $(PATHRC) +!endif +# --------------------------------------------------------------------------- +!ifdef IDEOPTIONS + +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1040 +CodePage=1252 + +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= + +[HistoryLists\hlIncludePath] +Count=2 +Item0=$(BCB)\include;$(BCB)\include\vcl +Item1=$(BCB)\include + +[HistoryLists\hlLibraryPath] +Count=1 +Item0=$(BCB)\lib\obj;$(BCB)\lib + +[HistoryLists\hlDebugSourcePath] +Count=1 +Item0=$(BCB)\source\vcl + +[Debugging] +DebugSourceDirs= + +[Parameters] +RunParams= +HostApplication= + +!endif + +$(PROJECT): $(OBJFILES) $(RESDEPEN) $(DEFFILE) + $(BCB)\BIN\$(LINKER) @&&! + $(LFLAGS) $(IFLAGS) + + $(ALLOBJ), + + $(PROJECT),, + + $(ALLLIB), + + $(DEFFILE), + + $(ALLRES) +! +# --------------------------------------------------------------------------- +.pas.hpp: + $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } + +.pas.obj: + $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } + +.cpp.obj: + $(BCB)\BIN\$(BCC32) $(CFLAG1) $(CFLAG2) $(CFLAG3) -n$(@D) {$< } + +.c.obj: + $(BCB)\BIN\$(BCC32) $(CFLAG1) $(CFLAG2) $(CFLAG3) -n$(@D) {$< } + +.asm.obj: + $(BCB)\BIN\$(TASM32) $(AFLAGS) $<, $@ + +.rc.res: + $(BCB)\BIN\$(BRCC32) $(RFLAGS) -fo$@ $< +# --------------------------------------------------------------------------- diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi2/zlib.cpp b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi2/zlib.cpp new file mode 100644 index 00000000000..bf6953ba198 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi2/zlib.cpp @@ -0,0 +1,22 @@ +#include +#pragma hdrstop +//--------------------------------------------------------------------------- +USEUNIT("adler32.c"); +USEUNIT("compress.c"); +USEUNIT("crc32.c"); +USEUNIT("deflate.c"); +USEUNIT("gzio.c"); +USEUNIT("infblock.c"); +USEUNIT("infcodes.c"); +USEUNIT("inffast.c"); +USEUNIT("inflate.c"); +USEUNIT("inftrees.c"); +USEUNIT("infutil.c"); +USEUNIT("trees.c"); +USEUNIT("uncompr.c"); +USEUNIT("zutil.c"); +//--------------------------------------------------------------------------- +#define Library + +// To add a file to the library use the Project menu 'Add to Project'. + diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi2/zlib.pas b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi2/zlib.pas new file mode 100644 index 00000000000..10ae4cae256 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi2/zlib.pas @@ -0,0 +1,534 @@ +{*******************************************************} +{ } +{ Delphi Supplemental Components } +{ ZLIB Data Compression Interface Unit } +{ } +{ Copyright (c) 1997 Borland International } +{ } +{*******************************************************} + +{ Modified for zlib 1.1.3 by Davide Moretti Z_STREAM_END do + begin + P := OutBuf; + Inc(OutBytes, 256); + ReallocMem(OutBuf, OutBytes); + strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P))); + strm.avail_out := 256; + end; + finally + CCheck(deflateEnd(strm)); + end; + ReallocMem(OutBuf, strm.total_out); + OutBytes := strm.total_out; + except + FreeMem(OutBuf); + raise + end; +end; + + +procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer; + OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer); +var + strm: TZStreamRec; + P: Pointer; + BufInc: Integer; +begin + FillChar(strm, sizeof(strm), 0); + BufInc := (InBytes + 255) and not 255; + if OutEstimate = 0 then + OutBytes := BufInc + else + OutBytes := OutEstimate; + GetMem(OutBuf, OutBytes); + try + strm.next_in := InBuf; + strm.avail_in := InBytes; + strm.next_out := OutBuf; + strm.avail_out := OutBytes; + DCheck(inflateInit_(strm, zlib_version, sizeof(strm))); + try + while DCheck(inflate(strm, Z_FINISH)) <> Z_STREAM_END do + begin + P := OutBuf; + Inc(OutBytes, BufInc); + ReallocMem(OutBuf, OutBytes); + strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P))); + strm.avail_out := BufInc; + end; + finally + DCheck(inflateEnd(strm)); + end; + ReallocMem(OutBuf, strm.total_out); + OutBytes := strm.total_out; + except + FreeMem(OutBuf); + raise + end; +end; + + +// TCustomZlibStream + +constructor TCustomZLibStream.Create(Strm: TStream); +begin + inherited Create; + FStrm := Strm; + FStrmPos := Strm.Position; +end; + +procedure TCustomZLibStream.Progress(Sender: TObject); +begin + if Assigned(FOnProgress) then FOnProgress(Sender); +end; + + +// TCompressionStream + +constructor TCompressionStream.Create(CompressionLevel: TCompressionLevel; + Dest: TStream); +const + Levels: array [TCompressionLevel] of ShortInt = + (Z_NO_COMPRESSION, Z_BEST_SPEED, Z_DEFAULT_COMPRESSION, Z_BEST_COMPRESSION); +begin + inherited Create(Dest); + FZRec.next_out := FBuffer; + FZRec.avail_out := sizeof(FBuffer); + CCheck(deflateInit_(FZRec, Levels[CompressionLevel], zlib_version, sizeof(FZRec))); +end; + +destructor TCompressionStream.Destroy; +begin + FZRec.next_in := nil; + FZRec.avail_in := 0; + try + if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos; + while (CCheck(deflate(FZRec, Z_FINISH)) <> Z_STREAM_END) + and (FZRec.avail_out = 0) do + begin + FStrm.WriteBuffer(FBuffer, sizeof(FBuffer)); + FZRec.next_out := FBuffer; + FZRec.avail_out := sizeof(FBuffer); + end; + if FZRec.avail_out < sizeof(FBuffer) then + FStrm.WriteBuffer(FBuffer, sizeof(FBuffer) - FZRec.avail_out); + finally + deflateEnd(FZRec); + end; + inherited Destroy; +end; + +function TCompressionStream.Read(var Buffer; Count: Longint): Longint; +begin + raise ECompressionError.Create('Invalid stream operation'); +end; + +function TCompressionStream.Write(const Buffer; Count: Longint): Longint; +begin + FZRec.next_in := @Buffer; + FZRec.avail_in := Count; + if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos; + while (FZRec.avail_in > 0) do + begin + CCheck(deflate(FZRec, 0)); + if FZRec.avail_out = 0 then + begin + FStrm.WriteBuffer(FBuffer, sizeof(FBuffer)); + FZRec.next_out := FBuffer; + FZRec.avail_out := sizeof(FBuffer); + FStrmPos := FStrm.Position; + Progress(Self); + end; + end; + Result := Count; +end; + +function TCompressionStream.Seek(Offset: Longint; Origin: Word): Longint; +begin + if (Offset = 0) and (Origin = soFromCurrent) then + Result := FZRec.total_in + else + raise ECompressionError.Create('Invalid stream operation'); +end; + +function TCompressionStream.GetCompressionRate: Single; +begin + if FZRec.total_in = 0 then + Result := 0 + else + Result := (1.0 - (FZRec.total_out / FZRec.total_in)) * 100.0; +end; + + +// TDecompressionStream + +constructor TDecompressionStream.Create(Source: TStream); +begin + inherited Create(Source); + FZRec.next_in := FBuffer; + FZRec.avail_in := 0; + DCheck(inflateInit_(FZRec, zlib_version, sizeof(FZRec))); +end; + +destructor TDecompressionStream.Destroy; +begin + inflateEnd(FZRec); + inherited Destroy; +end; + +function TDecompressionStream.Read(var Buffer; Count: Longint): Longint; +begin + FZRec.next_out := @Buffer; + FZRec.avail_out := Count; + if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos; + while (FZRec.avail_out > 0) do + begin + if FZRec.avail_in = 0 then + begin + FZRec.avail_in := FStrm.Read(FBuffer, sizeof(FBuffer)); + if FZRec.avail_in = 0 then + begin + Result := Count - FZRec.avail_out; + Exit; + end; + FZRec.next_in := FBuffer; + FStrmPos := FStrm.Position; + Progress(Self); + end; + DCheck(inflate(FZRec, 0)); + end; + Result := Count; +end; + +function TDecompressionStream.Write(const Buffer; Count: Longint): Longint; +begin + raise EDecompressionError.Create('Invalid stream operation'); +end; + +function TDecompressionStream.Seek(Offset: Longint; Origin: Word): Longint; +var + I: Integer; + Buf: array [0..4095] of Char; +begin + if (Offset = 0) and (Origin = soFromBeginning) then + begin + DCheck(inflateReset(FZRec)); + FZRec.next_in := FBuffer; + FZRec.avail_in := 0; + FStrm.Position := 0; + FStrmPos := 0; + end + else if ( (Offset >= 0) and (Origin = soFromCurrent)) or + ( ((Offset - FZRec.total_out) > 0) and (Origin = soFromBeginning)) then + begin + if Origin = soFromBeginning then Dec(Offset, FZRec.total_out); + if Offset > 0 then + begin + for I := 1 to Offset div sizeof(Buf) do + ReadBuffer(Buf, sizeof(Buf)); + ReadBuffer(Buf, Offset mod sizeof(Buf)); + end; + end + else + raise EDecompressionError.Create('Invalid stream operation'); + Result := FZRec.total_out; +end; + +end. diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi2/zlib32.bpr b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi2/zlib32.bpr new file mode 100644 index 00000000000..cabcec44947 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi2/zlib32.bpr @@ -0,0 +1,174 @@ +# --------------------------------------------------------------------------- +!if !$d(BCB) +BCB = $(MAKEDIR)\.. +!endif + +# --------------------------------------------------------------------------- +# IDE SECTION +# --------------------------------------------------------------------------- +# The following section of the project makefile is managed by the BCB IDE. +# It is recommended to use the IDE to change any of the values in this +# section. +# --------------------------------------------------------------------------- + +VERSION = BCB.03 +# --------------------------------------------------------------------------- +PROJECT = zlib32.dll +OBJFILES = zlib32.obj adler32.obj compress.obj crc32.obj deflate.obj gzio.obj infblock.obj \ + infcodes.obj inffast.obj inflate.obj inftrees.obj infutil.obj trees.obj \ + uncompr.obj zutil.obj +RESFILES = +RESDEPEN = $(RESFILES) +LIBFILES = +LIBRARIES = +SPARELIBS = +DEFFILE = +PACKAGES = VCLX35.bpi VCL35.bpi VCLDB35.bpi VCLDBX35.bpi ibsmp35.bpi bcbsmp35.bpi \ + dclocx35.bpi QRPT35.bpi TEEUI35.bpi TEEDB35.bpi TEE35.bpi DSS35.bpi \ + NMFAST35.bpi INETDB35.bpi INET35.bpi VCLMID35.bpi +# --------------------------------------------------------------------------- +PATHCPP = .; +PATHASM = .; +PATHPAS = .; +PATHRC = .; +DEBUGLIBPATH = $(BCB)\lib\debug +RELEASELIBPATH = $(BCB)\lib\release +# --------------------------------------------------------------------------- +CFLAG1 = -WD -O2 -Ve -d -k- -vi -c -tWD +CFLAG2 = -D_NO_VCL;ZLIB_DLL -I$(BCB)\include +CFLAG3 = -ff -5 +PFLAGS = -D_NO_VCL;ZLIB_DLL -U$(BCB)\lib;$(RELEASELIBPATH) -I$(BCB)\include -$I- -v \ + -JPHN -M +RFLAGS = -D_NO_VCL;ZLIB_DLL -i$(BCB)\include +AFLAGS = /i$(BCB)\include /d_NO_VCL /dZLIB_DLL /mx /w2 /zn +LFLAGS = -L$(BCB)\lib;$(RELEASELIBPATH) -aa -Tpd -x -Gi +IFLAGS = -Gn -g +# --------------------------------------------------------------------------- +ALLOBJ = c0d32.obj $(OBJFILES) +ALLRES = $(RESFILES) +ALLLIB = $(LIBFILES) import32.lib cw32mt.lib +# --------------------------------------------------------------------------- +!ifdef IDEOPTIONS + +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=1 +Locale=1040 +CodePage=1252 + +[Version Info Keys] +CompanyName= +FileDescription=DLL (GUI) +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= + +[HistoryLists\hlIncludePath] +Count=1 +Item0=$(BCB)\include + +[HistoryLists\hlLibraryPath] +Count=1 +Item0=$(BCB)\lib + +[HistoryLists\hlConditionals] +Count=1 +Item0=_NO_VCL;ZLIB_DLL + +[Debugging] +DebugSourceDirs= + +[Parameters] +RunParams= +HostApplication= + +!endif + +# --------------------------------------------------------------------------- +# MAKE SECTION +# --------------------------------------------------------------------------- +# This section of the project file is not used by the BCB IDE. It is for +# the benefit of building from the command-line using the MAKE utility. +# --------------------------------------------------------------------------- + +.autodepend +# --------------------------------------------------------------------------- +!if !$d(BCC32) +BCC32 = bcc32 +!endif + +!if !$d(DCC32) +DCC32 = dcc32 +!endif + +!if !$d(TASM32) +TASM32 = tasm32 +!endif + +!if !$d(LINKER) +LINKER = ilink32 +!endif + +!if !$d(BRCC32) +BRCC32 = brcc32 +!endif +# --------------------------------------------------------------------------- +!if $d(PATHCPP) +.PATH.CPP = $(PATHCPP) +.PATH.C = $(PATHCPP) +!endif + +!if $d(PATHPAS) +.PATH.PAS = $(PATHPAS) +!endif + +!if $d(PATHASM) +.PATH.ASM = $(PATHASM) +!endif + +!if $d(PATHRC) +.PATH.RC = $(PATHRC) +!endif +# --------------------------------------------------------------------------- +$(PROJECT): $(OBJFILES) $(RESDEPEN) $(DEFFILE) + $(BCB)\BIN\$(LINKER) @&&! + $(LFLAGS) $(IFLAGS) + + $(ALLOBJ), + + $(PROJECT),, + + $(ALLLIB), + + $(DEFFILE), + + $(ALLRES) +! +# --------------------------------------------------------------------------- +.pas.hpp: + $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } + +.pas.obj: + $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } + +.cpp.obj: + $(BCB)\BIN\$(BCC32) $(CFLAG1) $(CFLAG2) $(CFLAG3) -n$(@D) {$< } + +.c.obj: + $(BCB)\BIN\$(BCC32) $(CFLAG1) $(CFLAG2) $(CFLAG3) -n$(@D) {$< } + +.asm.obj: + $(BCB)\BIN\$(TASM32) $(AFLAGS) $<, $@ + +.rc.res: + $(BCB)\BIN\$(BRCC32) $(RFLAGS) -fo$@ $< +# --------------------------------------------------------------------------- diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi2/zlib32.cpp b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi2/zlib32.cpp new file mode 100644 index 00000000000..7372f6b985f --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/delphi2/zlib32.cpp @@ -0,0 +1,42 @@ + +#include +#pragma hdrstop +#include + + +//--------------------------------------------------------------------------- +// Important note about DLL memory management in a VCL DLL: +// +// +// +// If your DLL uses VCL and exports any functions that pass VCL String objects +// (or structs/classes containing nested Strings) as parameter or function +// results, you will need to build both your DLL project and any EXE projects +// that use your DLL with the dynamic RTL (the RTL DLL). This will change your +// DLL and its calling EXE's to use BORLNDMM.DLL as their memory manager. In +// these cases, the file BORLNDMM.DLL should be deployed along with your DLL +// and the RTL DLL (CP3240MT.DLL). To avoid the requiring BORLNDMM.DLL in +// these situations, pass string information using "char *" or ShortString +// parameters and then link with the static RTL. +// +//--------------------------------------------------------------------------- +USEUNIT("adler32.c"); +USEUNIT("compress.c"); +USEUNIT("crc32.c"); +USEUNIT("deflate.c"); +USEUNIT("gzio.c"); +USEUNIT("infblock.c"); +USEUNIT("infcodes.c"); +USEUNIT("inffast.c"); +USEUNIT("inflate.c"); +USEUNIT("inftrees.c"); +USEUNIT("infutil.c"); +USEUNIT("trees.c"); +USEUNIT("uncompr.c"); +USEUNIT("zutil.c"); +//--------------------------------------------------------------------------- +#pragma argsused +int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*) +{ + return 1; +} diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/iostream/test.cpp b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/iostream/test.cpp new file mode 100644 index 00000000000..7d265b3b5c0 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/iostream/test.cpp @@ -0,0 +1,24 @@ + +#include "zfstream.h" + +int main() { + + // Construct a stream object with this filebuffer. Anything sent + // to this stream will go to standard out. + gzofstream os( 1, ios::out ); + + // This text is getting compressed and sent to stdout. + // To prove this, run 'test | zcat'. + os << "Hello, Mommy" << endl; + + os << setcompressionlevel( Z_NO_COMPRESSION ); + os << "hello, hello, hi, ho!" << endl; + + setcompressionlevel( os, Z_DEFAULT_COMPRESSION ) + << "I'm compressing again" << endl; + + os.close(); + + return 0; + +} diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/iostream/zfstream.cpp b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/iostream/zfstream.cpp new file mode 100644 index 00000000000..a690bbefceb --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/iostream/zfstream.cpp @@ -0,0 +1,329 @@ + +#include +#include "zfstream.h" + +gzfilebuf::gzfilebuf() : + file(NULL), + mode(0), + own_file_descriptor(0) +{ } + +gzfilebuf::~gzfilebuf() { + + sync(); + if ( own_file_descriptor ) + close(); + +} + +gzfilebuf *gzfilebuf::open( const char *name, + int io_mode ) { + + if ( is_open() ) + return NULL; + + char char_mode[10]; + char *p; + memset(char_mode,'\0',10); + p = char_mode; + + if ( io_mode & ios::in ) { + mode = ios::in; + *p++ = 'r'; + } else if ( io_mode & ios::app ) { + mode = ios::app; + *p++ = 'a'; + } else { + mode = ios::out; + *p++ = 'w'; + } + + if ( io_mode & ios::binary ) { + mode |= ios::binary; + *p++ = 'b'; + } + + // Hard code the compression level + if ( io_mode & (ios::out|ios::app )) { + *p++ = '9'; + } + + if ( (file = gzopen(name, char_mode)) == NULL ) + return NULL; + + own_file_descriptor = 1; + + return this; + +} + +gzfilebuf *gzfilebuf::attach( int file_descriptor, + int io_mode ) { + + if ( is_open() ) + return NULL; + + char char_mode[10]; + char *p; + memset(char_mode,'\0',10); + p = char_mode; + + if ( io_mode & ios::in ) { + mode = ios::in; + *p++ = 'r'; + } else if ( io_mode & ios::app ) { + mode = ios::app; + *p++ = 'a'; + } else { + mode = ios::out; + *p++ = 'w'; + } + + if ( io_mode & ios::binary ) { + mode |= ios::binary; + *p++ = 'b'; + } + + // Hard code the compression level + if ( io_mode & (ios::out|ios::app )) { + *p++ = '9'; + } + + if ( (file = gzdopen(file_descriptor, char_mode)) == NULL ) + return NULL; + + own_file_descriptor = 0; + + return this; + +} + +gzfilebuf *gzfilebuf::close() { + + if ( is_open() ) { + + sync(); + gzclose( file ); + file = NULL; + + } + + return this; + +} + +int gzfilebuf::setcompressionlevel( short comp_level ) { + + return gzsetparams(file, comp_level, -2); + +} + +int gzfilebuf::setcompressionstrategy( short comp_strategy ) { + + return gzsetparams(file, -2, comp_strategy); + +} + + +streampos gzfilebuf::seekoff( streamoff off, ios::seek_dir dir, int which ) { + + return streampos(EOF); + +} + +int gzfilebuf::underflow() { + + // If the file hasn't been opened for reading, error. + if ( !is_open() || !(mode & ios::in) ) + return EOF; + + // if a buffer doesn't exists, allocate one. + if ( !base() ) { + + if ( (allocate()) == EOF ) + return EOF; + setp(0,0); + + } else { + + if ( in_avail() ) + return (unsigned char) *gptr(); + + if ( out_waiting() ) { + if ( flushbuf() == EOF ) + return EOF; + } + + } + + // Attempt to fill the buffer. + + int result = fillbuf(); + if ( result == EOF ) { + // disable get area + setg(0,0,0); + return EOF; + } + + return (unsigned char) *gptr(); + +} + +int gzfilebuf::overflow( int c ) { + + if ( !is_open() || !(mode & ios::out) ) + return EOF; + + if ( !base() ) { + if ( allocate() == EOF ) + return EOF; + setg(0,0,0); + } else { + if (in_avail()) { + return EOF; + } + if (out_waiting()) { + if (flushbuf() == EOF) + return EOF; + } + } + + int bl = blen(); + setp( base(), base() + bl); + + if ( c != EOF ) { + + *pptr() = c; + pbump(1); + + } + + return 0; + +} + +int gzfilebuf::sync() { + + if ( !is_open() ) + return EOF; + + if ( out_waiting() ) + return flushbuf(); + + return 0; + +} + +int gzfilebuf::flushbuf() { + + int n; + char *q; + + q = pbase(); + n = pptr() - q; + + if ( gzwrite( file, q, n) < n ) + return EOF; + + setp(0,0); + + return 0; + +} + +int gzfilebuf::fillbuf() { + + int required; + char *p; + + p = base(); + + required = blen(); + + int t = gzread( file, p, required ); + + if ( t <= 0) return EOF; + + setg( base(), base(), base()+t); + + return t; + +} + +gzfilestream_common::gzfilestream_common() : + ios( gzfilestream_common::rdbuf() ) +{ } + +gzfilestream_common::~gzfilestream_common() +{ } + +void gzfilestream_common::attach( int fd, int io_mode ) { + + if ( !buffer.attach( fd, io_mode) ) + clear( ios::failbit | ios::badbit ); + else + clear(); + +} + +void gzfilestream_common::open( const char *name, int io_mode ) { + + if ( !buffer.open( name, io_mode ) ) + clear( ios::failbit | ios::badbit ); + else + clear(); + +} + +void gzfilestream_common::close() { + + if ( !buffer.close() ) + clear( ios::failbit | ios::badbit ); + +} + +gzfilebuf *gzfilestream_common::rdbuf() { + + return &buffer; + +} + +gzifstream::gzifstream() : + ios( gzfilestream_common::rdbuf() ) +{ + clear( ios::badbit ); +} + +gzifstream::gzifstream( const char *name, int io_mode ) : + ios( gzfilestream_common::rdbuf() ) +{ + gzfilestream_common::open( name, io_mode ); +} + +gzifstream::gzifstream( int fd, int io_mode ) : + ios( gzfilestream_common::rdbuf() ) +{ + gzfilestream_common::attach( fd, io_mode ); +} + +gzifstream::~gzifstream() { } + +gzofstream::gzofstream() : + ios( gzfilestream_common::rdbuf() ) +{ + clear( ios::badbit ); +} + +gzofstream::gzofstream( const char *name, int io_mode ) : + ios( gzfilestream_common::rdbuf() ) +{ + gzfilestream_common::open( name, io_mode ); +} + +gzofstream::gzofstream( int fd, int io_mode ) : + ios( gzfilestream_common::rdbuf() ) +{ + gzfilestream_common::attach( fd, io_mode ); +} + +gzofstream::~gzofstream() { } diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/iostream/zfstream.h b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/iostream/zfstream.h new file mode 100644 index 00000000000..c87fa08e9d1 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/iostream/zfstream.h @@ -0,0 +1,142 @@ + +#ifndef _zfstream_h +#define _zfstream_h + +#include +#include "zlib.h" + +class gzfilebuf : public streambuf { + +public: + + gzfilebuf( ); + virtual ~gzfilebuf(); + + gzfilebuf *open( const char *name, int io_mode ); + gzfilebuf *attach( int file_descriptor, int io_mode ); + gzfilebuf *close(); + + int setcompressionlevel( short comp_level ); + int setcompressionstrategy( short comp_strategy ); + + inline int is_open() const { return (file !=NULL); } + + virtual streampos seekoff( streamoff, ios::seek_dir, int ); + + virtual int sync(); + +protected: + + virtual int underflow(); + virtual int overflow( int = EOF ); + +private: + + gzFile file; + short mode; + short own_file_descriptor; + + int flushbuf(); + int fillbuf(); + +}; + +class gzfilestream_common : virtual public ios { + + friend class gzifstream; + friend class gzofstream; + friend gzofstream &setcompressionlevel( gzofstream &, int ); + friend gzofstream &setcompressionstrategy( gzofstream &, int ); + +public: + virtual ~gzfilestream_common(); + + void attach( int fd, int io_mode ); + void open( const char *name, int io_mode ); + void close(); + +protected: + gzfilestream_common(); + +private: + gzfilebuf *rdbuf(); + + gzfilebuf buffer; + +}; + +class gzifstream : public gzfilestream_common, public istream { + +public: + + gzifstream(); + gzifstream( const char *name, int io_mode = ios::in ); + gzifstream( int fd, int io_mode = ios::in ); + + virtual ~gzifstream(); + +}; + +class gzofstream : public gzfilestream_common, public ostream { + +public: + + gzofstream(); + gzofstream( const char *name, int io_mode = ios::out ); + gzofstream( int fd, int io_mode = ios::out ); + + virtual ~gzofstream(); + +}; + +template class gzomanip { + friend gzofstream &operator<<(gzofstream &, const gzomanip &); +public: + gzomanip(gzofstream &(*f)(gzofstream &, T), T v) : func(f), val(v) { } +private: + gzofstream &(*func)(gzofstream &, T); + T val; +}; + +template gzofstream &operator<<(gzofstream &s, + const gzomanip &m) { + return (*m.func)(s, m.val); + +} + +inline gzofstream &setcompressionlevel( gzofstream &s, int l ) { + (s.rdbuf())->setcompressionlevel(l); + return s; +} + +inline gzofstream &setcompressionstrategy( gzofstream &s, int l ) { + (s.rdbuf())->setcompressionstrategy(l); + return s; +} + +inline gzomanip setcompressionlevel(int l) +{ + return gzomanip(&setcompressionlevel,l); +} + +inline gzomanip setcompressionstrategy(int l) +{ + return gzomanip(&setcompressionstrategy,l); +} + +#endif + + + + + + + + + + + + + + + diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/iostream2/zstream.h b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/iostream2/zstream.h new file mode 100644 index 00000000000..43d2332b79b --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/iostream2/zstream.h @@ -0,0 +1,307 @@ +/* + * + * Copyright (c) 1997 + * Christian Michelsen Research AS + * Advanced Computing + * Fantoftvegen 38, 5036 BERGEN, Norway + * http://www.cmr.no + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Christian Michelsen Research AS makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +#ifndef ZSTREAM__H +#define ZSTREAM__H + +/* + * zstream.h - C++ interface to the 'zlib' general purpose compression library + * $Id: zstream.h 1.1 1997-06-25 12:00:56+02 tyge Exp tyge $ + */ + +#include +#include +#include +#include "zlib.h" + +#if defined(_WIN32) +# include +# include +# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) +#else +# define SET_BINARY_MODE(file) +#endif + +class zstringlen { +public: + zstringlen(class izstream&); + zstringlen(class ozstream&, const char*); + size_t value() const { return val.word; } +private: + struct Val { unsigned char byte; size_t word; } val; +}; + +// ----------------------------- izstream ----------------------------- + +class izstream +{ + public: + izstream() : m_fp(0) {} + izstream(FILE* fp) : m_fp(0) { open(fp); } + izstream(const char* name) : m_fp(0) { open(name); } + ~izstream() { close(); } + + /* Opens a gzip (.gz) file for reading. + * open() can be used to read a file which is not in gzip format; + * in this case read() will directly read from the file without + * decompression. errno can be checked to distinguish two error + * cases (if errno is zero, the zlib error is Z_MEM_ERROR). + */ + void open(const char* name) { + if (m_fp) close(); + m_fp = ::gzopen(name, "rb"); + } + + void open(FILE* fp) { + SET_BINARY_MODE(fp); + if (m_fp) close(); + m_fp = ::gzdopen(fileno(fp), "rb"); + } + + /* Flushes all pending input if necessary, closes the compressed file + * and deallocates all the (de)compression state. The return value is + * the zlib error number (see function error() below). + */ + int close() { + int r = ::gzclose(m_fp); + m_fp = 0; return r; + } + + /* Binary read the given number of bytes from the compressed file. + */ + int read(void* buf, size_t len) { + return ::gzread(m_fp, buf, len); + } + + /* Returns the error message for the last error which occurred on the + * given compressed file. errnum is set to zlib error number. If an + * error occurred in the file system and not in the compression library, + * errnum is set to Z_ERRNO and the application may consult errno + * to get the exact error code. + */ + const char* error(int* errnum) { + return ::gzerror(m_fp, errnum); + } + + gzFile fp() { return m_fp; } + + private: + gzFile m_fp; +}; + +/* + * Binary read the given (array of) object(s) from the compressed file. + * If the input file was not in gzip format, read() copies the objects number + * of bytes into the buffer. + * returns the number of uncompressed bytes actually read + * (0 for end of file, -1 for error). + */ +template +inline int read(izstream& zs, T* x, Items items) { + return ::gzread(zs.fp(), x, items*sizeof(T)); +} + +/* + * Binary input with the '>' operator. + */ +template +inline izstream& operator>(izstream& zs, T& x) { + ::gzread(zs.fp(), &x, sizeof(T)); + return zs; +} + + +inline zstringlen::zstringlen(izstream& zs) { + zs > val.byte; + if (val.byte == 255) zs > val.word; + else val.word = val.byte; +} + +/* + * Read length of string + the string with the '>' operator. + */ +inline izstream& operator>(izstream& zs, char* x) { + zstringlen len(zs); + ::gzread(zs.fp(), x, len.value()); + x[len.value()] = '\0'; + return zs; +} + +inline char* read_string(izstream& zs) { + zstringlen len(zs); + char* x = new char[len.value()+1]; + ::gzread(zs.fp(), x, len.value()); + x[len.value()] = '\0'; + return x; +} + +// ----------------------------- ozstream ----------------------------- + +class ozstream +{ + public: + ozstream() : m_fp(0), m_os(0) { + } + ozstream(FILE* fp, int level = Z_DEFAULT_COMPRESSION) + : m_fp(0), m_os(0) { + open(fp, level); + } + ozstream(const char* name, int level = Z_DEFAULT_COMPRESSION) + : m_fp(0), m_os(0) { + open(name, level); + } + ~ozstream() { + close(); + } + + /* Opens a gzip (.gz) file for writing. + * The compression level parameter should be in 0..9 + * errno can be checked to distinguish two error cases + * (if errno is zero, the zlib error is Z_MEM_ERROR). + */ + void open(const char* name, int level = Z_DEFAULT_COMPRESSION) { + char mode[4] = "wb\0"; + if (level != Z_DEFAULT_COMPRESSION) mode[2] = '0'+level; + if (m_fp) close(); + m_fp = ::gzopen(name, mode); + } + + /* open from a FILE pointer. + */ + void open(FILE* fp, int level = Z_DEFAULT_COMPRESSION) { + SET_BINARY_MODE(fp); + char mode[4] = "wb\0"; + if (level != Z_DEFAULT_COMPRESSION) mode[2] = '0'+level; + if (m_fp) close(); + m_fp = ::gzdopen(fileno(fp), mode); + } + + /* Flushes all pending output if necessary, closes the compressed file + * and deallocates all the (de)compression state. The return value is + * the zlib error number (see function error() below). + */ + int close() { + if (m_os) { + ::gzwrite(m_fp, m_os->str(), m_os->pcount()); + delete[] m_os->str(); delete m_os; m_os = 0; + } + int r = ::gzclose(m_fp); m_fp = 0; return r; + } + + /* Binary write the given number of bytes into the compressed file. + */ + int write(const void* buf, size_t len) { + return ::gzwrite(m_fp, (voidp) buf, len); + } + + /* Flushes all pending output into the compressed file. The parameter + * _flush is as in the deflate() function. The return value is the zlib + * error number (see function gzerror below). flush() returns Z_OK if + * the flush_ parameter is Z_FINISH and all output could be flushed. + * flush() should be called only when strictly necessary because it can + * degrade compression. + */ + int flush(int _flush) { + os_flush(); + return ::gzflush(m_fp, _flush); + } + + /* Returns the error message for the last error which occurred on the + * given compressed file. errnum is set to zlib error number. If an + * error occurred in the file system and not in the compression library, + * errnum is set to Z_ERRNO and the application may consult errno + * to get the exact error code. + */ + const char* error(int* errnum) { + return ::gzerror(m_fp, errnum); + } + + gzFile fp() { return m_fp; } + + ostream& os() { + if (m_os == 0) m_os = new ostrstream; + return *m_os; + } + + void os_flush() { + if (m_os && m_os->pcount()>0) { + ostrstream* oss = new ostrstream; + oss->fill(m_os->fill()); + oss->flags(m_os->flags()); + oss->precision(m_os->precision()); + oss->width(m_os->width()); + ::gzwrite(m_fp, m_os->str(), m_os->pcount()); + delete[] m_os->str(); delete m_os; m_os = oss; + } + } + + private: + gzFile m_fp; + ostrstream* m_os; +}; + +/* + * Binary write the given (array of) object(s) into the compressed file. + * returns the number of uncompressed bytes actually written + * (0 in case of error). + */ +template +inline int write(ozstream& zs, const T* x, Items items) { + return ::gzwrite(zs.fp(), (voidp) x, items*sizeof(T)); +} + +/* + * Binary output with the '<' operator. + */ +template +inline ozstream& operator<(ozstream& zs, const T& x) { + ::gzwrite(zs.fp(), (voidp) &x, sizeof(T)); + return zs; +} + +inline zstringlen::zstringlen(ozstream& zs, const char* x) { + val.byte = 255; val.word = ::strlen(x); + if (val.word < 255) zs < (val.byte = val.word); + else zs < val; +} + +/* + * Write length of string + the string with the '<' operator. + */ +inline ozstream& operator<(ozstream& zs, const char* x) { + zstringlen len(zs, x); + ::gzwrite(zs.fp(), (voidp) x, len.value()); + return zs; +} + +#ifdef _MSC_VER +inline ozstream& operator<(ozstream& zs, char* const& x) { + return zs < (const char*) x; +} +#endif + +/* + * Ascii write with the << operator; + */ +template +inline ostream& operator<<(ozstream& zs, const T& x) { + zs.os_flush(); + return zs.os() << x; +} + +#endif diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/iostream2/zstream_test.cpp b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/iostream2/zstream_test.cpp new file mode 100644 index 00000000000..5bbd56c3ad8 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/iostream2/zstream_test.cpp @@ -0,0 +1,25 @@ +#include "zstream.h" +#include +#include +#include + +void main() { + char h[256] = "Hello"; + char* g = "Goodbye"; + ozstream out("temp.gz"); + out < "This works well" < h < g; + out.close(); + + izstream in("temp.gz"); // read it back + char *x = read_string(in), *y = new char[256], z[256]; + in > y > z; + in.close(); + cout << x << endl << y << endl << z << endl; + + out.open("temp.gz"); // try ascii output; zcat temp.gz to see the results + out << setw(50) << setfill('#') << setprecision(20) << x << endl << y << endl << z << endl; + out << z << endl << y << endl << x << endl; + out << 1.1234567890123456789 << endl; + + delete[] x; delete[] y; +} diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/ChangeLogUnzip b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/ChangeLogUnzip new file mode 100644 index 00000000000..9987c543cdc --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/ChangeLogUnzip @@ -0,0 +1,38 @@ +Change in 0.15: (19 Mar 98) +- fix memory leak in minizip.c + +Change in 0.14: (10 Mar 98) +- fix bugs in minizip.c sample for zipping big file +- fix problem in month in date handling +- fix bug in unzlocal_GetCurrentFileInfoInternal in unzip.c for + comment handling + +Change in 0.13: (6 Mar 98) +- fix bugs in zip.c +- add real minizip sample + +Change in 0.12: (4 Mar 98) +- add zip.c and zip.h for creates .zip file +- fix change_file_date in miniunz.c for Unix (Jean-loup Gailly) +- fix miniunz.c for file without specific record for directory + +Change in 0.11: (3 Mar 98) +- fix bug in unzGetCurrentFileInfo for get extra field and comment +- enhance miniunz sample, remove the bad unztst.c sample + +Change in 0.10: (2 Mar 98) +- fix bug in unzReadCurrentFile +- rename unzip* to unz* function and structure +- remove Windows-like hungary notation variable name +- modify some structure in unzip.h +- add somes comment in source +- remove unzipGetcCurrentFile function +- replace ZUNZEXPORT by ZEXPORT +- add unzGetLocalExtrafield for get the local extrafield info +- add a new sample, miniunz.c + +Change in 0.4: (25 Feb 98) +- suppress the type unzipFileInZip. + Only on file in the zipfile can be open at the same time +- fix somes typo in code +- added tm_unz structure in unzip_file_info (date/time in readable format) diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/Makefile b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/Makefile new file mode 100644 index 00000000000..a1dfc161437 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/Makefile @@ -0,0 +1,25 @@ +CC=cc +CFLAGS=-O -I../.. + +UNZ_OBJS = miniunz.o unzip.o ../../libz.a +ZIP_OBJS = minizip.o zip.o ../../libz.a + +.c.o: + $(CC) -c $(CFLAGS) $*.c + +all: miniunz minizip + +miniunz: $(UNZ_OBJS) + $(CC) $(CFLAGS) -o $@ $(UNZ_OBJS) + +minizip: $(ZIP_OBJS) + $(CC) $(CFLAGS) -o $@ $(ZIP_OBJS) + +test: miniunz minizip + ./minizip test readme.txt + ./miniunz -l test.zip + mv readme.txt readme.old + ./miniunz test.zip + +clean: + /bin/rm -f *.o *~ minizip miniunz diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/miniunz.c b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/miniunz.c new file mode 100644 index 00000000000..f3b7832878f --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/miniunz.c @@ -0,0 +1,508 @@ +#include +#include +#include +#include +#include +#include + +#ifdef unix +# include +# include +#else +# include +# include +#endif + +#include "unzip.h" + +#define CASESENSITIVITY (0) +#define WRITEBUFFERSIZE (8192) + +/* + mini unzip, demo of unzip package + + usage : + Usage : miniunz [-exvlo] file.zip [file_to_extract] + + list the file in the zipfile, and print the content of FILE_ID.ZIP or README.TXT + if it exists +*/ + + +/* change_file_date : change the date/time of a file + filename : the filename of the file where date/time must be modified + dosdate : the new date at the MSDos format (4 bytes) + tmu_date : the SAME new date at the tm_unz format */ +void change_file_date(filename,dosdate,tmu_date) + const char *filename; + uLong dosdate; + tm_unz tmu_date; +{ +#ifdef WIN32 + HANDLE hFile; + FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite; + + hFile = CreateFile(filename,GENERIC_READ | GENERIC_WRITE, + 0,NULL,OPEN_EXISTING,0,NULL); + GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite); + DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal); + LocalFileTimeToFileTime(&ftLocal,&ftm); + SetFileTime(hFile,&ftm,&ftLastAcc,&ftm); + CloseHandle(hFile); +#else +#ifdef unix + struct utimbuf ut; + struct tm newdate; + newdate.tm_sec = tmu_date.tm_sec; + newdate.tm_min=tmu_date.tm_min; + newdate.tm_hour=tmu_date.tm_hour; + newdate.tm_mday=tmu_date.tm_mday; + newdate.tm_mon=tmu_date.tm_mon; + if (tmu_date.tm_year > 1900) + newdate.tm_year=tmu_date.tm_year - 1900; + else + newdate.tm_year=tmu_date.tm_year ; + newdate.tm_isdst=-1; + + ut.actime=ut.modtime=mktime(&newdate); + utime(filename,&ut); +#endif +#endif +} + + +/* mymkdir and change_file_date are not 100 % portable + As I don't know well Unix, I wait feedback for the unix portion */ + +int mymkdir(dirname) + const char* dirname; +{ + int ret=0; +#ifdef WIN32 + ret = mkdir(dirname); +#else +#ifdef unix + ret = mkdir (dirname,0775); +#endif +#endif + return ret; +} + +int makedir (newdir) + char *newdir; +{ + char *buffer ; + char *p; + int len = strlen(newdir); + + if (len <= 0) + return 0; + + buffer = (char*)malloc(len+1); + strcpy(buffer,newdir); + + if (buffer[len-1] == '/') { + buffer[len-1] = '\0'; + } + if (mymkdir(buffer) == 0) + { + free(buffer); + return 1; + } + + p = buffer+1; + while (1) + { + char hold; + + while(*p && *p != '\\' && *p != '/') + p++; + hold = *p; + *p = 0; + if ((mymkdir(buffer) == -1) && (errno == ENOENT)) + { + printf("couldn't create directory %s\n",buffer); + free(buffer); + return 0; + } + if (hold == 0) + break; + *p++ = hold; + } + free(buffer); + return 1; +} + +void do_banner() +{ + printf("MiniUnz 0.15, demo of zLib + Unz package written by Gilles Vollant\n"); + printf("more info at http://wwww.winimage/zLibDll/unzip.htm\n\n"); +} + +void do_help() +{ + printf("Usage : miniunz [-exvlo] file.zip [file_to_extract]\n\n") ; +} + + +int do_list(uf) + unzFile uf; +{ + uLong i; + unz_global_info gi; + int err; + + err = unzGetGlobalInfo (uf,&gi); + if (err!=UNZ_OK) + printf("error %d with zipfile in unzGetGlobalInfo \n",err); + printf(" Length Method Size Ratio Date Time CRC-32 Name\n"); + printf(" ------ ------ ---- ----- ---- ---- ------ ----\n"); + for (i=0;i0) + ratio = (file_info.compressed_size*100)/file_info.uncompressed_size; + + if (file_info.compression_method==0) + string_method="Stored"; + else + if (file_info.compression_method==Z_DEFLATED) + { + uInt iLevel=(uInt)((file_info.flag & 0x6)/2); + if (iLevel==0) + string_method="Defl:N"; + else if (iLevel==1) + string_method="Defl:X"; + else if ((iLevel==2) || (iLevel==3)) + string_method="Defl:F"; /* 2:fast , 3 : extra fast*/ + } + else + string_method="Unkn. "; + + printf("%7lu %6s %7lu %3lu%% %2.2lu-%2.2lu-%2.2lu %2.2lu:%2.2lu %8.8lx %s\n", + file_info.uncompressed_size,string_method,file_info.compressed_size, + ratio, + (uLong)file_info.tmu_date.tm_mon + 1, + (uLong)file_info.tmu_date.tm_mday, + (uLong)file_info.tmu_date.tm_year % 100, + (uLong)file_info.tmu_date.tm_hour,(uLong)file_info.tmu_date.tm_min, + (uLong)file_info.crc,filename_inzip); + if ((i+1)='a') && (rep<='z')) + rep -= 0x20; + } + while ((rep!='Y') && (rep!='N') && (rep!='A')); + } + + if (rep == 'N') + skip = 1; + + if (rep == 'A') + *popt_overwrite=1; + } + + if ((skip==0) && (err==UNZ_OK)) + { + fout=fopen(write_filename,"wb"); + + /* some zipfile don't contain directory alone before file */ + if ((fout==NULL) && ((*popt_extract_without_path)==0) && + (filename_withoutpath!=(char*)filename_inzip)) + { + char c=*(filename_withoutpath-1); + *(filename_withoutpath-1)='\0'; + makedir(write_filename); + *(filename_withoutpath-1)=c; + fout=fopen(write_filename,"wb"); + } + + if (fout==NULL) + { + printf("error opening %s\n",write_filename); + } + } + + if (fout!=NULL) + { + printf(" extracting: %s\n",write_filename); + + do + { + err = unzReadCurrentFile(uf,buf,size_buf); + if (err<0) + { + printf("error %d with zipfile in unzReadCurrentFile\n",err); + break; + } + if (err>0) + if (fwrite(buf,err,1,fout)!=1) + { + printf("error in writing extracted file\n"); + err=UNZ_ERRNO; + break; + } + } + while (err>0); + fclose(fout); + if (err==0) + change_file_date(write_filename,file_info.dosDate, + file_info.tmu_date); + } + + if (err==UNZ_OK) + { + err = unzCloseCurrentFile (uf); + if (err!=UNZ_OK) + { + printf("error %d with zipfile in unzCloseCurrentFile\n",err); + } + } + else + unzCloseCurrentFile(uf); /* don't lose the error */ + } + + free(buf); + return err; +} + + +int do_extract(uf,opt_extract_without_path,opt_overwrite) + unzFile uf; + int opt_extract_without_path; + int opt_overwrite; +{ + uLong i; + unz_global_info gi; + int err; + FILE* fout=NULL; + + err = unzGetGlobalInfo (uf,&gi); + if (err!=UNZ_OK) + printf("error %d with zipfile in unzGetGlobalInfo \n",err); + + for (i=0;i +#include +#include +#include +#include +#include + +#ifdef unix +# include +# include +# include +# include +#else +# include +# include +#endif + +#include "zip.h" + + +#define WRITEBUFFERSIZE (16384) +#define MAXFILENAME (256) + +#ifdef WIN32 +uLong filetime(f, tmzip, dt) + char *f; /* name of file to get info on */ + tm_zip *tmzip; /* return value: access, modific. and creation times */ + uLong *dt; /* dostime */ +{ + int ret = 0; + { + FILETIME ftLocal; + HANDLE hFind; + WIN32_FIND_DATA ff32; + + hFind = FindFirstFile(f,&ff32); + if (hFind != INVALID_HANDLE_VALUE) + { + FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal); + FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0); + FindClose(hFind); + ret = 1; + } + } + return ret; +} +#else +#ifdef unix +uLong filetime(f, tmzip, dt) + char *f; /* name of file to get info on */ + tm_zip *tmzip; /* return value: access, modific. and creation times */ + uLong *dt; /* dostime */ +{ + int ret=0; + struct stat s; /* results of stat() */ + struct tm* filedate; + time_t tm_t=0; + + if (strcmp(f,"-")!=0) + { + char name[MAXFILENAME]; + int len = strlen(f); + strcpy(name, f); + if (name[len - 1] == '/') + name[len - 1] = '\0'; + /* not all systems allow stat'ing a file with / appended */ + if (stat(name,&s)==0) + { + tm_t = s.st_mtime; + ret = 1; + } + } + filedate = localtime(&tm_t); + + tmzip->tm_sec = filedate->tm_sec; + tmzip->tm_min = filedate->tm_min; + tmzip->tm_hour = filedate->tm_hour; + tmzip->tm_mday = filedate->tm_mday; + tmzip->tm_mon = filedate->tm_mon ; + tmzip->tm_year = filedate->tm_year; + + return ret; +} +#else +uLong filetime(f, tmzip, dt) + char *f; /* name of file to get info on */ + tm_zip *tmzip; /* return value: access, modific. and creation times */ + uLong *dt; /* dostime */ +{ + return 0; +} +#endif +#endif + + + + +int check_exist_file(filename) + const char* filename; +{ + FILE* ftestexist; + int ret = 1; + ftestexist = fopen(filename,"rb"); + if (ftestexist==NULL) + ret = 0; + else + fclose(ftestexist); + return ret; +} + +void do_banner() +{ + printf("MiniZip 0.15, demo of zLib + Zip package written by Gilles Vollant\n"); + printf("more info at http://wwww.winimage/zLibDll/unzip.htm\n\n"); +} + +void do_help() +{ + printf("Usage : minizip [-o] file.zip [files_to_add]\n\n") ; +} + +int main(argc,argv) + int argc; + char *argv[]; +{ + int i; + int opt_overwrite=0; + int opt_compress_level=Z_DEFAULT_COMPRESSION; + int zipfilenamearg = 0; + char filename_try[MAXFILENAME]; + int zipok; + int err=0; + int size_buf=0; + void* buf=NULL, + + + do_banner(); + if (argc==1) + { + do_help(); + exit(0); + return 0; + } + else + { + for (i=1;i='0') && (c<='9')) + opt_compress_level = c-'0'; + } + } + else + if (zipfilenamearg == 0) + zipfilenamearg = i ; + } + } + + size_buf = WRITEBUFFERSIZE; + buf = (void*)malloc(size_buf); + if (buf==NULL) + { + printf("Error allocating memory\n"); + return ZIP_INTERNALERROR; + } + + if (zipfilenamearg==0) + zipok=0; + else + { + int i,len; + int dot_found=0; + + zipok = 1 ; + strcpy(filename_try,argv[zipfilenamearg]); + len=strlen(filename_try); + for (i=0;i='a') && (rep<='z')) + rep -= 0x20; + } + while ((rep!='Y') && (rep!='N')); + if (rep=='N') + zipok = 0; + } + } + + if (zipok==1) + { + zipFile zf; + int errclose; + zf = zipOpen(filename_try,0); + if (zf == NULL) + { + printf("error opening %s\n",filename_try); + err= ZIP_ERRNO; + } + else + printf("creating %s\n",filename_try); + + for (i=zipfilenamearg+1;(i0) + { + err = zipWriteInFileInZip (zf,buf,size_read); + if (err<0) + { + printf("error in writing %s in the zipfile\n", + filenameinzip); + } + + } + } while ((err == ZIP_OK) && (size_read>0)); + + fclose(fin); + if (err<0) + err=ZIP_ERRNO; + else + { + err = zipCloseFileInZip(zf); + if (err!=ZIP_OK) + printf("error in closing %s in the zipfile\n", + filenameinzip); + } + } + } + errclose = zipClose(zf,NULL); + if (errclose != ZIP_OK) + printf("error in closing %s\n",filename_try); + } + + free(buf); + exit(0); + return 0; /* to avoid warning */ +} diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/readme.txt b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/readme.txt new file mode 100644 index 00000000000..1fc023c720b --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/readme.txt @@ -0,0 +1,37 @@ + +UnZip 0.15 additionnal library + + + This unzip package allow extract file from .ZIP file, compatible with +PKZip 2.04g, WinZip, InfoZip tools and compatible. + + Multi volume ZipFile (span) are not supported, and old compression used by old +PKZip 1.x are not supported. + +See probdesc.zip from PKWare for specification of .ZIP format. + +What is Unzip + The Zlib library support the deflate compression and the creation of gzip (.gz) +file. Zlib is free and small. + The .Zip format, which can contain several compressed files (.gz can containt +only one file) is a very popular format. This is why I've written a package for reading file compressed in Zipfile. + +Using Unzip package + +You need source of Zlib (get zlib111.zip and read zlib.h). +Get unzlb015.zip and read unzip.h (whith documentation of unzip functions) + +The Unzip package is only two file : unzip.h and unzip.c. But it use the Zlib + files. +unztst.c is a simple sample program, which list file in a zipfile and display + README.TXT or FILE_ID.DIZ (if these files are found). +miniunz.c is a mini unzip program. + +I'm also currenlyt writing a zipping portion (zip.h, zip.c and test with minizip.c) + +Please email me for feedback. +I hope my source is compatible with Unix system, but I need your help for be sure + +Latest revision : Mar 04th, 1998 + +Check http://www.winimage.com/zLibDll/unzip.html for up to date info. diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/unzip.c b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/unzip.c new file mode 100644 index 00000000000..ff71a474da1 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/unzip.c @@ -0,0 +1,1294 @@ +/* unzip.c -- IO on .zip files using zlib + Version 0.15 beta, Mar 19th, 1998, + + Read unzip.h for more info +*/ + + +#include +#include +#include +#include "zlib.h" +#include "unzip.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + + + +#if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) && \ + !defined(CASESENSITIVITYDEFAULT_NO) +#define CASESENSITIVITYDEFAULT_NO +#endif + + +#ifndef UNZ_BUFSIZE +#define UNZ_BUFSIZE (16384) +#endif + +#ifndef UNZ_MAXFILENAMEINZIP +#define UNZ_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p);} +#endif + +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) + + +/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ + +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif + +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +const char unz_copyright[] = + " unzip 0.15 Copyright 1998 Gilles Vollant "; + +/* unz_file_info_interntal contain internal info about a file in zipfile*/ +typedef struct unz_file_info_internal_s +{ + uLong offset_curfile;/* relative offset of local header 4 bytes */ +} unz_file_info_internal; + + +/* file_in_zip_read_info_s contain internal information about a file in zipfile, + when reading and decompress it */ +typedef struct +{ + char *read_buffer; /* internal buffer for compressed data */ + z_stream stream; /* zLib stream structure for inflate */ + + uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ + uLong stream_initialised; /* flag set if stream structure is initialised*/ + + uLong offset_local_extrafield;/* offset of the local extra field */ + uInt size_local_extrafield;/* size of the local extra field */ + uLong pos_local_extrafield; /* position in the local extra field in read*/ + + uLong crc32; /* crc32 of all data uncompressed */ + uLong crc32_wait; /* crc32 we must obtain after decompress all */ + uLong rest_read_compressed; /* number of byte to be decompressed */ + uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/ + FILE* file; /* io structore of the zipfile */ + uLong compression_method; /* compression method (0==store) */ + uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ +} file_in_zip_read_info_s; + + +/* unz_s contain internal information about the zipfile +*/ +typedef struct +{ + FILE* file; /* io structore of the zipfile */ + unz_global_info gi; /* public global information */ + uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + uLong num_file; /* number of the current file in the zipfile*/ + uLong pos_in_central_dir; /* pos of the current file in the central dir*/ + uLong current_file_ok; /* flag about the usability of the current file*/ + uLong central_pos; /* position of the beginning of the central dir*/ + + uLong size_central_dir; /* size of the central directory */ + uLong offset_central_dir; /* offset of start of central directory with + respect to the starting disk number */ + + unz_file_info cur_file_info; /* public info about the current file in zip*/ + unz_file_info_internal cur_file_info_internal; /* private info about it*/ + file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current + file if we are decompressing it */ +} unz_s; + + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been sucessfully opened for reading. +*/ + + +local int unzlocal_getByte(fin,pi) + FILE *fin; + int *pi; +{ + unsigned char c; + int err = fread(&c, 1, 1, fin); + if (err==1) + { + *pi = (int)c; + return UNZ_OK; + } + else + { + if (ferror(fin)) + return UNZ_ERRNO; + else + return UNZ_EOF; + } +} + + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets +*/ +local int unzlocal_getShort (fin,pX) + FILE* fin; + uLong *pX; +{ + uLong x ; + int i; + int err; + + err = unzlocal_getByte(fin,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unzlocal_getByte(fin,&i); + x += ((uLong)i)<<8; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int unzlocal_getLong (fin,pX) + FILE* fin; + uLong *pX; +{ + uLong x ; + int i; + int err; + + err = unzlocal_getByte(fin,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unzlocal_getByte(fin,&i); + x += ((uLong)i)<<8; + + if (err==UNZ_OK) + err = unzlocal_getByte(fin,&i); + x += ((uLong)i)<<16; + + if (err==UNZ_OK) + err = unzlocal_getByte(fin,&i); + x += ((uLong)i)<<24; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + + +/* My own strcmpi / strcasecmp */ +local int strcmpcasenosensitive_internal (fileName1,fileName2) + const char* fileName1; + const char* fileName2; +{ + for (;;) + { + char c1=*(fileName1++); + char c2=*(fileName2++); + if ((c1>='a') && (c1<='z')) + c1 -= 0x20; + if ((c2>='a') && (c2<='z')) + c2 -= 0x20; + if (c1=='\0') + return ((c2=='\0') ? 0 : -1); + if (c2=='\0') + return 1; + if (c1c2) + return 1; + } +} + + +#ifdef CASESENSITIVITYDEFAULT_NO +#define CASESENSITIVITYDEFAULTVALUE 2 +#else +#define CASESENSITIVITYDEFAULTVALUE 1 +#endif + +#ifndef STRCMPCASENOSENTIVEFUNCTION +#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal +#endif + +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) + +*/ +extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity) + const char* fileName1; + const char* fileName2; + int iCaseSensitivity; +{ + if (iCaseSensitivity==0) + iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; + + if (iCaseSensitivity==1) + return strcmp(fileName1,fileName2); + + return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); +} + +#define BUFREADCOMMENT (0x400) + +/* + Locate the Central directory of a zipfile (at the end, just before + the global comment) +*/ +local uLong unzlocal_SearchCentralDir(fin) + FILE *fin; +{ + unsigned char* buf; + uLong uSizeFile; + uLong uBackRead; + uLong uMaxBack=0xffff; /* maximum size of global comment */ + uLong uPosFound=0; + + if (fseek(fin,0,SEEK_END) != 0) + return 0; + + + uSizeFile = ftell( fin ); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); + if (fseek(fin,uReadPos,SEEK_SET)!=0) + break; + + if (fread(buf,(uInt)uReadSize,1,fin)!=1) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + return uPosFound; +} + +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows NT computer "c:\\test\\zlib109.zip" or on an Unix computer + "zlib/zlib109.zip". + If the zipfile cannot be opened (file don't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ +extern unzFile ZEXPORT unzOpen (path) + const char *path; +{ + unz_s us; + unz_s *s; + uLong central_pos,uL; + FILE * fin ; + + uLong number_disk; /* number of the current dist, used for + spaning ZIP, unsupported, always 0*/ + uLong number_disk_with_CD; /* number the the disk with central dir, used + for spaning ZIP, unsupported, always 0*/ + uLong number_entry_CD; /* total number of entries in + the central dir + (same than number_entry on nospan) */ + + int err=UNZ_OK; + + if (unz_copyright[0]!=' ') + return NULL; + + fin=fopen(path,"rb"); + if (fin==NULL) + return NULL; + + central_pos = unzlocal_SearchCentralDir(fin); + if (central_pos==0) + err=UNZ_ERRNO; + + if (fseek(fin,central_pos,SEEK_SET)!=0) + err=UNZ_ERRNO; + + /* the signature, already checked */ + if (unzlocal_getLong(fin,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of this disk */ + if (unzlocal_getShort(fin,&number_disk)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of the disk with the start of the central directory */ + if (unzlocal_getShort(fin,&number_disk_with_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir on this disk */ + if (unzlocal_getShort(fin,&us.gi.number_entry)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir */ + if (unzlocal_getShort(fin,&number_entry_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + if ((number_entry_CD!=us.gi.number_entry) || + (number_disk_with_CD!=0) || + (number_disk!=0)) + err=UNZ_BADZIPFILE; + + /* size of the central directory */ + if (unzlocal_getLong(fin,&us.size_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* offset of start of central directory with respect to the + starting disk number */ + if (unzlocal_getLong(fin,&us.offset_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* zipfile comment length */ + if (unzlocal_getShort(fin,&us.gi.size_comment)!=UNZ_OK) + err=UNZ_ERRNO; + + if ((central_pospfile_in_zip_read!=NULL) + unzCloseCurrentFile(file); + + fclose(s->file); + TRYFREE(s); + return UNZ_OK; +} + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ +extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info) + unzFile file; + unz_global_info *pglobal_info; +{ + unz_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + *pglobal_info=s->gi; + return UNZ_OK; +} + + +/* + Translate date/time from Dos format to tm_unz (readable more easilty) +*/ +local void unzlocal_DosDateToTmuDate (ulDosDate, ptm) + uLong ulDosDate; + tm_unz* ptm; +{ + uLong uDate; + uDate = (uLong)(ulDosDate>>16); + ptm->tm_mday = (uInt)(uDate&0x1f) ; + ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; + ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; + + ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); + ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; + ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; +} + +/* + Get Info about the current file in the zipfile, with internal only info +*/ +local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file, + unz_file_info *pfile_info, + unz_file_info_internal + *pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); + +local int unzlocal_GetCurrentFileInfoInternal (file, + pfile_info, + pfile_info_internal, + szFileName, fileNameBufferSize, + extraField, extraFieldBufferSize, + szComment, commentBufferSize) + unzFile file; + unz_file_info *pfile_info; + unz_file_info_internal *pfile_info_internal; + char *szFileName; + uLong fileNameBufferSize; + void *extraField; + uLong extraFieldBufferSize; + char *szComment; + uLong commentBufferSize; +{ + unz_s* s; + unz_file_info file_info; + unz_file_info_internal file_info_internal; + int err=UNZ_OK; + uLong uMagic; + long lSeek=0; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (fseek(s->file,s->pos_in_central_dir+s->byte_before_the_zipfile,SEEK_SET)!=0) + err=UNZ_ERRNO; + + + /* we check the magic */ + if (err==UNZ_OK) + if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x02014b50) + err=UNZ_BADZIPFILE; + + if (unzlocal_getShort(s->file,&file_info.version) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.version_needed) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.flag) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.compression_method) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(s->file,&file_info.dosDate) != UNZ_OK) + err=UNZ_ERRNO; + + unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); + + if (unzlocal_getLong(s->file,&file_info.crc) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(s->file,&file_info.compressed_size) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(s->file,&file_info.uncompressed_size) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.size_filename) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.size_file_extra) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.size_file_comment) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.disk_num_start) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.internal_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(s->file,&file_info.external_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(s->file,&file_info_internal.offset_curfile) != UNZ_OK) + err=UNZ_ERRNO; + + lSeek+=file_info.size_filename; + if ((err==UNZ_OK) && (szFileName!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_filename0) && (fileNameBufferSize>0)) + if (fread(szFileName,(uInt)uSizeRead,1,s->file)!=1) + err=UNZ_ERRNO; + lSeek -= uSizeRead; + } + + + if ((err==UNZ_OK) && (extraField!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_extrafile,lSeek,SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) + if (fread(extraField,(uInt)uSizeRead,1,s->file)!=1) + err=UNZ_ERRNO; + lSeek += file_info.size_file_extra - uSizeRead; + } + else + lSeek+=file_info.size_file_extra; + + + if ((err==UNZ_OK) && (szComment!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_commentfile,lSeek,SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + if ((file_info.size_file_comment>0) && (commentBufferSize>0)) + if (fread(szComment,(uInt)uSizeRead,1,s->file)!=1) + err=UNZ_ERRNO; + lSeek+=file_info.size_file_comment - uSizeRead; + } + else + lSeek+=file_info.size_file_comment; + + if ((err==UNZ_OK) && (pfile_info!=NULL)) + *pfile_info=file_info; + + if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) + *pfile_info_internal=file_info_internal; + + return err; +} + + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. +*/ +extern int ZEXPORT unzGetCurrentFileInfo (file, + pfile_info, + szFileName, fileNameBufferSize, + extraField, extraFieldBufferSize, + szComment, commentBufferSize) + unzFile file; + unz_file_info *pfile_info; + char *szFileName; + uLong fileNameBufferSize; + void *extraField; + uLong extraFieldBufferSize; + char *szComment; + uLong commentBufferSize; +{ + return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL, + szFileName,fileNameBufferSize, + extraField,extraFieldBufferSize, + szComment,commentBufferSize); +} + +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ +extern int ZEXPORT unzGoToFirstFile (file) + unzFile file; +{ + int err=UNZ_OK; + unz_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + s->pos_in_central_dir=s->offset_central_dir; + s->num_file=0; + err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + + +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ +extern int ZEXPORT unzGoToNextFile (file) + unzFile file; +{ + unz_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + if (s->num_file+1==s->gi.number_entry) + return UNZ_END_OF_LIST_OF_FILE; + + s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + + s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; + s->num_file++; + err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + + +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzipStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ +extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity) + unzFile file; + const char *szFileName; + int iCaseSensitivity; +{ + unz_s* s; + int err; + + + uLong num_fileSaved; + uLong pos_in_central_dirSaved; + + + if (file==NULL) + return UNZ_PARAMERROR; + + if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) + return UNZ_PARAMERROR; + + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + num_fileSaved = s->num_file; + pos_in_central_dirSaved = s->pos_in_central_dir; + + err = unzGoToFirstFile(file); + + while (err == UNZ_OK) + { + char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; + unzGetCurrentFileInfo(file,NULL, + szCurrentFileName,sizeof(szCurrentFileName)-1, + NULL,0,NULL,0); + if (unzStringFileNameCompare(szCurrentFileName, + szFileName,iCaseSensitivity)==0) + return UNZ_OK; + err = unzGoToNextFile(file); + } + + s->num_file = num_fileSaved ; + s->pos_in_central_dir = pos_in_central_dirSaved ; + return err; +} + + +/* + Read the local header of the current zipfile + Check the coherency of the local header and info in the end of central + directory about this file + store in *piSizeVar the size of extra info in local header + (filename and size of extra field data) +*/ +local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar, + poffset_local_extrafield, + psize_local_extrafield) + unz_s* s; + uInt* piSizeVar; + uLong *poffset_local_extrafield; + uInt *psize_local_extrafield; +{ + uLong uMagic,uData,uFlags; + uLong size_filename; + uLong size_extra_field; + int err=UNZ_OK; + + *piSizeVar = 0; + *poffset_local_extrafield = 0; + *psize_local_extrafield = 0; + + if (fseek(s->file,s->cur_file_info_internal.offset_curfile + + s->byte_before_the_zipfile,SEEK_SET)!=0) + return UNZ_ERRNO; + + + if (err==UNZ_OK) + if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x04034b50) + err=UNZ_BADZIPFILE; + + if (unzlocal_getShort(s->file,&uData) != UNZ_OK) + err=UNZ_ERRNO; +/* + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) + err=UNZ_BADZIPFILE; +*/ + if (unzlocal_getShort(s->file,&uFlags) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&uData) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) + err=UNZ_BADZIPFILE; + + if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* date/time */ + err=UNZ_ERRNO; + + if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* crc */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size compr */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size uncompr */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + + if (unzlocal_getShort(s->file,&size_filename) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) + err=UNZ_BADZIPFILE; + + *piSizeVar += (uInt)size_filename; + + if (unzlocal_getShort(s->file,&size_extra_field) != UNZ_OK) + err=UNZ_ERRNO; + *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + + SIZEZIPLOCALHEADER + size_filename; + *psize_local_extrafield = (uInt)size_extra_field; + + *piSizeVar += (uInt)size_extra_field; + + return err; +} + +/* + Open for reading data the current file in the zipfile. + If there is no error and the file is opened, the return value is UNZ_OK. +*/ +extern int ZEXPORT unzOpenCurrentFile (file) + unzFile file; +{ + int err=UNZ_OK; + int Store; + uInt iSizeVar; + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + uLong offset_local_extrafield; /* offset of the local extra field */ + uInt size_local_extrafield; /* size of the local extra field */ + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_PARAMERROR; + + if (s->pfile_in_zip_read != NULL) + unzCloseCurrentFile(file); + + if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar, + &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) + return UNZ_BADZIPFILE; + + pfile_in_zip_read_info = (file_in_zip_read_info_s*) + ALLOC(sizeof(file_in_zip_read_info_s)); + if (pfile_in_zip_read_info==NULL) + return UNZ_INTERNALERROR; + + pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE); + pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; + pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; + pfile_in_zip_read_info->pos_local_extrafield=0; + + if (pfile_in_zip_read_info->read_buffer==NULL) + { + TRYFREE(pfile_in_zip_read_info); + return UNZ_INTERNALERROR; + } + + pfile_in_zip_read_info->stream_initialised=0; + + if ((s->cur_file_info.compression_method!=0) && + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + Store = s->cur_file_info.compression_method==0; + + pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; + pfile_in_zip_read_info->crc32=0; + pfile_in_zip_read_info->compression_method = + s->cur_file_info.compression_method; + pfile_in_zip_read_info->file=s->file; + pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; + + pfile_in_zip_read_info->stream.total_out = 0; + + if (!Store) + { + pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; + pfile_in_zip_read_info->stream.zfree = (free_func)0; + pfile_in_zip_read_info->stream.opaque = (voidpf)0; + + err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); + if (err == Z_OK) + pfile_in_zip_read_info->stream_initialised=1; + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. + * In unzip, i don't wait absolutely Z_STREAM_END because I known the + * size of both compressed and uncompressed data + */ + } + pfile_in_zip_read_info->rest_read_compressed = + s->cur_file_info.compressed_size ; + pfile_in_zip_read_info->rest_read_uncompressed = + s->cur_file_info.uncompressed_size ; + + + pfile_in_zip_read_info->pos_in_zipfile = + s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + + iSizeVar; + + pfile_in_zip_read_info->stream.avail_in = (uInt)0; + + + s->pfile_in_zip_read = pfile_in_zip_read_info; + return UNZ_OK; +} + + +/* + Read bytes from the current file. + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ +extern int ZEXPORT unzReadCurrentFile (file, buf, len) + unzFile file; + voidp buf; + unsigned len; +{ + int err=UNZ_OK; + uInt iRead = 0; + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if ((pfile_in_zip_read_info->read_buffer == NULL)) + return UNZ_END_OF_LIST_OF_FILE; + if (len==0) + return 0; + + pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; + + pfile_in_zip_read_info->stream.avail_out = (uInt)len; + + if (len>pfile_in_zip_read_info->rest_read_uncompressed) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_uncompressed; + + while (pfile_in_zip_read_info->stream.avail_out>0) + { + if ((pfile_in_zip_read_info->stream.avail_in==0) && + (pfile_in_zip_read_info->rest_read_compressed>0)) + { + uInt uReadThis = UNZ_BUFSIZE; + if (pfile_in_zip_read_info->rest_read_compressedrest_read_compressed; + if (uReadThis == 0) + return UNZ_EOF; + if (fseek(pfile_in_zip_read_info->file, + pfile_in_zip_read_info->pos_in_zipfile + + pfile_in_zip_read_info->byte_before_the_zipfile,SEEK_SET)!=0) + return UNZ_ERRNO; + if (fread(pfile_in_zip_read_info->read_buffer,uReadThis,1, + pfile_in_zip_read_info->file)!=1) + return UNZ_ERRNO; + pfile_in_zip_read_info->pos_in_zipfile += uReadThis; + + pfile_in_zip_read_info->rest_read_compressed-=uReadThis; + + pfile_in_zip_read_info->stream.next_in = + (Bytef*)pfile_in_zip_read_info->read_buffer; + pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; + } + + if (pfile_in_zip_read_info->compression_method==0) + { + uInt uDoCopy,i ; + if (pfile_in_zip_read_info->stream.avail_out < + pfile_in_zip_read_info->stream.avail_in) + uDoCopy = pfile_in_zip_read_info->stream.avail_out ; + else + uDoCopy = pfile_in_zip_read_info->stream.avail_in ; + + for (i=0;istream.next_out+i) = + *(pfile_in_zip_read_info->stream.next_in+i); + + pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, + pfile_in_zip_read_info->stream.next_out, + uDoCopy); + pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; + pfile_in_zip_read_info->stream.avail_in -= uDoCopy; + pfile_in_zip_read_info->stream.avail_out -= uDoCopy; + pfile_in_zip_read_info->stream.next_out += uDoCopy; + pfile_in_zip_read_info->stream.next_in += uDoCopy; + pfile_in_zip_read_info->stream.total_out += uDoCopy; + iRead += uDoCopy; + } + else + { + uLong uTotalOutBefore,uTotalOutAfter; + const Bytef *bufBefore; + uLong uOutThis; + int flush=Z_SYNC_FLUSH; + + uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; + bufBefore = pfile_in_zip_read_info->stream.next_out; + + /* + if ((pfile_in_zip_read_info->rest_read_uncompressed == + pfile_in_zip_read_info->stream.avail_out) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + flush = Z_FINISH; + */ + err=inflate(&pfile_in_zip_read_info->stream,flush); + + uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; + uOutThis = uTotalOutAfter-uTotalOutBefore; + + pfile_in_zip_read_info->crc32 = + crc32(pfile_in_zip_read_info->crc32,bufBefore, + (uInt)(uOutThis)); + + pfile_in_zip_read_info->rest_read_uncompressed -= + uOutThis; + + iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); + + if (err==Z_STREAM_END) + return (iRead==0) ? UNZ_EOF : iRead; + if (err!=Z_OK) + break; + } + } + + if (err==Z_OK) + return iRead; + return err; +} + + +/* + Give the current position in uncompressed data +*/ +extern z_off_t ZEXPORT unztell (file) + unzFile file; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + return (z_off_t)pfile_in_zip_read_info->stream.total_out; +} + + +/* + return 1 if the end of file was reached, 0 elsewhere +*/ +extern int ZEXPORT unzeof (file) + unzFile file; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) + return 1; + else + return 0; +} + + + +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field that can be read + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ +extern int ZEXPORT unzGetLocalExtrafield (file,buf,len) + unzFile file; + voidp buf; + unsigned len; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + uInt read_now; + uLong size_to_read; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + size_to_read = (pfile_in_zip_read_info->size_local_extrafield - + pfile_in_zip_read_info->pos_local_extrafield); + + if (buf==NULL) + return (int)size_to_read; + + if (len>size_to_read) + read_now = (uInt)size_to_read; + else + read_now = (uInt)len ; + + if (read_now==0) + return 0; + + if (fseek(pfile_in_zip_read_info->file, + pfile_in_zip_read_info->offset_local_extrafield + + pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0) + return UNZ_ERRNO; + + if (fread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1) + return UNZ_ERRNO; + + return (int)read_now; +} + +/* + Close the file in zip opened with unzipOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ +extern int ZEXPORT unzCloseCurrentFile (file) + unzFile file; +{ + int err=UNZ_OK; + + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) + { + if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) + err=UNZ_CRCERROR; + } + + + TRYFREE(pfile_in_zip_read_info->read_buffer); + pfile_in_zip_read_info->read_buffer = NULL; + if (pfile_in_zip_read_info->stream_initialised) + inflateEnd(&pfile_in_zip_read_info->stream); + + pfile_in_zip_read_info->stream_initialised = 0; + TRYFREE(pfile_in_zip_read_info); + + s->pfile_in_zip_read=NULL; + + return err; +} + + +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ +extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf) + unzFile file; + char *szComment; + uLong uSizeBuf; +{ + int err=UNZ_OK; + unz_s* s; + uLong uReadThis ; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + + uReadThis = uSizeBuf; + if (uReadThis>s->gi.size_comment) + uReadThis = s->gi.size_comment; + + if (fseek(s->file,s->central_pos+22,SEEK_SET)!=0) + return UNZ_ERRNO; + + if (uReadThis>0) + { + *szComment='\0'; + if (fread(szComment,(uInt)uReadThis,1,s->file)!=1) + return UNZ_ERRNO; + } + + if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) + *(szComment+s->gi.size_comment)='\0'; + return (int)uReadThis; +} diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/unzip.def b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/unzip.def new file mode 100644 index 00000000000..f6ede89bc96 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/unzip.def @@ -0,0 +1,15 @@ + unzOpen @61 + unzClose @62 + unzGetGlobalInfo @63 + unzGetCurrentFileInfo @64 + unzGoToFirstFile @65 + unzGoToNextFile @66 + unzOpenCurrentFile @67 + unzReadCurrentFile @68 + unztell @70 + unzeof @71 + unzCloseCurrentFile @72 + unzGetGlobalComment @73 + unzStringFileNameCompare @74 + unzLocateFile @75 + unzGetLocalExtrafield @76 diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/unzip.h b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/unzip.h new file mode 100644 index 00000000000..76692cb703c --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/unzip.h @@ -0,0 +1,275 @@ +/* unzip.h -- IO for uncompress .zip files using zlib + Version 0.15 beta, Mar 19th, 1998, + + Copyright (C) 1998 Gilles Vollant + + This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g + WinZip, InfoZip tools and compatible. + Encryption and multi volume ZipFile (span) are not supported. + Old compressions used by old PKZip 1.x are not supported + + THIS IS AN ALPHA VERSION. AT THIS STAGE OF DEVELOPPEMENT, SOMES API OR STRUCTURE + CAN CHANGE IN FUTURE VERSION !! + I WAIT FEEDBACK at mail info@winimage.com + Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + +*/ +/* for more info about .ZIP format, see + ftp://ftp.cdrom.com/pub/infozip/doc/appnote-970311-iz.zip + PkWare has also a specification at : + ftp://ftp.pkware.com/probdesc.zip */ + +#ifndef _unz_H +#define _unz_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagunzFile__ { int unused; } unzFile__; +typedef unzFile__ *unzFile; +#else +typedef voidp unzFile; +#endif + + +#define UNZ_OK (0) +#define UNZ_END_OF_LIST_OF_FILE (-100) +#define UNZ_ERRNO (Z_ERRNO) +#define UNZ_EOF (0) +#define UNZ_PARAMERROR (-102) +#define UNZ_BADZIPFILE (-103) +#define UNZ_INTERNALERROR (-104) +#define UNZ_CRCERROR (-105) + +/* tm_unz contain date/time info */ +typedef struct tm_unz_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_unz; + +/* unz_global_info structure contain global data about the ZIPfile + These data comes from the end of central dir */ +typedef struct unz_global_info_s +{ + uLong number_entry; /* total number of entries in + the central dir on this disk */ + uLong size_comment; /* size of the global comment of the zipfile */ +} unz_global_info; + + +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_info_s +{ + uLong version; /* version made by 2 bytes */ + uLong version_needed; /* version needed to extract 2 bytes */ + uLong flag; /* general purpose bit flag 2 bytes */ + uLong compression_method; /* compression method 2 bytes */ + uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ + uLong crc; /* crc-32 4 bytes */ + uLong compressed_size; /* compressed size 4 bytes */ + uLong uncompressed_size; /* uncompressed size 4 bytes */ + uLong size_filename; /* filename length 2 bytes */ + uLong size_file_extra; /* extra field length 2 bytes */ + uLong size_file_comment; /* file comment length 2 bytes */ + + uLong disk_num_start; /* disk number start 2 bytes */ + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; +} unz_file_info; + +extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, + const char* fileName2, + int iCaseSensitivity)); +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) +*/ + + +extern unzFile ZEXPORT unzOpen OF((const char *path)); +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows NT computer "c:\\zlib\\zlib111.zip" or on an Unix computer + "zlib/zlib111.zip". + If the zipfile cannot be opened (file don't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ + +extern int ZEXPORT unzClose OF((unzFile file)); +/* + Close a ZipFile opened with unzipOpen. + If there is files inside the .Zip opened with unzOpenCurrentFile (see later), + these files MUST be closed with unzipCloseCurrentFile before call unzipClose. + return UNZ_OK if there is no problem. */ + +extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, + unz_global_info *pglobal_info)); +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ + + +extern int ZEXPORT unzGetGlobalComment OF((unzFile file, + char *szComment, + uLong uSizeBuf)); +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ + + +/***************************************************************************/ +/* Unzip package allow you browse the directory of the zipfile */ + +extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ + +extern int ZEXPORT unzGoToNextFile OF((unzFile file)); +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ + +extern int ZEXPORT unzLocateFile OF((unzFile file, + const char *szFileName, + int iCaseSensitivity)); +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ + + +extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, + unz_file_info *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); +/* + Get Info about the current file + if pfile_info!=NULL, the *pfile_info structure will contain somes info about + the current file + if szFileName!=NULL, the filemane string will be copied in szFileName + (fileNameBufferSize is the size of the buffer) + if extraField!=NULL, the extra field information will be copied in extraField + (extraFieldBufferSize is the size of the buffer). + This is the Central-header version of the extra field + if szComment!=NULL, the comment string of the file will be copied in szComment + (commentBufferSize is the size of the buffer) +*/ + +/***************************************************************************/ +/* for reading the content of the current zipfile, you can open it, read data + from it, and close it (you can close it before reading all the file) + */ + +extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); +/* + Open for reading data the current file in the zipfile. + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); +/* + Close the file in zip opened with unzOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ + + +extern int ZEXPORT unzReadCurrentFile OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read bytes from the current file (opened by unzOpenCurrentFile) + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ + +extern z_off_t ZEXPORT unztell OF((unzFile file)); +/* + Give the current position in uncompressed data +*/ + +extern int ZEXPORT unzeof OF((unzFile file)); +/* + return 1 if the end of file was reached, 0 elsewhere +*/ + +extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ + +#ifdef __cplusplus +} +#endif + +#endif /* _unz_H */ diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/zip.c b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/zip.c new file mode 100644 index 00000000000..0cae64ab7b1 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/zip.c @@ -0,0 +1,718 @@ +/* zip.c -- IO on .zip files using zlib + Version 0.15 beta, Mar 19th, 1998, + + Read zip.h for more info +*/ + + +#include +#include +#include +#include "zlib.h" +#include "zip.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +#ifndef VERSIONMADEBY +# define VERSIONMADEBY (0x0) /* platform depedent */ +#endif + +#ifndef Z_BUFSIZE +#define Z_BUFSIZE (16384) +#endif + +#ifndef Z_MAXFILENAMEINZIP +#define Z_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p);} +#endif + +/* +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) +*/ + +/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ + +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif + +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +const char zip_copyright[] = + " zip 0.15 Copyright 1998 Gilles Vollant "; + + +#define SIZEDATA_INDATABLOCK (4096-(4*4)) + +#define LOCALHEADERMAGIC (0x04034b50) +#define CENTRALHEADERMAGIC (0x02014b50) +#define ENDHEADERMAGIC (0x06054b50) + +#define FLAG_LOCALHEADER_OFFSET (0x06) +#define CRC_LOCALHEADER_OFFSET (0x0e) + +#define SIZECENTRALHEADER (0x2e) /* 46 */ + +typedef struct linkedlist_datablock_internal_s +{ + struct linkedlist_datablock_internal_s* next_datablock; + uLong avail_in_this_block; + uLong filled_in_this_block; + uLong unused; /* for future use and alignement */ + unsigned char data[SIZEDATA_INDATABLOCK]; +} linkedlist_datablock_internal; + +typedef struct linkedlist_data_s +{ + linkedlist_datablock_internal* first_block; + linkedlist_datablock_internal* last_block; +} linkedlist_data; + + +typedef struct +{ + z_stream stream; /* zLib stream structure for inflate */ + int stream_initialised; /* 1 is stream is initialised */ + uInt pos_in_buffered_data; /* last written byte in buffered_data */ + + uLong pos_local_header; /* offset of the local header of the file + currenty writing */ + char* central_header; /* central header data for the current file */ + uLong size_centralheader; /* size of the central header for cur file */ + uLong flag; /* flag of the file currently writing */ + + int method; /* compression method of file currenty wr.*/ + Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/ + uLong dosDate; + uLong crc32; +} curfile_info; + +typedef struct +{ + FILE * filezip; + linkedlist_data central_dir;/* datablock with central dir in construction*/ + int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/ + curfile_info ci; /* info on the file curretly writing */ + + uLong begin_pos; /* position of the beginning of the zipfile */ + uLong number_entry; +} zip_internal; + +local linkedlist_datablock_internal* allocate_new_datablock() +{ + linkedlist_datablock_internal* ldi; + ldi = (linkedlist_datablock_internal*) + ALLOC(sizeof(linkedlist_datablock_internal)); + if (ldi!=NULL) + { + ldi->next_datablock = NULL ; + ldi->filled_in_this_block = 0 ; + ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ; + } + return ldi; +} + +local void free_datablock(ldi) + linkedlist_datablock_internal* ldi; +{ + while (ldi!=NULL) + { + linkedlist_datablock_internal* ldinext = ldi->next_datablock; + TRYFREE(ldi); + ldi = ldinext; + } +} + +local void init_linkedlist(ll) + linkedlist_data* ll; +{ + ll->first_block = ll->last_block = NULL; +} + +local void free_linkedlist(ll) + linkedlist_data* ll; +{ + free_datablock(ll->first_block); + ll->first_block = ll->last_block = NULL; +} + + +local int add_data_in_datablock(ll,buf,len) + linkedlist_data* ll; + const void* buf; + uLong len; +{ + linkedlist_datablock_internal* ldi; + const unsigned char* from_copy; + + if (ll==NULL) + return ZIP_INTERNALERROR; + + if (ll->last_block == NULL) + { + ll->first_block = ll->last_block = allocate_new_datablock(); + if (ll->first_block == NULL) + return ZIP_INTERNALERROR; + } + + ldi = ll->last_block; + from_copy = (unsigned char*)buf; + + while (len>0) + { + uInt copy_this; + uInt i; + unsigned char* to_copy; + + if (ldi->avail_in_this_block==0) + { + ldi->next_datablock = allocate_new_datablock(); + if (ldi->next_datablock == NULL) + return ZIP_INTERNALERROR; + ldi = ldi->next_datablock ; + ll->last_block = ldi; + } + + if (ldi->avail_in_this_block < len) + copy_this = (uInt)ldi->avail_in_this_block; + else + copy_this = (uInt)len; + + to_copy = &(ldi->data[ldi->filled_in_this_block]); + + for (i=0;ifilled_in_this_block += copy_this; + ldi->avail_in_this_block -= copy_this; + from_copy += copy_this ; + len -= copy_this; + } + return ZIP_OK; +} + + +local int write_datablock(fout,ll) + FILE * fout; + linkedlist_data* ll; +{ + linkedlist_datablock_internal* ldi; + ldi = ll->first_block; + while (ldi!=NULL) + { + if (ldi->filled_in_this_block > 0) + if (fwrite(ldi->data,(uInt)ldi->filled_in_this_block,1,fout)!=1) + return ZIP_ERRNO; + ldi = ldi->next_datablock; + } + return ZIP_OK; +} + +/****************************************************************************/ + +/* =========================================================================== + Outputs a long in LSB order to the given file + nbByte == 1, 2 or 4 (byte, short or long) +*/ + +local int ziplocal_putValue OF((FILE *file, uLong x, int nbByte)); +local int ziplocal_putValue (file, x, nbByte) + FILE *file; + uLong x; + int nbByte; +{ + unsigned char buf[4]; + int n; + for (n = 0; n < nbByte; n++) { + buf[n] = (unsigned char)(x & 0xff); + x >>= 8; + } + if (fwrite(buf,nbByte,1,file)!=1) + return ZIP_ERRNO; + else + return ZIP_OK; +} + +local void ziplocal_putValue_inmemory OF((void* dest, uLong x, int nbByte)); +local void ziplocal_putValue_inmemory (dest, x, nbByte) + void* dest; + uLong x; + int nbByte; +{ + unsigned char* buf=(unsigned char*)dest; + int n; + for (n = 0; n < nbByte; n++) { + buf[n] = (unsigned char)(x & 0xff); + x >>= 8; + } +} +/****************************************************************************/ + + +local uLong ziplocal_TmzDateToDosDate(ptm,dosDate) + tm_zip* ptm; + uLong dosDate; +{ + uLong year = (uLong)ptm->tm_year; + if (year>1980) + year-=1980; + else if (year>80) + year-=80; + return + (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) | + ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour)); +} + + +/****************************************************************************/ + +extern zipFile ZEXPORT zipOpen (pathname, append) + const char *pathname; + int append; +{ + zip_internal ziinit; + zip_internal* zi; + + ziinit.filezip = fopen(pathname,(append == 0) ? "wb" : "ab"); + if (ziinit.filezip == NULL) + return NULL; + ziinit.begin_pos = ftell(ziinit.filezip); + ziinit.in_opened_file_inzip = 0; + ziinit.ci.stream_initialised = 0; + ziinit.number_entry = 0; + init_linkedlist(&(ziinit.central_dir)); + + + zi = (zip_internal*)ALLOC(sizeof(zip_internal)); + if (zi==NULL) + { + fclose(ziinit.filezip); + return NULL; + } + + *zi = ziinit; + return (zipFile)zi; +} + +extern int ZEXPORT zipOpenNewFileInZip (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level) + zipFile file; + const char* filename; + const zip_fileinfo* zipfi; + const void* extrafield_local; + uInt size_extrafield_local; + const void* extrafield_global; + uInt size_extrafield_global; + const char* comment; + int method; + int level; +{ + zip_internal* zi; + uInt size_filename; + uInt size_comment; + uInt i; + int err = ZIP_OK; + + if (file == NULL) + return ZIP_PARAMERROR; + if ((method!=0) && (method!=Z_DEFLATED)) + return ZIP_PARAMERROR; + + zi = (zip_internal*)file; + + if (zi->in_opened_file_inzip == 1) + { + err = zipCloseFileInZip (file); + if (err != ZIP_OK) + return err; + } + + + if (filename==NULL) + filename="-"; + + if (comment==NULL) + size_comment = 0; + else + size_comment = strlen(comment); + + size_filename = strlen(filename); + + if (zipfi == NULL) + zi->ci.dosDate = 0; + else + { + if (zipfi->dosDate != 0) + zi->ci.dosDate = zipfi->dosDate; + else zi->ci.dosDate = ziplocal_TmzDateToDosDate(&zipfi->tmz_date,zipfi->dosDate); + } + + zi->ci.flag = 0; + if ((level==8) || (level==9)) + zi->ci.flag |= 2; + if ((level==2)) + zi->ci.flag |= 4; + if ((level==1)) + zi->ci.flag |= 6; + + zi->ci.crc32 = 0; + zi->ci.method = method; + zi->ci.stream_initialised = 0; + zi->ci.pos_in_buffered_data = 0; + zi->ci.pos_local_header = ftell(zi->filezip); + zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + + size_extrafield_global + size_comment; + zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader); + + ziplocal_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4); + /* version info */ + ziplocal_putValue_inmemory(zi->ci.central_header+4,(uLong)VERSIONMADEBY,2); + ziplocal_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2); + ziplocal_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2); + ziplocal_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2); + ziplocal_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4); + ziplocal_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/ + ziplocal_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/ + ziplocal_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/ + ziplocal_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2); + ziplocal_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2); + ziplocal_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2); + ziplocal_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/ + + if (zipfi==NULL) + ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2); + else + ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2); + + if (zipfi==NULL) + ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4); + else + ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4); + + ziplocal_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header,4); + + for (i=0;ici.central_header+SIZECENTRALHEADER+i) = *(filename+i); + + for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+i) = + *(((const char*)extrafield_global)+i); + + for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+ + size_extrafield_global+i) = *(filename+i); + if (zi->ci.central_header == NULL) + return ZIP_INTERNALERROR; + + /* write the local header */ + err = ziplocal_putValue(zi->filezip,(uLong)LOCALHEADERMAGIC,4); + + if (err==ZIP_OK) + err = ziplocal_putValue(zi->filezip,(uLong)20,2);/* version needed to extract */ + if (err==ZIP_OK) + err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.flag,2); + + if (err==ZIP_OK) + err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.method,2); + + if (err==ZIP_OK) + err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.dosDate,4); + + if (err==ZIP_OK) + err = ziplocal_putValue(zi->filezip,(uLong)0,4); /* crc 32, unknown */ + if (err==ZIP_OK) + err = ziplocal_putValue(zi->filezip,(uLong)0,4); /* compressed size, unknown */ + if (err==ZIP_OK) + err = ziplocal_putValue(zi->filezip,(uLong)0,4); /* uncompressed size, unknown */ + + if (err==ZIP_OK) + err = ziplocal_putValue(zi->filezip,(uLong)size_filename,2); + + if (err==ZIP_OK) + err = ziplocal_putValue(zi->filezip,(uLong)size_extrafield_local,2); + + if ((err==ZIP_OK) && (size_filename>0)) + if (fwrite(filename,(uInt)size_filename,1,zi->filezip)!=1) + err = ZIP_ERRNO; + + if ((err==ZIP_OK) && (size_extrafield_local>0)) + if (fwrite(extrafield_local,(uInt)size_extrafield_local,1,zi->filezip) + !=1) + err = ZIP_ERRNO; + + zi->ci.stream.avail_in = (uInt)0; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + zi->ci.stream.total_in = 0; + zi->ci.stream.total_out = 0; + + if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED)) + { + zi->ci.stream.zalloc = (alloc_func)0; + zi->ci.stream.zfree = (free_func)0; + zi->ci.stream.opaque = (voidpf)0; + + err = deflateInit2(&zi->ci.stream, level, + Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, 0); + + if (err==Z_OK) + zi->ci.stream_initialised = 1; + } + + + if (err==Z_OK) + zi->in_opened_file_inzip = 1; + return err; +} + +extern int ZEXPORT zipWriteInFileInZip (file, buf, len) + zipFile file; + const voidp buf; + unsigned len; +{ + zip_internal* zi; + int err=ZIP_OK; + + if (file == NULL) + return ZIP_PARAMERROR; + zi = (zip_internal*)file; + + if (zi->in_opened_file_inzip == 0) + return ZIP_PARAMERROR; + + zi->ci.stream.next_in = buf; + zi->ci.stream.avail_in = len; + zi->ci.crc32 = crc32(zi->ci.crc32,buf,len); + + while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0)) + { + if (zi->ci.stream.avail_out == 0) + { + if (fwrite(zi->ci.buffered_data,(uInt)zi->ci.pos_in_buffered_data,1,zi->filezip) + !=1) + err = ZIP_ERRNO; + zi->ci.pos_in_buffered_data = 0; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + } + + if (zi->ci.method == Z_DEFLATED) + { + uLong uTotalOutBefore = zi->ci.stream.total_out; + err=deflate(&zi->ci.stream, Z_NO_FLUSH); + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; + + } + else + { + uInt copy_this,i; + if (zi->ci.stream.avail_in < zi->ci.stream.avail_out) + copy_this = zi->ci.stream.avail_in; + else + copy_this = zi->ci.stream.avail_out; + for (i=0;ici.stream.next_out)+i) = + *(((const char*)zi->ci.stream.next_in)+i); + { + zi->ci.stream.avail_in -= copy_this; + zi->ci.stream.avail_out-= copy_this; + zi->ci.stream.next_in+= copy_this; + zi->ci.stream.next_out+= copy_this; + zi->ci.stream.total_in+= copy_this; + zi->ci.stream.total_out+= copy_this; + zi->ci.pos_in_buffered_data += copy_this; + } + } + } + + return 0; +} + +extern int ZEXPORT zipCloseFileInZip (file) + zipFile file; +{ + zip_internal* zi; + int err=ZIP_OK; + + if (file == NULL) + return ZIP_PARAMERROR; + zi = (zip_internal*)file; + + if (zi->in_opened_file_inzip == 0) + return ZIP_PARAMERROR; + zi->ci.stream.avail_in = 0; + + if (zi->ci.method == Z_DEFLATED) + while (err==ZIP_OK) + { + uLong uTotalOutBefore; + if (zi->ci.stream.avail_out == 0) + { + if (fwrite(zi->ci.buffered_data,(uInt)zi->ci.pos_in_buffered_data,1,zi->filezip) + !=1) + err = ZIP_ERRNO; + zi->ci.pos_in_buffered_data = 0; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + } + uTotalOutBefore = zi->ci.stream.total_out; + err=deflate(&zi->ci.stream, Z_FINISH); + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; + } + + if (err==Z_STREAM_END) + err=ZIP_OK; /* this is normal */ + + if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK)) + if (fwrite(zi->ci.buffered_data,(uInt)zi->ci.pos_in_buffered_data,1,zi->filezip) + !=1) + err = ZIP_ERRNO; + + if ((zi->ci.method == Z_DEFLATED) && (err==ZIP_OK)) + { + err=deflateEnd(&zi->ci.stream); + zi->ci.stream_initialised = 0; + } + + ziplocal_putValue_inmemory(zi->ci.central_header+16,(uLong)zi->ci.crc32,4); /*crc*/ + ziplocal_putValue_inmemory(zi->ci.central_header+20, + (uLong)zi->ci.stream.total_out,4); /*compr size*/ + ziplocal_putValue_inmemory(zi->ci.central_header+24, + (uLong)zi->ci.stream.total_in,4); /*uncompr size*/ + + if (err==ZIP_OK) + err = add_data_in_datablock(&zi->central_dir,zi->ci.central_header, + (uLong)zi->ci.size_centralheader); + free(zi->ci.central_header); + + if (err==ZIP_OK) + { + long cur_pos_inzip = ftell(zi->filezip); + if (fseek(zi->filezip, + zi->ci.pos_local_header + 14,SEEK_SET)!=0) + err = ZIP_ERRNO; + + if (err==ZIP_OK) + err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.crc32,4); /* crc 32, unknown */ + + if (err==ZIP_OK) /* compressed size, unknown */ + err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.stream.total_out,4); + + if (err==ZIP_OK) /* uncompressed size, unknown */ + err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.stream.total_in,4); + + if (fseek(zi->filezip, + cur_pos_inzip,SEEK_SET)!=0) + err = ZIP_ERRNO; + } + + zi->number_entry ++; + zi->in_opened_file_inzip = 0; + + return err; +} + +extern int ZEXPORT zipClose (file, global_comment) + zipFile file; + const char* global_comment; +{ + zip_internal* zi; + int err = 0; + uLong size_centraldir = 0; + uLong centraldir_pos_inzip ; + uInt size_global_comment; + if (file == NULL) + return ZIP_PARAMERROR; + zi = (zip_internal*)file; + + if (zi->in_opened_file_inzip == 1) + { + err = zipCloseFileInZip (file); + } + + if (global_comment==NULL) + size_global_comment = 0; + else + size_global_comment = strlen(global_comment); + + + centraldir_pos_inzip = ftell(zi->filezip); + if (err==ZIP_OK) + { + linkedlist_datablock_internal* ldi = zi->central_dir.first_block ; + while (ldi!=NULL) + { + if ((err==ZIP_OK) && (ldi->filled_in_this_block>0)) + if (fwrite(ldi->data,(uInt)ldi->filled_in_this_block, + 1,zi->filezip) !=1 ) + err = ZIP_ERRNO; + + size_centraldir += ldi->filled_in_this_block; + ldi = ldi->next_datablock; + } + } + free_datablock(zi->central_dir.first_block); + + if (err==ZIP_OK) /* Magic End */ + err = ziplocal_putValue(zi->filezip,(uLong)ENDHEADERMAGIC,4); + + if (err==ZIP_OK) /* number of this disk */ + err = ziplocal_putValue(zi->filezip,(uLong)0,2); + + if (err==ZIP_OK) /* number of the disk with the start of the central directory */ + err = ziplocal_putValue(zi->filezip,(uLong)0,2); + + if (err==ZIP_OK) /* total number of entries in the central dir on this disk */ + err = ziplocal_putValue(zi->filezip,(uLong)zi->number_entry,2); + + if (err==ZIP_OK) /* total number of entries in the central dir */ + err = ziplocal_putValue(zi->filezip,(uLong)zi->number_entry,2); + + if (err==ZIP_OK) /* size of the central directory */ + err = ziplocal_putValue(zi->filezip,(uLong)size_centraldir,4); + + if (err==ZIP_OK) /* offset of start of central directory with respect to the + starting disk number */ + err = ziplocal_putValue(zi->filezip,(uLong)centraldir_pos_inzip ,4); + + if (err==ZIP_OK) /* zipfile comment length */ + err = ziplocal_putValue(zi->filezip,(uLong)size_global_comment,2); + + if ((err==ZIP_OK) && (size_global_comment>0)) + if (fwrite(global_comment,(uInt)size_global_comment,1,zi->filezip) !=1 ) + err = ZIP_ERRNO; + fclose(zi->filezip); + TRYFREE(zi); + + return err; +} diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/zip.def b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/zip.def new file mode 100644 index 00000000000..5d5079fbcee --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/zip.def @@ -0,0 +1,5 @@ + zipOpen @80 + zipOpenNewFileInZip @81 + zipWriteInFileInZip @82 + zipCloseFileInZip @83 + zipClose @84 diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/zip.h b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/zip.h new file mode 100644 index 00000000000..678260b330b --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/zip.h @@ -0,0 +1,150 @@ +/* zip.h -- IO for compress .zip files using zlib + Version 0.15 alpha, Mar 19th, 1998, + + Copyright (C) 1998 Gilles Vollant + + This unzip package allow creates .ZIP file, compatible with PKZip 2.04g + WinZip, InfoZip tools and compatible. + Encryption and multi volume ZipFile (span) are not supported. + Old compressions used by old PKZip 1.x are not supported + + For uncompress .zip file, look at unzip.h + + THIS IS AN ALPHA VERSION. AT THIS STAGE OF DEVELOPPEMENT, SOMES API OR STRUCTURE + CAN CHANGE IN FUTURE VERSION !! + I WAIT FEEDBACK at mail info@winimage.com + Visit also http://www.winimage.com/zLibDll/zip.htm for evolution + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + +*/ + +/* for more info about .ZIP format, see + ftp://ftp.cdrom.com/pub/infozip/doc/appnote-970311-iz.zip + PkWare has also a specification at : + ftp://ftp.pkware.com/probdesc.zip +*/ + +#ifndef _zip_H +#define _zip_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#if defined(STRICTZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagzipFile__ { int unused; } zipFile__; +typedef zipFile__ *zipFile; +#else +typedef voidp zipFile; +#endif + +#define ZIP_OK (0) +#define ZIP_ERRNO (Z_ERRNO) +#define ZIP_PARAMERROR (-102) +#define ZIP_INTERNALERROR (-104) + +/* tm_zip contain date/time info */ +typedef struct tm_zip_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_zip; + +typedef struct +{ + tm_zip tmz_date; /* date in understandable format */ + uLong dosDate; /* if dos_date == 0, tmu_date is used */ +/* uLong flag; */ /* general purpose bit flag 2 bytes */ + + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ +} zip_fileinfo; + +extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append)); +/* + Create a zipfile. + pathname contain on Windows NT a filename like "c:\\zlib\\zlib111.zip" or on + an Unix computer "zlib/zlib111.zip". + if the file pathname exist and append=1, the zip will be created at the end + of the file. (useful if the file contain a self extractor code) + If the zipfile cannot be opened, the return value is NULL. + Else, the return value is a zipFile Handle, usable with other function + of this zip package. + + +*/ + +extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level)); +/* + Open a file in the ZIP for writing. + filename : the filename in zip (if NULL, '-' without quote will be used + *zipfi contain supplemental information + if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local + contains the extrafield data the the local header + if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global + contains the extrafield data the the local header + if comment != NULL, comment contain the comment string + method contain the compression method (0 for store, Z_DEFLATED for deflate) + level contain the level of compression (can be Z_DEFAULT_COMPRESSION) +*/ + +extern int ZEXPORT zipWriteInFileInZip OF((zipFile file, + const voidp buf, + unsigned len)); +/* + Write data in the zipfile +*/ + +extern int ZEXPORT zipCloseFileInZip OF((zipFile file)); +/* + Close the current file in the zipfile +*/ + +extern int ZEXPORT zipClose OF((zipFile file, + const char* global_comment)); +/* + Close the zipfile +*/ + +#ifdef __cplusplus +} +#endif + +#endif /* _zip_H */ diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/zlibvc.def b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/zlibvc.def new file mode 100644 index 00000000000..7e9d60d55d9 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/zlibvc.def @@ -0,0 +1,74 @@ +LIBRARY "zlib" + +DESCRIPTION '"""zlib data compression library"""' + + +VERSION 1.11 + + +HEAPSIZE 1048576,8192 + +EXPORTS + adler32 @1 + compress @2 + crc32 @3 + deflate @4 + deflateCopy @5 + deflateEnd @6 + deflateInit2_ @7 + deflateInit_ @8 + deflateParams @9 + deflateReset @10 + deflateSetDictionary @11 + gzclose @12 + gzdopen @13 + gzerror @14 + gzflush @15 + gzopen @16 + gzread @17 + gzwrite @18 + inflate @19 + inflateEnd @20 + inflateInit2_ @21 + inflateInit_ @22 + inflateReset @23 + inflateSetDictionary @24 + inflateSync @25 + uncompress @26 + zlibVersion @27 + gzprintf @28 + gzputc @29 + gzgetc @30 + gzseek @31 + gzrewind @32 + gztell @33 + gzeof @34 + gzsetparams @35 + zError @36 + inflateSyncPoint @37 + get_crc_table @38 + compress2 @39 + gzputs @40 + gzgets @41 + + unzOpen @61 + unzClose @62 + unzGetGlobalInfo @63 + unzGetCurrentFileInfo @64 + unzGoToFirstFile @65 + unzGoToNextFile @66 + unzOpenCurrentFile @67 + unzReadCurrentFile @68 + unztell @70 + unzeof @71 + unzCloseCurrentFile @72 + unzGetGlobalComment @73 + unzStringFileNameCompare @74 + unzLocateFile @75 + unzGetLocalExtrafield @76 + + zipOpen @80 + zipOpenNewFileInZip @81 + zipWriteInFileInZip @82 + zipCloseFileInZip @83 + zipClose @84 diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/zlibvc.dsp b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/zlibvc.dsp new file mode 100644 index 00000000000..a70d4d4a6b0 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/zlibvc.dsp @@ -0,0 +1,651 @@ +# Microsoft Developer Studio Project File - Name="zlibvc" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 +# TARGTYPE "Win32 (ALPHA) Dynamic-Link Library" 0x0602 + +CFG=zlibvc - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "zlibvc.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "zlibvc.mak" CFG="zlibvc - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "zlibvc - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "zlibvc - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "zlibvc - Win32 ReleaseAxp" (based on\ + "Win32 (ALPHA) Dynamic-Link Library") +!MESSAGE "zlibvc - Win32 ReleaseWithoutAsm" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "zlibvc - Win32 ReleaseWithoutCrtdll" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir ".\Release" +# PROP BASE Intermediate_Dir ".\Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir ".\Release" +# PROP Intermediate_Dir ".\Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +CPP=cl.exe +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /D "ASMV" /FAcs /FR /FD /c +# SUBTRACT CPP /YX +MTL=midl.exe +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 +# ADD LINK32 gvmat32.obj kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\Release\zlib.dll" +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir ".\Debug" +# PROP BASE Intermediate_Dir ".\Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir ".\Debug" +# PROP Intermediate_Dir ".\Debug" +# PROP Target_Dir "" +CPP=cl.exe +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /FD /c +# SUBTRACT CPP /YX +MTL=midl.exe +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:".\Debug\zlib.dll" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "zlibvc__" +# PROP BASE Intermediate_Dir "zlibvc__" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "zlibvc__" +# PROP Intermediate_Dir "zlibvc__" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +MTL=midl.exe +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +CPP=cl.exe +# ADD BASE CPP /nologo /MT /Gt0 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /FAcs /FR /YX /FD /c +# ADD CPP /nologo /MT /Gt0 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /FAcs /FR /FD /c +# SUBTRACT CPP /YX +RSC=rc.exe +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 crtdll.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /map /machine:ALPHA /nodefaultlib /out:".\Release\zlib.dll" +# SUBTRACT BASE LINK32 /pdb:none +# ADD LINK32 crtdll.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /map /machine:ALPHA /nodefaultlib /out:"zlibvc__\zlib.dll" +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "zlibvc_0" +# PROP BASE Intermediate_Dir "zlibvc_0" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "zlibvc_0" +# PROP Intermediate_Dir "zlibvc_0" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +CPP=cl.exe +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /FAcs /FR /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /FAcs /FR /FD /c +# SUBTRACT CPP /YX +MTL=midl.exe +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\Release\zlib.dll" +# SUBTRACT BASE LINK32 /pdb:none +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\zlibvc_0\zlib.dll" +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "zlibvc_1" +# PROP BASE Intermediate_Dir "zlibvc_1" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "zlibvc_1" +# PROP Intermediate_Dir "zlibvc_1" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +CPP=cl.exe +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /D "ASMV" /FAcs /FR /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /D "ASMV" /FAcs /FR /FD /c +# SUBTRACT CPP /YX +MTL=midl.exe +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 gvmat32.obj kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\Release\zlib.dll" +# SUBTRACT BASE LINK32 /pdb:none +# ADD LINK32 gvmat32.obj kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\zlibvc_1\zlib.dll" +# SUBTRACT LINK32 /pdb:none + +!ENDIF + +# Begin Target + +# Name "zlibvc - Win32 Release" +# Name "zlibvc - Win32 Debug" +# Name "zlibvc - Win32 ReleaseAxp" +# Name "zlibvc - Win32 ReleaseWithoutAsm" +# Name "zlibvc - Win32 ReleaseWithoutCrtdll" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=.\adler32.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_ADLER=\ + ".\zconf.h"\ + ".\zlib.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\compress.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_COMPR=\ + ".\zconf.h"\ + ".\zlib.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\crc32.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_CRC32=\ + ".\zconf.h"\ + ".\zlib.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\deflate.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_DEFLA=\ + ".\deflate.h"\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\gvmat32c.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\gzio.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_GZIO_=\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\infblock.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_INFBL=\ + ".\infblock.h"\ + ".\infcodes.h"\ + ".\inftrees.h"\ + ".\infutil.h"\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\infcodes.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_INFCO=\ + ".\infblock.h"\ + ".\infcodes.h"\ + ".\inffast.h"\ + ".\inftrees.h"\ + ".\infutil.h"\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\inffast.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_INFFA=\ + ".\infblock.h"\ + ".\infcodes.h"\ + ".\inffast.h"\ + ".\inftrees.h"\ + ".\infutil.h"\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\inflate.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_INFLA=\ + ".\infblock.h"\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\inftrees.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_INFTR=\ + ".\inftrees.h"\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\infutil.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_INFUT=\ + ".\infblock.h"\ + ".\infcodes.h"\ + ".\inftrees.h"\ + ".\infutil.h"\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\trees.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_TREES=\ + ".\deflate.h"\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\uncompr.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_UNCOM=\ + ".\zconf.h"\ + ".\zlib.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\unzip.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\zip.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\zlib.rc +# End Source File +# Begin Source File + +SOURCE=.\zlibvc.def +# End Source File +# Begin Source File + +SOURCE=.\zutil.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_ZUTIL=\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\deflate.h +# End Source File +# Begin Source File + +SOURCE=.\infblock.h +# End Source File +# Begin Source File + +SOURCE=.\infcodes.h +# End Source File +# Begin Source File + +SOURCE=.\inffast.h +# End Source File +# Begin Source File + +SOURCE=.\inftrees.h +# End Source File +# Begin Source File + +SOURCE=.\infutil.h +# End Source File +# Begin Source File + +SOURCE=.\zconf.h +# End Source File +# Begin Source File + +SOURCE=.\zlib.h +# End Source File +# Begin Source File + +SOURCE=.\zutil.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/zlibvc.dsw b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/zlibvc.dsw new file mode 100644 index 00000000000..493cd870365 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/minizip/zlibvc.dsw @@ -0,0 +1,41 @@ +Microsoft Developer Studio Workspace File, Format Version 5.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "zlibstat"=.\zlibstat.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "zlibvc"=.\zlibvc.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/untgz/Makefile b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/untgz/Makefile new file mode 100644 index 00000000000..409b4bdeaae --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/untgz/Makefile @@ -0,0 +1,14 @@ +CC=cc +CFLAGS=-g + +untgz: untgz.o ../../libz.a + $(CC) $(CFLAGS) -o untgz untgz.o -L../.. -lz + +untgz.o: untgz.c ../../zlib.h + $(CC) $(CFLAGS) -c -I../.. untgz.c + +../../libz.a: + cd ../..; make + +clean: + rm -f untgz untgz.o *~ diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/untgz/makefile.w32 b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/untgz/makefile.w32 new file mode 100644 index 00000000000..c99dc28cf55 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/untgz/makefile.w32 @@ -0,0 +1,63 @@ +# Makefile for zlib. Modified for mingw32 +# For conditions of distribution and use, see copyright notice in zlib.h + +# To compile, +# +# make -fmakefile.w32 +# + +CC=gcc + +# Generate dependencies (see end of the file) + +CPPFLAGS=-MMD + +#CFLAGS=-MMD -O +#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 +#CFLAGS=-MMD -g -DDEBUG +CFLAGS=-O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ + -Wstrict-prototypes -Wmissing-prototypes + +# If cp.exe is not found, replace with copy /Y . +CP=cp -f + +# The default value of RM is "rm -f." +# If "rm.exe" is not found, uncomment: +# RM=del + +LD=gcc +LDLIBS=-L. -lz +LDFLAGS=-s + + +INCL=zlib.h zconf.h +LIBS=libz.a + +AR=ar rcs + +OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ + zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o \ + inffast.o + +TEST_OBJS = minigzip.o untgz.o + +all: minigzip.exe untgz.exe + +rebuild: clean all + +libz.a: $(OBJS) + $(AR) $@ $(OBJS) + +%.exe : %.o $(LIBS) + $(LD) $(LDFLAGS) -o $@ $< $(LDLIBS) + +.PHONY : clean + +clean: + $(RM) *.d *.o *.exe libz.a foo.gz + +DEPS := $(wildcard *.d) +ifneq ($(DEPS),) +include $(DEPS) +endif + diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/untgz/untgz.c b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/untgz/untgz.c new file mode 100644 index 00000000000..4a431ff3163 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/untgz/untgz.c @@ -0,0 +1,522 @@ +/* + * untgz.c -- Display contents and/or extract file from + * a gzip'd TAR file + * written by "Pedro A. Aranda Guti\irrez" + * adaptation to Unix by Jean-loup Gailly + */ + +#include +#include +#include +#include +#include +#include +#ifdef unix +# include +#else +# include +# include +#endif + +#include "zlib.h" + +#ifdef WIN32 +# ifndef F_OK +# define F_OK (0) +# endif +# ifdef _MSC_VER +# define mkdir(dirname,mode) _mkdir(dirname) +# define strdup(str) _strdup(str) +# define unlink(fn) _unlink(fn) +# define access(path,mode) _access(path,mode) +# else +# define mkdir(dirname,mode) _mkdir(dirname) +# endif +#else +# include +#endif + + +/* Values used in typeflag field. */ + +#define REGTYPE '0' /* regular file */ +#define AREGTYPE '\0' /* regular file */ +#define LNKTYPE '1' /* link */ +#define SYMTYPE '2' /* reserved */ +#define CHRTYPE '3' /* character special */ +#define BLKTYPE '4' /* block special */ +#define DIRTYPE '5' /* directory */ +#define FIFOTYPE '6' /* FIFO special */ +#define CONTTYPE '7' /* reserved */ + +#define BLOCKSIZE 512 + +struct tar_header +{ /* byte offset */ + char name[100]; /* 0 */ + char mode[8]; /* 100 */ + char uid[8]; /* 108 */ + char gid[8]; /* 116 */ + char size[12]; /* 124 */ + char mtime[12]; /* 136 */ + char chksum[8]; /* 148 */ + char typeflag; /* 156 */ + char linkname[100]; /* 157 */ + char magic[6]; /* 257 */ + char version[2]; /* 263 */ + char uname[32]; /* 265 */ + char gname[32]; /* 297 */ + char devmajor[8]; /* 329 */ + char devminor[8]; /* 337 */ + char prefix[155]; /* 345 */ + /* 500 */ +}; + +union tar_buffer { + char buffer[BLOCKSIZE]; + struct tar_header header; +}; + +enum { TGZ_EXTRACT = 0, TGZ_LIST }; + +static char *TGZfname OF((const char *)); +void TGZnotfound OF((const char *)); + +int getoct OF((char *, int)); +char *strtime OF((time_t *)); +int ExprMatch OF((char *,char *)); + +int makedir OF((char *)); +int matchname OF((int,int,char **,char *)); + +void error OF((const char *)); +int tar OF((gzFile, int, int, int, char **)); + +void help OF((int)); +int main OF((int, char **)); + +char *prog; + +/* This will give a benign warning */ + +static char *TGZprefix[] = { "\0", ".tgz", ".tar.gz", ".tar", NULL }; + +/* Return the real name of the TGZ archive */ +/* or NULL if it does not exist. */ + +static char *TGZfname OF((const char *fname)) +{ + static char buffer[1024]; + int origlen,i; + + strcpy(buffer,fname); + origlen = strlen(buffer); + + for (i=0; TGZprefix[i]; i++) + { + strcpy(buffer+origlen,TGZprefix[i]); + if (access(buffer,F_OK) == 0) + return buffer; + } + return NULL; +} + +/* error message for the filename */ + +void TGZnotfound OF((const char *fname)) +{ + int i; + + fprintf(stderr,"%s : couldn't find ",prog); + for (i=0;TGZprefix[i];i++) + fprintf(stderr,(TGZprefix[i+1]) ? "%s%s, " : "or %s%s\n", + fname, + TGZprefix[i]); + exit(1); +} + + +/* help functions */ + +int getoct(char *p,int width) +{ + int result = 0; + char c; + + while (width --) + { + c = *p++; + if (c == ' ') + continue; + if (c == 0) + break; + result = result * 8 + (c - '0'); + } + return result; +} + +char *strtime (time_t *t) +{ + struct tm *local; + static char result[32]; + + local = localtime(t); + sprintf(result,"%2d/%02d/%4d %02d:%02d:%02d", + local->tm_mday, local->tm_mon+1, local->tm_year+1900, + local->tm_hour, local->tm_min, local->tm_sec); + return result; +} + + +/* regular expression matching */ + +#define ISSPECIAL(c) (((c) == '*') || ((c) == '/')) + +int ExprMatch(char *string,char *expr) +{ + while (1) + { + if (ISSPECIAL(*expr)) + { + if (*expr == '/') + { + if (*string != '\\' && *string != '/') + return 0; + string ++; expr++; + } + else if (*expr == '*') + { + if (*expr ++ == 0) + return 1; + while (*++string != *expr) + if (*string == 0) + return 0; + } + } + else + { + if (*string != *expr) + return 0; + if (*expr++ == 0) + return 1; + string++; + } + } +} + +/* recursive make directory */ +/* abort if you get an ENOENT errno somewhere in the middle */ +/* e.g. ignore error "mkdir on existing directory" */ +/* */ +/* return 1 if OK */ +/* 0 on error */ + +int makedir (char *newdir) +{ + char *buffer = strdup(newdir); + char *p; + int len = strlen(buffer); + + if (len <= 0) { + free(buffer); + return 0; + } + if (buffer[len-1] == '/') { + buffer[len-1] = '\0'; + } + if (mkdir(buffer, 0775) == 0) + { + free(buffer); + return 1; + } + + p = buffer+1; + while (1) + { + char hold; + + while(*p && *p != '\\' && *p != '/') + p++; + hold = *p; + *p = 0; + if ((mkdir(buffer, 0775) == -1) && (errno == ENOENT)) + { + fprintf(stderr,"%s: couldn't create directory %s\n",prog,buffer); + free(buffer); + return 0; + } + if (hold == 0) + break; + *p++ = hold; + } + free(buffer); + return 1; +} + +int matchname (int arg,int argc,char **argv,char *fname) +{ + if (arg == argc) /* no arguments given (untgz tgzarchive) */ + return 1; + + while (arg < argc) + if (ExprMatch(fname,argv[arg++])) + return 1; + + return 0; /* ignore this for the moment being */ +} + + +/* Tar file list or extract */ + +int tar (gzFile in,int action,int arg,int argc,char **argv) +{ + union tar_buffer buffer; + int len; + int err; + int getheader = 1; + int remaining = 0; + FILE *outfile = NULL; + char fname[BLOCKSIZE]; + time_t tartime; + + if (action == TGZ_LIST) + printf(" day time size file\n" + " ---------- -------- --------- -------------------------------------\n"); + while (1) + { + len = gzread(in, &buffer, BLOCKSIZE); + if (len < 0) + error (gzerror(in, &err)); + /* + * Always expect complete blocks to process + * the tar information. + */ + if (len != BLOCKSIZE) + error("gzread: incomplete block read"); + + /* + * If we have to get a tar header + */ + if (getheader == 1) + { + /* + * if we met the end of the tar + * or the end-of-tar block, + * we are done + */ + if ((len == 0) || (buffer.header.name[0]== 0)) break; + + tartime = (time_t)getoct(buffer.header.mtime,12); + strcpy(fname,buffer.header.name); + + switch (buffer.header.typeflag) + { + case DIRTYPE: + if (action == TGZ_LIST) + printf(" %s %s\n",strtime(&tartime),fname); + if (action == TGZ_EXTRACT) + makedir(fname); + break; + case REGTYPE: + case AREGTYPE: + remaining = getoct(buffer.header.size,12); + if (action == TGZ_LIST) + printf(" %s %9d %s\n",strtime(&tartime),remaining,fname); + if (action == TGZ_EXTRACT) + { + if ((remaining) && (matchname(arg,argc,argv,fname))) + { + outfile = fopen(fname,"wb"); + if (outfile == NULL) { + /* try creating directory */ + char *p = strrchr(fname, '/'); + if (p != NULL) { + *p = '\0'; + makedir(fname); + *p = '/'; + outfile = fopen(fname,"wb"); + } + } + fprintf(stderr, + "%s %s\n", + (outfile) ? "Extracting" : "Couldn't create", + fname); + } + else + outfile = NULL; + } + /* + * could have no contents + */ + getheader = (remaining) ? 0 : 1; + break; + default: + if (action == TGZ_LIST) + printf(" %s <---> %s\n",strtime(&tartime),fname); + break; + } + } + else + { + unsigned int bytes = (remaining > BLOCKSIZE) ? BLOCKSIZE : remaining; + + if ((action == TGZ_EXTRACT) && (outfile != NULL)) + { + if (fwrite(&buffer,sizeof(char),bytes,outfile) != bytes) + { + fprintf(stderr,"%s : error writing %s skipping...\n",prog,fname); + fclose(outfile); + unlink(fname); + } + } + remaining -= bytes; + if (remaining == 0) + { + getheader = 1; + if ((action == TGZ_EXTRACT) && (outfile != NULL)) + { +#ifdef WIN32 + HANDLE hFile; + FILETIME ftm,ftLocal; + SYSTEMTIME st; + struct tm localt; + + fclose(outfile); + + localt = *localtime(&tartime); + + hFile = CreateFile(fname, GENERIC_READ | GENERIC_WRITE, + 0, NULL, OPEN_EXISTING, 0, NULL); + + st.wYear = (WORD)localt.tm_year+1900; + st.wMonth = (WORD)localt.tm_mon; + st.wDayOfWeek = (WORD)localt.tm_wday; + st.wDay = (WORD)localt.tm_mday; + st.wHour = (WORD)localt.tm_hour; + st.wMinute = (WORD)localt.tm_min; + st.wSecond = (WORD)localt.tm_sec; + st.wMilliseconds = 0; + SystemTimeToFileTime(&st,&ftLocal); + LocalFileTimeToFileTime(&ftLocal,&ftm); + SetFileTime(hFile,&ftm,NULL,&ftm); + CloseHandle(hFile); + + outfile = NULL; +#else + struct utimbuf settime; + + settime.actime = settime.modtime = tartime; + + fclose(outfile); + outfile = NULL; + utime(fname,&settime); +#endif + } + } + } + } + + if (gzclose(in) != Z_OK) + error("failed gzclose"); + + return 0; +} + + +/* =========================================================== */ + +void help(int exitval) +{ + fprintf(stderr, + "untgz v 0.1\n" + " an sample application of zlib 1.0.4\n\n" + "Usage : untgz TGZfile to extract all files\n" + " untgz TGZfile fname ... to extract selected files\n" + " untgz -l TGZfile to list archive contents\n" + " untgz -h to display this help\n\n"); + exit(exitval); +} + +void error(const char *msg) +{ + fprintf(stderr, "%s: %s\n", prog, msg); + exit(1); +} + + +/* ====================================================================== */ + +int _CRT_glob = 0; /* disable globbing of the arguments */ + +int main(int argc,char **argv) +{ + int action = TGZ_EXTRACT; + int arg = 1; + char *TGZfile; + gzFile *f; + + + prog = strrchr(argv[0],'\\'); + if (prog == NULL) + { + prog = strrchr(argv[0],'/'); + if (prog == NULL) + { + prog = strrchr(argv[0],':'); + if (prog == NULL) + prog = argv[0]; + else + prog++; + } + else + prog++; + } + else + prog++; + + if (argc == 1) + help(0); + + if (strcmp(argv[arg],"-l") == 0) + { + action = TGZ_LIST; + if (argc == ++arg) + help(0); + } + else if (strcmp(argv[arg],"-h") == 0) + { + help(0); + } + + if ((TGZfile = TGZfname(argv[arg])) == NULL) + TGZnotfound(argv[arg]); + + ++arg; + if ((action == TGZ_LIST) && (arg != argc)) + help(1); + +/* + * Process the TGZ file + */ + switch(action) + { + case TGZ_LIST: + case TGZ_EXTRACT: + f = gzopen(TGZfile,"rb"); + if (f == NULL) + { + fprintf(stderr,"%s: Couldn't gzopen %s\n", + prog, + TGZfile); + return 1; + } + exit(tar(f, action, arg, argc, argv)); + break; + + default: + error("Unknown option!"); + exit(1); + } + + return 0; +} diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/contrib/visual-basic.txt b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/visual-basic.txt new file mode 100644 index 00000000000..10fb44bc593 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/contrib/visual-basic.txt @@ -0,0 +1,69 @@ +See below some functions declarations for Visual Basic. + +Frequently Asked Question: + +Q: Each time I use the compress function I get the -5 error (not enough + room in the output buffer). + +A: Make sure that the length of the compressed buffer is passed by + reference ("as any"), not by value ("as long"). Also check that + before the call of compress this length is equal to the total size of + the compressed buffer and not zero. + + +From: "Jon Caruana" +Subject: Re: How to port zlib declares to vb? +Date: Mon, 28 Oct 1996 18:33:03 -0600 + +Got the answer! (I haven't had time to check this but it's what I got, and +looks correct): + +He has the following routines working: + compress + uncompress + gzopen + gzwrite + gzread + gzclose + +Declares follow: (Quoted from Carlos Rios , in Vb4 form) + +#If Win16 Then 'Use Win16 calls. +Declare Function compress Lib "ZLIB.DLL" (ByVal compr As + String, comprLen As Any, ByVal buf As String, ByVal buflen + As Long) As Integer +Declare Function uncompress Lib "ZLIB.DLL" (ByVal uncompr + As String, uncomprLen As Any, ByVal compr As String, ByVal + lcompr As Long) As Integer +Declare Function gzopen Lib "ZLIB.DLL" (ByVal filePath As + String, ByVal mode As String) As Long +Declare Function gzread Lib "ZLIB.DLL" (ByVal file As + Long, ByVal uncompr As String, ByVal uncomprLen As Integer) + As Integer +Declare Function gzwrite Lib "ZLIB.DLL" (ByVal file As + Long, ByVal uncompr As String, ByVal uncomprLen As Integer) + As Integer +Declare Function gzclose Lib "ZLIB.DLL" (ByVal file As + Long) As Integer +#Else +Declare Function compress Lib "ZLIB32.DLL" + (ByVal compr As String, comprLen As Any, ByVal buf As + String, ByVal buflen As Long) As Integer +Declare Function uncompress Lib "ZLIB32.DLL" + (ByVal uncompr As String, uncomprLen As Any, ByVal compr As + String, ByVal lcompr As Long) As Long +Declare Function gzopen Lib "ZLIB32.DLL" + (ByVal file As String, ByVal mode As String) As Long +Declare Function gzread Lib "ZLIB32.DLL" + (ByVal file As Long, ByVal uncompr As String, ByVal + uncomprLen As Long) As Long +Declare Function gzwrite Lib "ZLIB32.DLL" + (ByVal file As Long, ByVal uncompr As String, ByVal + uncomprLen As Long) As Long +Declare Function gzclose Lib "ZLIB32.DLL" + (ByVal file As Long) As Long +#End If + +-Jon Caruana +jon-net@usa.net +Microsoft Sitebuilder Network Level 1 Member - HTML Writer's Guild Member diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/crc32.c b/contrib/vmap_extractor_v2/stormlib/zlib/crc32.c new file mode 100644 index 00000000000..60deca2ddf4 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/crc32.c @@ -0,0 +1,162 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zlib.h" + +#define local static + +#ifdef DYNAMIC_CRC_TABLE + +local int crc_table_empty = 1; +local uLongf crc_table[256]; +local void make_crc_table OF((void)); + +/* + Generate a table for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The table is simply the CRC of all possible eight bit values. This is all + the information needed to generate CRC's on data a byte at a time for all + combinations of CRC register values and incoming bytes. +*/ +local void make_crc_table() +{ + uLong c; + int n, k; + uLong poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static const Byte p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* make exclusive-or pattern from polynomial (0xedb88320L) */ + poly = 0L; + for (n = 0; n < sizeof(p)/sizeof(Byte); n++) + poly |= 1L << (31 - p[n]); + + for (n = 0; n < 256; n++) + { + c = (uLong)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[n] = c; + } + crc_table_empty = 0; +} +#else +/* ======================================================================== + * Table of CRC-32's of all single-byte values (made by make_crc_table) + */ +local const uLongf crc_table[256] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, + 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, + 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, + 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, + 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, + 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, + 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, + 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, + 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, + 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, + 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, + 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, + 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, + 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, + 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, + 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, + 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, + 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, + 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, + 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, + 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, + 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, + 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, + 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, + 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, + 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, + 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, + 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, + 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, + 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, + 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, + 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, + 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, + 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, + 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, + 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, + 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, + 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, + 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, + 0x2d02ef8dL +}; +#endif + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const uLongf * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) make_crc_table(); +#endif + return (const uLongf *)crc_table; +} + +/* ========================================================================= */ +#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); +#define DO2(buf) DO1(buf); DO1(buf); +#define DO4(buf) DO2(buf); DO2(buf); +#define DO8(buf) DO4(buf); DO4(buf); + +/* ========================================================================= */ +uLong ZEXPORT crc32(crc, buf, len) + uLong crc; + const Bytef *buf; + uInt len; +{ + if (buf == Z_NULL) return 0L; +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif + crc = crc ^ 0xffffffffL; + while (len >= 8) + { + DO8(buf); + len -= 8; + } + if (len) do { + DO1(buf); + } while (--len); + return crc ^ 0xffffffffL; +} diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/deflate.c b/contrib/vmap_extractor_v2/stormlib/zlib/deflate.c new file mode 100644 index 00000000000..16ebdade3f1 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/deflate.c @@ -0,0 +1,1350 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in ftp://ds.internic.net/rfc/rfc1951.txt + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id$ */ + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.1.4 Copyright 1995-2002 Jean-loup Gailly "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +local block_state deflate_slow OF((deflate_state *s, int flush)); +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifdef ASMV + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif + +#ifdef DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* maximum speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* maximum compression */ + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of str are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + deflate_state *s; + int noheader = 0; + static const char* my_version = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == Z_NULL) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == Z_NULL) strm->zfree = zcfree; + + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#ifdef FASTEST + level = 1; +#endif + + if (windowBits < 0) { /* undocumented feature: suppress zlib header */ + noheader = 1; + windowBits = -windowBits; + } + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 9 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_HUFFMAN_ONLY) { + return Z_STREAM_ERROR; + } + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + + s->noheader = noheader; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; + + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || + strm->state->status != INIT_STATE) return Z_STREAM_ERROR; + + s = strm->state; + strm->adler = adler32(strm->adler, dictionary, dictLength); + + if (length < MIN_MATCH) return Z_OK; + if (length > MAX_DIST(s)) { + length = MAX_DIST(s); +#ifndef USE_DICT_HEAD + dictionary += dictLength - length; /* use the tail of the dictionary */ +#endif + } + zmemcpy(s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; + + /* Insert all strings in the hash table (except for the last two bytes). + * s->lookahead stays null, so s->ins_h will be recomputed at the next + * call of fill_window. + */ + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == Z_NULL || strm->zfree == Z_NULL) return Z_STREAM_ERROR; + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->noheader < 0) { + s->noheader = 0; /* was set to -1 by deflate(..., Z_FINISH); */ + } + s->status = s->noheader ? BUSY_STATE : INIT_STATE; + strm->adler = 1; + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + lm_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(strm, level, strategy) + z_streamp strm; + int level; + int strategy; +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + + if (level == Z_DEFAULT_COMPRESSION) { + level = 6; + } + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if (func != configuration_table[level].func && strm->total_in != 0) { + /* Flush the last buffer: */ + err = deflate(strm, Z_PARTIAL_FLUSH); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->next_out buffer and copying into it. + * (See also read_buf()). + */ +local void flush_pending(strm) + z_streamp strm; +{ + unsigned len = strm->state->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } +} + +/* ========================================================================= */ +int ZEXPORT deflate (strm, flush) + z_streamp strm; + int flush; +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_FINISH || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the zlib header */ + if (s->status == INIT_STATE) { + + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags = (s->level-1) >> 1; + + if (level_flags > 3) level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = 1L; + } + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUFF_ERROR. + */ + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = (*(configuration_table[s->level].func))(s, flush); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->noheader) return Z_STREAM_END; + + /* Write the zlib trailer (adler32) */ + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + s->noheader = -1; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (strm) + z_streamp strm; +{ + int status; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + status = strm->state->status; + if (status != INIT_STATE && status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (dest, source) + z_streamp dest; + z_streamp source; +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + *dest = *source; + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + *ds = *ss; + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local int read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + if (!strm->state->noheader) { + strm->adler = adler32(strm->adler, strm->next_in, len); + } + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (s) + deflate_state *s; +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +} + +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +#ifndef FASTEST +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2: + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} + +#else /* FASTEST */ +/* --------------------------------------------------------------------------- + * Optimized version for level == 1 only + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return len <= s->lookahead ? len : s->lookahead; +} +#endif /* FASTEST */ +#endif /* ASMV */ + +#ifdef DEBUG +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(s, start, match, length) + deflate_state *s; + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(s) + deflate_state *s; +{ + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if strstart == 0 + * and lookahead == 1 (input done one byte at time) + */ + more--; + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + } else if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) return; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, eof) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (eof)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, eof) { \ + FLUSH_BLOCK_ONLY(s, eof); \ + if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +local block_state deflate_stored(s, flush) + deflate_state *s; + int flush; +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy != Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } + /* longest_match() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in hash table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy != Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } + /* longest_match() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED || + (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR))) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/deflate.h b/contrib/vmap_extractor_v2/stormlib/zlib/deflate.h new file mode 100644 index 00000000000..b99a48a5214 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/deflate.h @@ -0,0 +1,318 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2002 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef _DEFLATE_H +#define _DEFLATE_H + +#include "zutil.h" + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + int pending; /* nb of bytes in the pending buffer */ + int noheader; /* suppress zlib header and adler32 */ + Byte data_type; /* UNKNOWN, BINARY or ASCII */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + + /* in trees.c */ +void _tr_init OF((deflate_state *s)); +int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); +void _tr_align OF((deflate_state *s)); +void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch _length_code[]; + extern uch _dist_code[]; +#else + extern const uch _length_code[]; + extern const uch _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/descrip.mms b/contrib/vmap_extractor_v2/stormlib/zlib/descrip.mms new file mode 100644 index 00000000000..9d364598a27 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/descrip.mms @@ -0,0 +1,48 @@ +# descrip.mms: MMS description file for building zlib on VMS +# written by Martin P.J. Zinser + +cc_defs = +c_deb = + +.ifdef __DECC__ +pref = /prefix=all +.endif + +OBJS = adler32.obj, compress.obj, crc32.obj, gzio.obj, uncompr.obj,\ + deflate.obj, trees.obj, zutil.obj, inflate.obj, infblock.obj,\ + inftrees.obj, infcodes.obj, infutil.obj, inffast.obj + +CFLAGS= $(C_DEB) $(CC_DEFS) $(PREF) + +all : example.exe minigzip.exe + @ write sys$output " Example applications available" +libz.olb : libz.olb($(OBJS)) + @ write sys$output " libz available" + +example.exe : example.obj libz.olb + link example,libz.olb/lib + +minigzip.exe : minigzip.obj libz.olb + link minigzip,libz.olb/lib,x11vms:xvmsutils.olb/lib + +clean : + delete *.obj;*,libz.olb;* + + +# Other dependencies. +adler32.obj : zutil.h zlib.h zconf.h +compress.obj : zlib.h zconf.h +crc32.obj : zutil.h zlib.h zconf.h +deflate.obj : deflate.h zutil.h zlib.h zconf.h +example.obj : zlib.h zconf.h +gzio.obj : zutil.h zlib.h zconf.h +infblock.obj : zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h +infcodes.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h infcodes.h inffast.h +inffast.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h inffast.h +inflate.obj : zutil.h zlib.h zconf.h infblock.h +inftrees.obj : zutil.h zlib.h zconf.h inftrees.h +infutil.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h +minigzip.obj : zlib.h zconf.h +trees.obj : deflate.h zutil.h zlib.h zconf.h +uncompr.obj : zlib.h zconf.h +zutil.obj : zutil.h zlib.h zconf.h diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/example.c b/contrib/vmap_extractor_v2/stormlib/zlib/example.c new file mode 100644 index 00000000000..e7e3673333e --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/example.c @@ -0,0 +1,556 @@ +/* example.c -- usage example of the zlib compression library + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include +#include "zlib.h" + +#ifdef STDC +# include +# include +#else + extern void exit OF((int)); +#endif + +#if defined(VMS) || defined(RISCOS) +# define TESTFILE "foo-gz" +#else +# define TESTFILE "foo.gz" +#endif + +#define CHECK_ERR(err, msg) { \ + if (err != Z_OK) { \ + fprintf(stderr, "%s error: %d\n", msg, err); \ + exit(1); \ + } \ +} + +const char hello[] = "hello, hello!"; +/* "hello world" would be more standard, but the repeated "hello" + * stresses the compression code better, sorry... + */ + +const char dictionary[] = "hello"; +uLong dictId; /* Adler32 value of the dictionary */ + +void test_compress OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_gzio OF((const char *out, const char *in, + Byte *uncompr, int uncomprLen)); +void test_deflate OF((Byte *compr, uLong comprLen)); +void test_inflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_large_deflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_large_inflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_flush OF((Byte *compr, uLong *comprLen)); +void test_sync OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_dict_deflate OF((Byte *compr, uLong comprLen)); +void test_dict_inflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +int main OF((int argc, char *argv[])); + +/* =========================================================================== + * Test compress() and uncompress() + */ +void test_compress(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + uLong len = strlen(hello)+1; + + err = compress(compr, &comprLen, (const Bytef*)hello, len); + CHECK_ERR(err, "compress"); + + strcpy((char*)uncompr, "garbage"); + + err = uncompress(uncompr, &uncomprLen, compr, comprLen); + CHECK_ERR(err, "uncompress"); + + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad uncompress\n"); + exit(1); + } else { + printf("uncompress(): %s\n", (char *)uncompr); + } +} + +/* =========================================================================== + * Test read/write of .gz files + */ +void test_gzio(out, in, uncompr, uncomprLen) + const char *out; /* compressed output file */ + const char *in; /* compressed input file */ + Byte *uncompr; + int uncomprLen; +{ + int err; + int len = strlen(hello)+1; + gzFile file; + z_off_t pos; + + file = gzopen(out, "wb"); + if (file == NULL) { + fprintf(stderr, "gzopen error\n"); + exit(1); + } + gzputc(file, 'h'); + if (gzputs(file, "ello") != 4) { + fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err)); + exit(1); + } + if (gzprintf(file, ", %s!", "hello") != 8) { + fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err)); + exit(1); + } + gzseek(file, 1L, SEEK_CUR); /* add one zero byte */ + gzclose(file); + + file = gzopen(in, "rb"); + if (file == NULL) { + fprintf(stderr, "gzopen error\n"); + } + strcpy((char*)uncompr, "garbage"); + + uncomprLen = gzread(file, uncompr, (unsigned)uncomprLen); + if (uncomprLen != len) { + fprintf(stderr, "gzread err: %s\n", gzerror(file, &err)); + exit(1); + } + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad gzread: %s\n", (char*)uncompr); + exit(1); + } else { + printf("gzread(): %s\n", (char *)uncompr); + } + + pos = gzseek(file, -8L, SEEK_CUR); + if (pos != 6 || gztell(file) != pos) { + fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n", + (long)pos, (long)gztell(file)); + exit(1); + } + + if (gzgetc(file) != ' ') { + fprintf(stderr, "gzgetc error\n"); + exit(1); + } + + gzgets(file, (char*)uncompr, uncomprLen); + uncomprLen = strlen((char*)uncompr); + if (uncomprLen != 6) { /* "hello!" */ + fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err)); + exit(1); + } + if (strcmp((char*)uncompr, hello+7)) { + fprintf(stderr, "bad gzgets after gzseek\n"); + exit(1); + } else { + printf("gzgets() after gzseek: %s\n", (char *)uncompr); + } + + gzclose(file); +} + +/* =========================================================================== + * Test deflate() with small buffers + */ +void test_deflate(compr, comprLen) + Byte *compr; + uLong comprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + int len = strlen(hello)+1; + + c_stream.zalloc = (alloc_func)0; + c_stream.zfree = (free_func)0; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); + CHECK_ERR(err, "deflateInit"); + + c_stream.next_in = (Bytef*)hello; + c_stream.next_out = compr; + + while (c_stream.total_in != (uLong)len && c_stream.total_out < comprLen) { + c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */ + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + } + /* Finish the stream, still forcing small buffers: */ + for (;;) { + c_stream.avail_out = 1; + err = deflate(&c_stream, Z_FINISH); + if (err == Z_STREAM_END) break; + CHECK_ERR(err, "deflate"); + } + + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); +} + +/* =========================================================================== + * Test inflate() with small buffers + */ +void test_inflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = (alloc_func)0; + d_stream.zfree = (free_func)0; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = 0; + d_stream.next_out = uncompr; + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) { + d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */ + err = inflate(&d_stream, Z_NO_FLUSH); + if (err == Z_STREAM_END) break; + CHECK_ERR(err, "inflate"); + } + + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad inflate\n"); + exit(1); + } else { + printf("inflate(): %s\n", (char *)uncompr); + } +} + +/* =========================================================================== + * Test deflate() with large buffers and dynamic change of compression level + */ +void test_large_deflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + + c_stream.zalloc = (alloc_func)0; + c_stream.zfree = (free_func)0; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_BEST_SPEED); + CHECK_ERR(err, "deflateInit"); + + c_stream.next_out = compr; + c_stream.avail_out = (uInt)comprLen; + + /* At this point, uncompr is still mostly zeroes, so it should compress + * very well: + */ + c_stream.next_in = uncompr; + c_stream.avail_in = (uInt)uncomprLen; + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + if (c_stream.avail_in != 0) { + fprintf(stderr, "deflate not greedy\n"); + exit(1); + } + + /* Feed in already compressed data and switch to no compression: */ + deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY); + c_stream.next_in = compr; + c_stream.avail_in = (uInt)comprLen/2; + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + + /* Switch back to compressing mode: */ + deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED); + c_stream.next_in = uncompr; + c_stream.avail_in = (uInt)uncomprLen; + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + + err = deflate(&c_stream, Z_FINISH); + if (err != Z_STREAM_END) { + fprintf(stderr, "deflate should report Z_STREAM_END\n"); + exit(1); + } + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); +} + +/* =========================================================================== + * Test inflate() with large buffers + */ +void test_large_inflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = (alloc_func)0; + d_stream.zfree = (free_func)0; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = (uInt)comprLen; + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + for (;;) { + d_stream.next_out = uncompr; /* discard the output */ + d_stream.avail_out = (uInt)uncomprLen; + err = inflate(&d_stream, Z_NO_FLUSH); + if (err == Z_STREAM_END) break; + CHECK_ERR(err, "large inflate"); + } + + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + if (d_stream.total_out != 2*uncomprLen + comprLen/2) { + fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out); + exit(1); + } else { + printf("large_inflate(): OK\n"); + } +} + +/* =========================================================================== + * Test deflate() with full flush + */ +void test_flush(compr, comprLen) + Byte *compr; + uLong *comprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + int len = strlen(hello)+1; + + c_stream.zalloc = (alloc_func)0; + c_stream.zfree = (free_func)0; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); + CHECK_ERR(err, "deflateInit"); + + c_stream.next_in = (Bytef*)hello; + c_stream.next_out = compr; + c_stream.avail_in = 3; + c_stream.avail_out = (uInt)*comprLen; + err = deflate(&c_stream, Z_FULL_FLUSH); + CHECK_ERR(err, "deflate"); + + compr[3]++; /* force an error in first compressed block */ + c_stream.avail_in = len - 3; + + err = deflate(&c_stream, Z_FINISH); + if (err != Z_STREAM_END) { + CHECK_ERR(err, "deflate"); + } + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); + + *comprLen = c_stream.total_out; +} + +/* =========================================================================== + * Test inflateSync() + */ +void test_sync(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = (alloc_func)0; + d_stream.zfree = (free_func)0; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = 2; /* just read the zlib header */ + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + d_stream.next_out = uncompr; + d_stream.avail_out = (uInt)uncomprLen; + + inflate(&d_stream, Z_NO_FLUSH); + CHECK_ERR(err, "inflate"); + + d_stream.avail_in = (uInt)comprLen-2; /* read all compressed data */ + err = inflateSync(&d_stream); /* but skip the damaged part */ + CHECK_ERR(err, "inflateSync"); + + err = inflate(&d_stream, Z_FINISH); + if (err != Z_DATA_ERROR) { + fprintf(stderr, "inflate should report DATA_ERROR\n"); + /* Because of incorrect adler32 */ + exit(1); + } + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + printf("after inflateSync(): hel%s\n", (char *)uncompr); +} + +/* =========================================================================== + * Test deflate() with preset dictionary + */ +void test_dict_deflate(compr, comprLen) + Byte *compr; + uLong comprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + + c_stream.zalloc = (alloc_func)0; + c_stream.zfree = (free_func)0; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_BEST_COMPRESSION); + CHECK_ERR(err, "deflateInit"); + + err = deflateSetDictionary(&c_stream, + (const Bytef*)dictionary, sizeof(dictionary)); + CHECK_ERR(err, "deflateSetDictionary"); + + dictId = c_stream.adler; + c_stream.next_out = compr; + c_stream.avail_out = (uInt)comprLen; + + c_stream.next_in = (Bytef*)hello; + c_stream.avail_in = (uInt)strlen(hello)+1; + + err = deflate(&c_stream, Z_FINISH); + if (err != Z_STREAM_END) { + fprintf(stderr, "deflate should report Z_STREAM_END\n"); + exit(1); + } + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); +} + +/* =========================================================================== + * Test inflate() with a preset dictionary + */ +void test_dict_inflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = (alloc_func)0; + d_stream.zfree = (free_func)0; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = (uInt)comprLen; + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + d_stream.next_out = uncompr; + d_stream.avail_out = (uInt)uncomprLen; + + for (;;) { + err = inflate(&d_stream, Z_NO_FLUSH); + if (err == Z_STREAM_END) break; + if (err == Z_NEED_DICT) { + if (d_stream.adler != dictId) { + fprintf(stderr, "unexpected dictionary"); + exit(1); + } + err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary, + sizeof(dictionary)); + } + CHECK_ERR(err, "inflate with dict"); + } + + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad inflate with dict\n"); + exit(1); + } else { + printf("inflate with dictionary: %s\n", (char *)uncompr); + } +} + +/* =========================================================================== + * Usage: example [output.gz [input.gz]] + */ + +int main(argc, argv) + int argc; + char *argv[]; +{ + Byte *compr, *uncompr; + uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */ + uLong uncomprLen = comprLen; + static const char* myVersion = ZLIB_VERSION; + + if (zlibVersion()[0] != myVersion[0]) { + fprintf(stderr, "incompatible zlib version\n"); + exit(1); + + } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) { + fprintf(stderr, "warning: different zlib version\n"); + } + + compr = (Byte*)calloc((uInt)comprLen, 1); + uncompr = (Byte*)calloc((uInt)uncomprLen, 1); + /* compr and uncompr are cleared to avoid reading uninitialized + * data and to ensure that uncompr compresses well. + */ + if (compr == Z_NULL || uncompr == Z_NULL) { + printf("out of memory\n"); + exit(1); + } + test_compress(compr, comprLen, uncompr, uncomprLen); + + test_gzio((argc > 1 ? argv[1] : TESTFILE), + (argc > 2 ? argv[2] : TESTFILE), + uncompr, (int)uncomprLen); + + test_deflate(compr, comprLen); + test_inflate(compr, comprLen, uncompr, uncomprLen); + + test_large_deflate(compr, comprLen, uncompr, uncomprLen); + test_large_inflate(compr, comprLen, uncompr, uncomprLen); + + test_flush(compr, &comprLen); + test_sync(compr, comprLen, uncompr, uncomprLen); + comprLen = uncomprLen; + + test_dict_deflate(compr, comprLen); + test_dict_inflate(compr, comprLen, uncompr, uncomprLen); + + exit(0); + return 0; /* to avoid warning */ +} diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/gzio.c b/contrib/vmap_extractor_v2/stormlib/zlib/gzio.c new file mode 100644 index 00000000000..09e0a20b8ce --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/gzio.c @@ -0,0 +1,875 @@ +/* gzio.c -- IO on .gz files + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Compile this file with -DNO_DEFLATE to avoid the compression code. + */ + +/* @(#) $Id$ */ + +#include + +#include "zutil.h" + +struct internal_state {int dummy;}; /* for buggy compilers */ + +#ifndef Z_BUFSIZE +# ifdef MAXSEG_64K +# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */ +# else +# define Z_BUFSIZE 16384 +# endif +#endif +#ifndef Z_PRINTF_BUFSIZE +# define Z_PRINTF_BUFSIZE 4096 +#endif + +#define ALLOC(size) malloc(size) +#define TRYFREE(p) {if (p) free(p);} + +static int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define RESERVED 0xE0 /* bits 5..7: reserved */ + +typedef struct gz_stream { + z_stream stream; + int z_err; /* error code for last stream operation */ + int z_eof; /* set if end of input file */ + FILE *file; /* .gz file */ + Byte *inbuf; /* input buffer */ + Byte *outbuf; /* output buffer */ + uLong crc; /* crc32 of uncompressed data */ + char *msg; /* error message */ + char *path; /* path name for debugging only */ + int transparent; /* 1 if input file is not a .gz file */ + char mode; /* 'w' or 'r' */ + long startpos; /* start of compressed data in file (header skipped) */ +} gz_stream; + + +local gzFile gz_open OF((const char *path, const char *mode, int fd)); +local int do_flush OF((gzFile file, int flush)); +local int get_byte OF((gz_stream *s)); +local void check_header OF((gz_stream *s)); +local int destroy OF((gz_stream *s)); +local void putLong OF((FILE *file, uLong x)); +local uLong getLong OF((gz_stream *s)); + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb"). The file is given either by file descriptor + or path name (if fd == -1). + gz_open return NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). +*/ +local gzFile gz_open (path, mode, fd) + const char *path; + const char *mode; + int fd; +{ + int err; + int level = Z_DEFAULT_COMPRESSION; /* compression level */ + int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */ + char *p = (char*)mode; + gz_stream *s; + char fmode[80]; /* copy of mode, without the compression level */ + char *m = fmode; + + if (!path || !mode) return Z_NULL; + + s = (gz_stream *)ALLOC(sizeof(gz_stream)); + if (!s) return Z_NULL; + + s->stream.zalloc = (alloc_func)0; + s->stream.zfree = (free_func)0; + s->stream.opaque = (voidpf)0; + s->stream.next_in = s->inbuf = Z_NULL; + s->stream.next_out = s->outbuf = Z_NULL; + s->stream.avail_in = s->stream.avail_out = 0; + s->file = NULL; + s->z_err = Z_OK; + s->z_eof = 0; + s->crc = crc32(0L, Z_NULL, 0); + s->msg = NULL; + s->transparent = 0; + + s->path = (char*)ALLOC(strlen(path)+1); + if (s->path == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + strcpy(s->path, path); /* do this early for debugging */ + + s->mode = '\0'; + do { + if (*p == 'r') s->mode = 'r'; + if (*p == 'w' || *p == 'a') s->mode = 'w'; + if (*p >= '0' && *p <= '9') { + level = *p - '0'; + } else if (*p == 'f') { + strategy = Z_FILTERED; + } else if (*p == 'h') { + strategy = Z_HUFFMAN_ONLY; + } else { + *m++ = *p; /* copy the mode */ + } + } while (*p++ && m != fmode + sizeof(fmode)); + if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; + + if (s->mode == 'w') { +#ifdef NO_DEFLATE + err = Z_STREAM_ERROR; +#else + err = deflateInit2(&(s->stream), level, + Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy); + /* windowBits is passed < 0 to suppress zlib header */ + + s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); +#endif + if (err != Z_OK || s->outbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } else { + s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); + + err = inflateInit2(&(s->stream), -MAX_WBITS); + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are + * present after the compressed stream. + */ + if (err != Z_OK || s->inbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } + s->stream.avail_out = Z_BUFSIZE; + + errno = 0; + s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode); + + if (s->file == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + if (s->mode == 'w') { + /* Write a very simple .gz header: + */ + fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], + Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); + s->startpos = 10L; + /* We use 10L instead of ftell(s->file) to because ftell causes an + * fflush on some systems. This version of the library doesn't use + * startpos anyway in write mode, so this initialization is not + * necessary. + */ + } else { + check_header(s); /* skip the .gz header */ + s->startpos = (ftell(s->file) - s->stream.avail_in); + } + + return (gzFile)s; +} + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. +*/ +gzFile ZEXPORT gzopen (path, mode) + const char *path; + const char *mode; +{ + return gz_open (path, mode, -1); +} + +/* =========================================================================== + Associate a gzFile with the file descriptor fd. fd is not dup'ed here + to mimic the behavio(u)r of fdopen. +*/ +gzFile ZEXPORT gzdopen (fd, mode) + int fd; + const char *mode; +{ + char name[20]; + + if (fd < 0) return (gzFile)Z_NULL; + sprintf(name, "", fd); /* for debugging */ + + return gz_open (name, mode, fd); +} + +/* =========================================================================== + * Update the compression level and strategy + */ +int ZEXPORT gzsetparams (file, level, strategy) + gzFile file; + int level; + int strategy; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + /* Make room to allow flushing */ + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + } + s->stream.avail_out = Z_BUFSIZE; + } + + return deflateParams (&(s->stream), level, strategy); +} + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been sucessfully opened for reading. +*/ +local int get_byte(s) + gz_stream *s; +{ + if (s->z_eof) return EOF; + if (s->stream.avail_in == 0) { + errno = 0; + s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) s->z_err = Z_ERRNO; + return EOF; + } + s->stream.next_in = s->inbuf; + } + s->stream.avail_in--; + return *(s->stream.next_in)++; +} + +/* =========================================================================== + Check the gzip header of a gz_stream opened for reading. Set the stream + mode to transparent if the gzip magic header is not present; set s->err + to Z_DATA_ERROR if the magic header is present but the rest of the header + is incorrect. + IN assertion: the stream s has already been created sucessfully; + s->stream.avail_in is zero for the first time, but may be non-zero + for concatenated .gz files. +*/ +local void check_header(s) + gz_stream *s; +{ + int method; /* method byte */ + int flags; /* flags byte */ + uInt len; + int c; + + /* Check the gzip magic header */ + for (len = 0; len < 2; len++) { + c = get_byte(s); + if (c != gz_magic[len]) { + if (len != 0) s->stream.avail_in++, s->stream.next_in--; + if (c != EOF) { + s->stream.avail_in++, s->stream.next_in--; + s->transparent = 1; + } + s->z_err = s->stream.avail_in != 0 ? Z_OK : Z_STREAM_END; + return; + } + } + method = get_byte(s); + flags = get_byte(s); + if (method != Z_DEFLATED || (flags & RESERVED) != 0) { + s->z_err = Z_DATA_ERROR; + return; + } + + /* Discard time, xflags and OS code: */ + for (len = 0; len < 6; len++) (void)get_byte(s); + + if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ + len = (uInt)get_byte(s); + len += ((uInt)get_byte(s))<<8; + /* len is garbage if EOF but the loop below will quit anyway */ + while (len-- != 0 && get_byte(s) != EOF) ; + } + if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ + for (len = 0; len < 2; len++) (void)get_byte(s); + } + s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK; +} + + /* =========================================================================== + * Cleanup then free the given gz_stream. Return a zlib error code. + Try freeing in the reverse order of allocations. + */ +local int destroy (s) + gz_stream *s; +{ + int err = Z_OK; + + if (!s) return Z_STREAM_ERROR; + + TRYFREE(s->msg); + + if (s->stream.state != NULL) { + if (s->mode == 'w') { +#ifdef NO_DEFLATE + err = Z_STREAM_ERROR; +#else + err = deflateEnd(&(s->stream)); +#endif + } else if (s->mode == 'r') { + err = inflateEnd(&(s->stream)); + } + } + if (s->file != NULL && fclose(s->file)) { +#ifdef ESPIPE + if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */ +#endif + err = Z_ERRNO; + } + if (s->z_err < 0) err = s->z_err; + + TRYFREE(s->inbuf); + TRYFREE(s->outbuf); + TRYFREE(s->path); + TRYFREE(s); + return err; +} + +/* =========================================================================== + Reads the given number of uncompressed bytes from the compressed file. + gzread returns the number of bytes actually read (0 for end of file). +*/ +int ZEXPORT gzread (file, buf, len) + gzFile file; + voidp buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + Bytef *start = (Bytef*)buf; /* starting point for crc computation */ + Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */ + + if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; + + if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; + if (s->z_err == Z_STREAM_END) return 0; /* EOF */ + + next_out = (Byte*)buf; + s->stream.next_out = (Bytef*)buf; + s->stream.avail_out = len; + + while (s->stream.avail_out != 0) { + + if (s->transparent) { + /* Copy first the lookahead bytes: */ + uInt n = s->stream.avail_in; + if (n > s->stream.avail_out) n = s->stream.avail_out; + if (n > 0) { + zmemcpy(s->stream.next_out, s->stream.next_in, n); + next_out += n; + s->stream.next_out = next_out; + s->stream.next_in += n; + s->stream.avail_out -= n; + s->stream.avail_in -= n; + } + if (s->stream.avail_out > 0) { + s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out, + s->file); + } + len -= s->stream.avail_out; + s->stream.total_in += (uLong)len; + s->stream.total_out += (uLong)len; + if (len == 0) s->z_eof = 1; + return (int)len; + } + if (s->stream.avail_in == 0 && !s->z_eof) { + + errno = 0; + s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) { + s->z_err = Z_ERRNO; + break; + } + } + s->stream.next_in = s->inbuf; + } + s->z_err = inflate(&(s->stream), Z_NO_FLUSH); + + if (s->z_err == Z_STREAM_END) { + /* Check CRC and original size */ + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + start = s->stream.next_out; + + if (getLong(s) != s->crc) { + s->z_err = Z_DATA_ERROR; + } else { + (void)getLong(s); + /* The uncompressed length returned by above getlong() may + * be different from s->stream.total_out) in case of + * concatenated .gz files. Check for such files: + */ + check_header(s); + if (s->z_err == Z_OK) { + uLong total_in = s->stream.total_in; + uLong total_out = s->stream.total_out; + + inflateReset(&(s->stream)); + s->stream.total_in = total_in; + s->stream.total_out = total_out; + s->crc = crc32(0L, Z_NULL, 0); + } + } + } + if (s->z_err != Z_OK || s->z_eof) break; + } + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + + return (int)(len - s->stream.avail_out); +} + + +/* =========================================================================== + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ +int ZEXPORT gzgetc(file) + gzFile file; +{ + unsigned char c; + + return gzread(file, &c, 1) == 1 ? c : -1; +} + + +/* =========================================================================== + Reads bytes from the compressed file until len-1 characters are + read, or a newline character is read and transferred to buf, or an + end-of-file condition is encountered. The string is then terminated + with a null character. + gzgets returns buf, or Z_NULL in case of error. + + The current implementation is not optimized at all. +*/ +char * ZEXPORT gzgets(file, buf, len) + gzFile file; + char *buf; + int len; +{ + char *b = buf; + if (buf == Z_NULL || len <= 0) return Z_NULL; + + while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ; + *buf = '\0'; + return b == buf && len > 0 ? Z_NULL : b; +} + + +#ifndef NO_DEFLATE +/* =========================================================================== + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of bytes actually written (0 in case of error). +*/ +int ZEXPORT gzwrite (file, buf, len) + gzFile file; + const voidp buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.next_in = (Bytef*)buf; + s->stream.avail_in = len; + + while (s->stream.avail_in != 0) { + + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + break; + } + s->stream.avail_out = Z_BUFSIZE; + } + s->z_err = deflate(&(s->stream), Z_NO_FLUSH); + if (s->z_err != Z_OK) break; + } + s->crc = crc32(s->crc, (const Bytef *)buf, len); + + return (int)(len - s->stream.avail_in); +} + +/* =========================================================================== + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). +*/ +#ifdef STDC +#include + +int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...) +{ + char buf[Z_PRINTF_BUFSIZE]; + va_list va; + int len; + + va_start(va, format); +#ifdef HAS_vsnprintf + (void)vsnprintf(buf, sizeof(buf), format, va); +#else + (void)vsprintf(buf, format, va); +#endif + va_end(va); + len = strlen(buf); /* some *sprintf don't return the nb of bytes written */ + if (len <= 0) return 0; + + return gzwrite(file, buf, (unsigned)len); +} +#else /* not ANSI C */ + +int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + gzFile file; + const char *format; + int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; +{ + char buf[Z_PRINTF_BUFSIZE]; + int len; + +#ifdef HAS_snprintf + snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +#else + sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +#endif + len = strlen(buf); /* old sprintf doesn't return the nb of bytes written */ + if (len <= 0) return 0; + + return gzwrite(file, buf, len); +} +#endif + +/* =========================================================================== + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ +int ZEXPORT gzputc(file, c) + gzFile file; + int c; +{ + unsigned char cc = (unsigned char) c; /* required for big endian systems */ + + return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1; +} + + +/* =========================================================================== + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ +int ZEXPORT gzputs(file, s) + gzFile file; + const char *s; +{ + return gzwrite(file, (char*)s, (unsigned)strlen(s)); +} + + +/* =========================================================================== + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. +*/ +local int do_flush (file, flush) + gzFile file; + int flush; +{ + uInt len; + int done = 0; + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.avail_in = 0; /* should be zero already anyway */ + + for (;;) { + len = Z_BUFSIZE - s->stream.avail_out; + + if (len != 0) { + if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) { + s->z_err = Z_ERRNO; + return Z_ERRNO; + } + s->stream.next_out = s->outbuf; + s->stream.avail_out = Z_BUFSIZE; + } + if (done) break; + s->z_err = deflate(&(s->stream), flush); + + /* Ignore the second of two consecutive flushes: */ + if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK; + + /* deflate has finished flushing only when it hasn't used up + * all the available space in the output buffer: + */ + done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END); + + if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; + } + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} + +int ZEXPORT gzflush (file, flush) + gzFile file; + int flush; +{ + gz_stream *s = (gz_stream*)file; + int err = do_flush (file, flush); + + if (err) return err; + fflush(s->file); + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} +#endif /* NO_DEFLATE */ + +/* =========================================================================== + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error. + SEEK_END is not implemented, returns error. + In this version of the library, gzseek can be extremely slow. +*/ +z_off_t ZEXPORT gzseek (file, offset, whence) + gzFile file; + z_off_t offset; + int whence; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || whence == SEEK_END || + s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) { + return -1L; + } + + if (s->mode == 'w') { +#ifdef NO_DEFLATE + return -1L; +#else + if (whence == SEEK_SET) { + offset -= s->stream.total_in; + } + if (offset < 0) return -1L; + + /* At this point, offset is the number of zero bytes to write. */ + if (s->inbuf == Z_NULL) { + s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */ + zmemzero(s->inbuf, Z_BUFSIZE); + } + while (offset > 0) { + uInt size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (uInt)offset; + + size = gzwrite(file, s->inbuf, size); + if (size == 0) return -1L; + + offset -= size; + } + return (z_off_t)s->stream.total_in; +#endif + } + /* Rest of function is for reading only */ + + /* compute absolute position */ + if (whence == SEEK_CUR) { + offset += s->stream.total_out; + } + if (offset < 0) return -1L; + + if (s->transparent) { + /* map to fseek */ + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + if (fseek(s->file, offset, SEEK_SET) < 0) return -1L; + + s->stream.total_in = s->stream.total_out = (uLong)offset; + return offset; + } + + /* For a negative seek, rewind and use positive seek */ + if ((uLong)offset >= s->stream.total_out) { + offset -= s->stream.total_out; + } else if (gzrewind(file) < 0) { + return -1L; + } + /* offset is now the number of bytes to skip. */ + + if (offset != 0 && s->outbuf == Z_NULL) { + s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); + } + while (offset > 0) { + int size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (int)offset; + + size = gzread(file, s->outbuf, (uInt)size); + if (size <= 0) return -1L; + offset -= size; + } + return (z_off_t)s->stream.total_out; +} + +/* =========================================================================== + Rewinds input file. +*/ +int ZEXPORT gzrewind (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r') return -1; + + s->z_err = Z_OK; + s->z_eof = 0; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + s->crc = crc32(0L, Z_NULL, 0); + + if (s->startpos == 0) { /* not a compressed file */ + rewind(s->file); + return 0; + } + + (void) inflateReset(&s->stream); + return fseek(s->file, s->startpos, SEEK_SET); +} + +/* =========================================================================== + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. +*/ +z_off_t ZEXPORT gztell (file) + gzFile file; +{ + return gzseek(file, 0L, SEEK_CUR); +} + +/* =========================================================================== + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ +int ZEXPORT gzeof (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + return (s == NULL || s->mode != 'r') ? 0 : s->z_eof; +} + +/* =========================================================================== + Outputs a long in LSB order to the given file +*/ +local void putLong (file, x) + FILE *file; + uLong x; +{ + int n; + for (n = 0; n < 4; n++) { + fputc((int)(x & 0xff), file); + x >>= 8; + } +} + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets z_err in case + of error. +*/ +local uLong getLong (s) + gz_stream *s; +{ + uLong x = (uLong)get_byte(s); + int c; + + x += ((uLong)get_byte(s))<<8; + x += ((uLong)get_byte(s))<<16; + c = get_byte(s); + if (c == EOF) s->z_err = Z_DATA_ERROR; + x += ((uLong)c)<<24; + return x; +} + +/* =========================================================================== + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. +*/ +int ZEXPORT gzclose (file) + gzFile file; +{ + int err; + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return Z_STREAM_ERROR; + + if (s->mode == 'w') { +#ifdef NO_DEFLATE + return Z_STREAM_ERROR; +#else + err = do_flush (file, Z_FINISH); + if (err != Z_OK) return destroy((gz_stream*)file); + + putLong (s->file, s->crc); + putLong (s->file, s->stream.total_in); +#endif + } + return destroy((gz_stream*)file); +} + +/* =========================================================================== + Returns the error message for the last error which occured on the + given compressed file. errnum is set to zlib error number. If an + error occured in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ +const char* ZEXPORT gzerror (file, errnum) + gzFile file; + int *errnum; +{ + char *m; + gz_stream *s = (gz_stream*)file; + + if (s == NULL) { + *errnum = Z_STREAM_ERROR; + return (const char*)ERR_MSG(Z_STREAM_ERROR); + } + *errnum = s->z_err; + if (*errnum == Z_OK) return (const char*)""; + + m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg); + + if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err); + + TRYFREE(s->msg); + s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3); + strcpy(s->msg, s->path); + strcat(s->msg, ": "); + strcat(s->msg, m); + return (const char*)s->msg; +} diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/infblock.c b/contrib/vmap_extractor_v2/stormlib/zlib/infblock.c new file mode 100644 index 00000000000..dd7a6d40a8d --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/infblock.c @@ -0,0 +1,403 @@ +/* infblock.c -- interpret and process block types to last block + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "infblock.h" +#include "inftrees.h" +#include "infcodes.h" +#include "infutil.h" + +struct inflate_codes_state {int dummy;}; /* for buggy compilers */ + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + +/* Table for deflate from PKZIP's appnote.txt. */ +local const uInt border[] = { /* Order of the bit length code lengths */ + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + +/* + Notes beyond the 1.93a appnote.txt: + + 1. Distance pointers never point before the beginning of the output + stream. + 2. Distance pointers can point back across blocks, up to 32k away. + 3. There is an implied maximum of 7 bits for the bit length table and + 15 bits for the actual data. + 4. If only one code exists, then it is encoded using one bit. (Zero + would be more efficient, but perhaps a little confusing.) If two + codes exist, they are coded using one bit each (0 and 1). + 5. There is no way of sending zero distance codes--a dummy must be + sent if there are none. (History: a pre 2.0 version of PKZIP would + store blocks with no distance codes, but this was discovered to be + too harsh a criterion.) Valid only for 1.93a. 2.04c does allow + zero distance codes, which is sent as one code of zero bits in + length. + 6. There are up to 286 literal/length codes. Code 256 represents the + end-of-block. Note however that the static length tree defines + 288 codes just to fill out the Huffman codes. Codes 286 and 287 + cannot be used though, since there is no length base or extra bits + defined for them. Similarily, there are up to 30 distance codes. + However, static trees define 32 codes (all 5 bits) to fill out the + Huffman codes, but the last two had better not show up in the data. + 7. Unzip can check dynamic Huffman blocks for complete code sets. + The exception is that a single code would not be complete (see #4). + 8. The five bits following the block type is really the number of + literal codes sent minus 257. + 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits + (1+6+6). Therefore, to output three times the length, you output + three codes (1+1+1), whereas to output four times the same length, + you only need two codes (1+3). Hmm. + 10. In the tree reconstruction algorithm, Code = Code + Increment + only if BitLength(i) is not zero. (Pretty obvious.) + 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) + 12. Note: length code 284 can represent 227-258, but length code 285 + really is 258. The last length deserves its own, short code + since it gets used a lot in very redundant files. The length + 258 is special since 258 - 3 (the min match length) is 255. + 13. The literal/length and distance code bit lengths are read as a + single stream of lengths. It is possible (and advantageous) for + a repeat code (16, 17, or 18) to go across the boundary between + the two sets of lengths. + */ + + +void inflate_blocks_reset(s, z, c) +inflate_blocks_statef *s; +z_streamp z; +uLongf *c; +{ + if (c != Z_NULL) + *c = s->check; + if (s->mode == BTREE || s->mode == DTREE) + ZFREE(z, s->sub.trees.blens); + if (s->mode == CODES) + inflate_codes_free(s->sub.decode.codes, z); + s->mode = TYPE; + s->bitk = 0; + s->bitb = 0; + s->read = s->write = s->window; + if (s->checkfn != Z_NULL) + z->adler = s->check = (*s->checkfn)(0L, (const Bytef *)Z_NULL, 0); + Tracev((stderr, "inflate: blocks reset\n")); +} + + +inflate_blocks_statef *inflate_blocks_new(z, c, w) +z_streamp z; +check_func c; +uInt w; +{ + inflate_blocks_statef *s; + + if ((s = (inflate_blocks_statef *)ZALLOC + (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL) + return s; + if ((s->hufts = + (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL) + { + ZFREE(z, s); + return Z_NULL; + } + if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL) + { + ZFREE(z, s->hufts); + ZFREE(z, s); + return Z_NULL; + } + s->end = s->window + w; + s->checkfn = c; + s->mode = TYPE; + Tracev((stderr, "inflate: blocks allocated\n")); + inflate_blocks_reset(s, z, Z_NULL); + return s; +} + + +int inflate_blocks(s, z, r) +inflate_blocks_statef *s; +z_streamp z; +int r; +{ + uInt t; /* temporary storage */ + uLong b; /* bit buffer */ + uInt k; /* bits in bit buffer */ + Bytef *p; /* input data pointer */ + uInt n; /* bytes available there */ + Bytef *q; /* output window write pointer */ + uInt m; /* bytes to end of window or read pointer */ + + /* copy input/output information to locals (UPDATE macro restores) */ + LOAD + + /* process input based on current state */ + while (1) switch (s->mode) + { + case TYPE: + NEEDBITS(3) + t = (uInt)b & 7; + s->last = t & 1; + switch (t >> 1) + { + case 0: /* stored */ + Tracev((stderr, "inflate: stored block%s\n", + s->last ? " (last)" : "")); + DUMPBITS(3) + t = k & 7; /* go to byte boundary */ + DUMPBITS(t) + s->mode = LENS; /* get length of stored block */ + break; + case 1: /* fixed */ + Tracev((stderr, "inflate: fixed codes block%s\n", + s->last ? " (last)" : "")); + { + uInt bl, bd; + inflate_huft *tl, *td; + + inflate_trees_fixed(&bl, &bd, &tl, &td, z); + s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z); + if (s->sub.decode.codes == Z_NULL) + { + r = Z_MEM_ERROR; + LEAVE + } + } + DUMPBITS(3) + s->mode = CODES; + break; + case 2: /* dynamic */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + s->last ? " (last)" : "")); + DUMPBITS(3) + s->mode = TABLE; + break; + case 3: /* illegal */ + DUMPBITS(3) + s->mode = BAD; + z->msg = (char*)"invalid block type"; + r = Z_DATA_ERROR; + LEAVE + } + break; + case LENS: + NEEDBITS(32) + if ((((~b) >> 16) & 0xffff) != (b & 0xffff)) + { + s->mode = BAD; + z->msg = (char*)"invalid stored block lengths"; + r = Z_DATA_ERROR; + LEAVE + } + s->sub.left = (uInt)b & 0xffff; + b = k = 0; /* dump bits */ + Tracev((stderr, "inflate: stored length %u\n", s->sub.left)); + s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE); + break; + case STORED: + if (n == 0) + LEAVE + NEEDOUT + t = s->sub.left; + if (t > n) t = n; + if (t > m) t = m; + zmemcpy(q, p, t); + p += t; n -= t; + q += t; m -= t; + if ((s->sub.left -= t) != 0) + break; + Tracev((stderr, "inflate: stored end, %lu total out\n", + z->total_out + (q >= s->read ? q - s->read : + (s->end - s->read) + (q - s->window)))); + s->mode = s->last ? DRY : TYPE; + break; + case TABLE: + NEEDBITS(14) + s->sub.trees.table = t = (uInt)b & 0x3fff; +#ifndef PKZIP_BUG_WORKAROUND + if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) + { + s->mode = BAD; + z->msg = (char*)"too many length or distance symbols"; + r = Z_DATA_ERROR; + LEAVE + } +#endif + t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); + if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL) + { + r = Z_MEM_ERROR; + LEAVE + } + DUMPBITS(14) + s->sub.trees.index = 0; + Tracev((stderr, "inflate: table sizes ok\n")); + s->mode = BTREE; + case BTREE: + while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10)) + { + NEEDBITS(3) + s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7; + DUMPBITS(3) + } + while (s->sub.trees.index < 19) + s->sub.trees.blens[border[s->sub.trees.index++]] = 0; + s->sub.trees.bb = 7; + t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb, + &s->sub.trees.tb, s->hufts, z); + if (t != Z_OK) + { + r = t; + if (r == Z_DATA_ERROR) + { + ZFREE(z, s->sub.trees.blens); + s->mode = BAD; + } + LEAVE + } + s->sub.trees.index = 0; + Tracev((stderr, "inflate: bits tree ok\n")); + s->mode = DTREE; + case DTREE: + while (t = s->sub.trees.table, + s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) + { + inflate_huft *h; + uInt i, j, c; + + t = s->sub.trees.bb; + NEEDBITS(t) + h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]); + t = h->bits; + c = h->base; + if (c < 16) + { + DUMPBITS(t) + s->sub.trees.blens[s->sub.trees.index++] = c; + } + else /* c == 16..18 */ + { + i = c == 18 ? 7 : c - 14; + j = c == 18 ? 11 : 3; + NEEDBITS(t + i) + DUMPBITS(t) + j += (uInt)b & inflate_mask[i]; + DUMPBITS(i) + i = s->sub.trees.index; + t = s->sub.trees.table; + if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || + (c == 16 && i < 1)) + { + ZFREE(z, s->sub.trees.blens); + s->mode = BAD; + z->msg = (char*)"invalid bit length repeat"; + r = Z_DATA_ERROR; + LEAVE + } + c = c == 16 ? s->sub.trees.blens[i - 1] : 0; + do { + s->sub.trees.blens[i++] = c; + } while (--j); + s->sub.trees.index = i; + } + } + s->sub.trees.tb = Z_NULL; + { + uInt bl, bd; + inflate_huft *tl, *td; + inflate_codes_statef *c; + + bl = 9; /* must be <= 9 for lookahead assumptions */ + bd = 6; /* must be <= 9 for lookahead assumptions */ + t = s->sub.trees.table; + t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), + s->sub.trees.blens, &bl, &bd, &tl, &td, + s->hufts, z); + if (t != Z_OK) + { + if (t == (uInt)Z_DATA_ERROR) + { + ZFREE(z, s->sub.trees.blens); + s->mode = BAD; + } + r = t; + LEAVE + } + Tracev((stderr, "inflate: trees ok\n")); + if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL) + { + r = Z_MEM_ERROR; + LEAVE + } + s->sub.decode.codes = c; + } + ZFREE(z, s->sub.trees.blens); + s->mode = CODES; + case CODES: + UPDATE + if ((r = inflate_codes(s, z, r)) != Z_STREAM_END) + return inflate_flush(s, z, r); + r = Z_OK; + inflate_codes_free(s->sub.decode.codes, z); + LOAD + Tracev((stderr, "inflate: codes end, %lu total out\n", + z->total_out + (q >= s->read ? q - s->read : + (s->end - s->read) + (q - s->window)))); + if (!s->last) + { + s->mode = TYPE; + break; + } + s->mode = DRY; + case DRY: + FLUSH + if (s->read != s->write) + LEAVE + s->mode = DONE; + case DONE: + r = Z_STREAM_END; + LEAVE + case BAD: + r = Z_DATA_ERROR; + LEAVE + default: + r = Z_STREAM_ERROR; + LEAVE + } +} + + +int inflate_blocks_free(s, z) +inflate_blocks_statef *s; +z_streamp z; +{ + inflate_blocks_reset(s, z, Z_NULL); + ZFREE(z, s->window); + ZFREE(z, s->hufts); + ZFREE(z, s); + Tracev((stderr, "inflate: blocks freed\n")); + return Z_OK; +} + + +void inflate_set_dictionary(s, d, n) +inflate_blocks_statef *s; +const Bytef *d; +uInt n; +{ + zmemcpy(s->window, d, n); + s->read = s->write = s->window + n; +} + + +/* Returns true if inflate is currently at the end of a block generated + * by Z_SYNC_FLUSH or Z_FULL_FLUSH. + * IN assertion: s != Z_NULL + */ +int inflate_blocks_sync_point(s) +inflate_blocks_statef *s; +{ + return s->mode == LENS; +} diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/infblock.h b/contrib/vmap_extractor_v2/stormlib/zlib/infblock.h new file mode 100644 index 00000000000..173b2267ade --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/infblock.h @@ -0,0 +1,39 @@ +/* infblock.h -- header to use infblock.c + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +struct inflate_blocks_state; +typedef struct inflate_blocks_state FAR inflate_blocks_statef; + +extern inflate_blocks_statef * inflate_blocks_new OF(( + z_streamp z, + check_func c, /* check function */ + uInt w)); /* window size */ + +extern int inflate_blocks OF(( + inflate_blocks_statef *, + z_streamp , + int)); /* initial return code */ + +extern void inflate_blocks_reset OF(( + inflate_blocks_statef *, + z_streamp , + uLongf *)); /* check value on output */ + +extern int inflate_blocks_free OF(( + inflate_blocks_statef *, + z_streamp)); + +extern void inflate_set_dictionary OF(( + inflate_blocks_statef *s, + const Bytef *d, /* dictionary */ + uInt n)); /* dictionary length */ + +extern int inflate_blocks_sync_point OF(( + inflate_blocks_statef *s)); diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/infcodes.c b/contrib/vmap_extractor_v2/stormlib/zlib/infcodes.c new file mode 100644 index 00000000000..9abe5412b9c --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/infcodes.c @@ -0,0 +1,251 @@ +/* infcodes.c -- process literals and length/distance pairs + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "infblock.h" +#include "infcodes.h" +#include "infutil.h" +#include "inffast.h" + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + +typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ + START, /* x: set up for LEN */ + LEN, /* i: get length/literal/eob next */ + LENEXT, /* i: getting length extra (have base) */ + DIST, /* i: get distance next */ + DISTEXT, /* i: getting distance extra */ + COPY, /* o: copying bytes in window, waiting for space */ + LIT, /* o: got literal, waiting for output space */ + WASH, /* o: got eob, possibly still output waiting */ + END, /* x: got eob and all data flushed */ + BADCODE} /* x: got error */ +inflate_codes_mode; + +/* inflate codes private state */ +struct inflate_codes_state { + + /* mode */ + inflate_codes_mode mode; /* current inflate_codes mode */ + + /* mode dependent information */ + uInt len; + union { + struct { + inflate_huft *tree; /* pointer into tree */ + uInt need; /* bits needed */ + } code; /* if LEN or DIST, where in tree */ + uInt lit; /* if LIT, literal */ + struct { + uInt get; /* bits to get for extra */ + uInt dist; /* distance back to copy from */ + } copy; /* if EXT or COPY, where and how much */ + } sub; /* submode */ + + /* mode independent information */ + Byte lbits; /* ltree bits decoded per branch */ + Byte dbits; /* dtree bits decoder per branch */ + inflate_huft *ltree; /* literal/length/eob tree */ + inflate_huft *dtree; /* distance tree */ + +}; + + +inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z) +uInt bl, bd; +inflate_huft *tl; +inflate_huft *td; /* need separate declaration for Borland C++ */ +z_streamp z; +{ + inflate_codes_statef *c; + + if ((c = (inflate_codes_statef *) + ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL) + { + c->mode = START; + c->lbits = (Byte)bl; + c->dbits = (Byte)bd; + c->ltree = tl; + c->dtree = td; + Tracev((stderr, "inflate: codes new\n")); + } + return c; +} + + +int inflate_codes(s, z, r) +inflate_blocks_statef *s; +z_streamp z; +int r; +{ + uInt j; /* temporary storage */ + inflate_huft *t; /* temporary pointer */ + uInt e; /* extra bits or operation */ + uLong b; /* bit buffer */ + uInt k; /* bits in bit buffer */ + Bytef *p; /* input data pointer */ + uInt n; /* bytes available there */ + Bytef *q; /* output window write pointer */ + uInt m; /* bytes to end of window or read pointer */ + Bytef *f; /* pointer to copy strings from */ + inflate_codes_statef *c = s->sub.decode.codes; /* codes state */ + + /* copy input/output information to locals (UPDATE macro restores) */ + LOAD + + /* process input and output based on current state */ + while (1) switch (c->mode) + { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ + case START: /* x: set up for LEN */ +#ifndef SLOW + if (m >= 258 && n >= 10) + { + UPDATE + r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z); + LOAD + if (r != Z_OK) + { + c->mode = r == Z_STREAM_END ? WASH : BADCODE; + break; + } + } +#endif /* !SLOW */ + c->sub.code.need = c->lbits; + c->sub.code.tree = c->ltree; + c->mode = LEN; + case LEN: /* i: get length/literal/eob next */ + j = c->sub.code.need; + NEEDBITS(j) + t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); + DUMPBITS(t->bits) + e = (uInt)(t->exop); + if (e == 0) /* literal */ + { + c->sub.lit = t->base; + Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", t->base)); + c->mode = LIT; + break; + } + if (e & 16) /* length */ + { + c->sub.copy.get = e & 15; + c->len = t->base; + c->mode = LENEXT; + break; + } + if ((e & 64) == 0) /* next table */ + { + c->sub.code.need = e; + c->sub.code.tree = t + t->base; + break; + } + if (e & 32) /* end of block */ + { + Tracevv((stderr, "inflate: end of block\n")); + c->mode = WASH; + break; + } + c->mode = BADCODE; /* invalid code */ + z->msg = (char*)"invalid literal/length code"; + r = Z_DATA_ERROR; + LEAVE + case LENEXT: /* i: getting length extra (have base) */ + j = c->sub.copy.get; + NEEDBITS(j) + c->len += (uInt)b & inflate_mask[j]; + DUMPBITS(j) + c->sub.code.need = c->dbits; + c->sub.code.tree = c->dtree; + Tracevv((stderr, "inflate: length %u\n", c->len)); + c->mode = DIST; + case DIST: /* i: get distance next */ + j = c->sub.code.need; + NEEDBITS(j) + t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); + DUMPBITS(t->bits) + e = (uInt)(t->exop); + if (e & 16) /* distance */ + { + c->sub.copy.get = e & 15; + c->sub.copy.dist = t->base; + c->mode = DISTEXT; + break; + } + if ((e & 64) == 0) /* next table */ + { + c->sub.code.need = e; + c->sub.code.tree = t + t->base; + break; + } + c->mode = BADCODE; /* invalid code */ + z->msg = (char*)"invalid distance code"; + r = Z_DATA_ERROR; + LEAVE + case DISTEXT: /* i: getting distance extra */ + j = c->sub.copy.get; + NEEDBITS(j) + c->sub.copy.dist += (uInt)b & inflate_mask[j]; + DUMPBITS(j) + Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist)); + c->mode = COPY; + case COPY: /* o: copying bytes in window, waiting for space */ + f = q - c->sub.copy.dist; + while (f < s->window) /* modulo window size-"while" instead */ + f += s->end - s->window; /* of "if" handles invalid distances */ + while (c->len) + { + NEEDOUT + OUTBYTE(*f++) + if (f == s->end) + f = s->window; + c->len--; + } + c->mode = START; + break; + case LIT: /* o: got literal, waiting for output space */ + NEEDOUT + OUTBYTE(c->sub.lit) + c->mode = START; + break; + case WASH: /* o: got eob, possibly more output */ + if (k > 7) /* return unused byte, if any */ + { + Assert(k < 16, "inflate_codes grabbed too many bytes") + k -= 8; + n++; + p--; /* can always return one */ + } + FLUSH + if (s->read != s->write) + LEAVE + c->mode = END; + case END: + r = Z_STREAM_END; + LEAVE + case BADCODE: /* x: got error */ + r = Z_DATA_ERROR; + LEAVE + default: + r = Z_STREAM_ERROR; + LEAVE + } +#ifdef NEED_DUMMY_RETURN + return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ +#endif +} + + +void inflate_codes_free(c, z) +inflate_codes_statef *c; +z_streamp z; +{ + ZFREE(z, c); + Tracev((stderr, "inflate: codes free\n")); +} diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/infcodes.h b/contrib/vmap_extractor_v2/stormlib/zlib/infcodes.h new file mode 100644 index 00000000000..46821a02be6 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/infcodes.h @@ -0,0 +1,27 @@ +/* infcodes.h -- header to use infcodes.c + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +struct inflate_codes_state; +typedef struct inflate_codes_state FAR inflate_codes_statef; + +extern inflate_codes_statef *inflate_codes_new OF(( + uInt, uInt, + inflate_huft *, inflate_huft *, + z_streamp )); + +extern int inflate_codes OF(( + inflate_blocks_statef *, + z_streamp , + int)); + +extern void inflate_codes_free OF(( + inflate_codes_statef *, + z_streamp )); + diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/inffast.c b/contrib/vmap_extractor_v2/stormlib/zlib/inffast.c new file mode 100644 index 00000000000..aa7f1d4d2ad --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/inffast.c @@ -0,0 +1,183 @@ +/* inffast.c -- process literals and length/distance pairs fast + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "infblock.h" +#include "infcodes.h" +#include "infutil.h" +#include "inffast.h" + +struct inflate_codes_state {int dummy;}; /* for buggy compilers */ + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + +/* macros for bit input with no checking and for returning unused bytes */ +#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<avail_in-n;c=(k>>3)>3:c;n+=c;p-=c;k-=c<<3;} + +/* Called with number of bytes left to write in window at least 258 + (the maximum string length) and number of input bytes available + at least ten. The ten bytes are six bytes for the longest length/ + distance pair plus four bytes for overloading the bit buffer. */ + +int inflate_fast(bl, bd, tl, td, s, z) +uInt bl, bd; +inflate_huft *tl; +inflate_huft *td; /* need separate declaration for Borland C++ */ +inflate_blocks_statef *s; +z_streamp z; +{ + inflate_huft *t; /* temporary pointer */ + uInt e; /* extra bits or operation */ + uLong b; /* bit buffer */ + uInt k; /* bits in bit buffer */ + Bytef *p; /* input data pointer */ + uInt n; /* bytes available there */ + Bytef *q; /* output window write pointer */ + uInt m; /* bytes to end of window or read pointer */ + uInt ml; /* mask for literal/length tree */ + uInt md; /* mask for distance tree */ + uInt c; /* bytes to copy */ + uInt d; /* distance back to copy from */ + Bytef *r; /* copy source pointer */ + + /* load input, output, bit values */ + LOAD + + /* initialize masks */ + ml = inflate_mask[bl]; + md = inflate_mask[bd]; + + /* do until not enough input or output space for fast loop */ + do { /* assume called with m >= 258 && n >= 10 */ + /* get literal/length code */ + GRABBITS(20) /* max bits for literal/length code */ + if ((e = (t = tl + ((uInt)b & ml))->exop) == 0) + { + DUMPBITS(t->bits) + Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? + "inflate: * literal '%c'\n" : + "inflate: * literal 0x%02x\n", t->base)); + *q++ = (Byte)t->base; + m--; + continue; + } + do { + DUMPBITS(t->bits) + if (e & 16) + { + /* get extra bits for length */ + e &= 15; + c = t->base + ((uInt)b & inflate_mask[e]); + DUMPBITS(e) + Tracevv((stderr, "inflate: * length %u\n", c)); + + /* decode distance base of block to copy */ + GRABBITS(15); /* max bits for distance code */ + e = (t = td + ((uInt)b & md))->exop; + do { + DUMPBITS(t->bits) + if (e & 16) + { + /* get extra bits to add to distance base */ + e &= 15; + GRABBITS(e) /* get extra bits (up to 13) */ + d = t->base + ((uInt)b & inflate_mask[e]); + DUMPBITS(e) + Tracevv((stderr, "inflate: * distance %u\n", d)); + + /* do the copy */ + m -= c; + r = q - d; + if (r < s->window) /* wrap if needed */ + { + do { + r += s->end - s->window; /* force pointer in window */ + } while (r < s->window); /* covers invalid distances */ + e = s->end - r; + if (c > e) + { + c -= e; /* wrapped copy */ + do { + *q++ = *r++; + } while (--e); + r = s->window; + do { + *q++ = *r++; + } while (--c); + } + else /* normal copy */ + { + *q++ = *r++; c--; + *q++ = *r++; c--; + do { + *q++ = *r++; + } while (--c); + } + } + else /* normal copy */ + { + *q++ = *r++; c--; + *q++ = *r++; c--; + do { + *q++ = *r++; + } while (--c); + } + break; + } + else if ((e & 64) == 0) + { + t += t->base; + e = (t += ((uInt)b & inflate_mask[e]))->exop; + } + else + { + z->msg = (char*)"invalid distance code"; + UNGRAB + UPDATE + return Z_DATA_ERROR; + } + } while (1); + break; + } + if ((e & 64) == 0) + { + t += t->base; + if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0) + { + DUMPBITS(t->bits) + Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? + "inflate: * literal '%c'\n" : + "inflate: * literal 0x%02x\n", t->base)); + *q++ = (Byte)t->base; + m--; + break; + } + } + else if (e & 32) + { + Tracevv((stderr, "inflate: * end of block\n")); + UNGRAB + UPDATE + return Z_STREAM_END; + } + else + { + z->msg = (char*)"invalid literal/length code"; + UNGRAB + UPDATE + return Z_DATA_ERROR; + } + } while (1); + } while (m >= 258 && n >= 10); + + /* not enough input or output--restore pointers and return */ + UNGRAB + UPDATE + return Z_OK; +} diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/inffast.h b/contrib/vmap_extractor_v2/stormlib/zlib/inffast.h new file mode 100644 index 00000000000..a31a4bbb058 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/inffast.h @@ -0,0 +1,17 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +extern int inflate_fast OF(( + uInt, + uInt, + inflate_huft *, + inflate_huft *, + inflate_blocks_statef *, + z_streamp )); diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/inffixed.h b/contrib/vmap_extractor_v2/stormlib/zlib/inffixed.h new file mode 100644 index 00000000000..77f7e763145 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/inffixed.h @@ -0,0 +1,151 @@ +/* inffixed.h -- table for decoding fixed codes + * Generated automatically by the maketree.c program + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +local uInt fixed_bl = 9; +local uInt fixed_bd = 5; +local inflate_huft fixed_tl[] = { + {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, + {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192}, + {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160}, + {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224}, + {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144}, + {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208}, + {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176}, + {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240}, + {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, + {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200}, + {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168}, + {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232}, + {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152}, + {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216}, + {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184}, + {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248}, + {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, + {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196}, + {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164}, + {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228}, + {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148}, + {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212}, + {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180}, + {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244}, + {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, + {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204}, + {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172}, + {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236}, + {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156}, + {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220}, + {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188}, + {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252}, + {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, + {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194}, + {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162}, + {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226}, + {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146}, + {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210}, + {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178}, + {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242}, + {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, + {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202}, + {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170}, + {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234}, + {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154}, + {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218}, + {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186}, + {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250}, + {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, + {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198}, + {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166}, + {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230}, + {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150}, + {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214}, + {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182}, + {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246}, + {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, + {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206}, + {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174}, + {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238}, + {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158}, + {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222}, + {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190}, + {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254}, + {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, + {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193}, + {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161}, + {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225}, + {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145}, + {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209}, + {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177}, + {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241}, + {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, + {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201}, + {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169}, + {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233}, + {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153}, + {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217}, + {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185}, + {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249}, + {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, + {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197}, + {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165}, + {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229}, + {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149}, + {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213}, + {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181}, + {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245}, + {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, + {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205}, + {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173}, + {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237}, + {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157}, + {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221}, + {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189}, + {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253}, + {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, + {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195}, + {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163}, + {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227}, + {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147}, + {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211}, + {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179}, + {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243}, + {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, + {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203}, + {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171}, + {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235}, + {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155}, + {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219}, + {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187}, + {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251}, + {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, + {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199}, + {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167}, + {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231}, + {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151}, + {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215}, + {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183}, + {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247}, + {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, + {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207}, + {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175}, + {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239}, + {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159}, + {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223}, + {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191}, + {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255} + }; +local inflate_huft fixed_td[] = { + {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097}, + {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385}, + {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193}, + {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577}, + {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145}, + {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577}, + {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289}, + {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577} + }; diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/inflate.c b/contrib/vmap_extractor_v2/stormlib/zlib/inflate.c new file mode 100644 index 00000000000..dfb2e867d81 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/inflate.c @@ -0,0 +1,366 @@ +/* inflate.c -- zlib interface to inflate modules + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "infblock.h" + +struct inflate_blocks_state {int dummy;}; /* for buggy compilers */ + +typedef enum { + METHOD, /* waiting for method byte */ + FLAG, /* waiting for flag byte */ + DICT4, /* four dictionary check bytes to go */ + DICT3, /* three dictionary check bytes to go */ + DICT2, /* two dictionary check bytes to go */ + DICT1, /* one dictionary check byte to go */ + DICT0, /* waiting for inflateSetDictionary */ + BLOCKS, /* decompressing blocks */ + CHECK4, /* four check bytes to go */ + CHECK3, /* three check bytes to go */ + CHECK2, /* two check bytes to go */ + CHECK1, /* one check byte to go */ + DONE, /* finished check, done */ + BAD} /* got an error--stay here */ +inflate_mode; + +/* inflate private state */ +struct internal_state { + + /* mode */ + inflate_mode mode; /* current inflate mode */ + + /* mode dependent information */ + union { + uInt method; /* if FLAGS, method byte */ + struct { + uLong was; /* computed check value */ + uLong need; /* stream check value */ + } check; /* if CHECK, check values to compare */ + uInt marker; /* if BAD, inflateSync's marker bytes count */ + } sub; /* submode */ + + /* mode independent information */ + int nowrap; /* flag for no wrapper */ + uInt wbits; /* log2(window size) (8..15, defaults to 15) */ + inflate_blocks_statef + *blocks; /* current inflate_blocks state */ + +}; + + +int ZEXPORT inflateReset(z) +z_streamp z; +{ + if (z == Z_NULL || z->state == Z_NULL) + return Z_STREAM_ERROR; + z->total_in = z->total_out = 0; + z->msg = Z_NULL; + z->state->mode = z->state->nowrap ? BLOCKS : METHOD; + inflate_blocks_reset(z->state->blocks, z, Z_NULL); + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + + +int ZEXPORT inflateEnd(z) +z_streamp z; +{ + if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) + return Z_STREAM_ERROR; + if (z->state->blocks != Z_NULL) + inflate_blocks_free(z->state->blocks, z); + ZFREE(z, z->state); + z->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + + +int ZEXPORT inflateInit2_(z, w, version, stream_size) +z_streamp z; +int w; +const char *version; +int stream_size; +{ + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != sizeof(z_stream)) + return Z_VERSION_ERROR; + + /* initialize state */ + if (z == Z_NULL) + return Z_STREAM_ERROR; + z->msg = Z_NULL; + if (z->zalloc == Z_NULL) + { + z->zalloc = zcalloc; + z->opaque = (voidpf)0; + } + if (z->zfree == Z_NULL) z->zfree = zcfree; + if ((z->state = (struct internal_state FAR *) + ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL) + return Z_MEM_ERROR; + z->state->blocks = Z_NULL; + + /* handle undocumented nowrap option (no zlib header or check) */ + z->state->nowrap = 0; + if (w < 0) + { + w = - w; + z->state->nowrap = 1; + } + + /* set window size */ + if (w < 8 || w > 15) + { + inflateEnd(z); + return Z_STREAM_ERROR; + } + z->state->wbits = (uInt)w; + + /* create inflate_blocks state */ + if ((z->state->blocks = + inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w)) + == Z_NULL) + { + inflateEnd(z); + return Z_MEM_ERROR; + } + Tracev((stderr, "inflate: allocated\n")); + + /* reset state */ + inflateReset(z); + return Z_OK; +} + + +int ZEXPORT inflateInit_(z, version, stream_size) +z_streamp z; +const char *version; +int stream_size; +{ + return inflateInit2_(z, DEF_WBITS, version, stream_size); +} + + +#define NEEDBYTE {if(z->avail_in==0)return r;r=f;} +#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) + +int ZEXPORT inflate(z, f) +z_streamp z; +int f; +{ + int r; + uInt b; + + if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL) + return Z_STREAM_ERROR; + f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK; + r = Z_BUF_ERROR; + while (1) switch (z->state->mode) + { + case METHOD: + NEEDBYTE + if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED) + { + z->state->mode = BAD; + z->msg = (char*)"unknown compression method"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + if ((z->state->sub.method >> 4) + 8 > z->state->wbits) + { + z->state->mode = BAD; + z->msg = (char*)"invalid window size"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + z->state->mode = FLAG; + case FLAG: + NEEDBYTE + b = NEXTBYTE; + if (((z->state->sub.method << 8) + b) % 31) + { + z->state->mode = BAD; + z->msg = (char*)"incorrect header check"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + Tracev((stderr, "inflate: zlib header ok\n")); + if (!(b & PRESET_DICT)) + { + z->state->mode = BLOCKS; + break; + } + z->state->mode = DICT4; + case DICT4: + NEEDBYTE + z->state->sub.check.need = (uLong)NEXTBYTE << 24; + z->state->mode = DICT3; + case DICT3: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE << 16; + z->state->mode = DICT2; + case DICT2: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE << 8; + z->state->mode = DICT1; + case DICT1: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE; + z->adler = z->state->sub.check.need; + z->state->mode = DICT0; + return Z_NEED_DICT; + case DICT0: + z->state->mode = BAD; + z->msg = (char*)"need dictionary"; + z->state->sub.marker = 0; /* can try inflateSync */ + return Z_STREAM_ERROR; + case BLOCKS: + r = inflate_blocks(z->state->blocks, z, r); + if (r == Z_DATA_ERROR) + { + z->state->mode = BAD; + z->state->sub.marker = 0; /* can try inflateSync */ + break; + } + if (r == Z_OK) + r = f; + if (r != Z_STREAM_END) + return r; + r = f; + inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); + if (z->state->nowrap) + { + z->state->mode = DONE; + break; + } + z->state->mode = CHECK4; + case CHECK4: + NEEDBYTE + z->state->sub.check.need = (uLong)NEXTBYTE << 24; + z->state->mode = CHECK3; + case CHECK3: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE << 16; + z->state->mode = CHECK2; + case CHECK2: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE << 8; + z->state->mode = CHECK1; + case CHECK1: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE; + + if (z->state->sub.check.was != z->state->sub.check.need) + { + z->state->mode = BAD; + z->msg = (char*)"incorrect data check"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + Tracev((stderr, "inflate: zlib check ok\n")); + z->state->mode = DONE; + case DONE: + return Z_STREAM_END; + case BAD: + return Z_DATA_ERROR; + default: + return Z_STREAM_ERROR; + } +#ifdef NEED_DUMMY_RETURN + return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ +#endif +} + + +int ZEXPORT inflateSetDictionary(z, dictionary, dictLength) +z_streamp z; +const Bytef *dictionary; +uInt dictLength; +{ + uInt length = dictLength; + + if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0) + return Z_STREAM_ERROR; + + if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR; + z->adler = 1L; + + if (length >= ((uInt)1<state->wbits)) + { + length = (1<state->wbits)-1; + dictionary += dictLength - length; + } + inflate_set_dictionary(z->state->blocks, dictionary, length); + z->state->mode = BLOCKS; + return Z_OK; +} + + +int ZEXPORT inflateSync(z) +z_streamp z; +{ + uInt n; /* number of bytes to look at */ + Bytef *p; /* pointer to bytes */ + uInt m; /* number of marker bytes found in a row */ + uLong r, w; /* temporaries to save total_in and total_out */ + + /* set up */ + if (z == Z_NULL || z->state == Z_NULL) + return Z_STREAM_ERROR; + if (z->state->mode != BAD) + { + z->state->mode = BAD; + z->state->sub.marker = 0; + } + if ((n = z->avail_in) == 0) + return Z_BUF_ERROR; + p = z->next_in; + m = z->state->sub.marker; + + /* search */ + while (n && m < 4) + { + static const Byte mark[4] = {0, 0, 0xff, 0xff}; + if (*p == mark[m]) + m++; + else if (*p) + m = 0; + else + m = 4 - m; + p++, n--; + } + + /* restore */ + z->total_in += p - z->next_in; + z->next_in = p; + z->avail_in = n; + z->state->sub.marker = m; + + /* return no joy or set up to restart on a new block */ + if (m != 4) + return Z_DATA_ERROR; + r = z->total_in; w = z->total_out; + inflateReset(z); + z->total_in = r; z->total_out = w; + z->state->mode = BLOCKS; + return Z_OK; +} + + +/* Returns true if inflate is currently at the end of a block generated + * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH + * but removes the length bytes of the resulting empty stored block. When + * decompressing, PPP checks that at the end of input packet, inflate is + * waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(z) +z_streamp z; +{ + if (z == Z_NULL || z->state == Z_NULL || z->state->blocks == Z_NULL) + return Z_STREAM_ERROR; + return inflate_blocks_sync_point(z->state->blocks); +} diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/inftrees.c b/contrib/vmap_extractor_v2/stormlib/zlib/inftrees.c new file mode 100644 index 00000000000..4c32ca30d99 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/inftrees.c @@ -0,0 +1,454 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#if !defined(BUILDFIXED) && !defined(STDC) +# define BUILDFIXED /* non ANSI compilers may not accept inffixed.h */ +#endif + +const char inflate_copyright[] = + " inflate 1.1.4 Copyright 1995-2002 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ +struct internal_state {int dummy;}; /* for buggy compilers */ + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + + +local int huft_build OF(( + uIntf *, /* code lengths in bits */ + uInt, /* number of codes */ + uInt, /* number of "simple" codes */ + const uIntf *, /* list of base values for non-simple codes */ + const uIntf *, /* list of extra bits for non-simple codes */ + inflate_huft * FAR*,/* result: starting table */ + uIntf *, /* maximum lookup bits (returns actual) */ + inflate_huft *, /* space for trees */ + uInt *, /* hufts used in space */ + uIntf * )); /* space for values */ + +/* Tables for deflate from PKZIP's appnote.txt. */ +local const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + /* see note #13 above about 258 */ +local const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */ +local const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577}; +local const uInt cpdext[30] = { /* Extra bits for distance codes */ + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13}; + +/* + Huffman code decoding is performed using a multi-level table lookup. + The fastest way to decode is to simply build a lookup table whose + size is determined by the longest code. However, the time it takes + to build this table can also be a factor if the data being decoded + is not very long. The most common codes are necessarily the + shortest codes, so those codes dominate the decoding time, and hence + the speed. The idea is you can have a shorter table that decodes the + shorter, more probable codes, and then point to subsidiary tables for + the longer codes. The time it costs to decode the longer codes is + then traded against the time it takes to make longer tables. + + This results of this trade are in the variables lbits and dbits + below. lbits is the number of bits the first level table for literal/ + length codes can decode in one step, and dbits is the same thing for + the distance codes. Subsequent tables are also less than or equal to + those sizes. These values may be adjusted either when all of the + codes are shorter than that, in which case the longest code length in + bits is used, or when the shortest code is *longer* than the requested + table size, in which case the length of the shortest code in bits is + used. + + There are two different values for the two tables, since they code a + different number of possibilities each. The literal/length table + codes 286 possible values, or in a flat code, a little over eight + bits. The distance table codes 30 possible values, or a little less + than five bits, flat. The optimum values for speed end up being + about one bit more than those, so lbits is 8+1 and dbits is 5+1. + The optimum values may differ though from machine to machine, and + possibly even between compilers. Your mileage may vary. + */ + + +/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */ +#define BMAX 15 /* maximum bit length of any code */ + +local int huft_build(b, n, s, d, e, t, m, hp, hn, v) +uIntf *b; /* code lengths in bits (all assumed <= BMAX) */ +uInt n; /* number of codes (assumed <= 288) */ +uInt s; /* number of simple-valued codes (0..s-1) */ +const uIntf *d; /* list of base values for non-simple codes */ +const uIntf *e; /* list of extra bits for non-simple codes */ +inflate_huft * FAR *t; /* result: starting table */ +uIntf *m; /* maximum lookup bits, returns actual */ +inflate_huft *hp; /* space for trees */ +uInt *hn; /* hufts used in space */ +uIntf *v; /* working area: values in order of bit length */ +/* Given a list of code lengths and a maximum table size, make a set of + tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR + if the given code set is incomplete (the tables are still built in this + case), or Z_DATA_ERROR if the input is invalid. */ +{ + + uInt a; /* counter for codes of length k */ + uInt c[BMAX+1]; /* bit length count table */ + uInt f; /* i repeats in table every f entries */ + int g; /* maximum code length */ + int h; /* table level */ + register uInt i; /* counter, current code */ + register uInt j; /* counter */ + register int k; /* number of bits in current code */ + int l; /* bits per table (returned in m) */ + uInt mask; /* (1 << w) - 1, to avoid cc -O bug on HP */ + register uIntf *p; /* pointer into c[], b[], or v[] */ + inflate_huft *q; /* points to current table */ + struct inflate_huft_s r; /* table entry for structure assignment */ + inflate_huft *u[BMAX]; /* table stack */ + register int w; /* bits before this table == (l * h) */ + uInt x[BMAX+1]; /* bit offsets, then code stack */ + uIntf *xp; /* pointer into x */ + int y; /* number of dummy codes added */ + uInt z; /* number of entries in current table */ + + + /* Generate counts for each bit length */ + p = c; +#define C0 *p++ = 0; +#define C2 C0 C0 C0 C0 +#define C4 C2 C2 C2 C2 + C4 /* clear c[]--assume BMAX+1 is 16 */ + p = b; i = n; + do { + c[*p++]++; /* assume all entries <= BMAX */ + } while (--i); + if (c[0] == n) /* null input--all zero length codes */ + { + *t = (inflate_huft *)Z_NULL; + *m = 0; + return Z_OK; + } + + + /* Find minimum and maximum length, bound *m by those */ + l = *m; + for (j = 1; j <= BMAX; j++) + if (c[j]) + break; + k = j; /* minimum code length */ + if ((uInt)l < j) + l = j; + for (i = BMAX; i; i--) + if (c[i]) + break; + g = i; /* maximum code length */ + if ((uInt)l > i) + l = i; + *m = l; + + + /* Adjust last length count to fill out codes, if needed */ + for (y = 1 << j; j < i; j++, y <<= 1) + if ((y -= c[j]) < 0) + return Z_DATA_ERROR; + if ((y -= c[i]) < 0) + return Z_DATA_ERROR; + c[i] += y; + + + /* Generate starting offsets into the value table for each length */ + x[1] = j = 0; + p = c + 1; xp = x + 2; + while (--i) { /* note that i == g from above */ + *xp++ = (j += *p++); + } + + + /* Make a table of values in order of bit lengths */ + p = b; i = 0; + do { + if ((j = *p++) != 0) + v[x[j]++] = i; + } while (++i < n); + n = x[g]; /* set n to length of v */ + + + /* Generate the Huffman codes and for each, make the table entries */ + x[0] = i = 0; /* first Huffman code is zero */ + p = v; /* grab values in bit order */ + h = -1; /* no tables yet--level -1 */ + w = -l; /* bits decoded == (l * h) */ + u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */ + q = (inflate_huft *)Z_NULL; /* ditto */ + z = 0; /* ditto */ + + /* go through the bit lengths (k already is bits in shortest code) */ + for (; k <= g; k++) + { + a = c[k]; + while (a--) + { + /* here i is the Huffman code of length k bits for value *p */ + /* make tables up to required level */ + while (k > w + l) + { + h++; + w += l; /* previous table always l bits */ + + /* compute minimum size table less than or equal to l bits */ + z = g - w; + z = z > (uInt)l ? l : z; /* table size upper limit */ + if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ + { /* too few codes for k-w bit table */ + f -= a + 1; /* deduct codes from patterns left */ + xp = c + k; + if (j < z) + while (++j < z) /* try smaller tables up to z bits */ + { + if ((f <<= 1) <= *++xp) + break; /* enough codes to use up j bits */ + f -= *xp; /* else deduct codes from patterns */ + } + } + z = 1 << j; /* table entries for j-bit table */ + + /* allocate new table */ + if (*hn + z > MANY) /* (note: doesn't matter for fixed) */ + return Z_DATA_ERROR; /* overflow of MANY */ + u[h] = q = hp + *hn; + *hn += z; + + /* connect to last table, if there is one */ + if (h) + { + x[h] = i; /* save pattern for backing up */ + r.bits = (Byte)l; /* bits to dump before this table */ + r.exop = (Byte)j; /* bits in this table */ + j = i >> (w - l); + r.base = (uInt)(q - u[h-1] - j); /* offset to this table */ + u[h-1][j] = r; /* connect to last table */ + } + else + *t = q; /* first table is returned result */ + } + + /* set up table entry in r */ + r.bits = (Byte)(k - w); + if (p >= v + n) + r.exop = 128 + 64; /* out of values--invalid code */ + else if (*p < s) + { + r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */ + r.base = *p++; /* simple code is just the value */ + } + else + { + r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */ + r.base = d[*p++ - s]; + } + + /* fill code-like entries with r */ + f = 1 << (k - w); + for (j = i >> w; j < z; j += f) + q[j] = r; + + /* backwards increment the k-bit code i */ + for (j = 1 << (k - 1); i & j; j >>= 1) + i ^= j; + i ^= j; + + /* backup over finished tables */ + mask = (1 << w) - 1; /* needed on HP, cc -O bug */ + while ((i & mask) != x[h]) + { + h--; /* don't need to update q */ + w -= l; + mask = (1 << w) - 1; + } + } + } + + + /* Return Z_BUF_ERROR if we were given an incomplete table */ + return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; +} + + +int inflate_trees_bits(c, bb, tb, hp, z) +uIntf *c; /* 19 code lengths */ +uIntf *bb; /* bits tree desired/actual depth */ +inflate_huft * FAR *tb; /* bits tree result */ +inflate_huft *hp; /* space for trees */ +z_streamp z; /* for messages */ +{ + int r; + uInt hn = 0; /* hufts used in space */ + uIntf *v; /* work area for huft_build */ + + if ((v = (uIntf*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL) + return Z_MEM_ERROR; + r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, + tb, bb, hp, &hn, v); + if (r == Z_DATA_ERROR) + z->msg = (char*)"oversubscribed dynamic bit lengths tree"; + else if (r == Z_BUF_ERROR || *bb == 0) + { + z->msg = (char*)"incomplete dynamic bit lengths tree"; + r = Z_DATA_ERROR; + } + ZFREE(z, v); + return r; +} + + +int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, hp, z) +uInt nl; /* number of literal/length codes */ +uInt nd; /* number of distance codes */ +uIntf *c; /* that many (total) code lengths */ +uIntf *bl; /* literal desired/actual bit depth */ +uIntf *bd; /* distance desired/actual bit depth */ +inflate_huft * FAR *tl; /* literal/length tree result */ +inflate_huft * FAR *td; /* distance tree result */ +inflate_huft *hp; /* space for trees */ +z_streamp z; /* for messages */ +{ + int r; + uInt hn = 0; /* hufts used in space */ + uIntf *v; /* work area for huft_build */ + + /* allocate work area */ + if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) + return Z_MEM_ERROR; + + /* build literal/length tree */ + r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v); + if (r != Z_OK || *bl == 0) + { + if (r == Z_DATA_ERROR) + z->msg = (char*)"oversubscribed literal/length tree"; + else if (r != Z_MEM_ERROR) + { + z->msg = (char*)"incomplete literal/length tree"; + r = Z_DATA_ERROR; + } + ZFREE(z, v); + return r; + } + + /* build distance tree */ + r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v); + if (r != Z_OK || (*bd == 0 && nl > 257)) + { + if (r == Z_DATA_ERROR) + z->msg = (char*)"oversubscribed distance tree"; + else if (r == Z_BUF_ERROR) { +#ifdef PKZIP_BUG_WORKAROUND + r = Z_OK; + } +#else + z->msg = (char*)"incomplete distance tree"; + r = Z_DATA_ERROR; + } + else if (r != Z_MEM_ERROR) + { + z->msg = (char*)"empty distance tree with lengths"; + r = Z_DATA_ERROR; + } + ZFREE(z, v); + return r; +#endif + } + + /* done */ + ZFREE(z, v); + return Z_OK; +} + + +/* build fixed tables only once--keep them here */ +#ifdef BUILDFIXED +local int fixed_built = 0; +#define FIXEDH 544 /* number of hufts used by fixed tables */ +local inflate_huft fixed_mem[FIXEDH]; +local uInt fixed_bl; +local uInt fixed_bd; +local inflate_huft *fixed_tl; +local inflate_huft *fixed_td; +#else +#include "inffixed.h" +#endif + + +int inflate_trees_fixed(bl, bd, tl, td, z) +uIntf *bl; /* literal desired/actual bit depth */ +uIntf *bd; /* distance desired/actual bit depth */ +inflate_huft * FAR *tl; /* literal/length tree result */ +inflate_huft * FAR *td; /* distance tree result */ +z_streamp z; /* for memory allocation */ +{ +#ifdef BUILDFIXED + /* build fixed tables if not already */ + if (!fixed_built) + { + int k; /* temporary variable */ + uInt f = 0; /* number of hufts used in fixed_mem */ + uIntf *c; /* length list for huft_build */ + uIntf *v; /* work area for huft_build */ + + /* allocate memory */ + if ((c = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) + return Z_MEM_ERROR; + if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) + { + ZFREE(z, c); + return Z_MEM_ERROR; + } + + /* literal table */ + for (k = 0; k < 144; k++) + c[k] = 8; + for (; k < 256; k++) + c[k] = 9; + for (; k < 280; k++) + c[k] = 7; + for (; k < 288; k++) + c[k] = 8; + fixed_bl = 9; + huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, + fixed_mem, &f, v); + + /* distance table */ + for (k = 0; k < 30; k++) + c[k] = 5; + fixed_bd = 5; + huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, + fixed_mem, &f, v); + + /* done */ + ZFREE(z, v); + ZFREE(z, c); + fixed_built = 1; + } +#endif + *bl = fixed_bl; + *bd = fixed_bd; + *tl = fixed_tl; + *td = fixed_td; + return Z_OK; +} diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/inftrees.h b/contrib/vmap_extractor_v2/stormlib/zlib/inftrees.h new file mode 100644 index 00000000000..04b73b7296a --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/inftrees.h @@ -0,0 +1,58 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Huffman code lookup table entry--this entry is four bytes for machines + that have 16-bit pointers (e.g. PC's in the small or medium model). */ + +typedef struct inflate_huft_s FAR inflate_huft; + +struct inflate_huft_s { + union { + struct { + Byte Exop; /* number of extra bits or operation */ + Byte Bits; /* number of bits in this code or subcode */ + } what; + uInt pad; /* pad structure to a power of 2 (4 bytes for */ + } word; /* 16-bit, 8 bytes for 32-bit int's) */ + uInt base; /* literal, length base, distance base, + or table offset */ +}; + +/* Maximum size of dynamic tree. The maximum found in a long but non- + exhaustive search was 1004 huft structures (850 for length/literals + and 154 for distances, the latter actually the result of an + exhaustive search). The actual maximum is not known, but the + value below is more than safe. */ +#define MANY 1440 + +extern int inflate_trees_bits OF(( + uIntf *, /* 19 code lengths */ + uIntf *, /* bits tree desired/actual depth */ + inflate_huft * FAR *, /* bits tree result */ + inflate_huft *, /* space for trees */ + z_streamp)); /* for messages */ + +extern int inflate_trees_dynamic OF(( + uInt, /* number of literal/length codes */ + uInt, /* number of distance codes */ + uIntf *, /* that many (total) code lengths */ + uIntf *, /* literal desired/actual bit depth */ + uIntf *, /* distance desired/actual bit depth */ + inflate_huft * FAR *, /* literal/length tree result */ + inflate_huft * FAR *, /* distance tree result */ + inflate_huft *, /* space for trees */ + z_streamp)); /* for messages */ + +extern int inflate_trees_fixed OF(( + uIntf *, /* literal desired/actual bit depth */ + uIntf *, /* distance desired/actual bit depth */ + inflate_huft * FAR *, /* literal/length tree result */ + inflate_huft * FAR *, /* distance tree result */ + z_streamp)); /* for memory allocation */ diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/infutil.c b/contrib/vmap_extractor_v2/stormlib/zlib/infutil.c new file mode 100644 index 00000000000..9a076221f2a --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/infutil.c @@ -0,0 +1,87 @@ +/* inflate_util.c -- data and routines common to blocks and codes + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "infblock.h" +#include "inftrees.h" +#include "infcodes.h" +#include "infutil.h" + +struct inflate_codes_state {int dummy;}; /* for buggy compilers */ + +/* And'ing with mask[n] masks the lower n bits */ +uInt inflate_mask[17] = { + 0x0000, + 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, + 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff +}; + + +/* copy as much as possible from the sliding window to the output area */ +int inflate_flush(s, z, r) +inflate_blocks_statef *s; +z_streamp z; +int r; +{ + uInt n; + Bytef *p; + Bytef *q; + + /* local copies of source and destination pointers */ + p = z->next_out; + q = s->read; + + /* compute number of bytes to copy as far as end of window */ + n = (uInt)((q <= s->write ? s->write : s->end) - q); + if (n > z->avail_out) n = z->avail_out; + if (n && r == Z_BUF_ERROR) r = Z_OK; + + /* update counters */ + z->avail_out -= n; + z->total_out += n; + + /* update check information */ + if (s->checkfn != Z_NULL) + z->adler = s->check = (*s->checkfn)(s->check, q, n); + + /* copy as far as end of window */ + zmemcpy(p, q, n); + p += n; + q += n; + + /* see if more to copy at beginning of window */ + if (q == s->end) + { + /* wrap pointers */ + q = s->window; + if (s->write == s->end) + s->write = s->window; + + /* compute bytes to copy */ + n = (uInt)(s->write - q); + if (n > z->avail_out) n = z->avail_out; + if (n && r == Z_BUF_ERROR) r = Z_OK; + + /* update counters */ + z->avail_out -= n; + z->total_out += n; + + /* update check information */ + if (s->checkfn != Z_NULL) + z->adler = s->check = (*s->checkfn)(s->check, q, n); + + /* copy */ + zmemcpy(p, q, n); + p += n; + q += n; + } + + /* update pointers */ + z->next_out = p; + s->read = q; + + /* done */ + return r; +} diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/infutil.h b/contrib/vmap_extractor_v2/stormlib/zlib/infutil.h new file mode 100644 index 00000000000..4401df82fc8 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/infutil.h @@ -0,0 +1,98 @@ +/* infutil.h -- types and macros common to blocks and codes + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +#ifndef _INFUTIL_H +#define _INFUTIL_H + +typedef enum { + TYPE, /* get type bits (3, including end bit) */ + LENS, /* get lengths for stored */ + STORED, /* processing stored block */ + TABLE, /* get table lengths */ + BTREE, /* get bit lengths tree for a dynamic block */ + DTREE, /* get length, distance trees for a dynamic block */ + CODES, /* processing fixed or dynamic block */ + DRY, /* output remaining window bytes */ + DONE, /* finished last block, done */ + BAD} /* got a data error--stuck here */ +inflate_block_mode; + +/* inflate blocks semi-private state */ +struct inflate_blocks_state { + + /* mode */ + inflate_block_mode mode; /* current inflate_block mode */ + + /* mode dependent information */ + union { + uInt left; /* if STORED, bytes left to copy */ + struct { + uInt table; /* table lengths (14 bits) */ + uInt index; /* index into blens (or border) */ + uIntf *blens; /* bit lengths of codes */ + uInt bb; /* bit length tree depth */ + inflate_huft *tb; /* bit length decoding tree */ + } trees; /* if DTREE, decoding info for trees */ + struct { + inflate_codes_statef + *codes; + } decode; /* if CODES, current state */ + } sub; /* submode */ + uInt last; /* true if this block is the last block */ + + /* mode independent information */ + uInt bitk; /* bits in bit buffer */ + uLong bitb; /* bit buffer */ + inflate_huft *hufts; /* single malloc for tree space */ + Bytef *window; /* sliding window */ + Bytef *end; /* one byte after sliding window */ + Bytef *read; /* window read pointer */ + Bytef *write; /* window write pointer */ + check_func checkfn; /* check function */ + uLong check; /* check on output */ + +}; + + +/* defines for inflate input/output */ +/* update pointers and return */ +#define UPDBITS {s->bitb=b;s->bitk=k;} +#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;} +#define UPDOUT {s->write=q;} +#define UPDATE {UPDBITS UPDIN UPDOUT} +#define LEAVE {UPDATE return inflate_flush(s,z,r);} +/* get bytes and bits */ +#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;} +#define NEEDBYTE {if(n)r=Z_OK;else LEAVE} +#define NEXTBYTE (n--,*p++) +#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<>=(j);k-=(j);} +/* output bytes */ +#define WAVAIL (uInt)(qread?s->read-q-1:s->end-q) +#define LOADOUT {q=s->write;m=(uInt)WAVAIL;} +#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}} +#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT} +#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;} +#define OUTBYTE(a) {*q++=(Byte)(a);m--;} +/* load local pointers */ +#define LOAD {LOADIN LOADOUT} + +/* masks for lower bits (size given to avoid silly warnings with Visual C++) */ +extern uInt inflate_mask[17]; + +/* copy as much as possible from the sliding window to the output area */ +extern int inflate_flush OF(( + inflate_blocks_statef *, + z_streamp , + int)); + +struct internal_state {int dummy;}; /* for buggy compilers */ + +#endif diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/maketree.c b/contrib/vmap_extractor_v2/stormlib/zlib/maketree.c new file mode 100644 index 00000000000..a16d4b14608 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/maketree.c @@ -0,0 +1,85 @@ +/* maketree.c -- make inffixed.h table for decoding fixed codes + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* This program is included in the distribution for completeness. + You do not need to compile or run this program since inffixed.h + is already included in the distribution. To use this program + you need to compile zlib with BUILDFIXED defined and then compile + and link this program with the zlib library. Then the output of + this program can be piped to inffixed.h. */ + +#include +#include +#include "zutil.h" +#include "inftrees.h" + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + +/* generate initialization table for an inflate_huft structure array */ +void maketree(uInt b, inflate_huft *t) +{ + int i, e; + + i = 0; + while (1) + { + e = t[i].exop; + if (e && (e & (16+64)) == 0) /* table pointer */ + { + fprintf(stderr, "maketree: cannot initialize sub-tables!\n"); + exit(1); + } + if (i % 4 == 0) + printf("\n "); + printf(" {{{%u,%u}},%u}", t[i].exop, t[i].bits, t[i].base); + if (++i == (1< +#include "zlib.h" + +#ifdef STDC +# include +# include +#else + extern void exit OF((int)); +#endif + +#ifdef USE_MMAP +# include +# include +# include +#endif + +#if defined(MSDOS) || defined(OS2) || defined(WIN32) +# include +# include +# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) +#else +# define SET_BINARY_MODE(file) +#endif + +#ifdef VMS +# define unlink delete +# define GZ_SUFFIX "-gz" +#endif +#ifdef RISCOS +# define unlink remove +# define GZ_SUFFIX "-gz" +# define fileno(file) file->__file +#endif +#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fileno */ +#endif + +#ifndef WIN32 /* unlink already in stdio.h for WIN32 */ + extern int unlink OF((const char *)); +#endif + +#ifndef GZ_SUFFIX +# define GZ_SUFFIX ".gz" +#endif +#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1) + +#define BUFLEN 16384 +#define MAX_NAME_LEN 1024 + +#ifdef MAXSEG_64K +# define local static + /* Needed for systems with limitation on stack size. */ +#else +# define local +#endif + +char *prog; + +void error OF((const char *msg)); +void gz_compress OF((FILE *in, gzFile out)); +#ifdef USE_MMAP +int gz_compress_mmap OF((FILE *in, gzFile out)); +#endif +void gz_uncompress OF((gzFile in, FILE *out)); +void file_compress OF((char *file, char *mode)); +void file_uncompress OF((char *file)); +int main OF((int argc, char *argv[])); + +/* =========================================================================== + * Display error message and exit + */ +void error(msg) + const char *msg; +{ + fprintf(stderr, "%s: %s\n", prog, msg); + exit(1); +} + +/* =========================================================================== + * Compress input to output then close both files. + */ + +void gz_compress(in, out) + FILE *in; + gzFile out; +{ + local char buf[BUFLEN]; + int len; + int err; + +#ifdef USE_MMAP + /* Try first compressing with mmap. If mmap fails (minigzip used in a + * pipe), use the normal fread loop. + */ + if (gz_compress_mmap(in, out) == Z_OK) return; +#endif + for (;;) { + len = fread(buf, 1, sizeof(buf), in); + if (ferror(in)) { + perror("fread"); + exit(1); + } + if (len == 0) break; + + if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err)); + } + fclose(in); + if (gzclose(out) != Z_OK) error("failed gzclose"); +} + +#ifdef USE_MMAP /* MMAP version, Miguel Albrecht */ + +/* Try compressing the input file at once using mmap. Return Z_OK if + * if success, Z_ERRNO otherwise. + */ +int gz_compress_mmap(in, out) + FILE *in; + gzFile out; +{ + int len; + int err; + int ifd = fileno(in); + caddr_t buf; /* mmap'ed buffer for the entire input file */ + off_t buf_len; /* length of the input file */ + struct stat sb; + + /* Determine the size of the file, needed for mmap: */ + if (fstat(ifd, &sb) < 0) return Z_ERRNO; + buf_len = sb.st_size; + if (buf_len <= 0) return Z_ERRNO; + + /* Now do the actual mmap: */ + buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0); + if (buf == (caddr_t)(-1)) return Z_ERRNO; + + /* Compress the whole file at once: */ + len = gzwrite(out, (char *)buf, (unsigned)buf_len); + + if (len != (int)buf_len) error(gzerror(out, &err)); + + munmap(buf, buf_len); + fclose(in); + if (gzclose(out) != Z_OK) error("failed gzclose"); + return Z_OK; +} +#endif /* USE_MMAP */ + +/* =========================================================================== + * Uncompress input to output then close both files. + */ +void gz_uncompress(in, out) + gzFile in; + FILE *out; +{ + local char buf[BUFLEN]; + int len; + int err; + + for (;;) { + len = gzread(in, buf, sizeof(buf)); + if (len < 0) error (gzerror(in, &err)); + if (len == 0) break; + + if ((int)fwrite(buf, 1, (unsigned)len, out) != len) { + error("failed fwrite"); + } + } + if (fclose(out)) error("failed fclose"); + + if (gzclose(in) != Z_OK) error("failed gzclose"); +} + + +/* =========================================================================== + * Compress the given file: create a corresponding .gz file and remove the + * original. + */ +void file_compress(file, mode) + char *file; + char *mode; +{ + local char outfile[MAX_NAME_LEN]; + FILE *in; + gzFile out; + + strcpy(outfile, file); + strcat(outfile, GZ_SUFFIX); + + in = fopen(file, "rb"); + if (in == NULL) { + perror(file); + exit(1); + } + out = gzopen(outfile, mode); + if (out == NULL) { + fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile); + exit(1); + } + gz_compress(in, out); + + unlink(file); +} + + +/* =========================================================================== + * Uncompress the given file and remove the original. + */ +void file_uncompress(file) + char *file; +{ + local char buf[MAX_NAME_LEN]; + char *infile, *outfile; + FILE *out; + gzFile in; + int len = strlen(file); + + strcpy(buf, file); + + if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) { + infile = file; + outfile = buf; + outfile[len-3] = '\0'; + } else { + outfile = file; + infile = buf; + strcat(infile, GZ_SUFFIX); + } + in = gzopen(infile, "rb"); + if (in == NULL) { + fprintf(stderr, "%s: can't gzopen %s\n", prog, infile); + exit(1); + } + out = fopen(outfile, "wb"); + if (out == NULL) { + perror(file); + exit(1); + } + + gz_uncompress(in, out); + + unlink(infile); +} + + +/* =========================================================================== + * Usage: minigzip [-d] [-f] [-h] [-1 to -9] [files...] + * -d : decompress + * -f : compress with Z_FILTERED + * -h : compress with Z_HUFFMAN_ONLY + * -1 to -9 : compression level + */ + +int main(argc, argv) + int argc; + char *argv[]; +{ + int uncompr = 0; + gzFile file; + char outmode[20]; + + strcpy(outmode, "wb6 "); + + prog = argv[0]; + argc--, argv++; + + while (argc > 0) { + if (strcmp(*argv, "-d") == 0) + uncompr = 1; + else if (strcmp(*argv, "-f") == 0) + outmode[3] = 'f'; + else if (strcmp(*argv, "-h") == 0) + outmode[3] = 'h'; + else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' && + (*argv)[2] == 0) + outmode[2] = (*argv)[1]; + else + break; + argc--, argv++; + } + if (argc == 0) { + SET_BINARY_MODE(stdin); + SET_BINARY_MODE(stdout); + if (uncompr) { + file = gzdopen(fileno(stdin), "rb"); + if (file == NULL) error("can't gzdopen stdin"); + gz_uncompress(file, stdout); + } else { + file = gzdopen(fileno(stdout), outmode); + if (file == NULL) error("can't gzdopen stdout"); + gz_compress(stdin, file); + } + } else { + do { + if (uncompr) { + file_uncompress(*argv); + } else { + file_compress(*argv, outmode); + } + } while (argv++, --argc); + } + exit(0); + return 0; /* to avoid warning */ +} diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/msdos/Makefile.b32 b/contrib/vmap_extractor_v2/stormlib/zlib/msdos/Makefile.b32 new file mode 100644 index 00000000000..f476da91649 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/msdos/Makefile.b32 @@ -0,0 +1,104 @@ +# Makefile for zlib +# Borland C++ + +# This version of the zlib makefile was adapted by Chris Young for use +# with Borland C 4.5x with the Dos Power Pack for a 32-bit protected mode +# flat memory model. It was created for use with POV-Ray ray tracer and +# you may choose to edit the CFLAGS to suit your needs but the +# switches -WX and -DMSDOS are required. +# -- Chris Young 76702.1655@compuserve.com + +# To use, do "make -fmakefile.b32" + +# See zconf.h for details about the memory requirements. + +# ------------- Borland C++ ------------- +MODEL=-WX +CFLAGS= $(MODEL) -P-C -K -N- -k- -d -3 -r- -v- -f -DMSDOS +CC=bcc32 +LD=bcc32 +LIB=tlib +LDFLAGS= $(MODEL) +O=.obj + +# variables +OBJ1 = adler32$(O) compress$(O) crc32$(O) gzio$(O) uncompr$(O) deflate$(O) \ + trees$(O) +OBJP1 = adler32$(O)+compress$(O)+crc32$(O)+gzio$(O)+uncompr$(O)+deflate$(O)+\ + trees$(O) +OBJ2 = zutil$(O) inflate$(O) infblock$(O) inftrees$(O) infcodes$(O) \ + infutil$(O) inffast$(O) +OBJP2 = zutil$(O)+inflate$(O)+infblock$(O)+inftrees$(O)+infcodes$(O)+\ + infutil$(O)+inffast$(O) + +all: test + +adler32.obj: adler32.c zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +compress.obj: compress.c zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +crc32.obj: crc32.c zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +gzio.obj: gzio.c zutil.h zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +infblock.obj: infblock.c zutil.h zlib.h zconf.h infblock.h inftrees.h\ + infcodes.h infutil.h + $(CC) -c $(CFLAGS) $*.c + +infcodes.obj: infcodes.c zutil.h zlib.h zconf.h inftrees.h infutil.h\ + infcodes.h inffast.h + $(CC) -c $(CFLAGS) $*.c + +inflate.obj: inflate.c zutil.h zlib.h zconf.h infblock.h + $(CC) -c $(CFLAGS) $*.c + +inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h + $(CC) -c $(CFLAGS) $*.c + +infutil.obj: infutil.c zutil.h zlib.h zconf.h inftrees.h infutil.h + $(CC) -c $(CFLAGS) $*.c + +inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h infutil.h inffast.h + $(CC) -c $(CFLAGS) $*.c + +trees.obj: trees.c deflate.h zutil.h zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +uncompr.obj: uncompr.c zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +zutil.obj: zutil.c zutil.h zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +example.obj: example.c zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +minigzip.obj: minigzip.c zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +# we must cut the command line to fit in the MS/DOS 128 byte limit: +zlib.lib: $(OBJ1) $(OBJ2) + del zlib.lib + $(LIB) zlib +$(OBJP1) + $(LIB) zlib +$(OBJP2) + +example.exe: example.obj zlib.lib + $(LD) $(LDFLAGS) example.obj zlib.lib + +minigzip.exe: minigzip.obj zlib.lib + $(LD) $(LDFLAGS) minigzip.obj zlib.lib + +test: example.exe minigzip.exe + example + echo hello world | minigzip | minigzip -d + +#clean: +# del *.obj +# del *.exe diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/msdos/Makefile.bor b/contrib/vmap_extractor_v2/stormlib/zlib/msdos/Makefile.bor new file mode 100644 index 00000000000..f5651b40fec --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/msdos/Makefile.bor @@ -0,0 +1,125 @@ +# Makefile for zlib +# Borland C++ ************ UNTESTED *********** + +# To use, do "make -fmakefile.bor" +# To compile in small model, set below: MODEL=s + +# WARNING: the small model is supported but only for small values of +# MAX_WBITS and MAX_MEM_LEVEL. For example: +# -DMAX_WBITS=11 -DDEF_WBITS=11 -DMAX_MEM_LEVEL=3 +# If you wish to reduce the memory requirements (default 256K for big +# objects plus a few K), you can add to the LOC macro below: +# -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14 +# See zconf.h for details about the memory requirements. + +# ------------- Turbo C++, Borland C++ ------------- + +# Optional nonstandard preprocessor flags (e.g. -DMAX_MEM_LEVEL=7) +# should be added to the environment via "set LOCAL_ZLIB=-DFOO" or added +# to the declaration of LOC here: +LOC = $(LOCAL_ZLIB) + +# Type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc. +CPU_TYP = 0 + +# Memory model: one of s, m, c, l (small, medium, compact, large) +MODEL=l + +CC=bcc +# replace bcc with tcc for Turbo C++ 1.0, with bcc32 for the 32 bit version +LD=$(CC) +AR=tlib + +# compiler flags +CFLAGS=-O2 -Z -m$(MODEL) $(LOC) +# replace "-O2" by "-O -G -a -d" for Turbo C++ 1.0 + +LDFLAGS=-m$(MODEL) + +O=.obj + +# variables +OBJ1 = adler32$(O) compress$(O) crc32$(O) gzio$(O) uncompr$(O) deflate$(O) \ + trees$(O) +OBJP1 = adler32$(O)+compress$(O)+crc32$(O)+gzio$(O)+uncompr$(O)+deflate$(O)+\ + trees$(O) +OBJ2 = zutil$(O) inflate$(O) infblock$(O) inftrees$(O) infcodes$(O) \ + infutil$(O) inffast$(O) +OBJP2 = zutil$(O)+inflate$(O)+infblock$(O)+inftrees$(O)+infcodes$(O)+\ + infutil$(O)+inffast$(O) + +ZLIB_H = zlib.h zconf.h +ZUTIL_H = zutil.h $(ZLIB_H) + +ZLIB_LIB = zlib_$(MODEL).lib + +all: test + +# individual dependencies and action rules: +adler32.obj: adler32.c $(ZLIB_H) + $(CC) -c $(CFLAGS) $*.c + +compress.obj: compress.c $(ZLIB_H) + $(CC) -c $(CFLAGS) $*.c + +crc32.obj: crc32.c $(ZLIB_H) + $(CC) -c $(CFLAGS) $*.c + +deflate.obj: deflate.c deflate.h $(ZUTIL_H) + $(CC) -c $(CFLAGS) $*.c + +gzio.obj: gzio.c $(ZUTIL_H) + $(CC) -c $(CFLAGS) $*.c + +infblock.obj: infblock.c $(ZUTIL_H) infblock.h inftrees.h infcodes.h infutil.h + $(CC) -c $(CFLAGS) $*.c + +infcodes.obj: infcodes.c $(ZUTIL_H) inftrees.h infutil.h infcodes.h inffast.h + $(CC) -c $(CFLAGS) $*.c + +inflate.obj: inflate.c $(ZUTIL_H) infblock.h + $(CC) -c $(CFLAGS) $*.c + +inftrees.obj: inftrees.c $(ZUTIL_H) inftrees.h + $(CC) -c $(CFLAGS) $*.c + +infutil.obj: infutil.c $(ZUTIL_H) inftrees.h infutil.h + $(CC) -c $(CFLAGS) $*.c + +inffast.obj: inffast.c $(ZUTIL_H) inftrees.h infutil.h inffast.h + $(CC) -c $(CFLAGS) $*.c + +trees.obj: trees.c deflate.h $(ZUTIL_H) + $(CC) -c $(CFLAGS) $*.c + +uncompr.obj: uncompr.c $(ZLIB_H) + $(CC) -c $(CFLAGS) $*.c + +zutil.obj: zutil.c $(ZUTIL_H) + $(CC) -c $(CFLAGS) $*.c + +example.obj: example.c $(ZLIB_H) + $(CC) -c $(CFLAGS) $*.c + +minigzip.obj: minigzip.c $(ZLIB_H) + $(CC) -c $(CFLAGS) $*.c + +# we must cut the command line to fit in the MS/DOS 128 byte limit: +$(ZLIB_LIB): $(OBJ1) $(OBJ2) + del $(ZLIB_LIB) + $(AR) $(ZLIB_LIB) +$(OBJP1) + $(AR) $(ZLIB_LIB) +$(OBJP2) + +example.exe: example.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) example.obj $(ZLIB_LIB) + +minigzip.exe: minigzip.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB) + +test: example.exe minigzip.exe + example + echo hello world | minigzip | minigzip -d + +#clean: +# del *.obj +# del *.exe diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/msdos/Makefile.dj2 b/contrib/vmap_extractor_v2/stormlib/zlib/msdos/Makefile.dj2 new file mode 100644 index 00000000000..0ab431c8a11 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/msdos/Makefile.dj2 @@ -0,0 +1,100 @@ +# Makefile for zlib. Modified for djgpp v2.0 by F. J. Donahoe, 3/15/96. +# Copyright (C) 1995-1998 Jean-loup Gailly. +# For conditions of distribution and use, see copyright notice in zlib.h + +# To compile, or to compile and test, type: +# +# make -fmakefile.dj2; make test -fmakefile.dj2 +# +# To install libz.a, zconf.h and zlib.h in the djgpp directories, type: +# +# make install -fmakefile.dj2 +# +# after first defining LIBRARY_PATH and INCLUDE_PATH in djgpp.env as +# in the sample below if the pattern of the DJGPP distribution is to +# be followed. Remember that, while 'es around <=> are ignored in +# makefiles, they are *not* in batch files or in djgpp.env. +# - - - - - +# [make] +# INCLUDE_PATH=%\>;INCLUDE_PATH%%\DJDIR%\include +# LIBRARY_PATH=%\>;LIBRARY_PATH%%\DJDIR%\lib +# BUTT=-m486 +# - - - - - +# Alternately, these variables may be defined below, overriding the values +# in djgpp.env, as +# INCLUDE_PATH=c:\usr\include +# LIBRARY_PATH=c:\usr\lib + +CC=gcc + +#CFLAGS=-MMD -O +#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 +#CFLAGS=-MMD -g -DDEBUG +CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ + -Wstrict-prototypes -Wmissing-prototypes + +# If cp.exe is available, replace "copy /Y" with "cp -fp" . +CP=copy /Y +# If gnu install.exe is available, replace $(CP) with ginstall. +INSTALL=$(CP) +# The default value of RM is "rm -f." If "rm.exe" is found, comment out: +RM=del +LDLIBS=-L. -lz +LD=$(CC) -s -o +LDSHARED=$(CC) + +INCL=zlib.h zconf.h +LIBS=libz.a + +AR=ar rcs + +prefix=/usr/local +exec_prefix = $(prefix) + +OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ + zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o + +TEST_OBJS = example.o minigzip.o + +all: example.exe minigzip.exe + +test: all + ./example + echo hello world | .\minigzip | .\minigzip -d + +%.o : %.c + $(CC) $(CFLAGS) -c $< -o $@ + +libz.a: $(OBJS) + $(AR) $@ $(OBJS) + +%.exe : %.o $(LIBS) + $(LD) $@ $< $(LDLIBS) + +# INCLUDE_PATH and LIBRARY_PATH were set for [make] in djgpp.env . + +.PHONY : uninstall clean + +install: $(INCL) $(LIBS) + -@if not exist $(INCLUDE_PATH)\nul mkdir $(INCLUDE_PATH) + -@if not exist $(LIBRARY_PATH)\nul mkdir $(LIBRARY_PATH) + $(INSTALL) zlib.h $(INCLUDE_PATH) + $(INSTALL) zconf.h $(INCLUDE_PATH) + $(INSTALL) libz.a $(LIBRARY_PATH) + +uninstall: + $(RM) $(INCLUDE_PATH)\zlib.h + $(RM) $(INCLUDE_PATH)\zconf.h + $(RM) $(LIBRARY_PATH)\libz.a + +clean: + $(RM) *.d + $(RM) *.o + $(RM) *.exe + $(RM) libz.a + $(RM) foo.gz + +DEPS := $(wildcard *.d) +ifneq ($(DEPS),) +include $(DEPS) +endif diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/msdos/Makefile.emx b/contrib/vmap_extractor_v2/stormlib/zlib/msdos/Makefile.emx new file mode 100644 index 00000000000..0e5e5cc4338 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/msdos/Makefile.emx @@ -0,0 +1,69 @@ +# Makefile for zlib. Modified for emx 0.9c by Chr. Spieler, 6/17/98. +# Copyright (C) 1995-1998 Jean-loup Gailly. +# For conditions of distribution and use, see copyright notice in zlib.h + +# To compile, or to compile and test, type: +# +# make -fmakefile.emx; make test -fmakefile.emx +# + +CC=gcc + +#CFLAGS=-MMD -O +#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 +#CFLAGS=-MMD -g -DDEBUG +CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ + -Wstrict-prototypes -Wmissing-prototypes + +# If cp.exe is available, replace "copy /Y" with "cp -fp" . +CP=copy /Y +# If gnu install.exe is available, replace $(CP) with ginstall. +INSTALL=$(CP) +# The default value of RM is "rm -f." If "rm.exe" is found, comment out: +RM=del +LDLIBS=-L. -lzlib +LD=$(CC) -s -o +LDSHARED=$(CC) + +INCL=zlib.h zconf.h +LIBS=zlib.a + +AR=ar rcs + +prefix=/usr/local +exec_prefix = $(prefix) + +OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ + zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o + +TEST_OBJS = example.o minigzip.o + +all: example.exe minigzip.exe + +test: all + ./example + echo hello world | .\minigzip | .\minigzip -d + +%.o : %.c + $(CC) $(CFLAGS) -c $< -o $@ + +zlib.a: $(OBJS) + $(AR) $@ $(OBJS) + +%.exe : %.o $(LIBS) + $(LD) $@ $< $(LDLIBS) + + +.PHONY : clean + +clean: + $(RM) *.d + $(RM) *.o + $(RM) *.exe + $(RM) zlib.a + $(RM) foo.gz + +DEPS := $(wildcard *.d) +ifneq ($(DEPS),) +include $(DEPS) +endif diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/msdos/Makefile.msc b/contrib/vmap_extractor_v2/stormlib/zlib/msdos/Makefile.msc new file mode 100644 index 00000000000..562201d87ea --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/msdos/Makefile.msc @@ -0,0 +1,121 @@ +# Makefile for zlib +# Microsoft C 5.1 or later + +# To use, do "make makefile.msc" +# To compile in small model, set below: MODEL=S + +# If you wish to reduce the memory requirements (default 256K for big +# objects plus a few K), you can add to the LOC macro below: +# -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14 +# See zconf.h for details about the memory requirements. + +# ------------- Microsoft C 5.1 and later ------------- + +# Optional nonstandard preprocessor flags (e.g. -DMAX_MEM_LEVEL=7) +# should be added to the environment via "set LOCAL_ZLIB=-DFOO" or added +# to the declaration of LOC here: +LOC = $(LOCAL_ZLIB) + +# Type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc. +CPU_TYP = 0 + +# Memory model: one of S, M, C, L (small, medium, compact, large) +MODEL=L + +CC=cl +CFLAGS=-nologo -A$(MODEL) -G$(CPU_TYP) -W3 -Oait -Gs $(LOC) +#-Ox generates bad code with MSC 5.1 +LIB_CFLAGS=-Zl $(CFLAGS) + +LD=link +LDFLAGS=/noi/e/st:0x1500/noe/farcall/packcode +# "/farcall/packcode" are only useful for `large code' memory models +# but should be a "no-op" for small code models. + +O=.obj + +# variables +OBJ1 = adler32$(O) compress$(O) crc32$(O) gzio$(O) uncompr$(O) deflate$(O) \ + trees$(O) +OBJP1 = adler32$(O)+compress$(O)+crc32$(O)+gzio$(O)+uncompr$(O)+deflate$(O)+\ + trees$(O) +OBJ2 = zutil$(O) inflate$(O) infblock$(O) inftrees$(O) infcodes$(O) \ + infutil$(O) inffast$(O) +OBJP2 = zutil$(O)+inflate$(O)+infblock$(O)+inftrees$(O)+infcodes$(O)+\ + infutil$(O)+inffast$(O) + +ZLIB_H = zlib.h zconf.h +ZUTIL_H = zutil.h $(ZLIB_H) + +ZLIB_LIB = zlib_$(MODEL).lib + +all: $(ZLIB_LIB) example.exe minigzip.exe + +# individual dependencies and action rules: +adler32.obj: adler32.c $(ZLIB_H) + $(CC) -c $(LIB_CFLAGS) $*.c + +compress.obj: compress.c $(ZLIB_H) + $(CC) -c $(LIB_CFLAGS) $*.c + +crc32.obj: crc32.c $(ZLIB_H) + $(CC) -c $(LIB_CFLAGS) $*.c + +deflate.obj: deflate.c deflate.h $(ZUTIL_H) + $(CC) -c $(LIB_CFLAGS) $*.c + +gzio.obj: gzio.c $(ZUTIL_H) + $(CC) -c $(LIB_CFLAGS) $*.c + +infblock.obj: infblock.c $(ZUTIL_H) infblock.h inftrees.h infcodes.h infutil.h + $(CC) -c $(LIB_CFLAGS) $*.c + +infcodes.obj: infcodes.c $(ZUTIL_H) inftrees.h infutil.h infcodes.h inffast.h + $(CC) -c $(LIB_CFLAGS) $*.c + +inflate.obj: inflate.c $(ZUTIL_H) infblock.h + $(CC) -c $(LIB_CFLAGS) $*.c + +inftrees.obj: inftrees.c $(ZUTIL_H) inftrees.h + $(CC) -c $(LIB_CFLAGS) $*.c + +infutil.obj: infutil.c $(ZUTIL_H) inftrees.h infutil.h + $(CC) -c $(LIB_CFLAGS) $*.c + +inffast.obj: inffast.c $(ZUTIL_H) inftrees.h infutil.h inffast.h + $(CC) -c $(LIB_CFLAGS) $*.c + +trees.obj: trees.c deflate.h $(ZUTIL_H) + $(CC) -c $(LIB_CFLAGS) $*.c + +uncompr.obj: uncompr.c $(ZLIB_H) + $(CC) -c $(LIB_CFLAGS) $*.c + +zutil.obj: zutil.c $(ZUTIL_H) + $(CC) -c $(LIB_CFLAGS) $*.c + +example.obj: example.c $(ZLIB_H) + $(CC) -c $(CFLAGS) $*.c + +minigzip.obj: minigzip.c $(ZLIB_H) + $(CC) -c $(CFLAGS) $*.c + +# we must cut the command line to fit in the MS/DOS 128 byte limit: +$(ZLIB_LIB): $(OBJ1) $(OBJ2) + if exist $(ZLIB_LIB) del $(ZLIB_LIB) + lib $(ZLIB_LIB) $(OBJ1); + lib $(ZLIB_LIB) $(OBJ2); + +example.exe: example.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) example.obj,,,$(ZLIB_LIB); + +minigzip.exe: minigzip.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) minigzip.obj,,,$(ZLIB_LIB); + +test: example.exe minigzip.exe + example + echo hello world | minigzip | minigzip -d + +#clean: +# del *.obj +# del *.exe diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/msdos/Makefile.tc b/contrib/vmap_extractor_v2/stormlib/zlib/msdos/Makefile.tc new file mode 100644 index 00000000000..63e0550359f --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/msdos/Makefile.tc @@ -0,0 +1,108 @@ +# Makefile for zlib +# TurboC 2.0 + +# To use, do "make -fmakefile.tc" +# To compile in small model, set below: MODEL=-ms + +# WARNING: the small model is supported but only for small values of +# MAX_WBITS and MAX_MEM_LEVEL. For example: +# -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3 +# If you wish to reduce the memory requirements (default 256K for big +# objects plus a few K), you can add to CFLAGS below: +# -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14 +# See zconf.h for details about the memory requirements. + +# ------------- Turbo C 2.0 ------------- +MODEL=l +# CFLAGS=-O2 -G -Z -m$(MODEL) -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3 +CFLAGS=-O2 -G -Z -m$(MODEL) +CC=tcc -I\tc\include +LD=tcc -L\tc\lib +AR=tlib +LDFLAGS=-m$(MODEL) -f- +O=.obj + +# variables +OBJ1 = adler32$(O) compress$(O) crc32$(O) gzio$(O) uncompr$(O) deflate$(O) \ + trees$(O) +OBJP1 = adler32$(O)+compress$(O)+crc32$(O)+gzio$(O)+uncompr$(O)+deflate$(O)+\ + trees$(O) +OBJ2 = zutil$(O) inflate$(O) infblock$(O) inftrees$(O) infcodes$(O) \ + infutil$(O) inffast$(O) +OBJP2 = zutil$(O)+inflate$(O)+infblock$(O)+inftrees$(O)+infcodes$(O)+\ + infutil$(O)+inffast$(O) + +ZLIB_H = zlib.h zconf.h +ZUTIL_H = zutil.h $(ZLIB_H) + +ZLIB_LIB = zlib_$(MODEL).lib + +all: test + +adler32.obj: adler32.c $(ZLIB_H) + $(CC) -c $(CFLAGS) $*.c + +compress.obj: compress.c $(ZLIB_H) + $(CC) -c $(CFLAGS) $*.c + +crc32.obj: crc32.c $(ZLIB_H) + $(CC) -c $(CFLAGS) $*.c + +deflate.obj: deflate.c deflate.h $(ZUTIL_H) + $(CC) -c $(CFLAGS) $*.c + +gzio.obj: gzio.c $(ZUTIL_H) + $(CC) -c $(CFLAGS) $*.c + +infblock.obj: infblock.c $(ZUTIL_H) infblock.h inftrees.h infcodes.h infutil.h + $(CC) -c $(CFLAGS) $*.c + +infcodes.obj: infcodes.c $(ZUTIL_H) inftrees.h infutil.h infcodes.h inffast.h + $(CC) -c $(CFLAGS) $*.c + +inflate.obj: inflate.c $(ZUTIL_H) infblock.h + $(CC) -c $(CFLAGS) $*.c + +inftrees.obj: inftrees.c $(ZUTIL_H) inftrees.h + $(CC) -c $(CFLAGS) $*.c + +infutil.obj: infutil.c $(ZUTIL_H) inftrees.h infutil.h + $(CC) -c $(CFLAGS) $*.c + +inffast.obj: inffast.c $(ZUTIL_H) inftrees.h infutil.h inffast.h + $(CC) -c $(CFLAGS) $*.c + +trees.obj: trees.c deflate.h $(ZUTIL_H) + $(CC) -c $(CFLAGS) $*.c + +uncompr.obj: uncompr.c $(ZLIB_H) + $(CC) -c $(CFLAGS) $*.c + +zutil.obj: zutil.c $(ZUTIL_H) + $(CC) -c $(CFLAGS) $*.c + +example.obj: example.c $(ZLIB_H) + $(CC) -c $(CFLAGS) $*.c + +minigzip.obj: minigzip.c $(ZLIB_H) + $(CC) -c $(CFLAGS) $*.c + +# we must cut the command line to fit in the MS/DOS 128 byte limit: +$(ZLIB_LIB): $(OBJ1) $(OBJ2) + del $(ZLIB_LIB) + $(AR) $(ZLIB_LIB) +$(OBJP1) + $(AR) $(ZLIB_LIB) +$(OBJP2) + +example.exe: example.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) -eexample.exe example.obj $(ZLIB_LIB) + +minigzip.exe: minigzip.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) -eminigzip.exe minigzip.obj $(ZLIB_LIB) + +test: example.exe minigzip.exe + example + echo hello world | minigzip | minigzip -d + +#clean: +# del *.obj +# del *.exe diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/msdos/Makefile.w32 b/contrib/vmap_extractor_v2/stormlib/zlib/msdos/Makefile.w32 new file mode 100644 index 00000000000..0a05fa9a469 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/msdos/Makefile.w32 @@ -0,0 +1,97 @@ +# Makefile for zlib +# Microsoft 32-bit Visual C++ 4.0 or later (may work on earlier versions) + +# To use, do "nmake /f makefile.w32" + +# If you wish to reduce the memory requirements (default 256K for big +# objects plus a few K), you can add to CFLAGS below: +# -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14 +# See zconf.h for details about the memory requirements. + +# ------------- Microsoft Visual C++ 4.0 and later ------------- +MODEL= +CFLAGS=-Ox -GA3s -nologo -W3 +CC=cl +LD=link +LDFLAGS= +O=.obj + +# variables +OBJ1 = adler32$(O) compress$(O) crc32$(O) gzio$(O) uncompr$(O) deflate$(O) \ + trees$(O) +OBJP1 = adler32$(O)+compress$(O)+crc32$(O)+gzio$(O)+uncompr$(O)+deflate$(O)+\ + trees$(O) +OBJ2 = zutil$(O) inflate$(O) infblock$(O) inftrees$(O) infcodes$(O) \ + infutil$(O) inffast$(O) +OBJP2 = zutil$(O)+inflate$(O)+infblock$(O)+inftrees$(O)+infcodes$(O)+\ + infutil$(O)+inffast$(O) + +all: zlib.lib example.exe minigzip.exe + +adler32.obj: adler32.c zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +compress.obj: compress.c zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +crc32.obj: crc32.c zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +gzio.obj: gzio.c zutil.h zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +infblock.obj: infblock.c zutil.h zlib.h zconf.h infblock.h inftrees.h\ + infcodes.h infutil.h + $(CC) -c $(CFLAGS) $*.c + +infcodes.obj: infcodes.c zutil.h zlib.h zconf.h inftrees.h infutil.h\ + infcodes.h inffast.h + $(CC) -c $(CFLAGS) $*.c + +inflate.obj: inflate.c zutil.h zlib.h zconf.h infblock.h + $(CC) -c $(CFLAGS) $*.c + +inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h + $(CC) -c $(CFLAGS) $*.c + +infutil.obj: infutil.c zutil.h zlib.h zconf.h inftrees.h infutil.h + $(CC) -c $(CFLAGS) $*.c + +inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h infutil.h inffast.h + $(CC) -c $(CFLAGS) $*.c + +trees.obj: trees.c deflate.h zutil.h zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +uncompr.obj: uncompr.c zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +zutil.obj: zutil.c zutil.h zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +example.obj: example.c zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +minigzip.obj: minigzip.c zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +zlib.lib: $(OBJ1) $(OBJ2) + if exist zlib.lib del zlib.lib + lib /OUT:zlib.lib $(OBJ1) $(OBJ2) + +example.exe: example.obj zlib.lib + $(LD) $(LDFLAGS) example.obj zlib.lib /OUT:example.exe /SUBSYSTEM:CONSOLE + +minigzip.exe: minigzip.obj zlib.lib + $(LD) $(LDFLAGS) minigzip.obj zlib.lib /OUT:minigzip.exe /SUBSYSTEM:CONSOLE + +test: example.exe minigzip.exe + example + echo hello world | minigzip | minigzip -d + +#clean: +# del *.obj +# del *.exe diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/msdos/Makefile.wat b/contrib/vmap_extractor_v2/stormlib/zlib/msdos/Makefile.wat new file mode 100644 index 00000000000..44bf8607f6f --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/msdos/Makefile.wat @@ -0,0 +1,103 @@ +# Makefile for zlib +# Watcom 10a + +# This version of the zlib makefile was adapted by Chris Young for use +# with Watcom 10a 32-bit protected mode flat memory model. It was created +# for use with POV-Ray ray tracer and you may choose to edit the CFLAGS to +# suit your needs but the -DMSDOS is required. +# -- Chris Young 76702.1655@compuserve.com + +# To use, do "wmake -f makefile.wat" + +# See zconf.h for details about the memory requirements. + +# ------------- Watcom 10a ------------- +MODEL=-mf +CFLAGS= $(MODEL) -fpi87 -fp5 -zp4 -5r -w5 -oneatx -DMSDOS +CC=wcc386 +LD=wcl386 +LIB=wlib -b -c +LDFLAGS= +O=.obj + +# variables +OBJ1=adler32$(O) compress$(O) crc32$(O) gzio$(O) uncompr$(O) deflate$(O) +OBJ2=trees$(O) zutil$(O) inflate$(O) infblock$(O) inftrees$(O) infcodes$(O) +OBJ3=infutil$(O) inffast$(O) +OBJP1=adler32$(O)+compress$(O)+crc32$(O)+gzio$(O)+uncompr$(O)+deflate$(O) +OBJP2=trees$(O)+zutil$(O)+inflate$(O)+infblock$(O)+inftrees$(O)+infcodes$(O) +OBJP3=infutil$(O)+inffast$(O) + +all: test + +adler32.obj: adler32.c zlib.h zconf.h + $(CC) $(CFLAGS) $*.c + +compress.obj: compress.c zlib.h zconf.h + $(CC) $(CFLAGS) $*.c + +crc32.obj: crc32.c zlib.h zconf.h + $(CC) $(CFLAGS) $*.c + +deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h + $(CC) $(CFLAGS) $*.c + +gzio.obj: gzio.c zutil.h zlib.h zconf.h + $(CC) $(CFLAGS) $*.c + +infblock.obj: infblock.c zutil.h zlib.h zconf.h infblock.h inftrees.h & + infcodes.h infutil.h + $(CC) $(CFLAGS) $*.c + +infcodes.obj: infcodes.c zutil.h zlib.h zconf.h inftrees.h infutil.h & + infcodes.h inffast.h + $(CC) $(CFLAGS) $*.c + +inflate.obj: inflate.c zutil.h zlib.h zconf.h infblock.h + $(CC) $(CFLAGS) $*.c + +inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h + $(CC) $(CFLAGS) $*.c + +infutil.obj: infutil.c zutil.h zlib.h zconf.h inftrees.h infutil.h + $(CC) $(CFLAGS) $*.c + +inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h infutil.h inffast.h + $(CC) $(CFLAGS) $*.c + +trees.obj: trees.c deflate.h zutil.h zlib.h zconf.h + $(CC) $(CFLAGS) $*.c + +uncompr.obj: uncompr.c zlib.h zconf.h + $(CC) $(CFLAGS) $*.c + +zutil.obj: zutil.c zutil.h zlib.h zconf.h + $(CC) $(CFLAGS) $*.c + +example.obj: example.c zlib.h zconf.h + $(CC) $(CFLAGS) $*.c + +minigzip.obj: minigzip.c zlib.h zconf.h + $(CC) $(CFLAGS) $*.c + +# we must cut the command line to fit in the MS/DOS 128 byte limit: +zlib.lib: $(OBJ1) $(OBJ2) $(OBJ3) + del zlib.lib + $(LIB) zlib.lib +$(OBJP1) + $(LIB) zlib.lib +$(OBJP2) + $(LIB) zlib.lib +$(OBJP3) + +example.exe: example.obj zlib.lib + $(LD) $(LDFLAGS) example.obj zlib.lib + +minigzip.exe: minigzip.obj zlib.lib + $(LD) $(LDFLAGS) minigzip.obj zlib.lib + +test: minigzip.exe example.exe + example + echo hello world | minigzip | minigzip -d >test + type test + +#clean: +# del *.obj +# del *.exe diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/msdos/zlib.def b/contrib/vmap_extractor_v2/stormlib/zlib/msdos/zlib.def new file mode 100644 index 00000000000..6c04412f9b0 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/msdos/zlib.def @@ -0,0 +1,60 @@ +LIBRARY "zlib" + +DESCRIPTION '"""zlib data compression library"""' + +EXETYPE NT + +SUBSYSTEM WINDOWS + +STUB 'WINSTUB.EXE' + +VERSION 1.13 + +CODE EXECUTE READ + +DATA READ WRITE + +HEAPSIZE 1048576,4096 + +EXPORTS + adler32 @1 + compress @2 + crc32 @3 + deflate @4 + deflateCopy @5 + deflateEnd @6 + deflateInit2_ @7 + deflateInit_ @8 + deflateParams @9 + deflateReset @10 + deflateSetDictionary @11 + gzclose @12 + gzdopen @13 + gzerror @14 + gzflush @15 + gzopen @16 + gzread @17 + gzwrite @18 + inflate @19 + inflateEnd @20 + inflateInit2_ @21 + inflateInit_ @22 + inflateReset @23 + inflateSetDictionary @24 + inflateSync @25 + uncompress @26 + zlibVersion @27 + gzprintf @28 + gzputc @29 + gzgetc @30 + gzseek @31 + gzrewind @32 + gztell @33 + gzeof @34 + gzsetparams @35 + zError @36 + inflateSyncPoint @37 + get_crc_table @38 + compress2 @39 + gzputs @40 + gzgets @41 diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/msdos/zlib.rc b/contrib/vmap_extractor_v2/stormlib/zlib/msdos/zlib.rc new file mode 100644 index 00000000000..556d4ff950a --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/msdos/zlib.rc @@ -0,0 +1,32 @@ +#include + +#define IDR_VERSION1 1 +IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE + FILEVERSION 1,1,3,0 + PRODUCTVERSION 1,1,3,0 + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGS 0 + FILEOS VOS_DOS_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0 // not used +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + //language ID = U.S. English, char set = Windows, Multilingual + + BEGIN + VALUE "FileDescription", "zlib data compression library\0" + VALUE "FileVersion", "1.1.3\0" + VALUE "InternalName", "zlib\0" + VALUE "OriginalFilename", "zlib.dll\0" + VALUE "ProductName", "ZLib.DLL\0" + VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" + VALUE "LegalCopyright", "(C) 1995-1998 Jean-loup Gailly & Mark Adler\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 1252 + END +END diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/nt/Makefile.emx b/contrib/vmap_extractor_v2/stormlib/zlib/nt/Makefile.emx new file mode 100644 index 00000000000..2d475b1847e --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/nt/Makefile.emx @@ -0,0 +1,138 @@ +# Makefile for zlib. Modified for emx/rsxnt by Chr. Spieler, 6/16/98. +# Copyright (C) 1995-1998 Jean-loup Gailly. +# For conditions of distribution and use, see copyright notice in zlib.h + +# To compile, or to compile and test, type: +# +# make -fmakefile.emx; make test -fmakefile.emx +# + +CC=gcc -Zwin32 + +#CFLAGS=-MMD -O +#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 +#CFLAGS=-MMD -g -DDEBUG +CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ + -Wstrict-prototypes -Wmissing-prototypes + +# If cp.exe is available, replace "copy /Y" with "cp -fp" . +CP=copy /Y +# If gnu install.exe is available, replace $(CP) with ginstall. +INSTALL=$(CP) +# The default value of RM is "rm -f." If "rm.exe" is found, comment out: +RM=del +LDLIBS=-L. -lzlib +LD=$(CC) -s -o +LDSHARED=$(CC) + +INCL=zlib.h zconf.h +LIBS=zlib.a + +AR=ar rcs + +prefix=/usr/local +exec_prefix = $(prefix) + +OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ + zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o + +TEST_OBJS = example.o minigzip.o + +all: example.exe minigzip.exe + +test: all + ./example + echo hello world | .\minigzip | .\minigzip -d + +%.o : %.c + $(CC) $(CFLAGS) -c $< -o $@ + +zlib.a: $(OBJS) + $(AR) $@ $(OBJS) + +%.exe : %.o $(LIBS) + $(LD) $@ $< $(LDLIBS) + + +.PHONY : clean + +clean: + $(RM) *.d + $(RM) *.o + $(RM) *.exe + $(RM) zlib.a + $(RM) foo.gz + +DEPS := $(wildcard *.d) +ifneq ($(DEPS),) +include $(DEPS) +endif +# Makefile for zlib. Modified for emx 0.9c by Chr. Spieler, 6/17/98. +# Copyright (C) 1995-1998 Jean-loup Gailly. +# For conditions of distribution and use, see copyright notice in zlib.h + +# To compile, or to compile and test, type: +# +# make -fmakefile.emx; make test -fmakefile.emx +# + +CC=gcc + +#CFLAGS=-MMD -O +#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 +#CFLAGS=-MMD -g -DDEBUG +CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ + -Wstrict-prototypes -Wmissing-prototypes + +# If cp.exe is available, replace "copy /Y" with "cp -fp" . +CP=copy /Y +# If gnu install.exe is available, replace $(CP) with ginstall. +INSTALL=$(CP) +# The default value of RM is "rm -f." If "rm.exe" is found, comment out: +RM=del +LDLIBS=-L. -lzlib +LD=$(CC) -s -o +LDSHARED=$(CC) + +INCL=zlib.h zconf.h +LIBS=zlib.a + +AR=ar rcs + +prefix=/usr/local +exec_prefix = $(prefix) + +OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ + zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o + +TEST_OBJS = example.o minigzip.o + +all: example.exe minigzip.exe + +test: all + ./example + echo hello world | .\minigzip | .\minigzip -d + +%.o : %.c + $(CC) $(CFLAGS) -c $< -o $@ + +zlib.a: $(OBJS) + $(AR) $@ $(OBJS) + +%.exe : %.o $(LIBS) + $(LD) $@ $< $(LDLIBS) + + +.PHONY : clean + +clean: + $(RM) *.d + $(RM) *.o + $(RM) *.exe + $(RM) zlib.a + $(RM) foo.gz + +DEPS := $(wildcard *.d) +ifneq ($(DEPS),) +include $(DEPS) +endif diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/nt/Makefile.gcc b/contrib/vmap_extractor_v2/stormlib/zlib/nt/Makefile.gcc new file mode 100644 index 00000000000..cdd652f2360 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/nt/Makefile.gcc @@ -0,0 +1,87 @@ +# Makefile for zlib. Modified for mingw32 by C. Spieler, 6/16/98. +# (This Makefile is directly derived from Makefile.dj2) +# Copyright (C) 1995-1998 Jean-loup Gailly. +# For conditions of distribution and use, see copyright notice in zlib.h + +# To compile, or to compile and test, type: +# +# make -fmakefile.gcc; make test -fmakefile.gcc +# +# To install libz.a, zconf.h and zlib.h in the mingw32 directories, type: +# +# make install -fmakefile.gcc +# + +CC=gcc + +#CFLAGS=-MMD -O +#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 +#CFLAGS=-MMD -g -DDEBUG +CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ + -Wstrict-prototypes -Wmissing-prototypes + +# If cp.exe is available, replace "copy /Y" with "cp -fp" . +CP=copy /Y +# If gnu install.exe is available, replace $(CP) with ginstall. +INSTALL=$(CP) +# The default value of RM is "rm -f." If "rm.exe" is found, comment out: +RM=del +LDLIBS=-L. -lz +LD=$(CC) -s -o +LDSHARED=$(CC) + +INCL=zlib.h zconf.h +LIBS=libz.a + +AR=ar rcs + +prefix=/usr/local +exec_prefix = $(prefix) + +OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ + zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o + +TEST_OBJS = example.o minigzip.o + +all: example.exe minigzip.exe + +test: all + ./example + echo hello world | .\minigzip | .\minigzip -d + +%.o : %.c + $(CC) $(CFLAGS) -c $< -o $@ + +libz.a: $(OBJS) + $(AR) $@ $(OBJS) + +%.exe : %.o $(LIBS) + $(LD) $@ $< $(LDLIBS) + +# INCLUDE_PATH and LIBRARY_PATH were set for [make] in djgpp.env . + +.PHONY : uninstall clean + +install: $(INCL) $(LIBS) + -@if not exist $(INCLUDE_PATH)\nul mkdir $(INCLUDE_PATH) + -@if not exist $(LIBRARY_PATH)\nul mkdir $(LIBRARY_PATH) + $(INSTALL) zlib.h $(INCLUDE_PATH) + $(INSTALL) zconf.h $(INCLUDE_PATH) + $(INSTALL) libz.a $(LIBRARY_PATH) + +uninstall: + $(RM) $(INCLUDE_PATH)\zlib.h + $(RM) $(INCLUDE_PATH)\zconf.h + $(RM) $(LIBRARY_PATH)\libz.a + +clean: + $(RM) *.d + $(RM) *.o + $(RM) *.exe + $(RM) libz.a + $(RM) foo.gz + +DEPS := $(wildcard *.d) +ifneq ($(DEPS),) +include $(DEPS) +endif diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/nt/Makefile.nt b/contrib/vmap_extractor_v2/stormlib/zlib/nt/Makefile.nt new file mode 100644 index 00000000000..b250f2ac7d2 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/nt/Makefile.nt @@ -0,0 +1,88 @@ +# Makefile for zlib + +!include + +CC=cl +LD=link +CFLAGS=-O -nologo +LDFLAGS= +O=.obj + +# variables +OBJ1 = adler32$(O) compress$(O) crc32$(O) gzio$(O) uncompr$(O) deflate$(O) \ + trees$(O) +OBJ2 = zutil$(O) inflate$(O) infblock$(O) inftrees$(O) infcodes$(O) \ + infutil$(O) inffast$(O) + +all: zlib.dll example.exe minigzip.exe + +adler32.obj: adler32.c zutil.h zlib.h zconf.h + $(CC) -c $(cvarsdll) $(CFLAGS) $*.c + +compress.obj: compress.c zlib.h zconf.h + $(CC) -c $(cvarsdll) $(CFLAGS) $*.c + +crc32.obj: crc32.c zutil.h zlib.h zconf.h + $(CC) -c $(cvarsdll) $(CFLAGS) $*.c + +deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h + $(CC) -c $(cvarsdll) $(CFLAGS) $*.c + +gzio.obj: gzio.c zutil.h zlib.h zconf.h + $(CC) -c $(cvarsdll) $(CFLAGS) $*.c + +infblock.obj: infblock.c zutil.h zlib.h zconf.h infblock.h inftrees.h\ + infcodes.h infutil.h + $(CC) -c $(cvarsdll) $(CFLAGS) $*.c + +infcodes.obj: infcodes.c zutil.h zlib.h zconf.h inftrees.h infutil.h\ + infcodes.h inffast.h + $(CC) -c $(cvarsdll) $(CFLAGS) $*.c + +inflate.obj: inflate.c zutil.h zlib.h zconf.h infblock.h + $(CC) -c $(cvarsdll) $(CFLAGS) $*.c + +inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h + $(CC) -c $(cvarsdll) $(CFLAGS) $*.c + +infutil.obj: infutil.c zutil.h zlib.h zconf.h inftrees.h infutil.h + $(CC) -c $(cvarsdll) $(CFLAGS) $*.c + +inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h infutil.h inffast.h + $(CC) -c $(cvarsdll) $(CFLAGS) $*.c + +trees.obj: trees.c deflate.h zutil.h zlib.h zconf.h + $(CC) -c $(cvarsdll) $(CFLAGS) $*.c + +uncompr.obj: uncompr.c zlib.h zconf.h + $(CC) -c $(cvarsdll) $(CFLAGS) $*.c + +zutil.obj: zutil.c zutil.h zlib.h zconf.h + $(CC) -c $(cvarsdll) $(CFLAGS) $*.c + +example.obj: example.c zlib.h zconf.h + $(CC) -c $(cvarsdll) $(CFLAGS) $*.c + +minigzip.obj: minigzip.c zlib.h zconf.h + $(CC) -c $(cvarsdll) $(CFLAGS) $*.c + +zlib.dll: $(OBJ1) $(OBJ2) zlib.dnt + link $(dlllflags) -out:$@ -def:zlib.dnt $(OBJ1) $(OBJ2) $(guilibsdll) + +zlib.lib: zlib.dll + +example.exe: example.obj zlib.lib + $(LD) $(LDFLAGS) example.obj zlib.lib + +minigzip.exe: minigzip.obj zlib.lib + $(LD) $(LDFLAGS) minigzip.obj zlib.lib + +test: example.exe minigzip.exe + example + echo hello world | minigzip | minigzip -d + +clean: + del *.obj + del *.exe + del *.dll + del *.lib diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/nt/zlib.dnt b/contrib/vmap_extractor_v2/stormlib/zlib/nt/zlib.dnt new file mode 100644 index 00000000000..7f9475cfb0e --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/nt/zlib.dnt @@ -0,0 +1,47 @@ +LIBRARY zlib.dll +EXETYPE WINDOWS +CODE PRELOAD MOVEABLE DISCARDABLE +DATA PRELOAD MOVEABLE MULTIPLE + +EXPORTS + adler32 @1 + compress @2 + crc32 @3 + deflate @4 + deflateCopy @5 + deflateEnd @6 + deflateInit2_ @7 + deflateInit_ @8 + deflateParams @9 + deflateReset @10 + deflateSetDictionary @11 + gzclose @12 + gzdopen @13 + gzerror @14 + gzflush @15 + gzopen @16 + gzread @17 + gzwrite @18 + inflate @19 + inflateEnd @20 + inflateInit2_ @21 + inflateInit_ @22 + inflateReset @23 + inflateSetDictionary @24 + inflateSync @25 + uncompress @26 + zlibVersion @27 + gzprintf @28 + gzputc @29 + gzgetc @30 + gzseek @31 + gzrewind @32 + gztell @33 + gzeof @34 + gzsetparams @35 + zError @36 + inflateSyncPoint @37 + get_crc_table @38 + compress2 @39 + gzputs @40 + gzgets @41 diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/os2/Makefile.os2 b/contrib/vmap_extractor_v2/stormlib/zlib/os2/Makefile.os2 new file mode 100644 index 00000000000..4f569471eca --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/os2/Makefile.os2 @@ -0,0 +1,136 @@ +# Makefile for zlib under OS/2 using GCC (PGCC) +# For conditions of distribution and use, see copyright notice in zlib.h + +# To compile and test, type: +# cp Makefile.os2 .. +# cd .. +# make -f Makefile.os2 test + +# This makefile will build a static library z.lib, a shared library +# z.dll and a import library zdll.lib. You can use either z.lib or +# zdll.lib by specifying either -lz or -lzdll on gcc's command line + +CC=gcc -Zomf -s + +CFLAGS=-O6 -Wall +#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 +#CFLAGS=-g -DDEBUG +#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ +# -Wstrict-prototypes -Wmissing-prototypes + +#################### BUG WARNING: ##################### +## infcodes.c hits a bug in pgcc-1.0, so you have to use either +## -O# where # <= 4 or one of (-fno-ommit-frame-pointer or -fno-force-mem) +## This bug is reportedly fixed in pgcc >1.0, but this was not tested +CFLAGS+=-fno-force-mem + +LDFLAGS=-s -L. -lzdll -Zcrtdll +LDSHARED=$(CC) -s -Zomf -Zdll -Zcrtdll + +VER=1.1.0 +ZLIB=z.lib +SHAREDLIB=z.dll +SHAREDLIBIMP=zdll.lib +LIBS=$(ZLIB) $(SHAREDLIB) $(SHAREDLIBIMP) + +AR=emxomfar cr +IMPLIB=emximp +RANLIB=echo +TAR=tar +SHELL=bash + +prefix=/usr/local +exec_prefix = $(prefix) + +OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ + zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o + +TEST_OBJS = example.o minigzip.o + +DISTFILES = README INDEX ChangeLog configure Make*[a-z0-9] *.[ch] descrip.mms \ + algorithm.txt zlib.3 msdos/Make*[a-z0-9] msdos/zlib.def msdos/zlib.rc \ + nt/Makefile.nt nt/zlib.dnt contrib/README.contrib contrib/*.txt \ + contrib/asm386/*.asm contrib/asm386/*.c \ + contrib/asm386/*.bat contrib/asm386/zlibvc.d?? contrib/iostream/*.cpp \ + contrib/iostream/*.h contrib/iostream2/*.h contrib/iostream2/*.cpp \ + contrib/untgz/Makefile contrib/untgz/*.c contrib/untgz/*.w32 + +all: example.exe minigzip.exe + +test: all + @LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \ + echo hello world | ./minigzip | ./minigzip -d || \ + echo ' *** minigzip test FAILED ***' ; \ + if ./example; then \ + echo ' *** zlib test OK ***'; \ + else \ + echo ' *** zlib test FAILED ***'; \ + fi + +$(ZLIB): $(OBJS) + $(AR) $@ $(OBJS) + -@ ($(RANLIB) $@ || true) >/dev/null 2>&1 + +$(SHAREDLIB): $(OBJS) os2/z.def + $(LDSHARED) -o $@ $^ + +$(SHAREDLIBIMP): os2/z.def + $(IMPLIB) -o $@ $^ + +example.exe: example.o $(LIBS) + $(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS) + +minigzip.exe: minigzip.o $(LIBS) + $(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS) + +clean: + rm -f *.o *~ example minigzip libz.a libz.so* foo.gz + +distclean: clean + +zip: + mv Makefile Makefile~; cp -p Makefile.in Makefile + rm -f test.c ztest*.c + v=`sed -n -e 's/\.//g' -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\ + zip -ul9 zlib$$v $(DISTFILES) + mv Makefile~ Makefile + +dist: + mv Makefile Makefile~; cp -p Makefile.in Makefile + rm -f test.c ztest*.c + d=zlib-`sed -n '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\ + rm -f $$d.tar.gz; \ + if test ! -d ../$$d; then rm -f ../$$d; ln -s `pwd` ../$$d; fi; \ + files=""; \ + for f in $(DISTFILES); do files="$$files $$d/$$f"; done; \ + cd ..; \ + GZIP=-9 $(TAR) chofz $$d/$$d.tar.gz $$files; \ + if test ! -d $$d; then rm -f $$d; fi + mv Makefile~ Makefile + +tags: + etags *.[ch] + +depend: + makedepend -- $(CFLAGS) -- *.[ch] + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +adler32.o: zlib.h zconf.h +compress.o: zlib.h zconf.h +crc32.o: zlib.h zconf.h +deflate.o: deflate.h zutil.h zlib.h zconf.h +example.o: zlib.h zconf.h +gzio.o: zutil.h zlib.h zconf.h +infblock.o: infblock.h inftrees.h infcodes.h infutil.h zutil.h zlib.h zconf.h +infcodes.o: zutil.h zlib.h zconf.h +infcodes.o: inftrees.h infblock.h infcodes.h infutil.h inffast.h +inffast.o: zutil.h zlib.h zconf.h inftrees.h +inffast.o: infblock.h infcodes.h infutil.h inffast.h +inflate.o: zutil.h zlib.h zconf.h infblock.h +inftrees.o: zutil.h zlib.h zconf.h inftrees.h +infutil.o: zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h +minigzip.o: zlib.h zconf.h +trees.o: deflate.h zutil.h zlib.h zconf.h trees.h +uncompr.o: zlib.h zconf.h +zutil.o: zutil.h zlib.h zconf.h diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/os2/zlib.def b/contrib/vmap_extractor_v2/stormlib/zlib/os2/zlib.def new file mode 100644 index 00000000000..4c753f1a3b9 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/os2/zlib.def @@ -0,0 +1,51 @@ +; +; Slightly modified version of ../nt/zlib.dnt :-) +; + +LIBRARY Z +DESCRIPTION "Zlib compression library for OS/2" +CODE PRELOAD MOVEABLE DISCARDABLE +DATA PRELOAD MOVEABLE MULTIPLE + +EXPORTS + adler32 + compress + crc32 + deflate + deflateCopy + deflateEnd + deflateInit2_ + deflateInit_ + deflateParams + deflateReset + deflateSetDictionary + gzclose + gzdopen + gzerror + gzflush + gzopen + gzread + gzwrite + inflate + inflateEnd + inflateInit2_ + inflateInit_ + inflateReset + inflateSetDictionary + inflateSync + uncompress + zlibVersion + gzprintf + gzputc + gzgetc + gzseek + gzrewind + gztell + gzeof + gzsetparams + zError + inflateSyncPoint + get_crc_table + compress2 + gzputs + gzgets diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/trees.c b/contrib/vmap_extractor_v2/stormlib/zlib/trees.c new file mode 100644 index 00000000000..0a984056738 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/trees.c @@ -0,0 +1,1214 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2002 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id$ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef DEBUG +# include +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local void set_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (value << s->bi_valid); + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (val << s->bi_valid);\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG */ + + +#define MAX(a,b) (a >= b ? a : b) +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG +# include +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if (tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch) (MAX(s->depth[n], s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void _tr_stored_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ +#ifdef DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + * The current inflate code requires 9 bits of lookahead. If the + * last two codes for the previous block (real code plus EOB) were coded + * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + * the last real code. In this case we send two empty static blocks instead + * of one. (There are no problems if the previous block is stored or fixed.) + * To simplify the code, we assume the worst case of last real code encoded + * on one bit only. + */ +void _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); + /* Of the 10 bits for the empty block, we have already sent + * (10 - bi_valid) bits. The lookahead for the last real code (before + * the EOB of the previous block) was thus at least one plus the length + * of the EOB plus what we have just sent of the empty static block. + */ + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; +#endif + bi_flush(s); + } + s->last_eob_len = 7; +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +void _tr_flush_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is ascii or binary */ + if (s->data_type == Z_UNKNOWN) set_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute first the block length in bytes*/ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, eof); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+eof, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+eof, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (eof) { + bi_windup(s); +#ifdef DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*eof)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(s, ltree, dtree) + deflate_state *s; + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert(s->pending < s->lit_bufsize + 2*lx, "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +/* =========================================================================== + * Set the data type to ASCII or BINARY, using a crude approximation: + * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. + * IN assertion: the fields freq of dyn_ltree are set and the total of all + * frequencies does not exceed 64K (to fit in an int on 16 bit machines). + */ +local void set_data_type(s) + deflate_state *s; +{ + int n = 0; + unsigned ascii_freq = 0; + unsigned bin_freq = 0; + while (n < 7) bin_freq += s->dyn_ltree[n++].Freq; + while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq; + while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq; + s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII); +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +local void copy_block(s, buf, len, header) + deflate_state *s; + charf *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/trees.h b/contrib/vmap_extractor_v2/stormlib/zlib/trees.h new file mode 100644 index 00000000000..72facf900f7 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/uncompr.c b/contrib/vmap_extractor_v2/stormlib/zlib/uncompr.c new file mode 100644 index 00000000000..a287714f5de --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/uncompr.c @@ -0,0 +1,58 @@ +/* uncompr.c -- decompress a memory buffer + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zlib.h" + +/* =========================================================================== + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ +int ZEXPORT uncompress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + err = inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = inflateEnd(&stream); + return err; +} diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/zconf.h b/contrib/vmap_extractor_v2/stormlib/zlib/zconf.h new file mode 100644 index 00000000000..eb0ae2e1a0c --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/zconf.h @@ -0,0 +1,279 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef _ZCONF_H +#define _ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateReset z_inflateReset +# define compress z_compress +# define compress2 z_compress2 +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table + +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) +# define WIN32 +#endif +#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386) +# ifndef __32BIT__ +# define __32BIT__ +# endif +#endif +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#if defined(MSDOS) && !defined(__32BIT__) +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC) +# define STDC +#endif +#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__) +# ifndef STDC +# define STDC +# endif +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Old Borland C incorrectly complains about missing returns: */ +#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500) +# define NEED_DUMMY_RETURN +#endif + + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +#endif +#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__)) +# ifndef __32BIT__ +# define SMALL_MEDIUM +# define FAR _far +# endif +#endif + +/* Compile with -DZLIB_DLL for Windows DLL support */ +#if defined(ZLIB_DLL) +# if defined(_WINDOWS) || defined(WINDOWS) +# ifdef FAR +# undef FAR +# endif +# include +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR _cdecl _export +# endif +# endif +# if defined (__BORLANDC__) +# if (__BORLANDC__ >= 0x0500) && defined (WIN32) +# include +# define ZEXPORT __declspec(dllexport) WINAPI +# define ZEXPORTRVA __declspec(dllexport) WINAPIV +# else +# if defined (_Windows) && defined (__DLL__) +# define ZEXPORT _export +# define ZEXPORTVA _export +# endif +# endif +# endif +#endif + +#if defined (__BEOS__) +# if defined (ZLIB_DLL) +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +#endif + +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif +#ifndef ZEXTERN +# define ZEXTERN extern +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(MACOS) && !defined(TARGET_OS_MAC) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#ifdef HAVE_UNISTD_H +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(inflate_blocks,"INBL") +# pragma map(inflate_blocks_new,"INBLNE") +# pragma map(inflate_blocks_free,"INBLFR") +# pragma map(inflate_blocks_reset,"INBLRE") +# pragma map(inflate_codes_free,"INCOFR") +# pragma map(inflate_codes,"INCO") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_flush,"INFLU") +# pragma map(inflate_mask,"INMA") +# pragma map(inflate_set_dictionary,"INSEDI2") +# pragma map(inflate_copyright,"INCOPY") +# pragma map(inflate_trees_bits,"INTRBI") +# pragma map(inflate_trees_dynamic,"INTRDY") +# pragma map(inflate_trees_fixed,"INTRFI") +# pragma map(inflate_trees_free,"INTRFR") +#endif + +#endif /* _ZCONF_H */ diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/zlib.3 b/contrib/vmap_extractor_v2/stormlib/zlib/zlib.3 new file mode 100644 index 00000000000..3a6e45047fe --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/zlib.3 @@ -0,0 +1,107 @@ +.TH ZLIB 3 "11 March 2002" +.SH NAME +zlib \- compression/decompression library +.SH SYNOPSIS +[see +.I zlib.h +for full description] +.SH DESCRIPTION +The +.I zlib +library is a general purpose data compression library. +The code is thread safe. +It provides in-memory compression and decompression functions, +including integrity checks of the uncompressed data. +This version of the library supports only one compression method (deflation) +but other algorithms will be added later and will have the same stream interface. +.LP +Compression can be done in a single step if the buffers are large enough +(for example if an input file is mmap'ed), +or can be done by repeated calls of the compression function. +In the latter case, +the application must provide more input and/or consume the output +(providing more output space) before each call. +.LP +The library also supports reading and writing files in +.I gzip +(.gz) format +with an interface similar to that of stdio. +.LP +The library does not install any signal handler. The decoder checks +the consistency of the compressed data, so the library should never +crash even in case of corrupted input. +.LP +All functions of the compression library are documented in the file +.IR zlib.h. +The distribution source includes examples of use of the library +the files +.I example.c +and +.IR minigzip.c . +.LP +A Java implementation of +.IR zlib +is available in the Java Development Kit 1.1 +.IP +http://www.javasoft.com/products/JDK/1.1/docs/api/Package-java.util.zip.html +.LP +A Perl interface to +.IR zlib , +written by Paul Marquess (pmarquess@bfsec.bt.co.uk) +is available at CPAN (Comprehensive Perl Archive Network) sites, +such as: +.IP +ftp://ftp.cis.ufl.edu/pub/perl/CPAN/modules/by-module/Compress/Compress-Zlib* +.LP +A Python interface to +.IR zlib +written by A.M. Kuchling +is available from the Python Software Association sites, such as: +.IP +ftp://ftp.python.org/pub/python/contrib/Encoding/zlib*.tar.gz +.SH "SEE ALSO" +Questions about zlib should be sent to: +.IP +zlib@quest.jpl.nasa.gov +or, if this fails, to the author addresses given below. +The zlib home page is: +.IP +http://www.cdrom.com/pub/infozip/zlib/ +.LP +The data format used by the zlib library is described by RFC +(Request for Comments) 1950 to 1952 in the files: +.IP +ftp://ds.internic.net/rfc/rfc1950.txt (zlib format) +.br +rfc1951.txt (deflate format) +.br +rfc1952.txt (gzip format) +.LP +These documents are also available in other formats from: +.IP +ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html +.SH AUTHORS +Version 1.1.4 +Copyright (C) 1995-2002 Jean-loup Gailly (jloup@gzip.org) +and Mark Adler (madler@alumni.caltech.edu). +.LP +This software is provided "as-is," +without any express or implied warranty. +In no event will the authors be held liable for any damages +arising from the use of this software. +See the distribution directory with respect to requirements +governing redistribution. +The deflate format used by +.I zlib +was defined by Phil Katz. +The deflate and +.I zlib +specifications were written by L. Peter Deutsch. +Thanks to all the people who reported problems and suggested various +improvements in +.IR zlib ; +who are too numerous to cite here. +.LP +UNIX manual page by R. P. C. Rodgers, +U.S. National Library of Medicine (rodgers@nlm.nih.gov). +.\" end of man page diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/zlib.h b/contrib/vmap_extractor_v2/stormlib/zlib/zlib.h new file mode 100644 index 00000000000..52cb529f6f3 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/zlib.h @@ -0,0 +1,893 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.1.4, March 11th, 2002 + + Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef _ZLIB_H +#define _ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.1.4" + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: ascii or binary */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +/* Allowed flush values; see deflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_ASCII 1 +#define Z_UNKNOWN 2 +/* Possible values of the data_type field */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + the compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + 0.1% larger than avail_in plus 12 bytes. If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update data_type if it can make a good guess about + the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may some + introduce some output latency (reading input without producing any output) + except when forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much + output as possible to the output buffer. The flushing behavior of inflate is + not specified for values of the flush parameter other than Z_SYNC_FLUSH + and Z_FINISH, but the current implementation actually flushes as much output + as possible anyway. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster routine + may be used for the single inflate() call. + + If a preset dictionary is needed at this point (see inflateSetDictionary + below), inflate sets strm-adler to the adler32 checksum of the + dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise + it sets strm->adler to the adler32 checksum of all output produced + so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or + an error code as described below. At the end of the stream, inflate() + checks that its computed adler32 checksum is equal to that saved by the + compressor and returns Z_STREAM_END only if the checksum is correct. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect + adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent + (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if no progress is possible or if there was not + enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR + case, the application may then call inflateSync to look for a good + compression block. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match). Filtered data consists mostly of small values with a + somewhat random distribution. In this case, the compression algorithm is + tuned to compress them better. The effect of Z_FILTERED is to force more + Huffman coding and less string matching; it is somewhat intermediate + between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects + the compression ratio but not the correctness of the compressed output even + if it is not set appropriately. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. + + Upon return of this function, strm->adler is set to the Adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. If a compressed stream with a larger window size is given as + input, inflate() will return with the error code Z_DATA_ERROR instead of + trying to allocate a larger window. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative + memLevel). msg is set to null if there is no error message. inflateInit2 + does not perform any decompression apart from reading the zlib header if + present: this will be done by inflate(). (So next_in and avail_in may be + modified, but next_out and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate + if this call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler32 value returned by this call of + inflate. The compressor and decompressor must use exactly the same + dictionary (see deflateSetDictionary). + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least 0.1% larger than + sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h". (See the description + of deflateInit2 for more information about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + const voidp buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); + +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running crc with the bytes buf[0..len-1] and return the updated + crc. If buf is NULL, this function returns the required initial value + for the crc. Pre- and post-conditioning (one's complement) is performed + within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int err)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* _ZLIB_H */ diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/zlib.html b/contrib/vmap_extractor_v2/stormlib/zlib/zlib.html new file mode 100644 index 00000000000..c3437038693 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/zlib.html @@ -0,0 +1,971 @@ + + + + zlib general purpose compression library version 1.1.4 + + + + + +

zlib 1.1.4 Manual

+
+

Contents

+
    +
  1. Prologue +
  2. Introduction +
  3. Utility functions +
  4. Basic functions +
  5. Advanced functions +
  6. Constants +
  7. struct z_stream_s +
  8. Checksum functions +
  9. Misc +
+
+

Prologue

+ 'zlib' general purpose compression library version 1.1.4, March 11th, 2002 +

+ Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler +

+ This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. +

+ Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: +

    +
  1. The origin of this software must not be misrepresented ; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +
  2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +
  3. This notice may not be removed or altered from any source distribution. +
+ +
+
Jean-loup Gailly +
jloup@gzip.org +
Mark Adler +
madler@alumni.caltech.edu +
+ + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files + + ftp://ds.internic.net/rfc/rfc1950.txt + (zlib format), + + rfc1951.txt + (deflate format) and + + rfc1952.txt + (gzip format). +

+ This manual is converted from zlib.h by + piaip +

+ Visit + http://ftp.cdrom.com/pub/infozip/zlib/ + for the official zlib web page. +

+ +


+

Introduction

+ The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. +

+ + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. +

+ + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio. +

+ + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +

+ +


+

Utility functions

+ The following utility functions are implemented on top of the +
basic stream-oriented functions. + To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +

Function list

+
    +
  • int compress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen); +
  • int compress2 (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level); +
  • int uncompress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen); +
  • typedef voidp gzFile; +
  • gzFile gzopen (const char *path, const char *mode); +
  • gzFile gzdopen (int fd, const char *mode); +
  • int gzsetparams (gzFile file, int level, int strategy); +
  • int gzread (gzFile file, voidp buf, unsigned len); +
  • int gzwrite (gzFile file, const voidp buf, unsigned len); +
  • int VA gzprintf (gzFile file, const char *format, ...); +
  • int gzputs (gzFile file, const char *s); +
  • char * gzgets (gzFile file, char *buf, int len); +
  • int gzputc (gzFile file, int c); +
  • int gzgetc (gzFile file); +
  • int gzflush (gzFile file, int flush); +
  • z_off_t gzseek (gzFile file, z_off_t offset, int whence); +
  • z_off_t gztell (gzFile file); +
  • int gzrewind (gzFile file); +
  • int gzeof (gzFile file); +
  • int gzclose (gzFile file); +
  • const char * gzerror (gzFile file, int *errnum); +
+

Function description

+
+
int compress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen); +
+ Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least 0.1% larger than + sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the + compressed buffer.

+ This function can be used to compress a whole file at once if the + input file is mmap'ed.

+ compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer.

+ +

int compress2 (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level); +
+ Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. +

+ + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +

+ +

int uncompress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen); +
+ Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer.

+ This function can be used to decompress a whole file at once if the + input file is mmap'ed. +

+ + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +

+ +

typedef voidp gzFile; +

+ +

gzFile gzopen (const char *path, const char *mode); +
+ Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h". (See the description + of deflateInit2 for more information about the strategy parameter.) +

+ + gzopen can be used to read a file which is not in gzip format ; in this + case gzread will directly read from the file without decompression. +

+ + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state ; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). +

+ +

gzFile gzdopen (int fd, const char *mode); +
+ gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. +

+ The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). +

+ gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +

+ +

int gzsetparams (gzFile file, int level, int strategy); +
+ Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. +

+ gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +

+ +

int gzread (gzFile file, voidp buf, unsigned len); +
+ Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. +

+ gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). +

+ +

int gzwrite (gzFile file, const voidp buf, unsigned len); +
+ Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +

+ +

int VA gzprintf (gzFile file, const char *format, ...); +
+ Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). +

+ +

int gzputs (gzFile file, const char *s); +
+ Writes the given null-terminated string to the compressed file, excluding + the terminating null character. +

+ gzputs returns the number of characters written, or -1 in case of error. +

+ +

char * gzgets (gzFile file, char *buf, int len); +
+ Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. +

+ gzgets returns buf, or Z_NULL in case of error. +

+ +

int gzputc (gzFile file, int c); +
+ Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +

+ +

int gzgetc (gzFile file); +
+ Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +

+ +

int gzflush (gzFile file, int flush); +
+ Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. +

+ gzflush should be called only when strictly necessary because it can + degrade compression. +

+ +

z_off_t gzseek (gzFile file, z_off_t offset, int whence); +
+ Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. +

+ If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported ; gzseek then compresses a sequence of zeroes up to the new + starting position. +

+ gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +

+ +

int gzrewind (gzFile file); +
+ Rewinds the given file. This function is supported only for reading. +

+ gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +

+ +

z_off_t gztell (gzFile file); +
+ Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. +

+ + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +

+ +

int gzeof (gzFile file); +
+ Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +

+ +

int gzclose (gzFile file); +
+ Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +

+ +

const char * gzerror (gzFile file, int *errnum); +
+ Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +

+

+
+

Basic functions

+

Function list

+
+ +

Function description

+
+
const char * zlibVersion (void); +
The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. +

+ +

int deflateInit (z_streamp strm, int level); +
+ Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. +

+ + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). +

+ + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). +

+ + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +

+ +

int deflate (z_streamp strm, int flush); +
+ deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush.

+ + The detailed semantics are as follows. deflate performs one or both of the + following actions: + +

    +
  • Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + +
  • + Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. +

+ + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly ; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. +

+ + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. +

+ + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + the compression. +

+ + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). +

+ + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space ; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. +

+ + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + 0.1% larger than avail_in plus 12 bytes. If deflate does not return + Z_STREAM_END, then it must be called again as described above. +

+ + deflate() sets strm-> adler to the adler32 checksum of all input read + so far (that is, total_in bytes). +

+ + deflate() may update data_type if it can make a good guess about + the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. +

+ + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). +

+ +

int deflateEnd (z_streamp strm); +
+ All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. +

+ + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +

+ +

int inflateInit (z_streamp strm); +
+ Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly ; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. +

+ + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +

+ +

int inflate (z_streamp strm, int flush); +
+ inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may some + introduce some output latency (reading input without producing any output) + except when forced to flush. +

+ + The detailed semantics are as follows. inflate performs one or both of the + following actions: + +

    +
  • Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + +
  • Provide more output starting at next_out and update next_out and + avail_out accordingly. inflate() provides as much output as possible, + until there is no more input data or no more space in the output buffer + (see below about the flush parameter). +

+ + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. +

+ + If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much + output as possible to the output buffer. The flushing behavior of inflate is + not specified for values of the flush parameter other than Z_SYNC_FLUSH + and Z_FINISH, but the current implementation actually flushes as much output + as possible anyway. +

+ + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed ; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster routine + may be used for the single inflate() call. +

+ + If a preset dictionary is needed at this point (see inflateSetDictionary + below), inflate sets strm-adler to the adler32 checksum of the + dictionary chosen by the compressor and returns Z_NEED_DICT ; otherwise + it sets strm-> adler to the adler32 checksum of all output produced + so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or + an error code as described below. At the end of the stream, inflate() + checks that its computed adler32 checksum is equal to that saved by the + compressor and returns Z_STREAM_END only if the checksum is correct. +

+ + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect + adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent + (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if no progress is possible or if there was not + enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR + case, the application may then call inflateSync to look for a good + compression block. +

+ +

int inflateEnd (z_streamp strm); +
+ All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. +

+ + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +

+
+

Advanced functions

+ The following functions are needed only in some special applications. +

Function list

+
+

Function description

+
+
int deflateInit2 (z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy); + +
This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller.

+ + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library.

+ + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead.

+ + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio ; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel.

+ + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match). Filtered data consists mostly of small values with a + somewhat random distribution. In this case, the compression algorithm is + tuned to compress them better. The effect of Z_FILTERED is to force more + Huffman coding and less string matching ; it is somewhat intermediate + between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects + the compression ratio but not the correctness of the compressed output even + if it is not set appropriately.

+ + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate().

+ +

int deflateSetDictionary (z_streamp strm, const Bytef *dictionary, uInt dictLength); +
+ Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary).

+ + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy ; the data can then be compressed better than + with the default empty dictionary.

+ + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front.

+ + Upon return of this function, strm-> adler is set to the Adler32 value + of the dictionary ; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.)

+ + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate().

+ +

int deflateCopy (z_streamp dest, z_streamp source); +
+ Sets the destination stream as a complete copy of the source stream.

+ + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory.

+ + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination.

+ +

int deflateReset (z_streamp strm); +
This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2.

+ + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL).

+ +

int deflateParams (z_streamp strm, int level, int strategy); +
+ Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate().

+ + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm-> avail_out must be + non-zero.

+ + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero.

+ +

int inflateInit2 (z_streamp strm, int windowBits); + +
This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller.

+ + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. If a compressed stream with a larger window size is given as + input, inflate() will return with the error code Z_DATA_ERROR instead of + trying to allocate a larger window.

+ + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative + memLevel). msg is set to null if there is no error message. inflateInit2 + does not perform any decompression apart from reading the zlib header if + present: this will be done by inflate(). (So next_in and avail_in may be + modified, but next_out and avail_out are unchanged.)

+ +

int inflateSetDictionary (z_streamp strm, const Bytef *dictionary, uInt dictLength); +
+ Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate + if this call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler32 value returned by this call of + inflate. The compressor and decompressor must use exactly the same + dictionary (see deflateSetDictionary).

+ + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate().

+ +

int inflateSync (z_streamp strm); + +
Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided.

+ + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data.

+ +

int inflateReset (z_streamp strm); +
+ This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. +

+ + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +

+

+ +
+

Checksum functions

+ These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +

Function list

+
+

Function description

+
+
uLong adler32 (uLong adler, const Bytef *buf, uInt len); +
+ Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. +

+ An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: +

+
+     uLong adler = adler32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       adler = adler32(adler, buffer, length);
+     }
+     if (adler != original_adler) error();
+   
+ +
uLong crc32 (uLong crc, const Bytef *buf, uInt len); +
+ Update a running crc with the bytes buf[0..len-1] and return the updated + crc. If buf is NULL, this function returns the required initial value + for the crc. Pre- and post-conditioning (one's complement) is performed + within this function so it shouldn't be done by the application. + Usage example: +
+
+     uLong crc = crc32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       crc = crc32(crc, buffer, length);
+     }
+     if (crc != original_crc) error();
+   
+
+
+

struct z_stream_s

+ +
+
+typedef struct z_stream_s {
+    Bytef    *next_in;  /* next input byte */
+    uInt     avail_in;  /* number of bytes available at next_in */
+    uLong    total_in;  /* total nb of input bytes read so far */
+
+    Bytef    *next_out; /* next output byte should be put there */
+    uInt     avail_out; /* remaining free space at next_out */
+    uLong    total_out; /* total nb of bytes output so far */
+
+    char     *msg;      /* last error message, NULL if no error */
+    struct internal_state FAR *state; /* not visible by applications */
+
+    alloc_func zalloc;  /* used to allocate the internal state */
+    free_func  zfree;   /* used to free the internal state */
+    voidpf     opaque;  /* private data object passed to zalloc and zfree */
+
+    int     data_type;  /* best guess about the data type: ascii or binary */
+    uLong   adler;      /* adler32 value of the uncompressed data */
+    uLong   reserved;   /* reserved for future use */
+} z_stream ;
+
+typedef z_stream FAR * z_streamp;  ÿ 
+
+
+ The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application.

+ + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value.

+ + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe.

+ + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). +

+ + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step).

+ +


+

Constants

+ +
+#define Z_NO_FLUSH      0
+#define Z_PARTIAL_FLUSH 1 
+	/* will be removed, use Z_SYNC_FLUSH instead */
+#define Z_SYNC_FLUSH    2
+#define Z_FULL_FLUSH    3
+#define Z_FINISH        4
+/* Allowed flush values ; see deflate() below for details */
+
+#define Z_OK            0
+#define Z_STREAM_END    1
+#define Z_NEED_DICT     2
+#define Z_ERRNO        (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR   (-3)
+#define Z_MEM_ERROR    (-4)
+#define Z_BUF_ERROR    (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION         0
+#define Z_BEST_SPEED             1
+#define Z_BEST_COMPRESSION       9
+#define Z_DEFAULT_COMPRESSION  (-1)
+/* compression levels */
+
+#define Z_FILTERED            1
+#define Z_HUFFMAN_ONLY        2
+#define Z_DEFAULT_STRATEGY    0
+/* compression strategy ; see deflateInit2() below for details */
+
+#define Z_BINARY   0
+#define Z_ASCII    1
+#define Z_UNKNOWN  2
+/* Possible values of the data_type field */
+
+#define Z_DEFLATED   8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions less than 1.0.2 */
+
+
+ +
+

Misc

+
deflateInit and inflateInit are macros to allow checking the zlib version + and the compiler's view of z_stream. +

+ Other functions: +

+
const char * zError (int err); +
int inflateSyncPoint (z_streamp z); +
const uLongf * get_crc_table (void); +
+
+ + Last update: Wed Oct 13 20:42:34 1999
+ piapi@csie.ntu.edu.tw +
+ + + diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/zmemory.c b/contrib/vmap_extractor_v2/stormlib/zlib/zmemory.c new file mode 100644 index 00000000000..fc9749c5711 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/zmemory.c @@ -0,0 +1,19 @@ +/* zmemory.c + Internal memory alloc and memory free functions + */ + +#include + +#include "zlib.h" + +const char *z_errmsg[10]; // Needed by zlib + +voidpf zcalloc(voidpf opaque, uInt items, uInt size) +{ + return (voidpf)calloc(items, size); +} + +void zcfree(voidpf opaque, voidpf address) +{ + free(address); +} diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/zutil.c b/contrib/vmap_extractor_v2/stormlib/zlib/zutil.c new file mode 100644 index 00000000000..9a076221f2a --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/zutil.c @@ -0,0 +1,87 @@ +/* inflate_util.c -- data and routines common to blocks and codes + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "infblock.h" +#include "inftrees.h" +#include "infcodes.h" +#include "infutil.h" + +struct inflate_codes_state {int dummy;}; /* for buggy compilers */ + +/* And'ing with mask[n] masks the lower n bits */ +uInt inflate_mask[17] = { + 0x0000, + 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, + 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff +}; + + +/* copy as much as possible from the sliding window to the output area */ +int inflate_flush(s, z, r) +inflate_blocks_statef *s; +z_streamp z; +int r; +{ + uInt n; + Bytef *p; + Bytef *q; + + /* local copies of source and destination pointers */ + p = z->next_out; + q = s->read; + + /* compute number of bytes to copy as far as end of window */ + n = (uInt)((q <= s->write ? s->write : s->end) - q); + if (n > z->avail_out) n = z->avail_out; + if (n && r == Z_BUF_ERROR) r = Z_OK; + + /* update counters */ + z->avail_out -= n; + z->total_out += n; + + /* update check information */ + if (s->checkfn != Z_NULL) + z->adler = s->check = (*s->checkfn)(s->check, q, n); + + /* copy as far as end of window */ + zmemcpy(p, q, n); + p += n; + q += n; + + /* see if more to copy at beginning of window */ + if (q == s->end) + { + /* wrap pointers */ + q = s->window; + if (s->write == s->end) + s->write = s->window; + + /* compute bytes to copy */ + n = (uInt)(s->write - q); + if (n > z->avail_out) n = z->avail_out; + if (n && r == Z_BUF_ERROR) r = Z_OK; + + /* update counters */ + z->avail_out -= n; + z->total_out += n; + + /* update check information */ + if (s->checkfn != Z_NULL) + z->adler = s->check = (*s->checkfn)(s->check, q, n); + + /* copy */ + zmemcpy(p, q, n); + p += n; + q += n; + } + + /* update pointers */ + z->next_out = p; + s->read = q; + + /* done */ + return r; +} diff --git a/contrib/vmap_extractor_v2/stormlib/zlib/zutil.h b/contrib/vmap_extractor_v2/stormlib/zlib/zutil.h new file mode 100644 index 00000000000..718ebc15be1 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlib/zlib/zutil.h @@ -0,0 +1,220 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef _Z_UTIL_H +#define _Z_UTIL_H + +#include "zlib.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#ifdef MSDOS +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +#endif + +#ifdef WIN32 /* Window 95 & Windows NT */ +# define OS_CODE 0x0b +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0F +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) +# define fdopen(fd,type) _fdopen(fd,type) +#endif + + + /* Common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#ifdef HAVE_STRERROR + extern char *strerror OF((int)); +# define zstrerror(errnum) strerror(errnum) +#else +# define zstrerror(errnum) "" +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + extern void zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int z_verbose; + extern void z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +typedef uLong (ZEXPORT *check_func) OF((uLong check, const Bytef *buf, + uInt len)); +voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); +void zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* _Z_UTIL_H */ diff --git a/contrib/vmap_extractor_v2/stormlibdll/DllMain.c b/contrib/vmap_extractor_v2/stormlibdll/DllMain.c new file mode 100644 index 00000000000..cbfa84a08a8 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlibdll/DllMain.c @@ -0,0 +1,24 @@ +/*****************************************************************************/ +/* DllMain.c Copyright (c) Ladislav Zezula 2006 */ +/*---------------------------------------------------------------------------*/ +/* Description: DllMain for the StormLib.dll library */ +/*---------------------------------------------------------------------------*/ +/* Date Ver Who Comment */ +/* -------- ---- --- ------- */ +/* 23.11.06 1.00 Lad The first version of DllMain.c */ +/*****************************************************************************/ + +#define WIN32_LEAN_AND_MEAN +#include + +//----------------------------------------------------------------------------- +// DllMain + +DWORD WINAPI DllMain(HINSTANCE hInst, DWORD dwReason, LPVOID lpReserved) +{ + UNREFERENCED_PARAMETER(hInst); + UNREFERENCED_PARAMETER(dwReason); + UNREFERENCED_PARAMETER(lpReserved); + + return TRUE; +} diff --git a/contrib/vmap_extractor_v2/stormlibdll/StormLib.def b/contrib/vmap_extractor_v2/stormlibdll/StormLib.def new file mode 100644 index 00000000000..c220b6dcca4 --- /dev/null +++ b/contrib/vmap_extractor_v2/stormlibdll/StormLib.def @@ -0,0 +1,47 @@ +LIBRARY StormLib.dll + +EXPORTS + + SFileSetLocale + SFileGetLocale + SFileOpenArchive + SFileCloseArchive + + SFileOpenFileEx + SFileCloseFile + SFileGetFilePos + SFileGetFileSize + SFileSetFilePointer + SFileReadFile + SFileExtractFile + + SFileAddListFile + + SFileCreateArchiveEx + + SFileAddFile + SFileAddWave + SFileRemoveFile + SFileRenameFile + SFileSetFileLocale + + SFileHasFile + SFileGetFileName + SFileGetFileInfo + + SFileFindFirstFile + SFileFindNextFile + SFileFindClose + + SListFileFindFirstFile + SListFileFindNextFile + SListFileFindClose + + SFileSetCompactCallback + SFileCompactArchive + + SFileEnumLocales + + SCompCompress + SCompDecompress + SCompSetDataCompression diff --git a/contrib/vmap_extractor_v2/vmapExtractor_VC71.sln b/contrib/vmap_extractor_v2/vmapExtractor_VC71.sln new file mode 100644 index 00000000000..13156cd66bd --- /dev/null +++ b/contrib/vmap_extractor_v2/vmapExtractor_VC71.sln @@ -0,0 +1,23 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vmapExtractor", "vmapExtractor_VC71.vcproj", "{87335BBF-5DA8-4FEC-A51E-1FB948F2FFE9}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug Ansi Static = Debug Ansi Static + Release Ansi Static = Release Ansi Static + EndGlobalSection + GlobalSection(ProjectDependencies) = postSolution + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {87335BBF-5DA8-4FEC-A51E-1FB948F2FFE9}.Debug Ansi Static.ActiveCfg = Debug Ansi Static|Win32 + {87335BBF-5DA8-4FEC-A51E-1FB948F2FFE9}.Debug Ansi Static.Build.0 = Debug Ansi Static|Win32 + {87335BBF-5DA8-4FEC-A51E-1FB948F2FFE9}.Release Ansi Static.ActiveCfg = Release Ansi Static|Win32 + {87335BBF-5DA8-4FEC-A51E-1FB948F2FFE9}.Release Ansi Static.Build.0 = Release Ansi Static|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/contrib/vmap_extractor_v2/vmapExtractor_VC71.vcproj b/contrib/vmap_extractor_v2/vmapExtractor_VC71.vcproj new file mode 100644 index 00000000000..c546fcc336b --- /dev/null +++ b/contrib/vmap_extractor_v2/vmapExtractor_VC71.vcproj @@ -0,0 +1,786 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/contrib/vmap_extractor_v2/vmapExtractor_VC80.sln b/contrib/vmap_extractor_v2/vmapExtractor_VC80.sln new file mode 100644 index 00000000000..cc24730b192 --- /dev/null +++ b/contrib/vmap_extractor_v2/vmapExtractor_VC80.sln @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual C++ Express 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vmapExtractor", "vmapExtractor_VC80.vcproj", "{87335BBF-5DA8-4FEC-A51E-1FB948F2FFE9}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug Ansi Static|Win32 = Debug Ansi Static|Win32 + Release Ansi Static|Win32 = Release Ansi Static|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {87335BBF-5DA8-4FEC-A51E-1FB948F2FFE9}.Debug Ansi Static|Win32.ActiveCfg = Debug Ansi Static|Win32 + {87335BBF-5DA8-4FEC-A51E-1FB948F2FFE9}.Debug Ansi Static|Win32.Build.0 = Debug Ansi Static|Win32 + {87335BBF-5DA8-4FEC-A51E-1FB948F2FFE9}.Release Ansi Static|Win32.ActiveCfg = Release Ansi Static|Win32 + {87335BBF-5DA8-4FEC-A51E-1FB948F2FFE9}.Release Ansi Static|Win32.Build.0 = Release Ansi Static|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/contrib/vmap_extractor_v2/vmapExtractor_VC80.vcproj b/contrib/vmap_extractor_v2/vmapExtractor_VC80.vcproj new file mode 100644 index 00000000000..5d8cdea90f7 --- /dev/null +++ b/contrib/vmap_extractor_v2/vmapExtractor_VC80.vcproj @@ -0,0 +1,1000 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/contrib/vmap_extractor_v2/vmapextract/adtfile.cpp b/contrib/vmap_extractor_v2/vmapextract/adtfile.cpp new file mode 100644 index 00000000000..b798263ca64 --- /dev/null +++ b/contrib/vmap_extractor_v2/vmapextract/adtfile.cpp @@ -0,0 +1,227 @@ +#include "adtfile.h" + + +char * GetPlainName(char * FileName) +{ + char * szTemp; + + if((szTemp = strrchr(FileName, '\\')) != NULL) + FileName = szTemp + 1; + return FileName; +} + +void fixnamen(char *name, size_t len) +{ + for (size_t i=0; i0 && name[i]>='A' && name[i]<='Z' && isalpha(name[i-1])) + { + name[i] |= 0x20; + } else if ((i==0 || !isalpha(name[i-1])) && name[i]>='a' && name[i]<='z') + { + name[i] &= ~0x20; + } + } +} +void fixname2(char *name, size_t len) +{ + for (size_t i=0; iopen()) + { + m2->ConvertToVMAPModel((char*)szLocalFile); + } + delete m2; + + } + else + fclose(output); + } + + delete[] buf; + } + + } + else if (!strcmp(fourcc,"MWMO")) + { + if (size) + { + + char *buf = new char[size]; + ADT.read(buf, size); + char *p=buf; + int q = 0; + WmoInstansName = new string[size]; + while (p= recordSize); + + data = new unsigned char[recordSize*recordCount+stringSize]; + stringTable = data + recordSize*recordCount; + f.read(data,recordSize*recordCount+stringSize); + f.close(); + return true; +} + +DBCFile::~DBCFile() +{ + delete [] data; +} + +DBCFile::Record DBCFile::getRecord(size_t id) +{ + assert(data); + return Record(*this, data + id*recordSize); +} + +DBCFile::Iterator DBCFile::begin() +{ + assert(data); + return Iterator(*this, data); +} +DBCFile::Iterator DBCFile::end() +{ + assert(data); + return Iterator(*this, stringTable); +} + diff --git a/contrib/vmap_extractor_v2/vmapextract/dbcfile.h b/contrib/vmap_extractor_v2/vmapextract/dbcfile.h new file mode 100644 index 00000000000..bf6b8635a96 --- /dev/null +++ b/contrib/vmap_extractor_v2/vmapextract/dbcfile.h @@ -0,0 +1,139 @@ +#ifndef DBCFILE_H +#define DBCFILE_H +#define __STORMLIB_SELF__ + +#include +#include +#include "Stormlib.h" + +class DBCFile +{ +public: + DBCFile(const std::string &filename); + ~DBCFile(); + + // Open database. It must be openened before it can be used. + bool open(); + + // TODO: Add a close function? + + // Database exceptions + class Exception + { + public: + Exception(const std::string &message): message(message) + { } + virtual ~Exception() + { } + const std::string &getMessage() {return message;} + private: + std::string message; + }; + + // + class NotFound: public Exception + { + public: + NotFound(): Exception("Key was not found") + { } + }; + + // Iteration over database + class Iterator; + class Record + { + public: + Record& operator= (const Record& r) + { + file = r.file; + offset = r.offset; + return *this; + } + float getFloat(size_t field) const + { + assert(field < file.fieldCount); + return *reinterpret_cast(offset+field*4); + } + unsigned int getUInt(size_t field) const + { + assert(field < file.fieldCount); + return *reinterpret_cast(offset+(field*4)); + } + int getInt(size_t field) const + { + assert(field < file.fieldCount); + return *reinterpret_cast(offset+field*4); + } + unsigned char getByte(size_t ofs) const + { + assert(ofs < file.recordSize); + return *reinterpret_cast(offset+ofs); + } + const char *getString(size_t field) const + { + assert(field < file.fieldCount); + size_t stringOffset = getUInt(field); + assert(stringOffset < file.stringSize); + //char * tmp = (char*)file.stringTable + stringOffset; + //unsigned char * tmp2 = file.stringTable + stringOffset; + return reinterpret_cast(file.stringTable + stringOffset); + } + private: + Record(DBCFile &file, unsigned char *offset): file(file), offset(offset) {} + unsigned char *offset; + DBCFile &file; + + friend class DBCFile; + friend class Iterator; + }; + + /* Iterator that iterates over records */ + class Iterator + { + public: + Iterator(DBCFile &file, unsigned char *offset): + record(file, offset) {} + /// Advance (prefix only) + Iterator & operator++() { + record.offset += record.file.recordSize; + return *this; + } + /// Return address of current instance + Record const & operator*() const { return record; } + const Record* operator->() const { + return &record; + } + /// Comparison + bool operator==(const Iterator &b) const + { + return record.offset == b.record.offset; + } + bool operator!=(const Iterator &b) const + { + return record.offset != b.record.offset; + } + private: + Record record; + }; + + // Get record by id + Record getRecord(size_t id); + /// Get begin iterator over records + Iterator begin(); + /// Get begin iterator over records + Iterator end(); + /// Trivial + size_t getRecordCount() const { return recordCount;} + size_t getFieldCount() const { return fieldCount; } + +private: + std::string filename; + size_t recordSize; + size_t recordCount; + size_t fieldCount; + size_t stringSize; + unsigned char *data; + unsigned char *stringTable; +}; + +#endif diff --git a/contrib/vmap_extractor_v2/vmapextract/model.cpp b/contrib/vmap_extractor_v2/vmapextract/model.cpp new file mode 100644 index 00000000000..7dca7841d74 --- /dev/null +++ b/contrib/vmap_extractor_v2/vmapextract/model.cpp @@ -0,0 +1,261 @@ +//#include "common.h" +#include "model.h" +//#include "world.h" +#include +#include + +//int globalTime = 0; + +Model::Model(std::string &filename) : filename(filename) +{ +} + +bool Model::open() +{ + MPQFile f(filename.c_str()); + + ok = !f.isEof(); + + if (!ok) + { + f.close(); + printf("Error loading model %s\n", filename.c_str()); + return false; + } + + memcpy(&header, f.getBuffer(), sizeof(ModelHeader)); + if(header.nBoundingTriangles > 0) { + +#if 0 + animated = isAnimated(f); + if(animated) + { + f.close(); + return false; + } +#endif + trans = 1.0f; + origVertices = (ModelVertex*)(f.getBuffer() + header.ofsVertices); + + vertices = new Vec3D[header.nVertices]; + normals = new Vec3D[header.nVertices]; + + for (size_t i=0; iofsIndex); + uint16 *triangles = (uint16*)(f.getBuffer() + view->ofsTris); + + nIndices = view->nTris; + indices = new uint16[nIndices]; + for (size_t i = 0; i0) { + ModelBoneDef &bb = bo[verts[i].bones[b]]; + if (bb.translation.type || bb.rotation.type || bb.scaling.type || (bb.flags&8)) { + if (bb.flags&8) { + // if we have billboarding, the model will need per-instance animation + ind = true; + } + animGeometry = true; + break; + } + } + } + } + + if (animGeometry) animBones = true; + else { + for (size_t i=0; i 0; + + bool animMisc = header.nCameras>0 || // why waste time, pretty much all models with cameras need animation + header.nLights>0 || // same here + header.nParticleEmitters>0 || + header.nRibbonEmitters>0; + + if (animMisc) animBones = true; + + // animated colors + if (header.nColors) { + ModelColorDef *cols = (ModelColorDef*)(f.getBuffer() + header.ofsColors); + for (size_t i=0; i0) + { + fwrite(indices, sizeof(unsigned short), nIdexes, output); + } + fwrite("VERT",4, 1, output); + wsize = sizeof(int) + sizeof(float) * 3 * nVertices; + fwrite(&wsize, sizeof(int), 1, output); + fwrite(&nVertices, sizeof(int), 1, output); + if(nVertices >0) + { + for(int vpos=0; vpos + +class Model; +class WMOInstance; + +Vec3D fixCoordSystem(Vec3D v); + + + + +class Model +{ +public: + ModelHeader header; + ModelAnimation *anims; + int *globalSequences; + +public: + bool animGeometry,animTextures,animBones; + bool animated; + + bool isAnimated(MPQFile &f); + ModelVertex *origVertices; + Vec3D *vertices, *normals; + uint16 *indices; + size_t nIndices; + + bool open(); + bool ConvertToVMAPModel(char * outfilename); + +public: + + bool ok; + bool ind; + + float rad; + float trans; + bool animcalc; + int anim, animtime; + + Model(std::string &filename); + ~Model(); + +private: + std::string filename; + char outfilename; +}; + +class ModelInstance +{ +public: + Model *model; + + int id; + + Vec3D pos, rot; + unsigned int d1, scale; + + float frot,w,sc; + + int light; + Vec3D ldir; + Vec3D lcol; + + ModelInstance() {} + ModelInstance(MPQFile &f,const char* ModelInstName,const char*MapName, FILE *pDirfile); + +}; + +#endif diff --git a/contrib/vmap_extractor_v2/vmapextract/modelheaders.h b/contrib/vmap_extractor_v2/vmapextract/modelheaders.h new file mode 100644 index 00000000000..7d5e800e796 --- /dev/null +++ b/contrib/vmap_extractor_v2/vmapextract/modelheaders.h @@ -0,0 +1,304 @@ +#ifndef MODELHEADERS_H +#define MODELHEADERS_H + +typedef unsigned char uint8; +typedef char int8; +typedef unsigned short uint16; +typedef short int16; +typedef unsigned int uint32; +typedef int int32; + +#pragma pack(push,1) + +struct ModelHeader { + char id[4]; + uint8 version[4]; + uint32 nameLength; + uint32 nameOfs; + uint32 type; + + uint32 nGlobalSequences; + uint32 ofsGlobalSequences; + uint32 nAnimations; + uint32 ofsAnimations; + uint32 nC; + uint32 ofsC; + uint32 nD; + uint32 ofsD; + uint32 nBones; + uint32 ofsBones; + uint32 nF; + uint32 ofsF; + + uint32 nVertices; + uint32 ofsVertices; + uint32 nViews; + uint32 ofsViews; + + uint32 nColors; + uint32 ofsColors; + + uint32 nTextures; + uint32 ofsTextures; + + uint32 nTransparency; // H + uint32 ofsTransparency; + uint32 nI; // always unused ? + uint32 ofsI; + uint32 nTexAnims; // J + uint32 ofsTexAnims; + uint32 nK; + uint32 ofsK; + + uint32 nTexFlags; + uint32 ofsTexFlags; + uint32 nY; + uint32 ofsY; + + uint32 nTexLookup; + uint32 ofsTexLookup; + + uint32 nTexUnitLookup; // L + uint32 ofsTexUnitLookup; + uint32 nTransparencyLookup; // M + uint32 ofsTransparencyLookup; + uint32 nTexAnimLookup; + uint32 ofsTexAnimLookup; + + float floats[14]; + + uint32 nBoundingTriangles; + uint32 ofsBoundingTriangles; + uint32 nBoundingVertices; + uint32 ofsBoundingVertices; + uint32 nBoundingNormals; + uint32 ofsBoundingNormals; + + uint32 nO; + uint32 ofsO; + uint32 nP; + uint32 ofsP; + uint32 nQ; + uint32 ofsQ; + uint32 nLights; // R + uint32 ofsLights; + uint32 nCameras; // S + uint32 ofsCameras; + uint32 nT; + uint32 ofsT; + uint32 nRibbonEmitters; // U + uint32 ofsRibbonEmitters; + uint32 nParticleEmitters; // V + uint32 ofsParticleEmitters; + +}; + +// block B - animations +struct ModelAnimation { + uint32 animID; + uint32 timeStart; + uint32 timeEnd; + + float moveSpeed; + + uint32 loopType; + uint32 flags; + uint32 d1; + uint32 d2; + uint32 playSpeed; // note: this can't be play speed because it's 0 for some models + + Vec3D boxA, boxB; + float rad; + + int16 s[2]; +}; + + +// sub-block in block E - animation data +struct AnimationBlock { + int16 type; // interpolation type (0=none, 1=linear, 2=hermite) + int16 seq; // global sequence id or -1 + uint32 nRanges; + uint32 ofsRanges; + uint32 nTimes; + uint32 ofsTimes; + uint32 nKeys; + uint32 ofsKeys; +}; + +// block E - bones +struct ModelBoneDef { + int32 animid; + int32 flags; + int16 parent; // parent bone index + int16 geoid; + // new int added to the bone definitions. Added in WoW 2.0 + int32 unknown; + AnimationBlock translation; + AnimationBlock rotation; + AnimationBlock scaling; + Vec3D pivot; +}; + +struct ModelTexAnimDef { + AnimationBlock trans, rot, scale; +}; + +struct ModelVertex { + Vec3D pos; + uint8 weights[4]; + uint8 bones[4]; + Vec3D normal; + Vec2D texcoords; + int unk1, unk2; // always 0,0 so this is probably unused +}; + +struct ModelView { + uint32 nIndex, ofsIndex; // Vertices in this model (index into vertices[]) + uint32 nTris, ofsTris; // indices + uint32 nProps, ofsProps; // additional vtx properties + uint32 nSub, ofsSub; // materials/renderops/submeshes + uint32 nTex, ofsTex; // material properties/textures + int32 lod; // LOD bias? +}; + + +/// One material + render operation +struct ModelGeoset { + uint16 d1; // mesh part id? + uint16 d2; // ? + uint16 vstart; // first vertex + uint16 vcount; // num vertices + uint16 istart; // first index + uint16 icount; // num indices + uint16 d3; // number of bone indices + uint16 d4; // offset into bone index list + uint16 d5; // ? + uint16 d6; // root bone? + Vec3D v; + float unknown[4]; // Added in WoW 2.0? +}; + +/// A texture unit (sub of material) +struct ModelTexUnit{ + // probably the texture units + // size always >=number of materials it seems + uint16 flags; // Flags + uint16 order; // ? + uint16 op; // Material this texture is part of (index into mat) + uint16 op2; // Always same as above? + int16 colorIndex; // color or -1 + uint16 flagsIndex; // more flags... + uint16 texunit; // Texture unit (0 or 1) + uint16 d4; // ? (seems to be always 1) + uint16 textureid; // Texture id (index into global texture list) + uint16 texunit2; // copy of texture unit value? + uint16 transid; // transparency id (index into transparency list) + uint16 texanimid; // texture animation id +}; + +// block X - render flags +struct ModelRenderFlags { + uint16 flags; + uint16 blend; +}; + +// block G - color defs +struct ModelColorDef { + AnimationBlock color; + AnimationBlock opacity; +}; + +// block H - transp defs +struct ModelTransDef { + AnimationBlock trans; +}; + +struct ModelTextureDef { + uint32 type; + uint32 flags; + uint32 nameLen; + uint32 nameOfs; +}; + +struct ModelLightDef { + int16 type; + int16 bone; + Vec3D pos; + AnimationBlock ambColor; + AnimationBlock ambIntensity; + AnimationBlock color; + AnimationBlock intensity; + AnimationBlock attStart; + AnimationBlock attEnd; + AnimationBlock unk1; +}; + +struct ModelCameraDef { + int32 id; + float fov, farclip, nearclip; + AnimationBlock transPos; + Vec3D pos; + AnimationBlock transTarget; + Vec3D target; + AnimationBlock rot; +}; + + +struct ModelParticleParams { + float mid; + uint32 colors[3]; + float sizes[3]; + int16 d[10]; + float unk[3]; + float scales[3]; + float slowdown; + float rotation; + float f2[16]; +}; + +struct ModelParticleEmitterDef { + int32 id; + int32 flags; + Vec3D pos; + int16 bone; + int16 texture; + int32 nZero1; + int32 ofsZero1; + int32 nZero2; + int32 ofsZero2; + int16 blend; + int16 type; + int16 s1; + int16 s2; + int16 cols; + int16 rows; + AnimationBlock params[10]; + ModelParticleParams p; + AnimationBlock unk; +}; + + +struct ModelRibbonEmitterDef { + int32 id; + int32 bone; + Vec3D pos; + int32 nTextures; + int32 ofsTextures; + int32 nUnknown; + int32 ofsUnknown; + AnimationBlock color; + AnimationBlock opacity; + AnimationBlock above; + AnimationBlock below; + float res, length, unk; + int16 s1, s2; + AnimationBlock unk1; + AnimationBlock unk2; +}; + + +#pragma pack(pop) + + +#endif \ No newline at end of file diff --git a/contrib/vmap_extractor_v2/vmapextract/mpq.cpp b/contrib/vmap_extractor_v2/vmapextract/mpq.cpp new file mode 100644 index 00000000000..ae847d8be33 --- /dev/null +++ b/contrib/vmap_extractor_v2/vmapextract/mpq.cpp @@ -0,0 +1,136 @@ +#include "mpq.h" +//#include +#include "Stormlib.h" +#define __STORMLIB_SELF__ + +typedef std::vector ArchiveSet; +ArchiveSet gOpenArchives; +//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +MPQArchive::MPQArchive(const char* filename) +{ + BOOL succ = SFileOpenArchive(filename, 0, 0,&hMPQ); + if (succ) + { + MPQArchive*ar = (MPQArchive*)(hMPQ); + printf("Opening %s\n", filename); + gOpenArchives.push_back(ar); + succ = true; + + } + else + { + printf("Error!!!Not open archive %s\n", filename); + } +} + +void MPQArchive::close() +{ + SFileCloseArchive(hMPQ); +} + +//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +MPQFile::MPQFile(const char* filename): + eof(false), + buffer(0), + pointer(0), + size(0) +{ + for(ArchiveSet::iterator i=gOpenArchives.begin(); i!=gOpenArchives.end();++i) + { + + HANDLE hFile = ""; + MPQArchive*(hMPQ) = *i; + BOOL succ = SFileOpenFileEx(hMPQ,filename,0, &hFile); + if (succ) + { + DWORD s = SFileGetFileSize(hFile, 0); + if (!s) + { + eof = true; + buffer = 0; + return; + } + size = (size_t)s; + buffer = new char[s]; + SFileReadFile(hFile, buffer, s, 0, 0); + SFileCloseFile(hFile); + + eof = false; + return; + } + } + + eof = true; + buffer = 0; + +} + +MPQFile::~MPQFile() +{ + close(); +} + +size_t MPQFile::read(void* dest, size_t bytes) +{ + if (eof) + return 0; + + size_t rpos = pointer + bytes; + if (rpos > size) + { + bytes = size - pointer; + eof = true; + } + + memcpy(dest, &(buffer[pointer]), bytes); + + pointer = rpos; + + return bytes; +} + +bool MPQFile::isEof() +{ + return eof; +} + +void MPQFile::seek(int offset) +{ + pointer = offset; + eof = (pointer >= size); +} + +void MPQFile::seekRelative(int offset) +{ + pointer += offset; + eof = (pointer >= size); +} + +void MPQFile::close() +{ + if (buffer) + delete[] buffer; + buffer = 0; + eof = true; +} + +size_t MPQFile::getSize() +{ + return size; +} + +size_t MPQFile::getPos() +{ + return pointer; +} + +char* MPQFile::getBuffer() +{ + return buffer; +} + +char* MPQFile::getPointer() +{ + return buffer + pointer; +} + diff --git a/contrib/vmap_extractor_v2/vmapextract/mpq.h b/contrib/vmap_extractor_v2/vmapextract/mpq.h new file mode 100644 index 00000000000..79f30afc79b --- /dev/null +++ b/contrib/vmap_extractor_v2/vmapextract/mpq.h @@ -0,0 +1,69 @@ +#define _CRT_SECURE_NO_DEPRECATE + +#ifndef MPQ_H +#define MPQ_H + +#define __STORMLIB_SELF__ + +#include +#include +#include +#include +#include "Stormlib.h" + +using namespace std; + +typedef unsigned int uint32; + + +class MPQArchive +{ + +public: + HANDLE hMPQ; + MPQArchive(const char* filename); + void close(); +}; + +class MPQFile +{ + HANDLE hFile; + HANDLE hMPQ; + bool eof; + char *buffer; + size_t pointer, + size; + + // disable copying + //MPQFile(const MPQFile &f) {} + //void operator=(const MPQFile &f) {} + +public: + MPQFile(const char* filename); + ~MPQFile(); + size_t read(void* dest, size_t bytes); + size_t getSize(); + size_t getPos(); + char* getBuffer(); + char* getPointer(); + bool isEof(); + void seek(int offset); + void seekRelative(int offset); + void close(); +}; + +inline void flipcc(char *fcc) +{ + char t; + t=fcc[0]; + fcc[0]=fcc[3]; + fcc[3]=t; + t=fcc[1]; + fcc[1]=fcc[2]; + fcc[2]=t; +} + + + +#endif + diff --git a/contrib/vmap_extractor_v2/vmapextract/vec3d.h b/contrib/vmap_extractor_v2/vmapextract/vec3d.h new file mode 100644 index 00000000000..88b8e1c4f32 --- /dev/null +++ b/contrib/vmap_extractor_v2/vmapextract/vec3d.h @@ -0,0 +1,230 @@ +#ifndef VEC3D_H +#define VEC3D_H + +#include +#include + + + +class Vec3D { +public: + float x,y,z; + + Vec3D(float x0 = 0.0f, float y0 = 0.0f, float z0 = 0.0f) : x(x0), y(y0), z(z0) {} + + Vec3D(const Vec3D& v) : x(v.x), y(v.y), z(v.z) {} + + Vec3D& operator= (const Vec3D &v) { + x = v.x; + y = v.y; + z = v.z; + return *this; + } + + Vec3D operator+ (const Vec3D &v) const + { + Vec3D r(x+v.x,y+v.y,z+v.z); + return r; + } + + Vec3D operator- (const Vec3D &v) const + { + Vec3D r(x-v.x,y-v.y,z-v.z); + return r; + } + + float operator* (const Vec3D &v) const + { + return x*v.x + y*v.y + z*v.z; + } + + Vec3D operator* (float d) const + { + Vec3D r(x*d,y*d,z*d); + return r; + } + + friend Vec3D operator* (float d, const Vec3D& v) + { + return v * d; + } + + Vec3D operator% (const Vec3D &v) const + { + Vec3D r(y*v.z-z*v.y, z*v.x-x*v.z, x*v.y-y*v.x); + return r; + } + + Vec3D& operator+= (const Vec3D &v) + { + x += v.x; + y += v.y; + z += v.z; + return *this; + } + + Vec3D& operator-= (const Vec3D &v) + { + x -= v.x; + y -= v.y; + z -= v.z; + return *this; + } + + Vec3D& operator*= (float d) + { + x *= d; + y *= d; + z *= d; + return *this; + } + + float lengthSquared() const + { + return x*x+y*y+z*z; + } + + float length() const + { + return sqrt(x*x+y*y+z*z); + } + + Vec3D& normalize() + { + this->operator*= (1.0f/length()); + return *this; + } + + Vec3D operator~ () const + { + Vec3D r(*this); + r.normalize(); + return r; + } + + friend std::istream& operator>>(std::istream& in, Vec3D& v) + { + in >> v.x >> v.y >> v.z; + return in; + } + + operator float*() + { + return (float*)this; + } + +}; + + +class Vec2D { +public: + float x,y; + + Vec2D(float x0 = 0.0f, float y0 = 0.0f) : x(x0), y(y0) {} + + Vec2D(const Vec2D& v) : x(v.x), y(v.y) {} + + Vec2D& operator= (const Vec2D &v) { + x = v.x; + y = v.y; + return *this; + } + + Vec2D operator+ (const Vec2D &v) const + { + Vec2D r(x+v.x,y+v.y); + return r; + } + + Vec2D operator- (const Vec2D &v) const + { + Vec2D r(x-v.x,y-v.y); + return r; + } + + float operator* (const Vec2D &v) const + { + return x*v.x + y*v.y; + } + + Vec2D operator* (float d) const + { + Vec2D r(x*d,y*d); + return r; + } + + friend Vec2D operator* (float d, const Vec2D& v) + { + return v * d; + } + + Vec2D& operator+= (const Vec2D &v) + { + x += v.x; + y += v.y; + return *this; + } + + Vec2D& operator-= (const Vec2D &v) + { + x -= v.x; + y -= v.y; + return *this; + } + + Vec2D& operator*= (float d) + { + x *= d; + y *= d; + return *this; + } + + float lengthSquared() const + { + return x*x+y*y; + } + + float length() const + { + return sqrt(x*x+y*y); + } + + Vec2D& normalize() + { + this->operator*= (1.0f/length()); + return *this; + } + + Vec2D operator~ () const + { + Vec2D r(*this); + r.normalize(); + return r; + } + + + friend std::istream& operator>>(std::istream& in, Vec2D& v) + { + in >> v.x >> v.y; + return in; + } + + operator float*() + { + return (float*)this; + } + +}; + + +inline void rotate(float x0, float y0, float *x, float *y, float angle) +{ + float xa = *x - x0, ya = *y - y0; + *x = xa*cosf(angle) - ya*sinf(angle) + x0; + *y = xa*sinf(angle) + ya*cosf(angle) + y0; +} + + + +#endif + diff --git a/contrib/vmap_extractor_v2/vmapextract/vmapexport.cpp b/contrib/vmap_extractor_v2/vmapextract/vmapexport.cpp new file mode 100644 index 00000000000..dfc7cddcfdd --- /dev/null +++ b/contrib/vmap_extractor_v2/vmapextract/vmapexport.cpp @@ -0,0 +1,566 @@ +/*****************************************************************************/ +/* StormLibTest.cpp Copyright (c) Ladislav Zezula 2003 */ +/*---------------------------------------------------------------------------*/ +/* This module uses very brutal test methods for StormLib. It extracts all */ +/* files from the archive with Storm.dll and with stormlib and compares them,*/ +/* then tries to build a copy of the entire archive, then removes a few files*/ +/* from the archive and adds them back, then compares the two archives, ... */ +/*---------------------------------------------------------------------------*/ +/* Date Ver Who Comment */ +/* -------- ---- --- ------- */ +/* 25.03.03 1.00 Lad The first version of StormLibTest.cpp */ +/*****************************************************************************/ + +#define _CRT_SECURE_NO_DEPRECATE +#include +#include +#include +#include +#include +#include +#include + + +#define __STORMLIB_SELF__ // Don't use StormLib.lib +#include "StormLib.h" + +#pragma warning(disable : 4505) +#pragma comment(lib, "Winmm.lib") + +//From Extractor +#include "adtfile.h" +#include "wdtfile.h" +#include "dbcfile.h" +#include "mpq.h" +#include "wmo.h" + +//------------------------------------------------------------------------------ +// Defines + +#define MPQ_BLOCK_SIZE 0x1000 + +//----------------------------------------------------------------------------- +// from extractor +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned int uint32; +typedef struct{ + char name[64]; + unsigned int id; +}map_id; + +map_id * map_ids; +uint16 * areas; +uint16 *areamax; +uint32 map_count; +char output_path[128]="."; +char input_path[1024]="."; +bool hasInputPathParam = false; +char tmp[512]; +bool preciseVectorData = false; +//char gamepath[1024]; + +//Convert function +//bool ConvertADT(char*,char*); + +// Constants + +//static const char * szWorkDirMaps = ".\\Maps"; +static const char * szWorkDirWmo = ".\\buildings"; + +//static LPBYTE pbBuffer1 = NULL; +//static LPBYTE pbBuffer2 = NULL; + +// Local testing functions + +static void clreol() +{ + printf("\r \r"); +} + +static const char * GetPlainName(const char * szFileName) +{ + const char * szTemp; + + if((szTemp = strrchr(szFileName, '\\')) != NULL) + szFileName = szTemp + 1; + return szFileName; +} +//------------------------------------------------------------------------------ +static void ShowProcessedFile(const char * szFileName) +{ + char szLine[80]; + size_t nLength = strlen(szFileName); + + memset(szLine, 0x20, sizeof(szLine)); + szLine[sizeof(szLine)-1] = 0; + + if(nLength > sizeof(szLine)-1) + nLength = sizeof(szLine)-1; + memcpy(szLine, szFileName, nLength); + printf("\r%s\n", szLine); +} + + +//---------------------------------------------------------------------------------------------------------------------------------------------------------------------- +int ExtractWmo(const std::vector& pArchiveNames) +{ + + char* szListFile = ""; + char szLocalFile[MAX_PATH] = ""; + HANDLE hMpq = ""; + BOOL bResult = FALSE; + + //const char* ParsArchiveNames[] = {"patch-2.MPQ", "patch.MPQ", "common.MPQ", "expansion.MPQ"}; + + int nError = ERROR_SUCCESS; + if(szListFile == NULL || *szListFile == 0) + szListFile = NULL; + //char tmp[1024]; + //for (size_t i=0; i<4; i++) + for (size_t i=0; iopen()) + { + printf("Not open RootWmo!!!\n"); + bResult = SFileFindNextFile(hFind, &wf); + continue; + } + FILE *output=fopen(szLocalFile,"wb"); + froot->ConvertToVMAPRootWmo(output); + int Wmo_nVertices = 0; + if(froot->nGroups !=0) + { + for (int i=0; inGroups; i++) + { + char temp[512]; + strcpy(temp, wf.cFileName); + temp[strlen(wf.cFileName)-4] = 0; + char groupFileName[512]; + sprintf(groupFileName,"%s_%03d.wmo",temp, i); + printf("%s\n",groupFileName); + //printf("GroupWmo!\n"); + string s = groupFileName; + WMOGroup * fgroup = new WMOGroup(s); + if(!fgroup->open()) + { + printf("Not all open Group file for: %s\n",GetPlainName(wf.cFileName)); + bResult = SFileFindNextFile(hFind, &wf); + break; + } + Wmo_nVertices += fgroup->ConvertToVMAPGroupWmo(output, preciseVectorData); + } + } + fseek(output, 8, SEEK_SET); // store the correct no of vertices + fwrite(&Wmo_nVertices,sizeof(int),1,output); + fclose(output); + } + } else { + fclose(n); + } + wf.dwFileFlags &= ~MPQ_FILE_HAS_EXTRA; + wf.dwFileFlags &= ~MPQ_FILE_EXISTS; + // Find the next file + bResult = SFileFindNextFile(hFind, &wf); + } + // Delete the extracted file in the case of an error + if(nError != ERROR_SUCCESS) + DeleteFile(szLocalFile); + // Close the search handle + if(hFind != NULL) + SFileFindClose(hFind); + + } + } + // Close both archives + if(hMpq != NULL) + //SFileCloseArchive(hMpq); + if(nError == ERROR_SUCCESS) + printf("\nExtract wmo complete (No errors)\n"); + + return nError; + +} + +void ExtractMapsFromMpq() +{ + +} +//----------------------------------------------------------------------------- +void ParsMapFiles() +{ + char fn[512]; + char id_filename[64]; + char id[10]; + for (unsigned int i=0; iinit(id_filename); + delete ADT; + } + + } + } + } + } +} +#if 0 +void ParsMapFiles() +{ + + char fn[512]; + for (unsigned int i=0; iinit(); + delete ADT; + } + + } + } + } + } +} +#endif +//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + +void getGamePath() +{ +#ifdef _WIN32 + HKEY key; + DWORD t,s; + LONG l; + s = sizeof(input_path); + memset(input_path,0,s); + l = RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Blizzard Entertainment\\World of Warcraft",0,KEY_QUERY_VALUE,&key); + //l = RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Blizzard Entertainment\\Burning Crusade Closed Beta",0,KEY_QUERY_VALUE,&key); + l = RegQueryValueEx(key,"InstallPath",0,&t,(LPBYTE)input_path,&s); + RegCloseKey(key); + if (strlen(input_path) > 0) + { + if (input_path[strlen(input_path) - 1] != '\\') strcat(input_path, "\\"); + } + strcat(input_path,"Data\\"); +#else + strcpy(input_path,"data/"); +#endif +} + +//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + +bool scan_patches(char* scanmatch, std::vector& pArchiveNames) +{ + int i; + char path[512]; + std::list matches; + + WIN32_FIND_DATA ffData; + HANDLE hFind; + + for (i = 1; i <= 99; i++) + { + if (i != 1) + { + sprintf(path, "%s-%d.mpq", scanmatch, i); + } + else + { + sprintf(path, "%s.mpq", scanmatch); + } + + hFind = INVALID_HANDLE_VALUE; + hFind = FindFirstFile(path, &ffData); + if (hFind == INVALID_HANDLE_VALUE) break; + FindClose(hFind); + + matches.push_back(path); + } + + matches.reverse(); + for (std::list::iterator i = matches.begin(); i != matches.end(); i++) + { + pArchiveNames.push_back(i->c_str()); + } + + printf("\n"); + + return(true); +} + +//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + +bool fillArchiveNameVector(std::vector& pArchiveNames) { + //srand((unsigned int)time(0)); + + if(!hasInputPathParam) + getGamePath(); + + printf("\nGame path: %s\n", input_path); + + char path[512]; + std::vector locales; + + // scan game directories + WIN32_FIND_DATA ffData; + HANDLE hFind; + DWORD dwError; + + // first, scan for locales (4-letter directories) + printf("Scanning for locales.\n"); + sprintf(path, "%s*.*", input_path); + hFind = INVALID_HANDLE_VALUE; + hFind = FindFirstFile(path, &ffData); + if (hFind == INVALID_HANDLE_VALUE) + { + printf("\nCould not open data directory for reading. Aborting.\n"); + return(false); + } + do + { + if (ffData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + if (ffData.cFileName[0] != '.') + { + if (strlen(ffData.cFileName) == 4) + { + printf("Found locale: %s\n", ffData.cFileName); + locales.push_back(ffData.cFileName); + } + } + } + } while (FindNextFile(hFind, &ffData) != 0); + dwError = GetLastError(); + FindClose(hFind); + if (dwError != ERROR_NO_MORE_FILES) + { + printf("\nError reading data directory while scanning locales. Aborting.\n"); + return(false); + } + printf("\n"); + + if (locales.size() == 0) + { + printf("Sorry, no locales found. Aborting.\n"); + return(false); + } + + // now, scan for the patch levels in the core dir + printf("Loading patch levels from data directory.\n"); + sprintf(path, "%spatch", input_path); + if (!scan_patches(path, pArchiveNames)) return(false); + + // now, scan for the patch levels in locale dirs + printf("Loading patch levels from locale directories.\n"); + for (std::vector::iterator i = locales.begin(); i != locales.end(); i++) + { + printf("Locale: %s\n", i->c_str()); + sprintf(path, "%s%s\\patch-%s", input_path, i->c_str(), i->c_str()); + if (!scan_patches(path, pArchiveNames)) return(false); + } + + // open expansion and common files + printf("Opening data files from data directory.\n"); + sprintf(path, "%sexpansion.mpq", input_path); + pArchiveNames.push_back(path); + sprintf(path, "%scommon.mpq", input_path); + pArchiveNames.push_back(path); + printf("\n"); + + // open locale expansion and common files + printf("Opening data files from locale directories.\n"); + for (std::vector::iterator i = locales.begin(); i != locales.end(); i++) + { + printf("Locale: %s\n", i->c_str()); + sprintf(path, "%s%s\\expansion-locale-%s.mpq", input_path, i->c_str(), i->c_str()); + pArchiveNames.push_back(path); + sprintf(path, "%s%s\\locale-%s.mpq", input_path, i->c_str(), i->c_str()); + pArchiveNames.push_back(path); + printf("\n"); + } + return true; +} +//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +// return false it normal processing can not proceed + +bool processArgv(int argc, char ** argv, char*versionString) +{ + bool result = true; + hasInputPathParam = false; + bool preciseVectorData = false; + + for(int i=1; i< argc; ++i) { + if(strcmp("-s",argv[i]) == 0) { + preciseVectorData = false; + } else if(strcmp("-d",argv[i]) == 0) { + if((i+1)]\n", argv[0]); + printf(" -s : (default) small size (data size optimization), ~500MB less vmap data.\n"); + printf(" -l : large size, ~500MB more vmap data. (might contain more details)\n"); + printf(" -d : Path to the vector data source folder.\n"); + printf(" -? : This message.\n"); + } + return result; +} + +//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +// Main +// +// The program must be run with two command line arguments +// +// Arg1 - The source MPQ name (for testing reading and file find) +// Arg2 - Listfile name +// + +int main(int argc, char ** argv) +{ + //char tmp[512]; +// FILE* pDatei; +// char tmp[512]; +// char tmp1[512]; + //char tmp2[512]; +// char tmp3[512]; +// char tmp4[512]; +// char szMpqName[MAX_PATH] = ""; +// char szListFile[MAX_PATH] = ""; + int nError = ERROR_SUCCESS; + char *versionString = "V2.4 2007_07_12"; + + // Use command line arguments, when some + if(!processArgv(argc, argv, versionString)) + return 1; + + printf("Extract %s. Beginning work ....\n",versionString); + // Set the lowest priority to allow running in the background + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL); + //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + // Create the working directory + if(nError == ERROR_SUCCESS) + { + //if(!CreateDirectory(szWorkDirMaps, NULL)) + // nError = GetLastError(); + if(!CreateDirectory(szWorkDirWmo, NULL)) + nError = GetLastError(); + if(nError == ERROR_ALREADY_EXISTS) + nError = ERROR_SUCCESS; + } + //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + // patch goes first -> fake priority handling + std::vector archives; + + //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + std::vector archiveNames; + + fillArchiveNameVector(archiveNames); + for (size_t i=0; iopen(); + map_count=dbc->getRecordCount (); + map_ids=new map_id[map_count]; + for(unsigned int x=0;xgetRecord (x).getUInt(0); + strcpy(map_ids[x].name,dbc->getRecord(x).getString(1)); + printf("Map - %s\n",map_ids[x].name); + } + + delete dbc; + ParsMapFiles(); + delete [] map_ids; + nError = ERROR_SUCCESS; + } + + clreol(); + if(nError != ERROR_SUCCESS) { + printf("ERROR: Extract %s. Work NOT complete.\n Precise vector data=%d.\nPress any key.\n",versionString, preciseVectorData); + _getch(); + } + printf("Extract %s. Work complete. No errors.",versionString); +} diff --git a/contrib/vmap_extractor_v2/vmapextract/wdtfile.cpp b/contrib/vmap_extractor_v2/vmapextract/wdtfile.cpp new file mode 100644 index 00000000000..831cdaae79f --- /dev/null +++ b/contrib/vmap_extractor_v2/vmapextract/wdtfile.cpp @@ -0,0 +1,120 @@ +#define __STORMLIB_SELF__ + +#include "wdtfile.h" +#include "adtfile.h" + + +char * wdtGetPlainName(char * FileName) +{ + char * szTemp; + + if((szTemp = strrchr(FileName, '\\')) != NULL) + FileName = szTemp + 1; + return FileName; +} + +WDTFile::WDTFile(char* file_name, char* file_name1):WDT(file_name) +{ + filename.append(file_name1,strlen(file_name1)); +} + +bool WDTFile::init(char *map_id) +{ + + if (WDT.isEof()) + { + //printf("Can't find WDT file.\n"); + return false; + } + + char fourcc[5]; + size_t size; + + + const char dirname[] = "buildings\\dir"; + FILE *dirfile; + dirfile = fopen(dirname, "ab"); + if(!dirfile) + { + printf("Can't open dirfile!'%s'\n"); + return false; + } + + + while (!WDT.isEof()) + { + WDT.read(fourcc,4); + WDT.read(&size, 4); + + flipcc(fourcc); + fourcc[4] = 0; + + size_t nextpos = WDT.getPos() + size; + + if (!strcmp(fourcc,"MAIN")) + { + } + if (!strcmp(fourcc,"MWMO")) + { + // global map objects + if (size) + { + char *buf = new char[size]; + WDT.read(buf, size); + char *p=buf; + int q = 0; + gWmoInstansName = new string[size]; + while (p=0 && z >= 0 && x<64 && z<64)) return NULL; + + char name[512]; + + sprintf(name,"World\\Maps\\%s\\%s_%d_%d.adt", filename.c_str(), filename.c_str(), x, z); + return new ADTFile(name); +} diff --git a/contrib/vmap_extractor_v2/vmapextract/wdtfile.h b/contrib/vmap_extractor_v2/vmapextract/wdtfile.h new file mode 100644 index 00000000000..7a7002a2ed8 --- /dev/null +++ b/contrib/vmap_extractor_v2/vmapextract/wdtfile.h @@ -0,0 +1,30 @@ +#ifndef WDTFILE_H +#define WDTFILE_H + +#define __STORMLIB_SELF__ + +#include "mpq.h" +#include "adtfile.h" +#include "wmo.h" +#include +#include "stdlib.h" + +class WDTFile +{ +public: + WDTFile(char* file_name, char* file_name1); + ~WDTFile(void); + bool init(char *map_id); + + string* gWmoInstansName; + int gnWMO, nMaps; + + ADTFile* GetMap(int x, int z); + +private: + MPQFile WDT; + bool maps[64][64]; + string filename; +}; + +#endif diff --git a/contrib/vmap_extractor_v2/vmapextract/wmo.cpp b/contrib/vmap_extractor_v2/vmapextract/wmo.cpp new file mode 100644 index 00000000000..9dfda6f771f --- /dev/null +++ b/contrib/vmap_extractor_v2/vmapextract/wmo.cpp @@ -0,0 +1,531 @@ +#define __STORMLIB_SELF__ + +#include "wmo.h" +#include "Stormlib.h" +#include "mpq.h" + +using namespace std; + + +WMORoot::WMORoot(std::string &filename) : filename(filename) +{ +} +//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + +bool WMORoot::open() +{ + + MPQFile f(filename.c_str()); + if(f.isEof ()) + { + printf("No such file.\n"); + return false; + } + + size_t size; + char fourcc[5]; + bbcorn1[3] = 0; + bbcorn2[3]= 0; + + while (!f.isEof ()) + { + f.read(fourcc,4); + f.read(&size, 4); + + flipcc(fourcc); + fourcc[4] = 0; + + size_t nextpos = f.getPos() + size; + + if (!strcmp(fourcc,"MOHD"))//header + { + + f.read(&nTextures, 4); + f.read(&nGroups, 4); + f.read(&nP, 4); + f.read(&nLights, 4); + f.read(&nModels, 4); + f.read(&nDoodads, 4); + f.read(&nDoodadSets, 4); + f.read(&col, 4); + f.read(&RootID, 4); + f.read(bbcorn1,12); + f.read(bbcorn2,12); + break; + } + /* + else if (!strcmp(fourcc,"MOTX")) + { + + } + else if (!strcmp(fourcc,"MOMT")) + { + + } + else if (!strcmp(fourcc,"MOGN")) + { + + } + else if (!strcmp(fourcc,"MOGI")) + { + + } + else if (!strcmp(fourcc,"MOLT")) + { + + } + else if (!strcmp(fourcc,"MODN")) + { + + } + else if (!strcmp(fourcc,"MODS")) + { + + } + else if (!strcmp(fourcc,"MODD")) + { + + } + else if (!strcmp(fourcc,"MOSB")) + { + + } + else if (!strcmp(fourcc,"MOPV")) + { + + } + else if (!strcmp(fourcc,"MOPT")) + { + + } + else if (!strcmp(fourcc,"MOPR")) + { + + } + else if (!strcmp(fourcc,"MFOG")) + { + + } + */ + f.seek((int)nextpos); + } + f.close (); + return true; +} +//--------------------------------------------------------------------------- + +bool WMORoot::ConvertToVMAPRootWmo(FILE *pOutfile) +{ + //printf("Convert RootWmo...\n"); + + fwrite("VMAP002",1,8,pOutfile); + unsigned int nVectors = 0; + fwrite(&nVectors,sizeof(nVectors),1,pOutfile); // will be filled later + fwrite(&nGroups,4,1,pOutfile); + return true; +} + +//---------------------------------------------------------------------------- +WMORoot::~WMORoot() +{ +} +//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + +WMOGroup::WMOGroup(std::string &filename) : filename(filename) +{ +} +//--------------------------------------------------------------------------- +bool WMOGroup::open() +{ + MPQFile f(filename.c_str()); + if(f.isEof ()) + { + printf("No such file.\n"); + return false; + } + size_t size; + char fourcc[5]; + bbcorn1[3] = 0; + bbcorn2[3] = 0; + while (!f.isEof ()) + { + f.read(fourcc,4); + f.read(&size, 4); + flipcc(fourcc); + if (!strcmp(fourcc,"MOGP"))//Fix sizeoff = Data size. + { + size = 68; + } + fourcc[4] = 0; + size_t nextpos = f.getPos() + size; + LiquEx_size = 0; + liquflags = 0; + + if (!strcmp(fourcc,"MOGP"))//header + { + f.seekRelative(-4); + f.read(&offsize, 4); + f.read(&flag, 4); + f.read(&flag1, 4); + f.read(&Xid, 4); + f.read(bbcorn1, 12); + f.read(bbcorn2, 12); + f.read(&Xid2, 4); + f.read(&Xid3, 4); + f.read(&zero1, 4); + f.read(&Xflag, 4); + f.read(&nTexture,4); + f.read(&GroupID,4); + } + else if (!strcmp(fourcc,"MOPY")) + { + MOPY = new char[size]; + mopy_size = size; + nTriangles = (int)size / 2; + f.read(MOPY, size); + } + else if (!strcmp(fourcc,"MOVI")) + { + MOVI = new uint16[size/2]; + f.read(MOVI, size); + + } + else if (!strcmp(fourcc,"MOVT")) + { + MOVT = new float[size/4]; + f.read(MOVT, size); + nVertices = (int)size / 12; + } + else if (!strcmp(fourcc,"MONR")) + { + } + else if (!strcmp(fourcc,"MOTV")) + { + } + else if (!strcmp(fourcc,"MOBA")) + { + MOBA = new uint16[size/2]; + moba_size = size/2; + f.read(MOBA, size); + } + else if (!strcmp(fourcc,"MLIQ")) + { + liquflags |= 1; + WMOLiquidHeader hlq; + f.read(&hlq, 0x1E); + float ydir = -1.0f; + hlq_xverts = hlq.xverts; + hlq_yverts = hlq.yverts; + int noVer = hlq.xverts * hlq.yverts; + float tilesize = CHUNKSIZE / 8.0f; + LiquEx_size = sizeof(float) * 3 * noVer; + LiquEx = new float[sizeof(float) * 3 * noVer]; + int p = 0; + + for (int j=0; j0) { + if(fwrite(MOVI, sizeof(unsigned short), nIdexes, output) != nIdexes) { printf("Error while writing file indexarray"); exit(0); } + } + + if(fwrite("VERT",4, 1, output) != 1) { printf("Error while writing file nbraches ID"); exit(0); } + wsize = sizeof(int) + sizeof(float) * 3 * nVertices; + if(fwrite(&wsize, sizeof(int), 1, output) != 1) { printf("Error while writing file wsize"); } + if(fwrite(&nVertices, sizeof(int), 1, output) != 1) { printf("Error while writing file nVertices"); exit(0); } + if(nVertices >0) { + if(fwrite(MOVT, sizeof(float)*3, nVertices, output) != nVertices) { printf("Error while writing file vectors"); exit(0); } + } + + if(LiquEx_size != 0) + { + int LIQU_h[] = {0x5551494C,LiquEx_size+8,hlq_xverts,hlq_yverts};// "LIQU" + fwrite(LIQU_h,4,4,output); + fwrite(LiquEx,4,LiquEx_size/4,output); + delete [] LiquEx; + } + + return nTriangles; + } else { + //printf("Convert GroupWmo...\n"); + //-------GRP ------------------------------------- + fwrite(&liquflags,sizeof(uint32),1,output); + char GRP[] = "GRP "; + fwrite(GRP,1,4,output); + int k = 0; + int moba_batch = moba_size/12; + MobaEx = new int[moba_batch*4]; + for(int i=8; i MoviExSort[i+1]) + { + hold = MoviExSort[i]; + MoviExSort[i] = MoviExSort[i+1]; + MoviExSort[i+1] = hold; + } + //double = 65535 + else + if (MoviExSort[i] == MoviExSort[i+1]) + MoviExSort[i+1] = 65535; + } + } + // double delet + uint16 s = 0; + for (int i=0; i < IndexExTr_size*3; i++) + { + if (MoviExSort[i]!=65535) + { + MoviExSort[s] = MoviExSort[i]; + s++; + } + } + MovtExSort = new uint16[s]; + for (int i=0; i < s; i++) + { + MovtExSort[i] = MoviExSort[i]; + } + + for (int i=0; i < IndexExTr_size*3; i++) + { + uint16 b = MoviEx[i]; + for (uint16 x = 0; x < s; x++) + { + if(MoviExSort[x] == b) + { + + MoviEx[i] = x; + break; + } + } + + } + int INDX[] = {0x58444E49,IndexExTr_size*6+4,IndexExTr_size*3}; + fwrite(INDX,4,3,output); + fwrite(MoviEx,2,IndexExTr_size*3,output); + + delete [] MoviEx; + delete [] MoviExSort; + delete [] IndexExTr; + + //----------VERT--------- + //-----MOVT---------- + int d = 0; + MovtEx = new float[s*3]; + for (uint16 i=0; i> 16; + + int realx1 = (int) ((float) pos2.x / 533.333333f); + int realy1 = (int) ((float) pos2.z / 533.333333f); + int realx2 = (int) ((float) pos3.x / 533.333333f); + int realy2 = (int) ((float) pos3.z / 533.333333f); + + if(realx1 < 0) + { + realx1 +=20; realx2+=20; + } + if(realy1 < 0) + { + realy1 +=20; realy2+=20; + } // hack to prevent neg. values + + //-----------add_in _dir_file---------------- + + char tempname[512]; + // const char dirname[] = "buildings\\dir"; + + sprintf(tempname, "buildings\\%s", WmoInstName); + FILE *input; + input = fopen(tempname, "r+b"); + if(!input) + { + return; + } + fseek(input, 8, SEEK_SET); // get the correct no of vertices + int nVertices; + fread(&nVertices, sizeof (int), 1, input); + fclose(input); + if(nVertices == 0) + { + return; + } + + /* FILE *dirfile; + dirfile = fopen(dirname, "ab"); + if(!dirfile) + { + printf("Can't open dirfile!'%s'\n"); + return; + } + */ + float x,z; + x = pos.x; + z = pos.z; + if(x==0 && z == 0) + { x = 533.33333f*32; z = 533.33333f*32; } + fprintf(pDirfile,"%s/%s %f,%f,%f_%f,%f,%f 1.0 %d %d %d,%d %d\n", + MapName, + WmoInstName, + (float) x, (float) pos.y, (float) z, + (float) rot.x, (float) rot.y, (float) rot.z, + nVertices, + realx1, realy1, + realx2, realy2 + ); + + // fclose(dirfile); +} + + + + diff --git a/contrib/vmap_extractor_v2/vmapextract/wmo.h b/contrib/vmap_extractor_v2/vmapextract/wmo.h new file mode 100644 index 00000000000..b8f6439e381 --- /dev/null +++ b/contrib/vmap_extractor_v2/vmapextract/wmo.h @@ -0,0 +1,107 @@ +#ifndef WMO_H +#define WMO_H +#define __STORMLIB_SELF__ +#define TILESIZE (533.33333f) +#define CHUNKSIZE ((TILESIZE) / 16.0f) + +#include "Stormlib.h" +#include +#include "vec3d.h" +#include +#include "mpq.h" + + +class WMOInstance; +class WMOManager; + +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned int uint32; + + +class WMORoot +{ +public: + int nTextures, nGroups, nP, nLights, nModels, nDoodads, nDoodadSets, RootID; + unsigned int col; + int bbcorn1[3]; + int bbcorn2[3]; + + WMORoot(std::string &filename); + ~WMORoot(); + + bool open(); + bool ConvertToVMAPRootWmo(FILE *output); +private: + std::string filename; + char outfilename; + +}; + +class WMOGroup +{ +public: + + int offsize,flag,flag1,Xid,Xid2,Xid3,zero1,Xflag,nTexture,GroupID; + int mopy_size,moba_size,hlq_xverts,hlq_yverts; + int MopyEx_size,IndexExTr_size,LiquEx_size; + unsigned int nVertices; // number when loaded + int nTriangles; // number when loaded + int bbcorn1[3]; + int bbcorn2[3]; + int * IndexExTr; + char* MOPY; + char* MopyEx; + uint16* MOVI; + uint16* MoviEx; + uint16* MoviExSort; + float* MOVT; + float* MovtEx; + uint16* MovtExSort; + float* MONR; + float* MonrEx; + uint16* MOBA; + int* MobaEx; + float* LiquEx; + uint32 liquflags; + + WMOGroup(std::string &filename); + ~WMOGroup(); + + bool open(); + int ConvertToVMAPGroupWmo(FILE *output, bool pPreciseVectorData); + +private: + std::string filename; + char outfilename; + +}; + +struct WMOLiquidHeader +{ + int xverts, yverts, xtiles, ytiles; + float pos_x; + float pos_y; + float pos_z; + short type; +}; + +class WMOInstance +{ + static std::set ids; +public: + string MapName; + int currx; + int curry; + WMOGroup *wmo; + Vec3D pos; + Vec3D pos2, pos3, rot; + int indx,id, d2, d3; + int doodadset; + + WMOInstance(MPQFile &f,const char* WmoInstName,const char*MapName, FILE *pDirfile); + + static void reset(); +}; + +#endif \ No newline at end of file diff --git a/dep/Makefile.am b/dep/Makefile.am new file mode 100644 index 00000000000..f82b7760833 --- /dev/null +++ b/dep/Makefile.am @@ -0,0 +1,23 @@ +# Copyright (C) 2005-2008 MaNGOS +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## Process this file with automake to produce Makefile.in + +## Sub-directories to parse +SUBDIRS = include lib src + +## Additional files to include when running 'make dist' +# Nothing yet. diff --git a/dep/include/Makefile.am b/dep/include/Makefile.am new file mode 100644 index 00000000000..f3fa8689b08 --- /dev/null +++ b/dep/include/Makefile.am @@ -0,0 +1,261 @@ +# Copyright (C) 2005-2008 MaNGOS +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## Process this file with automake to produce Makefile.in + +## Sub-directories to parse + +## Additional files to include when running 'make dist' +# G3DLite header files +EXTRA_DIST = \ + g3dlite/G3D/AABox.h \ + g3dlite/G3D/Array.h \ + g3dlite/G3D/Box.h \ + g3dlite/G3D/CollisionDetection.h \ + g3dlite/G3D/CoordinateFrame.h \ + g3dlite/G3D/Crypto.h \ + g3dlite/G3D/debug.h \ + g3dlite/G3D/format.h \ + g3dlite/G3D/g3dmath.h \ + g3dlite/G3D/g3dmath.inl \ + g3dlite/G3D/GCamera.h \ + g3dlite/G3D/Line.h \ + g3dlite/G3D/Matrix3.h \ + g3dlite/G3D/Plane.h \ + g3dlite/G3D/platform.h \ + g3dlite/G3D/Quat.h \ + g3dlite/G3D/Quat.inl \ + g3dlite/G3D/Ray.h \ + g3dlite/G3D/RegistryUtil.h \ + g3dlite/G3D/Sphere.h \ + g3dlite/G3D/stringutils.h \ + g3dlite/G3D/System.h \ + g3dlite/G3D/Table.h \ + g3dlite/G3D/Triangle.h \ + g3dlite/G3D/Vector2.h \ + g3dlite/G3D/Vector2.inl \ + g3dlite/G3D/Vector2int16.h \ + g3dlite/G3D/Vector3.h \ + g3dlite/G3D/Vector3.inl \ + g3dlite/G3D/Vector3int16.h \ + g3dlite/G3D/Vector4.h \ + g3dlite/G3D/Vector4.inl + +# MySQL header files for Win32 builds +EXTRA_DIST += \ + mysql/config-netware.h \ + mysql/config-os2.h \ + mysql/config-win.h \ + mysql/errmsg.h \ + mysql/libmysqld.def \ + mysql/Libmysql.def \ + mysql/m_ctype.h \ + mysql/m_string.h \ + mysql/my_alloc.h \ + mysql/my_dbug.h \ + mysql/my_getopt.h \ + mysql/my_global.h \ + mysql/my_list.h \ + mysql/my_pthread.h \ + mysql/mysql_com.h \ + mysql/mysqld_error.h \ + mysql/mysql_embed.h \ + mysql/mysql.h \ + mysql/mysql_time.h \ + mysql/mysql_version.h \ + mysql/my_sys.h \ + mysql/raid.h \ + mysql/typelib.h + +# OpenSSL header files for Win32 builds +EXTRA_DIST += \ + openssl/aes.h \ + openssl/asn1.h \ + openssl/asn1_mac.h \ + openssl/asn1t.h \ + openssl/bio.h \ + openssl/blowfish.h \ + openssl/bn.h \ + openssl/buffer.h \ + openssl/cast.h \ + openssl/comp.h \ + openssl/conf_api.h \ + openssl/conf.h \ + openssl/crypto.h \ + openssl/des.h \ + openssl/des_old.h \ + openssl/dh.h \ + openssl/dsa.h \ + openssl/dso.h \ + openssl/dtls1.h \ + openssl/ebcdic.h \ + openssl/ecdh.h \ + openssl/ecdsa.h \ + openssl/ec.h \ + openssl/engine.h \ + openssl/e_os2.h \ + openssl/err.h \ + openssl/evp.h \ + openssl/hmac.h \ + openssl/idea.h \ + openssl/krb5_asn.h \ + openssl/kssl.h \ + openssl/lhash.h \ + openssl/md2.h \ + openssl/md4.h \ + openssl/md5.h \ + openssl/mdc2.h \ + openssl/objects.h \ + openssl/obj_mac.h \ + openssl/ocsp.h \ + openssl/opensslconf.h \ + openssl/opensslv.h \ + openssl/ossl_typ.h \ + openssl/pem2.h \ + openssl/pem.h \ + openssl/pkcs12.h \ + openssl/pkcs7.h \ + openssl/pq_compat.h \ + openssl/pqueue.h \ + openssl/rand.h \ + openssl/rc2.h \ + openssl/rc4.h \ + openssl/rc5.h \ + openssl/ripemd.h \ + openssl/rsa.h \ + openssl/safestack.h \ + openssl/sha.h \ + openssl/ssl23.h \ + openssl/ssl2.h \ + openssl/ssl3.h \ + openssl/ssl.h \ + openssl/stack.h \ + openssl/store.h \ + openssl/symhacks.h \ + openssl/tls1.h \ + openssl/tmdiff.h \ + openssl/txt_db.h \ + openssl/ui_compat.h \ + openssl/ui.h \ + openssl/x509.h \ + openssl/x509v3.h \ + openssl/x509_vfy.h + +# PostgreSQL header files for Win32 builds +EXTRA_DIST += \ + postgre/libpq-fe.h \ + postgre/pg_type.h \ + postgre/postgres_ext.h + +# SQLite header files for Win32 builds +EXTRA_DIST += \ + sqlite/sqlite.h + +# Sockets header files for Win32 builds +EXTRA_DIST += \ + sockets\Base64.h \ + sockets\CircularBuffer.h \ + sockets\IFile.h \ + sockets\Ipv4Address.h \ + sockets\Ipv6Address.h \ + sockets\ISocketHandler.h \ + sockets\ListenSocket.h \ + sockets\Mutex.h \ + sockets\Parse.h \ + sockets\RandomNumber.h \ + sockets\ResolvServer.h \ + sockets\ResolvSocket.h \ + sockets\SctpSocket.h \ + sockets\Socket.h \ + sockets\socket_include.h \ + sockets\SocketAddress.h \ + sockets\SocketHandler.h \ + sockets\sockets-config.h \ + sockets\StdLog.h \ + sockets\StdoutLog.h \ + sockets\TcpSocket.h \ + sockets\Thread.h \ + sockets\UdpSocket.h \ + sockets\Uid.h \ + sockets\Utility.h + +# VLD header files for Win32 builds +EXTRA_DIST += \ + vld/vld.h + +# Zlib header files for Win32 builds +EXTRA_DIST += \ + zlib/zconf.h \ + zlib/zlib.h + +# ZThread header files for Win32 builds +EXTRA_DIST += \ + zthread/AtomicCount.h \ + zthread/Barrier.h \ + zthread/BiasedReadWriteLock.h \ + zthread/BlockingQueue.h \ + zthread/BoundedQueue.h \ + zthread/Cancelable.h \ + zthread/ClassLockable.h \ + zthread/ConcurrentExecutor.h \ + zthread/Condition.h \ + zthread/Config.h \ + zthread/CountedPtr.h \ + zthread/CountingSemaphore.h \ + zthread/Exceptions.h \ + zthread/Executor.h \ + zthread/FairReadWriteLock.h \ + zthread/FastMutex.h \ + zthread/FastRecursiveMutex.h \ + zthread/Guard.h \ + zthread/GuardedClass.h \ + zthread/Lockable.h \ + zthread/LockedQueue.h \ + zthread/MonitoredQueue.h \ + zthread/Mutex.h \ + zthread/NonCopyable.h \ + zthread/PoolExecutor.h \ + zthread/Priority.h \ + zthread/PriorityCondition.h \ + zthread/PriorityInheritanceMutex.h \ + zthread/PriorityMutex.h \ + zthread/PrioritySemaphore.h \ + zthread/Queue.h \ + zthread/ReadWriteLock.h \ + zthread/RecursiveMutex.h \ + zthread/Runnable.h \ + zthread/Semaphore.h \ + zthread/Singleton.h \ + zthread/SynchronousExecutor.h \ + zthread/Task.h \ + zthread/Thread.h \ + zthread/ThreadLocal.h \ + zthread/ThreadLocalImpl.h \ + zthread/ThreadedExecutor.h \ + zthread/Time.h \ + zthread/Waitable.h \ + zthread/ZThread.h + +# Mersenne Twister random number generator header files +EXTRA_DIST += \ + mersennetwister/MersenneTwister.h + +# UTF8-CPP header files +EXTRA_DIST += \ + utf8cpp/utf8.h \ + utf8cpp/utf8/checked.h \ + utf8cpp/utf8/core.h \ + utf8cpp/utf8/unchecked.h diff --git a/dep/include/g3dlite/G3D/AABox.h b/dep/include/g3dlite/G3D/AABox.h new file mode 100644 index 00000000000..b5e862a7721 --- /dev/null +++ b/dep/include/g3dlite/G3D/AABox.h @@ -0,0 +1,255 @@ +/** + @file AABox.h + + Axis-aligned box class + + @maintainer Morgan McGuire, matrix@graphics3d.com + + @created 2004-01-10 + @edited 2006-02-10 + + Copyright 2000-2006, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_AABOX_H +#define G3D_AABOX_H + +#include "G3D/platform.h" +#include "G3D/Vector3.h" +#include "G3D/debug.h" +#include "G3D/Array.h" + +namespace G3D { + +/** + An axis-aligned box. + */ +class AABox { +private: + + /** Optional argument placeholder */ + static int dummy; + + Vector3 lo; + Vector3 hi; + +public: + + /** Does not initialize the fields */ + inline AABox() {} + + /** + Constructs a zero-area AABox at v. + */ + inline AABox(const Vector3& v) { + lo = hi = v; + } + + /** Assumes that low is less than or equal to high along each dimension. + To have this automatically enforced, use + AABox(low.min(high), low.max(high)); + */ + inline AABox(const Vector3& low, const Vector3& high) { + set(low, high); + } + + /** Assumes that low is less than or equal to high along each dimension. + */ + inline void set(const Vector3& low, const Vector3& high) { + debugAssert( + (low.x <= high.x) && + (low.y <= high.y) && + (low.z <= high.z)); + lo = low; + hi = high; + } + + + inline const Vector3& low() const { + return lo; + } + + inline const Vector3& high() const { + return hi; + } + + /** + The largest possible finite box. + */ + static inline const AABox& maxFinite() { + static const AABox b = AABox(Vector3::minFinite(), Vector3::maxFinite()); + return b; + } + + static inline const AABox& inf() { + static const AABox b = AABox(-Vector3::inf(), Vector3::inf()); + return b; + } + + static inline const AABox& zero() { + static const AABox b = AABox(Vector3::zero(), Vector3::zero()); + return b; + } + + /** + Returns the centroid of the box. + */ + inline Vector3 center() const { + return (lo + hi) * 0.5; + } + + /** + Distance from corner(0) to the next corner along axis a. + */ + inline double extent(int a) const { + debugAssert(a < 3); + return hi[a] - lo[a]; + } + + inline Vector3 extent() const { + return hi - lo; + } + + /** + @deprecated Use culledBy(Array&) + */ + bool culledBy( + const class Plane* plane, + int numPlanes, + int32& cullingPlaneIndex, + const uint32 testMask, + uint32& childMask) const; + + /** + @deprecated Use culledBy(Array&) + */ + bool culledBy( + const class Plane* plane, + int numPlanes, + int32& cullingPlaneIndex = dummy, + const uint32 testMask = 0xFFFFFF) const; + + /** + Splits the box into two AABoxes along the specified axis. low contains + the part that was closer to negative infinity along axis, high contains + the other part. Either may have zero volume. + */ + void split(const Vector3::Axis& axis, float location, AABox& low, AABox& high) const; + + /** + Conservative culling test for up to 32 planes. + Returns true if there exists a plane[p] for + which the entire object is in the negative half space + (opposite the plane normal). + + testMask and childMask + are used for optimizing bounding volume hierarchies. + The version of this method that produces childMask + is slower than the version without; it should only + be used for parent nodes. + + @param cullingPlaneIndex The index of the first plane for which + the entire object is in the negative half-space. The function + exits early when one plane is found. -1 when the function + returns false (i.e. when no plane culls the whole object). + + @param testMask If bit p is 0, the + bounding volume automatically passes the culling test for + plane[p] (i.e. it is known that the volume + is entirely within the positive half space). The function + must return false if testMask is 0 and test all planes + when testMask is -1 (0xFFFFFFFF). + + @param childMask Test mask for the children of this volume. + + */ + bool culledBy( + const Array& plane, + int32& cullingPlaneIndex, + const uint32 testMask, + uint32& childMask) const; + + /** + Conservative culling test that does not produce a mask for children. + */ + bool culledBy( + const Array& plane, + int32& cullingPlaneIndex = dummy, + const uint32 testMask = -1) const; + + inline bool contains( + const Vector3& point) const { + return + (point.x >= lo.x) && + (point.y >= lo.y) && + (point.z >= lo.z) && + (point.x <= hi.x) && + (point.y <= hi.y) && + (point.z <= hi.z); + } + + /** @deprecated */ + inline float surfaceArea() const { + Vector3 diag = hi - lo; + return 2.0f * (diag.x * diag.y + diag.y * diag.z + diag.x * diag.z); + } + + inline float area() const { + return surfaceArea(); + } + + inline float volume() const { + Vector3 diag = hi - lo; + return diag.x * diag.y * diag.z; + } + + Vector3 randomInteriorPoint() const; + + Vector3 randomSurfacePoint() const; + + /** @deprecated use Box constructor */ + class Box toBox() const; + + /** Returns true if there is any overlap */ + bool intersects(const AABox& other) const; + + /** Returns true if there is any overlap. + @cite Jim Arvo's algorithm from Graphics Gems II*/ + bool intersects(const class Sphere& other) const; + + /** Return the intersection of the two boxes */ + AABox intersect(const AABox& other) const { + Vector3 H = hi.min(other.hi); + Vector3 L = lo.max(other.lo).min(H); + return AABox(L, H); + } + + inline unsigned int hashCode() const { + return lo.hashCode() + hi.hashCode(); + } + + inline bool operator==(const AABox& b) const { + return (lo == b.lo) && (hi == b.hi); + } + + inline bool operator!=(const AABox& b) const { + return !((lo == b.lo) && (hi == b.hi)); + } + + void getBounds(AABox& out) const { + out = *this; + } +}; + +} + +/** + Hashing function for use with Table. + */ +inline unsigned int hashCode(const G3D::AABox& b) { + return b.hashCode(); +} + + +#endif diff --git a/dep/include/g3dlite/G3D/Array.h b/dep/include/g3dlite/G3D/Array.h new file mode 100644 index 00000000000..290563b6719 --- /dev/null +++ b/dep/include/g3dlite/G3D/Array.h @@ -0,0 +1,1156 @@ +/** + @file Array.h + + @maintainer Morgan McGuire, graphics3d.com + @cite Portions written by Aaron Orenstein, a@orenstein.name + + @created 2001-03-11 + @edited 2007-05-12 + + Copyright 2000-2007, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_ARRAY_H +#define G3D_ARRAY_H + +#include "G3D/platform.h" +#include "G3D/debug.h" +#include "G3D/System.h" +#ifdef G3D_DEBUG +// For formatting error messages +# include "G3D/format.h" +#endif +#include +#include + +#ifdef G3D_WIN32 +# include + +# pragma warning (push) + // debug information too long +# pragma warning( disable : 4312) +# pragma warning( disable : 4786) +#endif + + +namespace G3D { + +/** + Constant for passing to Array::resize + */ +const bool DONT_SHRINK_UNDERLYING_ARRAY = false; + +/** Constant for Array::sort */ +const int SORT_INCREASING = 1; +/** Constant for Array::sort */ +const int SORT_DECREASING = -1; + +/** + Dynamic 1D array. + + Objects must have a default constructor (constructor that + takes no arguments) in order to be used with this template. + You will get the error "no appropriate default constructor found" + if they do not. + + Do not use with objects that overload placement operator new, + since the speed of Array is partly due to pooled allocation. + + If SSE is defined Arrays allocate the first element aligned to + 16 bytes. + + + Array is highly optimized compared to std::vector. + Array operations are less expensive than on std::vector and for large + amounts of data, Array consumes only 1.5x the total size of the + data, while std::vector consumes 2.0x. The default + array takes up zero heap space. The first resize (or append) + operation grows it to a reasonable internal size so it is efficient + to append to small arrays. Memory is allocated using + System::alignedMalloc, which produces pointers aligned to 16-byte + boundaries for use with SSE instructions and uses pooled storage for + fast allocation. When Array needs to copy + data internally on a resize operation it correctly invokes copy + constructors of the elements (the MSVC6 implementation of + std::vector uses realloc, which can create memory leaks for classes + containing references and pointers). Array provides a guaranteed + safe way to access the underlying data as a flat C array -- + Array::getCArray. Although (T*)std::vector::begin() can be used for + this purpose, it is not guaranteed to succeed on all platforms. + + To serialize an array, see G3D::serialize. + + Do not subclass an Array. + */ +template +class Array { +private: + /** 0...num-1 are initialized elements, num...numAllocated-1 are not */ + T* data; + + int num; + int numAllocated; + + void init(int n, int a) { + debugAssert(n <= a); + debugAssert(n >= 0); + this->num = 0; + this->numAllocated = 0; + data = NULL; + if (a > 0) { + resize(n); + } else { + data = NULL; + } + } + + void _copy(const Array &other) { + init(other.num, other.num); + for (int i = 0; i < num; i++) { + data[i] = other.data[i]; + } + } + + /** + Returns true iff address points to an element of this array. + Used by append. + */ + inline bool inArray(const T* address) { + return (address >= data) && (address < data + num); + } + + + /** Only compiled if you use the sort procedure. */ + static bool __cdecl compareGT(const T& a, const T& b) { + return a > b; + } + + + /** + Allocates a new array of size numAllocated (not a parameter to the method) + and then copies at most oldNum elements from the old array to it. Destructors are + called for oldNum elements of the old array. + */ + void realloc(int oldNum) { + T* oldData = data; + + // The allocation is separate from the constructor invocation because we don't want + // to pay for the cost of constructors until the newly allocated + // elements are actually revealed to the application. They + // will be constructed in the resize() method. + + data = (T*)System::alignedMalloc(sizeof(T) * numAllocated, 16); + + // Call the copy constructors + {const int N = iMin(oldNum, numAllocated); + const T* end = data + N; + T* oldPtr = oldData; + for (T* ptr = data; ptr < end; ++ptr, ++oldPtr) { + + // Use placement new to invoke the constructor at the location + // that we determined. Use the copy constructor to make the assignment. + const T* constructed = new (ptr) T(*oldPtr); + + (void)constructed; + debugAssertM(constructed == ptr, + "new returned a different address than the one provided by Array."); + }} + + // Call destructors on the old array (if there is no destructor, this will compile away) + {const T* end = oldData + oldNum; + for (T* ptr = oldData; ptr < end; ++ptr) { + ptr->~T(); + }} + + + System::alignedFree(oldData); + } + +public: + + /** + C++ STL style iterator variable. Call begin() to get + the first iterator, pre-increment (++i) the iterator to get to + the next value. Use dereference (*i) to access the element. + */ + typedef T* Iterator; + typedef const T* ConstIterator; + + /** + C++ STL style iterator method. Returns the first iterator element. + Do not change the size of the array while iterating. + */ + Iterator begin() { + return data; + } + + ConstIterator begin() const { + return data; + } + /** + C++ STL style iterator method. Returns one after the last iterator + element. + */ + ConstIterator end() const { + return data + num; + } + + Iterator end() { + return data + num; + } + + /** + The array returned is only valid until the next append() or resize call, or + the Array is deallocated. + */ + T* getCArray() { + return data; + } + + /** + The array returned is only valid until the next append() or resize call, or + the Array is deallocated. + */ + const T* getCArray() const { + return data; + } + + /** Creates a zero length array (no heap allocation occurs until resize). */ + Array() { + init(0, 0); + } + + /** + Creates an array of size. + */ + Array(int size) { + init(size, size); + } + + /** + Copy constructor + */ + Array(const Array& other) { + _copy(other); + } + + /** + Destructor does not delete() the objects if T is a pointer type + (e.g. T = int*) instead, it deletes the pointers themselves and + leaves the objects. Call deleteAll if you want to dealocate + the objects referenced. Do not call deleteAll if T is not a pointer + type (e.g. do call Array::deleteAll, do not call Array::deleteAll). + */ + ~Array() { + // Invoke the destructors on the elements + for (int i = 0; i < num; i++) { + (data + i)->~T(); + } + + System::alignedFree(data); + // Set to 0 in case this Array is global and gets referenced during app exit + data = NULL; + num = 0; + numAllocated = 0; + } + + + /** + Removes all elements. Use resize(0, false) or fastClear if you want to + remove all elements without deallocating the underlying array + so that future append() calls will be faster. + */ + void clear() { + resize(0); + } + + /** resize(0, false) */ + void fastClear() { + resize(0, false); + } + + /** + Assignment operator. + */ + Array& operator=(const Array& other) { + resize(other.num); + for (int i = 0; i < num; ++i) { + data[i] = other[i]; + } + return *this; + } + + Array& operator=(const std::vector& other) { + resize((int)other.size()); + for (int i = 0; i < num; ++i) { + data[i] = other[i]; + } + return *this; + } + + /** + Number of elements in the array. + */ + inline int size() const { + return num; + } + + /** + Number of elements in the array. (Same as size; this is just + here for convenience). + */ + inline int length() const { + return size(); + } + + /** + Swaps element index with the last element in the array then + shrinks the array by one. + */ + void fastRemove(int index) { + debugAssert(index >= 0); + debugAssert(index < num); + data[index] = data[num - 1]; + resize(size() - 1); + } + + /** + Resizes, calling the default constructor for + newly created objects and shrinking the underlying + array as needed (and calling destructors as needed). + */ + void resize(int n) { + resize(n, true); + } + + /** Resizes without shrinking the underlying array */ + void fastResize(int n) { + resize(n, false); + } + + + /** + Inserts at the specified index and shifts all other elements up by one. + */ + void insert(int n, const T& value) { + // Add space for the extra element + resize(num + 1, false); + + for (int i = num - 1; i > n; --i) { + data[i] = data[i - 1]; + } + data[n] = value; + } + + /** @param shrinkIfNecessary if false, memory will never be + reallocated when the array shrinks. This makes resizing much + faster but can waste memory. */ + void resize(int n, bool shrinkIfNecessary) { + int oldNum = num; + num = n; + + // Call the destructors on newly hidden elements if there are any + for (int i = num; i < oldNum; ++i) { + (data + i)->~T(); + } + + // Once allocated, always maintain 10 elements or 32 bytes, whichever is higher. + static const int minSize = iMax(10, 32 / sizeof(T)); + + if (num > numAllocated) { + // Grow the underlying array + + if (numAllocated == 0) { + // First allocation; grow to exactly the size requested to avoid wasting space. + numAllocated = n; + debugAssert(oldNum == 0); + realloc(oldNum); + } else { + + if (num < minSize) { + // Grow to at least the minimum size + numAllocated = minSize; + + } else { + + // Increase the underlying size of the array. Grow aggressively + // up to 64k, less aggressively up to 400k, and then grow relatively + // slowly (1.5x per resize) to avoid excessive space consumption. + // + // These numbers are tweaked according to performance tests. + + float growFactor = 3.0; + + size_t oldSizeBytes = numAllocated * sizeof(T); + if (oldSizeBytes > 400000) { + // Avoid bloat + growFactor = 1.5; + } else if (oldSizeBytes > 64000) { + // This is what std:: uses at all times + growFactor = 2.0; + } + + numAllocated = (num - numAllocated) + (int)(numAllocated * growFactor); + + if (numAllocated < minSize) { + numAllocated = minSize; + } + } + + realloc(oldNum); + } + + } else if ((num <= numAllocated / 3) && shrinkIfNecessary && (num > minSize)) { + // Shrink the underlying array + + // Only copy over old elements that still remain after resizing + // (destructors were called for others if we're shrinking) + realloc(iMin(num, oldNum)); + + } + + // Call the constructors on newly revealed elements. + // Do not use parens because we don't want the intializer + // invoked for POD types. + for (int i = oldNum; i < num; ++i) { + new (data + i) T; + } + } + + /** + Add an element to the end of the array. Will not shrink the underlying array + under any circumstances. It is safe to append an element that is already + in the array. + */ + inline void append(const T& value) { + + if (num < numAllocated) { + // This is a simple situation; just stick it in the next free slot using + // the copy constructor. + new (data + num) T(value); + ++num; + } else if (inArray(&value)) { + // The value was in the original array; resizing + // is dangerous because it may move the value + // we have a reference to. + T tmp = value; + append(tmp); + } else { + // Here we run the empty initializer where we don't have to, but + // this simplifies the computation. + resize(num + 1, DONT_SHRINK_UNDERLYING_ARRAY); + data[num - 1] = value; + } + } + + + inline void append(const T& v1, const T& v2) { + if (inArray(&v1) || inArray(&v2)) { + T t1 = v1; + T t2 = v2; + append(t1, t2); + } else if (num + 1 < numAllocated) { + // This is a simple situation; just stick it in the next free slot using + // the copy constructor. + new (data + num) T(v1); + new (data + num + 1) T(v2); + num += 2; + } else { + resize(num + 2, DONT_SHRINK_UNDERLYING_ARRAY); + data[num - 2] = v1; + data[num - 1] = v2; + } + } + + + inline void append(const T& v1, const T& v2, const T& v3) { + if (inArray(&v1) || inArray(&v2) || inArray(&v3)) { + T t1 = v1; + T t2 = v2; + T t3 = v3; + append(t1, t2, t3); + } else if (num + 2 < numAllocated) { + // This is a simple situation; just stick it in the next free slot using + // the copy constructor. + new (data + num) T(v1); + new (data + num + 1) T(v2); + new (data + num + 2) T(v3); + num += 3; + } else { + resize(num + 3, DONT_SHRINK_UNDERLYING_ARRAY); + data[num - 3] = v1; + data[num - 2] = v2; + data[num - 1] = v3; + } + } + + + inline void append(const T& v1, const T& v2, const T& v3, const T& v4) { + if (inArray(&v1) || inArray(&v2) || inArray(&v3) || inArray(&v4)) { + T t1 = v1; + T t2 = v2; + T t3 = v3; + T t4 = v4; + append(t1, t2, t3, t4); + } else if (num + 3 < numAllocated) { + // This is a simple situation; just stick it in the next free slot using + // the copy constructor. + new (data + num) T(v1); + new (data + num + 1) T(v2); + new (data + num + 2) T(v3); + new (data + num + 3) T(v4); + num += 4; + } else { + resize(num + 4, DONT_SHRINK_UNDERLYING_ARRAY); + data[num - 4] = v1; + data[num - 3] = v2; + data[num - 2] = v3; + data[num - 1] = v4; + } + } + + /** + Returns true if the given element is in the array. + */ + bool contains(const T& e) const { + for (int i = 0; i < size(); ++i) { + if ((*this)[i] == e) { + return true; + } + } + + return false; + } + + /** + Append the elements of array. Cannot be called with this array + as an argument. + */ + void append(const Array& array) { + debugAssert(this != &array); + int oldNum = num; + int arrayLength = array.length(); + + resize(num + arrayLength, false); + + for (int i = 0; i < arrayLength; i++) { + data[oldNum + i] = array.data[i]; + } + } + + /** + Pushes a new element onto the end and returns its address. + This is the same as A.resize(A.size() + 1, false); A.last() + */ + inline T& next() { + resize(num + 1, false); + return last(); + } + + /** + Pushes an element onto the end (appends) + */ + inline void push(const T& value) { + append(value); + } + + inline void push(const Array& array) { + append(array); + } + + /** Alias to provide std::vector compatibility */ + inline void push_back(const T& v) { + push(v); + } + + /** "The member function removes the last element of the controlled sequence, which must be non-empty." + For compatibility with std::vector. */ + inline void pop_back() { + pop(); + } + + /** + "The member function returns the storage currently allocated to hold the controlled + sequence, a value at least as large as size()" + For compatibility with std::vector. + */ + int capacity() const { + return numAllocated; + } + + /** + "The member function returns a reference to the first element of the controlled sequence, + which must be non-empty." + For compatibility with std::vector. + */ + T& front() { + return (*this)[0]; + } + + /** + "The member function returns a reference to the first element of the controlled sequence, + which must be non-empty." + For compatibility with std::vector. + */ + const T& front() const { + return (*this)[0]; + } + + /** + Removes the last element and returns it. By default, shrinks the underlying array. + */ + inline T pop(bool shrinkUnderlyingArrayIfNecessary = true) { + debugAssert(num > 0); + T temp = data[num - 1]; + resize(num - 1, shrinkUnderlyingArrayIfNecessary); + return temp; + } + + /** Pops the last element and discards it without returning anything. Faster than pop. + By default, does not shrink the underlying array.*/ + inline void popDiscard(bool shrinkUnderlyingArrayIfNecessary = false) { + debugAssert(num > 0); + resize(num - 1, shrinkUnderlyingArrayIfNecessary); + } + + + /** + "The member function swaps the controlled sequences between *this and str." + Note that this is slower than the optimal std implementation. + + For compatibility with std::vector. + */ + void swap(Array& str) { + Array temp = str; + str = *this; + *this = temp; + } + + + /** + Performs bounds checks in debug mode + */ + inline T& operator[](int n) { + debugAssertM((n >= 0) && (n < num), format("Array index out of bounds. n = %d, size() = %d", n, num)); + debugAssert(data!=NULL); + return data[n]; + } + + inline T& operator[](unsigned int n) { + debugAssertM(((int)n < num), format("Array index out of bounds. n = %d, size() = %d", n, num)); + return data[n]; + } + + /** + Performs bounds checks in debug mode + */ + inline const T& operator[](int n) const { + debugAssert((n >= 0) && (n < num)); + debugAssert(data!=NULL); + return data[n]; + } + + inline const T& operator[](unsigned int n) const { + debugAssert((n < (unsigned int)num)); + debugAssert(data!=NULL); + return data[n]; + } + + inline T& randomElement() { + debugAssert(num > 0); + debugAssert(data!=NULL); + return data[iRandom(0, num - 1)]; + } + + inline const T& randomElement() const { + debugAssert(num > 0); + debugAssert(data!=NULL); + return data[iRandom(0, num - 1)]; + } + + /** + Returns the last element, performing a check in + debug mode that there is at least one element. + */ + inline const T& last() const { + debugAssert(num > 0); + debugAssert(data!=NULL); + return data[num - 1]; + } + + /** Returns element lastIndex() */ + inline T& last() { + debugAssert(num > 0); + debugAssert(data!=NULL); + return data[num - 1]; + } + + /** Returns size() - 1 */ + inline int lastIndex() const { + debugAssertM(num > 0, "Array is empty"); + return num - 1; + } + + inline int firstIndex() const { + debugAssertM(num > 0, "Array is empty"); + return 0; + } + + /** Returns element firstIndex(), performing a check in debug mode to ensure that there is at least one */ + inline T& first() { + debugAssertM(num > 0, "Array is empty"); + return data[0]; + } + + inline const T& first() const { + debugAssertM(num > 0, "Array is empty"); + return data[0]; + } + + /** Returns iFloor(size() / 2), throws an assertion in debug mode if the array is empty */ + inline int middleIndex() const { + debugAssertM(num > 0, "Array is empty"); + return num >> 1; + } + + /** Returns element middleIndex() */ + inline const T& middle() const { + debugAssertM(num > 0, "Array is empty"); + return data[num >> 1]; + } + + /** Returns element middleIndex() */ + inline T& middle() { + debugAssertM(num > 0, "Array is empty"); + return data[num >> 1]; + } + + /** + Calls delete on all objects[0...size-1] + and sets the size to zero. + */ + void deleteAll() { + for (int i = 0; i < num; i++) { + delete data[i]; + } + resize(0); + } + + /** + Returns the index of (the first occurance of) an index or -1 if + not found. + */ + int findIndex(const T& value) const { + for (int i = 0; i < num; ++i) { + if (data[i] == value) { + return i; + } + } + return -1; + } + + /** + Finds an element and returns the iterator to it. If the element + isn't found then returns end(). + */ + Iterator find(const T& value) { + for (int i = 0; i < num; ++i) { + if (data[i] == value) { + return data + i; + } + } + return end(); + } + + ConstIterator find(const T& value) const { + for (int i = 0; i < num; ++i) { + if (data[i] == value) { + return data + i; + } + } + return end(); + } + + /** + Removes count elements from the array + referenced either by index or Iterator. + */ + void remove(Iterator element, int count = 1) { + debugAssert((element >= begin()) && (element < end())); + debugAssert((count > 0) && (element + count) <= end()); + Iterator last = end() - count; + + while(element < last) { + element[0] = element[count]; + ++element; + } + + resize(num - count); + } + + void remove(int index, int count = 1) { + debugAssert((index >= 0) && (index < num)); + debugAssert((count > 0) && (index + count <= num)); + + remove(begin() + index, count); + } + + /** + Reverse the elements of the array in place. + */ + void reverse() { + T temp; + + int n2 = num / 2; + for (int i = 0; i < n2; ++i) { + temp = data[num - 1 - i]; + data[num - 1 - i] = data[i]; + data[i] = temp; + } + } + + /** + Sort using a specific less-than function, e.g.: + +
+    bool __cdecl myLT(const MyClass& elem1, const MyClass& elem2) {
+        return elem1.x < elem2.x;
+    }
+    
+ + Note that for pointer arrays, the const must come + after the class name, e.g., Array uses: + +
+    bool __cdecl myLT(MyClass*const& elem1, MyClass*const& elem2) {
+        return elem1->x < elem2->x;
+    }
+    
+ */ + void sort(bool (__cdecl *lessThan)(const T& elem1, const T& elem2)) { + std::sort(data, data + num, lessThan); + } + + + /** + Sorts the array in increasing order using the > or < operator. To + invoke this method on Array, T must override those operator. + You can overide these operators as follows: + + bool T::operator>(const T& other) const { + return ...; + } + bool T::operator<(const T& other) const { + return ...; + } + + */ + void sort(int direction = SORT_INCREASING) { + if (direction == SORT_INCREASING) { + std::sort(data, data + num); + } else { + std::sort(data, data + num, compareGT); + } + } + + /** + Sorts elements beginIndex through and including endIndex. + */ + void sortSubArray(int beginIndex, int endIndex, int direction = SORT_INCREASING) { + if (direction == SORT_INCREASING) { + std::sort(data + beginIndex, data + endIndex + 1); + } else { + std::sort(data + beginIndex, data + endIndex + 1, compareGT); + } + } + + void sortSubArray(int beginIndex, int endIndex, bool (__cdecl *lessThan)(const T& elem1, const T& elem2)) { + std::sort(data + beginIndex, data + endIndex + 1, lessThan); + } + + /** + The StrictWeakOrdering can be either a class that overloads the function call operator() or + a function pointer of the form bool (__cdecl *lessThan)(const T& elem1, const T& elem2) + */ + template + void sortSubArray(int beginIndex, int endIndex, StrictWeakOrdering& lessThan) { + std::sort(data + beginIndex, data + endIndex + 1, lessThan); + } + + /** Uses < and == to evaluate operator(); this is the default comparator for Array::partition. */ + class DefaultComparator { + public: + inline int operator()(const T& A, const T& B) const { + if (A < B) { + return 1; + } else if (A == B) { + return 0; + } else { + return -1; + } + } + }; + + /** The output arrays are resized with fastClear() so that if they are already of the same size + as this array no memory is allocated during partitioning. + + @param comparator A function, or class instance with an overloaded operator() that compares + two elements of type T and returns 0 if they are equal, -1 if the second is smaller, + and 1 if the first is smaller (i.e., following the conventions of std::string::compare). For example: + +
+        int compare(int A, int B) {
+            if (A < B) {
+                return 1;
+            } else if (A == B) {
+                return 0;
+            } else {
+                return -1;
+            }
+        }
+        
+ */ + template + void partition( + const T& partitionElement, + Array& ltArray, + Array& eqArray, + Array& gtArray, + const Comparator& comparator) const { + + // Make sure all arrays are independent + debugAssert(<Array != this); + debugAssert(&eqArray != this); + debugAssert(>Array != this); + debugAssert(<Array != &eqArray); + debugAssert(<Array != >Array); + debugAssert(&eqArray != >Array); + + // Clear the arrays + ltArray.fastClear(); + eqArray.fastClear(); + gtArray.fastClear(); + + // Form a table of buckets for lt, eq, and gt + Array* bucket[3] = {<Array, &eqArray, >Array}; + + for (int i = 0; i < num; ++i) { + int c = comparator(partitionElement, data[i]); + debugAssertM(c >= -1 && c <= 1, "Comparator returned an illegal value."); + + // Insert into the correct bucket, 0, 1, or 2 + bucket[c + 1]->append(data[i]); + } + } + + /** + Uses < and == on elements to perform a partition. See partition(). + */ + void partition( + const T& partitionElement, + Array& ltArray, + Array& eqArray, + Array& gtArray) const { + + partition(partitionElement, ltArray, eqArray, gtArray, typename Array::DefaultComparator()); + } + + /** + Paritions the array into those below the median, those above the median, and those elements + equal to the median in expected O(n) time using quickselect. If the array has an even + number of different elements, the median for partition purposes is the largest value + less than the median. + + @param tempArray used for working scratch space + @param comparator see parition() for a discussion.*/ + template + void medianPartition( + Array& ltMedian, + Array& eqMedian, + Array& gtMedian, + Array& tempArray, + const Comparator& comparator) const { + + ltMedian.fastClear(); + eqMedian.fastClear(); + gtMedian.fastClear(); + + // Handle trivial cases first + switch (size()) { + case 0: + // Array is empty; no parition is possible + return; + + case 1: + // One element + eqMedian.append(first()); + return; + + case 2: + { + // Two element array; median is the smaller + int c = comparator(first(), last()); + + switch (c) { + case -1: + // first was bigger + eqMedian.append(last()); + gtMedian.append(first()); + break; + + case 0: + // Both equal to the median + eqMedian.append(first(), last()); + break; + + case 1: + // Last was bigger + eqMedian.append(first()); + gtMedian.append(last()); + break; + } + } + return; + } + + // All other cases use a recursive randomized median + + // Number of values less than all in the current arrays + int ltBoost = 0; + + // Number of values greater than all in the current arrays + int gtBoost = 0; + + // For even length arrays, force the gt array to be one larger than the + // lt array: + // [1 2 3] size = 3, choose half = (s + 1) /2 + // + int lowerHalfSize, upperHalfSize; + if (isEven(size())) { + lowerHalfSize = size() / 2; + upperHalfSize = lowerHalfSize + 1; + } else { + lowerHalfSize = upperHalfSize = (size() + 1) / 2; + } + const T* xPtr = NULL; + + // Maintain pointers to the arrays; we'll switch these around during sorting + // to avoid copies. + const Array* source = this; + Array* lt = <Median; + Array* eq = &eqMedian; + Array* gt = >Median; + Array* extra = &tempArray; + + while (true) { + // Choose a random element -- choose the middle element; this is theoretically + // suboptimal, but for loosly sorted array is actually the best strategy + + xPtr = &(source->middle()); + if (source->size() == 1) { + // Done; there's only one element left + break; + } + const T& x = *xPtr; + + // Note: partition (fast) clears the arrays for us + source->partition(x, *lt, *eq, *gt, comparator); + + int L = lt->size() + ltBoost + eq->size(); + int U = gt->size() + gtBoost + eq->size(); + if ((L >= lowerHalfSize) && + (U >= upperHalfSize)) { + + // x must be the partition median + break; + + } else if (L < lowerHalfSize) { + + // x must be smaller than the median. Recurse into the 'gt' array. + ltBoost += lt->size() + eq->size(); + + // The new gt array will be the old source array, unless + // that was the this pointer (i.e., unless we are on the + // first iteration) + Array* newGt = (source == this) ? extra : const_cast*>(source); + + // Now set up the gt array as the new source + source = gt; + gt = newGt; + + } else { + + // x must be bigger than the median. Recurse into the 'lt' array. + gtBoost += gt->size() + eq->size(); + + // The new lt array will be the old source array, unless + // that was the this pointer (i.e., unless we are on the + // first iteration) + Array* newLt = (source == this) ? extra : const_cast*>(source); + + // Now set up the lt array as the new source + source = lt; + lt = newLt; + } + } + + // Now that we know the median, make a copy of it (since we're about to destroy the array that it + // points into). + T median = *xPtr; + xPtr = NULL; + + // Partition the original array (note that this fast clears for us) + partition(median, ltMedian, eqMedian, gtMedian, comparator); + } + + /** + Computes a median partition using the default comparator and a dynamically allocated temporary + working array. If the median is not in the array, it is chosen to be the largest value smaller + than the true median. + */ + void medianPartition( + Array& ltMedian, + Array& eqMedian, + Array& gtMedian) const { + + Array temp; + medianPartition(ltMedian, eqMedian, gtMedian, temp, DefaultComparator()); + } + + + /** Redistributes the elements so that the new order is statistically independent + of the original order. O(n) time.*/ + void randomize() { + T temp; + + for (int i = size() - 1; i >= 0; --i) { + int x = iRandom(0, i); + + temp = data[i]; + data[i] = data[x]; + data[x] = temp; + } + } + + +}; + + +/** Array::contains for C-arrays */ +template bool contains(const T* array, int len, const T& e) { + for (int i = len - 1; i >= 0; --i) { + if (array[i] == e) { + return true; + } + } + return false; +} + +} // namespace + +#endif + +#ifdef G3D_WIN32 +# pragma warning (push) +#endif diff --git a/dep/include/g3dlite/G3D/Box.h b/dep/include/g3dlite/G3D/Box.h new file mode 100644 index 00000000000..f097c10e18e --- /dev/null +++ b/dep/include/g3dlite/G3D/Box.h @@ -0,0 +1,228 @@ +/** + @file Box.h + + Box class + + @maintainer Morgan McGuire, matrix@graphics3d.com + + @cite Portions based on Dave Eberly's Magic Software Library at http://www.magic-software.com + @created 2001-06-02 + @edited 2006-01-05 + + Copyright 2000-2006, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_BOX_H +#define G3D_BOX_H + +#include "G3D/platform.h" +#include "G3D/Vector3.h" +#include "G3D/Array.h" +#include "G3D/Plane.h" + +namespace G3D { + +class CoordinateFrame; + +/** + An arbitrary 3D box, useful as a bounding box. + + + To construct a box from a coordinate frame, center and extent, use the idiom: + + Box box = cframe.toObjectSpace(Box(center - extent/2, center + extent/2)); + */ +class Box { +private: + + static int32 dummy; + + friend class CoordinateFrame; + + /** +
+       3    2       7    6
+    
+       0    1       4    5
+
+       front    back (seen through front)
+      
+ */ + Vector3 _corner[8]; + + /** + Unit axes. + */ + Vector3 _axis[3]; + + Vector3 _center; + + /** + Extent along each axis. + */ + Vector3 _extent; + + float _area; + float _volume; + + void init( + const Vector3& min, + const Vector3& max); + +public: + + /** + Does not initialize the fields. + */ + Box(); + + /** + Constructs a box from two opposite corners. + */ + Box( + const Vector3& min, + const Vector3& max); + + Box(const class AABox& b); + + + /** + Returns the object to world transformation for + this box. localFrame().worldToObject(...) takes + objects into the space where the box axes are + (1,0,0), (0,1,0), (0,0,1). Note that there + is no scaling in this transformation. + */ + CoordinateFrame localFrame() const; + + void getLocalFrame(CoordinateFrame& frame) const; + + /** + Returns the centroid of the box. + */ + inline Vector3 center() const { + return _center; + } + + inline Vector3 getCenter() const { + return center(); + } + + /** + Returns a corner (0 <= i < 8) + @deprecated + */ + inline Vector3 getCorner(int i) const { + debugAssert(i < 8); + return _corner[i]; + } + + inline Vector3 corner(int i) const { + debugAssert(i < 8); + return _corner[i]; + } + + /** + Unit length. + */ + inline Vector3 axis(int a) const { + debugAssert(a < 3); + return _axis[a]; + } + + /** + Distance from corner(0) to the next corner + along the box's local axis a. + */ + inline float extent(int a) const { + debugAssert(a < 3); + return (float)_extent[a]; + } + + inline Vector3 extent() const { + return _extent; + } + + /** + Returns the four corners of a face (0 <= f < 6). + The corners are returned to form a counter clockwise quad facing outwards. + */ + void getFaceCorners( + int f, + Vector3& v0, + Vector3& v1, + Vector3& v2, + Vector3& v3) const; + +/** + @deprecated Use culledBy(Array&) + */ + bool culledBy( + const class Plane* plane, + int numPlanes, + int32& cullingPlaneIndex, + const uint32 testMask, + uint32& childMask) const; + + /** + @deprecated Use culledBy(Array&) + */ + bool culledBy( + const class Plane* plane, + int numPlanes, + int32& cullingPlaneIndex = dummy, + const uint32 testMask = -1) const; + + /** + See AABox::culledBy + */ + bool culledBy( + const Array& plane, + int32& cullingPlaneIndex, + const uint32 testMask, + uint32& childMask) const; + + /** + Conservative culling test that does not produce a mask for children. + */ + bool culledBy( + const Array& plane, + int32& cullingPlaneIndex = dummy, + const uint32 testMask = -1) const; + + bool contains( + const Vector3& point) const; + + /** @deprecated */ + float surfaceArea() const; + + inline float area() const { + return surfaceArea(); + } + + float volume() const; + + void getRandomSurfacePoint(Vector3& P, Vector3& N = Vector3::dummy) const; + + /** + @deprecated + Uniformly distributed on the surface. + */ + inline Vector3 randomSurfacePoint() const { + Vector3 V; + getRandomSurfacePoint(V); + return V; + } + + /** + Uniformly distributed on the interior (includes surface) + */ + Vector3 randomInteriorPoint() const; + + void getBounds(class AABox&) const; +}; + +} + +#endif diff --git a/dep/include/g3dlite/G3D/CollisionDetection.h b/dep/include/g3dlite/G3D/CollisionDetection.h new file mode 100644 index 00000000000..4dc8b26538d --- /dev/null +++ b/dep/include/g3dlite/G3D/CollisionDetection.h @@ -0,0 +1,1157 @@ +/** + @file CollisionDetection.h + + + Moving collision detection for simple primitives. + + @author Morgan McGuire, matrix@graphics3d.com + @cite Spherical collision based on Paul Nettle's + ftp://ftp.3dmaileffects.com/pub/FluidStudios/CollisionDetection/Fluid_Studios_Generic_Collision_Detection_for_Games_Using_Ellipsoids.pdf + and comments by Max McGuire. Ray-sphere intersection by Eric Haines. + Box-Box intersection written by Kevin Egan. + Thanks to Max McGuire of Iron Lore for various bug fixes. + + @created 2001-11-19 + @edited 2006-01-10 + + Copyright 2000-2006, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_COLLISIONDETECTION_H +#define G3D_COLLISIONDETECTION_H + +#include "G3D/platform.h" +#include "G3D/Vector3.h" +#include "G3D/Plane.h" +#include "G3D/Box.h" +#include "G3D/Triangle.h" +#include "G3D/Array.h" +#include "G3D/Ray.h" +#include "G3D/Line.h" + +namespace G3D { + + +/** + Collision detection primitives and tools for building + higher order collision detection schemes. + + These routines provide moving and static collision detection. + Moving collision detection allows the calculation of collisions that + occur during a period of time -- as opposed to the intersection of + two static bodies. + + Moving collision detection routines detect collisions between + only static primitives and moving spheres or points. Since the + reference frame can be user defined, these functions can be used to + detect the collision between two moving bodies by subtracting + the velocity vector of one object from the velocity vector of the + sphere or point the detection is to occur with. This unified + velocity vector will act as if both objects are moving simultaneously. + + Collisions are detected for single-sided objects only. That is, + no collision is detected when leaving a primitive or passing + through a plane or triangle opposite the normal... except for the + point-sphere calculation or when otherwise noted. + + For a sphere, the collision location returned is the point in world + space where the surface of the sphere and the fixed object meet. + It is not the position of the center of the sphere at + the time of the collision. + + The collision normal returned is the surface normal to the fixed + object at the collision location. + +

+ Static Collision Detection: (Neither object is moving) + + + + + + + + + + + + + + +
Vector3LineSegmentRay *LinePlaneTriangleSphereCylinderCapsuleAABoxBox
Vector3Vector3::operator== Vector3::fuzzyEq G3D::distance
LineSegmentLineSegment::closestPoint LineSegment::distance CollisionDetection::closestPointOnLineSegment
Ray *Ray::closestPoint Ray::distance
LineLine::closestPoint Line::distanceCollisionDetection::closestPointsBetweenLineAndLine
Plane
Triangle
SphereSphere::contains
CylinderCylinder::contains
CapsuleCapsule::contains
AABoxAABox::contains
BoxBox::contains(treat as Ray)CollisionDetection::collisionTimeForMovingPointFixedBox(treat as Ray)CollisionDetection::penetrationDepthForFixedBoxFixedPlaneCollisionDetection::penetrationDepthForFixedBoxFixedPlaneCollisionDetection::penetrationDepthForFixedSphereFixedBoxNone (use OPCODE)CollisionDetection::movingSpherePassesThroughFixedBoxCollisionDetection::penetrationDepthForFixedBoxFixedBoxCollisionDetection::penetrationDepthForFixedBoxFixedBox
+ +

+ Moving Collision Detection: + + * Note: Moving collision detection against certain primitives is equivalent to static collision + detection against a bigger primitive. Ray, Line Segment == ``moving Point''; Capsule ==``moving Sphere''; Plane == ``moving Line'' + */ +class CollisionDetection { +private: + + /** + Default parameter if value passed to a function as reference is + not to be calculated. Must be explicitly supported by function. + */ + static Vector3 ignore; + + /** + Default parameter if value passed to a function as reference is + not to be calculated. Must be explicitly supported by function. + */ + static bool ignoreBool; + + /** + Default parameter if value passed to a function as reference is + not to be calculated. Must be explicitly supported by function. + */ + static Array ignoreArray; + + + // Static class! + CollisionDetection() {} + virtual ~CollisionDetection() {} + +public: + + /** + Converts an index [0, 15] to the corresponding separating axis. + Does not return normalized vector in the edge-edge case + (indices 6 through 15). + + @param separatingAxisIndex Separating axis. + @param box1 Box 1. + @param box2 Box 2. + + @return Axis that separates the two boxes. + */ + static Vector3 separatingAxisForSolidBoxSolidBox( + const int separatingAxisIndex, + const Box & box1, + const Box & box2); + + /** + Tests whether two boxes have axes that are parallel to + each other. If they are, axis1 and axis2 are set to be + the parallel axes for both box1 and box2 respectively. + + @param ca Dot products of each of the boxes axes + @param epsilon Fudge factor (small unit by which the dot + products may vary and still be considered + zero). + @param axis1 Parallel Axis 1. [Post Condition] + @param axis2 Parallel Axis 2. [Post Condition] + + @return true - If boxes have a parallel axis + @return false - otherwise. + */ + static bool parallelAxisForSolidBoxSolidBox( + const double* ca, + const double epsilon, + int & axis1, + int & axis2); + + /** + Calculates the projected distance between the two boxes along + the specified separating axis, negative distances correspond + to an overlap along that separating axis. The distance is not + divided by denominator dot(L, L), see + penetrationDepthForFixedSphereFixedBox() for more details + + @param separatingAxisIndex + @param a Box 1's bounding sphere vector + @param b Box 2's bounding sphere vector + @param D Vector between Box 1 and Box 2's center points + @param c Pointer to array of dot products of the axes of Box 1 + and Box 2. + @param ca Pointer to array of unsigned dot products of the axes + of Box 1 and Box 2. + @param ad Pointer to array of dot products of Box 1 axes and D. + @param bd Pointer to array of dot products of Box 2 axes and D. + + @return Projected distance between the two boxes along the + specified separating axis. + */ + static float projectedDistanceForSolidBoxSolidBox( + const int separatingAxisIndex, + const Vector3 & a, + const Vector3 & b, + const Vector3 & D, + const double* c, + const double* ca, + const double* ad, + const double* bd); + + + /** + Creates a set of standard information about two boxes in order to + solve for their collision. This information includes a vector to + the radius of the bounding sphere for each box, the vector between + each boxes' center and a series of dot products between differing + important vectors. These dot products include those between the axes + of both boxes (signed and unsigned values), and the dot products + between all the axes of box1 and the boxes' center vector and box2 + and the boxes' center vector. + + @pre The following space requirements must be met: + - c[] 9 elements + - ca[] 9 elements + - ad[] 3 elements + - bd[] 3 elements + + @cite dobted from David Eberly's papers, variables used in this function + correspond to variables used in pages 6 and 7 in the pdf + http://www.magic-software.com/Intersection.html + http://www.magic-software.com/Documentation/DynamicCollisionDetection.pdf + + @note Links are out-dated. (Kept to preserve origin and authorship) + + @param box1 Box 1 + @param box2 Box 2 + @param a Box 1's bounding sphere vector + @param b Box 2's bounding sphere vector + @param D Vector between Box 1 and Box 2's center points + @param c Pointer to array of dot products of the axes of Box 1 + and Box 2. + @param ca Pointer to array of unsigned dot products of the axes + of Box 1 and Box 2. + @param ad Pointer to array of dot products of Box 1 axes and D. + @param bd Pointer to array of dot products of Box 2 axes and D. + */ + static void fillSolidBoxSolidBoxInfo( + const Box & box1, + const Box & box2, + Vector3 & a, + Vector3 & b, + Vector3 & D, + double* c, + double* ca, + double* ad, + double* bd); + + /** + Performs a simple bounding sphere check between two boxes to determine + whether these boxes could possibly intersect. This is a very + cheap operation (three dot products, two sqrts and a few others). If + it returns true, an intersection is possible, but not necessarily + guaranteed. + + @param a Vector from box A's center to an outer vertex + @param b Vector from box B's center to an outer vertex + @param D Distance between the centers of the two boxes + + @return true - if possible intersection + @return false - otherwise (This does not guarantee an intersection) + */ + static bool conservativeBoxBoxTest( + const Vector3 & a, + const Vector3 & b, + const Vector3 & D); + + /** + Determines whether two fixed solid boxes intersect. + + @note To speed up collision detection, the lastSeparatingAxis from + the previous time step can be passed in and that plane can be + checked first. If the separating axis was not saved, or if the + two boxes intersected then lastSeparatingAxis should equal -1. + + @cite Adobted from David Eberly's papers, variables used in this function + correspond to variables used in pages 6 and 7 in the pdf + http://www.magic-software.com/Intersection.html + http://www.magic-software.com/Documentation/DynamicCollisionDetection.pdf + + @param box1 Box 1. + @param box2 Box 2. + @param lastSeparatingAxis Last separating axis. + (optimization - see note) + + @return true - Intersection. + @return false - otherwise. + */ + static bool fixedSolidBoxIntersectsFixedSolidBox( + const Box& box1, + const Box& box2, + const int lastSeparatingAxis = -1); + + /** + Calculates the closest points on two lines with each other. If the + lines are parallel then using the starting point, else calculate the + closest point on each line to the other. + + @note This is very similiar to calculating the intersection of two lines. + Logically then, the two points calculated would be identical if calculated + with inifinite precision, but with the finite precision of floating point + calculations, these values could (will) differ as the line slope approaches + zero or inifinity. + + @cite variables and algorithm based on derivation at the following website: + http://softsurfer.com/Archive/algorithm_0106/algorithm_0106.htm + + @param line1 Line 1. + @param line2 Line 2. + @param closest1 Closest point on line 1. + @param closest2 Closest point on line 2. + */ + static void closestPointsBetweenLineAndLine( + const Line & line1, + const Line & line2, + Vector3 & closest1, + Vector3 & closest2); + + /** + Calculates the depth of penetration between two fixed boxes. + Contact normal faces away from box1 and into box2. If there is + contact, only one contact point is returned. The minimally + violated separating plane is computed + - if the separating axis corresponds to a face + the contact point is half way between the deepest vertex + and the face + - if the separating axis corresponds to two edges + the contact point is the midpoint of the smallest line + segment between the two edge lines + + @note This is very similiar to calculating the intersection of two lines. + Logically then, the two points calculated would be identical if calculated + with inifinite precision, but with the finite precision of floating point + calculations, these values could (will) differ as the line slope approaches + zero or inifinity. + + @cite adobted from David Eberly's papers, variables used in this function + correspond to variables used in pages 6 and 7 in the pdf + http://www.magic-software.com/Intersection.html + http://www.magic-software.com/Documentation/DynamicCollisionDetection.pdf + + @param box1 Box 1 + @param box2 Box 2 + @param contactPoints Contact point between boxes. [Post Condition] + @param contactNormals Surface normal at contact point. [Post Condition] + @param lastSeparatingAxis Last separating axis. (Used for optimization) + + @return Depth of penetration between the two boxes. If there is no + intersection between the boxes, then a negative value is returned. + */ + static float penetrationDepthForFixedBoxFixedBox( + const Box& box1, + const Box& box2, + Array& contactPoints, + Array& contactNormals, + const int lastSeparatingAxis = -1); + + /** + Calculates the depth of penetration between two fixed spheres as well + as the deepest point of Sphere A that penetrates Sphere B. The normal + returned points away from the object A, although it may + represent a perpendicular to either the faces of object B or object A + depending on their relative orientations. + + @param sphereA Fixed Sphere A. + @param sphereB Fixed Sphere B. + @param contactPoints Sphere A's deepest point that penetrates Sphere B. + [Post Condition] + @param contactNormals Normal at penetration point. [Post Condition] + + @return Depth of penetration. If there is no intersection between the + objects then the depth will be a negative value. + */ + static float penetrationDepthForFixedSphereFixedSphere( + const class Sphere& sphereA, + const Sphere& sphereB, + Array& contactPoints, + Array& contactNormals = ignoreArray); + + /** + Calculates the depth of penetration between a fixed sphere and a fixed + box as well as the deepest point of the sphere that penetrates the box + and the normal at that intersection. + + @note There are three possible intersections between a sphere and box. + - Sphere completely contained in the box + - Sphere intersects one edge + - Sphere intersects one vertex + + The contact point and contact normal vary for each of these situations. + - Sphere contained in Box: + - Normal is based on side of least penetration (as is the depth calculation). + - Point is based on center of sphere + - Sphere intersects one edge + - Normal is based on vector from the box center to the point of depth. + - Point is closest point to the sphere on the line + - Sphere intersects one vertex + - Normal is based on vector from the box center to the vertex of penetration. + - Point is vertex of penetration. + + @cite Adapted from Jim Arvo's method in Graphics Gems + See also http://www.win.tue.nl/~gino/solid/gdc2001depth.pdf + + @param sphere Fixed Sphere. + @param box Fixed Box. + @param contactPoints Sphere point that penetrates the box. [Post Condition] + @param contactNormals Normal at the penetration point. [Post Condition] + + @return Depth of penetration. If there is no intersection between the + objects then the depth will be a negative value. + */ + static float penetrationDepthForFixedSphereFixedBox( + const Sphere& sphere, + const Box& box, + Array& contactPoints, + Array& contactNormals = ignoreArray); + + /** + Calculates the depth of penetration between a Fixed Sphere and a Fixed + Plane as well as the deepest point of the sphere that penetrates the plane + and the plane normal at that intersection. + + @param sphere Fixed Sphere. + @param plane Fixed Plane. + @param contactPoints Sphere point that penetrates the plane. + [Post Condition] + @param contactNormals Normal at penetration point. [Post Condition] + + @return Depth of penetration. If there is no intersection between the + objects then the depth will be a negative value. + */ + static float penetrationDepthForFixedSphereFixedPlane( + const Sphere& sphereA, + const class Plane& planeB, + Array& contactPoints, + Array& contactNormals = ignoreArray); + + /** + Calculates the depth of penetration between a fixed box and a fixed + plane as well as the vertexes of the box that penetrate the plane + and the plane normals at those intersections. + + @param box Fixed Box. + @param plane Fixed Plane. + @param contactPoints Box points that penetrate the plane. + [Post Condition] + @param contactNormals Normals at penetration points [Post Condition] + + @return Depth of penetration. If there is no intersection between the + objects then the depth will be a negative value. + */ + static float penetrationDepthForFixedBoxFixedPlane( + const Box& box, + const Plane& plane, + Array& contactPoints, + Array& contactNormals = ignoreArray); + + /** + Calculates time between the intersection of a moving point and a fixed + plane. + + @note This is only a one sided collision test. The side defined by + the plane's surface normal is the only one tested. For a two sided + collision, call the function once for each side's surface normal. + + @param point Moving point. + @param velocity Point's velocity. + @param plane Fixed plane. + @param location Location of collision. [Post Condition] + (Infinite vector on no collision) + @param outNormal Plane's surface normal. [Post Condition] + + @return Time til collision. If there is no collision then the return + value will be inf(). + */ + static float collisionTimeForMovingPointFixedPlane( + const Vector3& point, + const Vector3& velocity, + const class Plane& plane, + Vector3& outLocation, + Vector3& outNormal = ignore); + + /** + Calculates time between the intersection of a moving point and a fixed + triangle. + + @note This is only a one sided collision test. The side defined by + the triangle's surface normal is the only one tested. For a two sided + collision, call the function once for each side's surface normal. + + @param orig Moving point. + @param dir Point's velocity. + @param v0 Triangle vertex 1. + @param v1 Triangle vertex 2. + @param v2 Triangle vertex 3 + @param location Location of collision. [Post Condition] + (Infinite vector on no collision) + + @return Time til collision. If there is no collision then the return + value will be inf(). + */ + inline static float collisionTimeForMovingPointFixedTriangle( + const Vector3& orig, + const Vector3& dir, + const Vector3& v0, + const Vector3& v1, + const Vector3& v2) { + return Ray::fromOriginAndDirection(orig, dir).intersectionTime(v0, v1, v2); + } + + /** + Calculates time between the intersection of a moving point and a fixed + triangle. + + @note This is only a one sided collision test. The side defined by + the triangle's surface normal is the only one tested. For a two sided + collision, call the function once for each side's surface normal. + + @param orig Moving point. + @param dir Point's velocity. + @param v0 Triangle vertex 1. + @param v1 Triangle vertex 2. + @param v2 Triangle vertex 3 + @param location Location of collision. [Post Condition] + (Infinite vector on no collision) + + @return Time til collision. If there is no collision then the return + value will be inf(). + */ + inline static float collisionTimeForMovingPointFixedTriangle( + const Vector3& orig, + const Vector3& dir, + const Vector3& v0, + const Vector3& v1, + const Vector3& v2, + Vector3& location) { + float t = collisionTimeForMovingPointFixedTriangle(orig, dir, v0, v1, v2); + if (t < inf()) { + location = orig + dir * t; + } + return t; + } + + /** + Calculates time between the intersection of a moving point and a fixed + triangle. + + @note This is only a one sided collision test. The side defined by + the triangle's surface normal is the only one tested. For a two sided + collision, call the function once for each side's surface normal. + + @param orig Moving point. + @param dir Point's velocity. + @param tri Fixed triangle. + @param location Location of collision. [Post Condition] + (Infinite vector on no collision) + @param normal Triangle's surface normal. [Post Condition] + + @return Time til collision. If there is no collision then the return + value will be inf(). + */ + inline static float collisionTimeForMovingPointFixedTriangle( + const Vector3& orig, + const Vector3& dir, + const Triangle& tri, + Vector3& location = ignore, + Vector3& normal = ignore) { + + float t = collisionTimeForMovingPointFixedTriangle( + orig, dir, tri.vertex(0), tri.vertex(1), tri.vertex(2)); + + if ((t < inf()) && (&location != &ignore)) { + location = orig + dir * t; + normal = tri.normal(); + } + return t; + } + + /** + Calculates time between the intersection of a moving point and a fixed + triangle. + + @note This is only a one sided collision test. The side defined by + the triangle's surface normal is the only one tested. For a two sided + collision, call the function once for each side's surface normal. + + @param orig Moving point. + @param dir Point's velocity. + @param v0 Triangle vertex 1. + @param v1 Triangle vertex 2. + @param v2 Triangle vertex 3 + @param location Location of collision. [Post Condition] + (Infinite vector on no collision) + @param normal Triangle's surface normal. [Post Condition] + + @return Time til collision. If there is no collision then the return + value will be inf(). + */ + inline static float collisionTimeForMovingPointFixedTriangle( + const Vector3& orig, + const Vector3& dir, + const Vector3& v0, + const Vector3& v1, + const Vector3& v2, + Vector3& location, + Vector3& normal) { + float t = collisionTimeForMovingPointFixedTriangle(orig, dir, v0, v1, v2); + if (t < inf()) { + location = orig + dir * t; + normal = (v2 - v0).cross(v1 - v0).direction(); + } + return t; + } + + /** + Unlike other methods, does not support an output normal. + If the ray origin is inside the box, returns inf() but inside + is set to true. + Beta API + + @cite Andrew Woo, from "Graphics Gems", Academic Press, 1990 + @cite Optimized code by Pierre Terdiman, 2000 (~20-30% faster on my Celeron 500) + @cite Epsilon value added by Klaus Hartmann + @cite http://www.codercorner.com/RayAABB.cpp + */ + static float collisionTimeForMovingPointFixedAABox( + const Vector3& point, + const Vector3& velocity, + const class AABox& box, + Vector3& outLocation, + bool& inside = ignoreBool, + Vector3& outNormal = ignore); + + /** + Calculates time between the intersection of a moving point and a fixed + Axis-Aligned Box (AABox). + + @note Avoids the sqrt from collisionTimeForMovingPointFixedAABox. + + @param point Moving point. + @param velocity Sphere's velocity. + @param box Fixed AAbox. + @param location Location of collision. [Post Condition] + @param Inside Does the ray originate inside the box? [Post Condition] + @param normal Box's surface normal to collision [Post Condition] + + @return Time til collision. If there is no collision then the return + value will be inf(). + */ + static bool collisionLocationForMovingPointFixedAABox( + const Vector3& point, + const Vector3& velocity, + const class AABox& box, + Vector3& outLocation, + bool& inside = ignoreBool, + Vector3& normal = ignore); + + /** + Calculates time between the intersection of a moving point and a fixed + sphere. + + @note When ray is starts inside the rectangle, the exiting intersection + is detected. + + @param point Moving point. + @param velocity Point's velocity. + @param Sphere Fixed Sphere. + @param location Location of collision. [Post Condition] + @param outNormal Sphere's surface normal to collision [Post Condition] + + @return Time til collision. If there is no collision then the return + value will be inf(). + */ + static float collisionTimeForMovingPointFixedSphere( + const Vector3& point, + const Vector3& velocity, + const class Sphere& sphere, + Vector3& outLocation, + Vector3& outNormal = ignore); + + /** + Calculates time between the intersection of a moving point and a fixed + box. + + @note If the point is already inside the box, no collision: inf is returned. + + @param point Moving point. + @param velocity Sphere's velocity. + @param box Fixed box. + @param location Position of collision. [Post Condition] + @param outNormal Box's surface normal to collision [Post Condition] + + @return Time til collision. If there is no collision then the return + value will be inf(). + */ + static float collisionTimeForMovingPointFixedBox( + const Vector3& point, + const Vector3& velocity, + const class Box& box, + Vector3& outLocation, + Vector3& outNormal = ignore); + + /** + Calculates time between the intersection of a moving point and a fixed + rectangle defined by the points v0, v1, v2, & v3. + + @note This is only a one sided collision test. The side defined by + the rectangle's surface normal is the only one tested. For a two sided + collision, call the function once for each side's surface normal. + + @param point Moving point. + @param velocity Sphere's velocity. + @param v0 Rectangle vertex 1. + @param v1 Rectangle vertex 2. + @param v2 Rectangle vertex 3 + @param v3 Rectangle vertex 4. + @param location Location of collision [Post Condition] + @param outNormal Rectangle's surface normal. [Post Condition] + + @return Time til collision. If there is no collision then the return + value will be inf(). + */ + static float collisionTimeForMovingPointFixedRectangle( + const Vector3& point, + const Vector3& velocity, + const Vector3& v0, + const Vector3& v1, + const Vector3& v2, + const Vector3& v3, + Vector3& outLocation, + Vector3& outNormal = ignore); + + /** + Calculates time between the intersection of a moving point and a fixed + capsule. + + @param point Moving point. + @param velocity Point's velocity. + @param capsule Fixed capsule. + @param location Location of collision. [Post Condition] + @param outNormal Capsule's surface normal to collision [Post Condition] + + @return Time til collision. If there is no collision then the return + value will be inf(). + */ + static float collisionTimeForMovingPointFixedCapsule( + const Vector3& point, + const Vector3& velocity, + const class Capsule& capsule, + Vector3& outLocation, + Vector3& outNormal = ignore); + + /** + Calculates time between the intersection of a moving sphere and a fixed + triangle. + + @param sphere Moving sphere. + @param velocity Sphere's velocity. + @param plane Fixed Plane. + @param location Location of collision -- not center position of sphere + at the collision time. [Post Condition] + @param outNormal Box's surface normal to collision [Post Condition] + + @return Time til collision. If there is no collision then the return + value will be inf(). + */ + static float collisionTimeForMovingSphereFixedPlane( + const class Sphere& sphere, + const Vector3& velocity, + const class Plane& plane, + Vector3& outLocation, + Vector3& outNormal = ignore); + + /** + Calculates time between the intersection of a moving sphere and a fixed + triangle. + + @param sphere Moving sphere. + @param velocity Sphere's velocity. + @param triangle Fixed Triangle. + @param location Location of collision -- not center position of sphere + at the collision time. [Post Condition] + @param outNormal Box's surface normal to collision [Post Condition] + + @return Time til collision. If there is no collision then the return + value will be inf(). + */ + static float collisionTimeForMovingSphereFixedTriangle( + const class Sphere& sphere, + const Vector3& velocity, + const Triangle& triangle, + Vector3& outLocation, + Vector3& outNormal = ignore); + + /** + Calculates time between the intersection of a moving sphere and a fixed + rectangle defined by the points v0, v1, v2, & v3. + + @param sphere Moving sphere. + @param velocity Sphere's velocity. + @param v0 Rectangle vertex 1. + @param v1 Rectangle vertex 2. + @param v2 Rectangle vertex 3 + @param v3 Rectangle vertex 4. + @param location Location of collision -- not center position of sphere + at the collision time. [Post Condition] + @param outNormal Box's surface normal to collision [Post Condition] + + @return Time til collision. If there is no collision then the return + value will be inf(). + */ + static float collisionTimeForMovingSphereFixedRectangle( + const class Sphere& sphere, + const Vector3& velocity, + const Vector3& v0, + const Vector3& v1, + const Vector3& v2, + const Vector3& v3, + Vector3& outLocation, + Vector3& outNormal = ignore); + + /** + Calculates time between the intersection of a moving sphere and a fixed + box. + + @note This function will not detect an intersection between a moving object + that is already interpenetrating the fixed object. + + @param sphere Moving sphere. + @param velocity Sphere's velocity. + @param box Fixed box. + @param location Location of collision -- not center position of sphere + at the collision time. [Post Condition] + @param outNormal Box's surface normal to collision [Post Condition] + + @return Time til collision. If there is no collision then the return + value will be inf(). + */ + static float collisionTimeForMovingSphereFixedBox( + const class Sphere& sphere, + const Vector3& velocity, + const class Box& box, + Vector3& outLocation, + Vector3& outNormal = ignore); + + /** + Calculates time between the intersection of a moving sphere and a fixed + sphere. + + @note This won't detect a collision if the sphere is already interpenetrating + the fixed sphere. + + @param movingSphere Moving sphere. + @param velocity Sphere's velocity. + @param fixedSphere Fixed Sphere. + @param location Location of collision -- not center position of sphere + at the collision time. [Post Condition] + @param outNormal Sphere's surface normal to collision [Post Condition] + + @return Time til collision. If there is no collision then the return + value will be inf(). + */ + static float collisionTimeForMovingSphereFixedSphere( + const class Sphere& sphere, + const Vector3& velocity, + const class Sphere& fixedSphere, + Vector3& outLocation, + Vector3& outNormal = ignore); + + /** + Calculates time between the intersection of a moving sphere and a fixed + capsule. + + @note This won't detect a collision if the sphere is already + interpenetrating the capsule. + + @param sphere Moving sphere. + @param velocity Sphere's velocity. + @param capsule Fixed capsule. + @param location Location of collision -- not center position of sphere + at the collision time. [Post Condition] + @param outNormal Capsule's surface normal to the collision [Post Condition] + + @return Time til collision. If there is no collision then the return + value will be inf(). + */ + static float collisionTimeForMovingSphereFixedCapsule( + const class Sphere& sphere, + const Vector3& velocity, + const class Capsule& capsule, + Vector3& outLocation, + Vector3& outNormal = ignore); + + /** + Finds the direction of bounce that a sphere would have when it + intersects an object with the given time of collision, the + collision location and the collision normal. + + @note This function works like a pong style ball bounce. + + @param sphere Moving sphere. + @param velocity Sphere's velocity. + @param collisionTime Time of collision. + @param collisionLocation Collision location. + @param collisionNormal Surface collision normal. + + @return Direction of bounce. + */ + static Vector3 bounceDirection( + const class Sphere& sphere, + const Vector3& velocity, + const float collisionTime, + const Vector3& collisionLocation, + const Vector3& collisionNormal); + + /** + Finds the direction of slide given a moving sphere, its velocity, the + time of collision and the collision location. This function works as + if the sphere intersects the surface and continues to hug it. + + @note The result will work well for calculating the movement of a player + who collides with an object and continues moving along the object instead + of just bouncing off it. + + @param sphere Moving sphere. + @param velocity Sphere's velocity. + @param collisionTime Time of collision + @param collisionLocation Collision location. + + @return Direction of slide. + */ + static Vector3 slideDirection( + const class Sphere& sphere, + const Vector3& velocity, + const float collisionTime, + const Vector3& collisionLocation); + + /** + Finds the closest point on a line segment to a given point. + + @param v0 line vertex 1. + @param v1 line vertex 2. + @param point External point. + + @return Closests point to point on the line segment. + */ + static Vector3 closestPointOnLineSegment( + const Vector3& v0, + const Vector3& v1, + const Vector3& point); + + /** + Finds the closest point on a line segment to a given point. + + @note This is an optimization to closestPointOnLineSegment. Edge length + and direction can be used in this function if already pre-calculated. This + prevents doing the same work twice. + + @param v0 line vertex 1. + @param v1 line vertex 2. + @param edgeDirection The direction of the segment (unit length). + @param edgeLength The length of the segment. + @param point External point. + + @return Closests point to point on the line segment. + */ + static Vector3 closestPointOnLineSegment( + const Vector3& v0, + const Vector3& v1, + const Vector3& edgeDirection, + float edgeLength, + const Vector3& point); + + /** + Finds the closest point on the perimeter of the triangle to an external point; + given a triangle defined by three points v0, v1, & v2, and the external point. + + @param v0 Triangle vertex 1. + @param v1 Triangle vertex 2. + @param v2 Triangle vertex 3. + @param point External point. + + @return Closests point to point on the perimeter of the + triangle. + */ + static Vector3 closestPointToTrianglePerimeter( + const Vector3& v0, + const Vector3& v1, + const Vector3& v2, + const Vector3& point); + + /** + Finds the closest point on the perimeter of the triangle to an external point; + given a triangle defined by the array of points v, its edge directions and + their lengths, as well as the external point. + + @note This is an optimization to closestPointToTrianglePerimeter. Edge length + and direction can be used in this function if already pre-calculated. This + prevents doing the same work twice. + + @param v0 Triangle vertex 1. + @param v1 Triangle vertex 2. + @param v2 Triangle vertex 3. + @param point External point. + + @return Closests point to point on the perimeter of the + triangle. + */ + static Vector3 closestPointToTrianglePerimeter( + const Vector3 v[3], + const Vector3 edgeDirection[3], + const double edgeLength[3], + const Vector3& point); + + /** + Tests whether a point is contained within the triangle defined by + v0, v1, & v2 and its plane's normal. + + @param v0 Triangle vertex 1. + @param v1 Triangle vertex 2. + @param v2 Triangle vertex 3. + @param normal Normal to triangle's plane. + @param point The point in question. + @param primaryAxis Primary axis of triangle. This will be detected + if not given. This parameter is provided as an optimization. + + @return true - if point is inside the triangle. + @return false - otherwise + */ + static bool isPointInsideTriangle( + const Vector3& v0, + const Vector3& v1, + const Vector3& v2, + const Vector3& normal, + const Vector3& point, + Vector3::Axis primaryAxis = Vector3::DETECT_AXIS); + + /** + Tests for the intersection of a moving sphere and a fixed box in a + given time limit. + + @note Returns true if any part of the sphere is inside the box + during the time period (inf means "ever"). Useful for + performing bounding-box collision detection. + + @param sphere Moving sphere. + @param velocity Velocity of moving sphere. + @param box Fixed box. + @param timeLimit Time limit for intersection test. + + @return true - if the two objects will touch. + @return false - if there is no intersection. + */ + static bool movingSpherePassesThroughFixedBox( + const Sphere& sphere, + const Vector3& velocity, + const Box& box, + double timeLimit = inf()); + + /** + Tests for the intersection of a moving sphere and a fixed sphere in a + given time limit. + + @note This function will not detect an intersection between a moving object + that is already interpenetrating the fixed object. + + @param sphere Moving sphere. + @param velocity Velocity of moving sphere. + @param fixedSphere Fixed sphere. + @param timeLimit Time limit for intersection test. + + @return true - if the two spheres will touch. + @return false - if there is no intersection. + */ + static bool movingSpherePassesThroughFixedSphere( + const Sphere& sphere, + const Vector3& velocity, + const Sphere& fixedSphere, + double timeLimit = inf()); + + /** + Tests for the intersection of two fixed spheres. + + @param sphere1 Fixed sphere 1. + @param sphere2 Fixed sphere 2. + + @return true - if the two spheres touch. + @return false - if there is no intersection. + */ + static bool fixedSolidSphereIntersectsFixedSolidSphere( + const Sphere& sphere1, + const Sphere& sphere2); + + /** + Tests for the intersection of a fixed sphere and a fixed box. + + @param sphere Fixed sphere. + @param box Fixed box. + + @return true - if the two objects touch. + @return false - if there is no intersection. + */ + static bool fixedSolidSphereIntersectsFixedSolidBox( + const Sphere& sphere, + const Box& box); + + /** + Tests whether a point is inside a rectangle defined by the vertexes + v0, v1, v2, & v3, and the rectangle's plane normal. + + @param v0 Rectangle vertex 1. + @param v1 Rectangle vertex 2. + @param v2 Rectangle vertex 3. + @param v3 Rectangle vertex 4. + @param normal Normal to rectangle's plane. + @param point The point in question. + + @return true - if point is inside the rectangle. + @return false - otherwise + */ + static bool isPointInsideRectangle( + const Vector3& v0, + const Vector3& v1, + const Vector3& v2, + const Vector3& v3, + const Vector3& normal, + const Vector3& point); + + /** + Finds the closest point on the perimeter of the rectangle to an + external point; given a rectangle defined by four points v0, v1, + v2, & v3, and the external point. + + @param v0 Rectangle vertex 1. + @param v1 Rectangle vertex 2. + @param v2 Rectangle vertex 3. + @param v3 Rectangle vertex 4. + @param point External point. + + @return Closests point to point on the perimeter of the + rectangle. + */ + static Vector3 closestPointToRectanglePerimeter( + const Vector3& v0, + const Vector3& v1, + const Vector3& v2, + const Vector3& v3, + const Vector3& point); + + /** + Finds the closest point in the rectangle to an external point; Given + a rectangle defined by four points v0, v1, v2, & v3, and the external + point. + + @param v0 Rectangle vertex 1. + @param v1 Rectangle vertex 2. + @param v2 Rectangle vertex 3 + @param v3 Rectangle vertex 4. + @param point External point. + + @return Closet point in the rectangle to the external point. + */ + static Vector3 closestPointToRectangle( + const Vector3& v0, + const Vector3& v1, + const Vector3& v2, + const Vector3& v3, + const Vector3& point); +}; + +} // namespace + +#endif // G3D_COLLISIONDETECTION_H diff --git a/dep/include/g3dlite/G3D/CoordinateFrame.h b/dep/include/g3dlite/G3D/CoordinateFrame.h new file mode 100644 index 00000000000..657323eea6b --- /dev/null +++ b/dep/include/g3dlite/G3D/CoordinateFrame.h @@ -0,0 +1,318 @@ +/** + @file CoordinateFrame.h + + @maintainer Morgan McGuire, matrix@graphics3d.com + + @created 2001-03-04 + @edited 2006-04-07 + + Copyright 2000-2006, Morgan McGuire. + All rights reserved. +*/ + +#ifndef G3D_COORDINATEFRAME_H +#define G3D_COORDINATEFRAME_H + +#include "G3D/platform.h" +#include "G3D/Vector3.h" +#include "G3D/Vector4.h" +#include "G3D/Matrix3.h" +#include "G3D/Array.h" +#include +#include +#include +#include +#include + +namespace G3D { + +/** + A rigid body RT (rotation-translation) transformation. + +CoordinateFrame abstracts a 4x4 matrix that maps object space to world space: + + v_world = C * v_object + +CoordinateFrame::rotation is the upper 3x3 submatrix, CoordinateFrame::translation +is the right 3x1 column. The 4th row is always [0 0 0 1], so it isn't stored. +So you don't have to remember which way the multiplication and transformation work, +it provides explicit toWorldSpace and toObjectSpace methods. Also, points, vectors +(directions), and surface normals transform differently, so they have separate methods. + +Some helper functions transform whole primitives like boxes in and out of object space. + +Convert to Matrix4 using CoordinateFrame::toMatrix4. You can construct a CoordinateFrame +from a Matrix4 using Matrix4::approxCoordinateFrame, however, because a Matrix4 is more +general than a CoordinateFrame, some information may be lost. + +See also: G3D::Matrix4, G3D::Quat +*/ +class CoordinateFrame { +public: + + /** + Takes object space points to world space. + */ + Matrix3 rotation; + + /** + Takes object space points to world space. + */ + Vector3 translation; + + /** + The direction an object "looks" relative to its own axes. + @deprecated This is always -1 and will be fixed at that value in future releases. + */ + static const float zLookDirection; + + inline bool operator==(const CoordinateFrame& other) const { + return (translation == other.translation) && (rotation == other.rotation); + } + + inline bool operator!=(const CoordinateFrame& other) const { + return !(*this == other); + } + + bool fuzzyEq(const CoordinateFrame& other) const; + + bool fuzzyIsIdentity() const; + + bool isIdentity() const; + + /** + Initializes to the identity coordinate frame. + */ + inline CoordinateFrame() : + rotation(Matrix3::identity()), translation(Vector3::zero()) { + } + + CoordinateFrame(const Vector3& _translation) : + rotation(Matrix3::identity()), translation(_translation) { + } + + CoordinateFrame(const Matrix3 &rotation, const Vector3 &translation) : + rotation(rotation), translation(translation) { + } + + CoordinateFrame(const Matrix3 &rotation) : + rotation(rotation), translation(Vector3::zero()) { + } + + CoordinateFrame(const CoordinateFrame &other) : + rotation(other.rotation), translation(other.translation) {} + + /** + Computes the inverse of this coordinate frame. + */ + inline CoordinateFrame inverse() const { + CoordinateFrame out; + out.rotation = rotation.transpose(); + out.translation = -out.rotation * translation; + return out; + } + + inline ~CoordinateFrame() {} + + /** See also Matrix4::approxCoordinateFrame */ + class Matrix4 toMatrix4() const; + + /** + Produces an XML serialization of this coordinate frame. + */ + std::string toXML() const; + + /** + Returns the heading of the lookVector as an angle in radians relative to + the world -z axis. That is, a counter-clockwise heading where north (-z) + is 0 and west (-x) is PI/2. + + Note that the heading ignores the Y axis, so an inverted + object has an inverted heading. + */ + inline float getHeading() const { + Vector3 look = rotation.getColumn(2); + float angle = -(float) atan2(-look.x, look.z); + return angle; + } + + /** + Takes the coordinate frame into object space. + this->inverse() * c + */ + inline CoordinateFrame toObjectSpace(const CoordinateFrame& c) const { + return this->inverse() * c; + } + + inline Vector4 toObjectSpace(const Vector4& v) const { + return this->inverse().toWorldSpace(v); + } + + inline Vector4 toWorldSpace(const Vector4& v) const { + return Vector4(rotation * Vector3(v.x, v.y, v.z) + translation * v.w, v.w); + } + + /** + Transforms the point into world space. + */ + inline Vector3 pointToWorldSpace(const Vector3& v) const { + return Vector3( + rotation[0][0] * v[0] + rotation[0][1] * v[1] + rotation[0][2] * v[2] + translation[0], + rotation[1][0] * v[0] + rotation[1][1] * v[1] + rotation[1][2] * v[2] + translation[1], + rotation[2][0] * v[0] + rotation[2][1] * v[1] + rotation[2][2] * v[2] + translation[2]); + } + + /** + Transforms the point into object space. + */ + inline Vector3 pointToObjectSpace(const Vector3& v) const { + float p[3]; + p[0] = v[0] - translation[0]; + p[1] = v[1] - translation[1]; + p[2] = v[2] - translation[2]; + return Vector3( + rotation[0][0] * p[0] + rotation[1][0] * p[1] + rotation[2][0] * p[2], + rotation[0][1] * p[0] + rotation[1][1] * p[1] + rotation[2][1] * p[2], + rotation[0][2] * p[0] + rotation[1][2] * p[1] + rotation[2][2] * p[2]); + } + + /** + Transforms the vector into world space (no translation). + */ + inline Vector3 vectorToWorldSpace(const Vector3& v) const { + return rotation * v; + } + + inline Vector3 normalToWorldSpace(const Vector3& v) const { + return rotation * v; + } + + class Ray toObjectSpace(const Ray& r) const; + + Ray toWorldSpace(const Ray& r) const; + + /** + Transforms the vector into object space (no translation). + */ + inline Vector3 vectorToObjectSpace(const Vector3 &v) const { + // Multiply on the left (same as rotation.transpose() * v) + return v * rotation; + } + + inline Vector3 normalToObjectSpace(const Vector3 &v) const { + // Multiply on the left (same as rotation.transpose() * v) + return v * rotation; + } + + void pointToWorldSpace(const Array& v, Array& vout) const; + + void normalToWorldSpace(const Array& v, Array& vout) const; + + void vectorToWorldSpace(const Array& v, Array& vout) const; + + void pointToObjectSpace(const Array& v, Array& vout) const; + + void normalToObjectSpace(const Array& v, Array& vout) const; + + void vectorToObjectSpace(const Array& v, Array& vout) const; + + class Box toWorldSpace(const class AABox& b) const; + + class Box toWorldSpace(const class Box& b) const; + + class Cylinder toWorldSpace(const class Cylinder& b) const; + + class Capsule toWorldSpace(const class Capsule& b) const; + + class Plane toWorldSpace(const class Plane& p) const; + + class Sphere toWorldSpace(const class Sphere& b) const; + + class Triangle toWorldSpace(const class Triangle& t) const; + + class Box toObjectSpace(const AABox& b) const; + + class Box toObjectSpace(const Box& b) const; + + class Plane toObjectSpace(const Plane& p) const; + + class Sphere toObjectSpace(const Sphere& b) const; + + Triangle toObjectSpace(const Triangle& t) const; + + /** Compose: create the transformation that is other followed by this.*/ + CoordinateFrame operator*(const CoordinateFrame &other) const { + return CoordinateFrame(rotation * other.rotation, + pointToWorldSpace(other.translation)); + } + + CoordinateFrame operator+(const Vector3& v) const { + return CoordinateFrame(rotation, translation + v); + } + + CoordinateFrame operator-(const Vector3& v) const { + return CoordinateFrame(rotation, translation - v); + } + + void lookAt(const Vector3& target); + + void lookAt( + const Vector3& target, + Vector3 up); + + /** @deprecated See lookVector */ + inline Vector3 getLookVector() const { + return rotation.getColumn(2) * zLookDirection; + } + + /** The direction this camera is looking (its negative z axis)*/ + inline Vector3 lookVector() const { + return rotation.getColumn(2) * zLookDirection; + } + + /** Returns the ray starting at the camera origin travelling in direction CoordinateFrame::lookVector. */ + class Ray lookRay() const; + + /** Up direction for this camera (its y axis). */ + inline Vector3 upVector() const { + return rotation.getColumn(1); + } + + /** + If a viewer looks along the look vector, this is the viewer's "left" + @deprecated leftVector + */ + inline Vector3 getLeftVector() const { + return -rotation.getColumn(0); + } + + /** @deprecated See rightVector */ + inline Vector3 getRightVector() const { + return rotation.getColumn(0); + } + + /** + If a viewer looks along the look vector, this is the viewer's "left". + Useful for strafing motions and building alternative coordinate frames. + */ + inline Vector3 leftVector() const { + return -rotation.getColumn(0); + } + + inline Vector3 rightVector() const { + return rotation.getColumn(0); + } + + /** + Linearly interpolates between two coordinate frames, using + Quat::slerp for the rotations. + */ + CoordinateFrame lerp( + const CoordinateFrame& other, + float alpha) const; + +}; + +} // namespace + +#endif diff --git a/dep/include/g3dlite/G3D/Crypto.h b/dep/include/g3dlite/G3D/Crypto.h new file mode 100644 index 00000000000..f4e7bfad6cd --- /dev/null +++ b/dep/include/g3dlite/G3D/Crypto.h @@ -0,0 +1,46 @@ +/** + @file Crypto.h + + @maintainer Morgan McGuire, matrix@graphics3d.com + + + @created 2006-03-29 + @edited 2006-04-06 + */ + +#ifndef G3D_CRYPTO_H +#define G3D_CRYPTO_H + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" +#include + +namespace G3D { + +/** Cryptography and hashing helper functions */ +class Crypto { +public: + + /** + Computes the CRC32 value of a byte array. CRC32 is designed to be a hash + function that produces different values for similar strings. + + This implementation is compatible with PKZIP and GZIP. + + Based on http://www.gamedev.net/reference/programming/features/crc32/ + */ + static uint32 crc32(const void* bytes, size_t numBytes); + + /** + Returns the nth prime less than 2000 in constant time. The first prime has index + 0 and is the number 2. + */ + static int smallPrime(int n); + + /** Returns 1 + the largest value that can be passed to smallPrime. */ + static int numSmallPrimes(); +}; + +} + +#endif diff --git a/dep/include/g3dlite/G3D/GCamera.h b/dep/include/g3dlite/G3D/GCamera.h new file mode 100644 index 00000000000..3205f3904b1 --- /dev/null +++ b/dep/include/g3dlite/G3D/GCamera.h @@ -0,0 +1,251 @@ +/** + @file GCamera.h + + @maintainer Morgan McGuire, matrix@graphics3d.com + + @created 2001-06-02 + @edited 2006-02-11 +*/ + +#ifndef G3D_GCAMERA_H +#define G3D_GCAMERA_H + +#include "G3D/platform.h" +#include "G3D/CoordinateFrame.h" +#include "G3D/Vector3.h" +#include "G3D/Plane.h" + +namespace G3D { + +/** + There is a viewport of width x height size in world space that corresponds to + a screenWidth x screenHeight pixel grid on a + renderDevice->getWidth() x renderDevice->getHeight() + window. + + All viewport arguments are the pixel bounds of the viewport-- e.g., + RenderDevice::getViewport(). + */ +class GCamera { +private: + + /** + Vertical field of view (in radians) + */ + float fieldOfView; + + /** + The image plane depth corresponding to a vertical field of + view, where the film size is 1x1. + */ + float imagePlaneDepth; + + /** + Clipping plane, *not* imaging plane. Positive numbers. + */ + float nearPlane; + + /** + Positive + */ + float farPlane; + + CoordinateFrame cframe; + +public: + + class Frustum { + public: + class Face { + public: + /** Counter clockwise indices into vertexPos */ + int vertexIndex[4]; + + /** The plane containing the face. */ + Plane plane; + }; + + /** The vertices, in homogeneous space. If w == 0, + a vertex is at infinity. */ + Array vertexPos; + + /** The faces in the frustum. When the + far plane is at infinity, there are 5 faces, + otherwise there are 6. The faces are in the order + N,R,L,B,T,[F]. + */ + Array faceArray; + }; + + GCamera(); + + virtual ~GCamera(); + + + CoordinateFrame getCoordinateFrame() const; + void getCoordinateFrame(CoordinateFrame& c) const; + void setCoordinateFrame(const CoordinateFrame& c); + + /** + Sets the horizontal field of view, in radians. The + initial angle is toRadians(55). +

    +
  • toRadians(50) - Telephoto +
  • toRadians(110) - Normal +
  • toRadians(140) - Wide angle +
+ */ + void setFieldOfView(float angle); + + /** + Sets the field of view based on a desired image plane depth + (s') and film dimensions in world space. Depth must be positive. Width, + depth, and height are measured in the same units (meters are + recommended). The field of view will span the diagonal to the + image.

Note: to simulate a 35mm GCamera, set width = + 0.36 mm and height = 0.24 mm. The width and height used are + generally not the pixel dimensions of the image. + */ + void setImagePlaneDepth( + float depth, + const class Rect2D& viewport); + + inline double getFieldOfView() const { + return fieldOfView; + } + + /** + Projects a world space point onto a width x height screen. The + returned coordinate uses pixmap addressing: x = right and y = + down. The resulting z value is rhw. + + If the point is behind the camera, Vector3::inf() is returned. + */ + G3D::Vector3 project( + const G3D::Vector3& point, + const class Rect2D& viewport) const; + + /** + Returns the pixel area covered by a shape of the given + world space area at the given z value (z must be negative). + */ + float worldToScreenSpaceArea(float area, float z, const class Rect2D& viewport) const; + + /** + Returns the world space 3D viewport corners. These + are at the near clipping plane. The corners are constructed + from the nearPlaneZ, getViewportWidth, and getViewportHeight. + "left" and "right" are from the GCamera's perspective. + */ + void get3DViewportCorners( + const class Rect2D& viewport, + Vector3& outUR, + Vector3& outUL, + Vector3& outLL, + Vector3& outLR) const; + + /** + Returns the image plane depth, s', given the current field + of view for film of dimensions width x height. See + setImagePlaneDepth for a discussion of worldspace values width and height. + */ + float getImagePlaneDepth( + const class Rect2D& viewport) const; + + + /** + Returns the world space ray passing through the center of pixel + (x, y) on the image plane. The pixel x and y axes are opposite + the 3D object space axes: (0,0) is the upper left corner of the screen. + They are in viewport coordinates, not screen coordinates. + + + Integer (x, y) values correspond to + the upper left corners of pixels. If you want to cast rays + through pixel centers, add 0.5 to x and y. + */ + Ray worldRay( + float x, + float y, + const class Rect2D& viewport) const; + + + /** + Returns a negative z-value. + */ + inline float getNearPlaneZ() const { + return -nearPlane; + } + + /** + Returns a negative z-value. + */ + inline float getFarPlaneZ() const { + return -farPlane; + } + + inline void setFarPlaneZ(float z) { + debugAssert(z < 0); + farPlane = -z; + } + + inline void setNearPlaneZ(float z) { + debugAssert(z < 0); + nearPlane = -z; + } + + /** + Returns the GCamera space width of the viewport. + */ + float getViewportWidth( + const class Rect2D& viewport) const; + + /** + Returns the GCamera space height of the viewport. + */ + float getViewportHeight( + const class Rect2D& viewport) const; + + /** + Read back a GCamera space z-value at pixel (x, y) from the depth buffer. + double getZValue( + double x, + double y, + const class Rect2D& viewport, + double polygonOffset = 0) const; + */ + + void setPosition(const Vector3& t); + + void lookAt(const Vector3& position, const Vector3& up = Vector3::unitY()); + + /** + Returns the clipping planes of the frustum, in world space. + The planes have normals facing into the view frustum. + + The plane order is guaranteed to be: + Near, Right, Left, Top, Bottom, [Far] + + If the far plane is at infinity, the resulting array will have + 5 planes, otherwise there will be 6. + + The viewport is used only to determine the aspect ratio of the screen; the + absolute dimensions and xy values don't matter. + */ + void getClipPlanes( + const Rect2D& viewport, + Array& outClip) const; + + /** + Returns the world space view frustum, which is a truncated pyramid describing + the volume of space seen by this camera. + */ + void getFrustum(const Rect2D& viewport, GCamera::Frustum& f) const; + + GCamera::Frustum frustum(const Rect2D& viewport) const; + +}; + +} // namespace G3D + +#endif diff --git a/dep/include/g3dlite/G3D/Line.h b/dep/include/g3dlite/G3D/Line.h new file mode 100644 index 00000000000..5dd82c19bc7 --- /dev/null +++ b/dep/include/g3dlite/G3D/Line.h @@ -0,0 +1,85 @@ +/** + @file Line.h + + Line class + + @maintainer Morgan McGuire, matrix@graphics3d.com + + @created 2001-06-02 + @edited 2006-02-28 + */ + +#ifndef G3D_LINE_H +#define G3D_LINE_H + +#include "G3D/platform.h" +#include "G3D/Vector3.h" + +namespace G3D { + +class Plane; + +/** + An infinite 3D line. + */ +class Line { +protected: + + Vector3 _point; + Vector3 _direction; + + Line(const Vector3& point, const Vector3& direction) { + _point = point; + _direction = direction.direction(); + } + +public: + + /** Undefined (provided for creating Array only) */ + inline Line() {} + + virtual ~Line() {} + + /** + Constructs a line from two (not equal) points. + */ + static Line fromTwoPoints(const Vector3 &point1, const Vector3 &point2) { + return Line(point1, point2 - point1); + } + + /** + Creates a line from a point and a (nonzero) direction. + */ + static Line fromPointAndDirection(const Vector3& point, const Vector3& direction) { + return Line(point, direction); + } + + /** + Returns the closest point on the line to point. + */ + Vector3 closestPoint(const Vector3& pt) const; + + /** + Returns the distance between point and the line + */ + double distance(const Vector3& point) const { + return (closestPoint(point) - point).magnitude(); + } + + /** Returns a point on the line */ + Vector3 point() const; + + /** Returns the direction (or negative direction) of the line */ + Vector3 direction() const; + + /** + Returns the point where the line and plane intersect. If there + is no intersection, returns a point at infinity. + */ + Vector3 intersection(const Plane &plane) const; +}; + +};// namespace + + +#endif diff --git a/dep/include/g3dlite/G3D/Matrix3.h b/dep/include/g3dlite/G3D/Matrix3.h new file mode 100644 index 00000000000..19eda497a15 --- /dev/null +++ b/dep/include/g3dlite/G3D/Matrix3.h @@ -0,0 +1,311 @@ +/** + @file Matrix3.h + + 3x3 matrix class + + @maintainer Morgan McGuire, matrix@graphics3d.com + + @cite Portions based on Dave Eberly's Magic Software Library at http://www.magic-software.com + + @created 2001-06-02 + @edited 2006-04-05 + */ + +#ifndef G3D_MATRIX3_H +#define G3D_MATRIX3_H + +#include "G3D/platform.h" +#include "G3D/System.h" +#include "G3D/Vector3.h" +#include "G3D/Vector4.h" + +namespace G3D { + +/** + 3x3 matrix. Do not subclass. + */ +class Matrix3 { +private: + + float elt[3][3]; + + // Hidden operators + bool operator<(const Matrix3&) const; + bool operator>(const Matrix3&) const; + bool operator<=(const Matrix3&) const; + bool operator>=(const Matrix3&) const; + +public: + + /** Initial values are undefined for performance. See also + Matrix3::zero(), Matrix3::identity(), Matrix3::fromAxisAngle, etc.*/ + inline Matrix3() {} + + Matrix3 (const float aafEntry[3][3]); + Matrix3 (const Matrix3& rkMatrix); + Matrix3 (float fEntry00, float fEntry01, float fEntry02, + float fEntry10, float fEntry11, float fEntry12, + float fEntry20, float fEntry21, float fEntry22); + + bool fuzzyEq(const Matrix3& b) const; + + /** Constructs a matrix from a quaternion. + @cite Graphics Gems II, p. 351--354 + @cite Implementation from Watt and Watt, pg 362*/ + Matrix3(const class Quat& q); + + + /** + Sets all elements. + */ + void set(float fEntry00, float fEntry01, float fEntry02, + float fEntry10, float fEntry11, float fEntry12, + float fEntry20, float fEntry21, float fEntry22); + + /** + * member access, allows use of construct mat[r][c] + */ + inline float* operator[] (int iRow) { + debugAssert(iRow >= 0); + debugAssert(iRow < 3); + return (float*)&elt[iRow][0]; + } + + inline const float* operator[] (int iRow) const { + debugAssert(iRow >= 0); + debugAssert(iRow < 3); + return (const float*)&elt[iRow][0]; + } + + inline operator float* () { + return (float*)&elt[0][0]; + } + + inline operator const float* () const{ + return (const float*)&elt[0][0]; + } + + Vector3 getColumn (int iCol) const; + Vector3 getRow (int iRow) const; + void setColumn(int iCol, const Vector3 &vector); + void setRow(int iRow, const Vector3 &vector); + + // assignment and comparison + inline Matrix3& operator= (const Matrix3& rkMatrix) { + System::memcpy(elt, rkMatrix.elt, 9 * sizeof(float)); + return *this; + } + + bool operator== (const Matrix3& rkMatrix) const; + bool operator!= (const Matrix3& rkMatrix) const; + + // arithmetic operations + Matrix3 operator+ (const Matrix3& rkMatrix) const; + Matrix3 operator- (const Matrix3& rkMatrix) const; + /** Matrix-matrix multiply */ + Matrix3 operator* (const Matrix3& rkMatrix) const; + Matrix3 operator- () const; + + Matrix3& operator+= (const Matrix3& rkMatrix); + Matrix3& operator-= (const Matrix3& rkMatrix); + Matrix3& operator*= (const Matrix3& rkMatrix); + + /** + * matrix * vector [3x3 * 3x1 = 3x1] + */ + inline Vector3 operator* (const Vector3& v) const { + Vector3 kProd; + + for (int r = 0; r < 3; ++r) { + kProd[r] = + elt[r][0] * v[0] + + elt[r][1] * v[1] + + elt[r][2] * v[2]; + } + + return kProd; + } + + + /** + * vector * matrix [1x3 * 3x3 = 1x3] + */ + friend Vector3 operator* (const Vector3& rkVector, + const Matrix3& rkMatrix); + + /** + * matrix * scalar + */ + Matrix3 operator* (float fScalar) const; + + /** scalar * matrix */ + friend Matrix3 operator* (double fScalar, const Matrix3& rkMatrix); + friend Matrix3 operator* (float fScalar, const Matrix3& rkMatrix); + friend Matrix3 operator* (int fScalar, const Matrix3& rkMatrix); + +private: + /** Multiplication where out != A and out != B */ + static void _mul(const Matrix3& A, const Matrix3& B, Matrix3& out); +public: + + /** Optimized implementation of out = A * B. It is safe (but slow) to call + with A, B, and out possibly pointer equal to one another.*/ + // This is a static method so that it is not ambiguous whether "this" + // is an input or output argument. + inline static void mul(const Matrix3& A, const Matrix3& B, Matrix3& out) { + if ((&out == &A) || (&out == &B)) { + // We need a temporary anyway, so revert to the stack method. + out = A * B; + } else { + // Optimized in-place multiplication. + _mul(A, B, out); + } + } + +private: + static void _transpose(const Matrix3& A, Matrix3& out); +public: + + /** Optimized implementation of out = A.transpose(). It is safe (but slow) to call + with A and out possibly pointer equal to one another. + + Note that A.transpose() * v can be computed + more efficiently as v * A. + */ + inline static void transpose(const Matrix3& A, Matrix3& out) { + if (&A == &out) { + out = A.transpose(); + } else { + _transpose(A, out); + } + } + + /** Returns true if the rows and column L2 norms are 1.0 and the rows are orthogonal. */ + bool isOrthonormal() const; + + Matrix3 transpose () const; + bool inverse (Matrix3& rkInverse, float fTolerance = 1e-06) const; + Matrix3 inverse (float fTolerance = 1e-06) const; + float determinant () const; + + /** singular value decomposition */ + void singularValueDecomposition (Matrix3& rkL, Vector3& rkS, + Matrix3& rkR) const; + /** singular value decomposition */ + void singularValueComposition (const Matrix3& rkL, + const Vector3& rkS, const Matrix3& rkR); + + /** Gram-Schmidt orthonormalization (applied to columns of rotation matrix) */ + void orthonormalize(); + + /** orthogonal Q, diagonal D, upper triangular U stored as (u01,u02,u12) */ + void qDUDecomposition (Matrix3& rkQ, Vector3& rkD, + Vector3& rkU) const; + + float spectralNorm () const; + + /** matrix must be orthonormal */ + void toAxisAngle(Vector3& rkAxis, float& rfRadians) const; + + static Matrix3 fromAxisAngle(const Vector3& rkAxis, float fRadians); + + /** + * The matrix must be orthonormal. The decomposition is yaw*pitch*roll + * where yaw is rotation about the Up vector, pitch is rotation about the + * right axis, and roll is rotation about the Direction axis. + */ + bool toEulerAnglesXYZ (float& rfYAngle, float& rfPAngle, + float& rfRAngle) const; + bool toEulerAnglesXZY (float& rfYAngle, float& rfPAngle, + float& rfRAngle) const; + bool toEulerAnglesYXZ (float& rfYAngle, float& rfPAngle, + float& rfRAngle) const; + bool toEulerAnglesYZX (float& rfYAngle, float& rfPAngle, + float& rfRAngle) const; + bool toEulerAnglesZXY (float& rfYAngle, float& rfPAngle, + float& rfRAngle) const; + bool toEulerAnglesZYX (float& rfYAngle, float& rfPAngle, + float& rfRAngle) const; + static Matrix3 fromEulerAnglesXYZ (float fYAngle, float fPAngle, float fRAngle); + static Matrix3 fromEulerAnglesXZY (float fYAngle, float fPAngle, float fRAngle); + static Matrix3 fromEulerAnglesYXZ (float fYAngle, float fPAngle, float fRAngle); + static Matrix3 fromEulerAnglesYZX (float fYAngle, float fPAngle, float fRAngle); + static Matrix3 fromEulerAnglesZXY (float fYAngle, float fPAngle, float fRAngle); + static Matrix3 fromEulerAnglesZYX (float fYAngle, float fPAngle, float fRAngle); + + /** eigensolver, matrix must be symmetric */ + void eigenSolveSymmetric (float afEigenvalue[3], + Vector3 akEigenvector[3]) const; + + static void tensorProduct (const Vector3& rkU, const Vector3& rkV, + Matrix3& rkProduct); + std::string toString() const; + + static const float EPSILON; + + // Special values. + // The unguaranteed order of initialization of static variables across + // translation units can be a source of annoying bugs, so now the static + // special values (like Vector3::ZERO, Color3::WHITE, ...) are wrapped + // inside static functions that return references to them. + // These functions are intentionally not inlined, because: + // "You might be tempted to write [...] them as inline functions + // inside their respective header files, but this is something you + // must definitely not do. An inline function can be duplicated + // in every file in which it appears – and this duplication + // includes the static object definition. Because inline functions + // automatically default to internal linkage, this would result in + // having multiple static objects across the various translation + // units, which would certainly cause problems. So you must + // ensure that there is only one definition of each wrapping + // function, and this means not making the wrapping functions inline", + // according to Chapter 10 of "Thinking in C++, 2nd ed. Volume 1" by Bruce Eckel, + // http://www.mindview.net/ + static const Matrix3& zero(); + static const Matrix3& identity(); + + // Deprecated. + /** @deprecated Use Matrix3::zero() */ + static const Matrix3 ZERO; + /** @deprecated Use Matrix3::identity() */ + static const Matrix3 IDENTITY; + +protected: + // support for eigensolver + void tridiagonal (float afDiag[3], float afSubDiag[3]); + bool qLAlgorithm (float afDiag[3], float afSubDiag[3]); + + // support for singular value decomposition + static const float ms_fSvdEpsilon; + static const int ms_iSvdMaxIterations; + static void bidiagonalize (Matrix3& kA, Matrix3& kL, + Matrix3& kR); + static void golubKahanStep (Matrix3& kA, Matrix3& kL, + Matrix3& kR); + + // support for spectral norm + static float maxCubicRoot (float afCoeff[3]); + +}; + + +//---------------------------------------------------------------------------- +/** v * M == M.transpose() * v */ +inline Vector3 operator* (const Vector3& rkPoint, const Matrix3& rkMatrix) { + Vector3 kProd; + + for (int r = 0; r < 3; ++r) { + kProd[r] = + rkPoint[0] * rkMatrix.elt[0][r] + + rkPoint[1] * rkMatrix.elt[1][r] + + rkPoint[2] * rkMatrix.elt[2][r]; + } + + return kProd; +} + + +} // namespace + +#endif + diff --git a/dep/include/g3dlite/G3D/Plane.h b/dep/include/g3dlite/G3D/Plane.h new file mode 100644 index 00000000000..f00c15c0988 --- /dev/null +++ b/dep/include/g3dlite/G3D/Plane.h @@ -0,0 +1,156 @@ +/** + @file Plane.h + + Plane class + + @maintainer Morgan McGuire, matrix@graphics3d.com + + @created 2001-06-02 + @edited 2004-07-18 +*/ + +#ifndef G3D_PLANE_H +#define G3D_PLANE_H + +#include "G3D/platform.h" +#include "G3D/Vector3.h" +#include "G3D/Vector4.h" + +namespace G3D { + +/** + An infinite 2D plane in 3D space. + */ +class Plane { +private: + + /** normal.Dot(x,y,z) = distance */ + Vector3 _normal; + float _distance; + + /** + Assumes the normal has unit length. + */ + Plane(const Vector3& n, float d) : _normal(n), _distance(d) { + } + +public: + + Plane() : _normal(Vector3::unitY()), _distance(0) { + } + + /** + Constructs a plane from three points. + */ + Plane( + const Vector3& point0, + const Vector3& point1, + const Vector3& point2); + + /** + Constructs a plane from three points, where at most two are + at infinity (w = 0, not xyz = inf). + */ + Plane( + Vector4 point0, + Vector4 point1, + Vector4 point2); + + /** + The normal will be unitized. + */ + Plane( + const Vector3& __normal, + const Vector3& point); + + static Plane fromEquation(float a, float b, float c, float d); + + virtual ~Plane() {} + + /** + Returns true if point is on the side the normal points to or + is in the plane. + */ + inline bool halfSpaceContains(Vector3 point) const { + // Clamp to a finite range for testing + point = point.clamp(Vector3::minFinite(), Vector3::maxFinite()); + + // We can get away with putting values *at* the limits of the float32 range into + // a dot product, since the dot product is carried out on float64. + return _normal.dot(point) >= _distance; + } + + /** + Returns true if point is on the side the normal points to or + is in the plane. + */ + inline bool halfSpaceContains(const Vector4& point) const { + if (point.w == 0) { + return _normal.dot(point.xyz()) > 0; + } else { + return halfSpaceContains(point.xyz() / point.w); + } + } + + /** + Returns true if point is on the side the normal points to or + is in the plane. Only call on finite points. Faster than halfSpaceContains. + */ + inline bool halfSpaceContainsFinite(const Vector3& point) const { + debugAssert(point.isFinite()); + return _normal.dot(point) >= _distance; + } + + /** + Returns true if the point is nearly in the plane. + */ + inline bool fuzzyContains(const Vector3 &point) const { + return fuzzyEq(point.dot(_normal), _distance); + } + + inline const Vector3& normal() const { + return _normal; + } + + /** + Returns distance from point to plane. Distance is negative if point is behind (not in plane in direction opposite normal) the plane. + */ + inline float distance(const Vector3& x) const { + return (_normal.dot(x) - _distance); + } + + inline Vector3 closestPoint(const Vector3& x) const { + return x + (_normal * (-distance(x))); + } + + /** Returns normal * distance from origin */ + Vector3 center() const { + return _normal * _distance; + } + + /** + Inverts the facing direction of the plane so the new normal + is the inverse of the old normal. + */ + void flip(); + + /** + Returns the equation in the form: + + normal.Dot(Vector3(x, y, z)) + d = 0 + */ + void getEquation(Vector3 &normal, double& d) const; + void getEquation(Vector3 &normal, float& d) const; + + /** + ax + by + cz + d = 0 + */ + void getEquation(double& a, double& b, double& c, double& d) const; + void getEquation(float& a, float& b, float& c, float& d) const; + + std::string toString() const; +}; + +} // namespace + +#endif diff --git a/dep/include/g3dlite/G3D/Quat.h b/dep/include/g3dlite/G3D/Quat.h new file mode 100644 index 00000000000..b852fe0fd47 --- /dev/null +++ b/dep/include/g3dlite/G3D/Quat.h @@ -0,0 +1,702 @@ +/** + @file Quat.h + + Quaternion + + @maintainer Morgan McGuire, matrix@graphics3d.com + + @created 2002-01-23 + @edited 2006-05-10 + */ + +#ifndef G3D_QUAT_H +#define G3D_QUAT_H + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" +#include "G3D/Vector3.h" +#include "G3D/Matrix3.h" +#include + +namespace G3D { + +/** + Unit quaternions are used in computer graphics to represent + rotation about an axis. Any 3x3 rotation matrix can + be stored as a quaternion. + + A quaternion represents the sum of a real scalar and + an imaginary vector: ix + jy + kz + w. A unit quaternion + representing a rotation by A about axis v has the form + [sin(A/2)*v, cos(A/2)]. For a unit quaternion, q.conj() == q.inverse() + is a rotation by -A about v. -q is the same rotation as q + (negate both the axis and angle). + + A non-unit quaterion q represents the same rotation as + q.unitize() (Dam98 pg 28). + + Although quaternion-vector operations (eg. Quat + Vector3) are + well defined, they are not supported by this class because + they typically are bugs when they appear in code. + + Do not subclass. + + BETA API -- subject to change + @cite Erik B. Dam, Martin Koch, Martin Lillholm, Quaternions, Interpolation and Animation. Technical Report DIKU-TR-98/5, Department of Computer Science, University of Copenhagen, Denmark. 1998. + */ +class Quat { +private: + // Hidden operators + bool operator<(const Quat&) const; + bool operator>(const Quat&) const; + bool operator<=(const Quat&) const; + bool operator>=(const Quat&) const; + +public: + + /** + q = [sin(angle / 2) * axis, cos(angle / 2)] + + In Watt & Watt's notation, s = w, v = (x, y, z) + In the Real-Time Rendering notation, u = (x, y, z), w = w + */ + float x, y, z, w; + + /** + Initializes to a zero degree rotation. + */ + inline Quat() : x(0), y(0), z(0), w(1) {} + + Quat( + const Matrix3& rot); + + inline Quat(float _x, float _y, float _z, float _w) : + x(_x), y(_y), z(_z), w(_w) {} + + /** Defaults to a pure vector quaternion */ + inline Quat(const Vector3& v, float _w = 0) : x(v.x), y(v.y), z(v.z), w(_w) { + } + + /** + The real part of the quaternion. + */ + inline const float& real() const { + return w; + } + + inline float& real() { + return w; + } + + /** Note: two quats can represent the Quat::sameRotation and not be equal. */ + bool fuzzyEq(const Quat& q) { + return G3D::fuzzyEq(x, q.x) && G3D::fuzzyEq(y, q.y) && G3D::fuzzyEq(z, q.z) && G3D::fuzzyEq(w, q.w); + } + + /** True if these quaternions represent the same rotation (note that every rotation is + represented by two values; q and -q). + */ + bool sameRotation(const Quat& q) { + return fuzzyEq(q) || fuzzyEq(-q); + } + + inline Quat operator-() const { + return Quat(-x, -y, -z, -w); + } + + /** + Returns the imaginary part (x, y, z) + */ + inline const Vector3& imag() const { + return *(reinterpret_cast(this)); + } + + inline Vector3& imag() { + return *(reinterpret_cast(this)); + } + + /** q = [sin(angle/2)*axis, cos(angle/2)] */ + static Quat fromAxisAngleRotation( + const Vector3& axis, + float angle); + + /** Returns the axis and angle of rotation represented + by this quaternion (i.e. q = [sin(angle/2)*axis, cos(angle/2)]) */ + void toAxisAngleRotation( + Vector3& axis, + double& angle) const; + + void toAxisAngleRotation( + Vector3& axis, + float& angle) const { + double d; + toAxisAngleRotation(axis, d); + angle = (float)d; + } + + Matrix3 toRotationMatrix() const; + + void toRotationMatrix( + Matrix3& rot) const; + + /** + Spherical linear interpolation: linear interpolation along the + shortest (3D) great-circle route between two quaternions. + + Note: Correct rotations are expected between 0 and PI in the right order. + + @cite Based on Game Physics -- David Eberly pg 538-540 + @param threshold Critical angle between between rotations at which + the algorithm switches to normalized lerp, which is more + numerically stable in those situations. 0.0 will always slerp. + */ + Quat slerp( + const Quat& other, + float alpha, + float threshold = 0.05f) const; + + /** Normalized linear interpolation of quaternion components. */ + Quat nlerp(const Quat& other, float alpha) const; + + /** + Negates the imaginary part. + */ + inline Quat conj() const { + return Quat(-x, -y, -z, w); + } + + inline float sum() const { + return x + y + z + w; + } + + inline float average() const { + return sum() / 4.0f; + } + + inline Quat operator*(float s) const { + return Quat(x * s, y * s, z * s, w * s); + } + + /** @cite Based on Watt & Watt, page 360 */ + friend Quat operator* (float s, const Quat& q); + + inline Quat operator/(float s) const { + return Quat(x / s, y / s, z / s, w / s); + } + + inline float dot(const Quat& other) const { + return (x * other.x) + (y * other.y) + (z * other.z) + (w * other.w); + } + + /** Note that q-1 = q.conj() for a unit quaternion. + @cite Dam99 page 13 */ + inline Quat inverse() const { + return conj() / dot(*this); + } + + Quat operator-(const Quat& other) const; + + Quat operator+(const Quat& other) const; + + /** + Quaternion multiplication (composition of rotations). + Note that this does not commute. + */ + Quat operator*(const Quat& other) const; + + /* (*this) * other.inverse() */ + Quat operator/(const Quat& other) const { + return (*this) * other.inverse(); + } + + + /** Is the magnitude nearly 1.0? */ + inline bool isUnit(float tolerance = 1e-5) const { + return abs(dot(*this) - 1.0f) < tolerance; + } + + + inline float magnitude() const { + return sqrtf(dot(*this)); + } + + inline Quat log() const { + if ((x == 0) && (y == 0) && (z == 0)) { + if (w > 0) { + return Quat(0, 0, 0, ::logf(w)); + } else if (w < 0) { + // Log of a negative number. Multivalued, any number of the form + // (PI * v, ln(-q.w)) + return Quat((float)G3D_PI, 0, 0, ::logf(-w)); + } else { + // log of zero! + return Quat((float)nan(), (float)nan(), (float)nan(), (float)nan()); + } + } else { + // Partly imaginary. + float imagLen = sqrtf(x * x + y * y + z * z); + float len = sqrtf(imagLen * imagLen + w * w); + float theta = atan2f(imagLen, (float)w); + float t = theta / imagLen; + return Quat(t * x, t * y, t * z, ::logf(len)); + } + } + /** log q = [Av, 0] where q = [sin(A) * v, cos(A)]. + Only for unit quaternions + debugAssertM(isUnit(), "Log only defined for unit quaternions"); + // Solve for A in q = [sin(A)*v, cos(A)] + Vector3 u(x, y, z); + double len = u.magnitude(); + + if (len == 0.0) { + return + } + double A = atan2((double)w, len); + Vector3 v = u / len; + + return Quat(v * A, 0); + } + */ + + /** exp q = [sin(A) * v, cos(A)] where q = [Av, 0]. + Only defined for pure-vector quaternions */ + inline Quat exp() const { + debugAssertM(w == 0, "exp only defined for vector quaternions"); + Vector3 u(x, y, z); + float A = u.magnitude(); + Vector3 v = u / A; + return Quat(sinf(A) * v, cosf(A)); + } + + + /** + Raise this quaternion to a power. For a rotation, this is + the effect of rotating x times as much as the original + quaterion. + + Note that q.pow(a).pow(b) == q.pow(a + b) + @cite Dam98 pg 21 + */ + inline Quat pow(float x) const { + return (log() * x).exp(); + } + + + /** + @deprecated + Use toUnit() + */ + inline Quat unitize() const { + float mag2 = dot(*this); + if (G3D::fuzzyEq(mag2, 1.0f)) { + return *this; + } else { + return *this / sqrtf(mag2); + } + } + + /** + Returns a unit quaterion obtained by dividing through by + the magnitude. + */ + inline Quat toUnit() const { + return unitize(); + } + + /** + The linear algebra 2-norm, sqrt(q dot q). This matches + the value used in Dam's 1998 tech report but differs from the + n(q) value used in Eberly's 1999 paper, which is the square of the + norm. + */ + inline float norm() const { + return magnitude(); + } + + // access quaternion as q[0] = q.x, q[1] = q.y, q[2] = q.z, q[3] = q.w + // + // WARNING. These member functions rely on + // (1) Quat not having virtual functions + // (2) the data packed in a 4*sizeof(float) memory block + const float& operator[] (int i) const; + float& operator[] (int i); + + /** Generate uniform random unit quaternion (i.e. random "direction") + @cite From "Uniform Random Rotations", Ken Shoemake, Graphics Gems III. + */ + static Quat unitRandom(); + + // 2-char swizzles + + Vector2 xx() const; + Vector2 yx() const; + Vector2 zx() const; + Vector2 wx() const; + Vector2 xy() const; + Vector2 yy() const; + Vector2 zy() const; + Vector2 wy() const; + Vector2 xz() const; + Vector2 yz() const; + Vector2 zz() const; + Vector2 wz() const; + Vector2 xw() const; + Vector2 yw() const; + Vector2 zw() const; + Vector2 ww() const; + + // 3-char swizzles + + Vector3 xxx() const; + Vector3 yxx() const; + Vector3 zxx() const; + Vector3 wxx() const; + Vector3 xyx() const; + Vector3 yyx() const; + Vector3 zyx() const; + Vector3 wyx() const; + Vector3 xzx() const; + Vector3 yzx() const; + Vector3 zzx() const; + Vector3 wzx() const; + Vector3 xwx() const; + Vector3 ywx() const; + Vector3 zwx() const; + Vector3 wwx() const; + Vector3 xxy() const; + Vector3 yxy() const; + Vector3 zxy() const; + Vector3 wxy() const; + Vector3 xyy() const; + Vector3 yyy() const; + Vector3 zyy() const; + Vector3 wyy() const; + Vector3 xzy() const; + Vector3 yzy() const; + Vector3 zzy() const; + Vector3 wzy() const; + Vector3 xwy() const; + Vector3 ywy() const; + Vector3 zwy() const; + Vector3 wwy() const; + Vector3 xxz() const; + Vector3 yxz() const; + Vector3 zxz() const; + Vector3 wxz() const; + Vector3 xyz() const; + Vector3 yyz() const; + Vector3 zyz() const; + Vector3 wyz() const; + Vector3 xzz() const; + Vector3 yzz() const; + Vector3 zzz() const; + Vector3 wzz() const; + Vector3 xwz() const; + Vector3 ywz() const; + Vector3 zwz() const; + Vector3 wwz() const; + Vector3 xxw() const; + Vector3 yxw() const; + Vector3 zxw() const; + Vector3 wxw() const; + Vector3 xyw() const; + Vector3 yyw() const; + Vector3 zyw() const; + Vector3 wyw() const; + Vector3 xzw() const; + Vector3 yzw() const; + Vector3 zzw() const; + Vector3 wzw() const; + Vector3 xww() const; + Vector3 yww() const; + Vector3 zww() const; + Vector3 www() const; + + // 4-char swizzles + + Vector4 xxxx() const; + Vector4 yxxx() const; + Vector4 zxxx() const; + Vector4 wxxx() const; + Vector4 xyxx() const; + Vector4 yyxx() const; + Vector4 zyxx() const; + Vector4 wyxx() const; + Vector4 xzxx() const; + Vector4 yzxx() const; + Vector4 zzxx() const; + Vector4 wzxx() const; + Vector4 xwxx() const; + Vector4 ywxx() const; + Vector4 zwxx() const; + Vector4 wwxx() const; + Vector4 xxyx() const; + Vector4 yxyx() const; + Vector4 zxyx() const; + Vector4 wxyx() const; + Vector4 xyyx() const; + Vector4 yyyx() const; + Vector4 zyyx() const; + Vector4 wyyx() const; + Vector4 xzyx() const; + Vector4 yzyx() const; + Vector4 zzyx() const; + Vector4 wzyx() const; + Vector4 xwyx() const; + Vector4 ywyx() const; + Vector4 zwyx() const; + Vector4 wwyx() const; + Vector4 xxzx() const; + Vector4 yxzx() const; + Vector4 zxzx() const; + Vector4 wxzx() const; + Vector4 xyzx() const; + Vector4 yyzx() const; + Vector4 zyzx() const; + Vector4 wyzx() const; + Vector4 xzzx() const; + Vector4 yzzx() const; + Vector4 zzzx() const; + Vector4 wzzx() const; + Vector4 xwzx() const; + Vector4 ywzx() const; + Vector4 zwzx() const; + Vector4 wwzx() const; + Vector4 xxwx() const; + Vector4 yxwx() const; + Vector4 zxwx() const; + Vector4 wxwx() const; + Vector4 xywx() const; + Vector4 yywx() const; + Vector4 zywx() const; + Vector4 wywx() const; + Vector4 xzwx() const; + Vector4 yzwx() const; + Vector4 zzwx() const; + Vector4 wzwx() const; + Vector4 xwwx() const; + Vector4 ywwx() const; + Vector4 zwwx() const; + Vector4 wwwx() const; + Vector4 xxxy() const; + Vector4 yxxy() const; + Vector4 zxxy() const; + Vector4 wxxy() const; + Vector4 xyxy() const; + Vector4 yyxy() const; + Vector4 zyxy() const; + Vector4 wyxy() const; + Vector4 xzxy() const; + Vector4 yzxy() const; + Vector4 zzxy() const; + Vector4 wzxy() const; + Vector4 xwxy() const; + Vector4 ywxy() const; + Vector4 zwxy() const; + Vector4 wwxy() const; + Vector4 xxyy() const; + Vector4 yxyy() const; + Vector4 zxyy() const; + Vector4 wxyy() const; + Vector4 xyyy() const; + Vector4 yyyy() const; + Vector4 zyyy() const; + Vector4 wyyy() const; + Vector4 xzyy() const; + Vector4 yzyy() const; + Vector4 zzyy() const; + Vector4 wzyy() const; + Vector4 xwyy() const; + Vector4 ywyy() const; + Vector4 zwyy() const; + Vector4 wwyy() const; + Vector4 xxzy() const; + Vector4 yxzy() const; + Vector4 zxzy() const; + Vector4 wxzy() const; + Vector4 xyzy() const; + Vector4 yyzy() const; + Vector4 zyzy() const; + Vector4 wyzy() const; + Vector4 xzzy() const; + Vector4 yzzy() const; + Vector4 zzzy() const; + Vector4 wzzy() const; + Vector4 xwzy() const; + Vector4 ywzy() const; + Vector4 zwzy() const; + Vector4 wwzy() const; + Vector4 xxwy() const; + Vector4 yxwy() const; + Vector4 zxwy() const; + Vector4 wxwy() const; + Vector4 xywy() const; + Vector4 yywy() const; + Vector4 zywy() const; + Vector4 wywy() const; + Vector4 xzwy() const; + Vector4 yzwy() const; + Vector4 zzwy() const; + Vector4 wzwy() const; + Vector4 xwwy() const; + Vector4 ywwy() const; + Vector4 zwwy() const; + Vector4 wwwy() const; + Vector4 xxxz() const; + Vector4 yxxz() const; + Vector4 zxxz() const; + Vector4 wxxz() const; + Vector4 xyxz() const; + Vector4 yyxz() const; + Vector4 zyxz() const; + Vector4 wyxz() const; + Vector4 xzxz() const; + Vector4 yzxz() const; + Vector4 zzxz() const; + Vector4 wzxz() const; + Vector4 xwxz() const; + Vector4 ywxz() const; + Vector4 zwxz() const; + Vector4 wwxz() const; + Vector4 xxyz() const; + Vector4 yxyz() const; + Vector4 zxyz() const; + Vector4 wxyz() const; + Vector4 xyyz() const; + Vector4 yyyz() const; + Vector4 zyyz() const; + Vector4 wyyz() const; + Vector4 xzyz() const; + Vector4 yzyz() const; + Vector4 zzyz() const; + Vector4 wzyz() const; + Vector4 xwyz() const; + Vector4 ywyz() const; + Vector4 zwyz() const; + Vector4 wwyz() const; + Vector4 xxzz() const; + Vector4 yxzz() const; + Vector4 zxzz() const; + Vector4 wxzz() const; + Vector4 xyzz() const; + Vector4 yyzz() const; + Vector4 zyzz() const; + Vector4 wyzz() const; + Vector4 xzzz() const; + Vector4 yzzz() const; + Vector4 zzzz() const; + Vector4 wzzz() const; + Vector4 xwzz() const; + Vector4 ywzz() const; + Vector4 zwzz() const; + Vector4 wwzz() const; + Vector4 xxwz() const; + Vector4 yxwz() const; + Vector4 zxwz() const; + Vector4 wxwz() const; + Vector4 xywz() const; + Vector4 yywz() const; + Vector4 zywz() const; + Vector4 wywz() const; + Vector4 xzwz() const; + Vector4 yzwz() const; + Vector4 zzwz() const; + Vector4 wzwz() const; + Vector4 xwwz() const; + Vector4 ywwz() const; + Vector4 zwwz() const; + Vector4 wwwz() const; + Vector4 xxxw() const; + Vector4 yxxw() const; + Vector4 zxxw() const; + Vector4 wxxw() const; + Vector4 xyxw() const; + Vector4 yyxw() const; + Vector4 zyxw() const; + Vector4 wyxw() const; + Vector4 xzxw() const; + Vector4 yzxw() const; + Vector4 zzxw() const; + Vector4 wzxw() const; + Vector4 xwxw() const; + Vector4 ywxw() const; + Vector4 zwxw() const; + Vector4 wwxw() const; + Vector4 xxyw() const; + Vector4 yxyw() const; + Vector4 zxyw() const; + Vector4 wxyw() const; + Vector4 xyyw() const; + Vector4 yyyw() const; + Vector4 zyyw() const; + Vector4 wyyw() const; + Vector4 xzyw() const; + Vector4 yzyw() const; + Vector4 zzyw() const; + Vector4 wzyw() const; + Vector4 xwyw() const; + Vector4 ywyw() const; + Vector4 zwyw() const; + Vector4 wwyw() const; + Vector4 xxzw() const; + Vector4 yxzw() const; + Vector4 zxzw() const; + Vector4 wxzw() const; + Vector4 xyzw() const; + Vector4 yyzw() const; + Vector4 zyzw() const; + Vector4 wyzw() const; + Vector4 xzzw() const; + Vector4 yzzw() const; + Vector4 zzzw() const; + Vector4 wzzw() const; + Vector4 xwzw() const; + Vector4 ywzw() const; + Vector4 zwzw() const; + Vector4 wwzw() const; + Vector4 xxww() const; + Vector4 yxww() const; + Vector4 zxww() const; + Vector4 wxww() const; + Vector4 xyww() const; + Vector4 yyww() const; + Vector4 zyww() const; + Vector4 wyww() const; + Vector4 xzww() const; + Vector4 yzww() const; + Vector4 zzww() const; + Vector4 wzww() const; + Vector4 xwww() const; + Vector4 ywww() const; + Vector4 zwww() const; + Vector4 wwww() const; +}; + +inline Quat exp(const Quat& q) { + return q.exp(); +} + +inline Quat log(const Quat& q) { + return q.log(); +} + +inline G3D::Quat operator*(double s, const G3D::Quat& q) { + return q * (float)s; +} + +inline G3D::Quat operator*(float s, const G3D::Quat& q) { + return q * s; +} + +} // Namespace G3D + +// Outside the namespace to avoid overloading confusion for C++ +inline G3D::Quat pow(const G3D::Quat& q, double x) { + return q.pow((float)x); +} + + + +#include "Quat.inl" + +#endif diff --git a/dep/include/g3dlite/G3D/Quat.inl b/dep/include/g3dlite/G3D/Quat.inl new file mode 100644 index 00000000000..705cb0455d4 --- /dev/null +++ b/dep/include/g3dlite/G3D/Quat.inl @@ -0,0 +1,38 @@ +/** + Quat.inl + + @cite Quaternion implementation based on Watt & Watt page 363. + Thanks to Max McGuire for slerp optimizations. + + @maintainer Morgan McGuire, matrix@graphics3d.com + + @created 2002-01-23 + @edited 2004-03-04 + */ + +namespace G3D { + +inline float& Quat::operator[] (int i) { + debugAssert(i >= 0); + debugAssert(i < 4); + return ((float*)this)[i]; +} + +inline const float& Quat::operator[] (int i) const { + debugAssert(i >= 0); + debugAssert(i < 4); + return ((float*)this)[i]; +} + + + +inline Quat Quat::operator-(const Quat& other) const { + return Quat(x - other.x, y - other.y, z - other.z, w - other.w); +} + +inline Quat Quat::operator+(const Quat& other) const { + return Quat(x + other.x, y + other.y, z + other.z, w + other.w); +} + +} + diff --git a/dep/include/g3dlite/G3D/Ray.h b/dep/include/g3dlite/G3D/Ray.h new file mode 100644 index 00000000000..3b54f145c33 --- /dev/null +++ b/dep/include/g3dlite/G3D/Ray.h @@ -0,0 +1,327 @@ +/** + @file Ray.h + + Ray class + + @maintainer Morgan McGuire, matrix@graphics3d.com + + @created 2002-07-12 + @edited 2006-02-21 + */ + +#ifndef G3D_RAY_H +#define G3D_RAY_H + +#include "G3D/platform.h" +#include "G3D/Vector3.h" +#include "G3D/Triangle.h" + +namespace G3D { + +/** + A 3D Ray. + */ +class Ray { +private: + Ray(const Vector3& origin, const Vector3& direction) { + this->origin = origin; + this->direction = direction; + } + +public: + Vector3 origin; + + /** + Not unit length + */ + Vector3 direction; + + Ray() : origin(Vector3::zero()), direction(Vector3::zero()) {} + + virtual ~Ray() {} + + /** + Creates a Ray from a origin and a (nonzero) direction. + */ + static Ray fromOriginAndDirection(const Vector3& point, const Vector3& direction) { + return Ray(point, direction); + } + + Ray unit() const { + return Ray(origin, direction.unit()); + } + + /** + Returns the closest point on the Ray to point. + */ + Vector3 closestPoint(const Vector3& point) const { + float t = direction.dot(point - this->origin); + if (t < 0) { + return this->origin; + } else { + return this->origin + direction * t; + } + } + + /** + Returns the closest distance between point and the Ray + */ + float distance(const Vector3& point) const { + return (closestPoint(point) - point).magnitude(); + } + + /** + Returns the point where the Ray and plane intersect. If there + is no intersection, returns a point at infinity. + + Planes are considered one-sided, so the ray will not intersect + a plane where the normal faces in the traveling direction. + */ + Vector3 intersection(const class Plane& plane) const; + + /** + Returns the distance until intersection with the (solid) sphere. + Will be 0 if inside the sphere, inf if there is no intersection. + + The ray direction is not normalized. If the ray direction + has unit length, the distance from the origin to intersection + is equal to the time. If the direction does not have unit length, + the distance = time * direction.length(). + + See also the G3D::CollisionDetection "movingPoint" methods, + which give more information about the intersection. + */ + float intersectionTime(const class Sphere& sphere) const; + + float intersectionTime(const class Plane& plane) const; + + float intersectionTime(const class Box& box) const; + + float intersectionTime(const class AABox& box) const; + + /** + The three extra arguments are the weights of vertices 0, 1, and 2 + at the intersection point; they are useful for texture mapping + and interpolated normals. + */ + float intersectionTime( + const Vector3& v0, const Vector3& v1, const Vector3& v2, + const Vector3& edge01, const Vector3& edge02, + double& w0, double& w1, double& w2) const; + + /** + Ray-triangle intersection for a 1-sided triangle. Fastest version. + @cite http://www.acm.org/jgt/papers/MollerTrumbore97/ + http://www.graphics.cornell.edu/pubs/1997/MT97.html + */ + inline float intersectionTime( + const Vector3& vert0, + const Vector3& vert1, + const Vector3& vert2, + const Vector3& edge01, + const Vector3& edge02) const; + + + inline float intersectionTime( + const Vector3& vert0, + const Vector3& vert1, + const Vector3& vert2) const { + + return intersectionTime(vert0, vert1, vert2, vert1 - vert0, vert2 - vert0); + } + + + inline float intersectionTime( + const Vector3& vert0, + const Vector3& vert1, + const Vector3& vert2, + double& w0, + double& w1, + double& w2) const { + + return intersectionTime(vert0, vert1, vert2, vert1 - vert0, vert2 - vert0, w0, w1, w2); + } + + /* One-sided triangle + */ + inline float intersectionTime(const Triangle& triangle) const { + return intersectionTime( + triangle.vertex(0), triangle.vertex(1), triangle.vertex(2), + triangle.edge01, triangle.edge02); + } + + inline float intersectionTime( + const Triangle& triangle, + double& w0, + double& w1, + double& w2) const { + return intersectionTime(triangle.vertex(0), triangle.vertex(1), triangle.vertex(2), + triangle.edge01, triangle.edge02, w0, w1, w2); + } + + /** Refracts about the normal + using G3D::Vector3::refractionDirection + and bumps the ray slightly from the newOrigin. */ + Ray refract( + const Vector3& newOrigin, + const Vector3& normal, + float iInside, + float iOutside) const; + + /** Reflects about the normal + using G3D::Vector3::reflectionDirection + and bumps the ray slightly from + the newOrigin. */ + Ray reflect( + const Vector3& newOrigin, + const Vector3& normal) const; +}; + + +#define EPSILON 0.000001 +#define CROSS(dest,v1,v2) \ + dest[0]=v1[1]*v2[2]-v1[2]*v2[1]; \ + dest[1]=v1[2]*v2[0]-v1[0]*v2[2]; \ + dest[2]=v1[0]*v2[1]-v1[1]*v2[0]; + +#define DOT(v1,v2) (v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2]) + +#define SUB(dest,v1,v2) \ + dest[0]=v1[0]-v2[0]; \ + dest[1]=v1[1]-v2[1]; \ + dest[2]=v1[2]-v2[2]; + +inline float Ray::intersectionTime( + const Vector3& vert0, + const Vector3& vert1, + const Vector3& vert2, + const Vector3& edge1, + const Vector3& edge2) const { + + (void)vert1; + (void)vert2; + + // Barycenteric coords + float u, v; + + float tvec[3], pvec[3], qvec[3]; + + // begin calculating determinant - also used to calculate U parameter + CROSS(pvec, direction, edge2); + + // if determinant is near zero, ray lies in plane of triangle + const float det = DOT(edge1, pvec); + + if (det < EPSILON) { + return (float)inf(); + } + + // calculate distance from vert0 to ray origin + SUB(tvec, origin, vert0); + + // calculate U parameter and test bounds + u = DOT(tvec, pvec); + if ((u < 0.0f) || (u > det)) { + // Hit the plane outside the triangle + return (float)inf(); + } + + // prepare to test V parameter + CROSS(qvec, tvec, edge1); + + // calculate V parameter and test bounds + v = DOT(direction, qvec); + if ((v < 0.0f) || (u + v > det)) { + // Hit the plane outside the triangle + return (float)inf(); + } + + + // Case where we don't need correct (u, v): + const float t = DOT(edge2, qvec); + + if (t >= 0.0f) { + // Note that det must be positive + return t / det; + } else { + // We had to travel backwards in time to intersect + return (float)inf(); + } +} + + +inline float Ray::intersectionTime( + const Vector3& vert0, + const Vector3& vert1, + const Vector3& vert2, + const Vector3& edge1, + const Vector3& edge2, + double& w0, + double& w1, + double& w2) const { + + (void)vert1; + (void)vert2; + + // Barycenteric coords + float u, v; + + float tvec[3], pvec[3], qvec[3]; + + // begin calculating determinant - also used to calculate U parameter + CROSS(pvec, direction, edge2); + + // if determinant is near zero, ray lies in plane of triangle + const float det = DOT(edge1, pvec); + + if (det < EPSILON) { + return (float)inf(); + } + + // calculate distance from vert0 to ray origin + SUB(tvec, origin, vert0); + + // calculate U parameter and test bounds + u = DOT(tvec, pvec); + if ((u < 0.0f) || (u > det)) { + // Hit the plane outside the triangle + return (float)inf(); + } + + // prepare to test V parameter + CROSS(qvec, tvec, edge1); + + // calculate V parameter and test bounds + v = DOT(direction, qvec); + if ((v < 0.0f) || (u + v > det)) { + // Hit the plane outside the triangle + return (float)inf(); + } + + float t = DOT(edge2, qvec); + + if (t >= 0) { + const float inv_det = 1.0f / det; + t *= inv_det; + u *= inv_det; + v *= inv_det; + + w0 = (1.0f - u - v); + w1 = u; + w2 = v; + + return t; + } else { + // We had to travel backwards in time to intersect + return (float)inf(); + } +} + +#undef EPSILON +#undef CROSS +#undef DOT +#undef SUB + +}// namespace + +#endif diff --git a/dep/include/g3dlite/G3D/RegistryUtil.h b/dep/include/g3dlite/G3D/RegistryUtil.h new file mode 100644 index 00000000000..97de8d06725 --- /dev/null +++ b/dep/include/g3dlite/G3D/RegistryUtil.h @@ -0,0 +1,86 @@ +/** + @file RegistryUtil.h + + @created 2006-04-06 + @edited 2006-04-06 + + Copyright 2000-2006, Morgan McGuire. + All rights reserved. +*/ + +#ifndef G3D_REGISTRYUTIL_H +#define G3D_REGISTRYUTIL_H + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" + +// This file is only used on Windows +#ifdef G3D_WIN32 + +#include + +namespace G3D { + +/** + Provides generalized Windows registry querying. + + All key names are one string in the format: + "[base key]\[sub-keys]\value" + + [base key] can be any of the following: + HKEY_CLASSES_ROOT + HKEY_CURRENT_CONFIG + HKEY_CURRENT_USER + HKEY_LOCAL_MACHINE + HKEY_PERFORMANCE_DATA + HKEY_PERFORMANCE_NLSTEXT + HKEY_PERFORMANCE_TEXT + HKEY_USERS + + keyExists() should be used to validate a key before reading or writing + to ensure that a debug assert or false return is for a different error. +*/ +class RegistryUtil { + +public: + /** returns true if the key exists */ + static bool keyExists(const std::string& key); + + /** returns false if the key could not be read for any reason. */ + static bool readInt32(const std::string& key, int32& valueData); + + /** + Reads an arbitrary amount of data from a binary registry key. + returns false if the key could not be read for any reason. + + @beta + @param valueData pointer to the output buffer of sufficient size. Pass NULL as valueData in order to have available data size returned in dataSize. + @param dataSize size of the output buffer. When NULL is passed for valueData, contains the size of available data on successful return. + */ + static bool readBytes(const std::string& key, uint8* valueData, uint32& dataSize); + + /** returns false if the key could not be read for any reason. */ + static bool readString(const std::string& key, std::string& valueData); + + /** returns false if the key could not be written for any reason. */ + static bool writeInt32(const std::string& key, int32 valueData); + + /** + Writes an arbitrary amount of data to a binary registry key. + returns false if the key could not be written for any reason. + + @param valueData pointer to the input buffer + @param dataSize size of the input buffer that should be written + */ + static bool writeBytes(const std::string& key, const uint8* valueData, uint32 dataSize); + + /** returns false if the key could not be written for any reason. */ + static bool writeString(const std::string& key, const std::string& valueData); + +}; + +} // namespace G3D + +#endif // G3D_WIN32 + +#endif // G3D_REGISTRYTUIL_H \ No newline at end of file diff --git a/dep/include/g3dlite/G3D/Sphere.h b/dep/include/g3dlite/G3D/Sphere.h new file mode 100644 index 00000000000..39097e01850 --- /dev/null +++ b/dep/include/g3dlite/G3D/Sphere.h @@ -0,0 +1,128 @@ +/** + @file Sphere.h + + Sphere class + + @maintainer Morgan McGuire, matrix@graphics3d.com + + @created 2001-06-02 + @edited 2004-07-05 + */ + +#ifndef G3D_SPHERE_H +#define G3D_SPHERE_H + +#include "G3D/platform.h" +#include "G3D/Vector3.h" +#include "G3D/Array.h" +#include "G3D/Sphere.h" + +namespace G3D { + +/** + Sphere. + */ +class Sphere { +private: + + static int32 dummy; + +public: + Vector3 center; + float radius; + + Sphere() { + center = Vector3::zero(); + radius = 0; + } + + Sphere( + const Vector3& center, + float radius) { + + this->center = center; + this->radius = radius; + } + + virtual ~Sphere() {} + + bool operator==(const Sphere& other) const { + return (center == other.center) && (radius == other.radius); + } + + bool operator!=(const Sphere& other) const { + return !((center == other.center) && (radius == other.radius)); + } + + /** + Returns true if point is less than or equal to radius away from + the center. + */ + bool contains(const Vector3& point) const; + +/** + @deprecated Use culledBy(Array&) + */ + bool culledBy( + const class Plane* plane, + int numPlanes, + int32& cullingPlaneIndex, + const uint32 testMask, + uint32& childMask) const; + + /** + @deprecated Use culledBy(Array&) + */ + bool culledBy( + const class Plane* plane, + int numPlanes, + int32& cullingPlaneIndex = dummy, + const uint32 testMask = -1) const; + + /** + See AABox::culledBy + */ + bool culledBy( + const Array& plane, + int32& cullingPlaneIndex, + const uint32 testMask, + uint32& childMask) const; + + /** + Conservative culling test that does not produce a mask for children. + */ + bool culledBy( + const Array& plane, + int32& cullingPlaneIndex = dummy, + const uint32 testMask = -1) const; + virtual std::string toString() const; + + float volume() const; + + /** @deprecated */ + float surfaceArea() const; + + inline float area() const { + return surfaceArea(); + } + + /** + Uniformly distributed on the surface. + */ + Vector3 randomSurfacePoint() const; + + /** + Uniformly distributed on the interior (includes surface) + */ + Vector3 randomInteriorPoint() const; + + void getBounds(class AABox& out) const; +}; + +} // namespace + +inline unsigned int hashCode(const G3D::Sphere& sphere) { + return (unsigned int)(hashCode(sphere.center) + (sphere.radius * 13)); +} + +#endif diff --git a/dep/include/g3dlite/G3D/System.h b/dep/include/g3dlite/G3D/System.h new file mode 100644 index 00000000000..507b44670da --- /dev/null +++ b/dep/include/g3dlite/G3D/System.h @@ -0,0 +1,122 @@ +/** + @file System.h + + @maintainer Morgan McGuire, matrix@graphics3d.com + + @cite Rob Wyatt http://www.gamasutra.com/features/wyatts_world/19990709/processor_detection_01.htm + @cite Benjamin Jurke http://www.flipcode.com/cgi-bin/msg.cgi?showThread=COTD-ProcessorDetectionClass&forum=cotd&id=-1 + @cite Michael Herf http://www.stereopsis.com/memcpy.html + + @created 2003-01-25 + @edited 2006-04-26 + */ + +#ifndef G3D_SYSTEM_H +#define G3D_SYSTEM_H + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" +#include + +#ifdef G3D_OSX +# include +#endif + + +namespace G3D { + +typedef double RealTime; + +class System { +public: + + /** Called automatically by the other System routines.*/ + static void init(); + + /** + Guarantees that the start of the array is aligned to the + specified number of bytes. + */ + static void* alignedMalloc(size_t bytes, size_t alignment); + + /** + Uses pooled storage to optimize small allocations (1 byte to 5 kilobytes). + Can be 10x to 100x faster than calling ::malloc or new. + + The result must be freed with free. + + Threadsafe on Win32. + + @sa calloc realloc OutOfMemoryCallback free + */ + static void* malloc(size_t bytes); + + static void* calloc(size_t n, size_t x); + + /** + @param size Size of memory that the system was trying to allocate + @param recoverable If true, the system will attempt to allocate again + if the callback returns true. If false, malloc is going to return + NULL and this invocation is just to notify the application. + @return Return true to force malloc to attempt allocation again if the + error was recoverable. + */ + typedef bool (*OutOfMemoryCallback)(size_t size, bool recoverable); + + /** + When System::malloc fails to allocate memory because the system is + out of memory, it invokes this handler (if it is not NULL). + The argument to the callback is the amount of memory that malloc + was trying to allocate when it ran out. If the callback returns + true, System::malloc will attempt to allocate the memory again. + If the callback returns false, then System::malloc will return NULL. + + You can use outOfMemoryCallback to free data structures or to + register the failure. + */ + static OutOfMemoryCallback outOfMemoryCallback; + + /** + Version of realloc that works with System::malloc. + */ + static void* realloc(void* block, size_t bytes); + + /** Returns a string describing how well System::malloc is using its internal pooled storage. + "heap" memory was slow to allocate; the other data sizes are comparatively fast.*/ + static std::string mallocPerformance(); + static void resetMallocPerformanceCounters(); + + /** + Returns a string describing the current usage of the buffer pools used for + optimizing System::malloc. + */ + static std::string mallocStatus(); + + /** + Free data allocated with System::malloc. + + Threadsafe on Win32. + */ + static void free(void* p); + + /** + Frees memory allocated with alignedMalloc. + */ + static void alignedFree(void* ptr); + + /** An implementation of memcpy that may be up to 2x as fast as the C library + one on some processors. Guaranteed to have the same behavior as memcpy + in all cases. */ + static void memcpy(void* dst, const void* src, size_t numBytes); + + /** An implementation of memset that may be up to 2x as fast as the C library + one on some processors. Guaranteed to have the same behavior as memset + in all cases. */ + static void memset(void* dst, uint8 value, size_t numBytes); + +}; + + +} // namespace + +#endif diff --git a/dep/include/g3dlite/G3D/Table.h b/dep/include/g3dlite/G3D/Table.h new file mode 100644 index 00000000000..285d774d24a --- /dev/null +++ b/dep/include/g3dlite/G3D/Table.h @@ -0,0 +1,695 @@ +/** + @file Table.h + + Templated hash table class. + + @maintainer Morgan McGuire, matrix@graphics3d.com + @created 2001-04-22 + @edited 2006-10-14 + Copyright 2000-2006, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_TABLE_H +#define G3D_TABLE_H + +#include "G3D/platform.h" +#include "G3D/Array.h" +#include "G3D/debug.h" +#include "G3D/System.h" +#include "G3D/g3dmath.h" +#include "G3D/Crypto.h" +#include +#include + +#ifdef G3D_WIN32 +# pragma warning (push) + // Debug name too long warning +# pragma warning (disable : 4786) +#endif + + +template +struct GHashCode{}; + +template <> +struct GHashCode +{ + size_t operator()(int key) const { return static_cast(key); } +}; + +template <> +struct GHashCode +{ + size_t operator()(G3D::uint32 key) const { return static_cast(key); } +}; + +template <> +struct GHashCode +{ + size_t operator()(G3D::uint64 key) const { return static_cast(key); } +}; + +template <> +struct GHashCode +{ + size_t operator()(const void* key) const { return reinterpret_cast(key); } +}; + +template +struct GHashCode +{ + size_t operator()(const T* key) const { return reinterpret_cast(key); } +}; + +template <> +struct GHashCode +{ + size_t operator()(const std::string& key) const { return static_cast(G3D::Crypto::crc32(key.c_str(), key.size())); } +}; + +template <> +struct GHashCode +{ + size_t operator()(const std::string& key) const { return static_cast(G3D::Crypto::crc32(key.c_str(), key.size())); } +}; + +namespace G3D { + + +/** + An unordered data structure mapping keys to values. + + Key must be a pointer, an int, a std::string, a class with a hashCode() method, + or provide overloads for: + +

+    template<> struct GHashCode {
+        size_t operator()(Key key) const { return reinterpret_cast( ... ); }
+    };
+
+   bool operator==(const Key&, const Key&);
+  
+ + G3D pre-defines GHashCode functions for common types (like int and std::string). + If you use a Table with a different type you must write those functions yourself. For example, + an enum would use: + +
+    template<> struct GHashCode {
+        size_t operator()(MyEnum key) const { return reinterpret_cast( key ); }
+    };
+  
+ + And rely on the default enum operator==. + + + Periodically check that debugGetLoad() is low (> 0.1). When it gets near + 1.0 your hash function is badly designed and maps too many inputs to + the same output. + */ +template > +class Table { +public: + + /** + The pairs returned by iterator. + */ + class Entry { + public: + Key key; + Value value; + }; + +private: + /** + Linked list nodes used internally by HashTable. + */ + class Node { + public: + size_t hashCode; + Entry entry; + Node* next; + + + /** Provide pooled allocation for speed. */ + inline void* operator new (size_t size) { + return System::malloc(size); + } + + inline void operator delete (void* p) { + System::free(p); + } + + + Node(Key key, Value value, size_t hashCode, Node* next) { + this->entry.key = key; + this->entry.value = value; + this->hashCode = hashCode; + this->next = next; + } + + /** + Clones a whole chain; + */ + Node* clone() { + return new Node(this->entry.key, this->entry.value, hashCode, (next == NULL) ? NULL : next->clone()); + } + }; + + HashFunc m_HashFunc; + + /** + Number of elements in the table. + */ + size_t _size; + + /** + Array of Node*. + We don't use Array because Table is lower level. + Some elements may be NULL. + */ + Node** bucket; + + /** + Length of the bucket array. + */ + size_t numBuckets; + + /** + Re-hashes for a larger bucket size. + */ + void resize(size_t numBuckets) { + + Node** oldBucket = bucket; + bucket = (Node**)System::alignedMalloc(sizeof(Node*) * numBuckets, 16); + System::memset(bucket, 0, sizeof(Node*) * numBuckets); + + for (size_t b = 0; b < this->numBuckets; b++) { + Node* node = oldBucket[b]; + + while (node != NULL) { + Node* nextNode = node->next; + + // insert at the head of the list for bucket[i] + size_t i = node->hashCode % numBuckets; + node->next = bucket[i]; + bucket[i] = node; + + node = nextNode; + } + } + + System::alignedFree(oldBucket); + this->numBuckets = numBuckets; + } + + void copyFrom(const Table& h) { + this->_size = h._size; + this->numBuckets = h.numBuckets; + this->bucket = (Node**)System::alignedMalloc(sizeof(Node*) * numBuckets, 16); + System::memset(this->bucket, 0, sizeof(Node*) * numBuckets); + for (size_t b = 0; b < this->numBuckets; b++) { + if (h.bucket[b] != NULL) { + bucket[b] = h.bucket[b]->clone(); + } + } + } + + /** + Frees the heap structures for the nodes. + */ + void freeMemory() { + for (size_t b = 0; b < numBuckets; b++) { + Node* node = bucket[b]; + while (node != NULL) { + Node* next = node->next; + delete node; + node = next; + } + } + System::alignedFree(bucket); + bucket = NULL; + numBuckets = 0; + _size = 0; + } + +public: + + /** + Creates an empty hash table. This causes some heap allocation to occur. + */ + Table() { + numBuckets = 10; + _size = 0; + bucket = (Node**)System::alignedMalloc(sizeof(Node*) * numBuckets, 16); + System::memset(bucket, 0, sizeof(Node*) * numBuckets); + } + + /** + Destroys all of the memory allocated by the table, but does not + call delete on keys or values if they are pointers. If you want to + deallocate things that the table points at, use getKeys() and Array::deleteAll() + to delete them. + */ + virtual ~Table() { + freeMemory(); + } + + Table(const Table& h) { + this->copyFrom(h); + } + + Table& operator=(const Table& h) { + // No need to copy if the argument is this + if (this != &h) { + // Free the existing nodes + freeMemory(); + this->copyFrom(h); + } + return *this; + } + + /** + Returns the length of the deepest bucket. + */ + size_t debugGetDeepestBucketSize() const { + size_t deepest = 0; + + for (size_t b = 0; b < numBuckets; b++) { + size_t count = 0; + Node* node = bucket[b]; + while (node != NULL) { + node = node->next; + ++count; + } + + if (count > deepest) { + deepest = count; + } + } + + return deepest; + } + + /** + A small load (close to zero) means the hash table is acting very + efficiently most of the time. A large load (close to 1) means + the hash table is acting poorly-- all operations will be very slow. + A large load will result from a bad hash function that maps too + many keys to the same code. + */ + double debugGetLoad() const { + return debugGetDeepestBucketSize() / (double)size(); + } + + /** + Returns the number of buckets. + */ + size_t debugGetNumBuckets() const { + return numBuckets; + } + + /** + C++ STL style iterator variable. See begin(). + */ + class Iterator { + private: + friend class Table; + + /** + Bucket index. + */ + size_t index; + + /** + Linked list node. + */ + Node* node; + Table* table; + size_t numBuckets; + Node** bucket; + bool isDone; + + /** + Creates the end iterator. + */ + Iterator(const Table* table) : table(const_cast*>(table)) { + isDone = true; + } + + Iterator(const Table* table, size_t numBuckets, Node** bucket) : + table(const_cast*>(table)), + numBuckets(numBuckets), + bucket(bucket) { + + if (numBuckets == 0) { + // Empty table + isDone = true; + return; + } + + index = 0; + node = bucket[index]; + isDone = false; + findNext(); + } + + /** + Finds the next element, setting isDone if one can't be found. + Looks at the current element first. + */ + void findNext() { + while (node == NULL) { + index++; + if (index >= numBuckets) { + isDone = true; + break; + } else { + node = bucket[index]; + } + } + } + + public: + inline bool operator!=(const Iterator& other) const { + return !(*this == other); + } + + bool operator==(const Iterator& other) const { + if (other.isDone || isDone) { + // Common case; check against isDone. + return (isDone == other.isDone) && (other.table == table); + } else { + return + (table == other.table) && + (node == other.node) && + (index == other.index); + } + } + + /** + Pre increment. + */ + Iterator& operator++() { + node = node->next; + findNext(); + return *this; + } + + /** + Post increment (slower than preincrement). + */ + Iterator operator++(int) { + Iterator old = *this; + ++(*this); + return old; + } + + const Entry& operator*() const { + return node->entry; + } + + Entry* operator->() const { + return &(node->entry); + } + + operator Entry*() const { + return &(node->entry); + } + }; + + + /** + C++ STL style iterator method. Returns the first Entry, which + contains a key and value. Use preincrement (++entry) to get to + the next element. Do not modify the table while iterating. + */ + Iterator begin() const { + return Iterator(this, numBuckets, bucket); + } + + /** + C++ STL style iterator method. Returns one after the last iterator + element. + */ + const Iterator end() const { + return Iterator(this); + } + + /** + Removes all elements + */ + void clear() { + freeMemory(); + numBuckets = 20; + _size = 0; + bucket = (Node**)System::alignedMalloc(sizeof(Node*) * numBuckets, 16); + System::memset(bucket, 0, sizeof(Node*) * numBuckets); + } + + + /** + Returns the number of keys. + */ + size_t size() const { + return _size; + } + + + /** + If you insert a pointer into the key or value of a table, you are + responsible for deallocating the object eventually. Inserting + key into a table is O(1), but may cause a potentially slow rehashing. + */ + void set(const Key& key, const Value& value) { + size_t code = m_HashFunc(key); + size_t b = code % numBuckets; + + // Go to the bucket + Node* n = bucket[b]; + + // No bucket, so this must be the first + if (n == NULL) { + bucket[b] = new Node(key, value, code, NULL); + ++_size; + return; + } + + size_t bucketLength = 1; + + // Sometimes a bad hash code will cause all elements + // to collide. Detect this case and don't rehash when + // it occurs; nothing good will come from the rehashing. + bool allSameCode = true; + + // Try to find the node + do { + allSameCode = allSameCode && (code == n->hashCode); + + if ((code == n->hashCode) && (n->entry.key == key)) { + // Replace the existing node. + n->entry.value = value; + return; + } + + n = n->next; + ++bucketLength; + } while (n != NULL); + + const size_t maxBucketLength = 5; + if ((bucketLength > maxBucketLength) & ! allSameCode && (numBuckets < _size * 20)) { + // This bucket was really large; rehash if all elements + // don't have the same hashcode the number of buckets is reasonable. + resize(numBuckets * 2 + 1); + } + + // Not found; insert at the head. + b = code % numBuckets; + bucket[b] = new Node(key, value, code, bucket[b]); + ++_size; + } + + /** + Removes an element from the table if it is present. It is an error + to remove an element that isn't present. + */ + void remove(const Key& key) { + + size_t code = m_HashFunc(key); + size_t b = code % numBuckets; + + // Go to the bucket + Node* n = bucket[b]; + + // Make sure it was found + alwaysAssertM(n != NULL, "Tried to remove a key that was not in the table."); + + Node* previous = NULL; + + // Try to find the node + do { + if ((code == n->hashCode) && (n->entry.key == key)) { + // This is the node; remove it + if (previous == NULL) { + bucket[b] = n->next; + } else { + previous->next = n->next; + } + // Delete the node + delete n; + --_size; + return; + } + + previous = n; + n = n->next; + } while (n != NULL); + + + alwaysAssertM(false, "Tried to remove a key that was not in the table."); + } + + /** + Returns the value associated with key. + @deprecated Use get(key, val) or + */ + Value& get(const Key& key) const { + + size_t code = m_HashFunc(key); + size_t b = code % numBuckets; + + Node* node = bucket[b]; + + while (node != NULL) { + if ((node->hashCode == code) && (node->entry.key == key)) { + return node->entry.value; + } + node = node->next; + } + + debugAssertM(false, "Key not found"); + // The next line is here just to make + // a compiler warning go away. + return node->entry.value; + } + + /** + If the key is present in the table, val is set to the associated value and returns true. + If the key is not present, returns false. + */ + bool get(const Key& key, Value& val) const { + size_t code = m_HashFunc(key); + size_t b = code % numBuckets; + + Node* node = bucket[b]; + + while (node != NULL) { + if ((node->hashCode == code) && (node->entry.key == key)) { + // found key + val = node->entry.value; + return true; + } + node = node->next; + } + + // Failed to find key + return false; + } + + /** + Returns true if key is in the table. + */ + bool containsKey(const Key& key) const { + size_t code = m_HashFunc(key); + size_t b = code % numBuckets; + + Node* node = bucket[b]; + + while (node != NULL) { + if ((node->hashCode == code) && (node->entry.key == key)) { + return true; + } + node = node->next; + } while (node != NULL); + + return false; + } + + + /** + Short syntax for get. + */ + inline Value& operator[](const Key &key) const { + return get(key); + } + + + /** + Returns an array of all of the keys in the table. + You can iterate over the keys to get the values. + */ + Array getKeys() const { + Array keyArray; + getKeys(keyArray); + return keyArray; + } + + void getKeys(Array& keyArray) const { + keyArray.resize(0, DONT_SHRINK_UNDERLYING_ARRAY); + for (size_t i = 0; i < numBuckets; i++) { + Node* node = bucket[i]; + while (node != NULL) { + keyArray.append(node->entry.key); + node = node->next; + } + } + } + + /** + Calls delete on all of the keys. Does not clear the table, + however, so you are left with a table of dangling pointers. + + Same as getKeys().deleteAll(); + + To delete all of the values, you may want something like +
+        Array keys = table.getKeys();
+        Set value;
+        for (int k = 0; k < keys.length(); k++) {
+           value.insert(keys[k]);
+        }
+        value.getMembers().deleteAll();
+        keys.deleteAll();
+    
+ */ + void deleteKeys() { + getKeys().deleteAll(); + } + + /** + Calls delete on all of the values. This is unsafe-- + do not call unless you know that each value appears + at most once. + + Does not clear the table, so you are left with a table + of dangling pointers. + */ + void deleteValues() { + for (int i = 0; i < numBuckets; i++) { + Node* node = bucket[i]; + while (node != NULL) { + delete node->entry.value; + node = node->next; + } + } + } +}; + +} // namespace + +#ifdef G3D_WIN32 +# pragma warning (pop) +#endif + +#endif diff --git a/dep/include/g3dlite/G3D/Triangle.h b/dep/include/g3dlite/G3D/Triangle.h new file mode 100644 index 00000000000..cbe46a8cf50 --- /dev/null +++ b/dep/include/g3dlite/G3D/Triangle.h @@ -0,0 +1,116 @@ +/** + @file Triangle.h + + @maintainer Morgan McGuire, matrix@graphics3d.com + + @created 2003-04-05 + @edited 2004-03-14 + + @cite Random point method by Greg Turk, Generating random points in triangles. In A. S. Glassner, ed., Graphics Gems, pp. 24-28. Academic Press, 1990 + + Copyright 2000-2006, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_TRIANGLE_H +#define G3D_TRIANGLE_H + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" +#include "G3D/Vector3.h" +#include "G3D/Plane.h" +#include + +namespace G3D { + +/** + A generic triangle representation. This should not be used + as the underlying triangle for creating models; it is intended + for providing fast property queries but requires a lot of + storage and is mostly immutable. + */ +class Triangle { +private: + friend class CollisionDetection; + friend class Ray; + + Vector3 _vertex[3]; + + /** edgeDirection[i] is the normalized vector v[i+1] - v[i] */ + Vector3 edgeDirection[3]; + double edgeMagnitude[3]; + Plane _plane; + Vector3::Axis _primaryAxis; + + /** vertex[1] - vertex[0] */ + Vector3 edge01; + /** vertex[2] - vertex[0] */ + Vector3 edge02; + + float _area; + + void init(const Vector3& v0, const Vector3& v1, const Vector3& v2); + +public: + + Triangle(); + + Triangle(const Vector3& v0, const Vector3& v1, const Vector3& v2); + + ~Triangle(); + + /** 0, 1, or 2 */ + inline const Vector3& vertex(int n) const { + debugAssert((n >= 0) && (n < 3)); + return _vertex[n]; + } + + double area() const; + + Vector3::Axis primaryAxis() const { + return _primaryAxis; + } + + const Vector3& normal() const; + + /** Barycenter */ + Vector3 center() const; + + const Plane& plane() const; + + /** Returns a random point in the triangle. */ + Vector3 randomPoint() const; + + /** + For two triangles to be equal they must have + the same vertices in the same order. + That is, vertex[0] == vertex[0], etc. + */ + inline bool operator==(const Triangle& other) const { + for (int i = 0; i < 3; ++i) { + if (_vertex[i] != other._vertex[i]) { + return false; + } + } + + return true; + } + + inline unsigned int hashCode() const { + return + _vertex[0].hashCode() + + (_vertex[1].hashCode() >> 2) + + _vertex[2].hashCode(); + } + + void getBounds(class AABox&) const; + +}; + +} // namespace + +inline unsigned int hashCode(const G3D::Triangle& t) { + return t.hashCode(); +} + +#endif diff --git a/dep/include/g3dlite/G3D/Vector2.h b/dep/include/g3dlite/G3D/Vector2.h new file mode 100644 index 00000000000..2d9d2662646 --- /dev/null +++ b/dep/include/g3dlite/G3D/Vector2.h @@ -0,0 +1,438 @@ +/** + @file Vector2.h + + 2D vector class + + @maintainer Morgan McGuire, matrix@graphics3d.com + + @created 2001-06-02 + @edited 2006-01-14 + Copyright 2000-2006, Morgan McGuire. + All rights reserved. +*/ + +#ifndef G3D_VECTOR2_H +#define G3D_VECTOR2_H + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" +#include "Vector2int16.h" +#include + +namespace G3D { + +class Vector2; +class Vector3; +class Vector4; + +/** + Do not subclass-- this implementation makes assumptions about the + memory layout. + */ +class Vector2 { +private: + // Hidden operators + bool operator<(const Vector2&) const; + bool operator>(const Vector2&) const; + bool operator<=(const Vector2&) const; + bool operator>=(const Vector2&) const; + +public: + // coordinates + float x, y; + + // construction + Vector2(); + Vector2(float x, float y); + Vector2(float coordinate[2]); + Vector2(double coordinate[2]); + Vector2(const Vector2& rkVector); + Vector2(const class Vector2int16& v); + + float& operator[] (int i); + const float& operator[] (int i) const; + operator float* (); + operator const float* () const; + + // assignment and comparison + Vector2& operator= (const Vector2& rkVector); + bool operator== (const Vector2& rkVector) const; + bool operator!= (const Vector2& rkVector) const; + unsigned int hashCode() const; + bool fuzzyEq(const Vector2& other) const; + bool fuzzyNe(const Vector2& other) const; + /** Returns true if this vector has finite length */ + bool isFinite() const; + + /** Returns true if this vector has length == 0 */ + bool isZero() const; + + /** Returns true if this vector has length == 1 */ + bool isUnit() const; + + // arithmetic operations + Vector2 operator+ (const Vector2& rkVector) const; + Vector2 operator- (const Vector2& rkVector) const; + Vector2 operator* (float fScalar) const; + Vector2 operator* (const Vector2& rkVector) const; + Vector2 operator/ (const Vector2& rkVector) const; + Vector2 operator/ (float fScalar) const; + Vector2 operator- () const; + + inline float sum() const { + return x + y; + } + + /** + Linear interpolation + */ + inline Vector2 lerp(const Vector2& v, float alpha) const { + return (*this) + (v - *this) * alpha; + } + + inline Vector2 clamp(const Vector2& low, const Vector2& high) const { + return Vector2( + G3D::clamp(x, low.x, high.x), + G3D::clamp(y, low.y, high.y)); + } + + inline Vector2 clamp(float low, float high) const { + return Vector2( + (float)G3D::clamp(x, low, high), + (float)G3D::clamp(y, low, high)); + } + + // arithmetic updates + Vector2& operator+= (const Vector2& rkVector); + Vector2& operator-= (const Vector2& rkVector); + Vector2& operator*= (float fScalar); + Vector2& operator/= (float fScalar); + Vector2& operator*= (const Vector2& rkVector); + Vector2& operator/= (const Vector2& rkVector); + + // vector operations + float length() const; + Vector2 direction() const; + /** + Potentially less accurate but faster than direction(). + Only works if System::hasSSE is true. + */ + Vector2 fastDirection() const { + return direction(); + } + + float squaredLength () const; + float dot (const Vector2& rkVector) const; + float unitize (float fTolerance = 1e-06); + + Vector2 min(const Vector2 &v) const; + Vector2 max(const Vector2 &v) const; + + // Random unit vector + static Vector2 random(); + + // Special values. + // Intentionally not inlined: see Matrix3::identity() for details. + static const Vector2& zero(); + inline static const Vector2& one() { static const Vector2 v(1, 1); return v; } + static const Vector2& unitX(); + static const Vector2& unitY(); + static const Vector2& inf(); + static const Vector2& nan(); + /** smallest (most negative) representable vector */ + static const Vector2& minFinite(); + /** Largest representable vector */ + static const Vector2& maxFinite(); + + + + // Deprecated. See Matrix3::identity() for details. + /** @deprecated Use Vector2::zero() */ + static const Vector2 ZERO; + /** @deprecated Use Vector2::unitX() */ + static const Vector2 UNIT_S; + /** @deprecated Use Vector2::unitY() */ + static const Vector2 UNIT_T; + + std::string toString() const; + + // 2-char swizzles + + Vector2 xx() const; + Vector2 yx() const; + Vector2 xy() const; + Vector2 yy() const; + + // 3-char swizzles + + Vector3 xxx() const; + Vector3 yxx() const; + Vector3 xyx() const; + Vector3 yyx() const; + Vector3 xxy() const; + Vector3 yxy() const; + Vector3 xyy() const; + Vector3 yyy() const; + + // 4-char swizzles + + Vector4 xxxx() const; + Vector4 yxxx() const; + Vector4 xyxx() const; + Vector4 yyxx() const; + Vector4 xxyx() const; + Vector4 yxyx() const; + Vector4 xyyx() const; + Vector4 yyyx() const; + Vector4 xxxy() const; + Vector4 yxxy() const; + Vector4 xyxy() const; + Vector4 yyxy() const; + Vector4 xxyy() const; + Vector4 yxyy() const; + Vector4 xyyy() const; + Vector4 yyyy() const; + +}; + +inline Vector2 operator*(double s, const Vector2& v) { + return v * (float)s; +} + +inline Vector2 operator*(float s, const Vector2& v) { + return v * s; +} + +inline Vector2 operator*(int s, const Vector2& v) { + return v * (float)s; +} + + +inline unsigned int hashCode(const G3D::Vector2& v) { + return v.hashCode(); +} + + +inline Vector2::Vector2 () : x(0.0f), y(0.0f) { +} + + +inline Vector2::Vector2(float _x, float _y) : x(_x), y(_y) { +} + + +inline Vector2::Vector2 (float afCoordinate[2]) { + x = afCoordinate[0]; + y = afCoordinate[1]; +} + + + +inline Vector2::Vector2 (double afCoordinate[2]) { + x = (float)afCoordinate[0]; + y = (float)afCoordinate[1]; +} + + +inline Vector2::Vector2 (const Vector2& rkVector) { + x = rkVector.x; + y = rkVector.y; +} + + +inline Vector2::Vector2 (const Vector2int16& v) : x(v.x), y(v.y) { +} + + +inline float& Vector2::operator[] (int i) { + return ((float*)this)[i]; +} + + +inline const float& Vector2::operator[] (int i) const { + return ((float*)this)[i]; +} + + +inline Vector2::operator float* () { + return (float*)this; +} + +inline Vector2::operator const float* () const { + return (float*)this; +} + + +inline Vector2& Vector2::operator= (const Vector2& rkVector) { + x = rkVector.x; + y = rkVector.y; + return *this; +} + + +inline bool Vector2::operator== (const Vector2& rkVector) const { + return ( x == rkVector.x && y == rkVector.y); +} + + +inline bool Vector2::operator!= (const Vector2& rkVector) const { + return ( x != rkVector.x || y != rkVector.y); +} + + +inline Vector2 Vector2::operator+ (const Vector2& rkVector) const { + return Vector2(x + rkVector.x, y + rkVector.y); +} + + +inline Vector2 Vector2::operator- (const Vector2& rkVector) const { + return Vector2(x - rkVector.x, y - rkVector.y); +} + + +inline Vector2 Vector2::operator* (float fScalar) const { + return Vector2(fScalar*x, fScalar*y); +} + + + +inline Vector2 Vector2::operator- () const { + return Vector2( -x, -y); +} + + + +inline Vector2& Vector2::operator+= (const Vector2& rkVector) { + x += rkVector.x; + y += rkVector.y; + return *this; +} + + + +inline Vector2& Vector2::operator-= (const Vector2& rkVector) { + x -= rkVector.x; + y -= rkVector.y; + return *this; +} + + + +inline Vector2& Vector2::operator*= (float fScalar) { + x *= fScalar; + y *= fScalar; + return *this; +} + + + + +inline Vector2& Vector2::operator*= (const Vector2& rkVector) { + x *= rkVector.x; + y *= rkVector.y; + return *this; +} + + + +inline Vector2& Vector2::operator/= (const Vector2& rkVector) { + x /= rkVector.x; + y /= rkVector.y; + return *this; +} + + +inline Vector2 Vector2::operator* (const Vector2& rkVector) const { + return Vector2(x * rkVector.x, y * rkVector.y); +} + + + +inline Vector2 Vector2::operator/ (const Vector2& rkVector) const { + return Vector2(x / rkVector.x, y / rkVector.y); +} + + +inline float Vector2::squaredLength () const { + return x*x + y*y; +} + + +inline float Vector2::length () const { + return sqrtf(x*x + y*y); +} + + +inline Vector2 Vector2::direction () const { + float lenSquared = x * x + y * y; + + if (lenSquared != 1.0f) { + return *this / sqrtf(lenSquared); + } else { + return *this; + } +} + + + +inline float Vector2::dot (const Vector2& rkVector) const { + return x*rkVector.x + y*rkVector.y; +} + + + +inline Vector2 Vector2::min(const Vector2 &v) const { + return Vector2(G3D::min(v.x, x), G3D::min(v.y, y)); +} + + + +inline Vector2 Vector2::max(const Vector2 &v) const { + return Vector2(G3D::max(v.x, x), G3D::max(v.y, y)); +} + + + +inline bool Vector2::fuzzyEq(const Vector2& other) const { + return G3D::fuzzyEq((*this - other).squaredLength(), 0); +} + + + +inline bool Vector2::fuzzyNe(const Vector2& other) const { + return G3D::fuzzyNe((*this - other).squaredLength(), 0); +} + + + +inline bool Vector2::isFinite() const { + return G3D::isFinite(x) && G3D::isFinite(y); +} + + + +inline bool Vector2::isZero() const { + return (x == 0.0f) && (y == 0.0f); +} + + + +inline bool Vector2::isUnit() const { + return squaredLength() == 1.0f; +} + +} + +// Intentionally outside namespace to avoid operator overloading confusion +inline G3D::Vector2 operator*(double s, const G3D::Vector2& v) { + return v * (float)s; +} +inline G3D::Vector2 operator*(int s, const G3D::Vector2& v) { + return v * (float)s; +} + + +inline unsigned int hashCode(const G3D::Vector2& v); + + +#endif diff --git a/dep/include/g3dlite/G3D/Vector2.inl b/dep/include/g3dlite/G3D/Vector2.inl new file mode 100644 index 00000000000..27abecf02ce --- /dev/null +++ b/dep/include/g3dlite/G3D/Vector2.inl @@ -0,0 +1,20 @@ +/** + @file Vector2.inl + + @maintainer Morgan McGuire, matrix@graphics3d.com + @cite Portions by Laura Wollstadt, graphics3d.com + + @cite Portions based on Dave Eberly'x Magic Software Library + at http://www.magic-software.com + + + @created 2001-06-02 + @edited 2006-01-14 + + Copyright 2000-2006, Morgan McGuire. + All rights reserved. + */ + + +} + diff --git a/dep/include/g3dlite/G3D/Vector2int16.h b/dep/include/g3dlite/G3D/Vector2int16.h new file mode 100644 index 00000000000..cadb4a80c5f --- /dev/null +++ b/dep/include/g3dlite/G3D/Vector2int16.h @@ -0,0 +1,75 @@ +/** + @file Vector2int16.h + + @maintainer Morgan McGuire, matrix@brown.edu + + @created 2003-08-09 + @edited 2004-01-03 + + Copyright 2000-2006, Morgan McGuire. + All rights reserved. + */ + +#ifndef VECTOR2INT16_H +#define VECTOR2INT16_H + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" + +namespace G3D { + +/** + A Vector2 that packs its fields into uint16s. + */ +#ifdef G3D_WIN32 + // Switch to tight alignment + #pragma pack(push, 2) +#endif + +class Vector2int16 { +private: + // Hidden operators + bool operator<(const Vector2int16&) const; + bool operator>(const Vector2int16&) const; + bool operator<=(const Vector2int16&) const; + bool operator>=(const Vector2int16&) const; + +public: + G3D::int16 x; + G3D::int16 y; + + Vector2int16() : x(0), y(0) {} + Vector2int16(G3D::int16 _x, G3D::int16 _y) : x(_x), y(_y){} + Vector2int16(const class Vector2& v); + + inline G3D::int16& operator[] (int i) { + debugAssert(((unsigned int)i) <= 1); + return ((G3D::int16*)this)[i]; + } + + inline const G3D::int16& operator[] (int i) const { + debugAssert(((unsigned int)i) <= 1); + return ((G3D::int16*)this)[i]; + } + + + inline bool operator== (const Vector2int16& rkVector) const { + return ((int32*)this)[0] == ((int32*)&rkVector)[0]; + } + + inline bool operator!= (const Vector2int16& rkVector) const { + return ((int32*)this)[0] != ((int32*)&rkVector)[0]; + } + +} +#if defined(G3D_LINUX) || defined(G3D_OSX) + __attribute((aligned(1))) +#endif +; + +#ifdef G3D_WIN32 + #pragma pack(pop) +#endif + +} +#endif diff --git a/dep/include/g3dlite/G3D/Vector3.h b/dep/include/g3dlite/G3D/Vector3.h new file mode 100644 index 00000000000..79c28fb5e7d --- /dev/null +++ b/dep/include/g3dlite/G3D/Vector3.h @@ -0,0 +1,504 @@ +/** + @file Vector3.h + + 3D vector class + + @maintainer Morgan McGuire, matrix@graphics3d.com + + @created 2001-06-02 + @edited 2005-08-23 + Copyright 2000-2006, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_VECTOR3_H +#define G3D_VECTOR3_H + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" +#include "G3D/Vector2.h" +#include +#include + +namespace G3D { + +class Vector2; +class Vector3; +class Vector4; + +/** + Swizzles + Vector classes have swizzle operators, e.g. v.xy(), that + allow selection of arbitrary sub-fields. These cannot be used as write + masks. Examples + +
+Vector3 v(1, 2, 3);
+Vector3 j;
+Vector2 b;
+
+b = v.xz();
+j = b.xx();
+
+ + + Warning + + Do not subclass-- this implementation makes assumptions about the + memory layout. + */ +class Vector3 { +private: + /** + Reflect this vector about the (not necessarily unit) normal. + Note that if used for a collision or ray reflection you + must negate the resulting vector to get a direction pointing + away from the collision. + +
+       V'    N      V
+                 
+         r   ^   -,
+          \  |  /
+            \|/
+     
+ + See also Vector3::reflectionDirection + */ + Vector3 reflectAbout(const Vector3& normal) const; + + // Hidden operators + bool operator<(const Vector3&) const; + bool operator>(const Vector3&) const; + bool operator<=(const Vector3&) const; + bool operator>=(const Vector3&) const; + +public: + // construction + Vector3(); + Vector3(float _x, float _y, float _z); + Vector3(const class Vector2& v, float _z); + Vector3(float coordinate[3]); + Vector3(double coordinate[3]); + Vector3(const Vector3& rkVector); + Vector3(const class Vector3int16& v); + + // coordinates + float x, y, z; + + // access vector V as V[0] = V.x, V[1] = V.y, V[2] = V.z + // + // WARNING. These member functions rely on + // (1) Vector3 not having virtual functions + // (2) the data packed in a 3*sizeof(float) memory block + const float& operator[] (int i) const; + float& operator[] (int i); + + inline operator float* () { + return (float*)this; + } + + operator const float* () const { + return (float*)this; + } + + enum Axis {X_AXIS=0, Y_AXIS=1, Z_AXIS=2, DETECT_AXIS=-1}; + + /** + Returns the largest dimension. Particularly convenient for determining + which plane to project a triangle onto for point-in-polygon tests. + */ + Axis primaryAxis() const; + + // assignment and comparison + Vector3& operator= (const Vector3& rkVector); + bool operator== (const Vector3& rkVector) const; + bool operator!= (const Vector3& rkVector) const; + unsigned int hashCode() const; + bool fuzzyEq(const Vector3& other) const; + bool fuzzyNe(const Vector3& other) const; + + /** Returns true if this vector has finite length. */ + bool isFinite() const; + + /** Returns true if this vector has length ~= 0 */ + bool isZero() const; + + /** Returns true if this vector has length ~= 1 */ + bool isUnit() const; + + // arithmetic operations + Vector3 operator+ (const Vector3& v) const; + Vector3 operator- (const Vector3& v) const; + Vector3 operator* (float s) const; + Vector3 operator/ (float s) const; + Vector3 operator* (const Vector3& v) const; + Vector3 operator/ (const Vector3& v) const; + Vector3 operator- () const; + + // arithmetic updates + Vector3& operator+= (const Vector3& v); + Vector3& operator-= (const Vector3& v); + Vector3& operator*= (float s); + Vector3& operator/= (float s); + Vector3& operator*= (const Vector3& v); + Vector3& operator/= (const Vector3& v); + + /** @deprecated Use magnitude */ + float G3D_DEPRECATED length() const; + + float magnitude() const; + + /** + The result is a nan vector if the length is almost zero. + */ + Vector3 direction() const; + + /** + Potentially less accurate but faster than direction(). + Only works if System::hasSSE is true. + */ + Vector3 fastDirection() const; + + + /** + See also G3D::Ray::reflect. + The length is 1. +
+       V'    N       V
+                 
+         r   ^    /
+          \  |  /
+            \|'-
+     
+ */ + Vector3 reflectionDirection(const Vector3& normal) const; + + + /** + Returns Vector3::zero() if the length is nearly zero, otherwise + returns a unit vector. + */ + inline Vector3 directionOrZero() const { + float mag = magnitude(); + if (G3D::fuzzyEq(mag, 0.0f)) { + return Vector3::zero(); + } else if (G3D::fuzzyEq(mag, 1.0f)) { + return *this; + } else { + return *this * (1.0f / mag); + } + } + + /** + Returns the direction of a refracted ray, + where iExit is the index of refraction for the + previous material and iEnter is the index of refraction + for the new material. Like Vector3::reflectionDirection, + the result has length 1 and is + pointed away from the intersection. + + Returns Vector3::zero() in the case of total internal refraction. + + @param iOutside The index of refraction (eta) outside + (on the positive normal side) of the surface. + + @param iInside The index of refraction (eta) inside + (on the negative normal side) of the surface. + + See also G3D::Ray::refract. +
+              N      V
+                  
+              ^    /
+              |  /
+              |'-
+          __--
+     V'<--
+     
+ */ + Vector3 refractionDirection( + const Vector3& normal, + float iInside, + float iOutside) const; + + /** Synonym for direction */ + inline Vector3 unit() const { + return direction(); + } + + /** Returns a normalized vector. May be computed with lower precision than unit */ + inline Vector3 fastUnit() const { + return fastDirection(); + } + + /** @deprecated Use squaredMagnitude */ + float G3D_DEPRECATED squaredLength() const; + + float squaredMagnitude () const; + + /** @deprecated Use squaredMagnitude */ + inline float G3D_DEPRECATED norm() const { + return squaredMagnitude(); + } + + float dot(const Vector3& rkVector) const; + + float G3D_DEPRECATED unitize(float fTolerance = 1e-06); + + /** Cross product. Note that two cross products in a row + can be computed more cheaply: v1 x (v2 x v3) = (v1 dot v3) v2 - (v1 dot v2) v3. + */ + Vector3 cross(const Vector3& rkVector) const; + Vector3 unitCross (const Vector3& rkVector) const; + + /** + Returns a matrix such that v.cross() * w = v.cross(w). +
+     [ 0  -v.z  v.y ]
+     [ v.z  0  -v.x ]
+     [ -v.y v.x  0  ]
+     
+ */ + class Matrix3 cross() const; + + Vector3 min(const Vector3 &v) const; + Vector3 max(const Vector3 &v) const; + + std::string toString() const; + + inline Vector3 clamp(const Vector3& low, const Vector3& high) const { + return Vector3( + G3D::clamp(x, low.x, high.x), + G3D::clamp(y, low.y, high.y), + G3D::clamp(z, low.z, high.z)); + } + + inline Vector3 clamp(float low, float high) const { + return Vector3( + G3D::clamp(x, low, high), + G3D::clamp(y, low, high), + G3D::clamp(z, low, high)); + } + + /** + Linear interpolation + */ + inline Vector3 lerp(const Vector3& v, float alpha) const { + return (*this) + (v - *this) * alpha; + } + + /** Gram-Schmidt orthonormalization. */ + static void orthonormalize (Vector3 akVector[3]); + + /** Random unit vector, uniformly distributed */ + static Vector3 random(); + + /** Random unit vector, distributed + so that the probability of V is proportional + to max(V dot Normal, 0). + + @cite Henrik Wann Jensen, Realistic Image Synthesis using Photon Mapping eqn 2.24 + */ + static Vector3 cosRandom(const Vector3& normal); + + + /** + Random vector distributed over the hemisphere about normal. + */ + static Vector3 hemiRandom(const Vector3& normal); + + // Input W must be initialize to a nonzero vector, output is {U,V,W} + // an orthonormal basis. A hint is provided about whether or not W + // is already unit length. + static void generateOrthonormalBasis (Vector3& rkU, Vector3& rkV, + Vector3& rkW, bool bUnitLengthW = true); + + inline float sum() const { + return x + y + z; + } + + inline float average() const { + return sum() / 3.0f; + } + + // Special values. + inline static const Vector3& zero() { static Vector3 v(0, 0, 0); return v; } + inline static const Vector3& one() { static Vector3 v(1, 1, 1); return v; } + inline static const Vector3& unitX() { static Vector3 v(1, 0, 0); return v; } + inline static const Vector3& unitY() { static Vector3 v(0, 1, 0); return v; } + inline static const Vector3& unitZ() { static Vector3 v(0, 0, 1); return v; } + inline static const Vector3& inf() { static Vector3 v((float)G3D::inf(), (float)G3D::inf(), (float)G3D::inf()); return v; } + inline static const Vector3& nan() { static Vector3 v((float)G3D::nan(), (float)G3D::nan(), (float)G3D::nan()); return v; } + /** Smallest (most negative) representable vector */ + inline static const Vector3& minFinite(){ static Vector3 v(-FLT_MAX, -FLT_MAX, -FLT_MAX); return v; } + /** Largest representable vector */ + inline static const Vector3& maxFinite(){ static Vector3 v(FLT_MAX, FLT_MAX, FLT_MAX); return v; } + + // Deprecated. See Matrix3::identity() for details. + /** @deprecated Use Vector3::zero() */ + static const Vector3 ZERO; + /** @deprecated Use Vector3::zero() */ + static const Vector3 ZERO3; + /** @deprecated Use Vector3::unitX() */ + static const Vector3 UNIT_X; + /** @deprecated Use Vector3::unitY() */ + static const Vector3 UNIT_Y; + /** @deprecated Use Vector3::unitZ() */ + static const Vector3 UNIT_Z; + /** @deprecated Use Vector3::inf() */ + static const Vector3 INF3; + /** @deprecated Use Vector3::nan() */ + static const Vector3 NAN3; + + // 2-char swizzles + + Vector2 xx() const; + Vector2 yx() const; + Vector2 zx() const; + Vector2 xy() const; + Vector2 yy() const; + Vector2 zy() const; + Vector2 xz() const; + Vector2 yz() const; + Vector2 zz() const; + + // 3-char swizzles + + Vector3 xxx() const; + Vector3 yxx() const; + Vector3 zxx() const; + Vector3 xyx() const; + Vector3 yyx() const; + Vector3 zyx() const; + Vector3 xzx() const; + Vector3 yzx() const; + Vector3 zzx() const; + Vector3 xxy() const; + Vector3 yxy() const; + Vector3 zxy() const; + Vector3 xyy() const; + Vector3 yyy() const; + Vector3 zyy() const; + Vector3 xzy() const; + Vector3 yzy() const; + Vector3 zzy() const; + Vector3 xxz() const; + Vector3 yxz() const; + Vector3 zxz() const; + Vector3 xyz() const; + Vector3 yyz() const; + Vector3 zyz() const; + Vector3 xzz() const; + Vector3 yzz() const; + Vector3 zzz() const; + + // 4-char swizzles + + Vector4 xxxx() const; + Vector4 yxxx() const; + Vector4 zxxx() const; + Vector4 xyxx() const; + Vector4 yyxx() const; + Vector4 zyxx() const; + Vector4 xzxx() const; + Vector4 yzxx() const; + Vector4 zzxx() const; + Vector4 xxyx() const; + Vector4 yxyx() const; + Vector4 zxyx() const; + Vector4 xyyx() const; + Vector4 yyyx() const; + Vector4 zyyx() const; + Vector4 xzyx() const; + Vector4 yzyx() const; + Vector4 zzyx() const; + Vector4 xxzx() const; + Vector4 yxzx() const; + Vector4 zxzx() const; + Vector4 xyzx() const; + Vector4 yyzx() const; + Vector4 zyzx() const; + Vector4 xzzx() const; + Vector4 yzzx() const; + Vector4 zzzx() const; + Vector4 xxxy() const; + Vector4 yxxy() const; + Vector4 zxxy() const; + Vector4 xyxy() const; + Vector4 yyxy() const; + Vector4 zyxy() const; + Vector4 xzxy() const; + Vector4 yzxy() const; + Vector4 zzxy() const; + Vector4 xxyy() const; + Vector4 yxyy() const; + Vector4 zxyy() const; + Vector4 xyyy() const; + Vector4 yyyy() const; + Vector4 zyyy() const; + Vector4 xzyy() const; + Vector4 yzyy() const; + Vector4 zzyy() const; + Vector4 xxzy() const; + Vector4 yxzy() const; + Vector4 zxzy() const; + Vector4 xyzy() const; + Vector4 yyzy() const; + Vector4 zyzy() const; + Vector4 xzzy() const; + Vector4 yzzy() const; + Vector4 zzzy() const; + Vector4 xxxz() const; + Vector4 yxxz() const; + Vector4 zxxz() const; + Vector4 xyxz() const; + Vector4 yyxz() const; + Vector4 zyxz() const; + Vector4 xzxz() const; + Vector4 yzxz() const; + Vector4 zzxz() const; + Vector4 xxyz() const; + Vector4 yxyz() const; + Vector4 zxyz() const; + Vector4 xyyz() const; + Vector4 yyyz() const; + Vector4 zyyz() const; + Vector4 xzyz() const; + Vector4 yzyz() const; + Vector4 zzyz() const; + Vector4 xxzz() const; + Vector4 yxzz() const; + Vector4 zxzz() const; + Vector4 xyzz() const; + Vector4 yyzz() const; + Vector4 zyzz() const; + Vector4 xzzz() const; + Vector4 yzzz() const; + Vector4 zzzz() const; + + /** A value that can be passed to ignore a parameter. Never look at the result of dummy. */ + static Vector3 dummy; +}; + +inline G3D::Vector3 operator*(float s, const G3D::Vector3& v) { + return v * s; +} + +inline G3D::Vector3 operator*(double s, const G3D::Vector3& v) { + return v * (float)s; +} + +inline G3D::Vector3 operator*(int s, const G3D::Vector3& v) { + return v * (float)s; +} + +std::ostream& operator<<(std::ostream& os, const Vector3&); + +} + +unsigned int hashCode(const G3D::Vector3& v); + +#include "Vector3.inl" + +#endif diff --git a/dep/include/g3dlite/G3D/Vector3.inl b/dep/include/g3dlite/G3D/Vector3.inl new file mode 100644 index 00000000000..99110ffc8eb --- /dev/null +++ b/dep/include/g3dlite/G3D/Vector3.inl @@ -0,0 +1,250 @@ +/** + @file Vector3.inl + + @maintainer Morgan McGuire, matrix@graphics3d.com + + @cite Portions based on Dave Eberly's Magic Software Library at http://www.magic-software.com + + @created 2001-06-02 + @edited 2004-05-21 + Copyright 2000-2004, Morgan McGuire. + All rights reserved. + */ + +//---------------------------------------------------------------------------- +#ifdef SSE + // If you receive an error on this line, it is because you do not have the file + // xmmintrin.h needed for MMX & SSE extensions. Download and install + // + // http://download.microsoft.com/download/vstudio60ent/SP5/Wideband-Full/WIN98Me/EN-US/vs6sp5.exe + // and + // http://download.microsoft.com/download/vb60ent/Update/6/W9X2KXP/EN-US/vcpp5.exe + // + // to get this file. +# include +#endif + +inline unsigned int hashCode(const G3D::Vector3& v) { + return v.hashCode(); +} + +namespace G3D { + +//---------------------------------------------------------------------------- +inline Vector3::Vector3() : x(0.0f), y(0.0f), z(0.0f) { +} + +//---------------------------------------------------------------------------- + +inline Vector3::Vector3 (float fX, float fY, float fZ) : x(fX), y(fY), z(fZ) { +} + +//---------------------------------------------------------------------------- +inline Vector3::Vector3 (float V[3]) : x(V[0]), y(V[1]), z(V[2]){ +} +//---------------------------------------------------------------------------- +inline Vector3::Vector3 (double V[3]) : x((float)V[0]), y((float)V[1]), z((float)V[2]){ +} + +//---------------------------------------------------------------------------- +inline Vector3::Vector3 (const Vector3& V) : x(V.x), y(V.y), z(V.z) { +} + +//---------------------------------------------------------------------------- + +//inline Vector3::Vector3 (const __m128& m) { + // Cast from SSE packed floats +// *this = *(Vector3*)&m; +//} + +//---------------------------------------------------------------------------- +inline const float& Vector3::operator[] (int i) const { + return ((float*)this)[i]; +} + +inline float& Vector3::operator[] (int i) { + return ((float*)this)[i]; +} + + +//---------------------------------------------------------------------------- +inline Vector3& Vector3::operator= (const Vector3& rkVector) { + x = rkVector.x; + y = rkVector.y; + z = rkVector.z; + return *this; +} + +//---------------------------------------------------------------------------- + +inline bool Vector3::fuzzyEq(const Vector3& other) const { + return G3D::fuzzyEq((*this - other).squaredMagnitude(), 0); +} + +//---------------------------------------------------------------------------- + +inline bool Vector3::fuzzyNe(const Vector3& other) const { + return G3D::fuzzyNe((*this - other).squaredMagnitude(), 0); +} + +//---------------------------------------------------------------------------- + +inline bool Vector3::isFinite() const { + return G3D::isFinite(x) && G3D::isFinite(y) && G3D::isFinite(z); +} + +//---------------------------------------------------------------------------- +inline bool Vector3::operator== (const Vector3& rkVector) const { + return ( x == rkVector.x && y == rkVector.y && z == rkVector.z ); +} + +//---------------------------------------------------------------------------- +inline bool Vector3::operator!= (const Vector3& rkVector) const { + return ( x != rkVector.x || y != rkVector.y || z != rkVector.z ); +} + +//---------------------------------------------------------------------------- +inline Vector3 Vector3::operator+ (const Vector3& rkVector) const { + return Vector3(x + rkVector.x, y + rkVector.y, z + rkVector.z); +} + +//---------------------------------------------------------------------------- +inline Vector3 Vector3::operator- (const Vector3& rkVector) const { + return Vector3(x - rkVector.x, y - rkVector.y, z - rkVector.z); +} + +//---------------------------------------------------------------------------- +inline Vector3 Vector3::operator* (const Vector3& rkVector) const { + return Vector3(x * rkVector.x, y * rkVector.y, z * rkVector.z); +} + +inline Vector3 Vector3::operator*(float f) const { + return Vector3(x * f, y * f, z * f); +} + +//---------------------------------------------------------------------------- +inline Vector3 Vector3::operator/ (const Vector3& rkVector) const { + return Vector3(x / rkVector.x, y / rkVector.y, z / rkVector.z); +} + +//---------------------------------------------------------------------------- +inline Vector3 Vector3::operator- () const { + return Vector3(-x, -y, -z); +} + +//---------------------------------------------------------------------------- +inline Vector3& Vector3::operator+= (const Vector3& rkVector) { + x += rkVector.x; + y += rkVector.y; + z += rkVector.z; + return *this; +} + +//---------------------------------------------------------------------------- +inline Vector3& Vector3::operator-= (const Vector3& rkVector) { + x -= rkVector.x; + y -= rkVector.y; + z -= rkVector.z; + return *this; +} + +//---------------------------------------------------------------------------- +inline Vector3& Vector3::operator*= (float fScalar) { + x *= fScalar; + y *= fScalar; + z *= fScalar; + return *this; +} + +//---------------------------------------------------------------------------- +inline Vector3& Vector3::operator*= (const Vector3& rkVector) { + x *= rkVector.x; + y *= rkVector.y; + z *= rkVector.z; + return *this; +} + +//---------------------------------------------------------------------------- +inline Vector3& Vector3::operator/= (const Vector3& rkVector) { + x /= rkVector.x; + y /= rkVector.y; + z /= rkVector.z; + return *this; +} + +//---------------------------------------------------------------------------- +inline float Vector3::squaredMagnitude () const { + return x*x + y*y + z*z; +} + +//---------------------------------------------------------------------------- +inline float Vector3::squaredLength () const { + return squaredMagnitude(); +} + +//---------------------------------------------------------------------------- +inline float Vector3::magnitude() const { + return sqrtf(x*x + y*y + z*z); +} + +//---------------------------------------------------------------------------- +inline float Vector3::length() const { + return magnitude(); +} + +//---------------------------------------------------------------------------- +inline Vector3 Vector3::direction () const { + float lenSquared = squaredMagnitude(); + float invSqrt = 1.0f / sqrtf(lenSquared); + return Vector3(x * invSqrt, y * invSqrt, z * invSqrt); +} + +//---------------------------------------------------------------------------- + +inline Vector3 Vector3::fastDirection () const { + float lenSquared = x * x + y * y + z * z; + float invSqrt = rsq(lenSquared); + return Vector3(x * invSqrt, y * invSqrt, z * invSqrt); +} + +//---------------------------------------------------------------------------- +inline float Vector3::dot (const Vector3& rkVector) const { + return x*rkVector.x + y*rkVector.y + z*rkVector.z; +} + +//---------------------------------------------------------------------------- +inline Vector3 Vector3::cross (const Vector3& rkVector) const { + return Vector3(y*rkVector.z - z*rkVector.y, z*rkVector.x - x*rkVector.z, + x*rkVector.y - y*rkVector.x); +} + +//---------------------------------------------------------------------------- +inline Vector3 Vector3::unitCross (const Vector3& rkVector) const { + Vector3 kCross(y*rkVector.z - z*rkVector.y, z*rkVector.x - x*rkVector.z, + x*rkVector.y - y*rkVector.x); + kCross.unitize(); + return kCross; +} + +//---------------------------------------------------------------------------- +inline Vector3 Vector3::min(const Vector3 &v) const { + return Vector3(G3D::min(v.x, x), G3D::min(v.y, y), G3D::min(v.z, z)); +} + +//---------------------------------------------------------------------------- +inline Vector3 Vector3::max(const Vector3 &v) const { + return Vector3(G3D::max(v.x, x), G3D::max(v.y, y), G3D::max(v.z, z)); +} + +//---------------------------------------------------------------------------- +inline bool Vector3::isZero() const { + return G3D::fuzzyEq(squaredMagnitude(), 0.0f); +} + +//---------------------------------------------------------------------------- + +inline bool Vector3::isUnit() const { + return G3D::fuzzyEq(squaredMagnitude(), 1.0f); +} + +} // namespace diff --git a/dep/include/g3dlite/G3D/Vector3int16.h b/dep/include/g3dlite/G3D/Vector3int16.h new file mode 100644 index 00000000000..9fd344b2da7 --- /dev/null +++ b/dep/include/g3dlite/G3D/Vector3int16.h @@ -0,0 +1,55 @@ +/** + @file Vector3int16.h + + @maintainer Morgan McGuire, matrix@brown.edu + + @created 2003-04-07 + @edited 2003-06-24 + Copyright 2000-2004, Morgan McGuire. + All rights reserved. + */ + +#ifndef VECTOR3INT16_H +#define VECTOR3INT16_H + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" + +namespace G3D { + +/** + A Vector3 that packs its fields into uint16s. + */ +#ifdef G3D_WIN32 + // Switch to tight alignment + #pragma pack(push, 2) +#endif + +class Vector3int16 { +private: + // Hidden operators + bool operator<(const Vector3int16&) const; + bool operator>(const Vector3int16&) const; + bool operator<=(const Vector3int16&) const; + bool operator>=(const Vector3int16&) const; + +public: + G3D::int16 x; + G3D::int16 y; + G3D::int16 z; + + Vector3int16() : x(0), y(0), z(0) {} + Vector3int16(G3D::int16 _x, G3D::int16 _y, G3D::int16 _z) : x(_x), y(_y), z(_z) {} + Vector3int16(const class Vector3& v); +} +#if defined(G3D_LINUX) || defined(G3D_OSX) + __attribute((aligned(1))) +#endif +; + +#ifdef G3D_WIN32 + #pragma pack(pop) +#endif + +} +#endif diff --git a/dep/include/g3dlite/G3D/Vector4.h b/dep/include/g3dlite/G3D/Vector4.h new file mode 100644 index 00000000000..b86bf95b003 --- /dev/null +++ b/dep/include/g3dlite/G3D/Vector4.h @@ -0,0 +1,524 @@ +/** + @file Vector4.h + + Homogeneous vector class. + + @maintainer Morgan McGuire, matrix@graphics3d.com + + @created 2002-07-09 + @edited 2005-03-28 + + Copyright 2000-2006, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_VECTOR4_H +#define G3D_VECTOR4_H + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" +#include "G3D/Vector3.h" +#include "G3D/Vector2.h" +#include + +namespace G3D { + +class Vector2; +class Vector3; +class Vector4; + +/** + Do not subclass-- this implementation makes assumptions about the + memory layout. + */ +class Vector4 { +private: + // Hidden operators + bool operator<(const Vector4&) const; + bool operator>(const Vector4&) const; + bool operator<=(const Vector4&) const; + bool operator>=(const Vector4&) const; + +public: + // construction + Vector4(); + Vector4(float fX, float fY, float fZ, float fW); + Vector4(float afCoordinate[4]); + Vector4(const Vector4& rkVector); + Vector4(const class Color4& c); + Vector4(const Vector3& rkVector, float fW); + Vector4(const Vector2& v1, const Vector2& v2); + Vector4(const Vector2& v1, float fz, float fw); + + // coordinates + float x, y, z, w; + + // access vector V as V[0] = V.x, V[1] = V.y, V[2] = V.z, etc. + // + // WARNING. These member functions rely on + // (1) Vector4 not having virtual functions + // (2) the data packed in a 4*sizeof(float) memory block + float& operator[] (int i); + const float& operator[] (int i) const; + operator float* (); + operator const float* () const; + + // assignment and comparison + Vector4& operator= (const Vector4& rkVector); + bool operator== (const Vector4& rkVector) const; + bool operator!= (const Vector4& rkVector) const; + + inline void set(float _x, float _y, float _z, float _w) { + x = _x; + y = _y; + z = _z; + w = _w; + } + + inline void set(const Vector3& v, float _w) { + x = v.x; + y = v.y; + z = v.z; + w = _w; + } + + inline void set(const Vector2& v, float _z, float _w) { + x = v.x; + y = v.y; + z = _z; + w = _w; + } + + unsigned int hashCode() const; + bool fuzzyEq(const Vector4& other) const; + bool fuzzyNe(const Vector4& other) const; + + inline static const Vector4& inf() { static Vector4 v((float)G3D::inf(), (float)G3D::inf(), (float)G3D::inf(), (float)G3D::inf()); return v; } + inline static const Vector4& nan() { static Vector4 v((float)G3D::nan(), (float)G3D::nan(), (float)G3D::nan(), (float)G3D::nan()); return v; } + + /** sqrt(this->dot(*this)) */ + float length() const; + float squaredLength() const; + + inline float sum() const { + return x + y + z + w; + } + + /** Returns true if this vector has finite length */ + bool isFinite() const; + + /** Returns true if this vector has length == 0 */ + bool isZero() const; + + /** Returns true if this vector has length == 1 */ + bool isUnit() const; + + // arithmetic operations + Vector4 operator+ (const Vector4& rkVector) const; + Vector4 operator- (const Vector4& rkVector) const; + + inline Vector4 operator*(const Vector4& rkVector) const { + return Vector4(x * rkVector.x, y * rkVector.y, z * rkVector.z, w * rkVector.w); + } + + inline Vector4 operator/(const Vector4& rkVector) const { + return Vector4(x / rkVector.x, y / rkVector.y, z / rkVector.z, w / rkVector.w); + } + + Vector4 operator* (float fScalar) const; + Vector4 operator/ (float fScalar) const; + Vector4 operator- () const; + friend Vector4 operator* (float, const Vector4& rkVector); + + // arithmetic updates + Vector4& operator+= (const Vector4& rkVector); + Vector4& operator-= (const Vector4& rkVector); + Vector4& operator*= (float fScalar); + Vector4& operator/= (float fScalar); + + inline Vector4 clamp(const Vector4& low, const Vector4& high) const { + return Vector4( + G3D::clamp(x, low.x, high.x), + G3D::clamp(y, low.y, high.y), + G3D::clamp(z, low.z, high.z), + G3D::clamp(w, low.w, high.w)); + } + + inline Vector4 clamp(float low, float high) const { + return Vector4( + G3D::clamp(x, low, high), + G3D::clamp(y, low, high), + G3D::clamp(z, low, high), + G3D::clamp(w, low, high)); + } + + float dot (const Vector4& rkVector) const; + + Vector4 min(const Vector4& v) const; + Vector4 max(const Vector4& v) const; + + std::string toString() const; + + /** + Linear interpolation + */ + Vector4 lerp(const Vector4& v, float alpha) const; + + // 2-char swizzles + + Vector2 xx() const; + Vector2 yx() const; + Vector2 zx() const; + Vector2 wx() const; + Vector2 xy() const; + Vector2 yy() const; + Vector2 zy() const; + Vector2 wy() const; + Vector2 xz() const; + Vector2 yz() const; + Vector2 zz() const; + Vector2 wz() const; + Vector2 xw() const; + Vector2 yw() const; + Vector2 zw() const; + Vector2 ww() const; + + // 3-char swizzles + + Vector3 xxx() const; + Vector3 yxx() const; + Vector3 zxx() const; + Vector3 wxx() const; + Vector3 xyx() const; + Vector3 yyx() const; + Vector3 zyx() const; + Vector3 wyx() const; + Vector3 xzx() const; + Vector3 yzx() const; + Vector3 zzx() const; + Vector3 wzx() const; + Vector3 xwx() const; + Vector3 ywx() const; + Vector3 zwx() const; + Vector3 wwx() const; + Vector3 xxy() const; + Vector3 yxy() const; + Vector3 zxy() const; + Vector3 wxy() const; + Vector3 xyy() const; + Vector3 yyy() const; + Vector3 zyy() const; + Vector3 wyy() const; + Vector3 xzy() const; + Vector3 yzy() const; + Vector3 zzy() const; + Vector3 wzy() const; + Vector3 xwy() const; + Vector3 ywy() const; + Vector3 zwy() const; + Vector3 wwy() const; + Vector3 xxz() const; + Vector3 yxz() const; + Vector3 zxz() const; + Vector3 wxz() const; + Vector3 xyz() const; + Vector3 yyz() const; + Vector3 zyz() const; + Vector3 wyz() const; + Vector3 xzz() const; + Vector3 yzz() const; + Vector3 zzz() const; + Vector3 wzz() const; + Vector3 xwz() const; + Vector3 ywz() const; + Vector3 zwz() const; + Vector3 wwz() const; + Vector3 xxw() const; + Vector3 yxw() const; + Vector3 zxw() const; + Vector3 wxw() const; + Vector3 xyw() const; + Vector3 yyw() const; + Vector3 zyw() const; + Vector3 wyw() const; + Vector3 xzw() const; + Vector3 yzw() const; + Vector3 zzw() const; + Vector3 wzw() const; + Vector3 xww() const; + Vector3 yww() const; + Vector3 zww() const; + Vector3 www() const; + + // 4-char swizzles + + Vector4 xxxx() const; + Vector4 yxxx() const; + Vector4 zxxx() const; + Vector4 wxxx() const; + Vector4 xyxx() const; + Vector4 yyxx() const; + Vector4 zyxx() const; + Vector4 wyxx() const; + Vector4 xzxx() const; + Vector4 yzxx() const; + Vector4 zzxx() const; + Vector4 wzxx() const; + Vector4 xwxx() const; + Vector4 ywxx() const; + Vector4 zwxx() const; + Vector4 wwxx() const; + Vector4 xxyx() const; + Vector4 yxyx() const; + Vector4 zxyx() const; + Vector4 wxyx() const; + Vector4 xyyx() const; + Vector4 yyyx() const; + Vector4 zyyx() const; + Vector4 wyyx() const; + Vector4 xzyx() const; + Vector4 yzyx() const; + Vector4 zzyx() const; + Vector4 wzyx() const; + Vector4 xwyx() const; + Vector4 ywyx() const; + Vector4 zwyx() const; + Vector4 wwyx() const; + Vector4 xxzx() const; + Vector4 yxzx() const; + Vector4 zxzx() const; + Vector4 wxzx() const; + Vector4 xyzx() const; + Vector4 yyzx() const; + Vector4 zyzx() const; + Vector4 wyzx() const; + Vector4 xzzx() const; + Vector4 yzzx() const; + Vector4 zzzx() const; + Vector4 wzzx() const; + Vector4 xwzx() const; + Vector4 ywzx() const; + Vector4 zwzx() const; + Vector4 wwzx() const; + Vector4 xxwx() const; + Vector4 yxwx() const; + Vector4 zxwx() const; + Vector4 wxwx() const; + Vector4 xywx() const; + Vector4 yywx() const; + Vector4 zywx() const; + Vector4 wywx() const; + Vector4 xzwx() const; + Vector4 yzwx() const; + Vector4 zzwx() const; + Vector4 wzwx() const; + Vector4 xwwx() const; + Vector4 ywwx() const; + Vector4 zwwx() const; + Vector4 wwwx() const; + Vector4 xxxy() const; + Vector4 yxxy() const; + Vector4 zxxy() const; + Vector4 wxxy() const; + Vector4 xyxy() const; + Vector4 yyxy() const; + Vector4 zyxy() const; + Vector4 wyxy() const; + Vector4 xzxy() const; + Vector4 yzxy() const; + Vector4 zzxy() const; + Vector4 wzxy() const; + Vector4 xwxy() const; + Vector4 ywxy() const; + Vector4 zwxy() const; + Vector4 wwxy() const; + Vector4 xxyy() const; + Vector4 yxyy() const; + Vector4 zxyy() const; + Vector4 wxyy() const; + Vector4 xyyy() const; + Vector4 yyyy() const; + Vector4 zyyy() const; + Vector4 wyyy() const; + Vector4 xzyy() const; + Vector4 yzyy() const; + Vector4 zzyy() const; + Vector4 wzyy() const; + Vector4 xwyy() const; + Vector4 ywyy() const; + Vector4 zwyy() const; + Vector4 wwyy() const; + Vector4 xxzy() const; + Vector4 yxzy() const; + Vector4 zxzy() const; + Vector4 wxzy() const; + Vector4 xyzy() const; + Vector4 yyzy() const; + Vector4 zyzy() const; + Vector4 wyzy() const; + Vector4 xzzy() const; + Vector4 yzzy() const; + Vector4 zzzy() const; + Vector4 wzzy() const; + Vector4 xwzy() const; + Vector4 ywzy() const; + Vector4 zwzy() const; + Vector4 wwzy() const; + Vector4 xxwy() const; + Vector4 yxwy() const; + Vector4 zxwy() const; + Vector4 wxwy() const; + Vector4 xywy() const; + Vector4 yywy() const; + Vector4 zywy() const; + Vector4 wywy() const; + Vector4 xzwy() const; + Vector4 yzwy() const; + Vector4 zzwy() const; + Vector4 wzwy() const; + Vector4 xwwy() const; + Vector4 ywwy() const; + Vector4 zwwy() const; + Vector4 wwwy() const; + Vector4 xxxz() const; + Vector4 yxxz() const; + Vector4 zxxz() const; + Vector4 wxxz() const; + Vector4 xyxz() const; + Vector4 yyxz() const; + Vector4 zyxz() const; + Vector4 wyxz() const; + Vector4 xzxz() const; + Vector4 yzxz() const; + Vector4 zzxz() const; + Vector4 wzxz() const; + Vector4 xwxz() const; + Vector4 ywxz() const; + Vector4 zwxz() const; + Vector4 wwxz() const; + Vector4 xxyz() const; + Vector4 yxyz() const; + Vector4 zxyz() const; + Vector4 wxyz() const; + Vector4 xyyz() const; + Vector4 yyyz() const; + Vector4 zyyz() const; + Vector4 wyyz() const; + Vector4 xzyz() const; + Vector4 yzyz() const; + Vector4 zzyz() const; + Vector4 wzyz() const; + Vector4 xwyz() const; + Vector4 ywyz() const; + Vector4 zwyz() const; + Vector4 wwyz() const; + Vector4 xxzz() const; + Vector4 yxzz() const; + Vector4 zxzz() const; + Vector4 wxzz() const; + Vector4 xyzz() const; + Vector4 yyzz() const; + Vector4 zyzz() const; + Vector4 wyzz() const; + Vector4 xzzz() const; + Vector4 yzzz() const; + Vector4 zzzz() const; + Vector4 wzzz() const; + Vector4 xwzz() const; + Vector4 ywzz() const; + Vector4 zwzz() const; + Vector4 wwzz() const; + Vector4 xxwz() const; + Vector4 yxwz() const; + Vector4 zxwz() const; + Vector4 wxwz() const; + Vector4 xywz() const; + Vector4 yywz() const; + Vector4 zywz() const; + Vector4 wywz() const; + Vector4 xzwz() const; + Vector4 yzwz() const; + Vector4 zzwz() const; + Vector4 wzwz() const; + Vector4 xwwz() const; + Vector4 ywwz() const; + Vector4 zwwz() const; + Vector4 wwwz() const; + Vector4 xxxw() const; + Vector4 yxxw() const; + Vector4 zxxw() const; + Vector4 wxxw() const; + Vector4 xyxw() const; + Vector4 yyxw() const; + Vector4 zyxw() const; + Vector4 wyxw() const; + Vector4 xzxw() const; + Vector4 yzxw() const; + Vector4 zzxw() const; + Vector4 wzxw() const; + Vector4 xwxw() const; + Vector4 ywxw() const; + Vector4 zwxw() const; + Vector4 wwxw() const; + Vector4 xxyw() const; + Vector4 yxyw() const; + Vector4 zxyw() const; + Vector4 wxyw() const; + Vector4 xyyw() const; + Vector4 yyyw() const; + Vector4 zyyw() const; + Vector4 wyyw() const; + Vector4 xzyw() const; + Vector4 yzyw() const; + Vector4 zzyw() const; + Vector4 wzyw() const; + Vector4 xwyw() const; + Vector4 ywyw() const; + Vector4 zwyw() const; + Vector4 wwyw() const; + Vector4 xxzw() const; + Vector4 yxzw() const; + Vector4 zxzw() const; + Vector4 wxzw() const; + Vector4 xyzw() const; + Vector4 yyzw() const; + Vector4 zyzw() const; + Vector4 wyzw() const; + Vector4 xzzw() const; + Vector4 yzzw() const; + Vector4 zzzw() const; + Vector4 wzzw() const; + Vector4 xwzw() const; + Vector4 ywzw() const; + Vector4 zwzw() const; + Vector4 wwzw() const; + Vector4 xxww() const; + Vector4 yxww() const; + Vector4 zxww() const; + Vector4 wxww() const; + Vector4 xyww() const; + Vector4 yyww() const; + Vector4 zyww() const; + Vector4 wyww() const; + Vector4 xzww() const; + Vector4 yzww() const; + Vector4 zzww() const; + Vector4 wzww() const; + Vector4 xwww() const; + Vector4 ywww() const; + Vector4 zwww() const; + Vector4 wwww() const; + +}; + +} + +inline G3D::Vector4 operator* (float s, const G3D::Vector4& v) { + return v * s; +} + +unsigned int hashCode(const G3D::Vector4& v); + +#include "Vector4.inl" + +#endif diff --git a/dep/include/g3dlite/G3D/Vector4.inl b/dep/include/g3dlite/G3D/Vector4.inl new file mode 100644 index 00000000000..48ebf542723 --- /dev/null +++ b/dep/include/g3dlite/G3D/Vector4.inl @@ -0,0 +1,193 @@ +/** + @file Vector4.inl + + @maintainer Morgan McGuire, matrix@graphics3d.com + + @created 2002-07-09 + @edited 2003-02-10 + */ + +//---------------------------------------------------------------------------- + +inline unsigned int hashCode(const G3D::Vector4& v) { + return v.hashCode(); +} + +namespace G3D { + +//---------------------------------------------------------------------------- +inline Vector4::Vector4() { + x = y = z = w = 0; +} + +//---------------------------------------------------------------------------- + +inline Vector4::Vector4 (float fX, float fY, float fZ, float fW) { + x = fX; + y = fY; + z = fZ; + w = fW; +} + +//---------------------------------------------------------------------------- +inline Vector4::Vector4 (float afCoordinate[4]) { + x = afCoordinate[0]; + y = afCoordinate[1]; + z = afCoordinate[2]; + w = afCoordinate[3]; +} + +//---------------------------------------------------------------------------- +inline Vector4::Vector4(const Vector4& rkVector) { + x = rkVector.x; + y = rkVector.y; + z = rkVector.z; + w = rkVector.w; +} +//---------------------------------------------------------------------------- +inline Vector4::Vector4(const Vector3& rkVector, float fW) { + x = rkVector.x; + y = rkVector.y; + z = rkVector.z; + w = fW; +} + +//---------------------------------------------------------------------------- +inline float& Vector4::operator[] (int i) { + return ((float*)this)[i]; +} + +//---------------------------------------------------------------------------- +inline const float& Vector4::operator[] (int i) const { + return ((float*)this)[i]; +} + +//---------------------------------------------------------------------------- +inline Vector4::operator float* () { + return (float*)this; +} + +inline Vector4::operator const float* () const { + return (float*)this; +} + +//---------------------------------------------------------------------------- +inline Vector4& Vector4::operator= (const Vector4& rkVector) { + x = rkVector.x; + y = rkVector.y; + z = rkVector.z; + w = rkVector.w; + return *this; +} + +//---------------------------------------------------------------------------- +inline bool Vector4::operator== (const Vector4& rkVector) const { + return ( (x == rkVector.x) && (y == rkVector.y) && (z == rkVector.z) && (w == rkVector.w)); +} + +//---------------------------------------------------------------------------- +inline bool Vector4::operator!= (const Vector4& rkVector) const { + return ( x != rkVector.x || y != rkVector.y || z != rkVector.z || w != rkVector.w); +} + +//---------------------------------------------------------------------------- +inline Vector4 Vector4::operator+ (const Vector4& rkVector) const { + return Vector4(x + rkVector.x, y + rkVector.y, z + rkVector.z, w + rkVector.w); +} + +//---------------------------------------------------------------------------- +inline Vector4 Vector4::operator- (const Vector4& rkVector) const { + return Vector4(x - rkVector.x, y - rkVector.y, z - rkVector.z, w - rkVector.w); +} + +//---------------------------------------------------------------------------- +inline Vector4 Vector4::operator* (float fScalar) const { + return Vector4(fScalar*x, fScalar*y, fScalar*z, fScalar*w); +} + +//---------------------------------------------------------------------------- +inline Vector4 Vector4::operator- () const { + return Vector4( -x, -y, -z, -w); +} + +//---------------------------------------------------------------------------- +inline Vector4& Vector4::operator+= (const Vector4& rkVector) { + x += rkVector.x; + y += rkVector.y; + z += rkVector.z; + w += rkVector.w; + return *this; +} + +//---------------------------------------------------------------------------- +inline Vector4& Vector4::operator-= (const Vector4& rkVector) { + x -= rkVector.x; + y -= rkVector.y; + z -= rkVector.z; + w -= rkVector.w; + return *this; +} + +//---------------------------------------------------------------------------- + +inline Vector4 Vector4::lerp(const Vector4& v, float alpha) const { + return (*this) + (v - *this) * alpha; +} + + +//---------------------------------------------------------------------------- +inline Vector4& Vector4::operator*= (float fScalar) { + x *= fScalar; + y *= fScalar; + z *= fScalar; + w *= fScalar; + return *this; +} + + +//---------------------------------------------------------------------------- +inline float Vector4::dot(const Vector4& rkVector) const { + return x*rkVector.x + y*rkVector.y + z*rkVector.z + w*rkVector.w; +} + +//---------------------------------------------------------------------------- +inline Vector4 Vector4::min(const Vector4 &v) const { + return Vector4(G3D::min(v.x, x), G3D::min(v.y, y), G3D::min(v.z, z), G3D::min(v.w, w)); +} + +//---------------------------------------------------------------------------- +inline Vector4 Vector4::max(const Vector4 &v) const { + return Vector4(G3D::max(v.x, x), G3D::max(v.y, y), G3D::max(v.z, z), G3D::max(v.w, w)); +} + +//---------------------------------------------------------------------------- +inline bool Vector4::isZero() const { + return (x == 0.0f) && (y == 0.0f) && (z == 0.0f) && (w == 0.0f); +} + +//---------------------------------------------------------------------------- + +inline bool Vector4::isFinite() const { + return G3D::isFinite(x) && G3D::isFinite(y) && G3D::isFinite(z) && G3D::isFinite(w); +} + +//---------------------------------------------------------------------------- + +inline bool Vector4::isUnit() const { + return squaredLength() == 1.0; +} + +//---------------------------------------------------------------------------- + +inline float Vector4::length() const { + return sqrtf(squaredLength()); +} + +//---------------------------------------------------------------------------- + +inline float Vector4::squaredLength() const { + return x * x + y * y + z * z + w * w; +} + +} + diff --git a/dep/include/g3dlite/G3D/debug.h b/dep/include/g3dlite/G3D/debug.h new file mode 100644 index 00000000000..0216d1daf11 --- /dev/null +++ b/dep/include/g3dlite/G3D/debug.h @@ -0,0 +1,11 @@ + +#ifndef G3D_LITE_DEBUG_H +#define G3D_LITE_DEBUG_H + +#define debugStatement(x) +#define debugAssert(x) +#define debugAssertM(x, y) +#define alwaysAssertM(x, y) + +#endif + diff --git a/dep/include/g3dlite/G3D/format.h b/dep/include/g3dlite/G3D/format.h new file mode 100644 index 00000000000..b031300ab1a --- /dev/null +++ b/dep/include/g3dlite/G3D/format.h @@ -0,0 +1,57 @@ +/** + @file format.h + + @maintainer Morgan McGuire, matrix@graphics3d.com + + @author 2000-09-09 + @edited 2005-11-03 + + Copyright 2000-2005, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_FORMAT_H +#define G3D_FORMAT_H + +#include "G3D/platform.h" +#include +#include +#include +#include +#ifndef G3D_WIN32 + // Don't include varargs.h for some random + // gcc reason + //#include + #include +#endif + +#ifndef _MSC_VER + #ifndef __cdecl + #define __cdecl __attribute__((cdecl)) + #endif +#endif + +namespace G3D { + +/** + Produces a string from arguments of the style of printf. This avoids + problems with buffer overflows when using sprintf and makes it easy + to use the result functionally. This function is fast when the resulting + string is under 160 characters (not including terminator) and slower + when the string is longer. + */ +std::string format( + const char* fmt + ...) G3D_CHECK_PRINTF_ARGS; + +/** + Like format, but can be called with the argument list from a ... function. + */ +std::string vformat( + const char* fmt, + va_list argPtr) G3D_CHECK_VPRINTF_ARGS; + + +}; // namespace + +#endif diff --git a/dep/include/g3dlite/G3D/g3dmath.h b/dep/include/g3dlite/G3D/g3dmath.h new file mode 100644 index 00000000000..1f3eaaae57c --- /dev/null +++ b/dep/include/g3dlite/G3D/g3dmath.h @@ -0,0 +1,525 @@ +/** + @file g3dmath.h + + Math util class. + + @maintainer Morgan McGuire, matrix@graphics3d.com + @cite highestBit by Jukka Liimatta + + @created 2001-06-02 + @edited 2006-01-16 + + Copyright 2000-2006, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3DMATH_H +#define G3DMATH_H + +#ifdef _MSC_VER +// Disable conditional expression is constant, which occurs incorrectly on inlined functions +# pragma warning (push) +# pragma warning (disable : 4127) +// disable: "C++ exception handler used" +# pragma warning (disable : 4530) +#endif + +#include "G3D/platform.h" +#include +#include +#include +#include + +/*These defines enable functionality introduced with the 1999 ISO C +**standard. They must be defined before the inclusion of math.h to +**engage them. If optimisation is enabled, these functions will be +**inlined. With optimisation switched off, you have to link in the +**maths library using -lm. +*/ + +#define _ISOC9X_SOURCE1 +#define _ISOC99_SOURCE1 +#define __USE_ISOC9X1 +#define __USE_ISOC991 + +#include + +#include "G3D/debug.h" + +#undef min +#undef max + +namespace G3D { + +#if defined(_MSC_VER) + +#if !defined(_WIN64) + +/** + Win32 implementation of the C99 fast rounding routines. + + @cite routines are + Copyright (C) 2001 Erik de Castro Lopo + + Permission to use, copy, modify, distribute, and sell this file for any + purpose is hereby granted without fee, provided that the above copyright + and this permission notice appear in all copies. No representations are + made about the suitability of this software for any purpose. It is + provided "as is" without express or implied warranty. +*/ + +__inline long int lrint (double flt) { + int intgr; + + _asm { + fld flt + fistp intgr + }; + + return intgr; +} + +__inline long int lrintf(float flt) { + int intgr; + + _asm { + fld flt + fistp intgr + }; + + return intgr; +} + +#else + + __inline long int lrint (double flt) { + return (long int)floor(flt+0.5f); + } + + __inline long int lrintf(float flt) { + return (long int)floorf(flt+0.5f); + } + + +#endif + +#endif + + +const double fuzzyEpsilon = 0.00001; + +/** Returns a reference to a static double. + This value should not be tested against directly, instead + G3D::isNan() and G3D::isFinite() will return reliable results. */ +inline const double& inf() { + +// We already have included but +// not using it in older gcc for safe compilations +#if (__GNUC__ == 2) + static const double i = 1.0/sin(0.0); +#else + // double is a standard type and should have infinity + static const double i = std::numeric_limits::infinity(); +#endif + return i; +} + +/** Returns a reference to a static double. + This value should not be tested against directly, instead + G3D::isNan() and G3D::isFinite() will return reliable results. */ +inline const double& nan() { + +// We already have included but +// not using it in older gcc for safe compilations +#if (__GNUC__ == 2) + static const double n = 0.0/sin(0.0); +#else + // double is a standard type and should have quiet NaN + static const double n = std::numeric_limits::quiet_NaN(); +#endif + return n; +} + +/** Returns a reference to a static double. Use instead of G3D_PI. */ +inline const double& pi() { + static const double p = 3.1415926535898; + return p; +} + +/** Returns a reference to a static double. Use instead of G3D_HALF_PI. */ +inline const double& halfPi() { + static const double p = 1.5707963267949; + return p; +} + +/** Returns a reference to a static double. Use instead of G3D_TWO_PI. */ +inline const double& twoPi() { + static const double p = 6.283185; + return p; +} + +/** @def G3D_PI + @deprecated Use G3D::pi() instead. */ +#define G3D_PI (3.1415926535898) +/** @def G3D_HALF_PI + @deprecated Use G3D::halfPi() instead. */ +#define G3D_HALF_PI (1.5707963267949) +/** @def G3D_TWO_PI + @deprecated Use G3D::twoPi() instead. */ +#define G3D_TWO_PI (6.283185) + +typedef signed char int8; +typedef unsigned char uint8; +typedef short int16; +typedef unsigned short uint16; +typedef int int32; +typedef unsigned int uint32; + +#ifdef _MSC_EXTENSIONS + typedef __int64 int64; + typedef unsigned __int64 uint64; +#else + typedef long long int64; + typedef unsigned long long uint64; +#endif +typedef unsigned int uint; + +typedef float float32; +typedef double float64; + +int iAbs(int iValue); +int iCeil(double fValue); + +/** + Clamps the value to the range [low, hi] (inclusive) + */ +int iClamp(int val, int low, int hi); +double clamp(double val, double low, double hi); +float clamp(float val, float low, float hi); + +/** + Returns a + (b - a) * f; + */ +inline double lerp(double a, double b, double f) { + return a + (b - a) * f; +} + +inline float lerp(float a, float b, float f) { + return a + (b - a) * f; +} + +/** + Wraps the value to the range [0, hi) (exclusive + on the high end). This is like the clock arithmetic + produced by % (modulo) except the result is guaranteed + to be positive. + */ +int iWrap(int val, int hi); + +int iFloor(double fValue); + +int iSign(int iValue); +int iSign(double fValue); + +inline int iSign(float f) { + return iSign((double)f); +} + + +/** + Fast round to integer using the lrint routine. + Typically 6x faster than casting to integer. + */ +inline int iRound(double fValue) { + return lrint(fValue); +} + +/** + Fast round to integer using the lrint routine. + Typically 6x faster than casting to integer. + */ +inline int iRound(float f) { + return lrintf(f); +} + +/** + Returns a random number uniformly at random between low and hi + (inclusive). + */ +int iRandom(int low, int hi); + +double abs (double fValue); +double aCos (double fValue); +double aSin (double fValue); +double aTan (double fValue); +double aTan2 (double fY, double fX); +double sign (double fValue); +double square (double fValue); + +/** + Returns true if the argument is a finite real number. + */ +bool isFinite(double x); + +/** + Returns true if the argument is NaN (not a number). + You can't use x == nan to test this because all + comparisons against nan return false. + */ +bool isNaN(double x); + +/** + Computes x % 3. + */ +int iMod3(int x); + +/** + [0, 1] + @deprecated use uniformRandom() + */ +double unitRandom (); + +/** + Uniform random number between low and hi, inclusive. + @deprecated use uniformRandom() + */ +double random(double low, double hi); + +/** + [-1, 1] + @deprecated use uniformRandom() + */ +double symmetricRandom (); + +/** + Uniform random number between low and hi, inclusive. [low, hi] + */ +float uniformRandom(float low = 0.0f, float hi = 1.0f); + +/** + Normally distributed random number. + */ +float gaussRandom(float mean = 0.0f, float stdev = 1.0f); + +#if defined(_MSC_VER) && (_MSC_VER <= 1200) + + /** VC6 lacks std::min and std::max */ + inline double min(double x, double y) { + return std::_cpp_min(x, y); + } + + /** VC6 lacks std::min and std::max */ + inline float min(float x, float y) { + return std::_cpp_min(x, y); + } + + /** VC6 lacks std::min and std::max */ + inline int min(int x, int y) { + return std::_cpp_min(x, y); + } + + /** VC6 lacks std::min and std::max */ + inline double max(double x, double y) { + return std::_cpp_max(x, y); + } + + /** VC6 lacks std::min and std::max */ + inline float max(float x, float y) { + return std::_cpp_max(x, y); + } + + /** VC6 lacks std::min and std::max */ + inline int max(int x, int y) { + return std::_cpp_max(x, y); + } + +#else + template + inline T min(const T& x, const T& y) { + return std::min(x, y); + } + + template + inline T max(const T& x, const T& y) { + return std::max(x, y); + } + +#endif + +int iMin(int x, int y); +int iMax(int x, int y); + +double square(double x); +double sumSquares(double x, double y); +double sumSquares(double x, double y, double z); +double distance(double x, double y); +double distance(double x, double y, double z); + +/** + Returnes the 0-based index of the highest 1 bit from + the left. -1 means the number was 0. + + @cite Based on code by jukka@liimatta.org + */ +int highestBit(uint32 x); + +/** + Note that fuzzyEq(a, b) && fuzzyEq(b, c) does not imply + fuzzyEq(a, c), although that will be the case on some + occasions. + */ +bool fuzzyEq(double a, double b); + +/** True if a is definitely not equal to b. + Guaranteed false if a == b. + Possibly false when a != b.*/ +bool fuzzyNe(double a, double b); + +/** Is a strictly greater than b? (Guaranteed false if a <= b). + (Possibly false if a > b) */ +bool fuzzyGt(double a, double b); + +/** Is a near or greater than b? */ +bool fuzzyGe(double a, double b); + +/** Is a strictly less than b? (Guaranteed false if a >= b)*/ +bool fuzzyLt(double a, double b); + +/** Is a near or less than b? */ +bool fuzzyLe(double a, double b); + +/** + Computes 1 / sqrt(x). + */ +inline float rsq(float x) { + return 1.0f / sqrtf(x); +} + +/** + Uses SSE to implement rsq. + @cite Nick nicolas@capens.net + */ +inline float SSErsq(float x) { + + #if defined(SSE) && defined(G3D_WIN32) && !defined(_WIN64) + __asm { + movss xmm0, x + rsqrtss xmm0, xmm0 + movss x, xmm0 + } + return x; + #else + return 1.0f / sqrt(x); + #endif +} + +/** + Return the next power of 2 higher than the input + If the input is already a power of 2, the output will be the same + as the input. + */ +int ceilPow2(unsigned int in); + +/** + * True if num is a power of two. + */ +bool isPow2(int num); + +bool isOdd(int num); +bool isEven(int num); + +double toRadians(double deg); +double toDegrees(double rad); + +/** + Returns true if x is not exactly equal to 0.0f. + */ +inline bool any(float x) { + return x != 0; +} + +/** + Returns true if x is not exactly equal to 0.0f. + */ +inline bool all(float x) { + return x != 0; +} + +/** + v / v (for DirectX/Cg support) + */ +inline float normalize(float v) { + return v / v; +} + +/** + a * b (for DirectX/Cg support) + */ +inline float dot(float a, float b) { + return a * b; +} + + +/** + a * b (for DirectX/Cg support) + */ +inline float mul(float a, float b) { + return a * b; +} + +/** + 2^x + */ +inline double exp2(double x) { + return pow(2.0, x); +} + +inline double rsqrt(double x) { + return 1.0 / sqrt(x); +} + + +/** + sin(x)/x + */ +inline double sinc(double x) { + double r = sin(x) / x; + + if (isNaN(r)) { + return 1.0; + } else { + return r; + } +} + +/** + Computes a floating point modulo; the result is t wrapped to the range [lo, hi). + */ +inline double wrap(double t, double lo, double hi) { + if ((t >= lo) && (t < hi)) { + return t; + } + + debugAssert(hi > lo); + + double interval = hi - lo; + + return t - interval * iFloor((t - lo) / interval); + +} + +inline double wrap(double t, double hi) { + return wrap(t, 0, hi); +} + + +} // namespace + +#ifdef _MSC_VER +# pragma warning (pop) +#endif + +#include "g3dmath.inl" + +#endif + diff --git a/dep/include/g3dlite/G3D/g3dmath.inl b/dep/include/g3dlite/G3D/g3dmath.inl new file mode 100644 index 00000000000..1068ed5bf81 --- /dev/null +++ b/dep/include/g3dlite/G3D/g3dmath.inl @@ -0,0 +1,289 @@ +/** + @file g3dmath.inl + + @maintainer Morgan McGuire, matrix@graphics3d.com + + @created 2001-06-02 + @edited 2006-01-14 + */ + +#include + +#ifdef _MSC_VER +// Disable conditional expression is constant, which occurs incorrectly on inlined functions +# pragma warning (push) +# pragma warning( disable : 4127 ) +#endif + +namespace G3D { + +inline bool isNaN(double x) { + bool b1 = (x < 0.0); + bool b2 = (x >= 0.0); + bool b3 = !(b1 || b2); + return b3; +} + +inline bool isFinite(double x) { + return ! isNaN(x) && (x < G3D::inf()) && (x > -G3D::inf()); +} + +//---------------------------------------------------------------------------- +inline int iAbs (int iValue) { + return ( iValue >= 0 ? iValue : -iValue ); +} + +//---------------------------------------------------------------------------- +inline int iCeil (double fValue) { + return int(::ceil(fValue)); +} + +//---------------------------------------------------------------------------- + +inline int iClamp(int val, int low, int hi) { + debugAssert(low <= hi); + if (val <= low) { + return low; + } else if (val >= hi) { + return hi; + } else { + return val; + } +} + +//---------------------------------------------------------------------------- + +inline double clamp(double val, double low, double hi) { + debugAssert(low <= hi); + if (val <= low) { + return low; + } else if (val >= hi) { + return hi; + } else { + return val; + } +} + +inline float clamp(float val, float low, float hi) { + debugAssert(low <= hi); + if (val <= low) { + return low; + } else if (val >= hi) { + return hi; + } else { + return val; + } +} +//---------------------------------------------------------------------------- + +inline int iWrap(int val, int hi) { + if (val < 0) { + return ((val % hi) + hi) % hi; + } else { + return val % hi; + } +} + +//---------------------------------------------------------------------------- +inline int iFloor (double fValue) { + return int(::floor(fValue)); +} + +//---------------------------------------------------------------------------- +inline int iSign (int iValue) { + return ( iValue > 0 ? + 1 : ( iValue < 0 ? -1 : 0 ) ); +} + +inline int iSign (double fValue) { + return ( fValue > 0.0 ? + 1 : ( fValue < 0.0 ? -1 : 0 ) ); +} + +//---------------------------------------------------------------------------- +inline double abs (double fValue) { + return double(::fabs(fValue)); +} + +//---------------------------------------------------------------------------- +inline double aCos (double fValue) { + if ( -1.0 < fValue ) { + if ( fValue < 1.0 ) + return double(::acos(fValue)); + else + return 0.0; + } else { + return G3D_PI; + } +} + +//---------------------------------------------------------------------------- +inline double aSin (double fValue) { + if ( -1.0 < fValue ) { + if ( fValue < 1.0 ) { + return double(::asin(fValue)); + } else { + return -G3D_HALF_PI; + } + } else { + return G3D_HALF_PI; + } +} + +//---------------------------------------------------------------------------- +inline double aTan (double fValue) { + return double(::atan(fValue)); +} + +//---------------------------------------------------------------------------- +inline double aTan2 (double fY, double fX) { + return double(::atan2(fY, fX)); +} + +//---------------------------------------------------------------------------- +inline double sign (double fValue) { + if (fValue > 0.0) { + return 1.0; + } + + if (fValue < 0.0) { + return -1.0; + } + + return 0.0; +} + +inline double G3D_DEPRECATED unitRandom () { + return double(::rand()) / double(RAND_MAX); +} + +inline float uniformRandom(float low, float hi) { + return (hi - low) * float(::rand()) / float(RAND_MAX) + low; +} + + +//---------------------------------------------------------------------------- +inline double G3D_DEPRECATED symmetricRandom () { + return 2.0 * double(::rand()) / double(RAND_MAX) - 1.0; +} + +//---------------------------------------------------------------------------- +inline double square(double x) { + return x * x; +} + +//---------------------------------------------------------------------------- +inline double sumSquares(double x, double y) { + return x*x + y*y; +} + +//---------------------------------------------------------------------------- +inline double sumSquares(double x, double y, double z) { + return x*x + y*y + z*z; +} + +//---------------------------------------------------------------------------- +inline double distance(double x, double y) { + return sqrt(sumSquares(x, y)); +} + +//---------------------------------------------------------------------------- +inline double distance(double x, double y, double z) { + return sqrt(sumSquares(x, y, z)); +} + +//---------------------------------------------------------------------------- + +/** @deprecated use G3D::min */ +inline int iMin(int x, int y) { + return (x >= y) ? y : x; +} + +//---------------------------------------------------------------------------- +/** @deprecated use G3D::min */ +inline int iMax(int x, int y) { + return (x >= y) ? x : y; +} + +//---------------------------------------------------------------------------- +inline int ceilPow2(unsigned int in) { + in -= 1; + + in |= in >> 16; + in |= in >> 8; + in |= in >> 4; + in |= in >> 2; + in |= in >> 1; + + return in + 1; +} + +inline bool isPow2(int num) { + return ((num & -num) == num); +} + +inline bool isOdd(int num) { + return (num & 1) == 1; +} + +inline bool isEven(int num) { + return (num & 1) == 0; +} + +inline double toRadians(double deg) { + return deg * G3D_PI / 180.0; +} + +inline double toDegrees(double rad) { + return rad * 180.0 / G3D_PI; +} + +/** + Computes an appropriate epsilon for comparing a and b. + */ +inline double eps(double a, double b) { + // For a and b to be nearly equal, they must have nearly + // the same magnitude. This means that we can ignore b + // since it either has the same magnitude or the comparison + // will fail anyway. + (void)b; + const double aa = abs(a) + 1; + if (aa == inf()) { + return fuzzyEpsilon; + } else { + return fuzzyEpsilon * aa; + } +} + +inline bool fuzzyEq(double a, double b) { + return (a == b) || (abs(a - b) <= eps(a, b)); +} + +inline bool fuzzyNe(double a, double b) { + return ! fuzzyEq(a, b); +} + +inline bool fuzzyGt(double a, double b) { + return a > b + eps(a, b); +} + +inline bool fuzzyGe(double a, double b) { + return a > b - eps(a, b); +} + +inline bool fuzzyLt(double a, double b) { + return a < b - eps(a, b); +} + +inline bool fuzzyLe(double a, double b) { + return a < b + eps(a, b); +} + +inline int iMod3(int x) { + return x % 3; +} + +} // namespace G3D + +#ifdef _MSC_VER +// Disable conditional expression is constant, which occurs incorrectly on inlined functions +# pragma warning (pop) +#endif diff --git a/dep/include/g3dlite/G3D/platform.h b/dep/include/g3dlite/G3D/platform.h new file mode 100644 index 00000000000..fed9c7b5324 --- /dev/null +++ b/dep/include/g3dlite/G3D/platform.h @@ -0,0 +1,269 @@ +/** + @file platform.h + + #defines for platform specific issues. + + @maintainer Morgan McGuire, matrix@graphics3d.com + + @created 2003-06-09 + @edited 2006-01-16 + */ + +#ifndef G3D_PLATFORM_H +#define G3D_PLATFORM_H + +/** + The version number of G3D in the form: MmmBB -> + version M.mm [beta BB] + */ +#define G3D_VER 61000 + +#if defined(G3D_RELEASEDEBUG) +# define G3D_DEBUGRELEASE +#endif + +#if defined(G3D_DEBUGRELEASE) && defined(_DEBUG) +# undef _DEBUG +#endif + +#if !defined(G3D_DEBUG) && (defined(_DEBUG) || defined(G3D_DEBUGRELEASE)) +# define G3D_DEBUG +#endif + +#ifdef _MSC_VER + #define G3D_WIN32 +#elif defined(__MINGW32__) + #define G3D_WIN32 + #define G3D_MINGW32 +#elif defined(__linux__) + #define G3D_LINUX +#elif defined(__OpenBSD__) + #define G3D_LINUX +#elif defined(__FreeBSD__) + #define G3D_LINUX +#elif defined(__NetBSD__) + #define G3D_LINUX +#elif defined(__APPLE__) + #define G3D_OSX +#else + #error Unknown platform +#endif + + +// Default to compiling with SSE, but if you want to compile +// without installing SP5.0 and the Processor Pack on Windows, compile with NO_SSE +// defined (can be passed to the compiler command line with /D "NO_SSE") +#if !defined(NO_SSE) + #define SSE +#endif + +#ifdef G3D_WIN32 +// Turn off warnings about deprecated C routines (TODO: revisit) +# pragma warning (disable : 4996) +#endif + +// On g++, recognize cases where the -msse2 flag was not specified +#if defined(SSE) && defined(__GNUC__) && ! defined (__SSE__) +# undef SSE +#endif + +#if defined(__GNUC__) +# if __STDC_VERSION__ < 199901 +# define restrict __restrict__ +# endif +#endif + + +// Verify that the supported compilers are being used and that this is a known +// processor. + +#ifdef G3D_LINUX +# ifndef __GNUC__ +# error G3D only supports the gcc compiler on Linux. +# endif + +//# ifndef __i386__ +//# error G3D only supports x86 machines on Linux. +//# endif + +# define G3D_DEPRECATED __attribute__((__deprecated__)) + +# ifndef __cdecl +# define __cdecl __attribute__((cdecl)) +# endif + +# ifndef __stdcall +# define __stdcall __attribute__((stdcall)) +# endif + +# define G3D_CHECK_PRINTF_METHOD_ARGS __attribute__((__format__(__printf__, 2, 3))) +# define G3D_CHECK_VPRINTF_METHOD_ARGS __attribute__((__format__(__printf__, 2, 0))) +# define G3D_CHECK_PRINTF_ARGS __attribute__((__format__(__printf__, 1, 2))) +# define G3D_CHECK_VPRINTF_ARGS __attribute__((__format__(__printf__, 1, 0))) +#endif + + +#ifdef G3D_OSX + #ifndef __GNUC__ + #error G3D only supports the gcc compiler on OS X. + #endif + + #if defined(__i386__) + #define G3D_OSX_INTEL + #elif defined(__PPC__) + #define G3D_OSX_PPC + #else + #define G3D_OSX_UNKNOWN + #endif + +# ifndef __cdecl +# define __cdecl __attribute__((cdecl)) +# endif + +# ifndef __stdcall +# define __stdcall __attribute__((stdcall)) +# endif + +# define G3D_DEPRECATED __attribute__((__deprecated__)) + +# define G3D_CHECK_PRINTF_METHOD_ARGS __attribute__((__format__(__printf__, 2, 3))) +# define G3D_CHECK_VPRINTF_METHOD_ARGS __attribute__((__format__(__printf__, 2, 0))) +# define G3D_CHECK_PRINTF_ARGS __attribute__((__format__(__printf__, 1, 2))) +# define G3D_CHECK_VPRINTF_ARGS __attribute__((__format__(__printf__, 1, 0))) +#endif + + +#ifdef G3D_WIN32 +// Microsoft Visual C++ 7.1 _MSC_VER = 1310 +// Microsoft Visual C++ 7.0 _MSC_VER = 1300 +// Microsoft Visual C++ 6.0 _MSC_VER = 1200 +// Microsoft Visual C++ 5.0 _MSC_VER = 1100 + + // Old versions of MSVC (6.0 and previous) don't + // support C99 for loop scoping rules. This fixes them. +# if (_MSC_VER <= 1200) + // This trick will generate a warning; disable the warning +# pragma warning (disable : 4127) +# define for if (false) {} else for +# endif + +# if (_MSC_VER <= 1200) +// Nothing we can do on VC6 for deprecated functions +# define G3D_DEPRECATED +# else +# define G3D_DEPRECATED __declspec(deprecated) +# endif + +// Prevent Winsock conflicts by hiding the winsock API +#ifndef _WINSOCKAPI_ +# define _G3D_INTERNAL_HIDE_WINSOCK_ +# define _WINSOCKAPI_ +# endif + +// Disable 'name too long for browse information' warning +# pragma warning (disable : 4786) +// TODO: remove +# pragma warning (disable : 4244) + +# if defined(_MSC_VER) && (_MSC_VER <= 1200) + // VC6 std:: has signed problems in it +# pragma warning (disable : 4018) +# endif + +# define ZLIB_WINAPI + +// Mingw32 defines restrict +# ifndef G3D_MINGW32 +# define restrict +# endif + +# define G3D_CHECK_PRINTF_ARGS +# define G3D_CHECK_VPRINTF_ARGS +# define G3D_CHECK_PRINTF_METHOD_ARGS +# define G3D_CHECK_VPRINTF_METHOD_ARGS + + // On MSVC, we need to link against the multithreaded DLL version of + // the C++ runtime because that is what SDL and ZLIB are compiled + // against. This is not the default for MSVC, so we set the following + // defines to force correct linking. + // + // For documentation on compiler options, see: + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/_core_.2f.md.2c_2f.ml.2c_2f.mt.2c_2f.ld.asp + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/HTML/_core_Compiler_Reference.asp + // + +#if 0 //ignore that for mangos + // DLL runtime + #ifndef _DLL + #define _DLL + #endif + + // Multithreaded runtime + #ifndef _MT + #define _MT 1 + #endif + // Ensure that we aren't forced into the static lib + #ifdef _STATIC_CPPLIB + #undef _STATIC_CPPLIB + #endif +#endif + + #ifdef _DEBUG + #pragma comment (linker, "/NODEFAULTLIB:libc.lib") + #pragma comment (linker, "/NODEFAULTLIB:libcmt.lib") + #pragma comment (linker, "/NODEFAULTLIB:msvcrt.lib") + #pragma comment (linker, "/NODEFAULTLIB:libcd.lib") + #pragma comment (linker, "/NODEFAULTLIB:msvcrtd.lib") + #else + #pragma comment(linker, "/NODEFAULTLIB:LIBC.LIB") + #pragma comment(linker, "/NODEFAULTLIB:msvcrt.lib") + #pragma comment(linker, "/NODEFAULTLIB:libcd.lib") + #pragma comment(linker, "/NODEFAULTLIB:libcmtd.lib") + #pragma comment(linker, "/NODEFAULTLIB:msvcrtd.lib") + #endif + + // Now set up external linking + + #ifdef _DEBUG + // zlib and SDL were linked against the release MSVCRT; force + // the debug version. + #pragma comment(linker, "/NODEFAULTLIB:MSVCRT.LIB") +# endif + +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN 1 +# endif + + +# define NOMINMAX 1 +# include +# undef WIN32_LEAN_AND_MEAN +# undef NOMINMAX + +#ifdef _G3D_INTERNAL_HIDE_WINSOCK_ +# undef _G3D_INTERNAL_HIDE_WINSOCK_ +# undef _WINSOCKAPI_ +#endif + +#endif + +# if defined(_MSC_VER) && (_MSC_VER <= 1200) + // VC6 std:: has signed/unsigned problems +# pragma warning (disable : 4018) +# endif + +/** + @def STR(expression) + + Creates a string from the expression. Frequently used with G3D::Shader + to express shading programs inline. + + STR(this becomes a string)
 evaluates the same as "this becomes a string"
+ */
+#define STR(x) #x
+
+#undef G3D_DEPRECATED
+#define G3D_DEPRECATED
+
+// Header guard
+#endif
diff --git a/dep/include/g3dlite/G3D/stringutils.h b/dep/include/g3dlite/G3D/stringutils.h
new file mode 100644
index 00000000000..9080d00b6a4
--- /dev/null
+++ b/dep/include/g3dlite/G3D/stringutils.h
@@ -0,0 +1,130 @@
+/**
+ @file stringutils.h
+ 
+ @maintainer Morgan McGuire, matrix@graphics3d.com
+ 
+ @author  2000-09-09
+ @edited  2002-11-30
+ */
+
+#ifndef G3D_STRINGUTILS_H
+#define G3D_STRINGUTILS_H
+
+#include "G3D/platform.h"
+#include "G3D/Array.h"
+#include 
+
+namespace G3D {
+
+extern const char* NEWLINE;
+
+/**
+ Returns true if the test string begins with the pattern string.
+ */
+bool beginsWith(
+    const std::string&          test,
+    const std::string&          pattern);
+
+/**
+ Returns true if the test string ends with the pattern string.
+ */
+bool endsWith(
+    const std::string&          test,
+    const std::string&          pattern);
+
+/**
+ Produces a new string that is the input string
+ wrapped at a certain number of columns (where
+ the line is broken at the latest space before the
+ column limit.)  Platform specific NEWLINEs
+ are inserted to wrap.
+ */
+std::string wordWrap(
+    const std::string&          input,
+    int                         numCols);
+
+/**
+ A comparison function for passing to Array::sort.
+ */
+int stringCompare(
+    const std::string&          s1,
+    const std::string&          s2);
+
+int stringPtrCompare(
+    const std::string*          s1,
+    const std::string*          s2);
+
+/**
+ Returns a new string that is an uppercase version of x.
+ */
+std::string toUpper(
+    const std::string&          x);
+
+std::string toLower(
+    const std::string&          x);
+
+/**
+ Splits x at each occurance of splitChar.
+ */
+G3D::Array stringSplit(
+    const std::string&          x,
+    char                        splitChar);
+
+/**
+ joinChar is not inserted at the beginning or end, just in between
+ elements.
+ */
+std::string stringJoin(
+    const G3D::Array&   a,
+    char                        joinChar);
+
+std::string stringJoin(
+    const G3D::Array&   a,
+    const std::string&               joinStr);
+
+/**
+ Strips whitespace from both ends of the string.
+ */
+std::string trimWhitespace(
+    const std::string&              s);
+
+/** These standard C functions are renamed for clarity/naming
+   conventions and to return bool, not int.
+   */
+inline bool isWhiteSpace(const char c) {
+    return isspace(c) != 0;
+}
+
+/** These standard C functions are renamed for clarity/naming
+   conventions and to return bool, not int.
+   */
+inline bool isNewline(const char c) {
+    return (c == '\n') || (c == '\r');
+}
+
+/** These standard C functions are renamed for clarity/naming
+   conventions and to return bool, not int.
+   */
+inline bool isDigit(const char c) {
+    return isdigit(c) != 0;
+}
+
+/** These standard C functions are renamed for clarity/naming
+   conventions and to return bool, not int.
+   */
+inline bool isLetter(const char c) {
+    return isalpha(c) != 0;
+}
+
+inline bool isSlash(const char c) {
+    return (c == '\\') || (c == '/');
+}
+
+inline bool isQuote(const char c) {
+    return (c == '\'') || (c == '\"');
+}
+
+}; // namespace
+
+#endif
+
diff --git a/dep/include/mersennetwister/MersenneTwister.h b/dep/include/mersennetwister/MersenneTwister.h
new file mode 100644
index 00000000000..9c6994bdfb4
--- /dev/null
+++ b/dep/include/mersennetwister/MersenneTwister.h
@@ -0,0 +1,414 @@
+// MersenneTwister.h
+// Mersenne Twister random number generator -- a C++ class MTRand
+// Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
+// Richard J. Wagner  v1.0  15 May 2003  rjwagner@writeme.com
+
+// The Mersenne Twister is an algorithm for generating random numbers.  It
+// was designed with consideration of the flaws in various other generators.
+// The period, 2^19937-1, and the order of equidistribution, 623 dimensions,
+// are far greater.  The generator is also fast; it avoids multiplication and
+// division, and it benefits from caches and pipelines.  For more information
+// see the inventors' web page at http://www.math.keio.ac.jp/~matumoto/emt.html
+
+// Reference
+// M. Matsumoto and T. Nishimura, "Mersenne Twister: A 623-Dimensionally
+// Equidistributed Uniform Pseudo-Random Number Generator", ACM Transactions on
+// Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3-30.
+
+// Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
+// Copyright (C) 2000 - 2003, Richard J. Wagner
+// All rights reserved.                          
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+//   1. Redistributions of source code must retain the above copyright
+//      notice, this list of conditions and the following disclaimer.
+//
+//   2. Redistributions in binary form must reproduce the above copyright
+//      notice, this list of conditions and the following disclaimer in the
+//      documentation and/or other materials provided with the distribution.
+//
+//   3. The names of its contributors may not be used to endorse or promote 
+//      products derived from this software without specific prior written 
+//      permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The original code included the following notice:
+//
+//     When you use this, send an email to: matumoto@math.keio.ac.jp
+//     with an appropriate reference to your work.
+//
+// It would be nice to CC: rjwagner@writeme.com and Cokus@math.washington.edu
+// when you write.
+
+#ifndef MERSENNETWISTER_H
+#define MERSENNETWISTER_H
+
+// Not thread safe (unless auto-initialization is avoided and each thread has
+// its own MTRand object)
+
+#include"Platform/Define.h"
+
+#include 
+#include 
+#include 
+
+class MTRand {
+// Data
+public:
+    typedef ::uint32 uint32;
+	enum { N = 624 };       // length of state vector
+	enum { SAVE = N + 1 };  // length of array for save()
+
+protected:
+	enum { M = 397 };  // period parameter
+	
+	uint32 state[N];   // internal state
+	uint32 *pNext;     // next value to get from state
+	int left;          // number of values left before reload needed
+
+
+//Methods
+public:
+	MTRand( const uint32& oneSeed );  // initialize with a simple uint32
+	MTRand( uint32 *const bigSeed, uint32 const seedLength = N );  // or an array
+	MTRand();                         // auto-initialize with /dev/urandom or time() and clock()
+    MTRand(const MTRand&);            // prevent copy constructor
+    MTRand& operator=(const MTRand&); // no-op operator=
+	
+	// Do NOT use for CRYPTOGRAPHY without securely hashing several returned
+	// values together, otherwise the generator state can be learned after
+	// reading 624 consecutive values.
+	
+	// Access to 32-bit random numbers
+	double rand();                          // real number in [0,1]
+	double rand( const double& n );         // real number in [0,n]
+	double randExc();                       // real number in [0,1)
+	double randExc( const double& n );      // real number in [0,n)
+	double randDblExc();                    // real number in (0,1)
+	double randDblExc( const double& n );   // real number in (0,n)
+	uint32 randInt();                       // integer in [0,2^32-1]
+	uint32 randInt( const uint32& n );      // integer in [0,n] for n < 2^32
+	double operator()() { return rand(); }  // same as rand()
+	
+	// Access to 53-bit random numbers (capacity of IEEE double precision)
+	double rand53();  // real number in [0,1)
+	
+	// Access to nonuniform random number distributions
+	double randNorm( const double& mean = 0.0, const double& variance = 0.0 );
+	
+	// Re-seeding functions with same behavior as initializers
+	void seed( const uint32 oneSeed );
+	void seed( uint32 *const bigSeed, const uint32 seedLength = N );
+	void seed();
+	
+	// Saving and loading generator state
+	void save( uint32* saveArray ) const;  // to array of size SAVE
+	void load( uint32 *const loadArray );  // from such array
+    /* Mangos not use streams for random values output
+	friend std::ostream& operator<<( std::ostream& os, const MTRand& mtrand );
+	friend std::istream& operator>>( std::istream& is, MTRand& mtrand );
+    */
+protected:
+	void initialize( const uint32 oneSeed );
+	void reload();
+	uint32 hiBit( const uint32& u ) const { return u & 0x80000000UL; }
+	uint32 loBit( const uint32& u ) const { return u & 0x00000001UL; }
+	uint32 loBits( const uint32& u ) const { return u & 0x7fffffffUL; }
+	uint32 mixBits( const uint32& u, const uint32& v ) const
+		{ return hiBit(u) | loBits(v); }
+	uint32 twist( const uint32& m, const uint32& s0, const uint32& s1 ) const
+		{ return m ^ (mixBits(s0,s1)>>1) ^ uint32(-(int32)(loBit(s1) & 0x9908b0dfUL)); }
+	static uint32 hash( time_t t, clock_t c );
+};
+
+inline MTRand::MTRand(const MTRand&)
+    { seed(); }
+
+inline MTRand& MTRand::operator=(const MTRand&) 
+    { return *this; }
+
+inline MTRand::MTRand( const uint32& oneSeed )
+	{ seed(oneSeed); }
+
+inline MTRand::MTRand( uint32 *const bigSeed, const uint32 seedLength )
+	{ seed(bigSeed,seedLength); }
+
+inline MTRand::MTRand()
+	{ seed(); }
+
+inline double MTRand::rand()
+	{ return double(randInt()) * (1.0/4294967295.0); }
+
+inline double MTRand::rand( const double& n )
+	{ return rand() * n; }
+
+inline double MTRand::randExc()
+	{ return double(randInt()) * (1.0/4294967296.0); }
+
+inline double MTRand::randExc( const double& n )
+	{ return randExc() * n; }
+
+inline double MTRand::randDblExc()
+	{ return ( double(randInt()) + 0.5 ) * (1.0/4294967296.0); }
+
+inline double MTRand::randDblExc( const double& n )
+	{ return randDblExc() * n; }
+
+inline double MTRand::rand53()
+{
+	uint32 a = randInt() >> 5, b = randInt() >> 6;
+	return ( a * 67108864.0 + b ) * (1.0/9007199254740992.0);  // by Isaku Wada
+}
+
+inline double MTRand::randNorm( const double& mean, const double& variance )
+{
+	// Return a real number from a normal (Gaussian) distribution with given
+	// mean and variance by Box-Muller method
+	double r = sqrt( -2.0 * log( 1.0-randDblExc()) ) * variance;
+	double phi = 2.0 * 3.14159265358979323846264338328 * randExc();
+	return mean + r * cos(phi);
+}
+
+inline MTRand::uint32 MTRand::randInt()
+{
+	// Pull a 32-bit integer from the generator state
+	// Every other access function simply transforms the numbers extracted here
+	
+	if( left == 0 ) reload();
+	--left;
+		
+	register uint32 s1;
+	s1 = *pNext++;
+	s1 ^= (s1 >> 11);
+	s1 ^= (s1 <<  7) & 0x9d2c5680UL;
+	s1 ^= (s1 << 15) & 0xefc60000UL;
+	return ( s1 ^ (s1 >> 18) );
+}
+
+inline MTRand::uint32 MTRand::randInt( const uint32& n )
+{
+	// Find which bits are used in n
+	// Optimized by Magnus Jonsson (magnus@smartelectronix.com)
+	uint32 used = n;
+	used |= used >> 1;
+	used |= used >> 2;
+	used |= used >> 4;
+	used |= used >> 8;
+	used |= used >> 16;
+	
+	// Draw numbers until one is found in [0,n]
+	uint32 i;
+	do
+		i = randInt() & used;  // toss unused bits to shorten search
+	while( i > n );
+	return i;
+}
+
+
+inline void MTRand::seed( const uint32 oneSeed )
+{
+	// Seed the generator with a simple uint32
+	initialize(oneSeed);
+	reload();
+}
+
+
+inline void MTRand::seed( uint32 *const bigSeed, const uint32 seedLength )
+{
+	// Seed the generator with an array of uint32's
+	// There are 2^19937-1 possible initial states.  This function allows
+	// all of those to be accessed by providing at least 19937 bits (with a
+	// default seed length of N = 624 uint32's).  Any bits above the lower 32
+	// in each element are discarded.
+	// Just call seed() if you want to get array from /dev/urandom
+	initialize(19650218UL);
+	register int i = 1;
+	register uint32 j = 0;
+	register int k = ( N > seedLength ? N : seedLength );
+	for( ; k; --k )
+	{
+		state[i] =
+			state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1664525UL );
+		state[i] += ( bigSeed[j] & 0xffffffffUL ) + j;
+		state[i] &= 0xffffffffUL;
+		++i;  ++j;
+		if( i >= N ) { state[0] = state[N-1];  i = 1; }
+		if( j >= seedLength ) j = 0;
+	}
+	for( k = N - 1; k; --k )
+	{
+		state[i] =
+			state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL );
+		state[i] -= i;
+		state[i] &= 0xffffffffUL;
+		++i;
+		if( i >= N ) { state[0] = state[N-1];  i = 1; }
+	}
+	state[0] = 0x80000000UL;  // MSB is 1, assuring non-zero initial array
+	reload();
+}
+
+
+inline void MTRand::seed()
+{
+	// Seed the generator with hash of time() and clock() values
+	seed( hash( time(NULL), clock() ) );
+}
+
+
+inline void MTRand::initialize( const uint32 seed )
+{
+	// Initialize generator state with seed
+	// See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
+	// In previous versions, most significant bits (MSBs) of the seed affect
+	// only MSBs of the state array.  Modified 9 Jan 2002 by Makoto Matsumoto.
+	register uint32 *s = state;
+	register uint32 *r = state;
+	register int i = 1;
+	*s++ = seed & 0xffffffffUL;
+	for( ; i < N; ++i )
+	{
+		*s++ = ( 1812433253UL * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffUL;
+		r++;
+	}
+}
+
+
+inline void MTRand::reload()
+{
+	// Generate N new values in state
+	// Made clearer and faster by Matthew Bellew (matthew.bellew@home.com)
+	register uint32 *p = state;
+	register int i;
+	for( i = N - M; i--; ++p )
+		*p = twist( p[M], p[0], p[1] );
+	for( i = M; --i; ++p )
+		*p = twist( p[M-N], p[0], p[1] );
+	*p = twist( p[M-N], p[0], state[0] );
+
+	left = N, pNext = state;
+}
+
+
+inline MTRand::uint32 MTRand::hash( time_t t, clock_t c )
+{
+	// Get a uint32 from t and c
+	// Better than uint32(x) in case x is floating point in [0,1]
+	// Based on code by Lawrence Kirby (fred@genesis.demon.co.uk)
+
+	static uint32 differ = 0;  // guarantee time-based seeds will change
+
+	uint32 h1 = 0;
+	unsigned char *p = (unsigned char *) &t;
+	for( size_t i = 0; i < sizeof(t); ++i )
+	{
+		h1 *= UCHAR_MAX + 2U;
+		h1 += p[i];
+	}
+	uint32 h2 = 0;
+	p = (unsigned char *) &c;
+	for( size_t j = 0; j < sizeof(c); ++j )
+	{
+		h2 *= UCHAR_MAX + 2U;
+		h2 += p[j];
+	}
+	return ( h1 + differ++ ) ^ h2;
+}
+
+
+inline void MTRand::save( uint32* saveArray ) const
+{
+	register uint32 *sa = saveArray;
+	register const uint32 *s = state;
+	register int i = N;
+	for( ; i--; *sa++ = *s++ ) {}
+	*sa = left;
+}
+
+
+inline void MTRand::load( uint32 *const loadArray )
+{
+	register uint32 *s = state;
+	register uint32 *la = loadArray;
+	register int i = N;
+	for( ; i--; *s++ = *la++ ) {}
+	left = *la;
+	pNext = &state[N-left];
+}
+
+/* Mangos not use streams for random values output
+inline std::ostream& operator<<( std::ostream& os, const MTRand& mtrand )
+{
+	register const MTRand::uint32 *s = mtrand.state;
+	register int i = mtrand.N;
+	for( ; i--; os << *s++ << "\t" ) {}
+	return os << mtrand.left;
+}
+
+
+inline std::istream& operator>>( std::istream& is, MTRand& mtrand )
+{
+	register MTRand::uint32 *s = mtrand.state;
+	register int i = mtrand.N;
+	for( ; i--; is >> *s++ ) {}
+	is >> mtrand.left;
+	mtrand.pNext = &mtrand.state[mtrand.N-mtrand.left];
+	return is;
+}
+*/
+
+#endif  // MERSENNETWISTER_H
+
+// Change log:
+//
+// v0.1 - First release on 15 May 2000
+//      - Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
+//      - Translated from C to C++
+//      - Made completely ANSI compliant
+//      - Designed convenient interface for initialization, seeding, and
+//        obtaining numbers in default or user-defined ranges
+//      - Added automatic seeding from /dev/urandom or time() and clock()
+//      - Provided functions for saving and loading generator state
+//
+// v0.2 - Fixed bug which reloaded generator one step too late
+//
+// v0.3 - Switched to clearer, faster reload() code from Matthew Bellew
+//
+// v0.4 - Removed trailing newline in saved generator format to be consistent
+//        with output format of built-in types
+//
+// v0.5 - Improved portability by replacing static const int's with enum's and
+//        clarifying return values in seed(); suggested by Eric Heimburg
+//      - Removed MAXINT constant; use 0xffffffffUL instead
+//
+// v0.6 - Eliminated seed overflow when uint32 is larger than 32 bits
+//      - Changed integer [0,n] generator to give better uniformity
+//
+// v0.7 - Fixed operator precedence ambiguity in reload()
+//      - Added access for real numbers in (0,1) and (0,n)
+//
+// v0.8 - Included time.h header to properly support time_t and clock_t
+//
+// v1.0 - Revised seeding to match 26 Jan 2002 update of Nishimura and Matsumoto
+//      - Allowed for seeding with arrays of any length
+//      - Added access for real numbers in [0,1) with 53-bit resolution
+//      - Added access for real numbers from normal (Gaussian) distributions
+//      - Increased overall speed by optimizing twist()
+//      - Doubled speed of integer [0,n] generation
+//      - Fixed out-of-range number generation on 64-bit machines
+//      - Improved portability by substituting literal constants for long enum's
+//      - Changed license from GNU LGPL to BSD
diff --git a/dep/include/mysql/Libmysql.def b/dep/include/mysql/Libmysql.def
new file mode 100644
index 00000000000..81f86dc8726
--- /dev/null
+++ b/dep/include/mysql/Libmysql.def
@@ -0,0 +1,153 @@
+LIBRARY		LIBMYSQL
+VERSION		6.0
+EXPORTS
+	_dig_vec_lower
+	_dig_vec_upper
+	bmove_upp
+	delete_dynamic
+	free_defaults
+	getopt_compare_strings
+	getopt_ull_limit_value
+	handle_options
+	init_dynamic_array
+	insert_dynamic
+	int2str
+	is_prefix
+	list_add
+	list_delete
+	load_defaults
+	my_end
+	my_getopt_print_errors
+	my_init
+	my_malloc
+	my_memdup
+	my_no_flags_free
+	my_path
+	mysql_get_parameters
+	my_print_help
+	my_print_variables
+	my_realloc
+	my_strdup
+	mysql_thread_end
+	mysql_thread_init
+	myodbc_remove_escape
+	mysql_affected_rows
+	mysql_autocommit
+	mysql_stmt_bind_param
+	mysql_stmt_bind_result
+	mysql_change_user
+	mysql_character_set_name
+	mysql_close
+	mysql_commit
+	mysql_data_seek
+	mysql_debug
+	mysql_dump_debug_info
+	mysql_eof
+	mysql_errno
+	mysql_error
+	mysql_escape_string
+	mysql_hex_string
+	mysql_stmt_execute
+	mysql_stmt_fetch
+	mysql_stmt_fetch_column
+	mysql_fetch_field
+	mysql_fetch_field_direct
+	mysql_fetch_fields
+	mysql_fetch_lengths
+	mysql_fetch_row
+	mysql_field_count
+	mysql_field_seek
+	mysql_field_tell
+	mysql_free_result
+	mysql_get_client_info
+	mysql_get_host_info
+	mysql_get_proto_info
+	mysql_get_server_info
+	mysql_get_client_version
+	mysql_get_ssl_cipher
+	mysql_info
+	mysql_init
+	mysql_insert_id
+	mysql_kill
+	mysql_set_server_option
+	mysql_list_dbs
+	mysql_list_fields
+	mysql_list_processes
+	mysql_list_tables
+	mysql_more_results
+	mysql_next_result
+	mysql_num_fields
+	mysql_num_rows
+	mysql_options
+	mysql_stmt_param_count
+	mysql_stmt_param_metadata
+	mysql_ping
+	mysql_stmt_result_metadata
+	mysql_query
+	mysql_read_query_result
+	mysql_real_connect
+	mysql_real_escape_string
+	mysql_real_query
+	mysql_refresh
+	mysql_rollback
+	mysql_row_seek
+	mysql_row_tell
+	mysql_select_db
+	mysql_stmt_send_long_data
+	mysql_send_query
+	mysql_shutdown
+	mysql_ssl_set
+	mysql_stat
+	mysql_stmt_affected_rows
+	mysql_stmt_close
+	mysql_stmt_reset
+	mysql_stmt_data_seek
+	mysql_stmt_errno
+	mysql_stmt_error
+	mysql_stmt_free_result
+	mysql_stmt_num_rows
+	mysql_stmt_row_seek
+	mysql_stmt_row_tell
+	mysql_stmt_store_result
+	mysql_store_result
+	mysql_thread_id
+	mysql_thread_safe
+	mysql_use_result
+	mysql_warning_count
+	mysql_stmt_sqlstate
+	mysql_sqlstate
+	mysql_get_server_version
+	set_dynamic
+	strcend
+	strcont
+	strdup_root
+	strfill
+	strinstr
+	strmake
+	strmov
+	strxmov
+	mysql_stmt_prepare
+	mysql_stmt_init
+	mysql_stmt_insert_id
+	mysql_stmt_attr_get
+	mysql_stmt_attr_set
+	mysql_stmt_field_count
+	client_errors
+	mysql_set_local_infile_default
+	mysql_set_local_infile_handler
+	mysql_disable_reads_from_master
+	mysql_disable_rpl_parse
+	mysql_enable_reads_from_master
+	mysql_enable_rpl_parse
+	mysql_master_query
+	mysql_rpl_parse_enabled
+	mysql_rpl_probe
+	mysql_rpl_query_type
+	mysql_slave_query
+	mysql_embedded
+	mysql_server_init
+	mysql_server_end
+	mysql_set_character_set
+	mysql_get_character_set_info
+	get_defaults_options
+	modify_defaults_file
diff --git a/dep/include/mysql/config-netware.h b/dep/include/mysql/config-netware.h
new file mode 100644
index 00000000000..9c99305789a
--- /dev/null
+++ b/dep/include/mysql/config-netware.h
@@ -0,0 +1,141 @@
+/* Copyright (C) 2000 MySQL AB
+
+   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; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+/* Header for NetWare compatible with MySQL */
+
+#ifndef _config_netware_h
+#define _config_netware_h
+
+/* required headers */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* required adjustments */
+#undef HAVE_READDIR_R
+#undef HAVE_RWLOCK_INIT
+#undef HAVE_SCHED_H
+#undef HAVE_SYS_MMAN_H
+#undef HAVE_SYNCH_H
+#undef HAVE_MMAP
+#undef HAVE_RINT
+
+#define HAVE_PTHREAD_ATTR_SETSTACKSIZE 1
+#define HAVE_PTHREAD_SIGMASK 1
+#define HAVE_PTHREAD_YIELD_ZERO_ARG 1
+#define HAVE_BROKEN_REALPATH 1
+
+/* changes made to make use of LibC-June-2004 for building purpose */
+#undef HAVE_POSIX_SIGNALS
+#undef HAVE_PTHREAD_ATTR_SETSCOPE
+#undef HAVE_ALLOC_A
+#undef HAVE_FINITE
+#undef HAVE_GETPWNAM
+#undef HAVE_GETPWUID
+#undef HAVE_PTHREAD_SETSCHEDPARAM
+#undef HAVE_READLINK
+#undef HAVE_STPCPY
+/* changes  end  */
+
+/* no libc crypt() function */
+#ifdef HAVE_OPENSSL
+  #define HAVE_CRYPT 1
+#else
+  #undef HAVE_CRYPT
+#endif /* HAVE_OPENSSL */
+
+/* Netware has an ancient zlib */
+#undef HAVE_COMPRESS
+#define HAVE_COMPRESS
+#undef HAVE_ARCHIVE_DB
+
+/* include the old function apis */
+#define USE_OLD_FUNCTIONS 1
+
+/* no case sensitivity */
+#define FN_NO_CASE_SENCE 1
+
+/* the thread alarm is not used */
+#define DONT_USE_THR_ALARM 1
+
+/* signals do not interrupt sockets */
+#define SIGNALS_DONT_BREAK_READ 1
+
+/* signal by closing the sockets */
+#define SIGNAL_WITH_VIO_CLOSE 1
+
+/* On NetWare, stack grows towards lower address*/
+#define STACK_DIRECTION -1
+
+/* On NetWare, we need to set stack size for threads, otherwise default 16K is used */
+#define NW_THD_STACKSIZE 65536
+
+/* On NetWare, to fix the problem with the deletion of open files */
+#define CANT_DELETE_OPEN_FILES 1
+
+#define FN_LIBCHAR '\\'
+#define FN_ROOTDIR "\\"
+#define FN_DEVCHAR ':'
+
+/* default directory information */
+#define	DEFAULT_MYSQL_HOME    "sys:/mysql"
+#define PACKAGE               "mysql"
+#define DEFAULT_BASEDIR       "sys:/"
+#define SHAREDIR              "share/"
+#define DEFAULT_CHARSET_HOME  "sys:/mysql/"
+#define DATADIR               "data/"
+
+/* 64-bit file system calls */
+#define SIZEOF_OFF_T          8
+#define off_t                 off64_t
+#define chsize                chsize64
+#define ftruncate             ftruncate64
+#define lseek                 lseek64
+#define pread                 pread64
+#define pwrite                pwrite64
+#define tell                  tell64
+
+/* do not use the extended time in LibC sys\stat.h */
+#define _POSIX_SOURCE
+
+/* Some macros for portability */
+
+#define set_timespec(ABSTIME,SEC) { (ABSTIME).tv_sec=time(NULL)+(SEC); (ABSTIME).tv_nsec=0; }
+
+/* extra protection against CPU Hogs on NetWare */
+#define NETWARE_YIELD pthread_yield()
+/* Screen mode for help texts */
+#define NETWARE_SET_SCREEN_MODE(A) setscreenmode(A)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _config_netware_h */
diff --git a/dep/include/mysql/config-os2.h b/dep/include/mysql/config-os2.h
new file mode 100644
index 00000000000..8e2d0e2e836
--- /dev/null
+++ b/dep/include/mysql/config-os2.h
@@ -0,0 +1,835 @@
+/* Copyright (C) 2000 MySQL AB & Yuri Dario
+   All the above parties has a full, independent copyright to
+   the following code, including the right to use the code in
+   any manner without any demands from the other parties.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; version 2
+   of the License.
+
+   This library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA */
+
+/* Defines for OS2 to make it compatible for MySQL */
+
+#ifndef __CONFIG_OS2_H__
+#define __CONFIG_OS2_H__
+
+#include 
+#include 
+#include 
+#include 
+
+/* Define to name of system eg solaris*/
+#define SYSTEM_TYPE "IBM OS/2 Warp"
+/* Define to machine type name eg sun10 */
+#define MACHINE_TYPE "i686"
+/* Name of package */
+#define PACKAGE "mysql"
+/* Version number of package */
+#define VERSION MYSQL_SERVER_VERSION
+/* Default socket */
+#define MYSQL_UNIX_ADDR "\\socket\\MySQL"
+
+#define FN_LIBCHAR		 '\\'
+#define FN_ROOTDIR		 "\\"
+#define MY_NFILE		1024  /* This is only used to save filenames */
+
+#define HAVE_ACCESS
+
+#define DEFAULT_MYSQL_HOME	"c:\\mysql"
+#define DEFAULT_BASEDIR		"C:\\"
+#define SHAREDIR		"share"
+#define DEFAULT_CHARSET_HOME	"C:/mysql/"
+#define _POSIX_PATH_MAX		255
+#define DWORD			ULONG
+
+#define O_SHARE		0x1000		/* Open file in sharing mode */
+#define FILE_BINARY	O_BINARY	/* my_fopen in binary mode */
+#define S_IROTH		S_IREAD		/* for my_lib */
+
+#define CANT_DELETE_OPEN_FILES		/* saves open files in a list, for delayed delete */
+
+#define O_NONBLOCK	0x10
+
+#define NO_OPEN_3			/* For my_create() */
+#define SIGQUIT		SIGTERM		/* No SIGQUIT */
+#define SIGALRM		14		/* Alarm */
+
+#define NO_FCNTL_NONBLOCK
+
+#define EFBIG			   E2BIG
+/*#define ENFILE		  EMFILE    */
+/*#define ENAMETOOLONG		(EOS2ERR+2) */
+/*#define ETIMEDOUT		  145       */
+/*#define EPIPE			  146       */
+#define EROFS			147
+
+#define sleep(A)	DosSleep((A)*1000)
+#define closesocket(A)	soclose(A)
+
+#define F_OK		0
+#define W_OK		2
+
+#define bzero(x,y)	memset((x),'\0',(y))
+#define bcopy(x,y,z)	memcpy((y),(x),(z))
+#define bcmp(x,y,z)	memcmp((y),(x),(z))
+
+#define F_RDLCK		4	    /* Read lock.  */
+#define F_WRLCK		2	    /* Write lock.  */
+#define F_UNLCK		0	    /* Remove lock.  */
+
+#define S_IFMT		0x17000	    /* Mask for file type */
+#define F_TO_EOF	0L	    /* Param to lockf() to lock rest of file */
+
+#define HUGE_PTR
+
+#ifdef __cplusplus
+extern "C"
+#endif
+double _cdecl rint( double nr);
+
+DWORD	 TlsAlloc( void);
+BOOL	 TlsFree( DWORD);
+PVOID	 TlsGetValue( DWORD);
+BOOL	 TlsSetValue( DWORD, PVOID);
+
+/* support for > 2GB file size */
+#define SIZEOF_OFF_T	8
+#define lseek(A,B,C)	_lseek64( A, B, C)
+#define tell(A)		_lseek64( A, 0, SEEK_CUR)
+
+void* dlopen( char* path, int flag);
+char* dlerror( void);
+void* dlsym( void* hmod, char* fn);
+void  dlclose( void* hmod);
+
+/* Some typedefs */
+typedef unsigned long long os_off_t;
+
+/* config.h.  Generated automatically by configure.  */
+/* config.h.in.  Generated automatically from configure.in by autoheader.  */
+
+/* Define if using alloca.c.  */
+/* #undef C_ALLOCA */
+
+/* Define to empty if the keyword does not work.  */
+/* #undef const */
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+   This function is required for alloca.c support on those systems.  */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define if you have alloca, as a function or macro.  */
+#define HAVE_ALLOCA 1
+
+/* Define if you have  and it should be used (not on Ultrix).  */
+/* #define HAVE_ALLOCA_H 1 */
+
+/* Define if you don't have vprintf but do have _doprnt.  */
+/* #undef HAVE_DOPRNT */
+
+/* Define if you have a working `mmap' system call.  */
+/* #undef HAVE_MMAP */
+
+/* Define if system calls automatically restart after interruption
+   by a signal.  */
+/* #undef HAVE_RESTARTABLE_SYSCALLS */
+
+/* Define if your struct stat has st_rdev.  */
+#define HAVE_ST_RDEV 1
+
+/* Define if you have  that is POSIX.1 compatible.	*/
+/* #define HAVE_SYS_WAIT_H 1 */
+
+/* Define if you don't have tm_zone but do have the external array
+   tzname.  */
+#define HAVE_TZNAME 1
+
+/* Define if utime(file, NULL) sets file's timestamp to the present.  */
+#define HAVE_UTIME_NULL 1
+
+/* Define if you have the vprintf function.  */
+#define HAVE_VPRINTF 1
+
+/* Define as __inline if that's what the C compiler calls it.  */
+/* #undef inline */
+
+/* Define to `long' if  doesn't define.  */
+/* #undef off_t */
+
+/* Define as the return type of signal handlers (int or void).	*/
+#define RETSIGTYPE void
+
+/* Define to `unsigned' if  doesn't define.  */
+/* #undef size_t */
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+#define STACK_DIRECTION -1
+
+/* Define if the `S_IS*' macros in  do not work properly.  */
+/* #undef STAT_MACROS_BROKEN */
+
+/* Define if you have the ANSI C header files.	*/
+#define STDC_HEADERS 1
+
+/* Define if you can safely include both  and .  */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define if your  declares struct tm.  */
+/* #undef TM_IN_SYS_TIME */
+
+/* Define if your processor stores words with the most significant
+   byte first (like Motorola and SPARC, unlike Intel and VAX).	*/
+/* #undef WORDS_BIGENDIAN */
+
+/* Version of .frm files */
+#define DOT_FRM_VERSION 6
+
+/* READLINE: */
+#define FIONREAD_IN_SYS_IOCTL 1
+
+/* READLINE: Define if your system defines TIOCGWINSZ in sys/ioctl.h.  */
+/* #undef GWINSZ_IN_SYS_IOCTL */
+
+/* Do we have FIONREAD */
+#define FIONREAD_IN_SYS_IOCTL 1
+
+/* atomic_add() from  (Linux only) */
+/* #undef HAVE_ATOMIC_ADD */
+
+/* atomic_sub() from  (Linux only) */
+/* #undef HAVE_ATOMIC_SUB */
+
+/* bool is not defined by all C++ compilators */
+#define HAVE_BOOL 1
+
+/* Have berkeley db installed */
+/* #define HAVE_BERKELEY_DB 1 */
+
+/* DSB style signals ? */
+/* #undef HAVE_BSD_SIGNALS */
+
+/* Can netinet be included */
+/* #undef HAVE_BROKEN_NETINET_INCLUDES */
+
+/* READLINE: */
+/* #undef HAVE_BSD_SIGNALS */
+
+/* ZLIB and compress: */
+#define HAVE_COMPRESS 1
+
+/* Define if we are using OSF1 DEC threads */
+/* #undef HAVE_DEC_THREADS */
+
+/* Define if we are using OSF1 DEC threads on 3.2 */
+/* #undef HAVE_DEC_3_2_THREADS */
+
+/* fp_except from ieeefp.h */
+/* #undef HAVE_FP_EXCEPT */
+
+/* READLINE: */
+/* #undef HAVE_GETPW_DECLS */
+
+/* Solaris define gethostbyname_r with 5 arguments. glibc2 defines
+   this with 6 arguments */
+/* #undef HAVE_GETHOSTBYNAME_R_GLIBC2_STYLE */
+
+/* In OSF 4.0f the 3'd argument to gethostname_r is hostent_data * */
+/* #undef HAVE_GETHOSTBYNAME_R_RETURN_INT */
+
+/* Define if int8, int16 and int32 types exist */
+/* #undef HAVE_INT_8_16_32 */
+
+/* Define if have -lwrap */
+/* #undef HAVE_LIBWRAP */
+
+/* Define if we are using Xavier Leroy's LinuxThreads */
+/* #undef HAVE_LINUXTHREADS */
+
+/* Do we use user level threads */
+/* #undef HAVE_mit_thread */
+
+/* For some non posix threads */
+/* #undef HAVE_NONPOSIX_PTHREAD_GETSPECIFIC */
+
+/* For some non posix threads */
+/* #undef HAVE_NONPOSIX_PTHREAD_MUTEX_INIT */
+
+/* READLINE: */
+#define HAVE_POSIX_SIGNALS 0
+
+/* sigwait with one argument */
+/* #undef HAVE_NONPOSIX_SIGWAIT */
+
+/* pthread_attr_setscope */
+#define HAVE_PTHREAD_ATTR_SETSCOPE 1
+
+/* POSIX readdir_r */
+/* #undef HAVE_READDIR_R */
+
+/* POSIX sigwait */
+/* #undef HAVE_SIGWAIT */
+
+/* crypt */
+#define HAVE_CRYPT 1
+
+/* Solaris define gethostbyaddr_r with 7 arguments. glibc2 defines
+   this with 8 arguments */
+/* #undef HAVE_SOLARIS_STYLE_GETHOST */
+
+/* Timespec has a ts_sec instead of tv_sev  */
+#define HAVE_TIMESPEC_TS_SEC 1
+
+/* Have the tzname variable */
+#define HAVE_TZNAME 1
+
+/* Define if the system files define uchar */
+/* #undef HAVE_UCHAR */
+
+/* Define if the system files define uint */
+/* #undef HAVE_UINT */
+
+/* Define if the system files define ulong */
+/* #undef HAVE_ULONG */
+
+/* UNIXWARE7 threads are not posix */
+/* #undef HAVE_UNIXWARE7_THREADS */
+
+/* new UNIXWARE7 threads that are not yet posix */
+/* #undef HAVE_UNIXWARE7_POSIX */
+
+/* READLINE: */
+/* #undef HAVE_USG_SIGHOLD */
+
+/* Define if want -lwrap */
+/* #undef LIBWRAP */
+
+/* mysql client protocoll version */
+#define PROTOCOL_VERSION 10
+
+/* Define if qsort returns void */
+#define QSORT_TYPE_IS_VOID 1
+
+/* Define as the return type of qsort (int or void). */
+#define RETQSORTTYPE void
+
+/* Define as the base type of the last arg to accept */
+#define SOCKET_SIZE_TYPE int
+
+/* Last argument to get/setsockopt */
+/* #undef SOCKOPT_OPTLEN_TYPE */
+
+/* #undef SPEED_T_IN_SYS_TYPES */
+/* #undef SPRINTF_RETURNS_PTR */
+#define SPRINTF_RETURNS_INT 1
+/* #undef SPRINTF_RETURNS_GARBAGE */
+
+/* #undef STRUCT_DIRENT_HAS_D_FILENO */
+#define STRUCT_DIRENT_HAS_D_INO 1
+
+/* Define if you want to have threaded code. This may be undef on client code */
+#define THREAD 1
+
+/* Should be client be thread safe */
+/* #undef THREAD_SAFE_CLIENT */
+
+/* READLINE: */
+/* #undef TIOCSTAT_IN_SYS_IOCTL */
+
+/* Use multi-byte character routines */
+/* #undef USE_MB */
+/* #undef USE_MB_IDENT */
+
+/* Use MySQL RAID */
+/* #undef USE_RAID */
+
+/* Use strcoll() functions when comparing and sorting. */
+/* #undef USE_STRCOLL */
+
+/* READLINE: */
+#define VOID_SIGHANDLER 1
+
+/* The number of bytes in a char.  */
+#define SIZEOF_CHAR 1
+
+/* The number of bytes in a int.  */
+#define SIZEOF_INT 4
+
+/* The number of bytes in a long.  */
+#define SIZEOF_LONG 4
+
+/* The number of bytes in a long long.	*/
+#define SIZEOF_LONG_LONG 8
+
+/* Define if you have the alarm function.  */
+#define HAVE_ALARM 1
+
+/* Define if you have the atod function.  */
+/* #undef HAVE_ATOD */
+
+/* Define if you have the bcmp function.  */
+#define HAVE_BCMP 1
+
+/* Define if you have the bfill function.  */
+/* #undef HAVE_BFILL */
+
+/* Define if you have the bmove function.  */
+/* #undef HAVE_BMOVE */
+
+/* Define if you have the bzero function.  */
+#define HAVE_BZERO 1
+
+/* Define if you have the chsize function.  */
+#define HAVE_CHSIZE 1
+
+/* Define if you have the cuserid function.  */
+/* #define HAVE_CUSERID 1 */
+
+/* Define if you have the dlerror function.  */
+#define HAVE_DLERROR 1
+
+/* Define if you have the dlopen function.  */
+#define HAVE_DLOPEN 1
+
+/* Define if you have the fchmod function.  */
+/* #undef HAVE_FCHMOD */
+
+/* Define if you have the fcntl function.  */
+/* #define HAVE_FCNTL 1 */
+
+/* Define if you have the fconvert function.  */
+/* #undef HAVE_FCONVERT */
+
+/* Define if you have the finite function.  */
+/* #undef HAVE_FINITE */
+
+/* Define if you have the fpresetsticky function.  */
+/* #undef HAVE_FPRESETSTICKY */
+
+/* Define if you have the fpsetmask function.  */
+/* #undef HAVE_FPSETMASK */
+
+/* Define if you have the fseeko function.  */
+/* #undef HAVE_FSEEKO */
+
+/* Define if you have the ftruncate function.  */
+/* #define HAVE_FTRUNCATE 1 */
+
+/* Define if you have the getcwd function.  */
+#define HAVE_GETCWD 1
+
+/* Define if you have the gethostbyaddr_r function.  */
+/* #undef HAVE_GETHOSTBYADDR_R */
+
+/* Define if you have the gethostbyname_r function.  */
+/* #undef HAVE_GETHOSTBYNAME_R */
+
+/* Define if you have the getpagesize function.  */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if you have the getpass function.  */
+/*#define HAVE_GETPASS 1 */
+
+/* Define if you have the getpassphrase function.  */
+/* #undef HAVE_GETPASSPHRASE */
+
+/* Define if you have the getpwnam function.  */
+/* #define HAVE_GETPWNAM 1 */
+
+/* Define if you have the getpwuid function.  */
+/* #define HAVE_GETPWUID 1 */
+
+/* Define if you have the getrlimit function.  */
+/* #undef HAVE_GETRLIMIT */
+
+/* Define if you have the getrusage function.  */
+/* #undef HAVE_GETRUSAGE */
+
+/* Define if you have the getwd function.  */
+#define HAVE_GETWD 1
+
+/* Define to 1 if you have the `gmtime_r' function. */
+#define HAVE_GMTIME_R 1
+
+/* Define if you have the index function.  */
+#define HAVE_INDEX 1
+
+/* Define if you have the initgroups function.	*/
+/* #undef HAVE_INITGROUPS */
+
+/* Define if you have the localtime_r function.  */
+#define HAVE_LOCALTIME_R 1
+
+/* Define if you have the locking function.  */
+/* #undef HAVE_LOCKING */
+
+/* Define if you have the longjmp function.  */
+#define HAVE_LONGJMP 1
+
+/* Define if you have the lrand48 function.  */
+/* #undef HAVE_LRAND48 */
+
+/* Define if you have the lstat function.  */
+/* #undef HAVE_LSTAT */
+
+/* Define if you have the madvise function.  */
+/* #undef HAVE_MADVISE */
+
+/* Define if you have the memcpy function.  */
+#define HAVE_MEMCPY 1
+
+/* Define if you have the memmove function.  */
+#define HAVE_MEMMOVE 1
+
+/* Define if you have the mkstemp function.  */
+/* #define HAVE_MKSTEMP 1 */
+
+/* Define if you have the mlockall function.  */
+/* #undef HAVE_MLOCKALL */
+
+/* Define if you have the perror function.  */
+#define HAVE_PERROR 1
+
+/* Define if you have the poll function.  */
+/* #undef HAVE_POLL */
+
+/* Define if you have the pread function.  */
+/* #undef HAVE_PREAD */
+
+/* Define if you have the pthread_attr_create function.  */
+/* #undef HAVE_PTHREAD_ATTR_CREATE */
+
+/* Define if you have the pthread_attr_setprio function.  */
+#define HAVE_PTHREAD_ATTR_SETPRIO 1
+
+/* Define if you have the pthread_attr_setschedparam function.	*/
+/* #undef HAVE_PTHREAD_ATTR_SETSCHEDPARAM */
+
+/* Define if you have the pthread_attr_setstacksize function.  */
+#define HAVE_PTHREAD_ATTR_SETSTACKSIZE 1
+
+/* Define if you have the pthread_condattr_create function.  */
+/* #undef HAVE_PTHREAD_CONDATTR_CREATE */
+
+/* Define if you have the pthread_getsequence_np function.  */
+/* #undef HAVE_PTHREAD_GETSEQUENCE_NP */
+
+/* Define if you have the pthread_init function.  */
+/* #undef HAVE_PTHREAD_INIT */
+
+/* Define if you have the pthread_rwlock_rdlock function.  */
+/* #undef HAVE_PTHREAD_RWLOCK_RDLOCK */
+
+/* Define if you have the pthread_setprio function.  */
+#define HAVE_PTHREAD_SETPRIO 1
+
+/* Define if you have the pthread_setprio_np function.	*/
+/* #undef HAVE_PTHREAD_SETPRIO_NP */
+
+/* Define if you have the pthread_setschedparam function.  */
+/* #undef HAVE_PTHREAD_SETSCHEDPARAM */
+
+/* Define if you have the pthread_sigmask function.  */
+#define HAVE_PTHREAD_SIGMASK 1
+
+/* Define if you have the putenv function.  */
+#define HAVE_PUTENV 1
+
+/* Define if you have the readlink function.  */
+/* #undef HAVE_READLINK */
+
+/* Define if you have the realpath function.  */
+/* #undef HAVE_REALPATH */
+
+/* Define if you have the rename function.  */
+#define HAVE_RENAME 1
+
+/* Define if you have the rint function.  */
+#define HAVE_RINT 1
+
+/* Define if you have the rwlock_init function.  */
+/* #undef HAVE_RWLOCK_INIT */
+
+/* Define if you have the select function.  */
+#define HAVE_SELECT 1
+
+/* Define if you have the setenv function.  */
+/* #undef HAVE_SETENV */
+
+/* Define if you have the setlocale function.  */
+#define HAVE_SETLOCALE 1
+
+/* Define if you have the setupterm function.  */
+/* #undef HAVE_SETUPTERM */
+
+/* Define if you have the sighold function.  */
+/* #undef HAVE_SIGHOLD */
+
+/* Define if you have the sigset function.  */
+/* #undef HAVE_SIGSET */
+
+/* Define if you have the sigthreadmask function.  */
+/* #undef HAVE_SIGTHREADMASK */
+
+/* Define if you have the snprintf function.  */
+/* #define HAVE_SNPRINTF 1 */
+
+/* Define if you have the socket function.  */
+#define HAVE_SOCKET 1
+
+/* Define if you have the stpcpy function.  */
+/* #undef HAVE_STPCPY */
+
+/* Define if you have the strcasecmp function.	*/
+/* #undef HAVE_STRCASECMP */
+
+/* Define if you have the strcoll function.  */
+#define HAVE_STRCOLL 1
+
+/* Define if you have the strerror function.  */
+#define HAVE_STRERROR 1
+
+/* Define if you have the strnlen function.  */
+/* #undef HAVE_STRNLEN */
+
+/* Define if you have the strpbrk function.  */
+#define HAVE_STRPBRK 1
+
+/* Define if you have the strstr function.  */
+#define HAVE_STRSTR 1
+
+/* Define if you have the strtok_r function.  */
+/* #undef HAVE_STRTOK_R */
+
+/* Define if you have the strtol function.  */
+#define HAVE_STRTOL 1
+
+/* Define if you have the strtoul function.  */
+#define HAVE_STRTOUL 1
+
+/* Define if you have the strtoull function.  */
+/* #undef HAVE_STRTOULL */
+
+/* Define if you have the tcgetattr function.  */
+#define HAVE_TCGETATTR 1
+
+/* Define if you have the tell function.  */
+#define HAVE_TELL 1
+
+/* Define if you have the tempnam function.  */
+#define HAVE_TEMPNAM 1
+
+/* Define if you have the thr_setconcurrency function.	*/
+/* #undef HAVE_THR_SETCONCURRENCY */
+
+/* Define if you have the vidattr function.  */
+/* #undef HAVE_VIDATTR */
+
+/* Define if you have the  header file.  */
+/* #define HAVE_ALLOCA_H 1 */
+
+/* Define if you have the  header file.  */
+#define HAVE_ARPA_INET_H 1
+
+/* Define if you have the  header file.  */
+/* #undef HAVE_ASM_TERMBITS_H */
+
+/* Define if you have the  header file.  */
+#define HAVE_CRYPT_H 1
+
+/* Define if you have the  header file.  */
+/* #define HAVE_CURSES_H 1 */
+
+/* Define if you have the  header file.  */
+/* #define HAVE_DIRENT_H 1 */
+
+/* Define if you have the  header file.  */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the  header file.  */
+#define HAVE_FLOAT_H 1
+
+/* Define if you have the  header file.  */
+/* #undef HAVE_FLOATINGPOINT_H */
+
+/* Define if you have the  header file.	*/
+/* #define HAVE_GRP_H 1 */
+
+/* Define if you have the  header file.  */
+/* #undef HAVE_IEEEFP_H */
+
+/* Define if you have the  header file.  */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the  header file.  */
+#define HAVE_LOCALE_H 1
+
+/* Define if you have the  header file.  */
+#define HAVE_MEMORY_H 1
+
+/* Define if you have the  header file.  */
+/* #undef HAVE_NDIR_H */
+
+/* Define if you have the  header file.  */
+#define HAVE_NETINET_IN_H 1
+
+/* Define if you have the  header file.  */
+/* #undef HAVE_PATHS_H */
+
+/* Define if you have the  header file.	*/
+/* #define HAVE_PWD_H 1 */
+
+/* Define if you have the  header file.  */
+/* #undef HAVE_SCHED_H */
+
+/* Define if you have the  header file.  */
+/* #undef HAVE_SELECT_H */
+
+/* Define if you have the  header file.  */
+#define HAVE_STDARG_H 1
+
+/* Define if you have the  header file.  */
+#define HAVE_STDDEF_H 1
+
+/* Define if you have the  header file.  */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the  header file.  */
+#define HAVE_STRING_H 1
+
+/* Define if you have the  header file.  */
+/* #define HAVE_STRINGS_H 1 */
+
+/* Define if you have the  header file.  */
+/* #undef HAVE_SYNCH_H */
+
+/* Define if you have the  header file.  */
+/* #define HAVE_SYS_DIR_H 1 */
+
+/* Define if you have the  header file.  */
+/* #define HAVE_SYS_FILE_H 1 */
+
+/* Define if you have the  header file.  */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define if you have the  header file.  */
+/* #undef HAVE_SYS_MMAN_H */
+
+/* Define if you have the  header file.  */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define if you have the  header file.  */
+/* #undef HAVE_SYS_PTE_H */
+
+/* Define if you have the  header file.  */
+/* #undef HAVE_SYS_PTEM_H */
+
+/* Define if you have the  header file.  */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define if you have the  header file.  */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define if you have the  header file.  */
+/* #undef HAVE_SYS_STREAM_H */
+
+/* Define if you have the  header file.  */
+#define HAVE_SYS_TIMEB_H 1
+
+/* Define if you have the  header file.  */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define if you have the  header file.  */
+#define HAVE_SYS_UN_H 1
+
+/* Define if you have the  header file.  */
+#define HAVE_SYS_UTIME_H 1
+
+/* Define if you have the  header file.	*/
+/* #undef HAVE_SYS_VADVISE_H */
+
+/* Define if you have the  header file.  */
+/* #define HAVE_SYS_WAIT_H 1 */
+
+/* Define if you have the  header file.  */
+/* #undef HAVE_TERM_H */
+
+/* Define if you have the  header file.  */
+/* #undef HAVE_TERMBITS_H */
+
+/* Define if you have the  header file.  */
+/* #define HAVE_TERMCAP_H 1 */
+
+/* Define if you have the  header file.  */
+/* /#define HAVE_TERMIO_H 1 */
+
+/* Define if you have the  header file.  */
+/* #define HAVE_TERMIOS_H 1 */
+
+/* Define if you have the  header file.  */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the  header file.  */
+#define HAVE_UTIME_H 1
+
+/* Define if you have the  header file.  */
+#define HAVE_VARARGS_H 1
+
+/* Define if you have the bind library (-lbind).  */
+/* #undef HAVE_LIBBIND */
+
+/* Define if you have the c_r library (-lc_r).	*/
+/* #undef HAVE_LIBC_R */
+
+/* Define if you have the compat library (-lcompat).  */
+/* #undef HAVE_LIBCOMPAT */
+
+/* Define if you have the crypt library (-lcrypt).  */
+#define HAVE_LIBCRYPT 1
+
+/* Define if you have the dl library (-ldl).  */
+#define HAVE_LIBDL 1
+
+/* Define if you have the gen library (-lgen).	*/
+/* #undef HAVE_LIBGEN */
+
+/* Define if you have the m library (-lm).  */
+#define HAVE_LIBM 1
+
+/* Define if you have the nsl library (-lnsl).	*/
+/* #undef HAVE_LIBNSL */
+
+/* Define if you have the nsl_r library (-lnsl_r).  */
+/* #undef HAVE_LIBNSL_R */
+
+/* Define if you have the pthread library (-lpthread).	*/
+/* #undef HAVE_LIBPTHREAD */
+
+/* Define if you have the socket library (-lsocket).  */
+/* #undef HAVE_LIBSOCKET */
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define to make fseeko etc. visible, on some hosts. */
+/* #undef _LARGEFILE_SOURCE */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+#endif /* __CONFIG_OS2_H__ */
diff --git a/dep/include/mysql/config-win.h b/dep/include/mysql/config-win.h
new file mode 100644
index 00000000000..45bfeb5ba26
--- /dev/null
+++ b/dep/include/mysql/config-win.h
@@ -0,0 +1,460 @@
+/* Copyright (C) 2000 MySQL AB
+
+   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; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+/* Defines for Win32 to make it compatible for MySQL */
+
+#ifdef __WIN2000__
+/* We have to do this define before including windows.h to get the AWE API
+functions */
+#define _WIN32_WINNT     0x0500
+#else
+/* Get NT 4.0 functions */
+#define _WIN32_WINNT     0x0400
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+/* Avoid endless warnings about sprintf() etc. being unsafe. */
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+#include 
+#include 
+#include 			/* Because of rint() */
+#include 
+#include 
+#include 
+
+#define BIG_TABLES 1
+#define HAVE_SMEM 1
+
+#if defined(_WIN64) || defined(WIN64) 
+#define SYSTEM_TYPE	"Win64" 
+#elif defined(_WIN32) || defined(WIN32) 
+#define SYSTEM_TYPE	"Win32" 
+#else
+#define SYSTEM_TYPE	"Windows"
+#endif
+
+#if defined(_M_IA64) 
+#define MACHINE_TYPE	"ia64" 
+#elif defined(_M_IX86) 
+#define MACHINE_TYPE	"ia32" 
+#elif defined(_M_ALPHA) 
+#define MACHINE_TYPE	"axp" 
+#else
+#define MACHINE_TYPE	"unknown"	/* Define to machine type name */
+#endif 
+ 
+#if !(defined(_WIN64) || defined(WIN64)) 
+#ifndef _WIN32
+#define _WIN32				/* Compatible with old source */
+#endif
+#ifndef __WIN32__
+#define __WIN32__
+#endif
+#endif /* _WIN64 */
+#ifndef __WIN__
+#define __WIN__			      /* To make it easier in VC++ */
+#endif
+
+#ifndef MAX_INDEXES
+#define MAX_INDEXES 64
+#endif
+
+/* File and lock constants */
+#define O_SHARE		0x1000		/* Open file in sharing mode */
+#ifdef __BORLANDC__
+#define F_RDLCK		LK_NBLCK	/* read lock */
+#define F_WRLCK		LK_NBRLCK	/* write lock */
+#define F_UNLCK		LK_UNLCK	/* remove lock(s) */
+#else
+#define F_RDLCK		_LK_NBLCK	/* read lock */
+#define F_WRLCK		_LK_NBRLCK	/* write lock */
+#define F_UNLCK		_LK_UNLCK	/* remove lock(s) */
+#endif
+
+#define F_EXCLUSIVE	1		/* We have only exclusive locking */
+#define F_TO_EOF	(INT_MAX32/2)	/* size for lock of all file */
+#define F_OK		0		/* parameter to access() */
+#define W_OK		2
+
+#define S_IROTH		S_IREAD		/* for my_lib */
+
+#ifdef __BORLANDC__
+#define FILE_BINARY	O_BINARY	/* my_fopen in binary mode */
+#define O_TEMPORARY	0
+#define O_SHORT_LIVED	0
+#define SH_DENYNO	_SH_DENYNO
+#else
+#define O_BINARY	_O_BINARY	/* compability with MSDOS */
+#define FILE_BINARY	_O_BINARY	/* my_fopen in binary mode */
+#define O_TEMPORARY	_O_TEMPORARY
+#define O_SHORT_LIVED	_O_SHORT_LIVED
+#define SH_DENYNO	_SH_DENYNO
+#endif
+#define NO_OPEN_3			/* For my_create() */
+
+#define SIGQUIT		SIGTERM		/* No SIGQUIT */
+
+#undef _REENTRANT			/* Crashes something for win32 */
+#undef SAFE_MUTEX			/* Can't be used on windows */
+
+#if defined(_MSC_VER) && _MSC_VER >= 1310
+#define LL(A)           A##ll
+#define ULL(A)          A##ull
+#else
+#define LL(A)           ((__int64) A)
+#define ULL(A)          ((unsigned __int64) A)
+#endif
+
+#define LONGLONG_MIN	LL(0x8000000000000000)
+#define LONGLONG_MAX	LL(0x7FFFFFFFFFFFFFFF)
+#define ULONGLONG_MAX	ULL(0xFFFFFFFFFFFFFFFF)
+
+/* Type information */
+
+#if defined(__EMX__) || !defined(HAVE_UINT)
+#undef HAVE_UINT
+#define HAVE_UINT
+typedef unsigned short	ushort;
+typedef unsigned int	uint;
+#endif /* defined(__EMX__) || !defined(HAVE_UINT) */
+
+typedef unsigned __int64 ulonglong;	/* Microsofts 64 bit types */
+typedef __int64 longlong;
+#ifndef HAVE_SIGSET_T
+typedef int sigset_t;
+#endif
+#define longlong_defined
+/*
+  off_t should not be __int64 because of conflicts in header files;
+  Use my_off_t or os_off_t instead
+*/
+#ifndef HAVE_OFF_T
+typedef long off_t;
+#endif
+typedef __int64 os_off_t;
+#ifdef _WIN64
+typedef UINT_PTR rf_SetTimer;
+#else
+#ifndef HAVE_SIZE_T
+typedef unsigned int size_t;
+#endif
+typedef uint rf_SetTimer;
+#endif
+
+#define Socket_defined
+#define my_socket SOCKET
+#define bool BOOL
+#define SIGPIPE SIGINT
+#define RETQSORTTYPE void
+#define QSORT_TYPE_IS_VOID
+#define RETSIGTYPE void
+#define SOCKET_SIZE_TYPE int
+#define my_socket_defined
+#define bool_defined
+#define byte_defined
+#define HUGE_PTR
+#define STDCALL __stdcall	    /* Used by libmysql.dll */
+#define isnan(X) _isnan(X)
+#define finite(X) _finite(X)
+
+#ifndef UNDEF_THREAD_HACK
+#define THREAD
+#endif
+#define VOID_SIGHANDLER
+#define SIZEOF_CHAR		1
+#define SIZEOF_LONG		4
+#define SIZEOF_LONG_LONG	8
+#define SIZEOF_OFF_T		8
+#ifdef _WIN64
+#define SIZEOF_CHARP		8
+#else
+#define SIZEOF_CHARP		4
+#endif
+#define HAVE_BROKEN_NETINET_INCLUDES
+#ifdef __NT__
+#define HAVE_NAMED_PIPE			/* We can only create pipes on NT */
+#endif
+
+/* ERROR is defined in wingdi.h */
+#undef ERROR
+
+/* We need to close files to break connections on shutdown */
+#ifndef SIGNAL_WITH_VIO_CLOSE
+#define SIGNAL_WITH_VIO_CLOSE
+#endif
+
+/* Use all character sets in MySQL */
+#define USE_MB 1
+#define USE_MB_IDENT 1
+#define USE_STRCOLL 1
+
+/* All windows servers should support .sym files */
+#undef USE_SYMDIR
+#define USE_SYMDIR
+
+/* If LOAD DATA LOCAL INFILE should be enabled by default */
+#define ENABLED_LOCAL_INFILE 1
+
+/* Convert some simple functions to Posix */
+
+#define my_sigset(A,B) signal((A),(B))
+#define finite(A) _finite(A)
+#define sleep(A)  Sleep((A)*1000)
+#define popen(A,B) _popen((A),(B))
+#define pclose(A) _pclose(A)
+
+#ifndef __BORLANDC__
+#define access(A,B) _access(A,B)
+#endif
+
+#if !defined(__cplusplus)
+#define inline __inline
+#endif /* __cplusplus */
+
+inline double rint(double nr)
+{
+  double f = floor(nr);
+  double c = ceil(nr);
+  return (((c-nr) >= (nr-f)) ? f :c);
+}
+
+#ifdef _WIN64
+#define ulonglong2double(A) ((double) (ulonglong) (A))
+#define my_off_t2double(A)  ((double) (my_off_t) (A))
+
+#else
+inline double ulonglong2double(ulonglong value)
+{
+  longlong nr=(longlong) value;
+  if (nr >= 0)
+    return (double) nr;
+  return (18446744073709551616.0 + (double) nr);
+}
+#define my_off_t2double(A) ulonglong2double(A)
+#endif /* _WIN64 */
+
+#if SIZEOF_OFF_T > 4
+#define lseek(A,B,C) _lseeki64((A),(longlong) (B),(C))
+#define tell(A) _telli64(A)
+#endif
+
+
+#define STACK_DIRECTION -1
+
+/* Optimized store functions for Intel x86 */
+
+#ifndef _WIN64
+#define sint2korr(A)	(*((int16 *) (A)))
+#define sint3korr(A)	((int32) ((((uchar) (A)[2]) & 128) ? \
+				  (((uint32) 255L << 24) | \
+				   (((uint32) (uchar) (A)[2]) << 16) |\
+				   (((uint32) (uchar) (A)[1]) << 8) | \
+				   ((uint32) (uchar) (A)[0])) : \
+				  (((uint32) (uchar) (A)[2]) << 16) |\
+				  (((uint32) (uchar) (A)[1]) << 8) | \
+				  ((uint32) (uchar) (A)[0])))
+#define sint4korr(A)	(*((long *) (A)))
+#define uint2korr(A)	(*((uint16 *) (A)))
+/*
+   ATTENTION !
+   
+    Please, note, uint3korr reads 4 bytes (not 3) !
+    It means, that you have to provide enough allocated space !
+*/
+#define uint3korr(A)	(long) (*((unsigned int *) (A)) & 0xFFFFFF)
+#define uint4korr(A)	(*((unsigned long *) (A)))
+#define uint5korr(A)	((ulonglong)(((uint32) ((uchar) (A)[0])) +\
+				    (((uint32) ((uchar) (A)[1])) << 8) +\
+				    (((uint32) ((uchar) (A)[2])) << 16) +\
+				    (((uint32) ((uchar) (A)[3])) << 24)) +\
+				    (((ulonglong) ((uchar) (A)[4])) << 32))
+#define uint8korr(A)	(*((ulonglong *) (A)))
+#define sint8korr(A)	(*((longlong *) (A)))
+#define int2store(T,A)	*((uint16*) (T))= (uint16) (A)
+#define int3store(T,A)		{ *(T)=  (uchar) ((A));\
+				  *(T+1)=(uchar) (((uint) (A) >> 8));\
+				  *(T+2)=(uchar) (((A) >> 16)); }
+#define int4store(T,A)	*((long *) (T))= (long) (A)
+#define int5store(T,A)	{ *(T)= (uchar)((A));\
+			  *((T)+1)=(uchar) (((A) >> 8));\
+			  *((T)+2)=(uchar) (((A) >> 16));\
+			  *((T)+3)=(uchar) (((A) >> 24)); \
+			  *((T)+4)=(uchar) (((A) >> 32)); }
+#define int8store(T,A)	*((ulonglong *) (T))= (ulonglong) (A)
+
+#define doubleget(V,M)	do { *((long *) &V) = *((long*) M); \
+			    *(((long *) &V)+1) = *(((long*) M)+1); } while(0)
+#define doublestore(T,V) do { *((long *) T) = *((long*) &V); \
+			      *(((long *) T)+1) = *(((long*) &V)+1); } while(0)
+#define float4get(V,M) { *((long *) &(V)) = *((long*) (M)); }
+#define floatstore(T,V) memcpy((byte*)(T), (byte*)(&V), sizeof(float))
+#define floatget(V,M)   memcpy((byte*)(&V), (byte*)(M), sizeof(float))
+#define float8get(V,M) doubleget((V),(M))
+#define float4store(V,M) memcpy((byte*) V,(byte*) (&M),sizeof(float))
+#define float8store(V,M) doublestore((V),(M))
+#endif /* _WIN64 */
+
+#define HAVE_PERROR
+#define HAVE_VFPRINT
+#define HAVE_RENAME		/* Have rename() as function */
+#define HAVE_BINARY_STREAMS	/* Have "b" flag in streams */
+#define HAVE_LONG_JMP		/* Have long jump function */
+#define HAVE_LOCKING		/* have locking() call */
+#define HAVE_ERRNO_AS_DEFINE	/* errno is a define */
+#define HAVE_STDLIB		/* everything is include in this file */
+#define HAVE_MEMCPY
+#define HAVE_MEMMOVE
+#define HAVE_GETCWD
+#define HAVE_TELL
+#define HAVE_TZNAME
+#define HAVE_PUTENV
+#define HAVE_SELECT
+#define HAVE_SETLOCALE
+#define HAVE_SOCKET		/* Giangi */
+#define HAVE_FLOAT_H
+#define HAVE_LIMITS_H
+#define HAVE_STDDEF_H
+#define HAVE_RINT		/* defined in this file */
+#define NO_FCNTL_NONBLOCK	/* No FCNTL */
+#define HAVE_ALLOCA
+#define HAVE_STRPBRK
+#define HAVE_STRSTR
+#define HAVE_COMPRESS
+#define HAVE_CREATESEMAPHORE
+#define HAVE_ISNAN
+#define HAVE_FINITE
+#define HAVE_QUERY_CACHE
+#define SPRINTF_RETURNS_INT
+#define HAVE_SETFILEPOINTER
+#define HAVE_VIO_READ_BUFF
+#define HAVE_STRNLEN
+
+#ifndef __NT__
+#undef FILE_SHARE_DELETE
+#define FILE_SHARE_DELETE 0     /* Not implemented on Win 98/ME */
+#endif
+
+#ifdef NOT_USED
+#define HAVE_SNPRINTF		/* Gave link error */
+#define _snprintf snprintf
+#endif
+
+#ifdef _MSC_VER
+#define HAVE_LDIV		/* The optimizer breaks in zortech for ldiv */
+#define HAVE_ANSI_INCLUDE
+#define HAVE_SYS_UTIME_H
+#define HAVE_STRTOUL
+#endif
+#define my_reinterpret_cast(A) reinterpret_cast 
+#define my_const_cast(A) const_cast
+
+
+/* MYSQL OPTIONS */
+
+#ifdef _CUSTOMCONFIG_
+#include 
+#else
+#define DEFAULT_MYSQL_HOME	"c:\\mysql"
+#define DATADIR         	"c:\\mysql\\data"
+#define PACKAGE			"mysql"
+#define DEFAULT_BASEDIR		"C:\\"
+#define SHAREDIR		"share"
+#define DEFAULT_CHARSET_HOME	"C:/mysql/"
+#endif
+#ifndef DEFAULT_HOME_ENV
+#define DEFAULT_HOME_ENV MYSQL_HOME
+#endif
+#ifndef DEFAULT_GROUP_SUFFIX_ENV
+#define DEFAULT_GROUP_SUFFIX_ENV MYSQL_GROUP_SUFFIX
+#endif
+
+/* File name handling */
+
+#define FN_LIBCHAR	'\\'
+#define FN_ROOTDIR	"\\"
+#define FN_DEVCHAR	':'
+#define FN_NETWORK_DRIVES	/* Uses \\ to indicate network drives */
+#define FN_NO_CASE_SENCE	/* Files are not case-sensitive */
+#define OS_FILE_LIMIT	2048
+
+#define DO_NOT_REMOVE_THREAD_WRAPPERS
+#define thread_safe_increment(V,L) InterlockedIncrement((long*) &(V))
+#define thread_safe_decrement(V,L) InterlockedDecrement((long*) &(V))
+/* The following is only used for statistics, so it should be good enough */
+#ifdef __NT__  /* This should also work on Win98 but .. */
+#define thread_safe_add(V,C,L) InterlockedExchangeAdd((long*) &(V),(C))
+#define thread_safe_sub(V,C,L) InterlockedExchangeAdd((long*) &(V),-(long) (C))
+#define statistic_add(V,C,L) thread_safe_add((V),(C),(L))
+#else
+#define thread_safe_add(V,C,L) \
+	pthread_mutex_lock((L)); (V)+=(C); pthread_mutex_unlock((L));
+#define thread_safe_sub(V,C,L) \
+	pthread_mutex_lock((L)); (V)-=(C); pthread_mutex_unlock((L));
+#define statistic_add(V,C,L)	 (V)+=(C)
+#endif
+#define statistic_increment(V,L) thread_safe_increment((V),(L))
+#define statistic_decrement(V,L) thread_safe_decrement((V),(L))
+
+#define shared_memory_buffer_length 16000
+#define default_shared_memory_base_name "MYSQL"
+
+#define MYSQL_DEFAULT_CHARSET_NAME "latin1"
+#define MYSQL_DEFAULT_COLLATION_NAME "latin1_swedish_ci"
+
+#define HAVE_SPATIAL 1
+#define HAVE_RTREE_KEYS 1
+
+#define HAVE_OPENSSL 1
+#define HAVE_YASSL 1
+
+/* Define charsets you want */
+/* #undef HAVE_CHARSET_armscii8 */
+/* #undef HAVE_CHARSET_ascii */
+#define HAVE_CHARSET_big5 1
+#define HAVE_CHARSET_cp1250 1
+/* #undef HAVE_CHARSET_cp1251 */
+/* #undef HAVE_CHARSET_cp1256 */
+/* #undef HAVE_CHARSET_cp1257 */
+/* #undef HAVE_CHARSET_cp850 */
+/* #undef HAVE_CHARSET_cp852 */
+/* #undef HAVE_CHARSET_cp866 */
+#define HAVE_CHARSET_cp932 1
+/* #undef HAVE_CHARSET_dec8 */
+#define HAVE_CHARSET_eucjpms 1
+#define HAVE_CHARSET_euckr 1
+#define HAVE_CHARSET_gb2312 1
+#define HAVE_CHARSET_gbk 1
+/* #undef HAVE_CHARSET_greek */
+/* #undef HAVE_CHARSET_hebrew */
+/* #undef HAVE_CHARSET_hp8 */
+/* #undef HAVE_CHARSET_keybcs2 */
+/* #undef HAVE_CHARSET_koi8r */
+/* #undef HAVE_CHARSET_koi8u */
+#define HAVE_CHARSET_latin1 1
+#define HAVE_CHARSET_latin2 1
+/* #undef HAVE_CHARSET_latin5 */
+/* #undef HAVE_CHARSET_latin7 */
+/* #undef HAVE_CHARSET_macce */
+/* #undef HAVE_CHARSET_macroman */
+#define HAVE_CHARSET_sjis 1
+/* #undef HAVE_CHARSET_swe7 */
+#define HAVE_CHARSET_tis620 1
+#define HAVE_CHARSET_ucs2 1
+#define HAVE_CHARSET_ujis 1
+#define HAVE_CHARSET_utf8 1
+#define HAVE_UCA_COLLATIONS 1
+
diff --git a/dep/include/mysql/errmsg.h b/dep/include/mysql/errmsg.h
new file mode 100644
index 00000000000..8b20b36eed7
--- /dev/null
+++ b/dep/include/mysql/errmsg.h
@@ -0,0 +1,102 @@
+/* Copyright (C) 2000 MySQL AB
+
+   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; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+/* Error messages for MySQL clients */
+/* (Error messages for the daemon are in share/language/errmsg.sys) */
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+void	init_client_errs(void);
+void	finish_client_errs(void);
+extern const char *client_errors[];	/* Error messages */
+#ifdef	__cplusplus
+}
+#endif
+
+#define CR_MIN_ERROR		2000	/* For easier client code */
+#define CR_MAX_ERROR		2999
+#if defined(OS2) && defined(MYSQL_SERVER)
+#define CER(X) client_errors[(X)-CR_MIN_ERROR]
+#elif !defined(ER)
+#define ER(X) client_errors[(X)-CR_MIN_ERROR]
+#endif
+#define CLIENT_ERRMAP		2	/* Errormap used by my_error() */
+
+/* Do not add error numbers before CR_ERROR_FIRST. */
+/* If necessary to add lower numbers, change CR_ERROR_FIRST accordingly. */
+#define CR_ERROR_FIRST  	2000 /*Copy first error nr.*/
+#define CR_UNKNOWN_ERROR	2000
+#define CR_SOCKET_CREATE_ERROR	2001
+#define CR_CONNECTION_ERROR	2002
+#define CR_CONN_HOST_ERROR	2003
+#define CR_IPSOCK_ERROR		2004
+#define CR_UNKNOWN_HOST		2005
+#define CR_SERVER_GONE_ERROR	2006
+#define CR_VERSION_ERROR	2007
+#define CR_OUT_OF_MEMORY	2008
+#define CR_WRONG_HOST_INFO	2009
+#define CR_LOCALHOST_CONNECTION 2010
+#define CR_TCP_CONNECTION	2011
+#define CR_SERVER_HANDSHAKE_ERR 2012
+#define CR_SERVER_LOST		2013
+#define CR_COMMANDS_OUT_OF_SYNC 2014
+#define CR_NAMEDPIPE_CONNECTION 2015
+#define CR_NAMEDPIPEWAIT_ERROR  2016
+#define CR_NAMEDPIPEOPEN_ERROR  2017
+#define CR_NAMEDPIPESETSTATE_ERROR 2018
+#define CR_CANT_READ_CHARSET	2019
+#define CR_NET_PACKET_TOO_LARGE 2020
+#define CR_EMBEDDED_CONNECTION	2021
+#define CR_PROBE_SLAVE_STATUS   2022
+#define CR_PROBE_SLAVE_HOSTS    2023
+#define CR_PROBE_SLAVE_CONNECT  2024
+#define CR_PROBE_MASTER_CONNECT 2025
+#define CR_SSL_CONNECTION_ERROR 2026
+#define CR_MALFORMED_PACKET     2027
+#define CR_WRONG_LICENSE	2028
+
+/* new 4.1 error codes */
+#define CR_NULL_POINTER		2029
+#define CR_NO_PREPARE_STMT	2030
+#define CR_PARAMS_NOT_BOUND	2031
+#define CR_DATA_TRUNCATED	2032
+#define CR_NO_PARAMETERS_EXISTS 2033
+#define CR_INVALID_PARAMETER_NO 2034
+#define CR_INVALID_BUFFER_USE	2035
+#define CR_UNSUPPORTED_PARAM_TYPE 2036
+
+#define CR_SHARED_MEMORY_CONNECTION             2037
+#define CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR  2038
+#define CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR   2039
+#define CR_SHARED_MEMORY_CONNECT_FILE_MAP_ERROR 2040
+#define CR_SHARED_MEMORY_CONNECT_MAP_ERROR      2041
+#define CR_SHARED_MEMORY_FILE_MAP_ERROR         2042
+#define CR_SHARED_MEMORY_MAP_ERROR              2043
+#define CR_SHARED_MEMORY_EVENT_ERROR     	2044
+#define CR_SHARED_MEMORY_CONNECT_ABANDONED_ERROR 2045
+#define CR_SHARED_MEMORY_CONNECT_SET_ERROR      2046
+#define CR_CONN_UNKNOW_PROTOCOL 		2047
+#define CR_INVALID_CONN_HANDLE			2048
+#define CR_SECURE_AUTH                          2049
+#define CR_FETCH_CANCELED                       2050
+#define CR_NO_DATA                              2051
+#define CR_NO_STMT_METADATA                     2052
+#define CR_NO_RESULT_SET                        2053
+#define CR_NOT_IMPLEMENTED                      2054
+#define CR_SERVER_LOST_EXTENDED			2055
+#define CR_ERROR_LAST  /*Copy last error nr:*/  2055
+/* Add error numbers before CR_ERROR_LAST and change it accordingly. */
+
diff --git a/dep/include/mysql/m_ctype.h b/dep/include/mysql/m_ctype.h
new file mode 100644
index 00000000000..218ec2daadb
--- /dev/null
+++ b/dep/include/mysql/m_ctype.h
@@ -0,0 +1,521 @@
+/* Copyright (C) 2000 MySQL AB
+
+   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; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+/*
+  A better inplementation of the UNIX ctype(3) library.
+  Notes:   my_global.h should be included before ctype.h
+*/
+
+#ifndef _m_ctype_h
+#define _m_ctype_h
+
+#include 
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#define MY_CS_NAME_SIZE			32
+#define MY_CS_CTYPE_TABLE_SIZE		257
+#define MY_CS_TO_LOWER_TABLE_SIZE	256
+#define MY_CS_TO_UPPER_TABLE_SIZE	256
+#define MY_CS_SORT_ORDER_TABLE_SIZE	256
+#define MY_CS_TO_UNI_TABLE_SIZE		256
+
+#define CHARSET_DIR	"charsets/"
+
+#define my_wc_t ulong
+
+typedef struct unicase_info_st
+{
+  uint16 toupper;
+  uint16 tolower;
+  uint16 sort;
+} MY_UNICASE_INFO;
+
+
+extern MY_UNICASE_INFO *my_unicase_default[256];
+extern MY_UNICASE_INFO *my_unicase_turkish[256];
+
+
+/* wm_wc and wc_mb return codes */
+#define MY_CS_ILSEQ	0     /* Wrong by sequence: wb_wc                   */
+#define MY_CS_ILUNI	0     /* Cannot encode Unicode to charset: wc_mb    */
+#define MY_CS_TOOSMALL  -101  /* Need at least one byte:    wc_mb and mb_wc */
+#define MY_CS_TOOSMALL2 -102  /* Need at least two bytes:   wc_mb and mb_wc */
+#define MY_CS_TOOSMALL3 -103  /* Need at least three bytes: wc_mb and mb_wc */
+/* These following three are currently not really used */
+#define MY_CS_TOOSMALL4 -104  /* Need at least 4 bytes: wc_mb and mb_wc */
+#define MY_CS_TOOSMALL5 -105  /* Need at least 5 bytes: wc_mb and mb_wc */
+#define MY_CS_TOOSMALL6 -106  /* Need at least 6 bytes: wc_mb and mb_wc */
+/* A helper macros for "need at least n bytes" */
+#define MY_CS_TOOSMALLN(n)    (-100-(n))
+
+#define MY_SEQ_INTTAIL	1
+#define MY_SEQ_SPACES	2
+
+        /* My charsets_list flags */
+#define MY_CS_COMPILED  1      /* compiled-in sets               */
+#define MY_CS_CONFIG    2      /* sets that have a *.conf file   */
+#define MY_CS_INDEX     4      /* sets listed in the Index file  */
+#define MY_CS_LOADED    8      /* sets that are currently loaded */
+#define MY_CS_BINSORT	16     /* if binary sort order           */
+#define MY_CS_PRIMARY	32     /* if primary collation           */
+#define MY_CS_STRNXFRM	64     /* if strnxfrm is used for sort   */
+#define MY_CS_UNICODE	128    /* is a charset is full unicode   */
+#define MY_CS_READY	256    /* if a charset is initialized    */
+#define MY_CS_AVAILABLE	512    /* If either compiled-in or loaded*/
+#define MY_CS_CSSORT	1024   /* if case sensitive sort order   */	
+#define MY_CS_PUREASCII 2048   /* if a charset is pure ascii     */
+#define MY_CHARSET_UNDEFINED 0
+
+/* Character repertoire flags */
+#define MY_REPERTOIRE_ASCII      1 /* Pure ASCII            U+0000..U+007F */
+#define MY_REPERTOIRE_EXTENDED   2 /* Extended characters:  U+0080..U+FFFF */
+#define MY_REPERTOIRE_UNICODE30  3 /* ASCII | EXTENDED:     U+0000..U+FFFF */
+
+
+typedef struct my_uni_idx_st
+{
+  uint16 from;
+  uint16 to;
+  uchar  *tab;
+} MY_UNI_IDX;
+
+typedef struct
+{
+  uint beg;
+  uint end;
+  uint mb_len;
+} my_match_t;
+
+enum my_lex_states
+{
+  MY_LEX_START, MY_LEX_CHAR, MY_LEX_IDENT, 
+  MY_LEX_IDENT_SEP, MY_LEX_IDENT_START,
+  MY_LEX_REAL, MY_LEX_HEX_NUMBER, MY_LEX_BIN_NUMBER,
+  MY_LEX_CMP_OP, MY_LEX_LONG_CMP_OP, MY_LEX_STRING, MY_LEX_COMMENT, MY_LEX_END,
+  MY_LEX_OPERATOR_OR_IDENT, MY_LEX_NUMBER_IDENT, MY_LEX_INT_OR_REAL,
+  MY_LEX_REAL_OR_POINT, MY_LEX_BOOL, MY_LEX_EOL, MY_LEX_ESCAPE, 
+  MY_LEX_LONG_COMMENT, MY_LEX_END_LONG_COMMENT, MY_LEX_SEMICOLON, 
+  MY_LEX_SET_VAR, MY_LEX_USER_END, MY_LEX_HOSTNAME, MY_LEX_SKIP, 
+  MY_LEX_USER_VARIABLE_DELIMITER, MY_LEX_SYSTEM_VAR,
+  MY_LEX_IDENT_OR_KEYWORD,
+  MY_LEX_IDENT_OR_HEX, MY_LEX_IDENT_OR_BIN, MY_LEX_IDENT_OR_NCHAR,
+  MY_LEX_STRING_OR_DELIMITER
+};
+
+struct charset_info_st;
+
+
+/* See strings/CHARSET_INFO.txt for information about this structure  */
+typedef struct my_collation_handler_st
+{
+  my_bool (*init)(struct charset_info_st *, void *(*alloc)(uint));
+  /* Collation routines */
+  int     (*strnncoll)(struct charset_info_st *,
+		       const uchar *, uint, const uchar *, uint, my_bool);
+  int     (*strnncollsp)(struct charset_info_st *,
+                         const uchar *, uint, const uchar *, uint,
+                         my_bool diff_if_only_endspace_difference);
+  int     (*strnxfrm)(struct charset_info_st *,
+		      uchar *, uint, const uchar *, uint);
+  uint    (*strnxfrmlen)(struct charset_info_st *, uint); 
+  my_bool (*like_range)(struct charset_info_st *,
+			const char *s, uint s_length,
+			pchar w_prefix, pchar w_one, pchar w_many, 
+			uint res_length,
+			char *min_str, char *max_str,
+			uint *min_len, uint *max_len);
+  int     (*wildcmp)(struct charset_info_st *,
+  		     const char *str,const char *str_end,
+                     const char *wildstr,const char *wildend,
+                     int escape,int w_one, int w_many);
+
+  int  (*strcasecmp)(struct charset_info_st *, const char *, const char *);
+  
+  uint (*instr)(struct charset_info_st *,
+                const char *b, uint b_length,
+                const char *s, uint s_length,
+                my_match_t *match, uint nmatch);
+  
+  /* Hash calculation */
+  void (*hash_sort)(struct charset_info_st *cs, const uchar *key, uint len,
+		    ulong *nr1, ulong *nr2); 
+  my_bool (*propagate)(struct charset_info_st *cs, const uchar *str, uint len);
+} MY_COLLATION_HANDLER;
+
+extern MY_COLLATION_HANDLER my_collation_mb_bin_handler;
+extern MY_COLLATION_HANDLER my_collation_8bit_bin_handler;
+extern MY_COLLATION_HANDLER my_collation_8bit_simple_ci_handler;
+extern MY_COLLATION_HANDLER my_collation_ucs2_uca_handler;
+
+
+/* See strings/CHARSET_INFO.txt about information on this structure  */
+typedef struct my_charset_handler_st
+{
+  my_bool (*init)(struct charset_info_st *, void *(*alloc)(uint));
+  /* Multibyte routines */
+  int     (*ismbchar)(struct charset_info_st *, const char *, const char *);
+  int     (*mbcharlen)(struct charset_info_st *, uint);
+  uint    (*numchars)(struct charset_info_st *, const char *b, const char *e);
+  uint    (*charpos)(struct charset_info_st *, const char *b, const char *e, uint pos);
+  uint    (*well_formed_len)(struct charset_info_st *,
+                             const char *b,const char *e,
+                             uint nchars, int *error);
+  uint    (*lengthsp)(struct charset_info_st *, const char *ptr, uint length);
+  uint    (*numcells)(struct charset_info_st *, const char *b, const char *e);
+  
+  /* Unicode convertion */
+  int (*mb_wc)(struct charset_info_st *cs,my_wc_t *wc,
+	       const unsigned char *s,const unsigned char *e);
+  int (*wc_mb)(struct charset_info_st *cs,my_wc_t wc,
+	       unsigned char *s,unsigned char *e);
+  
+  /* Functions for case and sort convertion */
+  uint    (*caseup_str)(struct charset_info_st *, char *);
+  uint    (*casedn_str)(struct charset_info_st *, char *);
+  uint    (*caseup)(struct charset_info_st *, char *src, uint srclen,
+                                              char *dst, uint dstlen);
+  uint    (*casedn)(struct charset_info_st *, char *src, uint srclen,
+                                              char *dst, uint dstlen);
+  
+  /* Charset dependant snprintf() */
+  int  (*snprintf)(struct charset_info_st *, char *to, uint n, const char *fmt,
+		   ...) ATTRIBUTE_FORMAT_FPTR(printf, 4, 5);
+  int  (*long10_to_str)(struct charset_info_st *, char *to, uint n, int radix,
+			long int val);
+  int (*longlong10_to_str)(struct charset_info_st *, char *to, uint n,
+			   int radix, longlong val);
+  
+  void (*fill)(struct charset_info_st *, char *to, uint len, int fill);
+  
+  /* String-to-number convertion routines */
+  long        (*strntol)(struct charset_info_st *, const char *s, uint l,
+			 int base, char **e, int *err);
+  ulong      (*strntoul)(struct charset_info_st *, const char *s, uint l,
+			 int base, char **e, int *err);
+  longlong   (*strntoll)(struct charset_info_st *, const char *s, uint l,
+			 int base, char **e, int *err);
+  ulonglong (*strntoull)(struct charset_info_st *, const char *s, uint l,
+			 int base, char **e, int *err);
+  double      (*strntod)(struct charset_info_st *, char *s, uint l, char **e,
+			 int *err);
+  longlong    (*strtoll10)(struct charset_info_st *cs,
+                           const char *nptr, char **endptr, int *error);
+  ulonglong   (*strntoull10rnd)(struct charset_info_st *cs,
+                                const char *str, uint length, int unsigned_fl,
+                                char **endptr, int *error);
+  ulong        (*scan)(struct charset_info_st *, const char *b, const char *e,
+		       int sq);
+} MY_CHARSET_HANDLER;
+
+extern MY_CHARSET_HANDLER my_charset_8bit_handler;
+extern MY_CHARSET_HANDLER my_charset_ucs2_handler;
+
+
+/* See strings/CHARSET_INFO.txt about information on this structure  */
+typedef struct charset_info_st
+{
+  uint      number;
+  uint      primary_number;
+  uint      binary_number;
+  uint      state;
+  const char *csname;
+  const char *name;
+  const char *comment;
+  const char *tailoring;
+  uchar    *ctype;
+  uchar    *to_lower;
+  uchar    *to_upper;
+  uchar    *sort_order;
+  uint16   *contractions;
+  uint16   **sort_order_big;
+  uint16      *tab_to_uni;
+  MY_UNI_IDX  *tab_from_uni;
+  MY_UNICASE_INFO **caseinfo;
+  uchar     *state_map;
+  uchar     *ident_map;
+  uint      strxfrm_multiply;
+  uchar     caseup_multiply;
+  uchar     casedn_multiply;
+  uint      mbminlen;
+  uint      mbmaxlen;
+  uint16    min_sort_char;
+  uint16    max_sort_char; /* For LIKE optimization */
+  uchar     pad_char;
+  my_bool   escape_with_backslash_is_dangerous;
+  
+  MY_CHARSET_HANDLER *cset;
+  MY_COLLATION_HANDLER *coll;
+  
+} CHARSET_INFO;
+
+
+extern CHARSET_INFO my_charset_bin;
+extern CHARSET_INFO my_charset_big5_chinese_ci;
+extern CHARSET_INFO my_charset_big5_bin;
+extern CHARSET_INFO my_charset_cp932_japanese_ci;
+extern CHARSET_INFO my_charset_cp932_bin;
+extern CHARSET_INFO my_charset_eucjpms_japanese_ci;
+extern CHARSET_INFO my_charset_eucjpms_bin;
+extern CHARSET_INFO my_charset_euckr_korean_ci;
+extern CHARSET_INFO my_charset_euckr_bin;
+extern CHARSET_INFO my_charset_gb2312_chinese_ci;
+extern CHARSET_INFO my_charset_gb2312_bin;
+extern CHARSET_INFO my_charset_gbk_chinese_ci;
+extern CHARSET_INFO my_charset_gbk_bin;
+extern CHARSET_INFO my_charset_latin1;
+extern CHARSET_INFO my_charset_latin1_german2_ci;
+extern CHARSET_INFO my_charset_latin1_bin;
+extern CHARSET_INFO my_charset_latin2_czech_ci;
+extern CHARSET_INFO my_charset_sjis_japanese_ci;
+extern CHARSET_INFO my_charset_sjis_bin;
+extern CHARSET_INFO my_charset_tis620_thai_ci;
+extern CHARSET_INFO my_charset_tis620_bin;
+extern CHARSET_INFO my_charset_ucs2_general_ci;
+extern CHARSET_INFO my_charset_ucs2_bin;
+extern CHARSET_INFO my_charset_ucs2_unicode_ci;
+extern CHARSET_INFO my_charset_ujis_japanese_ci;
+extern CHARSET_INFO my_charset_ujis_bin;
+extern CHARSET_INFO my_charset_utf8_general_ci;
+extern CHARSET_INFO my_charset_utf8_unicode_ci;
+extern CHARSET_INFO my_charset_utf8_bin;
+extern CHARSET_INFO my_charset_cp1250_czech_ci;
+
+/* declarations for simple charsets */
+extern int  my_strnxfrm_simple(CHARSET_INFO *, uchar *, uint, const uchar *,
+                               uint); 
+uint  my_strnxfrmlen_simple(CHARSET_INFO *, uint); 
+extern int  my_strnncoll_simple(CHARSET_INFO *, const uchar *, uint,
+				const uchar *, uint, my_bool);
+
+extern int  my_strnncollsp_simple(CHARSET_INFO *, const uchar *, uint,
+                                  const uchar *, uint,
+                                  my_bool diff_if_only_endspace_difference);
+
+extern void my_hash_sort_simple(CHARSET_INFO *cs,
+				const uchar *key, uint len,
+				ulong *nr1, ulong *nr2); 
+
+extern uint my_lengthsp_8bit(CHARSET_INFO *cs, const char *ptr, uint length);
+
+extern uint my_instr_simple(struct charset_info_st *,
+                            const char *b, uint b_length,
+                            const char *s, uint s_length,
+                            my_match_t *match, uint nmatch);
+
+
+/* Functions for 8bit */
+extern uint my_caseup_str_8bit(CHARSET_INFO *, char *);
+extern uint my_casedn_str_8bit(CHARSET_INFO *, char *);
+extern uint my_caseup_8bit(CHARSET_INFO *, char *src, uint srclen,
+                                           char *dst, uint dstlen);
+extern uint my_casedn_8bit(CHARSET_INFO *, char *src, uint srclen,
+                                           char *dst, uint dstlen);
+
+extern int my_strcasecmp_8bit(CHARSET_INFO * cs, const char *, const char *);
+
+int my_mb_wc_8bit(CHARSET_INFO *cs,my_wc_t *wc, const uchar *s,const uchar *e);
+int my_wc_mb_8bit(CHARSET_INFO *cs,my_wc_t wc, uchar *s, uchar *e);
+
+ulong my_scan_8bit(CHARSET_INFO *cs, const char *b, const char *e, int sq);
+
+int my_snprintf_8bit(struct charset_info_st *, char *to, uint n,
+		     const char *fmt, ...)
+  ATTRIBUTE_FORMAT(printf, 4, 5);
+
+long        my_strntol_8bit(CHARSET_INFO *, const char *s, uint l, int base,
+			    char **e, int *err);
+ulong      my_strntoul_8bit(CHARSET_INFO *, const char *s, uint l, int base,
+			    char **e, int *err);
+longlong   my_strntoll_8bit(CHARSET_INFO *, const char *s, uint l, int base,
+			    char **e, int *err);
+ulonglong my_strntoull_8bit(CHARSET_INFO *, const char *s, uint l, int base,
+			    char **e, int *err);
+double      my_strntod_8bit(CHARSET_INFO *, char *s, uint l,char **e,
+			    int *err);
+int  my_long10_to_str_8bit(CHARSET_INFO *, char *to, uint l, int radix,
+			   long int val);
+int my_longlong10_to_str_8bit(CHARSET_INFO *, char *to, uint l, int radix,
+			      longlong val);
+
+longlong my_strtoll10_8bit(CHARSET_INFO *cs,
+                           const char *nptr, char **endptr, int *error);
+longlong my_strtoll10_ucs2(CHARSET_INFO *cs, 
+                           const char *nptr, char **endptr, int *error);
+
+ulonglong my_strntoull10rnd_8bit(CHARSET_INFO *cs,
+                                 const char *str, uint length, int unsigned_fl,
+                                 char **endptr, int *error);
+ulonglong my_strntoull10rnd_ucs2(CHARSET_INFO *cs, 
+                                 const char *str, uint length, int unsigned_fl,
+                                 char **endptr, int *error);
+
+void my_fill_8bit(CHARSET_INFO *cs, char* to, uint l, int fill);
+
+my_bool  my_like_range_simple(CHARSET_INFO *cs,
+			      const char *ptr, uint ptr_length,
+			      pbool escape, pbool w_one, pbool w_many,
+			      uint res_length,
+			      char *min_str, char *max_str,
+			      uint *min_length, uint *max_length);
+
+my_bool  my_like_range_mb(CHARSET_INFO *cs,
+			  const char *ptr, uint ptr_length,
+			  pbool escape, pbool w_one, pbool w_many,
+			  uint res_length,
+			  char *min_str, char *max_str,
+			  uint *min_length, uint *max_length);
+
+my_bool  my_like_range_ucs2(CHARSET_INFO *cs,
+			    const char *ptr, uint ptr_length,
+			    pbool escape, pbool w_one, pbool w_many,
+			    uint res_length,
+			    char *min_str, char *max_str,
+			    uint *min_length, uint *max_length);
+
+
+int my_wildcmp_8bit(CHARSET_INFO *,
+		    const char *str,const char *str_end,
+		    const char *wildstr,const char *wildend,
+		    int escape, int w_one, int w_many);
+
+int my_wildcmp_bin(CHARSET_INFO *,
+		   const char *str,const char *str_end,
+		   const char *wildstr,const char *wildend,
+		   int escape, int w_one, int w_many);
+
+uint my_numchars_8bit(CHARSET_INFO *, const char *b, const char *e);
+uint my_numcells_8bit(CHARSET_INFO *, const char *b, const char *e);
+uint my_charpos_8bit(CHARSET_INFO *, const char *b, const char *e, uint pos);
+uint my_well_formed_len_8bit(CHARSET_INFO *, const char *b, const char *e,
+                             uint pos, int *error);
+int my_mbcharlen_8bit(CHARSET_INFO *, uint c);
+
+
+/* Functions for multibyte charsets */
+extern uint my_caseup_str_mb(CHARSET_INFO *, char *);
+extern uint my_casedn_str_mb(CHARSET_INFO *, char *);
+extern uint my_caseup_mb(CHARSET_INFO *, char *src, uint srclen,
+                                         char *dst, uint dstlen);
+extern uint my_casedn_mb(CHARSET_INFO *, char *src, uint srclen,
+                                         char *dst, uint dstlen);
+extern int my_strcasecmp_mb(CHARSET_INFO * cs,const char *, const char *);
+
+int my_wildcmp_mb(CHARSET_INFO *,
+		  const char *str,const char *str_end,
+		  const char *wildstr,const char *wildend,
+		  int escape, int w_one, int w_many);
+uint my_numchars_mb(CHARSET_INFO *, const char *b, const char *e);
+uint my_numcells_mb(CHARSET_INFO *, const char *b, const char *e);
+uint my_charpos_mb(CHARSET_INFO *, const char *b, const char *e, uint pos);
+uint my_well_formed_len_mb(CHARSET_INFO *, const char *b, const char *e,
+                           uint pos, int *error);
+uint my_instr_mb(struct charset_info_st *,
+                 const char *b, uint b_length,
+                 const char *s, uint s_length,
+                 my_match_t *match, uint nmatch);
+
+int my_wildcmp_unicode(CHARSET_INFO *cs,
+                       const char *str, const char *str_end,
+                       const char *wildstr, const char *wildend,
+                       int escape, int w_one, int w_many,
+                       MY_UNICASE_INFO **weights);
+
+extern my_bool my_parse_charset_xml(const char *bug, uint len,
+				    int (*add)(CHARSET_INFO *cs));
+
+my_bool my_propagate_simple(CHARSET_INFO *cs, const uchar *str, uint len);
+my_bool my_propagate_complex(CHARSET_INFO *cs, const uchar *str, uint len);
+
+
+uint my_string_repertoire(CHARSET_INFO *cs, const char *str, ulong len);
+my_bool my_charset_is_ascii_based(CHARSET_INFO *cs);
+my_bool my_charset_is_8bit_pure_ascii(CHARSET_INFO *cs);
+
+
+#define	_MY_U	01	/* Upper case */
+#define	_MY_L	02	/* Lower case */
+#define	_MY_NMR	04	/* Numeral (digit) */
+#define	_MY_SPC	010	/* Spacing character */
+#define	_MY_PNT	020	/* Punctuation */
+#define	_MY_CTR	040	/* Control character */
+#define	_MY_B	0100	/* Blank */
+#define	_MY_X	0200	/* heXadecimal digit */
+
+
+#define	my_isascii(c)	(!((c) & ~0177))
+#define	my_toascii(c)	((c) & 0177)
+#define my_tocntrl(c)	((c) & 31)
+#define my_toprint(c)	((c) | 64)
+#define my_toupper(s,c)	(char) ((s)->to_upper[(uchar) (c)])
+#define my_tolower(s,c)	(char) ((s)->to_lower[(uchar) (c)])
+#define	my_isalpha(s, c)  (((s)->ctype+1)[(uchar) (c)] & (_MY_U | _MY_L))
+#define	my_isupper(s, c)  (((s)->ctype+1)[(uchar) (c)] & _MY_U)
+#define	my_islower(s, c)  (((s)->ctype+1)[(uchar) (c)] & _MY_L)
+#define	my_isdigit(s, c)  (((s)->ctype+1)[(uchar) (c)] & _MY_NMR)
+#define	my_isxdigit(s, c) (((s)->ctype+1)[(uchar) (c)] & _MY_X)
+#define	my_isalnum(s, c)  (((s)->ctype+1)[(uchar) (c)] & (_MY_U | _MY_L | _MY_NMR))
+#define	my_isspace(s, c)  (((s)->ctype+1)[(uchar) (c)] & _MY_SPC)
+#define	my_ispunct(s, c)  (((s)->ctype+1)[(uchar) (c)] & _MY_PNT)
+#define	my_isprint(s, c)  (((s)->ctype+1)[(uchar) (c)] & (_MY_PNT | _MY_U | _MY_L | _MY_NMR | _MY_B))
+#define	my_isgraph(s, c)  (((s)->ctype+1)[(uchar) (c)] & (_MY_PNT | _MY_U | _MY_L | _MY_NMR))
+#define	my_iscntrl(s, c)  (((s)->ctype+1)[(uchar) (c)] & _MY_CTR)
+
+/* Some macros that should be cleaned up a little */
+#define my_isvar(s,c)                 (my_isalnum(s,c) || (c) == '_')
+#define my_isvar_start(s,c)           (my_isalpha(s,c) || (c) == '_')
+
+#define my_binary_compare(s)	      ((s)->state  & MY_CS_BINSORT)
+#define use_strnxfrm(s)               ((s)->state  & MY_CS_STRNXFRM)
+#define my_strnxfrm(s, a, b, c, d)    ((s)->coll->strnxfrm((s), (a), (b), (c), (d)))
+#define my_strnncoll(s, a, b, c, d) ((s)->coll->strnncoll((s), (a), (b), (c), (d), 0))
+#define my_like_range(s, a, b, c, d, e, f, g, h, i, j) \
+   ((s)->coll->like_range((s), (a), (b), (c), (d), (e), (f), (g), (h), (i), (j)))
+#define my_wildcmp(cs,s,se,w,we,e,o,m) ((cs)->coll->wildcmp((cs),(s),(se),(w),(we),(e),(o),(m)))
+#define my_strcasecmp(s, a, b)        ((s)->coll->strcasecmp((s), (a), (b)))
+#define my_charpos(cs, b, e, num)     (cs)->cset->charpos((cs), (const char*) (b), (const char *)(e), (num))
+
+
+#define use_mb(s)                     ((s)->cset->ismbchar != NULL)
+#define my_ismbchar(s, a, b)          ((s)->cset->ismbchar((s), (a), (b)))
+#ifdef USE_MB
+#define my_mbcharlen(s, a)            ((s)->cset->mbcharlen((s),(a)))
+#else
+#define my_mbcharlen(s, a)            1
+#endif
+
+#define my_caseup_str(s, a)           ((s)->cset->caseup_str((s), (a)))
+#define my_casedn_str(s, a)           ((s)->cset->casedn_str((s), (a)))
+#define my_strntol(s, a, b, c, d, e)  ((s)->cset->strntol((s),(a),(b),(c),(d),(e)))
+#define my_strntoul(s, a, b, c, d, e) ((s)->cset->strntoul((s),(a),(b),(c),(d),(e)))
+#define my_strntoll(s, a, b, c, d, e) ((s)->cset->strntoll((s),(a),(b),(c),(d),(e)))
+#define my_strntoull(s, a, b, c,d, e) ((s)->cset->strntoull((s),(a),(b),(c),(d),(e)))
+#define my_strntod(s, a, b, c, d)     ((s)->cset->strntod((s),(a),(b),(c),(d)))
+
+
+/* XXX: still need to take care of this one */
+#ifdef MY_CHARSET_TIS620
+#error The TIS620 charset is broken at the moment.  Tell tim to fix it.
+#define USE_TIS620
+#include "t_ctype.h"
+#endif
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif /* _m_ctype_h */
diff --git a/dep/include/mysql/m_string.h b/dep/include/mysql/m_string.h
new file mode 100644
index 00000000000..c26d0fb9260
--- /dev/null
+++ b/dep/include/mysql/m_string.h
@@ -0,0 +1,266 @@
+/* Copyright (C) 2000 MySQL AB
+
+   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; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+/* There may be prolems include all of theese. Try to test in
+   configure with ones are needed? */
+
+/*  This is needed for the definitions of strchr... on solaris */
+
+#ifndef _m_string_h
+#define _m_string_h
+#ifndef __USE_GNU
+#define __USE_GNU				/* We want to use stpcpy */
+#endif
+#if defined(HAVE_STRINGS_H)
+#include 
+#endif
+#if defined(HAVE_STRING_H)
+#include 
+#endif
+
+/* need by my_vsnprintf */
+#include  
+
+/* Correct some things for UNIXWARE7 */
+#ifdef HAVE_UNIXWARE7_THREADS
+#undef HAVE_STRINGS_H
+#undef HAVE_MEMORY_H
+#define HAVE_MEMCPY
+#ifndef HAVE_MEMMOVE
+#define HAVE_MEMMOVE
+#endif
+#undef HAVE_BCMP
+#undef bcopy
+#undef bcmp
+#undef bzero
+#endif /* HAVE_UNIXWARE7_THREADS */
+#ifdef _AIX
+#undef HAVE_BCMP
+#endif
+
+/*  This is needed for the definitions of bzero... on solaris */
+#if defined(HAVE_STRINGS_H) && !defined(HAVE_mit_thread)
+#include 
+#endif
+
+/*  This is needed for the definitions of memcpy... on solaris */
+#if defined(HAVE_MEMORY_H) && !defined(__cplusplus)
+#include 
+#endif
+
+#if !defined(HAVE_MEMCPY) && !defined(HAVE_MEMMOVE)
+# define memcpy(d, s, n)	bcopy ((s), (d), (n))
+# define memset(A,C,B)		bfill((A),(B),(C))
+# define memmove(d, s, n)	bmove ((d), (s), (n))
+#elif defined(HAVE_MEMMOVE)
+# define bmove(d, s, n)		memmove((d), (s), (n))
+#else
+# define memmove(d, s, n)	bmove((d), (s), (n)) /* our bmove */
+#endif
+
+/* Unixware 7 */
+#if !defined(HAVE_BFILL)
+# define bfill(A,B,C)           memset((A),(C),(B))
+# define bmove_align(A,B,C)    memcpy((A),(B),(C))
+#endif
+
+#if !defined(HAVE_BCMP)
+# define bcopy(s, d, n)		memcpy((d), (s), (n))
+# define bcmp(A,B,C)		memcmp((A),(B),(C))
+# define bzero(A,B)		memset((A),0,(B))
+# define bmove_align(A,B,C)    memcpy((A),(B),(C))
+#endif
+
+#if defined(__cplusplus) && !defined(OS2)
+extern "C" {
+#endif
+
+/*
+  my_str_malloc() and my_str_free() are assigned to implementations in
+  strings/alloc.c, but can be overridden in the calling program.
+ */
+extern void *(*my_str_malloc)(size_t);
+extern void (*my_str_free)(void *);
+
+#if defined(HAVE_STPCPY) && !defined(HAVE_mit_thread)
+#define strmov(A,B) stpcpy((A),(B))
+#ifndef stpcpy
+extern char *stpcpy(char *, const char *);	/* For AIX with gcc 2.95.3 */
+#endif
+#endif
+
+/* Declared in int2str() */
+extern char NEAR _dig_vec_upper[];
+extern char NEAR _dig_vec_lower[];
+
+/* Defined in strtod.c */
+extern const double log_10[309];
+
+#ifdef BAD_STRING_COMPILER
+#define strmov(A,B)  (memccpy(A,B,0,INT_MAX)-1)
+#else
+#define strmov_overlapp(A,B) strmov(A,B)
+#define strmake_overlapp(A,B,C) strmake(A,B,C)
+#endif
+
+#ifdef BAD_MEMCPY			/* Problem with gcc on Alpha */
+#define memcpy_fixed(A,B,C) bmove((A),(B),(C))
+#else
+#define memcpy_fixed(A,B,C) memcpy((A),(B),(C))
+#endif
+
+#ifdef MSDOS
+#undef bmove_align
+#define bmove512(A,B,C) bmove_align(A,B,C)
+extern	void bmove_align(gptr dst,const gptr src,uint len);
+#endif
+
+#if (!defined(USE_BMOVE512) || defined(HAVE_purify)) && !defined(bmove512)
+#define bmove512(A,B,C) memcpy(A,B,C)
+#endif
+
+	/* Prototypes for string functions */
+
+#if !defined(bfill) && !defined(HAVE_BFILL)
+extern	void bfill(gptr dst,uint len,pchar fill);
+#endif
+
+#if !defined(bzero) && !defined(HAVE_BZERO)
+extern	void bzero(gptr dst,uint len);
+#endif
+
+#if !defined(bcmp) && !defined(HAVE_BCMP)
+extern	int bcmp(const char *s1,const char *s2,uint len);
+#endif
+#ifdef HAVE_purify
+extern	int my_bcmp(const char *s1,const char *s2,uint len);
+#undef bcmp
+#define bcmp(A,B,C) my_bcmp((A),(B),(C))
+#endif
+
+#ifndef bmove512
+extern	void bmove512(gptr dst,const gptr src,uint len);
+#endif
+
+#if !defined(HAVE_BMOVE) && !defined(bmove)
+extern	void bmove(char *dst, const char *src,uint len);
+#endif
+
+extern	void bmove_upp(char *dst,const char *src,uint len);
+extern	void bchange(char *dst,uint old_len,const char *src,
+		     uint new_len,uint tot_len);
+extern	void strappend(char *s,uint len,pchar fill);
+extern	char *strend(const char *s);
+extern  char *strcend(const char *, pchar);
+extern	char *strfield(char *src,int fields,int chars,int blanks,
+			   int tabch);
+extern	char *strfill(my_string s,uint len,pchar fill);
+extern	uint strinstr(const char *str,const char *search);
+extern  uint r_strinstr(reg1 my_string str,int from, reg4 my_string search);
+extern	char *strkey(char *dst,char *head,char *tail,char *flags);
+extern	char *strmake(char *dst,const char *src,uint length);
+#ifndef strmake_overlapp
+extern	char *strmake_overlapp(char *dst,const char *src, uint length);
+#endif
+
+#ifndef strmov
+extern	char *strmov(char *dst,const char *src);
+#endif
+extern	char *strnmov(char *dst,const char *src,uint n);
+extern	char *strsuff(const char *src,const char *suffix);
+extern	char *strcont(const char *src,const char *set);
+extern	char *strxcat _VARARGS((char *dst,const char *src, ...));
+extern	char *strxmov _VARARGS((char *dst,const char *src, ...));
+extern	char *strxcpy _VARARGS((char *dst,const char *src, ...));
+extern	char *strxncat _VARARGS((char *dst,uint len, const char *src, ...));
+extern	char *strxnmov _VARARGS((char *dst,uint len, const char *src, ...));
+extern	char *strxncpy _VARARGS((char *dst,uint len, const char *src, ...));
+
+/* Prototypes of normal stringfunctions (with may ours) */
+
+#ifdef WANT_STRING_PROTOTYPES
+extern char *strcat(char *, const char *);
+extern char *strchr(const char *, pchar);
+extern char *strrchr(const char *, pchar);
+extern char *strcpy(char *, const char *);
+extern int strcmp(const char *, const char *);
+#ifndef __GNUC__
+extern size_t strlen(const char *);
+#endif
+#endif
+#ifndef HAVE_STRNLEN
+extern uint strnlen(const char *s, uint n);
+#endif
+
+#if !defined(__cplusplus)
+#ifndef HAVE_STRPBRK
+extern char *strpbrk(const char *, const char *);
+#endif
+#ifndef HAVE_STRSTR
+extern char *strstr(const char *, const char *);
+#endif
+#endif
+extern int is_prefix(const char *, const char *);
+
+/* Conversion routines */
+double my_strtod(const char *str, char **end, int *error);
+double my_atof(const char *nptr);
+
+extern char *llstr(longlong value,char *buff);
+extern char *ullstr(longlong value,char *buff);
+#ifndef HAVE_STRTOUL
+extern long strtol(const char *str, char **ptr, int base);
+extern ulong strtoul(const char *str, char **ptr, int base);
+#endif
+
+extern char *int2str(long val, char *dst, int radix, int upcase);
+extern char *int10_to_str(long val,char *dst,int radix);
+extern char *str2int(const char *src,int radix,long lower,long upper,
+			 long *val);
+longlong my_strtoll10(const char *nptr, char **endptr, int *error);
+#if SIZEOF_LONG == SIZEOF_LONG_LONG
+#define longlong2str(A,B,C) int2str((A),(B),(C),1)
+#define longlong10_to_str(A,B,C) int10_to_str((A),(B),(C))
+#undef strtoll
+#define strtoll(A,B,C) strtol((A),(B),(C))
+#define strtoull(A,B,C) strtoul((A),(B),(C))
+#ifndef HAVE_STRTOULL
+#define HAVE_STRTOULL
+#endif
+#ifndef HAVE_STRTOLL
+#define HAVE_STRTOLL
+#endif
+#else
+#ifdef HAVE_LONG_LONG
+extern char *longlong2str(longlong val,char *dst,int radix);
+extern char *longlong10_to_str(longlong val,char *dst,int radix);
+#if (!defined(HAVE_STRTOULL) || defined(HAVE_mit_thread)) || defined(NO_STRTOLL_PROTO)
+extern longlong strtoll(const char *str, char **ptr, int base);
+extern ulonglong strtoull(const char *str, char **ptr, int base);
+#endif
+#endif
+#endif
+
+/* my_vsnprintf.c */
+
+extern int my_vsnprintf( char *str, size_t n,
+                                const char *format, va_list ap );
+extern int my_snprintf(char *to, size_t n, const char *fmt, ...)
+  ATTRIBUTE_FORMAT(printf, 3, 4);
+
+#if defined(__cplusplus) && !defined(OS2)
+}
+#endif
+#endif
diff --git a/dep/include/mysql/my_alloc.h b/dep/include/mysql/my_alloc.h
new file mode 100644
index 00000000000..657394a363b
--- /dev/null
+++ b/dep/include/mysql/my_alloc.h
@@ -0,0 +1,51 @@
+/* Copyright (C) 2000 MySQL AB
+
+   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; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+/* 
+   Data structures for mysys/my_alloc.c (root memory allocator)
+*/
+
+#ifndef _my_alloc_h
+#define _my_alloc_h
+
+#define ALLOC_MAX_BLOCK_TO_DROP			4096
+#define ALLOC_MAX_BLOCK_USAGE_BEFORE_DROP	10
+
+typedef struct st_used_mem
+{				   /* struct for once_alloc (block) */
+  struct st_used_mem *next;	   /* Next block in use */
+  unsigned int	left;		   /* memory left in block  */
+  unsigned int	size;		   /* size of block */
+} USED_MEM;
+
+
+typedef struct st_mem_root
+{
+  USED_MEM *free;                  /* blocks with free memory in it */
+  USED_MEM *used;                  /* blocks almost without free memory */
+  USED_MEM *pre_alloc;             /* preallocated block */
+  /* if block have less memory it will be put in 'used' list */
+  unsigned int min_malloc;
+  unsigned int block_size;         /* initial block size */
+  unsigned int block_num;          /* allocated blocks counter */
+  /* 
+     first free block in queue test counter (if it exceed 
+     MAX_BLOCK_USAGE_BEFORE_DROP block will be dropped in 'used' list)
+  */
+  unsigned int first_block_usage;
+
+  void (*error_handler)(void);
+} MEM_ROOT;
+#endif
diff --git a/dep/include/mysql/my_dbug.h b/dep/include/mysql/my_dbug.h
new file mode 100644
index 00000000000..31fd507ec73
--- /dev/null
+++ b/dep/include/mysql/my_dbug.h
@@ -0,0 +1,107 @@
+/* Copyright (C) 2000 MySQL AB
+
+   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; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#ifndef _dbug_h
+#define _dbug_h
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+#if !defined(DBUG_OFF) && !defined(_lint)
+extern	int _db_on_,_no_db_;
+extern	FILE *_db_fp_;
+extern	char *_db_process_;
+extern	int _db_keyword_(const char *keyword);
+extern  int _db_strict_keyword_(const char *keyword);
+extern	void _db_setjmp_(void);
+extern	void _db_longjmp_(void);
+extern	void _db_push_(const char *control);
+extern	void _db_pop_(void);
+extern	void _db_enter_(const char *_func_,const char *_file_,uint _line_,
+			const char **_sfunc_,const char **_sfile_,
+			uint *_slevel_, char ***);
+extern	void _db_return_(uint _line_,const char **_sfunc_,const char **_sfile_,
+			 uint *_slevel_);
+extern	void _db_pargs_(uint _line_,const char *keyword);
+extern	void _db_doprnt_ _VARARGS((const char *format,...))
+  ATTRIBUTE_FORMAT(printf, 1, 2);
+extern	void _db_dump_(uint _line_,const char *keyword,const char *memory,
+		       uint length);
+extern	void _db_output_(uint flag);
+extern	void _db_end_(void);
+extern	void _db_lock_file(void);
+extern	void _db_unlock_file(void);
+
+#define DBUG_ENTER(a) const char *_db_func_, *_db_file_; uint _db_level_; \
+	char **_db_framep_; \
+	_db_enter_ (a,__FILE__,__LINE__,&_db_func_,&_db_file_,&_db_level_, \
+		    &_db_framep_)
+#define DBUG_LEAVE \
+	(_db_return_ (__LINE__, &_db_func_, &_db_file_, &_db_level_))
+#define DBUG_RETURN(a1) {DBUG_LEAVE; return(a1);}
+#define DBUG_VOID_RETURN {DBUG_LEAVE; return;}
+#define DBUG_EXECUTE(keyword,a1) \
+	{if (_db_on_) {if (_db_keyword_ (keyword)) { a1 }}}
+#define DBUG_PRINT(keyword,arglist) \
+	{if (_db_on_) {_db_pargs_(__LINE__,keyword); _db_doprnt_ arglist;}}
+#define DBUG_PUSH(a1) _db_push_ (a1)
+#define DBUG_POP() _db_pop_ ()
+#define DBUG_PROCESS(a1) (_db_process_ = a1)
+#define DBUG_FILE (_db_fp_)
+#define DBUG_SETJMP(a1) (_db_setjmp_ (), setjmp (a1))
+#define DBUG_LONGJMP(a1,a2) (_db_longjmp_ (), longjmp (a1, a2))
+#define DBUG_DUMP(keyword,a1,a2)\
+	{if (_db_on_) {_db_dump_(__LINE__,keyword,a1,a2);}}
+#define DBUG_IN_USE (_db_fp_ && _db_fp_ != stderr)
+#define DEBUGGER_OFF _no_db_=1;_db_on_=0;
+#define DEBUGGER_ON  _no_db_=0
+#define DBUG_END()  _db_end_ ()
+#define DBUG_LOCK_FILE { _db_lock_file(); }
+#define DBUG_UNLOCK_FILE { _db_unlock_file(); }
+#define DBUG_OUTPUT(A) { _db_output_(A); }
+#define DBUG_ASSERT(A) assert(A)
+#define DBUG_EXECUTE_IF(keyword,a1) \
+        {if (_db_on_) {if (_db_strict_keyword_ (keyword)) { a1 }}}
+#define IF_DBUG(A) A
+#else						/* No debugger */
+
+#define DBUG_ENTER(a1)
+#define DBUG_RETURN(a1) return(a1)
+#define DBUG_VOID_RETURN return
+#define DBUG_EXECUTE(keyword,a1) {}
+#define DBUG_EXECUTE_IF(keyword,a1) {}
+#define DBUG_PRINT(keyword,arglist) {}
+#define DBUG_PUSH(a1) {}
+#define DBUG_POP() {}
+#define DBUG_PROCESS(a1) {}
+#define DBUG_FILE (stderr)
+#define DBUG_SETJMP setjmp
+#define DBUG_LONGJMP longjmp
+#define DBUG_DUMP(keyword,a1,a2) {}
+#define DBUG_IN_USE 0
+#define DEBUGGER_OFF
+#define DEBUGGER_ON
+#define DBUG_END()
+#define DBUG_LOCK_FILE
+#define DBUG_UNLOCK_FILE
+#define DBUG_OUTPUT(A)
+#define DBUG_ASSERT(A) {}
+#define DBUG_LEAVE
+#define IF_DBUG(A)
+#endif
+#ifdef	__cplusplus
+}
+#endif
+#endif
diff --git a/dep/include/mysql/my_getopt.h b/dep/include/mysql/my_getopt.h
new file mode 100644
index 00000000000..f5688a37231
--- /dev/null
+++ b/dep/include/mysql/my_getopt.h
@@ -0,0 +1,77 @@
+/* Copyright (C) 2002-2004 MySQL AB
+
+   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; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#ifndef _my_getopt_h
+#define _my_getopt_h
+
+C_MODE_START
+
+#define GET_NO_ARG     1
+#define GET_BOOL       2
+#define GET_INT        3
+#define GET_UINT       4
+#define GET_LONG       5
+#define GET_ULONG      6
+#define GET_LL         7
+#define GET_ULL        8
+#define GET_STR        9
+#define GET_STR_ALLOC 10
+#define GET_DISABLED  11
+
+#define GET_ASK_ADDR	 128
+#define GET_TYPE_MASK	 127
+
+enum get_opt_arg_type { NO_ARG, OPT_ARG, REQUIRED_ARG };
+
+struct my_option
+{
+  const char *name;                     /* Name of the option */
+  int        id;                        /* unique id or short option */
+  const char *comment;                  /* option comment, for autom. --help */
+  gptr       *value;                    /* The variable value */
+  gptr       *u_max_value;              /* The user def. max variable value */
+  const char **str_values;              /* Pointer to possible values */
+  ulong     var_type;
+  enum get_opt_arg_type arg_type;
+  longlong   def_value;                 /* Default value */
+  longlong   min_value;                 /* Min allowed value */
+  longlong   max_value;                 /* Max allowed value */
+  longlong   sub_size;                  /* Subtract this from given value */
+  long       block_size;                /* Value should be a mult. of this */
+  int        app_type;                  /* To be used by an application */
+};
+
+typedef my_bool (* my_get_one_option) (int, const struct my_option *, char * );
+typedef void (* my_error_reporter) (enum loglevel level, const char *format, ... );
+
+extern char *disabled_my_option;
+extern my_bool my_getopt_print_errors;
+extern my_error_reporter my_getopt_error_reporter;
+
+extern int handle_options (int *argc, char ***argv, 
+			   const struct my_option *longopts, my_get_one_option);
+extern void my_print_help(const struct my_option *options);
+extern void my_print_variables(const struct my_option *options);
+extern void my_getopt_register_get_addr(gptr* (*func_addr)(const char *, uint,
+							   const struct my_option *));
+
+ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp,
+                                 bool *fixed);
+my_bool getopt_compare_strings(const char *s, const char *t, uint length);
+
+C_MODE_END
+
+#endif /* _my_getopt_h */
+
diff --git a/dep/include/mysql/my_global.h b/dep/include/mysql/my_global.h
new file mode 100644
index 00000000000..08877300d8a
--- /dev/null
+++ b/dep/include/mysql/my_global.h
@@ -0,0 +1,1354 @@
+/* Copyright (C) 2000-2003 MySQL AB
+
+   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; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+/* This is the include file that should be included 'first' in every C file. */
+
+#ifndef _global_h
+#define _global_h
+
+#ifndef EMBEDDED_LIBRARY
+#define HAVE_REPLICATION
+#define HAVE_EXTERNAL_CLIENT
+#endif
+
+#if defined( __EMX__) && !defined( MYSQL_SERVER)
+/* moved here to use below VOID macro redefinition */
+#define INCL_BASE
+#define INCL_NOPMAPI
+#include 
+#endif /* __EMX__ */
+
+#ifdef __CYGWIN__
+/* We use a Unix API, so pretend it's not Windows */
+#undef WIN
+#undef WIN32
+#undef _WIN
+#undef _WIN32
+#undef _WIN64
+#undef __WIN__
+#undef __WIN32__
+#define HAVE_ERRNO_AS_DEFINE
+#endif /* __CYGWIN__ */
+
+#if defined(__QNXNTO__) && !defined(FD_SETSIZE)
+#define FD_SETSIZE 1024         /* Max number of file descriptor bits in
+                                   fd_set, used when calling 'select'
+                                   Must be defined before including
+                                   "sys/select.h" and "sys/time.h"
+                                 */
+#endif
+
+
+/* to make command line shorter we'll define USE_PRAGMA_INTERFACE here */
+#ifdef USE_PRAGMA_IMPLEMENTATION
+#define USE_PRAGMA_INTERFACE
+#endif
+
+#if defined(i386) && !defined(__i386__)
+#define __i386__
+#endif
+
+/* Macros to make switching between C and C++ mode easier */
+#ifdef __cplusplus
+#define C_MODE_START    extern "C" {
+#define C_MODE_END	}
+#else
+#define C_MODE_START
+#define C_MODE_END
+#endif
+
+#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
+#include 
+#elif defined(OS2)
+#include 
+#elif defined(__NETWARE__)
+#include 
+#include 
+#if defined(__cplusplus) && defined(inline)
+#undef inline				/* fix configure problem */
+#endif
+#else
+#include 
+#if defined(__cplusplus) && defined(inline)
+#undef inline				/* fix configure problem */
+#endif
+#endif /* _WIN32... */
+
+/* Make it easier to add conditionl code for windows */
+#ifdef __WIN__
+#define IF_WIN(A,B) (A)
+#else
+#define IF_WIN(A,B) (B)
+#endif
+
+
+/* Some defines to avoid ifdefs in the code */
+#ifndef NETWARE_YIELD
+#define NETWARE_YIELD
+#define NETWARE_SET_SCREEN_MODE(A)
+#endif
+
+/* Workaround for _LARGE_FILES and _LARGE_FILE_API incompatibility on AIX */
+#if defined(_AIX) && defined(_LARGE_FILE_API)
+#undef _LARGE_FILE_API
+#endif
+
+/*
+  The macros below are used to allow build of Universal/fat binaries of
+  MySQL and MySQL applications under darwin. 
+*/
+#if defined(__APPLE__) && defined(__MACH__)
+#  undef SIZEOF_CHARP 
+#  undef SIZEOF_SHORT 
+#  undef SIZEOF_INT 
+#  undef SIZEOF_LONG 
+#  undef SIZEOF_LONG_LONG 
+#  undef SIZEOF_OFF_T 
+#  undef WORDS_BIGENDIAN
+#  define SIZEOF_SHORT 2
+#  define SIZEOF_INT 4
+#  define SIZEOF_LONG_LONG 8
+#  define SIZEOF_OFF_T 8
+#  if defined(__i386__) || defined(__ppc__)
+#    define SIZEOF_CHARP 4
+#    define SIZEOF_LONG 4
+#  elif defined(__x86_64__) || defined(__ppc64__)
+#    define SIZEOF_CHARP 8
+#    define SIZEOF_LONG 8
+#  else
+#    error Building FAT binary for an unknown architecture.
+#  endif
+#  if defined(__ppc__) || defined(__ppc64__)
+#    define WORDS_BIGENDIAN
+#  endif
+#endif /* defined(__APPLE__) && defined(__MACH__) */
+
+
+/*
+  The macros below are borrowed from include/linux/compiler.h in the
+  Linux kernel. Use them to indicate the likelyhood of the truthfulness
+  of a condition. This serves two purposes - newer versions of gcc will be
+  able to optimize for branch predication, which could yield siginficant
+  performance gains in frequently executed sections of the code, and the
+  other reason to use them is for documentation
+*/
+
+#if !defined(__GNUC__) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
+#define __builtin_expect(x, expected_value) (x)
+#endif
+
+#define likely(x)	__builtin_expect((x),1)
+#define unlikely(x)	__builtin_expect((x),0)
+
+
+/* Fix problem with S_ISLNK() on Linux */
+#if defined(TARGET_OS_LINUX) || defined(__GLIBC__)
+#undef  _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+/*
+  Temporary solution to solve bug#7156. Include "sys/types.h" before
+  the thread headers, else the function madvise() will not be defined
+*/
+#if defined(HAVE_SYS_TYPES_H) && ( defined(sun) || defined(__sun) )
+#include 
+#endif
+
+/* The client defines this to avoid all thread code */
+#if defined(UNDEF_THREADS_HACK)
+#undef THREAD
+#undef HAVE_mit_thread
+#undef HAVE_LINUXTHREADS
+#undef HAVE_NPTL
+#undef HAVE_UNIXWARE7_THREADS
+#endif
+
+#ifdef HAVE_THREADS_WITHOUT_SOCKETS
+/* MIT pthreads does not work with unix sockets */
+#undef HAVE_SYS_UN_H
+#endif
+
+#define __EXTENSIONS__ 1	/* We want some extension */
+#ifndef __STDC_EXT__
+#define __STDC_EXT__ 1          /* To get large file support on hpux */
+#endif
+
+/*
+  Solaris 9 include file  refers to X/Open document
+
+    System Interfaces and Headers, Issue 5
+
+  saying we should define _XOPEN_SOURCE=500 to get POSIX.1c prototypes,
+  but apparently other systems (namely FreeBSD) don't agree.
+
+  On a newer Solaris 10, the above file recognizes also _XOPEN_SOURCE=600.
+  Furthermore, it tests that if a program requires older standard
+  (_XOPEN_SOURCE<600 or _POSIX_C_SOURCE<200112L) it cannot be
+  run on a new compiler (that defines _STDC_C99) and issues an #error.
+  It's also an #error if a program requires new standard (_XOPEN_SOURCE=600
+  or _POSIX_C_SOURCE=200112L) and a compiler does not define _STDC_C99.
+
+  To add more to this mess, Sun Studio C compiler defines _STDC_C99 while
+  C++ compiler does not!
+
+  So, in a desperate attempt to get correct prototypes for both
+  C and C++ code, we define either _XOPEN_SOURCE=600 or _XOPEN_SOURCE=500
+  depending on the compiler's announced C standard support.
+
+  Cleaner solutions are welcome.
+*/
+#ifdef __sun
+#if __STDC_VERSION__ - 0 >= 199901L
+#define _XOPEN_SOURCE 600
+#else
+#define _XOPEN_SOURCE 500
+#endif
+#endif
+
+#if defined(THREAD) && !defined(__WIN__) && !defined(OS2)
+#ifndef _POSIX_PTHREAD_SEMANTICS
+#define _POSIX_PTHREAD_SEMANTICS /* We want posix threads */
+#endif
+
+#if !defined(SCO)
+#define _REENTRANT	1	/* Some thread libraries require this */
+#endif
+#if !defined(_THREAD_SAFE) && !defined(_AIX)
+#define _THREAD_SAFE            /* Required for OSF1 */
+#endif
+#ifndef HAVE_mit_thread
+#ifdef HAVE_UNIXWARE7_THREADS
+#include 
+#else
+#if defined(HPUX10) || defined(HPUX11)
+C_MODE_START			/* HPUX needs this, signal.h bug */
+#include 
+C_MODE_END
+#else
+#include 		/* AIX must have this included first */
+#endif
+#endif /* HAVE_UNIXWARE7_THREADS */
+#endif /* HAVE_mit_thread */
+#if !defined(SCO) && !defined(_REENTRANT)
+#define _REENTRANT	1	/* Threads requires reentrant code */
+#endif
+#endif /* THREAD */
+
+/* Go around some bugs in different OS and compilers */
+#ifdef _AIX			/* By soren@t.dk */
+#define _H_STRINGS
+#define _SYS_STREAM_H
+/* #define _AIX32_CURSES */	/* XXX: this breaks AIX 4.3.3 (others?). */
+#define ulonglong2double(A) my_ulonglong2double(A)
+#define my_off_t2double(A)  my_ulonglong2double(A)
+C_MODE_START
+double my_ulonglong2double(unsigned long long A);
+C_MODE_END
+#endif /* _AIX */
+
+#ifdef HAVE_BROKEN_SNPRINTF	/* HPUX 10.20 don't have this defined */
+#undef HAVE_SNPRINTF
+#endif
+#ifdef HAVE_BROKEN_PREAD
+/*
+  pread()/pwrite() are not 64 bit safe on HP-UX 11.0 without
+  installing the kernel patch PHKL_20349 or greater
+*/
+#undef HAVE_PREAD
+#undef HAVE_PWRITE
+#endif
+#if defined(HAVE_BROKEN_INLINE) && !defined(__cplusplus)
+#undef inline
+#define inline
+#endif
+
+#ifdef UNDEF_HAVE_GETHOSTBYNAME_R		/* For OSF4.x */
+#undef HAVE_GETHOSTBYNAME_R
+#endif
+#ifdef UNDEF_HAVE_INITGROUPS			/* For AIX 4.3 */
+#undef HAVE_INITGROUPS
+#endif
+
+/* gcc/egcs issues */
+
+#if defined(__GNUC) && defined(__EXCEPTIONS)
+#error "Please add -fno-exceptions to CXXFLAGS and reconfigure/recompile"
+#endif
+
+
+/* Fix a bug in gcc 2.8.0 on IRIX 6.2 */
+#if SIZEOF_LONG == 4 && defined(__LONG_MAX__) && (__GNUC__ == 2 && __GNUC_MINOR__ == 8)
+#undef __LONG_MAX__             /* Is a longlong value in gcc 2.8.0 ??? */
+#define __LONG_MAX__ 2147483647
+#endif
+
+/* egcs 1.1.2 has a problem with memcpy on Alpha */
+#if defined(__GNUC__) && defined(__alpha__) && ! (__GNUC__ > 2 || (__GNUC__ == 2 &&  __GNUC_MINOR__ >= 95))
+#define BAD_MEMCPY
+#endif
+
+#if defined(_lint) && !defined(lint)
+#define lint
+#endif
+#if SIZEOF_LONG_LONG > 4 && !defined(_LONG_LONG)
+#define _LONG_LONG 1		/* For AIX string library */
+#endif
+
+#ifndef stdin
+#include 
+#endif
+#ifdef HAVE_STDLIB_H
+#include 
+#endif
+#ifdef HAVE_STDDEF_H
+#include 
+#endif
+
+#include 
+#ifdef HAVE_LIMITS_H
+#include 
+#endif
+#ifdef HAVE_FLOAT_H
+#include 
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include 
+#endif
+#ifdef HAVE_FCNTL_H
+#include 
+#endif
+#ifdef HAVE_SYS_TIMEB_H
+#include 				/* Avoid warnings on SCO */
+#endif
+#if TIME_WITH_SYS_TIME
+# include 
+# include 
+#else
+# if HAVE_SYS_TIME_H
+#  include 
+# else
+#  include 
+# endif
+#endif /* TIME_WITH_SYS_TIME */
+#ifdef HAVE_UNISTD_H
+#include 
+#endif
+#if defined(__cplusplus) && defined(NO_CPLUSPLUS_ALLOCA)
+#undef HAVE_ALLOCA
+#undef HAVE_ALLOCA_H
+#endif
+#ifdef HAVE_ALLOCA_H
+#include 
+#endif
+#ifdef HAVE_ATOMIC_ADD
+#define new my_arg_new
+#define need_to_restore_new 1
+C_MODE_START
+#include 
+C_MODE_END
+#ifdef need_to_restore_new /* probably safer than #ifdef new */
+#undef new
+#undef need_to_restore_new
+#endif
+#endif
+#include 				/* Recommended by debian */
+/* We need the following to go around a problem with openssl on solaris */
+#if defined(HAVE_CRYPT_H)
+#include 
+#endif
+
+/*
+  A lot of our programs uses asserts, so better to always include it
+  This also fixes a problem when people uses DBUG_ASSERT without including
+  assert.h
+*/
+#include 
+
+/* Go around some bugs in different OS and compilers */
+#if defined(_HPUX_SOURCE) && defined(HAVE_SYS_STREAM_H)
+#include 		/* HPUX 10.20 defines ulong here. UGLY !!! */
+#define HAVE_ULONG
+#endif
+#ifdef DONT_USE_FINITE		/* HPUX 11.x has is_finite() */
+#undef HAVE_FINITE
+#endif
+#if defined(HPUX10) && defined(_LARGEFILE64_SOURCE) && defined(THREAD)
+/* Fix bug in setrlimit */
+#undef setrlimit
+#define setrlimit cma_setrlimit64
+#endif
+/* Declare madvise where it is not declared for C++, like Solaris */
+#if HAVE_MADVISE && !HAVE_DECL_MADVISE && defined(__cplusplus)
+extern "C" int madvise(void *addr, size_t len, int behav);
+#endif
+
+#ifdef __QNXNTO__
+/* This has to be after include limits.h */
+#define HAVE_ERRNO_AS_DEFINE
+#define HAVE_FCNTL_LOCK
+#undef  HAVE_FINITE
+#undef  LONGLONG_MIN            /* These get wrongly defined in QNX 6.2 */
+#undef  LONGLONG_MAX            /* standard system library 'limits.h' */
+#ifdef __cplusplus
+#ifndef HAVE_RINT
+#define HAVE_RINT
+#endif                          /* rint() and isnan() functions are not */
+#define rint(a) std::rint(a)    /* visible in C++ scope due to an error */
+#define isnan(a) std::isnan(a)  /* in the usr/include/math.h on QNX     */
+#endif
+#endif
+
+/* We can not live without the following defines */
+
+#define USE_MYFUNC 1		/* Must use syscall indirection */
+#define MASTER 1		/* Compile without unireg */
+#define ENGLISH 1		/* Messages in English */
+#define POSIX_MISTAKE 1		/* regexp: Fix stupid spec error */
+#define USE_REGEX 1		/* We want the use the regex library */
+/* Do not define for ultra sparcs */
+#ifndef OS2
+#define USE_BMOVE512 1		/* Use this unless system bmove is faster */
+#endif
+
+#define QUOTE_ARG(x)		#x	/* Quote argument (before cpp) */
+#define STRINGIFY_ARG(x) QUOTE_ARG(x)	/* Quote argument, after cpp */
+
+/* Paranoid settings. Define I_AM_PARANOID if you are paranoid */
+#ifdef I_AM_PARANOID
+#define DONT_ALLOW_USER_CHANGE 1
+#define DONT_USE_MYSQL_PWD 1
+#endif
+
+/* Does the system remember a signal handler after a signal ? */
+#ifndef HAVE_BSD_SIGNALS
+#define DONT_REMEMBER_SIGNAL
+#endif
+
+/* Define void to stop lint from generating "null effekt" comments */
+#ifndef DONT_DEFINE_VOID
+#ifdef _lint
+int	__void__;
+#define VOID(X)		(__void__ = (int) (X))
+#else
+#undef VOID
+#define VOID(X)		(X)
+#endif
+#endif /* DONT_DEFINE_VOID */
+
+#if defined(_lint) || defined(FORCE_INIT_OF_VARS)
+#define LINT_INIT(var)	var=0			/* No uninitialize-warning */
+#else
+#define LINT_INIT(var)
+#endif
+
+#if defined(_lint) || defined(FORCE_INIT_OF_VARS) || defined(HAVE_purify)
+#define PURIFY_OR_LINT_INIT(var) var=0
+#else
+#define PURIFY_OR_LINT_INIT(var)
+#endif
+
+/* Define some useful general macros */
+#if !defined(max)
+#define max(a, b)	((a) > (b) ? (a) : (b))
+#define min(a, b)	((a) < (b) ? (a) : (b))
+#endif
+
+#if defined(__EMX__) || !defined(HAVE_UINT)
+#undef HAVE_UINT
+#define HAVE_UINT
+typedef unsigned int uint;
+typedef unsigned short ushort;
+#endif
+
+#define CMP_NUM(a,b)    (((a) < (b)) ? -1 : ((a) == (b)) ? 0 : 1)
+#define sgn(a)		(((a) < 0) ? -1 : ((a) > 0) ? 1 : 0)
+#define swap_variables(t, a, b) { register t dummy; dummy= a; a= b; b= dummy; }
+#define test(a)		((a) ? 1 : 0)
+#define set_if_bigger(a,b)  do { if ((a) < (b)) (a)=(b); } while(0)
+#define set_if_smaller(a,b) do { if ((a) > (b)) (a)=(b); } while(0)
+#define test_all_bits(a,b) (((a) & (b)) == (b))
+#define set_bits(type, bit_count) (sizeof(type)*8 <= (bit_count) ? ~(type) 0 : ((((type) 1) << (bit_count)) - (type) 1))
+#define array_elements(A) ((uint) (sizeof(A)/sizeof(A[0])))
+#ifndef HAVE_RINT
+#define rint(A) floor((A)+(((A) < 0)? -0.5 : 0.5))
+#endif
+
+/* Define some general constants */
+#ifndef TRUE
+#define TRUE		(1)	/* Logical true */
+#define FALSE		(0)	/* Logical false */
+#endif
+
+#if defined(__GNUC__)
+#define function_volatile	volatile
+#define my_reinterpret_cast(A) reinterpret_cast
+#define my_const_cast(A) const_cast
+# ifndef GCC_VERSION
+#  define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
+# endif
+#elif !defined(my_reinterpret_cast)
+#define my_reinterpret_cast(A) (A)
+#define my_const_cast(A) (A)
+#endif
+
+#include 
+
+/*
+  Wen using the embedded library, users might run into link problems,
+  duplicate declaration of __cxa_pure_virtual, solved by declaring it a
+  weak symbol.
+*/
+#if defined(USE_MYSYS_NEW) && ! defined(DONT_DECLARE_CXA_PURE_VIRTUAL)
+C_MODE_START
+int __cxa_pure_virtual () __attribute__ ((weak));
+C_MODE_END
+#endif
+
+/* From old s-system.h */
+
+/*
+  Support macros for non ansi & other old compilers. Since such
+  things are no longer supported we do nothing. We keep then since
+  some of our code may still be needed to upgrade old customers.
+*/
+#define _VARARGS(X) X
+#define _STATIC_VARARGS(X) X
+#define _PC(X)	X
+
+#if defined(DBUG_ON) && defined(DBUG_OFF)
+#undef DBUG_OFF
+#endif
+
+#if defined(_lint) && !defined(DBUG_OFF)
+#define DBUG_OFF
+#endif
+
+#include 
+
+#define MIN_ARRAY_SIZE	0	/* Zero or One. Gcc allows zero*/
+#define ASCII_BITS_USED 8	/* Bit char used */
+#define NEAR_F			/* No near function handling */
+
+/* Some types that is different between systems */
+
+typedef int	File;		/* File descriptor */
+#ifndef Socket_defined
+typedef int	my_socket;	/* File descriptor for sockets */
+#define INVALID_SOCKET -1
+#endif
+/* Type for fuctions that handles signals */
+#define sig_handler RETSIGTYPE
+C_MODE_START
+typedef void	(*sig_return)();/* Returns type from signal */
+C_MODE_END
+#if defined(__GNUC__) && !defined(_lint)
+typedef char	pchar;		/* Mixed prototypes can take char */
+typedef char	puchar;		/* Mixed prototypes can take char */
+typedef char	pbool;		/* Mixed prototypes can take char */
+typedef short	pshort;		/* Mixed prototypes can take short int */
+typedef float	pfloat;		/* Mixed prototypes can take float */
+#else
+typedef int	pchar;		/* Mixed prototypes can't take char */
+typedef uint	puchar;		/* Mixed prototypes can't take char */
+typedef int	pbool;		/* Mixed prototypes can't take char */
+typedef int	pshort;		/* Mixed prototypes can't take short int */
+typedef double	pfloat;		/* Mixed prototypes can't take float */
+#endif
+C_MODE_START
+typedef int	(*qsort_cmp)(const void *,const void *);
+typedef int	(*qsort_cmp2)(void*, const void *,const void *);
+C_MODE_END
+#ifdef HAVE_mit_thread
+#define qsort_t void
+#undef QSORT_TYPE_IS_VOID
+#define QSORT_TYPE_IS_VOID
+#else
+#define qsort_t RETQSORTTYPE	/* Broken GCC cant handle typedef !!!! */
+#endif
+#ifdef HAVE_mit_thread
+#define size_socket socklen_t	/* Type of last arg to accept */
+#else
+#ifdef HAVE_SYS_SOCKET_H
+#include 
+#endif
+typedef SOCKET_SIZE_TYPE size_socket;
+#endif
+
+#ifndef SOCKOPT_OPTLEN_TYPE
+#define SOCKOPT_OPTLEN_TYPE size_socket
+#endif
+
+/* file create flags */
+
+#ifndef O_SHARE			/* Probably not windows */
+#define O_SHARE		0	/* Flag to my_open for shared files */
+#ifndef O_BINARY
+#define O_BINARY	0	/* Flag to my_open for binary files */
+#endif
+#ifndef FILE_BINARY
+#define FILE_BINARY	O_BINARY /* Flag to my_fopen for binary streams */
+#endif
+#ifdef HAVE_FCNTL
+#define HAVE_FCNTL_LOCK
+#define F_TO_EOF	0L	/* Param to lockf() to lock rest of file */
+#endif
+#endif /* O_SHARE */
+
+#ifndef O_TEMPORARY
+#define O_TEMPORARY	0
+#endif
+#ifndef O_SHORT_LIVED
+#define O_SHORT_LIVED	0
+#endif
+#ifndef O_NOFOLLOW
+#define O_NOFOLLOW      0
+#endif
+
+/* additional file share flags for win32 */
+#ifdef __WIN__
+#define _SH_DENYRWD     0x110    /* deny read/write mode & delete */
+#define _SH_DENYWRD     0x120    /* deny write mode & delete      */
+#define _SH_DENYRDD     0x130    /* deny read mode & delete       */
+#define _SH_DENYDEL     0x140    /* deny delete only              */
+#endif /* __WIN__ */
+
+
+/* #define USE_RECORD_LOCK	*/
+
+	/* Unsigned types supported by the compiler */
+#define UNSINT8			/* unsigned int8 (char) */
+#define UNSINT16		/* unsigned int16 */
+#define UNSINT32		/* unsigned int32 */
+
+	/* General constants */
+#define SC_MAXWIDTH	256	/* Max width of screen (for error messages) */
+#define FN_LEN		256	/* Max file name len */
+#define FN_HEADLEN	253	/* Max length of filepart of file name */
+#define FN_EXTLEN	20	/* Max length of extension (part of FN_LEN) */
+#define FN_REFLEN	512	/* Max length of full path-name */
+#define FN_EXTCHAR	'.'
+#define FN_HOMELIB	'~'	/* ~/ is used as abbrev for home dir */
+#define FN_CURLIB	'.'	/* ./ is used as abbrev for current dir */
+#define FN_PARENTDIR	".."	/* Parent directory; Must be a string */
+
+#ifndef FN_LIBCHAR
+#ifdef __EMX__
+#define FN_LIBCHAR	'\\'
+#define FN_ROOTDIR	"\\"
+#else
+#define FN_LIBCHAR	'/'
+#define FN_ROOTDIR	"/"
+#endif
+#endif
+#define MY_NFILE	64	/* This is only used to save filenames */
+#ifndef OS_FILE_LIMIT
+#define OS_FILE_LIMIT	65535
+#endif
+
+/* #define EXT_IN_LIBNAME     */
+/* #define FN_NO_CASE_SENCE   */
+/* #define FN_UPPER_CASE TRUE */
+
+/*
+  Io buffer size; Must be a power of 2 and a multiple of 512. May be
+  smaller what the disk page size. This influences the speed of the
+  isam btree library. eg to big to slow.
+*/
+#define IO_SIZE			4096
+/*
+  How much overhead does malloc have. The code often allocates
+  something like 1024-MALLOC_OVERHEAD bytes
+*/
+#ifdef SAFEMALLOC
+#define MALLOC_OVERHEAD (8+24+4)
+#else
+#define MALLOC_OVERHEAD 8
+#endif
+	/* get memory in huncs */
+#define ONCE_ALLOC_INIT		(uint) (4096-MALLOC_OVERHEAD)
+	/* Typical record cash */
+#define RECORD_CACHE_SIZE	(uint) (64*1024-MALLOC_OVERHEAD)
+	/* Typical key cash */
+#define KEY_CACHE_SIZE		(uint) (8*1024*1024-MALLOC_OVERHEAD)
+	/* Default size of a key cache block  */
+#define KEY_CACHE_BLOCK_SIZE	(uint) 1024
+
+
+	/* Some things that this system doesn't have */
+
+#define NO_HASH			/* Not needed anymore */
+#ifdef __WIN__
+#define NO_DIR_LIBRARY		/* Not standar dir-library */
+#define USE_MY_STAT_STRUCT	/* For my_lib */
+#endif
+
+/* Some defines of functions for portability */
+
+#undef remove		/* Crashes MySQL on SCO 5.0.0 */
+#ifndef __WIN__
+#ifdef OS2
+#define closesocket(A)	soclose(A)
+#else
+#define closesocket(A)	close(A)
+#endif
+#ifndef ulonglong2double
+#define ulonglong2double(A) ((double) (ulonglong) (A))
+#define my_off_t2double(A)  ((double) (my_off_t) (A))
+#endif
+#endif
+
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+#define ulong_to_double(X) ((double) (ulong) (X))
+#define SET_STACK_SIZE(X)	/* Not needed on real machines */
+
+#if !defined(HAVE_mit_thread) && !defined(HAVE_STRTOK_R)
+#define strtok_r(A,B,C) strtok((A),(B))
+#endif
+
+/* Remove some things that mit_thread break or doesn't support */
+#if defined(HAVE_mit_thread) && defined(THREAD)
+#undef HAVE_PREAD
+#undef HAVE_REALPATH
+#undef HAVE_MLOCK
+#undef HAVE_TEMPNAM				/* Use ours */
+#undef HAVE_PTHREAD_SETPRIO
+#undef HAVE_FTRUNCATE
+#undef HAVE_READLINK
+#endif
+
+/* This is from the old m-machine.h file */
+
+#if SIZEOF_LONG_LONG > 4
+#define HAVE_LONG_LONG 1
+#endif
+
+/*
+  Some pre-ANSI-C99 systems like AIX 5.1 and Linux/GCC 2.95 define
+  ULONGLONG_MAX, LONGLONG_MIN, LONGLONG_MAX; we use them if they're defined.
+  Also on Windows we define these constants by hand in config-win.h.
+*/
+
+#if defined(HAVE_LONG_LONG) && !defined(LONGLONG_MIN)
+#define LONGLONG_MIN	((long long) 0x8000000000000000LL)
+#define LONGLONG_MAX	((long long) 0x7FFFFFFFFFFFFFFFLL)
+#endif
+
+#if defined(HAVE_LONG_LONG) && !defined(ULONGLONG_MAX)
+/* First check for ANSI C99 definition: */
+#ifdef ULLONG_MAX
+#define ULONGLONG_MAX  ULLONG_MAX
+#else
+#define ULONGLONG_MAX ((unsigned long long)(~0ULL))
+#endif
+#endif /* defined (HAVE_LONG_LONG) && !defined(ULONGLONG_MAX)*/
+
+#define INT_MIN32       (~0x7FFFFFFFL)
+#define INT_MAX32       0x7FFFFFFFL
+#define UINT_MAX32      0xFFFFFFFFL
+#define INT_MIN24       (~0x007FFFFF)
+#define INT_MAX24       0x007FFFFF
+#define UINT_MAX24      0x00FFFFFF
+#define INT_MIN16       (~0x7FFF)
+#define INT_MAX16       0x7FFF
+#define UINT_MAX16      0xFFFF
+#define INT_MIN8        (~0x7F)
+#define INT_MAX8        0x7F
+#define UINT_MAX8       0xFF
+
+/* From limits.h instead */
+#ifndef DBL_MIN
+#define DBL_MIN		4.94065645841246544e-324
+#define FLT_MIN		((float)1.40129846432481707e-45)
+#endif
+#ifndef DBL_MAX
+#define DBL_MAX		1.79769313486231470e+308
+#define FLT_MAX		((float)3.40282346638528860e+38)
+#endif
+
+#ifndef HAVE_FINITE
+#define finite(x) (1.0 / fabs(x) > 0.0)
+#endif
+
+#ifndef HAVE_ISNAN
+#define isnan(x) ((x) != (x))
+#endif
+
+#ifdef HAVE_ISINF
+/* isinf() can be used in both C and C++ code */
+#define my_isinf(X) isinf(X)
+#else
+#define my_isinf(X) (!finite(X) && !isnan(X))
+#endif
+
+/* Define missing math constants. */
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_E
+#define M_E 2.7182818284590452354
+#endif
+#ifndef M_LN2
+#define M_LN2 0.69314718055994530942
+#endif
+
+/*
+  Max size that must be added to a so that we know Size to make
+  adressable obj.
+*/
+#if SIZEOF_CHARP == 4
+typedef long		my_ptrdiff_t;
+#else
+typedef long long	my_ptrdiff_t;
+#endif
+
+#define MY_ALIGN(A,L)	(((A) + (L) - 1) & ~((L) - 1))
+#define ALIGN_SIZE(A)	MY_ALIGN((A),sizeof(double))
+/* Size to make adressable obj. */
+#define ALIGN_PTR(A, t) ((t*) MY_ALIGN((A),sizeof(t)))
+			 /* Offset of field f in structure t */
+#define OFFSET(t, f)	((size_t)(char *)&((t *)0)->f)
+#define ADD_TO_PTR(ptr,size,type) (type) ((byte*) (ptr)+size)
+#define PTR_BYTE_DIFF(A,B) (my_ptrdiff_t) ((byte*) (A) - (byte*) (B))
+
+/*
+  Custom version of standard offsetof() macro which can be used to get
+  offsets of members in class for non-POD types (according to the current
+  version of C++ standard offsetof() macro can't be used in such cases and
+  attempt to do so causes warnings to be emitted, OTOH in many cases it is
+  still OK to assume that all instances of the class has the same offsets
+  for the same members).
+
+  This is temporary solution which should be removed once File_parser class
+  and related routines are refactored.
+*/
+
+#define my_offsetof(TYPE, MEMBER) \
+        ((size_t)((char *)&(((TYPE *)0x10)->MEMBER) - (char*)0x10))
+
+#define NullS		(char *) 0
+/* Nowdays we do not support MessyDos */
+#ifndef NEAR
+#define NEAR				/* Who needs segments ? */
+#define FAR				/* On a good machine */
+#ifndef HUGE_PTR
+#define HUGE_PTR
+#endif
+#endif
+#if defined(__IBMC__) || defined(__IBMCPP__)
+/* This was  _System _Export but caused a lot of warnings on _AIX43 */
+#define STDCALL
+#elif !defined( STDCALL)
+#define STDCALL
+#endif
+
+/* Typdefs for easyier portability */
+
+#if defined(VOIDTYPE)
+typedef void	*gptr;		/* Generic pointer */
+#else
+typedef char	*gptr;		/* Generic pointer */
+#endif
+#ifndef HAVE_INT_8_16_32
+typedef signed char int8;       /* Signed integer >= 8  bits */
+typedef short	int16;		/* Signed integer >= 16 bits */
+#endif
+#ifndef HAVE_UCHAR
+typedef unsigned char	uchar;	/* Short for unsigned char */
+#endif
+typedef unsigned char	uint8;	/* Short for unsigned integer >= 8  bits */
+typedef unsigned short	uint16; /* Short for unsigned integer >= 16 bits */
+
+#if SIZEOF_INT == 4
+#ifndef HAVE_INT_8_16_32
+typedef int		int32;
+#endif
+typedef unsigned int	uint32; /* Short for unsigned integer >= 32 bits */
+#elif SIZEOF_LONG == 4
+#ifndef HAVE_INT_8_16_32
+typedef long		int32;
+#endif
+typedef unsigned long	uint32; /* Short for unsigned integer >= 32 bits */
+#else
+#error "Neither int or long is of 4 bytes width"
+#endif
+
+#if !defined(HAVE_ULONG) && !defined(TARGET_OS_LINUX) && !defined(__USE_MISC)
+typedef unsigned long	ulong;		  /* Short for unsigned long */
+#endif
+#ifndef longlong_defined
+/* 
+  Using [unsigned] long long is preferable as [u]longlong because we use 
+  [unsigned] long long unconditionally in many places, 
+  for example in constants with [U]LL suffix.
+*/
+#if defined(HAVE_LONG_LONG) && SIZEOF_LONG_LONG == 8
+typedef unsigned long long int ulonglong; /* ulong or unsigned long long */
+typedef long long int	longlong;
+#else
+typedef unsigned long	ulonglong;	  /* ulong or unsigned long long */
+typedef long		longlong;
+#endif
+#endif
+
+#if defined(NO_CLIENT_LONG_LONG)
+typedef unsigned long my_ulonglong;
+#elif defined (__WIN__)
+typedef unsigned __int64 my_ulonglong;
+#else
+typedef unsigned long long my_ulonglong;
+#endif
+
+#ifdef USE_RAID
+/*
+  The following is done with a if to not get problems with pre-processors
+  with late define evaluation
+*/
+#if SIZEOF_OFF_T == 4
+#define SYSTEM_SIZEOF_OFF_T 4
+#else
+#define SYSTEM_SIZEOF_OFF_T 8
+#endif
+#undef  SIZEOF_OFF_T
+#define SIZEOF_OFF_T	    8
+#else
+#define SYSTEM_SIZEOF_OFF_T SIZEOF_OFF_T
+#endif /* USE_RAID */
+
+#if SIZEOF_OFF_T > 4
+typedef ulonglong my_off_t;
+#else
+typedef unsigned long my_off_t;
+#endif
+#define MY_FILEPOS_ERROR	(~(my_off_t) 0)
+#if !defined(__WIN__) && !defined(OS2)
+typedef off_t os_off_t;
+#endif
+
+#if defined(__WIN__)
+#define socket_errno	WSAGetLastError()
+#define SOCKET_EINTR	WSAEINTR
+#define SOCKET_EAGAIN	WSAEINPROGRESS
+#define SOCKET_ETIMEDOUT WSAETIMEDOUT
+#define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK
+#define SOCKET_EADDRINUSE WSAEADDRINUSE
+#define SOCKET_ENFILE	ENFILE
+#define SOCKET_EMFILE	EMFILE
+#elif defined(OS2)
+#define socket_errno	sock_errno()
+#define SOCKET_EINTR	SOCEINTR
+#define SOCKET_EAGAIN	SOCEINPROGRESS
+#define SOCKET_ETIMEDOUT SOCKET_EINTR
+#define SOCKET_EWOULDBLOCK SOCEWOULDBLOCK
+#define SOCKET_EADDRINUSE SOCEADDRINUSE
+#define SOCKET_ENFILE	SOCENFILE
+#define SOCKET_EMFILE	SOCEMFILE
+#define closesocket(A)	soclose(A)
+#else /* Unix */
+#define socket_errno	errno
+#define closesocket(A)	close(A)
+#define SOCKET_EINTR	EINTR
+#define SOCKET_EAGAIN	EAGAIN
+#define SOCKET_ETIMEDOUT SOCKET_EINTR
+#define SOCKET_EWOULDBLOCK EWOULDBLOCK
+#define SOCKET_EADDRINUSE EADDRINUSE
+#define SOCKET_ENFILE	ENFILE
+#define SOCKET_EMFILE	EMFILE
+#endif
+
+typedef uint8		int7;	/* Most effective integer 0 <= x <= 127 */
+typedef short		int15;	/* Most effective integer 0 <= x <= 32767 */
+typedef char		*my_string; /* String of characters */
+typedef unsigned long	size_s; /* Size of strings (In string-funcs) */
+typedef int		myf;	/* Type of MyFlags in my_funcs */
+#ifndef byte_defined
+typedef char		byte;	/* Smallest addressable unit */
+#endif
+typedef char		my_bool; /* Small bool */
+#if !defined(bool) && !defined(bool_defined) && (!defined(HAVE_BOOL) || !defined(__cplusplus))
+typedef char		bool;	/* Ordinary boolean values 0 1 */
+#endif
+	/* Macros for converting *constants* to the right type */
+#define INT8(v)		(int8) (v)
+#define INT16(v)	(int16) (v)
+#define INT32(v)	(int32) (v)
+#define MYF(v)		(myf) (v)
+
+#ifndef LL
+#ifdef HAVE_LONG_LONG
+#define LL(A) A ## LL
+#else
+#define LL(A) A ## L
+#endif
+#endif
+
+#ifndef ULL
+#ifdef HAVE_LONG_LONG
+#define ULL(A) A ## ULL
+#else
+#define ULL(A) A ## UL
+#endif
+#endif
+
+/*
+  Defines to make it possible to prioritize register assignments. No
+  longer that important with modern compilers.
+*/
+#ifndef USING_X
+#define reg1 register
+#define reg2 register
+#define reg3 register
+#define reg4 register
+#define reg5 register
+#define reg6 register
+#define reg7 register
+#define reg8 register
+#define reg9 register
+#define reg10 register
+#define reg11 register
+#define reg12 register
+#define reg13 register
+#define reg14 register
+#define reg15 register
+#define reg16 register
+#endif
+
+/*
+  Sometimes we want to make sure that the variable is not put into
+  a register in debugging mode so we can see its value in the core
+*/
+
+#ifndef DBUG_OFF
+#define dbug_volatile volatile
+#else
+#define dbug_volatile
+#endif
+
+/* Defines for time function */
+#define SCALE_SEC	100
+#define SCALE_USEC	10000
+#define MY_HOW_OFTEN_TO_ALARM	2	/* How often we want info on screen */
+#define MY_HOW_OFTEN_TO_WRITE	1000	/* How often we want info on screen */
+
+
+
+/*
+  Define-funktions for reading and storing in machine independent format
+  (low byte first)
+*/
+
+/* Optimized store functions for Intel x86 */
+#if defined(__i386__) && !defined(_WIN64)
+#define sint2korr(A)	(*((int16 *) (A)))
+#define sint3korr(A)	((int32) ((((uchar) (A)[2]) & 128) ? \
+				  (((uint32) 255L << 24) | \
+				   (((uint32) (uchar) (A)[2]) << 16) |\
+				   (((uint32) (uchar) (A)[1]) << 8) | \
+				   ((uint32) (uchar) (A)[0])) : \
+				  (((uint32) (uchar) (A)[2]) << 16) |\
+				  (((uint32) (uchar) (A)[1]) << 8) | \
+				  ((uint32) (uchar) (A)[0])))
+#define sint4korr(A)	(*((long *) (A)))
+#define uint2korr(A)	(*((uint16 *) (A)))
+#ifdef HAVE_purify
+#define uint3korr(A)	(uint32) (((uint32) ((uchar) (A)[0])) +\
+				  (((uint32) ((uchar) (A)[1])) << 8) +\
+				  (((uint32) ((uchar) (A)[2])) << 16))
+#else
+/*
+   ATTENTION !
+   
+    Please, note, uint3korr reads 4 bytes (not 3) !
+    It means, that you have to provide enough allocated space !
+*/
+#define uint3korr(A)	(long) (*((unsigned int *) (A)) & 0xFFFFFF)
+#endif
+#define uint4korr(A)	(*((uint32 *) (A)))
+#define uint5korr(A)	((ulonglong)(((uint32) ((uchar) (A)[0])) +\
+				    (((uint32) ((uchar) (A)[1])) << 8) +\
+				    (((uint32) ((uchar) (A)[2])) << 16) +\
+				    (((uint32) ((uchar) (A)[3])) << 24)) +\
+				    (((ulonglong) ((uchar) (A)[4])) << 32))
+#define uint8korr(A)	(*((ulonglong *) (A)))
+#define sint8korr(A)	(*((longlong *) (A)))
+#define int2store(T,A)	*((uint16*) (T))= (uint16) (A)
+#define int3store(T,A)  do { *(T)=  (uchar) ((A));\
+                            *(T+1)=(uchar) (((uint) (A) >> 8));\
+                            *(T+2)=(uchar) (((A) >> 16)); } while (0)
+#define int4store(T,A)	*((long *) (T))= (long) (A)
+#define int5store(T,A)  do { *(T)= (uchar)((A));\
+                             *((T)+1)=(uchar) (((A) >> 8));\
+                             *((T)+2)=(uchar) (((A) >> 16));\
+                             *((T)+3)=(uchar) (((A) >> 24)); \
+                             *((T)+4)=(uchar) (((A) >> 32)); } while(0)
+#define int8store(T,A)	*((ulonglong *) (T))= (ulonglong) (A)
+
+typedef union {
+  double v;
+  long m[2];
+} doubleget_union;
+#define doubleget(V,M)	\
+do { doubleget_union _tmp; \
+     _tmp.m[0] = *((long*)(M)); \
+     _tmp.m[1] = *(((long*) (M))+1); \
+     (V) = _tmp.v; } while(0)
+#define doublestore(T,V) do { *((long *) T) = ((doubleget_union *)&V)->m[0]; \
+			     *(((long *) T)+1) = ((doubleget_union *)&V)->m[1]; \
+                         } while (0)
+#define float4get(V,M)   do { *((float *) &(V)) = *((float*) (M)); } while(0)
+#define float8get(V,M)   doubleget((V),(M))
+#define float4store(V,M) memcpy((byte*) V,(byte*) (&M),sizeof(float))
+#define floatstore(T,V)  memcpy((byte*)(T), (byte*)(&V),sizeof(float))
+#define floatget(V,M)    memcpy((byte*) &V,(byte*) (M),sizeof(float))
+#define float8store(V,M) doublestore((V),(M))
+#endif /* __i386__ */
+
+#ifndef sint2korr
+/*
+  We're here if it's not a IA-32 architecture (Win32 and UNIX IA-32 defines
+  were done before)
+*/
+#define sint2korr(A)	(int16) (((int16) ((uchar) (A)[0])) +\
+				 ((int16) ((int16) (A)[1]) << 8))
+#define sint3korr(A)	((int32) ((((uchar) (A)[2]) & 128) ? \
+				  (((uint32) 255L << 24) | \
+				   (((uint32) (uchar) (A)[2]) << 16) |\
+				   (((uint32) (uchar) (A)[1]) << 8) | \
+				   ((uint32) (uchar) (A)[0])) : \
+				  (((uint32) (uchar) (A)[2]) << 16) |\
+				  (((uint32) (uchar) (A)[1]) << 8) | \
+				  ((uint32) (uchar) (A)[0])))
+#define sint4korr(A)	(int32) (((int32) ((uchar) (A)[0])) +\
+				(((int32) ((uchar) (A)[1]) << 8)) +\
+				(((int32) ((uchar) (A)[2]) << 16)) +\
+				(((int32) ((int16) (A)[3]) << 24)))
+#define sint8korr(A)	(longlong) uint8korr(A)
+#define uint2korr(A)	(uint16) (((uint16) ((uchar) (A)[0])) +\
+				  ((uint16) ((uchar) (A)[1]) << 8))
+#define uint3korr(A)	(uint32) (((uint32) ((uchar) (A)[0])) +\
+				  (((uint32) ((uchar) (A)[1])) << 8) +\
+				  (((uint32) ((uchar) (A)[2])) << 16))
+#define uint4korr(A)	(uint32) (((uint32) ((uchar) (A)[0])) +\
+				  (((uint32) ((uchar) (A)[1])) << 8) +\
+				  (((uint32) ((uchar) (A)[2])) << 16) +\
+				  (((uint32) ((uchar) (A)[3])) << 24))
+#define uint5korr(A)	((ulonglong)(((uint32) ((uchar) (A)[0])) +\
+				    (((uint32) ((uchar) (A)[1])) << 8) +\
+				    (((uint32) ((uchar) (A)[2])) << 16) +\
+				    (((uint32) ((uchar) (A)[3])) << 24)) +\
+				    (((ulonglong) ((uchar) (A)[4])) << 32))
+#define uint8korr(A)	((ulonglong)(((uint32) ((uchar) (A)[0])) +\
+				    (((uint32) ((uchar) (A)[1])) << 8) +\
+				    (((uint32) ((uchar) (A)[2])) << 16) +\
+				    (((uint32) ((uchar) (A)[3])) << 24)) +\
+			(((ulonglong) (((uint32) ((uchar) (A)[4])) +\
+				    (((uint32) ((uchar) (A)[5])) << 8) +\
+				    (((uint32) ((uchar) (A)[6])) << 16) +\
+				    (((uint32) ((uchar) (A)[7])) << 24))) <<\
+				    32))
+#define int2store(T,A)       do { uint def_temp= (uint) (A) ;\
+                                  *((uchar*) (T))=  (uchar)(def_temp); \
+                                   *((uchar*) (T)+1)=(uchar)((def_temp >> 8)); \
+                             } while(0)
+#define int3store(T,A)       do { /*lint -save -e734 */\
+                                  *((uchar*)(T))=(uchar) ((A));\
+                                  *((uchar*) (T)+1)=(uchar) (((A) >> 8));\
+                                  *((uchar*)(T)+2)=(uchar) (((A) >> 16)); \
+                                  /*lint -restore */} while(0)
+#define int4store(T,A)       do { *((char *)(T))=(char) ((A));\
+                                  *(((char *)(T))+1)=(char) (((A) >> 8));\
+                                  *(((char *)(T))+2)=(char) (((A) >> 16));\
+                                  *(((char *)(T))+3)=(char) (((A) >> 24)); } while(0)
+#define int5store(T,A)       do { *((char *)(T))=((A));\
+                                  *(((char *)(T))+1)=(((A) >> 8));\
+                                  *(((char *)(T))+2)=(((A) >> 16));\
+                                  *(((char *)(T))+3)=(((A) >> 24)); \
+                                  *(((char *)(T))+4)=(((A) >> 32)); } while(0)
+#define int8store(T,A)       do { uint def_temp= (uint) (A), def_temp2= (uint) ((A) >> 32); \
+                                  int4store((T),def_temp); \
+                                  int4store((T+4),def_temp2); } while(0)
+#ifdef WORDS_BIGENDIAN
+#define float4store(T,A) do { *(T)= ((byte *) &A)[3];\
+                              *((T)+1)=(char) ((byte *) &A)[2];\
+                              *((T)+2)=(char) ((byte *) &A)[1];\
+                              *((T)+3)=(char) ((byte *) &A)[0]; } while(0)
+
+#define float4get(V,M)   do { float def_temp;\
+                              ((byte*) &def_temp)[0]=(M)[3];\
+                              ((byte*) &def_temp)[1]=(M)[2];\
+                              ((byte*) &def_temp)[2]=(M)[1];\
+                              ((byte*) &def_temp)[3]=(M)[0];\
+                              (V)=def_temp; } while(0)
+#define float8store(T,V) do { *(T)= ((byte *) &V)[7];\
+                              *((T)+1)=(char) ((byte *) &V)[6];\
+                              *((T)+2)=(char) ((byte *) &V)[5];\
+                              *((T)+3)=(char) ((byte *) &V)[4];\
+                              *((T)+4)=(char) ((byte *) &V)[3];\
+                              *((T)+5)=(char) ((byte *) &V)[2];\
+                              *((T)+6)=(char) ((byte *) &V)[1];\
+                              *((T)+7)=(char) ((byte *) &V)[0]; } while(0)
+
+#define float8get(V,M)   do { double def_temp;\
+                              ((byte*) &def_temp)[0]=(M)[7];\
+                              ((byte*) &def_temp)[1]=(M)[6];\
+                              ((byte*) &def_temp)[2]=(M)[5];\
+                              ((byte*) &def_temp)[3]=(M)[4];\
+                              ((byte*) &def_temp)[4]=(M)[3];\
+                              ((byte*) &def_temp)[5]=(M)[2];\
+                              ((byte*) &def_temp)[6]=(M)[1];\
+                              ((byte*) &def_temp)[7]=(M)[0];\
+                              (V) = def_temp; } while(0)
+#else
+#define float4get(V,M)   memcpy_fixed((byte*) &V,(byte*) (M),sizeof(float))
+#define float4store(V,M) memcpy_fixed((byte*) V,(byte*) (&M),sizeof(float))
+
+#if defined(__FLOAT_WORD_ORDER) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN)
+#define doublestore(T,V) do { *(((char*)T)+0)=(char) ((byte *) &V)[4];\
+                              *(((char*)T)+1)=(char) ((byte *) &V)[5];\
+                              *(((char*)T)+2)=(char) ((byte *) &V)[6];\
+                              *(((char*)T)+3)=(char) ((byte *) &V)[7];\
+                              *(((char*)T)+4)=(char) ((byte *) &V)[0];\
+                              *(((char*)T)+5)=(char) ((byte *) &V)[1];\
+                              *(((char*)T)+6)=(char) ((byte *) &V)[2];\
+                              *(((char*)T)+7)=(char) ((byte *) &V)[3]; }\
+                         while(0)
+#define doubleget(V,M)   do { double def_temp;\
+                              ((byte*) &def_temp)[0]=(M)[4];\
+                              ((byte*) &def_temp)[1]=(M)[5];\
+                              ((byte*) &def_temp)[2]=(M)[6];\
+                              ((byte*) &def_temp)[3]=(M)[7];\
+                              ((byte*) &def_temp)[4]=(M)[0];\
+                              ((byte*) &def_temp)[5]=(M)[1];\
+                              ((byte*) &def_temp)[6]=(M)[2];\
+                              ((byte*) &def_temp)[7]=(M)[3];\
+                              (V) = def_temp; } while(0)
+#endif /* __FLOAT_WORD_ORDER */
+
+#define float8get(V,M)   doubleget((V),(M))
+#define float8store(V,M) doublestore((V),(M))
+#endif /* WORDS_BIGENDIAN */
+
+#endif /* sint2korr */
+
+/*
+  Macro for reading 32-bit integer from network byte order (big-endian)
+  from unaligned memory location.
+*/
+#define int4net(A)        (int32) (((uint32) ((uchar) (A)[3]))        |\
+				  (((uint32) ((uchar) (A)[2])) << 8)  |\
+				  (((uint32) ((uchar) (A)[1])) << 16) |\
+				  (((uint32) ((uchar) (A)[0])) << 24))
+/*
+  Define-funktions for reading and storing in machine format from/to
+  short/long to/from some place in memory V should be a (not
+  register) variable, M is a pointer to byte
+*/
+
+#ifdef WORDS_BIGENDIAN
+
+#define ushortget(V,M)  do { V = (uint16) (((uint16) ((uchar) (M)[1]))+\
+                                 ((uint16) ((uint16) (M)[0]) << 8)); } while(0)
+#define shortget(V,M)   do { V = (short) (((short) ((uchar) (M)[1]))+\
+                                 ((short) ((short) (M)[0]) << 8)); } while(0)
+#define longget(V,M)    do { int32 def_temp;\
+                             ((byte*) &def_temp)[0]=(M)[0];\
+                             ((byte*) &def_temp)[1]=(M)[1];\
+                             ((byte*) &def_temp)[2]=(M)[2];\
+                             ((byte*) &def_temp)[3]=(M)[3];\
+                             (V)=def_temp; } while(0)
+#define ulongget(V,M)   do { uint32 def_temp;\
+                            ((byte*) &def_temp)[0]=(M)[0];\
+                            ((byte*) &def_temp)[1]=(M)[1];\
+                            ((byte*) &def_temp)[2]=(M)[2];\
+                            ((byte*) &def_temp)[3]=(M)[3];\
+                            (V)=def_temp; } while(0)
+#define shortstore(T,A) do { uint def_temp=(uint) (A) ;\
+                             *(((char*)T)+1)=(char)(def_temp); \
+                             *(((char*)T)+0)=(char)(def_temp >> 8); } while(0)
+#define longstore(T,A)  do { *(((char*)T)+3)=((A));\
+                             *(((char*)T)+2)=(((A) >> 8));\
+                             *(((char*)T)+1)=(((A) >> 16));\
+                             *(((char*)T)+0)=(((A) >> 24)); } while(0)
+
+#define floatget(V,M)    memcpy_fixed((byte*) &V,(byte*) (M),sizeof(float))
+#define floatstore(T,V)  memcpy_fixed((byte*) (T),(byte*)(&V),sizeof(float))
+#define doubleget(V,M)	 memcpy_fixed((byte*) &V,(byte*) (M),sizeof(double))
+#define doublestore(T,V) memcpy_fixed((byte*) (T),(byte*) &V,sizeof(double))
+#define longlongget(V,M) memcpy_fixed((byte*) &V,(byte*) (M),sizeof(ulonglong))
+#define longlongstore(T,V) memcpy_fixed((byte*) (T),(byte*) &V,sizeof(ulonglong))
+
+#else
+
+#define ushortget(V,M)	do { V = uint2korr(M); } while(0)
+#define shortget(V,M)	do { V = sint2korr(M); } while(0)
+#define longget(V,M)	do { V = sint4korr(M); } while(0)
+#define ulongget(V,M)   do { V = uint4korr(M); } while(0)
+#define shortstore(T,V) int2store(T,V)
+#define longstore(T,V)	int4store(T,V)
+#ifndef floatstore
+#define floatstore(T,V)  memcpy_fixed((byte*) (T),(byte*) (&V),sizeof(float))
+#define floatget(V,M)    memcpy_fixed((byte*) &V, (byte*) (M), sizeof(float))
+#endif
+#ifndef doubleget
+#define doubleget(V,M)	 memcpy_fixed((byte*) &V,(byte*) (M),sizeof(double))
+#define doublestore(T,V) memcpy_fixed((byte*) (T),(byte*) &V,sizeof(double))
+#endif /* doubleget */
+#define longlongget(V,M) memcpy_fixed((byte*) &V,(byte*) (M),sizeof(ulonglong))
+#define longlongstore(T,V) memcpy_fixed((byte*) (T),(byte*) &V,sizeof(ulonglong))
+
+#endif /* WORDS_BIGENDIAN */
+
+/* sprintf does not always return the number of bytes :- */
+#ifdef SPRINTF_RETURNS_INT
+#define my_sprintf(buff,args) sprintf args
+#else
+#ifdef SPRINTF_RETURNS_PTR
+#define my_sprintf(buff,args) ((int)(sprintf args - buff))
+#else
+#define my_sprintf(buff,args) ((ulong) sprintf args, (ulong) strlen(buff))
+#endif
+#endif
+
+#ifndef THREAD
+#define thread_safe_increment(V,L) (V)++
+#define thread_safe_add(V,C,L)     (V)+=(C)
+#define thread_safe_sub(V,C,L)     (V)-=(C)
+#define statistic_increment(V,L)   (V)++
+#define statistic_add(V,C,L)       (V)+=(C)
+#endif
+
+#ifdef HAVE_CHARSET_utf8
+#define MYSQL_UNIVERSAL_CLIENT_CHARSET "utf8"
+#else
+#define MYSQL_UNIVERSAL_CLIENT_CHARSET MYSQL_DEFAULT_CHARSET_NAME
+#endif
+
+#if defined(EMBEDDED_LIBRARY) && !defined(HAVE_EMBEDDED_PRIVILEGE_CONTROL)
+#define NO_EMBEDDED_ACCESS_CHECKS
+#endif
+
+
+/* Length of decimal number represented by INT32. */
+
+#define MY_INT32_NUM_DECIMAL_DIGITS 11
+
+/* Length of decimal number represented by INT64. */
+
+#define MY_INT64_NUM_DECIMAL_DIGITS 21
+
+#endif /* my_global_h */
diff --git a/dep/include/mysql/my_list.h b/dep/include/mysql/my_list.h
new file mode 100644
index 00000000000..4a1737d4c53
--- /dev/null
+++ b/dep/include/mysql/my_list.h
@@ -0,0 +1,45 @@
+/* Copyright (C) 2000 MySQL AB
+
+   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; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#ifndef _list_h_
+#define _list_h_
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+typedef struct st_list {
+  struct st_list *prev,*next;
+  void *data;
+} LIST;
+
+typedef int (*list_walk_action)(void *,void *);
+
+extern LIST *list_add(LIST *root,LIST *element);
+extern LIST *list_delete(LIST *root,LIST *element);
+extern LIST *list_cons(void *data,LIST *root);
+extern LIST *list_reverse(LIST *root);
+extern void list_free(LIST *root,unsigned int free_data);
+extern unsigned int list_length(LIST *);
+extern int list_walk(LIST *,list_walk_action action,gptr argument);
+
+#define list_rest(a) ((a)->next)
+#define list_push(a,b) (a)=list_cons((b),(a))
+#define list_pop(A) {LIST *old=(A); (A)=list_delete(old,old) ; my_free((gptr) old,MYF(MY_FAE)); }
+
+#ifdef	__cplusplus
+}
+#endif
+#endif
diff --git a/dep/include/mysql/my_pthread.h b/dep/include/mysql/my_pthread.h
new file mode 100644
index 00000000000..13b7cf93d6f
--- /dev/null
+++ b/dep/include/mysql/my_pthread.h
@@ -0,0 +1,799 @@
+/* Copyright (C) 2000 MySQL AB
+
+   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; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+/* Defines to make different thread packages compatible */
+
+#ifndef _my_pthread_h
+#define _my_pthread_h
+
+#include 
+#ifndef ETIME
+#define ETIME ETIMEDOUT				/* For FreeBSD */
+#endif
+
+#ifdef  __cplusplus
+#define EXTERNC extern "C"
+extern "C" {
+#else
+#define EXTERNC
+#endif /* __cplusplus */ 
+
+#if defined(__WIN__) || defined(OS2)
+
+#ifdef OS2
+typedef ULONG     HANDLE;
+typedef ULONG     DWORD;
+typedef int sigset_t;
+#endif
+
+#ifdef OS2
+typedef HMTX             pthread_mutex_t;
+#else
+typedef CRITICAL_SECTION pthread_mutex_t;
+#endif
+typedef HANDLE		 pthread_t;
+typedef struct thread_attr {
+    DWORD dwStackSize ;
+    DWORD dwCreatingFlag ;
+    int priority ;
+} pthread_attr_t ;
+
+typedef struct { int dummy; } pthread_condattr_t;
+
+/* Implementation of posix conditions */
+
+typedef struct st_pthread_link {
+  DWORD thread_id;
+  struct st_pthread_link *next;
+} pthread_link;
+
+typedef struct {
+  uint32 waiting;
+  CRITICAL_SECTION lock_waiting;
+ 
+  enum {
+    SIGNAL= 0,
+    BROADCAST= 1,
+    MAX_EVENTS= 2
+  } EVENTS;
+
+  HANDLE events[MAX_EVENTS];
+  HANDLE broadcast_block_event;
+
+} pthread_cond_t;
+
+typedef int pthread_mutexattr_t;
+#define win_pthread_self my_thread_var->pthread_self
+#ifdef OS2
+#define pthread_handler_t EXTERNC void * _Optlink
+typedef void * (_Optlink *pthread_handler)(void *);
+#else
+#define pthread_handler_t EXTERNC void * __cdecl
+typedef void * (__cdecl *pthread_handler)(void *);
+#endif
+
+/*
+  Struct and macros to be used in combination with the
+  windows implementation of pthread_cond_timedwait
+*/
+
+/*
+   Declare a union to make sure FILETIME is properly aligned
+   so it can be used directly as a 64 bit value. The value
+   stored is in 100ns units.
+ */
+ union ft64 {
+  FILETIME ft;
+  __int64 i64;
+ };
+struct timespec {
+  union ft64 tv;
+  /* The max timeout value in millisecond for pthread_cond_timedwait */
+  long max_timeout_msec;
+};
+#define set_timespec(ABSTIME,SEC) { \
+  GetSystemTimeAsFileTime(&((ABSTIME).tv.ft)); \
+  (ABSTIME).tv.i64+= (__int64)(SEC)*10000000; \
+  (ABSTIME).max_timeout_msec= (long)((SEC)*1000); \
+}
+#define set_timespec_nsec(ABSTIME,NSEC) { \
+  GetSystemTimeAsFileTime(&((ABSTIME).tv.ft)); \
+  (ABSTIME).tv.i64+= (__int64)(NSEC)/100; \
+  (ABSTIME).max_timeout_msec= (long)((NSEC)/1000000); \
+}
+
+void win_pthread_init(void);
+int win_pthread_setspecific(void *A,void *B,uint length);
+int win_pthread_mutex_trylock(pthread_mutex_t *mutex);
+int pthread_create(pthread_t *,pthread_attr_t *,pthread_handler,void *);
+int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);
+int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
+int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
+			   struct timespec *abstime);
+int pthread_cond_signal(pthread_cond_t *cond);
+int pthread_cond_broadcast(pthread_cond_t *cond);
+int pthread_cond_destroy(pthread_cond_t *cond);
+int pthread_attr_init(pthread_attr_t *connect_att);
+int pthread_attr_setstacksize(pthread_attr_t *connect_att,DWORD stack);
+int pthread_attr_setprio(pthread_attr_t *connect_att,int priority);
+int pthread_attr_destroy(pthread_attr_t *connect_att);
+struct tm *localtime_r(const time_t *timep,struct tm *tmp);
+struct tm *gmtime_r(const time_t *timep,struct tm *tmp);
+
+
+void pthread_exit(void *a);	 /* was #define pthread_exit(A) ExitThread(A)*/
+
+#ifndef OS2
+#define ETIMEDOUT 145		    /* Win32 doesn't have this */
+#define getpid() GetCurrentThreadId()
+#endif
+#define pthread_self() win_pthread_self
+#define HAVE_LOCALTIME_R		1
+#define _REENTRANT			1
+#define HAVE_PTHREAD_ATTR_SETSTACKSIZE	1
+
+#ifdef USE_TLS					/* For LIBMYSQL.DLL */
+#undef SAFE_MUTEX				/* This will cause conflicts */
+#define pthread_key(T,V)  DWORD V
+#define pthread_key_create(A,B) ((*A=TlsAlloc())==0xFFFFFFFF)
+#define pthread_key_delete(A) TlsFree(A)
+#define pthread_getspecific(A) (TlsGetValue(A))
+#define my_pthread_getspecific(T,A) ((T) TlsGetValue(A))
+#define my_pthread_getspecific_ptr(T,V) ((T) TlsGetValue(V))
+#define my_pthread_setspecific_ptr(T,V) (!TlsSetValue((T),(V)))
+#define pthread_setspecific(A,B) (!TlsSetValue((A),(B)))
+#else
+#define pthread_key(T,V) __declspec(thread) T V
+#define pthread_key_create(A,B) pthread_dummy(0)
+#define pthread_key_delete(A) pthread_dummy(0)
+#define pthread_getspecific(A) (&(A))
+#define my_pthread_getspecific(T,A) (&(A))
+#define my_pthread_getspecific_ptr(T,V) (V)
+#define my_pthread_setspecific_ptr(T,V) ((T)=(V),0)
+#define pthread_setspecific(A,B) win_pthread_setspecific(&(A),(B),sizeof(A))
+#endif /* USE_TLS */
+
+#define pthread_equal(A,B) ((A) == (B))
+#ifdef OS2
+extern int pthread_mutex_init (pthread_mutex_t *, const pthread_mutexattr_t *);
+extern int pthread_mutex_lock (pthread_mutex_t *);
+extern int pthread_mutex_unlock (pthread_mutex_t *);
+extern int pthread_mutex_destroy (pthread_mutex_t *);
+#define my_pthread_setprio(A,B)  DosSetPriority(PRTYS_THREAD,PRTYC_NOCHANGE, B, A)
+#define pthread_kill(A,B) raise(B)
+#define pthread_exit(A) pthread_dummy()
+#else
+#define pthread_mutex_init(A,B)  (InitializeCriticalSection(A),0)
+#define pthread_mutex_lock(A)	 (EnterCriticalSection(A),0)
+#define pthread_mutex_trylock(A) win_pthread_mutex_trylock((A))
+#define pthread_mutex_unlock(A)  LeaveCriticalSection(A)
+#define pthread_mutex_destroy(A) DeleteCriticalSection(A)
+#define my_pthread_setprio(A,B)  SetThreadPriority(GetCurrentThread(), (B))
+#define pthread_kill(A,B) pthread_dummy(ESRCH)
+#endif /* OS2 */
+
+/* Dummy defines for easier code */
+#define pthread_attr_setdetachstate(A,B) pthread_dummy(0)
+#define my_pthread_attr_setprio(A,B) pthread_attr_setprio(A,B)
+#define pthread_attr_setscope(A,B)
+#define pthread_detach_this_thread()
+#define pthread_condattr_init(A)
+#define pthread_condattr_destroy(A)
+
+#define my_pthread_getprio(thread_id) pthread_dummy(0)
+
+#elif defined(HAVE_UNIXWARE7_THREADS)
+
+#include 
+#include 
+
+#ifndef _REENTRANT
+#define _REENTRANT
+#endif
+
+#define HAVE_NONPOSIX_SIGWAIT
+#define pthread_t thread_t
+#define pthread_cond_t cond_t
+#define pthread_mutex_t mutex_t
+#define pthread_key_t thread_key_t
+typedef int pthread_attr_t;			/* Needed by Unixware 7.0.0 */
+
+#define pthread_key_create(A,B) thr_keycreate((A),(B))
+#define pthread_key_delete(A) thr_keydelete(A)
+
+#define pthread_handler_t EXTERNC void *
+#define pthread_key(T,V) pthread_key_t V
+
+void *	my_pthread_getspecific_imp(pthread_key_t key);
+#define my_pthread_getspecific(A,B) ((A) my_pthread_getspecific_imp(B))
+#define my_pthread_getspecific_ptr(T,V) my_pthread_getspecific(T,V)
+
+#define pthread_setspecific(A,B) thr_setspecific(A,B)
+#define my_pthread_setspecific_ptr(T,V) pthread_setspecific(T,V)
+
+#define pthread_create(A,B,C,D) thr_create(NULL,65536L,(C),(D),THR_DETACHED,(A))
+#define pthread_cond_init(a,b) cond_init((a),USYNC_THREAD,NULL)
+#define pthread_cond_destroy(a) cond_destroy(a)
+#define pthread_cond_signal(a) cond_signal(a)
+#define pthread_cond_wait(a,b) cond_wait((a),(b))
+#define pthread_cond_timedwait(a,b,c) cond_timedwait((a),(b),(c))
+#define pthread_cond_broadcast(a) cond_broadcast(a)
+
+#define pthread_mutex_init(a,b) mutex_init((a),USYNC_THREAD,NULL)
+#define pthread_mutex_lock(a) mutex_lock(a)
+#define pthread_mutex_unlock(a) mutex_unlock(a)
+#define pthread_mutex_destroy(a) mutex_destroy(a)
+
+#define pthread_self() thr_self()
+#define pthread_exit(A) thr_exit(A)
+#define pthread_equal(A,B) (((A) == (B)) ? 1 : 0)
+#define pthread_kill(A,B) thr_kill((A),(B))
+#define HAVE_PTHREAD_KILL
+
+#define pthread_sigmask(A,B,C) thr_sigsetmask((A),(B),(C))
+
+extern int my_sigwait(const sigset_t *set,int *sig);
+
+#define pthread_detach_this_thread() pthread_dummy(0)
+
+#define pthread_attr_init(A) pthread_dummy(0)
+#define pthread_attr_destroy(A) pthread_dummy(0)
+#define pthread_attr_setscope(A,B) pthread_dummy(0)
+#define pthread_attr_setdetachstate(A,B) pthread_dummy(0)
+#define my_pthread_setprio(A,B) pthread_dummy (0)
+#define my_pthread_getprio(A) pthread_dummy (0)
+#define my_pthread_attr_setprio(A,B) pthread_dummy(0)
+
+#else /* Normal threads */
+
+#ifdef HAVE_rts_threads
+#define sigwait org_sigwait
+#include 
+#undef sigwait
+#endif
+#include 
+#ifndef _REENTRANT
+#define _REENTRANT
+#endif
+#ifdef HAVE_THR_SETCONCURRENCY
+#include 			/* Probably solaris */
+#endif
+#ifdef HAVE_SCHED_H
+#include 
+#endif
+#ifdef HAVE_SYNCH_H
+#include 
+#endif
+#if defined(__EMX__) && (!defined(EMX_PTHREAD_REV) || (EMX_PTHREAD_REV < 2))
+#error Requires at least rev 2 of EMX pthreads library.
+#endif
+
+#ifdef __NETWARE__
+void my_pthread_exit(void *status);
+#define pthread_exit(A) my_pthread_exit(A)
+#endif
+
+extern int my_pthread_getprio(pthread_t thread_id);
+
+#define pthread_key(T,V) pthread_key_t V
+#define my_pthread_getspecific_ptr(T,V) my_pthread_getspecific(T,(V))
+#define my_pthread_setspecific_ptr(T,V) pthread_setspecific(T,(void*) (V))
+#define pthread_detach_this_thread()
+#define pthread_handler_t EXTERNC void *
+typedef void *(* pthread_handler)(void *);
+
+/* Test first for RTS or FSU threads */
+
+#if defined(PTHREAD_SCOPE_GLOBAL) && !defined(PTHREAD_SCOPE_SYSTEM)
+#define HAVE_rts_threads
+extern int my_pthread_create_detached;
+#define pthread_sigmask(A,B,C) sigprocmask((A),(B),(C))
+#define PTHREAD_CREATE_DETACHED &my_pthread_create_detached
+#define PTHREAD_SCOPE_SYSTEM  PTHREAD_SCOPE_GLOBAL
+#define PTHREAD_SCOPE_PROCESS PTHREAD_SCOPE_LOCAL
+#define USE_ALARM_THREAD
+#elif defined(HAVE_mit_thread)
+#define USE_ALARM_THREAD
+#undef	HAVE_LOCALTIME_R
+#define HAVE_LOCALTIME_R
+#undef	HAVE_GMTIME_R
+#define HAVE_GMTIME_R
+#undef	HAVE_PTHREAD_ATTR_SETSCOPE
+#define HAVE_PTHREAD_ATTR_SETSCOPE
+#undef HAVE_GETHOSTBYNAME_R_GLIBC2_STYLE	/* If we are running linux */
+#undef HAVE_RWLOCK_T
+#undef HAVE_RWLOCK_INIT
+#undef HAVE_PTHREAD_RWLOCK_RDLOCK
+#undef HAVE_SNPRINTF
+
+#define my_pthread_attr_setprio(A,B)
+#endif /* defined(PTHREAD_SCOPE_GLOBAL) && !defined(PTHREAD_SCOPE_SYSTEM) */
+
+#if defined(_BSDI_VERSION) && _BSDI_VERSION < 199910
+int sigwait(sigset_t *set, int *sig);
+#endif
+
+#ifndef HAVE_NONPOSIX_SIGWAIT
+#define my_sigwait(A,B) sigwait((A),(B))
+#else
+int my_sigwait(const sigset_t *set,int *sig);
+#endif
+
+#ifdef HAVE_NONPOSIX_PTHREAD_MUTEX_INIT
+#ifndef SAFE_MUTEX
+#define pthread_mutex_init(a,b) my_pthread_mutex_init((a),(b))
+extern int my_pthread_mutex_init(pthread_mutex_t *mp,
+				 const pthread_mutexattr_t *attr);
+#endif /* SAFE_MUTEX */
+#define pthread_cond_init(a,b) my_pthread_cond_init((a),(b))
+extern int my_pthread_cond_init(pthread_cond_t *mp,
+				const pthread_condattr_t *attr);
+#endif /* HAVE_NONPOSIX_PTHREAD_MUTEX_INIT */
+
+#if defined(HAVE_SIGTHREADMASK) && !defined(HAVE_PTHREAD_SIGMASK)
+#define pthread_sigmask(A,B,C) sigthreadmask((A),(B),(C))
+#endif
+
+#if !defined(HAVE_SIGWAIT) && !defined(HAVE_mit_thread) && !defined(HAVE_rts_threads) && !defined(sigwait) && !defined(alpha_linux_port) && !defined(HAVE_NONPOSIX_SIGWAIT) && !defined(HAVE_DEC_3_2_THREADS) && !defined(_AIX)
+int sigwait(sigset_t *setp, int *sigp);		/* Use our implemention */
+#endif
+
+
+/*
+  We define my_sigset() and use that instead of the system sigset() so that
+  we can favor an implementation based on sigaction(). On some systems, such
+  as Mac OS X, sigset() results in flags such as SA_RESTART being set, and
+  we want to make sure that no such flags are set.
+*/
+#if defined(HAVE_SIGACTION) && !defined(my_sigset)
+#define my_sigset(A,B) do { struct sigaction l_s; sigset_t l_set; int l_rc; \
+                            DBUG_ASSERT((A) != 0);                          \
+                            sigemptyset(&l_set);                            \
+                            l_s.sa_handler = (B);                           \
+                            l_s.sa_mask   = l_set;                          \
+                            l_s.sa_flags   = 0;                             \
+                            l_rc= sigaction((A), &l_s, (struct sigaction *) NULL);\
+                            DBUG_ASSERT(l_rc == 0);                         \
+                          } while (0)
+#elif defined(HAVE_SIGSET) && !defined(my_sigset)
+#define my_sigset(A,B) sigset((A),(B))
+#elif !defined(my_sigset)
+#define my_sigset(A,B) signal((A),(B))
+#endif
+
+#ifndef my_pthread_setprio
+#if defined(HAVE_PTHREAD_SETPRIO_NP)		/* FSU threads */
+#define my_pthread_setprio(A,B) pthread_setprio_np((A),(B))
+#elif defined(HAVE_PTHREAD_SETPRIO)
+#define my_pthread_setprio(A,B) pthread_setprio((A),(B))
+#else
+extern void my_pthread_setprio(pthread_t thread_id,int prior);
+#endif
+#endif
+
+#ifndef my_pthread_attr_setprio
+#ifdef HAVE_PTHREAD_ATTR_SETPRIO
+#define my_pthread_attr_setprio(A,B) pthread_attr_setprio((A),(B))
+#else
+extern void my_pthread_attr_setprio(pthread_attr_t *attr, int priority);
+#endif
+#endif
+
+#if !defined(HAVE_PTHREAD_ATTR_SETSCOPE) || defined(HAVE_DEC_3_2_THREADS)
+#define pthread_attr_setscope(A,B)
+#undef	HAVE_GETHOSTBYADDR_R			/* No definition */
+#endif
+
+#if defined(HAVE_BROKEN_PTHREAD_COND_TIMEDWAIT) && !defined(SAFE_MUTEX)
+extern int my_pthread_cond_timedwait(pthread_cond_t *cond,
+				     pthread_mutex_t *mutex,
+				     struct timespec *abstime);
+#define pthread_cond_timedwait(A,B,C) my_pthread_cond_timedwait((A),(B),(C))
+#endif
+
+#if defined(OS2)
+#define my_pthread_getspecific(T,A) ((T) &(A))
+#define pthread_setspecific(A,B) win_pthread_setspecific(&(A),(B),sizeof(A))
+#elif !defined( HAVE_NONPOSIX_PTHREAD_GETSPECIFIC)
+#define my_pthread_getspecific(A,B) ((A) pthread_getspecific(B))
+#else
+#define my_pthread_getspecific(A,B) ((A) my_pthread_getspecific_imp(B))
+void *my_pthread_getspecific_imp(pthread_key_t key);
+#endif /* OS2 */
+
+#ifndef HAVE_LOCALTIME_R
+struct tm *localtime_r(const time_t *clock, struct tm *res);
+#endif
+
+#ifndef HAVE_GMTIME_R
+struct tm *gmtime_r(const time_t *clock, struct tm *res);
+#endif
+
+#ifdef HAVE_PTHREAD_CONDATTR_CREATE
+/* DCE threads on HPUX 10.20 */
+#define pthread_condattr_init pthread_condattr_create
+#define pthread_condattr_destroy pthread_condattr_delete
+#endif
+
+/* FSU THREADS */
+#if !defined(HAVE_PTHREAD_KEY_DELETE) && !defined(pthread_key_delete)
+#define pthread_key_delete(A) pthread_dummy(0)
+#endif
+
+#ifdef HAVE_CTHREADS_WRAPPER			/* For MacOSX */
+#define pthread_cond_destroy(A) pthread_dummy(0)
+#define pthread_mutex_destroy(A) pthread_dummy(0)
+#define pthread_attr_delete(A) pthread_dummy(0)
+#define pthread_condattr_delete(A) pthread_dummy(0)
+#define pthread_attr_setstacksize(A,B) pthread_dummy(0)
+#define pthread_equal(A,B) ((A) == (B))
+#define pthread_cond_timedwait(a,b,c) pthread_cond_wait((a),(b))
+#define pthread_attr_init(A) pthread_attr_create(A)
+#define pthread_attr_destroy(A) pthread_attr_delete(A)
+#define pthread_attr_setdetachstate(A,B) pthread_dummy(0)
+#define pthread_create(A,B,C,D) pthread_create((A),*(B),(C),(D))
+#define pthread_sigmask(A,B,C) sigprocmask((A),(B),(C))
+#define pthread_kill(A,B) pthread_dummy(ESRCH)
+#undef	pthread_detach_this_thread
+#define pthread_detach_this_thread() { pthread_t tmp=pthread_self() ; pthread_detach(&tmp); }
+#endif
+
+#ifdef HAVE_DARWIN5_THREADS
+#define pthread_sigmask(A,B,C) sigprocmask((A),(B),(C))
+#define pthread_kill(A,B) pthread_dummy(ESRCH)
+#define pthread_condattr_init(A) pthread_dummy(0)
+#define pthread_condattr_destroy(A) pthread_dummy(0)
+#undef	pthread_detach_this_thread
+#define pthread_detach_this_thread() { pthread_t tmp=pthread_self() ; pthread_detach(tmp); }
+#endif
+
+#if ((defined(HAVE_PTHREAD_ATTR_CREATE) && !defined(HAVE_SIGWAIT)) || defined(HAVE_DEC_3_2_THREADS)) && !defined(HAVE_CTHREADS_WRAPPER)
+/* This is set on AIX_3_2 and Siemens unix (and DEC OSF/1 3.2 too) */
+#define pthread_key_create(A,B) \
+		pthread_keycreate(A,(B) ?\
+				  (pthread_destructor_t) (B) :\
+				  (pthread_destructor_t) pthread_dummy)
+#define pthread_attr_init(A) pthread_attr_create(A)
+#define pthread_attr_destroy(A) pthread_attr_delete(A)
+#define pthread_attr_setdetachstate(A,B) pthread_dummy(0)
+#define pthread_create(A,B,C,D) pthread_create((A),*(B),(C),(D))
+#ifndef pthread_sigmask
+#define pthread_sigmask(A,B,C) sigprocmask((A),(B),(C))
+#endif
+#define pthread_kill(A,B) pthread_dummy(ESRCH)
+#undef	pthread_detach_this_thread
+#define pthread_detach_this_thread() { pthread_t tmp=pthread_self() ; pthread_detach(&tmp); }
+#elif !defined(__NETWARE__) /* HAVE_PTHREAD_ATTR_CREATE && !HAVE_SIGWAIT */
+#define HAVE_PTHREAD_KILL
+#endif
+
+#endif /* defined(__WIN__) */
+
+#if defined(HPUX10) && !defined(DONT_REMAP_PTHREAD_FUNCTIONS)
+#undef pthread_cond_timedwait
+#define pthread_cond_timedwait(a,b,c) my_pthread_cond_timedwait((a),(b),(c))
+int my_pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
+			      struct timespec *abstime);
+#endif
+
+#if defined(HPUX10)
+#define pthread_attr_getstacksize(A,B) my_pthread_attr_getstacksize(A,B)
+void my_pthread_attr_getstacksize(pthread_attr_t *attrib, size_t *size);
+#endif
+
+#if defined(HAVE_POSIX1003_4a_MUTEX) && !defined(DONT_REMAP_PTHREAD_FUNCTIONS)
+#undef pthread_mutex_trylock
+#define pthread_mutex_trylock(a) my_pthread_mutex_trylock((a))
+int my_pthread_mutex_trylock(pthread_mutex_t *mutex);
+#endif
+
+/*
+  The defines set_timespec and set_timespec_nsec should be used
+  for calculating an absolute time at which
+  pthread_cond_timedwait should timeout
+*/
+#ifdef HAVE_TIMESPEC_TS_SEC
+#ifndef set_timespec
+#define set_timespec(ABSTIME,SEC) \
+{ \
+  (ABSTIME).ts_sec=time(0) + (time_t) (SEC); \
+  (ABSTIME).ts_nsec=0; \
+}
+#endif /* !set_timespec */
+#ifndef set_timespec_nsec
+#define set_timespec_nsec(ABSTIME,NSEC) \
+{ \
+  ulonglong now= my_getsystime() + (NSEC/100); \
+  (ABSTIME).ts_sec=  (now / ULL(10000000)); \
+  (ABSTIME).ts_nsec= (now % ULL(10000000) * 100 + ((NSEC) % 100)); \
+}
+#endif /* !set_timespec_nsec */
+#else
+#ifndef set_timespec
+#define set_timespec(ABSTIME,SEC) \
+{\
+  struct timeval tv;\
+  gettimeofday(&tv,0);\
+  (ABSTIME).tv_sec=tv.tv_sec+(time_t) (SEC);\
+  (ABSTIME).tv_nsec=tv.tv_usec*1000;\
+}
+#endif /* !set_timespec */
+#ifndef set_timespec_nsec
+#define set_timespec_nsec(ABSTIME,NSEC) \
+{\
+  ulonglong now= my_getsystime() + (NSEC/100); \
+  (ABSTIME).tv_sec=  (time_t) (now / ULL(10000000));                  \
+  (ABSTIME).tv_nsec= (long) (now % ULL(10000000) * 100 + ((NSEC) % 100)); \
+}
+#endif /* !set_timespec_nsec */
+#endif /* HAVE_TIMESPEC_TS_SEC */
+
+	/* safe_mutex adds checking to mutex for easier debugging */
+
+#if defined(__NETWARE__) && !defined(SAFE_MUTEX_DETECT_DESTROY)
+#define SAFE_MUTEX_DETECT_DESTROY
+#endif
+
+typedef struct st_safe_mutex_t
+{
+  pthread_mutex_t global,mutex;
+  const char *file;
+  uint line,count;
+  pthread_t thread;
+#ifdef SAFE_MUTEX_DETECT_DESTROY
+  struct st_safe_mutex_info_t *info;	/* to track destroying of mutexes */
+#endif
+} safe_mutex_t;
+
+#ifdef SAFE_MUTEX_DETECT_DESTROY
+/*
+  Used to track the destroying of mutexes. This needs to be a seperate
+  structure because the safe_mutex_t structure could be freed before
+  the mutexes are destroyed.
+*/
+
+typedef struct st_safe_mutex_info_t
+{
+  struct st_safe_mutex_info_t *next;
+  struct st_safe_mutex_info_t *prev;
+  const char *init_file;
+  uint32 init_line;
+} safe_mutex_info_t;
+#endif /* SAFE_MUTEX_DETECT_DESTROY */
+
+int safe_mutex_init(safe_mutex_t *mp, const pthread_mutexattr_t *attr,
+                    const char *file, uint line);
+int safe_mutex_lock(safe_mutex_t *mp, my_bool try_lock, const char *file, uint line);
+int safe_mutex_unlock(safe_mutex_t *mp,const char *file, uint line);
+int safe_mutex_destroy(safe_mutex_t *mp,const char *file, uint line);
+int safe_cond_wait(pthread_cond_t *cond, safe_mutex_t *mp,const char *file,
+		   uint line);
+int safe_cond_timedwait(pthread_cond_t *cond, safe_mutex_t *mp,
+			struct timespec *abstime, const char *file, uint line);
+void safe_mutex_global_init(void);
+void safe_mutex_end(FILE *file);
+
+	/* Wrappers if safe mutex is actually used */
+#ifdef SAFE_MUTEX
+#undef pthread_mutex_init
+#undef pthread_mutex_lock
+#undef pthread_mutex_unlock
+#undef pthread_mutex_destroy
+#undef pthread_mutex_wait
+#undef pthread_mutex_timedwait
+#undef pthread_mutex_t
+#undef pthread_cond_wait
+#undef pthread_cond_timedwait
+#undef pthread_mutex_trylock
+#define pthread_mutex_init(A,B) safe_mutex_init((A),(B),__FILE__,__LINE__)
+#define pthread_mutex_lock(A) safe_mutex_lock((A), FALSE, __FILE__, __LINE__)
+#define pthread_mutex_unlock(A) safe_mutex_unlock((A),__FILE__,__LINE__)
+#define pthread_mutex_destroy(A) safe_mutex_destroy((A),__FILE__,__LINE__)
+#define pthread_cond_wait(A,B) safe_cond_wait((A),(B),__FILE__,__LINE__)
+#define pthread_cond_timedwait(A,B,C) safe_cond_timedwait((A),(B),(C),__FILE__,__LINE__)
+#define pthread_mutex_trylock(A) safe_mutex_lock((A), TRUE, __FILE__, __LINE__)
+#define pthread_mutex_t safe_mutex_t
+#define safe_mutex_assert_owner(mp) \
+          DBUG_ASSERT((mp)->count > 0 && \
+                      pthread_equal(pthread_self(), (mp)->thread))
+#define safe_mutex_assert_not_owner(mp) \
+          DBUG_ASSERT(! (mp)->count || \
+                      ! pthread_equal(pthread_self(), (mp)->thread))
+#else
+#define safe_mutex_assert_owner(mp)
+#define safe_mutex_assert_not_owner(mp)
+#endif /* SAFE_MUTEX */
+
+	/* READ-WRITE thread locking */
+
+#ifdef HAVE_BROKEN_RWLOCK			/* For OpenUnix */
+#undef HAVE_PTHREAD_RWLOCK_RDLOCK
+#undef HAVE_RWLOCK_INIT
+#undef HAVE_RWLOCK_T
+#endif
+
+#if defined(USE_MUTEX_INSTEAD_OF_RW_LOCKS)
+/* use these defs for simple mutex locking */
+#define rw_lock_t pthread_mutex_t
+#define my_rwlock_init(A,B) pthread_mutex_init((A),(B))
+#define rw_rdlock(A) pthread_mutex_lock((A))
+#define rw_wrlock(A) pthread_mutex_lock((A))
+#define rw_tryrdlock(A) pthread_mutex_trylock((A))
+#define rw_trywrlock(A) pthread_mutex_trylock((A))
+#define rw_unlock(A) pthread_mutex_unlock((A))
+#define rwlock_destroy(A) pthread_mutex_destroy((A))
+#elif defined(HAVE_PTHREAD_RWLOCK_RDLOCK)
+#define rw_lock_t pthread_rwlock_t
+#define my_rwlock_init(A,B) pthread_rwlock_init((A),(B))
+#define rw_rdlock(A) pthread_rwlock_rdlock(A)
+#define rw_wrlock(A) pthread_rwlock_wrlock(A)
+#define rw_tryrdlock(A) pthread_rwlock_tryrdlock((A))
+#define rw_trywrlock(A) pthread_rwlock_trywrlock((A))
+#define rw_unlock(A) pthread_rwlock_unlock(A)
+#define rwlock_destroy(A) pthread_rwlock_destroy(A)
+#elif defined(HAVE_RWLOCK_INIT)
+#ifdef HAVE_RWLOCK_T				/* For example Solaris 2.6-> */
+#define rw_lock_t rwlock_t
+#endif
+#define my_rwlock_init(A,B) rwlock_init((A),USYNC_THREAD,0)
+#else
+/* Use our own version of read/write locks */
+typedef struct _my_rw_lock_t {
+	pthread_mutex_t lock;		/* lock for structure		*/
+	pthread_cond_t	readers;	/* waiting readers		*/
+	pthread_cond_t	writers;	/* waiting writers		*/
+	int		state;		/* -1:writer,0:free,>0:readers	*/
+	int		waiters;	/* number of waiting writers	*/
+} my_rw_lock_t;
+
+#define rw_lock_t my_rw_lock_t
+#define rw_rdlock(A) my_rw_rdlock((A))
+#define rw_wrlock(A) my_rw_wrlock((A))
+#define rw_tryrdlock(A) my_rw_tryrdlock((A))
+#define rw_trywrlock(A) my_rw_trywrlock((A))
+#define rw_unlock(A) my_rw_unlock((A))
+#define rwlock_destroy(A) my_rwlock_destroy((A))
+
+extern int my_rwlock_init(my_rw_lock_t *, void *);
+extern int my_rwlock_destroy(my_rw_lock_t *);
+extern int my_rw_rdlock(my_rw_lock_t *);
+extern int my_rw_wrlock(my_rw_lock_t *);
+extern int my_rw_unlock(my_rw_lock_t *);
+extern int my_rw_tryrdlock(my_rw_lock_t *);
+extern int my_rw_trywrlock(my_rw_lock_t *);
+#endif /* USE_MUTEX_INSTEAD_OF_RW_LOCKS */
+
+#define GETHOSTBYADDR_BUFF_SIZE 2048
+
+#ifndef HAVE_THR_SETCONCURRENCY
+#define thr_setconcurrency(A) pthread_dummy(0)
+#endif
+#if !defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE) && ! defined(pthread_attr_setstacksize)
+#define pthread_attr_setstacksize(A,B) pthread_dummy(0)
+#endif
+
+/* Define mutex types, see my_thr_init.c */
+#define MY_MUTEX_INIT_SLOW   NULL
+#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
+extern pthread_mutexattr_t my_fast_mutexattr;
+#define MY_MUTEX_INIT_FAST &my_fast_mutexattr
+#else
+#define MY_MUTEX_INIT_FAST   NULL
+#endif
+#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
+extern pthread_mutexattr_t my_errorcheck_mutexattr;
+#define MY_MUTEX_INIT_ERRCHK &my_errorcheck_mutexattr
+#else
+#define MY_MUTEX_INIT_ERRCHK   NULL
+#endif
+
+#ifndef ESRCH
+/* Define it to something */
+#define ESRCH 1
+#endif
+
+extern my_bool my_thread_global_init(void);
+extern void my_thread_global_end(void);
+extern my_bool my_thread_init(void);
+extern void my_thread_end(void);
+extern const char *my_thread_name(void);
+extern long my_thread_id(void);
+extern int pthread_no_free(void *);
+extern int pthread_dummy(int);
+
+/* All thread specific variables are in the following struct */
+
+#define THREAD_NAME_SIZE 10
+#ifndef DEFAULT_THREAD_STACK
+#if SIZEOF_CHARP > 4
+/*
+  MySQL can survive with 32K, but some glibc libraries require > 128K stack
+  To resolve hostnames. Also recursive stored procedures needs stack.
+*/
+#define DEFAULT_THREAD_STACK	(256*1024L)
+#else
+#define DEFAULT_THREAD_STACK	(192*1024)
+#endif
+#endif
+
+struct st_my_thread_var
+{
+  int thr_errno;
+  pthread_cond_t suspend;
+  pthread_mutex_t mutex;
+  pthread_mutex_t * volatile current_mutex;
+  pthread_cond_t * volatile current_cond;
+  pthread_t pthread_self;
+  long id;
+  int cmp_length;
+  int volatile abort;
+  my_bool init;
+  struct st_my_thread_var *next,**prev;
+  void *opt_info;
+#ifndef DBUG_OFF
+  gptr dbug;
+  char name[THREAD_NAME_SIZE+1];
+#endif
+};
+
+extern struct st_my_thread_var *_my_thread_var(void) __attribute__ ((const));
+extern uint my_thread_end_wait_time;
+#define my_thread_var (_my_thread_var())
+#define my_errno my_thread_var->thr_errno
+/*
+  Keep track of shutdown,signal, and main threads so that my_end() will not
+  report errors with them
+*/
+
+/* Which kind of thread library is in use */
+
+#define THD_LIB_OTHER 1
+#define THD_LIB_NPTL  2
+#define THD_LIB_LT    4
+
+extern uint thd_lib_detected;
+
+	/* statistics_xxx functions are for not essential statistic */
+
+#ifndef thread_safe_increment
+#ifdef HAVE_ATOMIC_ADD
+#define thread_safe_increment(V,L) atomic_inc((atomic_t*) &V)
+#define thread_safe_decrement(V,L) atomic_dec((atomic_t*) &V)
+#define thread_safe_add(V,C,L)     atomic_add((C),(atomic_t*) &V)
+#define thread_safe_sub(V,C,L)     atomic_sub((C),(atomic_t*) &V)
+#else
+#define thread_safe_increment(V,L) \
+        (pthread_mutex_lock((L)), (V)++, pthread_mutex_unlock((L)))
+#define thread_safe_decrement(V,L) \
+        (pthread_mutex_lock((L)), (V)--, pthread_mutex_unlock((L)))
+#define thread_safe_add(V,C,L) (pthread_mutex_lock((L)), (V)+=(C), pthread_mutex_unlock((L)))
+#define thread_safe_sub(V,C,L) \
+        (pthread_mutex_lock((L)), (V)-=(C), pthread_mutex_unlock((L)))
+#endif /* HAVE_ATOMIC_ADD */
+#ifdef SAFE_STATISTICS
+#define statistic_increment(V,L)   thread_safe_increment((V),(L))
+#define statistic_decrement(V,L)   thread_safe_decrement((V),(L))
+#define statistic_add(V,C,L)       thread_safe_add((V),(C),(L))
+#else
+#define statistic_decrement(V,L) (V)--
+#define statistic_increment(V,L) (V)++
+#define statistic_add(V,C,L)     (V)+=(C)
+#endif /* SAFE_STATISTICS */
+#endif /* thread_safe_increment */
+
+#ifdef  __cplusplus
+}
+#endif
+#endif /* _my_ptread_h */
diff --git a/dep/include/mysql/my_sys.h b/dep/include/mysql/my_sys.h
new file mode 100644
index 00000000000..d656326e968
--- /dev/null
+++ b/dep/include/mysql/my_sys.h
@@ -0,0 +1,936 @@
+/* Copyright (C) 2000-2003 MySQL AB
+
+   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; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#ifndef _my_sys_h
+#define _my_sys_h
+C_MODE_START
+
+#ifdef HAVE_AIOWAIT
+#include 			/* Used by record-cache */
+typedef struct my_aio_result {
+  aio_result_t result;
+  int	       pending;
+} my_aio_result;
+#endif
+
+#ifndef THREAD
+extern int NEAR my_errno;		/* Last error in mysys */
+#else
+#include 
+#endif
+
+#include                     /* for CHARSET_INFO */
+#include 
+#include 
+
+#define MYSYS_PROGRAM_USES_CURSES()  { error_handler_hook = my_message_curses;	mysys_uses_curses=1; }
+#define MYSYS_PROGRAM_DONT_USE_CURSES()  { error_handler_hook = my_message_no_curses; mysys_uses_curses=0;}
+#define MY_INIT(name);		{ my_progname= name; my_init(); }
+
+#define ERRMSGSIZE	(SC_MAXWIDTH)	/* Max length of a error message */
+#define NRERRBUFFS	(2)	/* Buffers for parameters */
+#define MY_FILE_ERROR	((uint) ~0)
+
+	/* General bitmaps for my_func's */
+#define MY_FFNF		1	/* Fatal if file not found */
+#define MY_FNABP	2	/* Fatal if not all bytes read/writen */
+#define MY_NABP		4	/* Error if not all bytes read/writen */
+#define MY_FAE		8	/* Fatal if any error */
+#define MY_WME		16	/* Write message on error */
+#define MY_WAIT_IF_FULL 32	/* Wait and try again if disk full error */
+#define MY_IGNORE_BADFD 32      /* my_sync: ignore 'bad descriptor' errors */
+#define MY_RAID         64      /* Support for RAID */
+#define MY_FULL_IO     512      /* For my_read - loop intil I/O is complete */
+#define MY_DONT_CHECK_FILESIZE 128 /* Option to init_io_cache() */
+#define MY_LINK_WARNING 32	/* my_redel() gives warning if links */
+#define MY_COPYTIME	64	/* my_redel() copys time */
+#define MY_DELETE_OLD	256	/* my_create_with_symlink() */
+#define MY_RESOLVE_LINK 128	/* my_realpath(); Only resolve links */
+#define MY_HOLD_ORIGINAL_MODES 128  /* my_copy() holds to file modes */
+#define MY_REDEL_MAKE_BACKUP 256
+#define MY_SEEK_NOT_DONE 32	/* my_lock may have to do a seek */
+#define MY_DONT_WAIT	64	/* my_lock() don't wait if can't lock */
+#define MY_ZEROFILL	32	/* my_malloc(), fill array with zero */
+#define MY_ALLOW_ZERO_PTR 64	/* my_realloc() ; zero ptr -> malloc */
+#define MY_FREE_ON_ERROR 128	/* my_realloc() ; Free old ptr on error */
+#define MY_HOLD_ON_ERROR 256	/* my_realloc() ; Return old ptr on error */
+#define MY_DONT_OVERWRITE_FILE 1024	/* my_copy: Don't overwrite file */
+#define MY_THREADSAFE 2048      /* my_seek(): lock fd mutex */
+
+#define MY_CHECK_ERROR	1	/* Params to my_end; Check open-close */
+#define MY_GIVE_INFO	2	/* Give time info about process*/
+#define MY_DONT_FREE_DBUG 4     /* Do not call DBUG_END() in my_end() */
+
+#define ME_HIGHBYTE	8	/* Shift for colours */
+#define ME_NOCUR	1	/* Don't use curses message */
+#define ME_OLDWIN	2	/* Use old window */
+#define ME_BELL		4	/* Ring bell then printing message */
+#define ME_HOLDTANG	8	/* Don't delete last keys */
+#define ME_WAITTOT	16	/* Wait for errtime secs of for a action */
+#define ME_WAITTANG	32	/* Wait for a user action  */
+#define ME_NOREFRESH	64	/* Dont refresh screen */
+#define ME_NOINPUT	128	/* Dont use the input libary */
+#define ME_COLOUR1	((1 << ME_HIGHBYTE))	/* Possibly error-colours */
+#define ME_COLOUR2	((2 << ME_HIGHBYTE))
+#define ME_COLOUR3	((3 << ME_HIGHBYTE))
+
+	/* Bits in last argument to fn_format */
+#define MY_REPLACE_DIR		1	/* replace dir in name with 'dir' */
+#define MY_REPLACE_EXT		2	/* replace extension with 'ext' */
+#define MY_UNPACK_FILENAME	4	/* Unpack name (~ -> home) */
+#define MY_PACK_FILENAME	8	/* Pack name (home -> ~) */
+#define MY_RESOLVE_SYMLINKS	16	/* Resolve all symbolic links */
+#define MY_RETURN_REAL_PATH	32	/* return full path for file */
+#define MY_SAFE_PATH		64	/* Return NULL if too long path */
+#define MY_RELATIVE_PATH	128	/* name is relative to 'dir' */
+
+	/* My seek flags */
+#define MY_SEEK_SET	0
+#define MY_SEEK_CUR	1
+#define MY_SEEK_END	2
+
+	/* Some constants */
+#define MY_WAIT_FOR_USER_TO_FIX_PANIC	60	/* in seconds */
+#define MY_WAIT_GIVE_USER_A_MESSAGE	10	/* Every 10 times of prev */
+#define MIN_COMPRESS_LENGTH		50	/* Don't compress small bl. */
+#define DFLT_INIT_HITS  3
+
+	/* root_alloc flags */
+#define MY_KEEP_PREALLOC	1
+#define MY_MARK_BLOCKS_FREE     2  /* move used to free list and reuse them */
+
+	/* Internal error numbers (for assembler functions) */
+#define MY_ERRNO_EDOM		33
+#define MY_ERRNO_ERANGE		34
+
+	/* Bits for get_date timeflag */
+#define GETDATE_DATE_TIME	1
+#define GETDATE_SHORT_DATE	2
+#define GETDATE_HHMMSSTIME	4
+#define GETDATE_GMT		8
+#define GETDATE_FIXEDLENGTH	16
+
+	/* defines when allocating data */
+#ifdef SAFEMALLOC
+#define my_malloc(SZ,FLAG) _mymalloc((SZ), __FILE__, __LINE__, FLAG )
+#define my_malloc_ci(SZ,FLAG) _mymalloc((SZ), sFile, uLine, FLAG )
+#define my_realloc(PTR,SZ,FLAG) _myrealloc((PTR), (SZ), __FILE__, __LINE__, FLAG )
+#define my_checkmalloc() _sanity( __FILE__, __LINE__ )
+#define my_free(PTR,FLAG) _myfree((PTR), __FILE__, __LINE__,FLAG)
+#define my_memdup(A,B,C) _my_memdup((A),(B), __FILE__,__LINE__,C)
+#define my_strdup(A,C) _my_strdup((A), __FILE__,__LINE__,C)
+#define my_strdup_with_length(A,B,C) _my_strdup_with_length((A),(B),__FILE__,__LINE__,C)
+#define TRASH(A,B) bfill(A, B, 0x8F)
+#define QUICK_SAFEMALLOC sf_malloc_quick=1
+#define NORMAL_SAFEMALLOC sf_malloc_quick=0
+extern uint sf_malloc_prehunc,sf_malloc_endhunc,sf_malloc_quick;
+extern ulonglong sf_malloc_mem_limit;
+
+#define CALLER_INFO_PROTO   , const char *sFile, uint uLine
+#define CALLER_INFO         , __FILE__, __LINE__
+#define ORIG_CALLER_INFO    , sFile, uLine
+#else
+#define my_checkmalloc()
+#undef TERMINATE
+#define TERMINATE(A) {}
+#define QUICK_SAFEMALLOC
+#define NORMAL_SAFEMALLOC
+extern gptr my_malloc(size_t Size, myf MyFlags);
+#define my_malloc_ci(SZ,FLAG) my_malloc( SZ, FLAG )
+extern gptr my_realloc(gptr oldpoint,uint Size,myf MyFlags);
+extern void my_no_flags_free(gptr ptr);
+extern gptr my_memdup(const byte *from, size_t length, myf MyFlags);
+extern char *my_strdup(const char *from,myf MyFlags);
+extern char *my_strdup_with_length(const char *from, size_t length,
+                                   myf MyFlags);
+/* we do use FG (as a no-op) in below so that a typo on FG is caught */
+#define my_free(PTR,FG) ((void)FG,my_no_flags_free(PTR))
+#define CALLER_INFO_PROTO   /* nothing */
+#define CALLER_INFO         /* nothing */
+#define ORIG_CALLER_INFO    /* nothing */
+#define TRASH(A,B) /* nothing */
+#endif
+
+#ifdef HAVE_LARGE_PAGES
+extern uint my_get_large_page_size(void);
+extern gptr my_large_malloc(size_t size, myf my_flags);
+extern void my_large_free(gptr ptr, myf my_flags);
+#else
+#define my_get_large_page_size() (0)
+#define my_large_malloc(A,B) my_malloc_lock((A),(B))
+#define my_large_free(A,B) my_free_lock((A),(B))
+#endif /* HAVE_LARGE_PAGES */
+
+#ifdef HAVE_ALLOCA
+#if defined(_AIX) && !defined(__GNUC__) && !defined(_AIX43)
+#pragma alloca
+#endif /* _AIX */
+#if defined(__MWERKS__)
+#undef alloca
+#define alloca _alloca
+#endif /* __MWERKS__ */
+#if defined(__GNUC__) && !defined(HAVE_ALLOCA_H) && ! defined(alloca)
+#define alloca __builtin_alloca
+#endif /* GNUC */
+#define my_alloca(SZ) alloca((size_t) (SZ))
+#define my_afree(PTR) {}
+#else
+#define my_alloca(SZ) my_malloc(SZ,MYF(0))
+#define my_afree(PTR) my_free(PTR,MYF(MY_WME))
+#endif /* HAVE_ALLOCA */
+
+#ifdef MSDOS
+#ifdef __ZTC__
+void * __CDECL halloc(long count,size_t length);
+void   __CDECL hfree(void *ptr);
+#endif
+#if defined(USE_HALLOC)
+#if defined(_VCM_) || defined(M_IC80386)
+#undef USE_HALLOC
+#endif
+#endif
+#ifdef USE_HALLOC
+#define malloc(a) halloc((long) (a),1)
+#define free(a) hfree(a)
+#endif
+#endif /* MSDOS */
+
+#ifndef errno				/* did we already get it? */
+#ifdef HAVE_ERRNO_AS_DEFINE
+#include 			/* errno is a define */
+#else
+extern int errno;			/* declare errno */
+#endif
+#endif					/* #ifndef errno */
+extern char NEAR errbuff[NRERRBUFFS][ERRMSGSIZE];
+extern char *home_dir;			/* Home directory for user */
+extern const char *my_progname;		/* program-name (printed in errors) */
+extern char NEAR curr_dir[];		/* Current directory for user */
+extern int (*error_handler_hook)(uint my_err, const char *str,myf MyFlags);
+extern int (*fatal_error_handler_hook)(uint my_err, const char *str,
+				       myf MyFlags);
+extern uint my_file_limit;
+
+#ifdef HAVE_LARGE_PAGES
+extern my_bool my_use_large_pages;
+extern uint    my_large_page_size;
+#endif
+
+/* charsets */
+extern CHARSET_INFO *default_charset_info;
+extern CHARSET_INFO *all_charsets[256];
+extern CHARSET_INFO compiled_charsets[];
+
+/* statistics */
+extern ulong	my_file_opened,my_stream_opened, my_tmp_file_created;
+extern uint	mysys_usage_id;
+extern my_bool	my_init_done;
+
+					/* Point to current my_message() */
+extern void (*my_sigtstp_cleanup)(void),
+					/* Executed before jump to shell */
+	    (*my_sigtstp_restart)(void),
+	    (*my_abort_hook)(int);
+					/* Executed when comming from shell */
+extern int NEAR my_umask,		/* Default creation mask  */
+	   NEAR my_umask_dir,
+	   NEAR my_recived_signals,	/* Signals we have got */
+	   NEAR my_safe_to_handle_signal, /* Set when allowed to SIGTSTP */
+	   NEAR my_dont_interrupt;	/* call remember_intr when set */
+extern my_bool NEAR mysys_uses_curses, my_use_symdir;
+extern ulong sf_malloc_cur_memory, sf_malloc_max_memory;
+
+extern ulong	my_default_record_cache_size;
+extern my_bool NEAR my_disable_locking,NEAR my_disable_async_io,
+               NEAR my_disable_flush_key_blocks, NEAR my_disable_symlinks;
+extern char	wild_many,wild_one,wild_prefix;
+extern const char *charsets_dir;
+/* from default.c */
+extern char *my_defaults_extra_file;
+extern const char *my_defaults_group_suffix;
+extern const char *my_defaults_file;
+
+extern my_bool timed_mutexes;
+
+typedef struct wild_file_pack	/* Struct to hold info when selecting files */
+{
+  uint		wilds;		/* How many wildcards */
+  uint		not_pos;	/* Start of not-theese-files */
+  my_string	*wild;		/* Pointer to wildcards */
+} WF_PACK;
+
+enum loglevel {
+   ERROR_LEVEL,
+   WARNING_LEVEL,
+   INFORMATION_LEVEL
+};
+
+enum cache_type
+{
+  TYPE_NOT_SET= 0, READ_CACHE, WRITE_CACHE,
+  SEQ_READ_APPEND		/* sequential read or append */,
+  READ_FIFO, READ_NET,WRITE_NET};
+
+enum flush_type
+{
+  FLUSH_KEEP, FLUSH_RELEASE, FLUSH_IGNORE_CHANGED, FLUSH_FORCE_WRITE
+};
+
+typedef struct st_record_cache	/* Used when cacheing records */
+{
+  File file;
+  int	rc_seek,error,inited;
+  uint	rc_length,read_length,reclength;
+  my_off_t rc_record_pos,end_of_file;
+  byte	*rc_buff,*rc_buff2,*rc_pos,*rc_end,*rc_request_pos;
+#ifdef HAVE_AIOWAIT
+  int	use_async_io;
+  my_aio_result aio_result;
+#endif
+  enum cache_type type;
+} RECORD_CACHE;
+
+enum file_type
+{
+  UNOPEN = 0, FILE_BY_OPEN, FILE_BY_CREATE, STREAM_BY_FOPEN, STREAM_BY_FDOPEN,
+  FILE_BY_MKSTEMP, FILE_BY_DUP
+};
+
+struct st_my_file_info
+{
+  my_string		name;
+  enum file_type	type;
+#if defined(THREAD) && !defined(HAVE_PREAD)
+  pthread_mutex_t	mutex;
+#endif
+};
+
+extern struct st_my_file_info *my_file_info;
+
+typedef struct st_dynamic_array
+{
+  char *buffer;
+  uint elements,max_element;
+  uint alloc_increment;
+  uint size_of_element;
+} DYNAMIC_ARRAY;
+
+typedef struct st_my_tmpdir
+{
+  DYNAMIC_ARRAY full_list;
+  char **list;
+  uint cur, max;
+#ifdef THREAD
+  pthread_mutex_t mutex;
+#endif
+} MY_TMPDIR;
+
+typedef struct st_dynamic_string
+{
+  char *str;
+  uint length,max_length,alloc_increment;
+} DYNAMIC_STRING;
+
+struct st_io_cache;
+typedef int (*IO_CACHE_CALLBACK)(struct st_io_cache*);
+
+#ifdef THREAD
+typedef struct st_io_cache_share
+{
+  pthread_mutex_t       mutex;           /* To sync on reads into buffer. */
+  pthread_cond_t        cond;            /* To wait for signals. */
+  pthread_cond_t        cond_writer;     /* For a synchronized writer. */
+  /* Offset in file corresponding to the first byte of buffer. */
+  my_off_t              pos_in_file;
+  /* If a synchronized write cache is the source of the data. */
+  struct st_io_cache    *source_cache;
+  byte                  *buffer;         /* The read buffer. */
+  byte                  *read_end;       /* Behind last valid byte of buffer. */
+  int                   running_threads; /* threads not in lock. */
+  int                   total_threads;   /* threads sharing the cache. */
+  int                   error;           /* Last error. */
+#ifdef NOT_YET_IMPLEMENTED
+  /* whether the structure should be free'd */
+  my_bool alloced;
+#endif
+} IO_CACHE_SHARE;
+#endif
+
+typedef struct st_io_cache		/* Used when cacheing files */
+{
+  /* Offset in file corresponding to the first byte of byte* buffer. */
+  my_off_t pos_in_file;
+  /*
+    The offset of end of file for READ_CACHE and WRITE_CACHE.
+    For SEQ_READ_APPEND it the maximum of the actual end of file and
+    the position represented by read_end.
+  */
+  my_off_t end_of_file;
+  /* Points to current read position in the buffer */
+  byte	*read_pos;
+  /* the non-inclusive boundary in the buffer for the currently valid read */
+  byte  *read_end;
+  byte  *buffer;				/* The read buffer */
+  /* Used in ASYNC_IO */
+  byte  *request_pos;
+
+  /* Only used in WRITE caches and in SEQ_READ_APPEND to buffer writes */
+  byte  *write_buffer;
+  /*
+    Only used in SEQ_READ_APPEND, and points to the current read position
+    in the write buffer. Note that reads in SEQ_READ_APPEND caches can
+    happen from both read buffer (byte* buffer) and write buffer
+    (byte* write_buffer).
+  */
+  byte *append_read_pos;
+  /* Points to current write position in the write buffer */
+  byte *write_pos;
+  /* The non-inclusive boundary of the valid write area */
+  byte *write_end;
+
+  /*
+    Current_pos and current_end are convenience variables used by
+    my_b_tell() and other routines that need to know the current offset
+    current_pos points to &write_pos, and current_end to &write_end in a
+    WRITE_CACHE, and &read_pos and &read_end respectively otherwise
+  */
+  byte  **current_pos, **current_end;
+#ifdef THREAD
+  /*
+    The lock is for append buffer used in SEQ_READ_APPEND cache
+    need mutex copying from append buffer to read buffer.
+  */
+  pthread_mutex_t append_buffer_lock;
+  /*
+    The following is used when several threads are reading the
+    same file in parallel. They are synchronized on disk
+    accesses reading the cached part of the file asynchronously.
+    It should be set to NULL to disable the feature.  Only
+    READ_CACHE mode is supported.
+  */
+  IO_CACHE_SHARE *share;
+#endif
+  /*
+    A caller will use my_b_read() macro to read from the cache
+    if the data is already in cache, it will be simply copied with
+    memcpy() and internal variables will be accordinging updated with
+    no functions invoked. However, if the data is not fully in the cache,
+    my_b_read() will call read_function to fetch the data. read_function
+    must never be invoked directly.
+  */
+  int (*read_function)(struct st_io_cache *,byte *,uint);
+  /*
+    Same idea as in the case of read_function, except my_b_write() needs to
+    be replaced with my_b_append() for a SEQ_READ_APPEND cache
+  */
+  int (*write_function)(struct st_io_cache *,const byte *,uint);
+  /*
+    Specifies the type of the cache. Depending on the type of the cache
+    certain operations might not be available and yield unpredicatable
+    results. Details to be documented later
+  */
+  enum cache_type type;
+  /*
+    Callbacks when the actual read I/O happens. These were added and
+    are currently used for binary logging of LOAD DATA INFILE - when a
+    block is read from the file, we create a block create/append event, and
+    when IO_CACHE is closed, we create an end event. These functions could,
+    of course be used for other things
+  */
+  IO_CACHE_CALLBACK pre_read;
+  IO_CACHE_CALLBACK post_read;
+  IO_CACHE_CALLBACK pre_close;
+  /*
+    Counts the number of times, when we were forced to use disk. We use it to
+    increase the binlog_cache_disk_use status variable.
+  */
+  ulong disk_writes;
+  void* arg;				/* for use by pre/post_read */
+  char *file_name;			/* if used with 'open_cached_file' */
+  char *dir,*prefix;
+  File file; /* file descriptor */
+  /*
+    seek_not_done is set by my_b_seek() to inform the upcoming read/write
+    operation that a seek needs to be preformed prior to the actual I/O
+    error is 0 if the cache operation was successful, -1 if there was a
+    "hard" error, and the actual number of I/O-ed bytes if the read/write was
+    partial.
+  */
+  int	seek_not_done,error;
+  /* buffer_length is memory size allocated for buffer or write_buffer */
+  uint	buffer_length;
+  /* read_length is the same as buffer_length except when we use async io */
+  uint  read_length;
+  myf	myflags;			/* Flags used to my_read/my_write */
+  /*
+    alloced_buffer is 1 if the buffer was allocated by init_io_cache() and
+    0 if it was supplied by the user.
+    Currently READ_NET is the only one that will use a buffer allocated
+    somewhere else
+  */
+  my_bool alloced_buffer;
+#ifdef HAVE_AIOWAIT
+  /*
+    As inidicated by ifdef, this is for async I/O, which is not currently
+    used (because it's not reliable on all systems)
+  */
+  uint inited;
+  my_off_t aio_read_pos;
+  my_aio_result aio_result;
+#endif
+} IO_CACHE;
+
+typedef int (*qsort2_cmp)(const void *, const void *, const void *);
+
+	/* defines for mf_iocache */
+
+	/* Test if buffer is inited */
+#define my_b_clear(info) (info)->buffer=0
+#define my_b_inited(info) (info)->buffer
+#define my_b_EOF INT_MIN
+
+#define my_b_read(info,Buffer,Count) \
+  ((info)->read_pos + (Count) <= (info)->read_end ?\
+   (memcpy(Buffer,(info)->read_pos,(size_t) (Count)), \
+    ((info)->read_pos+=(Count)),0) :\
+   (*(info)->read_function)((info),Buffer,Count))
+
+#define my_b_write(info,Buffer,Count) \
+ ((info)->write_pos + (Count) <=(info)->write_end ?\
+  (memcpy((info)->write_pos, (Buffer), (size_t)(Count)),\
+   ((info)->write_pos+=(Count)),0) : \
+   (*(info)->write_function)((info),(Buffer),(Count)))
+
+#define my_b_get(info) \
+  ((info)->read_pos != (info)->read_end ?\
+   ((info)->read_pos++, (int) (uchar) (info)->read_pos[-1]) :\
+   _my_b_get(info))
+
+	/* my_b_write_byte dosn't have any err-check */
+#define my_b_write_byte(info,chr) \
+  (((info)->write_pos < (info)->write_end) ?\
+   ((*(info)->write_pos++)=(chr)) :\
+   (_my_b_write(info,0,0) , ((*(info)->write_pos++)=(chr))))
+
+#define my_b_fill_cache(info) \
+  (((info)->read_end=(info)->read_pos),(*(info)->read_function)(info,0,0))
+
+#define my_b_tell(info) ((info)->pos_in_file + \
+			 (uint) (*(info)->current_pos - (info)->request_pos))
+
+#define my_b_get_buffer_start(info) (info)->request_pos 
+#define my_b_get_bytes_in_buffer(info) (char*) (info)->read_end -   \
+  (char*) my_b_get_buffer_start(info)
+#define my_b_get_pos_in_file(info) (info)->pos_in_file
+
+
+/* tell write offset in the SEQ_APPEND cache */
+my_off_t my_b_append_tell(IO_CACHE* info);
+my_off_t my_b_safe_tell(IO_CACHE* info); /* picks the correct tell() */
+
+#define my_b_bytes_in_cache(info) (uint) (*(info)->current_end - \
+					  *(info)->current_pos)
+
+typedef uint32 ha_checksum;
+
+/* Define the type of function to be passed to process_default_option_files */
+typedef int (*Process_option_func)(void *ctx, const char *group_name,
+                                   const char *option);
+
+#include 
+
+
+	/* Prototypes for mysys and my_func functions */
+
+extern int my_copy(const char *from,const char *to,myf MyFlags);
+extern int my_append(const char *from,const char *to,myf MyFlags);
+extern int my_delete(const char *name,myf MyFlags);
+extern int my_getwd(my_string buf,uint size,myf MyFlags);
+extern int my_setwd(const char *dir,myf MyFlags);
+extern int my_lock(File fd,int op,my_off_t start, my_off_t length,myf MyFlags);
+extern gptr my_once_alloc(uint Size,myf MyFlags);
+extern void my_once_free(void);
+extern char *my_once_strdup(const char *src,myf myflags);
+extern char *my_once_memdup(const char *src, uint len, myf myflags);
+extern File my_open(const char *FileName,int Flags,myf MyFlags);
+extern File my_register_filename(File fd, const char *FileName,
+				 enum file_type type_of_file,
+				 uint error_message_number, myf MyFlags);
+extern File my_create(const char *FileName,int CreateFlags,
+		      int AccsesFlags, myf MyFlags);
+extern int my_close(File Filedes,myf MyFlags);
+extern File my_dup(File file, myf MyFlags);
+extern int my_mkdir(const char *dir, int Flags, myf MyFlags);
+extern int my_readlink(char *to, const char *filename, myf MyFlags);
+extern int my_realpath(char *to, const char *filename, myf MyFlags);
+extern File my_create_with_symlink(const char *linkname, const char *filename,
+				   int createflags, int access_flags,
+				   myf MyFlags);
+extern int my_delete_with_symlink(const char *name, myf MyFlags);
+extern int my_rename_with_symlink(const char *from,const char *to,myf MyFlags);
+extern int my_symlink(const char *content, const char *linkname, myf MyFlags);
+extern uint my_read(File Filedes,byte *Buffer,uint Count,myf MyFlags);
+extern uint my_pread(File Filedes,byte *Buffer,uint Count,my_off_t offset,
+		     myf MyFlags);
+extern int my_rename(const char *from,const char *to,myf MyFlags);
+extern my_off_t my_seek(File fd,my_off_t pos,int whence,myf MyFlags);
+extern my_off_t my_tell(File fd,myf MyFlags);
+extern uint my_write(File Filedes,const byte *Buffer,uint Count,
+		     myf MyFlags);
+extern uint my_pwrite(File Filedes,const byte *Buffer,uint Count,
+		      my_off_t offset,myf MyFlags);
+extern uint my_fread(FILE *stream,byte *Buffer,uint Count,myf MyFlags);
+extern uint my_fwrite(FILE *stream,const byte *Buffer,uint Count,
+		      myf MyFlags);
+extern my_off_t my_fseek(FILE *stream,my_off_t pos,int whence,myf MyFlags);
+extern my_off_t my_ftell(FILE *stream,myf MyFlags);
+extern gptr _mymalloc(size_t uSize, const char *sFile,
+                       uint uLine, myf MyFlag);
+extern gptr _myrealloc(gptr pPtr, size_t uSize, const char *sFile,
+                        uint uLine, myf MyFlag);
+extern gptr my_multi_malloc _VARARGS((myf MyFlags, ...));
+extern void _myfree(gptr pPtr, const char *sFile, uint uLine, myf MyFlag);
+extern int _sanity(const char *sFile,unsigned int uLine);
+extern gptr _my_memdup(const byte *from, size_t length,
+                        const char *sFile, uint uLine, myf MyFlag);
+extern my_string _my_strdup(const char *from, const char *sFile, uint uLine,
+			    myf MyFlag);
+extern char *_my_strdup_with_length(const char *from, size_t length,
+				    const char *sFile, uint uLine,
+				    myf MyFlag);
+
+/* implemented in my_memmem.c */
+extern void *my_memmem(const void *haystack, size_t haystacklen,
+    const void *needle, size_t needlelen);
+
+
+#ifdef __WIN__
+extern int my_access(const char *path, int amode);
+extern File my_sopen(const char *path, int oflag, int shflag, int pmode);
+#else
+#define my_access access
+#endif
+extern int check_if_legal_filename(const char *path);
+
+#if defined(__WIN__) && defined(__NT__)
+extern int nt_share_delete(const char *name,myf MyFlags);
+#define my_delete_allow_opened(fname,flags)  nt_share_delete((fname),(flags))
+#else
+#define my_delete_allow_opened(fname,flags)  my_delete((fname),(flags))
+#endif
+
+#ifndef TERMINATE
+extern void TERMINATE(FILE *file);
+#endif
+extern void init_glob_errs(void);
+extern FILE *my_fopen(const char *FileName,int Flags,myf MyFlags);
+extern FILE *my_fdopen(File Filedes,const char *name, int Flags,myf MyFlags);
+extern int my_fclose(FILE *fd,myf MyFlags);
+extern int my_chsize(File fd,my_off_t newlength, int filler, myf MyFlags);
+extern int my_sync(File fd, myf my_flags);
+extern int my_error _VARARGS((int nr,myf MyFlags, ...));
+extern int my_printf_error _VARARGS((uint my_err, const char *format,
+				     myf MyFlags, ...))
+				    ATTRIBUTE_FORMAT(printf, 2, 4);
+extern int my_error_register(const char **errmsgs, int first, int last);
+extern const char **my_error_unregister(int first, int last);
+extern int my_message(uint my_err, const char *str,myf MyFlags);
+extern int my_message_no_curses(uint my_err, const char *str,myf MyFlags);
+extern int my_message_curses(uint my_err, const char *str,myf MyFlags);
+extern my_bool my_init(void);
+extern void my_end(int infoflag);
+extern int my_redel(const char *from, const char *to, int MyFlags);
+extern int my_copystat(const char *from, const char *to, int MyFlags);
+extern my_string my_filename(File fd);
+
+#ifndef THREAD
+extern void dont_break(void);
+extern void allow_break(void);
+#else
+#define dont_break()
+#define allow_break()
+#endif
+
+extern my_bool init_tmpdir(MY_TMPDIR *tmpdir, const char *pathlist);
+extern char *my_tmpdir(MY_TMPDIR *tmpdir);
+extern void free_tmpdir(MY_TMPDIR *tmpdir);
+
+extern void my_remember_signal(int signal_number,sig_handler (*func)(int));
+extern uint dirname_part(my_string to,const char *name);
+extern uint dirname_length(const char *name);
+#define base_name(A) (A+dirname_length(A))
+extern int test_if_hard_path(const char *dir_name);
+extern my_bool has_path(const char *name);
+extern char *convert_dirname(char *to, const char *from, const char *from_end);
+extern void to_unix_path(my_string name);
+extern my_string fn_ext(const char *name);
+extern my_string fn_same(my_string toname,const char *name,int flag);
+extern my_string fn_format(my_string to,const char *name,const char *dir,
+			   const char *form, uint flag);
+extern size_s strlength(const char *str);
+extern void pack_dirname(my_string to,const char *from);
+extern uint unpack_dirname(my_string to,const char *from);
+extern uint cleanup_dirname(my_string to,const char *from);
+extern uint system_filename(my_string to,const char *from);
+extern uint unpack_filename(my_string to,const char *from);
+extern my_string intern_filename(my_string to,const char *from);
+extern my_string directory_file_name(my_string dst, const char *src);
+extern int pack_filename(my_string to, const char *name, size_s max_length);
+extern my_string my_path(my_string to,const char *progname,
+			 const char *own_pathname_part);
+extern my_string my_load_path(my_string to, const char *path,
+			      const char *own_path_prefix);
+extern int wild_compare(const char *str,const char *wildstr,pbool str_is_pattern);
+extern WF_PACK *wf_comp(my_string str);
+extern int wf_test(struct wild_file_pack *wf_pack,const char *name);
+extern void wf_end(struct wild_file_pack *buffer);
+extern size_s strip_sp(my_string str);
+extern my_bool array_append_string_unique(const char *str,
+                                          const char **array, size_t size);
+extern void get_date(my_string to,int timeflag,time_t use_time);
+extern void soundex(CHARSET_INFO *, my_string out_pntr, my_string in_pntr,pbool remove_garbage);
+extern int init_record_cache(RECORD_CACHE *info,uint cachesize,File file,
+			     uint reclength,enum cache_type type,
+			     pbool use_async_io);
+extern int read_cache_record(RECORD_CACHE *info,byte *to);
+extern int end_record_cache(RECORD_CACHE *info);
+extern int write_cache_record(RECORD_CACHE *info,my_off_t filepos,
+			      const byte *record,uint length);
+extern int flush_write_cache(RECORD_CACHE *info);
+extern long my_clock(void);
+extern sig_handler sigtstp_handler(int signal_number);
+extern void handle_recived_signals(void);
+
+extern sig_handler my_set_alarm_variable(int signo);
+extern void my_string_ptr_sort(void *base,uint items,size_s size);
+extern void radixsort_for_str_ptr(uchar* base[], uint number_of_elements,
+				  size_s size_of_element,uchar *buffer[]);
+extern qsort_t my_qsort(void *base_ptr, size_t total_elems, size_t size,
+                        qsort_cmp cmp);
+extern qsort_t my_qsort2(void *base_ptr, size_t total_elems, size_t size,
+                         qsort2_cmp cmp, void *cmp_argument);
+extern qsort2_cmp get_ptr_compare(uint);
+void my_store_ptr(byte *buff, uint pack_length, my_off_t pos);
+my_off_t my_get_ptr(byte *ptr, uint pack_length);
+extern int init_io_cache(IO_CACHE *info,File file,uint cachesize,
+			 enum cache_type type,my_off_t seek_offset,
+			 pbool use_async_io, myf cache_myflags);
+extern my_bool reinit_io_cache(IO_CACHE *info,enum cache_type type,
+			       my_off_t seek_offset,pbool use_async_io,
+			       pbool clear_cache);
+extern void setup_io_cache(IO_CACHE* info);
+extern int _my_b_read(IO_CACHE *info,byte *Buffer,uint Count);
+#ifdef THREAD
+extern int _my_b_read_r(IO_CACHE *info,byte *Buffer,uint Count);
+extern void init_io_cache_share(IO_CACHE *read_cache, IO_CACHE_SHARE *cshare,
+                                IO_CACHE *write_cache, uint num_threads);
+extern void remove_io_thread(IO_CACHE *info);
+#endif
+extern int _my_b_seq_read(IO_CACHE *info,byte *Buffer,uint Count);
+extern int _my_b_net_read(IO_CACHE *info,byte *Buffer,uint Count);
+extern int _my_b_get(IO_CACHE *info);
+extern int _my_b_async_read(IO_CACHE *info,byte *Buffer,uint Count);
+extern int _my_b_write(IO_CACHE *info,const byte *Buffer,uint Count);
+extern int my_b_append(IO_CACHE *info,const byte *Buffer,uint Count);
+extern int my_b_safe_write(IO_CACHE *info,const byte *Buffer,uint Count);
+
+extern int my_block_write(IO_CACHE *info, const byte *Buffer,
+			  uint Count, my_off_t pos);
+extern int my_b_flush_io_cache(IO_CACHE *info, int need_append_buffer_lock);
+
+#define flush_io_cache(info) my_b_flush_io_cache((info),1)
+
+extern int end_io_cache(IO_CACHE *info);
+extern uint my_b_fill(IO_CACHE *info);
+extern void my_b_seek(IO_CACHE *info,my_off_t pos);
+extern uint my_b_gets(IO_CACHE *info, char *to, uint max_length);
+extern my_off_t my_b_filelength(IO_CACHE *info);
+extern uint my_b_printf(IO_CACHE *info, const char* fmt, ...);
+extern uint my_b_vprintf(IO_CACHE *info, const char* fmt, va_list ap);
+extern my_bool open_cached_file(IO_CACHE *cache,const char *dir,
+				 const char *prefix, uint cache_size,
+				 myf cache_myflags);
+extern my_bool real_open_cached_file(IO_CACHE *cache);
+extern void close_cached_file(IO_CACHE *cache);
+File create_temp_file(char *to, const char *dir, const char *pfx,
+		      int mode, myf MyFlags);
+#define my_init_dynamic_array(A,B,C,D) init_dynamic_array(A,B,C,D CALLER_INFO)
+#define my_init_dynamic_array_ci(A,B,C,D) init_dynamic_array(A,B,C,D ORIG_CALLER_INFO)
+extern my_bool init_dynamic_array(DYNAMIC_ARRAY *array,uint element_size,
+                                  uint init_alloc,uint alloc_increment
+                                  CALLER_INFO_PROTO);
+extern my_bool insert_dynamic(DYNAMIC_ARRAY *array,gptr element);
+extern byte *alloc_dynamic(DYNAMIC_ARRAY *array);
+extern byte *pop_dynamic(DYNAMIC_ARRAY*);
+extern my_bool set_dynamic(DYNAMIC_ARRAY *array,gptr element,uint array_index);
+extern void get_dynamic(DYNAMIC_ARRAY *array,gptr element,uint array_index);
+extern void delete_dynamic(DYNAMIC_ARRAY *array);
+extern void delete_dynamic_element(DYNAMIC_ARRAY *array, uint array_index);
+extern void freeze_size(DYNAMIC_ARRAY *array);
+#define dynamic_array_ptr(array,array_index) ((array)->buffer+(array_index)*(array)->size_of_element)
+#define dynamic_element(array,array_index,type) ((type)((array)->buffer) +(array_index))
+#define push_dynamic(A,B) insert_dynamic(A,B)
+#define reset_dynamic(array) ((array)->elements= 0)
+
+extern my_bool init_dynamic_string(DYNAMIC_STRING *str, const char *init_str,
+				   uint init_alloc,uint alloc_increment);
+extern my_bool dynstr_append(DYNAMIC_STRING *str, const char *append);
+my_bool dynstr_append_mem(DYNAMIC_STRING *str, const char *append,
+			  uint length);
+extern my_bool dynstr_append_os_quoted(DYNAMIC_STRING *str, const char *append,
+                                       ...);
+extern my_bool dynstr_set(DYNAMIC_STRING *str, const char *init_str);
+extern my_bool dynstr_realloc(DYNAMIC_STRING *str, ulong additional_size);
+extern void dynstr_free(DYNAMIC_STRING *str);
+#ifdef HAVE_MLOCK
+extern byte *my_malloc_lock(uint length,myf flags);
+extern void my_free_lock(byte *ptr,myf flags);
+#else
+#define my_malloc_lock(A,B) my_malloc((A),(B))
+#define my_free_lock(A,B) my_free((A),(B))
+#endif
+#define alloc_root_inited(A) ((A)->min_malloc != 0)
+#define ALLOC_ROOT_MIN_BLOCK_SIZE (MALLOC_OVERHEAD + sizeof(USED_MEM) + 8)
+#define clear_alloc_root(A) do { (A)->free= (A)->used= (A)->pre_alloc= 0; (A)->min_malloc=0;} while(0)
+extern void init_alloc_root(MEM_ROOT *mem_root, uint block_size,
+			    uint pre_alloc_size);
+extern gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size);
+extern gptr multi_alloc_root(MEM_ROOT *mem_root, ...);
+extern void free_root(MEM_ROOT *root, myf MyFLAGS);
+extern void set_prealloc_root(MEM_ROOT *root, char *ptr);
+extern void reset_root_defaults(MEM_ROOT *mem_root, uint block_size,
+                                uint prealloc_size);
+extern char *strdup_root(MEM_ROOT *root,const char *str);
+extern char *strmake_root(MEM_ROOT *root,const char *str,uint len);
+extern char *memdup_root(MEM_ROOT *root,const char *str,uint len);
+extern int get_defaults_options(int argc, char **argv,
+                                char **defaults, char **extra_defaults,
+                                char **group_suffix);
+extern int load_defaults(const char *conf_file, const char **groups,
+			 int *argc, char ***argv);
+extern int modify_defaults_file(const char *file_location, const char *option,
+                                const char *option_value,
+                                const char *section_name, int remove_option);
+extern int my_search_option_files(const char *conf_file, int *argc,
+                                  char ***argv, uint *args_used,
+                                  Process_option_func func, void *func_ctx);
+extern void free_defaults(char **argv);
+extern void my_print_default_files(const char *conf_file);
+extern void print_defaults(const char *conf_file, const char **groups);
+extern my_bool my_compress(byte *, ulong *, ulong *);
+extern my_bool my_uncompress(byte *, ulong *, ulong *);
+extern byte *my_compress_alloc(const byte *packet, ulong *len, ulong *complen);
+extern ha_checksum my_checksum(ha_checksum crc, const byte *mem, uint count);
+extern uint my_bit_log2(ulong value);
+extern uint my_count_bits(ulonglong v);
+extern uint my_count_bits_ushort(ushort v);
+extern void my_sleep(ulong m_seconds);
+extern ulong crc32(ulong crc, const uchar *buf, uint len);
+extern uint my_set_max_open_files(uint files);
+void my_free_open_file_info(void);
+
+ulonglong my_getsystime(void);
+my_bool my_gethwaddr(uchar *to);
+
+#ifdef HAVE_SYS_MMAN_H
+#include 
+
+#ifndef MAP_NOSYNC
+#define MAP_NOSYNC      0
+#endif
+
+#define my_mmap(a,b,c,d,e,f)    mmap(a,b,c,d,e,f)
+#define my_munmap(a,b)          munmap((a),(b))
+
+#else
+/* not a complete set of mmap() flags, but only those that nesessary */
+#define PROT_READ        1
+#define PROT_WRITE       2
+#define MAP_SHARED       0x0001
+#define MAP_NOSYNC       0x0800
+#define MAP_FAILED       ((void *)-1)
+#define MS_SYNC          0x0000
+
+#ifndef __NETWARE__
+#define HAVE_MMAP
+#endif
+
+void *my_mmap(void *, size_t, int, int, int, my_off_t);
+int my_munmap(void *, size_t);
+#endif
+
+/* my_getpagesize */
+#ifdef HAVE_GETPAGESIZE
+#define my_getpagesize()        getpagesize()
+#else
+int my_getpagesize(void);
+#endif
+
+int my_msync(int, void *, size_t, int);
+
+/* character sets */
+extern uint get_charset_number(const char *cs_name, uint cs_flags);
+extern uint get_collation_number(const char *name);
+extern const char *get_charset_name(uint cs_number);
+
+extern CHARSET_INFO *get_charset(uint cs_number, myf flags);
+extern CHARSET_INFO *get_charset_by_name(const char *cs_name, myf flags);
+extern CHARSET_INFO *get_charset_by_csname(const char *cs_name,
+					   uint cs_flags, myf my_flags);
+extern CHARSET_INFO *get_compatible_charset_with_ctype(CHARSET_INFO
+                                                       *original_cs);
+extern void free_charsets(void);
+extern char *get_charsets_dir(char *buf);
+extern my_bool my_charset_same(CHARSET_INFO *cs1, CHARSET_INFO *cs2);
+extern my_bool init_compiled_charsets(myf flags);
+extern void add_compiled_collation(CHARSET_INFO *cs);
+extern ulong escape_string_for_mysql(CHARSET_INFO *charset_info,
+                                     char *to, ulong to_length,
+                                     const char *from, ulong length);
+#ifdef __WIN__
+#define BACKSLASH_MBTAIL
+/* File system character set */
+extern CHARSET_INFO *fs_character_set(void);
+#endif
+extern ulong escape_quotes_for_mysql(CHARSET_INFO *charset_info,
+                                     char *to, ulong to_length,
+                                     const char *from, ulong length);
+
+extern void thd_increment_bytes_sent(ulong length);
+extern void thd_increment_bytes_received(ulong length);
+extern void thd_increment_net_big_packet_count(ulong length);
+
+#ifdef __WIN__
+extern my_bool have_tcpip;		/* Is set if tcpip is used */
+
+/* implemented in my_windac.c */
+
+int my_security_attr_create(SECURITY_ATTRIBUTES **psa, const char **perror,
+                            DWORD owner_rights, DWORD everybody_rights);
+
+void my_security_attr_free(SECURITY_ATTRIBUTES *sa);
+
+/* implemented in my_conio.c */
+char* my_cgets(char *string, unsigned long clen, unsigned long* plen);
+
+#endif
+#ifdef __NETWARE__
+void netware_reg_user(const char *ip, const char *user,
+		      const char *application);
+#endif
+
+C_MODE_END
+#include "raid.h"
+#endif /* _my_sys_h */
diff --git a/dep/include/mysql/mysql.h b/dep/include/mysql/mysql.h
new file mode 100644
index 00000000000..18b82b8a943
--- /dev/null
+++ b/dep/include/mysql/mysql.h
@@ -0,0 +1,871 @@
+/* Copyright (C) 2000-2003 MySQL AB
+
+   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; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+/*
+  This file defines the client API to MySQL and also the ABI of the
+  dynamically linked libmysqlclient.
+
+  The ABI should never be changed in a released product of MySQL
+  thus you need to take great care when changing the file. In case
+  the file is changed so the ABI is broken, you must also
+  update the SHAREDLIB_MAJOR_VERSION in configure.in .
+
+*/
+
+#ifndef _mysql_h
+#define _mysql_h
+
+#ifdef _AIX           /* large-file support will break without this */
+#include 
+#endif
+
+#ifdef __CYGWIN__     /* CYGWIN implements a UNIX API */
+#undef WIN
+#undef _WIN
+#undef _WIN32
+#undef _WIN64
+#undef __WIN__
+#endif
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#ifndef _global_h				/* If not standard header */
+#include 
+#ifdef __LCC__
+#include 				/* For windows */
+#endif
+typedef char my_bool;
+#if (defined(_WIN32) || defined(_WIN64)) && !defined(__WIN__)
+#define __WIN__
+#endif
+#if !defined(__WIN__)
+#define STDCALL
+#else
+#define STDCALL __stdcall
+#endif
+typedef char * gptr;
+
+#ifndef my_socket_defined
+#ifdef __WIN__
+#define my_socket SOCKET
+#else
+typedef int my_socket;
+#endif /* __WIN__ */
+#endif /* my_socket_defined */
+#endif /* _global_h */
+
+#include "mysql_version.h"
+#include "mysql_com.h"
+#include "mysql_time.h"
+#include "typelib.h"
+
+#include "my_list.h" /* for LISTs used in 'MYSQL' and 'MYSQL_STMT' */
+
+extern unsigned int mysql_port;
+extern char *mysql_unix_port;
+
+#define CLIENT_NET_READ_TIMEOUT		365*24*3600	/* Timeout on read */
+#define CLIENT_NET_WRITE_TIMEOUT	365*24*3600	/* Timeout on write */
+
+#ifdef __NETWARE__
+// GCC have alternative #pragma pack(8) syntax and old gcc version not support pack(push,8), also any gcc version not support it at some paltform
+#if defined( __GNUC__ )
+#pragma pack(8) 
+#else 
+#pragma pack(push,8) 
+#endif 
+
+#endif
+
+#define IS_PRI_KEY(n)	((n) & PRI_KEY_FLAG)
+#define IS_NOT_NULL(n)	((n) & NOT_NULL_FLAG)
+#define IS_BLOB(n)	((n) & BLOB_FLAG)
+#define IS_NUM(t)	((t) <= FIELD_TYPE_INT24 || (t) == FIELD_TYPE_YEAR || (t) == FIELD_TYPE_NEWDECIMAL)
+#define IS_NUM_FIELD(f)	 ((f)->flags & NUM_FLAG)
+#define INTERNAL_NUM_FIELD(f) (((f)->type <= FIELD_TYPE_INT24 && ((f)->type != FIELD_TYPE_TIMESTAMP || (f)->length == 14 || (f)->length == 8)) || (f)->type == FIELD_TYPE_YEAR)
+#define IS_LONGDATA(t) ((t) >= MYSQL_TYPE_TINY_BLOB && (t) <= MYSQL_TYPE_STRING)
+
+
+typedef struct st_mysql_field {
+  char *name;                 /* Name of column */
+  char *org_name;             /* Original column name, if an alias */
+  char *table;                /* Table of column if column was a field */
+  char *org_table;            /* Org table name, if table was an alias */
+  char *db;                   /* Database for table */
+  char *catalog;	      /* Catalog for table */
+  char *def;                  /* Default value (set by mysql_list_fields) */
+  unsigned long length;       /* Width of column (create length) */
+  unsigned long max_length;   /* Max width for selected set */
+  unsigned int name_length;
+  unsigned int org_name_length;
+  unsigned int table_length;
+  unsigned int org_table_length;
+  unsigned int db_length;
+  unsigned int catalog_length;
+  unsigned int def_length;
+  unsigned int flags;         /* Div flags */
+  unsigned int decimals;      /* Number of decimals in field */
+  unsigned int charsetnr;     /* Character set */
+  enum enum_field_types type; /* Type of field. See mysql_com.h for types */
+} MYSQL_FIELD;
+
+typedef char **MYSQL_ROW;		/* return data as array of strings */
+typedef unsigned int MYSQL_FIELD_OFFSET; /* offset to current field */
+
+#ifndef _global_h
+#if defined(NO_CLIENT_LONG_LONG)
+typedef unsigned long my_ulonglong;
+#elif defined (__WIN__)
+typedef unsigned __int64 my_ulonglong;
+#else
+typedef unsigned long long my_ulonglong;
+#endif
+#endif
+
+#define MYSQL_COUNT_ERROR (~(my_ulonglong) 0)
+
+/* backward compatibility define - to be removed eventually */
+#define ER_WARN_DATA_TRUNCATED WARN_DATA_TRUNCATED
+
+typedef struct st_mysql_rows {
+  struct st_mysql_rows *next;		/* list of rows */
+  MYSQL_ROW data;
+  unsigned long length;
+} MYSQL_ROWS;
+
+typedef MYSQL_ROWS *MYSQL_ROW_OFFSET;	/* offset to current row */
+
+#include "my_alloc.h"
+
+typedef struct embedded_query_result EMBEDDED_QUERY_RESULT;
+typedef struct st_mysql_data {
+  my_ulonglong rows;
+  unsigned int fields;
+  MYSQL_ROWS *data;
+  MEM_ROOT alloc;
+  /* extra info for embedded library */
+  struct embedded_query_result *embedded_info;
+} MYSQL_DATA;
+
+enum mysql_option 
+{
+  MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_OPT_COMPRESS, MYSQL_OPT_NAMED_PIPE,
+  MYSQL_INIT_COMMAND, MYSQL_READ_DEFAULT_FILE, MYSQL_READ_DEFAULT_GROUP,
+  MYSQL_SET_CHARSET_DIR, MYSQL_SET_CHARSET_NAME, MYSQL_OPT_LOCAL_INFILE,
+  MYSQL_OPT_PROTOCOL, MYSQL_SHARED_MEMORY_BASE_NAME, MYSQL_OPT_READ_TIMEOUT,
+  MYSQL_OPT_WRITE_TIMEOUT, MYSQL_OPT_USE_RESULT,
+  MYSQL_OPT_USE_REMOTE_CONNECTION, MYSQL_OPT_USE_EMBEDDED_CONNECTION,
+  MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH,
+  MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT,
+  MYSQL_OPT_SSL_VERIFY_SERVER_CERT
+};
+
+struct st_mysql_options {
+  unsigned int connect_timeout, read_timeout, write_timeout;
+  unsigned int port, protocol;
+  unsigned long client_flag;
+  char *host,*user,*password,*unix_socket,*db;
+  struct st_dynamic_array *init_commands;
+  char *my_cnf_file,*my_cnf_group, *charset_dir, *charset_name;
+  char *ssl_key;				/* PEM key file */
+  char *ssl_cert;				/* PEM cert file */
+  char *ssl_ca;					/* PEM CA file */
+  char *ssl_capath;				/* PEM directory of CA-s? */
+  char *ssl_cipher;				/* cipher to use */
+  char *shared_memory_base_name;
+  unsigned long max_allowed_packet;
+  my_bool use_ssl;				/* if to use SSL or not */
+  my_bool compress,named_pipe;
+ /*
+   On connect, find out the replication role of the server, and
+   establish connections to all the peers
+ */
+  my_bool rpl_probe;
+ /*
+   Each call to mysql_real_query() will parse it to tell if it is a read
+   or a write, and direct it to the slave or the master
+ */
+  my_bool rpl_parse;
+ /*
+   If set, never read from a master, only from slave, when doing
+   a read that is replication-aware
+ */
+  my_bool no_master_reads;
+#if !defined(CHECK_EMBEDDED_DIFFERENCES) || defined(EMBEDDED_LIBRARY)
+  my_bool separate_thread;
+#endif
+  enum mysql_option methods_to_use;
+  char *client_ip;
+  /* Refuse client connecting to server if it uses old (pre-4.1.1) protocol */
+  my_bool secure_auth;
+  /* 0 - never report, 1 - always report (default) */
+  my_bool report_data_truncation;
+
+  /* function pointers for local infile support */
+  int (*local_infile_init)(void **, const char *, void *);
+  int (*local_infile_read)(void *, char *, unsigned int);
+  void (*local_infile_end)(void *);
+  int (*local_infile_error)(void *, char *, unsigned int);
+  void *local_infile_userdata;
+};
+
+enum mysql_status 
+{
+  MYSQL_STATUS_READY,MYSQL_STATUS_GET_RESULT,MYSQL_STATUS_USE_RESULT
+};
+
+enum mysql_protocol_type 
+{
+  MYSQL_PROTOCOL_DEFAULT, MYSQL_PROTOCOL_TCP, MYSQL_PROTOCOL_SOCKET,
+  MYSQL_PROTOCOL_PIPE, MYSQL_PROTOCOL_MEMORY
+};
+/*
+  There are three types of queries - the ones that have to go to
+  the master, the ones that go to a slave, and the adminstrative
+  type which must happen on the pivot connectioin
+*/
+enum mysql_rpl_type 
+{
+  MYSQL_RPL_MASTER, MYSQL_RPL_SLAVE, MYSQL_RPL_ADMIN
+};
+
+typedef struct character_set
+{
+  unsigned int      number;     /* character set number              */
+  unsigned int      state;      /* character set state               */
+  const char        *csname;    /* collation name                    */
+  const char        *name;      /* character set name                */
+  const char        *comment;   /* comment                           */
+  const char        *dir;       /* character set directory           */
+  unsigned int      mbminlen;   /* min. length for multibyte strings */
+  unsigned int      mbmaxlen;   /* max. length for multibyte strings */
+} MY_CHARSET_INFO;
+
+struct st_mysql_methods;
+struct st_mysql_stmt;
+
+typedef struct st_mysql
+{
+  NET		net;			/* Communication parameters */
+  gptr		connector_fd;		/* ConnectorFd for SSL */
+  char		*host,*user,*passwd,*unix_socket,*server_version,*host_info,*info;
+  char          *db;
+  struct charset_info_st *charset;
+  MYSQL_FIELD	*fields;
+  MEM_ROOT	field_alloc;
+  my_ulonglong affected_rows;
+  my_ulonglong insert_id;		/* id if insert on table with NEXTNR */
+  my_ulonglong extra_info;		/* Not used */
+  unsigned long thread_id;		/* Id for connection in server */
+  unsigned long packet_length;
+  unsigned int	port;
+  unsigned long client_flag,server_capabilities;
+  unsigned int	protocol_version;
+  unsigned int	field_count;
+  unsigned int 	server_status;
+  unsigned int  server_language;
+  unsigned int	warning_count;
+  struct st_mysql_options options;
+  enum mysql_status status;
+  my_bool	free_me;		/* If free in mysql_close */
+  my_bool	reconnect;		/* set to 1 if automatic reconnect */
+
+  /* session-wide random string */
+  char	        scramble[SCRAMBLE_LENGTH+1];
+
+ /*
+   Set if this is the original connection, not a master or a slave we have
+   added though mysql_rpl_probe() or mysql_set_master()/ mysql_add_slave()
+ */
+  my_bool rpl_pivot;
+  /*
+    Pointers to the master, and the next slave connections, points to
+    itself if lone connection.
+  */
+  struct st_mysql* master, *next_slave;
+
+  struct st_mysql* last_used_slave; /* needed for round-robin slave pick */
+ /* needed for send/read/store/use result to work correctly with replication */
+  struct st_mysql* last_used_con;
+
+  LIST  *stmts;                     /* list of all statements */
+  const struct st_mysql_methods *methods;
+  void *thd;
+  /*
+    Points to boolean flag in MYSQL_RES  or MYSQL_STMT. We set this flag 
+    from mysql_stmt_close if close had to cancel result set of this object.
+  */
+  my_bool *unbuffered_fetch_owner;
+#if defined(EMBEDDED_LIBRARY) || defined(EMBEDDED_LIBRARY_COMPATIBLE) || MYSQL_VERSION_ID >= 50100
+  /* needed for embedded server - no net buffer to store the 'info' */
+  char *info_buffer;
+#endif
+} MYSQL;
+
+typedef struct st_mysql_res {
+  my_ulonglong row_count;
+  MYSQL_FIELD	*fields;
+  MYSQL_DATA	*data;
+  MYSQL_ROWS	*data_cursor;
+  unsigned long *lengths;		/* column lengths of current row */
+  MYSQL		*handle;		/* for unbuffered reads */
+  MEM_ROOT	field_alloc;
+  unsigned int	field_count, current_field;
+  MYSQL_ROW	row;			/* If unbuffered read */
+  MYSQL_ROW	current_row;		/* buffer to current row */
+  my_bool	eof;			/* Used by mysql_fetch_row */
+  /* mysql_stmt_close() had to cancel this result */
+  my_bool       unbuffered_fetch_cancelled;  
+  const struct st_mysql_methods *methods;
+} MYSQL_RES;
+
+#define MAX_MYSQL_MANAGER_ERR 256  
+#define MAX_MYSQL_MANAGER_MSG 256
+
+#define MANAGER_OK           200
+#define MANAGER_INFO         250
+#define MANAGER_ACCESS       401
+#define MANAGER_CLIENT_ERR   450
+#define MANAGER_INTERNAL_ERR 500
+
+#if !defined(MYSQL_SERVER) && !defined(MYSQL_CLIENT)
+#define MYSQL_CLIENT
+#endif
+
+
+typedef struct st_mysql_manager
+{
+  NET net;
+  char *host,*user,*passwd;
+  unsigned int port;
+  my_bool free_me;
+  my_bool eof;
+  int cmd_status;
+  int last_errno;
+  char* net_buf,*net_buf_pos,*net_data_end;
+  int net_buf_size;
+  char last_error[MAX_MYSQL_MANAGER_ERR];
+} MYSQL_MANAGER;
+
+typedef struct st_mysql_parameters
+{
+  unsigned long *p_max_allowed_packet;
+  unsigned long *p_net_buffer_length;
+} MYSQL_PARAMETERS;
+
+#if !defined(MYSQL_SERVER) && !defined(EMBEDDED_LIBRARY)
+#define max_allowed_packet (*mysql_get_parameters()->p_max_allowed_packet)
+#define net_buffer_length (*mysql_get_parameters()->p_net_buffer_length)
+#endif
+
+/*
+  Set up and bring down the server; to ensure that applications will
+  work when linked against either the standard client library or the
+  embedded server library, these functions should be called.
+*/
+int STDCALL mysql_server_init(int argc, char **argv, char **groups);
+void STDCALL mysql_server_end(void);
+/*
+  mysql_server_init/end need to be called when using libmysqld or
+  libmysqlclient (exactly, mysql_server_init() is called by mysql_init() so
+  you don't need to call it explicitely; but you need to call
+  mysql_server_end() to free memory). The names are a bit misleading
+  (mysql_SERVER* to be used when using libmysqlCLIENT). So we add more general
+  names which suit well whether you're using libmysqld or libmysqlclient. We
+  intend to promote these aliases over the mysql_server* ones.
+*/
+#define mysql_library_init mysql_server_init
+#define mysql_library_end mysql_server_end
+
+MYSQL_PARAMETERS *STDCALL mysql_get_parameters(void);
+
+/*
+  Set up and bring down a thread; these function should be called
+  for each thread in an application which opens at least one MySQL
+  connection.  All uses of the connection(s) should be between these
+  function calls.
+*/
+my_bool STDCALL mysql_thread_init(void);
+void STDCALL mysql_thread_end(void);
+
+/*
+  Functions to get information from the MYSQL and MYSQL_RES structures
+  Should definitely be used if one uses shared libraries.
+*/
+
+my_ulonglong STDCALL mysql_num_rows(MYSQL_RES *res);
+unsigned int STDCALL mysql_num_fields(MYSQL_RES *res);
+my_bool STDCALL mysql_eof(MYSQL_RES *res);
+MYSQL_FIELD *STDCALL mysql_fetch_field_direct(MYSQL_RES *res,
+					      unsigned int fieldnr);
+MYSQL_FIELD * STDCALL mysql_fetch_fields(MYSQL_RES *res);
+MYSQL_ROW_OFFSET STDCALL mysql_row_tell(MYSQL_RES *res);
+MYSQL_FIELD_OFFSET STDCALL mysql_field_tell(MYSQL_RES *res);
+
+unsigned int STDCALL mysql_field_count(MYSQL *mysql);
+my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql);
+my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql);
+unsigned int STDCALL mysql_errno(MYSQL *mysql);
+const char * STDCALL mysql_error(MYSQL *mysql);
+const char *STDCALL mysql_sqlstate(MYSQL *mysql);
+unsigned int STDCALL mysql_warning_count(MYSQL *mysql);
+const char * STDCALL mysql_info(MYSQL *mysql);
+unsigned long STDCALL mysql_thread_id(MYSQL *mysql);
+const char * STDCALL mysql_character_set_name(MYSQL *mysql);
+int          STDCALL mysql_set_character_set(MYSQL *mysql, const char *csname);
+
+MYSQL *		STDCALL mysql_init(MYSQL *mysql);
+my_bool		STDCALL mysql_ssl_set(MYSQL *mysql, const char *key,
+				      const char *cert, const char *ca,
+				      const char *capath, const char *cipher);
+const char *    STDCALL mysql_get_ssl_cipher(MYSQL *mysql);
+my_bool		STDCALL mysql_change_user(MYSQL *mysql, const char *user, 
+					  const char *passwd, const char *db);
+MYSQL *		STDCALL mysql_real_connect(MYSQL *mysql, const char *host,
+					   const char *user,
+					   const char *passwd,
+					   const char *db,
+					   unsigned int port,
+					   const char *unix_socket,
+					   unsigned long clientflag);
+int		STDCALL mysql_select_db(MYSQL *mysql, const char *db);
+int		STDCALL mysql_query(MYSQL *mysql, const char *q);
+int		STDCALL mysql_send_query(MYSQL *mysql, const char *q,
+					 unsigned long length);
+int		STDCALL mysql_real_query(MYSQL *mysql, const char *q,
+					unsigned long length);
+MYSQL_RES *     STDCALL mysql_store_result(MYSQL *mysql);
+MYSQL_RES *     STDCALL mysql_use_result(MYSQL *mysql);
+
+/* perform query on master */
+my_bool		STDCALL mysql_master_query(MYSQL *mysql, const char *q,
+					   unsigned long length);
+my_bool		STDCALL mysql_master_send_query(MYSQL *mysql, const char *q,
+						unsigned long length);
+/* perform query on slave */  
+my_bool		STDCALL mysql_slave_query(MYSQL *mysql, const char *q,
+					  unsigned long length);
+my_bool		STDCALL mysql_slave_send_query(MYSQL *mysql, const char *q,
+					       unsigned long length);
+void        STDCALL mysql_get_character_set_info(MYSQL *mysql,
+                           MY_CHARSET_INFO *charset);
+
+/* local infile support */
+
+#define LOCAL_INFILE_ERROR_LEN 512
+
+void
+mysql_set_local_infile_handler(MYSQL *mysql,
+                               int (*local_infile_init)(void **, const char *,
+                            void *),
+                               int (*local_infile_read)(void *, char *,
+							unsigned int),
+                               void (*local_infile_end)(void *),
+                               int (*local_infile_error)(void *, char*,
+							 unsigned int),
+                               void *);
+
+void
+mysql_set_local_infile_default(MYSQL *mysql);
+
+
+/*
+  enable/disable parsing of all queries to decide if they go on master or
+  slave
+*/
+void            STDCALL mysql_enable_rpl_parse(MYSQL* mysql);
+void            STDCALL mysql_disable_rpl_parse(MYSQL* mysql);
+/* get the value of the parse flag */  
+int             STDCALL mysql_rpl_parse_enabled(MYSQL* mysql);
+
+/*  enable/disable reads from master */
+void            STDCALL mysql_enable_reads_from_master(MYSQL* mysql);
+void            STDCALL mysql_disable_reads_from_master(MYSQL* mysql);
+/* get the value of the master read flag */  
+my_bool		STDCALL mysql_reads_from_master_enabled(MYSQL* mysql);
+
+enum mysql_rpl_type     STDCALL mysql_rpl_query_type(const char* q, int len);  
+
+/* discover the master and its slaves */  
+my_bool		STDCALL mysql_rpl_probe(MYSQL* mysql);
+
+/* set the master, close/free the old one, if it is not a pivot */
+int             STDCALL mysql_set_master(MYSQL* mysql, const char* host,
+					 unsigned int port,
+					 const char* user,
+					 const char* passwd);
+int             STDCALL mysql_add_slave(MYSQL* mysql, const char* host,
+					unsigned int port,
+					const char* user,
+					const char* passwd);
+
+int		STDCALL mysql_shutdown(MYSQL *mysql,
+                                       enum mysql_enum_shutdown_level
+                                       shutdown_level);
+int		STDCALL mysql_dump_debug_info(MYSQL *mysql);
+int		STDCALL mysql_refresh(MYSQL *mysql,
+				     unsigned int refresh_options);
+int		STDCALL mysql_kill(MYSQL *mysql,unsigned long pid);
+int		STDCALL mysql_set_server_option(MYSQL *mysql,
+						enum enum_mysql_set_option
+						option);
+int		STDCALL mysql_ping(MYSQL *mysql);
+const char *	STDCALL mysql_stat(MYSQL *mysql);
+const char *	STDCALL mysql_get_server_info(MYSQL *mysql);
+const char *	STDCALL mysql_get_client_info(void);
+unsigned long	STDCALL mysql_get_client_version(void);
+const char *	STDCALL mysql_get_host_info(MYSQL *mysql);
+unsigned long	STDCALL mysql_get_server_version(MYSQL *mysql);
+unsigned int	STDCALL mysql_get_proto_info(MYSQL *mysql);
+MYSQL_RES *	STDCALL mysql_list_dbs(MYSQL *mysql,const char *wild);
+MYSQL_RES *	STDCALL mysql_list_tables(MYSQL *mysql,const char *wild);
+MYSQL_RES *	STDCALL mysql_list_processes(MYSQL *mysql);
+int		STDCALL mysql_options(MYSQL *mysql,enum mysql_option option,
+				      const char *arg);
+void		STDCALL mysql_free_result(MYSQL_RES *result);
+void		STDCALL mysql_data_seek(MYSQL_RES *result,
+					my_ulonglong offset);
+MYSQL_ROW_OFFSET STDCALL mysql_row_seek(MYSQL_RES *result,
+						MYSQL_ROW_OFFSET offset);
+MYSQL_FIELD_OFFSET STDCALL mysql_field_seek(MYSQL_RES *result,
+					   MYSQL_FIELD_OFFSET offset);
+MYSQL_ROW	STDCALL mysql_fetch_row(MYSQL_RES *result);
+unsigned long * STDCALL mysql_fetch_lengths(MYSQL_RES *result);
+MYSQL_FIELD *	STDCALL mysql_fetch_field(MYSQL_RES *result);
+MYSQL_RES *     STDCALL mysql_list_fields(MYSQL *mysql, const char *table,
+					  const char *wild);
+unsigned long	STDCALL mysql_escape_string(char *to,const char *from,
+					    unsigned long from_length);
+unsigned long	STDCALL mysql_hex_string(char *to,const char *from,
+                                         unsigned long from_length);
+unsigned long STDCALL mysql_real_escape_string(MYSQL *mysql,
+					       char *to,const char *from,
+					       unsigned long length);
+void		STDCALL mysql_debug(const char *debug);
+void 		STDCALL myodbc_remove_escape(MYSQL *mysql,char *name);
+unsigned int	STDCALL mysql_thread_safe(void);
+my_bool		STDCALL mysql_embedded(void);
+MYSQL_MANAGER*  STDCALL mysql_manager_init(MYSQL_MANAGER* con);  
+MYSQL_MANAGER*  STDCALL mysql_manager_connect(MYSQL_MANAGER* con,
+					      const char* host,
+					      const char* user,
+					      const char* passwd,
+					      unsigned int port);
+void            STDCALL mysql_manager_close(MYSQL_MANAGER* con);
+int             STDCALL mysql_manager_command(MYSQL_MANAGER* con,
+						const char* cmd, int cmd_len);
+int             STDCALL mysql_manager_fetch_line(MYSQL_MANAGER* con,
+						  char* res_buf,
+						 int res_buf_size);
+my_bool         STDCALL mysql_read_query_result(MYSQL *mysql);
+
+
+/*
+  The following definitions are added for the enhanced 
+  client-server protocol
+*/
+
+/* statement state */
+enum enum_mysql_stmt_state
+{
+  MYSQL_STMT_INIT_DONE= 1, MYSQL_STMT_PREPARE_DONE, MYSQL_STMT_EXECUTE_DONE,
+  MYSQL_STMT_FETCH_DONE
+};
+
+
+/*
+  This structure is used to define bind information, and
+  internally by the client library.
+  Public members with their descriptions are listed below
+  (conventionally `On input' refers to the binds given to
+  mysql_stmt_bind_param, `On output' refers to the binds given
+  to mysql_stmt_bind_result):
+
+  buffer_type    - One of the MYSQL_* types, used to describe
+                   the host language type of buffer.
+                   On output: if column type is different from
+                   buffer_type, column value is automatically converted
+                   to buffer_type before it is stored in the buffer.
+  buffer         - On input: points to the buffer with input data.
+                   On output: points to the buffer capable to store
+                   output data.
+                   The type of memory pointed by buffer must correspond
+                   to buffer_type. See the correspondence table in
+                   the comment to mysql_stmt_bind_param.
+
+  The two above members are mandatory for any kind of bind.
+
+  buffer_length  - the length of the buffer. You don't have to set
+                   it for any fixed length buffer: float, double,
+                   int, etc. It must be set however for variable-length
+                   types, such as BLOBs or STRINGs.
+
+  length         - On input: in case when lengths of input values
+                   are different for each execute, you can set this to
+                   point at a variable containining value length. This
+                   way the value length can be different in each execute.
+                   If length is not NULL, buffer_length is not used.
+                   Note, length can even point at buffer_length if
+                   you keep bind structures around while fetching:
+                   this way you can change buffer_length before
+                   each execution, everything will work ok.
+                   On output: if length is set, mysql_stmt_fetch will
+                   write column length into it.
+
+  is_null        - On input: points to a boolean variable that should
+                   be set to TRUE for NULL values.
+                   This member is useful only if your data may be
+                   NULL in some but not all cases.
+                   If your data is never NULL, is_null should be set to 0.
+                   If your data is always NULL, set buffer_type
+                   to MYSQL_TYPE_NULL, and is_null will not be used.
+
+  is_unsigned    - On input: used to signify that values provided for one
+                   of numeric types are unsigned.
+                   On output describes signedness of the output buffer.
+                   If, taking into account is_unsigned flag, column data
+                   is out of range of the output buffer, data for this column
+                   is regarded truncated. Note that this has no correspondence
+                   to the sign of result set column, if you need to find it out
+                   use mysql_stmt_result_metadata.
+  error          - where to write a truncation error if it is present.
+                   possible error value is:
+                   0  no truncation
+                   1  value is out of range or buffer is too small
+
+  Please note that MYSQL_BIND also has internals members.
+*/
+
+typedef struct st_mysql_bind
+{
+  unsigned long	*length;          /* output length pointer */
+  my_bool       *is_null;	  /* Pointer to null indicator */
+  void		*buffer;	  /* buffer to get/put data */
+  /* set this if you want to track data truncations happened during fetch */
+  my_bool       *error;
+  enum enum_field_types buffer_type;	/* buffer type */
+  /* output buffer length, must be set when fetching str/binary */
+  unsigned long buffer_length;
+  unsigned char *row_ptr;         /* for the current data position */
+  unsigned long offset;           /* offset position for char/binary fetch */
+  unsigned long	length_value;     /* Used if length is 0 */
+  unsigned int	param_number;	  /* For null count and error messages */
+  unsigned int  pack_length;	  /* Internal length for packed data */
+  my_bool       error_value;      /* used if error is 0 */
+  my_bool       is_unsigned;      /* set if integer type is unsigned */
+  my_bool	long_data_used;	  /* If used with mysql_send_long_data */
+  my_bool	is_null_value;    /* Used if is_null is 0 */
+  void (*store_param_func)(NET *net, struct st_mysql_bind *param);
+  void (*fetch_result)(struct st_mysql_bind *, MYSQL_FIELD *,
+                       unsigned char **row);
+  void (*skip_result)(struct st_mysql_bind *, MYSQL_FIELD *,
+		      unsigned char **row);
+} MYSQL_BIND;
+
+
+/* statement handler */
+typedef struct st_mysql_stmt
+{
+  MEM_ROOT       mem_root;             /* root allocations */
+  LIST           list;                 /* list to keep track of all stmts */
+  MYSQL          *mysql;               /* connection handle */
+  MYSQL_BIND     *params;              /* input parameters */
+  MYSQL_BIND     *bind;                /* output parameters */
+  MYSQL_FIELD    *fields;              /* result set metadata */
+  MYSQL_DATA     result;               /* cached result set */
+  MYSQL_ROWS     *data_cursor;         /* current row in cached result */
+  /* copy of mysql->affected_rows after statement execution */
+  my_ulonglong   affected_rows;
+  my_ulonglong   insert_id;            /* copy of mysql->insert_id */
+  /*
+    mysql_stmt_fetch() calls this function to fetch one row (it's different
+    for buffered, unbuffered and cursor fetch).
+  */
+  int            (*read_row_func)(struct st_mysql_stmt *stmt, 
+                                  unsigned char **row);
+  unsigned long	 stmt_id;	       /* Id for prepared statement */
+  unsigned long  flags;                /* i.e. type of cursor to open */
+  unsigned long  prefetch_rows;        /* number of rows per one COM_FETCH */
+  /*
+    Copied from mysql->server_status after execute/fetch to know
+    server-side cursor status for this statement.
+  */
+  unsigned int   server_status;
+  unsigned int	 last_errno;	       /* error code */
+  unsigned int   param_count;          /* input parameter count */
+  unsigned int   field_count;          /* number of columns in result set */
+  enum enum_mysql_stmt_state state;    /* statement state */
+  char		 last_error[MYSQL_ERRMSG_SIZE]; /* error message */
+  char		 sqlstate[SQLSTATE_LENGTH+1];
+  /* Types of input parameters should be sent to server */
+  my_bool        send_types_to_server;
+  my_bool        bind_param_done;      /* input buffers were supplied */
+  unsigned char  bind_result_done;     /* output buffers were supplied */
+  /* mysql_stmt_close() had to cancel this result */
+  my_bool       unbuffered_fetch_cancelled;  
+  /*
+    Is set to true if we need to calculate field->max_length for 
+    metadata fields when doing mysql_stmt_store_result.
+  */
+  my_bool       update_max_length;     
+} MYSQL_STMT;
+
+enum enum_stmt_attr_type
+{
+  /*
+    When doing mysql_stmt_store_result calculate max_length attribute
+    of statement metadata. This is to be consistent with the old API, 
+    where this was done automatically.
+    In the new API we do that only by request because it slows down
+    mysql_stmt_store_result sufficiently.
+  */
+  STMT_ATTR_UPDATE_MAX_LENGTH,
+  /*
+    unsigned long with combination of cursor flags (read only, for update,
+    etc)
+  */
+  STMT_ATTR_CURSOR_TYPE,
+  /*
+    Amount of rows to retrieve from server per one fetch if using cursors.
+    Accepts unsigned long attribute in the range 1 - ulong_max
+  */
+  STMT_ATTR_PREFETCH_ROWS
+};
+
+
+typedef struct st_mysql_methods
+{
+  my_bool (*read_query_result)(MYSQL *mysql);
+  my_bool (*advanced_command)(MYSQL *mysql,
+			      enum enum_server_command command,
+			      const char *header,
+			      unsigned long header_length,
+			      const char *arg,
+			      unsigned long arg_length,
+			      my_bool skip_check,
+                              MYSQL_STMT *stmt);
+  MYSQL_DATA *(*read_rows)(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
+			   unsigned int fields);
+  MYSQL_RES * (*use_result)(MYSQL *mysql);
+  void (*fetch_lengths)(unsigned long *to, 
+			MYSQL_ROW column, unsigned int field_count);
+  void (*flush_use_result)(MYSQL *mysql);
+#if !defined(MYSQL_SERVER) || defined(EMBEDDED_LIBRARY)
+  MYSQL_FIELD * (*list_fields)(MYSQL *mysql);
+  my_bool (*read_prepare_result)(MYSQL *mysql, MYSQL_STMT *stmt);
+  int (*stmt_execute)(MYSQL_STMT *stmt);
+  int (*read_binary_rows)(MYSQL_STMT *stmt);
+  int (*unbuffered_fetch)(MYSQL *mysql, char **row);
+  void (*free_embedded_thd)(MYSQL *mysql);
+  const char *(*read_statistics)(MYSQL *mysql);
+  my_bool (*next_result)(MYSQL *mysql);
+  int (*read_change_user_result)(MYSQL *mysql, char *buff, const char *passwd);
+  int (*read_rows_from_cursor)(MYSQL_STMT *stmt);
+#endif
+} MYSQL_METHODS;
+
+
+MYSQL_STMT * STDCALL mysql_stmt_init(MYSQL *mysql);
+int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query,
+                               unsigned long length);
+int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt);
+int STDCALL mysql_stmt_fetch(MYSQL_STMT *stmt);
+int STDCALL mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind_arg, 
+                                    unsigned int column,
+                                    unsigned long offset);
+int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt);
+unsigned long STDCALL mysql_stmt_param_count(MYSQL_STMT * stmt);
+my_bool STDCALL mysql_stmt_attr_set(MYSQL_STMT *stmt,
+                                    enum enum_stmt_attr_type attr_type,
+                                    const void *attr);
+my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt,
+                                    enum enum_stmt_attr_type attr_type,
+                                    void *attr);
+my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT * stmt, MYSQL_BIND * bnd);
+my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bnd);
+my_bool STDCALL mysql_stmt_close(MYSQL_STMT * stmt);
+my_bool STDCALL mysql_stmt_reset(MYSQL_STMT * stmt);
+my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt);
+my_bool STDCALL mysql_stmt_send_long_data(MYSQL_STMT *stmt, 
+                                          unsigned int param_number,
+                                          const char *data, 
+                                          unsigned long length);
+MYSQL_RES *STDCALL mysql_stmt_result_metadata(MYSQL_STMT *stmt);
+MYSQL_RES *STDCALL mysql_stmt_param_metadata(MYSQL_STMT *stmt);
+unsigned int STDCALL mysql_stmt_errno(MYSQL_STMT * stmt);
+const char *STDCALL mysql_stmt_error(MYSQL_STMT * stmt);
+const char *STDCALL mysql_stmt_sqlstate(MYSQL_STMT * stmt);
+MYSQL_ROW_OFFSET STDCALL mysql_stmt_row_seek(MYSQL_STMT *stmt, 
+                                             MYSQL_ROW_OFFSET offset);
+MYSQL_ROW_OFFSET STDCALL mysql_stmt_row_tell(MYSQL_STMT *stmt);
+void STDCALL mysql_stmt_data_seek(MYSQL_STMT *stmt, my_ulonglong offset);
+my_ulonglong STDCALL mysql_stmt_num_rows(MYSQL_STMT *stmt);
+my_ulonglong STDCALL mysql_stmt_affected_rows(MYSQL_STMT *stmt);
+my_ulonglong STDCALL mysql_stmt_insert_id(MYSQL_STMT *stmt);
+unsigned int STDCALL mysql_stmt_field_count(MYSQL_STMT *stmt);
+
+my_bool STDCALL mysql_commit(MYSQL * mysql);
+my_bool STDCALL mysql_rollback(MYSQL * mysql);
+my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode);
+my_bool STDCALL mysql_more_results(MYSQL *mysql);
+int STDCALL mysql_next_result(MYSQL *mysql);
+void STDCALL mysql_close(MYSQL *sock);
+
+
+/* status return codes */
+#define MYSQL_NO_DATA        100
+#define MYSQL_DATA_TRUNCATED 101
+
+#define mysql_reload(mysql) mysql_refresh((mysql),REFRESH_GRANT)
+
+#ifdef USE_OLD_FUNCTIONS
+MYSQL *		STDCALL mysql_connect(MYSQL *mysql, const char *host,
+				      const char *user, const char *passwd);
+int		STDCALL mysql_create_db(MYSQL *mysql, const char *DB);
+int		STDCALL mysql_drop_db(MYSQL *mysql, const char *DB);
+#define	 mysql_reload(mysql) mysql_refresh((mysql),REFRESH_GRANT)
+#endif
+#define HAVE_MYSQL_REAL_CONNECT
+
+/*
+  The following functions are mainly exported because of mysqlbinlog;
+  They are not for general usage
+*/
+
+#define simple_command(mysql, command, arg, length, skip_check) \
+  (*(mysql)->methods->advanced_command)(mysql, command, NullS,  \
+                                        0, arg, length, skip_check, NULL)
+#define stmt_command(mysql, command, arg, length, stmt) \
+  (*(mysql)->methods->advanced_command)(mysql, command, NullS,  \
+                                        0, arg, length, 1, stmt)
+
+#ifdef __NETWARE__
+
+// GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some paltform
+#if defined( __GNUC__ )
+#pragma pack()
+#else
+#pragma pack(pop)
+#endif 
+
+#endif
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif /* _mysql_h */
diff --git a/dep/include/mysql/mysql_com.h b/dep/include/mysql/mysql_com.h
new file mode 100644
index 00000000000..94b34c1c3f0
--- /dev/null
+++ b/dep/include/mysql/mysql_com.h
@@ -0,0 +1,467 @@
+/* Copyright (C) 2000 MySQL AB
+
+   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; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+/*
+** Common definition between mysql server & client
+*/
+
+#ifndef _mysql_com_h
+#define _mysql_com_h
+
+#define NAME_LEN	64		/* Field/table name length */
+#define HOSTNAME_LENGTH 60
+#define USERNAME_LENGTH 16
+#define SERVER_VERSION_LENGTH 60
+#define SQLSTATE_LENGTH 5
+
+/*
+  USER_HOST_BUFF_SIZE -- length of string buffer, that is enough to contain
+  username and hostname parts of the user identifier with trailing zero in
+  MySQL standard format:
+  user_name_part@host_name_part\0
+*/
+#define USER_HOST_BUFF_SIZE HOSTNAME_LENGTH + USERNAME_LENGTH + 2
+
+#define LOCAL_HOST	"localhost"
+#define LOCAL_HOST_NAMEDPIPE "."
+
+
+#if defined(__WIN__) && !defined( _CUSTOMCONFIG_)
+#define MYSQL_NAMEDPIPE "MySQL"
+#define MYSQL_SERVICENAME "MySQL"
+#endif /* __WIN__ */
+
+/*
+  You should add new commands to the end of this list, otherwise old
+  servers won't be able to handle them as 'unsupported'.
+*/
+
+enum enum_server_command
+{
+  COM_SLEEP, COM_QUIT, COM_INIT_DB, COM_QUERY, COM_FIELD_LIST,
+  COM_CREATE_DB, COM_DROP_DB, COM_REFRESH, COM_SHUTDOWN, COM_STATISTICS,
+  COM_PROCESS_INFO, COM_CONNECT, COM_PROCESS_KILL, COM_DEBUG, COM_PING,
+  COM_TIME, COM_DELAYED_INSERT, COM_CHANGE_USER, COM_BINLOG_DUMP,
+  COM_TABLE_DUMP, COM_CONNECT_OUT, COM_REGISTER_SLAVE,
+  COM_STMT_PREPARE, COM_STMT_EXECUTE, COM_STMT_SEND_LONG_DATA, COM_STMT_CLOSE,
+  COM_STMT_RESET, COM_SET_OPTION, COM_STMT_FETCH,
+  /* don't forget to update const char *command_name[] in sql_parse.cc */
+
+  /* Must be last */
+  COM_END
+};
+
+
+/*
+  Length of random string sent by server on handshake; this is also length of
+  obfuscated password, recieved from client
+*/
+#define SCRAMBLE_LENGTH 20
+#define SCRAMBLE_LENGTH_323 8
+/* length of password stored in the db: new passwords are preceeded with '*' */
+#define SCRAMBLED_PASSWORD_CHAR_LENGTH (SCRAMBLE_LENGTH*2+1)
+#define SCRAMBLED_PASSWORD_CHAR_LENGTH_323 (SCRAMBLE_LENGTH_323*2)
+
+
+#define NOT_NULL_FLAG	1		/* Field can't be NULL */
+#define PRI_KEY_FLAG	2		/* Field is part of a primary key */
+#define UNIQUE_KEY_FLAG 4		/* Field is part of a unique key */
+#define MULTIPLE_KEY_FLAG 8		/* Field is part of a key */
+#define BLOB_FLAG	16		/* Field is a blob */
+#define UNSIGNED_FLAG	32		/* Field is unsigned */
+#define ZEROFILL_FLAG	64		/* Field is zerofill */
+#define BINARY_FLAG	128		/* Field is binary   */
+
+/* The following are only sent to new clients */
+#define ENUM_FLAG	256		/* field is an enum */
+#define AUTO_INCREMENT_FLAG 512		/* field is a autoincrement field */
+#define TIMESTAMP_FLAG	1024		/* Field is a timestamp */
+#define SET_FLAG	2048		/* field is a set */
+#define NO_DEFAULT_VALUE_FLAG 4096	/* Field doesn't have default value */
+#define NUM_FLAG	32768		/* Field is num (for clients) */
+#define PART_KEY_FLAG	16384		/* Intern; Part of some key */
+#define GROUP_FLAG	32768		/* Intern: Group field */
+#define UNIQUE_FLAG	65536		/* Intern: Used by sql_yacc */
+#define BINCMP_FLAG	131072		/* Intern: Used by sql_yacc */
+
+#define REFRESH_GRANT		1	/* Refresh grant tables */
+#define REFRESH_LOG		2	/* Start on new log file */
+#define REFRESH_TABLES		4	/* close all tables */
+#define REFRESH_HOSTS		8	/* Flush host cache */
+#define REFRESH_STATUS		16	/* Flush status variables */
+#define REFRESH_THREADS		32	/* Flush thread cache */
+#define REFRESH_SLAVE           64      /* Reset master info and restart slave
+					   thread */
+#define REFRESH_MASTER          128     /* Remove all bin logs in the index
+					   and truncate the index */
+
+/* The following can't be set with mysql_refresh() */
+#define REFRESH_READ_LOCK	16384	/* Lock tables for read */
+#define REFRESH_FAST		32768	/* Intern flag */
+
+/* RESET (remove all queries) from query cache */
+#define REFRESH_QUERY_CACHE	65536
+#define REFRESH_QUERY_CACHE_FREE 0x20000L /* pack query cache */
+#define REFRESH_DES_KEY_FILE	0x40000L
+#define REFRESH_USER_RESOURCES	0x80000L
+
+#define CLIENT_LONG_PASSWORD	1	/* new more secure passwords */
+#define CLIENT_FOUND_ROWS	2	/* Found instead of affected rows */
+#define CLIENT_LONG_FLAG	4	/* Get all column flags */
+#define CLIENT_CONNECT_WITH_DB	8	/* One can specify db on connect */
+#define CLIENT_NO_SCHEMA	16	/* Don't allow database.table.column */
+#define CLIENT_COMPRESS		32	/* Can use compression protocol */
+#define CLIENT_ODBC		64	/* Odbc client */
+#define CLIENT_LOCAL_FILES	128	/* Can use LOAD DATA LOCAL */
+#define CLIENT_IGNORE_SPACE	256	/* Ignore spaces before '(' */
+#define CLIENT_PROTOCOL_41	512	/* New 4.1 protocol */
+#define CLIENT_INTERACTIVE	1024	/* This is an interactive client */
+#define CLIENT_SSL              2048	/* Switch to SSL after handshake */
+#define CLIENT_IGNORE_SIGPIPE   4096    /* IGNORE sigpipes */
+#define CLIENT_TRANSACTIONS	8192	/* Client knows about transactions */
+#define CLIENT_RESERVED         16384   /* Old flag for 4.1 protocol  */
+#define CLIENT_SECURE_CONNECTION 32768  /* New 4.1 authentication */
+#define CLIENT_MULTI_STATEMENTS (1UL << 16) /* Enable/disable multi-stmt support */
+#define CLIENT_MULTI_RESULTS    (1UL << 17) /* Enable/disable multi-results */
+
+#define CLIENT_SSL_VERIFY_SERVER_CERT (1UL << 30)
+#define CLIENT_REMEMBER_OPTIONS (1UL << 31)
+
+#define SERVER_STATUS_IN_TRANS     1	/* Transaction has started */
+#define SERVER_STATUS_AUTOCOMMIT   2	/* Server in auto_commit mode */
+#define SERVER_MORE_RESULTS_EXISTS 8    /* Multi query - next query exists */
+#define SERVER_QUERY_NO_GOOD_INDEX_USED 16
+#define SERVER_QUERY_NO_INDEX_USED      32
+/*
+  The server was able to fulfill the clients request and opened a
+  read-only non-scrollable cursor for a query. This flag comes
+  in reply to COM_STMT_EXECUTE and COM_STMT_FETCH commands.
+*/
+#define SERVER_STATUS_CURSOR_EXISTS 64
+/*
+  This flag is sent when a read-only cursor is exhausted, in reply to
+  COM_STMT_FETCH command.
+*/
+#define SERVER_STATUS_LAST_ROW_SENT 128
+#define SERVER_STATUS_DB_DROPPED        256 /* A database was dropped */
+#define SERVER_STATUS_NO_BACKSLASH_ESCAPES 512
+
+#define MYSQL_ERRMSG_SIZE	512
+#define NET_READ_TIMEOUT	30		/* Timeout on read */
+#define NET_WRITE_TIMEOUT	60		/* Timeout on write */
+#define NET_WAIT_TIMEOUT	8*60*60		/* Wait for new query */
+
+#define ONLY_KILL_QUERY         1
+
+struct st_vio;					/* Only C */
+typedef struct st_vio Vio;
+
+#define MAX_TINYINT_WIDTH       3       /* Max width for a TINY w.o. sign */
+#define MAX_SMALLINT_WIDTH      5       /* Max width for a SHORT w.o. sign */
+#define MAX_MEDIUMINT_WIDTH     8       /* Max width for a INT24 w.o. sign */
+#define MAX_INT_WIDTH           10      /* Max width for a LONG w.o. sign */
+#define MAX_BIGINT_WIDTH        20      /* Max width for a LONGLONG */
+#define MAX_CHAR_WIDTH		255	/* Max length for a CHAR colum */
+#define MAX_BLOB_WIDTH		8192	/* Default width for blob */
+
+typedef struct st_net {
+#if !defined(CHECK_EMBEDDED_DIFFERENCES) || !defined(EMBEDDED_LIBRARY)
+  Vio* vio;
+  unsigned char *buff,*buff_end,*write_pos,*read_pos;
+  my_socket fd;					/* For Perl DBI/dbd */
+  unsigned long max_packet,max_packet_size;
+  unsigned int pkt_nr,compress_pkt_nr;
+  unsigned int write_timeout, read_timeout, retry_count;
+  int fcntl;
+  my_bool compress;
+  /*
+    The following variable is set if we are doing several queries in one
+    command ( as in LOAD TABLE ... FROM MASTER ),
+    and do not want to confuse the client with OK at the wrong time
+  */
+  unsigned long remain_in_buf,length, buf_length, where_b;
+  unsigned int *return_status;
+  unsigned char reading_or_writing;
+  char save_char;
+  my_bool no_send_ok;  /* For SPs and other things that do multiple stmts */
+  my_bool no_send_eof; /* For SPs' first version read-only cursors */
+  /*
+    Set if OK packet is already sent, and we do not need to send error
+    messages
+  */
+  my_bool no_send_error;
+  /*
+    Pointer to query object in query cache, do not equal NULL (0) for
+    queries in cache that have not stored its results yet
+  */
+#endif
+  char last_error[MYSQL_ERRMSG_SIZE], sqlstate[SQLSTATE_LENGTH+1];
+  unsigned int last_errno;
+  unsigned char error;
+
+  /*
+    'query_cache_query' should be accessed only via query cache
+    functions and methods to maintain proper locking.
+  */
+  gptr query_cache_query;
+
+  my_bool report_error; /* We should report error (we have unreported error) */
+  my_bool return_errno;
+} NET;
+
+#define packet_error (~(unsigned long) 0)
+
+enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
+			MYSQL_TYPE_SHORT,  MYSQL_TYPE_LONG,
+			MYSQL_TYPE_FLOAT,  MYSQL_TYPE_DOUBLE,
+			MYSQL_TYPE_NULL,   MYSQL_TYPE_TIMESTAMP,
+			MYSQL_TYPE_LONGLONG,MYSQL_TYPE_INT24,
+			MYSQL_TYPE_DATE,   MYSQL_TYPE_TIME,
+			MYSQL_TYPE_DATETIME, MYSQL_TYPE_YEAR,
+			MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR,
+			MYSQL_TYPE_BIT,
+                        MYSQL_TYPE_NEWDECIMAL=246,
+			MYSQL_TYPE_ENUM=247,
+			MYSQL_TYPE_SET=248,
+			MYSQL_TYPE_TINY_BLOB=249,
+			MYSQL_TYPE_MEDIUM_BLOB=250,
+			MYSQL_TYPE_LONG_BLOB=251,
+			MYSQL_TYPE_BLOB=252,
+			MYSQL_TYPE_VAR_STRING=253,
+			MYSQL_TYPE_STRING=254,
+			MYSQL_TYPE_GEOMETRY=255
+
+};
+
+/* For backward compatibility */
+#define CLIENT_MULTI_QUERIES    CLIENT_MULTI_STATEMENTS    
+#define FIELD_TYPE_DECIMAL     MYSQL_TYPE_DECIMAL
+#define FIELD_TYPE_NEWDECIMAL  MYSQL_TYPE_NEWDECIMAL
+#define FIELD_TYPE_TINY        MYSQL_TYPE_TINY
+#define FIELD_TYPE_SHORT       MYSQL_TYPE_SHORT
+#define FIELD_TYPE_LONG        MYSQL_TYPE_LONG
+#define FIELD_TYPE_FLOAT       MYSQL_TYPE_FLOAT
+#define FIELD_TYPE_DOUBLE      MYSQL_TYPE_DOUBLE
+#define FIELD_TYPE_NULL        MYSQL_TYPE_NULL
+#define FIELD_TYPE_TIMESTAMP   MYSQL_TYPE_TIMESTAMP
+#define FIELD_TYPE_LONGLONG    MYSQL_TYPE_LONGLONG
+#define FIELD_TYPE_INT24       MYSQL_TYPE_INT24
+#define FIELD_TYPE_DATE        MYSQL_TYPE_DATE
+#define FIELD_TYPE_TIME        MYSQL_TYPE_TIME
+#define FIELD_TYPE_DATETIME    MYSQL_TYPE_DATETIME
+#define FIELD_TYPE_YEAR        MYSQL_TYPE_YEAR
+#define FIELD_TYPE_NEWDATE     MYSQL_TYPE_NEWDATE
+#define FIELD_TYPE_ENUM        MYSQL_TYPE_ENUM
+#define FIELD_TYPE_SET         MYSQL_TYPE_SET
+#define FIELD_TYPE_TINY_BLOB   MYSQL_TYPE_TINY_BLOB
+#define FIELD_TYPE_MEDIUM_BLOB MYSQL_TYPE_MEDIUM_BLOB
+#define FIELD_TYPE_LONG_BLOB   MYSQL_TYPE_LONG_BLOB
+#define FIELD_TYPE_BLOB        MYSQL_TYPE_BLOB
+#define FIELD_TYPE_VAR_STRING  MYSQL_TYPE_VAR_STRING
+#define FIELD_TYPE_STRING      MYSQL_TYPE_STRING
+#define FIELD_TYPE_CHAR        MYSQL_TYPE_TINY
+#define FIELD_TYPE_INTERVAL    MYSQL_TYPE_ENUM
+#define FIELD_TYPE_GEOMETRY    MYSQL_TYPE_GEOMETRY
+#define FIELD_TYPE_BIT         MYSQL_TYPE_BIT
+
+
+/* Shutdown/kill enums and constants */ 
+
+/* Bits for THD::killable. */
+#define MYSQL_SHUTDOWN_KILLABLE_CONNECT    (unsigned char)(1 << 0)
+#define MYSQL_SHUTDOWN_KILLABLE_TRANS      (unsigned char)(1 << 1)
+#define MYSQL_SHUTDOWN_KILLABLE_LOCK_TABLE (unsigned char)(1 << 2)
+#define MYSQL_SHUTDOWN_KILLABLE_UPDATE     (unsigned char)(1 << 3)
+
+enum mysql_enum_shutdown_level {
+  /*
+    We want levels to be in growing order of hardness (because we use number
+    comparisons). Note that DEFAULT does not respect the growing property, but
+    it's ok.
+  */
+  SHUTDOWN_DEFAULT = 0,
+  /* wait for existing connections to finish */
+  SHUTDOWN_WAIT_CONNECTIONS= MYSQL_SHUTDOWN_KILLABLE_CONNECT,
+  /* wait for existing trans to finish */
+  SHUTDOWN_WAIT_TRANSACTIONS= MYSQL_SHUTDOWN_KILLABLE_TRANS,
+  /* wait for existing updates to finish (=> no partial MyISAM update) */
+  SHUTDOWN_WAIT_UPDATES= MYSQL_SHUTDOWN_KILLABLE_UPDATE,
+  /* flush InnoDB buffers and other storage engines' buffers*/
+  SHUTDOWN_WAIT_ALL_BUFFERS= (MYSQL_SHUTDOWN_KILLABLE_UPDATE << 1),
+  /* don't flush InnoDB buffers, flush other storage engines' buffers*/
+  SHUTDOWN_WAIT_CRITICAL_BUFFERS= (MYSQL_SHUTDOWN_KILLABLE_UPDATE << 1) + 1,
+  /* Now the 2 levels of the KILL command */
+#if MYSQL_VERSION_ID >= 50000
+  KILL_QUERY= 254,
+#endif
+  KILL_CONNECTION= 255
+};
+
+
+enum enum_cursor_type
+{
+  CURSOR_TYPE_NO_CURSOR= 0,
+  CURSOR_TYPE_READ_ONLY= 1,
+  CURSOR_TYPE_FOR_UPDATE= 2,
+  CURSOR_TYPE_SCROLLABLE= 4
+};
+
+
+/* options for mysql_set_option */
+enum enum_mysql_set_option
+{
+  MYSQL_OPTION_MULTI_STATEMENTS_ON,
+  MYSQL_OPTION_MULTI_STATEMENTS_OFF
+};
+
+#define net_new_transaction(net) ((net)->pkt_nr=0)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+my_bool	my_net_init(NET *net, Vio* vio);
+void	my_net_local_init(NET *net);
+void	net_end(NET *net);
+void	net_clear(NET *net);
+my_bool net_realloc(NET *net, unsigned long length);
+my_bool	net_flush(NET *net);
+my_bool	my_net_write(NET *net,const char *packet,unsigned long len);
+my_bool	net_write_command(NET *net,unsigned char command,
+			  const char *header, unsigned long head_len,
+			  const char *packet, unsigned long len);
+int	net_real_write(NET *net,const char *packet,unsigned long len);
+unsigned long my_net_read(NET *net);
+
+#ifdef _global_h
+void my_net_set_write_timeout(NET *net, uint timeout);
+void my_net_set_read_timeout(NET *net, uint timeout);
+#endif
+
+/*
+  The following function is not meant for normal usage
+  Currently it's used internally by manager.c
+*/
+struct sockaddr;
+int my_connect(my_socket s, const struct sockaddr *name, unsigned int namelen,
+	       unsigned int timeout);
+
+struct rand_struct {
+  unsigned long seed1,seed2,max_value;
+  double max_value_dbl;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+  /* The following is for user defined functions */
+
+enum Item_result {STRING_RESULT=0, REAL_RESULT, INT_RESULT, ROW_RESULT,
+                  DECIMAL_RESULT};
+
+typedef struct st_udf_args
+{
+  unsigned int arg_count;		/* Number of arguments */
+  enum Item_result *arg_type;		/* Pointer to item_results */
+  char **args;				/* Pointer to argument */
+  unsigned long *lengths;		/* Length of string arguments */
+  char *maybe_null;			/* Set to 1 for all maybe_null args */
+  char **attributes;                    /* Pointer to attribute name */
+  unsigned long *attribute_lengths;     /* Length of attribute arguments */
+} UDF_ARGS;
+
+  /* This holds information about the result */
+
+typedef struct st_udf_init
+{
+  my_bool maybe_null;          /* 1 if function can return NULL */
+  unsigned int decimals;       /* for real functions */
+  unsigned long max_length;    /* For string functions */
+  char *ptr;                   /* free pointer for function data */
+  my_bool const_item;          /* 1 if function always returns the same value */
+} UDF_INIT;
+/* 
+  TODO: add a notion for determinism of the UDF. 
+  See Item_udf_func::update_used_tables ()
+*/
+
+  /* Constants when using compression */
+#define NET_HEADER_SIZE 4		/* standard header size */
+#define COMP_HEADER_SIZE 3		/* compression header extra size */
+
+  /* Prototypes to password functions */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+  These functions are used for authentication by client and server and
+  implemented in sql/password.c
+*/
+
+void randominit(struct rand_struct *, unsigned long seed1,
+                unsigned long seed2);
+double my_rnd(struct rand_struct *);
+void create_random_string(char *to, unsigned int length, struct rand_struct *rand_st);
+
+void hash_password(unsigned long *to, const char *password, unsigned int password_len);
+void make_scrambled_password_323(char *to, const char *password);
+void scramble_323(char *to, const char *message, const char *password);
+my_bool check_scramble_323(const char *, const char *message,
+                           unsigned long *salt);
+void get_salt_from_password_323(unsigned long *res, const char *password);
+void make_password_from_salt_323(char *to, const unsigned long *salt);
+
+void make_scrambled_password(char *to, const char *password);
+void scramble(char *to, const char *message, const char *password);
+my_bool check_scramble(const char *reply, const char *message,
+                       const unsigned char *hash_stage2);
+void get_salt_from_password(unsigned char *res, const char *password);
+void make_password_from_salt(char *to, const unsigned char *hash_stage2);
+char *octet2hex(char *to, const char *str, unsigned int len);
+
+/* end of password.c */
+
+char *get_tty_password(char *opt_message);
+const char *mysql_errno_to_sqlstate(unsigned int mysql_errno);
+
+/* Some other useful functions */
+
+my_bool my_init(void);
+extern int modify_defaults_file(const char *file_location, const char *option,
+                                const char *option_value,
+                                const char *section_name, int remove_option);
+int load_defaults(const char *conf_file, const char **groups,
+		  int *argc, char ***argv);
+my_bool my_thread_init(void);
+void my_thread_end(void);
+
+#ifdef _global_h
+ulong STDCALL net_field_length(uchar **packet);
+my_ulonglong net_field_length_ll(uchar **packet);
+char *net_store_length(char *pkg, ulonglong length);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#define NULL_LENGTH ((unsigned long) ~0) /* For net_store_length */
+#define MYSQL_STMT_HEADER       4
+#define MYSQL_LONG_DATA_HEADER  6
+
+#endif
diff --git a/dep/include/mysql/mysql_embed.h b/dep/include/mysql/mysql_embed.h
new file mode 100644
index 00000000000..7416283d83d
--- /dev/null
+++ b/dep/include/mysql/mysql_embed.h
@@ -0,0 +1,31 @@
+/* Copyright (C) 2000 MySQL AB
+
+   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; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+/* Defines that are unique to the embedded version of MySQL */
+
+#ifdef EMBEDDED_LIBRARY
+
+/* Things we don't need in the embedded version of MySQL */
+/* TODO HF add #undef HAVE_VIO if we don't want client in embedded library */
+
+#undef HAVE_PSTACK				/* No stacktrace */
+#undef HAVE_DLOPEN				/* No udf functions */
+#undef HAVE_OPENSSL
+#undef HAVE_SMEM				/* No shared memory */
+#undef HAVE_NDBCLUSTER_DB /* No NDB cluster */
+
+#define DONT_USE_RAID
+
+#endif /* EMBEDDED_LIBRARY */
diff --git a/dep/include/mysql/mysql_time.h b/dep/include/mysql/mysql_time.h
new file mode 100644
index 00000000000..0a3f17a81fb
--- /dev/null
+++ b/dep/include/mysql/mysql_time.h
@@ -0,0 +1,55 @@
+/* Copyright (C) 2004 MySQL AB
+
+ 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; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#ifndef _mysql_time_h_
+#define _mysql_time_h_
+
+/*
+  Time declarations shared between the server and client API:
+  you should not add anything to this header unless it's used
+  (and hence should be visible) in mysql.h.
+  If you're looking for a place to add new time-related declaration,
+  it's most likely my_time.h. See also "C API Handling of Date
+  and Time Values" chapter in documentation.
+*/
+
+enum enum_mysql_timestamp_type
+{
+  MYSQL_TIMESTAMP_NONE= -2, MYSQL_TIMESTAMP_ERROR= -1,
+  MYSQL_TIMESTAMP_DATE= 0, MYSQL_TIMESTAMP_DATETIME= 1, MYSQL_TIMESTAMP_TIME= 2
+};
+
+
+/*
+  Structure which is used to represent datetime values inside MySQL.
+
+  We assume that values in this structure are normalized, i.e. year <= 9999,
+  month <= 12, day <= 31, hour <= 23, hour <= 59, hour <= 59. Many functions
+  in server such as my_system_gmt_sec() or make_time() family of functions
+  rely on this (actually now usage of make_*() family relies on a bit weaker
+  restriction). Also functions that produce MYSQL_TIME as result ensure this.
+  There is one exception to this rule though if this structure holds time
+  value (time_type == MYSQL_TIMESTAMP_TIME) days and hour member can hold
+  bigger values.
+*/
+typedef struct st_mysql_time
+{
+  unsigned int  year, month, day, hour, minute, second;
+  unsigned long second_part;
+  my_bool       neg;
+  enum enum_mysql_timestamp_type time_type;
+} MYSQL_TIME;
+
+#endif /* _mysql_time_h_ */
diff --git a/dep/include/mysql/mysql_version.h b/dep/include/mysql/mysql_version.h
new file mode 100644
index 00000000000..3ec91e40930
--- /dev/null
+++ b/dep/include/mysql/mysql_version.h
@@ -0,0 +1,30 @@
+/* Copyright Abandoned 1996, 1999, 2001 MySQL AB
+   This file is public domain and comes with NO WARRANTY of any kind */
+
+/* Version numbers for protocol & mysqld */
+
+#ifndef _mysql_version_h
+#define _mysql_version_h
+#ifdef _CUSTOMCONFIG_
+#include 
+#else
+#define PROTOCOL_VERSION		10
+#define MYSQL_SERVER_VERSION		"5.0.56"
+#define MYSQL_BASE_VERSION		"mysqld-5.0"
+#define MYSQL_SERVER_SUFFIX_DEF		"-nt"
+#define FRM_VER				6
+#define MYSQL_VERSION_ID		50056
+#define MYSQL_PORT			3306
+#define MYSQL_PORT_DEFAULT		0
+#define MYSQL_UNIX_ADDR			"/tmp/mysql.sock"
+#define MYSQL_CONFIG_NAME		"my"
+#define MYSQL_COMPILATION_COMMENT	"From Sources"
+
+/* mysqld compile time options */
+#endif /* _CUSTOMCONFIG_ */
+
+#ifndef LICENSE
+#define LICENSE				GPL
+#endif /* LICENSE */
+
+#endif /* _mysql_version_h */
diff --git a/dep/include/mysql/mysqld_error.h b/dep/include/mysql/mysqld_error.h
new file mode 100644
index 00000000000..591ff78c5e1
--- /dev/null
+++ b/dep/include/mysql/mysqld_error.h
@@ -0,0 +1,480 @@
+/* Autogenerated file, please don't edit */
+
+#define ER_ERROR_FIRST 1000
+#define ER_HASHCHK 1000
+#define ER_NISAMCHK 1001
+#define ER_NO 1002
+#define ER_YES 1003
+#define ER_CANT_CREATE_FILE 1004
+#define ER_CANT_CREATE_TABLE 1005
+#define ER_CANT_CREATE_DB 1006
+#define ER_DB_CREATE_EXISTS 1007
+#define ER_DB_DROP_EXISTS 1008
+#define ER_DB_DROP_DELETE 1009
+#define ER_DB_DROP_RMDIR 1010
+#define ER_CANT_DELETE_FILE 1011
+#define ER_CANT_FIND_SYSTEM_REC 1012
+#define ER_CANT_GET_STAT 1013
+#define ER_CANT_GET_WD 1014
+#define ER_CANT_LOCK 1015
+#define ER_CANT_OPEN_FILE 1016
+#define ER_FILE_NOT_FOUND 1017
+#define ER_CANT_READ_DIR 1018
+#define ER_CANT_SET_WD 1019
+#define ER_CHECKREAD 1020
+#define ER_DISK_FULL 1021
+#define ER_DUP_KEY 1022
+#define ER_ERROR_ON_CLOSE 1023
+#define ER_ERROR_ON_READ 1024
+#define ER_ERROR_ON_RENAME 1025
+#define ER_ERROR_ON_WRITE 1026
+#define ER_FILE_USED 1027
+#define ER_FILSORT_ABORT 1028
+#define ER_FORM_NOT_FOUND 1029
+#define ER_GET_ERRNO 1030
+#define ER_ILLEGAL_HA 1031
+#define ER_KEY_NOT_FOUND 1032
+#define ER_NOT_FORM_FILE 1033
+#define ER_NOT_KEYFILE 1034
+#define ER_OLD_KEYFILE 1035
+#define ER_OPEN_AS_READONLY 1036
+#define ER_OUTOFMEMORY 1037
+#define ER_OUT_OF_SORTMEMORY 1038
+#define ER_UNEXPECTED_EOF 1039
+#define ER_CON_COUNT_ERROR 1040
+#define ER_OUT_OF_RESOURCES 1041
+#define ER_BAD_HOST_ERROR 1042
+#define ER_HANDSHAKE_ERROR 1043
+#define ER_DBACCESS_DENIED_ERROR 1044
+#define ER_ACCESS_DENIED_ERROR 1045
+#define ER_NO_DB_ERROR 1046
+#define ER_UNKNOWN_COM_ERROR 1047
+#define ER_BAD_NULL_ERROR 1048
+#define ER_BAD_DB_ERROR 1049
+#define ER_TABLE_EXISTS_ERROR 1050
+#define ER_BAD_TABLE_ERROR 1051
+#define ER_NON_UNIQ_ERROR 1052
+#define ER_SERVER_SHUTDOWN 1053
+#define ER_BAD_FIELD_ERROR 1054
+#define ER_WRONG_FIELD_WITH_GROUP 1055
+#define ER_WRONG_GROUP_FIELD 1056
+#define ER_WRONG_SUM_SELECT 1057
+#define ER_WRONG_VALUE_COUNT 1058
+#define ER_TOO_LONG_IDENT 1059
+#define ER_DUP_FIELDNAME 1060
+#define ER_DUP_KEYNAME 1061
+#define ER_DUP_ENTRY 1062
+#define ER_WRONG_FIELD_SPEC 1063
+#define ER_PARSE_ERROR 1064
+#define ER_EMPTY_QUERY 1065
+#define ER_NONUNIQ_TABLE 1066
+#define ER_INVALID_DEFAULT 1067
+#define ER_MULTIPLE_PRI_KEY 1068
+#define ER_TOO_MANY_KEYS 1069
+#define ER_TOO_MANY_KEY_PARTS 1070
+#define ER_TOO_LONG_KEY 1071
+#define ER_KEY_COLUMN_DOES_NOT_EXITS 1072
+#define ER_BLOB_USED_AS_KEY 1073
+#define ER_TOO_BIG_FIELDLENGTH 1074
+#define ER_WRONG_AUTO_KEY 1075
+#define ER_READY 1076
+#define ER_NORMAL_SHUTDOWN 1077
+#define ER_GOT_SIGNAL 1078
+#define ER_SHUTDOWN_COMPLETE 1079
+#define ER_FORCING_CLOSE 1080
+#define ER_IPSOCK_ERROR 1081
+#define ER_NO_SUCH_INDEX 1082
+#define ER_WRONG_FIELD_TERMINATORS 1083
+#define ER_BLOBS_AND_NO_TERMINATED 1084
+#define ER_TEXTFILE_NOT_READABLE 1085
+#define ER_FILE_EXISTS_ERROR 1086
+#define ER_LOAD_INFO 1087
+#define ER_ALTER_INFO 1088
+#define ER_WRONG_SUB_KEY 1089
+#define ER_CANT_REMOVE_ALL_FIELDS 1090
+#define ER_CANT_DROP_FIELD_OR_KEY 1091
+#define ER_INSERT_INFO 1092
+#define ER_UPDATE_TABLE_USED 1093
+#define ER_NO_SUCH_THREAD 1094
+#define ER_KILL_DENIED_ERROR 1095
+#define ER_NO_TABLES_USED 1096
+#define ER_TOO_BIG_SET 1097
+#define ER_NO_UNIQUE_LOGFILE 1098
+#define ER_TABLE_NOT_LOCKED_FOR_WRITE 1099
+#define ER_TABLE_NOT_LOCKED 1100
+#define ER_BLOB_CANT_HAVE_DEFAULT 1101
+#define ER_WRONG_DB_NAME 1102
+#define ER_WRONG_TABLE_NAME 1103
+#define ER_TOO_BIG_SELECT 1104
+#define ER_UNKNOWN_ERROR 1105
+#define ER_UNKNOWN_PROCEDURE 1106
+#define ER_WRONG_PARAMCOUNT_TO_PROCEDURE 1107
+#define ER_WRONG_PARAMETERS_TO_PROCEDURE 1108
+#define ER_UNKNOWN_TABLE 1109
+#define ER_FIELD_SPECIFIED_TWICE 1110
+#define ER_INVALID_GROUP_FUNC_USE 1111
+#define ER_UNSUPPORTED_EXTENSION 1112
+#define ER_TABLE_MUST_HAVE_COLUMNS 1113
+#define ER_RECORD_FILE_FULL 1114
+#define ER_UNKNOWN_CHARACTER_SET 1115
+#define ER_TOO_MANY_TABLES 1116
+#define ER_TOO_MANY_FIELDS 1117
+#define ER_TOO_BIG_ROWSIZE 1118
+#define ER_STACK_OVERRUN 1119
+#define ER_WRONG_OUTER_JOIN 1120
+#define ER_NULL_COLUMN_IN_INDEX 1121
+#define ER_CANT_FIND_UDF 1122
+#define ER_CANT_INITIALIZE_UDF 1123
+#define ER_UDF_NO_PATHS 1124
+#define ER_UDF_EXISTS 1125
+#define ER_CANT_OPEN_LIBRARY 1126
+#define ER_CANT_FIND_DL_ENTRY 1127
+#define ER_FUNCTION_NOT_DEFINED 1128
+#define ER_HOST_IS_BLOCKED 1129
+#define ER_HOST_NOT_PRIVILEGED 1130
+#define ER_PASSWORD_ANONYMOUS_USER 1131
+#define ER_PASSWORD_NOT_ALLOWED 1132
+#define ER_PASSWORD_NO_MATCH 1133
+#define ER_UPDATE_INFO 1134
+#define ER_CANT_CREATE_THREAD 1135
+#define ER_WRONG_VALUE_COUNT_ON_ROW 1136
+#define ER_CANT_REOPEN_TABLE 1137
+#define ER_INVALID_USE_OF_NULL 1138
+#define ER_REGEXP_ERROR 1139
+#define ER_MIX_OF_GROUP_FUNC_AND_FIELDS 1140
+#define ER_NONEXISTING_GRANT 1141
+#define ER_TABLEACCESS_DENIED_ERROR 1142
+#define ER_COLUMNACCESS_DENIED_ERROR 1143
+#define ER_ILLEGAL_GRANT_FOR_TABLE 1144
+#define ER_GRANT_WRONG_HOST_OR_USER 1145
+#define ER_NO_SUCH_TABLE 1146
+#define ER_NONEXISTING_TABLE_GRANT 1147
+#define ER_NOT_ALLOWED_COMMAND 1148
+#define ER_SYNTAX_ERROR 1149
+#define ER_DELAYED_CANT_CHANGE_LOCK 1150
+#define ER_TOO_MANY_DELAYED_THREADS 1151
+#define ER_ABORTING_CONNECTION 1152
+#define ER_NET_PACKET_TOO_LARGE 1153
+#define ER_NET_READ_ERROR_FROM_PIPE 1154
+#define ER_NET_FCNTL_ERROR 1155
+#define ER_NET_PACKETS_OUT_OF_ORDER 1156
+#define ER_NET_UNCOMPRESS_ERROR 1157
+#define ER_NET_READ_ERROR 1158
+#define ER_NET_READ_INTERRUPTED 1159
+#define ER_NET_ERROR_ON_WRITE 1160
+#define ER_NET_WRITE_INTERRUPTED 1161
+#define ER_TOO_LONG_STRING 1162
+#define ER_TABLE_CANT_HANDLE_BLOB 1163
+#define ER_TABLE_CANT_HANDLE_AUTO_INCREMENT 1164
+#define ER_DELAYED_INSERT_TABLE_LOCKED 1165
+#define ER_WRONG_COLUMN_NAME 1166
+#define ER_WRONG_KEY_COLUMN 1167
+#define ER_WRONG_MRG_TABLE 1168
+#define ER_DUP_UNIQUE 1169
+#define ER_BLOB_KEY_WITHOUT_LENGTH 1170
+#define ER_PRIMARY_CANT_HAVE_NULL 1171
+#define ER_TOO_MANY_ROWS 1172
+#define ER_REQUIRES_PRIMARY_KEY 1173
+#define ER_NO_RAID_COMPILED 1174
+#define ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE 1175
+#define ER_KEY_DOES_NOT_EXITS 1176
+#define ER_CHECK_NO_SUCH_TABLE 1177
+#define ER_CHECK_NOT_IMPLEMENTED 1178
+#define ER_CANT_DO_THIS_DURING_AN_TRANSACTION 1179
+#define ER_ERROR_DURING_COMMIT 1180
+#define ER_ERROR_DURING_ROLLBACK 1181
+#define ER_ERROR_DURING_FLUSH_LOGS 1182
+#define ER_ERROR_DURING_CHECKPOINT 1183
+#define ER_NEW_ABORTING_CONNECTION 1184
+#define ER_DUMP_NOT_IMPLEMENTED 1185
+#define ER_FLUSH_MASTER_BINLOG_CLOSED 1186
+#define ER_INDEX_REBUILD 1187
+#define ER_MASTER 1188
+#define ER_MASTER_NET_READ 1189
+#define ER_MASTER_NET_WRITE 1190
+#define ER_FT_MATCHING_KEY_NOT_FOUND 1191
+#define ER_LOCK_OR_ACTIVE_TRANSACTION 1192
+#define ER_UNKNOWN_SYSTEM_VARIABLE 1193
+#define ER_CRASHED_ON_USAGE 1194
+#define ER_CRASHED_ON_REPAIR 1195
+#define ER_WARNING_NOT_COMPLETE_ROLLBACK 1196
+#define ER_TRANS_CACHE_FULL 1197
+#define ER_SLAVE_MUST_STOP 1198
+#define ER_SLAVE_NOT_RUNNING 1199
+#define ER_BAD_SLAVE 1200
+#define ER_MASTER_INFO 1201
+#define ER_SLAVE_THREAD 1202
+#define ER_TOO_MANY_USER_CONNECTIONS 1203
+#define ER_SET_CONSTANTS_ONLY 1204
+#define ER_LOCK_WAIT_TIMEOUT 1205
+#define ER_LOCK_TABLE_FULL 1206
+#define ER_READ_ONLY_TRANSACTION 1207
+#define ER_DROP_DB_WITH_READ_LOCK 1208
+#define ER_CREATE_DB_WITH_READ_LOCK 1209
+#define ER_WRONG_ARGUMENTS 1210
+#define ER_NO_PERMISSION_TO_CREATE_USER 1211
+#define ER_UNION_TABLES_IN_DIFFERENT_DIR 1212
+#define ER_LOCK_DEADLOCK 1213
+#define ER_TABLE_CANT_HANDLE_FT 1214
+#define ER_CANNOT_ADD_FOREIGN 1215
+#define ER_NO_REFERENCED_ROW 1216
+#define ER_ROW_IS_REFERENCED 1217
+#define ER_CONNECT_TO_MASTER 1218
+#define ER_QUERY_ON_MASTER 1219
+#define ER_ERROR_WHEN_EXECUTING_COMMAND 1220
+#define ER_WRONG_USAGE 1221
+#define ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT 1222
+#define ER_CANT_UPDATE_WITH_READLOCK 1223
+#define ER_MIXING_NOT_ALLOWED 1224
+#define ER_DUP_ARGUMENT 1225
+#define ER_USER_LIMIT_REACHED 1226
+#define ER_SPECIFIC_ACCESS_DENIED_ERROR 1227
+#define ER_LOCAL_VARIABLE 1228
+#define ER_GLOBAL_VARIABLE 1229
+#define ER_NO_DEFAULT 1230
+#define ER_WRONG_VALUE_FOR_VAR 1231
+#define ER_WRONG_TYPE_FOR_VAR 1232
+#define ER_VAR_CANT_BE_READ 1233
+#define ER_CANT_USE_OPTION_HERE 1234
+#define ER_NOT_SUPPORTED_YET 1235
+#define ER_MASTER_FATAL_ERROR_READING_BINLOG 1236
+#define ER_SLAVE_IGNORED_TABLE 1237
+#define ER_INCORRECT_GLOBAL_LOCAL_VAR 1238
+#define ER_WRONG_FK_DEF 1239
+#define ER_KEY_REF_DO_NOT_MATCH_TABLE_REF 1240
+#define ER_OPERAND_COLUMNS 1241
+#define ER_SUBQUERY_NO_1_ROW 1242
+#define ER_UNKNOWN_STMT_HANDLER 1243
+#define ER_CORRUPT_HELP_DB 1244
+#define ER_CYCLIC_REFERENCE 1245
+#define ER_AUTO_CONVERT 1246
+#define ER_ILLEGAL_REFERENCE 1247
+#define ER_DERIVED_MUST_HAVE_ALIAS 1248
+#define ER_SELECT_REDUCED 1249
+#define ER_TABLENAME_NOT_ALLOWED_HERE 1250
+#define ER_NOT_SUPPORTED_AUTH_MODE 1251
+#define ER_SPATIAL_CANT_HAVE_NULL 1252
+#define ER_COLLATION_CHARSET_MISMATCH 1253
+#define ER_SLAVE_WAS_RUNNING 1254
+#define ER_SLAVE_WAS_NOT_RUNNING 1255
+#define ER_TOO_BIG_FOR_UNCOMPRESS 1256
+#define ER_ZLIB_Z_MEM_ERROR 1257
+#define ER_ZLIB_Z_BUF_ERROR 1258
+#define ER_ZLIB_Z_DATA_ERROR 1259
+#define ER_CUT_VALUE_GROUP_CONCAT 1260
+#define ER_WARN_TOO_FEW_RECORDS 1261
+#define ER_WARN_TOO_MANY_RECORDS 1262
+#define ER_WARN_NULL_TO_NOTNULL 1263
+#define ER_WARN_DATA_OUT_OF_RANGE 1264
+#define WARN_DATA_TRUNCATED 1265
+#define ER_WARN_USING_OTHER_HANDLER 1266
+#define ER_CANT_AGGREGATE_2COLLATIONS 1267
+#define ER_DROP_USER 1268
+#define ER_REVOKE_GRANTS 1269
+#define ER_CANT_AGGREGATE_3COLLATIONS 1270
+#define ER_CANT_AGGREGATE_NCOLLATIONS 1271
+#define ER_VARIABLE_IS_NOT_STRUCT 1272
+#define ER_UNKNOWN_COLLATION 1273
+#define ER_SLAVE_IGNORED_SSL_PARAMS 1274
+#define ER_SERVER_IS_IN_SECURE_AUTH_MODE 1275
+#define ER_WARN_FIELD_RESOLVED 1276
+#define ER_BAD_SLAVE_UNTIL_COND 1277
+#define ER_MISSING_SKIP_SLAVE 1278
+#define ER_UNTIL_COND_IGNORED 1279
+#define ER_WRONG_NAME_FOR_INDEX 1280
+#define ER_WRONG_NAME_FOR_CATALOG 1281
+#define ER_WARN_QC_RESIZE 1282
+#define ER_BAD_FT_COLUMN 1283
+#define ER_UNKNOWN_KEY_CACHE 1284
+#define ER_WARN_HOSTNAME_WONT_WORK 1285
+#define ER_UNKNOWN_STORAGE_ENGINE 1286
+#define ER_WARN_DEPRECATED_SYNTAX 1287
+#define ER_NON_UPDATABLE_TABLE 1288
+#define ER_FEATURE_DISABLED 1289
+#define ER_OPTION_PREVENTS_STATEMENT 1290
+#define ER_DUPLICATED_VALUE_IN_TYPE 1291
+#define ER_TRUNCATED_WRONG_VALUE 1292
+#define ER_TOO_MUCH_AUTO_TIMESTAMP_COLS 1293
+#define ER_INVALID_ON_UPDATE 1294
+#define ER_UNSUPPORTED_PS 1295
+#define ER_GET_ERRMSG 1296
+#define ER_GET_TEMPORARY_ERRMSG 1297
+#define ER_UNKNOWN_TIME_ZONE 1298
+#define ER_WARN_INVALID_TIMESTAMP 1299
+#define ER_INVALID_CHARACTER_STRING 1300
+#define ER_WARN_ALLOWED_PACKET_OVERFLOWED 1301
+#define ER_CONFLICTING_DECLARATIONS 1302
+#define ER_SP_NO_RECURSIVE_CREATE 1303
+#define ER_SP_ALREADY_EXISTS 1304
+#define ER_SP_DOES_NOT_EXIST 1305
+#define ER_SP_DROP_FAILED 1306
+#define ER_SP_STORE_FAILED 1307
+#define ER_SP_LILABEL_MISMATCH 1308
+#define ER_SP_LABEL_REDEFINE 1309
+#define ER_SP_LABEL_MISMATCH 1310
+#define ER_SP_UNINIT_VAR 1311
+#define ER_SP_BADSELECT 1312
+#define ER_SP_BADRETURN 1313
+#define ER_SP_BADSTATEMENT 1314
+#define ER_UPDATE_LOG_DEPRECATED_IGNORED 1315
+#define ER_UPDATE_LOG_DEPRECATED_TRANSLATED 1316
+#define ER_QUERY_INTERRUPTED 1317
+#define ER_SP_WRONG_NO_OF_ARGS 1318
+#define ER_SP_COND_MISMATCH 1319
+#define ER_SP_NORETURN 1320
+#define ER_SP_NORETURNEND 1321
+#define ER_SP_BAD_CURSOR_QUERY 1322
+#define ER_SP_BAD_CURSOR_SELECT 1323
+#define ER_SP_CURSOR_MISMATCH 1324
+#define ER_SP_CURSOR_ALREADY_OPEN 1325
+#define ER_SP_CURSOR_NOT_OPEN 1326
+#define ER_SP_UNDECLARED_VAR 1327
+#define ER_SP_WRONG_NO_OF_FETCH_ARGS 1328
+#define ER_SP_FETCH_NO_DATA 1329
+#define ER_SP_DUP_PARAM 1330
+#define ER_SP_DUP_VAR 1331
+#define ER_SP_DUP_COND 1332
+#define ER_SP_DUP_CURS 1333
+#define ER_SP_CANT_ALTER 1334
+#define ER_SP_SUBSELECT_NYI 1335
+#define ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG 1336
+#define ER_SP_VARCOND_AFTER_CURSHNDLR 1337
+#define ER_SP_CURSOR_AFTER_HANDLER 1338
+#define ER_SP_CASE_NOT_FOUND 1339
+#define ER_FPARSER_TOO_BIG_FILE 1340
+#define ER_FPARSER_BAD_HEADER 1341
+#define ER_FPARSER_EOF_IN_COMMENT 1342
+#define ER_FPARSER_ERROR_IN_PARAMETER 1343
+#define ER_FPARSER_EOF_IN_UNKNOWN_PARAMETER 1344
+#define ER_VIEW_NO_EXPLAIN 1345
+#define ER_FRM_UNKNOWN_TYPE 1346
+#define ER_WRONG_OBJECT 1347
+#define ER_NONUPDATEABLE_COLUMN 1348
+#define ER_VIEW_SELECT_DERIVED 1349
+#define ER_VIEW_SELECT_CLAUSE 1350
+#define ER_VIEW_SELECT_VARIABLE 1351
+#define ER_VIEW_SELECT_TMPTABLE 1352
+#define ER_VIEW_WRONG_LIST 1353
+#define ER_WARN_VIEW_MERGE 1354
+#define ER_WARN_VIEW_WITHOUT_KEY 1355
+#define ER_VIEW_INVALID 1356
+#define ER_SP_NO_DROP_SP 1357
+#define ER_SP_GOTO_IN_HNDLR 1358
+#define ER_TRG_ALREADY_EXISTS 1359
+#define ER_TRG_DOES_NOT_EXIST 1360
+#define ER_TRG_ON_VIEW_OR_TEMP_TABLE 1361
+#define ER_TRG_CANT_CHANGE_ROW 1362
+#define ER_TRG_NO_SUCH_ROW_IN_TRG 1363
+#define ER_NO_DEFAULT_FOR_FIELD 1364
+#define ER_DIVISION_BY_ZERO 1365
+#define ER_TRUNCATED_WRONG_VALUE_FOR_FIELD 1366
+#define ER_ILLEGAL_VALUE_FOR_TYPE 1367
+#define ER_VIEW_NONUPD_CHECK 1368
+#define ER_VIEW_CHECK_FAILED 1369
+#define ER_PROCACCESS_DENIED_ERROR 1370
+#define ER_RELAY_LOG_FAIL 1371
+#define ER_PASSWD_LENGTH 1372
+#define ER_UNKNOWN_TARGET_BINLOG 1373
+#define ER_IO_ERR_LOG_INDEX_READ 1374
+#define ER_BINLOG_PURGE_PROHIBITED 1375
+#define ER_FSEEK_FAIL 1376
+#define ER_BINLOG_PURGE_FATAL_ERR 1377
+#define ER_LOG_IN_USE 1378
+#define ER_LOG_PURGE_UNKNOWN_ERR 1379
+#define ER_RELAY_LOG_INIT 1380
+#define ER_NO_BINARY_LOGGING 1381
+#define ER_RESERVED_SYNTAX 1382
+#define ER_WSAS_FAILED 1383
+#define ER_DIFF_GROUPS_PROC 1384
+#define ER_NO_GROUP_FOR_PROC 1385
+#define ER_ORDER_WITH_PROC 1386
+#define ER_LOGGING_PROHIBIT_CHANGING_OF 1387
+#define ER_NO_FILE_MAPPING 1388
+#define ER_WRONG_MAGIC 1389
+#define ER_PS_MANY_PARAM 1390
+#define ER_KEY_PART_0 1391
+#define ER_VIEW_CHECKSUM 1392
+#define ER_VIEW_MULTIUPDATE 1393
+#define ER_VIEW_NO_INSERT_FIELD_LIST 1394
+#define ER_VIEW_DELETE_MERGE_VIEW 1395
+#define ER_CANNOT_USER 1396
+#define ER_XAER_NOTA 1397
+#define ER_XAER_INVAL 1398
+#define ER_XAER_RMFAIL 1399
+#define ER_XAER_OUTSIDE 1400
+#define ER_XAER_RMERR 1401
+#define ER_XA_RBROLLBACK 1402
+#define ER_NONEXISTING_PROC_GRANT 1403
+#define ER_PROC_AUTO_GRANT_FAIL 1404
+#define ER_PROC_AUTO_REVOKE_FAIL 1405
+#define ER_DATA_TOO_LONG 1406
+#define ER_SP_BAD_SQLSTATE 1407
+#define ER_STARTUP 1408
+#define ER_LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR 1409
+#define ER_CANT_CREATE_USER_WITH_GRANT 1410
+#define ER_WRONG_VALUE_FOR_TYPE 1411
+#define ER_TABLE_DEF_CHANGED 1412
+#define ER_SP_DUP_HANDLER 1413
+#define ER_SP_NOT_VAR_ARG 1414
+#define ER_SP_NO_RETSET 1415
+#define ER_CANT_CREATE_GEOMETRY_OBJECT 1416
+#define ER_FAILED_ROUTINE_BREAK_BINLOG 1417
+#define ER_BINLOG_UNSAFE_ROUTINE 1418
+#define ER_BINLOG_CREATE_ROUTINE_NEED_SUPER 1419
+#define ER_EXEC_STMT_WITH_OPEN_CURSOR 1420
+#define ER_STMT_HAS_NO_OPEN_CURSOR 1421
+#define ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG 1422
+#define ER_NO_DEFAULT_FOR_VIEW_FIELD 1423
+#define ER_SP_NO_RECURSION 1424
+#define ER_TOO_BIG_SCALE 1425
+#define ER_TOO_BIG_PRECISION 1426
+#define ER_M_BIGGER_THAN_D 1427
+#define ER_WRONG_LOCK_OF_SYSTEM_TABLE 1428
+#define ER_CONNECT_TO_FOREIGN_DATA_SOURCE 1429
+#define ER_QUERY_ON_FOREIGN_DATA_SOURCE 1430
+#define ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST 1431
+#define ER_FOREIGN_DATA_STRING_INVALID_CANT_CREATE 1432
+#define ER_FOREIGN_DATA_STRING_INVALID 1433
+#define ER_CANT_CREATE_FEDERATED_TABLE 1434
+#define ER_TRG_IN_WRONG_SCHEMA 1435
+#define ER_STACK_OVERRUN_NEED_MORE 1436
+#define ER_TOO_LONG_BODY 1437
+#define ER_WARN_CANT_DROP_DEFAULT_KEYCACHE 1438
+#define ER_TOO_BIG_DISPLAYWIDTH 1439
+#define ER_XAER_DUPID 1440
+#define ER_DATETIME_FUNCTION_OVERFLOW 1441
+#define ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG 1442
+#define ER_VIEW_PREVENT_UPDATE 1443
+#define ER_PS_NO_RECURSION 1444
+#define ER_SP_CANT_SET_AUTOCOMMIT 1445
+#define ER_MALFORMED_DEFINER 1446
+#define ER_VIEW_FRM_NO_USER 1447
+#define ER_VIEW_OTHER_USER 1448
+#define ER_NO_SUCH_USER 1449
+#define ER_FORBID_SCHEMA_CHANGE 1450
+#define ER_ROW_IS_REFERENCED_2 1451
+#define ER_NO_REFERENCED_ROW_2 1452
+#define ER_SP_BAD_VAR_SHADOW 1453
+#define ER_TRG_NO_DEFINER 1454
+#define ER_OLD_FILE_FORMAT 1455
+#define ER_SP_RECURSION_LIMIT 1456
+#define ER_SP_PROC_TABLE_CORRUPT 1457
+#define ER_SP_WRONG_NAME 1458
+#define ER_TABLE_NEEDS_UPGRADE 1459
+#define ER_SP_NO_AGGREGATE 1460
+#define ER_MAX_PREPARED_STMT_COUNT_REACHED 1461
+#define ER_VIEW_RECURSIVE 1462
+#define ER_NON_GROUPING_FIELD_USED 1463
+#define ER_TABLE_CANT_HANDLE_SPKEYS 1464
+#define ER_NO_TRIGGERS_ON_SYSTEM_SCHEMA 1465
+#define ER_REMOVED_SPACES 1466
+#define ER_AUTOINC_READ_FAILED 1467
+#define ER_USERNAME 1468
+#define ER_HOSTNAME 1469
+#define ER_WRONG_STRING_LENGTH 1470
+#define ER_NON_INSERTABLE_TABLE 1471
+#define ER_ADMIN_WRONG_MRG_TABLE 1472
+#define ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT 1473
+#define ER_NAME_BECOMES_EMPTY 1474
+#define ER_AMBIGUOUS_FIELD_TERM 1475
+#define ER_ERROR_LAST 1475
diff --git a/dep/include/mysql/raid.h b/dep/include/mysql/raid.h
new file mode 100644
index 00000000000..9d098305d14
--- /dev/null
+++ b/dep/include/mysql/raid.h
@@ -0,0 +1,158 @@
+/* Copyright (C) 2000 MySQL AB
+
+   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; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+/* Parser needs these defines  always, even if USE_RAID is not defined */
+#define RAID_TYPE_0 1       /* Striping */
+#define RAID_TYPE_x 2       /* Some new modes */
+#define RAID_TYPE_y 3
+
+#define RAID_DEFAULT_CHUNKS 4
+#define RAID_DEFAULT_CHUNKSIZE 256*1024 /* 256kB */
+
+C_MODE_START
+#define my_raid_type(raid_type)  raid_type_string[(int)(raid_type)]
+extern const char *raid_type_string[];
+C_MODE_END
+
+#ifdef DONT_USE_RAID
+#undef USE_RAID
+#endif
+#if defined(USE_RAID)
+
+#include "my_dir.h"
+
+/* Trap all occurences of my_...() in source and use our wrapper around this function */
+
+#ifdef MAP_TO_USE_RAID
+#define my_read(A,B,C,D)     my_raid_read(A,B,C,D)
+#define my_write(A,B,C,D)    my_raid_write(A,B,C,D)
+#define my_pwrite(A,B,C,D,E) my_raid_pwrite(A,B,C,D,E)
+#define my_pread(A,B,C,D,E)  my_raid_pread(A,B,C,D,E)
+#define my_chsize(A,B,C,D)   my_raid_chsize(A,B,C,D)
+#define my_close(A,B)        my_raid_close(A,B)
+#define my_tell(A,B)         my_raid_tell(A,B)
+#define my_seek(A,B,C,D)     my_raid_seek(A,B,C,D)
+#define my_lock(A,B,C,D,E)     my_raid_lock(A,B,C,D,E)
+#define my_fstat(A,B,C)     my_raid_fstat(A,B,C)
+#endif /* MAP_TO_USE_RAID */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+  void init_raid(void);
+  void end_raid(void);
+
+  bool is_raid(File fd);
+  File my_raid_create(const char *FileName, int CreateFlags, int access_flags,
+		      uint raid_type, uint raid_chunks, ulong raid_chunksize,
+		      myf MyFlags);
+  File my_raid_open(const char *FileName, int Flags,
+		    uint raid_type, uint raid_chunks, ulong raid_chunksize,
+		    myf MyFlags);
+  int my_raid_rename(const char *from, const char *to, uint raid_chunks,
+		     myf MyFlags);
+  int my_raid_delete(const char *from, uint raid_chunks, myf MyFlags);
+  int my_raid_redel(const char *old_name, const char *new_name,
+		    uint raid_chunks, myf MyFlags);
+
+  my_off_t my_raid_seek(File fd, my_off_t pos, int whence, myf MyFlags);
+  my_off_t my_raid_tell(File fd, myf MyFlags);
+
+  uint my_raid_write(File,const byte *Buffer, uint Count, myf MyFlags);
+  uint my_raid_read(File Filedes, byte *Buffer, uint Count, myf MyFlags);
+
+  uint my_raid_pread(File Filedes, byte *Buffer, uint Count, my_off_t offset,
+		     myf MyFlags);
+  uint my_raid_pwrite(int Filedes, const byte *Buffer, uint Count,
+		      my_off_t offset, myf MyFlags);
+
+  int my_raid_lock(File,int locktype, my_off_t start, my_off_t length,
+		   myf MyFlags);
+  int my_raid_chsize(File fd, my_off_t newlength, int filler, myf MyFlags);
+  int my_raid_close(File, myf MyFlags);
+  int my_raid_fstat(int Filedes, struct stat *buf,  myf MyFlags);
+
+#ifdef __cplusplus
+}
+
+#ifdef USE_PRAGMA_INTERFACE
+#pragma interface			/* gcc class implementation */
+#endif
+
+class RaidName {
+  public:
+    RaidName(const char *FileName);
+    ~RaidName();
+    bool IsRaid();
+    int Rename(const char * from, const char * to, myf MyFlags);
+  private:
+    uint _raid_type;       /* RAID_TYPE_0 or RAID_TYPE_1 or RAID_TYPE_5 */
+    uint _raid_chunks;     /* 1..n */
+    ulong _raid_chunksize; /* 1..n in bytes */
+};
+
+class RaidFd {
+  public:
+    RaidFd(uint raid_type, uint raid_chunks , ulong raid_chunksize);
+    ~RaidFd();
+    File Create(const char *FileName, int CreateFlags, int access_flags,
+		myf MyFlags);
+    File Open(const char *FileName, int Flags, myf MyFlags);
+    my_off_t Seek(my_off_t pos,int whence,myf MyFlags);
+    my_off_t Tell(myf MyFlags);
+    int Write(const byte *Buffer, uint Count, myf MyFlags);
+    int Read(const byte *Buffer, uint Count, myf MyFlags);
+    int Lock(int locktype, my_off_t start, my_off_t length, myf MyFlags);
+    int Chsize(File fd, my_off_t newlength, int filler, myf MyFlags);
+    int Fstat(int fd, MY_STAT *stat_area, myf MyFlags );
+    int Close(myf MyFlags);
+    static bool IsRaid(File fd);
+    static DYNAMIC_ARRAY _raid_map;		/* Map of RaidFD* */
+  private:
+
+    uint _raid_type;       /* RAID_TYPE_0 or RAID_TYPE_1 or RAID_TYPE_5 */
+    uint _raid_chunks;     /* 1..n */
+    ulong _raid_chunksize; /* 1..n in bytes */
+
+    ulong _total_block;    /* We are operating with block no x (can be 0..many). */
+    uint _this_block;      /* can be 0.._raid_chunks */
+    uint _remaining_bytes; /* Maximum bytes that can be written in this block */
+
+    my_off_t _position;
+    my_off_t _size;        /* Cached file size for faster seek(SEEK_END) */
+    File _fd;
+    File *_fd_vector;		/* Array of File */
+    off_t *_seek_vector;	/* Array of cached seek positions */
+
+    inline void Calculate()
+    {
+      DBUG_ENTER("RaidFd::_Calculate");
+      DBUG_PRINT("info",("_position: %lu  _raid_chunksize: %lu  _size: %lu",
+			 (ulong) _position, _raid_chunksize, (ulong) _size));
+
+      _total_block = (ulong) (_position / _raid_chunksize);
+      _this_block = _total_block % _raid_chunks;    /* can be 0.._raid_chunks */
+      _remaining_bytes = (uint) (_raid_chunksize -
+				 (_position - _total_block * _raid_chunksize));
+      DBUG_PRINT("info",
+		 ("_total_block: %lu  this_block: %d  _remaining_bytes: %d",
+		  _total_block, _this_block, _remaining_bytes));
+      DBUG_VOID_RETURN;
+    }
+};
+
+#endif /* __cplusplus */
+#endif /* USE_RAID */
diff --git a/dep/include/mysql/typelib.h b/dep/include/mysql/typelib.h
new file mode 100644
index 00000000000..75d170e59d3
--- /dev/null
+++ b/dep/include/mysql/typelib.h
@@ -0,0 +1,36 @@
+/* Copyright (C) 2000 MySQL AB
+
+   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; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+
+#ifndef _typelib_h
+#define _typelib_h
+
+#include "my_alloc.h"
+
+typedef struct st_typelib {	/* Different types saved here */
+  unsigned int count;		/* How many types */
+  const char *name;		/* Name of typelib */
+  const char **type_names;
+  unsigned int *type_lengths;
+} TYPELIB;
+
+extern int find_type(char *x,TYPELIB *typelib,unsigned int full_name);
+extern void make_type(char *to,unsigned int nr,TYPELIB *typelib);
+extern const char *get_type(TYPELIB *typelib,unsigned int nr);
+extern TYPELIB *copy_typelib(MEM_ROOT *root, TYPELIB *from);
+
+extern TYPELIB sql_protocol_typelib;
+
+#endif /* _typelib_h */
diff --git a/dep/include/openssl/aes.h b/dep/include/openssl/aes.h
new file mode 100644
index 00000000000..e6fc44a24d4
--- /dev/null
+++ b/dep/include/openssl/aes.h
@@ -0,0 +1,138 @@
+/* crypto/aes/aes.h -*- mode:C; c-file-style: "eay" -*- */
+/* ====================================================================
+ * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ */
+
+#ifndef HEADER_AES_H
+#define HEADER_AES_H
+
+#include 
+
+#ifdef OPENSSL_NO_AES
+#error AES is disabled.
+#endif
+
+#define AES_ENCRYPT	1
+#define AES_DECRYPT	0
+
+/* Because array size can't be a const in C, the following two are macros.
+   Both sizes are in bytes. */
+#define AES_MAXNR 14
+#define AES_BLOCK_SIZE 16
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* This should be a hidden type, but EVP requires that the size be known */
+struct aes_key_st {
+#ifdef AES_LONG
+    unsigned long rd_key[4 *(AES_MAXNR + 1)];
+#else
+    unsigned int rd_key[4 *(AES_MAXNR + 1)];
+#endif
+    int rounds;
+};
+typedef struct aes_key_st AES_KEY;
+
+const char *AES_options(void);
+
+int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
+	AES_KEY *key);
+int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
+	AES_KEY *key);
+
+void AES_encrypt(const unsigned char *in, unsigned char *out,
+	const AES_KEY *key);
+void AES_decrypt(const unsigned char *in, unsigned char *out,
+	const AES_KEY *key);
+
+void AES_ecb_encrypt(const unsigned char *in, unsigned char *out,
+	const AES_KEY *key, const int enc);
+void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
+	const unsigned long length, const AES_KEY *key,
+	unsigned char *ivec, const int enc);
+void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out,
+	const unsigned long length, const AES_KEY *key,
+	unsigned char *ivec, int *num, const int enc);
+void AES_cfb1_encrypt(const unsigned char *in, unsigned char *out,
+	const unsigned long length, const AES_KEY *key,
+	unsigned char *ivec, int *num, const int enc);
+void AES_cfb8_encrypt(const unsigned char *in, unsigned char *out,
+	const unsigned long length, const AES_KEY *key,
+	unsigned char *ivec, int *num, const int enc);
+void AES_cfbr_encrypt_block(const unsigned char *in,unsigned char *out,
+			    const int nbits,const AES_KEY *key,
+			    unsigned char *ivec,const int enc);
+void AES_ofb128_encrypt(const unsigned char *in, unsigned char *out,
+	const unsigned long length, const AES_KEY *key,
+	unsigned char *ivec, int *num);
+void AES_ctr128_encrypt(const unsigned char *in, unsigned char *out,
+	const unsigned long length, const AES_KEY *key,
+	unsigned char ivec[AES_BLOCK_SIZE],
+	unsigned char ecount_buf[AES_BLOCK_SIZE],
+	unsigned int *num);
+
+/* For IGE, see also http://www.links.org/files/openssl-ige.pdf */
+/* NB: the IV is _two_ blocks long */
+void AES_ige_encrypt(const unsigned char *in, unsigned char *out,
+		     const unsigned long length, const AES_KEY *key,
+		     unsigned char *ivec, const int enc);
+/* NB: the IV is _four_ blocks long */
+void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out,
+			const unsigned long length, const AES_KEY *key,
+			const AES_KEY *key2, const unsigned char *ivec,
+			const int enc);
+
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif /* !HEADER_AES_H */
diff --git a/dep/include/openssl/asn1.h b/dep/include/openssl/asn1.h
new file mode 100644
index 00000000000..30f1eecd5b9
--- /dev/null
+++ b/dep/include/openssl/asn1.h
@@ -0,0 +1,1233 @@
+/* crypto/asn1/asn1.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_ASN1_H
+#define HEADER_ASN1_H
+
+#include 
+#include 
+#ifndef OPENSSL_NO_BIO
+#include 
+#endif
+#include 
+#include 
+
+#include 
+
+#include 
+#ifndef OPENSSL_NO_DEPRECATED
+#include 
+#endif
+
+#ifdef OPENSSL_BUILD_SHLIBCRYPTO
+# undef OPENSSL_EXTERN
+# define OPENSSL_EXTERN OPENSSL_EXPORT
+#endif
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#define V_ASN1_UNIVERSAL		0x00
+#define	V_ASN1_APPLICATION		0x40
+#define V_ASN1_CONTEXT_SPECIFIC		0x80
+#define V_ASN1_PRIVATE			0xc0
+
+#define V_ASN1_CONSTRUCTED		0x20
+#define V_ASN1_PRIMITIVE_TAG		0x1f
+#define V_ASN1_PRIMATIVE_TAG		0x1f
+
+#define V_ASN1_APP_CHOOSE		-2	/* let the recipient choose */
+#define V_ASN1_OTHER			-3	/* used in ASN1_TYPE */
+#define V_ASN1_ANY			-4	/* used in ASN1 template code */
+
+#define V_ASN1_NEG			0x100	/* negative flag */
+
+#define V_ASN1_UNDEF			-1
+#define V_ASN1_EOC			0
+#define V_ASN1_BOOLEAN			1	/**/
+#define V_ASN1_INTEGER			2
+#define V_ASN1_NEG_INTEGER		(2 | V_ASN1_NEG)
+#define V_ASN1_BIT_STRING		3
+#define V_ASN1_OCTET_STRING		4
+#define V_ASN1_NULL			5
+#define V_ASN1_OBJECT			6
+#define V_ASN1_OBJECT_DESCRIPTOR	7
+#define V_ASN1_EXTERNAL			8
+#define V_ASN1_REAL			9
+#define V_ASN1_ENUMERATED		10
+#define V_ASN1_NEG_ENUMERATED		(10 | V_ASN1_NEG)
+#define V_ASN1_UTF8STRING		12
+#define V_ASN1_SEQUENCE			16
+#define V_ASN1_SET			17
+#define V_ASN1_NUMERICSTRING		18	/**/
+#define V_ASN1_PRINTABLESTRING		19
+#define V_ASN1_T61STRING		20
+#define V_ASN1_TELETEXSTRING		20	/* alias */
+#define V_ASN1_VIDEOTEXSTRING		21	/**/
+#define V_ASN1_IA5STRING		22
+#define V_ASN1_UTCTIME			23
+#define V_ASN1_GENERALIZEDTIME		24	/**/
+#define V_ASN1_GRAPHICSTRING		25	/**/
+#define V_ASN1_ISO64STRING		26	/**/
+#define V_ASN1_VISIBLESTRING		26	/* alias */
+#define V_ASN1_GENERALSTRING		27	/**/
+#define V_ASN1_UNIVERSALSTRING		28	/**/
+#define V_ASN1_BMPSTRING		30
+
+/* For use with d2i_ASN1_type_bytes() */
+#define B_ASN1_NUMERICSTRING	0x0001
+#define B_ASN1_PRINTABLESTRING	0x0002
+#define B_ASN1_T61STRING	0x0004
+#define B_ASN1_TELETEXSTRING	0x0004
+#define B_ASN1_VIDEOTEXSTRING	0x0008
+#define B_ASN1_IA5STRING	0x0010
+#define B_ASN1_GRAPHICSTRING	0x0020
+#define B_ASN1_ISO64STRING	0x0040
+#define B_ASN1_VISIBLESTRING	0x0040
+#define B_ASN1_GENERALSTRING	0x0080
+#define B_ASN1_UNIVERSALSTRING	0x0100
+#define B_ASN1_OCTET_STRING	0x0200
+#define B_ASN1_BIT_STRING	0x0400
+#define B_ASN1_BMPSTRING	0x0800
+#define B_ASN1_UNKNOWN		0x1000
+#define B_ASN1_UTF8STRING	0x2000
+#define B_ASN1_UTCTIME		0x4000
+#define B_ASN1_GENERALIZEDTIME	0x8000
+#define B_ASN1_SEQUENCE		0x10000
+
+/* For use with ASN1_mbstring_copy() */
+#define MBSTRING_FLAG		0x1000
+#define MBSTRING_UTF8		(MBSTRING_FLAG)
+#define MBSTRING_ASC		(MBSTRING_FLAG|1)
+#define MBSTRING_BMP		(MBSTRING_FLAG|2)
+#define MBSTRING_UNIV		(MBSTRING_FLAG|4)
+
+struct X509_algor_st;
+
+#define DECLARE_ASN1_SET_OF(type) /* filled in by mkstack.pl */
+#define IMPLEMENT_ASN1_SET_OF(type) /* nothing, no longer needed */
+
+/* We MUST make sure that, except for constness, asn1_ctx_st and
+   asn1_const_ctx are exactly the same.  Fortunately, as soon as
+   the old ASN1 parsing macros are gone, we can throw this away
+   as well... */
+typedef struct asn1_ctx_st
+	{
+	unsigned char *p;/* work char pointer */
+	int eos;	/* end of sequence read for indefinite encoding */
+	int error;	/* error code to use when returning an error */
+	int inf;	/* constructed if 0x20, indefinite is 0x21 */
+	int tag;	/* tag from last 'get object' */
+	int xclass;	/* class from last 'get object' */
+	long slen;	/* length of last 'get object' */
+	unsigned char *max; /* largest value of p allowed */
+	unsigned char *q;/* temporary variable */
+	unsigned char **pp;/* variable */
+	int line;	/* used in error processing */
+	} ASN1_CTX;
+
+typedef struct asn1_const_ctx_st
+	{
+	const unsigned char *p;/* work char pointer */
+	int eos;	/* end of sequence read for indefinite encoding */
+	int error;	/* error code to use when returning an error */
+	int inf;	/* constructed if 0x20, indefinite is 0x21 */
+	int tag;	/* tag from last 'get object' */
+	int xclass;	/* class from last 'get object' */
+	long slen;	/* length of last 'get object' */
+	const unsigned char *max; /* largest value of p allowed */
+	const unsigned char *q;/* temporary variable */
+	const unsigned char **pp;/* variable */
+	int line;	/* used in error processing */
+	} ASN1_const_CTX;
+
+/* These are used internally in the ASN1_OBJECT to keep track of
+ * whether the names and data need to be free()ed */
+#define ASN1_OBJECT_FLAG_DYNAMIC	 0x01	/* internal use */
+#define ASN1_OBJECT_FLAG_CRITICAL	 0x02	/* critical x509v3 object id */
+#define ASN1_OBJECT_FLAG_DYNAMIC_STRINGS 0x04	/* internal use */
+#define ASN1_OBJECT_FLAG_DYNAMIC_DATA 	 0x08	/* internal use */
+typedef struct asn1_object_st
+	{
+	const char *sn,*ln;
+	int nid;
+	int length;
+	unsigned char *data;
+	int flags;	/* Should we free this one */
+	} ASN1_OBJECT;
+
+#define ASN1_STRING_FLAG_BITS_LEFT 0x08 /* Set if 0x07 has bits left value */
+/* This indicates that the ASN1_STRING is not a real value but just a place
+ * holder for the location where indefinite length constructed data should
+ * be inserted in the memory buffer 
+ */
+#define ASN1_STRING_FLAG_NDEF 0x010 
+/* This is the base type that holds just about everything :-) */
+typedef struct asn1_string_st
+	{
+	int length;
+	int type;
+	unsigned char *data;
+	/* The value of the following field depends on the type being
+	 * held.  It is mostly being used for BIT_STRING so if the
+	 * input data has a non-zero 'unused bits' value, it will be
+	 * handled correctly */
+	long flags;
+	} ASN1_STRING;
+
+/* ASN1_ENCODING structure: this is used to save the received
+ * encoding of an ASN1 type. This is useful to get round
+ * problems with invalid encodings which can break signatures.
+ */
+
+typedef struct ASN1_ENCODING_st
+	{
+	unsigned char *enc;	/* DER encoding */
+	long len;		/* Length of encoding */
+	int modified;		 /* set to 1 if 'enc' is invalid */
+	} ASN1_ENCODING;
+
+/* Used with ASN1 LONG type: if a long is set to this it is omitted */
+#define ASN1_LONG_UNDEF	0x7fffffffL
+
+#define STABLE_FLAGS_MALLOC	0x01
+#define STABLE_NO_MASK		0x02
+#define DIRSTRING_TYPE	\
+ (B_ASN1_PRINTABLESTRING|B_ASN1_T61STRING|B_ASN1_BMPSTRING|B_ASN1_UTF8STRING)
+#define PKCS9STRING_TYPE (DIRSTRING_TYPE|B_ASN1_IA5STRING)
+
+typedef struct asn1_string_table_st {
+	int nid;
+	long minsize;
+	long maxsize;
+	unsigned long mask;
+	unsigned long flags;
+} ASN1_STRING_TABLE;
+
+DECLARE_STACK_OF(ASN1_STRING_TABLE)
+
+/* size limits: this stuff is taken straight from RFC2459 */
+
+#define ub_name				32768
+#define ub_common_name			64
+#define ub_locality_name		128
+#define ub_state_name			128
+#define ub_organization_name		64
+#define ub_organization_unit_name	64
+#define ub_title			64
+#define ub_email_address		128
+
+/* Declarations for template structures: for full definitions
+ * see asn1t.h
+ */
+typedef struct ASN1_TEMPLATE_st ASN1_TEMPLATE;
+typedef struct ASN1_ITEM_st ASN1_ITEM;
+typedef struct ASN1_TLC_st ASN1_TLC;
+/* This is just an opaque pointer */
+typedef struct ASN1_VALUE_st ASN1_VALUE;
+
+/* Declare ASN1 functions: the implement macro in in asn1t.h */
+
+#define DECLARE_ASN1_FUNCTIONS(type) DECLARE_ASN1_FUNCTIONS_name(type, type)
+
+#define DECLARE_ASN1_ALLOC_FUNCTIONS(type) \
+	DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, type)
+
+#define DECLARE_ASN1_FUNCTIONS_name(type, name) \
+	DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \
+	DECLARE_ASN1_ENCODE_FUNCTIONS(type, name, name)
+
+#define DECLARE_ASN1_FUNCTIONS_fname(type, itname, name) \
+	DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \
+	DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name)
+
+#define	DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) \
+	type *d2i_##name(type **a, const unsigned char **in, long len); \
+	int i2d_##name(type *a, unsigned char **out); \
+	DECLARE_ASN1_ITEM(itname)
+
+#define	DECLARE_ASN1_ENCODE_FUNCTIONS_const(type, name) \
+	type *d2i_##name(type **a, const unsigned char **in, long len); \
+	int i2d_##name(const type *a, unsigned char **out); \
+	DECLARE_ASN1_ITEM(name)
+
+#define	DECLARE_ASN1_NDEF_FUNCTION(name) \
+	int i2d_##name##_NDEF(name *a, unsigned char **out);
+
+#define DECLARE_ASN1_FUNCTIONS_const(name) \
+	name *name##_new(void); \
+	void name##_free(name *a);
+
+#define DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \
+	type *name##_new(void); \
+	void name##_free(type *a);
+
+#define D2I_OF(type) type *(*)(type **,const unsigned char **,long)
+#define I2D_OF(type) int (*)(type *,unsigned char **)
+#define I2D_OF_const(type) int (*)(const type *,unsigned char **)
+
+#define TYPEDEF_D2I_OF(type) typedef type *d2i_of_##type(type **,const unsigned char **,long)
+#define TYPEDEF_I2D_OF(type) typedef int i2d_of_##type(type *,unsigned char **)
+#define TYPEDEF_D2I2D_OF(type) TYPEDEF_D2I_OF(type); TYPEDEF_I2D_OF(type)
+
+TYPEDEF_D2I2D_OF(void);
+
+/* The following macros and typedefs allow an ASN1_ITEM
+ * to be embedded in a structure and referenced. Since
+ * the ASN1_ITEM pointers need to be globally accessible
+ * (possibly from shared libraries) they may exist in
+ * different forms. On platforms that support it the
+ * ASN1_ITEM structure itself will be globally exported.
+ * Other platforms will export a function that returns
+ * an ASN1_ITEM pointer.
+ *
+ * To handle both cases transparently the macros below
+ * should be used instead of hard coding an ASN1_ITEM
+ * pointer in a structure.
+ *
+ * The structure will look like this:
+ *
+ * typedef struct SOMETHING_st {
+ *      ...
+ *      ASN1_ITEM_EXP *iptr;
+ *      ...
+ * } SOMETHING; 
+ *
+ * It would be initialised as e.g.:
+ *
+ * SOMETHING somevar = {...,ASN1_ITEM_ref(X509),...};
+ *
+ * and the actual pointer extracted with:
+ *
+ * const ASN1_ITEM *it = ASN1_ITEM_ptr(somevar.iptr);
+ *
+ * Finally an ASN1_ITEM pointer can be extracted from an
+ * appropriate reference with: ASN1_ITEM_rptr(X509). This
+ * would be used when a function takes an ASN1_ITEM * argument.
+ *
+ */
+
+#ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION
+
+/* ASN1_ITEM pointer exported type */
+typedef const ASN1_ITEM ASN1_ITEM_EXP;
+
+/* Macro to obtain ASN1_ITEM pointer from exported type */
+#define ASN1_ITEM_ptr(iptr) (iptr)
+
+/* Macro to include ASN1_ITEM pointer from base type */
+#define ASN1_ITEM_ref(iptr) (&(iptr##_it))
+
+#define ASN1_ITEM_rptr(ref) (&(ref##_it))
+
+#define DECLARE_ASN1_ITEM(name) \
+	OPENSSL_EXTERN const ASN1_ITEM name##_it;
+
+#else
+
+/* Platforms that can't easily handle shared global variables are declared
+ * as functions returning ASN1_ITEM pointers.
+ */
+
+/* ASN1_ITEM pointer exported type */
+typedef const ASN1_ITEM * ASN1_ITEM_EXP(void);
+
+/* Macro to obtain ASN1_ITEM pointer from exported type */
+#define ASN1_ITEM_ptr(iptr) (iptr())
+
+/* Macro to include ASN1_ITEM pointer from base type */
+#define ASN1_ITEM_ref(iptr) (iptr##_it)
+
+#define ASN1_ITEM_rptr(ref) (ref##_it())
+
+#define DECLARE_ASN1_ITEM(name) \
+	const ASN1_ITEM * name##_it(void);
+
+#endif
+
+/* Parameters used by ASN1_STRING_print_ex() */
+
+/* These determine which characters to escape:
+ * RFC2253 special characters, control characters and
+ * MSB set characters
+ */
+
+#define ASN1_STRFLGS_ESC_2253		1
+#define ASN1_STRFLGS_ESC_CTRL		2
+#define ASN1_STRFLGS_ESC_MSB		4
+
+
+/* This flag determines how we do escaping: normally
+ * RC2253 backslash only, set this to use backslash and
+ * quote.
+ */
+
+#define ASN1_STRFLGS_ESC_QUOTE		8
+
+
+/* These three flags are internal use only. */
+
+/* Character is a valid PrintableString character */
+#define CHARTYPE_PRINTABLESTRING	0x10
+/* Character needs escaping if it is the first character */
+#define CHARTYPE_FIRST_ESC_2253		0x20
+/* Character needs escaping if it is the last character */
+#define CHARTYPE_LAST_ESC_2253		0x40
+
+/* NB the internal flags are safely reused below by flags
+ * handled at the top level.
+ */
+
+/* If this is set we convert all character strings
+ * to UTF8 first 
+ */
+
+#define ASN1_STRFLGS_UTF8_CONVERT	0x10
+
+/* If this is set we don't attempt to interpret content:
+ * just assume all strings are 1 byte per character. This
+ * will produce some pretty odd looking output!
+ */
+
+#define ASN1_STRFLGS_IGNORE_TYPE	0x20
+
+/* If this is set we include the string type in the output */
+#define ASN1_STRFLGS_SHOW_TYPE		0x40
+
+/* This determines which strings to display and which to
+ * 'dump' (hex dump of content octets or DER encoding). We can
+ * only dump non character strings or everything. If we
+ * don't dump 'unknown' they are interpreted as character
+ * strings with 1 octet per character and are subject to
+ * the usual escaping options.
+ */
+
+#define ASN1_STRFLGS_DUMP_ALL		0x80
+#define ASN1_STRFLGS_DUMP_UNKNOWN	0x100
+
+/* These determine what 'dumping' does, we can dump the
+ * content octets or the DER encoding: both use the
+ * RFC2253 #XXXXX notation.
+ */
+
+#define ASN1_STRFLGS_DUMP_DER		0x200
+
+/* All the string flags consistent with RFC2253,
+ * escaping control characters isn't essential in
+ * RFC2253 but it is advisable anyway.
+ */
+
+#define ASN1_STRFLGS_RFC2253	(ASN1_STRFLGS_ESC_2253 | \
+				ASN1_STRFLGS_ESC_CTRL | \
+				ASN1_STRFLGS_ESC_MSB | \
+				ASN1_STRFLGS_UTF8_CONVERT | \
+				ASN1_STRFLGS_DUMP_UNKNOWN | \
+				ASN1_STRFLGS_DUMP_DER)
+
+DECLARE_STACK_OF(ASN1_INTEGER)
+DECLARE_ASN1_SET_OF(ASN1_INTEGER)
+
+DECLARE_STACK_OF(ASN1_GENERALSTRING)
+
+typedef struct asn1_type_st
+	{
+	int type;
+	union	{
+		char *ptr;
+		ASN1_BOOLEAN		boolean;
+		ASN1_STRING *		asn1_string;
+		ASN1_OBJECT *		object;
+		ASN1_INTEGER *		integer;
+		ASN1_ENUMERATED *	enumerated;
+		ASN1_BIT_STRING *	bit_string;
+		ASN1_OCTET_STRING *	octet_string;
+		ASN1_PRINTABLESTRING *	printablestring;
+		ASN1_T61STRING *	t61string;
+		ASN1_IA5STRING *	ia5string;
+		ASN1_GENERALSTRING *	generalstring;
+		ASN1_BMPSTRING *	bmpstring;
+		ASN1_UNIVERSALSTRING *	universalstring;
+		ASN1_UTCTIME *		utctime;
+		ASN1_GENERALIZEDTIME *	generalizedtime;
+		ASN1_VISIBLESTRING *	visiblestring;
+		ASN1_UTF8STRING *	utf8string;
+		/* set and sequence are left complete and still
+		 * contain the set or sequence bytes */
+		ASN1_STRING *		set;
+		ASN1_STRING *		sequence;
+		} value;
+	} ASN1_TYPE;
+
+DECLARE_STACK_OF(ASN1_TYPE)
+DECLARE_ASN1_SET_OF(ASN1_TYPE)
+
+typedef struct asn1_method_st
+	{
+	i2d_of_void *i2d;
+	d2i_of_void *d2i;
+	void *(*create)(void);
+	void (*destroy)(void *);
+	} ASN1_METHOD;
+
+/* This is used when parsing some Netscape objects */
+typedef struct asn1_header_st
+	{
+	ASN1_OCTET_STRING *header;
+	void *data;
+	ASN1_METHOD *meth;
+	} ASN1_HEADER;
+
+/* This is used to contain a list of bit names */
+typedef struct BIT_STRING_BITNAME_st {
+	int bitnum;
+	const char *lname;
+	const char *sname;
+} BIT_STRING_BITNAME;
+
+
+#define M_ASN1_STRING_length(x)	((x)->length)
+#define M_ASN1_STRING_length_set(x, n)	((x)->length = (n))
+#define M_ASN1_STRING_type(x)	((x)->type)
+#define M_ASN1_STRING_data(x)	((x)->data)
+
+/* Macros for string operations */
+#define M_ASN1_BIT_STRING_new()	(ASN1_BIT_STRING *)\
+		ASN1_STRING_type_new(V_ASN1_BIT_STRING)
+#define M_ASN1_BIT_STRING_free(a)	ASN1_STRING_free((ASN1_STRING *)a)
+#define M_ASN1_BIT_STRING_dup(a) (ASN1_BIT_STRING *)\
+		ASN1_STRING_dup((ASN1_STRING *)a)
+#define M_ASN1_BIT_STRING_cmp(a,b) ASN1_STRING_cmp(\
+		(ASN1_STRING *)a,(ASN1_STRING *)b)
+#define M_ASN1_BIT_STRING_set(a,b,c) ASN1_STRING_set((ASN1_STRING *)a,b,c)
+
+#define M_ASN1_INTEGER_new()	(ASN1_INTEGER *)\
+		ASN1_STRING_type_new(V_ASN1_INTEGER)
+#define M_ASN1_INTEGER_free(a)		ASN1_STRING_free((ASN1_STRING *)a)
+#define M_ASN1_INTEGER_dup(a) (ASN1_INTEGER *)ASN1_STRING_dup((ASN1_STRING *)a)
+#define M_ASN1_INTEGER_cmp(a,b)	ASN1_STRING_cmp(\
+		(ASN1_STRING *)a,(ASN1_STRING *)b)
+
+#define M_ASN1_ENUMERATED_new()	(ASN1_ENUMERATED *)\
+		ASN1_STRING_type_new(V_ASN1_ENUMERATED)
+#define M_ASN1_ENUMERATED_free(a)	ASN1_STRING_free((ASN1_STRING *)a)
+#define M_ASN1_ENUMERATED_dup(a) (ASN1_ENUMERATED *)ASN1_STRING_dup((ASN1_STRING *)a)
+#define M_ASN1_ENUMERATED_cmp(a,b)	ASN1_STRING_cmp(\
+		(ASN1_STRING *)a,(ASN1_STRING *)b)
+
+#define M_ASN1_OCTET_STRING_new()	(ASN1_OCTET_STRING *)\
+		ASN1_STRING_type_new(V_ASN1_OCTET_STRING)
+#define M_ASN1_OCTET_STRING_free(a)	ASN1_STRING_free((ASN1_STRING *)a)
+#define M_ASN1_OCTET_STRING_dup(a) (ASN1_OCTET_STRING *)\
+		ASN1_STRING_dup((ASN1_STRING *)a)
+#define M_ASN1_OCTET_STRING_cmp(a,b) ASN1_STRING_cmp(\
+		(ASN1_STRING *)a,(ASN1_STRING *)b)
+#define M_ASN1_OCTET_STRING_set(a,b,c)	ASN1_STRING_set((ASN1_STRING *)a,b,c)
+#define M_ASN1_OCTET_STRING_print(a,b)	ASN1_STRING_print(a,(ASN1_STRING *)b)
+#define M_i2d_ASN1_OCTET_STRING(a,pp) \
+		i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_OCTET_STRING,\
+		V_ASN1_UNIVERSAL)
+
+#define B_ASN1_TIME \
+			B_ASN1_UTCTIME | \
+			B_ASN1_GENERALIZEDTIME
+
+#define B_ASN1_PRINTABLE \
+			B_ASN1_PRINTABLESTRING| \
+			B_ASN1_T61STRING| \
+			B_ASN1_IA5STRING| \
+			B_ASN1_BIT_STRING| \
+			B_ASN1_UNIVERSALSTRING|\
+			B_ASN1_BMPSTRING|\
+			B_ASN1_UTF8STRING|\
+			B_ASN1_SEQUENCE|\
+			B_ASN1_UNKNOWN
+
+#define B_ASN1_DIRECTORYSTRING \
+			B_ASN1_PRINTABLESTRING| \
+			B_ASN1_TELETEXSTRING|\
+			B_ASN1_BMPSTRING|\
+			B_ASN1_UNIVERSALSTRING|\
+			B_ASN1_UTF8STRING
+
+#define B_ASN1_DISPLAYTEXT \
+			B_ASN1_IA5STRING| \
+			B_ASN1_VISIBLESTRING| \
+			B_ASN1_BMPSTRING|\
+			B_ASN1_UTF8STRING
+
+#define M_ASN1_PRINTABLE_new()	ASN1_STRING_type_new(V_ASN1_T61STRING)
+#define M_ASN1_PRINTABLE_free(a)	ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_ASN1_PRINTABLE(a,pp) i2d_ASN1_bytes((ASN1_STRING *)a,\
+		pp,a->type,V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_PRINTABLE(a,pp,l) \
+		d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l, \
+			B_ASN1_PRINTABLE)
+
+#define M_DIRECTORYSTRING_new() ASN1_STRING_type_new(V_ASN1_PRINTABLESTRING)
+#define M_DIRECTORYSTRING_free(a)	ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_DIRECTORYSTRING(a,pp) i2d_ASN1_bytes((ASN1_STRING *)a,\
+						pp,a->type,V_ASN1_UNIVERSAL)
+#define M_d2i_DIRECTORYSTRING(a,pp,l) \
+		d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l, \
+			B_ASN1_DIRECTORYSTRING)
+
+#define M_DISPLAYTEXT_new() ASN1_STRING_type_new(V_ASN1_VISIBLESTRING)
+#define M_DISPLAYTEXT_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_DISPLAYTEXT(a,pp) i2d_ASN1_bytes((ASN1_STRING *)a,\
+						pp,a->type,V_ASN1_UNIVERSAL)
+#define M_d2i_DISPLAYTEXT(a,pp,l) \
+		d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l, \
+			B_ASN1_DISPLAYTEXT)
+
+#define M_ASN1_PRINTABLESTRING_new() (ASN1_PRINTABLESTRING *)\
+		ASN1_STRING_type_new(V_ASN1_PRINTABLESTRING)
+#define M_ASN1_PRINTABLESTRING_free(a)	ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_ASN1_PRINTABLESTRING(a,pp) \
+		i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_PRINTABLESTRING,\
+		V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_PRINTABLESTRING(a,pp,l) \
+		(ASN1_PRINTABLESTRING *)d2i_ASN1_type_bytes\
+		((ASN1_STRING **)a,pp,l,B_ASN1_PRINTABLESTRING)
+
+#define M_ASN1_T61STRING_new()	(ASN1_T61STRING *)\
+		ASN1_STRING_type_new(V_ASN1_T61STRING)
+#define M_ASN1_T61STRING_free(a)	ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_ASN1_T61STRING(a,pp) \
+		i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_T61STRING,\
+		V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_T61STRING(a,pp,l) \
+		(ASN1_T61STRING *)d2i_ASN1_type_bytes\
+		((ASN1_STRING **)a,pp,l,B_ASN1_T61STRING)
+
+#define M_ASN1_IA5STRING_new()	(ASN1_IA5STRING *)\
+		ASN1_STRING_type_new(V_ASN1_IA5STRING)
+#define M_ASN1_IA5STRING_free(a)	ASN1_STRING_free((ASN1_STRING *)a)
+#define M_ASN1_IA5STRING_dup(a)	\
+			(ASN1_IA5STRING *)ASN1_STRING_dup((ASN1_STRING *)a)
+#define M_i2d_ASN1_IA5STRING(a,pp) \
+		i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_IA5STRING,\
+			V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_IA5STRING(a,pp,l) \
+		(ASN1_IA5STRING *)d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l,\
+			B_ASN1_IA5STRING)
+
+#define M_ASN1_UTCTIME_new()	(ASN1_UTCTIME *)\
+		ASN1_STRING_type_new(V_ASN1_UTCTIME)
+#define M_ASN1_UTCTIME_free(a)	ASN1_STRING_free((ASN1_STRING *)a)
+#define M_ASN1_UTCTIME_dup(a) (ASN1_UTCTIME *)ASN1_STRING_dup((ASN1_STRING *)a)
+
+#define M_ASN1_GENERALIZEDTIME_new()	(ASN1_GENERALIZEDTIME *)\
+		ASN1_STRING_type_new(V_ASN1_GENERALIZEDTIME)
+#define M_ASN1_GENERALIZEDTIME_free(a)	ASN1_STRING_free((ASN1_STRING *)a)
+#define M_ASN1_GENERALIZEDTIME_dup(a) (ASN1_GENERALIZEDTIME *)ASN1_STRING_dup(\
+	(ASN1_STRING *)a)
+
+#define M_ASN1_TIME_new()	(ASN1_TIME *)\
+		ASN1_STRING_type_new(V_ASN1_UTCTIME)
+#define M_ASN1_TIME_free(a)	ASN1_STRING_free((ASN1_STRING *)a)
+#define M_ASN1_TIME_dup(a) (ASN1_TIME *)ASN1_STRING_dup((ASN1_STRING *)a)
+
+#define M_ASN1_GENERALSTRING_new()	(ASN1_GENERALSTRING *)\
+		ASN1_STRING_type_new(V_ASN1_GENERALSTRING)
+#define M_ASN1_GENERALSTRING_free(a)	ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_ASN1_GENERALSTRING(a,pp) \
+		i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_GENERALSTRING,\
+			V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_GENERALSTRING(a,pp,l) \
+		(ASN1_GENERALSTRING *)d2i_ASN1_type_bytes\
+		((ASN1_STRING **)a,pp,l,B_ASN1_GENERALSTRING)
+
+#define M_ASN1_UNIVERSALSTRING_new()	(ASN1_UNIVERSALSTRING *)\
+		ASN1_STRING_type_new(V_ASN1_UNIVERSALSTRING)
+#define M_ASN1_UNIVERSALSTRING_free(a)	ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_ASN1_UNIVERSALSTRING(a,pp) \
+		i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_UNIVERSALSTRING,\
+			V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_UNIVERSALSTRING(a,pp,l) \
+		(ASN1_UNIVERSALSTRING *)d2i_ASN1_type_bytes\
+		((ASN1_STRING **)a,pp,l,B_ASN1_UNIVERSALSTRING)
+
+#define M_ASN1_BMPSTRING_new()	(ASN1_BMPSTRING *)\
+		ASN1_STRING_type_new(V_ASN1_BMPSTRING)
+#define M_ASN1_BMPSTRING_free(a)	ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_ASN1_BMPSTRING(a,pp) \
+		i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_BMPSTRING,\
+			V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_BMPSTRING(a,pp,l) \
+		(ASN1_BMPSTRING *)d2i_ASN1_type_bytes\
+		((ASN1_STRING **)a,pp,l,B_ASN1_BMPSTRING)
+
+#define M_ASN1_VISIBLESTRING_new()	(ASN1_VISIBLESTRING *)\
+		ASN1_STRING_type_new(V_ASN1_VISIBLESTRING)
+#define M_ASN1_VISIBLESTRING_free(a)	ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_ASN1_VISIBLESTRING(a,pp) \
+		i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_VISIBLESTRING,\
+			V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_VISIBLESTRING(a,pp,l) \
+		(ASN1_VISIBLESTRING *)d2i_ASN1_type_bytes\
+		((ASN1_STRING **)a,pp,l,B_ASN1_VISIBLESTRING)
+
+#define M_ASN1_UTF8STRING_new()	(ASN1_UTF8STRING *)\
+		ASN1_STRING_type_new(V_ASN1_UTF8STRING)
+#define M_ASN1_UTF8STRING_free(a)	ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_ASN1_UTF8STRING(a,pp) \
+		i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_UTF8STRING,\
+			V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_UTF8STRING(a,pp,l) \
+		(ASN1_UTF8STRING *)d2i_ASN1_type_bytes\
+		((ASN1_STRING **)a,pp,l,B_ASN1_UTF8STRING)
+
+  /* for the is_set parameter to i2d_ASN1_SET */
+#define IS_SEQUENCE	0
+#define IS_SET		1
+
+DECLARE_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE)
+
+int ASN1_TYPE_get(ASN1_TYPE *a);
+void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value);
+
+ASN1_OBJECT *	ASN1_OBJECT_new(void );
+void		ASN1_OBJECT_free(ASN1_OBJECT *a);
+int		i2d_ASN1_OBJECT(ASN1_OBJECT *a,unsigned char **pp);
+ASN1_OBJECT *	c2i_ASN1_OBJECT(ASN1_OBJECT **a,const unsigned char **pp,
+			long length);
+ASN1_OBJECT *	d2i_ASN1_OBJECT(ASN1_OBJECT **a,const unsigned char **pp,
+			long length);
+
+DECLARE_ASN1_ITEM(ASN1_OBJECT)
+
+DECLARE_STACK_OF(ASN1_OBJECT)
+DECLARE_ASN1_SET_OF(ASN1_OBJECT)
+
+ASN1_STRING *	ASN1_STRING_new(void);
+void		ASN1_STRING_free(ASN1_STRING *a);
+ASN1_STRING *	ASN1_STRING_dup(ASN1_STRING *a);
+ASN1_STRING *	ASN1_STRING_type_new(int type );
+int 		ASN1_STRING_cmp(ASN1_STRING *a, ASN1_STRING *b);
+  /* Since this is used to store all sorts of things, via macros, for now, make
+     its data void * */
+int 		ASN1_STRING_set(ASN1_STRING *str, const void *data, int len);
+int ASN1_STRING_length(ASN1_STRING *x);
+void ASN1_STRING_length_set(ASN1_STRING *x, int n);
+int ASN1_STRING_type(ASN1_STRING *x);
+unsigned char * ASN1_STRING_data(ASN1_STRING *x);
+
+DECLARE_ASN1_FUNCTIONS(ASN1_BIT_STRING)
+int		i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a,unsigned char **pp);
+ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,const unsigned char **pp,
+			long length);
+int		ASN1_BIT_STRING_set(ASN1_BIT_STRING *a, unsigned char *d,
+			int length );
+int		ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value);
+int		ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *a, int n);
+
+#ifndef OPENSSL_NO_BIO
+int ASN1_BIT_STRING_name_print(BIO *out, ASN1_BIT_STRING *bs,
+				BIT_STRING_BITNAME *tbl, int indent);
+#endif
+int ASN1_BIT_STRING_num_asc(char *name, BIT_STRING_BITNAME *tbl);
+int ASN1_BIT_STRING_set_asc(ASN1_BIT_STRING *bs, char *name, int value,
+				BIT_STRING_BITNAME *tbl);
+
+int		i2d_ASN1_BOOLEAN(int a,unsigned char **pp);
+int 		d2i_ASN1_BOOLEAN(int *a,const unsigned char **pp,long length);
+
+DECLARE_ASN1_FUNCTIONS(ASN1_INTEGER)
+int		i2c_ASN1_INTEGER(ASN1_INTEGER *a,unsigned char **pp);
+ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a,const unsigned char **pp,
+			long length);
+ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a,const unsigned char **pp,
+			long length);
+ASN1_INTEGER *	ASN1_INTEGER_dup(ASN1_INTEGER *x);
+int ASN1_INTEGER_cmp(ASN1_INTEGER *x, ASN1_INTEGER *y);
+
+DECLARE_ASN1_FUNCTIONS(ASN1_ENUMERATED)
+
+int ASN1_UTCTIME_check(ASN1_UTCTIME *a);
+ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s,time_t t);
+int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str);
+int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t);
+#if 0
+time_t ASN1_UTCTIME_get(const ASN1_UTCTIME *s);
+#endif
+
+int ASN1_GENERALIZEDTIME_check(ASN1_GENERALIZEDTIME *a);
+ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s,time_t t);
+int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str);
+
+DECLARE_ASN1_FUNCTIONS(ASN1_OCTET_STRING)
+ASN1_OCTET_STRING *	ASN1_OCTET_STRING_dup(ASN1_OCTET_STRING *a);
+int 	ASN1_OCTET_STRING_cmp(ASN1_OCTET_STRING *a, ASN1_OCTET_STRING *b);
+int 	ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *str, const unsigned char *data, int len);
+
+DECLARE_ASN1_FUNCTIONS(ASN1_VISIBLESTRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_UNIVERSALSTRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_UTF8STRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_NULL)
+DECLARE_ASN1_FUNCTIONS(ASN1_BMPSTRING)
+
+int UTF8_getc(const unsigned char *str, int len, unsigned long *val);
+int UTF8_putc(unsigned char *str, int len, unsigned long value);
+
+DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, ASN1_PRINTABLE)
+
+DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, DIRECTORYSTRING)
+DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, DISPLAYTEXT)
+DECLARE_ASN1_FUNCTIONS(ASN1_PRINTABLESTRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_T61STRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_IA5STRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_GENERALSTRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_UTCTIME)
+DECLARE_ASN1_FUNCTIONS(ASN1_GENERALIZEDTIME)
+DECLARE_ASN1_FUNCTIONS(ASN1_TIME)
+
+DECLARE_ASN1_ITEM(ASN1_OCTET_STRING_NDEF)
+
+ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s,time_t t);
+int ASN1_TIME_check(ASN1_TIME *t);
+ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out);
+
+int i2d_ASN1_SET(STACK *a, unsigned char **pp,
+		 i2d_of_void *i2d, int ex_tag, int ex_class, int is_set);
+STACK *	d2i_ASN1_SET(STACK **a, const unsigned char **pp, long length,
+		     d2i_of_void *d2i, void (*free_func)(void *),
+		     int ex_tag, int ex_class);
+
+#ifndef OPENSSL_NO_BIO
+int i2a_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *a);
+int a2i_ASN1_INTEGER(BIO *bp,ASN1_INTEGER *bs,char *buf,int size);
+int i2a_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *a);
+int a2i_ASN1_ENUMERATED(BIO *bp,ASN1_ENUMERATED *bs,char *buf,int size);
+int i2a_ASN1_OBJECT(BIO *bp,ASN1_OBJECT *a);
+int a2i_ASN1_STRING(BIO *bp,ASN1_STRING *bs,char *buf,int size);
+int i2a_ASN1_STRING(BIO *bp, ASN1_STRING *a, int type);
+#endif
+int i2t_ASN1_OBJECT(char *buf,int buf_len,ASN1_OBJECT *a);
+
+int a2d_ASN1_OBJECT(unsigned char *out,int olen, const char *buf, int num);
+ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data,int len,
+	const char *sn, const char *ln);
+
+int ASN1_INTEGER_set(ASN1_INTEGER *a, long v);
+long ASN1_INTEGER_get(ASN1_INTEGER *a);
+ASN1_INTEGER *BN_to_ASN1_INTEGER(BIGNUM *bn, ASN1_INTEGER *ai);
+BIGNUM *ASN1_INTEGER_to_BN(ASN1_INTEGER *ai,BIGNUM *bn);
+
+int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v);
+long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a);
+ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(BIGNUM *bn, ASN1_ENUMERATED *ai);
+BIGNUM *ASN1_ENUMERATED_to_BN(ASN1_ENUMERATED *ai,BIGNUM *bn);
+
+/* General */
+/* given a string, return the correct type, max is the maximum length */
+int ASN1_PRINTABLE_type(const unsigned char *s, int max);
+
+int i2d_ASN1_bytes(ASN1_STRING *a, unsigned char **pp, int tag, int xclass);
+ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp,
+	long length, int Ptag, int Pclass);
+unsigned long ASN1_tag2bit(int tag);
+/* type is one or more of the B_ASN1_ values. */
+ASN1_STRING *d2i_ASN1_type_bytes(ASN1_STRING **a,const unsigned char **pp,
+		long length,int type);
+
+/* PARSING */
+int asn1_Finish(ASN1_CTX *c);
+int asn1_const_Finish(ASN1_const_CTX *c);
+
+/* SPECIALS */
+int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
+	int *pclass, long omax);
+int ASN1_check_infinite_end(unsigned char **p,long len);
+int ASN1_const_check_infinite_end(const unsigned char **p,long len);
+void ASN1_put_object(unsigned char **pp, int constructed, int length,
+	int tag, int xclass);
+int ASN1_put_eoc(unsigned char **pp);
+int ASN1_object_size(int constructed, int length, int tag);
+
+/* Used to implement other functions */
+void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, char *x);
+#define ASN1_dup_of(type,i2d,d2i,x) \
+	((type *(*)(I2D_OF(type),D2I_OF(type),type *))openssl_fcast(ASN1_dup))(i2d,d2i,x)
+#define ASN1_dup_of_const(type,i2d,d2i,x) \
+	((type *(*)(I2D_OF_const(type),D2I_OF(type),type *))openssl_fcast(ASN1_dup))(i2d,d2i,x)
+
+void *ASN1_item_dup(const ASN1_ITEM *it, void *x);
+
+#ifndef OPENSSL_NO_FP_API
+void *ASN1_d2i_fp(void *(*xnew)(void), d2i_of_void *d2i, FILE *in, void **x);
+#define ASN1_d2i_fp_of(type,xnew,d2i,in,x) \
+	((type *(*)(type *(*)(void),D2I_OF(type),FILE *,type **))openssl_fcast(ASN1_d2i_fp))(xnew,d2i,in,x)
+void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x);
+int ASN1_i2d_fp(i2d_of_void *i2d,FILE *out,void *x);
+#define ASN1_i2d_fp_of(type,i2d,out,x) \
+	((int (*)(I2D_OF(type),FILE *,type *))openssl_fcast(ASN1_i2d_fp))(i2d,out,x)
+#define ASN1_i2d_fp_of_const(type,i2d,out,x) \
+	((int (*)(I2D_OF_const(type),FILE *,type *))openssl_fcast(ASN1_i2d_fp))(i2d,out,x)
+int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x);
+int ASN1_STRING_print_ex_fp(FILE *fp, ASN1_STRING *str, unsigned long flags);
+#endif
+
+int ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in);
+
+#ifndef OPENSSL_NO_BIO
+void *ASN1_d2i_bio(void *(*xnew)(void), d2i_of_void *d2i, BIO *in, void **x);
+#define ASN1_d2i_bio_of(type,xnew,d2i,in,x) \
+	((type *(*)(type *(*)(void),D2I_OF(type),BIO *,type **))openssl_fcast(ASN1_d2i_bio))(xnew,d2i,in,x)
+void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x);
+int ASN1_i2d_bio(i2d_of_void *i2d,BIO *out, unsigned char *x);
+#define ASN1_i2d_bio_of(type,i2d,out,x) \
+	((int (*)(I2D_OF(type),BIO *,type *))openssl_fcast(ASN1_i2d_bio))(i2d,out,x)
+#define ASN1_i2d_bio_of_const(type,i2d,out,x) \
+	((int (*)(I2D_OF_const(type),BIO *,const type *))openssl_fcast(ASN1_i2d_bio))(i2d,out,x)
+int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x);
+int ASN1_UTCTIME_print(BIO *fp,ASN1_UTCTIME *a);
+int ASN1_GENERALIZEDTIME_print(BIO *fp,ASN1_GENERALIZEDTIME *a);
+int ASN1_TIME_print(BIO *fp,ASN1_TIME *a);
+int ASN1_STRING_print(BIO *bp,ASN1_STRING *v);
+int ASN1_STRING_print_ex(BIO *out, ASN1_STRING *str, unsigned long flags);
+int ASN1_parse(BIO *bp,const unsigned char *pp,long len,int indent);
+int ASN1_parse_dump(BIO *bp,const unsigned char *pp,long len,int indent,int dump);
+#endif
+const char *ASN1_tag2str(int tag);
+
+/* Used to load and write netscape format cert/key */
+int i2d_ASN1_HEADER(ASN1_HEADER *a,unsigned char **pp);
+ASN1_HEADER *d2i_ASN1_HEADER(ASN1_HEADER **a,const unsigned char **pp, long length);
+ASN1_HEADER *ASN1_HEADER_new(void );
+void ASN1_HEADER_free(ASN1_HEADER *a);
+
+int ASN1_UNIVERSALSTRING_to_string(ASN1_UNIVERSALSTRING *s);
+
+/* Not used that much at this point, except for the first two */
+ASN1_METHOD *X509_asn1_meth(void);
+ASN1_METHOD *RSAPrivateKey_asn1_meth(void);
+ASN1_METHOD *ASN1_IA5STRING_asn1_meth(void);
+ASN1_METHOD *ASN1_BIT_STRING_asn1_meth(void);
+
+int ASN1_TYPE_set_octetstring(ASN1_TYPE *a,
+	unsigned char *data, int len);
+int ASN1_TYPE_get_octetstring(ASN1_TYPE *a,
+	unsigned char *data, int max_len);
+int ASN1_TYPE_set_int_octetstring(ASN1_TYPE *a, long num,
+	unsigned char *data, int len);
+int ASN1_TYPE_get_int_octetstring(ASN1_TYPE *a,long *num,
+	unsigned char *data, int max_len);
+
+STACK *ASN1_seq_unpack(const unsigned char *buf, int len,
+		       d2i_of_void *d2i, void (*free_func)(void *));
+unsigned char *ASN1_seq_pack(STACK *safes, i2d_of_void *i2d,
+			     unsigned char **buf, int *len );
+void *ASN1_unpack_string(ASN1_STRING *oct, d2i_of_void *d2i);
+void *ASN1_item_unpack(ASN1_STRING *oct, const ASN1_ITEM *it);
+ASN1_STRING *ASN1_pack_string(void *obj, i2d_of_void *i2d,
+			      ASN1_OCTET_STRING **oct);
+#define ASN1_pack_string_of(type,obj,i2d,oct) \
+	((ASN1_STRING *(*)(type *,I2D_OF(type),ASN1_OCTET_STRING **))openssl_fcast(ASN1_pack_string))(obj,i2d,oct)
+ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_OCTET_STRING **oct);
+
+void ASN1_STRING_set_default_mask(unsigned long mask);
+int ASN1_STRING_set_default_mask_asc(char *p);
+unsigned long ASN1_STRING_get_default_mask(void);
+int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
+					int inform, unsigned long mask);
+int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
+					int inform, unsigned long mask, 
+					long minsize, long maxsize);
+
+ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, 
+		const unsigned char *in, int inlen, int inform, int nid);
+ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid);
+int ASN1_STRING_TABLE_add(int, long, long, unsigned long, unsigned long);
+void ASN1_STRING_TABLE_cleanup(void);
+
+/* ASN1 template functions */
+
+/* Old API compatible functions */
+ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it);
+void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it);
+ASN1_VALUE * ASN1_item_d2i(ASN1_VALUE **val, const unsigned char **in, long len, const ASN1_ITEM *it);
+int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it);
+int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it);
+
+void ASN1_add_oid_module(void);
+
+ASN1_TYPE *ASN1_generate_nconf(char *str, CONF *nconf);
+ASN1_TYPE *ASN1_generate_v3(char *str, X509V3_CTX *cnf);
+	
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_ASN1_strings(void);
+
+/* Error codes for the ASN1 functions. */
+
+/* Function codes. */
+#define ASN1_F_A2D_ASN1_OBJECT				 100
+#define ASN1_F_A2I_ASN1_ENUMERATED			 101
+#define ASN1_F_A2I_ASN1_INTEGER				 102
+#define ASN1_F_A2I_ASN1_STRING				 103
+#define ASN1_F_APPEND_EXP				 176
+#define ASN1_F_ASN1_BIT_STRING_SET_BIT			 183
+#define ASN1_F_ASN1_CB					 177
+#define ASN1_F_ASN1_CHECK_TLEN				 104
+#define ASN1_F_ASN1_COLLATE_PRIMITIVE			 105
+#define ASN1_F_ASN1_COLLECT				 106
+#define ASN1_F_ASN1_D2I_EX_PRIMITIVE			 108
+#define ASN1_F_ASN1_D2I_FP				 109
+#define ASN1_F_ASN1_D2I_READ_BIO			 107
+#define ASN1_F_ASN1_DIGEST				 184
+#define ASN1_F_ASN1_DO_ADB				 110
+#define ASN1_F_ASN1_DUP					 111
+#define ASN1_F_ASN1_ENUMERATED_SET			 112
+#define ASN1_F_ASN1_ENUMERATED_TO_BN			 113
+#define ASN1_F_ASN1_EX_C2I				 204
+#define ASN1_F_ASN1_FIND_END				 190
+#define ASN1_F_ASN1_GENERALIZEDTIME_SET			 185
+#define ASN1_F_ASN1_GENERATE_V3				 178
+#define ASN1_F_ASN1_GET_OBJECT				 114
+#define ASN1_F_ASN1_HEADER_NEW				 115
+#define ASN1_F_ASN1_I2D_BIO				 116
+#define ASN1_F_ASN1_I2D_FP				 117
+#define ASN1_F_ASN1_INTEGER_SET				 118
+#define ASN1_F_ASN1_INTEGER_TO_BN			 119
+#define ASN1_F_ASN1_ITEM_D2I_FP				 206
+#define ASN1_F_ASN1_ITEM_DUP				 191
+#define ASN1_F_ASN1_ITEM_EX_COMBINE_NEW			 121
+#define ASN1_F_ASN1_ITEM_EX_D2I				 120
+#define ASN1_F_ASN1_ITEM_I2D_BIO			 192
+#define ASN1_F_ASN1_ITEM_I2D_FP				 193
+#define ASN1_F_ASN1_ITEM_PACK				 198
+#define ASN1_F_ASN1_ITEM_SIGN				 195
+#define ASN1_F_ASN1_ITEM_UNPACK				 199
+#define ASN1_F_ASN1_ITEM_VERIFY				 197
+#define ASN1_F_ASN1_MBSTRING_NCOPY			 122
+#define ASN1_F_ASN1_OBJECT_NEW				 123
+#define ASN1_F_ASN1_PACK_STRING				 124
+#define ASN1_F_ASN1_PCTX_NEW				 205
+#define ASN1_F_ASN1_PKCS5_PBE_SET			 125
+#define ASN1_F_ASN1_SEQ_PACK				 126
+#define ASN1_F_ASN1_SEQ_UNPACK				 127
+#define ASN1_F_ASN1_SIGN				 128
+#define ASN1_F_ASN1_STR2TYPE				 179
+#define ASN1_F_ASN1_STRING_SET				 186
+#define ASN1_F_ASN1_STRING_TABLE_ADD			 129
+#define ASN1_F_ASN1_STRING_TYPE_NEW			 130
+#define ASN1_F_ASN1_TEMPLATE_EX_D2I			 132
+#define ASN1_F_ASN1_TEMPLATE_NEW			 133
+#define ASN1_F_ASN1_TEMPLATE_NOEXP_D2I			 131
+#define ASN1_F_ASN1_TIME_SET				 175
+#define ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING		 134
+#define ASN1_F_ASN1_TYPE_GET_OCTETSTRING		 135
+#define ASN1_F_ASN1_UNPACK_STRING			 136
+#define ASN1_F_ASN1_UTCTIME_SET				 187
+#define ASN1_F_ASN1_VERIFY				 137
+#define ASN1_F_BITSTR_CB				 180
+#define ASN1_F_BN_TO_ASN1_ENUMERATED			 138
+#define ASN1_F_BN_TO_ASN1_INTEGER			 139
+#define ASN1_F_C2I_ASN1_BIT_STRING			 189
+#define ASN1_F_C2I_ASN1_INTEGER				 194
+#define ASN1_F_C2I_ASN1_OBJECT				 196
+#define ASN1_F_COLLECT_DATA				 140
+#define ASN1_F_D2I_ASN1_BIT_STRING			 141
+#define ASN1_F_D2I_ASN1_BOOLEAN				 142
+#define ASN1_F_D2I_ASN1_BYTES				 143
+#define ASN1_F_D2I_ASN1_GENERALIZEDTIME			 144
+#define ASN1_F_D2I_ASN1_HEADER				 145
+#define ASN1_F_D2I_ASN1_INTEGER				 146
+#define ASN1_F_D2I_ASN1_OBJECT				 147
+#define ASN1_F_D2I_ASN1_SET				 148
+#define ASN1_F_D2I_ASN1_TYPE_BYTES			 149
+#define ASN1_F_D2I_ASN1_UINTEGER			 150
+#define ASN1_F_D2I_ASN1_UTCTIME				 151
+#define ASN1_F_D2I_NETSCAPE_RSA				 152
+#define ASN1_F_D2I_NETSCAPE_RSA_2			 153
+#define ASN1_F_D2I_PRIVATEKEY				 154
+#define ASN1_F_D2I_PUBLICKEY				 155
+#define ASN1_F_D2I_RSA_NET				 200
+#define ASN1_F_D2I_RSA_NET_2				 201
+#define ASN1_F_D2I_X509					 156
+#define ASN1_F_D2I_X509_CINF				 157
+#define ASN1_F_D2I_X509_PKEY				 159
+#define ASN1_F_I2D_ASN1_SET				 188
+#define ASN1_F_I2D_ASN1_TIME				 160
+#define ASN1_F_I2D_DSA_PUBKEY				 161
+#define ASN1_F_I2D_EC_PUBKEY				 181
+#define ASN1_F_I2D_PRIVATEKEY				 163
+#define ASN1_F_I2D_PUBLICKEY				 164
+#define ASN1_F_I2D_RSA_NET				 162
+#define ASN1_F_I2D_RSA_PUBKEY				 165
+#define ASN1_F_LONG_C2I					 166
+#define ASN1_F_OID_MODULE_INIT				 174
+#define ASN1_F_PARSE_TAGGING				 182
+#define ASN1_F_PKCS5_PBE2_SET				 167
+#define ASN1_F_PKCS5_PBE_SET				 202
+#define ASN1_F_X509_CINF_NEW				 168
+#define ASN1_F_X509_CRL_ADD0_REVOKED			 169
+#define ASN1_F_X509_INFO_NEW				 170
+#define ASN1_F_X509_NAME_ENCODE				 203
+#define ASN1_F_X509_NAME_EX_D2I				 158
+#define ASN1_F_X509_NAME_EX_NEW				 171
+#define ASN1_F_X509_NEW					 172
+#define ASN1_F_X509_PKEY_NEW				 173
+
+/* Reason codes. */
+#define ASN1_R_ADDING_OBJECT				 171
+#define ASN1_R_AUX_ERROR				 100
+#define ASN1_R_BAD_CLASS				 101
+#define ASN1_R_BAD_OBJECT_HEADER			 102
+#define ASN1_R_BAD_PASSWORD_READ			 103
+#define ASN1_R_BAD_TAG					 104
+#define ASN1_R_BN_LIB					 105
+#define ASN1_R_BOOLEAN_IS_WRONG_LENGTH			 106
+#define ASN1_R_BUFFER_TOO_SMALL				 107
+#define ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER		 108
+#define ASN1_R_DATA_IS_WRONG				 109
+#define ASN1_R_DECODE_ERROR				 110
+#define ASN1_R_DECODING_ERROR				 111
+#define ASN1_R_DEPTH_EXCEEDED				 174
+#define ASN1_R_ENCODE_ERROR				 112
+#define ASN1_R_ERROR_GETTING_TIME			 173
+#define ASN1_R_ERROR_LOADING_SECTION			 172
+#define ASN1_R_ERROR_PARSING_SET_ELEMENT		 113
+#define ASN1_R_ERROR_SETTING_CIPHER_PARAMS		 114
+#define ASN1_R_EXPECTING_AN_INTEGER			 115
+#define ASN1_R_EXPECTING_AN_OBJECT			 116
+#define ASN1_R_EXPECTING_A_BOOLEAN			 117
+#define ASN1_R_EXPECTING_A_TIME				 118
+#define ASN1_R_EXPLICIT_LENGTH_MISMATCH			 119
+#define ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED		 120
+#define ASN1_R_FIELD_MISSING				 121
+#define ASN1_R_FIRST_NUM_TOO_LARGE			 122
+#define ASN1_R_HEADER_TOO_LONG				 123
+#define ASN1_R_ILLEGAL_BITSTRING_FORMAT			 175
+#define ASN1_R_ILLEGAL_BOOLEAN				 176
+#define ASN1_R_ILLEGAL_CHARACTERS			 124
+#define ASN1_R_ILLEGAL_FORMAT				 177
+#define ASN1_R_ILLEGAL_HEX				 178
+#define ASN1_R_ILLEGAL_IMPLICIT_TAG			 179
+#define ASN1_R_ILLEGAL_INTEGER				 180
+#define ASN1_R_ILLEGAL_NESTED_TAGGING			 181
+#define ASN1_R_ILLEGAL_NULL				 125
+#define ASN1_R_ILLEGAL_NULL_VALUE			 182
+#define ASN1_R_ILLEGAL_OBJECT				 183
+#define ASN1_R_ILLEGAL_OPTIONAL_ANY			 126
+#define ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE		 170
+#define ASN1_R_ILLEGAL_TAGGED_ANY			 127
+#define ASN1_R_ILLEGAL_TIME_VALUE			 184
+#define ASN1_R_INTEGER_NOT_ASCII_FORMAT			 185
+#define ASN1_R_INTEGER_TOO_LARGE_FOR_LONG		 128
+#define ASN1_R_INVALID_BMPSTRING_LENGTH			 129
+#define ASN1_R_INVALID_DIGIT				 130
+#define ASN1_R_INVALID_MODIFIER				 186
+#define ASN1_R_INVALID_NUMBER				 187
+#define ASN1_R_INVALID_SEPARATOR			 131
+#define ASN1_R_INVALID_TIME_FORMAT			 132
+#define ASN1_R_INVALID_UNIVERSALSTRING_LENGTH		 133
+#define ASN1_R_INVALID_UTF8STRING			 134
+#define ASN1_R_IV_TOO_LARGE				 135
+#define ASN1_R_LENGTH_ERROR				 136
+#define ASN1_R_LIST_ERROR				 188
+#define ASN1_R_MISSING_EOC				 137
+#define ASN1_R_MISSING_SECOND_NUMBER			 138
+#define ASN1_R_MISSING_VALUE				 189
+#define ASN1_R_MSTRING_NOT_UNIVERSAL			 139
+#define ASN1_R_MSTRING_WRONG_TAG			 140
+#define ASN1_R_NESTED_ASN1_STRING			 197
+#define ASN1_R_NON_HEX_CHARACTERS			 141
+#define ASN1_R_NOT_ASCII_FORMAT				 190
+#define ASN1_R_NOT_ENOUGH_DATA				 142
+#define ASN1_R_NO_MATCHING_CHOICE_TYPE			 143
+#define ASN1_R_NULL_IS_WRONG_LENGTH			 144
+#define ASN1_R_OBJECT_NOT_ASCII_FORMAT			 191
+#define ASN1_R_ODD_NUMBER_OF_CHARS			 145
+#define ASN1_R_PRIVATE_KEY_HEADER_MISSING		 146
+#define ASN1_R_SECOND_NUMBER_TOO_LARGE			 147
+#define ASN1_R_SEQUENCE_LENGTH_MISMATCH			 148
+#define ASN1_R_SEQUENCE_NOT_CONSTRUCTED			 149
+#define ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG		 192
+#define ASN1_R_SHORT_LINE				 150
+#define ASN1_R_STRING_TOO_LONG				 151
+#define ASN1_R_STRING_TOO_SHORT				 152
+#define ASN1_R_TAG_VALUE_TOO_HIGH			 153
+#define ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 154
+#define ASN1_R_TIME_NOT_ASCII_FORMAT			 193
+#define ASN1_R_TOO_LONG					 155
+#define ASN1_R_TYPE_NOT_CONSTRUCTED			 156
+#define ASN1_R_UNABLE_TO_DECODE_RSA_KEY			 157
+#define ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY		 158
+#define ASN1_R_UNEXPECTED_EOC				 159
+#define ASN1_R_UNKNOWN_FORMAT				 160
+#define ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM		 161
+#define ASN1_R_UNKNOWN_OBJECT_TYPE			 162
+#define ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE			 163
+#define ASN1_R_UNKNOWN_TAG				 194
+#define ASN1_R_UNKOWN_FORMAT				 195
+#define ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE		 164
+#define ASN1_R_UNSUPPORTED_CIPHER			 165
+#define ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM		 166
+#define ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE		 167
+#define ASN1_R_UNSUPPORTED_TYPE				 196
+#define ASN1_R_WRONG_TAG				 168
+#define ASN1_R_WRONG_TYPE				 169
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/dep/include/openssl/asn1_mac.h b/dep/include/openssl/asn1_mac.h
new file mode 100644
index 00000000000..d958ca60d9d
--- /dev/null
+++ b/dep/include/openssl/asn1_mac.h
@@ -0,0 +1,571 @@
+/* crypto/asn1/asn1_mac.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_ASN1_MAC_H
+#define HEADER_ASN1_MAC_H
+
+#include 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#ifndef ASN1_MAC_ERR_LIB
+#define ASN1_MAC_ERR_LIB	ERR_LIB_ASN1
+#endif 
+
+#define ASN1_MAC_H_err(f,r,line) \
+	ERR_PUT_error(ASN1_MAC_ERR_LIB,(f),(r),__FILE__,(line))
+
+#define M_ASN1_D2I_vars(a,type,func) \
+	ASN1_const_CTX c; \
+	type ret=NULL; \
+	\
+	c.pp=(const unsigned char **)pp; \
+	c.q= *(const unsigned char **)pp; \
+	c.error=ERR_R_NESTED_ASN1_ERROR; \
+	if ((a == NULL) || ((*a) == NULL)) \
+		{ if ((ret=(type)func()) == NULL) \
+			{ c.line=__LINE__; goto err; } } \
+	else	ret=(*a);
+
+#define M_ASN1_D2I_Init() \
+	c.p= *(const unsigned char **)pp; \
+	c.max=(length == 0)?0:(c.p+length);
+
+#define M_ASN1_D2I_Finish_2(a) \
+	if (!asn1_const_Finish(&c)) \
+		{ c.line=__LINE__; goto err; } \
+	*(const unsigned char **)pp=c.p; \
+	if (a != NULL) (*a)=ret; \
+	return(ret);
+
+#define M_ASN1_D2I_Finish(a,func,e) \
+	M_ASN1_D2I_Finish_2(a); \
+err:\
+	ASN1_MAC_H_err((e),c.error,c.line); \
+	asn1_add_error(*(const unsigned char **)pp,(int)(c.q- *pp)); \
+	if ((ret != NULL) && ((a == NULL) || (*a != ret))) func(ret); \
+	return(NULL)
+
+#define M_ASN1_D2I_start_sequence() \
+	if (!asn1_GetSequence(&c,&length)) \
+		{ c.line=__LINE__; goto err; }
+/* Begin reading ASN1 without a surrounding sequence */
+#define M_ASN1_D2I_begin() \
+	c.slen = length;
+
+/* End reading ASN1 with no check on length */
+#define M_ASN1_D2I_Finish_nolen(a, func, e) \
+	*pp=c.p; \
+	if (a != NULL) (*a)=ret; \
+	return(ret); \
+err:\
+	ASN1_MAC_H_err((e),c.error,c.line); \
+	asn1_add_error(*pp,(int)(c.q- *pp)); \
+	if ((ret != NULL) && ((a == NULL) || (*a != ret))) func(ret); \
+	return(NULL)
+
+#define M_ASN1_D2I_end_sequence() \
+	(((c.inf&1) == 0)?(c.slen <= 0): \
+		(c.eos=ASN1_const_check_infinite_end(&c.p,c.slen)))
+
+/* Don't use this with d2i_ASN1_BOOLEAN() */
+#define M_ASN1_D2I_get(b, func) \
+	c.q=c.p; \
+	if (func(&(b),&c.p,c.slen) == NULL) \
+		{c.line=__LINE__; goto err; } \
+	c.slen-=(c.p-c.q);
+
+/* Don't use this with d2i_ASN1_BOOLEAN() */
+#define M_ASN1_D2I_get_x(type,b,func) \
+	c.q=c.p; \
+	if (((D2I_OF(type))func)(&(b),&c.p,c.slen) == NULL) \
+		{c.line=__LINE__; goto err; } \
+	c.slen-=(c.p-c.q);
+
+/* use this instead () */
+#define M_ASN1_D2I_get_int(b,func) \
+	c.q=c.p; \
+	if (func(&(b),&c.p,c.slen) < 0) \
+		{c.line=__LINE__; goto err; } \
+	c.slen-=(c.p-c.q);
+
+#define M_ASN1_D2I_get_opt(b,func,type) \
+	if ((c.slen != 0) && ((M_ASN1_next & (~V_ASN1_CONSTRUCTED)) \
+		== (V_ASN1_UNIVERSAL|(type)))) \
+		{ \
+		M_ASN1_D2I_get(b,func); \
+		}
+
+#define M_ASN1_D2I_get_imp(b,func, type) \
+	M_ASN1_next=(_tmp& V_ASN1_CONSTRUCTED)|type; \
+	c.q=c.p; \
+	if (func(&(b),&c.p,c.slen) == NULL) \
+		{c.line=__LINE__; M_ASN1_next_prev = _tmp; goto err; } \
+	c.slen-=(c.p-c.q);\
+	M_ASN1_next_prev=_tmp;
+
+#define M_ASN1_D2I_get_IMP_opt(b,func,tag,type) \
+	if ((c.slen != 0) && ((M_ASN1_next & (~V_ASN1_CONSTRUCTED)) == \
+		(V_ASN1_CONTEXT_SPECIFIC|(tag)))) \
+		{ \
+		unsigned char _tmp = M_ASN1_next; \
+		M_ASN1_D2I_get_imp(b,func, type);\
+		}
+
+#define M_ASN1_D2I_get_set(r,func,free_func) \
+		M_ASN1_D2I_get_imp_set(r,func,free_func, \
+			V_ASN1_SET,V_ASN1_UNIVERSAL);
+
+#define M_ASN1_D2I_get_set_type(type,r,func,free_func) \
+		M_ASN1_D2I_get_imp_set_type(type,r,func,free_func, \
+			V_ASN1_SET,V_ASN1_UNIVERSAL);
+
+#define M_ASN1_D2I_get_set_opt(r,func,free_func) \
+	if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \
+		V_ASN1_CONSTRUCTED|V_ASN1_SET)))\
+		{ M_ASN1_D2I_get_set(r,func,free_func); }
+
+#define M_ASN1_D2I_get_set_opt_type(type,r,func,free_func) \
+	if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \
+		V_ASN1_CONSTRUCTED|V_ASN1_SET)))\
+		{ M_ASN1_D2I_get_set_type(type,r,func,free_func); }
+
+#define M_ASN1_I2D_len_SET_opt(a,f) \
+	if ((a != NULL) && (sk_num(a) != 0)) \
+		M_ASN1_I2D_len_SET(a,f);
+
+#define M_ASN1_I2D_put_SET_opt(a,f) \
+	if ((a != NULL) && (sk_num(a) != 0)) \
+		M_ASN1_I2D_put_SET(a,f);
+
+#define M_ASN1_I2D_put_SEQUENCE_opt(a,f) \
+	if ((a != NULL) && (sk_num(a) != 0)) \
+		M_ASN1_I2D_put_SEQUENCE(a,f);
+
+#define M_ASN1_I2D_put_SEQUENCE_opt_type(type,a,f) \
+	if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+		M_ASN1_I2D_put_SEQUENCE_type(type,a,f);
+
+#define M_ASN1_D2I_get_IMP_set_opt(b,func,free_func,tag) \
+	if ((c.slen != 0) && \
+		(M_ASN1_next == \
+		(V_ASN1_CONTEXT_SPECIFIC|V_ASN1_CONSTRUCTED|(tag))))\
+		{ \
+		M_ASN1_D2I_get_imp_set(b,func,free_func,\
+			tag,V_ASN1_CONTEXT_SPECIFIC); \
+		}
+
+#define M_ASN1_D2I_get_IMP_set_opt_type(type,b,func,free_func,tag) \
+	if ((c.slen != 0) && \
+		(M_ASN1_next == \
+		(V_ASN1_CONTEXT_SPECIFIC|V_ASN1_CONSTRUCTED|(tag))))\
+		{ \
+		M_ASN1_D2I_get_imp_set_type(type,b,func,free_func,\
+			tag,V_ASN1_CONTEXT_SPECIFIC); \
+		}
+
+#define M_ASN1_D2I_get_seq(r,func,free_func) \
+		M_ASN1_D2I_get_imp_set(r,func,free_func,\
+			V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL);
+
+#define M_ASN1_D2I_get_seq_type(type,r,func,free_func) \
+		M_ASN1_D2I_get_imp_set_type(type,r,func,free_func,\
+					    V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL)
+
+#define M_ASN1_D2I_get_seq_opt(r,func,free_func) \
+	if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \
+		V_ASN1_CONSTRUCTED|V_ASN1_SEQUENCE)))\
+		{ M_ASN1_D2I_get_seq(r,func,free_func); }
+
+#define M_ASN1_D2I_get_seq_opt_type(type,r,func,free_func) \
+	if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \
+		V_ASN1_CONSTRUCTED|V_ASN1_SEQUENCE)))\
+		{ M_ASN1_D2I_get_seq_type(type,r,func,free_func); }
+
+#define M_ASN1_D2I_get_IMP_set(r,func,free_func,x) \
+		M_ASN1_D2I_get_imp_set(r,func,free_func,\
+			x,V_ASN1_CONTEXT_SPECIFIC);
+
+#define M_ASN1_D2I_get_IMP_set_type(type,r,func,free_func,x) \
+		M_ASN1_D2I_get_imp_set_type(type,r,func,free_func,\
+			x,V_ASN1_CONTEXT_SPECIFIC);
+
+#define M_ASN1_D2I_get_imp_set(r,func,free_func,a,b) \
+	c.q=c.p; \
+	if (d2i_ASN1_SET(&(r),&c.p,c.slen,(char *(*)())func,\
+		(void (*)())free_func,a,b) == NULL) \
+		{ c.line=__LINE__; goto err; } \
+	c.slen-=(c.p-c.q);
+
+#define M_ASN1_D2I_get_imp_set_type(type,r,func,free_func,a,b) \
+	c.q=c.p; \
+	if (d2i_ASN1_SET_OF_##type(&(r),&c.p,c.slen,func,\
+				   free_func,a,b) == NULL) \
+		{ c.line=__LINE__; goto err; } \
+	c.slen-=(c.p-c.q);
+
+#define M_ASN1_D2I_get_set_strings(r,func,a,b) \
+	c.q=c.p; \
+	if (d2i_ASN1_STRING_SET(&(r),&c.p,c.slen,a,b) == NULL) \
+		{ c.line=__LINE__; goto err; } \
+	c.slen-=(c.p-c.q);
+
+#define M_ASN1_D2I_get_EXP_opt(r,func,tag) \
+	if ((c.slen != 0L) && (M_ASN1_next == \
+		(V_ASN1_CONSTRUCTED|V_ASN1_CONTEXT_SPECIFIC|tag))) \
+		{ \
+		int Tinf,Ttag,Tclass; \
+		long Tlen; \
+		\
+		c.q=c.p; \
+		Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); \
+		if (Tinf & 0x80) \
+			{ c.error=ERR_R_BAD_ASN1_OBJECT_HEADER; \
+			c.line=__LINE__; goto err; } \
+		if (Tinf == (V_ASN1_CONSTRUCTED+1)) \
+					Tlen = c.slen - (c.p - c.q) - 2; \
+		if (func(&(r),&c.p,Tlen) == NULL) \
+			{ c.line=__LINE__; goto err; } \
+		if (Tinf == (V_ASN1_CONSTRUCTED+1)) { \
+			Tlen = c.slen - (c.p - c.q); \
+			if(!ASN1_const_check_infinite_end(&c.p, Tlen)) \
+				{ c.error=ERR_R_MISSING_ASN1_EOS; \
+				c.line=__LINE__; goto err; } \
+		}\
+		c.slen-=(c.p-c.q); \
+		}
+
+#define M_ASN1_D2I_get_EXP_set_opt(r,func,free_func,tag,b) \
+	if ((c.slen != 0) && (M_ASN1_next == \
+		(V_ASN1_CONSTRUCTED|V_ASN1_CONTEXT_SPECIFIC|tag))) \
+		{ \
+		int Tinf,Ttag,Tclass; \
+		long Tlen; \
+		\
+		c.q=c.p; \
+		Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); \
+		if (Tinf & 0x80) \
+			{ c.error=ERR_R_BAD_ASN1_OBJECT_HEADER; \
+			c.line=__LINE__; goto err; } \
+		if (Tinf == (V_ASN1_CONSTRUCTED+1)) \
+					Tlen = c.slen - (c.p - c.q) - 2; \
+		if (d2i_ASN1_SET(&(r),&c.p,Tlen,(char *(*)())func, \
+			(void (*)())free_func, \
+			b,V_ASN1_UNIVERSAL) == NULL) \
+			{ c.line=__LINE__; goto err; } \
+		if (Tinf == (V_ASN1_CONSTRUCTED+1)) { \
+			Tlen = c.slen - (c.p - c.q); \
+			if(!ASN1_check_infinite_end(&c.p, Tlen)) \
+				{ c.error=ERR_R_MISSING_ASN1_EOS; \
+				c.line=__LINE__; goto err; } \
+		}\
+		c.slen-=(c.p-c.q); \
+		}
+
+#define M_ASN1_D2I_get_EXP_set_opt_type(type,r,func,free_func,tag,b) \
+	if ((c.slen != 0) && (M_ASN1_next == \
+		(V_ASN1_CONSTRUCTED|V_ASN1_CONTEXT_SPECIFIC|tag))) \
+		{ \
+		int Tinf,Ttag,Tclass; \
+		long Tlen; \
+		\
+		c.q=c.p; \
+		Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); \
+		if (Tinf & 0x80) \
+			{ c.error=ERR_R_BAD_ASN1_OBJECT_HEADER; \
+			c.line=__LINE__; goto err; } \
+		if (Tinf == (V_ASN1_CONSTRUCTED+1)) \
+					Tlen = c.slen - (c.p - c.q) - 2; \
+		if (d2i_ASN1_SET_OF_##type(&(r),&c.p,Tlen,func, \
+			free_func,b,V_ASN1_UNIVERSAL) == NULL) \
+			{ c.line=__LINE__; goto err; } \
+		if (Tinf == (V_ASN1_CONSTRUCTED+1)) { \
+			Tlen = c.slen - (c.p - c.q); \
+			if(!ASN1_check_infinite_end(&c.p, Tlen)) \
+				{ c.error=ERR_R_MISSING_ASN1_EOS; \
+				c.line=__LINE__; goto err; } \
+		}\
+		c.slen-=(c.p-c.q); \
+		}
+
+/* New macros */
+#define M_ASN1_New_Malloc(ret,type) \
+	if ((ret=(type *)OPENSSL_malloc(sizeof(type))) == NULL) \
+		{ c.line=__LINE__; goto err2; }
+
+#define M_ASN1_New(arg,func) \
+	if (((arg)=func()) == NULL) return(NULL)
+
+#define M_ASN1_New_Error(a) \
+/*	err:	ASN1_MAC_H_err((a),ERR_R_NESTED_ASN1_ERROR,c.line); \
+		return(NULL);*/ \
+	err2:	ASN1_MAC_H_err((a),ERR_R_MALLOC_FAILURE,c.line); \
+		return(NULL)
+
+
+/* BIG UGLY WARNING!  This is so damn ugly I wanna puke.  Unfortunately,
+   some macros that use ASN1_const_CTX still insist on writing in the input
+   stream.  ARGH!  ARGH!  ARGH!  Let's get rid of this macro package.
+   Please?						-- Richard Levitte */
+#define M_ASN1_next		(*((unsigned char *)(c.p)))
+#define M_ASN1_next_prev	(*((unsigned char *)(c.q)))
+
+/*************************************************/
+
+#define M_ASN1_I2D_vars(a)	int r=0,ret=0; \
+				unsigned char *p; \
+				if (a == NULL) return(0)
+
+/* Length Macros */
+#define M_ASN1_I2D_len(a,f)	ret+=f(a,NULL)
+#define M_ASN1_I2D_len_IMP_opt(a,f)	if (a != NULL) M_ASN1_I2D_len(a,f)
+
+#define M_ASN1_I2D_len_SET(a,f) \
+		ret+=i2d_ASN1_SET(a,NULL,f,V_ASN1_SET,V_ASN1_UNIVERSAL,IS_SET);
+
+#define M_ASN1_I2D_len_SET_type(type,a,f) \
+		ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,V_ASN1_SET, \
+					    V_ASN1_UNIVERSAL,IS_SET);
+
+#define M_ASN1_I2D_len_SEQUENCE(a,f) \
+		ret+=i2d_ASN1_SET(a,NULL,f,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL, \
+				  IS_SEQUENCE);
+
+#define M_ASN1_I2D_len_SEQUENCE_type(type,a,f) \
+		ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,V_ASN1_SEQUENCE, \
+					    V_ASN1_UNIVERSAL,IS_SEQUENCE)
+
+#define M_ASN1_I2D_len_SEQUENCE_opt(a,f) \
+		if ((a != NULL) && (sk_num(a) != 0)) \
+			M_ASN1_I2D_len_SEQUENCE(a,f);
+
+#define M_ASN1_I2D_len_SEQUENCE_opt_type(type,a,f) \
+		if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+			M_ASN1_I2D_len_SEQUENCE_type(type,a,f);
+
+#define M_ASN1_I2D_len_IMP_SET(a,f,x) \
+		ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC,IS_SET);
+
+#define M_ASN1_I2D_len_IMP_SET_type(type,a,f,x) \
+		ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,x, \
+					    V_ASN1_CONTEXT_SPECIFIC,IS_SET);
+
+#define M_ASN1_I2D_len_IMP_SET_opt(a,f,x) \
+		if ((a != NULL) && (sk_num(a) != 0)) \
+			ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC, \
+					  IS_SET);
+
+#define M_ASN1_I2D_len_IMP_SET_opt_type(type,a,f,x) \
+		if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+			ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,x, \
+					       V_ASN1_CONTEXT_SPECIFIC,IS_SET);
+
+#define M_ASN1_I2D_len_IMP_SEQUENCE(a,f,x) \
+		ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC, \
+				  IS_SEQUENCE);
+
+#define M_ASN1_I2D_len_IMP_SEQUENCE_opt(a,f,x) \
+		if ((a != NULL) && (sk_num(a) != 0)) \
+			ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC, \
+					  IS_SEQUENCE);
+
+#define M_ASN1_I2D_len_IMP_SEQUENCE_opt_type(type,a,f,x) \
+		if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+			ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,x, \
+						    V_ASN1_CONTEXT_SPECIFIC, \
+						    IS_SEQUENCE);
+
+#define M_ASN1_I2D_len_EXP_opt(a,f,mtag,v) \
+		if (a != NULL)\
+			{ \
+			v=f(a,NULL); \
+			ret+=ASN1_object_size(1,v,mtag); \
+			}
+
+#define M_ASN1_I2D_len_EXP_SET_opt(a,f,mtag,tag,v) \
+		if ((a != NULL) && (sk_num(a) != 0))\
+			{ \
+			v=i2d_ASN1_SET(a,NULL,f,tag,V_ASN1_UNIVERSAL,IS_SET); \
+			ret+=ASN1_object_size(1,v,mtag); \
+			}
+
+#define M_ASN1_I2D_len_EXP_SEQUENCE_opt(a,f,mtag,tag,v) \
+		if ((a != NULL) && (sk_num(a) != 0))\
+			{ \
+			v=i2d_ASN1_SET(a,NULL,f,tag,V_ASN1_UNIVERSAL, \
+				       IS_SEQUENCE); \
+			ret+=ASN1_object_size(1,v,mtag); \
+			}
+
+#define M_ASN1_I2D_len_EXP_SEQUENCE_opt_type(type,a,f,mtag,tag,v) \
+		if ((a != NULL) && (sk_##type##_num(a) != 0))\
+			{ \
+			v=i2d_ASN1_SET_OF_##type(a,NULL,f,tag, \
+						 V_ASN1_UNIVERSAL, \
+						 IS_SEQUENCE); \
+			ret+=ASN1_object_size(1,v,mtag); \
+			}
+
+/* Put Macros */
+#define M_ASN1_I2D_put(a,f)	f(a,&p)
+
+#define M_ASN1_I2D_put_IMP_opt(a,f,t)	\
+		if (a != NULL) \
+			{ \
+			unsigned char *q=p; \
+			f(a,&p); \
+			*q=(V_ASN1_CONTEXT_SPECIFIC|t|(*q&V_ASN1_CONSTRUCTED));\
+			}
+
+#define M_ASN1_I2D_put_SET(a,f) i2d_ASN1_SET(a,&p,f,V_ASN1_SET,\
+			V_ASN1_UNIVERSAL,IS_SET)
+#define M_ASN1_I2D_put_SET_type(type,a,f) \
+     i2d_ASN1_SET_OF_##type(a,&p,f,V_ASN1_SET,V_ASN1_UNIVERSAL,IS_SET)
+#define M_ASN1_I2D_put_IMP_SET(a,f,x) i2d_ASN1_SET(a,&p,f,x,\
+			V_ASN1_CONTEXT_SPECIFIC,IS_SET)
+#define M_ASN1_I2D_put_IMP_SET_type(type,a,f,x) \
+     i2d_ASN1_SET_OF_##type(a,&p,f,x,V_ASN1_CONTEXT_SPECIFIC,IS_SET)
+#define M_ASN1_I2D_put_IMP_SEQUENCE(a,f,x) i2d_ASN1_SET(a,&p,f,x,\
+			V_ASN1_CONTEXT_SPECIFIC,IS_SEQUENCE)
+
+#define M_ASN1_I2D_put_SEQUENCE(a,f) i2d_ASN1_SET(a,&p,f,V_ASN1_SEQUENCE,\
+					     V_ASN1_UNIVERSAL,IS_SEQUENCE)
+
+#define M_ASN1_I2D_put_SEQUENCE_type(type,a,f) \
+     i2d_ASN1_SET_OF_##type(a,&p,f,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL, \
+			    IS_SEQUENCE)
+
+#define M_ASN1_I2D_put_SEQUENCE_opt(a,f) \
+		if ((a != NULL) && (sk_num(a) != 0)) \
+			M_ASN1_I2D_put_SEQUENCE(a,f);
+
+#define M_ASN1_I2D_put_IMP_SET_opt(a,f,x) \
+		if ((a != NULL) && (sk_num(a) != 0)) \
+			{ i2d_ASN1_SET(a,&p,f,x,V_ASN1_CONTEXT_SPECIFIC, \
+				       IS_SET); }
+
+#define M_ASN1_I2D_put_IMP_SET_opt_type(type,a,f,x) \
+		if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+			{ i2d_ASN1_SET_OF_##type(a,&p,f,x, \
+						 V_ASN1_CONTEXT_SPECIFIC, \
+						 IS_SET); }
+
+#define M_ASN1_I2D_put_IMP_SEQUENCE_opt(a,f,x) \
+		if ((a != NULL) && (sk_num(a) != 0)) \
+			{ i2d_ASN1_SET(a,&p,f,x,V_ASN1_CONTEXT_SPECIFIC, \
+				       IS_SEQUENCE); }
+
+#define M_ASN1_I2D_put_IMP_SEQUENCE_opt_type(type,a,f,x) \
+		if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+			{ i2d_ASN1_SET_OF_##type(a,&p,f,x, \
+						 V_ASN1_CONTEXT_SPECIFIC, \
+						 IS_SEQUENCE); }
+
+#define M_ASN1_I2D_put_EXP_opt(a,f,tag,v) \
+		if (a != NULL) \
+			{ \
+			ASN1_put_object(&p,1,v,tag,V_ASN1_CONTEXT_SPECIFIC); \
+			f(a,&p); \
+			}
+
+#define M_ASN1_I2D_put_EXP_SET_opt(a,f,mtag,tag,v) \
+		if ((a != NULL) && (sk_num(a) != 0)) \
+			{ \
+			ASN1_put_object(&p,1,v,mtag,V_ASN1_CONTEXT_SPECIFIC); \
+			i2d_ASN1_SET(a,&p,f,tag,V_ASN1_UNIVERSAL,IS_SET); \
+			}
+
+#define M_ASN1_I2D_put_EXP_SEQUENCE_opt(a,f,mtag,tag,v) \
+		if ((a != NULL) && (sk_num(a) != 0)) \
+			{ \
+			ASN1_put_object(&p,1,v,mtag,V_ASN1_CONTEXT_SPECIFIC); \
+			i2d_ASN1_SET(a,&p,f,tag,V_ASN1_UNIVERSAL,IS_SEQUENCE); \
+			}
+
+#define M_ASN1_I2D_put_EXP_SEQUENCE_opt_type(type,a,f,mtag,tag,v) \
+		if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+			{ \
+			ASN1_put_object(&p,1,v,mtag,V_ASN1_CONTEXT_SPECIFIC); \
+			i2d_ASN1_SET_OF_##type(a,&p,f,tag,V_ASN1_UNIVERSAL, \
+					       IS_SEQUENCE); \
+			}
+
+#define M_ASN1_I2D_seq_total() \
+		r=ASN1_object_size(1,ret,V_ASN1_SEQUENCE); \
+		if (pp == NULL) return(r); \
+		p= *pp; \
+		ASN1_put_object(&p,1,ret,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL)
+
+#define M_ASN1_I2D_INF_seq_start(tag,ctx) \
+		*(p++)=(V_ASN1_CONSTRUCTED|(tag)|(ctx)); \
+		*(p++)=0x80
+
+#define M_ASN1_I2D_INF_seq_end() *(p++)=0x00; *(p++)=0x00
+
+#define M_ASN1_I2D_finish()	*pp=p; \
+				return(r);
+
+int asn1_GetSequence(ASN1_const_CTX *c, long *length);
+void asn1_add_error(const unsigned char *address,int offset);
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff --git a/dep/include/openssl/asn1t.h b/dep/include/openssl/asn1t.h
new file mode 100644
index 00000000000..adbc2a63dd0
--- /dev/null
+++ b/dep/include/openssl/asn1t.h
@@ -0,0 +1,886 @@
+/* asn1t.h */
+/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+#ifndef HEADER_ASN1T_H
+#define HEADER_ASN1T_H
+
+#include 
+#include 
+#include 
+
+#ifdef OPENSSL_BUILD_SHLIBCRYPTO
+# undef OPENSSL_EXTERN
+# define OPENSSL_EXTERN OPENSSL_EXPORT
+#endif
+
+/* ASN1 template defines, structures and functions */
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+
+#ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION
+
+/* Macro to obtain ASN1_ADB pointer from a type (only used internally) */
+#define ASN1_ADB_ptr(iptr) ((const ASN1_ADB *)(iptr))
+
+
+/* Macros for start and end of ASN1_ITEM definition */
+
+#define ASN1_ITEM_start(itname) \
+	OPENSSL_GLOBAL const ASN1_ITEM itname##_it = {
+
+#define ASN1_ITEM_end(itname) \
+		};
+
+#else
+
+/* Macro to obtain ASN1_ADB pointer from a type (only used internally) */
+#define ASN1_ADB_ptr(iptr) ((const ASN1_ADB *)(iptr()))
+
+
+/* Macros for start and end of ASN1_ITEM definition */
+
+#define ASN1_ITEM_start(itname) \
+	const ASN1_ITEM * itname##_it(void) \
+	{ \
+		static const ASN1_ITEM local_it = { 
+
+#define ASN1_ITEM_end(itname) \
+		}; \
+	return &local_it; \
+	}
+
+#endif
+
+
+/* Macros to aid ASN1 template writing */
+
+#define ASN1_ITEM_TEMPLATE(tname) \
+	static const ASN1_TEMPLATE tname##_item_tt 
+
+#define ASN1_ITEM_TEMPLATE_END(tname) \
+	;\
+	ASN1_ITEM_start(tname) \
+		ASN1_ITYPE_PRIMITIVE,\
+		-1,\
+		&tname##_item_tt,\
+		0,\
+		NULL,\
+		0,\
+		#tname \
+	ASN1_ITEM_end(tname)
+
+
+/* This is a ASN1 type which just embeds a template */
+ 
+/* This pair helps declare a SEQUENCE. We can do:
+ *
+ * 	ASN1_SEQUENCE(stname) = {
+ * 		... SEQUENCE components ...
+ * 	} ASN1_SEQUENCE_END(stname)
+ *
+ * 	This will produce an ASN1_ITEM called stname_it
+ *	for a structure called stname.
+ *
+ * 	If you want the same structure but a different
+ *	name then use:
+ *
+ * 	ASN1_SEQUENCE(itname) = {
+ * 		... SEQUENCE components ...
+ * 	} ASN1_SEQUENCE_END_name(stname, itname)
+ *
+ *	This will create an item called itname_it using
+ *	a structure called stname.
+ */
+
+#define ASN1_SEQUENCE(tname) \
+	static const ASN1_TEMPLATE tname##_seq_tt[] 
+
+#define ASN1_SEQUENCE_END(stname) ASN1_SEQUENCE_END_name(stname, stname)
+
+#define ASN1_SEQUENCE_END_name(stname, tname) \
+	;\
+	ASN1_ITEM_start(tname) \
+		ASN1_ITYPE_SEQUENCE,\
+		V_ASN1_SEQUENCE,\
+		tname##_seq_tt,\
+		sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\
+		NULL,\
+		sizeof(stname),\
+		#stname \
+	ASN1_ITEM_end(tname)
+
+#define ASN1_NDEF_SEQUENCE(tname) \
+	ASN1_SEQUENCE(tname)
+
+#define ASN1_SEQUENCE_cb(tname, cb) \
+	static const ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0}; \
+	ASN1_SEQUENCE(tname)
+
+#define ASN1_BROKEN_SEQUENCE(tname) \
+	static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_BROKEN, 0, 0, 0, 0}; \
+	ASN1_SEQUENCE(tname)
+
+#define ASN1_SEQUENCE_ref(tname, cb, lck) \
+	static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_REFCOUNT, offsetof(tname, references), lck, cb, 0}; \
+	ASN1_SEQUENCE(tname)
+
+#define ASN1_SEQUENCE_enc(tname, enc, cb) \
+	static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_ENCODING, 0, 0, cb, offsetof(tname, enc)}; \
+	ASN1_SEQUENCE(tname)
+
+#define ASN1_NDEF_SEQUENCE_END(tname) \
+	;\
+	ASN1_ITEM_start(tname) \
+		ASN1_ITYPE_NDEF_SEQUENCE,\
+		V_ASN1_SEQUENCE,\
+		tname##_seq_tt,\
+		sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\
+		NULL,\
+		sizeof(tname),\
+		#tname \
+	ASN1_ITEM_end(tname)
+
+#define ASN1_BROKEN_SEQUENCE_END(stname) ASN1_SEQUENCE_END_ref(stname, stname)
+
+#define ASN1_SEQUENCE_END_enc(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname)
+
+#define ASN1_SEQUENCE_END_cb(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname)
+
+#define ASN1_SEQUENCE_END_ref(stname, tname) \
+	;\
+	ASN1_ITEM_start(tname) \
+		ASN1_ITYPE_SEQUENCE,\
+		V_ASN1_SEQUENCE,\
+		tname##_seq_tt,\
+		sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\
+		&tname##_aux,\
+		sizeof(stname),\
+		#stname \
+	ASN1_ITEM_end(tname)
+
+
+/* This pair helps declare a CHOICE type. We can do:
+ *
+ * 	ASN1_CHOICE(chname) = {
+ * 		... CHOICE options ...
+ * 	ASN1_CHOICE_END(chname)
+ *
+ * 	This will produce an ASN1_ITEM called chname_it
+ *	for a structure called chname. The structure
+ *	definition must look like this:
+ *	typedef struct {
+ *		int type;
+ *		union {
+ *			ASN1_SOMETHING *opt1;
+ *			ASN1_SOMEOTHER *opt2;
+ *		} value;
+ *	} chname;
+ *	
+ *	the name of the selector must be 'type'.
+ * 	to use an alternative selector name use the
+ *      ASN1_CHOICE_END_selector() version.
+ */
+
+#define ASN1_CHOICE(tname) \
+	static const ASN1_TEMPLATE tname##_ch_tt[] 
+
+#define ASN1_CHOICE_cb(tname, cb) \
+	static const ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0}; \
+	ASN1_CHOICE(tname)
+
+#define ASN1_CHOICE_END(stname) ASN1_CHOICE_END_name(stname, stname)
+
+#define ASN1_CHOICE_END_name(stname, tname) ASN1_CHOICE_END_selector(stname, tname, type)
+
+#define ASN1_CHOICE_END_selector(stname, tname, selname) \
+	;\
+	ASN1_ITEM_start(tname) \
+		ASN1_ITYPE_CHOICE,\
+		offsetof(stname,selname) ,\
+		tname##_ch_tt,\
+		sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\
+		NULL,\
+		sizeof(stname),\
+		#stname \
+	ASN1_ITEM_end(tname)
+
+#define ASN1_CHOICE_END_cb(stname, tname, selname) \
+	;\
+	ASN1_ITEM_start(tname) \
+		ASN1_ITYPE_CHOICE,\
+		offsetof(stname,selname) ,\
+		tname##_ch_tt,\
+		sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\
+		&tname##_aux,\
+		sizeof(stname),\
+		#stname \
+	ASN1_ITEM_end(tname)
+
+/* This helps with the template wrapper form of ASN1_ITEM */
+
+#define ASN1_EX_TEMPLATE_TYPE(flags, tag, name, type) { \
+	(flags), (tag), 0,\
+	#name, ASN1_ITEM_ref(type) }
+
+/* These help with SEQUENCE or CHOICE components */
+
+/* used to declare other types */
+
+#define ASN1_EX_TYPE(flags, tag, stname, field, type) { \
+	(flags), (tag), offsetof(stname, field),\
+	#field, ASN1_ITEM_ref(type) }
+
+/* used when the structure is combined with the parent */
+
+#define ASN1_EX_COMBINE(flags, tag, type) { \
+	(flags)|ASN1_TFLG_COMBINE, (tag), 0, NULL, ASN1_ITEM_ref(type) }
+
+/* implicit and explicit helper macros */
+
+#define ASN1_IMP_EX(stname, field, type, tag, ex) \
+		ASN1_EX_TYPE(ASN1_TFLG_IMPLICIT | ex, tag, stname, field, type)
+
+#define ASN1_EXP_EX(stname, field, type, tag, ex) \
+		ASN1_EX_TYPE(ASN1_TFLG_EXPLICIT | ex, tag, stname, field, type)
+
+/* Any defined by macros: the field used is in the table itself */
+
+#ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION
+#define ASN1_ADB_OBJECT(tblname) { ASN1_TFLG_ADB_OID, -1, 0, #tblname, (const ASN1_ITEM *)&(tblname##_adb) }
+#define ASN1_ADB_INTEGER(tblname) { ASN1_TFLG_ADB_INT, -1, 0, #tblname, (const ASN1_ITEM *)&(tblname##_adb) }
+#else
+#define ASN1_ADB_OBJECT(tblname) { ASN1_TFLG_ADB_OID, -1, 0, #tblname, tblname##_adb }
+#define ASN1_ADB_INTEGER(tblname) { ASN1_TFLG_ADB_INT, -1, 0, #tblname, tblname##_adb }
+#endif
+/* Plain simple type */
+#define ASN1_SIMPLE(stname, field, type) ASN1_EX_TYPE(0,0, stname, field, type)
+
+/* OPTIONAL simple type */
+#define ASN1_OPT(stname, field, type) ASN1_EX_TYPE(ASN1_TFLG_OPTIONAL, 0, stname, field, type)
+
+/* IMPLICIT tagged simple type */
+#define ASN1_IMP(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, 0)
+
+/* IMPLICIT tagged OPTIONAL simple type */
+#define ASN1_IMP_OPT(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL)
+
+/* Same as above but EXPLICIT */
+
+#define ASN1_EXP(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, 0)
+#define ASN1_EXP_OPT(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL)
+
+/* SEQUENCE OF type */
+#define ASN1_SEQUENCE_OF(stname, field, type) \
+		ASN1_EX_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, stname, field, type)
+
+/* OPTIONAL SEQUENCE OF */
+#define ASN1_SEQUENCE_OF_OPT(stname, field, type) \
+		ASN1_EX_TYPE(ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL, 0, stname, field, type)
+
+/* Same as above but for SET OF */
+
+#define ASN1_SET_OF(stname, field, type) \
+		ASN1_EX_TYPE(ASN1_TFLG_SET_OF, 0, stname, field, type)
+
+#define ASN1_SET_OF_OPT(stname, field, type) \
+		ASN1_EX_TYPE(ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL, 0, stname, field, type)
+
+/* Finally compound types of SEQUENCE, SET, IMPLICIT, EXPLICIT and OPTIONAL */
+
+#define ASN1_IMP_SET_OF(stname, field, type, tag) \
+			ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF)
+
+#define ASN1_EXP_SET_OF(stname, field, type, tag) \
+			ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF)
+
+#define ASN1_IMP_SET_OF_OPT(stname, field, type, tag) \
+			ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL)
+
+#define ASN1_EXP_SET_OF_OPT(stname, field, type, tag) \
+			ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL)
+
+#define ASN1_IMP_SEQUENCE_OF(stname, field, type, tag) \
+			ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF)
+
+#define ASN1_IMP_SEQUENCE_OF_OPT(stname, field, type, tag) \
+			ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL)
+
+#define ASN1_EXP_SEQUENCE_OF(stname, field, type, tag) \
+			ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF)
+
+#define ASN1_EXP_SEQUENCE_OF_OPT(stname, field, type, tag) \
+			ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL)
+
+/* EXPLICIT OPTIONAL using indefinite length constructed form */
+#define ASN1_NDEF_EXP_OPT(stname, field, type, tag) \
+			ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL|ASN1_TFLG_NDEF)
+
+/* Macros for the ASN1_ADB structure */
+
+#define ASN1_ADB(name) \
+	static const ASN1_ADB_TABLE name##_adbtbl[] 
+
+#ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION
+
+#define ASN1_ADB_END(name, flags, field, app_table, def, none) \
+	;\
+	static const ASN1_ADB name##_adb = {\
+		flags,\
+		offsetof(name, field),\
+		app_table,\
+		name##_adbtbl,\
+		sizeof(name##_adbtbl) / sizeof(ASN1_ADB_TABLE),\
+		def,\
+		none\
+	}
+
+#else
+
+#define ASN1_ADB_END(name, flags, field, app_table, def, none) \
+	;\
+	static const ASN1_ITEM *name##_adb(void) \
+	{ \
+	static const ASN1_ADB internal_adb = \
+		{\
+		flags,\
+		offsetof(name, field),\
+		app_table,\
+		name##_adbtbl,\
+		sizeof(name##_adbtbl) / sizeof(ASN1_ADB_TABLE),\
+		def,\
+		none\
+		}; \
+		return (const ASN1_ITEM *) &internal_adb; \
+	} \
+	void dummy_function(void)
+
+#endif
+
+#define ADB_ENTRY(val, template) {val, template}
+
+#define ASN1_ADB_TEMPLATE(name) \
+	static const ASN1_TEMPLATE name##_tt 
+
+/* This is the ASN1 template structure that defines
+ * a wrapper round the actual type. It determines the
+ * actual position of the field in the value structure,
+ * various flags such as OPTIONAL and the field name.
+ */
+
+struct ASN1_TEMPLATE_st {
+unsigned long flags;		/* Various flags */
+long tag;			/* tag, not used if no tagging */
+unsigned long offset;		/* Offset of this field in structure */
+#ifndef NO_ASN1_FIELD_NAMES
+const char *field_name;		/* Field name */
+#endif
+ASN1_ITEM_EXP *item;		/* Relevant ASN1_ITEM or ASN1_ADB */
+};
+
+/* Macro to extract ASN1_ITEM and ASN1_ADB pointer from ASN1_TEMPLATE */
+
+#define ASN1_TEMPLATE_item(t) (t->item_ptr)
+#define ASN1_TEMPLATE_adb(t) (t->item_ptr)
+
+typedef struct ASN1_ADB_TABLE_st ASN1_ADB_TABLE;
+typedef struct ASN1_ADB_st ASN1_ADB;
+
+struct ASN1_ADB_st {
+	unsigned long flags;	/* Various flags */
+	unsigned long offset;	/* Offset of selector field */
+	STACK_OF(ASN1_ADB_TABLE) **app_items; /* Application defined items */
+	const ASN1_ADB_TABLE *tbl;	/* Table of possible types */
+	long tblcount;		/* Number of entries in tbl */
+	const ASN1_TEMPLATE *default_tt;  /* Type to use if no match */
+	const ASN1_TEMPLATE *null_tt;  /* Type to use if selector is NULL */
+};
+
+struct ASN1_ADB_TABLE_st {
+	long value;		/* NID for an object or value for an int */
+	const ASN1_TEMPLATE tt;		/* item for this value */
+};
+
+/* template flags */
+
+/* Field is optional */
+#define ASN1_TFLG_OPTIONAL	(0x1)
+
+/* Field is a SET OF */
+#define ASN1_TFLG_SET_OF	(0x1 << 1)
+
+/* Field is a SEQUENCE OF */
+#define ASN1_TFLG_SEQUENCE_OF	(0x2 << 1)
+
+/* Special case: this refers to a SET OF that
+ * will be sorted into DER order when encoded *and*
+ * the corresponding STACK will be modified to match
+ * the new order.
+ */
+#define ASN1_TFLG_SET_ORDER	(0x3 << 1)
+
+/* Mask for SET OF or SEQUENCE OF */
+#define ASN1_TFLG_SK_MASK	(0x3 << 1)
+
+/* These flags mean the tag should be taken from the
+ * tag field. If EXPLICIT then the underlying type
+ * is used for the inner tag.
+ */
+
+/* IMPLICIT tagging */
+#define ASN1_TFLG_IMPTAG	(0x1 << 3)
+
+
+/* EXPLICIT tagging, inner tag from underlying type */
+#define ASN1_TFLG_EXPTAG	(0x2 << 3)
+
+#define ASN1_TFLG_TAG_MASK	(0x3 << 3)
+
+/* context specific IMPLICIT */
+#define ASN1_TFLG_IMPLICIT	ASN1_TFLG_IMPTAG|ASN1_TFLG_CONTEXT
+
+/* context specific EXPLICIT */
+#define ASN1_TFLG_EXPLICIT	ASN1_TFLG_EXPTAG|ASN1_TFLG_CONTEXT
+
+/* If tagging is in force these determine the
+ * type of tag to use. Otherwise the tag is
+ * determined by the underlying type. These 
+ * values reflect the actual octet format.
+ */
+
+/* Universal tag */ 
+#define ASN1_TFLG_UNIVERSAL	(0x0<<6)
+/* Application tag */ 
+#define ASN1_TFLG_APPLICATION	(0x1<<6)
+/* Context specific tag */ 
+#define ASN1_TFLG_CONTEXT	(0x2<<6)
+/* Private tag */ 
+#define ASN1_TFLG_PRIVATE	(0x3<<6)
+
+#define ASN1_TFLG_TAG_CLASS	(0x3<<6)
+
+/* These are for ANY DEFINED BY type. In this case
+ * the 'item' field points to an ASN1_ADB structure
+ * which contains a table of values to decode the
+ * relevant type
+ */
+
+#define ASN1_TFLG_ADB_MASK	(0x3<<8)
+
+#define ASN1_TFLG_ADB_OID	(0x1<<8)
+
+#define ASN1_TFLG_ADB_INT	(0x1<<9)
+
+/* This flag means a parent structure is passed
+ * instead of the field: this is useful is a
+ * SEQUENCE is being combined with a CHOICE for
+ * example. Since this means the structure and
+ * item name will differ we need to use the
+ * ASN1_CHOICE_END_name() macro for example.
+ */
+
+#define ASN1_TFLG_COMBINE	(0x1<<10)
+
+/* This flag when present in a SEQUENCE OF, SET OF
+ * or EXPLICIT causes indefinite length constructed
+ * encoding to be used if required.
+ */
+
+#define ASN1_TFLG_NDEF		(0x1<<11)
+
+/* This is the actual ASN1 item itself */
+
+struct ASN1_ITEM_st {
+char itype;			/* The item type, primitive, SEQUENCE, CHOICE or extern */
+long utype;			/* underlying type */
+const ASN1_TEMPLATE *templates;	/* If SEQUENCE or CHOICE this contains the contents */
+long tcount;			/* Number of templates if SEQUENCE or CHOICE */
+const void *funcs;		/* functions that handle this type */
+long size;			/* Structure size (usually)*/
+#ifndef NO_ASN1_FIELD_NAMES
+const char *sname;		/* Structure name */
+#endif
+};
+
+/* These are values for the itype field and
+ * determine how the type is interpreted.
+ *
+ * For PRIMITIVE types the underlying type
+ * determines the behaviour if items is NULL.
+ *
+ * Otherwise templates must contain a single 
+ * template and the type is treated in the
+ * same way as the type specified in the template.
+ *
+ * For SEQUENCE types the templates field points
+ * to the members, the size field is the
+ * structure size.
+ *
+ * For CHOICE types the templates field points
+ * to each possible member (typically a union)
+ * and the 'size' field is the offset of the
+ * selector.
+ *
+ * The 'funcs' field is used for application
+ * specific functions. 
+ *
+ * For COMPAT types the funcs field gives a
+ * set of functions that handle this type, this
+ * supports the old d2i, i2d convention.
+ *
+ * The EXTERN type uses a new style d2i/i2d.
+ * The new style should be used where possible
+ * because it avoids things like the d2i IMPLICIT
+ * hack.
+ *
+ * MSTRING is a multiple string type, it is used
+ * for a CHOICE of character strings where the
+ * actual strings all occupy an ASN1_STRING
+ * structure. In this case the 'utype' field
+ * has a special meaning, it is used as a mask
+ * of acceptable types using the B_ASN1 constants.
+ *
+ * NDEF_SEQUENCE is the same as SEQUENCE except
+ * that it will use indefinite length constructed
+ * encoding if requested.
+ *
+ */
+
+#define ASN1_ITYPE_PRIMITIVE		0x0
+
+#define ASN1_ITYPE_SEQUENCE		0x1
+
+#define ASN1_ITYPE_CHOICE		0x2
+
+#define ASN1_ITYPE_COMPAT		0x3
+
+#define ASN1_ITYPE_EXTERN		0x4
+
+#define ASN1_ITYPE_MSTRING		0x5
+
+#define ASN1_ITYPE_NDEF_SEQUENCE	0x6
+
+/* Cache for ASN1 tag and length, so we
+ * don't keep re-reading it for things
+ * like CHOICE
+ */
+
+struct ASN1_TLC_st{
+	char valid;	/* Values below are valid */
+	int ret;	/* return value */
+	long plen;	/* length */
+	int ptag;	/* class value */
+	int pclass;	/* class value */
+	int hdrlen;	/* header length */
+};
+
+/* Typedefs for ASN1 function pointers */
+
+typedef ASN1_VALUE * ASN1_new_func(void);
+typedef void ASN1_free_func(ASN1_VALUE *a);
+typedef ASN1_VALUE * ASN1_d2i_func(ASN1_VALUE **a, const unsigned char ** in, long length);
+typedef int ASN1_i2d_func(ASN1_VALUE * a, unsigned char **in);
+
+typedef int ASN1_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_ITEM *it,
+					int tag, int aclass, char opt, ASN1_TLC *ctx);
+
+typedef int ASN1_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass);
+typedef int ASN1_ex_new_func(ASN1_VALUE **pval, const ASN1_ITEM *it);
+typedef void ASN1_ex_free_func(ASN1_VALUE **pval, const ASN1_ITEM *it);
+
+typedef int ASN1_primitive_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it);
+typedef int ASN1_primitive_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it);
+
+typedef struct ASN1_COMPAT_FUNCS_st {
+	ASN1_new_func *asn1_new;
+	ASN1_free_func *asn1_free;
+	ASN1_d2i_func *asn1_d2i;
+	ASN1_i2d_func *asn1_i2d;
+} ASN1_COMPAT_FUNCS;
+
+typedef struct ASN1_EXTERN_FUNCS_st {
+	void *app_data;
+	ASN1_ex_new_func *asn1_ex_new;
+	ASN1_ex_free_func *asn1_ex_free;
+	ASN1_ex_free_func *asn1_ex_clear;
+	ASN1_ex_d2i *asn1_ex_d2i;
+	ASN1_ex_i2d *asn1_ex_i2d;
+} ASN1_EXTERN_FUNCS;
+
+typedef struct ASN1_PRIMITIVE_FUNCS_st {
+	void *app_data;
+	unsigned long flags;
+	ASN1_ex_new_func *prim_new;
+	ASN1_ex_free_func *prim_free;
+	ASN1_ex_free_func *prim_clear;
+	ASN1_primitive_c2i *prim_c2i;
+	ASN1_primitive_i2c *prim_i2c;
+} ASN1_PRIMITIVE_FUNCS;
+
+/* This is the ASN1_AUX structure: it handles various
+ * miscellaneous requirements. For example the use of
+ * reference counts and an informational callback.
+ *
+ * The "informational callback" is called at various
+ * points during the ASN1 encoding and decoding. It can
+ * be used to provide minor customisation of the structures
+ * used. This is most useful where the supplied routines
+ * *almost* do the right thing but need some extra help
+ * at a few points. If the callback returns zero then
+ * it is assumed a fatal error has occurred and the 
+ * main operation should be abandoned.
+ *
+ * If major changes in the default behaviour are required
+ * then an external type is more appropriate.
+ */
+
+typedef int ASN1_aux_cb(int operation, ASN1_VALUE **in, const ASN1_ITEM *it);
+
+typedef struct ASN1_AUX_st {
+	void *app_data;
+	int flags;
+	int ref_offset;		/* Offset of reference value */
+	int ref_lock;		/* Lock type to use */
+	ASN1_aux_cb *asn1_cb;
+	int enc_offset;		/* Offset of ASN1_ENCODING structure */
+} ASN1_AUX;
+
+/* Flags in ASN1_AUX */
+
+/* Use a reference count */
+#define ASN1_AFLG_REFCOUNT	1
+/* Save the encoding of structure (useful for signatures) */
+#define ASN1_AFLG_ENCODING	2
+/* The Sequence length is invalid */
+#define ASN1_AFLG_BROKEN	4
+
+/* operation values for asn1_cb */
+
+#define ASN1_OP_NEW_PRE		0
+#define ASN1_OP_NEW_POST	1
+#define ASN1_OP_FREE_PRE	2
+#define ASN1_OP_FREE_POST	3
+#define ASN1_OP_D2I_PRE		4
+#define ASN1_OP_D2I_POST	5
+#define ASN1_OP_I2D_PRE		6
+#define ASN1_OP_I2D_POST	7
+
+/* Macro to implement a primitive type */
+#define IMPLEMENT_ASN1_TYPE(stname) IMPLEMENT_ASN1_TYPE_ex(stname, stname, 0)
+#define IMPLEMENT_ASN1_TYPE_ex(itname, vname, ex) \
+				ASN1_ITEM_start(itname) \
+					ASN1_ITYPE_PRIMITIVE, V_##vname, NULL, 0, NULL, ex, #itname \
+				ASN1_ITEM_end(itname)
+
+/* Macro to implement a multi string type */
+#define IMPLEMENT_ASN1_MSTRING(itname, mask) \
+				ASN1_ITEM_start(itname) \
+					ASN1_ITYPE_MSTRING, mask, NULL, 0, NULL, sizeof(ASN1_STRING), #itname \
+				ASN1_ITEM_end(itname)
+
+/* Macro to implement an ASN1_ITEM in terms of old style funcs */
+
+#define IMPLEMENT_COMPAT_ASN1(sname) IMPLEMENT_COMPAT_ASN1_type(sname, V_ASN1_SEQUENCE)
+
+#define IMPLEMENT_COMPAT_ASN1_type(sname, tag) \
+	static const ASN1_COMPAT_FUNCS sname##_ff = { \
+		(ASN1_new_func *)sname##_new, \
+		(ASN1_free_func *)sname##_free, \
+		(ASN1_d2i_func *)d2i_##sname, \
+		(ASN1_i2d_func *)i2d_##sname, \
+	}; \
+	ASN1_ITEM_start(sname) \
+		ASN1_ITYPE_COMPAT, \
+		tag, \
+		NULL, \
+		0, \
+		&sname##_ff, \
+		0, \
+		#sname \
+	ASN1_ITEM_end(sname)
+
+#define IMPLEMENT_EXTERN_ASN1(sname, tag, fptrs) \
+	ASN1_ITEM_start(sname) \
+		ASN1_ITYPE_EXTERN, \
+		tag, \
+		NULL, \
+		0, \
+		&fptrs, \
+		0, \
+		#sname \
+	ASN1_ITEM_end(sname)
+
+/* Macro to implement standard functions in terms of ASN1_ITEM structures */
+
+#define IMPLEMENT_ASN1_FUNCTIONS(stname) IMPLEMENT_ASN1_FUNCTIONS_fname(stname, stname, stname)
+
+#define IMPLEMENT_ASN1_FUNCTIONS_name(stname, itname) IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, itname)
+
+#define IMPLEMENT_ASN1_FUNCTIONS_ENCODE_name(stname, itname) \
+			IMPLEMENT_ASN1_FUNCTIONS_ENCODE_fname(stname, itname, itname)
+
+#define IMPLEMENT_ASN1_ALLOC_FUNCTIONS(stname) \
+		IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, stname, stname)
+
+#define IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) \
+	stname *fname##_new(void) \
+	{ \
+		return (stname *)ASN1_item_new(ASN1_ITEM_rptr(itname)); \
+	} \
+	void fname##_free(stname *a) \
+	{ \
+		ASN1_item_free((ASN1_VALUE *)a, ASN1_ITEM_rptr(itname)); \
+	}
+
+#define IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, fname) \
+	IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \
+	IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname)
+
+#define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \
+	stname *d2i_##fname(stname **a, const unsigned char **in, long len) \
+	{ \
+		return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname));\
+	} \
+	int i2d_##fname(stname *a, unsigned char **out) \
+	{ \
+		return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\
+	} 
+
+#define IMPLEMENT_ASN1_NDEF_FUNCTION(stname) \
+	int i2d_##stname##_NDEF(stname *a, unsigned char **out) \
+	{ \
+		return ASN1_item_ndef_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(stname));\
+	} 
+
+/* This includes evil casts to remove const: they will go away when full
+ * ASN1 constification is done.
+ */
+#define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(stname, itname, fname) \
+	stname *d2i_##fname(stname **a, const unsigned char **in, long len) \
+	{ \
+		return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname));\
+	} \
+	int i2d_##fname(const stname *a, unsigned char **out) \
+	{ \
+		return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\
+	} 
+
+#define IMPLEMENT_ASN1_DUP_FUNCTION(stname) \
+	stname * stname##_dup(stname *x) \
+        { \
+        return ASN1_item_dup(ASN1_ITEM_rptr(stname), x); \
+        }
+
+#define IMPLEMENT_ASN1_FUNCTIONS_const(name) \
+		IMPLEMENT_ASN1_FUNCTIONS_const_fname(name, name, name)
+
+#define IMPLEMENT_ASN1_FUNCTIONS_const_fname(stname, itname, fname) \
+	IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(stname, itname, fname) \
+	IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname)
+
+/* external definitions for primitive types */
+
+DECLARE_ASN1_ITEM(ASN1_BOOLEAN)
+DECLARE_ASN1_ITEM(ASN1_TBOOLEAN)
+DECLARE_ASN1_ITEM(ASN1_FBOOLEAN)
+DECLARE_ASN1_ITEM(ASN1_SEQUENCE)
+DECLARE_ASN1_ITEM(CBIGNUM)
+DECLARE_ASN1_ITEM(BIGNUM)
+DECLARE_ASN1_ITEM(LONG)
+DECLARE_ASN1_ITEM(ZLONG)
+
+DECLARE_STACK_OF(ASN1_VALUE)
+
+/* Functions used internally by the ASN1 code */
+
+int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
+void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
+int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
+int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
+
+void ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
+int ASN1_template_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_TEMPLATE *tt);
+int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_ITEM *it,
+				int tag, int aclass, char opt, ASN1_TLC *ctx);
+
+int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass);
+int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_TEMPLATE *tt);
+void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
+
+int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it);
+int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it);
+
+int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it);
+int asn1_set_choice_selector(ASN1_VALUE **pval, int value, const ASN1_ITEM *it);
+
+ASN1_VALUE ** asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
+
+const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt, int nullerr);
+
+int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it);
+
+void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it);
+void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
+int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval, const ASN1_ITEM *it);
+int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen, const ASN1_ITEM *it);
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/dep/include/openssl/bio.h b/dep/include/openssl/bio.h
new file mode 100644
index 00000000000..2c9e8a7c804
--- /dev/null
+++ b/dep/include/openssl/bio.h
@@ -0,0 +1,775 @@
+/* crypto/bio/bio.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_BIO_H
+#define HEADER_BIO_H
+
+#include 
+
+#ifndef OPENSSL_NO_FP_API
+# include 
+#endif
+#include 
+
+#include 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* These are the 'types' of BIOs */
+#define BIO_TYPE_NONE		0
+#define BIO_TYPE_MEM		(1|0x0400)
+#define BIO_TYPE_FILE		(2|0x0400)
+
+#define BIO_TYPE_FD		(4|0x0400|0x0100)
+#define BIO_TYPE_SOCKET		(5|0x0400|0x0100)
+#define BIO_TYPE_NULL		(6|0x0400)
+#define BIO_TYPE_SSL		(7|0x0200)
+#define BIO_TYPE_MD		(8|0x0200)		/* passive filter */
+#define BIO_TYPE_BUFFER		(9|0x0200)		/* filter */
+#define BIO_TYPE_CIPHER		(10|0x0200)		/* filter */
+#define BIO_TYPE_BASE64		(11|0x0200)		/* filter */
+#define BIO_TYPE_CONNECT	(12|0x0400|0x0100)	/* socket - connect */
+#define BIO_TYPE_ACCEPT		(13|0x0400|0x0100)	/* socket for accept */
+#define BIO_TYPE_PROXY_CLIENT	(14|0x0200)		/* client proxy BIO */
+#define BIO_TYPE_PROXY_SERVER	(15|0x0200)		/* server proxy BIO */
+#define BIO_TYPE_NBIO_TEST	(16|0x0200)		/* server proxy BIO */
+#define BIO_TYPE_NULL_FILTER	(17|0x0200)
+#define BIO_TYPE_BER		(18|0x0200)		/* BER -> bin filter */
+#define BIO_TYPE_BIO		(19|0x0400)		/* (half a) BIO pair */
+#define BIO_TYPE_LINEBUFFER	(20|0x0200)		/* filter */
+#define BIO_TYPE_DGRAM		(21|0x0400|0x0100)
+
+#define BIO_TYPE_DESCRIPTOR	0x0100	/* socket, fd, connect or accept */
+#define BIO_TYPE_FILTER		0x0200
+#define BIO_TYPE_SOURCE_SINK	0x0400
+
+/* BIO_FILENAME_READ|BIO_CLOSE to open or close on free.
+ * BIO_set_fp(in,stdin,BIO_NOCLOSE); */
+#define BIO_NOCLOSE		0x00
+#define BIO_CLOSE		0x01
+
+/* These are used in the following macros and are passed to
+ * BIO_ctrl() */
+#define BIO_CTRL_RESET		1  /* opt - rewind/zero etc */
+#define BIO_CTRL_EOF		2  /* opt - are we at the eof */
+#define BIO_CTRL_INFO		3  /* opt - extra tit-bits */
+#define BIO_CTRL_SET		4  /* man - set the 'IO' type */
+#define BIO_CTRL_GET		5  /* man - get the 'IO' type */
+#define BIO_CTRL_PUSH		6  /* opt - internal, used to signify change */
+#define BIO_CTRL_POP		7  /* opt - internal, used to signify change */
+#define BIO_CTRL_GET_CLOSE	8  /* man - set the 'close' on free */
+#define BIO_CTRL_SET_CLOSE	9  /* man - set the 'close' on free */
+#define BIO_CTRL_PENDING	10  /* opt - is their more data buffered */
+#define BIO_CTRL_FLUSH		11  /* opt - 'flush' buffered output */
+#define BIO_CTRL_DUP		12  /* man - extra stuff for 'duped' BIO */
+#define BIO_CTRL_WPENDING	13  /* opt - number of bytes still to write */
+/* callback is int cb(BIO *bio,state,ret); */
+#define BIO_CTRL_SET_CALLBACK	14  /* opt - set callback function */
+#define BIO_CTRL_GET_CALLBACK	15  /* opt - set callback function */
+
+#define BIO_CTRL_SET_FILENAME	30	/* BIO_s_file special */
+
+/* dgram BIO stuff */
+#define BIO_CTRL_DGRAM_CONNECT       31  /* BIO dgram special */
+#define BIO_CTRL_DGRAM_SET_CONNECTED 32  /* allow for an externally
+										  * connected socket to be
+										  * passed in */ 
+#define BIO_CTRL_DGRAM_SET_RECV_TIMEOUT 33 /* setsockopt, essentially */
+#define BIO_CTRL_DGRAM_GET_RECV_TIMEOUT 34 /* getsockopt, essentially */
+#define BIO_CTRL_DGRAM_SET_SEND_TIMEOUT 35 /* setsockopt, essentially */
+#define BIO_CTRL_DGRAM_GET_SEND_TIMEOUT 36 /* getsockopt, essentially */
+
+#define BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP 37 /* flag whether the last */
+#define BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP 38 /* I/O operation tiemd out */
+					
+/* #ifdef IP_MTU_DISCOVER */
+#define BIO_CTRL_DGRAM_MTU_DISCOVER       39 /* set DF bit on egress packets */
+/* #endif */
+
+#define BIO_CTRL_DGRAM_QUERY_MTU          40 /* as kernel for current MTU */
+#define BIO_CTRL_DGRAM_GET_MTU            41 /* get cached value for MTU */
+#define BIO_CTRL_DGRAM_SET_MTU            42 /* set cached value for
+											  * MTU. want to use this
+                                              * if asking the kernel
+                                              * fails */
+
+#define BIO_CTRL_DGRAM_MTU_EXCEEDED       43 /* check whether the MTU
+											  * was exceed in the
+											  * previous write
+											  * operation */
+
+#define BIO_CTRL_DGRAM_SET_PEER           44 /* Destination for the data */
+
+
+/* modifiers */
+#define BIO_FP_READ		0x02
+#define BIO_FP_WRITE		0x04
+#define BIO_FP_APPEND		0x08
+#define BIO_FP_TEXT		0x10
+
+#define BIO_FLAGS_READ		0x01
+#define BIO_FLAGS_WRITE		0x02
+#define BIO_FLAGS_IO_SPECIAL	0x04
+#define BIO_FLAGS_RWS (BIO_FLAGS_READ|BIO_FLAGS_WRITE|BIO_FLAGS_IO_SPECIAL)
+#define BIO_FLAGS_SHOULD_RETRY	0x08
+#ifndef	BIO_FLAGS_UPLINK
+/* "UPLINK" flag denotes file descriptors provided by application.
+   It defaults to 0, as most platforms don't require UPLINK interface. */
+#define	BIO_FLAGS_UPLINK	0
+#endif
+
+/* Used in BIO_gethostbyname() */
+#define BIO_GHBN_CTRL_HITS		1
+#define BIO_GHBN_CTRL_MISSES		2
+#define BIO_GHBN_CTRL_CACHE_SIZE	3
+#define BIO_GHBN_CTRL_GET_ENTRY		4
+#define BIO_GHBN_CTRL_FLUSH		5
+
+/* Mostly used in the SSL BIO */
+/* Not used anymore
+ * #define BIO_FLAGS_PROTOCOL_DELAYED_READ 0x10
+ * #define BIO_FLAGS_PROTOCOL_DELAYED_WRITE 0x20
+ * #define BIO_FLAGS_PROTOCOL_STARTUP	0x40
+ */
+
+#define BIO_FLAGS_BASE64_NO_NL	0x100
+
+/* This is used with memory BIOs: it means we shouldn't free up or change the
+ * data in any way.
+ */
+#define BIO_FLAGS_MEM_RDONLY	0x200
+
+typedef struct bio_st BIO;
+
+void BIO_set_flags(BIO *b, int flags);
+int  BIO_test_flags(const BIO *b, int flags);
+void BIO_clear_flags(BIO *b, int flags);
+
+#define BIO_get_flags(b) BIO_test_flags(b, ~(0x0))
+#define BIO_set_retry_special(b) \
+		BIO_set_flags(b, (BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY))
+#define BIO_set_retry_read(b) \
+		BIO_set_flags(b, (BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY))
+#define BIO_set_retry_write(b) \
+		BIO_set_flags(b, (BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY))
+
+/* These are normally used internally in BIOs */
+#define BIO_clear_retry_flags(b) \
+		BIO_clear_flags(b, (BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY))
+#define BIO_get_retry_flags(b) \
+		BIO_test_flags(b, (BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY))
+
+/* These should be used by the application to tell why we should retry */
+#define BIO_should_read(a)		BIO_test_flags(a, BIO_FLAGS_READ)
+#define BIO_should_write(a)		BIO_test_flags(a, BIO_FLAGS_WRITE)
+#define BIO_should_io_special(a)	BIO_test_flags(a, BIO_FLAGS_IO_SPECIAL)
+#define BIO_retry_type(a)		BIO_test_flags(a, BIO_FLAGS_RWS)
+#define BIO_should_retry(a)		BIO_test_flags(a, BIO_FLAGS_SHOULD_RETRY)
+
+/* The next three are used in conjunction with the
+ * BIO_should_io_special() condition.  After this returns true,
+ * BIO *BIO_get_retry_BIO(BIO *bio, int *reason); will walk the BIO 
+ * stack and return the 'reason' for the special and the offending BIO.
+ * Given a BIO, BIO_get_retry_reason(bio) will return the code. */
+/* Returned from the SSL bio when the certificate retrieval code had an error */
+#define BIO_RR_SSL_X509_LOOKUP		0x01
+/* Returned from the connect BIO when a connect would have blocked */
+#define BIO_RR_CONNECT			0x02
+/* Returned from the accept BIO when an accept would have blocked */
+#define BIO_RR_ACCEPT			0x03
+
+/* These are passed by the BIO callback */
+#define BIO_CB_FREE	0x01
+#define BIO_CB_READ	0x02
+#define BIO_CB_WRITE	0x03
+#define BIO_CB_PUTS	0x04
+#define BIO_CB_GETS	0x05
+#define BIO_CB_CTRL	0x06
+
+/* The callback is called before and after the underling operation,
+ * The BIO_CB_RETURN flag indicates if it is after the call */
+#define BIO_CB_RETURN	0x80
+#define BIO_CB_return(a) ((a)|BIO_CB_RETURN))
+#define BIO_cb_pre(a)	(!((a)&BIO_CB_RETURN))
+#define BIO_cb_post(a)	((a)&BIO_CB_RETURN)
+
+long (*BIO_get_callback(const BIO *b)) (struct bio_st *,int,const char *,int, long,long);
+void BIO_set_callback(BIO *b, 
+	long (*callback)(struct bio_st *,int,const char *,int, long,long));
+char *BIO_get_callback_arg(const BIO *b);
+void BIO_set_callback_arg(BIO *b, char *arg);
+
+const char * BIO_method_name(const BIO *b);
+int BIO_method_type(const BIO *b);
+
+typedef void bio_info_cb(struct bio_st *, int, const char *, int, long, long);
+
+#ifndef OPENSSL_SYS_WIN16
+typedef struct bio_method_st
+	{
+	int type;
+	const char *name;
+	int (*bwrite)(BIO *, const char *, int);
+	int (*bread)(BIO *, char *, int);
+	int (*bputs)(BIO *, const char *);
+	int (*bgets)(BIO *, char *, int);
+	long (*ctrl)(BIO *, int, long, void *);
+	int (*create)(BIO *);
+	int (*destroy)(BIO *);
+        long (*callback_ctrl)(BIO *, int, bio_info_cb *);
+	} BIO_METHOD;
+#else
+typedef struct bio_method_st
+	{
+	int type;
+	const char *name;
+	int (_far *bwrite)();
+	int (_far *bread)();
+	int (_far *bputs)();
+	int (_far *bgets)();
+	long (_far *ctrl)();
+	int (_far *create)();
+	int (_far *destroy)();
+	long (_far *callback_ctrl)();
+	} BIO_METHOD;
+#endif
+
+struct bio_st
+	{
+	BIO_METHOD *method;
+	/* bio, mode, argp, argi, argl, ret */
+	long (*callback)(struct bio_st *,int,const char *,int, long,long);
+	char *cb_arg; /* first argument for the callback */
+
+	int init;
+	int shutdown;
+	int flags;	/* extra storage */
+	int retry_reason;
+	int num;
+	void *ptr;
+	struct bio_st *next_bio;	/* used by filter BIOs */
+	struct bio_st *prev_bio;	/* used by filter BIOs */
+	int references;
+	unsigned long num_read;
+	unsigned long num_write;
+
+	CRYPTO_EX_DATA ex_data;
+	};
+
+DECLARE_STACK_OF(BIO)
+
+typedef struct bio_f_buffer_ctx_struct
+	{
+	/* BIO *bio; */ /* this is now in the BIO struct */
+	int ibuf_size;	/* how big is the input buffer */
+	int obuf_size;	/* how big is the output buffer */
+
+	char *ibuf;		/* the char array */
+	int ibuf_len;		/* how many bytes are in it */
+	int ibuf_off;		/* write/read offset */
+
+	char *obuf;		/* the char array */
+	int obuf_len;		/* how many bytes are in it */
+	int obuf_off;		/* write/read offset */
+	} BIO_F_BUFFER_CTX;
+
+/* connect BIO stuff */
+#define BIO_CONN_S_BEFORE		1
+#define BIO_CONN_S_GET_IP		2
+#define BIO_CONN_S_GET_PORT		3
+#define BIO_CONN_S_CREATE_SOCKET	4
+#define BIO_CONN_S_CONNECT		5
+#define BIO_CONN_S_OK			6
+#define BIO_CONN_S_BLOCKED_CONNECT	7
+#define BIO_CONN_S_NBIO			8
+/*#define BIO_CONN_get_param_hostname	BIO_ctrl */
+
+#define BIO_C_SET_CONNECT			100
+#define BIO_C_DO_STATE_MACHINE			101
+#define BIO_C_SET_NBIO				102
+#define BIO_C_SET_PROXY_PARAM			103
+#define BIO_C_SET_FD				104
+#define BIO_C_GET_FD				105
+#define BIO_C_SET_FILE_PTR			106
+#define BIO_C_GET_FILE_PTR			107
+#define BIO_C_SET_FILENAME			108
+#define BIO_C_SET_SSL				109
+#define BIO_C_GET_SSL				110
+#define BIO_C_SET_MD				111
+#define BIO_C_GET_MD				112
+#define BIO_C_GET_CIPHER_STATUS			113
+#define BIO_C_SET_BUF_MEM			114
+#define BIO_C_GET_BUF_MEM_PTR			115
+#define BIO_C_GET_BUFF_NUM_LINES		116
+#define BIO_C_SET_BUFF_SIZE			117
+#define BIO_C_SET_ACCEPT			118
+#define BIO_C_SSL_MODE				119
+#define BIO_C_GET_MD_CTX			120
+#define BIO_C_GET_PROXY_PARAM			121
+#define BIO_C_SET_BUFF_READ_DATA		122 /* data to read first */
+#define BIO_C_GET_CONNECT			123
+#define BIO_C_GET_ACCEPT			124
+#define BIO_C_SET_SSL_RENEGOTIATE_BYTES		125
+#define BIO_C_GET_SSL_NUM_RENEGOTIATES		126
+#define BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT	127
+#define BIO_C_FILE_SEEK				128
+#define BIO_C_GET_CIPHER_CTX			129
+#define BIO_C_SET_BUF_MEM_EOF_RETURN		130/*return end of input value*/
+#define BIO_C_SET_BIND_MODE			131
+#define BIO_C_GET_BIND_MODE			132
+#define BIO_C_FILE_TELL				133
+#define BIO_C_GET_SOCKS				134
+#define BIO_C_SET_SOCKS				135
+
+#define BIO_C_SET_WRITE_BUF_SIZE		136/* for BIO_s_bio */
+#define BIO_C_GET_WRITE_BUF_SIZE		137
+#define BIO_C_MAKE_BIO_PAIR			138
+#define BIO_C_DESTROY_BIO_PAIR			139
+#define BIO_C_GET_WRITE_GUARANTEE		140
+#define BIO_C_GET_READ_REQUEST			141
+#define BIO_C_SHUTDOWN_WR			142
+#define BIO_C_NREAD0				143
+#define BIO_C_NREAD				144
+#define BIO_C_NWRITE0				145
+#define BIO_C_NWRITE				146
+#define BIO_C_RESET_READ_REQUEST		147
+#define BIO_C_SET_MD_CTX			148
+
+
+#define BIO_set_app_data(s,arg)		BIO_set_ex_data(s,0,arg)
+#define BIO_get_app_data(s)		BIO_get_ex_data(s,0)
+
+/* BIO_s_connect() and BIO_s_socks4a_connect() */
+#define BIO_set_conn_hostname(b,name) BIO_ctrl(b,BIO_C_SET_CONNECT,0,(char *)name)
+#define BIO_set_conn_port(b,port) BIO_ctrl(b,BIO_C_SET_CONNECT,1,(char *)port)
+#define BIO_set_conn_ip(b,ip)	  BIO_ctrl(b,BIO_C_SET_CONNECT,2,(char *)ip)
+#define BIO_set_conn_int_port(b,port) BIO_ctrl(b,BIO_C_SET_CONNECT,3,(char *)port)
+#define BIO_get_conn_hostname(b)  BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,0)
+#define BIO_get_conn_port(b)      BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,1)
+#define BIO_get_conn_ip(b) 		 BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,2)
+#define BIO_get_conn_int_port(b) BIO_int_ctrl(b,BIO_C_GET_CONNECT,3)
+
+
+#define BIO_set_nbio(b,n)	BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL)
+
+/* BIO_s_accept_socket() */
+#define BIO_set_accept_port(b,name) BIO_ctrl(b,BIO_C_SET_ACCEPT,0,(char *)name)
+#define BIO_get_accept_port(b)	BIO_ptr_ctrl(b,BIO_C_GET_ACCEPT,0)
+/* #define BIO_set_nbio(b,n)	BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL) */
+#define BIO_set_nbio_accept(b,n) BIO_ctrl(b,BIO_C_SET_ACCEPT,1,(n)?"a":NULL)
+#define BIO_set_accept_bios(b,bio) BIO_ctrl(b,BIO_C_SET_ACCEPT,2,(char *)bio)
+
+#define BIO_BIND_NORMAL			0
+#define BIO_BIND_REUSEADDR_IF_UNUSED	1
+#define BIO_BIND_REUSEADDR		2
+#define BIO_set_bind_mode(b,mode) BIO_ctrl(b,BIO_C_SET_BIND_MODE,mode,NULL)
+#define BIO_get_bind_mode(b,mode) BIO_ctrl(b,BIO_C_GET_BIND_MODE,0,NULL)
+
+#define BIO_do_connect(b)	BIO_do_handshake(b)
+#define BIO_do_accept(b)	BIO_do_handshake(b)
+#define BIO_do_handshake(b)	BIO_ctrl(b,BIO_C_DO_STATE_MACHINE,0,NULL)
+
+/* BIO_s_proxy_client() */
+#define BIO_set_url(b,url)	BIO_ctrl(b,BIO_C_SET_PROXY_PARAM,0,(char *)(url))
+#define BIO_set_proxies(b,p)	BIO_ctrl(b,BIO_C_SET_PROXY_PARAM,1,(char *)(p))
+/* BIO_set_nbio(b,n) */
+#define BIO_set_filter_bio(b,s) BIO_ctrl(b,BIO_C_SET_PROXY_PARAM,2,(char *)(s))
+/* BIO *BIO_get_filter_bio(BIO *bio); */
+#define BIO_set_proxy_cb(b,cb) BIO_callback_ctrl(b,BIO_C_SET_PROXY_PARAM,3,(void *(*cb)()))
+#define BIO_set_proxy_header(b,sk) BIO_ctrl(b,BIO_C_SET_PROXY_PARAM,4,(char *)sk)
+#define BIO_set_no_connect_return(b,bool) BIO_int_ctrl(b,BIO_C_SET_PROXY_PARAM,5,bool)
+
+#define BIO_get_proxy_header(b,skp) BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,0,(char *)skp)
+#define BIO_get_proxies(b,pxy_p) BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,1,(char *)(pxy_p))
+#define BIO_get_url(b,url)	BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,2,(char *)(url))
+#define BIO_get_no_connect_return(b)	BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,5,NULL)
+
+#define BIO_set_fd(b,fd,c)	BIO_int_ctrl(b,BIO_C_SET_FD,c,fd)
+#define BIO_get_fd(b,c)		BIO_ctrl(b,BIO_C_GET_FD,0,(char *)c)
+
+#define BIO_set_fp(b,fp,c)	BIO_ctrl(b,BIO_C_SET_FILE_PTR,c,(char *)fp)
+#define BIO_get_fp(b,fpp)	BIO_ctrl(b,BIO_C_GET_FILE_PTR,0,(char *)fpp)
+
+#define BIO_seek(b,ofs)	(int)BIO_ctrl(b,BIO_C_FILE_SEEK,ofs,NULL)
+#define BIO_tell(b)	(int)BIO_ctrl(b,BIO_C_FILE_TELL,0,NULL)
+
+/* name is cast to lose const, but might be better to route through a function
+   so we can do it safely */
+#ifdef CONST_STRICT
+/* If you are wondering why this isn't defined, its because CONST_STRICT is
+ * purely a compile-time kludge to allow const to be checked.
+ */
+int BIO_read_filename(BIO *b,const char *name);
+#else
+#define BIO_read_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \
+		BIO_CLOSE|BIO_FP_READ,(char *)name)
+#endif
+#define BIO_write_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \
+		BIO_CLOSE|BIO_FP_WRITE,name)
+#define BIO_append_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \
+		BIO_CLOSE|BIO_FP_APPEND,name)
+#define BIO_rw_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \
+		BIO_CLOSE|BIO_FP_READ|BIO_FP_WRITE,name)
+
+/* WARNING WARNING, this ups the reference count on the read bio of the
+ * SSL structure.  This is because the ssl read BIO is now pointed to by
+ * the next_bio field in the bio.  So when you free the BIO, make sure
+ * you are doing a BIO_free_all() to catch the underlying BIO. */
+#define BIO_set_ssl(b,ssl,c)	BIO_ctrl(b,BIO_C_SET_SSL,c,(char *)ssl)
+#define BIO_get_ssl(b,sslp)	BIO_ctrl(b,BIO_C_GET_SSL,0,(char *)sslp)
+#define BIO_set_ssl_mode(b,client)	BIO_ctrl(b,BIO_C_SSL_MODE,client,NULL)
+#define BIO_set_ssl_renegotiate_bytes(b,num) \
+	BIO_ctrl(b,BIO_C_SET_SSL_RENEGOTIATE_BYTES,num,NULL);
+#define BIO_get_num_renegotiates(b) \
+	BIO_ctrl(b,BIO_C_GET_SSL_NUM_RENEGOTIATES,0,NULL);
+#define BIO_set_ssl_renegotiate_timeout(b,seconds) \
+	BIO_ctrl(b,BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT,seconds,NULL);
+
+/* defined in evp.h */
+/* #define BIO_set_md(b,md)	BIO_ctrl(b,BIO_C_SET_MD,1,(char *)md) */
+
+#define BIO_get_mem_data(b,pp)	BIO_ctrl(b,BIO_CTRL_INFO,0,(char *)pp)
+#define BIO_set_mem_buf(b,bm,c)	BIO_ctrl(b,BIO_C_SET_BUF_MEM,c,(char *)bm)
+#define BIO_get_mem_ptr(b,pp)	BIO_ctrl(b,BIO_C_GET_BUF_MEM_PTR,0,(char *)pp)
+#define BIO_set_mem_eof_return(b,v) \
+				BIO_ctrl(b,BIO_C_SET_BUF_MEM_EOF_RETURN,v,NULL)
+
+/* For the BIO_f_buffer() type */
+#define BIO_get_buffer_num_lines(b)	BIO_ctrl(b,BIO_C_GET_BUFF_NUM_LINES,0,NULL)
+#define BIO_set_buffer_size(b,size)	BIO_ctrl(b,BIO_C_SET_BUFF_SIZE,size,NULL)
+#define BIO_set_read_buffer_size(b,size) BIO_int_ctrl(b,BIO_C_SET_BUFF_SIZE,size,0)
+#define BIO_set_write_buffer_size(b,size) BIO_int_ctrl(b,BIO_C_SET_BUFF_SIZE,size,1)
+#define BIO_set_buffer_read_data(b,buf,num) BIO_ctrl(b,BIO_C_SET_BUFF_READ_DATA,num,buf)
+
+/* Don't use the next one unless you know what you are doing :-) */
+#define BIO_dup_state(b,ret)	BIO_ctrl(b,BIO_CTRL_DUP,0,(char *)(ret))
+
+#define BIO_reset(b)		(int)BIO_ctrl(b,BIO_CTRL_RESET,0,NULL)
+#define BIO_eof(b)		(int)BIO_ctrl(b,BIO_CTRL_EOF,0,NULL)
+#define BIO_set_close(b,c)	(int)BIO_ctrl(b,BIO_CTRL_SET_CLOSE,(c),NULL)
+#define BIO_get_close(b)	(int)BIO_ctrl(b,BIO_CTRL_GET_CLOSE,0,NULL)
+#define BIO_pending(b)		(int)BIO_ctrl(b,BIO_CTRL_PENDING,0,NULL)
+#define BIO_wpending(b)		(int)BIO_ctrl(b,BIO_CTRL_WPENDING,0,NULL)
+/* ...pending macros have inappropriate return type */
+size_t BIO_ctrl_pending(BIO *b);
+size_t BIO_ctrl_wpending(BIO *b);
+#define BIO_flush(b)		(int)BIO_ctrl(b,BIO_CTRL_FLUSH,0,NULL)
+#define BIO_get_info_callback(b,cbp) (int)BIO_ctrl(b,BIO_CTRL_GET_CALLBACK,0, \
+						   cbp)
+#define BIO_set_info_callback(b,cb) (int)BIO_callback_ctrl(b,BIO_CTRL_SET_CALLBACK,cb)
+
+/* For the BIO_f_buffer() type */
+#define BIO_buffer_get_num_lines(b) BIO_ctrl(b,BIO_CTRL_GET,0,NULL)
+
+/* For BIO_s_bio() */
+#define BIO_set_write_buf_size(b,size) (int)BIO_ctrl(b,BIO_C_SET_WRITE_BUF_SIZE,size,NULL)
+#define BIO_get_write_buf_size(b,size) (size_t)BIO_ctrl(b,BIO_C_GET_WRITE_BUF_SIZE,size,NULL)
+#define BIO_make_bio_pair(b1,b2)   (int)BIO_ctrl(b1,BIO_C_MAKE_BIO_PAIR,0,b2)
+#define BIO_destroy_bio_pair(b)    (int)BIO_ctrl(b,BIO_C_DESTROY_BIO_PAIR,0,NULL)
+#define BIO_shutdown_wr(b) (int)BIO_ctrl(b, BIO_C_SHUTDOWN_WR, 0, NULL)
+/* macros with inappropriate type -- but ...pending macros use int too: */
+#define BIO_get_write_guarantee(b) (int)BIO_ctrl(b,BIO_C_GET_WRITE_GUARANTEE,0,NULL)
+#define BIO_get_read_request(b)    (int)BIO_ctrl(b,BIO_C_GET_READ_REQUEST,0,NULL)
+size_t BIO_ctrl_get_write_guarantee(BIO *b);
+size_t BIO_ctrl_get_read_request(BIO *b);
+int BIO_ctrl_reset_read_request(BIO *b);
+
+/* ctrl macros for dgram */
+#define BIO_ctrl_dgram_connect(b,peer)  \
+                     (int)BIO_ctrl(b,BIO_CTRL_DGRAM_CONNECT,0, (char *)peer)
+#define BIO_ctrl_set_connected(b, state, peer) \
+         (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SET_CONNECTED, state, (char *)peer)
+#define BIO_dgram_recv_timedout(b) \
+         (int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP, 0, NULL)
+#define BIO_dgram_send_timedout(b) \
+         (int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP, 0, NULL)
+#define BIO_dgram_set_peer(b,peer) \
+         (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, (char *)peer)
+
+/* These two aren't currently implemented */
+/* int BIO_get_ex_num(BIO *bio); */
+/* void BIO_set_ex_free_func(BIO *bio,int idx,void (*cb)()); */
+int BIO_set_ex_data(BIO *bio,int idx,void *data);
+void *BIO_get_ex_data(BIO *bio,int idx);
+int BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+	CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+unsigned long BIO_number_read(BIO *bio);
+unsigned long BIO_number_written(BIO *bio);
+
+# ifndef OPENSSL_NO_FP_API
+#  if defined(OPENSSL_SYS_WIN16) && defined(_WINDLL)
+BIO_METHOD *BIO_s_file_internal(void);
+BIO *BIO_new_file_internal(char *filename, char *mode);
+BIO *BIO_new_fp_internal(FILE *stream, int close_flag);
+#    define BIO_s_file	BIO_s_file_internal
+#    define BIO_new_file	BIO_new_file_internal
+#    define BIO_new_fp	BIO_new_fp_internal
+#  else /* FP_API */
+BIO_METHOD *BIO_s_file(void );
+BIO *BIO_new_file(const char *filename, const char *mode);
+BIO *BIO_new_fp(FILE *stream, int close_flag);
+#    define BIO_s_file_internal		BIO_s_file
+#    define BIO_new_file_internal	BIO_new_file
+#    define BIO_new_fp_internal		BIO_s_file
+#  endif /* FP_API */
+# endif
+BIO *	BIO_new(BIO_METHOD *type);
+int	BIO_set(BIO *a,BIO_METHOD *type);
+int	BIO_free(BIO *a);
+void	BIO_vfree(BIO *a);
+int	BIO_read(BIO *b, void *data, int len);
+int	BIO_gets(BIO *bp,char *buf, int size);
+int	BIO_write(BIO *b, const void *data, int len);
+int	BIO_puts(BIO *bp,const char *buf);
+int	BIO_indent(BIO *b,int indent,int max);
+long	BIO_ctrl(BIO *bp,int cmd,long larg,void *parg);
+long BIO_callback_ctrl(BIO *b, int cmd, void (*fp)(struct bio_st *, int, const char *, int, long, long));
+char *	BIO_ptr_ctrl(BIO *bp,int cmd,long larg);
+long	BIO_int_ctrl(BIO *bp,int cmd,long larg,int iarg);
+BIO *	BIO_push(BIO *b,BIO *append);
+BIO *	BIO_pop(BIO *b);
+void	BIO_free_all(BIO *a);
+BIO *	BIO_find_type(BIO *b,int bio_type);
+BIO *	BIO_next(BIO *b);
+BIO *	BIO_get_retry_BIO(BIO *bio, int *reason);
+int	BIO_get_retry_reason(BIO *bio);
+BIO *	BIO_dup_chain(BIO *in);
+
+int BIO_nread0(BIO *bio, char **buf);
+int BIO_nread(BIO *bio, char **buf, int num);
+int BIO_nwrite0(BIO *bio, char **buf);
+int BIO_nwrite(BIO *bio, char **buf, int num);
+
+#ifndef OPENSSL_SYS_WIN16
+long BIO_debug_callback(BIO *bio,int cmd,const char *argp,int argi,
+	long argl,long ret);
+#else
+long _far _loadds BIO_debug_callback(BIO *bio,int cmd,const char *argp,int argi,
+	long argl,long ret);
+#endif
+
+BIO_METHOD *BIO_s_mem(void);
+BIO *BIO_new_mem_buf(void *buf, int len);
+BIO_METHOD *BIO_s_socket(void);
+BIO_METHOD *BIO_s_connect(void);
+BIO_METHOD *BIO_s_accept(void);
+BIO_METHOD *BIO_s_fd(void);
+#ifndef OPENSSL_SYS_OS2
+BIO_METHOD *BIO_s_log(void);
+#endif
+BIO_METHOD *BIO_s_bio(void);
+BIO_METHOD *BIO_s_null(void);
+BIO_METHOD *BIO_f_null(void);
+BIO_METHOD *BIO_f_buffer(void);
+#ifdef OPENSSL_SYS_VMS
+BIO_METHOD *BIO_f_linebuffer(void);
+#endif
+BIO_METHOD *BIO_f_nbio_test(void);
+#ifndef OPENSSL_NO_DGRAM
+BIO_METHOD *BIO_s_datagram(void);
+#endif
+
+/* BIO_METHOD *BIO_f_ber(void); */
+
+int BIO_sock_should_retry(int i);
+int BIO_sock_non_fatal_error(int error);
+int BIO_dgram_non_fatal_error(int error);
+
+int BIO_fd_should_retry(int i);
+int BIO_fd_non_fatal_error(int error);
+int BIO_dump_cb(int (*cb)(const void *data, size_t len, void *u),
+		void *u, const char *s, int len);
+int BIO_dump_indent_cb(int (*cb)(const void *data, size_t len, void *u),
+		       void *u, const char *s, int len, int indent);
+int BIO_dump(BIO *b,const char *bytes,int len);
+int BIO_dump_indent(BIO *b,const char *bytes,int len,int indent);
+#ifndef OPENSSL_NO_FP_API
+int BIO_dump_fp(FILE *fp, const char *s, int len);
+int BIO_dump_indent_fp(FILE *fp, const char *s, int len, int indent);
+#endif
+struct hostent *BIO_gethostbyname(const char *name);
+/* We might want a thread-safe interface too:
+ * struct hostent *BIO_gethostbyname_r(const char *name,
+ *     struct hostent *result, void *buffer, size_t buflen);
+ * or something similar (caller allocates a struct hostent,
+ * pointed to by "result", and additional buffer space for the various
+ * substructures; if the buffer does not suffice, NULL is returned
+ * and an appropriate error code is set).
+ */
+int BIO_sock_error(int sock);
+int BIO_socket_ioctl(int fd, long type, void *arg);
+int BIO_socket_nbio(int fd,int mode);
+int BIO_get_port(const char *str, unsigned short *port_ptr);
+int BIO_get_host_ip(const char *str, unsigned char *ip);
+int BIO_get_accept_socket(char *host_port,int mode);
+int BIO_accept(int sock,char **ip_port);
+int BIO_sock_init(void );
+void BIO_sock_cleanup(void);
+int BIO_set_tcp_ndelay(int sock,int turn_on);
+
+BIO *BIO_new_socket(int sock, int close_flag);
+BIO *BIO_new_dgram(int fd, int close_flag);
+BIO *BIO_new_fd(int fd, int close_flag);
+BIO *BIO_new_connect(char *host_port);
+BIO *BIO_new_accept(char *host_port);
+
+int BIO_new_bio_pair(BIO **bio1, size_t writebuf1,
+	BIO **bio2, size_t writebuf2);
+/* If successful, returns 1 and in *bio1, *bio2 two BIO pair endpoints.
+ * Otherwise returns 0 and sets *bio1 and *bio2 to NULL.
+ * Size 0 uses default value.
+ */
+
+void BIO_copy_next_retry(BIO *b);
+
+/*long BIO_ghbn_ctrl(int cmd,int iarg,char *parg);*/
+
+#ifdef __GNUC__
+#  define __bio_h__attr__ __attribute__
+#else
+#  define __bio_h__attr__(x)
+#endif
+int BIO_printf(BIO *bio, const char *format, ...)
+	__bio_h__attr__((__format__(__printf__,2,3)));
+int BIO_vprintf(BIO *bio, const char *format, va_list args)
+	__bio_h__attr__((__format__(__printf__,2,0)));
+int BIO_snprintf(char *buf, size_t n, const char *format, ...)
+	__bio_h__attr__((__format__(__printf__,3,4)));
+int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
+	__bio_h__attr__((__format__(__printf__,3,0)));
+#undef __bio_h__attr__
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_BIO_strings(void);
+
+/* Error codes for the BIO functions. */
+
+/* Function codes. */
+#define BIO_F_ACPT_STATE				 100
+#define BIO_F_BIO_ACCEPT				 101
+#define BIO_F_BIO_BER_GET_HEADER			 102
+#define BIO_F_BIO_CALLBACK_CTRL				 131
+#define BIO_F_BIO_CTRL					 103
+#define BIO_F_BIO_GETHOSTBYNAME				 120
+#define BIO_F_BIO_GETS					 104
+#define BIO_F_BIO_GET_ACCEPT_SOCKET			 105
+#define BIO_F_BIO_GET_HOST_IP				 106
+#define BIO_F_BIO_GET_PORT				 107
+#define BIO_F_BIO_MAKE_PAIR				 121
+#define BIO_F_BIO_NEW					 108
+#define BIO_F_BIO_NEW_FILE				 109
+#define BIO_F_BIO_NEW_MEM_BUF				 126
+#define BIO_F_BIO_NREAD					 123
+#define BIO_F_BIO_NREAD0				 124
+#define BIO_F_BIO_NWRITE				 125
+#define BIO_F_BIO_NWRITE0				 122
+#define BIO_F_BIO_PUTS					 110
+#define BIO_F_BIO_READ					 111
+#define BIO_F_BIO_SOCK_INIT				 112
+#define BIO_F_BIO_WRITE					 113
+#define BIO_F_BUFFER_CTRL				 114
+#define BIO_F_CONN_CTRL					 127
+#define BIO_F_CONN_STATE				 115
+#define BIO_F_FILE_CTRL					 116
+#define BIO_F_FILE_READ					 130
+#define BIO_F_LINEBUFFER_CTRL				 129
+#define BIO_F_MEM_READ					 128
+#define BIO_F_MEM_WRITE					 117
+#define BIO_F_SSL_NEW					 118
+#define BIO_F_WSASTARTUP				 119
+
+/* Reason codes. */
+#define BIO_R_ACCEPT_ERROR				 100
+#define BIO_R_BAD_FOPEN_MODE				 101
+#define BIO_R_BAD_HOSTNAME_LOOKUP			 102
+#define BIO_R_BROKEN_PIPE				 124
+#define BIO_R_CONNECT_ERROR				 103
+#define BIO_R_EOF_ON_MEMORY_BIO				 127
+#define BIO_R_ERROR_SETTING_NBIO			 104
+#define BIO_R_ERROR_SETTING_NBIO_ON_ACCEPTED_SOCKET	 105
+#define BIO_R_ERROR_SETTING_NBIO_ON_ACCEPT_SOCKET	 106
+#define BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET		 107
+#define BIO_R_INVALID_ARGUMENT				 125
+#define BIO_R_INVALID_IP_ADDRESS			 108
+#define BIO_R_IN_USE					 123
+#define BIO_R_KEEPALIVE					 109
+#define BIO_R_NBIO_CONNECT_ERROR			 110
+#define BIO_R_NO_ACCEPT_PORT_SPECIFIED			 111
+#define BIO_R_NO_HOSTNAME_SPECIFIED			 112
+#define BIO_R_NO_PORT_DEFINED				 113
+#define BIO_R_NO_PORT_SPECIFIED				 114
+#define BIO_R_NO_SUCH_FILE				 128
+#define BIO_R_NULL_PARAMETER				 115
+#define BIO_R_TAG_MISMATCH				 116
+#define BIO_R_UNABLE_TO_BIND_SOCKET			 117
+#define BIO_R_UNABLE_TO_CREATE_SOCKET			 118
+#define BIO_R_UNABLE_TO_LISTEN_SOCKET			 119
+#define BIO_R_UNINITIALIZED				 120
+#define BIO_R_UNSUPPORTED_METHOD			 121
+#define BIO_R_WRITE_TO_READ_ONLY_BIO			 126
+#define BIO_R_WSASTARTUP				 122
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/dep/include/openssl/blowfish.h b/dep/include/openssl/blowfish.h
new file mode 100644
index 00000000000..cd49e85ab29
--- /dev/null
+++ b/dep/include/openssl/blowfish.h
@@ -0,0 +1,127 @@
+/* crypto/bf/blowfish.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_BLOWFISH_H
+#define HEADER_BLOWFISH_H
+
+#include 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#ifdef OPENSSL_NO_BF
+#error BF is disabled.
+#endif
+
+#define BF_ENCRYPT	1
+#define BF_DECRYPT	0
+
+/*
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * ! BF_LONG has to be at least 32 bits wide. If it's wider, then !
+ * ! BF_LONG_LOG2 has to be defined along.                        !
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ */
+
+#if defined(OPENSSL_SYS_WIN16) || defined(__LP32__)
+#define BF_LONG unsigned long
+#elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__)
+#define BF_LONG unsigned long
+#define BF_LONG_LOG2 3
+/*
+ * _CRAY note. I could declare short, but I have no idea what impact
+ * does it have on performance on none-T3E machines. I could declare
+ * int, but at least on C90 sizeof(int) can be chosen at compile time.
+ * So I've chosen long...
+ *					
+ */
+#else
+#define BF_LONG unsigned int
+#endif
+
+#define BF_ROUNDS	16
+#define BF_BLOCK	8
+
+typedef struct bf_key_st
+	{
+	BF_LONG P[BF_ROUNDS+2];
+	BF_LONG S[4*256];
+	} BF_KEY;
+
+ 
+void BF_set_key(BF_KEY *key, int len, const unsigned char *data);
+
+void BF_encrypt(BF_LONG *data,const BF_KEY *key);
+void BF_decrypt(BF_LONG *data,const BF_KEY *key);
+
+void BF_ecb_encrypt(const unsigned char *in, unsigned char *out,
+	const BF_KEY *key, int enc);
+void BF_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,
+	const BF_KEY *schedule, unsigned char *ivec, int enc);
+void BF_cfb64_encrypt(const unsigned char *in, unsigned char *out, long length,
+	const BF_KEY *schedule, unsigned char *ivec, int *num, int enc);
+void BF_ofb64_encrypt(const unsigned char *in, unsigned char *out, long length,
+	const BF_KEY *schedule, unsigned char *ivec, int *num);
+const char *BF_options(void);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff --git a/dep/include/openssl/bn.h b/dep/include/openssl/bn.h
new file mode 100644
index 00000000000..95c5d643cbd
--- /dev/null
+++ b/dep/include/openssl/bn.h
@@ -0,0 +1,827 @@
+/* crypto/bn/bn.h */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * Portions of the attached software ("Contribution") are developed by 
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the Eric Young open source
+ * license provided above.
+ *
+ * The binary polynomial arithmetic software is originally written by 
+ * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
+ *
+ */
+
+#ifndef HEADER_BN_H
+#define HEADER_BN_H
+
+#include 
+#ifndef OPENSSL_NO_FP_API
+#include  /* FILE */
+#endif
+#include 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* These preprocessor symbols control various aspects of the bignum headers and
+ * library code. They're not defined by any "normal" configuration, as they are
+ * intended for development and testing purposes. NB: defining all three can be
+ * useful for debugging application code as well as openssl itself.
+ *
+ * BN_DEBUG - turn on various debugging alterations to the bignum code
+ * BN_DEBUG_RAND - uses random poisoning of unused words to trip up
+ * mismanagement of bignum internals. You must also define BN_DEBUG.
+ */
+/* #define BN_DEBUG */
+/* #define BN_DEBUG_RAND */
+
+#define BN_MUL_COMBA
+#define BN_SQR_COMBA
+#define BN_RECURSION
+
+/* This next option uses the C libraries (2 word)/(1 word) function.
+ * If it is not defined, I use my C version (which is slower).
+ * The reason for this flag is that when the particular C compiler
+ * library routine is used, and the library is linked with a different
+ * compiler, the library is missing.  This mostly happens when the
+ * library is built with gcc and then linked using normal cc.  This would
+ * be a common occurrence because gcc normally produces code that is
+ * 2 times faster than system compilers for the big number stuff.
+ * For machines with only one compiler (or shared libraries), this should
+ * be on.  Again this in only really a problem on machines
+ * using "long long's", are 32bit, and are not using my assembler code. */
+#if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WINDOWS) || \
+    defined(OPENSSL_SYS_WIN32) || defined(linux)
+# ifndef BN_DIV2W
+#  define BN_DIV2W
+# endif
+#endif
+
+/* assuming long is 64bit - this is the DEC Alpha
+ * unsigned long long is only 64 bits :-(, don't define
+ * BN_LLONG for the DEC Alpha */
+#ifdef SIXTY_FOUR_BIT_LONG
+#define BN_ULLONG	unsigned long long
+#define BN_ULONG	unsigned long
+#define BN_LONG		long
+#define BN_BITS		128
+#define BN_BYTES	8
+#define BN_BITS2	64
+#define BN_BITS4	32
+#define BN_MASK		(0xffffffffffffffffffffffffffffffffLL)
+#define BN_MASK2	(0xffffffffffffffffL)
+#define BN_MASK2l	(0xffffffffL)
+#define BN_MASK2h	(0xffffffff00000000L)
+#define BN_MASK2h1	(0xffffffff80000000L)
+#define BN_TBIT		(0x8000000000000000L)
+#define BN_DEC_CONV	(10000000000000000000UL)
+#define BN_DEC_FMT1	"%lu"
+#define BN_DEC_FMT2	"%019lu"
+#define BN_DEC_NUM	19
+#endif
+
+/* This is where the long long data type is 64 bits, but long is 32.
+ * For machines where there are 64bit registers, this is the mode to use.
+ * IRIX, on R4000 and above should use this mode, along with the relevant
+ * assembler code :-).  Do NOT define BN_LLONG.
+ */
+#ifdef SIXTY_FOUR_BIT
+#undef BN_LLONG
+#undef BN_ULLONG
+#define BN_ULONG	unsigned long long
+#define BN_LONG		long long
+#define BN_BITS		128
+#define BN_BYTES	8
+#define BN_BITS2	64
+#define BN_BITS4	32
+#define BN_MASK2	(0xffffffffffffffffLL)
+#define BN_MASK2l	(0xffffffffL)
+#define BN_MASK2h	(0xffffffff00000000LL)
+#define BN_MASK2h1	(0xffffffff80000000LL)
+#define BN_TBIT		(0x8000000000000000LL)
+#define BN_DEC_CONV	(10000000000000000000ULL)
+#define BN_DEC_FMT1	"%llu"
+#define BN_DEC_FMT2	"%019llu"
+#define BN_DEC_NUM	19
+#endif
+
+#ifdef THIRTY_TWO_BIT
+#ifdef BN_LLONG
+# if defined(OPENSSL_SYS_WIN32) && !defined(__GNUC__)
+#  define BN_ULLONG	unsigned __int64
+# else
+#  define BN_ULLONG	unsigned long long
+# endif
+#endif
+#define BN_ULONG	unsigned long
+#define BN_LONG		long
+#define BN_BITS		64
+#define BN_BYTES	4
+#define BN_BITS2	32
+#define BN_BITS4	16
+#ifdef OPENSSL_SYS_WIN32
+/* VC++ doesn't like the LL suffix */
+#define BN_MASK		(0xffffffffffffffffL)
+#else
+#define BN_MASK		(0xffffffffffffffffLL)
+#endif
+#define BN_MASK2	(0xffffffffL)
+#define BN_MASK2l	(0xffff)
+#define BN_MASK2h1	(0xffff8000L)
+#define BN_MASK2h	(0xffff0000L)
+#define BN_TBIT		(0x80000000L)
+#define BN_DEC_CONV	(1000000000L)
+#define BN_DEC_FMT1	"%lu"
+#define BN_DEC_FMT2	"%09lu"
+#define BN_DEC_NUM	9
+#endif
+
+#ifdef SIXTEEN_BIT
+#ifndef BN_DIV2W
+#define BN_DIV2W
+#endif
+#define BN_ULLONG	unsigned long
+#define BN_ULONG	unsigned short
+#define BN_LONG		short
+#define BN_BITS		32
+#define BN_BYTES	2
+#define BN_BITS2	16
+#define BN_BITS4	8
+#define BN_MASK		(0xffffffff)
+#define BN_MASK2	(0xffff)
+#define BN_MASK2l	(0xff)
+#define BN_MASK2h1	(0xff80)
+#define BN_MASK2h	(0xff00)
+#define BN_TBIT		(0x8000)
+#define BN_DEC_CONV	(100000)
+#define BN_DEC_FMT1	"%u"
+#define BN_DEC_FMT2	"%05u"
+#define BN_DEC_NUM	5
+#endif
+
+#ifdef EIGHT_BIT
+#ifndef BN_DIV2W
+#define BN_DIV2W
+#endif
+#define BN_ULLONG	unsigned short
+#define BN_ULONG	unsigned char
+#define BN_LONG		char
+#define BN_BITS		16
+#define BN_BYTES	1
+#define BN_BITS2	8
+#define BN_BITS4	4
+#define BN_MASK		(0xffff)
+#define BN_MASK2	(0xff)
+#define BN_MASK2l	(0xf)
+#define BN_MASK2h1	(0xf8)
+#define BN_MASK2h	(0xf0)
+#define BN_TBIT		(0x80)
+#define BN_DEC_CONV	(100)
+#define BN_DEC_FMT1	"%u"
+#define BN_DEC_FMT2	"%02u"
+#define BN_DEC_NUM	2
+#endif
+
+#define BN_DEFAULT_BITS	1280
+
+#define BN_FLG_MALLOCED		0x01
+#define BN_FLG_STATIC_DATA	0x02
+#define BN_FLG_EXP_CONSTTIME	0x04 /* avoid leaking exponent information through timings
+                            	      * (BN_mod_exp_mont() will call BN_mod_exp_mont_consttime) */
+#ifndef OPENSSL_NO_DEPRECATED
+#define BN_FLG_FREE		0x8000	/* used for debuging */
+#endif
+#define BN_set_flags(b,n)	((b)->flags|=(n))
+#define BN_get_flags(b,n)	((b)->flags&(n))
+
+/* get a clone of a BIGNUM with changed flags, for *temporary* use only
+ * (the two BIGNUMs cannot not be used in parallel!) */
+#define BN_with_flags(dest,b,n)  ((dest)->d=(b)->d, \
+                                  (dest)->top=(b)->top, \
+                                  (dest)->dmax=(b)->dmax, \
+                                  (dest)->neg=(b)->neg, \
+                                  (dest)->flags=(((dest)->flags & BN_FLG_MALLOCED) \
+                                                 |  ((b)->flags & ~BN_FLG_MALLOCED) \
+                                                 |  BN_FLG_STATIC_DATA \
+                                                 |  (n)))
+
+/* Already declared in ossl_typ.h */
+#if 0
+typedef struct bignum_st BIGNUM;
+/* Used for temp variables (declaration hidden in bn_lcl.h) */
+typedef struct bignum_ctx BN_CTX;
+typedef struct bn_blinding_st BN_BLINDING;
+typedef struct bn_mont_ctx_st BN_MONT_CTX;
+typedef struct bn_recp_ctx_st BN_RECP_CTX;
+typedef struct bn_gencb_st BN_GENCB;
+#endif
+
+struct bignum_st
+	{
+	BN_ULONG *d;	/* Pointer to an array of 'BN_BITS2' bit chunks. */
+	int top;	/* Index of last used d +1. */
+	/* The next are internal book keeping for bn_expand. */
+	int dmax;	/* Size of the d array. */
+	int neg;	/* one if the number is negative */
+	int flags;
+	};
+
+/* Used for montgomery multiplication */
+struct bn_mont_ctx_st
+	{
+	int ri;        /* number of bits in R */
+	BIGNUM RR;     /* used to convert to montgomery form */
+	BIGNUM N;      /* The modulus */
+	BIGNUM Ni;     /* R*(1/R mod N) - N*Ni = 1
+	                * (Ni is only stored for bignum algorithm) */
+	BN_ULONG n0;   /* least significant word of Ni */
+	int flags;
+	};
+
+/* Used for reciprocal division/mod functions
+ * It cannot be shared between threads
+ */
+struct bn_recp_ctx_st
+	{
+	BIGNUM N;	/* the divisor */
+	BIGNUM Nr;	/* the reciprocal */
+	int num_bits;
+	int shift;
+	int flags;
+	};
+
+/* Used for slow "generation" functions. */
+struct bn_gencb_st
+	{
+	unsigned int ver;	/* To handle binary (in)compatibility */
+	void *arg;		/* callback-specific data */
+	union
+		{
+		/* if(ver==1) - handles old style callbacks */
+		void (*cb_1)(int, int, void *);
+		/* if(ver==2) - new callback style */
+		int (*cb_2)(int, int, BN_GENCB *);
+		} cb;
+	};
+/* Wrapper function to make using BN_GENCB easier,  */
+int BN_GENCB_call(BN_GENCB *cb, int a, int b);
+/* Macro to populate a BN_GENCB structure with an "old"-style callback */
+#define BN_GENCB_set_old(gencb, callback, cb_arg) { \
+		BN_GENCB *tmp_gencb = (gencb); \
+		tmp_gencb->ver = 1; \
+		tmp_gencb->arg = (cb_arg); \
+		tmp_gencb->cb.cb_1 = (callback); }
+/* Macro to populate a BN_GENCB structure with a "new"-style callback */
+#define BN_GENCB_set(gencb, callback, cb_arg) { \
+		BN_GENCB *tmp_gencb = (gencb); \
+		tmp_gencb->ver = 2; \
+		tmp_gencb->arg = (cb_arg); \
+		tmp_gencb->cb.cb_2 = (callback); }
+
+#define BN_prime_checks 0 /* default: select number of iterations
+			     based on the size of the number */
+
+/* number of Miller-Rabin iterations for an error rate  of less than 2^-80
+ * for random 'b'-bit input, b >= 100 (taken from table 4.4 in the Handbook
+ * of Applied Cryptography [Menezes, van Oorschot, Vanstone; CRC Press 1996];
+ * original paper: Damgaard, Landrock, Pomerance: Average case error estimates
+ * for the strong probable prime test. -- Math. Comp. 61 (1993) 177-194) */
+#define BN_prime_checks_for_size(b) ((b) >= 1300 ?  2 : \
+                                (b) >=  850 ?  3 : \
+                                (b) >=  650 ?  4 : \
+                                (b) >=  550 ?  5 : \
+                                (b) >=  450 ?  6 : \
+                                (b) >=  400 ?  7 : \
+                                (b) >=  350 ?  8 : \
+                                (b) >=  300 ?  9 : \
+                                (b) >=  250 ? 12 : \
+                                (b) >=  200 ? 15 : \
+                                (b) >=  150 ? 18 : \
+                                /* b >= 100 */ 27)
+
+#define BN_num_bytes(a)	((BN_num_bits(a)+7)/8)
+
+/* Note that BN_abs_is_word didn't work reliably for w == 0 until 0.9.8 */
+#define BN_abs_is_word(a,w) ((((a)->top == 1) && ((a)->d[0] == (BN_ULONG)(w))) || \
+				(((w) == 0) && ((a)->top == 0)))
+#define BN_is_zero(a)       ((a)->top == 0)
+#define BN_is_one(a)        (BN_abs_is_word((a),1) && !(a)->neg)
+#define BN_is_word(a,w)     (BN_abs_is_word((a),(w)) && (!(w) || !(a)->neg))
+#define BN_is_odd(a)	    (((a)->top > 0) && ((a)->d[0] & 1))
+
+#define BN_one(a)	(BN_set_word((a),1))
+#define BN_zero_ex(a) \
+	do { \
+		BIGNUM *_tmp_bn = (a); \
+		_tmp_bn->top = 0; \
+		_tmp_bn->neg = 0; \
+	} while(0)
+#ifdef OPENSSL_NO_DEPRECATED
+#define BN_zero(a)	BN_zero_ex(a)
+#else
+#define BN_zero(a)	(BN_set_word((a),0))
+#endif
+
+const BIGNUM *BN_value_one(void);
+char *	BN_options(void);
+BN_CTX *BN_CTX_new(void);
+#ifndef OPENSSL_NO_DEPRECATED
+void	BN_CTX_init(BN_CTX *c);
+#endif
+void	BN_CTX_free(BN_CTX *c);
+void	BN_CTX_start(BN_CTX *ctx);
+BIGNUM *BN_CTX_get(BN_CTX *ctx);
+void	BN_CTX_end(BN_CTX *ctx);
+int     BN_rand(BIGNUM *rnd, int bits, int top,int bottom);
+int     BN_pseudo_rand(BIGNUM *rnd, int bits, int top,int bottom);
+int	BN_rand_range(BIGNUM *rnd, BIGNUM *range);
+int	BN_pseudo_rand_range(BIGNUM *rnd, BIGNUM *range);
+int	BN_num_bits(const BIGNUM *a);
+int	BN_num_bits_word(BN_ULONG);
+BIGNUM *BN_new(void);
+void	BN_init(BIGNUM *);
+void	BN_clear_free(BIGNUM *a);
+BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b);
+void	BN_swap(BIGNUM *a, BIGNUM *b);
+BIGNUM *BN_bin2bn(const unsigned char *s,int len,BIGNUM *ret);
+int	BN_bn2bin(const BIGNUM *a, unsigned char *to);
+BIGNUM *BN_mpi2bn(const unsigned char *s,int len,BIGNUM *ret);
+int	BN_bn2mpi(const BIGNUM *a, unsigned char *to);
+int	BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
+int	BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
+int	BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
+int	BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
+int	BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
+int	BN_sqr(BIGNUM *r, const BIGNUM *a,BN_CTX *ctx);
+/** BN_set_negative sets sign of a BIGNUM
+ * \param  b  pointer to the BIGNUM object
+ * \param  n  0 if the BIGNUM b should be positive and a value != 0 otherwise 
+ */
+void	BN_set_negative(BIGNUM *b, int n);
+/** BN_is_negative returns 1 if the BIGNUM is negative
+ * \param  a  pointer to the BIGNUM object
+ * \return 1 if a < 0 and 0 otherwise
+ */
+#define BN_is_negative(a) ((a)->neg != 0)
+
+int	BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d,
+	BN_CTX *ctx);
+#define BN_mod(rem,m,d,ctx) BN_div(NULL,(rem),(m),(d),(ctx))
+int	BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx);
+int	BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx);
+int	BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m);
+int	BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx);
+int	BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m);
+int	BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+	const BIGNUM *m, BN_CTX *ctx);
+int	BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);
+int	BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);
+int	BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *m);
+int	BN_mod_lshift(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m, BN_CTX *ctx);
+int	BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m);
+
+BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w);
+BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w);
+int	BN_mul_word(BIGNUM *a, BN_ULONG w);
+int	BN_add_word(BIGNUM *a, BN_ULONG w);
+int	BN_sub_word(BIGNUM *a, BN_ULONG w);
+int	BN_set_word(BIGNUM *a, BN_ULONG w);
+BN_ULONG BN_get_word(const BIGNUM *a);
+
+int	BN_cmp(const BIGNUM *a, const BIGNUM *b);
+void	BN_free(BIGNUM *a);
+int	BN_is_bit_set(const BIGNUM *a, int n);
+int	BN_lshift(BIGNUM *r, const BIGNUM *a, int n);
+int	BN_lshift1(BIGNUM *r, const BIGNUM *a);
+int	BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,BN_CTX *ctx);
+
+int	BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+	const BIGNUM *m,BN_CTX *ctx);
+int	BN_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+	const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
+	const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont);
+int	BN_mod_exp_mont_word(BIGNUM *r, BN_ULONG a, const BIGNUM *p,
+	const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+int	BN_mod_exp2_mont(BIGNUM *r, const BIGNUM *a1, const BIGNUM *p1,
+	const BIGNUM *a2, const BIGNUM *p2,const BIGNUM *m,
+	BN_CTX *ctx,BN_MONT_CTX *m_ctx);
+int	BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+	const BIGNUM *m,BN_CTX *ctx);
+
+int	BN_mask_bits(BIGNUM *a,int n);
+#ifndef OPENSSL_NO_FP_API
+int	BN_print_fp(FILE *fp, const BIGNUM *a);
+#endif
+#ifdef HEADER_BIO_H
+int	BN_print(BIO *fp, const BIGNUM *a);
+#else
+int	BN_print(void *fp, const BIGNUM *a);
+#endif
+int	BN_reciprocal(BIGNUM *r, const BIGNUM *m, int len, BN_CTX *ctx);
+int	BN_rshift(BIGNUM *r, const BIGNUM *a, int n);
+int	BN_rshift1(BIGNUM *r, const BIGNUM *a);
+void	BN_clear(BIGNUM *a);
+BIGNUM *BN_dup(const BIGNUM *a);
+int	BN_ucmp(const BIGNUM *a, const BIGNUM *b);
+int	BN_set_bit(BIGNUM *a, int n);
+int	BN_clear_bit(BIGNUM *a, int n);
+char *	BN_bn2hex(const BIGNUM *a);
+char *	BN_bn2dec(const BIGNUM *a);
+int 	BN_hex2bn(BIGNUM **a, const char *str);
+int 	BN_dec2bn(BIGNUM **a, const char *str);
+int	BN_gcd(BIGNUM *r,const BIGNUM *a,const BIGNUM *b,BN_CTX *ctx);
+int	BN_kronecker(const BIGNUM *a,const BIGNUM *b,BN_CTX *ctx); /* returns -2 for error */
+BIGNUM *BN_mod_inverse(BIGNUM *ret,
+	const BIGNUM *a, const BIGNUM *n,BN_CTX *ctx);
+BIGNUM *BN_mod_sqrt(BIGNUM *ret,
+	const BIGNUM *a, const BIGNUM *n,BN_CTX *ctx);
+
+/* Deprecated versions */
+#ifndef OPENSSL_NO_DEPRECATED
+BIGNUM *BN_generate_prime(BIGNUM *ret,int bits,int safe,
+	const BIGNUM *add, const BIGNUM *rem,
+	void (*callback)(int,int,void *),void *cb_arg);
+int	BN_is_prime(const BIGNUM *p,int nchecks,
+	void (*callback)(int,int,void *),
+	BN_CTX *ctx,void *cb_arg);
+int	BN_is_prime_fasttest(const BIGNUM *p,int nchecks,
+	void (*callback)(int,int,void *),BN_CTX *ctx,void *cb_arg,
+	int do_trial_division);
+#endif /* !defined(OPENSSL_NO_DEPRECATED) */
+
+/* Newer versions */
+int	BN_generate_prime_ex(BIGNUM *ret,int bits,int safe, const BIGNUM *add,
+		const BIGNUM *rem, BN_GENCB *cb);
+int	BN_is_prime_ex(const BIGNUM *p,int nchecks, BN_CTX *ctx, BN_GENCB *cb);
+int	BN_is_prime_fasttest_ex(const BIGNUM *p,int nchecks, BN_CTX *ctx,
+		int do_trial_division, BN_GENCB *cb);
+
+BN_MONT_CTX *BN_MONT_CTX_new(void );
+void BN_MONT_CTX_init(BN_MONT_CTX *ctx);
+int BN_mod_mul_montgomery(BIGNUM *r,const BIGNUM *a,const BIGNUM *b,
+	BN_MONT_CTX *mont, BN_CTX *ctx);
+#define BN_to_montgomery(r,a,mont,ctx)	BN_mod_mul_montgomery(\
+	(r),(a),&((mont)->RR),(mont),(ctx))
+int BN_from_montgomery(BIGNUM *r,const BIGNUM *a,
+	BN_MONT_CTX *mont, BN_CTX *ctx);
+void BN_MONT_CTX_free(BN_MONT_CTX *mont);
+int BN_MONT_CTX_set(BN_MONT_CTX *mont,const BIGNUM *mod,BN_CTX *ctx);
+BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to,BN_MONT_CTX *from);
+BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, int lock,
+					const BIGNUM *mod, BN_CTX *ctx);
+
+/* BN_BLINDING flags */
+#define	BN_BLINDING_NO_UPDATE	0x00000001
+#define	BN_BLINDING_NO_RECREATE	0x00000002
+
+BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod);
+void BN_BLINDING_free(BN_BLINDING *b);
+int BN_BLINDING_update(BN_BLINDING *b,BN_CTX *ctx);
+int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx);
+int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx);
+int BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *);
+int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b, BN_CTX *);
+unsigned long BN_BLINDING_get_thread_id(const BN_BLINDING *);
+void BN_BLINDING_set_thread_id(BN_BLINDING *, unsigned long);
+unsigned long BN_BLINDING_get_flags(const BN_BLINDING *);
+void BN_BLINDING_set_flags(BN_BLINDING *, unsigned long);
+BN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b,
+	const BIGNUM *e, BIGNUM *m, BN_CTX *ctx,
+	int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+			  const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx),
+	BN_MONT_CTX *m_ctx);
+
+#ifndef OPENSSL_NO_DEPRECATED
+void BN_set_params(int mul,int high,int low,int mont);
+int BN_get_params(int which); /* 0, mul, 1 high, 2 low, 3 mont */
+#endif
+
+void	BN_RECP_CTX_init(BN_RECP_CTX *recp);
+BN_RECP_CTX *BN_RECP_CTX_new(void);
+void	BN_RECP_CTX_free(BN_RECP_CTX *recp);
+int	BN_RECP_CTX_set(BN_RECP_CTX *recp,const BIGNUM *rdiv,BN_CTX *ctx);
+int	BN_mod_mul_reciprocal(BIGNUM *r, const BIGNUM *x, const BIGNUM *y,
+	BN_RECP_CTX *recp,BN_CTX *ctx);
+int	BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+	const BIGNUM *m, BN_CTX *ctx);
+int	BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m,
+	BN_RECP_CTX *recp, BN_CTX *ctx);
+
+/* Functions for arithmetic over binary polynomials represented by BIGNUMs. 
+ *
+ * The BIGNUM::neg property of BIGNUMs representing binary polynomials is
+ * ignored.
+ *
+ * Note that input arguments are not const so that their bit arrays can
+ * be expanded to the appropriate size if needed.
+ */
+
+int	BN_GF2m_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); /*r = a + b*/
+#define BN_GF2m_sub(r, a, b) BN_GF2m_add(r, a, b)
+int	BN_GF2m_mod(BIGNUM *r, const BIGNUM *a, const BIGNUM *p); /*r=a mod p*/
+int	BN_GF2m_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+	const BIGNUM *p, BN_CTX *ctx); /* r = (a * b) mod p */
+int	BN_GF2m_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+	BN_CTX *ctx); /* r = (a * a) mod p */
+int	BN_GF2m_mod_inv(BIGNUM *r, const BIGNUM *b, const BIGNUM *p,
+	BN_CTX *ctx); /* r = (1 / b) mod p */
+int	BN_GF2m_mod_div(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+	const BIGNUM *p, BN_CTX *ctx); /* r = (a / b) mod p */
+int	BN_GF2m_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+	const BIGNUM *p, BN_CTX *ctx); /* r = (a ^ b) mod p */
+int	BN_GF2m_mod_sqrt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+	BN_CTX *ctx); /* r = sqrt(a) mod p */
+int	BN_GF2m_mod_solve_quad(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+	BN_CTX *ctx); /* r^2 + r = a mod p */
+#define BN_GF2m_cmp(a, b) BN_ucmp((a), (b))
+/* Some functions allow for representation of the irreducible polynomials
+ * as an unsigned int[], say p.  The irreducible f(t) is then of the form:
+ *     t^p[0] + t^p[1] + ... + t^p[k]
+ * where m = p[0] > p[1] > ... > p[k] = 0.
+ */
+int	BN_GF2m_mod_arr(BIGNUM *r, const BIGNUM *a, const unsigned int p[]);
+	/* r = a mod p */
+int	BN_GF2m_mod_mul_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+	const unsigned int p[], BN_CTX *ctx); /* r = (a * b) mod p */
+int	BN_GF2m_mod_sqr_arr(BIGNUM *r, const BIGNUM *a, const unsigned int p[],
+	BN_CTX *ctx); /* r = (a * a) mod p */
+int	BN_GF2m_mod_inv_arr(BIGNUM *r, const BIGNUM *b, const unsigned int p[],
+	BN_CTX *ctx); /* r = (1 / b) mod p */
+int	BN_GF2m_mod_div_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+	const unsigned int p[], BN_CTX *ctx); /* r = (a / b) mod p */
+int	BN_GF2m_mod_exp_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+	const unsigned int p[], BN_CTX *ctx); /* r = (a ^ b) mod p */
+int	BN_GF2m_mod_sqrt_arr(BIGNUM *r, const BIGNUM *a,
+	const unsigned int p[], BN_CTX *ctx); /* r = sqrt(a) mod p */
+int	BN_GF2m_mod_solve_quad_arr(BIGNUM *r, const BIGNUM *a,
+	const unsigned int p[], BN_CTX *ctx); /* r^2 + r = a mod p */
+int	BN_GF2m_poly2arr(const BIGNUM *a, unsigned int p[], int max);
+int	BN_GF2m_arr2poly(const unsigned int p[], BIGNUM *a);
+
+/* faster mod functions for the 'NIST primes' 
+ * 0 <= a < p^2 */
+int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
+int BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
+int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
+int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
+int BN_nist_mod_521(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
+
+const BIGNUM *BN_get0_nist_prime_192(void);
+const BIGNUM *BN_get0_nist_prime_224(void);
+const BIGNUM *BN_get0_nist_prime_256(void);
+const BIGNUM *BN_get0_nist_prime_384(void);
+const BIGNUM *BN_get0_nist_prime_521(void);
+
+/* library internal functions */
+
+#define bn_expand(a,bits) ((((((bits+BN_BITS2-1))/BN_BITS2)) <= (a)->dmax)?\
+	(a):bn_expand2((a),(bits+BN_BITS2-1)/BN_BITS2))
+#define bn_wexpand(a,words) (((words) <= (a)->dmax)?(a):bn_expand2((a),(words)))
+BIGNUM *bn_expand2(BIGNUM *a, int words);
+#ifndef OPENSSL_NO_DEPRECATED
+BIGNUM *bn_dup_expand(const BIGNUM *a, int words); /* unused */
+#endif
+
+/* Bignum consistency macros
+ * There is one "API" macro, bn_fix_top(), for stripping leading zeroes from
+ * bignum data after direct manipulations on the data. There is also an
+ * "internal" macro, bn_check_top(), for verifying that there are no leading
+ * zeroes. Unfortunately, some auditing is required due to the fact that
+ * bn_fix_top() has become an overabused duct-tape because bignum data is
+ * occasionally passed around in an inconsistent state. So the following
+ * changes have been made to sort this out;
+ * - bn_fix_top()s implementation has been moved to bn_correct_top()
+ * - if BN_DEBUG isn't defined, bn_fix_top() maps to bn_correct_top(), and
+ *   bn_check_top() is as before.
+ * - if BN_DEBUG *is* defined;
+ *   - bn_check_top() tries to pollute unused words even if the bignum 'top' is
+ *     consistent. (ed: only if BN_DEBUG_RAND is defined)
+ *   - bn_fix_top() maps to bn_check_top() rather than "fixing" anything.
+ * The idea is to have debug builds flag up inconsistent bignums when they
+ * occur. If that occurs in a bn_fix_top(), we examine the code in question; if
+ * the use of bn_fix_top() was appropriate (ie. it follows directly after code
+ * that manipulates the bignum) it is converted to bn_correct_top(), and if it
+ * was not appropriate, we convert it permanently to bn_check_top() and track
+ * down the cause of the bug. Eventually, no internal code should be using the
+ * bn_fix_top() macro. External applications and libraries should try this with
+ * their own code too, both in terms of building against the openssl headers
+ * with BN_DEBUG defined *and* linking with a version of OpenSSL built with it
+ * defined. This not only improves external code, it provides more test
+ * coverage for openssl's own code.
+ */
+
+#ifdef BN_DEBUG
+
+/* We only need assert() when debugging */
+#include 
+
+#ifdef BN_DEBUG_RAND
+/* To avoid "make update" cvs wars due to BN_DEBUG, use some tricks */
+#ifndef RAND_pseudo_bytes
+int RAND_pseudo_bytes(unsigned char *buf,int num);
+#define BN_DEBUG_TRIX
+#endif
+#define bn_pollute(a) \
+	do { \
+		const BIGNUM *_bnum1 = (a); \
+		if(_bnum1->top < _bnum1->dmax) { \
+			unsigned char _tmp_char; \
+			/* We cast away const without the compiler knowing, any \
+			 * *genuinely* constant variables that aren't mutable \
+			 * wouldn't be constructed with top!=dmax. */ \
+			BN_ULONG *_not_const; \
+			memcpy(&_not_const, &_bnum1->d, sizeof(BN_ULONG*)); \
+			RAND_pseudo_bytes(&_tmp_char, 1); \
+			memset((unsigned char *)(_not_const + _bnum1->top), _tmp_char, \
+				(_bnum1->dmax - _bnum1->top) * sizeof(BN_ULONG)); \
+		} \
+	} while(0)
+#ifdef BN_DEBUG_TRIX
+#undef RAND_pseudo_bytes
+#endif
+#else
+#define bn_pollute(a)
+#endif
+#define bn_check_top(a) \
+	do { \
+		const BIGNUM *_bnum2 = (a); \
+		if (_bnum2 != NULL) { \
+			assert((_bnum2->top == 0) || \
+				(_bnum2->d[_bnum2->top - 1] != 0)); \
+			bn_pollute(_bnum2); \
+		} \
+	} while(0)
+
+#define bn_fix_top(a)		bn_check_top(a)
+
+#else /* !BN_DEBUG */
+
+#define bn_pollute(a)
+#define bn_check_top(a)
+#define bn_fix_top(a)		bn_correct_top(a)
+
+#endif
+
+#define bn_correct_top(a) \
+        { \
+        BN_ULONG *ftl; \
+	if ((a)->top > 0) \
+		{ \
+		for (ftl= &((a)->d[(a)->top-1]); (a)->top > 0; (a)->top--) \
+		if (*(ftl--)) break; \
+		} \
+	bn_pollute(a); \
+	}
+
+BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
+BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
+void     bn_sqr_words(BN_ULONG *rp, const BN_ULONG *ap, int num);
+BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d);
+BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int num);
+BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int num);
+
+/* Primes from RFC 2409 */
+BIGNUM *get_rfc2409_prime_768(BIGNUM *bn);
+BIGNUM *get_rfc2409_prime_1024(BIGNUM *bn);
+
+/* Primes from RFC 3526 */
+BIGNUM *get_rfc3526_prime_1536(BIGNUM *bn);
+BIGNUM *get_rfc3526_prime_2048(BIGNUM *bn);
+BIGNUM *get_rfc3526_prime_3072(BIGNUM *bn);
+BIGNUM *get_rfc3526_prime_4096(BIGNUM *bn);
+BIGNUM *get_rfc3526_prime_6144(BIGNUM *bn);
+BIGNUM *get_rfc3526_prime_8192(BIGNUM *bn);
+
+int BN_bntest_rand(BIGNUM *rnd, int bits, int top,int bottom);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_BN_strings(void);
+
+/* Error codes for the BN functions. */
+
+/* Function codes. */
+#define BN_F_BNRAND					 127
+#define BN_F_BN_BLINDING_CONVERT_EX			 100
+#define BN_F_BN_BLINDING_CREATE_PARAM			 128
+#define BN_F_BN_BLINDING_INVERT_EX			 101
+#define BN_F_BN_BLINDING_NEW				 102
+#define BN_F_BN_BLINDING_UPDATE				 103
+#define BN_F_BN_BN2DEC					 104
+#define BN_F_BN_BN2HEX					 105
+#define BN_F_BN_CTX_GET					 116
+#define BN_F_BN_CTX_NEW					 106
+#define BN_F_BN_CTX_START				 129
+#define BN_F_BN_DIV					 107
+#define BN_F_BN_DIV_RECP				 130
+#define BN_F_BN_EXP					 123
+#define BN_F_BN_EXPAND2					 108
+#define BN_F_BN_EXPAND_INTERNAL				 120
+#define BN_F_BN_GF2M_MOD				 131
+#define BN_F_BN_GF2M_MOD_EXP				 132
+#define BN_F_BN_GF2M_MOD_MUL				 133
+#define BN_F_BN_GF2M_MOD_SOLVE_QUAD			 134
+#define BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR			 135
+#define BN_F_BN_GF2M_MOD_SQR				 136
+#define BN_F_BN_GF2M_MOD_SQRT				 137
+#define BN_F_BN_MOD_EXP2_MONT				 118
+#define BN_F_BN_MOD_EXP_MONT				 109
+#define BN_F_BN_MOD_EXP_MONT_CONSTTIME			 124
+#define BN_F_BN_MOD_EXP_MONT_WORD			 117
+#define BN_F_BN_MOD_EXP_RECP				 125
+#define BN_F_BN_MOD_EXP_SIMPLE				 126
+#define BN_F_BN_MOD_INVERSE				 110
+#define BN_F_BN_MOD_LSHIFT_QUICK			 119
+#define BN_F_BN_MOD_MUL_RECIPROCAL			 111
+#define BN_F_BN_MOD_SQRT				 121
+#define BN_F_BN_MPI2BN					 112
+#define BN_F_BN_NEW					 113
+#define BN_F_BN_RAND					 114
+#define BN_F_BN_RAND_RANGE				 122
+#define BN_F_BN_USUB					 115
+
+/* Reason codes. */
+#define BN_R_ARG2_LT_ARG3				 100
+#define BN_R_BAD_RECIPROCAL				 101
+#define BN_R_BIGNUM_TOO_LONG				 114
+#define BN_R_CALLED_WITH_EVEN_MODULUS			 102
+#define BN_R_DIV_BY_ZERO				 103
+#define BN_R_ENCODING_ERROR				 104
+#define BN_R_EXPAND_ON_STATIC_BIGNUM_DATA		 105
+#define BN_R_INPUT_NOT_REDUCED				 110
+#define BN_R_INVALID_LENGTH				 106
+#define BN_R_INVALID_RANGE				 115
+#define BN_R_NOT_A_SQUARE				 111
+#define BN_R_NOT_INITIALIZED				 107
+#define BN_R_NO_INVERSE					 108
+#define BN_R_NO_SOLUTION				 116
+#define BN_R_P_IS_NOT_PRIME				 112
+#define BN_R_TOO_MANY_ITERATIONS			 113
+#define BN_R_TOO_MANY_TEMPORARY_VARIABLES		 109
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/dep/include/openssl/buffer.h b/dep/include/openssl/buffer.h
new file mode 100644
index 00000000000..1db96074503
--- /dev/null
+++ b/dep/include/openssl/buffer.h
@@ -0,0 +1,118 @@
+/* crypto/buffer/buffer.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_BUFFER_H
+#define HEADER_BUFFER_H
+
+#include 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#include 
+
+#if !defined(NO_SYS_TYPES_H)
+#include 
+#endif
+
+/* Already declared in ossl_typ.h */
+/* typedef struct buf_mem_st BUF_MEM; */
+
+struct buf_mem_st
+	{
+	int length;	/* current number of bytes */
+	char *data;
+	int max;	/* size of buffer */
+	};
+
+BUF_MEM *BUF_MEM_new(void);
+void	BUF_MEM_free(BUF_MEM *a);
+int	BUF_MEM_grow(BUF_MEM *str, int len);
+int	BUF_MEM_grow_clean(BUF_MEM *str, int len);
+char *	BUF_strdup(const char *str);
+char *	BUF_strndup(const char *str, size_t siz);
+void *	BUF_memdup(const void *data, size_t siz);
+
+/* safe string functions */
+size_t BUF_strlcpy(char *dst,const char *src,size_t siz);
+size_t BUF_strlcat(char *dst,const char *src,size_t siz);
+
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_BUF_strings(void);
+
+/* Error codes for the BUF functions. */
+
+/* Function codes. */
+#define BUF_F_BUF_MEMDUP				 103
+#define BUF_F_BUF_MEM_GROW				 100
+#define BUF_F_BUF_MEM_GROW_CLEAN			 105
+#define BUF_F_BUF_MEM_NEW				 101
+#define BUF_F_BUF_STRDUP				 102
+#define BUF_F_BUF_STRNDUP				 104
+
+/* Reason codes. */
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/dep/include/openssl/cast.h b/dep/include/openssl/cast.h
new file mode 100644
index 00000000000..90b45b950aa
--- /dev/null
+++ b/dep/include/openssl/cast.h
@@ -0,0 +1,105 @@
+/* crypto/cast/cast.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_CAST_H
+#define HEADER_CAST_H
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#include 
+
+#ifdef OPENSSL_NO_CAST
+#error CAST is disabled.
+#endif
+
+#define CAST_ENCRYPT	1
+#define CAST_DECRYPT	0
+
+#define CAST_LONG unsigned long
+
+#define CAST_BLOCK	8
+#define CAST_KEY_LENGTH	16
+
+typedef struct cast_key_st
+	{
+	CAST_LONG data[32];
+	int short_key;	/* Use reduced rounds for short key */
+	} CAST_KEY;
+
+ 
+void CAST_set_key(CAST_KEY *key, int len, const unsigned char *data);
+void CAST_ecb_encrypt(const unsigned char *in,unsigned char *out,CAST_KEY *key,
+		      int enc);
+void CAST_encrypt(CAST_LONG *data,CAST_KEY *key);
+void CAST_decrypt(CAST_LONG *data,CAST_KEY *key);
+void CAST_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,
+		      CAST_KEY *ks, unsigned char *iv, int enc);
+void CAST_cfb64_encrypt(const unsigned char *in, unsigned char *out,
+			long length, CAST_KEY *schedule, unsigned char *ivec,
+			int *num, int enc);
+void CAST_ofb64_encrypt(const unsigned char *in, unsigned char *out, 
+			long length, CAST_KEY *schedule, unsigned char *ivec,
+			int *num);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff --git a/dep/include/openssl/comp.h b/dep/include/openssl/comp.h
new file mode 100644
index 00000000000..5d59354a571
--- /dev/null
+++ b/dep/include/openssl/comp.h
@@ -0,0 +1,66 @@
+
+#ifndef HEADER_COMP_H
+#define HEADER_COMP_H
+
+#include 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+typedef struct comp_ctx_st COMP_CTX;
+
+typedef struct comp_method_st
+	{
+	int type;		/* NID for compression library */
+	const char *name;	/* A text string to identify the library */
+	int (*init)(COMP_CTX *ctx);
+	void (*finish)(COMP_CTX *ctx);
+	int (*compress)(COMP_CTX *ctx,
+			unsigned char *out, unsigned int olen,
+			unsigned char *in, unsigned int ilen);
+	int (*expand)(COMP_CTX *ctx,
+		      unsigned char *out, unsigned int olen,
+		      unsigned char *in, unsigned int ilen);
+	/* The following two do NOTHING, but are kept for backward compatibility */
+	long (*ctrl)(void);
+	long (*callback_ctrl)(void);
+	} COMP_METHOD;
+
+struct comp_ctx_st
+	{
+	COMP_METHOD *meth;
+	unsigned long compress_in;
+	unsigned long compress_out;
+	unsigned long expand_in;
+	unsigned long expand_out;
+
+	CRYPTO_EX_DATA	ex_data;
+	};
+
+
+COMP_CTX *COMP_CTX_new(COMP_METHOD *meth);
+void COMP_CTX_free(COMP_CTX *ctx);
+int COMP_compress_block(COMP_CTX *ctx, unsigned char *out, int olen,
+	unsigned char *in, int ilen);
+int COMP_expand_block(COMP_CTX *ctx, unsigned char *out, int olen,
+	unsigned char *in, int ilen);
+COMP_METHOD *COMP_rle(void );
+COMP_METHOD *COMP_zlib(void );
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_COMP_strings(void);
+
+/* Error codes for the COMP functions. */
+
+/* Function codes. */
+
+/* Reason codes. */
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/dep/include/openssl/conf.h b/dep/include/openssl/conf.h
new file mode 100644
index 00000000000..4c073dd8317
--- /dev/null
+++ b/dep/include/openssl/conf.h
@@ -0,0 +1,253 @@
+/* crypto/conf/conf.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef  HEADER_CONF_H
+#define HEADER_CONF_H
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+typedef struct
+	{
+	char *section;
+	char *name;
+	char *value;
+	} CONF_VALUE;
+
+DECLARE_STACK_OF(CONF_VALUE)
+DECLARE_STACK_OF(CONF_MODULE)
+DECLARE_STACK_OF(CONF_IMODULE)
+
+struct conf_st;
+struct conf_method_st;
+typedef struct conf_method_st CONF_METHOD;
+
+struct conf_method_st
+	{
+	const char *name;
+	CONF *(*create)(CONF_METHOD *meth);
+	int (*init)(CONF *conf);
+	int (*destroy)(CONF *conf);
+	int (*destroy_data)(CONF *conf);
+	int (*load_bio)(CONF *conf, BIO *bp, long *eline);
+	int (*dump)(const CONF *conf, BIO *bp);
+	int (*is_number)(const CONF *conf, char c);
+	int (*to_int)(const CONF *conf, char c);
+	int (*load)(CONF *conf, const char *name, long *eline);
+	};
+
+/* Module definitions */
+
+typedef struct conf_imodule_st CONF_IMODULE;
+typedef struct conf_module_st CONF_MODULE;
+
+/* DSO module function typedefs */
+typedef int conf_init_func(CONF_IMODULE *md, const CONF *cnf);
+typedef void conf_finish_func(CONF_IMODULE *md);
+
+#define	CONF_MFLAGS_IGNORE_ERRORS	0x1
+#define CONF_MFLAGS_IGNORE_RETURN_CODES	0x2
+#define CONF_MFLAGS_SILENT		0x4
+#define CONF_MFLAGS_NO_DSO		0x8
+#define CONF_MFLAGS_IGNORE_MISSING_FILE	0x10
+
+int CONF_set_default_method(CONF_METHOD *meth);
+void CONF_set_nconf(CONF *conf,LHASH *hash);
+LHASH *CONF_load(LHASH *conf,const char *file,long *eline);
+#ifndef OPENSSL_NO_FP_API
+LHASH *CONF_load_fp(LHASH *conf, FILE *fp,long *eline);
+#endif
+LHASH *CONF_load_bio(LHASH *conf, BIO *bp,long *eline);
+STACK_OF(CONF_VALUE) *CONF_get_section(LHASH *conf,const char *section);
+char *CONF_get_string(LHASH *conf,const char *group,const char *name);
+long CONF_get_number(LHASH *conf,const char *group,const char *name);
+void CONF_free(LHASH *conf);
+int CONF_dump_fp(LHASH *conf, FILE *out);
+int CONF_dump_bio(LHASH *conf, BIO *out);
+
+void OPENSSL_config(const char *config_name);
+void OPENSSL_no_config(void);
+
+/* New conf code.  The semantics are different from the functions above.
+   If that wasn't the case, the above functions would have been replaced */
+
+struct conf_st
+	{
+	CONF_METHOD *meth;
+	void *meth_data;
+	LHASH *data;
+	};
+
+CONF *NCONF_new(CONF_METHOD *meth);
+CONF_METHOD *NCONF_default(void);
+CONF_METHOD *NCONF_WIN32(void);
+#if 0 /* Just to give you an idea of what I have in mind */
+CONF_METHOD *NCONF_XML(void);
+#endif
+void NCONF_free(CONF *conf);
+void NCONF_free_data(CONF *conf);
+
+int NCONF_load(CONF *conf,const char *file,long *eline);
+#ifndef OPENSSL_NO_FP_API
+int NCONF_load_fp(CONF *conf, FILE *fp,long *eline);
+#endif
+int NCONF_load_bio(CONF *conf, BIO *bp,long *eline);
+STACK_OF(CONF_VALUE) *NCONF_get_section(const CONF *conf,const char *section);
+char *NCONF_get_string(const CONF *conf,const char *group,const char *name);
+int NCONF_get_number_e(const CONF *conf,const char *group,const char *name,
+		       long *result);
+int NCONF_dump_fp(const CONF *conf, FILE *out);
+int NCONF_dump_bio(const CONF *conf, BIO *out);
+
+#if 0 /* The following function has no error checking,
+	 and should therefore be avoided */
+long NCONF_get_number(CONF *conf,char *group,char *name);
+#else
+#define NCONF_get_number(c,g,n,r) NCONF_get_number_e(c,g,n,r)
+#endif
+  
+/* Module functions */
+
+int CONF_modules_load(const CONF *cnf, const char *appname,
+		      unsigned long flags);
+int CONF_modules_load_file(const char *filename, const char *appname,
+			   unsigned long flags);
+void CONF_modules_unload(int all);
+void CONF_modules_finish(void);
+void CONF_modules_free(void);
+int CONF_module_add(const char *name, conf_init_func *ifunc,
+		    conf_finish_func *ffunc);
+
+const char *CONF_imodule_get_name(const CONF_IMODULE *md);
+const char *CONF_imodule_get_value(const CONF_IMODULE *md);
+void *CONF_imodule_get_usr_data(const CONF_IMODULE *md);
+void CONF_imodule_set_usr_data(CONF_IMODULE *md, void *usr_data);
+CONF_MODULE *CONF_imodule_get_module(const CONF_IMODULE *md);
+unsigned long CONF_imodule_get_flags(const CONF_IMODULE *md);
+void CONF_imodule_set_flags(CONF_IMODULE *md, unsigned long flags);
+void *CONF_module_get_usr_data(CONF_MODULE *pmod);
+void CONF_module_set_usr_data(CONF_MODULE *pmod, void *usr_data);
+
+char *CONF_get1_default_config_file(void);
+
+int CONF_parse_list(const char *list, int sep, int nospc,
+	int (*list_cb)(const char *elem, int len, void *usr), void *arg);
+
+void OPENSSL_load_builtin_modules(void);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_CONF_strings(void);
+
+/* Error codes for the CONF functions. */
+
+/* Function codes. */
+#define CONF_F_CONF_DUMP_FP				 104
+#define CONF_F_CONF_LOAD				 100
+#define CONF_F_CONF_LOAD_BIO				 102
+#define CONF_F_CONF_LOAD_FP				 103
+#define CONF_F_CONF_MODULES_LOAD			 116
+#define CONF_F_DEF_LOAD					 120
+#define CONF_F_DEF_LOAD_BIO				 121
+#define CONF_F_MODULE_INIT				 115
+#define CONF_F_MODULE_LOAD_DSO				 117
+#define CONF_F_MODULE_RUN				 118
+#define CONF_F_NCONF_DUMP_BIO				 105
+#define CONF_F_NCONF_DUMP_FP				 106
+#define CONF_F_NCONF_GET_NUMBER				 107
+#define CONF_F_NCONF_GET_NUMBER_E			 112
+#define CONF_F_NCONF_GET_SECTION			 108
+#define CONF_F_NCONF_GET_STRING				 109
+#define CONF_F_NCONF_LOAD				 113
+#define CONF_F_NCONF_LOAD_BIO				 110
+#define CONF_F_NCONF_LOAD_FP				 114
+#define CONF_F_NCONF_NEW				 111
+#define CONF_F_STR_COPY					 101
+
+/* Reason codes. */
+#define CONF_R_ERROR_LOADING_DSO			 110
+#define CONF_R_MISSING_CLOSE_SQUARE_BRACKET		 100
+#define CONF_R_MISSING_EQUAL_SIGN			 101
+#define CONF_R_MISSING_FINISH_FUNCTION			 111
+#define CONF_R_MISSING_INIT_FUNCTION			 112
+#define CONF_R_MODULE_INITIALIZATION_ERROR		 109
+#define CONF_R_NO_CLOSE_BRACE				 102
+#define CONF_R_NO_CONF					 105
+#define CONF_R_NO_CONF_OR_ENVIRONMENT_VARIABLE		 106
+#define CONF_R_NO_SECTION				 107
+#define CONF_R_NO_SUCH_FILE				 114
+#define CONF_R_NO_VALUE					 108
+#define CONF_R_UNABLE_TO_CREATE_NEW_SECTION		 103
+#define CONF_R_UNKNOWN_MODULE_NAME			 113
+#define CONF_R_VARIABLE_HAS_NO_VALUE			 104
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/dep/include/openssl/conf_api.h b/dep/include/openssl/conf_api.h
new file mode 100644
index 00000000000..87a954aff63
--- /dev/null
+++ b/dep/include/openssl/conf_api.h
@@ -0,0 +1,89 @@
+/* conf_api.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef  HEADER_CONF_API_H
+#define HEADER_CONF_API_H
+
+#include 
+#include 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* Up until OpenSSL 0.9.5a, this was new_section */
+CONF_VALUE *_CONF_new_section(CONF *conf, const char *section);
+/* Up until OpenSSL 0.9.5a, this was get_section */
+CONF_VALUE *_CONF_get_section(const CONF *conf, const char *section);
+/* Up until OpenSSL 0.9.5a, this was CONF_get_section */
+STACK_OF(CONF_VALUE) *_CONF_get_section_values(const CONF *conf,
+					       const char *section);
+
+int _CONF_add_string(CONF *conf, CONF_VALUE *section, CONF_VALUE *value);
+char *_CONF_get_string(const CONF *conf, const char *section,
+		       const char *name);
+long _CONF_get_number(const CONF *conf, const char *section, const char *name);
+
+int _CONF_new_data(CONF *conf);
+void _CONF_free_data(CONF *conf);
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
+
diff --git a/dep/include/openssl/crypto.h b/dep/include/openssl/crypto.h
new file mode 100644
index 00000000000..d2b5ffe3325
--- /dev/null
+++ b/dep/include/openssl/crypto.h
@@ -0,0 +1,550 @@
+/* crypto/crypto.h */
+/* ====================================================================
+ * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECDH support in OpenSSL originally developed by 
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#ifndef HEADER_CRYPTO_H
+#define HEADER_CRYPTO_H
+
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_FP_API
+#include 
+#endif
+
+#include 
+#include 
+#include 
+#include 
+
+#ifdef CHARSET_EBCDIC
+#include 
+#endif
+
+/* Resolve problems on some operating systems with symbol names that clash
+   one way or another */
+#include 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* Backward compatibility to SSLeay */
+/* This is more to be used to check the correct DLL is being used
+ * in the MS world. */
+#define SSLEAY_VERSION_NUMBER	OPENSSL_VERSION_NUMBER
+#define SSLEAY_VERSION		0
+/* #define SSLEAY_OPTIONS	1 no longer supported */
+#define SSLEAY_CFLAGS		2
+#define SSLEAY_BUILT_ON		3
+#define SSLEAY_PLATFORM		4
+#define SSLEAY_DIR		5
+
+/* Already declared in ossl_typ.h */
+#if 0
+typedef struct crypto_ex_data_st CRYPTO_EX_DATA;
+/* Called when a new object is created */
+typedef int CRYPTO_EX_new(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
+					int idx, long argl, void *argp);
+/* Called when an object is free()ed */
+typedef void CRYPTO_EX_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
+					int idx, long argl, void *argp);
+/* Called when we need to dup an object */
+typedef int CRYPTO_EX_dup(CRYPTO_EX_DATA *to, CRYPTO_EX_DATA *from, void *from_d, 
+					int idx, long argl, void *argp);
+#endif
+
+/* A generic structure to pass assorted data in a expandable way */
+typedef struct openssl_item_st
+	{
+	int code;
+	void *value;		/* Not used for flag attributes */
+	size_t value_size;	/* Max size of value for output, length for input */
+	size_t *value_length;	/* Returned length of value for output */
+	} OPENSSL_ITEM;
+
+
+/* When changing the CRYPTO_LOCK_* list, be sure to maintin the text lock
+ * names in cryptlib.c
+ */
+
+#define	CRYPTO_LOCK_ERR			1
+#define	CRYPTO_LOCK_EX_DATA		2
+#define	CRYPTO_LOCK_X509		3
+#define	CRYPTO_LOCK_X509_INFO		4
+#define	CRYPTO_LOCK_X509_PKEY		5
+#define CRYPTO_LOCK_X509_CRL		6
+#define CRYPTO_LOCK_X509_REQ		7
+#define CRYPTO_LOCK_DSA			8
+#define CRYPTO_LOCK_RSA			9
+#define CRYPTO_LOCK_EVP_PKEY		10
+#define CRYPTO_LOCK_X509_STORE		11
+#define CRYPTO_LOCK_SSL_CTX		12
+#define CRYPTO_LOCK_SSL_CERT		13
+#define CRYPTO_LOCK_SSL_SESSION		14
+#define CRYPTO_LOCK_SSL_SESS_CERT	15
+#define CRYPTO_LOCK_SSL			16
+#define CRYPTO_LOCK_SSL_METHOD		17
+#define CRYPTO_LOCK_RAND		18
+#define CRYPTO_LOCK_RAND2		19
+#define CRYPTO_LOCK_MALLOC		20
+#define CRYPTO_LOCK_BIO			21
+#define CRYPTO_LOCK_GETHOSTBYNAME	22
+#define CRYPTO_LOCK_GETSERVBYNAME	23
+#define CRYPTO_LOCK_READDIR		24
+#define CRYPTO_LOCK_RSA_BLINDING	25
+#define CRYPTO_LOCK_DH			26
+#define CRYPTO_LOCK_MALLOC2		27
+#define CRYPTO_LOCK_DSO			28
+#define CRYPTO_LOCK_DYNLOCK		29
+#define CRYPTO_LOCK_ENGINE		30
+#define CRYPTO_LOCK_UI			31
+#define CRYPTO_LOCK_ECDSA               32
+#define CRYPTO_LOCK_EC			33
+#define CRYPTO_LOCK_ECDH		34
+#define CRYPTO_LOCK_BN  		35
+#define CRYPTO_LOCK_EC_PRE_COMP		36
+#define CRYPTO_LOCK_STORE		37
+#define CRYPTO_LOCK_COMP		38
+#define CRYPTO_NUM_LOCKS		39
+
+#define CRYPTO_LOCK		1
+#define CRYPTO_UNLOCK		2
+#define CRYPTO_READ		4
+#define CRYPTO_WRITE		8
+
+#ifndef OPENSSL_NO_LOCKING
+#ifndef CRYPTO_w_lock
+#define CRYPTO_w_lock(type)	\
+	CRYPTO_lock(CRYPTO_LOCK|CRYPTO_WRITE,type,__FILE__,__LINE__)
+#define CRYPTO_w_unlock(type)	\
+	CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_WRITE,type,__FILE__,__LINE__)
+#define CRYPTO_r_lock(type)	\
+	CRYPTO_lock(CRYPTO_LOCK|CRYPTO_READ,type,__FILE__,__LINE__)
+#define CRYPTO_r_unlock(type)	\
+	CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_READ,type,__FILE__,__LINE__)
+#define CRYPTO_add(addr,amount,type)	\
+	CRYPTO_add_lock(addr,amount,type,__FILE__,__LINE__)
+#endif
+#else
+#define CRYPTO_w_lock(a)
+#define CRYPTO_w_unlock(a)
+#define CRYPTO_r_lock(a)
+#define CRYPTO_r_unlock(a)
+#define CRYPTO_add(a,b,c)	((*(a))+=(b))
+#endif
+
+/* Some applications as well as some parts of OpenSSL need to allocate
+   and deallocate locks in a dynamic fashion.  The following typedef
+   makes this possible in a type-safe manner.  */
+/* struct CRYPTO_dynlock_value has to be defined by the application. */
+typedef struct
+	{
+	int references;
+	struct CRYPTO_dynlock_value *data;
+	} CRYPTO_dynlock;
+
+
+/* The following can be used to detect memory leaks in the SSLeay library.
+ * It used, it turns on malloc checking */
+
+#define CRYPTO_MEM_CHECK_OFF	0x0	/* an enume */
+#define CRYPTO_MEM_CHECK_ON	0x1	/* a bit */
+#define CRYPTO_MEM_CHECK_ENABLE	0x2	/* a bit */
+#define CRYPTO_MEM_CHECK_DISABLE 0x3	/* an enume */
+
+/* The following are bit values to turn on or off options connected to the
+ * malloc checking functionality */
+
+/* Adds time to the memory checking information */
+#define V_CRYPTO_MDEBUG_TIME	0x1 /* a bit */
+/* Adds thread number to the memory checking information */
+#define V_CRYPTO_MDEBUG_THREAD	0x2 /* a bit */
+
+#define V_CRYPTO_MDEBUG_ALL (V_CRYPTO_MDEBUG_TIME | V_CRYPTO_MDEBUG_THREAD)
+
+
+/* predec of the BIO type */
+typedef struct bio_st BIO_dummy;
+
+struct crypto_ex_data_st
+	{
+	STACK *sk;
+	int dummy; /* gcc is screwing up this data structure :-( */
+	};
+
+/* This stuff is basically class callback functions
+ * The current classes are SSL_CTX, SSL, SSL_SESSION, and a few more */
+
+typedef struct crypto_ex_data_func_st
+	{
+	long argl;	/* Arbitary long */
+	void *argp;	/* Arbitary void * */
+	CRYPTO_EX_new *new_func;
+	CRYPTO_EX_free *free_func;
+	CRYPTO_EX_dup *dup_func;
+	} CRYPTO_EX_DATA_FUNCS;
+
+DECLARE_STACK_OF(CRYPTO_EX_DATA_FUNCS)
+
+/* Per class, we have a STACK of CRYPTO_EX_DATA_FUNCS for each CRYPTO_EX_DATA
+ * entry.
+ */
+
+#define CRYPTO_EX_INDEX_BIO		0
+#define CRYPTO_EX_INDEX_SSL		1
+#define CRYPTO_EX_INDEX_SSL_CTX		2
+#define CRYPTO_EX_INDEX_SSL_SESSION	3
+#define CRYPTO_EX_INDEX_X509_STORE	4
+#define CRYPTO_EX_INDEX_X509_STORE_CTX	5
+#define CRYPTO_EX_INDEX_RSA		6
+#define CRYPTO_EX_INDEX_DSA		7
+#define CRYPTO_EX_INDEX_DH		8
+#define CRYPTO_EX_INDEX_ENGINE		9
+#define CRYPTO_EX_INDEX_X509		10
+#define CRYPTO_EX_INDEX_UI		11
+#define CRYPTO_EX_INDEX_ECDSA		12
+#define CRYPTO_EX_INDEX_ECDH		13
+#define CRYPTO_EX_INDEX_COMP		14
+#define CRYPTO_EX_INDEX_STORE		15
+
+/* Dynamically assigned indexes start from this value (don't use directly, use
+ * via CRYPTO_ex_data_new_class). */
+#define CRYPTO_EX_INDEX_USER		100
+
+
+/* This is the default callbacks, but we can have others as well:
+ * this is needed in Win32 where the application malloc and the
+ * library malloc may not be the same.
+ */
+#define CRYPTO_malloc_init()	CRYPTO_set_mem_functions(\
+	malloc, realloc, free)
+
+#if defined CRYPTO_MDEBUG_ALL || defined CRYPTO_MDEBUG_TIME || defined CRYPTO_MDEBUG_THREAD
+# ifndef CRYPTO_MDEBUG /* avoid duplicate #define */
+#  define CRYPTO_MDEBUG
+# endif
+#endif
+
+/* Set standard debugging functions (not done by default
+ * unless CRYPTO_MDEBUG is defined) */
+#define CRYPTO_malloc_debug_init()	do {\
+	CRYPTO_set_mem_debug_functions(\
+		CRYPTO_dbg_malloc,\
+		CRYPTO_dbg_realloc,\
+		CRYPTO_dbg_free,\
+		CRYPTO_dbg_set_options,\
+		CRYPTO_dbg_get_options);\
+	} while(0)
+
+int CRYPTO_mem_ctrl(int mode);
+int CRYPTO_is_mem_check_on(void);
+
+/* for applications */
+#define MemCheck_start() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON)
+#define MemCheck_stop()	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF)
+
+/* for library-internal use */
+#define MemCheck_on()	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE)
+#define MemCheck_off()	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE)
+#define is_MemCheck_on() CRYPTO_is_mem_check_on()
+
+#define OPENSSL_malloc(num)	CRYPTO_malloc((int)num,__FILE__,__LINE__)
+#define OPENSSL_realloc(addr,num) \
+	CRYPTO_realloc((char *)addr,(int)num,__FILE__,__LINE__)
+#define OPENSSL_realloc_clean(addr,old_num,num) \
+	CRYPTO_realloc_clean(addr,old_num,num,__FILE__,__LINE__)
+#define OPENSSL_remalloc(addr,num) \
+	CRYPTO_remalloc((char **)addr,(int)num,__FILE__,__LINE__)
+#define OPENSSL_freeFunc	CRYPTO_free
+#define OPENSSL_free(addr)	CRYPTO_free(addr)
+
+#define OPENSSL_malloc_locked(num) \
+	CRYPTO_malloc_locked((int)num,__FILE__,__LINE__)
+#define OPENSSL_free_locked(addr) CRYPTO_free_locked(addr)
+
+
+const char *SSLeay_version(int type);
+unsigned long SSLeay(void);
+
+int OPENSSL_issetugid(void);
+
+/* An opaque type representing an implementation of "ex_data" support */
+typedef struct st_CRYPTO_EX_DATA_IMPL	CRYPTO_EX_DATA_IMPL;
+/* Return an opaque pointer to the current "ex_data" implementation */
+const CRYPTO_EX_DATA_IMPL *CRYPTO_get_ex_data_implementation(void);
+/* Sets the "ex_data" implementation to be used (if it's not too late) */
+int CRYPTO_set_ex_data_implementation(const CRYPTO_EX_DATA_IMPL *i);
+/* Get a new "ex_data" class, and return the corresponding "class_index" */
+int CRYPTO_ex_data_new_class(void);
+/* Within a given class, get/register a new index */
+int CRYPTO_get_ex_new_index(int class_index, long argl, void *argp,
+		CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func,
+		CRYPTO_EX_free *free_func);
+/* Initialise/duplicate/free CRYPTO_EX_DATA variables corresponding to a given
+ * class (invokes whatever per-class callbacks are applicable) */
+int CRYPTO_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad);
+int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to,
+		CRYPTO_EX_DATA *from);
+void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad);
+/* Get/set data in a CRYPTO_EX_DATA variable corresponding to a particular index
+ * (relative to the class type involved) */
+int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int idx, void *val);
+void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad,int idx);
+/* This function cleans up all "ex_data" state. It mustn't be called under
+ * potential race-conditions. */
+void CRYPTO_cleanup_all_ex_data(void);
+
+int CRYPTO_get_new_lockid(char *name);
+
+int CRYPTO_num_locks(void); /* return CRYPTO_NUM_LOCKS (shared libs!) */
+void CRYPTO_lock(int mode, int type,const char *file,int line);
+void CRYPTO_set_locking_callback(void (*func)(int mode,int type,
+					      const char *file,int line));
+void (*CRYPTO_get_locking_callback(void))(int mode,int type,const char *file,
+		int line);
+void CRYPTO_set_add_lock_callback(int (*func)(int *num,int mount,int type,
+					      const char *file, int line));
+int (*CRYPTO_get_add_lock_callback(void))(int *num,int mount,int type,
+					  const char *file,int line);
+void CRYPTO_set_id_callback(unsigned long (*func)(void));
+unsigned long (*CRYPTO_get_id_callback(void))(void);
+unsigned long CRYPTO_thread_id(void);
+const char *CRYPTO_get_lock_name(int type);
+int CRYPTO_add_lock(int *pointer,int amount,int type, const char *file,
+		    int line);
+
+int CRYPTO_get_new_dynlockid(void);
+void CRYPTO_destroy_dynlockid(int i);
+struct CRYPTO_dynlock_value *CRYPTO_get_dynlock_value(int i);
+void CRYPTO_set_dynlock_create_callback(struct CRYPTO_dynlock_value *(*dyn_create_function)(const char *file, int line));
+void CRYPTO_set_dynlock_lock_callback(void (*dyn_lock_function)(int mode, struct CRYPTO_dynlock_value *l, const char *file, int line));
+void CRYPTO_set_dynlock_destroy_callback(void (*dyn_destroy_function)(struct CRYPTO_dynlock_value *l, const char *file, int line));
+struct CRYPTO_dynlock_value *(*CRYPTO_get_dynlock_create_callback(void))(const char *file,int line);
+void (*CRYPTO_get_dynlock_lock_callback(void))(int mode, struct CRYPTO_dynlock_value *l, const char *file,int line);
+void (*CRYPTO_get_dynlock_destroy_callback(void))(struct CRYPTO_dynlock_value *l, const char *file,int line);
+
+/* CRYPTO_set_mem_functions includes CRYPTO_set_locked_mem_functions --
+ * call the latter last if you need different functions */
+int CRYPTO_set_mem_functions(void *(*m)(size_t),void *(*r)(void *,size_t), void (*f)(void *));
+int CRYPTO_set_locked_mem_functions(void *(*m)(size_t), void (*free_func)(void *));
+int CRYPTO_set_mem_ex_functions(void *(*m)(size_t,const char *,int),
+                                void *(*r)(void *,size_t,const char *,int),
+                                void (*f)(void *));
+int CRYPTO_set_locked_mem_ex_functions(void *(*m)(size_t,const char *,int),
+                                       void (*free_func)(void *));
+int CRYPTO_set_mem_debug_functions(void (*m)(void *,int,const char *,int,int),
+				   void (*r)(void *,void *,int,const char *,int,int),
+				   void (*f)(void *,int),
+				   void (*so)(long),
+				   long (*go)(void));
+void CRYPTO_get_mem_functions(void *(**m)(size_t),void *(**r)(void *, size_t), void (**f)(void *));
+void CRYPTO_get_locked_mem_functions(void *(**m)(size_t), void (**f)(void *));
+void CRYPTO_get_mem_ex_functions(void *(**m)(size_t,const char *,int),
+                                 void *(**r)(void *, size_t,const char *,int),
+                                 void (**f)(void *));
+void CRYPTO_get_locked_mem_ex_functions(void *(**m)(size_t,const char *,int),
+                                        void (**f)(void *));
+void CRYPTO_get_mem_debug_functions(void (**m)(void *,int,const char *,int,int),
+				    void (**r)(void *,void *,int,const char *,int,int),
+				    void (**f)(void *,int),
+				    void (**so)(long),
+				    long (**go)(void));
+
+void *CRYPTO_malloc_locked(int num, const char *file, int line);
+void CRYPTO_free_locked(void *);
+void *CRYPTO_malloc(int num, const char *file, int line);
+void CRYPTO_free(void *);
+void *CRYPTO_realloc(void *addr,int num, const char *file, int line);
+void *CRYPTO_realloc_clean(void *addr,int old_num,int num,const char *file,
+			   int line);
+void *CRYPTO_remalloc(void *addr,int num, const char *file, int line);
+
+void OPENSSL_cleanse(void *ptr, size_t len);
+
+void CRYPTO_set_mem_debug_options(long bits);
+long CRYPTO_get_mem_debug_options(void);
+
+#define CRYPTO_push_info(info) \
+        CRYPTO_push_info_(info, __FILE__, __LINE__);
+int CRYPTO_push_info_(const char *info, const char *file, int line);
+int CRYPTO_pop_info(void);
+int CRYPTO_remove_all_info(void);
+
+
+/* Default debugging functions (enabled by CRYPTO_malloc_debug_init() macro;
+ * used as default in CRYPTO_MDEBUG compilations): */
+/* The last argument has the following significance:
+ *
+ * 0:	called before the actual memory allocation has taken place
+ * 1:	called after the actual memory allocation has taken place
+ */
+void CRYPTO_dbg_malloc(void *addr,int num,const char *file,int line,int before_p);
+void CRYPTO_dbg_realloc(void *addr1,void *addr2,int num,const char *file,int line,int before_p);
+void CRYPTO_dbg_free(void *addr,int before_p);
+/* Tell the debugging code about options.  By default, the following values
+ * apply:
+ *
+ * 0:                           Clear all options.
+ * V_CRYPTO_MDEBUG_TIME (1):    Set the "Show Time" option.
+ * V_CRYPTO_MDEBUG_THREAD (2):  Set the "Show Thread Number" option.
+ * V_CRYPTO_MDEBUG_ALL (3):     1 + 2
+ */
+void CRYPTO_dbg_set_options(long bits);
+long CRYPTO_dbg_get_options(void);
+
+
+#ifndef OPENSSL_NO_FP_API
+void CRYPTO_mem_leaks_fp(FILE *);
+#endif
+void CRYPTO_mem_leaks(struct bio_st *bio);
+/* unsigned long order, char *file, int line, int num_bytes, char *addr */
+typedef void *CRYPTO_MEM_LEAK_CB(unsigned long, const char *, int, int, void *);
+void CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb);
+
+/* die if we have to */
+void OpenSSLDie(const char *file,int line,const char *assertion);
+#define OPENSSL_assert(e)       (void)((e) ? 0 : (OpenSSLDie(__FILE__, __LINE__, #e),1))
+
+unsigned long *OPENSSL_ia32cap_loc(void);
+#define OPENSSL_ia32cap (*(OPENSSL_ia32cap_loc()))
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_CRYPTO_strings(void);
+
+/* Error codes for the CRYPTO functions. */
+
+/* Function codes. */
+#define CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX		 100
+#define CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID		 103
+#define CRYPTO_F_CRYPTO_GET_NEW_LOCKID			 101
+#define CRYPTO_F_CRYPTO_SET_EX_DATA			 102
+#define CRYPTO_F_DEF_ADD_INDEX				 104
+#define CRYPTO_F_DEF_GET_CLASS				 105
+#define CRYPTO_F_INT_DUP_EX_DATA			 106
+#define CRYPTO_F_INT_FREE_EX_DATA			 107
+#define CRYPTO_F_INT_NEW_EX_DATA			 108
+
+/* Reason codes. */
+#define CRYPTO_R_NO_DYNLOCK_CREATE_CALLBACK		 100
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/dep/include/openssl/des.h b/dep/include/openssl/des.h
new file mode 100644
index 00000000000..3cbc2b568e9
--- /dev/null
+++ b/dep/include/openssl/des.h
@@ -0,0 +1,244 @@
+/* crypto/des/des.h */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_NEW_DES_H
+#define HEADER_NEW_DES_H
+
+#include 	/* OPENSSL_EXTERN, OPENSSL_NO_DES,
+				   DES_LONG (via openssl/opensslconf.h */
+
+#ifdef OPENSSL_NO_DES
+#error DES is disabled.
+#endif
+
+#ifdef OPENSSL_BUILD_SHLIBCRYPTO
+# undef OPENSSL_EXTERN
+# define OPENSSL_EXTERN OPENSSL_EXPORT
+#endif
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+typedef unsigned char DES_cblock[8];
+typedef /* const */ unsigned char const_DES_cblock[8];
+/* With "const", gcc 2.8.1 on Solaris thinks that DES_cblock *
+ * and const_DES_cblock * are incompatible pointer types. */
+
+typedef struct DES_ks
+    {
+    union
+	{
+	DES_cblock cblock;
+	/* make sure things are correct size on machines with
+	 * 8 byte longs */
+	DES_LONG deslong[2];
+	} ks[16];
+    } DES_key_schedule;
+
+#ifndef OPENSSL_DISABLE_OLD_DES_SUPPORT
+# ifndef OPENSSL_ENABLE_OLD_DES_SUPPORT
+#  define OPENSSL_ENABLE_OLD_DES_SUPPORT
+# endif
+#endif
+
+#ifdef OPENSSL_ENABLE_OLD_DES_SUPPORT
+# include 
+#endif
+
+#define DES_KEY_SZ 	(sizeof(DES_cblock))
+#define DES_SCHEDULE_SZ (sizeof(DES_key_schedule))
+
+#define DES_ENCRYPT	1
+#define DES_DECRYPT	0
+
+#define DES_CBC_MODE	0
+#define DES_PCBC_MODE	1
+
+#define DES_ecb2_encrypt(i,o,k1,k2,e) \
+	DES_ecb3_encrypt((i),(o),(k1),(k2),(k1),(e))
+
+#define DES_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \
+	DES_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(e))
+
+#define DES_ede2_cfb64_encrypt(i,o,l,k1,k2,iv,n,e) \
+	DES_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n),(e))
+
+#define DES_ede2_ofb64_encrypt(i,o,l,k1,k2,iv,n) \
+	DES_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n))
+
+OPENSSL_DECLARE_GLOBAL(int,DES_check_key);	/* defaults to false */
+#define DES_check_key OPENSSL_GLOBAL_REF(DES_check_key)
+OPENSSL_DECLARE_GLOBAL(int,DES_rw_mode);	/* defaults to DES_PCBC_MODE */
+#define DES_rw_mode OPENSSL_GLOBAL_REF(DES_rw_mode)
+
+const char *DES_options(void);
+void DES_ecb3_encrypt(const_DES_cblock *input, DES_cblock *output,
+		      DES_key_schedule *ks1,DES_key_schedule *ks2,
+		      DES_key_schedule *ks3, int enc);
+DES_LONG DES_cbc_cksum(const unsigned char *input,DES_cblock *output,
+		       long length,DES_key_schedule *schedule,
+		       const_DES_cblock *ivec);
+/* DES_cbc_encrypt does not update the IV!  Use DES_ncbc_encrypt instead. */
+void DES_cbc_encrypt(const unsigned char *input,unsigned char *output,
+		     long length,DES_key_schedule *schedule,DES_cblock *ivec,
+		     int enc);
+void DES_ncbc_encrypt(const unsigned char *input,unsigned char *output,
+		      long length,DES_key_schedule *schedule,DES_cblock *ivec,
+		      int enc);
+void DES_xcbc_encrypt(const unsigned char *input,unsigned char *output,
+		      long length,DES_key_schedule *schedule,DES_cblock *ivec,
+		      const_DES_cblock *inw,const_DES_cblock *outw,int enc);
+void DES_cfb_encrypt(const unsigned char *in,unsigned char *out,int numbits,
+		     long length,DES_key_schedule *schedule,DES_cblock *ivec,
+		     int enc);
+void DES_ecb_encrypt(const_DES_cblock *input,DES_cblock *output,
+		     DES_key_schedule *ks,int enc);
+
+/* 	This is the DES encryption function that gets called by just about
+	every other DES routine in the library.  You should not use this
+	function except to implement 'modes' of DES.  I say this because the
+	functions that call this routine do the conversion from 'char *' to
+	long, and this needs to be done to make sure 'non-aligned' memory
+	access do not occur.  The characters are loaded 'little endian'.
+	Data is a pointer to 2 unsigned long's and ks is the
+	DES_key_schedule to use.  enc, is non zero specifies encryption,
+	zero if decryption. */
+void DES_encrypt1(DES_LONG *data,DES_key_schedule *ks, int enc);
+
+/* 	This functions is the same as DES_encrypt1() except that the DES
+	initial permutation (IP) and final permutation (FP) have been left
+	out.  As for DES_encrypt1(), you should not use this function.
+	It is used by the routines in the library that implement triple DES.
+	IP() DES_encrypt2() DES_encrypt2() DES_encrypt2() FP() is the same
+	as DES_encrypt1() DES_encrypt1() DES_encrypt1() except faster :-). */
+void DES_encrypt2(DES_LONG *data,DES_key_schedule *ks, int enc);
+
+void DES_encrypt3(DES_LONG *data, DES_key_schedule *ks1,
+		  DES_key_schedule *ks2, DES_key_schedule *ks3);
+void DES_decrypt3(DES_LONG *data, DES_key_schedule *ks1,
+		  DES_key_schedule *ks2, DES_key_schedule *ks3);
+void DES_ede3_cbc_encrypt(const unsigned char *input,unsigned char *output, 
+			  long length,
+			  DES_key_schedule *ks1,DES_key_schedule *ks2,
+			  DES_key_schedule *ks3,DES_cblock *ivec,int enc);
+void DES_ede3_cbcm_encrypt(const unsigned char *in,unsigned char *out,
+			   long length,
+			   DES_key_schedule *ks1,DES_key_schedule *ks2,
+			   DES_key_schedule *ks3,
+			   DES_cblock *ivec1,DES_cblock *ivec2,
+			   int enc);
+void DES_ede3_cfb64_encrypt(const unsigned char *in,unsigned char *out,
+			    long length,DES_key_schedule *ks1,
+			    DES_key_schedule *ks2,DES_key_schedule *ks3,
+			    DES_cblock *ivec,int *num,int enc);
+void DES_ede3_cfb_encrypt(const unsigned char *in,unsigned char *out,
+			  int numbits,long length,DES_key_schedule *ks1,
+			  DES_key_schedule *ks2,DES_key_schedule *ks3,
+			  DES_cblock *ivec,int enc);
+void DES_ede3_ofb64_encrypt(const unsigned char *in,unsigned char *out,
+			    long length,DES_key_schedule *ks1,
+			    DES_key_schedule *ks2,DES_key_schedule *ks3,
+			    DES_cblock *ivec,int *num);
+
+void DES_xwhite_in2out(const_DES_cblock *DES_key,const_DES_cblock *in_white,
+		       DES_cblock *out_white);
+
+int DES_enc_read(int fd,void *buf,int len,DES_key_schedule *sched,
+		 DES_cblock *iv);
+int DES_enc_write(int fd,const void *buf,int len,DES_key_schedule *sched,
+		  DES_cblock *iv);
+char *DES_fcrypt(const char *buf,const char *salt, char *ret);
+char *DES_crypt(const char *buf,const char *salt);
+void DES_ofb_encrypt(const unsigned char *in,unsigned char *out,int numbits,
+		     long length,DES_key_schedule *schedule,DES_cblock *ivec);
+void DES_pcbc_encrypt(const unsigned char *input,unsigned char *output,
+		      long length,DES_key_schedule *schedule,DES_cblock *ivec,
+		      int enc);
+DES_LONG DES_quad_cksum(const unsigned char *input,DES_cblock output[],
+			long length,int out_count,DES_cblock *seed);
+int DES_random_key(DES_cblock *ret);
+void DES_set_odd_parity(DES_cblock *key);
+int DES_check_key_parity(const_DES_cblock *key);
+int DES_is_weak_key(const_DES_cblock *key);
+/* DES_set_key (= set_key = DES_key_sched = key_sched) calls
+ * DES_set_key_checked if global variable DES_check_key is set,
+ * DES_set_key_unchecked otherwise. */
+int DES_set_key(const_DES_cblock *key,DES_key_schedule *schedule);
+int DES_key_sched(const_DES_cblock *key,DES_key_schedule *schedule);
+int DES_set_key_checked(const_DES_cblock *key,DES_key_schedule *schedule);
+void DES_set_key_unchecked(const_DES_cblock *key,DES_key_schedule *schedule);
+void DES_string_to_key(const char *str,DES_cblock *key);
+void DES_string_to_2keys(const char *str,DES_cblock *key1,DES_cblock *key2);
+void DES_cfb64_encrypt(const unsigned char *in,unsigned char *out,long length,
+		       DES_key_schedule *schedule,DES_cblock *ivec,int *num,
+		       int enc);
+void DES_ofb64_encrypt(const unsigned char *in,unsigned char *out,long length,
+		       DES_key_schedule *schedule,DES_cblock *ivec,int *num);
+
+int DES_read_password(DES_cblock *key, const char *prompt, int verify);
+int DES_read_2passwords(DES_cblock *key1, DES_cblock *key2, const char *prompt,
+	int verify);
+
+#define DES_fixup_key_parity DES_set_odd_parity
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff --git a/dep/include/openssl/des_old.h b/dep/include/openssl/des_old.h
new file mode 100644
index 00000000000..1b0620c3a2e
--- /dev/null
+++ b/dep/include/openssl/des_old.h
@@ -0,0 +1,445 @@
+/* crypto/des/des_old.h -*- mode:C; c-file-style: "eay" -*- */
+
+/* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+ *
+ * The function names in here are deprecated and are only present to
+ * provide an interface compatible with openssl 0.9.6 and older as
+ * well as libdes.  OpenSSL now provides functions where "des_" has
+ * been replaced with "DES_" in the names, to make it possible to
+ * make incompatible changes that are needed for C type security and
+ * other stuff.
+ *
+ * This include files has two compatibility modes:
+ *
+ *   - If OPENSSL_DES_LIBDES_COMPATIBILITY is defined, you get an API
+ *     that is compatible with libdes and SSLeay.
+ *   - If OPENSSL_DES_LIBDES_COMPATIBILITY isn't defined, you get an
+ *     API that is compatible with OpenSSL 0.9.5x to 0.9.6x.
+ *
+ * Note that these modes break earlier snapshots of OpenSSL, where
+ * libdes compatibility was the only available mode or (later on) the
+ * prefered compatibility mode.  However, after much consideration
+ * (and more or less violent discussions with external parties), it
+ * was concluded that OpenSSL should be compatible with earlier versions
+ * of itself before anything else.  Also, in all honesty, libdes is
+ * an old beast that shouldn't really be used any more.
+ *
+ * Please consider starting to use the DES_ functions rather than the
+ * des_ ones.  The des_ functions will disappear completely before
+ * OpenSSL 1.0!
+ *
+ * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+ */
+
+/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL
+ * project 2001.
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_DES_H
+#define HEADER_DES_H
+
+#include 	/* OPENSSL_EXTERN, OPENSSL_NO_DES, DES_LONG */
+
+#ifdef OPENSSL_NO_DES
+#error DES is disabled.
+#endif
+
+#ifndef HEADER_NEW_DES_H
+#error You must include des.h, not des_old.h directly.
+#endif
+
+#ifdef _KERBEROS_DES_H
+#error  replaces .
+#endif
+
+#include 
+
+#ifdef OPENSSL_BUILD_SHLIBCRYPTO
+# undef OPENSSL_EXTERN
+# define OPENSSL_EXTERN OPENSSL_EXPORT
+#endif
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#ifdef _
+#undef _
+#endif
+
+typedef unsigned char _ossl_old_des_cblock[8];
+typedef struct _ossl_old_des_ks_struct
+	{
+	union	{
+		_ossl_old_des_cblock _;
+		/* make sure things are correct size on machines with
+		 * 8 byte longs */
+		DES_LONG pad[2];
+		} ks;
+	} _ossl_old_des_key_schedule[16];
+
+#ifndef OPENSSL_DES_LIBDES_COMPATIBILITY
+#define des_cblock DES_cblock
+#define const_des_cblock const_DES_cblock
+#define des_key_schedule DES_key_schedule
+#define des_ecb3_encrypt(i,o,k1,k2,k3,e)\
+	DES_ecb3_encrypt((i),(o),&(k1),&(k2),&(k3),(e))
+#define des_ede3_cbc_encrypt(i,o,l,k1,k2,k3,iv,e)\
+	DES_ede3_cbc_encrypt((i),(o),(l),&(k1),&(k2),&(k3),(iv),(e))
+#define des_ede3_cbcm_encrypt(i,o,l,k1,k2,k3,iv1,iv2,e)\
+	DES_ede3_cbcm_encrypt((i),(o),(l),&(k1),&(k2),&(k3),(iv1),(iv2),(e))
+#define des_ede3_cfb64_encrypt(i,o,l,k1,k2,k3,iv,n,e)\
+	DES_ede3_cfb64_encrypt((i),(o),(l),&(k1),&(k2),&(k3),(iv),(n),(e))
+#define des_ede3_ofb64_encrypt(i,o,l,k1,k2,k3,iv,n)\
+	DES_ede3_ofb64_encrypt((i),(o),(l),&(k1),&(k2),&(k3),(iv),(n))
+#define des_options()\
+	DES_options()
+#define des_cbc_cksum(i,o,l,k,iv)\
+	DES_cbc_cksum((i),(o),(l),&(k),(iv))
+#define des_cbc_encrypt(i,o,l,k,iv,e)\
+	DES_cbc_encrypt((i),(o),(l),&(k),(iv),(e))
+#define des_ncbc_encrypt(i,o,l,k,iv,e)\
+	DES_ncbc_encrypt((i),(o),(l),&(k),(iv),(e))
+#define des_xcbc_encrypt(i,o,l,k,iv,inw,outw,e)\
+	DES_xcbc_encrypt((i),(o),(l),&(k),(iv),(inw),(outw),(e))
+#define des_cfb_encrypt(i,o,n,l,k,iv,e)\
+	DES_cfb_encrypt((i),(o),(n),(l),&(k),(iv),(e))
+#define des_ecb_encrypt(i,o,k,e)\
+	DES_ecb_encrypt((i),(o),&(k),(e))
+#define des_encrypt1(d,k,e)\
+	DES_encrypt1((d),&(k),(e))
+#define des_encrypt2(d,k,e)\
+	DES_encrypt2((d),&(k),(e))
+#define des_encrypt3(d,k1,k2,k3)\
+	DES_encrypt3((d),&(k1),&(k2),&(k3))
+#define des_decrypt3(d,k1,k2,k3)\
+	DES_decrypt3((d),&(k1),&(k2),&(k3))
+#define des_xwhite_in2out(k,i,o)\
+	DES_xwhite_in2out((k),(i),(o))
+#define des_enc_read(f,b,l,k,iv)\
+	DES_enc_read((f),(b),(l),&(k),(iv))
+#define des_enc_write(f,b,l,k,iv)\
+	DES_enc_write((f),(b),(l),&(k),(iv))
+#define des_fcrypt(b,s,r)\
+	DES_fcrypt((b),(s),(r))
+#if 0
+#define des_crypt(b,s)\
+	DES_crypt((b),(s))
+#if !defined(PERL5) && !defined(__FreeBSD__) && !defined(NeXT) && !defined(__OpenBSD__)
+#define crypt(b,s)\
+	DES_crypt((b),(s))
+#endif
+#endif
+#define des_ofb_encrypt(i,o,n,l,k,iv)\
+	DES_ofb_encrypt((i),(o),(n),(l),&(k),(iv))
+#define des_pcbc_encrypt(i,o,l,k,iv,e)\
+	DES_pcbc_encrypt((i),(o),(l),&(k),(iv),(e))
+#define des_quad_cksum(i,o,l,c,s)\
+	DES_quad_cksum((i),(o),(l),(c),(s))
+#define des_random_seed(k)\
+	_ossl_096_des_random_seed((k))
+#define des_random_key(r)\
+	DES_random_key((r))
+#define des_read_password(k,p,v) \
+	DES_read_password((k),(p),(v))
+#define des_read_2passwords(k1,k2,p,v) \
+	DES_read_2passwords((k1),(k2),(p),(v))
+#define des_set_odd_parity(k)\
+	DES_set_odd_parity((k))
+#define des_check_key_parity(k)\
+	DES_check_key_parity((k))
+#define des_is_weak_key(k)\
+	DES_is_weak_key((k))
+#define des_set_key(k,ks)\
+	DES_set_key((k),&(ks))
+#define des_key_sched(k,ks)\
+	DES_key_sched((k),&(ks))
+#define des_set_key_checked(k,ks)\
+	DES_set_key_checked((k),&(ks))
+#define des_set_key_unchecked(k,ks)\
+	DES_set_key_unchecked((k),&(ks))
+#define des_string_to_key(s,k)\
+	DES_string_to_key((s),(k))
+#define des_string_to_2keys(s,k1,k2)\
+	DES_string_to_2keys((s),(k1),(k2))
+#define des_cfb64_encrypt(i,o,l,ks,iv,n,e)\
+	DES_cfb64_encrypt((i),(o),(l),&(ks),(iv),(n),(e))
+#define des_ofb64_encrypt(i,o,l,ks,iv,n)\
+	DES_ofb64_encrypt((i),(o),(l),&(ks),(iv),(n))
+		
+
+#define des_ecb2_encrypt(i,o,k1,k2,e) \
+	des_ecb3_encrypt((i),(o),(k1),(k2),(k1),(e))
+
+#define des_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \
+	des_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(e))
+
+#define des_ede2_cfb64_encrypt(i,o,l,k1,k2,iv,n,e) \
+	des_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n),(e))
+
+#define des_ede2_ofb64_encrypt(i,o,l,k1,k2,iv,n) \
+	des_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n))
+
+#define des_check_key DES_check_key
+#define des_rw_mode DES_rw_mode
+#else /* libdes compatibility */
+/* Map all symbol names to _ossl_old_des_* form, so we avoid all
+   clashes with libdes */
+#define des_cblock _ossl_old_des_cblock
+#define des_key_schedule _ossl_old_des_key_schedule
+#define des_ecb3_encrypt(i,o,k1,k2,k3,e)\
+	_ossl_old_des_ecb3_encrypt((i),(o),(k1),(k2),(k3),(e))
+#define des_ede3_cbc_encrypt(i,o,l,k1,k2,k3,iv,e)\
+	_ossl_old_des_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k3),(iv),(e))
+#define des_ede3_cfb64_encrypt(i,o,l,k1,k2,k3,iv,n,e)\
+	_ossl_old_des_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k3),(iv),(n),(e))
+#define des_ede3_ofb64_encrypt(i,o,l,k1,k2,k3,iv,n)\
+	_ossl_old_des_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k3),(iv),(n))
+#define des_options()\
+	_ossl_old_des_options()
+#define des_cbc_cksum(i,o,l,k,iv)\
+	_ossl_old_des_cbc_cksum((i),(o),(l),(k),(iv))
+#define des_cbc_encrypt(i,o,l,k,iv,e)\
+	_ossl_old_des_cbc_encrypt((i),(o),(l),(k),(iv),(e))
+#define des_ncbc_encrypt(i,o,l,k,iv,e)\
+	_ossl_old_des_ncbc_encrypt((i),(o),(l),(k),(iv),(e))
+#define des_xcbc_encrypt(i,o,l,k,iv,inw,outw,e)\
+	_ossl_old_des_xcbc_encrypt((i),(o),(l),(k),(iv),(inw),(outw),(e))
+#define des_cfb_encrypt(i,o,n,l,k,iv,e)\
+	_ossl_old_des_cfb_encrypt((i),(o),(n),(l),(k),(iv),(e))
+#define des_ecb_encrypt(i,o,k,e)\
+	_ossl_old_des_ecb_encrypt((i),(o),(k),(e))
+#define des_encrypt(d,k,e)\
+	_ossl_old_des_encrypt((d),(k),(e))
+#define des_encrypt2(d,k,e)\
+	_ossl_old_des_encrypt2((d),(k),(e))
+#define des_encrypt3(d,k1,k2,k3)\
+	_ossl_old_des_encrypt3((d),(k1),(k2),(k3))
+#define des_decrypt3(d,k1,k2,k3)\
+	_ossl_old_des_decrypt3((d),(k1),(k2),(k3))
+#define des_xwhite_in2out(k,i,o)\
+	_ossl_old_des_xwhite_in2out((k),(i),(o))
+#define des_enc_read(f,b,l,k,iv)\
+	_ossl_old_des_enc_read((f),(b),(l),(k),(iv))
+#define des_enc_write(f,b,l,k,iv)\
+	_ossl_old_des_enc_write((f),(b),(l),(k),(iv))
+#define des_fcrypt(b,s,r)\
+	_ossl_old_des_fcrypt((b),(s),(r))
+#define des_crypt(b,s)\
+	_ossl_old_des_crypt((b),(s))
+#if 0
+#define crypt(b,s)\
+	_ossl_old_crypt((b),(s))
+#endif
+#define des_ofb_encrypt(i,o,n,l,k,iv)\
+	_ossl_old_des_ofb_encrypt((i),(o),(n),(l),(k),(iv))
+#define des_pcbc_encrypt(i,o,l,k,iv,e)\
+	_ossl_old_des_pcbc_encrypt((i),(o),(l),(k),(iv),(e))
+#define des_quad_cksum(i,o,l,c,s)\
+	_ossl_old_des_quad_cksum((i),(o),(l),(c),(s))
+#define des_random_seed(k)\
+	_ossl_old_des_random_seed((k))
+#define des_random_key(r)\
+	_ossl_old_des_random_key((r))
+#define des_read_password(k,p,v) \
+	_ossl_old_des_read_password((k),(p),(v))
+#define des_read_2passwords(k1,k2,p,v) \
+	_ossl_old_des_read_2passwords((k1),(k2),(p),(v))
+#define des_set_odd_parity(k)\
+	_ossl_old_des_set_odd_parity((k))
+#define des_is_weak_key(k)\
+	_ossl_old_des_is_weak_key((k))
+#define des_set_key(k,ks)\
+	_ossl_old_des_set_key((k),(ks))
+#define des_key_sched(k,ks)\
+	_ossl_old_des_key_sched((k),(ks))
+#define des_string_to_key(s,k)\
+	_ossl_old_des_string_to_key((s),(k))
+#define des_string_to_2keys(s,k1,k2)\
+	_ossl_old_des_string_to_2keys((s),(k1),(k2))
+#define des_cfb64_encrypt(i,o,l,ks,iv,n,e)\
+	_ossl_old_des_cfb64_encrypt((i),(o),(l),(ks),(iv),(n),(e))
+#define des_ofb64_encrypt(i,o,l,ks,iv,n)\
+	_ossl_old_des_ofb64_encrypt((i),(o),(l),(ks),(iv),(n))
+		
+
+#define des_ecb2_encrypt(i,o,k1,k2,e) \
+	des_ecb3_encrypt((i),(o),(k1),(k2),(k1),(e))
+
+#define des_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \
+	des_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(e))
+
+#define des_ede2_cfb64_encrypt(i,o,l,k1,k2,iv,n,e) \
+	des_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n),(e))
+
+#define des_ede2_ofb64_encrypt(i,o,l,k1,k2,iv,n) \
+	des_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n))
+
+#define des_check_key DES_check_key
+#define des_rw_mode DES_rw_mode
+#endif
+
+const char *_ossl_old_des_options(void);
+void _ossl_old_des_ecb3_encrypt(_ossl_old_des_cblock *input,_ossl_old_des_cblock *output,
+	_ossl_old_des_key_schedule ks1,_ossl_old_des_key_schedule ks2,
+	_ossl_old_des_key_schedule ks3, int enc);
+DES_LONG _ossl_old_des_cbc_cksum(_ossl_old_des_cblock *input,_ossl_old_des_cblock *output,
+	long length,_ossl_old_des_key_schedule schedule,_ossl_old_des_cblock *ivec);
+void _ossl_old_des_cbc_encrypt(_ossl_old_des_cblock *input,_ossl_old_des_cblock *output,long length,
+	_ossl_old_des_key_schedule schedule,_ossl_old_des_cblock *ivec,int enc);
+void _ossl_old_des_ncbc_encrypt(_ossl_old_des_cblock *input,_ossl_old_des_cblock *output,long length,
+	_ossl_old_des_key_schedule schedule,_ossl_old_des_cblock *ivec,int enc);
+void _ossl_old_des_xcbc_encrypt(_ossl_old_des_cblock *input,_ossl_old_des_cblock *output,long length,
+	_ossl_old_des_key_schedule schedule,_ossl_old_des_cblock *ivec,
+	_ossl_old_des_cblock *inw,_ossl_old_des_cblock *outw,int enc);
+void _ossl_old_des_cfb_encrypt(unsigned char *in,unsigned char *out,int numbits,
+	long length,_ossl_old_des_key_schedule schedule,_ossl_old_des_cblock *ivec,int enc);
+void _ossl_old_des_ecb_encrypt(_ossl_old_des_cblock *input,_ossl_old_des_cblock *output,
+	_ossl_old_des_key_schedule ks,int enc);
+void _ossl_old_des_encrypt(DES_LONG *data,_ossl_old_des_key_schedule ks, int enc);
+void _ossl_old_des_encrypt2(DES_LONG *data,_ossl_old_des_key_schedule ks, int enc);
+void _ossl_old_des_encrypt3(DES_LONG *data, _ossl_old_des_key_schedule ks1,
+	_ossl_old_des_key_schedule ks2, _ossl_old_des_key_schedule ks3);
+void _ossl_old_des_decrypt3(DES_LONG *data, _ossl_old_des_key_schedule ks1,
+	_ossl_old_des_key_schedule ks2, _ossl_old_des_key_schedule ks3);
+void _ossl_old_des_ede3_cbc_encrypt(_ossl_old_des_cblock *input, _ossl_old_des_cblock *output, 
+	long length, _ossl_old_des_key_schedule ks1, _ossl_old_des_key_schedule ks2, 
+	_ossl_old_des_key_schedule ks3, _ossl_old_des_cblock *ivec, int enc);
+void _ossl_old_des_ede3_cfb64_encrypt(unsigned char *in, unsigned char *out,
+	long length, _ossl_old_des_key_schedule ks1, _ossl_old_des_key_schedule ks2,
+	_ossl_old_des_key_schedule ks3, _ossl_old_des_cblock *ivec, int *num, int enc);
+void _ossl_old_des_ede3_ofb64_encrypt(unsigned char *in, unsigned char *out,
+	long length, _ossl_old_des_key_schedule ks1, _ossl_old_des_key_schedule ks2,
+	_ossl_old_des_key_schedule ks3, _ossl_old_des_cblock *ivec, int *num);
+
+void _ossl_old_des_xwhite_in2out(_ossl_old_des_cblock (*des_key), _ossl_old_des_cblock (*in_white),
+	_ossl_old_des_cblock (*out_white));
+
+int _ossl_old_des_enc_read(int fd,char *buf,int len,_ossl_old_des_key_schedule sched,
+	_ossl_old_des_cblock *iv);
+int _ossl_old_des_enc_write(int fd,char *buf,int len,_ossl_old_des_key_schedule sched,
+	_ossl_old_des_cblock *iv);
+char *_ossl_old_des_fcrypt(const char *buf,const char *salt, char *ret);
+char *_ossl_old_des_crypt(const char *buf,const char *salt);
+#if !defined(PERL5) && !defined(NeXT)
+char *_ossl_old_crypt(const char *buf,const char *salt);
+#endif
+void _ossl_old_des_ofb_encrypt(unsigned char *in,unsigned char *out,
+	int numbits,long length,_ossl_old_des_key_schedule schedule,_ossl_old_des_cblock *ivec);
+void _ossl_old_des_pcbc_encrypt(_ossl_old_des_cblock *input,_ossl_old_des_cblock *output,long length,
+	_ossl_old_des_key_schedule schedule,_ossl_old_des_cblock *ivec,int enc);
+DES_LONG _ossl_old_des_quad_cksum(_ossl_old_des_cblock *input,_ossl_old_des_cblock *output,
+	long length,int out_count,_ossl_old_des_cblock *seed);
+void _ossl_old_des_random_seed(_ossl_old_des_cblock key);
+void _ossl_old_des_random_key(_ossl_old_des_cblock ret);
+int _ossl_old_des_read_password(_ossl_old_des_cblock *key,const char *prompt,int verify);
+int _ossl_old_des_read_2passwords(_ossl_old_des_cblock *key1,_ossl_old_des_cblock *key2,
+	const char *prompt,int verify);
+void _ossl_old_des_set_odd_parity(_ossl_old_des_cblock *key);
+int _ossl_old_des_is_weak_key(_ossl_old_des_cblock *key);
+int _ossl_old_des_set_key(_ossl_old_des_cblock *key,_ossl_old_des_key_schedule schedule);
+int _ossl_old_des_key_sched(_ossl_old_des_cblock *key,_ossl_old_des_key_schedule schedule);
+void _ossl_old_des_string_to_key(char *str,_ossl_old_des_cblock *key);
+void _ossl_old_des_string_to_2keys(char *str,_ossl_old_des_cblock *key1,_ossl_old_des_cblock *key2);
+void _ossl_old_des_cfb64_encrypt(unsigned char *in, unsigned char *out, long length,
+	_ossl_old_des_key_schedule schedule, _ossl_old_des_cblock *ivec, int *num, int enc);
+void _ossl_old_des_ofb64_encrypt(unsigned char *in, unsigned char *out, long length,
+	_ossl_old_des_key_schedule schedule, _ossl_old_des_cblock *ivec, int *num);
+
+void _ossl_096_des_random_seed(des_cblock *key);
+
+/* The following definitions provide compatibility with the MIT Kerberos
+ * library. The _ossl_old_des_key_schedule structure is not binary compatible. */
+
+#define _KERBEROS_DES_H
+
+#define KRBDES_ENCRYPT DES_ENCRYPT
+#define KRBDES_DECRYPT DES_DECRYPT
+
+#ifdef KERBEROS
+#  define ENCRYPT DES_ENCRYPT
+#  define DECRYPT DES_DECRYPT
+#endif
+
+#ifndef NCOMPAT
+#  define C_Block des_cblock
+#  define Key_schedule des_key_schedule
+#  define KEY_SZ DES_KEY_SZ
+#  define string_to_key des_string_to_key
+#  define read_pw_string des_read_pw_string
+#  define random_key des_random_key
+#  define pcbc_encrypt des_pcbc_encrypt
+#  define set_key des_set_key
+#  define key_sched des_key_sched
+#  define ecb_encrypt des_ecb_encrypt
+#  define cbc_encrypt des_cbc_encrypt
+#  define ncbc_encrypt des_ncbc_encrypt
+#  define xcbc_encrypt des_xcbc_encrypt
+#  define cbc_cksum des_cbc_cksum
+#  define quad_cksum des_quad_cksum
+#  define check_parity des_check_key_parity
+#endif
+
+#define des_fixup_key_parity DES_fixup_key_parity
+
+#ifdef  __cplusplus
+}
+#endif
+
+/* for DES_read_pw_string et al */
+#include 
+
+#endif
diff --git a/dep/include/openssl/dh.h b/dep/include/openssl/dh.h
new file mode 100644
index 00000000000..ccdf35ae1c2
--- /dev/null
+++ b/dep/include/openssl/dh.h
@@ -0,0 +1,234 @@
+/* crypto/dh/dh.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_DH_H
+#define HEADER_DH_H
+
+#include 
+
+#ifdef OPENSSL_NO_DH
+#error DH is disabled.
+#endif
+
+#ifndef OPENSSL_NO_BIO
+#include 
+#endif
+#include 
+#ifndef OPENSSL_NO_DEPRECATED
+#include 
+#endif
+	
+#ifndef OPENSSL_DH_MAX_MODULUS_BITS
+# define OPENSSL_DH_MAX_MODULUS_BITS	10000
+#endif
+
+#define DH_FLAG_CACHE_MONT_P     0x01
+#define DH_FLAG_NO_EXP_CONSTTIME 0x02 /* new with 0.9.7h; the built-in DH
+                                       * implementation now uses constant time
+                                       * modular exponentiation for secret exponents
+                                       * by default. This flag causes the
+                                       * faster variable sliding window method to
+                                       * be used for all exponents.
+                                       */
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* Already defined in ossl_typ.h */
+/* typedef struct dh_st DH; */
+/* typedef struct dh_method DH_METHOD; */
+
+struct dh_method
+	{
+	const char *name;
+	/* Methods here */
+	int (*generate_key)(DH *dh);
+	int (*compute_key)(unsigned char *key,const BIGNUM *pub_key,DH *dh);
+	int (*bn_mod_exp)(const DH *dh, BIGNUM *r, const BIGNUM *a,
+				const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
+				BN_MONT_CTX *m_ctx); /* Can be null */
+
+	int (*init)(DH *dh);
+	int (*finish)(DH *dh);
+	int flags;
+	char *app_data;
+	/* If this is non-NULL, it will be used to generate parameters */
+	int (*generate_params)(DH *dh, int prime_len, int generator, BN_GENCB *cb);
+	};
+
+struct dh_st
+	{
+	/* This first argument is used to pick up errors when
+	 * a DH is passed instead of a EVP_PKEY */
+	int pad;
+	int version;
+	BIGNUM *p;
+	BIGNUM *g;
+	long length; /* optional */
+	BIGNUM *pub_key;	/* g^x */
+	BIGNUM *priv_key;	/* x */
+
+	int flags;
+	BN_MONT_CTX *method_mont_p;
+	/* Place holders if we want to do X9.42 DH */
+	BIGNUM *q;
+	BIGNUM *j;
+	unsigned char *seed;
+	int seedlen;
+	BIGNUM *counter;
+
+	int references;
+	CRYPTO_EX_DATA ex_data;
+	const DH_METHOD *meth;
+	ENGINE *engine;
+	};
+
+#define DH_GENERATOR_2		2
+/* #define DH_GENERATOR_3	3 */
+#define DH_GENERATOR_5		5
+
+/* DH_check error codes */
+#define DH_CHECK_P_NOT_PRIME		0x01
+#define DH_CHECK_P_NOT_SAFE_PRIME	0x02
+#define DH_UNABLE_TO_CHECK_GENERATOR	0x04
+#define DH_NOT_SUITABLE_GENERATOR	0x08
+
+/* DH_check_pub_key error codes */
+#define DH_CHECK_PUBKEY_TOO_SMALL	0x01
+#define DH_CHECK_PUBKEY_TOO_LARGE	0x02
+
+/* primes p where (p-1)/2 is prime too are called "safe"; we define
+   this for backward compatibility: */
+#define DH_CHECK_P_NOT_STRONG_PRIME	DH_CHECK_P_NOT_SAFE_PRIME
+
+#define DHparams_dup(x) ASN1_dup_of_const(DH,i2d_DHparams,d2i_DHparams,x)
+#define d2i_DHparams_fp(fp,x) (DH *)ASN1_d2i_fp((char *(*)())DH_new, \
+		(char *(*)())d2i_DHparams,(fp),(unsigned char **)(x))
+#define i2d_DHparams_fp(fp,x) ASN1_i2d_fp(i2d_DHparams,(fp), \
+		(unsigned char *)(x))
+#define d2i_DHparams_bio(bp,x) ASN1_d2i_bio_of(DH,DH_new,d2i_DHparams,bp,x)
+#define i2d_DHparams_bio(bp,x) ASN1_i2d_bio_of_const(DH,i2d_DHparams,bp,x)
+
+const DH_METHOD *DH_OpenSSL(void);
+
+void DH_set_default_method(const DH_METHOD *meth);
+const DH_METHOD *DH_get_default_method(void);
+int DH_set_method(DH *dh, const DH_METHOD *meth);
+DH *DH_new_method(ENGINE *engine);
+
+DH *	DH_new(void);
+void	DH_free(DH *dh);
+int	DH_up_ref(DH *dh);
+int	DH_size(const DH *dh);
+int DH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int DH_set_ex_data(DH *d, int idx, void *arg);
+void *DH_get_ex_data(DH *d, int idx);
+
+/* Deprecated version */
+#ifndef OPENSSL_NO_DEPRECATED
+DH *	DH_generate_parameters(int prime_len,int generator,
+		void (*callback)(int,int,void *),void *cb_arg);
+#endif /* !defined(OPENSSL_NO_DEPRECATED) */
+
+/* New version */
+int	DH_generate_parameters_ex(DH *dh, int prime_len,int generator, BN_GENCB *cb);
+
+int	DH_check(const DH *dh,int *codes);
+int	DH_check_pub_key(const DH *dh,const BIGNUM *pub_key, int *codes);
+int	DH_generate_key(DH *dh);
+int	DH_compute_key(unsigned char *key,const BIGNUM *pub_key,DH *dh);
+DH *	d2i_DHparams(DH **a,const unsigned char **pp, long length);
+int	i2d_DHparams(const DH *a,unsigned char **pp);
+#ifndef OPENSSL_NO_FP_API
+int	DHparams_print_fp(FILE *fp, const DH *x);
+#endif
+#ifndef OPENSSL_NO_BIO
+int	DHparams_print(BIO *bp, const DH *x);
+#else
+int	DHparams_print(char *bp, const DH *x);
+#endif
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_DH_strings(void);
+
+/* Error codes for the DH functions. */
+
+/* Function codes. */
+#define DH_F_COMPUTE_KEY				 102
+#define DH_F_DHPARAMS_PRINT				 100
+#define DH_F_DHPARAMS_PRINT_FP				 101
+#define DH_F_DH_BUILTIN_GENPARAMS			 106
+#define DH_F_DH_NEW_METHOD				 105
+#define DH_F_GENERATE_KEY				 103
+#define DH_F_GENERATE_PARAMETERS			 104
+
+/* Reason codes. */
+#define DH_R_BAD_GENERATOR				 101
+#define DH_R_INVALID_PUBKEY				 102
+#define DH_R_MODULUS_TOO_LARGE				 103
+#define DH_R_NO_PRIVATE_VALUE				 100
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/dep/include/openssl/dsa.h b/dep/include/openssl/dsa.h
new file mode 100644
index 00000000000..3a8fe5b56bb
--- /dev/null
+++ b/dep/include/openssl/dsa.h
@@ -0,0 +1,285 @@
+/* crypto/dsa/dsa.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/*
+ * The DSS routines are based on patches supplied by
+ * Steven Schoch .  He basically did the
+ * work and I have just tweaked them a little to fit into my
+ * stylistic vision for SSLeay :-) */
+
+#ifndef HEADER_DSA_H
+#define HEADER_DSA_H
+
+#include 
+
+#ifdef OPENSSL_NO_DSA
+#error DSA is disabled.
+#endif
+
+#ifndef OPENSSL_NO_BIO
+#include 
+#endif
+#include 
+#include 
+
+#ifndef OPENSSL_NO_DEPRECATED
+#include 
+#ifndef OPENSSL_NO_DH
+# include 
+#endif
+#endif
+
+#ifndef OPENSSL_DSA_MAX_MODULUS_BITS
+# define OPENSSL_DSA_MAX_MODULUS_BITS	10000
+#endif
+
+#define DSA_FLAG_CACHE_MONT_P	0x01
+#define DSA_FLAG_NO_EXP_CONSTTIME       0x02 /* new with 0.9.7h; the built-in DSA
+                                              * implementation now uses constant time
+                                              * modular exponentiation for secret exponents
+                                              * by default. This flag causes the
+                                              * faster variable sliding window method to
+                                              * be used for all exponents.
+                                              */
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* Already defined in ossl_typ.h */
+/* typedef struct dsa_st DSA; */
+/* typedef struct dsa_method DSA_METHOD; */
+
+typedef struct DSA_SIG_st
+	{
+	BIGNUM *r;
+	BIGNUM *s;
+	} DSA_SIG;
+
+struct dsa_method
+	{
+	const char *name;
+	DSA_SIG * (*dsa_do_sign)(const unsigned char *dgst, int dlen, DSA *dsa);
+	int (*dsa_sign_setup)(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
+								BIGNUM **rp);
+	int (*dsa_do_verify)(const unsigned char *dgst, int dgst_len,
+							DSA_SIG *sig, DSA *dsa);
+	int (*dsa_mod_exp)(DSA *dsa, BIGNUM *rr, BIGNUM *a1, BIGNUM *p1,
+			BIGNUM *a2, BIGNUM *p2, BIGNUM *m, BN_CTX *ctx,
+			BN_MONT_CTX *in_mont);
+	int (*bn_mod_exp)(DSA *dsa, BIGNUM *r, BIGNUM *a, const BIGNUM *p,
+				const BIGNUM *m, BN_CTX *ctx,
+				BN_MONT_CTX *m_ctx); /* Can be null */
+	int (*init)(DSA *dsa);
+	int (*finish)(DSA *dsa);
+	int flags;
+	char *app_data;
+	/* If this is non-NULL, it is used to generate DSA parameters */
+	int (*dsa_paramgen)(DSA *dsa, int bits,
+			unsigned char *seed, int seed_len,
+			int *counter_ret, unsigned long *h_ret,
+			BN_GENCB *cb);
+	/* If this is non-NULL, it is used to generate DSA keys */
+	int (*dsa_keygen)(DSA *dsa);
+	};
+
+struct dsa_st
+	{
+	/* This first variable is used to pick up errors where
+	 * a DSA is passed instead of of a EVP_PKEY */
+	int pad;
+	long version;
+	int write_params;
+	BIGNUM *p;
+	BIGNUM *q;	/* == 20 */
+	BIGNUM *g;
+
+	BIGNUM *pub_key;  /* y public key */
+	BIGNUM *priv_key; /* x private key */
+
+	BIGNUM *kinv;	/* Signing pre-calc */
+	BIGNUM *r;	/* Signing pre-calc */
+
+	int flags;
+	/* Normally used to cache montgomery values */
+	BN_MONT_CTX *method_mont_p;
+	int references;
+	CRYPTO_EX_DATA ex_data;
+	const DSA_METHOD *meth;
+	/* functional reference if 'meth' is ENGINE-provided */
+	ENGINE *engine;
+	};
+
+#define DSAparams_dup(x) ASN1_dup_of_const(DSA,i2d_DSAparams,d2i_DSAparams,x)
+#define d2i_DSAparams_fp(fp,x) (DSA *)ASN1_d2i_fp((char *(*)())DSA_new, \
+		(char *(*)())d2i_DSAparams,(fp),(unsigned char **)(x))
+#define i2d_DSAparams_fp(fp,x) ASN1_i2d_fp(i2d_DSAparams,(fp), \
+		(unsigned char *)(x))
+#define d2i_DSAparams_bio(bp,x) ASN1_d2i_bio_of(DSA,DSA_new,d2i_DSAparams,bp,x)
+#define i2d_DSAparams_bio(bp,x) ASN1_i2d_bio_of_const(DSA,i2d_DSAparams,bp,x)
+
+
+DSA_SIG * DSA_SIG_new(void);
+void	DSA_SIG_free(DSA_SIG *a);
+int	i2d_DSA_SIG(const DSA_SIG *a, unsigned char **pp);
+DSA_SIG * d2i_DSA_SIG(DSA_SIG **v, const unsigned char **pp, long length);
+
+DSA_SIG * DSA_do_sign(const unsigned char *dgst,int dlen,DSA *dsa);
+int	DSA_do_verify(const unsigned char *dgst,int dgst_len,
+		      DSA_SIG *sig,DSA *dsa);
+
+const DSA_METHOD *DSA_OpenSSL(void);
+
+void	DSA_set_default_method(const DSA_METHOD *);
+const DSA_METHOD *DSA_get_default_method(void);
+int	DSA_set_method(DSA *dsa, const DSA_METHOD *);
+
+DSA *	DSA_new(void);
+DSA *	DSA_new_method(ENGINE *engine);
+void	DSA_free (DSA *r);
+/* "up" the DSA object's reference count */
+int	DSA_up_ref(DSA *r);
+int	DSA_size(const DSA *);
+	/* next 4 return -1 on error */
+int	DSA_sign_setup( DSA *dsa,BN_CTX *ctx_in,BIGNUM **kinvp,BIGNUM **rp);
+int	DSA_sign(int type,const unsigned char *dgst,int dlen,
+		unsigned char *sig, unsigned int *siglen, DSA *dsa);
+int	DSA_verify(int type,const unsigned char *dgst,int dgst_len,
+		const unsigned char *sigbuf, int siglen, DSA *dsa);
+int DSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int DSA_set_ex_data(DSA *d, int idx, void *arg);
+void *DSA_get_ex_data(DSA *d, int idx);
+
+DSA *	d2i_DSAPublicKey(DSA **a, const unsigned char **pp, long length);
+DSA *	d2i_DSAPrivateKey(DSA **a, const unsigned char **pp, long length);
+DSA * 	d2i_DSAparams(DSA **a, const unsigned char **pp, long length);
+
+/* Deprecated version */
+#ifndef OPENSSL_NO_DEPRECATED
+DSA *	DSA_generate_parameters(int bits,
+		unsigned char *seed,int seed_len,
+		int *counter_ret, unsigned long *h_ret,void
+		(*callback)(int, int, void *),void *cb_arg);
+#endif /* !defined(OPENSSL_NO_DEPRECATED) */
+
+/* New version */
+int	DSA_generate_parameters_ex(DSA *dsa, int bits,
+		unsigned char *seed,int seed_len,
+		int *counter_ret, unsigned long *h_ret, BN_GENCB *cb);
+
+int	DSA_generate_key(DSA *a);
+int	i2d_DSAPublicKey(const DSA *a, unsigned char **pp);
+int 	i2d_DSAPrivateKey(const DSA *a, unsigned char **pp);
+int	i2d_DSAparams(const DSA *a,unsigned char **pp);
+
+#ifndef OPENSSL_NO_BIO
+int	DSAparams_print(BIO *bp, const DSA *x);
+int	DSA_print(BIO *bp, const DSA *x, int off);
+#endif
+#ifndef OPENSSL_NO_FP_API
+int	DSAparams_print_fp(FILE *fp, const DSA *x);
+int	DSA_print_fp(FILE *bp, const DSA *x, int off);
+#endif
+
+#define DSS_prime_checks 50
+/* Primality test according to FIPS PUB 186[-1], Appendix 2.1:
+ * 50 rounds of Rabin-Miller */
+#define DSA_is_prime(n, callback, cb_arg) \
+	BN_is_prime(n, DSS_prime_checks, callback, NULL, cb_arg)
+
+#ifndef OPENSSL_NO_DH
+/* Convert DSA structure (key or just parameters) into DH structure
+ * (be careful to avoid small subgroup attacks when using this!) */
+DH *DSA_dup_DH(const DSA *r);
+#endif
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_DSA_strings(void);
+
+/* Error codes for the DSA functions. */
+
+/* Function codes. */
+#define DSA_F_D2I_DSA_SIG				 110
+#define DSA_F_DSAPARAMS_PRINT				 100
+#define DSA_F_DSAPARAMS_PRINT_FP			 101
+#define DSA_F_DSA_DO_SIGN				 112
+#define DSA_F_DSA_DO_VERIFY				 113
+#define DSA_F_DSA_NEW_METHOD				 103
+#define DSA_F_DSA_PRINT					 104
+#define DSA_F_DSA_PRINT_FP				 105
+#define DSA_F_DSA_SIGN					 106
+#define DSA_F_DSA_SIGN_SETUP				 107
+#define DSA_F_DSA_SIG_NEW				 109
+#define DSA_F_DSA_VERIFY				 108
+#define DSA_F_I2D_DSA_SIG				 111
+#define DSA_F_SIG_CB					 114
+
+/* Reason codes. */
+#define DSA_R_BAD_Q_VALUE				 102
+#define DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE		 100
+#define DSA_R_MISSING_PARAMETERS			 101
+#define DSA_R_MODULUS_TOO_LARGE				 103
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/dep/include/openssl/dso.h b/dep/include/openssl/dso.h
new file mode 100644
index 00000000000..3e51913a725
--- /dev/null
+++ b/dep/include/openssl/dso.h
@@ -0,0 +1,368 @@
+/* dso.h -*- mode:C; c-file-style: "eay" -*- */
+/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_DSO_H
+#define HEADER_DSO_H
+
+#include 
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* These values are used as commands to DSO_ctrl() */
+#define DSO_CTRL_GET_FLAGS	1
+#define DSO_CTRL_SET_FLAGS	2
+#define DSO_CTRL_OR_FLAGS	3
+
+/* By default, DSO_load() will translate the provided filename into a form
+ * typical for the platform (more specifically the DSO_METHOD) using the
+ * dso_name_converter function of the method. Eg. win32 will transform "blah"
+ * into "blah.dll", and dlfcn will transform it into "libblah.so". The
+ * behaviour can be overriden by setting the name_converter callback in the DSO
+ * object (using DSO_set_name_converter()). This callback could even utilise
+ * the DSO_METHOD's converter too if it only wants to override behaviour for
+ * one or two possible DSO methods. However, the following flag can be set in a
+ * DSO to prevent *any* native name-translation at all - eg. if the caller has
+ * prompted the user for a path to a driver library so the filename should be
+ * interpreted as-is. */
+#define DSO_FLAG_NO_NAME_TRANSLATION		0x01
+/* An extra flag to give if only the extension should be added as
+ * translation.  This is obviously only of importance on Unix and
+ * other operating systems where the translation also may prefix
+ * the name with something, like 'lib', and ignored everywhere else.
+ * This flag is also ignored if DSO_FLAG_NO_NAME_TRANSLATION is used
+ * at the same time. */
+#define DSO_FLAG_NAME_TRANSLATION_EXT_ONLY	0x02
+
+/* The following flag controls the translation of symbol names to upper
+ * case.  This is currently only being implemented for OpenVMS.
+ */
+#define DSO_FLAG_UPCASE_SYMBOL			0x10
+
+/* This flag loads the library with public symbols.
+ * Meaning: The exported symbols of this library are public
+ * to all libraries loaded after this library.
+ * At the moment only implemented in unix.
+ */
+#define DSO_FLAG_GLOBAL_SYMBOLS			0x20
+
+
+typedef void (*DSO_FUNC_TYPE)(void);
+
+typedef struct dso_st DSO;
+
+/* The function prototype used for method functions (or caller-provided
+ * callbacks) that transform filenames. They are passed a DSO structure pointer
+ * (or NULL if they are to be used independantly of a DSO object) and a
+ * filename to transform. They should either return NULL (if there is an error
+ * condition) or a newly allocated string containing the transformed form that
+ * the caller will need to free with OPENSSL_free() when done. */
+typedef char* (*DSO_NAME_CONVERTER_FUNC)(DSO *, const char *);
+/* The function prototype used for method functions (or caller-provided
+ * callbacks) that merge two file specifications. They are passed a
+ * DSO structure pointer (or NULL if they are to be used independantly of
+ * a DSO object) and two file specifications to merge. They should
+ * either return NULL (if there is an error condition) or a newly allocated
+ * string containing the result of merging that the caller will need
+ * to free with OPENSSL_free() when done.
+ * Here, merging means that bits and pieces are taken from each of the
+ * file specifications and added together in whatever fashion that is
+ * sensible for the DSO method in question.  The only rule that really
+ * applies is that if the two specification contain pieces of the same
+ * type, the copy from the first string takes priority.  One could see
+ * it as the first specification is the one given by the user and the
+ * second being a bunch of defaults to add on if they're missing in the
+ * first. */
+typedef char* (*DSO_MERGER_FUNC)(DSO *, const char *, const char *);
+
+typedef struct dso_meth_st
+	{
+	const char *name;
+	/* Loads a shared library, NB: new DSO_METHODs must ensure that a
+	 * successful load populates the loaded_filename field, and likewise a
+	 * successful unload OPENSSL_frees and NULLs it out. */
+	int (*dso_load)(DSO *dso);
+	/* Unloads a shared library */
+	int (*dso_unload)(DSO *dso);
+	/* Binds a variable */
+	void *(*dso_bind_var)(DSO *dso, const char *symname);
+	/* Binds a function - assumes a return type of DSO_FUNC_TYPE.
+	 * This should be cast to the real function prototype by the
+	 * caller. Platforms that don't have compatible representations
+	 * for different prototypes (this is possible within ANSI C)
+	 * are highly unlikely to have shared libraries at all, let
+	 * alone a DSO_METHOD implemented for them. */
+	DSO_FUNC_TYPE (*dso_bind_func)(DSO *dso, const char *symname);
+
+/* I don't think this would actually be used in any circumstances. */
+#if 0
+	/* Unbinds a variable */
+	int (*dso_unbind_var)(DSO *dso, char *symname, void *symptr);
+	/* Unbinds a function */
+	int (*dso_unbind_func)(DSO *dso, char *symname, DSO_FUNC_TYPE symptr);
+#endif
+	/* The generic (yuck) "ctrl()" function. NB: Negative return
+	 * values (rather than zero) indicate errors. */
+	long (*dso_ctrl)(DSO *dso, int cmd, long larg, void *parg);
+	/* The default DSO_METHOD-specific function for converting filenames to
+	 * a canonical native form. */
+	DSO_NAME_CONVERTER_FUNC dso_name_converter;
+	/* The default DSO_METHOD-specific function for converting filenames to
+	 * a canonical native form. */
+	DSO_MERGER_FUNC dso_merger;
+
+	/* [De]Initialisation handlers. */
+	int (*init)(DSO *dso);
+	int (*finish)(DSO *dso);
+	} DSO_METHOD;
+
+/**********************************************************************/
+/* The low-level handle type used to refer to a loaded shared library */
+
+struct dso_st
+	{
+	DSO_METHOD *meth;
+	/* Standard dlopen uses a (void *). Win32 uses a HANDLE. VMS
+	 * doesn't use anything but will need to cache the filename
+	 * for use in the dso_bind handler. All in all, let each
+	 * method control its own destiny. "Handles" and such go in
+	 * a STACK. */
+	STACK *meth_data;
+	int references;
+	int flags;
+	/* For use by applications etc ... use this for your bits'n'pieces,
+	 * don't touch meth_data! */
+	CRYPTO_EX_DATA ex_data;
+	/* If this callback function pointer is set to non-NULL, then it will
+	 * be used in DSO_load() in place of meth->dso_name_converter. NB: This
+	 * should normally set using DSO_set_name_converter(). */
+	DSO_NAME_CONVERTER_FUNC name_converter;
+	/* If this callback function pointer is set to non-NULL, then it will
+	 * be used in DSO_load() in place of meth->dso_merger. NB: This
+	 * should normally set using DSO_set_merger(). */
+	DSO_MERGER_FUNC merger;
+	/* This is populated with (a copy of) the platform-independant
+	 * filename used for this DSO. */
+	char *filename;
+	/* This is populated with (a copy of) the translated filename by which
+	 * the DSO was actually loaded. It is NULL iff the DSO is not currently
+	 * loaded. NB: This is here because the filename translation process
+	 * may involve a callback being invoked more than once not only to
+	 * convert to a platform-specific form, but also to try different
+	 * filenames in the process of trying to perform a load. As such, this
+	 * variable can be used to indicate (a) whether this DSO structure
+	 * corresponds to a loaded library or not, and (b) the filename with
+	 * which it was actually loaded. */
+	char *loaded_filename;
+	};
+
+
+DSO *	DSO_new(void);
+DSO *	DSO_new_method(DSO_METHOD *method);
+int	DSO_free(DSO *dso);
+int	DSO_flags(DSO *dso);
+int	DSO_up_ref(DSO *dso);
+long	DSO_ctrl(DSO *dso, int cmd, long larg, void *parg);
+
+/* This function sets the DSO's name_converter callback. If it is non-NULL,
+ * then it will be used instead of the associated DSO_METHOD's function. If
+ * oldcb is non-NULL then it is set to the function pointer value being
+ * replaced. Return value is non-zero for success. */
+int	DSO_set_name_converter(DSO *dso, DSO_NAME_CONVERTER_FUNC cb,
+				DSO_NAME_CONVERTER_FUNC *oldcb);
+/* These functions can be used to get/set the platform-independant filename
+ * used for a DSO. NB: set will fail if the DSO is already loaded. */
+const char *DSO_get_filename(DSO *dso);
+int	DSO_set_filename(DSO *dso, const char *filename);
+/* This function will invoke the DSO's name_converter callback to translate a
+ * filename, or if the callback isn't set it will instead use the DSO_METHOD's
+ * converter. If "filename" is NULL, the "filename" in the DSO itself will be
+ * used. If the DSO_FLAG_NO_NAME_TRANSLATION flag is set, then the filename is
+ * simply duplicated. NB: This function is usually called from within a
+ * DSO_METHOD during the processing of a DSO_load() call, and is exposed so that
+ * caller-created DSO_METHODs can do the same thing. A non-NULL return value
+ * will need to be OPENSSL_free()'d. */
+char	*DSO_convert_filename(DSO *dso, const char *filename);
+/* This function will invoke the DSO's merger callback to merge two file
+ * specifications, or if the callback isn't set it will instead use the
+ * DSO_METHOD's merger.  A non-NULL return value will need to be
+ * OPENSSL_free()'d. */
+char	*DSO_merge(DSO *dso, const char *filespec1, const char *filespec2);
+/* If the DSO is currently loaded, this returns the filename that it was loaded
+ * under, otherwise it returns NULL. So it is also useful as a test as to
+ * whether the DSO is currently loaded. NB: This will not necessarily return
+ * the same value as DSO_convert_filename(dso, dso->filename), because the
+ * DSO_METHOD's load function may have tried a variety of filenames (with
+ * and/or without the aid of the converters) before settling on the one it
+ * actually loaded. */
+const char *DSO_get_loaded_filename(DSO *dso);
+
+void	DSO_set_default_method(DSO_METHOD *meth);
+DSO_METHOD *DSO_get_default_method(void);
+DSO_METHOD *DSO_get_method(DSO *dso);
+DSO_METHOD *DSO_set_method(DSO *dso, DSO_METHOD *meth);
+
+/* The all-singing all-dancing load function, you normally pass NULL
+ * for the first and third parameters. Use DSO_up and DSO_free for
+ * subsequent reference count handling. Any flags passed in will be set
+ * in the constructed DSO after its init() function but before the
+ * load operation. If 'dso' is non-NULL, 'flags' is ignored. */
+DSO *DSO_load(DSO *dso, const char *filename, DSO_METHOD *meth, int flags);
+
+/* This function binds to a variable inside a shared library. */
+void *DSO_bind_var(DSO *dso, const char *symname);
+
+/* This function binds to a function inside a shared library. */
+DSO_FUNC_TYPE DSO_bind_func(DSO *dso, const char *symname);
+
+/* This method is the default, but will beg, borrow, or steal whatever
+ * method should be the default on any particular platform (including
+ * DSO_METH_null() if necessary). */
+DSO_METHOD *DSO_METHOD_openssl(void);
+
+/* This method is defined for all platforms - if a platform has no
+ * DSO support then this will be the only method! */
+DSO_METHOD *DSO_METHOD_null(void);
+
+/* If DSO_DLFCN is defined, the standard dlfcn.h-style functions
+ * (dlopen, dlclose, dlsym, etc) will be used and incorporated into
+ * this method. If not, this method will return NULL. */
+DSO_METHOD *DSO_METHOD_dlfcn(void);
+
+/* If DSO_DL is defined, the standard dl.h-style functions (shl_load, 
+ * shl_unload, shl_findsym, etc) will be used and incorporated into
+ * this method. If not, this method will return NULL. */
+DSO_METHOD *DSO_METHOD_dl(void);
+
+/* If WIN32 is defined, use DLLs. If not, return NULL. */
+DSO_METHOD *DSO_METHOD_win32(void);
+
+/* If VMS is defined, use shared images. If not, return NULL. */
+DSO_METHOD *DSO_METHOD_vms(void);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_DSO_strings(void);
+
+/* Error codes for the DSO functions. */
+
+/* Function codes. */
+#define DSO_F_DLFCN_BIND_FUNC				 100
+#define DSO_F_DLFCN_BIND_VAR				 101
+#define DSO_F_DLFCN_LOAD				 102
+#define DSO_F_DLFCN_MERGER				 130
+#define DSO_F_DLFCN_NAME_CONVERTER			 123
+#define DSO_F_DLFCN_UNLOAD				 103
+#define DSO_F_DL_BIND_FUNC				 104
+#define DSO_F_DL_BIND_VAR				 105
+#define DSO_F_DL_LOAD					 106
+#define DSO_F_DL_MERGER					 131
+#define DSO_F_DL_NAME_CONVERTER				 124
+#define DSO_F_DL_UNLOAD					 107
+#define DSO_F_DSO_BIND_FUNC				 108
+#define DSO_F_DSO_BIND_VAR				 109
+#define DSO_F_DSO_CONVERT_FILENAME			 126
+#define DSO_F_DSO_CTRL					 110
+#define DSO_F_DSO_FREE					 111
+#define DSO_F_DSO_GET_FILENAME				 127
+#define DSO_F_DSO_GET_LOADED_FILENAME			 128
+#define DSO_F_DSO_LOAD					 112
+#define DSO_F_DSO_MERGE					 132
+#define DSO_F_DSO_NEW_METHOD				 113
+#define DSO_F_DSO_SET_FILENAME				 129
+#define DSO_F_DSO_SET_NAME_CONVERTER			 122
+#define DSO_F_DSO_UP_REF				 114
+#define DSO_F_VMS_BIND_SYM				 115
+#define DSO_F_VMS_LOAD					 116
+#define DSO_F_VMS_MERGER				 133
+#define DSO_F_VMS_UNLOAD				 117
+#define DSO_F_WIN32_BIND_FUNC				 118
+#define DSO_F_WIN32_BIND_VAR				 119
+#define DSO_F_WIN32_JOINER				 135
+#define DSO_F_WIN32_LOAD				 120
+#define DSO_F_WIN32_MERGER				 134
+#define DSO_F_WIN32_NAME_CONVERTER			 125
+#define DSO_F_WIN32_SPLITTER				 136
+#define DSO_F_WIN32_UNLOAD				 121
+
+/* Reason codes. */
+#define DSO_R_CTRL_FAILED				 100
+#define DSO_R_DSO_ALREADY_LOADED			 110
+#define DSO_R_EMPTY_FILE_STRUCTURE			 113
+#define DSO_R_FAILURE					 114
+#define DSO_R_FILENAME_TOO_BIG				 101
+#define DSO_R_FINISH_FAILED				 102
+#define DSO_R_INCORRECT_FILE_SYNTAX			 115
+#define DSO_R_LOAD_FAILED				 103
+#define DSO_R_NAME_TRANSLATION_FAILED			 109
+#define DSO_R_NO_FILENAME				 111
+#define DSO_R_NO_FILE_SPECIFICATION			 116
+#define DSO_R_NULL_HANDLE				 104
+#define DSO_R_SET_FILENAME_FAILED			 112
+#define DSO_R_STACK_ERROR				 105
+#define DSO_R_SYM_FAILURE				 106
+#define DSO_R_UNLOAD_FAILED				 107
+#define DSO_R_UNSUPPORTED				 108
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/dep/include/openssl/dtls1.h b/dep/include/openssl/dtls1.h
new file mode 100644
index 00000000000..b377cc5f6b2
--- /dev/null
+++ b/dep/include/openssl/dtls1.h
@@ -0,0 +1,212 @@
+/* ssl/dtls1.h */
+/* 
+ * DTLS implementation written by Nagendra Modadugu
+ * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.  
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_DTLS1_H 
+#define HEADER_DTLS1_H 
+
+#include 
+#include 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#define DTLS1_VERSION			0x0100
+#define DTLS1_VERSION_MAJOR		0x01
+#define DTLS1_VERSION_MINOR		0x00
+
+#define DTLS1_AD_MISSING_HANDSHAKE_MESSAGE    110
+
+/* lengths of messages */
+#define DTLS1_COOKIE_LENGTH                     32
+
+#define DTLS1_RT_HEADER_LENGTH                  13
+
+#define DTLS1_HM_HEADER_LENGTH                  12
+
+#define DTLS1_HM_BAD_FRAGMENT                   -2
+#define DTLS1_HM_FRAGMENT_RETRY                 -3
+
+#define DTLS1_CCS_HEADER_LENGTH                  3
+
+#define DTLS1_AL_HEADER_LENGTH                   7
+
+
+typedef struct dtls1_bitmap_st
+	{
+	PQ_64BIT map;
+	unsigned long length;     /* sizeof the bitmap in bits */
+	PQ_64BIT max_seq_num;  /* max record number seen so far */
+	} DTLS1_BITMAP;
+
+struct hm_header_st
+	{
+	unsigned char type;
+	unsigned long msg_len;
+	unsigned short seq;
+	unsigned long frag_off;
+	unsigned long frag_len;
+	unsigned int is_ccs;
+	};
+
+struct ccs_header_st
+	{
+	unsigned char type;
+	unsigned short seq;
+	};
+
+struct dtls1_timeout_st
+	{
+	/* Number of read timeouts so far */
+	unsigned int read_timeouts;
+	
+	/* Number of write timeouts so far */
+	unsigned int write_timeouts;
+	
+	/* Number of alerts received so far */
+	unsigned int num_alerts;
+	};
+
+typedef struct record_pqueue_st
+	{
+	unsigned short epoch;
+	pqueue q;
+	} record_pqueue;
+
+typedef struct hm_fragment_st
+	{
+	struct hm_header_st msg_header;
+	unsigned char *fragment;
+	} hm_fragment;
+
+typedef struct dtls1_state_st
+	{
+	unsigned int send_cookie;
+	unsigned char cookie[DTLS1_COOKIE_LENGTH];
+	unsigned char rcvd_cookie[DTLS1_COOKIE_LENGTH];
+	unsigned int cookie_len;
+
+	/* 
+	 * The current data and handshake epoch.  This is initially
+	 * undefined, and starts at zero once the initial handshake is
+	 * completed 
+	 */
+	unsigned short r_epoch;
+	unsigned short w_epoch;
+
+	/* records being received in the current epoch */
+	DTLS1_BITMAP bitmap;
+
+	/* renegotiation starts a new set of sequence numbers */
+	DTLS1_BITMAP next_bitmap;
+
+	/* handshake message numbers */
+	unsigned short handshake_write_seq;
+	unsigned short next_handshake_write_seq;
+
+	unsigned short handshake_read_seq;
+
+	/* Received handshake records (processed and unprocessed) */
+	record_pqueue unprocessed_rcds;
+	record_pqueue processed_rcds;
+
+	/* Buffered handshake messages */
+	pqueue buffered_messages;
+
+	/* Buffered (sent) handshake records */
+	pqueue sent_messages;
+
+	unsigned int mtu; /* max wire packet size */
+
+	struct hm_header_st w_msg_hdr;
+	struct hm_header_st r_msg_hdr;
+
+	struct dtls1_timeout_st timeout;
+	
+	/* storage for Alert/Handshake protocol data received but not
+	 * yet processed by ssl3_read_bytes: */
+	unsigned char alert_fragment[DTLS1_AL_HEADER_LENGTH];
+	unsigned int alert_fragment_len;
+	unsigned char handshake_fragment[DTLS1_HM_HEADER_LENGTH];
+	unsigned int handshake_fragment_len;
+
+	unsigned int retransmitting;
+
+	} DTLS1_STATE;
+
+typedef struct dtls1_record_data_st
+	{
+	unsigned char *packet;
+	unsigned int   packet_length;
+	SSL3_BUFFER    rbuf;
+	SSL3_RECORD    rrec;
+	} DTLS1_RECORD_DATA;
+
+
+/* Timeout multipliers (timeout slice is defined in apps/timeouts.h */
+#define DTLS1_TMO_READ_COUNT                      2
+#define DTLS1_TMO_WRITE_COUNT                     2
+
+#define DTLS1_TMO_ALERT_COUNT                     12
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
+
diff --git a/dep/include/openssl/e_os2.h b/dep/include/openssl/e_os2.h
new file mode 100644
index 00000000000..9da0b654481
--- /dev/null
+++ b/dep/include/openssl/e_os2.h
@@ -0,0 +1,279 @@
+/* e_os2.h */
+/* ====================================================================
+ * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#ifndef HEADER_E_OS2_H
+#define HEADER_E_OS2_H
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************
+ * Detect operating systems.  This probably needs completing.
+ * The result is that at least one OPENSSL_SYS_os macro should be defined.
+ * However, if none is defined, Unix is assumed.
+ **/
+
+#define OPENSSL_SYS_UNIX
+
+/* ----------------------- Macintosh, before MacOS X ----------------------- */
+#if defined(__MWERKS__) && defined(macintosh) || defined(OPENSSL_SYSNAME_MAC)
+# undef OPENSSL_SYS_UNIX
+# define OPENSSL_SYS_MACINTOSH_CLASSIC
+#endif
+
+/* ----------------------- NetWare ----------------------------------------- */
+#if defined(NETWARE) || defined(OPENSSL_SYSNAME_NETWARE)
+# undef OPENSSL_SYS_UNIX
+# define OPENSSL_SYS_NETWARE
+#endif
+
+/* ---------------------- Microsoft operating systems ---------------------- */
+
+/* Note that MSDOS actually denotes 32-bit environments running on top of
+   MS-DOS, such as DJGPP one. */
+#if defined(OPENSSL_SYSNAME_MSDOS)
+# undef OPENSSL_SYS_UNIX
+# define OPENSSL_SYS_MSDOS
+#endif
+
+/* For 32 bit environment, there seems to be the CygWin environment and then
+   all the others that try to do the same thing Microsoft does... */
+#if defined(OPENSSL_SYSNAME_UWIN)
+# undef OPENSSL_SYS_UNIX
+# define OPENSSL_SYS_WIN32_UWIN
+#else
+# if defined(__CYGWIN32__) || defined(OPENSSL_SYSNAME_CYGWIN32)
+#  undef OPENSSL_SYS_UNIX
+#  define OPENSSL_SYS_WIN32_CYGWIN
+# else
+#  if defined(_WIN32) || defined(OPENSSL_SYSNAME_WIN32)
+#   undef OPENSSL_SYS_UNIX
+#   define OPENSSL_SYS_WIN32
+#  endif
+#  if defined(OPENSSL_SYSNAME_WINNT)
+#   undef OPENSSL_SYS_UNIX
+#   define OPENSSL_SYS_WINNT
+#  endif
+#  if defined(OPENSSL_SYSNAME_WINCE)
+#   undef OPENSSL_SYS_UNIX
+#   define OPENSSL_SYS_WINCE
+#  endif
+# endif
+#endif
+
+/* Anything that tries to look like Microsoft is "Windows" */
+#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WINNT) || defined(OPENSSL_SYS_WINCE)
+# undef OPENSSL_SYS_UNIX
+# define OPENSSL_SYS_WINDOWS
+# ifndef OPENSSL_SYS_MSDOS
+#  define OPENSSL_SYS_MSDOS
+# endif
+#endif
+
+/* DLL settings.  This part is a bit tough, because it's up to the application
+   implementor how he or she will link the application, so it requires some
+   macro to be used. */
+#ifdef OPENSSL_SYS_WINDOWS
+# ifndef OPENSSL_OPT_WINDLL
+#  if defined(_WINDLL) /* This is used when building OpenSSL to indicate that
+                          DLL linkage should be used */
+#   define OPENSSL_OPT_WINDLL
+#  endif
+# endif
+#endif
+
+/* -------------------------------- OpenVMS -------------------------------- */
+#if defined(__VMS) || defined(VMS) || defined(OPENSSL_SYSNAME_VMS)
+# undef OPENSSL_SYS_UNIX
+# define OPENSSL_SYS_VMS
+# if defined(__DECC)
+#  define OPENSSL_SYS_VMS_DECC
+# elif defined(__DECCXX)
+#  define OPENSSL_SYS_VMS_DECC
+#  define OPENSSL_SYS_VMS_DECCXX
+# else
+#  define OPENSSL_SYS_VMS_NODECC
+# endif
+#endif
+
+/* --------------------------------- OS/2 ---------------------------------- */
+#if defined(__EMX__) || defined(__OS2__)
+# undef OPENSSL_SYS_UNIX
+# define OPENSSL_SYS_OS2
+#endif
+
+/* --------------------------------- Unix ---------------------------------- */
+#ifdef OPENSSL_SYS_UNIX
+# if defined(linux) || defined(__linux__) || defined(OPENSSL_SYSNAME_LINUX)
+#  define OPENSSL_SYS_LINUX
+# endif
+# ifdef OPENSSL_SYSNAME_MPE
+#  define OPENSSL_SYS_MPE
+# endif
+# ifdef OPENSSL_SYSNAME_SNI
+#  define OPENSSL_SYS_SNI
+# endif
+# ifdef OPENSSL_SYSNAME_ULTRASPARC
+#  define OPENSSL_SYS_ULTRASPARC
+# endif
+# ifdef OPENSSL_SYSNAME_NEWS4
+#  define OPENSSL_SYS_NEWS4
+# endif
+# ifdef OPENSSL_SYSNAME_MACOSX
+#  define OPENSSL_SYS_MACOSX
+# endif
+# ifdef OPENSSL_SYSNAME_MACOSX_RHAPSODY
+#  define OPENSSL_SYS_MACOSX_RHAPSODY
+#  define OPENSSL_SYS_MACOSX
+# endif
+# ifdef OPENSSL_SYSNAME_SUNOS
+#  define OPENSSL_SYS_SUNOS
+#endif
+# if defined(_CRAY) || defined(OPENSSL_SYSNAME_CRAY)
+#  define OPENSSL_SYS_CRAY
+# endif
+# if defined(_AIX) || defined(OPENSSL_SYSNAME_AIX)
+#  define OPENSSL_SYS_AIX
+# endif
+#endif
+
+/* --------------------------------- VOS ----------------------------------- */
+#ifdef OPENSSL_SYSNAME_VOS
+# define OPENSSL_SYS_VOS
+#endif
+
+/* ------------------------------- VxWorks --------------------------------- */
+#ifdef OPENSSL_SYSNAME_VXWORKS
+# define OPENSSL_SYS_VXWORKS
+#endif
+
+/**
+ * That's it for OS-specific stuff
+ *****************************************************************************/
+
+
+/* Specials for I/O an exit */
+#ifdef OPENSSL_SYS_MSDOS
+# define OPENSSL_UNISTD_IO 
+# define OPENSSL_DECLARE_EXIT extern void exit(int);
+#else
+# define OPENSSL_UNISTD_IO OPENSSL_UNISTD
+# define OPENSSL_DECLARE_EXIT /* declared in unistd.h */
+#endif
+
+/* Definitions of OPENSSL_GLOBAL and OPENSSL_EXTERN, to define and declare
+   certain global symbols that, with some compilers under VMS, have to be
+   defined and declared explicitely with globaldef and globalref.
+   Definitions of OPENSSL_EXPORT and OPENSSL_IMPORT, to define and declare
+   DLL exports and imports for compilers under Win32.  These are a little
+   more complicated to use.  Basically, for any library that exports some
+   global variables, the following code must be present in the header file
+   that declares them, before OPENSSL_EXTERN is used:
+
+   #ifdef SOME_BUILD_FLAG_MACRO
+   # undef OPENSSL_EXTERN
+   # define OPENSSL_EXTERN OPENSSL_EXPORT
+   #endif
+
+   The default is to have OPENSSL_EXPORT, OPENSSL_IMPORT and OPENSSL_GLOBAL
+   have some generally sensible values, and for OPENSSL_EXTERN to have the
+   value OPENSSL_IMPORT.
+*/
+
+#if defined(OPENSSL_SYS_VMS_NODECC)
+# define OPENSSL_EXPORT globalref
+# define OPENSSL_IMPORT globalref
+# define OPENSSL_GLOBAL globaldef
+#elif defined(OPENSSL_SYS_WINDOWS) && defined(OPENSSL_OPT_WINDLL)
+# define OPENSSL_EXPORT extern __declspec(dllexport)
+# define OPENSSL_IMPORT extern __declspec(dllimport)
+# define OPENSSL_GLOBAL
+#else
+# define OPENSSL_EXPORT extern
+# define OPENSSL_IMPORT extern
+# define OPENSSL_GLOBAL
+#endif
+#define OPENSSL_EXTERN OPENSSL_IMPORT
+
+/* Macros to allow global variables to be reached through function calls when
+   required (if a shared library version requvres it, for example.
+   The way it's done allows definitions like this:
+
+	// in foobar.c
+	OPENSSL_IMPLEMENT_GLOBAL(int,foobar) = 0;
+	// in foobar.h
+	OPENSSL_DECLARE_GLOBAL(int,foobar);
+	#define foobar OPENSSL_GLOBAL_REF(foobar)
+*/
+#ifdef OPENSSL_EXPORT_VAR_AS_FUNCTION
+# define OPENSSL_IMPLEMENT_GLOBAL(type,name)			     \
+	extern type _hide_##name;				     \
+	type *_shadow_##name(void) { return &_hide_##name; }	     \
+	static type _hide_##name
+# define OPENSSL_DECLARE_GLOBAL(type,name) type *_shadow_##name(void)
+# define OPENSSL_GLOBAL_REF(name) (*(_shadow_##name()))
+#else
+# define OPENSSL_IMPLEMENT_GLOBAL(type,name) OPENSSL_GLOBAL type _shadow_##name
+# define OPENSSL_DECLARE_GLOBAL(type,name) OPENSSL_EXPORT type _shadow_##name
+# define OPENSSL_GLOBAL_REF(name) _shadow_##name
+#endif
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/dep/include/openssl/ebcdic.h b/dep/include/openssl/ebcdic.h
new file mode 100644
index 00000000000..6d65afcf9e7
--- /dev/null
+++ b/dep/include/openssl/ebcdic.h
@@ -0,0 +1,19 @@
+/* crypto/ebcdic.h */
+
+#ifndef HEADER_EBCDIC_H
+#define HEADER_EBCDIC_H
+
+#include 
+
+/* Avoid name clashes with other applications */
+#define os_toascii   _openssl_os_toascii
+#define os_toebcdic  _openssl_os_toebcdic
+#define ebcdic2ascii _openssl_ebcdic2ascii
+#define ascii2ebcdic _openssl_ascii2ebcdic
+
+extern const unsigned char os_toascii[256];
+extern const unsigned char os_toebcdic[256];
+void *ebcdic2ascii(void *dest, const void *srce, size_t count);
+void *ascii2ebcdic(void *dest, const void *srce, size_t count);
+
+#endif
diff --git a/dep/include/openssl/ec.h b/dep/include/openssl/ec.h
new file mode 100644
index 00000000000..3c96fbd0d86
--- /dev/null
+++ b/dep/include/openssl/ec.h
@@ -0,0 +1,525 @@
+/* crypto/ec/ec.h */
+/*
+ * Originally written by Bodo Moeller for the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * Portions of the attached software ("Contribution") are developed by 
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the OpenSSL open source
+ * license provided above.
+ *
+ * The elliptic curve binary polynomial software is originally written by 
+ * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
+ *
+ */
+
+#ifndef HEADER_EC_H
+#define HEADER_EC_H
+
+#include 
+
+#ifdef OPENSSL_NO_EC
+#error EC is disabled.
+#endif
+
+#include 
+#include 
+#ifndef OPENSSL_NO_DEPRECATED
+#include 
+#endif
+
+#ifdef  __cplusplus
+extern "C" {
+#elif defined(__SUNPRO_C)
+# if __SUNPRO_C >= 0x520
+# pragma error_messages (off,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE)
+# endif
+#endif
+
+
+#ifndef OPENSSL_ECC_MAX_FIELD_BITS
+# define OPENSSL_ECC_MAX_FIELD_BITS 661
+#endif
+
+typedef enum {
+	/* values as defined in X9.62 (ECDSA) and elsewhere */
+	POINT_CONVERSION_COMPRESSED = 2,
+	POINT_CONVERSION_UNCOMPRESSED = 4,
+	POINT_CONVERSION_HYBRID = 6
+} point_conversion_form_t;
+
+
+typedef struct ec_method_st EC_METHOD;
+
+typedef struct ec_group_st
+	/*
+	 EC_METHOD *meth;
+	 -- field definition
+	 -- curve coefficients
+	 -- optional generator with associated information (order, cofactor)
+	 -- optional extra data (precomputed table for fast computation of multiples of generator)
+	 -- ASN1 stuff
+	*/
+	EC_GROUP;
+
+typedef struct ec_point_st EC_POINT;
+
+
+/* EC_METHODs for curves over GF(p).
+ * EC_GFp_simple_method provides the basis for the optimized methods.
+ */
+const EC_METHOD *EC_GFp_simple_method(void);
+const EC_METHOD *EC_GFp_mont_method(void);
+const EC_METHOD *EC_GFp_nist_method(void);
+
+/* EC_METHOD for curves over GF(2^m).
+ */
+const EC_METHOD *EC_GF2m_simple_method(void);
+
+
+EC_GROUP *EC_GROUP_new(const EC_METHOD *);
+void EC_GROUP_free(EC_GROUP *);
+void EC_GROUP_clear_free(EC_GROUP *);
+int EC_GROUP_copy(EC_GROUP *, const EC_GROUP *);
+EC_GROUP *EC_GROUP_dup(const EC_GROUP *);
+
+const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *);
+int EC_METHOD_get_field_type(const EC_METHOD *);
+
+int EC_GROUP_set_generator(EC_GROUP *, const EC_POINT *generator, const BIGNUM *order, const BIGNUM *cofactor);
+const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *);
+int EC_GROUP_get_order(const EC_GROUP *, BIGNUM *order, BN_CTX *);
+int EC_GROUP_get_cofactor(const EC_GROUP *, BIGNUM *cofactor, BN_CTX *);
+
+void EC_GROUP_set_curve_name(EC_GROUP *, int nid);
+int EC_GROUP_get_curve_name(const EC_GROUP *);
+
+void EC_GROUP_set_asn1_flag(EC_GROUP *, int flag);
+int EC_GROUP_get_asn1_flag(const EC_GROUP *);
+
+void EC_GROUP_set_point_conversion_form(EC_GROUP *, point_conversion_form_t);
+point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP *);
+
+unsigned char *EC_GROUP_get0_seed(const EC_GROUP *);
+size_t EC_GROUP_get_seed_len(const EC_GROUP *);
+size_t EC_GROUP_set_seed(EC_GROUP *, const unsigned char *, size_t len);
+
+int EC_GROUP_set_curve_GFp(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
+int EC_GROUP_get_curve_GFp(const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *);
+int EC_GROUP_set_curve_GF2m(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
+int EC_GROUP_get_curve_GF2m(const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *);
+
+/* returns the number of bits needed to represent a field element */
+int EC_GROUP_get_degree(const EC_GROUP *);
+
+/* EC_GROUP_check() returns 1 if 'group' defines a valid group, 0 otherwise */
+int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx);
+/* EC_GROUP_check_discriminant() returns 1 if the discriminant of the
+ * elliptic curve is not zero, 0 otherwise */
+int EC_GROUP_check_discriminant(const EC_GROUP *, BN_CTX *);
+
+/* EC_GROUP_cmp() returns 0 if both groups are equal and 1 otherwise */
+int EC_GROUP_cmp(const EC_GROUP *, const EC_GROUP *, BN_CTX *);
+
+/* EC_GROUP_new_GF*() calls EC_GROUP_new() and EC_GROUP_set_GF*()
+ * after choosing an appropriate EC_METHOD */
+EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
+EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
+
+/* EC_GROUP_new_by_curve_name() creates a EC_GROUP structure
+ * specified by a curve name (in form of a NID) */
+EC_GROUP *EC_GROUP_new_by_curve_name(int nid);
+/* handling of internal curves */
+typedef struct { 
+	int nid;
+	const char *comment;
+	} EC_builtin_curve;
+/* EC_builtin_curves(EC_builtin_curve *r, size_t size) returns number 
+ * of all available curves or zero if a error occurred. 
+ * In case r ist not zero nitems EC_builtin_curve structures 
+ * are filled with the data of the first nitems internal groups */
+size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems);
+
+
+/* EC_POINT functions */
+
+EC_POINT *EC_POINT_new(const EC_GROUP *);
+void EC_POINT_free(EC_POINT *);
+void EC_POINT_clear_free(EC_POINT *);
+int EC_POINT_copy(EC_POINT *, const EC_POINT *);
+EC_POINT *EC_POINT_dup(const EC_POINT *, const EC_GROUP *);
+ 
+const EC_METHOD *EC_POINT_method_of(const EC_POINT *);
+
+int EC_POINT_set_to_infinity(const EC_GROUP *, EC_POINT *);
+int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *, EC_POINT *,
+	const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *);
+int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *, const EC_POINT *,
+	BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *);
+int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *, EC_POINT *,
+	const BIGNUM *x, const BIGNUM *y, BN_CTX *);
+int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *, const EC_POINT *,
+	BIGNUM *x, BIGNUM *y, BN_CTX *);
+int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *, EC_POINT *,
+	const BIGNUM *x, int y_bit, BN_CTX *);
+
+int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *, EC_POINT *,
+	const BIGNUM *x, const BIGNUM *y, BN_CTX *);
+int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *, const EC_POINT *,
+	BIGNUM *x, BIGNUM *y, BN_CTX *);
+int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *, EC_POINT *,
+	const BIGNUM *x, int y_bit, BN_CTX *);
+
+size_t EC_POINT_point2oct(const EC_GROUP *, const EC_POINT *, point_conversion_form_t form,
+        unsigned char *buf, size_t len, BN_CTX *);
+int EC_POINT_oct2point(const EC_GROUP *, EC_POINT *,
+        const unsigned char *buf, size_t len, BN_CTX *);
+
+/* other interfaces to point2oct/oct2point: */
+BIGNUM *EC_POINT_point2bn(const EC_GROUP *, const EC_POINT *,
+	point_conversion_form_t form, BIGNUM *, BN_CTX *);
+EC_POINT *EC_POINT_bn2point(const EC_GROUP *, const BIGNUM *,
+	EC_POINT *, BN_CTX *);
+char *EC_POINT_point2hex(const EC_GROUP *, const EC_POINT *,
+	point_conversion_form_t form, BN_CTX *);
+EC_POINT *EC_POINT_hex2point(const EC_GROUP *, const char *,
+	EC_POINT *, BN_CTX *);
+
+int EC_POINT_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *);
+int EC_POINT_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, BN_CTX *);
+int EC_POINT_invert(const EC_GROUP *, EC_POINT *, BN_CTX *);
+
+int EC_POINT_is_at_infinity(const EC_GROUP *, const EC_POINT *);
+int EC_POINT_is_on_curve(const EC_GROUP *, const EC_POINT *, BN_CTX *);
+int EC_POINT_cmp(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b, BN_CTX *);
+
+int EC_POINT_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *);
+int EC_POINTs_make_affine(const EC_GROUP *, size_t num, EC_POINT *[], BN_CTX *);
+
+
+int EC_POINTs_mul(const EC_GROUP *, EC_POINT *r, const BIGNUM *, size_t num, const EC_POINT *[], const BIGNUM *[], BN_CTX *);
+int EC_POINT_mul(const EC_GROUP *, EC_POINT *r, const BIGNUM *, const EC_POINT *, const BIGNUM *, BN_CTX *);
+
+/* EC_GROUP_precompute_mult() stores multiples of generator for faster point multiplication */
+int EC_GROUP_precompute_mult(EC_GROUP *, BN_CTX *);
+/* EC_GROUP_have_precompute_mult() reports whether such precomputation has been done */
+int EC_GROUP_have_precompute_mult(const EC_GROUP *);
+
+
+
+/* ASN1 stuff */
+
+/* EC_GROUP_get_basis_type() returns the NID of the basis type
+ * used to represent the field elements */
+int EC_GROUP_get_basis_type(const EC_GROUP *);
+int EC_GROUP_get_trinomial_basis(const EC_GROUP *, unsigned int *k);
+int EC_GROUP_get_pentanomial_basis(const EC_GROUP *, unsigned int *k1, 
+	unsigned int *k2, unsigned int *k3);
+
+#define OPENSSL_EC_NAMED_CURVE	0x001
+
+typedef struct ecpk_parameters_st ECPKPARAMETERS;
+
+EC_GROUP *d2i_ECPKParameters(EC_GROUP **, const unsigned char **in, long len);
+int i2d_ECPKParameters(const EC_GROUP *, unsigned char **out);
+
+#define d2i_ECPKParameters_bio(bp,x) ASN1_d2i_bio_of(EC_GROUP,NULL,d2i_ECPKParameters,bp,x)
+#define i2d_ECPKParameters_bio(bp,x) ASN1_i2d_bio_of_const(EC_GROUP,i2d_ECPKParameters,bp,x)
+#define d2i_ECPKParameters_fp(fp,x) (EC_GROUP *)ASN1_d2i_fp(NULL, \
+                (char *(*)())d2i_ECPKParameters,(fp),(unsigned char **)(x))
+#define i2d_ECPKParameters_fp(fp,x) ASN1_i2d_fp(i2d_ECPKParameters,(fp), \
+		(unsigned char *)(x))
+
+#ifndef OPENSSL_NO_BIO
+int     ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off);
+#endif
+#ifndef OPENSSL_NO_FP_API
+int     ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off);
+#endif
+
+/* the EC_KEY stuff */
+typedef struct ec_key_st EC_KEY;
+
+/* some values for the encoding_flag */
+#define EC_PKEY_NO_PARAMETERS	0x001
+#define EC_PKEY_NO_PUBKEY	0x002
+
+EC_KEY *EC_KEY_new(void);
+EC_KEY *EC_KEY_new_by_curve_name(int nid);
+void EC_KEY_free(EC_KEY *);
+EC_KEY *EC_KEY_copy(EC_KEY *, const EC_KEY *);
+EC_KEY *EC_KEY_dup(const EC_KEY *);
+
+int EC_KEY_up_ref(EC_KEY *);
+
+const EC_GROUP *EC_KEY_get0_group(const EC_KEY *);
+int EC_KEY_set_group(EC_KEY *, const EC_GROUP *);
+const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *);
+int EC_KEY_set_private_key(EC_KEY *, const BIGNUM *);
+const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *);
+int EC_KEY_set_public_key(EC_KEY *, const EC_POINT *);
+unsigned EC_KEY_get_enc_flags(const EC_KEY *);
+void EC_KEY_set_enc_flags(EC_KEY *, unsigned int);
+point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *);
+void EC_KEY_set_conv_form(EC_KEY *, point_conversion_form_t);
+/* functions to set/get method specific data  */
+void *EC_KEY_get_key_method_data(EC_KEY *, 
+	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *));
+void EC_KEY_insert_key_method_data(EC_KEY *, void *data,
+	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *));
+/* wrapper functions for the underlying EC_GROUP object */
+void EC_KEY_set_asn1_flag(EC_KEY *, int);
+int EC_KEY_precompute_mult(EC_KEY *, BN_CTX *ctx);
+
+/* EC_KEY_generate_key() creates a ec private (public) key */
+int EC_KEY_generate_key(EC_KEY *);
+/* EC_KEY_check_key() */
+int EC_KEY_check_key(const EC_KEY *);
+
+/* de- and encoding functions for SEC1 ECPrivateKey */
+EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len);
+int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out);
+/* de- and encoding functions for EC parameters */
+EC_KEY *d2i_ECParameters(EC_KEY **a, const unsigned char **in, long len);
+int i2d_ECParameters(EC_KEY *a, unsigned char **out);
+/* de- and encoding functions for EC public key
+ * (octet string, not DER -- hence 'o2i' and 'i2o') */
+EC_KEY *o2i_ECPublicKey(EC_KEY **a, const unsigned char **in, long len);
+int i2o_ECPublicKey(EC_KEY *a, unsigned char **out);
+
+#ifndef OPENSSL_NO_BIO
+int	ECParameters_print(BIO *bp, const EC_KEY *x);
+int	EC_KEY_print(BIO *bp, const EC_KEY *x, int off);
+#endif
+#ifndef OPENSSL_NO_FP_API
+int	ECParameters_print_fp(FILE *fp, const EC_KEY *x);
+int	EC_KEY_print_fp(FILE *fp, const EC_KEY *x, int off);
+#endif
+
+#define ECParameters_dup(x) ASN1_dup_of(EC_KEY,i2d_ECParameters,d2i_ECParameters,x)
+
+#ifndef __cplusplus
+#if defined(__SUNPRO_C)
+#  if __SUNPRO_C >= 0x520
+# pragma error_messages (default,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE)
+#  endif
+# endif
+#endif
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_EC_strings(void);
+
+/* Error codes for the EC functions. */
+
+/* Function codes. */
+#define EC_F_COMPUTE_WNAF				 143
+#define EC_F_D2I_ECPARAMETERS				 144
+#define EC_F_D2I_ECPKPARAMETERS				 145
+#define EC_F_D2I_ECPRIVATEKEY				 146
+#define EC_F_ECPARAMETERS_PRINT				 147
+#define EC_F_ECPARAMETERS_PRINT_FP			 148
+#define EC_F_ECPKPARAMETERS_PRINT			 149
+#define EC_F_ECPKPARAMETERS_PRINT_FP			 150
+#define EC_F_ECP_NIST_MOD_192				 203
+#define EC_F_ECP_NIST_MOD_224				 204
+#define EC_F_ECP_NIST_MOD_256				 205
+#define EC_F_ECP_NIST_MOD_521				 206
+#define EC_F_EC_ASN1_GROUP2CURVE			 153
+#define EC_F_EC_ASN1_GROUP2FIELDID			 154
+#define EC_F_EC_ASN1_GROUP2PARAMETERS			 155
+#define EC_F_EC_ASN1_GROUP2PKPARAMETERS			 156
+#define EC_F_EC_ASN1_PARAMETERS2GROUP			 157
+#define EC_F_EC_ASN1_PKPARAMETERS2GROUP			 158
+#define EC_F_EC_EX_DATA_SET_DATA			 211
+#define EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY		 208
+#define EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT	 159
+#define EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE		 195
+#define EC_F_EC_GF2M_SIMPLE_OCT2POINT			 160
+#define EC_F_EC_GF2M_SIMPLE_POINT2OCT			 161
+#define EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES 162
+#define EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES 163
+#define EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES	 164
+#define EC_F_EC_GFP_MONT_FIELD_DECODE			 133
+#define EC_F_EC_GFP_MONT_FIELD_ENCODE			 134
+#define EC_F_EC_GFP_MONT_FIELD_MUL			 131
+#define EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE		 209
+#define EC_F_EC_GFP_MONT_FIELD_SQR			 132
+#define EC_F_EC_GFP_MONT_GROUP_SET_CURVE		 189
+#define EC_F_EC_GFP_MONT_GROUP_SET_CURVE_GFP		 135
+#define EC_F_EC_GFP_NIST_FIELD_MUL			 200
+#define EC_F_EC_GFP_NIST_FIELD_SQR			 201
+#define EC_F_EC_GFP_NIST_GROUP_SET_CURVE		 202
+#define EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT	 165
+#define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE		 166
+#define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP		 100
+#define EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR		 101
+#define EC_F_EC_GFP_SIMPLE_MAKE_AFFINE			 102
+#define EC_F_EC_GFP_SIMPLE_OCT2POINT			 103
+#define EC_F_EC_GFP_SIMPLE_POINT2OCT			 104
+#define EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE		 137
+#define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES	 167
+#define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP 105
+#define EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES	 168
+#define EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP 128
+#define EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES	 169
+#define EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP 129
+#define EC_F_EC_GROUP_CHECK				 170
+#define EC_F_EC_GROUP_CHECK_DISCRIMINANT		 171
+#define EC_F_EC_GROUP_COPY				 106
+#define EC_F_EC_GROUP_GET0_GENERATOR			 139
+#define EC_F_EC_GROUP_GET_COFACTOR			 140
+#define EC_F_EC_GROUP_GET_CURVE_GF2M			 172
+#define EC_F_EC_GROUP_GET_CURVE_GFP			 130
+#define EC_F_EC_GROUP_GET_DEGREE			 173
+#define EC_F_EC_GROUP_GET_ORDER				 141
+#define EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS		 193
+#define EC_F_EC_GROUP_GET_TRINOMIAL_BASIS		 194
+#define EC_F_EC_GROUP_NEW				 108
+#define EC_F_EC_GROUP_NEW_BY_CURVE_NAME			 174
+#define EC_F_EC_GROUP_NEW_FROM_DATA			 175
+#define EC_F_EC_GROUP_PRECOMPUTE_MULT			 142
+#define EC_F_EC_GROUP_SET_CURVE_GF2M			 176
+#define EC_F_EC_GROUP_SET_CURVE_GFP			 109
+#define EC_F_EC_GROUP_SET_EXTRA_DATA			 110
+#define EC_F_EC_GROUP_SET_GENERATOR			 111
+#define EC_F_EC_KEY_CHECK_KEY				 177
+#define EC_F_EC_KEY_COPY				 178
+#define EC_F_EC_KEY_GENERATE_KEY			 179
+#define EC_F_EC_KEY_NEW					 182
+#define EC_F_EC_KEY_PRINT				 180
+#define EC_F_EC_KEY_PRINT_FP				 181
+#define EC_F_EC_POINTS_MAKE_AFFINE			 136
+#define EC_F_EC_POINTS_MUL				 138
+#define EC_F_EC_POINT_ADD				 112
+#define EC_F_EC_POINT_CMP				 113
+#define EC_F_EC_POINT_COPY				 114
+#define EC_F_EC_POINT_DBL				 115
+#define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M	 183
+#define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP	 116
+#define EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP	 117
+#define EC_F_EC_POINT_INVERT				 210
+#define EC_F_EC_POINT_IS_AT_INFINITY			 118
+#define EC_F_EC_POINT_IS_ON_CURVE			 119
+#define EC_F_EC_POINT_MAKE_AFFINE			 120
+#define EC_F_EC_POINT_MUL				 184
+#define EC_F_EC_POINT_NEW				 121
+#define EC_F_EC_POINT_OCT2POINT				 122
+#define EC_F_EC_POINT_POINT2OCT				 123
+#define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M	 185
+#define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP	 124
+#define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M	 186
+#define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP	 125
+#define EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP	 126
+#define EC_F_EC_POINT_SET_TO_INFINITY			 127
+#define EC_F_EC_PRE_COMP_DUP				 207
+#define EC_F_EC_WNAF_MUL				 187
+#define EC_F_EC_WNAF_PRECOMPUTE_MULT			 188
+#define EC_F_I2D_ECPARAMETERS				 190
+#define EC_F_I2D_ECPKPARAMETERS				 191
+#define EC_F_I2D_ECPRIVATEKEY				 192
+#define EC_F_I2O_ECPUBLICKEY				 151
+#define EC_F_O2I_ECPUBLICKEY				 152
+
+/* Reason codes. */
+#define EC_R_ASN1_ERROR					 115
+#define EC_R_ASN1_UNKNOWN_FIELD				 116
+#define EC_R_BUFFER_TOO_SMALL				 100
+#define EC_R_D2I_ECPKPARAMETERS_FAILURE			 117
+#define EC_R_DISCRIMINANT_IS_ZERO			 118
+#define EC_R_EC_GROUP_NEW_BY_NAME_FAILURE		 119
+#define EC_R_FIELD_TOO_LARGE				 138
+#define EC_R_GROUP2PKPARAMETERS_FAILURE			 120
+#define EC_R_I2D_ECPKPARAMETERS_FAILURE			 121
+#define EC_R_INCOMPATIBLE_OBJECTS			 101
+#define EC_R_INVALID_ARGUMENT				 112
+#define EC_R_INVALID_COMPRESSED_POINT			 110
+#define EC_R_INVALID_COMPRESSION_BIT			 109
+#define EC_R_INVALID_ENCODING				 102
+#define EC_R_INVALID_FIELD				 103
+#define EC_R_INVALID_FORM				 104
+#define EC_R_INVALID_GROUP_ORDER			 122
+#define EC_R_INVALID_PENTANOMIAL_BASIS			 132
+#define EC_R_INVALID_PRIVATE_KEY			 123
+#define EC_R_INVALID_TRINOMIAL_BASIS			 137
+#define EC_R_MISSING_PARAMETERS				 124
+#define EC_R_MISSING_PRIVATE_KEY			 125
+#define EC_R_NOT_A_NIST_PRIME				 135
+#define EC_R_NOT_A_SUPPORTED_NIST_PRIME			 136
+#define EC_R_NOT_IMPLEMENTED				 126
+#define EC_R_NOT_INITIALIZED				 111
+#define EC_R_NO_FIELD_MOD				 133
+#define EC_R_PASSED_NULL_PARAMETER			 134
+#define EC_R_PKPARAMETERS2GROUP_FAILURE			 127
+#define EC_R_POINT_AT_INFINITY				 106
+#define EC_R_POINT_IS_NOT_ON_CURVE			 107
+#define EC_R_SLOT_FULL					 108
+#define EC_R_UNDEFINED_GENERATOR			 113
+#define EC_R_UNDEFINED_ORDER				 128
+#define EC_R_UNKNOWN_GROUP				 129
+#define EC_R_UNKNOWN_ORDER				 114
+#define EC_R_UNSUPPORTED_FIELD				 131
+#define EC_R_WRONG_ORDER				 130
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/dep/include/openssl/ecdh.h b/dep/include/openssl/ecdh.h
new file mode 100644
index 00000000000..b4b58ee65ba
--- /dev/null
+++ b/dep/include/openssl/ecdh.h
@@ -0,0 +1,123 @@
+/* crypto/ecdh/ecdh.h */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
+ * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
+ * to the OpenSSL project.
+ *
+ * The ECC Code is licensed pursuant to the OpenSSL open source
+ * license provided below.
+ *
+ * The ECDH software is originally written by Douglas Stebila of
+ * Sun Microsystems Laboratories.
+ *
+ */
+/* ====================================================================
+ * Copyright (c) 2000-2002 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+#ifndef HEADER_ECDH_H
+#define HEADER_ECDH_H
+
+#include 
+
+#ifdef OPENSSL_NO_ECDH
+#error ECDH is disabled.
+#endif
+
+#include 
+#include 
+#ifndef OPENSSL_NO_DEPRECATED
+#include 
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const ECDH_METHOD *ECDH_OpenSSL(void);
+
+void	  ECDH_set_default_method(const ECDH_METHOD *);
+const ECDH_METHOD *ECDH_get_default_method(void);
+int 	  ECDH_set_method(EC_KEY *, const ECDH_METHOD *);
+
+int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, EC_KEY *ecdh,
+                     void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen));
+
+int 	  ECDH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new 
+		*new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int 	  ECDH_set_ex_data(EC_KEY *d, int idx, void *arg);
+void 	  *ECDH_get_ex_data(EC_KEY *d, int idx);
+
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_ECDH_strings(void);
+
+/* Error codes for the ECDH functions. */
+
+/* Function codes. */
+#define ECDH_F_ECDH_COMPUTE_KEY				 100
+#define ECDH_F_ECDH_DATA_NEW_METHOD			 101
+
+/* Reason codes. */
+#define ECDH_R_KDF_FAILED				 102
+#define ECDH_R_NO_PRIVATE_VALUE				 100
+#define ECDH_R_POINT_ARITHMETIC_FAILURE			 101
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/dep/include/openssl/ecdsa.h b/dep/include/openssl/ecdsa.h
new file mode 100644
index 00000000000..f20c8ee7381
--- /dev/null
+++ b/dep/include/openssl/ecdsa.h
@@ -0,0 +1,271 @@
+/* crypto/ecdsa/ecdsa.h */
+/**
+ * \file   crypto/ecdsa/ecdsa.h Include file for the OpenSSL ECDSA functions
+ * \author Written by Nils Larsch for the OpenSSL project
+ */
+/* ====================================================================
+ * Copyright (c) 2000-2003 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+#ifndef HEADER_ECDSA_H
+#define HEADER_ECDSA_H
+
+#include 
+
+#ifdef OPENSSL_NO_ECDSA
+#error ECDSA is disabled.
+#endif
+
+#include 
+#include 
+#ifndef OPENSSL_NO_DEPRECATED
+#include 
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct ECDSA_SIG_st
+	{
+	BIGNUM *r;
+	BIGNUM *s;
+	} ECDSA_SIG;
+
+/** ECDSA_SIG *ECDSA_SIG_new(void)
+ * allocates and initialize a ECDSA_SIG structure
+ * \return pointer to a ECDSA_SIG structure or NULL if an error occurred
+ */
+ECDSA_SIG *ECDSA_SIG_new(void);
+
+/** ECDSA_SIG_free
+ * frees a ECDSA_SIG structure
+ * \param a pointer to the ECDSA_SIG structure
+ */
+void	  ECDSA_SIG_free(ECDSA_SIG *a);
+
+/** i2d_ECDSA_SIG
+ * DER encode content of ECDSA_SIG object (note: this function modifies *pp
+ * (*pp += length of the DER encoded signature)).
+ * \param a  pointer to the ECDSA_SIG object
+ * \param pp pointer to a unsigned char pointer for the output or NULL
+ * \return the length of the DER encoded ECDSA_SIG object or 0 
+ */
+int	  i2d_ECDSA_SIG(const ECDSA_SIG *a, unsigned char **pp);
+
+/** d2i_ECDSA_SIG
+ * decodes a DER encoded ECDSA signature (note: this function changes *pp
+ * (*pp += len)). 
+ * \param v pointer to ECDSA_SIG pointer (may be NULL)
+ * \param pp buffer with the DER encoded signature
+ * \param len bufferlength
+ * \return pointer to the decoded ECDSA_SIG structure (or NULL)
+ */
+ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **v, const unsigned char **pp, long len);
+
+/** ECDSA_do_sign
+ * computes the ECDSA signature of the given hash value using
+ * the supplied private key and returns the created signature.
+ * \param dgst pointer to the hash value
+ * \param dgst_len length of the hash value
+ * \param eckey pointer to the EC_KEY object containing a private EC key
+ * \return pointer to a ECDSA_SIG structure or NULL
+ */
+ECDSA_SIG *ECDSA_do_sign(const unsigned char *dgst,int dgst_len,EC_KEY *eckey);
+
+/** ECDSA_do_sign_ex
+ * computes ECDSA signature of a given hash value using the supplied
+ * private key (note: sig must point to ECDSA_size(eckey) bytes of memory).
+ * \param dgst pointer to the hash value to sign
+ * \param dgstlen length of the hash value
+ * \param kinv optional pointer to a pre-computed inverse k
+ * \param rp optional pointer to the pre-computed rp value (see 
+ *        ECDSA_sign_setup
+ * \param eckey pointer to the EC_KEY object containing a private EC key
+ * \return pointer to a ECDSA_SIG structure or NULL
+ */
+ECDSA_SIG *ECDSA_do_sign_ex(const unsigned char *dgst, int dgstlen, 
+		const BIGNUM *kinv, const BIGNUM *rp, EC_KEY *eckey);
+
+/** ECDSA_do_verify
+ * verifies that the supplied signature is a valid ECDSA
+ * signature of the supplied hash value using the supplied public key.
+ * \param dgst pointer to the hash value
+ * \param dgst_len length of the hash value
+ * \param sig  pointer to the ECDSA_SIG structure
+ * \param eckey pointer to the EC_KEY object containing a public EC key
+ * \return 1 if the signature is valid, 0 if the signature is invalid and -1 on error
+ */
+int	  ECDSA_do_verify(const unsigned char *dgst, int dgst_len,
+		const ECDSA_SIG *sig, EC_KEY* eckey);
+
+const ECDSA_METHOD *ECDSA_OpenSSL(void);
+
+/** ECDSA_set_default_method
+ * sets the default ECDSA method
+ * \param meth the new default ECDSA_METHOD
+ */
+void	  ECDSA_set_default_method(const ECDSA_METHOD *meth);
+
+/** ECDSA_get_default_method
+ * returns the default ECDSA method
+ * \return pointer to ECDSA_METHOD structure containing the default method
+ */
+const ECDSA_METHOD *ECDSA_get_default_method(void);
+
+/** ECDSA_set_method
+ * sets method to be used for the ECDSA operations
+ * \param eckey pointer to the EC_KEY object
+ * \param meth  pointer to the new method
+ * \return 1 on success and 0 otherwise 
+ */
+int 	  ECDSA_set_method(EC_KEY *eckey, const ECDSA_METHOD *meth);
+
+/** ECDSA_size
+ * returns the maximum length of the DER encoded signature
+ * \param  eckey pointer to a EC_KEY object
+ * \return numbers of bytes required for the DER encoded signature
+ */
+int	  ECDSA_size(const EC_KEY *eckey);
+
+/** ECDSA_sign_setup
+ * precompute parts of the signing operation. 
+ * \param eckey pointer to the EC_KEY object containing a private EC key
+ * \param ctx  pointer to a BN_CTX object (may be NULL)
+ * \param kinv pointer to a BIGNUM pointer for the inverse of k
+ * \param rp   pointer to a BIGNUM pointer for x coordinate of k * generator
+ * \return 1 on success and 0 otherwise
+ */
+int 	  ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, 
+		BIGNUM **rp);
+
+/** ECDSA_sign
+ * computes ECDSA signature of a given hash value using the supplied
+ * private key (note: sig must point to ECDSA_size(eckey) bytes of memory).
+ * \param type this parameter is ignored
+ * \param dgst pointer to the hash value to sign
+ * \param dgstlen length of the hash value
+ * \param sig buffer to hold the DER encoded signature
+ * \param siglen pointer to the length of the returned signature
+ * \param eckey pointer to the EC_KEY object containing a private EC key
+ * \return 1 on success and 0 otherwise
+ */
+int	  ECDSA_sign(int type, const unsigned char *dgst, int dgstlen, 
+		unsigned char *sig, unsigned int *siglen, EC_KEY *eckey);
+
+
+/** ECDSA_sign_ex
+ * computes ECDSA signature of a given hash value using the supplied
+ * private key (note: sig must point to ECDSA_size(eckey) bytes of memory).
+ * \param type this parameter is ignored
+ * \param dgst pointer to the hash value to sign
+ * \param dgstlen length of the hash value
+ * \param sig buffer to hold the DER encoded signature
+ * \param siglen pointer to the length of the returned signature
+ * \param kinv optional pointer to a pre-computed inverse k
+ * \param rp optional pointer to the pre-computed rp value (see 
+ *        ECDSA_sign_setup
+ * \param eckey pointer to the EC_KEY object containing a private EC key
+ * \return 1 on success and 0 otherwise
+ */
+int	  ECDSA_sign_ex(int type, const unsigned char *dgst, int dgstlen, 
+		unsigned char *sig, unsigned int *siglen, const BIGNUM *kinv,
+		const BIGNUM *rp, EC_KEY *eckey);
+
+/** ECDSA_verify
+ * verifies that the given signature is valid ECDSA signature
+ * of the supplied hash value using the specified public key.
+ * \param type this parameter is ignored
+ * \param dgst pointer to the hash value 
+ * \param dgstlen length of the hash value
+ * \param sig  pointer to the DER encoded signature
+ * \param siglen length of the DER encoded signature
+ * \param eckey pointer to the EC_KEY object containing a public EC key
+ * \return 1 if the signature is valid, 0 if the signature is invalid and -1 on error
+ */
+int 	  ECDSA_verify(int type, const unsigned char *dgst, int dgstlen, 
+		const unsigned char *sig, int siglen, EC_KEY *eckey);
+
+/* the standard ex_data functions */
+int 	  ECDSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new 
+		*new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int 	  ECDSA_set_ex_data(EC_KEY *d, int idx, void *arg);
+void 	  *ECDSA_get_ex_data(EC_KEY *d, int idx);
+
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_ECDSA_strings(void);
+
+/* Error codes for the ECDSA functions. */
+
+/* Function codes. */
+#define ECDSA_F_ECDSA_DATA_NEW_METHOD			 100
+#define ECDSA_F_ECDSA_DO_SIGN				 101
+#define ECDSA_F_ECDSA_DO_VERIFY				 102
+#define ECDSA_F_ECDSA_SIGN_SETUP			 103
+
+/* Reason codes. */
+#define ECDSA_R_BAD_SIGNATURE				 100
+#define ECDSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE		 101
+#define ECDSA_R_ERR_EC_LIB				 102
+#define ECDSA_R_MISSING_PARAMETERS			 103
+#define ECDSA_R_NEED_NEW_SETUP_VALUES			 106
+#define ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED		 104
+#define ECDSA_R_SIGNATURE_MALLOC_FAILED			 105
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/dep/include/openssl/engine.h b/dep/include/openssl/engine.h
new file mode 100644
index 00000000000..3ec59338ffd
--- /dev/null
+++ b/dep/include/openssl/engine.h
@@ -0,0 +1,785 @@
+/* openssl/engine.h */
+/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2004 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECDH support in OpenSSL originally developed by 
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#ifndef HEADER_ENGINE_H
+#define HEADER_ENGINE_H
+
+#include 
+
+#ifdef OPENSSL_NO_ENGINE
+#error ENGINE is disabled.
+#endif
+
+#ifndef OPENSSL_NO_DEPRECATED
+#include 
+#ifndef OPENSSL_NO_RSA
+#include 
+#endif
+#ifndef OPENSSL_NO_DSA
+#include 
+#endif
+#ifndef OPENSSL_NO_DH
+#include 
+#endif
+#ifndef OPENSSL_NO_ECDH
+#include 
+#endif
+#ifndef OPENSSL_NO_ECDSA
+#include 
+#endif
+#include 
+#include 
+#include 
+#include 
+#endif
+
+#include 
+#include 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* These flags are used to control combinations of algorithm (methods)
+ * by bitwise "OR"ing. */
+#define ENGINE_METHOD_RSA		(unsigned int)0x0001
+#define ENGINE_METHOD_DSA		(unsigned int)0x0002
+#define ENGINE_METHOD_DH		(unsigned int)0x0004
+#define ENGINE_METHOD_RAND		(unsigned int)0x0008
+#define ENGINE_METHOD_ECDH		(unsigned int)0x0010
+#define ENGINE_METHOD_ECDSA		(unsigned int)0x0020
+#define ENGINE_METHOD_CIPHERS		(unsigned int)0x0040
+#define ENGINE_METHOD_DIGESTS		(unsigned int)0x0080
+#define ENGINE_METHOD_STORE		(unsigned int)0x0100
+/* Obvious all-or-nothing cases. */
+#define ENGINE_METHOD_ALL		(unsigned int)0xFFFF
+#define ENGINE_METHOD_NONE		(unsigned int)0x0000
+
+/* This(ese) flag(s) controls behaviour of the ENGINE_TABLE mechanism used
+ * internally to control registration of ENGINE implementations, and can be set
+ * by ENGINE_set_table_flags(). The "NOINIT" flag prevents attempts to
+ * initialise registered ENGINEs if they are not already initialised. */
+#define ENGINE_TABLE_FLAG_NOINIT	(unsigned int)0x0001
+
+/* ENGINE flags that can be set by ENGINE_set_flags(). */
+/* #define ENGINE_FLAGS_MALLOCED	0x0001 */ /* Not used */
+
+/* This flag is for ENGINEs that wish to handle the various 'CMD'-related
+ * control commands on their own. Without this flag, ENGINE_ctrl() handles these
+ * control commands on behalf of the ENGINE using their "cmd_defns" data. */
+#define ENGINE_FLAGS_MANUAL_CMD_CTRL	(int)0x0002
+
+/* This flag is for ENGINEs who return new duplicate structures when found via
+ * "ENGINE_by_id()". When an ENGINE must store state (eg. if ENGINE_ctrl()
+ * commands are called in sequence as part of some stateful process like
+ * key-generation setup and execution), it can set this flag - then each attempt
+ * to obtain the ENGINE will result in it being copied into a new structure.
+ * Normally, ENGINEs don't declare this flag so ENGINE_by_id() just increments
+ * the existing ENGINE's structural reference count. */
+#define ENGINE_FLAGS_BY_ID_COPY		(int)0x0004
+
+/* ENGINEs can support their own command types, and these flags are used in
+ * ENGINE_CTRL_GET_CMD_FLAGS to indicate to the caller what kind of input each
+ * command expects. Currently only numeric and string input is supported. If a
+ * control command supports none of the _NUMERIC, _STRING, or _NO_INPUT options,
+ * then it is regarded as an "internal" control command - and not for use in
+ * config setting situations. As such, they're not available to the
+ * ENGINE_ctrl_cmd_string() function, only raw ENGINE_ctrl() access. Changes to
+ * this list of 'command types' should be reflected carefully in
+ * ENGINE_cmd_is_executable() and ENGINE_ctrl_cmd_string(). */
+
+/* accepts a 'long' input value (3rd parameter to ENGINE_ctrl) */
+#define ENGINE_CMD_FLAG_NUMERIC		(unsigned int)0x0001
+/* accepts string input (cast from 'void*' to 'const char *', 4th parameter to
+ * ENGINE_ctrl) */
+#define ENGINE_CMD_FLAG_STRING		(unsigned int)0x0002
+/* Indicates that the control command takes *no* input. Ie. the control command
+ * is unparameterised. */
+#define ENGINE_CMD_FLAG_NO_INPUT	(unsigned int)0x0004
+/* Indicates that the control command is internal. This control command won't
+ * be shown in any output, and is only usable through the ENGINE_ctrl_cmd()
+ * function. */
+#define ENGINE_CMD_FLAG_INTERNAL	(unsigned int)0x0008
+
+/* NB: These 3 control commands are deprecated and should not be used. ENGINEs
+ * relying on these commands should compile conditional support for
+ * compatibility (eg. if these symbols are defined) but should also migrate the
+ * same functionality to their own ENGINE-specific control functions that can be
+ * "discovered" by calling applications. The fact these control commands
+ * wouldn't be "executable" (ie. usable by text-based config) doesn't change the
+ * fact that application code can find and use them without requiring per-ENGINE
+ * hacking. */
+
+/* These flags are used to tell the ctrl function what should be done.
+ * All command numbers are shared between all engines, even if some don't
+ * make sense to some engines.  In such a case, they do nothing but return
+ * the error ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED. */
+#define ENGINE_CTRL_SET_LOGSTREAM		1
+#define ENGINE_CTRL_SET_PASSWORD_CALLBACK	2
+#define ENGINE_CTRL_HUP				3 /* Close and reinitialise any
+						     handles/connections etc. */
+#define ENGINE_CTRL_SET_USER_INTERFACE          4 /* Alternative to callback */
+#define ENGINE_CTRL_SET_CALLBACK_DATA           5 /* User-specific data, used
+						     when calling the password
+						     callback and the user
+						     interface */
+#define ENGINE_CTRL_LOAD_CONFIGURATION		6 /* Load a configuration, given
+						     a string that represents a
+						     file name or so */
+#define ENGINE_CTRL_LOAD_SECTION		7 /* Load data from a given
+						     section in the already loaded
+						     configuration */
+
+/* These control commands allow an application to deal with an arbitrary engine
+ * in a dynamic way. Warn: Negative return values indicate errors FOR THESE
+ * COMMANDS because zero is used to indicate 'end-of-list'. Other commands,
+ * including ENGINE-specific command types, return zero for an error.
+ *
+ * An ENGINE can choose to implement these ctrl functions, and can internally
+ * manage things however it chooses - it does so by setting the
+ * ENGINE_FLAGS_MANUAL_CMD_CTRL flag (using ENGINE_set_flags()). Otherwise the
+ * ENGINE_ctrl() code handles this on the ENGINE's behalf using the cmd_defns
+ * data (set using ENGINE_set_cmd_defns()). This means an ENGINE's ctrl()
+ * handler need only implement its own commands - the above "meta" commands will
+ * be taken care of. */
+
+/* Returns non-zero if the supplied ENGINE has a ctrl() handler. If "not", then
+ * all the remaining control commands will return failure, so it is worth
+ * checking this first if the caller is trying to "discover" the engine's
+ * capabilities and doesn't want errors generated unnecessarily. */
+#define ENGINE_CTRL_HAS_CTRL_FUNCTION		10
+/* Returns a positive command number for the first command supported by the
+ * engine. Returns zero if no ctrl commands are supported. */
+#define ENGINE_CTRL_GET_FIRST_CMD_TYPE		11
+/* The 'long' argument specifies a command implemented by the engine, and the
+ * return value is the next command supported, or zero if there are no more. */
+#define ENGINE_CTRL_GET_NEXT_CMD_TYPE		12
+/* The 'void*' argument is a command name (cast from 'const char *'), and the
+ * return value is the command that corresponds to it. */
+#define ENGINE_CTRL_GET_CMD_FROM_NAME		13
+/* The next two allow a command to be converted into its corresponding string
+ * form. In each case, the 'long' argument supplies the command. In the NAME_LEN
+ * case, the return value is the length of the command name (not counting a
+ * trailing EOL). In the NAME case, the 'void*' argument must be a string buffer
+ * large enough, and it will be populated with the name of the command (WITH a
+ * trailing EOL). */
+#define ENGINE_CTRL_GET_NAME_LEN_FROM_CMD	14
+#define ENGINE_CTRL_GET_NAME_FROM_CMD		15
+/* The next two are similar but give a "short description" of a command. */
+#define ENGINE_CTRL_GET_DESC_LEN_FROM_CMD	16
+#define ENGINE_CTRL_GET_DESC_FROM_CMD		17
+/* With this command, the return value is the OR'd combination of
+ * ENGINE_CMD_FLAG_*** values that indicate what kind of input a given
+ * engine-specific ctrl command expects. */
+#define ENGINE_CTRL_GET_CMD_FLAGS		18
+
+/* ENGINE implementations should start the numbering of their own control
+ * commands from this value. (ie. ENGINE_CMD_BASE, ENGINE_CMD_BASE + 1, etc). */
+#define ENGINE_CMD_BASE				200
+
+/* NB: These 2 nCipher "chil" control commands are deprecated, and their
+ * functionality is now available through ENGINE-specific control commands
+ * (exposed through the above-mentioned 'CMD'-handling). Code using these 2
+ * commands should be migrated to the more general command handling before these
+ * are removed. */
+
+/* Flags specific to the nCipher "chil" engine */
+#define ENGINE_CTRL_CHIL_SET_FORKCHECK		100
+	/* Depending on the value of the (long)i argument, this sets or
+	 * unsets the SimpleForkCheck flag in the CHIL API to enable or
+	 * disable checking and workarounds for applications that fork().
+	 */
+#define ENGINE_CTRL_CHIL_NO_LOCKING		101
+	/* This prevents the initialisation function from providing mutex
+	 * callbacks to the nCipher library. */
+
+/* If an ENGINE supports its own specific control commands and wishes the
+ * framework to handle the above 'ENGINE_CMD_***'-manipulation commands on its
+ * behalf, it should supply a null-terminated array of ENGINE_CMD_DEFN entries
+ * to ENGINE_set_cmd_defns(). It should also implement a ctrl() handler that
+ * supports the stated commands (ie. the "cmd_num" entries as described by the
+ * array). NB: The array must be ordered in increasing order of cmd_num.
+ * "null-terminated" means that the last ENGINE_CMD_DEFN element has cmd_num set
+ * to zero and/or cmd_name set to NULL. */
+typedef struct ENGINE_CMD_DEFN_st
+	{
+	unsigned int cmd_num; /* The command number */
+	const char *cmd_name; /* The command name itself */
+	const char *cmd_desc; /* A short description of the command */
+	unsigned int cmd_flags; /* The input the command expects */
+	} ENGINE_CMD_DEFN;
+
+/* Generic function pointer */
+typedef int (*ENGINE_GEN_FUNC_PTR)(void);
+/* Generic function pointer taking no arguments */
+typedef int (*ENGINE_GEN_INT_FUNC_PTR)(ENGINE *);
+/* Specific control function pointer */
+typedef int (*ENGINE_CTRL_FUNC_PTR)(ENGINE *, int, long, void *, void (*f)(void));
+/* Generic load_key function pointer */
+typedef EVP_PKEY * (*ENGINE_LOAD_KEY_PTR)(ENGINE *, const char *,
+	UI_METHOD *ui_method, void *callback_data);
+/* These callback types are for an ENGINE's handler for cipher and digest logic.
+ * These handlers have these prototypes;
+ *   int foo(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid);
+ *   int foo(ENGINE *e, const EVP_MD **digest, const int **nids, int nid);
+ * Looking at how to implement these handlers in the case of cipher support, if
+ * the framework wants the EVP_CIPHER for 'nid', it will call;
+ *   foo(e, &p_evp_cipher, NULL, nid);    (return zero for failure)
+ * If the framework wants a list of supported 'nid's, it will call;
+ *   foo(e, NULL, &p_nids, 0); (returns number of 'nids' or -1 for error)
+ */
+/* Returns to a pointer to the array of supported cipher 'nid's. If the second
+ * parameter is non-NULL it is set to the size of the returned array. */
+typedef int (*ENGINE_CIPHERS_PTR)(ENGINE *, const EVP_CIPHER **, const int **, int);
+typedef int (*ENGINE_DIGESTS_PTR)(ENGINE *, const EVP_MD **, const int **, int);
+
+/* STRUCTURE functions ... all of these functions deal with pointers to ENGINE
+ * structures where the pointers have a "structural reference". This means that
+ * their reference is to allowed access to the structure but it does not imply
+ * that the structure is functional. To simply increment or decrement the
+ * structural reference count, use ENGINE_by_id and ENGINE_free. NB: This is not
+ * required when iterating using ENGINE_get_next as it will automatically
+ * decrement the structural reference count of the "current" ENGINE and
+ * increment the structural reference count of the ENGINE it returns (unless it
+ * is NULL). */
+
+/* Get the first/last "ENGINE" type available. */
+ENGINE *ENGINE_get_first(void);
+ENGINE *ENGINE_get_last(void);
+/* Iterate to the next/previous "ENGINE" type (NULL = end of the list). */
+ENGINE *ENGINE_get_next(ENGINE *e);
+ENGINE *ENGINE_get_prev(ENGINE *e);
+/* Add another "ENGINE" type into the array. */
+int ENGINE_add(ENGINE *e);
+/* Remove an existing "ENGINE" type from the array. */
+int ENGINE_remove(ENGINE *e);
+/* Retrieve an engine from the list by its unique "id" value. */
+ENGINE *ENGINE_by_id(const char *id);
+/* Add all the built-in engines. */
+void ENGINE_load_openssl(void);
+void ENGINE_load_dynamic(void);
+#ifndef OPENSSL_NO_STATIC_ENGINE
+void ENGINE_load_4758cca(void);
+void ENGINE_load_aep(void);
+void ENGINE_load_atalla(void);
+void ENGINE_load_chil(void);
+void ENGINE_load_cswift(void);
+#ifndef OPENSSL_NO_GMP
+void ENGINE_load_gmp(void);
+#endif
+void ENGINE_load_nuron(void);
+void ENGINE_load_sureware(void);
+void ENGINE_load_ubsec(void);
+#endif
+void ENGINE_load_cryptodev(void);
+void ENGINE_load_padlock(void);
+void ENGINE_load_builtin_engines(void);
+
+/* Get and set global flags (ENGINE_TABLE_FLAG_***) for the implementation
+ * "registry" handling. */
+unsigned int ENGINE_get_table_flags(void);
+void ENGINE_set_table_flags(unsigned int flags);
+
+/* Manage registration of ENGINEs per "table". For each type, there are 3
+ * functions;
+ *   ENGINE_register_***(e) - registers the implementation from 'e' (if it has one)
+ *   ENGINE_unregister_***(e) - unregister the implementation from 'e'
+ *   ENGINE_register_all_***() - call ENGINE_register_***() for each 'e' in the list
+ * Cleanup is automatically registered from each table when required, so
+ * ENGINE_cleanup() will reverse any "register" operations. */
+
+int ENGINE_register_RSA(ENGINE *e);
+void ENGINE_unregister_RSA(ENGINE *e);
+void ENGINE_register_all_RSA(void);
+
+int ENGINE_register_DSA(ENGINE *e);
+void ENGINE_unregister_DSA(ENGINE *e);
+void ENGINE_register_all_DSA(void);
+
+int ENGINE_register_ECDH(ENGINE *e);
+void ENGINE_unregister_ECDH(ENGINE *e);
+void ENGINE_register_all_ECDH(void);
+
+int ENGINE_register_ECDSA(ENGINE *e);
+void ENGINE_unregister_ECDSA(ENGINE *e);
+void ENGINE_register_all_ECDSA(void);
+
+int ENGINE_register_DH(ENGINE *e);
+void ENGINE_unregister_DH(ENGINE *e);
+void ENGINE_register_all_DH(void);
+
+int ENGINE_register_RAND(ENGINE *e);
+void ENGINE_unregister_RAND(ENGINE *e);
+void ENGINE_register_all_RAND(void);
+
+int ENGINE_register_STORE(ENGINE *e);
+void ENGINE_unregister_STORE(ENGINE *e);
+void ENGINE_register_all_STORE(void);
+
+int ENGINE_register_ciphers(ENGINE *e);
+void ENGINE_unregister_ciphers(ENGINE *e);
+void ENGINE_register_all_ciphers(void);
+
+int ENGINE_register_digests(ENGINE *e);
+void ENGINE_unregister_digests(ENGINE *e);
+void ENGINE_register_all_digests(void);
+
+/* These functions register all support from the above categories. Note, use of
+ * these functions can result in static linkage of code your application may not
+ * need. If you only need a subset of functionality, consider using more
+ * selective initialisation. */
+int ENGINE_register_complete(ENGINE *e);
+int ENGINE_register_all_complete(void);
+
+/* Send parametrised control commands to the engine. The possibilities to send
+ * down an integer, a pointer to data or a function pointer are provided. Any of
+ * the parameters may or may not be NULL, depending on the command number. In
+ * actuality, this function only requires a structural (rather than functional)
+ * reference to an engine, but many control commands may require the engine be
+ * functional. The caller should be aware of trying commands that require an
+ * operational ENGINE, and only use functional references in such situations. */
+int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void));
+
+/* This function tests if an ENGINE-specific command is usable as a "setting".
+ * Eg. in an application's config file that gets processed through
+ * ENGINE_ctrl_cmd_string(). If this returns zero, it is not available to
+ * ENGINE_ctrl_cmd_string(), only ENGINE_ctrl(). */
+int ENGINE_cmd_is_executable(ENGINE *e, int cmd);
+
+/* This function works like ENGINE_ctrl() with the exception of taking a
+ * command name instead of a command number, and can handle optional commands.
+ * See the comment on ENGINE_ctrl_cmd_string() for an explanation on how to
+ * use the cmd_name and cmd_optional. */
+int ENGINE_ctrl_cmd(ENGINE *e, const char *cmd_name,
+        long i, void *p, void (*f)(void), int cmd_optional);
+
+/* This function passes a command-name and argument to an ENGINE. The cmd_name
+ * is converted to a command number and the control command is called using
+ * 'arg' as an argument (unless the ENGINE doesn't support such a command, in
+ * which case no control command is called). The command is checked for input
+ * flags, and if necessary the argument will be converted to a numeric value. If
+ * cmd_optional is non-zero, then if the ENGINE doesn't support the given
+ * cmd_name the return value will be success anyway. This function is intended
+ * for applications to use so that users (or config files) can supply
+ * engine-specific config data to the ENGINE at run-time to control behaviour of
+ * specific engines. As such, it shouldn't be used for calling ENGINE_ctrl()
+ * functions that return data, deal with binary data, or that are otherwise
+ * supposed to be used directly through ENGINE_ctrl() in application code. Any
+ * "return" data from an ENGINE_ctrl() operation in this function will be lost -
+ * the return value is interpreted as failure if the return value is zero,
+ * success otherwise, and this function returns a boolean value as a result. In
+ * other words, vendors of 'ENGINE'-enabled devices should write ENGINE
+ * implementations with parameterisations that work in this scheme, so that
+ * compliant ENGINE-based applications can work consistently with the same
+ * configuration for the same ENGINE-enabled devices, across applications. */
+int ENGINE_ctrl_cmd_string(ENGINE *e, const char *cmd_name, const char *arg,
+				int cmd_optional);
+
+/* These functions are useful for manufacturing new ENGINE structures. They
+ * don't address reference counting at all - one uses them to populate an ENGINE
+ * structure with personalised implementations of things prior to using it
+ * directly or adding it to the builtin ENGINE list in OpenSSL. These are also
+ * here so that the ENGINE structure doesn't have to be exposed and break binary
+ * compatibility! */
+ENGINE *ENGINE_new(void);
+int ENGINE_free(ENGINE *e);
+int ENGINE_up_ref(ENGINE *e);
+int ENGINE_set_id(ENGINE *e, const char *id);
+int ENGINE_set_name(ENGINE *e, const char *name);
+int ENGINE_set_RSA(ENGINE *e, const RSA_METHOD *rsa_meth);
+int ENGINE_set_DSA(ENGINE *e, const DSA_METHOD *dsa_meth);
+int ENGINE_set_ECDH(ENGINE *e, const ECDH_METHOD *ecdh_meth);
+int ENGINE_set_ECDSA(ENGINE *e, const ECDSA_METHOD *ecdsa_meth);
+int ENGINE_set_DH(ENGINE *e, const DH_METHOD *dh_meth);
+int ENGINE_set_RAND(ENGINE *e, const RAND_METHOD *rand_meth);
+int ENGINE_set_STORE(ENGINE *e, const STORE_METHOD *store_meth);
+int ENGINE_set_destroy_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR destroy_f);
+int ENGINE_set_init_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR init_f);
+int ENGINE_set_finish_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR finish_f);
+int ENGINE_set_ctrl_function(ENGINE *e, ENGINE_CTRL_FUNC_PTR ctrl_f);
+int ENGINE_set_load_privkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpriv_f);
+int ENGINE_set_load_pubkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpub_f);
+int ENGINE_set_ciphers(ENGINE *e, ENGINE_CIPHERS_PTR f);
+int ENGINE_set_digests(ENGINE *e, ENGINE_DIGESTS_PTR f);
+int ENGINE_set_flags(ENGINE *e, int flags);
+int ENGINE_set_cmd_defns(ENGINE *e, const ENGINE_CMD_DEFN *defns);
+/* These functions allow control over any per-structure ENGINE data. */
+int ENGINE_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+		CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int ENGINE_set_ex_data(ENGINE *e, int idx, void *arg);
+void *ENGINE_get_ex_data(const ENGINE *e, int idx);
+
+/* This function cleans up anything that needs it. Eg. the ENGINE_add() function
+ * automatically ensures the list cleanup function is registered to be called
+ * from ENGINE_cleanup(). Similarly, all ENGINE_register_*** functions ensure
+ * ENGINE_cleanup() will clean up after them. */
+void ENGINE_cleanup(void);
+
+/* These return values from within the ENGINE structure. These can be useful
+ * with functional references as well as structural references - it depends
+ * which you obtained. Using the result for functional purposes if you only
+ * obtained a structural reference may be problematic! */
+const char *ENGINE_get_id(const ENGINE *e);
+const char *ENGINE_get_name(const ENGINE *e);
+const RSA_METHOD *ENGINE_get_RSA(const ENGINE *e);
+const DSA_METHOD *ENGINE_get_DSA(const ENGINE *e);
+const ECDH_METHOD *ENGINE_get_ECDH(const ENGINE *e);
+const ECDSA_METHOD *ENGINE_get_ECDSA(const ENGINE *e);
+const DH_METHOD *ENGINE_get_DH(const ENGINE *e);
+const RAND_METHOD *ENGINE_get_RAND(const ENGINE *e);
+const STORE_METHOD *ENGINE_get_STORE(const ENGINE *e);
+ENGINE_GEN_INT_FUNC_PTR ENGINE_get_destroy_function(const ENGINE *e);
+ENGINE_GEN_INT_FUNC_PTR ENGINE_get_init_function(const ENGINE *e);
+ENGINE_GEN_INT_FUNC_PTR ENGINE_get_finish_function(const ENGINE *e);
+ENGINE_CTRL_FUNC_PTR ENGINE_get_ctrl_function(const ENGINE *e);
+ENGINE_LOAD_KEY_PTR ENGINE_get_load_privkey_function(const ENGINE *e);
+ENGINE_LOAD_KEY_PTR ENGINE_get_load_pubkey_function(const ENGINE *e);
+ENGINE_CIPHERS_PTR ENGINE_get_ciphers(const ENGINE *e);
+ENGINE_DIGESTS_PTR ENGINE_get_digests(const ENGINE *e);
+const EVP_CIPHER *ENGINE_get_cipher(ENGINE *e, int nid);
+const EVP_MD *ENGINE_get_digest(ENGINE *e, int nid);
+const ENGINE_CMD_DEFN *ENGINE_get_cmd_defns(const ENGINE *e);
+int ENGINE_get_flags(const ENGINE *e);
+
+/* FUNCTIONAL functions. These functions deal with ENGINE structures
+ * that have (or will) be initialised for use. Broadly speaking, the
+ * structural functions are useful for iterating the list of available
+ * engine types, creating new engine types, and other "list" operations.
+ * These functions actually deal with ENGINEs that are to be used. As
+ * such these functions can fail (if applicable) when particular
+ * engines are unavailable - eg. if a hardware accelerator is not
+ * attached or not functioning correctly. Each ENGINE has 2 reference
+ * counts; structural and functional. Every time a functional reference
+ * is obtained or released, a corresponding structural reference is
+ * automatically obtained or released too. */
+
+/* Initialise a engine type for use (or up its reference count if it's
+ * already in use). This will fail if the engine is not currently
+ * operational and cannot initialise. */
+int ENGINE_init(ENGINE *e);
+/* Free a functional reference to a engine type. This does not require
+ * a corresponding call to ENGINE_free as it also releases a structural
+ * reference. */
+int ENGINE_finish(ENGINE *e);
+
+/* The following functions handle keys that are stored in some secondary
+ * location, handled by the engine.  The storage may be on a card or
+ * whatever. */
+EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id,
+	UI_METHOD *ui_method, void *callback_data);
+EVP_PKEY *ENGINE_load_public_key(ENGINE *e, const char *key_id,
+	UI_METHOD *ui_method, void *callback_data);
+
+/* This returns a pointer for the current ENGINE structure that
+ * is (by default) performing any RSA operations. The value returned
+ * is an incremented reference, so it should be free'd (ENGINE_finish)
+ * before it is discarded. */
+ENGINE *ENGINE_get_default_RSA(void);
+/* Same for the other "methods" */
+ENGINE *ENGINE_get_default_DSA(void);
+ENGINE *ENGINE_get_default_ECDH(void);
+ENGINE *ENGINE_get_default_ECDSA(void);
+ENGINE *ENGINE_get_default_DH(void);
+ENGINE *ENGINE_get_default_RAND(void);
+/* These functions can be used to get a functional reference to perform
+ * ciphering or digesting corresponding to "nid". */
+ENGINE *ENGINE_get_cipher_engine(int nid);
+ENGINE *ENGINE_get_digest_engine(int nid);
+
+/* This sets a new default ENGINE structure for performing RSA
+ * operations. If the result is non-zero (success) then the ENGINE
+ * structure will have had its reference count up'd so the caller
+ * should still free their own reference 'e'. */
+int ENGINE_set_default_RSA(ENGINE *e);
+int ENGINE_set_default_string(ENGINE *e, const char *def_list);
+/* Same for the other "methods" */
+int ENGINE_set_default_DSA(ENGINE *e);
+int ENGINE_set_default_ECDH(ENGINE *e);
+int ENGINE_set_default_ECDSA(ENGINE *e);
+int ENGINE_set_default_DH(ENGINE *e);
+int ENGINE_set_default_RAND(ENGINE *e);
+int ENGINE_set_default_ciphers(ENGINE *e);
+int ENGINE_set_default_digests(ENGINE *e);
+
+/* The combination "set" - the flags are bitwise "OR"d from the
+ * ENGINE_METHOD_*** defines above. As with the "ENGINE_register_complete()"
+ * function, this function can result in unnecessary static linkage. If your
+ * application requires only specific functionality, consider using more
+ * selective functions. */
+int ENGINE_set_default(ENGINE *e, unsigned int flags);
+
+void ENGINE_add_conf_module(void);
+
+/* Deprecated functions ... */
+/* int ENGINE_clear_defaults(void); */
+
+/**************************/
+/* DYNAMIC ENGINE SUPPORT */
+/**************************/
+
+/* Binary/behaviour compatibility levels */
+#define OSSL_DYNAMIC_VERSION		(unsigned long)0x00020000
+/* Binary versions older than this are too old for us (whether we're a loader or
+ * a loadee) */
+#define OSSL_DYNAMIC_OLDEST		(unsigned long)0x00020000
+
+/* When compiling an ENGINE entirely as an external shared library, loadable by
+ * the "dynamic" ENGINE, these types are needed. The 'dynamic_fns' structure
+ * type provides the calling application's (or library's) error functionality
+ * and memory management function pointers to the loaded library. These should
+ * be used/set in the loaded library code so that the loading application's
+ * 'state' will be used/changed in all operations. The 'static_state' pointer
+ * allows the loaded library to know if it shares the same static data as the
+ * calling application (or library), and thus whether these callbacks need to be
+ * set or not. */
+typedef void *(*dyn_MEM_malloc_cb)(size_t);
+typedef void *(*dyn_MEM_realloc_cb)(void *, size_t);
+typedef void (*dyn_MEM_free_cb)(void *);
+typedef struct st_dynamic_MEM_fns {
+	dyn_MEM_malloc_cb			malloc_cb;
+	dyn_MEM_realloc_cb			realloc_cb;
+	dyn_MEM_free_cb				free_cb;
+	} dynamic_MEM_fns;
+/* FIXME: Perhaps the memory and locking code (crypto.h) should declare and use
+ * these types so we (and any other dependant code) can simplify a bit?? */
+typedef void (*dyn_lock_locking_cb)(int,int,const char *,int);
+typedef int (*dyn_lock_add_lock_cb)(int*,int,int,const char *,int);
+typedef struct CRYPTO_dynlock_value *(*dyn_dynlock_create_cb)(
+						const char *,int);
+typedef void (*dyn_dynlock_lock_cb)(int,struct CRYPTO_dynlock_value *,
+						const char *,int);
+typedef void (*dyn_dynlock_destroy_cb)(struct CRYPTO_dynlock_value *,
+						const char *,int);
+typedef struct st_dynamic_LOCK_fns {
+	dyn_lock_locking_cb			lock_locking_cb;
+	dyn_lock_add_lock_cb			lock_add_lock_cb;
+	dyn_dynlock_create_cb			dynlock_create_cb;
+	dyn_dynlock_lock_cb			dynlock_lock_cb;
+	dyn_dynlock_destroy_cb			dynlock_destroy_cb;
+	} dynamic_LOCK_fns;
+/* The top-level structure */
+typedef struct st_dynamic_fns {
+	void 					*static_state;
+	const ERR_FNS				*err_fns;
+	const CRYPTO_EX_DATA_IMPL		*ex_data_fns;
+	dynamic_MEM_fns				mem_fns;
+	dynamic_LOCK_fns			lock_fns;
+	} dynamic_fns;
+
+/* The version checking function should be of this prototype. NB: The
+ * ossl_version value passed in is the OSSL_DYNAMIC_VERSION of the loading code.
+ * If this function returns zero, it indicates a (potential) version
+ * incompatibility and the loaded library doesn't believe it can proceed.
+ * Otherwise, the returned value is the (latest) version supported by the
+ * loading library. The loader may still decide that the loaded code's version
+ * is unsatisfactory and could veto the load. The function is expected to
+ * be implemented with the symbol name "v_check", and a default implementation
+ * can be fully instantiated with IMPLEMENT_DYNAMIC_CHECK_FN(). */
+typedef unsigned long (*dynamic_v_check_fn)(unsigned long ossl_version);
+#define IMPLEMENT_DYNAMIC_CHECK_FN() \
+	OPENSSL_EXPORT unsigned long v_check(unsigned long v) { \
+		if(v >= OSSL_DYNAMIC_OLDEST) return OSSL_DYNAMIC_VERSION; \
+		return 0; }
+
+/* This function is passed the ENGINE structure to initialise with its own
+ * function and command settings. It should not adjust the structural or
+ * functional reference counts. If this function returns zero, (a) the load will
+ * be aborted, (b) the previous ENGINE state will be memcpy'd back onto the
+ * structure, and (c) the shared library will be unloaded. So implementations
+ * should do their own internal cleanup in failure circumstances otherwise they
+ * could leak. The 'id' parameter, if non-NULL, represents the ENGINE id that
+ * the loader is looking for. If this is NULL, the shared library can choose to
+ * return failure or to initialise a 'default' ENGINE. If non-NULL, the shared
+ * library must initialise only an ENGINE matching the passed 'id'. The function
+ * is expected to be implemented with the symbol name "bind_engine". A standard
+ * implementation can be instantiated with IMPLEMENT_DYNAMIC_BIND_FN(fn) where
+ * the parameter 'fn' is a callback function that populates the ENGINE structure
+ * and returns an int value (zero for failure). 'fn' should have prototype;
+ *    [static] int fn(ENGINE *e, const char *id); */
+typedef int (*dynamic_bind_engine)(ENGINE *e, const char *id,
+				const dynamic_fns *fns);
+#define IMPLEMENT_DYNAMIC_BIND_FN(fn) \
+	OPENSSL_EXPORT \
+	int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns) { \
+		if(ENGINE_get_static_state() == fns->static_state) goto skip_cbs; \
+		if(!CRYPTO_set_mem_functions(fns->mem_fns.malloc_cb, \
+			fns->mem_fns.realloc_cb, fns->mem_fns.free_cb)) \
+			return 0; \
+		CRYPTO_set_locking_callback(fns->lock_fns.lock_locking_cb); \
+		CRYPTO_set_add_lock_callback(fns->lock_fns.lock_add_lock_cb); \
+		CRYPTO_set_dynlock_create_callback(fns->lock_fns.dynlock_create_cb); \
+		CRYPTO_set_dynlock_lock_callback(fns->lock_fns.dynlock_lock_cb); \
+		CRYPTO_set_dynlock_destroy_callback(fns->lock_fns.dynlock_destroy_cb); \
+		if(!CRYPTO_set_ex_data_implementation(fns->ex_data_fns)) \
+			return 0; \
+		if(!ERR_set_implementation(fns->err_fns)) return 0; \
+	skip_cbs: \
+		if(!fn(e,id)) return 0; \
+		return 1; }
+
+/* If the loading application (or library) and the loaded ENGINE library share
+ * the same static data (eg. they're both dynamically linked to the same
+ * libcrypto.so) we need a way to avoid trying to set system callbacks - this
+ * would fail, and for the same reason that it's unnecessary to try. If the
+ * loaded ENGINE has (or gets from through the loader) its own copy of the
+ * libcrypto static data, we will need to set the callbacks. The easiest way to
+ * detect this is to have a function that returns a pointer to some static data
+ * and let the loading application and loaded ENGINE compare their respective
+ * values. */
+void *ENGINE_get_static_state(void);
+
+#if defined(__OpenBSD__) || defined(__FreeBSD__)
+void ENGINE_setup_bsd_cryptodev(void);
+#endif
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_ENGINE_strings(void);
+
+/* Error codes for the ENGINE functions. */
+
+/* Function codes. */
+#define ENGINE_F_DYNAMIC_CTRL				 180
+#define ENGINE_F_DYNAMIC_GET_DATA_CTX			 181
+#define ENGINE_F_DYNAMIC_LOAD				 182
+#define ENGINE_F_DYNAMIC_SET_DATA_CTX			 183
+#define ENGINE_F_ENGINE_ADD				 105
+#define ENGINE_F_ENGINE_BY_ID				 106
+#define ENGINE_F_ENGINE_CMD_IS_EXECUTABLE		 170
+#define ENGINE_F_ENGINE_CTRL				 142
+#define ENGINE_F_ENGINE_CTRL_CMD			 178
+#define ENGINE_F_ENGINE_CTRL_CMD_STRING			 171
+#define ENGINE_F_ENGINE_FINISH				 107
+#define ENGINE_F_ENGINE_FREE_UTIL			 108
+#define ENGINE_F_ENGINE_GET_CIPHER			 185
+#define ENGINE_F_ENGINE_GET_DEFAULT_TYPE		 177
+#define ENGINE_F_ENGINE_GET_DIGEST			 186
+#define ENGINE_F_ENGINE_GET_NEXT			 115
+#define ENGINE_F_ENGINE_GET_PREV			 116
+#define ENGINE_F_ENGINE_INIT				 119
+#define ENGINE_F_ENGINE_LIST_ADD			 120
+#define ENGINE_F_ENGINE_LIST_REMOVE			 121
+#define ENGINE_F_ENGINE_LOAD_PRIVATE_KEY		 150
+#define ENGINE_F_ENGINE_LOAD_PUBLIC_KEY			 151
+#define ENGINE_F_ENGINE_NEW				 122
+#define ENGINE_F_ENGINE_REMOVE				 123
+#define ENGINE_F_ENGINE_SET_DEFAULT_STRING		 189
+#define ENGINE_F_ENGINE_SET_DEFAULT_TYPE		 126
+#define ENGINE_F_ENGINE_SET_ID				 129
+#define ENGINE_F_ENGINE_SET_NAME			 130
+#define ENGINE_F_ENGINE_TABLE_REGISTER			 184
+#define ENGINE_F_ENGINE_UNLOAD_KEY			 152
+#define ENGINE_F_ENGINE_UNLOCKED_FINISH			 191
+#define ENGINE_F_ENGINE_UP_REF				 190
+#define ENGINE_F_INT_CTRL_HELPER			 172
+#define ENGINE_F_INT_ENGINE_CONFIGURE			 188
+#define ENGINE_F_INT_ENGINE_MODULE_INIT			 187
+#define ENGINE_F_LOG_MESSAGE				 141
+
+/* Reason codes. */
+#define ENGINE_R_ALREADY_LOADED				 100
+#define ENGINE_R_ARGUMENT_IS_NOT_A_NUMBER		 133
+#define ENGINE_R_CMD_NOT_EXECUTABLE			 134
+#define ENGINE_R_COMMAND_TAKES_INPUT			 135
+#define ENGINE_R_COMMAND_TAKES_NO_INPUT			 136
+#define ENGINE_R_CONFLICTING_ENGINE_ID			 103
+#define ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED		 119
+#define ENGINE_R_DH_NOT_IMPLEMENTED			 139
+#define ENGINE_R_DSA_NOT_IMPLEMENTED			 140
+#define ENGINE_R_DSO_FAILURE				 104
+#define ENGINE_R_DSO_NOT_FOUND				 132
+#define ENGINE_R_ENGINES_SECTION_ERROR			 148
+#define ENGINE_R_ENGINE_IS_NOT_IN_LIST			 105
+#define ENGINE_R_ENGINE_SECTION_ERROR			 149
+#define ENGINE_R_FAILED_LOADING_PRIVATE_KEY		 128
+#define ENGINE_R_FAILED_LOADING_PUBLIC_KEY		 129
+#define ENGINE_R_FINISH_FAILED				 106
+#define ENGINE_R_GET_HANDLE_FAILED			 107
+#define ENGINE_R_ID_OR_NAME_MISSING			 108
+#define ENGINE_R_INIT_FAILED				 109
+#define ENGINE_R_INTERNAL_LIST_ERROR			 110
+#define ENGINE_R_INVALID_ARGUMENT			 143
+#define ENGINE_R_INVALID_CMD_NAME			 137
+#define ENGINE_R_INVALID_CMD_NUMBER			 138
+#define ENGINE_R_INVALID_INIT_VALUE			 151
+#define ENGINE_R_INVALID_STRING				 150
+#define ENGINE_R_NOT_INITIALISED			 117
+#define ENGINE_R_NOT_LOADED				 112
+#define ENGINE_R_NO_CONTROL_FUNCTION			 120
+#define ENGINE_R_NO_INDEX				 144
+#define ENGINE_R_NO_LOAD_FUNCTION			 125
+#define ENGINE_R_NO_REFERENCE				 130
+#define ENGINE_R_NO_SUCH_ENGINE				 116
+#define ENGINE_R_NO_UNLOAD_FUNCTION			 126
+#define ENGINE_R_PROVIDE_PARAMETERS			 113
+#define ENGINE_R_RSA_NOT_IMPLEMENTED			 141
+#define ENGINE_R_UNIMPLEMENTED_CIPHER			 146
+#define ENGINE_R_UNIMPLEMENTED_DIGEST			 147
+#define ENGINE_R_VERSION_INCOMPATIBILITY		 145
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/dep/include/openssl/err.h b/dep/include/openssl/err.h
new file mode 100644
index 00000000000..b723cd977a4
--- /dev/null
+++ b/dep/include/openssl/err.h
@@ -0,0 +1,318 @@
+/* crypto/err/err.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_ERR_H
+#define HEADER_ERR_H
+
+#include 
+
+#ifndef OPENSSL_NO_FP_API
+#include 
+#include 
+#endif
+
+#include 
+#ifndef OPENSSL_NO_BIO
+#include 
+#endif
+#ifndef OPENSSL_NO_LHASH
+#include 
+#endif
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#ifndef OPENSSL_NO_ERR
+#define ERR_PUT_error(a,b,c,d,e)	ERR_put_error(a,b,c,d,e)
+#else
+#define ERR_PUT_error(a,b,c,d,e)	ERR_put_error(a,b,c,NULL,0)
+#endif
+
+#include 
+
+#define ERR_TXT_MALLOCED	0x01
+#define ERR_TXT_STRING		0x02
+
+#define ERR_FLAG_MARK		0x01
+
+#define ERR_NUM_ERRORS	16
+typedef struct err_state_st
+	{
+	unsigned long pid;
+	int err_flags[ERR_NUM_ERRORS];
+	unsigned long err_buffer[ERR_NUM_ERRORS];
+	char *err_data[ERR_NUM_ERRORS];
+	int err_data_flags[ERR_NUM_ERRORS];
+	const char *err_file[ERR_NUM_ERRORS];
+	int err_line[ERR_NUM_ERRORS];
+	int top,bottom;
+	} ERR_STATE;
+
+/* library */
+#define ERR_LIB_NONE		1
+#define ERR_LIB_SYS		2
+#define ERR_LIB_BN		3
+#define ERR_LIB_RSA		4
+#define ERR_LIB_DH		5
+#define ERR_LIB_EVP		6
+#define ERR_LIB_BUF		7
+#define ERR_LIB_OBJ		8
+#define ERR_LIB_PEM		9
+#define ERR_LIB_DSA		10
+#define ERR_LIB_X509		11
+/* #define ERR_LIB_METH         12 */
+#define ERR_LIB_ASN1		13
+#define ERR_LIB_CONF		14
+#define ERR_LIB_CRYPTO		15
+#define ERR_LIB_EC		16
+#define ERR_LIB_SSL		20
+/* #define ERR_LIB_SSL23        21 */
+/* #define ERR_LIB_SSL2         22 */
+/* #define ERR_LIB_SSL3         23 */
+/* #define ERR_LIB_RSAREF       30 */
+/* #define ERR_LIB_PROXY        31 */
+#define ERR_LIB_BIO		32
+#define ERR_LIB_PKCS7		33
+#define ERR_LIB_X509V3		34
+#define ERR_LIB_PKCS12		35
+#define ERR_LIB_RAND		36
+#define ERR_LIB_DSO		37
+#define ERR_LIB_ENGINE		38
+#define ERR_LIB_OCSP            39
+#define ERR_LIB_UI              40
+#define ERR_LIB_COMP            41
+#define ERR_LIB_ECDSA		42
+#define ERR_LIB_ECDH		43
+#define ERR_LIB_STORE           44
+
+#define ERR_LIB_USER		128
+
+#define SYSerr(f,r)  ERR_PUT_error(ERR_LIB_SYS,(f),(r),__FILE__,__LINE__)
+#define BNerr(f,r)   ERR_PUT_error(ERR_LIB_BN,(f),(r),__FILE__,__LINE__)
+#define RSAerr(f,r)  ERR_PUT_error(ERR_LIB_RSA,(f),(r),__FILE__,__LINE__)
+#define DHerr(f,r)   ERR_PUT_error(ERR_LIB_DH,(f),(r),__FILE__,__LINE__)
+#define EVPerr(f,r)  ERR_PUT_error(ERR_LIB_EVP,(f),(r),__FILE__,__LINE__)
+#define BUFerr(f,r)  ERR_PUT_error(ERR_LIB_BUF,(f),(r),__FILE__,__LINE__)
+#define OBJerr(f,r)  ERR_PUT_error(ERR_LIB_OBJ,(f),(r),__FILE__,__LINE__)
+#define PEMerr(f,r)  ERR_PUT_error(ERR_LIB_PEM,(f),(r),__FILE__,__LINE__)
+#define DSAerr(f,r)  ERR_PUT_error(ERR_LIB_DSA,(f),(r),__FILE__,__LINE__)
+#define X509err(f,r) ERR_PUT_error(ERR_LIB_X509,(f),(r),__FILE__,__LINE__)
+#define ASN1err(f,r) ERR_PUT_error(ERR_LIB_ASN1,(f),(r),__FILE__,__LINE__)
+#define CONFerr(f,r) ERR_PUT_error(ERR_LIB_CONF,(f),(r),__FILE__,__LINE__)
+#define CRYPTOerr(f,r) ERR_PUT_error(ERR_LIB_CRYPTO,(f),(r),__FILE__,__LINE__)
+#define ECerr(f,r)   ERR_PUT_error(ERR_LIB_EC,(f),(r),__FILE__,__LINE__)
+#define SSLerr(f,r)  ERR_PUT_error(ERR_LIB_SSL,(f),(r),__FILE__,__LINE__)
+#define BIOerr(f,r)  ERR_PUT_error(ERR_LIB_BIO,(f),(r),__FILE__,__LINE__)
+#define PKCS7err(f,r) ERR_PUT_error(ERR_LIB_PKCS7,(f),(r),__FILE__,__LINE__)
+#define X509V3err(f,r) ERR_PUT_error(ERR_LIB_X509V3,(f),(r),__FILE__,__LINE__)
+#define PKCS12err(f,r) ERR_PUT_error(ERR_LIB_PKCS12,(f),(r),__FILE__,__LINE__)
+#define RANDerr(f,r) ERR_PUT_error(ERR_LIB_RAND,(f),(r),__FILE__,__LINE__)
+#define DSOerr(f,r) ERR_PUT_error(ERR_LIB_DSO,(f),(r),__FILE__,__LINE__)
+#define ENGINEerr(f,r) ERR_PUT_error(ERR_LIB_ENGINE,(f),(r),__FILE__,__LINE__)
+#define OCSPerr(f,r) ERR_PUT_error(ERR_LIB_OCSP,(f),(r),__FILE__,__LINE__)
+#define UIerr(f,r) ERR_PUT_error(ERR_LIB_UI,(f),(r),__FILE__,__LINE__)
+#define COMPerr(f,r) ERR_PUT_error(ERR_LIB_COMP,(f),(r),__FILE__,__LINE__)
+#define ECDSAerr(f,r)  ERR_PUT_error(ERR_LIB_ECDSA,(f),(r),__FILE__,__LINE__)
+#define ECDHerr(f,r)  ERR_PUT_error(ERR_LIB_ECDH,(f),(r),__FILE__,__LINE__)
+#define STOREerr(f,r) ERR_PUT_error(ERR_LIB_STORE,(f),(r),__FILE__,__LINE__)
+
+/* Borland C seems too stupid to be able to shift and do longs in
+ * the pre-processor :-( */
+#define ERR_PACK(l,f,r)		(((((unsigned long)l)&0xffL)*0x1000000)| \
+				((((unsigned long)f)&0xfffL)*0x1000)| \
+				((((unsigned long)r)&0xfffL)))
+#define ERR_GET_LIB(l)		(int)((((unsigned long)l)>>24L)&0xffL)
+#define ERR_GET_FUNC(l)		(int)((((unsigned long)l)>>12L)&0xfffL)
+#define ERR_GET_REASON(l)	(int)((l)&0xfffL)
+#define ERR_FATAL_ERROR(l)	(int)((l)&ERR_R_FATAL)
+
+
+/* OS functions */
+#define SYS_F_FOPEN		1
+#define SYS_F_CONNECT		2
+#define SYS_F_GETSERVBYNAME	3
+#define SYS_F_SOCKET		4
+#define SYS_F_IOCTLSOCKET	5
+#define SYS_F_BIND		6
+#define SYS_F_LISTEN		7
+#define SYS_F_ACCEPT		8
+#define SYS_F_WSASTARTUP	9 /* Winsock stuff */
+#define SYS_F_OPENDIR		10
+#define SYS_F_FREAD		11
+
+
+/* reasons */
+#define ERR_R_SYS_LIB	ERR_LIB_SYS       /* 2 */
+#define ERR_R_BN_LIB	ERR_LIB_BN        /* 3 */
+#define ERR_R_RSA_LIB	ERR_LIB_RSA       /* 4 */
+#define ERR_R_DH_LIB	ERR_LIB_DH        /* 5 */
+#define ERR_R_EVP_LIB	ERR_LIB_EVP       /* 6 */
+#define ERR_R_BUF_LIB	ERR_LIB_BUF       /* 7 */
+#define ERR_R_OBJ_LIB	ERR_LIB_OBJ       /* 8 */
+#define ERR_R_PEM_LIB	ERR_LIB_PEM       /* 9 */
+#define ERR_R_DSA_LIB	ERR_LIB_DSA      /* 10 */
+#define ERR_R_X509_LIB	ERR_LIB_X509     /* 11 */
+#define ERR_R_ASN1_LIB	ERR_LIB_ASN1     /* 13 */
+#define ERR_R_CONF_LIB	ERR_LIB_CONF     /* 14 */
+#define ERR_R_CRYPTO_LIB ERR_LIB_CRYPTO  /* 15 */
+#define ERR_R_EC_LIB	ERR_LIB_EC       /* 16 */
+#define ERR_R_SSL_LIB	ERR_LIB_SSL      /* 20 */
+#define ERR_R_BIO_LIB	ERR_LIB_BIO      /* 32 */
+#define ERR_R_PKCS7_LIB	ERR_LIB_PKCS7    /* 33 */
+#define ERR_R_X509V3_LIB ERR_LIB_X509V3  /* 34 */
+#define ERR_R_PKCS12_LIB ERR_LIB_PKCS12  /* 35 */
+#define ERR_R_RAND_LIB	ERR_LIB_RAND     /* 36 */
+#define ERR_R_DSO_LIB	ERR_LIB_DSO      /* 37 */
+#define ERR_R_ENGINE_LIB ERR_LIB_ENGINE  /* 38 */
+#define ERR_R_OCSP_LIB  ERR_LIB_OCSP     /* 39 */
+#define ERR_R_UI_LIB    ERR_LIB_UI       /* 40 */
+#define ERR_R_COMP_LIB	ERR_LIB_COMP     /* 41 */
+#define ERR_R_ECDSA_LIB ERR_LIB_ECDSA	 /* 42 */
+#define ERR_R_ECDH_LIB  ERR_LIB_ECDH	 /* 43 */
+#define ERR_R_STORE_LIB ERR_LIB_STORE    /* 44 */
+
+#define ERR_R_NESTED_ASN1_ERROR			58
+#define ERR_R_BAD_ASN1_OBJECT_HEADER		59
+#define ERR_R_BAD_GET_ASN1_OBJECT_CALL		60
+#define ERR_R_EXPECTING_AN_ASN1_SEQUENCE	61
+#define ERR_R_ASN1_LENGTH_MISMATCH		62
+#define ERR_R_MISSING_ASN1_EOS			63
+
+/* fatal error */
+#define ERR_R_FATAL				64
+#define	ERR_R_MALLOC_FAILURE			(1|ERR_R_FATAL)
+#define	ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED	(2|ERR_R_FATAL)
+#define	ERR_R_PASSED_NULL_PARAMETER		(3|ERR_R_FATAL)
+#define	ERR_R_INTERNAL_ERROR			(4|ERR_R_FATAL)
+#define	ERR_R_DISABLED				(5|ERR_R_FATAL)
+
+/* 99 is the maximum possible ERR_R_... code, higher values
+ * are reserved for the individual libraries */
+
+
+typedef struct ERR_string_data_st
+	{
+	unsigned long error;
+	const char *string;
+	} ERR_STRING_DATA;
+
+void ERR_put_error(int lib, int func,int reason,const char *file,int line);
+void ERR_set_error_data(char *data,int flags);
+
+unsigned long ERR_get_error(void);
+unsigned long ERR_get_error_line(const char **file,int *line);
+unsigned long ERR_get_error_line_data(const char **file,int *line,
+				      const char **data, int *flags);
+unsigned long ERR_peek_error(void);
+unsigned long ERR_peek_error_line(const char **file,int *line);
+unsigned long ERR_peek_error_line_data(const char **file,int *line,
+				       const char **data,int *flags);
+unsigned long ERR_peek_last_error(void);
+unsigned long ERR_peek_last_error_line(const char **file,int *line);
+unsigned long ERR_peek_last_error_line_data(const char **file,int *line,
+				       const char **data,int *flags);
+void ERR_clear_error(void );
+char *ERR_error_string(unsigned long e,char *buf);
+void ERR_error_string_n(unsigned long e, char *buf, size_t len);
+const char *ERR_lib_error_string(unsigned long e);
+const char *ERR_func_error_string(unsigned long e);
+const char *ERR_reason_error_string(unsigned long e);
+void ERR_print_errors_cb(int (*cb)(const char *str, size_t len, void *u),
+			 void *u);
+#ifndef OPENSSL_NO_FP_API
+void ERR_print_errors_fp(FILE *fp);
+#endif
+#ifndef OPENSSL_NO_BIO
+void ERR_print_errors(BIO *bp);
+void ERR_add_error_data(int num, ...);
+#endif
+void ERR_load_strings(int lib,ERR_STRING_DATA str[]);
+void ERR_unload_strings(int lib,ERR_STRING_DATA str[]);
+void ERR_load_ERR_strings(void);
+void ERR_load_crypto_strings(void);
+void ERR_free_strings(void);
+
+void ERR_remove_state(unsigned long pid); /* if zero we look it up */
+ERR_STATE *ERR_get_state(void);
+
+#ifndef OPENSSL_NO_LHASH
+LHASH *ERR_get_string_table(void);
+LHASH *ERR_get_err_state_table(void);
+void ERR_release_err_state_table(LHASH **hash);
+#endif
+
+int ERR_get_next_error_library(void);
+
+int ERR_set_mark(void);
+int ERR_pop_to_mark(void);
+
+/* Already defined in ossl_typ.h */
+/* typedef struct st_ERR_FNS ERR_FNS; */
+/* An application can use this function and provide the return value to loaded
+ * modules that should use the application's ERR state/functionality */
+const ERR_FNS *ERR_get_implementation(void);
+/* A loaded module should call this function prior to any ERR operations using
+ * the application's "ERR_FNS". */
+int ERR_set_implementation(const ERR_FNS *fns);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif
diff --git a/dep/include/openssl/evp.h b/dep/include/openssl/evp.h
new file mode 100644
index 00000000000..636f426c699
--- /dev/null
+++ b/dep/include/openssl/evp.h
@@ -0,0 +1,970 @@
+/* crypto/evp/evp.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_ENVELOPE_H
+#define HEADER_ENVELOPE_H
+
+#ifdef OPENSSL_ALGORITHM_DEFINES
+# include 
+#else
+# define OPENSSL_ALGORITHM_DEFINES
+# include 
+# undef OPENSSL_ALGORITHM_DEFINES
+#endif
+
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_BIO
+#include 
+#endif
+
+/*
+#define EVP_RC2_KEY_SIZE		16
+#define EVP_RC4_KEY_SIZE		16
+#define EVP_BLOWFISH_KEY_SIZE		16
+#define EVP_CAST5_KEY_SIZE		16
+#define EVP_RC5_32_12_16_KEY_SIZE	16
+*/
+#define EVP_MAX_MD_SIZE			64	/* longest known is SHA512 */
+#define EVP_MAX_KEY_LENGTH		32
+#define EVP_MAX_IV_LENGTH		16
+#define EVP_MAX_BLOCK_LENGTH		32
+
+#define PKCS5_SALT_LEN			8
+/* Default PKCS#5 iteration count */
+#define PKCS5_DEFAULT_ITER		2048
+
+#include 
+
+#define EVP_PK_RSA	0x0001
+#define EVP_PK_DSA	0x0002
+#define EVP_PK_DH	0x0004
+#define EVP_PK_EC	0x0008
+#define EVP_PKT_SIGN	0x0010
+#define EVP_PKT_ENC	0x0020
+#define EVP_PKT_EXCH	0x0040
+#define EVP_PKS_RSA	0x0100
+#define EVP_PKS_DSA	0x0200
+#define EVP_PKS_EC	0x0400
+#define EVP_PKT_EXP	0x1000 /* <= 512 bit key */
+
+#define EVP_PKEY_NONE	NID_undef
+#define EVP_PKEY_RSA	NID_rsaEncryption
+#define EVP_PKEY_RSA2	NID_rsa
+#define EVP_PKEY_DSA	NID_dsa
+#define EVP_PKEY_DSA1	NID_dsa_2
+#define EVP_PKEY_DSA2	NID_dsaWithSHA
+#define EVP_PKEY_DSA3	NID_dsaWithSHA1
+#define EVP_PKEY_DSA4	NID_dsaWithSHA1_2
+#define EVP_PKEY_DH	NID_dhKeyAgreement
+#define EVP_PKEY_EC	NID_X9_62_id_ecPublicKey
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/* Type needs to be a bit field
+ * Sub-type needs to be for variations on the method, as in, can it do
+ * arbitrary encryption.... */
+struct evp_pkey_st
+	{
+	int type;
+	int save_type;
+	int references;
+	union	{
+		char *ptr;
+#ifndef OPENSSL_NO_RSA
+		struct rsa_st *rsa;	/* RSA */
+#endif
+#ifndef OPENSSL_NO_DSA
+		struct dsa_st *dsa;	/* DSA */
+#endif
+#ifndef OPENSSL_NO_DH
+		struct dh_st *dh;	/* DH */
+#endif
+#ifndef OPENSSL_NO_EC
+		struct ec_key_st *ec;	/* ECC */
+#endif
+		} pkey;
+	int save_parameters;
+	STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */
+	} /* EVP_PKEY */;
+
+#define EVP_PKEY_MO_SIGN	0x0001
+#define EVP_PKEY_MO_VERIFY	0x0002
+#define EVP_PKEY_MO_ENCRYPT	0x0004
+#define EVP_PKEY_MO_DECRYPT	0x0008
+
+#if 0
+/* This structure is required to tie the message digest and signing together.
+ * The lookup can be done by md/pkey_method, oid, oid/pkey_method, or
+ * oid, md and pkey.
+ * This is required because for various smart-card perform the digest and
+ * signing/verification on-board.  To handle this case, the specific
+ * EVP_MD and EVP_PKEY_METHODs need to be closely associated.
+ * When a PKEY is created, it will have a EVP_PKEY_METHOD associated with it.
+ * This can either be software or a token to provide the required low level
+ * routines.
+ */
+typedef struct evp_pkey_md_st
+	{
+	int oid;
+	EVP_MD *md;
+	EVP_PKEY_METHOD *pkey;
+	} EVP_PKEY_MD;
+
+#define EVP_rsa_md2() \
+		EVP_PKEY_MD_add(NID_md2WithRSAEncryption,\
+			EVP_rsa_pkcs1(),EVP_md2())
+#define EVP_rsa_md5() \
+		EVP_PKEY_MD_add(NID_md5WithRSAEncryption,\
+			EVP_rsa_pkcs1(),EVP_md5())
+#define EVP_rsa_sha0() \
+		EVP_PKEY_MD_add(NID_shaWithRSAEncryption,\
+			EVP_rsa_pkcs1(),EVP_sha())
+#define EVP_rsa_sha1() \
+		EVP_PKEY_MD_add(NID_sha1WithRSAEncryption,\
+			EVP_rsa_pkcs1(),EVP_sha1())
+#define EVP_rsa_ripemd160() \
+		EVP_PKEY_MD_add(NID_ripemd160WithRSA,\
+			EVP_rsa_pkcs1(),EVP_ripemd160())
+#define EVP_rsa_mdc2() \
+		EVP_PKEY_MD_add(NID_mdc2WithRSA,\
+			EVP_rsa_octet_string(),EVP_mdc2())
+#define EVP_dsa_sha() \
+		EVP_PKEY_MD_add(NID_dsaWithSHA,\
+			EVP_dsa(),EVP_sha())
+#define EVP_dsa_sha1() \
+		EVP_PKEY_MD_add(NID_dsaWithSHA1,\
+			EVP_dsa(),EVP_sha1())
+
+typedef struct evp_pkey_method_st
+	{
+	char *name;
+	int flags;
+	int type;		/* RSA, DSA, an SSLeay specific constant */
+	int oid;		/* For the pub-key type */
+	int encrypt_oid;	/* pub/priv key encryption */
+
+	int (*sign)();
+	int (*verify)();
+	struct	{
+		int (*set)();	/* get and/or set the underlying type */
+		int (*get)();
+		int (*encrypt)();
+		int (*decrypt)();
+		int (*i2d)();
+		int (*d2i)();
+		int (*dup)();
+		} pub,priv;
+	int (*set_asn1_parameters)();
+	int (*get_asn1_parameters)();
+	} EVP_PKEY_METHOD;
+#endif
+
+#ifndef EVP_MD
+struct env_md_st
+	{
+	int type;
+	int pkey_type;
+	int md_size;
+	unsigned long flags;
+	int (*init)(EVP_MD_CTX *ctx);
+	int (*update)(EVP_MD_CTX *ctx,const void *data,size_t count);
+	int (*final)(EVP_MD_CTX *ctx,unsigned char *md);
+	int (*copy)(EVP_MD_CTX *to,const EVP_MD_CTX *from);
+	int (*cleanup)(EVP_MD_CTX *ctx);
+
+	/* FIXME: prototype these some day */
+	int (*sign)(int type, const unsigned char *m, unsigned int m_length,
+		    unsigned char *sigret, unsigned int *siglen, void *key);
+	int (*verify)(int type, const unsigned char *m, unsigned int m_length,
+		      const unsigned char *sigbuf, unsigned int siglen,
+		      void *key);
+	int required_pkey_type[5]; /*EVP_PKEY_xxx */
+	int block_size;
+	int ctx_size; /* how big does the ctx->md_data need to be */
+	} /* EVP_MD */;
+
+typedef int evp_sign_method(int type,const unsigned char *m,
+			    unsigned int m_length,unsigned char *sigret,
+			    unsigned int *siglen, void *key);
+typedef int evp_verify_method(int type,const unsigned char *m,
+			    unsigned int m_length,const unsigned char *sigbuf,
+			    unsigned int siglen, void *key);
+
+#define EVP_MD_FLAG_ONESHOT	0x0001 /* digest can only handle a single
+					* block */
+
+#define EVP_PKEY_NULL_method	NULL,NULL,{0,0,0,0}
+
+#ifndef OPENSSL_NO_DSA
+#define EVP_PKEY_DSA_method	(evp_sign_method *)DSA_sign, \
+				(evp_verify_method *)DSA_verify, \
+				{EVP_PKEY_DSA,EVP_PKEY_DSA2,EVP_PKEY_DSA3, \
+					EVP_PKEY_DSA4,0}
+#else
+#define EVP_PKEY_DSA_method	EVP_PKEY_NULL_method
+#endif
+
+#ifndef OPENSSL_NO_ECDSA
+#define EVP_PKEY_ECDSA_method   (evp_sign_method *)ECDSA_sign, \
+				(evp_verify_method *)ECDSA_verify, \
+                                 {EVP_PKEY_EC,0,0,0}
+#else   
+#define EVP_PKEY_ECDSA_method   EVP_PKEY_NULL_method
+#endif
+
+#ifndef OPENSSL_NO_RSA
+#define EVP_PKEY_RSA_method	(evp_sign_method *)RSA_sign, \
+				(evp_verify_method *)RSA_verify, \
+				{EVP_PKEY_RSA,EVP_PKEY_RSA2,0,0}
+#define EVP_PKEY_RSA_ASN1_OCTET_STRING_method \
+				(evp_sign_method *)RSA_sign_ASN1_OCTET_STRING, \
+				(evp_verify_method *)RSA_verify_ASN1_OCTET_STRING, \
+				{EVP_PKEY_RSA,EVP_PKEY_RSA2,0,0}
+#else
+#define EVP_PKEY_RSA_method	EVP_PKEY_NULL_method
+#define EVP_PKEY_RSA_ASN1_OCTET_STRING_method EVP_PKEY_NULL_method
+#endif
+
+#endif /* !EVP_MD */
+
+struct env_md_ctx_st
+	{
+	const EVP_MD *digest;
+	ENGINE *engine; /* functional reference if 'digest' is ENGINE-provided */
+	unsigned long flags;
+	void *md_data;
+	} /* EVP_MD_CTX */;
+
+/* values for EVP_MD_CTX flags */
+
+#define EVP_MD_CTX_FLAG_ONESHOT		0x0001 /* digest update will be called
+						* once only */
+#define EVP_MD_CTX_FLAG_CLEANED		0x0002 /* context has already been
+						* cleaned */
+#define EVP_MD_CTX_FLAG_REUSE		0x0004 /* Don't free up ctx->md_data
+						* in EVP_MD_CTX_cleanup */
+
+struct evp_cipher_st
+	{
+	int nid;
+	int block_size;
+	int key_len;		/* Default value for variable length ciphers */
+	int iv_len;
+	unsigned long flags;	/* Various flags */
+	int (*init)(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+		    const unsigned char *iv, int enc);	/* init key */
+	int (*do_cipher)(EVP_CIPHER_CTX *ctx, unsigned char *out,
+			 const unsigned char *in, unsigned int inl);/* encrypt/decrypt data */
+	int (*cleanup)(EVP_CIPHER_CTX *); /* cleanup ctx */
+	int ctx_size;		/* how big ctx->cipher_data needs to be */
+	int (*set_asn1_parameters)(EVP_CIPHER_CTX *, ASN1_TYPE *); /* Populate a ASN1_TYPE with parameters */
+	int (*get_asn1_parameters)(EVP_CIPHER_CTX *, ASN1_TYPE *); /* Get parameters from a ASN1_TYPE */
+	int (*ctrl)(EVP_CIPHER_CTX *, int type, int arg, void *ptr); /* Miscellaneous operations */
+	void *app_data;		/* Application data */
+	} /* EVP_CIPHER */;
+
+/* Values for cipher flags */
+
+/* Modes for ciphers */
+
+#define		EVP_CIPH_STREAM_CIPHER		0x0
+#define		EVP_CIPH_ECB_MODE		0x1
+#define		EVP_CIPH_CBC_MODE		0x2
+#define		EVP_CIPH_CFB_MODE		0x3
+#define		EVP_CIPH_OFB_MODE		0x4
+#define 	EVP_CIPH_MODE			0x7
+/* Set if variable length cipher */
+#define 	EVP_CIPH_VARIABLE_LENGTH	0x8
+/* Set if the iv handling should be done by the cipher itself */
+#define 	EVP_CIPH_CUSTOM_IV		0x10
+/* Set if the cipher's init() function should be called if key is NULL */
+#define 	EVP_CIPH_ALWAYS_CALL_INIT	0x20
+/* Call ctrl() to init cipher parameters */
+#define 	EVP_CIPH_CTRL_INIT		0x40
+/* Don't use standard key length function */
+#define 	EVP_CIPH_CUSTOM_KEY_LENGTH	0x80
+/* Don't use standard block padding */
+#define 	EVP_CIPH_NO_PADDING		0x100
+/* cipher handles random key generation */
+#define 	EVP_CIPH_RAND_KEY		0x200
+
+/* ctrl() values */
+
+#define		EVP_CTRL_INIT			0x0
+#define 	EVP_CTRL_SET_KEY_LENGTH		0x1
+#define 	EVP_CTRL_GET_RC2_KEY_BITS	0x2
+#define 	EVP_CTRL_SET_RC2_KEY_BITS	0x3
+#define 	EVP_CTRL_GET_RC5_ROUNDS		0x4
+#define 	EVP_CTRL_SET_RC5_ROUNDS		0x5
+#define 	EVP_CTRL_RAND_KEY		0x6
+
+typedef struct evp_cipher_info_st
+	{
+	const EVP_CIPHER *cipher;
+	unsigned char iv[EVP_MAX_IV_LENGTH];
+	} EVP_CIPHER_INFO;
+
+struct evp_cipher_ctx_st
+	{
+	const EVP_CIPHER *cipher;
+	ENGINE *engine;	/* functional reference if 'cipher' is ENGINE-provided */
+	int encrypt;		/* encrypt or decrypt */
+	int buf_len;		/* number we have left */
+
+	unsigned char  oiv[EVP_MAX_IV_LENGTH];	/* original iv */
+	unsigned char  iv[EVP_MAX_IV_LENGTH];	/* working iv */
+	unsigned char buf[EVP_MAX_BLOCK_LENGTH];/* saved partial block */
+	int num;				/* used by cfb/ofb mode */
+
+	void *app_data;		/* application stuff */
+	int key_len;		/* May change for variable length cipher */
+	unsigned long flags;	/* Various flags */
+	void *cipher_data; /* per EVP data */
+	int final_used;
+	int block_mask;
+	unsigned char final[EVP_MAX_BLOCK_LENGTH];/* possible final block */
+	} /* EVP_CIPHER_CTX */;
+
+typedef struct evp_Encode_Ctx_st
+	{
+	int num;	/* number saved in a partial encode/decode */
+	int length;	/* The length is either the output line length
+			 * (in input bytes) or the shortest input line
+			 * length that is ok.  Once decoding begins,
+			 * the length is adjusted up each time a longer
+			 * line is decoded */
+	unsigned char enc_data[80];	/* data to encode */
+	int line_num;	/* number read on current line */
+	int expect_nl;
+	} EVP_ENCODE_CTX;
+
+/* Password based encryption function */
+typedef int (EVP_PBE_KEYGEN)(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+		ASN1_TYPE *param, const EVP_CIPHER *cipher,
+                const EVP_MD *md, int en_de);
+
+#ifndef OPENSSL_NO_RSA
+#define EVP_PKEY_assign_RSA(pkey,rsa) EVP_PKEY_assign((pkey),EVP_PKEY_RSA,\
+					(char *)(rsa))
+#endif
+
+#ifndef OPENSSL_NO_DSA
+#define EVP_PKEY_assign_DSA(pkey,dsa) EVP_PKEY_assign((pkey),EVP_PKEY_DSA,\
+					(char *)(dsa))
+#endif
+
+#ifndef OPENSSL_NO_DH
+#define EVP_PKEY_assign_DH(pkey,dh) EVP_PKEY_assign((pkey),EVP_PKEY_DH,\
+					(char *)(dh))
+#endif
+
+#ifndef OPENSSL_NO_EC
+#define EVP_PKEY_assign_EC_KEY(pkey,eckey) EVP_PKEY_assign((pkey),EVP_PKEY_EC,\
+                                        (char *)(eckey))
+#endif
+
+/* Add some extra combinations */
+#define EVP_get_digestbynid(a) EVP_get_digestbyname(OBJ_nid2sn(a))
+#define EVP_get_digestbyobj(a) EVP_get_digestbynid(OBJ_obj2nid(a))
+#define EVP_get_cipherbynid(a) EVP_get_cipherbyname(OBJ_nid2sn(a))
+#define EVP_get_cipherbyobj(a) EVP_get_cipherbynid(OBJ_obj2nid(a))
+
+int EVP_MD_type(const EVP_MD *md);
+#define EVP_MD_nid(e)			EVP_MD_type(e)
+#define EVP_MD_name(e)			OBJ_nid2sn(EVP_MD_nid(e))
+int EVP_MD_pkey_type(const EVP_MD *md);	
+int EVP_MD_size(const EVP_MD *md);
+int EVP_MD_block_size(const EVP_MD *md);
+
+const EVP_MD * EVP_MD_CTX_md(const EVP_MD_CTX *ctx);
+#define EVP_MD_CTX_size(e)		EVP_MD_size(EVP_MD_CTX_md(e))
+#define EVP_MD_CTX_block_size(e)	EVP_MD_block_size(EVP_MD_CTX_md(e))
+#define EVP_MD_CTX_type(e)		EVP_MD_type(EVP_MD_CTX_md(e))
+
+int EVP_CIPHER_nid(const EVP_CIPHER *cipher);
+#define EVP_CIPHER_name(e)		OBJ_nid2sn(EVP_CIPHER_nid(e))
+int EVP_CIPHER_block_size(const EVP_CIPHER *cipher);
+int EVP_CIPHER_key_length(const EVP_CIPHER *cipher);
+int EVP_CIPHER_iv_length(const EVP_CIPHER *cipher);
+unsigned long EVP_CIPHER_flags(const EVP_CIPHER *cipher);
+#define EVP_CIPHER_mode(e)		(EVP_CIPHER_flags(e) & EVP_CIPH_MODE)
+
+const EVP_CIPHER * EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *ctx);
+int EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx);
+int EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx);
+int EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx);
+int EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx);
+void * EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx);
+void EVP_CIPHER_CTX_set_app_data(EVP_CIPHER_CTX *ctx, void *data);
+#define EVP_CIPHER_CTX_type(c)         EVP_CIPHER_type(EVP_CIPHER_CTX_cipher(c))
+unsigned long EVP_CIPHER_CTX_flags(const EVP_CIPHER_CTX *ctx);
+#define EVP_CIPHER_CTX_mode(e)		(EVP_CIPHER_CTX_flags(e) & EVP_CIPH_MODE)
+
+#define EVP_ENCODE_LENGTH(l)	(((l+2)/3*4)+(l/48+1)*2+80)
+#define EVP_DECODE_LENGTH(l)	((l+3)/4*3+80)
+
+#define EVP_SignInit_ex(a,b,c)		EVP_DigestInit_ex(a,b,c)
+#define EVP_SignInit(a,b)		EVP_DigestInit(a,b)
+#define EVP_SignUpdate(a,b,c)		EVP_DigestUpdate(a,b,c)
+#define	EVP_VerifyInit_ex(a,b,c)	EVP_DigestInit_ex(a,b,c)
+#define	EVP_VerifyInit(a,b)		EVP_DigestInit(a,b)
+#define	EVP_VerifyUpdate(a,b,c)		EVP_DigestUpdate(a,b,c)
+#define EVP_OpenUpdate(a,b,c,d,e)	EVP_DecryptUpdate(a,b,c,d,e)
+#define EVP_SealUpdate(a,b,c,d,e)	EVP_EncryptUpdate(a,b,c,d,e)	
+
+#ifdef CONST_STRICT
+void BIO_set_md(BIO *,const EVP_MD *md);
+#else
+# define BIO_set_md(b,md)		BIO_ctrl(b,BIO_C_SET_MD,0,(char *)md)
+#endif
+#define BIO_get_md(b,mdp)		BIO_ctrl(b,BIO_C_GET_MD,0,(char *)mdp)
+#define BIO_get_md_ctx(b,mdcp)     BIO_ctrl(b,BIO_C_GET_MD_CTX,0,(char *)mdcp)
+#define BIO_set_md_ctx(b,mdcp)     BIO_ctrl(b,BIO_C_SET_MD_CTX,0,(char *)mdcp)
+#define BIO_get_cipher_status(b)	BIO_ctrl(b,BIO_C_GET_CIPHER_STATUS,0,NULL)
+#define BIO_get_cipher_ctx(b,c_pp)	BIO_ctrl(b,BIO_C_GET_CIPHER_CTX,0,(char *)c_pp)
+
+int EVP_Cipher(EVP_CIPHER_CTX *c,
+		unsigned char *out,
+		const unsigned char *in,
+		unsigned int inl);
+
+#define EVP_add_cipher_alias(n,alias) \
+	OBJ_NAME_add((alias),OBJ_NAME_TYPE_CIPHER_METH|OBJ_NAME_ALIAS,(n))
+#define EVP_add_digest_alias(n,alias) \
+	OBJ_NAME_add((alias),OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS,(n))
+#define EVP_delete_cipher_alias(alias) \
+	OBJ_NAME_remove(alias,OBJ_NAME_TYPE_CIPHER_METH|OBJ_NAME_ALIAS);
+#define EVP_delete_digest_alias(alias) \
+	OBJ_NAME_remove(alias,OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS);
+
+void	EVP_MD_CTX_init(EVP_MD_CTX *ctx);
+int	EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx);
+EVP_MD_CTX *EVP_MD_CTX_create(void);
+void	EVP_MD_CTX_destroy(EVP_MD_CTX *ctx);
+int     EVP_MD_CTX_copy_ex(EVP_MD_CTX *out,const EVP_MD_CTX *in);  
+void	EVP_MD_CTX_set_flags(EVP_MD_CTX *ctx, int flags);
+void	EVP_MD_CTX_clear_flags(EVP_MD_CTX *ctx, int flags);
+int 	EVP_MD_CTX_test_flags(const EVP_MD_CTX *ctx,int flags);
+int	EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl);
+int	EVP_DigestUpdate(EVP_MD_CTX *ctx,const void *d,
+			 size_t cnt);
+int	EVP_DigestFinal_ex(EVP_MD_CTX *ctx,unsigned char *md,unsigned int *s);
+int	EVP_Digest(const void *data, size_t count,
+		unsigned char *md, unsigned int *size, const EVP_MD *type, ENGINE *impl);
+
+int     EVP_MD_CTX_copy(EVP_MD_CTX *out,const EVP_MD_CTX *in);  
+int	EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type);
+int	EVP_DigestFinal(EVP_MD_CTX *ctx,unsigned char *md,unsigned int *s);
+
+int	EVP_read_pw_string(char *buf,int length,const char *prompt,int verify);
+void	EVP_set_pw_prompt(const char *prompt);
+char *	EVP_get_pw_prompt(void);
+
+int	EVP_BytesToKey(const EVP_CIPHER *type,const EVP_MD *md,
+		const unsigned char *salt, const unsigned char *data,
+		int datal, int count, unsigned char *key,unsigned char *iv);
+
+int	EVP_EncryptInit(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher,
+		const unsigned char *key, const unsigned char *iv);
+int	EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher, ENGINE *impl,
+		const unsigned char *key, const unsigned char *iv);
+int	EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
+		int *outl, const unsigned char *in, int inl);
+int	EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
+int	EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
+
+int	EVP_DecryptInit(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher,
+		const unsigned char *key, const unsigned char *iv);
+int	EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher, ENGINE *impl,
+		const unsigned char *key, const unsigned char *iv);
+int	EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
+		int *outl, const unsigned char *in, int inl);
+int	EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
+int	EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
+
+int	EVP_CipherInit(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher,
+		       const unsigned char *key,const unsigned char *iv,
+		       int enc);
+int	EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher, ENGINE *impl,
+		       const unsigned char *key,const unsigned char *iv,
+		       int enc);
+int	EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
+		int *outl, const unsigned char *in, int inl);
+int	EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
+int	EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
+
+int	EVP_SignFinal(EVP_MD_CTX *ctx,unsigned char *md,unsigned int *s,
+		EVP_PKEY *pkey);
+
+int	EVP_VerifyFinal(EVP_MD_CTX *ctx,const unsigned char *sigbuf,
+		unsigned int siglen,EVP_PKEY *pkey);
+
+int	EVP_OpenInit(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *type,
+		const unsigned char *ek, int ekl, const unsigned char *iv,
+		EVP_PKEY *priv);
+int	EVP_OpenFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
+
+int	EVP_SealInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
+		 unsigned char **ek, int *ekl, unsigned char *iv,
+		EVP_PKEY **pubk, int npubk);
+int	EVP_SealFinal(EVP_CIPHER_CTX *ctx,unsigned char *out,int *outl);
+
+void	EVP_EncodeInit(EVP_ENCODE_CTX *ctx);
+void	EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx,unsigned char *out,int *outl,
+		const unsigned char *in,int inl);
+void	EVP_EncodeFinal(EVP_ENCODE_CTX *ctx,unsigned char *out,int *outl);
+int	EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int n);
+
+void	EVP_DecodeInit(EVP_ENCODE_CTX *ctx);
+int	EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx,unsigned char *out,int *outl,
+		const unsigned char *in, int inl);
+int	EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned
+		char *out, int *outl);
+int	EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n);
+
+void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *a);
+int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a);
+EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void);
+void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *a);
+int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen);
+int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *c, int pad);
+int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr);
+int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key);
+
+#ifndef OPENSSL_NO_BIO
+BIO_METHOD *BIO_f_md(void);
+BIO_METHOD *BIO_f_base64(void);
+BIO_METHOD *BIO_f_cipher(void);
+BIO_METHOD *BIO_f_reliable(void);
+void BIO_set_cipher(BIO *b,const EVP_CIPHER *c,const unsigned char *k,
+		const unsigned char *i, int enc);
+#endif
+
+const EVP_MD *EVP_md_null(void);
+#ifndef OPENSSL_NO_MD2
+const EVP_MD *EVP_md2(void);
+#endif
+#ifndef OPENSSL_NO_MD4
+const EVP_MD *EVP_md4(void);
+#endif
+#ifndef OPENSSL_NO_MD5
+const EVP_MD *EVP_md5(void);
+#endif
+#ifndef OPENSSL_NO_SHA
+const EVP_MD *EVP_sha(void);
+const EVP_MD *EVP_sha1(void);
+const EVP_MD *EVP_dss(void);
+const EVP_MD *EVP_dss1(void);
+const EVP_MD *EVP_ecdsa(void);
+#endif
+#ifndef OPENSSL_NO_SHA256
+const EVP_MD *EVP_sha224(void);
+const EVP_MD *EVP_sha256(void);
+#endif
+#ifndef OPENSSL_NO_SHA512
+const EVP_MD *EVP_sha384(void);
+const EVP_MD *EVP_sha512(void);
+#endif
+#ifndef OPENSSL_NO_MDC2
+const EVP_MD *EVP_mdc2(void);
+#endif
+#ifndef OPENSSL_NO_RIPEMD
+const EVP_MD *EVP_ripemd160(void);
+#endif
+const EVP_CIPHER *EVP_enc_null(void);		/* does nothing :-) */
+#ifndef OPENSSL_NO_DES
+const EVP_CIPHER *EVP_des_ecb(void);
+const EVP_CIPHER *EVP_des_ede(void);
+const EVP_CIPHER *EVP_des_ede3(void);
+const EVP_CIPHER *EVP_des_ede_ecb(void);
+const EVP_CIPHER *EVP_des_ede3_ecb(void);
+const EVP_CIPHER *EVP_des_cfb64(void);
+# define EVP_des_cfb EVP_des_cfb64
+const EVP_CIPHER *EVP_des_cfb1(void);
+const EVP_CIPHER *EVP_des_cfb8(void);
+const EVP_CIPHER *EVP_des_ede_cfb64(void);
+# define EVP_des_ede_cfb EVP_des_ede_cfb64
+#if 0
+const EVP_CIPHER *EVP_des_ede_cfb1(void);
+const EVP_CIPHER *EVP_des_ede_cfb8(void);
+#endif
+const EVP_CIPHER *EVP_des_ede3_cfb64(void);
+# define EVP_des_ede3_cfb EVP_des_ede3_cfb64
+const EVP_CIPHER *EVP_des_ede3_cfb1(void);
+const EVP_CIPHER *EVP_des_ede3_cfb8(void);
+const EVP_CIPHER *EVP_des_ofb(void);
+const EVP_CIPHER *EVP_des_ede_ofb(void);
+const EVP_CIPHER *EVP_des_ede3_ofb(void);
+const EVP_CIPHER *EVP_des_cbc(void);
+const EVP_CIPHER *EVP_des_ede_cbc(void);
+const EVP_CIPHER *EVP_des_ede3_cbc(void);
+const EVP_CIPHER *EVP_desx_cbc(void);
+/* This should now be supported through the dev_crypto ENGINE. But also, why are
+ * rc4 and md5 declarations made here inside a "NO_DES" precompiler branch? */
+#if 0
+# ifdef OPENSSL_OPENBSD_DEV_CRYPTO
+const EVP_CIPHER *EVP_dev_crypto_des_ede3_cbc(void);
+const EVP_CIPHER *EVP_dev_crypto_rc4(void);
+const EVP_MD *EVP_dev_crypto_md5(void);
+# endif
+#endif
+#endif
+#ifndef OPENSSL_NO_RC4
+const EVP_CIPHER *EVP_rc4(void);
+const EVP_CIPHER *EVP_rc4_40(void);
+#endif
+#ifndef OPENSSL_NO_IDEA
+const EVP_CIPHER *EVP_idea_ecb(void);
+const EVP_CIPHER *EVP_idea_cfb64(void);
+# define EVP_idea_cfb EVP_idea_cfb64
+const EVP_CIPHER *EVP_idea_ofb(void);
+const EVP_CIPHER *EVP_idea_cbc(void);
+#endif
+#ifndef OPENSSL_NO_RC2
+const EVP_CIPHER *EVP_rc2_ecb(void);
+const EVP_CIPHER *EVP_rc2_cbc(void);
+const EVP_CIPHER *EVP_rc2_40_cbc(void);
+const EVP_CIPHER *EVP_rc2_64_cbc(void);
+const EVP_CIPHER *EVP_rc2_cfb64(void);
+# define EVP_rc2_cfb EVP_rc2_cfb64
+const EVP_CIPHER *EVP_rc2_ofb(void);
+#endif
+#ifndef OPENSSL_NO_BF
+const EVP_CIPHER *EVP_bf_ecb(void);
+const EVP_CIPHER *EVP_bf_cbc(void);
+const EVP_CIPHER *EVP_bf_cfb64(void);
+# define EVP_bf_cfb EVP_bf_cfb64
+const EVP_CIPHER *EVP_bf_ofb(void);
+#endif
+#ifndef OPENSSL_NO_CAST
+const EVP_CIPHER *EVP_cast5_ecb(void);
+const EVP_CIPHER *EVP_cast5_cbc(void);
+const EVP_CIPHER *EVP_cast5_cfb64(void);
+# define EVP_cast5_cfb EVP_cast5_cfb64
+const EVP_CIPHER *EVP_cast5_ofb(void);
+#endif
+#ifndef OPENSSL_NO_RC5
+const EVP_CIPHER *EVP_rc5_32_12_16_cbc(void);
+const EVP_CIPHER *EVP_rc5_32_12_16_ecb(void);
+const EVP_CIPHER *EVP_rc5_32_12_16_cfb64(void);
+# define EVP_rc5_32_12_16_cfb EVP_rc5_32_12_16_cfb64
+const EVP_CIPHER *EVP_rc5_32_12_16_ofb(void);
+#endif
+#ifndef OPENSSL_NO_AES
+const EVP_CIPHER *EVP_aes_128_ecb(void);
+const EVP_CIPHER *EVP_aes_128_cbc(void);
+const EVP_CIPHER *EVP_aes_128_cfb1(void);
+const EVP_CIPHER *EVP_aes_128_cfb8(void);
+const EVP_CIPHER *EVP_aes_128_cfb128(void);
+# define EVP_aes_128_cfb EVP_aes_128_cfb128
+const EVP_CIPHER *EVP_aes_128_ofb(void);
+#if 0
+const EVP_CIPHER *EVP_aes_128_ctr(void);
+#endif
+const EVP_CIPHER *EVP_aes_192_ecb(void);
+const EVP_CIPHER *EVP_aes_192_cbc(void);
+const EVP_CIPHER *EVP_aes_192_cfb1(void);
+const EVP_CIPHER *EVP_aes_192_cfb8(void);
+const EVP_CIPHER *EVP_aes_192_cfb128(void);
+# define EVP_aes_192_cfb EVP_aes_192_cfb128
+const EVP_CIPHER *EVP_aes_192_ofb(void);
+#if 0
+const EVP_CIPHER *EVP_aes_192_ctr(void);
+#endif
+const EVP_CIPHER *EVP_aes_256_ecb(void);
+const EVP_CIPHER *EVP_aes_256_cbc(void);
+const EVP_CIPHER *EVP_aes_256_cfb1(void);
+const EVP_CIPHER *EVP_aes_256_cfb8(void);
+const EVP_CIPHER *EVP_aes_256_cfb128(void);
+# define EVP_aes_256_cfb EVP_aes_256_cfb128
+const EVP_CIPHER *EVP_aes_256_ofb(void);
+#if 0
+const EVP_CIPHER *EVP_aes_256_ctr(void);
+#endif
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+const EVP_CIPHER *EVP_camellia_128_ecb(void);
+const EVP_CIPHER *EVP_camellia_128_cbc(void);
+const EVP_CIPHER *EVP_camellia_128_cfb1(void);
+const EVP_CIPHER *EVP_camellia_128_cfb8(void);
+const EVP_CIPHER *EVP_camellia_128_cfb128(void);
+# define EVP_camellia_128_cfb EVP_camellia_128_cfb128
+const EVP_CIPHER *EVP_camellia_128_ofb(void);
+const EVP_CIPHER *EVP_camellia_192_ecb(void);
+const EVP_CIPHER *EVP_camellia_192_cbc(void);
+const EVP_CIPHER *EVP_camellia_192_cfb1(void);
+const EVP_CIPHER *EVP_camellia_192_cfb8(void);
+const EVP_CIPHER *EVP_camellia_192_cfb128(void);
+# define EVP_camellia_192_cfb EVP_camellia_192_cfb128
+const EVP_CIPHER *EVP_camellia_192_ofb(void);
+const EVP_CIPHER *EVP_camellia_256_ecb(void);
+const EVP_CIPHER *EVP_camellia_256_cbc(void);
+const EVP_CIPHER *EVP_camellia_256_cfb1(void);
+const EVP_CIPHER *EVP_camellia_256_cfb8(void);
+const EVP_CIPHER *EVP_camellia_256_cfb128(void);
+# define EVP_camellia_256_cfb EVP_camellia_256_cfb128
+const EVP_CIPHER *EVP_camellia_256_ofb(void);
+#endif
+
+void OPENSSL_add_all_algorithms_noconf(void);
+void OPENSSL_add_all_algorithms_conf(void);
+
+#ifdef OPENSSL_LOAD_CONF
+#define OpenSSL_add_all_algorithms() \
+		OPENSSL_add_all_algorithms_conf()
+#else
+#define OpenSSL_add_all_algorithms() \
+		OPENSSL_add_all_algorithms_noconf()
+#endif
+
+void OpenSSL_add_all_ciphers(void);
+void OpenSSL_add_all_digests(void);
+#define SSLeay_add_all_algorithms() OpenSSL_add_all_algorithms()
+#define SSLeay_add_all_ciphers() OpenSSL_add_all_ciphers()
+#define SSLeay_add_all_digests() OpenSSL_add_all_digests()
+
+int EVP_add_cipher(const EVP_CIPHER *cipher);
+int EVP_add_digest(const EVP_MD *digest);
+
+const EVP_CIPHER *EVP_get_cipherbyname(const char *name);
+const EVP_MD *EVP_get_digestbyname(const char *name);
+void EVP_cleanup(void);
+
+int		EVP_PKEY_decrypt(unsigned char *dec_key,
+			const unsigned char *enc_key,int enc_key_len,
+			EVP_PKEY *private_key);
+int		EVP_PKEY_encrypt(unsigned char *enc_key,
+			const unsigned char *key,int key_len,
+			EVP_PKEY *pub_key);
+int		EVP_PKEY_type(int type);
+int		EVP_PKEY_bits(EVP_PKEY *pkey);
+int		EVP_PKEY_size(EVP_PKEY *pkey);
+int 		EVP_PKEY_assign(EVP_PKEY *pkey,int type,char *key);
+
+#ifndef OPENSSL_NO_RSA
+struct rsa_st;
+int EVP_PKEY_set1_RSA(EVP_PKEY *pkey,struct rsa_st *key);
+struct rsa_st *EVP_PKEY_get1_RSA(EVP_PKEY *pkey);
+#endif
+#ifndef OPENSSL_NO_DSA
+struct dsa_st;
+int EVP_PKEY_set1_DSA(EVP_PKEY *pkey,struct dsa_st *key);
+struct dsa_st *EVP_PKEY_get1_DSA(EVP_PKEY *pkey);
+#endif
+#ifndef OPENSSL_NO_DH
+struct dh_st;
+int EVP_PKEY_set1_DH(EVP_PKEY *pkey,struct dh_st *key);
+struct dh_st *EVP_PKEY_get1_DH(EVP_PKEY *pkey);
+#endif
+#ifndef OPENSSL_NO_EC
+struct ec_key_st;
+int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey,struct ec_key_st *key);
+struct ec_key_st *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey);
+#endif
+
+EVP_PKEY *	EVP_PKEY_new(void);
+void		EVP_PKEY_free(EVP_PKEY *pkey);
+
+EVP_PKEY *	d2i_PublicKey(int type,EVP_PKEY **a, const unsigned char **pp,
+			long length);
+int		i2d_PublicKey(EVP_PKEY *a, unsigned char **pp);
+
+EVP_PKEY *	d2i_PrivateKey(int type,EVP_PKEY **a, const unsigned char **pp,
+			long length);
+EVP_PKEY *	d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp,
+			long length);
+int		i2d_PrivateKey(EVP_PKEY *a, unsigned char **pp);
+
+int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from);
+int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey);
+int EVP_PKEY_save_parameters(EVP_PKEY *pkey,int mode);
+int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b);
+
+int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b);
+
+int EVP_CIPHER_type(const EVP_CIPHER *ctx);
+
+/* calls methods */
+int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
+int EVP_CIPHER_asn1_to_param(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
+
+/* These are used by EVP_CIPHER methods */
+int EVP_CIPHER_set_asn1_iv(EVP_CIPHER_CTX *c,ASN1_TYPE *type);
+int EVP_CIPHER_get_asn1_iv(EVP_CIPHER_CTX *c,ASN1_TYPE *type);
+
+/* PKCS5 password based encryption */
+int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+			 ASN1_TYPE *param, const EVP_CIPHER *cipher, const EVP_MD *md,
+			 int en_de);
+int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen,
+			   const unsigned char *salt, int saltlen, int iter,
+			   int keylen, unsigned char *out);
+int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+			 ASN1_TYPE *param, const EVP_CIPHER *cipher, const EVP_MD *md,
+			 int en_de);
+
+void PKCS5_PBE_add(void);
+
+int EVP_PBE_CipherInit (ASN1_OBJECT *pbe_obj, const char *pass, int passlen,
+	     ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de);
+int EVP_PBE_alg_add(int nid, const EVP_CIPHER *cipher, const EVP_MD *md,
+		    EVP_PBE_KEYGEN *keygen);
+void EVP_PBE_cleanup(void);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_EVP_strings(void);
+
+/* Error codes for the EVP functions. */
+
+/* Function codes. */
+#define EVP_F_AES_INIT_KEY				 133
+#define EVP_F_CAMELLIA_INIT_KEY				 159
+#define EVP_F_D2I_PKEY					 100
+#define EVP_F_DSAPKEY2PKCS8				 134
+#define EVP_F_DSA_PKEY2PKCS8				 135
+#define EVP_F_ECDSA_PKEY2PKCS8				 129
+#define EVP_F_ECKEY_PKEY2PKCS8				 132
+#define EVP_F_EVP_CIPHERINIT_EX				 123
+#define EVP_F_EVP_CIPHER_CTX_CTRL			 124
+#define EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH		 122
+#define EVP_F_EVP_DECRYPTFINAL_EX			 101
+#define EVP_F_EVP_DIGESTINIT_EX				 128
+#define EVP_F_EVP_ENCRYPTFINAL_EX			 127
+#define EVP_F_EVP_MD_CTX_COPY_EX			 110
+#define EVP_F_EVP_OPENINIT				 102
+#define EVP_F_EVP_PBE_ALG_ADD				 115
+#define EVP_F_EVP_PBE_CIPHERINIT			 116
+#define EVP_F_EVP_PKCS82PKEY				 111
+#define EVP_F_EVP_PKEY2PKCS8_BROKEN			 113
+#define EVP_F_EVP_PKEY_COPY_PARAMETERS			 103
+#define EVP_F_EVP_PKEY_DECRYPT				 104
+#define EVP_F_EVP_PKEY_ENCRYPT				 105
+#define EVP_F_EVP_PKEY_GET1_DH				 119
+#define EVP_F_EVP_PKEY_GET1_DSA				 120
+#define EVP_F_EVP_PKEY_GET1_ECDSA			 130
+#define EVP_F_EVP_PKEY_GET1_EC_KEY			 131
+#define EVP_F_EVP_PKEY_GET1_RSA				 121
+#define EVP_F_EVP_PKEY_NEW				 106
+#define EVP_F_EVP_RIJNDAEL				 126
+#define EVP_F_EVP_SIGNFINAL				 107
+#define EVP_F_EVP_VERIFYFINAL				 108
+#define EVP_F_PKCS5_PBE_KEYIVGEN			 117
+#define EVP_F_PKCS5_V2_PBE_KEYIVGEN			 118
+#define EVP_F_PKCS8_SET_BROKEN				 112
+#define EVP_F_RC2_MAGIC_TO_METH				 109
+#define EVP_F_RC5_CTRL					 125
+
+/* Reason codes. */
+#define EVP_R_AES_KEY_SETUP_FAILED			 143
+#define EVP_R_ASN1_LIB					 140
+#define EVP_R_BAD_BLOCK_LENGTH				 136
+#define EVP_R_BAD_DECRYPT				 100
+#define EVP_R_BAD_KEY_LENGTH				 137
+#define EVP_R_BN_DECODE_ERROR				 112
+#define EVP_R_BN_PUBKEY_ERROR				 113
+#define EVP_R_CAMELLIA_KEY_SETUP_FAILED			 157
+#define EVP_R_CIPHER_PARAMETER_ERROR			 122
+#define EVP_R_CTRL_NOT_IMPLEMENTED			 132
+#define EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED		 133
+#define EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH		 138
+#define EVP_R_DECODE_ERROR				 114
+#define EVP_R_DIFFERENT_KEY_TYPES			 101
+#define EVP_R_ENCODE_ERROR				 115
+#define EVP_R_EVP_PBE_CIPHERINIT_ERROR			 119
+#define EVP_R_EXPECTING_AN_RSA_KEY			 127
+#define EVP_R_EXPECTING_A_DH_KEY			 128
+#define EVP_R_EXPECTING_A_DSA_KEY			 129
+#define EVP_R_EXPECTING_A_ECDSA_KEY			 141
+#define EVP_R_EXPECTING_A_EC_KEY			 142
+#define EVP_R_INITIALIZATION_ERROR			 134
+#define EVP_R_INPUT_NOT_INITIALIZED			 111
+#define EVP_R_INVALID_KEY_LENGTH			 130
+#define EVP_R_IV_TOO_LARGE				 102
+#define EVP_R_KEYGEN_FAILURE				 120
+#define EVP_R_MISSING_PARAMETERS			 103
+#define EVP_R_NO_CIPHER_SET				 131
+#define EVP_R_NO_DIGEST_SET				 139
+#define EVP_R_NO_DSA_PARAMETERS				 116
+#define EVP_R_NO_SIGN_FUNCTION_CONFIGURED		 104
+#define EVP_R_NO_VERIFY_FUNCTION_CONFIGURED		 105
+#define EVP_R_PKCS8_UNKNOWN_BROKEN_TYPE			 117
+#define EVP_R_PUBLIC_KEY_NOT_RSA			 106
+#define EVP_R_UNKNOWN_PBE_ALGORITHM			 121
+#define EVP_R_UNSUPORTED_NUMBER_OF_ROUNDS		 135
+#define EVP_R_UNSUPPORTED_CIPHER			 107
+#define EVP_R_UNSUPPORTED_KEYLENGTH			 123
+#define EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION	 124
+#define EVP_R_UNSUPPORTED_KEY_SIZE			 108
+#define EVP_R_UNSUPPORTED_PRF				 125
+#define EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM		 118
+#define EVP_R_UNSUPPORTED_SALT_TYPE			 126
+#define EVP_R_WRONG_FINAL_BLOCK_LENGTH			 109
+#define EVP_R_WRONG_PUBLIC_KEY_TYPE			 110
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/dep/include/openssl/hmac.h b/dep/include/openssl/hmac.h
new file mode 100644
index 00000000000..719fc408ace
--- /dev/null
+++ b/dep/include/openssl/hmac.h
@@ -0,0 +1,108 @@
+/* crypto/hmac/hmac.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+#ifndef HEADER_HMAC_H
+#define HEADER_HMAC_H
+
+#include 
+
+#ifdef OPENSSL_NO_HMAC
+#error HMAC is disabled.
+#endif
+
+#include 
+
+#define HMAC_MAX_MD_CBLOCK	128	/* largest known is SHA512 */
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+typedef struct hmac_ctx_st
+	{
+	const EVP_MD *md;
+	EVP_MD_CTX md_ctx;
+	EVP_MD_CTX i_ctx;
+	EVP_MD_CTX o_ctx;
+	unsigned int key_length;
+	unsigned char key[HMAC_MAX_MD_CBLOCK];
+	} HMAC_CTX;
+
+#define HMAC_size(e)	(EVP_MD_size((e)->md))
+
+
+void HMAC_CTX_init(HMAC_CTX *ctx);
+void HMAC_CTX_cleanup(HMAC_CTX *ctx);
+
+#define HMAC_cleanup(ctx) HMAC_CTX_cleanup(ctx) /* deprecated */
+
+void HMAC_Init(HMAC_CTX *ctx, const void *key, int len,
+	       const EVP_MD *md); /* deprecated */
+void HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
+		  const EVP_MD *md, ENGINE *impl);
+void HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len);
+void HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len);
+unsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len,
+		    const unsigned char *d, size_t n, unsigned char *md,
+		    unsigned int *md_len);
+
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff --git a/dep/include/openssl/idea.h b/dep/include/openssl/idea.h
new file mode 100644
index 00000000000..bf97a37e39b
--- /dev/null
+++ b/dep/include/openssl/idea.h
@@ -0,0 +1,100 @@
+/* crypto/idea/idea.h */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_IDEA_H
+#define HEADER_IDEA_H
+
+#include  /* IDEA_INT, OPENSSL_NO_IDEA */
+
+#ifdef OPENSSL_NO_IDEA
+#error IDEA is disabled.
+#endif
+
+#define IDEA_ENCRYPT	1
+#define IDEA_DECRYPT	0
+
+#define IDEA_BLOCK	8
+#define IDEA_KEY_LENGTH	16
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+typedef struct idea_key_st
+	{
+	IDEA_INT data[9][6];
+	} IDEA_KEY_SCHEDULE;
+
+const char *idea_options(void);
+void idea_ecb_encrypt(const unsigned char *in, unsigned char *out,
+	IDEA_KEY_SCHEDULE *ks);
+void idea_set_encrypt_key(const unsigned char *key, IDEA_KEY_SCHEDULE *ks);
+void idea_set_decrypt_key(const IDEA_KEY_SCHEDULE *ek, IDEA_KEY_SCHEDULE *dk);
+void idea_cbc_encrypt(const unsigned char *in, unsigned char *out,
+	long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv,int enc);
+void idea_cfb64_encrypt(const unsigned char *in, unsigned char *out,
+	long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv,
+	int *num,int enc);
+void idea_ofb64_encrypt(const unsigned char *in, unsigned char *out,
+	long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv, int *num);
+void idea_encrypt(unsigned long *in, IDEA_KEY_SCHEDULE *ks);
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff --git a/dep/include/openssl/krb5_asn.h b/dep/include/openssl/krb5_asn.h
new file mode 100644
index 00000000000..41725d0dc44
--- /dev/null
+++ b/dep/include/openssl/krb5_asn.h
@@ -0,0 +1,256 @@
+/* krb5_asn.h */
+/* Written by Vern Staats  for the OpenSSL project,
+** using ocsp/{*.h,*asn*.c} as a starting point
+*/
+
+/* ====================================================================
+ * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_KRB5_ASN_H
+#define HEADER_KRB5_ASN_H
+
+/*
+#include 
+*/
+#include 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+
+/*	ASN.1 from Kerberos RFC 1510
+*/
+
+/*	EncryptedData ::=   SEQUENCE {
+**		etype[0]                      INTEGER, -- EncryptionType
+**		kvno[1]                       INTEGER OPTIONAL,
+**		cipher[2]                     OCTET STRING -- ciphertext
+**	}
+*/
+typedef	struct	krb5_encdata_st
+	{
+	ASN1_INTEGER			*etype;
+	ASN1_INTEGER			*kvno;
+	ASN1_OCTET_STRING		*cipher;
+	}	KRB5_ENCDATA;
+
+DECLARE_STACK_OF(KRB5_ENCDATA)
+
+/*	PrincipalName ::=   SEQUENCE {
+**		name-type[0]                  INTEGER,
+**		name-string[1]                SEQUENCE OF GeneralString
+**	}
+*/
+typedef	struct	krb5_princname_st
+	{
+	ASN1_INTEGER			*nametype;
+	STACK_OF(ASN1_GENERALSTRING)	*namestring;
+	}	KRB5_PRINCNAME;
+
+DECLARE_STACK_OF(KRB5_PRINCNAME)
+
+
+/*	Ticket ::=	[APPLICATION 1] SEQUENCE {
+**		tkt-vno[0]                    INTEGER,
+**		realm[1]                      Realm,
+**		sname[2]                      PrincipalName,
+**		enc-part[3]                   EncryptedData
+**	}
+*/
+typedef	struct	krb5_tktbody_st
+	{
+	ASN1_INTEGER			*tktvno;
+	ASN1_GENERALSTRING		*realm;
+	KRB5_PRINCNAME			*sname;
+	KRB5_ENCDATA			*encdata;
+	}	KRB5_TKTBODY;
+
+typedef STACK_OF(KRB5_TKTBODY) KRB5_TICKET;
+DECLARE_STACK_OF(KRB5_TKTBODY)
+
+
+/*	AP-REQ ::=      [APPLICATION 14] SEQUENCE {
+**		pvno[0]                       INTEGER,
+**		msg-type[1]                   INTEGER,
+**		ap-options[2]                 APOptions,
+**		ticket[3]                     Ticket,
+**		authenticator[4]              EncryptedData
+**	}
+**
+**	APOptions ::=   BIT STRING {
+**		reserved(0), use-session-key(1), mutual-required(2) }
+*/
+typedef	struct	krb5_ap_req_st
+	{
+	ASN1_INTEGER			*pvno;
+	ASN1_INTEGER			*msgtype;
+	ASN1_BIT_STRING			*apoptions;
+	KRB5_TICKET			*ticket;
+	KRB5_ENCDATA			*authenticator;
+	}	KRB5_APREQBODY;
+
+typedef STACK_OF(KRB5_APREQBODY) KRB5_APREQ;
+DECLARE_STACK_OF(KRB5_APREQBODY)
+
+
+/*	Authenticator Stuff	*/
+
+
+/*	Checksum ::=   SEQUENCE {
+**		cksumtype[0]                  INTEGER,
+**		checksum[1]                   OCTET STRING
+**	}
+*/
+typedef	struct	krb5_checksum_st
+	{
+	ASN1_INTEGER			*ctype;
+	ASN1_OCTET_STRING		*checksum;
+	}	KRB5_CHECKSUM;
+
+DECLARE_STACK_OF(KRB5_CHECKSUM)
+
+
+/*	EncryptionKey ::=   SEQUENCE {
+**		keytype[0]                    INTEGER,
+**		keyvalue[1]                   OCTET STRING
+**	}
+*/
+typedef struct  krb5_encryptionkey_st
+	{
+	ASN1_INTEGER			*ktype;
+	ASN1_OCTET_STRING		*keyvalue;
+	}	KRB5_ENCKEY;
+
+DECLARE_STACK_OF(KRB5_ENCKEY)
+
+
+/*	AuthorizationData ::=   SEQUENCE OF SEQUENCE {
+**		ad-type[0]                    INTEGER,
+**              ad-data[1]                    OCTET STRING
+**	}
+*/
+typedef struct	krb5_authorization_st
+	{
+	ASN1_INTEGER			*adtype;
+	ASN1_OCTET_STRING		*addata;
+	}	KRB5_AUTHDATA;
+
+DECLARE_STACK_OF(KRB5_AUTHDATA)
+
+			
+/*	-- Unencrypted authenticator
+**	Authenticator ::=    [APPLICATION 2] SEQUENCE    {
+**		authenticator-vno[0]          INTEGER,
+**		crealm[1]                     Realm,
+**		cname[2]                      PrincipalName,
+**		cksum[3]                      Checksum OPTIONAL,
+**		cusec[4]                      INTEGER,
+**		ctime[5]                      KerberosTime,
+**		subkey[6]                     EncryptionKey OPTIONAL,
+**		seq-number[7]                 INTEGER OPTIONAL,
+**		authorization-data[8]         AuthorizationData OPTIONAL
+**	}
+*/
+typedef struct	krb5_authenticator_st
+	{
+	ASN1_INTEGER			*avno;
+	ASN1_GENERALSTRING		*crealm;
+	KRB5_PRINCNAME			*cname;
+	KRB5_CHECKSUM			*cksum;
+	ASN1_INTEGER			*cusec;
+	ASN1_GENERALIZEDTIME		*ctime;
+	KRB5_ENCKEY			*subkey;
+	ASN1_INTEGER			*seqnum;
+	KRB5_AUTHDATA			*authorization;
+	}	KRB5_AUTHENTBODY;
+
+typedef STACK_OF(KRB5_AUTHENTBODY) KRB5_AUTHENT;
+DECLARE_STACK_OF(KRB5_AUTHENTBODY)
+
+
+/*  DECLARE_ASN1_FUNCTIONS(type) = DECLARE_ASN1_FUNCTIONS_name(type, type) =
+**	type *name##_new(void);
+**	void name##_free(type *a);
+**	DECLARE_ASN1_ENCODE_FUNCTIONS(type, name, name) =
+**	 DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) =
+**	  type *d2i_##name(type **a, const unsigned char **in, long len);
+**	  int i2d_##name(type *a, unsigned char **out);
+**	  DECLARE_ASN1_ITEM(itname) = OPENSSL_EXTERN const ASN1_ITEM itname##_it
+*/
+
+DECLARE_ASN1_FUNCTIONS(KRB5_ENCDATA)
+DECLARE_ASN1_FUNCTIONS(KRB5_PRINCNAME)
+DECLARE_ASN1_FUNCTIONS(KRB5_TKTBODY)
+DECLARE_ASN1_FUNCTIONS(KRB5_APREQBODY)
+DECLARE_ASN1_FUNCTIONS(KRB5_TICKET)
+DECLARE_ASN1_FUNCTIONS(KRB5_APREQ)
+
+DECLARE_ASN1_FUNCTIONS(KRB5_CHECKSUM)
+DECLARE_ASN1_FUNCTIONS(KRB5_ENCKEY)
+DECLARE_ASN1_FUNCTIONS(KRB5_AUTHDATA)
+DECLARE_ASN1_FUNCTIONS(KRB5_AUTHENTBODY)
+DECLARE_ASN1_FUNCTIONS(KRB5_AUTHENT)
+
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
+
diff --git a/dep/include/openssl/kssl.h b/dep/include/openssl/kssl.h
new file mode 100644
index 00000000000..a3d20e1ccbd
--- /dev/null
+++ b/dep/include/openssl/kssl.h
@@ -0,0 +1,179 @@
+/* ssl/kssl.h -*- mode: C; c-file-style: "eay" -*- */
+/* Written by Vern Staats  for the OpenSSL project 2000.
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/*
+**	19990701	VRS 	Started.
+*/
+
+#ifndef	KSSL_H
+#define	KSSL_H
+
+#include 
+
+#ifndef OPENSSL_NO_KRB5
+
+#include 
+#include 
+#include 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/*
+**	Depending on which KRB5 implementation used, some types from
+**	the other may be missing.  Resolve that here and now
+*/
+#ifdef KRB5_HEIMDAL
+typedef unsigned char krb5_octet;
+#define FAR
+#else
+
+#ifndef FAR
+#define FAR
+#endif
+
+#endif
+
+/*	Uncomment this to debug kssl problems or
+**	to trace usage of the Kerberos session key
+**
+**	#define		KSSL_DEBUG
+*/
+
+#ifndef	KRB5SVC
+#define KRB5SVC	"host"
+#endif
+
+#ifndef	KRB5KEYTAB
+#define KRB5KEYTAB	"/etc/krb5.keytab"
+#endif
+
+#ifndef KRB5SENDAUTH
+#define KRB5SENDAUTH	1
+#endif
+
+#ifndef KRB5CHECKAUTH
+#define KRB5CHECKAUTH	1
+#endif
+
+#ifndef KSSL_CLOCKSKEW
+#define	KSSL_CLOCKSKEW	300;
+#endif
+
+#define	KSSL_ERR_MAX	255
+typedef struct kssl_err_st  {
+	int  reason;
+	char text[KSSL_ERR_MAX+1];
+	} KSSL_ERR;
+
+
+/*	Context for passing
+**		(1) Kerberos session key to SSL, and
+**		(2)	Config data between application and SSL lib
+*/
+typedef struct kssl_ctx_st
+        {
+                                /*	used by:    disposition:            */
+	char *service_name;	/*	C,S	    default ok (kssl)       */
+	char *service_host;	/*	C	    input, REQUIRED         */
+	char *client_princ;	/*	S	    output from krb5 ticket */
+	char *keytab_file;	/*      S	    NULL (/etc/krb5.keytab) */
+	char *cred_cache;	/*	C	    NULL (default)          */
+	krb5_enctype enctype;
+	int length;
+	krb5_octet FAR *key;
+	} KSSL_CTX;
+
+#define	KSSL_CLIENT 	1
+#define KSSL_SERVER 	2
+#define	KSSL_SERVICE	3
+#define	KSSL_KEYTAB 	4
+
+#define KSSL_CTX_OK 	0
+#define KSSL_CTX_ERR	1
+#define KSSL_NOMEM	2
+
+/* Public (for use by applications that use OpenSSL with Kerberos 5 support */
+krb5_error_code kssl_ctx_setstring(KSSL_CTX *kssl_ctx, int which, char *text);
+KSSL_CTX *kssl_ctx_new(void);
+KSSL_CTX *kssl_ctx_free(KSSL_CTX *kssl_ctx);
+void kssl_ctx_show(KSSL_CTX *kssl_ctx);
+krb5_error_code kssl_ctx_setprinc(KSSL_CTX *kssl_ctx, int which,
+        krb5_data *realm, krb5_data *entity, int nentities);
+krb5_error_code	kssl_cget_tkt(KSSL_CTX *kssl_ctx,  krb5_data **enc_tktp,
+        krb5_data *authenp, KSSL_ERR *kssl_err);
+krb5_error_code	kssl_sget_tkt(KSSL_CTX *kssl_ctx,  krb5_data *indata,
+        krb5_ticket_times *ttimes, KSSL_ERR *kssl_err);
+krb5_error_code kssl_ctx_setkey(KSSL_CTX *kssl_ctx, krb5_keyblock *session);
+void	kssl_err_set(KSSL_ERR *kssl_err, int reason, char *text);
+void kssl_krb5_free_data_contents(krb5_context context, krb5_data *data);
+krb5_error_code  kssl_build_principal_2(krb5_context context,
+			krb5_principal *princ, int rlen, const char *realm,
+			int slen, const char *svc, int hlen, const char *host);
+krb5_error_code  kssl_validate_times(krb5_timestamp atime,
+					krb5_ticket_times *ttimes);
+krb5_error_code  kssl_check_authent(KSSL_CTX *kssl_ctx, krb5_data *authentp,
+			            krb5_timestamp *atimep, KSSL_ERR *kssl_err);
+unsigned char	*kssl_skip_confound(krb5_enctype enctype, unsigned char *authn);
+
+#ifdef  __cplusplus
+}
+#endif
+#endif	/* OPENSSL_NO_KRB5	*/
+#endif	/* KSSL_H 	*/
diff --git a/dep/include/openssl/lhash.h b/dep/include/openssl/lhash.h
new file mode 100644
index 00000000000..d392d0cd80d
--- /dev/null
+++ b/dep/include/openssl/lhash.h
@@ -0,0 +1,200 @@
+/* crypto/lhash/lhash.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/* Header for dynamic hash table routines
+ * Author - Eric Young
+ */
+
+#ifndef HEADER_LHASH_H
+#define HEADER_LHASH_H
+
+#include 
+#ifndef OPENSSL_NO_FP_API
+#include 
+#endif
+
+#ifndef OPENSSL_NO_BIO
+#include 
+#endif
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+typedef struct lhash_node_st
+	{
+	void *data;
+	struct lhash_node_st *next;
+#ifndef OPENSSL_NO_HASH_COMP
+	unsigned long hash;
+#endif
+	} LHASH_NODE;
+
+typedef int (*LHASH_COMP_FN_TYPE)(const void *, const void *);
+typedef unsigned long (*LHASH_HASH_FN_TYPE)(const void *);
+typedef void (*LHASH_DOALL_FN_TYPE)(void *);
+typedef void (*LHASH_DOALL_ARG_FN_TYPE)(void *, void *);
+
+/* Macros for declaring and implementing type-safe wrappers for LHASH callbacks.
+ * This way, callbacks can be provided to LHASH structures without function
+ * pointer casting and the macro-defined callbacks provide per-variable casting
+ * before deferring to the underlying type-specific callbacks. NB: It is
+ * possible to place a "static" in front of both the DECLARE and IMPLEMENT
+ * macros if the functions are strictly internal. */
+
+/* First: "hash" functions */
+#define DECLARE_LHASH_HASH_FN(f_name,o_type) \
+	unsigned long f_name##_LHASH_HASH(const void *);
+#define IMPLEMENT_LHASH_HASH_FN(f_name,o_type) \
+	unsigned long f_name##_LHASH_HASH(const void *arg) { \
+		o_type a = (o_type)arg; \
+		return f_name(a); }
+#define LHASH_HASH_FN(f_name) f_name##_LHASH_HASH
+
+/* Second: "compare" functions */
+#define DECLARE_LHASH_COMP_FN(f_name,o_type) \
+	int f_name##_LHASH_COMP(const void *, const void *);
+#define IMPLEMENT_LHASH_COMP_FN(f_name,o_type) \
+	int f_name##_LHASH_COMP(const void *arg1, const void *arg2) { \
+		o_type a = (o_type)arg1; \
+		o_type b = (o_type)arg2; \
+		return f_name(a,b); }
+#define LHASH_COMP_FN(f_name) f_name##_LHASH_COMP
+
+/* Third: "doall" functions */
+#define DECLARE_LHASH_DOALL_FN(f_name,o_type) \
+	void f_name##_LHASH_DOALL(void *);
+#define IMPLEMENT_LHASH_DOALL_FN(f_name,o_type) \
+	void f_name##_LHASH_DOALL(void *arg) { \
+		o_type a = (o_type)arg; \
+		f_name(a); }
+#define LHASH_DOALL_FN(f_name) f_name##_LHASH_DOALL
+
+/* Fourth: "doall_arg" functions */
+#define DECLARE_LHASH_DOALL_ARG_FN(f_name,o_type,a_type) \
+	void f_name##_LHASH_DOALL_ARG(void *, void *);
+#define IMPLEMENT_LHASH_DOALL_ARG_FN(f_name,o_type,a_type) \
+	void f_name##_LHASH_DOALL_ARG(void *arg1, void *arg2) { \
+		o_type a = (o_type)arg1; \
+		a_type b = (a_type)arg2; \
+		f_name(a,b); }
+#define LHASH_DOALL_ARG_FN(f_name) f_name##_LHASH_DOALL_ARG
+
+typedef struct lhash_st
+	{
+	LHASH_NODE **b;
+	LHASH_COMP_FN_TYPE comp;
+	LHASH_HASH_FN_TYPE hash;
+	unsigned int num_nodes;
+	unsigned int num_alloc_nodes;
+	unsigned int p;
+	unsigned int pmax;
+	unsigned long up_load; /* load times 256 */
+	unsigned long down_load; /* load times 256 */
+	unsigned long num_items;
+
+	unsigned long num_expands;
+	unsigned long num_expand_reallocs;
+	unsigned long num_contracts;
+	unsigned long num_contract_reallocs;
+	unsigned long num_hash_calls;
+	unsigned long num_comp_calls;
+	unsigned long num_insert;
+	unsigned long num_replace;
+	unsigned long num_delete;
+	unsigned long num_no_delete;
+	unsigned long num_retrieve;
+	unsigned long num_retrieve_miss;
+	unsigned long num_hash_comps;
+
+	int error;
+	} LHASH;
+
+#define LH_LOAD_MULT	256
+
+/* Indicates a malloc() error in the last call, this is only bad
+ * in lh_insert(). */
+#define lh_error(lh)	((lh)->error)
+
+LHASH *lh_new(LHASH_HASH_FN_TYPE h, LHASH_COMP_FN_TYPE c);
+void lh_free(LHASH *lh);
+void *lh_insert(LHASH *lh, void *data);
+void *lh_delete(LHASH *lh, const void *data);
+void *lh_retrieve(LHASH *lh, const void *data);
+void lh_doall(LHASH *lh, LHASH_DOALL_FN_TYPE func);
+void lh_doall_arg(LHASH *lh, LHASH_DOALL_ARG_FN_TYPE func, void *arg);
+unsigned long lh_strhash(const char *c);
+unsigned long lh_num_items(const LHASH *lh);
+
+#ifndef OPENSSL_NO_FP_API
+void lh_stats(const LHASH *lh, FILE *out);
+void lh_node_stats(const LHASH *lh, FILE *out);
+void lh_node_usage_stats(const LHASH *lh, FILE *out);
+#endif
+
+#ifndef OPENSSL_NO_BIO
+void lh_stats_bio(const LHASH *lh, BIO *out);
+void lh_node_stats_bio(const LHASH *lh, BIO *out);
+void lh_node_usage_stats_bio(const LHASH *lh, BIO *out);
+#endif
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/dep/include/openssl/md2.h b/dep/include/openssl/md2.h
new file mode 100644
index 00000000000..a46120e7d41
--- /dev/null
+++ b/dep/include/openssl/md2.h
@@ -0,0 +1,92 @@
+/* crypto/md/md2.h */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_MD2_H
+#define HEADER_MD2_H
+
+#include  /* OPENSSL_NO_MD2, MD2_INT */
+#ifdef OPENSSL_NO_MD2
+#error MD2 is disabled.
+#endif
+#include 
+
+#define MD2_DIGEST_LENGTH	16
+#define MD2_BLOCK       	16
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+typedef struct MD2state_st
+	{
+	unsigned int num;
+	unsigned char data[MD2_BLOCK];
+	MD2_INT cksm[MD2_BLOCK];
+	MD2_INT state[MD2_BLOCK];
+	} MD2_CTX;
+
+const char *MD2_options(void);
+int MD2_Init(MD2_CTX *c);
+int MD2_Update(MD2_CTX *c, const unsigned char *data, size_t len);
+int MD2_Final(unsigned char *md, MD2_CTX *c);
+unsigned char *MD2(const unsigned char *d, size_t n,unsigned char *md);
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff --git a/dep/include/openssl/md4.h b/dep/include/openssl/md4.h
new file mode 100644
index 00000000000..5598c93a4fe
--- /dev/null
+++ b/dep/include/openssl/md4.h
@@ -0,0 +1,117 @@
+/* crypto/md4/md4.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_MD4_H
+#define HEADER_MD4_H
+
+#include 
+#include 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#ifdef OPENSSL_NO_MD4
+#error MD4 is disabled.
+#endif
+
+/*
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * ! MD4_LONG has to be at least 32 bits wide. If it's wider, then !
+ * ! MD4_LONG_LOG2 has to be defined along.			   !
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ */
+
+#if defined(OPENSSL_SYS_WIN16) || defined(__LP32__)
+#define MD4_LONG unsigned long
+#elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__)
+#define MD4_LONG unsigned long
+#define MD4_LONG_LOG2 3
+/*
+ * _CRAY note. I could declare short, but I have no idea what impact
+ * does it have on performance on none-T3E machines. I could declare
+ * int, but at least on C90 sizeof(int) can be chosen at compile time.
+ * So I've chosen long...
+ *					
+ */
+#else
+#define MD4_LONG unsigned int
+#endif
+
+#define MD4_CBLOCK	64
+#define MD4_LBLOCK	(MD4_CBLOCK/4)
+#define MD4_DIGEST_LENGTH 16
+
+typedef struct MD4state_st
+	{
+	MD4_LONG A,B,C,D;
+	MD4_LONG Nl,Nh;
+	MD4_LONG data[MD4_LBLOCK];
+	unsigned int num;
+	} MD4_CTX;
+
+int MD4_Init(MD4_CTX *c);
+int MD4_Update(MD4_CTX *c, const void *data, size_t len);
+int MD4_Final(unsigned char *md, MD4_CTX *c);
+unsigned char *MD4(const unsigned char *d, size_t n, unsigned char *md);
+void MD4_Transform(MD4_CTX *c, const unsigned char *b);
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff --git a/dep/include/openssl/md5.h b/dep/include/openssl/md5.h
new file mode 100644
index 00000000000..dbdc0e1abc7
--- /dev/null
+++ b/dep/include/openssl/md5.h
@@ -0,0 +1,117 @@
+/* crypto/md5/md5.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_MD5_H
+#define HEADER_MD5_H
+
+#include 
+#include 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#ifdef OPENSSL_NO_MD5
+#error MD5 is disabled.
+#endif
+
+/*
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * ! MD5_LONG has to be at least 32 bits wide. If it's wider, then !
+ * ! MD5_LONG_LOG2 has to be defined along.			   !
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ */
+
+#if defined(OPENSSL_SYS_WIN16) || defined(__LP32__)
+#define MD5_LONG unsigned long
+#elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__)
+#define MD5_LONG unsigned long
+#define MD5_LONG_LOG2 3
+/*
+ * _CRAY note. I could declare short, but I have no idea what impact
+ * does it have on performance on none-T3E machines. I could declare
+ * int, but at least on C90 sizeof(int) can be chosen at compile time.
+ * So I've chosen long...
+ *					
+ */
+#else
+#define MD5_LONG unsigned int
+#endif
+
+#define MD5_CBLOCK	64
+#define MD5_LBLOCK	(MD5_CBLOCK/4)
+#define MD5_DIGEST_LENGTH 16
+
+typedef struct MD5state_st
+	{
+	MD5_LONG A,B,C,D;
+	MD5_LONG Nl,Nh;
+	MD5_LONG data[MD5_LBLOCK];
+	unsigned int num;
+	} MD5_CTX;
+
+int MD5_Init(MD5_CTX *c);
+int MD5_Update(MD5_CTX *c, const void *data, size_t len);
+int MD5_Final(unsigned char *md, MD5_CTX *c);
+unsigned char *MD5(const unsigned char *d, size_t n, unsigned char *md);
+void MD5_Transform(MD5_CTX *c, const unsigned char *b);
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff --git a/dep/include/openssl/mdc2.h b/dep/include/openssl/mdc2.h
new file mode 100644
index 00000000000..e5ba226cae8
--- /dev/null
+++ b/dep/include/openssl/mdc2.h
@@ -0,0 +1,96 @@
+/* crypto/mdc2/mdc2.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_MDC2_H
+#define HEADER_MDC2_H
+
+#include 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#ifdef OPENSSL_NO_MDC2
+#error MDC2 is disabled.
+#endif
+
+#define MDC2_BLOCK              8
+#define MDC2_DIGEST_LENGTH      16
+
+typedef struct mdc2_ctx_st
+	{
+	int num;
+	unsigned char data[MDC2_BLOCK];
+	DES_cblock h,hh;
+	int pad_type; /* either 1 or 2, default 1 */
+	} MDC2_CTX;
+
+
+int MDC2_Init(MDC2_CTX *c);
+int MDC2_Update(MDC2_CTX *c, const unsigned char *data, unsigned long len);
+int MDC2_Final(unsigned char *md, MDC2_CTX *c);
+unsigned char *MDC2(const unsigned char *d, unsigned long n,
+	unsigned char *md);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/dep/include/openssl/obj_mac.h b/dep/include/openssl/obj_mac.h
new file mode 100644
index 00000000000..f447bbe69af
--- /dev/null
+++ b/dep/include/openssl/obj_mac.h
@@ -0,0 +1,3408 @@
+/* crypto/objects/obj_mac.h */
+
+/* THIS FILE IS GENERATED FROM objects.txt by objects.pl via the
+ * following command:
+ * perl objects.pl objects.txt obj_mac.num obj_mac.h
+ */
+
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#define SN_undef			"UNDEF"
+#define LN_undef			"undefined"
+#define NID_undef			0
+#define OBJ_undef			0L
+
+#define SN_itu_t		"ITU-T"
+#define LN_itu_t		"itu-t"
+#define NID_itu_t		645
+#define OBJ_itu_t		0L
+
+#define NID_ccitt		404
+#define OBJ_ccitt		OBJ_itu_t
+
+#define SN_iso		"ISO"
+#define LN_iso		"iso"
+#define NID_iso		181
+#define OBJ_iso		1L
+
+#define SN_joint_iso_itu_t		"JOINT-ISO-ITU-T"
+#define LN_joint_iso_itu_t		"joint-iso-itu-t"
+#define NID_joint_iso_itu_t		646
+#define OBJ_joint_iso_itu_t		2L
+
+#define NID_joint_iso_ccitt		393
+#define OBJ_joint_iso_ccitt		OBJ_joint_iso_itu_t
+
+#define SN_member_body		"member-body"
+#define LN_member_body		"ISO Member Body"
+#define NID_member_body		182
+#define OBJ_member_body		OBJ_iso,2L
+
+#define SN_identified_organization		"identified-organization"
+#define NID_identified_organization		676
+#define OBJ_identified_organization		OBJ_iso,3L
+
+#define SN_certicom_arc		"certicom-arc"
+#define NID_certicom_arc		677
+#define OBJ_certicom_arc		OBJ_identified_organization,132L
+
+#define SN_international_organizations		"international-organizations"
+#define LN_international_organizations		"International Organizations"
+#define NID_international_organizations		647
+#define OBJ_international_organizations		OBJ_joint_iso_itu_t,23L
+
+#define SN_wap		"wap"
+#define NID_wap		678
+#define OBJ_wap		OBJ_international_organizations,43L
+
+#define SN_wap_wsg		"wap-wsg"
+#define NID_wap_wsg		679
+#define OBJ_wap_wsg		OBJ_wap,13L
+
+#define SN_selected_attribute_types		"selected-attribute-types"
+#define LN_selected_attribute_types		"Selected Attribute Types"
+#define NID_selected_attribute_types		394
+#define OBJ_selected_attribute_types		OBJ_joint_iso_itu_t,5L,1L,5L
+
+#define SN_clearance		"clearance"
+#define NID_clearance		395
+#define OBJ_clearance		OBJ_selected_attribute_types,55L
+
+#define SN_ISO_US		"ISO-US"
+#define LN_ISO_US		"ISO US Member Body"
+#define NID_ISO_US		183
+#define OBJ_ISO_US		OBJ_member_body,840L
+
+#define SN_X9_57		"X9-57"
+#define LN_X9_57		"X9.57"
+#define NID_X9_57		184
+#define OBJ_X9_57		OBJ_ISO_US,10040L
+
+#define SN_X9cm		"X9cm"
+#define LN_X9cm		"X9.57 CM ?"
+#define NID_X9cm		185
+#define OBJ_X9cm		OBJ_X9_57,4L
+
+#define SN_dsa		"DSA"
+#define LN_dsa		"dsaEncryption"
+#define NID_dsa		116
+#define OBJ_dsa		OBJ_X9cm,1L
+
+#define SN_dsaWithSHA1		"DSA-SHA1"
+#define LN_dsaWithSHA1		"dsaWithSHA1"
+#define NID_dsaWithSHA1		113
+#define OBJ_dsaWithSHA1		OBJ_X9cm,3L
+
+#define SN_ansi_X9_62		"ansi-X9-62"
+#define LN_ansi_X9_62		"ANSI X9.62"
+#define NID_ansi_X9_62		405
+#define OBJ_ansi_X9_62		OBJ_ISO_US,10045L
+
+#define OBJ_X9_62_id_fieldType		OBJ_ansi_X9_62,1L
+
+#define SN_X9_62_prime_field		"prime-field"
+#define NID_X9_62_prime_field		406
+#define OBJ_X9_62_prime_field		OBJ_X9_62_id_fieldType,1L
+
+#define SN_X9_62_characteristic_two_field		"characteristic-two-field"
+#define NID_X9_62_characteristic_two_field		407
+#define OBJ_X9_62_characteristic_two_field		OBJ_X9_62_id_fieldType,2L
+
+#define SN_X9_62_id_characteristic_two_basis		"id-characteristic-two-basis"
+#define NID_X9_62_id_characteristic_two_basis		680
+#define OBJ_X9_62_id_characteristic_two_basis		OBJ_X9_62_characteristic_two_field,3L
+
+#define SN_X9_62_onBasis		"onBasis"
+#define NID_X9_62_onBasis		681
+#define OBJ_X9_62_onBasis		OBJ_X9_62_id_characteristic_two_basis,1L
+
+#define SN_X9_62_tpBasis		"tpBasis"
+#define NID_X9_62_tpBasis		682
+#define OBJ_X9_62_tpBasis		OBJ_X9_62_id_characteristic_two_basis,2L
+
+#define SN_X9_62_ppBasis		"ppBasis"
+#define NID_X9_62_ppBasis		683
+#define OBJ_X9_62_ppBasis		OBJ_X9_62_id_characteristic_two_basis,3L
+
+#define OBJ_X9_62_id_publicKeyType		OBJ_ansi_X9_62,2L
+
+#define SN_X9_62_id_ecPublicKey		"id-ecPublicKey"
+#define NID_X9_62_id_ecPublicKey		408
+#define OBJ_X9_62_id_ecPublicKey		OBJ_X9_62_id_publicKeyType,1L
+
+#define OBJ_X9_62_ellipticCurve		OBJ_ansi_X9_62,3L
+
+#define OBJ_X9_62_c_TwoCurve		OBJ_X9_62_ellipticCurve,0L
+
+#define SN_X9_62_c2pnb163v1		"c2pnb163v1"
+#define NID_X9_62_c2pnb163v1		684
+#define OBJ_X9_62_c2pnb163v1		OBJ_X9_62_c_TwoCurve,1L
+
+#define SN_X9_62_c2pnb163v2		"c2pnb163v2"
+#define NID_X9_62_c2pnb163v2		685
+#define OBJ_X9_62_c2pnb163v2		OBJ_X9_62_c_TwoCurve,2L
+
+#define SN_X9_62_c2pnb163v3		"c2pnb163v3"
+#define NID_X9_62_c2pnb163v3		686
+#define OBJ_X9_62_c2pnb163v3		OBJ_X9_62_c_TwoCurve,3L
+
+#define SN_X9_62_c2pnb176v1		"c2pnb176v1"
+#define NID_X9_62_c2pnb176v1		687
+#define OBJ_X9_62_c2pnb176v1		OBJ_X9_62_c_TwoCurve,4L
+
+#define SN_X9_62_c2tnb191v1		"c2tnb191v1"
+#define NID_X9_62_c2tnb191v1		688
+#define OBJ_X9_62_c2tnb191v1		OBJ_X9_62_c_TwoCurve,5L
+
+#define SN_X9_62_c2tnb191v2		"c2tnb191v2"
+#define NID_X9_62_c2tnb191v2		689
+#define OBJ_X9_62_c2tnb191v2		OBJ_X9_62_c_TwoCurve,6L
+
+#define SN_X9_62_c2tnb191v3		"c2tnb191v3"
+#define NID_X9_62_c2tnb191v3		690
+#define OBJ_X9_62_c2tnb191v3		OBJ_X9_62_c_TwoCurve,7L
+
+#define SN_X9_62_c2onb191v4		"c2onb191v4"
+#define NID_X9_62_c2onb191v4		691
+#define OBJ_X9_62_c2onb191v4		OBJ_X9_62_c_TwoCurve,8L
+
+#define SN_X9_62_c2onb191v5		"c2onb191v5"
+#define NID_X9_62_c2onb191v5		692
+#define OBJ_X9_62_c2onb191v5		OBJ_X9_62_c_TwoCurve,9L
+
+#define SN_X9_62_c2pnb208w1		"c2pnb208w1"
+#define NID_X9_62_c2pnb208w1		693
+#define OBJ_X9_62_c2pnb208w1		OBJ_X9_62_c_TwoCurve,10L
+
+#define SN_X9_62_c2tnb239v1		"c2tnb239v1"
+#define NID_X9_62_c2tnb239v1		694
+#define OBJ_X9_62_c2tnb239v1		OBJ_X9_62_c_TwoCurve,11L
+
+#define SN_X9_62_c2tnb239v2		"c2tnb239v2"
+#define NID_X9_62_c2tnb239v2		695
+#define OBJ_X9_62_c2tnb239v2		OBJ_X9_62_c_TwoCurve,12L
+
+#define SN_X9_62_c2tnb239v3		"c2tnb239v3"
+#define NID_X9_62_c2tnb239v3		696
+#define OBJ_X9_62_c2tnb239v3		OBJ_X9_62_c_TwoCurve,13L
+
+#define SN_X9_62_c2onb239v4		"c2onb239v4"
+#define NID_X9_62_c2onb239v4		697
+#define OBJ_X9_62_c2onb239v4		OBJ_X9_62_c_TwoCurve,14L
+
+#define SN_X9_62_c2onb239v5		"c2onb239v5"
+#define NID_X9_62_c2onb239v5		698
+#define OBJ_X9_62_c2onb239v5		OBJ_X9_62_c_TwoCurve,15L
+
+#define SN_X9_62_c2pnb272w1		"c2pnb272w1"
+#define NID_X9_62_c2pnb272w1		699
+#define OBJ_X9_62_c2pnb272w1		OBJ_X9_62_c_TwoCurve,16L
+
+#define SN_X9_62_c2pnb304w1		"c2pnb304w1"
+#define NID_X9_62_c2pnb304w1		700
+#define OBJ_X9_62_c2pnb304w1		OBJ_X9_62_c_TwoCurve,17L
+
+#define SN_X9_62_c2tnb359v1		"c2tnb359v1"
+#define NID_X9_62_c2tnb359v1		701
+#define OBJ_X9_62_c2tnb359v1		OBJ_X9_62_c_TwoCurve,18L
+
+#define SN_X9_62_c2pnb368w1		"c2pnb368w1"
+#define NID_X9_62_c2pnb368w1		702
+#define OBJ_X9_62_c2pnb368w1		OBJ_X9_62_c_TwoCurve,19L
+
+#define SN_X9_62_c2tnb431r1		"c2tnb431r1"
+#define NID_X9_62_c2tnb431r1		703
+#define OBJ_X9_62_c2tnb431r1		OBJ_X9_62_c_TwoCurve,20L
+
+#define OBJ_X9_62_primeCurve		OBJ_X9_62_ellipticCurve,1L
+
+#define SN_X9_62_prime192v1		"prime192v1"
+#define NID_X9_62_prime192v1		409
+#define OBJ_X9_62_prime192v1		OBJ_X9_62_primeCurve,1L
+
+#define SN_X9_62_prime192v2		"prime192v2"
+#define NID_X9_62_prime192v2		410
+#define OBJ_X9_62_prime192v2		OBJ_X9_62_primeCurve,2L
+
+#define SN_X9_62_prime192v3		"prime192v3"
+#define NID_X9_62_prime192v3		411
+#define OBJ_X9_62_prime192v3		OBJ_X9_62_primeCurve,3L
+
+#define SN_X9_62_prime239v1		"prime239v1"
+#define NID_X9_62_prime239v1		412
+#define OBJ_X9_62_prime239v1		OBJ_X9_62_primeCurve,4L
+
+#define SN_X9_62_prime239v2		"prime239v2"
+#define NID_X9_62_prime239v2		413
+#define OBJ_X9_62_prime239v2		OBJ_X9_62_primeCurve,5L
+
+#define SN_X9_62_prime239v3		"prime239v3"
+#define NID_X9_62_prime239v3		414
+#define OBJ_X9_62_prime239v3		OBJ_X9_62_primeCurve,6L
+
+#define SN_X9_62_prime256v1		"prime256v1"
+#define NID_X9_62_prime256v1		415
+#define OBJ_X9_62_prime256v1		OBJ_X9_62_primeCurve,7L
+
+#define OBJ_X9_62_id_ecSigType		OBJ_ansi_X9_62,4L
+
+#define SN_ecdsa_with_SHA1		"ecdsa-with-SHA1"
+#define NID_ecdsa_with_SHA1		416
+#define OBJ_ecdsa_with_SHA1		OBJ_X9_62_id_ecSigType,1L
+
+#define OBJ_secg_ellipticCurve		OBJ_certicom_arc,0L
+
+#define SN_secp112r1		"secp112r1"
+#define NID_secp112r1		704
+#define OBJ_secp112r1		OBJ_secg_ellipticCurve,6L
+
+#define SN_secp112r2		"secp112r2"
+#define NID_secp112r2		705
+#define OBJ_secp112r2		OBJ_secg_ellipticCurve,7L
+
+#define SN_secp128r1		"secp128r1"
+#define NID_secp128r1		706
+#define OBJ_secp128r1		OBJ_secg_ellipticCurve,28L
+
+#define SN_secp128r2		"secp128r2"
+#define NID_secp128r2		707
+#define OBJ_secp128r2		OBJ_secg_ellipticCurve,29L
+
+#define SN_secp160k1		"secp160k1"
+#define NID_secp160k1		708
+#define OBJ_secp160k1		OBJ_secg_ellipticCurve,9L
+
+#define SN_secp160r1		"secp160r1"
+#define NID_secp160r1		709
+#define OBJ_secp160r1		OBJ_secg_ellipticCurve,8L
+
+#define SN_secp160r2		"secp160r2"
+#define NID_secp160r2		710
+#define OBJ_secp160r2		OBJ_secg_ellipticCurve,30L
+
+#define SN_secp192k1		"secp192k1"
+#define NID_secp192k1		711
+#define OBJ_secp192k1		OBJ_secg_ellipticCurve,31L
+
+#define SN_secp224k1		"secp224k1"
+#define NID_secp224k1		712
+#define OBJ_secp224k1		OBJ_secg_ellipticCurve,32L
+
+#define SN_secp224r1		"secp224r1"
+#define NID_secp224r1		713
+#define OBJ_secp224r1		OBJ_secg_ellipticCurve,33L
+
+#define SN_secp256k1		"secp256k1"
+#define NID_secp256k1		714
+#define OBJ_secp256k1		OBJ_secg_ellipticCurve,10L
+
+#define SN_secp384r1		"secp384r1"
+#define NID_secp384r1		715
+#define OBJ_secp384r1		OBJ_secg_ellipticCurve,34L
+
+#define SN_secp521r1		"secp521r1"
+#define NID_secp521r1		716
+#define OBJ_secp521r1		OBJ_secg_ellipticCurve,35L
+
+#define SN_sect113r1		"sect113r1"
+#define NID_sect113r1		717
+#define OBJ_sect113r1		OBJ_secg_ellipticCurve,4L
+
+#define SN_sect113r2		"sect113r2"
+#define NID_sect113r2		718
+#define OBJ_sect113r2		OBJ_secg_ellipticCurve,5L
+
+#define SN_sect131r1		"sect131r1"
+#define NID_sect131r1		719
+#define OBJ_sect131r1		OBJ_secg_ellipticCurve,22L
+
+#define SN_sect131r2		"sect131r2"
+#define NID_sect131r2		720
+#define OBJ_sect131r2		OBJ_secg_ellipticCurve,23L
+
+#define SN_sect163k1		"sect163k1"
+#define NID_sect163k1		721
+#define OBJ_sect163k1		OBJ_secg_ellipticCurve,1L
+
+#define SN_sect163r1		"sect163r1"
+#define NID_sect163r1		722
+#define OBJ_sect163r1		OBJ_secg_ellipticCurve,2L
+
+#define SN_sect163r2		"sect163r2"
+#define NID_sect163r2		723
+#define OBJ_sect163r2		OBJ_secg_ellipticCurve,15L
+
+#define SN_sect193r1		"sect193r1"
+#define NID_sect193r1		724
+#define OBJ_sect193r1		OBJ_secg_ellipticCurve,24L
+
+#define SN_sect193r2		"sect193r2"
+#define NID_sect193r2		725
+#define OBJ_sect193r2		OBJ_secg_ellipticCurve,25L
+
+#define SN_sect233k1		"sect233k1"
+#define NID_sect233k1		726
+#define OBJ_sect233k1		OBJ_secg_ellipticCurve,26L
+
+#define SN_sect233r1		"sect233r1"
+#define NID_sect233r1		727
+#define OBJ_sect233r1		OBJ_secg_ellipticCurve,27L
+
+#define SN_sect239k1		"sect239k1"
+#define NID_sect239k1		728
+#define OBJ_sect239k1		OBJ_secg_ellipticCurve,3L
+
+#define SN_sect283k1		"sect283k1"
+#define NID_sect283k1		729
+#define OBJ_sect283k1		OBJ_secg_ellipticCurve,16L
+
+#define SN_sect283r1		"sect283r1"
+#define NID_sect283r1		730
+#define OBJ_sect283r1		OBJ_secg_ellipticCurve,17L
+
+#define SN_sect409k1		"sect409k1"
+#define NID_sect409k1		731
+#define OBJ_sect409k1		OBJ_secg_ellipticCurve,36L
+
+#define SN_sect409r1		"sect409r1"
+#define NID_sect409r1		732
+#define OBJ_sect409r1		OBJ_secg_ellipticCurve,37L
+
+#define SN_sect571k1		"sect571k1"
+#define NID_sect571k1		733
+#define OBJ_sect571k1		OBJ_secg_ellipticCurve,38L
+
+#define SN_sect571r1		"sect571r1"
+#define NID_sect571r1		734
+#define OBJ_sect571r1		OBJ_secg_ellipticCurve,39L
+
+#define OBJ_wap_wsg_idm_ecid		OBJ_wap_wsg,4L
+
+#define SN_wap_wsg_idm_ecid_wtls1		"wap-wsg-idm-ecid-wtls1"
+#define NID_wap_wsg_idm_ecid_wtls1		735
+#define OBJ_wap_wsg_idm_ecid_wtls1		OBJ_wap_wsg_idm_ecid,1L
+
+#define SN_wap_wsg_idm_ecid_wtls3		"wap-wsg-idm-ecid-wtls3"
+#define NID_wap_wsg_idm_ecid_wtls3		736
+#define OBJ_wap_wsg_idm_ecid_wtls3		OBJ_wap_wsg_idm_ecid,3L
+
+#define SN_wap_wsg_idm_ecid_wtls4		"wap-wsg-idm-ecid-wtls4"
+#define NID_wap_wsg_idm_ecid_wtls4		737
+#define OBJ_wap_wsg_idm_ecid_wtls4		OBJ_wap_wsg_idm_ecid,4L
+
+#define SN_wap_wsg_idm_ecid_wtls5		"wap-wsg-idm-ecid-wtls5"
+#define NID_wap_wsg_idm_ecid_wtls5		738
+#define OBJ_wap_wsg_idm_ecid_wtls5		OBJ_wap_wsg_idm_ecid,5L
+
+#define SN_wap_wsg_idm_ecid_wtls6		"wap-wsg-idm-ecid-wtls6"
+#define NID_wap_wsg_idm_ecid_wtls6		739
+#define OBJ_wap_wsg_idm_ecid_wtls6		OBJ_wap_wsg_idm_ecid,6L
+
+#define SN_wap_wsg_idm_ecid_wtls7		"wap-wsg-idm-ecid-wtls7"
+#define NID_wap_wsg_idm_ecid_wtls7		740
+#define OBJ_wap_wsg_idm_ecid_wtls7		OBJ_wap_wsg_idm_ecid,7L
+
+#define SN_wap_wsg_idm_ecid_wtls8		"wap-wsg-idm-ecid-wtls8"
+#define NID_wap_wsg_idm_ecid_wtls8		741
+#define OBJ_wap_wsg_idm_ecid_wtls8		OBJ_wap_wsg_idm_ecid,8L
+
+#define SN_wap_wsg_idm_ecid_wtls9		"wap-wsg-idm-ecid-wtls9"
+#define NID_wap_wsg_idm_ecid_wtls9		742
+#define OBJ_wap_wsg_idm_ecid_wtls9		OBJ_wap_wsg_idm_ecid,9L
+
+#define SN_wap_wsg_idm_ecid_wtls10		"wap-wsg-idm-ecid-wtls10"
+#define NID_wap_wsg_idm_ecid_wtls10		743
+#define OBJ_wap_wsg_idm_ecid_wtls10		OBJ_wap_wsg_idm_ecid,10L
+
+#define SN_wap_wsg_idm_ecid_wtls11		"wap-wsg-idm-ecid-wtls11"
+#define NID_wap_wsg_idm_ecid_wtls11		744
+#define OBJ_wap_wsg_idm_ecid_wtls11		OBJ_wap_wsg_idm_ecid,11L
+
+#define SN_wap_wsg_idm_ecid_wtls12		"wap-wsg-idm-ecid-wtls12"
+#define NID_wap_wsg_idm_ecid_wtls12		745
+#define OBJ_wap_wsg_idm_ecid_wtls12		OBJ_wap_wsg_idm_ecid,12L
+
+#define SN_cast5_cbc		"CAST5-CBC"
+#define LN_cast5_cbc		"cast5-cbc"
+#define NID_cast5_cbc		108
+#define OBJ_cast5_cbc		OBJ_ISO_US,113533L,7L,66L,10L
+
+#define SN_cast5_ecb		"CAST5-ECB"
+#define LN_cast5_ecb		"cast5-ecb"
+#define NID_cast5_ecb		109
+
+#define SN_cast5_cfb64		"CAST5-CFB"
+#define LN_cast5_cfb64		"cast5-cfb"
+#define NID_cast5_cfb64		110
+
+#define SN_cast5_ofb64		"CAST5-OFB"
+#define LN_cast5_ofb64		"cast5-ofb"
+#define NID_cast5_ofb64		111
+
+#define LN_pbeWithMD5AndCast5_CBC		"pbeWithMD5AndCast5CBC"
+#define NID_pbeWithMD5AndCast5_CBC		112
+#define OBJ_pbeWithMD5AndCast5_CBC		OBJ_ISO_US,113533L,7L,66L,12L
+
+#define SN_rsadsi		"rsadsi"
+#define LN_rsadsi		"RSA Data Security, Inc."
+#define NID_rsadsi		1
+#define OBJ_rsadsi		OBJ_ISO_US,113549L
+
+#define SN_pkcs		"pkcs"
+#define LN_pkcs		"RSA Data Security, Inc. PKCS"
+#define NID_pkcs		2
+#define OBJ_pkcs		OBJ_rsadsi,1L
+
+#define SN_pkcs1		"pkcs1"
+#define NID_pkcs1		186
+#define OBJ_pkcs1		OBJ_pkcs,1L
+
+#define LN_rsaEncryption		"rsaEncryption"
+#define NID_rsaEncryption		6
+#define OBJ_rsaEncryption		OBJ_pkcs1,1L
+
+#define SN_md2WithRSAEncryption		"RSA-MD2"
+#define LN_md2WithRSAEncryption		"md2WithRSAEncryption"
+#define NID_md2WithRSAEncryption		7
+#define OBJ_md2WithRSAEncryption		OBJ_pkcs1,2L
+
+#define SN_md4WithRSAEncryption		"RSA-MD4"
+#define LN_md4WithRSAEncryption		"md4WithRSAEncryption"
+#define NID_md4WithRSAEncryption		396
+#define OBJ_md4WithRSAEncryption		OBJ_pkcs1,3L
+
+#define SN_md5WithRSAEncryption		"RSA-MD5"
+#define LN_md5WithRSAEncryption		"md5WithRSAEncryption"
+#define NID_md5WithRSAEncryption		8
+#define OBJ_md5WithRSAEncryption		OBJ_pkcs1,4L
+
+#define SN_sha1WithRSAEncryption		"RSA-SHA1"
+#define LN_sha1WithRSAEncryption		"sha1WithRSAEncryption"
+#define NID_sha1WithRSAEncryption		65
+#define OBJ_sha1WithRSAEncryption		OBJ_pkcs1,5L
+
+#define SN_sha256WithRSAEncryption		"RSA-SHA256"
+#define LN_sha256WithRSAEncryption		"sha256WithRSAEncryption"
+#define NID_sha256WithRSAEncryption		668
+#define OBJ_sha256WithRSAEncryption		OBJ_pkcs1,11L
+
+#define SN_sha384WithRSAEncryption		"RSA-SHA384"
+#define LN_sha384WithRSAEncryption		"sha384WithRSAEncryption"
+#define NID_sha384WithRSAEncryption		669
+#define OBJ_sha384WithRSAEncryption		OBJ_pkcs1,12L
+
+#define SN_sha512WithRSAEncryption		"RSA-SHA512"
+#define LN_sha512WithRSAEncryption		"sha512WithRSAEncryption"
+#define NID_sha512WithRSAEncryption		670
+#define OBJ_sha512WithRSAEncryption		OBJ_pkcs1,13L
+
+#define SN_sha224WithRSAEncryption		"RSA-SHA224"
+#define LN_sha224WithRSAEncryption		"sha224WithRSAEncryption"
+#define NID_sha224WithRSAEncryption		671
+#define OBJ_sha224WithRSAEncryption		OBJ_pkcs1,14L
+
+#define SN_pkcs3		"pkcs3"
+#define NID_pkcs3		27
+#define OBJ_pkcs3		OBJ_pkcs,3L
+
+#define LN_dhKeyAgreement		"dhKeyAgreement"
+#define NID_dhKeyAgreement		28
+#define OBJ_dhKeyAgreement		OBJ_pkcs3,1L
+
+#define SN_pkcs5		"pkcs5"
+#define NID_pkcs5		187
+#define OBJ_pkcs5		OBJ_pkcs,5L
+
+#define SN_pbeWithMD2AndDES_CBC		"PBE-MD2-DES"
+#define LN_pbeWithMD2AndDES_CBC		"pbeWithMD2AndDES-CBC"
+#define NID_pbeWithMD2AndDES_CBC		9
+#define OBJ_pbeWithMD2AndDES_CBC		OBJ_pkcs5,1L
+
+#define SN_pbeWithMD5AndDES_CBC		"PBE-MD5-DES"
+#define LN_pbeWithMD5AndDES_CBC		"pbeWithMD5AndDES-CBC"
+#define NID_pbeWithMD5AndDES_CBC		10
+#define OBJ_pbeWithMD5AndDES_CBC		OBJ_pkcs5,3L
+
+#define SN_pbeWithMD2AndRC2_CBC		"PBE-MD2-RC2-64"
+#define LN_pbeWithMD2AndRC2_CBC		"pbeWithMD2AndRC2-CBC"
+#define NID_pbeWithMD2AndRC2_CBC		168
+#define OBJ_pbeWithMD2AndRC2_CBC		OBJ_pkcs5,4L
+
+#define SN_pbeWithMD5AndRC2_CBC		"PBE-MD5-RC2-64"
+#define LN_pbeWithMD5AndRC2_CBC		"pbeWithMD5AndRC2-CBC"
+#define NID_pbeWithMD5AndRC2_CBC		169
+#define OBJ_pbeWithMD5AndRC2_CBC		OBJ_pkcs5,6L
+
+#define SN_pbeWithSHA1AndDES_CBC		"PBE-SHA1-DES"
+#define LN_pbeWithSHA1AndDES_CBC		"pbeWithSHA1AndDES-CBC"
+#define NID_pbeWithSHA1AndDES_CBC		170
+#define OBJ_pbeWithSHA1AndDES_CBC		OBJ_pkcs5,10L
+
+#define SN_pbeWithSHA1AndRC2_CBC		"PBE-SHA1-RC2-64"
+#define LN_pbeWithSHA1AndRC2_CBC		"pbeWithSHA1AndRC2-CBC"
+#define NID_pbeWithSHA1AndRC2_CBC		68
+#define OBJ_pbeWithSHA1AndRC2_CBC		OBJ_pkcs5,11L
+
+#define LN_id_pbkdf2		"PBKDF2"
+#define NID_id_pbkdf2		69
+#define OBJ_id_pbkdf2		OBJ_pkcs5,12L
+
+#define LN_pbes2		"PBES2"
+#define NID_pbes2		161
+#define OBJ_pbes2		OBJ_pkcs5,13L
+
+#define LN_pbmac1		"PBMAC1"
+#define NID_pbmac1		162
+#define OBJ_pbmac1		OBJ_pkcs5,14L
+
+#define SN_pkcs7		"pkcs7"
+#define NID_pkcs7		20
+#define OBJ_pkcs7		OBJ_pkcs,7L
+
+#define LN_pkcs7_data		"pkcs7-data"
+#define NID_pkcs7_data		21
+#define OBJ_pkcs7_data		OBJ_pkcs7,1L
+
+#define LN_pkcs7_signed		"pkcs7-signedData"
+#define NID_pkcs7_signed		22
+#define OBJ_pkcs7_signed		OBJ_pkcs7,2L
+
+#define LN_pkcs7_enveloped		"pkcs7-envelopedData"
+#define NID_pkcs7_enveloped		23
+#define OBJ_pkcs7_enveloped		OBJ_pkcs7,3L
+
+#define LN_pkcs7_signedAndEnveloped		"pkcs7-signedAndEnvelopedData"
+#define NID_pkcs7_signedAndEnveloped		24
+#define OBJ_pkcs7_signedAndEnveloped		OBJ_pkcs7,4L
+
+#define LN_pkcs7_digest		"pkcs7-digestData"
+#define NID_pkcs7_digest		25
+#define OBJ_pkcs7_digest		OBJ_pkcs7,5L
+
+#define LN_pkcs7_encrypted		"pkcs7-encryptedData"
+#define NID_pkcs7_encrypted		26
+#define OBJ_pkcs7_encrypted		OBJ_pkcs7,6L
+
+#define SN_pkcs9		"pkcs9"
+#define NID_pkcs9		47
+#define OBJ_pkcs9		OBJ_pkcs,9L
+
+#define LN_pkcs9_emailAddress		"emailAddress"
+#define NID_pkcs9_emailAddress		48
+#define OBJ_pkcs9_emailAddress		OBJ_pkcs9,1L
+
+#define LN_pkcs9_unstructuredName		"unstructuredName"
+#define NID_pkcs9_unstructuredName		49
+#define OBJ_pkcs9_unstructuredName		OBJ_pkcs9,2L
+
+#define LN_pkcs9_contentType		"contentType"
+#define NID_pkcs9_contentType		50
+#define OBJ_pkcs9_contentType		OBJ_pkcs9,3L
+
+#define LN_pkcs9_messageDigest		"messageDigest"
+#define NID_pkcs9_messageDigest		51
+#define OBJ_pkcs9_messageDigest		OBJ_pkcs9,4L
+
+#define LN_pkcs9_signingTime		"signingTime"
+#define NID_pkcs9_signingTime		52
+#define OBJ_pkcs9_signingTime		OBJ_pkcs9,5L
+
+#define LN_pkcs9_countersignature		"countersignature"
+#define NID_pkcs9_countersignature		53
+#define OBJ_pkcs9_countersignature		OBJ_pkcs9,6L
+
+#define LN_pkcs9_challengePassword		"challengePassword"
+#define NID_pkcs9_challengePassword		54
+#define OBJ_pkcs9_challengePassword		OBJ_pkcs9,7L
+
+#define LN_pkcs9_unstructuredAddress		"unstructuredAddress"
+#define NID_pkcs9_unstructuredAddress		55
+#define OBJ_pkcs9_unstructuredAddress		OBJ_pkcs9,8L
+
+#define LN_pkcs9_extCertAttributes		"extendedCertificateAttributes"
+#define NID_pkcs9_extCertAttributes		56
+#define OBJ_pkcs9_extCertAttributes		OBJ_pkcs9,9L
+
+#define SN_ext_req		"extReq"
+#define LN_ext_req		"Extension Request"
+#define NID_ext_req		172
+#define OBJ_ext_req		OBJ_pkcs9,14L
+
+#define SN_SMIMECapabilities		"SMIME-CAPS"
+#define LN_SMIMECapabilities		"S/MIME Capabilities"
+#define NID_SMIMECapabilities		167
+#define OBJ_SMIMECapabilities		OBJ_pkcs9,15L
+
+#define SN_SMIME		"SMIME"
+#define LN_SMIME		"S/MIME"
+#define NID_SMIME		188
+#define OBJ_SMIME		OBJ_pkcs9,16L
+
+#define SN_id_smime_mod		"id-smime-mod"
+#define NID_id_smime_mod		189
+#define OBJ_id_smime_mod		OBJ_SMIME,0L
+
+#define SN_id_smime_ct		"id-smime-ct"
+#define NID_id_smime_ct		190
+#define OBJ_id_smime_ct		OBJ_SMIME,1L
+
+#define SN_id_smime_aa		"id-smime-aa"
+#define NID_id_smime_aa		191
+#define OBJ_id_smime_aa		OBJ_SMIME,2L
+
+#define SN_id_smime_alg		"id-smime-alg"
+#define NID_id_smime_alg		192
+#define OBJ_id_smime_alg		OBJ_SMIME,3L
+
+#define SN_id_smime_cd		"id-smime-cd"
+#define NID_id_smime_cd		193
+#define OBJ_id_smime_cd		OBJ_SMIME,4L
+
+#define SN_id_smime_spq		"id-smime-spq"
+#define NID_id_smime_spq		194
+#define OBJ_id_smime_spq		OBJ_SMIME,5L
+
+#define SN_id_smime_cti		"id-smime-cti"
+#define NID_id_smime_cti		195
+#define OBJ_id_smime_cti		OBJ_SMIME,6L
+
+#define SN_id_smime_mod_cms		"id-smime-mod-cms"
+#define NID_id_smime_mod_cms		196
+#define OBJ_id_smime_mod_cms		OBJ_id_smime_mod,1L
+
+#define SN_id_smime_mod_ess		"id-smime-mod-ess"
+#define NID_id_smime_mod_ess		197
+#define OBJ_id_smime_mod_ess		OBJ_id_smime_mod,2L
+
+#define SN_id_smime_mod_oid		"id-smime-mod-oid"
+#define NID_id_smime_mod_oid		198
+#define OBJ_id_smime_mod_oid		OBJ_id_smime_mod,3L
+
+#define SN_id_smime_mod_msg_v3		"id-smime-mod-msg-v3"
+#define NID_id_smime_mod_msg_v3		199
+#define OBJ_id_smime_mod_msg_v3		OBJ_id_smime_mod,4L
+
+#define SN_id_smime_mod_ets_eSignature_88		"id-smime-mod-ets-eSignature-88"
+#define NID_id_smime_mod_ets_eSignature_88		200
+#define OBJ_id_smime_mod_ets_eSignature_88		OBJ_id_smime_mod,5L
+
+#define SN_id_smime_mod_ets_eSignature_97		"id-smime-mod-ets-eSignature-97"
+#define NID_id_smime_mod_ets_eSignature_97		201
+#define OBJ_id_smime_mod_ets_eSignature_97		OBJ_id_smime_mod,6L
+
+#define SN_id_smime_mod_ets_eSigPolicy_88		"id-smime-mod-ets-eSigPolicy-88"
+#define NID_id_smime_mod_ets_eSigPolicy_88		202
+#define OBJ_id_smime_mod_ets_eSigPolicy_88		OBJ_id_smime_mod,7L
+
+#define SN_id_smime_mod_ets_eSigPolicy_97		"id-smime-mod-ets-eSigPolicy-97"
+#define NID_id_smime_mod_ets_eSigPolicy_97		203
+#define OBJ_id_smime_mod_ets_eSigPolicy_97		OBJ_id_smime_mod,8L
+
+#define SN_id_smime_ct_receipt		"id-smime-ct-receipt"
+#define NID_id_smime_ct_receipt		204
+#define OBJ_id_smime_ct_receipt		OBJ_id_smime_ct,1L
+
+#define SN_id_smime_ct_authData		"id-smime-ct-authData"
+#define NID_id_smime_ct_authData		205
+#define OBJ_id_smime_ct_authData		OBJ_id_smime_ct,2L
+
+#define SN_id_smime_ct_publishCert		"id-smime-ct-publishCert"
+#define NID_id_smime_ct_publishCert		206
+#define OBJ_id_smime_ct_publishCert		OBJ_id_smime_ct,3L
+
+#define SN_id_smime_ct_TSTInfo		"id-smime-ct-TSTInfo"
+#define NID_id_smime_ct_TSTInfo		207
+#define OBJ_id_smime_ct_TSTInfo		OBJ_id_smime_ct,4L
+
+#define SN_id_smime_ct_TDTInfo		"id-smime-ct-TDTInfo"
+#define NID_id_smime_ct_TDTInfo		208
+#define OBJ_id_smime_ct_TDTInfo		OBJ_id_smime_ct,5L
+
+#define SN_id_smime_ct_contentInfo		"id-smime-ct-contentInfo"
+#define NID_id_smime_ct_contentInfo		209
+#define OBJ_id_smime_ct_contentInfo		OBJ_id_smime_ct,6L
+
+#define SN_id_smime_ct_DVCSRequestData		"id-smime-ct-DVCSRequestData"
+#define NID_id_smime_ct_DVCSRequestData		210
+#define OBJ_id_smime_ct_DVCSRequestData		OBJ_id_smime_ct,7L
+
+#define SN_id_smime_ct_DVCSResponseData		"id-smime-ct-DVCSResponseData"
+#define NID_id_smime_ct_DVCSResponseData		211
+#define OBJ_id_smime_ct_DVCSResponseData		OBJ_id_smime_ct,8L
+
+#define SN_id_smime_aa_receiptRequest		"id-smime-aa-receiptRequest"
+#define NID_id_smime_aa_receiptRequest		212
+#define OBJ_id_smime_aa_receiptRequest		OBJ_id_smime_aa,1L
+
+#define SN_id_smime_aa_securityLabel		"id-smime-aa-securityLabel"
+#define NID_id_smime_aa_securityLabel		213
+#define OBJ_id_smime_aa_securityLabel		OBJ_id_smime_aa,2L
+
+#define SN_id_smime_aa_mlExpandHistory		"id-smime-aa-mlExpandHistory"
+#define NID_id_smime_aa_mlExpandHistory		214
+#define OBJ_id_smime_aa_mlExpandHistory		OBJ_id_smime_aa,3L
+
+#define SN_id_smime_aa_contentHint		"id-smime-aa-contentHint"
+#define NID_id_smime_aa_contentHint		215
+#define OBJ_id_smime_aa_contentHint		OBJ_id_smime_aa,4L
+
+#define SN_id_smime_aa_msgSigDigest		"id-smime-aa-msgSigDigest"
+#define NID_id_smime_aa_msgSigDigest		216
+#define OBJ_id_smime_aa_msgSigDigest		OBJ_id_smime_aa,5L
+
+#define SN_id_smime_aa_encapContentType		"id-smime-aa-encapContentType"
+#define NID_id_smime_aa_encapContentType		217
+#define OBJ_id_smime_aa_encapContentType		OBJ_id_smime_aa,6L
+
+#define SN_id_smime_aa_contentIdentifier		"id-smime-aa-contentIdentifier"
+#define NID_id_smime_aa_contentIdentifier		218
+#define OBJ_id_smime_aa_contentIdentifier		OBJ_id_smime_aa,7L
+
+#define SN_id_smime_aa_macValue		"id-smime-aa-macValue"
+#define NID_id_smime_aa_macValue		219
+#define OBJ_id_smime_aa_macValue		OBJ_id_smime_aa,8L
+
+#define SN_id_smime_aa_equivalentLabels		"id-smime-aa-equivalentLabels"
+#define NID_id_smime_aa_equivalentLabels		220
+#define OBJ_id_smime_aa_equivalentLabels		OBJ_id_smime_aa,9L
+
+#define SN_id_smime_aa_contentReference		"id-smime-aa-contentReference"
+#define NID_id_smime_aa_contentReference		221
+#define OBJ_id_smime_aa_contentReference		OBJ_id_smime_aa,10L
+
+#define SN_id_smime_aa_encrypKeyPref		"id-smime-aa-encrypKeyPref"
+#define NID_id_smime_aa_encrypKeyPref		222
+#define OBJ_id_smime_aa_encrypKeyPref		OBJ_id_smime_aa,11L
+
+#define SN_id_smime_aa_signingCertificate		"id-smime-aa-signingCertificate"
+#define NID_id_smime_aa_signingCertificate		223
+#define OBJ_id_smime_aa_signingCertificate		OBJ_id_smime_aa,12L
+
+#define SN_id_smime_aa_smimeEncryptCerts		"id-smime-aa-smimeEncryptCerts"
+#define NID_id_smime_aa_smimeEncryptCerts		224
+#define OBJ_id_smime_aa_smimeEncryptCerts		OBJ_id_smime_aa,13L
+
+#define SN_id_smime_aa_timeStampToken		"id-smime-aa-timeStampToken"
+#define NID_id_smime_aa_timeStampToken		225
+#define OBJ_id_smime_aa_timeStampToken		OBJ_id_smime_aa,14L
+
+#define SN_id_smime_aa_ets_sigPolicyId		"id-smime-aa-ets-sigPolicyId"
+#define NID_id_smime_aa_ets_sigPolicyId		226
+#define OBJ_id_smime_aa_ets_sigPolicyId		OBJ_id_smime_aa,15L
+
+#define SN_id_smime_aa_ets_commitmentType		"id-smime-aa-ets-commitmentType"
+#define NID_id_smime_aa_ets_commitmentType		227
+#define OBJ_id_smime_aa_ets_commitmentType		OBJ_id_smime_aa,16L
+
+#define SN_id_smime_aa_ets_signerLocation		"id-smime-aa-ets-signerLocation"
+#define NID_id_smime_aa_ets_signerLocation		228
+#define OBJ_id_smime_aa_ets_signerLocation		OBJ_id_smime_aa,17L
+
+#define SN_id_smime_aa_ets_signerAttr		"id-smime-aa-ets-signerAttr"
+#define NID_id_smime_aa_ets_signerAttr		229
+#define OBJ_id_smime_aa_ets_signerAttr		OBJ_id_smime_aa,18L
+
+#define SN_id_smime_aa_ets_otherSigCert		"id-smime-aa-ets-otherSigCert"
+#define NID_id_smime_aa_ets_otherSigCert		230
+#define OBJ_id_smime_aa_ets_otherSigCert		OBJ_id_smime_aa,19L
+
+#define SN_id_smime_aa_ets_contentTimestamp		"id-smime-aa-ets-contentTimestamp"
+#define NID_id_smime_aa_ets_contentTimestamp		231
+#define OBJ_id_smime_aa_ets_contentTimestamp		OBJ_id_smime_aa,20L
+
+#define SN_id_smime_aa_ets_CertificateRefs		"id-smime-aa-ets-CertificateRefs"
+#define NID_id_smime_aa_ets_CertificateRefs		232
+#define OBJ_id_smime_aa_ets_CertificateRefs		OBJ_id_smime_aa,21L
+
+#define SN_id_smime_aa_ets_RevocationRefs		"id-smime-aa-ets-RevocationRefs"
+#define NID_id_smime_aa_ets_RevocationRefs		233
+#define OBJ_id_smime_aa_ets_RevocationRefs		OBJ_id_smime_aa,22L
+
+#define SN_id_smime_aa_ets_certValues		"id-smime-aa-ets-certValues"
+#define NID_id_smime_aa_ets_certValues		234
+#define OBJ_id_smime_aa_ets_certValues		OBJ_id_smime_aa,23L
+
+#define SN_id_smime_aa_ets_revocationValues		"id-smime-aa-ets-revocationValues"
+#define NID_id_smime_aa_ets_revocationValues		235
+#define OBJ_id_smime_aa_ets_revocationValues		OBJ_id_smime_aa,24L
+
+#define SN_id_smime_aa_ets_escTimeStamp		"id-smime-aa-ets-escTimeStamp"
+#define NID_id_smime_aa_ets_escTimeStamp		236
+#define OBJ_id_smime_aa_ets_escTimeStamp		OBJ_id_smime_aa,25L
+
+#define SN_id_smime_aa_ets_certCRLTimestamp		"id-smime-aa-ets-certCRLTimestamp"
+#define NID_id_smime_aa_ets_certCRLTimestamp		237
+#define OBJ_id_smime_aa_ets_certCRLTimestamp		OBJ_id_smime_aa,26L
+
+#define SN_id_smime_aa_ets_archiveTimeStamp		"id-smime-aa-ets-archiveTimeStamp"
+#define NID_id_smime_aa_ets_archiveTimeStamp		238
+#define OBJ_id_smime_aa_ets_archiveTimeStamp		OBJ_id_smime_aa,27L
+
+#define SN_id_smime_aa_signatureType		"id-smime-aa-signatureType"
+#define NID_id_smime_aa_signatureType		239
+#define OBJ_id_smime_aa_signatureType		OBJ_id_smime_aa,28L
+
+#define SN_id_smime_aa_dvcs_dvc		"id-smime-aa-dvcs-dvc"
+#define NID_id_smime_aa_dvcs_dvc		240
+#define OBJ_id_smime_aa_dvcs_dvc		OBJ_id_smime_aa,29L
+
+#define SN_id_smime_alg_ESDHwith3DES		"id-smime-alg-ESDHwith3DES"
+#define NID_id_smime_alg_ESDHwith3DES		241
+#define OBJ_id_smime_alg_ESDHwith3DES		OBJ_id_smime_alg,1L
+
+#define SN_id_smime_alg_ESDHwithRC2		"id-smime-alg-ESDHwithRC2"
+#define NID_id_smime_alg_ESDHwithRC2		242
+#define OBJ_id_smime_alg_ESDHwithRC2		OBJ_id_smime_alg,2L
+
+#define SN_id_smime_alg_3DESwrap		"id-smime-alg-3DESwrap"
+#define NID_id_smime_alg_3DESwrap		243
+#define OBJ_id_smime_alg_3DESwrap		OBJ_id_smime_alg,3L
+
+#define SN_id_smime_alg_RC2wrap		"id-smime-alg-RC2wrap"
+#define NID_id_smime_alg_RC2wrap		244
+#define OBJ_id_smime_alg_RC2wrap		OBJ_id_smime_alg,4L
+
+#define SN_id_smime_alg_ESDH		"id-smime-alg-ESDH"
+#define NID_id_smime_alg_ESDH		245
+#define OBJ_id_smime_alg_ESDH		OBJ_id_smime_alg,5L
+
+#define SN_id_smime_alg_CMS3DESwrap		"id-smime-alg-CMS3DESwrap"
+#define NID_id_smime_alg_CMS3DESwrap		246
+#define OBJ_id_smime_alg_CMS3DESwrap		OBJ_id_smime_alg,6L
+
+#define SN_id_smime_alg_CMSRC2wrap		"id-smime-alg-CMSRC2wrap"
+#define NID_id_smime_alg_CMSRC2wrap		247
+#define OBJ_id_smime_alg_CMSRC2wrap		OBJ_id_smime_alg,7L
+
+#define SN_id_smime_cd_ldap		"id-smime-cd-ldap"
+#define NID_id_smime_cd_ldap		248
+#define OBJ_id_smime_cd_ldap		OBJ_id_smime_cd,1L
+
+#define SN_id_smime_spq_ets_sqt_uri		"id-smime-spq-ets-sqt-uri"
+#define NID_id_smime_spq_ets_sqt_uri		249
+#define OBJ_id_smime_spq_ets_sqt_uri		OBJ_id_smime_spq,1L
+
+#define SN_id_smime_spq_ets_sqt_unotice		"id-smime-spq-ets-sqt-unotice"
+#define NID_id_smime_spq_ets_sqt_unotice		250
+#define OBJ_id_smime_spq_ets_sqt_unotice		OBJ_id_smime_spq,2L
+
+#define SN_id_smime_cti_ets_proofOfOrigin		"id-smime-cti-ets-proofOfOrigin"
+#define NID_id_smime_cti_ets_proofOfOrigin		251
+#define OBJ_id_smime_cti_ets_proofOfOrigin		OBJ_id_smime_cti,1L
+
+#define SN_id_smime_cti_ets_proofOfReceipt		"id-smime-cti-ets-proofOfReceipt"
+#define NID_id_smime_cti_ets_proofOfReceipt		252
+#define OBJ_id_smime_cti_ets_proofOfReceipt		OBJ_id_smime_cti,2L
+
+#define SN_id_smime_cti_ets_proofOfDelivery		"id-smime-cti-ets-proofOfDelivery"
+#define NID_id_smime_cti_ets_proofOfDelivery		253
+#define OBJ_id_smime_cti_ets_proofOfDelivery		OBJ_id_smime_cti,3L
+
+#define SN_id_smime_cti_ets_proofOfSender		"id-smime-cti-ets-proofOfSender"
+#define NID_id_smime_cti_ets_proofOfSender		254
+#define OBJ_id_smime_cti_ets_proofOfSender		OBJ_id_smime_cti,4L
+
+#define SN_id_smime_cti_ets_proofOfApproval		"id-smime-cti-ets-proofOfApproval"
+#define NID_id_smime_cti_ets_proofOfApproval		255
+#define OBJ_id_smime_cti_ets_proofOfApproval		OBJ_id_smime_cti,5L
+
+#define SN_id_smime_cti_ets_proofOfCreation		"id-smime-cti-ets-proofOfCreation"
+#define NID_id_smime_cti_ets_proofOfCreation		256
+#define OBJ_id_smime_cti_ets_proofOfCreation		OBJ_id_smime_cti,6L
+
+#define LN_friendlyName		"friendlyName"
+#define NID_friendlyName		156
+#define OBJ_friendlyName		OBJ_pkcs9,20L
+
+#define LN_localKeyID		"localKeyID"
+#define NID_localKeyID		157
+#define OBJ_localKeyID		OBJ_pkcs9,21L
+
+#define SN_ms_csp_name		"CSPName"
+#define LN_ms_csp_name		"Microsoft CSP Name"
+#define NID_ms_csp_name		417
+#define OBJ_ms_csp_name		1L,3L,6L,1L,4L,1L,311L,17L,1L
+
+#define OBJ_certTypes		OBJ_pkcs9,22L
+
+#define LN_x509Certificate		"x509Certificate"
+#define NID_x509Certificate		158
+#define OBJ_x509Certificate		OBJ_certTypes,1L
+
+#define LN_sdsiCertificate		"sdsiCertificate"
+#define NID_sdsiCertificate		159
+#define OBJ_sdsiCertificate		OBJ_certTypes,2L
+
+#define OBJ_crlTypes		OBJ_pkcs9,23L
+
+#define LN_x509Crl		"x509Crl"
+#define NID_x509Crl		160
+#define OBJ_x509Crl		OBJ_crlTypes,1L
+
+#define OBJ_pkcs12		OBJ_pkcs,12L
+
+#define OBJ_pkcs12_pbeids		OBJ_pkcs12,1L
+
+#define SN_pbe_WithSHA1And128BitRC4		"PBE-SHA1-RC4-128"
+#define LN_pbe_WithSHA1And128BitRC4		"pbeWithSHA1And128BitRC4"
+#define NID_pbe_WithSHA1And128BitRC4		144
+#define OBJ_pbe_WithSHA1And128BitRC4		OBJ_pkcs12_pbeids,1L
+
+#define SN_pbe_WithSHA1And40BitRC4		"PBE-SHA1-RC4-40"
+#define LN_pbe_WithSHA1And40BitRC4		"pbeWithSHA1And40BitRC4"
+#define NID_pbe_WithSHA1And40BitRC4		145
+#define OBJ_pbe_WithSHA1And40BitRC4		OBJ_pkcs12_pbeids,2L
+
+#define SN_pbe_WithSHA1And3_Key_TripleDES_CBC		"PBE-SHA1-3DES"
+#define LN_pbe_WithSHA1And3_Key_TripleDES_CBC		"pbeWithSHA1And3-KeyTripleDES-CBC"
+#define NID_pbe_WithSHA1And3_Key_TripleDES_CBC		146
+#define OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC		OBJ_pkcs12_pbeids,3L
+
+#define SN_pbe_WithSHA1And2_Key_TripleDES_CBC		"PBE-SHA1-2DES"
+#define LN_pbe_WithSHA1And2_Key_TripleDES_CBC		"pbeWithSHA1And2-KeyTripleDES-CBC"
+#define NID_pbe_WithSHA1And2_Key_TripleDES_CBC		147
+#define OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC		OBJ_pkcs12_pbeids,4L
+
+#define SN_pbe_WithSHA1And128BitRC2_CBC		"PBE-SHA1-RC2-128"
+#define LN_pbe_WithSHA1And128BitRC2_CBC		"pbeWithSHA1And128BitRC2-CBC"
+#define NID_pbe_WithSHA1And128BitRC2_CBC		148
+#define OBJ_pbe_WithSHA1And128BitRC2_CBC		OBJ_pkcs12_pbeids,5L
+
+#define SN_pbe_WithSHA1And40BitRC2_CBC		"PBE-SHA1-RC2-40"
+#define LN_pbe_WithSHA1And40BitRC2_CBC		"pbeWithSHA1And40BitRC2-CBC"
+#define NID_pbe_WithSHA1And40BitRC2_CBC		149
+#define OBJ_pbe_WithSHA1And40BitRC2_CBC		OBJ_pkcs12_pbeids,6L
+
+#define OBJ_pkcs12_Version1		OBJ_pkcs12,10L
+
+#define OBJ_pkcs12_BagIds		OBJ_pkcs12_Version1,1L
+
+#define LN_keyBag		"keyBag"
+#define NID_keyBag		150
+#define OBJ_keyBag		OBJ_pkcs12_BagIds,1L
+
+#define LN_pkcs8ShroudedKeyBag		"pkcs8ShroudedKeyBag"
+#define NID_pkcs8ShroudedKeyBag		151
+#define OBJ_pkcs8ShroudedKeyBag		OBJ_pkcs12_BagIds,2L
+
+#define LN_certBag		"certBag"
+#define NID_certBag		152
+#define OBJ_certBag		OBJ_pkcs12_BagIds,3L
+
+#define LN_crlBag		"crlBag"
+#define NID_crlBag		153
+#define OBJ_crlBag		OBJ_pkcs12_BagIds,4L
+
+#define LN_secretBag		"secretBag"
+#define NID_secretBag		154
+#define OBJ_secretBag		OBJ_pkcs12_BagIds,5L
+
+#define LN_safeContentsBag		"safeContentsBag"
+#define NID_safeContentsBag		155
+#define OBJ_safeContentsBag		OBJ_pkcs12_BagIds,6L
+
+#define SN_md2		"MD2"
+#define LN_md2		"md2"
+#define NID_md2		3
+#define OBJ_md2		OBJ_rsadsi,2L,2L
+
+#define SN_md4		"MD4"
+#define LN_md4		"md4"
+#define NID_md4		257
+#define OBJ_md4		OBJ_rsadsi,2L,4L
+
+#define SN_md5		"MD5"
+#define LN_md5		"md5"
+#define NID_md5		4
+#define OBJ_md5		OBJ_rsadsi,2L,5L
+
+#define SN_md5_sha1		"MD5-SHA1"
+#define LN_md5_sha1		"md5-sha1"
+#define NID_md5_sha1		114
+
+#define LN_hmacWithSHA1		"hmacWithSHA1"
+#define NID_hmacWithSHA1		163
+#define OBJ_hmacWithSHA1		OBJ_rsadsi,2L,7L
+
+#define SN_rc2_cbc		"RC2-CBC"
+#define LN_rc2_cbc		"rc2-cbc"
+#define NID_rc2_cbc		37
+#define OBJ_rc2_cbc		OBJ_rsadsi,3L,2L
+
+#define SN_rc2_ecb		"RC2-ECB"
+#define LN_rc2_ecb		"rc2-ecb"
+#define NID_rc2_ecb		38
+
+#define SN_rc2_cfb64		"RC2-CFB"
+#define LN_rc2_cfb64		"rc2-cfb"
+#define NID_rc2_cfb64		39
+
+#define SN_rc2_ofb64		"RC2-OFB"
+#define LN_rc2_ofb64		"rc2-ofb"
+#define NID_rc2_ofb64		40
+
+#define SN_rc2_40_cbc		"RC2-40-CBC"
+#define LN_rc2_40_cbc		"rc2-40-cbc"
+#define NID_rc2_40_cbc		98
+
+#define SN_rc2_64_cbc		"RC2-64-CBC"
+#define LN_rc2_64_cbc		"rc2-64-cbc"
+#define NID_rc2_64_cbc		166
+
+#define SN_rc4		"RC4"
+#define LN_rc4		"rc4"
+#define NID_rc4		5
+#define OBJ_rc4		OBJ_rsadsi,3L,4L
+
+#define SN_rc4_40		"RC4-40"
+#define LN_rc4_40		"rc4-40"
+#define NID_rc4_40		97
+
+#define SN_des_ede3_cbc		"DES-EDE3-CBC"
+#define LN_des_ede3_cbc		"des-ede3-cbc"
+#define NID_des_ede3_cbc		44
+#define OBJ_des_ede3_cbc		OBJ_rsadsi,3L,7L
+
+#define SN_rc5_cbc		"RC5-CBC"
+#define LN_rc5_cbc		"rc5-cbc"
+#define NID_rc5_cbc		120
+#define OBJ_rc5_cbc		OBJ_rsadsi,3L,8L
+
+#define SN_rc5_ecb		"RC5-ECB"
+#define LN_rc5_ecb		"rc5-ecb"
+#define NID_rc5_ecb		121
+
+#define SN_rc5_cfb64		"RC5-CFB"
+#define LN_rc5_cfb64		"rc5-cfb"
+#define NID_rc5_cfb64		122
+
+#define SN_rc5_ofb64		"RC5-OFB"
+#define LN_rc5_ofb64		"rc5-ofb"
+#define NID_rc5_ofb64		123
+
+#define SN_ms_ext_req		"msExtReq"
+#define LN_ms_ext_req		"Microsoft Extension Request"
+#define NID_ms_ext_req		171
+#define OBJ_ms_ext_req		1L,3L,6L,1L,4L,1L,311L,2L,1L,14L
+
+#define SN_ms_code_ind		"msCodeInd"
+#define LN_ms_code_ind		"Microsoft Individual Code Signing"
+#define NID_ms_code_ind		134
+#define OBJ_ms_code_ind		1L,3L,6L,1L,4L,1L,311L,2L,1L,21L
+
+#define SN_ms_code_com		"msCodeCom"
+#define LN_ms_code_com		"Microsoft Commercial Code Signing"
+#define NID_ms_code_com		135
+#define OBJ_ms_code_com		1L,3L,6L,1L,4L,1L,311L,2L,1L,22L
+
+#define SN_ms_ctl_sign		"msCTLSign"
+#define LN_ms_ctl_sign		"Microsoft Trust List Signing"
+#define NID_ms_ctl_sign		136
+#define OBJ_ms_ctl_sign		1L,3L,6L,1L,4L,1L,311L,10L,3L,1L
+
+#define SN_ms_sgc		"msSGC"
+#define LN_ms_sgc		"Microsoft Server Gated Crypto"
+#define NID_ms_sgc		137
+#define OBJ_ms_sgc		1L,3L,6L,1L,4L,1L,311L,10L,3L,3L
+
+#define SN_ms_efs		"msEFS"
+#define LN_ms_efs		"Microsoft Encrypted File System"
+#define NID_ms_efs		138
+#define OBJ_ms_efs		1L,3L,6L,1L,4L,1L,311L,10L,3L,4L
+
+#define SN_ms_smartcard_login		"msSmartcardLogin"
+#define LN_ms_smartcard_login		"Microsoft Smartcardlogin"
+#define NID_ms_smartcard_login		648
+#define OBJ_ms_smartcard_login		1L,3L,6L,1L,4L,1L,311L,20L,2L,2L
+
+#define SN_ms_upn		"msUPN"
+#define LN_ms_upn		"Microsoft Universal Principal Name"
+#define NID_ms_upn		649
+#define OBJ_ms_upn		1L,3L,6L,1L,4L,1L,311L,20L,2L,3L
+
+#define SN_idea_cbc		"IDEA-CBC"
+#define LN_idea_cbc		"idea-cbc"
+#define NID_idea_cbc		34
+#define OBJ_idea_cbc		1L,3L,6L,1L,4L,1L,188L,7L,1L,1L,2L
+
+#define SN_idea_ecb		"IDEA-ECB"
+#define LN_idea_ecb		"idea-ecb"
+#define NID_idea_ecb		36
+
+#define SN_idea_cfb64		"IDEA-CFB"
+#define LN_idea_cfb64		"idea-cfb"
+#define NID_idea_cfb64		35
+
+#define SN_idea_ofb64		"IDEA-OFB"
+#define LN_idea_ofb64		"idea-ofb"
+#define NID_idea_ofb64		46
+
+#define SN_bf_cbc		"BF-CBC"
+#define LN_bf_cbc		"bf-cbc"
+#define NID_bf_cbc		91
+#define OBJ_bf_cbc		1L,3L,6L,1L,4L,1L,3029L,1L,2L
+
+#define SN_bf_ecb		"BF-ECB"
+#define LN_bf_ecb		"bf-ecb"
+#define NID_bf_ecb		92
+
+#define SN_bf_cfb64		"BF-CFB"
+#define LN_bf_cfb64		"bf-cfb"
+#define NID_bf_cfb64		93
+
+#define SN_bf_ofb64		"BF-OFB"
+#define LN_bf_ofb64		"bf-ofb"
+#define NID_bf_ofb64		94
+
+#define SN_id_pkix		"PKIX"
+#define NID_id_pkix		127
+#define OBJ_id_pkix		1L,3L,6L,1L,5L,5L,7L
+
+#define SN_id_pkix_mod		"id-pkix-mod"
+#define NID_id_pkix_mod		258
+#define OBJ_id_pkix_mod		OBJ_id_pkix,0L
+
+#define SN_id_pe		"id-pe"
+#define NID_id_pe		175
+#define OBJ_id_pe		OBJ_id_pkix,1L
+
+#define SN_id_qt		"id-qt"
+#define NID_id_qt		259
+#define OBJ_id_qt		OBJ_id_pkix,2L
+
+#define SN_id_kp		"id-kp"
+#define NID_id_kp		128
+#define OBJ_id_kp		OBJ_id_pkix,3L
+
+#define SN_id_it		"id-it"
+#define NID_id_it		260
+#define OBJ_id_it		OBJ_id_pkix,4L
+
+#define SN_id_pkip		"id-pkip"
+#define NID_id_pkip		261
+#define OBJ_id_pkip		OBJ_id_pkix,5L
+
+#define SN_id_alg		"id-alg"
+#define NID_id_alg		262
+#define OBJ_id_alg		OBJ_id_pkix,6L
+
+#define SN_id_cmc		"id-cmc"
+#define NID_id_cmc		263
+#define OBJ_id_cmc		OBJ_id_pkix,7L
+
+#define SN_id_on		"id-on"
+#define NID_id_on		264
+#define OBJ_id_on		OBJ_id_pkix,8L
+
+#define SN_id_pda		"id-pda"
+#define NID_id_pda		265
+#define OBJ_id_pda		OBJ_id_pkix,9L
+
+#define SN_id_aca		"id-aca"
+#define NID_id_aca		266
+#define OBJ_id_aca		OBJ_id_pkix,10L
+
+#define SN_id_qcs		"id-qcs"
+#define NID_id_qcs		267
+#define OBJ_id_qcs		OBJ_id_pkix,11L
+
+#define SN_id_cct		"id-cct"
+#define NID_id_cct		268
+#define OBJ_id_cct		OBJ_id_pkix,12L
+
+#define SN_id_ppl		"id-ppl"
+#define NID_id_ppl		662
+#define OBJ_id_ppl		OBJ_id_pkix,21L
+
+#define SN_id_ad		"id-ad"
+#define NID_id_ad		176
+#define OBJ_id_ad		OBJ_id_pkix,48L
+
+#define SN_id_pkix1_explicit_88		"id-pkix1-explicit-88"
+#define NID_id_pkix1_explicit_88		269
+#define OBJ_id_pkix1_explicit_88		OBJ_id_pkix_mod,1L
+
+#define SN_id_pkix1_implicit_88		"id-pkix1-implicit-88"
+#define NID_id_pkix1_implicit_88		270
+#define OBJ_id_pkix1_implicit_88		OBJ_id_pkix_mod,2L
+
+#define SN_id_pkix1_explicit_93		"id-pkix1-explicit-93"
+#define NID_id_pkix1_explicit_93		271
+#define OBJ_id_pkix1_explicit_93		OBJ_id_pkix_mod,3L
+
+#define SN_id_pkix1_implicit_93		"id-pkix1-implicit-93"
+#define NID_id_pkix1_implicit_93		272
+#define OBJ_id_pkix1_implicit_93		OBJ_id_pkix_mod,4L
+
+#define SN_id_mod_crmf		"id-mod-crmf"
+#define NID_id_mod_crmf		273
+#define OBJ_id_mod_crmf		OBJ_id_pkix_mod,5L
+
+#define SN_id_mod_cmc		"id-mod-cmc"
+#define NID_id_mod_cmc		274
+#define OBJ_id_mod_cmc		OBJ_id_pkix_mod,6L
+
+#define SN_id_mod_kea_profile_88		"id-mod-kea-profile-88"
+#define NID_id_mod_kea_profile_88		275
+#define OBJ_id_mod_kea_profile_88		OBJ_id_pkix_mod,7L
+
+#define SN_id_mod_kea_profile_93		"id-mod-kea-profile-93"
+#define NID_id_mod_kea_profile_93		276
+#define OBJ_id_mod_kea_profile_93		OBJ_id_pkix_mod,8L
+
+#define SN_id_mod_cmp		"id-mod-cmp"
+#define NID_id_mod_cmp		277
+#define OBJ_id_mod_cmp		OBJ_id_pkix_mod,9L
+
+#define SN_id_mod_qualified_cert_88		"id-mod-qualified-cert-88"
+#define NID_id_mod_qualified_cert_88		278
+#define OBJ_id_mod_qualified_cert_88		OBJ_id_pkix_mod,10L
+
+#define SN_id_mod_qualified_cert_93		"id-mod-qualified-cert-93"
+#define NID_id_mod_qualified_cert_93		279
+#define OBJ_id_mod_qualified_cert_93		OBJ_id_pkix_mod,11L
+
+#define SN_id_mod_attribute_cert		"id-mod-attribute-cert"
+#define NID_id_mod_attribute_cert		280
+#define OBJ_id_mod_attribute_cert		OBJ_id_pkix_mod,12L
+
+#define SN_id_mod_timestamp_protocol		"id-mod-timestamp-protocol"
+#define NID_id_mod_timestamp_protocol		281
+#define OBJ_id_mod_timestamp_protocol		OBJ_id_pkix_mod,13L
+
+#define SN_id_mod_ocsp		"id-mod-ocsp"
+#define NID_id_mod_ocsp		282
+#define OBJ_id_mod_ocsp		OBJ_id_pkix_mod,14L
+
+#define SN_id_mod_dvcs		"id-mod-dvcs"
+#define NID_id_mod_dvcs		283
+#define OBJ_id_mod_dvcs		OBJ_id_pkix_mod,15L
+
+#define SN_id_mod_cmp2000		"id-mod-cmp2000"
+#define NID_id_mod_cmp2000		284
+#define OBJ_id_mod_cmp2000		OBJ_id_pkix_mod,16L
+
+#define SN_info_access		"authorityInfoAccess"
+#define LN_info_access		"Authority Information Access"
+#define NID_info_access		177
+#define OBJ_info_access		OBJ_id_pe,1L
+
+#define SN_biometricInfo		"biometricInfo"
+#define LN_biometricInfo		"Biometric Info"
+#define NID_biometricInfo		285
+#define OBJ_biometricInfo		OBJ_id_pe,2L
+
+#define SN_qcStatements		"qcStatements"
+#define NID_qcStatements		286
+#define OBJ_qcStatements		OBJ_id_pe,3L
+
+#define SN_ac_auditEntity		"ac-auditEntity"
+#define NID_ac_auditEntity		287
+#define OBJ_ac_auditEntity		OBJ_id_pe,4L
+
+#define SN_ac_targeting		"ac-targeting"
+#define NID_ac_targeting		288
+#define OBJ_ac_targeting		OBJ_id_pe,5L
+
+#define SN_aaControls		"aaControls"
+#define NID_aaControls		289
+#define OBJ_aaControls		OBJ_id_pe,6L
+
+#define SN_sbgp_ipAddrBlock		"sbgp-ipAddrBlock"
+#define NID_sbgp_ipAddrBlock		290
+#define OBJ_sbgp_ipAddrBlock		OBJ_id_pe,7L
+
+#define SN_sbgp_autonomousSysNum		"sbgp-autonomousSysNum"
+#define NID_sbgp_autonomousSysNum		291
+#define OBJ_sbgp_autonomousSysNum		OBJ_id_pe,8L
+
+#define SN_sbgp_routerIdentifier		"sbgp-routerIdentifier"
+#define NID_sbgp_routerIdentifier		292
+#define OBJ_sbgp_routerIdentifier		OBJ_id_pe,9L
+
+#define SN_ac_proxying		"ac-proxying"
+#define NID_ac_proxying		397
+#define OBJ_ac_proxying		OBJ_id_pe,10L
+
+#define SN_sinfo_access		"subjectInfoAccess"
+#define LN_sinfo_access		"Subject Information Access"
+#define NID_sinfo_access		398
+#define OBJ_sinfo_access		OBJ_id_pe,11L
+
+#define SN_proxyCertInfo		"proxyCertInfo"
+#define LN_proxyCertInfo		"Proxy Certificate Information"
+#define NID_proxyCertInfo		663
+#define OBJ_proxyCertInfo		OBJ_id_pe,14L
+
+#define SN_id_qt_cps		"id-qt-cps"
+#define LN_id_qt_cps		"Policy Qualifier CPS"
+#define NID_id_qt_cps		164
+#define OBJ_id_qt_cps		OBJ_id_qt,1L
+
+#define SN_id_qt_unotice		"id-qt-unotice"
+#define LN_id_qt_unotice		"Policy Qualifier User Notice"
+#define NID_id_qt_unotice		165
+#define OBJ_id_qt_unotice		OBJ_id_qt,2L
+
+#define SN_textNotice		"textNotice"
+#define NID_textNotice		293
+#define OBJ_textNotice		OBJ_id_qt,3L
+
+#define SN_server_auth		"serverAuth"
+#define LN_server_auth		"TLS Web Server Authentication"
+#define NID_server_auth		129
+#define OBJ_server_auth		OBJ_id_kp,1L
+
+#define SN_client_auth		"clientAuth"
+#define LN_client_auth		"TLS Web Client Authentication"
+#define NID_client_auth		130
+#define OBJ_client_auth		OBJ_id_kp,2L
+
+#define SN_code_sign		"codeSigning"
+#define LN_code_sign		"Code Signing"
+#define NID_code_sign		131
+#define OBJ_code_sign		OBJ_id_kp,3L
+
+#define SN_email_protect		"emailProtection"
+#define LN_email_protect		"E-mail Protection"
+#define NID_email_protect		132
+#define OBJ_email_protect		OBJ_id_kp,4L
+
+#define SN_ipsecEndSystem		"ipsecEndSystem"
+#define LN_ipsecEndSystem		"IPSec End System"
+#define NID_ipsecEndSystem		294
+#define OBJ_ipsecEndSystem		OBJ_id_kp,5L
+
+#define SN_ipsecTunnel		"ipsecTunnel"
+#define LN_ipsecTunnel		"IPSec Tunnel"
+#define NID_ipsecTunnel		295
+#define OBJ_ipsecTunnel		OBJ_id_kp,6L
+
+#define SN_ipsecUser		"ipsecUser"
+#define LN_ipsecUser		"IPSec User"
+#define NID_ipsecUser		296
+#define OBJ_ipsecUser		OBJ_id_kp,7L
+
+#define SN_time_stamp		"timeStamping"
+#define LN_time_stamp		"Time Stamping"
+#define NID_time_stamp		133
+#define OBJ_time_stamp		OBJ_id_kp,8L
+
+#define SN_OCSP_sign		"OCSPSigning"
+#define LN_OCSP_sign		"OCSP Signing"
+#define NID_OCSP_sign		180
+#define OBJ_OCSP_sign		OBJ_id_kp,9L
+
+#define SN_dvcs		"DVCS"
+#define LN_dvcs		"dvcs"
+#define NID_dvcs		297
+#define OBJ_dvcs		OBJ_id_kp,10L
+
+#define SN_id_it_caProtEncCert		"id-it-caProtEncCert"
+#define NID_id_it_caProtEncCert		298
+#define OBJ_id_it_caProtEncCert		OBJ_id_it,1L
+
+#define SN_id_it_signKeyPairTypes		"id-it-signKeyPairTypes"
+#define NID_id_it_signKeyPairTypes		299
+#define OBJ_id_it_signKeyPairTypes		OBJ_id_it,2L
+
+#define SN_id_it_encKeyPairTypes		"id-it-encKeyPairTypes"
+#define NID_id_it_encKeyPairTypes		300
+#define OBJ_id_it_encKeyPairTypes		OBJ_id_it,3L
+
+#define SN_id_it_preferredSymmAlg		"id-it-preferredSymmAlg"
+#define NID_id_it_preferredSymmAlg		301
+#define OBJ_id_it_preferredSymmAlg		OBJ_id_it,4L
+
+#define SN_id_it_caKeyUpdateInfo		"id-it-caKeyUpdateInfo"
+#define NID_id_it_caKeyUpdateInfo		302
+#define OBJ_id_it_caKeyUpdateInfo		OBJ_id_it,5L
+
+#define SN_id_it_currentCRL		"id-it-currentCRL"
+#define NID_id_it_currentCRL		303
+#define OBJ_id_it_currentCRL		OBJ_id_it,6L
+
+#define SN_id_it_unsupportedOIDs		"id-it-unsupportedOIDs"
+#define NID_id_it_unsupportedOIDs		304
+#define OBJ_id_it_unsupportedOIDs		OBJ_id_it,7L
+
+#define SN_id_it_subscriptionRequest		"id-it-subscriptionRequest"
+#define NID_id_it_subscriptionRequest		305
+#define OBJ_id_it_subscriptionRequest		OBJ_id_it,8L
+
+#define SN_id_it_subscriptionResponse		"id-it-subscriptionResponse"
+#define NID_id_it_subscriptionResponse		306
+#define OBJ_id_it_subscriptionResponse		OBJ_id_it,9L
+
+#define SN_id_it_keyPairParamReq		"id-it-keyPairParamReq"
+#define NID_id_it_keyPairParamReq		307
+#define OBJ_id_it_keyPairParamReq		OBJ_id_it,10L
+
+#define SN_id_it_keyPairParamRep		"id-it-keyPairParamRep"
+#define NID_id_it_keyPairParamRep		308
+#define OBJ_id_it_keyPairParamRep		OBJ_id_it,11L
+
+#define SN_id_it_revPassphrase		"id-it-revPassphrase"
+#define NID_id_it_revPassphrase		309
+#define OBJ_id_it_revPassphrase		OBJ_id_it,12L
+
+#define SN_id_it_implicitConfirm		"id-it-implicitConfirm"
+#define NID_id_it_implicitConfirm		310
+#define OBJ_id_it_implicitConfirm		OBJ_id_it,13L
+
+#define SN_id_it_confirmWaitTime		"id-it-confirmWaitTime"
+#define NID_id_it_confirmWaitTime		311
+#define OBJ_id_it_confirmWaitTime		OBJ_id_it,14L
+
+#define SN_id_it_origPKIMessage		"id-it-origPKIMessage"
+#define NID_id_it_origPKIMessage		312
+#define OBJ_id_it_origPKIMessage		OBJ_id_it,15L
+
+#define SN_id_regCtrl		"id-regCtrl"
+#define NID_id_regCtrl		313
+#define OBJ_id_regCtrl		OBJ_id_pkip,1L
+
+#define SN_id_regInfo		"id-regInfo"
+#define NID_id_regInfo		314
+#define OBJ_id_regInfo		OBJ_id_pkip,2L
+
+#define SN_id_regCtrl_regToken		"id-regCtrl-regToken"
+#define NID_id_regCtrl_regToken		315
+#define OBJ_id_regCtrl_regToken		OBJ_id_regCtrl,1L
+
+#define SN_id_regCtrl_authenticator		"id-regCtrl-authenticator"
+#define NID_id_regCtrl_authenticator		316
+#define OBJ_id_regCtrl_authenticator		OBJ_id_regCtrl,2L
+
+#define SN_id_regCtrl_pkiPublicationInfo		"id-regCtrl-pkiPublicationInfo"
+#define NID_id_regCtrl_pkiPublicationInfo		317
+#define OBJ_id_regCtrl_pkiPublicationInfo		OBJ_id_regCtrl,3L
+
+#define SN_id_regCtrl_pkiArchiveOptions		"id-regCtrl-pkiArchiveOptions"
+#define NID_id_regCtrl_pkiArchiveOptions		318
+#define OBJ_id_regCtrl_pkiArchiveOptions		OBJ_id_regCtrl,4L
+
+#define SN_id_regCtrl_oldCertID		"id-regCtrl-oldCertID"
+#define NID_id_regCtrl_oldCertID		319
+#define OBJ_id_regCtrl_oldCertID		OBJ_id_regCtrl,5L
+
+#define SN_id_regCtrl_protocolEncrKey		"id-regCtrl-protocolEncrKey"
+#define NID_id_regCtrl_protocolEncrKey		320
+#define OBJ_id_regCtrl_protocolEncrKey		OBJ_id_regCtrl,6L
+
+#define SN_id_regInfo_utf8Pairs		"id-regInfo-utf8Pairs"
+#define NID_id_regInfo_utf8Pairs		321
+#define OBJ_id_regInfo_utf8Pairs		OBJ_id_regInfo,1L
+
+#define SN_id_regInfo_certReq		"id-regInfo-certReq"
+#define NID_id_regInfo_certReq		322
+#define OBJ_id_regInfo_certReq		OBJ_id_regInfo,2L
+
+#define SN_id_alg_des40		"id-alg-des40"
+#define NID_id_alg_des40		323
+#define OBJ_id_alg_des40		OBJ_id_alg,1L
+
+#define SN_id_alg_noSignature		"id-alg-noSignature"
+#define NID_id_alg_noSignature		324
+#define OBJ_id_alg_noSignature		OBJ_id_alg,2L
+
+#define SN_id_alg_dh_sig_hmac_sha1		"id-alg-dh-sig-hmac-sha1"
+#define NID_id_alg_dh_sig_hmac_sha1		325
+#define OBJ_id_alg_dh_sig_hmac_sha1		OBJ_id_alg,3L
+
+#define SN_id_alg_dh_pop		"id-alg-dh-pop"
+#define NID_id_alg_dh_pop		326
+#define OBJ_id_alg_dh_pop		OBJ_id_alg,4L
+
+#define SN_id_cmc_statusInfo		"id-cmc-statusInfo"
+#define NID_id_cmc_statusInfo		327
+#define OBJ_id_cmc_statusInfo		OBJ_id_cmc,1L
+
+#define SN_id_cmc_identification		"id-cmc-identification"
+#define NID_id_cmc_identification		328
+#define OBJ_id_cmc_identification		OBJ_id_cmc,2L
+
+#define SN_id_cmc_identityProof		"id-cmc-identityProof"
+#define NID_id_cmc_identityProof		329
+#define OBJ_id_cmc_identityProof		OBJ_id_cmc,3L
+
+#define SN_id_cmc_dataReturn		"id-cmc-dataReturn"
+#define NID_id_cmc_dataReturn		330
+#define OBJ_id_cmc_dataReturn		OBJ_id_cmc,4L
+
+#define SN_id_cmc_transactionId		"id-cmc-transactionId"
+#define NID_id_cmc_transactionId		331
+#define OBJ_id_cmc_transactionId		OBJ_id_cmc,5L
+
+#define SN_id_cmc_senderNonce		"id-cmc-senderNonce"
+#define NID_id_cmc_senderNonce		332
+#define OBJ_id_cmc_senderNonce		OBJ_id_cmc,6L
+
+#define SN_id_cmc_recipientNonce		"id-cmc-recipientNonce"
+#define NID_id_cmc_recipientNonce		333
+#define OBJ_id_cmc_recipientNonce		OBJ_id_cmc,7L
+
+#define SN_id_cmc_addExtensions		"id-cmc-addExtensions"
+#define NID_id_cmc_addExtensions		334
+#define OBJ_id_cmc_addExtensions		OBJ_id_cmc,8L
+
+#define SN_id_cmc_encryptedPOP		"id-cmc-encryptedPOP"
+#define NID_id_cmc_encryptedPOP		335
+#define OBJ_id_cmc_encryptedPOP		OBJ_id_cmc,9L
+
+#define SN_id_cmc_decryptedPOP		"id-cmc-decryptedPOP"
+#define NID_id_cmc_decryptedPOP		336
+#define OBJ_id_cmc_decryptedPOP		OBJ_id_cmc,10L
+
+#define SN_id_cmc_lraPOPWitness		"id-cmc-lraPOPWitness"
+#define NID_id_cmc_lraPOPWitness		337
+#define OBJ_id_cmc_lraPOPWitness		OBJ_id_cmc,11L
+
+#define SN_id_cmc_getCert		"id-cmc-getCert"
+#define NID_id_cmc_getCert		338
+#define OBJ_id_cmc_getCert		OBJ_id_cmc,15L
+
+#define SN_id_cmc_getCRL		"id-cmc-getCRL"
+#define NID_id_cmc_getCRL		339
+#define OBJ_id_cmc_getCRL		OBJ_id_cmc,16L
+
+#define SN_id_cmc_revokeRequest		"id-cmc-revokeRequest"
+#define NID_id_cmc_revokeRequest		340
+#define OBJ_id_cmc_revokeRequest		OBJ_id_cmc,17L
+
+#define SN_id_cmc_regInfo		"id-cmc-regInfo"
+#define NID_id_cmc_regInfo		341
+#define OBJ_id_cmc_regInfo		OBJ_id_cmc,18L
+
+#define SN_id_cmc_responseInfo		"id-cmc-responseInfo"
+#define NID_id_cmc_responseInfo		342
+#define OBJ_id_cmc_responseInfo		OBJ_id_cmc,19L
+
+#define SN_id_cmc_queryPending		"id-cmc-queryPending"
+#define NID_id_cmc_queryPending		343
+#define OBJ_id_cmc_queryPending		OBJ_id_cmc,21L
+
+#define SN_id_cmc_popLinkRandom		"id-cmc-popLinkRandom"
+#define NID_id_cmc_popLinkRandom		344
+#define OBJ_id_cmc_popLinkRandom		OBJ_id_cmc,22L
+
+#define SN_id_cmc_popLinkWitness		"id-cmc-popLinkWitness"
+#define NID_id_cmc_popLinkWitness		345
+#define OBJ_id_cmc_popLinkWitness		OBJ_id_cmc,23L
+
+#define SN_id_cmc_confirmCertAcceptance		"id-cmc-confirmCertAcceptance"
+#define NID_id_cmc_confirmCertAcceptance		346
+#define OBJ_id_cmc_confirmCertAcceptance		OBJ_id_cmc,24L
+
+#define SN_id_on_personalData		"id-on-personalData"
+#define NID_id_on_personalData		347
+#define OBJ_id_on_personalData		OBJ_id_on,1L
+
+#define SN_id_pda_dateOfBirth		"id-pda-dateOfBirth"
+#define NID_id_pda_dateOfBirth		348
+#define OBJ_id_pda_dateOfBirth		OBJ_id_pda,1L
+
+#define SN_id_pda_placeOfBirth		"id-pda-placeOfBirth"
+#define NID_id_pda_placeOfBirth		349
+#define OBJ_id_pda_placeOfBirth		OBJ_id_pda,2L
+
+#define SN_id_pda_gender		"id-pda-gender"
+#define NID_id_pda_gender		351
+#define OBJ_id_pda_gender		OBJ_id_pda,3L
+
+#define SN_id_pda_countryOfCitizenship		"id-pda-countryOfCitizenship"
+#define NID_id_pda_countryOfCitizenship		352
+#define OBJ_id_pda_countryOfCitizenship		OBJ_id_pda,4L
+
+#define SN_id_pda_countryOfResidence		"id-pda-countryOfResidence"
+#define NID_id_pda_countryOfResidence		353
+#define OBJ_id_pda_countryOfResidence		OBJ_id_pda,5L
+
+#define SN_id_aca_authenticationInfo		"id-aca-authenticationInfo"
+#define NID_id_aca_authenticationInfo		354
+#define OBJ_id_aca_authenticationInfo		OBJ_id_aca,1L
+
+#define SN_id_aca_accessIdentity		"id-aca-accessIdentity"
+#define NID_id_aca_accessIdentity		355
+#define OBJ_id_aca_accessIdentity		OBJ_id_aca,2L
+
+#define SN_id_aca_chargingIdentity		"id-aca-chargingIdentity"
+#define NID_id_aca_chargingIdentity		356
+#define OBJ_id_aca_chargingIdentity		OBJ_id_aca,3L
+
+#define SN_id_aca_group		"id-aca-group"
+#define NID_id_aca_group		357
+#define OBJ_id_aca_group		OBJ_id_aca,4L
+
+#define SN_id_aca_role		"id-aca-role"
+#define NID_id_aca_role		358
+#define OBJ_id_aca_role		OBJ_id_aca,5L
+
+#define SN_id_aca_encAttrs		"id-aca-encAttrs"
+#define NID_id_aca_encAttrs		399
+#define OBJ_id_aca_encAttrs		OBJ_id_aca,6L
+
+#define SN_id_qcs_pkixQCSyntax_v1		"id-qcs-pkixQCSyntax-v1"
+#define NID_id_qcs_pkixQCSyntax_v1		359
+#define OBJ_id_qcs_pkixQCSyntax_v1		OBJ_id_qcs,1L
+
+#define SN_id_cct_crs		"id-cct-crs"
+#define NID_id_cct_crs		360
+#define OBJ_id_cct_crs		OBJ_id_cct,1L
+
+#define SN_id_cct_PKIData		"id-cct-PKIData"
+#define NID_id_cct_PKIData		361
+#define OBJ_id_cct_PKIData		OBJ_id_cct,2L
+
+#define SN_id_cct_PKIResponse		"id-cct-PKIResponse"
+#define NID_id_cct_PKIResponse		362
+#define OBJ_id_cct_PKIResponse		OBJ_id_cct,3L
+
+#define SN_id_ppl_anyLanguage		"id-ppl-anyLanguage"
+#define LN_id_ppl_anyLanguage		"Any language"
+#define NID_id_ppl_anyLanguage		664
+#define OBJ_id_ppl_anyLanguage		OBJ_id_ppl,0L
+
+#define SN_id_ppl_inheritAll		"id-ppl-inheritAll"
+#define LN_id_ppl_inheritAll		"Inherit all"
+#define NID_id_ppl_inheritAll		665
+#define OBJ_id_ppl_inheritAll		OBJ_id_ppl,1L
+
+#define SN_Independent		"id-ppl-independent"
+#define LN_Independent		"Independent"
+#define NID_Independent		667
+#define OBJ_Independent		OBJ_id_ppl,2L
+
+#define SN_ad_OCSP		"OCSP"
+#define LN_ad_OCSP		"OCSP"
+#define NID_ad_OCSP		178
+#define OBJ_ad_OCSP		OBJ_id_ad,1L
+
+#define SN_ad_ca_issuers		"caIssuers"
+#define LN_ad_ca_issuers		"CA Issuers"
+#define NID_ad_ca_issuers		179
+#define OBJ_ad_ca_issuers		OBJ_id_ad,2L
+
+#define SN_ad_timeStamping		"ad_timestamping"
+#define LN_ad_timeStamping		"AD Time Stamping"
+#define NID_ad_timeStamping		363
+#define OBJ_ad_timeStamping		OBJ_id_ad,3L
+
+#define SN_ad_dvcs		"AD_DVCS"
+#define LN_ad_dvcs		"ad dvcs"
+#define NID_ad_dvcs		364
+#define OBJ_ad_dvcs		OBJ_id_ad,4L
+
+#define OBJ_id_pkix_OCSP		OBJ_ad_OCSP
+
+#define SN_id_pkix_OCSP_basic		"basicOCSPResponse"
+#define LN_id_pkix_OCSP_basic		"Basic OCSP Response"
+#define NID_id_pkix_OCSP_basic		365
+#define OBJ_id_pkix_OCSP_basic		OBJ_id_pkix_OCSP,1L
+
+#define SN_id_pkix_OCSP_Nonce		"Nonce"
+#define LN_id_pkix_OCSP_Nonce		"OCSP Nonce"
+#define NID_id_pkix_OCSP_Nonce		366
+#define OBJ_id_pkix_OCSP_Nonce		OBJ_id_pkix_OCSP,2L
+
+#define SN_id_pkix_OCSP_CrlID		"CrlID"
+#define LN_id_pkix_OCSP_CrlID		"OCSP CRL ID"
+#define NID_id_pkix_OCSP_CrlID		367
+#define OBJ_id_pkix_OCSP_CrlID		OBJ_id_pkix_OCSP,3L
+
+#define SN_id_pkix_OCSP_acceptableResponses		"acceptableResponses"
+#define LN_id_pkix_OCSP_acceptableResponses		"Acceptable OCSP Responses"
+#define NID_id_pkix_OCSP_acceptableResponses		368
+#define OBJ_id_pkix_OCSP_acceptableResponses		OBJ_id_pkix_OCSP,4L
+
+#define SN_id_pkix_OCSP_noCheck		"noCheck"
+#define LN_id_pkix_OCSP_noCheck		"OCSP No Check"
+#define NID_id_pkix_OCSP_noCheck		369
+#define OBJ_id_pkix_OCSP_noCheck		OBJ_id_pkix_OCSP,5L
+
+#define SN_id_pkix_OCSP_archiveCutoff		"archiveCutoff"
+#define LN_id_pkix_OCSP_archiveCutoff		"OCSP Archive Cutoff"
+#define NID_id_pkix_OCSP_archiveCutoff		370
+#define OBJ_id_pkix_OCSP_archiveCutoff		OBJ_id_pkix_OCSP,6L
+
+#define SN_id_pkix_OCSP_serviceLocator		"serviceLocator"
+#define LN_id_pkix_OCSP_serviceLocator		"OCSP Service Locator"
+#define NID_id_pkix_OCSP_serviceLocator		371
+#define OBJ_id_pkix_OCSP_serviceLocator		OBJ_id_pkix_OCSP,7L
+
+#define SN_id_pkix_OCSP_extendedStatus		"extendedStatus"
+#define LN_id_pkix_OCSP_extendedStatus		"Extended OCSP Status"
+#define NID_id_pkix_OCSP_extendedStatus		372
+#define OBJ_id_pkix_OCSP_extendedStatus		OBJ_id_pkix_OCSP,8L
+
+#define SN_id_pkix_OCSP_valid		"valid"
+#define NID_id_pkix_OCSP_valid		373
+#define OBJ_id_pkix_OCSP_valid		OBJ_id_pkix_OCSP,9L
+
+#define SN_id_pkix_OCSP_path		"path"
+#define NID_id_pkix_OCSP_path		374
+#define OBJ_id_pkix_OCSP_path		OBJ_id_pkix_OCSP,10L
+
+#define SN_id_pkix_OCSP_trustRoot		"trustRoot"
+#define LN_id_pkix_OCSP_trustRoot		"Trust Root"
+#define NID_id_pkix_OCSP_trustRoot		375
+#define OBJ_id_pkix_OCSP_trustRoot		OBJ_id_pkix_OCSP,11L
+
+#define SN_algorithm		"algorithm"
+#define LN_algorithm		"algorithm"
+#define NID_algorithm		376
+#define OBJ_algorithm		1L,3L,14L,3L,2L
+
+#define SN_md5WithRSA		"RSA-NP-MD5"
+#define LN_md5WithRSA		"md5WithRSA"
+#define NID_md5WithRSA		104
+#define OBJ_md5WithRSA		OBJ_algorithm,3L
+
+#define SN_des_ecb		"DES-ECB"
+#define LN_des_ecb		"des-ecb"
+#define NID_des_ecb		29
+#define OBJ_des_ecb		OBJ_algorithm,6L
+
+#define SN_des_cbc		"DES-CBC"
+#define LN_des_cbc		"des-cbc"
+#define NID_des_cbc		31
+#define OBJ_des_cbc		OBJ_algorithm,7L
+
+#define SN_des_ofb64		"DES-OFB"
+#define LN_des_ofb64		"des-ofb"
+#define NID_des_ofb64		45
+#define OBJ_des_ofb64		OBJ_algorithm,8L
+
+#define SN_des_cfb64		"DES-CFB"
+#define LN_des_cfb64		"des-cfb"
+#define NID_des_cfb64		30
+#define OBJ_des_cfb64		OBJ_algorithm,9L
+
+#define SN_rsaSignature		"rsaSignature"
+#define NID_rsaSignature		377
+#define OBJ_rsaSignature		OBJ_algorithm,11L
+
+#define SN_dsa_2		"DSA-old"
+#define LN_dsa_2		"dsaEncryption-old"
+#define NID_dsa_2		67
+#define OBJ_dsa_2		OBJ_algorithm,12L
+
+#define SN_dsaWithSHA		"DSA-SHA"
+#define LN_dsaWithSHA		"dsaWithSHA"
+#define NID_dsaWithSHA		66
+#define OBJ_dsaWithSHA		OBJ_algorithm,13L
+
+#define SN_shaWithRSAEncryption		"RSA-SHA"
+#define LN_shaWithRSAEncryption		"shaWithRSAEncryption"
+#define NID_shaWithRSAEncryption		42
+#define OBJ_shaWithRSAEncryption		OBJ_algorithm,15L
+
+#define SN_des_ede_ecb		"DES-EDE"
+#define LN_des_ede_ecb		"des-ede"
+#define NID_des_ede_ecb		32
+#define OBJ_des_ede_ecb		OBJ_algorithm,17L
+
+#define SN_des_ede3_ecb		"DES-EDE3"
+#define LN_des_ede3_ecb		"des-ede3"
+#define NID_des_ede3_ecb		33
+
+#define SN_des_ede_cbc		"DES-EDE-CBC"
+#define LN_des_ede_cbc		"des-ede-cbc"
+#define NID_des_ede_cbc		43
+
+#define SN_des_ede_cfb64		"DES-EDE-CFB"
+#define LN_des_ede_cfb64		"des-ede-cfb"
+#define NID_des_ede_cfb64		60
+
+#define SN_des_ede3_cfb64		"DES-EDE3-CFB"
+#define LN_des_ede3_cfb64		"des-ede3-cfb"
+#define NID_des_ede3_cfb64		61
+
+#define SN_des_ede_ofb64		"DES-EDE-OFB"
+#define LN_des_ede_ofb64		"des-ede-ofb"
+#define NID_des_ede_ofb64		62
+
+#define SN_des_ede3_ofb64		"DES-EDE3-OFB"
+#define LN_des_ede3_ofb64		"des-ede3-ofb"
+#define NID_des_ede3_ofb64		63
+
+#define SN_desx_cbc		"DESX-CBC"
+#define LN_desx_cbc		"desx-cbc"
+#define NID_desx_cbc		80
+
+#define SN_sha		"SHA"
+#define LN_sha		"sha"
+#define NID_sha		41
+#define OBJ_sha		OBJ_algorithm,18L
+
+#define SN_sha1		"SHA1"
+#define LN_sha1		"sha1"
+#define NID_sha1		64
+#define OBJ_sha1		OBJ_algorithm,26L
+
+#define SN_dsaWithSHA1_2		"DSA-SHA1-old"
+#define LN_dsaWithSHA1_2		"dsaWithSHA1-old"
+#define NID_dsaWithSHA1_2		70
+#define OBJ_dsaWithSHA1_2		OBJ_algorithm,27L
+
+#define SN_sha1WithRSA		"RSA-SHA1-2"
+#define LN_sha1WithRSA		"sha1WithRSA"
+#define NID_sha1WithRSA		115
+#define OBJ_sha1WithRSA		OBJ_algorithm,29L
+
+#define SN_ripemd160		"RIPEMD160"
+#define LN_ripemd160		"ripemd160"
+#define NID_ripemd160		117
+#define OBJ_ripemd160		1L,3L,36L,3L,2L,1L
+
+#define SN_ripemd160WithRSA		"RSA-RIPEMD160"
+#define LN_ripemd160WithRSA		"ripemd160WithRSA"
+#define NID_ripemd160WithRSA		119
+#define OBJ_ripemd160WithRSA		1L,3L,36L,3L,3L,1L,2L
+
+#define SN_sxnet		"SXNetID"
+#define LN_sxnet		"Strong Extranet ID"
+#define NID_sxnet		143
+#define OBJ_sxnet		1L,3L,101L,1L,4L,1L
+
+#define SN_X500		"X500"
+#define LN_X500		"directory services (X.500)"
+#define NID_X500		11
+#define OBJ_X500		2L,5L
+
+#define SN_X509		"X509"
+#define NID_X509		12
+#define OBJ_X509		OBJ_X500,4L
+
+#define SN_commonName		"CN"
+#define LN_commonName		"commonName"
+#define NID_commonName		13
+#define OBJ_commonName		OBJ_X509,3L
+
+#define SN_surname		"SN"
+#define LN_surname		"surname"
+#define NID_surname		100
+#define OBJ_surname		OBJ_X509,4L
+
+#define LN_serialNumber		"serialNumber"
+#define NID_serialNumber		105
+#define OBJ_serialNumber		OBJ_X509,5L
+
+#define SN_countryName		"C"
+#define LN_countryName		"countryName"
+#define NID_countryName		14
+#define OBJ_countryName		OBJ_X509,6L
+
+#define SN_localityName		"L"
+#define LN_localityName		"localityName"
+#define NID_localityName		15
+#define OBJ_localityName		OBJ_X509,7L
+
+#define SN_stateOrProvinceName		"ST"
+#define LN_stateOrProvinceName		"stateOrProvinceName"
+#define NID_stateOrProvinceName		16
+#define OBJ_stateOrProvinceName		OBJ_X509,8L
+
+#define LN_streetAddress		"streetAddress"
+#define NID_streetAddress		660
+#define OBJ_streetAddress		OBJ_X509,9L
+
+#define SN_organizationName		"O"
+#define LN_organizationName		"organizationName"
+#define NID_organizationName		17
+#define OBJ_organizationName		OBJ_X509,10L
+
+#define SN_organizationalUnitName		"OU"
+#define LN_organizationalUnitName		"organizationalUnitName"
+#define NID_organizationalUnitName		18
+#define OBJ_organizationalUnitName		OBJ_X509,11L
+
+#define LN_title		"title"
+#define NID_title		106
+#define OBJ_title		OBJ_X509,12L
+
+#define LN_description		"description"
+#define NID_description		107
+#define OBJ_description		OBJ_X509,13L
+
+#define LN_postalCode		"postalCode"
+#define NID_postalCode		661
+#define OBJ_postalCode		OBJ_X509,17L
+
+#define SN_name		"name"
+#define LN_name		"name"
+#define NID_name		173
+#define OBJ_name		OBJ_X509,41L
+
+#define SN_givenName		"GN"
+#define LN_givenName		"givenName"
+#define NID_givenName		99
+#define OBJ_givenName		OBJ_X509,42L
+
+#define LN_initials		"initials"
+#define NID_initials		101
+#define OBJ_initials		OBJ_X509,43L
+
+#define LN_generationQualifier		"generationQualifier"
+#define NID_generationQualifier		509
+#define OBJ_generationQualifier		OBJ_X509,44L
+
+#define LN_x500UniqueIdentifier		"x500UniqueIdentifier"
+#define NID_x500UniqueIdentifier		503
+#define OBJ_x500UniqueIdentifier		OBJ_X509,45L
+
+#define SN_dnQualifier		"dnQualifier"
+#define LN_dnQualifier		"dnQualifier"
+#define NID_dnQualifier		174
+#define OBJ_dnQualifier		OBJ_X509,46L
+
+#define LN_pseudonym		"pseudonym"
+#define NID_pseudonym		510
+#define OBJ_pseudonym		OBJ_X509,65L
+
+#define SN_role		"role"
+#define LN_role		"role"
+#define NID_role		400
+#define OBJ_role		OBJ_X509,72L
+
+#define SN_X500algorithms		"X500algorithms"
+#define LN_X500algorithms		"directory services - algorithms"
+#define NID_X500algorithms		378
+#define OBJ_X500algorithms		OBJ_X500,8L
+
+#define SN_rsa		"RSA"
+#define LN_rsa		"rsa"
+#define NID_rsa		19
+#define OBJ_rsa		OBJ_X500algorithms,1L,1L
+
+#define SN_mdc2WithRSA		"RSA-MDC2"
+#define LN_mdc2WithRSA		"mdc2WithRSA"
+#define NID_mdc2WithRSA		96
+#define OBJ_mdc2WithRSA		OBJ_X500algorithms,3L,100L
+
+#define SN_mdc2		"MDC2"
+#define LN_mdc2		"mdc2"
+#define NID_mdc2		95
+#define OBJ_mdc2		OBJ_X500algorithms,3L,101L
+
+#define SN_id_ce		"id-ce"
+#define NID_id_ce		81
+#define OBJ_id_ce		OBJ_X500,29L
+
+#define SN_subject_directory_attributes		"subjectDirectoryAttributes"
+#define LN_subject_directory_attributes		"X509v3 Subject Directory Attributes"
+#define NID_subject_directory_attributes		769
+#define OBJ_subject_directory_attributes		OBJ_id_ce,9L
+
+#define SN_subject_key_identifier		"subjectKeyIdentifier"
+#define LN_subject_key_identifier		"X509v3 Subject Key Identifier"
+#define NID_subject_key_identifier		82
+#define OBJ_subject_key_identifier		OBJ_id_ce,14L
+
+#define SN_key_usage		"keyUsage"
+#define LN_key_usage		"X509v3 Key Usage"
+#define NID_key_usage		83
+#define OBJ_key_usage		OBJ_id_ce,15L
+
+#define SN_private_key_usage_period		"privateKeyUsagePeriod"
+#define LN_private_key_usage_period		"X509v3 Private Key Usage Period"
+#define NID_private_key_usage_period		84
+#define OBJ_private_key_usage_period		OBJ_id_ce,16L
+
+#define SN_subject_alt_name		"subjectAltName"
+#define LN_subject_alt_name		"X509v3 Subject Alternative Name"
+#define NID_subject_alt_name		85
+#define OBJ_subject_alt_name		OBJ_id_ce,17L
+
+#define SN_issuer_alt_name		"issuerAltName"
+#define LN_issuer_alt_name		"X509v3 Issuer Alternative Name"
+#define NID_issuer_alt_name		86
+#define OBJ_issuer_alt_name		OBJ_id_ce,18L
+
+#define SN_basic_constraints		"basicConstraints"
+#define LN_basic_constraints		"X509v3 Basic Constraints"
+#define NID_basic_constraints		87
+#define OBJ_basic_constraints		OBJ_id_ce,19L
+
+#define SN_crl_number		"crlNumber"
+#define LN_crl_number		"X509v3 CRL Number"
+#define NID_crl_number		88
+#define OBJ_crl_number		OBJ_id_ce,20L
+
+#define SN_crl_reason		"CRLReason"
+#define LN_crl_reason		"X509v3 CRL Reason Code"
+#define NID_crl_reason		141
+#define OBJ_crl_reason		OBJ_id_ce,21L
+
+#define SN_invalidity_date		"invalidityDate"
+#define LN_invalidity_date		"Invalidity Date"
+#define NID_invalidity_date		142
+#define OBJ_invalidity_date		OBJ_id_ce,24L
+
+#define SN_delta_crl		"deltaCRL"
+#define LN_delta_crl		"X509v3 Delta CRL Indicator"
+#define NID_delta_crl		140
+#define OBJ_delta_crl		OBJ_id_ce,27L
+
+#define SN_issuing_distribution_point		"issuingDistributionPoint"
+#define LN_issuing_distribution_point		"X509v3 Issuing Distrubution Point"
+#define NID_issuing_distribution_point		770
+#define OBJ_issuing_distribution_point		OBJ_id_ce,28L
+
+#define SN_certificate_issuer		"certificateIssuer"
+#define LN_certificate_issuer		"X509v3 Certificate Issuer"
+#define NID_certificate_issuer		771
+#define OBJ_certificate_issuer		OBJ_id_ce,29L
+
+#define SN_name_constraints		"nameConstraints"
+#define LN_name_constraints		"X509v3 Name Constraints"
+#define NID_name_constraints		666
+#define OBJ_name_constraints		OBJ_id_ce,30L
+
+#define SN_crl_distribution_points		"crlDistributionPoints"
+#define LN_crl_distribution_points		"X509v3 CRL Distribution Points"
+#define NID_crl_distribution_points		103
+#define OBJ_crl_distribution_points		OBJ_id_ce,31L
+
+#define SN_certificate_policies		"certificatePolicies"
+#define LN_certificate_policies		"X509v3 Certificate Policies"
+#define NID_certificate_policies		89
+#define OBJ_certificate_policies		OBJ_id_ce,32L
+
+#define SN_any_policy		"anyPolicy"
+#define LN_any_policy		"X509v3 Any Policy"
+#define NID_any_policy		746
+#define OBJ_any_policy		OBJ_certificate_policies,0L
+
+#define SN_policy_mappings		"policyMappings"
+#define LN_policy_mappings		"X509v3 Policy Mappings"
+#define NID_policy_mappings		747
+#define OBJ_policy_mappings		OBJ_id_ce,33L
+
+#define SN_authority_key_identifier		"authorityKeyIdentifier"
+#define LN_authority_key_identifier		"X509v3 Authority Key Identifier"
+#define NID_authority_key_identifier		90
+#define OBJ_authority_key_identifier		OBJ_id_ce,35L
+
+#define SN_policy_constraints		"policyConstraints"
+#define LN_policy_constraints		"X509v3 Policy Constraints"
+#define NID_policy_constraints		401
+#define OBJ_policy_constraints		OBJ_id_ce,36L
+
+#define SN_ext_key_usage		"extendedKeyUsage"
+#define LN_ext_key_usage		"X509v3 Extended Key Usage"
+#define NID_ext_key_usage		126
+#define OBJ_ext_key_usage		OBJ_id_ce,37L
+
+#define SN_inhibit_any_policy		"inhibitAnyPolicy"
+#define LN_inhibit_any_policy		"X509v3 Inhibit Any Policy"
+#define NID_inhibit_any_policy		748
+#define OBJ_inhibit_any_policy		OBJ_id_ce,54L
+
+#define SN_target_information		"targetInformation"
+#define LN_target_information		"X509v3 AC Targeting"
+#define NID_target_information		402
+#define OBJ_target_information		OBJ_id_ce,55L
+
+#define SN_no_rev_avail		"noRevAvail"
+#define LN_no_rev_avail		"X509v3 No Revocation Available"
+#define NID_no_rev_avail		403
+#define OBJ_no_rev_avail		OBJ_id_ce,56L
+
+#define SN_netscape		"Netscape"
+#define LN_netscape		"Netscape Communications Corp."
+#define NID_netscape		57
+#define OBJ_netscape		2L,16L,840L,1L,113730L
+
+#define SN_netscape_cert_extension		"nsCertExt"
+#define LN_netscape_cert_extension		"Netscape Certificate Extension"
+#define NID_netscape_cert_extension		58
+#define OBJ_netscape_cert_extension		OBJ_netscape,1L
+
+#define SN_netscape_data_type		"nsDataType"
+#define LN_netscape_data_type		"Netscape Data Type"
+#define NID_netscape_data_type		59
+#define OBJ_netscape_data_type		OBJ_netscape,2L
+
+#define SN_netscape_cert_type		"nsCertType"
+#define LN_netscape_cert_type		"Netscape Cert Type"
+#define NID_netscape_cert_type		71
+#define OBJ_netscape_cert_type		OBJ_netscape_cert_extension,1L
+
+#define SN_netscape_base_url		"nsBaseUrl"
+#define LN_netscape_base_url		"Netscape Base Url"
+#define NID_netscape_base_url		72
+#define OBJ_netscape_base_url		OBJ_netscape_cert_extension,2L
+
+#define SN_netscape_revocation_url		"nsRevocationUrl"
+#define LN_netscape_revocation_url		"Netscape Revocation Url"
+#define NID_netscape_revocation_url		73
+#define OBJ_netscape_revocation_url		OBJ_netscape_cert_extension,3L
+
+#define SN_netscape_ca_revocation_url		"nsCaRevocationUrl"
+#define LN_netscape_ca_revocation_url		"Netscape CA Revocation Url"
+#define NID_netscape_ca_revocation_url		74
+#define OBJ_netscape_ca_revocation_url		OBJ_netscape_cert_extension,4L
+
+#define SN_netscape_renewal_url		"nsRenewalUrl"
+#define LN_netscape_renewal_url		"Netscape Renewal Url"
+#define NID_netscape_renewal_url		75
+#define OBJ_netscape_renewal_url		OBJ_netscape_cert_extension,7L
+
+#define SN_netscape_ca_policy_url		"nsCaPolicyUrl"
+#define LN_netscape_ca_policy_url		"Netscape CA Policy Url"
+#define NID_netscape_ca_policy_url		76
+#define OBJ_netscape_ca_policy_url		OBJ_netscape_cert_extension,8L
+
+#define SN_netscape_ssl_server_name		"nsSslServerName"
+#define LN_netscape_ssl_server_name		"Netscape SSL Server Name"
+#define NID_netscape_ssl_server_name		77
+#define OBJ_netscape_ssl_server_name		OBJ_netscape_cert_extension,12L
+
+#define SN_netscape_comment		"nsComment"
+#define LN_netscape_comment		"Netscape Comment"
+#define NID_netscape_comment		78
+#define OBJ_netscape_comment		OBJ_netscape_cert_extension,13L
+
+#define SN_netscape_cert_sequence		"nsCertSequence"
+#define LN_netscape_cert_sequence		"Netscape Certificate Sequence"
+#define NID_netscape_cert_sequence		79
+#define OBJ_netscape_cert_sequence		OBJ_netscape_data_type,5L
+
+#define SN_ns_sgc		"nsSGC"
+#define LN_ns_sgc		"Netscape Server Gated Crypto"
+#define NID_ns_sgc		139
+#define OBJ_ns_sgc		OBJ_netscape,4L,1L
+
+#define SN_org		"ORG"
+#define LN_org		"org"
+#define NID_org		379
+#define OBJ_org		OBJ_iso,3L
+
+#define SN_dod		"DOD"
+#define LN_dod		"dod"
+#define NID_dod		380
+#define OBJ_dod		OBJ_org,6L
+
+#define SN_iana		"IANA"
+#define LN_iana		"iana"
+#define NID_iana		381
+#define OBJ_iana		OBJ_dod,1L
+
+#define OBJ_internet		OBJ_iana
+
+#define SN_Directory		"directory"
+#define LN_Directory		"Directory"
+#define NID_Directory		382
+#define OBJ_Directory		OBJ_internet,1L
+
+#define SN_Management		"mgmt"
+#define LN_Management		"Management"
+#define NID_Management		383
+#define OBJ_Management		OBJ_internet,2L
+
+#define SN_Experimental		"experimental"
+#define LN_Experimental		"Experimental"
+#define NID_Experimental		384
+#define OBJ_Experimental		OBJ_internet,3L
+
+#define SN_Private		"private"
+#define LN_Private		"Private"
+#define NID_Private		385
+#define OBJ_Private		OBJ_internet,4L
+
+#define SN_Security		"security"
+#define LN_Security		"Security"
+#define NID_Security		386
+#define OBJ_Security		OBJ_internet,5L
+
+#define SN_SNMPv2		"snmpv2"
+#define LN_SNMPv2		"SNMPv2"
+#define NID_SNMPv2		387
+#define OBJ_SNMPv2		OBJ_internet,6L
+
+#define LN_Mail		"Mail"
+#define NID_Mail		388
+#define OBJ_Mail		OBJ_internet,7L
+
+#define SN_Enterprises		"enterprises"
+#define LN_Enterprises		"Enterprises"
+#define NID_Enterprises		389
+#define OBJ_Enterprises		OBJ_Private,1L
+
+#define SN_dcObject		"dcobject"
+#define LN_dcObject		"dcObject"
+#define NID_dcObject		390
+#define OBJ_dcObject		OBJ_Enterprises,1466L,344L
+
+#define SN_mime_mhs		"mime-mhs"
+#define LN_mime_mhs		"MIME MHS"
+#define NID_mime_mhs		504
+#define OBJ_mime_mhs		OBJ_Mail,1L
+
+#define SN_mime_mhs_headings		"mime-mhs-headings"
+#define LN_mime_mhs_headings		"mime-mhs-headings"
+#define NID_mime_mhs_headings		505
+#define OBJ_mime_mhs_headings		OBJ_mime_mhs,1L
+
+#define SN_mime_mhs_bodies		"mime-mhs-bodies"
+#define LN_mime_mhs_bodies		"mime-mhs-bodies"
+#define NID_mime_mhs_bodies		506
+#define OBJ_mime_mhs_bodies		OBJ_mime_mhs,2L
+
+#define SN_id_hex_partial_message		"id-hex-partial-message"
+#define LN_id_hex_partial_message		"id-hex-partial-message"
+#define NID_id_hex_partial_message		507
+#define OBJ_id_hex_partial_message		OBJ_mime_mhs_headings,1L
+
+#define SN_id_hex_multipart_message		"id-hex-multipart-message"
+#define LN_id_hex_multipart_message		"id-hex-multipart-message"
+#define NID_id_hex_multipart_message		508
+#define OBJ_id_hex_multipart_message		OBJ_mime_mhs_headings,2L
+
+#define SN_rle_compression		"RLE"
+#define LN_rle_compression		"run length compression"
+#define NID_rle_compression		124
+#define OBJ_rle_compression		1L,1L,1L,1L,666L,1L
+
+#define SN_zlib_compression		"ZLIB"
+#define LN_zlib_compression		"zlib compression"
+#define NID_zlib_compression		125
+#define OBJ_zlib_compression		1L,1L,1L,1L,666L,2L
+
+#define OBJ_csor		2L,16L,840L,1L,101L,3L
+
+#define OBJ_nistAlgorithms		OBJ_csor,4L
+
+#define OBJ_aes		OBJ_nistAlgorithms,1L
+
+#define SN_aes_128_ecb		"AES-128-ECB"
+#define LN_aes_128_ecb		"aes-128-ecb"
+#define NID_aes_128_ecb		418
+#define OBJ_aes_128_ecb		OBJ_aes,1L
+
+#define SN_aes_128_cbc		"AES-128-CBC"
+#define LN_aes_128_cbc		"aes-128-cbc"
+#define NID_aes_128_cbc		419
+#define OBJ_aes_128_cbc		OBJ_aes,2L
+
+#define SN_aes_128_ofb128		"AES-128-OFB"
+#define LN_aes_128_ofb128		"aes-128-ofb"
+#define NID_aes_128_ofb128		420
+#define OBJ_aes_128_ofb128		OBJ_aes,3L
+
+#define SN_aes_128_cfb128		"AES-128-CFB"
+#define LN_aes_128_cfb128		"aes-128-cfb"
+#define NID_aes_128_cfb128		421
+#define OBJ_aes_128_cfb128		OBJ_aes,4L
+
+#define SN_aes_192_ecb		"AES-192-ECB"
+#define LN_aes_192_ecb		"aes-192-ecb"
+#define NID_aes_192_ecb		422
+#define OBJ_aes_192_ecb		OBJ_aes,21L
+
+#define SN_aes_192_cbc		"AES-192-CBC"
+#define LN_aes_192_cbc		"aes-192-cbc"
+#define NID_aes_192_cbc		423
+#define OBJ_aes_192_cbc		OBJ_aes,22L
+
+#define SN_aes_192_ofb128		"AES-192-OFB"
+#define LN_aes_192_ofb128		"aes-192-ofb"
+#define NID_aes_192_ofb128		424
+#define OBJ_aes_192_ofb128		OBJ_aes,23L
+
+#define SN_aes_192_cfb128		"AES-192-CFB"
+#define LN_aes_192_cfb128		"aes-192-cfb"
+#define NID_aes_192_cfb128		425
+#define OBJ_aes_192_cfb128		OBJ_aes,24L
+
+#define SN_aes_256_ecb		"AES-256-ECB"
+#define LN_aes_256_ecb		"aes-256-ecb"
+#define NID_aes_256_ecb		426
+#define OBJ_aes_256_ecb		OBJ_aes,41L
+
+#define SN_aes_256_cbc		"AES-256-CBC"
+#define LN_aes_256_cbc		"aes-256-cbc"
+#define NID_aes_256_cbc		427
+#define OBJ_aes_256_cbc		OBJ_aes,42L
+
+#define SN_aes_256_ofb128		"AES-256-OFB"
+#define LN_aes_256_ofb128		"aes-256-ofb"
+#define NID_aes_256_ofb128		428
+#define OBJ_aes_256_ofb128		OBJ_aes,43L
+
+#define SN_aes_256_cfb128		"AES-256-CFB"
+#define LN_aes_256_cfb128		"aes-256-cfb"
+#define NID_aes_256_cfb128		429
+#define OBJ_aes_256_cfb128		OBJ_aes,44L
+
+#define SN_aes_128_cfb1		"AES-128-CFB1"
+#define LN_aes_128_cfb1		"aes-128-cfb1"
+#define NID_aes_128_cfb1		650
+
+#define SN_aes_192_cfb1		"AES-192-CFB1"
+#define LN_aes_192_cfb1		"aes-192-cfb1"
+#define NID_aes_192_cfb1		651
+
+#define SN_aes_256_cfb1		"AES-256-CFB1"
+#define LN_aes_256_cfb1		"aes-256-cfb1"
+#define NID_aes_256_cfb1		652
+
+#define SN_aes_128_cfb8		"AES-128-CFB8"
+#define LN_aes_128_cfb8		"aes-128-cfb8"
+#define NID_aes_128_cfb8		653
+
+#define SN_aes_192_cfb8		"AES-192-CFB8"
+#define LN_aes_192_cfb8		"aes-192-cfb8"
+#define NID_aes_192_cfb8		654
+
+#define SN_aes_256_cfb8		"AES-256-CFB8"
+#define LN_aes_256_cfb8		"aes-256-cfb8"
+#define NID_aes_256_cfb8		655
+
+#define SN_des_cfb1		"DES-CFB1"
+#define LN_des_cfb1		"des-cfb1"
+#define NID_des_cfb1		656
+
+#define SN_des_cfb8		"DES-CFB8"
+#define LN_des_cfb8		"des-cfb8"
+#define NID_des_cfb8		657
+
+#define SN_des_ede3_cfb1		"DES-EDE3-CFB1"
+#define LN_des_ede3_cfb1		"des-ede3-cfb1"
+#define NID_des_ede3_cfb1		658
+
+#define SN_des_ede3_cfb8		"DES-EDE3-CFB8"
+#define LN_des_ede3_cfb8		"des-ede3-cfb8"
+#define NID_des_ede3_cfb8		659
+
+#define OBJ_nist_hashalgs		OBJ_nistAlgorithms,2L
+
+#define SN_sha256		"SHA256"
+#define LN_sha256		"sha256"
+#define NID_sha256		672
+#define OBJ_sha256		OBJ_nist_hashalgs,1L
+
+#define SN_sha384		"SHA384"
+#define LN_sha384		"sha384"
+#define NID_sha384		673
+#define OBJ_sha384		OBJ_nist_hashalgs,2L
+
+#define SN_sha512		"SHA512"
+#define LN_sha512		"sha512"
+#define NID_sha512		674
+#define OBJ_sha512		OBJ_nist_hashalgs,3L
+
+#define SN_sha224		"SHA224"
+#define LN_sha224		"sha224"
+#define NID_sha224		675
+#define OBJ_sha224		OBJ_nist_hashalgs,4L
+
+#define SN_hold_instruction_code		"holdInstructionCode"
+#define LN_hold_instruction_code		"Hold Instruction Code"
+#define NID_hold_instruction_code		430
+#define OBJ_hold_instruction_code		OBJ_id_ce,23L
+
+#define OBJ_holdInstruction		OBJ_X9_57,2L
+
+#define SN_hold_instruction_none		"holdInstructionNone"
+#define LN_hold_instruction_none		"Hold Instruction None"
+#define NID_hold_instruction_none		431
+#define OBJ_hold_instruction_none		OBJ_holdInstruction,1L
+
+#define SN_hold_instruction_call_issuer		"holdInstructionCallIssuer"
+#define LN_hold_instruction_call_issuer		"Hold Instruction Call Issuer"
+#define NID_hold_instruction_call_issuer		432
+#define OBJ_hold_instruction_call_issuer		OBJ_holdInstruction,2L
+
+#define SN_hold_instruction_reject		"holdInstructionReject"
+#define LN_hold_instruction_reject		"Hold Instruction Reject"
+#define NID_hold_instruction_reject		433
+#define OBJ_hold_instruction_reject		OBJ_holdInstruction,3L
+
+#define SN_data		"data"
+#define NID_data		434
+#define OBJ_data		OBJ_itu_t,9L
+
+#define SN_pss		"pss"
+#define NID_pss		435
+#define OBJ_pss		OBJ_data,2342L
+
+#define SN_ucl		"ucl"
+#define NID_ucl		436
+#define OBJ_ucl		OBJ_pss,19200300L
+
+#define SN_pilot		"pilot"
+#define NID_pilot		437
+#define OBJ_pilot		OBJ_ucl,100L
+
+#define LN_pilotAttributeType		"pilotAttributeType"
+#define NID_pilotAttributeType		438
+#define OBJ_pilotAttributeType		OBJ_pilot,1L
+
+#define LN_pilotAttributeSyntax		"pilotAttributeSyntax"
+#define NID_pilotAttributeSyntax		439
+#define OBJ_pilotAttributeSyntax		OBJ_pilot,3L
+
+#define LN_pilotObjectClass		"pilotObjectClass"
+#define NID_pilotObjectClass		440
+#define OBJ_pilotObjectClass		OBJ_pilot,4L
+
+#define LN_pilotGroups		"pilotGroups"
+#define NID_pilotGroups		441
+#define OBJ_pilotGroups		OBJ_pilot,10L
+
+#define LN_iA5StringSyntax		"iA5StringSyntax"
+#define NID_iA5StringSyntax		442
+#define OBJ_iA5StringSyntax		OBJ_pilotAttributeSyntax,4L
+
+#define LN_caseIgnoreIA5StringSyntax		"caseIgnoreIA5StringSyntax"
+#define NID_caseIgnoreIA5StringSyntax		443
+#define OBJ_caseIgnoreIA5StringSyntax		OBJ_pilotAttributeSyntax,5L
+
+#define LN_pilotObject		"pilotObject"
+#define NID_pilotObject		444
+#define OBJ_pilotObject		OBJ_pilotObjectClass,3L
+
+#define LN_pilotPerson		"pilotPerson"
+#define NID_pilotPerson		445
+#define OBJ_pilotPerson		OBJ_pilotObjectClass,4L
+
+#define SN_account		"account"
+#define NID_account		446
+#define OBJ_account		OBJ_pilotObjectClass,5L
+
+#define SN_document		"document"
+#define NID_document		447
+#define OBJ_document		OBJ_pilotObjectClass,6L
+
+#define SN_room		"room"
+#define NID_room		448
+#define OBJ_room		OBJ_pilotObjectClass,7L
+
+#define LN_documentSeries		"documentSeries"
+#define NID_documentSeries		449
+#define OBJ_documentSeries		OBJ_pilotObjectClass,9L
+
+#define SN_Domain		"domain"
+#define LN_Domain		"Domain"
+#define NID_Domain		392
+#define OBJ_Domain		OBJ_pilotObjectClass,13L
+
+#define LN_rFC822localPart		"rFC822localPart"
+#define NID_rFC822localPart		450
+#define OBJ_rFC822localPart		OBJ_pilotObjectClass,14L
+
+#define LN_dNSDomain		"dNSDomain"
+#define NID_dNSDomain		451
+#define OBJ_dNSDomain		OBJ_pilotObjectClass,15L
+
+#define LN_domainRelatedObject		"domainRelatedObject"
+#define NID_domainRelatedObject		452
+#define OBJ_domainRelatedObject		OBJ_pilotObjectClass,17L
+
+#define LN_friendlyCountry		"friendlyCountry"
+#define NID_friendlyCountry		453
+#define OBJ_friendlyCountry		OBJ_pilotObjectClass,18L
+
+#define LN_simpleSecurityObject		"simpleSecurityObject"
+#define NID_simpleSecurityObject		454
+#define OBJ_simpleSecurityObject		OBJ_pilotObjectClass,19L
+
+#define LN_pilotOrganization		"pilotOrganization"
+#define NID_pilotOrganization		455
+#define OBJ_pilotOrganization		OBJ_pilotObjectClass,20L
+
+#define LN_pilotDSA		"pilotDSA"
+#define NID_pilotDSA		456
+#define OBJ_pilotDSA		OBJ_pilotObjectClass,21L
+
+#define LN_qualityLabelledData		"qualityLabelledData"
+#define NID_qualityLabelledData		457
+#define OBJ_qualityLabelledData		OBJ_pilotObjectClass,22L
+
+#define SN_userId		"UID"
+#define LN_userId		"userId"
+#define NID_userId		458
+#define OBJ_userId		OBJ_pilotAttributeType,1L
+
+#define LN_textEncodedORAddress		"textEncodedORAddress"
+#define NID_textEncodedORAddress		459
+#define OBJ_textEncodedORAddress		OBJ_pilotAttributeType,2L
+
+#define SN_rfc822Mailbox		"mail"
+#define LN_rfc822Mailbox		"rfc822Mailbox"
+#define NID_rfc822Mailbox		460
+#define OBJ_rfc822Mailbox		OBJ_pilotAttributeType,3L
+
+#define SN_info		"info"
+#define NID_info		461
+#define OBJ_info		OBJ_pilotAttributeType,4L
+
+#define LN_favouriteDrink		"favouriteDrink"
+#define NID_favouriteDrink		462
+#define OBJ_favouriteDrink		OBJ_pilotAttributeType,5L
+
+#define LN_roomNumber		"roomNumber"
+#define NID_roomNumber		463
+#define OBJ_roomNumber		OBJ_pilotAttributeType,6L
+
+#define SN_photo		"photo"
+#define NID_photo		464
+#define OBJ_photo		OBJ_pilotAttributeType,7L
+
+#define LN_userClass		"userClass"
+#define NID_userClass		465
+#define OBJ_userClass		OBJ_pilotAttributeType,8L
+
+#define SN_host		"host"
+#define NID_host		466
+#define OBJ_host		OBJ_pilotAttributeType,9L
+
+#define SN_manager		"manager"
+#define NID_manager		467
+#define OBJ_manager		OBJ_pilotAttributeType,10L
+
+#define LN_documentIdentifier		"documentIdentifier"
+#define NID_documentIdentifier		468
+#define OBJ_documentIdentifier		OBJ_pilotAttributeType,11L
+
+#define LN_documentTitle		"documentTitle"
+#define NID_documentTitle		469
+#define OBJ_documentTitle		OBJ_pilotAttributeType,12L
+
+#define LN_documentVersion		"documentVersion"
+#define NID_documentVersion		470
+#define OBJ_documentVersion		OBJ_pilotAttributeType,13L
+
+#define LN_documentAuthor		"documentAuthor"
+#define NID_documentAuthor		471
+#define OBJ_documentAuthor		OBJ_pilotAttributeType,14L
+
+#define LN_documentLocation		"documentLocation"
+#define NID_documentLocation		472
+#define OBJ_documentLocation		OBJ_pilotAttributeType,15L
+
+#define LN_homeTelephoneNumber		"homeTelephoneNumber"
+#define NID_homeTelephoneNumber		473
+#define OBJ_homeTelephoneNumber		OBJ_pilotAttributeType,20L
+
+#define SN_secretary		"secretary"
+#define NID_secretary		474
+#define OBJ_secretary		OBJ_pilotAttributeType,21L
+
+#define LN_otherMailbox		"otherMailbox"
+#define NID_otherMailbox		475
+#define OBJ_otherMailbox		OBJ_pilotAttributeType,22L
+
+#define LN_lastModifiedTime		"lastModifiedTime"
+#define NID_lastModifiedTime		476
+#define OBJ_lastModifiedTime		OBJ_pilotAttributeType,23L
+
+#define LN_lastModifiedBy		"lastModifiedBy"
+#define NID_lastModifiedBy		477
+#define OBJ_lastModifiedBy		OBJ_pilotAttributeType,24L
+
+#define SN_domainComponent		"DC"
+#define LN_domainComponent		"domainComponent"
+#define NID_domainComponent		391
+#define OBJ_domainComponent		OBJ_pilotAttributeType,25L
+
+#define LN_aRecord		"aRecord"
+#define NID_aRecord		478
+#define OBJ_aRecord		OBJ_pilotAttributeType,26L
+
+#define LN_pilotAttributeType27		"pilotAttributeType27"
+#define NID_pilotAttributeType27		479
+#define OBJ_pilotAttributeType27		OBJ_pilotAttributeType,27L
+
+#define LN_mXRecord		"mXRecord"
+#define NID_mXRecord		480
+#define OBJ_mXRecord		OBJ_pilotAttributeType,28L
+
+#define LN_nSRecord		"nSRecord"
+#define NID_nSRecord		481
+#define OBJ_nSRecord		OBJ_pilotAttributeType,29L
+
+#define LN_sOARecord		"sOARecord"
+#define NID_sOARecord		482
+#define OBJ_sOARecord		OBJ_pilotAttributeType,30L
+
+#define LN_cNAMERecord		"cNAMERecord"
+#define NID_cNAMERecord		483
+#define OBJ_cNAMERecord		OBJ_pilotAttributeType,31L
+
+#define LN_associatedDomain		"associatedDomain"
+#define NID_associatedDomain		484
+#define OBJ_associatedDomain		OBJ_pilotAttributeType,37L
+
+#define LN_associatedName		"associatedName"
+#define NID_associatedName		485
+#define OBJ_associatedName		OBJ_pilotAttributeType,38L
+
+#define LN_homePostalAddress		"homePostalAddress"
+#define NID_homePostalAddress		486
+#define OBJ_homePostalAddress		OBJ_pilotAttributeType,39L
+
+#define LN_personalTitle		"personalTitle"
+#define NID_personalTitle		487
+#define OBJ_personalTitle		OBJ_pilotAttributeType,40L
+
+#define LN_mobileTelephoneNumber		"mobileTelephoneNumber"
+#define NID_mobileTelephoneNumber		488
+#define OBJ_mobileTelephoneNumber		OBJ_pilotAttributeType,41L
+
+#define LN_pagerTelephoneNumber		"pagerTelephoneNumber"
+#define NID_pagerTelephoneNumber		489
+#define OBJ_pagerTelephoneNumber		OBJ_pilotAttributeType,42L
+
+#define LN_friendlyCountryName		"friendlyCountryName"
+#define NID_friendlyCountryName		490
+#define OBJ_friendlyCountryName		OBJ_pilotAttributeType,43L
+
+#define LN_organizationalStatus		"organizationalStatus"
+#define NID_organizationalStatus		491
+#define OBJ_organizationalStatus		OBJ_pilotAttributeType,45L
+
+#define LN_janetMailbox		"janetMailbox"
+#define NID_janetMailbox		492
+#define OBJ_janetMailbox		OBJ_pilotAttributeType,46L
+
+#define LN_mailPreferenceOption		"mailPreferenceOption"
+#define NID_mailPreferenceOption		493
+#define OBJ_mailPreferenceOption		OBJ_pilotAttributeType,47L
+
+#define LN_buildingName		"buildingName"
+#define NID_buildingName		494
+#define OBJ_buildingName		OBJ_pilotAttributeType,48L
+
+#define LN_dSAQuality		"dSAQuality"
+#define NID_dSAQuality		495
+#define OBJ_dSAQuality		OBJ_pilotAttributeType,49L
+
+#define LN_singleLevelQuality		"singleLevelQuality"
+#define NID_singleLevelQuality		496
+#define OBJ_singleLevelQuality		OBJ_pilotAttributeType,50L
+
+#define LN_subtreeMinimumQuality		"subtreeMinimumQuality"
+#define NID_subtreeMinimumQuality		497
+#define OBJ_subtreeMinimumQuality		OBJ_pilotAttributeType,51L
+
+#define LN_subtreeMaximumQuality		"subtreeMaximumQuality"
+#define NID_subtreeMaximumQuality		498
+#define OBJ_subtreeMaximumQuality		OBJ_pilotAttributeType,52L
+
+#define LN_personalSignature		"personalSignature"
+#define NID_personalSignature		499
+#define OBJ_personalSignature		OBJ_pilotAttributeType,53L
+
+#define LN_dITRedirect		"dITRedirect"
+#define NID_dITRedirect		500
+#define OBJ_dITRedirect		OBJ_pilotAttributeType,54L
+
+#define SN_audio		"audio"
+#define NID_audio		501
+#define OBJ_audio		OBJ_pilotAttributeType,55L
+
+#define LN_documentPublisher		"documentPublisher"
+#define NID_documentPublisher		502
+#define OBJ_documentPublisher		OBJ_pilotAttributeType,56L
+
+#define SN_id_set		"id-set"
+#define LN_id_set		"Secure Electronic Transactions"
+#define NID_id_set		512
+#define OBJ_id_set		OBJ_international_organizations,42L
+
+#define SN_set_ctype		"set-ctype"
+#define LN_set_ctype		"content types"
+#define NID_set_ctype		513
+#define OBJ_set_ctype		OBJ_id_set,0L
+
+#define SN_set_msgExt		"set-msgExt"
+#define LN_set_msgExt		"message extensions"
+#define NID_set_msgExt		514
+#define OBJ_set_msgExt		OBJ_id_set,1L
+
+#define SN_set_attr		"set-attr"
+#define NID_set_attr		515
+#define OBJ_set_attr		OBJ_id_set,3L
+
+#define SN_set_policy		"set-policy"
+#define NID_set_policy		516
+#define OBJ_set_policy		OBJ_id_set,5L
+
+#define SN_set_certExt		"set-certExt"
+#define LN_set_certExt		"certificate extensions"
+#define NID_set_certExt		517
+#define OBJ_set_certExt		OBJ_id_set,7L
+
+#define SN_set_brand		"set-brand"
+#define NID_set_brand		518
+#define OBJ_set_brand		OBJ_id_set,8L
+
+#define SN_setct_PANData		"setct-PANData"
+#define NID_setct_PANData		519
+#define OBJ_setct_PANData		OBJ_set_ctype,0L
+
+#define SN_setct_PANToken		"setct-PANToken"
+#define NID_setct_PANToken		520
+#define OBJ_setct_PANToken		OBJ_set_ctype,1L
+
+#define SN_setct_PANOnly		"setct-PANOnly"
+#define NID_setct_PANOnly		521
+#define OBJ_setct_PANOnly		OBJ_set_ctype,2L
+
+#define SN_setct_OIData		"setct-OIData"
+#define NID_setct_OIData		522
+#define OBJ_setct_OIData		OBJ_set_ctype,3L
+
+#define SN_setct_PI		"setct-PI"
+#define NID_setct_PI		523
+#define OBJ_setct_PI		OBJ_set_ctype,4L
+
+#define SN_setct_PIData		"setct-PIData"
+#define NID_setct_PIData		524
+#define OBJ_setct_PIData		OBJ_set_ctype,5L
+
+#define SN_setct_PIDataUnsigned		"setct-PIDataUnsigned"
+#define NID_setct_PIDataUnsigned		525
+#define OBJ_setct_PIDataUnsigned		OBJ_set_ctype,6L
+
+#define SN_setct_HODInput		"setct-HODInput"
+#define NID_setct_HODInput		526
+#define OBJ_setct_HODInput		OBJ_set_ctype,7L
+
+#define SN_setct_AuthResBaggage		"setct-AuthResBaggage"
+#define NID_setct_AuthResBaggage		527
+#define OBJ_setct_AuthResBaggage		OBJ_set_ctype,8L
+
+#define SN_setct_AuthRevReqBaggage		"setct-AuthRevReqBaggage"
+#define NID_setct_AuthRevReqBaggage		528
+#define OBJ_setct_AuthRevReqBaggage		OBJ_set_ctype,9L
+
+#define SN_setct_AuthRevResBaggage		"setct-AuthRevResBaggage"
+#define NID_setct_AuthRevResBaggage		529
+#define OBJ_setct_AuthRevResBaggage		OBJ_set_ctype,10L
+
+#define SN_setct_CapTokenSeq		"setct-CapTokenSeq"
+#define NID_setct_CapTokenSeq		530
+#define OBJ_setct_CapTokenSeq		OBJ_set_ctype,11L
+
+#define SN_setct_PInitResData		"setct-PInitResData"
+#define NID_setct_PInitResData		531
+#define OBJ_setct_PInitResData		OBJ_set_ctype,12L
+
+#define SN_setct_PI_TBS		"setct-PI-TBS"
+#define NID_setct_PI_TBS		532
+#define OBJ_setct_PI_TBS		OBJ_set_ctype,13L
+
+#define SN_setct_PResData		"setct-PResData"
+#define NID_setct_PResData		533
+#define OBJ_setct_PResData		OBJ_set_ctype,14L
+
+#define SN_setct_AuthReqTBS		"setct-AuthReqTBS"
+#define NID_setct_AuthReqTBS		534
+#define OBJ_setct_AuthReqTBS		OBJ_set_ctype,16L
+
+#define SN_setct_AuthResTBS		"setct-AuthResTBS"
+#define NID_setct_AuthResTBS		535
+#define OBJ_setct_AuthResTBS		OBJ_set_ctype,17L
+
+#define SN_setct_AuthResTBSX		"setct-AuthResTBSX"
+#define NID_setct_AuthResTBSX		536
+#define OBJ_setct_AuthResTBSX		OBJ_set_ctype,18L
+
+#define SN_setct_AuthTokenTBS		"setct-AuthTokenTBS"
+#define NID_setct_AuthTokenTBS		537
+#define OBJ_setct_AuthTokenTBS		OBJ_set_ctype,19L
+
+#define SN_setct_CapTokenData		"setct-CapTokenData"
+#define NID_setct_CapTokenData		538
+#define OBJ_setct_CapTokenData		OBJ_set_ctype,20L
+
+#define SN_setct_CapTokenTBS		"setct-CapTokenTBS"
+#define NID_setct_CapTokenTBS		539
+#define OBJ_setct_CapTokenTBS		OBJ_set_ctype,21L
+
+#define SN_setct_AcqCardCodeMsg		"setct-AcqCardCodeMsg"
+#define NID_setct_AcqCardCodeMsg		540
+#define OBJ_setct_AcqCardCodeMsg		OBJ_set_ctype,22L
+
+#define SN_setct_AuthRevReqTBS		"setct-AuthRevReqTBS"
+#define NID_setct_AuthRevReqTBS		541
+#define OBJ_setct_AuthRevReqTBS		OBJ_set_ctype,23L
+
+#define SN_setct_AuthRevResData		"setct-AuthRevResData"
+#define NID_setct_AuthRevResData		542
+#define OBJ_setct_AuthRevResData		OBJ_set_ctype,24L
+
+#define SN_setct_AuthRevResTBS		"setct-AuthRevResTBS"
+#define NID_setct_AuthRevResTBS		543
+#define OBJ_setct_AuthRevResTBS		OBJ_set_ctype,25L
+
+#define SN_setct_CapReqTBS		"setct-CapReqTBS"
+#define NID_setct_CapReqTBS		544
+#define OBJ_setct_CapReqTBS		OBJ_set_ctype,26L
+
+#define SN_setct_CapReqTBSX		"setct-CapReqTBSX"
+#define NID_setct_CapReqTBSX		545
+#define OBJ_setct_CapReqTBSX		OBJ_set_ctype,27L
+
+#define SN_setct_CapResData		"setct-CapResData"
+#define NID_setct_CapResData		546
+#define OBJ_setct_CapResData		OBJ_set_ctype,28L
+
+#define SN_setct_CapRevReqTBS		"setct-CapRevReqTBS"
+#define NID_setct_CapRevReqTBS		547
+#define OBJ_setct_CapRevReqTBS		OBJ_set_ctype,29L
+
+#define SN_setct_CapRevReqTBSX		"setct-CapRevReqTBSX"
+#define NID_setct_CapRevReqTBSX		548
+#define OBJ_setct_CapRevReqTBSX		OBJ_set_ctype,30L
+
+#define SN_setct_CapRevResData		"setct-CapRevResData"
+#define NID_setct_CapRevResData		549
+#define OBJ_setct_CapRevResData		OBJ_set_ctype,31L
+
+#define SN_setct_CredReqTBS		"setct-CredReqTBS"
+#define NID_setct_CredReqTBS		550
+#define OBJ_setct_CredReqTBS		OBJ_set_ctype,32L
+
+#define SN_setct_CredReqTBSX		"setct-CredReqTBSX"
+#define NID_setct_CredReqTBSX		551
+#define OBJ_setct_CredReqTBSX		OBJ_set_ctype,33L
+
+#define SN_setct_CredResData		"setct-CredResData"
+#define NID_setct_CredResData		552
+#define OBJ_setct_CredResData		OBJ_set_ctype,34L
+
+#define SN_setct_CredRevReqTBS		"setct-CredRevReqTBS"
+#define NID_setct_CredRevReqTBS		553
+#define OBJ_setct_CredRevReqTBS		OBJ_set_ctype,35L
+
+#define SN_setct_CredRevReqTBSX		"setct-CredRevReqTBSX"
+#define NID_setct_CredRevReqTBSX		554
+#define OBJ_setct_CredRevReqTBSX		OBJ_set_ctype,36L
+
+#define SN_setct_CredRevResData		"setct-CredRevResData"
+#define NID_setct_CredRevResData		555
+#define OBJ_setct_CredRevResData		OBJ_set_ctype,37L
+
+#define SN_setct_PCertReqData		"setct-PCertReqData"
+#define NID_setct_PCertReqData		556
+#define OBJ_setct_PCertReqData		OBJ_set_ctype,38L
+
+#define SN_setct_PCertResTBS		"setct-PCertResTBS"
+#define NID_setct_PCertResTBS		557
+#define OBJ_setct_PCertResTBS		OBJ_set_ctype,39L
+
+#define SN_setct_BatchAdminReqData		"setct-BatchAdminReqData"
+#define NID_setct_BatchAdminReqData		558
+#define OBJ_setct_BatchAdminReqData		OBJ_set_ctype,40L
+
+#define SN_setct_BatchAdminResData		"setct-BatchAdminResData"
+#define NID_setct_BatchAdminResData		559
+#define OBJ_setct_BatchAdminResData		OBJ_set_ctype,41L
+
+#define SN_setct_CardCInitResTBS		"setct-CardCInitResTBS"
+#define NID_setct_CardCInitResTBS		560
+#define OBJ_setct_CardCInitResTBS		OBJ_set_ctype,42L
+
+#define SN_setct_MeAqCInitResTBS		"setct-MeAqCInitResTBS"
+#define NID_setct_MeAqCInitResTBS		561
+#define OBJ_setct_MeAqCInitResTBS		OBJ_set_ctype,43L
+
+#define SN_setct_RegFormResTBS		"setct-RegFormResTBS"
+#define NID_setct_RegFormResTBS		562
+#define OBJ_setct_RegFormResTBS		OBJ_set_ctype,44L
+
+#define SN_setct_CertReqData		"setct-CertReqData"
+#define NID_setct_CertReqData		563
+#define OBJ_setct_CertReqData		OBJ_set_ctype,45L
+
+#define SN_setct_CertReqTBS		"setct-CertReqTBS"
+#define NID_setct_CertReqTBS		564
+#define OBJ_setct_CertReqTBS		OBJ_set_ctype,46L
+
+#define SN_setct_CertResData		"setct-CertResData"
+#define NID_setct_CertResData		565
+#define OBJ_setct_CertResData		OBJ_set_ctype,47L
+
+#define SN_setct_CertInqReqTBS		"setct-CertInqReqTBS"
+#define NID_setct_CertInqReqTBS		566
+#define OBJ_setct_CertInqReqTBS		OBJ_set_ctype,48L
+
+#define SN_setct_ErrorTBS		"setct-ErrorTBS"
+#define NID_setct_ErrorTBS		567
+#define OBJ_setct_ErrorTBS		OBJ_set_ctype,49L
+
+#define SN_setct_PIDualSignedTBE		"setct-PIDualSignedTBE"
+#define NID_setct_PIDualSignedTBE		568
+#define OBJ_setct_PIDualSignedTBE		OBJ_set_ctype,50L
+
+#define SN_setct_PIUnsignedTBE		"setct-PIUnsignedTBE"
+#define NID_setct_PIUnsignedTBE		569
+#define OBJ_setct_PIUnsignedTBE		OBJ_set_ctype,51L
+
+#define SN_setct_AuthReqTBE		"setct-AuthReqTBE"
+#define NID_setct_AuthReqTBE		570
+#define OBJ_setct_AuthReqTBE		OBJ_set_ctype,52L
+
+#define SN_setct_AuthResTBE		"setct-AuthResTBE"
+#define NID_setct_AuthResTBE		571
+#define OBJ_setct_AuthResTBE		OBJ_set_ctype,53L
+
+#define SN_setct_AuthResTBEX		"setct-AuthResTBEX"
+#define NID_setct_AuthResTBEX		572
+#define OBJ_setct_AuthResTBEX		OBJ_set_ctype,54L
+
+#define SN_setct_AuthTokenTBE		"setct-AuthTokenTBE"
+#define NID_setct_AuthTokenTBE		573
+#define OBJ_setct_AuthTokenTBE		OBJ_set_ctype,55L
+
+#define SN_setct_CapTokenTBE		"setct-CapTokenTBE"
+#define NID_setct_CapTokenTBE		574
+#define OBJ_setct_CapTokenTBE		OBJ_set_ctype,56L
+
+#define SN_setct_CapTokenTBEX		"setct-CapTokenTBEX"
+#define NID_setct_CapTokenTBEX		575
+#define OBJ_setct_CapTokenTBEX		OBJ_set_ctype,57L
+
+#define SN_setct_AcqCardCodeMsgTBE		"setct-AcqCardCodeMsgTBE"
+#define NID_setct_AcqCardCodeMsgTBE		576
+#define OBJ_setct_AcqCardCodeMsgTBE		OBJ_set_ctype,58L
+
+#define SN_setct_AuthRevReqTBE		"setct-AuthRevReqTBE"
+#define NID_setct_AuthRevReqTBE		577
+#define OBJ_setct_AuthRevReqTBE		OBJ_set_ctype,59L
+
+#define SN_setct_AuthRevResTBE		"setct-AuthRevResTBE"
+#define NID_setct_AuthRevResTBE		578
+#define OBJ_setct_AuthRevResTBE		OBJ_set_ctype,60L
+
+#define SN_setct_AuthRevResTBEB		"setct-AuthRevResTBEB"
+#define NID_setct_AuthRevResTBEB		579
+#define OBJ_setct_AuthRevResTBEB		OBJ_set_ctype,61L
+
+#define SN_setct_CapReqTBE		"setct-CapReqTBE"
+#define NID_setct_CapReqTBE		580
+#define OBJ_setct_CapReqTBE		OBJ_set_ctype,62L
+
+#define SN_setct_CapReqTBEX		"setct-CapReqTBEX"
+#define NID_setct_CapReqTBEX		581
+#define OBJ_setct_CapReqTBEX		OBJ_set_ctype,63L
+
+#define SN_setct_CapResTBE		"setct-CapResTBE"
+#define NID_setct_CapResTBE		582
+#define OBJ_setct_CapResTBE		OBJ_set_ctype,64L
+
+#define SN_setct_CapRevReqTBE		"setct-CapRevReqTBE"
+#define NID_setct_CapRevReqTBE		583
+#define OBJ_setct_CapRevReqTBE		OBJ_set_ctype,65L
+
+#define SN_setct_CapRevReqTBEX		"setct-CapRevReqTBEX"
+#define NID_setct_CapRevReqTBEX		584
+#define OBJ_setct_CapRevReqTBEX		OBJ_set_ctype,66L
+
+#define SN_setct_CapRevResTBE		"setct-CapRevResTBE"
+#define NID_setct_CapRevResTBE		585
+#define OBJ_setct_CapRevResTBE		OBJ_set_ctype,67L
+
+#define SN_setct_CredReqTBE		"setct-CredReqTBE"
+#define NID_setct_CredReqTBE		586
+#define OBJ_setct_CredReqTBE		OBJ_set_ctype,68L
+
+#define SN_setct_CredReqTBEX		"setct-CredReqTBEX"
+#define NID_setct_CredReqTBEX		587
+#define OBJ_setct_CredReqTBEX		OBJ_set_ctype,69L
+
+#define SN_setct_CredResTBE		"setct-CredResTBE"
+#define NID_setct_CredResTBE		588
+#define OBJ_setct_CredResTBE		OBJ_set_ctype,70L
+
+#define SN_setct_CredRevReqTBE		"setct-CredRevReqTBE"
+#define NID_setct_CredRevReqTBE		589
+#define OBJ_setct_CredRevReqTBE		OBJ_set_ctype,71L
+
+#define SN_setct_CredRevReqTBEX		"setct-CredRevReqTBEX"
+#define NID_setct_CredRevReqTBEX		590
+#define OBJ_setct_CredRevReqTBEX		OBJ_set_ctype,72L
+
+#define SN_setct_CredRevResTBE		"setct-CredRevResTBE"
+#define NID_setct_CredRevResTBE		591
+#define OBJ_setct_CredRevResTBE		OBJ_set_ctype,73L
+
+#define SN_setct_BatchAdminReqTBE		"setct-BatchAdminReqTBE"
+#define NID_setct_BatchAdminReqTBE		592
+#define OBJ_setct_BatchAdminReqTBE		OBJ_set_ctype,74L
+
+#define SN_setct_BatchAdminResTBE		"setct-BatchAdminResTBE"
+#define NID_setct_BatchAdminResTBE		593
+#define OBJ_setct_BatchAdminResTBE		OBJ_set_ctype,75L
+
+#define SN_setct_RegFormReqTBE		"setct-RegFormReqTBE"
+#define NID_setct_RegFormReqTBE		594
+#define OBJ_setct_RegFormReqTBE		OBJ_set_ctype,76L
+
+#define SN_setct_CertReqTBE		"setct-CertReqTBE"
+#define NID_setct_CertReqTBE		595
+#define OBJ_setct_CertReqTBE		OBJ_set_ctype,77L
+
+#define SN_setct_CertReqTBEX		"setct-CertReqTBEX"
+#define NID_setct_CertReqTBEX		596
+#define OBJ_setct_CertReqTBEX		OBJ_set_ctype,78L
+
+#define SN_setct_CertResTBE		"setct-CertResTBE"
+#define NID_setct_CertResTBE		597
+#define OBJ_setct_CertResTBE		OBJ_set_ctype,79L
+
+#define SN_setct_CRLNotificationTBS		"setct-CRLNotificationTBS"
+#define NID_setct_CRLNotificationTBS		598
+#define OBJ_setct_CRLNotificationTBS		OBJ_set_ctype,80L
+
+#define SN_setct_CRLNotificationResTBS		"setct-CRLNotificationResTBS"
+#define NID_setct_CRLNotificationResTBS		599
+#define OBJ_setct_CRLNotificationResTBS		OBJ_set_ctype,81L
+
+#define SN_setct_BCIDistributionTBS		"setct-BCIDistributionTBS"
+#define NID_setct_BCIDistributionTBS		600
+#define OBJ_setct_BCIDistributionTBS		OBJ_set_ctype,82L
+
+#define SN_setext_genCrypt		"setext-genCrypt"
+#define LN_setext_genCrypt		"generic cryptogram"
+#define NID_setext_genCrypt		601
+#define OBJ_setext_genCrypt		OBJ_set_msgExt,1L
+
+#define SN_setext_miAuth		"setext-miAuth"
+#define LN_setext_miAuth		"merchant initiated auth"
+#define NID_setext_miAuth		602
+#define OBJ_setext_miAuth		OBJ_set_msgExt,3L
+
+#define SN_setext_pinSecure		"setext-pinSecure"
+#define NID_setext_pinSecure		603
+#define OBJ_setext_pinSecure		OBJ_set_msgExt,4L
+
+#define SN_setext_pinAny		"setext-pinAny"
+#define NID_setext_pinAny		604
+#define OBJ_setext_pinAny		OBJ_set_msgExt,5L
+
+#define SN_setext_track2		"setext-track2"
+#define NID_setext_track2		605
+#define OBJ_setext_track2		OBJ_set_msgExt,7L
+
+#define SN_setext_cv		"setext-cv"
+#define LN_setext_cv		"additional verification"
+#define NID_setext_cv		606
+#define OBJ_setext_cv		OBJ_set_msgExt,8L
+
+#define SN_set_policy_root		"set-policy-root"
+#define NID_set_policy_root		607
+#define OBJ_set_policy_root		OBJ_set_policy,0L
+
+#define SN_setCext_hashedRoot		"setCext-hashedRoot"
+#define NID_setCext_hashedRoot		608
+#define OBJ_setCext_hashedRoot		OBJ_set_certExt,0L
+
+#define SN_setCext_certType		"setCext-certType"
+#define NID_setCext_certType		609
+#define OBJ_setCext_certType		OBJ_set_certExt,1L
+
+#define SN_setCext_merchData		"setCext-merchData"
+#define NID_setCext_merchData		610
+#define OBJ_setCext_merchData		OBJ_set_certExt,2L
+
+#define SN_setCext_cCertRequired		"setCext-cCertRequired"
+#define NID_setCext_cCertRequired		611
+#define OBJ_setCext_cCertRequired		OBJ_set_certExt,3L
+
+#define SN_setCext_tunneling		"setCext-tunneling"
+#define NID_setCext_tunneling		612
+#define OBJ_setCext_tunneling		OBJ_set_certExt,4L
+
+#define SN_setCext_setExt		"setCext-setExt"
+#define NID_setCext_setExt		613
+#define OBJ_setCext_setExt		OBJ_set_certExt,5L
+
+#define SN_setCext_setQualf		"setCext-setQualf"
+#define NID_setCext_setQualf		614
+#define OBJ_setCext_setQualf		OBJ_set_certExt,6L
+
+#define SN_setCext_PGWYcapabilities		"setCext-PGWYcapabilities"
+#define NID_setCext_PGWYcapabilities		615
+#define OBJ_setCext_PGWYcapabilities		OBJ_set_certExt,7L
+
+#define SN_setCext_TokenIdentifier		"setCext-TokenIdentifier"
+#define NID_setCext_TokenIdentifier		616
+#define OBJ_setCext_TokenIdentifier		OBJ_set_certExt,8L
+
+#define SN_setCext_Track2Data		"setCext-Track2Data"
+#define NID_setCext_Track2Data		617
+#define OBJ_setCext_Track2Data		OBJ_set_certExt,9L
+
+#define SN_setCext_TokenType		"setCext-TokenType"
+#define NID_setCext_TokenType		618
+#define OBJ_setCext_TokenType		OBJ_set_certExt,10L
+
+#define SN_setCext_IssuerCapabilities		"setCext-IssuerCapabilities"
+#define NID_setCext_IssuerCapabilities		619
+#define OBJ_setCext_IssuerCapabilities		OBJ_set_certExt,11L
+
+#define SN_setAttr_Cert		"setAttr-Cert"
+#define NID_setAttr_Cert		620
+#define OBJ_setAttr_Cert		OBJ_set_attr,0L
+
+#define SN_setAttr_PGWYcap		"setAttr-PGWYcap"
+#define LN_setAttr_PGWYcap		"payment gateway capabilities"
+#define NID_setAttr_PGWYcap		621
+#define OBJ_setAttr_PGWYcap		OBJ_set_attr,1L
+
+#define SN_setAttr_TokenType		"setAttr-TokenType"
+#define NID_setAttr_TokenType		622
+#define OBJ_setAttr_TokenType		OBJ_set_attr,2L
+
+#define SN_setAttr_IssCap		"setAttr-IssCap"
+#define LN_setAttr_IssCap		"issuer capabilities"
+#define NID_setAttr_IssCap		623
+#define OBJ_setAttr_IssCap		OBJ_set_attr,3L
+
+#define SN_set_rootKeyThumb		"set-rootKeyThumb"
+#define NID_set_rootKeyThumb		624
+#define OBJ_set_rootKeyThumb		OBJ_setAttr_Cert,0L
+
+#define SN_set_addPolicy		"set-addPolicy"
+#define NID_set_addPolicy		625
+#define OBJ_set_addPolicy		OBJ_setAttr_Cert,1L
+
+#define SN_setAttr_Token_EMV		"setAttr-Token-EMV"
+#define NID_setAttr_Token_EMV		626
+#define OBJ_setAttr_Token_EMV		OBJ_setAttr_TokenType,1L
+
+#define SN_setAttr_Token_B0Prime		"setAttr-Token-B0Prime"
+#define NID_setAttr_Token_B0Prime		627
+#define OBJ_setAttr_Token_B0Prime		OBJ_setAttr_TokenType,2L
+
+#define SN_setAttr_IssCap_CVM		"setAttr-IssCap-CVM"
+#define NID_setAttr_IssCap_CVM		628
+#define OBJ_setAttr_IssCap_CVM		OBJ_setAttr_IssCap,3L
+
+#define SN_setAttr_IssCap_T2		"setAttr-IssCap-T2"
+#define NID_setAttr_IssCap_T2		629
+#define OBJ_setAttr_IssCap_T2		OBJ_setAttr_IssCap,4L
+
+#define SN_setAttr_IssCap_Sig		"setAttr-IssCap-Sig"
+#define NID_setAttr_IssCap_Sig		630
+#define OBJ_setAttr_IssCap_Sig		OBJ_setAttr_IssCap,5L
+
+#define SN_setAttr_GenCryptgrm		"setAttr-GenCryptgrm"
+#define LN_setAttr_GenCryptgrm		"generate cryptogram"
+#define NID_setAttr_GenCryptgrm		631
+#define OBJ_setAttr_GenCryptgrm		OBJ_setAttr_IssCap_CVM,1L
+
+#define SN_setAttr_T2Enc		"setAttr-T2Enc"
+#define LN_setAttr_T2Enc		"encrypted track 2"
+#define NID_setAttr_T2Enc		632
+#define OBJ_setAttr_T2Enc		OBJ_setAttr_IssCap_T2,1L
+
+#define SN_setAttr_T2cleartxt		"setAttr-T2cleartxt"
+#define LN_setAttr_T2cleartxt		"cleartext track 2"
+#define NID_setAttr_T2cleartxt		633
+#define OBJ_setAttr_T2cleartxt		OBJ_setAttr_IssCap_T2,2L
+
+#define SN_setAttr_TokICCsig		"setAttr-TokICCsig"
+#define LN_setAttr_TokICCsig		"ICC or token signature"
+#define NID_setAttr_TokICCsig		634
+#define OBJ_setAttr_TokICCsig		OBJ_setAttr_IssCap_Sig,1L
+
+#define SN_setAttr_SecDevSig		"setAttr-SecDevSig"
+#define LN_setAttr_SecDevSig		"secure device signature"
+#define NID_setAttr_SecDevSig		635
+#define OBJ_setAttr_SecDevSig		OBJ_setAttr_IssCap_Sig,2L
+
+#define SN_set_brand_IATA_ATA		"set-brand-IATA-ATA"
+#define NID_set_brand_IATA_ATA		636
+#define OBJ_set_brand_IATA_ATA		OBJ_set_brand,1L
+
+#define SN_set_brand_Diners		"set-brand-Diners"
+#define NID_set_brand_Diners		637
+#define OBJ_set_brand_Diners		OBJ_set_brand,30L
+
+#define SN_set_brand_AmericanExpress		"set-brand-AmericanExpress"
+#define NID_set_brand_AmericanExpress		638
+#define OBJ_set_brand_AmericanExpress		OBJ_set_brand,34L
+
+#define SN_set_brand_JCB		"set-brand-JCB"
+#define NID_set_brand_JCB		639
+#define OBJ_set_brand_JCB		OBJ_set_brand,35L
+
+#define SN_set_brand_Visa		"set-brand-Visa"
+#define NID_set_brand_Visa		640
+#define OBJ_set_brand_Visa		OBJ_set_brand,4L
+
+#define SN_set_brand_MasterCard		"set-brand-MasterCard"
+#define NID_set_brand_MasterCard		641
+#define OBJ_set_brand_MasterCard		OBJ_set_brand,5L
+
+#define SN_set_brand_Novus		"set-brand-Novus"
+#define NID_set_brand_Novus		642
+#define OBJ_set_brand_Novus		OBJ_set_brand,6011L
+
+#define SN_des_cdmf		"DES-CDMF"
+#define LN_des_cdmf		"des-cdmf"
+#define NID_des_cdmf		643
+#define OBJ_des_cdmf		OBJ_rsadsi,3L,10L
+
+#define SN_rsaOAEPEncryptionSET		"rsaOAEPEncryptionSET"
+#define NID_rsaOAEPEncryptionSET		644
+#define OBJ_rsaOAEPEncryptionSET		OBJ_rsadsi,1L,1L,6L
+
+#define SN_ipsec3		"Oakley-EC2N-3"
+#define LN_ipsec3		"ipsec3"
+#define NID_ipsec3		749
+
+#define SN_ipsec4		"Oakley-EC2N-4"
+#define LN_ipsec4		"ipsec4"
+#define NID_ipsec4		750
+
+#define SN_camellia_128_cbc		"CAMELLIA-128-CBC"
+#define LN_camellia_128_cbc		"camellia-128-cbc"
+#define NID_camellia_128_cbc		751
+#define OBJ_camellia_128_cbc		1L,2L,392L,200011L,61L,1L,1L,1L,2L
+
+#define SN_camellia_192_cbc		"CAMELLIA-192-CBC"
+#define LN_camellia_192_cbc		"camellia-192-cbc"
+#define NID_camellia_192_cbc		752
+#define OBJ_camellia_192_cbc		1L,2L,392L,200011L,61L,1L,1L,1L,3L
+
+#define SN_camellia_256_cbc		"CAMELLIA-256-CBC"
+#define LN_camellia_256_cbc		"camellia-256-cbc"
+#define NID_camellia_256_cbc		753
+#define OBJ_camellia_256_cbc		1L,2L,392L,200011L,61L,1L,1L,1L,4L
+
+#define OBJ_ntt_ds		0L,3L,4401L,5L
+
+#define OBJ_camellia		OBJ_ntt_ds,3L,1L,9L
+
+#define SN_camellia_128_ecb		"CAMELLIA-128-ECB"
+#define LN_camellia_128_ecb		"camellia-128-ecb"
+#define NID_camellia_128_ecb		754
+#define OBJ_camellia_128_ecb		OBJ_camellia,1L
+
+#define SN_camellia_128_ofb128		"CAMELLIA-128-OFB"
+#define LN_camellia_128_ofb128		"camellia-128-ofb"
+#define NID_camellia_128_ofb128		766
+#define OBJ_camellia_128_ofb128		OBJ_camellia,3L
+
+#define SN_camellia_128_cfb128		"CAMELLIA-128-CFB"
+#define LN_camellia_128_cfb128		"camellia-128-cfb"
+#define NID_camellia_128_cfb128		757
+#define OBJ_camellia_128_cfb128		OBJ_camellia,4L
+
+#define SN_camellia_192_ecb		"CAMELLIA-192-ECB"
+#define LN_camellia_192_ecb		"camellia-192-ecb"
+#define NID_camellia_192_ecb		755
+#define OBJ_camellia_192_ecb		OBJ_camellia,21L
+
+#define SN_camellia_192_ofb128		"CAMELLIA-192-OFB"
+#define LN_camellia_192_ofb128		"camellia-192-ofb"
+#define NID_camellia_192_ofb128		767
+#define OBJ_camellia_192_ofb128		OBJ_camellia,23L
+
+#define SN_camellia_192_cfb128		"CAMELLIA-192-CFB"
+#define LN_camellia_192_cfb128		"camellia-192-cfb"
+#define NID_camellia_192_cfb128		758
+#define OBJ_camellia_192_cfb128		OBJ_camellia,24L
+
+#define SN_camellia_256_ecb		"CAMELLIA-256-ECB"
+#define LN_camellia_256_ecb		"camellia-256-ecb"
+#define NID_camellia_256_ecb		756
+#define OBJ_camellia_256_ecb		OBJ_camellia,41L
+
+#define SN_camellia_256_ofb128		"CAMELLIA-256-OFB"
+#define LN_camellia_256_ofb128		"camellia-256-ofb"
+#define NID_camellia_256_ofb128		768
+#define OBJ_camellia_256_ofb128		OBJ_camellia,43L
+
+#define SN_camellia_256_cfb128		"CAMELLIA-256-CFB"
+#define LN_camellia_256_cfb128		"camellia-256-cfb"
+#define NID_camellia_256_cfb128		759
+#define OBJ_camellia_256_cfb128		OBJ_camellia,44L
+
+#define SN_camellia_128_cfb1		"CAMELLIA-128-CFB1"
+#define LN_camellia_128_cfb1		"camellia-128-cfb1"
+#define NID_camellia_128_cfb1		760
+
+#define SN_camellia_192_cfb1		"CAMELLIA-192-CFB1"
+#define LN_camellia_192_cfb1		"camellia-192-cfb1"
+#define NID_camellia_192_cfb1		761
+
+#define SN_camellia_256_cfb1		"CAMELLIA-256-CFB1"
+#define LN_camellia_256_cfb1		"camellia-256-cfb1"
+#define NID_camellia_256_cfb1		762
+
+#define SN_camellia_128_cfb8		"CAMELLIA-128-CFB8"
+#define LN_camellia_128_cfb8		"camellia-128-cfb8"
+#define NID_camellia_128_cfb8		763
+
+#define SN_camellia_192_cfb8		"CAMELLIA-192-CFB8"
+#define LN_camellia_192_cfb8		"camellia-192-cfb8"
+#define NID_camellia_192_cfb8		764
+
+#define SN_camellia_256_cfb8		"CAMELLIA-256-CFB8"
+#define LN_camellia_256_cfb8		"camellia-256-cfb8"
+#define NID_camellia_256_cfb8		765
+
diff --git a/dep/include/openssl/objects.h b/dep/include/openssl/objects.h
new file mode 100644
index 00000000000..7242f76fb0f
--- /dev/null
+++ b/dep/include/openssl/objects.h
@@ -0,0 +1,1049 @@
+/* crypto/objects/objects.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_OBJECTS_H
+#define HEADER_OBJECTS_H
+
+#define USE_OBJ_MAC
+
+#ifdef USE_OBJ_MAC
+#include 
+#else
+#define SN_undef			"UNDEF"
+#define LN_undef			"undefined"
+#define NID_undef			0
+#define OBJ_undef			0L
+
+#define SN_Algorithm			"Algorithm"
+#define LN_algorithm			"algorithm"
+#define NID_algorithm			38
+#define OBJ_algorithm			1L,3L,14L,3L,2L
+
+#define LN_rsadsi			"rsadsi"
+#define NID_rsadsi			1
+#define OBJ_rsadsi			1L,2L,840L,113549L
+
+#define LN_pkcs				"pkcs"
+#define NID_pkcs			2
+#define OBJ_pkcs			OBJ_rsadsi,1L
+
+#define SN_md2				"MD2"
+#define LN_md2				"md2"
+#define NID_md2				3
+#define OBJ_md2				OBJ_rsadsi,2L,2L
+
+#define SN_md5				"MD5"
+#define LN_md5				"md5"
+#define NID_md5				4
+#define OBJ_md5				OBJ_rsadsi,2L,5L
+
+#define SN_rc4				"RC4"
+#define LN_rc4				"rc4"
+#define NID_rc4				5
+#define OBJ_rc4				OBJ_rsadsi,3L,4L
+
+#define LN_rsaEncryption		"rsaEncryption"
+#define NID_rsaEncryption		6
+#define OBJ_rsaEncryption		OBJ_pkcs,1L,1L
+
+#define SN_md2WithRSAEncryption		"RSA-MD2"
+#define LN_md2WithRSAEncryption		"md2WithRSAEncryption"
+#define NID_md2WithRSAEncryption	7
+#define OBJ_md2WithRSAEncryption	OBJ_pkcs,1L,2L
+
+#define SN_md5WithRSAEncryption		"RSA-MD5"
+#define LN_md5WithRSAEncryption		"md5WithRSAEncryption"
+#define NID_md5WithRSAEncryption	8
+#define OBJ_md5WithRSAEncryption	OBJ_pkcs,1L,4L
+
+#define SN_pbeWithMD2AndDES_CBC		"PBE-MD2-DES"
+#define LN_pbeWithMD2AndDES_CBC		"pbeWithMD2AndDES-CBC"
+#define NID_pbeWithMD2AndDES_CBC	9
+#define OBJ_pbeWithMD2AndDES_CBC	OBJ_pkcs,5L,1L
+
+#define SN_pbeWithMD5AndDES_CBC		"PBE-MD5-DES"
+#define LN_pbeWithMD5AndDES_CBC		"pbeWithMD5AndDES-CBC"
+#define NID_pbeWithMD5AndDES_CBC	10
+#define OBJ_pbeWithMD5AndDES_CBC	OBJ_pkcs,5L,3L
+
+#define LN_X500				"X500"
+#define NID_X500			11
+#define OBJ_X500			2L,5L
+
+#define LN_X509				"X509"
+#define NID_X509			12
+#define OBJ_X509			OBJ_X500,4L
+
+#define SN_commonName			"CN"
+#define LN_commonName			"commonName"
+#define NID_commonName			13
+#define OBJ_commonName			OBJ_X509,3L
+
+#define SN_countryName			"C"
+#define LN_countryName			"countryName"
+#define NID_countryName			14
+#define OBJ_countryName			OBJ_X509,6L
+
+#define SN_localityName			"L"
+#define LN_localityName			"localityName"
+#define NID_localityName		15
+#define OBJ_localityName		OBJ_X509,7L
+
+/* Postal Address? PA */
+
+/* should be "ST" (rfc1327) but MS uses 'S' */
+#define SN_stateOrProvinceName		"ST"
+#define LN_stateOrProvinceName		"stateOrProvinceName"
+#define NID_stateOrProvinceName		16
+#define OBJ_stateOrProvinceName		OBJ_X509,8L
+
+#define SN_organizationName		"O"
+#define LN_organizationName		"organizationName"
+#define NID_organizationName		17
+#define OBJ_organizationName		OBJ_X509,10L
+
+#define SN_organizationalUnitName	"OU"
+#define LN_organizationalUnitName	"organizationalUnitName"
+#define NID_organizationalUnitName	18
+#define OBJ_organizationalUnitName	OBJ_X509,11L
+
+#define SN_rsa				"RSA"
+#define LN_rsa				"rsa"
+#define NID_rsa				19
+#define OBJ_rsa				OBJ_X500,8L,1L,1L
+
+#define LN_pkcs7			"pkcs7"
+#define NID_pkcs7			20
+#define OBJ_pkcs7			OBJ_pkcs,7L
+
+#define LN_pkcs7_data			"pkcs7-data"
+#define NID_pkcs7_data			21
+#define OBJ_pkcs7_data			OBJ_pkcs7,1L
+
+#define LN_pkcs7_signed			"pkcs7-signedData"
+#define NID_pkcs7_signed		22
+#define OBJ_pkcs7_signed		OBJ_pkcs7,2L
+
+#define LN_pkcs7_enveloped		"pkcs7-envelopedData"
+#define NID_pkcs7_enveloped		23
+#define OBJ_pkcs7_enveloped		OBJ_pkcs7,3L
+
+#define LN_pkcs7_signedAndEnveloped	"pkcs7-signedAndEnvelopedData"
+#define NID_pkcs7_signedAndEnveloped	24
+#define OBJ_pkcs7_signedAndEnveloped	OBJ_pkcs7,4L
+
+#define LN_pkcs7_digest			"pkcs7-digestData"
+#define NID_pkcs7_digest		25
+#define OBJ_pkcs7_digest		OBJ_pkcs7,5L
+
+#define LN_pkcs7_encrypted		"pkcs7-encryptedData"
+#define NID_pkcs7_encrypted		26
+#define OBJ_pkcs7_encrypted		OBJ_pkcs7,6L
+
+#define LN_pkcs3			"pkcs3"
+#define NID_pkcs3			27
+#define OBJ_pkcs3			OBJ_pkcs,3L
+
+#define LN_dhKeyAgreement		"dhKeyAgreement"
+#define NID_dhKeyAgreement		28
+#define OBJ_dhKeyAgreement		OBJ_pkcs3,1L
+
+#define SN_des_ecb			"DES-ECB"
+#define LN_des_ecb			"des-ecb"
+#define NID_des_ecb			29
+#define OBJ_des_ecb			OBJ_algorithm,6L
+
+#define SN_des_cfb64			"DES-CFB"
+#define LN_des_cfb64			"des-cfb"
+#define NID_des_cfb64			30
+/* IV + num */
+#define OBJ_des_cfb64			OBJ_algorithm,9L
+
+#define SN_des_cbc			"DES-CBC"
+#define LN_des_cbc			"des-cbc"
+#define NID_des_cbc			31
+/* IV */
+#define OBJ_des_cbc			OBJ_algorithm,7L
+
+#define SN_des_ede			"DES-EDE"
+#define LN_des_ede			"des-ede"
+#define NID_des_ede			32
+/* ?? */
+#define OBJ_des_ede			OBJ_algorithm,17L
+
+#define SN_des_ede3			"DES-EDE3"
+#define LN_des_ede3			"des-ede3"
+#define NID_des_ede3			33
+
+#define SN_idea_cbc			"IDEA-CBC"
+#define LN_idea_cbc			"idea-cbc"
+#define NID_idea_cbc			34
+#define OBJ_idea_cbc			1L,3L,6L,1L,4L,1L,188L,7L,1L,1L,2L
+
+#define SN_idea_cfb64			"IDEA-CFB"
+#define LN_idea_cfb64			"idea-cfb"
+#define NID_idea_cfb64			35
+
+#define SN_idea_ecb			"IDEA-ECB"
+#define LN_idea_ecb			"idea-ecb"
+#define NID_idea_ecb			36
+
+#define SN_rc2_cbc			"RC2-CBC"
+#define LN_rc2_cbc			"rc2-cbc"
+#define NID_rc2_cbc			37
+#define OBJ_rc2_cbc			OBJ_rsadsi,3L,2L
+
+#define SN_rc2_ecb			"RC2-ECB"
+#define LN_rc2_ecb			"rc2-ecb"
+#define NID_rc2_ecb			38
+
+#define SN_rc2_cfb64			"RC2-CFB"
+#define LN_rc2_cfb64			"rc2-cfb"
+#define NID_rc2_cfb64			39
+
+#define SN_rc2_ofb64			"RC2-OFB"
+#define LN_rc2_ofb64			"rc2-ofb"
+#define NID_rc2_ofb64			40
+
+#define SN_sha				"SHA"
+#define LN_sha				"sha"
+#define NID_sha				41
+#define OBJ_sha				OBJ_algorithm,18L
+
+#define SN_shaWithRSAEncryption		"RSA-SHA"
+#define LN_shaWithRSAEncryption		"shaWithRSAEncryption"
+#define NID_shaWithRSAEncryption	42
+#define OBJ_shaWithRSAEncryption	OBJ_algorithm,15L
+
+#define SN_des_ede_cbc			"DES-EDE-CBC"
+#define LN_des_ede_cbc			"des-ede-cbc"
+#define NID_des_ede_cbc			43
+
+#define SN_des_ede3_cbc			"DES-EDE3-CBC"
+#define LN_des_ede3_cbc			"des-ede3-cbc"
+#define NID_des_ede3_cbc		44
+#define OBJ_des_ede3_cbc		OBJ_rsadsi,3L,7L
+
+#define SN_des_ofb64			"DES-OFB"
+#define LN_des_ofb64			"des-ofb"
+#define NID_des_ofb64			45
+#define OBJ_des_ofb64			OBJ_algorithm,8L
+
+#define SN_idea_ofb64			"IDEA-OFB"
+#define LN_idea_ofb64			"idea-ofb"
+#define NID_idea_ofb64			46
+
+#define LN_pkcs9			"pkcs9"
+#define NID_pkcs9			47
+#define OBJ_pkcs9			OBJ_pkcs,9L
+
+#define SN_pkcs9_emailAddress		"Email"
+#define LN_pkcs9_emailAddress		"emailAddress"
+#define NID_pkcs9_emailAddress		48
+#define OBJ_pkcs9_emailAddress		OBJ_pkcs9,1L
+
+#define LN_pkcs9_unstructuredName	"unstructuredName"
+#define NID_pkcs9_unstructuredName	49
+#define OBJ_pkcs9_unstructuredName	OBJ_pkcs9,2L
+
+#define LN_pkcs9_contentType		"contentType"
+#define NID_pkcs9_contentType		50
+#define OBJ_pkcs9_contentType		OBJ_pkcs9,3L
+
+#define LN_pkcs9_messageDigest		"messageDigest"
+#define NID_pkcs9_messageDigest		51
+#define OBJ_pkcs9_messageDigest		OBJ_pkcs9,4L
+
+#define LN_pkcs9_signingTime		"signingTime"
+#define NID_pkcs9_signingTime		52
+#define OBJ_pkcs9_signingTime		OBJ_pkcs9,5L
+
+#define LN_pkcs9_countersignature	"countersignature"
+#define NID_pkcs9_countersignature	53
+#define OBJ_pkcs9_countersignature	OBJ_pkcs9,6L
+
+#define LN_pkcs9_challengePassword	"challengePassword"
+#define NID_pkcs9_challengePassword	54
+#define OBJ_pkcs9_challengePassword	OBJ_pkcs9,7L
+
+#define LN_pkcs9_unstructuredAddress	"unstructuredAddress"
+#define NID_pkcs9_unstructuredAddress	55
+#define OBJ_pkcs9_unstructuredAddress	OBJ_pkcs9,8L
+
+#define LN_pkcs9_extCertAttributes	"extendedCertificateAttributes"
+#define NID_pkcs9_extCertAttributes	56
+#define OBJ_pkcs9_extCertAttributes	OBJ_pkcs9,9L
+
+#define SN_netscape			"Netscape"
+#define LN_netscape			"Netscape Communications Corp."
+#define NID_netscape			57
+#define OBJ_netscape			2L,16L,840L,1L,113730L
+
+#define SN_netscape_cert_extension	"nsCertExt"
+#define LN_netscape_cert_extension	"Netscape Certificate Extension"
+#define NID_netscape_cert_extension	58
+#define OBJ_netscape_cert_extension	OBJ_netscape,1L
+
+#define SN_netscape_data_type		"nsDataType"
+#define LN_netscape_data_type		"Netscape Data Type"
+#define NID_netscape_data_type		59
+#define OBJ_netscape_data_type		OBJ_netscape,2L
+
+#define SN_des_ede_cfb64		"DES-EDE-CFB"
+#define LN_des_ede_cfb64		"des-ede-cfb"
+#define NID_des_ede_cfb64		60
+
+#define SN_des_ede3_cfb64		"DES-EDE3-CFB"
+#define LN_des_ede3_cfb64		"des-ede3-cfb"
+#define NID_des_ede3_cfb64		61
+
+#define SN_des_ede_ofb64		"DES-EDE-OFB"
+#define LN_des_ede_ofb64		"des-ede-ofb"
+#define NID_des_ede_ofb64		62
+
+#define SN_des_ede3_ofb64		"DES-EDE3-OFB"
+#define LN_des_ede3_ofb64		"des-ede3-ofb"
+#define NID_des_ede3_ofb64		63
+
+/* I'm not sure about the object ID */
+#define SN_sha1				"SHA1"
+#define LN_sha1				"sha1"
+#define NID_sha1			64
+#define OBJ_sha1			OBJ_algorithm,26L
+/* 28 Jun 1996 - eay */
+/* #define OBJ_sha1			1L,3L,14L,2L,26L,05L <- wrong */
+
+#define SN_sha1WithRSAEncryption	"RSA-SHA1"
+#define LN_sha1WithRSAEncryption	"sha1WithRSAEncryption"
+#define NID_sha1WithRSAEncryption	65
+#define OBJ_sha1WithRSAEncryption	OBJ_pkcs,1L,5L
+
+#define SN_dsaWithSHA			"DSA-SHA"
+#define LN_dsaWithSHA			"dsaWithSHA"
+#define NID_dsaWithSHA			66
+#define OBJ_dsaWithSHA			OBJ_algorithm,13L
+
+#define SN_dsa_2			"DSA-old"
+#define LN_dsa_2			"dsaEncryption-old"
+#define NID_dsa_2			67
+#define OBJ_dsa_2			OBJ_algorithm,12L
+
+/* proposed by microsoft to RSA */
+#define SN_pbeWithSHA1AndRC2_CBC	"PBE-SHA1-RC2-64"
+#define LN_pbeWithSHA1AndRC2_CBC	"pbeWithSHA1AndRC2-CBC"
+#define NID_pbeWithSHA1AndRC2_CBC	68
+#define OBJ_pbeWithSHA1AndRC2_CBC	OBJ_pkcs,5L,11L 
+
+/* proposed by microsoft to RSA as pbeWithSHA1AndRC4: it is now
+ * defined explicitly in PKCS#5 v2.0 as id-PBKDF2 which is something
+ * completely different.
+ */
+#define LN_id_pbkdf2			"PBKDF2"
+#define NID_id_pbkdf2			69
+#define OBJ_id_pbkdf2			OBJ_pkcs,5L,12L 
+
+#define SN_dsaWithSHA1_2		"DSA-SHA1-old"
+#define LN_dsaWithSHA1_2		"dsaWithSHA1-old"
+#define NID_dsaWithSHA1_2		70
+/* Got this one from 'sdn706r20.pdf' which is actually an NSA document :-) */
+#define OBJ_dsaWithSHA1_2		OBJ_algorithm,27L
+
+#define SN_netscape_cert_type		"nsCertType"
+#define LN_netscape_cert_type		"Netscape Cert Type"
+#define NID_netscape_cert_type		71
+#define OBJ_netscape_cert_type		OBJ_netscape_cert_extension,1L
+
+#define SN_netscape_base_url		"nsBaseUrl"
+#define LN_netscape_base_url		"Netscape Base Url"
+#define NID_netscape_base_url		72
+#define OBJ_netscape_base_url		OBJ_netscape_cert_extension,2L
+
+#define SN_netscape_revocation_url	"nsRevocationUrl"
+#define LN_netscape_revocation_url	"Netscape Revocation Url"
+#define NID_netscape_revocation_url	73
+#define OBJ_netscape_revocation_url	OBJ_netscape_cert_extension,3L
+
+#define SN_netscape_ca_revocation_url	"nsCaRevocationUrl"
+#define LN_netscape_ca_revocation_url	"Netscape CA Revocation Url"
+#define NID_netscape_ca_revocation_url	74
+#define OBJ_netscape_ca_revocation_url	OBJ_netscape_cert_extension,4L
+
+#define SN_netscape_renewal_url		"nsRenewalUrl"
+#define LN_netscape_renewal_url		"Netscape Renewal Url"
+#define NID_netscape_renewal_url	75
+#define OBJ_netscape_renewal_url	OBJ_netscape_cert_extension,7L
+
+#define SN_netscape_ca_policy_url	"nsCaPolicyUrl"
+#define LN_netscape_ca_policy_url	"Netscape CA Policy Url"
+#define NID_netscape_ca_policy_url	76
+#define OBJ_netscape_ca_policy_url	OBJ_netscape_cert_extension,8L
+
+#define SN_netscape_ssl_server_name	"nsSslServerName"
+#define LN_netscape_ssl_server_name	"Netscape SSL Server Name"
+#define NID_netscape_ssl_server_name	77
+#define OBJ_netscape_ssl_server_name	OBJ_netscape_cert_extension,12L
+
+#define SN_netscape_comment		"nsComment"
+#define LN_netscape_comment		"Netscape Comment"
+#define NID_netscape_comment		78
+#define OBJ_netscape_comment		OBJ_netscape_cert_extension,13L
+
+#define SN_netscape_cert_sequence	"nsCertSequence"
+#define LN_netscape_cert_sequence	"Netscape Certificate Sequence"
+#define NID_netscape_cert_sequence	79
+#define OBJ_netscape_cert_sequence	OBJ_netscape_data_type,5L
+
+#define SN_desx_cbc			"DESX-CBC"
+#define LN_desx_cbc			"desx-cbc"
+#define NID_desx_cbc			80
+
+#define SN_id_ce			"id-ce"
+#define NID_id_ce			81
+#define OBJ_id_ce			2L,5L,29L
+
+#define SN_subject_key_identifier	"subjectKeyIdentifier"
+#define LN_subject_key_identifier	"X509v3 Subject Key Identifier"
+#define NID_subject_key_identifier	82
+#define OBJ_subject_key_identifier	OBJ_id_ce,14L
+
+#define SN_key_usage			"keyUsage"
+#define LN_key_usage			"X509v3 Key Usage"
+#define NID_key_usage			83
+#define OBJ_key_usage			OBJ_id_ce,15L
+
+#define SN_private_key_usage_period	"privateKeyUsagePeriod"
+#define LN_private_key_usage_period	"X509v3 Private Key Usage Period"
+#define NID_private_key_usage_period	84
+#define OBJ_private_key_usage_period	OBJ_id_ce,16L
+
+#define SN_subject_alt_name		"subjectAltName"
+#define LN_subject_alt_name		"X509v3 Subject Alternative Name"
+#define NID_subject_alt_name		85
+#define OBJ_subject_alt_name		OBJ_id_ce,17L
+
+#define SN_issuer_alt_name		"issuerAltName"
+#define LN_issuer_alt_name		"X509v3 Issuer Alternative Name"
+#define NID_issuer_alt_name		86
+#define OBJ_issuer_alt_name		OBJ_id_ce,18L
+
+#define SN_basic_constraints		"basicConstraints"
+#define LN_basic_constraints		"X509v3 Basic Constraints"
+#define NID_basic_constraints		87
+#define OBJ_basic_constraints		OBJ_id_ce,19L
+
+#define SN_crl_number			"crlNumber"
+#define LN_crl_number			"X509v3 CRL Number"
+#define NID_crl_number			88
+#define OBJ_crl_number			OBJ_id_ce,20L
+
+#define SN_certificate_policies		"certificatePolicies"
+#define LN_certificate_policies		"X509v3 Certificate Policies"
+#define NID_certificate_policies	89
+#define OBJ_certificate_policies	OBJ_id_ce,32L
+
+#define SN_authority_key_identifier	"authorityKeyIdentifier"
+#define LN_authority_key_identifier	"X509v3 Authority Key Identifier"
+#define NID_authority_key_identifier	90
+#define OBJ_authority_key_identifier	OBJ_id_ce,35L
+
+#define SN_bf_cbc			"BF-CBC"
+#define LN_bf_cbc			"bf-cbc"
+#define NID_bf_cbc			91
+#define OBJ_bf_cbc			1L,3L,6L,1L,4L,1L,3029L,1L,2L
+
+#define SN_bf_ecb			"BF-ECB"
+#define LN_bf_ecb			"bf-ecb"
+#define NID_bf_ecb			92
+
+#define SN_bf_cfb64			"BF-CFB"
+#define LN_bf_cfb64			"bf-cfb"
+#define NID_bf_cfb64			93
+
+#define SN_bf_ofb64			"BF-OFB"
+#define LN_bf_ofb64			"bf-ofb"
+#define NID_bf_ofb64			94
+
+#define SN_mdc2				"MDC2"
+#define LN_mdc2				"mdc2"
+#define NID_mdc2			95
+#define OBJ_mdc2			2L,5L,8L,3L,101L
+/* An alternative?			1L,3L,14L,3L,2L,19L */
+
+#define SN_mdc2WithRSA			"RSA-MDC2"
+#define LN_mdc2WithRSA			"mdc2withRSA"
+#define NID_mdc2WithRSA			96
+#define OBJ_mdc2WithRSA			2L,5L,8L,3L,100L
+
+#define SN_rc4_40			"RC4-40"
+#define LN_rc4_40			"rc4-40"
+#define NID_rc4_40			97
+
+#define SN_rc2_40_cbc			"RC2-40-CBC"
+#define LN_rc2_40_cbc			"rc2-40-cbc"
+#define NID_rc2_40_cbc			98
+
+#define SN_givenName			"G"
+#define LN_givenName			"givenName"
+#define NID_givenName			99
+#define OBJ_givenName			OBJ_X509,42L
+
+#define SN_surname			"S"
+#define LN_surname			"surname"
+#define NID_surname			100
+#define OBJ_surname			OBJ_X509,4L
+
+#define SN_initials			"I"
+#define LN_initials			"initials"
+#define NID_initials			101
+#define OBJ_initials			OBJ_X509,43L
+
+#define SN_uniqueIdentifier		"UID"
+#define LN_uniqueIdentifier		"uniqueIdentifier"
+#define NID_uniqueIdentifier		102
+#define OBJ_uniqueIdentifier		OBJ_X509,45L
+
+#define SN_crl_distribution_points	"crlDistributionPoints"
+#define LN_crl_distribution_points	"X509v3 CRL Distribution Points"
+#define NID_crl_distribution_points	103
+#define OBJ_crl_distribution_points	OBJ_id_ce,31L
+
+#define SN_md5WithRSA			"RSA-NP-MD5"
+#define LN_md5WithRSA			"md5WithRSA"
+#define NID_md5WithRSA			104
+#define OBJ_md5WithRSA			OBJ_algorithm,3L
+
+#define SN_serialNumber			"SN"
+#define LN_serialNumber			"serialNumber"
+#define NID_serialNumber		105
+#define OBJ_serialNumber		OBJ_X509,5L
+
+#define SN_title			"T"
+#define LN_title			"title"
+#define NID_title			106
+#define OBJ_title			OBJ_X509,12L
+
+#define SN_description			"D"
+#define LN_description			"description"
+#define NID_description			107
+#define OBJ_description			OBJ_X509,13L
+
+/* CAST5 is CAST-128, I'm just sticking with the documentation */
+#define SN_cast5_cbc			"CAST5-CBC"
+#define LN_cast5_cbc			"cast5-cbc"
+#define NID_cast5_cbc			108
+#define OBJ_cast5_cbc			1L,2L,840L,113533L,7L,66L,10L
+
+#define SN_cast5_ecb			"CAST5-ECB"
+#define LN_cast5_ecb			"cast5-ecb"
+#define NID_cast5_ecb			109
+
+#define SN_cast5_cfb64			"CAST5-CFB"
+#define LN_cast5_cfb64			"cast5-cfb"
+#define NID_cast5_cfb64			110
+
+#define SN_cast5_ofb64			"CAST5-OFB"
+#define LN_cast5_ofb64			"cast5-ofb"
+#define NID_cast5_ofb64			111
+
+#define LN_pbeWithMD5AndCast5_CBC	"pbeWithMD5AndCast5CBC"
+#define NID_pbeWithMD5AndCast5_CBC	112
+#define OBJ_pbeWithMD5AndCast5_CBC	1L,2L,840L,113533L,7L,66L,12L
+
+/* This is one sun will soon be using :-(
+ * id-dsa-with-sha1 ID  ::= {
+ *   iso(1) member-body(2) us(840) x9-57 (10040) x9cm(4) 3 }
+ */
+#define SN_dsaWithSHA1			"DSA-SHA1"
+#define LN_dsaWithSHA1			"dsaWithSHA1"
+#define NID_dsaWithSHA1			113
+#define OBJ_dsaWithSHA1			1L,2L,840L,10040L,4L,3L
+
+#define NID_md5_sha1			114
+#define SN_md5_sha1			"MD5-SHA1"
+#define LN_md5_sha1			"md5-sha1"
+
+#define SN_sha1WithRSA			"RSA-SHA1-2"
+#define LN_sha1WithRSA			"sha1WithRSA"
+#define NID_sha1WithRSA			115
+#define OBJ_sha1WithRSA			OBJ_algorithm,29L
+
+#define SN_dsa				"DSA"
+#define LN_dsa				"dsaEncryption"
+#define NID_dsa				116
+#define OBJ_dsa				1L,2L,840L,10040L,4L,1L
+
+#define SN_ripemd160			"RIPEMD160"
+#define LN_ripemd160			"ripemd160"
+#define NID_ripemd160			117
+#define OBJ_ripemd160			1L,3L,36L,3L,2L,1L
+
+/* The name should actually be rsaSignatureWithripemd160, but I'm going
+ * to continue using the convention I'm using with the other ciphers */
+#define SN_ripemd160WithRSA		"RSA-RIPEMD160"
+#define LN_ripemd160WithRSA		"ripemd160WithRSA"
+#define NID_ripemd160WithRSA		119
+#define OBJ_ripemd160WithRSA		1L,3L,36L,3L,3L,1L,2L
+
+/* Taken from rfc2040
+ *  RC5_CBC_Parameters ::= SEQUENCE {
+ *	version           INTEGER (v1_0(16)),
+ *	rounds            INTEGER (8..127),
+ *	blockSizeInBits   INTEGER (64, 128),
+ *	iv                OCTET STRING OPTIONAL
+ *	}
+ */
+#define SN_rc5_cbc			"RC5-CBC"
+#define LN_rc5_cbc			"rc5-cbc"
+#define NID_rc5_cbc			120
+#define OBJ_rc5_cbc			OBJ_rsadsi,3L,8L
+
+#define SN_rc5_ecb			"RC5-ECB"
+#define LN_rc5_ecb			"rc5-ecb"
+#define NID_rc5_ecb			121
+
+#define SN_rc5_cfb64			"RC5-CFB"
+#define LN_rc5_cfb64			"rc5-cfb"
+#define NID_rc5_cfb64			122
+
+#define SN_rc5_ofb64			"RC5-OFB"
+#define LN_rc5_ofb64			"rc5-ofb"
+#define NID_rc5_ofb64			123
+
+#define SN_rle_compression		"RLE"
+#define LN_rle_compression		"run length compression"
+#define NID_rle_compression		124
+#define OBJ_rle_compression		1L,1L,1L,1L,666L,1L
+
+#define SN_zlib_compression		"ZLIB"
+#define LN_zlib_compression		"zlib compression"
+#define NID_zlib_compression		125
+#define OBJ_zlib_compression		1L,1L,1L,1L,666L,2L
+
+#define SN_ext_key_usage		"extendedKeyUsage"
+#define LN_ext_key_usage		"X509v3 Extended Key Usage"
+#define NID_ext_key_usage		126
+#define OBJ_ext_key_usage		OBJ_id_ce,37
+
+#define SN_id_pkix			"PKIX"
+#define NID_id_pkix			127
+#define OBJ_id_pkix			1L,3L,6L,1L,5L,5L,7L
+
+#define SN_id_kp			"id-kp"
+#define NID_id_kp			128
+#define OBJ_id_kp			OBJ_id_pkix,3L
+
+/* PKIX extended key usage OIDs */
+
+#define SN_server_auth			"serverAuth"
+#define LN_server_auth			"TLS Web Server Authentication"
+#define NID_server_auth			129
+#define OBJ_server_auth			OBJ_id_kp,1L
+
+#define SN_client_auth			"clientAuth"
+#define LN_client_auth			"TLS Web Client Authentication"
+#define NID_client_auth			130
+#define OBJ_client_auth			OBJ_id_kp,2L
+
+#define SN_code_sign			"codeSigning"
+#define LN_code_sign			"Code Signing"
+#define NID_code_sign			131
+#define OBJ_code_sign			OBJ_id_kp,3L
+
+#define SN_email_protect		"emailProtection"
+#define LN_email_protect		"E-mail Protection"
+#define NID_email_protect		132
+#define OBJ_email_protect		OBJ_id_kp,4L
+
+#define SN_time_stamp			"timeStamping"
+#define LN_time_stamp			"Time Stamping"
+#define NID_time_stamp			133
+#define OBJ_time_stamp			OBJ_id_kp,8L
+
+/* Additional extended key usage OIDs: Microsoft */
+
+#define SN_ms_code_ind			"msCodeInd"
+#define LN_ms_code_ind			"Microsoft Individual Code Signing"
+#define NID_ms_code_ind			134
+#define OBJ_ms_code_ind			1L,3L,6L,1L,4L,1L,311L,2L,1L,21L
+
+#define SN_ms_code_com			"msCodeCom"
+#define LN_ms_code_com			"Microsoft Commercial Code Signing"
+#define NID_ms_code_com			135
+#define OBJ_ms_code_com			1L,3L,6L,1L,4L,1L,311L,2L,1L,22L
+
+#define SN_ms_ctl_sign			"msCTLSign"
+#define LN_ms_ctl_sign			"Microsoft Trust List Signing"
+#define NID_ms_ctl_sign			136
+#define OBJ_ms_ctl_sign			1L,3L,6L,1L,4L,1L,311L,10L,3L,1L
+
+#define SN_ms_sgc			"msSGC"
+#define LN_ms_sgc			"Microsoft Server Gated Crypto"
+#define NID_ms_sgc			137
+#define OBJ_ms_sgc			1L,3L,6L,1L,4L,1L,311L,10L,3L,3L
+
+#define SN_ms_efs			"msEFS"
+#define LN_ms_efs			"Microsoft Encrypted File System"
+#define NID_ms_efs			138
+#define OBJ_ms_efs			1L,3L,6L,1L,4L,1L,311L,10L,3L,4L
+
+/* Additional usage: Netscape */
+
+#define SN_ns_sgc			"nsSGC"
+#define LN_ns_sgc			"Netscape Server Gated Crypto"
+#define NID_ns_sgc			139
+#define OBJ_ns_sgc			OBJ_netscape,4L,1L
+
+#define SN_delta_crl			"deltaCRL"
+#define LN_delta_crl			"X509v3 Delta CRL Indicator"
+#define NID_delta_crl			140
+#define OBJ_delta_crl			OBJ_id_ce,27L
+
+#define SN_crl_reason			"CRLReason"
+#define LN_crl_reason			"CRL Reason Code"
+#define NID_crl_reason			141
+#define OBJ_crl_reason			OBJ_id_ce,21L
+
+#define SN_invalidity_date		"invalidityDate"
+#define LN_invalidity_date		"Invalidity Date"
+#define NID_invalidity_date		142
+#define OBJ_invalidity_date		OBJ_id_ce,24L
+
+#define SN_sxnet			"SXNetID"
+#define LN_sxnet			"Strong Extranet ID"
+#define NID_sxnet			143
+#define OBJ_sxnet			1L,3L,101L,1L,4L,1L
+
+/* PKCS12 and related OBJECT IDENTIFIERS */
+
+#define OBJ_pkcs12			OBJ_pkcs,12L
+#define OBJ_pkcs12_pbeids		OBJ_pkcs12, 1
+
+#define SN_pbe_WithSHA1And128BitRC4	"PBE-SHA1-RC4-128"
+#define LN_pbe_WithSHA1And128BitRC4	"pbeWithSHA1And128BitRC4"
+#define NID_pbe_WithSHA1And128BitRC4	144
+#define OBJ_pbe_WithSHA1And128BitRC4	OBJ_pkcs12_pbeids, 1L
+
+#define SN_pbe_WithSHA1And40BitRC4	"PBE-SHA1-RC4-40"
+#define LN_pbe_WithSHA1And40BitRC4	"pbeWithSHA1And40BitRC4"
+#define NID_pbe_WithSHA1And40BitRC4	145
+#define OBJ_pbe_WithSHA1And40BitRC4	OBJ_pkcs12_pbeids, 2L
+
+#define SN_pbe_WithSHA1And3_Key_TripleDES_CBC	"PBE-SHA1-3DES"
+#define LN_pbe_WithSHA1And3_Key_TripleDES_CBC	"pbeWithSHA1And3-KeyTripleDES-CBC"
+#define NID_pbe_WithSHA1And3_Key_TripleDES_CBC	146
+#define OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC	OBJ_pkcs12_pbeids, 3L
+
+#define SN_pbe_WithSHA1And2_Key_TripleDES_CBC	"PBE-SHA1-2DES"
+#define LN_pbe_WithSHA1And2_Key_TripleDES_CBC	"pbeWithSHA1And2-KeyTripleDES-CBC"
+#define NID_pbe_WithSHA1And2_Key_TripleDES_CBC	147
+#define OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC	OBJ_pkcs12_pbeids, 4L
+
+#define SN_pbe_WithSHA1And128BitRC2_CBC		"PBE-SHA1-RC2-128"
+#define LN_pbe_WithSHA1And128BitRC2_CBC		"pbeWithSHA1And128BitRC2-CBC"
+#define NID_pbe_WithSHA1And128BitRC2_CBC	148
+#define OBJ_pbe_WithSHA1And128BitRC2_CBC	OBJ_pkcs12_pbeids, 5L
+
+#define SN_pbe_WithSHA1And40BitRC2_CBC	"PBE-SHA1-RC2-40"
+#define LN_pbe_WithSHA1And40BitRC2_CBC	"pbeWithSHA1And40BitRC2-CBC"
+#define NID_pbe_WithSHA1And40BitRC2_CBC	149
+#define OBJ_pbe_WithSHA1And40BitRC2_CBC	OBJ_pkcs12_pbeids, 6L
+
+#define OBJ_pkcs12_Version1	OBJ_pkcs12, 10L
+
+#define OBJ_pkcs12_BagIds	OBJ_pkcs12_Version1, 1L
+
+#define LN_keyBag		"keyBag"
+#define NID_keyBag		150
+#define OBJ_keyBag		OBJ_pkcs12_BagIds, 1L
+
+#define LN_pkcs8ShroudedKeyBag	"pkcs8ShroudedKeyBag"
+#define NID_pkcs8ShroudedKeyBag	151
+#define OBJ_pkcs8ShroudedKeyBag	OBJ_pkcs12_BagIds, 2L
+
+#define LN_certBag		"certBag"
+#define NID_certBag		152
+#define OBJ_certBag		OBJ_pkcs12_BagIds, 3L
+
+#define LN_crlBag		"crlBag"
+#define NID_crlBag		153
+#define OBJ_crlBag		OBJ_pkcs12_BagIds, 4L
+
+#define LN_secretBag		"secretBag"
+#define NID_secretBag		154
+#define OBJ_secretBag		OBJ_pkcs12_BagIds, 5L
+
+#define LN_safeContentsBag	"safeContentsBag"
+#define NID_safeContentsBag	155
+#define OBJ_safeContentsBag	OBJ_pkcs12_BagIds, 6L
+
+#define LN_friendlyName		"friendlyName"
+#define	NID_friendlyName	156
+#define OBJ_friendlyName	OBJ_pkcs9, 20L
+
+#define LN_localKeyID		"localKeyID"
+#define	NID_localKeyID		157
+#define OBJ_localKeyID		OBJ_pkcs9, 21L
+
+#define OBJ_certTypes		OBJ_pkcs9, 22L
+
+#define LN_x509Certificate	"x509Certificate"
+#define	NID_x509Certificate	158
+#define OBJ_x509Certificate	OBJ_certTypes, 1L
+
+#define LN_sdsiCertificate	"sdsiCertificate"
+#define	NID_sdsiCertificate	159
+#define OBJ_sdsiCertificate	OBJ_certTypes, 2L
+
+#define OBJ_crlTypes		OBJ_pkcs9, 23L
+
+#define LN_x509Crl		"x509Crl"
+#define	NID_x509Crl		160
+#define OBJ_x509Crl		OBJ_crlTypes, 1L
+
+/* PKCS#5 v2 OIDs */
+
+#define LN_pbes2		"PBES2"
+#define NID_pbes2		161
+#define OBJ_pbes2		OBJ_pkcs,5L,13L
+
+#define LN_pbmac1		"PBMAC1"
+#define NID_pbmac1		162
+#define OBJ_pbmac1		OBJ_pkcs,5L,14L
+
+#define LN_hmacWithSHA1		"hmacWithSHA1"
+#define NID_hmacWithSHA1	163
+#define OBJ_hmacWithSHA1	OBJ_rsadsi,2L,7L
+
+/* Policy Qualifier Ids */
+
+#define LN_id_qt_cps		"Policy Qualifier CPS"
+#define SN_id_qt_cps		"id-qt-cps"
+#define NID_id_qt_cps		164
+#define OBJ_id_qt_cps		OBJ_id_pkix,2L,1L
+
+#define LN_id_qt_unotice	"Policy Qualifier User Notice"
+#define SN_id_qt_unotice	"id-qt-unotice"
+#define NID_id_qt_unotice	165
+#define OBJ_id_qt_unotice	OBJ_id_pkix,2L,2L
+
+#define SN_rc2_64_cbc			"RC2-64-CBC"
+#define LN_rc2_64_cbc			"rc2-64-cbc"
+#define NID_rc2_64_cbc			166
+
+#define SN_SMIMECapabilities		"SMIME-CAPS"
+#define LN_SMIMECapabilities		"S/MIME Capabilities"
+#define NID_SMIMECapabilities		167
+#define OBJ_SMIMECapabilities		OBJ_pkcs9,15L
+
+#define SN_pbeWithMD2AndRC2_CBC		"PBE-MD2-RC2-64"
+#define LN_pbeWithMD2AndRC2_CBC		"pbeWithMD2AndRC2-CBC"
+#define NID_pbeWithMD2AndRC2_CBC	168
+#define OBJ_pbeWithMD2AndRC2_CBC	OBJ_pkcs,5L,4L
+
+#define SN_pbeWithMD5AndRC2_CBC		"PBE-MD5-RC2-64"
+#define LN_pbeWithMD5AndRC2_CBC		"pbeWithMD5AndRC2-CBC"
+#define NID_pbeWithMD5AndRC2_CBC	169
+#define OBJ_pbeWithMD5AndRC2_CBC	OBJ_pkcs,5L,6L
+
+#define SN_pbeWithSHA1AndDES_CBC	"PBE-SHA1-DES"
+#define LN_pbeWithSHA1AndDES_CBC	"pbeWithSHA1AndDES-CBC"
+#define NID_pbeWithSHA1AndDES_CBC	170
+#define OBJ_pbeWithSHA1AndDES_CBC	OBJ_pkcs,5L,10L
+
+/* Extension request OIDs */
+
+#define LN_ms_ext_req			"Microsoft Extension Request"
+#define SN_ms_ext_req			"msExtReq"
+#define NID_ms_ext_req			171
+#define OBJ_ms_ext_req			1L,3L,6L,1L,4L,1L,311L,2L,1L,14L
+
+#define LN_ext_req			"Extension Request"
+#define SN_ext_req			"extReq"
+#define NID_ext_req			172
+#define OBJ_ext_req			OBJ_pkcs9,14L
+
+#define SN_name				"name"
+#define LN_name				"name"
+#define NID_name			173
+#define OBJ_name			OBJ_X509,41L
+
+#define SN_dnQualifier			"dnQualifier"
+#define LN_dnQualifier			"dnQualifier"
+#define NID_dnQualifier			174
+#define OBJ_dnQualifier			OBJ_X509,46L
+
+#define SN_id_pe			"id-pe"
+#define NID_id_pe			175
+#define OBJ_id_pe			OBJ_id_pkix,1L
+
+#define SN_id_ad			"id-ad"
+#define NID_id_ad			176
+#define OBJ_id_ad			OBJ_id_pkix,48L
+
+#define SN_info_access			"authorityInfoAccess"
+#define LN_info_access			"Authority Information Access"
+#define NID_info_access			177
+#define OBJ_info_access			OBJ_id_pe,1L
+
+#define SN_ad_OCSP			"OCSP"
+#define LN_ad_OCSP			"OCSP"
+#define NID_ad_OCSP			178
+#define OBJ_ad_OCSP			OBJ_id_ad,1L
+
+#define SN_ad_ca_issuers		"caIssuers"
+#define LN_ad_ca_issuers		"CA Issuers"
+#define NID_ad_ca_issuers		179
+#define OBJ_ad_ca_issuers		OBJ_id_ad,2L
+
+#define SN_OCSP_sign			"OCSPSigning"
+#define LN_OCSP_sign			"OCSP Signing"
+#define NID_OCSP_sign			180
+#define OBJ_OCSP_sign			OBJ_id_kp,9L
+#endif /* USE_OBJ_MAC */
+
+#include 
+#include 
+
+#define	OBJ_NAME_TYPE_UNDEF		0x00
+#define	OBJ_NAME_TYPE_MD_METH		0x01
+#define	OBJ_NAME_TYPE_CIPHER_METH	0x02
+#define	OBJ_NAME_TYPE_PKEY_METH		0x03
+#define	OBJ_NAME_TYPE_COMP_METH		0x04
+#define	OBJ_NAME_TYPE_NUM		0x05
+
+#define	OBJ_NAME_ALIAS			0x8000
+
+#define OBJ_BSEARCH_VALUE_ON_NOMATCH		0x01
+#define OBJ_BSEARCH_FIRST_VALUE_ON_MATCH	0x02
+
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+typedef struct obj_name_st
+	{
+	int type;
+	int alias;
+	const char *name;
+	const char *data;
+	} OBJ_NAME;
+
+#define		OBJ_create_and_add_object(a,b,c) OBJ_create(a,b,c)
+
+
+int OBJ_NAME_init(void);
+int OBJ_NAME_new_index(unsigned long (*hash_func)(const char *),
+		       int (*cmp_func)(const char *, const char *),
+		       void (*free_func)(const char *, int, const char *));
+const char *OBJ_NAME_get(const char *name,int type);
+int OBJ_NAME_add(const char *name,int type,const char *data);
+int OBJ_NAME_remove(const char *name,int type);
+void OBJ_NAME_cleanup(int type); /* -1 for everything */
+void OBJ_NAME_do_all(int type,void (*fn)(const OBJ_NAME *,void *arg),
+		     void *arg);
+void OBJ_NAME_do_all_sorted(int type,void (*fn)(const OBJ_NAME *,void *arg),
+			    void *arg);
+
+ASN1_OBJECT *	OBJ_dup(const ASN1_OBJECT *o);
+ASN1_OBJECT *	OBJ_nid2obj(int n);
+const char *	OBJ_nid2ln(int n);
+const char *	OBJ_nid2sn(int n);
+int		OBJ_obj2nid(const ASN1_OBJECT *o);
+ASN1_OBJECT *	OBJ_txt2obj(const char *s, int no_name);
+int	OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name);
+int		OBJ_txt2nid(const char *s);
+int		OBJ_ln2nid(const char *s);
+int		OBJ_sn2nid(const char *s);
+int		OBJ_cmp(const ASN1_OBJECT *a,const ASN1_OBJECT *b);
+const char *	OBJ_bsearch(const char *key,const char *base,int num,int size,
+	int (*cmp)(const void *, const void *));
+const char *	OBJ_bsearch_ex(const char *key,const char *base,int num,
+	int size, int (*cmp)(const void *, const void *), int flags);
+
+int		OBJ_new_nid(int num);
+int		OBJ_add_object(const ASN1_OBJECT *obj);
+int		OBJ_create(const char *oid,const char *sn,const char *ln);
+void		OBJ_cleanup(void );
+int		OBJ_create_objects(BIO *in);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_OBJ_strings(void);
+
+/* Error codes for the OBJ functions. */
+
+/* Function codes. */
+#define OBJ_F_OBJ_ADD_OBJECT				 105
+#define OBJ_F_OBJ_CREATE				 100
+#define OBJ_F_OBJ_DUP					 101
+#define OBJ_F_OBJ_NAME_NEW_INDEX			 106
+#define OBJ_F_OBJ_NID2LN				 102
+#define OBJ_F_OBJ_NID2OBJ				 103
+#define OBJ_F_OBJ_NID2SN				 104
+
+/* Reason codes. */
+#define OBJ_R_MALLOC_FAILURE				 100
+#define OBJ_R_UNKNOWN_NID				 101
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/dep/include/openssl/ocsp.h b/dep/include/openssl/ocsp.h
new file mode 100644
index 00000000000..53f3364af0c
--- /dev/null
+++ b/dep/include/openssl/ocsp.h
@@ -0,0 +1,614 @@
+/* ocsp.h */
+/* Written by Tom Titchener  for the OpenSSL
+ * project. */
+
+/* History:
+   This file was transfered to Richard Levitte from CertCo by Kathy
+   Weinhold in mid-spring 2000 to be included in OpenSSL or released
+   as a patch kit. */
+
+/* ====================================================================
+ * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_OCSP_H
+#define HEADER_OCSP_H
+
+#include 
+#include 
+#include 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* Various flags and values */
+
+#define OCSP_DEFAULT_NONCE_LENGTH	16
+
+#define OCSP_NOCERTS			0x1
+#define OCSP_NOINTERN			0x2
+#define OCSP_NOSIGS			0x4
+#define OCSP_NOCHAIN			0x8
+#define OCSP_NOVERIFY			0x10
+#define OCSP_NOEXPLICIT			0x20
+#define OCSP_NOCASIGN			0x40
+#define OCSP_NODELEGATED		0x80
+#define OCSP_NOCHECKS			0x100
+#define OCSP_TRUSTOTHER			0x200
+#define OCSP_RESPID_KEY			0x400
+#define OCSP_NOTIME			0x800
+
+/*   CertID ::= SEQUENCE {
+ *       hashAlgorithm            AlgorithmIdentifier,
+ *       issuerNameHash     OCTET STRING, -- Hash of Issuer's DN
+ *       issuerKeyHash      OCTET STRING, -- Hash of Issuers public key (excluding the tag & length fields)
+ *       serialNumber       CertificateSerialNumber }
+ */
+typedef struct ocsp_cert_id_st
+	{
+	X509_ALGOR *hashAlgorithm;
+	ASN1_OCTET_STRING *issuerNameHash;
+	ASN1_OCTET_STRING *issuerKeyHash;
+	ASN1_INTEGER *serialNumber;
+	} OCSP_CERTID;
+
+DECLARE_STACK_OF(OCSP_CERTID)
+
+/*   Request ::=     SEQUENCE {
+ *       reqCert                    CertID,
+ *       singleRequestExtensions    [0] EXPLICIT Extensions OPTIONAL }
+ */
+typedef struct ocsp_one_request_st
+	{
+	OCSP_CERTID *reqCert;
+	STACK_OF(X509_EXTENSION) *singleRequestExtensions;
+	} OCSP_ONEREQ;
+
+DECLARE_STACK_OF(OCSP_ONEREQ)
+DECLARE_ASN1_SET_OF(OCSP_ONEREQ)
+
+
+/*   TBSRequest      ::=     SEQUENCE {
+ *       version             [0] EXPLICIT Version DEFAULT v1,
+ *       requestorName       [1] EXPLICIT GeneralName OPTIONAL,
+ *       requestList             SEQUENCE OF Request,
+ *       requestExtensions   [2] EXPLICIT Extensions OPTIONAL }
+ */
+typedef struct ocsp_req_info_st
+	{
+	ASN1_INTEGER *version;
+	GENERAL_NAME *requestorName;
+	STACK_OF(OCSP_ONEREQ) *requestList;
+	STACK_OF(X509_EXTENSION) *requestExtensions;
+	} OCSP_REQINFO;
+
+/*   Signature       ::=     SEQUENCE {
+ *       signatureAlgorithm   AlgorithmIdentifier,
+ *       signature            BIT STRING,
+ *       certs                [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
+ */
+typedef struct ocsp_signature_st
+	{
+	X509_ALGOR *signatureAlgorithm;
+	ASN1_BIT_STRING *signature;
+	STACK_OF(X509) *certs;
+	} OCSP_SIGNATURE;
+
+/*   OCSPRequest     ::=     SEQUENCE {
+ *       tbsRequest                  TBSRequest,
+ *       optionalSignature   [0]     EXPLICIT Signature OPTIONAL }
+ */
+typedef struct ocsp_request_st
+	{
+	OCSP_REQINFO *tbsRequest;
+	OCSP_SIGNATURE *optionalSignature; /* OPTIONAL */
+	} OCSP_REQUEST;
+
+/*   OCSPResponseStatus ::= ENUMERATED {
+ *       successful            (0),      --Response has valid confirmations
+ *       malformedRequest      (1),      --Illegal confirmation request
+ *       internalError         (2),      --Internal error in issuer
+ *       tryLater              (3),      --Try again later
+ *                                       --(4) is not used
+ *       sigRequired           (5),      --Must sign the request
+ *       unauthorized          (6)       --Request unauthorized
+ *   }
+ */
+#define OCSP_RESPONSE_STATUS_SUCCESSFUL          0
+#define OCSP_RESPONSE_STATUS_MALFORMEDREQUEST     1
+#define OCSP_RESPONSE_STATUS_INTERNALERROR        2
+#define OCSP_RESPONSE_STATUS_TRYLATER             3
+#define OCSP_RESPONSE_STATUS_SIGREQUIRED          5
+#define OCSP_RESPONSE_STATUS_UNAUTHORIZED         6
+
+/*   ResponseBytes ::=       SEQUENCE {
+ *       responseType   OBJECT IDENTIFIER,
+ *       response       OCTET STRING }
+ */
+typedef struct ocsp_resp_bytes_st
+	{
+	ASN1_OBJECT *responseType;
+	ASN1_OCTET_STRING *response;
+	} OCSP_RESPBYTES;
+
+/*   OCSPResponse ::= SEQUENCE {
+ *      responseStatus         OCSPResponseStatus,
+ *      responseBytes          [0] EXPLICIT ResponseBytes OPTIONAL }
+ */
+typedef struct ocsp_response_st
+	{
+	ASN1_ENUMERATED *responseStatus;
+	OCSP_RESPBYTES  *responseBytes;
+	} OCSP_RESPONSE;
+
+/*   ResponderID ::= CHOICE {
+ *      byName   [1] Name,
+ *      byKey    [2] KeyHash }
+ */
+#define V_OCSP_RESPID_NAME 0
+#define V_OCSP_RESPID_KEY  1
+typedef struct ocsp_responder_id_st
+	{
+	int type;
+	union   {
+		X509_NAME* byName;
+        	ASN1_OCTET_STRING *byKey;
+		} value;
+	} OCSP_RESPID;
+/*   KeyHash ::= OCTET STRING --SHA-1 hash of responder's public key
+ *                            --(excluding the tag and length fields)
+ */
+
+/*   RevokedInfo ::= SEQUENCE {
+ *       revocationTime              GeneralizedTime,
+ *       revocationReason    [0]     EXPLICIT CRLReason OPTIONAL }
+ */
+typedef struct ocsp_revoked_info_st
+	{
+	ASN1_GENERALIZEDTIME *revocationTime;
+	ASN1_ENUMERATED *revocationReason;
+	} OCSP_REVOKEDINFO;
+
+/*   CertStatus ::= CHOICE {
+ *       good                [0]     IMPLICIT NULL,
+ *       revoked             [1]     IMPLICIT RevokedInfo,
+ *       unknown             [2]     IMPLICIT UnknownInfo }
+ */
+#define V_OCSP_CERTSTATUS_GOOD    0
+#define V_OCSP_CERTSTATUS_REVOKED 1
+#define V_OCSP_CERTSTATUS_UNKNOWN 2
+typedef struct ocsp_cert_status_st
+	{
+	int type;
+	union	{
+		ASN1_NULL *good;
+		OCSP_REVOKEDINFO *revoked;
+		ASN1_NULL *unknown;
+		} value;
+	} OCSP_CERTSTATUS;
+
+/*   SingleResponse ::= SEQUENCE {
+ *      certID                       CertID,
+ *      certStatus                   CertStatus,
+ *      thisUpdate                   GeneralizedTime,
+ *      nextUpdate           [0]     EXPLICIT GeneralizedTime OPTIONAL,
+ *      singleExtensions     [1]     EXPLICIT Extensions OPTIONAL }
+ */
+typedef struct ocsp_single_response_st
+	{
+	OCSP_CERTID *certId;
+	OCSP_CERTSTATUS *certStatus;
+	ASN1_GENERALIZEDTIME *thisUpdate;
+	ASN1_GENERALIZEDTIME *nextUpdate;
+	STACK_OF(X509_EXTENSION) *singleExtensions;
+	} OCSP_SINGLERESP;
+
+DECLARE_STACK_OF(OCSP_SINGLERESP)
+DECLARE_ASN1_SET_OF(OCSP_SINGLERESP)
+
+/*   ResponseData ::= SEQUENCE {
+ *      version              [0] EXPLICIT Version DEFAULT v1,
+ *      responderID              ResponderID,
+ *      producedAt               GeneralizedTime,
+ *      responses                SEQUENCE OF SingleResponse,
+ *      responseExtensions   [1] EXPLICIT Extensions OPTIONAL }
+ */
+typedef struct ocsp_response_data_st
+	{
+	ASN1_INTEGER *version;
+	OCSP_RESPID  *responderId;
+	ASN1_GENERALIZEDTIME *producedAt;
+	STACK_OF(OCSP_SINGLERESP) *responses;
+	STACK_OF(X509_EXTENSION) *responseExtensions;
+	} OCSP_RESPDATA;
+
+/*   BasicOCSPResponse       ::= SEQUENCE {
+ *      tbsResponseData      ResponseData,
+ *      signatureAlgorithm   AlgorithmIdentifier,
+ *      signature            BIT STRING,
+ *      certs                [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
+ */
+  /* Note 1:
+     The value for "signature" is specified in the OCSP rfc2560 as follows:
+     "The value for the signature SHALL be computed on the hash of the DER
+     encoding ResponseData."  This means that you must hash the DER-encoded
+     tbsResponseData, and then run it through a crypto-signing function, which
+     will (at least w/RSA) do a hash-'n'-private-encrypt operation.  This seems
+     a bit odd, but that's the spec.  Also note that the data structures do not
+     leave anywhere to independently specify the algorithm used for the initial
+     hash. So, we look at the signature-specification algorithm, and try to do
+     something intelligent.	-- Kathy Weinhold, CertCo */
+  /* Note 2:
+     It seems that the mentioned passage from RFC 2560 (section 4.2.1) is open
+     for interpretation.  I've done tests against another responder, and found
+     that it doesn't do the double hashing that the RFC seems to say one
+     should.  Therefore, all relevant functions take a flag saying which
+     variant should be used.	-- Richard Levitte, OpenSSL team and CeloCom */
+typedef struct ocsp_basic_response_st
+	{
+	OCSP_RESPDATA *tbsResponseData;
+	X509_ALGOR *signatureAlgorithm;
+	ASN1_BIT_STRING *signature;
+	STACK_OF(X509) *certs;
+	} OCSP_BASICRESP;
+
+/*
+ *   CRLReason ::= ENUMERATED {
+ *        unspecified             (0),
+ *        keyCompromise           (1),
+ *        cACompromise            (2),
+ *        affiliationChanged      (3),
+ *        superseded              (4),
+ *        cessationOfOperation    (5),
+ *        certificateHold         (6),
+ *        removeFromCRL           (8) }
+ */
+#define OCSP_REVOKED_STATUS_NOSTATUS               -1
+#define OCSP_REVOKED_STATUS_UNSPECIFIED             0
+#define OCSP_REVOKED_STATUS_KEYCOMPROMISE           1
+#define OCSP_REVOKED_STATUS_CACOMPROMISE            2
+#define OCSP_REVOKED_STATUS_AFFILIATIONCHANGED      3
+#define OCSP_REVOKED_STATUS_SUPERSEDED              4
+#define OCSP_REVOKED_STATUS_CESSATIONOFOPERATION    5
+#define OCSP_REVOKED_STATUS_CERTIFICATEHOLD         6
+#define OCSP_REVOKED_STATUS_REMOVEFROMCRL           8
+
+/* CrlID ::= SEQUENCE {
+ *     crlUrl               [0]     EXPLICIT IA5String OPTIONAL,
+ *     crlNum               [1]     EXPLICIT INTEGER OPTIONAL,
+ *     crlTime              [2]     EXPLICIT GeneralizedTime OPTIONAL }
+ */
+typedef struct ocsp_crl_id_st
+        {
+	ASN1_IA5STRING *crlUrl;
+	ASN1_INTEGER *crlNum;
+	ASN1_GENERALIZEDTIME *crlTime;
+        } OCSP_CRLID;
+
+/* ServiceLocator ::= SEQUENCE {
+ *      issuer    Name,
+ *      locator   AuthorityInfoAccessSyntax OPTIONAL }
+ */
+typedef struct ocsp_service_locator_st
+        {
+	X509_NAME* issuer;
+	STACK_OF(ACCESS_DESCRIPTION) *locator;
+        } OCSP_SERVICELOC;
+ 
+#define PEM_STRING_OCSP_REQUEST	"OCSP REQUEST"
+#define PEM_STRING_OCSP_RESPONSE "OCSP RESPONSE"
+
+#define d2i_OCSP_REQUEST_bio(bp,p) ASN1_d2i_bio_of(OCSP_REQUEST,OCSP_REQUEST_new,d2i_OCSP_REQUEST,bp,p)
+
+#define d2i_OCSP_RESPONSE_bio(bp,p) ASN1_d2i_bio_of(OCSP_RESPONSE,OCSP_RESPONSE_new,d2i_OCSP_RESPONSE,bp,p)
+
+#define	PEM_read_bio_OCSP_REQUEST(bp,x,cb) (OCSP_REQUEST *)PEM_ASN1_read_bio( \
+     (char *(*)())d2i_OCSP_REQUEST,PEM_STRING_OCSP_REQUEST,bp,(char **)x,cb,NULL)
+
+#define	PEM_read_bio_OCSP_RESPONSE(bp,x,cb)(OCSP_RESPONSE *)PEM_ASN1_read_bio(\
+     (char *(*)())d2i_OCSP_RESPONSE,PEM_STRING_OCSP_RESPONSE,bp,(char **)x,cb,NULL)
+
+#define PEM_write_bio_OCSP_REQUEST(bp,o) \
+    PEM_ASN1_write_bio((int (*)())i2d_OCSP_REQUEST,PEM_STRING_OCSP_REQUEST,\
+			bp,(char *)o, NULL,NULL,0,NULL,NULL)
+
+#define PEM_write_bio_OCSP_RESPONSE(bp,o) \
+    PEM_ASN1_write_bio((int (*)())i2d_OCSP_RESPONSE,PEM_STRING_OCSP_RESPONSE,\
+			bp,(char *)o, NULL,NULL,0,NULL,NULL)
+
+#define i2d_OCSP_RESPONSE_bio(bp,o) ASN1_i2d_bio_of(OCSP_RESPONSE,i2d_OCSP_RESPONSE,bp,o)
+
+#define i2d_OCSP_REQUEST_bio(bp,o) ASN1_i2d_bio_of(OCSP_REQUEST,i2d_OCSP_REQUEST,bp,o)
+
+#define OCSP_REQUEST_sign(o,pkey,md) \
+	ASN1_item_sign(ASN1_ITEM_rptr(OCSP_REQINFO),\
+		o->optionalSignature->signatureAlgorithm,NULL,\
+	        o->optionalSignature->signature,o->tbsRequest,pkey,md)
+
+#define OCSP_BASICRESP_sign(o,pkey,md,d) \
+	ASN1_item_sign(ASN1_ITEM_rptr(OCSP_RESPDATA),o->signatureAlgorithm,NULL,\
+		o->signature,o->tbsResponseData,pkey,md)
+
+#define OCSP_REQUEST_verify(a,r) ASN1_item_verify(ASN1_ITEM_rptr(OCSP_REQINFO),\
+        a->optionalSignature->signatureAlgorithm,\
+	a->optionalSignature->signature,a->tbsRequest,r)
+
+#define OCSP_BASICRESP_verify(a,r,d) ASN1_item_verify(ASN1_ITEM_rptr(OCSP_RESPDATA),\
+	a->signatureAlgorithm,a->signature,a->tbsResponseData,r)
+
+#define ASN1_BIT_STRING_digest(data,type,md,len) \
+	ASN1_item_digest(ASN1_ITEM_rptr(ASN1_BIT_STRING),type,data,md,len)
+
+#define OCSP_CERTID_dup(cid) ASN1_dup_of(OCSP_CERTID,i2d_OCSP_CERTID,d2i_OCSP_CERTID,cid)
+
+#define OCSP_CERTSTATUS_dup(cs)\
+                (OCSP_CERTSTATUS*)ASN1_dup((int(*)())i2d_OCSP_CERTSTATUS,\
+		(char *(*)())d2i_OCSP_CERTSTATUS,(char *)(cs))
+
+OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, char *path, OCSP_REQUEST *req);
+
+OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, X509 *subject, X509 *issuer);
+
+OCSP_CERTID *OCSP_cert_id_new(const EVP_MD *dgst, 
+			      X509_NAME *issuerName, 
+			      ASN1_BIT_STRING* issuerKey, 
+			      ASN1_INTEGER *serialNumber);
+
+OCSP_ONEREQ *OCSP_request_add0_id(OCSP_REQUEST *req, OCSP_CERTID *cid);
+
+int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len);
+int OCSP_basic_add1_nonce(OCSP_BASICRESP *resp, unsigned char *val, int len);
+int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs);
+int OCSP_copy_nonce(OCSP_BASICRESP *resp, OCSP_REQUEST *req);
+
+int OCSP_request_set1_name(OCSP_REQUEST *req, X509_NAME *nm);
+int OCSP_request_add1_cert(OCSP_REQUEST *req, X509 *cert);
+
+int OCSP_request_sign(OCSP_REQUEST   *req,
+		      X509           *signer,
+		      EVP_PKEY       *key,
+		      const EVP_MD   *dgst,
+		      STACK_OF(X509) *certs,
+		      unsigned long flags);
+
+int OCSP_response_status(OCSP_RESPONSE *resp);
+OCSP_BASICRESP *OCSP_response_get1_basic(OCSP_RESPONSE *resp);
+
+int OCSP_resp_count(OCSP_BASICRESP *bs);
+OCSP_SINGLERESP *OCSP_resp_get0(OCSP_BASICRESP *bs, int idx);
+int OCSP_resp_find(OCSP_BASICRESP *bs, OCSP_CERTID *id, int last);
+int OCSP_single_get0_status(OCSP_SINGLERESP *single, int *reason,
+				ASN1_GENERALIZEDTIME **revtime,
+				ASN1_GENERALIZEDTIME **thisupd,
+				ASN1_GENERALIZEDTIME **nextupd);
+int OCSP_resp_find_status(OCSP_BASICRESP *bs, OCSP_CERTID *id, int *status,
+				int *reason,
+				ASN1_GENERALIZEDTIME **revtime,
+				ASN1_GENERALIZEDTIME **thisupd,
+				ASN1_GENERALIZEDTIME **nextupd);
+int OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd,
+			ASN1_GENERALIZEDTIME *nextupd,
+			long sec, long maxsec);
+
+int OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs, X509_STORE *store, unsigned long flags);
+
+int OCSP_parse_url(char *url, char **phost, char **pport, char **ppath, int *pssl);
+
+int OCSP_id_issuer_cmp(OCSP_CERTID *a, OCSP_CERTID *b);
+int OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b);
+
+int OCSP_request_onereq_count(OCSP_REQUEST *req);
+OCSP_ONEREQ *OCSP_request_onereq_get0(OCSP_REQUEST *req, int i);
+OCSP_CERTID *OCSP_onereq_get0_id(OCSP_ONEREQ *one);
+int OCSP_id_get0_info(ASN1_OCTET_STRING **piNameHash, ASN1_OBJECT **pmd,
+			ASN1_OCTET_STRING **pikeyHash,
+			ASN1_INTEGER **pserial, OCSP_CERTID *cid);
+int OCSP_request_is_signed(OCSP_REQUEST *req);
+OCSP_RESPONSE *OCSP_response_create(int status, OCSP_BASICRESP *bs);
+OCSP_SINGLERESP *OCSP_basic_add1_status(OCSP_BASICRESP *rsp,
+						OCSP_CERTID *cid,
+						int status, int reason,
+						ASN1_TIME *revtime,
+					ASN1_TIME *thisupd, ASN1_TIME *nextupd);
+int OCSP_basic_add1_cert(OCSP_BASICRESP *resp, X509 *cert);
+int OCSP_basic_sign(OCSP_BASICRESP *brsp, 
+			X509 *signer, EVP_PKEY *key, const EVP_MD *dgst,
+			STACK_OF(X509) *certs, unsigned long flags);
+
+ASN1_STRING *ASN1_STRING_encode(ASN1_STRING *s, i2d_of_void *i2d,
+				void *data, STACK_OF(ASN1_OBJECT) *sk);
+#define ASN1_STRING_encode_of(type,s,i2d,data,sk) \
+((ASN1_STRING *(*)(ASN1_STRING *,I2D_OF(type),type *,STACK_OF(ASN1_OBJECT) *))openssl_fcast(ASN1_STRING_encode))(s,i2d,data,sk)
+
+X509_EXTENSION *OCSP_crlID_new(char *url, long *n, char *tim);
+
+X509_EXTENSION *OCSP_accept_responses_new(char **oids);
+
+X509_EXTENSION *OCSP_archive_cutoff_new(char* tim);
+
+X509_EXTENSION *OCSP_url_svcloc_new(X509_NAME* issuer, char **urls);
+
+int OCSP_REQUEST_get_ext_count(OCSP_REQUEST *x);
+int OCSP_REQUEST_get_ext_by_NID(OCSP_REQUEST *x, int nid, int lastpos);
+int OCSP_REQUEST_get_ext_by_OBJ(OCSP_REQUEST *x, ASN1_OBJECT *obj, int lastpos);
+int OCSP_REQUEST_get_ext_by_critical(OCSP_REQUEST *x, int crit, int lastpos);
+X509_EXTENSION *OCSP_REQUEST_get_ext(OCSP_REQUEST *x, int loc);
+X509_EXTENSION *OCSP_REQUEST_delete_ext(OCSP_REQUEST *x, int loc);
+void *OCSP_REQUEST_get1_ext_d2i(OCSP_REQUEST *x, int nid, int *crit, int *idx);
+int OCSP_REQUEST_add1_ext_i2d(OCSP_REQUEST *x, int nid, void *value, int crit,
+							unsigned long flags);
+int OCSP_REQUEST_add_ext(OCSP_REQUEST *x, X509_EXTENSION *ex, int loc);
+
+int OCSP_ONEREQ_get_ext_count(OCSP_ONEREQ *x);
+int OCSP_ONEREQ_get_ext_by_NID(OCSP_ONEREQ *x, int nid, int lastpos);
+int OCSP_ONEREQ_get_ext_by_OBJ(OCSP_ONEREQ *x, ASN1_OBJECT *obj, int lastpos);
+int OCSP_ONEREQ_get_ext_by_critical(OCSP_ONEREQ *x, int crit, int lastpos);
+X509_EXTENSION *OCSP_ONEREQ_get_ext(OCSP_ONEREQ *x, int loc);
+X509_EXTENSION *OCSP_ONEREQ_delete_ext(OCSP_ONEREQ *x, int loc);
+void *OCSP_ONEREQ_get1_ext_d2i(OCSP_ONEREQ *x, int nid, int *crit, int *idx);
+int OCSP_ONEREQ_add1_ext_i2d(OCSP_ONEREQ *x, int nid, void *value, int crit,
+							unsigned long flags);
+int OCSP_ONEREQ_add_ext(OCSP_ONEREQ *x, X509_EXTENSION *ex, int loc);
+
+int OCSP_BASICRESP_get_ext_count(OCSP_BASICRESP *x);
+int OCSP_BASICRESP_get_ext_by_NID(OCSP_BASICRESP *x, int nid, int lastpos);
+int OCSP_BASICRESP_get_ext_by_OBJ(OCSP_BASICRESP *x, ASN1_OBJECT *obj, int lastpos);
+int OCSP_BASICRESP_get_ext_by_critical(OCSP_BASICRESP *x, int crit, int lastpos);
+X509_EXTENSION *OCSP_BASICRESP_get_ext(OCSP_BASICRESP *x, int loc);
+X509_EXTENSION *OCSP_BASICRESP_delete_ext(OCSP_BASICRESP *x, int loc);
+void *OCSP_BASICRESP_get1_ext_d2i(OCSP_BASICRESP *x, int nid, int *crit, int *idx);
+int OCSP_BASICRESP_add1_ext_i2d(OCSP_BASICRESP *x, int nid, void *value, int crit,
+							unsigned long flags);
+int OCSP_BASICRESP_add_ext(OCSP_BASICRESP *x, X509_EXTENSION *ex, int loc);
+
+int OCSP_SINGLERESP_get_ext_count(OCSP_SINGLERESP *x);
+int OCSP_SINGLERESP_get_ext_by_NID(OCSP_SINGLERESP *x, int nid, int lastpos);
+int OCSP_SINGLERESP_get_ext_by_OBJ(OCSP_SINGLERESP *x, ASN1_OBJECT *obj, int lastpos);
+int OCSP_SINGLERESP_get_ext_by_critical(OCSP_SINGLERESP *x, int crit, int lastpos);
+X509_EXTENSION *OCSP_SINGLERESP_get_ext(OCSP_SINGLERESP *x, int loc);
+X509_EXTENSION *OCSP_SINGLERESP_delete_ext(OCSP_SINGLERESP *x, int loc);
+void *OCSP_SINGLERESP_get1_ext_d2i(OCSP_SINGLERESP *x, int nid, int *crit, int *idx);
+int OCSP_SINGLERESP_add1_ext_i2d(OCSP_SINGLERESP *x, int nid, void *value, int crit,
+							unsigned long flags);
+int OCSP_SINGLERESP_add_ext(OCSP_SINGLERESP *x, X509_EXTENSION *ex, int loc);
+
+DECLARE_ASN1_FUNCTIONS(OCSP_SINGLERESP)
+DECLARE_ASN1_FUNCTIONS(OCSP_CERTSTATUS)
+DECLARE_ASN1_FUNCTIONS(OCSP_REVOKEDINFO)
+DECLARE_ASN1_FUNCTIONS(OCSP_BASICRESP)
+DECLARE_ASN1_FUNCTIONS(OCSP_RESPDATA)
+DECLARE_ASN1_FUNCTIONS(OCSP_RESPID)
+DECLARE_ASN1_FUNCTIONS(OCSP_RESPONSE)
+DECLARE_ASN1_FUNCTIONS(OCSP_RESPBYTES)
+DECLARE_ASN1_FUNCTIONS(OCSP_ONEREQ)
+DECLARE_ASN1_FUNCTIONS(OCSP_CERTID)
+DECLARE_ASN1_FUNCTIONS(OCSP_REQUEST)
+DECLARE_ASN1_FUNCTIONS(OCSP_SIGNATURE)
+DECLARE_ASN1_FUNCTIONS(OCSP_REQINFO)
+DECLARE_ASN1_FUNCTIONS(OCSP_CRLID)
+DECLARE_ASN1_FUNCTIONS(OCSP_SERVICELOC)
+
+char *OCSP_response_status_str(long s);
+char *OCSP_cert_status_str(long s);
+char *OCSP_crl_reason_str(long s);
+
+int OCSP_REQUEST_print(BIO *bp, OCSP_REQUEST* a, unsigned long flags);
+int OCSP_RESPONSE_print(BIO *bp, OCSP_RESPONSE* o, unsigned long flags);
+
+int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
+				X509_STORE *st, unsigned long flags);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_OCSP_strings(void);
+
+/* Error codes for the OCSP functions. */
+
+/* Function codes. */
+#define OCSP_F_ASN1_STRING_ENCODE			 100
+#define OCSP_F_D2I_OCSP_NONCE				 102
+#define OCSP_F_OCSP_BASIC_ADD1_STATUS			 103
+#define OCSP_F_OCSP_BASIC_SIGN				 104
+#define OCSP_F_OCSP_BASIC_VERIFY			 105
+#define OCSP_F_OCSP_CERT_ID_NEW				 101
+#define OCSP_F_OCSP_CHECK_DELEGATED			 106
+#define OCSP_F_OCSP_CHECK_IDS				 107
+#define OCSP_F_OCSP_CHECK_ISSUER			 108
+#define OCSP_F_OCSP_CHECK_VALIDITY			 115
+#define OCSP_F_OCSP_MATCH_ISSUERID			 109
+#define OCSP_F_OCSP_PARSE_URL				 114
+#define OCSP_F_OCSP_REQUEST_SIGN			 110
+#define OCSP_F_OCSP_REQUEST_VERIFY			 116
+#define OCSP_F_OCSP_RESPONSE_GET1_BASIC			 111
+#define OCSP_F_OCSP_SENDREQ_BIO				 112
+#define OCSP_F_REQUEST_VERIFY				 113
+
+/* Reason codes. */
+#define OCSP_R_BAD_DATA					 100
+#define OCSP_R_CERTIFICATE_VERIFY_ERROR			 101
+#define OCSP_R_DIGEST_ERR				 102
+#define OCSP_R_ERROR_IN_NEXTUPDATE_FIELD		 122
+#define OCSP_R_ERROR_IN_THISUPDATE_FIELD		 123
+#define OCSP_R_ERROR_PARSING_URL			 121
+#define OCSP_R_MISSING_OCSPSIGNING_USAGE		 103
+#define OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE		 124
+#define OCSP_R_NOT_BASIC_RESPONSE			 104
+#define OCSP_R_NO_CERTIFICATES_IN_CHAIN			 105
+#define OCSP_R_NO_CONTENT				 106
+#define OCSP_R_NO_PUBLIC_KEY				 107
+#define OCSP_R_NO_RESPONSE_DATA				 108
+#define OCSP_R_NO_REVOKED_TIME				 109
+#define OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE	 110
+#define OCSP_R_REQUEST_NOT_SIGNED			 128
+#define OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA	 111
+#define OCSP_R_ROOT_CA_NOT_TRUSTED			 112
+#define OCSP_R_SERVER_READ_ERROR			 113
+#define OCSP_R_SERVER_RESPONSE_ERROR			 114
+#define OCSP_R_SERVER_RESPONSE_PARSE_ERROR		 115
+#define OCSP_R_SERVER_WRITE_ERROR			 116
+#define OCSP_R_SIGNATURE_FAILURE			 117
+#define OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND		 118
+#define OCSP_R_STATUS_EXPIRED				 125
+#define OCSP_R_STATUS_NOT_YET_VALID			 126
+#define OCSP_R_STATUS_TOO_OLD				 127
+#define OCSP_R_UNKNOWN_MESSAGE_DIGEST			 119
+#define OCSP_R_UNKNOWN_NID				 120
+#define OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE		 129
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/dep/include/openssl/opensslconf.h b/dep/include/openssl/opensslconf.h
new file mode 100644
index 00000000000..4620e0e530e
--- /dev/null
+++ b/dep/include/openssl/opensslconf.h
@@ -0,0 +1,214 @@
+/* opensslconf.h */
+/* WARNING: Generated automatically from opensslconf.h.in by Configure. */
+
+/* OpenSSL was configured with the following options: */
+#ifndef OPENSSL_DOING_MAKEDEPEND
+
+#ifndef OPENSSL_NO_CAMELLIA
+# define OPENSSL_NO_CAMELLIA
+#endif
+#ifndef OPENSSL_NO_GMP
+# define OPENSSL_NO_GMP
+#endif
+#ifndef OPENSSL_NO_KRB5
+# define OPENSSL_NO_KRB5
+#endif
+#ifndef OPENSSL_NO_MDC2
+# define OPENSSL_NO_MDC2
+#endif
+#ifndef OPENSSL_NO_RC5
+# define OPENSSL_NO_RC5
+#endif
+#ifndef OPENSSL_NO_RFC3779
+# define OPENSSL_NO_RFC3779
+#endif
+
+#endif /* OPENSSL_DOING_MAKEDEPEND */
+#ifndef OPENSSL_NO_DYNAMIC_ENGINE
+# define OPENSSL_NO_DYNAMIC_ENGINE
+#endif
+
+/* The OPENSSL_NO_* macros are also defined as NO_* if the application
+   asks for it.  This is a transient feature that is provided for those
+   who haven't had the time to do the appropriate changes in their
+   applications.  */
+#ifdef OPENSSL_ALGORITHM_DEFINES
+# if defined(OPENSSL_NO_CAMELLIA) && !defined(NO_CAMELLIA)
+#  define NO_CAMELLIA
+# endif
+# if defined(OPENSSL_NO_GMP) && !defined(NO_GMP)
+#  define NO_GMP
+# endif
+# if defined(OPENSSL_NO_KRB5) && !defined(NO_KRB5)
+#  define NO_KRB5
+# endif
+# if defined(OPENSSL_NO_MDC2) && !defined(NO_MDC2)
+#  define NO_MDC2
+# endif
+# if defined(OPENSSL_NO_RC5) && !defined(NO_RC5)
+#  define NO_RC5
+# endif
+# if defined(OPENSSL_NO_RFC3779) && !defined(NO_RFC3779)
+#  define NO_RFC3779
+# endif
+#endif
+
+/* crypto/opensslconf.h.in */
+
+/* Generate 80386 code? */
+#undef I386_ONLY
+
+#if !(defined(VMS) || defined(__VMS)) /* VMS uses logical names instead */
+#if defined(HEADER_CRYPTLIB_H) && !defined(OPENSSLDIR)
+#define ENGINESDIR "/usr/local/ssl/lib/engines"
+#define OPENSSLDIR "/usr/local/ssl"
+#endif
+#endif
+
+#undef OPENSSL_UNISTD
+#define OPENSSL_UNISTD 
+
+#undef OPENSSL_EXPORT_VAR_AS_FUNCTION
+
+#if defined(HEADER_IDEA_H) && !defined(IDEA_INT)
+#define IDEA_INT unsigned int
+#endif
+
+#if defined(HEADER_MD2_H) && !defined(MD2_INT)
+#define MD2_INT unsigned int
+#endif
+
+#if defined(HEADER_RC2_H) && !defined(RC2_INT)
+/* I need to put in a mod for the alpha - eay */
+#define RC2_INT unsigned int
+#endif
+
+#if defined(HEADER_RC4_H)
+#if !defined(RC4_INT)
+/* using int types make the structure larger but make the code faster
+ * on most boxes I have tested - up to %20 faster. */
+/*
+ * I don't know what does "most" mean, but declaring "int" is a must on:
+ * - Intel P6 because partial register stalls are very expensive;
+ * - elder Alpha because it lacks byte load/store instructions;
+ */
+#define RC4_INT unsigned int
+#endif
+#if !defined(RC4_CHUNK)
+/*
+ * This enables code handling data aligned at natural CPU word
+ * boundary. See crypto/rc4/rc4_enc.c for further details.
+ */
+#undef RC4_CHUNK
+#endif
+#endif
+
+#if (defined(HEADER_NEW_DES_H) || defined(HEADER_DES_H)) && !defined(DES_LONG)
+/* If this is set to 'unsigned int' on a DEC Alpha, this gives about a
+ * %20 speed up (longs are 8 bytes, int's are 4). */
+#ifndef DES_LONG
+#define DES_LONG unsigned long
+#endif
+#endif
+
+#if defined(HEADER_BN_H) && !defined(CONFIG_HEADER_BN_H)
+#define CONFIG_HEADER_BN_H
+#undef BN_LLONG
+
+/* Should we define BN_DIV2W here? */
+
+/* Only one for the following should be defined */
+/* The prime number generation stuff may not work when
+ * EIGHT_BIT but I don't care since I've only used this mode
+ * for debuging the bignum libraries */
+#undef SIXTY_FOUR_BIT_LONG
+#undef SIXTY_FOUR_BIT
+#define THIRTY_TWO_BIT
+#undef SIXTEEN_BIT
+#undef EIGHT_BIT
+#endif
+
+#if defined(HEADER_RC4_LOCL_H) && !defined(CONFIG_HEADER_RC4_LOCL_H)
+#define CONFIG_HEADER_RC4_LOCL_H
+/* if this is defined data[i] is used instead of *data, this is a %20
+ * speedup on x86 */
+#undef RC4_INDEX
+#endif
+
+#if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H)
+#define CONFIG_HEADER_BF_LOCL_H
+#undef BF_PTR
+#endif /* HEADER_BF_LOCL_H */
+
+#if defined(HEADER_DES_LOCL_H) && !defined(CONFIG_HEADER_DES_LOCL_H)
+#define CONFIG_HEADER_DES_LOCL_H
+#ifndef DES_DEFAULT_OPTIONS
+/* the following is tweaked from a config script, that is why it is a
+ * protected undef/define */
+#ifndef DES_PTR
+#undef DES_PTR
+#endif
+
+/* This helps C compiler generate the correct code for multiple functional
+ * units.  It reduces register dependancies at the expense of 2 more
+ * registers */
+#ifndef DES_RISC1
+#undef DES_RISC1
+#endif
+
+#ifndef DES_RISC2
+#undef DES_RISC2
+#endif
+
+#if defined(DES_RISC1) && defined(DES_RISC2)
+YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!!
+#endif
+
+/* Unroll the inner loop, this sometimes helps, sometimes hinders.
+ * Very mucy CPU dependant */
+#ifndef DES_UNROLL
+#undef DES_UNROLL
+#endif
+
+/* These default values were supplied by
+ * Peter Gutman 
+ * They are only used if nothing else has been defined */
+#if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && !defined(DES_UNROLL)
+/* Special defines which change the way the code is built depending on the
+   CPU and OS.  For SGI machines you can use _MIPS_SZLONG (32 or 64) to find
+   even newer MIPS CPU's, but at the moment one size fits all for
+   optimization options.  Older Sparc's work better with only UNROLL, but
+   there's no way to tell at compile time what it is you're running on */
+ 
+#if defined( sun )		/* Newer Sparc's */
+#  define DES_PTR
+#  define DES_RISC1
+#  define DES_UNROLL
+#elif defined( __ultrix )	/* Older MIPS */
+#  define DES_PTR
+#  define DES_RISC2
+#  define DES_UNROLL
+#elif defined( __osf1__ )	/* Alpha */
+#  define DES_PTR
+#  define DES_RISC2
+#elif defined ( _AIX )		/* RS6000 */
+  /* Unknown */
+#elif defined( __hpux )		/* HP-PA */
+  /* Unknown */
+#elif defined( __aux )		/* 68K */
+  /* Unknown */
+#elif defined( __dgux )		/* 88K (but P6 in latest boxes) */
+#  define DES_UNROLL
+#elif defined( __sgi )		/* Newer MIPS */
+#  define DES_PTR
+#  define DES_RISC2
+#  define DES_UNROLL
+#elif defined(i386) || defined(__i386__)	/* x86 boxes, should be gcc */
+#  define DES_PTR
+#  define DES_RISC1
+#  define DES_UNROLL
+#endif /* Systems-specific speed defines */
+#endif
+
+#endif /* DES_DEFAULT_OPTIONS */
+#endif /* HEADER_DES_LOCL_H */
diff --git a/dep/include/openssl/opensslv.h b/dep/include/openssl/opensslv.h
new file mode 100644
index 00000000000..8a5b34e4f07
--- /dev/null
+++ b/dep/include/openssl/opensslv.h
@@ -0,0 +1,89 @@
+#ifndef HEADER_OPENSSLV_H
+#define HEADER_OPENSSLV_H
+
+/* Numeric release version identifier:
+ * MNNFFPPS: major minor fix patch status
+ * The status nibble has one of the values 0 for development, 1 to e for betas
+ * 1 to 14, and f for release.  The patch level is exactly that.
+ * For example:
+ * 0.9.3-dev	  0x00903000
+ * 0.9.3-beta1	  0x00903001
+ * 0.9.3-beta2-dev 0x00903002
+ * 0.9.3-beta2    0x00903002 (same as ...beta2-dev)
+ * 0.9.3	  0x0090300f
+ * 0.9.3a	  0x0090301f
+ * 0.9.4	  0x0090400f
+ * 1.2.3z	  0x102031af
+ *
+ * For continuity reasons (because 0.9.5 is already out, and is coded
+ * 0x00905100), between 0.9.5 and 0.9.6 the coding of the patch level
+ * part is slightly different, by setting the highest bit.  This means
+ * that 0.9.5a looks like this: 0x0090581f.  At 0.9.6, we can start
+ * with 0x0090600S...
+ *
+ * (Prior to 0.9.3-dev a different scheme was used: 0.9.2b is 0x0922.)
+ * (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for
+ *  major minor fix final patch/beta)
+ */
+#define OPENSSL_VERSION_NUMBER	0x0090805fL
+#ifdef OPENSSL_FIPS
+#define OPENSSL_VERSION_TEXT	"OpenSSL 0.9.8e-fips 23 Feb 2007"
+#else
+#define OPENSSL_VERSION_TEXT	"OpenSSL 0.9.8e 23 Feb 2007"
+#endif
+#define OPENSSL_VERSION_PTEXT	" part of " OPENSSL_VERSION_TEXT
+
+
+/* The macros below are to be used for shared library (.so, .dll, ...)
+ * versioning.  That kind of versioning works a bit differently between
+ * operating systems.  The most usual scheme is to set a major and a minor
+ * number, and have the runtime loader check that the major number is equal
+ * to what it was at application link time, while the minor number has to
+ * be greater or equal to what it was at application link time.  With this
+ * scheme, the version number is usually part of the file name, like this:
+ *
+ *	libcrypto.so.0.9
+ *
+ * Some unixen also make a softlink with the major verson number only:
+ *
+ *	libcrypto.so.0
+ *
+ * On Tru64 and IRIX 6.x it works a little bit differently.  There, the
+ * shared library version is stored in the file, and is actually a series
+ * of versions, separated by colons.  The rightmost version present in the
+ * library when linking an application is stored in the application to be
+ * matched at run time.  When the application is run, a check is done to
+ * see if the library version stored in the application matches any of the
+ * versions in the version string of the library itself.
+ * This version string can be constructed in any way, depending on what
+ * kind of matching is desired.  However, to implement the same scheme as
+ * the one used in the other unixen, all compatible versions, from lowest
+ * to highest, should be part of the string.  Consecutive builds would
+ * give the following versions strings:
+ *
+ *	3.0
+ *	3.0:3.1
+ *	3.0:3.1:3.2
+ *	4.0
+ *	4.0:4.1
+ *
+ * Notice how version 4 is completely incompatible with version, and
+ * therefore give the breach you can see.
+ *
+ * There may be other schemes as well that I haven't yet discovered.
+ *
+ * So, here's the way it works here: first of all, the library version
+ * number doesn't need at all to match the overall OpenSSL version.
+ * However, it's nice and more understandable if it actually does.
+ * The current library version is stored in the macro SHLIB_VERSION_NUMBER,
+ * which is just a piece of text in the format "M.m.e" (Major, minor, edit).
+ * For the sake of Tru64, IRIX, and any other OS that behaves in similar ways,
+ * we need to keep a history of version numbers, which is done in the
+ * macro SHLIB_VERSION_HISTORY.  The numbers are separated by colons and
+ * should only keep the versions that are binary compatible with the current.
+ */
+#define SHLIB_VERSION_HISTORY ""
+#define SHLIB_VERSION_NUMBER "0.9.8"
+
+
+#endif /* HEADER_OPENSSLV_H */
diff --git a/dep/include/openssl/ossl_typ.h b/dep/include/openssl/ossl_typ.h
new file mode 100644
index 00000000000..9c335a18190
--- /dev/null
+++ b/dep/include/openssl/ossl_typ.h
@@ -0,0 +1,174 @@
+/* ====================================================================
+ * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_OPENSSL_TYPES_H
+#define HEADER_OPENSSL_TYPES_H
+
+#include 
+
+#ifdef NO_ASN1_TYPEDEFS
+#define ASN1_INTEGER		ASN1_STRING
+#define ASN1_ENUMERATED		ASN1_STRING
+#define ASN1_BIT_STRING		ASN1_STRING
+#define ASN1_OCTET_STRING	ASN1_STRING
+#define ASN1_PRINTABLESTRING	ASN1_STRING
+#define ASN1_T61STRING		ASN1_STRING
+#define ASN1_IA5STRING		ASN1_STRING
+#define ASN1_UTCTIME		ASN1_STRING
+#define ASN1_GENERALIZEDTIME	ASN1_STRING
+#define ASN1_TIME		ASN1_STRING
+#define ASN1_GENERALSTRING	ASN1_STRING
+#define ASN1_UNIVERSALSTRING	ASN1_STRING
+#define ASN1_BMPSTRING		ASN1_STRING
+#define ASN1_VISIBLESTRING	ASN1_STRING
+#define ASN1_UTF8STRING		ASN1_STRING
+#define ASN1_BOOLEAN		int
+#define ASN1_NULL		int
+#else
+typedef struct asn1_string_st ASN1_INTEGER;
+typedef struct asn1_string_st ASN1_ENUMERATED;
+typedef struct asn1_string_st ASN1_BIT_STRING;
+typedef struct asn1_string_st ASN1_OCTET_STRING;
+typedef struct asn1_string_st ASN1_PRINTABLESTRING;
+typedef struct asn1_string_st ASN1_T61STRING;
+typedef struct asn1_string_st ASN1_IA5STRING;
+typedef struct asn1_string_st ASN1_GENERALSTRING;
+typedef struct asn1_string_st ASN1_UNIVERSALSTRING;
+typedef struct asn1_string_st ASN1_BMPSTRING;
+typedef struct asn1_string_st ASN1_UTCTIME;
+typedef struct asn1_string_st ASN1_TIME;
+typedef struct asn1_string_st ASN1_GENERALIZEDTIME;
+typedef struct asn1_string_st ASN1_VISIBLESTRING;
+typedef struct asn1_string_st ASN1_UTF8STRING;
+typedef int ASN1_BOOLEAN;
+typedef int ASN1_NULL;
+#endif
+
+#ifdef OPENSSL_SYS_WIN32
+#undef X509_NAME
+#undef X509_CERT_PAIR
+#undef PKCS7_ISSUER_AND_SERIAL
+#endif
+
+#ifdef BIGNUM
+#undef BIGNUM
+#endif
+typedef struct bignum_st BIGNUM;
+typedef struct bignum_ctx BN_CTX;
+typedef struct bn_blinding_st BN_BLINDING;
+typedef struct bn_mont_ctx_st BN_MONT_CTX;
+typedef struct bn_recp_ctx_st BN_RECP_CTX;
+typedef struct bn_gencb_st BN_GENCB;
+
+typedef struct buf_mem_st BUF_MEM;
+
+typedef struct evp_cipher_st EVP_CIPHER;
+typedef struct evp_cipher_ctx_st EVP_CIPHER_CTX;
+typedef struct env_md_st EVP_MD;
+typedef struct env_md_ctx_st EVP_MD_CTX;
+typedef struct evp_pkey_st EVP_PKEY;
+
+typedef struct dh_st DH;
+typedef struct dh_method DH_METHOD;
+
+typedef struct dsa_st DSA;
+typedef struct dsa_method DSA_METHOD;
+
+typedef struct rsa_st RSA;
+typedef struct rsa_meth_st RSA_METHOD;
+
+typedef struct rand_meth_st RAND_METHOD;
+
+typedef struct ecdh_method ECDH_METHOD;
+typedef struct ecdsa_method ECDSA_METHOD;
+
+typedef struct x509_st X509;
+typedef struct X509_algor_st X509_ALGOR;
+typedef struct X509_crl_st X509_CRL;
+typedef struct X509_name_st X509_NAME;
+typedef struct x509_store_st X509_STORE;
+typedef struct x509_store_ctx_st X509_STORE_CTX;
+
+typedef struct v3_ext_ctx X509V3_CTX;
+typedef struct conf_st CONF;
+
+typedef struct store_st STORE;
+typedef struct store_method_st STORE_METHOD;
+
+typedef struct ui_st UI;
+typedef struct ui_method_st UI_METHOD;
+
+typedef struct st_ERR_FNS ERR_FNS;
+
+typedef struct engine_st ENGINE;
+
+typedef struct X509_POLICY_NODE_st X509_POLICY_NODE;
+typedef struct X509_POLICY_LEVEL_st X509_POLICY_LEVEL;
+typedef struct X509_POLICY_TREE_st X509_POLICY_TREE;
+typedef struct X509_POLICY_CACHE_st X509_POLICY_CACHE;
+
+  /* If placed in pkcs12.h, we end up with a circular depency with pkcs7.h */
+#define DECLARE_PKCS12_STACK_OF(type) /* Nothing */
+#define IMPLEMENT_PKCS12_STACK_OF(type) /* Nothing */
+
+typedef struct crypto_ex_data_st CRYPTO_EX_DATA;
+/* Callback types for crypto.h */
+typedef int CRYPTO_EX_new(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
+					int idx, long argl, void *argp);
+typedef void CRYPTO_EX_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
+					int idx, long argl, void *argp);
+typedef int CRYPTO_EX_dup(CRYPTO_EX_DATA *to, CRYPTO_EX_DATA *from, void *from_d, 
+					int idx, long argl, void *argp);
+
+#endif /* def HEADER_OPENSSL_TYPES_H */
diff --git a/dep/include/openssl/pem.h b/dep/include/openssl/pem.h
new file mode 100644
index 00000000000..c28706ddc03
--- /dev/null
+++ b/dep/include/openssl/pem.h
@@ -0,0 +1,737 @@
+/* crypto/pem/pem.h */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_PEM_H
+#define HEADER_PEM_H
+
+#include 
+#ifndef OPENSSL_NO_BIO
+#include 
+#endif
+#ifndef OPENSSL_NO_STACK
+#include 
+#endif
+#include 
+#include 
+#include 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#define PEM_BUFSIZE		1024
+
+#define PEM_OBJ_UNDEF		0
+#define PEM_OBJ_X509		1
+#define PEM_OBJ_X509_REQ	2
+#define PEM_OBJ_CRL		3
+#define PEM_OBJ_SSL_SESSION	4
+#define PEM_OBJ_PRIV_KEY	10
+#define PEM_OBJ_PRIV_RSA	11
+#define PEM_OBJ_PRIV_DSA	12
+#define PEM_OBJ_PRIV_DH		13
+#define PEM_OBJ_PUB_RSA		14
+#define PEM_OBJ_PUB_DSA		15
+#define PEM_OBJ_PUB_DH		16
+#define PEM_OBJ_DHPARAMS	17
+#define PEM_OBJ_DSAPARAMS	18
+#define PEM_OBJ_PRIV_RSA_PUBLIC	19
+#define PEM_OBJ_PRIV_ECDSA	20
+#define PEM_OBJ_PUB_ECDSA	21
+#define PEM_OBJ_ECPARAMETERS	22
+
+#define PEM_ERROR		30
+#define PEM_DEK_DES_CBC         40
+#define PEM_DEK_IDEA_CBC        45
+#define PEM_DEK_DES_EDE         50
+#define PEM_DEK_DES_ECB         60
+#define PEM_DEK_RSA             70
+#define PEM_DEK_RSA_MD2         80
+#define PEM_DEK_RSA_MD5         90
+
+#define PEM_MD_MD2		NID_md2
+#define PEM_MD_MD5		NID_md5
+#define PEM_MD_SHA		NID_sha
+#define PEM_MD_MD2_RSA		NID_md2WithRSAEncryption
+#define PEM_MD_MD5_RSA		NID_md5WithRSAEncryption
+#define PEM_MD_SHA_RSA		NID_sha1WithRSAEncryption
+
+#define PEM_STRING_X509_OLD	"X509 CERTIFICATE"
+#define PEM_STRING_X509		"CERTIFICATE"
+#define PEM_STRING_X509_PAIR	"CERTIFICATE PAIR"
+#define PEM_STRING_X509_TRUSTED	"TRUSTED CERTIFICATE"
+#define PEM_STRING_X509_REQ_OLD	"NEW CERTIFICATE REQUEST"
+#define PEM_STRING_X509_REQ	"CERTIFICATE REQUEST"
+#define PEM_STRING_X509_CRL	"X509 CRL"
+#define PEM_STRING_EVP_PKEY	"ANY PRIVATE KEY"
+#define PEM_STRING_PUBLIC	"PUBLIC KEY"
+#define PEM_STRING_RSA		"RSA PRIVATE KEY"
+#define PEM_STRING_RSA_PUBLIC	"RSA PUBLIC KEY"
+#define PEM_STRING_DSA		"DSA PRIVATE KEY"
+#define PEM_STRING_DSA_PUBLIC	"DSA PUBLIC KEY"
+#define PEM_STRING_PKCS7	"PKCS7"
+#define PEM_STRING_PKCS8	"ENCRYPTED PRIVATE KEY"
+#define PEM_STRING_PKCS8INF	"PRIVATE KEY"
+#define PEM_STRING_DHPARAMS	"DH PARAMETERS"
+#define PEM_STRING_SSL_SESSION	"SSL SESSION PARAMETERS"
+#define PEM_STRING_DSAPARAMS	"DSA PARAMETERS"
+#define PEM_STRING_ECDSA_PUBLIC "ECDSA PUBLIC KEY"
+#define PEM_STRING_ECPARAMETERS "EC PARAMETERS"
+#define PEM_STRING_ECPRIVATEKEY	"EC PRIVATE KEY"
+
+  /* Note that this structure is initialised by PEM_SealInit and cleaned up
+     by PEM_SealFinal (at least for now) */
+typedef struct PEM_Encode_Seal_st
+	{
+	EVP_ENCODE_CTX encode;
+	EVP_MD_CTX md;
+	EVP_CIPHER_CTX cipher;
+	} PEM_ENCODE_SEAL_CTX;
+
+/* enc_type is one off */
+#define PEM_TYPE_ENCRYPTED      10
+#define PEM_TYPE_MIC_ONLY       20
+#define PEM_TYPE_MIC_CLEAR      30
+#define PEM_TYPE_CLEAR		40
+
+typedef struct pem_recip_st
+	{
+	char *name;
+	X509_NAME *dn;
+
+	int cipher;
+	int key_enc;
+	/*	char iv[8]; unused and wrong size */
+	} PEM_USER;
+
+typedef struct pem_ctx_st
+	{
+	int type;		/* what type of object */
+
+	struct	{
+		int version;	
+		int mode;		
+		} proc_type;
+
+	char *domain;
+
+	struct	{
+		int cipher;
+	/* unused, and wrong size
+	   unsigned char iv[8]; */
+		} DEK_info;
+		
+	PEM_USER *originator;
+
+	int num_recipient;
+	PEM_USER **recipient;
+
+#ifndef OPENSSL_NO_STACK
+	STACK *x509_chain;	/* certificate chain */
+#else
+	char *x509_chain;	/* certificate chain */
+#endif
+	EVP_MD *md;		/* signature type */
+
+	int md_enc;		/* is the md encrypted or not? */
+	int md_len;		/* length of md_data */
+	char *md_data;		/* message digest, could be pkey encrypted */
+
+	EVP_CIPHER *dec;	/* date encryption cipher */
+	int key_len;		/* key length */
+	unsigned char *key;	/* key */
+	/* unused, and wrong size
+	   unsigned char iv[8]; */
+
+	
+	int  data_enc;		/* is the data encrypted */
+	int data_len;
+	unsigned char *data;
+	} PEM_CTX;
+
+/* These macros make the PEM_read/PEM_write functions easier to maintain and
+ * write. Now they are all implemented with either:
+ * IMPLEMENT_PEM_rw(...) or IMPLEMENT_PEM_rw_cb(...)
+ */
+
+#ifdef OPENSSL_NO_FP_API
+
+#define IMPLEMENT_PEM_read_fp(name, type, str, asn1) /**/
+#define IMPLEMENT_PEM_write_fp(name, type, str, asn1) /**/
+#define IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) /**/
+
+#else
+
+#define IMPLEMENT_PEM_read_fp(name, type, str, asn1) \
+type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u)\
+{ \
+return(((type *(*)(D2I_OF(type),char *,FILE *,type **,pem_password_cb *,void *))openssl_fcast(PEM_ASN1_read))(d2i_##asn1, str,fp,x,cb,u)); \
+} 
+
+#define IMPLEMENT_PEM_write_fp(name, type, str, asn1) \
+int PEM_write_##name(FILE *fp, type *x) \
+{ \
+return(((int (*)(I2D_OF(type),const char *,FILE *,type *, const EVP_CIPHER *,unsigned char *,int, pem_password_cb *,void *))openssl_fcast(PEM_ASN1_write))(i2d_##asn1,str,fp,x,NULL,NULL,0,NULL,NULL)); \
+}
+
+#define IMPLEMENT_PEM_write_fp_const(name, type, str, asn1) \
+int PEM_write_##name(FILE *fp, const type *x) \
+{ \
+return(((int (*)(I2D_OF_const(type),const char *,FILE *, const type *, const EVP_CIPHER *,unsigned char *,int, pem_password_cb *,void *))openssl_fcast(PEM_ASN1_write))(i2d_##asn1,str,fp,x,NULL,NULL,0,NULL,NULL)); \
+}
+
+#define IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) \
+int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \
+	     unsigned char *kstr, int klen, pem_password_cb *cb, \
+		  void *u) \
+	{ \
+	return(((int (*)(I2D_OF(type),const char *,FILE *,type *, const EVP_CIPHER *,unsigned char *,int, pem_password_cb *,void *))openssl_fcast(PEM_ASN1_write))(i2d_##asn1,str,fp,x,enc,kstr,klen,cb,u)); \
+	}
+
+#define IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1) \
+int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \
+	     unsigned char *kstr, int klen, pem_password_cb *cb, \
+		  void *u) \
+	{ \
+	return(((int (*)(I2D_OF_const(type),const char *,FILE *,type *, const EVP_CIPHER *,unsigned char *,int, pem_password_cb *,void *))openssl_fcast(PEM_ASN1_write))(i2d_##asn1,str,fp,x,enc,kstr,klen,cb,u)); \
+	}
+
+#endif
+
+#define IMPLEMENT_PEM_read_bio(name, type, str, asn1) \
+type *PEM_read_bio_##name(BIO *bp, type **x, pem_password_cb *cb, void *u)\
+{ \
+return(((type *(*)(D2I_OF(type),const char *,BIO *,type **,pem_password_cb *,void *))openssl_fcast(PEM_ASN1_read_bio))(d2i_##asn1, str,bp,x,cb,u)); \
+}
+
+#define IMPLEMENT_PEM_write_bio(name, type, str, asn1) \
+int PEM_write_bio_##name(BIO *bp, type *x) \
+{ \
+return(((int (*)(I2D_OF(type),const char *,BIO *,type *, const EVP_CIPHER *,unsigned char *,int, pem_password_cb *,void *))openssl_fcast(PEM_ASN1_write_bio))(i2d_##asn1,str,bp,x,NULL,NULL,0,NULL,NULL)); \
+}
+
+#define IMPLEMENT_PEM_write_bio_const(name, type, str, asn1) \
+int PEM_write_bio_##name(BIO *bp, const type *x) \
+{ \
+return(((int (*)(I2D_OF_const(type),const char *,BIO *,const type *, const EVP_CIPHER *,unsigned char *,int, pem_password_cb *,void *))openssl_fcast(PEM_ASN1_write_bio))(i2d_##asn1,str,bp,x,NULL,NULL,0,NULL,NULL)); \
+}
+
+#define IMPLEMENT_PEM_write_cb_bio(name, type, str, asn1) \
+int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \
+	     unsigned char *kstr, int klen, pem_password_cb *cb, void *u) \
+	{ \
+	return(((int (*)(I2D_OF(type),const char *,BIO *,type *,const EVP_CIPHER *,unsigned char *,int,pem_password_cb *,void *))openssl_fcast(PEM_ASN1_write_bio))(i2d_##asn1,str,bp,x,enc,kstr,klen,cb,u)); \
+	}
+
+#define IMPLEMENT_PEM_write_cb_bio_const(name, type, str, asn1) \
+int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \
+	     unsigned char *kstr, int klen, pem_password_cb *cb, void *u) \
+	{ \
+	return(((int (*)(I2D_OF_const(type),const char *,BIO *,type *,const EVP_CIPHER *,unsigned char *,int,pem_password_cb *,void *))openssl_fcast(PEM_ASN1_write_bio))(i2d_##asn1,str,bp,x,enc,kstr,klen,cb,u)); \
+	}
+
+#define IMPLEMENT_PEM_write(name, type, str, asn1) \
+	IMPLEMENT_PEM_write_bio(name, type, str, asn1) \
+	IMPLEMENT_PEM_write_fp(name, type, str, asn1) 
+
+#define IMPLEMENT_PEM_write_const(name, type, str, asn1) \
+	IMPLEMENT_PEM_write_bio_const(name, type, str, asn1) \
+	IMPLEMENT_PEM_write_fp_const(name, type, str, asn1) 
+
+#define IMPLEMENT_PEM_write_cb(name, type, str, asn1) \
+	IMPLEMENT_PEM_write_cb_bio(name, type, str, asn1) \
+	IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) 
+
+#define IMPLEMENT_PEM_write_cb_const(name, type, str, asn1) \
+	IMPLEMENT_PEM_write_cb_bio_const(name, type, str, asn1) \
+	IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1) 
+
+#define IMPLEMENT_PEM_read(name, type, str, asn1) \
+	IMPLEMENT_PEM_read_bio(name, type, str, asn1) \
+	IMPLEMENT_PEM_read_fp(name, type, str, asn1) 
+
+#define IMPLEMENT_PEM_rw(name, type, str, asn1) \
+	IMPLEMENT_PEM_read(name, type, str, asn1) \
+	IMPLEMENT_PEM_write(name, type, str, asn1)
+
+#define IMPLEMENT_PEM_rw_const(name, type, str, asn1) \
+	IMPLEMENT_PEM_read(name, type, str, asn1) \
+	IMPLEMENT_PEM_write_const(name, type, str, asn1)
+
+#define IMPLEMENT_PEM_rw_cb(name, type, str, asn1) \
+	IMPLEMENT_PEM_read(name, type, str, asn1) \
+	IMPLEMENT_PEM_write_cb(name, type, str, asn1)
+
+/* These are the same except they are for the declarations */
+
+#if defined(OPENSSL_SYS_WIN16) || defined(OPENSSL_NO_FP_API)
+
+#define DECLARE_PEM_read_fp(name, type) /**/
+#define DECLARE_PEM_write_fp(name, type) /**/
+#define DECLARE_PEM_write_cb_fp(name, type) /**/
+
+#else
+
+#define DECLARE_PEM_read_fp(name, type) \
+	type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u);
+
+#define DECLARE_PEM_write_fp(name, type) \
+	int PEM_write_##name(FILE *fp, type *x);
+
+#define DECLARE_PEM_write_fp_const(name, type) \
+	int PEM_write_##name(FILE *fp, const type *x);
+
+#define DECLARE_PEM_write_cb_fp(name, type) \
+	int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \
+	     unsigned char *kstr, int klen, pem_password_cb *cb, void *u);
+
+#endif
+
+#ifndef OPENSSL_NO_BIO
+#define DECLARE_PEM_read_bio(name, type) \
+	type *PEM_read_bio_##name(BIO *bp, type **x, pem_password_cb *cb, void *u);
+
+#define DECLARE_PEM_write_bio(name, type) \
+	int PEM_write_bio_##name(BIO *bp, type *x);
+
+#define DECLARE_PEM_write_bio_const(name, type) \
+	int PEM_write_bio_##name(BIO *bp, const type *x);
+
+#define DECLARE_PEM_write_cb_bio(name, type) \
+	int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \
+	     unsigned char *kstr, int klen, pem_password_cb *cb, void *u);
+
+#else
+
+#define DECLARE_PEM_read_bio(name, type) /**/
+#define DECLARE_PEM_write_bio(name, type) /**/
+#define DECLARE_PEM_write_cb_bio(name, type) /**/
+
+#endif
+
+#define DECLARE_PEM_write(name, type) \
+	DECLARE_PEM_write_bio(name, type) \
+	DECLARE_PEM_write_fp(name, type) 
+
+#define DECLARE_PEM_write_const(name, type) \
+	DECLARE_PEM_write_bio_const(name, type) \
+	DECLARE_PEM_write_fp_const(name, type)
+
+#define DECLARE_PEM_write_cb(name, type) \
+	DECLARE_PEM_write_cb_bio(name, type) \
+	DECLARE_PEM_write_cb_fp(name, type) 
+
+#define DECLARE_PEM_read(name, type) \
+	DECLARE_PEM_read_bio(name, type) \
+	DECLARE_PEM_read_fp(name, type)
+
+#define DECLARE_PEM_rw(name, type) \
+	DECLARE_PEM_read(name, type) \
+	DECLARE_PEM_write(name, type)
+
+#define DECLARE_PEM_rw_const(name, type) \
+	DECLARE_PEM_read(name, type) \
+	DECLARE_PEM_write_const(name, type)
+
+#define DECLARE_PEM_rw_cb(name, type) \
+	DECLARE_PEM_read(name, type) \
+	DECLARE_PEM_write_cb(name, type)
+
+#ifdef SSLEAY_MACROS
+
+#define PEM_write_SSL_SESSION(fp,x) \
+		PEM_ASN1_write((int (*)())i2d_SSL_SESSION, \
+			PEM_STRING_SSL_SESSION,fp, (char *)x, NULL,NULL,0,NULL,NULL)
+#define PEM_write_X509(fp,x) \
+		PEM_ASN1_write((int (*)())i2d_X509,PEM_STRING_X509,fp, \
+			(char *)x, NULL,NULL,0,NULL,NULL)
+#define PEM_write_X509_REQ(fp,x) PEM_ASN1_write( \
+		(int (*)())i2d_X509_REQ,PEM_STRING_X509_REQ,fp,(char *)x, \
+			NULL,NULL,0,NULL,NULL)
+#define PEM_write_X509_CRL(fp,x) \
+		PEM_ASN1_write((int (*)())i2d_X509_CRL,PEM_STRING_X509_CRL, \
+			fp,(char *)x, NULL,NULL,0,NULL,NULL)
+#define	PEM_write_RSAPrivateKey(fp,x,enc,kstr,klen,cb,u) \
+		PEM_ASN1_write((int (*)())i2d_RSAPrivateKey,PEM_STRING_RSA,fp,\
+			(char *)x,enc,kstr,klen,cb,u)
+#define	PEM_write_RSAPublicKey(fp,x) \
+		PEM_ASN1_write((int (*)())i2d_RSAPublicKey,\
+			PEM_STRING_RSA_PUBLIC,fp,(char *)x,NULL,NULL,0,NULL,NULL)
+#define	PEM_write_DSAPrivateKey(fp,x,enc,kstr,klen,cb,u) \
+		PEM_ASN1_write((int (*)())i2d_DSAPrivateKey,PEM_STRING_DSA,fp,\
+			(char *)x,enc,kstr,klen,cb,u)
+#define	PEM_write_PrivateKey(bp,x,enc,kstr,klen,cb,u) \
+		PEM_ASN1_write((int (*)())i2d_PrivateKey,\
+		(((x)->type == EVP_PKEY_DSA)?PEM_STRING_DSA:PEM_STRING_RSA),\
+			bp,(char *)x,enc,kstr,klen,cb,u)
+#define PEM_write_PKCS7(fp,x) \
+		PEM_ASN1_write((int (*)())i2d_PKCS7,PEM_STRING_PKCS7,fp, \
+			(char *)x, NULL,NULL,0,NULL,NULL)
+#define PEM_write_DHparams(fp,x) \
+		PEM_ASN1_write((int (*)())i2d_DHparams,PEM_STRING_DHPARAMS,fp,\
+			(char *)x,NULL,NULL,0,NULL,NULL)
+
+#define PEM_write_NETSCAPE_CERT_SEQUENCE(fp,x) \
+                PEM_ASN1_write((int (*)())i2d_NETSCAPE_CERT_SEQUENCE, \
+			PEM_STRING_X509,fp, \
+                        (char *)x, NULL,NULL,0,NULL,NULL)
+
+#define	PEM_read_SSL_SESSION(fp,x,cb,u) (SSL_SESSION *)PEM_ASN1_read( \
+	(char *(*)())d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,fp,(char **)x,cb,u)
+#define	PEM_read_X509(fp,x,cb,u) (X509 *)PEM_ASN1_read( \
+	(char *(*)())d2i_X509,PEM_STRING_X509,fp,(char **)x,cb,u)
+#define	PEM_read_X509_REQ(fp,x,cb,u) (X509_REQ *)PEM_ASN1_read( \
+	(char *(*)())d2i_X509_REQ,PEM_STRING_X509_REQ,fp,(char **)x,cb,u)
+#define	PEM_read_X509_CRL(fp,x,cb,u) (X509_CRL *)PEM_ASN1_read( \
+	(char *(*)())d2i_X509_CRL,PEM_STRING_X509_CRL,fp,(char **)x,cb,u)
+#define	PEM_read_RSAPrivateKey(fp,x,cb,u) (RSA *)PEM_ASN1_read( \
+	(char *(*)())d2i_RSAPrivateKey,PEM_STRING_RSA,fp,(char **)x,cb,u)
+#define	PEM_read_RSAPublicKey(fp,x,cb,u) (RSA *)PEM_ASN1_read( \
+	(char *(*)())d2i_RSAPublicKey,PEM_STRING_RSA_PUBLIC,fp,(char **)x,cb,u)
+#define	PEM_read_DSAPrivateKey(fp,x,cb,u) (DSA *)PEM_ASN1_read( \
+	(char *(*)())d2i_DSAPrivateKey,PEM_STRING_DSA,fp,(char **)x,cb,u)
+#define	PEM_read_PrivateKey(fp,x,cb,u) (EVP_PKEY *)PEM_ASN1_read( \
+	(char *(*)())d2i_PrivateKey,PEM_STRING_EVP_PKEY,fp,(char **)x,cb,u)
+#define	PEM_read_PKCS7(fp,x,cb,u) (PKCS7 *)PEM_ASN1_read( \
+	(char *(*)())d2i_PKCS7,PEM_STRING_PKCS7,fp,(char **)x,cb,u)
+#define	PEM_read_DHparams(fp,x,cb,u) (DH *)PEM_ASN1_read( \
+	(char *(*)())d2i_DHparams,PEM_STRING_DHPARAMS,fp,(char **)x,cb,u)
+
+#define PEM_read_NETSCAPE_CERT_SEQUENCE(fp,x,cb,u) \
+		(NETSCAPE_CERT_SEQUENCE *)PEM_ASN1_read( \
+        (char *(*)())d2i_NETSCAPE_CERT_SEQUENCE,PEM_STRING_X509,fp,\
+							(char **)x,cb,u)
+
+#define PEM_write_bio_X509(bp,x) \
+		PEM_ASN1_write_bio((int (*)())i2d_X509,PEM_STRING_X509,bp, \
+			(char *)x, NULL,NULL,0,NULL,NULL)
+#define PEM_write_bio_X509_REQ(bp,x) PEM_ASN1_write_bio( \
+		(int (*)())i2d_X509_REQ,PEM_STRING_X509_REQ,bp,(char *)x, \
+			NULL,NULL,0,NULL,NULL)
+#define PEM_write_bio_X509_CRL(bp,x) \
+		PEM_ASN1_write_bio((int (*)())i2d_X509_CRL,PEM_STRING_X509_CRL,\
+			bp,(char *)x, NULL,NULL,0,NULL,NULL)
+#define	PEM_write_bio_RSAPrivateKey(bp,x,enc,kstr,klen,cb,u) \
+		PEM_ASN1_write_bio((int (*)())i2d_RSAPrivateKey,PEM_STRING_RSA,\
+			bp,(char *)x,enc,kstr,klen,cb,u)
+#define	PEM_write_bio_RSAPublicKey(bp,x) \
+		PEM_ASN1_write_bio((int (*)())i2d_RSAPublicKey, \
+			PEM_STRING_RSA_PUBLIC,\
+			bp,(char *)x,NULL,NULL,0,NULL,NULL)
+#define	PEM_write_bio_DSAPrivateKey(bp,x,enc,kstr,klen,cb,u) \
+		PEM_ASN1_write_bio((int (*)())i2d_DSAPrivateKey,PEM_STRING_DSA,\
+			bp,(char *)x,enc,kstr,klen,cb,u)
+#define	PEM_write_bio_PrivateKey(bp,x,enc,kstr,klen,cb,u) \
+		PEM_ASN1_write_bio((int (*)())i2d_PrivateKey,\
+		(((x)->type == EVP_PKEY_DSA)?PEM_STRING_DSA:PEM_STRING_RSA),\
+			bp,(char *)x,enc,kstr,klen,cb,u)
+#define PEM_write_bio_PKCS7(bp,x) \
+		PEM_ASN1_write_bio((int (*)())i2d_PKCS7,PEM_STRING_PKCS7,bp, \
+			(char *)x, NULL,NULL,0,NULL,NULL)
+#define PEM_write_bio_DHparams(bp,x) \
+		PEM_ASN1_write_bio((int (*)())i2d_DHparams,PEM_STRING_DHPARAMS,\
+			bp,(char *)x,NULL,NULL,0,NULL,NULL)
+#define PEM_write_bio_DSAparams(bp,x) \
+		PEM_ASN1_write_bio((int (*)())i2d_DSAparams, \
+			PEM_STRING_DSAPARAMS,bp,(char *)x,NULL,NULL,0,NULL,NULL)
+
+#define PEM_write_bio_NETSCAPE_CERT_SEQUENCE(bp,x) \
+                PEM_ASN1_write_bio((int (*)())i2d_NETSCAPE_CERT_SEQUENCE, \
+			PEM_STRING_X509,bp, \
+                        (char *)x, NULL,NULL,0,NULL,NULL)
+
+#define	PEM_read_bio_X509(bp,x,cb,u) (X509 *)PEM_ASN1_read_bio( \
+	(char *(*)())d2i_X509,PEM_STRING_X509,bp,(char **)x,cb,u)
+#define	PEM_read_bio_X509_REQ(bp,x,cb,u) (X509_REQ *)PEM_ASN1_read_bio( \
+	(char *(*)())d2i_X509_REQ,PEM_STRING_X509_REQ,bp,(char **)x,cb,u)
+#define	PEM_read_bio_X509_CRL(bp,x,cb,u) (X509_CRL *)PEM_ASN1_read_bio( \
+	(char *(*)())d2i_X509_CRL,PEM_STRING_X509_CRL,bp,(char **)x,cb,u)
+#define	PEM_read_bio_RSAPrivateKey(bp,x,cb,u) (RSA *)PEM_ASN1_read_bio( \
+	(char *(*)())d2i_RSAPrivateKey,PEM_STRING_RSA,bp,(char **)x,cb,u)
+#define	PEM_read_bio_RSAPublicKey(bp,x,cb,u) (RSA *)PEM_ASN1_read_bio( \
+	(char *(*)())d2i_RSAPublicKey,PEM_STRING_RSA_PUBLIC,bp,(char **)x,cb,u)
+#define	PEM_read_bio_DSAPrivateKey(bp,x,cb,u) (DSA *)PEM_ASN1_read_bio( \
+	(char *(*)())d2i_DSAPrivateKey,PEM_STRING_DSA,bp,(char **)x,cb,u)
+#define	PEM_read_bio_PrivateKey(bp,x,cb,u) (EVP_PKEY *)PEM_ASN1_read_bio( \
+	(char *(*)())d2i_PrivateKey,PEM_STRING_EVP_PKEY,bp,(char **)x,cb,u)
+
+#define	PEM_read_bio_PKCS7(bp,x,cb,u) (PKCS7 *)PEM_ASN1_read_bio( \
+	(char *(*)())d2i_PKCS7,PEM_STRING_PKCS7,bp,(char **)x,cb,u)
+#define	PEM_read_bio_DHparams(bp,x,cb,u) (DH *)PEM_ASN1_read_bio( \
+	(char *(*)())d2i_DHparams,PEM_STRING_DHPARAMS,bp,(char **)x,cb,u)
+#define	PEM_read_bio_DSAparams(bp,x,cb,u) (DSA *)PEM_ASN1_read_bio( \
+	(char *(*)())d2i_DSAparams,PEM_STRING_DSAPARAMS,bp,(char **)x,cb,u)
+
+#define PEM_read_bio_NETSCAPE_CERT_SEQUENCE(bp,x,cb,u) \
+		(NETSCAPE_CERT_SEQUENCE *)PEM_ASN1_read_bio( \
+        (char *(*)())d2i_NETSCAPE_CERT_SEQUENCE,PEM_STRING_X509,bp,\
+							(char **)x,cb,u)
+
+#endif
+
+#if 1
+/* "userdata": new with OpenSSL 0.9.4 */
+typedef int pem_password_cb(char *buf, int size, int rwflag, void *userdata);
+#else
+/* OpenSSL 0.9.3, 0.9.3a */
+typedef int pem_password_cb(char *buf, int size, int rwflag);
+#endif
+
+int	PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher);
+int	PEM_do_header (EVP_CIPHER_INFO *cipher, unsigned char *data,long *len,
+	pem_password_cb *callback,void *u);
+
+#ifndef OPENSSL_NO_BIO
+int	PEM_read_bio(BIO *bp, char **name, char **header,
+		unsigned char **data,long *len);
+int	PEM_write_bio(BIO *bp,const char *name,char *hdr,unsigned char *data,
+		long len);
+int PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm, const char *name, BIO *bp,
+	     pem_password_cb *cb, void *u);
+void *	PEM_ASN1_read_bio(d2i_of_void *d2i, const char *name, BIO *bp,
+			  void **x, pem_password_cb *cb, void *u);
+#define PEM_ASN1_read_bio_of(type,d2i,name,bp,x,cb,u) \
+((type *(*)(D2I_OF(type),const char *,BIO *,type **,pem_password_cb *,void *))openssl_fcast(PEM_ASN1_read_bio))(d2i,name,bp,x,cb,u)
+int	PEM_ASN1_write_bio(i2d_of_void *i2d,const char *name,BIO *bp,char *x,
+			   const EVP_CIPHER *enc,unsigned char *kstr,int klen,
+			   pem_password_cb *cb, void *u);
+#define PEM_ASN1_write_bio_of(type,i2d,name,bp,x,enc,kstr,klen,cb,u) \
+	((int (*)(I2D_OF(type),const char *,BIO *,type *, const EVP_CIPHER *,unsigned char *,int, pem_password_cb *,void *))openssl_fcast(PEM_ASN1_write_bio))(i2d,name,bp,x,enc,kstr,klen,cb,u)
+
+STACK_OF(X509_INFO) *	PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb, void *u);
+int	PEM_X509_INFO_write_bio(BIO *bp,X509_INFO *xi, EVP_CIPHER *enc,
+		unsigned char *kstr, int klen, pem_password_cb *cd, void *u);
+#endif
+
+#ifndef OPENSSL_SYS_WIN16
+int	PEM_read(FILE *fp, char **name, char **header,
+		unsigned char **data,long *len);
+int	PEM_write(FILE *fp,char *name,char *hdr,unsigned char *data,long len);
+void *  PEM_ASN1_read(d2i_of_void *d2i, const char *name, FILE *fp, void **x,
+		      pem_password_cb *cb, void *u);
+int	PEM_ASN1_write(i2d_of_void *i2d,const char *name,FILE *fp,
+		       char *x,const EVP_CIPHER *enc,unsigned char *kstr,
+		       int klen,pem_password_cb *callback, void *u);
+STACK_OF(X509_INFO) *	PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk,
+	pem_password_cb *cb, void *u);
+#endif
+
+int	PEM_SealInit(PEM_ENCODE_SEAL_CTX *ctx, EVP_CIPHER *type,
+		EVP_MD *md_type, unsigned char **ek, int *ekl,
+		unsigned char *iv, EVP_PKEY **pubk, int npubk);
+void	PEM_SealUpdate(PEM_ENCODE_SEAL_CTX *ctx, unsigned char *out, int *outl,
+		unsigned char *in, int inl);
+int	PEM_SealFinal(PEM_ENCODE_SEAL_CTX *ctx, unsigned char *sig,int *sigl,
+		unsigned char *out, int *outl, EVP_PKEY *priv);
+
+void    PEM_SignInit(EVP_MD_CTX *ctx, EVP_MD *type);
+void    PEM_SignUpdate(EVP_MD_CTX *ctx,unsigned char *d,unsigned int cnt);
+int	PEM_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
+		unsigned int *siglen, EVP_PKEY *pkey);
+
+int	PEM_def_callback(char *buf, int num, int w, void *key);
+void	PEM_proc_type(char *buf, int type);
+void	PEM_dek_info(char *buf, const char *type, int len, char *str);
+
+#ifndef SSLEAY_MACROS
+
+#include 
+
+DECLARE_PEM_rw(X509, X509)
+
+DECLARE_PEM_rw(X509_AUX, X509)
+
+DECLARE_PEM_rw(X509_CERT_PAIR, X509_CERT_PAIR)
+
+DECLARE_PEM_rw(X509_REQ, X509_REQ)
+DECLARE_PEM_write(X509_REQ_NEW, X509_REQ)
+
+DECLARE_PEM_rw(X509_CRL, X509_CRL)
+
+DECLARE_PEM_rw(PKCS7, PKCS7)
+
+DECLARE_PEM_rw(NETSCAPE_CERT_SEQUENCE, NETSCAPE_CERT_SEQUENCE)
+
+DECLARE_PEM_rw(PKCS8, X509_SIG)
+
+DECLARE_PEM_rw(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO)
+
+#ifndef OPENSSL_NO_RSA
+
+DECLARE_PEM_rw_cb(RSAPrivateKey, RSA)
+
+DECLARE_PEM_rw_const(RSAPublicKey, RSA)
+DECLARE_PEM_rw(RSA_PUBKEY, RSA)
+
+#endif
+
+#ifndef OPENSSL_NO_DSA
+
+DECLARE_PEM_rw_cb(DSAPrivateKey, DSA)
+
+DECLARE_PEM_rw(DSA_PUBKEY, DSA)
+
+DECLARE_PEM_rw_const(DSAparams, DSA)
+
+#endif
+
+#ifndef OPENSSL_NO_EC
+DECLARE_PEM_rw_const(ECPKParameters, EC_GROUP)
+DECLARE_PEM_rw_cb(ECPrivateKey, EC_KEY)
+DECLARE_PEM_rw(EC_PUBKEY, EC_KEY)
+#endif
+
+#ifndef OPENSSL_NO_DH
+
+DECLARE_PEM_rw_const(DHparams, DH)
+
+#endif
+
+DECLARE_PEM_rw_cb(PrivateKey, EVP_PKEY)
+
+DECLARE_PEM_rw(PUBKEY, EVP_PKEY)
+
+int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, EVP_PKEY *x, int nid,
+				  char *kstr, int klen,
+				  pem_password_cb *cb, void *u);
+int PEM_write_bio_PKCS8PrivateKey(BIO *, EVP_PKEY *, const EVP_CIPHER *,
+                                  char *, int, pem_password_cb *, void *);
+int i2d_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
+				  char *kstr, int klen,
+				  pem_password_cb *cb, void *u);
+int i2d_PKCS8PrivateKey_nid_bio(BIO *bp, EVP_PKEY *x, int nid,
+				  char *kstr, int klen,
+				  pem_password_cb *cb, void *u);
+EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, void *u);
+
+int i2d_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
+				  char *kstr, int klen,
+				  pem_password_cb *cb, void *u);
+int i2d_PKCS8PrivateKey_nid_fp(FILE *fp, EVP_PKEY *x, int nid,
+				  char *kstr, int klen,
+				  pem_password_cb *cb, void *u);
+int PEM_write_PKCS8PrivateKey_nid(FILE *fp, EVP_PKEY *x, int nid,
+				  char *kstr, int klen,
+				  pem_password_cb *cb, void *u);
+
+EVP_PKEY *d2i_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, void *u);
+
+int PEM_write_PKCS8PrivateKey(FILE *fp,EVP_PKEY *x,const EVP_CIPHER *enc,
+			      char *kstr,int klen, pem_password_cb *cd, void *u);
+
+#endif /* SSLEAY_MACROS */
+
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_PEM_strings(void);
+
+/* Error codes for the PEM functions. */
+
+/* Function codes. */
+#define PEM_F_D2I_PKCS8PRIVATEKEY_BIO			 120
+#define PEM_F_D2I_PKCS8PRIVATEKEY_FP			 121
+#define PEM_F_DO_PK8PKEY				 126
+#define PEM_F_DO_PK8PKEY_FP				 125
+#define PEM_F_LOAD_IV					 101
+#define PEM_F_PEM_ASN1_READ				 102
+#define PEM_F_PEM_ASN1_READ_BIO				 103
+#define PEM_F_PEM_ASN1_WRITE				 104
+#define PEM_F_PEM_ASN1_WRITE_BIO			 105
+#define PEM_F_PEM_DEF_CALLBACK				 100
+#define PEM_F_PEM_DO_HEADER				 106
+#define PEM_F_PEM_F_PEM_WRITE_PKCS8PRIVATEKEY		 118
+#define PEM_F_PEM_GET_EVP_CIPHER_INFO			 107
+#define PEM_F_PEM_PK8PKEY				 119
+#define PEM_F_PEM_READ					 108
+#define PEM_F_PEM_READ_BIO				 109
+#define PEM_F_PEM_READ_BIO_PRIVATEKEY			 123
+#define PEM_F_PEM_READ_PRIVATEKEY			 124
+#define PEM_F_PEM_SEALFINAL				 110
+#define PEM_F_PEM_SEALINIT				 111
+#define PEM_F_PEM_SIGNFINAL				 112
+#define PEM_F_PEM_WRITE					 113
+#define PEM_F_PEM_WRITE_BIO				 114
+#define PEM_F_PEM_X509_INFO_READ			 115
+#define PEM_F_PEM_X509_INFO_READ_BIO			 116
+#define PEM_F_PEM_X509_INFO_WRITE_BIO			 117
+
+/* Reason codes. */
+#define PEM_R_BAD_BASE64_DECODE				 100
+#define PEM_R_BAD_DECRYPT				 101
+#define PEM_R_BAD_END_LINE				 102
+#define PEM_R_BAD_IV_CHARS				 103
+#define PEM_R_BAD_PASSWORD_READ				 104
+#define PEM_R_ERROR_CONVERTING_PRIVATE_KEY		 115
+#define PEM_R_NOT_DEK_INFO				 105
+#define PEM_R_NOT_ENCRYPTED				 106
+#define PEM_R_NOT_PROC_TYPE				 107
+#define PEM_R_NO_START_LINE				 108
+#define PEM_R_PROBLEMS_GETTING_PASSWORD			 109
+#define PEM_R_PUBLIC_KEY_NO_RSA				 110
+#define PEM_R_READ_KEY					 111
+#define PEM_R_SHORT_HEADER				 112
+#define PEM_R_UNSUPPORTED_CIPHER			 113
+#define PEM_R_UNSUPPORTED_ENCRYPTION			 114
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/dep/include/openssl/pem2.h b/dep/include/openssl/pem2.h
new file mode 100644
index 00000000000..f31790d69cb
--- /dev/null
+++ b/dep/include/openssl/pem2.h
@@ -0,0 +1,70 @@
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/*
+ * This header only exists to break a circular dependency between pem and err
+ * Ben 30 Jan 1999.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef HEADER_PEM_H
+void ERR_load_PEM_strings(void);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/dep/include/openssl/pkcs12.h b/dep/include/openssl/pkcs12.h
new file mode 100644
index 00000000000..a2d7e359a0f
--- /dev/null
+++ b/dep/include/openssl/pkcs12.h
@@ -0,0 +1,333 @@
+/* pkcs12.h */
+/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_PKCS12_H
+#define HEADER_PKCS12_H
+
+#include 
+#include 
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PKCS12_KEY_ID	1
+#define PKCS12_IV_ID	2
+#define PKCS12_MAC_ID	3
+
+/* Default iteration count */
+#ifndef PKCS12_DEFAULT_ITER
+#define PKCS12_DEFAULT_ITER	PKCS5_DEFAULT_ITER
+#endif
+
+#define PKCS12_MAC_KEY_LENGTH 20
+
+#define PKCS12_SALT_LEN	8
+
+/* Uncomment out next line for unicode password and names, otherwise ASCII */
+
+/*#define PBE_UNICODE*/
+
+#ifdef PBE_UNICODE
+#define PKCS12_key_gen PKCS12_key_gen_uni
+#define PKCS12_add_friendlyname PKCS12_add_friendlyname_uni
+#else
+#define PKCS12_key_gen PKCS12_key_gen_asc
+#define PKCS12_add_friendlyname PKCS12_add_friendlyname_asc
+#endif
+
+/* MS key usage constants */
+
+#define KEY_EX	0x10
+#define KEY_SIG 0x80
+
+typedef struct {
+X509_SIG *dinfo;
+ASN1_OCTET_STRING *salt;
+ASN1_INTEGER *iter;	/* defaults to 1 */
+} PKCS12_MAC_DATA;
+
+typedef struct {
+ASN1_INTEGER *version;
+PKCS12_MAC_DATA *mac;
+PKCS7 *authsafes;
+} PKCS12;
+
+PREDECLARE_STACK_OF(PKCS12_SAFEBAG)
+
+typedef struct {
+ASN1_OBJECT *type;
+union {
+	struct pkcs12_bag_st *bag; /* secret, crl and certbag */
+	struct pkcs8_priv_key_info_st	*keybag; /* keybag */
+	X509_SIG *shkeybag; /* shrouded key bag */
+	STACK_OF(PKCS12_SAFEBAG) *safes;
+	ASN1_TYPE *other;
+}value;
+STACK_OF(X509_ATTRIBUTE) *attrib;
+} PKCS12_SAFEBAG;
+
+DECLARE_STACK_OF(PKCS12_SAFEBAG)
+DECLARE_ASN1_SET_OF(PKCS12_SAFEBAG)
+DECLARE_PKCS12_STACK_OF(PKCS12_SAFEBAG)
+
+typedef struct pkcs12_bag_st {
+ASN1_OBJECT *type;
+union {
+	ASN1_OCTET_STRING *x509cert;
+	ASN1_OCTET_STRING *x509crl;
+	ASN1_OCTET_STRING *octet;
+	ASN1_IA5STRING *sdsicert;
+	ASN1_TYPE *other; /* Secret or other bag */
+}value;
+} PKCS12_BAGS;
+
+#define PKCS12_ERROR	0
+#define PKCS12_OK	1
+
+/* Compatibility macros */
+
+#define M_PKCS12_x5092certbag PKCS12_x5092certbag
+#define M_PKCS12_x509crl2certbag PKCS12_x509crl2certbag
+
+#define M_PKCS12_certbag2x509 PKCS12_certbag2x509
+#define M_PKCS12_certbag2x509crl PKCS12_certbag2x509crl 
+
+#define M_PKCS12_unpack_p7data PKCS12_unpack_p7data
+#define M_PKCS12_pack_authsafes PKCS12_pack_authsafes
+#define M_PKCS12_unpack_authsafes PKCS12_unpack_authsafes
+#define M_PKCS12_unpack_p7encdata PKCS12_unpack_p7encdata
+
+#define M_PKCS12_decrypt_skey PKCS12_decrypt_skey
+#define M_PKCS8_decrypt PKCS8_decrypt
+
+#define M_PKCS12_bag_type(bg) OBJ_obj2nid((bg)->type)
+#define M_PKCS12_cert_bag_type(bg) OBJ_obj2nid((bg)->value.bag->type)
+#define M_PKCS12_crl_bag_type M_PKCS12_cert_bag_type
+
+#define PKCS12_get_attr(bag, attr_nid) \
+			 PKCS12_get_attr_gen(bag->attrib, attr_nid)
+
+#define PKCS8_get_attr(p8, attr_nid) \
+		PKCS12_get_attr_gen(p8->attributes, attr_nid)
+
+#define PKCS12_mac_present(p12) ((p12)->mac ? 1 : 0)
+
+
+PKCS12_SAFEBAG *PKCS12_x5092certbag(X509 *x509);
+PKCS12_SAFEBAG *PKCS12_x509crl2certbag(X509_CRL *crl);
+X509 *PKCS12_certbag2x509(PKCS12_SAFEBAG *bag);
+X509_CRL *PKCS12_certbag2x509crl(PKCS12_SAFEBAG *bag);
+
+PKCS12_SAFEBAG *PKCS12_item_pack_safebag(void *obj, const ASN1_ITEM *it, int nid1,
+	     int nid2);
+PKCS12_SAFEBAG *PKCS12_MAKE_KEYBAG(PKCS8_PRIV_KEY_INFO *p8);
+PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(X509_SIG *p8, const char *pass, int passlen);
+PKCS8_PRIV_KEY_INFO *PKCS12_decrypt_skey(PKCS12_SAFEBAG *bag, const char *pass,
+								int passlen);
+X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher, 
+			const char *pass, int passlen,
+			unsigned char *salt, int saltlen, int iter,
+			PKCS8_PRIV_KEY_INFO *p8);
+PKCS12_SAFEBAG *PKCS12_MAKE_SHKEYBAG(int pbe_nid, const char *pass,
+				     int passlen, unsigned char *salt,
+				     int saltlen, int iter,
+				     PKCS8_PRIV_KEY_INFO *p8);
+PKCS7 *PKCS12_pack_p7data(STACK_OF(PKCS12_SAFEBAG) *sk);
+STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7data(PKCS7 *p7);
+PKCS7 *PKCS12_pack_p7encdata(int pbe_nid, const char *pass, int passlen,
+			     unsigned char *salt, int saltlen, int iter,
+			     STACK_OF(PKCS12_SAFEBAG) *bags);
+STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7encdata(PKCS7 *p7, const char *pass, int passlen);
+
+int PKCS12_pack_authsafes(PKCS12 *p12, STACK_OF(PKCS7) *safes);
+STACK_OF(PKCS7) *PKCS12_unpack_authsafes(PKCS12 *p12);
+
+int PKCS12_add_localkeyid(PKCS12_SAFEBAG *bag, unsigned char *name, int namelen);
+int PKCS12_add_friendlyname_asc(PKCS12_SAFEBAG *bag, const char *name,
+				int namelen);
+int PKCS12_add_CSPName_asc(PKCS12_SAFEBAG *bag, const char *name,
+				int namelen);
+int PKCS12_add_friendlyname_uni(PKCS12_SAFEBAG *bag, const unsigned char *name,
+				int namelen);
+int PKCS8_add_keyusage(PKCS8_PRIV_KEY_INFO *p8, int usage);
+ASN1_TYPE *PKCS12_get_attr_gen(STACK_OF(X509_ATTRIBUTE) *attrs, int attr_nid);
+char *PKCS12_get_friendlyname(PKCS12_SAFEBAG *bag);
+unsigned char *PKCS12_pbe_crypt(X509_ALGOR *algor, const char *pass,
+				int passlen, unsigned char *in, int inlen,
+				unsigned char **data, int *datalen, int en_de);
+void * PKCS12_item_decrypt_d2i(X509_ALGOR *algor, const ASN1_ITEM *it,
+	     const char *pass, int passlen, ASN1_OCTET_STRING *oct, int zbuf);
+ASN1_OCTET_STRING *PKCS12_item_i2d_encrypt(X509_ALGOR *algor, const ASN1_ITEM *it,
+				       const char *pass, int passlen,
+				       void *obj, int zbuf);
+PKCS12 *PKCS12_init(int mode);
+int PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt,
+		       int saltlen, int id, int iter, int n,
+		       unsigned char *out, const EVP_MD *md_type);
+int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt, int saltlen, int id, int iter, int n, unsigned char *out, const EVP_MD *md_type);
+int PKCS12_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+			 ASN1_TYPE *param, const EVP_CIPHER *cipher, const EVP_MD *md_type,
+			 int en_de);
+int PKCS12_gen_mac(PKCS12 *p12, const char *pass, int passlen,
+			 unsigned char *mac, unsigned int *maclen);
+int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen);
+int PKCS12_set_mac(PKCS12 *p12, const char *pass, int passlen,
+		   unsigned char *salt, int saltlen, int iter,
+		   const EVP_MD *md_type);
+int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt,
+					 int saltlen, const EVP_MD *md_type);
+unsigned char *asc2uni(const char *asc, int asclen, unsigned char **uni, int *unilen);
+char *uni2asc(unsigned char *uni, int unilen);
+
+DECLARE_ASN1_FUNCTIONS(PKCS12)
+DECLARE_ASN1_FUNCTIONS(PKCS12_MAC_DATA)
+DECLARE_ASN1_FUNCTIONS(PKCS12_SAFEBAG)
+DECLARE_ASN1_FUNCTIONS(PKCS12_BAGS)
+
+DECLARE_ASN1_ITEM(PKCS12_SAFEBAGS)
+DECLARE_ASN1_ITEM(PKCS12_AUTHSAFES)
+
+void PKCS12_PBE_add(void);
+int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert,
+		 STACK_OF(X509) **ca);
+PKCS12 *PKCS12_create(char *pass, char *name, EVP_PKEY *pkey, X509 *cert,
+			 STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter,
+						 int mac_iter, int keytype);
+
+PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert);
+PKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags, EVP_PKEY *key,
+						int key_usage, int iter,
+						int key_nid, char *pass);
+int PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
+					int safe_nid, int iter, char *pass);
+PKCS12 *PKCS12_add_safes(STACK_OF(PKCS7) *safes, int p7_nid);
+
+int i2d_PKCS12_bio(BIO *bp, PKCS12 *p12);
+int i2d_PKCS12_fp(FILE *fp, PKCS12 *p12);
+PKCS12 *d2i_PKCS12_bio(BIO *bp, PKCS12 **p12);
+PKCS12 *d2i_PKCS12_fp(FILE *fp, PKCS12 **p12);
+int PKCS12_newpass(PKCS12 *p12, char *oldpass, char *newpass);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_PKCS12_strings(void);
+
+/* Error codes for the PKCS12 functions. */
+
+/* Function codes. */
+#define PKCS12_F_PARSE_BAG				 129
+#define PKCS12_F_PARSE_BAGS				 103
+#define PKCS12_F_PKCS12_ADD_FRIENDLYNAME		 100
+#define PKCS12_F_PKCS12_ADD_FRIENDLYNAME_ASC		 127
+#define PKCS12_F_PKCS12_ADD_FRIENDLYNAME_UNI		 102
+#define PKCS12_F_PKCS12_ADD_LOCALKEYID			 104
+#define PKCS12_F_PKCS12_CREATE				 105
+#define PKCS12_F_PKCS12_GEN_MAC				 107
+#define PKCS12_F_PKCS12_INIT				 109
+#define PKCS12_F_PKCS12_ITEM_DECRYPT_D2I		 106
+#define PKCS12_F_PKCS12_ITEM_I2D_ENCRYPT		 108
+#define PKCS12_F_PKCS12_ITEM_PACK_SAFEBAG		 117
+#define PKCS12_F_PKCS12_KEY_GEN_ASC			 110
+#define PKCS12_F_PKCS12_KEY_GEN_UNI			 111
+#define PKCS12_F_PKCS12_MAKE_KEYBAG			 112
+#define PKCS12_F_PKCS12_MAKE_SHKEYBAG			 113
+#define PKCS12_F_PKCS12_NEWPASS				 128
+#define PKCS12_F_PKCS12_PACK_P7DATA			 114
+#define PKCS12_F_PKCS12_PACK_P7ENCDATA			 115
+#define PKCS12_F_PKCS12_PARSE				 118
+#define PKCS12_F_PKCS12_PBE_CRYPT			 119
+#define PKCS12_F_PKCS12_PBE_KEYIVGEN			 120
+#define PKCS12_F_PKCS12_SETUP_MAC			 122
+#define PKCS12_F_PKCS12_SET_MAC				 123
+#define PKCS12_F_PKCS12_UNPACK_AUTHSAFES		 130
+#define PKCS12_F_PKCS12_UNPACK_P7DATA			 131
+#define PKCS12_F_PKCS12_VERIFY_MAC			 126
+#define PKCS12_F_PKCS8_ADD_KEYUSAGE			 124
+#define PKCS12_F_PKCS8_ENCRYPT				 125
+
+/* Reason codes. */
+#define PKCS12_R_CANT_PACK_STRUCTURE			 100
+#define PKCS12_R_CONTENT_TYPE_NOT_DATA			 121
+#define PKCS12_R_DECODE_ERROR				 101
+#define PKCS12_R_ENCODE_ERROR				 102
+#define PKCS12_R_ENCRYPT_ERROR				 103
+#define PKCS12_R_ERROR_SETTING_ENCRYPTED_DATA_TYPE	 120
+#define PKCS12_R_INVALID_NULL_ARGUMENT			 104
+#define PKCS12_R_INVALID_NULL_PKCS12_POINTER		 105
+#define PKCS12_R_IV_GEN_ERROR				 106
+#define PKCS12_R_KEY_GEN_ERROR				 107
+#define PKCS12_R_MAC_ABSENT				 108
+#define PKCS12_R_MAC_GENERATION_ERROR			 109
+#define PKCS12_R_MAC_SETUP_ERROR			 110
+#define PKCS12_R_MAC_STRING_SET_ERROR			 111
+#define PKCS12_R_MAC_VERIFY_ERROR			 112
+#define PKCS12_R_MAC_VERIFY_FAILURE			 113
+#define PKCS12_R_PARSE_ERROR				 114
+#define PKCS12_R_PKCS12_ALGOR_CIPHERINIT_ERROR		 115
+#define PKCS12_R_PKCS12_CIPHERFINAL_ERROR		 116
+#define PKCS12_R_PKCS12_PBE_CRYPT_ERROR			 117
+#define PKCS12_R_UNKNOWN_DIGEST_ALGORITHM		 118
+#define PKCS12_R_UNSUPPORTED_PKCS12_MODE		 119
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/dep/include/openssl/pkcs7.h b/dep/include/openssl/pkcs7.h
new file mode 100644
index 00000000000..cc092d262dc
--- /dev/null
+++ b/dep/include/openssl/pkcs7.h
@@ -0,0 +1,464 @@
+/* crypto/pkcs7/pkcs7.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_PKCS7_H
+#define HEADER_PKCS7_H
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#ifdef OPENSSL_SYS_WIN32
+/* Under Win32 thes are defined in wincrypt.h */
+#undef PKCS7_ISSUER_AND_SERIAL
+#undef PKCS7_SIGNER_INFO
+#endif
+
+/*
+Encryption_ID		DES-CBC
+Digest_ID		MD5
+Digest_Encryption_ID	rsaEncryption
+Key_Encryption_ID	rsaEncryption
+*/
+
+typedef struct pkcs7_issuer_and_serial_st
+	{
+	X509_NAME *issuer;
+	ASN1_INTEGER *serial;
+	} PKCS7_ISSUER_AND_SERIAL;
+
+typedef struct pkcs7_signer_info_st
+	{
+	ASN1_INTEGER 			*version;	/* version 1 */
+	PKCS7_ISSUER_AND_SERIAL		*issuer_and_serial;
+	X509_ALGOR			*digest_alg;
+	STACK_OF(X509_ATTRIBUTE)	*auth_attr;	/* [ 0 ] */
+	X509_ALGOR			*digest_enc_alg;
+	ASN1_OCTET_STRING		*enc_digest;
+	STACK_OF(X509_ATTRIBUTE)	*unauth_attr;	/* [ 1 ] */
+
+	/* The private key to sign with */
+	EVP_PKEY			*pkey;
+	} PKCS7_SIGNER_INFO;
+
+DECLARE_STACK_OF(PKCS7_SIGNER_INFO)
+DECLARE_ASN1_SET_OF(PKCS7_SIGNER_INFO)
+
+typedef struct pkcs7_recip_info_st
+	{
+	ASN1_INTEGER			*version;	/* version 0 */
+	PKCS7_ISSUER_AND_SERIAL		*issuer_and_serial;
+	X509_ALGOR			*key_enc_algor;
+	ASN1_OCTET_STRING		*enc_key;
+	X509				*cert; /* get the pub-key from this */
+	} PKCS7_RECIP_INFO;
+
+DECLARE_STACK_OF(PKCS7_RECIP_INFO)
+DECLARE_ASN1_SET_OF(PKCS7_RECIP_INFO)
+
+typedef struct pkcs7_signed_st
+	{
+	ASN1_INTEGER			*version;	/* version 1 */
+	STACK_OF(X509_ALGOR)		*md_algs;	/* md used */
+	STACK_OF(X509)			*cert;		/* [ 0 ] */
+	STACK_OF(X509_CRL)		*crl;		/* [ 1 ] */
+	STACK_OF(PKCS7_SIGNER_INFO)	*signer_info;
+
+	struct pkcs7_st			*contents;
+	} PKCS7_SIGNED;
+/* The above structure is very very similar to PKCS7_SIGN_ENVELOPE.
+ * How about merging the two */
+
+typedef struct pkcs7_enc_content_st
+	{
+	ASN1_OBJECT			*content_type;
+	X509_ALGOR			*algorithm;
+	ASN1_OCTET_STRING		*enc_data;	/* [ 0 ] */
+	const EVP_CIPHER		*cipher;
+	} PKCS7_ENC_CONTENT;
+
+typedef struct pkcs7_enveloped_st
+	{
+	ASN1_INTEGER			*version;	/* version 0 */
+	STACK_OF(PKCS7_RECIP_INFO)	*recipientinfo;
+	PKCS7_ENC_CONTENT		*enc_data;
+	} PKCS7_ENVELOPE;
+
+typedef struct pkcs7_signedandenveloped_st
+	{
+	ASN1_INTEGER			*version;	/* version 1 */
+	STACK_OF(X509_ALGOR)		*md_algs;	/* md used */
+	STACK_OF(X509)			*cert;		/* [ 0 ] */
+	STACK_OF(X509_CRL)		*crl;		/* [ 1 ] */
+	STACK_OF(PKCS7_SIGNER_INFO)	*signer_info;
+
+	PKCS7_ENC_CONTENT		*enc_data;
+	STACK_OF(PKCS7_RECIP_INFO)	*recipientinfo;
+	} PKCS7_SIGN_ENVELOPE;
+
+typedef struct pkcs7_digest_st
+	{
+	ASN1_INTEGER			*version;	/* version 0 */
+	X509_ALGOR			*md;		/* md used */
+	struct pkcs7_st 		*contents;
+	ASN1_OCTET_STRING		*digest;
+	} PKCS7_DIGEST;
+
+typedef struct pkcs7_encrypted_st
+	{
+	ASN1_INTEGER			*version;	/* version 0 */
+	PKCS7_ENC_CONTENT		*enc_data;
+	} PKCS7_ENCRYPT;
+
+typedef struct pkcs7_st
+	{
+	/* The following is non NULL if it contains ASN1 encoding of
+	 * this structure */
+	unsigned char *asn1;
+	long length;
+
+#define PKCS7_S_HEADER	0
+#define PKCS7_S_BODY	1
+#define PKCS7_S_TAIL	2
+	int state; /* used during processing */
+
+	int detached;
+
+	ASN1_OBJECT *type;
+	/* content as defined by the type */
+	/* all encryption/message digests are applied to the 'contents',
+	 * leaving out the 'type' field. */
+	union	{
+		char *ptr;
+
+		/* NID_pkcs7_data */
+		ASN1_OCTET_STRING *data;
+
+		/* NID_pkcs7_signed */
+		PKCS7_SIGNED *sign;
+
+		/* NID_pkcs7_enveloped */
+		PKCS7_ENVELOPE *enveloped;
+
+		/* NID_pkcs7_signedAndEnveloped */
+		PKCS7_SIGN_ENVELOPE *signed_and_enveloped;
+
+		/* NID_pkcs7_digest */
+		PKCS7_DIGEST *digest;
+
+		/* NID_pkcs7_encrypted */
+		PKCS7_ENCRYPT *encrypted;
+
+		/* Anything else */
+		ASN1_TYPE *other;
+		} d;
+	} PKCS7;
+
+DECLARE_STACK_OF(PKCS7)
+DECLARE_ASN1_SET_OF(PKCS7)
+DECLARE_PKCS12_STACK_OF(PKCS7)
+
+#define PKCS7_OP_SET_DETACHED_SIGNATURE	1
+#define PKCS7_OP_GET_DETACHED_SIGNATURE	2
+
+#define PKCS7_get_signed_attributes(si)	((si)->auth_attr)
+#define PKCS7_get_attributes(si)	((si)->unauth_attr)
+
+#define PKCS7_type_is_signed(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_signed)
+#define PKCS7_type_is_encrypted(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_encrypted)
+#define PKCS7_type_is_enveloped(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_enveloped)
+#define PKCS7_type_is_signedAndEnveloped(a) \
+		(OBJ_obj2nid((a)->type) == NID_pkcs7_signedAndEnveloped)
+#define PKCS7_type_is_data(a)   (OBJ_obj2nid((a)->type) == NID_pkcs7_data)
+
+#define PKCS7_type_is_digest(a)   (OBJ_obj2nid((a)->type) == NID_pkcs7_digest)
+
+#define PKCS7_set_detached(p,v) \
+		PKCS7_ctrl(p,PKCS7_OP_SET_DETACHED_SIGNATURE,v,NULL)
+#define PKCS7_get_detached(p) \
+		PKCS7_ctrl(p,PKCS7_OP_GET_DETACHED_SIGNATURE,0,NULL)
+
+#define PKCS7_is_detached(p7) (PKCS7_type_is_signed(p7) && PKCS7_get_detached(p7))
+
+#ifdef SSLEAY_MACROS
+#ifndef PKCS7_ISSUER_AND_SERIAL_digest
+#define PKCS7_ISSUER_AND_SERIAL_digest(data,type,md,len) \
+        ASN1_digest((int (*)())i2d_PKCS7_ISSUER_AND_SERIAL,type,\
+	                (char *)data,md,len)
+#endif
+#endif
+
+/* S/MIME related flags */
+
+#define PKCS7_TEXT		0x1
+#define PKCS7_NOCERTS		0x2
+#define PKCS7_NOSIGS		0x4
+#define PKCS7_NOCHAIN		0x8
+#define PKCS7_NOINTERN		0x10
+#define PKCS7_NOVERIFY		0x20
+#define PKCS7_DETACHED		0x40
+#define PKCS7_BINARY		0x80
+#define PKCS7_NOATTR		0x100
+#define	PKCS7_NOSMIMECAP	0x200
+#define PKCS7_NOOLDMIMETYPE	0x400
+#define PKCS7_CRLFEOL		0x800
+#define PKCS7_STREAM		0x1000
+#define PKCS7_NOCRL		0x2000
+
+/* Flags: for compatibility with older code */
+
+#define SMIME_TEXT	PKCS7_TEXT
+#define SMIME_NOCERTS	PKCS7_NOCERTS
+#define SMIME_NOSIGS	PKCS7_NOSIGS
+#define SMIME_NOCHAIN	PKCS7_NOCHAIN
+#define SMIME_NOINTERN	PKCS7_NOINTERN
+#define SMIME_NOVERIFY	PKCS7_NOVERIFY
+#define SMIME_DETACHED	PKCS7_DETACHED
+#define SMIME_BINARY	PKCS7_BINARY
+#define SMIME_NOATTR	PKCS7_NOATTR
+
+DECLARE_ASN1_FUNCTIONS(PKCS7_ISSUER_AND_SERIAL)
+
+#ifndef SSLEAY_MACROS
+int PKCS7_ISSUER_AND_SERIAL_digest(PKCS7_ISSUER_AND_SERIAL *data,const EVP_MD *type,
+	unsigned char *md,unsigned int *len);
+#ifndef OPENSSL_NO_FP_API
+PKCS7 *d2i_PKCS7_fp(FILE *fp,PKCS7 **p7);
+int i2d_PKCS7_fp(FILE *fp,PKCS7 *p7);
+#endif
+PKCS7 *PKCS7_dup(PKCS7 *p7);
+PKCS7 *d2i_PKCS7_bio(BIO *bp,PKCS7 **p7);
+int i2d_PKCS7_bio(BIO *bp,PKCS7 *p7);
+#endif
+
+DECLARE_ASN1_FUNCTIONS(PKCS7_SIGNER_INFO)
+DECLARE_ASN1_FUNCTIONS(PKCS7_RECIP_INFO)
+DECLARE_ASN1_FUNCTIONS(PKCS7_SIGNED)
+DECLARE_ASN1_FUNCTIONS(PKCS7_ENC_CONTENT)
+DECLARE_ASN1_FUNCTIONS(PKCS7_ENVELOPE)
+DECLARE_ASN1_FUNCTIONS(PKCS7_SIGN_ENVELOPE)
+DECLARE_ASN1_FUNCTIONS(PKCS7_DIGEST)
+DECLARE_ASN1_FUNCTIONS(PKCS7_ENCRYPT)
+DECLARE_ASN1_FUNCTIONS(PKCS7)
+
+DECLARE_ASN1_ITEM(PKCS7_ATTR_SIGN)
+DECLARE_ASN1_ITEM(PKCS7_ATTR_VERIFY)
+
+DECLARE_ASN1_NDEF_FUNCTION(PKCS7)
+
+long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg);
+
+int PKCS7_set_type(PKCS7 *p7, int type);
+int PKCS7_set0_type_other(PKCS7 *p7, int type, ASN1_TYPE *other);
+int PKCS7_set_content(PKCS7 *p7, PKCS7 *p7_data);
+int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey,
+	const EVP_MD *dgst);
+int PKCS7_add_signer(PKCS7 *p7, PKCS7_SIGNER_INFO *p7i);
+int PKCS7_add_certificate(PKCS7 *p7, X509 *x509);
+int PKCS7_add_crl(PKCS7 *p7, X509_CRL *x509);
+int PKCS7_content_new(PKCS7 *p7, int nid);
+int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx,
+	BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si); 
+int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si,
+								X509 *x509);
+
+BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio);
+int PKCS7_dataFinal(PKCS7 *p7, BIO *bio);
+BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert);
+
+
+PKCS7_SIGNER_INFO *PKCS7_add_signature(PKCS7 *p7, X509 *x509,
+	EVP_PKEY *pkey, const EVP_MD *dgst);
+X509 *PKCS7_cert_from_signer_info(PKCS7 *p7, PKCS7_SIGNER_INFO *si);
+int PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md);
+STACK_OF(PKCS7_SIGNER_INFO) *PKCS7_get_signer_info(PKCS7 *p7);
+
+PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509);
+int PKCS7_add_recipient_info(PKCS7 *p7, PKCS7_RECIP_INFO *ri);
+int PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509);
+int PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher);
+
+PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx);
+ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk);
+int PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si,int nid,int type,
+	void *data);
+int PKCS7_add_attribute (PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
+	void *value);
+ASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid);
+ASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid);
+int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si,
+				STACK_OF(X509_ATTRIBUTE) *sk);
+int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si,STACK_OF(X509_ATTRIBUTE) *sk);
+
+
+PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
+							BIO *data, int flags);
+int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
+					BIO *indata, BIO *out, int flags);
+STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, int flags);
+PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher,
+								int flags);
+int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags);
+
+int PKCS7_add_attrib_smimecap(PKCS7_SIGNER_INFO *si,
+			      STACK_OF(X509_ALGOR) *cap);
+STACK_OF(X509_ALGOR) *PKCS7_get_smimecap(PKCS7_SIGNER_INFO *si);
+int PKCS7_simple_smimecap(STACK_OF(X509_ALGOR) *sk, int nid, int arg);
+
+int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags);
+PKCS7 *SMIME_read_PKCS7(BIO *bio, BIO **bcont);
+int SMIME_crlf_copy(BIO *in, BIO *out, int flags);
+int SMIME_text(BIO *in, BIO *out);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_PKCS7_strings(void);
+
+/* Error codes for the PKCS7 functions. */
+
+/* Function codes. */
+#define PKCS7_F_B64_READ_PKCS7				 120
+#define PKCS7_F_B64_WRITE_PKCS7				 121
+#define PKCS7_F_PKCS7_ADD_ATTRIB_SMIMECAP		 118
+#define PKCS7_F_PKCS7_ADD_CERTIFICATE			 100
+#define PKCS7_F_PKCS7_ADD_CRL				 101
+#define PKCS7_F_PKCS7_ADD_RECIPIENT_INFO		 102
+#define PKCS7_F_PKCS7_ADD_SIGNER			 103
+#define PKCS7_F_PKCS7_BIO_ADD_DIGEST			 125
+#define PKCS7_F_PKCS7_CTRL				 104
+#define PKCS7_F_PKCS7_DATADECODE			 112
+#define PKCS7_F_PKCS7_DATAFINAL				 128
+#define PKCS7_F_PKCS7_DATAINIT				 105
+#define PKCS7_F_PKCS7_DATASIGN				 106
+#define PKCS7_F_PKCS7_DATAVERIFY			 107
+#define PKCS7_F_PKCS7_DECRYPT				 114
+#define PKCS7_F_PKCS7_ENCRYPT				 115
+#define PKCS7_F_PKCS7_FIND_DIGEST			 127
+#define PKCS7_F_PKCS7_GET0_SIGNERS			 124
+#define PKCS7_F_PKCS7_SET_CIPHER			 108
+#define PKCS7_F_PKCS7_SET_CONTENT			 109
+#define PKCS7_F_PKCS7_SET_DIGEST			 126
+#define PKCS7_F_PKCS7_SET_TYPE				 110
+#define PKCS7_F_PKCS7_SIGN				 116
+#define PKCS7_F_PKCS7_SIGNATUREVERIFY			 113
+#define PKCS7_F_PKCS7_SIMPLE_SMIMECAP			 119
+#define PKCS7_F_PKCS7_VERIFY				 117
+#define PKCS7_F_SMIME_READ_PKCS7			 122
+#define PKCS7_F_SMIME_TEXT				 123
+
+/* Reason codes. */
+#define PKCS7_R_CERTIFICATE_VERIFY_ERROR		 117
+#define PKCS7_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER		 144
+#define PKCS7_R_CIPHER_NOT_INITIALIZED			 116
+#define PKCS7_R_CONTENT_AND_DATA_PRESENT		 118
+#define PKCS7_R_DECODE_ERROR				 130
+#define PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH		 100
+#define PKCS7_R_DECRYPT_ERROR				 119
+#define PKCS7_R_DIGEST_FAILURE				 101
+#define PKCS7_R_ERROR_ADDING_RECIPIENT			 120
+#define PKCS7_R_ERROR_SETTING_CIPHER			 121
+#define PKCS7_R_INVALID_MIME_TYPE			 131
+#define PKCS7_R_INVALID_NULL_POINTER			 143
+#define PKCS7_R_MIME_NO_CONTENT_TYPE			 132
+#define PKCS7_R_MIME_PARSE_ERROR			 133
+#define PKCS7_R_MIME_SIG_PARSE_ERROR			 134
+#define PKCS7_R_MISSING_CERIPEND_INFO			 103
+#define PKCS7_R_NO_CONTENT				 122
+#define PKCS7_R_NO_CONTENT_TYPE				 135
+#define PKCS7_R_NO_MULTIPART_BODY_FAILURE		 136
+#define PKCS7_R_NO_MULTIPART_BOUNDARY			 137
+#define PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE	 115
+#define PKCS7_R_NO_RECIPIENT_MATCHES_KEY		 146
+#define PKCS7_R_NO_SIGNATURES_ON_DATA			 123
+#define PKCS7_R_NO_SIGNERS				 142
+#define PKCS7_R_NO_SIG_CONTENT_TYPE			 138
+#define PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE	 104
+#define PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR		 124
+#define PKCS7_R_PKCS7_DATAFINAL				 126
+#define PKCS7_R_PKCS7_DATAFINAL_ERROR			 125
+#define PKCS7_R_PKCS7_DATASIGN				 145
+#define PKCS7_R_PKCS7_PARSE_ERROR			 139
+#define PKCS7_R_PKCS7_SIG_PARSE_ERROR			 140
+#define PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE	 127
+#define PKCS7_R_SIGNATURE_FAILURE			 105
+#define PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND		 128
+#define PKCS7_R_SIG_INVALID_MIME_TYPE			 141
+#define PKCS7_R_SMIME_TEXT_ERROR			 129
+#define PKCS7_R_UNABLE_TO_FIND_CERTIFICATE		 106
+#define PKCS7_R_UNABLE_TO_FIND_MEM_BIO			 107
+#define PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST		 108
+#define PKCS7_R_UNKNOWN_DIGEST_TYPE			 109
+#define PKCS7_R_UNKNOWN_OPERATION			 110
+#define PKCS7_R_UNSUPPORTED_CIPHER_TYPE			 111
+#define PKCS7_R_UNSUPPORTED_CONTENT_TYPE		 112
+#define PKCS7_R_WRONG_CONTENT_TYPE			 113
+#define PKCS7_R_WRONG_PKCS7_TYPE			 114
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/dep/include/openssl/pq_compat.h b/dep/include/openssl/pq_compat.h
new file mode 100644
index 00000000000..28c58a0261d
--- /dev/null
+++ b/dep/include/openssl/pq_compat.h
@@ -0,0 +1,147 @@
+/* crypto/pqueue/pqueue_compat.h */
+/* 
+ * DTLS implementation written by Nagendra Modadugu
+ * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.  
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include "opensslconf.h"
+#include 
+
+/* 
+ * The purpose of this header file is for supporting 64-bit integer
+ * manipulation on 32-bit (and lower) machines.  Currently the only
+ * such environment is VMS, Utrix and those with smaller default integer
+ * sizes than 32 bits.  For all such environment, we fall back to using
+ * BIGNUM.  We may need to fine tune the conditions for systems that
+ * are incorrectly configured.
+ *
+ * The only clients of this code are (1) pqueue for priority, and
+ * (2) DTLS, for sequence number manipulation.
+ */
+
+#if (defined(THIRTY_TWO_BIT) && !defined(BN_LLONG)) || defined(SIXTEEN_BIT) || defined(EIGHT_BIT)
+
+#define PQ_64BIT_IS_INTEGER 0
+#define PQ_64BIT_IS_BIGNUM 1
+
+#define PQ_64BIT     BIGNUM
+#define PQ_64BIT_CTX BN_CTX
+
+#define pq_64bit_init(x)           BN_init(x)
+#define pq_64bit_free(x)           BN_free(x)
+
+#define pq_64bit_ctx_new(ctx)      BN_CTX_new()
+#define pq_64bit_ctx_free(x)       BN_CTX_free(x)
+
+#define pq_64bit_assign(x, y)      BN_copy(x, y)
+#define pq_64bit_assign_word(x, y) BN_set_word(x, y)
+#define pq_64bit_gt(x, y)          BN_ucmp(x, y) >= 1 ? 1 : 0
+#define pq_64bit_eq(x, y)          BN_ucmp(x, y) == 0 ? 1 : 0
+#define pq_64bit_add_word(x, w)    BN_add_word(x, w)
+#define pq_64bit_sub(r, x, y)      BN_sub(r, x, y)
+#define pq_64bit_sub_word(x, w)    BN_sub_word(x, w)
+#define pq_64bit_mod(r, x, n, ctx) BN_mod(r, x, n, ctx)
+
+#define pq_64bit_bin2num(bn, bytes, len)   BN_bin2bn(bytes, len, bn)
+#define pq_64bit_num2bin(bn, bytes)        BN_bn2bin(bn, bytes)
+#define pq_64bit_get_word(x)               BN_get_word(x)
+#define pq_64bit_is_bit_set(x, offset)     BN_is_bit_set(x, offset)
+#define pq_64bit_lshift(r, x, shift)       BN_lshift(r, x, shift)
+#define pq_64bit_set_bit(x, num)           BN_set_bit(x, num)
+#define pq_64bit_get_length(x)             BN_num_bits((x))
+
+#else
+
+#define PQ_64BIT_IS_INTEGER 1
+#define PQ_64BIT_IS_BIGNUM 0
+
+#if defined(SIXTY_FOUR_BIT)
+#define PQ_64BIT BN_ULONG
+#define PQ_64BIT_PRINT "%lld"
+#elif defined(SIXTY_FOUR_BIT_LONG)
+#define PQ_64BIT BN_ULONG
+#define PQ_64BIT_PRINT "%ld"
+#elif defined(THIRTY_TWO_BIT)
+#define PQ_64BIT BN_ULLONG
+#define PQ_64BIT_PRINT "%lld"
+#endif
+
+#define PQ_64BIT_CTX      void
+
+#define pq_64bit_init(x)
+#define pq_64bit_free(x)
+#define pq_64bit_ctx_new(ctx)        (ctx)
+#define pq_64bit_ctx_free(x)
+
+#define pq_64bit_assign(x, y)        (*(x) = *(y))
+#define pq_64bit_assign_word(x, y)   (*(x) = y)
+#define pq_64bit_gt(x, y)	         (*(x) > *(y))
+#define pq_64bit_eq(x, y)            (*(x) == *(y))
+#define pq_64bit_add_word(x, w)      (*(x) = (*(x) + (w)))
+#define pq_64bit_sub(r, x, y)        (*(r) = (*(x) - *(y)))
+#define pq_64bit_sub_word(x, w)      (*(x) = (*(x) - (w)))
+#define pq_64bit_mod(r, x, n, ctx)
+
+#define pq_64bit_bin2num(num, bytes, len) bytes_to_long_long(bytes, num)
+#define pq_64bit_num2bin(num, bytes)      long_long_to_bytes(num, bytes)
+#define pq_64bit_get_word(x)              *(x)
+#define pq_64bit_lshift(r, x, shift)      (*(r) = (*(x) << (shift)))
+#define pq_64bit_set_bit(x, num)          do { \
+                                              PQ_64BIT mask = 1; \
+                                              mask = mask << (num); \
+                                              *(x) |= mask; \
+                                          } while(0)
+#endif /* OPENSSL_SYS_VMS */
diff --git a/dep/include/openssl/pqueue.h b/dep/include/openssl/pqueue.h
new file mode 100644
index 00000000000..02386d130e9
--- /dev/null
+++ b/dep/include/openssl/pqueue.h
@@ -0,0 +1,95 @@
+/* crypto/pqueue/pqueue.h */
+/* 
+ * DTLS implementation written by Nagendra Modadugu
+ * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.  
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_PQUEUE_H
+#define HEADER_PQUEUE_H
+
+#include 
+#include 
+#include 
+
+#include 
+
+typedef struct _pqueue *pqueue;
+
+typedef struct _pitem
+	{
+	PQ_64BIT priority;
+	void *data;
+	struct _pitem *next;
+	} pitem;
+
+typedef struct _pitem *piterator;
+
+pitem *pitem_new(PQ_64BIT priority, void *data);
+void   pitem_free(pitem *item);
+
+pqueue pqueue_new(void);
+void   pqueue_free(pqueue pq);
+
+pitem *pqueue_insert(pqueue pq, pitem *item);
+pitem *pqueue_peek(pqueue pq);
+pitem *pqueue_pop(pqueue pq);
+pitem *pqueue_find(pqueue pq, PQ_64BIT priority);
+pitem *pqueue_iterator(pqueue pq);
+pitem *pqueue_next(piterator *iter);
+
+void   pqueue_print(pqueue pq);
+
+#endif /* ! HEADER_PQUEUE_H */
diff --git a/dep/include/openssl/rand.h b/dep/include/openssl/rand.h
new file mode 100644
index 00000000000..ac6c0217636
--- /dev/null
+++ b/dep/include/openssl/rand.h
@@ -0,0 +1,140 @@
+/* crypto/rand/rand.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_RAND_H
+#define HEADER_RAND_H
+
+#include 
+#include 
+#include 
+
+#if defined(OPENSSL_SYS_WINDOWS)
+#include 
+#endif
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#if defined(OPENSSL_FIPS)
+#define FIPS_RAND_SIZE_T size_t
+#endif
+
+/* Already defined in ossl_typ.h */
+/* typedef struct rand_meth_st RAND_METHOD; */
+
+struct rand_meth_st
+	{
+	void (*seed)(const void *buf, int num);
+	int (*bytes)(unsigned char *buf, int num);
+	void (*cleanup)(void);
+	void (*add)(const void *buf, int num, double entropy);
+	int (*pseudorand)(unsigned char *buf, int num);
+	int (*status)(void);
+	};
+
+#ifdef BN_DEBUG
+extern int rand_predictable;
+#endif
+
+int RAND_set_rand_method(const RAND_METHOD *meth);
+const RAND_METHOD *RAND_get_rand_method(void);
+#ifndef OPENSSL_NO_ENGINE
+int RAND_set_rand_engine(ENGINE *engine);
+#endif
+RAND_METHOD *RAND_SSLeay(void);
+void RAND_cleanup(void );
+int  RAND_bytes(unsigned char *buf,int num);
+int  RAND_pseudo_bytes(unsigned char *buf,int num);
+void RAND_seed(const void *buf,int num);
+void RAND_add(const void *buf,int num,double entropy);
+int  RAND_load_file(const char *file,long max_bytes);
+int  RAND_write_file(const char *file);
+const char *RAND_file_name(char *file,size_t num);
+int RAND_status(void);
+int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes);
+int RAND_egd(const char *path);
+int RAND_egd_bytes(const char *path,int bytes);
+int RAND_poll(void);
+
+#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
+
+void RAND_screen(void);
+int RAND_event(UINT, WPARAM, LPARAM);
+
+#endif
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_RAND_strings(void);
+
+/* Error codes for the RAND functions. */
+
+/* Function codes. */
+#define RAND_F_RAND_GET_RAND_METHOD			 101
+#define RAND_F_SSLEAY_RAND_BYTES			 100
+
+/* Reason codes. */
+#define RAND_R_PRNG_NOT_SEEDED				 100
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/dep/include/openssl/rc2.h b/dep/include/openssl/rc2.h
new file mode 100644
index 00000000000..34c83623172
--- /dev/null
+++ b/dep/include/openssl/rc2.h
@@ -0,0 +1,101 @@
+/* crypto/rc2/rc2.h */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_RC2_H
+#define HEADER_RC2_H
+
+#include  /* OPENSSL_NO_RC2, RC2_INT */
+#ifdef OPENSSL_NO_RC2
+#error RC2 is disabled.
+#endif
+
+#define RC2_ENCRYPT	1
+#define RC2_DECRYPT	0
+
+#define RC2_BLOCK	8
+#define RC2_KEY_LENGTH	16
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+typedef struct rc2_key_st
+	{
+	RC2_INT data[64];
+	} RC2_KEY;
+
+ 
+void RC2_set_key(RC2_KEY *key, int len, const unsigned char *data,int bits);
+void RC2_ecb_encrypt(const unsigned char *in,unsigned char *out,RC2_KEY *key,
+		     int enc);
+void RC2_encrypt(unsigned long *data,RC2_KEY *key);
+void RC2_decrypt(unsigned long *data,RC2_KEY *key);
+void RC2_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,
+	RC2_KEY *ks, unsigned char *iv, int enc);
+void RC2_cfb64_encrypt(const unsigned char *in, unsigned char *out,
+		       long length, RC2_KEY *schedule, unsigned char *ivec,
+		       int *num, int enc);
+void RC2_ofb64_encrypt(const unsigned char *in, unsigned char *out,
+		       long length, RC2_KEY *schedule, unsigned char *ivec,
+		       int *num);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff --git a/dep/include/openssl/rc4.h b/dep/include/openssl/rc4.h
new file mode 100644
index 00000000000..7aec04fe93a
--- /dev/null
+++ b/dep/include/openssl/rc4.h
@@ -0,0 +1,87 @@
+/* crypto/rc4/rc4.h */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_RC4_H
+#define HEADER_RC4_H
+
+#include  /* OPENSSL_NO_RC4, RC4_INT */
+#ifdef OPENSSL_NO_RC4
+#error RC4 is disabled.
+#endif
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+typedef struct rc4_key_st
+	{
+	RC4_INT x,y;
+	RC4_INT data[256];
+	} RC4_KEY;
+
+ 
+const char *RC4_options(void);
+void RC4_set_key(RC4_KEY *key, int len, const unsigned char *data);
+void RC4(RC4_KEY *key, unsigned long len, const unsigned char *indata,
+		unsigned char *outdata);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff --git a/dep/include/openssl/rc5.h b/dep/include/openssl/rc5.h
new file mode 100644
index 00000000000..de61ce83f49
--- /dev/null
+++ b/dep/include/openssl/rc5.h
@@ -0,0 +1,117 @@
+/* crypto/rc5/rc5.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_RC5_H
+#define HEADER_RC5_H
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#ifdef OPENSSL_NO_RC5
+#error RC5 is disabled.
+#endif
+
+#define RC5_ENCRYPT	1
+#define RC5_DECRYPT	0
+
+/* 32 bit.  For Alpha, things may get weird */
+#define RC5_32_INT unsigned long
+
+#define RC5_32_BLOCK		8
+#define RC5_32_KEY_LENGTH	16 /* This is a default, max is 255 */
+
+/* This are the only values supported.  Tweak the code if you want more
+ * The most supported modes will be
+ * RC5-32/12/16
+ * RC5-32/16/8
+ */
+#define RC5_8_ROUNDS	8
+#define RC5_12_ROUNDS	12
+#define RC5_16_ROUNDS	16
+
+typedef struct rc5_key_st
+	{
+	/* Number of rounds */
+	int rounds;
+	RC5_32_INT data[2*(RC5_16_ROUNDS+1)];
+	} RC5_32_KEY;
+
+
+void RC5_32_set_key(RC5_32_KEY *key, int len, const unsigned char *data,
+	int rounds);
+void RC5_32_ecb_encrypt(const unsigned char *in,unsigned char *out,RC5_32_KEY *key,
+	int enc);
+void RC5_32_encrypt(unsigned long *data,RC5_32_KEY *key);
+void RC5_32_decrypt(unsigned long *data,RC5_32_KEY *key);
+void RC5_32_cbc_encrypt(const unsigned char *in, unsigned char *out,
+			long length, RC5_32_KEY *ks, unsigned char *iv,
+			int enc);
+void RC5_32_cfb64_encrypt(const unsigned char *in, unsigned char *out,
+			  long length, RC5_32_KEY *schedule,
+			  unsigned char *ivec, int *num, int enc);
+void RC5_32_ofb64_encrypt(const unsigned char *in, unsigned char *out,
+			  long length, RC5_32_KEY *schedule,
+			  unsigned char *ivec, int *num);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/dep/include/openssl/ripemd.h b/dep/include/openssl/ripemd.h
new file mode 100644
index 00000000000..033a5965b58
--- /dev/null
+++ b/dep/include/openssl/ripemd.h
@@ -0,0 +1,104 @@
+/* crypto/ripemd/ripemd.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_RIPEMD_H
+#define HEADER_RIPEMD_H
+
+#include 
+#include 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#ifdef OPENSSL_NO_RIPEMD
+#error RIPEMD is disabled.
+#endif
+
+#if defined(OPENSSL_SYS_WIN16) || defined(__LP32__)
+#define RIPEMD160_LONG unsigned long
+#elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__)
+#define RIPEMD160_LONG unsigned long
+#define RIPEMD160_LONG_LOG2 3
+#else
+#define RIPEMD160_LONG unsigned int
+#endif
+
+#define RIPEMD160_CBLOCK	64
+#define RIPEMD160_LBLOCK	(RIPEMD160_CBLOCK/4)
+#define RIPEMD160_DIGEST_LENGTH	20
+
+typedef struct RIPEMD160state_st
+	{
+	RIPEMD160_LONG A,B,C,D,E;
+	RIPEMD160_LONG Nl,Nh;
+	RIPEMD160_LONG data[RIPEMD160_LBLOCK];
+	unsigned int   num;
+	} RIPEMD160_CTX;
+
+int RIPEMD160_Init(RIPEMD160_CTX *c);
+int RIPEMD160_Update(RIPEMD160_CTX *c, const void *data, size_t len);
+int RIPEMD160_Final(unsigned char *md, RIPEMD160_CTX *c);
+unsigned char *RIPEMD160(const unsigned char *d, size_t n,
+	unsigned char *md);
+void RIPEMD160_Transform(RIPEMD160_CTX *c, const unsigned char *b);
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff --git a/dep/include/openssl/rsa.h b/dep/include/openssl/rsa.h
new file mode 100644
index 00000000000..b19c556930f
--- /dev/null
+++ b/dep/include/openssl/rsa.h
@@ -0,0 +1,441 @@
+/* crypto/rsa/rsa.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_RSA_H
+#define HEADER_RSA_H
+
+#include 
+
+#ifndef OPENSSL_NO_BIO
+#include 
+#endif
+#include 
+#include 
+#ifndef OPENSSL_NO_DEPRECATED
+#include 
+#endif
+
+#ifdef OPENSSL_NO_RSA
+#error RSA is disabled.
+#endif
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* Declared already in ossl_typ.h */
+/* typedef struct rsa_st RSA; */
+/* typedef struct rsa_meth_st RSA_METHOD; */
+
+struct rsa_meth_st
+	{
+	const char *name;
+	int (*rsa_pub_enc)(int flen,const unsigned char *from,
+			   unsigned char *to,
+			   RSA *rsa,int padding);
+	int (*rsa_pub_dec)(int flen,const unsigned char *from,
+			   unsigned char *to,
+			   RSA *rsa,int padding);
+	int (*rsa_priv_enc)(int flen,const unsigned char *from,
+			    unsigned char *to,
+			    RSA *rsa,int padding);
+	int (*rsa_priv_dec)(int flen,const unsigned char *from,
+			    unsigned char *to,
+			    RSA *rsa,int padding);
+	int (*rsa_mod_exp)(BIGNUM *r0,const BIGNUM *I,RSA *rsa,BN_CTX *ctx); /* Can be null */
+	int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+			  const BIGNUM *m, BN_CTX *ctx,
+			  BN_MONT_CTX *m_ctx); /* Can be null */
+	int (*init)(RSA *rsa);		/* called at new */
+	int (*finish)(RSA *rsa);	/* called at free */
+	int flags;			/* RSA_METHOD_FLAG_* things */
+	char *app_data;			/* may be needed! */
+/* New sign and verify functions: some libraries don't allow arbitrary data
+ * to be signed/verified: this allows them to be used. Note: for this to work
+ * the RSA_public_decrypt() and RSA_private_encrypt() should *NOT* be used
+ * RSA_sign(), RSA_verify() should be used instead. Note: for backwards
+ * compatibility this functionality is only enabled if the RSA_FLAG_SIGN_VER
+ * option is set in 'flags'.
+ */
+	int (*rsa_sign)(int type,
+		const unsigned char *m, unsigned int m_length,
+		unsigned char *sigret, unsigned int *siglen, const RSA *rsa);
+	int (*rsa_verify)(int dtype,
+		const unsigned char *m, unsigned int m_length,
+		unsigned char *sigbuf, unsigned int siglen, const RSA *rsa);
+/* If this callback is NULL, the builtin software RSA key-gen will be used. This
+ * is for behavioural compatibility whilst the code gets rewired, but one day
+ * it would be nice to assume there are no such things as "builtin software"
+ * implementations. */
+	int (*rsa_keygen)(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
+	};
+
+struct rsa_st
+	{
+	/* The first parameter is used to pickup errors where
+	 * this is passed instead of aEVP_PKEY, it is set to 0 */
+	int pad;
+	long version;
+	const RSA_METHOD *meth;
+	/* functional reference if 'meth' is ENGINE-provided */
+	ENGINE *engine;
+	BIGNUM *n;
+	BIGNUM *e;
+	BIGNUM *d;
+	BIGNUM *p;
+	BIGNUM *q;
+	BIGNUM *dmp1;
+	BIGNUM *dmq1;
+	BIGNUM *iqmp;
+	/* be careful using this if the RSA structure is shared */
+	CRYPTO_EX_DATA ex_data;
+	int references;
+	int flags;
+
+	/* Used to cache montgomery values */
+	BN_MONT_CTX *_method_mod_n;
+	BN_MONT_CTX *_method_mod_p;
+	BN_MONT_CTX *_method_mod_q;
+
+	/* all BIGNUM values are actually in the following data, if it is not
+	 * NULL */
+	char *bignum_data;
+	BN_BLINDING *blinding;
+	BN_BLINDING *mt_blinding;
+	};
+
+#ifndef OPENSSL_RSA_MAX_MODULUS_BITS
+# define OPENSSL_RSA_MAX_MODULUS_BITS	16384
+#endif
+
+#ifndef OPENSSL_RSA_SMALL_MODULUS_BITS
+# define OPENSSL_RSA_SMALL_MODULUS_BITS	3072
+#endif
+#ifndef OPENSSL_RSA_MAX_PUBEXP_BITS
+# define OPENSSL_RSA_MAX_PUBEXP_BITS	64 /* exponent limit enforced for "large" modulus only */
+#endif
+
+#define RSA_3	0x3L
+#define RSA_F4	0x10001L
+
+#define RSA_METHOD_FLAG_NO_CHECK	0x0001 /* don't check pub/private match */
+
+#define RSA_FLAG_CACHE_PUBLIC		0x0002
+#define RSA_FLAG_CACHE_PRIVATE		0x0004
+#define RSA_FLAG_BLINDING		0x0008
+#define RSA_FLAG_THREAD_SAFE		0x0010
+/* This flag means the private key operations will be handled by rsa_mod_exp
+ * and that they do not depend on the private key components being present:
+ * for example a key stored in external hardware. Without this flag bn_mod_exp
+ * gets called when private key components are absent.
+ */
+#define RSA_FLAG_EXT_PKEY		0x0020
+
+/* This flag in the RSA_METHOD enables the new rsa_sign, rsa_verify functions.
+ */
+#define RSA_FLAG_SIGN_VER		0x0040
+
+#define RSA_FLAG_NO_BLINDING		0x0080 /* new with 0.9.6j and 0.9.7b; the built-in
+                                                * RSA implementation now uses blinding by
+                                                * default (ignoring RSA_FLAG_BLINDING),
+                                                * but other engines might not need it
+                                                */
+#define RSA_FLAG_NO_EXP_CONSTTIME	0x0100 /* new with 0.9.7h; the built-in RSA
+                                                * implementation now uses constant time
+                                                * modular exponentiation for secret exponents
+                                                * by default. This flag causes the
+                                                * faster variable sliding window method to
+                                                * be used for all exponents.
+                                                */
+
+#define RSA_PKCS1_PADDING	1
+#define RSA_SSLV23_PADDING	2
+#define RSA_NO_PADDING		3
+#define RSA_PKCS1_OAEP_PADDING	4
+#define RSA_X931_PADDING	5
+
+#define RSA_PKCS1_PADDING_SIZE	11
+
+#define RSA_set_app_data(s,arg)         RSA_set_ex_data(s,0,arg)
+#define RSA_get_app_data(s)             RSA_get_ex_data(s,0)
+
+RSA *	RSA_new(void);
+RSA *	RSA_new_method(ENGINE *engine);
+int	RSA_size(const RSA *);
+
+/* Deprecated version */
+#ifndef OPENSSL_NO_DEPRECATED
+RSA *	RSA_generate_key(int bits, unsigned long e,void
+		(*callback)(int,int,void *),void *cb_arg);
+#endif /* !defined(OPENSSL_NO_DEPRECATED) */
+
+/* New version */
+int	RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
+
+int	RSA_check_key(const RSA *);
+	/* next 4 return -1 on error */
+int	RSA_public_encrypt(int flen, const unsigned char *from,
+		unsigned char *to, RSA *rsa,int padding);
+int	RSA_private_encrypt(int flen, const unsigned char *from,
+		unsigned char *to, RSA *rsa,int padding);
+int	RSA_public_decrypt(int flen, const unsigned char *from, 
+		unsigned char *to, RSA *rsa,int padding);
+int	RSA_private_decrypt(int flen, const unsigned char *from, 
+		unsigned char *to, RSA *rsa,int padding);
+void	RSA_free (RSA *r);
+/* "up" the RSA object's reference count */
+int	RSA_up_ref(RSA *r);
+
+int	RSA_flags(const RSA *r);
+
+void RSA_set_default_method(const RSA_METHOD *meth);
+const RSA_METHOD *RSA_get_default_method(void);
+const RSA_METHOD *RSA_get_method(const RSA *rsa);
+int RSA_set_method(RSA *rsa, const RSA_METHOD *meth);
+
+/* This function needs the memory locking malloc callbacks to be installed */
+int RSA_memory_lock(RSA *r);
+
+/* these are the actual SSLeay RSA functions */
+const RSA_METHOD *RSA_PKCS1_SSLeay(void);
+
+const RSA_METHOD *RSA_null_method(void);
+
+DECLARE_ASN1_ENCODE_FUNCTIONS_const(RSA, RSAPublicKey)
+DECLARE_ASN1_ENCODE_FUNCTIONS_const(RSA, RSAPrivateKey)
+
+#ifndef OPENSSL_NO_FP_API
+int	RSA_print_fp(FILE *fp, const RSA *r,int offset);
+#endif
+
+#ifndef OPENSSL_NO_BIO
+int	RSA_print(BIO *bp, const RSA *r,int offset);
+#endif
+
+int i2d_RSA_NET(const RSA *a, unsigned char **pp,
+		int (*cb)(char *buf, int len, const char *prompt, int verify),
+		int sgckey);
+RSA *d2i_RSA_NET(RSA **a, const unsigned char **pp, long length,
+		 int (*cb)(char *buf, int len, const char *prompt, int verify),
+		 int sgckey);
+
+int i2d_Netscape_RSA(const RSA *a, unsigned char **pp,
+		     int (*cb)(char *buf, int len, const char *prompt,
+			       int verify));
+RSA *d2i_Netscape_RSA(RSA **a, const unsigned char **pp, long length,
+		      int (*cb)(char *buf, int len, const char *prompt,
+				int verify));
+
+/* The following 2 functions sign and verify a X509_SIG ASN1 object
+ * inside PKCS#1 padded RSA encryption */
+int RSA_sign(int type, const unsigned char *m, unsigned int m_length,
+	unsigned char *sigret, unsigned int *siglen, RSA *rsa);
+int RSA_verify(int type, const unsigned char *m, unsigned int m_length,
+	unsigned char *sigbuf, unsigned int siglen, RSA *rsa);
+
+/* The following 2 function sign and verify a ASN1_OCTET_STRING
+ * object inside PKCS#1 padded RSA encryption */
+int RSA_sign_ASN1_OCTET_STRING(int type,
+	const unsigned char *m, unsigned int m_length,
+	unsigned char *sigret, unsigned int *siglen, RSA *rsa);
+int RSA_verify_ASN1_OCTET_STRING(int type,
+	const unsigned char *m, unsigned int m_length,
+	unsigned char *sigbuf, unsigned int siglen, RSA *rsa);
+
+int RSA_blinding_on(RSA *rsa, BN_CTX *ctx);
+void RSA_blinding_off(RSA *rsa);
+BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *ctx);
+
+int RSA_padding_add_PKCS1_type_1(unsigned char *to,int tlen,
+	const unsigned char *f,int fl);
+int RSA_padding_check_PKCS1_type_1(unsigned char *to,int tlen,
+	const unsigned char *f,int fl,int rsa_len);
+int RSA_padding_add_PKCS1_type_2(unsigned char *to,int tlen,
+	const unsigned char *f,int fl);
+int RSA_padding_check_PKCS1_type_2(unsigned char *to,int tlen,
+	const unsigned char *f,int fl,int rsa_len);
+int PKCS1_MGF1(unsigned char *mask, long len,
+	const unsigned char *seed, long seedlen, const EVP_MD *dgst);
+int RSA_padding_add_PKCS1_OAEP(unsigned char *to,int tlen,
+	const unsigned char *f,int fl,
+	const unsigned char *p,int pl);
+int RSA_padding_check_PKCS1_OAEP(unsigned char *to,int tlen,
+	const unsigned char *f,int fl,int rsa_len,
+	const unsigned char *p,int pl);
+int RSA_padding_add_SSLv23(unsigned char *to,int tlen,
+	const unsigned char *f,int fl);
+int RSA_padding_check_SSLv23(unsigned char *to,int tlen,
+	const unsigned char *f,int fl,int rsa_len);
+int RSA_padding_add_none(unsigned char *to,int tlen,
+	const unsigned char *f,int fl);
+int RSA_padding_check_none(unsigned char *to,int tlen,
+	const unsigned char *f,int fl,int rsa_len);
+int RSA_padding_add_X931(unsigned char *to,int tlen,
+	const unsigned char *f,int fl);
+int RSA_padding_check_X931(unsigned char *to,int tlen,
+	const unsigned char *f,int fl,int rsa_len);
+int RSA_X931_hash_id(int nid);
+
+int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash,
+			const EVP_MD *Hash, const unsigned char *EM, int sLen);
+int RSA_padding_add_PKCS1_PSS(RSA *rsa, unsigned char *EM,
+			const unsigned char *mHash,
+			const EVP_MD *Hash, int sLen);
+
+int RSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+	CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int RSA_set_ex_data(RSA *r,int idx,void *arg);
+void *RSA_get_ex_data(const RSA *r, int idx);
+
+RSA *RSAPublicKey_dup(RSA *rsa);
+RSA *RSAPrivateKey_dup(RSA *rsa);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_RSA_strings(void);
+
+/* Error codes for the RSA functions. */
+
+/* Function codes. */
+#define RSA_F_MEMORY_LOCK				 100
+#define RSA_F_RSA_BUILTIN_KEYGEN			 129
+#define RSA_F_RSA_CHECK_KEY				 123
+#define RSA_F_RSA_EAY_PRIVATE_DECRYPT			 101
+#define RSA_F_RSA_EAY_PRIVATE_ENCRYPT			 102
+#define RSA_F_RSA_EAY_PUBLIC_DECRYPT			 103
+#define RSA_F_RSA_EAY_PUBLIC_ENCRYPT			 104
+#define RSA_F_RSA_GENERATE_KEY				 105
+#define RSA_F_RSA_MEMORY_LOCK				 130
+#define RSA_F_RSA_NEW_METHOD				 106
+#define RSA_F_RSA_NULL					 124
+#define RSA_F_RSA_NULL_MOD_EXP				 131
+#define RSA_F_RSA_NULL_PRIVATE_DECRYPT			 132
+#define RSA_F_RSA_NULL_PRIVATE_ENCRYPT			 133
+#define RSA_F_RSA_NULL_PUBLIC_DECRYPT			 134
+#define RSA_F_RSA_NULL_PUBLIC_ENCRYPT			 135
+#define RSA_F_RSA_PADDING_ADD_NONE			 107
+#define RSA_F_RSA_PADDING_ADD_PKCS1_OAEP		 121
+#define RSA_F_RSA_PADDING_ADD_PKCS1_PSS			 125
+#define RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1		 108
+#define RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2		 109
+#define RSA_F_RSA_PADDING_ADD_SSLV23			 110
+#define RSA_F_RSA_PADDING_ADD_X931			 127
+#define RSA_F_RSA_PADDING_CHECK_NONE			 111
+#define RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP		 122
+#define RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1		 112
+#define RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2		 113
+#define RSA_F_RSA_PADDING_CHECK_SSLV23			 114
+#define RSA_F_RSA_PADDING_CHECK_X931			 128
+#define RSA_F_RSA_PRINT					 115
+#define RSA_F_RSA_PRINT_FP				 116
+#define RSA_F_RSA_SETUP_BLINDING			 136
+#define RSA_F_RSA_SIGN					 117
+#define RSA_F_RSA_SIGN_ASN1_OCTET_STRING		 118
+#define RSA_F_RSA_VERIFY				 119
+#define RSA_F_RSA_VERIFY_ASN1_OCTET_STRING		 120
+#define RSA_F_RSA_VERIFY_PKCS1_PSS			 126
+
+/* Reason codes. */
+#define RSA_R_ALGORITHM_MISMATCH			 100
+#define RSA_R_BAD_E_VALUE				 101
+#define RSA_R_BAD_FIXED_HEADER_DECRYPT			 102
+#define RSA_R_BAD_PAD_BYTE_COUNT			 103
+#define RSA_R_BAD_SIGNATURE				 104
+#define RSA_R_BLOCK_TYPE_IS_NOT_01			 106
+#define RSA_R_BLOCK_TYPE_IS_NOT_02			 107
+#define RSA_R_DATA_GREATER_THAN_MOD_LEN			 108
+#define RSA_R_DATA_TOO_LARGE				 109
+#define RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE		 110
+#define RSA_R_DATA_TOO_LARGE_FOR_MODULUS		 132
+#define RSA_R_DATA_TOO_SMALL				 111
+#define RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE		 122
+#define RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY		 112
+#define RSA_R_DMP1_NOT_CONGRUENT_TO_D			 124
+#define RSA_R_DMQ1_NOT_CONGRUENT_TO_D			 125
+#define RSA_R_D_E_NOT_CONGRUENT_TO_1			 123
+#define RSA_R_FIRST_OCTET_INVALID			 133
+#define RSA_R_INVALID_HEADER				 137
+#define RSA_R_INVALID_MESSAGE_LENGTH			 131
+#define RSA_R_INVALID_PADDING				 138
+#define RSA_R_INVALID_TRAILER				 139
+#define RSA_R_IQMP_NOT_INVERSE_OF_Q			 126
+#define RSA_R_KEY_SIZE_TOO_SMALL			 120
+#define RSA_R_LAST_OCTET_INVALID			 134
+#define RSA_R_MODULUS_TOO_LARGE				 105
+#define RSA_R_NO_PUBLIC_EXPONENT			 140
+#define RSA_R_NULL_BEFORE_BLOCK_MISSING			 113
+#define RSA_R_N_DOES_NOT_EQUAL_P_Q			 127
+#define RSA_R_OAEP_DECODING_ERROR			 121
+#define RSA_R_PADDING_CHECK_FAILED			 114
+#define RSA_R_P_NOT_PRIME				 128
+#define RSA_R_Q_NOT_PRIME				 129
+#define RSA_R_RSA_OPERATIONS_NOT_SUPPORTED		 130
+#define RSA_R_SLEN_CHECK_FAILED				 136
+#define RSA_R_SLEN_RECOVERY_FAILED			 135
+#define RSA_R_SSLV3_ROLLBACK_ATTACK			 115
+#define RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 116
+#define RSA_R_UNKNOWN_ALGORITHM_TYPE			 117
+#define RSA_R_UNKNOWN_PADDING_TYPE			 118
+#define RSA_R_WRONG_SIGNATURE_LENGTH			 119
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/dep/include/openssl/safestack.h b/dep/include/openssl/safestack.h
new file mode 100644
index 00000000000..d496f365c27
--- /dev/null
+++ b/dep/include/openssl/safestack.h
@@ -0,0 +1,1850 @@
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_SAFESTACK_H
+#define HEADER_SAFESTACK_H
+
+#include 
+
+typedef void (*openssl_fptr)(void);
+#define openssl_fcast(f) ((openssl_fptr)f)
+
+#ifdef DEBUG_SAFESTACK
+
+#define STACK_OF(type) struct stack_st_##type
+#define PREDECLARE_STACK_OF(type) STACK_OF(type);
+
+#define DECLARE_STACK_OF(type) \
+STACK_OF(type) \
+    { \
+    STACK stack; \
+    };
+
+#define IMPLEMENT_STACK_OF(type) /* nada (obsolete in new safestack approach)*/
+
+/* SKM_sk_... stack macros are internal to safestack.h:
+ * never use them directly, use sk__... instead */
+#define SKM_sk_new(type, cmp) \
+	((STACK_OF(type) * (*)(int (*)(const type * const *, const type * const *)))openssl_fcast(sk_new))(cmp)
+#define SKM_sk_new_null(type) \
+	((STACK_OF(type) * (*)(void))openssl_fcast(sk_new_null))()
+#define SKM_sk_free(type, st) \
+	((void (*)(STACK_OF(type) *))openssl_fcast(sk_free))(st)
+#define SKM_sk_num(type, st) \
+	((int (*)(const STACK_OF(type) *))openssl_fcast(sk_num))(st)
+#define SKM_sk_value(type, st,i) \
+	((type * (*)(const STACK_OF(type) *, int))openssl_fcast(sk_value))(st, i)
+#define SKM_sk_set(type, st,i,val) \
+	((type * (*)(STACK_OF(type) *, int, type *))openssl_fcast(sk_set))(st, i, val)
+#define SKM_sk_zero(type, st) \
+	((void (*)(STACK_OF(type) *))openssl_fcast(sk_zero))(st)
+#define SKM_sk_push(type, st,val) \
+	((int (*)(STACK_OF(type) *, type *))openssl_fcast(sk_push))(st, val)
+#define SKM_sk_unshift(type, st,val) \
+	((int (*)(STACK_OF(type) *, type *))openssl_fcast(sk_unshift))(st, val)
+#define SKM_sk_find(type, st,val) \
+	((int (*)(STACK_OF(type) *, type *))openssl_fcast(sk_find))(st, val)
+#define SKM_sk_delete(type, st,i) \
+	((type * (*)(STACK_OF(type) *, int))openssl_fcast(sk_delete))(st, i)
+#define SKM_sk_delete_ptr(type, st,ptr) \
+	((type * (*)(STACK_OF(type) *, type *))openssl_fcast(sk_delete_ptr))(st, ptr)
+#define SKM_sk_insert(type, st,val,i) \
+	((int (*)(STACK_OF(type) *, type *, int))openssl_fcast(sk_insert))(st, val, i)
+#define SKM_sk_set_cmp_func(type, st,cmp) \
+	((int (*(*)(STACK_OF(type) *, int (*)(const type * const *, const type * const *))) \
+	  (const type * const *, const type * const *))openssl_fcast(sk_set_cmp_func))\
+	(st, cmp)
+#define SKM_sk_dup(type, st) \
+	((STACK_OF(type) *(*)(STACK_OF(type) *))openssl_fcast(sk_dup))(st)
+#define SKM_sk_pop_free(type, st,free_func) \
+	((void (*)(STACK_OF(type) *, void (*)(type *)))openssl_fcast(sk_pop_free))\
+	(st, free_func)
+#define SKM_sk_shift(type, st) \
+	((type * (*)(STACK_OF(type) *))openssl_fcast(sk_shift))(st)
+#define SKM_sk_pop(type, st) \
+	((type * (*)(STACK_OF(type) *))openssl_fcast(sk_pop))(st)
+#define SKM_sk_sort(type, st) \
+	((void (*)(STACK_OF(type) *))openssl_fcast(sk_sort))(st)
+#define SKM_sk_is_sorted(type, st) \
+	((int (*)(const STACK_OF(type) *))openssl_fcast(sk_is_sorted))(st)
+
+#define	SKM_ASN1_SET_OF_d2i(type, st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+((STACK_OF(type) * (*) (STACK_OF(type) **,const unsigned char **, long , \
+                         type *(*)(type **, const unsigned char **,long), \
+                                void (*)(type *), int ,int )) openssl_fcast(d2i_ASN1_SET)) \
+			(st,pp,length, d2i_func, free_func, ex_tag,ex_class)
+#define	SKM_ASN1_SET_OF_i2d(type, st, pp, i2d_func, ex_tag, ex_class, is_set) \
+	((int (*)(STACK_OF(type) *,unsigned char **, \
+        int (*)(type *,unsigned char **), int , int , int)) openssl_fcast(i2d_ASN1_SET)) \
+						(st,pp,i2d_func,ex_tag,ex_class,is_set)
+
+#define	SKM_ASN1_seq_pack(type, st, i2d_func, buf, len) \
+	((unsigned char *(*)(STACK_OF(type) *, \
+        int (*)(type *,unsigned char **), unsigned char **,int *)) openssl_fcast(ASN1_seq_pack)) \
+				(st, i2d_func, buf, len)
+#define	SKM_ASN1_seq_unpack(type, buf, len, d2i_func, free_func) \
+	((STACK_OF(type) * (*)(const unsigned char *,int, \
+                              type *(*)(type **,const unsigned char **, long), \
+                              void (*)(type *)))openssl_fcast(ASN1_seq_unpack)) \
+					(buf,len,d2i_func, free_func)
+
+#define SKM_PKCS12_decrypt_d2i(type, algor, d2i_func, free_func, pass, passlen, oct, seq) \
+	((STACK_OF(type) * (*)(X509_ALGOR *, \
+            		type *(*)(type **, const unsigned char **, long), \
+				void (*)(type *), \
+                                const char *, int, \
+                                ASN1_STRING *, int))PKCS12_decrypt_d2i) \
+				(algor,d2i_func,free_func,pass,passlen,oct,seq)
+
+#else
+
+#define STACK_OF(type) STACK
+#define PREDECLARE_STACK_OF(type) /* nada */
+#define DECLARE_STACK_OF(type)    /* nada */
+#define IMPLEMENT_STACK_OF(type)  /* nada */
+
+#define SKM_sk_new(type, cmp) \
+	sk_new((int (*)(const char * const *, const char * const *))(cmp))
+#define SKM_sk_new_null(type) \
+	sk_new_null()
+#define SKM_sk_free(type, st) \
+	sk_free(st)
+#define SKM_sk_num(type, st) \
+	sk_num(st)
+#define SKM_sk_value(type, st,i) \
+	((type *)sk_value(st, i))
+#define SKM_sk_set(type, st,i,val) \
+	((type *)sk_set(st, i,(char *)val))
+#define SKM_sk_zero(type, st) \
+	sk_zero(st)
+#define SKM_sk_push(type, st,val) \
+	sk_push(st, (char *)val)
+#define SKM_sk_unshift(type, st,val) \
+	sk_unshift(st, val)
+#define SKM_sk_find(type, st,val) \
+	sk_find(st, (char *)val)
+#define SKM_sk_delete(type, st,i) \
+	((type *)sk_delete(st, i))
+#define SKM_sk_delete_ptr(type, st,ptr) \
+	((type *)sk_delete_ptr(st,(char *)ptr))
+#define SKM_sk_insert(type, st,val,i) \
+	sk_insert(st, (char *)val, i)
+#define SKM_sk_set_cmp_func(type, st,cmp) \
+	((int (*)(const type * const *,const type * const *)) \
+	sk_set_cmp_func(st, (int (*)(const char * const *, const char * const *))(cmp)))
+#define SKM_sk_dup(type, st) \
+	sk_dup(st)
+#define SKM_sk_pop_free(type, st,free_func) \
+	sk_pop_free(st, (void (*)(void *))free_func)
+#define SKM_sk_shift(type, st) \
+	((type *)sk_shift(st))
+#define SKM_sk_pop(type, st) \
+	((type *)sk_pop(st))
+#define SKM_sk_sort(type, st) \
+	sk_sort(st)
+#define SKM_sk_is_sorted(type, st) \
+	sk_is_sorted(st)
+
+#define	SKM_ASN1_SET_OF_d2i(type, st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+	d2i_ASN1_SET(st,pp,length, (void *(*)(void ** ,const unsigned char ** ,long))d2i_func, (void (*)(void *))free_func, ex_tag,ex_class)
+#define	SKM_ASN1_SET_OF_i2d(type, st, pp, i2d_func, ex_tag, ex_class, is_set) \
+	i2d_ASN1_SET(st,pp,(int (*)(void *, unsigned char **))i2d_func,ex_tag,ex_class,is_set)
+
+#define	SKM_ASN1_seq_pack(type, st, i2d_func, buf, len) \
+	ASN1_seq_pack(st, (int (*)(void *, unsigned char **))i2d_func, buf, len)
+#define	SKM_ASN1_seq_unpack(type, buf, len, d2i_func, free_func) \
+	ASN1_seq_unpack(buf,len,(void *(*)(void **,const unsigned char **,long))d2i_func, (void(*)(void *))free_func)
+
+#define SKM_PKCS12_decrypt_d2i(type, algor, d2i_func, free_func, pass, passlen, oct, seq) \
+	((STACK *)PKCS12_decrypt_d2i(algor,(char *(*)())d2i_func, (void(*)(void *))free_func,pass,passlen,oct,seq))
+
+#endif
+
+/* This block of defines is updated by util/mkstack.pl, please do not touch! */
+#define sk_ACCESS_DESCRIPTION_new(st) SKM_sk_new(ACCESS_DESCRIPTION, (st))
+#define sk_ACCESS_DESCRIPTION_new_null() SKM_sk_new_null(ACCESS_DESCRIPTION)
+#define sk_ACCESS_DESCRIPTION_free(st) SKM_sk_free(ACCESS_DESCRIPTION, (st))
+#define sk_ACCESS_DESCRIPTION_num(st) SKM_sk_num(ACCESS_DESCRIPTION, (st))
+#define sk_ACCESS_DESCRIPTION_value(st, i) SKM_sk_value(ACCESS_DESCRIPTION, (st), (i))
+#define sk_ACCESS_DESCRIPTION_set(st, i, val) SKM_sk_set(ACCESS_DESCRIPTION, (st), (i), (val))
+#define sk_ACCESS_DESCRIPTION_zero(st) SKM_sk_zero(ACCESS_DESCRIPTION, (st))
+#define sk_ACCESS_DESCRIPTION_push(st, val) SKM_sk_push(ACCESS_DESCRIPTION, (st), (val))
+#define sk_ACCESS_DESCRIPTION_unshift(st, val) SKM_sk_unshift(ACCESS_DESCRIPTION, (st), (val))
+#define sk_ACCESS_DESCRIPTION_find(st, val) SKM_sk_find(ACCESS_DESCRIPTION, (st), (val))
+#define sk_ACCESS_DESCRIPTION_find_ex(st, val) SKM_sk_find_ex(ACCESS_DESCRIPTION, (st), (val))
+#define sk_ACCESS_DESCRIPTION_delete(st, i) SKM_sk_delete(ACCESS_DESCRIPTION, (st), (i))
+#define sk_ACCESS_DESCRIPTION_delete_ptr(st, ptr) SKM_sk_delete_ptr(ACCESS_DESCRIPTION, (st), (ptr))
+#define sk_ACCESS_DESCRIPTION_insert(st, val, i) SKM_sk_insert(ACCESS_DESCRIPTION, (st), (val), (i))
+#define sk_ACCESS_DESCRIPTION_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ACCESS_DESCRIPTION, (st), (cmp))
+#define sk_ACCESS_DESCRIPTION_dup(st) SKM_sk_dup(ACCESS_DESCRIPTION, st)
+#define sk_ACCESS_DESCRIPTION_pop_free(st, free_func) SKM_sk_pop_free(ACCESS_DESCRIPTION, (st), (free_func))
+#define sk_ACCESS_DESCRIPTION_shift(st) SKM_sk_shift(ACCESS_DESCRIPTION, (st))
+#define sk_ACCESS_DESCRIPTION_pop(st) SKM_sk_pop(ACCESS_DESCRIPTION, (st))
+#define sk_ACCESS_DESCRIPTION_sort(st) SKM_sk_sort(ACCESS_DESCRIPTION, (st))
+#define sk_ACCESS_DESCRIPTION_is_sorted(st) SKM_sk_is_sorted(ACCESS_DESCRIPTION, (st))
+
+#define sk_ASIdOrRange_new(st) SKM_sk_new(ASIdOrRange, (st))
+#define sk_ASIdOrRange_new_null() SKM_sk_new_null(ASIdOrRange)
+#define sk_ASIdOrRange_free(st) SKM_sk_free(ASIdOrRange, (st))
+#define sk_ASIdOrRange_num(st) SKM_sk_num(ASIdOrRange, (st))
+#define sk_ASIdOrRange_value(st, i) SKM_sk_value(ASIdOrRange, (st), (i))
+#define sk_ASIdOrRange_set(st, i, val) SKM_sk_set(ASIdOrRange, (st), (i), (val))
+#define sk_ASIdOrRange_zero(st) SKM_sk_zero(ASIdOrRange, (st))
+#define sk_ASIdOrRange_push(st, val) SKM_sk_push(ASIdOrRange, (st), (val))
+#define sk_ASIdOrRange_unshift(st, val) SKM_sk_unshift(ASIdOrRange, (st), (val))
+#define sk_ASIdOrRange_find(st, val) SKM_sk_find(ASIdOrRange, (st), (val))
+#define sk_ASIdOrRange_find_ex(st, val) SKM_sk_find_ex(ASIdOrRange, (st), (val))
+#define sk_ASIdOrRange_delete(st, i) SKM_sk_delete(ASIdOrRange, (st), (i))
+#define sk_ASIdOrRange_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASIdOrRange, (st), (ptr))
+#define sk_ASIdOrRange_insert(st, val, i) SKM_sk_insert(ASIdOrRange, (st), (val), (i))
+#define sk_ASIdOrRange_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASIdOrRange, (st), (cmp))
+#define sk_ASIdOrRange_dup(st) SKM_sk_dup(ASIdOrRange, st)
+#define sk_ASIdOrRange_pop_free(st, free_func) SKM_sk_pop_free(ASIdOrRange, (st), (free_func))
+#define sk_ASIdOrRange_shift(st) SKM_sk_shift(ASIdOrRange, (st))
+#define sk_ASIdOrRange_pop(st) SKM_sk_pop(ASIdOrRange, (st))
+#define sk_ASIdOrRange_sort(st) SKM_sk_sort(ASIdOrRange, (st))
+#define sk_ASIdOrRange_is_sorted(st) SKM_sk_is_sorted(ASIdOrRange, (st))
+
+#define sk_ASN1_GENERALSTRING_new(st) SKM_sk_new(ASN1_GENERALSTRING, (st))
+#define sk_ASN1_GENERALSTRING_new_null() SKM_sk_new_null(ASN1_GENERALSTRING)
+#define sk_ASN1_GENERALSTRING_free(st) SKM_sk_free(ASN1_GENERALSTRING, (st))
+#define sk_ASN1_GENERALSTRING_num(st) SKM_sk_num(ASN1_GENERALSTRING, (st))
+#define sk_ASN1_GENERALSTRING_value(st, i) SKM_sk_value(ASN1_GENERALSTRING, (st), (i))
+#define sk_ASN1_GENERALSTRING_set(st, i, val) SKM_sk_set(ASN1_GENERALSTRING, (st), (i), (val))
+#define sk_ASN1_GENERALSTRING_zero(st) SKM_sk_zero(ASN1_GENERALSTRING, (st))
+#define sk_ASN1_GENERALSTRING_push(st, val) SKM_sk_push(ASN1_GENERALSTRING, (st), (val))
+#define sk_ASN1_GENERALSTRING_unshift(st, val) SKM_sk_unshift(ASN1_GENERALSTRING, (st), (val))
+#define sk_ASN1_GENERALSTRING_find(st, val) SKM_sk_find(ASN1_GENERALSTRING, (st), (val))
+#define sk_ASN1_GENERALSTRING_find_ex(st, val) SKM_sk_find_ex(ASN1_GENERALSTRING, (st), (val))
+#define sk_ASN1_GENERALSTRING_delete(st, i) SKM_sk_delete(ASN1_GENERALSTRING, (st), (i))
+#define sk_ASN1_GENERALSTRING_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_GENERALSTRING, (st), (ptr))
+#define sk_ASN1_GENERALSTRING_insert(st, val, i) SKM_sk_insert(ASN1_GENERALSTRING, (st), (val), (i))
+#define sk_ASN1_GENERALSTRING_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_GENERALSTRING, (st), (cmp))
+#define sk_ASN1_GENERALSTRING_dup(st) SKM_sk_dup(ASN1_GENERALSTRING, st)
+#define sk_ASN1_GENERALSTRING_pop_free(st, free_func) SKM_sk_pop_free(ASN1_GENERALSTRING, (st), (free_func))
+#define sk_ASN1_GENERALSTRING_shift(st) SKM_sk_shift(ASN1_GENERALSTRING, (st))
+#define sk_ASN1_GENERALSTRING_pop(st) SKM_sk_pop(ASN1_GENERALSTRING, (st))
+#define sk_ASN1_GENERALSTRING_sort(st) SKM_sk_sort(ASN1_GENERALSTRING, (st))
+#define sk_ASN1_GENERALSTRING_is_sorted(st) SKM_sk_is_sorted(ASN1_GENERALSTRING, (st))
+
+#define sk_ASN1_INTEGER_new(st) SKM_sk_new(ASN1_INTEGER, (st))
+#define sk_ASN1_INTEGER_new_null() SKM_sk_new_null(ASN1_INTEGER)
+#define sk_ASN1_INTEGER_free(st) SKM_sk_free(ASN1_INTEGER, (st))
+#define sk_ASN1_INTEGER_num(st) SKM_sk_num(ASN1_INTEGER, (st))
+#define sk_ASN1_INTEGER_value(st, i) SKM_sk_value(ASN1_INTEGER, (st), (i))
+#define sk_ASN1_INTEGER_set(st, i, val) SKM_sk_set(ASN1_INTEGER, (st), (i), (val))
+#define sk_ASN1_INTEGER_zero(st) SKM_sk_zero(ASN1_INTEGER, (st))
+#define sk_ASN1_INTEGER_push(st, val) SKM_sk_push(ASN1_INTEGER, (st), (val))
+#define sk_ASN1_INTEGER_unshift(st, val) SKM_sk_unshift(ASN1_INTEGER, (st), (val))
+#define sk_ASN1_INTEGER_find(st, val) SKM_sk_find(ASN1_INTEGER, (st), (val))
+#define sk_ASN1_INTEGER_find_ex(st, val) SKM_sk_find_ex(ASN1_INTEGER, (st), (val))
+#define sk_ASN1_INTEGER_delete(st, i) SKM_sk_delete(ASN1_INTEGER, (st), (i))
+#define sk_ASN1_INTEGER_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_INTEGER, (st), (ptr))
+#define sk_ASN1_INTEGER_insert(st, val, i) SKM_sk_insert(ASN1_INTEGER, (st), (val), (i))
+#define sk_ASN1_INTEGER_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_INTEGER, (st), (cmp))
+#define sk_ASN1_INTEGER_dup(st) SKM_sk_dup(ASN1_INTEGER, st)
+#define sk_ASN1_INTEGER_pop_free(st, free_func) SKM_sk_pop_free(ASN1_INTEGER, (st), (free_func))
+#define sk_ASN1_INTEGER_shift(st) SKM_sk_shift(ASN1_INTEGER, (st))
+#define sk_ASN1_INTEGER_pop(st) SKM_sk_pop(ASN1_INTEGER, (st))
+#define sk_ASN1_INTEGER_sort(st) SKM_sk_sort(ASN1_INTEGER, (st))
+#define sk_ASN1_INTEGER_is_sorted(st) SKM_sk_is_sorted(ASN1_INTEGER, (st))
+
+#define sk_ASN1_OBJECT_new(st) SKM_sk_new(ASN1_OBJECT, (st))
+#define sk_ASN1_OBJECT_new_null() SKM_sk_new_null(ASN1_OBJECT)
+#define sk_ASN1_OBJECT_free(st) SKM_sk_free(ASN1_OBJECT, (st))
+#define sk_ASN1_OBJECT_num(st) SKM_sk_num(ASN1_OBJECT, (st))
+#define sk_ASN1_OBJECT_value(st, i) SKM_sk_value(ASN1_OBJECT, (st), (i))
+#define sk_ASN1_OBJECT_set(st, i, val) SKM_sk_set(ASN1_OBJECT, (st), (i), (val))
+#define sk_ASN1_OBJECT_zero(st) SKM_sk_zero(ASN1_OBJECT, (st))
+#define sk_ASN1_OBJECT_push(st, val) SKM_sk_push(ASN1_OBJECT, (st), (val))
+#define sk_ASN1_OBJECT_unshift(st, val) SKM_sk_unshift(ASN1_OBJECT, (st), (val))
+#define sk_ASN1_OBJECT_find(st, val) SKM_sk_find(ASN1_OBJECT, (st), (val))
+#define sk_ASN1_OBJECT_find_ex(st, val) SKM_sk_find_ex(ASN1_OBJECT, (st), (val))
+#define sk_ASN1_OBJECT_delete(st, i) SKM_sk_delete(ASN1_OBJECT, (st), (i))
+#define sk_ASN1_OBJECT_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_OBJECT, (st), (ptr))
+#define sk_ASN1_OBJECT_insert(st, val, i) SKM_sk_insert(ASN1_OBJECT, (st), (val), (i))
+#define sk_ASN1_OBJECT_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_OBJECT, (st), (cmp))
+#define sk_ASN1_OBJECT_dup(st) SKM_sk_dup(ASN1_OBJECT, st)
+#define sk_ASN1_OBJECT_pop_free(st, free_func) SKM_sk_pop_free(ASN1_OBJECT, (st), (free_func))
+#define sk_ASN1_OBJECT_shift(st) SKM_sk_shift(ASN1_OBJECT, (st))
+#define sk_ASN1_OBJECT_pop(st) SKM_sk_pop(ASN1_OBJECT, (st))
+#define sk_ASN1_OBJECT_sort(st) SKM_sk_sort(ASN1_OBJECT, (st))
+#define sk_ASN1_OBJECT_is_sorted(st) SKM_sk_is_sorted(ASN1_OBJECT, (st))
+
+#define sk_ASN1_STRING_TABLE_new(st) SKM_sk_new(ASN1_STRING_TABLE, (st))
+#define sk_ASN1_STRING_TABLE_new_null() SKM_sk_new_null(ASN1_STRING_TABLE)
+#define sk_ASN1_STRING_TABLE_free(st) SKM_sk_free(ASN1_STRING_TABLE, (st))
+#define sk_ASN1_STRING_TABLE_num(st) SKM_sk_num(ASN1_STRING_TABLE, (st))
+#define sk_ASN1_STRING_TABLE_value(st, i) SKM_sk_value(ASN1_STRING_TABLE, (st), (i))
+#define sk_ASN1_STRING_TABLE_set(st, i, val) SKM_sk_set(ASN1_STRING_TABLE, (st), (i), (val))
+#define sk_ASN1_STRING_TABLE_zero(st) SKM_sk_zero(ASN1_STRING_TABLE, (st))
+#define sk_ASN1_STRING_TABLE_push(st, val) SKM_sk_push(ASN1_STRING_TABLE, (st), (val))
+#define sk_ASN1_STRING_TABLE_unshift(st, val) SKM_sk_unshift(ASN1_STRING_TABLE, (st), (val))
+#define sk_ASN1_STRING_TABLE_find(st, val) SKM_sk_find(ASN1_STRING_TABLE, (st), (val))
+#define sk_ASN1_STRING_TABLE_find_ex(st, val) SKM_sk_find_ex(ASN1_STRING_TABLE, (st), (val))
+#define sk_ASN1_STRING_TABLE_delete(st, i) SKM_sk_delete(ASN1_STRING_TABLE, (st), (i))
+#define sk_ASN1_STRING_TABLE_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_STRING_TABLE, (st), (ptr))
+#define sk_ASN1_STRING_TABLE_insert(st, val, i) SKM_sk_insert(ASN1_STRING_TABLE, (st), (val), (i))
+#define sk_ASN1_STRING_TABLE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_STRING_TABLE, (st), (cmp))
+#define sk_ASN1_STRING_TABLE_dup(st) SKM_sk_dup(ASN1_STRING_TABLE, st)
+#define sk_ASN1_STRING_TABLE_pop_free(st, free_func) SKM_sk_pop_free(ASN1_STRING_TABLE, (st), (free_func))
+#define sk_ASN1_STRING_TABLE_shift(st) SKM_sk_shift(ASN1_STRING_TABLE, (st))
+#define sk_ASN1_STRING_TABLE_pop(st) SKM_sk_pop(ASN1_STRING_TABLE, (st))
+#define sk_ASN1_STRING_TABLE_sort(st) SKM_sk_sort(ASN1_STRING_TABLE, (st))
+#define sk_ASN1_STRING_TABLE_is_sorted(st) SKM_sk_is_sorted(ASN1_STRING_TABLE, (st))
+
+#define sk_ASN1_TYPE_new(st) SKM_sk_new(ASN1_TYPE, (st))
+#define sk_ASN1_TYPE_new_null() SKM_sk_new_null(ASN1_TYPE)
+#define sk_ASN1_TYPE_free(st) SKM_sk_free(ASN1_TYPE, (st))
+#define sk_ASN1_TYPE_num(st) SKM_sk_num(ASN1_TYPE, (st))
+#define sk_ASN1_TYPE_value(st, i) SKM_sk_value(ASN1_TYPE, (st), (i))
+#define sk_ASN1_TYPE_set(st, i, val) SKM_sk_set(ASN1_TYPE, (st), (i), (val))
+#define sk_ASN1_TYPE_zero(st) SKM_sk_zero(ASN1_TYPE, (st))
+#define sk_ASN1_TYPE_push(st, val) SKM_sk_push(ASN1_TYPE, (st), (val))
+#define sk_ASN1_TYPE_unshift(st, val) SKM_sk_unshift(ASN1_TYPE, (st), (val))
+#define sk_ASN1_TYPE_find(st, val) SKM_sk_find(ASN1_TYPE, (st), (val))
+#define sk_ASN1_TYPE_find_ex(st, val) SKM_sk_find_ex(ASN1_TYPE, (st), (val))
+#define sk_ASN1_TYPE_delete(st, i) SKM_sk_delete(ASN1_TYPE, (st), (i))
+#define sk_ASN1_TYPE_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_TYPE, (st), (ptr))
+#define sk_ASN1_TYPE_insert(st, val, i) SKM_sk_insert(ASN1_TYPE, (st), (val), (i))
+#define sk_ASN1_TYPE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_TYPE, (st), (cmp))
+#define sk_ASN1_TYPE_dup(st) SKM_sk_dup(ASN1_TYPE, st)
+#define sk_ASN1_TYPE_pop_free(st, free_func) SKM_sk_pop_free(ASN1_TYPE, (st), (free_func))
+#define sk_ASN1_TYPE_shift(st) SKM_sk_shift(ASN1_TYPE, (st))
+#define sk_ASN1_TYPE_pop(st) SKM_sk_pop(ASN1_TYPE, (st))
+#define sk_ASN1_TYPE_sort(st) SKM_sk_sort(ASN1_TYPE, (st))
+#define sk_ASN1_TYPE_is_sorted(st) SKM_sk_is_sorted(ASN1_TYPE, (st))
+
+#define sk_ASN1_VALUE_new(st) SKM_sk_new(ASN1_VALUE, (st))
+#define sk_ASN1_VALUE_new_null() SKM_sk_new_null(ASN1_VALUE)
+#define sk_ASN1_VALUE_free(st) SKM_sk_free(ASN1_VALUE, (st))
+#define sk_ASN1_VALUE_num(st) SKM_sk_num(ASN1_VALUE, (st))
+#define sk_ASN1_VALUE_value(st, i) SKM_sk_value(ASN1_VALUE, (st), (i))
+#define sk_ASN1_VALUE_set(st, i, val) SKM_sk_set(ASN1_VALUE, (st), (i), (val))
+#define sk_ASN1_VALUE_zero(st) SKM_sk_zero(ASN1_VALUE, (st))
+#define sk_ASN1_VALUE_push(st, val) SKM_sk_push(ASN1_VALUE, (st), (val))
+#define sk_ASN1_VALUE_unshift(st, val) SKM_sk_unshift(ASN1_VALUE, (st), (val))
+#define sk_ASN1_VALUE_find(st, val) SKM_sk_find(ASN1_VALUE, (st), (val))
+#define sk_ASN1_VALUE_find_ex(st, val) SKM_sk_find_ex(ASN1_VALUE, (st), (val))
+#define sk_ASN1_VALUE_delete(st, i) SKM_sk_delete(ASN1_VALUE, (st), (i))
+#define sk_ASN1_VALUE_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_VALUE, (st), (ptr))
+#define sk_ASN1_VALUE_insert(st, val, i) SKM_sk_insert(ASN1_VALUE, (st), (val), (i))
+#define sk_ASN1_VALUE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_VALUE, (st), (cmp))
+#define sk_ASN1_VALUE_dup(st) SKM_sk_dup(ASN1_VALUE, st)
+#define sk_ASN1_VALUE_pop_free(st, free_func) SKM_sk_pop_free(ASN1_VALUE, (st), (free_func))
+#define sk_ASN1_VALUE_shift(st) SKM_sk_shift(ASN1_VALUE, (st))
+#define sk_ASN1_VALUE_pop(st) SKM_sk_pop(ASN1_VALUE, (st))
+#define sk_ASN1_VALUE_sort(st) SKM_sk_sort(ASN1_VALUE, (st))
+#define sk_ASN1_VALUE_is_sorted(st) SKM_sk_is_sorted(ASN1_VALUE, (st))
+
+#define sk_BIO_new(st) SKM_sk_new(BIO, (st))
+#define sk_BIO_new_null() SKM_sk_new_null(BIO)
+#define sk_BIO_free(st) SKM_sk_free(BIO, (st))
+#define sk_BIO_num(st) SKM_sk_num(BIO, (st))
+#define sk_BIO_value(st, i) SKM_sk_value(BIO, (st), (i))
+#define sk_BIO_set(st, i, val) SKM_sk_set(BIO, (st), (i), (val))
+#define sk_BIO_zero(st) SKM_sk_zero(BIO, (st))
+#define sk_BIO_push(st, val) SKM_sk_push(BIO, (st), (val))
+#define sk_BIO_unshift(st, val) SKM_sk_unshift(BIO, (st), (val))
+#define sk_BIO_find(st, val) SKM_sk_find(BIO, (st), (val))
+#define sk_BIO_find_ex(st, val) SKM_sk_find_ex(BIO, (st), (val))
+#define sk_BIO_delete(st, i) SKM_sk_delete(BIO, (st), (i))
+#define sk_BIO_delete_ptr(st, ptr) SKM_sk_delete_ptr(BIO, (st), (ptr))
+#define sk_BIO_insert(st, val, i) SKM_sk_insert(BIO, (st), (val), (i))
+#define sk_BIO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(BIO, (st), (cmp))
+#define sk_BIO_dup(st) SKM_sk_dup(BIO, st)
+#define sk_BIO_pop_free(st, free_func) SKM_sk_pop_free(BIO, (st), (free_func))
+#define sk_BIO_shift(st) SKM_sk_shift(BIO, (st))
+#define sk_BIO_pop(st) SKM_sk_pop(BIO, (st))
+#define sk_BIO_sort(st) SKM_sk_sort(BIO, (st))
+#define sk_BIO_is_sorted(st) SKM_sk_is_sorted(BIO, (st))
+
+#define sk_CONF_IMODULE_new(st) SKM_sk_new(CONF_IMODULE, (st))
+#define sk_CONF_IMODULE_new_null() SKM_sk_new_null(CONF_IMODULE)
+#define sk_CONF_IMODULE_free(st) SKM_sk_free(CONF_IMODULE, (st))
+#define sk_CONF_IMODULE_num(st) SKM_sk_num(CONF_IMODULE, (st))
+#define sk_CONF_IMODULE_value(st, i) SKM_sk_value(CONF_IMODULE, (st), (i))
+#define sk_CONF_IMODULE_set(st, i, val) SKM_sk_set(CONF_IMODULE, (st), (i), (val))
+#define sk_CONF_IMODULE_zero(st) SKM_sk_zero(CONF_IMODULE, (st))
+#define sk_CONF_IMODULE_push(st, val) SKM_sk_push(CONF_IMODULE, (st), (val))
+#define sk_CONF_IMODULE_unshift(st, val) SKM_sk_unshift(CONF_IMODULE, (st), (val))
+#define sk_CONF_IMODULE_find(st, val) SKM_sk_find(CONF_IMODULE, (st), (val))
+#define sk_CONF_IMODULE_find_ex(st, val) SKM_sk_find_ex(CONF_IMODULE, (st), (val))
+#define sk_CONF_IMODULE_delete(st, i) SKM_sk_delete(CONF_IMODULE, (st), (i))
+#define sk_CONF_IMODULE_delete_ptr(st, ptr) SKM_sk_delete_ptr(CONF_IMODULE, (st), (ptr))
+#define sk_CONF_IMODULE_insert(st, val, i) SKM_sk_insert(CONF_IMODULE, (st), (val), (i))
+#define sk_CONF_IMODULE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CONF_IMODULE, (st), (cmp))
+#define sk_CONF_IMODULE_dup(st) SKM_sk_dup(CONF_IMODULE, st)
+#define sk_CONF_IMODULE_pop_free(st, free_func) SKM_sk_pop_free(CONF_IMODULE, (st), (free_func))
+#define sk_CONF_IMODULE_shift(st) SKM_sk_shift(CONF_IMODULE, (st))
+#define sk_CONF_IMODULE_pop(st) SKM_sk_pop(CONF_IMODULE, (st))
+#define sk_CONF_IMODULE_sort(st) SKM_sk_sort(CONF_IMODULE, (st))
+#define sk_CONF_IMODULE_is_sorted(st) SKM_sk_is_sorted(CONF_IMODULE, (st))
+
+#define sk_CONF_MODULE_new(st) SKM_sk_new(CONF_MODULE, (st))
+#define sk_CONF_MODULE_new_null() SKM_sk_new_null(CONF_MODULE)
+#define sk_CONF_MODULE_free(st) SKM_sk_free(CONF_MODULE, (st))
+#define sk_CONF_MODULE_num(st) SKM_sk_num(CONF_MODULE, (st))
+#define sk_CONF_MODULE_value(st, i) SKM_sk_value(CONF_MODULE, (st), (i))
+#define sk_CONF_MODULE_set(st, i, val) SKM_sk_set(CONF_MODULE, (st), (i), (val))
+#define sk_CONF_MODULE_zero(st) SKM_sk_zero(CONF_MODULE, (st))
+#define sk_CONF_MODULE_push(st, val) SKM_sk_push(CONF_MODULE, (st), (val))
+#define sk_CONF_MODULE_unshift(st, val) SKM_sk_unshift(CONF_MODULE, (st), (val))
+#define sk_CONF_MODULE_find(st, val) SKM_sk_find(CONF_MODULE, (st), (val))
+#define sk_CONF_MODULE_find_ex(st, val) SKM_sk_find_ex(CONF_MODULE, (st), (val))
+#define sk_CONF_MODULE_delete(st, i) SKM_sk_delete(CONF_MODULE, (st), (i))
+#define sk_CONF_MODULE_delete_ptr(st, ptr) SKM_sk_delete_ptr(CONF_MODULE, (st), (ptr))
+#define sk_CONF_MODULE_insert(st, val, i) SKM_sk_insert(CONF_MODULE, (st), (val), (i))
+#define sk_CONF_MODULE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CONF_MODULE, (st), (cmp))
+#define sk_CONF_MODULE_dup(st) SKM_sk_dup(CONF_MODULE, st)
+#define sk_CONF_MODULE_pop_free(st, free_func) SKM_sk_pop_free(CONF_MODULE, (st), (free_func))
+#define sk_CONF_MODULE_shift(st) SKM_sk_shift(CONF_MODULE, (st))
+#define sk_CONF_MODULE_pop(st) SKM_sk_pop(CONF_MODULE, (st))
+#define sk_CONF_MODULE_sort(st) SKM_sk_sort(CONF_MODULE, (st))
+#define sk_CONF_MODULE_is_sorted(st) SKM_sk_is_sorted(CONF_MODULE, (st))
+
+#define sk_CONF_VALUE_new(st) SKM_sk_new(CONF_VALUE, (st))
+#define sk_CONF_VALUE_new_null() SKM_sk_new_null(CONF_VALUE)
+#define sk_CONF_VALUE_free(st) SKM_sk_free(CONF_VALUE, (st))
+#define sk_CONF_VALUE_num(st) SKM_sk_num(CONF_VALUE, (st))
+#define sk_CONF_VALUE_value(st, i) SKM_sk_value(CONF_VALUE, (st), (i))
+#define sk_CONF_VALUE_set(st, i, val) SKM_sk_set(CONF_VALUE, (st), (i), (val))
+#define sk_CONF_VALUE_zero(st) SKM_sk_zero(CONF_VALUE, (st))
+#define sk_CONF_VALUE_push(st, val) SKM_sk_push(CONF_VALUE, (st), (val))
+#define sk_CONF_VALUE_unshift(st, val) SKM_sk_unshift(CONF_VALUE, (st), (val))
+#define sk_CONF_VALUE_find(st, val) SKM_sk_find(CONF_VALUE, (st), (val))
+#define sk_CONF_VALUE_find_ex(st, val) SKM_sk_find_ex(CONF_VALUE, (st), (val))
+#define sk_CONF_VALUE_delete(st, i) SKM_sk_delete(CONF_VALUE, (st), (i))
+#define sk_CONF_VALUE_delete_ptr(st, ptr) SKM_sk_delete_ptr(CONF_VALUE, (st), (ptr))
+#define sk_CONF_VALUE_insert(st, val, i) SKM_sk_insert(CONF_VALUE, (st), (val), (i))
+#define sk_CONF_VALUE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CONF_VALUE, (st), (cmp))
+#define sk_CONF_VALUE_dup(st) SKM_sk_dup(CONF_VALUE, st)
+#define sk_CONF_VALUE_pop_free(st, free_func) SKM_sk_pop_free(CONF_VALUE, (st), (free_func))
+#define sk_CONF_VALUE_shift(st) SKM_sk_shift(CONF_VALUE, (st))
+#define sk_CONF_VALUE_pop(st) SKM_sk_pop(CONF_VALUE, (st))
+#define sk_CONF_VALUE_sort(st) SKM_sk_sort(CONF_VALUE, (st))
+#define sk_CONF_VALUE_is_sorted(st) SKM_sk_is_sorted(CONF_VALUE, (st))
+
+#define sk_CRYPTO_EX_DATA_FUNCS_new(st) SKM_sk_new(CRYPTO_EX_DATA_FUNCS, (st))
+#define sk_CRYPTO_EX_DATA_FUNCS_new_null() SKM_sk_new_null(CRYPTO_EX_DATA_FUNCS)
+#define sk_CRYPTO_EX_DATA_FUNCS_free(st) SKM_sk_free(CRYPTO_EX_DATA_FUNCS, (st))
+#define sk_CRYPTO_EX_DATA_FUNCS_num(st) SKM_sk_num(CRYPTO_EX_DATA_FUNCS, (st))
+#define sk_CRYPTO_EX_DATA_FUNCS_value(st, i) SKM_sk_value(CRYPTO_EX_DATA_FUNCS, (st), (i))
+#define sk_CRYPTO_EX_DATA_FUNCS_set(st, i, val) SKM_sk_set(CRYPTO_EX_DATA_FUNCS, (st), (i), (val))
+#define sk_CRYPTO_EX_DATA_FUNCS_zero(st) SKM_sk_zero(CRYPTO_EX_DATA_FUNCS, (st))
+#define sk_CRYPTO_EX_DATA_FUNCS_push(st, val) SKM_sk_push(CRYPTO_EX_DATA_FUNCS, (st), (val))
+#define sk_CRYPTO_EX_DATA_FUNCS_unshift(st, val) SKM_sk_unshift(CRYPTO_EX_DATA_FUNCS, (st), (val))
+#define sk_CRYPTO_EX_DATA_FUNCS_find(st, val) SKM_sk_find(CRYPTO_EX_DATA_FUNCS, (st), (val))
+#define sk_CRYPTO_EX_DATA_FUNCS_find_ex(st, val) SKM_sk_find_ex(CRYPTO_EX_DATA_FUNCS, (st), (val))
+#define sk_CRYPTO_EX_DATA_FUNCS_delete(st, i) SKM_sk_delete(CRYPTO_EX_DATA_FUNCS, (st), (i))
+#define sk_CRYPTO_EX_DATA_FUNCS_delete_ptr(st, ptr) SKM_sk_delete_ptr(CRYPTO_EX_DATA_FUNCS, (st), (ptr))
+#define sk_CRYPTO_EX_DATA_FUNCS_insert(st, val, i) SKM_sk_insert(CRYPTO_EX_DATA_FUNCS, (st), (val), (i))
+#define sk_CRYPTO_EX_DATA_FUNCS_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CRYPTO_EX_DATA_FUNCS, (st), (cmp))
+#define sk_CRYPTO_EX_DATA_FUNCS_dup(st) SKM_sk_dup(CRYPTO_EX_DATA_FUNCS, st)
+#define sk_CRYPTO_EX_DATA_FUNCS_pop_free(st, free_func) SKM_sk_pop_free(CRYPTO_EX_DATA_FUNCS, (st), (free_func))
+#define sk_CRYPTO_EX_DATA_FUNCS_shift(st) SKM_sk_shift(CRYPTO_EX_DATA_FUNCS, (st))
+#define sk_CRYPTO_EX_DATA_FUNCS_pop(st) SKM_sk_pop(CRYPTO_EX_DATA_FUNCS, (st))
+#define sk_CRYPTO_EX_DATA_FUNCS_sort(st) SKM_sk_sort(CRYPTO_EX_DATA_FUNCS, (st))
+#define sk_CRYPTO_EX_DATA_FUNCS_is_sorted(st) SKM_sk_is_sorted(CRYPTO_EX_DATA_FUNCS, (st))
+
+#define sk_CRYPTO_dynlock_new(st) SKM_sk_new(CRYPTO_dynlock, (st))
+#define sk_CRYPTO_dynlock_new_null() SKM_sk_new_null(CRYPTO_dynlock)
+#define sk_CRYPTO_dynlock_free(st) SKM_sk_free(CRYPTO_dynlock, (st))
+#define sk_CRYPTO_dynlock_num(st) SKM_sk_num(CRYPTO_dynlock, (st))
+#define sk_CRYPTO_dynlock_value(st, i) SKM_sk_value(CRYPTO_dynlock, (st), (i))
+#define sk_CRYPTO_dynlock_set(st, i, val) SKM_sk_set(CRYPTO_dynlock, (st), (i), (val))
+#define sk_CRYPTO_dynlock_zero(st) SKM_sk_zero(CRYPTO_dynlock, (st))
+#define sk_CRYPTO_dynlock_push(st, val) SKM_sk_push(CRYPTO_dynlock, (st), (val))
+#define sk_CRYPTO_dynlock_unshift(st, val) SKM_sk_unshift(CRYPTO_dynlock, (st), (val))
+#define sk_CRYPTO_dynlock_find(st, val) SKM_sk_find(CRYPTO_dynlock, (st), (val))
+#define sk_CRYPTO_dynlock_find_ex(st, val) SKM_sk_find_ex(CRYPTO_dynlock, (st), (val))
+#define sk_CRYPTO_dynlock_delete(st, i) SKM_sk_delete(CRYPTO_dynlock, (st), (i))
+#define sk_CRYPTO_dynlock_delete_ptr(st, ptr) SKM_sk_delete_ptr(CRYPTO_dynlock, (st), (ptr))
+#define sk_CRYPTO_dynlock_insert(st, val, i) SKM_sk_insert(CRYPTO_dynlock, (st), (val), (i))
+#define sk_CRYPTO_dynlock_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CRYPTO_dynlock, (st), (cmp))
+#define sk_CRYPTO_dynlock_dup(st) SKM_sk_dup(CRYPTO_dynlock, st)
+#define sk_CRYPTO_dynlock_pop_free(st, free_func) SKM_sk_pop_free(CRYPTO_dynlock, (st), (free_func))
+#define sk_CRYPTO_dynlock_shift(st) SKM_sk_shift(CRYPTO_dynlock, (st))
+#define sk_CRYPTO_dynlock_pop(st) SKM_sk_pop(CRYPTO_dynlock, (st))
+#define sk_CRYPTO_dynlock_sort(st) SKM_sk_sort(CRYPTO_dynlock, (st))
+#define sk_CRYPTO_dynlock_is_sorted(st) SKM_sk_is_sorted(CRYPTO_dynlock, (st))
+
+#define sk_DIST_POINT_new(st) SKM_sk_new(DIST_POINT, (st))
+#define sk_DIST_POINT_new_null() SKM_sk_new_null(DIST_POINT)
+#define sk_DIST_POINT_free(st) SKM_sk_free(DIST_POINT, (st))
+#define sk_DIST_POINT_num(st) SKM_sk_num(DIST_POINT, (st))
+#define sk_DIST_POINT_value(st, i) SKM_sk_value(DIST_POINT, (st), (i))
+#define sk_DIST_POINT_set(st, i, val) SKM_sk_set(DIST_POINT, (st), (i), (val))
+#define sk_DIST_POINT_zero(st) SKM_sk_zero(DIST_POINT, (st))
+#define sk_DIST_POINT_push(st, val) SKM_sk_push(DIST_POINT, (st), (val))
+#define sk_DIST_POINT_unshift(st, val) SKM_sk_unshift(DIST_POINT, (st), (val))
+#define sk_DIST_POINT_find(st, val) SKM_sk_find(DIST_POINT, (st), (val))
+#define sk_DIST_POINT_find_ex(st, val) SKM_sk_find_ex(DIST_POINT, (st), (val))
+#define sk_DIST_POINT_delete(st, i) SKM_sk_delete(DIST_POINT, (st), (i))
+#define sk_DIST_POINT_delete_ptr(st, ptr) SKM_sk_delete_ptr(DIST_POINT, (st), (ptr))
+#define sk_DIST_POINT_insert(st, val, i) SKM_sk_insert(DIST_POINT, (st), (val), (i))
+#define sk_DIST_POINT_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(DIST_POINT, (st), (cmp))
+#define sk_DIST_POINT_dup(st) SKM_sk_dup(DIST_POINT, st)
+#define sk_DIST_POINT_pop_free(st, free_func) SKM_sk_pop_free(DIST_POINT, (st), (free_func))
+#define sk_DIST_POINT_shift(st) SKM_sk_shift(DIST_POINT, (st))
+#define sk_DIST_POINT_pop(st) SKM_sk_pop(DIST_POINT, (st))
+#define sk_DIST_POINT_sort(st) SKM_sk_sort(DIST_POINT, (st))
+#define sk_DIST_POINT_is_sorted(st) SKM_sk_is_sorted(DIST_POINT, (st))
+
+#define sk_ENGINE_new(st) SKM_sk_new(ENGINE, (st))
+#define sk_ENGINE_new_null() SKM_sk_new_null(ENGINE)
+#define sk_ENGINE_free(st) SKM_sk_free(ENGINE, (st))
+#define sk_ENGINE_num(st) SKM_sk_num(ENGINE, (st))
+#define sk_ENGINE_value(st, i) SKM_sk_value(ENGINE, (st), (i))
+#define sk_ENGINE_set(st, i, val) SKM_sk_set(ENGINE, (st), (i), (val))
+#define sk_ENGINE_zero(st) SKM_sk_zero(ENGINE, (st))
+#define sk_ENGINE_push(st, val) SKM_sk_push(ENGINE, (st), (val))
+#define sk_ENGINE_unshift(st, val) SKM_sk_unshift(ENGINE, (st), (val))
+#define sk_ENGINE_find(st, val) SKM_sk_find(ENGINE, (st), (val))
+#define sk_ENGINE_find_ex(st, val) SKM_sk_find_ex(ENGINE, (st), (val))
+#define sk_ENGINE_delete(st, i) SKM_sk_delete(ENGINE, (st), (i))
+#define sk_ENGINE_delete_ptr(st, ptr) SKM_sk_delete_ptr(ENGINE, (st), (ptr))
+#define sk_ENGINE_insert(st, val, i) SKM_sk_insert(ENGINE, (st), (val), (i))
+#define sk_ENGINE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ENGINE, (st), (cmp))
+#define sk_ENGINE_dup(st) SKM_sk_dup(ENGINE, st)
+#define sk_ENGINE_pop_free(st, free_func) SKM_sk_pop_free(ENGINE, (st), (free_func))
+#define sk_ENGINE_shift(st) SKM_sk_shift(ENGINE, (st))
+#define sk_ENGINE_pop(st) SKM_sk_pop(ENGINE, (st))
+#define sk_ENGINE_sort(st) SKM_sk_sort(ENGINE, (st))
+#define sk_ENGINE_is_sorted(st) SKM_sk_is_sorted(ENGINE, (st))
+
+#define sk_ENGINE_CLEANUP_ITEM_new(st) SKM_sk_new(ENGINE_CLEANUP_ITEM, (st))
+#define sk_ENGINE_CLEANUP_ITEM_new_null() SKM_sk_new_null(ENGINE_CLEANUP_ITEM)
+#define sk_ENGINE_CLEANUP_ITEM_free(st) SKM_sk_free(ENGINE_CLEANUP_ITEM, (st))
+#define sk_ENGINE_CLEANUP_ITEM_num(st) SKM_sk_num(ENGINE_CLEANUP_ITEM, (st))
+#define sk_ENGINE_CLEANUP_ITEM_value(st, i) SKM_sk_value(ENGINE_CLEANUP_ITEM, (st), (i))
+#define sk_ENGINE_CLEANUP_ITEM_set(st, i, val) SKM_sk_set(ENGINE_CLEANUP_ITEM, (st), (i), (val))
+#define sk_ENGINE_CLEANUP_ITEM_zero(st) SKM_sk_zero(ENGINE_CLEANUP_ITEM, (st))
+#define sk_ENGINE_CLEANUP_ITEM_push(st, val) SKM_sk_push(ENGINE_CLEANUP_ITEM, (st), (val))
+#define sk_ENGINE_CLEANUP_ITEM_unshift(st, val) SKM_sk_unshift(ENGINE_CLEANUP_ITEM, (st), (val))
+#define sk_ENGINE_CLEANUP_ITEM_find(st, val) SKM_sk_find(ENGINE_CLEANUP_ITEM, (st), (val))
+#define sk_ENGINE_CLEANUP_ITEM_find_ex(st, val) SKM_sk_find_ex(ENGINE_CLEANUP_ITEM, (st), (val))
+#define sk_ENGINE_CLEANUP_ITEM_delete(st, i) SKM_sk_delete(ENGINE_CLEANUP_ITEM, (st), (i))
+#define sk_ENGINE_CLEANUP_ITEM_delete_ptr(st, ptr) SKM_sk_delete_ptr(ENGINE_CLEANUP_ITEM, (st), (ptr))
+#define sk_ENGINE_CLEANUP_ITEM_insert(st, val, i) SKM_sk_insert(ENGINE_CLEANUP_ITEM, (st), (val), (i))
+#define sk_ENGINE_CLEANUP_ITEM_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ENGINE_CLEANUP_ITEM, (st), (cmp))
+#define sk_ENGINE_CLEANUP_ITEM_dup(st) SKM_sk_dup(ENGINE_CLEANUP_ITEM, st)
+#define sk_ENGINE_CLEANUP_ITEM_pop_free(st, free_func) SKM_sk_pop_free(ENGINE_CLEANUP_ITEM, (st), (free_func))
+#define sk_ENGINE_CLEANUP_ITEM_shift(st) SKM_sk_shift(ENGINE_CLEANUP_ITEM, (st))
+#define sk_ENGINE_CLEANUP_ITEM_pop(st) SKM_sk_pop(ENGINE_CLEANUP_ITEM, (st))
+#define sk_ENGINE_CLEANUP_ITEM_sort(st) SKM_sk_sort(ENGINE_CLEANUP_ITEM, (st))
+#define sk_ENGINE_CLEANUP_ITEM_is_sorted(st) SKM_sk_is_sorted(ENGINE_CLEANUP_ITEM, (st))
+
+#define sk_GENERAL_NAME_new(st) SKM_sk_new(GENERAL_NAME, (st))
+#define sk_GENERAL_NAME_new_null() SKM_sk_new_null(GENERAL_NAME)
+#define sk_GENERAL_NAME_free(st) SKM_sk_free(GENERAL_NAME, (st))
+#define sk_GENERAL_NAME_num(st) SKM_sk_num(GENERAL_NAME, (st))
+#define sk_GENERAL_NAME_value(st, i) SKM_sk_value(GENERAL_NAME, (st), (i))
+#define sk_GENERAL_NAME_set(st, i, val) SKM_sk_set(GENERAL_NAME, (st), (i), (val))
+#define sk_GENERAL_NAME_zero(st) SKM_sk_zero(GENERAL_NAME, (st))
+#define sk_GENERAL_NAME_push(st, val) SKM_sk_push(GENERAL_NAME, (st), (val))
+#define sk_GENERAL_NAME_unshift(st, val) SKM_sk_unshift(GENERAL_NAME, (st), (val))
+#define sk_GENERAL_NAME_find(st, val) SKM_sk_find(GENERAL_NAME, (st), (val))
+#define sk_GENERAL_NAME_find_ex(st, val) SKM_sk_find_ex(GENERAL_NAME, (st), (val))
+#define sk_GENERAL_NAME_delete(st, i) SKM_sk_delete(GENERAL_NAME, (st), (i))
+#define sk_GENERAL_NAME_delete_ptr(st, ptr) SKM_sk_delete_ptr(GENERAL_NAME, (st), (ptr))
+#define sk_GENERAL_NAME_insert(st, val, i) SKM_sk_insert(GENERAL_NAME, (st), (val), (i))
+#define sk_GENERAL_NAME_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(GENERAL_NAME, (st), (cmp))
+#define sk_GENERAL_NAME_dup(st) SKM_sk_dup(GENERAL_NAME, st)
+#define sk_GENERAL_NAME_pop_free(st, free_func) SKM_sk_pop_free(GENERAL_NAME, (st), (free_func))
+#define sk_GENERAL_NAME_shift(st) SKM_sk_shift(GENERAL_NAME, (st))
+#define sk_GENERAL_NAME_pop(st) SKM_sk_pop(GENERAL_NAME, (st))
+#define sk_GENERAL_NAME_sort(st) SKM_sk_sort(GENERAL_NAME, (st))
+#define sk_GENERAL_NAME_is_sorted(st) SKM_sk_is_sorted(GENERAL_NAME, (st))
+
+#define sk_GENERAL_SUBTREE_new(st) SKM_sk_new(GENERAL_SUBTREE, (st))
+#define sk_GENERAL_SUBTREE_new_null() SKM_sk_new_null(GENERAL_SUBTREE)
+#define sk_GENERAL_SUBTREE_free(st) SKM_sk_free(GENERAL_SUBTREE, (st))
+#define sk_GENERAL_SUBTREE_num(st) SKM_sk_num(GENERAL_SUBTREE, (st))
+#define sk_GENERAL_SUBTREE_value(st, i) SKM_sk_value(GENERAL_SUBTREE, (st), (i))
+#define sk_GENERAL_SUBTREE_set(st, i, val) SKM_sk_set(GENERAL_SUBTREE, (st), (i), (val))
+#define sk_GENERAL_SUBTREE_zero(st) SKM_sk_zero(GENERAL_SUBTREE, (st))
+#define sk_GENERAL_SUBTREE_push(st, val) SKM_sk_push(GENERAL_SUBTREE, (st), (val))
+#define sk_GENERAL_SUBTREE_unshift(st, val) SKM_sk_unshift(GENERAL_SUBTREE, (st), (val))
+#define sk_GENERAL_SUBTREE_find(st, val) SKM_sk_find(GENERAL_SUBTREE, (st), (val))
+#define sk_GENERAL_SUBTREE_find_ex(st, val) SKM_sk_find_ex(GENERAL_SUBTREE, (st), (val))
+#define sk_GENERAL_SUBTREE_delete(st, i) SKM_sk_delete(GENERAL_SUBTREE, (st), (i))
+#define sk_GENERAL_SUBTREE_delete_ptr(st, ptr) SKM_sk_delete_ptr(GENERAL_SUBTREE, (st), (ptr))
+#define sk_GENERAL_SUBTREE_insert(st, val, i) SKM_sk_insert(GENERAL_SUBTREE, (st), (val), (i))
+#define sk_GENERAL_SUBTREE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(GENERAL_SUBTREE, (st), (cmp))
+#define sk_GENERAL_SUBTREE_dup(st) SKM_sk_dup(GENERAL_SUBTREE, st)
+#define sk_GENERAL_SUBTREE_pop_free(st, free_func) SKM_sk_pop_free(GENERAL_SUBTREE, (st), (free_func))
+#define sk_GENERAL_SUBTREE_shift(st) SKM_sk_shift(GENERAL_SUBTREE, (st))
+#define sk_GENERAL_SUBTREE_pop(st) SKM_sk_pop(GENERAL_SUBTREE, (st))
+#define sk_GENERAL_SUBTREE_sort(st) SKM_sk_sort(GENERAL_SUBTREE, (st))
+#define sk_GENERAL_SUBTREE_is_sorted(st) SKM_sk_is_sorted(GENERAL_SUBTREE, (st))
+
+#define sk_IPAddressFamily_new(st) SKM_sk_new(IPAddressFamily, (st))
+#define sk_IPAddressFamily_new_null() SKM_sk_new_null(IPAddressFamily)
+#define sk_IPAddressFamily_free(st) SKM_sk_free(IPAddressFamily, (st))
+#define sk_IPAddressFamily_num(st) SKM_sk_num(IPAddressFamily, (st))
+#define sk_IPAddressFamily_value(st, i) SKM_sk_value(IPAddressFamily, (st), (i))
+#define sk_IPAddressFamily_set(st, i, val) SKM_sk_set(IPAddressFamily, (st), (i), (val))
+#define sk_IPAddressFamily_zero(st) SKM_sk_zero(IPAddressFamily, (st))
+#define sk_IPAddressFamily_push(st, val) SKM_sk_push(IPAddressFamily, (st), (val))
+#define sk_IPAddressFamily_unshift(st, val) SKM_sk_unshift(IPAddressFamily, (st), (val))
+#define sk_IPAddressFamily_find(st, val) SKM_sk_find(IPAddressFamily, (st), (val))
+#define sk_IPAddressFamily_find_ex(st, val) SKM_sk_find_ex(IPAddressFamily, (st), (val))
+#define sk_IPAddressFamily_delete(st, i) SKM_sk_delete(IPAddressFamily, (st), (i))
+#define sk_IPAddressFamily_delete_ptr(st, ptr) SKM_sk_delete_ptr(IPAddressFamily, (st), (ptr))
+#define sk_IPAddressFamily_insert(st, val, i) SKM_sk_insert(IPAddressFamily, (st), (val), (i))
+#define sk_IPAddressFamily_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(IPAddressFamily, (st), (cmp))
+#define sk_IPAddressFamily_dup(st) SKM_sk_dup(IPAddressFamily, st)
+#define sk_IPAddressFamily_pop_free(st, free_func) SKM_sk_pop_free(IPAddressFamily, (st), (free_func))
+#define sk_IPAddressFamily_shift(st) SKM_sk_shift(IPAddressFamily, (st))
+#define sk_IPAddressFamily_pop(st) SKM_sk_pop(IPAddressFamily, (st))
+#define sk_IPAddressFamily_sort(st) SKM_sk_sort(IPAddressFamily, (st))
+#define sk_IPAddressFamily_is_sorted(st) SKM_sk_is_sorted(IPAddressFamily, (st))
+
+#define sk_IPAddressOrRange_new(st) SKM_sk_new(IPAddressOrRange, (st))
+#define sk_IPAddressOrRange_new_null() SKM_sk_new_null(IPAddressOrRange)
+#define sk_IPAddressOrRange_free(st) SKM_sk_free(IPAddressOrRange, (st))
+#define sk_IPAddressOrRange_num(st) SKM_sk_num(IPAddressOrRange, (st))
+#define sk_IPAddressOrRange_value(st, i) SKM_sk_value(IPAddressOrRange, (st), (i))
+#define sk_IPAddressOrRange_set(st, i, val) SKM_sk_set(IPAddressOrRange, (st), (i), (val))
+#define sk_IPAddressOrRange_zero(st) SKM_sk_zero(IPAddressOrRange, (st))
+#define sk_IPAddressOrRange_push(st, val) SKM_sk_push(IPAddressOrRange, (st), (val))
+#define sk_IPAddressOrRange_unshift(st, val) SKM_sk_unshift(IPAddressOrRange, (st), (val))
+#define sk_IPAddressOrRange_find(st, val) SKM_sk_find(IPAddressOrRange, (st), (val))
+#define sk_IPAddressOrRange_find_ex(st, val) SKM_sk_find_ex(IPAddressOrRange, (st), (val))
+#define sk_IPAddressOrRange_delete(st, i) SKM_sk_delete(IPAddressOrRange, (st), (i))
+#define sk_IPAddressOrRange_delete_ptr(st, ptr) SKM_sk_delete_ptr(IPAddressOrRange, (st), (ptr))
+#define sk_IPAddressOrRange_insert(st, val, i) SKM_sk_insert(IPAddressOrRange, (st), (val), (i))
+#define sk_IPAddressOrRange_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(IPAddressOrRange, (st), (cmp))
+#define sk_IPAddressOrRange_dup(st) SKM_sk_dup(IPAddressOrRange, st)
+#define sk_IPAddressOrRange_pop_free(st, free_func) SKM_sk_pop_free(IPAddressOrRange, (st), (free_func))
+#define sk_IPAddressOrRange_shift(st) SKM_sk_shift(IPAddressOrRange, (st))
+#define sk_IPAddressOrRange_pop(st) SKM_sk_pop(IPAddressOrRange, (st))
+#define sk_IPAddressOrRange_sort(st) SKM_sk_sort(IPAddressOrRange, (st))
+#define sk_IPAddressOrRange_is_sorted(st) SKM_sk_is_sorted(IPAddressOrRange, (st))
+
+#define sk_KRB5_APREQBODY_new(st) SKM_sk_new(KRB5_APREQBODY, (st))
+#define sk_KRB5_APREQBODY_new_null() SKM_sk_new_null(KRB5_APREQBODY)
+#define sk_KRB5_APREQBODY_free(st) SKM_sk_free(KRB5_APREQBODY, (st))
+#define sk_KRB5_APREQBODY_num(st) SKM_sk_num(KRB5_APREQBODY, (st))
+#define sk_KRB5_APREQBODY_value(st, i) SKM_sk_value(KRB5_APREQBODY, (st), (i))
+#define sk_KRB5_APREQBODY_set(st, i, val) SKM_sk_set(KRB5_APREQBODY, (st), (i), (val))
+#define sk_KRB5_APREQBODY_zero(st) SKM_sk_zero(KRB5_APREQBODY, (st))
+#define sk_KRB5_APREQBODY_push(st, val) SKM_sk_push(KRB5_APREQBODY, (st), (val))
+#define sk_KRB5_APREQBODY_unshift(st, val) SKM_sk_unshift(KRB5_APREQBODY, (st), (val))
+#define sk_KRB5_APREQBODY_find(st, val) SKM_sk_find(KRB5_APREQBODY, (st), (val))
+#define sk_KRB5_APREQBODY_find_ex(st, val) SKM_sk_find_ex(KRB5_APREQBODY, (st), (val))
+#define sk_KRB5_APREQBODY_delete(st, i) SKM_sk_delete(KRB5_APREQBODY, (st), (i))
+#define sk_KRB5_APREQBODY_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_APREQBODY, (st), (ptr))
+#define sk_KRB5_APREQBODY_insert(st, val, i) SKM_sk_insert(KRB5_APREQBODY, (st), (val), (i))
+#define sk_KRB5_APREQBODY_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_APREQBODY, (st), (cmp))
+#define sk_KRB5_APREQBODY_dup(st) SKM_sk_dup(KRB5_APREQBODY, st)
+#define sk_KRB5_APREQBODY_pop_free(st, free_func) SKM_sk_pop_free(KRB5_APREQBODY, (st), (free_func))
+#define sk_KRB5_APREQBODY_shift(st) SKM_sk_shift(KRB5_APREQBODY, (st))
+#define sk_KRB5_APREQBODY_pop(st) SKM_sk_pop(KRB5_APREQBODY, (st))
+#define sk_KRB5_APREQBODY_sort(st) SKM_sk_sort(KRB5_APREQBODY, (st))
+#define sk_KRB5_APREQBODY_is_sorted(st) SKM_sk_is_sorted(KRB5_APREQBODY, (st))
+
+#define sk_KRB5_AUTHDATA_new(st) SKM_sk_new(KRB5_AUTHDATA, (st))
+#define sk_KRB5_AUTHDATA_new_null() SKM_sk_new_null(KRB5_AUTHDATA)
+#define sk_KRB5_AUTHDATA_free(st) SKM_sk_free(KRB5_AUTHDATA, (st))
+#define sk_KRB5_AUTHDATA_num(st) SKM_sk_num(KRB5_AUTHDATA, (st))
+#define sk_KRB5_AUTHDATA_value(st, i) SKM_sk_value(KRB5_AUTHDATA, (st), (i))
+#define sk_KRB5_AUTHDATA_set(st, i, val) SKM_sk_set(KRB5_AUTHDATA, (st), (i), (val))
+#define sk_KRB5_AUTHDATA_zero(st) SKM_sk_zero(KRB5_AUTHDATA, (st))
+#define sk_KRB5_AUTHDATA_push(st, val) SKM_sk_push(KRB5_AUTHDATA, (st), (val))
+#define sk_KRB5_AUTHDATA_unshift(st, val) SKM_sk_unshift(KRB5_AUTHDATA, (st), (val))
+#define sk_KRB5_AUTHDATA_find(st, val) SKM_sk_find(KRB5_AUTHDATA, (st), (val))
+#define sk_KRB5_AUTHDATA_find_ex(st, val) SKM_sk_find_ex(KRB5_AUTHDATA, (st), (val))
+#define sk_KRB5_AUTHDATA_delete(st, i) SKM_sk_delete(KRB5_AUTHDATA, (st), (i))
+#define sk_KRB5_AUTHDATA_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_AUTHDATA, (st), (ptr))
+#define sk_KRB5_AUTHDATA_insert(st, val, i) SKM_sk_insert(KRB5_AUTHDATA, (st), (val), (i))
+#define sk_KRB5_AUTHDATA_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_AUTHDATA, (st), (cmp))
+#define sk_KRB5_AUTHDATA_dup(st) SKM_sk_dup(KRB5_AUTHDATA, st)
+#define sk_KRB5_AUTHDATA_pop_free(st, free_func) SKM_sk_pop_free(KRB5_AUTHDATA, (st), (free_func))
+#define sk_KRB5_AUTHDATA_shift(st) SKM_sk_shift(KRB5_AUTHDATA, (st))
+#define sk_KRB5_AUTHDATA_pop(st) SKM_sk_pop(KRB5_AUTHDATA, (st))
+#define sk_KRB5_AUTHDATA_sort(st) SKM_sk_sort(KRB5_AUTHDATA, (st))
+#define sk_KRB5_AUTHDATA_is_sorted(st) SKM_sk_is_sorted(KRB5_AUTHDATA, (st))
+
+#define sk_KRB5_AUTHENTBODY_new(st) SKM_sk_new(KRB5_AUTHENTBODY, (st))
+#define sk_KRB5_AUTHENTBODY_new_null() SKM_sk_new_null(KRB5_AUTHENTBODY)
+#define sk_KRB5_AUTHENTBODY_free(st) SKM_sk_free(KRB5_AUTHENTBODY, (st))
+#define sk_KRB5_AUTHENTBODY_num(st) SKM_sk_num(KRB5_AUTHENTBODY, (st))
+#define sk_KRB5_AUTHENTBODY_value(st, i) SKM_sk_value(KRB5_AUTHENTBODY, (st), (i))
+#define sk_KRB5_AUTHENTBODY_set(st, i, val) SKM_sk_set(KRB5_AUTHENTBODY, (st), (i), (val))
+#define sk_KRB5_AUTHENTBODY_zero(st) SKM_sk_zero(KRB5_AUTHENTBODY, (st))
+#define sk_KRB5_AUTHENTBODY_push(st, val) SKM_sk_push(KRB5_AUTHENTBODY, (st), (val))
+#define sk_KRB5_AUTHENTBODY_unshift(st, val) SKM_sk_unshift(KRB5_AUTHENTBODY, (st), (val))
+#define sk_KRB5_AUTHENTBODY_find(st, val) SKM_sk_find(KRB5_AUTHENTBODY, (st), (val))
+#define sk_KRB5_AUTHENTBODY_find_ex(st, val) SKM_sk_find_ex(KRB5_AUTHENTBODY, (st), (val))
+#define sk_KRB5_AUTHENTBODY_delete(st, i) SKM_sk_delete(KRB5_AUTHENTBODY, (st), (i))
+#define sk_KRB5_AUTHENTBODY_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_AUTHENTBODY, (st), (ptr))
+#define sk_KRB5_AUTHENTBODY_insert(st, val, i) SKM_sk_insert(KRB5_AUTHENTBODY, (st), (val), (i))
+#define sk_KRB5_AUTHENTBODY_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_AUTHENTBODY, (st), (cmp))
+#define sk_KRB5_AUTHENTBODY_dup(st) SKM_sk_dup(KRB5_AUTHENTBODY, st)
+#define sk_KRB5_AUTHENTBODY_pop_free(st, free_func) SKM_sk_pop_free(KRB5_AUTHENTBODY, (st), (free_func))
+#define sk_KRB5_AUTHENTBODY_shift(st) SKM_sk_shift(KRB5_AUTHENTBODY, (st))
+#define sk_KRB5_AUTHENTBODY_pop(st) SKM_sk_pop(KRB5_AUTHENTBODY, (st))
+#define sk_KRB5_AUTHENTBODY_sort(st) SKM_sk_sort(KRB5_AUTHENTBODY, (st))
+#define sk_KRB5_AUTHENTBODY_is_sorted(st) SKM_sk_is_sorted(KRB5_AUTHENTBODY, (st))
+
+#define sk_KRB5_CHECKSUM_new(st) SKM_sk_new(KRB5_CHECKSUM, (st))
+#define sk_KRB5_CHECKSUM_new_null() SKM_sk_new_null(KRB5_CHECKSUM)
+#define sk_KRB5_CHECKSUM_free(st) SKM_sk_free(KRB5_CHECKSUM, (st))
+#define sk_KRB5_CHECKSUM_num(st) SKM_sk_num(KRB5_CHECKSUM, (st))
+#define sk_KRB5_CHECKSUM_value(st, i) SKM_sk_value(KRB5_CHECKSUM, (st), (i))
+#define sk_KRB5_CHECKSUM_set(st, i, val) SKM_sk_set(KRB5_CHECKSUM, (st), (i), (val))
+#define sk_KRB5_CHECKSUM_zero(st) SKM_sk_zero(KRB5_CHECKSUM, (st))
+#define sk_KRB5_CHECKSUM_push(st, val) SKM_sk_push(KRB5_CHECKSUM, (st), (val))
+#define sk_KRB5_CHECKSUM_unshift(st, val) SKM_sk_unshift(KRB5_CHECKSUM, (st), (val))
+#define sk_KRB5_CHECKSUM_find(st, val) SKM_sk_find(KRB5_CHECKSUM, (st), (val))
+#define sk_KRB5_CHECKSUM_find_ex(st, val) SKM_sk_find_ex(KRB5_CHECKSUM, (st), (val))
+#define sk_KRB5_CHECKSUM_delete(st, i) SKM_sk_delete(KRB5_CHECKSUM, (st), (i))
+#define sk_KRB5_CHECKSUM_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_CHECKSUM, (st), (ptr))
+#define sk_KRB5_CHECKSUM_insert(st, val, i) SKM_sk_insert(KRB5_CHECKSUM, (st), (val), (i))
+#define sk_KRB5_CHECKSUM_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_CHECKSUM, (st), (cmp))
+#define sk_KRB5_CHECKSUM_dup(st) SKM_sk_dup(KRB5_CHECKSUM, st)
+#define sk_KRB5_CHECKSUM_pop_free(st, free_func) SKM_sk_pop_free(KRB5_CHECKSUM, (st), (free_func))
+#define sk_KRB5_CHECKSUM_shift(st) SKM_sk_shift(KRB5_CHECKSUM, (st))
+#define sk_KRB5_CHECKSUM_pop(st) SKM_sk_pop(KRB5_CHECKSUM, (st))
+#define sk_KRB5_CHECKSUM_sort(st) SKM_sk_sort(KRB5_CHECKSUM, (st))
+#define sk_KRB5_CHECKSUM_is_sorted(st) SKM_sk_is_sorted(KRB5_CHECKSUM, (st))
+
+#define sk_KRB5_ENCDATA_new(st) SKM_sk_new(KRB5_ENCDATA, (st))
+#define sk_KRB5_ENCDATA_new_null() SKM_sk_new_null(KRB5_ENCDATA)
+#define sk_KRB5_ENCDATA_free(st) SKM_sk_free(KRB5_ENCDATA, (st))
+#define sk_KRB5_ENCDATA_num(st) SKM_sk_num(KRB5_ENCDATA, (st))
+#define sk_KRB5_ENCDATA_value(st, i) SKM_sk_value(KRB5_ENCDATA, (st), (i))
+#define sk_KRB5_ENCDATA_set(st, i, val) SKM_sk_set(KRB5_ENCDATA, (st), (i), (val))
+#define sk_KRB5_ENCDATA_zero(st) SKM_sk_zero(KRB5_ENCDATA, (st))
+#define sk_KRB5_ENCDATA_push(st, val) SKM_sk_push(KRB5_ENCDATA, (st), (val))
+#define sk_KRB5_ENCDATA_unshift(st, val) SKM_sk_unshift(KRB5_ENCDATA, (st), (val))
+#define sk_KRB5_ENCDATA_find(st, val) SKM_sk_find(KRB5_ENCDATA, (st), (val))
+#define sk_KRB5_ENCDATA_find_ex(st, val) SKM_sk_find_ex(KRB5_ENCDATA, (st), (val))
+#define sk_KRB5_ENCDATA_delete(st, i) SKM_sk_delete(KRB5_ENCDATA, (st), (i))
+#define sk_KRB5_ENCDATA_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_ENCDATA, (st), (ptr))
+#define sk_KRB5_ENCDATA_insert(st, val, i) SKM_sk_insert(KRB5_ENCDATA, (st), (val), (i))
+#define sk_KRB5_ENCDATA_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_ENCDATA, (st), (cmp))
+#define sk_KRB5_ENCDATA_dup(st) SKM_sk_dup(KRB5_ENCDATA, st)
+#define sk_KRB5_ENCDATA_pop_free(st, free_func) SKM_sk_pop_free(KRB5_ENCDATA, (st), (free_func))
+#define sk_KRB5_ENCDATA_shift(st) SKM_sk_shift(KRB5_ENCDATA, (st))
+#define sk_KRB5_ENCDATA_pop(st) SKM_sk_pop(KRB5_ENCDATA, (st))
+#define sk_KRB5_ENCDATA_sort(st) SKM_sk_sort(KRB5_ENCDATA, (st))
+#define sk_KRB5_ENCDATA_is_sorted(st) SKM_sk_is_sorted(KRB5_ENCDATA, (st))
+
+#define sk_KRB5_ENCKEY_new(st) SKM_sk_new(KRB5_ENCKEY, (st))
+#define sk_KRB5_ENCKEY_new_null() SKM_sk_new_null(KRB5_ENCKEY)
+#define sk_KRB5_ENCKEY_free(st) SKM_sk_free(KRB5_ENCKEY, (st))
+#define sk_KRB5_ENCKEY_num(st) SKM_sk_num(KRB5_ENCKEY, (st))
+#define sk_KRB5_ENCKEY_value(st, i) SKM_sk_value(KRB5_ENCKEY, (st), (i))
+#define sk_KRB5_ENCKEY_set(st, i, val) SKM_sk_set(KRB5_ENCKEY, (st), (i), (val))
+#define sk_KRB5_ENCKEY_zero(st) SKM_sk_zero(KRB5_ENCKEY, (st))
+#define sk_KRB5_ENCKEY_push(st, val) SKM_sk_push(KRB5_ENCKEY, (st), (val))
+#define sk_KRB5_ENCKEY_unshift(st, val) SKM_sk_unshift(KRB5_ENCKEY, (st), (val))
+#define sk_KRB5_ENCKEY_find(st, val) SKM_sk_find(KRB5_ENCKEY, (st), (val))
+#define sk_KRB5_ENCKEY_find_ex(st, val) SKM_sk_find_ex(KRB5_ENCKEY, (st), (val))
+#define sk_KRB5_ENCKEY_delete(st, i) SKM_sk_delete(KRB5_ENCKEY, (st), (i))
+#define sk_KRB5_ENCKEY_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_ENCKEY, (st), (ptr))
+#define sk_KRB5_ENCKEY_insert(st, val, i) SKM_sk_insert(KRB5_ENCKEY, (st), (val), (i))
+#define sk_KRB5_ENCKEY_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_ENCKEY, (st), (cmp))
+#define sk_KRB5_ENCKEY_dup(st) SKM_sk_dup(KRB5_ENCKEY, st)
+#define sk_KRB5_ENCKEY_pop_free(st, free_func) SKM_sk_pop_free(KRB5_ENCKEY, (st), (free_func))
+#define sk_KRB5_ENCKEY_shift(st) SKM_sk_shift(KRB5_ENCKEY, (st))
+#define sk_KRB5_ENCKEY_pop(st) SKM_sk_pop(KRB5_ENCKEY, (st))
+#define sk_KRB5_ENCKEY_sort(st) SKM_sk_sort(KRB5_ENCKEY, (st))
+#define sk_KRB5_ENCKEY_is_sorted(st) SKM_sk_is_sorted(KRB5_ENCKEY, (st))
+
+#define sk_KRB5_PRINCNAME_new(st) SKM_sk_new(KRB5_PRINCNAME, (st))
+#define sk_KRB5_PRINCNAME_new_null() SKM_sk_new_null(KRB5_PRINCNAME)
+#define sk_KRB5_PRINCNAME_free(st) SKM_sk_free(KRB5_PRINCNAME, (st))
+#define sk_KRB5_PRINCNAME_num(st) SKM_sk_num(KRB5_PRINCNAME, (st))
+#define sk_KRB5_PRINCNAME_value(st, i) SKM_sk_value(KRB5_PRINCNAME, (st), (i))
+#define sk_KRB5_PRINCNAME_set(st, i, val) SKM_sk_set(KRB5_PRINCNAME, (st), (i), (val))
+#define sk_KRB5_PRINCNAME_zero(st) SKM_sk_zero(KRB5_PRINCNAME, (st))
+#define sk_KRB5_PRINCNAME_push(st, val) SKM_sk_push(KRB5_PRINCNAME, (st), (val))
+#define sk_KRB5_PRINCNAME_unshift(st, val) SKM_sk_unshift(KRB5_PRINCNAME, (st), (val))
+#define sk_KRB5_PRINCNAME_find(st, val) SKM_sk_find(KRB5_PRINCNAME, (st), (val))
+#define sk_KRB5_PRINCNAME_find_ex(st, val) SKM_sk_find_ex(KRB5_PRINCNAME, (st), (val))
+#define sk_KRB5_PRINCNAME_delete(st, i) SKM_sk_delete(KRB5_PRINCNAME, (st), (i))
+#define sk_KRB5_PRINCNAME_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_PRINCNAME, (st), (ptr))
+#define sk_KRB5_PRINCNAME_insert(st, val, i) SKM_sk_insert(KRB5_PRINCNAME, (st), (val), (i))
+#define sk_KRB5_PRINCNAME_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_PRINCNAME, (st), (cmp))
+#define sk_KRB5_PRINCNAME_dup(st) SKM_sk_dup(KRB5_PRINCNAME, st)
+#define sk_KRB5_PRINCNAME_pop_free(st, free_func) SKM_sk_pop_free(KRB5_PRINCNAME, (st), (free_func))
+#define sk_KRB5_PRINCNAME_shift(st) SKM_sk_shift(KRB5_PRINCNAME, (st))
+#define sk_KRB5_PRINCNAME_pop(st) SKM_sk_pop(KRB5_PRINCNAME, (st))
+#define sk_KRB5_PRINCNAME_sort(st) SKM_sk_sort(KRB5_PRINCNAME, (st))
+#define sk_KRB5_PRINCNAME_is_sorted(st) SKM_sk_is_sorted(KRB5_PRINCNAME, (st))
+
+#define sk_KRB5_TKTBODY_new(st) SKM_sk_new(KRB5_TKTBODY, (st))
+#define sk_KRB5_TKTBODY_new_null() SKM_sk_new_null(KRB5_TKTBODY)
+#define sk_KRB5_TKTBODY_free(st) SKM_sk_free(KRB5_TKTBODY, (st))
+#define sk_KRB5_TKTBODY_num(st) SKM_sk_num(KRB5_TKTBODY, (st))
+#define sk_KRB5_TKTBODY_value(st, i) SKM_sk_value(KRB5_TKTBODY, (st), (i))
+#define sk_KRB5_TKTBODY_set(st, i, val) SKM_sk_set(KRB5_TKTBODY, (st), (i), (val))
+#define sk_KRB5_TKTBODY_zero(st) SKM_sk_zero(KRB5_TKTBODY, (st))
+#define sk_KRB5_TKTBODY_push(st, val) SKM_sk_push(KRB5_TKTBODY, (st), (val))
+#define sk_KRB5_TKTBODY_unshift(st, val) SKM_sk_unshift(KRB5_TKTBODY, (st), (val))
+#define sk_KRB5_TKTBODY_find(st, val) SKM_sk_find(KRB5_TKTBODY, (st), (val))
+#define sk_KRB5_TKTBODY_find_ex(st, val) SKM_sk_find_ex(KRB5_TKTBODY, (st), (val))
+#define sk_KRB5_TKTBODY_delete(st, i) SKM_sk_delete(KRB5_TKTBODY, (st), (i))
+#define sk_KRB5_TKTBODY_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_TKTBODY, (st), (ptr))
+#define sk_KRB5_TKTBODY_insert(st, val, i) SKM_sk_insert(KRB5_TKTBODY, (st), (val), (i))
+#define sk_KRB5_TKTBODY_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_TKTBODY, (st), (cmp))
+#define sk_KRB5_TKTBODY_dup(st) SKM_sk_dup(KRB5_TKTBODY, st)
+#define sk_KRB5_TKTBODY_pop_free(st, free_func) SKM_sk_pop_free(KRB5_TKTBODY, (st), (free_func))
+#define sk_KRB5_TKTBODY_shift(st) SKM_sk_shift(KRB5_TKTBODY, (st))
+#define sk_KRB5_TKTBODY_pop(st) SKM_sk_pop(KRB5_TKTBODY, (st))
+#define sk_KRB5_TKTBODY_sort(st) SKM_sk_sort(KRB5_TKTBODY, (st))
+#define sk_KRB5_TKTBODY_is_sorted(st) SKM_sk_is_sorted(KRB5_TKTBODY, (st))
+
+#define sk_MIME_HEADER_new(st) SKM_sk_new(MIME_HEADER, (st))
+#define sk_MIME_HEADER_new_null() SKM_sk_new_null(MIME_HEADER)
+#define sk_MIME_HEADER_free(st) SKM_sk_free(MIME_HEADER, (st))
+#define sk_MIME_HEADER_num(st) SKM_sk_num(MIME_HEADER, (st))
+#define sk_MIME_HEADER_value(st, i) SKM_sk_value(MIME_HEADER, (st), (i))
+#define sk_MIME_HEADER_set(st, i, val) SKM_sk_set(MIME_HEADER, (st), (i), (val))
+#define sk_MIME_HEADER_zero(st) SKM_sk_zero(MIME_HEADER, (st))
+#define sk_MIME_HEADER_push(st, val) SKM_sk_push(MIME_HEADER, (st), (val))
+#define sk_MIME_HEADER_unshift(st, val) SKM_sk_unshift(MIME_HEADER, (st), (val))
+#define sk_MIME_HEADER_find(st, val) SKM_sk_find(MIME_HEADER, (st), (val))
+#define sk_MIME_HEADER_find_ex(st, val) SKM_sk_find_ex(MIME_HEADER, (st), (val))
+#define sk_MIME_HEADER_delete(st, i) SKM_sk_delete(MIME_HEADER, (st), (i))
+#define sk_MIME_HEADER_delete_ptr(st, ptr) SKM_sk_delete_ptr(MIME_HEADER, (st), (ptr))
+#define sk_MIME_HEADER_insert(st, val, i) SKM_sk_insert(MIME_HEADER, (st), (val), (i))
+#define sk_MIME_HEADER_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(MIME_HEADER, (st), (cmp))
+#define sk_MIME_HEADER_dup(st) SKM_sk_dup(MIME_HEADER, st)
+#define sk_MIME_HEADER_pop_free(st, free_func) SKM_sk_pop_free(MIME_HEADER, (st), (free_func))
+#define sk_MIME_HEADER_shift(st) SKM_sk_shift(MIME_HEADER, (st))
+#define sk_MIME_HEADER_pop(st) SKM_sk_pop(MIME_HEADER, (st))
+#define sk_MIME_HEADER_sort(st) SKM_sk_sort(MIME_HEADER, (st))
+#define sk_MIME_HEADER_is_sorted(st) SKM_sk_is_sorted(MIME_HEADER, (st))
+
+#define sk_MIME_PARAM_new(st) SKM_sk_new(MIME_PARAM, (st))
+#define sk_MIME_PARAM_new_null() SKM_sk_new_null(MIME_PARAM)
+#define sk_MIME_PARAM_free(st) SKM_sk_free(MIME_PARAM, (st))
+#define sk_MIME_PARAM_num(st) SKM_sk_num(MIME_PARAM, (st))
+#define sk_MIME_PARAM_value(st, i) SKM_sk_value(MIME_PARAM, (st), (i))
+#define sk_MIME_PARAM_set(st, i, val) SKM_sk_set(MIME_PARAM, (st), (i), (val))
+#define sk_MIME_PARAM_zero(st) SKM_sk_zero(MIME_PARAM, (st))
+#define sk_MIME_PARAM_push(st, val) SKM_sk_push(MIME_PARAM, (st), (val))
+#define sk_MIME_PARAM_unshift(st, val) SKM_sk_unshift(MIME_PARAM, (st), (val))
+#define sk_MIME_PARAM_find(st, val) SKM_sk_find(MIME_PARAM, (st), (val))
+#define sk_MIME_PARAM_find_ex(st, val) SKM_sk_find_ex(MIME_PARAM, (st), (val))
+#define sk_MIME_PARAM_delete(st, i) SKM_sk_delete(MIME_PARAM, (st), (i))
+#define sk_MIME_PARAM_delete_ptr(st, ptr) SKM_sk_delete_ptr(MIME_PARAM, (st), (ptr))
+#define sk_MIME_PARAM_insert(st, val, i) SKM_sk_insert(MIME_PARAM, (st), (val), (i))
+#define sk_MIME_PARAM_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(MIME_PARAM, (st), (cmp))
+#define sk_MIME_PARAM_dup(st) SKM_sk_dup(MIME_PARAM, st)
+#define sk_MIME_PARAM_pop_free(st, free_func) SKM_sk_pop_free(MIME_PARAM, (st), (free_func))
+#define sk_MIME_PARAM_shift(st) SKM_sk_shift(MIME_PARAM, (st))
+#define sk_MIME_PARAM_pop(st) SKM_sk_pop(MIME_PARAM, (st))
+#define sk_MIME_PARAM_sort(st) SKM_sk_sort(MIME_PARAM, (st))
+#define sk_MIME_PARAM_is_sorted(st) SKM_sk_is_sorted(MIME_PARAM, (st))
+
+#define sk_NAME_FUNCS_new(st) SKM_sk_new(NAME_FUNCS, (st))
+#define sk_NAME_FUNCS_new_null() SKM_sk_new_null(NAME_FUNCS)
+#define sk_NAME_FUNCS_free(st) SKM_sk_free(NAME_FUNCS, (st))
+#define sk_NAME_FUNCS_num(st) SKM_sk_num(NAME_FUNCS, (st))
+#define sk_NAME_FUNCS_value(st, i) SKM_sk_value(NAME_FUNCS, (st), (i))
+#define sk_NAME_FUNCS_set(st, i, val) SKM_sk_set(NAME_FUNCS, (st), (i), (val))
+#define sk_NAME_FUNCS_zero(st) SKM_sk_zero(NAME_FUNCS, (st))
+#define sk_NAME_FUNCS_push(st, val) SKM_sk_push(NAME_FUNCS, (st), (val))
+#define sk_NAME_FUNCS_unshift(st, val) SKM_sk_unshift(NAME_FUNCS, (st), (val))
+#define sk_NAME_FUNCS_find(st, val) SKM_sk_find(NAME_FUNCS, (st), (val))
+#define sk_NAME_FUNCS_find_ex(st, val) SKM_sk_find_ex(NAME_FUNCS, (st), (val))
+#define sk_NAME_FUNCS_delete(st, i) SKM_sk_delete(NAME_FUNCS, (st), (i))
+#define sk_NAME_FUNCS_delete_ptr(st, ptr) SKM_sk_delete_ptr(NAME_FUNCS, (st), (ptr))
+#define sk_NAME_FUNCS_insert(st, val, i) SKM_sk_insert(NAME_FUNCS, (st), (val), (i))
+#define sk_NAME_FUNCS_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(NAME_FUNCS, (st), (cmp))
+#define sk_NAME_FUNCS_dup(st) SKM_sk_dup(NAME_FUNCS, st)
+#define sk_NAME_FUNCS_pop_free(st, free_func) SKM_sk_pop_free(NAME_FUNCS, (st), (free_func))
+#define sk_NAME_FUNCS_shift(st) SKM_sk_shift(NAME_FUNCS, (st))
+#define sk_NAME_FUNCS_pop(st) SKM_sk_pop(NAME_FUNCS, (st))
+#define sk_NAME_FUNCS_sort(st) SKM_sk_sort(NAME_FUNCS, (st))
+#define sk_NAME_FUNCS_is_sorted(st) SKM_sk_is_sorted(NAME_FUNCS, (st))
+
+#define sk_OCSP_CERTID_new(st) SKM_sk_new(OCSP_CERTID, (st))
+#define sk_OCSP_CERTID_new_null() SKM_sk_new_null(OCSP_CERTID)
+#define sk_OCSP_CERTID_free(st) SKM_sk_free(OCSP_CERTID, (st))
+#define sk_OCSP_CERTID_num(st) SKM_sk_num(OCSP_CERTID, (st))
+#define sk_OCSP_CERTID_value(st, i) SKM_sk_value(OCSP_CERTID, (st), (i))
+#define sk_OCSP_CERTID_set(st, i, val) SKM_sk_set(OCSP_CERTID, (st), (i), (val))
+#define sk_OCSP_CERTID_zero(st) SKM_sk_zero(OCSP_CERTID, (st))
+#define sk_OCSP_CERTID_push(st, val) SKM_sk_push(OCSP_CERTID, (st), (val))
+#define sk_OCSP_CERTID_unshift(st, val) SKM_sk_unshift(OCSP_CERTID, (st), (val))
+#define sk_OCSP_CERTID_find(st, val) SKM_sk_find(OCSP_CERTID, (st), (val))
+#define sk_OCSP_CERTID_find_ex(st, val) SKM_sk_find_ex(OCSP_CERTID, (st), (val))
+#define sk_OCSP_CERTID_delete(st, i) SKM_sk_delete(OCSP_CERTID, (st), (i))
+#define sk_OCSP_CERTID_delete_ptr(st, ptr) SKM_sk_delete_ptr(OCSP_CERTID, (st), (ptr))
+#define sk_OCSP_CERTID_insert(st, val, i) SKM_sk_insert(OCSP_CERTID, (st), (val), (i))
+#define sk_OCSP_CERTID_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(OCSP_CERTID, (st), (cmp))
+#define sk_OCSP_CERTID_dup(st) SKM_sk_dup(OCSP_CERTID, st)
+#define sk_OCSP_CERTID_pop_free(st, free_func) SKM_sk_pop_free(OCSP_CERTID, (st), (free_func))
+#define sk_OCSP_CERTID_shift(st) SKM_sk_shift(OCSP_CERTID, (st))
+#define sk_OCSP_CERTID_pop(st) SKM_sk_pop(OCSP_CERTID, (st))
+#define sk_OCSP_CERTID_sort(st) SKM_sk_sort(OCSP_CERTID, (st))
+#define sk_OCSP_CERTID_is_sorted(st) SKM_sk_is_sorted(OCSP_CERTID, (st))
+
+#define sk_OCSP_ONEREQ_new(st) SKM_sk_new(OCSP_ONEREQ, (st))
+#define sk_OCSP_ONEREQ_new_null() SKM_sk_new_null(OCSP_ONEREQ)
+#define sk_OCSP_ONEREQ_free(st) SKM_sk_free(OCSP_ONEREQ, (st))
+#define sk_OCSP_ONEREQ_num(st) SKM_sk_num(OCSP_ONEREQ, (st))
+#define sk_OCSP_ONEREQ_value(st, i) SKM_sk_value(OCSP_ONEREQ, (st), (i))
+#define sk_OCSP_ONEREQ_set(st, i, val) SKM_sk_set(OCSP_ONEREQ, (st), (i), (val))
+#define sk_OCSP_ONEREQ_zero(st) SKM_sk_zero(OCSP_ONEREQ, (st))
+#define sk_OCSP_ONEREQ_push(st, val) SKM_sk_push(OCSP_ONEREQ, (st), (val))
+#define sk_OCSP_ONEREQ_unshift(st, val) SKM_sk_unshift(OCSP_ONEREQ, (st), (val))
+#define sk_OCSP_ONEREQ_find(st, val) SKM_sk_find(OCSP_ONEREQ, (st), (val))
+#define sk_OCSP_ONEREQ_find_ex(st, val) SKM_sk_find_ex(OCSP_ONEREQ, (st), (val))
+#define sk_OCSP_ONEREQ_delete(st, i) SKM_sk_delete(OCSP_ONEREQ, (st), (i))
+#define sk_OCSP_ONEREQ_delete_ptr(st, ptr) SKM_sk_delete_ptr(OCSP_ONEREQ, (st), (ptr))
+#define sk_OCSP_ONEREQ_insert(st, val, i) SKM_sk_insert(OCSP_ONEREQ, (st), (val), (i))
+#define sk_OCSP_ONEREQ_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(OCSP_ONEREQ, (st), (cmp))
+#define sk_OCSP_ONEREQ_dup(st) SKM_sk_dup(OCSP_ONEREQ, st)
+#define sk_OCSP_ONEREQ_pop_free(st, free_func) SKM_sk_pop_free(OCSP_ONEREQ, (st), (free_func))
+#define sk_OCSP_ONEREQ_shift(st) SKM_sk_shift(OCSP_ONEREQ, (st))
+#define sk_OCSP_ONEREQ_pop(st) SKM_sk_pop(OCSP_ONEREQ, (st))
+#define sk_OCSP_ONEREQ_sort(st) SKM_sk_sort(OCSP_ONEREQ, (st))
+#define sk_OCSP_ONEREQ_is_sorted(st) SKM_sk_is_sorted(OCSP_ONEREQ, (st))
+
+#define sk_OCSP_SINGLERESP_new(st) SKM_sk_new(OCSP_SINGLERESP, (st))
+#define sk_OCSP_SINGLERESP_new_null() SKM_sk_new_null(OCSP_SINGLERESP)
+#define sk_OCSP_SINGLERESP_free(st) SKM_sk_free(OCSP_SINGLERESP, (st))
+#define sk_OCSP_SINGLERESP_num(st) SKM_sk_num(OCSP_SINGLERESP, (st))
+#define sk_OCSP_SINGLERESP_value(st, i) SKM_sk_value(OCSP_SINGLERESP, (st), (i))
+#define sk_OCSP_SINGLERESP_set(st, i, val) SKM_sk_set(OCSP_SINGLERESP, (st), (i), (val))
+#define sk_OCSP_SINGLERESP_zero(st) SKM_sk_zero(OCSP_SINGLERESP, (st))
+#define sk_OCSP_SINGLERESP_push(st, val) SKM_sk_push(OCSP_SINGLERESP, (st), (val))
+#define sk_OCSP_SINGLERESP_unshift(st, val) SKM_sk_unshift(OCSP_SINGLERESP, (st), (val))
+#define sk_OCSP_SINGLERESP_find(st, val) SKM_sk_find(OCSP_SINGLERESP, (st), (val))
+#define sk_OCSP_SINGLERESP_find_ex(st, val) SKM_sk_find_ex(OCSP_SINGLERESP, (st), (val))
+#define sk_OCSP_SINGLERESP_delete(st, i) SKM_sk_delete(OCSP_SINGLERESP, (st), (i))
+#define sk_OCSP_SINGLERESP_delete_ptr(st, ptr) SKM_sk_delete_ptr(OCSP_SINGLERESP, (st), (ptr))
+#define sk_OCSP_SINGLERESP_insert(st, val, i) SKM_sk_insert(OCSP_SINGLERESP, (st), (val), (i))
+#define sk_OCSP_SINGLERESP_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(OCSP_SINGLERESP, (st), (cmp))
+#define sk_OCSP_SINGLERESP_dup(st) SKM_sk_dup(OCSP_SINGLERESP, st)
+#define sk_OCSP_SINGLERESP_pop_free(st, free_func) SKM_sk_pop_free(OCSP_SINGLERESP, (st), (free_func))
+#define sk_OCSP_SINGLERESP_shift(st) SKM_sk_shift(OCSP_SINGLERESP, (st))
+#define sk_OCSP_SINGLERESP_pop(st) SKM_sk_pop(OCSP_SINGLERESP, (st))
+#define sk_OCSP_SINGLERESP_sort(st) SKM_sk_sort(OCSP_SINGLERESP, (st))
+#define sk_OCSP_SINGLERESP_is_sorted(st) SKM_sk_is_sorted(OCSP_SINGLERESP, (st))
+
+#define sk_PKCS12_SAFEBAG_new(st) SKM_sk_new(PKCS12_SAFEBAG, (st))
+#define sk_PKCS12_SAFEBAG_new_null() SKM_sk_new_null(PKCS12_SAFEBAG)
+#define sk_PKCS12_SAFEBAG_free(st) SKM_sk_free(PKCS12_SAFEBAG, (st))
+#define sk_PKCS12_SAFEBAG_num(st) SKM_sk_num(PKCS12_SAFEBAG, (st))
+#define sk_PKCS12_SAFEBAG_value(st, i) SKM_sk_value(PKCS12_SAFEBAG, (st), (i))
+#define sk_PKCS12_SAFEBAG_set(st, i, val) SKM_sk_set(PKCS12_SAFEBAG, (st), (i), (val))
+#define sk_PKCS12_SAFEBAG_zero(st) SKM_sk_zero(PKCS12_SAFEBAG, (st))
+#define sk_PKCS12_SAFEBAG_push(st, val) SKM_sk_push(PKCS12_SAFEBAG, (st), (val))
+#define sk_PKCS12_SAFEBAG_unshift(st, val) SKM_sk_unshift(PKCS12_SAFEBAG, (st), (val))
+#define sk_PKCS12_SAFEBAG_find(st, val) SKM_sk_find(PKCS12_SAFEBAG, (st), (val))
+#define sk_PKCS12_SAFEBAG_find_ex(st, val) SKM_sk_find_ex(PKCS12_SAFEBAG, (st), (val))
+#define sk_PKCS12_SAFEBAG_delete(st, i) SKM_sk_delete(PKCS12_SAFEBAG, (st), (i))
+#define sk_PKCS12_SAFEBAG_delete_ptr(st, ptr) SKM_sk_delete_ptr(PKCS12_SAFEBAG, (st), (ptr))
+#define sk_PKCS12_SAFEBAG_insert(st, val, i) SKM_sk_insert(PKCS12_SAFEBAG, (st), (val), (i))
+#define sk_PKCS12_SAFEBAG_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(PKCS12_SAFEBAG, (st), (cmp))
+#define sk_PKCS12_SAFEBAG_dup(st) SKM_sk_dup(PKCS12_SAFEBAG, st)
+#define sk_PKCS12_SAFEBAG_pop_free(st, free_func) SKM_sk_pop_free(PKCS12_SAFEBAG, (st), (free_func))
+#define sk_PKCS12_SAFEBAG_shift(st) SKM_sk_shift(PKCS12_SAFEBAG, (st))
+#define sk_PKCS12_SAFEBAG_pop(st) SKM_sk_pop(PKCS12_SAFEBAG, (st))
+#define sk_PKCS12_SAFEBAG_sort(st) SKM_sk_sort(PKCS12_SAFEBAG, (st))
+#define sk_PKCS12_SAFEBAG_is_sorted(st) SKM_sk_is_sorted(PKCS12_SAFEBAG, (st))
+
+#define sk_PKCS7_new(st) SKM_sk_new(PKCS7, (st))
+#define sk_PKCS7_new_null() SKM_sk_new_null(PKCS7)
+#define sk_PKCS7_free(st) SKM_sk_free(PKCS7, (st))
+#define sk_PKCS7_num(st) SKM_sk_num(PKCS7, (st))
+#define sk_PKCS7_value(st, i) SKM_sk_value(PKCS7, (st), (i))
+#define sk_PKCS7_set(st, i, val) SKM_sk_set(PKCS7, (st), (i), (val))
+#define sk_PKCS7_zero(st) SKM_sk_zero(PKCS7, (st))
+#define sk_PKCS7_push(st, val) SKM_sk_push(PKCS7, (st), (val))
+#define sk_PKCS7_unshift(st, val) SKM_sk_unshift(PKCS7, (st), (val))
+#define sk_PKCS7_find(st, val) SKM_sk_find(PKCS7, (st), (val))
+#define sk_PKCS7_find_ex(st, val) SKM_sk_find_ex(PKCS7, (st), (val))
+#define sk_PKCS7_delete(st, i) SKM_sk_delete(PKCS7, (st), (i))
+#define sk_PKCS7_delete_ptr(st, ptr) SKM_sk_delete_ptr(PKCS7, (st), (ptr))
+#define sk_PKCS7_insert(st, val, i) SKM_sk_insert(PKCS7, (st), (val), (i))
+#define sk_PKCS7_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(PKCS7, (st), (cmp))
+#define sk_PKCS7_dup(st) SKM_sk_dup(PKCS7, st)
+#define sk_PKCS7_pop_free(st, free_func) SKM_sk_pop_free(PKCS7, (st), (free_func))
+#define sk_PKCS7_shift(st) SKM_sk_shift(PKCS7, (st))
+#define sk_PKCS7_pop(st) SKM_sk_pop(PKCS7, (st))
+#define sk_PKCS7_sort(st) SKM_sk_sort(PKCS7, (st))
+#define sk_PKCS7_is_sorted(st) SKM_sk_is_sorted(PKCS7, (st))
+
+#define sk_PKCS7_RECIP_INFO_new(st) SKM_sk_new(PKCS7_RECIP_INFO, (st))
+#define sk_PKCS7_RECIP_INFO_new_null() SKM_sk_new_null(PKCS7_RECIP_INFO)
+#define sk_PKCS7_RECIP_INFO_free(st) SKM_sk_free(PKCS7_RECIP_INFO, (st))
+#define sk_PKCS7_RECIP_INFO_num(st) SKM_sk_num(PKCS7_RECIP_INFO, (st))
+#define sk_PKCS7_RECIP_INFO_value(st, i) SKM_sk_value(PKCS7_RECIP_INFO, (st), (i))
+#define sk_PKCS7_RECIP_INFO_set(st, i, val) SKM_sk_set(PKCS7_RECIP_INFO, (st), (i), (val))
+#define sk_PKCS7_RECIP_INFO_zero(st) SKM_sk_zero(PKCS7_RECIP_INFO, (st))
+#define sk_PKCS7_RECIP_INFO_push(st, val) SKM_sk_push(PKCS7_RECIP_INFO, (st), (val))
+#define sk_PKCS7_RECIP_INFO_unshift(st, val) SKM_sk_unshift(PKCS7_RECIP_INFO, (st), (val))
+#define sk_PKCS7_RECIP_INFO_find(st, val) SKM_sk_find(PKCS7_RECIP_INFO, (st), (val))
+#define sk_PKCS7_RECIP_INFO_find_ex(st, val) SKM_sk_find_ex(PKCS7_RECIP_INFO, (st), (val))
+#define sk_PKCS7_RECIP_INFO_delete(st, i) SKM_sk_delete(PKCS7_RECIP_INFO, (st), (i))
+#define sk_PKCS7_RECIP_INFO_delete_ptr(st, ptr) SKM_sk_delete_ptr(PKCS7_RECIP_INFO, (st), (ptr))
+#define sk_PKCS7_RECIP_INFO_insert(st, val, i) SKM_sk_insert(PKCS7_RECIP_INFO, (st), (val), (i))
+#define sk_PKCS7_RECIP_INFO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(PKCS7_RECIP_INFO, (st), (cmp))
+#define sk_PKCS7_RECIP_INFO_dup(st) SKM_sk_dup(PKCS7_RECIP_INFO, st)
+#define sk_PKCS7_RECIP_INFO_pop_free(st, free_func) SKM_sk_pop_free(PKCS7_RECIP_INFO, (st), (free_func))
+#define sk_PKCS7_RECIP_INFO_shift(st) SKM_sk_shift(PKCS7_RECIP_INFO, (st))
+#define sk_PKCS7_RECIP_INFO_pop(st) SKM_sk_pop(PKCS7_RECIP_INFO, (st))
+#define sk_PKCS7_RECIP_INFO_sort(st) SKM_sk_sort(PKCS7_RECIP_INFO, (st))
+#define sk_PKCS7_RECIP_INFO_is_sorted(st) SKM_sk_is_sorted(PKCS7_RECIP_INFO, (st))
+
+#define sk_PKCS7_SIGNER_INFO_new(st) SKM_sk_new(PKCS7_SIGNER_INFO, (st))
+#define sk_PKCS7_SIGNER_INFO_new_null() SKM_sk_new_null(PKCS7_SIGNER_INFO)
+#define sk_PKCS7_SIGNER_INFO_free(st) SKM_sk_free(PKCS7_SIGNER_INFO, (st))
+#define sk_PKCS7_SIGNER_INFO_num(st) SKM_sk_num(PKCS7_SIGNER_INFO, (st))
+#define sk_PKCS7_SIGNER_INFO_value(st, i) SKM_sk_value(PKCS7_SIGNER_INFO, (st), (i))
+#define sk_PKCS7_SIGNER_INFO_set(st, i, val) SKM_sk_set(PKCS7_SIGNER_INFO, (st), (i), (val))
+#define sk_PKCS7_SIGNER_INFO_zero(st) SKM_sk_zero(PKCS7_SIGNER_INFO, (st))
+#define sk_PKCS7_SIGNER_INFO_push(st, val) SKM_sk_push(PKCS7_SIGNER_INFO, (st), (val))
+#define sk_PKCS7_SIGNER_INFO_unshift(st, val) SKM_sk_unshift(PKCS7_SIGNER_INFO, (st), (val))
+#define sk_PKCS7_SIGNER_INFO_find(st, val) SKM_sk_find(PKCS7_SIGNER_INFO, (st), (val))
+#define sk_PKCS7_SIGNER_INFO_find_ex(st, val) SKM_sk_find_ex(PKCS7_SIGNER_INFO, (st), (val))
+#define sk_PKCS7_SIGNER_INFO_delete(st, i) SKM_sk_delete(PKCS7_SIGNER_INFO, (st), (i))
+#define sk_PKCS7_SIGNER_INFO_delete_ptr(st, ptr) SKM_sk_delete_ptr(PKCS7_SIGNER_INFO, (st), (ptr))
+#define sk_PKCS7_SIGNER_INFO_insert(st, val, i) SKM_sk_insert(PKCS7_SIGNER_INFO, (st), (val), (i))
+#define sk_PKCS7_SIGNER_INFO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(PKCS7_SIGNER_INFO, (st), (cmp))
+#define sk_PKCS7_SIGNER_INFO_dup(st) SKM_sk_dup(PKCS7_SIGNER_INFO, st)
+#define sk_PKCS7_SIGNER_INFO_pop_free(st, free_func) SKM_sk_pop_free(PKCS7_SIGNER_INFO, (st), (free_func))
+#define sk_PKCS7_SIGNER_INFO_shift(st) SKM_sk_shift(PKCS7_SIGNER_INFO, (st))
+#define sk_PKCS7_SIGNER_INFO_pop(st) SKM_sk_pop(PKCS7_SIGNER_INFO, (st))
+#define sk_PKCS7_SIGNER_INFO_sort(st) SKM_sk_sort(PKCS7_SIGNER_INFO, (st))
+#define sk_PKCS7_SIGNER_INFO_is_sorted(st) SKM_sk_is_sorted(PKCS7_SIGNER_INFO, (st))
+
+#define sk_POLICYINFO_new(st) SKM_sk_new(POLICYINFO, (st))
+#define sk_POLICYINFO_new_null() SKM_sk_new_null(POLICYINFO)
+#define sk_POLICYINFO_free(st) SKM_sk_free(POLICYINFO, (st))
+#define sk_POLICYINFO_num(st) SKM_sk_num(POLICYINFO, (st))
+#define sk_POLICYINFO_value(st, i) SKM_sk_value(POLICYINFO, (st), (i))
+#define sk_POLICYINFO_set(st, i, val) SKM_sk_set(POLICYINFO, (st), (i), (val))
+#define sk_POLICYINFO_zero(st) SKM_sk_zero(POLICYINFO, (st))
+#define sk_POLICYINFO_push(st, val) SKM_sk_push(POLICYINFO, (st), (val))
+#define sk_POLICYINFO_unshift(st, val) SKM_sk_unshift(POLICYINFO, (st), (val))
+#define sk_POLICYINFO_find(st, val) SKM_sk_find(POLICYINFO, (st), (val))
+#define sk_POLICYINFO_find_ex(st, val) SKM_sk_find_ex(POLICYINFO, (st), (val))
+#define sk_POLICYINFO_delete(st, i) SKM_sk_delete(POLICYINFO, (st), (i))
+#define sk_POLICYINFO_delete_ptr(st, ptr) SKM_sk_delete_ptr(POLICYINFO, (st), (ptr))
+#define sk_POLICYINFO_insert(st, val, i) SKM_sk_insert(POLICYINFO, (st), (val), (i))
+#define sk_POLICYINFO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(POLICYINFO, (st), (cmp))
+#define sk_POLICYINFO_dup(st) SKM_sk_dup(POLICYINFO, st)
+#define sk_POLICYINFO_pop_free(st, free_func) SKM_sk_pop_free(POLICYINFO, (st), (free_func))
+#define sk_POLICYINFO_shift(st) SKM_sk_shift(POLICYINFO, (st))
+#define sk_POLICYINFO_pop(st) SKM_sk_pop(POLICYINFO, (st))
+#define sk_POLICYINFO_sort(st) SKM_sk_sort(POLICYINFO, (st))
+#define sk_POLICYINFO_is_sorted(st) SKM_sk_is_sorted(POLICYINFO, (st))
+
+#define sk_POLICYQUALINFO_new(st) SKM_sk_new(POLICYQUALINFO, (st))
+#define sk_POLICYQUALINFO_new_null() SKM_sk_new_null(POLICYQUALINFO)
+#define sk_POLICYQUALINFO_free(st) SKM_sk_free(POLICYQUALINFO, (st))
+#define sk_POLICYQUALINFO_num(st) SKM_sk_num(POLICYQUALINFO, (st))
+#define sk_POLICYQUALINFO_value(st, i) SKM_sk_value(POLICYQUALINFO, (st), (i))
+#define sk_POLICYQUALINFO_set(st, i, val) SKM_sk_set(POLICYQUALINFO, (st), (i), (val))
+#define sk_POLICYQUALINFO_zero(st) SKM_sk_zero(POLICYQUALINFO, (st))
+#define sk_POLICYQUALINFO_push(st, val) SKM_sk_push(POLICYQUALINFO, (st), (val))
+#define sk_POLICYQUALINFO_unshift(st, val) SKM_sk_unshift(POLICYQUALINFO, (st), (val))
+#define sk_POLICYQUALINFO_find(st, val) SKM_sk_find(POLICYQUALINFO, (st), (val))
+#define sk_POLICYQUALINFO_find_ex(st, val) SKM_sk_find_ex(POLICYQUALINFO, (st), (val))
+#define sk_POLICYQUALINFO_delete(st, i) SKM_sk_delete(POLICYQUALINFO, (st), (i))
+#define sk_POLICYQUALINFO_delete_ptr(st, ptr) SKM_sk_delete_ptr(POLICYQUALINFO, (st), (ptr))
+#define sk_POLICYQUALINFO_insert(st, val, i) SKM_sk_insert(POLICYQUALINFO, (st), (val), (i))
+#define sk_POLICYQUALINFO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(POLICYQUALINFO, (st), (cmp))
+#define sk_POLICYQUALINFO_dup(st) SKM_sk_dup(POLICYQUALINFO, st)
+#define sk_POLICYQUALINFO_pop_free(st, free_func) SKM_sk_pop_free(POLICYQUALINFO, (st), (free_func))
+#define sk_POLICYQUALINFO_shift(st) SKM_sk_shift(POLICYQUALINFO, (st))
+#define sk_POLICYQUALINFO_pop(st) SKM_sk_pop(POLICYQUALINFO, (st))
+#define sk_POLICYQUALINFO_sort(st) SKM_sk_sort(POLICYQUALINFO, (st))
+#define sk_POLICYQUALINFO_is_sorted(st) SKM_sk_is_sorted(POLICYQUALINFO, (st))
+
+#define sk_POLICY_MAPPING_new(st) SKM_sk_new(POLICY_MAPPING, (st))
+#define sk_POLICY_MAPPING_new_null() SKM_sk_new_null(POLICY_MAPPING)
+#define sk_POLICY_MAPPING_free(st) SKM_sk_free(POLICY_MAPPING, (st))
+#define sk_POLICY_MAPPING_num(st) SKM_sk_num(POLICY_MAPPING, (st))
+#define sk_POLICY_MAPPING_value(st, i) SKM_sk_value(POLICY_MAPPING, (st), (i))
+#define sk_POLICY_MAPPING_set(st, i, val) SKM_sk_set(POLICY_MAPPING, (st), (i), (val))
+#define sk_POLICY_MAPPING_zero(st) SKM_sk_zero(POLICY_MAPPING, (st))
+#define sk_POLICY_MAPPING_push(st, val) SKM_sk_push(POLICY_MAPPING, (st), (val))
+#define sk_POLICY_MAPPING_unshift(st, val) SKM_sk_unshift(POLICY_MAPPING, (st), (val))
+#define sk_POLICY_MAPPING_find(st, val) SKM_sk_find(POLICY_MAPPING, (st), (val))
+#define sk_POLICY_MAPPING_find_ex(st, val) SKM_sk_find_ex(POLICY_MAPPING, (st), (val))
+#define sk_POLICY_MAPPING_delete(st, i) SKM_sk_delete(POLICY_MAPPING, (st), (i))
+#define sk_POLICY_MAPPING_delete_ptr(st, ptr) SKM_sk_delete_ptr(POLICY_MAPPING, (st), (ptr))
+#define sk_POLICY_MAPPING_insert(st, val, i) SKM_sk_insert(POLICY_MAPPING, (st), (val), (i))
+#define sk_POLICY_MAPPING_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(POLICY_MAPPING, (st), (cmp))
+#define sk_POLICY_MAPPING_dup(st) SKM_sk_dup(POLICY_MAPPING, st)
+#define sk_POLICY_MAPPING_pop_free(st, free_func) SKM_sk_pop_free(POLICY_MAPPING, (st), (free_func))
+#define sk_POLICY_MAPPING_shift(st) SKM_sk_shift(POLICY_MAPPING, (st))
+#define sk_POLICY_MAPPING_pop(st) SKM_sk_pop(POLICY_MAPPING, (st))
+#define sk_POLICY_MAPPING_sort(st) SKM_sk_sort(POLICY_MAPPING, (st))
+#define sk_POLICY_MAPPING_is_sorted(st) SKM_sk_is_sorted(POLICY_MAPPING, (st))
+
+#define sk_SSL_CIPHER_new(st) SKM_sk_new(SSL_CIPHER, (st))
+#define sk_SSL_CIPHER_new_null() SKM_sk_new_null(SSL_CIPHER)
+#define sk_SSL_CIPHER_free(st) SKM_sk_free(SSL_CIPHER, (st))
+#define sk_SSL_CIPHER_num(st) SKM_sk_num(SSL_CIPHER, (st))
+#define sk_SSL_CIPHER_value(st, i) SKM_sk_value(SSL_CIPHER, (st), (i))
+#define sk_SSL_CIPHER_set(st, i, val) SKM_sk_set(SSL_CIPHER, (st), (i), (val))
+#define sk_SSL_CIPHER_zero(st) SKM_sk_zero(SSL_CIPHER, (st))
+#define sk_SSL_CIPHER_push(st, val) SKM_sk_push(SSL_CIPHER, (st), (val))
+#define sk_SSL_CIPHER_unshift(st, val) SKM_sk_unshift(SSL_CIPHER, (st), (val))
+#define sk_SSL_CIPHER_find(st, val) SKM_sk_find(SSL_CIPHER, (st), (val))
+#define sk_SSL_CIPHER_find_ex(st, val) SKM_sk_find_ex(SSL_CIPHER, (st), (val))
+#define sk_SSL_CIPHER_delete(st, i) SKM_sk_delete(SSL_CIPHER, (st), (i))
+#define sk_SSL_CIPHER_delete_ptr(st, ptr) SKM_sk_delete_ptr(SSL_CIPHER, (st), (ptr))
+#define sk_SSL_CIPHER_insert(st, val, i) SKM_sk_insert(SSL_CIPHER, (st), (val), (i))
+#define sk_SSL_CIPHER_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(SSL_CIPHER, (st), (cmp))
+#define sk_SSL_CIPHER_dup(st) SKM_sk_dup(SSL_CIPHER, st)
+#define sk_SSL_CIPHER_pop_free(st, free_func) SKM_sk_pop_free(SSL_CIPHER, (st), (free_func))
+#define sk_SSL_CIPHER_shift(st) SKM_sk_shift(SSL_CIPHER, (st))
+#define sk_SSL_CIPHER_pop(st) SKM_sk_pop(SSL_CIPHER, (st))
+#define sk_SSL_CIPHER_sort(st) SKM_sk_sort(SSL_CIPHER, (st))
+#define sk_SSL_CIPHER_is_sorted(st) SKM_sk_is_sorted(SSL_CIPHER, (st))
+
+#define sk_SSL_COMP_new(st) SKM_sk_new(SSL_COMP, (st))
+#define sk_SSL_COMP_new_null() SKM_sk_new_null(SSL_COMP)
+#define sk_SSL_COMP_free(st) SKM_sk_free(SSL_COMP, (st))
+#define sk_SSL_COMP_num(st) SKM_sk_num(SSL_COMP, (st))
+#define sk_SSL_COMP_value(st, i) SKM_sk_value(SSL_COMP, (st), (i))
+#define sk_SSL_COMP_set(st, i, val) SKM_sk_set(SSL_COMP, (st), (i), (val))
+#define sk_SSL_COMP_zero(st) SKM_sk_zero(SSL_COMP, (st))
+#define sk_SSL_COMP_push(st, val) SKM_sk_push(SSL_COMP, (st), (val))
+#define sk_SSL_COMP_unshift(st, val) SKM_sk_unshift(SSL_COMP, (st), (val))
+#define sk_SSL_COMP_find(st, val) SKM_sk_find(SSL_COMP, (st), (val))
+#define sk_SSL_COMP_find_ex(st, val) SKM_sk_find_ex(SSL_COMP, (st), (val))
+#define sk_SSL_COMP_delete(st, i) SKM_sk_delete(SSL_COMP, (st), (i))
+#define sk_SSL_COMP_delete_ptr(st, ptr) SKM_sk_delete_ptr(SSL_COMP, (st), (ptr))
+#define sk_SSL_COMP_insert(st, val, i) SKM_sk_insert(SSL_COMP, (st), (val), (i))
+#define sk_SSL_COMP_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(SSL_COMP, (st), (cmp))
+#define sk_SSL_COMP_dup(st) SKM_sk_dup(SSL_COMP, st)
+#define sk_SSL_COMP_pop_free(st, free_func) SKM_sk_pop_free(SSL_COMP, (st), (free_func))
+#define sk_SSL_COMP_shift(st) SKM_sk_shift(SSL_COMP, (st))
+#define sk_SSL_COMP_pop(st) SKM_sk_pop(SSL_COMP, (st))
+#define sk_SSL_COMP_sort(st) SKM_sk_sort(SSL_COMP, (st))
+#define sk_SSL_COMP_is_sorted(st) SKM_sk_is_sorted(SSL_COMP, (st))
+
+#define sk_STORE_OBJECT_new(st) SKM_sk_new(STORE_OBJECT, (st))
+#define sk_STORE_OBJECT_new_null() SKM_sk_new_null(STORE_OBJECT)
+#define sk_STORE_OBJECT_free(st) SKM_sk_free(STORE_OBJECT, (st))
+#define sk_STORE_OBJECT_num(st) SKM_sk_num(STORE_OBJECT, (st))
+#define sk_STORE_OBJECT_value(st, i) SKM_sk_value(STORE_OBJECT, (st), (i))
+#define sk_STORE_OBJECT_set(st, i, val) SKM_sk_set(STORE_OBJECT, (st), (i), (val))
+#define sk_STORE_OBJECT_zero(st) SKM_sk_zero(STORE_OBJECT, (st))
+#define sk_STORE_OBJECT_push(st, val) SKM_sk_push(STORE_OBJECT, (st), (val))
+#define sk_STORE_OBJECT_unshift(st, val) SKM_sk_unshift(STORE_OBJECT, (st), (val))
+#define sk_STORE_OBJECT_find(st, val) SKM_sk_find(STORE_OBJECT, (st), (val))
+#define sk_STORE_OBJECT_find_ex(st, val) SKM_sk_find_ex(STORE_OBJECT, (st), (val))
+#define sk_STORE_OBJECT_delete(st, i) SKM_sk_delete(STORE_OBJECT, (st), (i))
+#define sk_STORE_OBJECT_delete_ptr(st, ptr) SKM_sk_delete_ptr(STORE_OBJECT, (st), (ptr))
+#define sk_STORE_OBJECT_insert(st, val, i) SKM_sk_insert(STORE_OBJECT, (st), (val), (i))
+#define sk_STORE_OBJECT_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(STORE_OBJECT, (st), (cmp))
+#define sk_STORE_OBJECT_dup(st) SKM_sk_dup(STORE_OBJECT, st)
+#define sk_STORE_OBJECT_pop_free(st, free_func) SKM_sk_pop_free(STORE_OBJECT, (st), (free_func))
+#define sk_STORE_OBJECT_shift(st) SKM_sk_shift(STORE_OBJECT, (st))
+#define sk_STORE_OBJECT_pop(st) SKM_sk_pop(STORE_OBJECT, (st))
+#define sk_STORE_OBJECT_sort(st) SKM_sk_sort(STORE_OBJECT, (st))
+#define sk_STORE_OBJECT_is_sorted(st) SKM_sk_is_sorted(STORE_OBJECT, (st))
+
+#define sk_SXNETID_new(st) SKM_sk_new(SXNETID, (st))
+#define sk_SXNETID_new_null() SKM_sk_new_null(SXNETID)
+#define sk_SXNETID_free(st) SKM_sk_free(SXNETID, (st))
+#define sk_SXNETID_num(st) SKM_sk_num(SXNETID, (st))
+#define sk_SXNETID_value(st, i) SKM_sk_value(SXNETID, (st), (i))
+#define sk_SXNETID_set(st, i, val) SKM_sk_set(SXNETID, (st), (i), (val))
+#define sk_SXNETID_zero(st) SKM_sk_zero(SXNETID, (st))
+#define sk_SXNETID_push(st, val) SKM_sk_push(SXNETID, (st), (val))
+#define sk_SXNETID_unshift(st, val) SKM_sk_unshift(SXNETID, (st), (val))
+#define sk_SXNETID_find(st, val) SKM_sk_find(SXNETID, (st), (val))
+#define sk_SXNETID_find_ex(st, val) SKM_sk_find_ex(SXNETID, (st), (val))
+#define sk_SXNETID_delete(st, i) SKM_sk_delete(SXNETID, (st), (i))
+#define sk_SXNETID_delete_ptr(st, ptr) SKM_sk_delete_ptr(SXNETID, (st), (ptr))
+#define sk_SXNETID_insert(st, val, i) SKM_sk_insert(SXNETID, (st), (val), (i))
+#define sk_SXNETID_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(SXNETID, (st), (cmp))
+#define sk_SXNETID_dup(st) SKM_sk_dup(SXNETID, st)
+#define sk_SXNETID_pop_free(st, free_func) SKM_sk_pop_free(SXNETID, (st), (free_func))
+#define sk_SXNETID_shift(st) SKM_sk_shift(SXNETID, (st))
+#define sk_SXNETID_pop(st) SKM_sk_pop(SXNETID, (st))
+#define sk_SXNETID_sort(st) SKM_sk_sort(SXNETID, (st))
+#define sk_SXNETID_is_sorted(st) SKM_sk_is_sorted(SXNETID, (st))
+
+#define sk_UI_STRING_new(st) SKM_sk_new(UI_STRING, (st))
+#define sk_UI_STRING_new_null() SKM_sk_new_null(UI_STRING)
+#define sk_UI_STRING_free(st) SKM_sk_free(UI_STRING, (st))
+#define sk_UI_STRING_num(st) SKM_sk_num(UI_STRING, (st))
+#define sk_UI_STRING_value(st, i) SKM_sk_value(UI_STRING, (st), (i))
+#define sk_UI_STRING_set(st, i, val) SKM_sk_set(UI_STRING, (st), (i), (val))
+#define sk_UI_STRING_zero(st) SKM_sk_zero(UI_STRING, (st))
+#define sk_UI_STRING_push(st, val) SKM_sk_push(UI_STRING, (st), (val))
+#define sk_UI_STRING_unshift(st, val) SKM_sk_unshift(UI_STRING, (st), (val))
+#define sk_UI_STRING_find(st, val) SKM_sk_find(UI_STRING, (st), (val))
+#define sk_UI_STRING_find_ex(st, val) SKM_sk_find_ex(UI_STRING, (st), (val))
+#define sk_UI_STRING_delete(st, i) SKM_sk_delete(UI_STRING, (st), (i))
+#define sk_UI_STRING_delete_ptr(st, ptr) SKM_sk_delete_ptr(UI_STRING, (st), (ptr))
+#define sk_UI_STRING_insert(st, val, i) SKM_sk_insert(UI_STRING, (st), (val), (i))
+#define sk_UI_STRING_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(UI_STRING, (st), (cmp))
+#define sk_UI_STRING_dup(st) SKM_sk_dup(UI_STRING, st)
+#define sk_UI_STRING_pop_free(st, free_func) SKM_sk_pop_free(UI_STRING, (st), (free_func))
+#define sk_UI_STRING_shift(st) SKM_sk_shift(UI_STRING, (st))
+#define sk_UI_STRING_pop(st) SKM_sk_pop(UI_STRING, (st))
+#define sk_UI_STRING_sort(st) SKM_sk_sort(UI_STRING, (st))
+#define sk_UI_STRING_is_sorted(st) SKM_sk_is_sorted(UI_STRING, (st))
+
+#define sk_X509_new(st) SKM_sk_new(X509, (st))
+#define sk_X509_new_null() SKM_sk_new_null(X509)
+#define sk_X509_free(st) SKM_sk_free(X509, (st))
+#define sk_X509_num(st) SKM_sk_num(X509, (st))
+#define sk_X509_value(st, i) SKM_sk_value(X509, (st), (i))
+#define sk_X509_set(st, i, val) SKM_sk_set(X509, (st), (i), (val))
+#define sk_X509_zero(st) SKM_sk_zero(X509, (st))
+#define sk_X509_push(st, val) SKM_sk_push(X509, (st), (val))
+#define sk_X509_unshift(st, val) SKM_sk_unshift(X509, (st), (val))
+#define sk_X509_find(st, val) SKM_sk_find(X509, (st), (val))
+#define sk_X509_find_ex(st, val) SKM_sk_find_ex(X509, (st), (val))
+#define sk_X509_delete(st, i) SKM_sk_delete(X509, (st), (i))
+#define sk_X509_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509, (st), (ptr))
+#define sk_X509_insert(st, val, i) SKM_sk_insert(X509, (st), (val), (i))
+#define sk_X509_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509, (st), (cmp))
+#define sk_X509_dup(st) SKM_sk_dup(X509, st)
+#define sk_X509_pop_free(st, free_func) SKM_sk_pop_free(X509, (st), (free_func))
+#define sk_X509_shift(st) SKM_sk_shift(X509, (st))
+#define sk_X509_pop(st) SKM_sk_pop(X509, (st))
+#define sk_X509_sort(st) SKM_sk_sort(X509, (st))
+#define sk_X509_is_sorted(st) SKM_sk_is_sorted(X509, (st))
+
+#define sk_X509V3_EXT_METHOD_new(st) SKM_sk_new(X509V3_EXT_METHOD, (st))
+#define sk_X509V3_EXT_METHOD_new_null() SKM_sk_new_null(X509V3_EXT_METHOD)
+#define sk_X509V3_EXT_METHOD_free(st) SKM_sk_free(X509V3_EXT_METHOD, (st))
+#define sk_X509V3_EXT_METHOD_num(st) SKM_sk_num(X509V3_EXT_METHOD, (st))
+#define sk_X509V3_EXT_METHOD_value(st, i) SKM_sk_value(X509V3_EXT_METHOD, (st), (i))
+#define sk_X509V3_EXT_METHOD_set(st, i, val) SKM_sk_set(X509V3_EXT_METHOD, (st), (i), (val))
+#define sk_X509V3_EXT_METHOD_zero(st) SKM_sk_zero(X509V3_EXT_METHOD, (st))
+#define sk_X509V3_EXT_METHOD_push(st, val) SKM_sk_push(X509V3_EXT_METHOD, (st), (val))
+#define sk_X509V3_EXT_METHOD_unshift(st, val) SKM_sk_unshift(X509V3_EXT_METHOD, (st), (val))
+#define sk_X509V3_EXT_METHOD_find(st, val) SKM_sk_find(X509V3_EXT_METHOD, (st), (val))
+#define sk_X509V3_EXT_METHOD_find_ex(st, val) SKM_sk_find_ex(X509V3_EXT_METHOD, (st), (val))
+#define sk_X509V3_EXT_METHOD_delete(st, i) SKM_sk_delete(X509V3_EXT_METHOD, (st), (i))
+#define sk_X509V3_EXT_METHOD_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509V3_EXT_METHOD, (st), (ptr))
+#define sk_X509V3_EXT_METHOD_insert(st, val, i) SKM_sk_insert(X509V3_EXT_METHOD, (st), (val), (i))
+#define sk_X509V3_EXT_METHOD_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509V3_EXT_METHOD, (st), (cmp))
+#define sk_X509V3_EXT_METHOD_dup(st) SKM_sk_dup(X509V3_EXT_METHOD, st)
+#define sk_X509V3_EXT_METHOD_pop_free(st, free_func) SKM_sk_pop_free(X509V3_EXT_METHOD, (st), (free_func))
+#define sk_X509V3_EXT_METHOD_shift(st) SKM_sk_shift(X509V3_EXT_METHOD, (st))
+#define sk_X509V3_EXT_METHOD_pop(st) SKM_sk_pop(X509V3_EXT_METHOD, (st))
+#define sk_X509V3_EXT_METHOD_sort(st) SKM_sk_sort(X509V3_EXT_METHOD, (st))
+#define sk_X509V3_EXT_METHOD_is_sorted(st) SKM_sk_is_sorted(X509V3_EXT_METHOD, (st))
+
+#define sk_X509_ALGOR_new(st) SKM_sk_new(X509_ALGOR, (st))
+#define sk_X509_ALGOR_new_null() SKM_sk_new_null(X509_ALGOR)
+#define sk_X509_ALGOR_free(st) SKM_sk_free(X509_ALGOR, (st))
+#define sk_X509_ALGOR_num(st) SKM_sk_num(X509_ALGOR, (st))
+#define sk_X509_ALGOR_value(st, i) SKM_sk_value(X509_ALGOR, (st), (i))
+#define sk_X509_ALGOR_set(st, i, val) SKM_sk_set(X509_ALGOR, (st), (i), (val))
+#define sk_X509_ALGOR_zero(st) SKM_sk_zero(X509_ALGOR, (st))
+#define sk_X509_ALGOR_push(st, val) SKM_sk_push(X509_ALGOR, (st), (val))
+#define sk_X509_ALGOR_unshift(st, val) SKM_sk_unshift(X509_ALGOR, (st), (val))
+#define sk_X509_ALGOR_find(st, val) SKM_sk_find(X509_ALGOR, (st), (val))
+#define sk_X509_ALGOR_find_ex(st, val) SKM_sk_find_ex(X509_ALGOR, (st), (val))
+#define sk_X509_ALGOR_delete(st, i) SKM_sk_delete(X509_ALGOR, (st), (i))
+#define sk_X509_ALGOR_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_ALGOR, (st), (ptr))
+#define sk_X509_ALGOR_insert(st, val, i) SKM_sk_insert(X509_ALGOR, (st), (val), (i))
+#define sk_X509_ALGOR_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_ALGOR, (st), (cmp))
+#define sk_X509_ALGOR_dup(st) SKM_sk_dup(X509_ALGOR, st)
+#define sk_X509_ALGOR_pop_free(st, free_func) SKM_sk_pop_free(X509_ALGOR, (st), (free_func))
+#define sk_X509_ALGOR_shift(st) SKM_sk_shift(X509_ALGOR, (st))
+#define sk_X509_ALGOR_pop(st) SKM_sk_pop(X509_ALGOR, (st))
+#define sk_X509_ALGOR_sort(st) SKM_sk_sort(X509_ALGOR, (st))
+#define sk_X509_ALGOR_is_sorted(st) SKM_sk_is_sorted(X509_ALGOR, (st))
+
+#define sk_X509_ATTRIBUTE_new(st) SKM_sk_new(X509_ATTRIBUTE, (st))
+#define sk_X509_ATTRIBUTE_new_null() SKM_sk_new_null(X509_ATTRIBUTE)
+#define sk_X509_ATTRIBUTE_free(st) SKM_sk_free(X509_ATTRIBUTE, (st))
+#define sk_X509_ATTRIBUTE_num(st) SKM_sk_num(X509_ATTRIBUTE, (st))
+#define sk_X509_ATTRIBUTE_value(st, i) SKM_sk_value(X509_ATTRIBUTE, (st), (i))
+#define sk_X509_ATTRIBUTE_set(st, i, val) SKM_sk_set(X509_ATTRIBUTE, (st), (i), (val))
+#define sk_X509_ATTRIBUTE_zero(st) SKM_sk_zero(X509_ATTRIBUTE, (st))
+#define sk_X509_ATTRIBUTE_push(st, val) SKM_sk_push(X509_ATTRIBUTE, (st), (val))
+#define sk_X509_ATTRIBUTE_unshift(st, val) SKM_sk_unshift(X509_ATTRIBUTE, (st), (val))
+#define sk_X509_ATTRIBUTE_find(st, val) SKM_sk_find(X509_ATTRIBUTE, (st), (val))
+#define sk_X509_ATTRIBUTE_find_ex(st, val) SKM_sk_find_ex(X509_ATTRIBUTE, (st), (val))
+#define sk_X509_ATTRIBUTE_delete(st, i) SKM_sk_delete(X509_ATTRIBUTE, (st), (i))
+#define sk_X509_ATTRIBUTE_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_ATTRIBUTE, (st), (ptr))
+#define sk_X509_ATTRIBUTE_insert(st, val, i) SKM_sk_insert(X509_ATTRIBUTE, (st), (val), (i))
+#define sk_X509_ATTRIBUTE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_ATTRIBUTE, (st), (cmp))
+#define sk_X509_ATTRIBUTE_dup(st) SKM_sk_dup(X509_ATTRIBUTE, st)
+#define sk_X509_ATTRIBUTE_pop_free(st, free_func) SKM_sk_pop_free(X509_ATTRIBUTE, (st), (free_func))
+#define sk_X509_ATTRIBUTE_shift(st) SKM_sk_shift(X509_ATTRIBUTE, (st))
+#define sk_X509_ATTRIBUTE_pop(st) SKM_sk_pop(X509_ATTRIBUTE, (st))
+#define sk_X509_ATTRIBUTE_sort(st) SKM_sk_sort(X509_ATTRIBUTE, (st))
+#define sk_X509_ATTRIBUTE_is_sorted(st) SKM_sk_is_sorted(X509_ATTRIBUTE, (st))
+
+#define sk_X509_CRL_new(st) SKM_sk_new(X509_CRL, (st))
+#define sk_X509_CRL_new_null() SKM_sk_new_null(X509_CRL)
+#define sk_X509_CRL_free(st) SKM_sk_free(X509_CRL, (st))
+#define sk_X509_CRL_num(st) SKM_sk_num(X509_CRL, (st))
+#define sk_X509_CRL_value(st, i) SKM_sk_value(X509_CRL, (st), (i))
+#define sk_X509_CRL_set(st, i, val) SKM_sk_set(X509_CRL, (st), (i), (val))
+#define sk_X509_CRL_zero(st) SKM_sk_zero(X509_CRL, (st))
+#define sk_X509_CRL_push(st, val) SKM_sk_push(X509_CRL, (st), (val))
+#define sk_X509_CRL_unshift(st, val) SKM_sk_unshift(X509_CRL, (st), (val))
+#define sk_X509_CRL_find(st, val) SKM_sk_find(X509_CRL, (st), (val))
+#define sk_X509_CRL_find_ex(st, val) SKM_sk_find_ex(X509_CRL, (st), (val))
+#define sk_X509_CRL_delete(st, i) SKM_sk_delete(X509_CRL, (st), (i))
+#define sk_X509_CRL_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_CRL, (st), (ptr))
+#define sk_X509_CRL_insert(st, val, i) SKM_sk_insert(X509_CRL, (st), (val), (i))
+#define sk_X509_CRL_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_CRL, (st), (cmp))
+#define sk_X509_CRL_dup(st) SKM_sk_dup(X509_CRL, st)
+#define sk_X509_CRL_pop_free(st, free_func) SKM_sk_pop_free(X509_CRL, (st), (free_func))
+#define sk_X509_CRL_shift(st) SKM_sk_shift(X509_CRL, (st))
+#define sk_X509_CRL_pop(st) SKM_sk_pop(X509_CRL, (st))
+#define sk_X509_CRL_sort(st) SKM_sk_sort(X509_CRL, (st))
+#define sk_X509_CRL_is_sorted(st) SKM_sk_is_sorted(X509_CRL, (st))
+
+#define sk_X509_EXTENSION_new(st) SKM_sk_new(X509_EXTENSION, (st))
+#define sk_X509_EXTENSION_new_null() SKM_sk_new_null(X509_EXTENSION)
+#define sk_X509_EXTENSION_free(st) SKM_sk_free(X509_EXTENSION, (st))
+#define sk_X509_EXTENSION_num(st) SKM_sk_num(X509_EXTENSION, (st))
+#define sk_X509_EXTENSION_value(st, i) SKM_sk_value(X509_EXTENSION, (st), (i))
+#define sk_X509_EXTENSION_set(st, i, val) SKM_sk_set(X509_EXTENSION, (st), (i), (val))
+#define sk_X509_EXTENSION_zero(st) SKM_sk_zero(X509_EXTENSION, (st))
+#define sk_X509_EXTENSION_push(st, val) SKM_sk_push(X509_EXTENSION, (st), (val))
+#define sk_X509_EXTENSION_unshift(st, val) SKM_sk_unshift(X509_EXTENSION, (st), (val))
+#define sk_X509_EXTENSION_find(st, val) SKM_sk_find(X509_EXTENSION, (st), (val))
+#define sk_X509_EXTENSION_find_ex(st, val) SKM_sk_find_ex(X509_EXTENSION, (st), (val))
+#define sk_X509_EXTENSION_delete(st, i) SKM_sk_delete(X509_EXTENSION, (st), (i))
+#define sk_X509_EXTENSION_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_EXTENSION, (st), (ptr))
+#define sk_X509_EXTENSION_insert(st, val, i) SKM_sk_insert(X509_EXTENSION, (st), (val), (i))
+#define sk_X509_EXTENSION_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_EXTENSION, (st), (cmp))
+#define sk_X509_EXTENSION_dup(st) SKM_sk_dup(X509_EXTENSION, st)
+#define sk_X509_EXTENSION_pop_free(st, free_func) SKM_sk_pop_free(X509_EXTENSION, (st), (free_func))
+#define sk_X509_EXTENSION_shift(st) SKM_sk_shift(X509_EXTENSION, (st))
+#define sk_X509_EXTENSION_pop(st) SKM_sk_pop(X509_EXTENSION, (st))
+#define sk_X509_EXTENSION_sort(st) SKM_sk_sort(X509_EXTENSION, (st))
+#define sk_X509_EXTENSION_is_sorted(st) SKM_sk_is_sorted(X509_EXTENSION, (st))
+
+#define sk_X509_INFO_new(st) SKM_sk_new(X509_INFO, (st))
+#define sk_X509_INFO_new_null() SKM_sk_new_null(X509_INFO)
+#define sk_X509_INFO_free(st) SKM_sk_free(X509_INFO, (st))
+#define sk_X509_INFO_num(st) SKM_sk_num(X509_INFO, (st))
+#define sk_X509_INFO_value(st, i) SKM_sk_value(X509_INFO, (st), (i))
+#define sk_X509_INFO_set(st, i, val) SKM_sk_set(X509_INFO, (st), (i), (val))
+#define sk_X509_INFO_zero(st) SKM_sk_zero(X509_INFO, (st))
+#define sk_X509_INFO_push(st, val) SKM_sk_push(X509_INFO, (st), (val))
+#define sk_X509_INFO_unshift(st, val) SKM_sk_unshift(X509_INFO, (st), (val))
+#define sk_X509_INFO_find(st, val) SKM_sk_find(X509_INFO, (st), (val))
+#define sk_X509_INFO_find_ex(st, val) SKM_sk_find_ex(X509_INFO, (st), (val))
+#define sk_X509_INFO_delete(st, i) SKM_sk_delete(X509_INFO, (st), (i))
+#define sk_X509_INFO_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_INFO, (st), (ptr))
+#define sk_X509_INFO_insert(st, val, i) SKM_sk_insert(X509_INFO, (st), (val), (i))
+#define sk_X509_INFO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_INFO, (st), (cmp))
+#define sk_X509_INFO_dup(st) SKM_sk_dup(X509_INFO, st)
+#define sk_X509_INFO_pop_free(st, free_func) SKM_sk_pop_free(X509_INFO, (st), (free_func))
+#define sk_X509_INFO_shift(st) SKM_sk_shift(X509_INFO, (st))
+#define sk_X509_INFO_pop(st) SKM_sk_pop(X509_INFO, (st))
+#define sk_X509_INFO_sort(st) SKM_sk_sort(X509_INFO, (st))
+#define sk_X509_INFO_is_sorted(st) SKM_sk_is_sorted(X509_INFO, (st))
+
+#define sk_X509_LOOKUP_new(st) SKM_sk_new(X509_LOOKUP, (st))
+#define sk_X509_LOOKUP_new_null() SKM_sk_new_null(X509_LOOKUP)
+#define sk_X509_LOOKUP_free(st) SKM_sk_free(X509_LOOKUP, (st))
+#define sk_X509_LOOKUP_num(st) SKM_sk_num(X509_LOOKUP, (st))
+#define sk_X509_LOOKUP_value(st, i) SKM_sk_value(X509_LOOKUP, (st), (i))
+#define sk_X509_LOOKUP_set(st, i, val) SKM_sk_set(X509_LOOKUP, (st), (i), (val))
+#define sk_X509_LOOKUP_zero(st) SKM_sk_zero(X509_LOOKUP, (st))
+#define sk_X509_LOOKUP_push(st, val) SKM_sk_push(X509_LOOKUP, (st), (val))
+#define sk_X509_LOOKUP_unshift(st, val) SKM_sk_unshift(X509_LOOKUP, (st), (val))
+#define sk_X509_LOOKUP_find(st, val) SKM_sk_find(X509_LOOKUP, (st), (val))
+#define sk_X509_LOOKUP_find_ex(st, val) SKM_sk_find_ex(X509_LOOKUP, (st), (val))
+#define sk_X509_LOOKUP_delete(st, i) SKM_sk_delete(X509_LOOKUP, (st), (i))
+#define sk_X509_LOOKUP_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_LOOKUP, (st), (ptr))
+#define sk_X509_LOOKUP_insert(st, val, i) SKM_sk_insert(X509_LOOKUP, (st), (val), (i))
+#define sk_X509_LOOKUP_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_LOOKUP, (st), (cmp))
+#define sk_X509_LOOKUP_dup(st) SKM_sk_dup(X509_LOOKUP, st)
+#define sk_X509_LOOKUP_pop_free(st, free_func) SKM_sk_pop_free(X509_LOOKUP, (st), (free_func))
+#define sk_X509_LOOKUP_shift(st) SKM_sk_shift(X509_LOOKUP, (st))
+#define sk_X509_LOOKUP_pop(st) SKM_sk_pop(X509_LOOKUP, (st))
+#define sk_X509_LOOKUP_sort(st) SKM_sk_sort(X509_LOOKUP, (st))
+#define sk_X509_LOOKUP_is_sorted(st) SKM_sk_is_sorted(X509_LOOKUP, (st))
+
+#define sk_X509_NAME_new(st) SKM_sk_new(X509_NAME, (st))
+#define sk_X509_NAME_new_null() SKM_sk_new_null(X509_NAME)
+#define sk_X509_NAME_free(st) SKM_sk_free(X509_NAME, (st))
+#define sk_X509_NAME_num(st) SKM_sk_num(X509_NAME, (st))
+#define sk_X509_NAME_value(st, i) SKM_sk_value(X509_NAME, (st), (i))
+#define sk_X509_NAME_set(st, i, val) SKM_sk_set(X509_NAME, (st), (i), (val))
+#define sk_X509_NAME_zero(st) SKM_sk_zero(X509_NAME, (st))
+#define sk_X509_NAME_push(st, val) SKM_sk_push(X509_NAME, (st), (val))
+#define sk_X509_NAME_unshift(st, val) SKM_sk_unshift(X509_NAME, (st), (val))
+#define sk_X509_NAME_find(st, val) SKM_sk_find(X509_NAME, (st), (val))
+#define sk_X509_NAME_find_ex(st, val) SKM_sk_find_ex(X509_NAME, (st), (val))
+#define sk_X509_NAME_delete(st, i) SKM_sk_delete(X509_NAME, (st), (i))
+#define sk_X509_NAME_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_NAME, (st), (ptr))
+#define sk_X509_NAME_insert(st, val, i) SKM_sk_insert(X509_NAME, (st), (val), (i))
+#define sk_X509_NAME_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_NAME, (st), (cmp))
+#define sk_X509_NAME_dup(st) SKM_sk_dup(X509_NAME, st)
+#define sk_X509_NAME_pop_free(st, free_func) SKM_sk_pop_free(X509_NAME, (st), (free_func))
+#define sk_X509_NAME_shift(st) SKM_sk_shift(X509_NAME, (st))
+#define sk_X509_NAME_pop(st) SKM_sk_pop(X509_NAME, (st))
+#define sk_X509_NAME_sort(st) SKM_sk_sort(X509_NAME, (st))
+#define sk_X509_NAME_is_sorted(st) SKM_sk_is_sorted(X509_NAME, (st))
+
+#define sk_X509_NAME_ENTRY_new(st) SKM_sk_new(X509_NAME_ENTRY, (st))
+#define sk_X509_NAME_ENTRY_new_null() SKM_sk_new_null(X509_NAME_ENTRY)
+#define sk_X509_NAME_ENTRY_free(st) SKM_sk_free(X509_NAME_ENTRY, (st))
+#define sk_X509_NAME_ENTRY_num(st) SKM_sk_num(X509_NAME_ENTRY, (st))
+#define sk_X509_NAME_ENTRY_value(st, i) SKM_sk_value(X509_NAME_ENTRY, (st), (i))
+#define sk_X509_NAME_ENTRY_set(st, i, val) SKM_sk_set(X509_NAME_ENTRY, (st), (i), (val))
+#define sk_X509_NAME_ENTRY_zero(st) SKM_sk_zero(X509_NAME_ENTRY, (st))
+#define sk_X509_NAME_ENTRY_push(st, val) SKM_sk_push(X509_NAME_ENTRY, (st), (val))
+#define sk_X509_NAME_ENTRY_unshift(st, val) SKM_sk_unshift(X509_NAME_ENTRY, (st), (val))
+#define sk_X509_NAME_ENTRY_find(st, val) SKM_sk_find(X509_NAME_ENTRY, (st), (val))
+#define sk_X509_NAME_ENTRY_find_ex(st, val) SKM_sk_find_ex(X509_NAME_ENTRY, (st), (val))
+#define sk_X509_NAME_ENTRY_delete(st, i) SKM_sk_delete(X509_NAME_ENTRY, (st), (i))
+#define sk_X509_NAME_ENTRY_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_NAME_ENTRY, (st), (ptr))
+#define sk_X509_NAME_ENTRY_insert(st, val, i) SKM_sk_insert(X509_NAME_ENTRY, (st), (val), (i))
+#define sk_X509_NAME_ENTRY_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_NAME_ENTRY, (st), (cmp))
+#define sk_X509_NAME_ENTRY_dup(st) SKM_sk_dup(X509_NAME_ENTRY, st)
+#define sk_X509_NAME_ENTRY_pop_free(st, free_func) SKM_sk_pop_free(X509_NAME_ENTRY, (st), (free_func))
+#define sk_X509_NAME_ENTRY_shift(st) SKM_sk_shift(X509_NAME_ENTRY, (st))
+#define sk_X509_NAME_ENTRY_pop(st) SKM_sk_pop(X509_NAME_ENTRY, (st))
+#define sk_X509_NAME_ENTRY_sort(st) SKM_sk_sort(X509_NAME_ENTRY, (st))
+#define sk_X509_NAME_ENTRY_is_sorted(st) SKM_sk_is_sorted(X509_NAME_ENTRY, (st))
+
+#define sk_X509_OBJECT_new(st) SKM_sk_new(X509_OBJECT, (st))
+#define sk_X509_OBJECT_new_null() SKM_sk_new_null(X509_OBJECT)
+#define sk_X509_OBJECT_free(st) SKM_sk_free(X509_OBJECT, (st))
+#define sk_X509_OBJECT_num(st) SKM_sk_num(X509_OBJECT, (st))
+#define sk_X509_OBJECT_value(st, i) SKM_sk_value(X509_OBJECT, (st), (i))
+#define sk_X509_OBJECT_set(st, i, val) SKM_sk_set(X509_OBJECT, (st), (i), (val))
+#define sk_X509_OBJECT_zero(st) SKM_sk_zero(X509_OBJECT, (st))
+#define sk_X509_OBJECT_push(st, val) SKM_sk_push(X509_OBJECT, (st), (val))
+#define sk_X509_OBJECT_unshift(st, val) SKM_sk_unshift(X509_OBJECT, (st), (val))
+#define sk_X509_OBJECT_find(st, val) SKM_sk_find(X509_OBJECT, (st), (val))
+#define sk_X509_OBJECT_find_ex(st, val) SKM_sk_find_ex(X509_OBJECT, (st), (val))
+#define sk_X509_OBJECT_delete(st, i) SKM_sk_delete(X509_OBJECT, (st), (i))
+#define sk_X509_OBJECT_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_OBJECT, (st), (ptr))
+#define sk_X509_OBJECT_insert(st, val, i) SKM_sk_insert(X509_OBJECT, (st), (val), (i))
+#define sk_X509_OBJECT_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_OBJECT, (st), (cmp))
+#define sk_X509_OBJECT_dup(st) SKM_sk_dup(X509_OBJECT, st)
+#define sk_X509_OBJECT_pop_free(st, free_func) SKM_sk_pop_free(X509_OBJECT, (st), (free_func))
+#define sk_X509_OBJECT_shift(st) SKM_sk_shift(X509_OBJECT, (st))
+#define sk_X509_OBJECT_pop(st) SKM_sk_pop(X509_OBJECT, (st))
+#define sk_X509_OBJECT_sort(st) SKM_sk_sort(X509_OBJECT, (st))
+#define sk_X509_OBJECT_is_sorted(st) SKM_sk_is_sorted(X509_OBJECT, (st))
+
+#define sk_X509_POLICY_DATA_new(st) SKM_sk_new(X509_POLICY_DATA, (st))
+#define sk_X509_POLICY_DATA_new_null() SKM_sk_new_null(X509_POLICY_DATA)
+#define sk_X509_POLICY_DATA_free(st) SKM_sk_free(X509_POLICY_DATA, (st))
+#define sk_X509_POLICY_DATA_num(st) SKM_sk_num(X509_POLICY_DATA, (st))
+#define sk_X509_POLICY_DATA_value(st, i) SKM_sk_value(X509_POLICY_DATA, (st), (i))
+#define sk_X509_POLICY_DATA_set(st, i, val) SKM_sk_set(X509_POLICY_DATA, (st), (i), (val))
+#define sk_X509_POLICY_DATA_zero(st) SKM_sk_zero(X509_POLICY_DATA, (st))
+#define sk_X509_POLICY_DATA_push(st, val) SKM_sk_push(X509_POLICY_DATA, (st), (val))
+#define sk_X509_POLICY_DATA_unshift(st, val) SKM_sk_unshift(X509_POLICY_DATA, (st), (val))
+#define sk_X509_POLICY_DATA_find(st, val) SKM_sk_find(X509_POLICY_DATA, (st), (val))
+#define sk_X509_POLICY_DATA_find_ex(st, val) SKM_sk_find_ex(X509_POLICY_DATA, (st), (val))
+#define sk_X509_POLICY_DATA_delete(st, i) SKM_sk_delete(X509_POLICY_DATA, (st), (i))
+#define sk_X509_POLICY_DATA_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_POLICY_DATA, (st), (ptr))
+#define sk_X509_POLICY_DATA_insert(st, val, i) SKM_sk_insert(X509_POLICY_DATA, (st), (val), (i))
+#define sk_X509_POLICY_DATA_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_POLICY_DATA, (st), (cmp))
+#define sk_X509_POLICY_DATA_dup(st) SKM_sk_dup(X509_POLICY_DATA, st)
+#define sk_X509_POLICY_DATA_pop_free(st, free_func) SKM_sk_pop_free(X509_POLICY_DATA, (st), (free_func))
+#define sk_X509_POLICY_DATA_shift(st) SKM_sk_shift(X509_POLICY_DATA, (st))
+#define sk_X509_POLICY_DATA_pop(st) SKM_sk_pop(X509_POLICY_DATA, (st))
+#define sk_X509_POLICY_DATA_sort(st) SKM_sk_sort(X509_POLICY_DATA, (st))
+#define sk_X509_POLICY_DATA_is_sorted(st) SKM_sk_is_sorted(X509_POLICY_DATA, (st))
+
+#define sk_X509_POLICY_NODE_new(st) SKM_sk_new(X509_POLICY_NODE, (st))
+#define sk_X509_POLICY_NODE_new_null() SKM_sk_new_null(X509_POLICY_NODE)
+#define sk_X509_POLICY_NODE_free(st) SKM_sk_free(X509_POLICY_NODE, (st))
+#define sk_X509_POLICY_NODE_num(st) SKM_sk_num(X509_POLICY_NODE, (st))
+#define sk_X509_POLICY_NODE_value(st, i) SKM_sk_value(X509_POLICY_NODE, (st), (i))
+#define sk_X509_POLICY_NODE_set(st, i, val) SKM_sk_set(X509_POLICY_NODE, (st), (i), (val))
+#define sk_X509_POLICY_NODE_zero(st) SKM_sk_zero(X509_POLICY_NODE, (st))
+#define sk_X509_POLICY_NODE_push(st, val) SKM_sk_push(X509_POLICY_NODE, (st), (val))
+#define sk_X509_POLICY_NODE_unshift(st, val) SKM_sk_unshift(X509_POLICY_NODE, (st), (val))
+#define sk_X509_POLICY_NODE_find(st, val) SKM_sk_find(X509_POLICY_NODE, (st), (val))
+#define sk_X509_POLICY_NODE_find_ex(st, val) SKM_sk_find_ex(X509_POLICY_NODE, (st), (val))
+#define sk_X509_POLICY_NODE_delete(st, i) SKM_sk_delete(X509_POLICY_NODE, (st), (i))
+#define sk_X509_POLICY_NODE_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_POLICY_NODE, (st), (ptr))
+#define sk_X509_POLICY_NODE_insert(st, val, i) SKM_sk_insert(X509_POLICY_NODE, (st), (val), (i))
+#define sk_X509_POLICY_NODE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_POLICY_NODE, (st), (cmp))
+#define sk_X509_POLICY_NODE_dup(st) SKM_sk_dup(X509_POLICY_NODE, st)
+#define sk_X509_POLICY_NODE_pop_free(st, free_func) SKM_sk_pop_free(X509_POLICY_NODE, (st), (free_func))
+#define sk_X509_POLICY_NODE_shift(st) SKM_sk_shift(X509_POLICY_NODE, (st))
+#define sk_X509_POLICY_NODE_pop(st) SKM_sk_pop(X509_POLICY_NODE, (st))
+#define sk_X509_POLICY_NODE_sort(st) SKM_sk_sort(X509_POLICY_NODE, (st))
+#define sk_X509_POLICY_NODE_is_sorted(st) SKM_sk_is_sorted(X509_POLICY_NODE, (st))
+
+#define sk_X509_POLICY_REF_new(st) SKM_sk_new(X509_POLICY_REF, (st))
+#define sk_X509_POLICY_REF_new_null() SKM_sk_new_null(X509_POLICY_REF)
+#define sk_X509_POLICY_REF_free(st) SKM_sk_free(X509_POLICY_REF, (st))
+#define sk_X509_POLICY_REF_num(st) SKM_sk_num(X509_POLICY_REF, (st))
+#define sk_X509_POLICY_REF_value(st, i) SKM_sk_value(X509_POLICY_REF, (st), (i))
+#define sk_X509_POLICY_REF_set(st, i, val) SKM_sk_set(X509_POLICY_REF, (st), (i), (val))
+#define sk_X509_POLICY_REF_zero(st) SKM_sk_zero(X509_POLICY_REF, (st))
+#define sk_X509_POLICY_REF_push(st, val) SKM_sk_push(X509_POLICY_REF, (st), (val))
+#define sk_X509_POLICY_REF_unshift(st, val) SKM_sk_unshift(X509_POLICY_REF, (st), (val))
+#define sk_X509_POLICY_REF_find(st, val) SKM_sk_find(X509_POLICY_REF, (st), (val))
+#define sk_X509_POLICY_REF_find_ex(st, val) SKM_sk_find_ex(X509_POLICY_REF, (st), (val))
+#define sk_X509_POLICY_REF_delete(st, i) SKM_sk_delete(X509_POLICY_REF, (st), (i))
+#define sk_X509_POLICY_REF_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_POLICY_REF, (st), (ptr))
+#define sk_X509_POLICY_REF_insert(st, val, i) SKM_sk_insert(X509_POLICY_REF, (st), (val), (i))
+#define sk_X509_POLICY_REF_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_POLICY_REF, (st), (cmp))
+#define sk_X509_POLICY_REF_dup(st) SKM_sk_dup(X509_POLICY_REF, st)
+#define sk_X509_POLICY_REF_pop_free(st, free_func) SKM_sk_pop_free(X509_POLICY_REF, (st), (free_func))
+#define sk_X509_POLICY_REF_shift(st) SKM_sk_shift(X509_POLICY_REF, (st))
+#define sk_X509_POLICY_REF_pop(st) SKM_sk_pop(X509_POLICY_REF, (st))
+#define sk_X509_POLICY_REF_sort(st) SKM_sk_sort(X509_POLICY_REF, (st))
+#define sk_X509_POLICY_REF_is_sorted(st) SKM_sk_is_sorted(X509_POLICY_REF, (st))
+
+#define sk_X509_PURPOSE_new(st) SKM_sk_new(X509_PURPOSE, (st))
+#define sk_X509_PURPOSE_new_null() SKM_sk_new_null(X509_PURPOSE)
+#define sk_X509_PURPOSE_free(st) SKM_sk_free(X509_PURPOSE, (st))
+#define sk_X509_PURPOSE_num(st) SKM_sk_num(X509_PURPOSE, (st))
+#define sk_X509_PURPOSE_value(st, i) SKM_sk_value(X509_PURPOSE, (st), (i))
+#define sk_X509_PURPOSE_set(st, i, val) SKM_sk_set(X509_PURPOSE, (st), (i), (val))
+#define sk_X509_PURPOSE_zero(st) SKM_sk_zero(X509_PURPOSE, (st))
+#define sk_X509_PURPOSE_push(st, val) SKM_sk_push(X509_PURPOSE, (st), (val))
+#define sk_X509_PURPOSE_unshift(st, val) SKM_sk_unshift(X509_PURPOSE, (st), (val))
+#define sk_X509_PURPOSE_find(st, val) SKM_sk_find(X509_PURPOSE, (st), (val))
+#define sk_X509_PURPOSE_find_ex(st, val) SKM_sk_find_ex(X509_PURPOSE, (st), (val))
+#define sk_X509_PURPOSE_delete(st, i) SKM_sk_delete(X509_PURPOSE, (st), (i))
+#define sk_X509_PURPOSE_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_PURPOSE, (st), (ptr))
+#define sk_X509_PURPOSE_insert(st, val, i) SKM_sk_insert(X509_PURPOSE, (st), (val), (i))
+#define sk_X509_PURPOSE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_PURPOSE, (st), (cmp))
+#define sk_X509_PURPOSE_dup(st) SKM_sk_dup(X509_PURPOSE, st)
+#define sk_X509_PURPOSE_pop_free(st, free_func) SKM_sk_pop_free(X509_PURPOSE, (st), (free_func))
+#define sk_X509_PURPOSE_shift(st) SKM_sk_shift(X509_PURPOSE, (st))
+#define sk_X509_PURPOSE_pop(st) SKM_sk_pop(X509_PURPOSE, (st))
+#define sk_X509_PURPOSE_sort(st) SKM_sk_sort(X509_PURPOSE, (st))
+#define sk_X509_PURPOSE_is_sorted(st) SKM_sk_is_sorted(X509_PURPOSE, (st))
+
+#define sk_X509_REVOKED_new(st) SKM_sk_new(X509_REVOKED, (st))
+#define sk_X509_REVOKED_new_null() SKM_sk_new_null(X509_REVOKED)
+#define sk_X509_REVOKED_free(st) SKM_sk_free(X509_REVOKED, (st))
+#define sk_X509_REVOKED_num(st) SKM_sk_num(X509_REVOKED, (st))
+#define sk_X509_REVOKED_value(st, i) SKM_sk_value(X509_REVOKED, (st), (i))
+#define sk_X509_REVOKED_set(st, i, val) SKM_sk_set(X509_REVOKED, (st), (i), (val))
+#define sk_X509_REVOKED_zero(st) SKM_sk_zero(X509_REVOKED, (st))
+#define sk_X509_REVOKED_push(st, val) SKM_sk_push(X509_REVOKED, (st), (val))
+#define sk_X509_REVOKED_unshift(st, val) SKM_sk_unshift(X509_REVOKED, (st), (val))
+#define sk_X509_REVOKED_find(st, val) SKM_sk_find(X509_REVOKED, (st), (val))
+#define sk_X509_REVOKED_find_ex(st, val) SKM_sk_find_ex(X509_REVOKED, (st), (val))
+#define sk_X509_REVOKED_delete(st, i) SKM_sk_delete(X509_REVOKED, (st), (i))
+#define sk_X509_REVOKED_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_REVOKED, (st), (ptr))
+#define sk_X509_REVOKED_insert(st, val, i) SKM_sk_insert(X509_REVOKED, (st), (val), (i))
+#define sk_X509_REVOKED_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_REVOKED, (st), (cmp))
+#define sk_X509_REVOKED_dup(st) SKM_sk_dup(X509_REVOKED, st)
+#define sk_X509_REVOKED_pop_free(st, free_func) SKM_sk_pop_free(X509_REVOKED, (st), (free_func))
+#define sk_X509_REVOKED_shift(st) SKM_sk_shift(X509_REVOKED, (st))
+#define sk_X509_REVOKED_pop(st) SKM_sk_pop(X509_REVOKED, (st))
+#define sk_X509_REVOKED_sort(st) SKM_sk_sort(X509_REVOKED, (st))
+#define sk_X509_REVOKED_is_sorted(st) SKM_sk_is_sorted(X509_REVOKED, (st))
+
+#define sk_X509_TRUST_new(st) SKM_sk_new(X509_TRUST, (st))
+#define sk_X509_TRUST_new_null() SKM_sk_new_null(X509_TRUST)
+#define sk_X509_TRUST_free(st) SKM_sk_free(X509_TRUST, (st))
+#define sk_X509_TRUST_num(st) SKM_sk_num(X509_TRUST, (st))
+#define sk_X509_TRUST_value(st, i) SKM_sk_value(X509_TRUST, (st), (i))
+#define sk_X509_TRUST_set(st, i, val) SKM_sk_set(X509_TRUST, (st), (i), (val))
+#define sk_X509_TRUST_zero(st) SKM_sk_zero(X509_TRUST, (st))
+#define sk_X509_TRUST_push(st, val) SKM_sk_push(X509_TRUST, (st), (val))
+#define sk_X509_TRUST_unshift(st, val) SKM_sk_unshift(X509_TRUST, (st), (val))
+#define sk_X509_TRUST_find(st, val) SKM_sk_find(X509_TRUST, (st), (val))
+#define sk_X509_TRUST_find_ex(st, val) SKM_sk_find_ex(X509_TRUST, (st), (val))
+#define sk_X509_TRUST_delete(st, i) SKM_sk_delete(X509_TRUST, (st), (i))
+#define sk_X509_TRUST_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_TRUST, (st), (ptr))
+#define sk_X509_TRUST_insert(st, val, i) SKM_sk_insert(X509_TRUST, (st), (val), (i))
+#define sk_X509_TRUST_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_TRUST, (st), (cmp))
+#define sk_X509_TRUST_dup(st) SKM_sk_dup(X509_TRUST, st)
+#define sk_X509_TRUST_pop_free(st, free_func) SKM_sk_pop_free(X509_TRUST, (st), (free_func))
+#define sk_X509_TRUST_shift(st) SKM_sk_shift(X509_TRUST, (st))
+#define sk_X509_TRUST_pop(st) SKM_sk_pop(X509_TRUST, (st))
+#define sk_X509_TRUST_sort(st) SKM_sk_sort(X509_TRUST, (st))
+#define sk_X509_TRUST_is_sorted(st) SKM_sk_is_sorted(X509_TRUST, (st))
+
+#define sk_X509_VERIFY_PARAM_new(st) SKM_sk_new(X509_VERIFY_PARAM, (st))
+#define sk_X509_VERIFY_PARAM_new_null() SKM_sk_new_null(X509_VERIFY_PARAM)
+#define sk_X509_VERIFY_PARAM_free(st) SKM_sk_free(X509_VERIFY_PARAM, (st))
+#define sk_X509_VERIFY_PARAM_num(st) SKM_sk_num(X509_VERIFY_PARAM, (st))
+#define sk_X509_VERIFY_PARAM_value(st, i) SKM_sk_value(X509_VERIFY_PARAM, (st), (i))
+#define sk_X509_VERIFY_PARAM_set(st, i, val) SKM_sk_set(X509_VERIFY_PARAM, (st), (i), (val))
+#define sk_X509_VERIFY_PARAM_zero(st) SKM_sk_zero(X509_VERIFY_PARAM, (st))
+#define sk_X509_VERIFY_PARAM_push(st, val) SKM_sk_push(X509_VERIFY_PARAM, (st), (val))
+#define sk_X509_VERIFY_PARAM_unshift(st, val) SKM_sk_unshift(X509_VERIFY_PARAM, (st), (val))
+#define sk_X509_VERIFY_PARAM_find(st, val) SKM_sk_find(X509_VERIFY_PARAM, (st), (val))
+#define sk_X509_VERIFY_PARAM_find_ex(st, val) SKM_sk_find_ex(X509_VERIFY_PARAM, (st), (val))
+#define sk_X509_VERIFY_PARAM_delete(st, i) SKM_sk_delete(X509_VERIFY_PARAM, (st), (i))
+#define sk_X509_VERIFY_PARAM_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_VERIFY_PARAM, (st), (ptr))
+#define sk_X509_VERIFY_PARAM_insert(st, val, i) SKM_sk_insert(X509_VERIFY_PARAM, (st), (val), (i))
+#define sk_X509_VERIFY_PARAM_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_VERIFY_PARAM, (st), (cmp))
+#define sk_X509_VERIFY_PARAM_dup(st) SKM_sk_dup(X509_VERIFY_PARAM, st)
+#define sk_X509_VERIFY_PARAM_pop_free(st, free_func) SKM_sk_pop_free(X509_VERIFY_PARAM, (st), (free_func))
+#define sk_X509_VERIFY_PARAM_shift(st) SKM_sk_shift(X509_VERIFY_PARAM, (st))
+#define sk_X509_VERIFY_PARAM_pop(st) SKM_sk_pop(X509_VERIFY_PARAM, (st))
+#define sk_X509_VERIFY_PARAM_sort(st) SKM_sk_sort(X509_VERIFY_PARAM, (st))
+#define sk_X509_VERIFY_PARAM_is_sorted(st) SKM_sk_is_sorted(X509_VERIFY_PARAM, (st))
+
+#define d2i_ASN1_SET_OF_ACCESS_DESCRIPTION(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+	SKM_ASN1_SET_OF_d2i(ACCESS_DESCRIPTION, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) 
+#define i2d_ASN1_SET_OF_ACCESS_DESCRIPTION(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+	SKM_ASN1_SET_OF_i2d(ACCESS_DESCRIPTION, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_ACCESS_DESCRIPTION(st, i2d_func, buf, len) \
+	SKM_ASN1_seq_pack(ACCESS_DESCRIPTION, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_ACCESS_DESCRIPTION(buf, len, d2i_func, free_func) \
+	SKM_ASN1_seq_unpack(ACCESS_DESCRIPTION, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_ASN1_INTEGER(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+	SKM_ASN1_SET_OF_d2i(ASN1_INTEGER, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) 
+#define i2d_ASN1_SET_OF_ASN1_INTEGER(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+	SKM_ASN1_SET_OF_i2d(ASN1_INTEGER, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_ASN1_INTEGER(st, i2d_func, buf, len) \
+	SKM_ASN1_seq_pack(ASN1_INTEGER, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_ASN1_INTEGER(buf, len, d2i_func, free_func) \
+	SKM_ASN1_seq_unpack(ASN1_INTEGER, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_ASN1_OBJECT(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+	SKM_ASN1_SET_OF_d2i(ASN1_OBJECT, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) 
+#define i2d_ASN1_SET_OF_ASN1_OBJECT(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+	SKM_ASN1_SET_OF_i2d(ASN1_OBJECT, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_ASN1_OBJECT(st, i2d_func, buf, len) \
+	SKM_ASN1_seq_pack(ASN1_OBJECT, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_ASN1_OBJECT(buf, len, d2i_func, free_func) \
+	SKM_ASN1_seq_unpack(ASN1_OBJECT, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_ASN1_TYPE(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+	SKM_ASN1_SET_OF_d2i(ASN1_TYPE, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) 
+#define i2d_ASN1_SET_OF_ASN1_TYPE(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+	SKM_ASN1_SET_OF_i2d(ASN1_TYPE, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_ASN1_TYPE(st, i2d_func, buf, len) \
+	SKM_ASN1_seq_pack(ASN1_TYPE, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_ASN1_TYPE(buf, len, d2i_func, free_func) \
+	SKM_ASN1_seq_unpack(ASN1_TYPE, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_DIST_POINT(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+	SKM_ASN1_SET_OF_d2i(DIST_POINT, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) 
+#define i2d_ASN1_SET_OF_DIST_POINT(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+	SKM_ASN1_SET_OF_i2d(DIST_POINT, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_DIST_POINT(st, i2d_func, buf, len) \
+	SKM_ASN1_seq_pack(DIST_POINT, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_DIST_POINT(buf, len, d2i_func, free_func) \
+	SKM_ASN1_seq_unpack(DIST_POINT, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_GENERAL_NAME(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+	SKM_ASN1_SET_OF_d2i(GENERAL_NAME, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) 
+#define i2d_ASN1_SET_OF_GENERAL_NAME(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+	SKM_ASN1_SET_OF_i2d(GENERAL_NAME, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_GENERAL_NAME(st, i2d_func, buf, len) \
+	SKM_ASN1_seq_pack(GENERAL_NAME, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_GENERAL_NAME(buf, len, d2i_func, free_func) \
+	SKM_ASN1_seq_unpack(GENERAL_NAME, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_OCSP_ONEREQ(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+	SKM_ASN1_SET_OF_d2i(OCSP_ONEREQ, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) 
+#define i2d_ASN1_SET_OF_OCSP_ONEREQ(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+	SKM_ASN1_SET_OF_i2d(OCSP_ONEREQ, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_OCSP_ONEREQ(st, i2d_func, buf, len) \
+	SKM_ASN1_seq_pack(OCSP_ONEREQ, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_OCSP_ONEREQ(buf, len, d2i_func, free_func) \
+	SKM_ASN1_seq_unpack(OCSP_ONEREQ, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_OCSP_SINGLERESP(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+	SKM_ASN1_SET_OF_d2i(OCSP_SINGLERESP, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) 
+#define i2d_ASN1_SET_OF_OCSP_SINGLERESP(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+	SKM_ASN1_SET_OF_i2d(OCSP_SINGLERESP, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_OCSP_SINGLERESP(st, i2d_func, buf, len) \
+	SKM_ASN1_seq_pack(OCSP_SINGLERESP, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_OCSP_SINGLERESP(buf, len, d2i_func, free_func) \
+	SKM_ASN1_seq_unpack(OCSP_SINGLERESP, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_PKCS12_SAFEBAG(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+	SKM_ASN1_SET_OF_d2i(PKCS12_SAFEBAG, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) 
+#define i2d_ASN1_SET_OF_PKCS12_SAFEBAG(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+	SKM_ASN1_SET_OF_i2d(PKCS12_SAFEBAG, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_PKCS12_SAFEBAG(st, i2d_func, buf, len) \
+	SKM_ASN1_seq_pack(PKCS12_SAFEBAG, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_PKCS12_SAFEBAG(buf, len, d2i_func, free_func) \
+	SKM_ASN1_seq_unpack(PKCS12_SAFEBAG, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_PKCS7(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+	SKM_ASN1_SET_OF_d2i(PKCS7, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) 
+#define i2d_ASN1_SET_OF_PKCS7(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+	SKM_ASN1_SET_OF_i2d(PKCS7, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_PKCS7(st, i2d_func, buf, len) \
+	SKM_ASN1_seq_pack(PKCS7, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_PKCS7(buf, len, d2i_func, free_func) \
+	SKM_ASN1_seq_unpack(PKCS7, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_PKCS7_RECIP_INFO(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+	SKM_ASN1_SET_OF_d2i(PKCS7_RECIP_INFO, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) 
+#define i2d_ASN1_SET_OF_PKCS7_RECIP_INFO(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+	SKM_ASN1_SET_OF_i2d(PKCS7_RECIP_INFO, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_PKCS7_RECIP_INFO(st, i2d_func, buf, len) \
+	SKM_ASN1_seq_pack(PKCS7_RECIP_INFO, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_PKCS7_RECIP_INFO(buf, len, d2i_func, free_func) \
+	SKM_ASN1_seq_unpack(PKCS7_RECIP_INFO, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_PKCS7_SIGNER_INFO(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+	SKM_ASN1_SET_OF_d2i(PKCS7_SIGNER_INFO, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) 
+#define i2d_ASN1_SET_OF_PKCS7_SIGNER_INFO(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+	SKM_ASN1_SET_OF_i2d(PKCS7_SIGNER_INFO, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_PKCS7_SIGNER_INFO(st, i2d_func, buf, len) \
+	SKM_ASN1_seq_pack(PKCS7_SIGNER_INFO, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_PKCS7_SIGNER_INFO(buf, len, d2i_func, free_func) \
+	SKM_ASN1_seq_unpack(PKCS7_SIGNER_INFO, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_POLICYINFO(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+	SKM_ASN1_SET_OF_d2i(POLICYINFO, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) 
+#define i2d_ASN1_SET_OF_POLICYINFO(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+	SKM_ASN1_SET_OF_i2d(POLICYINFO, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_POLICYINFO(st, i2d_func, buf, len) \
+	SKM_ASN1_seq_pack(POLICYINFO, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_POLICYINFO(buf, len, d2i_func, free_func) \
+	SKM_ASN1_seq_unpack(POLICYINFO, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_POLICYQUALINFO(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+	SKM_ASN1_SET_OF_d2i(POLICYQUALINFO, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) 
+#define i2d_ASN1_SET_OF_POLICYQUALINFO(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+	SKM_ASN1_SET_OF_i2d(POLICYQUALINFO, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_POLICYQUALINFO(st, i2d_func, buf, len) \
+	SKM_ASN1_seq_pack(POLICYQUALINFO, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_POLICYQUALINFO(buf, len, d2i_func, free_func) \
+	SKM_ASN1_seq_unpack(POLICYQUALINFO, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_SXNETID(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+	SKM_ASN1_SET_OF_d2i(SXNETID, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) 
+#define i2d_ASN1_SET_OF_SXNETID(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+	SKM_ASN1_SET_OF_i2d(SXNETID, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_SXNETID(st, i2d_func, buf, len) \
+	SKM_ASN1_seq_pack(SXNETID, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_SXNETID(buf, len, d2i_func, free_func) \
+	SKM_ASN1_seq_unpack(SXNETID, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_X509(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+	SKM_ASN1_SET_OF_d2i(X509, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) 
+#define i2d_ASN1_SET_OF_X509(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+	SKM_ASN1_SET_OF_i2d(X509, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_X509(st, i2d_func, buf, len) \
+	SKM_ASN1_seq_pack(X509, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_X509(buf, len, d2i_func, free_func) \
+	SKM_ASN1_seq_unpack(X509, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_X509_ALGOR(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+	SKM_ASN1_SET_OF_d2i(X509_ALGOR, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) 
+#define i2d_ASN1_SET_OF_X509_ALGOR(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+	SKM_ASN1_SET_OF_i2d(X509_ALGOR, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_X509_ALGOR(st, i2d_func, buf, len) \
+	SKM_ASN1_seq_pack(X509_ALGOR, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_X509_ALGOR(buf, len, d2i_func, free_func) \
+	SKM_ASN1_seq_unpack(X509_ALGOR, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_X509_ATTRIBUTE(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+	SKM_ASN1_SET_OF_d2i(X509_ATTRIBUTE, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) 
+#define i2d_ASN1_SET_OF_X509_ATTRIBUTE(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+	SKM_ASN1_SET_OF_i2d(X509_ATTRIBUTE, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_X509_ATTRIBUTE(st, i2d_func, buf, len) \
+	SKM_ASN1_seq_pack(X509_ATTRIBUTE, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_X509_ATTRIBUTE(buf, len, d2i_func, free_func) \
+	SKM_ASN1_seq_unpack(X509_ATTRIBUTE, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_X509_CRL(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+	SKM_ASN1_SET_OF_d2i(X509_CRL, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) 
+#define i2d_ASN1_SET_OF_X509_CRL(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+	SKM_ASN1_SET_OF_i2d(X509_CRL, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_X509_CRL(st, i2d_func, buf, len) \
+	SKM_ASN1_seq_pack(X509_CRL, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_X509_CRL(buf, len, d2i_func, free_func) \
+	SKM_ASN1_seq_unpack(X509_CRL, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_X509_EXTENSION(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+	SKM_ASN1_SET_OF_d2i(X509_EXTENSION, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) 
+#define i2d_ASN1_SET_OF_X509_EXTENSION(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+	SKM_ASN1_SET_OF_i2d(X509_EXTENSION, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_X509_EXTENSION(st, i2d_func, buf, len) \
+	SKM_ASN1_seq_pack(X509_EXTENSION, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_X509_EXTENSION(buf, len, d2i_func, free_func) \
+	SKM_ASN1_seq_unpack(X509_EXTENSION, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_X509_NAME_ENTRY(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+	SKM_ASN1_SET_OF_d2i(X509_NAME_ENTRY, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) 
+#define i2d_ASN1_SET_OF_X509_NAME_ENTRY(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+	SKM_ASN1_SET_OF_i2d(X509_NAME_ENTRY, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_X509_NAME_ENTRY(st, i2d_func, buf, len) \
+	SKM_ASN1_seq_pack(X509_NAME_ENTRY, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_X509_NAME_ENTRY(buf, len, d2i_func, free_func) \
+	SKM_ASN1_seq_unpack(X509_NAME_ENTRY, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_X509_REVOKED(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+	SKM_ASN1_SET_OF_d2i(X509_REVOKED, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) 
+#define i2d_ASN1_SET_OF_X509_REVOKED(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+	SKM_ASN1_SET_OF_i2d(X509_REVOKED, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_X509_REVOKED(st, i2d_func, buf, len) \
+	SKM_ASN1_seq_pack(X509_REVOKED, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_X509_REVOKED(buf, len, d2i_func, free_func) \
+	SKM_ASN1_seq_unpack(X509_REVOKED, (buf), (len), (d2i_func), (free_func))
+
+#define PKCS12_decrypt_d2i_PKCS12_SAFEBAG(algor, d2i_func, free_func, pass, passlen, oct, seq) \
+	SKM_PKCS12_decrypt_d2i(PKCS12_SAFEBAG, (algor), (d2i_func), (free_func), (pass), (passlen), (oct), (seq))
+
+#define PKCS12_decrypt_d2i_PKCS7(algor, d2i_func, free_func, pass, passlen, oct, seq) \
+	SKM_PKCS12_decrypt_d2i(PKCS7, (algor), (d2i_func), (free_func), (pass), (passlen), (oct), (seq))
+/* End of util/mkstack.pl block, you may now edit :-) */
+
+#endif /* !defined HEADER_SAFESTACK_H */
diff --git a/dep/include/openssl/sha.h b/dep/include/openssl/sha.h
new file mode 100644
index 00000000000..eed44d7f946
--- /dev/null
+++ b/dep/include/openssl/sha.h
@@ -0,0 +1,200 @@
+/* crypto/sha/sha.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_SHA_H
+#define HEADER_SHA_H
+
+#include 
+#include 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#if defined(OPENSSL_NO_SHA) || (defined(OPENSSL_NO_SHA0) && defined(OPENSSL_NO_SHA1))
+#error SHA is disabled.
+#endif
+
+#if defined(OPENSSL_FIPS)
+#define FIPS_SHA_SIZE_T size_t
+#endif
+
+/*
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * ! SHA_LONG has to be at least 32 bits wide. If it's wider, then !
+ * ! SHA_LONG_LOG2 has to be defined along.                        !
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ */
+
+#if defined(OPENSSL_SYS_WIN16) || defined(__LP32__)
+#define SHA_LONG unsigned long
+#elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__)
+#define SHA_LONG unsigned long
+#define SHA_LONG_LOG2 3
+#else
+#define SHA_LONG unsigned int
+#endif
+
+#define SHA_LBLOCK	16
+#define SHA_CBLOCK	(SHA_LBLOCK*4)	/* SHA treats input data as a
+					 * contiguous array of 32 bit
+					 * wide big-endian values. */
+#define SHA_LAST_BLOCK  (SHA_CBLOCK-8)
+#define SHA_DIGEST_LENGTH 20
+
+typedef struct SHAstate_st
+	{
+	SHA_LONG h0,h1,h2,h3,h4;
+	SHA_LONG Nl,Nh;
+	SHA_LONG data[SHA_LBLOCK];
+	unsigned int num;
+	} SHA_CTX;
+
+#ifndef OPENSSL_NO_SHA0
+int SHA_Init(SHA_CTX *c);
+int SHA_Update(SHA_CTX *c, const void *data, size_t len);
+int SHA_Final(unsigned char *md, SHA_CTX *c);
+unsigned char *SHA(const unsigned char *d, size_t n, unsigned char *md);
+void SHA_Transform(SHA_CTX *c, const unsigned char *data);
+#endif
+#ifndef OPENSSL_NO_SHA1
+int SHA1_Init(SHA_CTX *c);
+int SHA1_Update(SHA_CTX *c, const void *data, size_t len);
+int SHA1_Final(unsigned char *md, SHA_CTX *c);
+unsigned char *SHA1(const unsigned char *d, size_t n, unsigned char *md);
+void SHA1_Transform(SHA_CTX *c, const unsigned char *data);
+#endif
+
+#define SHA256_CBLOCK	(SHA_LBLOCK*4)	/* SHA-256 treats input data as a
+					 * contiguous array of 32 bit
+					 * wide big-endian values. */
+#define SHA224_DIGEST_LENGTH	28
+#define SHA256_DIGEST_LENGTH	32
+
+typedef struct SHA256state_st
+	{
+	SHA_LONG h[8];
+	SHA_LONG Nl,Nh;
+	SHA_LONG data[SHA_LBLOCK];
+	unsigned int num,md_len;
+	} SHA256_CTX;
+
+#ifndef OPENSSL_NO_SHA256
+int SHA224_Init(SHA256_CTX *c);
+int SHA224_Update(SHA256_CTX *c, const void *data, size_t len);
+int SHA224_Final(unsigned char *md, SHA256_CTX *c);
+unsigned char *SHA224(const unsigned char *d, size_t n,unsigned char *md);
+int SHA256_Init(SHA256_CTX *c);
+int SHA256_Update(SHA256_CTX *c, const void *data, size_t len);
+int SHA256_Final(unsigned char *md, SHA256_CTX *c);
+unsigned char *SHA256(const unsigned char *d, size_t n,unsigned char *md);
+void SHA256_Transform(SHA256_CTX *c, const unsigned char *data);
+#endif
+
+#define SHA384_DIGEST_LENGTH	48
+#define SHA512_DIGEST_LENGTH	64
+
+#ifndef OPENSSL_NO_SHA512
+/*
+ * Unlike 32-bit digest algorithms, SHA-512 *relies* on SHA_LONG64
+ * being exactly 64-bit wide. See Implementation Notes in sha512.c
+ * for further details.
+ */
+#define SHA512_CBLOCK	(SHA_LBLOCK*8)	/* SHA-512 treats input data as a
+					 * contiguous array of 64 bit
+					 * wide big-endian values. */
+#if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__)
+#define SHA_LONG64 unsigned __int64
+#define U64(C)     C##UI64
+#elif defined(__arch64__)
+#define SHA_LONG64 unsigned long
+#define U64(C)     C##UL
+#else
+#define SHA_LONG64 unsigned long long
+#define U64(C)     C##ULL
+#endif
+
+typedef struct SHA512state_st
+	{
+	SHA_LONG64 h[8];
+	SHA_LONG64 Nl,Nh;
+	union {
+		SHA_LONG64	d[SHA_LBLOCK];
+		unsigned char	p[SHA512_CBLOCK];
+	} u;
+	unsigned int num,md_len;
+	} SHA512_CTX;
+#endif
+
+#ifndef OPENSSL_NO_SHA512
+int SHA384_Init(SHA512_CTX *c);
+int SHA384_Update(SHA512_CTX *c, const void *data, size_t len);
+int SHA384_Final(unsigned char *md, SHA512_CTX *c);
+unsigned char *SHA384(const unsigned char *d, size_t n,unsigned char *md);
+int SHA512_Init(SHA512_CTX *c);
+int SHA512_Update(SHA512_CTX *c, const void *data, size_t len);
+int SHA512_Final(unsigned char *md, SHA512_CTX *c);
+unsigned char *SHA512(const unsigned char *d, size_t n,unsigned char *md);
+void SHA512_Transform(SHA512_CTX *c, const unsigned char *data);
+#endif
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff --git a/dep/include/openssl/ssl.h b/dep/include/openssl/ssl.h
new file mode 100644
index 00000000000..2e067e7a78e
--- /dev/null
+++ b/dep/include/openssl/ssl.h
@@ -0,0 +1,1960 @@
+/* ssl/ssl.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECC cipher suite support in OpenSSL originally developed by 
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#ifndef HEADER_SSL_H 
+#define HEADER_SSL_H 
+
+#include 
+
+#ifndef OPENSSL_NO_COMP
+#include 
+#endif
+#ifndef OPENSSL_NO_BIO
+#include 
+#endif
+#ifndef OPENSSL_NO_DEPRECATED
+#ifndef OPENSSL_NO_X509
+#include 
+#endif
+#include 
+#include 
+#include 
+#endif
+#include 
+
+#include 
+#include 
+#include 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* SSLeay version number for ASN.1 encoding of the session information */
+/* Version 0 - initial version
+ * Version 1 - added the optional peer certificate
+ */
+#define SSL_SESSION_ASN1_VERSION 0x0001
+
+/* text strings for the ciphers */
+#define SSL_TXT_NULL_WITH_MD5		SSL2_TXT_NULL_WITH_MD5			
+#define SSL_TXT_RC4_128_WITH_MD5	SSL2_TXT_RC4_128_WITH_MD5		
+#define SSL_TXT_RC4_128_EXPORT40_WITH_MD5 SSL2_TXT_RC4_128_EXPORT40_WITH_MD5	
+#define SSL_TXT_RC2_128_CBC_WITH_MD5	SSL2_TXT_RC2_128_CBC_WITH_MD5		
+#define SSL_TXT_RC2_128_CBC_EXPORT40_WITH_MD5 SSL2_TXT_RC2_128_CBC_EXPORT40_WITH_MD5	
+#define SSL_TXT_IDEA_128_CBC_WITH_MD5	SSL2_TXT_IDEA_128_CBC_WITH_MD5		
+#define SSL_TXT_DES_64_CBC_WITH_MD5	SSL2_TXT_DES_64_CBC_WITH_MD5		
+#define SSL_TXT_DES_64_CBC_WITH_SHA	SSL2_TXT_DES_64_CBC_WITH_SHA		
+#define SSL_TXT_DES_192_EDE3_CBC_WITH_MD5 SSL2_TXT_DES_192_EDE3_CBC_WITH_MD5	
+#define SSL_TXT_DES_192_EDE3_CBC_WITH_SHA SSL2_TXT_DES_192_EDE3_CBC_WITH_SHA	
+
+/*    VRS Additional Kerberos5 entries
+ */
+#define SSL_TXT_KRB5_DES_64_CBC_SHA   SSL3_TXT_KRB5_DES_64_CBC_SHA
+#define SSL_TXT_KRB5_DES_192_CBC3_SHA SSL3_TXT_KRB5_DES_192_CBC3_SHA
+#define SSL_TXT_KRB5_RC4_128_SHA      SSL3_TXT_KRB5_RC4_128_SHA
+#define SSL_TXT_KRB5_IDEA_128_CBC_SHA SSL3_TXT_KRB5_IDEA_128_CBC_SHA
+#define SSL_TXT_KRB5_DES_64_CBC_MD5   SSL3_TXT_KRB5_DES_64_CBC_MD5       
+#define SSL_TXT_KRB5_DES_192_CBC3_MD5 SSL3_TXT_KRB5_DES_192_CBC3_MD5       
+#define SSL_TXT_KRB5_RC4_128_MD5      SSL3_TXT_KRB5_RC4_128_MD5
+#define SSL_TXT_KRB5_IDEA_128_CBC_MD5 SSL3_TXT_KRB5_IDEA_128_CBC_MD5 
+
+#define SSL_TXT_KRB5_DES_40_CBC_SHA   SSL3_TXT_KRB5_DES_40_CBC_SHA 
+#define SSL_TXT_KRB5_RC2_40_CBC_SHA   SSL3_TXT_KRB5_RC2_40_CBC_SHA 
+#define SSL_TXT_KRB5_RC4_40_SHA	      SSL3_TXT_KRB5_RC4_40_SHA
+#define SSL_TXT_KRB5_DES_40_CBC_MD5   SSL3_TXT_KRB5_DES_40_CBC_MD5 
+#define SSL_TXT_KRB5_RC2_40_CBC_MD5   SSL3_TXT_KRB5_RC2_40_CBC_MD5 
+#define SSL_TXT_KRB5_RC4_40_MD5	      SSL3_TXT_KRB5_RC4_40_MD5
+
+#define SSL_TXT_KRB5_DES_40_CBC_SHA   SSL3_TXT_KRB5_DES_40_CBC_SHA
+#define SSL_TXT_KRB5_DES_40_CBC_MD5   SSL3_TXT_KRB5_DES_40_CBC_MD5
+#define SSL_TXT_KRB5_DES_64_CBC_SHA   SSL3_TXT_KRB5_DES_64_CBC_SHA
+#define SSL_TXT_KRB5_DES_64_CBC_MD5   SSL3_TXT_KRB5_DES_64_CBC_MD5
+#define SSL_TXT_KRB5_DES_192_CBC3_SHA SSL3_TXT_KRB5_DES_192_CBC3_SHA
+#define SSL_TXT_KRB5_DES_192_CBC3_MD5 SSL3_TXT_KRB5_DES_192_CBC3_MD5
+#define SSL_MAX_KRB5_PRINCIPAL_LENGTH  256
+
+#define SSL_MAX_SSL_SESSION_ID_LENGTH		32
+#define SSL_MAX_SID_CTX_LENGTH			32
+
+#define SSL_MIN_RSA_MODULUS_LENGTH_IN_BYTES	(512/8)
+#define SSL_MAX_KEY_ARG_LENGTH			8
+#define SSL_MAX_MASTER_KEY_LENGTH		48
+
+/* These are used to specify which ciphers to use and not to use */
+#define SSL_TXT_LOW		"LOW"
+#define SSL_TXT_MEDIUM		"MEDIUM"
+#define SSL_TXT_HIGH		"HIGH"
+#define SSL_TXT_kFZA		"kFZA"
+#define	SSL_TXT_aFZA		"aFZA"
+#define SSL_TXT_eFZA		"eFZA"
+#define SSL_TXT_FZA		"FZA"
+
+#define	SSL_TXT_aNULL		"aNULL"
+#define	SSL_TXT_eNULL		"eNULL"
+#define	SSL_TXT_NULL		"NULL"
+
+#define SSL_TXT_kKRB5     	"kKRB5"
+#define SSL_TXT_aKRB5     	"aKRB5"
+#define SSL_TXT_KRB5      	"KRB5"
+
+#define SSL_TXT_kRSA		"kRSA"
+#define SSL_TXT_kDHr		"kDHr"
+#define SSL_TXT_kDHd		"kDHd"
+#define SSL_TXT_kEDH		"kEDH"
+#define	SSL_TXT_aRSA		"aRSA"
+#define	SSL_TXT_aDSS		"aDSS"
+#define	SSL_TXT_aDH		"aDH"
+#define	SSL_TXT_DSS		"DSS"
+#define SSL_TXT_DH		"DH"
+#define SSL_TXT_EDH		"EDH"
+#define SSL_TXT_ADH		"ADH"
+#define SSL_TXT_RSA		"RSA"
+#define SSL_TXT_DES		"DES"
+#define SSL_TXT_3DES		"3DES"
+#define SSL_TXT_RC4		"RC4"
+#define SSL_TXT_RC2		"RC2"
+#define SSL_TXT_IDEA		"IDEA"
+#define SSL_TXT_AES		"AES"
+#define SSL_TXT_CAMELLIA	"CAMELLIA"
+#define SSL_TXT_MD5		"MD5"
+#define SSL_TXT_SHA1		"SHA1"
+#define SSL_TXT_SHA		"SHA"
+#define SSL_TXT_EXP		"EXP"
+#define SSL_TXT_EXPORT		"EXPORT"
+#define SSL_TXT_EXP40		"EXPORT40"
+#define SSL_TXT_EXP56		"EXPORT56"
+#define SSL_TXT_SSLV2		"SSLv2"
+#define SSL_TXT_SSLV3		"SSLv3"
+#define SSL_TXT_TLSV1		"TLSv1"
+#define SSL_TXT_ALL		"ALL"
+#define SSL_TXT_ECC		"ECCdraft" /* ECC ciphersuites are not yet official */
+
+/*
+ * COMPLEMENTOF* definitions. These identifiers are used to (de-select)
+ * ciphers normally not being used.
+ * Example: "RC4" will activate all ciphers using RC4 including ciphers
+ * without authentication, which would normally disabled by DEFAULT (due
+ * the "!ADH" being part of default). Therefore "RC4:!COMPLEMENTOFDEFAULT"
+ * will make sure that it is also disabled in the specific selection.
+ * COMPLEMENTOF* identifiers are portable between version, as adjustments
+ * to the default cipher setup will also be included here.
+ *
+ * COMPLEMENTOFDEFAULT does not experience the same special treatment that
+ * DEFAULT gets, as only selection is being done and no sorting as needed
+ * for DEFAULT.
+ */
+#define SSL_TXT_CMPALL		"COMPLEMENTOFALL"
+#define SSL_TXT_CMPDEF		"COMPLEMENTOFDEFAULT"
+
+/* The following cipher list is used by default.
+ * It also is substituted when an application-defined cipher list string
+ * starts with 'DEFAULT'. */
+#ifdef OPENSSL_NO_CAMELLIA
+# define SSL_DEFAULT_CIPHER_LIST	"ALL:!ADH:+RC4:@STRENGTH" /* low priority for RC4 */
+#else
+# define SSL_DEFAULT_CIPHER_LIST	"AES:CAMELLIA:ALL:!ADH:+RC4:@STRENGTH" /* low priority for RC4 */
+#endif
+
+/* Used in SSL_set_shutdown()/SSL_get_shutdown(); */
+#define SSL_SENT_SHUTDOWN	1
+#define SSL_RECEIVED_SHUTDOWN	2
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#if (defined(OPENSSL_NO_RSA) || defined(OPENSSL_NO_MD5)) && !defined(OPENSSL_NO_SSL2)
+#define OPENSSL_NO_SSL2
+#endif
+
+#define SSL_FILETYPE_ASN1	X509_FILETYPE_ASN1
+#define SSL_FILETYPE_PEM	X509_FILETYPE_PEM
+
+/* This is needed to stop compilers complaining about the
+ * 'struct ssl_st *' function parameters used to prototype callbacks
+ * in SSL_CTX. */
+typedef struct ssl_st *ssl_crock_st;
+
+/* used to hold info on the particular ciphers used */
+typedef struct ssl_cipher_st
+	{
+	int valid;
+	const char *name;		/* text name */
+	unsigned long id;		/* id, 4 bytes, first is version */
+	unsigned long algorithms;	/* what ciphers are used */
+	unsigned long algo_strength;	/* strength and export flags */
+	unsigned long algorithm2;	/* Extra flags */
+	int strength_bits;		/* Number of bits really used */
+	int alg_bits;			/* Number of bits for algorithm */
+	unsigned long mask;		/* used for matching */
+	unsigned long mask_strength;	/* also used for matching */
+	} SSL_CIPHER;
+
+DECLARE_STACK_OF(SSL_CIPHER)
+
+typedef struct ssl_st SSL;
+typedef struct ssl_ctx_st SSL_CTX;
+
+/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
+typedef struct ssl_method_st
+	{
+	int version;
+	int (*ssl_new)(SSL *s);
+	void (*ssl_clear)(SSL *s);
+	void (*ssl_free)(SSL *s);
+	int (*ssl_accept)(SSL *s);
+	int (*ssl_connect)(SSL *s);
+	int (*ssl_read)(SSL *s,void *buf,int len);
+	int (*ssl_peek)(SSL *s,void *buf,int len);
+	int (*ssl_write)(SSL *s,const void *buf,int len);
+	int (*ssl_shutdown)(SSL *s);
+	int (*ssl_renegotiate)(SSL *s);
+	int (*ssl_renegotiate_check)(SSL *s);
+	long (*ssl_get_message)(SSL *s, int st1, int stn, int mt, long
+		max, int *ok);
+	int (*ssl_read_bytes)(SSL *s, int type, unsigned char *buf, int len, 
+		int peek);
+	int (*ssl_write_bytes)(SSL *s, int type, const void *buf_, int len);
+	int (*ssl_dispatch_alert)(SSL *s);
+	long (*ssl_ctrl)(SSL *s,int cmd,long larg,void *parg);
+	long (*ssl_ctx_ctrl)(SSL_CTX *ctx,int cmd,long larg,void *parg);
+	SSL_CIPHER *(*get_cipher_by_char)(const unsigned char *ptr);
+	int (*put_cipher_by_char)(const SSL_CIPHER *cipher,unsigned char *ptr);
+	int (*ssl_pending)(const SSL *s);
+	int (*num_ciphers)(void);
+	SSL_CIPHER *(*get_cipher)(unsigned ncipher);
+	struct ssl_method_st *(*get_ssl_method)(int version);
+	long (*get_timeout)(void);
+	struct ssl3_enc_method *ssl3_enc; /* Extra SSLv3/TLS stuff */
+	int (*ssl_version)(void);
+	long (*ssl_callback_ctrl)(SSL *s, int cb_id, void (*fp)(void));
+	long (*ssl_ctx_callback_ctrl)(SSL_CTX *s, int cb_id, void (*fp)(void));
+	} SSL_METHOD;
+
+/* Lets make this into an ASN.1 type structure as follows
+ * SSL_SESSION_ID ::= SEQUENCE {
+ *	version 		INTEGER,	-- structure version number
+ *	SSLversion 		INTEGER,	-- SSL version number
+ *	Cipher 			OCTET_STRING,	-- the 3 byte cipher ID
+ *	Session_ID 		OCTET_STRING,	-- the Session ID
+ *	Master_key 		OCTET_STRING,	-- the master key
+ *	KRB5_principal		OCTET_STRING	-- optional Kerberos principal
+ *	Key_Arg [ 0 ] IMPLICIT	OCTET_STRING,	-- the optional Key argument
+ *	Time [ 1 ] EXPLICIT	INTEGER,	-- optional Start Time
+ *	Timeout [ 2 ] EXPLICIT	INTEGER,	-- optional Timeout ins seconds
+ *	Peer [ 3 ] EXPLICIT	X509,		-- optional Peer Certificate
+ *	Session_ID_context [ 4 ] EXPLICIT OCTET_STRING,   -- the Session ID context
+ *	Verify_result [ 5 ] EXPLICIT INTEGER    -- X509_V_... code for `Peer'
+ *	Compression [6] IMPLICIT ASN1_OBJECT	-- compression OID XXXXX
+ *	}
+ * Look in ssl/ssl_asn1.c for more details
+ * I'm using EXPLICIT tags so I can read the damn things using asn1parse :-).
+ */
+typedef struct ssl_session_st
+	{
+	int ssl_version;	/* what ssl version session info is
+				 * being kept in here? */
+
+	/* only really used in SSLv2 */
+	unsigned int key_arg_length;
+	unsigned char key_arg[SSL_MAX_KEY_ARG_LENGTH];
+	int master_key_length;
+	unsigned char master_key[SSL_MAX_MASTER_KEY_LENGTH];
+	/* session_id - valid? */
+	unsigned int session_id_length;
+	unsigned char session_id[SSL_MAX_SSL_SESSION_ID_LENGTH];
+	/* this is used to determine whether the session is being reused in
+	 * the appropriate context. It is up to the application to set this,
+	 * via SSL_new */
+	unsigned int sid_ctx_length;
+	unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH];
+
+#ifndef OPENSSL_NO_KRB5
+        unsigned int krb5_client_princ_len;
+        unsigned char krb5_client_princ[SSL_MAX_KRB5_PRINCIPAL_LENGTH];
+#endif /* OPENSSL_NO_KRB5 */
+
+	int not_resumable;
+
+	/* The cert is the certificate used to establish this connection */
+	struct sess_cert_st /* SESS_CERT */ *sess_cert;
+
+	/* This is the cert for the other end.
+	 * On clients, it will be the same as sess_cert->peer_key->x509
+	 * (the latter is not enough as sess_cert is not retained
+	 * in the external representation of sessions, see ssl_asn1.c). */
+	X509 *peer;
+	/* when app_verify_callback accepts a session where the peer's certificate
+	 * is not ok, we must remember the error for session reuse: */
+	long verify_result; /* only for servers */
+
+	int references;
+	long timeout;
+	long time;
+
+	int compress_meth;		/* Need to lookup the method */
+
+	SSL_CIPHER *cipher;
+	unsigned long cipher_id;	/* when ASN.1 loaded, this
+					 * needs to be used to load
+					 * the 'cipher' structure */
+
+	STACK_OF(SSL_CIPHER) *ciphers; /* shared ciphers? */
+
+	CRYPTO_EX_DATA ex_data; /* application specific data */
+
+	/* These are used to make removal of session-ids more
+	 * efficient and to implement a maximum cache size. */
+	struct ssl_session_st *prev,*next;
+	} SSL_SESSION;
+
+
+#define SSL_OP_MICROSOFT_SESS_ID_BUG			0x00000001L
+#define SSL_OP_NETSCAPE_CHALLENGE_BUG			0x00000002L
+#define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG		0x00000008L
+#define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG		0x00000010L
+#define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER		0x00000020L
+#define SSL_OP_MSIE_SSLV2_RSA_PADDING			0x00000040L /* no effect since 0.9.7h and 0.9.8b */
+#define SSL_OP_SSLEAY_080_CLIENT_DH_BUG			0x00000080L
+#define SSL_OP_TLS_D5_BUG				0x00000100L
+#define SSL_OP_TLS_BLOCK_PADDING_BUG			0x00000200L
+
+/* Disable SSL 3.0/TLS 1.0 CBC vulnerability workaround that was added
+ * in OpenSSL 0.9.6d.  Usually (depending on the application protocol)
+ * the workaround is not needed.  Unfortunately some broken SSL/TLS
+ * implementations cannot handle it at all, which is why we include
+ * it in SSL_OP_ALL. */
+#define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS              0x00000800L /* added in 0.9.6e */
+
+/* SSL_OP_ALL: various bug workarounds that should be rather harmless.
+ *             This used to be 0x000FFFFFL before 0.9.7. */
+#define SSL_OP_ALL					0x00000FFFL
+
+/* DTLS options */
+#define SSL_OP_NO_QUERY_MTU                 0x00001000L
+/* Turn on Cookie Exchange (on relevant for servers) */
+#define SSL_OP_COOKIE_EXCHANGE              0x00002000L
+
+/* As server, disallow session resumption on renegotiation */
+#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION	0x00010000L
+/* If set, always create a new key when using tmp_ecdh parameters */
+#define SSL_OP_SINGLE_ECDH_USE				0x00080000L
+/* If set, always create a new key when using tmp_dh parameters */
+#define SSL_OP_SINGLE_DH_USE				0x00100000L
+/* Set to always use the tmp_rsa key when doing RSA operations,
+ * even when this violates protocol specs */
+#define SSL_OP_EPHEMERAL_RSA				0x00200000L
+/* Set on servers to choose the cipher according to the server's
+ * preferences */
+#define SSL_OP_CIPHER_SERVER_PREFERENCE			0x00400000L
+/* If set, a server will allow a client to issue a SSLv3.0 version number
+ * as latest version supported in the premaster secret, even when TLSv1.0
+ * (version 3.1) was announced in the client hello. Normally this is
+ * forbidden to prevent version rollback attacks. */
+#define SSL_OP_TLS_ROLLBACK_BUG				0x00800000L
+
+#define SSL_OP_NO_SSLv2					0x01000000L
+#define SSL_OP_NO_SSLv3					0x02000000L
+#define SSL_OP_NO_TLSv1					0x04000000L
+
+/* The next flag deliberately changes the ciphertest, this is a check
+ * for the PKCS#1 attack */
+#define SSL_OP_PKCS1_CHECK_1				0x08000000L
+#define SSL_OP_PKCS1_CHECK_2				0x10000000L
+#define SSL_OP_NETSCAPE_CA_DN_BUG			0x20000000L
+#define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG		0x40000000L
+
+
+/* Allow SSL_write(..., n) to return r with 0 < r < n (i.e. report success
+ * when just a single record has been written): */
+#define SSL_MODE_ENABLE_PARTIAL_WRITE       0x00000001L
+/* Make it possible to retry SSL_write() with changed buffer location
+ * (buffer contents must stay the same!); this is not the default to avoid
+ * the misconception that non-blocking SSL_write() behaves like
+ * non-blocking write(): */
+#define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER 0x00000002L
+/* Never bother the application with retries if the transport
+ * is blocking: */
+#define SSL_MODE_AUTO_RETRY 0x00000004L
+/* Don't attempt to automatically build certificate chain */
+#define SSL_MODE_NO_AUTO_CHAIN 0x00000008L
+
+
+/* Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value,
+ * they cannot be used to clear bits. */
+
+#define SSL_CTX_set_options(ctx,op) \
+	SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,(op),NULL)
+#define SSL_CTX_get_options(ctx) \
+	SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,0,NULL)
+#define SSL_set_options(ssl,op) \
+	SSL_ctrl((ssl),SSL_CTRL_OPTIONS,(op),NULL)
+#define SSL_get_options(ssl) \
+        SSL_ctrl((ssl),SSL_CTRL_OPTIONS,0,NULL)
+
+#define SSL_CTX_set_mode(ctx,op) \
+	SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,(op),NULL)
+#define SSL_CTX_get_mode(ctx) \
+	SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,0,NULL)
+#define SSL_set_mode(ssl,op) \
+	SSL_ctrl((ssl),SSL_CTRL_MODE,(op),NULL)
+#define SSL_get_mode(ssl) \
+        SSL_ctrl((ssl),SSL_CTRL_MODE,0,NULL)
+#define SSL_set_mtu(ssl, mtu) \
+        SSL_ctrl((ssl),SSL_CTRL_SET_MTU,(mtu),NULL)
+
+
+void SSL_CTX_set_msg_callback(SSL_CTX *ctx, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg));
+void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg));
+#define SSL_CTX_set_msg_callback_arg(ctx, arg) SSL_CTX_ctrl((ctx), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))
+#define SSL_set_msg_callback_arg(ssl, arg) SSL_ctrl((ssl), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))
+
+
+
+#if defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN32)
+#define SSL_MAX_CERT_LIST_DEFAULT 1024*30 /* 30k max cert list :-) */
+#else
+#define SSL_MAX_CERT_LIST_DEFAULT 1024*100 /* 100k max cert list :-) */
+#endif
+
+#define SSL_SESSION_CACHE_MAX_SIZE_DEFAULT	(1024*20)
+
+/* This callback type is used inside SSL_CTX, SSL, and in the functions that set
+ * them. It is used to override the generation of SSL/TLS session IDs in a
+ * server. Return value should be zero on an error, non-zero to proceed. Also,
+ * callbacks should themselves check if the id they generate is unique otherwise
+ * the SSL handshake will fail with an error - callbacks can do this using the
+ * 'ssl' value they're passed by;
+ *      SSL_has_matching_session_id(ssl, id, *id_len)
+ * The length value passed in is set at the maximum size the session ID can be.
+ * In SSLv2 this is 16 bytes, whereas SSLv3/TLSv1 it is 32 bytes. The callback
+ * can alter this length to be less if desired, but under SSLv2 session IDs are
+ * supposed to be fixed at 16 bytes so the id will be padded after the callback
+ * returns in this case. It is also an error for the callback to set the size to
+ * zero. */
+typedef int (*GEN_SESSION_CB)(const SSL *ssl, unsigned char *id,
+				unsigned int *id_len);
+
+typedef struct ssl_comp_st
+	{
+	int id;
+	const char *name;
+#ifndef OPENSSL_NO_COMP
+	COMP_METHOD *method;
+#else
+	char *method;
+#endif
+	} SSL_COMP;
+
+DECLARE_STACK_OF(SSL_COMP)
+
+struct ssl_ctx_st
+	{
+	SSL_METHOD *method;
+
+	STACK_OF(SSL_CIPHER) *cipher_list;
+	/* same as above but sorted for lookup */
+	STACK_OF(SSL_CIPHER) *cipher_list_by_id;
+
+	struct x509_store_st /* X509_STORE */ *cert_store;
+	struct lhash_st /* LHASH */ *sessions;	/* a set of SSL_SESSIONs */
+	/* Most session-ids that will be cached, default is
+	 * SSL_SESSION_CACHE_MAX_SIZE_DEFAULT. 0 is unlimited. */
+	unsigned long session_cache_size;
+	struct ssl_session_st *session_cache_head;
+	struct ssl_session_st *session_cache_tail;
+
+	/* This can have one of 2 values, ored together,
+	 * SSL_SESS_CACHE_CLIENT,
+	 * SSL_SESS_CACHE_SERVER,
+	 * Default is SSL_SESSION_CACHE_SERVER, which means only
+	 * SSL_accept which cache SSL_SESSIONS. */
+	int session_cache_mode;
+
+	/* If timeout is not 0, it is the default timeout value set
+	 * when SSL_new() is called.  This has been put in to make
+	 * life easier to set things up */
+	long session_timeout;
+
+	/* If this callback is not null, it will be called each
+	 * time a session id is added to the cache.  If this function
+	 * returns 1, it means that the callback will do a
+	 * SSL_SESSION_free() when it has finished using it.  Otherwise,
+	 * on 0, it means the callback has finished with it.
+	 * If remove_session_cb is not null, it will be called when
+	 * a session-id is removed from the cache.  After the call,
+	 * OpenSSL will SSL_SESSION_free() it. */
+	int (*new_session_cb)(struct ssl_st *ssl,SSL_SESSION *sess);
+	void (*remove_session_cb)(struct ssl_ctx_st *ctx,SSL_SESSION *sess);
+	SSL_SESSION *(*get_session_cb)(struct ssl_st *ssl,
+		unsigned char *data,int len,int *copy);
+
+	struct
+		{
+		int sess_connect;	/* SSL new conn - started */
+		int sess_connect_renegotiate;/* SSL reneg - requested */
+		int sess_connect_good;	/* SSL new conne/reneg - finished */
+		int sess_accept;	/* SSL new accept - started */
+		int sess_accept_renegotiate;/* SSL reneg - requested */
+		int sess_accept_good;	/* SSL accept/reneg - finished */
+		int sess_miss;		/* session lookup misses  */
+		int sess_timeout;	/* reuse attempt on timeouted session */
+		int sess_cache_full;	/* session removed due to full cache */
+		int sess_hit;		/* session reuse actually done */
+		int sess_cb_hit;	/* session-id that was not
+					 * in the cache was
+					 * passed back via the callback.  This
+					 * indicates that the application is
+					 * supplying session-id's from other
+					 * processes - spooky :-) */
+		} stats;
+
+	int references;
+
+	/* if defined, these override the X509_verify_cert() calls */
+	int (*app_verify_callback)(X509_STORE_CTX *, void *);
+	void *app_verify_arg;
+	/* before OpenSSL 0.9.7, 'app_verify_arg' was ignored
+	 * ('app_verify_callback' was called with just one argument) */
+
+	/* Default password callback. */
+	pem_password_cb *default_passwd_callback;
+
+	/* Default password callback user data. */
+	void *default_passwd_callback_userdata;
+
+	/* get client cert callback */
+	int (*client_cert_cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey);
+
+    /* cookie generate callback */
+    int (*app_gen_cookie_cb)(SSL *ssl, unsigned char *cookie, 
+        unsigned int *cookie_len);
+
+    /* verify cookie callback */
+    int (*app_verify_cookie_cb)(SSL *ssl, unsigned char *cookie, 
+        unsigned int cookie_len);
+
+	CRYPTO_EX_DATA ex_data;
+
+	const EVP_MD *rsa_md5;/* For SSLv2 - name is 'ssl2-md5' */
+	const EVP_MD *md5;	/* For SSLv3/TLSv1 'ssl3-md5' */
+	const EVP_MD *sha1;   /* For SSLv3/TLSv1 'ssl3->sha1' */
+
+	STACK_OF(X509) *extra_certs;
+	STACK_OF(SSL_COMP) *comp_methods; /* stack of SSL_COMP, SSLv3/TLSv1 */
+
+
+	/* Default values used when no per-SSL value is defined follow */
+
+	void (*info_callback)(const SSL *ssl,int type,int val); /* used if SSL's info_callback is NULL */
+
+	/* what we put in client cert requests */
+	STACK_OF(X509_NAME) *client_CA;
+
+
+	/* Default values to use in SSL structures follow (these are copied by SSL_new) */
+
+	unsigned long options;
+	unsigned long mode;
+	long max_cert_list;
+
+	struct cert_st /* CERT */ *cert;
+	int read_ahead;
+
+	/* callback that allows applications to peek at protocol messages */
+	void (*msg_callback)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg);
+	void *msg_callback_arg;
+
+	int verify_mode;
+	unsigned int sid_ctx_length;
+	unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH];
+	int (*default_verify_callback)(int ok,X509_STORE_CTX *ctx); /* called 'verify_callback' in the SSL */
+
+	/* Default generate session ID callback. */
+	GEN_SESSION_CB generate_session_id;
+
+	X509_VERIFY_PARAM *param;
+
+#if 0
+	int purpose;		/* Purpose setting */
+	int trust;		/* Trust setting */
+#endif
+
+	int quiet_shutdown;
+	};
+
+#define SSL_SESS_CACHE_OFF			0x0000
+#define SSL_SESS_CACHE_CLIENT			0x0001
+#define SSL_SESS_CACHE_SERVER			0x0002
+#define SSL_SESS_CACHE_BOTH	(SSL_SESS_CACHE_CLIENT|SSL_SESS_CACHE_SERVER)
+#define SSL_SESS_CACHE_NO_AUTO_CLEAR		0x0080
+/* enough comments already ... see SSL_CTX_set_session_cache_mode(3) */
+#define SSL_SESS_CACHE_NO_INTERNAL_LOOKUP	0x0100
+#define SSL_SESS_CACHE_NO_INTERNAL_STORE	0x0200
+#define SSL_SESS_CACHE_NO_INTERNAL \
+	(SSL_SESS_CACHE_NO_INTERNAL_LOOKUP|SSL_SESS_CACHE_NO_INTERNAL_STORE)
+
+  struct lhash_st *SSL_CTX_sessions(SSL_CTX *ctx);
+#define SSL_CTX_sess_number(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_NUMBER,0,NULL)
+#define SSL_CTX_sess_connect(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT,0,NULL)
+#define SSL_CTX_sess_connect_good(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_GOOD,0,NULL)
+#define SSL_CTX_sess_connect_renegotiate(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_RENEGOTIATE,0,NULL)
+#define SSL_CTX_sess_accept(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT,0,NULL)
+#define SSL_CTX_sess_accept_renegotiate(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_RENEGOTIATE,0,NULL)
+#define SSL_CTX_sess_accept_good(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_GOOD,0,NULL)
+#define SSL_CTX_sess_hits(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_HIT,0,NULL)
+#define SSL_CTX_sess_cb_hits(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CB_HIT,0,NULL)
+#define SSL_CTX_sess_misses(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_MISSES,0,NULL)
+#define SSL_CTX_sess_timeouts(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_TIMEOUTS,0,NULL)
+#define SSL_CTX_sess_cache_full(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CACHE_FULL,0,NULL)
+
+void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx, int (*new_session_cb)(struct ssl_st *ssl,SSL_SESSION *sess));
+int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(struct ssl_st *ssl, SSL_SESSION *sess);
+void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx, void (*remove_session_cb)(struct ssl_ctx_st *ctx,SSL_SESSION *sess));
+void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(struct ssl_ctx_st *ctx, SSL_SESSION *sess);
+void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx, SSL_SESSION *(*get_session_cb)(struct ssl_st *ssl, unsigned char *data,int len,int *copy));
+SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(struct ssl_st *ssl, unsigned char *Data, int len, int *copy);
+void SSL_CTX_set_info_callback(SSL_CTX *ctx, void (*cb)(const SSL *ssl,int type,int val));
+void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl,int type,int val);
+void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, int (*client_cert_cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey));
+int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL *ssl, X509 **x509, EVP_PKEY **pkey);
+void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx, int (*app_gen_cookie_cb)(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len));
+void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx, int (*app_verify_cookie_cb)(SSL *ssl, unsigned char *cookie, unsigned int cookie_len));
+
+#define SSL_NOTHING	1
+#define SSL_WRITING	2
+#define SSL_READING	3
+#define SSL_X509_LOOKUP	4
+
+/* These will only be used when doing non-blocking IO */
+#define SSL_want_nothing(s)	(SSL_want(s) == SSL_NOTHING)
+#define SSL_want_read(s)	(SSL_want(s) == SSL_READING)
+#define SSL_want_write(s)	(SSL_want(s) == SSL_WRITING)
+#define SSL_want_x509_lookup(s)	(SSL_want(s) == SSL_X509_LOOKUP)
+
+struct ssl_st
+	{
+	/* protocol version
+	 * (one of SSL2_VERSION, SSL3_VERSION, TLS1_VERSION, DTLS1_VERSION)
+	 */
+	int version;
+	int type; /* SSL_ST_CONNECT or SSL_ST_ACCEPT */
+
+	SSL_METHOD *method; /* SSLv3 */
+
+	/* There are 2 BIO's even though they are normally both the
+	 * same.  This is so data can be read and written to different
+	 * handlers */
+
+#ifndef OPENSSL_NO_BIO
+	BIO *rbio; /* used by SSL_read */
+	BIO *wbio; /* used by SSL_write */
+	BIO *bbio; /* used during session-id reuse to concatenate
+		    * messages */
+#else
+	char *rbio; /* used by SSL_read */
+	char *wbio; /* used by SSL_write */
+	char *bbio;
+#endif
+	/* This holds a variable that indicates what we were doing
+	 * when a 0 or -1 is returned.  This is needed for
+	 * non-blocking IO so we know what request needs re-doing when
+	 * in SSL_accept or SSL_connect */
+	int rwstate;
+
+	/* true when we are actually in SSL_accept() or SSL_connect() */
+	int in_handshake;
+	int (*handshake_func)(SSL *);
+
+	/* Imagine that here's a boolean member "init" that is
+	 * switched as soon as SSL_set_{accept/connect}_state
+	 * is called for the first time, so that "state" and
+	 * "handshake_func" are properly initialized.  But as
+	 * handshake_func is == 0 until then, we use this
+	 * test instead of an "init" member.
+	 */
+
+	int server;	/* are we the server side? - mostly used by SSL_clear*/
+
+	int new_session;/* 1 if we are to use a new session.
+	                 * 2 if we are a server and are inside a handshake
+	                 *   (i.e. not just sending a HelloRequest)
+	                 * NB: For servers, the 'new' session may actually be a previously
+	                 * cached session or even the previous session unless
+	                 * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */
+	int quiet_shutdown;/* don't send shutdown packets */
+	int shutdown;	/* we have shut things down, 0x01 sent, 0x02
+			 * for received */
+	int state;	/* where we are */
+	int rstate;	/* where we are when reading */
+
+	BUF_MEM *init_buf;	/* buffer used during init */
+	void *init_msg;   	/* pointer to handshake message body, set by ssl3_get_message() */
+	int init_num;		/* amount read/written */
+	int init_off;		/* amount read/written */
+
+	/* used internally to point at a raw packet */
+	unsigned char *packet;
+	unsigned int packet_length;
+
+	struct ssl2_state_st *s2; /* SSLv2 variables */
+	struct ssl3_state_st *s3; /* SSLv3 variables */
+	struct dtls1_state_st *d1; /* DTLSv1 variables */
+
+	int read_ahead;		/* Read as many input bytes as possible
+	               	 	 * (for non-blocking reads) */
+
+	/* callback that allows applications to peek at protocol messages */
+	void (*msg_callback)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg);
+	void *msg_callback_arg;
+
+	int hit;		/* reusing a previous session */
+
+	X509_VERIFY_PARAM *param;
+
+#if 0
+	int purpose;		/* Purpose setting */
+	int trust;		/* Trust setting */
+#endif
+
+	/* crypto */
+	STACK_OF(SSL_CIPHER) *cipher_list;
+	STACK_OF(SSL_CIPHER) *cipher_list_by_id;
+
+	/* These are the ones being used, the ones in SSL_SESSION are
+	 * the ones to be 'copied' into these ones */
+
+	EVP_CIPHER_CTX *enc_read_ctx;		/* cryptographic state */
+	const EVP_MD *read_hash;		/* used for mac generation */
+#ifndef OPENSSL_NO_COMP
+	COMP_CTX *expand;			/* uncompress */
+#else
+	char *expand;
+#endif
+
+	EVP_CIPHER_CTX *enc_write_ctx;		/* cryptographic state */
+	const EVP_MD *write_hash;		/* used for mac generation */
+#ifndef OPENSSL_NO_COMP
+	COMP_CTX *compress;			/* compression */
+#else
+	char *compress;	
+#endif
+
+	/* session info */
+
+	/* client cert? */
+	/* This is used to hold the server certificate used */
+	struct cert_st /* CERT */ *cert;
+
+	/* the session_id_context is used to ensure sessions are only reused
+	 * in the appropriate context */
+	unsigned int sid_ctx_length;
+	unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH];
+
+	/* This can also be in the session once a session is established */
+	SSL_SESSION *session;
+
+	/* Default generate session ID callback. */
+	GEN_SESSION_CB generate_session_id;
+
+	/* Used in SSL2 and SSL3 */
+	int verify_mode;	/* 0 don't care about verify failure.
+				 * 1 fail if verify fails */
+	int (*verify_callback)(int ok,X509_STORE_CTX *ctx); /* fail if callback returns 0 */
+
+	void (*info_callback)(const SSL *ssl,int type,int val); /* optional informational callback */
+
+	int error;		/* error bytes to be written */
+	int error_code;		/* actual code */
+
+#ifndef OPENSSL_NO_KRB5
+	KSSL_CTX *kssl_ctx;     /* Kerberos 5 context */
+#endif	/* OPENSSL_NO_KRB5 */
+
+	SSL_CTX *ctx;
+	/* set this flag to 1 and a sleep(1) is put into all SSL_read()
+	 * and SSL_write() calls, good for nbio debuging :-) */
+	int debug;	
+
+	/* extra application data */
+	long verify_result;
+	CRYPTO_EX_DATA ex_data;
+
+	/* for server side, keep the list of CA_dn we can use */
+	STACK_OF(X509_NAME) *client_CA;
+
+	int references;
+	unsigned long options; /* protocol behaviour */
+	unsigned long mode; /* API behaviour */
+	long max_cert_list;
+	int first_packet;
+	int client_version;	/* what was passed, used for
+				 * SSLv3/TLS rollback check */
+	};
+
+#ifdef __cplusplus
+}
+#endif
+
+#include 
+#include 
+#include  /* This is mostly sslv3 with a few tweaks */
+#include  /* Datagram TLS */
+#include 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* compatibility */
+#define SSL_set_app_data(s,arg)		(SSL_set_ex_data(s,0,(char *)arg))
+#define SSL_get_app_data(s)		(SSL_get_ex_data(s,0))
+#define SSL_SESSION_set_app_data(s,a)	(SSL_SESSION_set_ex_data(s,0,(char *)a))
+#define SSL_SESSION_get_app_data(s)	(SSL_SESSION_get_ex_data(s,0))
+#define SSL_CTX_get_app_data(ctx)	(SSL_CTX_get_ex_data(ctx,0))
+#define SSL_CTX_set_app_data(ctx,arg)	(SSL_CTX_set_ex_data(ctx,0,(char *)arg))
+
+/* The following are the possible values for ssl->state are are
+ * used to indicate where we are up to in the SSL connection establishment.
+ * The macros that follow are about the only things you should need to use
+ * and even then, only when using non-blocking IO.
+ * It can also be useful to work out where you were when the connection
+ * failed */
+
+#define SSL_ST_CONNECT			0x1000
+#define SSL_ST_ACCEPT			0x2000
+#define SSL_ST_MASK			0x0FFF
+#define SSL_ST_INIT			(SSL_ST_CONNECT|SSL_ST_ACCEPT)
+#define SSL_ST_BEFORE			0x4000
+#define SSL_ST_OK			0x03
+#define SSL_ST_RENEGOTIATE		(0x04|SSL_ST_INIT)
+
+#define SSL_CB_LOOP			0x01
+#define SSL_CB_EXIT			0x02
+#define SSL_CB_READ			0x04
+#define SSL_CB_WRITE			0x08
+#define SSL_CB_ALERT			0x4000 /* used in callback */
+#define SSL_CB_READ_ALERT		(SSL_CB_ALERT|SSL_CB_READ)
+#define SSL_CB_WRITE_ALERT		(SSL_CB_ALERT|SSL_CB_WRITE)
+#define SSL_CB_ACCEPT_LOOP		(SSL_ST_ACCEPT|SSL_CB_LOOP)
+#define SSL_CB_ACCEPT_EXIT		(SSL_ST_ACCEPT|SSL_CB_EXIT)
+#define SSL_CB_CONNECT_LOOP		(SSL_ST_CONNECT|SSL_CB_LOOP)
+#define SSL_CB_CONNECT_EXIT		(SSL_ST_CONNECT|SSL_CB_EXIT)
+#define SSL_CB_HANDSHAKE_START		0x10
+#define SSL_CB_HANDSHAKE_DONE		0x20
+
+/* Is the SSL_connection established? */
+#define SSL_get_state(a)		SSL_state(a)
+#define SSL_is_init_finished(a)		(SSL_state(a) == SSL_ST_OK)
+#define SSL_in_init(a)			(SSL_state(a)&SSL_ST_INIT)
+#define SSL_in_before(a)		(SSL_state(a)&SSL_ST_BEFORE)
+#define SSL_in_connect_init(a)		(SSL_state(a)&SSL_ST_CONNECT)
+#define SSL_in_accept_init(a)		(SSL_state(a)&SSL_ST_ACCEPT)
+
+/* The following 2 states are kept in ssl->rstate when reads fail,
+ * you should not need these */
+#define SSL_ST_READ_HEADER			0xF0
+#define SSL_ST_READ_BODY			0xF1
+#define SSL_ST_READ_DONE			0xF2
+
+/* Obtain latest Finished message
+ *   -- that we sent (SSL_get_finished)
+ *   -- that we expected from peer (SSL_get_peer_finished).
+ * Returns length (0 == no Finished so far), copies up to 'count' bytes. */
+size_t SSL_get_finished(const SSL *s, void *buf, size_t count);
+size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count);
+
+/* use either SSL_VERIFY_NONE or SSL_VERIFY_PEER, the last 2 options
+ * are 'ored' with SSL_VERIFY_PEER if they are desired */
+#define SSL_VERIFY_NONE			0x00
+#define SSL_VERIFY_PEER			0x01
+#define SSL_VERIFY_FAIL_IF_NO_PEER_CERT	0x02
+#define SSL_VERIFY_CLIENT_ONCE		0x04
+
+#define OpenSSL_add_ssl_algorithms()	SSL_library_init()
+#define SSLeay_add_ssl_algorithms()	SSL_library_init()
+
+/* this is for backward compatibility */
+#if 0 /* NEW_SSLEAY */
+#define SSL_CTX_set_default_verify(a,b,c) SSL_CTX_set_verify(a,b,c)
+#define SSL_set_pref_cipher(c,n)	SSL_set_cipher_list(c,n)
+#define SSL_add_session(a,b)            SSL_CTX_add_session((a),(b))
+#define SSL_remove_session(a,b)		SSL_CTX_remove_session((a),(b))
+#define SSL_flush_sessions(a,b)		SSL_CTX_flush_sessions((a),(b))
+#endif
+/* More backward compatibility */
+#define SSL_get_cipher(s) \
+		SSL_CIPHER_get_name(SSL_get_current_cipher(s))
+#define SSL_get_cipher_bits(s,np) \
+		SSL_CIPHER_get_bits(SSL_get_current_cipher(s),np)
+#define SSL_get_cipher_version(s) \
+		SSL_CIPHER_get_version(SSL_get_current_cipher(s))
+#define SSL_get_cipher_name(s) \
+		SSL_CIPHER_get_name(SSL_get_current_cipher(s))
+#define SSL_get_time(a)		SSL_SESSION_get_time(a)
+#define SSL_set_time(a,b)	SSL_SESSION_set_time((a),(b))
+#define SSL_get_timeout(a)	SSL_SESSION_get_timeout(a)
+#define SSL_set_timeout(a,b)	SSL_SESSION_set_timeout((a),(b))
+
+#if 1 /*SSLEAY_MACROS*/
+#define d2i_SSL_SESSION_bio(bp,s_id) ASN1_d2i_bio_of(SSL_SESSION,SSL_SESSION_new,d2i_SSL_SESSION,bp,s_id)
+#define i2d_SSL_SESSION_bio(bp,s_id) ASN1_i2d_bio_of(SSL_SESSION,i2d_SSL_SESSION,bp,s_id)
+#define PEM_read_SSL_SESSION(fp,x,cb,u) (SSL_SESSION *)PEM_ASN1_read( \
+	(char *(*)())d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,fp,(char **)x,cb,u)
+#define PEM_read_bio_SSL_SESSION(bp,x,cb,u) PEM_ASN1_read_bio_of(SSL_SESSION,d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,bp,x,cb,u)
+#define PEM_write_SSL_SESSION(fp,x) \
+	PEM_ASN1_write((int (*)())i2d_SSL_SESSION, \
+		PEM_STRING_SSL_SESSION,fp, (char *)x, NULL,NULL,0,NULL,NULL)
+#define PEM_write_bio_SSL_SESSION(bp,x) \
+	PEM_ASN1_write_bio_of(SSL_SESSION,i2d_SSL_SESSION,PEM_STRING_SSL_SESSION,bp,x,NULL,NULL,0,NULL,NULL)
+#endif
+
+#define SSL_AD_REASON_OFFSET		1000
+/* These alert types are for SSLv3 and TLSv1 */
+#define SSL_AD_CLOSE_NOTIFY		SSL3_AD_CLOSE_NOTIFY
+#define SSL_AD_UNEXPECTED_MESSAGE	SSL3_AD_UNEXPECTED_MESSAGE /* fatal */
+#define SSL_AD_BAD_RECORD_MAC		SSL3_AD_BAD_RECORD_MAC     /* fatal */
+#define SSL_AD_DECRYPTION_FAILED	TLS1_AD_DECRYPTION_FAILED
+#define SSL_AD_RECORD_OVERFLOW		TLS1_AD_RECORD_OVERFLOW
+#define SSL_AD_DECOMPRESSION_FAILURE	SSL3_AD_DECOMPRESSION_FAILURE/* fatal */
+#define SSL_AD_HANDSHAKE_FAILURE	SSL3_AD_HANDSHAKE_FAILURE/* fatal */
+#define SSL_AD_NO_CERTIFICATE		SSL3_AD_NO_CERTIFICATE /* Not for TLS */
+#define SSL_AD_BAD_CERTIFICATE		SSL3_AD_BAD_CERTIFICATE
+#define SSL_AD_UNSUPPORTED_CERTIFICATE	SSL3_AD_UNSUPPORTED_CERTIFICATE
+#define SSL_AD_CERTIFICATE_REVOKED	SSL3_AD_CERTIFICATE_REVOKED
+#define SSL_AD_CERTIFICATE_EXPIRED	SSL3_AD_CERTIFICATE_EXPIRED
+#define SSL_AD_CERTIFICATE_UNKNOWN	SSL3_AD_CERTIFICATE_UNKNOWN
+#define SSL_AD_ILLEGAL_PARAMETER	SSL3_AD_ILLEGAL_PARAMETER   /* fatal */
+#define SSL_AD_UNKNOWN_CA		TLS1_AD_UNKNOWN_CA	/* fatal */
+#define SSL_AD_ACCESS_DENIED		TLS1_AD_ACCESS_DENIED	/* fatal */
+#define SSL_AD_DECODE_ERROR		TLS1_AD_DECODE_ERROR	/* fatal */
+#define SSL_AD_DECRYPT_ERROR		TLS1_AD_DECRYPT_ERROR
+#define SSL_AD_EXPORT_RESTRICTION	TLS1_AD_EXPORT_RESTRICTION/* fatal */
+#define SSL_AD_PROTOCOL_VERSION		TLS1_AD_PROTOCOL_VERSION /* fatal */
+#define SSL_AD_INSUFFICIENT_SECURITY	TLS1_AD_INSUFFICIENT_SECURITY/* fatal */
+#define SSL_AD_INTERNAL_ERROR		TLS1_AD_INTERNAL_ERROR	/* fatal */
+#define SSL_AD_USER_CANCELLED		TLS1_AD_USER_CANCELLED
+#define SSL_AD_NO_RENEGOTIATION		TLS1_AD_NO_RENEGOTIATION
+
+#define SSL_ERROR_NONE			0
+#define SSL_ERROR_SSL			1
+#define SSL_ERROR_WANT_READ		2
+#define SSL_ERROR_WANT_WRITE		3
+#define SSL_ERROR_WANT_X509_LOOKUP	4
+#define SSL_ERROR_SYSCALL		5 /* look at error stack/return value/errno */
+#define SSL_ERROR_ZERO_RETURN		6
+#define SSL_ERROR_WANT_CONNECT		7
+#define SSL_ERROR_WANT_ACCEPT		8
+
+#define SSL_CTRL_NEED_TMP_RSA			1
+#define SSL_CTRL_SET_TMP_RSA			2
+#define SSL_CTRL_SET_TMP_DH			3
+#define SSL_CTRL_SET_TMP_ECDH			4
+#define SSL_CTRL_SET_TMP_RSA_CB			5
+#define SSL_CTRL_SET_TMP_DH_CB			6
+#define SSL_CTRL_SET_TMP_ECDH_CB		7
+
+#define SSL_CTRL_GET_SESSION_REUSED		8
+#define SSL_CTRL_GET_CLIENT_CERT_REQUEST	9
+#define SSL_CTRL_GET_NUM_RENEGOTIATIONS		10
+#define SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS	11
+#define SSL_CTRL_GET_TOTAL_RENEGOTIATIONS	12
+#define SSL_CTRL_GET_FLAGS			13
+#define SSL_CTRL_EXTRA_CHAIN_CERT		14
+
+#define SSL_CTRL_SET_MSG_CALLBACK               15
+#define SSL_CTRL_SET_MSG_CALLBACK_ARG           16
+
+/* only applies to datagram connections */
+#define SSL_CTRL_SET_MTU                17
+/* Stats */
+#define SSL_CTRL_SESS_NUMBER			20
+#define SSL_CTRL_SESS_CONNECT			21
+#define SSL_CTRL_SESS_CONNECT_GOOD		22
+#define SSL_CTRL_SESS_CONNECT_RENEGOTIATE	23
+#define SSL_CTRL_SESS_ACCEPT			24
+#define SSL_CTRL_SESS_ACCEPT_GOOD		25
+#define SSL_CTRL_SESS_ACCEPT_RENEGOTIATE	26
+#define SSL_CTRL_SESS_HIT			27
+#define SSL_CTRL_SESS_CB_HIT			28
+#define SSL_CTRL_SESS_MISSES			29
+#define SSL_CTRL_SESS_TIMEOUTS			30
+#define SSL_CTRL_SESS_CACHE_FULL		31
+#define SSL_CTRL_OPTIONS			32
+#define SSL_CTRL_MODE				33
+
+#define SSL_CTRL_GET_READ_AHEAD			40
+#define SSL_CTRL_SET_READ_AHEAD			41
+#define SSL_CTRL_SET_SESS_CACHE_SIZE		42
+#define SSL_CTRL_GET_SESS_CACHE_SIZE		43
+#define SSL_CTRL_SET_SESS_CACHE_MODE		44
+#define SSL_CTRL_GET_SESS_CACHE_MODE		45
+
+#define SSL_CTRL_GET_MAX_CERT_LIST		50
+#define SSL_CTRL_SET_MAX_CERT_LIST		51
+
+#define SSL_session_reused(ssl) \
+	SSL_ctrl((ssl),SSL_CTRL_GET_SESSION_REUSED,0,NULL)
+#define SSL_num_renegotiations(ssl) \
+	SSL_ctrl((ssl),SSL_CTRL_GET_NUM_RENEGOTIATIONS,0,NULL)
+#define SSL_clear_num_renegotiations(ssl) \
+	SSL_ctrl((ssl),SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS,0,NULL)
+#define SSL_total_renegotiations(ssl) \
+	SSL_ctrl((ssl),SSL_CTRL_GET_TOTAL_RENEGOTIATIONS,0,NULL)
+
+#define SSL_CTX_need_tmp_RSA(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_NEED_TMP_RSA,0,NULL)
+#define SSL_CTX_set_tmp_rsa(ctx,rsa) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_RSA,0,(char *)rsa)
+#define SSL_CTX_set_tmp_dh(ctx,dh) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH,0,(char *)dh)
+#define SSL_CTX_set_tmp_ecdh(ctx,ecdh) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_ECDH,0,(char *)ecdh)
+
+#define SSL_need_tmp_RSA(ssl) \
+	SSL_ctrl(ssl,SSL_CTRL_NEED_TMP_RSA,0,NULL)
+#define SSL_set_tmp_rsa(ssl,rsa) \
+	SSL_ctrl(ssl,SSL_CTRL_SET_TMP_RSA,0,(char *)rsa)
+#define SSL_set_tmp_dh(ssl,dh) \
+	SSL_ctrl(ssl,SSL_CTRL_SET_TMP_DH,0,(char *)dh)
+#define SSL_set_tmp_ecdh(ssl,ecdh) \
+	SSL_ctrl(ssl,SSL_CTRL_SET_TMP_ECDH,0,(char *)ecdh)
+
+#define SSL_CTX_add_extra_chain_cert(ctx,x509) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,(char *)x509)
+
+#ifndef OPENSSL_NO_BIO
+BIO_METHOD *BIO_f_ssl(void);
+BIO *BIO_new_ssl(SSL_CTX *ctx,int client);
+BIO *BIO_new_ssl_connect(SSL_CTX *ctx);
+BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx);
+int BIO_ssl_copy_session_id(BIO *to,BIO *from);
+void BIO_ssl_shutdown(BIO *ssl_bio);
+
+#endif
+
+int	SSL_CTX_set_cipher_list(SSL_CTX *,const char *str);
+SSL_CTX *SSL_CTX_new(SSL_METHOD *meth);
+void	SSL_CTX_free(SSL_CTX *);
+long SSL_CTX_set_timeout(SSL_CTX *ctx,long t);
+long SSL_CTX_get_timeout(const SSL_CTX *ctx);
+X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *);
+void SSL_CTX_set_cert_store(SSL_CTX *,X509_STORE *);
+int SSL_want(const SSL *s);
+int	SSL_clear(SSL *s);
+
+void	SSL_CTX_flush_sessions(SSL_CTX *ctx,long tm);
+
+SSL_CIPHER *SSL_get_current_cipher(const SSL *s);
+int	SSL_CIPHER_get_bits(const SSL_CIPHER *c,int *alg_bits);
+char *	SSL_CIPHER_get_version(const SSL_CIPHER *c);
+const char *	SSL_CIPHER_get_name(const SSL_CIPHER *c);
+
+int	SSL_get_fd(const SSL *s);
+int	SSL_get_rfd(const SSL *s);
+int	SSL_get_wfd(const SSL *s);
+const char  * SSL_get_cipher_list(const SSL *s,int n);
+char *	SSL_get_shared_ciphers(const SSL *s, char *buf, int len);
+int	SSL_get_read_ahead(const SSL * s);
+int	SSL_pending(const SSL *s);
+#ifndef OPENSSL_NO_SOCK
+int	SSL_set_fd(SSL *s, int fd);
+int	SSL_set_rfd(SSL *s, int fd);
+int	SSL_set_wfd(SSL *s, int fd);
+#endif
+#ifndef OPENSSL_NO_BIO
+void	SSL_set_bio(SSL *s, BIO *rbio,BIO *wbio);
+BIO *	SSL_get_rbio(const SSL *s);
+BIO *	SSL_get_wbio(const SSL *s);
+#endif
+int	SSL_set_cipher_list(SSL *s, const char *str);
+void	SSL_set_read_ahead(SSL *s, int yes);
+int	SSL_get_verify_mode(const SSL *s);
+int	SSL_get_verify_depth(const SSL *s);
+int	(*SSL_get_verify_callback(const SSL *s))(int,X509_STORE_CTX *);
+void	SSL_set_verify(SSL *s, int mode,
+		       int (*callback)(int ok,X509_STORE_CTX *ctx));
+void	SSL_set_verify_depth(SSL *s, int depth);
+#ifndef OPENSSL_NO_RSA
+int	SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa);
+#endif
+int	SSL_use_RSAPrivateKey_ASN1(SSL *ssl, unsigned char *d, long len);
+int	SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey);
+int	SSL_use_PrivateKey_ASN1(int pk,SSL *ssl, const unsigned char *d, long len);
+int	SSL_use_certificate(SSL *ssl, X509 *x);
+int	SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len);
+
+#ifndef OPENSSL_NO_STDIO
+int	SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type);
+int	SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type);
+int	SSL_use_certificate_file(SSL *ssl, const char *file, int type);
+int	SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type);
+int	SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type);
+int	SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type);
+int	SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file); /* PEM type */
+STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file);
+int	SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
+					    const char *file);
+#ifndef OPENSSL_SYS_VMS
+#ifndef OPENSSL_SYS_MACINTOSH_CLASSIC /* XXXXX: Better scheme needed! [was: #ifndef MAC_OS_pre_X] */
+int	SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
+					   const char *dir);
+#endif
+#endif
+
+#endif
+
+void	SSL_load_error_strings(void );
+const char *SSL_state_string(const SSL *s);
+const char *SSL_rstate_string(const SSL *s);
+const char *SSL_state_string_long(const SSL *s);
+const char *SSL_rstate_string_long(const SSL *s);
+long	SSL_SESSION_get_time(const SSL_SESSION *s);
+long	SSL_SESSION_set_time(SSL_SESSION *s, long t);
+long	SSL_SESSION_get_timeout(const SSL_SESSION *s);
+long	SSL_SESSION_set_timeout(SSL_SESSION *s, long t);
+void	SSL_copy_session_id(SSL *to,const SSL *from);
+
+SSL_SESSION *SSL_SESSION_new(void);
+unsigned long SSL_SESSION_hash(const SSL_SESSION *a);
+int	SSL_SESSION_cmp(const SSL_SESSION *a,const SSL_SESSION *b);
+const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len);
+#ifndef OPENSSL_NO_FP_API
+int	SSL_SESSION_print_fp(FILE *fp,const SSL_SESSION *ses);
+#endif
+#ifndef OPENSSL_NO_BIO
+int	SSL_SESSION_print(BIO *fp,const SSL_SESSION *ses);
+#endif
+void	SSL_SESSION_free(SSL_SESSION *ses);
+int	i2d_SSL_SESSION(SSL_SESSION *in,unsigned char **pp);
+int	SSL_set_session(SSL *to, SSL_SESSION *session);
+int	SSL_CTX_add_session(SSL_CTX *s, SSL_SESSION *c);
+int	SSL_CTX_remove_session(SSL_CTX *,SSL_SESSION *c);
+int	SSL_CTX_set_generate_session_id(SSL_CTX *, GEN_SESSION_CB);
+int	SSL_set_generate_session_id(SSL *, GEN_SESSION_CB);
+int	SSL_has_matching_session_id(const SSL *ssl, const unsigned char *id,
+					unsigned int id_len);
+SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a,const unsigned char **pp,
+			     long length);
+
+#ifdef HEADER_X509_H
+X509 *	SSL_get_peer_certificate(const SSL *s);
+#endif
+
+STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *s);
+
+int SSL_CTX_get_verify_mode(const SSL_CTX *ctx);
+int SSL_CTX_get_verify_depth(const SSL_CTX *ctx);
+int (*SSL_CTX_get_verify_callback(const SSL_CTX *ctx))(int,X509_STORE_CTX *);
+void SSL_CTX_set_verify(SSL_CTX *ctx,int mode,
+			int (*callback)(int, X509_STORE_CTX *));
+void SSL_CTX_set_verify_depth(SSL_CTX *ctx,int depth);
+void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, int (*cb)(X509_STORE_CTX *,void *), void *arg);
+#ifndef OPENSSL_NO_RSA
+int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa);
+#endif
+int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d, long len);
+int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey);
+int SSL_CTX_use_PrivateKey_ASN1(int pk,SSL_CTX *ctx,
+	const unsigned char *d, long len);
+int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x);
+int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const unsigned char *d);
+
+void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb);
+void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u);
+
+int SSL_CTX_check_private_key(const SSL_CTX *ctx);
+int SSL_check_private_key(const SSL *ctx);
+
+int	SSL_CTX_set_session_id_context(SSL_CTX *ctx,const unsigned char *sid_ctx,
+				       unsigned int sid_ctx_len);
+
+SSL *	SSL_new(SSL_CTX *ctx);
+int	SSL_set_session_id_context(SSL *ssl,const unsigned char *sid_ctx,
+				   unsigned int sid_ctx_len);
+
+int SSL_CTX_set_purpose(SSL_CTX *s, int purpose);
+int SSL_set_purpose(SSL *s, int purpose);
+int SSL_CTX_set_trust(SSL_CTX *s, int trust);
+int SSL_set_trust(SSL *s, int trust);
+
+void	SSL_free(SSL *ssl);
+int 	SSL_accept(SSL *ssl);
+int 	SSL_connect(SSL *ssl);
+int 	SSL_read(SSL *ssl,void *buf,int num);
+int 	SSL_peek(SSL *ssl,void *buf,int num);
+int 	SSL_write(SSL *ssl,const void *buf,int num);
+long	SSL_ctrl(SSL *ssl,int cmd, long larg, void *parg);
+long	SSL_callback_ctrl(SSL *, int, void (*)(void));
+long	SSL_CTX_ctrl(SSL_CTX *ctx,int cmd, long larg, void *parg);
+long	SSL_CTX_callback_ctrl(SSL_CTX *, int, void (*)(void));
+
+int	SSL_get_error(const SSL *s,int ret_code);
+const char *SSL_get_version(const SSL *s);
+
+/* This sets the 'default' SSL version that SSL_new() will create */
+int SSL_CTX_set_ssl_version(SSL_CTX *ctx,SSL_METHOD *meth);
+
+SSL_METHOD *SSLv2_method(void);		/* SSLv2 */
+SSL_METHOD *SSLv2_server_method(void);	/* SSLv2 */
+SSL_METHOD *SSLv2_client_method(void);	/* SSLv2 */
+
+SSL_METHOD *SSLv3_method(void);		/* SSLv3 */
+SSL_METHOD *SSLv3_server_method(void);	/* SSLv3 */
+SSL_METHOD *SSLv3_client_method(void);	/* SSLv3 */
+
+SSL_METHOD *SSLv23_method(void);	/* SSLv3 but can rollback to v2 */
+SSL_METHOD *SSLv23_server_method(void);	/* SSLv3 but can rollback to v2 */
+SSL_METHOD *SSLv23_client_method(void);	/* SSLv3 but can rollback to v2 */
+
+SSL_METHOD *TLSv1_method(void);		/* TLSv1.0 */
+SSL_METHOD *TLSv1_server_method(void);	/* TLSv1.0 */
+SSL_METHOD *TLSv1_client_method(void);	/* TLSv1.0 */
+
+SSL_METHOD *DTLSv1_method(void);		/* DTLSv1.0 */
+SSL_METHOD *DTLSv1_server_method(void);	/* DTLSv1.0 */
+SSL_METHOD *DTLSv1_client_method(void);	/* DTLSv1.0 */
+
+STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s);
+
+int SSL_do_handshake(SSL *s);
+int SSL_renegotiate(SSL *s);
+int SSL_renegotiate_pending(SSL *s);
+int SSL_shutdown(SSL *s);
+
+SSL_METHOD *SSL_get_ssl_method(SSL *s);
+int SSL_set_ssl_method(SSL *s,SSL_METHOD *method);
+const char *SSL_alert_type_string_long(int value);
+const char *SSL_alert_type_string(int value);
+const char *SSL_alert_desc_string_long(int value);
+const char *SSL_alert_desc_string(int value);
+
+void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list);
+void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list);
+STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s);
+STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *s);
+int SSL_add_client_CA(SSL *ssl,X509 *x);
+int SSL_CTX_add_client_CA(SSL_CTX *ctx,X509 *x);
+
+void SSL_set_connect_state(SSL *s);
+void SSL_set_accept_state(SSL *s);
+
+long SSL_get_default_timeout(const SSL *s);
+
+int SSL_library_init(void );
+
+char *SSL_CIPHER_description(SSL_CIPHER *,char *buf,int size);
+STACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *sk);
+
+SSL *SSL_dup(SSL *ssl);
+
+X509 *SSL_get_certificate(const SSL *ssl);
+/* EVP_PKEY */ struct evp_pkey_st *SSL_get_privatekey(SSL *ssl);
+
+void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx,int mode);
+int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx);
+void SSL_set_quiet_shutdown(SSL *ssl,int mode);
+int SSL_get_quiet_shutdown(const SSL *ssl);
+void SSL_set_shutdown(SSL *ssl,int mode);
+int SSL_get_shutdown(const SSL *ssl);
+int SSL_version(const SSL *ssl);
+int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx);
+int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,
+	const char *CApath);
+#define SSL_get0_session SSL_get_session /* just peek at pointer */
+SSL_SESSION *SSL_get_session(const SSL *ssl);
+SSL_SESSION *SSL_get1_session(SSL *ssl); /* obtain a reference count */
+SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl);
+void SSL_set_info_callback(SSL *ssl,
+			   void (*cb)(const SSL *ssl,int type,int val));
+void (*SSL_get_info_callback(const SSL *ssl))(const SSL *ssl,int type,int val);
+int SSL_state(const SSL *ssl);
+
+void SSL_set_verify_result(SSL *ssl,long v);
+long SSL_get_verify_result(const SSL *ssl);
+
+int SSL_set_ex_data(SSL *ssl,int idx,void *data);
+void *SSL_get_ex_data(const SSL *ssl,int idx);
+int SSL_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+	CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+
+int SSL_SESSION_set_ex_data(SSL_SESSION *ss,int idx,void *data);
+void *SSL_SESSION_get_ex_data(const SSL_SESSION *ss,int idx);
+int SSL_SESSION_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+	CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+
+int SSL_CTX_set_ex_data(SSL_CTX *ssl,int idx,void *data);
+void *SSL_CTX_get_ex_data(const SSL_CTX *ssl,int idx);
+int SSL_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+	CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+
+int SSL_get_ex_data_X509_STORE_CTX_idx(void );
+
+#define SSL_CTX_sess_set_cache_size(ctx,t) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_SIZE,t,NULL)
+#define SSL_CTX_sess_get_cache_size(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_SIZE,0,NULL)
+#define SSL_CTX_set_session_cache_mode(ctx,m) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_MODE,m,NULL)
+#define SSL_CTX_get_session_cache_mode(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_MODE,0,NULL)
+
+#define SSL_CTX_get_default_read_ahead(ctx) SSL_CTX_get_read_ahead(ctx)
+#define SSL_CTX_set_default_read_ahead(ctx,m) SSL_CTX_set_read_ahead(ctx,m)
+#define SSL_CTX_get_read_ahead(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_GET_READ_AHEAD,0,NULL)
+#define SSL_CTX_set_read_ahead(ctx,m) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_READ_AHEAD,m,NULL)
+#define SSL_CTX_get_max_cert_list(ctx) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL)
+#define SSL_CTX_set_max_cert_list(ctx,m) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL)
+#define SSL_get_max_cert_list(ssl) \
+	SSL_ctrl(ssl,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL)
+#define SSL_set_max_cert_list(ssl,m) \
+	SSL_ctrl(ssl,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL)
+
+     /* NB: the keylength is only applicable when is_export is true */
+#ifndef OPENSSL_NO_RSA
+void SSL_CTX_set_tmp_rsa_callback(SSL_CTX *ctx,
+				  RSA *(*cb)(SSL *ssl,int is_export,
+					     int keylength));
+
+void SSL_set_tmp_rsa_callback(SSL *ssl,
+				  RSA *(*cb)(SSL *ssl,int is_export,
+					     int keylength));
+#endif
+#ifndef OPENSSL_NO_DH
+void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,
+				 DH *(*dh)(SSL *ssl,int is_export,
+					   int keylength));
+void SSL_set_tmp_dh_callback(SSL *ssl,
+				 DH *(*dh)(SSL *ssl,int is_export,
+					   int keylength));
+#endif
+#ifndef OPENSSL_NO_ECDH
+void SSL_CTX_set_tmp_ecdh_callback(SSL_CTX *ctx,
+				 EC_KEY *(*ecdh)(SSL *ssl,int is_export,
+					   int keylength));
+void SSL_set_tmp_ecdh_callback(SSL *ssl,
+				 EC_KEY *(*ecdh)(SSL *ssl,int is_export,
+					   int keylength));
+#endif
+
+#ifndef OPENSSL_NO_COMP
+const COMP_METHOD *SSL_get_current_compression(SSL *s);
+const COMP_METHOD *SSL_get_current_expansion(SSL *s);
+const char *SSL_COMP_get_name(const COMP_METHOD *comp);
+STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void);
+int SSL_COMP_add_compression_method(int id,COMP_METHOD *cm);
+#else
+const void *SSL_get_current_compression(SSL *s);
+const void *SSL_get_current_expansion(SSL *s);
+const char *SSL_COMP_get_name(const void *comp);
+void *SSL_COMP_get_compression_methods(void);
+int SSL_COMP_add_compression_method(int id,void *cm);
+#endif
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_SSL_strings(void);
+
+/* Error codes for the SSL functions. */
+
+/* Function codes. */
+#define SSL_F_CLIENT_CERTIFICATE			 100
+#define SSL_F_CLIENT_FINISHED				 167
+#define SSL_F_CLIENT_HELLO				 101
+#define SSL_F_CLIENT_MASTER_KEY				 102
+#define SSL_F_D2I_SSL_SESSION				 103
+#define SSL_F_DO_DTLS1_WRITE				 245
+#define SSL_F_DO_SSL3_WRITE				 104
+#define SSL_F_DTLS1_ACCEPT				 246
+#define SSL_F_DTLS1_BUFFER_RECORD			 247
+#define SSL_F_DTLS1_CLIENT_HELLO			 248
+#define SSL_F_DTLS1_CONNECT				 249
+#define SSL_F_DTLS1_ENC					 250
+#define SSL_F_DTLS1_GET_HELLO_VERIFY			 251
+#define SSL_F_DTLS1_GET_MESSAGE				 252
+#define SSL_F_DTLS1_GET_MESSAGE_FRAGMENT		 253
+#define SSL_F_DTLS1_GET_RECORD				 254
+#define SSL_F_DTLS1_OUTPUT_CERT_CHAIN			 255
+#define SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE		 256
+#define SSL_F_DTLS1_PROCESS_RECORD			 257
+#define SSL_F_DTLS1_READ_BYTES				 258
+#define SSL_F_DTLS1_READ_FAILED				 259
+#define SSL_F_DTLS1_SEND_CERTIFICATE_REQUEST		 260
+#define SSL_F_DTLS1_SEND_CLIENT_CERTIFICATE		 261
+#define SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE		 262
+#define SSL_F_DTLS1_SEND_CLIENT_VERIFY			 263
+#define SSL_F_DTLS1_SEND_HELLO_VERIFY_REQUEST		 264
+#define SSL_F_DTLS1_SEND_SERVER_CERTIFICATE		 265
+#define SSL_F_DTLS1_SEND_SERVER_HELLO			 266
+#define SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE		 267
+#define SSL_F_DTLS1_WRITE_APP_DATA_BYTES		 268
+#define SSL_F_GET_CLIENT_FINISHED			 105
+#define SSL_F_GET_CLIENT_HELLO				 106
+#define SSL_F_GET_CLIENT_MASTER_KEY			 107
+#define SSL_F_GET_SERVER_FINISHED			 108
+#define SSL_F_GET_SERVER_HELLO				 109
+#define SSL_F_GET_SERVER_VERIFY				 110
+#define SSL_F_I2D_SSL_SESSION				 111
+#define SSL_F_READ_N					 112
+#define SSL_F_REQUEST_CERTIFICATE			 113
+#define SSL_F_SERVER_FINISH				 239
+#define SSL_F_SERVER_HELLO				 114
+#define SSL_F_SERVER_VERIFY				 240
+#define SSL_F_SSL23_ACCEPT				 115
+#define SSL_F_SSL23_CLIENT_HELLO			 116
+#define SSL_F_SSL23_CONNECT				 117
+#define SSL_F_SSL23_GET_CLIENT_HELLO			 118
+#define SSL_F_SSL23_GET_SERVER_HELLO			 119
+#define SSL_F_SSL23_PEEK				 237
+#define SSL_F_SSL23_READ				 120
+#define SSL_F_SSL23_WRITE				 121
+#define SSL_F_SSL2_ACCEPT				 122
+#define SSL_F_SSL2_CONNECT				 123
+#define SSL_F_SSL2_ENC_INIT				 124
+#define SSL_F_SSL2_GENERATE_KEY_MATERIAL		 241
+#define SSL_F_SSL2_PEEK					 234
+#define SSL_F_SSL2_READ					 125
+#define SSL_F_SSL2_READ_INTERNAL			 236
+#define SSL_F_SSL2_SET_CERTIFICATE			 126
+#define SSL_F_SSL2_WRITE				 127
+#define SSL_F_SSL3_ACCEPT				 128
+#define SSL_F_SSL3_CALLBACK_CTRL			 233
+#define SSL_F_SSL3_CHANGE_CIPHER_STATE			 129
+#define SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM		 130
+#define SSL_F_SSL3_CLIENT_HELLO				 131
+#define SSL_F_SSL3_CONNECT				 132
+#define SSL_F_SSL3_CTRL					 213
+#define SSL_F_SSL3_CTX_CTRL				 133
+#define SSL_F_SSL3_ENC					 134
+#define SSL_F_SSL3_GENERATE_KEY_BLOCK			 238
+#define SSL_F_SSL3_GET_CERTIFICATE_REQUEST		 135
+#define SSL_F_SSL3_GET_CERT_VERIFY			 136
+#define SSL_F_SSL3_GET_CLIENT_CERTIFICATE		 137
+#define SSL_F_SSL3_GET_CLIENT_HELLO			 138
+#define SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE		 139
+#define SSL_F_SSL3_GET_FINISHED				 140
+#define SSL_F_SSL3_GET_KEY_EXCHANGE			 141
+#define SSL_F_SSL3_GET_MESSAGE				 142
+#define SSL_F_SSL3_GET_RECORD				 143
+#define SSL_F_SSL3_GET_SERVER_CERTIFICATE		 144
+#define SSL_F_SSL3_GET_SERVER_DONE			 145
+#define SSL_F_SSL3_GET_SERVER_HELLO			 146
+#define SSL_F_SSL3_OUTPUT_CERT_CHAIN			 147
+#define SSL_F_SSL3_PEEK					 235
+#define SSL_F_SSL3_READ_BYTES				 148
+#define SSL_F_SSL3_READ_N				 149
+#define SSL_F_SSL3_SEND_CERTIFICATE_REQUEST		 150
+#define SSL_F_SSL3_SEND_CLIENT_CERTIFICATE		 151
+#define SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE		 152
+#define SSL_F_SSL3_SEND_CLIENT_VERIFY			 153
+#define SSL_F_SSL3_SEND_SERVER_CERTIFICATE		 154
+#define SSL_F_SSL3_SEND_SERVER_HELLO			 242
+#define SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE		 155
+#define SSL_F_SSL3_SETUP_BUFFERS			 156
+#define SSL_F_SSL3_SETUP_KEY_BLOCK			 157
+#define SSL_F_SSL3_WRITE_BYTES				 158
+#define SSL_F_SSL3_WRITE_PENDING			 159
+#define SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK	 215
+#define SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK	 216
+#define SSL_F_SSL_BAD_METHOD				 160
+#define SSL_F_SSL_BYTES_TO_CIPHER_LIST			 161
+#define SSL_F_SSL_CERT_DUP				 221
+#define SSL_F_SSL_CERT_INST				 222
+#define SSL_F_SSL_CERT_INSTANTIATE			 214
+#define SSL_F_SSL_CERT_NEW				 162
+#define SSL_F_SSL_CHECK_PRIVATE_KEY			 163
+#define SSL_F_SSL_CIPHER_PROCESS_RULESTR		 230
+#define SSL_F_SSL_CIPHER_STRENGTH_SORT			 231
+#define SSL_F_SSL_CLEAR					 164
+#define SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD		 165
+#define SSL_F_SSL_CREATE_CIPHER_LIST			 166
+#define SSL_F_SSL_CTRL					 232
+#define SSL_F_SSL_CTX_CHECK_PRIVATE_KEY			 168
+#define SSL_F_SSL_CTX_NEW				 169
+#define SSL_F_SSL_CTX_SET_CIPHER_LIST			 269
+#define SSL_F_SSL_CTX_SET_PURPOSE			 226
+#define SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT		 219
+#define SSL_F_SSL_CTX_SET_SSL_VERSION			 170
+#define SSL_F_SSL_CTX_SET_TRUST				 229
+#define SSL_F_SSL_CTX_USE_CERTIFICATE			 171
+#define SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1		 172
+#define SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE	 220
+#define SSL_F_SSL_CTX_USE_CERTIFICATE_FILE		 173
+#define SSL_F_SSL_CTX_USE_PRIVATEKEY			 174
+#define SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1		 175
+#define SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE		 176
+#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY			 177
+#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1		 178
+#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE		 179
+#define SSL_F_SSL_DO_HANDSHAKE				 180
+#define SSL_F_SSL_GET_NEW_SESSION			 181
+#define SSL_F_SSL_GET_PREV_SESSION			 217
+#define SSL_F_SSL_GET_SERVER_SEND_CERT			 182
+#define SSL_F_SSL_GET_SIGN_PKEY				 183
+#define SSL_F_SSL_INIT_WBIO_BUFFER			 184
+#define SSL_F_SSL_LOAD_CLIENT_CA_FILE			 185
+#define SSL_F_SSL_NEW					 186
+#define SSL_F_SSL_PEEK					 270
+#define SSL_F_SSL_READ					 223
+#define SSL_F_SSL_RSA_PRIVATE_DECRYPT			 187
+#define SSL_F_SSL_RSA_PUBLIC_ENCRYPT			 188
+#define SSL_F_SSL_SESSION_NEW				 189
+#define SSL_F_SSL_SESSION_PRINT_FP			 190
+#define SSL_F_SSL_SESS_CERT_NEW				 225
+#define SSL_F_SSL_SET_CERT				 191
+#define SSL_F_SSL_SET_CIPHER_LIST			 271
+#define SSL_F_SSL_SET_FD				 192
+#define SSL_F_SSL_SET_PKEY				 193
+#define SSL_F_SSL_SET_PURPOSE				 227
+#define SSL_F_SSL_SET_RFD				 194
+#define SSL_F_SSL_SET_SESSION				 195
+#define SSL_F_SSL_SET_SESSION_ID_CONTEXT		 218
+#define SSL_F_SSL_SET_TRUST				 228
+#define SSL_F_SSL_SET_WFD				 196
+#define SSL_F_SSL_SHUTDOWN				 224
+#define SSL_F_SSL_UNDEFINED_CONST_FUNCTION		 243
+#define SSL_F_SSL_UNDEFINED_FUNCTION			 197
+#define SSL_F_SSL_UNDEFINED_VOID_FUNCTION		 244
+#define SSL_F_SSL_USE_CERTIFICATE			 198
+#define SSL_F_SSL_USE_CERTIFICATE_ASN1			 199
+#define SSL_F_SSL_USE_CERTIFICATE_FILE			 200
+#define SSL_F_SSL_USE_PRIVATEKEY			 201
+#define SSL_F_SSL_USE_PRIVATEKEY_ASN1			 202
+#define SSL_F_SSL_USE_PRIVATEKEY_FILE			 203
+#define SSL_F_SSL_USE_RSAPRIVATEKEY			 204
+#define SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1		 205
+#define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE		 206
+#define SSL_F_SSL_VERIFY_CERT_CHAIN			 207
+#define SSL_F_SSL_WRITE					 208
+#define SSL_F_TLS1_CHANGE_CIPHER_STATE			 209
+#define SSL_F_TLS1_ENC					 210
+#define SSL_F_TLS1_SETUP_KEY_BLOCK			 211
+#define SSL_F_WRITE_PENDING				 212
+
+/* Reason codes. */
+#define SSL_R_APP_DATA_IN_HANDSHAKE			 100
+#define SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT 272
+#define SSL_R_BAD_ALERT_RECORD				 101
+#define SSL_R_BAD_AUTHENTICATION_TYPE			 102
+#define SSL_R_BAD_CHANGE_CIPHER_SPEC			 103
+#define SSL_R_BAD_CHECKSUM				 104
+#define SSL_R_BAD_DATA_RETURNED_BY_CALLBACK		 106
+#define SSL_R_BAD_DECOMPRESSION				 107
+#define SSL_R_BAD_DH_G_LENGTH				 108
+#define SSL_R_BAD_DH_PUB_KEY_LENGTH			 109
+#define SSL_R_BAD_DH_P_LENGTH				 110
+#define SSL_R_BAD_DIGEST_LENGTH				 111
+#define SSL_R_BAD_DSA_SIGNATURE				 112
+#define SSL_R_BAD_ECC_CERT				 304
+#define SSL_R_BAD_ECDSA_SIGNATURE			 305
+#define SSL_R_BAD_ECPOINT				 306
+#define SSL_R_BAD_HELLO_REQUEST				 105
+#define SSL_R_BAD_LENGTH				 271
+#define SSL_R_BAD_MAC_DECODE				 113
+#define SSL_R_BAD_MESSAGE_TYPE				 114
+#define SSL_R_BAD_PACKET_LENGTH				 115
+#define SSL_R_BAD_PROTOCOL_VERSION_NUMBER		 116
+#define SSL_R_BAD_RESPONSE_ARGUMENT			 117
+#define SSL_R_BAD_RSA_DECRYPT				 118
+#define SSL_R_BAD_RSA_ENCRYPT				 119
+#define SSL_R_BAD_RSA_E_LENGTH				 120
+#define SSL_R_BAD_RSA_MODULUS_LENGTH			 121
+#define SSL_R_BAD_RSA_SIGNATURE				 122
+#define SSL_R_BAD_SIGNATURE				 123
+#define SSL_R_BAD_SSL_FILETYPE				 124
+#define SSL_R_BAD_SSL_SESSION_ID_LENGTH			 125
+#define SSL_R_BAD_STATE					 126
+#define SSL_R_BAD_WRITE_RETRY				 127
+#define SSL_R_BIO_NOT_SET				 128
+#define SSL_R_BLOCK_CIPHER_PAD_IS_WRONG			 129
+#define SSL_R_BN_LIB					 130
+#define SSL_R_CA_DN_LENGTH_MISMATCH			 131
+#define SSL_R_CA_DN_TOO_LONG				 132
+#define SSL_R_CCS_RECEIVED_EARLY			 133
+#define SSL_R_CERTIFICATE_VERIFY_FAILED			 134
+#define SSL_R_CERT_LENGTH_MISMATCH			 135
+#define SSL_R_CHALLENGE_IS_DIFFERENT			 136
+#define SSL_R_CIPHER_CODE_WRONG_LENGTH			 137
+#define SSL_R_CIPHER_OR_HASH_UNAVAILABLE		 138
+#define SSL_R_CIPHER_TABLE_SRC_ERROR			 139
+#define SSL_R_COMPRESSED_LENGTH_TOO_LONG		 140
+#define SSL_R_COMPRESSION_FAILURE			 141
+#define SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE	 307
+#define SSL_R_COMPRESSION_LIBRARY_ERROR			 142
+#define SSL_R_CONNECTION_ID_IS_DIFFERENT		 143
+#define SSL_R_CONNECTION_TYPE_NOT_SET			 144
+#define SSL_R_COOKIE_MISMATCH				 308
+#define SSL_R_DATA_BETWEEN_CCS_AND_FINISHED		 145
+#define SSL_R_DATA_LENGTH_TOO_LONG			 146
+#define SSL_R_DECRYPTION_FAILED				 147
+#define SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC	 281
+#define SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG		 148
+#define SSL_R_DIGEST_CHECK_FAILED			 149
+#define SSL_R_DUPLICATE_COMPRESSION_ID			 309
+#define SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER		 310
+#define SSL_R_ENCRYPTED_LENGTH_TOO_LONG			 150
+#define SSL_R_ERROR_GENERATING_TMP_RSA_KEY		 282
+#define SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST		 151
+#define SSL_R_EXCESSIVE_MESSAGE_SIZE			 152
+#define SSL_R_EXTRA_DATA_IN_MESSAGE			 153
+#define SSL_R_GOT_A_FIN_BEFORE_A_CCS			 154
+#define SSL_R_HTTPS_PROXY_REQUEST			 155
+#define SSL_R_HTTP_REQUEST				 156
+#define SSL_R_ILLEGAL_PADDING				 283
+#define SSL_R_INVALID_CHALLENGE_LENGTH			 158
+#define SSL_R_INVALID_COMMAND				 280
+#define SSL_R_INVALID_PURPOSE				 278
+#define SSL_R_INVALID_TRUST				 279
+#define SSL_R_KEY_ARG_TOO_LONG				 284
+#define SSL_R_KRB5					 285
+#define SSL_R_KRB5_C_CC_PRINC				 286
+#define SSL_R_KRB5_C_GET_CRED				 287
+#define SSL_R_KRB5_C_INIT				 288
+#define SSL_R_KRB5_C_MK_REQ				 289
+#define SSL_R_KRB5_S_BAD_TICKET				 290
+#define SSL_R_KRB5_S_INIT				 291
+#define SSL_R_KRB5_S_RD_REQ				 292
+#define SSL_R_KRB5_S_TKT_EXPIRED			 293
+#define SSL_R_KRB5_S_TKT_NYV				 294
+#define SSL_R_KRB5_S_TKT_SKEW				 295
+#define SSL_R_LENGTH_MISMATCH				 159
+#define SSL_R_LENGTH_TOO_SHORT				 160
+#define SSL_R_LIBRARY_BUG				 274
+#define SSL_R_LIBRARY_HAS_NO_CIPHERS			 161
+#define SSL_R_MESSAGE_TOO_LONG				 296
+#define SSL_R_MISSING_DH_DSA_CERT			 162
+#define SSL_R_MISSING_DH_KEY				 163
+#define SSL_R_MISSING_DH_RSA_CERT			 164
+#define SSL_R_MISSING_DSA_SIGNING_CERT			 165
+#define SSL_R_MISSING_EXPORT_TMP_DH_KEY			 166
+#define SSL_R_MISSING_EXPORT_TMP_RSA_KEY		 167
+#define SSL_R_MISSING_RSA_CERTIFICATE			 168
+#define SSL_R_MISSING_RSA_ENCRYPTING_CERT		 169
+#define SSL_R_MISSING_RSA_SIGNING_CERT			 170
+#define SSL_R_MISSING_TMP_DH_KEY			 171
+#define SSL_R_MISSING_TMP_ECDH_KEY			 311
+#define SSL_R_MISSING_TMP_RSA_KEY			 172
+#define SSL_R_MISSING_TMP_RSA_PKEY			 173
+#define SSL_R_MISSING_VERIFY_MESSAGE			 174
+#define SSL_R_NON_SSLV2_INITIAL_PACKET			 175
+#define SSL_R_NO_CERTIFICATES_RETURNED			 176
+#define SSL_R_NO_CERTIFICATE_ASSIGNED			 177
+#define SSL_R_NO_CERTIFICATE_RETURNED			 178
+#define SSL_R_NO_CERTIFICATE_SET			 179
+#define SSL_R_NO_CERTIFICATE_SPECIFIED			 180
+#define SSL_R_NO_CIPHERS_AVAILABLE			 181
+#define SSL_R_NO_CIPHERS_PASSED				 182
+#define SSL_R_NO_CIPHERS_SPECIFIED			 183
+#define SSL_R_NO_CIPHER_LIST				 184
+#define SSL_R_NO_CIPHER_MATCH				 185
+#define SSL_R_NO_CLIENT_CERT_RECEIVED			 186
+#define SSL_R_NO_COMPRESSION_SPECIFIED			 187
+#define SSL_R_NO_METHOD_SPECIFIED			 188
+#define SSL_R_NO_PRIVATEKEY				 189
+#define SSL_R_NO_PRIVATE_KEY_ASSIGNED			 190
+#define SSL_R_NO_PROTOCOLS_AVAILABLE			 191
+#define SSL_R_NO_PUBLICKEY				 192
+#define SSL_R_NO_SHARED_CIPHER				 193
+#define SSL_R_NO_VERIFY_CALLBACK			 194
+#define SSL_R_NULL_SSL_CTX				 195
+#define SSL_R_NULL_SSL_METHOD_PASSED			 196
+#define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED		 197
+#define SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE		 297
+#define SSL_R_PACKET_LENGTH_TOO_LONG			 198
+#define SSL_R_PATH_TOO_LONG				 270
+#define SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE		 199
+#define SSL_R_PEER_ERROR				 200
+#define SSL_R_PEER_ERROR_CERTIFICATE			 201
+#define SSL_R_PEER_ERROR_NO_CERTIFICATE			 202
+#define SSL_R_PEER_ERROR_NO_CIPHER			 203
+#define SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE	 204
+#define SSL_R_PRE_MAC_LENGTH_TOO_LONG			 205
+#define SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS		 206
+#define SSL_R_PROTOCOL_IS_SHUTDOWN			 207
+#define SSL_R_PUBLIC_KEY_ENCRYPT_ERROR			 208
+#define SSL_R_PUBLIC_KEY_IS_NOT_RSA			 209
+#define SSL_R_PUBLIC_KEY_NOT_RSA			 210
+#define SSL_R_READ_BIO_NOT_SET				 211
+#define SSL_R_READ_TIMEOUT_EXPIRED			 312
+#define SSL_R_READ_WRONG_PACKET_TYPE			 212
+#define SSL_R_RECORD_LENGTH_MISMATCH			 213
+#define SSL_R_RECORD_TOO_LARGE				 214
+#define SSL_R_RECORD_TOO_SMALL				 298
+#define SSL_R_REQUIRED_CIPHER_MISSING			 215
+#define SSL_R_REUSE_CERT_LENGTH_NOT_ZERO		 216
+#define SSL_R_REUSE_CERT_TYPE_NOT_ZERO			 217
+#define SSL_R_REUSE_CIPHER_LIST_NOT_ZERO		 218
+#define SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED		 277
+#define SSL_R_SHORT_READ				 219
+#define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE	 220
+#define SSL_R_SSL23_DOING_SESSION_ID_REUSE		 221
+#define SSL_R_SSL2_CONNECTION_ID_TOO_LONG		 299
+#define SSL_R_SSL3_SESSION_ID_TOO_LONG			 300
+#define SSL_R_SSL3_SESSION_ID_TOO_SHORT			 222
+#define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE		 1042
+#define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC		 1020
+#define SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED		 1045
+#define SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED		 1044
+#define SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN		 1046
+#define SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE		 1030
+#define SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE		 1040
+#define SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER		 1047
+#define SSL_R_SSLV3_ALERT_NO_CERTIFICATE		 1041
+#define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE		 1010
+#define SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE	 1043
+#define SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION	 228
+#define SSL_R_SSL_HANDSHAKE_FAILURE			 229
+#define SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS		 230
+#define SSL_R_SSL_SESSION_ID_CALLBACK_FAILED		 301
+#define SSL_R_SSL_SESSION_ID_CONFLICT			 302
+#define SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG		 273
+#define SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH		 303
+#define SSL_R_SSL_SESSION_ID_IS_DIFFERENT		 231
+#define SSL_R_TLSV1_ALERT_ACCESS_DENIED			 1049
+#define SSL_R_TLSV1_ALERT_DECODE_ERROR			 1050
+#define SSL_R_TLSV1_ALERT_DECRYPTION_FAILED		 1021
+#define SSL_R_TLSV1_ALERT_DECRYPT_ERROR			 1051
+#define SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION		 1060
+#define SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY		 1071
+#define SSL_R_TLSV1_ALERT_INTERNAL_ERROR		 1080
+#define SSL_R_TLSV1_ALERT_NO_RENEGOTIATION		 1100
+#define SSL_R_TLSV1_ALERT_PROTOCOL_VERSION		 1070
+#define SSL_R_TLSV1_ALERT_RECORD_OVERFLOW		 1022
+#define SSL_R_TLSV1_ALERT_UNKNOWN_CA			 1048
+#define SSL_R_TLSV1_ALERT_USER_CANCELLED		 1090
+#define SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER	 232
+#define SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST 233
+#define SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG	 234
+#define SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER		 235
+#define SSL_R_UNABLE_TO_DECODE_DH_CERTS			 236
+#define SSL_R_UNABLE_TO_DECODE_ECDH_CERTS		 313
+#define SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY		 237
+#define SSL_R_UNABLE_TO_FIND_DH_PARAMETERS		 238
+#define SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS		 314
+#define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS	 239
+#define SSL_R_UNABLE_TO_FIND_SSL_METHOD			 240
+#define SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES		 241
+#define SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES		 242
+#define SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES		 243
+#define SSL_R_UNEXPECTED_MESSAGE			 244
+#define SSL_R_UNEXPECTED_RECORD				 245
+#define SSL_R_UNINITIALIZED				 276
+#define SSL_R_UNKNOWN_ALERT_TYPE			 246
+#define SSL_R_UNKNOWN_CERTIFICATE_TYPE			 247
+#define SSL_R_UNKNOWN_CIPHER_RETURNED			 248
+#define SSL_R_UNKNOWN_CIPHER_TYPE			 249
+#define SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE			 250
+#define SSL_R_UNKNOWN_PKEY_TYPE				 251
+#define SSL_R_UNKNOWN_PROTOCOL				 252
+#define SSL_R_UNKNOWN_REMOTE_ERROR_TYPE			 253
+#define SSL_R_UNKNOWN_SSL_VERSION			 254
+#define SSL_R_UNKNOWN_STATE				 255
+#define SSL_R_UNSUPPORTED_CIPHER			 256
+#define SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM		 257
+#define SSL_R_UNSUPPORTED_ELLIPTIC_CURVE		 315
+#define SSL_R_UNSUPPORTED_PROTOCOL			 258
+#define SSL_R_UNSUPPORTED_SSL_VERSION			 259
+#define SSL_R_WRITE_BIO_NOT_SET				 260
+#define SSL_R_WRONG_CIPHER_RETURNED			 261
+#define SSL_R_WRONG_MESSAGE_TYPE			 262
+#define SSL_R_WRONG_NUMBER_OF_KEY_BITS			 263
+#define SSL_R_WRONG_SIGNATURE_LENGTH			 264
+#define SSL_R_WRONG_SIGNATURE_SIZE			 265
+#define SSL_R_WRONG_SSL_VERSION				 266
+#define SSL_R_WRONG_VERSION_NUMBER			 267
+#define SSL_R_X509_LIB					 268
+#define SSL_R_X509_VERIFICATION_SETUP_PROBLEMS		 269
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/dep/include/openssl/ssl2.h b/dep/include/openssl/ssl2.h
new file mode 100644
index 00000000000..99a52ea0dd9
--- /dev/null
+++ b/dep/include/openssl/ssl2.h
@@ -0,0 +1,268 @@
+/* ssl/ssl2.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_SSL2_H 
+#define HEADER_SSL2_H 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* Protocol Version Codes */
+#define SSL2_VERSION		0x0002
+#define SSL2_VERSION_MAJOR	0x00
+#define SSL2_VERSION_MINOR	0x02
+/* #define SSL2_CLIENT_VERSION	0x0002 */
+/* #define SSL2_SERVER_VERSION	0x0002 */
+
+/* Protocol Message Codes */
+#define SSL2_MT_ERROR			0
+#define SSL2_MT_CLIENT_HELLO		1
+#define SSL2_MT_CLIENT_MASTER_KEY	2
+#define SSL2_MT_CLIENT_FINISHED		3
+#define SSL2_MT_SERVER_HELLO		4
+#define SSL2_MT_SERVER_VERIFY		5
+#define SSL2_MT_SERVER_FINISHED		6
+#define SSL2_MT_REQUEST_CERTIFICATE	7
+#define SSL2_MT_CLIENT_CERTIFICATE	8
+
+/* Error Message Codes */
+#define SSL2_PE_UNDEFINED_ERROR		0x0000
+#define SSL2_PE_NO_CIPHER		0x0001
+#define SSL2_PE_NO_CERTIFICATE		0x0002
+#define SSL2_PE_BAD_CERTIFICATE		0x0004
+#define SSL2_PE_UNSUPPORTED_CERTIFICATE_TYPE 0x0006
+
+/* Cipher Kind Values */
+#define SSL2_CK_NULL_WITH_MD5			0x02000000 /* v3 */
+#define SSL2_CK_RC4_128_WITH_MD5		0x02010080
+#define SSL2_CK_RC4_128_EXPORT40_WITH_MD5	0x02020080
+#define SSL2_CK_RC2_128_CBC_WITH_MD5		0x02030080
+#define SSL2_CK_RC2_128_CBC_EXPORT40_WITH_MD5	0x02040080
+#define SSL2_CK_IDEA_128_CBC_WITH_MD5		0x02050080
+#define SSL2_CK_DES_64_CBC_WITH_MD5		0x02060040
+#define SSL2_CK_DES_64_CBC_WITH_SHA		0x02060140 /* v3 */
+#define SSL2_CK_DES_192_EDE3_CBC_WITH_MD5	0x020700c0
+#define SSL2_CK_DES_192_EDE3_CBC_WITH_SHA	0x020701c0 /* v3 */
+#define SSL2_CK_RC4_64_WITH_MD5			0x02080080 /* MS hack */
+ 
+#define SSL2_CK_DES_64_CFB64_WITH_MD5_1		0x02ff0800 /* SSLeay */
+#define SSL2_CK_NULL				0x02ff0810 /* SSLeay */
+
+#define SSL2_TXT_DES_64_CFB64_WITH_MD5_1	"DES-CFB-M1"
+#define SSL2_TXT_NULL_WITH_MD5			"NULL-MD5"
+#define SSL2_TXT_RC4_128_WITH_MD5		"RC4-MD5"
+#define SSL2_TXT_RC4_128_EXPORT40_WITH_MD5	"EXP-RC4-MD5"
+#define SSL2_TXT_RC2_128_CBC_WITH_MD5		"RC2-CBC-MD5"
+#define SSL2_TXT_RC2_128_CBC_EXPORT40_WITH_MD5	"EXP-RC2-CBC-MD5"
+#define SSL2_TXT_IDEA_128_CBC_WITH_MD5		"IDEA-CBC-MD5"
+#define SSL2_TXT_DES_64_CBC_WITH_MD5		"DES-CBC-MD5"
+#define SSL2_TXT_DES_64_CBC_WITH_SHA		"DES-CBC-SHA"
+#define SSL2_TXT_DES_192_EDE3_CBC_WITH_MD5	"DES-CBC3-MD5"
+#define SSL2_TXT_DES_192_EDE3_CBC_WITH_SHA	"DES-CBC3-SHA"
+#define SSL2_TXT_RC4_64_WITH_MD5		"RC4-64-MD5"
+
+#define SSL2_TXT_NULL				"NULL"
+
+/* Flags for the SSL_CIPHER.algorithm2 field */
+#define SSL2_CF_5_BYTE_ENC			0x01
+#define SSL2_CF_8_BYTE_ENC			0x02
+
+/* Certificate Type Codes */
+#define SSL2_CT_X509_CERTIFICATE		0x01
+
+/* Authentication Type Code */
+#define SSL2_AT_MD5_WITH_RSA_ENCRYPTION		0x01
+
+#define SSL2_MAX_SSL_SESSION_ID_LENGTH		32
+
+/* Upper/Lower Bounds */
+#define SSL2_MAX_MASTER_KEY_LENGTH_IN_BITS	256
+#ifdef OPENSSL_SYS_MPE
+#define SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER	29998u
+#else
+#define SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER	32767u  /* 2^15-1 */
+#endif
+#define SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER	16383 /* 2^14-1 */
+
+#define SSL2_CHALLENGE_LENGTH	16
+/*#define SSL2_CHALLENGE_LENGTH	32 */
+#define SSL2_MIN_CHALLENGE_LENGTH	16
+#define SSL2_MAX_CHALLENGE_LENGTH	32
+#define SSL2_CONNECTION_ID_LENGTH	16
+#define SSL2_MAX_CONNECTION_ID_LENGTH	16
+#define SSL2_SSL_SESSION_ID_LENGTH	16
+#define SSL2_MAX_CERT_CHALLENGE_LENGTH	32
+#define SSL2_MIN_CERT_CHALLENGE_LENGTH	16
+#define SSL2_MAX_KEY_MATERIAL_LENGTH	24
+
+#ifndef HEADER_SSL_LOCL_H
+#define  CERT		char
+#endif
+
+typedef struct ssl2_state_st
+	{
+	int three_byte_header;
+	int clear_text;		/* clear text */
+	int escape;		/* not used in SSLv2 */
+	int ssl2_rollback;	/* used if SSLv23 rolled back to SSLv2 */
+
+	/* non-blocking io info, used to make sure the same
+	 * args were passwd */
+	unsigned int wnum;	/* number of bytes sent so far */
+	int wpend_tot;
+	const unsigned char *wpend_buf;
+
+	int wpend_off;	/* offset to data to write */
+	int wpend_len; 	/* number of bytes passwd to write */
+	int wpend_ret; 	/* number of bytes to return to caller */
+
+	/* buffer raw data */
+	int rbuf_left;
+	int rbuf_offs;
+	unsigned char *rbuf;
+	unsigned char *wbuf;
+
+	unsigned char *write_ptr;/* used to point to the start due to
+				  * 2/3 byte header. */
+
+	unsigned int padding;
+	unsigned int rlength; /* passed to ssl2_enc */
+	int ract_data_length; /* Set when things are encrypted. */
+	unsigned int wlength; /* passed to ssl2_enc */
+	int wact_data_length; /* Set when things are decrypted. */
+	unsigned char *ract_data;
+	unsigned char *wact_data;
+	unsigned char *mac_data;
+
+	unsigned char *read_key;
+	unsigned char *write_key;
+
+		/* Stuff specifically to do with this SSL session */
+	unsigned int challenge_length;
+	unsigned char challenge[SSL2_MAX_CHALLENGE_LENGTH];
+	unsigned int conn_id_length;
+	unsigned char conn_id[SSL2_MAX_CONNECTION_ID_LENGTH];
+	unsigned int key_material_length;
+	unsigned char key_material[SSL2_MAX_KEY_MATERIAL_LENGTH*2];
+
+	unsigned long read_sequence;
+	unsigned long write_sequence;
+
+	struct	{
+		unsigned int conn_id_length;
+		unsigned int cert_type;	
+		unsigned int cert_length;
+		unsigned int csl; 
+		unsigned int clear;
+		unsigned int enc; 
+		unsigned char ccl[SSL2_MAX_CERT_CHALLENGE_LENGTH];
+		unsigned int cipher_spec_length;
+		unsigned int session_id_length;
+		unsigned int clen;
+		unsigned int rlen;
+		} tmp;
+	} SSL2_STATE;
+
+/* SSLv2 */
+/* client */
+#define SSL2_ST_SEND_CLIENT_HELLO_A		(0x10|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_HELLO_B		(0x11|SSL_ST_CONNECT)
+#define SSL2_ST_GET_SERVER_HELLO_A		(0x20|SSL_ST_CONNECT)
+#define SSL2_ST_GET_SERVER_HELLO_B		(0x21|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_MASTER_KEY_A	(0x30|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_MASTER_KEY_B	(0x31|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_FINISHED_A		(0x40|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_FINISHED_B		(0x41|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_CERTIFICATE_A	(0x50|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_CERTIFICATE_B	(0x51|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_CERTIFICATE_C	(0x52|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_CERTIFICATE_D	(0x53|SSL_ST_CONNECT)
+#define SSL2_ST_GET_SERVER_VERIFY_A		(0x60|SSL_ST_CONNECT)
+#define SSL2_ST_GET_SERVER_VERIFY_B		(0x61|SSL_ST_CONNECT)
+#define SSL2_ST_GET_SERVER_FINISHED_A		(0x70|SSL_ST_CONNECT)
+#define SSL2_ST_GET_SERVER_FINISHED_B		(0x71|SSL_ST_CONNECT)
+#define SSL2_ST_CLIENT_START_ENCRYPTION		(0x80|SSL_ST_CONNECT)
+#define SSL2_ST_X509_GET_CLIENT_CERTIFICATE	(0x90|SSL_ST_CONNECT)
+/* server */
+#define SSL2_ST_GET_CLIENT_HELLO_A		(0x10|SSL_ST_ACCEPT)
+#define SSL2_ST_GET_CLIENT_HELLO_B		(0x11|SSL_ST_ACCEPT)
+#define SSL2_ST_GET_CLIENT_HELLO_C		(0x12|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_HELLO_A		(0x20|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_HELLO_B		(0x21|SSL_ST_ACCEPT)
+#define SSL2_ST_GET_CLIENT_MASTER_KEY_A		(0x30|SSL_ST_ACCEPT)
+#define SSL2_ST_GET_CLIENT_MASTER_KEY_B		(0x31|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_VERIFY_A		(0x40|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_VERIFY_B		(0x41|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_VERIFY_C		(0x42|SSL_ST_ACCEPT)
+#define SSL2_ST_GET_CLIENT_FINISHED_A		(0x50|SSL_ST_ACCEPT)
+#define SSL2_ST_GET_CLIENT_FINISHED_B		(0x51|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_FINISHED_A		(0x60|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_FINISHED_B		(0x61|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_REQUEST_CERTIFICATE_A	(0x70|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_REQUEST_CERTIFICATE_B	(0x71|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_REQUEST_CERTIFICATE_C	(0x72|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_REQUEST_CERTIFICATE_D	(0x73|SSL_ST_ACCEPT)
+#define SSL2_ST_SERVER_START_ENCRYPTION		(0x80|SSL_ST_ACCEPT)
+#define SSL2_ST_X509_GET_SERVER_CERTIFICATE	(0x90|SSL_ST_ACCEPT)
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
+
diff --git a/dep/include/openssl/ssl23.h b/dep/include/openssl/ssl23.h
new file mode 100644
index 00000000000..d3228983c75
--- /dev/null
+++ b/dep/include/openssl/ssl23.h
@@ -0,0 +1,83 @@
+/* ssl/ssl23.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_SSL23_H 
+#define HEADER_SSL23_H 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/*client */
+/* write to server */
+#define SSL23_ST_CW_CLNT_HELLO_A	(0x210|SSL_ST_CONNECT)
+#define SSL23_ST_CW_CLNT_HELLO_B	(0x211|SSL_ST_CONNECT)
+/* read from server */
+#define SSL23_ST_CR_SRVR_HELLO_A	(0x220|SSL_ST_CONNECT)
+#define SSL23_ST_CR_SRVR_HELLO_B	(0x221|SSL_ST_CONNECT)
+
+/* server */
+/* read from client */
+#define SSL23_ST_SR_CLNT_HELLO_A	(0x210|SSL_ST_ACCEPT)
+#define SSL23_ST_SR_CLNT_HELLO_B	(0x211|SSL_ST_ACCEPT)
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
+
diff --git a/dep/include/openssl/ssl3.h b/dep/include/openssl/ssl3.h
new file mode 100644
index 00000000000..bacaff157e5
--- /dev/null
+++ b/dep/include/openssl/ssl3.h
@@ -0,0 +1,555 @@
+/* ssl/ssl3.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECC cipher suite support in OpenSSL originally developed by 
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#ifndef HEADER_SSL3_H 
+#define HEADER_SSL3_H 
+
+#ifndef OPENSSL_NO_COMP
+#include 
+#endif
+#include 
+#include 
+#include 
+#include 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#define SSL3_CK_RSA_NULL_MD5			0x03000001
+#define SSL3_CK_RSA_NULL_SHA			0x03000002
+#define SSL3_CK_RSA_RC4_40_MD5 			0x03000003
+#define SSL3_CK_RSA_RC4_128_MD5			0x03000004
+#define SSL3_CK_RSA_RC4_128_SHA			0x03000005
+#define SSL3_CK_RSA_RC2_40_MD5			0x03000006
+#define SSL3_CK_RSA_IDEA_128_SHA		0x03000007
+#define SSL3_CK_RSA_DES_40_CBC_SHA		0x03000008
+#define SSL3_CK_RSA_DES_64_CBC_SHA		0x03000009
+#define SSL3_CK_RSA_DES_192_CBC3_SHA		0x0300000A
+
+#define SSL3_CK_DH_DSS_DES_40_CBC_SHA		0x0300000B
+#define SSL3_CK_DH_DSS_DES_64_CBC_SHA		0x0300000C
+#define SSL3_CK_DH_DSS_DES_192_CBC3_SHA 	0x0300000D
+#define SSL3_CK_DH_RSA_DES_40_CBC_SHA		0x0300000E
+#define SSL3_CK_DH_RSA_DES_64_CBC_SHA		0x0300000F
+#define SSL3_CK_DH_RSA_DES_192_CBC3_SHA 	0x03000010
+
+#define SSL3_CK_EDH_DSS_DES_40_CBC_SHA		0x03000011
+#define SSL3_CK_EDH_DSS_DES_64_CBC_SHA		0x03000012
+#define SSL3_CK_EDH_DSS_DES_192_CBC3_SHA	0x03000013
+#define SSL3_CK_EDH_RSA_DES_40_CBC_SHA		0x03000014
+#define SSL3_CK_EDH_RSA_DES_64_CBC_SHA		0x03000015
+#define SSL3_CK_EDH_RSA_DES_192_CBC3_SHA	0x03000016
+
+#define SSL3_CK_ADH_RC4_40_MD5			0x03000017
+#define SSL3_CK_ADH_RC4_128_MD5			0x03000018
+#define SSL3_CK_ADH_DES_40_CBC_SHA		0x03000019
+#define SSL3_CK_ADH_DES_64_CBC_SHA		0x0300001A
+#define SSL3_CK_ADH_DES_192_CBC_SHA		0x0300001B
+
+#define SSL3_CK_FZA_DMS_NULL_SHA		0x0300001C
+#define SSL3_CK_FZA_DMS_FZA_SHA			0x0300001D
+#if 0 /* Because it clashes with KRB5, is never used any more, and is safe
+	 to remove according to David Hopwood 
+	 of the ietf-tls list */
+#define SSL3_CK_FZA_DMS_RC4_SHA			0x0300001E
+#endif
+
+/*    VRS Additional Kerberos5 entries
+ */
+#define SSL3_CK_KRB5_DES_64_CBC_SHA		0x0300001E
+#define SSL3_CK_KRB5_DES_192_CBC3_SHA		0x0300001F
+#define SSL3_CK_KRB5_RC4_128_SHA		0x03000020
+#define SSL3_CK_KRB5_IDEA_128_CBC_SHA	       	0x03000021
+#define SSL3_CK_KRB5_DES_64_CBC_MD5       	0x03000022
+#define SSL3_CK_KRB5_DES_192_CBC3_MD5       	0x03000023
+#define SSL3_CK_KRB5_RC4_128_MD5	       	0x03000024
+#define SSL3_CK_KRB5_IDEA_128_CBC_MD5 		0x03000025
+
+#define SSL3_CK_KRB5_DES_40_CBC_SHA 		0x03000026
+#define SSL3_CK_KRB5_RC2_40_CBC_SHA 		0x03000027
+#define SSL3_CK_KRB5_RC4_40_SHA	 		0x03000028
+#define SSL3_CK_KRB5_DES_40_CBC_MD5 		0x03000029
+#define SSL3_CK_KRB5_RC2_40_CBC_MD5 		0x0300002A
+#define SSL3_CK_KRB5_RC4_40_MD5	 		0x0300002B
+
+#define SSL3_TXT_RSA_NULL_MD5			"NULL-MD5"
+#define SSL3_TXT_RSA_NULL_SHA			"NULL-SHA"
+#define SSL3_TXT_RSA_RC4_40_MD5 		"EXP-RC4-MD5"
+#define SSL3_TXT_RSA_RC4_128_MD5		"RC4-MD5"
+#define SSL3_TXT_RSA_RC4_128_SHA		"RC4-SHA"
+#define SSL3_TXT_RSA_RC2_40_MD5			"EXP-RC2-CBC-MD5"
+#define SSL3_TXT_RSA_IDEA_128_SHA		"IDEA-CBC-SHA"
+#define SSL3_TXT_RSA_DES_40_CBC_SHA		"EXP-DES-CBC-SHA"
+#define SSL3_TXT_RSA_DES_64_CBC_SHA		"DES-CBC-SHA"
+#define SSL3_TXT_RSA_DES_192_CBC3_SHA		"DES-CBC3-SHA"
+
+#define SSL3_TXT_DH_DSS_DES_40_CBC_SHA		"EXP-DH-DSS-DES-CBC-SHA"
+#define SSL3_TXT_DH_DSS_DES_64_CBC_SHA		"DH-DSS-DES-CBC-SHA"
+#define SSL3_TXT_DH_DSS_DES_192_CBC3_SHA 	"DH-DSS-DES-CBC3-SHA"
+#define SSL3_TXT_DH_RSA_DES_40_CBC_SHA		"EXP-DH-RSA-DES-CBC-SHA"
+#define SSL3_TXT_DH_RSA_DES_64_CBC_SHA		"DH-RSA-DES-CBC-SHA"
+#define SSL3_TXT_DH_RSA_DES_192_CBC3_SHA 	"DH-RSA-DES-CBC3-SHA"
+
+#define SSL3_TXT_EDH_DSS_DES_40_CBC_SHA		"EXP-EDH-DSS-DES-CBC-SHA"
+#define SSL3_TXT_EDH_DSS_DES_64_CBC_SHA		"EDH-DSS-DES-CBC-SHA"
+#define SSL3_TXT_EDH_DSS_DES_192_CBC3_SHA	"EDH-DSS-DES-CBC3-SHA"
+#define SSL3_TXT_EDH_RSA_DES_40_CBC_SHA		"EXP-EDH-RSA-DES-CBC-SHA"
+#define SSL3_TXT_EDH_RSA_DES_64_CBC_SHA		"EDH-RSA-DES-CBC-SHA"
+#define SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA	"EDH-RSA-DES-CBC3-SHA"
+
+#define SSL3_TXT_ADH_RC4_40_MD5			"EXP-ADH-RC4-MD5"
+#define SSL3_TXT_ADH_RC4_128_MD5		"ADH-RC4-MD5"
+#define SSL3_TXT_ADH_DES_40_CBC_SHA		"EXP-ADH-DES-CBC-SHA"
+#define SSL3_TXT_ADH_DES_64_CBC_SHA		"ADH-DES-CBC-SHA"
+#define SSL3_TXT_ADH_DES_192_CBC_SHA		"ADH-DES-CBC3-SHA"
+
+#define SSL3_TXT_FZA_DMS_NULL_SHA		"FZA-NULL-SHA"
+#define SSL3_TXT_FZA_DMS_FZA_SHA		"FZA-FZA-CBC-SHA"
+#define SSL3_TXT_FZA_DMS_RC4_SHA		"FZA-RC4-SHA"
+
+#define SSL3_TXT_KRB5_DES_64_CBC_SHA		"KRB5-DES-CBC-SHA"
+#define SSL3_TXT_KRB5_DES_192_CBC3_SHA		"KRB5-DES-CBC3-SHA"
+#define SSL3_TXT_KRB5_RC4_128_SHA		"KRB5-RC4-SHA"
+#define SSL3_TXT_KRB5_IDEA_128_CBC_SHA	       	"KRB5-IDEA-CBC-SHA"
+#define SSL3_TXT_KRB5_DES_64_CBC_MD5       	"KRB5-DES-CBC-MD5"
+#define SSL3_TXT_KRB5_DES_192_CBC3_MD5       	"KRB5-DES-CBC3-MD5"
+#define SSL3_TXT_KRB5_RC4_128_MD5		"KRB5-RC4-MD5"
+#define SSL3_TXT_KRB5_IDEA_128_CBC_MD5 		"KRB5-IDEA-CBC-MD5"
+
+#define SSL3_TXT_KRB5_DES_40_CBC_SHA 		"EXP-KRB5-DES-CBC-SHA"
+#define SSL3_TXT_KRB5_RC2_40_CBC_SHA 		"EXP-KRB5-RC2-CBC-SHA"
+#define SSL3_TXT_KRB5_RC4_40_SHA	 	"EXP-KRB5-RC4-SHA"
+#define SSL3_TXT_KRB5_DES_40_CBC_MD5 		"EXP-KRB5-DES-CBC-MD5"
+#define SSL3_TXT_KRB5_RC2_40_CBC_MD5 		"EXP-KRB5-RC2-CBC-MD5"
+#define SSL3_TXT_KRB5_RC4_40_MD5	 	"EXP-KRB5-RC4-MD5"
+
+#define SSL3_SSL_SESSION_ID_LENGTH		32
+#define SSL3_MAX_SSL_SESSION_ID_LENGTH		32
+
+#define SSL3_MASTER_SECRET_SIZE			48
+#define SSL3_RANDOM_SIZE			32
+#define SSL3_SESSION_ID_SIZE			32
+#define SSL3_RT_HEADER_LENGTH			5
+
+/* Due to MS stuffing up, this can change.... */
+#if defined(OPENSSL_SYS_WIN16) || \
+	(defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN32))
+#define SSL3_RT_MAX_EXTRA			(14000)
+#else
+#define SSL3_RT_MAX_EXTRA			(16384)
+#endif
+
+#define SSL3_RT_MAX_PLAIN_LENGTH		16384
+#ifdef OPENSSL_NO_COMP
+#define SSL3_RT_MAX_COMPRESSED_LENGTH	SSL3_RT_MAX_PLAIN_LENGTH
+#else
+#define SSL3_RT_MAX_COMPRESSED_LENGTH	(1024+SSL3_RT_MAX_PLAIN_LENGTH)
+#endif
+#define SSL3_RT_MAX_ENCRYPTED_LENGTH	(1024+SSL3_RT_MAX_COMPRESSED_LENGTH)
+#define SSL3_RT_MAX_PACKET_SIZE		(SSL3_RT_MAX_ENCRYPTED_LENGTH+SSL3_RT_HEADER_LENGTH)
+#define SSL3_RT_MAX_DATA_SIZE			(1024*1024)
+
+#define SSL3_MD_CLIENT_FINISHED_CONST	"\x43\x4C\x4E\x54"
+#define SSL3_MD_SERVER_FINISHED_CONST	"\x53\x52\x56\x52"
+
+#define SSL3_VERSION			0x0300
+#define SSL3_VERSION_MAJOR		0x03
+#define SSL3_VERSION_MINOR		0x00
+
+#define SSL3_RT_CHANGE_CIPHER_SPEC	20
+#define SSL3_RT_ALERT			21
+#define SSL3_RT_HANDSHAKE		22
+#define SSL3_RT_APPLICATION_DATA	23
+
+#define SSL3_AL_WARNING			1
+#define SSL3_AL_FATAL			2
+
+#define SSL3_AD_CLOSE_NOTIFY		 0
+#define SSL3_AD_UNEXPECTED_MESSAGE	10	/* fatal */
+#define SSL3_AD_BAD_RECORD_MAC		20	/* fatal */
+#define SSL3_AD_DECOMPRESSION_FAILURE	30	/* fatal */
+#define SSL3_AD_HANDSHAKE_FAILURE	40	/* fatal */
+#define SSL3_AD_NO_CERTIFICATE		41
+#define SSL3_AD_BAD_CERTIFICATE		42
+#define SSL3_AD_UNSUPPORTED_CERTIFICATE	43
+#define SSL3_AD_CERTIFICATE_REVOKED	44
+#define SSL3_AD_CERTIFICATE_EXPIRED	45
+#define SSL3_AD_CERTIFICATE_UNKNOWN	46
+#define SSL3_AD_ILLEGAL_PARAMETER	47	/* fatal */
+
+typedef struct ssl3_record_st
+	{
+/*r */	int type;               /* type of record */
+/*rw*/	unsigned int length;    /* How many bytes available */
+/*r */	unsigned int off;       /* read/write offset into 'buf' */
+/*rw*/	unsigned char *data;    /* pointer to the record data */
+/*rw*/	unsigned char *input;   /* where the decode bytes are */
+/*r */	unsigned char *comp;    /* only used with decompression - malloc()ed */
+/*r */  unsigned long epoch;    /* epoch number, needed by DTLS1 */
+/*r */  PQ_64BIT seq_num;       /* sequence number, needed by DTLS1 */
+	} SSL3_RECORD;
+
+typedef struct ssl3_buffer_st
+	{
+	unsigned char *buf;     /* at least SSL3_RT_MAX_PACKET_SIZE bytes,
+	                         * see ssl3_setup_buffers() */
+	size_t len;             /* buffer size */
+	int offset;             /* where to 'copy from' */
+	int left;               /* how many bytes left */
+	} SSL3_BUFFER;
+
+#define SSL3_CT_RSA_SIGN			1
+#define SSL3_CT_DSS_SIGN			2
+#define SSL3_CT_RSA_FIXED_DH			3
+#define SSL3_CT_DSS_FIXED_DH			4
+#define SSL3_CT_RSA_EPHEMERAL_DH		5
+#define SSL3_CT_DSS_EPHEMERAL_DH		6
+#define SSL3_CT_FORTEZZA_DMS			20
+/* SSL3_CT_NUMBER is used to size arrays and it must be large
+ * enough to contain all of the cert types defined either for
+ * SSLv3 and TLSv1.
+ */
+#define SSL3_CT_NUMBER			7
+
+
+#define SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS	0x0001
+#define SSL3_FLAGS_DELAY_CLIENT_FINISHED	0x0002
+#define SSL3_FLAGS_POP_BUFFER			0x0004
+#define TLS1_FLAGS_TLS_PADDING_BUG		0x0008
+
+typedef struct ssl3_state_st
+	{
+	long flags;
+	int delay_buf_pop_ret;
+
+	unsigned char read_sequence[8];
+	unsigned char read_mac_secret[EVP_MAX_MD_SIZE];
+	unsigned char write_sequence[8];
+	unsigned char write_mac_secret[EVP_MAX_MD_SIZE];
+
+	unsigned char server_random[SSL3_RANDOM_SIZE];
+	unsigned char client_random[SSL3_RANDOM_SIZE];
+
+	/* flags for countermeasure against known-IV weakness */
+	int need_empty_fragments;
+	int empty_fragment_done;
+
+	SSL3_BUFFER rbuf;	/* read IO goes into here */
+	SSL3_BUFFER wbuf;	/* write IO goes into here */
+
+	SSL3_RECORD rrec;	/* each decoded record goes in here */
+	SSL3_RECORD wrec;	/* goes out from here */
+
+	/* storage for Alert/Handshake protocol data received but not
+	 * yet processed by ssl3_read_bytes: */
+	unsigned char alert_fragment[2];
+	unsigned int alert_fragment_len;
+	unsigned char handshake_fragment[4];
+	unsigned int handshake_fragment_len;
+
+	/* partial write - check the numbers match */
+	unsigned int wnum;	/* number of bytes sent so far */
+	int wpend_tot;		/* number bytes written */
+	int wpend_type;
+	int wpend_ret;		/* number of bytes submitted */
+	const unsigned char *wpend_buf;
+
+	/* used during startup, digest all incoming/outgoing packets */
+	EVP_MD_CTX finish_dgst1;
+	EVP_MD_CTX finish_dgst2;
+
+	/* this is set whenerver we see a change_cipher_spec message
+	 * come in when we are not looking for one */
+	int change_cipher_spec;
+
+	int warn_alert;
+	int fatal_alert;
+	/* we allow one fatal and one warning alert to be outstanding,
+	 * send close alert via the warning alert */
+	int alert_dispatch;
+	unsigned char send_alert[2];
+
+	/* This flag is set when we should renegotiate ASAP, basically when
+	 * there is no more data in the read or write buffers */
+	int renegotiate;
+	int total_renegotiations;
+	int num_renegotiations;
+
+	int in_read_app_data;
+
+	struct	{
+		/* actually only needs to be 16+20 */
+		unsigned char cert_verify_md[EVP_MAX_MD_SIZE*2];
+
+		/* actually only need to be 16+20 for SSLv3 and 12 for TLS */
+		unsigned char finish_md[EVP_MAX_MD_SIZE*2];
+		int finish_md_len;
+		unsigned char peer_finish_md[EVP_MAX_MD_SIZE*2];
+		int peer_finish_md_len;
+		
+		unsigned long message_size;
+		int message_type;
+
+		/* used to hold the new cipher we are going to use */
+		SSL_CIPHER *new_cipher;
+#ifndef OPENSSL_NO_DH
+		DH *dh;
+#endif
+
+#ifndef OPENSSL_NO_ECDH
+		EC_KEY *ecdh; /* holds short lived ECDH key */
+#endif
+
+		/* used when SSL_ST_FLUSH_DATA is entered */
+		int next_state;			
+
+		int reuse_message;
+
+		/* used for certificate requests */
+		int cert_req;
+		int ctype_num;
+		char ctype[SSL3_CT_NUMBER];
+		STACK_OF(X509_NAME) *ca_names;
+
+		int use_rsa_tmp;
+
+		int key_block_length;
+		unsigned char *key_block;
+
+		const EVP_CIPHER *new_sym_enc;
+		const EVP_MD *new_hash;
+#ifndef OPENSSL_NO_COMP
+		const SSL_COMP *new_compression;
+#else
+		char *new_compression;
+#endif
+		int cert_request;
+		} tmp;
+
+	} SSL3_STATE;
+
+
+/* SSLv3 */
+/*client */
+/* extra state */
+#define SSL3_ST_CW_FLUSH		(0x100|SSL_ST_CONNECT)
+/* write to server */
+#define SSL3_ST_CW_CLNT_HELLO_A		(0x110|SSL_ST_CONNECT)
+#define SSL3_ST_CW_CLNT_HELLO_B		(0x111|SSL_ST_CONNECT)
+/* read from server */
+#define SSL3_ST_CR_SRVR_HELLO_A		(0x120|SSL_ST_CONNECT)
+#define SSL3_ST_CR_SRVR_HELLO_B		(0x121|SSL_ST_CONNECT)
+#define DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A (0x126|SSL_ST_CONNECT)
+#define DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B (0x127|SSL_ST_CONNECT)
+#define SSL3_ST_CR_CERT_A		(0x130|SSL_ST_CONNECT)
+#define SSL3_ST_CR_CERT_B		(0x131|SSL_ST_CONNECT)
+#define SSL3_ST_CR_KEY_EXCH_A		(0x140|SSL_ST_CONNECT)
+#define SSL3_ST_CR_KEY_EXCH_B		(0x141|SSL_ST_CONNECT)
+#define SSL3_ST_CR_CERT_REQ_A		(0x150|SSL_ST_CONNECT)
+#define SSL3_ST_CR_CERT_REQ_B		(0x151|SSL_ST_CONNECT)
+#define SSL3_ST_CR_SRVR_DONE_A		(0x160|SSL_ST_CONNECT)
+#define SSL3_ST_CR_SRVR_DONE_B		(0x161|SSL_ST_CONNECT)
+/* write to server */
+#define SSL3_ST_CW_CERT_A		(0x170|SSL_ST_CONNECT)
+#define SSL3_ST_CW_CERT_B		(0x171|SSL_ST_CONNECT)
+#define SSL3_ST_CW_CERT_C		(0x172|SSL_ST_CONNECT)
+#define SSL3_ST_CW_CERT_D		(0x173|SSL_ST_CONNECT)
+#define SSL3_ST_CW_KEY_EXCH_A		(0x180|SSL_ST_CONNECT)
+#define SSL3_ST_CW_KEY_EXCH_B		(0x181|SSL_ST_CONNECT)
+#define SSL3_ST_CW_CERT_VRFY_A		(0x190|SSL_ST_CONNECT)
+#define SSL3_ST_CW_CERT_VRFY_B		(0x191|SSL_ST_CONNECT)
+#define SSL3_ST_CW_CHANGE_A		(0x1A0|SSL_ST_CONNECT)
+#define SSL3_ST_CW_CHANGE_B		(0x1A1|SSL_ST_CONNECT)
+#define SSL3_ST_CW_FINISHED_A		(0x1B0|SSL_ST_CONNECT)
+#define SSL3_ST_CW_FINISHED_B		(0x1B1|SSL_ST_CONNECT)
+/* read from server */
+#define SSL3_ST_CR_CHANGE_A		(0x1C0|SSL_ST_CONNECT)
+#define SSL3_ST_CR_CHANGE_B		(0x1C1|SSL_ST_CONNECT)
+#define SSL3_ST_CR_FINISHED_A		(0x1D0|SSL_ST_CONNECT)
+#define SSL3_ST_CR_FINISHED_B		(0x1D1|SSL_ST_CONNECT)
+
+/* server */
+/* extra state */
+#define SSL3_ST_SW_FLUSH		(0x100|SSL_ST_ACCEPT)
+/* read from client */
+/* Do not change the number values, they do matter */
+#define SSL3_ST_SR_CLNT_HELLO_A		(0x110|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_CLNT_HELLO_B		(0x111|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_CLNT_HELLO_C		(0x112|SSL_ST_ACCEPT)
+/* write to client */
+#define DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A (0x113|SSL_ST_ACCEPT)
+#define DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B (0x114|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_HELLO_REQ_A		(0x120|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_HELLO_REQ_B		(0x121|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_HELLO_REQ_C		(0x122|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_SRVR_HELLO_A		(0x130|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_SRVR_HELLO_B		(0x131|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_CERT_A		(0x140|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_CERT_B		(0x141|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_KEY_EXCH_A		(0x150|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_KEY_EXCH_B		(0x151|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_CERT_REQ_A		(0x160|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_CERT_REQ_B		(0x161|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_SRVR_DONE_A		(0x170|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_SRVR_DONE_B		(0x171|SSL_ST_ACCEPT)
+/* read from client */
+#define SSL3_ST_SR_CERT_A		(0x180|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_CERT_B		(0x181|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_KEY_EXCH_A		(0x190|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_KEY_EXCH_B		(0x191|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_CERT_VRFY_A		(0x1A0|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_CERT_VRFY_B		(0x1A1|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_CHANGE_A		(0x1B0|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_CHANGE_B		(0x1B1|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_FINISHED_A		(0x1C0|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_FINISHED_B		(0x1C1|SSL_ST_ACCEPT)
+/* write to client */
+#define SSL3_ST_SW_CHANGE_A		(0x1D0|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_CHANGE_B		(0x1D1|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_FINISHED_A		(0x1E0|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_FINISHED_B		(0x1E1|SSL_ST_ACCEPT)
+
+#define SSL3_MT_HELLO_REQUEST			0
+#define SSL3_MT_CLIENT_HELLO			1
+#define SSL3_MT_SERVER_HELLO			2
+#define SSL3_MT_CERTIFICATE			11
+#define SSL3_MT_SERVER_KEY_EXCHANGE		12
+#define SSL3_MT_CERTIFICATE_REQUEST		13
+#define SSL3_MT_SERVER_DONE			14
+#define SSL3_MT_CERTIFICATE_VERIFY		15
+#define SSL3_MT_CLIENT_KEY_EXCHANGE		16
+#define SSL3_MT_FINISHED			20
+#define DTLS1_MT_HELLO_VERIFY_REQUEST    3
+
+
+#define SSL3_MT_CCS				1
+
+/* These are used when changing over to a new cipher */
+#define SSL3_CC_READ		0x01
+#define SSL3_CC_WRITE		0x02
+#define SSL3_CC_CLIENT		0x10
+#define SSL3_CC_SERVER		0x20
+#define SSL3_CHANGE_CIPHER_CLIENT_WRITE	(SSL3_CC_CLIENT|SSL3_CC_WRITE)	
+#define SSL3_CHANGE_CIPHER_SERVER_READ	(SSL3_CC_SERVER|SSL3_CC_READ)
+#define SSL3_CHANGE_CIPHER_CLIENT_READ	(SSL3_CC_CLIENT|SSL3_CC_READ)
+#define SSL3_CHANGE_CIPHER_SERVER_WRITE	(SSL3_CC_SERVER|SSL3_CC_WRITE)
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
+
diff --git a/dep/include/openssl/stack.h b/dep/include/openssl/stack.h
new file mode 100644
index 00000000000..5cbb116a8b2
--- /dev/null
+++ b/dep/include/openssl/stack.h
@@ -0,0 +1,109 @@
+/* crypto/stack/stack.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_STACK_H
+#define HEADER_STACK_H
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+typedef struct stack_st
+	{
+	int num;
+	char **data;
+	int sorted;
+
+	int num_alloc;
+	int (*comp)(const char * const *, const char * const *);
+	} STACK;
+
+#define M_sk_num(sk)		((sk) ? (sk)->num:-1)
+#define M_sk_value(sk,n)	((sk) ? (sk)->data[n] : NULL)
+
+int sk_num(const STACK *);
+char *sk_value(const STACK *, int);
+
+char *sk_set(STACK *, int, char *);
+
+STACK *sk_new(int (*cmp)(const char * const *, const char * const *));
+STACK *sk_new_null(void);
+void sk_free(STACK *);
+void sk_pop_free(STACK *st, void (*func)(void *));
+int sk_insert(STACK *sk,char *data,int where);
+char *sk_delete(STACK *st,int loc);
+char *sk_delete_ptr(STACK *st, char *p);
+int sk_find(STACK *st,char *data);
+int sk_find_ex(STACK *st,char *data);
+int sk_push(STACK *st,char *data);
+int sk_unshift(STACK *st,char *data);
+char *sk_shift(STACK *st);
+char *sk_pop(STACK *st);
+void sk_zero(STACK *st);
+int (*sk_set_cmp_func(STACK *sk, int (*c)(const char * const *,
+			const char * const *)))
+			(const char * const *, const char * const *);
+STACK *sk_dup(STACK *st);
+void sk_sort(STACK *st);
+int sk_is_sorted(const STACK *st);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff --git a/dep/include/openssl/store.h b/dep/include/openssl/store.h
new file mode 100644
index 00000000000..64583377a94
--- /dev/null
+++ b/dep/include/openssl/store.h
@@ -0,0 +1,554 @@
+/* crypto/store/store.h -*- mode:C; c-file-style: "eay" -*- */
+/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL
+ * project 2003.
+ */
+/* ====================================================================
+ * Copyright (c) 2003 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_STORE_H
+#define HEADER_STORE_H
+
+#include 
+#ifndef OPENSSL_NO_DEPRECATED
+#include 
+#include 
+#include 
+#endif
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* Already defined in ossl_typ.h */
+/* typedef struct store_st STORE; */
+/* typedef struct store_method_st STORE_METHOD; */
+
+
+/* All the following functions return 0, a negative number or NULL on error.
+   When everything is fine, they return a positive value or a non-NULL
+   pointer, all depending on their purpose. */
+
+/* Creators and destructor.   */
+STORE *STORE_new_method(const STORE_METHOD *method);
+STORE *STORE_new_engine(ENGINE *engine);
+void STORE_free(STORE *ui);
+
+
+/* Give a user interface parametrised control commands.  This can be used to
+   send down an integer, a data pointer or a function pointer, as well as
+   be used to get information from a STORE. */
+int STORE_ctrl(STORE *store, int cmd, long i, void *p, void (*f)(void));
+
+/* A control to set the directory with keys and certificates.  Used by the
+   built-in directory level method. */
+#define STORE_CTRL_SET_DIRECTORY	0x0001
+/* A control to set a file to load.  Used by the built-in file level method. */
+#define STORE_CTRL_SET_FILE		0x0002
+/* A control to set a configuration file to load.  Can be used by any method
+   that wishes to load a configuration file. */
+#define STORE_CTRL_SET_CONF_FILE	0x0003
+/* A control to set a the section of the loaded configuration file.  Can be
+   used by any method that wishes to load a configuration file. */
+#define STORE_CTRL_SET_CONF_SECTION	0x0004
+
+
+/* Some methods may use extra data */
+#define STORE_set_app_data(s,arg)	STORE_set_ex_data(s,0,arg)
+#define STORE_get_app_data(s)		STORE_get_ex_data(s,0)
+int STORE_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+	CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int STORE_set_ex_data(STORE *r,int idx,void *arg);
+void *STORE_get_ex_data(STORE *r, int idx);
+
+/* Use specific methods instead of the built-in one */
+const STORE_METHOD *STORE_get_method(STORE *store);
+const STORE_METHOD *STORE_set_method(STORE *store, const STORE_METHOD *meth);
+
+/* The standard OpenSSL methods. */
+/* This is the in-memory method.  It does everything except revoking and updating,
+   and is of course volatile.  It's used by other methods that have an in-memory
+   cache. */
+const STORE_METHOD *STORE_Memory(void);
+#if 0 /* Not yet implemented */
+/* This is the directory store.  It does everything except revoking and updating,
+   and uses STORE_Memory() to cache things in memory. */
+const STORE_METHOD *STORE_Directory(void);
+/* This is the file store.  It does everything except revoking and updating,
+   and uses STORE_Memory() to cache things in memory.  Certificates are added
+   to it with the store operation, and it will only get cached certificates. */
+const STORE_METHOD *STORE_File(void);
+#endif
+
+/* Store functions take a type code for the type of data they should store
+   or fetch */
+typedef enum STORE_object_types
+	{
+	STORE_OBJECT_TYPE_X509_CERTIFICATE=	0x01, /* X509 * */
+	STORE_OBJECT_TYPE_X509_CRL=		0x02, /* X509_CRL * */
+	STORE_OBJECT_TYPE_PRIVATE_KEY=		0x03, /* EVP_PKEY * */
+	STORE_OBJECT_TYPE_PUBLIC_KEY=		0x04, /* EVP_PKEY * */
+	STORE_OBJECT_TYPE_NUMBER=		0x05, /* BIGNUM * */
+	STORE_OBJECT_TYPE_ARBITRARY=		0x06, /* BUF_MEM * */
+	STORE_OBJECT_TYPE_NUM=			0x06  /* The amount of known
+							 object types */
+	} STORE_OBJECT_TYPES;
+/* List of text strings corresponding to the object types. */
+extern const char * const STORE_object_type_string[STORE_OBJECT_TYPE_NUM+1];
+
+/* Some store functions take a parameter list.  Those parameters come with
+   one of the following codes. The comments following the codes below indicate
+   what type the value should be a pointer to. */
+typedef enum STORE_params
+	{
+	STORE_PARAM_EVP_TYPE=			0x01, /* int */
+	STORE_PARAM_BITS=			0x02, /* size_t */
+	STORE_PARAM_KEY_PARAMETERS=		0x03, /* ??? */
+	STORE_PARAM_KEY_NO_PARAMETERS=		0x04, /* N/A */
+	STORE_PARAM_AUTH_PASSPHRASE=		0x05, /* char * */
+	STORE_PARAM_AUTH_KRB5_TICKET=		0x06, /* void * */
+	STORE_PARAM_TYPE_NUM=			0x06  /* The amount of known
+							 parameter types */
+	} STORE_PARAM_TYPES;
+/* Parameter value sizes.  -1 means unknown, anything else is the required size. */
+extern const int STORE_param_sizes[STORE_PARAM_TYPE_NUM+1];
+
+/* Store functions take attribute lists.  Those attributes come with codes.
+   The comments following the codes below indicate what type the value should
+   be a pointer to. */
+typedef enum STORE_attribs
+	{
+	STORE_ATTR_END=				0x00,
+	STORE_ATTR_FRIENDLYNAME=		0x01, /* C string */
+	STORE_ATTR_KEYID=			0x02, /* 160 bit string (SHA1) */
+	STORE_ATTR_ISSUERKEYID=			0x03, /* 160 bit string (SHA1) */
+	STORE_ATTR_SUBJECTKEYID=		0x04, /* 160 bit string (SHA1) */
+	STORE_ATTR_ISSUERSERIALHASH=		0x05, /* 160 bit string (SHA1) */
+	STORE_ATTR_ISSUER=			0x06, /* X509_NAME * */
+	STORE_ATTR_SERIAL=			0x07, /* BIGNUM * */
+	STORE_ATTR_SUBJECT=			0x08, /* X509_NAME * */
+	STORE_ATTR_CERTHASH=			0x09, /* 160 bit string (SHA1) */
+	STORE_ATTR_EMAIL=			0x0a, /* C string */
+	STORE_ATTR_FILENAME=			0x0b, /* C string */
+	STORE_ATTR_TYPE_NUM=			0x0b, /* The amount of known
+							 attribute types */
+	STORE_ATTR_OR=				0xff  /* This is a special
+							 separator, which
+							 expresses the OR
+							 operation.  */
+	} STORE_ATTR_TYPES;
+/* Attribute value sizes.  -1 means unknown, anything else is the required size. */
+extern const int STORE_attr_sizes[STORE_ATTR_TYPE_NUM+1];
+
+typedef enum STORE_certificate_status
+	{
+	STORE_X509_VALID=			0x00,
+	STORE_X509_EXPIRED=			0x01,
+	STORE_X509_SUSPENDED=			0x02,
+	STORE_X509_REVOKED=			0x03
+	} STORE_CERTIFICATE_STATUS;
+
+/* Engine store functions will return a structure that contains all the necessary
+ * information, including revokation status for certificates.  This is really not
+ * needed for application authors, as the ENGINE framework functions will extract
+ * the OpenSSL-specific information when at all possible.  However, for engine
+ * authors, it's crucial to know this structure.  */
+typedef struct STORE_OBJECT_st
+	{
+	STORE_OBJECT_TYPES type;
+	union
+		{
+		struct
+			{
+			STORE_CERTIFICATE_STATUS status;
+			X509 *certificate;
+			} x509;
+		X509_CRL *crl;
+		EVP_PKEY *key;
+		BIGNUM *number;
+		BUF_MEM *arbitrary;
+		} data;
+	} STORE_OBJECT;
+DECLARE_STACK_OF(STORE_OBJECT)
+STORE_OBJECT *STORE_OBJECT_new(void);
+void STORE_OBJECT_free(STORE_OBJECT *data);
+
+
+
+/* The following functions handle the storage. They return 0, a negative number
+   or NULL on error, anything else on success. */
+X509 *STORE_get_certificate(STORE *e, OPENSSL_ITEM attributes[],
+	OPENSSL_ITEM parameters[]);
+int STORE_store_certificate(STORE *e, X509 *data, OPENSSL_ITEM attributes[],
+	OPENSSL_ITEM parameters[]);
+int STORE_modify_certificate(STORE *e, OPENSSL_ITEM search_attributes[],
+	OPENSSL_ITEM add_attributes[], OPENSSL_ITEM modify_attributes[],
+	OPENSSL_ITEM delete_attributes[], OPENSSL_ITEM parameters[]);
+int STORE_revoke_certificate(STORE *e, OPENSSL_ITEM attributes[],
+	OPENSSL_ITEM parameters[]);
+int STORE_delete_certificate(STORE *e, OPENSSL_ITEM attributes[],
+	OPENSSL_ITEM parameters[]);
+void *STORE_list_certificate_start(STORE *e, OPENSSL_ITEM attributes[],
+	OPENSSL_ITEM parameters[]);
+X509 *STORE_list_certificate_next(STORE *e, void *handle);
+int STORE_list_certificate_end(STORE *e, void *handle);
+int STORE_list_certificate_endp(STORE *e, void *handle);
+EVP_PKEY *STORE_generate_key(STORE *e, OPENSSL_ITEM attributes[],
+	OPENSSL_ITEM parameters[]);
+EVP_PKEY *STORE_get_private_key(STORE *e, OPENSSL_ITEM attributes[],
+	OPENSSL_ITEM parameters[]);
+int STORE_store_private_key(STORE *e, EVP_PKEY *data,
+	OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
+int STORE_modify_private_key(STORE *e, OPENSSL_ITEM search_attributes[],
+	OPENSSL_ITEM add_sttributes[], OPENSSL_ITEM modify_attributes[],
+	OPENSSL_ITEM delete_attributes[], OPENSSL_ITEM parameters[]);
+int STORE_revoke_private_key(STORE *e, OPENSSL_ITEM attributes[],
+	OPENSSL_ITEM parameters[]);
+int STORE_delete_private_key(STORE *e, OPENSSL_ITEM attributes[],
+	OPENSSL_ITEM parameters[]);
+void *STORE_list_private_key_start(STORE *e, OPENSSL_ITEM attributes[],
+	OPENSSL_ITEM parameters[]);
+EVP_PKEY *STORE_list_private_key_next(STORE *e, void *handle);
+int STORE_list_private_key_end(STORE *e, void *handle);
+int STORE_list_private_key_endp(STORE *e, void *handle);
+EVP_PKEY *STORE_get_public_key(STORE *e, OPENSSL_ITEM attributes[],
+	OPENSSL_ITEM parameters[]);
+int STORE_store_public_key(STORE *e, EVP_PKEY *data, OPENSSL_ITEM attributes[],
+	OPENSSL_ITEM parameters[]);
+int STORE_modify_public_key(STORE *e, OPENSSL_ITEM search_attributes[],
+	OPENSSL_ITEM add_sttributes[], OPENSSL_ITEM modify_attributes[],
+	OPENSSL_ITEM delete_attributes[], OPENSSL_ITEM parameters[]);
+int STORE_revoke_public_key(STORE *e, OPENSSL_ITEM attributes[],
+	OPENSSL_ITEM parameters[]);
+int STORE_delete_public_key(STORE *e, OPENSSL_ITEM attributes[],
+	OPENSSL_ITEM parameters[]);
+void *STORE_list_public_key_start(STORE *e, OPENSSL_ITEM attributes[],
+	OPENSSL_ITEM parameters[]);
+EVP_PKEY *STORE_list_public_key_next(STORE *e, void *handle);
+int STORE_list_public_key_end(STORE *e, void *handle);
+int STORE_list_public_key_endp(STORE *e, void *handle);
+X509_CRL *STORE_generate_crl(STORE *e, OPENSSL_ITEM attributes[],
+	OPENSSL_ITEM parameters[]);
+X509_CRL *STORE_get_crl(STORE *e, OPENSSL_ITEM attributes[],
+	OPENSSL_ITEM parameters[]);
+int STORE_store_crl(STORE *e, X509_CRL *data, OPENSSL_ITEM attributes[],
+	OPENSSL_ITEM parameters[]);
+int STORE_modify_crl(STORE *e, OPENSSL_ITEM search_attributes[],
+	OPENSSL_ITEM add_sttributes[], OPENSSL_ITEM modify_attributes[],
+	OPENSSL_ITEM delete_attributes[], OPENSSL_ITEM parameters[]);
+int STORE_delete_crl(STORE *e, OPENSSL_ITEM attributes[],
+	OPENSSL_ITEM parameters[]);
+void *STORE_list_crl_start(STORE *e, OPENSSL_ITEM attributes[],
+	OPENSSL_ITEM parameters[]);
+X509_CRL *STORE_list_crl_next(STORE *e, void *handle);
+int STORE_list_crl_end(STORE *e, void *handle);
+int STORE_list_crl_endp(STORE *e, void *handle);
+int STORE_store_number(STORE *e, BIGNUM *data, OPENSSL_ITEM attributes[],
+	OPENSSL_ITEM parameters[]);
+int STORE_modify_number(STORE *e, OPENSSL_ITEM search_attributes[],
+	OPENSSL_ITEM add_sttributes[], OPENSSL_ITEM modify_attributes[],
+	OPENSSL_ITEM delete_attributes[], OPENSSL_ITEM parameters[]);
+BIGNUM *STORE_get_number(STORE *e, OPENSSL_ITEM attributes[],
+	OPENSSL_ITEM parameters[]);
+int STORE_delete_number(STORE *e, OPENSSL_ITEM attributes[],
+	OPENSSL_ITEM parameters[]);
+int STORE_store_arbitrary(STORE *e, BUF_MEM *data, OPENSSL_ITEM attributes[],
+	OPENSSL_ITEM parameters[]);
+int STORE_modify_arbitrary(STORE *e, OPENSSL_ITEM search_attributes[],
+	OPENSSL_ITEM add_sttributes[], OPENSSL_ITEM modify_attributes[],
+	OPENSSL_ITEM delete_attributes[], OPENSSL_ITEM parameters[]);
+BUF_MEM *STORE_get_arbitrary(STORE *e, OPENSSL_ITEM attributes[],
+	OPENSSL_ITEM parameters[]);
+int STORE_delete_arbitrary(STORE *e, OPENSSL_ITEM attributes[],
+	OPENSSL_ITEM parameters[]);
+
+
+/* Create and manipulate methods */
+STORE_METHOD *STORE_create_method(char *name);
+void STORE_destroy_method(STORE_METHOD *store_method);
+
+/* These callback types are use for store handlers */
+typedef int (*STORE_INITIALISE_FUNC_PTR)(STORE *);
+typedef void (*STORE_CLEANUP_FUNC_PTR)(STORE *);
+typedef STORE_OBJECT *(*STORE_GENERATE_OBJECT_FUNC_PTR)(STORE *, STORE_OBJECT_TYPES type, OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
+typedef STORE_OBJECT *(*STORE_GET_OBJECT_FUNC_PTR)(STORE *, STORE_OBJECT_TYPES type, OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
+typedef void *(*STORE_START_OBJECT_FUNC_PTR)(STORE *, STORE_OBJECT_TYPES type, OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
+typedef STORE_OBJECT *(*STORE_NEXT_OBJECT_FUNC_PTR)(STORE *, void *handle);
+typedef int (*STORE_END_OBJECT_FUNC_PTR)(STORE *, void *handle);
+typedef int (*STORE_HANDLE_OBJECT_FUNC_PTR)(STORE *, STORE_OBJECT_TYPES type, OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
+typedef int (*STORE_STORE_OBJECT_FUNC_PTR)(STORE *, STORE_OBJECT_TYPES type, STORE_OBJECT *data, OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
+typedef int (*STORE_MODIFY_OBJECT_FUNC_PTR)(STORE *, STORE_OBJECT_TYPES type, OPENSSL_ITEM search_attributes[], OPENSSL_ITEM add_attributes[], OPENSSL_ITEM modify_attributes[], OPENSSL_ITEM delete_attributes[], OPENSSL_ITEM parameters[]);
+typedef int (*STORE_GENERIC_FUNC_PTR)(STORE *, OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
+typedef int (*STORE_CTRL_FUNC_PTR)(STORE *, int cmd, long l, void *p, void (*f)(void));
+
+int STORE_method_set_initialise_function(STORE_METHOD *sm, STORE_INITIALISE_FUNC_PTR init_f);
+int STORE_method_set_cleanup_function(STORE_METHOD *sm, STORE_CLEANUP_FUNC_PTR clean_f);
+int STORE_method_set_generate_function(STORE_METHOD *sm, STORE_GENERATE_OBJECT_FUNC_PTR generate_f);
+int STORE_method_set_get_function(STORE_METHOD *sm, STORE_GET_OBJECT_FUNC_PTR get_f);
+int STORE_method_set_store_function(STORE_METHOD *sm, STORE_STORE_OBJECT_FUNC_PTR store_f);
+int STORE_method_set_modify_function(STORE_METHOD *sm, STORE_MODIFY_OBJECT_FUNC_PTR store_f);
+int STORE_method_set_revoke_function(STORE_METHOD *sm, STORE_HANDLE_OBJECT_FUNC_PTR revoke_f);
+int STORE_method_set_delete_function(STORE_METHOD *sm, STORE_HANDLE_OBJECT_FUNC_PTR delete_f);
+int STORE_method_set_list_start_function(STORE_METHOD *sm, STORE_START_OBJECT_FUNC_PTR list_start_f);
+int STORE_method_set_list_next_function(STORE_METHOD *sm, STORE_NEXT_OBJECT_FUNC_PTR list_next_f);
+int STORE_method_set_list_end_function(STORE_METHOD *sm, STORE_END_OBJECT_FUNC_PTR list_end_f);
+int STORE_method_set_update_store_function(STORE_METHOD *sm, STORE_GENERIC_FUNC_PTR);
+int STORE_method_set_lock_store_function(STORE_METHOD *sm, STORE_GENERIC_FUNC_PTR);
+int STORE_method_set_unlock_store_function(STORE_METHOD *sm, STORE_GENERIC_FUNC_PTR);
+int STORE_method_set_ctrl_function(STORE_METHOD *sm, STORE_CTRL_FUNC_PTR ctrl_f);
+
+STORE_INITIALISE_FUNC_PTR STORE_method_get_initialise_function(STORE_METHOD *sm);
+STORE_CLEANUP_FUNC_PTR STORE_method_get_cleanup_function(STORE_METHOD *sm);
+STORE_GENERATE_OBJECT_FUNC_PTR STORE_method_get_generate_function(STORE_METHOD *sm);
+STORE_GET_OBJECT_FUNC_PTR STORE_method_get_get_function(STORE_METHOD *sm);
+STORE_STORE_OBJECT_FUNC_PTR STORE_method_get_store_function(STORE_METHOD *sm);
+STORE_MODIFY_OBJECT_FUNC_PTR STORE_method_get_modify_function(STORE_METHOD *sm);
+STORE_HANDLE_OBJECT_FUNC_PTR STORE_method_get_revoke_function(STORE_METHOD *sm);
+STORE_HANDLE_OBJECT_FUNC_PTR STORE_method_get_delete_function(STORE_METHOD *sm);
+STORE_START_OBJECT_FUNC_PTR STORE_method_get_list_start_function(STORE_METHOD *sm);
+STORE_NEXT_OBJECT_FUNC_PTR STORE_method_get_list_next_function(STORE_METHOD *sm);
+STORE_END_OBJECT_FUNC_PTR STORE_method_get_list_end_function(STORE_METHOD *sm);
+STORE_GENERIC_FUNC_PTR STORE_method_get_update_store_function(STORE_METHOD *sm);
+STORE_GENERIC_FUNC_PTR STORE_method_get_lock_store_function(STORE_METHOD *sm);
+STORE_GENERIC_FUNC_PTR STORE_method_get_unlock_store_function(STORE_METHOD *sm);
+STORE_CTRL_FUNC_PTR STORE_method_get_ctrl_function(STORE_METHOD *sm);
+
+/* Method helper structures and functions. */
+
+/* This structure is the result of parsing through the information in a list
+   of OPENSSL_ITEMs.  It stores all the necessary information in a structured
+   way.*/
+typedef struct STORE_attr_info_st STORE_ATTR_INFO;
+
+/* Parse a list of OPENSSL_ITEMs and return a pointer to a STORE_ATTR_INFO.
+   Note that we do this in the list form, since the list of OPENSSL_ITEMs can
+   come in blocks separated with STORE_ATTR_OR.  Note that the value returned
+   by STORE_parse_attrs_next() must be freed with STORE_ATTR_INFO_free(). */
+void *STORE_parse_attrs_start(OPENSSL_ITEM *attributes);
+STORE_ATTR_INFO *STORE_parse_attrs_next(void *handle);
+int STORE_parse_attrs_end(void *handle);
+int STORE_parse_attrs_endp(void *handle);
+
+/* Creator and destructor */
+STORE_ATTR_INFO *STORE_ATTR_INFO_new(void);
+int STORE_ATTR_INFO_free(STORE_ATTR_INFO *attrs);
+
+/* Manipulators */
+char *STORE_ATTR_INFO_get0_cstr(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code);
+unsigned char *STORE_ATTR_INFO_get0_sha1str(STORE_ATTR_INFO *attrs,
+	STORE_ATTR_TYPES code);
+X509_NAME *STORE_ATTR_INFO_get0_dn(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code);
+BIGNUM *STORE_ATTR_INFO_get0_number(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code);
+int STORE_ATTR_INFO_set_cstr(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code,
+	char *cstr, size_t cstr_size);
+int STORE_ATTR_INFO_set_sha1str(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code,
+	unsigned char *sha1str, size_t sha1str_size);
+int STORE_ATTR_INFO_set_dn(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code,
+	X509_NAME *dn);
+int STORE_ATTR_INFO_set_number(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code,
+	BIGNUM *number);
+int STORE_ATTR_INFO_modify_cstr(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code,
+	char *cstr, size_t cstr_size);
+int STORE_ATTR_INFO_modify_sha1str(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code,
+	unsigned char *sha1str, size_t sha1str_size);
+int STORE_ATTR_INFO_modify_dn(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code,
+	X509_NAME *dn);
+int STORE_ATTR_INFO_modify_number(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code,
+	BIGNUM *number);
+
+/* Compare on basis of a bit pattern formed by the STORE_ATTR_TYPES values
+   in each contained attribute. */
+int STORE_ATTR_INFO_compare(STORE_ATTR_INFO *a, STORE_ATTR_INFO *b);
+/* Check if the set of attributes in a is within the range of attributes
+   set in b. */
+int STORE_ATTR_INFO_in_range(STORE_ATTR_INFO *a, STORE_ATTR_INFO *b);
+/* Check if the set of attributes in a are also set in b. */
+int STORE_ATTR_INFO_in(STORE_ATTR_INFO *a, STORE_ATTR_INFO *b);
+/* Same as STORE_ATTR_INFO_in(), but also checks the attribute values. */
+int STORE_ATTR_INFO_in_ex(STORE_ATTR_INFO *a, STORE_ATTR_INFO *b);
+
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_STORE_strings(void);
+
+/* Error codes for the STORE functions. */
+
+/* Function codes. */
+#define STORE_F_MEM_DELETE				 134
+#define STORE_F_MEM_GENERATE				 135
+#define STORE_F_MEM_LIST_END				 168
+#define STORE_F_MEM_LIST_NEXT				 136
+#define STORE_F_MEM_LIST_START				 137
+#define STORE_F_MEM_MODIFY				 169
+#define STORE_F_MEM_STORE				 138
+#define STORE_F_STORE_ATTR_INFO_GET0_CSTR		 139
+#define STORE_F_STORE_ATTR_INFO_GET0_DN			 140
+#define STORE_F_STORE_ATTR_INFO_GET0_NUMBER		 141
+#define STORE_F_STORE_ATTR_INFO_GET0_SHA1STR		 142
+#define STORE_F_STORE_ATTR_INFO_MODIFY_CSTR		 143
+#define STORE_F_STORE_ATTR_INFO_MODIFY_DN		 144
+#define STORE_F_STORE_ATTR_INFO_MODIFY_NUMBER		 145
+#define STORE_F_STORE_ATTR_INFO_MODIFY_SHA1STR		 146
+#define STORE_F_STORE_ATTR_INFO_SET_CSTR		 147
+#define STORE_F_STORE_ATTR_INFO_SET_DN			 148
+#define STORE_F_STORE_ATTR_INFO_SET_NUMBER		 149
+#define STORE_F_STORE_ATTR_INFO_SET_SHA1STR		 150
+#define STORE_F_STORE_CERTIFICATE			 170
+#define STORE_F_STORE_CTRL				 161
+#define STORE_F_STORE_DELETE_ARBITRARY			 158
+#define STORE_F_STORE_DELETE_CERTIFICATE		 102
+#define STORE_F_STORE_DELETE_CRL			 103
+#define STORE_F_STORE_DELETE_NUMBER			 104
+#define STORE_F_STORE_DELETE_PRIVATE_KEY		 105
+#define STORE_F_STORE_DELETE_PUBLIC_KEY			 106
+#define STORE_F_STORE_GENERATE_CRL			 107
+#define STORE_F_STORE_GENERATE_KEY			 108
+#define STORE_F_STORE_GET_ARBITRARY			 159
+#define STORE_F_STORE_GET_CERTIFICATE			 109
+#define STORE_F_STORE_GET_CRL				 110
+#define STORE_F_STORE_GET_NUMBER			 111
+#define STORE_F_STORE_GET_PRIVATE_KEY			 112
+#define STORE_F_STORE_GET_PUBLIC_KEY			 113
+#define STORE_F_STORE_LIST_CERTIFICATE_END		 114
+#define STORE_F_STORE_LIST_CERTIFICATE_ENDP		 153
+#define STORE_F_STORE_LIST_CERTIFICATE_NEXT		 115
+#define STORE_F_STORE_LIST_CERTIFICATE_START		 116
+#define STORE_F_STORE_LIST_CRL_END			 117
+#define STORE_F_STORE_LIST_CRL_ENDP			 154
+#define STORE_F_STORE_LIST_CRL_NEXT			 118
+#define STORE_F_STORE_LIST_CRL_START			 119
+#define STORE_F_STORE_LIST_PRIVATE_KEY_END		 120
+#define STORE_F_STORE_LIST_PRIVATE_KEY_ENDP		 155
+#define STORE_F_STORE_LIST_PRIVATE_KEY_NEXT		 121
+#define STORE_F_STORE_LIST_PRIVATE_KEY_START		 122
+#define STORE_F_STORE_LIST_PUBLIC_KEY_END		 123
+#define STORE_F_STORE_LIST_PUBLIC_KEY_ENDP		 156
+#define STORE_F_STORE_LIST_PUBLIC_KEY_NEXT		 124
+#define STORE_F_STORE_LIST_PUBLIC_KEY_START		 125
+#define STORE_F_STORE_MODIFY_ARBITRARY			 162
+#define STORE_F_STORE_MODIFY_CERTIFICATE		 163
+#define STORE_F_STORE_MODIFY_CRL			 164
+#define STORE_F_STORE_MODIFY_NUMBER			 165
+#define STORE_F_STORE_MODIFY_PRIVATE_KEY		 166
+#define STORE_F_STORE_MODIFY_PUBLIC_KEY			 167
+#define STORE_F_STORE_NEW_ENGINE			 133
+#define STORE_F_STORE_NEW_METHOD			 132
+#define STORE_F_STORE_PARSE_ATTRS_END			 151
+#define STORE_F_STORE_PARSE_ATTRS_ENDP			 172
+#define STORE_F_STORE_PARSE_ATTRS_NEXT			 152
+#define STORE_F_STORE_PARSE_ATTRS_START			 171
+#define STORE_F_STORE_REVOKE_CERTIFICATE		 129
+#define STORE_F_STORE_REVOKE_PRIVATE_KEY		 130
+#define STORE_F_STORE_REVOKE_PUBLIC_KEY			 131
+#define STORE_F_STORE_STORE_ARBITRARY			 157
+#define STORE_F_STORE_STORE_CERTIFICATE			 100
+#define STORE_F_STORE_STORE_CRL				 101
+#define STORE_F_STORE_STORE_NUMBER			 126
+#define STORE_F_STORE_STORE_PRIVATE_KEY			 127
+#define STORE_F_STORE_STORE_PUBLIC_KEY			 128
+
+/* Reason codes. */
+#define STORE_R_ALREADY_HAS_A_VALUE			 127
+#define STORE_R_FAILED_DELETING_ARBITRARY		 132
+#define STORE_R_FAILED_DELETING_CERTIFICATE		 100
+#define STORE_R_FAILED_DELETING_KEY			 101
+#define STORE_R_FAILED_DELETING_NUMBER			 102
+#define STORE_R_FAILED_GENERATING_CRL			 103
+#define STORE_R_FAILED_GENERATING_KEY			 104
+#define STORE_R_FAILED_GETTING_ARBITRARY		 133
+#define STORE_R_FAILED_GETTING_CERTIFICATE		 105
+#define STORE_R_FAILED_GETTING_KEY			 106
+#define STORE_R_FAILED_GETTING_NUMBER			 107
+#define STORE_R_FAILED_LISTING_CERTIFICATES		 108
+#define STORE_R_FAILED_LISTING_KEYS			 109
+#define STORE_R_FAILED_MODIFYING_ARBITRARY		 138
+#define STORE_R_FAILED_MODIFYING_CERTIFICATE		 139
+#define STORE_R_FAILED_MODIFYING_CRL			 140
+#define STORE_R_FAILED_MODIFYING_NUMBER			 141
+#define STORE_R_FAILED_MODIFYING_PRIVATE_KEY		 142
+#define STORE_R_FAILED_MODIFYING_PUBLIC_KEY		 143
+#define STORE_R_FAILED_REVOKING_CERTIFICATE		 110
+#define STORE_R_FAILED_REVOKING_KEY			 111
+#define STORE_R_FAILED_STORING_ARBITRARY		 134
+#define STORE_R_FAILED_STORING_CERTIFICATE		 112
+#define STORE_R_FAILED_STORING_KEY			 113
+#define STORE_R_FAILED_STORING_NUMBER			 114
+#define STORE_R_NOT_IMPLEMENTED				 128
+#define STORE_R_NO_CONTROL_FUNCTION			 144
+#define STORE_R_NO_DELETE_ARBITRARY_FUNCTION		 135
+#define STORE_R_NO_DELETE_NUMBER_FUNCTION		 115
+#define STORE_R_NO_DELETE_OBJECT_FUNCTION		 116
+#define STORE_R_NO_GENERATE_CRL_FUNCTION		 117
+#define STORE_R_NO_GENERATE_OBJECT_FUNCTION		 118
+#define STORE_R_NO_GET_OBJECT_ARBITRARY_FUNCTION	 136
+#define STORE_R_NO_GET_OBJECT_FUNCTION			 119
+#define STORE_R_NO_GET_OBJECT_NUMBER_FUNCTION		 120
+#define STORE_R_NO_LIST_OBJECT_ENDP_FUNCTION		 131
+#define STORE_R_NO_LIST_OBJECT_END_FUNCTION		 121
+#define STORE_R_NO_LIST_OBJECT_NEXT_FUNCTION		 122
+#define STORE_R_NO_LIST_OBJECT_START_FUNCTION		 123
+#define STORE_R_NO_MODIFY_OBJECT_FUNCTION		 145
+#define STORE_R_NO_REVOKE_OBJECT_FUNCTION		 124
+#define STORE_R_NO_STORE				 129
+#define STORE_R_NO_STORE_OBJECT_ARBITRARY_FUNCTION	 137
+#define STORE_R_NO_STORE_OBJECT_FUNCTION		 125
+#define STORE_R_NO_STORE_OBJECT_NUMBER_FUNCTION		 126
+#define STORE_R_NO_VALUE				 130
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/dep/include/openssl/symhacks.h b/dep/include/openssl/symhacks.h
new file mode 100644
index 00000000000..7e3602d2ea4
--- /dev/null
+++ b/dep/include/openssl/symhacks.h
@@ -0,0 +1,383 @@
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_SYMHACKS_H
+#define HEADER_SYMHACKS_H
+
+#include 
+
+/* Hacks to solve the problem with linkers incapable of handling very long
+   symbol names.  In the case of VMS, the limit is 31 characters on VMS for
+   VAX. */
+#ifdef OPENSSL_SYS_VMS
+
+/* Hack a long name in crypto/ex_data.c */
+#undef CRYPTO_get_ex_data_implementation
+#define CRYPTO_get_ex_data_implementation	CRYPTO_get_ex_data_impl
+#undef CRYPTO_set_ex_data_implementation
+#define CRYPTO_set_ex_data_implementation	CRYPTO_set_ex_data_impl
+
+/* Hack a long name in crypto/asn1/a_mbstr.c */
+#undef ASN1_STRING_set_default_mask_asc
+#define ASN1_STRING_set_default_mask_asc	ASN1_STRING_set_def_mask_asc
+
+#if 0 /* No longer needed, since safestack macro magic does the job */
+/* Hack the names created with DECLARE_ASN1_SET_OF(PKCS7_SIGNER_INFO) */
+#undef i2d_ASN1_SET_OF_PKCS7_SIGNER_INFO
+#define i2d_ASN1_SET_OF_PKCS7_SIGNER_INFO	i2d_ASN1_SET_OF_PKCS7_SIGINF
+#undef d2i_ASN1_SET_OF_PKCS7_SIGNER_INFO
+#define d2i_ASN1_SET_OF_PKCS7_SIGNER_INFO	d2i_ASN1_SET_OF_PKCS7_SIGINF
+#endif
+
+#if 0 /* No longer needed, since safestack macro magic does the job */
+/* Hack the names created with DECLARE_ASN1_SET_OF(PKCS7_RECIP_INFO) */
+#undef i2d_ASN1_SET_OF_PKCS7_RECIP_INFO
+#define i2d_ASN1_SET_OF_PKCS7_RECIP_INFO	i2d_ASN1_SET_OF_PKCS7_RECINF
+#undef d2i_ASN1_SET_OF_PKCS7_RECIP_INFO
+#define d2i_ASN1_SET_OF_PKCS7_RECIP_INFO	d2i_ASN1_SET_OF_PKCS7_RECINF
+#endif
+
+#if 0 /* No longer needed, since safestack macro magic does the job */
+/* Hack the names created with DECLARE_ASN1_SET_OF(ACCESS_DESCRIPTION) */
+#undef i2d_ASN1_SET_OF_ACCESS_DESCRIPTION
+#define i2d_ASN1_SET_OF_ACCESS_DESCRIPTION	i2d_ASN1_SET_OF_ACC_DESC
+#undef d2i_ASN1_SET_OF_ACCESS_DESCRIPTION
+#define d2i_ASN1_SET_OF_ACCESS_DESCRIPTION	d2i_ASN1_SET_OF_ACC_DESC
+#endif
+
+/* Hack the names created with DECLARE_PEM_rw(NETSCAPE_CERT_SEQUENCE) */
+#undef PEM_read_NETSCAPE_CERT_SEQUENCE
+#define PEM_read_NETSCAPE_CERT_SEQUENCE		PEM_read_NS_CERT_SEQ
+#undef PEM_write_NETSCAPE_CERT_SEQUENCE
+#define PEM_write_NETSCAPE_CERT_SEQUENCE	PEM_write_NS_CERT_SEQ
+#undef PEM_read_bio_NETSCAPE_CERT_SEQUENCE
+#define PEM_read_bio_NETSCAPE_CERT_SEQUENCE	PEM_read_bio_NS_CERT_SEQ
+#undef PEM_write_bio_NETSCAPE_CERT_SEQUENCE
+#define PEM_write_bio_NETSCAPE_CERT_SEQUENCE	PEM_write_bio_NS_CERT_SEQ
+#undef PEM_write_cb_bio_NETSCAPE_CERT_SEQUENCE
+#define PEM_write_cb_bio_NETSCAPE_CERT_SEQUENCE	PEM_write_cb_bio_NS_CERT_SEQ
+
+/* Hack the names created with DECLARE_PEM_rw(PKCS8_PRIV_KEY_INFO) */
+#undef PEM_read_PKCS8_PRIV_KEY_INFO
+#define PEM_read_PKCS8_PRIV_KEY_INFO		PEM_read_P8_PRIV_KEY_INFO
+#undef PEM_write_PKCS8_PRIV_KEY_INFO
+#define PEM_write_PKCS8_PRIV_KEY_INFO		PEM_write_P8_PRIV_KEY_INFO
+#undef PEM_read_bio_PKCS8_PRIV_KEY_INFO
+#define PEM_read_bio_PKCS8_PRIV_KEY_INFO	PEM_read_bio_P8_PRIV_KEY_INFO
+#undef PEM_write_bio_PKCS8_PRIV_KEY_INFO
+#define PEM_write_bio_PKCS8_PRIV_KEY_INFO	PEM_write_bio_P8_PRIV_KEY_INFO
+#undef PEM_write_cb_bio_PKCS8_PRIV_KEY_INFO
+#define PEM_write_cb_bio_PKCS8_PRIV_KEY_INFO	PEM_wrt_cb_bio_P8_PRIV_KEY_INFO
+
+/* Hack other PEM names */
+#undef PEM_write_bio_PKCS8PrivateKey_nid
+#define PEM_write_bio_PKCS8PrivateKey_nid	PEM_write_bio_PKCS8PrivKey_nid
+
+/* Hack some long X509 names */
+#undef X509_REVOKED_get_ext_by_critical
+#define X509_REVOKED_get_ext_by_critical	X509_REVOKED_get_ext_by_critic
+#undef X509_policy_tree_get0_user_policies
+#define X509_policy_tree_get0_user_policies	X509_pcy_tree_get0_usr_policies
+#undef X509_policy_node_get0_qualifiers
+#define X509_policy_node_get0_qualifiers	X509_pcy_node_get0_qualifiers
+#undef X509_STORE_CTX_get_explicit_policy
+#define X509_STORE_CTX_get_explicit_policy	X509_STORE_CTX_get_expl_policy
+
+/* Hack some long CRYPTO names */
+#undef CRYPTO_set_dynlock_destroy_callback
+#define CRYPTO_set_dynlock_destroy_callback     CRYPTO_set_dynlock_destroy_cb
+#undef CRYPTO_set_dynlock_create_callback
+#define CRYPTO_set_dynlock_create_callback      CRYPTO_set_dynlock_create_cb
+#undef CRYPTO_set_dynlock_lock_callback
+#define CRYPTO_set_dynlock_lock_callback        CRYPTO_set_dynlock_lock_cb
+#undef CRYPTO_get_dynlock_lock_callback
+#define CRYPTO_get_dynlock_lock_callback        CRYPTO_get_dynlock_lock_cb
+#undef CRYPTO_get_dynlock_destroy_callback
+#define CRYPTO_get_dynlock_destroy_callback     CRYPTO_get_dynlock_destroy_cb
+#undef CRYPTO_get_dynlock_create_callback
+#define CRYPTO_get_dynlock_create_callback      CRYPTO_get_dynlock_create_cb
+#undef CRYPTO_set_locked_mem_ex_functions
+#define CRYPTO_set_locked_mem_ex_functions      CRYPTO_set_locked_mem_ex_funcs
+#undef CRYPTO_get_locked_mem_ex_functions
+#define CRYPTO_get_locked_mem_ex_functions      CRYPTO_get_locked_mem_ex_funcs
+
+/* Hack some long SSL names */
+#undef SSL_CTX_set_default_verify_paths
+#define SSL_CTX_set_default_verify_paths        SSL_CTX_set_def_verify_paths
+#undef SSL_get_ex_data_X509_STORE_CTX_idx
+#define SSL_get_ex_data_X509_STORE_CTX_idx      SSL_get_ex_d_X509_STORE_CTX_idx
+#undef SSL_add_file_cert_subjects_to_stack
+#define SSL_add_file_cert_subjects_to_stack     SSL_add_file_cert_subjs_to_stk
+#undef SSL_add_dir_cert_subjects_to_stack
+#define SSL_add_dir_cert_subjects_to_stack      SSL_add_dir_cert_subjs_to_stk
+#undef SSL_CTX_use_certificate_chain_file
+#define SSL_CTX_use_certificate_chain_file      SSL_CTX_use_cert_chain_file
+#undef SSL_CTX_set_cert_verify_callback
+#define SSL_CTX_set_cert_verify_callback        SSL_CTX_set_cert_verify_cb
+#undef SSL_CTX_set_default_passwd_cb_userdata
+#define SSL_CTX_set_default_passwd_cb_userdata  SSL_CTX_set_def_passwd_cb_ud
+#undef SSL_COMP_get_compression_methods
+#define SSL_COMP_get_compression_methods	SSL_COMP_get_compress_methods
+
+/* Hack some long ENGINE names */
+#undef ENGINE_get_default_BN_mod_exp_crt
+#define ENGINE_get_default_BN_mod_exp_crt	ENGINE_get_def_BN_mod_exp_crt
+#undef ENGINE_set_default_BN_mod_exp_crt
+#define ENGINE_set_default_BN_mod_exp_crt	ENGINE_set_def_BN_mod_exp_crt
+#undef ENGINE_set_load_privkey_function
+#define ENGINE_set_load_privkey_function        ENGINE_set_load_privkey_fn
+#undef ENGINE_get_load_privkey_function
+#define ENGINE_get_load_privkey_function        ENGINE_get_load_privkey_fn
+
+/* Hack some long OCSP names */
+#undef OCSP_REQUEST_get_ext_by_critical
+#define OCSP_REQUEST_get_ext_by_critical        OCSP_REQUEST_get_ext_by_crit
+#undef OCSP_BASICRESP_get_ext_by_critical
+#define OCSP_BASICRESP_get_ext_by_critical      OCSP_BASICRESP_get_ext_by_crit
+#undef OCSP_SINGLERESP_get_ext_by_critical
+#define OCSP_SINGLERESP_get_ext_by_critical     OCSP_SINGLERESP_get_ext_by_crit
+
+/* Hack some long DES names */
+#undef _ossl_old_des_ede3_cfb64_encrypt
+#define _ossl_old_des_ede3_cfb64_encrypt	_ossl_odes_ede3_cfb64_encrypt
+#undef _ossl_old_des_ede3_ofb64_encrypt
+#define _ossl_old_des_ede3_ofb64_encrypt	_ossl_odes_ede3_ofb64_encrypt
+
+/* Hack some long EVP names */
+#undef OPENSSL_add_all_algorithms_noconf
+#define OPENSSL_add_all_algorithms_noconf	OPENSSL_add_all_algo_noconf
+#undef OPENSSL_add_all_algorithms_conf
+#define OPENSSL_add_all_algorithms_conf		OPENSSL_add_all_algo_conf
+
+/* Hack some long EC names */
+#undef EC_GROUP_set_point_conversion_form
+#define EC_GROUP_set_point_conversion_form	EC_GROUP_set_point_conv_form
+#undef EC_GROUP_get_point_conversion_form
+#define EC_GROUP_get_point_conversion_form	EC_GROUP_get_point_conv_form
+#undef EC_GROUP_clear_free_all_extra_data
+#define EC_GROUP_clear_free_all_extra_data	EC_GROUP_clr_free_all_xtra_data
+#undef EC_POINT_set_Jprojective_coordinates_GFp
+#define EC_POINT_set_Jprojective_coordinates_GFp \
+                                                EC_POINT_set_Jproj_coords_GFp
+#undef EC_POINT_get_Jprojective_coordinates_GFp
+#define EC_POINT_get_Jprojective_coordinates_GFp \
+                                                EC_POINT_get_Jproj_coords_GFp
+#undef EC_POINT_set_affine_coordinates_GFp
+#define EC_POINT_set_affine_coordinates_GFp     EC_POINT_set_affine_coords_GFp
+#undef EC_POINT_get_affine_coordinates_GFp
+#define EC_POINT_get_affine_coordinates_GFp     EC_POINT_get_affine_coords_GFp
+#undef EC_POINT_set_compressed_coordinates_GFp
+#define EC_POINT_set_compressed_coordinates_GFp EC_POINT_set_compr_coords_GFp
+#undef EC_POINT_set_affine_coordinates_GF2m
+#define EC_POINT_set_affine_coordinates_GF2m    EC_POINT_set_affine_coords_GF2m
+#undef EC_POINT_get_affine_coordinates_GF2m
+#define EC_POINT_get_affine_coordinates_GF2m    EC_POINT_get_affine_coords_GF2m
+#undef EC_POINT_set_compressed_coordinates_GF2m
+#define EC_POINT_set_compressed_coordinates_GF2m \
+                                                EC_POINT_set_compr_coords_GF2m
+#undef ec_GF2m_simple_group_clear_finish
+#define ec_GF2m_simple_group_clear_finish        ec_GF2m_simple_grp_clr_finish
+#undef ec_GF2m_simple_group_check_discriminant
+#define ec_GF2m_simple_group_check_discriminant	ec_GF2m_simple_grp_chk_discrim
+#undef ec_GF2m_simple_point_clear_finish
+#define ec_GF2m_simple_point_clear_finish        ec_GF2m_simple_pt_clr_finish
+#undef ec_GF2m_simple_point_set_to_infinity
+#define ec_GF2m_simple_point_set_to_infinity     ec_GF2m_simple_pt_set_to_inf
+#undef ec_GF2m_simple_points_make_affine
+#define ec_GF2m_simple_points_make_affine        ec_GF2m_simple_pts_make_affine
+#undef ec_GF2m_simple_point_set_affine_coordinates
+#define ec_GF2m_simple_point_set_affine_coordinates \
+                                                ec_GF2m_smp_pt_set_af_coords
+#undef ec_GF2m_simple_point_get_affine_coordinates
+#define ec_GF2m_simple_point_get_affine_coordinates \
+                                                ec_GF2m_smp_pt_get_af_coords
+#undef ec_GF2m_simple_set_compressed_coordinates
+#define ec_GF2m_simple_set_compressed_coordinates \
+                                                ec_GF2m_smp_set_compr_coords
+#undef ec_GFp_simple_group_set_curve_GFp
+#define ec_GFp_simple_group_set_curve_GFp       ec_GFp_simple_grp_set_curve_GFp
+#undef ec_GFp_simple_group_get_curve_GFp
+#define ec_GFp_simple_group_get_curve_GFp       ec_GFp_simple_grp_get_curve_GFp
+#undef ec_GFp_simple_group_clear_finish
+#define ec_GFp_simple_group_clear_finish        ec_GFp_simple_grp_clear_finish
+#undef ec_GFp_simple_group_set_generator
+#define ec_GFp_simple_group_set_generator       ec_GFp_simple_grp_set_generator
+#undef ec_GFp_simple_group_get0_generator
+#define ec_GFp_simple_group_get0_generator      ec_GFp_simple_grp_gt0_generator
+#undef ec_GFp_simple_group_get_cofactor
+#define ec_GFp_simple_group_get_cofactor        ec_GFp_simple_grp_get_cofactor
+#undef ec_GFp_simple_point_clear_finish
+#define ec_GFp_simple_point_clear_finish        ec_GFp_simple_pt_clear_finish
+#undef ec_GFp_simple_point_set_to_infinity
+#define ec_GFp_simple_point_set_to_infinity     ec_GFp_simple_pt_set_to_inf
+#undef ec_GFp_simple_points_make_affine
+#define ec_GFp_simple_points_make_affine        ec_GFp_simple_pts_make_affine
+#undef ec_GFp_simple_group_get_curve_GFp
+#define ec_GFp_simple_group_get_curve_GFp       ec_GFp_simple_grp_get_curve_GFp
+#undef ec_GFp_simple_set_Jprojective_coordinates_GFp
+#define ec_GFp_simple_set_Jprojective_coordinates_GFp \
+                                                ec_GFp_smp_set_Jproj_coords_GFp
+#undef ec_GFp_simple_get_Jprojective_coordinates_GFp
+#define ec_GFp_simple_get_Jprojective_coordinates_GFp \
+                                                ec_GFp_smp_get_Jproj_coords_GFp
+#undef ec_GFp_simple_point_set_affine_coordinates_GFp
+#define ec_GFp_simple_point_set_affine_coordinates_GFp \
+                                                ec_GFp_smp_pt_set_af_coords_GFp
+#undef ec_GFp_simple_point_get_affine_coordinates_GFp
+#define ec_GFp_simple_point_get_affine_coordinates_GFp \
+                                                ec_GFp_smp_pt_get_af_coords_GFp
+#undef ec_GFp_simple_set_compressed_coordinates_GFp
+#define ec_GFp_simple_set_compressed_coordinates_GFp \
+                                                ec_GFp_smp_set_compr_coords_GFp
+#undef ec_GFp_simple_point_set_affine_coordinates
+#define ec_GFp_simple_point_set_affine_coordinates \
+                                                ec_GFp_smp_pt_set_af_coords
+#undef ec_GFp_simple_point_get_affine_coordinates
+#define ec_GFp_simple_point_get_affine_coordinates \
+                                                ec_GFp_smp_pt_get_af_coords
+#undef ec_GFp_simple_set_compressed_coordinates
+#define ec_GFp_simple_set_compressed_coordinates \
+                                                ec_GFp_smp_set_compr_coords
+#undef ec_GFp_simple_group_check_discriminant
+#define ec_GFp_simple_group_check_discriminant	ec_GFp_simple_grp_chk_discrim
+
+/* Hack som long STORE names */
+#undef STORE_method_set_initialise_function
+#define STORE_method_set_initialise_function	STORE_meth_set_initialise_fn
+#undef STORE_method_set_cleanup_function
+#define STORE_method_set_cleanup_function	STORE_meth_set_cleanup_fn
+#undef STORE_method_set_generate_function
+#define STORE_method_set_generate_function	STORE_meth_set_generate_fn
+#undef STORE_method_set_modify_function
+#define STORE_method_set_modify_function	STORE_meth_set_modify_fn
+#undef STORE_method_set_revoke_function
+#define STORE_method_set_revoke_function	STORE_meth_set_revoke_fn
+#undef STORE_method_set_delete_function
+#define STORE_method_set_delete_function	STORE_meth_set_delete_fn
+#undef STORE_method_set_list_start_function
+#define STORE_method_set_list_start_function	STORE_meth_set_list_start_fn
+#undef STORE_method_set_list_next_function
+#define STORE_method_set_list_next_function	STORE_meth_set_list_next_fn
+#undef STORE_method_set_list_end_function
+#define STORE_method_set_list_end_function	STORE_meth_set_list_end_fn
+#undef STORE_method_set_update_store_function
+#define STORE_method_set_update_store_function	STORE_meth_set_update_store_fn
+#undef STORE_method_set_lock_store_function
+#define STORE_method_set_lock_store_function	STORE_meth_set_lock_store_fn
+#undef STORE_method_set_unlock_store_function
+#define STORE_method_set_unlock_store_function	STORE_meth_set_unlock_store_fn
+#undef STORE_method_get_initialise_function
+#define STORE_method_get_initialise_function	STORE_meth_get_initialise_fn
+#undef STORE_method_get_cleanup_function
+#define STORE_method_get_cleanup_function	STORE_meth_get_cleanup_fn
+#undef STORE_method_get_generate_function
+#define STORE_method_get_generate_function	STORE_meth_get_generate_fn
+#undef STORE_method_get_modify_function
+#define STORE_method_get_modify_function	STORE_meth_get_modify_fn
+#undef STORE_method_get_revoke_function
+#define STORE_method_get_revoke_function	STORE_meth_get_revoke_fn
+#undef STORE_method_get_delete_function
+#define STORE_method_get_delete_function	STORE_meth_get_delete_fn
+#undef STORE_method_get_list_start_function
+#define STORE_method_get_list_start_function	STORE_meth_get_list_start_fn
+#undef STORE_method_get_list_next_function
+#define STORE_method_get_list_next_function	STORE_meth_get_list_next_fn
+#undef STORE_method_get_list_end_function
+#define STORE_method_get_list_end_function	STORE_meth_get_list_end_fn
+#undef STORE_method_get_update_store_function
+#define STORE_method_get_update_store_function	STORE_meth_get_update_store_fn
+#undef STORE_method_get_lock_store_function
+#define STORE_method_get_lock_store_function	STORE_meth_get_lock_store_fn
+#undef STORE_method_get_unlock_store_function
+#define STORE_method_get_unlock_store_function	STORE_meth_get_unlock_store_fn
+
+#endif /* defined OPENSSL_SYS_VMS */
+
+
+/* Case insensiteve linking causes problems.... */
+#if defined(OPENSSL_SYS_WIN16) || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_OS2)
+#undef ERR_load_CRYPTO_strings
+#define ERR_load_CRYPTO_strings			ERR_load_CRYPTOlib_strings
+#undef OCSP_crlID_new
+#define OCSP_crlID_new                          OCSP_crlID2_new
+
+#undef d2i_ECPARAMETERS
+#define d2i_ECPARAMETERS                        d2i_UC_ECPARAMETERS
+#undef i2d_ECPARAMETERS
+#define i2d_ECPARAMETERS                        i2d_UC_ECPARAMETERS
+#undef d2i_ECPKPARAMETERS
+#define d2i_ECPKPARAMETERS                      d2i_UC_ECPKPARAMETERS
+#undef i2d_ECPKPARAMETERS
+#define i2d_ECPKPARAMETERS                      i2d_UC_ECPKPARAMETERS
+
+/* These functions do not seem to exist!  However, I'm paranoid...
+   Original command in x509v3.h:
+   These functions are being redefined in another directory,
+   and clash when the linker is case-insensitive, so let's
+   hide them a little, by giving them an extra 'o' at the
+   beginning of the name... */
+#undef X509v3_cleanup_extensions
+#define X509v3_cleanup_extensions               oX509v3_cleanup_extensions
+#undef X509v3_add_extension
+#define X509v3_add_extension                    oX509v3_add_extension
+#undef X509v3_add_netscape_extensions
+#define X509v3_add_netscape_extensions          oX509v3_add_netscape_extensions
+#undef X509v3_add_standard_extensions
+#define X509v3_add_standard_extensions          oX509v3_add_standard_extensions
+
+
+#endif
+
+
+#endif /* ! defined HEADER_VMS_IDHACKS_H */
diff --git a/dep/include/openssl/tls1.h b/dep/include/openssl/tls1.h
new file mode 100644
index 00000000000..e5f9aa1ef6f
--- /dev/null
+++ b/dep/include/openssl/tls1.h
@@ -0,0 +1,305 @@
+/* ssl/tls1.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * Portions of the attached software ("Contribution") are developed by 
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the OpenSSL open source
+ * license provided above.
+ *
+ * ECC cipher suite support in OpenSSL originally written by
+ * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
+ *
+ */
+
+#ifndef HEADER_TLS1_H 
+#define HEADER_TLS1_H 
+
+#include 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#define TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES	0
+
+#define TLS1_VERSION			0x0301
+#define TLS1_VERSION_MAJOR		0x03
+#define TLS1_VERSION_MINOR		0x01
+
+#define TLS1_AD_DECRYPTION_FAILED	21
+#define TLS1_AD_RECORD_OVERFLOW		22
+#define TLS1_AD_UNKNOWN_CA		48	/* fatal */
+#define TLS1_AD_ACCESS_DENIED		49	/* fatal */
+#define TLS1_AD_DECODE_ERROR		50	/* fatal */
+#define TLS1_AD_DECRYPT_ERROR		51
+#define TLS1_AD_EXPORT_RESTRICTION	60	/* fatal */
+#define TLS1_AD_PROTOCOL_VERSION	70	/* fatal */
+#define TLS1_AD_INSUFFICIENT_SECURITY	71	/* fatal */
+#define TLS1_AD_INTERNAL_ERROR		80	/* fatal */
+#define TLS1_AD_USER_CANCELLED		90
+#define TLS1_AD_NO_RENEGOTIATION	100
+
+/* Additional TLS ciphersuites from draft-ietf-tls-56-bit-ciphersuites-00.txt
+ * (available if TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES is defined, see
+ * s3_lib.c).  We actually treat them like SSL 3.0 ciphers, which we probably
+ * shouldn't. */
+#define TLS1_CK_RSA_EXPORT1024_WITH_RC4_56_MD5		0x03000060
+#define TLS1_CK_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5	0x03000061
+#define TLS1_CK_RSA_EXPORT1024_WITH_DES_CBC_SHA		0x03000062
+#define TLS1_CK_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA	0x03000063
+#define TLS1_CK_RSA_EXPORT1024_WITH_RC4_56_SHA		0x03000064
+#define TLS1_CK_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA	0x03000065
+#define TLS1_CK_DHE_DSS_WITH_RC4_128_SHA		0x03000066
+
+/* AES ciphersuites from RFC3268 */
+
+#define TLS1_CK_RSA_WITH_AES_128_SHA			0x0300002F
+#define TLS1_CK_DH_DSS_WITH_AES_128_SHA			0x03000030
+#define TLS1_CK_DH_RSA_WITH_AES_128_SHA			0x03000031
+#define TLS1_CK_DHE_DSS_WITH_AES_128_SHA		0x03000032
+#define TLS1_CK_DHE_RSA_WITH_AES_128_SHA		0x03000033
+#define TLS1_CK_ADH_WITH_AES_128_SHA			0x03000034
+
+#define TLS1_CK_RSA_WITH_AES_256_SHA			0x03000035
+#define TLS1_CK_DH_DSS_WITH_AES_256_SHA			0x03000036
+#define TLS1_CK_DH_RSA_WITH_AES_256_SHA			0x03000037
+#define TLS1_CK_DHE_DSS_WITH_AES_256_SHA		0x03000038
+#define TLS1_CK_DHE_RSA_WITH_AES_256_SHA		0x03000039
+#define TLS1_CK_ADH_WITH_AES_256_SHA			0x0300003A
+
+/* Camellia ciphersuites from RFC4132 */
+#define TLS1_CK_RSA_WITH_CAMELLIA_128_CBC_SHA		0x03000041
+#define TLS1_CK_DH_DSS_WITH_CAMELLIA_128_CBC_SHA	0x03000042
+#define TLS1_CK_DH_RSA_WITH_CAMELLIA_128_CBC_SHA	0x03000043
+#define TLS1_CK_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA	0x03000044
+#define TLS1_CK_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA	0x03000045
+#define TLS1_CK_ADH_WITH_CAMELLIA_128_CBC_SHA		0x03000046
+
+#define TLS1_CK_RSA_WITH_CAMELLIA_256_CBC_SHA		0x03000084
+#define TLS1_CK_DH_DSS_WITH_CAMELLIA_256_CBC_SHA	0x03000085
+#define TLS1_CK_DH_RSA_WITH_CAMELLIA_256_CBC_SHA	0x03000086
+#define TLS1_CK_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA	0x03000087
+#define TLS1_CK_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA	0x03000088
+#define TLS1_CK_ADH_WITH_CAMELLIA_256_CBC_SHA		0x03000089
+
+/* ECC ciphersuites from draft-ietf-tls-ecc-12.txt with changes soon to be in draft 13 */
+#define TLS1_CK_ECDH_ECDSA_WITH_NULL_SHA                0x0300C001
+#define TLS1_CK_ECDH_ECDSA_WITH_RC4_128_SHA             0x0300C002
+#define TLS1_CK_ECDH_ECDSA_WITH_DES_192_CBC3_SHA        0x0300C003
+#define TLS1_CK_ECDH_ECDSA_WITH_AES_128_CBC_SHA         0x0300C004
+#define TLS1_CK_ECDH_ECDSA_WITH_AES_256_CBC_SHA         0x0300C005
+
+#define TLS1_CK_ECDHE_ECDSA_WITH_NULL_SHA               0x0300C006
+#define TLS1_CK_ECDHE_ECDSA_WITH_RC4_128_SHA            0x0300C007
+#define TLS1_CK_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA       0x0300C008
+#define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA        0x0300C009
+#define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA        0x0300C00A
+
+#define TLS1_CK_ECDH_RSA_WITH_NULL_SHA                  0x0300C00B
+#define TLS1_CK_ECDH_RSA_WITH_RC4_128_SHA               0x0300C00C
+#define TLS1_CK_ECDH_RSA_WITH_DES_192_CBC3_SHA          0x0300C00D
+#define TLS1_CK_ECDH_RSA_WITH_AES_128_CBC_SHA           0x0300C00E
+#define TLS1_CK_ECDH_RSA_WITH_AES_256_CBC_SHA           0x0300C00F
+
+#define TLS1_CK_ECDHE_RSA_WITH_NULL_SHA                 0x0300C010
+#define TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA              0x0300C011
+#define TLS1_CK_ECDHE_RSA_WITH_DES_192_CBC3_SHA         0x0300C012
+#define TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA          0x0300C013
+#define TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA          0x0300C014
+
+#define TLS1_CK_ECDH_anon_WITH_NULL_SHA                 0x0300C015
+#define TLS1_CK_ECDH_anon_WITH_RC4_128_SHA              0x0300C016
+#define TLS1_CK_ECDH_anon_WITH_DES_192_CBC3_SHA         0x0300C017
+#define TLS1_CK_ECDH_anon_WITH_AES_128_CBC_SHA          0x0300C018
+#define TLS1_CK_ECDH_anon_WITH_AES_256_CBC_SHA          0x0300C019
+
+/* XXX
+ * Inconsistency alert:
+ * The OpenSSL names of ciphers with ephemeral DH here include the string
+ * "DHE", while elsewhere it has always been "EDH".
+ * (The alias for the list of all such ciphers also is "EDH".)
+ * The specifications speak of "EDH"; maybe we should allow both forms
+ * for everything. */
+#define TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_MD5		"EXP1024-RC4-MD5"
+#define TLS1_TXT_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5	"EXP1024-RC2-CBC-MD5"
+#define TLS1_TXT_RSA_EXPORT1024_WITH_DES_CBC_SHA	"EXP1024-DES-CBC-SHA"
+#define TLS1_TXT_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA	"EXP1024-DHE-DSS-DES-CBC-SHA"
+#define TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_SHA		"EXP1024-RC4-SHA"
+#define TLS1_TXT_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA	"EXP1024-DHE-DSS-RC4-SHA"
+#define TLS1_TXT_DHE_DSS_WITH_RC4_128_SHA		"DHE-DSS-RC4-SHA"
+
+/* AES ciphersuites from RFC3268 */
+#define TLS1_TXT_RSA_WITH_AES_128_SHA			"AES128-SHA"
+#define TLS1_TXT_DH_DSS_WITH_AES_128_SHA		"DH-DSS-AES128-SHA"
+#define TLS1_TXT_DH_RSA_WITH_AES_128_SHA		"DH-RSA-AES128-SHA"
+#define TLS1_TXT_DHE_DSS_WITH_AES_128_SHA		"DHE-DSS-AES128-SHA"
+#define TLS1_TXT_DHE_RSA_WITH_AES_128_SHA		"DHE-RSA-AES128-SHA"
+#define TLS1_TXT_ADH_WITH_AES_128_SHA			"ADH-AES128-SHA"
+
+#define TLS1_TXT_RSA_WITH_AES_256_SHA			"AES256-SHA"
+#define TLS1_TXT_DH_DSS_WITH_AES_256_SHA		"DH-DSS-AES256-SHA"
+#define TLS1_TXT_DH_RSA_WITH_AES_256_SHA		"DH-RSA-AES256-SHA"
+#define TLS1_TXT_DHE_DSS_WITH_AES_256_SHA		"DHE-DSS-AES256-SHA"
+#define TLS1_TXT_DHE_RSA_WITH_AES_256_SHA		"DHE-RSA-AES256-SHA"
+#define TLS1_TXT_ADH_WITH_AES_256_SHA			"ADH-AES256-SHA"
+
+/* ECC ciphersuites from draft-ietf-tls-ecc-01.txt (Mar 15, 2001) */
+#define TLS1_TXT_ECDH_ECDSA_WITH_NULL_SHA               "ECDH-ECDSA-NULL-SHA"
+#define TLS1_TXT_ECDH_ECDSA_WITH_RC4_128_SHA            "ECDH-ECDSA-RC4-SHA"
+#define TLS1_TXT_ECDH_ECDSA_WITH_DES_192_CBC3_SHA       "ECDH-ECDSA-DES-CBC3-SHA"
+#define TLS1_TXT_ECDH_ECDSA_WITH_AES_128_CBC_SHA        "ECDH-ECDSA-AES128-SHA"
+#define TLS1_TXT_ECDH_ECDSA_WITH_AES_256_CBC_SHA        "ECDH-ECDSA-AES256-SHA"
+
+#define TLS1_TXT_ECDHE_ECDSA_WITH_NULL_SHA              "ECDHE-ECDSA-NULL-SHA"
+#define TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA           "ECDHE-ECDSA-RC4-SHA"
+#define TLS1_TXT_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA      "ECDHE-ECDSA-DES-CBC3-SHA"
+#define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA       "ECDHE-ECDSA-AES128-SHA"
+#define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA       "ECDHE-ECDSA-AES256-SHA"
+
+#define TLS1_TXT_ECDH_RSA_WITH_NULL_SHA                 "ECDH-RSA-NULL-SHA"
+#define TLS1_TXT_ECDH_RSA_WITH_RC4_128_SHA              "ECDH-RSA-RC4-SHA"
+#define TLS1_TXT_ECDH_RSA_WITH_DES_192_CBC3_SHA         "ECDH-RSA-DES-CBC3-SHA"
+#define TLS1_TXT_ECDH_RSA_WITH_AES_128_CBC_SHA          "ECDH-RSA-AES128-SHA"
+#define TLS1_TXT_ECDH_RSA_WITH_AES_256_CBC_SHA          "ECDH-RSA-AES256-SHA"
+
+#define TLS1_TXT_ECDHE_RSA_WITH_NULL_SHA                "ECDHE-RSA-NULL-SHA"
+#define TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA             "ECDHE-RSA-RC4-SHA"
+#define TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA        "ECDHE-RSA-DES-CBC3-SHA"
+#define TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA         "ECDHE-RSA-AES128-SHA"
+#define TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA         "ECDHE-RSA-AES256-SHA"
+
+#define TLS1_TXT_ECDH_anon_WITH_NULL_SHA                "AECDH-NULL-SHA"
+#define TLS1_TXT_ECDH_anon_WITH_RC4_128_SHA             "AECDH-RC4-SHA"
+#define TLS1_TXT_ECDH_anon_WITH_DES_192_CBC3_SHA        "AECDH-DES-CBC3-SHA"
+#define TLS1_TXT_ECDH_anon_WITH_AES_128_CBC_SHA         "AECDH-AES128-SHA"
+#define TLS1_TXT_ECDH_anon_WITH_AES_256_CBC_SHA         "AECDH-AES256-SHA"
+
+/* Camellia ciphersuites form RFC4132 */
+#define TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA		"CAMELLIA128-SHA"
+#define TLS1_TXT_DH_DSS_WITH_CAMELLIA_128_CBC_SHA	"DH-DSS-CAMELLIA128-SHA"
+#define TLS1_TXT_DH_RSA_WITH_CAMELLIA_128_CBC_SHA	"DH-RSA-CAMELLIA128-SHA"
+#define TLS1_TXT_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA	"DHE-DSS-CAMELLIA128-SHA"
+#define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA	"DHE-RSA-CAMELLIA128-SHA"
+#define TLS1_TXT_ADH_WITH_CAMELLIA_128_CBC_SHA		"ADH-CAMELLIA128-SHA"
+
+#define TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA		"CAMELLIA256-SHA"
+#define TLS1_TXT_DH_DSS_WITH_CAMELLIA_256_CBC_SHA	"DH-DSS-CAMELLIA256-SHA"
+#define TLS1_TXT_DH_RSA_WITH_CAMELLIA_256_CBC_SHA	"DH-RSA-CAMELLIA256-SHA"
+#define TLS1_TXT_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA	"DHE-DSS-CAMELLIA256-SHA"
+#define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA	"DHE-RSA-CAMELLIA256-SHA"
+#define TLS1_TXT_ADH_WITH_CAMELLIA_256_CBC_SHA		"ADH-CAMELLIA256-SHA"
+
+
+#define TLS_CT_RSA_SIGN			1
+#define TLS_CT_DSS_SIGN			2
+#define TLS_CT_RSA_FIXED_DH		3
+#define TLS_CT_DSS_FIXED_DH		4
+#define TLS_CT_ECDSA_SIGN		64
+#define TLS_CT_RSA_FIXED_ECDH		65
+#define TLS_CT_ECDSA_FIXED_ECDH 	66
+#define TLS_CT_NUMBER			7
+
+#define TLS1_FINISH_MAC_LENGTH		12
+
+#define TLS_MD_MAX_CONST_SIZE			20
+#define TLS_MD_CLIENT_FINISH_CONST		"client finished"
+#define TLS_MD_CLIENT_FINISH_CONST_SIZE		15
+#define TLS_MD_SERVER_FINISH_CONST		"server finished"
+#define TLS_MD_SERVER_FINISH_CONST_SIZE		15
+#define TLS_MD_SERVER_WRITE_KEY_CONST		"server write key"
+#define TLS_MD_SERVER_WRITE_KEY_CONST_SIZE	16
+#define TLS_MD_KEY_EXPANSION_CONST		"key expansion"
+#define TLS_MD_KEY_EXPANSION_CONST_SIZE		13
+#define TLS_MD_CLIENT_WRITE_KEY_CONST		"client write key"
+#define TLS_MD_CLIENT_WRITE_KEY_CONST_SIZE	16
+#define TLS_MD_SERVER_WRITE_KEY_CONST		"server write key"
+#define TLS_MD_SERVER_WRITE_KEY_CONST_SIZE	16
+#define TLS_MD_IV_BLOCK_CONST			"IV block"
+#define TLS_MD_IV_BLOCK_CONST_SIZE		8
+#define TLS_MD_MASTER_SECRET_CONST		"master secret"
+#define TLS_MD_MASTER_SECRET_CONST_SIZE		13
+
+#ifdef CHARSET_EBCDIC
+#undef TLS_MD_CLIENT_FINISH_CONST
+#define TLS_MD_CLIENT_FINISH_CONST    "\x63\x6c\x69\x65\x6e\x74\x20\x66\x69\x6e\x69\x73\x68\x65\x64"  /*client finished*/
+#undef TLS_MD_SERVER_FINISH_CONST
+#define TLS_MD_SERVER_FINISH_CONST    "\x73\x65\x72\x76\x65\x72\x20\x66\x69\x6e\x69\x73\x68\x65\x64"  /*server finished*/
+#undef TLS_MD_SERVER_WRITE_KEY_CONST
+#define TLS_MD_SERVER_WRITE_KEY_CONST "\x73\x65\x72\x76\x65\x72\x20\x77\x72\x69\x74\x65\x20\x6b\x65\x79"  /*server write key*/
+#undef TLS_MD_KEY_EXPANSION_CONST
+#define TLS_MD_KEY_EXPANSION_CONST    "\x6b\x65\x79\x20\x65\x78\x70\x61\x6e\x73\x69\x6f\x6e"  /*key expansion*/
+#undef TLS_MD_CLIENT_WRITE_KEY_CONST
+#define TLS_MD_CLIENT_WRITE_KEY_CONST "\x63\x6c\x69\x65\x6e\x74\x20\x77\x72\x69\x74\x65\x20\x6b\x65\x79"  /*client write key*/
+#undef TLS_MD_SERVER_WRITE_KEY_CONST
+#define TLS_MD_SERVER_WRITE_KEY_CONST "\x73\x65\x72\x76\x65\x72\x20\x77\x72\x69\x74\x65\x20\x6b\x65\x79"  /*server write key*/
+#undef TLS_MD_IV_BLOCK_CONST
+#define TLS_MD_IV_BLOCK_CONST         "\x49\x56\x20\x62\x6c\x6f\x63\x6b"  /*IV block*/
+#undef TLS_MD_MASTER_SECRET_CONST
+#define TLS_MD_MASTER_SECRET_CONST    "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74"  /*master secret*/
+#endif
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
+
+
+
diff --git a/dep/include/openssl/tmdiff.h b/dep/include/openssl/tmdiff.h
new file mode 100644
index 00000000000..af5c41c6499
--- /dev/null
+++ b/dep/include/openssl/tmdiff.h
@@ -0,0 +1,93 @@
+/* crypto/tmdiff.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/* Header for dynamic hash table routines
+ * Author - Eric Young
+ */
+/* ... erm yeah, "dynamic hash tables" you say?
+ * 
+ * And what would dynamic hash tables have to do with any of this code *now*?
+ * AFAICS, this code is only referenced by crypto/bn/exp.c which is an unused
+ * file that I doubt compiles any more. speed.c is the only thing that could
+ * use this (and it has nothing to do with hash tables), yet it instead has its
+ * own duplication of all this stuff and looks, if anything, more complete. See
+ * the corresponding note in apps/speed.c.
+ * The Bemused - Geoff
+ */
+
+#ifndef HEADER_TMDIFF_H
+#define HEADER_TMDIFF_H
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+typedef struct ms_tm MS_TM;
+
+MS_TM *ms_time_new(void );
+void ms_time_free(MS_TM *a);
+void ms_time_get(MS_TM *a);
+double ms_time_diff(MS_TM *start, MS_TM *end);
+int ms_time_cmp(const MS_TM *ap, const MS_TM *bp);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/dep/include/openssl/txt_db.h b/dep/include/openssl/txt_db.h
new file mode 100644
index 00000000000..307e1ba23fc
--- /dev/null
+++ b/dep/include/openssl/txt_db.h
@@ -0,0 +1,109 @@
+/* crypto/txt_db/txt_db.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_TXT_DB_H
+#define HEADER_TXT_DB_H
+
+#include 
+#ifndef OPENSSL_NO_BIO
+#include 
+#endif
+#include 
+#include 
+
+#define DB_ERROR_OK			0
+#define DB_ERROR_MALLOC			1
+#define DB_ERROR_INDEX_CLASH    	2
+#define DB_ERROR_INDEX_OUT_OF_RANGE	3
+#define DB_ERROR_NO_INDEX		4
+#define DB_ERROR_INSERT_INDEX_CLASH    	5
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+typedef struct txt_db_st
+	{
+	int num_fields;
+	STACK /* char ** */ *data;
+	LHASH **index;
+	int (**qual)(char **);
+	long error;
+	long arg1;
+	long arg2;
+	char **arg_row;
+	} TXT_DB;
+
+#ifndef OPENSSL_NO_BIO
+TXT_DB *TXT_DB_read(BIO *in, int num);
+long TXT_DB_write(BIO *out, TXT_DB *db);
+#else
+TXT_DB *TXT_DB_read(char *in, int num);
+long TXT_DB_write(char *out, TXT_DB *db);
+#endif
+int TXT_DB_create_index(TXT_DB *db,int field,int (*qual)(char **),
+		LHASH_HASH_FN_TYPE hash, LHASH_COMP_FN_TYPE cmp);
+void TXT_DB_free(TXT_DB *db);
+char **TXT_DB_get_by_index(TXT_DB *db, int idx, char **value);
+int TXT_DB_insert(TXT_DB *db,char **value);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff --git a/dep/include/openssl/ui.h b/dep/include/openssl/ui.h
new file mode 100644
index 00000000000..018296412b1
--- /dev/null
+++ b/dep/include/openssl/ui.h
@@ -0,0 +1,381 @@
+/* crypto/ui/ui.h -*- mode:C; c-file-style: "eay" -*- */
+/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL
+ * project 2001.
+ */
+/* ====================================================================
+ * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_UI_H
+#define HEADER_UI_H
+
+#ifndef OPENSSL_NO_DEPRECATED
+#include 
+#endif
+#include 
+#include 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* Declared already in ossl_typ.h */
+/* typedef struct ui_st UI; */
+/* typedef struct ui_method_st UI_METHOD; */
+
+
+/* All the following functions return -1 or NULL on error and in some cases
+   (UI_process()) -2 if interrupted or in some other way cancelled.
+   When everything is fine, they return 0, a positive value or a non-NULL
+   pointer, all depending on their purpose. */
+
+/* Creators and destructor.   */
+UI *UI_new(void);
+UI *UI_new_method(const UI_METHOD *method);
+void UI_free(UI *ui);
+
+/* The following functions are used to add strings to be printed and prompt
+   strings to prompt for data.  The names are UI_{add,dup}__string
+   and UI_{add,dup}_input_boolean.
+
+   UI_{add,dup}__string have the following meanings:
+	add	add a text or prompt string.  The pointers given to these
+		functions are used verbatim, no copying is done.
+	dup	make a copy of the text or prompt string, then add the copy
+		to the collection of strings in the user interface.
+	
+		The function is a name for the functionality that the given
+		string shall be used for.  It can be one of:
+			input	use the string as data prompt.
+			verify	use the string as verification prompt.  This
+				is used to verify a previous input.
+			info	use the string for informational output.
+			error	use the string for error output.
+   Honestly, there's currently no difference between info and error for the
+   moment.
+
+   UI_{add,dup}_input_boolean have the same semantics for "add" and "dup",
+   and are typically used when one wants to prompt for a yes/no response.
+
+
+   All of the functions in this group take a UI and a prompt string.
+   The string input and verify addition functions also take a flag argument,
+   a buffer for the result to end up with, a minimum input size and a maximum
+   input size (the result buffer MUST be large enough to be able to contain
+   the maximum number of characters).  Additionally, the verify addition
+   functions takes another buffer to compare the result against.
+   The boolean input functions take an action description string (which should
+   be safe to ignore if the expected user action is obvious, for example with
+   a dialog box with an OK button and a Cancel button), a string of acceptable
+   characters to mean OK and to mean Cancel.  The two last strings are checked
+   to make sure they don't have common characters.  Additionally, the same
+   flag argument as for the string input is taken, as well as a result buffer.
+   The result buffer is required to be at least one byte long.  Depending on
+   the answer, the first character from the OK or the Cancel character strings
+   will be stored in the first byte of the result buffer.  No NUL will be
+   added, so the result is *not* a string.
+
+   On success, the all return an index of the added information.  That index
+   is usefull when retrieving results with UI_get0_result(). */
+int UI_add_input_string(UI *ui, const char *prompt, int flags,
+	char *result_buf, int minsize, int maxsize);
+int UI_dup_input_string(UI *ui, const char *prompt, int flags,
+	char *result_buf, int minsize, int maxsize);
+int UI_add_verify_string(UI *ui, const char *prompt, int flags,
+	char *result_buf, int minsize, int maxsize, const char *test_buf);
+int UI_dup_verify_string(UI *ui, const char *prompt, int flags,
+	char *result_buf, int minsize, int maxsize, const char *test_buf);
+int UI_add_input_boolean(UI *ui, const char *prompt, const char *action_desc,
+	const char *ok_chars, const char *cancel_chars,
+	int flags, char *result_buf);
+int UI_dup_input_boolean(UI *ui, const char *prompt, const char *action_desc,
+	const char *ok_chars, const char *cancel_chars,
+	int flags, char *result_buf);
+int UI_add_info_string(UI *ui, const char *text);
+int UI_dup_info_string(UI *ui, const char *text);
+int UI_add_error_string(UI *ui, const char *text);
+int UI_dup_error_string(UI *ui, const char *text);
+
+/* These are the possible flags.  They can be or'ed together. */
+/* Use to have echoing of input */
+#define UI_INPUT_FLAG_ECHO		0x01
+/* Use a default password.  Where that password is found is completely
+   up to the application, it might for example be in the user data set
+   with UI_add_user_data().  It is not recommended to have more than
+   one input in each UI being marked with this flag, or the application
+   might get confused. */
+#define UI_INPUT_FLAG_DEFAULT_PWD	0x02
+
+/* The user of these routines may want to define flags of their own.  The core
+   UI won't look at those, but will pass them on to the method routines.  They
+   must use higher bits so they don't get confused with the UI bits above.
+   UI_INPUT_FLAG_USER_BASE tells which is the lowest bit to use.  A good
+   example of use is this:
+
+	#define MY_UI_FLAG1	(0x01 << UI_INPUT_FLAG_USER_BASE)
+
+*/
+#define UI_INPUT_FLAG_USER_BASE	16
+
+
+/* The following function helps construct a prompt.  object_desc is a
+   textual short description of the object, for example "pass phrase",
+   and object_name is the name of the object (might be a card name or
+   a file name.
+   The returned string shall always be allocated on the heap with
+   OPENSSL_malloc(), and need to be free'd with OPENSSL_free().
+
+   If the ui_method doesn't contain a pointer to a user-defined prompt
+   constructor, a default string is built, looking like this:
+
+	"Enter {object_desc} for {object_name}:"
+
+   So, if object_desc has the value "pass phrase" and object_name has
+   the value "foo.key", the resulting string is:
+
+	"Enter pass phrase for foo.key:"
+*/
+char *UI_construct_prompt(UI *ui_method,
+	const char *object_desc, const char *object_name);
+
+
+/* The following function is used to store a pointer to user-specific data.
+   Any previous such pointer will be returned and replaced.
+
+   For callback purposes, this function makes a lot more sense than using
+   ex_data, since the latter requires that different parts of OpenSSL or
+   applications share the same ex_data index.
+
+   Note that the UI_OpenSSL() method completely ignores the user data.
+   Other methods may not, however.  */
+void *UI_add_user_data(UI *ui, void *user_data);
+/* We need a user data retrieving function as well.  */
+void *UI_get0_user_data(UI *ui);
+
+/* Return the result associated with a prompt given with the index i. */
+const char *UI_get0_result(UI *ui, int i);
+
+/* When all strings have been added, process the whole thing. */
+int UI_process(UI *ui);
+
+/* Give a user interface parametrised control commands.  This can be used to
+   send down an integer, a data pointer or a function pointer, as well as
+   be used to get information from a UI. */
+int UI_ctrl(UI *ui, int cmd, long i, void *p, void (*f)(void));
+
+/* The commands */
+/* Use UI_CONTROL_PRINT_ERRORS with the value 1 to have UI_process print the
+   OpenSSL error stack before printing any info or added error messages and
+   before any prompting. */
+#define UI_CTRL_PRINT_ERRORS		1
+/* Check if a UI_process() is possible to do again with the same instance of
+   a user interface.  This makes UI_ctrl() return 1 if it is redoable, and 0
+   if not. */
+#define UI_CTRL_IS_REDOABLE		2
+
+
+/* Some methods may use extra data */
+#define UI_set_app_data(s,arg)         UI_set_ex_data(s,0,arg)
+#define UI_get_app_data(s)             UI_get_ex_data(s,0)
+int UI_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+	CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int UI_set_ex_data(UI *r,int idx,void *arg);
+void *UI_get_ex_data(UI *r, int idx);
+
+/* Use specific methods instead of the built-in one */
+void UI_set_default_method(const UI_METHOD *meth);
+const UI_METHOD *UI_get_default_method(void);
+const UI_METHOD *UI_get_method(UI *ui);
+const UI_METHOD *UI_set_method(UI *ui, const UI_METHOD *meth);
+
+/* The method with all the built-in thingies */
+UI_METHOD *UI_OpenSSL(void);
+
+
+/* ---------- For method writers ---------- */
+/* A method contains a number of functions that implement the low level
+   of the User Interface.  The functions are:
+
+	an opener	This function starts a session, maybe by opening
+			a channel to a tty, or by opening a window.
+	a writer	This function is called to write a given string,
+			maybe to the tty, maybe as a field label in a
+			window.
+	a flusher	This function is called to flush everything that
+			has been output so far.  It can be used to actually
+			display a dialog box after it has been built.
+	a reader	This function is called to read a given prompt,
+			maybe from the tty, maybe from a field in a
+			window.  Note that it's called wth all string
+			structures, not only the prompt ones, so it must
+			check such things itself.
+	a closer	This function closes the session, maybe by closing
+			the channel to the tty, or closing the window.
+
+   All these functions are expected to return:
+
+	0	on error.
+	1	on success.
+	-1	on out-of-band events, for example if some prompting has
+		been canceled (by pressing Ctrl-C, for example).  This is
+		only checked when returned by the flusher or the reader.
+
+   The way this is used, the opener is first called, then the writer for all
+   strings, then the flusher, then the reader for all strings and finally the
+   closer.  Note that if you want to prompt from a terminal or other command
+   line interface, the best is to have the reader also write the prompts
+   instead of having the writer do it.  If you want to prompt from a dialog
+   box, the writer can be used to build up the contents of the box, and the
+   flusher to actually display the box and run the event loop until all data
+   has been given, after which the reader only grabs the given data and puts
+   them back into the UI strings.
+
+   All method functions take a UI as argument.  Additionally, the writer and
+   the reader take a UI_STRING.
+*/
+
+/* The UI_STRING type is the data structure that contains all the needed info
+   about a string or a prompt, including test data for a verification prompt.
+*/
+DECLARE_STACK_OF(UI_STRING)
+typedef struct ui_string_st UI_STRING;
+
+/* The different types of strings that are currently supported.
+   This is only needed by method authors. */
+enum UI_string_types
+	{
+	UIT_NONE=0,
+	UIT_PROMPT,		/* Prompt for a string */
+	UIT_VERIFY,		/* Prompt for a string and verify */
+	UIT_BOOLEAN,		/* Prompt for a yes/no response */
+	UIT_INFO,		/* Send info to the user */
+	UIT_ERROR		/* Send an error message to the user */
+	};
+
+/* Create and manipulate methods */
+UI_METHOD *UI_create_method(char *name);
+void UI_destroy_method(UI_METHOD *ui_method);
+int UI_method_set_opener(UI_METHOD *method, int (*opener)(UI *ui));
+int UI_method_set_writer(UI_METHOD *method, int (*writer)(UI *ui, UI_STRING *uis));
+int UI_method_set_flusher(UI_METHOD *method, int (*flusher)(UI *ui));
+int UI_method_set_reader(UI_METHOD *method, int (*reader)(UI *ui, UI_STRING *uis));
+int UI_method_set_closer(UI_METHOD *method, int (*closer)(UI *ui));
+int (*UI_method_get_opener(UI_METHOD *method))(UI*);
+int (*UI_method_get_writer(UI_METHOD *method))(UI*,UI_STRING*);
+int (*UI_method_get_flusher(UI_METHOD *method))(UI*);
+int (*UI_method_get_reader(UI_METHOD *method))(UI*,UI_STRING*);
+int (*UI_method_get_closer(UI_METHOD *method))(UI*);
+
+/* The following functions are helpers for method writers to access relevant
+   data from a UI_STRING. */
+
+/* Return type of the UI_STRING */
+enum UI_string_types UI_get_string_type(UI_STRING *uis);
+/* Return input flags of the UI_STRING */
+int UI_get_input_flags(UI_STRING *uis);
+/* Return the actual string to output (the prompt, info or error) */
+const char *UI_get0_output_string(UI_STRING *uis);
+/* Return the optional action string to output (the boolean promtp instruction) */
+const char *UI_get0_action_string(UI_STRING *uis);
+/* Return the result of a prompt */
+const char *UI_get0_result_string(UI_STRING *uis);
+/* Return the string to test the result against.  Only useful with verifies. */
+const char *UI_get0_test_string(UI_STRING *uis);
+/* Return the required minimum size of the result */
+int UI_get_result_minsize(UI_STRING *uis);
+/* Return the required maximum size of the result */
+int UI_get_result_maxsize(UI_STRING *uis);
+/* Set the result of a UI_STRING. */
+int UI_set_result(UI *ui, UI_STRING *uis, const char *result);
+
+
+/* A couple of popular utility functions */
+int UI_UTIL_read_pw_string(char *buf,int length,const char *prompt,int verify);
+int UI_UTIL_read_pw(char *buf,char *buff,int size,const char *prompt,int verify);
+
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_UI_strings(void);
+
+/* Error codes for the UI functions. */
+
+/* Function codes. */
+#define UI_F_GENERAL_ALLOCATE_BOOLEAN			 108
+#define UI_F_GENERAL_ALLOCATE_PROMPT			 109
+#define UI_F_GENERAL_ALLOCATE_STRING			 100
+#define UI_F_UI_CTRL					 111
+#define UI_F_UI_DUP_ERROR_STRING			 101
+#define UI_F_UI_DUP_INFO_STRING				 102
+#define UI_F_UI_DUP_INPUT_BOOLEAN			 110
+#define UI_F_UI_DUP_INPUT_STRING			 103
+#define UI_F_UI_DUP_VERIFY_STRING			 106
+#define UI_F_UI_GET0_RESULT				 107
+#define UI_F_UI_NEW_METHOD				 104
+#define UI_F_UI_SET_RESULT				 105
+
+/* Reason codes. */
+#define UI_R_COMMON_OK_AND_CANCEL_CHARACTERS		 104
+#define UI_R_INDEX_TOO_LARGE				 102
+#define UI_R_INDEX_TOO_SMALL				 103
+#define UI_R_NO_RESULT_BUFFER				 105
+#define UI_R_RESULT_TOO_LARGE				 100
+#define UI_R_RESULT_TOO_SMALL				 101
+#define UI_R_UNKNOWN_CONTROL_COMMAND			 106
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/dep/include/openssl/ui_compat.h b/dep/include/openssl/ui_compat.h
new file mode 100644
index 00000000000..b35c9bb7fd3
--- /dev/null
+++ b/dep/include/openssl/ui_compat.h
@@ -0,0 +1,83 @@
+/* crypto/ui/ui.h -*- mode:C; c-file-style: "eay" -*- */
+/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL
+ * project 2001.
+ */
+/* ====================================================================
+ * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_UI_COMPAT_H
+#define HEADER_UI_COMPAT_H
+
+#include 
+#include 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* The following functions were previously part of the DES section,
+   and are provided here for backward compatibility reasons. */
+
+#define des_read_pw_string(b,l,p,v) \
+	_ossl_old_des_read_pw_string((b),(l),(p),(v))
+#define des_read_pw(b,bf,s,p,v) \
+	_ossl_old_des_read_pw((b),(bf),(s),(p),(v))
+
+int _ossl_old_des_read_pw_string(char *buf,int length,const char *prompt,int verify);
+int _ossl_old_des_read_pw(char *buf,char *buff,int size,const char *prompt,int verify);
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/dep/include/openssl/x509.h b/dep/include/openssl/x509.h
new file mode 100644
index 00000000000..16a954f7099
--- /dev/null
+++ b/dep/include/openssl/x509.h
@@ -0,0 +1,1344 @@
+/* crypto/x509/x509.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECDH support in OpenSSL originally developed by 
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#ifndef HEADER_X509_H
+#define HEADER_X509_H
+
+#include 
+#include 
+#ifndef OPENSSL_NO_BUFFER
+#include 
+#endif
+#ifndef OPENSSL_NO_EVP
+#include 
+#endif
+#ifndef OPENSSL_NO_BIO
+#include 
+#endif
+#include 
+#include 
+#include 
+
+#ifndef OPENSSL_NO_EC
+#include 
+#endif
+
+#ifndef OPENSSL_NO_ECDSA
+#include 
+#endif
+
+#ifndef OPENSSL_NO_ECDH
+#include 
+#endif
+
+#ifndef OPENSSL_NO_DEPRECATED
+#ifndef OPENSSL_NO_RSA
+#include 
+#endif
+#ifndef OPENSSL_NO_DSA
+#include 
+#endif
+#ifndef OPENSSL_NO_DH
+#include 
+#endif
+#endif
+
+#ifndef OPENSSL_NO_SHA
+#include 
+#endif
+#include 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#ifdef OPENSSL_SYS_WIN32
+/* Under Win32 these are defined in wincrypt.h */
+#undef X509_NAME
+#undef X509_CERT_PAIR
+#endif
+
+#define X509_FILETYPE_PEM	1
+#define X509_FILETYPE_ASN1	2
+#define X509_FILETYPE_DEFAULT	3
+
+#define X509v3_KU_DIGITAL_SIGNATURE	0x0080
+#define X509v3_KU_NON_REPUDIATION	0x0040
+#define X509v3_KU_KEY_ENCIPHERMENT	0x0020
+#define X509v3_KU_DATA_ENCIPHERMENT	0x0010
+#define X509v3_KU_KEY_AGREEMENT		0x0008
+#define X509v3_KU_KEY_CERT_SIGN		0x0004
+#define X509v3_KU_CRL_SIGN		0x0002
+#define X509v3_KU_ENCIPHER_ONLY		0x0001
+#define X509v3_KU_DECIPHER_ONLY		0x8000
+#define X509v3_KU_UNDEF			0xffff
+
+typedef struct X509_objects_st
+	{
+	int nid;
+	int (*a2i)(void);
+	int (*i2a)(void);
+	} X509_OBJECTS;
+
+struct X509_algor_st
+	{
+	ASN1_OBJECT *algorithm;
+	ASN1_TYPE *parameter;
+	} /* X509_ALGOR */;
+
+DECLARE_STACK_OF(X509_ALGOR)
+DECLARE_ASN1_SET_OF(X509_ALGOR)
+
+typedef struct X509_val_st
+	{
+	ASN1_TIME *notBefore;
+	ASN1_TIME *notAfter;
+	} X509_VAL;
+
+typedef struct X509_pubkey_st
+	{
+	X509_ALGOR *algor;
+	ASN1_BIT_STRING *public_key;
+	EVP_PKEY *pkey;
+	} X509_PUBKEY;
+
+typedef struct X509_sig_st
+	{
+	X509_ALGOR *algor;
+	ASN1_OCTET_STRING *digest;
+	} X509_SIG;
+
+typedef struct X509_name_entry_st
+	{
+	ASN1_OBJECT *object;
+	ASN1_STRING *value;
+	int set;
+	int size; 	/* temp variable */
+	} X509_NAME_ENTRY;
+
+DECLARE_STACK_OF(X509_NAME_ENTRY)
+DECLARE_ASN1_SET_OF(X509_NAME_ENTRY)
+
+/* we always keep X509_NAMEs in 2 forms. */
+struct X509_name_st
+	{
+	STACK_OF(X509_NAME_ENTRY) *entries;
+	int modified;	/* true if 'bytes' needs to be built */
+#ifndef OPENSSL_NO_BUFFER
+	BUF_MEM *bytes;
+#else
+	char *bytes;
+#endif
+	unsigned long hash; /* Keep the hash around for lookups */
+	} /* X509_NAME */;
+
+DECLARE_STACK_OF(X509_NAME)
+
+#define X509_EX_V_NETSCAPE_HACK		0x8000
+#define X509_EX_V_INIT			0x0001
+typedef struct X509_extension_st
+	{
+	ASN1_OBJECT *object;
+	ASN1_BOOLEAN critical;
+	ASN1_OCTET_STRING *value;
+	} X509_EXTENSION;
+
+DECLARE_STACK_OF(X509_EXTENSION)
+DECLARE_ASN1_SET_OF(X509_EXTENSION)
+
+/* a sequence of these are used */
+typedef struct x509_attributes_st
+	{
+	ASN1_OBJECT *object;
+	int single; /* 0 for a set, 1 for a single item (which is wrong) */
+	union	{
+		char		*ptr;
+/* 0 */		STACK_OF(ASN1_TYPE) *set;
+/* 1 */		ASN1_TYPE	*single;
+		} value;
+	} X509_ATTRIBUTE;
+
+DECLARE_STACK_OF(X509_ATTRIBUTE)
+DECLARE_ASN1_SET_OF(X509_ATTRIBUTE)
+
+
+typedef struct X509_req_info_st
+	{
+	ASN1_ENCODING enc;
+	ASN1_INTEGER *version;
+	X509_NAME *subject;
+	X509_PUBKEY *pubkey;
+	/*  d=2 hl=2 l=  0 cons: cont: 00 */
+	STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */
+	} X509_REQ_INFO;
+
+typedef struct X509_req_st
+	{
+	X509_REQ_INFO *req_info;
+	X509_ALGOR *sig_alg;
+	ASN1_BIT_STRING *signature;
+	int references;
+	} X509_REQ;
+
+typedef struct x509_cinf_st
+	{
+	ASN1_INTEGER *version;		/* [ 0 ] default of v1 */
+	ASN1_INTEGER *serialNumber;
+	X509_ALGOR *signature;
+	X509_NAME *issuer;
+	X509_VAL *validity;
+	X509_NAME *subject;
+	X509_PUBKEY *key;
+	ASN1_BIT_STRING *issuerUID;		/* [ 1 ] optional in v2 */
+	ASN1_BIT_STRING *subjectUID;		/* [ 2 ] optional in v2 */
+	STACK_OF(X509_EXTENSION) *extensions;	/* [ 3 ] optional in v3 */
+	} X509_CINF;
+
+/* This stuff is certificate "auxiliary info"
+ * it contains details which are useful in certificate
+ * stores and databases. When used this is tagged onto
+ * the end of the certificate itself
+ */
+
+typedef struct x509_cert_aux_st
+	{
+	STACK_OF(ASN1_OBJECT) *trust;		/* trusted uses */
+	STACK_OF(ASN1_OBJECT) *reject;		/* rejected uses */
+	ASN1_UTF8STRING *alias;			/* "friendly name" */
+	ASN1_OCTET_STRING *keyid;		/* key id of private key */
+	STACK_OF(X509_ALGOR) *other;		/* other unspecified info */
+	} X509_CERT_AUX;
+
+struct x509_st
+	{
+	X509_CINF *cert_info;
+	X509_ALGOR *sig_alg;
+	ASN1_BIT_STRING *signature;
+	int valid;
+	int references;
+	char *name;
+	CRYPTO_EX_DATA ex_data;
+	/* These contain copies of various extension values */
+	long ex_pathlen;
+	long ex_pcpathlen;
+	unsigned long ex_flags;
+	unsigned long ex_kusage;
+	unsigned long ex_xkusage;
+	unsigned long ex_nscert;
+	ASN1_OCTET_STRING *skid;
+	struct AUTHORITY_KEYID_st *akid;
+	X509_POLICY_CACHE *policy_cache;
+#ifndef OPENSSL_NO_RFC3779
+	STACK_OF(IPAddressFamily) *rfc3779_addr;
+	struct ASIdentifiers_st *rfc3779_asid;
+#endif
+#ifndef OPENSSL_NO_SHA
+	unsigned char sha1_hash[SHA_DIGEST_LENGTH];
+#endif
+	X509_CERT_AUX *aux;
+	} /* X509 */;
+
+DECLARE_STACK_OF(X509)
+DECLARE_ASN1_SET_OF(X509)
+
+/* This is used for a table of trust checking functions */
+
+typedef struct x509_trust_st {
+	int trust;
+	int flags;
+	int (*check_trust)(struct x509_trust_st *, X509 *, int);
+	char *name;
+	int arg1;
+	void *arg2;
+} X509_TRUST;
+
+DECLARE_STACK_OF(X509_TRUST)
+
+typedef struct x509_cert_pair_st {
+	X509 *forward;
+	X509 *reverse;
+} X509_CERT_PAIR;
+
+/* standard trust ids */
+
+#define X509_TRUST_DEFAULT	-1	/* Only valid in purpose settings */
+
+#define X509_TRUST_COMPAT	1
+#define X509_TRUST_SSL_CLIENT	2
+#define X509_TRUST_SSL_SERVER	3
+#define X509_TRUST_EMAIL	4
+#define X509_TRUST_OBJECT_SIGN	5
+#define X509_TRUST_OCSP_SIGN	6
+#define X509_TRUST_OCSP_REQUEST	7
+
+/* Keep these up to date! */
+#define X509_TRUST_MIN		1
+#define X509_TRUST_MAX		7
+
+
+/* trust_flags values */
+#define	X509_TRUST_DYNAMIC 	1
+#define	X509_TRUST_DYNAMIC_NAME	2
+
+/* check_trust return codes */
+
+#define X509_TRUST_TRUSTED	1
+#define X509_TRUST_REJECTED	2
+#define X509_TRUST_UNTRUSTED	3
+
+/* Flags for X509_print_ex() */
+
+#define	X509_FLAG_COMPAT		0
+#define	X509_FLAG_NO_HEADER		1L
+#define	X509_FLAG_NO_VERSION		(1L << 1)
+#define	X509_FLAG_NO_SERIAL		(1L << 2)
+#define	X509_FLAG_NO_SIGNAME		(1L << 3)
+#define	X509_FLAG_NO_ISSUER		(1L << 4)
+#define	X509_FLAG_NO_VALIDITY		(1L << 5)
+#define	X509_FLAG_NO_SUBJECT		(1L << 6)
+#define	X509_FLAG_NO_PUBKEY		(1L << 7)
+#define	X509_FLAG_NO_EXTENSIONS		(1L << 8)
+#define	X509_FLAG_NO_SIGDUMP		(1L << 9)
+#define	X509_FLAG_NO_AUX		(1L << 10)
+#define	X509_FLAG_NO_ATTRIBUTES		(1L << 11)
+
+/* Flags specific to X509_NAME_print_ex() */	
+
+/* The field separator information */
+
+#define XN_FLAG_SEP_MASK	(0xf << 16)
+
+#define XN_FLAG_COMPAT		0		/* Traditional SSLeay: use old X509_NAME_print */
+#define XN_FLAG_SEP_COMMA_PLUS	(1 << 16)	/* RFC2253 ,+ */
+#define XN_FLAG_SEP_CPLUS_SPC	(2 << 16)	/* ,+ spaced: more readable */
+#define XN_FLAG_SEP_SPLUS_SPC	(3 << 16)	/* ;+ spaced */
+#define XN_FLAG_SEP_MULTILINE	(4 << 16)	/* One line per field */
+
+#define XN_FLAG_DN_REV		(1 << 20)	/* Reverse DN order */
+
+/* How the field name is shown */
+
+#define XN_FLAG_FN_MASK		(0x3 << 21)
+
+#define XN_FLAG_FN_SN		0		/* Object short name */
+#define XN_FLAG_FN_LN		(1 << 21)	/* Object long name */
+#define XN_FLAG_FN_OID		(2 << 21)	/* Always use OIDs */
+#define XN_FLAG_FN_NONE		(3 << 21)	/* No field names */
+
+#define XN_FLAG_SPC_EQ		(1 << 23)	/* Put spaces round '=' */
+
+/* This determines if we dump fields we don't recognise:
+ * RFC2253 requires this.
+ */
+
+#define XN_FLAG_DUMP_UNKNOWN_FIELDS (1 << 24)
+
+#define XN_FLAG_FN_ALIGN	(1 << 25)	/* Align field names to 20 characters */
+
+/* Complete set of RFC2253 flags */
+
+#define XN_FLAG_RFC2253 (ASN1_STRFLGS_RFC2253 | \
+			XN_FLAG_SEP_COMMA_PLUS | \
+			XN_FLAG_DN_REV | \
+			XN_FLAG_FN_SN | \
+			XN_FLAG_DUMP_UNKNOWN_FIELDS)
+
+/* readable oneline form */
+
+#define XN_FLAG_ONELINE (ASN1_STRFLGS_RFC2253 | \
+			ASN1_STRFLGS_ESC_QUOTE | \
+			XN_FLAG_SEP_CPLUS_SPC | \
+			XN_FLAG_SPC_EQ | \
+			XN_FLAG_FN_SN)
+
+/* readable multiline form */
+
+#define XN_FLAG_MULTILINE (ASN1_STRFLGS_ESC_CTRL | \
+			ASN1_STRFLGS_ESC_MSB | \
+			XN_FLAG_SEP_MULTILINE | \
+			XN_FLAG_SPC_EQ | \
+			XN_FLAG_FN_LN | \
+			XN_FLAG_FN_ALIGN)
+
+typedef struct X509_revoked_st
+	{
+	ASN1_INTEGER *serialNumber;
+	ASN1_TIME *revocationDate;
+	STACK_OF(X509_EXTENSION) /* optional */ *extensions;
+	int sequence; /* load sequence */
+	} X509_REVOKED;
+
+DECLARE_STACK_OF(X509_REVOKED)
+DECLARE_ASN1_SET_OF(X509_REVOKED)
+
+typedef struct X509_crl_info_st
+	{
+	ASN1_INTEGER *version;
+	X509_ALGOR *sig_alg;
+	X509_NAME *issuer;
+	ASN1_TIME *lastUpdate;
+	ASN1_TIME *nextUpdate;
+	STACK_OF(X509_REVOKED) *revoked;
+	STACK_OF(X509_EXTENSION) /* [0] */ *extensions;
+	ASN1_ENCODING enc;
+	} X509_CRL_INFO;
+
+struct X509_crl_st
+	{
+	/* actual signature */
+	X509_CRL_INFO *crl;
+	X509_ALGOR *sig_alg;
+	ASN1_BIT_STRING *signature;
+	int references;
+	} /* X509_CRL */;
+
+DECLARE_STACK_OF(X509_CRL)
+DECLARE_ASN1_SET_OF(X509_CRL)
+
+typedef struct private_key_st
+	{
+	int version;
+	/* The PKCS#8 data types */
+	X509_ALGOR *enc_algor;
+	ASN1_OCTET_STRING *enc_pkey;	/* encrypted pub key */
+
+	/* When decrypted, the following will not be NULL */
+	EVP_PKEY *dec_pkey;
+
+	/* used to encrypt and decrypt */
+	int key_length;
+	char *key_data;
+	int key_free;	/* true if we should auto free key_data */
+
+	/* expanded version of 'enc_algor' */
+	EVP_CIPHER_INFO cipher;
+
+	int references;
+	} X509_PKEY;
+
+#ifndef OPENSSL_NO_EVP
+typedef struct X509_info_st
+	{
+	X509 *x509;
+	X509_CRL *crl;
+	X509_PKEY *x_pkey;
+
+	EVP_CIPHER_INFO enc_cipher;
+	int enc_len;
+	char *enc_data;
+
+	int references;
+	} X509_INFO;
+
+DECLARE_STACK_OF(X509_INFO)
+#endif
+
+/* The next 2 structures and their 8 routines were sent to me by
+ * Pat Richard  and are used to manipulate
+ * Netscapes spki structures - useful if you are writing a CA web page
+ */
+typedef struct Netscape_spkac_st
+	{
+	X509_PUBKEY *pubkey;
+	ASN1_IA5STRING *challenge;	/* challenge sent in atlas >= PR2 */
+	} NETSCAPE_SPKAC;
+
+typedef struct Netscape_spki_st
+	{
+	NETSCAPE_SPKAC *spkac;	/* signed public key and challenge */
+	X509_ALGOR *sig_algor;
+	ASN1_BIT_STRING *signature;
+	} NETSCAPE_SPKI;
+
+/* Netscape certificate sequence structure */
+typedef struct Netscape_certificate_sequence
+	{
+	ASN1_OBJECT *type;
+	STACK_OF(X509) *certs;
+	} NETSCAPE_CERT_SEQUENCE;
+
+/* Unused (and iv length is wrong)
+typedef struct CBCParameter_st
+	{
+	unsigned char iv[8];
+	} CBC_PARAM;
+*/
+
+/* Password based encryption structure */
+
+typedef struct PBEPARAM_st {
+ASN1_OCTET_STRING *salt;
+ASN1_INTEGER *iter;
+} PBEPARAM;
+
+/* Password based encryption V2 structures */
+
+typedef struct PBE2PARAM_st {
+X509_ALGOR *keyfunc;
+X509_ALGOR *encryption;
+} PBE2PARAM;
+
+typedef struct PBKDF2PARAM_st {
+ASN1_TYPE *salt;	/* Usually OCTET STRING but could be anything */
+ASN1_INTEGER *iter;
+ASN1_INTEGER *keylength;
+X509_ALGOR *prf;
+} PBKDF2PARAM;
+
+
+/* PKCS#8 private key info structure */
+
+typedef struct pkcs8_priv_key_info_st
+        {
+        int broken;     /* Flag for various broken formats */
+#define PKCS8_OK		0
+#define PKCS8_NO_OCTET		1
+#define PKCS8_EMBEDDED_PARAM	2
+#define PKCS8_NS_DB		3
+        ASN1_INTEGER *version;
+        X509_ALGOR *pkeyalg;
+        ASN1_TYPE *pkey; /* Should be OCTET STRING but some are broken */
+        STACK_OF(X509_ATTRIBUTE) *attributes;
+        } PKCS8_PRIV_KEY_INFO;
+
+#ifdef  __cplusplus
+}
+#endif
+
+#include 
+#include 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#ifdef SSLEAY_MACROS
+#define X509_verify(a,r) ASN1_verify((int (*)())i2d_X509_CINF,a->sig_alg,\
+	a->signature,(char *)a->cert_info,r)
+#define X509_REQ_verify(a,r) ASN1_verify((int (*)())i2d_X509_REQ_INFO, \
+	a->sig_alg,a->signature,(char *)a->req_info,r)
+#define X509_CRL_verify(a,r) ASN1_verify((int (*)())i2d_X509_CRL_INFO, \
+	a->sig_alg, a->signature,(char *)a->crl,r)
+
+#define X509_sign(x,pkey,md) \
+	ASN1_sign((int (*)())i2d_X509_CINF, x->cert_info->signature, \
+		x->sig_alg, x->signature, (char *)x->cert_info,pkey,md)
+#define X509_REQ_sign(x,pkey,md) \
+	ASN1_sign((int (*)())i2d_X509_REQ_INFO,x->sig_alg, NULL, \
+		x->signature, (char *)x->req_info,pkey,md)
+#define X509_CRL_sign(x,pkey,md) \
+	ASN1_sign((int (*)())i2d_X509_CRL_INFO,x->crl->sig_alg,x->sig_alg, \
+		x->signature, (char *)x->crl,pkey,md)
+#define NETSCAPE_SPKI_sign(x,pkey,md) \
+	ASN1_sign((int (*)())i2d_NETSCAPE_SPKAC, x->sig_algor,NULL, \
+		x->signature, (char *)x->spkac,pkey,md)
+
+#define X509_dup(x509) (X509 *)ASN1_dup((int (*)())i2d_X509, \
+		(char *(*)())d2i_X509,(char *)x509)
+#define X509_ATTRIBUTE_dup(xa) (X509_ATTRIBUTE *)ASN1_dup(\
+		(int (*)())i2d_X509_ATTRIBUTE, \
+		(char *(*)())d2i_X509_ATTRIBUTE,(char *)xa)
+#define X509_EXTENSION_dup(ex) (X509_EXTENSION *)ASN1_dup( \
+		(int (*)())i2d_X509_EXTENSION, \
+		(char *(*)())d2i_X509_EXTENSION,(char *)ex)
+#define d2i_X509_fp(fp,x509) (X509 *)ASN1_d2i_fp((char *(*)())X509_new, \
+		(char *(*)())d2i_X509, (fp),(unsigned char **)(x509))
+#define i2d_X509_fp(fp,x509) ASN1_i2d_fp(i2d_X509,fp,(unsigned char *)x509)
+#define d2i_X509_bio(bp,x509) (X509 *)ASN1_d2i_bio((char *(*)())X509_new, \
+		(char *(*)())d2i_X509, (bp),(unsigned char **)(x509))
+#define i2d_X509_bio(bp,x509) ASN1_i2d_bio(i2d_X509,bp,(unsigned char *)x509)
+
+#define X509_CRL_dup(crl) (X509_CRL *)ASN1_dup((int (*)())i2d_X509_CRL, \
+		(char *(*)())d2i_X509_CRL,(char *)crl)
+#define d2i_X509_CRL_fp(fp,crl) (X509_CRL *)ASN1_d2i_fp((char *(*)()) \
+		X509_CRL_new,(char *(*)())d2i_X509_CRL, (fp),\
+		(unsigned char **)(crl))
+#define i2d_X509_CRL_fp(fp,crl) ASN1_i2d_fp(i2d_X509_CRL,fp,\
+		(unsigned char *)crl)
+#define d2i_X509_CRL_bio(bp,crl) (X509_CRL *)ASN1_d2i_bio((char *(*)()) \
+		X509_CRL_new,(char *(*)())d2i_X509_CRL, (bp),\
+		(unsigned char **)(crl))
+#define i2d_X509_CRL_bio(bp,crl) ASN1_i2d_bio(i2d_X509_CRL,bp,\
+		(unsigned char *)crl)
+
+#define PKCS7_dup(p7) (PKCS7 *)ASN1_dup((int (*)())i2d_PKCS7, \
+		(char *(*)())d2i_PKCS7,(char *)p7)
+#define d2i_PKCS7_fp(fp,p7) (PKCS7 *)ASN1_d2i_fp((char *(*)()) \
+		PKCS7_new,(char *(*)())d2i_PKCS7, (fp),\
+		(unsigned char **)(p7))
+#define i2d_PKCS7_fp(fp,p7) ASN1_i2d_fp(i2d_PKCS7,fp,\
+		(unsigned char *)p7)
+#define d2i_PKCS7_bio(bp,p7) (PKCS7 *)ASN1_d2i_bio((char *(*)()) \
+		PKCS7_new,(char *(*)())d2i_PKCS7, (bp),\
+		(unsigned char **)(p7))
+#define i2d_PKCS7_bio(bp,p7) ASN1_i2d_bio(i2d_PKCS7,bp,\
+		(unsigned char *)p7)
+
+#define X509_REQ_dup(req) (X509_REQ *)ASN1_dup((int (*)())i2d_X509_REQ, \
+		(char *(*)())d2i_X509_REQ,(char *)req)
+#define d2i_X509_REQ_fp(fp,req) (X509_REQ *)ASN1_d2i_fp((char *(*)())\
+		X509_REQ_new, (char *(*)())d2i_X509_REQ, (fp),\
+		(unsigned char **)(req))
+#define i2d_X509_REQ_fp(fp,req) ASN1_i2d_fp(i2d_X509_REQ,fp,\
+		(unsigned char *)req)
+#define d2i_X509_REQ_bio(bp,req) (X509_REQ *)ASN1_d2i_bio((char *(*)())\
+		X509_REQ_new, (char *(*)())d2i_X509_REQ, (bp),\
+		(unsigned char **)(req))
+#define i2d_X509_REQ_bio(bp,req) ASN1_i2d_bio(i2d_X509_REQ,bp,\
+		(unsigned char *)req)
+
+#define RSAPublicKey_dup(rsa) (RSA *)ASN1_dup((int (*)())i2d_RSAPublicKey, \
+		(char *(*)())d2i_RSAPublicKey,(char *)rsa)
+#define RSAPrivateKey_dup(rsa) (RSA *)ASN1_dup((int (*)())i2d_RSAPrivateKey, \
+		(char *(*)())d2i_RSAPrivateKey,(char *)rsa)
+
+#define d2i_RSAPrivateKey_fp(fp,rsa) (RSA *)ASN1_d2i_fp((char *(*)())\
+		RSA_new,(char *(*)())d2i_RSAPrivateKey, (fp), \
+		(unsigned char **)(rsa))
+#define i2d_RSAPrivateKey_fp(fp,rsa) ASN1_i2d_fp(i2d_RSAPrivateKey,fp, \
+		(unsigned char *)rsa)
+#define d2i_RSAPrivateKey_bio(bp,rsa) (RSA *)ASN1_d2i_bio((char *(*)())\
+		RSA_new,(char *(*)())d2i_RSAPrivateKey, (bp), \
+		(unsigned char **)(rsa))
+#define i2d_RSAPrivateKey_bio(bp,rsa) ASN1_i2d_bio(i2d_RSAPrivateKey,bp, \
+		(unsigned char *)rsa)
+
+#define d2i_RSAPublicKey_fp(fp,rsa) (RSA *)ASN1_d2i_fp((char *(*)())\
+		RSA_new,(char *(*)())d2i_RSAPublicKey, (fp), \
+		(unsigned char **)(rsa))
+#define i2d_RSAPublicKey_fp(fp,rsa) ASN1_i2d_fp(i2d_RSAPublicKey,fp, \
+		(unsigned char *)rsa)
+#define d2i_RSAPublicKey_bio(bp,rsa) (RSA *)ASN1_d2i_bio((char *(*)())\
+		RSA_new,(char *(*)())d2i_RSAPublicKey, (bp), \
+		(unsigned char **)(rsa))
+#define i2d_RSAPublicKey_bio(bp,rsa) ASN1_i2d_bio(i2d_RSAPublicKey,bp, \
+		(unsigned char *)rsa)
+
+#define d2i_DSAPrivateKey_fp(fp,dsa) (DSA *)ASN1_d2i_fp((char *(*)())\
+		DSA_new,(char *(*)())d2i_DSAPrivateKey, (fp), \
+		(unsigned char **)(dsa))
+#define i2d_DSAPrivateKey_fp(fp,dsa) ASN1_i2d_fp(i2d_DSAPrivateKey,fp, \
+		(unsigned char *)dsa)
+#define d2i_DSAPrivateKey_bio(bp,dsa) (DSA *)ASN1_d2i_bio((char *(*)())\
+		DSA_new,(char *(*)())d2i_DSAPrivateKey, (bp), \
+		(unsigned char **)(dsa))
+#define i2d_DSAPrivateKey_bio(bp,dsa) ASN1_i2d_bio(i2d_DSAPrivateKey,bp, \
+		(unsigned char *)dsa)
+
+#define d2i_ECPrivateKey_fp(fp,ecdsa) (EC_KEY *)ASN1_d2i_fp((char *(*)())\
+		EC_KEY_new,(char *(*)())d2i_ECPrivateKey, (fp), \
+		(unsigned char **)(ecdsa))
+#define i2d_ECPrivateKey_fp(fp,ecdsa) ASN1_i2d_fp(i2d_ECPrivateKey,fp, \
+		(unsigned char *)ecdsa)
+#define d2i_ECPrivateKey_bio(bp,ecdsa) (EC_KEY *)ASN1_d2i_bio((char *(*)())\
+		EC_KEY_new,(char *(*)())d2i_ECPrivateKey, (bp), \
+		(unsigned char **)(ecdsa))
+#define i2d_ECPrivateKey_bio(bp,ecdsa) ASN1_i2d_bio(i2d_ECPrivateKey,bp, \
+		(unsigned char *)ecdsa)
+
+#define X509_ALGOR_dup(xn) (X509_ALGOR *)ASN1_dup((int (*)())i2d_X509_ALGOR,\
+		(char *(*)())d2i_X509_ALGOR,(char *)xn)
+
+#define X509_NAME_dup(xn) (X509_NAME *)ASN1_dup((int (*)())i2d_X509_NAME, \
+		(char *(*)())d2i_X509_NAME,(char *)xn)
+#define X509_NAME_ENTRY_dup(ne) (X509_NAME_ENTRY *)ASN1_dup( \
+		(int (*)())i2d_X509_NAME_ENTRY, \
+		(char *(*)())d2i_X509_NAME_ENTRY,\
+		(char *)ne)
+
+#define X509_digest(data,type,md,len) \
+	ASN1_digest((int (*)())i2d_X509,type,(char *)data,md,len)
+#define X509_NAME_digest(data,type,md,len) \
+	ASN1_digest((int (*)())i2d_X509_NAME,type,(char *)data,md,len)
+#ifndef PKCS7_ISSUER_AND_SERIAL_digest
+#define PKCS7_ISSUER_AND_SERIAL_digest(data,type,md,len) \
+	ASN1_digest((int (*)())i2d_PKCS7_ISSUER_AND_SERIAL,type,\
+		(char *)data,md,len)
+#endif
+#endif
+
+#define X509_EXT_PACK_UNKNOWN	1
+#define X509_EXT_PACK_STRING	2
+
+#define		X509_get_version(x) ASN1_INTEGER_get((x)->cert_info->version)
+/* #define	X509_get_serialNumber(x) ((x)->cert_info->serialNumber) */
+#define		X509_get_notBefore(x) ((x)->cert_info->validity->notBefore)
+#define		X509_get_notAfter(x) ((x)->cert_info->validity->notAfter)
+#define		X509_extract_key(x)	X509_get_pubkey(x) /*****/
+#define		X509_REQ_get_version(x) ASN1_INTEGER_get((x)->req_info->version)
+#define		X509_REQ_get_subject_name(x) ((x)->req_info->subject)
+#define		X509_REQ_extract_key(a)	X509_REQ_get_pubkey(a)
+#define		X509_name_cmp(a,b)	X509_NAME_cmp((a),(b))
+#define		X509_get_signature_type(x) EVP_PKEY_type(OBJ_obj2nid((x)->sig_alg->algorithm))
+
+#define		X509_CRL_get_version(x) ASN1_INTEGER_get((x)->crl->version)
+#define 	X509_CRL_get_lastUpdate(x) ((x)->crl->lastUpdate)
+#define 	X509_CRL_get_nextUpdate(x) ((x)->crl->nextUpdate)
+#define		X509_CRL_get_issuer(x) ((x)->crl->issuer)
+#define		X509_CRL_get_REVOKED(x) ((x)->crl->revoked)
+
+/* This one is only used so that a binary form can output, as in
+ * i2d_X509_NAME(X509_get_X509_PUBKEY(x),&buf) */
+#define 	X509_get_X509_PUBKEY(x) ((x)->cert_info->key)
+
+
+const char *X509_verify_cert_error_string(long n);
+
+#ifndef SSLEAY_MACROS
+#ifndef OPENSSL_NO_EVP
+int X509_verify(X509 *a, EVP_PKEY *r);
+
+int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r);
+int X509_CRL_verify(X509_CRL *a, EVP_PKEY *r);
+int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *a, EVP_PKEY *r);
+
+NETSCAPE_SPKI * NETSCAPE_SPKI_b64_decode(const char *str, int len);
+char * NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *x);
+EVP_PKEY *NETSCAPE_SPKI_get_pubkey(NETSCAPE_SPKI *x);
+int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *x, EVP_PKEY *pkey);
+
+int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki);
+
+int X509_signature_print(BIO *bp,X509_ALGOR *alg, ASN1_STRING *sig);
+
+int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md);
+int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md);
+int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md);
+int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md);
+
+int X509_pubkey_digest(const X509 *data,const EVP_MD *type,
+		unsigned char *md, unsigned int *len);
+int X509_digest(const X509 *data,const EVP_MD *type,
+		unsigned char *md, unsigned int *len);
+int X509_CRL_digest(const X509_CRL *data,const EVP_MD *type,
+		unsigned char *md, unsigned int *len);
+int X509_REQ_digest(const X509_REQ *data,const EVP_MD *type,
+		unsigned char *md, unsigned int *len);
+int X509_NAME_digest(const X509_NAME *data,const EVP_MD *type,
+		unsigned char *md, unsigned int *len);
+#endif
+
+#ifndef OPENSSL_NO_FP_API
+X509 *d2i_X509_fp(FILE *fp, X509 **x509);
+int i2d_X509_fp(FILE *fp,X509 *x509);
+X509_CRL *d2i_X509_CRL_fp(FILE *fp,X509_CRL **crl);
+int i2d_X509_CRL_fp(FILE *fp,X509_CRL *crl);
+X509_REQ *d2i_X509_REQ_fp(FILE *fp,X509_REQ **req);
+int i2d_X509_REQ_fp(FILE *fp,X509_REQ *req);
+#ifndef OPENSSL_NO_RSA
+RSA *d2i_RSAPrivateKey_fp(FILE *fp,RSA **rsa);
+int i2d_RSAPrivateKey_fp(FILE *fp,RSA *rsa);
+RSA *d2i_RSAPublicKey_fp(FILE *fp,RSA **rsa);
+int i2d_RSAPublicKey_fp(FILE *fp,RSA *rsa);
+RSA *d2i_RSA_PUBKEY_fp(FILE *fp,RSA **rsa);
+int i2d_RSA_PUBKEY_fp(FILE *fp,RSA *rsa);
+#endif
+#ifndef OPENSSL_NO_DSA
+DSA *d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa);
+int i2d_DSA_PUBKEY_fp(FILE *fp, DSA *dsa);
+DSA *d2i_DSAPrivateKey_fp(FILE *fp, DSA **dsa);
+int i2d_DSAPrivateKey_fp(FILE *fp, DSA *dsa);
+#endif
+#ifndef OPENSSL_NO_EC
+EC_KEY *d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **eckey);
+int   i2d_EC_PUBKEY_fp(FILE *fp, EC_KEY *eckey);
+EC_KEY *d2i_ECPrivateKey_fp(FILE *fp, EC_KEY **eckey);
+int   i2d_ECPrivateKey_fp(FILE *fp, EC_KEY *eckey);
+#endif
+X509_SIG *d2i_PKCS8_fp(FILE *fp,X509_SIG **p8);
+int i2d_PKCS8_fp(FILE *fp,X509_SIG *p8);
+PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_fp(FILE *fp,
+						PKCS8_PRIV_KEY_INFO **p8inf);
+int i2d_PKCS8_PRIV_KEY_INFO_fp(FILE *fp,PKCS8_PRIV_KEY_INFO *p8inf);
+int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, EVP_PKEY *key);
+int i2d_PrivateKey_fp(FILE *fp, EVP_PKEY *pkey);
+EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a);
+int i2d_PUBKEY_fp(FILE *fp, EVP_PKEY *pkey);
+EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a);
+#endif
+
+#ifndef OPENSSL_NO_BIO
+X509 *d2i_X509_bio(BIO *bp,X509 **x509);
+int i2d_X509_bio(BIO *bp,X509 *x509);
+X509_CRL *d2i_X509_CRL_bio(BIO *bp,X509_CRL **crl);
+int i2d_X509_CRL_bio(BIO *bp,X509_CRL *crl);
+X509_REQ *d2i_X509_REQ_bio(BIO *bp,X509_REQ **req);
+int i2d_X509_REQ_bio(BIO *bp,X509_REQ *req);
+#ifndef OPENSSL_NO_RSA
+RSA *d2i_RSAPrivateKey_bio(BIO *bp,RSA **rsa);
+int i2d_RSAPrivateKey_bio(BIO *bp,RSA *rsa);
+RSA *d2i_RSAPublicKey_bio(BIO *bp,RSA **rsa);
+int i2d_RSAPublicKey_bio(BIO *bp,RSA *rsa);
+RSA *d2i_RSA_PUBKEY_bio(BIO *bp,RSA **rsa);
+int i2d_RSA_PUBKEY_bio(BIO *bp,RSA *rsa);
+#endif
+#ifndef OPENSSL_NO_DSA
+DSA *d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa);
+int i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa);
+DSA *d2i_DSAPrivateKey_bio(BIO *bp, DSA **dsa);
+int i2d_DSAPrivateKey_bio(BIO *bp, DSA *dsa);
+#endif
+#ifndef OPENSSL_NO_EC
+EC_KEY *d2i_EC_PUBKEY_bio(BIO *bp, EC_KEY **eckey);
+int   i2d_EC_PUBKEY_bio(BIO *bp, EC_KEY *eckey);
+EC_KEY *d2i_ECPrivateKey_bio(BIO *bp, EC_KEY **eckey);
+int   i2d_ECPrivateKey_bio(BIO *bp, EC_KEY *eckey);
+#endif
+X509_SIG *d2i_PKCS8_bio(BIO *bp,X509_SIG **p8);
+int i2d_PKCS8_bio(BIO *bp,X509_SIG *p8);
+PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_bio(BIO *bp,
+						PKCS8_PRIV_KEY_INFO **p8inf);
+int i2d_PKCS8_PRIV_KEY_INFO_bio(BIO *bp,PKCS8_PRIV_KEY_INFO *p8inf);
+int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, EVP_PKEY *key);
+int i2d_PrivateKey_bio(BIO *bp, EVP_PKEY *pkey);
+EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a);
+int i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey);
+EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a);
+#endif
+
+X509 *X509_dup(X509 *x509);
+X509_ATTRIBUTE *X509_ATTRIBUTE_dup(X509_ATTRIBUTE *xa);
+X509_EXTENSION *X509_EXTENSION_dup(X509_EXTENSION *ex);
+X509_CRL *X509_CRL_dup(X509_CRL *crl);
+X509_REQ *X509_REQ_dup(X509_REQ *req);
+X509_ALGOR *X509_ALGOR_dup(X509_ALGOR *xn);
+X509_NAME *X509_NAME_dup(X509_NAME *xn);
+X509_NAME_ENTRY *X509_NAME_ENTRY_dup(X509_NAME_ENTRY *ne);
+
+#endif /* !SSLEAY_MACROS */
+
+int		X509_cmp_time(ASN1_TIME *s, time_t *t);
+int		X509_cmp_current_time(ASN1_TIME *s);
+ASN1_TIME *	X509_time_adj(ASN1_TIME *s, long adj, time_t *t);
+ASN1_TIME *	X509_gmtime_adj(ASN1_TIME *s, long adj);
+
+const char *	X509_get_default_cert_area(void );
+const char *	X509_get_default_cert_dir(void );
+const char *	X509_get_default_cert_file(void );
+const char *	X509_get_default_cert_dir_env(void );
+const char *	X509_get_default_cert_file_env(void );
+const char *	X509_get_default_private_dir(void );
+
+X509_REQ *	X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md);
+X509 *		X509_REQ_to_X509(X509_REQ *r, int days,EVP_PKEY *pkey);
+
+DECLARE_ASN1_FUNCTIONS(X509_ALGOR)
+DECLARE_ASN1_FUNCTIONS(X509_VAL)
+
+DECLARE_ASN1_FUNCTIONS(X509_PUBKEY)
+
+int		X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey);
+EVP_PKEY *	X509_PUBKEY_get(X509_PUBKEY *key);
+int		X509_get_pubkey_parameters(EVP_PKEY *pkey,
+					   STACK_OF(X509) *chain);
+int		i2d_PUBKEY(EVP_PKEY *a,unsigned char **pp);
+EVP_PKEY *	d2i_PUBKEY(EVP_PKEY **a,const unsigned char **pp,
+			long length);
+#ifndef OPENSSL_NO_RSA
+int		i2d_RSA_PUBKEY(RSA *a,unsigned char **pp);
+RSA *		d2i_RSA_PUBKEY(RSA **a,const unsigned char **pp,
+			long length);
+#endif
+#ifndef OPENSSL_NO_DSA
+int		i2d_DSA_PUBKEY(DSA *a,unsigned char **pp);
+DSA *		d2i_DSA_PUBKEY(DSA **a,const unsigned char **pp,
+			long length);
+#endif
+#ifndef OPENSSL_NO_EC
+int		i2d_EC_PUBKEY(EC_KEY *a, unsigned char **pp);
+EC_KEY 		*d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp,
+			long length);
+#endif
+
+DECLARE_ASN1_FUNCTIONS(X509_SIG)
+DECLARE_ASN1_FUNCTIONS(X509_REQ_INFO)
+DECLARE_ASN1_FUNCTIONS(X509_REQ)
+
+DECLARE_ASN1_FUNCTIONS(X509_ATTRIBUTE)
+X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, void *value);
+
+DECLARE_ASN1_FUNCTIONS(X509_EXTENSION)
+
+DECLARE_ASN1_FUNCTIONS(X509_NAME_ENTRY)
+
+DECLARE_ASN1_FUNCTIONS(X509_NAME)
+
+int		X509_NAME_set(X509_NAME **xn, X509_NAME *name);
+
+DECLARE_ASN1_FUNCTIONS(X509_CINF)
+
+DECLARE_ASN1_FUNCTIONS(X509)
+DECLARE_ASN1_FUNCTIONS(X509_CERT_AUX)
+
+DECLARE_ASN1_FUNCTIONS(X509_CERT_PAIR)
+
+int X509_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int X509_set_ex_data(X509 *r, int idx, void *arg);
+void *X509_get_ex_data(X509 *r, int idx);
+int		i2d_X509_AUX(X509 *a,unsigned char **pp);
+X509 *		d2i_X509_AUX(X509 **a,const unsigned char **pp,long length);
+
+int X509_alias_set1(X509 *x, unsigned char *name, int len);
+int X509_keyid_set1(X509 *x, unsigned char *id, int len);
+unsigned char * X509_alias_get0(X509 *x, int *len);
+unsigned char * X509_keyid_get0(X509 *x, int *len);
+int (*X509_TRUST_set_default(int (*trust)(int , X509 *, int)))(int, X509 *, int);
+int X509_TRUST_set(int *t, int trust);
+int X509_add1_trust_object(X509 *x, ASN1_OBJECT *obj);
+int X509_add1_reject_object(X509 *x, ASN1_OBJECT *obj);
+void X509_trust_clear(X509 *x);
+void X509_reject_clear(X509 *x);
+
+DECLARE_ASN1_FUNCTIONS(X509_REVOKED)
+DECLARE_ASN1_FUNCTIONS(X509_CRL_INFO)
+DECLARE_ASN1_FUNCTIONS(X509_CRL)
+
+int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev);
+
+X509_PKEY *	X509_PKEY_new(void );
+void		X509_PKEY_free(X509_PKEY *a);
+int		i2d_X509_PKEY(X509_PKEY *a,unsigned char **pp);
+X509_PKEY *	d2i_X509_PKEY(X509_PKEY **a,const unsigned char **pp,long length);
+
+DECLARE_ASN1_FUNCTIONS(NETSCAPE_SPKI)
+DECLARE_ASN1_FUNCTIONS(NETSCAPE_SPKAC)
+DECLARE_ASN1_FUNCTIONS(NETSCAPE_CERT_SEQUENCE)
+
+#ifndef OPENSSL_NO_EVP
+X509_INFO *	X509_INFO_new(void);
+void		X509_INFO_free(X509_INFO *a);
+char *		X509_NAME_oneline(X509_NAME *a,char *buf,int size);
+
+int ASN1_verify(i2d_of_void *i2d, X509_ALGOR *algor1,
+		ASN1_BIT_STRING *signature,char *data,EVP_PKEY *pkey);
+
+int ASN1_digest(i2d_of_void *i2d,const EVP_MD *type,char *data,
+		unsigned char *md,unsigned int *len);
+
+int ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1,
+	      X509_ALGOR *algor2, ASN1_BIT_STRING *signature,
+	      char *data,EVP_PKEY *pkey, const EVP_MD *type);
+
+int ASN1_item_digest(const ASN1_ITEM *it,const EVP_MD *type,void *data,
+	unsigned char *md,unsigned int *len);
+
+int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *algor1,
+	ASN1_BIT_STRING *signature,void *data,EVP_PKEY *pkey);
+
+int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2,
+	ASN1_BIT_STRING *signature,
+	void *data, EVP_PKEY *pkey, const EVP_MD *type);
+#endif
+
+int 		X509_set_version(X509 *x,long version);
+int 		X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial);
+ASN1_INTEGER *	X509_get_serialNumber(X509 *x);
+int 		X509_set_issuer_name(X509 *x, X509_NAME *name);
+X509_NAME *	X509_get_issuer_name(X509 *a);
+int 		X509_set_subject_name(X509 *x, X509_NAME *name);
+X509_NAME *	X509_get_subject_name(X509 *a);
+int 		X509_set_notBefore(X509 *x, ASN1_TIME *tm);
+int 		X509_set_notAfter(X509 *x, ASN1_TIME *tm);
+int 		X509_set_pubkey(X509 *x, EVP_PKEY *pkey);
+EVP_PKEY *	X509_get_pubkey(X509 *x);
+ASN1_BIT_STRING * X509_get0_pubkey_bitstr(const X509 *x);
+int		X509_certificate_type(X509 *x,EVP_PKEY *pubkey /* optional */);
+
+int		X509_REQ_set_version(X509_REQ *x,long version);
+int		X509_REQ_set_subject_name(X509_REQ *req,X509_NAME *name);
+int		X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey);
+EVP_PKEY *	X509_REQ_get_pubkey(X509_REQ *req);
+int		X509_REQ_extension_nid(int nid);
+int *		X509_REQ_get_extension_nids(void);
+void		X509_REQ_set_extension_nids(int *nids);
+STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req);
+int X509_REQ_add_extensions_nid(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts,
+				int nid);
+int X509_REQ_add_extensions(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts);
+int X509_REQ_get_attr_count(const X509_REQ *req);
+int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid,
+			  int lastpos);
+int X509_REQ_get_attr_by_OBJ(const X509_REQ *req, ASN1_OBJECT *obj,
+			  int lastpos);
+X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc);
+X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc);
+int X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr);
+int X509_REQ_add1_attr_by_OBJ(X509_REQ *req,
+			const ASN1_OBJECT *obj, int type,
+			const unsigned char *bytes, int len);
+int X509_REQ_add1_attr_by_NID(X509_REQ *req,
+			int nid, int type,
+			const unsigned char *bytes, int len);
+int X509_REQ_add1_attr_by_txt(X509_REQ *req,
+			const char *attrname, int type,
+			const unsigned char *bytes, int len);
+
+int X509_CRL_set_version(X509_CRL *x, long version);
+int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name);
+int X509_CRL_set_lastUpdate(X509_CRL *x, ASN1_TIME *tm);
+int X509_CRL_set_nextUpdate(X509_CRL *x, ASN1_TIME *tm);
+int X509_CRL_sort(X509_CRL *crl);
+
+int X509_REVOKED_set_serialNumber(X509_REVOKED *x, ASN1_INTEGER *serial);
+int X509_REVOKED_set_revocationDate(X509_REVOKED *r, ASN1_TIME *tm);
+
+int		X509_REQ_check_private_key(X509_REQ *x509,EVP_PKEY *pkey);
+
+int		X509_check_private_key(X509 *x509,EVP_PKEY *pkey);
+
+int		X509_issuer_and_serial_cmp(const X509 *a, const X509 *b);
+unsigned long	X509_issuer_and_serial_hash(X509 *a);
+
+int		X509_issuer_name_cmp(const X509 *a, const X509 *b);
+unsigned long	X509_issuer_name_hash(X509 *a);
+
+int		X509_subject_name_cmp(const X509 *a, const X509 *b);
+unsigned long	X509_subject_name_hash(X509 *x);
+
+int		X509_cmp(const X509 *a, const X509 *b);
+int		X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b);
+unsigned long	X509_NAME_hash(X509_NAME *x);
+
+int		X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b);
+#ifndef OPENSSL_NO_FP_API
+int		X509_print_ex_fp(FILE *bp,X509 *x, unsigned long nmflag, unsigned long cflag);
+int		X509_print_fp(FILE *bp,X509 *x);
+int		X509_CRL_print_fp(FILE *bp,X509_CRL *x);
+int		X509_REQ_print_fp(FILE *bp,X509_REQ *req);
+int X509_NAME_print_ex_fp(FILE *fp, X509_NAME *nm, int indent, unsigned long flags);
+#endif
+
+#ifndef OPENSSL_NO_BIO
+int		X509_NAME_print(BIO *bp, X509_NAME *name, int obase);
+int X509_NAME_print_ex(BIO *out, X509_NAME *nm, int indent, unsigned long flags);
+int		X509_print_ex(BIO *bp,X509 *x, unsigned long nmflag, unsigned long cflag);
+int		X509_print(BIO *bp,X509 *x);
+int		X509_ocspid_print(BIO *bp,X509 *x);
+int		X509_CERT_AUX_print(BIO *bp,X509_CERT_AUX *x, int indent);
+int		X509_CRL_print(BIO *bp,X509_CRL *x);
+int		X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflag, unsigned long cflag);
+int		X509_REQ_print(BIO *bp,X509_REQ *req);
+#endif
+
+int 		X509_NAME_entry_count(X509_NAME *name);
+int 		X509_NAME_get_text_by_NID(X509_NAME *name, int nid,
+			char *buf,int len);
+int		X509_NAME_get_text_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj,
+			char *buf,int len);
+
+/* NOTE: you should be passsing -1, not 0 as lastpos.  The functions that use
+ * lastpos, search after that position on. */
+int 		X509_NAME_get_index_by_NID(X509_NAME *name,int nid,int lastpos);
+int 		X509_NAME_get_index_by_OBJ(X509_NAME *name,ASN1_OBJECT *obj,
+			int lastpos);
+X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc);
+X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc);
+int 		X509_NAME_add_entry(X509_NAME *name,X509_NAME_ENTRY *ne,
+			int loc, int set);
+int X509_NAME_add_entry_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int type,
+			unsigned char *bytes, int len, int loc, int set);
+int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type,
+			unsigned char *bytes, int len, int loc, int set);
+X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne,
+		const char *field, int type, const unsigned char *bytes, int len);
+X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid,
+			int type,unsigned char *bytes, int len);
+int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type,
+			const unsigned char *bytes, int len, int loc, int set);
+X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne,
+			ASN1_OBJECT *obj, int type,const unsigned char *bytes,
+			int len);
+int 		X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne,
+			ASN1_OBJECT *obj);
+int 		X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type,
+			const unsigned char *bytes, int len);
+ASN1_OBJECT *	X509_NAME_ENTRY_get_object(X509_NAME_ENTRY *ne);
+ASN1_STRING *	X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne);
+
+int		X509v3_get_ext_count(const STACK_OF(X509_EXTENSION) *x);
+int		X509v3_get_ext_by_NID(const STACK_OF(X509_EXTENSION) *x,
+				      int nid, int lastpos);
+int		X509v3_get_ext_by_OBJ(const STACK_OF(X509_EXTENSION) *x,
+				      ASN1_OBJECT *obj,int lastpos);
+int		X509v3_get_ext_by_critical(const STACK_OF(X509_EXTENSION) *x,
+					   int crit, int lastpos);
+X509_EXTENSION *X509v3_get_ext(const STACK_OF(X509_EXTENSION) *x, int loc);
+X509_EXTENSION *X509v3_delete_ext(STACK_OF(X509_EXTENSION) *x, int loc);
+STACK_OF(X509_EXTENSION) *X509v3_add_ext(STACK_OF(X509_EXTENSION) **x,
+					 X509_EXTENSION *ex, int loc);
+
+int		X509_get_ext_count(X509 *x);
+int		X509_get_ext_by_NID(X509 *x, int nid, int lastpos);
+int		X509_get_ext_by_OBJ(X509 *x,ASN1_OBJECT *obj,int lastpos);
+int		X509_get_ext_by_critical(X509 *x, int crit, int lastpos);
+X509_EXTENSION *X509_get_ext(X509 *x, int loc);
+X509_EXTENSION *X509_delete_ext(X509 *x, int loc);
+int		X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc);
+void	*	X509_get_ext_d2i(X509 *x, int nid, int *crit, int *idx);
+int		X509_add1_ext_i2d(X509 *x, int nid, void *value, int crit,
+							unsigned long flags);
+
+int		X509_CRL_get_ext_count(X509_CRL *x);
+int		X509_CRL_get_ext_by_NID(X509_CRL *x, int nid, int lastpos);
+int		X509_CRL_get_ext_by_OBJ(X509_CRL *x,ASN1_OBJECT *obj,int lastpos);
+int		X509_CRL_get_ext_by_critical(X509_CRL *x, int crit, int lastpos);
+X509_EXTENSION *X509_CRL_get_ext(X509_CRL *x, int loc);
+X509_EXTENSION *X509_CRL_delete_ext(X509_CRL *x, int loc);
+int		X509_CRL_add_ext(X509_CRL *x, X509_EXTENSION *ex, int loc);
+void	*	X509_CRL_get_ext_d2i(X509_CRL *x, int nid, int *crit, int *idx);
+int		X509_CRL_add1_ext_i2d(X509_CRL *x, int nid, void *value, int crit,
+							unsigned long flags);
+
+int		X509_REVOKED_get_ext_count(X509_REVOKED *x);
+int		X509_REVOKED_get_ext_by_NID(X509_REVOKED *x, int nid, int lastpos);
+int		X509_REVOKED_get_ext_by_OBJ(X509_REVOKED *x,ASN1_OBJECT *obj,int lastpos);
+int		X509_REVOKED_get_ext_by_critical(X509_REVOKED *x, int crit, int lastpos);
+X509_EXTENSION *X509_REVOKED_get_ext(X509_REVOKED *x, int loc);
+X509_EXTENSION *X509_REVOKED_delete_ext(X509_REVOKED *x, int loc);
+int		X509_REVOKED_add_ext(X509_REVOKED *x, X509_EXTENSION *ex, int loc);
+void	*	X509_REVOKED_get_ext_d2i(X509_REVOKED *x, int nid, int *crit, int *idx);
+int		X509_REVOKED_add1_ext_i2d(X509_REVOKED *x, int nid, void *value, int crit,
+							unsigned long flags);
+
+X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex,
+			int nid, int crit, ASN1_OCTET_STRING *data);
+X509_EXTENSION *X509_EXTENSION_create_by_OBJ(X509_EXTENSION **ex,
+			ASN1_OBJECT *obj,int crit,ASN1_OCTET_STRING *data);
+int		X509_EXTENSION_set_object(X509_EXTENSION *ex,ASN1_OBJECT *obj);
+int		X509_EXTENSION_set_critical(X509_EXTENSION *ex, int crit);
+int		X509_EXTENSION_set_data(X509_EXTENSION *ex,
+			ASN1_OCTET_STRING *data);
+ASN1_OBJECT *	X509_EXTENSION_get_object(X509_EXTENSION *ex);
+ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ne);
+int		X509_EXTENSION_get_critical(X509_EXTENSION *ex);
+
+int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x);
+int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid,
+			  int lastpos);
+int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk, ASN1_OBJECT *obj,
+			  int lastpos);
+X509_ATTRIBUTE *X509at_get_attr(const STACK_OF(X509_ATTRIBUTE) *x, int loc);
+X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc);
+STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x,
+					 X509_ATTRIBUTE *attr);
+STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE) **x,
+			const ASN1_OBJECT *obj, int type,
+			const unsigned char *bytes, int len);
+STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE) **x,
+			int nid, int type,
+			const unsigned char *bytes, int len);
+STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE) **x,
+			const char *attrname, int type,
+			const unsigned char *bytes, int len);
+X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid,
+	     int atrtype, const void *data, int len);
+X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr,
+	     const ASN1_OBJECT *obj, int atrtype, const void *data, int len);
+X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr,
+		const char *atrname, int type, const unsigned char *bytes, int len);
+int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj);
+int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, const void *data, int len);
+void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx,
+					int atrtype, void *data);
+int X509_ATTRIBUTE_count(X509_ATTRIBUTE *attr);
+ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr);
+ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx);
+
+int EVP_PKEY_get_attr_count(const EVP_PKEY *key);
+int EVP_PKEY_get_attr_by_NID(const EVP_PKEY *key, int nid,
+			  int lastpos);
+int EVP_PKEY_get_attr_by_OBJ(const EVP_PKEY *key, ASN1_OBJECT *obj,
+			  int lastpos);
+X509_ATTRIBUTE *EVP_PKEY_get_attr(const EVP_PKEY *key, int loc);
+X509_ATTRIBUTE *EVP_PKEY_delete_attr(EVP_PKEY *key, int loc);
+int EVP_PKEY_add1_attr(EVP_PKEY *key, X509_ATTRIBUTE *attr);
+int EVP_PKEY_add1_attr_by_OBJ(EVP_PKEY *key,
+			const ASN1_OBJECT *obj, int type,
+			const unsigned char *bytes, int len);
+int EVP_PKEY_add1_attr_by_NID(EVP_PKEY *key,
+			int nid, int type,
+			const unsigned char *bytes, int len);
+int EVP_PKEY_add1_attr_by_txt(EVP_PKEY *key,
+			const char *attrname, int type,
+			const unsigned char *bytes, int len);
+
+int		X509_verify_cert(X509_STORE_CTX *ctx);
+
+/* lookup a cert from a X509 STACK */
+X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk,X509_NAME *name,
+				     ASN1_INTEGER *serial);
+X509 *X509_find_by_subject(STACK_OF(X509) *sk,X509_NAME *name);
+
+DECLARE_ASN1_FUNCTIONS(PBEPARAM)
+DECLARE_ASN1_FUNCTIONS(PBE2PARAM)
+DECLARE_ASN1_FUNCTIONS(PBKDF2PARAM)
+
+X509_ALGOR *PKCS5_pbe_set(int alg, int iter, unsigned char *salt, int saltlen);
+X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter,
+					 unsigned char *salt, int saltlen);
+
+/* PKCS#8 utilities */
+
+DECLARE_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO)
+
+EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8);
+PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey);
+PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8_broken(EVP_PKEY *pkey, int broken);
+PKCS8_PRIV_KEY_INFO *PKCS8_set_broken(PKCS8_PRIV_KEY_INFO *p8, int broken);
+
+int X509_check_trust(X509 *x, int id, int flags);
+int X509_TRUST_get_count(void);
+X509_TRUST * X509_TRUST_get0(int idx);
+int X509_TRUST_get_by_id(int id);
+int X509_TRUST_add(int id, int flags, int (*ck)(X509_TRUST *, X509 *, int),
+					char *name, int arg1, void *arg2);
+void X509_TRUST_cleanup(void);
+int X509_TRUST_get_flags(X509_TRUST *xp);
+char *X509_TRUST_get0_name(X509_TRUST *xp);
+int X509_TRUST_get_trust(X509_TRUST *xp);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_X509_strings(void);
+
+/* Error codes for the X509 functions. */
+
+/* Function codes. */
+#define X509_F_ADD_CERT_DIR				 100
+#define X509_F_BY_FILE_CTRL				 101
+#define X509_F_CHECK_POLICY				 145
+#define X509_F_DIR_CTRL					 102
+#define X509_F_GET_CERT_BY_SUBJECT			 103
+#define X509_F_NETSCAPE_SPKI_B64_DECODE			 129
+#define X509_F_NETSCAPE_SPKI_B64_ENCODE			 130
+#define X509_F_X509AT_ADD1_ATTR				 135
+#define X509_F_X509V3_ADD_EXT				 104
+#define X509_F_X509_ATTRIBUTE_CREATE_BY_NID		 136
+#define X509_F_X509_ATTRIBUTE_CREATE_BY_OBJ		 137
+#define X509_F_X509_ATTRIBUTE_CREATE_BY_TXT		 140
+#define X509_F_X509_ATTRIBUTE_GET0_DATA			 139
+#define X509_F_X509_ATTRIBUTE_SET1_DATA			 138
+#define X509_F_X509_CHECK_PRIVATE_KEY			 128
+#define X509_F_X509_CRL_PRINT_FP			 147
+#define X509_F_X509_EXTENSION_CREATE_BY_NID		 108
+#define X509_F_X509_EXTENSION_CREATE_BY_OBJ		 109
+#define X509_F_X509_GET_PUBKEY_PARAMETERS		 110
+#define X509_F_X509_LOAD_CERT_CRL_FILE			 132
+#define X509_F_X509_LOAD_CERT_FILE			 111
+#define X509_F_X509_LOAD_CRL_FILE			 112
+#define X509_F_X509_NAME_ADD_ENTRY			 113
+#define X509_F_X509_NAME_ENTRY_CREATE_BY_NID		 114
+#define X509_F_X509_NAME_ENTRY_CREATE_BY_TXT		 131
+#define X509_F_X509_NAME_ENTRY_SET_OBJECT		 115
+#define X509_F_X509_NAME_ONELINE			 116
+#define X509_F_X509_NAME_PRINT				 117
+#define X509_F_X509_PRINT_EX_FP				 118
+#define X509_F_X509_PUBKEY_GET				 119
+#define X509_F_X509_PUBKEY_SET				 120
+#define X509_F_X509_REQ_CHECK_PRIVATE_KEY		 144
+#define X509_F_X509_REQ_PRINT_EX			 121
+#define X509_F_X509_REQ_PRINT_FP			 122
+#define X509_F_X509_REQ_TO_X509				 123
+#define X509_F_X509_STORE_ADD_CERT			 124
+#define X509_F_X509_STORE_ADD_CRL			 125
+#define X509_F_X509_STORE_CTX_GET1_ISSUER		 146
+#define X509_F_X509_STORE_CTX_INIT			 143
+#define X509_F_X509_STORE_CTX_NEW			 142
+#define X509_F_X509_STORE_CTX_PURPOSE_INHERIT		 134
+#define X509_F_X509_TO_X509_REQ				 126
+#define X509_F_X509_TRUST_ADD				 133
+#define X509_F_X509_TRUST_SET				 141
+#define X509_F_X509_VERIFY_CERT				 127
+
+/* Reason codes. */
+#define X509_R_BAD_X509_FILETYPE			 100
+#define X509_R_BASE64_DECODE_ERROR			 118
+#define X509_R_CANT_CHECK_DH_KEY			 114
+#define X509_R_CERT_ALREADY_IN_HASH_TABLE		 101
+#define X509_R_ERR_ASN1_LIB				 102
+#define X509_R_INVALID_DIRECTORY			 113
+#define X509_R_INVALID_FIELD_NAME			 119
+#define X509_R_INVALID_TRUST				 123
+#define X509_R_KEY_TYPE_MISMATCH			 115
+#define X509_R_KEY_VALUES_MISMATCH			 116
+#define X509_R_LOADING_CERT_DIR				 103
+#define X509_R_LOADING_DEFAULTS				 104
+#define X509_R_NO_CERT_SET_FOR_US_TO_VERIFY		 105
+#define X509_R_SHOULD_RETRY				 106
+#define X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN	 107
+#define X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY		 108
+#define X509_R_UNKNOWN_KEY_TYPE				 117
+#define X509_R_UNKNOWN_NID				 109
+#define X509_R_UNKNOWN_PURPOSE_ID			 121
+#define X509_R_UNKNOWN_TRUST_ID				 120
+#define X509_R_UNSUPPORTED_ALGORITHM			 111
+#define X509_R_WRONG_LOOKUP_TYPE			 112
+#define X509_R_WRONG_TYPE				 122
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/dep/include/openssl/x509_vfy.h b/dep/include/openssl/x509_vfy.h
new file mode 100644
index 00000000000..76c76e17193
--- /dev/null
+++ b/dep/include/openssl/x509_vfy.h
@@ -0,0 +1,531 @@
+/* crypto/x509/x509_vfy.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_X509_H
+#include 
+/* openssl/x509.h ends up #include-ing this file at about the only
+ * appropriate moment. */
+#endif
+
+#ifndef HEADER_X509_VFY_H
+#define HEADER_X509_VFY_H
+
+#include 
+#ifndef OPENSSL_NO_LHASH
+#include 
+#endif
+#include 
+#include 
+#include 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* Outer object */
+typedef struct x509_hash_dir_st
+	{
+	int num_dirs;
+	char **dirs;
+	int *dirs_type;
+	int num_dirs_alloced;
+	} X509_HASH_DIR_CTX;
+
+typedef struct x509_file_st
+	{
+	int num_paths;	/* number of paths to files or directories */
+	int num_alloced;
+	char **paths;	/* the list of paths or directories */
+	int *path_type;
+	} X509_CERT_FILE_CTX;
+
+/*******************************/
+/*
+SSL_CTX -> X509_STORE    
+		-> X509_LOOKUP
+			->X509_LOOKUP_METHOD
+		-> X509_LOOKUP
+			->X509_LOOKUP_METHOD
+ 
+SSL	-> X509_STORE_CTX
+		->X509_STORE    
+
+The X509_STORE holds the tables etc for verification stuff.
+A X509_STORE_CTX is used while validating a single certificate.
+The X509_STORE has X509_LOOKUPs for looking up certs.
+The X509_STORE then calls a function to actually verify the
+certificate chain.
+*/
+
+#define X509_LU_RETRY		-1
+#define X509_LU_FAIL		0
+#define X509_LU_X509		1
+#define X509_LU_CRL		2
+#define X509_LU_PKEY		3
+
+typedef struct x509_object_st
+	{
+	/* one of the above types */
+	int type;
+	union	{
+		char *ptr;
+		X509 *x509;
+		X509_CRL *crl;
+		EVP_PKEY *pkey;
+		} data;
+	} X509_OBJECT;
+
+typedef struct x509_lookup_st X509_LOOKUP;
+
+DECLARE_STACK_OF(X509_LOOKUP)
+DECLARE_STACK_OF(X509_OBJECT)
+
+/* This is a static that defines the function interface */
+typedef struct x509_lookup_method_st
+	{
+	const char *name;
+	int (*new_item)(X509_LOOKUP *ctx);
+	void (*free)(X509_LOOKUP *ctx);
+	int (*init)(X509_LOOKUP *ctx);
+	int (*shutdown)(X509_LOOKUP *ctx);
+	int (*ctrl)(X509_LOOKUP *ctx,int cmd,const char *argc,long argl,
+			char **ret);
+	int (*get_by_subject)(X509_LOOKUP *ctx,int type,X509_NAME *name,
+			      X509_OBJECT *ret);
+	int (*get_by_issuer_serial)(X509_LOOKUP *ctx,int type,X509_NAME *name,
+				    ASN1_INTEGER *serial,X509_OBJECT *ret);
+	int (*get_by_fingerprint)(X509_LOOKUP *ctx,int type,
+				  unsigned char *bytes,int len,
+				  X509_OBJECT *ret);
+	int (*get_by_alias)(X509_LOOKUP *ctx,int type,char *str,int len,
+			    X509_OBJECT *ret);
+	} X509_LOOKUP_METHOD;
+
+/* This structure hold all parameters associated with a verify operation
+ * by including an X509_VERIFY_PARAM structure in related structures the
+ * parameters used can be customized
+ */
+
+typedef struct X509_VERIFY_PARAM_st
+	{
+	char *name;
+	time_t check_time;	/* Time to use */
+	unsigned long inh_flags; /* Inheritance flags */
+	unsigned long flags;	/* Various verify flags */
+	int purpose;		/* purpose to check untrusted certificates */
+	int trust;		/* trust setting to check */
+	int depth;		/* Verify depth */
+	STACK_OF(ASN1_OBJECT) *policies;	/* Permissible policies */
+	} X509_VERIFY_PARAM;
+
+DECLARE_STACK_OF(X509_VERIFY_PARAM)
+
+/* This is used to hold everything.  It is used for all certificate
+ * validation.  Once we have a certificate chain, the 'verify'
+ * function is then called to actually check the cert chain. */
+struct x509_store_st
+	{
+	/* The following is a cache of trusted certs */
+	int cache; 	/* if true, stash any hits */
+	STACK_OF(X509_OBJECT) *objs;	/* Cache of all objects */
+
+	/* These are external lookup methods */
+	STACK_OF(X509_LOOKUP) *get_cert_methods;
+
+	X509_VERIFY_PARAM *param;
+
+	/* Callbacks for various operations */
+	int (*verify)(X509_STORE_CTX *ctx);	/* called to verify a certificate */
+	int (*verify_cb)(int ok,X509_STORE_CTX *ctx);	/* error callback */
+	int (*get_issuer)(X509 **issuer, X509_STORE_CTX *ctx, X509 *x);	/* get issuers cert from ctx */
+	int (*check_issued)(X509_STORE_CTX *ctx, X509 *x, X509 *issuer); /* check issued */
+	int (*check_revocation)(X509_STORE_CTX *ctx); /* Check revocation status of chain */
+	int (*get_crl)(X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x); /* retrieve CRL */
+	int (*check_crl)(X509_STORE_CTX *ctx, X509_CRL *crl); /* Check CRL validity */
+	int (*cert_crl)(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); /* Check certificate against CRL */
+	int (*cleanup)(X509_STORE_CTX *ctx);
+
+	CRYPTO_EX_DATA ex_data;
+	int references;
+	} /* X509_STORE */;
+
+int X509_STORE_set_depth(X509_STORE *store, int depth);
+
+#define X509_STORE_set_verify_cb_func(ctx,func) ((ctx)->verify_cb=(func))
+#define X509_STORE_set_verify_func(ctx,func)	((ctx)->verify=(func))
+
+/* This is the functions plus an instance of the local variables. */
+struct x509_lookup_st
+	{
+	int init;			/* have we been started */
+	int skip;			/* don't use us. */
+	X509_LOOKUP_METHOD *method;	/* the functions */
+	char *method_data;		/* method data */
+
+	X509_STORE *store_ctx;	/* who owns us */
+	} /* X509_LOOKUP */;
+
+/* This is a used when verifying cert chains.  Since the
+ * gathering of the cert chain can take some time (and have to be
+ * 'retried', this needs to be kept and passed around. */
+struct x509_store_ctx_st      /* X509_STORE_CTX */
+	{
+	X509_STORE *ctx;
+	int current_method;	/* used when looking up certs */
+
+	/* The following are set by the caller */
+	X509 *cert;		/* The cert to check */
+	STACK_OF(X509) *untrusted;	/* chain of X509s - untrusted - passed in */
+	STACK_OF(X509_CRL) *crls;	/* set of CRLs passed in */
+
+	X509_VERIFY_PARAM *param;
+	void *other_ctx;	/* Other info for use with get_issuer() */
+
+	/* Callbacks for various operations */
+	int (*verify)(X509_STORE_CTX *ctx);	/* called to verify a certificate */
+	int (*verify_cb)(int ok,X509_STORE_CTX *ctx);		/* error callback */
+	int (*get_issuer)(X509 **issuer, X509_STORE_CTX *ctx, X509 *x);	/* get issuers cert from ctx */
+	int (*check_issued)(X509_STORE_CTX *ctx, X509 *x, X509 *issuer); /* check issued */
+	int (*check_revocation)(X509_STORE_CTX *ctx); /* Check revocation status of chain */
+	int (*get_crl)(X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x); /* retrieve CRL */
+	int (*check_crl)(X509_STORE_CTX *ctx, X509_CRL *crl); /* Check CRL validity */
+	int (*cert_crl)(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); /* Check certificate against CRL */
+	int (*check_policy)(X509_STORE_CTX *ctx);
+	int (*cleanup)(X509_STORE_CTX *ctx);
+
+	/* The following is built up */
+	int valid;		/* if 0, rebuild chain */
+	int last_untrusted;	/* index of last untrusted cert */
+	STACK_OF(X509) *chain; 		/* chain of X509s - built up and trusted */
+	X509_POLICY_TREE *tree;	/* Valid policy tree */
+
+	int explicit_policy;	/* Require explicit policy value */
+
+	/* When something goes wrong, this is why */
+	int error_depth;
+	int error;
+	X509 *current_cert;
+	X509 *current_issuer;	/* cert currently being tested as valid issuer */
+	X509_CRL *current_crl;	/* current CRL */
+
+	CRYPTO_EX_DATA ex_data;
+	} /* X509_STORE_CTX */;
+
+void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth);
+
+#define X509_STORE_CTX_set_app_data(ctx,data) \
+	X509_STORE_CTX_set_ex_data(ctx,0,data)
+#define X509_STORE_CTX_get_app_data(ctx) \
+	X509_STORE_CTX_get_ex_data(ctx,0)
+
+#define X509_L_FILE_LOAD	1
+#define X509_L_ADD_DIR		2
+
+#define X509_LOOKUP_load_file(x,name,type) \
+		X509_LOOKUP_ctrl((x),X509_L_FILE_LOAD,(name),(long)(type),NULL)
+
+#define X509_LOOKUP_add_dir(x,name,type) \
+		X509_LOOKUP_ctrl((x),X509_L_ADD_DIR,(name),(long)(type),NULL)
+
+#define		X509_V_OK					0
+/* illegal error (for uninitialized values, to avoid X509_V_OK): 1 */
+
+#define		X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT		2
+#define		X509_V_ERR_UNABLE_TO_GET_CRL			3
+#define		X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE	4
+#define		X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE	5
+#define		X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY	6
+#define		X509_V_ERR_CERT_SIGNATURE_FAILURE		7
+#define		X509_V_ERR_CRL_SIGNATURE_FAILURE		8
+#define		X509_V_ERR_CERT_NOT_YET_VALID			9
+#define		X509_V_ERR_CERT_HAS_EXPIRED			10
+#define		X509_V_ERR_CRL_NOT_YET_VALID			11
+#define		X509_V_ERR_CRL_HAS_EXPIRED			12
+#define		X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD	13
+#define		X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD	14
+#define		X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD	15
+#define		X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD	16
+#define		X509_V_ERR_OUT_OF_MEM				17
+#define		X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT		18
+#define		X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN		19
+#define		X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY	20
+#define		X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE	21
+#define		X509_V_ERR_CERT_CHAIN_TOO_LONG			22
+#define		X509_V_ERR_CERT_REVOKED				23
+#define		X509_V_ERR_INVALID_CA				24
+#define		X509_V_ERR_PATH_LENGTH_EXCEEDED			25
+#define		X509_V_ERR_INVALID_PURPOSE			26
+#define		X509_V_ERR_CERT_UNTRUSTED			27
+#define		X509_V_ERR_CERT_REJECTED			28
+/* These are 'informational' when looking for issuer cert */
+#define		X509_V_ERR_SUBJECT_ISSUER_MISMATCH		29
+#define		X509_V_ERR_AKID_SKID_MISMATCH			30
+#define		X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH		31
+#define		X509_V_ERR_KEYUSAGE_NO_CERTSIGN			32
+
+#define		X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER		33
+#define		X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION		34
+#define		X509_V_ERR_KEYUSAGE_NO_CRL_SIGN			35
+#define		X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION	36
+#define		X509_V_ERR_INVALID_NON_CA			37
+#define		X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED		38
+#define		X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE	39
+#define		X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED	40
+
+#define		X509_V_ERR_INVALID_EXTENSION			41
+#define		X509_V_ERR_INVALID_POLICY_EXTENSION		42
+#define		X509_V_ERR_NO_EXPLICIT_POLICY			43
+
+#define		X509_V_ERR_UNNESTED_RESOURCE			44
+
+/* The application is not happy */
+#define		X509_V_ERR_APPLICATION_VERIFICATION		50
+
+/* Certificate verify flags */
+
+/* Send issuer+subject checks to verify_cb */
+#define	X509_V_FLAG_CB_ISSUER_CHECK		0x1
+/* Use check time instead of current time */
+#define	X509_V_FLAG_USE_CHECK_TIME		0x2
+/* Lookup CRLs */
+#define	X509_V_FLAG_CRL_CHECK			0x4
+/* Lookup CRLs for whole chain */
+#define	X509_V_FLAG_CRL_CHECK_ALL		0x8
+/* Ignore unhandled critical extensions */
+#define	X509_V_FLAG_IGNORE_CRITICAL		0x10
+/* Disable workarounds for broken certificates */
+#define	X509_V_FLAG_X509_STRICT			0x20
+/* Enable proxy certificate validation */
+#define	X509_V_FLAG_ALLOW_PROXY_CERTS		0x40
+/* Enable policy checking */
+#define X509_V_FLAG_POLICY_CHECK		0x80
+/* Policy variable require-explicit-policy */
+#define X509_V_FLAG_EXPLICIT_POLICY		0x100
+/* Policy variable inhibit-any-policy */
+#define	X509_V_FLAG_INHIBIT_ANY			0x200
+/* Policy variable inhibit-policy-mapping */
+#define X509_V_FLAG_INHIBIT_MAP			0x400
+/* Notify callback that policy is OK */
+#define X509_V_FLAG_NOTIFY_POLICY		0x800
+
+#define X509_VP_FLAG_DEFAULT			0x1
+#define X509_VP_FLAG_OVERWRITE			0x2
+#define X509_VP_FLAG_RESET_FLAGS		0x4
+#define X509_VP_FLAG_LOCKED			0x8
+#define X509_VP_FLAG_ONCE			0x10
+
+/* Internal use: mask of policy related options */
+#define X509_V_FLAG_POLICY_MASK (X509_V_FLAG_POLICY_CHECK \
+				| X509_V_FLAG_EXPLICIT_POLICY \
+				| X509_V_FLAG_INHIBIT_ANY \
+				| X509_V_FLAG_INHIBIT_MAP)
+
+int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type,
+	     X509_NAME *name);
+X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h,int type,X509_NAME *name);
+X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, X509_OBJECT *x);
+void X509_OBJECT_up_ref_count(X509_OBJECT *a);
+void X509_OBJECT_free_contents(X509_OBJECT *a);
+X509_STORE *X509_STORE_new(void );
+void X509_STORE_free(X509_STORE *v);
+
+int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags);
+int X509_STORE_set_purpose(X509_STORE *ctx, int purpose);
+int X509_STORE_set_trust(X509_STORE *ctx, int trust);
+int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *pm);
+
+X509_STORE_CTX *X509_STORE_CTX_new(void);
+
+int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x);
+
+void X509_STORE_CTX_free(X509_STORE_CTX *ctx);
+int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store,
+			 X509 *x509, STACK_OF(X509) *chain);
+void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk);
+void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx);
+
+X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m);
+
+X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void);
+X509_LOOKUP_METHOD *X509_LOOKUP_file(void);
+
+int X509_STORE_add_cert(X509_STORE *ctx, X509 *x);
+int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x);
+
+int X509_STORE_get_by_subject(X509_STORE_CTX *vs,int type,X509_NAME *name,
+	X509_OBJECT *ret);
+
+int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc,
+	long argl, char **ret);
+
+#ifndef OPENSSL_NO_STDIO
+int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type);
+int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type);
+int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type);
+#endif
+
+
+X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method);
+void X509_LOOKUP_free(X509_LOOKUP *ctx);
+int X509_LOOKUP_init(X509_LOOKUP *ctx);
+int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, int type, X509_NAME *name,
+	X509_OBJECT *ret);
+int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, int type, X509_NAME *name,
+	ASN1_INTEGER *serial, X509_OBJECT *ret);
+int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, int type,
+	unsigned char *bytes, int len, X509_OBJECT *ret);
+int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, int type, char *str,
+	int len, X509_OBJECT *ret);
+int X509_LOOKUP_shutdown(X509_LOOKUP *ctx);
+
+#ifndef OPENSSL_NO_STDIO
+int	X509_STORE_load_locations (X509_STORE *ctx,
+		const char *file, const char *dir);
+int	X509_STORE_set_default_paths(X509_STORE *ctx);
+#endif
+
+int X509_STORE_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+	CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int	X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx,int idx,void *data);
+void *	X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx,int idx);
+int	X509_STORE_CTX_get_error(X509_STORE_CTX *ctx);
+void	X509_STORE_CTX_set_error(X509_STORE_CTX *ctx,int s);
+int	X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx);
+X509 *	X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx);
+STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx);
+STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx);
+void	X509_STORE_CTX_set_cert(X509_STORE_CTX *c,X509 *x);
+void	X509_STORE_CTX_set_chain(X509_STORE_CTX *c,STACK_OF(X509) *sk);
+void	X509_STORE_CTX_set0_crls(X509_STORE_CTX *c,STACK_OF(X509_CRL) *sk);
+int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose);
+int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust);
+int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose,
+				int purpose, int trust);
+void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, unsigned long flags);
+void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags,
+								time_t t);
+void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx,
+				  int (*verify_cb)(int, X509_STORE_CTX *));
+  
+X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(X509_STORE_CTX *ctx);
+int X509_STORE_CTX_get_explicit_policy(X509_STORE_CTX *ctx);
+
+X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx);
+void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param);
+int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name);
+
+/* X509_VERIFY_PARAM functions */
+
+X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void);
+void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param);
+int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *to,
+						const X509_VERIFY_PARAM *from);
+int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to, 
+						const X509_VERIFY_PARAM *from);
+int X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name);
+int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags);
+int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param,
+							unsigned long flags);
+unsigned long X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param);
+int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose);
+int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust);
+void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth);
+void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t);
+int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param,
+						ASN1_OBJECT *policy);
+int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param, 
+					STACK_OF(ASN1_OBJECT) *policies);
+int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param);
+
+int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param);
+const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name);
+void X509_VERIFY_PARAM_table_cleanup(void);
+
+int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
+			STACK_OF(X509) *certs,
+			STACK_OF(ASN1_OBJECT) *policy_oids,
+			unsigned int flags);
+
+void X509_policy_tree_free(X509_POLICY_TREE *tree);
+
+int X509_policy_tree_level_count(const X509_POLICY_TREE *tree);
+X509_POLICY_LEVEL *
+	X509_policy_tree_get0_level(const X509_POLICY_TREE *tree, int i);
+
+STACK_OF(X509_POLICY_NODE) *
+	X509_policy_tree_get0_policies(const X509_POLICY_TREE *tree);
+
+STACK_OF(X509_POLICY_NODE) *
+	X509_policy_tree_get0_user_policies(const X509_POLICY_TREE *tree);
+
+int X509_policy_level_node_count(X509_POLICY_LEVEL *level);
+
+X509_POLICY_NODE *X509_policy_level_get0_node(X509_POLICY_LEVEL *level, int i);
+
+const ASN1_OBJECT *X509_policy_node_get0_policy(const X509_POLICY_NODE *node);
+
+STACK_OF(POLICYQUALINFO) *
+	X509_policy_node_get0_qualifiers(const X509_POLICY_NODE *node);
+const X509_POLICY_NODE *
+	X509_policy_node_get0_parent(const X509_POLICY_NODE *node);
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
+
diff --git a/dep/include/openssl/x509v3.h b/dep/include/openssl/x509v3.h
new file mode 100644
index 00000000000..91d2fb5b8ba
--- /dev/null
+++ b/dep/include/openssl/x509v3.h
@@ -0,0 +1,919 @@
+/* x509v3.h */
+/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2004 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+#ifndef HEADER_X509V3_H
+#define HEADER_X509V3_H
+
+#include 
+#include 
+#include 
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Forward reference */
+struct v3_ext_method;
+struct v3_ext_ctx;
+
+/* Useful typedefs */
+
+typedef void * (*X509V3_EXT_NEW)(void);
+typedef void (*X509V3_EXT_FREE)(void *);
+typedef void * (*X509V3_EXT_D2I)(void *, const unsigned char ** , long);
+typedef int (*X509V3_EXT_I2D)(void *, unsigned char **);
+typedef STACK_OF(CONF_VALUE) * (*X509V3_EXT_I2V)(struct v3_ext_method *method, void *ext, STACK_OF(CONF_VALUE) *extlist);
+typedef void * (*X509V3_EXT_V2I)(struct v3_ext_method *method, struct v3_ext_ctx *ctx, STACK_OF(CONF_VALUE) *values);
+typedef char * (*X509V3_EXT_I2S)(struct v3_ext_method *method, void *ext);
+typedef void * (*X509V3_EXT_S2I)(struct v3_ext_method *method, struct v3_ext_ctx *ctx, const char *str);
+typedef int (*X509V3_EXT_I2R)(struct v3_ext_method *method, void *ext, BIO *out, int indent);
+typedef void * (*X509V3_EXT_R2I)(struct v3_ext_method *method, struct v3_ext_ctx *ctx, const char *str);
+
+/* V3 extension structure */
+
+struct v3_ext_method {
+int ext_nid;
+int ext_flags;
+/* If this is set the following four fields are ignored */
+ASN1_ITEM_EXP *it;
+/* Old style ASN1 calls */
+X509V3_EXT_NEW ext_new;
+X509V3_EXT_FREE ext_free;
+X509V3_EXT_D2I d2i;
+X509V3_EXT_I2D i2d;
+
+/* The following pair is used for string extensions */
+X509V3_EXT_I2S i2s;
+X509V3_EXT_S2I s2i;
+
+/* The following pair is used for multi-valued extensions */
+X509V3_EXT_I2V i2v;
+X509V3_EXT_V2I v2i;
+
+/* The following are used for raw extensions */
+X509V3_EXT_I2R i2r;
+X509V3_EXT_R2I r2i;
+
+void *usr_data;	/* Any extension specific data */
+};
+
+typedef struct X509V3_CONF_METHOD_st {
+char * (*get_string)(void *db, char *section, char *value);
+STACK_OF(CONF_VALUE) * (*get_section)(void *db, char *section);
+void (*free_string)(void *db, char * string);
+void (*free_section)(void *db, STACK_OF(CONF_VALUE) *section);
+} X509V3_CONF_METHOD;
+
+/* Context specific info */
+struct v3_ext_ctx {
+#define CTX_TEST 0x1
+int flags;
+X509 *issuer_cert;
+X509 *subject_cert;
+X509_REQ *subject_req;
+X509_CRL *crl;
+X509V3_CONF_METHOD *db_meth;
+void *db;
+/* Maybe more here */
+};
+
+typedef struct v3_ext_method X509V3_EXT_METHOD;
+
+DECLARE_STACK_OF(X509V3_EXT_METHOD)
+
+/* ext_flags values */
+#define X509V3_EXT_DYNAMIC	0x1
+#define X509V3_EXT_CTX_DEP	0x2
+#define X509V3_EXT_MULTILINE	0x4
+
+typedef BIT_STRING_BITNAME ENUMERATED_NAMES;
+
+typedef struct BASIC_CONSTRAINTS_st {
+int ca;
+ASN1_INTEGER *pathlen;
+} BASIC_CONSTRAINTS;
+
+
+typedef struct PKEY_USAGE_PERIOD_st {
+ASN1_GENERALIZEDTIME *notBefore;
+ASN1_GENERALIZEDTIME *notAfter;
+} PKEY_USAGE_PERIOD;
+
+typedef struct otherName_st {
+ASN1_OBJECT *type_id;
+ASN1_TYPE *value;
+} OTHERNAME;
+
+typedef struct EDIPartyName_st {
+	ASN1_STRING *nameAssigner;
+	ASN1_STRING *partyName;
+} EDIPARTYNAME;
+
+typedef struct GENERAL_NAME_st {
+
+#define GEN_OTHERNAME	0
+#define GEN_EMAIL	1
+#define GEN_DNS		2
+#define GEN_X400	3
+#define GEN_DIRNAME	4
+#define GEN_EDIPARTY	5
+#define GEN_URI		6
+#define GEN_IPADD	7
+#define GEN_RID		8
+
+int type;
+union {
+	char *ptr;
+	OTHERNAME *otherName; /* otherName */
+	ASN1_IA5STRING *rfc822Name;
+	ASN1_IA5STRING *dNSName;
+	ASN1_TYPE *x400Address;
+	X509_NAME *directoryName;
+	EDIPARTYNAME *ediPartyName;
+	ASN1_IA5STRING *uniformResourceIdentifier;
+	ASN1_OCTET_STRING *iPAddress;
+	ASN1_OBJECT *registeredID;
+
+	/* Old names */
+	ASN1_OCTET_STRING *ip; /* iPAddress */
+	X509_NAME *dirn;		/* dirn */
+	ASN1_IA5STRING *ia5;/* rfc822Name, dNSName, uniformResourceIdentifier */
+	ASN1_OBJECT *rid; /* registeredID */
+	ASN1_TYPE *other; /* x400Address */
+} d;
+} GENERAL_NAME;
+
+typedef STACK_OF(GENERAL_NAME) GENERAL_NAMES;
+
+typedef struct ACCESS_DESCRIPTION_st {
+	ASN1_OBJECT *method;
+	GENERAL_NAME *location;
+} ACCESS_DESCRIPTION;
+
+typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS;
+
+typedef STACK_OF(ASN1_OBJECT) EXTENDED_KEY_USAGE;
+
+DECLARE_STACK_OF(GENERAL_NAME)
+DECLARE_ASN1_SET_OF(GENERAL_NAME)
+
+DECLARE_STACK_OF(ACCESS_DESCRIPTION)
+DECLARE_ASN1_SET_OF(ACCESS_DESCRIPTION)
+
+typedef struct DIST_POINT_NAME_st {
+int type;
+union {
+	GENERAL_NAMES *fullname;
+	STACK_OF(X509_NAME_ENTRY) *relativename;
+} name;
+} DIST_POINT_NAME;
+
+typedef struct DIST_POINT_st {
+DIST_POINT_NAME	*distpoint;
+ASN1_BIT_STRING *reasons;
+GENERAL_NAMES *CRLissuer;
+} DIST_POINT;
+
+typedef STACK_OF(DIST_POINT) CRL_DIST_POINTS;
+
+DECLARE_STACK_OF(DIST_POINT)
+DECLARE_ASN1_SET_OF(DIST_POINT)
+
+typedef struct AUTHORITY_KEYID_st {
+ASN1_OCTET_STRING *keyid;
+GENERAL_NAMES *issuer;
+ASN1_INTEGER *serial;
+} AUTHORITY_KEYID;
+
+/* Strong extranet structures */
+
+typedef struct SXNET_ID_st {
+	ASN1_INTEGER *zone;
+	ASN1_OCTET_STRING *user;
+} SXNETID;
+
+DECLARE_STACK_OF(SXNETID)
+DECLARE_ASN1_SET_OF(SXNETID)
+
+typedef struct SXNET_st {
+	ASN1_INTEGER *version;
+	STACK_OF(SXNETID) *ids;
+} SXNET;
+
+typedef struct NOTICEREF_st {
+	ASN1_STRING *organization;
+	STACK_OF(ASN1_INTEGER) *noticenos;
+} NOTICEREF;
+
+typedef struct USERNOTICE_st {
+	NOTICEREF *noticeref;
+	ASN1_STRING *exptext;
+} USERNOTICE;
+
+typedef struct POLICYQUALINFO_st {
+	ASN1_OBJECT *pqualid;
+	union {
+		ASN1_IA5STRING *cpsuri;
+		USERNOTICE *usernotice;
+		ASN1_TYPE *other;
+	} d;
+} POLICYQUALINFO;
+
+DECLARE_STACK_OF(POLICYQUALINFO)
+DECLARE_ASN1_SET_OF(POLICYQUALINFO)
+
+typedef struct POLICYINFO_st {
+	ASN1_OBJECT *policyid;
+	STACK_OF(POLICYQUALINFO) *qualifiers;
+} POLICYINFO;
+
+typedef STACK_OF(POLICYINFO) CERTIFICATEPOLICIES;
+
+DECLARE_STACK_OF(POLICYINFO)
+DECLARE_ASN1_SET_OF(POLICYINFO)
+
+typedef struct POLICY_MAPPING_st {
+	ASN1_OBJECT *issuerDomainPolicy;
+	ASN1_OBJECT *subjectDomainPolicy;
+} POLICY_MAPPING;
+
+DECLARE_STACK_OF(POLICY_MAPPING)
+
+typedef STACK_OF(POLICY_MAPPING) POLICY_MAPPINGS;
+
+typedef struct GENERAL_SUBTREE_st {
+	GENERAL_NAME *base;
+	ASN1_INTEGER *minimum;
+	ASN1_INTEGER *maximum;
+} GENERAL_SUBTREE;
+
+DECLARE_STACK_OF(GENERAL_SUBTREE)
+
+typedef struct NAME_CONSTRAINTS_st {
+	STACK_OF(GENERAL_SUBTREE) *permittedSubtrees;
+	STACK_OF(GENERAL_SUBTREE) *excludedSubtrees;
+} NAME_CONSTRAINTS;
+
+typedef struct POLICY_CONSTRAINTS_st {
+	ASN1_INTEGER *requireExplicitPolicy;
+	ASN1_INTEGER *inhibitPolicyMapping;
+} POLICY_CONSTRAINTS;
+
+/* Proxy certificate structures, see RFC 3820 */
+typedef struct PROXY_POLICY_st
+	{
+	ASN1_OBJECT *policyLanguage;
+	ASN1_OCTET_STRING *policy;
+	} PROXY_POLICY;
+
+typedef struct PROXY_CERT_INFO_EXTENSION_st
+	{
+	ASN1_INTEGER *pcPathLengthConstraint;
+	PROXY_POLICY *proxyPolicy;
+	} PROXY_CERT_INFO_EXTENSION;
+
+DECLARE_ASN1_FUNCTIONS(PROXY_POLICY)
+DECLARE_ASN1_FUNCTIONS(PROXY_CERT_INFO_EXTENSION)
+
+
+#define X509V3_conf_err(val) ERR_add_error_data(6, "section:", val->section, \
+",name:", val->name, ",value:", val->value);
+
+#define X509V3_set_ctx_test(ctx) \
+			X509V3_set_ctx(ctx, NULL, NULL, NULL, NULL, CTX_TEST)
+#define X509V3_set_ctx_nodb(ctx) (ctx)->db = NULL;
+
+#define EXT_BITSTRING(nid, table) { nid, 0, ASN1_ITEM_ref(ASN1_BIT_STRING), \
+			0,0,0,0, \
+			0,0, \
+			(X509V3_EXT_I2V)i2v_ASN1_BIT_STRING, \
+			(X509V3_EXT_V2I)v2i_ASN1_BIT_STRING, \
+			NULL, NULL, \
+			table}
+
+#define EXT_IA5STRING(nid) { nid, 0, ASN1_ITEM_ref(ASN1_IA5STRING), \
+			0,0,0,0, \
+			(X509V3_EXT_I2S)i2s_ASN1_IA5STRING, \
+			(X509V3_EXT_S2I)s2i_ASN1_IA5STRING, \
+			0,0,0,0, \
+			NULL}
+
+#define EXT_END { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+
+
+/* X509_PURPOSE stuff */
+
+#define EXFLAG_BCONS		0x1
+#define EXFLAG_KUSAGE		0x2
+#define EXFLAG_XKUSAGE		0x4
+#define EXFLAG_NSCERT		0x8
+
+#define EXFLAG_CA		0x10
+#define EXFLAG_SS		0x20
+#define EXFLAG_V1		0x40
+#define EXFLAG_INVALID		0x80
+#define EXFLAG_SET		0x100
+#define EXFLAG_CRITICAL		0x200
+#define EXFLAG_PROXY		0x400
+
+#define EXFLAG_INVALID_POLICY	0x400
+
+#define KU_DIGITAL_SIGNATURE	0x0080
+#define KU_NON_REPUDIATION	0x0040
+#define KU_KEY_ENCIPHERMENT	0x0020
+#define KU_DATA_ENCIPHERMENT	0x0010
+#define KU_KEY_AGREEMENT	0x0008
+#define KU_KEY_CERT_SIGN	0x0004
+#define KU_CRL_SIGN		0x0002
+#define KU_ENCIPHER_ONLY	0x0001
+#define KU_DECIPHER_ONLY	0x8000
+
+#define NS_SSL_CLIENT		0x80
+#define NS_SSL_SERVER		0x40
+#define NS_SMIME		0x20
+#define NS_OBJSIGN		0x10
+#define NS_SSL_CA		0x04
+#define NS_SMIME_CA		0x02
+#define NS_OBJSIGN_CA		0x01
+#define NS_ANY_CA		(NS_SSL_CA|NS_SMIME_CA|NS_OBJSIGN_CA)
+
+#define XKU_SSL_SERVER		0x1	
+#define XKU_SSL_CLIENT		0x2
+#define XKU_SMIME		0x4
+#define XKU_CODE_SIGN		0x8
+#define XKU_SGC			0x10
+#define XKU_OCSP_SIGN		0x20
+#define XKU_TIMESTAMP		0x40
+#define XKU_DVCS		0x80
+
+#define X509_PURPOSE_DYNAMIC	0x1
+#define X509_PURPOSE_DYNAMIC_NAME	0x2
+
+typedef struct x509_purpose_st {
+	int purpose;
+	int trust;		/* Default trust ID */
+	int flags;
+	int (*check_purpose)(const struct x509_purpose_st *,
+				const X509 *, int);
+	char *name;
+	char *sname;
+	void *usr_data;
+} X509_PURPOSE;
+
+#define X509_PURPOSE_SSL_CLIENT		1
+#define X509_PURPOSE_SSL_SERVER		2
+#define X509_PURPOSE_NS_SSL_SERVER	3
+#define X509_PURPOSE_SMIME_SIGN		4
+#define X509_PURPOSE_SMIME_ENCRYPT	5
+#define X509_PURPOSE_CRL_SIGN		6
+#define X509_PURPOSE_ANY		7
+#define X509_PURPOSE_OCSP_HELPER	8
+
+#define X509_PURPOSE_MIN		1
+#define X509_PURPOSE_MAX		8
+
+/* Flags for X509V3_EXT_print() */
+
+#define X509V3_EXT_UNKNOWN_MASK		(0xfL << 16)
+/* Return error for unknown extensions */
+#define X509V3_EXT_DEFAULT		0
+/* Print error for unknown extensions */
+#define X509V3_EXT_ERROR_UNKNOWN	(1L << 16)
+/* ASN1 parse unknown extensions */
+#define X509V3_EXT_PARSE_UNKNOWN	(2L << 16)
+/* BIO_dump unknown extensions */
+#define X509V3_EXT_DUMP_UNKNOWN		(3L << 16)
+
+/* Flags for X509V3_add1_i2d */
+
+#define X509V3_ADD_OP_MASK		0xfL
+#define X509V3_ADD_DEFAULT		0L
+#define X509V3_ADD_APPEND		1L
+#define X509V3_ADD_REPLACE		2L
+#define X509V3_ADD_REPLACE_EXISTING	3L
+#define X509V3_ADD_KEEP_EXISTING	4L
+#define X509V3_ADD_DELETE		5L
+#define X509V3_ADD_SILENT		0x10
+
+DECLARE_STACK_OF(X509_PURPOSE)
+
+DECLARE_ASN1_FUNCTIONS(BASIC_CONSTRAINTS)
+
+DECLARE_ASN1_FUNCTIONS(SXNET)
+DECLARE_ASN1_FUNCTIONS(SXNETID)
+
+int SXNET_add_id_asc(SXNET **psx, char *zone, char *user, int userlen); 
+int SXNET_add_id_ulong(SXNET **psx, unsigned long lzone, char *user, int userlen); 
+int SXNET_add_id_INTEGER(SXNET **psx, ASN1_INTEGER *izone, char *user, int userlen); 
+
+ASN1_OCTET_STRING *SXNET_get_id_asc(SXNET *sx, char *zone);
+ASN1_OCTET_STRING *SXNET_get_id_ulong(SXNET *sx, unsigned long lzone);
+ASN1_OCTET_STRING *SXNET_get_id_INTEGER(SXNET *sx, ASN1_INTEGER *zone);
+
+DECLARE_ASN1_FUNCTIONS(AUTHORITY_KEYID)
+
+DECLARE_ASN1_FUNCTIONS(PKEY_USAGE_PERIOD)
+
+DECLARE_ASN1_FUNCTIONS(GENERAL_NAME)
+
+
+ASN1_BIT_STRING *v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method,
+				X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
+STACK_OF(CONF_VALUE) *i2v_ASN1_BIT_STRING(X509V3_EXT_METHOD *method,
+				ASN1_BIT_STRING *bits,
+				STACK_OF(CONF_VALUE) *extlist);
+
+STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, GENERAL_NAME *gen, STACK_OF(CONF_VALUE) *ret);
+int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen);
+
+DECLARE_ASN1_FUNCTIONS(GENERAL_NAMES)
+
+STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method,
+		GENERAL_NAMES *gen, STACK_OF(CONF_VALUE) *extlist);
+GENERAL_NAMES *v2i_GENERAL_NAMES(X509V3_EXT_METHOD *method,
+				X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
+
+DECLARE_ASN1_FUNCTIONS(OTHERNAME)
+DECLARE_ASN1_FUNCTIONS(EDIPARTYNAME)
+
+char *i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, ASN1_OCTET_STRING *ia5);
+ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *str);
+
+DECLARE_ASN1_FUNCTIONS(EXTENDED_KEY_USAGE)
+int i2a_ACCESS_DESCRIPTION(BIO *bp, ACCESS_DESCRIPTION* a);
+
+DECLARE_ASN1_FUNCTIONS(CERTIFICATEPOLICIES)
+DECLARE_ASN1_FUNCTIONS(POLICYINFO)
+DECLARE_ASN1_FUNCTIONS(POLICYQUALINFO)
+DECLARE_ASN1_FUNCTIONS(USERNOTICE)
+DECLARE_ASN1_FUNCTIONS(NOTICEREF)
+
+DECLARE_ASN1_FUNCTIONS(CRL_DIST_POINTS)
+DECLARE_ASN1_FUNCTIONS(DIST_POINT)
+DECLARE_ASN1_FUNCTIONS(DIST_POINT_NAME)
+
+DECLARE_ASN1_FUNCTIONS(ACCESS_DESCRIPTION)
+DECLARE_ASN1_FUNCTIONS(AUTHORITY_INFO_ACCESS)
+
+DECLARE_ASN1_ITEM(POLICY_MAPPING)
+DECLARE_ASN1_ALLOC_FUNCTIONS(POLICY_MAPPING)
+DECLARE_ASN1_ITEM(POLICY_MAPPINGS)
+
+DECLARE_ASN1_ITEM(GENERAL_SUBTREE)
+DECLARE_ASN1_ALLOC_FUNCTIONS(GENERAL_SUBTREE)
+
+DECLARE_ASN1_ITEM(NAME_CONSTRAINTS)
+DECLARE_ASN1_ALLOC_FUNCTIONS(NAME_CONSTRAINTS)
+
+DECLARE_ASN1_ALLOC_FUNCTIONS(POLICY_CONSTRAINTS)
+DECLARE_ASN1_ITEM(POLICY_CONSTRAINTS)
+
+#ifdef HEADER_CONF_H
+GENERAL_NAME *v2i_GENERAL_NAME(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
+							CONF_VALUE *cnf);
+GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out, X509V3_EXT_METHOD *method,
+				X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc);
+void X509V3_conf_free(CONF_VALUE *val);
+
+X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid, char *value);
+X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, char *name, char *value);
+int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, char *section, STACK_OF(X509_EXTENSION) **sk);
+int X509V3_EXT_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, X509 *cert);
+int X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, X509_REQ *req);
+int X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, X509_CRL *crl);
+
+X509_EXTENSION *X509V3_EXT_conf_nid(LHASH *conf, X509V3_CTX *ctx, int ext_nid, char *value);
+X509_EXTENSION *X509V3_EXT_conf(LHASH *conf, X509V3_CTX *ctx, char *name, char *value);
+int X509V3_EXT_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, X509 *cert);
+int X509V3_EXT_REQ_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, X509_REQ *req);
+int X509V3_EXT_CRL_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, X509_CRL *crl);
+
+int X509V3_add_value_bool_nf(char *name, int asn1_bool,
+						STACK_OF(CONF_VALUE) **extlist);
+int X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool);
+int X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint);
+void X509V3_set_nconf(X509V3_CTX *ctx, CONF *conf);
+void X509V3_set_conf_lhash(X509V3_CTX *ctx, LHASH *lhash);
+#endif
+
+char * X509V3_get_string(X509V3_CTX *ctx, char *name, char *section);
+STACK_OF(CONF_VALUE) * X509V3_get_section(X509V3_CTX *ctx, char *section);
+void X509V3_string_free(X509V3_CTX *ctx, char *str);
+void X509V3_section_free( X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *section);
+void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subject,
+				 X509_REQ *req, X509_CRL *crl, int flags);
+
+int X509V3_add_value(const char *name, const char *value,
+						STACK_OF(CONF_VALUE) **extlist);
+int X509V3_add_value_uchar(const char *name, const unsigned char *value,
+						STACK_OF(CONF_VALUE) **extlist);
+int X509V3_add_value_bool(const char *name, int asn1_bool,
+						STACK_OF(CONF_VALUE) **extlist);
+int X509V3_add_value_int(const char *name, ASN1_INTEGER *aint,
+						STACK_OF(CONF_VALUE) **extlist);
+char * i2s_ASN1_INTEGER(X509V3_EXT_METHOD *meth, ASN1_INTEGER *aint);
+ASN1_INTEGER * s2i_ASN1_INTEGER(X509V3_EXT_METHOD *meth, char *value);
+char * i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *meth, ASN1_ENUMERATED *aint);
+char * i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD *meth, ASN1_ENUMERATED *aint);
+int X509V3_EXT_add(X509V3_EXT_METHOD *ext);
+int X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist);
+int X509V3_EXT_add_alias(int nid_to, int nid_from);
+void X509V3_EXT_cleanup(void);
+
+X509V3_EXT_METHOD *X509V3_EXT_get(X509_EXTENSION *ext);
+X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid);
+int X509V3_add_standard_extensions(void);
+STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line);
+void *X509V3_EXT_d2i(X509_EXTENSION *ext);
+void *X509V3_get_d2i(STACK_OF(X509_EXTENSION) *x, int nid, int *crit, int *idx);
+
+
+X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc);
+int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value, int crit, unsigned long flags);
+
+char *hex_to_string(unsigned char *buffer, long len);
+unsigned char *string_to_hex(char *str, long *len);
+int name_cmp(const char *name, const char *cmp);
+
+void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent,
+								 int ml);
+int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, int indent);
+int X509V3_EXT_print_fp(FILE *out, X509_EXTENSION *ext, int flag, int indent);
+
+int X509V3_extensions_print(BIO *out, char *title, STACK_OF(X509_EXTENSION) *exts, unsigned long flag, int indent);
+
+int X509_check_ca(X509 *x);
+int X509_check_purpose(X509 *x, int id, int ca);
+int X509_supported_extension(X509_EXTENSION *ex);
+int X509_PURPOSE_set(int *p, int purpose);
+int X509_check_issued(X509 *issuer, X509 *subject);
+int X509_PURPOSE_get_count(void);
+X509_PURPOSE * X509_PURPOSE_get0(int idx);
+int X509_PURPOSE_get_by_sname(char *sname);
+int X509_PURPOSE_get_by_id(int id);
+int X509_PURPOSE_add(int id, int trust, int flags,
+			int (*ck)(const X509_PURPOSE *, const X509 *, int),
+				char *name, char *sname, void *arg);
+char *X509_PURPOSE_get0_name(X509_PURPOSE *xp);
+char *X509_PURPOSE_get0_sname(X509_PURPOSE *xp);
+int X509_PURPOSE_get_trust(X509_PURPOSE *xp);
+void X509_PURPOSE_cleanup(void);
+int X509_PURPOSE_get_id(X509_PURPOSE *);
+
+STACK *X509_get1_email(X509 *x);
+STACK *X509_REQ_get1_email(X509_REQ *x);
+void X509_email_free(STACK *sk);
+
+ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc);
+ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc);
+int a2i_ipadd(unsigned char *ipout, const char *ipasc);
+int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE)*dn_sk,
+						unsigned long chtype);
+
+void X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent);
+
+#ifndef OPENSSL_NO_RFC3779
+
+typedef struct ASRange_st {
+  ASN1_INTEGER *min, *max;
+} ASRange;
+
+#define	ASIdOrRange_id		0
+#define	ASIdOrRange_range	1
+
+typedef struct ASIdOrRange_st {
+  int type;
+  union {
+    ASN1_INTEGER *id;
+    ASRange      *range;
+  } u;
+} ASIdOrRange;
+
+typedef STACK_OF(ASIdOrRange) ASIdOrRanges;
+DECLARE_STACK_OF(ASIdOrRange)
+
+#define	ASIdentifierChoice_inherit		0
+#define	ASIdentifierChoice_asIdsOrRanges	1
+
+typedef struct ASIdentifierChoice_st {
+  int type;
+  union {
+    ASN1_NULL    *inherit;
+    ASIdOrRanges *asIdsOrRanges;
+  } u;
+} ASIdentifierChoice;
+
+typedef struct ASIdentifiers_st {
+  ASIdentifierChoice *asnum, *rdi;
+} ASIdentifiers;
+
+DECLARE_ASN1_FUNCTIONS(ASRange)
+DECLARE_ASN1_FUNCTIONS(ASIdOrRange)
+DECLARE_ASN1_FUNCTIONS(ASIdentifierChoice)
+DECLARE_ASN1_FUNCTIONS(ASIdentifiers)
+
+
+typedef struct IPAddressRange_st {
+  ASN1_BIT_STRING	*min, *max;
+} IPAddressRange;
+
+#define	IPAddressOrRange_addressPrefix	0
+#define	IPAddressOrRange_addressRange	1
+
+typedef struct IPAddressOrRange_st {
+  int type;
+  union {
+    ASN1_BIT_STRING	*addressPrefix;
+    IPAddressRange	*addressRange;
+  } u;
+} IPAddressOrRange;
+
+typedef STACK_OF(IPAddressOrRange) IPAddressOrRanges;
+DECLARE_STACK_OF(IPAddressOrRange)
+
+#define	IPAddressChoice_inherit			0
+#define	IPAddressChoice_addressesOrRanges	1
+
+typedef struct IPAddressChoice_st {
+  int type;
+  union {
+    ASN1_NULL		*inherit;
+    IPAddressOrRanges	*addressesOrRanges;
+  } u;
+} IPAddressChoice;
+
+typedef struct IPAddressFamily_st {
+  ASN1_OCTET_STRING	*addressFamily;
+  IPAddressChoice	*ipAddressChoice;
+} IPAddressFamily;
+
+typedef STACK_OF(IPAddressFamily) IPAddrBlocks;
+DECLARE_STACK_OF(IPAddressFamily)
+
+DECLARE_ASN1_FUNCTIONS(IPAddressRange)
+DECLARE_ASN1_FUNCTIONS(IPAddressOrRange)
+DECLARE_ASN1_FUNCTIONS(IPAddressChoice)
+DECLARE_ASN1_FUNCTIONS(IPAddressFamily)
+
+/*
+ * API tag for elements of the ASIdentifer SEQUENCE.
+ */
+#define	V3_ASID_ASNUM	0
+#define	V3_ASID_RDI	1
+
+/*
+ * AFI values, assigned by IANA.  It'd be nice to make the AFI
+ * handling code totally generic, but there are too many little things
+ * that would need to be defined for other address families for it to
+ * be worth the trouble.
+ */
+#define	IANA_AFI_IPV4	1
+#define	IANA_AFI_IPV6	2
+
+/*
+ * Utilities to construct and extract values from RFC3779 extensions,
+ * since some of the encodings (particularly for IP address prefixes
+ * and ranges) are a bit tedious to work with directly.
+ */
+int v3_asid_add_inherit(ASIdentifiers *asid, int which);
+int v3_asid_add_id_or_range(ASIdentifiers *asid, int which,
+			    ASN1_INTEGER *min, ASN1_INTEGER *max);
+int v3_addr_add_inherit(IPAddrBlocks *addr,
+			const unsigned afi, const unsigned *safi);
+int v3_addr_add_prefix(IPAddrBlocks *addr,
+		       const unsigned afi, const unsigned *safi,
+		       unsigned char *a, const int prefixlen);
+int v3_addr_add_range(IPAddrBlocks *addr,
+		      const unsigned afi, const unsigned *safi,
+		      unsigned char *min, unsigned char *max);
+unsigned v3_addr_get_afi(const IPAddressFamily *f);
+int v3_addr_get_range(IPAddressOrRange *aor, const unsigned afi,
+		      unsigned char *min, unsigned char *max,
+		      const int length);
+
+/*
+ * Canonical forms.
+ */
+int v3_asid_is_canonical(ASIdentifiers *asid);
+int v3_addr_is_canonical(IPAddrBlocks *addr);
+int v3_asid_canonize(ASIdentifiers *asid);
+int v3_addr_canonize(IPAddrBlocks *addr);
+
+/*
+ * Tests for inheritance and containment.
+ */
+int v3_asid_inherits(ASIdentifiers *asid);
+int v3_addr_inherits(IPAddrBlocks *addr);
+int v3_asid_subset(ASIdentifiers *a, ASIdentifiers *b);
+int v3_addr_subset(IPAddrBlocks *a, IPAddrBlocks *b);
+
+/*
+ * Check whether RFC 3779 extensions nest properly in chains.
+ */
+int v3_asid_validate_path(X509_STORE_CTX *);
+int v3_addr_validate_path(X509_STORE_CTX *);
+int v3_asid_validate_resource_set(STACK_OF(X509) *chain,
+				  ASIdentifiers *ext,
+				  int allow_inheritance);
+int v3_addr_validate_resource_set(STACK_OF(X509) *chain,
+				  IPAddrBlocks *ext,
+				  int allow_inheritance);
+
+#endif /* OPENSSL_NO_RFC3779 */
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_X509V3_strings(void);
+
+/* Error codes for the X509V3 functions. */
+
+/* Function codes. */
+#define X509V3_F_ASIDENTIFIERCHOICE_CANONIZE		 156
+#define X509V3_F_ASIDENTIFIERCHOICE_IS_CANONICAL	 157
+#define X509V3_F_COPY_EMAIL				 122
+#define X509V3_F_COPY_ISSUER				 123
+#define X509V3_F_DO_DIRNAME				 144
+#define X509V3_F_DO_EXT_CONF				 124
+#define X509V3_F_DO_EXT_I2D				 135
+#define X509V3_F_DO_EXT_NCONF				 151
+#define X509V3_F_DO_I2V_NAME_CONSTRAINTS		 148
+#define X509V3_F_HEX_TO_STRING				 111
+#define X509V3_F_I2S_ASN1_ENUMERATED			 121
+#define X509V3_F_I2S_ASN1_IA5STRING			 149
+#define X509V3_F_I2S_ASN1_INTEGER			 120
+#define X509V3_F_I2V_AUTHORITY_INFO_ACCESS		 138
+#define X509V3_F_NOTICE_SECTION				 132
+#define X509V3_F_NREF_NOS				 133
+#define X509V3_F_POLICY_SECTION				 131
+#define X509V3_F_PROCESS_PCI_VALUE			 150
+#define X509V3_F_R2I_CERTPOL				 130
+#define X509V3_F_R2I_PCI				 155
+#define X509V3_F_S2I_ASN1_IA5STRING			 100
+#define X509V3_F_S2I_ASN1_INTEGER			 108
+#define X509V3_F_S2I_ASN1_OCTET_STRING			 112
+#define X509V3_F_S2I_ASN1_SKEY_ID			 114
+#define X509V3_F_S2I_SKEY_ID				 115
+#define X509V3_F_STRING_TO_HEX				 113
+#define X509V3_F_SXNET_ADD_ID_ASC			 125
+#define X509V3_F_SXNET_ADD_ID_INTEGER			 126
+#define X509V3_F_SXNET_ADD_ID_ULONG			 127
+#define X509V3_F_SXNET_GET_ID_ASC			 128
+#define X509V3_F_SXNET_GET_ID_ULONG			 129
+#define X509V3_F_V2I_ASIDENTIFIERS			 158
+#define X509V3_F_V2I_ASN1_BIT_STRING			 101
+#define X509V3_F_V2I_AUTHORITY_INFO_ACCESS		 139
+#define X509V3_F_V2I_AUTHORITY_KEYID			 119
+#define X509V3_F_V2I_BASIC_CONSTRAINTS			 102
+#define X509V3_F_V2I_CRLD				 134
+#define X509V3_F_V2I_EXTENDED_KEY_USAGE			 103
+#define X509V3_F_V2I_GENERAL_NAMES			 118
+#define X509V3_F_V2I_GENERAL_NAME_EX			 117
+#define X509V3_F_V2I_IPADDRBLOCKS			 159
+#define X509V3_F_V2I_ISSUER_ALT				 153
+#define X509V3_F_V2I_NAME_CONSTRAINTS			 147
+#define X509V3_F_V2I_POLICY_CONSTRAINTS			 146
+#define X509V3_F_V2I_POLICY_MAPPINGS			 145
+#define X509V3_F_V2I_SUBJECT_ALT			 154
+#define X509V3_F_V3_ADDR_VALIDATE_PATH_INTERNAL		 160
+#define X509V3_F_V3_GENERIC_EXTENSION			 116
+#define X509V3_F_X509V3_ADD1_I2D			 140
+#define X509V3_F_X509V3_ADD_VALUE			 105
+#define X509V3_F_X509V3_EXT_ADD				 104
+#define X509V3_F_X509V3_EXT_ADD_ALIAS			 106
+#define X509V3_F_X509V3_EXT_CONF			 107
+#define X509V3_F_X509V3_EXT_I2D				 136
+#define X509V3_F_X509V3_EXT_NCONF			 152
+#define X509V3_F_X509V3_GET_SECTION			 142
+#define X509V3_F_X509V3_GET_STRING			 143
+#define X509V3_F_X509V3_GET_VALUE_BOOL			 110
+#define X509V3_F_X509V3_PARSE_LIST			 109
+#define X509V3_F_X509_PURPOSE_ADD			 137
+#define X509V3_F_X509_PURPOSE_SET			 141
+
+/* Reason codes. */
+#define X509V3_R_BAD_IP_ADDRESS				 118
+#define X509V3_R_BAD_OBJECT				 119
+#define X509V3_R_BN_DEC2BN_ERROR			 100
+#define X509V3_R_BN_TO_ASN1_INTEGER_ERROR		 101
+#define X509V3_R_DIRNAME_ERROR				 149
+#define X509V3_R_DUPLICATE_ZONE_ID			 133
+#define X509V3_R_ERROR_CONVERTING_ZONE			 131
+#define X509V3_R_ERROR_CREATING_EXTENSION		 144
+#define X509V3_R_ERROR_IN_EXTENSION			 128
+#define X509V3_R_EXPECTED_A_SECTION_NAME		 137
+#define X509V3_R_EXTENSION_EXISTS			 145
+#define X509V3_R_EXTENSION_NAME_ERROR			 115
+#define X509V3_R_EXTENSION_NOT_FOUND			 102
+#define X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED	 103
+#define X509V3_R_EXTENSION_VALUE_ERROR			 116
+#define X509V3_R_ILLEGAL_EMPTY_EXTENSION		 151
+#define X509V3_R_ILLEGAL_HEX_DIGIT			 113
+#define X509V3_R_INCORRECT_POLICY_SYNTAX_TAG		 152
+#define X509V3_R_INVALID_ASNUMBER			 160
+#define X509V3_R_INVALID_ASRANGE			 161
+#define X509V3_R_INVALID_BOOLEAN_STRING			 104
+#define X509V3_R_INVALID_EXTENSION_STRING		 105
+#define X509V3_R_INVALID_INHERITANCE			 162
+#define X509V3_R_INVALID_IPADDRESS			 163
+#define X509V3_R_INVALID_NAME				 106
+#define X509V3_R_INVALID_NULL_ARGUMENT			 107
+#define X509V3_R_INVALID_NULL_NAME			 108
+#define X509V3_R_INVALID_NULL_VALUE			 109
+#define X509V3_R_INVALID_NUMBER				 140
+#define X509V3_R_INVALID_NUMBERS			 141
+#define X509V3_R_INVALID_OBJECT_IDENTIFIER		 110
+#define X509V3_R_INVALID_OPTION				 138
+#define X509V3_R_INVALID_POLICY_IDENTIFIER		 134
+#define X509V3_R_INVALID_PROXY_POLICY_SETTING		 153
+#define X509V3_R_INVALID_PURPOSE			 146
+#define X509V3_R_INVALID_SAFI				 164
+#define X509V3_R_INVALID_SECTION			 135
+#define X509V3_R_INVALID_SYNTAX				 143
+#define X509V3_R_ISSUER_DECODE_ERROR			 126
+#define X509V3_R_MISSING_VALUE				 124
+#define X509V3_R_NEED_ORGANIZATION_AND_NUMBERS		 142
+#define X509V3_R_NO_CONFIG_DATABASE			 136
+#define X509V3_R_NO_ISSUER_CERTIFICATE			 121
+#define X509V3_R_NO_ISSUER_DETAILS			 127
+#define X509V3_R_NO_POLICY_IDENTIFIER			 139
+#define X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED	 154
+#define X509V3_R_NO_PUBLIC_KEY				 114
+#define X509V3_R_NO_SUBJECT_DETAILS			 125
+#define X509V3_R_ODD_NUMBER_OF_DIGITS			 112
+#define X509V3_R_OPERATION_NOT_DEFINED			 148
+#define X509V3_R_OTHERNAME_ERROR			 147
+#define X509V3_R_POLICY_LANGUAGE_ALREADTY_DEFINED	 155
+#define X509V3_R_POLICY_PATH_LENGTH			 156
+#define X509V3_R_POLICY_PATH_LENGTH_ALREADTY_DEFINED	 157
+#define X509V3_R_POLICY_SYNTAX_NOT_CURRENTLY_SUPPORTED	 158
+#define X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY 159
+#define X509V3_R_SECTION_NOT_FOUND			 150
+#define X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS		 122
+#define X509V3_R_UNABLE_TO_GET_ISSUER_KEYID		 123
+#define X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT		 111
+#define X509V3_R_UNKNOWN_EXTENSION			 129
+#define X509V3_R_UNKNOWN_EXTENSION_NAME			 130
+#define X509V3_R_UNKNOWN_OPTION				 120
+#define X509V3_R_UNSUPPORTED_OPTION			 117
+#define X509V3_R_USER_TOO_LONG				 132
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/dep/include/postgre/libpq-fe.h b/dep/include/postgre/libpq-fe.h
new file mode 100644
index 00000000000..f51c6b38acd
--- /dev/null
+++ b/dep/include/postgre/libpq-fe.h
@@ -0,0 +1,525 @@
+/*-------------------------------------------------------------------------
+ *
+ * libpq-fe.h
+ *	  This file contains definitions for structures and
+ *	  externs for functions used by frontend postgres applications.
+ *
+ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-fe.h,v 1.141 2008/01/01 19:46:00 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef LIBPQ_FE_H
+#define LIBPQ_FE_H
+
+#ifdef __cplusplus
+extern		"C"
+{
+#endif
+
+#include 
+
+/*
+ * postgres_ext.h defines the backend's externally visible types,
+ * such as Oid.
+ */
+#include "postgres_ext.h"
+
+/* Application-visible enum types */
+
+typedef enum
+{
+	/*
+	 * Although it is okay to add to this list, values which become unused
+	 * should never be removed, nor should constants be redefined - that would
+	 * break compatibility with existing code.
+	 */
+	CONNECTION_OK,
+	CONNECTION_BAD,
+	/* Non-blocking mode only below here */
+
+	/*
+	 * The existence of these should never be relied upon - they should only
+	 * be used for user feedback or similar purposes.
+	 */
+	CONNECTION_STARTED,			/* Waiting for connection to be made.  */
+	CONNECTION_MADE,			/* Connection OK; waiting to send.	   */
+	CONNECTION_AWAITING_RESPONSE,		/* Waiting for a response from the
+										 * postmaster.		  */
+	CONNECTION_AUTH_OK,			/* Received authentication; waiting for
+								 * backend startup. */
+	CONNECTION_SETENV,			/* Negotiating environment. */
+	CONNECTION_SSL_STARTUP,		/* Negotiating SSL. */
+	CONNECTION_NEEDED			/* Internal state: connect() needed */
+} ConnStatusType;
+
+typedef enum
+{
+	PGRES_POLLING_FAILED = 0,
+	PGRES_POLLING_READING,		/* These two indicate that one may	  */
+	PGRES_POLLING_WRITING,		/* use select before polling again.   */
+	PGRES_POLLING_OK,
+	PGRES_POLLING_ACTIVE		/* unused; keep for awhile for backwards
+								 * compatibility */
+} PostgresPollingStatusType;
+
+typedef enum
+{
+	PGRES_EMPTY_QUERY = 0,		/* empty query string was executed */
+	PGRES_COMMAND_OK,			/* a query command that doesn't return
+								 * anything was executed properly by the
+								 * backend */
+	PGRES_TUPLES_OK,			/* a query command that returns tuples was
+								 * executed properly by the backend, PGresult
+								 * contains the result tuples */
+	PGRES_COPY_OUT,				/* Copy Out data transfer in progress */
+	PGRES_COPY_IN,				/* Copy In data transfer in progress */
+	PGRES_BAD_RESPONSE,			/* an unexpected response was recv'd from the
+								 * backend */
+	PGRES_NONFATAL_ERROR,		/* notice or warning message */
+	PGRES_FATAL_ERROR			/* query failed */
+} ExecStatusType;
+
+typedef enum
+{
+	PQTRANS_IDLE,				/* connection idle */
+	PQTRANS_ACTIVE,				/* command in progress */
+	PQTRANS_INTRANS,			/* idle, within transaction block */
+	PQTRANS_INERROR,			/* idle, within failed transaction */
+	PQTRANS_UNKNOWN				/* cannot determine status */
+} PGTransactionStatusType;
+
+typedef enum
+{
+	PQERRORS_TERSE,				/* single-line error messages */
+	PQERRORS_DEFAULT,			/* recommended style */
+	PQERRORS_VERBOSE			/* all the facts, ma'am */
+} PGVerbosity;
+
+/* PGconn encapsulates a connection to the backend.
+ * The contents of this struct are not supposed to be known to applications.
+ */
+typedef struct pg_conn PGconn;
+
+/* PGresult encapsulates the result of a query (or more precisely, of a single
+ * SQL command --- a query string given to PQsendQuery can contain multiple
+ * commands and thus return multiple PGresult objects).
+ * The contents of this struct are not supposed to be known to applications.
+ */
+typedef struct pg_result PGresult;
+
+/* PGcancel encapsulates the information needed to cancel a running
+ * query on an existing connection.
+ * The contents of this struct are not supposed to be known to applications.
+ */
+typedef struct pg_cancel PGcancel;
+
+/* PGnotify represents the occurrence of a NOTIFY message.
+ * Ideally this would be an opaque typedef, but it's so simple that it's
+ * unlikely to change.
+ * NOTE: in Postgres 6.4 and later, the be_pid is the notifying backend's,
+ * whereas in earlier versions it was always your own backend's PID.
+ */
+typedef struct pgNotify
+{
+	char	   *relname;		/* notification condition name */
+	int			be_pid;			/* process ID of notifying server process */
+	char	   *extra;			/* notification parameter */
+	/* Fields below here are private to libpq; apps should not use 'em */
+	struct pgNotify *next;		/* list link */
+} PGnotify;
+
+/* Function types for notice-handling callbacks */
+typedef void (*PQnoticeReceiver) (void *arg, const PGresult *res);
+typedef void (*PQnoticeProcessor) (void *arg, const char *message);
+
+/* Print options for PQprint() */
+typedef char pqbool;
+
+typedef struct _PQprintOpt
+{
+	pqbool		header;			/* print output field headings and row count */
+	pqbool		align;			/* fill align the fields */
+	pqbool		standard;		/* old brain dead format */
+	pqbool		html3;			/* output html tables */
+	pqbool		expanded;		/* expand tables */
+	pqbool		pager;			/* use pager for output if needed */
+	char	   *fieldSep;		/* field separator */
+	char	   *tableOpt;		/* insert to HTML  */
+	char	   *caption;		/* HTML 
*/ + char **fieldName; /* null terminated array of replacement field + * names */ +} PQprintOpt; + +/* ---------------- + * Structure for the conninfo parameter definitions returned by PQconndefaults + * + * All fields except "val" point at static strings which must not be altered. + * "val" is either NULL or a malloc'd current-value string. PQconninfoFree() + * will release both the val strings and the PQconninfoOption array itself. + * ---------------- + */ +typedef struct _PQconninfoOption +{ + char *keyword; /* The keyword of the option */ + char *envvar; /* Fallback environment variable name */ + char *compiled; /* Fallback compiled in default value */ + char *val; /* Option's current value, or NULL */ + char *label; /* Label for field in connect dialog */ + char *dispchar; /* Character to display for this field in a + * connect dialog. Values are: "" Display + * entered value as is "*" Password field - + * hide value "D" Debug option - don't show + * by default */ + int dispsize; /* Field size in characters for dialog */ +} PQconninfoOption; + +/* ---------------- + * PQArgBlock -- structure for PQfn() arguments + * ---------------- + */ +typedef struct +{ + int len; + int isint; + union + { + int *ptr; /* can't use void (dec compiler barfs) */ + int integer; + } u; +} PQArgBlock; + +/* ---------------- + * Exported functions of libpq + * ---------------- + */ + +/* === in fe-connect.c === */ + +/* make a new client connection to the backend */ +/* Asynchronous (non-blocking) */ +extern PGconn *PQconnectStart(const char *conninfo); +extern PostgresPollingStatusType PQconnectPoll(PGconn *conn); + +/* Synchronous (blocking) */ +extern PGconn *PQconnectdb(const char *conninfo); +extern PGconn *PQsetdbLogin(const char *pghost, const char *pgport, + const char *pgoptions, const char *pgtty, + const char *dbName, + const char *login, const char *pwd); + +#define PQsetdb(M_PGHOST,M_PGPORT,M_PGOPT,M_PGTTY,M_DBNAME) \ + PQsetdbLogin(M_PGHOST, M_PGPORT, M_PGOPT, M_PGTTY, M_DBNAME, NULL, NULL) + +/* close the current connection and free the PGconn data structure */ +extern void PQfinish(PGconn *conn); + +/* get info about connection options known to PQconnectdb */ +extern PQconninfoOption *PQconndefaults(void); + +/* free the data structure returned by PQconndefaults() */ +extern void PQconninfoFree(PQconninfoOption *connOptions); + +/* + * close the current connection and restablish a new one with the same + * parameters + */ +/* Asynchronous (non-blocking) */ +extern int PQresetStart(PGconn *conn); +extern PostgresPollingStatusType PQresetPoll(PGconn *conn); + +/* Synchronous (blocking) */ +extern void PQreset(PGconn *conn); + +/* request a cancel structure */ +extern PGcancel *PQgetCancel(PGconn *conn); + +/* free a cancel structure */ +extern void PQfreeCancel(PGcancel *cancel); + +/* issue a cancel request */ +extern int PQcancel(PGcancel *cancel, char *errbuf, int errbufsize); + +/* backwards compatible version of PQcancel; not thread-safe */ +extern int PQrequestCancel(PGconn *conn); + +/* Accessor functions for PGconn objects */ +extern char *PQdb(const PGconn *conn); +extern char *PQuser(const PGconn *conn); +extern char *PQpass(const PGconn *conn); +extern char *PQhost(const PGconn *conn); +extern char *PQport(const PGconn *conn); +extern char *PQtty(const PGconn *conn); +extern char *PQoptions(const PGconn *conn); +extern ConnStatusType PQstatus(const PGconn *conn); +extern PGTransactionStatusType PQtransactionStatus(const PGconn *conn); +extern const char *PQparameterStatus(const PGconn *conn, + const char *paramName); +extern int PQprotocolVersion(const PGconn *conn); +extern int PQserverVersion(const PGconn *conn); +extern char *PQerrorMessage(const PGconn *conn); +extern int PQsocket(const PGconn *conn); +extern int PQbackendPID(const PGconn *conn); +extern int PQconnectionNeedsPassword(const PGconn *conn); +extern int PQconnectionUsedPassword(const PGconn *conn); +extern int PQclientEncoding(const PGconn *conn); +extern int PQsetClientEncoding(PGconn *conn, const char *encoding); + +/* Get the OpenSSL structure associated with a connection. Returns NULL for + * unencrypted connections or if any other TLS library is in use. */ +extern void *PQgetssl(PGconn *conn); + +/* Tell libpq whether it needs to initialize OpenSSL */ +extern void PQinitSSL(int do_init); + +/* Set verbosity for PQerrorMessage and PQresultErrorMessage */ +extern PGVerbosity PQsetErrorVerbosity(PGconn *conn, PGVerbosity verbosity); + +/* Enable/disable tracing */ +extern void PQtrace(PGconn *conn, FILE *debug_port); +extern void PQuntrace(PGconn *conn); + +/* Override default notice handling routines */ +extern PQnoticeReceiver PQsetNoticeReceiver(PGconn *conn, + PQnoticeReceiver proc, + void *arg); +extern PQnoticeProcessor PQsetNoticeProcessor(PGconn *conn, + PQnoticeProcessor proc, + void *arg); + +/* + * Used to set callback that prevents concurrent access to + * non-thread safe functions that libpq needs. + * The default implementation uses a libpq internal mutex. + * Only required for multithreaded apps that use kerberos + * both within their app and for postgresql connections. + */ +typedef void (*pgthreadlock_t) (int acquire); + +extern pgthreadlock_t PQregisterThreadLock(pgthreadlock_t newhandler); + +/* === in fe-exec.c === */ + +/* Simple synchronous query */ +extern PGresult *PQexec(PGconn *conn, const char *query); +extern PGresult *PQexecParams(PGconn *conn, + const char *command, + int nParams, + const Oid *paramTypes, + const char *const * paramValues, + const int *paramLengths, + const int *paramFormats, + int resultFormat); +extern PGresult *PQprepare(PGconn *conn, const char *stmtName, + const char *query, int nParams, + const Oid *paramTypes); +extern PGresult *PQexecPrepared(PGconn *conn, + const char *stmtName, + int nParams, + const char *const * paramValues, + const int *paramLengths, + const int *paramFormats, + int resultFormat); + +/* Interface for multiple-result or asynchronous queries */ +extern int PQsendQuery(PGconn *conn, const char *query); +extern int PQsendQueryParams(PGconn *conn, + const char *command, + int nParams, + const Oid *paramTypes, + const char *const * paramValues, + const int *paramLengths, + const int *paramFormats, + int resultFormat); +extern int PQsendPrepare(PGconn *conn, const char *stmtName, + const char *query, int nParams, + const Oid *paramTypes); +extern int PQsendQueryPrepared(PGconn *conn, + const char *stmtName, + int nParams, + const char *const * paramValues, + const int *paramLengths, + const int *paramFormats, + int resultFormat); +extern PGresult *PQgetResult(PGconn *conn); + +/* Routines for managing an asynchronous query */ +extern int PQisBusy(PGconn *conn); +extern int PQconsumeInput(PGconn *conn); + +/* LISTEN/NOTIFY support */ +extern PGnotify *PQnotifies(PGconn *conn); + +/* Routines for copy in/out */ +extern int PQputCopyData(PGconn *conn, const char *buffer, int nbytes); +extern int PQputCopyEnd(PGconn *conn, const char *errormsg); +extern int PQgetCopyData(PGconn *conn, char **buffer, int async); + +/* Deprecated routines for copy in/out */ +extern int PQgetline(PGconn *conn, char *string, int length); +extern int PQputline(PGconn *conn, const char *string); +extern int PQgetlineAsync(PGconn *conn, char *buffer, int bufsize); +extern int PQputnbytes(PGconn *conn, const char *buffer, int nbytes); +extern int PQendcopy(PGconn *conn); + +/* Set blocking/nonblocking connection to the backend */ +extern int PQsetnonblocking(PGconn *conn, int arg); +extern int PQisnonblocking(const PGconn *conn); +extern int PQisthreadsafe(void); + +/* Force the write buffer to be written (or at least try) */ +extern int PQflush(PGconn *conn); + +/* + * "Fast path" interface --- not really recommended for application + * use + */ +extern PGresult *PQfn(PGconn *conn, + int fnid, + int *result_buf, + int *result_len, + int result_is_int, + const PQArgBlock *args, + int nargs); + +/* Accessor functions for PGresult objects */ +extern ExecStatusType PQresultStatus(const PGresult *res); +extern char *PQresStatus(ExecStatusType status); +extern char *PQresultErrorMessage(const PGresult *res); +extern char *PQresultErrorField(const PGresult *res, int fieldcode); +extern int PQntuples(const PGresult *res); +extern int PQnfields(const PGresult *res); +extern int PQbinaryTuples(const PGresult *res); +extern char *PQfname(const PGresult *res, int field_num); +extern int PQfnumber(const PGresult *res, const char *field_name); +extern Oid PQftable(const PGresult *res, int field_num); +extern int PQftablecol(const PGresult *res, int field_num); +extern int PQfformat(const PGresult *res, int field_num); +extern Oid PQftype(const PGresult *res, int field_num); +extern int PQfsize(const PGresult *res, int field_num); +extern int PQfmod(const PGresult *res, int field_num); +extern char *PQcmdStatus(PGresult *res); +extern char *PQoidStatus(const PGresult *res); /* old and ugly */ +extern Oid PQoidValue(const PGresult *res); /* new and improved */ +extern char *PQcmdTuples(PGresult *res); +extern char *PQgetvalue(const PGresult *res, int tup_num, int field_num); +extern int PQgetlength(const PGresult *res, int tup_num, int field_num); +extern int PQgetisnull(const PGresult *res, int tup_num, int field_num); +extern int PQnparams(const PGresult *res); +extern Oid PQparamtype(const PGresult *res, int param_num); + +/* Describe prepared statements and portals */ +extern PGresult *PQdescribePrepared(PGconn *conn, const char *stmt); +extern PGresult *PQdescribePortal(PGconn *conn, const char *portal); +extern int PQsendDescribePrepared(PGconn *conn, const char *stmt); +extern int PQsendDescribePortal(PGconn *conn, const char *portal); + +/* Delete a PGresult */ +extern void PQclear(PGresult *res); + +/* For freeing other alloc'd results, such as PGnotify structs */ +extern void PQfreemem(void *ptr); + +/* Exists for backward compatibility. bjm 2003-03-24 */ +#define PQfreeNotify(ptr) PQfreemem(ptr) + +/* Error when no password was given. */ +/* Note: depending on this is deprecated; use PQconnectionNeedsPassword(). */ +#define PQnoPasswordSupplied "fe_sendauth: no password supplied\n" + +/* + * Make an empty PGresult with given status (some apps find this + * useful). If conn is not NULL and status indicates an error, the + * conn's errorMessage is copied. + */ +extern PGresult *PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status); + + +/* Quoting strings before inclusion in queries. */ +extern size_t PQescapeStringConn(PGconn *conn, + char *to, const char *from, size_t length, + int *error); +extern unsigned char *PQescapeByteaConn(PGconn *conn, + const unsigned char *from, size_t from_length, + size_t *to_length); +extern unsigned char *PQunescapeBytea(const unsigned char *strtext, + size_t *retbuflen); + +/* These forms are deprecated! */ +extern size_t PQescapeString(char *to, const char *from, size_t length); +extern unsigned char *PQescapeBytea(const unsigned char *from, size_t from_length, + size_t *to_length); + + + +/* === in fe-print.c === */ + +extern void +PQprint(FILE *fout, /* output stream */ + const PGresult *res, + const PQprintOpt *ps); /* option structure */ + +/* + * really old printing routines + */ +extern void +PQdisplayTuples(const PGresult *res, + FILE *fp, /* where to send the output */ + int fillAlign, /* pad the fields with spaces */ + const char *fieldSep, /* field separator */ + int printHeader, /* display headers? */ + int quiet); + +extern void +PQprintTuples(const PGresult *res, + FILE *fout, /* output stream */ + int printAttName, /* print attribute names */ + int terseOutput, /* delimiter bars */ + int width); /* width of column, if 0, use variable width */ + + +/* === in fe-lobj.c === */ + +/* Large-object access routines */ +extern int lo_open(PGconn *conn, Oid lobjId, int mode); +extern int lo_close(PGconn *conn, int fd); +extern int lo_read(PGconn *conn, int fd, char *buf, size_t len); +extern int lo_write(PGconn *conn, int fd, const char *buf, size_t len); +extern int lo_lseek(PGconn *conn, int fd, int offset, int whence); +extern Oid lo_creat(PGconn *conn, int mode); +extern Oid lo_create(PGconn *conn, Oid lobjId); +extern int lo_tell(PGconn *conn, int fd); +extern int lo_truncate(PGconn *conn, int fd, size_t len); +extern int lo_unlink(PGconn *conn, Oid lobjId); +extern Oid lo_import(PGconn *conn, const char *filename); +extern int lo_export(PGconn *conn, Oid lobjId, const char *filename); + +/* === in fe-misc.c === */ + +/* Determine length of multibyte encoded char at *s */ +extern int PQmblen(const char *s, int encoding); + +/* Determine display length of multibyte encoded char at *s */ +extern int PQdsplen(const char *s, int encoding); + +/* Get encoding id from environment variable PGCLIENTENCODING */ +extern int PQenv2encoding(void); + +/* === in fe-auth.c === */ + +extern char *PQencryptPassword(const char *passwd, const char *user); + +/* === in encnames.c === */ + +extern int pg_char_to_encoding(const char *name); +extern const char *pg_encoding_to_char(int encoding); +extern int pg_valid_server_encoding_id(int encoding); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBPQ_FE_H */ diff --git a/dep/include/postgre/pg_type.h b/dep/include/postgre/pg_type.h new file mode 100644 index 00000000000..823656cb1ca --- /dev/null +++ b/dep/include/postgre/pg_type.h @@ -0,0 +1,73 @@ +/*------------------------------------------------------------------------- + * + * pg_type.h + * definition of the system "type" relation (pg_type) + * along with the relation's initial contents. + * + * + * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/pg_type.h,v 1.8 2008/01/01 19:45:59 momjian Exp $ + * + * NOTES + * the genbki.sh script reads this file and generates .bki + * information from the DATA() statements. + * + *------------------------------------------------------------------------- + */ +#ifndef PG_TYPE_H +#define PG_TYPE_H + +/* ---------------- + * initial contents of pg_type + * ---------------- + */ + +/* keep the following ordered by OID so that later changes can be made easier*/ + +/* OIDS 1 - 99 */ +#define BOOLOID 16 +#define BYTEAOID 17 +#define CHAROID 18 +#define NAMEOID 19 +#define INT8OID 20 +#define INT2OID 21 +#define INT2VECTOROID 22 +#define INT4OID 23 +#define REGPROCOID 24 +#define TEXTOID 25 +#define OIDOID 26 +#define TIDOID 27 +#define XIDOID 28 +#define CIDOID 29 +#define OIDVECTOROID 30 +#define POINTOID 600 +#define LSEGOID 601 +#define PATHOID 602 +#define BOXOID 603 +#define POLYGONOID 604 +#define LINEOID 628 +#define FLOAT4OID 700 +#define FLOAT8OID 701 +#define ABSTIMEOID 702 +#define RELTIMEOID 703 +#define TINTERVALOID 704 +#define UNKNOWNOID 705 +#define CIRCLEOID 718 +#define CASHOID 790 +#define INETOID 869 +#define CIDROID 650 +#define BPCHAROID 1042 +#define VARCHAROID 1043 +#define DATEOID 1082 +#define TIMEOID 1083 +#define TIMESTAMPOID 1114 +#define TIMESTAMPTZOID 1184 +#define INTERVALOID 1186 +#define TIMETZOID 1266 +#define ZPBITOID 1560 +#define VARBITOID 1562 +#define NUMERICOID 1700 + +#endif /* PG_TYPE_H */ diff --git a/dep/include/postgre/postgres_ext.h b/dep/include/postgre/postgres_ext.h new file mode 100644 index 00000000000..51a18b7dcc3 --- /dev/null +++ b/dep/include/postgre/postgres_ext.h @@ -0,0 +1,59 @@ +/*------------------------------------------------------------------------- + * + * postgres_ext.h + * + * This file contains declarations of things that are visible everywhere + * in PostgreSQL *and* are visible to clients of frontend interface libraries. + * For example, the Oid type is part of the API of libpq and other libraries. + * + * Declarations which are specific to a particular interface should + * go in the header file for that interface (such as libpq-fe.h). This + * file is only for fundamental Postgres declarations. + * + * User-written C functions don't count as "external to Postgres." + * Those function much as local modifications to the backend itself, and + * use header files that are otherwise internal to Postgres to interface + * with the backend. + * + * $PostgreSQL: pgsql/src/include/postgres_ext.h,v 1.17 2007/02/06 09:16:08 petere Exp $ + * + *------------------------------------------------------------------------- + */ + +#ifndef POSTGRES_EXT_H +#define POSTGRES_EXT_H + +/* + * Object ID is a fundamental type in Postgres. + */ +typedef unsigned int Oid; + +#ifdef __cplusplus +#define InvalidOid (Oid(0)) +#else +#define InvalidOid ((Oid) 0) +#endif + +#define OID_MAX UINT_MAX +/* you will need to include to use the above #define */ + + +/* + * Identifiers of error message fields. Kept here to keep common + * between frontend and backend, and also to export them to libpq + * applications. + */ +#define PG_DIAG_SEVERITY 'S' +#define PG_DIAG_SQLSTATE 'C' +#define PG_DIAG_MESSAGE_PRIMARY 'M' +#define PG_DIAG_MESSAGE_DETAIL 'D' +#define PG_DIAG_MESSAGE_HINT 'H' +#define PG_DIAG_STATEMENT_POSITION 'P' +#define PG_DIAG_INTERNAL_POSITION 'p' +#define PG_DIAG_INTERNAL_QUERY 'q' +#define PG_DIAG_CONTEXT 'W' +#define PG_DIAG_SOURCE_FILE 'F' +#define PG_DIAG_SOURCE_LINE 'L' +#define PG_DIAG_SOURCE_FUNCTION 'R' + +#endif diff --git a/dep/include/sockets/Base64.h b/dep/include/sockets/Base64.h new file mode 100644 index 00000000000..a632bbec730 --- /dev/null +++ b/dep/include/sockets/Base64.h @@ -0,0 +1,77 @@ +/** \file Base64.h + ** \date 2004-02-13 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2004-2007 Anders Hedstrom + +This library is made available under the terms of the GNU GPL. + +If you would like to use this library in a closed-source application, +a separate license agreement is available. For information about +the closed-source license agreement for the C++ sockets library, +please visit http://www.alhem.net/Sockets/license.html and/or +email license@alhem.net. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef _SOCKETS_Base64_H +#define _SOCKETS_Base64_H + +#include "sockets-config.h" +#ifdef _MSC_VER +#pragma warning(disable:4514) +#endif + +#include +#include + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + +/** \defgroup util Utilities */ + +/** Base64 encode/decode. + \ingroup util */ +class Base64 +{ +public: + Base64(); + + void encode(FILE *, std::string& , bool add_crlf = true); + void encode(const std::string&, std::string& , bool add_crlf = true); + void encode(const char *, size_t, std::string& , bool add_crlf = true); + void encode(const unsigned char *, size_t, std::string& , bool add_crlf = true); + + void decode(const std::string&, std::string& ); + void decode(const std::string&, unsigned char *, size_t&); + + size_t decode_length(const std::string& ); + +private: + Base64(const Base64& ) {} + Base64& operator=(const Base64& ) { return *this; } +static const char *bstr; +static const char rstr[128]; +}; + + +#ifdef SOCKETS_NAMESPACE +} +#endif + +#endif // _SOCKETS_Base64_H + diff --git a/dep/include/sockets/Exception.h b/dep/include/sockets/Exception.h new file mode 100644 index 00000000000..81ba7373d0d --- /dev/null +++ b/dep/include/sockets/Exception.h @@ -0,0 +1,58 @@ +/** + ** \file Exception.h + ** \date 2007-09-28 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2007 Anders Hedstrom + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef _Sockets_Exception_H +#define _Sockets_Exception_H + +#include + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + + + +class Exception +{ +public: + Exception(const std::string& description); + virtual ~Exception() {} + + virtual const std::string ToString() const; + + Exception(const Exception& ) {} // copy constructor + + Exception& operator=(const Exception& ) { return *this; } // assignment operator + +private: + std::string m_description; + +}; + + + +#ifdef SOCKETS_NAMESPACE +} // namespace SOCKETS_NAMESPACE { +#endif + +#endif // _Sockets_Exception_H + diff --git a/dep/include/sockets/File.h b/dep/include/sockets/File.h new file mode 100644 index 00000000000..58a1b71bb85 --- /dev/null +++ b/dep/include/sockets/File.h @@ -0,0 +1,84 @@ +/** \file File.h + ** \date 2005-04-25 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2004-2007 Anders Hedstrom + +This library is made available under the terms of the GNU GPL. + +If you would like to use this library in a closed-source application, +a separate license agreement is available. For information about +the closed-source license agreement for the C++ sockets library, +please visit http://www.alhem.net/Sockets/license.html and/or +email license@alhem.net. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef _SOCKETS_File_H +#define _SOCKETS_File_H + +#include "sockets-config.h" +#include "IFile.h" +#include + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + + +/** IFile implementation of a disk file. + \ingroup file */ +class File : public IFile +{ +public: + File(); + ~File(); + + bool fopen(const std::string&, const std::string&); + void fclose(); + + size_t fread(char *, size_t, size_t) const; + size_t fwrite(const char *, size_t, size_t); + + char *fgets(char *, int) const; + void fprintf(const char *format, ...); + + off_t size() const; + bool eof() const; + + void reset_read() const; + void reset_write(); + +private: + File(const File& ) {} // copy constructor + File& operator=(const File& ) { return *this; } // assignment operator + + std::string m_path; + std::string m_mode; + FILE *m_fil; + mutable long m_rptr; + long m_wptr; +}; + + + + +#ifdef SOCKETS_NAMESPACE +} +#endif + +#endif // _SOCKETS_File_H + diff --git a/dep/include/sockets/IFile.h b/dep/include/sockets/IFile.h new file mode 100644 index 00000000000..aecc50f5997 --- /dev/null +++ b/dep/include/sockets/IFile.h @@ -0,0 +1,71 @@ +/** \file IFile.h + ** \date 2005-04-25 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2004-2007 Anders Hedstrom + +This library is made available under the terms of the GNU GPL. + +If you would like to use this library in a closed-source application, +a separate license agreement is available. For information about +the closed-source license agreement for the C++ sockets library, +please visit http://www.alhem.net/Sockets/license.html and/or +email license@alhem.net. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef _SOCKETS_IFile_H +#define _SOCKETS_IFile_H + +#include "sockets-config.h" +#include + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + +/** \defgroup file File handling */ +/** Pure virtual file I/O interface. + \ingroup file */ +class IFile +{ +public: + virtual ~IFile() {} + + virtual bool fopen(const std::string&, const std::string&) = 0; + virtual void fclose() = 0; + + virtual size_t fread(char *, size_t, size_t) const = 0; + virtual size_t fwrite(const char *, size_t, size_t) = 0; + + virtual char *fgets(char *, int) const = 0; + virtual void fprintf(const char *format, ...) = 0; + + virtual off_t size() const = 0; + virtual bool eof() const = 0; + + virtual void reset_read() const = 0; + virtual void reset_write() = 0; + +}; + + +#ifdef SOCKETS_NAMESPACE +} +#endif + +#endif // _SOCKETS_IFile_H + diff --git a/dep/include/sockets/ISocketHandler.h b/dep/include/sockets/ISocketHandler.h new file mode 100644 index 00000000000..2667e2d22ed --- /dev/null +++ b/dep/include/sockets/ISocketHandler.h @@ -0,0 +1,232 @@ +/** \file ISocketHandler.h + ** \date 2004-02-13 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2004-2007 Anders Hedstrom + +This library is made available under the terms of the GNU GPL. + +If you would like to use this library in a closed-source application, +a separate license agreement is available. For information about +the closed-source license agreement for the C++ sockets library, +please visit http://www.alhem.net/Sockets/license.html and/or +email license@alhem.net. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef _SOCKETS_ISocketHandler_H +#define _SOCKETS_ISocketHandler_H +#include "sockets-config.h" + +#include + +#include "socket_include.h" +#include "Socket.h" +#include "StdLog.h" + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + +typedef enum { + LIST_CALLONCONNECT = 0, +#ifdef ENABLE_DETACH + LIST_DETACH, +#endif + LIST_TIMEOUT, + LIST_RETRY, + LIST_CLOSE +} list_t; + +class SocketAddress; +class Mutex; + + +/** Socket container class, event generator. + \ingroup basic */ +class ISocketHandler +{ + friend class Socket; + +public: + /** Connection pool class for internal use by the ISocketHandler. + \ingroup internal */ +#ifdef ENABLE_POOL + class PoolSocket : public Socket + { + public: + PoolSocket(ISocketHandler& h,Socket *src) : Socket(h) { + CopyConnection( src ); + SetIsClient(); + } + + void OnRead() { + Handler().LogError(this, "OnRead", 0, "data on hibernating socket", LOG_LEVEL_FATAL); + SetCloseAndDelete(); + } + void OnOptions(int,int,int,SOCKET) {} + + }; +#endif + +public: + virtual ~ISocketHandler() {} + + /** Get mutex reference for threadsafe operations. */ + virtual Mutex& GetMutex() const = 0; + + /** Register StdLog object for error callback. + \param log Pointer to log class */ + virtual void RegStdLog(StdLog *log) = 0; + + /** Log error to log class for print out / storage. */ + virtual void LogError(Socket *p,const std::string& user_text,int err,const std::string& sys_err,loglevel_t t = LOG_LEVEL_WARNING) = 0; + + // ------------------------------------------------------------------------- + // Socket stuff + // ------------------------------------------------------------------------- + /** Add socket instance to socket map. Removal is always automatic. */ + virtual void Add(Socket *) = 0; +private: + /** Remove socket from socket map, used by Socket class. */ + virtual void Remove(Socket *) = 0; +public: + /** Get status of read/write/exception file descriptor set for a socket. */ + virtual void Get(SOCKET s,bool& r,bool& w,bool& e) = 0; + /** Set read/write/exception file descriptor sets (fd_set). */ + virtual void Set(SOCKET s,bool bRead,bool bWrite,bool bException = true) = 0; + + /** Wait for events, generate callbacks. */ + virtual int Select(long sec,long usec) = 0; + /** This method will not return until an event has been detected. */ + virtual int Select() = 0; + /** Wait for events, generate callbacks. */ + virtual int Select(struct timeval *tsel) = 0; + + /** Check that a socket really is handled by this socket handler. */ + virtual bool Valid(Socket *) = 0; + /** Return number of sockets handled by this handler. */ + virtual size_t GetCount() = 0; + + /** Override and return false to deny all incoming connections. + \param p ListenSocket class pointer (use GetPort to identify which one) */ + virtual bool OkToAccept(Socket *p) = 0; + + /** Called by Socket when a socket changes state. */ + virtual void AddList(SOCKET s,list_t which_one,bool add) = 0; + + // ------------------------------------------------------------------------- + // Connection pool + // ------------------------------------------------------------------------- +#ifdef ENABLE_POOL + /** Find available open connection (used by connection pool). */ + virtual ISocketHandler::PoolSocket *FindConnection(int type,const std::string& protocol,SocketAddress&) = 0; + /** Enable connection pool (by default disabled). */ + virtual void EnablePool(bool = true) = 0; + /** Check pool status. + \return true if connection pool is enabled */ + virtual bool PoolEnabled() = 0; +#endif // ENABLE_POOL + + // ------------------------------------------------------------------------- + // Socks4 + // ------------------------------------------------------------------------- +#ifdef ENABLE_SOCKS4 + /** Set socks4 server ip that all new tcp sockets should use. */ + virtual void SetSocks4Host(ipaddr_t) = 0; + /** Set socks4 server hostname that all new tcp sockets should use. */ + virtual void SetSocks4Host(const std::string& ) = 0; + /** Set socks4 server port number that all new tcp sockets should use. */ + virtual void SetSocks4Port(port_t) = 0; + /** Set optional socks4 userid. */ + virtual void SetSocks4Userid(const std::string& ) = 0; + /** If connection to socks4 server fails, immediately try direct connection to final host. */ + virtual void SetSocks4TryDirect(bool = true) = 0; + /** Get socks4 server ip. + \return socks4 server ip */ + virtual ipaddr_t GetSocks4Host() = 0; + /** Get socks4 port number. + \return socks4 port number */ + virtual port_t GetSocks4Port() = 0; + /** Get socks4 userid (optional). + \return socks4 userid */ + virtual const std::string& GetSocks4Userid() = 0; + /** Check status of socks4 try direct flag. + \return true if direct connection should be tried if connection to socks4 server fails */ + virtual bool Socks4TryDirect() = 0; +#endif // ENABLE_SOCKS4 + + // ------------------------------------------------------------------------- + // DNS resolve server + // ------------------------------------------------------------------------- +#ifdef ENABLE_RESOLVER + /** Enable asynchronous DNS. + \param port Listen port of asynchronous dns server */ + virtual void EnableResolver(port_t = 16667) = 0; + /** Check resolver status. + \return true if resolver is enabled */ + virtual bool ResolverEnabled() = 0; + /** Queue a dns request. + \param host Hostname to be resolved + \param port Port number will be echoed in Socket::OnResolved callback */ + virtual int Resolve(Socket *,const std::string& host,port_t port) = 0; +#ifdef ENABLE_IPV6 + virtual int Resolve6(Socket *,const std::string& host,port_t port) = 0; +#endif + /** Do a reverse dns lookup. */ + virtual int Resolve(Socket *,ipaddr_t a) = 0; +#ifdef ENABLE_IPV6 + virtual int Resolve(Socket *,in6_addr& a) = 0; +#endif + /** Get listen port of asynchronous dns server. */ + virtual port_t GetResolverPort() = 0; + /** Resolver thread ready for queries. */ + virtual bool ResolverReady() = 0; + /** Returns true if socket waiting for a resolve event. */ + virtual bool Resolving(Socket *) = 0; +#endif // ENABLE_RESOLVER + +#ifdef ENABLE_TRIGGERS + /** Fetch unique trigger id. */ + virtual int TriggerID(Socket *src) = 0; + /** Subscribe socket to trigger id. */ + virtual bool Subscribe(int id, Socket *dst) = 0; + /** Unsubscribe socket from trigger id. */ + virtual bool Unsubscribe(int id, Socket *dst) = 0; + /** Execute OnTrigger for subscribed sockets. + \param id Trigger ID + \param data Data passed from source to destination + \param erase Empty trigger id source and destination maps if 'true', + Leave them in place if 'false' - if a trigger should be called many times */ + virtual void Trigger(int id, Socket::TriggerData& data, bool erase = true) = 0; +#endif // ENABLE_TRIGGERS + +#ifdef ENABLE_DETACH + /** Indicates that the handler runs under SocketThread. */ + virtual void SetSlave(bool x = true) = 0; + /** Indicates that the handler runs under SocketThread. */ + virtual bool IsSlave() = 0; +#endif // ENABLE_DETACH + +}; + + +#ifdef SOCKETS_NAMESPACE +} +#endif + +#endif // _SOCKETS_ISocketHandler_H + diff --git a/dep/include/sockets/Ipv4Address.h b/dep/include/sockets/Ipv4Address.h new file mode 100644 index 00000000000..b58c2ce9425 --- /dev/null +++ b/dep/include/sockets/Ipv4Address.h @@ -0,0 +1,98 @@ +/** + ** \file Ipv4Address.h + ** \date 2006-09-21 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2007 Anders Hedstrom + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef _SOCKETS_Ipv4Address_H +#define _SOCKETS_Ipv4Address_H + +#include "sockets-config.h" +#include "SocketAddress.h" + + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + + +/* Ipv4 address implementation. + \ingroup basic */ +class Ipv4Address : public SocketAddress +{ +public: + /** Create empty Ipv4 address structure. + \param port Port number */ + Ipv4Address(port_t port = 0); + /** Create Ipv4 address structure. + \param a Socket address in network byte order (as returned by Utility::u2ip) + \param port Port number in host byte order */ + Ipv4Address(ipaddr_t a,port_t port); + /** Create Ipv4 address structure. + \param a Socket address in network byte order + \param port Port number in host byte order */ + Ipv4Address(struct in_addr& a,port_t port); + /** Create Ipv4 address structure. + \param host Hostname to be resolved + \param port Port number in host byte order */ + Ipv4Address(const std::string& host,port_t port); + Ipv4Address(struct sockaddr_in&); + ~Ipv4Address(); + + // SocketAddress implementation + + operator struct sockaddr *(); + operator socklen_t(); + bool operator==(SocketAddress&); + + void SetPort(port_t port); + port_t GetPort(); + + void SetAddress(struct sockaddr *sa); + int GetFamily(); + + bool IsValid(); + std::auto_ptr GetCopy(); + + /** Convert address struct to text. */ + std::string Convert(bool include_port = false); + std::string Reverse(); + + /** Resolve hostname. */ +static bool Resolve(const std::string& hostname,struct in_addr& a); + /** Reverse resolve (IP to hostname). */ +static bool Reverse(struct in_addr& a,std::string& name); + /** Convert address struct to text. */ +static std::string Convert(struct in_addr& a); + +private: + Ipv4Address(const Ipv4Address& ) {} // copy constructor + Ipv4Address& operator=(const Ipv4Address& ) { return *this; } // assignment operator + struct sockaddr_in m_addr; + bool m_valid; +}; + + + + +#ifdef SOCKETS_NAMESPACE +} // namespace SOCKETS_NAMESPACE { +#endif +#endif // _SOCKETS_Ipv4Address_H + diff --git a/dep/include/sockets/Ipv6Address.h b/dep/include/sockets/Ipv6Address.h new file mode 100644 index 00000000000..a0711417956 --- /dev/null +++ b/dep/include/sockets/Ipv6Address.h @@ -0,0 +1,107 @@ +/** + ** \file Ipv6Address.h + ** \date 2006-09-21 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2007 Anders Hedstrom + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef _SOCKETS_Ipv6Address_H +#define _SOCKETS_Ipv6Address_H +#include "sockets-config.h" +#ifdef ENABLE_IPV6 + +#include "SocketAddress.h" +#ifdef IPPROTO_IPV6 +#if defined( _WIN32) && !defined(__CYGWIN__) +typedef unsigned __int32 uint32_t; +#endif + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + + +/** Ipv6 address implementation. + \ingroup basic */ +class Ipv6Address : public SocketAddress +{ +public: + /** Create empty Ipv6 address structure. + \param port Port number */ + Ipv6Address(port_t port = 0); + /** Create Ipv6 address structure. + \param a Socket address in network byte order + \param port Port number in host byte order */ + Ipv6Address(struct in6_addr& a,port_t port); + /** Create Ipv6 address structure. + \param host Hostname to be resolved + \param port Port number in host byte order */ + Ipv6Address(const std::string& host,port_t port); + Ipv6Address(struct sockaddr_in6&); + ~Ipv6Address(); + + // SocketAddress implementation + + operator struct sockaddr *(); + operator socklen_t(); + bool operator==(SocketAddress&); + + void SetPort(port_t port); + port_t GetPort(); + + void SetAddress(struct sockaddr *sa); + int GetFamily(); + + bool IsValid(); + std::auto_ptr GetCopy(); + + /** Convert address struct to text. */ + std::string Convert(bool include_port = false); + std::string Reverse(); + + /** Resolve hostname. */ +static bool Resolve(const std::string& hostname,struct in6_addr& a); + /** Reverse resolve (IP to hostname). */ +static bool Reverse(struct in6_addr& a,std::string& name); + /** Convert address struct to text. */ +static std::string Convert(struct in6_addr& a,bool mixed = false); + + void SetFlowinfo(uint32_t); + uint32_t GetFlowinfo(); +#ifndef _WIN32 + void SetScopeId(uint32_t); + uint32_t GetScopeId(); +#endif + +private: + Ipv6Address(const Ipv6Address& ) {} // copy constructor + Ipv6Address& operator=(const Ipv6Address& ) { return *this; } // assignment operator + struct sockaddr_in6 m_addr; + bool m_valid; +}; + + + + +#ifdef SOCKETS_NAMESPACE +} // namespace SOCKETS_NAMESPACE { +#endif +#endif // IPPROTO_IPV6 +#endif // ENABLE_IPV6 +#endif // _SOCKETS_Ipv6Address_H + diff --git a/dep/include/sockets/ListenSocket.h b/dep/include/sockets/ListenSocket.h new file mode 100644 index 00000000000..f4edc37d6c3 --- /dev/null +++ b/dep/include/sockets/ListenSocket.h @@ -0,0 +1,420 @@ +/** \file ListenSocket.h + ** \date 2004-02-13 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2004-2007 Anders Hedstrom + +This library is made available under the terms of the GNU GPL. + +If you would like to use this library in a closed-source application, +a separate license agreement is available. For information about +the closed-source license agreement for the C++ sockets library, +please visit http://www.alhem.net/Sockets/license.html and/or +email license@alhem.net. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef _SOCKETS_ListenSocket_H +#define _SOCKETS_ListenSocket_H +#include "sockets-config.h" + +#ifdef _WIN32 +#include +#else +#include +#endif + +#include "ISocketHandler.h" +#include "Socket.h" +#include "Utility.h" +#include "SctpSocket.h" +#include "Ipv4Address.h" +#include "Ipv6Address.h" +#ifdef ENABLE_EXCEPTIONS +#include "Exception.h" +#endif + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + + +/** Binds incoming port number to new Socket class X. + \ingroup basic */ +template +class ListenSocket : public Socket +{ +public: + /** Constructor. + \param h ISocketHandler reference + \param use_creator Optional use of creator (default true) */ + ListenSocket(ISocketHandler& h,bool use_creator = true) : Socket(h), m_depth(0), m_creator(NULL) + ,m_bHasCreate(false) + { + if (use_creator) + { + m_creator = new X(h); + Socket *tmp = m_creator -> Create(); + if (tmp && dynamic_cast(tmp)) + { + m_bHasCreate = true; + } + if (tmp) + { + delete tmp; + } + } + } + ~ListenSocket() { + if (m_creator) + { + delete m_creator; + } + } + + /** Close file descriptor. */ + int Close() { + if (GetSocket() != INVALID_SOCKET) + { + closesocket(GetSocket()); + } + return 0; + } + + /** Bind and listen to any interface. + \param port Port (0 is random) + \param depth Listen queue depth */ + int Bind(port_t port,int depth = 20) { +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + if (IsIpv6()) + { + Ipv6Address ad(port); + return Bind(ad, depth); + } + else +#endif +#endif + { + Ipv4Address ad(port); + return Bind(ad, depth); + } + } + + int Bind(SocketAddress& ad,int depth) { +#ifdef USE_SCTP + if (dynamic_cast(m_creator)) + { + return Bind(ad, "sctp", depth); + } +#endif + return Bind(ad, "tcp", depth); + } + + /** Bind and listen to any interface, with optional protocol. + \param port Port (0 is random) + \param protocol Network protocol + \param depth Listen queue depth */ + int Bind(port_t port,const std::string& protocol,int depth = 20) { +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + if (IsIpv6()) + { + Ipv6Address ad(port); + return Bind(ad, protocol, depth); + } + else +#endif +#endif + { + Ipv4Address ad(port); + return Bind(ad, protocol, depth); + } + } + + /** Bind and listen to specific interface. + \param intf Interface hostname + \param port Port (0 is random) + \param depth Listen queue depth */ + int Bind(const std::string& intf,port_t port,int depth = 20) { +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + if (IsIpv6()) + { + Ipv6Address ad(intf, port); + if (ad.IsValid()) + { + return Bind(ad, depth); + } + Handler().LogError(this, "Bind", 0, "name resolution of interface name failed", LOG_LEVEL_FATAL); + return -1; + } + else +#endif +#endif + { + Ipv4Address ad(intf, port); + if (ad.IsValid()) + { + return Bind(ad, depth); + } + Handler().LogError(this, "Bind", 0, "name resolution of interface name failed", LOG_LEVEL_FATAL); + return -1; + } + } + + /** Bind and listen to specific interface. + \param intf Interface hostname + \param port Port (0 is random) + \param protocol Network protocol + \param depth Listen queue depth */ + int Bind(const std::string& intf,port_t port,const std::string& protocol,int depth = 20) { +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + if (IsIpv6()) + { + Ipv6Address ad(intf, port); + if (ad.IsValid()) + { + return Bind(ad, protocol, depth); + } + Handler().LogError(this, "Bind", 0, "name resolution of interface name failed", LOG_LEVEL_FATAL); + return -1; + } + else +#endif +#endif + { + Ipv4Address ad(intf, port); + if (ad.IsValid()) + { + return Bind(ad, protocol, depth); + } + Handler().LogError(this, "Bind", 0, "name resolution of interface name failed", LOG_LEVEL_FATAL); + return -1; + } + } + + /** Bind and listen to ipv4 interface. + \param a Ipv4 interface address + \param port Port (0 is random) + \param depth Listen queue depth */ + int Bind(ipaddr_t a,port_t port,int depth = 20) { + Ipv4Address ad(a, port); +#ifdef USE_SCTP + if (dynamic_cast(m_creator)) + { + return Bind(ad, "sctp", depth); + } +#endif + return Bind(ad, "tcp", depth); + } + /** Bind and listen to ipv4 interface. + \param a Ipv4 interface address + \param port Port (0 is random) + \param protocol Network protocol + \param depth Listen queue depth */ + int Bind(ipaddr_t a,port_t port,const std::string& protocol,int depth) { + Ipv4Address ad(a, port); + return Bind(ad, protocol, depth); + } + +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + /** Bind and listen to ipv6 interface. + \param a Ipv6 interface address + \param port Port (0 is random) + \param depth Listen queue depth */ + int Bind(in6_addr a,port_t port,int depth = 20) { + Ipv6Address ad(a, port); +#ifdef USE_SCTP + if (dynamic_cast(m_creator)) + { + return Bind(ad, "sctp", depth); + } +#endif + return Bind(ad, "tcp", depth); + } + /** Bind and listen to ipv6 interface. + \param a Ipv6 interface address + \param port Port (0 is random) + \param protocol Network protocol + \param depth Listen queue depth */ + int Bind(in6_addr a,port_t port,const std::string& protocol,int depth) { + Ipv6Address ad(a, port); + return Bind(ad, protocol, depth); + } +#endif +#endif + + /** Bind and listen to network interface. + \param ad Interface address + \param protocol Network protocol + \param depth Listen queue depth */ + int Bind(SocketAddress& ad,const std::string& protocol,int depth) { + SOCKET s; + if ( (s = CreateSocket(ad.GetFamily(), SOCK_STREAM, protocol)) == INVALID_SOCKET) + { + return -1; + } + if (bind(s, ad, ad) == -1) + { + Handler().LogError(this, "bind", Errno, StrError(Errno), LOG_LEVEL_FATAL); + closesocket(s); +#ifdef ENABLE_EXCEPTIONS + throw Exception("bind() failed for port " + Utility::l2string(ad.GetPort()) + ": " + StrError(Errno)); +#endif + return -1; + } + if (listen(s, depth) == -1) + { + Handler().LogError(this, "listen", Errno, StrError(Errno), LOG_LEVEL_FATAL); + closesocket(s); +#ifdef ENABLE_EXCEPTIONS + throw Exception("listen() failed for port " + Utility::l2string(ad.GetPort()) + ": " + StrError(Errno)); +#endif + return -1; + } + m_depth = depth; + Attach(s); + return 0; + } + + /** Return assigned port number. */ + port_t GetPort() + { + return GetSockPort(); + } + + /** Return listen queue depth. */ + int GetDepth() + { + return m_depth; + } + + /** OnRead on a ListenSocket receives an incoming connection. */ + void OnRead() + { + struct sockaddr sa; + socklen_t sa_len = sizeof(struct sockaddr); + SOCKET a_s = accept(GetSocket(), &sa, &sa_len); + + if (a_s == INVALID_SOCKET) + { + Handler().LogError(this, "accept", Errno, StrError(Errno), LOG_LEVEL_ERROR); + return; + } + if (!Handler().OkToAccept(this)) + { + Handler().LogError(this, "accept", -1, "Not OK to accept", LOG_LEVEL_WARNING); + closesocket(a_s); + return; + } + if (Handler().GetCount() >= FD_SETSIZE) + { + Handler().LogError(this, "accept", (int)Handler().GetCount(), "ISocketHandler fd_set limit reached", LOG_LEVEL_FATAL); + closesocket(a_s); + return; + } + Socket *tmp = m_bHasCreate ? m_creator -> Create() : new X(Handler()); +#ifdef ENABLE_IPV6 + tmp -> SetIpv6( IsIpv6() ); +#endif + tmp -> SetParent(this); + tmp -> Attach(a_s); + tmp -> SetNonblocking(true); + { +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + if (sa_len == sizeof(struct sockaddr_in6)) + { + struct sockaddr_in6 *p = (struct sockaddr_in6 *)&sa; + if (p -> sin6_family == AF_INET6) + { + Ipv6Address ad(p -> sin6_addr,ntohs(p -> sin6_port)); + ad.SetFlowinfo(p -> sin6_flowinfo); +#ifndef _WIN32 + ad.SetScopeId(p -> sin6_scope_id); +#endif + tmp -> SetRemoteAddress(ad); + } + } +#endif +#endif + if (sa_len == sizeof(struct sockaddr_in)) + { + struct sockaddr_in *p = (struct sockaddr_in *)&sa; + if (p -> sin_family == AF_INET) + { + Ipv4Address ad(p -> sin_addr,ntohs(p -> sin_port)); + tmp -> SetRemoteAddress(ad); + } + } + } + tmp -> SetConnected(true); + tmp -> Init(); + tmp -> SetDeleteByHandler(true); + Handler().Add(tmp); +#ifdef HAVE_OPENSSL + if (tmp -> IsSSL()) // SSL Enabled socket + { + // %! OnSSLAccept calls SSLNegotiate that can finish in this one call. + // %! If that happens and negotiation fails, the 'tmp' instance is + // %! still added to the list of active sockets in the sockethandler. + // %! See bugfix for this in SocketHandler::Select - don't Set rwx + // %! flags if CloseAndDelete() flag is true. + // %! An even better fugbix (see TcpSocket::OnSSLAccept) now avoids + // %! the Add problem altogether, so ignore the above. + // %! (OnSSLAccept does no longer call SSLNegotiate().) + tmp -> OnSSLAccept(); + } + else +#endif + { + tmp -> OnAccept(); + } + } + + /** Please don't use this method. + "accept()" is handled automatically in the OnRead() method. */ + virtual SOCKET Accept(SOCKET socket, struct sockaddr *saptr, socklen_t *lenptr) + { + return accept(socket, saptr, lenptr); + } + + bool HasCreator() { return m_bHasCreate; } + + void OnOptions(int,int,int,SOCKET) { + SetSoReuseaddr(true); + } + +protected: + ListenSocket(const ListenSocket& s) : Socket(s) {} +private: + ListenSocket& operator=(const ListenSocket& ) { return *this; } + int m_depth; + X *m_creator; + bool m_bHasCreate; +}; + + + +#ifdef SOCKETS_NAMESPACE +} +#endif + +#endif // _SOCKETS_ListenSocket_H + diff --git a/dep/include/sockets/Lock.h b/dep/include/sockets/Lock.h new file mode 100644 index 00000000000..71fdd5e733d --- /dev/null +++ b/dep/include/sockets/Lock.h @@ -0,0 +1,59 @@ +/** \file Lock.h + ** \date 2005-08-22 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2005,2007 Anders Hedstrom + +This library is made available under the terms of the GNU GPL. + +If you would like to use this library in a closed-source application, +a separate license agreement is available. For information about +the closed-source license agreement for the C++ sockets library, +please visit http://www.alhem.net/Sockets/license.html and/or +email license@alhem.net. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef _SOCKETS_Lock_H +#define _SOCKETS_Lock_H + +#include "sockets-config.h" +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + +class Mutex; + +/** Mutex encapsulation class. + \ingroup threading */ +class Lock +{ +public: + Lock(Mutex&); + ~Lock(); + +private: + Mutex& m_mutex; +}; + + + + +#ifdef SOCKETS_NAMESPACE +} +#endif +#endif // _SOCKETS_Lock_H + diff --git a/dep/include/sockets/Mutex.h b/dep/include/sockets/Mutex.h new file mode 100644 index 00000000000..1de27760a1c --- /dev/null +++ b/dep/include/sockets/Mutex.h @@ -0,0 +1,68 @@ +/** \file Mutex.h + ** \date 2004-10-30 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2004-2007 Anders Hedstrom + +This library is made available under the terms of the GNU GPL. + +If you would like to use this library in a closed-source application, +a separate license agreement is available. For information about +the closed-source license agreement for the C++ sockets library, +please visit http://www.alhem.net/Sockets/license.html and/or +email license@alhem.net. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef _SOCKETS_Mutex_H +#define _SOCKETS_Mutex_H + +#include "sockets-config.h" +#ifndef _WIN32 +#include +#else +#include +#endif + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + +/** Mutex container class, used by Lock. + \ingroup threading */ +class Mutex +{ + friend class Lock; +public: + Mutex(); + ~Mutex(); + + void Lock(); + void Unlock(); +private: +#ifdef _WIN32 + HANDLE m_mutex; +#else + pthread_mutex_t m_mutex; +#endif +}; + + +#ifdef SOCKETS_NAMESPACE +} +#endif +#endif // _SOCKETS_Mutex_H + diff --git a/dep/include/sockets/Parse.h b/dep/include/sockets/Parse.h new file mode 100644 index 00000000000..6961f3b1bc9 --- /dev/null +++ b/dep/include/sockets/Parse.h @@ -0,0 +1,101 @@ +/** \file Parse.h - parse a string + ** + ** Written: 1999-Feb-10 grymse@alhem.net + **/ + +/* +Copyright (C) 1999-2007 Anders Hedstrom + +This library is made available under the terms of the GNU GPL. + +If you would like to use this library in a closed-source application, +a separate license agreement is available. For information about +the closed-source license agreement for the C++ sockets library, +please visit http://www.alhem.net/Sockets/license.html and/or +email license@alhem.net. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _SOCKETS_Parse_H +#define _SOCKETS_Parse_H + +#include "sockets-config.h" +#ifdef _MSC_VER +#pragma warning(disable:4514) +#endif + +#include + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + + +/***************************************************/ +/* interface of class Parse */ + +/** Splits a string whatever way you want. + \ingroup util */ +class Parse +{ +public: + Parse(); + Parse(const std::string&); + Parse(const std::string&,const std::string&); + Parse(const std::string&,const std::string&,short); + ~Parse(); + short issplit(const char); + void getsplit(); + void getsplit(std::string&); + std::string getword(); + void getword(std::string&); + void getword(std::string&,std::string&,int); + std::string getrest(); + void getrest(std::string&); + long getvalue(); + void setbreak(const char); + int getwordlen(); + int getrestlen(); + void enablebreak(const char c) { + pa_enable = c; + } + void disablebreak(const char c) { + pa_disable = c; + } + void getline(); + void getline(std::string&); + size_t getptr() { return pa_the_ptr; } + void EnableQuote(bool b) { pa_quote = b; } + +private: + std::string pa_the_str; + std::string pa_splits; + std::string pa_ord; + size_t pa_the_ptr; + char pa_breakchar; + char pa_enable; + char pa_disable; + short pa_nospace; + bool pa_quote; +}; + + +#ifdef SOCKETS_NAMESPACE +} +#endif + +#endif // _SOCKETS_Parse_H + diff --git a/dep/include/sockets/ResolvServer.h b/dep/include/sockets/ResolvServer.h new file mode 100644 index 00000000000..f8f8f5aadbf --- /dev/null +++ b/dep/include/sockets/ResolvServer.h @@ -0,0 +1,73 @@ +/** \file ResolvServer.h + ** \date 2005-03-24 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2004-2007 Anders Hedstrom + +This library is made available under the terms of the GNU GPL. + +If you would like to use this library in a closed-source application, +a separate license agreement is available. For information about +the closed-source license agreement for the C++ sockets library, +please visit http://www.alhem.net/Sockets/license.html and/or +email license@alhem.net. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef _SOCKETS_ResolvServer_H +#define _SOCKETS_ResolvServer_H +#include "sockets-config.h" +#ifdef ENABLE_RESOLVER +#include "socket_include.h" +#include "Thread.h" + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + +/** \defgroup async Asynchronous DNS */ +/** Async DNS resolver thread. + \ingroup async */ +class ResolvServer : public Thread +{ +public: + ResolvServer(port_t); + ~ResolvServer(); + + void Run(); + void Quit(); + + bool Ready(); + +private: + ResolvServer(const ResolvServer& ) {} // copy constructor + ResolvServer& operator=(const ResolvServer& ) { return *this; } // assignment operator + + bool m_quit; + port_t m_port; + bool m_ready; +}; + + + + +#ifdef SOCKETS_NAMESPACE +} +#endif + +#endif // ENABLE_RESOLVER +#endif // _SOCKETS_ResolvServer_H + diff --git a/dep/include/sockets/ResolvSocket.h b/dep/include/sockets/ResolvSocket.h new file mode 100644 index 00000000000..ff4b1a5a982 --- /dev/null +++ b/dep/include/sockets/ResolvSocket.h @@ -0,0 +1,106 @@ +/** \file ResolvSocket.h + ** \date 2005-03-24 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2004-2007 Anders Hedstrom + +This library is made available under the terms of the GNU GPL. + +If you would like to use this library in a closed-source application, +a separate license agreement is available. For information about +the closed-source license agreement for the C++ sockets library, +please visit http://www.alhem.net/Sockets/license.html and/or +email license@alhem.net. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef _SOCKETS_ResolvSocket_H +#define _SOCKETS_ResolvSocket_H +#include "sockets-config.h" +#ifdef ENABLE_RESOLVER +#include "TcpSocket.h" +#include + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + +class Mutex; + +/** Async DNS resolver socket. + \ingroup async */ +class ResolvSocket : public TcpSocket +{ + typedef std::map > cache_t; /* host, result */ + typedef std::map > timeout_t; /* host, time */ + +public: + ResolvSocket(ISocketHandler&); + ResolvSocket(ISocketHandler&, Socket *parent, const std::string& host, port_t port, bool ipv6 = false); + ResolvSocket(ISocketHandler&, Socket *parent, ipaddr_t); +#ifdef ENABLE_IPV6 + ResolvSocket(ISocketHandler&, Socket *parent, in6_addr&); +#endif + ~ResolvSocket(); + + void OnAccept() { m_bServer = true; } + void OnLine(const std::string& line); + void OnDetached(); + void OnDelete(); + + void SetId(int x) { m_resolv_id = x; } + int GetId() { return m_resolv_id; } + + void OnConnect(); + +#ifdef ENABLE_IPV6 + void SetResolveIpv6(bool x = true) { m_resolve_ipv6 = x; } +#endif + +private: + ResolvSocket(const ResolvSocket& s) : TcpSocket(s) {} // copy constructor + ResolvSocket& operator=(const ResolvSocket& ) { return *this; } // assignment operator + + std::string m_query; + std::string m_data; + bool m_bServer; + Socket *m_parent; + int m_resolv_id; + std::string m_resolv_host; + port_t m_resolv_port; + ipaddr_t m_resolv_address; +#ifdef ENABLE_IPV6 + bool m_resolve_ipv6; + in6_addr m_resolv_address6; +#endif + static cache_t m_cache; + static timeout_t m_cache_to; + static Mutex m_cache_mutex; + bool m_cached; +}; + + + + +#ifdef SOCKETS_NAMESPACE +} +#endif + +#endif // ENABLE_RESOLVER +#endif // _SOCKETS_ResolvSocket_H + diff --git a/dep/include/sockets/SctpSocket.h b/dep/include/sockets/SctpSocket.h new file mode 100644 index 00000000000..d6d55f6be78 --- /dev/null +++ b/dep/include/sockets/SctpSocket.h @@ -0,0 +1,109 @@ +/** + ** \file SctpSocket.h + ** \date 2006-09-04 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2007 Anders Hedstrom + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef _SOCKETS_SctpSocket_H +#define _SOCKETS_SctpSocket_H +#include "sockets-config.h" + +#include "StreamSocket.h" +#ifdef USE_SCTP +#include + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + +#define SCTP_BUFSIZE_READ 16400 + +class SocketAddress; + + +class SctpSocket : public StreamSocket +{ +public: + /** SctpSocket constructor. + \param h Owner + \param type SCTP_STREAM or SCTP_SEQPACKET */ + SctpSocket(ISocketHandler& h,int type); + ~SctpSocket(); + + /** bind() */ + int Bind(const std::string&,port_t); + int Bind(SocketAddress&); + /** sctp_bindx() */ + int AddAddress(const std::string&,port_t); + int AddAddress(SocketAddress&); + /** sctp_bindx() */ + int RemoveAddress(const std::string&,port_t); + int RemoveAddress(SocketAddress&); + + /** connect() */ + int Open(const std::string&,port_t); + int Open(SocketAddress&); + + /** Connect timeout callback. */ + void OnConnectTimeout(); +#ifdef _WIN32 + /** Connection failed reported as exception on win32 */ + void OnException(); +#endif + +#ifndef SOLARIS + /** sctp_connectx() */ + int AddConnection(const std::string&,port_t); + int AddConnection(SocketAddress&); +#endif + + /** Get peer addresses of an association. */ + int getpaddrs(sctp_assoc_t id,std::list&); + /** Get all bound addresses of an association. */ + int getladdrs(sctp_assoc_t id,std::list&); + + /** sctp_peeloff */ + int PeelOff(sctp_assoc_t id); + + /** recvmsg callback */ + virtual void OnReceiveMessage(const char *buf,size_t sz,struct sockaddr *sa,socklen_t sa_len,struct sctp_sndrcvinfo *sinfo,int msg_flags) = 0; + + void OnOptions(int,int,int,SOCKET) {} + + virtual int Protocol(); + +protected: + SctpSocket(const SctpSocket& s) : StreamSocket(s) {} + void OnRead(); + void OnWrite(); + +private: + SctpSocket& operator=(const SctpSocket& s) { return *this; } + int m_type; ///< SCTP_STREAM or SCTP_SEQPACKET + char *m_buf; ///< Temporary receive buffer +}; + + +#ifdef SOCKETS_NAMESPACE +} // namespace SOCKETS_NAMESPACE +#endif + +#endif // USE_SCTP +#endif // _SOCKETS_SctpSocket_H + diff --git a/dep/include/sockets/Socket.h b/dep/include/sockets/Socket.h new file mode 100644 index 00000000000..bdb5fc60392 --- /dev/null +++ b/dep/include/sockets/Socket.h @@ -0,0 +1,739 @@ +/** \file Socket.h + ** \date 2004-02-13 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2004-2007 Anders Hedstrom + +This software is made available under the terms of the GNU GPL. + +If you would like to use this library in a closed-source application, +a separate license agreement is available. For information about +the closed-source license agreement for the C++ sockets library, +please visit http://www.alhem.net/Sockets/license.html and/or +email license@alhem.net. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef _SOCKETS_Socket_H +#define _SOCKETS_Socket_H +#include "sockets-config.h" + +#include +#include +#include +#ifdef HAVE_OPENSSL +#include +#endif + +#include "socket_include.h" +#include +#include "SocketAddress.h" +#include "Thread.h" + + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + + +class ISocketHandler; +class SocketAddress; +class IFile; + + +/** \defgroup basic Basic sockets */ +/** Socket base class. + \ingroup basic */ +class Socket +{ + friend class ISocketHandler; +#ifdef ENABLE_DETACH + /** Detached socket run thread. + \ingroup internal */ + class SocketThread : public Thread + { + public: + SocketThread(Socket *p); + ~SocketThread(); + + void Run(); + + private: + Socket *GetSocket() const { return m_socket; } + SocketThread(const SocketThread& s) : m_socket(s.GetSocket()) {} + SocketThread& operator=(const SocketThread& ) { return *this; } + Socket *m_socket; + }; +#endif // ENABLE_DETACH + +#ifdef ENABLE_TRIGGERS +public: + /** Data pass class from source to destination. */ + class TriggerData + { + public: + TriggerData() : m_src(NULL) {} + virtual ~TriggerData() {} + + Socket *GetSource() const { return m_src; } + void SetSource(Socket *x) { m_src = x; } + + private: + Socket *m_src; + }; +#endif // ENABLE_TRIGGERS + + /** Socket mode flags. */ +/* + enum { + // Socket + SOCK_DEL = 0x01, ///< Delete by handler flag + SOCK_CLOSE = 0x02, ///< Close and delete flag + SOCK_DISABLE_READ = 0x04, ///< Disable checking for read events + SOCK_CONNECTED = 0x08, ///< Socket is connected (tcp/udp) + + SOCK_ERASED_BY_HANDLER = 0x10, ///< Set by handler before delete + // HAVE_OPENSSL + SOCK_ENABLE_SSL = 0x20, ///< Enable SSL for this TcpSocket + SOCK_SSL = 0x40, ///< ssl negotiation mode (TcpSocket) + SOCK_SSL_SERVER = 0x80, ///< True if this is an incoming ssl TcpSocket connection + + // ENABLE_IPV6 + SOCK_IPV6 = 0x0100, ///< This is an ipv6 socket if this one is true + // ENABLE_POOL + SOCK_CLIENT = 0x0200, ///< only client connections are pooled + SOCK_RETAIN = 0x0400, ///< keep connection on close + SOCK_LOST = 0x0800, ///< connection lost + + // ENABLE_SOCKS4 + SOCK_SOCKS4 = 0x1000, ///< socks4 negotiation mode (TcpSocket) + // ENABLE_DETACH + SOCK_DETACH = 0x2000, ///< Socket ordered to detach flag + SOCK_DETACHED = 0x4000, ///< Socket has been detached + // StreamSocket + STREAMSOCK_CONNECTING = 0x8000, ///< Flag indicating connection in progress + + STREAMSOCK_FLUSH_BEFORE_CLOSE = 0x010000L, ///< Send all data before closing (default true) + STREAMSOCK_CALL_ON_CONNECT = 0x020000L, ///< OnConnect will be called next ISocketHandler cycle if true + STREAMSOCK_RETRY_CONNECT = 0x040000L, ///< Try another connection attempt next ISocketHandler cycle + STREAMSOCK_LINE_PROTOCOL = 0x080000L, ///< Line protocol mode flag + + }; +*/ + +public: + /** "Default" constructor */ + Socket(ISocketHandler&); + + virtual ~Socket(); + + /** Socket class instantiation method. Used when a "non-standard" constructor + * needs to be used for the socket class. Note: the socket class still needs + * the "default" constructor with one ISocketHandler& as input parameter. + */ + virtual Socket *Create() { return NULL; } + + /** Returns reference to sockethandler that owns the socket. + If the socket is detached, this is a reference to the slave sockethandler. + */ + ISocketHandler& Handler() const; + + /** Returns reference to sockethandler that owns the socket. + This one always returns the reference to the original sockethandler, + even if the socket is detached. + */ + ISocketHandler& MasterHandler() const; + + /** Called by ListenSocket after accept but before socket is added to handler. + * CTcpSocket uses this to create its ICrypt member variable. + * The ICrypt member variable is created by a virtual method, therefore + * it can't be called directly from the CTcpSocket constructor. + * Also used to determine if incoming HTTP connection is normal (port 80) + * or ssl (port 443). + */ + virtual void Init(); + + /** Create a socket file descriptor. + \param af Address family AF_INET / AF_INET6 / ... + \param type SOCK_STREAM / SOCK_DGRAM / ... + \param protocol "tcp" / "udp" / ... */ + SOCKET CreateSocket(int af,int type,const std::string& protocol = ""); + + /** Assign this socket a file descriptor created + by a call to socket() or otherwise. */ + void Attach(SOCKET s); + + /** Return file descriptor assigned to this socket. */ + SOCKET GetSocket(); + + /** Close connection immediately - internal use. + \sa SetCloseAndDelete */ + virtual int Close(); + + /** Add file descriptor to sockethandler fd_set's. */ + void Set(bool bRead,bool bWrite,bool bException = true); + + /** Returns true when socket file descriptor is valid + and socket is not about to be closed. */ + virtual bool Ready(); + + /** Returns pointer to ListenSocket that created this instance + * on an incoming connection. */ + Socket *GetParent(); + + /** Used by ListenSocket to set parent pointer of newly created + * socket instance. */ + void SetParent(Socket *); + + /** Get listening port from ListenSocket<>. */ + virtual port_t GetPort(); + + /** Set socket non-block operation. */ + bool SetNonblocking(bool); + + /** Set socket non-block operation. */ + bool SetNonblocking(bool, SOCKET); + + /** Total lifetime of instance. */ + time_t Uptime(); + + /** Set address/port of last connect() call. */ + void SetClientRemoteAddress(SocketAddress&); + + /** Get address/port of last connect() call. */ + std::auto_ptr GetClientRemoteAddress(); + + /** Common interface for SendBuf used by Tcp and Udp sockets. */ + virtual void SendBuf(const char *,size_t,int = 0); + + /** Common interface for Send used by Tcp and Udp sockets. */ + virtual void Send(const std::string&,int = 0); + + /** Outgoing traffic counter. */ + virtual uint64_t GetBytesSent(bool clear = false); + + /** Incoming traffic counter. */ + virtual uint64_t GetBytesReceived(bool clear = false); + + // LIST_TIMEOUT + + /** Enable timeout control. 0=disable timeout check. */ + void SetTimeout(time_t secs); + + /** Check timeout. \return true if time limit reached */ + bool Timeout(time_t tnow); + + /** Used by ListenSocket. ipv4 and ipv6 */ + void SetRemoteAddress(SocketAddress&); + + /** \name Event callbacks */ + //@{ + + /** Called when there is something to be read from the file descriptor. */ + virtual void OnRead(); + /** Called when there is room for another write on the file descriptor. */ + virtual void OnWrite(); + /** Called on socket exception. */ + virtual void OnException(); + /** Called before a socket class is deleted by the ISocketHandler. */ + virtual void OnDelete(); + /** Called when a connection has completed. */ + virtual void OnConnect(); + /** Called when an incoming connection has been completed. */ + virtual void OnAccept(); + /** Called when a complete line has been read and the socket is in + * line protocol mode. */ + virtual void OnLine(const std::string& ); + /** Called on connect timeout (5s). */ + virtual void OnConnectFailed(); + /** Called when a client socket is created, to set socket options. + \param family AF_INET, AF_INET6, etc + \param type SOCK_STREAM, SOCK_DGRAM, etc + \param protocol Protocol number (tcp, udp, sctp, etc) + \param s Socket file descriptor + */ + virtual void OnOptions(int family,int type,int protocol,SOCKET s) = 0; + /** Connection retry callback - return false to abort connection attempts */ + virtual bool OnConnectRetry(); +#ifdef ENABLE_RECONNECT + /** a reconnect has been made */ + virtual void OnReconnect(); +#endif + /** TcpSocket: When a disconnect has been detected (recv/SSL_read returns 0 bytes). */ + virtual void OnDisconnect(); + /** Timeout callback. */ + virtual void OnTimeout(); + /** Connection timeout. */ + virtual void OnConnectTimeout(); + //@} + + /** \name Socket mode flags, set/reset */ + //@{ + /** Set delete by handler true when you want the sockethandler to + delete the socket instance after use. */ + void SetDeleteByHandler(bool = true); + /** Check delete by handler flag. + \return true if this instance should be deleted by the sockethandler */ + bool DeleteByHandler(); + + // LIST_CLOSE - conditional event queue + + /** Set close and delete to terminate the connection. */ + void SetCloseAndDelete(bool = true); + /** Check close and delete flag. + \return true if this socket should be closed and the instance removed */ + bool CloseAndDelete(); + + /** Return number of seconds since socket was ordered to close. \sa SetCloseAndDelete */ + time_t TimeSinceClose(); + + /** Ignore read events for an output only socket. */ + void DisableRead(bool x = true); + /** Check ignore read events flag. + \return true if read events should be ignored */ + bool IsDisableRead(); + + /** Set connected status. */ + void SetConnected(bool = true); + /** Check connected status. + \return true if connected */ + bool IsConnected(); + + /** Connection lost - error while reading/writing from a socket - TcpSocket only. */ + void SetLost(); + /** Check connection lost status flag, used by TcpSocket only. + \return true if there was an error while r/w causing the socket to close */ + bool Lost(); + + /** Set flag indicating the socket is being actively deleted by the sockethandler. */ + void SetErasedByHandler(bool x = true); + /** Get value of flag indicating socket is deleted by sockethandler. */ + bool ErasedByHandler(); + + //@} + + /** \name Information about remote connection */ + //@{ + /** Returns address of remote end. */ + std::auto_ptr GetRemoteSocketAddress(); + /** Returns address of remote end: ipv4. */ + ipaddr_t GetRemoteIP4(); +#ifdef ENABLE_IPV6 + /** Returns address of remote end: ipv6. */ +#ifdef IPPROTO_IPV6 + struct in6_addr GetRemoteIP6(); +#endif +#endif + /** Returns remote port number: ipv4 and ipv6. */ + port_t GetRemotePort(); + /** Returns remote ip as string? ipv4 and ipv6. */ + std::string GetRemoteAddress(); + /** ipv4 and ipv6(not implemented) */ + std::string GetRemoteHostname(); + //@} + + /** Returns local port number for bound socket file descriptor. */ + port_t GetSockPort(); + /** Returns local ipv4 address for bound socket file descriptor. */ + ipaddr_t GetSockIP4(); + /** Returns local ipv4 address as text for bound socket file descriptor. */ + std::string GetSockAddress(); +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + /** Returns local ipv6 address for bound socket file descriptor. */ + struct in6_addr GetSockIP6(); + /** Returns local ipv6 address as text for bound socket file descriptor. */ + std::string GetSockAddress6(); +#endif +#endif + // -------------------------------------------------------------------------- + /** @name IP options + When an ip or socket option is available on all of the operating systems + I'm testing on (linux 2.4.x, _win32, macosx, solaris9 intel) they are not + checked with an #ifdef below. + This might cause a compile error on other operating systems. */ + // -------------------------------------------------------------------------- + + // IP options + //@{ + + bool SetIpOptions(const void *p, socklen_t len); + bool SetIpTOS(unsigned char tos); + unsigned char IpTOS(); + bool SetIpTTL(int ttl); + int IpTTL(); + bool SetIpHdrincl(bool x = true); + bool SetIpMulticastTTL(int); + int IpMulticastTTL(); + bool SetMulticastLoop(bool x = true); + bool IpAddMembership(struct ip_mreq&); + bool IpDropMembership(struct ip_mreq&); + +#ifdef IP_PKTINFO + bool SetIpPktinfo(bool x = true); +#endif +#ifdef IP_RECVTOS + bool SetIpRecvTOS(bool x = true); +#endif +#ifdef IP_RECVTTL + bool SetIpRecvTTL(bool x = true); +#endif +#ifdef IP_RECVOPTS + bool SetIpRecvopts(bool x = true); +#endif +#ifdef IP_RETOPTS + bool SetIpRetopts(bool x = true); +#endif +#ifdef IP_RECVERR + bool SetIpRecverr(bool x = true); +#endif +#ifdef IP_MTU_DISCOVER + bool SetIpMtudiscover(bool x = true); +#endif +#ifdef IP_MTU + int IpMtu(); +#endif +#ifdef IP_ROUTER_ALERT + bool SetIpRouterAlert(bool x = true); +#endif +#ifdef LINUX + bool IpAddMembership(struct ip_mreqn&); +#endif +#ifdef LINUX + bool IpDropMembership(struct ip_mreqn&); +#endif + //@} + + // SOCKET options + /** @name Socket Options */ + //@{ + + bool SoAcceptconn(); + bool SetSoBroadcast(bool x = true); + bool SetSoDebug(bool x = true); + int SoError(); + bool SetSoDontroute(bool x = true); + bool SetSoLinger(int onoff, int linger); + bool SetSoOobinline(bool x = true); + bool SetSoRcvlowat(int); + bool SetSoSndlowat(int); + bool SetSoRcvtimeo(struct timeval&); + bool SetSoSndtimeo(struct timeval&); + bool SetSoRcvbuf(int); + int SoRcvbuf(); + bool SetSoSndbuf(int); + int SoSndbuf(); + int SoType(); + bool SetSoReuseaddr(bool x = true); + bool SetSoKeepalive(bool x = true); + +#ifdef SO_BSDCOMPAT + bool SetSoBsdcompat(bool x = true); +#endif +#ifdef SO_BINDTODEVICE + bool SetSoBindtodevice(const std::string& intf); +#endif +#ifdef SO_PASSCRED + bool SetSoPasscred(bool x = true); +#endif +#ifdef SO_PEERCRED + bool SoPeercred(struct ucred& ); +#endif +#ifdef SO_PRIORITY + bool SetSoPriority(int); +#endif +#ifdef SO_RCVBUFFORCE + bool SetSoRcvbufforce(int); +#endif +#ifdef SO_SNDBUFFORCE + bool SetSoSndbufforce(int); +#endif +#ifdef SO_TIMESTAMP + bool SetSoTimestamp(bool x = true); +#endif +#ifdef SO_NOSIGPIPE + bool SetSoNosigpipe(bool x = true); +#endif + //@} + + // TCP options in TcpSocket.h/TcpSocket.cpp + + +#ifdef HAVE_OPENSSL + /** @name SSL Support */ + //@{ + /** SSL client/server support - internal use. \sa TcpSocket */ + virtual void OnSSLConnect(); + /** SSL client/server support - internal use. \sa TcpSocket */ + virtual void OnSSLAccept(); + /** SSL negotiation failed for client connect. */ + virtual void OnSSLConnectFailed(); + /** SSL negotiation failed for server accept. */ + virtual void OnSSLAcceptFailed(); + /** new SSL support */ + virtual bool SSLNegotiate(); + /** Check if SSL is Enabled for this TcpSocket. + \return true if this is a TcpSocket with SSL enabled */ + bool IsSSL(); + /** Enable SSL operation for a TcpSocket. */ + void EnableSSL(bool x = true); + /** Still negotiating ssl connection. + \return true if ssl negotiating is still in progress */ + bool IsSSLNegotiate(); + /** Set flag indicating ssl handshaking still in progress. */ + void SetSSLNegotiate(bool x = true); + /** OnAccept called with SSL Enabled. + \return true if this is a TcpSocket with an incoming SSL connection */ + bool IsSSLServer(); + /** Set flag indicating that this is a TcpSocket with incoming SSL connection. */ + void SetSSLServer(bool x = true); + /** SSL; Get pointer to ssl context structure. */ + virtual SSL_CTX *GetSslContext() { return NULL; } + /** SSL; Get pointer to ssl structure. */ + virtual SSL *GetSsl() { return NULL; } + //@} +#endif // HAVE_OPENSSL + +#ifdef ENABLE_IPV6 + /** Enable ipv6 for this socket. */ + void SetIpv6(bool x = true); + /** Check ipv6 socket. + \return true if this is an ipv6 socket */ + bool IsIpv6(); +#endif + +#ifdef ENABLE_POOL + /** @name Connection Pool */ + //@{ + /** Client = connecting TcpSocket. */ + void SetIsClient(); + /** Socket type from socket() call. */ + void SetSocketType(int x); + /** Socket type from socket() call. */ + int GetSocketType(); + /** Protocol type from socket() call. */ + void SetSocketProtocol(const std::string& x); + /** Protocol type from socket() call. */ + const std::string& GetSocketProtocol(); + /** Instruct a client socket to stay open in the connection pool after use. + If you have connected to a server using tcp, you can call SetRetain + to leave the connection open after your socket instance has been deleted. + The next connection you make to the same server will reuse the already + opened connection, if it is still available. + */ + void SetRetain(); + /** Check retain flag. + \return true if the socket should be moved to connection pool after use */ + bool Retain(); + /** Copy connection parameters from sock. */ + void CopyConnection(Socket *sock); + //@} +#endif // ENABLE_POOL + +#ifdef ENABLE_SOCKS4 + /** \name Socks4 support */ + //@{ + /** Socks4 client support internal use. \sa TcpSocket */ + virtual void OnSocks4Connect(); + /** Socks4 client support internal use. \sa TcpSocket */ + virtual void OnSocks4ConnectFailed(); + /** Socks4 client support internal use. \sa TcpSocket */ + virtual bool OnSocks4Read(); + /** Called when the last write caused the tcp output buffer to + * become empty. */ + /** socket still in socks4 negotiation mode */ + bool Socks4(); + /** Set flag indicating Socks4 handshaking in progress */ + void SetSocks4(bool x = true); + + /** Set socks4 server host address to use */ + void SetSocks4Host(ipaddr_t a); + /** Set socks4 server hostname to use. */ + void SetSocks4Host(const std::string& ); + /** Socks4 server port to use. */ + void SetSocks4Port(port_t p); + /** Provide a socks4 userid if required by the socks4 server. */ + void SetSocks4Userid(const std::string& x); + /** Get the ip address of socks4 server to use. + \return socks4 server host address */ + ipaddr_t GetSocks4Host(); + /** Get the socks4 server port to use. + \return socks4 server port */ + port_t GetSocks4Port(); + /** Get socks4 userid. + \return Socks4 userid */ + const std::string& GetSocks4Userid(); + //@} +#endif // ENABLE_SOCKS4 + +#ifdef ENABLE_RESOLVER + /** \name Asynchronous Resolver */ + //@{ + /** Request an asynchronous dns resolution. + \param host hostname to be resolved + \param port port number passed along for the ride + \return Resolve ID */ + int Resolve(const std::string& host,port_t port = 0); +#ifdef ENABLE_IPV6 + int Resolve6(const std::string& host, port_t port = 0); +#endif + /** Callback returning a resolved address. + \param id Resolve ID from Resolve call + \param a resolved ip address + \param port port number passed to Resolve */ + virtual void OnResolved(int id,ipaddr_t a,port_t port); +#ifdef ENABLE_IPV6 + virtual void OnResolved(int id,in6_addr& a,port_t port); +#endif + /** Request asynchronous reverse dns lookup. + \param a in_addr to be translated */ + int Resolve(ipaddr_t a); +#ifdef ENABLE_IPV6 + int Resolve(in6_addr& a); +#endif + /** Callback returning reverse resolve results. + \param id Resolve ID + \param name Resolved hostname */ + virtual void OnReverseResolved(int id,const std::string& name); + /** Callback indicating failed dns lookup. + \param id Resolve ID */ + virtual void OnResolveFailed(int id); + //@} +#endif // ENABLE_RESOLVER + +#ifdef ENABLE_DETACH + /** \name Thread Support */ + //@{ + /** Callback fires when a new socket thread has started and this + socket is ready for operation again. + \sa ResolvSocket */ + virtual void OnDetached(); + + // LIST_DETACH + + /** Internal use. */ + void SetDetach(bool x = true); + /** Check detach flag. + \return true if the socket should detach to its own thread */ + bool IsDetach(); + + /** Internal use. */ + void SetDetached(bool x = true); + /** Check detached flag. + \return true if the socket runs in its own thread. */ + const bool IsDetached() const; + /** Order this socket to start its own thread and call OnDetached + when ready for operation. */ + bool Detach(); + /** Store the slave sockethandler pointer. */ + void SetSlaveHandler(ISocketHandler *); + /** Create new thread for this socket to run detached in. */ + void DetachSocket(); + //@} +#endif // ENABLE_DETACH + + /** Write traffic to an IFile. Socket will not delete this object. */ + void SetTrafficMonitor(IFile *p) { m_traffic_monitor = p; } + +#ifdef ENABLE_TRIGGERS + /** \name Triggers */ + //@{ + /** Subscribe to trigger id. */ + void Subscribe(int id); + /** Unsubscribe from trigger id. */ + void Unsubscribe(int id); + /** Trigger callback, with data passed from source to destination. */ + virtual void OnTrigger(int id, const TriggerData& data); + /** Trigger cancelled because source has been deleted (as in delete). */ + virtual void OnCancelled(int id); + //@} +#endif + +protected: + /** default constructor not available */ + Socket() : m_handler(m_handler) {} + /** copy constructor not available */ + Socket(const Socket& s) : m_handler(s.m_handler) {} + + /** assignment operator not available. */ + Socket& operator=(const Socket& ) { return *this; } + + /** All traffic will be written to this IFile, if set. */ + IFile *GetTrafficMonitor() { return m_traffic_monitor; } + +// unsigned long m_flags; ///< boolean flags, replacing old 'bool' members + +private: + ISocketHandler& m_handler; ///< Reference of ISocketHandler in control of this socket + SOCKET m_socket; ///< File descriptor + bool m_bDel; ///< Delete by handler flag + bool m_bClose; ///< Close and delete flag + time_t m_tCreate; ///< Time in seconds when this socket was created + Socket *m_parent; ///< Pointer to ListenSocket class, valid for incoming sockets + bool m_b_disable_read; ///< Disable checking for read events + bool m_connected; ///< Socket is connected (tcp/udp) + bool m_b_erased_by_handler; ///< Set by handler before delete + time_t m_tClose; ///< Time in seconds when ordered to close + std::auto_ptr m_client_remote_address; ///< Address of last connect() + std::auto_ptr m_remote_address; ///< Remote end address + IFile *m_traffic_monitor; + time_t m_timeout_start; ///< Set by SetTimeout + time_t m_timeout_limit; ///< Defined by SetTimeout + bool m_bLost; ///< connection lost + +#ifdef _WIN32 +static WSAInitializer m_winsock_init; ///< Winsock initialization singleton class +#endif + +#ifdef HAVE_OPENSSL + bool m_b_enable_ssl; ///< Enable SSL for this TcpSocket + bool m_b_ssl; ///< ssl negotiation mode (TcpSocket) + bool m_b_ssl_server; ///< True if this is an incoming ssl TcpSocket connection +#endif + +#ifdef ENABLE_IPV6 + bool m_ipv6; ///< This is an ipv6 socket if this one is true +#endif + +#ifdef ENABLE_POOL + int m_socket_type; ///< Type of socket, from socket() call + std::string m_socket_protocol; ///< Protocol, from socket() call + bool m_bClient; ///< only client connections are pooled + bool m_bRetain; ///< keep connection on close +#endif + +#ifdef ENABLE_SOCKS4 + bool m_bSocks4; ///< socks4 negotiation mode (TcpSocket) + ipaddr_t m_socks4_host; ///< socks4 server address + port_t m_socks4_port; ///< socks4 server port number + std::string m_socks4_userid; ///< socks4 server usedid +#endif + +#ifdef ENABLE_DETACH + bool m_detach; ///< Socket ordered to detach flag + bool m_detached; ///< Socket has been detached + SocketThread *m_pThread; ///< Detach socket thread class pointer + ISocketHandler *m_slave_handler; ///< Actual sockethandler while detached +#endif +}; + +#ifdef SOCKETS_NAMESPACE +} +#endif + + +#endif // _SOCKETS_Socket_H + diff --git a/dep/include/sockets/SocketAddress.h b/dep/include/sockets/SocketAddress.h new file mode 100644 index 00000000000..d5a56433ba7 --- /dev/null +++ b/dep/include/sockets/SocketAddress.h @@ -0,0 +1,95 @@ +/** + ** \file SocketAddress.h + ** \date 2006-09-21 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2007 Anders Hedstrom + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef _SOCKETS_SocketAddress_H +#define _SOCKETS_SocketAddress_H + +#include "sockets-config.h" +#include +#include +#include "socket_include.h" + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + + +/** + This class and its subclasses is intended to be used as replacement + for the internal data type 'ipaddr_t' and various implementations of + IPv6 addressing found throughout the library. + 'ipaddr_t' is an IPv4 address in network byte order. + 'port_t' is the portnumber in host byte order. + 'struct in6_addr' is an IPv6 address. + 'struct in_addr' is an IPv4 address. + \ingroup basic +*/ +class SocketAddress +{ +public: + virtual ~SocketAddress() {} + + /** Get a pointer to the address struct. */ + virtual operator struct sockaddr *() = 0; + + /** Get length of address struct. */ + virtual operator socklen_t() = 0; + + /** Compare two addresses. */ + virtual bool operator==(SocketAddress&) = 0; + + /** Set port number. + \param port Port number in host byte order */ + virtual void SetPort(port_t port) = 0; + + /** Get port number. + \return Port number in host byte order. */ + virtual port_t GetPort() = 0; + + /** Set socket address. + \param sa Pointer to either 'struct sockaddr_in' or 'struct sockaddr_in6'. */ + virtual void SetAddress(struct sockaddr *sa) = 0; + + /** Convert address to text. */ + virtual std::string Convert(bool include_port) = 0; + + /** Reverse lookup of address. */ + virtual std::string Reverse() = 0; + + /** Get address family. */ + virtual int GetFamily() = 0; + + /** Address structure is valid. */ + virtual bool IsValid() = 0; + + /** Get a copy of this SocketAddress object. */ + virtual std::auto_ptr GetCopy() = 0; +}; + + + + +#ifdef SOCKETS_NAMESPACE +} // namespace SOCKETS_NAMESPACE { +#endif +#endif // _SOCKETS_SocketAddress_H + diff --git a/dep/include/sockets/SocketHandler.h b/dep/include/sockets/SocketHandler.h new file mode 100644 index 00000000000..c7e20dfde82 --- /dev/null +++ b/dep/include/sockets/SocketHandler.h @@ -0,0 +1,266 @@ +/** \file SocketHandler.h + ** \date 2004-02-13 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2004-2007 Anders Hedstrom + +This library is made available under the terms of the GNU GPL. + +If you would like to use this library in a closed-source application, +a separate license agreement is available. For information about +the closed-source license agreement for the C++ sockets library, +please visit http://www.alhem.net/Sockets/license.html and/or +email license@alhem.net. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef _SOCKETS_SocketHandler_H +#define _SOCKETS_SocketHandler_H + +#include "sockets-config.h" +#include +#include + +#include "socket_include.h" +#include "ISocketHandler.h" + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + + +class Socket; +#ifdef ENABLE_RESOLVER +class ResolvServer; +#endif +class Mutex; + +/** Socket container class, event generator. + \ingroup basic */ +class SocketHandler : public ISocketHandler +{ +protected: + /** Map type for holding file descriptors/socket object pointers. */ + typedef std::map socket_m; + +public: + /** SocketHandler constructor. + \param log Optional log class pointer */ + SocketHandler(StdLog *log = NULL); + + /** SocketHandler threadsafe constructor. + \param mutex Externally declared mutex variable + \param log Optional log class pointer */ + SocketHandler(Mutex& mutex,StdLog *log = NULL); + + ~SocketHandler(); + + /** Get mutex reference for threadsafe operations. */ + Mutex& GetMutex() const; + + /** Register StdLog object for error callback. + \param log Pointer to log class */ + void RegStdLog(StdLog *log); + + /** Log error to log class for print out / storage. */ + void LogError(Socket *p,const std::string& user_text,int err,const std::string& sys_err,loglevel_t t = LOG_LEVEL_WARNING); + + /** Add socket instance to socket map. Removal is always automatic. */ + void Add(Socket *); + + /** Get status of read/write/exception file descriptor set for a socket. */ + void Get(SOCKET s,bool& r,bool& w,bool& e); + + /** Set read/write/exception file descriptor sets (fd_set). */ + void Set(SOCKET s,bool bRead,bool bWrite,bool bException = true); + + /** Wait for events, generate callbacks. */ + int Select(long sec,long usec); + + /** This method will not return until an event has been detected. */ + int Select(); + + /** Wait for events, generate callbacks. */ + int Select(struct timeval *tsel); + + /** Check that a socket really is handled by this socket handler. */ + bool Valid(Socket *); + + /** Return number of sockets handled by this handler. */ + size_t GetCount(); + + /** Override and return false to deny all incoming connections. + \param p ListenSocket class pointer (use GetPort to identify which one) */ + bool OkToAccept(Socket *p); + + /** Called by Socket when a socket changes state. */ + void AddList(SOCKET s,list_t which_one,bool add); + + // Connection pool +#ifdef ENABLE_POOL + /** Find available open connection (used by connection pool). */ + ISocketHandler::PoolSocket *FindConnection(int type,const std::string& protocol,SocketAddress&); + /** Enable connection pool (by default disabled). */ + void EnablePool(bool x = true); + /** Check pool status. + \return true if connection pool is enabled */ + bool PoolEnabled(); +#endif // ENABLE_POOL + + // Socks4 +#ifdef ENABLE_SOCKS4 + /** Set socks4 server ip that all new tcp sockets should use. */ + void SetSocks4Host(ipaddr_t); + /** Set socks4 server hostname that all new tcp sockets should use. */ + void SetSocks4Host(const std::string& ); + /** Set socks4 server port number that all new tcp sockets should use. */ + void SetSocks4Port(port_t); + /** Set optional socks4 userid. */ + void SetSocks4Userid(const std::string& ); + /** If connection to socks4 server fails, immediately try direct connection to final host. */ + void SetSocks4TryDirect(bool x = true); + /** Get socks4 server ip. + \return socks4 server ip */ + ipaddr_t GetSocks4Host(); + /** Get socks4 port number. + \return socks4 port number */ + port_t GetSocks4Port(); + /** Get socks4 userid (optional). + \return socks4 userid */ + const std::string& GetSocks4Userid(); + /** Check status of socks4 try direct flag. + \return true if direct connection should be tried if connection to socks4 server fails */ + bool Socks4TryDirect(); +#endif // ENABLE_SOCKS4 + + // DNS resolve server +#ifdef ENABLE_RESOLVER + /** Enable asynchronous DNS. + \param port Listen port of asynchronous dns server */ + void EnableResolver(port_t port = 16667); + /** Check resolver status. + \return true if resolver is enabled */ + bool ResolverEnabled(); + /** Queue a dns request. + \param host Hostname to be resolved + \param port Port number will be echoed in Socket::OnResolved callback */ + int Resolve(Socket *,const std::string& host,port_t port); +#ifdef ENABLE_IPV6 + int Resolve6(Socket *,const std::string& host,port_t port); +#endif + /** Do a reverse dns lookup. */ + int Resolve(Socket *,ipaddr_t a); +#ifdef ENABLE_IPV6 + int Resolve(Socket *,in6_addr& a); +#endif + /** Get listen port of asynchronous dns server. */ + port_t GetResolverPort(); + /** Resolver thread ready for queries. */ + bool ResolverReady(); + /** Returns true if the socket is waiting for a resolve event. */ + bool Resolving(Socket *); +#endif // ENABLE_RESOLVER + +#ifdef ENABLE_TRIGGERS + /** Fetch unique trigger id. */ + int TriggerID(Socket *src); + /** Subscribe socket to trigger id. */ + bool Subscribe(int id, Socket *dst); + /** Unsubscribe socket from trigger id. */ + bool Unsubscribe(int id, Socket *dst); + /** Execute OnTrigger for subscribed sockets. + \param id Trigger ID + \param data Data passed from source to destination + \param erase Empty trigger id source and destination maps if 'true', + Leave them in place if 'false' - if a trigger should be called many times */ + void Trigger(int id, Socket::TriggerData& data, bool erase = true); +#endif // ENABLE_TRIGGERS + +#ifdef ENABLE_DETACH + /** Indicates that the handler runs under SocketThread. */ + void SetSlave(bool x = true); + /** Indicates that the handler runs under SocketThread. */ + bool IsSlave(); +#endif + + /** Sanity check of those accursed lists. */ + void CheckSanity(); + +protected: + socket_m m_sockets; ///< Active sockets map + socket_m m_add; ///< Sockets to be added to sockets map + std::list m_delete; ///< Sockets to be deleted (failed when Add) + +protected: + StdLog *m_stdlog; ///< Registered log class, or NULL + Mutex& m_mutex; ///< Thread safety mutex + bool m_b_use_mutex; ///< Mutex correctly initialized + +private: + void CheckList(socket_v&,const std::string&); ///< Used by CheckSanity + /** Remove socket from socket map, used by Socket class. */ + void Remove(Socket *); + SOCKET m_maxsock; ///< Highest file descriptor + 1 in active sockets list + fd_set m_rfds; ///< file descriptor set monitored for read events + fd_set m_wfds; ///< file descriptor set monitored for write events + fd_set m_efds; ///< file descriptor set monitored for exceptions + int m_preverror; ///< debug select() error + int m_errcnt; ///< debug select() error + time_t m_tlast; ///< timeout control + + // state lists + socket_v m_fds; ///< Active file descriptor list + socket_v m_fds_erase; ///< File descriptors that are to be erased from m_sockets + socket_v m_fds_callonconnect; ///< checklist CallOnConnect +#ifdef ENABLE_DETACH + socket_v m_fds_detach; ///< checklist Detach +#endif + socket_v m_fds_timeout; ///< checklist timeout + socket_v m_fds_retry; ///< checklist retry client connect + socket_v m_fds_close; ///< checklist close and delete + +#ifdef ENABLE_SOCKS4 + ipaddr_t m_socks4_host; ///< Socks4 server host ip + port_t m_socks4_port; ///< Socks4 server port number + std::string m_socks4_userid; ///< Socks4 userid + bool m_bTryDirect; ///< Try direct connection if socks4 server fails +#endif +#ifdef ENABLE_RESOLVER + int m_resolv_id; ///< Resolver id counter + ResolvServer *m_resolver; ///< Resolver thread pointer + port_t m_resolver_port; ///< Resolver listen port + std::map m_resolve_q; ///< resolve queue +#endif +#ifdef ENABLE_POOL + bool m_b_enable_pool; ///< Connection pool enabled if true +#endif +#ifdef ENABLE_TRIGGERS + int m_next_trigger_id; ///< Unique trigger id counter + std::map m_trigger_src; ///< mapping trigger id to source socket + std::map > m_trigger_dst; ///< mapping trigger id to destination sockets +#endif +#ifdef ENABLE_DETACH + bool m_slave; ///< Indicates that this is a ISocketHandler run in SocketThread +#endif +}; + + +#ifdef SOCKETS_NAMESPACE +} +#endif + +#endif // _SOCKETS_SocketHandler_H + diff --git a/dep/include/sockets/StdLog.h b/dep/include/sockets/StdLog.h new file mode 100644 index 00000000000..c07037bbd4f --- /dev/null +++ b/dep/include/sockets/StdLog.h @@ -0,0 +1,74 @@ +/** \file StdLog.h + ** \date 2004-06-01 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2004-2007 Anders Hedstrom + +This library is made available under the terms of the GNU GPL. + +If you would like to use this library in a closed-source application, +a separate license agreement is available. For information about +the closed-source license agreement for the C++ sockets library, +please visit http://www.alhem.net/Sockets/license.html and/or +email license@alhem.net. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef _SOCKETS_StdLog_H +#define _SOCKETS_StdLog_H + +#include "sockets-config.h" +#include + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + +/** error level enum. */ +typedef enum +{ + LOG_LEVEL_WARNING = 0, + LOG_LEVEL_ERROR, + LOG_LEVEL_FATAL, + LOG_LEVEL_INFO +} loglevel_t; + + +class ISocketHandler; +class Socket; + +/** \defgroup logging Log help classes */ +/** Log class interface. + \ingroup logging */ +class StdLog +{ +public: + virtual ~StdLog() {} + + virtual void error(ISocketHandler *,Socket *, + const std::string& user_text, + int err, + const std::string& sys_err, + loglevel_t = LOG_LEVEL_WARNING) = 0; +}; + + +#ifdef SOCKETS_NAMESPACE +} +#endif + +#endif // _SOCKETS_StdLog_H + diff --git a/dep/include/sockets/StdoutLog.h b/dep/include/sockets/StdoutLog.h new file mode 100644 index 00000000000..5f96b340dc2 --- /dev/null +++ b/dep/include/sockets/StdoutLog.h @@ -0,0 +1,57 @@ +/** \file StdoutLog.h + ** \date 2004-06-01 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2004-2007 Anders Hedstrom + +This library is made available under the terms of the GNU GPL. + +If you would like to use this library in a closed-source application, +a separate license agreement is available. For information about +the closed-source license agreement for the C++ sockets library, +please visit http://www.alhem.net/Sockets/license.html and/or +email license@alhem.net. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef _SOCKETS_StdoutLog_H +#define _SOCKETS_StdoutLog_H + +#include "sockets-config.h" +#include "StdLog.h" + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + + +/** StdLog implementation, logs to stdout. + \ingroup logging */ +class StdoutLog : public StdLog +{ +public: + void error(ISocketHandler *,Socket *,const std::string& call,int err,const std::string& sys_err,loglevel_t); +}; + + + + +#ifdef SOCKETS_NAMESPACE +} +#endif + +#endif // _SOCKETS_StdoutLog_H + diff --git a/dep/include/sockets/StreamSocket.h b/dep/include/sockets/StreamSocket.h new file mode 100644 index 00000000000..3c248110b88 --- /dev/null +++ b/dep/include/sockets/StreamSocket.h @@ -0,0 +1,127 @@ +#ifndef _StreamSocket_H +#define _StreamSocket_H + +#include "Socket.h" + + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + + +/** SOCK_STREAM Socket base class. + \ingroup basic */ +class StreamSocket : public Socket +{ +public: + StreamSocket(ISocketHandler& ); + ~StreamSocket(); + + /** Socket should Check Connect on next write event from select(). */ + void SetConnecting(bool = true); + + /** Check connecting flag. + \return true if the socket is still trying to connect */ + bool Connecting(); + + /** Returns true when socket file descriptor is valid, + socket connection is established, and socket is not about to + be closed. */ + bool Ready(); + + /** Set timeout to use for connection attempt. + \param x Timeout in seconds */ + void SetConnectTimeout(int x); + + /** Return number of seconds to wait for a connection. + \return Connection timeout (seconds) */ + int GetConnectTimeout(); + + /** Set flush before close to make a tcp socket completely empty its + output buffer before closing the connection. */ + void SetFlushBeforeClose(bool = true); + + /** Check flush before status. + \return true if the socket should send all data before closing */ + bool GetFlushBeforeClose(); + + /** Define number of connection retries (tcp only). + n = 0 - no retry + n > 0 - number of retries + n = -1 - unlimited retries */ + void SetConnectionRetry(int n); + + /** Get number of maximum connection retries (tcp only). */ + int GetConnectionRetry(); + + /** Increase number of actual connection retries (tcp only). */ + void IncreaseConnectionRetries(); + + /** Get number of actual connection retries (tcp only). */ + int GetConnectionRetries(); + + /** Reset actual connection retries (tcp only). */ + void ResetConnectionRetries(); + + // LIST_CALLONCONNECT + + /** Instruct socket to call OnConnect callback next sockethandler cycle. */ + void SetCallOnConnect(bool x = true); + + /** Check call on connect flag. + \return true if OnConnect() should be called a.s.a.p */ + bool CallOnConnect(); + + // LIST_RETRY + + /** Set flag to initiate a connection attempt after a connection timeout. */ + void SetRetryClientConnect(bool x = true); + + /** Check if a connection attempt should be made. + \return true when another attempt should be made */ + bool RetryClientConnect(); + + /** Called after OnRead if socket is in line protocol mode. + \sa SetLineProtocol */ + /** Enable the OnLine callback. Do not create your own OnRead + * callback when using this. */ + virtual void SetLineProtocol(bool = true); + + /** Check line protocol mode. + \return true if socket is in line protocol mode */ + bool LineProtocol(); + + /** Set shutdown status. */ + void SetShutdown(int); + + /** Get shutdown status. */ + int GetShutdown(); + + /** Returns IPPROTO_TCP or IPPROTO_SCTP */ + virtual int Protocol() = 0; + +protected: + StreamSocket(const StreamSocket& ) {} // copy constructor + +private: + StreamSocket& operator=(const StreamSocket& ) { return *this; } // assignment operator + + bool m_bConnecting; ///< Flag indicating connection in progress + int m_connect_timeout; ///< Connection timeout (seconds) + bool m_flush_before_close; ///< Send all data before closing (default true) + int m_connection_retry; ///< Maximum connection retries (tcp) + int m_retries; ///< Actual number of connection retries (tcp) + bool m_call_on_connect; ///< OnConnect will be called next ISocketHandler cycle if true + bool m_b_retry_connect; ///< Try another connection attempt next ISocketHandler cycle + bool m_line_protocol; ///< Line protocol mode flag + int m_shutdown; ///< Shutdown status +}; + + +#ifdef SOCKETS_NAMESPACE +} // namespace SOCKETS_NAMESPACE { +#endif + + +#endif // _StreamSocket_H + diff --git a/dep/include/sockets/TcpSocket.h b/dep/include/sockets/TcpSocket.h new file mode 100644 index 00000000000..515f5aa6cc7 --- /dev/null +++ b/dep/include/sockets/TcpSocket.h @@ -0,0 +1,358 @@ +/** \file TcpSocket.h + ** \date 2004-02-13 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2004-2007 Anders Hedstrom + +This library is made available under the terms of the GNU GPL. + +If you would like to use this library in a closed-source application, +a separate license agreement is available. For information about +the closed-source license agreement for the C++ sockets library, +please visit http://www.alhem.net/Sockets/license.html and/or +email license@alhem.net. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef _SOCKETS_TcpSocket_H +#define _SOCKETS_TcpSocket_H +#include "sockets-config.h" +#include "StreamSocket.h" +#ifdef HAVE_OPENSSL +#include +#include "SSLInitializer.h" +#endif + +#include + +#define TCP_BUFSIZE_READ 16400 +#define TCP_OUTPUT_CAPACITY 1024000 + + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + +class SocketAddress; + + +/** Socket implementation for TCP. + \ingroup basic */ +class TcpSocket : public StreamSocket +{ + /** \defgroup internal Internal utility */ +protected: + /** Buffer class containing one read/write circular buffer. + \ingroup internal */ + class CircularBuffer + { + public: + CircularBuffer(size_t size); + ~CircularBuffer(); + + /** append l bytes from p to buffer */ + bool Write(const char *p,size_t l); + /** copy l bytes from buffer to dest */ + bool Read(char *dest,size_t l); + /** copy l bytes from buffer to dest, dont touch buffer pointers */ + bool SoftRead(char *dest, size_t l); + /** skip l bytes from buffer */ + bool Remove(size_t l); + /** read l bytes from buffer, returns as string. */ + std::string ReadString(size_t l); + + /** total buffer length */ + size_t GetLength(); + /** pointer to circular buffer beginning */ + const char *GetStart(); + /** return number of bytes from circular buffer beginning to buffer physical end */ + size_t GetL(); + /** return free space in buffer, number of bytes until buffer overrun */ + size_t Space(); + + /** return total number of bytes written to this buffer, ever */ + unsigned long ByteCounter(bool clear = false); + + private: + CircularBuffer(const CircularBuffer& /*s*/) {} + CircularBuffer& operator=(const CircularBuffer& ) { return *this; } + char *buf; + size_t m_max; + size_t m_q; + size_t m_b; + size_t m_t; + unsigned long m_count; + }; + /** Output buffer struct. + \ingroup internal */ + struct OUTPUT { + OUTPUT() : _b(0), _t(0), _q(0) {} + OUTPUT(const char *buf, size_t len) : _b(0), _t(len), _q(len) { + memcpy(_buf, buf, len); + } + size_t Space() { + return TCP_OUTPUT_CAPACITY - _t; + } + void Add(const char *buf, size_t len) { + memcpy(_buf + _t, buf, len); + _t += len; + _q += len; + } + size_t Remove(size_t len) { + _b += len; + _q -= len; + return _q; + } + const char *Buf() { + return _buf + _b; + } + size_t Len() { + return _q; + } + size_t _b; + size_t _t; + size_t _q; + char _buf[TCP_OUTPUT_CAPACITY]; + }; + typedef std::list output_l; + +public: + /** Constructor with standard values on input/output buffers. */ + TcpSocket(ISocketHandler& ); + /** Constructor with custom values for i/o buffer. + \param h ISocketHandler reference + \param isize Input buffer size + \param osize Output buffer size */ + TcpSocket(ISocketHandler& h,size_t isize,size_t osize); + ~TcpSocket(); + + /** Open a connection to a remote server. + If you want your socket to connect to a server, + always call Open before Add'ing a socket to the sockethandler. + If not, the connection attempt will not be monitored by the + socket handler... + \param ip IP address + \param port Port number + \param skip_socks Do not use socks4 even if configured */ + bool Open(ipaddr_t ip,port_t port,bool skip_socks = false); +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + /** Open connection. + \param ip Ipv6 address + \param port Port number + \param skip_socks Do not use socks4 even if configured */ + bool Open(in6_addr ip,port_t port,bool skip_socks = false); +#endif +#endif + bool Open(SocketAddress&,bool skip_socks = false); + bool Open(SocketAddress&,SocketAddress& bind_address,bool skip_socks = false); + /** Open connection. + \param host Hostname + \param port Port number */ + bool Open(const std::string &host,port_t port); + + /** Connect timeout callback. */ + void OnConnectTimeout(); +#ifdef _WIN32 + /** Connection failed reported as exception on win32 */ + void OnException(); +#endif + + /** Close file descriptor - internal use only. + \sa SetCloseAndDelete */ + int Close(); + + /** Send a string. + \param s String to send + \param f Dummy flags -- not used */ + void Send(const std::string &s,int f = 0); + /** Send string using printf formatting. */ + void Sendf(const char *format, ...); + /** Send buffer of bytes. + \param buf Buffer pointer + \param len Length of data + \param f Dummy flags -- not used */ + void SendBuf(const char *buf,size_t len,int f = 0); + /** This callback is executed after a successful read from the socket. + \param buf Pointer to the data + \param len Length of the data */ + virtual void OnRawData(const char *buf,size_t len); + + /** Called when output buffer has been sent. + Note: Will only be called IF the output buffer has been used. + Send's that was successful without needing the output buffer + will not generate a call to this method. */ + virtual void OnWriteComplete(); + /** Number of bytes in input buffer. */ + size_t GetInputLength(); + /** Number of bytes in output buffer. */ + size_t GetOutputLength(); + + /** Callback fires when a socket in line protocol has read one full line. + \param line Line read */ + void OnLine(const std::string& line); + /** Get counter of number of bytes received. */ + uint64_t GetBytesReceived(bool clear = false); + /** Get counter of number of bytes sent. */ + uint64_t GetBytesSent(bool clear = false); + + /** Socks4 specific callback. */ + void OnSocks4Connect(); + /** Socks4 specific callback. */ + void OnSocks4ConnectFailed(); + /** Socks4 specific callback. + \return 'need_more' */ + bool OnSocks4Read(); + +#ifdef ENABLE_RESOLVER + /** Callback executed when resolver thread has finished a resolve request. */ + void OnResolved(int id,ipaddr_t a,port_t port); +#ifdef ENABLE_IPV6 + void OnResolved(int id,in6_addr& a,port_t port); +#endif +#endif +#ifdef HAVE_OPENSSL + /** Callback for 'New' ssl support - replaces SSLSocket. Internal use. */ + void OnSSLConnect(); + /** Callback for 'New' ssl support - replaces SSLSocket. Internal use. */ + void OnSSLAccept(); + /** This method must be implemented to initialize + the ssl context for an outgoing connection. */ + virtual void InitSSLClient(); + /** This method must be implemented to initialize + the ssl context for an incoming connection. */ + virtual void InitSSLServer(); +#endif + +#ifdef ENABLE_RECONNECT + /** Flag that says a broken connection will try to reconnect. */ + void SetReconnect(bool = true); + /** Check reconnect on lost connection flag status. */ + bool Reconnect(); + /** Flag to determine if a reconnect is in progress. */ + void SetIsReconnect(bool x = true); + /** Socket is reconnecting. */ + bool IsReconnect(); +#endif + + void DisableInputBuffer(bool = true); + + void OnOptions(int,int,int,SOCKET); + + void SetLineProtocol(bool = true); + + // TCP options + bool SetTcpNodelay(bool = true); + + virtual int Protocol(); + + /** Trigger limit for callback OnTransferLimit. */ + void SetTransferLimit(size_t sz); + /** This callback fires when the output buffer drops below the value + set by SetTransferLimit. Default: 0 (disabled). */ + virtual void OnTransferLimit(); + +protected: + TcpSocket(const TcpSocket& ); + void OnRead(); + void OnRead( char *buf, size_t n ); + void OnWrite(); +#ifdef HAVE_OPENSSL + /** SSL; Initialize ssl context for a client socket. + \param meth_in SSL method */ + void InitializeContext(const std::string& context, SSL_METHOD *meth_in = NULL); + /** SSL; Initialize ssl context for a server socket. + \param keyfile Combined private key/certificate file + \param password Password for private key + \param meth_in SSL method */ + void InitializeContext(const std::string& context, const std::string& keyfile, const std::string& password, SSL_METHOD *meth_in = NULL); + /** SSL; Initialize ssl context for a server socket. + \param certfile Separate certificate file + \param keyfile Combined private key/certificate file + \param password Password for private key + \param meth_in SSL method */ + void InitializeContext(const std::string& context, const std::string& certfile, const std::string& keyfile, const std::string& password, SSL_METHOD *meth_in = NULL); + /** SSL; Password callback method. */ +static int SSL_password_cb(char *buf,int num,int rwflag,void *userdata); + /** SSL; Get pointer to ssl context structure. */ + virtual SSL_CTX *GetSslContext(); + /** SSL; Get pointer to ssl structure. */ + virtual SSL *GetSsl(); + /** ssl; still negotiating connection. */ + bool SSLNegotiate(); + /** SSL; Get ssl password. */ + const std::string& GetPassword(); +#endif + + CircularBuffer ibuf; ///< Circular input buffer + +private: + TcpSocket& operator=(const TcpSocket& ) { return *this; } + + /** the actual send() */ + int TryWrite(const char *buf, size_t len); + /** add data to output buffer top */ + void Buffer(const char *buf, size_t len); + + // + bool m_b_input_buffer_disabled; + uint64_t m_bytes_sent; + uint64_t m_bytes_received; + bool m_skip_c; ///< Skip second char of CRLF or LFCR sequence in OnRead + char m_c; ///< First char in CRLF or LFCR sequence + std::string m_line; ///< Current line in line protocol mode +#ifdef SOCKETS_DYNAMIC_TEMP + char *m_buf; ///< temporary read buffer +#endif + output_l m_obuf; ///< output buffer + OUTPUT *m_obuf_top; ///< output buffer on top + size_t m_transfer_limit; + size_t m_output_length; + +#ifdef HAVE_OPENSSL +static SSLInitializer m_ssl_init; + SSL_CTX *m_ssl_ctx; ///< ssl context + SSL *m_ssl; ///< ssl 'socket' + BIO *m_sbio; ///< ssl bio + std::string m_password; ///< ssl password +#endif + +#ifdef ENABLE_SOCKS4 + int m_socks4_state; ///< socks4 support + char m_socks4_vn; ///< socks4 support, temporary variable + char m_socks4_cd; ///< socks4 support, temporary variable + unsigned short m_socks4_dstport; ///< socks4 support + unsigned long m_socks4_dstip; ///< socks4 support +#endif + +#ifdef ENABLE_RESOLVER + int m_resolver_id; ///< Resolver id (if any) for current Open call +#endif + +#ifdef ENABLE_RECONNECT + bool m_b_reconnect; ///< Reconnect on lost connection flag + bool m_b_is_reconnect; ///< Trying to reconnect +#endif + +}; + + +#ifdef SOCKETS_NAMESPACE +} +#endif + +#endif // _SOCKETS_TcpSocket_H + diff --git a/dep/include/sockets/Thread.h b/dep/include/sockets/Thread.h new file mode 100644 index 00000000000..d784a1594f6 --- /dev/null +++ b/dep/include/sockets/Thread.h @@ -0,0 +1,100 @@ +/** \file Thread.h + ** \date 2004-10-30 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2004-2007 Anders Hedstrom + +This library is made available under the terms of the GNU GPL. + +If you would like to use this library in a closed-source application, +a separate license agreement is available. For information about +the closed-source license agreement for the C++ sockets library, +please visit http://www.alhem.net/Sockets/license.html and/or +email license@alhem.net. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef _SOCKETS_Thread_H +#define _SOCKETS_Thread_H + +#include "sockets-config.h" +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + +#ifdef _WIN32 +// to be +//typedef DWORD threadfunc_t; +//typedef LPVOID threadparam_t; +//#define STDPREFIX WINAPI +typedef unsigned threadfunc_t; +typedef void * threadparam_t; +#define STDPREFIX __stdcall +#else +#include + +typedef void * threadfunc_t; +typedef void * threadparam_t; +#define STDPREFIX +#endif + +/** \defgroup threading Threading */ +/** Thread base class. +The Thread class is used by the resolver (ResolvServer) and running a detached socket (SocketThread). +When you know some processing will take a long time and will freeze up a socket, there is always the +possibility to call Detach() on that socket before starting the processing. +When the OnDetached() callback is later called the processing can continue, now in its own thread. + \ingroup threading */ +class Thread +{ +public: + Thread(bool release = true); + virtual ~Thread(); + + static threadfunc_t STDPREFIX StartThread(threadparam_t); + + virtual void Run() = 0; + + bool IsRunning(); + void SetRunning(bool x); + bool IsReleased(); + void SetRelease(bool x); + bool DeleteOnExit(); + void SetDeleteOnExit(bool x = true); + bool IsDestructor(); + +private: + Thread(const Thread& ) {} + Thread& operator=(const Thread& ) { return *this; } +#ifdef _WIN32 + HANDLE m_thread; + unsigned m_dwThreadId; +#else + pthread_t m_thread; +#endif + bool m_running; + bool m_release; + bool m_b_delete_on_exit; + bool m_b_destructor; +}; + + +#ifdef SOCKETS_NAMESPACE +} +#endif + +#endif // _SOCKETS_Thread_H + diff --git a/dep/include/sockets/UdpSocket.h b/dep/include/sockets/UdpSocket.h new file mode 100644 index 00000000000..d32aabf67aa --- /dev/null +++ b/dep/include/sockets/UdpSocket.h @@ -0,0 +1,215 @@ +/** \file UdpSocket.h + ** \date 2004-02-13 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2004-2007 Anders Hedstrom + +This library is made available under the terms of the GNU GPL. + +If you would like to use this library in a closed-source application, +a separate license agreement is available. For information about +the closed-source license agreement for the C++ sockets library, +please visit http://www.alhem.net/Sockets/license.html and/or +email license@alhem.net. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef _SOCKETS_UdpSocket_H +#define _SOCKETS_UdpSocket_H + +#include "sockets-config.h" +#include "Socket.h" + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + +/** Socket implementation for UDP. + \ingroup basic */ +class UdpSocket : public Socket +{ +public: + /** Constructor. + \param h ISocketHandler reference + \param ibufsz Maximum size of receive message (extra bytes will be truncated) + \param ipv6 'true' if this is an ipv6 socket */ + UdpSocket(ISocketHandler& h,int ibufsz = 16384,bool ipv6 = false, int retries = 0); + ~UdpSocket(); + + /** Called when incoming data has been received. + \param buf Pointer to data + \param len Length of data + \param sa Pointer to sockaddr struct of sender + \param sa_len Length of sockaddr struct */ + virtual void OnRawData(const char *buf,size_t len,struct sockaddr *sa,socklen_t sa_len); + + /** Called when incoming data has been received and read timestamp is enabled. + \param buf Pointer to data + \param len Length of data + \param sa Pointer to sockaddr struct of sender + \param sa_len Length of sockaddr struct + \param ts Timestamp from message */ + virtual void OnRawData(const char *buf,size_t len,struct sockaddr *sa,socklen_t sa_len,struct timeval *ts); + + /** To receive incoming data, call Bind to setup an incoming port. + \param port Incoming port number + \param range Port range to try if ports already in use + \return 0 if bind succeeded */ + int Bind(port_t& port,int range = 1); + /** To receive data on a specific interface:port, use this. + \param intf Interface ip/hostname + \param port Port number + \param range Port range + \return 0 if bind succeeded */ + int Bind(const std::string& intf,port_t& port,int range = 1); + /** To receive data on a specific interface:port, use this. + \param a Ip address + \param port Port number + \param range Port range + \return 0 if bind succeeded */ + int Bind(ipaddr_t a,port_t& port,int range = 1); +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + /** To receive data on a specific interface:port, use this. + \param a Ipv6 address + \param port Port number + \param range Port range + \return 0 if bind succeeded */ + int Bind(in6_addr a,port_t& port,int range = 1); +#endif +#endif + /** To receive data on a specific interface:port, use this. + \param ad Socket address + \param range Port range + \return 0 if bind succeeded */ + int Bind(SocketAddress& ad,int range = 1); + + /** Define remote host. + \param l Address of remote host + \param port Port of remote host + \return true if successful */ + bool Open(ipaddr_t l,port_t port); + /** Define remote host. + \param host Hostname + \param port Port number + \return true if successful */ + bool Open(const std::string& host,port_t port); +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + /** Define remote host. + \param a Address of remote host, ipv6 + \param port Port of remote host + \return true if successful */ + bool Open(struct in6_addr& a,port_t port); +#endif +#endif + /** Define remote host. + \param ad Socket address + \return true if successful */ + bool Open(SocketAddress& ad); + + /** Send to specified host */ + void SendToBuf(const std::string& ,port_t,const char *data,int len,int flags = 0); + /** Send to specified address */ + void SendToBuf(ipaddr_t,port_t,const char *data,int len,int flags = 0); +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + /** Send to specified ipv6 address */ + void SendToBuf(in6_addr,port_t,const char *data,int len,int flags = 0); +#endif +#endif + /** Send to specified socket address */ + void SendToBuf(SocketAddress& ad,const char *data,int len,int flags = 0); + + /** Send string to specified host */ + void SendTo(const std::string&,port_t,const std::string&,int flags = 0); + /** Send string to specified address */ + void SendTo(ipaddr_t,port_t,const std::string&,int flags = 0); +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + /** Send string to specified ipv6 address */ + void SendTo(in6_addr,port_t,const std::string&,int flags = 0); +#endif +#endif + /** Send string to specified socket address */ + void SendTo(SocketAddress& ad,const std::string&,int flags = 0); + + /** Send to connected address */ + void SendBuf(const char *data,size_t,int flags = 0); + /** Send string to connected address. */ + void Send(const std::string& ,int flags = 0); + + /** Set broadcast */ + void SetBroadcast(bool b = true); + /** Check broadcast flag. + \return true broadcast is enabled. */ + bool IsBroadcast(); + + /** multicast */ + void SetMulticastTTL(int ttl = 1); + int GetMulticastTTL(); + void SetMulticastLoop(bool = true); + bool IsMulticastLoop(); + void AddMulticastMembership(const std::string& group,const std::string& intf = "0.0.0.0",int if_index = 0); + void DropMulticastMembership(const std::string& group,const std::string& intf = "0.0.0.0",int if_index = 0); +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + /** multicast, ipv6 only */ + void SetMulticastHops(int = -1); + /** multicast, ipv6 only */ + int GetMulticastHops(); +#endif +#endif + /** Returns true if Bind succeeded. */ + bool IsBound(); + /** Return Bind port number */ + port_t GetPort(); + + void OnOptions(int,int,int,SOCKET) {} + + int GetLastSizeWritten(); + + /** Also read timestamp information from incoming message */ + void SetTimestamp(bool = true); + +protected: + UdpSocket(const UdpSocket& s) : Socket(s) {} + void OnRead(); +#if defined(LINUX) || defined(MACOSX) + /** This method emulates socket recvfrom, but uses messages so we can get the timestamp */ + int ReadTS(char *ioBuf, int inBufSize, struct sockaddr *from, socklen_t fromlen, struct timeval *ts); +#endif + +private: + UdpSocket& operator=(const UdpSocket& ) { return *this; } + /** create before using sendto methods */ + void CreateConnection(); + char *m_ibuf; ///< Input buffer + int m_ibufsz; ///< Size of input buffer + bool m_bind_ok; ///< Bind completed successfully + port_t m_port; ///< Bind port number + int m_last_size_written; + int m_retries; + bool m_b_read_ts; +}; + + +#ifdef SOCKETS_NAMESPACE +} +#endif + +#endif // _SOCKETS_UdpSocket_H + diff --git a/dep/include/sockets/Utility.h b/dep/include/sockets/Utility.h new file mode 100644 index 00000000000..0fbccd3dfa3 --- /dev/null +++ b/dep/include/sockets/Utility.h @@ -0,0 +1,186 @@ +/** \file Utility.h + ** \date 2004-02-13 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2004-2007 Anders Hedstrom + +This library is made available under the terms of the GNU GPL. + +If you would like to use this library in a closed-source application, +a separate license agreement is available. For information about +the closed-source license agreement for the C++ sockets library, +please visit http://www.alhem.net/Sockets/license.html and/or +email license@alhem.net. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef _SOCKETS_Utility_H +#define _SOCKETS_Utility_H + +#include "sockets-config.h" +#include +#include +#include +#include "socket_include.h" +#include +#include + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + +#define TWIST_LEN 624 + +class SocketAddress; + +/** Conversion utilities. + \ingroup util */ +class Utility +{ + /** + The Mersenne Twister + http://www.math.keio.ac.jp/~matumoto/emt.html + */ + class Rng { + public: + Rng(unsigned long seed); + + unsigned long Get(); + + private: + int m_value; + unsigned long m_tmp[TWIST_LEN]; + }; + class ncmap_compare { + public: + bool operator()(const std::string& x, const std::string& y) const { + return strcasecmp(x.c_str(), y.c_str()) < 0; + } + }; +public: + template class ncmap : public std::map { + public: + ncmap() {} + }; +public: + static std::string base64(const std::string& str_in); + static std::string base64d(const std::string& str_in); + static std::string l2string(long l); + static std::string bigint2string(uint64_t l); + static uint64_t atoi64(const std::string& str); + static unsigned int hex2unsigned(const std::string& str); + static std::string rfc1738_encode(const std::string& src); + static std::string rfc1738_decode(const std::string& src); + + /** Checks whether a string is a valid ipv4/ipv6 ip number. */ + static bool isipv4(const std::string&); + /** Checks whether a string is a valid ipv4/ipv6 ip number. */ + static bool isipv6(const std::string&); + + /** Hostname to ip resolution ipv4, not asynchronous. */ + static bool u2ip(const std::string&, ipaddr_t&); + static bool u2ip(const std::string&, struct sockaddr_in& sa, int ai_flags = 0); + +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + /** Hostname to ip resolution ipv6, not asynchronous. */ + static bool u2ip(const std::string&, struct in6_addr&); + static bool u2ip(const std::string&, struct sockaddr_in6& sa, int ai_flags = 0); +#endif +#endif + + /** Reverse lookup of address to hostname */ + static bool reverse(struct sockaddr *sa, socklen_t sa_len, std::string&, int flags = 0); + static bool reverse(struct sockaddr *sa, socklen_t sa_len, std::string& hostname, std::string& service, int flags = 0); + + static bool u2service(const std::string& name, int& service, int ai_flags = 0); + + /** Convert binary ip address to string: ipv4. */ + static void l2ip(const ipaddr_t,std::string& ); + static void l2ip(const in_addr&,std::string& ); +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + /** Convert binary ip address to string: ipv6. */ + static void l2ip(const struct in6_addr&,std::string& ,bool mixed = false); + + /** ipv6 address compare. */ + static int in6_addr_compare(in6_addr,in6_addr); +#endif +#endif + /** ResolveLocal (hostname) - call once before calling any GetLocal method. */ + static void ResolveLocal(); + /** Returns local hostname, ResolveLocal must be called once before using. + \sa ResolveLocal */ + static const std::string& GetLocalHostname(); + /** Returns local ip, ResolveLocal must be called once before using. + \sa ResolveLocal */ + static ipaddr_t GetLocalIP(); + /** Returns local ip number as string. + \sa ResolveLocal */ + static const std::string& GetLocalAddress(); +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + /** Returns local ipv6 ip. + \sa ResolveLocal */ + static const struct in6_addr& GetLocalIP6(); + /** Returns local ipv6 address. + \sa ResolveLocal */ + static const std::string& GetLocalAddress6(); +#endif +#endif + /** Set environment variable. + \param var Name of variable to set + \param value Value */ + static void SetEnv(const std::string& var,const std::string& value); + /** Convert sockaddr struct to human readable string. + \param sa Ptr to sockaddr struct */ + static std::string Sa2String(struct sockaddr *sa); + + /** Get current time in sec/microseconds. */ + static void GetTime(struct timeval *); + + static std::auto_ptr CreateAddress(struct sockaddr *,socklen_t); + + static unsigned long ThreadID(); + + static std::string ToLower(const std::string& str); + static std::string ToUpper(const std::string& str); + + static std::string ToString(double d); + + /** Returns a random 32-bit integer */ + static unsigned long Rnd(); + +private: + static std::string m_host; ///< local hostname + static ipaddr_t m_ip; ///< local ip address + static std::string m_addr; ///< local ip address in string format +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + static struct in6_addr m_local_ip6; ///< local ipv6 address +#endif + static std::string m_local_addr6; ///< local ipv6 address in string format +#endif + static bool m_local_resolved; ///< ResolveLocal has been called if true +}; + + +#ifdef SOCKETS_NAMESPACE +} +#endif + +#endif // _SOCKETS_Utility_H + diff --git a/dep/include/sockets/socket_include.h b/dep/include/sockets/socket_include.h new file mode 100644 index 00000000000..34e7a8ca5d1 --- /dev/null +++ b/dep/include/sockets/socket_include.h @@ -0,0 +1,299 @@ +/** \file socket_include.h + ** \date 2005-04-12 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2004-2007 Anders Hedstrom + +This library is made available under the terms of the GNU GPL. + +If you would like to use this library in a closed-source application, +a separate license agreement is available. For information about +the closed-source license agreement for the C++ sockets library, +please visit http://www.alhem.net/Sockets/license.html and/or +email license@alhem.net. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef _SOCKETS_socket_include_H +#define _SOCKETS_socket_include_H +#include "sockets-config.h" + +#ifdef _MSC_VER +#pragma warning(disable:4514) +#endif + +// common defines affecting library and applications using library + +/* Define SOCKETS_DYNAMIC_TEMP to use dynamically allocated buffers + in read operations - helps on ECOS */ +#define SOCKETS_DYNAMIC_TEMP + + +// platform specific stuff +#if (defined(__unix__) || defined(unix)) && !defined(USG) +#include +#endif +#include + +// int64 +#ifdef _WIN32 +typedef unsigned __int64 uint64_t; +#else +#include +#ifdef SOLARIS +# include +#else +# include +#endif +#endif + +#ifndef _WIN32 +// ---------------------------------------- +// common unix includes / defines +#include +#include +#include +#include +#include +#include +//#include + +// all typedefs in this file will be declared outside the sockets namespace, +// because some os's will already have one or more of the type defined. +typedef int SOCKET; +#define Errno errno +#define StrError strerror + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + + +// WIN32 adapt +#define closesocket close +#define INVALID_SOCKET -1 +#define SOCKET_ERROR -1 + +#ifndef INADDR_NONE +#define INADDR_NONE ((unsigned long) -1) +#endif // INADDR_NONE + +#ifdef SOCKETS_NAMESPACE +} +#endif + +#endif // !_WIN32 + + +// ---------------------------------------- +// Generic +#ifndef SOL_IP +#define SOL_IP IPPROTO_IP +#endif + + +// ---------------------------------------- +// OS specific adaptions + +#ifdef SOLARIS +// ---------------------------------------- +// Solaris +typedef unsigned short port_t; +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif +// no defs + +#ifdef SOCKETS_NAMESPACE +} +#endif + +#define s6_addr16 _S6_un._S6_u8 +#define MSG_NOSIGNAL 0 + +#elif defined __FreeBSD__ +// ---------------------------------------- +// FreeBSD +# if __FreeBSD_version >= 400014 +# define s6_addr16 __u6_addr.__u6_addr16 +# if !defined(MSG_NOSIGNAL) +# define MSG_NOSIGNAL 0 +# endif +# include +typedef in_addr_t ipaddr_t; +typedef in_port_t port_t; +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif +// no defs + +#ifdef SOCKETS_NAMESPACE +} +#endif + +# define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP +# define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP +# else +# error FreeBSD versions prior to 400014 does not support ipv6 +# endif + +#elif defined __NetBSD__ +# if !defined(MSG_NOSIGNAL) +# define MSG_NOSIGNAL 0 +# endif +# include +typedef in_addr_t ipaddr_t; +typedef in_port_t port_t; +#elif defined MACOSX +// ---------------------------------------- +// Mac OS X +#include +#ifdef __DARWIN_UNIX03 +typedef unsigned short port_t; +#else +#include +#endif // __DARWIN_UNIX03 +typedef unsigned long ipaddr_t; +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif +// no defs + +#ifdef SOCKETS_NAMESPACE +} +#endif + +#define s6_addr16 __u6_addr.__u6_addr16 +#define MSG_NOSIGNAL 0 // oops - thanks Derek +#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP +#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP + +#elif defined _WIN32 +// ---------------------------------------- +// Win32 +#ifdef _MSC_VER +#pragma comment(lib, "wsock32.lib") +#endif +#define strcasecmp _stricmp + +typedef unsigned long ipaddr_t; +typedef unsigned short port_t; +typedef int socklen_t; +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif +// no defs + +#ifdef SOCKETS_NAMESPACE +} +#endif + +// 1.8.6: define FD_SETSIZE to something bigger than 64 if there are a lot of +// simultaneous connections (must be done before including winsock.h) +#define FD_SETSIZE 1024 + +// windows 2000 with ipv6 preview installed: +// http://msdn.microsoft.com/downloads/sdks/platform/tpipv6.asp +// see the FAQ on how to install +#define WIN32_LEAN_AND_MEAN +#include +#include +#if _MSC_VER < 1200 +#ifndef __CYGWIN__ +#ifdef ENABLE_IPV6 +#include // For IPv6 Tech Preview. +#endif +#endif +#endif // _MSC_VER < 1200 + + +#define MSG_NOSIGNAL 0 +//#define SHUT_RDWR 2 +#define SHUT_WR 1 + +#define Errno WSAGetLastError() +const char *StrError(int x); + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + + +// class WSAInitializer is a part of the Socket class (on win32) +// as a static instance - so whenever an application uses a Socket, +// winsock is initialized +class WSAInitializer // Winsock Initializer +{ +public: + WSAInitializer() { + if (WSAStartup(0x101,&m_wsadata)) + { + exit(-1); + } + } + ~WSAInitializer() { + WSACleanup(); + } +private: + WSADATA m_wsadata; +}; + +#ifdef SOCKETS_NAMESPACE +} +#endif + +#else +// ---------------------------------------- +// LINUX +typedef unsigned long ipaddr_t; +typedef unsigned short port_t; +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif +// no defs + +#ifdef SOCKETS_NAMESPACE +} +#endif + + +#endif + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + /** List type containing file descriptors. */ + typedef std::list socket_v; + + +#ifdef SOCKETS_NAMESPACE +} +#endif + + +// getaddrinfo / getnameinfo replacements +#ifdef NO_GETADDRINFO +#ifndef AI_NUMERICHOST +#define AI_NUMERICHOST 1 +#endif +#ifndef NI_NUMERICHOST +#define NI_NUMERICHOST 1 +#endif +#endif + + +#endif // _SOCKETS_socket_include_H + diff --git a/dep/include/sockets/sockets-config.h b/dep/include/sockets/sockets-config.h new file mode 100644 index 00000000000..fffc2bbe7f1 --- /dev/null +++ b/dep/include/sockets/sockets-config.h @@ -0,0 +1,101 @@ +/** + ** \file sockets-config.h + ** \date 2007-04-14 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2007 Anders Hedstrom + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef _SOCKETS_CONFIG_H +#define _SOCKETS_CONFIG_H + +#ifndef _RUN_DP +/* First undefine symbols if already defined. */ +#undef HAVE_OPENSSL +#undef ENABLE_IPV6 +#undef USE_SCTP +#undef NO_GETADDRINFO +#undef ENABLE_POOL +#undef ENABLE_SOCKS4 +#undef ENABLE_RESOLVER +#undef ENABLE_RECONNECT +#undef ENABLE_DETACH +#undef ENABLE_TRIGGERS +#undef ENABLE_EXCEPTIONS +#endif // _RUN_DP + +// define MACOSX for internal socket library checks +#if defined(__APPLE__) && defined(__MACH__) && !defined(MACOSX) +#define MACOSX +#endif + +/* OpenSSL support. */ +//#define HAVE_OPENSSL + + +/* Ipv6 support. */ +//#define ENABLE_IPV6 + + +/* SCTP support. */ +//#define USE_SCTP + + +/* Define NO_GETADDRINFO if your operating system does not support + the "getaddrinfo" and "getnameinfo" function calls. */ +#define NO_GETADDRINFO + + +/* Connection pool support. */ +#define ENABLE_POOL + + +/* Socks4 client support. */ +//#define ENABLE_SOCKS4 + + +/* Asynchronous resolver. */ +#define ENABLE_RESOLVER + + +/* Enable TCP reconnect on lost connection. + Socket::OnReconnect + Socket::OnDisconnect +*/ +#define ENABLE_RECONNECT + + +/* Enable socket thread detach functionality. */ +#define ENABLE_DETACH + + +/* Enable socket to socket triggers. Not yet in use. */ +//#define ENABLE_TRIGGERS + + +/* Enabled exceptions. */ +//#define ENABLE_EXCEPTIONS + + +/* Resolver uses the detach function so either enable both or disable both. */ +#ifndef ENABLE_DETACH +#undef ENABLE_RESOLVER +#endif + + +#endif // _SOCKETS_CONFIG_H + diff --git a/dep/include/sqlite/sqlite.h b/dep/include/sqlite/sqlite.h new file mode 100644 index 00000000000..f9690d0583f --- /dev/null +++ b/dep/include/sqlite/sqlite.h @@ -0,0 +1,834 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This header file defines the interface that the SQLite library +** presents to client programs. +** +** @(#) $Id: sqlite.h,v 1.3 2004/06/29 01:57:36 silent Exp $ +*/ +#ifndef _SQLITE_H_ +#define _SQLITE_H_ +#include /* Needed for the definition of va_list */ + +/* +** Make sure we can call this stuff from C++. +*/ +#ifdef __cplusplus +extern "C" { +#endif + +/* +** The version of the SQLite library. +*/ +#define SQLITE_VERSION "2.8.13" + +/* +** The version string is also compiled into the library so that a program +** can check to make sure that the lib*.a file and the *.h file are from +** the same version. +*/ +extern const char sqlite_version[]; + +/* +** The SQLITE_UTF8 macro is defined if the library expects to see +** UTF-8 encoded data. The SQLITE_ISO8859 macro is defined if the +** iso8859 encoded should be used. +*/ +#define SQLITE_ISO8859 1 + +/* +** The following constant holds one of two strings, "UTF-8" or "iso8859", +** depending on which character encoding the SQLite library expects to +** see. The character encoding makes a difference for the LIKE and GLOB +** operators and for the LENGTH() and SUBSTR() functions. +*/ +extern const char sqlite_encoding[]; + +/* +** Each open sqlite database is represented by an instance of the +** following opaque structure. +*/ +typedef struct sqlite sqlite; + +/* +** A function to open a new sqlite database. +** +** If the database does not exist and mode indicates write +** permission, then a new database is created. If the database +** does not exist and mode does not indicate write permission, +** then the open fails, an error message generated (if errmsg!=0) +** and the function returns 0. +** +** If mode does not indicates user write permission, then the +** database is opened read-only. +** +** The Truth: As currently implemented, all databases are opened +** for writing all the time. Maybe someday we will provide the +** ability to open a database readonly. The mode parameters is +** provided in anticipation of that enhancement. +*/ +sqlite *sqlite_open(const char *filename, int mode, char **errmsg); + +/* +** A function to close the database. +** +** Call this function with a pointer to a structure that was previously +** returned from sqlite_open() and the corresponding database will by closed. +*/ +void sqlite_close(sqlite *); + +/* +** The type for a callback function. +*/ +typedef int (*sqlite_callback)(void*,int,char**, char**); + +/* +** A function to executes one or more statements of SQL. +** +** If one or more of the SQL statements are queries, then +** the callback function specified by the 3rd parameter is +** invoked once for each row of the query result. This callback +** should normally return 0. If the callback returns a non-zero +** value then the query is aborted, all subsequent SQL statements +** are skipped and the sqlite_exec() function returns the SQLITE_ABORT. +** +** The 4th parameter is an arbitrary pointer that is passed +** to the callback function as its first parameter. +** +** The 2nd parameter to the callback function is the number of +** columns in the query result. The 3rd parameter to the callback +** is an array of strings holding the values for each column. +** The 4th parameter to the callback is an array of strings holding +** the names of each column. +** +** The callback function may be NULL, even for queries. A NULL +** callback is not an error. It just means that no callback +** will be invoked. +** +** If an error occurs while parsing or evaluating the SQL (but +** not while executing the callback) then an appropriate error +** message is written into memory obtained from malloc() and +** *errmsg is made to point to that message. The calling function +** is responsible for freeing the memory that holds the error +** message. Use sqlite_freemem() for this. If errmsg==NULL, +** then no error message is ever written. +** +** The return value is is SQLITE_OK if there are no errors and +** some other return code if there is an error. The particular +** return value depends on the type of error. +** +** If the query could not be executed because a database file is +** locked or busy, then this function returns SQLITE_BUSY. (This +** behavior can be modified somewhat using the sqlite_busy_handler() +** and sqlite_busy_timeout() functions below.) +*/ +int sqlite_exec( + sqlite*, /* An open database */ + const char *sql, /* SQL to be executed */ + sqlite_callback, /* Callback function */ + void *, /* 1st argument to callback function */ + char **errmsg /* Error msg written here */ +); + +/* +** Return values for sqlite_exec() and sqlite_step() +*/ +#define SQLITE_OK 0 /* Successful result */ +#define SQLITE_ERROR 1 /* SQL error or missing database */ +#define SQLITE_INTERNAL 2 /* An internal logic error in SQLite */ +#define SQLITE_PERM 3 /* Access permission denied */ +#define SQLITE_ABORT 4 /* Callback routine requested an abort */ +#define SQLITE_BUSY 5 /* The database file is locked */ +#define SQLITE_LOCKED 6 /* A table in the database is locked */ +#define SQLITE_NOMEM 7 /* A malloc() failed */ +#define SQLITE_READONLY 8 /* Attempt to write a readonly database */ +#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite_interrupt() */ +#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */ +#define SQLITE_CORRUPT 11 /* The database disk image is malformed */ +#define SQLITE_NOTFOUND 12 /* (Internal Only) Table or record not found */ +#define SQLITE_FULL 13 /* Insertion failed because database is full */ +#define SQLITE_CANTOPEN 14 /* Unable to open the database file */ +#define SQLITE_PROTOCOL 15 /* Database lock protocol error */ +#define SQLITE_EMPTY 16 /* (Internal Only) Database table is empty */ +#define SQLITE_SCHEMA 17 /* The database schema changed */ +#define SQLITE_TOOBIG 18 /* Too much data for one row of a table */ +#define SQLITE_CONSTRAINT 19 /* Abort due to contraint violation */ +#define SQLITE_MISMATCH 20 /* Data type mismatch */ +#define SQLITE_MISUSE 21 /* Library used incorrectly */ +#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ +#define SQLITE_AUTH 23 /* Authorization denied */ +#define SQLITE_FORMAT 24 /* Auxiliary database format error */ +#define SQLITE_RANGE 25 /* 2nd parameter to sqlite_bind out of range */ +#define SQLITE_NOTADB 26 /* File opened that is not a database file */ +#define SQLITE_ROW 100 /* sqlite_step() has another row ready */ +#define SQLITE_DONE 101 /* sqlite_step() has finished executing */ + +/* +** Each entry in an SQLite table has a unique integer key. (The key is +** the value of the INTEGER PRIMARY KEY column if there is such a column, +** otherwise the key is generated at random. The unique key is always +** available as the ROWID, OID, or _ROWID_ column.) The following routine +** returns the integer key of the most recent insert in the database. +** +** This function is similar to the mysql_insert_id() function from MySQL. +*/ +int sqlite_last_insert_rowid(sqlite*); + +/* +** This function returns the number of database rows that were changed +** (or inserted or deleted) by the most recent called sqlite_exec(). +** +** All changes are counted, even if they were later undone by a +** ROLLBACK or ABORT. Except, changes associated with creating and +** dropping tables are not counted. +** +** If a callback invokes sqlite_exec() recursively, then the changes +** in the inner, recursive call are counted together with the changes +** in the outer call. +** +** SQLite implements the command "DELETE FROM table" without a WHERE clause +** by dropping and recreating the table. (This is much faster than going +** through and deleting individual elements form the table.) Because of +** this optimization, the change count for "DELETE FROM table" will be +** zero regardless of the number of elements that were originally in the +** table. To get an accurate count of the number of rows deleted, use +** "DELETE FROM table WHERE 1" instead. +*/ +int sqlite_changes(sqlite*); + +/* +** This function returns the number of database rows that were changed +** by the last INSERT, UPDATE, or DELETE statment executed by sqlite_exec(), +** or by the last VM to run to completion. The change count is not updated +** by SQL statements other than INSERT, UPDATE or DELETE. +** +** Changes are counted, even if they are later undone by a ROLLBACK or +** ABORT. Changes associated with trigger programs that execute as a +** result of the INSERT, UPDATE, or DELETE statement are not counted. +** +** If a callback invokes sqlite_exec() recursively, then the changes +** in the inner, recursive call are counted together with the changes +** in the outer call. +** +** SQLite implements the command "DELETE FROM table" without a WHERE clause +** by dropping and recreating the table. (This is much faster than going +** through and deleting individual elements form the table.) Because of +** this optimization, the change count for "DELETE FROM table" will be +** zero regardless of the number of elements that were originally in the +** table. To get an accurate count of the number of rows deleted, use +** "DELETE FROM table WHERE 1" instead. +** +******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ****** +*/ +int sqlite_last_statement_changes(sqlite*); + +/* If the parameter to this routine is one of the return value constants +** defined above, then this routine returns a constant text string which +** descripts (in English) the meaning of the return value. +*/ +const char *sqlite_error_string(int); +#define sqliteErrStr sqlite_error_string /* Legacy. Do not use in new code. */ + +/* This function causes any pending database operation to abort and +** return at its earliest opportunity. This routine is typically +** called in response to a user action such as pressing "Cancel" +** or Ctrl-C where the user wants a long query operation to halt +** immediately. +*/ +void sqlite_interrupt(sqlite*); + + +/* This function returns true if the given input string comprises +** one or more complete SQL statements. +** +** The algorithm is simple. If the last token other than spaces +** and comments is a semicolon, then return true. otherwise return +** false. +*/ +int sqlite_complete(const char *sql); + +/* +** This routine identifies a callback function that is invoked +** whenever an attempt is made to open a database table that is +** currently locked by another process or thread. If the busy callback +** is NULL, then sqlite_exec() returns SQLITE_BUSY immediately if +** it finds a locked table. If the busy callback is not NULL, then +** sqlite_exec() invokes the callback with three arguments. The +** second argument is the name of the locked table and the third +** argument is the number of times the table has been busy. If the +** busy callback returns 0, then sqlite_exec() immediately returns +** SQLITE_BUSY. If the callback returns non-zero, then sqlite_exec() +** tries to open the table again and the cycle repeats. +** +** The default busy callback is NULL. +** +** Sqlite is re-entrant, so the busy handler may start a new query. +** (It is not clear why anyone would every want to do this, but it +** is allowed, in theory.) But the busy handler may not close the +** database. Closing the database from a busy handler will delete +** data structures out from under the executing query and will +** probably result in a coredump. +*/ +void sqlite_busy_handler(sqlite*, int(*)(void*,const char*,int), void*); + +/* +** This routine sets a busy handler that sleeps for a while when a +** table is locked. The handler will sleep multiple times until +** at least "ms" milleseconds of sleeping have been done. After +** "ms" milleseconds of sleeping, the handler returns 0 which +** causes sqlite_exec() to return SQLITE_BUSY. +** +** Calling this routine with an argument less than or equal to zero +** turns off all busy handlers. +*/ +void sqlite_busy_timeout(sqlite*, int ms); + +/* +** This next routine is really just a wrapper around sqlite_exec(). +** Instead of invoking a user-supplied callback for each row of the +** result, this routine remembers each row of the result in memory +** obtained from malloc(), then returns all of the result after the +** query has finished. +** +** As an example, suppose the query result where this table: +** +** Name | Age +** ----------------------- +** Alice | 43 +** Bob | 28 +** Cindy | 21 +** +** If the 3rd argument were &azResult then after the function returns +** azResult will contain the following data: +** +** azResult[0] = "Name"; +** azResult[1] = "Age"; +** azResult[2] = "Alice"; +** azResult[3] = "43"; +** azResult[4] = "Bob"; +** azResult[5] = "28"; +** azResult[6] = "Cindy"; +** azResult[7] = "21"; +** +** Notice that there is an extra row of data containing the column +** headers. But the *nrow return value is still 3. *ncolumn is +** set to 2. In general, the number of values inserted into azResult +** will be ((*nrow) + 1)*(*ncolumn). +** +** After the calling function has finished using the result, it should +** pass the result data pointer to sqlite_free_table() in order to +** release the memory that was malloc-ed. Because of the way the +** malloc() happens, the calling function must not try to call +** malloc() directly. Only sqlite_free_table() is able to release +** the memory properly and safely. +** +** The return value of this routine is the same as from sqlite_exec(). +*/ +int sqlite_get_table( + sqlite*, /* An open database */ + const char *sql, /* SQL to be executed */ + char ***resultp, /* Result written to a char *[] that this points to */ + int *nrow, /* Number of result rows written here */ + int *ncolumn, /* Number of result columns written here */ + char **errmsg /* Error msg written here */ +); + +/* +** Call this routine to free the memory that sqlite_get_table() allocated. +*/ +void sqlite_free_table(char **result); + +/* +** The following routines are wrappers around sqlite_exec() and +** sqlite_get_table(). The only difference between the routines that +** follow and the originals is that the second argument to the +** routines that follow is really a printf()-style format +** string describing the SQL to be executed. Arguments to the format +** string appear at the end of the argument list. +** +** All of the usual printf formatting options apply. In addition, there +** is a "%q" option. %q works like %s in that it substitutes a null-terminated +** string from the argument list. But %q also doubles every '\'' character. +** %q is designed for use inside a string literal. By doubling each '\'' +** character it escapes that character and allows it to be inserted into +** the string. +** +** For example, so some string variable contains text as follows: +** +** char *zText = "It's a happy day!"; +** +** We can use this text in an SQL statement as follows: +** +** sqlite_exec_printf(db, "INSERT INTO table VALUES('%q')", +** callback1, 0, 0, zText); +** +** Because the %q format string is used, the '\'' character in zText +** is escaped and the SQL generated is as follows: +** +** INSERT INTO table1 VALUES('It''s a happy day!') +** +** This is correct. Had we used %s instead of %q, the generated SQL +** would have looked like this: +** +** INSERT INTO table1 VALUES('It's a happy day!'); +** +** This second example is an SQL syntax error. As a general rule you +** should always use %q instead of %s when inserting text into a string +** literal. +*/ +int sqlite_exec_printf( + sqlite*, /* An open database */ + const char *sqlFormat, /* printf-style format string for the SQL */ + sqlite_callback, /* Callback function */ + void *, /* 1st argument to callback function */ + char **errmsg, /* Error msg written here */ + ... /* Arguments to the format string. */ +); +int sqlite_exec_vprintf( + sqlite*, /* An open database */ + const char *sqlFormat, /* printf-style format string for the SQL */ + sqlite_callback, /* Callback function */ + void *, /* 1st argument to callback function */ + char **errmsg, /* Error msg written here */ + va_list ap /* Arguments to the format string. */ +); +int sqlite_get_table_printf( + sqlite*, /* An open database */ + const char *sqlFormat, /* printf-style format string for the SQL */ + char ***resultp, /* Result written to a char *[] that this points to */ + int *nrow, /* Number of result rows written here */ + int *ncolumn, /* Number of result columns written here */ + char **errmsg, /* Error msg written here */ + ... /* Arguments to the format string */ +); +int sqlite_get_table_vprintf( + sqlite*, /* An open database */ + const char *sqlFormat, /* printf-style format string for the SQL */ + char ***resultp, /* Result written to a char *[] that this points to */ + int *nrow, /* Number of result rows written here */ + int *ncolumn, /* Number of result columns written here */ + char **errmsg, /* Error msg written here */ + va_list ap /* Arguments to the format string */ +); +char *sqlite_mprintf(const char*,...); +char *sqlite_vmprintf(const char*, va_list); + +/* +** Windows systems should call this routine to free memory that +** is returned in the in the errmsg parameter of sqlite_open() when +** SQLite is a DLL. For some reason, it does not work to call free() +** directly. +*/ +void sqlite_freemem(void *p); + +/* +** Windows systems need functions to call to return the sqlite_version +** and sqlite_encoding strings. +*/ +const char *sqlite_libversion(void); +const char *sqlite_libencoding(void); + +/* +** A pointer to the following structure is used to communicate with +** the implementations of user-defined functions. +*/ +typedef struct sqlite_func sqlite_func; + +/* +** Use the following routines to create new user-defined functions. See +** the documentation for details. +*/ +int sqlite_create_function( + sqlite*, /* Database where the new function is registered */ + const char *zName, /* Name of the new function */ + int nArg, /* Number of arguments. -1 means any number */ + void (*xFunc)(sqlite_func*,int,const char**), /* C code to implement */ + void *pUserData /* Available via the sqlite_user_data() call */ +); +int sqlite_create_aggregate( + sqlite*, /* Database where the new function is registered */ + const char *zName, /* Name of the function */ + int nArg, /* Number of arguments */ + void (*xStep)(sqlite_func*,int,const char**), /* Called for each row */ + void (*xFinalize)(sqlite_func*), /* Called once to get final result */ + void *pUserData /* Available via the sqlite_user_data() call */ +); + +/* +** Use the following routine to define the datatype returned by a +** user-defined function. The second argument can be one of the +** constants SQLITE_NUMERIC, SQLITE_TEXT, or SQLITE_ARGS or it +** can be an integer greater than or equal to zero. When the datatype +** parameter is non-negative, the type of the result will be the +** same as the datatype-th argument. If datatype==SQLITE_NUMERIC +** then the result is always numeric. If datatype==SQLITE_TEXT then +** the result is always text. If datatype==SQLITE_ARGS then the result +** is numeric if any argument is numeric and is text otherwise. +*/ +int sqlite_function_type( + sqlite *db, /* The database there the function is registered */ + const char *zName, /* Name of the function */ + int datatype /* The datatype for this function */ +); +#define SQLITE_NUMERIC (-1) +#define SQLITE_TEXT (-2) +#define SQLITE_ARGS (-3) + +/* +** The user function implementations call one of the following four routines +** in order to return their results. The first parameter to each of these +** routines is a copy of the first argument to xFunc() or xFinialize(). +** The second parameter to these routines is the result to be returned. +** A NULL can be passed as the second parameter to sqlite_set_result_string() +** in order to return a NULL result. +** +** The 3rd argument to _string and _error is the number of characters to +** take from the string. If this argument is negative, then all characters +** up to and including the first '\000' are used. +** +** The sqlite_set_result_string() function allocates a buffer to hold the +** result and returns a pointer to this buffer. The calling routine +** (that is, the implmentation of a user function) can alter the content +** of this buffer if desired. +*/ +char *sqlite_set_result_string(sqlite_func*,const char*,int); +void sqlite_set_result_int(sqlite_func*,int); +void sqlite_set_result_double(sqlite_func*,double); +void sqlite_set_result_error(sqlite_func*,const char*,int); + +/* +** The pUserData parameter to the sqlite_create_function() and +** sqlite_create_aggregate() routines used to register user functions +** is available to the implementation of the function using this +** call. +*/ +void *sqlite_user_data(sqlite_func*); + +/* +** Aggregate functions use the following routine to allocate +** a structure for storing their state. The first time this routine +** is called for a particular aggregate, a new structure of size nBytes +** is allocated, zeroed, and returned. On subsequent calls (for the +** same aggregate instance) the same buffer is returned. The implementation +** of the aggregate can use the returned buffer to accumulate data. +** +** The buffer allocated is freed automatically be SQLite. +*/ +void *sqlite_aggregate_context(sqlite_func*, int nBytes); + +/* +** The next routine returns the number of calls to xStep for a particular +** aggregate function instance. The current call to xStep counts so this +** routine always returns at least 1. +*/ +int sqlite_aggregate_count(sqlite_func*); + +/* +** This routine registers a callback with the SQLite library. The +** callback is invoked (at compile-time, not at run-time) for each +** attempt to access a column of a table in the database. The callback +** returns SQLITE_OK if access is allowed, SQLITE_DENY if the entire +** SQL statement should be aborted with an error and SQLITE_IGNORE +** if the column should be treated as a NULL value. +*/ +int sqlite_set_authorizer( + sqlite*, + int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), + void *pUserData +); + +/* +** The second parameter to the access authorization function above will +** be one of the values below. These values signify what kind of operation +** is to be authorized. The 3rd and 4th parameters to the authorization +** function will be parameters or NULL depending on which of the following +** codes is used as the second parameter. The 5th parameter is the name +** of the database ("main", "temp", etc.) if applicable. The 6th parameter +** is the name of the inner-most trigger or view that is responsible for +** the access attempt or NULL if this access attempt is directly from +** input SQL code. +** +** Arg-3 Arg-4 +*/ +#define SQLITE_COPY 0 /* Table Name File Name */ +#define SQLITE_CREATE_INDEX 1 /* Index Name Table Name */ +#define SQLITE_CREATE_TABLE 2 /* Table Name NULL */ +#define SQLITE_CREATE_TEMP_INDEX 3 /* Index Name Table Name */ +#define SQLITE_CREATE_TEMP_TABLE 4 /* Table Name NULL */ +#define SQLITE_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */ +#define SQLITE_CREATE_TEMP_VIEW 6 /* View Name NULL */ +#define SQLITE_CREATE_TRIGGER 7 /* Trigger Name Table Name */ +#define SQLITE_CREATE_VIEW 8 /* View Name NULL */ +#define SQLITE_DELETE 9 /* Table Name NULL */ +#define SQLITE_DROP_INDEX 10 /* Index Name Table Name */ +#define SQLITE_DROP_TABLE 11 /* Table Name NULL */ +#define SQLITE_DROP_TEMP_INDEX 12 /* Index Name Table Name */ +#define SQLITE_DROP_TEMP_TABLE 13 /* Table Name NULL */ +#define SQLITE_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */ +#define SQLITE_DROP_TEMP_VIEW 15 /* View Name NULL */ +#define SQLITE_DROP_TRIGGER 16 /* Trigger Name Table Name */ +#define SQLITE_DROP_VIEW 17 /* View Name NULL */ +#define SQLITE_INSERT 18 /* Table Name NULL */ +#define SQLITE_PRAGMA 19 /* Pragma Name 1st arg or NULL */ +#define SQLITE_READ 20 /* Table Name Column Name */ +#define SQLITE_SELECT 21 /* NULL NULL */ +#define SQLITE_TRANSACTION 22 /* NULL NULL */ +#define SQLITE_UPDATE 23 /* Table Name Column Name */ +#define SQLITE_ATTACH 24 /* Filename NULL */ +#define SQLITE_DETACH 25 /* Database Name NULL */ + + +/* +** The return value of the authorization function should be one of the +** following constants: +*/ +/* #define SQLITE_OK 0 // Allow access (This is actually defined above) */ +#define SQLITE_DENY 1 /* Abort the SQL statement with an error */ +#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */ + +/* +** Register a function that is called at every invocation of sqlite_exec() +** or sqlite_compile(). This function can be used (for example) to generate +** a log file of all SQL executed against a database. +*/ +void *sqlite_trace(sqlite*, void(*xTrace)(void*,const char*), void*); + +/*** The Callback-Free API +** +** The following routines implement a new way to access SQLite that does not +** involve the use of callbacks. +** +** An sqlite_vm is an opaque object that represents a single SQL statement +** that is ready to be executed. +*/ +typedef struct sqlite_vm sqlite_vm; + +/* +** To execute an SQLite query without the use of callbacks, you first have +** to compile the SQL using this routine. The 1st parameter "db" is a pointer +** to an sqlite object obtained from sqlite_open(). The 2nd parameter +** "zSql" is the text of the SQL to be compiled. The remaining parameters +** are all outputs. +** +** *pzTail is made to point to the first character past the end of the first +** SQL statement in zSql. This routine only compiles the first statement +** in zSql, so *pzTail is left pointing to what remains uncompiled. +** +** *ppVm is left pointing to a "virtual machine" that can be used to execute +** the compiled statement. Or if there is an error, *ppVm may be set to NULL. +** If the input text contained no SQL (if the input is and empty string or +** a comment) then *ppVm is set to NULL. +** +** If any errors are detected during compilation, an error message is written +** into space obtained from malloc() and *pzErrMsg is made to point to that +** error message. The calling routine is responsible for freeing the text +** of this message when it has finished with it. Use sqlite_freemem() to +** free the message. pzErrMsg may be NULL in which case no error message +** will be generated. +** +** On success, SQLITE_OK is returned. Otherwise and error code is returned. +*/ +int sqlite_compile( + sqlite *db, /* The open database */ + const char *zSql, /* SQL statement to be compiled */ + const char **pzTail, /* OUT: uncompiled tail of zSql */ + sqlite_vm **ppVm, /* OUT: the virtual machine to execute zSql */ + char **pzErrmsg /* OUT: Error message. */ +); + +/* +** After an SQL statement has been compiled, it is handed to this routine +** to be executed. This routine executes the statement as far as it can +** go then returns. The return value will be one of SQLITE_DONE, +** SQLITE_ERROR, SQLITE_BUSY, SQLITE_ROW, or SQLITE_MISUSE. +** +** SQLITE_DONE means that the execute of the SQL statement is complete +** an no errors have occurred. sqlite_step() should not be called again +** for the same virtual machine. *pN is set to the number of columns in +** the result set and *pazColName is set to an array of strings that +** describe the column names and datatypes. The name of the i-th column +** is (*pazColName)[i] and the datatype of the i-th column is +** (*pazColName)[i+*pN]. *pazValue is set to NULL. +** +** SQLITE_ERROR means that the virtual machine encountered a run-time +** error. sqlite_step() should not be called again for the same +** virtual machine. *pN is set to 0 and *pazColName and *pazValue are set +** to NULL. Use sqlite_finalize() to obtain the specific error code +** and the error message text for the error. +** +** SQLITE_BUSY means that an attempt to open the database failed because +** another thread or process is holding a lock. The calling routine +** can try again to open the database by calling sqlite_step() again. +** The return code will only be SQLITE_BUSY if no busy handler is registered +** using the sqlite_busy_handler() or sqlite_busy_timeout() routines. If +** a busy handler callback has been registered but returns 0, then this +** routine will return SQLITE_ERROR and sqltie_finalize() will return +** SQLITE_BUSY when it is called. +** +** SQLITE_ROW means that a single row of the result is now available. +** The data is contained in *pazValue. The value of the i-th column is +** (*azValue)[i]. *pN and *pazColName are set as described in SQLITE_DONE. +** Invoke sqlite_step() again to advance to the next row. +** +** SQLITE_MISUSE is returned if sqlite_step() is called incorrectly. +** For example, if you call sqlite_step() after the virtual machine +** has halted (after a prior call to sqlite_step() has returned SQLITE_DONE) +** or if you call sqlite_step() with an incorrectly initialized virtual +** machine or a virtual machine that has been deleted or that is associated +** with an sqlite structure that has been closed. +*/ +int sqlite_step( + sqlite_vm *pVm, /* The virtual machine to execute */ + int *pN, /* OUT: Number of columns in result */ + const char ***pazValue, /* OUT: Column data */ + const char ***pazColName /* OUT: Column names and datatypes */ +); + +/* +** This routine is called to delete a virtual machine after it has finished +** executing. The return value is the result code. SQLITE_OK is returned +** if the statement executed successfully and some other value is returned if +** there was any kind of error. If an error occurred and pzErrMsg is not +** NULL, then an error message is written into memory obtained from malloc() +** and *pzErrMsg is made to point to that error message. The calling routine +** should use sqlite_freemem() to delete this message when it has finished +** with it. +** +** This routine can be called at any point during the execution of the +** virtual machine. If the virtual machine has not completed execution +** when this routine is called, that is like encountering an error or +** an interrupt. (See sqlite_interrupt().) Incomplete updates may be +** rolled back and transactions cancelled, depending on the circumstances, +** and the result code returned will be SQLITE_ABORT. +*/ +int sqlite_finalize(sqlite_vm*, char **pzErrMsg); + +/* +** This routine deletes the virtual machine, writes any error message to +** *pzErrMsg and returns an SQLite return code in the same way as the +** sqlite_finalize() function. +** +** Additionally, if ppVm is not NULL, *ppVm is left pointing to a new virtual +** machine loaded with the compiled version of the original query ready for +** execution. +** +** If sqlite_reset() returns SQLITE_SCHEMA, then *ppVm is set to NULL. +** +******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ****** +*/ +int sqlite_reset(sqlite_vm*, char **pzErrMsg); + +/* +** If the SQL that was handed to sqlite_compile contains variables that +** are represeted in the SQL text by a question mark ('?'). This routine +** is used to assign values to those variables. +** +** The first parameter is a virtual machine obtained from sqlite_compile(). +** The 2nd "idx" parameter determines which variable in the SQL statement +** to bind the value to. The left most '?' is 1. The 3rd parameter is +** the value to assign to that variable. The 4th parameter is the number +** of bytes in the value, including the terminating \000 for strings. +** Finally, the 5th "copy" parameter is TRUE if SQLite should make its +** own private copy of this value, or false if the space that the 3rd +** parameter points to will be unchanging and can be used directly by +** SQLite. +** +** Unbound variables are treated as having a value of NULL. To explicitly +** set a variable to NULL, call this routine with the 3rd parameter as a +** NULL pointer. +** +** If the 4th "len" parameter is -1, then strlen() is used to find the +** length. +** +** This routine can only be called immediately after sqlite_compile() +** or sqlite_reset() and before any calls to sqlite_step(). +** +******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ****** +*/ +int sqlite_bind(sqlite_vm*, int idx, const char *value, int len, int copy); + +/* +** This routine configures a callback function - the progress callback - that +** is invoked periodically during long running calls to sqlite_exec(), +** sqlite_step() and sqlite_get_table(). An example use for this API is to keep +** a GUI updated during a large query. +** +** The progress callback is invoked once for every N virtual machine opcodes, +** where N is the second argument to this function. The progress callback +** itself is identified by the third argument to this function. The fourth +** argument to this function is a void pointer passed to the progress callback +** function each time it is invoked. +** +** If a call to sqlite_exec(), sqlite_step() or sqlite_get_table() results +** in less than N opcodes being executed, then the progress callback is not +** invoked. +** +** Calling this routine overwrites any previously installed progress callback. +** To remove the progress callback altogether, pass NULL as the third +** argument to this function. +** +** If the progress callback returns a result other than 0, then the current +** query is immediately terminated and any database changes rolled back. If the +** query was part of a larger transaction, then the transaction is not rolled +** back and remains active. The sqlite_exec() call returns SQLITE_ABORT. +** +******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ****** +*/ +void sqlite_progress_handler(sqlite*, int, int(*)(void*), void*); + +/* +** Register a callback function to be invoked whenever a new transaction +** is committed. The pArg argument is passed through to the callback. +** callback. If the callback function returns non-zero, then the commit +** is converted into a rollback. +** +** If another function was previously registered, its pArg value is returned. +** Otherwise NULL is returned. +** +** Registering a NULL function disables the callback. +** +******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ****** +*/ +void *sqlite_commit_hook(sqlite*, int(*)(void*), void*); + +/* +** Open an encrypted SQLite database. If pKey==0 or nKey==0, this routine +** is the same as sqlite_open(). +** +** The code to implement this API is not available in the public release +** of SQLite. +*/ +sqlite *sqlite_open_encrypted( + const char *zFilename, /* Name of the encrypted database */ + const void *pKey, /* Pointer to the key */ + int nKey, /* Number of bytes in the key */ + int *pErrcode, /* Write error code here */ + char **pzErrmsg /* Write error message here */ +); + +/* +** Change the key on an open database. If the current database is not +** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the +** database is decrypted. +** +** The code to implement this API is not available in the public release +** of SQLite. +*/ +int sqlite_rekey( + sqlite *db, /* Database to be rekeyed */ + const void *pKey, int nKey /* The new key */ +); + +#ifdef __cplusplus +} /* End of the 'extern "C"' block */ +#endif + +#endif /* _SQLITE_H_ */ diff --git a/dep/include/utf8cpp/doc/ReleaseNotes b/dep/include/utf8cpp/doc/ReleaseNotes new file mode 100644 index 00000000000..8541c7a6031 --- /dev/null +++ b/dep/include/utf8cpp/doc/ReleaseNotes @@ -0,0 +1,9 @@ +utf8 cpp library +Release 2.1 + +This is a minor feature release - added the function peek_next. + +Changes from version 2.o +- Implemented feature request [ 1770746 ] "Provide a const version of next() (some sort of a peek() ) + +Files included in the release: utf8.h, core.h, checked.h, unchecked.h, utf8cpp.html, ReleaseNotes diff --git a/dep/include/utf8cpp/doc/utf8cpp.html b/dep/include/utf8cpp/doc/utf8cpp.html new file mode 100644 index 00000000000..4ad7e1002a9 --- /dev/null +++ b/dep/include/utf8cpp/doc/utf8cpp.html @@ -0,0 +1,1574 @@ + + + + + + + + + UTF8-CPP: UTF-8 with C++ in a Portable Way + + + + +

+ UTF8-CPP: UTF-8 with C++ in a Portable Way +

+

+ The Sourceforge project page +

+ +

+ Introduction +

+

+ Many C++ developers miss an easy and portable way of handling Unicode encoded + strings. C++ Standard is currently Unicode agnostic, and while some work is being + done to introduce Unicode to the next incarnation called C++0x, for the moment + nothing of the sort is available. In the meantime, developers use 3rd party + libraries like ICU, OS specific capabilities, or simply roll out their own + solutions. +

+

+ In order to easily handle UTF-8 encoded Unicode strings, I have come up with a small + generic library. For anybody used to work with STL algorithms and iterators, it should be + easy and natural to use. The code is freely available for any purpose - check out + the license at the beginning of the utf8.h file. If you run into + bugs or performance issues, please let me know and I'll do my best to address them. +

+

+ The purpose of this article is not to offer an introduction to Unicode in general, + and UTF-8 in particular. If you are not familiar with Unicode, be sure to check out + Unicode Home Page or some other source of + information for Unicode. Also, it is not my aim to advocate the use of UTF-8 + encoded strings in C++ programs; if you want to handle UTF-8 encoded strings from + C++, I am sure you have good reasons for it. +

+

+ Examples of use +

+

+ To illustrate the use of this utf8 library, we shall open a file containing UTF-8 + encoded text, check whether it starts with a byte order mark, read each line into a + std::string, check it for validity, convert the text to UTF-16, and + back to UTF-8: +

+
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <vector>
+#include "utf8.h"
+using namespace std;
+int main()
+{
+    if (argc != 2) {
+        cout << "\nUsage: docsample filename\n";
+        return 0;
+    }
+    const char* test_file_path = argv[1];
+    // Open the test file (must be UTF-8 encoded)
+    ifstream fs8(test_file_path);
+    if (!fs8.is_open()) {
+    cout << "Could not open " << test_file_path << endl;
+    return 0;
+    }
+    // Read the first line of the file
+    unsigned line_count = 1;
+    string line;
+    if (!getline(fs8, line)) 
+        return 0;
+    // Look for utf-8 byte-order mark at the beginning
+    if (line.size() > 2) {
+        if (utf8::is_bom(line.c_str()))
+            cout << "There is a byte order mark at the beginning of the file\n";
+    }
+    // Play with all the lines in the file
+    do {
+       // check for invalid utf-8 (for a simple yes/no check, there is also utf8::is_valid function)
+        string::iterator end_it = utf8::find_invalid(line.begin(), line.end());
+        if (end_it != line.end()) {
+            cout << "Invalid UTF-8 encoding detected at line " << line_count << "\n";
+            cout << "This part is fine: " << string(line.begin(), end_it) << "\n";
+        }
+        // Get the line length (at least for the valid part)
+        int length = utf8::distance(line.begin(), end_it);
+        cout << "Length of line " << line_count << " is " << length <<  "\n";
+        // Convert it to utf-16
+        vector<unsigned short> utf16line;
+        utf8::utf8to16(line.begin(), end_it, back_inserter(utf16line));
+        // And back to utf-8
+        string utf8line; 
+        utf8::utf16to8(utf16line.begin(), utf16line.end(), back_inserter(utf8line));
+        // Confirm that the conversion went OK:
+        if (utf8line != string(line.begin(), end_it))
+            cout << "Error in UTF-16 conversion at line: " << line_count << "\n";        
+        getline(fs8, line);
+        line_count++;
+    } while (!fs8.eof());
+    return 0;
+}
+
+

+ In the previous code sample, we have seen the use of the following functions from + utf8 namespace: first we used is_bom function to detect + UTF-8 byte order mark at the beginning of the file; then for each line we performed + a detection of invalid UTF-8 sequences with find_invalid; the number + of characters (more precisely - the number of Unicode code points) in each line was + determined with a use of utf8::distance; finally, we have converted + each line to UTF-16 encoding with utf8to16 and back to UTF-8 with + utf16to8. +

+

+ Reference +

+

+ Functions From utf8 Namespace +

+

+ utf8::append +

+

+ Available in version 1.0 and later. +

+

+ Encodes a 32 bit code point as a UTF-8 sequence of octets and appends the sequence + to a UTF-8 string. +

+
+template <typename octet_iterator>
+octet_iterator append(uint32_t cp, octet_iterator result);
+   
+
+

+ cp: A 32 bit integer representing a code point to append to the + sequence.
+ result: An output iterator to the place in the sequence where to + append the code point.
+ Return value: An iterator pointing to the place + after the newly appended sequence. +

+

+ Example of use: +

+
+unsigned char u[5] = {0,0,0,0,0};
+unsigned char* end = append(0x0448, u);
+assert (u[0] == 0xd1 && u[1] == 0x88 && u[2] == 0 && u[3] == 0 && u[4] == 0);
+
+

+ Note that append does not allocate any memory - it is the burden of + the caller to make sure there is enough memory allocated for the operation. To make + things more interesting, append can add anywhere between 1 and 4 + octets to the sequence. In practice, you would most often want to use + std::back_inserter to ensure that the necessary memory is allocated. +

+

+ In case of an invalid code point, a utf8::invalid_code_point exception + is thrown. +

+

+ utf8::next +

+

+ Available in version 1.0 and later. +

+

+ Given the iterator to the beginning of the UTF-8 sequence, it returns the code + point and moves the iterator to the next position. +

+
+template <typename octet_iterator> 
+uint32_t next(octet_iterator& it, octet_iterator end);
+   
+
+

+ it: a reference to an iterator pointing to the beginning of an UTF-8 + encoded code point. After the function returns, it is incremented to point to the + beginning of the next code point.
+ end: end of the UTF-8 sequence to be processed. If it + gets equal to end during the extraction of a code point, an + utf8::not_enough_room exception is thrown.
+ Return value: the 32 bit representation of the + processed UTF-8 code point. +

+

+ Example of use: +

+
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+char* w = twochars;
+int cp = next(w, twochars + 6);
+assert (cp == 0x65e5);
+assert (w == twochars + 3);
+
+

+ This function is typically used to iterate through a UTF-8 encoded string. +

+

+ In case of an invalid UTF-8 seqence, a utf8::invalid_utf8 exception is + thrown. +

+

+ utf8::peek_next +

+

+ Available in version 2.1 and later. +

+

+ Given the iterator to the beginning of the UTF-8 sequence, it returns the code + point for the following sequence without changing the value of the iterator. +

+
+template <typename octet_iterator> 
+uint32_t peek_next(octet_iterator it, octet_iterator end);
+   
+
+

+ it: an iterator pointing to the beginning of an UTF-8 + encoded code point.
+ end: end of the UTF-8 sequence to be processed. If it + gets equal to end during the extraction of a code point, an + utf8::not_enough_room exception is thrown.
+ Return value: the 32 bit representation of the + processed UTF-8 code point. +

+

+ Example of use: +

+
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+char* w = twochars;
+int cp = peek_next(w, twochars + 6);
+assert (cp == 0x65e5);
+assert (w == twochars);
+
+

+ In case of an invalid UTF-8 seqence, a utf8::invalid_utf8 exception is + thrown. +

+

+ utf8::prior +

+

+ Available in version 1.02 and later. +

+

+ Given a reference to an iterator pointing to an octet in a UTF-8 seqence, it + decreases the iterator until it hits the beginning of the previous UTF-8 encoded + code point and returns the 32 bits representation of the code point. +

+
+template <typename octet_iterator> 
+uint32_t prior(octet_iterator& it, octet_iterator start);
+   
+
+

+ it: a reference pointing to an octet within a UTF-8 encoded string. + After the function returns, it is decremented to point to the beginning of the + previous code point.
+ start: an iterator to the beginning of the sequence where the search + for the beginning of a code point is performed. It is a + safety measure to prevent passing the beginning of the string in the search for a + UTF-8 lead octet.
+ Return value: the 32 bit representation of the + previous code point. +

+

+ Example of use: +

+
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+unsigned char* w = twochars + 3;
+int cp = prior (w, twochars);
+assert (cp == 0x65e5);
+assert (w == twochars);
+
+

+ This function has two purposes: one is two iterate backwards through a UTF-8 + encoded string. Note that it is usually a better idea to iterate forward instead, + since utf8::next is faster. The second purpose is to find a beginning + of a UTF-8 sequence if we have a random position within a string. +

+

+ it will typically point to the beginning of + a code point, and start will point to the + beginning of the string to ensure we don't go backwards too far. it is + decreased until it points to a lead UTF-8 octet, and then the UTF-8 sequence + beginning with that octet is decoded to a 32 bit representation and returned. +

+

+ In case pass_end is reached before a UTF-8 lead octet is hit, or if an + invalid UTF-8 sequence is started by the lead octet, an invalid_utf8 + exception is thrown. +

+

+ utf8::previous +

+

+ Deprecated in version 1.02 and later. +

+

+ Given a reference to an iterator pointing to an octet in a UTF-8 seqence, it + decreases the iterator until it hits the beginning of the previous UTF-8 encoded + code point and returns the 32 bits representation of the code point. +

+
+template <typename octet_iterator> 
+uint32_t previous(octet_iterator& it, octet_iterator pass_start);
+   
+
+

+ it: a reference pointing to an octet within a UTF-8 encoded string. + After the function returns, it is decremented to point to the beginning of the + previous code point.
+ pass_start: an iterator to the point in the sequence where the search + for the beginning of a code point is aborted if no result was reached. It is a + safety measure to prevent passing the beginning of the string in the search for a + UTF-8 lead octet.
+ Return value: the 32 bit representation of the + previous code point. +

+

+ Example of use: +

+
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+unsigned char* w = twochars + 3;
+int cp = previous (w, twochars - 1);
+assert (cp == 0x65e5);
+assert (w == twochars);
+
+

+ utf8::previous is deprecated, and utf8::prior should + be used instead, although the existing code can continue using this function. + The problem is the parameter pass_start that points to the position + just before the beginning of the sequence. Standard containers don't have the + concept of "pass start" and the function can not be used with their iterators. +

+

+ it will typically point to the beginning of + a code point, and pass_start will point to the octet just before the + beginning of the string to ensure we don't go backwards too far. it is + decreased until it points to a lead UTF-8 octet, and then the UTF-8 sequence + beginning with that octet is decoded to a 32 bit representation and returned. +

+

+ In case pass_end is reached before a UTF-8 lead octet is hit, or if an + invalid UTF-8 sequence is started by the lead octet, an invalid_utf8 + exception is thrown +

+

+ utf8::advance +

+

+ Available in version 1.0 and later. +

+

+ Advances an iterator by the specified number of code points within an UTF-8 + sequence. +

+
+template <typename octet_iterator, typename distance_type> 
+void advance (octet_iterator& it, distance_type n, octet_iterator end);
+   
+
+

+ it: a reference to an iterator pointing to the beginning of an UTF-8 + encoded code point. After the function returns, it is incremented to point to the + nth following code point.
+ n: a positive integer that shows how many code points we want to + advance.
+ end: end of the UTF-8 sequence to be processed. If it + gets equal to end during the extraction of a code point, an + utf8::not_enough_room exception is thrown.
+

+

+ Example of use: +

+
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+unsigned char* w = twochars;
+advance (w, 2, twochars + 6);
+assert (w == twochars + 5);
+
+

+ This function works only "forward". In case of a negative n, there is + no effect. +

+

+ In case of an invalid code point, a utf8::invalid_code_point exception + is thrown. +

+

+ utf8::distance +

+

+ Available in version 1.0 and later. +

+

+ Given the iterators to two UTF-8 encoded code points in a seqence, returns the + number of code points between them. +

+
+template <typename octet_iterator> 
+typename std::iterator_traits<octet_iterator>::difference_type distance (octet_iterator first, octet_iterator last);
+   
+
+

+ first: an iterator to a beginning of a UTF-8 encoded code point.
+ last: an iterator to a "post-end" of the last UTF-8 encoded code + point in the sequence we are trying to determine the length. It can be the + beginning of a new code point, or not.
+ Return value the distance between the iterators, + in code points. +

+

+ Example of use: +

+
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+size_t dist = utf8::distance(twochars, twochars + 5);
+assert (dist == 2);
+
+

+ This function is used to find the length (in code points) of a UTF-8 encoded + string. The reason it is called distance, rather than, say, + length is mainly because developers are used that length is an + O(1) function. Computing the length of an UTF-8 string is a linear operation, and + it looked better to model it after std::distance algorithm. +

+

+ In case of an invalid UTF-8 seqence, a utf8::invalid_utf8 exception is + thrown. If last does not point to the past-of-end of a UTF-8 seqence, + a utf8::not_enough_room exception is thrown. +

+

+ utf8::utf16to8 +

+

+ Available in version 1.0 and later. +

+

+ Converts a UTF-16 encoded string to UTF-8. +

+
+template <typename u16bit_iterator, typename octet_iterator>
+octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result);
+   
+
+

+ start: an iterator pointing to the beginning of the UTF-16 encoded + string to convert.
+ end: an iterator pointing to pass-the-end of the UTF-16 encoded + string to convert.
+ result: an output iterator to the place in the UTF-8 string where to + append the result of conversion.
+ Return value: An iterator pointing to the place + after the appended UTF-8 string. +

+

+ Example of use: +

+
+unsigned short utf16string[] = {0x41, 0x0448, 0x65e5, 0xd834, 0xdd1e};
+vector<unsigned char> utf8result;
+utf16to8(utf16string, utf16string + 5, back_inserter(utf8result));
+assert (utf8result.size() == 10);    
+
+

+ In case of invalid UTF-16 sequence, a utf8::invalid_utf16 exception is + thrown. +

+

+ utf8::utf8to16 +

+

+ Available in version 1.0 and later. +

+

+ Converts an UTF-8 encoded string to UTF-16 +

+
+template <typename u16bit_iterator, typename octet_iterator>
+u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result);
+   
+
+

+ start: an iterator pointing to the beginning of the UTF-8 encoded + string to convert. < br /> end: an iterator pointing to + pass-the-end of the UTF-8 encoded string to convert.
+ result: an output iterator to the place in the UTF-16 string where to + append the result of conversion.
+ Return value: An iterator pointing to the place + after the appended UTF-16 string. +

+

+ Example of use: +

+
+char utf8_with_surrogates[] = "\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e";
+vector <unsigned short> utf16result;
+utf8to16(utf8_with_surrogates, utf8_with_surrogates + 9, back_inserter(utf16result));
+assert (utf16result.size() == 4);
+assert (utf16result[2] == 0xd834);
+assert (utf16result[3] == 0xdd1e);
+
+

+ In case of an invalid UTF-8 seqence, a utf8::invalid_utf8 exception is + thrown. If end does not point to the past-of-end of a UTF-8 seqence, a + utf8::not_enough_room exception is thrown. +

+

+ utf8::utf32to8 +

+

+ Available in version 1.0 and later. +

+

+ Converts a UTF-32 encoded string to UTF-8. +

+
+template <typename octet_iterator, typename u32bit_iterator>
+octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result);
+   
+
+

+ start: an iterator pointing to the beginning of the UTF-32 encoded + string to convert.
+ end: an iterator pointing to pass-the-end of the UTF-32 encoded + string to convert.
+ result: an output iterator to the place in the UTF-8 string where to + append the result of conversion.
+ Return value: An iterator pointing to the place + after the appended UTF-8 string. +

+

+ Example of use: +

+
+int utf32string[] = {0x448, 0x65E5, 0x10346, 0};
+vector<unsigned char> utf8result;
+utf32to8(utf32string, utf32string + 3, back_inserter(utf8result));
+assert (utf8result.size() == 9);
+
+

+ In case of invalid UTF-32 string, a utf8::invalid_code_point exception + is thrown. +

+

+ utf8::utf8to32 +

+

+ Available in version 1.0 and later. +

+

+ Converts a UTF-8 encoded string to UTF-32. +

+
+template <typename octet_iterator, typename u32bit_iterator>
+u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result);
+   
+
+

+ start: an iterator pointing to the beginning of the UTF-8 encoded + string to convert.
+ end: an iterator pointing to pass-the-end of the UTF-8 encoded string + to convert.
+ result: an output iterator to the place in the UTF-32 string where to + append the result of conversion.
+ Return value: An iterator pointing to the place + after the appended UTF-32 string. +

+

+ Example of use: +

+
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+vector<int> utf32result;
+utf8to32(twochars, twochars + 5, back_inserter(utf32result));
+assert (utf32result.size() == 2);
+
+

+ In case of an invalid UTF-8 seqence, a utf8::invalid_utf8 exception is + thrown. If end does not point to the past-of-end of a UTF-8 seqence, a + utf8::not_enough_room exception is thrown. +

+

+ utf8::find_invalid +

+

+ Available in version 1.0 and later. +

+

+ Detects an invalid sequence within a UTF-8 string. +

+
+template <typename octet_iterator> 
+octet_iterator find_invalid(octet_iterator start, octet_iterator end);
+
+

+ start: an iterator pointing to the beginning of the UTF-8 string to + test for validity.
+ end: an iterator pointing to pass-the-end of the UTF-8 string to test + for validity.
+ Return value: an iterator pointing to the first + invalid octet in the UTF-8 string. In case none were found, equals + end. +

+

+ Example of use: +

+
+char utf_invalid[] = "\xe6\x97\xa5\xd1\x88\xfa";
+char* invalid = find_invalid(utf_invalid, utf_invalid + 6);
+assert (invalid == utf_invalid + 5);
+
+

+ This function is typically used to make sure a UTF-8 string is valid before + processing it with other functions. It is especially important to call it if before + doing any of the unchecked operations on it. +

+

+ utf8::is_valid +

+

+ Available in version 1.0 and later. +

+

+ Checks whether a sequence of octets is a valid UTF-8 string. +

+
+template <typename octet_iterator> 
+bool is_valid(octet_iterator start, octet_iterator end);
+   
+
+

+ start: an iterator pointing to the beginning of the UTF-8 string to + test for validity.
+ end: an iterator pointing to pass-the-end of the UTF-8 string to test + for validity.
+ Return value: true if the sequence + is a valid UTF-8 string; false if not. +

+ Example of use: +
+char utf_invalid[] = "\xe6\x97\xa5\xd1\x88\xfa";
+bool bvalid = is_valid(utf_invalid, utf_invalid + 6);
+assert (bvalid == false);
+
+

+ is_valid is a shorthand for find_invalid(start, end) == + end;. You may want to use it to make sure that a byte seqence is a valid + UTF-8 string without the need to know where it fails if it is not valid. +

+

+ utf8::replace_invalid +

+

+ Available in version 2.0 and later. +

+

+ Replaces all invalid UTF-8 sequences within a string with a replacement marker. +

+
+template <typename octet_iterator, typename output_iterator>
+output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement);
+template <typename octet_iterator, typename output_iterator>
+output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out);
+   
+
+

+ start: an iterator pointing to the beginning of the UTF-8 string to + look for invalid UTF-8 sequences.
+ end: an iterator pointing to pass-the-end of the UTF-8 string to look + for invalid UTF-8 sequences.
+ out: An output iterator to the range where the result of replacement + is stored.
+ replacement: A Unicode code point for the replacement marker. The + version without this parameter assumes the value 0xfffd
+ Return value: An iterator pointing to the place + after the UTF-8 string with replaced invalid sequences. +

+

+ Example of use: +

+
+char invalid_sequence[] = "a\x80\xe0\xa0\xc0\xaf\xed\xa0\x80z";
+vector<char> replace_invalid_result;
+replace_invalid (invalid_sequence, invalid_sequence + sizeof(invalid_sequence), back_inserter(replace_invalid_result), '?');
+bvalid = is_valid(replace_invalid_result.begin(), replace_invalid_result.end());
+assert (bvalid);
+char* fixed_invalid_sequence = "a????z";
+assert (std::equal(replace_invalid_result.begin(), replace_invalid_result.end(), fixed_invalid_sequence));
+
+

+ replace_invalid does not perform in-place replacement of invalid + sequences. Rather, it produces a copy of the original string with the invalid + sequences replaced with a replacement marker. Therefore, out must not + be in the [start, end] range. +

+

+ If end does not point to the past-of-end of a UTF-8 sequence, a + utf8::not_enough_room exception is thrown. +

+

+ utf8::is_bom +

+

+ Available in version 1.0 and later. +

+

+ Checks whether a sequence of three octets is a UTF-8 byte order mark (BOM) +

+
+template <typename octet_iterator> 
+bool is_bom (octet_iterator it);
+
+

+ it: beginning of the 3-octet sequence to check
+ Return value: true if the sequence + is UTF-8 byte order mark; false if not. +

+

+ Example of use: +

+
+unsigned char byte_order_mark[] = {0xef, 0xbb, 0xbf};
+bool bbom = is_bom(byte_order_mark);
+assert (bbom == true);
+
+

+ The typical use of this function is to check the first three bytes of a file. If + they form the UTF-8 BOM, we want to skip them before processing the actual UTF-8 + encoded text. +

+

+ Types From utf8 Namespace +

+

+ utf8::iterator +

+

+ Available in version 2.0 and later. +

+

+ Adapts the underlying octet iterator to iterate over the sequence of code points, + rather than raw octets. +

+
+template <typename octet_iterator>
+class iterator;
+
+ +
Member functions
+
+
iterator();
the deafult constructor; the underlying octet_iterator is + constructed with its default constructor. +
explicit iterator (const octet_iterator& octet_it, + const octet_iterator& range_start, + const octet_iterator& range_end);
a constructor + that initializes the underlying octet_iterator with octet_it + and sets the range in which the iterator is considered valid. +
octet_iterator base () const;
returns the + underlying octet_iterator. +
uint32_t operator * () const;
decodes the utf-8 sequence + the underlying octet_iterator is pointing to and returns the code point. +
bool operator == (const iterator& rhs) + const;
returns true + if the two underlaying iterators are equal. +
bool operator != (const iterator& rhs) + const;
returns true + if the two underlaying iterators are not equal. +
iterator& operator ++ ();
the prefix increment - moves + the iterator to the next UTF-8 encoded code point. +
iterator operator ++ (int);
+ the postfix increment - moves the iterator to the next UTF-8 encoded code point and returns the current one. +
iterator& operator -- ();
the prefix decrement - moves + the iterator to the previous UTF-8 encoded code point. +
iterator operator -- (int);
+ the postfix decrement - moves the iterator to the previous UTF-8 encoded code point and returns the current one. +
+

+ Example of use: +

+
+char* threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+utf8::iterator<char*> it(threechars, threechars, threechars + 9);
+utf8::iterator<char*> it2 = it;
+assert (it2 == it);
+assert (*it == 0x10346);
+assert (*(++it) == 0x65e5);
+assert ((*it++) == 0x65e5);
+assert (*it == 0x0448);
+assert (it != it2);
+utf8::iterator<char*> endit (threechars + 9, threechars, threechars + 9);  
+assert (++it == endit);
+assert (*(--it) == 0x0448);
+assert ((*it--) == 0x0448);
+assert (*it == 0x65e5);
+assert (--it == utf8::iterator<char*>(threechars, threechars, threechars + 9));
+assert (*it == 0x10346);
+
+

+ The purpose of utf8::iterator adapter is to enable easy iteration as well as the use of STL + algorithms with UTF-8 encoded strings. Increment and decrement operators are implemented in terms of + utf8::next() and utf8::prior() functions. +

+

+ Note that utf8::iterator adapter is a checked iterator. It operates on the range specified in + the constructor; any attempt to go out of that range will result in an exception. Even the comparison operators + require both iterator object to be constructed against the same range - otherwise an exception is thrown. Typically, + the range will be determined by sequence container functions begin and end, i.e.: +

+
+std::string s = "example";
+utf8::iterator i (s.begin(), s.begin(), s.end());
+
+

+ Functions From utf8::unchecked Namespace +

+

+ utf8::unchecked::append +

+

+ Available in version 1.0 and later. +

+

+ Encodes a 32 bit code point as a UTF-8 sequence of octets and appends the sequence + to a UTF-8 string. +

+
+template <typename octet_iterator>
+octet_iterator append(uint32_t cp, octet_iterator result);
+   
+
+

+ cp: A 32 bit integer representing a code point to append to the + sequence.
+ result: An output iterator to the place in the sequence where to + append the code point.
+ Return value: An iterator pointing to the place + after the newly appended sequence. +

+

+ Example of use: +

+
+unsigned char u[5] = {0,0,0,0,0};
+unsigned char* end = unchecked::append(0x0448, u);
+assert (u[0] == 0xd1 && u[1] == 0x88 && u[2] == 0 && u[3] == 0 && u[4] == 0);
+
+

+ This is a faster but less safe version of utf8::append. It does not + check for validity of the supplied code point, and may produce an invalid UTF-8 + sequence. +

+

+ utf8::unchecked::next +

+

+ Available in version 1.0 and later. +

+

+ Given the iterator to the beginning of a UTF-8 sequence, it returns the code point + and moves the iterator to the next position. +

+
+template <typename octet_iterator>
+uint32_t next(octet_iterator& it);
+   
+
+

+ it: a reference to an iterator pointing to the beginning of an UTF-8 + encoded code point. After the function returns, it is incremented to point to the + beginning of the next code point.
+ Return value: the 32 bit representation of the + processed UTF-8 code point. +

+

+ Example of use: +

+
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+char* w = twochars;
+int cp = unchecked::next(w);
+assert (cp == 0x65e5);
+assert (w == twochars + 3);
+
+

+ This is a faster but less safe version of utf8::next. It does not + check for validity of the supplied UTF-8 sequence. +

+

+ utf8::unchecked::peek_next +

+

+ Available in version 2.1 and later. +

+

+ Given the iterator to the beginning of a UTF-8 sequence, it returns the code point. +

+
+template <typename octet_iterator>
+uint32_t peek_next(octet_iterator it);
+   
+
+

+ it: an iterator pointing to the beginning of an UTF-8 + encoded code point.
+ Return value: the 32 bit representation of the + processed UTF-8 code point. +

+

+ Example of use: +

+
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+char* w = twochars;
+int cp = unchecked::peek_next(w);
+assert (cp == 0x65e5);
+assert (w == twochars);
+
+

+ This is a faster but less safe version of utf8::peek_next. It does not + check for validity of the supplied UTF-8 sequence. +

+

+ utf8::unchecked::prior +

+

+ Available in version 1.02 and later. +

+

+ Given a reference to an iterator pointing to an octet in a UTF-8 seqence, it + decreases the iterator until it hits the beginning of the previous UTF-8 encoded + code point and returns the 32 bits representation of the code point. +

+
+template <typename octet_iterator>
+uint32_t prior(octet_iterator& it);
+   
+
+

+ it: a reference pointing to an octet within a UTF-8 encoded string. + After the function returns, it is decremented to point to the beginning of the + previous code point.
+ Return value: the 32 bit representation of the + previous code point. +

+

+ Example of use: +

+
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+char* w = twochars + 3;
+int cp = unchecked::prior (w);
+assert (cp == 0x65e5);
+assert (w == twochars);
+
+

+ This is a faster but less safe version of utf8::prior. It does not + check for validity of the supplied UTF-8 sequence and offers no boundary checking. +

+

+ utf8::unchecked::previous (deprecated, see utf8::unchecked::prior) +

+

+ Deprecated in version 1.02 and later. +

+

+ Given a reference to an iterator pointing to an octet in a UTF-8 seqence, it + decreases the iterator until it hits the beginning of the previous UTF-8 encoded + code point and returns the 32 bits representation of the code point. +

+
+template <typename octet_iterator>
+uint32_t previous(octet_iterator& it);
+   
+
+

+ it: a reference pointing to an octet within a UTF-8 encoded string. + After the function returns, it is decremented to point to the beginning of the + previous code point.
+ Return value: the 32 bit representation of the + previous code point. +

+

+ Example of use: +

+
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+char* w = twochars + 3;
+int cp = unchecked::previous (w);
+assert (cp == 0x65e5);
+assert (w == twochars);
+
+

+ The reason this function is deprecated is just the consistency with the "checked" + versions, where prior should be used instead of previous. + In fact, unchecked::previous behaves exactly the same as + unchecked::prior +

+

+ This is a faster but less safe version of utf8::previous. It does not + check for validity of the supplied UTF-8 sequence and offers no boundary checking. +

+

+ utf8::unchecked::advance +

+

+ Available in version 1.0 and later. +

+

+ Advances an iterator by the specified number of code points within an UTF-8 + sequence. +

+
+template <typename octet_iterator, typename distance_type>
+void advance (octet_iterator& it, distance_type n);
+   
+
+

+ it: a reference to an iterator pointing to the beginning of an UTF-8 + encoded code point. After the function returns, it is incremented to point to the + nth following code point.
+ n: a positive integer that shows how many code points we want to + advance.
+

+

+ Example of use: +

+
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+char* w = twochars;
+unchecked::advance (w, 2);
+assert (w == twochars + 5);
+
+

+ This function works only "forward". In case of a negative n, there is + no effect. +

+

+ This is a faster but less safe version of utf8::advance. It does not + check for validity of the supplied UTF-8 sequence and offers no boundary checking. +

+

+ utf8::unchecked::distance +

+

+ Available in version 1.0 and later. +

+

+ Given the iterators to two UTF-8 encoded code points in a seqence, returns the + number of code points between them. +

+
+template <typename octet_iterator>
+typename std::iterator_traits<octet_iterator>::difference_type distance (octet_iterator first, octet_iterator last);
+
+

+ first: an iterator to a beginning of a UTF-8 encoded code point.
+ last: an iterator to a "post-end" of the last UTF-8 encoded code + point in the sequence we are trying to determine the length. It can be the + beginning of a new code point, or not.
+ Return value the distance between the iterators, + in code points. +

+

+ Example of use: +

+
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+size_t dist = utf8::unchecked::distance(twochars, twochars + 5);
+assert (dist == 2);
+
+

+ This is a faster but less safe version of utf8::distance. It does not + check for validity of the supplied UTF-8 sequence. +

+

+ utf8::unchecked::utf16to8 +

+

+ Available in version 1.0 and later. +

+

+ Converts a UTF-16 encoded string to UTF-8. +

+
+template <typename u16bit_iterator, typename octet_iterator>
+octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result);
+   
+
+

+ start: an iterator pointing to the beginning of the UTF-16 encoded + string to convert.
+ end: an iterator pointing to pass-the-end of the UTF-16 encoded + string to convert.
+ result: an output iterator to the place in the UTF-8 string where to + append the result of conversion.
+ Return value: An iterator pointing to the place + after the appended UTF-8 string. +

+

+ Example of use: +

+
+unsigned short utf16string[] = {0x41, 0x0448, 0x65e5, 0xd834, 0xdd1e};
+vector<unsigned char> utf8result;
+unchecked::utf16to8(utf16string, utf16string + 5, back_inserter(utf8result));
+assert (utf8result.size() == 10);    
+
+

+ This is a faster but less safe version of utf8::utf16to8. It does not + check for validity of the supplied UTF-16 sequence. +

+

+ utf8::unchecked::utf8to16 +

+

+ Available in version 1.0 and later. +

+

+ Converts an UTF-8 encoded string to UTF-16 +

+
+template <typename u16bit_iterator, typename octet_iterator>
+u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result);
+   
+
+

+ start: an iterator pointing to the beginning of the UTF-8 encoded + string to convert. < br /> end: an iterator pointing to + pass-the-end of the UTF-8 encoded string to convert.
+ result: an output iterator to the place in the UTF-16 string where to + append the result of conversion.
+ Return value: An iterator pointing to the place + after the appended UTF-16 string. +

+

+ Example of use: +

+
+char utf8_with_surrogates[] = "\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e";
+vector <unsigned short> utf16result;
+unchecked::utf8to16(utf8_with_surrogates, utf8_with_surrogates + 9, back_inserter(utf16result));
+assert (utf16result.size() == 4);
+assert (utf16result[2] == 0xd834);
+assert (utf16result[3] == 0xdd1e);
+
+

+ This is a faster but less safe version of utf8::utf8to16. It does not + check for validity of the supplied UTF-8 sequence. +

+

+ utf8::unchecked::utf32to8 +

+

+ Available in version 1.0 and later. +

+

+ Converts a UTF-32 encoded string to UTF-8. +

+
+template <typename octet_iterator, typename u32bit_iterator>
+octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result);
+   
+
+

+ start: an iterator pointing to the beginning of the UTF-32 encoded + string to convert.
+ end: an iterator pointing to pass-the-end of the UTF-32 encoded + string to convert.
+ result: an output iterator to the place in the UTF-8 string where to + append the result of conversion.
+ Return value: An iterator pointing to the place + after the appended UTF-8 string. +

+

+ Example of use: +

+
+int utf32string[] = {0x448, 0x65e5, 0x10346, 0};
+vector<unsigned char> utf8result;
+utf32to8(utf32string, utf32string + 3, back_inserter(utf8result));
+assert (utf8result.size() == 9);
+
+

+ This is a faster but less safe version of utf8::utf32to8. It does not + check for validity of the supplied UTF-32 sequence. +

+

+ utf8::unchecked::utf8to32 +

+

+ Available in version 1.0 and later. +

+

+ Converts a UTF-8 encoded string to UTF-32. +

+
+template <typename octet_iterator, typename u32bit_iterator>
+u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result);
+   
+
+

+ start: an iterator pointing to the beginning of the UTF-8 encoded + string to convert.
+ end: an iterator pointing to pass-the-end of the UTF-8 encoded string + to convert.
+ result: an output iterator to the place in the UTF-32 string where to + append the result of conversion.
+ Return value: An iterator pointing to the place + after the appended UTF-32 string. +

+

+ Example of use: +

+
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+vector<int> utf32result;
+unchecked::utf8to32(twochars, twochars + 5, back_inserter(utf32result));
+assert (utf32result.size() == 2);
+
+

+ This is a faster but less safe version of utf8::utf8to32. It does not + check for validity of the supplied UTF-8 sequence. +

+

+ Types From utf8::unchecked Namespace +

+

+ utf8::iterator +

+

+ Available in version 2.0 and later. +

+

+ Adapts the underlying octet iterator to iterate over the sequence of code points, + rather than raw octets. +

+
+template <typename octet_iterator>
+class iterator;
+
+ +
Member functions
+
+
iterator();
the deafult constructor; the underlying octet_iterator is + constructed with its default constructor. +
explicit iterator (const octet_iterator& octet_it); +
a constructor + that initializes the underlying octet_iterator with octet_it +
octet_iterator base () const;
returns the + underlying octet_iterator. +
uint32_t operator * () const;
decodes the utf-8 sequence + the underlying octet_iterator is pointing to and returns the code point. +
bool operator == (const iterator& rhs) + const;
returns true + if the two underlaying iterators are equal. +
bool operator != (const iterator& rhs) + const;
returns true + if the two underlaying iterators are not equal. +
iterator& operator ++ ();
the prefix increment - moves + the iterator to the next UTF-8 encoded code point. +
iterator operator ++ (int);
+ the postfix increment - moves the iterator to the next UTF-8 encoded code point and returns the current one. +
iterator& operator -- ();
the prefix decrement - moves + the iterator to the previous UTF-8 encoded code point. +
iterator operator -- (int);
+ the postfix decrement - moves the iterator to the previous UTF-8 encoded code point and returns the current one. +
+

+ Example of use: +

+
+char* threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+utf8::unchecked::iterator<char*> un_it(threechars);
+utf8::unchecked::iterator<char*> un_it2 = un_it;
+assert (un_it2 == un_it);
+assert (*un_it == 0x10346);
+assert (*(++un_it) == 0x65e5);
+assert ((*un_it++) == 0x65e5);
+assert (*un_it == 0x0448);
+assert (un_it != un_it2);
+utf8::::unchecked::iterator<char*> un_endit (threechars + 9);  
+assert (++un_it == un_endit);
+assert (*(--un_it) == 0x0448);
+assert ((*un_it--) == 0x0448);
+assert (*un_it == 0x65e5);
+assert (--un_it == utf8::unchecked::iterator<char*>(threechars));
+assert (*un_it == 0x10346);
+
+

+ This is an unchecked version of utf8::iterator. It is faster in many cases, but offers + no validity or range checks. +

+

+ Points of interest +

+

+ Design goals and decisions +

+

+ The library was designed to be: +

+
    +
  1. + Generic: for better or worse, there are many C++ string classes out there, and + the library should work with as many of them as possible. +
  2. +
  3. + Portable: the library should be portable both accross different platforms and + compilers. The only non-portable code is a small section that declares unsigned + integers of different sizes: three typedefs. They can be changed by the users of + the library if they don't match their platform. The default setting should work + for Windows (both 32 and 64 bit), and most 32 bit and 64 bit Unix derivatives. +
  4. +
  5. + Lightweight: follow the "pay only for what you use" guidline. +
  6. +
  7. + Unintrusive: avoid forcing any particular design or even programming style on the + user. This is a library, not a framework. +
  8. +
+

+ Alternatives +

+

+ In case you want to look into other means of working with UTF-8 strings from C++, + here is the list of solutions I am aware of: +

+
    +
  1. + ICU Library. It is very powerful, + complete, feature-rich, mature, and widely used. Also big, intrusive, + non-generic, and doesn't play well with the Standard Library. I definitelly + recommend looking at ICU even if you don't plan to use it. +
  2. +
  3. + Glib::ustring. + A class specifically made to work with UTF-8 strings, and also feel like + std::string. If you prefer to have yet another string class in your + code, it may be worth a look. Be aware of the licensing issues, though. +
  4. +
  5. + Platform dependent solutions: Windows and POSIX have functions to convert strings + from one encoding to another. That is only a subset of what my library offers, + but if that is all you need it may be good enough, especially given the fact that + these functions are mature and tested in production. +
  6. +
+

+ Conclusion +

+

+ Until Unicode becomes officially recognized by the C++ Standard Library, we need to + use other means to work with UTF-8 strings. Template functions I describe in this + article may be a good step in this direction. +

+ +
    +
  1. + The Unicode Consortium. +
  2. +
  3. + ICU Library. +
  4. +
  5. + UTF-8 at Wikipedia +
  6. +
  7. + UTF-8 and Unicode FAQ for + Unix/Linux +
  8. +
+ + diff --git a/dep/include/utf8cpp/utf8.h b/dep/include/utf8cpp/utf8.h new file mode 100644 index 00000000000..82b13f59f98 --- /dev/null +++ b/dep/include/utf8cpp/utf8.h @@ -0,0 +1,34 @@ +// Copyright 2006 Nemanja Trifunovic + +/* +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +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, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + + +#ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731 +#define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731 + +#include "utf8/checked.h" +#include "utf8/unchecked.h" + +#endif // header guard diff --git a/dep/include/utf8cpp/utf8/checked.h b/dep/include/utf8cpp/utf8/checked.h new file mode 100644 index 00000000000..5670c196d5e --- /dev/null +++ b/dep/include/utf8cpp/utf8/checked.h @@ -0,0 +1,318 @@ +// Copyright 2006 Nemanja Trifunovic + +/* +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +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, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + + +#ifndef UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 +#define UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 + +#include "core.h" +#include + +namespace utf8 +{ + // Exceptions that may be thrown from the library functions. + class invalid_code_point : public std::exception { + uint32_t cp; + public: + invalid_code_point(uint32_t cp) : cp(cp) {} + virtual const char* what() const throw() { return "Invalid code point"; } + uint32_t code_point() const {return cp;} + }; + + class invalid_utf8 : public std::exception { + uint8_t u8; + public: + invalid_utf8 (uint8_t u) : u8(u) {} + virtual const char* what() const throw() { return "Invalid UTF-8"; } + uint8_t utf8_octet() const {return u8;} + }; + + class invalid_utf16 : public std::exception { + uint16_t u16; + public: + invalid_utf16 (uint16_t u) : u16(u) {} + virtual const char* what() const throw() { return "Invalid UTF-16"; } + uint16_t utf16_word() const {return u16;} + }; + + class not_enough_room : public std::exception { + public: + virtual const char* what() const throw() { return "Not enough space"; } + }; + + /// The library API - functions intended to be called by the users + + template + output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement) + { + while (start != end) { + octet_iterator sequence_start = start; + internal::utf_error err_code = internal::validate_next(start, end); + switch (err_code) { + case internal::OK : + for (octet_iterator it = sequence_start; it != start; ++it) + *out++ = *it; + break; + case internal::NOT_ENOUGH_ROOM: + throw not_enough_room(); + case internal::INVALID_LEAD: + append (replacement, out); + ++start; + break; + case internal::INCOMPLETE_SEQUENCE: + case internal::OVERLONG_SEQUENCE: + case internal::INVALID_CODE_POINT: + append (replacement, out); + ++start; + // just one replacement mark for the sequence + while (internal::is_trail(*start) && start != end) + ++start; + break; + } + } + return out; + } + + template + inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out) + { + static const uint32_t replacement_marker = internal::mask16(0xfffd); + return replace_invalid(start, end, out, replacement_marker); + } + + template + octet_iterator append(uint32_t cp, octet_iterator result) + { + if (!internal::is_code_point_valid(cp)) + throw invalid_code_point(cp); + + if (cp < 0x80) // one octet + *(result++) = static_cast(cp); + else if (cp < 0x800) { // two octets + *(result++) = static_cast((cp >> 6) | 0xc0); + *(result++) = static_cast((cp & 0x3f) | 0x80); + } + else if (cp < 0x10000) { // three octets + *(result++) = static_cast((cp >> 12) | 0xe0); + *(result++) = static_cast((cp >> 6) & 0x3f | 0x80); + *(result++) = static_cast((cp & 0x3f) | 0x80); + } + else if (cp <= internal::CODE_POINT_MAX) { // four octets + *(result++) = static_cast((cp >> 18) | 0xf0); + *(result++) = static_cast((cp >> 12)& 0x3f | 0x80); + *(result++) = static_cast((cp >> 6) & 0x3f | 0x80); + *(result++) = static_cast((cp & 0x3f) | 0x80); + } + else + throw invalid_code_point(cp); + + return result; + } + + template + uint32_t next(octet_iterator& it, octet_iterator end) + { + uint32_t cp = 0; + internal::utf_error err_code = internal::validate_next(it, end, &cp); + switch (err_code) { + case internal::OK : + break; + case internal::NOT_ENOUGH_ROOM : + throw not_enough_room(); + case internal::INVALID_LEAD : + case internal::INCOMPLETE_SEQUENCE : + case internal::OVERLONG_SEQUENCE : + throw invalid_utf8(*it); + case internal::INVALID_CODE_POINT : + throw invalid_code_point(cp); + } + return cp; + } + + template + uint32_t peek_next(octet_iterator it, octet_iterator end) + { + return next(it, end); + } + + template + uint32_t prior(octet_iterator& it, octet_iterator start) + { + octet_iterator end = it; + while (internal::is_trail(*(--it))) + if (it < start) + throw invalid_utf8(*it); // error - no lead byte in the sequence + octet_iterator temp = it; + return next(temp, end); + } + + /// Deprecated in versions that include "prior" + template + uint32_t previous(octet_iterator& it, octet_iterator pass_start) + { + octet_iterator end = it; + while (internal::is_trail(*(--it))) + if (it == pass_start) + throw invalid_utf8(*it); // error - no lead byte in the sequence + octet_iterator temp = it; + return next(temp, end); + } + + template + void advance (octet_iterator& it, distance_type n, octet_iterator end) + { + for (distance_type i = 0; i < n; ++i) + next(it, end); + } + + template + typename std::iterator_traits::difference_type + distance (octet_iterator first, octet_iterator last) + { + typename std::iterator_traits::difference_type dist; + for (dist = 0; first < last; ++dist) + next(first, last); + return dist; + } + + template + octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result) + { + while (start != end) { + uint32_t cp = internal::mask16(*start++); + // Take care of surrogate pairs first + if (internal::is_surrogate(cp)) { + if (start != end) { + uint32_t trail_surrogate = internal::mask16(*start++); + if (trail_surrogate >= internal::TRAIL_SURROGATE_MIN && trail_surrogate <= internal::TRAIL_SURROGATE_MAX) + cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET; + else + throw invalid_utf16(static_cast(trail_surrogate)); + } + else + throw invalid_utf16(static_cast(*start)); + + } + result = append(cp, result); + } + return result; + } + + template + u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result) + { + while (start != end) { + uint32_t cp = next(start, end); + if (cp > 0xffff) { //make a surrogate pair + *result++ = static_cast((cp >> 10) + internal::LEAD_OFFSET); + *result++ = static_cast((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN); + } + else + *result++ = static_cast(cp); + } + return result; + } + + template + octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result) + { + while (start != end) + result = append(*(start++), result); + + return result; + } + + template + u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result) + { + while (start < end) + (*result++) = next(start, end); + + return result; + } + + // The iterator class + template + class iterator : public std::iterator { + octet_iterator it; + octet_iterator range_start; + octet_iterator range_end; + public: + iterator () {}; + explicit iterator (const octet_iterator& octet_it, + const octet_iterator& range_start, + const octet_iterator& range_end) : + it(octet_it), range_start(range_start), range_end(range_end) + { + if (it < range_start || it > range_end) + throw std::out_of_range("Invalid utf-8 iterator position"); + } + // the default "big three" are OK + octet_iterator base () const { return it; } + uint32_t operator * () const + { + octet_iterator temp = it; + return next(temp, range_end); + } + bool operator == (const iterator& rhs) const + { + if (range_start != rhs.range_start || range_end != rhs.range_end) + throw std::logic_error("Comparing utf-8 iterators defined with different ranges"); + return (it == rhs.it); + } + bool operator != (const iterator& rhs) const + { + return !(operator == (rhs)); + } + iterator& operator ++ () + { + next(it, range_end); + return *this; + } + iterator operator ++ (int) + { + iterator temp = *this; + next(it, range_end); + return temp; + } + iterator& operator -- () + { + prior(it, range_start); + return *this; + } + iterator operator -- (int) + { + iterator temp = *this; + prior(it, range_start); + return temp; + } + }; // class iterator + +} // namespace utf8 + +#endif //header guard + + diff --git a/dep/include/utf8cpp/utf8/core.h b/dep/include/utf8cpp/utf8/core.h new file mode 100644 index 00000000000..538d56bd468 --- /dev/null +++ b/dep/include/utf8cpp/utf8/core.h @@ -0,0 +1,268 @@ +// Copyright 2006 Nemanja Trifunovic + +/* +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +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, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + + +#ifndef UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 +#define UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 + +#include + +// use MaNGOS core types +#include "Platform/Define.h" + +namespace utf8 +{ + // The typedefs for 8-bit, 16-bit and 32-bit unsigned integers + // You may need to change them to match your system. + // These typedefs have the same names as ones from cstdint, or boost/cstdint + + /* use MaNGOS alternatives + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; + */ + typedef uint8 uint8_t; + typedef uint16 uint16_t; + typedef uint32 uint32_t; + +// Helper code - not intended to be directly called by the library users. May be changed at any time +namespace internal +{ + // Unicode constants + // Leading (high) surrogates: 0xd800 - 0xdbff + // Trailing (low) surrogates: 0xdc00 - 0xdfff + const uint16_t LEAD_SURROGATE_MIN = 0xd800u; + const uint16_t LEAD_SURROGATE_MAX = 0xdbffu; + const uint16_t TRAIL_SURROGATE_MIN = 0xdc00u; + const uint16_t TRAIL_SURROGATE_MAX = 0xdfffu; + const uint16_t LEAD_OFFSET = LEAD_SURROGATE_MIN - (0x10000 >> 10); + const uint32_t SURROGATE_OFFSET = 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN; + + // Maximum valid value for a Unicode code point + const uint32_t CODE_POINT_MAX = 0x0010ffffu; + + template + inline uint8_t mask8(octet_type oc) + { + return static_cast(0xff & oc); + } + template + inline uint16_t mask16(u16_type oc) + { + return static_cast(0xffff & oc); + } + template + inline bool is_trail(octet_type oc) + { + return ((mask8(oc) >> 6) == 0x2); + } + + template + inline bool is_surrogate(u16 cp) + { + return (cp >= LEAD_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX); + } + + template + inline bool is_code_point_valid(u32 cp) + { + return (cp <= CODE_POINT_MAX && !is_surrogate(cp) && cp != 0xfffe && cp != 0xffff); + } + + template + inline typename std::iterator_traits::difference_type + sequence_length(octet_iterator lead_it) + { + uint8_t lead = mask8(*lead_it); + if (lead < 0x80) + return 1; + else if ((lead >> 5) == 0x6) + return 2; + else if ((lead >> 4) == 0xe) + return 3; + else if ((lead >> 3) == 0x1e) + return 4; + else + return 0; + } + + enum utf_error {OK, NOT_ENOUGH_ROOM, INVALID_LEAD, INCOMPLETE_SEQUENCE, OVERLONG_SEQUENCE, INVALID_CODE_POINT}; + + template + utf_error validate_next(octet_iterator& it, octet_iterator end, uint32_t* code_point) + { + uint32_t cp = mask8(*it); + // Check the lead octet + typedef typename std::iterator_traits::difference_type octet_difference_type; + octet_difference_type length = sequence_length(it); + + // "Shortcut" for ASCII characters + if (length == 1) { + if (end - it > 0) { + if (code_point) + *code_point = cp; + ++it; + return OK; + } + else + return NOT_ENOUGH_ROOM; + } + + // Do we have enough memory? + if (std::distance(it, end) < length) + return NOT_ENOUGH_ROOM; + + // Check trail octets and calculate the code point + switch (length) { + case 0: + return INVALID_LEAD; + break; + case 2: + if (is_trail(*(++it))) { + cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f); + } + else { + --it; + return INCOMPLETE_SEQUENCE; + } + break; + case 3: + if (is_trail(*(++it))) { + cp = ((cp << 12) & 0xffff) + ((mask8(*it) << 6) & 0xfff); + if (is_trail(*(++it))) { + cp += (*it) & 0x3f; + } + else { + std::advance(it, -2); + return INCOMPLETE_SEQUENCE; + } + } + else { + --it; + return INCOMPLETE_SEQUENCE; + } + break; + case 4: + if (is_trail(*(++it))) { + cp = ((cp << 18) & 0x1fffff) + ((mask8(*it) << 12) & 0x3ffff); + if (is_trail(*(++it))) { + cp += (mask8(*it) << 6) & 0xfff; + if (is_trail(*(++it))) { + cp += (*it) & 0x3f; + } + else { + std::advance(it, -3); + return INCOMPLETE_SEQUENCE; + } + } + else { + std::advance(it, -2); + return INCOMPLETE_SEQUENCE; + } + } + else { + --it; + return INCOMPLETE_SEQUENCE; + } + break; + } + // Is the code point valid? + if (!is_code_point_valid(cp)) { + for (octet_difference_type i = 0; i < length - 1; ++i) + --it; + return INVALID_CODE_POINT; + } + + if (code_point) + *code_point = cp; + + if (cp < 0x80) { + if (length != 1) { + std::advance(it, -(length-1)); + return OVERLONG_SEQUENCE; + } + } + else if (cp < 0x800) { + if (length != 2) { + std::advance(it, -(length-1)); + return OVERLONG_SEQUENCE; + } + } + else if (cp < 0x10000) { + if (length != 3) { + std::advance(it, -(length-1)); + return OVERLONG_SEQUENCE; + } + } + + ++it; + return OK; + } + + template + inline utf_error validate_next(octet_iterator& it, octet_iterator end) { + return validate_next(it, end, 0); + } + +} // namespace internal + + /// The library API - functions intended to be called by the users + + // Byte order mark + const uint8_t bom[] = {0xef, 0xbb, 0xbf}; + + template + octet_iterator find_invalid(octet_iterator start, octet_iterator end) + { + octet_iterator result = start; + while (result != end) { + internal::utf_error err_code = internal::validate_next(result, end); + if (err_code != internal::OK) + return result; + } + return result; + } + + template + inline bool is_valid(octet_iterator start, octet_iterator end) + { + return (find_invalid(start, end) == end); + } + + template + inline bool is_bom (octet_iterator it) + { + return ( + (internal::mask8(*it++)) == bom[0] && + (internal::mask8(*it++)) == bom[1] && + (internal::mask8(*it)) == bom[2] + ); + } +} // namespace utf8 + +#endif // header guard + + diff --git a/dep/include/utf8cpp/utf8/unchecked.h b/dep/include/utf8cpp/utf8/unchecked.h new file mode 100644 index 00000000000..4009cebe6e4 --- /dev/null +++ b/dep/include/utf8cpp/utf8/unchecked.h @@ -0,0 +1,228 @@ +// Copyright 2006 Nemanja Trifunovic + +/* +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +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, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + + +#ifndef UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 +#define UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 + +#include "core.h" + +namespace utf8 +{ + namespace unchecked + { + template + octet_iterator append(uint32_t cp, octet_iterator result) + { + if (cp < 0x80) // one octet + *(result++) = static_cast(cp); + else if (cp < 0x800) { // two octets + *(result++) = static_cast((cp >> 6) | 0xc0); + *(result++) = static_cast((cp & 0x3f) | 0x80); + } + else if (cp < 0x10000) { // three octets + *(result++) = static_cast((cp >> 12) | 0xe0); + *(result++) = static_cast((cp >> 6) & 0x3f | 0x80); + *(result++) = static_cast((cp & 0x3f) | 0x80); + } + else { // four octets + *(result++) = static_cast((cp >> 18) | 0xf0); + *(result++) = static_cast((cp >> 12)& 0x3f | 0x80); + *(result++) = static_cast((cp >> 6) & 0x3f | 0x80); + *(result++) = static_cast((cp & 0x3f) | 0x80); + } + return result; + } + + template + uint32_t next(octet_iterator& it) + { + uint32_t cp = internal::mask8(*it); + typename std::iterator_traits::difference_type length = utf8::internal::sequence_length(it); + switch (length) { + case 1: + break; + case 2: + it++; + cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f); + break; + case 3: + ++it; + cp = ((cp << 12) & 0xffff) + ((internal::mask8(*it) << 6) & 0xfff); + ++it; + cp += (*it) & 0x3f; + break; + case 4: + ++it; + cp = ((cp << 18) & 0x1fffff) + ((internal::mask8(*it) << 12) & 0x3ffff); + ++it; + cp += (internal::mask8(*it) << 6) & 0xfff; + ++it; + cp += (*it) & 0x3f; + break; + } + ++it; + return cp; + } + + template + uint32_t peek_next(octet_iterator it) + { + return next(it); + } + + template + uint32_t prior(octet_iterator& it) + { + while (internal::is_trail(*(--it))) ; + octet_iterator temp = it; + return next(temp); + } + + // Deprecated in versions that include prior, but only for the sake of consistency (see utf8::previous) + template + inline uint32_t previous(octet_iterator& it) + { + return prior(it); + } + + template + void advance (octet_iterator& it, distance_type n) + { + for (distance_type i = 0; i < n; ++i) + next(it); + } + + template + typename std::iterator_traits::difference_type + distance (octet_iterator first, octet_iterator last) + { + typename std::iterator_traits::difference_type dist; + for (dist = 0; first < last; ++dist) + next(first); + return dist; + } + + template + octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result) + { + while (start != end) { + uint32_t cp = internal::mask16(*start++); + // Take care of surrogate pairs first + if (internal::is_surrogate(cp)) { + uint32_t trail_surrogate = internal::mask16(*start++); + cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET; + } + result = append(cp, result); + } + return result; + } + + template + u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result) + { + while (start != end) { + uint32_t cp = next(start); + if (cp > 0xffff) { //make a surrogate pair + *result++ = static_cast((cp >> 10) + internal::LEAD_OFFSET); + *result++ = static_cast((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN); + } + else + *result++ = static_cast(cp); + } + return result; + } + + template + octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result) + { + while (start != end) + result = append(*(start++), result); + + return result; + } + + template + u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result) + { + while (start < end) + (*result++) = next(start); + + return result; + } + + // The iterator class + template + class iterator : public std::iterator { + octet_iterator it; + public: + iterator () {}; + explicit iterator (const octet_iterator& octet_it): it(octet_it) {} + // the default "big three" are OK + octet_iterator base () const { return it; } + uint32_t operator * () const + { + octet_iterator temp = it; + return next(temp); + } + bool operator == (const iterator& rhs) const + { + return (it == rhs.it); + } + bool operator != (const iterator& rhs) const + { + return !(operator == (rhs)); + } + iterator& operator ++ () + { + std::advance(it, internal::sequence_length(it)); + return *this; + } + iterator operator ++ (int) + { + iterator temp = *this; + std::advance(it, internal::sequence_length(it)); + return temp; + } + iterator& operator -- () + { + prior(it); + return *this; + } + iterator operator -- (int) + { + iterator temp = *this; + prior(it); + return temp; + } + }; // class iterator + + } // namespace utf8::unchecked +} // namespace utf8 + + +#endif // header guard + diff --git a/dep/include/vld/vld.h b/dep/include/vld/vld.h new file mode 100644 index 00000000000..ffe675d7d79 --- /dev/null +++ b/dep/include/vld/vld.h @@ -0,0 +1,104 @@ +//////////////////////////////////////////////////////////////////////////////// +// $Id: vld.h,v 1.27 2006/11/12 18:09:20 dmouldin Exp $ +// +// Visual Leak Detector (Version 1.9d) - Import Library Header +// Copyright (c) 2006 Dan Moulding +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +// See COPYING.txt for the full terms of the GNU Lesser General Public License. +// +//////////////////////////////////////////////////////////////////////////////// + +//#pragma once +#ifndef _VLD_H_ +#define _VLD_H_ + +#ifdef _DEBUG + +#pragma comment(lib, "vld.lib") + +// Force a symbolic reference to the global VisualLeakDetector class object from +// the DLL. This enusres that the DLL is loaded and linked with the program, +// even if no code otherwise imports any of the DLL's exports. +#pragma comment(linker, "/include:__imp_?vld@@3VVisualLeakDetector@@A") + +//////////////////////////////////////////////////////////////////////////////// +// +// Visual Leak Detector APIs +// + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +// VLDDisable - Disables Visual Leak Detector's memory leak detection at +// runtime. If memory leak detection is already disabled, then calling this +// function has no effect. +// +// Note: In multithreaded programs, this function operates on a per-thread +// basis. In other words, if you call this function from one thread, then +// memory leak detection is only disabled for that thread. If memory leak +// detection is enabled for other threads, then it will remain enabled for +// those other threads. It was designed to work this way to insulate you, +// the programmer, from having to ensure thread synchronization when calling +// VLDEnable() and VLDDisable(). Without this, calling these two functions +// unsychronized could result in unpredictable and unintended behavior. +// But this also means that if you want to disable memory leak detection +// process-wide, then you need to call this function from every thread in +// the process. +// +// Return Value: +// +// None. +// + +__declspec(dllimport) void VLDDisable (); + +// VLDEnable - Enables Visual Leak Detector's memory leak detection at runtime. +// If memory leak detection is already enabled, which it is by default, then +// calling this function has no effect. +// +// Note: In multithreaded programs, this function operates on a per-thread +// basis. In other words, if you call this function from one thread, then +// memory leak detection is only enabled for that thread. If memory leak +// detection is disabled for other threads, then it will remain disabled for +// those other threads. It was designed to work this way to insulate you, +// the programmer, from having to ensure thread synchronization when calling +// VLDEnable() and VLDDisable(). Without this, calling these two functions +// unsychronized could result in unpredictable and unintended behavior. +// But this also means that if you want to enable memory leak detection +// process-wide, then you need to call this function from every thread in +// the process. +// +// Return Value: +// +// None. +// + +__declspec(dllimport) void VLDEnable (); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#else // !_DEBUG + +#define VLDEnable() +#define VLDDisable() + +#endif // _DEBUG + +#endif // _VLD_H_ diff --git a/dep/include/zlib/zconf.h b/dep/include/zlib/zconf.h new file mode 100644 index 00000000000..03a9431c8be --- /dev/null +++ b/dep/include/zlib/zconf.h @@ -0,0 +1,332 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define deflatePrime z_deflatePrime +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table +# define zError z_zError + +# define alloc_func z_alloc_func +# define free_func z_free_func +# define in_func z_in_func +# define out_func z_out_func +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/dep/include/zlib/zlib.h b/dep/include/zlib/zlib.h new file mode 100644 index 00000000000..022817927ce --- /dev/null +++ b/dep/include/zlib/zlib.h @@ -0,0 +1,1357 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.3, July 18th, 2005 + + Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.3" +#define ZLIB_VERNUM 0x1230 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip streams in memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumualte before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + the value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, + Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() stop + if and when it gets to the next deflate block boundary. When decoding the + zlib or gzip format, this will cause inflate() to return immediately after + the header and before the first block. When doing a raw inflate, inflate() + will go ahead and process the first block, and will return when it gets to + the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 + if inflate() is currently decoding the last block in the deflate stream, + plus 128 if inflate() returned immediately after decoding an end-of-block + code or decoding the complete header up to just before the first byte of the + deflate stream. The end-of-block will not be indicated until all of the + uncompressed data from that block has been written to strm->next_out. The + number of unused bits may in general be greater than seven, except when + bit 7 of data_type is set, in which case the number of unused bits will be + less than eight. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster approach + may be used for the single inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() will decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically. Any information + contained in the gzip header is not retained, so applications that need that + information should instead use raw inflate, see inflateInit2() below, or + inflateBack() and perform their own processing of the gzip header and + trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may then + call inflateSync() to look for a good compression block if a partial recovery + of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), + no header crc, and the operating system will be set to 255 (unknown). If a + gzip stream is being written, strm->adler is a crc32 instead of an adler32. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as + Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy + parameter only affects the compression ratio but not the correctness of the + compressed output even if it is not set appropriately. Z_FIXED prevents the + use of dynamic Huffman codes, allowing for a simpler decoder for special + applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. In addition, the + current implementation of deflate will use at most the window size minus + 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() + or deflateInit2(). This would be used to allocate an output buffer + for deflation in a single pass, and so would be called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the + bits leftover from a previous deflate stream when appending to it. As such, + this function can only be used for raw deflate, and must be used before the + first deflate() call after a deflateInit2() or deflateReset(). bits must be + less than or equal to 16, and that many of the least significant bits of + value will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is + a crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg + is set to null if there is no error message. inflateInit2 does not perform + any decompression apart from reading the zlib header if present: this will + be done by inflate(). (So next_in and avail_in may be modified, but next_out + and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called + immediately after inflateInit2() or inflateReset() and before any call of + inflate() to set the dictionary. The application must insure that the + dictionary that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK can be used to + force inflate() to return immediately after header processing is complete + and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When + any of extra, name, or comment are not Z_NULL and the respective field is + not present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not + be allocated, or Z_VERSION_ERROR if the version of the library does not + match the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free + the allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects + only the raw deflate stream to decompress. This is different from the + normal behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format + error in the deflate stream (in which case strm->msg is set to indicate the + nature of the error), or Z_STREAM_ERROR if the stream was not properly + initialized. In the case of Z_BUF_ERROR, an input or output error can be + distinguished using strm->next_in which will be Z_NULL only if in() returned + an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to + out() returning non-zero. (in() will always be called before out(), so + strm->next_in is assured to be defined if out() returns non-zero.) Note + that inflateBack() cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least the value returned + by compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before + a compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h", or 'R' for run-length encoding + as in "wb1R". (See the description of deflateInit2 for more information + about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). The number of + uncompressed bytes written is limited to 4095. The caller should assure that + this limit is not exceeded. If it is exceeded, then gzprintf() will return + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read again later. + Only one character of push-back is allowed. gzungetc() returns the + character pushed, or -1 on failure. gzungetc() will fail if a + character has been pushed but not read yet, or if c is -1. The pushed + character will be discarded if the stream is repositioned with gzseek() + or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns 1 if file is being read directly without decompression, otherwise + zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); +/* + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is NULL, this function returns the required initial + value for the for the crc. Pre- and post-conditioning (one's complement) is + performed within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + +/* + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/dep/include/zthread/AtomicCount.h b/dep/include/zthread/AtomicCount.h new file mode 100644 index 00000000000..ea042a7feb2 --- /dev/null +++ b/dep/include/zthread/AtomicCount.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTATOMICCOUNT_H__ +#define __ZTATOMICCOUNT_H__ + +#include + +#include "zthread/Config.h" +#include "zthread/NonCopyable.h" + +namespace ZThread { + + /** + * @class AtomicCount + * @author Eric Crahen + * @date <2003-07-16T09:41:55-0400> + * @version 2.3.0 + * + * This class provides an interface to a small integer whose value can be + * incremented or decremented atomically. It's designed to be as simple and + * lightweight as possible so that it can be used cheaply to create reference + * counts. + */ + class ZTHREAD_API AtomicCount : public NonCopyable { + + void* _value; + + public: + + //! Create a new AtomicCount, initialized to a value of 1 + AtomicCount(); + + //! Destroy a new AtomicCount + ~AtomicCount(); + + //! Postfix decrement and return the current value + size_t operator--(int); + + //! Postfix increment and return the current value + size_t operator++(int); + + //! Prefix decrement and return the current value + size_t operator--(); + + //! Prefix increment and return the current value + size_t operator++(); + + + }; /* AtomicCount */ + + +} // namespace ZThread + +#endif // __ZTATOMICCOUNT_H__ diff --git a/dep/include/zthread/Barrier.h b/dep/include/zthread/Barrier.h new file mode 100644 index 00000000000..6aaafa93678 --- /dev/null +++ b/dep/include/zthread/Barrier.h @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTBARRIER_H__ +#define __ZTBARRIER_H__ + +#include "zthread/Condition.h" +#include "zthread/Guard.h" +#include "zthread/Waitable.h" +#include "zthread/Runnable.h" + +namespace ZThread { + + /** + * @class Barrier + * @author Eric Crahen + * @date <2003-07-16T09:54:01-0400> + * @version 2.2.1 + * + * A Barrier is a Waitable object that serves as synchronization points for + * a set of threads. A Barrier is constructed for a fixed number (N) of threads. + * Threads attempting to wait() on a Barrier ( 1 - N) will block until the Nth + * thread arrives. The Nth thread will awaken all the the others. + * + * An optional Runnable command may be associated with the Barrier. This will be run() + * when the Nth thread arrives and Barrier is not broken. + * + * Error Checking + * + * A Barrier uses an all-or-nothing. All threads involved must successfully + * meet at Barrier. If any one of those threads leaves before all the threads + * have (as the result of an error or exception) then all threads present at + * the Barrier will throw BrokenBarrier_Exception. + * + * A broken Barrier will cause all threads attempting to wait() on it to + * throw a BrokenBarrier_Exception. + * + * A Barrier will remain 'broken', until it is manually reset(). + */ + template + class Barrier : public Waitable, private NonCopyable { + + //! Broken flag + bool _broken; + //! Task flag + bool _haveTask; + //! Thread count + unsigned int _count; + //! Wait generation + unsigned int _generation; + //! Serialize access + LockType _lock; + //! Signaled when all thread arrive + Condition _arrived; + //! Command to run when all the thread arrive + Task _task; + + public: + + //! Create a Barrier + Barrier() + : _broken(false), _haveTask(false), _count(Count), _generation(0), _arrived(_lock), _task(0) { } + + /** + * Create a Barrier that executes the given task when all threads arrive + * without error + * + * @param task Task to associate with this Barrier + */ + Barrier(const Task& task) + : _broken(false), _haveTask(true), _count(Count), _generation(0), _arrived(_lock), + _task(task) { } + + //! Destroy this Barrier + virtual ~Barrier() {} + + /** + * Enter barrier and wait for the other threads to arrive. This can block for an indefinite + * amount of time. + * + * @exception BrokenBarrier_Exception thrown when any thread has left a wait on this + * Barrier as a result of an error. + * @exception Interrupted_Exception thrown when the calling thread is interrupted. + * A thread may be interrupted at any time, prematurely ending a wait + * for one thread and breaking the barrier for all threads + * + * @see Waitable::wait() + * + * @post If no exception was thrown, all threads have successfully arrived + * @post If an exception was thrown, the barrier is broken + */ + virtual void wait() { + + Guard g(_lock); + + if(_broken) + throw BrokenBarrier_Exception(); + + // Break the barrier if an arriving thread is interrupted + if(Thread::interrupted()) { + + // Release the other waiter, propagate the exception + _arrived.broadcast(); + _broken = true; + + throw Interrupted_Exception(); + + } + + if(--_count == 0) { + + // Wake the other threads if this was the last + // arriving thread + _arrived.broadcast(); + + // Try to run the associated task, if it throws then + // break the barrier and propagate the exception + try { + + if(_task) + _task->run(); + + _generation++; + + } catch(Synchronization_Exception&) { + + _broken = true; + throw; + + } catch(...) { assert(0); } + + } else { + + int myGeneration = _generation; + + try { + + // Wait for the other threads to arrive + _arrived.wait(); + + } catch(Interrupted_Exception&) { + + // Its possible for a thread to be interrupted before the + // last thread arrives. If the interrupted thread hasn't + // resumed, then just propagate the interruption + + if(myGeneration != _generation) + Thread().interrupt(); + + else _broken = true; + + } catch(Synchronization_Exception&) { + + // Break the barrier and propagate the exception + _broken = true; + throw; + + } + + // If the thread woke because it was notified by the thread + // that broke the barrier, throw. + if(_broken) + throw BrokenBarrier_Exception(); + + } + + } + + /** + * Enter barrier and wait for the other threads to arrive. This can block up to the + * amount of time specified with the timeout parameter. The barrier will not break + * if a thread leaves this function due to a timeout. + * + * @param timeout maximum amount of time, in milliseconds, to wait before + * + * @return + * - true if the set of tasks being wait for complete before + * timeout milliseconds elapse. + * - false otherwise. + * + * @exception BrokenBarrier_Exception thrown when any thread has left a wait on this + * Barrier as a result of an error. + * @exception Interrupted_Exception thrown when the calling thread is interrupted. + * A thread may be interrupted at any time, prematurely ending a wait + * for one thread and breaking the barrier for all threads + * + * @see Waitable::wait(unsigned long timeout) + * + * @post If no exception was thrown, all threads have successfully arrived + * @post If an exception was thrown, the barrier is broken + */ + virtual bool wait(unsigned long timeout) { + + Guard g(_lock); + + if(_broken) + throw BrokenBarrier_Exception(); + + // Break the barrier if an arriving thread is interrupted + if(Thread::interrupted()) { + + // Release the other waiter, propagate the exception + _arrived.broadcast(); + _broken = true; + + throw Interrupted_Exception(); + + } + + + if(--_count == 0) { + + // Wake the other threads if this was the last + // arriving thread + _arrived.broadcast(); + + // Try to run the associated task, if it throws then + // break the barrier and propagate the exception + try { + + if(_task) + _task->run(); + + _generation++; + + } catch(Synchronization_Exception&) { + + _broken = true; + throw; + + } catch(...) { assert(0); } + + } else { + + int myGeneration = _generation; + + try { + + // Wait for the other threads to arrive + if(!_arrived.wait(timeout)) + _broken = true; + + } catch(Interrupted_Exception&) { + + // Its possible for a thread to be interrupted before the + // last thread arrives. If the interrupted thread hasn't + // resumed, then just propagate the interruption + + if(myGeneration != _generation) + Thread().interrupt(); + + else _broken = true; + + } catch(Synchronization_Exception&) { + + // Break the barrier and propagate the exception + _broken = true; + throw; + + } + + // If the thread woke because it was notified by the thread + // that broke the barrier, throw. + if(_broken) + throw BrokenBarrier_Exception(); + + } + + return true; + + } + + /** + * Break the Barrier ending the wait for any threads that were waiting on + * the barrier. + * + * @post the Barrier is broken, all waiting threads will throw the + * BrokenBarrier_Exception + */ + void shatter() { + + Guard g(_lock); + + _broken = true; + _arrived.broadcast(); + + } + + /** + * Reset the Barrier. + * + * @post the Barrier is no longer Broken and can be used again. + */ + void reset() { + + Guard g(_lock); + + _broken = false; + _generation++; + _count = Count; + + } + + }; + + +} // namespace ZThread + +#endif // __ZTBARRIER_H__ diff --git a/dep/include/zthread/BiasedReadWriteLock.h b/dep/include/zthread/BiasedReadWriteLock.h new file mode 100644 index 00000000000..b1de74292cf --- /dev/null +++ b/dep/include/zthread/BiasedReadWriteLock.h @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTBIASEDREADWRITELOCK_H__ +#define __ZTBIASEDREADWRITELOCK_H__ + +#include "zthread/ReadWriteLock.h" +#include "zthread/Condition.h" +#include "zthread/Guard.h" +#include "zthread/FastMutex.h" + +namespace ZThread { + + /** + * @class BiasedReadWriteLock + * + * @author Eric Crahen + * @date <2003-07-16T10:22:34-0400> + * @version 2.2.7 + * + * A BiasedReadWriteLock has a bias toward writers. It will prefer read-write access over + * read-only access when many threads are contending for access to either Lockable this + * ReadWriteLock provides. + * + * @see ReadWriteLock + */ + class BiasedReadWriteLock : public ReadWriteLock { + + FastMutex _lock; + Condition _condRead; + Condition _condWrite; + + volatile int _activeWriters; + volatile int _activeReaders; + + volatile int _waitingReaders; + volatile int _waitingWriters; + + //! @class ReadLock + class ReadLock : public Lockable { + + BiasedReadWriteLock& _rwlock; + + public: + + ReadLock(BiasedReadWriteLock& rwlock) : _rwlock(rwlock) {} + + virtual ~ReadLock() {} + + virtual void acquire() { + _rwlock.beforeRead(); + } + + virtual bool tryAcquire(unsigned long timeout) { + return _rwlock.beforeReadAttempt(timeout); + } + + virtual void release() { + _rwlock.afterRead(); + } + + }; + + //! @class WriteLock + class WriteLock : public Lockable { + + BiasedReadWriteLock& _rwlock; + + public: + + WriteLock(BiasedReadWriteLock& rwlock) : _rwlock(rwlock) {} + + virtual ~WriteLock() {} + + + virtual void acquire() { + _rwlock.beforeWrite(); + } + + virtual bool tryAcquire(unsigned long timeout) { + return _rwlock.beforeWriteAttempt(timeout); + } + + virtual void release() { + _rwlock.afterWrite(); + } + + }; + + friend class ReadLock; + friend class WriteLock; + + ReadLock _rlock; + WriteLock _wlock; + + public: + + /** + * Create a BiasedReadWriteLock + * + * @exception Initialization_Exception thrown if resources could not be + * allocated for this object. + */ + BiasedReadWriteLock() : _condRead(_lock), _condWrite(_lock), _rlock(*this), _wlock(*this) { + + _activeWriters = 0; + _activeReaders = 0; + + _waitingReaders = 0; + _waitingWriters = 0; + + } + + //! Destroy this ReadWriteLock + virtual ~BiasedReadWriteLock() {} + + /** + * @see ReadWriteLock::getReadLock() + */ + virtual Lockable& getReadLock() { return _rlock; } + + /** + * @see ReadWriteLock::getWriteLock() + */ + virtual Lockable& getWriteLock() { return _wlock; } + + + protected: + + void beforeRead() { + + Guard guard(_lock); + + ++_waitingReaders; + + while(!allowReader()) { + + try { + + // wait + _condRead.wait(); + + } catch(...) { + + --_waitingReaders; + throw; + + } + + } + + --_waitingReaders; + ++_activeReaders; + + } + + bool beforeReadAttempt(unsigned long timeout) { + + Guard guard(_lock); + bool result = false; + + ++_waitingReaders; + + while(!allowReader()) { + + try { + + result = _condRead.wait(timeout); + + } catch(...) { + + --_waitingReaders; + throw; + + } + + } + + --_waitingReaders; + ++_activeReaders; + + return result; + } + + + void afterRead() { + + bool wakeReader = false; + bool wakeWriter = false; + + { + + Guard guard(_lock); + + --_activeReaders; + + wakeReader = (_waitingReaders > 0); + wakeWriter = (_waitingWriters > 0); + + } + + if(wakeWriter) + _condWrite.signal(); + + else if(wakeReader) + _condRead.signal(); + + } + + void beforeWrite() { + + Guard guard(_lock); + + ++_waitingWriters; + + while(!allowWriter()) { + + try { + + _condWrite.wait(); + + } catch(...) { + + --_waitingWriters; + throw; + + } + + } + + --_waitingWriters; + ++_activeWriters; + + } + + bool beforeWriteAttempt(unsigned long timeout) { + + Guard guard(_lock); + bool result = false; + + ++_waitingWriters; + + while(!allowWriter()) { + + try { + + result = _condWrite.wait(timeout); + + } catch(...) { + + --_waitingWriters; + throw; + } + + } + + --_waitingWriters; + ++_activeWriters; + + return result; + + } + + void afterWrite() { + + bool wakeReader = false; + bool wakeWriter = false; + + { + + Guard guard(_lock); + + --_activeWriters; + + wakeReader = (_waitingReaders > 0); + wakeWriter = (_waitingWriters > 0); + + } + + if(wakeWriter) + _condWrite.signal(); + + else if(wakeReader) + _condRead.signal(); + + } + + bool allowReader() { + return (_activeWriters == 0); + } + + bool allowWriter() { + return (_activeWriters == 0 && _activeReaders == 0); + } + + }; + +}; // __ZTBIASEDREADWRITELOCK_H__ + +#endif diff --git a/dep/include/zthread/BlockingQueue.h b/dep/include/zthread/BlockingQueue.h new file mode 100644 index 00000000000..ac17347d1cc --- /dev/null +++ b/dep/include/zthread/BlockingQueue.h @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTBLOCKINGQUEUE_H__ +#define __ZTBLOCKINGQUEUE_H__ + +#include "zthread/Guard.h" +#include "zthread/Condition.h" +#include "zthread/Queue.h" + +#include + +namespace ZThread { + + /** + * @class BlockingQueue + * @author Eric Crahen + * @date <2003-07-16T12:01:43-0400> + * @version 2.3.0 + * + * Like a LockedQueue, a BlockingQueue is a Queue implementation that provides + * serialized access to the items added to it. It differs by causing threads + * accessing the next() methods to block until a value becomes available. + */ + template > + class BlockingQueue : public Queue, public Lockable { + + //! Serialize access + LockType _lock; + + //! Signaled when empty + Condition _notEmpty; + + //! Storage backing the queue + StorageType _queue; + + //! Cancellation flag + volatile bool _canceled; + + public: + + //! Create a new BlockingQueue + BlockingQueue() : _notEmpty(_lock), _canceled(false) {} + + //! Destroy this BlockingQueue + virtual ~BlockingQueue() { } + + /** + * @see Queue::add(const T& item) + */ + virtual void add(const T& item) { + + Guard g(_lock); + + if(_canceled) + throw Cancellation_Exception(); + + _queue.push_back(item); + + _notEmpty.signal(); + + } + + /** + * @see Queue::add(const T& item, unsigned long timeout) + */ + virtual bool add(T item, unsigned long timeout) { + + try { + + Guard g(_lock, timeout); + + if(_canceled) + throw Cancellation_Exception(); + + _queue.push_back(item); + + _notEmpty.signal(); + + } catch(Timeout_Exception&) { return false; } + + return true; + + } + + /** + * Get a value from this Queue. The calling thread may block indefinitely. + * + * @return T next available value + * + * @exception Cancellation_Exception thrown if this Queue has been canceled. + * + * @exception Interrupted_Exception thrown if the calling thread is interrupted + * before a value becomes available. + * + * @pre The Queue should not have been canceled prior to the invocation of this function. + * @post The value returned will have been removed from the Queue. + * + * @see Queue::next() + */ + virtual T next() { + + Guard g(_lock); + + while(_queue.empty() && !_canceled) + _notEmpty.wait(); + + if( _queue.empty() ) + throw Cancellation_Exception(); + + T item = _queue.front(); + _queue.pop_front(); + + return item; + + } + + + /** + * Get a value from this Queue. The calling thread may block indefinitely. + * + * @param timeout maximum amount of time (milliseconds) this method may block + * the calling thread. + * + * @return T next available value + * + * @exception Cancellation_Exception thrown if this Queue has been canceled. + * @exception Timeout_Exception thrown if the timeout expires before a value + * can be retrieved. + * @exception Interrupted_Exception thrown if the calling thread is interrupted + * before a value becomes available. + * + * @pre The Queue should not have been canceled prior to the invocation of this function. + * @post The value returned will have been removed from the Queue. + * + * @see Queue::next(unsigned long timeout) + */ + virtual T next(unsigned long timeout) { + + Guard g(_lock, timeout); + + while(_queue.empty() && !_canceled) { + if(!_notEmpty.wait(timeout)) + throw Timeout_Exception(); + } + + if(_queue.empty() ) + throw Cancellation_Exception(); + + T item = _queue.front(); + _queue.pop_front(); + + return item; + + } + + + /** + * @see Queue::cancel() + * + * @post If threads are blocked on one of the next() functions then + * they will be awakened with a Cancellation_Exception. + */ + virtual void cancel() { + + Guard g(_lock); + + _notEmpty.broadcast(); + _canceled = true; + + } + + /** + * @see Queue::isCanceled() + */ + virtual bool isCanceled() { + + // Faster check since the queue will not become un-canceled + if(_canceled) + return true; + + Guard g(_lock); + + return _canceled; + + } + + /** + * @see Queue::size() + */ + virtual size_t size() { + + Guard g(_lock); + return _queue.size(); + + } + + /** + * @see Queue::size(unsigned long timeout) + */ + virtual size_t size(unsigned long timeout) { + + Guard g(_lock, timeout); + return _queue.size(); + + } + + public: + + virtual void acquire() { + _lock.acquire(); + } + + virtual bool tryAcquire(unsigned long timeout) { + return _lock.tryAcquire(timeout); + } + + virtual void release() { + _lock.release(); + } + + }; /* BlockingQueue */ + +} // namespace ZThread + +#endif // __ZTBLOCKINGQUEUE_H__ diff --git a/dep/include/zthread/BoundedQueue.h b/dep/include/zthread/BoundedQueue.h new file mode 100644 index 00000000000..2b3a616f1fb --- /dev/null +++ b/dep/include/zthread/BoundedQueue.h @@ -0,0 +1,387 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTBOUNDEDQUEUE_H__ +#define __ZTBOUNDEDQUEUE_H__ + +#include "zthread/Condition.h" +#include "zthread/Guard.h" +#include "zthread/Queue.h" + +#include + +namespace ZThread { + + /** + * @class BoundedQueue + * + * @author Eric Crahen + * @date <2003-07-16T13:54:04-0400> + * @version 2.3.0 + * + * A BoundedQueue provides serialized access to a set of values. It differs from other + * Queues by adding a maximum capacity, giving it the following properties: + * + * - Threads calling the empty() methods will be blocked until the BoundedQueue becomes empty. + * - Threads calling the next() methods will be blocked until the BoundedQueue has a value to + * return. + * - Threads calling the add() methods will be blocked until the number of values in the + * Queue drops below the maximum capacity. + * + * @see Queue + */ + template > + class BoundedQueue : public Queue, public Lockable { + + //! Maximum capacity for the Queue + size_t _capacity; + + //! Serialize access + LockType _lock; + + //! Signaled if not full + Condition _notFull; + + //! Signaled if not empty + Condition _notEmpty; + + //! Signaled if empty + Condition _isEmpty; + + //! Storage backing the queue + StorageType _queue; + + //! Cancellation flag + volatile bool _canceled; + + public: + + /** + * Create a BoundedQueue with the given capacity. + * + * @param capacity maximum number of values to allow in the Queue at + * at any time + */ + BoundedQueue(size_t capacity) + : _notFull(_lock), _notEmpty(_lock), _isEmpty(_lock), + _capacity(capacity), _canceled(false) {} + + //! Destroy this Queue + virtual ~BoundedQueue() { } + + /** + * Get the maximum capacity of this Queue. + * + * @return size_t maximum capacity + */ + size_t capacity() { + return _capacity; + } + + /** + * Add a value to this Queue. + * + * If the number of values in the queue matches the value returned by capacity() + * then the calling thread will be blocked until at least one value is removed from + * the Queue. + * + * @param item value to be added to the Queue + * + * @exception Cancellation_Exception thrown if this Queue has been canceled. + * @exception Interrupted_Exception thrown if the thread was interrupted while waiting + * to add a value + * + * @pre The Queue should not have been canceled prior to the invocation of this function. + * @post If no exception is thrown, a copy of item will have been added to the Queue. + * + * @see Queue::add(const T& item) + */ + virtual void add(const T& item) { + + Guard g(_lock); + + // Wait for the capacity of the Queue to drop + while ((_queue.size() == _capacity) && !_canceled) + _notFull.wait(); + + if(_canceled) + throw Cancellation_Exception(); + + _queue.push_back(item); + _notEmpty.signal(); // Wake any waiters + + + } + + /** + * Add a value to this Queue. + * + * If the number of values in the queue matches the value returned by capacity() + * then the calling thread will be blocked until at least one value is removed from + * the Queue. + * + * @param item value to be added to the Queue + * @param timeout maximum amount of time (milliseconds) this method may block + * the calling thread. + * + * @return + * - true if a copy of item can be added before timeout + * milliseconds elapse. + * - false otherwise. + * + * @exception Cancellation_Exception thrown if this Queue has been canceled. + * @exception Interrupted_Exception thrown if the thread was interrupted while waiting + * to add a value + * + * @pre The Queue should not have been canceled prior to the invocation of this function. + * @post If no exception is thrown, a copy of item will have been added to the Queue. + * + * @see Queue::add(const T& item, unsigned long timeout) + */ + virtual bool add(const T& item, unsigned long timeout) { + + try { + + Guard g(_lock, timeout); + + // Wait for the capacity of the Queue to drop + while ((_queue.size() == _capacity) && !_canceled) + if(!_notFull.wait(timeout)) + return false; + + if(_canceled) + throw Cancellation_Exception(); + + _queue.push_back(item); + _notEmpty.signal(); // Wake any waiters + + } catch(Timeout_Exception&) { return false; } + + return true; + + } + + /** + * Retrieve and remove a value from this Queue. + * + * If invoked when there are no values present to return then the calling thread + * will be blocked until a value arrives in the Queue. + * + * @return T next available value + * + * @exception Cancellation_Exception thrown if this Queue has been canceled. + * @exception Interrupted_Exception thrown if the thread was interrupted while waiting + * to retrieve a value + * + * @pre The Queue should not have been canceled prior to the invocation of this function. + * @post The value returned will have been removed from the Queue. + */ + virtual T next() { + + Guard g(_lock); + + while ( _queue.empty() && !_canceled) + _notEmpty.wait(); + + if( _queue.empty()) // Queue canceled + throw Cancellation_Exception(); + + T item = _queue.front(); + _queue.pop_front(); + + _notFull.signal(); // Wake any thread trying to add + + if(_queue.empty()) // Wake empty waiters + _isEmpty.broadcast(); + + return item; + + } + + /** + * Retrieve and remove a value from this Queue. + * + * If invoked when there are no values present to return then the calling thread + * will be blocked until a value arrives in the Queue. + * + * @param timeout maximum amount of time (milliseconds) this method may block + * the calling thread. + * + * @return T next available value + * + * @exception Cancellation_Exception thrown if this Queue has been canceled. + * @exception Timeout_Exception thrown if the timeout expires before a value + * can be retrieved. + * + * @pre The Queue should not have been canceled prior to the invocation of this function. + * @post The value returned will have been removed from the Queue. + */ + virtual T next(unsigned long timeout) { + + Guard g(_lock, timeout); + + // Wait for items to be added + while (_queue.empty() && !_canceled) { + if(!_notEmpty.wait(timeout)) + throw Timeout_Exception(); + } + + if(_queue.empty()) // Queue canceled + throw Cancellation_Exception(); + + T item = _queue.front(); + _queue.pop_front(); + + _notFull.signal(); // Wake add() waiters + + if(_queue.empty()) // Wake empty() waiters + _isEmpty.broadcast(); + + return item; + + } + + /** + * Cancel this queue. + * + * @post Any threads blocked by an add() function will throw a Cancellation_Exception. + * @post Any threads blocked by a next() function will throw a Cancellation_Exception. + * + * @see Queue::cancel() + */ + virtual void cancel() { + + Guard g(_lock); + + _canceled = true; + _notEmpty.broadcast(); // Wake next() waiters + + } + + /** + * @see Queue::isCanceled() + */ + virtual bool isCanceled() { + + // Faster check since the Queue will not become un-canceled + if(_canceled) + return true; + + Guard g(_lock); + + return _canceled; + + } + + /** + * @see Queue::size() + */ + virtual size_t size() { + + Guard g(_lock); + return _queue.size(); + + } + + /** + * @see Queue::size(unsigned long timeout) + */ + virtual size_t size(unsigned long timeout) { + + Guard g(_lock, timeout); + return _queue.size(); + + } + + /** + * Test whether any values are available in this Queue. + * + * The calling thread is blocked until there are no values present + * in the Queue. + * + * @return + * - true if there are no values available. + * - false if there are values available. + * + * @see Queue::empty() + */ + virtual bool empty() { + + Guard g(_lock); + + while(!_queue.empty()) // Wait for an empty signal + _isEmpty.wait(); + + return true; + + + } + + + /** + * Test whether any values are available in this Queue. + * + * The calling thread is blocked until there are no values present + * in the Queue. + * + * @param timeout maximum amount of time (milliseconds) this method may block + * the calling thread. + * + * @return + * - true if there are no values available. + * - false if there are values available. + * + * @exception Timeout_Exception thrown if timeout milliseconds + * expire before a value becomes available + * + * @see Queue::empty() + */ + virtual bool empty(unsigned long timeout) { + + Guard g(_lock, timeout); + + while(!_queue.empty()) // Wait for an empty signal + _isEmpty.wait(timeout); + + return true; + + } + + public: + + virtual void acquire() { + _lock.acquire(); + } + + virtual bool tryAcquire(unsigned long timeout) { + return _lock.tryAcquire(timeout); + } + + virtual void release() { + _lock.release(); + } + + }; /* BoundedQueue */ + +} // namespace ZThread + +#endif // __ZTBOUNDEDQUEUE_H__ diff --git a/dep/include/zthread/Cancelable.h b/dep/include/zthread/Cancelable.h new file mode 100644 index 00000000000..9151ec8dd03 --- /dev/null +++ b/dep/include/zthread/Cancelable.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTCANCELABLE_H__ +#define __ZTCANCELABLE_H__ + +#include "zthread/Exceptions.h" + +namespace ZThread { + + /** + * @class Cancelable + * + * @author Eric Crahen + * @date <2003-07-16T09:28:46-0400> + * @version 2.3.0 + * + * The Cancelable interface defines a common method of adding general disable-and-exit + * semantics to some object. By cancel()ing a Cancelable object, a request is + * made to disable that object. + * + * Disabling + * + * A cancel()ed object may not necessarily abort it work immediately. Often, it much more + * elegant for a cancel()ed object to complete handling whatever responsibilities have + * been assigned to it, but it will not take on any new responsibility. + * + * Exiting + * + * A cancel()ed should complete its responsibilities as soon as possible. + * Canceling is not only a request to stop taking on new responsibility, and to + * complete its current responsibility. Its also a request to complete dealing with its + * current responsibilities, quickly when possible. + */ + class Cancelable { + public: + + //! Destroy a Cancelable object. + virtual ~Cancelable() {} + + /** + * Canceling a Cancelable object makes a request to disable that object. + * This entails refusing to take on any new responsibility, and completing + * its current responsibilities quickly. + * + * Canceling an object more than once has no effect. + * + * @post The Cancelable object will have permanently transitioned to a + * disabled state; it will now refuse to accept new responsibility. + */ + virtual void cancel() = 0; + + /** + * Determine if a Cancelable object has been canceled. + * + * @return + * - true if cancel() was called prior to this function. + * - false otherwise. + */ + virtual bool isCanceled() = 0; + + }; /* Cancelable */ + + +} // namespace ZThread + +#endif // __ZTCANCELABLE_H__ diff --git a/dep/include/zthread/ClassLockable.h b/dep/include/zthread/ClassLockable.h new file mode 100644 index 00000000000..a10fb4932a2 --- /dev/null +++ b/dep/include/zthread/ClassLockable.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTCLASSLOCKABLE_H__ +#define __ZTCLASSLOCKABLE_H__ + +#include "zthread/CountedPtr.h" +#include "zthread/Mutex.h" + +namespace ZThread { + + /** + * @class ClassLockable + * + * @author Eric Crahen + * @date <2003-07-16T23:37:38-0400> + * @version 2.3.0 + * + * + */ + template + class ClassLockable : public Lockable { + + static CountedPtr _instance; + CountedPtr _lock; + + public: + + //! Create a ClassLockable + ClassLockable() + : _lock(_instance) {} + + //! acquire() the ClassLockable + virtual void acquire() { + _lock->acquire(); + } + + //! tryAcquire() the ClassLockable + virtual bool tryAcquire(unsigned long timeout) { + return _lock->tryAcquire(timeout); + } + + //! release() the ClassLockable + virtual void release() { + _lock->release(); + } + + }; + + template + CountedPtr ClassLockable::_instance(new LockType); + +} // namespace ZThread + +#endif // __ZTCLASSLOCKABLE_H__ diff --git a/dep/include/zthread/ConcurrentExecutor.h b/dep/include/zthread/ConcurrentExecutor.h new file mode 100644 index 00000000000..199fe306e08 --- /dev/null +++ b/dep/include/zthread/ConcurrentExecutor.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTCONCURRENTEXECUTOR_H__ +#define __ZTCONCURRENTEXECUTOR_H__ + +#include "zthread/PoolExecutor.h" + +namespace ZThread { + + /** + * @class ConcurrentExecutor + * + * @author Eric Crahen + * @date <2003-07-16T22:36:11-0400> + * @version 2.3.0 + * + * A ConcurrentExecutor spawns a single thread to service a series of Tasks. + * + * @see PoolExecutor. + */ + class ConcurrentExecutor : public Executor { + + PoolExecutor _executor; + + public: + + //! Create a ConcurrentExecutor + ConcurrentExecutor(); + + /** + * Interrupting a ConcurrentExecutor will cause the thread running the tasks to be + * be interrupted once during the execution of each task that has been submitted + * at the time this function is called. + * + * Tasks that are submitted after this function is called will + * not be interrupt()ed; unless this function is invoked again(). + * + * @code + * + * void aFunction() { + * + * ConcurrentExecutor executor; + * + * // Submit p Tasks + * for(size_t n = 0; n < p; n++) + * executor.execute(new aRunnable); + * + * // Tasks [m, p) may be interrupted, where m is the first task that has + * // not completed at the time the interrupt() is invoked. + * executor.interrupt(); + * + * // Submit (q - p) Tasks + * for(size_t n = p; n < q; n++) + * executor.execute(new Chore); + * + * // Tasks [p, q) are not interrupted + * + * } + * + * @endcode + */ + virtual void interrupt(); + + /** + * Submit a Task to this Executor. This will not block the current thread + * for very long. The task will be enqueued internally and eventually run + * in the context of the single thread driving all the Tasks submitted to this + * Executor. + * + * @exception Cancellation_Exception thrown if this Executor has been canceled. + * The Task being submitted will not be executed by this Executor. + * + * @exception Synchronization_Exception thrown only in the event of an error + * in the implementation of the library. + * + * @see Executor::execute(const Task&) + */ + virtual void execute(const Task&); + + /** + * @see Cancelable::cancel() + */ + virtual void cancel(); + + /** + * @see Cancelable::isCanceled() + */ + virtual bool isCanceled(); + + /** + * @see PoolExecutor::wait() + */ + virtual void wait(); + + /** + * @see PoolExecutor::wait(unsigned long timeout) + */ + virtual bool wait(unsigned long timeout); + + }; /* ConcurrentExecutor */ + +} // namespace ZThread + +#endif // __ZTCONCURRENTEXECUTOR_H__ diff --git a/dep/include/zthread/Condition.h b/dep/include/zthread/Condition.h new file mode 100644 index 00000000000..eba93619bfe --- /dev/null +++ b/dep/include/zthread/Condition.h @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTCONDITION_H__ +#define __ZTCONDITION_H__ + +#include "zthread/Lockable.h" +#include "zthread/NonCopyable.h" +#include "zthread/Waitable.h" + +namespace ZThread { + + class FifoConditionImpl; + + /** + * @class Condition + * @author Eric Crahen + * @date <2003-07-16T14:38:59-0400> + * @version 2.2.1 + * + * A Condition is a Waitable object used to block a thread until a particular + * condition is met. A Condition object is always used in conjunction with Lockable + * object. This object should be a FastMutex, Mutex, PriorityMutex or PriorityInheritanceMutex. + * + * Condition objects are reminiscent of POSIX condition variables in several ways but + * are slightly different. + * + * A Condition is not subject to spurious wakeup. + * + * Like all Waitable objects, Conditions are sensitive to Thread::interupt() which can + * be used to prematurely end a wait(). + * + * @see Thread::interupt() + * + * Before a wait() is performed on a Condition, the associated Lockable object should + * have been acquire()ed. When the wait() begins, that Lockable object is release()d + * (wait() will atomically begin the wait and unlock the Lockable). + * + * A thread blocked by wait() will remain so until an exception occurs, or until + * the thread awakened by a signal() or broadcast(). When the thread resumes execution, + * the associated Lockable is acquire()d before wait() returns. + * + * Scheduling + * + * Threads blocked on a Condition are resumed in FIFO order. + */ + class ZTHREAD_API Condition : public Waitable, private NonCopyable { + + FifoConditionImpl* _impl; + + public: + + /** + * Create a Condition associated with the given Lockable object. + * + * @param l Lockable object to associate with this Condition object. + */ + Condition(Lockable& l); + + //! Destroy Condition object + virtual ~Condition(); + + /** + * Wake one thread waiting on this Condition. + * + * The associated Lockable need not have been acquire when this function is + * invoked. + * + * @post a waiting thread, if any exists, will be awakened. + */ + void signal(); + + /** + * Wake all threads wait()ing on this Condition. + * + * The associated Lockable need not have been acquire when this function is + * invoked. + * + * @post all wait()ing threads, if any exist, will be awakened. + */ + void broadcast(); + + /** + * Wait for this Condition, blocking the calling thread until a signal or broadcast + * is received. + * + * This operation atomically releases the associated Lockable and blocks the calling thread. + * + * @exception Interrupted_Exception thrown when the calling thread is interrupted. + * A thread may be interrupted at any time, prematurely ending any wait. + * + * @pre The thread calling this method must have first acquired the associated + * Lockable object. + * + * @post A thread that has resumed execution without exception (because of a signal(), + * broadcast() or exception) will have acquire()d the associated Lockable object + * before returning from a wait(). + * + * @see Waitable::wait() + */ + virtual void wait(); + + /** + * Wait for this Condition, blocking the calling thread until a signal or broadcast + * is received. + * + * This operation atomically releases the associated Lockable and blocks the calling thread. + * + * @param timeout maximum amount of time (milliseconds) this method could block + * + * @return + * - true if the Condition receives a signal or broadcast before + * timeout milliseconds elapse. + * - false otherwise. + * + * @exception Interrupted_Exception thrown when the calling thread is interrupted. + * A thread may be interrupted at any time, prematurely ending any wait. + * + * @pre The thread calling this method must have first acquired the associated + * Lockable object. + * + * @post A thread that has resumed execution without exception (because of a signal(), + * broadcast() or exception) will have acquire()d the associated Lockable object + * before returning from a wait(). + * + * @see Waitable::wait(unsigned long timeout) + */ + virtual bool wait(unsigned long timeout); + + + }; + +} // namespace ZThread + +#endif // __ZTCONDITION_H__ diff --git a/dep/include/zthread/Config.h b/dep/include/zthread/Config.h new file mode 100644 index 00000000000..21e08bf8461 --- /dev/null +++ b/dep/include/zthread/Config.h @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTCONFIG_H__ +#define __ZTCONFIG_H__ + +// ===================================================================================== +// The following section describes the symbols the configure program will define. +// If you are not using configure (autoconf), then you make want to set these by +// uncommenting them here, or whatever other means you'd like. +// ===================================================================================== + +// (configure) +// Uncomment to disable actually changing the operating systems real thread priority +// #define ZTHREAD_DISABLE_PRIORITY 1 + +// (configure) +// Uncomment to disable compiling the interrupt() hook mechanisms. +// #define ZTHREAD_DISABLE_INTERRUPT 1 + +// (configure) +// Uncomment to select a Win32 ThreadOps implementation that uses _beginthreadex() +// otherwise, CreateThread() will be used for a Windows compilation +// #define HAVE_BEGINTHREADEX 1 + +// (configure) +// Uncomment to select a pthreads based implementation +// #define ZT_POSIX 1 + +// (configure) +// Uncomment to select a Windows based implementation that uses features not +// supported by windows 98 and 95 +// #define ZT_WIN32 1 + +// (configure) +// Uncomment to select a Windows based implementation that does not use features not +// supported by windows 98 and 95, but may not be compatible with 64 bit or alpha systems +// #define ZT_WIN9X 1 + +// (configure) +// Uncomment to select a MacOS based implementation +// #define ZT_MACOS 1 + +// (configure) +// Uncomment to prefer vanilla implementations of primatives when possible +// #define ZT_VANILLA 1 + +// ===================================================================================== +// The following section can be customized to select the implementation that is compiled +// Eventually, the configure program will be updated to define these symbols as well. +// ===================================================================================== + +// Uncomment to select very simple spinlock based implementations +// #define ZTHREAD_USE_SPIN_LOCKS 1 + +// Uncomment to select the vannila dual mutex implementation of FastRecursiveLock +// #define ZTHREAD_DUAL_LOCKS 1 + +// Uncomment to select a POSIX implementation of FastRecursiveLock that does not +// spin, but instead sleeps on a condition variable. +// #define ZTHREAD_CONDITION_LOCKS 1 + +// Uncomment if you want to eliminate inlined code used as a part of some template classes +// #define ZTHREAD_NOINLINE + +// Uncomment if you want to compile a DLL version of the library. (Win32) +// #define ZTHREAD_EXPORTS 1 + +// Uncomment if you want to compile a client using the DLL version of the library. (Win32) +// #define ZTHREAD_IMPORTS 1 + +// =================================================================================== +// The following section will attempt to guess the best configuration for your system +// =================================================================================== + +// Select an implementation by checking out the environment, first looking for +// compilers, then by looking for other definitions that could be present + +#if !defined(ZT_POSIX) && !defined(ZT_WIN9X) && !defined(ZT_WIN32) && !defined(ZT_MACOS) + +// Check for well known compilers +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__BCPLUSPLUS__) || defined(__MINGW32__) + +# define ZT_WIN32 + +#elif defined(__CYGWIN__) + +# define ZT_POSIX + +// Check for well known platforms +#elif defined(__linux__) || \ + defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \ + defined(__hpux) || \ + defined(__sgi) || \ + defined(__sun) + +# define ZT_POSIX + +// Check for definitions from well known headers +#elif defined(_POSIX_SOURCE) || defined(_XOPEN_SOURCE) + +# define ZT_POSIX + +#elif defined(WIN32_LEAN_AND_MEAN) + +# define ZT_WIN32 + +#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) + +# define ZT_MACOS + +#else +# error "Could not select implementation, define ZT_WIN9X, ZT_WIN32, ZT_POSIX or ZT_MACOS" +#endif + +#endif + +// Once an implementation has been selected, configure the API decorator +// for shared libraries if its needed. + +#if defined(ZTHREAD_SHARED) // Compatibility w/ past releases + +# define ZTHREAD_IMPORTS + +#elif defined(ZTHREAD_STATIC) + +# undef ZTHREAD_EXPORTS +# undef ZTHREAD_IMPORTS + +#endif + +// Windows users will get a static build by default, unless they +// define either ZTHREAD_IMPORTS or ZTHREAD_EXPORTS. Client code +// of a dll version of this library should define the first flag; +// To build the dll version of this library, define the second. + +#if defined(ZTHREAD_IMPORTS) && defined(ZTHREAD_EXPORTS) +# error "Import and export declarations are not valid" +#else + +# if defined(ZTHREAD_IMPORTS) +# define ZTHREAD_API __declspec(dllimport) +# elif defined(ZTHREAD_EXPORTS) +# define ZTHREAD_API __declspec(dllexport) +# else +# define ZTHREAD_API +# endif + +#endif + +// Once the API decorator is configured, create a macro for +// explicit template instantiation (whose need can hopefully +// be removed from the library) + +#if defined(ZTHREAD_EXPORTS) +# define EXPLICIT_TEMPLATE(X) template class __declspec( dllexport ) X; +#elif defined(ZTHREAD_IMPORTS) +# define EXPLICIT_TEMPLATE(X) template class __declspec( dllimport ) X; +#else +# define EXPLICIT_TEMPLATE(X) +#endif + +// Give libc a hint, should be defined by the user - but people tend +// to forget. + +#if !defined(REENTRANT) +# define REENTRANT +#endif + +#if !defined(_REENTRANT) +# define _REENTRANT +#endif + +#if defined(_MSC_VER) +# pragma warning(disable:4275) +# pragma warning(disable:4290) +# pragma warning(disable:4786) +# pragma warning(disable:4251) +# pragma warning(disable:4355) +#endif + +// Ensure that only one implementation is selected +#if \ +(defined(ZT_POSIX) && defined(ZT_WIN32)) \ + || (defined(ZT_POSIX) && defined(ZT_WIN9X)) \ + || (defined(ZT_WIN32) && defined(ZT_WIN9X)) + +# error "Only one implementation should be selected!" + +#endif + +#if defined(ZTHREAD_NOINLINE) +# define ZTHREAD_INLINE +#else +# define ZTHREAD_INLINE inline +#endif + +#endif // __ZTCONFIG_H__ + diff --git a/dep/include/zthread/CountedPtr.h b/dep/include/zthread/CountedPtr.h new file mode 100644 index 00000000000..a4dcc6ef248 --- /dev/null +++ b/dep/include/zthread/CountedPtr.h @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTCOUNTEDPTR_H__ +#define __ZTCOUNTEDPTR_H__ + +#include +#include + +#include "zthread/AtomicCount.h" + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable:4786) // warning: long template symbol name +# pragma warning(push) +# pragma warning(disable:4284) // warning: odd return type for operator-> +#endif + +namespace ZThread { + + /** + * @class CountedPtr + * + * @author Eric Crahen + * @date <2003-07-29T06:43:48-0400> + * @version 2.3.0 + * + */ + template + class CountedPtr { + +#if !defined(__MWERKS__) +#if !defined(_MSC_VER) || (_MSC_VER > 1200) + template friend class CountedPtr; +#endif +#endif + + CountT* _count; + T* _instance; + + public: + + CountedPtr() : _count(0), _instance(0) { } + +#if !defined(__MWERKS__) +#if !defined(_MSC_VER) || (_MSC_VER > 1200) + + explicit CountedPtr(T* raw) : _count(new CountT()), _instance(raw) { + (*_count)++; + } + +#endif +#endif + + template + explicit CountedPtr(U* raw) : _count(new CountT()), _instance(raw) { + (*_count)++; + } + +#if !defined(__MWERKS__) +#if !defined(_MSC_VER) || (_MSC_VER > 1200) + + CountedPtr(const CountedPtr& ptr) : _count(ptr._count), _instance(ptr._instance) { + + if(_count) + (*_count)++; + + } + +#endif +#endif + + template + CountedPtr(const CountedPtr& ptr) : _count(ptr._count), _instance(ptr._instance) { + + if(_count) + (*_count)++; + + } + + ~CountedPtr() { + + if(_count && --(*_count) == 0) { + + if(_instance) + delete _instance; + + delete _count; + + } + + } + + +#if !defined(__MWERKS__) +#if !defined(_MSC_VER) || (_MSC_VER > 1200) + + const CountedPtr& operator=(const CountedPtr& ptr) { + + typedef CountedPtr ThisT; + + ThisT(ptr).swap(*this); + return *this; + + } + +#endif +#endif + + template + const CountedPtr& operator=(const CountedPtr& ptr) { + + typedef CountedPtr ThisT; + + ThisT(ptr).swap(*this); + return *this; + + } + + void reset() { + + typedef CountedPtr ThisT; + ThisT().swap(*this); + + } + +#if !defined(__MWERKS__) +#if !defined(_MSC_VER) || (_MSC_VER > 1200) + + void swap(CountedPtr& ptr) { + + std::swap(_count, ptr._count); + std::swap(_instance, ptr._instance); + + } + +#endif +#endif + + template + void swap(CountedPtr& ptr) { + + std::swap(_count, ptr._count); + std::swap(_instance, ptr._instance); + + } + + // Convience operators + +#if !defined(__MWERKS__) +#if !defined(_MSC_VER) || (_MSC_VER > 1200) + + bool less(const CountedPtr& ptr) const { + return _instance < ptr._instance; + } + +#endif +#endif + + template + bool less(const CountedPtr& ptr) const { + return _instance < ptr._instance; + } + + +#if !defined(__MWERKS__) +#if !defined(_MSC_VER) || (_MSC_VER > 1200) + + bool equal(const CountedPtr& ptr) const { + return _count == ptr._count; + } + +#endif +#endif + + template + bool equal(const CountedPtr& ptr) const { + return _count == ptr._count; + } + + + friend inline bool operator==(const CountedPtr& lhs, const CountedPtr& rhs) { + return lhs.equal(rhs); + } + + friend inline bool operator<(const CountedPtr& lhs, const CountedPtr& rhs) { + return lhs.less(rhs); + } + + + T& operator*() { + assert(_instance != 0); + return *_instance; + } + + T* operator->() { + assert(_instance != 0); + return _instance; + } + + const T* operator->() const { + assert(_instance != 0); + return _instance; + } + + bool operator!() const { + return _instance == 0; + } + + operator bool() const { + return _instance != 0; + } + + }; /* CountedPtr */ + + template + inline bool operator<(CountedPtr const &lhs, CountedPtr const &rhs) { + return lhs.less(rhs); + } + + template + inline bool operator==(CountedPtr const &lhs, CountedPtr const &rhs) { + return lhs.equal(rhs.get); + } + + template + inline bool operator!=(CountedPtr const &lhs, CountedPtr const &rhs) { + return !(lhs.equal(rhs.get)); + } + + template + inline void swap(CountedPtr const &lhs, CountedPtr const &rhs) { + lhs.swap(rhs); + } + +#if !defined(__MWERKS__) +#if !defined(_MSC_VER) || (_MSC_VER > 1200) + + template + inline bool operator<(CountedPtr const &lhs, CountedPtr const &rhs) { + return lhs.less(rhs); + } + + template + inline bool operator==(CountedPtr const &lhs, CountedPtr const &rhs) { + return lhs.equal(rhs.get); + } + + template + inline bool operator!=(CountedPtr const &lhs, CountedPtr const &rhs) { + return !(lhs.equal(rhs.get)); + } + + template + inline void swap(CountedPtr const &lhs, CountedPtr const &rhs) { + lhs.swap(rhs); + } + +#endif +#endif + +} // namespace ZThread + +#ifdef _MSC_VER +# pragma warning(pop) +# pragma warning(pop) +#endif + + +#endif // __ZTCOUNTEDPTR_H__ diff --git a/dep/include/zthread/CountingSemaphore.h b/dep/include/zthread/CountingSemaphore.h new file mode 100644 index 00000000000..f580a65f726 --- /dev/null +++ b/dep/include/zthread/CountingSemaphore.h @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTCOUNTINGSEMAPHORE_H__ +#define __ZTCOUNTINGSEMAPHORE_H__ + +#include "zthread/Lockable.h" +#include "zthread/NonCopyable.h" + +namespace ZThread { + + class FifoSemaphoreImpl; + + /** + * @class CountingSemaphore + * @author Eric Crahen + * @date <2003-07-16T15:26:18-0400> + * @version 2.2.1 + * + * A CountingSemaphore is an owner-less Lockable object. + * + * It differs from a normal Semaphore in that there is no upper bound on the count + * and it will not throw an exception because a maximum value has been exceeded. + * + * @see Semaphore + * + * Threads blocked on a CountingSemaphore are resumed in FIFO order. + */ + class ZTHREAD_API CountingSemaphore : public Lockable, private NonCopyable { + + FifoSemaphoreImpl* _impl; + + public: + + /** + * Create a new CountingSemaphore. + * + * @param count - initial count + */ + CountingSemaphore(int initialCount = 0); + + //! Destroy the CountingSemaphore + virtual ~CountingSemaphore(); + + /** + * Provided to reflect the traditional Semaphore semantics + * + * @see acquire() + */ + void wait(); + + + /** + * Provided to reflect the traditional Semaphore semantics + * + * @see tryAcquire(unsigned long timeout) + */ + bool tryWait(unsigned long timeout); + + /** + * Provided to reflect the traditional Semaphore semantics + * + * @see release() + */ + void post(); + + + /** + * Get the current count of the semaphore. + * + * This value may change immediately after this function returns to the calling thread. + * + * @return int count + */ + virtual int count(); + + /** + * Decrement the count, blocking that calling thread if the count becomes 0 or + * less than 0. The calling thread will remain blocked until the count is + * raised above 0, an exception is thrown or the given amount of time expires. + * + * @param timeout maximum amount of time (milliseconds) this method could block + * + * @return + * - true if the Semaphore was acquired before timeout milliseconds elapse. + * - false otherwise. + * + * @exception Interrupted_Exception thrown when the calling thread is interrupted. + * A thread may be interrupted at any time, prematurely ending any wait. + * + * @see Lockable::tryAcquire(unsigned long timeout) + */ + virtual bool tryAcquire(unsigned long timeout); + + /** + * Decrement the count, blocking that calling thread if the count becomes 0 or + * less than 0. The calling thread will remain blocked until the count is + * raised above 0 or if an exception is thrown. + * + * @exception Interrupted_Exception thrown when the calling thread is interrupted. + * A thread may be interrupted at any time, prematurely ending any wait. + * + * @see Lockable::acquire() + */ + virtual void acquire(); + + /** + * Increment the count, unblocking one thread if count is positive. + * + * @see Lockable::release() + */ + virtual void release(); + + }; + + +} // namespace ZThread + +#endif // __ZTCOUNTINGSEMAPHORE_H__ diff --git a/dep/include/zthread/Exceptions.h b/dep/include/zthread/Exceptions.h new file mode 100644 index 00000000000..b7207932af4 --- /dev/null +++ b/dep/include/zthread/Exceptions.h @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTEXCEPTIONS_H__ +#define __ZTEXCEPTIONS_H__ + + +#include "zthread/Config.h" +#include + +namespace ZThread { + +/** + * @class Synchronization_Exception + * + * Serves as a general base class for the Exception hierarchy used within + * this package. + * + */ +class Synchronization_Exception { + + // Restrict heap allocation + static void * operator new(size_t size); + static void * operator new[](size_t size); + + std::string _msg; + +public: + + /** + * Create a new exception with a default error message 'Synchronization + * Exception' + */ + Synchronization_Exception() : _msg("Synchronization exception") { } + + /** + * Create a new exception with a given error message + * + * @param const char* - error message + */ + Synchronization_Exception(const char* msg) : _msg(msg) { } + + /** + * Get additional info about the exception + * + * @return const char* for the error message + */ + const char* what() const { + return _msg.c_str(); + } + +}; + + +/** + * @class Interrupted_Exception + * + * Used to describe an interrupted operation that would have normally + * blocked the calling thread + */ +class Interrupted_Exception : public Synchronization_Exception { + + public: + + //! Create a new exception + Interrupted_Exception() : Synchronization_Exception("Thread interrupted") { } + + //! Create a new exception + Interrupted_Exception(const char* msg) : Synchronization_Exception(msg) { } + +}; + + + +/** + * @class Deadlock_Exception + * + * Thrown when deadlock has been detected + */ +class Deadlock_Exception : public Synchronization_Exception { + public: + + //! Create a new exception + Deadlock_Exception() : Synchronization_Exception("Deadlock detected") { } + + //! Create a new exception + Deadlock_Exception(const char* msg) : Synchronization_Exception(msg) { } + +}; + + +/** + * @class InvalidOp_Exception + * + * Thrown when performing an illegal operation this object + */ +class InvalidOp_Exception : public Synchronization_Exception { + public: + + //! Create a new exception + InvalidOp_Exception() : Synchronization_Exception("Invalid operation") { } + //! Create a new exception + InvalidOp_Exception(const char* msg) : Synchronization_Exception(msg) { } + +}; + + + +/** + * @class Initialization_Exception + * + * Thrown when the system has no more resources to create new + * synchronization controls + */ +class Initialization_Exception : public Synchronization_Exception { + + public: + + //! Create a new exception + Initialization_Exception() : Synchronization_Exception("Initialization error") { } + //! Create a new exception + Initialization_Exception(const char*msg) : Synchronization_Exception(msg) { } + +}; + +/** + * @class Cancellation_Exception + * + * Cancellation_Exceptions are thrown by 'Canceled' objects. + * @see Cancelable + */ +class Cancellation_Exception : public Synchronization_Exception { + + public: + + //! Create a new Cancelltion_Exception + Cancellation_Exception() : Synchronization_Exception("Canceled") { } + //! Create a new Cancelltion_Exception + Cancellation_Exception(const char*msg) : Synchronization_Exception(msg) { } + +}; + + +/** + * @class Timeout_Exception + * + * There is no need for error messaged simply indicates the last + * operation timed out + */ +class Timeout_Exception : public Synchronization_Exception { + public: + + //! Create a new Timeout_Exception + Timeout_Exception() : Synchronization_Exception("Timeout") { } + //! Create a new + Timeout_Exception(const char*msg) : Synchronization_Exception(msg) { } + +}; + +/** + * @class NoSuchElement_Exception + * + * The last operation that was attempted on a Queue could not find + * the item that was indicated (during that last Queue method invocation) + */ +class NoSuchElement_Exception { + public: + + //! Create a new exception + NoSuchElement_Exception() {} + +}; + +/** + * @class InvalidTask_Exception + * + * Thrown when a task is not valid (e.g. null or start()ing a thread with + * no overriden run() method) + */ +class InvalidTask_Exception : public InvalidOp_Exception { + public: + + //! Create a new exception + InvalidTask_Exception() : InvalidOp_Exception("Invalid task") {} + +}; + +/** + * @class BrokenBarrier_Exception + * + * Thrown when a Barrier is broken because one of the participating threads + * has been interrupted. + */ +class BrokenBarrier_Exception : public Synchronization_Exception { + + public: + + //! Create a new exception + BrokenBarrier_Exception() : Synchronization_Exception("Barrier broken") { } + + //! Create a new exception + BrokenBarrier_Exception(const char* msg) : Synchronization_Exception(msg) { } + +}; + +/** + * @class Future_Exception + * + * Thrown when there is an error using a Future. + */ +class Future_Exception : public Synchronization_Exception { + + public: + + //! Create a new exception + Future_Exception() : Synchronization_Exception() { } + + //! Create a new exception + Future_Exception(const char* msg) : Synchronization_Exception(msg) { } + +}; + +}; + +#endif // __ZTEXCEPTIONS_H__ diff --git a/dep/include/zthread/Executor.h b/dep/include/zthread/Executor.h new file mode 100644 index 00000000000..833d0d4c3d1 --- /dev/null +++ b/dep/include/zthread/Executor.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTEXECUTOR_H__ +#define __ZTEXECUTOR_H__ + +#include "zthread/Thread.h" +#include "zthread/Waitable.h" + +namespace ZThread { + + + /** + * @class Executor + * + * @author Eric Crahen + * @date <2003-07-16T22:39:39-0400> + * @version 2.3.0 + * + * Execeutors are an implementation of the Executor pattern. This is + * a more versatile construct than a thread pool. A paper describing can + * be found in the proceedings of the 2002 VikingPLOP conference. + * + * Executing + * + * - execute()ing task with an Executor will submit the task, scheduling + * it for execution at some future time depending on the Executor being used. + * + * Disabling + * + * - cancel()ing an Executor will cause it to stop accepting + * new tasks. + * + * Interrupting + * + * - interrupt()ing an Executor will cause the any thread running + * a task which was submitted prior to the invocation of this function to + * be interrupted during the execution of that task. + * + * Waiting + * + * - wait()ing on a PoolExecutor will block the calling thread + * until all tasks that were submitted prior to the invocation of this function + * have completed. + * + * @see Cancelable + * @see Waitable + */ + class Executor : public Cancelable, public Waitable, private NonCopyable { + public: + + /** + * If supported by the Executor, interrupt all tasks submitted prior to + * the invocation of this function. + */ + virtual void interrupt() = 0; + + /** + * Submit a task to this Executor. + * + * @param task Task to be run by a thread managed by this executor + * + * @pre The Executor should have been canceled prior to this invocation. + * @post The submitted task will be run at some point in the future by this Executor. + * + * @exception Cancellation_Exception thrown if the Executor was canceled prior to + * the invocation of this function. + */ + virtual void execute(const Task& task) = 0; + + }; + +} // namespace ZThread + +#endif // __ZTEXECUTOR_H__ diff --git a/dep/include/zthread/FairReadWriteLock.h b/dep/include/zthread/FairReadWriteLock.h new file mode 100644 index 00000000000..8f183b62839 --- /dev/null +++ b/dep/include/zthread/FairReadWriteLock.h @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTFAIRREADWRITELOCK_H__ +#define __ZTFAIRREADWRITELOCK_H__ + +#include "zthread/ReadWriteLock.h" +#include "zthread/Condition.h" +#include "zthread/Guard.h" +#include "zthread/Mutex.h" + +namespace ZThread { + + /** + * @class FairReadWriteLock + * + * @author Eric Crahen + * @date <2003-07-16T10:26:25-0400> + * @version 2.2.7 + * + * A FairReadWriteLock maintains a balance between the order read-only access + * and read-write access is allowed. Threads contending for the pair of Lockable + * objects this ReadWriteLock provides will gain access to the locks in FIFO order. + * + * @see ReadWriteLock + */ + class FairReadWriteLock : public ReadWriteLock { + + Mutex _lock; + Condition _cond; + + volatile int _readers; + + //! @class ReadLock + class ReadLock : public Lockable { + + FairReadWriteLock& _rwlock; + + public: + + ReadLock(FairReadWriteLock& rwlock) : _rwlock(rwlock) {} + + virtual ~ReadLock() {} + + virtual void acquire() { + + Guard g(_rwlock._lock); + ++_rwlock._readers; + + } + + virtual bool tryAcquire(unsigned long timeout) { + + if(!_rwlock._lock.tryAcquire(timeout)) + return false; + + ++_rwlock._readers; + _rwlock._lock.release(); + + return true; + } + + virtual void release() { + + Guard g(_rwlock._lock); + --_rwlock._readers; + + if(_rwlock._readers == 0) + _rwlock._cond.signal(); + + } + + }; + + //! @class WriteLock + class WriteLock : public Lockable { + + FairReadWriteLock& _rwlock; + + public: + + WriteLock(FairReadWriteLock& rwlock) : _rwlock(rwlock) {} + + virtual ~WriteLock() {} + + virtual void acquire() { + + _rwlock._lock.acquire(); + + try { + + while(_rwlock._readers > 0) + _rwlock._cond.wait(); + + } catch(...) { + + _rwlock._lock.release(); + throw; + + } + + } + + virtual bool tryAcquire(unsigned long timeout) { + + if(!_rwlock._lock.tryAcquire(timeout)) + return false; + + try { + + while(_rwlock._readers > 0) + _rwlock._cond.wait(timeout); + + } catch(...) { + + _rwlock._lock.release(); + throw; + + } + + return true; + + } + + virtual void release() { + _rwlock._lock.release(); + } + + }; + + friend class ReadLock; + friend class WriteLock; + + ReadLock _rlock; + WriteLock _wlock; + + public: + + /** + * Create a BiasedReadWriteLock + * + * @exception Initialization_Exception thrown if resources could not be + * allocated for this object. + */ + FairReadWriteLock() : _cond(_lock), _readers(0), _rlock(*this), _wlock(*this) {} + + //! Destroy this ReadWriteLock + virtual ~FairReadWriteLock() {} + + /** + * @see ReadWriteLock::getReadLock() + */ + virtual Lockable& getReadLock() { return _rlock; } + + /** + * @see ReadWriteLock::getWriteLock() + */ + virtual Lockable& getWriteLock() { return _wlock; } + + }; + +}; // __ZTFAIRREADWRITELOCK_H__ + +#endif diff --git a/dep/include/zthread/FastMutex.h b/dep/include/zthread/FastMutex.h new file mode 100644 index 00000000000..1812c3e55a5 --- /dev/null +++ b/dep/include/zthread/FastMutex.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTFASTMUTEX_H__ +#define __ZTFASTMUTEX_H__ + +#include "zthread/Lockable.h" +#include "zthread/NonCopyable.h" + +namespace ZThread { + + class FastLock; + + /** + * @class FastMutex + * @author Eric Crahen + * @date <2003-07-19T18:45:39-0400> + * @version 2.2.0 + * + * A FastMutex is a small fast implementation of a non-recursive, mutually exclusive + * Lockable object. This implementation is a bit faster than the other Mutex classes + * as it involved the least overhead. However, this slight increase in speed is + * gained by sacrificing the robustness provided by the other classes. + * + * A FastMutex has the useful property of not being interruptable; that is to say + * that acquire() and tryAcquire() will not throw Interrupted_Exceptions. + * + * @see Mutex + * + * Scheduling + * + * Scheduling is left to the operating systems and may vary. + * + * Error Checking + * + * No error checking is performed, this means there is the potential for deadlock. + */ + class ZTHREAD_API FastMutex : public Lockable, private NonCopyable { + + FastLock* _lock; + + public: + + //! Create a FastMutex + FastMutex(); + + //! Destroy a FastMutex + virtual ~FastMutex(); + + /** + * Acquire exclusive access to the mutex. The calling thread will block until the + * lock can be acquired. No safety or state checks are performed. + * + * @pre The calling thread should not have previously acquired this lock. + * Deadlock will result if the same thread attempts to acquire the mutex more + * than once. + * + * @post The calling thread obtains the lock successfully if no exception is thrown. + * @exception Interrupted_Exception never thrown + */ + virtual void acquire(); + + /** + * Release exclusive access. No safety or state checks are performed. + * + * @pre the caller should have previously acquired this lock + */ + virtual void release(); + + /** + * Try to acquire exclusive access to the mutex. The calling thread will block until the + * lock can be acquired. No safety or state checks are performed. + * + * @pre The calling thread should not have previously acquired this lock. + * Deadlock will result if the same thread attempts to acquire the mutex more + * than once. + * + * @param timeout unused + * @return + * - true if the lock was acquired + * - false if the lock was acquired + * + * @post The calling thread obtains the lock successfully if no exception is thrown. + * @exception Interrupted_Exception never thrown + */ + virtual bool tryAcquire(unsigned long timeout); + + }; /* FastMutex */ + +}; + +#endif // __ZTFASTMUTEX_H__ diff --git a/dep/include/zthread/FastRecursiveMutex.h b/dep/include/zthread/FastRecursiveMutex.h new file mode 100644 index 00000000000..a30f4b53aa7 --- /dev/null +++ b/dep/include/zthread/FastRecursiveMutex.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTFASTRECURSIVEMUTEX_H__ +#define __ZTFASTRECURSIVEMUTEX_H__ + +#include "zthread/Lockable.h" +#include "zthread/NonCopyable.h" + +namespace ZThread { + + class FastRecursiveLock; + + /** + * @class FastRecursiveMutex + * + * @author Eric Crahen + * @date <2003-07-19T19:00:25-0400> + * @version 2.2.0 + * + * A FastRecursiveMutex is a small fast implementation of a recursive, mutally exclusive + * Lockable object. This implementation is a bit faster than the other Mutex classes + * as it involved the least overhead. However, this slight increase in speed is + * gained by sacrificing the robustness provided by the other classes. + * + * A FastRecursiveMutex has the useful property of not being interruptable; that is to say + * that acquire() and tryAcquire() will not throw Interrupted_Exceptions. + * + * @see RecursiveMutex + * + * Scheduling + * + * Scheduling is left to the operating systems and may vary. + * + * Error Checking + * + * No error checking is performed, this means there is the potential for deadlock. + */ + class ZTHREAD_API FastRecursiveMutex : public Lockable, private NonCopyable { + + FastRecursiveLock* _lock; + + public: + + //! Create a new FastRecursiveMutex + FastRecursiveMutex(); + + //! Destroy this FastRecursiveMutex + virtual ~FastRecursiveMutex(); + + /** + * Acquire exclusive access to the mutex. The calling thread will block until the + * lock can be acquired. No safety or state checks are performed. The calling thread + * may acquire the mutex nore than once. + * + * @post The calling thread obtains the lock successfully if no exception is thrown. + * @exception Interrupted_Exception never thrown + */ + virtual void acquire(); + + /** + * Release access. No safety or state checks are performed. + * + * @pre the caller should have previously acquired this lock at least once. + */ + virtual void release(); + + /** + * Try to acquire exclusive access to the mutex. The calling thread will block until the + * lock can be acquired. No safety or state checks are performed. The calling thread + * may acquire the mutex more than once. + * + * @param timeout unused + * @return + * - true if the lock was acquired + * - false if the lock was acquired + * + * @post The calling thread obtains the lock successfully if no exception is thrown. + * @exception Interrupted_Exception never thrown + */ + virtual bool tryAcquire(unsigned long timeout); + + }; + +} // namespace ZThread + +#endif // __ZTFASTRECURSIVEMUTEX_H__ diff --git a/dep/include/zthread/Guard.h b/dep/include/zthread/Guard.h new file mode 100644 index 00000000000..988c3cfa3c2 --- /dev/null +++ b/dep/include/zthread/Guard.h @@ -0,0 +1,511 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTGUARD_H__ +#define __ZTGUARD_H__ + +#include "zthread/NonCopyable.h" +#include "zthread/Exceptions.h" + +namespace ZThread { + +// +// GuardLockingPolicyContract { +// +// createScope(lock_type&) +// bool createScope(lock_type&, unsigned long) +// destroyScope(lock_type&) +// +// } +// + +/** + * @class LockHolder + * @author Eric Crahen + * @date <2003-07-16T17:55:42-0400> + * @version 2.2.0 + * + * This is a simple base class for Guards class. It allows Guards + * that have compatible targets to refer to each others targets + * allowing for the construction of Guards that share the same lock + * but have different locking policies. + */ +template +class LockHolder { + + LockType &_lock; + bool _enabled; + + public: + + template + LockHolder(T& t) : _lock(extract(t)._lock), _enabled(true) { } + + LockHolder(LockHolder& holder) : _lock(holder._lock), _enabled(true) { } + + LockHolder(LockType& lock) : _lock(lock), _enabled(true) { } + + void disable() { + _enabled = false; + } + + bool isDisabled() { + return !_enabled; + } + + LockType& getLock() { + return _lock; + } + + protected: + + template + static LockHolder& extract(T& t) { + // Design and Evolution of C++, page 328 + return (LockHolder&)(t); + } + +}; + +/** + * @class CompoundScope + * @author Eric Crahen + * @date <2003-07-16T17:55:42-0400> + * @version 2.2.0 + * + * Locking policy that aggregates two policies that share a target. + * It is not appropriate to use with any type of OverlappedScope + */ +template +class CompoundScope { + public: + + template + static void createScope(LockHolder& l) { + + Scope1::createScope(l); + Scope2::createScope(l); + + } + + template + static void createScope(LockHolder& l, unsigned long ms) { + + if(Scope1::createScope(l, ms)) + if(!Scope2::createScope(l, ms)) { + + Scope1::destroyScope(l); + return false; + + } + + return true; + + } + + template + static void destroyScope(LockHolder& l) { + + Scope1::destroyScope(l); + Scope2::destroyScope(l); + + } + +}; + + +/** + * @class LockedScope + * @author Eric Crahen + * @date <2003-07-16T17:55:42-0400> + * @version 2.2.0 + * + * Locking policy for Lockable objects. This policy acquire()s a Lockable + * when the protection scope is created, and it release()s a Lockable + * when the scope is destroyed. + */ +class LockedScope { + public: + + /** + * A new protection scope is being created by l2, using an existing scope + * created by l1. + * + * @param lock1 LockType1& is the LockHolder that holds the desired lock + * @param lock2 LockType1& is the LockHolder that wants to share + template + static void shareScope(LockHolder& l1, LockHolder& l2) { + + l2.getLock().acquire(); + + } + */ + + /** + * A new protection scope is being created. + * + * @param lock LockType& is a type of LockHolder. + */ + template + static bool createScope(LockHolder& l, unsigned long ms) { + + return l.getLock().tryAcquire(ms); + + } + + /** + * A new protection scope is being created. + * + * @param lock LockType& is a type of LockHolder. + */ + template + static void createScope(LockHolder& l) { + + l.getLock().acquire(); + + } + + /** + * A protection scope is being destroyed. + * + * @param lock LockType& is a type of LockHolder. + */ + template + static void destroyScope(LockHolder& l) { + + l.getLock().release(); + + } + +}; + + +/** + * @class UnlockedScope + * @author Eric Crahen + * @date <2003-07-16T17:55:42-0400> + * @version 2.2.0 + * + * Locking policy for Lockable objects. This policy release()s a Lockable + * when the protection scope is created, and it acquire()s a Lockable + * when the scope is destroyed. + */ +class UnlockedScope { + public: + + /** + * A new protection scope is being created by l2, using an existing scope + * created by l1. + * + * @param lock1 LockType1& is the LockHolder that holds the desired lock + * @param lock2 LockType1& is the LockHolder that wants to share + */ + template + static void shareScope(LockHolder& /*l1*/, LockHolder& l2) { + + l2.getLock().release(); + + } + + /** + * A new protection scope is being created. + * + * @param lock LockType& is a type of LockHolder. + template + static void createScope(LockHolder& l) { + + l.getLock().release(); + + } + */ + + /** + * A protection scope is being destroyed. + * + * @param lock LockType& is a type of LockHolder. + */ + template + static void destroyScope(LockHolder& l) { + + l.getLock().acquire(); + + } + +}; + + + +/** + * @class TimedLockedScope + * @author Eric Crahen + * @date <2003-07-16T17:55:42-0400> + * @version 2.2.0 + * + * Locking policy that attempts to enterScope some resource + * in a certain amount of time using an tryEnterScope-relase protocol. + */ +template +class TimedLockedScope { + public: + + /** + * Try to enterScope the given LockHolder. + * + * @param lock LockType& is a type of LockHolder. + */ + template + static void shareScope(LockHolder& l1, LockHolder& l2) { + + if(!l2.getLock().tryAcquire(TimeOut)) + throw Timeout_Exception(); + + } + + template + static void createScope(LockHolder& l) { + + if(!l.getLock().tryAcquire(TimeOut)) + throw Timeout_Exception(); + + } + + template + static void destroyScope(LockHolder& l) { + + l.getLock().release(); + + } + +}; + + +/** + * @class OverlappedScope + * @author Eric Crahen + * @date <2003-07-16T17:55:42-0400> + * @version 2.2.0 + * + * Locking policy allows the effective scope of two locks to overlap + * by releasing and disabling one lock before its Guard does so. + */ +class OverlappedScope { + public: + + template + static void transferScope(LockHolder& l1, LockHolder& l2) { + + l1.getLock().acquire(); + + l2.getLock().release(); + l2.disable(); + + } + + template + static void destroyScope(LockHolder& l) { + + l.getLock().release(); + + } + +}; + + + +/** + * @class Guard + * @author Eric Crahen + * @date <2003-07-16T17:55:42-0400> + * @version 2.2.0 + * + * Scoped locking utility. This template class can be given a Lockable + * synchronization object and can 'Guard' or serialize access to + * that method. + * + * For instance, consider a case in which a class or program have a + * Mutex object associated with it. Access can be serialized with a + * Guard as shown below. + * + * @code + * + * Mutex _mtx; + * void guarded() { + * + * Guard g(_mtx); + * + * } + * + * @endcode + * + * The Guard will lock the synchronization object when it is created and + * automatically unlock it when it goes out of scope. This eliminates + * common mistakes like forgetting to unlock your mutex. + * + * An alternative to the above example would be + * + * @code + * + * void guarded() { + * + * (Guard)(_mtx); + * + * } + * + * @endcode + * + * HOWEVER; using a Guard in this method is dangerous. Depending on your + * compiler an anonymous variable like this can go out of scope immediately + * which can result in unexpected behavior. - This is the case with MSVC + * and was the reason for introducing assertions into the Win32_MutexImpl + * to track this problem down + * + */ +template +class Guard : private LockHolder, private NonCopyable { + + friend class LockHolder; + +public: + + /** + * Create a Guard that enforces a the effective protection scope + * throughout the lifetime of the Guard object or until the protection + * scope is modified by another Guard. + * + * @param lock LockType the lock this Guard will use to enforce its + * protection scope. + * @post the protection scope may be ended prematurely + */ + Guard(LockType& lock) : LockHolder(lock) { + + LockingPolicy::createScope(*this); + + }; + + /** + * Create a Guard that enforces a the effective protection scope + * throughout the lifetime of the Guard object or until the protection + * scope is modified by another Guard. + * + * @param lock LockType the lock this Guard will use to enforce its + * protection scope. + * @post the protection scope may be ended prematurely + */ + Guard(LockType& lock, unsigned long timeout) : LockHolder(lock) { + + if(!LockingPolicy::createScope(*this, timeout)) + throw Timeout_Exception(); + + }; + + /** + * Create a Guard that shares the effective protection scope + * from the given Guard to this Guard. + * + * @param g Guard guard that is currently enabled + * @param lock LockType the lock this Guard will use to enforce its + * protection scope. + */ + template + Guard(Guard& g) : LockHolder(g) { + + LockingPolicy::shareScope(*this, extract(g)); + + } + + /** + * Create a Guard that shares the effective protection scope + * from the given Guard to this Guard. + * + * @param g Guard guard that is currently enabled + * @param lock LockType the lock this Guard will use to enforce its + * protection scope. + */ + Guard(Guard& g) : LockHolder(g) { + + LockingPolicy::shareScope(*this, g); + + } + + + /** + * Create a Guard that transfers the effective protection scope + * from the given Guard to this Guard. + * + * @param g Guard guard that is currently enabled + * @param lock LockType the lock this Guard will use to enforce its + * protection scope. + */ + template + Guard(Guard& g, LockType& lock) : LockHolder(lock) { + + LockingPolicy::transferScope(*this, extract(g)); + + } + + + /** + * Create a Guard that transfers the effective protection scope + * from the given Guard to this Guard. + * + * @param g Guard guard that is currently enabled + * @param lock LockType the lock this Guard will use to enforce its + * protection scope. + */ + Guard(Guard& g, LockType& lock) : LockHolder(lock) { + + LockingPolicy::transferScope(*this, g); + + } + + + /** + * Unlock a given Lockable object with the destruction of this Guard + */ + ~Guard() throw(); + +}; /* Guard */ + + +template +Guard::~Guard() throw() { + + try { + + if(!this->isDisabled()) + LockingPolicy::destroyScope(*this); + + } catch (...) { /* ignore */ } + +} + + +}; + +#endif // __ZTGUARD_H__ + + + + + + + diff --git a/dep/include/zthread/GuardedClass.h b/dep/include/zthread/GuardedClass.h new file mode 100644 index 00000000000..4ef3879cb08 --- /dev/null +++ b/dep/include/zthread/GuardedClass.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __GUARDEDCLASS_H__ +#define __GUARDEDCLASS_H__ + +#include "zthread/Guard.h" +#include "zthread/Mutex.h" + +namespace ZThread { + + /** + * @class GuardedClass + * @author Eric Crahen + * @date <2003-07-20T20:17:34-0400> + * @version 2.3.0 + * + * A simple wrapper template that uses Guard's to provide + * serialized access to an objects member functions. + */ + template + class GuardedClass { + + LockType _lock; + T* _ptr; + + class TransferedScope { + public: + + template + static void shareScope(LockHolder& l1, + LockHolder& l2) { + l1.disable(); + l2.getLock().acquire(); + } + + template + static void createScope(LockHolder& l) { + // Don't acquire the lock when scope the Guard is created + } + + template + static void destroyScope(LockHolder& l) { + l.getLock().release(); + } + + }; + + class Proxy : Guard { + + T* _object; + + public: + + Proxy(LockType& lock, T* object) : + Guard(lock), _object(object) { } + + T* operator->() { + return _object; + } + + }; + + GuardedClass(); + GuardedClass& operator=(const GuardedClass&); + + public: + + GuardedClass(T* ptr) : _ptr(ptr) {} + ~GuardedClass() { + if(_ptr) + delete _ptr; + } + + Proxy operator->() { + Proxy p(_lock, _ptr); + return p; + } + + }; + +} // namespace ZThread + +#endif // __ZTGUARDEDCLASS_H__ diff --git a/dep/include/zthread/Lockable.h b/dep/include/zthread/Lockable.h new file mode 100644 index 00000000000..32f7eeda97b --- /dev/null +++ b/dep/include/zthread/Lockable.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTLOCKABLE_H__ +#define __ZTLOCKABLE_H__ + +#include "zthread/Exceptions.h" + +namespace ZThread { + + /** + * @class Lockable + * @author Eric Crahen + * @date <2003-07-16T10:33:32-0400> + * @version 2.3.0 + * + * The Lockable interface defines a common method of adding general acquire-release + * semantics to an object. An acquire-release protocol does not necessarily imply + * exclusive access. + */ + class Lockable { + public: + + //! Destroy a Lockable object. + virtual ~Lockable() {} + + /** + * Acquire the Lockable object. + * + * This method may or may not block the caller for an indefinite amount + * of time. Those details are defined by specializations of this class. + * + * @exception Interrupted_Exception thrown if the calling thread is interrupted before + * the operation completes. + * + * @post The Lockable is acquired only if no exception was thrown. + */ + virtual void acquire() = 0; + + /** + * Attempt to acquire the Lockable object. + * + * This method may or may not block the caller for a definite amount + * of time. Those details are defined by specializations of this class; + * however, this method includes a timeout value that can be used to + * limit the maximum amount of time that a specialization could block. + * + * @param timeout - maximum amount of time (milliseconds) this method could block + * + * @return + * - true if the operation completes and the Lockable is acquired before + * the timeout expires. + * - false if the operation times out before the Lockable can be acquired. + * + * @exception Interrupted_Exception thrown if the calling thread is interrupted before + * the operation completes. + * + * @post The Lockable is acquired only if no exception was thrown. + */ + virtual bool tryAcquire(unsigned long timeout) = 0; + + /** + * Release the Lockable object. + * + * This method may or may not block the caller for an indefinite amount + * of time. Those details are defined by specializations of this class. + * + * @post The Lockable is released only if no exception was thrown. + */ + virtual void release() = 0; + + }; + + +} // namespace ZThread + +#endif // __ZTLOCKABLE_H__ diff --git a/dep/include/zthread/LockedQueue.h b/dep/include/zthread/LockedQueue.h new file mode 100644 index 00000000000..a1f0df26431 --- /dev/null +++ b/dep/include/zthread/LockedQueue.h @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTLOCKEDQUEUE_H__ +#define __ZTLOCKEDQUEUE_H__ + +#include "zthread/Guard.h" +#include "zthread/Queue.h" + +#include + +namespace ZThread { + + /** + * @class LockedQueue + * @author Eric Crahen + * @date <2003-07-16T11:42:33-0400> + * @version 2.3.0 + * + * A LockedQueue is the simple Queue implementation that provides + * serialized access to the values added to it. + */ + template > + class LockedQueue : public Queue { + + //! Serialize access to the Queue + LockType _lock; + + //! Storage backing the queue + StorageType _queue; + + //! Cancellation flag + volatile bool _canceled; + + public: + + //! Create a LockedQueue + LockedQueue() : _canceled(false) {} + + //! Destroy a LockedQueue + virtual ~LockedQueue() { } + + /** + * @see Queue::add(const T& item) + */ + virtual void add(const T& item) { + + Guard g(_lock); + + if(_canceled) + throw Cancellation_Exception(); + + _queue.push_back(item); + + } + + /** + * @see Queue::add(const T& item, unsigned long timeout) + */ + virtual bool add(const T& item, unsigned long timeout) { + + try { + + Guard g(_lock, timeout); + + if(_canceled) + throw Cancellation_Exception(); + + _queue.push_back(item); + + } catch(Timeout_Exception&) { return false; } + + return true; + + } + + /** + * @see Queue::next() + */ + virtual T next() { + + Guard g(_lock); + + if(_queue.empty() && _canceled) + throw Cancellation_Exception(); + + if(_queue.empty()) + throw NoSuchElement_Exception(); + + T item = _queue.front(); + _queue.pop_front(); + + return item; + + } + + + /** + * @see Queue::next(unsigned long timeout) + */ + virtual T next(unsigned long timeout) { + + Guard g(_lock, timeout); + + if(_queue.empty() && _canceled) + throw Cancellation_Exception(); + + if(_queue.empty()) + throw NoSuchElement_Exception(); + + T item = _queue.front(); + _queue.pop_front(); + + return item; + + } + + virtual T front() + { + Guard g(_lock); + + if(_queue.empty()) + throw NoSuchElement_Exception(); + + return _queue.front(); + } + + /** + * @see Queue::cancel() + */ + virtual void cancel() { + + Guard g(_lock); + + _canceled = true; + + } + + /** + * @see Queue::isCanceled() + */ + virtual bool isCanceled() { + + // Faster check since the queue will not become un-canceled + if(_canceled) + return true; + + Guard g(_lock); + + return _canceled; + + } + + /** + * @see Queue::size() + */ + virtual size_t size() { + + Guard g(_lock); + return _queue.size(); + + } + + /** + * @see Queue::size(unsigned long timeout) + */ + virtual size_t size(unsigned long timeout) { + + Guard g(_lock, timeout); + return _queue.size(); + + } + + }; /* LockedQueue */ + +} // namespace ZThread + +#endif // __ZTLOCKEDQUEUE_H__ diff --git a/dep/include/zthread/MonitoredQueue.h b/dep/include/zthread/MonitoredQueue.h new file mode 100644 index 00000000000..8578fe62b96 --- /dev/null +++ b/dep/include/zthread/MonitoredQueue.h @@ -0,0 +1,345 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTMONITOREDQUEUE_H__ +#define __ZTMONITOREDQUEUE_H__ + +#include "zthread/Condition.h" +#include "zthread/Guard.h" +#include "zthread/Queue.h" + +#include + +namespace ZThread { + + /** + * @class MonitoredQueue + * @author Eric Crahen + * @date <2003-07-16T20:23:28-0400> + * @version 2.3.0 + * + * A MonitoredQueue is a Queue implementation that provides serialized access to the + * items added to it. + * + * - Threads calling the empty() methods will be blocked until the BoundedQueue becomes empty. + * - Threads calling the next() methods will be blocked until the BoundedQueue has a value to + * return. + * + * @see Queue + */ + template > + class MonitoredQueue : public Queue, public Lockable { + + //! Serialize access + LockType _lock; + + //! Signaled on not empty + Condition _notEmpty; + + //! Signaled on empty + Condition _isEmpty; + + //! Storage backing the queue + StorageType _queue; + + //! Cancellation flag + volatile bool _canceled; + + public: + + //! Create a new MonitoredQueue + MonitoredQueue() + : _notEmpty(_lock), _isEmpty(_lock), _canceled(false) {} + + //! Destroy a MonitoredQueue, delete remaining items + virtual ~MonitoredQueue() { } + + /** + * Add a value to this Queue. + * + * @param item value to be added to the Queue + * + * @exception Cancellation_Exception thrown if this Queue has been canceled. + * @exception Interrupted_Exception thrown if the thread was interrupted while waiting + * to add a value + * + * @pre The Queue should not have been canceled prior to the invocation of this function. + * @post If no exception is thrown, a copy of item will have been added to the Queue. + * + * @see Queue::add(const T& item) + */ + virtual void add(const T& item) { + + Guard g(_lock); + + // Allow no further additions in the canceled state + if(_canceled) + throw Cancellation_Exception(); + + _queue.push_back( item ); + + _notEmpty.signal(); // Wake one waiter + + } + + /** + * Add a value to this Queue. + * + * @param item value to be added to the Queue + * @param timeout maximum amount of time (milliseconds) this method may block + * the calling thread. + * + * @return + * - true if a copy of item can be added before timeout + * milliseconds elapse. + * - false otherwise. + * + * @exception Cancellation_Exception thrown if this Queue has been canceled. + * @exception Interrupted_Exception thrown if the thread was interrupted while waiting + * to add a value + * + * @pre The Queue should not have been canceled prior to the invocation of this function. + * @post If no exception is thrown, a copy of item will have been added to the Queue. + * + * @see Queue::add(const T& item, unsigned long timeout) + */ + virtual bool add(const T& item, unsigned long timeout) { + + try { + + Guard g(_lock, timeout); + + if(_canceled) + throw Cancellation_Exception(); + + _queue.push_back(item); + + _notEmpty.signal(); + + } catch(Timeout_Exception&) { return false; } + + return true; + + } + + /** + * Retrieve and remove a value from this Queue. + * + * If invoked when there are no values present to return then the calling thread + * will be blocked until a value arrives in the Queue. + * + * @return T next available value + * + * @exception Cancellation_Exception thrown if this Queue has been canceled. + * @exception Interrupted_Exception thrown if the thread was interrupted while waiting + * to retrieve a value + * + * @pre The Queue should not have been canceled prior to the invocation of this function. + * @post The value returned will have been removed from the Queue. + */ + virtual T next() { + + Guard g(_lock); + + while (_queue.empty() && !_canceled) + _notEmpty.wait(); + + if(_queue.empty()) // Queue canceled + throw Cancellation_Exception(); + + T item = _queue.front(); + _queue.pop_front(); + + if(_queue.empty()) // Wake empty waiters + _isEmpty.broadcast(); + + return item; + + } + + /** + * Retrieve and remove a value from this Queue. + * + * If invoked when there are no values present to return then the calling thread + * will be blocked until a value arrives in the Queue. + * + * @param timeout maximum amount of time (milliseconds) this method may block + * the calling thread. + * + * @return T next available value + * + * @exception Cancellation_Exception thrown if this Queue has been canceled. + * @exception Timeout_Exception thrown if the timeout expires before a value + * can be retrieved. + * + * @pre The Queue should not have been canceled prior to the invocation of this function. + * @post The value returned will have been removed from the Queue. + */ + virtual T next(unsigned long timeout) { + + Guard g(_lock, timeout); + + while(_queue.empty() && !_canceled) { + if(!_notEmpty.wait(timeout)) + throw Timeout_Exception(); + } + + if( _queue.empty()) // Queue canceled + throw Cancellation_Exception(); + + T item = _queue.front(); + _queue.pop_front(); + + if(_queue.empty()) // Wake empty waiters + _isEmpty.broadcast(); + + return item; + + } + + + /** + * Cancel this queue. + * + * @post Any threads blocked by a next() function will throw a Cancellation_Exception. + * + * @see Queue::cancel() + */ + virtual void cancel() { + + Guard g(_lock); + + _canceled = true; + _notEmpty.broadcast(); // Wake next() waiters + + } + + /** + * @see Queue::isCanceled() + */ + virtual bool isCanceled() { + + // Faster check since the queue will not become un-canceled + if(_canceled) + return true; + + Guard g(_lock); + + return _canceled; + + } + + + /** + * @see Queue::size() + */ + virtual size_t size() { + + Guard g(_lock); + return _queue.size(); + + } + + /** + * @see Queue::size(unsigned long timeout) + */ + virtual size_t size(unsigned long timeout) { + + Guard g(_lock, timeout); + return _queue.size(); + + } + + /** + * Test whether any values are available in this Queue. + * + * The calling thread is blocked until there are no values present + * in the Queue. + * + * @return + * - true if there are no values available. + * - false if there are values available. + * + * @see Queue::empty() + */ + virtual bool empty() { + + Guard g(_lock); + + while(!_queue.empty()) // Wait for an empty signal + _isEmpty.wait(); + + return true; + + } + + /** + * Test whether any values are available in this Queue. + * + * The calling thread is blocked until there are no values present + * in the Queue. + * + * @param timeout maximum amount of time (milliseconds) this method may block + * the calling thread. + * + * @return + * - true if there are no values available. + * - false if there are values available. + * + * @exception Timeout_Exception thrown if timeout milliseconds + * expire before a value becomes available + * + * @see Queue::empty() + */ + virtual bool empty(unsigned long timeout) { + + Guard g(_lock, timeout); + + while(!_queue.empty()) // Wait for an empty signal + _isEmpty.wait(timeout); + + return true; + + } + + public: + + virtual void acquire() { + _lock.acquire(); + } + + virtual bool tryAcquire(unsigned long timeout) { + return _lock.tryAcquire(timeout); + } + + virtual void release() { + _lock.release(); + } + + + }; /* MonitoredQueue */ + + +} // namespace ZThread + +#endif // __ZTMONITOREDQUEUE_H__ + diff --git a/dep/include/zthread/Mutex.h b/dep/include/zthread/Mutex.h new file mode 100644 index 00000000000..1b521b1598d --- /dev/null +++ b/dep/include/zthread/Mutex.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTMUTEX_H__ +#define __ZTMUTEX_H__ + +#include "zthread/Lockable.h" +#include "zthread/NonCopyable.h" + +namespace ZThread { + + class FifoMutexImpl; + + /** + * @class Mutex + * @author Eric Crahen + * @date <2003-07-16T19:35:28-0400> + * @version 2.2.1 + * + * A Mutex is used to provide serialized (one thread at a time) access to some portion + * of code. This is accomplished by attempting to acquire the Mutex before entering that + * piece of code, and by releasing the Mutex when leaving that region. It is a non-reentrant, + * MUTual EXclusion Lockable object. + * + * @see Guard + * + * Scheduling + * + * Threads competing to acquire() a Mutex are granted access in FIFO order. + * + * Error Checking + * + * A Mutex will throw a Deadlock_Exception if an attempt to acquire a Mutex more + * than once is made from the context of the same thread. + * + * A Mutex will throw an InvalidOp_Exception if an attempt to release a Mutex is + * made from the context of a thread that does not currently own that Mutex. + */ + class ZTHREAD_API Mutex : public Lockable, private NonCopyable { + + FifoMutexImpl* _impl; + + public: + + //! Create a new Mutex. + Mutex(); + + //! Destroy this Mutex. + virtual ~Mutex(); + + /** + * Acquire a Mutex, possibly blocking until either the current owner of the + * Mutex releases it or until an exception is thrown. + * + * Only one thread may acquire() the Mutex at any given time. + * + * @exception Interrupted_Exception thrown when the calling thread is interrupted. + * A thread may be interrupted at any time, prematurely ending any wait. + * @exception Deadlock_Exception thrown when the same thread attempts to acquire + * a Mutex more than once, without having first release()ed it. + * + * @pre the calling thread must not have already acquired Mutex + * + * @post the calling thread successfully acquired Mutex only if no exception + * was thrown. + * + * @see Lockable::acquire() + */ + virtual void acquire(); + + /** + * Acquire a Mutex, possibly blocking until the current owner of the + * Mutex releases it, until an exception is thrown or until the given amount + * of time expires. + * + * Only one thread may acquire the Mutex at any given time. + * + * @param timeout maximum amount of time (milliseconds) this method could block + * @return + * - true if the lock was acquired + * - false if the lock was acquired + * + * @exception Interrupted_Exception thrown when the calling thread is interrupted. + * A thread may be interrupted at any time, prematurely ending any wait. + * @exception Deadlock_Exception thrown when the same thread attempts to acquire + * a Mutex more than once, without having first released it. + * + * @pre the calling thread must not have already acquired Mutex + * + * @post the calling thread successfully acquired Mutex only if no exception + * was thrown. + * + * @see Lockable::tryAcquire(unsigned long timeout) + */ + virtual bool tryAcquire(unsigned long timeout); + + /** + * Release a Mutex allowing another thread to acquire it. + * + * @exception InvalidOp_Exception - thrown if there is an attempt to release is + * a Mutex that was not owner by the calling thread. + * + * @pre the calling thread must have first acquired the Mutex. + * @post the calling thread successfully released Mutex only if no exception + * was thrown. + * + * @see Lockable::release() + */ + virtual void release(); + + }; + + +} // namespace ZThread + +#endif // __ZTMUTEX_H__ diff --git a/dep/include/zthread/NonCopyable.h b/dep/include/zthread/NonCopyable.h new file mode 100644 index 00000000000..5c33f345f46 --- /dev/null +++ b/dep/include/zthread/NonCopyable.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTNONCOPYABLE_H__ +#define __ZTNONCOPYABLE_H__ + +namespace ZThread { + + /** + * @class NonCopyable + * @author Eric Crahen + * @date <2003-07-16T19:36:00-0400> + * @version 2.2.11 + * + * Some objects kind of objects should not be copied. This is particularly true + * of objects involved in providing mutually exclusive access to something + * (e.g. Mutexes, Queues, Semaphores, etc.) + * + * Based on Dave Abrahams contribution to the Boost library. + */ + class NonCopyable { + + //! Restrict the copy constructor + NonCopyable(const NonCopyable&); + + //! Restrict the assignment operator + const NonCopyable& operator=(const NonCopyable&); + + protected: + + //! Create a NonCopyable object + NonCopyable() { } + + //! Destroy a NonCopyable object + ~NonCopyable() { } + + }; /* NonCopyable */ + +} // namespace ZThread + +#endif // __ZTNONCOPYABLE_H__ diff --git a/dep/include/zthread/PoolExecutor.h b/dep/include/zthread/PoolExecutor.h new file mode 100644 index 00000000000..82f5c4f05ba --- /dev/null +++ b/dep/include/zthread/PoolExecutor.h @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTPOOLEXECUTOR_H__ +#define __ZTPOOLEXECUTOR_H__ + +#include "zthread/Executor.h" +#include "zthread/CountedPtr.h" +#include "zthread/Thread.h" + +namespace ZThread { + + namespace { class ExecutorImpl; } + + /** + * @class PoolExecutor + * + * @author Eric Crahen + * @date <2003-07-16T22:41:07-0400> + * @version 2.3.0 + * + * A PoolExecutor spawns a set of threads that are used to run tasks + * that are submitted in parallel. A PoolExecutor supports the following + * optional operations, + * + * - cancel()ing a PoolExecutor will cause it to stop accepting + * new tasks. + * + * - interrupt()ing a PoolExecutor will cause the any thread running + * a task which was submitted prior to the invocation of this function to + * be interrupted during the execution of that task. + * + * - wait()ing on a PoolExecutor will block the calling thread + * until all tasks that were submitted prior to the invocation of this function + * have completed. + * + * @see Executor. + */ + class PoolExecutor : public Executor { + + //! Reference to the internal implementation + CountedPtr< ExecutorImpl > _impl; + + //! Cancellation task + Task _shutdown; + + public: + + /** + * Create a PoolExecutor + * + * @param n number of threads to service tasks with + */ + PoolExecutor(size_t n); + + //! Destroy a PoolExecutor + virtual ~PoolExecutor(); + + /** + * Invoking this function causes each task that had been submitted prior to + * this function to be interrupted. Tasks submitted after the invocation of + * this function are unaffected. + * + * @post Any task submitted prior to the invocation of this function will be + * run in the context of an interrupted thread. + * @post Any thread already executing a task which was submitted prior to the + * invocation of this function will be interrupted. + */ + virtual void interrupt(); + + /** + * Alter the number of threads being used to execute submitted tasks. + * + * @param n number of worker threads. + * + * @pre n must be greater than 0. + * @post n threads will be executing tasks submitted to this executor. + * + * @exception InvalidOp_Exception thrown if the new number of threads + * n is less than 1. + */ + void size(size_t n); + + /** + * Get the current number of threads being used to execute submitted tasks. + * + * @return n number of worker threads. + */ + size_t size(); + + /** + * Submit a task to this Executor. + * + * This will not block the calling thread very long. The submitted task will + * be executed at some later point by another thread. + * + * @param task Task to be run by a thread managed by this executor + * + * @pre The Executor should have been canceled prior to this invocation. + * @post The submitted task will be run at some point in the future by this Executor. + * + * @exception Cancellation_Exception thrown if the Executor was canceled prior to + * the invocation of this function. + * + * @see PoolExecutor::cancel() + * @see Executor::execute(const Task& task) + */ + virtual void execute(const Task& task); + + /** + * @see Cancelable::cancel() + */ + virtual void cancel(); + + /** + * @see Cancelable::isCanceled() + */ + virtual bool isCanceled(); + + /** + * Block the calling thread until all tasks submitted prior to this invocation + * complete. + * + * @exception Interrupted_Exception thrown if the calling thread is interrupted + * before the set of tasks being wait for can complete. + * + * @see Waitable::wait() + */ + virtual void wait(); + + /** + * Block the calling thread until all tasks submitted prior to this invocation + * complete or until the calling thread is interrupted. + * + * @param timeout maximum amount of time, in milliseconds, to wait for the + * currently submitted set of Tasks to complete. + * + * @exception Interrupted_Exception thrown if the calling thread is interrupted + * before the set of tasks being wait for can complete. + * + * @return + * - true if the set of tasks being wait for complete before + * timeout milliseconds elapse. + * - false otherwise. + * + * @see Waitable::wait(unsigned long timeout) + */ + virtual bool wait(unsigned long timeout); + + }; /* PoolExecutor */ + + +} // namespace ZThread + +#endif // __ZTPOOLEXECUTOR_H__ + + + + diff --git a/dep/include/zthread/Priority.h b/dep/include/zthread/Priority.h new file mode 100644 index 00000000000..907d1f153a8 --- /dev/null +++ b/dep/include/zthread/Priority.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTPRIORITY_H__ +#define __ZTPRIORITY_H__ + +namespace ZThread { + + //! Priorities + typedef enum { + + Low, + Medium = Low + 1, + High = Low + 2 + + } Priority; + +} + +#endif // __ZTPRIORITY_H__ diff --git a/dep/include/zthread/PriorityCondition.h b/dep/include/zthread/PriorityCondition.h new file mode 100644 index 00000000000..1fd86c41c11 --- /dev/null +++ b/dep/include/zthread/PriorityCondition.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTPRIORITYCONDITION_H__ +#define __ZTPRIORITYCONDITION_H__ + +#include "zthread/Lockable.h" +#include "zthread/NonCopyable.h" +#include "zthread/Waitable.h" + +namespace ZThread { + + class PriorityConditionImpl; + + /** + * @class PriorityCondition + * @author Eric Crahen + * @date <2003-07-16T17:35:28-0400> + * @version 2.2.1 + * + * A PriorityCondition is a Condition that is sensitive to thread priority. + * + * @see Condition + * + * Scheduling + * + * Threads blocked on a PriorityCondition are resumed in priority order, highest priority + * first + */ + class ZTHREAD_API PriorityCondition : public Waitable, private NonCopyable { + + PriorityConditionImpl* _impl; + + public: + + /** + * @see Condition::Condition(Lockable& l) + */ + PriorityCondition(Lockable& l); + + /** + * @see Condition::~Condition() + */ + ~PriorityCondition(); + + /** + * @see Condition::signal() + */ + void signal(); + + /** + * @see Condition::broadcast() + */ + void broadcast(); + + /** + * @see Condition::wait() + */ + virtual void wait(); + + /** + * @see Condition::wait(unsigned long timeout) + */ + virtual bool wait(unsigned long timeout); + + }; + +} // namespace ZThread + +#endif // __ZTPRIORITYCONDITION_H__ diff --git a/dep/include/zthread/PriorityInheritanceMutex.h b/dep/include/zthread/PriorityInheritanceMutex.h new file mode 100644 index 00000000000..1a5f5bfd300 --- /dev/null +++ b/dep/include/zthread/PriorityInheritanceMutex.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTPRIORITYINHERITANCEMUTEX_H__ +#define __ZTPRIORITYINHERITANCEMUTEX_H__ + +#include "zthread/Lockable.h" +#include "zthread/NonCopyable.h" + +namespace ZThread { + + class PriorityInheritanceMutexImpl; + + /** + * @class PriorityInheritanceMutex + * + * @author Eric Crahen + * @date <2003-07-16T19:37:36-0400> + * @version 2.2.1 + * + * A PriorityInheritanceMutex is similar to a PriorityMutex, it is a non-reentrant, + * priority sensitive MUTual EXclusion Lockable object. It differs only in its + * scheduling policy. + * + * @see PriorityMutex + * + * Scheduling + * + * Threads competing to acquire() a PriorityInheritanceMutex are granted access in + * order of priority. Threads with a higher priority will be given access first. + * + * When a higher priority thread tries to acquire() a PriorityInheritanceMutex and is + * about to be blocked by a lower priority thread that has already acquire()d it, the + * lower priority thread will temporarily have its effective priority raised to that + * of the higher priority thread until it release()s the mutex; at which point its + * previous priority will be restored. + */ + class ZTHREAD_API PriorityInheritanceMutex : public Lockable, private NonCopyable { + + PriorityInheritanceMutexImpl* _impl; + + public: + + /** + * @see Mutex::Mutex() + */ + PriorityInheritanceMutex(); + + /** + * @see Mutex::~Mutex() + */ + virtual ~PriorityInheritanceMutex(); + + /** + * @see Mutex::acquire() + */ + virtual void acquire(); + + /** + * @see Mutex::tryAcquire(unsigned long timeout) + */ + virtual bool tryAcquire(unsigned long timeout); + + /** + * @see Mutex::release() + */ + virtual void release(); + + }; + + +} // namespace ZThread + +#endif // __ZTPRIORITYINHERITANCEMUTEX_H__ diff --git a/dep/include/zthread/PriorityMutex.h b/dep/include/zthread/PriorityMutex.h new file mode 100644 index 00000000000..477c8d9fd4d --- /dev/null +++ b/dep/include/zthread/PriorityMutex.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTPRIORITYMUTEX_H__ +#define __ZTPRIORITYMUTEX_H__ + +#include "zthread/Lockable.h" +#include "zthread/NonCopyable.h" + +namespace ZThread { + + class PriorityMutexImpl; + + /** + * @class PriorityMutex + * @author Eric Crahen + * @date <2003-07-16T17:35:46-0400> + * @version 2.2.1 + * + * A PriorityMutex is similar to a Mutex, with exception that a PriorityMutex + * has a difference scheduling policy. It is a non-reentrant, priority sensitive + * MUTual EXclusion Lockable object. + * + * @see Mutex + * + * Scheduling + * + * Threads competing to acquire() a Mutex are granted access in order of priority. Threads + * with a higher priority will be given access first. + */ + class ZTHREAD_API PriorityMutex : public Lockable, private NonCopyable { + + PriorityMutexImpl* _impl; + + public: + + /** + * @see Mutex::Mutex() + */ + PriorityMutex(); + + /** + * @see Mutex::~Mutex() + */ + virtual ~PriorityMutex(); + + /** + * @see Mutex::acquire() + */ + virtual void acquire(); + + /** + * @see Mutex::tryAcquire(unsigned long timeout) + */ + virtual bool tryAcquire(unsigned long timeout); + + /** + * @see Mutex::release() + */ + virtual void release(); + + }; + + +} // namespace ZThread + +#endif // __ZTPRIORITYMUTEX_H__ diff --git a/dep/include/zthread/PrioritySemaphore.h b/dep/include/zthread/PrioritySemaphore.h new file mode 100644 index 00000000000..54ef2c48c52 --- /dev/null +++ b/dep/include/zthread/PrioritySemaphore.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + + +#ifndef __ZTPRIORITYSEMAPHORE_H__ +#define __ZTPRIORITYSEMAPHORE_H__ + +#include "zthread/Lockable.h" +#include "zthread/NonCopyable.h" + +namespace ZThread { + + class PrioritySemaphoreImpl; + + /** + * @class PrioritySemaphore + * @author Eric Crahen + * @date <2003-07-16T15:36:07-0400> + * @version 2.2.1 + * + * A PrioritySemaphore operates in the same way as a Semaphore. Its an owner-less + * Lockable object that is sensitive to priority. + * + * Scheduling + * + * Threads blocked on a PrioritySemaphore are resumed in priority order, highest + * priority first. + * + * Error Checking + * + * An attempt to increase a PrioritySemaphore beyond its maximum value will result in + * an InvalidOp_Exception. + * + * @see Semaphore + */ + class ZTHREAD_API PrioritySemaphore : public Lockable, private NonCopyable { + + PrioritySemaphoreImpl* _impl; + + public: + + /** + * @see Semaphore::Semaphore(int count, unsigned int maxCount) + */ + PrioritySemaphore(int count = 1, unsigned int maxCount = 1); + + /** + * @see Semaphore::~Semaphore() + */ + virtual ~PrioritySemaphore(); + + /** + * @see Semaphore::wait() + */ + void wait(); + + /** + * @see Semaphore::tryWait(unsigned long) + */ + bool tryWait(unsigned long); + + /** + * @see Semaphore::post() + */ + void post(); + + /** + * @see Semaphore::count() + */ + virtual int count(); + + /** + * @see Semaphore::tryAcquire(unsigned long timeout) + */ + virtual bool tryAcquire(unsigned long timeout); + + /** + * @see Semaphore::acquire() + */ + virtual void acquire(); + + /** + * @see Semaphore::release() + */ + virtual void release(); + + }; + + +} // namespace ZThread + +#endif // __ZTPRIORITYSEMAPHORE_H__ diff --git a/dep/include/zthread/Queue.h b/dep/include/zthread/Queue.h new file mode 100644 index 00000000000..98b83a10c63 --- /dev/null +++ b/dep/include/zthread/Queue.h @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTQUEUE_H__ +#define __ZTQUEUE_H__ + +#include "zthread/Cancelable.h" +#include "zthread/NonCopyable.h" + +namespace ZThread { + + /** + * @class Queue + * @author Eric Crahen + * @date <2003-07-16T11:32:42-0400> + * @version 2.3.0 + * + * A Queue defines an interface for a value-oriented collection objects (similar to + * STL collections). + */ + template + class Queue : public Cancelable, private NonCopyable { + public: + + //! Destroy a Queue + virtual ~Queue() { } + + /** + * Add an object to this Queue. + * + * @param item value to be added to the Queue + * + * @exception Cancellation_Exception thrown if this Queue has been canceled. + * + * @pre The Queue should not have been canceled prior to the invocation of this function. + * @post If no exception is thrown, a copy of item will have been added to the Queue. + */ + virtual void add(const T& item) = 0; + + /** + * Add an object to this Queue. + * + * @param item value to be added to the Queue + * @param timeout maximum amount of time (milliseconds) this method may block + * the calling thread. + * + * @return + * - true if a copy of item can be added before timeout + * milliseconds elapse. + * - false otherwise. + * + * @exception Cancellation_Exception thrown if this Queue has been canceled. + * + * @pre The Queue should not have been canceled prior to the invocation of this function. + * @post If this function returns true a copy of item will have been added to the Queue. + */ + virtual bool add(const T& item, unsigned long timeout) = 0; + + /** + * Retrieve and remove a value from this Queue. + * + * @return T next available value + * + * @exception Cancellation_Exception thrown if this Queue has been canceled. + * + * @pre The Queue should not have been canceled prior to the invocation of this function. + * @post The value returned will have been removed from the Queue. + */ + virtual T next() = 0; + + /** + * Retrieve and remove a value from this Queue. + * + * @param timeout maximum amount of time (milliseconds) this method may block + * the calling thread. + * + * @return T next available value + * + * @exception Cancellation_Exception thrown if this Queue has been canceled. + * @exception Timeout_Exception thrown if the timeout expires before a value + * can be retrieved. + * + * @pre The Queue should not have been canceled prior to the invocation of this function. + * @post The value returned will have been removed from the Queue. + */ + virtual T next(unsigned long timeout) = 0; + + /** + * Canceling a Queue disables it, disallowing further additions. Values already + * present in the Queue can still be retrieved and are still available through + * the next() methods. + * + * Canceling a Queue more than once has no effect. + * + * @post The next() methods will continue to return objects until + * the Queue has been emptied. + * @post Once emptied, the next() methods will throw a Cancellation_Exception. + * @post The add() methods will throw a Cancellation_Exceptions from this point on. + */ + virtual void cancel() = 0; + + /** + * Count the values present in this Queue. + * + * @return size_t number of elements available in the Queue. + */ + virtual size_t size() = 0; + + /** + * Count the values present in this Queue. + * + * @param timeout maximum amount of time (milliseconds) this method may block + * the calling thread. + * + * @return size_t number of elements available in the Queue. + * + * @exception Timeout_Exception thrown if timeout milliseconds + * expire before a value becomes available + */ + virtual size_t size(unsigned long timeout) = 0; + + /** + * Test whether any values are available in this Queue. + * + * @return + * - true if there are no values available. + * - false if there are values available. + */ + virtual bool empty() { + + try { + + return size() == 0; + + } catch(Cancellation_Exception&) { } + + return true; + + } + + /** + * Test whether any values are available in this Queue. + * + * @param timeout maximum amount of time (milliseconds) this method may block + * the calling thread. + * + * @return + * - true if there are no values available. + * - false if there are values available. + * + * @exception Timeout_Exception thrown if timeout milliseconds + * expire before a value becomes available + */ + virtual bool empty(unsigned long timeout) { + + try { + + return size(timeout) == 0; + + } catch(Cancellation_Exception&) { } + + return true; + + } + + }; /* Queue */ + +} // namespace ZThread + +#endif // __ZTQUEUE_H__ diff --git a/dep/include/zthread/ReadWriteLock.h b/dep/include/zthread/ReadWriteLock.h new file mode 100644 index 00000000000..e01643f1993 --- /dev/null +++ b/dep/include/zthread/ReadWriteLock.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTREADWRITELOCK_H__ +#define __ZTREADWRITELOCK_H__ + +#include "zthread/Lockable.h" +#include "zthread/NonCopyable.h" + +namespace ZThread { + + /** + * @class ReadWriteLock + * + * @author Eric Crahen + * @date <2003-07-16T10:17:31-0400> + * @version 2.2.7 + * + * A ReadWriteLock provides a set of coordinated Lockable objects that can be used to + * guard an object; One for read-only access, and another for read-write access. + * + * @see BiasedReadWriteLock + * @see FairReadWriteLock + */ + class ReadWriteLock : public NonCopyable { + public: + + /** + * Create a ReadWriteLock + * + * @exception Initialization_Exception thrown if resources could not be + * allocated for this object. + */ + ReadWriteLock() {} + + //! Destroy this ReadWriteLock + virtual ~ReadWriteLock() {} + + /** + * Get a reference to the read-only Lockable. + * + * @return Lockable& reference to a Lockable that provides read-only + * access. + */ + virtual Lockable& getReadLock() = 0; + + /** + * Get a reference to the read-write Lockable. + * + * @return Lockable& reference to a Lockable that provides read-write + * access. + */ + virtual Lockable& getWriteLock() = 0; + + + }; /* ReadWriteLock */ + + +}; // __ZTREADWRITELOCK_H__ + +#endif diff --git a/dep/include/zthread/RecursiveMutex.h b/dep/include/zthread/RecursiveMutex.h new file mode 100644 index 00000000000..7dda9c5119b --- /dev/null +++ b/dep/include/zthread/RecursiveMutex.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTRECURSIVEMUTEX_H__ +#define __ZTRECURSIVEMUTEX_H__ + +#include "zthread/Lockable.h" +#include "zthread/NonCopyable.h" + +namespace ZThread { + + class RecursiveMutexImpl; + + /** + * @class RecursiveMutex + * + * @author Eric Crahen + * @date <2003-07-16T17:51:33-0400> + * @version 2.2.1 + * + * A RecursiveMutex is a recursive, MUTual EXclusion Lockable object. It is + * recursive because it can be acquire()d and release()d more than once + * by the same thread, instead of causing a Deadlock_Exception. + * + * @see Mutex + * @see Guard + * + * Scheduling + * + * Threads competing to acquire() a Mutex are granted access in FIFO order. + * + * Error Checking + * + * A Mutex will throw an InvalidOp_Exception if an attempt to release() a Mutex is + * made from the context of a thread that does not currently own that Mutex. + */ + class ZTHREAD_API RecursiveMutex : public Lockable, private NonCopyable { + + RecursiveMutexImpl* _impl; + + public: + + //! Create a new RecursiveMutex. + RecursiveMutex(); + + //! Destroy this RecursiveMutex. + virtual ~RecursiveMutex(); + + /** + * Acquire a RecursiveMutex, possibly blocking until the the current owner of the + * releases it or until an exception is thrown. + * + * Only one thread may acquire the RecursiveMutex at any given time. + * The same thread may acquire a RecursiveMutex multiple times. + * + * @exception Interrupted_Exception thrown when the calling thread is interrupted. + * A thread may be interrupted at any time, prematurely ending any wait. + * + * @post the calling thread successfully acquire ed RecursiveMutex only if no exception + * was thrown. + * + * @see Lockable::acquire() + */ + virtual void acquire(); + + /** + * Acquire a RecursiveMutex, possibly blocking until the the current owner + * releases it, until an exception is thrown or until the given amount + * of time expires. + * + * Only one thread may acquire the RecursiveMutex at any given time. + * The same thread may acquire a RecursiveMutex multiple times. + * + * @param timeout maximum amount of time (milliseconds) this method could block + * @return + * - true if the lock was acquired + * - false if the lock was acquired + * + * @exception Interrupted_Exception thrown when the calling thread is interrupted. + * A thread may be interrupted at any time, prematurely ending any wait. + * + * @post the calling thread successfully acquired RecursiveMutex only if no exception + * was thrown. + * + * @see Lockable::tryAcquire(unsigned long timeout) + */ + virtual bool tryAcquire(unsigned long timeout); + + + /** + * Release exclusive access. No safety or state checks are performed. + * + * @pre This should not be called more times than the acquire() method was + * called. + * + * @see Lockable::release() + */ + virtual void release(); + + }; + +} // namespace ZThread + +#endif // __ZTRECURSIVEMUTEX_H__ diff --git a/dep/include/zthread/Runnable.h b/dep/include/zthread/Runnable.h new file mode 100644 index 00000000000..98628530a14 --- /dev/null +++ b/dep/include/zthread/Runnable.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + + +#ifndef __ZTRUNNABLE_H__ +#define __ZTRUNNABLE_H__ + +#include "zthread/Config.h" + +namespace ZThread { + + /** + * @class Runnable + * + * @author Eric Crahen + * @date <2003-07-16T17:45:35-0400> + * @version 2.2.11 + * + * Encapsulates a Runnable task. + */ + class Runnable { + public: + + /** + * Runnables should never throw in their destructors + */ + virtual ~Runnable() {} + + /** + * Task to be performed in another thread of execution + */ + virtual void run() = 0; + + }; + + +} + +#endif // __ZTRUNNABLE_H__ diff --git a/dep/include/zthread/Semaphore.h b/dep/include/zthread/Semaphore.h new file mode 100644 index 00000000000..2a9e4d02d03 --- /dev/null +++ b/dep/include/zthread/Semaphore.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTSEMAPHORE_H__ +#define __ZTSEMAPHORE_H__ + +#include "zthread/Lockable.h" +#include "zthread/NonCopyable.h" + +namespace ZThread { + + class FifoSemaphoreImpl; + + /** + * @class Semaphore + * @author Eric Crahen + * @date <2003-07-16T15:28:01-0400> + * @version 2.2.1 + * + * A Semaphore is an owner-less Lockable object. Its probably best described as + * a set of 'permits'. A Semaphore is initialized with an initial count and + * a maximum count, these would correspond to the number of 'permits' currently + * available and the number of' permits' in total. + * + * - Acquiring the Semaphore means taking a permit, but if there are none + * (the count is 0) the Semaphore will block the calling thread. + * + * - Releasing the Semaphore means returning a permit, unblocking a thread + * waiting for one. + * + * A Semaphore with an initial value of 1 and maximum value of 1 will act as + * a Mutex. + * + * Threads blocked on a Semaphore are resumed in FIFO order. + * + */ + class ZTHREAD_API Semaphore : public Lockable, private NonCopyable { + + FifoSemaphoreImpl* _impl; + + public: + + /** + * Create a new Semaphore. + * + * @param count initial count + * @param maxCount maximum count + */ + Semaphore(int count = 1, unsigned int maxCount = 1); + + //! Destroy the Semaphore + virtual ~Semaphore(); + + /** + * Provided to reflect the traditional Semaphore semantics + * + * @see acquire() + */ + void wait(); + + + /** + * Provided to reflect the traditional Semaphore semantics + * + * @see tryAcquire(unsigned long timeout) + */ + bool tryWait(unsigned long timeout); + + /** + * Provided to reflect the traditional Semaphore semantics + * + * @see release() + */ + void post(); + + + /** + * Get the current count of the semaphore. + * + * This value may change immediately after this function returns to the calling thread. + * + * @return int count + */ + virtual int count(); + + /** + * Decrement the count, blocking that calling thread if the count becomes 0 or + * less than 0. The calling thread will remain blocked until the count is + * raised above 0, an exception is thrown or the given amount of time expires. + * + * @param timeout maximum amount of time (milliseconds) this method could block + * + * @return + * - true if the Semaphore was acquired before timeout milliseconds elapse. + * - false otherwise. + * + * @exception Interrupted_Exception thrown when the calling thread is interrupted. + * A thread may be interrupted at any time, prematurely ending any wait. + * + * @see Lockable::tryAcquire(unsigned long timeout) + */ + virtual bool tryAcquire(unsigned long timeout); + + + /** + * Decrement the count, blocking that calling thread if the count becomes 0 or + * less than 0. The calling thread will remain blocked until the count is + * raised above 0 or if an exception is thrown. + * + * @exception Interrupted_Exception thrown when the calling thread is interrupted. + * A thread may be interrupted at any time, prematurely ending any wait. + * + * @see Lockable::acquire() + */ + virtual void acquire(); + + /** + * Increment the count, unblocking one thread if count is positive. + * + * @exception InvalidOp_Exception thrown if the maximum count would be exceeded. + * + * @see Lockable::release() + */ + virtual void release(); + + }; + + +} // namespace ZThread + +#endif // __ZTSEMAPHORE_H__ diff --git a/dep/include/zthread/Singleton.h b/dep/include/zthread/Singleton.h new file mode 100644 index 00000000000..b66c9d0898a --- /dev/null +++ b/dep/include/zthread/Singleton.h @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTSINGLETON_H__ +#define __ZTSINGLETON_H__ + +#include "zthread/Guard.h" +#include "zthread/FastMutex.h" +#include + +namespace ZThread { + +// +// This policy controls how an object is instantiated +// as well as how and when its destroyed. Phoenix-style +// singletons are not supported easily with type of policy, +// this is intentional since I do not believe that is in +// the true spirit of a singleton. +// +// InstantiationPolicContract { +// +// create(pointer_type&) +// +// } + +/** + * @class LocalStaticInstantiation + * @author Eric Crahen + * @date <2003-07-16T17:57:45-0400> + * @version 2.2.0 + * + * The LocalStaticInstantiation policy allows the creation + * and lifetime of an instance of a particular type + * to be managed using static local values. This will + * abide by the standard C++ rules for static objects + * lifetimes. + */ +class LocalStaticInstantiation { +protected: + + /** + * Create an instance of an object, using a local static. The + * object will be destroyed by the system. + * + * @param ptr reference to location to receive the address + * of the allocated object + */ + template + static void create(T*& ptr) { + + static T instance; + ptr = &instance; + + } + +}; + +//! Helper class +template +class StaticInstantiationHelper { + //! Friend class + friend class StaticInstantiation; + //! Holder + static T instance; + + }; + + template + T StaticInstantiationHelper::instance; + +/** + * @class StaticInstantiation + * @author Eric Crahen + * @date <2003-07-16T17:57:45-0400> + * @version 2.2.0 + * + * The StaticInstantiation policy allows the creation + * and lifetime of an instance of a particular type + * to be managed using static instantiation. This will + * abide by the standard C++ rules for static objects + * lifetimes. + */ +class StaticInstantiation { +protected: + + /** + * Create an instance of an object using by simply allocating it statically. + * + * @param ptr reference to location to receive the address + * of the allocated object + */ + template + static void create(T*& ptr) { + ptr = &StaticInstantiationHelper::instance; + } + +}; + +//! SingletonDestroyer +template +class Destroyer { + + T* doomed; + + public: + + Destroyer(T* q) : doomed(q) { + assert(doomed); + } + + ~Destroyer(); + +}; + +template +Destroyer::~Destroyer() { + + try { + + if(doomed) + delete doomed; + + } catch(...) { } + + doomed = 0; + +} + + +/** + * @class LazyInstantiation + * @author Eric Crahen + * @date <2003-07-16T17:57:45-0400> + * @version 2.2.0 + * + * The LazyInstantiation policy allows the creation + * and lifetime of an instance of a particular type + * to be managed using dynamic allocation and a singleton + * destroyer. This will abide by the standard C++ rules + * for static objects lifetimes. + */ +class LazyInstantiation { +protected: + + /** + * Create an instance of an object, using new, that will be + * destroyed when an associated Destroyer object (allocated + * statically) goes out of scope. + * + * @param ptr reference to location to receive the address + * of the allocated object + */ + template + static void create(T*& ptr) { + + ptr = new T; + static Destroyer destroyer(ptr); + + } + +}; + + +/** + * @class Singleton + * @author Eric Crahen + * @date <2003-07-16T17:57:45-0400> + * @version 2.2.0 + * + * Based on the work of John Vlissidles in his book 'Pattern Hatching' + * an article by Douglas Schmidtt on double-checked locking and policy + * templates described by Andrei Alexandrescu. + * + * This is a thread safe wrapper for creating Singleton classes. The + * synchronization method and instantiation methods can be changed + * easily by specifying different policy implementations as the + * templates parameters. + * + * @code + * + * // Most common Singleton + * Singletion + * + * // Singleton that uses static storage + * Singletion + * + * // Single-threaded singleton that uses static storage (Meyers-like) + * Singletion + * + * @endcode + */ +template +class Singleton : private InstantiationPolicy, private NonCopyable { +public: + + /** + * Provide access to the single instance through double-checked locking + * + * @return T* single instance + */ + static T* instance(); + +}; + +template +T* Singleton::instance() { + + // Uses local static storage to avoid static construction + // sequence issues. (regaring when the lock is created) + static T* ptr = 0; + static LockType lock; + + if(!ptr) { + + Guard g(lock); + if(!ptr) + InstantiationPolicy::create(ptr); + + } + + return const_cast(ptr); + + } + + +}; + +#endif + + diff --git a/dep/include/zthread/SynchronousExecutor.h b/dep/include/zthread/SynchronousExecutor.h new file mode 100644 index 00000000000..b6dbbef6af6 --- /dev/null +++ b/dep/include/zthread/SynchronousExecutor.h @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTSYNCHRONOUSEXECUTOR_H__ +#define __ZTSYNCHRONOUSEXECUTOR_H__ + +#include "zthread/Executor.h" +#include "zthread/Guard.h" +#include "zthread/Mutex.h" +#include "zthread/Thread.h" + +namespace ZThread { + + /** + * @class SynchronousExecutor + * + * @author Eric Crahen + * @date <2003-07-16T22:33:51-0400> + * @version 2.3.0 + * + * A SynchronousExecutor is an Executor which runs tasks using the thread that + * submits the task. It runs tasks serially, one at a time, in the order they + * were submitted to the executor. + * + * @see Executor. + */ + class SynchronousExecutor : public Executor { + + //! Serialize access + Mutex _lock; + + //! Cancellation flag + bool _canceled; + + public: + + //! Create a new SynchronousExecutor + SynchronousExecutor(); + + //! Destroy a SynchronousExecutor + virtual ~SynchronousExecutor(); + + /** + * This operation is not supported by this executor. + */ + virtual void interrupt(); + + /** + * Submit a task to this Executor, blocking the calling thread until the + * task is executed. + * + * @param task Task to be run by a thread managed by this executor + * + * @pre The Executor should have been canceled prior to this invocation. + * @post The submitted task will be run at some point in the future by this Executor. + * + * @exception Cancellation_Exception thrown if the Executor was canceled prior to + * the invocation of this function. + * + * @see Executor::execute(const Task& task) + */ + virtual void execute(const Task& task); + + /** + * @see Cancelable::cancel() + */ + virtual void cancel(); + + /** + * @see Cancelable::cancel() + */ + virtual bool isCanceled(); + + /** + * Block the calling thread until all tasks submitted prior to this invocation + * complete. + * + * @exception Interrupted_Exception thrown if the calling thread is interrupted + * before the set of tasks being wait for can complete. + * + * @see Executor::wait() + */ + virtual void wait(); + + /** + * Block the calling thread until all tasks submitted prior to this invocation + * complete or until the calling thread is interrupted. + * + * @param timeout - maximum amount of time, in milliseconds, to wait for the + * currently submitted set of Tasks to complete. + * + * @exception Interrupted_Exception thrown if the calling thread is interrupted + * before the set of tasks being wait for can complete. + * + * @return + * - true if the set of tasks being wait for complete before + * timeout milliseconds elapse. + * - false othewise. + */ + virtual bool wait(unsigned long timeout); + + + }; /* SynchronousExecutor */ + +} // namespace ZThread + +#endif // __ZTSYNCHRONOUSEXECUTOR_H__ diff --git a/dep/include/zthread/Task.h b/dep/include/zthread/Task.h new file mode 100644 index 00000000000..6503be66f33 --- /dev/null +++ b/dep/include/zthread/Task.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTTASK_H__ +#define __ZTTASK_H__ + +#include "zthread/CountedPtr.h" +#include "zthread/Runnable.h" + +namespace ZThread { + + class ThreadImpl; + + /** + * @class Task + * + * @author Eric Crahen + * @date <2003-07-20T05:22:38-0400> + * @version 2.3.0 + * + * A Task provides a CountedPtr wrapper for Runnable objects. + * This wrapper enables an implicit conversion from a + * Runnable* to a Task adding some syntactic sugar + * to the interface. + */ + class ZTHREAD_API Task : public CountedPtr { + public: + + +#if !defined(_MSC_VER) || (_MSC_VER > 1200) + + Task(Runnable* raw) + : CountedPtr(raw) { } + +#endif + + template + Task(U* raw) + : CountedPtr(raw) { } + + Task(const CountedPtr& ptr) + : CountedPtr(ptr) { } + + template + Task(const CountedPtr& ptr) + : CountedPtr(ptr) { } + + void operator()() { + (*this)->run(); + } + + }; /* Task */ + +} // namespace ZThread + +#endif // __ZTTASK_H__ + + + diff --git a/dep/include/zthread/Thread.h b/dep/include/zthread/Thread.h new file mode 100644 index 00000000000..e1700c737fa --- /dev/null +++ b/dep/include/zthread/Thread.h @@ -0,0 +1,381 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTTHREAD_H__ +#define __ZTTHREAD_H__ + +#include "zthread/Cancelable.h" +#include "zthread/Priority.h" +#include "zthread/NonCopyable.h" +#include "zthread/Task.h" +#include "zthread/Waitable.h" + +namespace ZThread { + + class ThreadImpl; + + /** + * @class Thread + * @author Eric Crahen + * @date <2003-07-27T11:17:59-0400> + * @version 2.3.0 + * + * + * @see Task + * @see Executor + * + *

Examples

+ * - Launching a task + * - Waiting for a task + * - Sharing a task + * + *

Launching a task

+ * + * A thread is started simply by constructing a thread object and giving + * it a task to perform. The thread will continue to run its task, even + * after the Thread object used to launch the thread has gone out of scope. + * + * @code + * #include "zthread/Thread.h" + * #include + * + * using namespace ZThread; + * + * class aRunnable : public Runnable { + * + * void run() { + * + * Thread::sleep(1000); + * std::cout << "Hello from another thread" << std::endl; + * + * } + * + * }; + * + * int main() { + * + * try { + * + * // Implictly constructs a Task + * Thread t(new aRunnable); + * + * } catch(Synchronization_Exception& e) { + * std::cerr << e.what() << std::endl; + * } + * + * std::cout << "Hello from the main thread" << std::endl; + * + * // Output: + * + * // Hello from the main thread + * // Hello from another thread + * + * return 0; + * + * } + * + * @endcode + * + *

Waiting for a task

+ * + * A user can exercise some simple synchronization by waiting for a thread + * to complete running its task. + * + * @code + * #include "zthread/Thread.h" + * #include + * + * using namespace ZThread; + * + * class aRunnable : public Runnable { + * public: + * + * void run() { + * + * Thread::sleep(1000); + * std::cout << "Hello from another thread" << std::endl; + * + * } + * + * }; + * + * int main() { + * + * try { + * + * // Implictly constructs a Task + * Thread t(new aRunnable); + * t.wait(); + * + * } catch(Synchronization_Exception& e) { + * std::cerr << e.what() << std::endl; + * } + * + * std::cout << "Hello from the main thread" << std::endl; + * + * // Output: + * + * // Hello from another thread + * // Hello from the main thread + * + * return 0; + * + * } + * + * @endcode + * + *

Sharing a task

+ * + * The same task can be shared by more than one thread. A Task is constructed + * from a Runnable, and that Task object is copied by value and handed off to + * each thread. + * + * @code + * #include "zthread/Thread.h" + * #include + * + * using namespace ZThread; + * + * class aRunnable : public Runnable { + * + * void run() { + * + * Thread::sleep(1000); + * std::cout << "Hello from another thread" << std::endl; + * + * } + * + * }; + * + * int main() { + * + * try { + * + * // Explictly constructs a Task + * Task task(new aRunnable); + * + * // Two threads created to run the same Task + * Thread t1(task); + * Thread t2(task); + * + * } catch(Synchronization_Exception& e) { + * std::cerr << e.what() << std::endl; + * } + * + * std::cout << "Hello from the main thread" << std::endl; + * + * // Output: + * + * // Hello from the main thread + * // Hello from another thread + * // Hello from another thread + * + * return 0; + * + * } + * + * @endcode + */ + class ZTHREAD_API Thread + : public Cancelable, public Waitable, public NonCopyable { + + //! Delegate + ThreadImpl* _impl; + + public: + + /** + * Create a Thread that represents the current thread. + * Using the static members of Thread should be preferred over using this constructor + */ + Thread(); + + /** + * Create a Thread that spawns a new thread to run the given task. + * + * @param task Task to be run by a thread managed by this executor + * @param autoCancel flag to requestion automatic cancellation + * + * @post if the autoCancel flag was true, this thread will + * automatically be canceled when main() goes out of scope. + */ + Thread(const Task&, bool autoCancel = false); + + //! Destroy the Thread + ~Thread(); + + //! Comparison operator + bool operator==(const Thread& t) const; + + //! Comparison operator + inline bool operator!=(const Thread& t) const { + return !(*this == t); + } + + /** + * Wait for the thread represented by this object to complete its task. + * The calling thread is blocked until the thread represented by this + * object exits. + * + * @exception Deadlock_Exception thrown if thread attempts to join itself + * @exception InvalidOp_Exception thrown if the thread cannot be joined + * @exception Interrupted_Exception thrown if the joining thread has been interrupt()ed + */ + void wait(); + + /** + * Wait for the thread represented by this object to complete its task. + * The calling thread is blocked until the thread represented by this + * object exits, or until the timeout expires. + * + * @param timeout maximum amount of time (milliseconds) this method + * could block the calling thread. + * + * @return + * - true if the thread task complete before timeout + * milliseconds elapse. + * - false othewise. + * + * @exception Deadlock_Exception thrown if thread attempts to join itself + * @exception InvalidOp_Exception thrown if the thread cannot be joined + * @exception Interrupted_Exception thrown if the joining thread has been interrupt()ed + */ + bool wait(unsigned long timeout); + + /** + * Change the priority of this Thread. This will change the actual + * priority of the thread when the OS supports it. + * + * If there is no real priority support, it's simulated. + * + * @param p - new Priority + */ + void setPriority(Priority p); + + /** + * Get the priority of this Thread. + * + * @return Priority + */ + Priority getPriority(); + + /** + * Interrupts this thread, setting the interrupted status of the thread. + * This status is cleared by one of three methods. + * + * If this thread is blocked when this method is called, the thread will + * abort that blocking operation with an Interrupted_Exception. + * + * - The first is by attempting an operation on a synchronization object that + * would normally block the calling thread; Instead of blocking the calling + * the calling thread, the function that would normally block will thrown an + * Interrupted_Exception and clear the interrupted status of the thread. + * + * - The second is by calling Thread::interrupted(). + * + * - The third is by calling Thread::canceled(). + * + * Threads already blocked by an operation on a synchronization object will abort + * that operation with an Interrupted_Exception, clearing the threads interrupted + * status as in the first case described above. + * + * Interrupting a thread that is no longer running will have no effect. + * + * @return + * - true if the thread was interrupted while not blocked by a wait + * on a synchronization object. + * - false othewise. + */ + bool interrupt(); + + /** + * Tests whether the current Thread has been interrupt()ed, clearing + * its interruption status. + * + * @return + * - true if the Thread was interrupted. + * - false otherwise. + * + * @post The interrupted status of the current thread will be cleared, + * allowing it to perform a blocking operation on a synchronization + * object without throwing an exception. + */ + static bool interrupted(); + + /** + * Tests whether the current Thread has been canceled, and clears the + * interrupted status. + * + * @return bool true only if the Thread::cancel() has been invoked. + */ + static bool canceled(); + + /** + * Tests whether this thread has been canceled. If called from the context + * of this thread, the interrupted status is cleared. + * + * @return + * - true if the Thread was canceled. + * - false otherwise. + * + * @see Cancelable::isCanceled() + */ + virtual bool isCanceled(); + + /** + * Interrupt and cancel this thread in a single operation. The thread will + * return true whenever its cancelation status is tested in the future. + * + * @exception InvalidOp_Exception thrown if a thread attempts to cancel itself + * + * @see Thread::interrupt() + * @see Cancelable::cancel() + */ + virtual void cancel(); + + /** + * Put the currently executing thread to sleep for a given amount of + * time. + * + * @param timeout maximum amount of time (milliseconds) this method could block + * + * @exception Interrupted_Exception thrown if the threads sleep is interrupted + * before timeout milliseconds expire. + */ + static void sleep(unsigned long timeout); + + /** + * Cause the currently executing thread to yield, allowing the scheduler + * to assign some execution time to another thread. + */ + static void yield(); + + + }; /* Thread */ + + +} // namespace ZThread + +#endif // __ZTTHREAD_H__ + + + diff --git a/dep/include/zthread/ThreadLocal.h b/dep/include/zthread/ThreadLocal.h new file mode 100644 index 00000000000..bb83a0fe3ef --- /dev/null +++ b/dep/include/zthread/ThreadLocal.h @@ -0,0 +1,382 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTTHREADLOCAL_H__ +#define __ZTTHREADLOCAL_H__ + +#include "zthread/ThreadLocalImpl.h" + +namespace ZThread { + + /** + * @class ThreadLocal + * + * @author Eric Crahen + * @date <2003-07-27T11:18:21-0400> + * @version 2.3.0 + * + * Provides access to store and retrieve value types to and from a thread local + * storage context. A thread local storage context consists of the calling thread + * a specific ThreadLocal object. Since this context is specific to each thread + * whenever a value is stored in a ThreadLocal that is accessible from multiple + * threads, it can only be retrieved by the thread that stored it. + * + * The first time a thread accesses the value associated with a thread local storage + * context, a value is created. That value is either an initial value (determined by + * InitialValueT) or an inherited value (determined by ChildValueT). + * + * - If a threads parent had no value associated with a ThreadLocal when the thread was created, + * then the InitialValueT functor is used to create an initial value. + * + * - If a threads parent did have a value associated with a ThreadLocal when the thread was + * created, then the childValueT functor is used to create an initial value. + * + * Not all ThreadLocal's support the inheritance of values from parent threads. The default + * behavoir is to create values through the InitialValueT functor for all thread when + * they first access a thread local storage context. + * + * - Inheritance is enabled automatically when a user supplies a ChildValueT functor other + * than the default one supplied. + * + * - Inheritance can be controlled explicitly by the user through a third functor, + * InheritableValueT. + * + *

Examples

+ * + * - Default initial value + * - User-specified initial value + * - User-specified inherited value + * + *

Default initial value

+ * A ThreadLocal that does not inherit, and uses the default value + * for an int as its initial value. + * + * @code + * + * #include "zthread/ThreadLocal.h" + * #include "zthread/Thread.h" + * #include + * + * using namespace ZThread; + * + * class aRunnable : public Runnable { + * ThreadLocal localValue; + * public: + * void run() { + * std::cout << localValue.get() << std::endl; + * } + * }; + * + * int main() { + * + * // Create a shared task to display ThreadLocal values + * Task task(new aRunnable); + * + * Thread t0(task); t0.wait(); + * Thread t1(task); t1.wait(); + * Thread t2(task); t2.wait(); + * + * // Output: + * + * // 0 + * // 0 + * // 0 + * + * return 0; + * + * } + * + * @endcode + * + *

User-specified initial value

+ * A ThreadLocal that does not inherit, and uses a custom initial value. + * + * @code + * + * #include "zthread/ThreadLocal.h" + * #include "zthread/Thread.h" + * #include + * + * using namespace ZThread; + * + * struct anInitialValueFn { + * int operator()() { + * static int next = 100; + * int val = next; next += 100; + * return val; + * } + * }; + * + * class aRunnable : public Runnable { + * ThreadLocal localValue; + * public: + * void run() { + * std::cout << localValue.get() << std::endl; + * } + * }; + * + * int main() { + * + * // Create a shared task to display ThreadLocal values + * Task task(new aRunnable); + * + * Thread t0(task); t0.wait(); + * Thread t1(task); t1.wait(); + * Thread t2(task); t2.wait(); + * + * // Output: + * + * // 100 + * // 200 + * // 300 + * + * return 0; + * + * } + * + * @endcode + * + *

User-specified inherited value

+ * A ThreadLocal that does inherit and modify child values. + * (The default initial value functor is used) + * + * @code + * + * #include "zthread/ThreadLocal.h" + * #include "zthread/Thread.h" + * #include + * + * using namespace ZThread; + * + * struct anInheritedValueFn { + * int operator()(int val) { + * return val + 100; + * } + * }; + * + * // This Runnable associates no ThreadLocal value in the main thread; so + * // none of the child threads have anything to inherit. + * class aRunnable : public Runnable { + * ThreadLocal, anInheritedValueFn> localValue; + * public: + * void run() { + * std::cout << localValue.get() << std::endl; + * } + * }; + * + * // This Runnable associates a ThreadLocal value in the main thread which + * // is inherited when the child threads are created. + * class anotherRunnable : public Runnable { + * ThreadLocal, anInheritedValueFn> localValue; + * public: + * anotherRunnable() { + * localValue.set(100); + * } + * void run() { + * std::cout << localValue.get() << std::endl; + * } + * }; + * + * int main() { + * + * // Create a shared task to display ThreadLocal values + * Task task(new aRunnable); + * + * Thread t0(task); t0.wait(); + * Thread t1(task); t1.wait(); + * Thread t2(task); t2.wait(); + * + * // Output: + * + * // 0 + * // 0 + * // 0 + * + * task = Task(new anotherRunnable); + * + * Thread t10(task); t10.wait(); + * Thread t11(task); t11.wait(); + * Thread t12(task); t12.wait(); + * + * // Output: + * + * // 200 + * // 200 + * // 200 + * + * return 0; + * + * } + * + * @endcode + * + *

Parameters

+ * + * InitialValueT + * + * This template parameter should indicate the functor used to set + * the initial value. It should support the following operator: + * + * + * // required operator + * T operator() + * + * // supported expression + * InitialValueT()() + * + * + * + * ChildValueT + * + * This template parameter should indicate the functor used to set + * the value that will be inherited by thread whose parent have associated + * a value with the ThreadLocal's context at the time they are created. + * It should support the following operator: + * + * + * // required operator + * T operator(const T& parentValue) + * + * // supported expression + * ChildValueT()(parentValue) + * + * + * + * InheritableValueT + * + * This template parameter should indicate the functor, used to determine + * wheather or not this ThreadLocal will allow values from a parent threads + * context to be inherited by child threads when they are created. + * It should support the following operator: + * + * + * // required operator + * bool operator(const T& childValueFunctor) + * + * // supported expression + * InheritableValueT()( ChildValueT() ) + * + * + */ + template < + typename T, + typename InitialValueT = ThreadLocalImpl::InitialValueFn, + typename ChildValueT = ThreadLocalImpl::UniqueChildValueFn, + typename InheritableValueT = ThreadLocalImpl::InheritableValueFn + > + class ThreadLocal : private ThreadLocalImpl { + + typedef ThreadLocalImpl::ValuePtr ValuePtr; + + class Value : public ThreadLocalImpl::Value { + + T value; + + public: + + Value() : value( InitialValueT()() ) { } + + Value(const Value& v) : value( ChildValueT()(v.value) ) { } + + virtual ~Value() { } + + operator T() { return value; } + + const Value& operator=(const T& v) { value = v; } + + virtual bool isInheritable() const { + return InheritableValueT()( ChildValueT() ); + } + + virtual ValuePtr clone() const { + return ValuePtr( new Value(*this) ); + } + + }; + + static ValuePtr createValue() { + return ValuePtr( new Value ); + } + + public: + + /** + * Get the value associated with the context (this ThreadLocal and + * the calling thread) of the invoker. If no value is currently + * associated, then an intial value is created and associated; that value + * is returned. + * + * @return T associated value. + * + * @post If no value has been associated with the invoking context + * then an inital value will be associated. That value is + * created by the InitialValueT functor. + */ + T get() const { + return (T)reinterpret_cast( *value(&createValue) ); + } + + /** + * Replace the value associated with the context (this ThreadLocal and + * the calling thread) of the invoker. If no value is currently + * associated, then an intial value is first created and subsequently + * replaced by the new value. + * + * @param v value of type T to associate. + * + * @post If no value has been associated with the invoking context + * then an inital value will first be associated. That value is + * created by the InitialValueT functor and then + * replaced with the new value. + */ + void set(T v) const { + reinterpret_cast( *value(&createValue) ) = v; + } + + /** + * Remove any value current associated with this ThreadLocal. + * + * @post Upon thier next invocation the get() and set() functions will behave as + * if no value has been associated with this ThreadLocal and an + * initial value will be generated. + */ + void clear() const { + ThreadLocalImpl::clear(); + } + + /** + * Remove any value current associated with any ThreadLocal. + * + * @post Upon thier next invocation the get() and set() functions will behave as + * if no value has been associated with any ThreadLocal and new + * initial values will be generated. + */ + static void clearAll() { + ThreadLocalImpl::clearAll(); + } + + }; + + +} // namespace ZThread + +#endif // __ZTTHREADLOCAL_H__ diff --git a/dep/include/zthread/ThreadLocalImpl.h b/dep/include/zthread/ThreadLocalImpl.h new file mode 100644 index 00000000000..3b4046f8f58 --- /dev/null +++ b/dep/include/zthread/ThreadLocalImpl.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTTHREADLOCALIMPL_H__ +#define __ZTTHREADLOCALIMPL_H__ + +#include "zthread/CountedPtr.h" + +namespace ZThread { + + /** + * @class ThreadLocalImpl + * @author Eric Crahen + * @date <2003-07-27T10:23:19-0400> + * @version 2.3.0 + * + * @see ThreadLocal + */ + class ZTHREAD_API ThreadLocalImpl : private NonCopyable { + public: + + class Value; + typedef CountedPtr ValuePtr; + + //! + class Value { + Value& operator=(const Value&); + public: + virtual ~Value() {} + virtual bool isInheritable() const = 0; + virtual ValuePtr clone() const = 0; + }; + + //! Create a ThreadLocalImpl + ThreadLocalImpl(); + + //! Destroy a ThreadLocalImpl + ~ThreadLocalImpl(); + + /** + * @class InitialValueFn + */ + template + struct InitialValueFn { + T operator()() { return T(); } + }; + + /** + * @class ChildValueFn + */ + struct ChildValueFn { + template + T operator()(const T& value) { return T(value); } + }; + + /** + * @class UniqueChildValueFn + */ + struct UniqueChildValueFn : public ChildValueFn { }; + + /** + * @class InheritableValueFn + */ + struct InheritableValueFn { + + template + bool operator()(const T&) { return true; } + + bool operator()(const UniqueChildValueFn&) { return false; } + + }; + + protected: + + //! Get the Value for the current thread + ValuePtr value( ValuePtr (*pfn)() ) const; + + //! Clear any value set for this thread + void clear() const; + + //! Clear any value set with any ThreadLocal for this thread + static void clearAll(); + + }; + +} // __ZTTHREADLOCALIMPL_H__ + +#endif + diff --git a/dep/include/zthread/ThreadedExecutor.h b/dep/include/zthread/ThreadedExecutor.h new file mode 100644 index 00000000000..9bc29b3c497 --- /dev/null +++ b/dep/include/zthread/ThreadedExecutor.h @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTTHREADEDEXECUTOR_H__ +#define __ZTTHREADEDEXECUTOR_H__ + +#include "zthread/Executor.h" +#include "zthread/CountedPtr.h" + +namespace ZThread { + + namespace { class ExecutorImpl; } + + /** + * @class ThreadedExecutor + * + * @author Eric Crahen + * @date <2003-07-16T22:39:13-0400> + * @version 2.3.0 + * + * A ThreadedExecutor spawns a new thread to execute each task submitted. + * A ThreadedExecutor supports the following optional operations, + * + * - cancel()ing a ThreadedExecutor will cause it to stop accepting + * new tasks. + * + * - interrupt()ing a ThreadedExecutor will cause the any thread running + * a task which was submitted prior to the invocation of this function to + * be interrupted during the execution of that task. + * + * - wait()ing on a ThreadedExecutor will block the calling thread + * until all tasks that were submitted prior to the invocation of this function + * have completed. + * + * @see Executor. + */ + class ThreadedExecutor : public Executor { + + CountedPtr< ExecutorImpl > _impl; + + public: + + //! Create a new ThreadedExecutor + ThreadedExecutor(); + + //! Destroy a ThreadedExecutor + virtual ~ThreadedExecutor(); + + /** + * Interrupting a ThreadedExecutor will cause an interrupt() to be sent + * to every Task that has been submitted at the time this function is + * called. Tasks that are submitted after this function is called will + * not be interrupt()ed; unless this function is invoked again(). + */ + virtual void interrupt(); + + /** + * Submit a task to this Executor. This will not block the current thread + * for very long. A new thread will be created and the task will be run() + * within the context of that new thread. + * + * @exception Cancellation_Exception thrown if this Executor has been canceled. + * The Task being submitted will not be executed by this Executor. + * + * @see Executor::execute(const Task&) + */ + virtual void execute(const Task&); + + /** + * @see Cancelable::cancel() + */ + virtual void cancel(); + + /** + * @see Cancelable::isCanceled() + */ + virtual bool isCanceled(); + + /** + * Waiting on a ThreadedExecutor will block the current thread until all + * tasks submitted to the Executor up until the time this function was called + * have completed. + * + * Tasks submitted after this function is called will not delay a thread that + * was already waiting on the Executor any longer. In order to wait for + * those tasks to complete as well, another wait() would be needed. + * + * @exception Interrupted_Exception thrown if the calling thread is interrupted + * before the set of tasks for which it was waiting complete. + * + * @see Waitable::wait() + */ + virtual void wait(); + + /** + * Operates the same as ThreadedExecutor::wait() but with a timeout. + * + * @param timeout maximum amount of time, in milliseconds, to wait for the + * currently submitted set of Tasks to complete. + * + * @exception Interrupted_Exception thrown if the calling thread is interrupt()ed + * while waiting for the current set of Tasks to complete. + * + * @return + * - true if the set of tasks running at the time this function is invoked complete + * before timeout milliseconds elapse. + * - false othewise. + * + * @see Waitable::wait(unsigned long timeout) + */ + virtual bool wait(unsigned long timeout); + + }; /* ThreadedExecutor */ + +} // namespace ZThread + +#endif // __ZTTHREADEDEXECUTOR_H__ diff --git a/dep/include/zthread/Time.h b/dep/include/zthread/Time.h new file mode 100644 index 00000000000..374c4fd6bf0 --- /dev/null +++ b/dep/include/zthread/Time.h @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTTIME_H__ +#define __ZTTIME_H__ + +#include "zthread/Config.h" + +namespace ZThread { + +/** + * @class Time + * @author Eric Crahen + * @date <2003-07-16T17:52:46-0400> + * @version 2.2.11 + * + * The Time class provides access to time values relative to when the program + * was started. In other words, this class might be thought of as a timer that + * starts at 0 and counts upwards. This class offers millisecond resolution. + */ +class ZTHREAD_API Time { + + unsigned long _seconds; + unsigned long _milliseconds; + + //! Create a new Time object + Time(unsigned long secs, unsigned long millis) + : _seconds(secs), _milliseconds(millis) { } + + /** + * Set the number of milliseconds in this Time object. + * + * @param millis - new milliseconds value + * @return unsigned long old milliseconds value + */ + unsigned long milliseconds(unsigned long millis) { + + unsigned long n = _milliseconds; + _milliseconds = millis; + + return n; + + } + + /** + * Set the number of seconds in this Time object. + * + * @param secs - new seconds value + * @return unsigned long old seconds value + */ + unsigned long seconds(unsigned long secs) { + + unsigned long n = _seconds; + _seconds = secs; + + return n; + + } + + public: + + + /** + * Create a Time object with the current time relative to the + * beginning of the program. + */ + Time(); + + /** + * Create a Time object by copying another. + * + * @param t - Time object to copy. + */ + Time(const Time& t) + : _seconds(t._seconds), _milliseconds(t._milliseconds) { } + + + /** + * Get the number of milliseconds in this Time object. + * + * @return unsigned long milliseconds value + */ + unsigned long milliseconds() const { + return _milliseconds; + } + + /** + * Get the number of seconds in this Time object. + * + * @return unsigned long seconds value + */ + unsigned long seconds() const { + return _seconds; + } + + /** + * Add some number of milliseconds to this Time object. + * + * @param millis - number of milliseconds to add to this Time object + * @return const Time& this object + */ + const Time& operator+=(unsigned long millis) { + + _milliseconds += millis; + _seconds += (_milliseconds / 1000); + _milliseconds %= 1000; + + return *this; + + } + + /** + * Subtract some number of milliseconds to this Time object. + * + * @param millis - number of milliseconds to subtract from this Time object + * @return const Time& this object + */ +const Time& operator-=(unsigned long millis) { + + if(_milliseconds > millis) + _milliseconds -= millis; + + else { + + while(_seconds > 0 && _milliseconds < millis) { + + _milliseconds += 1000; + _seconds -= 1; + + } + + _milliseconds = (_milliseconds < millis) ? 0 : (_milliseconds - millis); + + } + + return *this; + +} + + + /** + * Add the value of another Time object to this one. + * + * @param t - Time object whose value should be added to this object + * @return const Time& this object + */ + const Time& operator+=(const Time& t) { + + _milliseconds += t.milliseconds(); + _seconds += (_milliseconds / 1000) + t.seconds(); + _milliseconds %= 1000; + + return *this; + + } + + /** + * Subtract the value of another Time object from this one. + * This function has a floor of 0. + * + * @param t - Time object whose value should be subtracted from this object + * @return const Time& this object + */ +const Time& operator-=(const Time& t) { + + unsigned long millis = t.milliseconds(); + unsigned long secs = t.seconds(); + + if(_seconds >= secs) { + + if(_milliseconds > millis) { + _milliseconds -= millis; + _seconds -= secs; + + } else { + + while(_seconds > 0 && _milliseconds < millis) { + + _milliseconds += 1000; + _seconds -= 1; + + } + + _milliseconds = (_milliseconds < millis) ? 0 : (_milliseconds - millis); + _seconds = (_seconds < secs) ? 0 : (_seconds - secs); + + } + + } else { + + _milliseconds = 0; + _seconds = 0; + + } + + return *this; + +} + +}; + + + +} // namespace ZThread + +#endif // __ZTTIME_H__ diff --git a/dep/include/zthread/Waitable.h b/dep/include/zthread/Waitable.h new file mode 100644 index 00000000000..3d925f2a691 --- /dev/null +++ b/dep/include/zthread/Waitable.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTWAITABLE_H__ +#define __ZTWAITABLE_H__ + +#include "zthread/Exceptions.h" + +namespace ZThread { + + /** + * @class Waitable + * + * @author Eric Crahen + * @date <2003-07-16T22:16:41-0400> + * @version 2.3.0 + * + * The Waitable interface defines a common method of adding generic wait semantics + * to a class. + * + * Waiting + * + * An object implementing the Waitable interface externalizes a mechanism for testing + * some internal condition. Another object may wait()s for a Waitable object; + * in doing so, it wait()s for that condition to become true by blocking the caller + * while the condition is false. + * + * For example, a Condition is Waitable object that extends wait semantics + * so that wait()ing means a thread is blocked until some external stimulus + * specifically performs an operation on the Condition to make its internal condition true. + * (serialization aside) + * + * A Barrier extends wait semantics so that wait()ing mean waiting for other + * waiters, and may include automatically resetting the condition once a wait is complete. + * + * @see Condition + * @see Barrier + * @see Executor + */ + class Waitable { + public: + + //! Destroy a Waitable object. + virtual ~Waitable() {} + + /** + * Waiting on an object will generally cause the calling thread to be blocked + * for some indefinite period of time. The thread executing will not proceed + * any further until the Waitable object releases it unless or an exception + * is thrown. + */ + virtual void wait() = 0; + + /** + * Waiting on an object will generally cause the calling thread to be blocked + * for some indefinite period of time. The thread executing will not proceed + * any further until the Waitable object releases it unless or an exception + * is thrown. + * + * @param timeout maximum amount of time, in milliseconds, to spend waiting. + * + * @return + * - true if the set of tasks being wait for complete before + * timeout milliseconds elapse. + * - false othewise. + */ + virtual bool wait(unsigned long timeout) = 0; + + + }; /* Waitable */ + + +} // namespace ZThread + +#endif // __ZTWAITABLE_H__ diff --git a/dep/include/zthread/ZThread.h b/dep/include/zthread/ZThread.h new file mode 100644 index 00000000000..1df5bb67a7c --- /dev/null +++ b/dep/include/zthread/ZThread.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTLIBRARY_H__ +#define __ZTLIBRARY_H__ + + +#include "zthread/Barrier.h" +#include "zthread/BiasedReadWriteLock.h" +#include "zthread/BlockingQueue.h" +#include "zthread/BoundedQueue.h" +#include "zthread/Cancelable.h" +#include "zthread/ClassLockable.h" +#include "zthread/ConcurrentExecutor.h" +#include "zthread/Condition.h" +#include "zthread/Config.h" +#include "zthread/CountedPtr.h" +#include "zthread/CountingSemaphore.h" +#include "zthread/Exceptions.h" +#include "zthread/Executor.h" +#include "zthread/FairReadWriteLock.h" +#include "zthread/FastMutex.h" +#include "zthread/FastRecursiveMutex.h" +#include "zthread/Guard.h" +#include "zthread/Lockable.h" +#include "zthread/LockedQueue.h" +#include "zthread/MonitoredQueue.h" +#include "zthread/Mutex.h" +#include "zthread/NonCopyable.h" +#include "zthread/PoolExecutor.h" +#include "zthread/Priority.h" +#include "zthread/PriorityCondition.h" +#include "zthread/PriorityInheritanceMutex.h" +#include "zthread/PriorityMutex.h" +#include "zthread/PrioritySemaphore.h" +#include "zthread/Queue.h" +#include "zthread/ReadWriteLock.h" +#include "zthread/RecursiveMutex.h" +#include "zthread/Runnable.h" +#include "zthread/Semaphore.h" +#include "zthread/Singleton.h" +#include "zthread/SynchronousExecutor.h" +#include "zthread/Thread.h" +#include "zthread/ThreadLocal.h" +#include "zthread/Time.h" +#include "zthread/Waitable.h" + +#endif diff --git a/dep/lib/Makefile.am b/dep/lib/Makefile.am new file mode 100644 index 00000000000..921a48c2083 --- /dev/null +++ b/dep/lib/Makefile.am @@ -0,0 +1,50 @@ +# Copyright (C) 2005-2008 MaNGOS +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## Process this file with automake to produce Makefile.in + +## Sub-directories to parse + +## Additional files to include when running 'make dist' +# Debug libraries for Win32 builds. +EXTRA_DIST = \ + win32_debug/libeay32.dll \ + win32_debug/libeay32.lib \ + win32_debug/libmySQL.dll \ + win32_debug/libmySQL.lib \ + win32_debug/sqlite.lib + +# Release libraries for Win32 builds. +EXTRA_DIST += \ + win32_release/libeay32.dll \ + win32_release/libeay32.lib \ + win32_release/libmySQL.dll \ + win32_release/libmySQL.lib \ + win32_release/sqlite.lib + +# Debug libraries for Win64 builds. +EXTRA_DIST += \ + x64_Debug/libeay32.dll \ + x64_Debug/libeay32.lib \ + x64_Debug/libmySQL.dll \ + x64_Debug/libmySQL.lib + +# Release libraries for Win64 builds. +EXTRA_DIST += \ + x64_release/libeay32.dll \ + x64_release/libeay32.lib \ + x64_release/libmySQL.dll \ + x64_release/libmySQL.lib diff --git a/dep/lib/win32_debug/dbghelp.dll b/dep/lib/win32_debug/dbghelp.dll new file mode 100644 index 00000000000..597188d77e9 Binary files /dev/null and b/dep/lib/win32_debug/dbghelp.dll differ diff --git a/dep/lib/win32_debug/libeay32.dll b/dep/lib/win32_debug/libeay32.dll new file mode 100644 index 00000000000..f62b057bb23 Binary files /dev/null and b/dep/lib/win32_debug/libeay32.dll differ diff --git a/dep/lib/win32_debug/libeay32.lib b/dep/lib/win32_debug/libeay32.lib new file mode 100644 index 00000000000..7f89f68e413 Binary files /dev/null and b/dep/lib/win32_debug/libeay32.lib differ diff --git a/dep/lib/win32_debug/libmySQL.dll b/dep/lib/win32_debug/libmySQL.dll new file mode 100644 index 00000000000..8bc44d3a428 Binary files /dev/null and b/dep/lib/win32_debug/libmySQL.dll differ diff --git a/dep/lib/win32_debug/libmySQL.lib b/dep/lib/win32_debug/libmySQL.lib new file mode 100644 index 00000000000..bdf57ad35a0 Binary files /dev/null and b/dep/lib/win32_debug/libmySQL.lib differ diff --git a/dep/lib/win32_debug/sqlite.lib b/dep/lib/win32_debug/sqlite.lib new file mode 100644 index 00000000000..aa335a68d2e Binary files /dev/null and b/dep/lib/win32_debug/sqlite.lib differ diff --git a/dep/lib/win32_release/dbghelp.dll b/dep/lib/win32_release/dbghelp.dll new file mode 100644 index 00000000000..597188d77e9 Binary files /dev/null and b/dep/lib/win32_release/dbghelp.dll differ diff --git a/dep/lib/win32_release/libeay32.dll b/dep/lib/win32_release/libeay32.dll new file mode 100644 index 00000000000..e078a35487a Binary files /dev/null and b/dep/lib/win32_release/libeay32.dll differ diff --git a/dep/lib/win32_release/libeay32.lib b/dep/lib/win32_release/libeay32.lib new file mode 100644 index 00000000000..b5ad42ae274 Binary files /dev/null and b/dep/lib/win32_release/libeay32.lib differ diff --git a/dep/lib/win32_release/libmySQL.dll b/dep/lib/win32_release/libmySQL.dll new file mode 100644 index 00000000000..594aaf85278 Binary files /dev/null and b/dep/lib/win32_release/libmySQL.dll differ diff --git a/dep/lib/win32_release/libmySQL.lib b/dep/lib/win32_release/libmySQL.lib new file mode 100644 index 00000000000..dc1e360b2d5 Binary files /dev/null and b/dep/lib/win32_release/libmySQL.lib differ diff --git a/dep/lib/win32_release/sqlite.lib b/dep/lib/win32_release/sqlite.lib new file mode 100644 index 00000000000..aa335a68d2e Binary files /dev/null and b/dep/lib/win32_release/sqlite.lib differ diff --git a/dep/lib/x64_Debug/libeay32.dll b/dep/lib/x64_Debug/libeay32.dll new file mode 100644 index 00000000000..75058bd0cc0 Binary files /dev/null and b/dep/lib/x64_Debug/libeay32.dll differ diff --git a/dep/lib/x64_Debug/libeay32.lib b/dep/lib/x64_Debug/libeay32.lib new file mode 100644 index 00000000000..679578e78e8 Binary files /dev/null and b/dep/lib/x64_Debug/libeay32.lib differ diff --git a/dep/lib/x64_Debug/libmySQL.dll b/dep/lib/x64_Debug/libmySQL.dll new file mode 100644 index 00000000000..0abe0003142 Binary files /dev/null and b/dep/lib/x64_Debug/libmySQL.dll differ diff --git a/dep/lib/x64_Debug/libmysql.lib b/dep/lib/x64_Debug/libmysql.lib new file mode 100644 index 00000000000..60a050d8a0e Binary files /dev/null and b/dep/lib/x64_Debug/libmysql.lib differ diff --git a/dep/lib/x64_release/libeay32.dll b/dep/lib/x64_release/libeay32.dll new file mode 100644 index 00000000000..75058bd0cc0 Binary files /dev/null and b/dep/lib/x64_release/libeay32.dll differ diff --git a/dep/lib/x64_release/libeay32.lib b/dep/lib/x64_release/libeay32.lib new file mode 100644 index 00000000000..679578e78e8 Binary files /dev/null and b/dep/lib/x64_release/libeay32.lib differ diff --git a/dep/lib/x64_release/libmySQL.dll b/dep/lib/x64_release/libmySQL.dll new file mode 100644 index 00000000000..34ff51ad5d8 Binary files /dev/null and b/dep/lib/x64_release/libmySQL.dll differ diff --git a/dep/lib/x64_release/libmysql.lib b/dep/lib/x64_release/libmysql.lib new file mode 100644 index 00000000000..c13543e0c61 Binary files /dev/null and b/dep/lib/x64_release/libmysql.lib differ diff --git a/dep/src/Makefile.am b/dep/src/Makefile.am new file mode 100644 index 00000000000..e9707b52dac --- /dev/null +++ b/dep/src/Makefile.am @@ -0,0 +1,23 @@ +# Copyright (C) 2005-2008 MaNGOS +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## Process this file with automake to produce Makefile.in + +## Sub-directories to parse +SUBDIRS = g3dlite sockets zlib zthread + +## Additional files to include when running 'make dist' +# Nothing yet. diff --git a/dep/src/g3dlite/AABox.cpp b/dep/src/g3dlite/AABox.cpp new file mode 100644 index 00000000000..d147a1080e8 --- /dev/null +++ b/dep/src/g3dlite/AABox.cpp @@ -0,0 +1,299 @@ +/** + @file AABox.cpp + + @maintainer Morgan McGuire, matrix@graphics3d.com + + @created 2004-01-10 + @edited 2006-01-11 +*/ + +#include "G3D/platform.h" +# if defined(_MSC_VER) && (_MSC_VER <= 1200) + // VC6 std:: has signed/unsigned problems +# pragma warning (disable : 4018) +# endif + +#include +#include "G3D/AABox.h" +#include "G3D/Box.h" +#include "G3D/Plane.h" +#include "G3D/Sphere.h" + + +namespace G3D { + +Box AABox::toBox() const { + return Box(lo, hi); +} + + + +void AABox::split(const Vector3::Axis& axis, float location, AABox& low, AABox& high) const { + // Low, medium, and high along the chosen axis + float L = G3D::min(location, lo[axis]); + float M = G3D::min(G3D::max(location, lo[axis]), hi[axis]); + float H = G3D::max(location, hi[axis]); + + // Copy over this box. + high = low = *this; + + // Now move the split points along the special axis + low.lo[axis] = L; + low.hi[axis] = M; + high.lo[axis] = M; + high.hi[axis] = H; +} + +#if 0 +Vector3 AABox::randomSurfacePoint() const { + Vector3 extent = hi - lo; + float aXY = extent.x * extent.y; + float aYZ = extent.y * extent.z; + float aZX = extent.z * extent.x; + + float r = (float)random(0, aXY + aYZ + aZX); + + // Choose evenly between positive and negative face planes + float d = ((float)random(0, 1) < 0.5f) ? 0.0f : 1.0f; + + // The probability of choosing a given face is proportional to + // its area. + if (r < aXY) { + return + lo + + Vector3( + (float)random(0, extent.x), + (float)random(0, extent.y), + d * extent.z); + } else if (r < aYZ) { + return + lo + + Vector3( + d * extent.x, + (float)random(0, extent.y), + (float)random(0, extent.z)); + } else { + return + lo + + Vector3( + (float)random(0, extent.x), + d * extent.y, + (float)random(0, extent.z)); + } +} + + +Vector3 AABox::randomInteriorPoint() const { + return Vector3( + (float)random(lo.x, hi.x), + (float)random(lo.y, hi.y), + (float)random(lo.z, hi.z)); +} +#endif + + +bool AABox::intersects(const AABox& other) const { + // Must be overlap along all three axes. + // Try to find a separating axis. + + for (int a = 0; a < 3; ++a) { + + // |--------| + // |------| + + if ((lo[a] > other.hi[a]) || + (hi[a] < other.lo[a])) { + return false; + } + } + + return true; +} + + +bool AABox::culledBy( + const Array& plane, + int& cullingPlaneIndex, + const uint32 inMask, + uint32& outMask) const { + + return culledBy(plane.getCArray(), plane.size(), cullingPlaneIndex, inMask, outMask); +} + + +bool AABox::culledBy( + const Array& plane, + int& cullingPlaneIndex, + const uint32 inMask) const { + + return culledBy(plane.getCArray(), plane.size(), cullingPlaneIndex, inMask); +} + + +int AABox::dummy = 0; + + +bool AABox::culledBy( + const class Plane* plane, + int numPlanes, + int& cullingPlane, + const uint32 _inMask, + uint32& childMask) const { + + uint32 inMask = _inMask; + assert(numPlanes < 31); + + childMask = 0; + + const bool finite = + (abs(lo.x) < G3D::inf()) && + (abs(hi.x) < G3D::inf()) && + (abs(lo.y) < G3D::inf()) && + (abs(hi.y) < G3D::inf()) && + (abs(lo.z) < G3D::inf()) && + (abs(hi.z) < G3D::inf()); + + // See if there is one plane for which all of the + // vertices are in the negative half space. + for (int p = 0; p < numPlanes; p++) { + + // Only test planes that are not masked + if ((inMask & 1) != 0) { + + Vector3 corner; + + int numContained = 0; + int v = 0; + + // We can early-out only if we have found one point on each + // side of the plane (i.e. if we are straddling). That + // occurs when (numContained < v) && (numContained > 0) + for (v = 0; (v < 8) && ((numContained == v) || (numContained == 0)); ++v) { + // Unrolling these 3 if's into a switch decreases performance + // by about 2x + corner.x = (v & 1) ? hi.x : lo.x; + corner.y = (v & 2) ? hi.y : lo.y; + corner.z = (v & 4) ? hi.z : lo.z; + + if (finite) { // this branch is highly predictable + if (plane[p].halfSpaceContainsFinite(corner)) { + ++numContained; + } + } else { + if (plane[p].halfSpaceContains(corner)) { + ++numContained; + } + } + } + + if (numContained == 0) { + // Plane p culled the box + cullingPlane = p; + + // The caller should not recurse into the children, + // since the parent is culled. If they do recurse, + // make them only test against this one plane, which + // will immediately cull the volume. + childMask = 1 << p; + return true; + + } else if (numContained < v) { + // The bounding volume straddled the plane; we have + // to keep testing against this plane + childMask |= (1 << p); + } + } + + // Move on to the next bit. + inMask = inMask >> 1; + } + + // None of the planes could cull this box + cullingPlane = -1; + return false; +} + + +bool AABox::culledBy( + const class Plane* plane, + int numPlanes, + int& cullingPlane, + const uint32 _inMask) const { + + uint32 inMask = _inMask; + assert(numPlanes < 31); + + const bool finite = + (abs(lo.x) < G3D::inf()) && + (abs(hi.x) < G3D::inf()) && + (abs(lo.y) < G3D::inf()) && + (abs(hi.y) < G3D::inf()) && + (abs(lo.z) < G3D::inf()) && + (abs(hi.z) < G3D::inf()); + + // See if there is one plane for which all of the + // vertices are in the negative half space. + for (int p = 0; p < numPlanes; p++) { + + // Only test planes that are not masked + if ((inMask & 1) != 0) { + + bool culled = true; + Vector3 corner; + + int v; + + // Assume this plane culls all points. See if there is a point + // not culled by the plane... early out when at least one point + // is in the positive half space. + for (v = 0; (v < 8) && culled; ++v) { + + // Unrolling these 3 if's into a switch decreases performance + // by about 2x + corner.x = (v & 1) ? hi.x : lo.x; + corner.y = (v & 2) ? hi.y : lo.y; + corner.z = (v & 4) ? hi.z : lo.z; + + if (finite) { // this branch is highly predictable + culled = ! plane[p].halfSpaceContainsFinite(corner); + } else { + culled = ! plane[p].halfSpaceContains(corner); + } + } + + if (culled) { + // Plane p culled the box + cullingPlane = p; + + return true; + } + } + + // Move on to the next bit. + inMask = inMask >> 1; + } + + // None of the planes could cull this box + cullingPlane = -1; + return false; +} + + +bool AABox::intersects(const class Sphere& sphere) const { + double d = 0; + + //find the square of the distance + //from the sphere to the box + for (int i = 0; i < 3; ++i) { + if (sphere.center[i] < lo[i]) { + d += square(sphere.center[i] - lo[i]); + } else if (sphere.center[i] > hi[i]) { + d += square(sphere.center[i] - hi[i]); + } + } + + return d <= square(sphere.radius); +} + + +} // namespace diff --git a/dep/src/g3dlite/Box.cpp b/dep/src/g3dlite/Box.cpp new file mode 100644 index 00000000000..b99104ff28b --- /dev/null +++ b/dep/src/g3dlite/Box.cpp @@ -0,0 +1,348 @@ +/** + @file Box.cpp + Box class + + @maintainer Morgan McGuire, matrix@graphics3d.com + + @created 2001-06-02 + @edited 2006-02-05 +*/ + +#include "G3D/Box.h" +#include "G3D/debug.h" +#include "G3D/Plane.h" +#include "G3D/AABox.h" +#include "G3D/CoordinateFrame.h" + +namespace G3D { + +/** + Sets a field on four vertices. Used by the constructor. + */ +#define setMany(i0, i1, i2, i3, field, extreme) \ + _corner[i0].field = _corner[i1].field = \ + _corner[i2].field = _corner[i3].field = \ + (extreme).field + +Box::Box() { +} + + +Box::Box(const AABox& b) { + init(b.low(), b.high()); +} + + +Box::Box( + const Vector3& min, + const Vector3& max) { + + init(min.min(max), min.max(max)); + +} + +void Box::init( + const Vector3& min, + const Vector3& max) { + + setMany(0, 1, 2, 3, z, max); + setMany(4, 5, 6, 7, z, min); + + setMany(1, 2, 5, 6, x, max); + setMany(0, 3, 4, 7, x, min); + + setMany(3, 2, 6, 7, y, max); + setMany(0, 1, 5, 4, y, min); + + _extent = max - min; + + _axis[0] = Vector3::unitX(); + _axis[1] = Vector3::unitY(); + _axis[2] = Vector3::unitZ(); + + _volume = _extent.x * _extent.y * _extent.z; + _area = 2 * + (_extent.x * _extent.y + + _extent.y * _extent.z + + _extent.z * _extent.x); + + _center = (max + min) / 2; +} + + +float Box::volume() const { + return _volume; +} + + +float Box::surfaceArea() const { + return _area; +} + + +void Box::getLocalFrame(CoordinateFrame& frame) const { + + frame.rotation = Matrix3( + _axis[0][0], _axis[1][0], _axis[2][0], + _axis[0][1], _axis[1][1], _axis[2][1], + _axis[0][2], _axis[1][2], _axis[2][2]); + + frame.translation = _center; +} + + +CoordinateFrame Box::localFrame() const { + CoordinateFrame out; + getLocalFrame(out); + return out; +} + + +void Box::getFaceCorners(int f, Vector3& v0, Vector3& v1, Vector3& v2, Vector3& v3) const { + switch (f) { + case 0: + v0 = _corner[0]; v1 = _corner[1]; v2 = _corner[2]; v3 = _corner[3]; + break; + + case 1: + v0 = _corner[1]; v1 = _corner[5]; v2 = _corner[6]; v3 = _corner[2]; + break; + + case 2: + v0 = _corner[7]; v1 = _corner[6]; v2 = _corner[5]; v3 = _corner[4]; + break; + + case 3: + v0 = _corner[2]; v1 = _corner[6]; v2 = _corner[7]; v3 = _corner[3]; + break; + + case 4: + v0 = _corner[3]; v1 = _corner[7]; v2 = _corner[4]; v3 = _corner[0]; + break; + + case 5: + v0 = _corner[1]; v1 = _corner[0]; v2 = _corner[4]; v3 = _corner[5]; + break; + + default: + debugAssert((f >= 0) && (f < 6)); + } +} + + +bool Box::culledBy( + const Array& plane, + int& cullingPlaneIndex, + const uint32 inMask, + uint32& outMask) const { + + return culledBy(plane.getCArray(), plane.size(), cullingPlaneIndex, inMask, outMask); +} + + +bool Box::culledBy( + const Array& plane, + int& cullingPlaneIndex, + const uint32 inMask) const { + + return culledBy(plane.getCArray(), plane.size(), cullingPlaneIndex, inMask); +} + + +int32 Box::dummy = 0; + +bool Box::culledBy( + const class Plane* plane, + int numPlanes, + int& cullingPlane, + const uint32 _inMask, + uint32& childMask) const { + + uint32 inMask = _inMask; + assert(numPlanes < 31); + + childMask = 0; + + // See if there is one plane for which all of the + // vertices are in the negative half space. + for (int p = 0; p < numPlanes; p++) { + + // Only test planes that are not masked + if ((inMask & 1) != 0) { + + Vector3 corner; + + int numContained = 0; + int v = 0; + + // We can early-out only if we have found one point on each + // side of the plane (i.e. if we are straddling). That + // occurs when (numContained < v) && (numContained > 0) + for (v = 0; (v < 8) && ((numContained == v) || (numContained == 0)); ++v) { + if (plane[p].halfSpaceContains(getCorner(v))) { + ++numContained; + } + } + + if (numContained == 0) { + // Plane p culled the box + cullingPlane = p; + + // The caller should not recurse into the children, + // since the parent is culled. If they do recurse, + // make them only test against this one plane, which + // will immediately cull the volume. + childMask = 1 << p; + return true; + + } else if (numContained < v) { + // The bounding volume straddled the plane; we have + // to keep testing against this plane + childMask |= (1 << p); + } + } + + // Move on to the next bit. + inMask = inMask >> 1; + } + + // None of the planes could cull this box + cullingPlane = -1; + return false; +} + + +bool Box::culledBy( + const class Plane* plane, + int numPlanes, + int& cullingPlane, + const uint32 _inMask) const { + + uint32 inMask = _inMask; + assert(numPlanes < 31); + + // See if there is one plane for which all of the + // vertices are in the negative half space. + for (int p = 0; p < numPlanes; p++) { + + // Only test planes that are not masked + if ((inMask & 1) != 0) { + + bool culled = true; + + int v; + + // Assume this plane culls all points. See if there is a point + // not culled by the plane... early out when at least one point + // is in the positive half space. + for (v = 0; (v < 8) && culled; ++v) { + culled = ! plane[p].halfSpaceContains(getCorner(v)); + } + + if (culled) { + // Plane p culled the box + cullingPlane = p; + + return true; + } + } + + // Move on to the next bit. + inMask = inMask >> 1; + } + + // None of the planes could cull this box + cullingPlane = -1; + return false; +} + + +bool Box::contains( + const Vector3& point) const { + + // Form axes from three edges, transform the point into that + // space, and perform 3 interval tests + + Vector3 u = _corner[4] - _corner[0]; + Vector3 v = _corner[3] - _corner[0]; + Vector3 w = _corner[1] - _corner[0]; + + Matrix3 M = Matrix3(u.x, v.x, w.x, + u.y, v.y, w.y, + u.z, v.z, w.z); + + // M^-1 * (point - _corner[0]) = point in unit cube's object space + // compute the inverse of M + Vector3 osPoint = M.inverse() * (point - _corner[0]); + + return + (osPoint.x >= 0) && + (osPoint.y >= 0) && + (osPoint.z >= 0) && + (osPoint.x <= 1) && + (osPoint.y <= 1) && + (osPoint.z <= 1); +} + +#undef setMany + +#if 0 +void Box::getRandomSurfacePoint(Vector3& P, Vector3& N) const { + float aXY = _extent.x * _extent.y; + float aYZ = _extent.y * _extent.z; + float aZX = _extent.z * _extent.x; + + float r = (float)random(0, aXY + aYZ + aZX); + + // Choose evenly between positive and negative face planes + float d = (random(0, 1) < 0.5f) ? -1.0f : 1.0f; + + // The probability of choosing a given face is proportional to + // its area. + if (r < aXY) { + P = _axis[0] * (float)random(-0.5, 0.5) * _extent.x + + _axis[1] * (float)random(-0.5, 0.5) * _extent.y + + _center + _axis[2] * d * _extent.z * 0.5f; + N = _axis[2] * d; + } else if (r < aYZ) { + P = _axis[1] * (float)random(-0.5, 0.5) * _extent.y + + _axis[2] * (float)random(-0.5, 0.5) * _extent.z + + _center + _axis[0] * d * _extent.x * 0.5f; + N = _axis[0] * d; + } else { + P = _axis[2] * (float)random(-0.5, 0.5) * _extent.z + + _axis[0] *(float) random(-0.5, 0.5) * _extent.x + + _center + _axis[1] * d * _extent.y * 0.5f; + N = _axis[1] * d; + } +} + + +Vector3 Box::randomInteriorPoint() const { + Vector3 sum = _center; + + for (int a = 0; a < 3; ++a) { + sum += _axis[a] * (float)random(-0.5, 0.5) * _extent[a]; + } + + return sum; +} +#endif + + +void Box::getBounds(class AABox& aabb) const { + + Vector3 lo = _corner[0]; + Vector3 hi = lo; + + for (int v = 1; v < 8; ++v) { + const Vector3& C = _corner[v]; + lo = lo.min(C); + hi = hi.max(C); + } + + aabb = AABox(lo, hi); +} + + +} // namespace diff --git a/dep/src/g3dlite/Crypto.cpp b/dep/src/g3dlite/Crypto.cpp new file mode 100644 index 00000000000..c07e5da3c70 --- /dev/null +++ b/dep/src/g3dlite/Crypto.cpp @@ -0,0 +1,146 @@ +/** + @file Crypto.cpp + + @author Morgan McGuire, matrix@graphics3d.com + + + @created 2006-03-28 + @edited 2006-04-06 + */ + +#include "G3D/platform.h" +#include "G3D/Crypto.h" +#include "G3D/g3dmath.h" + +namespace G3D { + + +int Crypto::smallPrime(int n) { + debugAssert(n < numSmallPrimes() && n >= 0); + + // From: + // http://primes.utm.edu/lists/small/1000.txt + + static const int table[] = { + 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, + 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, + 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, + 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, + 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, + 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, + 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, + 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, + 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, + 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, + 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, + 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, + 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, + 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, + 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, + 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, + 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, + 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, + 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, + 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, + 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, + 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, + 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, + 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, + 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, + 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, + 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, + 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, + 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, + 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, + 1993, 1997, 1999}; + + return table[n]; +} + + +int Crypto::numSmallPrimes() { + return 303; +} + +uint32 Crypto::crc32(const void* byte, size_t numBytes) { + static const uint32 crc32Table[256] = { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, + 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, + 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, + 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, + 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, + 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, + 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, + 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, + 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, + 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, + 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, + 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, + 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, + 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, + 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, + 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, + 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, + 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, + 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, + 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, + 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, + 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, + 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, + 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, + 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, + 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, + 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, + 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, + 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, + 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, + 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D, + }; + + // By definition, initialize to all binary 1's + uint32 value = 0xFFFFFFFF; + + for (size_t i = 0; i < numBytes; ++i) { + value = (value >> 8 ) ^ crc32Table[static_cast(byte)[i] ^ (value & 0xFF)]; + } + + return value; +} + +} // G3D diff --git a/dep/src/g3dlite/Makefile.am b/dep/src/g3dlite/Makefile.am new file mode 100644 index 00000000000..27096a795f8 --- /dev/null +++ b/dep/src/g3dlite/Makefile.am @@ -0,0 +1,41 @@ +## Modified for MaNGOS project +## +## 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. + +## Process this file with automake to produce Makefile.in + +## CPP flags for includes, defines, etc. +AM_CPPFLAGS = -I$(srcdir) -I$(srcdir)/../../include -I$(srcdir)/../../include/g3dlite + +noinst_LIBRARIES = libg3dlite.a +libg3dlite_a_SOURCES = \ + AABox.cpp \ + Box.cpp \ + Crypto.cpp \ + format.cpp \ + Matrix3.cpp \ + Plane.cpp \ + System.cpp \ + Triangle.cpp \ + Vector3.cpp \ + Vector4.cpp + +EXTRA_DIST = \ + license.html + + diff --git a/dep/src/g3dlite/Matrix3.cpp b/dep/src/g3dlite/Matrix3.cpp new file mode 100644 index 00000000000..1d6df3ff7d7 --- /dev/null +++ b/dep/src/g3dlite/Matrix3.cpp @@ -0,0 +1,1686 @@ +/** + @file Matrix3.cpp + + 3x3 matrix class + + @author Morgan McGuire, graphics3d.com + + @created 2001-06-02 + @edited 2006-04-06 +*/ + +#include "G3D/platform.h" +#include "G3D/format.h" +#include +#include +#include "G3D/Matrix3.h" +#include "G3D/g3dmath.h" +#include "G3D/Quat.h" + +namespace G3D { + +const float Matrix3::EPSILON = 1e-06f; + +const Matrix3& Matrix3::zero() { + static Matrix3 m(0, 0, 0, 0, 0, 0, 0, 0, 0); + return m; +} + +const Matrix3& Matrix3::identity() { + static Matrix3 m(1, 0, 0, 0, 1, 0, 0, 0, 1); + return m; +} + +// Deprecated. +const Matrix3 Matrix3::ZERO(0, 0, 0, 0, 0, 0, 0, 0, 0); +const Matrix3 Matrix3::IDENTITY(1, 0, 0, 0, 1, 0, 0, 0, 1); + +const float Matrix3::ms_fSvdEpsilon = 1e-04f; +const int Matrix3::ms_iSvdMaxIterations = 32; + +bool Matrix3::fuzzyEq(const Matrix3& b) const { + for (int r = 0; r < 3; ++r) { + for (int c = 0; c < 3; ++c) { + if (! G3D::fuzzyEq(elt[r][c], b[r][c])) { + return false; + } + } + } + return true; +} + + +bool Matrix3::isOrthonormal() const { + Vector3 X = getColumn(0); + Vector3 Y = getColumn(1); + Vector3 Z = getColumn(2); + + return + (G3D::fuzzyEq(X.dot(Y), 0.0f) && + G3D::fuzzyEq(Y.dot(Z), 0.0f) && + G3D::fuzzyEq(X.dot(Z), 0.0f) && + G3D::fuzzyEq(X.squaredMagnitude(), 1.0f) && + G3D::fuzzyEq(Y.squaredMagnitude(), 1.0f) && + G3D::fuzzyEq(Z.squaredMagnitude(), 1.0f)); +} + +//---------------------------------------------------------------------------- +Matrix3::Matrix3(const Quat& _q) { + // Implementation from Watt and Watt, pg 362 + // See also http://www.flipcode.com/documents/matrfaq.html#Q54 + Quat q = _q.unitize(); + float xx = 2.0f * q.x * q.x; + float xy = 2.0f * q.x * q.y; + float xz = 2.0f * q.x * q.z; + float xw = 2.0f * q.x * q.w; + + float yy = 2.0f * q.y * q.y; + float yz = 2.0f * q.y * q.z; + float yw = 2.0f * q.y * q.w; + + float zz = 2.0f * q.z * q.z; + float zw = 2.0f * q.z * q.w; + + set(1.0f - yy - zz, xy - zw, xz + yw, + xy + zw, 1.0f - xx - zz, yz - xw, + xz - yw, yz + xw, 1.0f - xx - yy); +} + +//---------------------------------------------------------------------------- + +Matrix3::Matrix3 (const float aafEntry[3][3]) { + memcpy(elt, aafEntry, 9*sizeof(float)); +} + +//---------------------------------------------------------------------------- +Matrix3::Matrix3 (const Matrix3& rkMatrix) { + memcpy(elt, rkMatrix.elt, 9*sizeof(float)); +} + +//---------------------------------------------------------------------------- +Matrix3::Matrix3( + float fEntry00, float fEntry01, float fEntry02, + float fEntry10, float fEntry11, float fEntry12, + float fEntry20, float fEntry21, float fEntry22) { + set(fEntry00, fEntry01, fEntry02, + fEntry10, fEntry11, fEntry12, + fEntry20, fEntry21, fEntry22); +} + +void Matrix3::set( + float fEntry00, float fEntry01, float fEntry02, + float fEntry10, float fEntry11, float fEntry12, + float fEntry20, float fEntry21, float fEntry22) { + + elt[0][0] = fEntry00; + elt[0][1] = fEntry01; + elt[0][2] = fEntry02; + elt[1][0] = fEntry10; + elt[1][1] = fEntry11; + elt[1][2] = fEntry12; + elt[2][0] = fEntry20; + elt[2][1] = fEntry21; + elt[2][2] = fEntry22; +} + + +//---------------------------------------------------------------------------- +Vector3 Matrix3::getColumn (int iCol) const { + assert((0 <= iCol) && (iCol < 3)); + return Vector3(elt[0][iCol], elt[1][iCol], + elt[2][iCol]); +} + +Vector3 Matrix3::getRow (int iRow) const { + return Vector3(elt[iRow][0], elt[iRow][1], elt[iRow][2]); +} + +void Matrix3::setColumn(int iCol, const Vector3 &vector) { + debugAssert((iCol >= 0) && (iCol < 3)); + elt[0][iCol] = vector.x; + elt[1][iCol] = vector.y; + elt[2][iCol] = vector.z; +} + + +void Matrix3::setRow(int iRow, const Vector3 &vector) { + debugAssert((iRow >= 0) && (iRow < 3)); + elt[iRow][0] = vector.x; + elt[iRow][1] = vector.y; + elt[iRow][2] = vector.z; +} + + +//---------------------------------------------------------------------------- +bool Matrix3::operator== (const Matrix3& rkMatrix) const { + for (int iRow = 0; iRow < 3; iRow++) { + for (int iCol = 0; iCol < 3; iCol++) { + if ( elt[iRow][iCol] != rkMatrix.elt[iRow][iCol] ) + return false; + } + } + + return true; +} + +//---------------------------------------------------------------------------- +bool Matrix3::operator!= (const Matrix3& rkMatrix) const { + return !operator==(rkMatrix); +} + +//---------------------------------------------------------------------------- +Matrix3 Matrix3::operator+ (const Matrix3& rkMatrix) const { + Matrix3 kSum; + + for (int iRow = 0; iRow < 3; iRow++) { + for (int iCol = 0; iCol < 3; iCol++) { + kSum.elt[iRow][iCol] = elt[iRow][iCol] + + rkMatrix.elt[iRow][iCol]; + } + } + + return kSum; +} + +//---------------------------------------------------------------------------- +Matrix3 Matrix3::operator- (const Matrix3& rkMatrix) const { + Matrix3 kDiff; + + for (int iRow = 0; iRow < 3; iRow++) { + for (int iCol = 0; iCol < 3; iCol++) { + kDiff.elt[iRow][iCol] = elt[iRow][iCol] - + rkMatrix.elt[iRow][iCol]; + } + } + + return kDiff; +} + +//---------------------------------------------------------------------------- +Matrix3 Matrix3::operator* (const Matrix3& rkMatrix) const { + Matrix3 kProd; + + for (int iRow = 0; iRow < 3; iRow++) { + for (int iCol = 0; iCol < 3; iCol++) { + kProd.elt[iRow][iCol] = + elt[iRow][0] * rkMatrix.elt[0][iCol] + + elt[iRow][1] * rkMatrix.elt[1][iCol] + + elt[iRow][2] * rkMatrix.elt[2][iCol]; + } + } + + return kProd; +} + +Matrix3& Matrix3::operator+= (const Matrix3& rkMatrix) { + for (int iRow = 0; iRow < 3; iRow++) { + for (int iCol = 0; iCol < 3; iCol++) { + elt[iRow][iCol] = elt[iRow][iCol] + rkMatrix.elt[iRow][iCol]; + } + } + + return *this; +} + +Matrix3& Matrix3::operator-= (const Matrix3& rkMatrix) { + for (int iRow = 0; iRow < 3; iRow++) { + for (int iCol = 0; iCol < 3; iCol++) { + elt[iRow][iCol] = elt[iRow][iCol] - rkMatrix.elt[iRow][iCol]; + } + } + + return *this; +} + +Matrix3& Matrix3::operator*= (const Matrix3& rkMatrix) { + Matrix3 mulMat; + for (int iRow = 0; iRow < 3; iRow++) { + for (int iCol = 0; iCol < 3; iCol++) { + mulMat.elt[iRow][iCol] = + elt[iRow][0] * rkMatrix.elt[0][iCol] + + elt[iRow][1] * rkMatrix.elt[1][iCol] + + elt[iRow][2] * rkMatrix.elt[2][iCol]; + } + } + + *this = mulMat; + return *this; +} + +//---------------------------------------------------------------------------- +Matrix3 Matrix3::operator- () const { + Matrix3 kNeg; + + for (int iRow = 0; iRow < 3; iRow++) { + for (int iCol = 0; iCol < 3; iCol++) { + kNeg[iRow][iCol] = -elt[iRow][iCol]; + } + } + + return kNeg; +} + +//---------------------------------------------------------------------------- +Matrix3 Matrix3::operator* (float fScalar) const { + Matrix3 kProd; + + for (int iRow = 0; iRow < 3; iRow++) { + for (int iCol = 0; iCol < 3; iCol++) { + kProd[iRow][iCol] = fScalar * elt[iRow][iCol]; + } + } + + return kProd; +} + +//---------------------------------------------------------------------------- +Matrix3 operator* (double fScalar, const Matrix3& rkMatrix) { + Matrix3 kProd; + + for (int iRow = 0; iRow < 3; iRow++) { + for (int iCol = 0; iCol < 3; iCol++) { + kProd[iRow][iCol] = fScalar * rkMatrix.elt[iRow][iCol]; + } + } + + return kProd; +} + +Matrix3 operator* (float fScalar, const Matrix3& rkMatrix) { + return (double)fScalar * rkMatrix; +} + + +Matrix3 operator* (int fScalar, const Matrix3& rkMatrix) { + return (double)fScalar * rkMatrix; +} +//---------------------------------------------------------------------------- +Matrix3 Matrix3::transpose () const { + Matrix3 kTranspose; + + for (int iRow = 0; iRow < 3; iRow++) { + for (int iCol = 0; iCol < 3; iCol++) { + kTranspose[iRow][iCol] = elt[iCol][iRow]; + } + } + + return kTranspose; +} + +//---------------------------------------------------------------------------- +bool Matrix3::inverse (Matrix3& rkInverse, float fTolerance) const { + // Invert a 3x3 using cofactors. This is about 8 times faster than + // the Numerical Recipes code which uses Gaussian elimination. + + rkInverse[0][0] = elt[1][1] * elt[2][2] - + elt[1][2] * elt[2][1]; + rkInverse[0][1] = elt[0][2] * elt[2][1] - + elt[0][1] * elt[2][2]; + rkInverse[0][2] = elt[0][1] * elt[1][2] - + elt[0][2] * elt[1][1]; + rkInverse[1][0] = elt[1][2] * elt[2][0] - + elt[1][0] * elt[2][2]; + rkInverse[1][1] = elt[0][0] * elt[2][2] - + elt[0][2] * elt[2][0]; + rkInverse[1][2] = elt[0][2] * elt[1][0] - + elt[0][0] * elt[1][2]; + rkInverse[2][0] = elt[1][0] * elt[2][1] - + elt[1][1] * elt[2][0]; + rkInverse[2][1] = elt[0][1] * elt[2][0] - + elt[0][0] * elt[2][1]; + rkInverse[2][2] = elt[0][0] * elt[1][1] - + elt[0][1] * elt[1][0]; + + float fDet = + elt[0][0] * rkInverse[0][0] + + elt[0][1] * rkInverse[1][0] + + elt[0][2] * rkInverse[2][0]; + + if ( G3D::abs(fDet) <= fTolerance ) + return false; + + float fInvDet = 1.0 / fDet; + + for (int iRow = 0; iRow < 3; iRow++) { + for (int iCol = 0; iCol < 3; iCol++) + rkInverse[iRow][iCol] *= fInvDet; + } + + return true; +} + +//---------------------------------------------------------------------------- +Matrix3 Matrix3::inverse (float fTolerance) const { + Matrix3 kInverse = Matrix3::zero(); + inverse(kInverse, fTolerance); + return kInverse; +} + +//---------------------------------------------------------------------------- +float Matrix3::determinant () const { + float fCofactor00 = elt[1][1] * elt[2][2] - + elt[1][2] * elt[2][1]; + float fCofactor10 = elt[1][2] * elt[2][0] - + elt[1][0] * elt[2][2]; + float fCofactor20 = elt[1][0] * elt[2][1] - + elt[1][1] * elt[2][0]; + + float fDet = + elt[0][0] * fCofactor00 + + elt[0][1] * fCofactor10 + + elt[0][2] * fCofactor20; + + return fDet; +} + +//---------------------------------------------------------------------------- +void Matrix3::bidiagonalize (Matrix3& kA, Matrix3& kL, + Matrix3& kR) { + float afV[3], afW[3]; + float fLength, fSign, fT1, fInvT1, fT2; + bool bIdentity; + + // map first column to (*,0,0) + fLength = sqrt(kA[0][0] * kA[0][0] + kA[1][0] * kA[1][0] + + kA[2][0] * kA[2][0]); + + if ( fLength > 0.0 ) { + fSign = (kA[0][0] > 0.0 ? 1.0 : -1.0); + fT1 = kA[0][0] + fSign * fLength; + fInvT1 = 1.0 / fT1; + afV[1] = kA[1][0] * fInvT1; + afV[2] = kA[2][0] * fInvT1; + + fT2 = -2.0 / (1.0 + afV[1] * afV[1] + afV[2] * afV[2]); + afW[0] = fT2 * (kA[0][0] + kA[1][0] * afV[1] + kA[2][0] * afV[2]); + afW[1] = fT2 * (kA[0][1] + kA[1][1] * afV[1] + kA[2][1] * afV[2]); + afW[2] = fT2 * (kA[0][2] + kA[1][2] * afV[1] + kA[2][2] * afV[2]); + kA[0][0] += afW[0]; + kA[0][1] += afW[1]; + kA[0][2] += afW[2]; + kA[1][1] += afV[1] * afW[1]; + kA[1][2] += afV[1] * afW[2]; + kA[2][1] += afV[2] * afW[1]; + kA[2][2] += afV[2] * afW[2]; + + kL[0][0] = 1.0 + fT2; + kL[0][1] = kL[1][0] = fT2 * afV[1]; + kL[0][2] = kL[2][0] = fT2 * afV[2]; + kL[1][1] = 1.0 + fT2 * afV[1] * afV[1]; + kL[1][2] = kL[2][1] = fT2 * afV[1] * afV[2]; + kL[2][2] = 1.0 + fT2 * afV[2] * afV[2]; + bIdentity = false; + } else { + kL = Matrix3::identity(); + bIdentity = true; + } + + // map first row to (*,*,0) + fLength = sqrt(kA[0][1] * kA[0][1] + kA[0][2] * kA[0][2]); + + if ( fLength > 0.0 ) { + fSign = (kA[0][1] > 0.0 ? 1.0 : -1.0); + fT1 = kA[0][1] + fSign * fLength; + afV[2] = kA[0][2] / fT1; + + fT2 = -2.0 / (1.0 + afV[2] * afV[2]); + afW[0] = fT2 * (kA[0][1] + kA[0][2] * afV[2]); + afW[1] = fT2 * (kA[1][1] + kA[1][2] * afV[2]); + afW[2] = fT2 * (kA[2][1] + kA[2][2] * afV[2]); + kA[0][1] += afW[0]; + kA[1][1] += afW[1]; + kA[1][2] += afW[1] * afV[2]; + kA[2][1] += afW[2]; + kA[2][2] += afW[2] * afV[2]; + + kR[0][0] = 1.0; + kR[0][1] = kR[1][0] = 0.0; + kR[0][2] = kR[2][0] = 0.0; + kR[1][1] = 1.0 + fT2; + kR[1][2] = kR[2][1] = fT2 * afV[2]; + kR[2][2] = 1.0 + fT2 * afV[2] * afV[2]; + } else { + kR = Matrix3::identity(); + } + + // map second column to (*,*,0) + fLength = sqrt(kA[1][1] * kA[1][1] + kA[2][1] * kA[2][1]); + + if ( fLength > 0.0 ) { + fSign = (kA[1][1] > 0.0 ? 1.0 : -1.0); + fT1 = kA[1][1] + fSign * fLength; + afV[2] = kA[2][1] / fT1; + + fT2 = -2.0 / (1.0 + afV[2] * afV[2]); + afW[1] = fT2 * (kA[1][1] + kA[2][1] * afV[2]); + afW[2] = fT2 * (kA[1][2] + kA[2][2] * afV[2]); + kA[1][1] += afW[1]; + kA[1][2] += afW[2]; + kA[2][2] += afV[2] * afW[2]; + + float fA = 1.0 + fT2; + float fB = fT2 * afV[2]; + float fC = 1.0 + fB * afV[2]; + + if ( bIdentity ) { + kL[0][0] = 1.0; + kL[0][1] = kL[1][0] = 0.0; + kL[0][2] = kL[2][0] = 0.0; + kL[1][1] = fA; + kL[1][2] = kL[2][1] = fB; + kL[2][2] = fC; + } else { + for (int iRow = 0; iRow < 3; iRow++) { + float fTmp0 = kL[iRow][1]; + float fTmp1 = kL[iRow][2]; + kL[iRow][1] = fA * fTmp0 + fB * fTmp1; + kL[iRow][2] = fB * fTmp0 + fC * fTmp1; + } + } + } +} + +//---------------------------------------------------------------------------- +void Matrix3::golubKahanStep (Matrix3& kA, Matrix3& kL, + Matrix3& kR) { + float fT11 = kA[0][1] * kA[0][1] + kA[1][1] * kA[1][1]; + float fT22 = kA[1][2] * kA[1][2] + kA[2][2] * kA[2][2]; + float fT12 = kA[1][1] * kA[1][2]; + float fTrace = fT11 + fT22; + float fDiff = fT11 - fT22; + float fDiscr = sqrt(fDiff * fDiff + 4.0 * fT12 * fT12); + float fRoot1 = 0.5 * (fTrace + fDiscr); + float fRoot2 = 0.5 * (fTrace - fDiscr); + + // adjust right + float fY = kA[0][0] - (G3D::abs(fRoot1 - fT22) <= + G3D::abs(fRoot2 - fT22) ? fRoot1 : fRoot2); + float fZ = kA[0][1]; + float fInvLength = 1.0 / sqrt(fY * fY + fZ * fZ); + float fSin = fZ * fInvLength; + float fCos = -fY * fInvLength; + + float fTmp0 = kA[0][0]; + float fTmp1 = kA[0][1]; + kA[0][0] = fCos * fTmp0 - fSin * fTmp1; + kA[0][1] = fSin * fTmp0 + fCos * fTmp1; + kA[1][0] = -fSin * kA[1][1]; + kA[1][1] *= fCos; + + int iRow; + + for (iRow = 0; iRow < 3; iRow++) { + fTmp0 = kR[0][iRow]; + fTmp1 = kR[1][iRow]; + kR[0][iRow] = fCos * fTmp0 - fSin * fTmp1; + kR[1][iRow] = fSin * fTmp0 + fCos * fTmp1; + } + + // adjust left + fY = kA[0][0]; + + fZ = kA[1][0]; + + fInvLength = 1.0 / sqrt(fY * fY + fZ * fZ); + + fSin = fZ * fInvLength; + + fCos = -fY * fInvLength; + + kA[0][0] = fCos * kA[0][0] - fSin * kA[1][0]; + + fTmp0 = kA[0][1]; + + fTmp1 = kA[1][1]; + + kA[0][1] = fCos * fTmp0 - fSin * fTmp1; + + kA[1][1] = fSin * fTmp0 + fCos * fTmp1; + + kA[0][2] = -fSin * kA[1][2]; + + kA[1][2] *= fCos; + + int iCol; + + for (iCol = 0; iCol < 3; iCol++) { + fTmp0 = kL[iCol][0]; + fTmp1 = kL[iCol][1]; + kL[iCol][0] = fCos * fTmp0 - fSin * fTmp1; + kL[iCol][1] = fSin * fTmp0 + fCos * fTmp1; + } + + // adjust right + fY = kA[0][1]; + + fZ = kA[0][2]; + + fInvLength = 1.0 / sqrt(fY * fY + fZ * fZ); + + fSin = fZ * fInvLength; + + fCos = -fY * fInvLength; + + kA[0][1] = fCos * kA[0][1] - fSin * kA[0][2]; + + fTmp0 = kA[1][1]; + + fTmp1 = kA[1][2]; + + kA[1][1] = fCos * fTmp0 - fSin * fTmp1; + + kA[1][2] = fSin * fTmp0 + fCos * fTmp1; + + kA[2][1] = -fSin * kA[2][2]; + + kA[2][2] *= fCos; + + for (iRow = 0; iRow < 3; iRow++) { + fTmp0 = kR[1][iRow]; + fTmp1 = kR[2][iRow]; + kR[1][iRow] = fCos * fTmp0 - fSin * fTmp1; + kR[2][iRow] = fSin * fTmp0 + fCos * fTmp1; + } + + // adjust left + fY = kA[1][1]; + + fZ = kA[2][1]; + + fInvLength = 1.0 / sqrt(fY * fY + fZ * fZ); + + fSin = fZ * fInvLength; + + fCos = -fY * fInvLength; + + kA[1][1] = fCos * kA[1][1] - fSin * kA[2][1]; + + fTmp0 = kA[1][2]; + + fTmp1 = kA[2][2]; + + kA[1][2] = fCos * fTmp0 - fSin * fTmp1; + + kA[2][2] = fSin * fTmp0 + fCos * fTmp1; + + for (iCol = 0; iCol < 3; iCol++) { + fTmp0 = kL[iCol][1]; + fTmp1 = kL[iCol][2]; + kL[iCol][1] = fCos * fTmp0 - fSin * fTmp1; + kL[iCol][2] = fSin * fTmp0 + fCos * fTmp1; + } +} + +//---------------------------------------------------------------------------- +void Matrix3::singularValueDecomposition (Matrix3& kL, Vector3& kS, + Matrix3& kR) const { + int iRow, iCol; + + Matrix3 kA = *this; + bidiagonalize(kA, kL, kR); + + for (int i = 0; i < ms_iSvdMaxIterations; i++) { + float fTmp, fTmp0, fTmp1; + float fSin0, fCos0, fTan0; + float fSin1, fCos1, fTan1; + + bool bTest1 = (G3D::abs(kA[0][1]) <= + ms_fSvdEpsilon * (G3D::abs(kA[0][0]) + G3D::abs(kA[1][1]))); + bool bTest2 = (G3D::abs(kA[1][2]) <= + ms_fSvdEpsilon * (G3D::abs(kA[1][1]) + G3D::abs(kA[2][2]))); + + if ( bTest1 ) { + if ( bTest2 ) { + kS[0] = kA[0][0]; + kS[1] = kA[1][1]; + kS[2] = kA[2][2]; + break; + } else { + // 2x2 closed form factorization + fTmp = (kA[1][1] * kA[1][1] - kA[2][2] * kA[2][2] + + kA[1][2] * kA[1][2]) / (kA[1][2] * kA[2][2]); + fTan0 = 0.5 * (fTmp + sqrt(fTmp * fTmp + 4.0)); + fCos0 = 1.0 / sqrt(1.0 + fTan0 * fTan0); + fSin0 = fTan0 * fCos0; + + for (iCol = 0; iCol < 3; iCol++) { + fTmp0 = kL[iCol][1]; + fTmp1 = kL[iCol][2]; + kL[iCol][1] = fCos0 * fTmp0 - fSin0 * fTmp1; + kL[iCol][2] = fSin0 * fTmp0 + fCos0 * fTmp1; + } + + fTan1 = (kA[1][2] - kA[2][2] * fTan0) / kA[1][1]; + fCos1 = 1.0 / sqrt(1.0 + fTan1 * fTan1); + fSin1 = -fTan1 * fCos1; + + for (iRow = 0; iRow < 3; iRow++) { + fTmp0 = kR[1][iRow]; + fTmp1 = kR[2][iRow]; + kR[1][iRow] = fCos1 * fTmp0 - fSin1 * fTmp1; + kR[2][iRow] = fSin1 * fTmp0 + fCos1 * fTmp1; + } + + kS[0] = kA[0][0]; + kS[1] = fCos0 * fCos1 * kA[1][1] - + fSin1 * (fCos0 * kA[1][2] - fSin0 * kA[2][2]); + kS[2] = fSin0 * fSin1 * kA[1][1] + + fCos1 * (fSin0 * kA[1][2] + fCos0 * kA[2][2]); + break; + } + } else { + if ( bTest2 ) { + // 2x2 closed form factorization + fTmp = (kA[0][0] * kA[0][0] + kA[1][1] * kA[1][1] - + kA[0][1] * kA[0][1]) / (kA[0][1] * kA[1][1]); + fTan0 = 0.5 * ( -fTmp + sqrt(fTmp * fTmp + 4.0)); + fCos0 = 1.0 / sqrt(1.0 + fTan0 * fTan0); + fSin0 = fTan0 * fCos0; + + for (iCol = 0; iCol < 3; iCol++) { + fTmp0 = kL[iCol][0]; + fTmp1 = kL[iCol][1]; + kL[iCol][0] = fCos0 * fTmp0 - fSin0 * fTmp1; + kL[iCol][1] = fSin0 * fTmp0 + fCos0 * fTmp1; + } + + fTan1 = (kA[0][1] - kA[1][1] * fTan0) / kA[0][0]; + fCos1 = 1.0 / sqrt(1.0 + fTan1 * fTan1); + fSin1 = -fTan1 * fCos1; + + for (iRow = 0; iRow < 3; iRow++) { + fTmp0 = kR[0][iRow]; + fTmp1 = kR[1][iRow]; + kR[0][iRow] = fCos1 * fTmp0 - fSin1 * fTmp1; + kR[1][iRow] = fSin1 * fTmp0 + fCos1 * fTmp1; + } + + kS[0] = fCos0 * fCos1 * kA[0][0] - + fSin1 * (fCos0 * kA[0][1] - fSin0 * kA[1][1]); + kS[1] = fSin0 * fSin1 * kA[0][0] + + fCos1 * (fSin0 * kA[0][1] + fCos0 * kA[1][1]); + kS[2] = kA[2][2]; + break; + } else { + golubKahanStep(kA, kL, kR); + } + } + } + + // positize diagonal + for (iRow = 0; iRow < 3; iRow++) { + if ( kS[iRow] < 0.0 ) { + kS[iRow] = -kS[iRow]; + + for (iCol = 0; iCol < 3; iCol++) + kR[iRow][iCol] = -kR[iRow][iCol]; + } + } +} + +//---------------------------------------------------------------------------- +void Matrix3::singularValueComposition (const Matrix3& kL, + const Vector3& kS, const Matrix3& kR) { + int iRow, iCol; + Matrix3 kTmp; + + // product S*R + for (iRow = 0; iRow < 3; iRow++) { + for (iCol = 0; iCol < 3; iCol++) + kTmp[iRow][iCol] = kS[iRow] * kR[iRow][iCol]; + } + + // product L*S*R + for (iRow = 0; iRow < 3; iRow++) { + for (iCol = 0; iCol < 3; iCol++) { + elt[iRow][iCol] = 0.0; + + for (int iMid = 0; iMid < 3; iMid++) + elt[iRow][iCol] += kL[iRow][iMid] * kTmp[iMid][iCol]; + } + } +} + +//---------------------------------------------------------------------------- +void Matrix3::orthonormalize () { + // Algorithm uses Gram-Schmidt orthogonalization. If 'this' matrix is + // M = [m0|m1|m2], then orthonormal output matrix is Q = [q0|q1|q2], + // + // q0 = m0/|m0| + // q1 = (m1-(q0*m1)q0)/|m1-(q0*m1)q0| + // q2 = (m2-(q0*m2)q0-(q1*m2)q1)/|m2-(q0*m2)q0-(q1*m2)q1| + // + // where |V| indicates length of vector V and A*B indicates dot + // product of vectors A and B. + + // compute q0 + float fInvLength = 1.0 / sqrt(elt[0][0] * elt[0][0] + + elt[1][0] * elt[1][0] + + elt[2][0] * elt[2][0]); + + elt[0][0] *= fInvLength; + elt[1][0] *= fInvLength; + elt[2][0] *= fInvLength; + + // compute q1 + float fDot0 = + elt[0][0] * elt[0][1] + + elt[1][0] * elt[1][1] + + elt[2][0] * elt[2][1]; + + elt[0][1] -= fDot0 * elt[0][0]; + elt[1][1] -= fDot0 * elt[1][0]; + elt[2][1] -= fDot0 * elt[2][0]; + + fInvLength = 1.0 / sqrt(elt[0][1] * elt[0][1] + + elt[1][1] * elt[1][1] + + elt[2][1] * elt[2][1]); + + elt[0][1] *= fInvLength; + elt[1][1] *= fInvLength; + elt[2][1] *= fInvLength; + + // compute q2 + float fDot1 = + elt[0][1] * elt[0][2] + + elt[1][1] * elt[1][2] + + elt[2][1] * elt[2][2]; + + fDot0 = + elt[0][0] * elt[0][2] + + elt[1][0] * elt[1][2] + + elt[2][0] * elt[2][2]; + + elt[0][2] -= fDot0 * elt[0][0] + fDot1 * elt[0][1]; + elt[1][2] -= fDot0 * elt[1][0] + fDot1 * elt[1][1]; + elt[2][2] -= fDot0 * elt[2][0] + fDot1 * elt[2][1]; + + fInvLength = 1.0 / sqrt(elt[0][2] * elt[0][2] + + elt[1][2] * elt[1][2] + + elt[2][2] * elt[2][2]); + + elt[0][2] *= fInvLength; + elt[1][2] *= fInvLength; + elt[2][2] *= fInvLength; +} + +//---------------------------------------------------------------------------- +void Matrix3::qDUDecomposition (Matrix3& kQ, + Vector3& kD, Vector3& kU) const { + // Factor M = QR = QDU where Q is orthogonal, D is diagonal, + // and U is upper triangular with ones on its diagonal. Algorithm uses + // Gram-Schmidt orthogonalization (the QR algorithm). + // + // If M = [ m0 | m1 | m2 ] and Q = [ q0 | q1 | q2 ], then + // + // q0 = m0/|m0| + // q1 = (m1-(q0*m1)q0)/|m1-(q0*m1)q0| + // q2 = (m2-(q0*m2)q0-(q1*m2)q1)/|m2-(q0*m2)q0-(q1*m2)q1| + // + // where |V| indicates length of vector V and A*B indicates dot + // product of vectors A and B. The matrix R has entries + // + // r00 = q0*m0 r01 = q0*m1 r02 = q0*m2 + // r10 = 0 r11 = q1*m1 r12 = q1*m2 + // r20 = 0 r21 = 0 r22 = q2*m2 + // + // so D = diag(r00,r11,r22) and U has entries u01 = r01/r00, + // u02 = r02/r00, and u12 = r12/r11. + + // Q = rotation + // D = scaling + // U = shear + + // D stores the three diagonal entries r00, r11, r22 + // U stores the entries U[0] = u01, U[1] = u02, U[2] = u12 + + // build orthogonal matrix Q + float fInvLength = 1.0 / sqrt(elt[0][0] * elt[0][0] + + elt[1][0] * elt[1][0] + + elt[2][0] * elt[2][0]); + kQ[0][0] = elt[0][0] * fInvLength; + kQ[1][0] = elt[1][0] * fInvLength; + kQ[2][0] = elt[2][0] * fInvLength; + + float fDot = kQ[0][0] * elt[0][1] + kQ[1][0] * elt[1][1] + + kQ[2][0] * elt[2][1]; + kQ[0][1] = elt[0][1] - fDot * kQ[0][0]; + kQ[1][1] = elt[1][1] - fDot * kQ[1][0]; + kQ[2][1] = elt[2][1] - fDot * kQ[2][0]; + fInvLength = 1.0 / sqrt(kQ[0][1] * kQ[0][1] + kQ[1][1] * kQ[1][1] + + kQ[2][1] * kQ[2][1]); + kQ[0][1] *= fInvLength; + kQ[1][1] *= fInvLength; + kQ[2][1] *= fInvLength; + + fDot = kQ[0][0] * elt[0][2] + kQ[1][0] * elt[1][2] + + kQ[2][0] * elt[2][2]; + kQ[0][2] = elt[0][2] - fDot * kQ[0][0]; + kQ[1][2] = elt[1][2] - fDot * kQ[1][0]; + kQ[2][2] = elt[2][2] - fDot * kQ[2][0]; + fDot = kQ[0][1] * elt[0][2] + kQ[1][1] * elt[1][2] + + kQ[2][1] * elt[2][2]; + kQ[0][2] -= fDot * kQ[0][1]; + kQ[1][2] -= fDot * kQ[1][1]; + kQ[2][2] -= fDot * kQ[2][1]; + fInvLength = 1.0 / sqrt(kQ[0][2] * kQ[0][2] + kQ[1][2] * kQ[1][2] + + kQ[2][2] * kQ[2][2]); + kQ[0][2] *= fInvLength; + kQ[1][2] *= fInvLength; + kQ[2][2] *= fInvLength; + + // guarantee that orthogonal matrix has determinant 1 (no reflections) + float fDet = kQ[0][0] * kQ[1][1] * kQ[2][2] + kQ[0][1] * kQ[1][2] * kQ[2][0] + + kQ[0][2] * kQ[1][0] * kQ[2][1] - kQ[0][2] * kQ[1][1] * kQ[2][0] - + kQ[0][1] * kQ[1][0] * kQ[2][2] - kQ[0][0] * kQ[1][2] * kQ[2][1]; + + if ( fDet < 0.0 ) { + for (int iRow = 0; iRow < 3; iRow++) + for (int iCol = 0; iCol < 3; iCol++) + kQ[iRow][iCol] = -kQ[iRow][iCol]; + } + + // build "right" matrix R + Matrix3 kR; + + kR[0][0] = kQ[0][0] * elt[0][0] + kQ[1][0] * elt[1][0] + + kQ[2][0] * elt[2][0]; + + kR[0][1] = kQ[0][0] * elt[0][1] + kQ[1][0] * elt[1][1] + + kQ[2][0] * elt[2][1]; + + kR[1][1] = kQ[0][1] * elt[0][1] + kQ[1][1] * elt[1][1] + + kQ[2][1] * elt[2][1]; + + kR[0][2] = kQ[0][0] * elt[0][2] + kQ[1][0] * elt[1][2] + + kQ[2][0] * elt[2][2]; + + kR[1][2] = kQ[0][1] * elt[0][2] + kQ[1][1] * elt[1][2] + + kQ[2][1] * elt[2][2]; + + kR[2][2] = kQ[0][2] * elt[0][2] + kQ[1][2] * elt[1][2] + + kQ[2][2] * elt[2][2]; + + // the scaling component + kD[0] = kR[0][0]; + + kD[1] = kR[1][1]; + + kD[2] = kR[2][2]; + + // the shear component + float fInvD0 = 1.0 / kD[0]; + + kU[0] = kR[0][1] * fInvD0; + + kU[1] = kR[0][2] * fInvD0; + + kU[2] = kR[1][2] / kD[1]; +} + +//---------------------------------------------------------------------------- +float Matrix3::maxCubicRoot (float afCoeff[3]) { + // Spectral norm is for A^T*A, so characteristic polynomial + // P(x) = c[0]+c[1]*x+c[2]*x^2+x^3 has three positive float roots. + // This yields the assertions c[0] < 0 and c[2]*c[2] >= 3*c[1]. + + // quick out for uniform scale (triple root) + const float fOneThird = 1.0f / 3.0f; + const float fEpsilon = 1e-06f; + float fDiscr = afCoeff[2] * afCoeff[2] - 3.0f * afCoeff[1]; + + if ( fDiscr <= fEpsilon ) + return -fOneThird*afCoeff[2]; + + // Compute an upper bound on roots of P(x). This assumes that A^T*A + // has been scaled by its largest entry. + float fX = 1.0f; + + float fPoly = afCoeff[0] + fX * (afCoeff[1] + fX * (afCoeff[2] + fX)); + + if ( fPoly < 0.0f ) { + // uses a matrix norm to find an upper bound on maximum root + fX = G3D::abs(afCoeff[0]); + float fTmp = 1.0 + G3D::abs(afCoeff[1]); + + if ( fTmp > fX ) + fX = fTmp; + + fTmp = 1.0 + G3D::abs(afCoeff[2]); + + if ( fTmp > fX ) + fX = fTmp; + } + + // Newton's method to find root + float fTwoC2 = 2.0f * afCoeff[2]; + + for (int i = 0; i < 16; i++) { + fPoly = afCoeff[0] + fX * (afCoeff[1] + fX * (afCoeff[2] + fX)); + + if ( G3D::abs(fPoly) <= fEpsilon ) + return fX; + + float fDeriv = afCoeff[1] + fX * (fTwoC2 + 3.0f * fX); + + fX -= fPoly / fDeriv; + } + + return fX; +} + +//---------------------------------------------------------------------------- +float Matrix3::spectralNorm () const { + Matrix3 kP; + int iRow, iCol; + float fPmax = 0.0; + + for (iRow = 0; iRow < 3; iRow++) { + for (iCol = 0; iCol < 3; iCol++) { + kP[iRow][iCol] = 0.0; + + for (int iMid = 0; iMid < 3; iMid++) { + kP[iRow][iCol] += + elt[iMid][iRow] * elt[iMid][iCol]; + } + + if ( kP[iRow][iCol] > fPmax ) + fPmax = kP[iRow][iCol]; + } + } + + float fInvPmax = 1.0 / fPmax; + + for (iRow = 0; iRow < 3; iRow++) { + for (iCol = 0; iCol < 3; iCol++) + kP[iRow][iCol] *= fInvPmax; + } + + float afCoeff[3]; + afCoeff[0] = -(kP[0][0] * (kP[1][1] * kP[2][2] - kP[1][2] * kP[2][1]) + + kP[0][1] * (kP[2][0] * kP[1][2] - kP[1][0] * kP[2][2]) + + kP[0][2] * (kP[1][0] * kP[2][1] - kP[2][0] * kP[1][1])); + afCoeff[1] = kP[0][0] * kP[1][1] - kP[0][1] * kP[1][0] + + kP[0][0] * kP[2][2] - kP[0][2] * kP[2][0] + + kP[1][1] * kP[2][2] - kP[1][2] * kP[2][1]; + afCoeff[2] = -(kP[0][0] + kP[1][1] + kP[2][2]); + + float fRoot = maxCubicRoot(afCoeff); + float fNorm = sqrt(fPmax * fRoot); + return fNorm; +} + +//---------------------------------------------------------------------------- +void Matrix3::toAxisAngle (Vector3& rkAxis, float& rfRadians) const { + // Let (x,y,z) be the unit-length axis and let A be an angle of rotation. + // The rotation matrix is R = I + sin(A)*P + (1-cos(A))*P^2 where + // I is the identity and + // + // +- -+ + // P = | 0 -z +y | + // | +z 0 -x | + // | -y +x 0 | + // +- -+ + // + // If A > 0, R represents a counterclockwise rotation about the axis in + // the sense of looking from the tip of the axis vector towards the + // origin. Some algebra will show that + // + // cos(A) = (trace(R)-1)/2 and R - R^t = 2*sin(A)*P + // + // In the event that A = pi, R-R^t = 0 which prevents us from extracting + // the axis through P. Instead note that R = I+2*P^2 when A = pi, so + // P^2 = (R-I)/2. The diagonal entries of P^2 are x^2-1, y^2-1, and + // z^2-1. We can solve these for axis (x,y,z). Because the angle is pi, + // it does not matter which sign you choose on the square roots. + + float fTrace = elt[0][0] + elt[1][1] + elt[2][2]; + float fCos = 0.5 * (fTrace - 1.0); + rfRadians = G3D::aCos(fCos); // in [0,PI] + + if ( rfRadians > 0.0 ) { + if ( rfRadians < G3D_PI ) { + rkAxis.x = elt[2][1] - elt[1][2]; + rkAxis.y = elt[0][2] - elt[2][0]; + rkAxis.z = elt[1][0] - elt[0][1]; + rkAxis.unitize(); + } else { + // angle is PI + float fHalfInverse; + + if ( elt[0][0] >= elt[1][1] ) { + // r00 >= r11 + if ( elt[0][0] >= elt[2][2] ) { + // r00 is maximum diagonal term + rkAxis.x = 0.5 * sqrt(elt[0][0] - + elt[1][1] - elt[2][2] + 1.0); + fHalfInverse = 0.5 / rkAxis.x; + rkAxis.y = fHalfInverse * elt[0][1]; + rkAxis.z = fHalfInverse * elt[0][2]; + } else { + // r22 is maximum diagonal term + rkAxis.z = 0.5 * sqrt(elt[2][2] - + elt[0][0] - elt[1][1] + 1.0); + fHalfInverse = 0.5 / rkAxis.z; + rkAxis.x = fHalfInverse * elt[0][2]; + rkAxis.y = fHalfInverse * elt[1][2]; + } + } else { + // r11 > r00 + if ( elt[1][1] >= elt[2][2] ) { + // r11 is maximum diagonal term + rkAxis.y = 0.5 * sqrt(elt[1][1] - + elt[0][0] - elt[2][2] + 1.0); + fHalfInverse = 0.5 / rkAxis.y; + rkAxis.x = fHalfInverse * elt[0][1]; + rkAxis.z = fHalfInverse * elt[1][2]; + } else { + // r22 is maximum diagonal term + rkAxis.z = 0.5 * sqrt(elt[2][2] - + elt[0][0] - elt[1][1] + 1.0); + fHalfInverse = 0.5 / rkAxis.z; + rkAxis.x = fHalfInverse * elt[0][2]; + rkAxis.y = fHalfInverse * elt[1][2]; + } + } + } + } else { + // The angle is 0 and the matrix is the identity. Any axis will + // work, so just use the x-axis. + rkAxis.x = 1.0; + rkAxis.y = 0.0; + rkAxis.z = 0.0; + } +} + +//---------------------------------------------------------------------------- +Matrix3 Matrix3::fromAxisAngle (const Vector3& rkAxis, float fRadians) { + Matrix3 m; + + float fCos = cos(fRadians); + float fSin = sin(fRadians); + float fOneMinusCos = 1.0 - fCos; + float fX2 = rkAxis.x * rkAxis.x; + float fY2 = rkAxis.y * rkAxis.y; + float fZ2 = rkAxis.z * rkAxis.z; + float fXYM = rkAxis.x * rkAxis.y * fOneMinusCos; + float fXZM = rkAxis.x * rkAxis.z * fOneMinusCos; + float fYZM = rkAxis.y * rkAxis.z * fOneMinusCos; + float fXSin = rkAxis.x * fSin; + float fYSin = rkAxis.y * fSin; + float fZSin = rkAxis.z * fSin; + + m.elt[0][0] = fX2 * fOneMinusCos + fCos; + m.elt[0][1] = fXYM - fZSin; + m.elt[0][2] = fXZM + fYSin; + m.elt[1][0] = fXYM + fZSin; + m.elt[1][1] = fY2 * fOneMinusCos + fCos; + m.elt[1][2] = fYZM - fXSin; + m.elt[2][0] = fXZM - fYSin; + m.elt[2][1] = fYZM + fXSin; + m.elt[2][2] = fZ2 * fOneMinusCos + fCos; + + return m; +} + +//---------------------------------------------------------------------------- +bool Matrix3::toEulerAnglesXYZ (float& rfXAngle, float& rfYAngle, + float& rfZAngle) const { + // rot = cy*cz -cy*sz sy + // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx + // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy + + if ( elt[0][2] < 1.0f ) { + if ( elt[0][2] > -1.0f ) { + rfXAngle = G3D::aTan2( -elt[1][2], elt[2][2]); + rfYAngle = (float) G3D::aSin(elt[0][2]); + rfZAngle = G3D::aTan2( -elt[0][1], elt[0][0]); + return true; + } else { + // WARNING. Not unique. XA - ZA = -atan2(r10,r11) + rfXAngle = -G3D::aTan2(elt[1][0], elt[1][1]); + rfYAngle = -(float)G3D_HALF_PI; + rfZAngle = 0.0f; + return false; + } + } else { + // WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11) + rfXAngle = G3D::aTan2(elt[1][0], elt[1][1]); + rfYAngle = (float)G3D_HALF_PI; + rfZAngle = 0.0f; + return false; + } +} + +//---------------------------------------------------------------------------- +bool Matrix3::toEulerAnglesXZY (float& rfXAngle, float& rfZAngle, + float& rfYAngle) const { + // rot = cy*cz -sz cz*sy + // sx*sy+cx*cy*sz cx*cz -cy*sx+cx*sy*sz + // -cx*sy+cy*sx*sz cz*sx cx*cy+sx*sy*sz + + if ( elt[0][1] < 1.0f ) { + if ( elt[0][1] > -1.0f ) { + rfXAngle = G3D::aTan2(elt[2][1], elt[1][1]); + rfZAngle = (float) asin( -elt[0][1]); + rfYAngle = G3D::aTan2(elt[0][2], elt[0][0]); + return true; + } else { + // WARNING. Not unique. XA - YA = atan2(r20,r22) + rfXAngle = G3D::aTan2(elt[2][0], elt[2][2]); + rfZAngle = (float)G3D_HALF_PI; + rfYAngle = 0.0; + return false; + } + } else { + // WARNING. Not unique. XA + YA = atan2(-r20,r22) + rfXAngle = G3D::aTan2( -elt[2][0], elt[2][2]); + rfZAngle = -(float)G3D_HALF_PI; + rfYAngle = 0.0f; + return false; + } +} + +//---------------------------------------------------------------------------- +bool Matrix3::toEulerAnglesYXZ (float& rfYAngle, float& rfXAngle, + float& rfZAngle) const { + // rot = cy*cz+sx*sy*sz cz*sx*sy-cy*sz cx*sy + // cx*sz cx*cz -sx + // -cz*sy+cy*sx*sz cy*cz*sx+sy*sz cx*cy + + if ( elt[1][2] < 1.0 ) { + if ( elt[1][2] > -1.0 ) { + rfYAngle = G3D::aTan2(elt[0][2], elt[2][2]); + rfXAngle = (float) asin( -elt[1][2]); + rfZAngle = G3D::aTan2(elt[1][0], elt[1][1]); + return true; + } else { + // WARNING. Not unique. YA - ZA = atan2(r01,r00) + rfYAngle = G3D::aTan2(elt[0][1], elt[0][0]); + rfXAngle = (float)G3D_HALF_PI; + rfZAngle = 0.0; + return false; + } + } else { + // WARNING. Not unique. YA + ZA = atan2(-r01,r00) + rfYAngle = G3D::aTan2( -elt[0][1], elt[0][0]); + rfXAngle = -(float)G3D_HALF_PI; + rfZAngle = 0.0f; + return false; + } +} + +//---------------------------------------------------------------------------- +bool Matrix3::toEulerAnglesYZX (float& rfYAngle, float& rfZAngle, + float& rfXAngle) const { + // rot = cy*cz sx*sy-cx*cy*sz cx*sy+cy*sx*sz + // sz cx*cz -cz*sx + // -cz*sy cy*sx+cx*sy*sz cx*cy-sx*sy*sz + + if ( elt[1][0] < 1.0 ) { + if ( elt[1][0] > -1.0 ) { + rfYAngle = G3D::aTan2( -elt[2][0], elt[0][0]); + rfZAngle = (float) asin(elt[1][0]); + rfXAngle = G3D::aTan2( -elt[1][2], elt[1][1]); + return true; + } else { + // WARNING. Not unique. YA - XA = -atan2(r21,r22); + rfYAngle = -G3D::aTan2(elt[2][1], elt[2][2]); + rfZAngle = -(float)G3D_HALF_PI; + rfXAngle = 0.0; + return false; + } + } else { + // WARNING. Not unique. YA + XA = atan2(r21,r22) + rfYAngle = G3D::aTan2(elt[2][1], elt[2][2]); + rfZAngle = (float)G3D_HALF_PI; + rfXAngle = 0.0f; + return false; + } +} + +//---------------------------------------------------------------------------- +bool Matrix3::toEulerAnglesZXY (float& rfZAngle, float& rfXAngle, + float& rfYAngle) const { + // rot = cy*cz-sx*sy*sz -cx*sz cz*sy+cy*sx*sz + // cz*sx*sy+cy*sz cx*cz -cy*cz*sx+sy*sz + // -cx*sy sx cx*cy + + if ( elt[2][1] < 1.0 ) { + if ( elt[2][1] > -1.0 ) { + rfZAngle = G3D::aTan2( -elt[0][1], elt[1][1]); + rfXAngle = (float) asin(elt[2][1]); + rfYAngle = G3D::aTan2( -elt[2][0], elt[2][2]); + return true; + } else { + // WARNING. Not unique. ZA - YA = -atan(r02,r00) + rfZAngle = -G3D::aTan2(elt[0][2], elt[0][0]); + rfXAngle = -(float)G3D_HALF_PI; + rfYAngle = 0.0f; + return false; + } + } else { + // WARNING. Not unique. ZA + YA = atan2(r02,r00) + rfZAngle = G3D::aTan2(elt[0][2], elt[0][0]); + rfXAngle = (float)G3D_HALF_PI; + rfYAngle = 0.0f; + return false; + } +} + +//---------------------------------------------------------------------------- +bool Matrix3::toEulerAnglesZYX (float& rfZAngle, float& rfYAngle, + float& rfXAngle) const { + // rot = cy*cz cz*sx*sy-cx*sz cx*cz*sy+sx*sz + // cy*sz cx*cz+sx*sy*sz -cz*sx+cx*sy*sz + // -sy cy*sx cx*cy + + if ( elt[2][0] < 1.0 ) { + if ( elt[2][0] > -1.0 ) { + rfZAngle = atan2f(elt[1][0], elt[0][0]); + rfYAngle = asinf(-(double)elt[2][1]); + rfXAngle = atan2f(elt[2][1], elt[2][2]); + return true; + } else { + // WARNING. Not unique. ZA - XA = -atan2(r01,r02) + rfZAngle = -G3D::aTan2(elt[0][1], elt[0][2]); + rfYAngle = (float)G3D_HALF_PI; + rfXAngle = 0.0f; + return false; + } + } else { + // WARNING. Not unique. ZA + XA = atan2(-r01,-r02) + rfZAngle = G3D::aTan2( -elt[0][1], -elt[0][2]); + rfYAngle = -(float)G3D_HALF_PI; + rfXAngle = 0.0f; + return false; + } +} + +//---------------------------------------------------------------------------- +Matrix3 Matrix3::fromEulerAnglesXYZ (float fYAngle, float fPAngle, + float fRAngle) { + float fCos, fSin; + + fCos = cosf(fYAngle); + fSin = sinf(fYAngle); + Matrix3 kXMat(1.0f, 0.0f, 0.0f, 0.0f, fCos, -fSin, 0.0, fSin, fCos); + + fCos = cosf(fPAngle); + fSin = sinf(fPAngle); + Matrix3 kYMat(fCos, 0.0f, fSin, 0.0f, 1.0f, 0.0f, -fSin, 0.0f, fCos); + + fCos = cosf(fRAngle); + fSin = sinf(fRAngle); + Matrix3 kZMat(fCos, -fSin, 0.0f, fSin, fCos, 0.0f, 0.0f, 0.0f, 1.0f); + + return kXMat * (kYMat * kZMat); +} + +//---------------------------------------------------------------------------- +Matrix3 Matrix3::fromEulerAnglesXZY (float fYAngle, float fPAngle, + float fRAngle) { + + float fCos, fSin; + + fCos = cosf(fYAngle); + fSin = sinf(fYAngle); + Matrix3 kXMat(1.0, 0.0, 0.0, 0.0, fCos, -fSin, 0.0, fSin, fCos); + + fCos = cosf(fPAngle); + fSin = sinf(fPAngle); + Matrix3 kZMat(fCos, -fSin, 0.0, fSin, fCos, 0.0, 0.0, 0.0, 1.0); + + fCos = cosf(fRAngle); + fSin = sinf(fRAngle); + Matrix3 kYMat(fCos, 0.0, fSin, 0.0, 1.0, 0.0, -fSin, 0.0, fCos); + + return kXMat * (kZMat * kYMat); +} + +//---------------------------------------------------------------------------- +Matrix3 Matrix3::fromEulerAnglesYXZ( + float fYAngle, + float fPAngle, + float fRAngle) { + + float fCos, fSin; + + fCos = cos(fYAngle); + fSin = sin(fYAngle); + Matrix3 kYMat(fCos, 0.0f, fSin, 0.0f, 1.0f, 0.0f, -fSin, 0.0f, fCos); + + fCos = cos(fPAngle); + fSin = sin(fPAngle); + Matrix3 kXMat(1.0f, 0.0f, 0.0f, 0.0f, fCos, -fSin, 0.0f, fSin, fCos); + + fCos = cos(fRAngle); + fSin = sin(fRAngle); + Matrix3 kZMat(fCos, -fSin, 0.0f, fSin, fCos, 0.0f, 0.0f, 0.0f, 1.0f); + + return kYMat * (kXMat * kZMat); +} + +//---------------------------------------------------------------------------- +Matrix3 Matrix3::fromEulerAnglesYZX( + float fYAngle, + float fPAngle, + float fRAngle) { + + float fCos, fSin; + + fCos = cos(fYAngle); + fSin = sin(fYAngle); + Matrix3 kYMat(fCos, 0.0f, fSin, 0.0f, 1.0f, 0.0f, -fSin, 0.0f, fCos); + + fCos = cos(fPAngle); + fSin = sin(fPAngle); + Matrix3 kZMat(fCos, -fSin, 0.0f, fSin, fCos, 0.0f, 0.0f, 0.0f, 1.0f); + + fCos = cos(fRAngle); + fSin = sin(fRAngle); + Matrix3 kXMat(1.0f, 0.0f, 0.0f, 0.0f, fCos, -fSin, 0.0f, fSin, fCos); + + return kYMat * (kZMat * kXMat); +} + +//---------------------------------------------------------------------------- +Matrix3 Matrix3::fromEulerAnglesZXY (float fYAngle, float fPAngle, + float fRAngle) { + float fCos, fSin; + + fCos = cos(fYAngle); + fSin = sin(fYAngle); + Matrix3 kZMat(fCos, -fSin, 0.0, fSin, fCos, 0.0, 0.0, 0.0, 1.0); + + fCos = cos(fPAngle); + fSin = sin(fPAngle); + Matrix3 kXMat(1.0, 0.0, 0.0, 0.0, fCos, -fSin, 0.0, fSin, fCos); + + fCos = cos(fRAngle); + fSin = sin(fRAngle); + Matrix3 kYMat(fCos, 0.0, fSin, 0.0, 1.0, 0.0, -fSin, 0.0, fCos); + + return kZMat * (kXMat * kYMat); +} + +//---------------------------------------------------------------------------- +Matrix3 Matrix3::fromEulerAnglesZYX (float fYAngle, float fPAngle, + float fRAngle) { + float fCos, fSin; + + fCos = cos(fYAngle); + fSin = sin(fYAngle); + Matrix3 kZMat(fCos, -fSin, 0.0, fSin, fCos, 0.0, 0.0, 0.0, 1.0); + + fCos = cos(fPAngle); + fSin = sin(fPAngle); + Matrix3 kYMat(fCos, 0.0, fSin, 0.0, 1.0, 0.0, -fSin, 0.0, fCos); + + fCos = cos(fRAngle); + fSin = sin(fRAngle); + Matrix3 kXMat(1.0, 0.0, 0.0, 0.0, fCos, -fSin, 0.0, fSin, fCos); + + return kZMat * (kYMat * kXMat); +} + +//---------------------------------------------------------------------------- +void Matrix3::tridiagonal (float afDiag[3], float afSubDiag[3]) { + // Householder reduction T = Q^t M Q + // Input: + // mat, symmetric 3x3 matrix M + // Output: + // mat, orthogonal matrix Q + // diag, diagonal entries of T + // subd, subdiagonal entries of T (T is symmetric) + + float fA = elt[0][0]; + float fB = elt[0][1]; + float fC = elt[0][2]; + float fD = elt[1][1]; + float fE = elt[1][2]; + float fF = elt[2][2]; + + afDiag[0] = fA; + afSubDiag[2] = 0.0; + + if ( G3D::abs(fC) >= EPSILON ) { + float fLength = sqrt(fB * fB + fC * fC); + float fInvLength = 1.0 / fLength; + fB *= fInvLength; + fC *= fInvLength; + float fQ = 2.0 * fB * fE + fC * (fF - fD); + afDiag[1] = fD + fC * fQ; + afDiag[2] = fF - fC * fQ; + afSubDiag[0] = fLength; + afSubDiag[1] = fE - fB * fQ; + elt[0][0] = 1.0; + elt[0][1] = 0.0; + elt[0][2] = 0.0; + elt[1][0] = 0.0; + elt[1][1] = fB; + elt[1][2] = fC; + elt[2][0] = 0.0; + elt[2][1] = fC; + elt[2][2] = -fB; + } else { + afDiag[1] = fD; + afDiag[2] = fF; + afSubDiag[0] = fB; + afSubDiag[1] = fE; + elt[0][0] = 1.0; + elt[0][1] = 0.0; + elt[0][2] = 0.0; + elt[1][0] = 0.0; + elt[1][1] = 1.0; + elt[1][2] = 0.0; + elt[2][0] = 0.0; + elt[2][1] = 0.0; + elt[2][2] = 1.0; + } +} + +//---------------------------------------------------------------------------- +bool Matrix3::qLAlgorithm (float afDiag[3], float afSubDiag[3]) { + // QL iteration with implicit shifting to reduce matrix from tridiagonal + // to diagonal + + for (int i0 = 0; i0 < 3; i0++) { + const int iMaxIter = 32; + int iIter; + + for (iIter = 0; iIter < iMaxIter; iIter++) { + int i1; + + for (i1 = i0; i1 <= 1; i1++) { + float fSum = G3D::abs(afDiag[i1]) + + G3D::abs(afDiag[i1 + 1]); + + if ( G3D::abs(afSubDiag[i1]) + fSum == fSum ) + break; + } + + if ( i1 == i0 ) + break; + + float fTmp0 = (afDiag[i0 + 1] - afDiag[i0]) / (2.0 * afSubDiag[i0]); + + float fTmp1 = sqrt(fTmp0 * fTmp0 + 1.0); + + if ( fTmp0 < 0.0 ) + fTmp0 = afDiag[i1] - afDiag[i0] + afSubDiag[i0] / (fTmp0 - fTmp1); + else + fTmp0 = afDiag[i1] - afDiag[i0] + afSubDiag[i0] / (fTmp0 + fTmp1); + + float fSin = 1.0; + + float fCos = 1.0; + + float fTmp2 = 0.0; + + for (int i2 = i1 - 1; i2 >= i0; i2--) { + float fTmp3 = fSin * afSubDiag[i2]; + float fTmp4 = fCos * afSubDiag[i2]; + + if (G3D::abs(fTmp3) >= G3D::abs(fTmp0)) { + fCos = fTmp0 / fTmp3; + fTmp1 = sqrt(fCos * fCos + 1.0); + afSubDiag[i2 + 1] = fTmp3 * fTmp1; + fSin = 1.0 / fTmp1; + fCos *= fSin; + } else { + fSin = fTmp3 / fTmp0; + fTmp1 = sqrt(fSin * fSin + 1.0); + afSubDiag[i2 + 1] = fTmp0 * fTmp1; + fCos = 1.0 / fTmp1; + fSin *= fCos; + } + + fTmp0 = afDiag[i2 + 1] - fTmp2; + fTmp1 = (afDiag[i2] - fTmp0) * fSin + 2.0 * fTmp4 * fCos; + fTmp2 = fSin * fTmp1; + afDiag[i2 + 1] = fTmp0 + fTmp2; + fTmp0 = fCos * fTmp1 - fTmp4; + + for (int iRow = 0; iRow < 3; iRow++) { + fTmp3 = elt[iRow][i2 + 1]; + elt[iRow][i2 + 1] = fSin * elt[iRow][i2] + + fCos * fTmp3; + elt[iRow][i2] = fCos * elt[iRow][i2] - + fSin * fTmp3; + } + } + + afDiag[i0] -= fTmp2; + afSubDiag[i0] = fTmp0; + afSubDiag[i1] = 0.0; + } + + if ( iIter == iMaxIter ) { + // should not get here under normal circumstances + return false; + } + } + + return true; +} + +//---------------------------------------------------------------------------- +void Matrix3::eigenSolveSymmetric (float afEigenvalue[3], + Vector3 akEigenvector[3]) const { + Matrix3 kMatrix = *this; + float afSubDiag[3]; + kMatrix.tridiagonal(afEigenvalue, afSubDiag); + kMatrix.qLAlgorithm(afEigenvalue, afSubDiag); + + for (int i = 0; i < 3; i++) { + akEigenvector[i][0] = kMatrix[0][i]; + akEigenvector[i][1] = kMatrix[1][i]; + akEigenvector[i][2] = kMatrix[2][i]; + } + + // make eigenvectors form a right--handed system + Vector3 kCross = akEigenvector[1].cross(akEigenvector[2]); + + float fDet = akEigenvector[0].dot(kCross); + + if ( fDet < 0.0 ) { + akEigenvector[2][0] = - akEigenvector[2][0]; + akEigenvector[2][1] = - akEigenvector[2][1]; + akEigenvector[2][2] = - akEigenvector[2][2]; + } +} + +//---------------------------------------------------------------------------- +void Matrix3::tensorProduct (const Vector3& rkU, const Vector3& rkV, + Matrix3& rkProduct) { + for (int iRow = 0; iRow < 3; iRow++) { + for (int iCol = 0; iCol < 3; iCol++) { + rkProduct[iRow][iCol] = rkU[iRow] * rkV[iCol]; + } + } +} + +//---------------------------------------------------------------------------- + +// Runs in 52 cycles on AMD, 76 cycles on Intel Centrino +// +// The loop unrolling is necessary for performance. +// I was unable to improve performance further by flattening the matrices +// into float*'s instead of 2D arrays. +// +// -morgan +void Matrix3::_mul(const Matrix3& A, const Matrix3& B, Matrix3& out) { + const float* ARowPtr = A.elt[0]; + float* outRowPtr = out.elt[0]; + outRowPtr[0] = + ARowPtr[0] * B.elt[0][0] + + ARowPtr[1] * B.elt[1][0] + + ARowPtr[2] * B.elt[2][0]; + outRowPtr[1] = + ARowPtr[0] * B.elt[0][1] + + ARowPtr[1] * B.elt[1][1] + + ARowPtr[2] * B.elt[2][1]; + outRowPtr[2] = + ARowPtr[0] * B.elt[0][2] + + ARowPtr[1] * B.elt[1][2] + + ARowPtr[2] * B.elt[2][2]; + + ARowPtr = A.elt[1]; + outRowPtr = out.elt[1]; + + outRowPtr[0] = + ARowPtr[0] * B.elt[0][0] + + ARowPtr[1] * B.elt[1][0] + + ARowPtr[2] * B.elt[2][0]; + outRowPtr[1] = + ARowPtr[0] * B.elt[0][1] + + ARowPtr[1] * B.elt[1][1] + + ARowPtr[2] * B.elt[2][1]; + outRowPtr[2] = + ARowPtr[0] * B.elt[0][2] + + ARowPtr[1] * B.elt[1][2] + + ARowPtr[2] * B.elt[2][2]; + + ARowPtr = A.elt[2]; + outRowPtr = out.elt[2]; + + outRowPtr[0] = + ARowPtr[0] * B.elt[0][0] + + ARowPtr[1] * B.elt[1][0] + + ARowPtr[2] * B.elt[2][0]; + outRowPtr[1] = + ARowPtr[0] * B.elt[0][1] + + ARowPtr[1] * B.elt[1][1] + + ARowPtr[2] * B.elt[2][1]; + outRowPtr[2] = + ARowPtr[0] * B.elt[0][2] + + ARowPtr[1] * B.elt[1][2] + + ARowPtr[2] * B.elt[2][2]; +} + +//---------------------------------------------------------------------------- +void Matrix3::_transpose(const Matrix3& A, Matrix3& out) { + out[0][0] = A.elt[0][0]; + out[0][1] = A.elt[1][0]; + out[0][2] = A.elt[2][0]; + out[1][0] = A.elt[0][1]; + out[1][1] = A.elt[1][1]; + out[1][2] = A.elt[2][1]; + out[2][0] = A.elt[0][2]; + out[2][1] = A.elt[1][2]; + out[2][2] = A.elt[2][2]; +} + +//----------------------------------------------------------------------------- +std::string Matrix3::toString() const { + return G3D::format("[%g, %g, %g; %g, %g, %g; %g, %g, %g]", + elt[0][0], elt[0][1], elt[0][2], + elt[1][0], elt[1][1], elt[1][2], + elt[2][0], elt[2][1], elt[2][2]); +} + + + +} // namespace + diff --git a/dep/src/g3dlite/Plane.cpp b/dep/src/g3dlite/Plane.cpp new file mode 100644 index 00000000000..c958a10a710 --- /dev/null +++ b/dep/src/g3dlite/Plane.cpp @@ -0,0 +1,131 @@ +/** + @file Plane.cpp + + @maintainer Morgan McGuire, matrix@graphics3d.com + + @created 2003-02-06 + @edited 2006-01-29 + */ + +#include "G3D/platform.h" +#include "G3D/format.h" +#include "G3D/Plane.h" +#include "G3D/stringutils.h" + +namespace G3D { + +Plane::Plane( + Vector4 point0, + Vector4 point1, + Vector4 point2) { + + debugAssertM( + point0.w != 0 || + point1.w != 0 || + point2.w != 0, + "At least one point must be finite."); + + // Rotate the points around so that the finite points come first. + + while ((point0.w == 0) && + ((point1.w == 0) || (point2.w != 0))) { + Vector4 temp = point0; + point0 = point1; + point1 = point2; + point2 = temp; + } + + Vector3 dir1; + Vector3 dir2; + + if (point1.w == 0) { + // 1 finite, 2 infinite points; the plane must contain + // the direction of the two direcitons + dir1 = point1.xyz(); + dir2 = point2.xyz(); + } else if (point2.w != 0) { + // 3 finite points, the plane must contain the directions + // betwseen the points. + dir1 = point1.xyz() - point0.xyz(); + dir2 = point2.xyz() - point0.xyz(); + } else { + // 2 finite, 1 infinite point; the plane must contain + // the direction between the first two points and the + // direction of the third point. + dir1 = point1.xyz() - point0.xyz(); + dir2 = point2.xyz(); + } + + _normal = dir1.cross(dir2).direction(); + _distance = _normal.dot(point0.xyz()); +} + + +Plane::Plane( + const Vector3& point0, + const Vector3& point1, + const Vector3& point2) { + + _normal = (point1 - point0).cross(point2 - point0).direction(); + _distance = _normal.dot(point0); +} + + +Plane::Plane( + const Vector3& __normal, + const Vector3& point) { + + _normal = __normal.direction(); + _distance = _normal.dot(point); +} + + +Plane Plane::fromEquation(float a, float b, float c, float d) { + Vector3 n(a, b, c); + float magnitude = n.magnitude(); + d /= magnitude; + n /= magnitude; + return Plane(n, -d); +} + + +void Plane::flip() { + _normal = -_normal; + _distance = -_distance; +} + + +void Plane::getEquation(Vector3& n, float& d) const { + double _d; + getEquation(n, _d); + d = (float)_d; +} + +void Plane::getEquation(Vector3& n, double& d) const { + n = _normal; + d = -_distance; +} + + +void Plane::getEquation(float& a, float& b, float& c, float& d) const { + double _a, _b, _c, _d; + getEquation(_a, _b, _c, _d); + a = (float)_a; + b = (float)_b; + c = (float)_c; + d = (float)_d; +} + +void Plane::getEquation(double& a, double& b, double& c, double& d) const { + a = _normal.x; + b = _normal.y; + c = _normal.z; + d = -_distance; +} + + +std::string Plane::toString() const { + return format("Plane(%g, %g, %g, %g)", _normal.x, _normal.y, _normal.z, _distance); +} + +} diff --git a/dep/src/g3dlite/System.cpp b/dep/src/g3dlite/System.cpp new file mode 100644 index 00000000000..06be7cd25e0 --- /dev/null +++ b/dep/src/g3dlite/System.cpp @@ -0,0 +1,666 @@ +/** + @file System.cpp + + @maintainer Morgan McGuire, matrix@graphics3d.com + + Note: every routine must call init() first. + + There are two kinds of detection used in this file. At compile + time, the _MSC_VER #define is used to determine whether x86 assembly + can be used at all. At runtime, processor detection is used to + determine if we can safely call the routines that use that assembly. + + @cite Rob Wyatt http://www.gamasutra.com/features/wyatts_world/19990709/processor_detection_01.htm + @cite Benjamin Jurke http://www.flipcode.com/cgi-bin/msg.cgi?showThread=COTD-ProcessorDetectionClass&forum=cotd&id=-1 + @cite Michael Herf http://www.stereopsis.com/memcpy.html + + @created 2003-01-25 + @edited 2006-05-17 + */ + +#include "G3D/platform.h" +#include "G3D/System.h" +#include "G3D/debug.h" +#include "G3D/format.h" + +#ifdef G3D_WIN32 + + #include + #include + #include "G3D/RegistryUtil.h" + +#elif defined(G3D_LINUX) + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + // #include + +#elif defined(G3D_OSX) + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #include + #include +#endif + +#if defined(SSE) + #include +#endif + +namespace G3D { + +static char versionCstr[1024]; +System::OutOfMemoryCallback System::outOfMemoryCallback = NULL; + + +void System::init() { + // Cannot use most G3D data structures or utility functions in here because + // they are not initialized. + + static bool initialized = false; + + if (initialized) { + return; + } + + initialized = true; + + if ((G3D_VER % 100) != 0) { + sprintf(versionCstr, "G3D %d.%02d beta %d", + G3D_VER / 10000, + (G3D_VER / 100) % 100, + G3D_VER % 100); + } else { + sprintf(versionCstr, "G3D %d.%02d", + G3D_VER / 10000, + (G3D_VER / 100) % 100); + } + +} + + + +void System::memcpy(void* dst, const void* src, size_t numBytes) { + ::memcpy(dst, src, numBytes); +} + + +void System::memset(void* dst, uint8 value, size_t numBytes) { + ::memset(dst, value, numBytes); +} + + + + + +//////////////////////////////////////////////////////////////// +class BufferPool { +public: + + /** Only store buffers up to these sizes (in bytes) in each pool-> + Different pools have different management strategies. + + A large block is preallocated for tiny buffers; they are used with + tremendous frequency. Other buffers are allocated as demanded. + */ + enum {tinyBufferSize = 128, smallBufferSize = 1024, medBufferSize = 4096}; + + /** + Most buffers we're allowed to store. + 64000 * 128 = 8 MB (preallocated) + 1024 * 1024 = 1 MB (allocated on demand) + 1024 * 4096 = 4 MB (allocated on demand) + */ + enum {maxTinyBuffers = 64000, maxSmallBuffers = 1024, maxMedBuffers = 1024}; + +private: + + class MemBlock { + public: + void* ptr; + size_t bytes; + + inline MemBlock() : ptr(NULL), bytes(0) {} + inline MemBlock(void* p, size_t b) : ptr(p), bytes(b) {} + }; + + MemBlock smallPool[maxSmallBuffers]; + int smallPoolSize; + + MemBlock medPool[maxMedBuffers]; + int medPoolSize; + + /** The tiny pool is a single block of storage into which all tiny + objects are allocated. This provides better locality for + small objects and avoids the search time, since all tiny + blocks are exactly the same size. */ + void* tinyPool[maxTinyBuffers]; + int tinyPoolSize; + + /** Pointer to the data in the tiny pool */ + void* tinyHeap; + +# ifdef G3D_WIN32 + CRITICAL_SECTION mutex; +# else + pthread_mutex_t mutex; +# endif + + /** Provide synchronization between threads */ + void lock() { +# ifdef G3D_WIN32 + EnterCriticalSection(&mutex); +# else + pthread_mutex_lock(&mutex); +# endif + } + + void unlock() { +# ifdef G3D_WIN32 + LeaveCriticalSection(&mutex); +# else + pthread_mutex_unlock(&mutex); +# endif + } + + /** + Malloc out of the tiny heap. + */ + inline void* tinyMalloc(size_t bytes) { + // Note that we ignore the actual byte size + // and create a constant size block. + (void)bytes; + debugAssert(tinyBufferSize >= bytes); + + void* ptr = NULL; + + if (tinyPoolSize > 0) { + --tinyPoolSize; + // Return the last one + ptr = tinyPool[tinyPoolSize]; + } + + return ptr; + } + + /** Returns true if this is a pointer into the tiny heap. */ + bool inTinyHeap(void* ptr) { + return (ptr >= tinyHeap) && + (ptr < (uint8*)tinyHeap + maxTinyBuffers * tinyBufferSize); + } + + void tinyFree(void* ptr) { + debugAssert(tinyPoolSize < maxTinyBuffers); + + // Put the pointer back into the free list + tinyPool[tinyPoolSize] = ptr; + ++tinyPoolSize; + + } + + void flushPool(MemBlock* pool, int& poolSize) { + for (int i = 0; i < poolSize; ++i) { + ::free(pool->ptr); + pool->ptr = NULL; + pool->bytes = 0; + } + poolSize = 0; + } + + + /** Allocate out of a specific pool-> Return NULL if no suitable + memory was found. + + */ + void* malloc(MemBlock* pool, int& poolSize, size_t bytes) { + + // OPT: find the smallest block that satisfies the request. + + // See if there's something we can use in the buffer pool-> + // Search backwards since usually we'll re-use the last one. + for (int i = (int)poolSize - 1; i >= 0; --i) { + if (pool[i].bytes >= bytes) { + // We found a suitable entry in the pool-> + + // No need to offset the pointer; it is already offset + void* ptr = pool[i].ptr; + + // Remove this element from the pool + --poolSize; + pool[i] = pool[poolSize]; + + return ptr; + } + } + + return NULL; + } + +public: + + /** Count of memory allocations that have occurred. */ + int totalMallocs; + int mallocsFromTinyPool; + int mallocsFromSmallPool; + int mallocsFromMedPool; + + /** Amount of memory currently allocated (according to the application). + This does not count the memory still remaining in the buffer pool, + but does count extra memory required for rounding off to the size + of a buffer. + Primarily useful for detecting leaks.*/ + // TODO: make me an atomic int! + int bytesAllocated; + + BufferPool() { + totalMallocs = 0; + + mallocsFromTinyPool = 0; + mallocsFromSmallPool = 0; + mallocsFromMedPool = 0; + + bytesAllocated = true; + + tinyPoolSize = 0; + tinyHeap = NULL; + + smallPoolSize = 0; + + medPoolSize = 0; + + + // Initialize the tiny heap as a bunch of pointers into one + // pre-allocated buffer. + tinyHeap = ::malloc(maxTinyBuffers * tinyBufferSize); + for (int i = 0; i < maxTinyBuffers; ++i) { + tinyPool[i] = (uint8*)tinyHeap + (tinyBufferSize * i); + } + tinyPoolSize = maxTinyBuffers; + +# ifdef G3D_WIN32 + InitializeCriticalSection(&mutex); +# else + pthread_mutex_init(&mutex, NULL); +# endif + } + + + ~BufferPool() { + ::free(tinyHeap); +# ifdef G3D_WIN32 + DeleteCriticalSection(&mutex); +# else + // No destruction on pthreads +# endif + } + + + void* realloc(void* ptr, size_t bytes) { + if (ptr == NULL) { + return malloc(bytes); + } + + if (inTinyHeap(ptr)) { + if (bytes <= tinyBufferSize) { + // The old pointer actually had enough space. + return ptr; + } else { + // Free the old pointer and malloc + + void* newPtr = malloc(bytes); + System::memcpy(newPtr, ptr, tinyBufferSize); + tinyFree(ptr); + return newPtr; + + } + } else { + // In one of our heaps. + + // See how big the block really was + size_t realSize = ((uint32*)ptr)[-1]; + if (bytes <= realSize) { + // The old block was big enough. + return ptr; + } + + // Need to reallocate + void* newPtr = malloc(bytes); + System::memcpy(newPtr, ptr, realSize); + free(ptr); + return newPtr; + } + } + + + void* malloc(size_t bytes) { + lock(); + ++totalMallocs; + + if (bytes <= tinyBufferSize) { + + void* ptr = tinyMalloc(bytes); + + if (ptr) { + ++mallocsFromTinyPool; + unlock(); + return ptr; + } + + } + + // Failure to allocate a tiny buffer is allowed to flow + // through to a small buffer + if (bytes <= smallBufferSize) { + + void* ptr = malloc(smallPool, smallPoolSize, bytes); + + if (ptr) { + ++mallocsFromSmallPool; + unlock(); + return ptr; + } + + } else if (bytes <= medBufferSize) { + // Note that a small allocation failure does *not* fall + // through into a medium allocation because that would + // waste the medium buffer's resources. + + void* ptr = malloc(medPool, medPoolSize, bytes); + + if (ptr) { + ++mallocsFromMedPool; + unlock(); + return ptr; + } + } + + bytesAllocated += 4 + (int) bytes; + unlock(); + + // Heap allocate + + // Allocate 4 extra bytes for our size header (unfortunate, + // since malloc already added its own header). + void* ptr = ::malloc(bytes + 4); + + if (ptr == NULL) { + // Flush memory pools to try and recover space + flushPool(smallPool, smallPoolSize); + flushPool(medPool, medPoolSize); + ptr = ::malloc(bytes + 4); + } + + + if (ptr == NULL) { + if ((System::outOfMemoryCallback != NULL) && + (System::outOfMemoryCallback(bytes + 4, true) == true)) { + // Re-attempt the malloc + ptr = ::malloc(bytes + 4); + } + } + + if (ptr == NULL) { + if (System::outOfMemoryCallback != NULL) { + // Notify the application + System::outOfMemoryCallback(bytes + 4, false); + } + return NULL; + } + + *(uint32*)ptr = (uint32)bytes; + + return (uint8*)ptr + 4; + } + + + void free(void* ptr) { + if (ptr == NULL) { + // Free does nothing on null pointers + return; + } + + debugAssert(isValidPointer(ptr)); + + if (inTinyHeap(ptr)) { + lock(); + tinyFree(ptr); + unlock(); + return; + } + + uint32 bytes = ((uint32*)ptr)[-1]; + + lock(); + if (bytes <= smallBufferSize) { + if (smallPoolSize < maxSmallBuffers) { + smallPool[smallPoolSize] = MemBlock(ptr, bytes); + ++smallPoolSize; + unlock(); + return; + } + } else if (bytes <= medBufferSize) { + if (medPoolSize < maxMedBuffers) { + medPool[medPoolSize] = MemBlock(ptr, bytes); + ++medPoolSize; + unlock(); + return; + } + } + bytesAllocated -= bytes + 4; + unlock(); + + // Free; the buffer pools are full or this is too big to store. + ::free((uint8*)ptr - 4); + } + + std::string performance() const { + if (totalMallocs > 0) { + int pooled = mallocsFromTinyPool + + mallocsFromSmallPool + + mallocsFromMedPool; + + int total = totalMallocs; + + return format("malloc performance: %5.1f%% <= %db, %5.1f%% <= %db, " + "%5.1f%% <= %db, %5.1f%% > %db", + 100.0 * mallocsFromTinyPool / total, + BufferPool::tinyBufferSize, + 100.0 * mallocsFromSmallPool / total, + BufferPool::smallBufferSize, + 100.0 * mallocsFromMedPool / total, + BufferPool::medBufferSize, + 100.0 * (1.0 - (double)pooled / total), + BufferPool::medBufferSize); + } else { + return "No System::malloc calls made yet."; + } + } + + std::string status() const { + return format("preallocated shared buffers: %5d/%d x %db", + maxTinyBuffers - tinyPoolSize, maxTinyBuffers, tinyBufferSize); + } +}; + +// Dynamically allocated because we need to ensure that +// the buffer pool is still around when the last global variable +// is deallocated. +static BufferPool* bufferpool = NULL; + +std::string System::mallocPerformance() { +#ifndef NO_BUFFERPOOL + return bufferpool->performance(); +#else + return "NO_BUFFERPOOL"; +#endif +} + +std::string System::mallocStatus() { +#ifndef NO_BUFFERPOOL + return bufferpool->status(); +#else + return "NO_BUFFERPOOL"; +#endif +} + + +void System::resetMallocPerformanceCounters() { +#ifndef NO_BUFFERPOOL + bufferpool->totalMallocs = 0; + bufferpool->mallocsFromMedPool = 0; + bufferpool->mallocsFromSmallPool = 0; + bufferpool->mallocsFromTinyPool = 0; +#endif +} + + +#ifndef NO_BUFFERPOOL +inline void initMem() { + // Putting the test here ensures that the system is always + // initialized, even when globals are being allocated. + static bool initialized = false; + if (! initialized) { + bufferpool = new BufferPool(); + initialized = true; + } +} +#endif + + +void* System::malloc(size_t bytes) { +#ifndef NO_BUFFERPOOL + initMem(); + return bufferpool->malloc(bytes); +#else + return ::malloc(bytes); +#endif +} + +void* System::calloc(size_t n, size_t x) { +#ifndef NO_BUFFERPOOL + void* b = System::malloc(n * x); + System::memset(b, 0, n * x); + return b; +#else + return ::calloc(n, x); +#endif +} + + +void* System::realloc(void* block, size_t bytes) { +#ifndef NO_BUFFERPOOL + initMem(); + return bufferpool->realloc(block, bytes); +#else + return ::realloc(block, bytes); +#endif +} + + +void System::free(void* p) { +#ifndef NO_BUFFERPOOL + bufferpool->free(p); +#else + return ::free(p); +#endif +} + + +void* System::alignedMalloc(size_t bytes, size_t alignment) { + alwaysAssertM(isPow2(alignment), "alignment must be a power of 2"); + + // We must align to at least a word boundary. + alignment = iMax((int)alignment, sizeof(void *)); + + // Pad the allocation size with the alignment size and the + // size of the redirect pointer. + size_t totalBytes = bytes + alignment + sizeof(intptr_t); + + void* truePtr = System::malloc(totalBytes); + + if (!truePtr) { + // malloc returned NULL + return NULL; + } + + debugAssert(isValidHeapPointer(truePtr)); + #ifdef G3D_WIN32 + // The blocks we return will not be valid Win32 debug heap + // pointers because they are offset + // debugAssert(_CrtIsValidPointer(truePtr, totalBytes, TRUE) ); + #endif + + // The return pointer will be the next aligned location (we must at least + // leave space for the redirect pointer, however). + char* alignedPtr = ((char*)truePtr)+ sizeof(intptr_t); + +#if 0 + // 2^n - 1 has the form 1111... in binary. + uint32 bitMask = (alignment - 1); + + // Advance forward until we reach an aligned location. + while ((((intptr_t)alignedPtr) & bitMask) != 0) { + alignedPtr += sizeof(void*); + } +#else + alignedPtr += alignment - (((intptr_t)alignedPtr) & (alignment - 1)); + // assert((alignedPtr - truePtr) + bytes <= totalBytes); +#endif + + debugAssert((alignedPtr - truePtr) + bytes <= totalBytes); + + // Immediately before the aligned location, write the true array location + // so that we can free it correctly. + intptr_t* redirectPtr = (intptr_t*)(alignedPtr - sizeof(intptr_t)); + redirectPtr[0] = (intptr_t)truePtr; + + debugAssert(isValidHeapPointer(truePtr)); + + #ifdef G3D_WIN32 + debugAssert( _CrtIsValidPointer(alignedPtr, bytes, TRUE) ); + #endif + return (void*)alignedPtr; +} + + +void System::alignedFree(void* _ptr) { + if (_ptr == NULL) { + return; + } + + char* alignedPtr = (char*)_ptr; + + // Back up one word from the pointer the user passed in. + // We now have a pointer to a pointer to the true start + // of the memory block. + intptr_t* redirectPtr = (intptr_t*)(alignedPtr - sizeof(intptr_t)); + + // Dereference that pointer so that ptr = true start + void* truePtr = (void*)(redirectPtr[0]); + + debugAssert(isValidHeapPointer(truePtr)); + System::free(truePtr); +} + + +} // namespace diff --git a/dep/src/g3dlite/Triangle.cpp b/dep/src/g3dlite/Triangle.cpp new file mode 100644 index 00000000000..adb815e1602 --- /dev/null +++ b/dep/src/g3dlite/Triangle.cpp @@ -0,0 +1,112 @@ +/** + @file Triangle.cpp + + @maintainer Morgan McGuire, graphics3d.com + + @created 2001-04-06 + @edited 2006-01-20 + + Copyright 2000-2006, Morgan McGuire. + All rights reserved. + */ + +#include "G3D/platform.h" +#include "G3D/Triangle.h" +#include "G3D/Plane.h" +#include "G3D/AABox.h" + +namespace G3D { + + +void Triangle::init(const Vector3& v0, const Vector3& v1, const Vector3& v2) { + + _plane = Plane(v0, v1, v2); + _vertex[0] = v0; + _vertex[1] = v1; + _vertex[2] = v2; + + static int next[] = {1,2,0}; + + for (int i = 0; i < 3; ++i) { + const Vector3 e = _vertex[next[i]] - _vertex[i]; + edgeMagnitude[i] = e.magnitude(); + + if (edgeMagnitude[i] == 0) { + edgeDirection[i] = Vector3::zero(); + } else { + edgeDirection[i] = e / (float)edgeMagnitude[i]; + } + } + + edge01 = _vertex[1] - _vertex[0]; + edge02 = _vertex[2] - _vertex[0]; + + _primaryAxis = _plane.normal().primaryAxis(); + _area = (float)edgeDirection[0].cross(edgeDirection[2]).magnitude() * (edgeMagnitude[0] * edgeMagnitude[2]); + +} + + +Triangle::Triangle() { + init(Vector3::zero(), Vector3::zero(), Vector3::zero()); +} + + +Triangle::Triangle(const Vector3& v0, const Vector3& v1, const Vector3& v2) { + init(v0, v1, v2); +} + + +Triangle::~Triangle() { +} + + +double Triangle::area() const { + return _area; +} + + +const Vector3& Triangle::normal() const { + return _plane.normal(); +} + + +const Plane& Triangle::plane() const { + return _plane; +} + + +Vector3 Triangle::center() const { + return (_vertex[0] + _vertex[1] + _vertex[2]) / 3.0; +} + +Vector3 Triangle::randomPoint() const { + // Choose a random point in the parallelogram + + float s = uniformRandom(); + float t = uniformRandom(); + + if (t > 1.0f - s) { + // Outside the triangle; reflect about the + // diagonal of the parallelogram + t = 1.0f - t; + s = 1.0f - s; + } + + return edge01 * s + edge02 * t + _vertex[0]; +} + + +void Triangle::getBounds(AABox& out) const { + Vector3 lo = _vertex[0]; + Vector3 hi = lo; + + for (int i = 1; i < 3; ++i) { + lo = lo.min(_vertex[i]); + hi = hi.max(_vertex[i]); + } + + out = AABox(lo, hi); +} + +} // G3D diff --git a/dep/src/g3dlite/Vector3.cpp b/dep/src/g3dlite/Vector3.cpp new file mode 100644 index 00000000000..57ee76d1eb1 --- /dev/null +++ b/dep/src/g3dlite/Vector3.cpp @@ -0,0 +1,443 @@ +/** + @file Vector3.cpp + + 3D vector class + + @maintainer Morgan McGuire, matrix@graphics3d.com + + @cite Portions based on Dave Eberly's Magic Software Library at http://www.magic-software.com + + @created 2001-06-02 + @edited 2006-01-30 + */ + +#include +#include +#include "G3D/Vector3.h" +#include "G3D/g3dmath.h" +#include "G3D/format.h" +#include "G3D/stringutils.h" +#include "G3D/Vector3int16.h" +#include "G3D/Matrix3.h" +#include "G3D/Vector2.h" + +namespace G3D { + +Vector3 Vector3::dummy; + +// Deprecated. +const Vector3 Vector3::ZERO(0, 0, 0); +const Vector3 Vector3::ZERO3(0, 0, 0); +const Vector3 Vector3::UNIT_X(1, 0, 0); +const Vector3 Vector3::UNIT_Y(0, 1, 0); +const Vector3 Vector3::UNIT_Z(0, 0, 1); +const Vector3 Vector3::INF3((float)G3D::inf(), (float)G3D::inf(), (float)G3D::inf()); +const Vector3 Vector3::NAN3((float)G3D::nan(), (float)G3D::nan(), (float)G3D::nan()); + +Vector3::Vector3(const class Vector2& v, float _z) : x(v.x), y(v.y), z(_z) { +} + +Vector3::Axis Vector3::primaryAxis() const { + + Axis a = X_AXIS; + + double nx = abs(x); + double ny = abs(y); + double nz = abs(z); + + if (nx > ny) { + if (nx > nz) { + a = X_AXIS; + } else { + a = Z_AXIS; + } + } else { + if (ny > nz) { + a = Y_AXIS; + } else { + a = Z_AXIS; + } + } + + return a; +} + + +unsigned int Vector3::hashCode() const { + unsigned int xhash = (*(int*)(void*)(&x)); + unsigned int yhash = (*(int*)(void*)(&y)); + unsigned int zhash = (*(int*)(void*)(&z)); + + return xhash + (yhash * 37) + (zhash * 101); +} + +std::ostream& operator<<(std::ostream& os, const Vector3& v) { + return os << v.toString(); +} + + +//---------------------------------------------------------------------------- + +double frand() { + return rand() / (double) RAND_MAX; +} + + +Vector3::Vector3(const class Vector3int16& v) { + x = v.x; + y = v.y; + z = v.z; +} + + +Vector3 Vector3::random() { + Vector3 result; + + do { + result = Vector3(uniformRandom(-1.0, 1.0), + uniformRandom(-1.0, 1.0), + uniformRandom(-1.0, 1.0)); + } while (result.squaredMagnitude() >= 1.0f); + + result.unitize(); + + return result; +} + +//---------------------------------------------------------------------------- +Vector3 Vector3::operator/ (float fScalar) const { + Vector3 kQuot; + + if ( fScalar != 0.0 ) { + float fInvScalar = 1.0f / fScalar; + kQuot.x = fInvScalar * x; + kQuot.y = fInvScalar * y; + kQuot.z = fInvScalar * z; + return kQuot; + } else { + return Vector3::inf(); + } +} + +//---------------------------------------------------------------------------- +Vector3& Vector3::operator/= (float fScalar) { + if (fScalar != 0.0) { + float fInvScalar = 1.0f / fScalar; + x *= fInvScalar; + y *= fInvScalar; + z *= fInvScalar; + } else { + x = (float)G3D::inf(); + y = (float)G3D::inf(); + z = (float)G3D::inf(); + } + + return *this; +} + +//---------------------------------------------------------------------------- +float Vector3::unitize (float fTolerance) { + float fMagnitude = magnitude(); + + if (fMagnitude > fTolerance) { + float fInvMagnitude = 1.0f / fMagnitude; + x *= fInvMagnitude; + y *= fInvMagnitude; + z *= fInvMagnitude; + } else { + fMagnitude = 0.0f; + } + + return fMagnitude; +} + +//---------------------------------------------------------------------------- + +Vector3 Vector3::reflectAbout(const Vector3& normal) const { + + Vector3 out; + + Vector3 N = normal.direction(); + + // 2 * normal.dot(this) * normal - this + return N * 2 * this->dot(N) - *this; +} + +//---------------------------------------------------------------------------- +#if 0 +Vector3 Vector3::cosRandom(const Vector3& normal) { + double e1 = G3D::random(0, 1); + double e2 = G3D::random(0, 1); + + // Angle from normal + double theta = acos(sqrt(e1)); + + // Angle about normal + double phi = 2 * G3D_PI * e2; + + // Make a coordinate system + Vector3 U = normal.direction(); + Vector3 V = Vector3::unitX(); + + if (abs(U.dot(V)) > .9) { + V = Vector3::unitY(); + } + + Vector3 W = U.cross(V).direction(); + V = W.cross(U); + + // Convert to rectangular form + return cos(theta) * U + sin(theta) * (cos(phi) * V + sin(phi) * W); +} +//---------------------------------------------------------------------------- + +Vector3 Vector3::hemiRandom(const Vector3& normal) { + Vector3 V = Vector3::random(); + + if (V.dot(normal) < 0) { + return -V; + } else { + return V; + } +} +#endif +//---------------------------------------------------------------------------- + +Vector3 Vector3::reflectionDirection(const Vector3& normal) const { + return -reflectAbout(normal).direction(); +} + +//---------------------------------------------------------------------------- + +Vector3 Vector3::refractionDirection( + const Vector3& normal, + float iInside, + float iOutside) const { + + // From pg. 24 of Henrik Wann Jensen. Realistic Image Synthesis + // Using Photon Mapping. AK Peters. ISBN: 1568811470. July 2001. + + // Invert the directions from Wann Jensen's formulation + // and normalize the vectors. + const Vector3 W = -direction(); + Vector3 N = normal.direction(); + + float h1 = iOutside; + float h2 = iInside; + + if (normal.dot(*this) > 0.0f) { + h1 = iInside; + h2 = iOutside; + N = -N; + } + + const float hRatio = h1 / h2; + const float WdotN = W.dot(N); + + float det = 1.0f - (float)square(hRatio) * (1.0f - (float)square(WdotN)); + + if (det < 0) { + // Total internal reflection + return Vector3::zero(); + } else { + return -hRatio * (W - WdotN * N) - N * sqrt(det); + } +} + +//---------------------------------------------------------------------------- +void Vector3::orthonormalize (Vector3 akVector[3]) { + // If the input vectors are v0, v1, and v2, then the Gram-Schmidt + // orthonormalization produces vectors u0, u1, and u2 as follows, + // + // u0 = v0/|v0| + // u1 = (v1-(u0*v1)u0)/|v1-(u0*v1)u0| + // u2 = (v2-(u0*v2)u0-(u1*v2)u1)/|v2-(u0*v2)u0-(u1*v2)u1| + // + // where |A| indicates length of vector A and A*B indicates dot + // product of vectors A and B. + + // compute u0 + akVector[0].unitize(); + + // compute u1 + float fDot0 = akVector[0].dot(akVector[1]); + akVector[1] -= akVector[0] * fDot0; + akVector[1].unitize(); + + // compute u2 + float fDot1 = akVector[1].dot(akVector[2]); + fDot0 = akVector[0].dot(akVector[2]); + akVector[2] -= akVector[0] * fDot0 + akVector[1] * fDot1; + akVector[2].unitize(); +} + +//---------------------------------------------------------------------------- +void Vector3::generateOrthonormalBasis (Vector3& rkU, Vector3& rkV, + Vector3& rkW, bool bUnitLengthW) { + if ( !bUnitLengthW ) + rkW.unitize(); + + if ( G3D::abs(rkW.x) >= G3D::abs(rkW.y) + && G3D::abs(rkW.x) >= G3D::abs(rkW.z) ) { + rkU.x = -rkW.y; + rkU.y = + rkW.x; + rkU.z = 0.0; + } else { + rkU.x = 0.0; + rkU.y = + rkW.z; + rkU.z = -rkW.y; + } + + rkU.unitize(); + rkV = rkW.cross(rkU); +} + +//---------------------------------------------------------------------------- + +std::string Vector3::toString() const { + return G3D::format("(%g, %g, %g)", x, y, z); +} + + +//---------------------------------------------------------------------------- + +Matrix3 Vector3::cross() const { + return Matrix3( 0, -z, y, + z, 0, -x, + -y, x, 0); +} + + +//---------------------------------------------------------------------------- +// 2-char swizzles + +Vector2 Vector3::xx() const { return Vector2 (x, x); } +Vector2 Vector3::yx() const { return Vector2 (y, x); } +Vector2 Vector3::zx() const { return Vector2 (z, x); } +Vector2 Vector3::xy() const { return Vector2 (x, y); } +Vector2 Vector3::yy() const { return Vector2 (y, y); } +Vector2 Vector3::zy() const { return Vector2 (z, y); } +Vector2 Vector3::xz() const { return Vector2 (x, z); } +Vector2 Vector3::yz() const { return Vector2 (y, z); } +Vector2 Vector3::zz() const { return Vector2 (z, z); } + +// 3-char swizzles + +Vector3 Vector3::xxx() const { return Vector3 (x, x, x); } +Vector3 Vector3::yxx() const { return Vector3 (y, x, x); } +Vector3 Vector3::zxx() const { return Vector3 (z, x, x); } +Vector3 Vector3::xyx() const { return Vector3 (x, y, x); } +Vector3 Vector3::yyx() const { return Vector3 (y, y, x); } +Vector3 Vector3::zyx() const { return Vector3 (z, y, x); } +Vector3 Vector3::xzx() const { return Vector3 (x, z, x); } +Vector3 Vector3::yzx() const { return Vector3 (y, z, x); } +Vector3 Vector3::zzx() const { return Vector3 (z, z, x); } +Vector3 Vector3::xxy() const { return Vector3 (x, x, y); } +Vector3 Vector3::yxy() const { return Vector3 (y, x, y); } +Vector3 Vector3::zxy() const { return Vector3 (z, x, y); } +Vector3 Vector3::xyy() const { return Vector3 (x, y, y); } +Vector3 Vector3::yyy() const { return Vector3 (y, y, y); } +Vector3 Vector3::zyy() const { return Vector3 (z, y, y); } +Vector3 Vector3::xzy() const { return Vector3 (x, z, y); } +Vector3 Vector3::yzy() const { return Vector3 (y, z, y); } +Vector3 Vector3::zzy() const { return Vector3 (z, z, y); } +Vector3 Vector3::xxz() const { return Vector3 (x, x, z); } +Vector3 Vector3::yxz() const { return Vector3 (y, x, z); } +Vector3 Vector3::zxz() const { return Vector3 (z, x, z); } +Vector3 Vector3::xyz() const { return Vector3 (x, y, z); } +Vector3 Vector3::yyz() const { return Vector3 (y, y, z); } +Vector3 Vector3::zyz() const { return Vector3 (z, y, z); } +Vector3 Vector3::xzz() const { return Vector3 (x, z, z); } +Vector3 Vector3::yzz() const { return Vector3 (y, z, z); } +Vector3 Vector3::zzz() const { return Vector3 (z, z, z); } + +// 4-char swizzles + +Vector4 Vector3::xxxx() const { return Vector4 (x, x, x, x); } +Vector4 Vector3::yxxx() const { return Vector4 (y, x, x, x); } +Vector4 Vector3::zxxx() const { return Vector4 (z, x, x, x); } +Vector4 Vector3::xyxx() const { return Vector4 (x, y, x, x); } +Vector4 Vector3::yyxx() const { return Vector4 (y, y, x, x); } +Vector4 Vector3::zyxx() const { return Vector4 (z, y, x, x); } +Vector4 Vector3::xzxx() const { return Vector4 (x, z, x, x); } +Vector4 Vector3::yzxx() const { return Vector4 (y, z, x, x); } +Vector4 Vector3::zzxx() const { return Vector4 (z, z, x, x); } +Vector4 Vector3::xxyx() const { return Vector4 (x, x, y, x); } +Vector4 Vector3::yxyx() const { return Vector4 (y, x, y, x); } +Vector4 Vector3::zxyx() const { return Vector4 (z, x, y, x); } +Vector4 Vector3::xyyx() const { return Vector4 (x, y, y, x); } +Vector4 Vector3::yyyx() const { return Vector4 (y, y, y, x); } +Vector4 Vector3::zyyx() const { return Vector4 (z, y, y, x); } +Vector4 Vector3::xzyx() const { return Vector4 (x, z, y, x); } +Vector4 Vector3::yzyx() const { return Vector4 (y, z, y, x); } +Vector4 Vector3::zzyx() const { return Vector4 (z, z, y, x); } +Vector4 Vector3::xxzx() const { return Vector4 (x, x, z, x); } +Vector4 Vector3::yxzx() const { return Vector4 (y, x, z, x); } +Vector4 Vector3::zxzx() const { return Vector4 (z, x, z, x); } +Vector4 Vector3::xyzx() const { return Vector4 (x, y, z, x); } +Vector4 Vector3::yyzx() const { return Vector4 (y, y, z, x); } +Vector4 Vector3::zyzx() const { return Vector4 (z, y, z, x); } +Vector4 Vector3::xzzx() const { return Vector4 (x, z, z, x); } +Vector4 Vector3::yzzx() const { return Vector4 (y, z, z, x); } +Vector4 Vector3::zzzx() const { return Vector4 (z, z, z, x); } +Vector4 Vector3::xxxy() const { return Vector4 (x, x, x, y); } +Vector4 Vector3::yxxy() const { return Vector4 (y, x, x, y); } +Vector4 Vector3::zxxy() const { return Vector4 (z, x, x, y); } +Vector4 Vector3::xyxy() const { return Vector4 (x, y, x, y); } +Vector4 Vector3::yyxy() const { return Vector4 (y, y, x, y); } +Vector4 Vector3::zyxy() const { return Vector4 (z, y, x, y); } +Vector4 Vector3::xzxy() const { return Vector4 (x, z, x, y); } +Vector4 Vector3::yzxy() const { return Vector4 (y, z, x, y); } +Vector4 Vector3::zzxy() const { return Vector4 (z, z, x, y); } +Vector4 Vector3::xxyy() const { return Vector4 (x, x, y, y); } +Vector4 Vector3::yxyy() const { return Vector4 (y, x, y, y); } +Vector4 Vector3::zxyy() const { return Vector4 (z, x, y, y); } +Vector4 Vector3::xyyy() const { return Vector4 (x, y, y, y); } +Vector4 Vector3::yyyy() const { return Vector4 (y, y, y, y); } +Vector4 Vector3::zyyy() const { return Vector4 (z, y, y, y); } +Vector4 Vector3::xzyy() const { return Vector4 (x, z, y, y); } +Vector4 Vector3::yzyy() const { return Vector4 (y, z, y, y); } +Vector4 Vector3::zzyy() const { return Vector4 (z, z, y, y); } +Vector4 Vector3::xxzy() const { return Vector4 (x, x, z, y); } +Vector4 Vector3::yxzy() const { return Vector4 (y, x, z, y); } +Vector4 Vector3::zxzy() const { return Vector4 (z, x, z, y); } +Vector4 Vector3::xyzy() const { return Vector4 (x, y, z, y); } +Vector4 Vector3::yyzy() const { return Vector4 (y, y, z, y); } +Vector4 Vector3::zyzy() const { return Vector4 (z, y, z, y); } +Vector4 Vector3::xzzy() const { return Vector4 (x, z, z, y); } +Vector4 Vector3::yzzy() const { return Vector4 (y, z, z, y); } +Vector4 Vector3::zzzy() const { return Vector4 (z, z, z, y); } +Vector4 Vector3::xxxz() const { return Vector4 (x, x, x, z); } +Vector4 Vector3::yxxz() const { return Vector4 (y, x, x, z); } +Vector4 Vector3::zxxz() const { return Vector4 (z, x, x, z); } +Vector4 Vector3::xyxz() const { return Vector4 (x, y, x, z); } +Vector4 Vector3::yyxz() const { return Vector4 (y, y, x, z); } +Vector4 Vector3::zyxz() const { return Vector4 (z, y, x, z); } +Vector4 Vector3::xzxz() const { return Vector4 (x, z, x, z); } +Vector4 Vector3::yzxz() const { return Vector4 (y, z, x, z); } +Vector4 Vector3::zzxz() const { return Vector4 (z, z, x, z); } +Vector4 Vector3::xxyz() const { return Vector4 (x, x, y, z); } +Vector4 Vector3::yxyz() const { return Vector4 (y, x, y, z); } +Vector4 Vector3::zxyz() const { return Vector4 (z, x, y, z); } +Vector4 Vector3::xyyz() const { return Vector4 (x, y, y, z); } +Vector4 Vector3::yyyz() const { return Vector4 (y, y, y, z); } +Vector4 Vector3::zyyz() const { return Vector4 (z, y, y, z); } +Vector4 Vector3::xzyz() const { return Vector4 (x, z, y, z); } +Vector4 Vector3::yzyz() const { return Vector4 (y, z, y, z); } +Vector4 Vector3::zzyz() const { return Vector4 (z, z, y, z); } +Vector4 Vector3::xxzz() const { return Vector4 (x, x, z, z); } +Vector4 Vector3::yxzz() const { return Vector4 (y, x, z, z); } +Vector4 Vector3::zxzz() const { return Vector4 (z, x, z, z); } +Vector4 Vector3::xyzz() const { return Vector4 (x, y, z, z); } +Vector4 Vector3::yyzz() const { return Vector4 (y, y, z, z); } +Vector4 Vector3::zyzz() const { return Vector4 (z, y, z, z); } +Vector4 Vector3::xzzz() const { return Vector4 (x, z, z, z); } +Vector4 Vector3::yzzz() const { return Vector4 (y, z, z, z); } +Vector4 Vector3::zzzz() const { return Vector4 (z, z, z, z); } + + + + + + +} // namespace diff --git a/dep/src/g3dlite/Vector4.cpp b/dep/src/g3dlite/Vector4.cpp new file mode 100644 index 00000000000..bfea20202c4 --- /dev/null +++ b/dep/src/g3dlite/Vector4.cpp @@ -0,0 +1,438 @@ +/** + @file Vector4.cpp + + @maintainer Morgan McGuire, matrix@graphics3d.com + + @created 2001-07-09 + @edited 2003-09-29 + */ + +#include +#include +#include "G3D/Vector4.h" +//#include "G3D/Color4.h" +#include "G3D/g3dmath.h" +#include "G3D/format.h" +#include "G3D/stringutils.h" + +namespace G3D { + +unsigned int Vector4::hashCode() const { + unsigned int xhash = (*(int*)(void*)(&x)); + unsigned int yhash = (*(int*)(void*)(&y)); + unsigned int zhash = (*(int*)(void*)(&z)); + unsigned int whash = (*(int*)(void*)(&w)); + + return xhash + (yhash * 37) + (zhash * 101) + (whash * 241); +} + +#if 0 +Vector4::Vector4(const class Color4& c) { + x = c.r; + y = c.g; + z = c.b; + w = c.a; +} +#endif + + +Vector4::Vector4(const Vector2& v1, const Vector2& v2) { + x = v1.x; + y = v1.y; + z = v2.x; + w = v2.y; +} + + +Vector4::Vector4(const Vector2& v1, float fz, float fw) { + x = v1.x; + y = v1.y; + z = fz; + w = fw; +} + +//---------------------------------------------------------------------------- + +Vector4 Vector4::operator/ (float fScalar) const { + Vector4 kQuot; + + if ( fScalar != 0.0 ) { + float fInvScalar = 1.0f / fScalar; + kQuot.x = fInvScalar * x; + kQuot.y = fInvScalar * y; + kQuot.z = fInvScalar * z; + kQuot.w = fInvScalar * w; + return kQuot; + } else { + return Vector4::inf(); + } +} + +//---------------------------------------------------------------------------- +Vector4& Vector4::operator/= (float fScalar) { + if (fScalar != 0.0f) { + float fInvScalar = 1.0f / fScalar; + x *= fInvScalar; + y *= fInvScalar; + z *= fInvScalar; + w *= fInvScalar; + } else { + *this = Vector4::inf(); + } + + return *this; +} + + +//---------------------------------------------------------------------------- + +std::string Vector4::toString() const { + return G3D::format("(%g, %g, %g, %g)", x, y, z, w); +} +// 2-char swizzles + +Vector2 Vector4::xx() const { return Vector2 (x, x); } +Vector2 Vector4::yx() const { return Vector2 (y, x); } +Vector2 Vector4::zx() const { return Vector2 (z, x); } +Vector2 Vector4::wx() const { return Vector2 (w, x); } +Vector2 Vector4::xy() const { return Vector2 (x, y); } +Vector2 Vector4::yy() const { return Vector2 (y, y); } +Vector2 Vector4::zy() const { return Vector2 (z, y); } +Vector2 Vector4::wy() const { return Vector2 (w, y); } +Vector2 Vector4::xz() const { return Vector2 (x, z); } +Vector2 Vector4::yz() const { return Vector2 (y, z); } +Vector2 Vector4::zz() const { return Vector2 (z, z); } +Vector2 Vector4::wz() const { return Vector2 (w, z); } +Vector2 Vector4::xw() const { return Vector2 (x, w); } +Vector2 Vector4::yw() const { return Vector2 (y, w); } +Vector2 Vector4::zw() const { return Vector2 (z, w); } +Vector2 Vector4::ww() const { return Vector2 (w, w); } + +// 3-char swizzles + +Vector3 Vector4::xxx() const { return Vector3 (x, x, x); } +Vector3 Vector4::yxx() const { return Vector3 (y, x, x); } +Vector3 Vector4::zxx() const { return Vector3 (z, x, x); } +Vector3 Vector4::wxx() const { return Vector3 (w, x, x); } +Vector3 Vector4::xyx() const { return Vector3 (x, y, x); } +Vector3 Vector4::yyx() const { return Vector3 (y, y, x); } +Vector3 Vector4::zyx() const { return Vector3 (z, y, x); } +Vector3 Vector4::wyx() const { return Vector3 (w, y, x); } +Vector3 Vector4::xzx() const { return Vector3 (x, z, x); } +Vector3 Vector4::yzx() const { return Vector3 (y, z, x); } +Vector3 Vector4::zzx() const { return Vector3 (z, z, x); } +Vector3 Vector4::wzx() const { return Vector3 (w, z, x); } +Vector3 Vector4::xwx() const { return Vector3 (x, w, x); } +Vector3 Vector4::ywx() const { return Vector3 (y, w, x); } +Vector3 Vector4::zwx() const { return Vector3 (z, w, x); } +Vector3 Vector4::wwx() const { return Vector3 (w, w, x); } +Vector3 Vector4::xxy() const { return Vector3 (x, x, y); } +Vector3 Vector4::yxy() const { return Vector3 (y, x, y); } +Vector3 Vector4::zxy() const { return Vector3 (z, x, y); } +Vector3 Vector4::wxy() const { return Vector3 (w, x, y); } +Vector3 Vector4::xyy() const { return Vector3 (x, y, y); } +Vector3 Vector4::yyy() const { return Vector3 (y, y, y); } +Vector3 Vector4::zyy() const { return Vector3 (z, y, y); } +Vector3 Vector4::wyy() const { return Vector3 (w, y, y); } +Vector3 Vector4::xzy() const { return Vector3 (x, z, y); } +Vector3 Vector4::yzy() const { return Vector3 (y, z, y); } +Vector3 Vector4::zzy() const { return Vector3 (z, z, y); } +Vector3 Vector4::wzy() const { return Vector3 (w, z, y); } +Vector3 Vector4::xwy() const { return Vector3 (x, w, y); } +Vector3 Vector4::ywy() const { return Vector3 (y, w, y); } +Vector3 Vector4::zwy() const { return Vector3 (z, w, y); } +Vector3 Vector4::wwy() const { return Vector3 (w, w, y); } +Vector3 Vector4::xxz() const { return Vector3 (x, x, z); } +Vector3 Vector4::yxz() const { return Vector3 (y, x, z); } +Vector3 Vector4::zxz() const { return Vector3 (z, x, z); } +Vector3 Vector4::wxz() const { return Vector3 (w, x, z); } +Vector3 Vector4::xyz() const { return Vector3 (x, y, z); } +Vector3 Vector4::yyz() const { return Vector3 (y, y, z); } +Vector3 Vector4::zyz() const { return Vector3 (z, y, z); } +Vector3 Vector4::wyz() const { return Vector3 (w, y, z); } +Vector3 Vector4::xzz() const { return Vector3 (x, z, z); } +Vector3 Vector4::yzz() const { return Vector3 (y, z, z); } +Vector3 Vector4::zzz() const { return Vector3 (z, z, z); } +Vector3 Vector4::wzz() const { return Vector3 (w, z, z); } +Vector3 Vector4::xwz() const { return Vector3 (x, w, z); } +Vector3 Vector4::ywz() const { return Vector3 (y, w, z); } +Vector3 Vector4::zwz() const { return Vector3 (z, w, z); } +Vector3 Vector4::wwz() const { return Vector3 (w, w, z); } +Vector3 Vector4::xxw() const { return Vector3 (x, x, w); } +Vector3 Vector4::yxw() const { return Vector3 (y, x, w); } +Vector3 Vector4::zxw() const { return Vector3 (z, x, w); } +Vector3 Vector4::wxw() const { return Vector3 (w, x, w); } +Vector3 Vector4::xyw() const { return Vector3 (x, y, w); } +Vector3 Vector4::yyw() const { return Vector3 (y, y, w); } +Vector3 Vector4::zyw() const { return Vector3 (z, y, w); } +Vector3 Vector4::wyw() const { return Vector3 (w, y, w); } +Vector3 Vector4::xzw() const { return Vector3 (x, z, w); } +Vector3 Vector4::yzw() const { return Vector3 (y, z, w); } +Vector3 Vector4::zzw() const { return Vector3 (z, z, w); } +Vector3 Vector4::wzw() const { return Vector3 (w, z, w); } +Vector3 Vector4::xww() const { return Vector3 (x, w, w); } +Vector3 Vector4::yww() const { return Vector3 (y, w, w); } +Vector3 Vector4::zww() const { return Vector3 (z, w, w); } +Vector3 Vector4::www() const { return Vector3 (w, w, w); } + +// 4-char swizzles + +Vector4 Vector4::xxxx() const { return Vector4 (x, x, x, x); } +Vector4 Vector4::yxxx() const { return Vector4 (y, x, x, x); } +Vector4 Vector4::zxxx() const { return Vector4 (z, x, x, x); } +Vector4 Vector4::wxxx() const { return Vector4 (w, x, x, x); } +Vector4 Vector4::xyxx() const { return Vector4 (x, y, x, x); } +Vector4 Vector4::yyxx() const { return Vector4 (y, y, x, x); } +Vector4 Vector4::zyxx() const { return Vector4 (z, y, x, x); } +Vector4 Vector4::wyxx() const { return Vector4 (w, y, x, x); } +Vector4 Vector4::xzxx() const { return Vector4 (x, z, x, x); } +Vector4 Vector4::yzxx() const { return Vector4 (y, z, x, x); } +Vector4 Vector4::zzxx() const { return Vector4 (z, z, x, x); } +Vector4 Vector4::wzxx() const { return Vector4 (w, z, x, x); } +Vector4 Vector4::xwxx() const { return Vector4 (x, w, x, x); } +Vector4 Vector4::ywxx() const { return Vector4 (y, w, x, x); } +Vector4 Vector4::zwxx() const { return Vector4 (z, w, x, x); } +Vector4 Vector4::wwxx() const { return Vector4 (w, w, x, x); } +Vector4 Vector4::xxyx() const { return Vector4 (x, x, y, x); } +Vector4 Vector4::yxyx() const { return Vector4 (y, x, y, x); } +Vector4 Vector4::zxyx() const { return Vector4 (z, x, y, x); } +Vector4 Vector4::wxyx() const { return Vector4 (w, x, y, x); } +Vector4 Vector4::xyyx() const { return Vector4 (x, y, y, x); } +Vector4 Vector4::yyyx() const { return Vector4 (y, y, y, x); } +Vector4 Vector4::zyyx() const { return Vector4 (z, y, y, x); } +Vector4 Vector4::wyyx() const { return Vector4 (w, y, y, x); } +Vector4 Vector4::xzyx() const { return Vector4 (x, z, y, x); } +Vector4 Vector4::yzyx() const { return Vector4 (y, z, y, x); } +Vector4 Vector4::zzyx() const { return Vector4 (z, z, y, x); } +Vector4 Vector4::wzyx() const { return Vector4 (w, z, y, x); } +Vector4 Vector4::xwyx() const { return Vector4 (x, w, y, x); } +Vector4 Vector4::ywyx() const { return Vector4 (y, w, y, x); } +Vector4 Vector4::zwyx() const { return Vector4 (z, w, y, x); } +Vector4 Vector4::wwyx() const { return Vector4 (w, w, y, x); } +Vector4 Vector4::xxzx() const { return Vector4 (x, x, z, x); } +Vector4 Vector4::yxzx() const { return Vector4 (y, x, z, x); } +Vector4 Vector4::zxzx() const { return Vector4 (z, x, z, x); } +Vector4 Vector4::wxzx() const { return Vector4 (w, x, z, x); } +Vector4 Vector4::xyzx() const { return Vector4 (x, y, z, x); } +Vector4 Vector4::yyzx() const { return Vector4 (y, y, z, x); } +Vector4 Vector4::zyzx() const { return Vector4 (z, y, z, x); } +Vector4 Vector4::wyzx() const { return Vector4 (w, y, z, x); } +Vector4 Vector4::xzzx() const { return Vector4 (x, z, z, x); } +Vector4 Vector4::yzzx() const { return Vector4 (y, z, z, x); } +Vector4 Vector4::zzzx() const { return Vector4 (z, z, z, x); } +Vector4 Vector4::wzzx() const { return Vector4 (w, z, z, x); } +Vector4 Vector4::xwzx() const { return Vector4 (x, w, z, x); } +Vector4 Vector4::ywzx() const { return Vector4 (y, w, z, x); } +Vector4 Vector4::zwzx() const { return Vector4 (z, w, z, x); } +Vector4 Vector4::wwzx() const { return Vector4 (w, w, z, x); } +Vector4 Vector4::xxwx() const { return Vector4 (x, x, w, x); } +Vector4 Vector4::yxwx() const { return Vector4 (y, x, w, x); } +Vector4 Vector4::zxwx() const { return Vector4 (z, x, w, x); } +Vector4 Vector4::wxwx() const { return Vector4 (w, x, w, x); } +Vector4 Vector4::xywx() const { return Vector4 (x, y, w, x); } +Vector4 Vector4::yywx() const { return Vector4 (y, y, w, x); } +Vector4 Vector4::zywx() const { return Vector4 (z, y, w, x); } +Vector4 Vector4::wywx() const { return Vector4 (w, y, w, x); } +Vector4 Vector4::xzwx() const { return Vector4 (x, z, w, x); } +Vector4 Vector4::yzwx() const { return Vector4 (y, z, w, x); } +Vector4 Vector4::zzwx() const { return Vector4 (z, z, w, x); } +Vector4 Vector4::wzwx() const { return Vector4 (w, z, w, x); } +Vector4 Vector4::xwwx() const { return Vector4 (x, w, w, x); } +Vector4 Vector4::ywwx() const { return Vector4 (y, w, w, x); } +Vector4 Vector4::zwwx() const { return Vector4 (z, w, w, x); } +Vector4 Vector4::wwwx() const { return Vector4 (w, w, w, x); } +Vector4 Vector4::xxxy() const { return Vector4 (x, x, x, y); } +Vector4 Vector4::yxxy() const { return Vector4 (y, x, x, y); } +Vector4 Vector4::zxxy() const { return Vector4 (z, x, x, y); } +Vector4 Vector4::wxxy() const { return Vector4 (w, x, x, y); } +Vector4 Vector4::xyxy() const { return Vector4 (x, y, x, y); } +Vector4 Vector4::yyxy() const { return Vector4 (y, y, x, y); } +Vector4 Vector4::zyxy() const { return Vector4 (z, y, x, y); } +Vector4 Vector4::wyxy() const { return Vector4 (w, y, x, y); } +Vector4 Vector4::xzxy() const { return Vector4 (x, z, x, y); } +Vector4 Vector4::yzxy() const { return Vector4 (y, z, x, y); } +Vector4 Vector4::zzxy() const { return Vector4 (z, z, x, y); } +Vector4 Vector4::wzxy() const { return Vector4 (w, z, x, y); } +Vector4 Vector4::xwxy() const { return Vector4 (x, w, x, y); } +Vector4 Vector4::ywxy() const { return Vector4 (y, w, x, y); } +Vector4 Vector4::zwxy() const { return Vector4 (z, w, x, y); } +Vector4 Vector4::wwxy() const { return Vector4 (w, w, x, y); } +Vector4 Vector4::xxyy() const { return Vector4 (x, x, y, y); } +Vector4 Vector4::yxyy() const { return Vector4 (y, x, y, y); } +Vector4 Vector4::zxyy() const { return Vector4 (z, x, y, y); } +Vector4 Vector4::wxyy() const { return Vector4 (w, x, y, y); } +Vector4 Vector4::xyyy() const { return Vector4 (x, y, y, y); } +Vector4 Vector4::yyyy() const { return Vector4 (y, y, y, y); } +Vector4 Vector4::zyyy() const { return Vector4 (z, y, y, y); } +Vector4 Vector4::wyyy() const { return Vector4 (w, y, y, y); } +Vector4 Vector4::xzyy() const { return Vector4 (x, z, y, y); } +Vector4 Vector4::yzyy() const { return Vector4 (y, z, y, y); } +Vector4 Vector4::zzyy() const { return Vector4 (z, z, y, y); } +Vector4 Vector4::wzyy() const { return Vector4 (w, z, y, y); } +Vector4 Vector4::xwyy() const { return Vector4 (x, w, y, y); } +Vector4 Vector4::ywyy() const { return Vector4 (y, w, y, y); } +Vector4 Vector4::zwyy() const { return Vector4 (z, w, y, y); } +Vector4 Vector4::wwyy() const { return Vector4 (w, w, y, y); } +Vector4 Vector4::xxzy() const { return Vector4 (x, x, z, y); } +Vector4 Vector4::yxzy() const { return Vector4 (y, x, z, y); } +Vector4 Vector4::zxzy() const { return Vector4 (z, x, z, y); } +Vector4 Vector4::wxzy() const { return Vector4 (w, x, z, y); } +Vector4 Vector4::xyzy() const { return Vector4 (x, y, z, y); } +Vector4 Vector4::yyzy() const { return Vector4 (y, y, z, y); } +Vector4 Vector4::zyzy() const { return Vector4 (z, y, z, y); } +Vector4 Vector4::wyzy() const { return Vector4 (w, y, z, y); } +Vector4 Vector4::xzzy() const { return Vector4 (x, z, z, y); } +Vector4 Vector4::yzzy() const { return Vector4 (y, z, z, y); } +Vector4 Vector4::zzzy() const { return Vector4 (z, z, z, y); } +Vector4 Vector4::wzzy() const { return Vector4 (w, z, z, y); } +Vector4 Vector4::xwzy() const { return Vector4 (x, w, z, y); } +Vector4 Vector4::ywzy() const { return Vector4 (y, w, z, y); } +Vector4 Vector4::zwzy() const { return Vector4 (z, w, z, y); } +Vector4 Vector4::wwzy() const { return Vector4 (w, w, z, y); } +Vector4 Vector4::xxwy() const { return Vector4 (x, x, w, y); } +Vector4 Vector4::yxwy() const { return Vector4 (y, x, w, y); } +Vector4 Vector4::zxwy() const { return Vector4 (z, x, w, y); } +Vector4 Vector4::wxwy() const { return Vector4 (w, x, w, y); } +Vector4 Vector4::xywy() const { return Vector4 (x, y, w, y); } +Vector4 Vector4::yywy() const { return Vector4 (y, y, w, y); } +Vector4 Vector4::zywy() const { return Vector4 (z, y, w, y); } +Vector4 Vector4::wywy() const { return Vector4 (w, y, w, y); } +Vector4 Vector4::xzwy() const { return Vector4 (x, z, w, y); } +Vector4 Vector4::yzwy() const { return Vector4 (y, z, w, y); } +Vector4 Vector4::zzwy() const { return Vector4 (z, z, w, y); } +Vector4 Vector4::wzwy() const { return Vector4 (w, z, w, y); } +Vector4 Vector4::xwwy() const { return Vector4 (x, w, w, y); } +Vector4 Vector4::ywwy() const { return Vector4 (y, w, w, y); } +Vector4 Vector4::zwwy() const { return Vector4 (z, w, w, y); } +Vector4 Vector4::wwwy() const { return Vector4 (w, w, w, y); } +Vector4 Vector4::xxxz() const { return Vector4 (x, x, x, z); } +Vector4 Vector4::yxxz() const { return Vector4 (y, x, x, z); } +Vector4 Vector4::zxxz() const { return Vector4 (z, x, x, z); } +Vector4 Vector4::wxxz() const { return Vector4 (w, x, x, z); } +Vector4 Vector4::xyxz() const { return Vector4 (x, y, x, z); } +Vector4 Vector4::yyxz() const { return Vector4 (y, y, x, z); } +Vector4 Vector4::zyxz() const { return Vector4 (z, y, x, z); } +Vector4 Vector4::wyxz() const { return Vector4 (w, y, x, z); } +Vector4 Vector4::xzxz() const { return Vector4 (x, z, x, z); } +Vector4 Vector4::yzxz() const { return Vector4 (y, z, x, z); } +Vector4 Vector4::zzxz() const { return Vector4 (z, z, x, z); } +Vector4 Vector4::wzxz() const { return Vector4 (w, z, x, z); } +Vector4 Vector4::xwxz() const { return Vector4 (x, w, x, z); } +Vector4 Vector4::ywxz() const { return Vector4 (y, w, x, z); } +Vector4 Vector4::zwxz() const { return Vector4 (z, w, x, z); } +Vector4 Vector4::wwxz() const { return Vector4 (w, w, x, z); } +Vector4 Vector4::xxyz() const { return Vector4 (x, x, y, z); } +Vector4 Vector4::yxyz() const { return Vector4 (y, x, y, z); } +Vector4 Vector4::zxyz() const { return Vector4 (z, x, y, z); } +Vector4 Vector4::wxyz() const { return Vector4 (w, x, y, z); } +Vector4 Vector4::xyyz() const { return Vector4 (x, y, y, z); } +Vector4 Vector4::yyyz() const { return Vector4 (y, y, y, z); } +Vector4 Vector4::zyyz() const { return Vector4 (z, y, y, z); } +Vector4 Vector4::wyyz() const { return Vector4 (w, y, y, z); } +Vector4 Vector4::xzyz() const { return Vector4 (x, z, y, z); } +Vector4 Vector4::yzyz() const { return Vector4 (y, z, y, z); } +Vector4 Vector4::zzyz() const { return Vector4 (z, z, y, z); } +Vector4 Vector4::wzyz() const { return Vector4 (w, z, y, z); } +Vector4 Vector4::xwyz() const { return Vector4 (x, w, y, z); } +Vector4 Vector4::ywyz() const { return Vector4 (y, w, y, z); } +Vector4 Vector4::zwyz() const { return Vector4 (z, w, y, z); } +Vector4 Vector4::wwyz() const { return Vector4 (w, w, y, z); } +Vector4 Vector4::xxzz() const { return Vector4 (x, x, z, z); } +Vector4 Vector4::yxzz() const { return Vector4 (y, x, z, z); } +Vector4 Vector4::zxzz() const { return Vector4 (z, x, z, z); } +Vector4 Vector4::wxzz() const { return Vector4 (w, x, z, z); } +Vector4 Vector4::xyzz() const { return Vector4 (x, y, z, z); } +Vector4 Vector4::yyzz() const { return Vector4 (y, y, z, z); } +Vector4 Vector4::zyzz() const { return Vector4 (z, y, z, z); } +Vector4 Vector4::wyzz() const { return Vector4 (w, y, z, z); } +Vector4 Vector4::xzzz() const { return Vector4 (x, z, z, z); } +Vector4 Vector4::yzzz() const { return Vector4 (y, z, z, z); } +Vector4 Vector4::zzzz() const { return Vector4 (z, z, z, z); } +Vector4 Vector4::wzzz() const { return Vector4 (w, z, z, z); } +Vector4 Vector4::xwzz() const { return Vector4 (x, w, z, z); } +Vector4 Vector4::ywzz() const { return Vector4 (y, w, z, z); } +Vector4 Vector4::zwzz() const { return Vector4 (z, w, z, z); } +Vector4 Vector4::wwzz() const { return Vector4 (w, w, z, z); } +Vector4 Vector4::xxwz() const { return Vector4 (x, x, w, z); } +Vector4 Vector4::yxwz() const { return Vector4 (y, x, w, z); } +Vector4 Vector4::zxwz() const { return Vector4 (z, x, w, z); } +Vector4 Vector4::wxwz() const { return Vector4 (w, x, w, z); } +Vector4 Vector4::xywz() const { return Vector4 (x, y, w, z); } +Vector4 Vector4::yywz() const { return Vector4 (y, y, w, z); } +Vector4 Vector4::zywz() const { return Vector4 (z, y, w, z); } +Vector4 Vector4::wywz() const { return Vector4 (w, y, w, z); } +Vector4 Vector4::xzwz() const { return Vector4 (x, z, w, z); } +Vector4 Vector4::yzwz() const { return Vector4 (y, z, w, z); } +Vector4 Vector4::zzwz() const { return Vector4 (z, z, w, z); } +Vector4 Vector4::wzwz() const { return Vector4 (w, z, w, z); } +Vector4 Vector4::xwwz() const { return Vector4 (x, w, w, z); } +Vector4 Vector4::ywwz() const { return Vector4 (y, w, w, z); } +Vector4 Vector4::zwwz() const { return Vector4 (z, w, w, z); } +Vector4 Vector4::wwwz() const { return Vector4 (w, w, w, z); } +Vector4 Vector4::xxxw() const { return Vector4 (x, x, x, w); } +Vector4 Vector4::yxxw() const { return Vector4 (y, x, x, w); } +Vector4 Vector4::zxxw() const { return Vector4 (z, x, x, w); } +Vector4 Vector4::wxxw() const { return Vector4 (w, x, x, w); } +Vector4 Vector4::xyxw() const { return Vector4 (x, y, x, w); } +Vector4 Vector4::yyxw() const { return Vector4 (y, y, x, w); } +Vector4 Vector4::zyxw() const { return Vector4 (z, y, x, w); } +Vector4 Vector4::wyxw() const { return Vector4 (w, y, x, w); } +Vector4 Vector4::xzxw() const { return Vector4 (x, z, x, w); } +Vector4 Vector4::yzxw() const { return Vector4 (y, z, x, w); } +Vector4 Vector4::zzxw() const { return Vector4 (z, z, x, w); } +Vector4 Vector4::wzxw() const { return Vector4 (w, z, x, w); } +Vector4 Vector4::xwxw() const { return Vector4 (x, w, x, w); } +Vector4 Vector4::ywxw() const { return Vector4 (y, w, x, w); } +Vector4 Vector4::zwxw() const { return Vector4 (z, w, x, w); } +Vector4 Vector4::wwxw() const { return Vector4 (w, w, x, w); } +Vector4 Vector4::xxyw() const { return Vector4 (x, x, y, w); } +Vector4 Vector4::yxyw() const { return Vector4 (y, x, y, w); } +Vector4 Vector4::zxyw() const { return Vector4 (z, x, y, w); } +Vector4 Vector4::wxyw() const { return Vector4 (w, x, y, w); } +Vector4 Vector4::xyyw() const { return Vector4 (x, y, y, w); } +Vector4 Vector4::yyyw() const { return Vector4 (y, y, y, w); } +Vector4 Vector4::zyyw() const { return Vector4 (z, y, y, w); } +Vector4 Vector4::wyyw() const { return Vector4 (w, y, y, w); } +Vector4 Vector4::xzyw() const { return Vector4 (x, z, y, w); } +Vector4 Vector4::yzyw() const { return Vector4 (y, z, y, w); } +Vector4 Vector4::zzyw() const { return Vector4 (z, z, y, w); } +Vector4 Vector4::wzyw() const { return Vector4 (w, z, y, w); } +Vector4 Vector4::xwyw() const { return Vector4 (x, w, y, w); } +Vector4 Vector4::ywyw() const { return Vector4 (y, w, y, w); } +Vector4 Vector4::zwyw() const { return Vector4 (z, w, y, w); } +Vector4 Vector4::wwyw() const { return Vector4 (w, w, y, w); } +Vector4 Vector4::xxzw() const { return Vector4 (x, x, z, w); } +Vector4 Vector4::yxzw() const { return Vector4 (y, x, z, w); } +Vector4 Vector4::zxzw() const { return Vector4 (z, x, z, w); } +Vector4 Vector4::wxzw() const { return Vector4 (w, x, z, w); } +Vector4 Vector4::xyzw() const { return Vector4 (x, y, z, w); } +Vector4 Vector4::yyzw() const { return Vector4 (y, y, z, w); } +Vector4 Vector4::zyzw() const { return Vector4 (z, y, z, w); } +Vector4 Vector4::wyzw() const { return Vector4 (w, y, z, w); } +Vector4 Vector4::xzzw() const { return Vector4 (x, z, z, w); } +Vector4 Vector4::yzzw() const { return Vector4 (y, z, z, w); } +Vector4 Vector4::zzzw() const { return Vector4 (z, z, z, w); } +Vector4 Vector4::wzzw() const { return Vector4 (w, z, z, w); } +Vector4 Vector4::xwzw() const { return Vector4 (x, w, z, w); } +Vector4 Vector4::ywzw() const { return Vector4 (y, w, z, w); } +Vector4 Vector4::zwzw() const { return Vector4 (z, w, z, w); } +Vector4 Vector4::wwzw() const { return Vector4 (w, w, z, w); } +Vector4 Vector4::xxww() const { return Vector4 (x, x, w, w); } +Vector4 Vector4::yxww() const { return Vector4 (y, x, w, w); } +Vector4 Vector4::zxww() const { return Vector4 (z, x, w, w); } +Vector4 Vector4::wxww() const { return Vector4 (w, x, w, w); } +Vector4 Vector4::xyww() const { return Vector4 (x, y, w, w); } +Vector4 Vector4::yyww() const { return Vector4 (y, y, w, w); } +Vector4 Vector4::zyww() const { return Vector4 (z, y, w, w); } +Vector4 Vector4::wyww() const { return Vector4 (w, y, w, w); } +Vector4 Vector4::xzww() const { return Vector4 (x, z, w, w); } +Vector4 Vector4::yzww() const { return Vector4 (y, z, w, w); } +Vector4 Vector4::zzww() const { return Vector4 (z, z, w, w); } +Vector4 Vector4::wzww() const { return Vector4 (w, z, w, w); } +Vector4 Vector4::xwww() const { return Vector4 (x, w, w, w); } +Vector4 Vector4::ywww() const { return Vector4 (y, w, w, w); } +Vector4 Vector4::zwww() const { return Vector4 (z, w, w, w); } +Vector4 Vector4::wwww() const { return Vector4 (w, w, w, w); } + + +}; // namespace diff --git a/dep/src/g3dlite/format.cpp b/dep/src/g3dlite/format.cpp new file mode 100644 index 00000000000..6def987c21b --- /dev/null +++ b/dep/src/g3dlite/format.cpp @@ -0,0 +1,171 @@ +/** + @file format.cpp + + @author Morgan McGuire, graphics3d.com + + @created 2000-09-09 + @edited 2006-04-30 +*/ + +#include "G3D/format.h" +#include "G3D/platform.h" +#include "G3D/System.h" + +#ifdef G3D_WIN32 + #include + #define vsnprintf _vsnprintf + #define NEWLINE "\r\n" +#else + #include + #define NEWLINE "\n" +#endif + +#ifdef _MSC_VER + // disable: "C++ exception handler used" +# pragma warning (push) +# pragma warning (disable : 4530) +#endif // _MSC_VER + +// If your platform does not have vsnprintf, you can find a +// implementation at http://www.ijs.si/software/snprintf/ + +namespace G3D { + +std::string format(const char* fmt,...) { + va_list argList; + va_start(argList,fmt); + std::string result = vformat(fmt, argList); + va_end(argList); + + return result; +} + +#if defined(G3D_WIN32) && (_MSC_VER >= 1300) +// Both MSVC6 and 7 seem to use the non-standard vsnprintf +// so we are using vscprintf to determine buffer size, however +// only MSVC7 headers include vscprintf for some reason. +std::string vformat(const char *fmt, va_list argPtr) { + // We draw the line at a 1MB string. + const int maxSize = 1000000; + + // If the string is less than 161 characters, + // allocate it on the stack because this saves + // the malloc/free time. + const int bufSize = 161; + char stackBuffer[bufSize]; + + int actualSize = _vscprintf(fmt, argPtr) + 1; + + if (actualSize > bufSize) { + + // Now use the heap. + char* heapBuffer = NULL; + + if (actualSize < maxSize) { + + heapBuffer = (char*)System::malloc(maxSize + 1); + vsnprintf(heapBuffer, maxSize, fmt, argPtr); + heapBuffer[maxSize] = '\0'; + } else { + heapBuffer = (char*)System::malloc(actualSize); + vsprintf(heapBuffer, fmt, argPtr); + } + + std::string formattedString(heapBuffer); + System::free(heapBuffer); + return formattedString; + } else { + + vsprintf(stackBuffer, fmt, argPtr); + return std::string(stackBuffer); + } +} + +#elif defined(G3D_WIN32) && (_MSC_VER < 1300) + +std::string vformat(const char *fmt, va_list argPtr) { + // We draw the line at a 1MB string. + const int maxSize = 1000000; + + // If the string is less than 161 characters, + // allocate it on the stack because this saves + // the malloc/free time. + const int bufSize = 161; + char stackBuffer[bufSize]; + + int actualWritten = vsnprintf(stackBuffer, bufSize, fmt, argPtr); + + // Not a big enough buffer, bufSize characters written + if (actualWritten == -1) { + + int heapSize = 512; + double powSize = 1.0; + char* heapBuffer = (char*)System::malloc(heapSize); + + while ((vsnprintf(heapBuffer, heapSize, fmt, argPtr) == -1) && + (heapSize < maxSize)) { + + heapSize = iCeil(heapSize * ::pow((double)2.0, powSize++)); + heapBuffer = (char*)System::realloc(heapBuffer, heapSize); + } + + heapBuffer[heapSize-1] = '\0'; + + std::string heapString(heapBuffer); + System::free(heapBuffer); + + return heapString; + } else { + + return std::string(stackBuffer); + } +} + +#else + +// glibc 2.1 has been updated to the C99 standard +std::string vformat(const char* fmt, va_list argPtr) { + // If the string is less than 161 characters, + // allocate it on the stack because this saves + // the malloc/free time. The number 161 is chosen + // to support two lines of text on an 80 character + // console (plus the null terminator). + const int bufSize = 161; + char stackBuffer[bufSize]; + + int numChars = vsnprintf(stackBuffer, bufSize, fmt, argPtr); + + if (numChars >= bufSize) { + // We didn't allocate a big enough string. + char* heapBuffer = (char*)System::malloc((numChars + 1) * sizeof(char)); + + assert(heapBuffer); + int numChars2 = vsnprintf(heapBuffer, numChars + 1, fmt, argPtr); + assert(numChars2 == numChars); + + std::string result(heapBuffer); + + System::free(heapBuffer); + + return result; + + } else { + + return std::string(stackBuffer); + + } +} + +#endif + +} // namespace + +#ifdef G3D_WIN32 +# undef vsnprintf +#endif + +#ifdef _MSC_VER +# pragma warning (pop) +#endif + +#undef NEWLINE diff --git a/dep/src/g3dlite/license.html b/dep/src/g3dlite/license.html new file mode 100644 index 00000000000..9bbb2ad5f9a --- /dev/null +++ b/dep/src/g3dlite/license.html @@ -0,0 +1,109 @@ + + + + + + G3D: License + + + + + +
+ + + + +
+ + Contents + Functions + Classes + Topics + User Forum + CVS +
+ + +
+ + + +

License

+
+ +Introduction + +Installation
+

+Intent of License

+(This section is informal and not legally binding.)

+
+ This library is free code-- you can use it without charge and it is minimally legally encumbered. Unlike some other free libraries, we <u>do not</u> require you to release your source code or make your own program open source.

+I intend the license (below) to protect me and the other contributors from liability and allow you to use the source however you want. You can make your own closed or open-source programs, sell them, give them away, whatever.

+You have an obligation to say "this software is based in part on the work of the Independent JPEG Group" in your documentation or application help if you use the G3D::GImage class because it is based on the IJG library. The OpenGL headers and ZLib headers included may be freely distributed provided their copyright notices remain intact.

+For convenience, G3D::license is a function that returns the license string you must put in your documentation. G3D::GApp will automatically write a file (g3d-license.txt) to disk with the contents of this license unless you tell it not to.

+Most of the data resources have either entered the public domain and have been in several published papers or are data that I have explicitly received permission to distribute with G3D. The G3D fonts are actually font images, not TrueType font descriptions and may be freely distributed. As a rule of thumb, you can freely use and distribute anything you find in the data directory but may need permission to use it in a commercial product. Check the various copyright.txt files in the data directories for specific information.

+You are required by the BSD license to acknowledge G3D in your documentation. This can be as minimal as a note buried in the fine print at the end of a manual or a text file accompanying your program. I appreciate it if you acknowledged the library more publicly but you aren't required to.

+Likewise, you are encouraged but not required to submit patches to improve the library for the benefit of all. E-mail me with bugs, patches, and questions.

+-Morgan McGuire <matrix@graphics3d.com>

+


+

+License

+G3D is licensed under the BSD license, with portions controlled by the IJG license and PNG Reference Library license

+

+osi-certified-120x100.gif +
+

+This product uses software from the G3D project (http://g3d-cpp.sf.net)

+Copyright © 2000-2006, Morgan McGuire

+All rights reserved.

+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

+ Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

+ Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

+ Neither the name of Morgan McGuire, Williams College, Brown University, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+You must also agree to be bound by the terms of the Independent JPEG Group license for the portions of this library that are based on the work of the Independent JPEG Group, if you use those portions. Note: if you do not use the G3D::GImage class, this clause does not apply to you because the linker will strip that code from your project. The IJG-README.TXT file contains the Independent JPEG Group license. +


+Generated on Tue Jul 18 12:05:54 2006 for G3D by +doxygen + 1.4.6-NO
+Hosted by SourceForge.net Logo + + diff --git a/dep/src/sockets/Base64.cpp b/dep/src/sockets/Base64.cpp new file mode 100644 index 00000000000..b8cf1237175 --- /dev/null +++ b/dep/src/sockets/Base64.cpp @@ -0,0 +1,272 @@ +/** \file Base64.cpp + ** \date 2004-02-13 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2004-2007 Anders Hedstrom + +This library is made available under the terms of the GNU GPL. + +If you would like to use this library in a closed-source application, +a separate license agreement is available. For information about +the closed-source license agreement for the C++ sockets library, +please visit http://www.alhem.net/Sockets/license.html and/or +email license@alhem.net. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#include "Base64.h" + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + + +const char *Base64::bstr = + "ABCDEFGHIJKLMNOPQ" + "RSTUVWXYZabcdefgh" + "ijklmnopqrstuvwxy" + "z0123456789+/"; + +const char Base64::rstr[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0, + 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0}; + + +Base64::Base64() +{ +} + + +void Base64::encode(FILE *fil, std::string& output, bool add_crlf) +{ + size_t remain; + size_t i = 0; + size_t o = 0; + char input[4]; + + output = ""; + remain = fread(input,1,3,fil); + while (remain > 0) + { + if (add_crlf && o && o % 76 == 0) + output += "\n"; + switch (remain) + { + case 1: + output += bstr[ ((input[i] >> 2) & 0x3f) ]; + output += bstr[ ((input[i] << 4) & 0x30) ]; + output += "=="; + break; + case 2: + output += bstr[ ((input[i] >> 2) & 0x3f) ]; + output += bstr[ ((input[i] << 4) & 0x30) + ((input[i + 1] >> 4) & 0x0f) ]; + output += bstr[ ((input[i + 1] << 2) & 0x3c) ]; + output += "="; + break; + default: + output += bstr[ ((input[i] >> 2) & 0x3f) ]; + output += bstr[ ((input[i] << 4) & 0x30) + ((input[i + 1] >> 4) & 0x0f) ]; + output += bstr[ ((input[i + 1] << 2) & 0x3c) + ((input[i + 2] >> 6) & 0x03) ]; + output += bstr[ (input[i + 2] & 0x3f) ]; + } + o += 4; + // + remain = fread(input,1,3,fil); + } +} + + +void Base64::encode(const std::string& str_in, std::string& str_out, bool add_crlf) +{ + encode(str_in.c_str(), str_in.size(), str_out, add_crlf); +} + + +void Base64::encode(const char* input,size_t l,std::string& output, bool add_crlf) +{ + size_t i = 0; + size_t o = 0; + + output = ""; + while (i < l) + { + size_t remain = l - i; + if (add_crlf && o && o % 76 == 0) + output += "\n"; + switch (remain) + { + case 1: + output += bstr[ ((input[i] >> 2) & 0x3f) ]; + output += bstr[ ((input[i] << 4) & 0x30) ]; + output += "=="; + break; + case 2: + output += bstr[ ((input[i] >> 2) & 0x3f) ]; + output += bstr[ ((input[i] << 4) & 0x30) + ((input[i + 1] >> 4) & 0x0f) ]; + output += bstr[ ((input[i + 1] << 2) & 0x3c) ]; + output += "="; + break; + default: + output += bstr[ ((input[i] >> 2) & 0x3f) ]; + output += bstr[ ((input[i] << 4) & 0x30) + ((input[i + 1] >> 4) & 0x0f) ]; + output += bstr[ ((input[i + 1] << 2) & 0x3c) + ((input[i + 2] >> 6) & 0x03) ]; + output += bstr[ (input[i + 2] & 0x3f) ]; + } + o += 4; + i += 3; + } +} + + +void Base64::encode(const unsigned char* input,size_t l,std::string& output,bool add_crlf) +{ + size_t i = 0; + size_t o = 0; + + output = ""; + while (i < l) + { + size_t remain = l - i; + if (add_crlf && o && o % 76 == 0) + output += "\n"; + switch (remain) + { + case 1: + output += bstr[ ((input[i] >> 2) & 0x3f) ]; + output += bstr[ ((input[i] << 4) & 0x30) ]; + output += "=="; + break; + case 2: + output += bstr[ ((input[i] >> 2) & 0x3f) ]; + output += bstr[ ((input[i] << 4) & 0x30) + ((input[i + 1] >> 4) & 0x0f) ]; + output += bstr[ ((input[i + 1] << 2) & 0x3c) ]; + output += "="; + break; + default: + output += bstr[ ((input[i] >> 2) & 0x3f) ]; + output += bstr[ ((input[i] << 4) & 0x30) + ((input[i + 1] >> 4) & 0x0f) ]; + output += bstr[ ((input[i + 1] << 2) & 0x3c) + ((input[i + 2] >> 6) & 0x03) ]; + output += bstr[ (input[i + 2] & 0x3f) ]; + } + o += 4; + i += 3; + } +} + + +void Base64::decode(const std::string& input,std::string& output) +{ + size_t i = 0; + size_t l = input.size(); + + output = ""; + while (i < l) + { + while (i < l && (input[i] == 13 || input[i] == 10)) + i++; + if (i < l) + { + char b1 = (char)((rstr[(int)input[i]] << 2 & 0xfc) + + (rstr[(int)input[i + 1]] >> 4 & 0x03)); + output += b1; + if (input[i + 2] != '=') + { + char b2 = (char)((rstr[(int)input[i + 1]] << 4 & 0xf0) + + (rstr[(int)input[i + 2]] >> 2 & 0x0f)); + output += b2; + } + if (input[i + 3] != '=') + { + char b3 = (char)((rstr[(int)input[i + 2]] << 6 & 0xc0) + + rstr[(int)input[i + 3]]); + output += b3; + } + i += 4; + } + } +} + + +void Base64::decode(const std::string& input, unsigned char *output, size_t& sz) +{ + size_t i = 0; + size_t l = input.size(); + size_t j = 0; + + while (i < l) + { + while (i < l && (input[i] == 13 || input[i] == 10)) + i++; + if (i < l) + { + unsigned char b1 = (unsigned char)((rstr[(int)input[i]] << 2 & 0xfc) + + (rstr[(int)input[i + 1]] >> 4 & 0x03)); + if (output) + { + output[j] = b1; + } + j++; + if (input[i + 2] != '=') + { + unsigned char b2 = (unsigned char)((rstr[(int)input[i + 1]] << 4 & 0xf0) + + (rstr[(int)input[i + 2]] >> 2 & 0x0f)); + if (output) + { + output[j] = b2; + } + j++; + } + if (input[i + 3] != '=') + { + unsigned char b3 = (unsigned char)((rstr[(int)input[i + 2]] << 6 & 0xc0) + + rstr[(int)input[i + 3]]); + if (output) + { + output[j] = b3; + } + j++; + } + i += 4; + } + } + sz = j; +} + + +size_t Base64::decode_length(const std::string& str64) +{ + if (str64.empty() || str64.size() % 4) + return 0; + size_t l = 3 * (str64.size() / 4 - 1) + 1; + if (str64[str64.size() - 2] != '=') + l++; + if (str64[str64.size() - 1] != '=') + l++; + return l; +} + + +#ifdef SOCKETS_NAMESPACE +} +#endif + + diff --git a/dep/src/sockets/Exception.cpp b/dep/src/sockets/Exception.cpp new file mode 100644 index 00000000000..a005669e4c9 --- /dev/null +++ b/dep/src/sockets/Exception.cpp @@ -0,0 +1,48 @@ +/** + ** \file Exception.cpp + ** \date 2007-09-28 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2007 Anders Hedstrom + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifdef _MSC_VER +#pragma warning(disable:4786) +#endif +#include "Exception.h" + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + + + +Exception::Exception(const std::string& description) : m_description(description) +{ +} + + +const std::string Exception::ToString() const +{ + return m_description; +} + + +#ifdef SOCKETS_NAMESPACE +} // namespace SOCKETS_NAMESPACE { +#endif + diff --git a/dep/src/sockets/Ipv4Address.cpp b/dep/src/sockets/Ipv4Address.cpp new file mode 100644 index 00000000000..58f25e53b83 --- /dev/null +++ b/dep/src/sockets/Ipv4Address.cpp @@ -0,0 +1,214 @@ +/** + ** \file Ipv4Address.cpp + ** \date 2006-09-21 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2007 Anders Hedstrom + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#include "Ipv4Address.h" +#include "Utility.h" +#include "Parse.h" +#ifndef _WIN32 +#include +#endif + + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + + + +Ipv4Address::Ipv4Address(port_t port) : m_valid(true) +{ + memset(&m_addr, 0, sizeof(m_addr)); + m_addr.sin_family = AF_INET; + m_addr.sin_port = htons( port ); +} + + +Ipv4Address::Ipv4Address(ipaddr_t a,port_t port) : m_valid(true) +{ + memset(&m_addr, 0, sizeof(m_addr)); + m_addr.sin_family = AF_INET; + m_addr.sin_port = htons( port ); + memcpy(&m_addr.sin_addr, &a, sizeof(struct in_addr)); +} + + +Ipv4Address::Ipv4Address(struct in_addr& a,port_t port) : m_valid(true) +{ + memset(&m_addr, 0, sizeof(m_addr)); + m_addr.sin_family = AF_INET; + m_addr.sin_port = htons( port ); + m_addr.sin_addr = a; +} + + +Ipv4Address::Ipv4Address(const std::string& host,port_t port) : m_valid(false) +{ + memset(&m_addr, 0, sizeof(m_addr)); + m_addr.sin_family = AF_INET; + m_addr.sin_port = htons( port ); + { + ipaddr_t a; + if (Utility::u2ip(host, a)) + { + memcpy(&m_addr.sin_addr, &a, sizeof(struct in_addr)); + m_valid = true; + } + } +} + + +Ipv4Address::Ipv4Address(struct sockaddr_in& sa) +{ + m_addr = sa; + m_valid = sa.sin_family == AF_INET; +} + + +Ipv4Address::~Ipv4Address() +{ +} + + +Ipv4Address::operator struct sockaddr *() +{ + return (struct sockaddr *)&m_addr; +} + + +Ipv4Address::operator socklen_t() +{ + return sizeof(struct sockaddr_in); +} + + +void Ipv4Address::SetPort(port_t port) +{ + m_addr.sin_port = htons( port ); +} + + +port_t Ipv4Address::GetPort() +{ + return ntohs( m_addr.sin_port ); +} + + +bool Ipv4Address::Resolve(const std::string& hostname,struct in_addr& a) +{ + struct sockaddr_in sa; + memset(&a, 0, sizeof(a)); + if (Utility::isipv4(hostname)) + { + if (!Utility::u2ip(hostname, sa, AI_NUMERICHOST)) + return false; + a = sa.sin_addr; + return true; + } + if (!Utility::u2ip(hostname, sa)) + return false; + a = sa.sin_addr; + return true; +} + + +bool Ipv4Address::Reverse(struct in_addr& a,std::string& name) +{ + struct sockaddr_in sa; + memset(&sa, 0, sizeof(sa)); + sa.sin_family = AF_INET; + sa.sin_addr = a; + return Utility::reverse((struct sockaddr *)&sa, sizeof(sa), name); +} + + +std::string Ipv4Address::Convert(bool include_port) +{ + if (include_port) + return Convert(m_addr.sin_addr) + ":" + Utility::l2string(GetPort()); + return Convert(m_addr.sin_addr); +} + + +std::string Ipv4Address::Convert(struct in_addr& a) +{ + struct sockaddr_in sa; + memset(&sa, 0, sizeof(sa)); + sa.sin_family = AF_INET; + sa.sin_addr = a; + std::string name; + Utility::reverse((struct sockaddr *)&sa, sizeof(sa), name, NI_NUMERICHOST); + return name; +} + + +void Ipv4Address::SetAddress(struct sockaddr *sa) +{ + memcpy(&m_addr, sa, sizeof(struct sockaddr_in)); +} + + +int Ipv4Address::GetFamily() +{ + return m_addr.sin_family; +} + + +bool Ipv4Address::IsValid() +{ + return m_valid; +} + + +bool Ipv4Address::operator==(SocketAddress& a) +{ + if (a.GetFamily() != GetFamily()) + return false; + if ((socklen_t)a != sizeof(m_addr)) + return false; + struct sockaddr *sa = a; + struct sockaddr_in *p = (struct sockaddr_in *)sa; + if (p -> sin_port != m_addr.sin_port) + return false; + if (memcmp(&p -> sin_addr, &m_addr.sin_addr, 4)) + return false; + return true; +} + + +std::auto_ptr Ipv4Address::GetCopy() +{ + return std::auto_ptr(new Ipv4Address(m_addr)); +} + + +std::string Ipv4Address::Reverse() +{ + std::string tmp; + Reverse(m_addr.sin_addr, tmp); + return tmp; +} + + +#ifdef SOCKETS_NAMESPACE +} // namespace SOCKETS_NAMESPACE { +#endif + diff --git a/dep/src/sockets/Ipv6Address.cpp b/dep/src/sockets/Ipv6Address.cpp new file mode 100644 index 00000000000..2e0f1e9acf3 --- /dev/null +++ b/dep/src/sockets/Ipv6Address.cpp @@ -0,0 +1,270 @@ +/** + ** \file Ipv6Address.cpp + ** \date 2006-09-21 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2007 Anders Hedstrom + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#include "Ipv6Address.h" +#ifdef ENABLE_IPV6 + +#include "Utility.h" +#include "Parse.h" +#ifndef _WIN32 +#include +#endif +#ifdef IPPROTO_IPV6 + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + + +Ipv6Address::Ipv6Address(port_t port) : m_valid(true) +{ + memset(&m_addr, 0, sizeof(m_addr)); + m_addr.sin6_family = AF_INET6; + m_addr.sin6_port = htons( port ); +} + + +Ipv6Address::Ipv6Address(struct in6_addr& a,port_t port) : m_valid(true) +{ + memset(&m_addr, 0, sizeof(m_addr)); + m_addr.sin6_family = AF_INET6; + m_addr.sin6_port = htons( port ); + m_addr.sin6_addr = a; +} + + +Ipv6Address::Ipv6Address(const std::string& host,port_t port) : m_valid(false) +{ + memset(&m_addr, 0, sizeof(m_addr)); + m_addr.sin6_family = AF_INET6; + m_addr.sin6_port = htons( port ); + { + struct in6_addr a; + if (Utility::u2ip(host, a)) + { + m_addr.sin6_addr = a; + m_valid = true; + } + } +} + + +Ipv6Address::Ipv6Address(struct sockaddr_in6& sa) +{ + m_addr = sa; + m_valid = sa.sin6_family == AF_INET6; +} + + +Ipv6Address::~Ipv6Address() +{ +} + + +Ipv6Address::operator struct sockaddr *() +{ + return (struct sockaddr *)&m_addr; +} + + +Ipv6Address::operator socklen_t() +{ + return sizeof(struct sockaddr_in6); +} + + +void Ipv6Address::SetPort(port_t port) +{ + m_addr.sin6_port = htons( port ); +} + + +port_t Ipv6Address::GetPort() +{ + return ntohs( m_addr.sin6_port ); +} + + +bool Ipv6Address::Resolve(const std::string& hostname,struct in6_addr& a) +{ + struct sockaddr_in6 sa; + memset(&a, 0, sizeof(a)); + if (Utility::isipv6(hostname)) + { + if (!Utility::u2ip(hostname, sa, AI_NUMERICHOST)) + return false; + a = sa.sin6_addr; + return true; + } + if (!Utility::u2ip(hostname, sa)) + return false; + a = sa.sin6_addr; + return true; +} + + +bool Ipv6Address::Reverse(struct in6_addr& a,std::string& name) +{ + struct sockaddr_in6 sa; + memset(&sa, 0, sizeof(sa)); + sa.sin6_family = AF_INET6; + sa.sin6_addr = a; + return Utility::reverse((struct sockaddr *)&sa, sizeof(sa), name); +} + + +std::string Ipv6Address::Convert(bool include_port) +{ + if (include_port) + return Convert(m_addr.sin6_addr) + ":" + Utility::l2string(GetPort()); + return Convert(m_addr.sin6_addr); +} + + +std::string Ipv6Address::Convert(struct in6_addr& a,bool mixed) +{ + char slask[100]; // l2ip temporary + *slask = 0; + unsigned int prev = 0; + bool skipped = false; + bool ok_to_skip = true; + if (mixed) + { + unsigned short x; + unsigned short addr16[8]; + memcpy(addr16, &a, sizeof(addr16)); + for (size_t i = 0; i < 6; i++) + { + x = ntohs(addr16[i]); + if (*slask && (x || !ok_to_skip || prev)) + strcat(slask,":"); + if (x || !ok_to_skip) + { + sprintf(slask + strlen(slask),"%x", x); + if (x && skipped) + ok_to_skip = false; + } + else + { + skipped = true; + } + prev = x; + } + x = ntohs(addr16[6]); + sprintf(slask + strlen(slask),":%u.%u",x / 256,x & 255); + x = ntohs(addr16[7]); + sprintf(slask + strlen(slask),".%u.%u",x / 256,x & 255); + } + else + { + struct sockaddr_in6 sa; + memset(&sa, 0, sizeof(sa)); + sa.sin6_family = AF_INET6; + sa.sin6_addr = a; + std::string name; + Utility::reverse((struct sockaddr *)&sa, sizeof(sa), name, NI_NUMERICHOST); + return name; + } + return slask; +} + + +void Ipv6Address::SetAddress(struct sockaddr *sa) +{ + memcpy(&m_addr, sa, sizeof(struct sockaddr_in6)); +} + + +int Ipv6Address::GetFamily() +{ + return m_addr.sin6_family; +} + + +void Ipv6Address::SetFlowinfo(uint32_t x) +{ + m_addr.sin6_flowinfo = x; +} + + +uint32_t Ipv6Address::GetFlowinfo() +{ + return m_addr.sin6_flowinfo; +} + + +#ifndef _WIN32 +void Ipv6Address::SetScopeId(uint32_t x) +{ + m_addr.sin6_scope_id = x; +} + + +uint32_t Ipv6Address::GetScopeId() +{ + return m_addr.sin6_scope_id; +} +#endif + + +bool Ipv6Address::IsValid() +{ + return m_valid; +} + + +bool Ipv6Address::operator==(SocketAddress& a) +{ + if (a.GetFamily() != GetFamily()) + return false; + if ((socklen_t)a != sizeof(m_addr)) + return false; + struct sockaddr *sa = a; + struct sockaddr_in6 *p = (struct sockaddr_in6 *)sa; + if (p -> sin6_port != m_addr.sin6_port) + return false; + if (memcmp(&p -> sin6_addr, &m_addr.sin6_addr, sizeof(struct in6_addr))) + return false; + return true; +} + + +std::auto_ptr Ipv6Address::GetCopy() +{ + return std::auto_ptr(new Ipv6Address(m_addr)); +} + + +std::string Ipv6Address::Reverse() +{ + std::string tmp; + Reverse(m_addr.sin6_addr, tmp); + return tmp; +} + + +#ifdef SOCKETS_NAMESPACE +} // namespace SOCKETS_NAMESPACE { +#endif +#endif // IPPROTO_IPV6 +#endif // ENABLE_IPV6 + diff --git a/dep/src/sockets/Lock.cpp b/dep/src/sockets/Lock.cpp new file mode 100644 index 00000000000..3f7902e232b --- /dev/null +++ b/dep/src/sockets/Lock.cpp @@ -0,0 +1,55 @@ +/** \file Lock.cpp + ** \date 2005-08-22 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2005,2007 Anders Hedstrom + +This library is made available under the terms of the GNU GPL. + +If you would like to use this library in a closed-source application, +a separate license agreement is available. For information about +the closed-source license agreement for the C++ sockets library, +please visit http://www.alhem.net/Sockets/license.html and/or +email license@alhem.net. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#include "Mutex.h" +#include "Lock.h" + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + + +Lock::Lock(Mutex& m) : m_mutex(m) +{ + m_mutex.Lock(); +} + + +Lock::~Lock() +{ + m_mutex.Unlock(); +} + + + + +#ifdef SOCKETS_NAMESPACE +} +#endif + diff --git a/dep/src/sockets/Makefile.am b/dep/src/sockets/Makefile.am new file mode 100644 index 00000000000..dd74bd959f9 --- /dev/null +++ b/dep/src/sockets/Makefile.am @@ -0,0 +1,47 @@ +# Copyright (C) 2005-2008 MaNGOS +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## Process this file with automake to produce Makefile.in + +## Sub-directories to parse + +## CPP flags for includes, defines, etc. +AM_CPPFLAGS = -I$(srcdir) -I$(srcdir)/../../include/sockets + +## Build MaNGOS shared library and its parts as convenience library. +# All libraries will be convenience libraries. Might be changed to shared +# later. +noinst_LIBRARIES = libmangossockets.a + +libmangossockets_a_SOURCES = \ + Base64.cpp \ + Exception.cpp \ + Ipv4Address.cpp \ + Ipv6Address.cpp \ + Lock.cpp \ + Mutex.cpp \ + Parse.cpp \ + ResolvServer.cpp \ + ResolvSocket.cpp \ + Socket.cpp \ + SocketHandler.cpp \ + StdoutLog.cpp \ + StreamSocket.cpp \ + TcpSocket.cpp \ + Thread.cpp \ + UdpSocket.cpp \ + Utility.cpp \ + socket_include.cpp diff --git a/dep/src/sockets/Mutex.cpp b/dep/src/sockets/Mutex.cpp new file mode 100644 index 00000000000..f7a03c7d990 --- /dev/null +++ b/dep/src/sockets/Mutex.cpp @@ -0,0 +1,81 @@ +/** \file Mutex.cpp + ** \date 2004-10-30 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2004-2007 Anders Hedstrom + +This library is made available under the terms of the GNU GPL. + +If you would like to use this library in a closed-source application, +a separate license agreement is available. For information about +the closed-source license agreement for the C++ sockets library, +please visit http://www.alhem.net/Sockets/license.html and/or +email license@alhem.net. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#include "Mutex.h" + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + + +Mutex::Mutex() +{ +#ifdef _WIN32 + m_mutex = ::CreateMutex(NULL, FALSE, NULL); +#else + pthread_mutex_init(&m_mutex, NULL); +#endif +} + + +Mutex::~Mutex() +{ +#ifdef _WIN32 + ::CloseHandle(m_mutex); +#else + pthread_mutex_destroy(&m_mutex); +#endif +} + + +void Mutex::Lock() +{ +#ifdef _WIN32 + /*DWORD d =*/ WaitForSingleObject(m_mutex, INFINITE); + /// \todo check 'd' for result +#else + pthread_mutex_lock(&m_mutex); +#endif +} + + +void Mutex::Unlock() +{ +#ifdef _WIN32 + ::ReleaseMutex(m_mutex); +#else + pthread_mutex_unlock(&m_mutex); +#endif +} + + +#ifdef SOCKETS_NAMESPACE +} +#endif + diff --git a/dep/src/sockets/Parse.cpp b/dep/src/sockets/Parse.cpp new file mode 100644 index 00000000000..58122c0c96e --- /dev/null +++ b/dep/src/sockets/Parse.cpp @@ -0,0 +1,321 @@ +/** \file Parse.cpp - parse a string + ** + ** Written: 1999-Feb-10 grymse@alhem.net + **/ + +/* +Copyright (C) 1999-2007 Anders Hedstrom + +This library is made available under the terms of the GNU GPL. + +If you would like to use this library in a closed-source application, +a separate license agreement is available. For information about +the closed-source license agreement for the C++ sockets library, +please visit http://www.alhem.net/Sockets/license.html and/or +email license@alhem.net. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#include +#include + +#include "Parse.h" + + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + + +/* implementation of class Parse */ + +Parse::Parse() +:pa_the_str("") +,pa_splits("") +,pa_ord("") +,pa_the_ptr(0) +,pa_breakchar(0) +,pa_enable(0) +,pa_disable(0) +,pa_nospace(0) +,pa_quote(false) +{ +} + +Parse::Parse(const std::string&s) +:pa_the_str(s) +,pa_splits("") +,pa_ord("") +,pa_the_ptr(0) +,pa_breakchar(0) +,pa_enable(0) +,pa_disable(0) +,pa_nospace(0) +,pa_quote(false) +{ +} + +Parse::Parse(const std::string&s,const std::string&sp) +:pa_the_str(s) +,pa_splits(sp) +,pa_ord("") +,pa_the_ptr(0) +,pa_breakchar(0) +,pa_enable(0) +,pa_disable(0) +,pa_nospace(0) +,pa_quote(false) +{ +} + +Parse::Parse(const std::string&s,const std::string&sp,short /*nospace*/) +:pa_the_str(s) +,pa_splits(sp) +,pa_ord("") +,pa_the_ptr(0) +,pa_breakchar(0) +,pa_enable(0) +,pa_disable(0) +,pa_nospace(1) +,pa_quote(false) +{ +} + + +Parse::~Parse() +{ +} + +#define C ((pa_the_ptr l(h); + + if (l.Bind("127.0.0.1", m_port)) + { + return; + } + h.Add(&l); + + m_ready = true; + while (!m_quit && IsRunning() ) + { + h.Select(0, 500000); + } + SetRunning(false); +} + + +void ResolvServer::Quit() +{ + m_quit = true; +} + + +bool ResolvServer::Ready() +{ + return m_ready; +} + + +#ifdef SOCKETS_NAMESPACE +} +#endif + +#endif // ENABLE_RESOLVER + diff --git a/dep/src/sockets/ResolvSocket.cpp b/dep/src/sockets/ResolvSocket.cpp new file mode 100644 index 00000000000..2d9d31d5a4f --- /dev/null +++ b/dep/src/sockets/ResolvSocket.cpp @@ -0,0 +1,436 @@ +/** \file ResolvSocket.cpp + ** \date 2005-03-24 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2004-2007 Anders Hedstrom + +This library is made available under the terms of the GNU GPL. + +If you would like to use this library in a closed-source application, +a separate license agreement is available. For information about +the closed-source license agreement for the C++ sockets library, +please visit http://www.alhem.net/Sockets/license.html and/or +email license@alhem.net. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifdef _WIN32 +#ifdef _MSC_VER +#pragma warning(disable:4786) +#pragma warning(disable:4503) +#endif +#else +#include +#endif +#include "ResolvSocket.h" +#ifdef ENABLE_RESOLVER +#include "Utility.h" +#include "Parse.h" +#include "ISocketHandler.h" +#include "Lock.h" +#include "Mutex.h" + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + +//#ifdef _DEBUG +//#define DEB(x) x +//#else +#define DEB(x) +//#endif + + +// static +ResolvSocket::cache_t ResolvSocket::m_cache; +ResolvSocket::timeout_t ResolvSocket::m_cache_to; +Mutex ResolvSocket::m_cache_mutex; + + +ResolvSocket::ResolvSocket(ISocketHandler& h) +:TcpSocket(h) +,m_bServer(false) +,m_parent(NULL) +#ifdef ENABLE_IPV6 +,m_resolve_ipv6(false) +#endif +,m_cached(false) +{ + SetLineProtocol(); +} + + +ResolvSocket::ResolvSocket(ISocketHandler& h, Socket *parent, const std::string& host, port_t port, bool ipv6) +:TcpSocket(h) +,m_bServer(false) +,m_parent(parent) +,m_resolv_host(host) +,m_resolv_port(port) +#ifdef ENABLE_IPV6 +,m_resolve_ipv6(ipv6) +#endif +,m_cached(false) +{ + SetLineProtocol(); +} + + +ResolvSocket::ResolvSocket(ISocketHandler& h, Socket *parent, ipaddr_t a) +:TcpSocket(h) +,m_bServer(false) +,m_parent(parent) +,m_resolv_port(0) +,m_resolv_address(a) +#ifdef ENABLE_IPV6 +,m_resolve_ipv6(false) +#endif +,m_cached(false) +{ + SetLineProtocol(); +} + + +#ifdef ENABLE_IPV6 +ResolvSocket::ResolvSocket(ISocketHandler& h, Socket *parent, in6_addr& a) +:TcpSocket(h) +,m_bServer(false) +,m_parent(parent) +,m_resolv_port(0) +,m_resolve_ipv6(true) +,m_resolv_address6(a) +,m_cached(false) +{ + SetLineProtocol(); +} +#endif + + +ResolvSocket::~ResolvSocket() +{ +} + + +void ResolvSocket::OnLine(const std::string& line) +{ + Parse pa(line, ":"); + if (m_bServer) + { + m_query = pa.getword(); + m_data = pa.getrest(); +DEB( fprintf(stderr, " *** ResolvSocket server; query=%s, data=%s\n", m_query.c_str(), m_data.c_str());) + // %! check cache + { + Lock lock(m_cache_mutex); + if (m_cache[m_query].find(m_data) != m_cache[m_query].end()) + { + if (time(NULL) - m_cache_to[m_query][m_data] < 3600) // ttl + { + std::string result = m_cache[m_query][m_data]; +DEB(fprintf(stderr, " *** Returning cache for [%s][%s] = '%s'\n", m_query.c_str(), m_data.c_str(), result.c_str());) + Send("Cached\n"); + if (!result.size()) /* failed */ + { + Send("Failed\n\n"); + SetCloseAndDelete(); + return; + } + else + if (m_query == "gethostbyname") + { + Send("A: " + result + "\n\n"); + SetCloseAndDelete(); + return; + } + else +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + if (m_query == "gethostbyname2") + { + Send("AAAA: " + result + "\n\n"); + SetCloseAndDelete(); + return; + } + else +#endif +#endif + if (m_query == "gethostbyaddr") + { + Send("Name: " + result + "\n\n"); + SetCloseAndDelete(); + return; + } + } + } + } + if (!Detach()) // detach failed? + { + SetCloseAndDelete(); + } + return; + } + std::string key = pa.getword(); + std::string value = pa.getrest(); +DEB( fprintf(stderr, " *** ResolvSocket response; %s: %s\n", key.c_str(), value.c_str());) + + if (key == "Cached") + { + m_cached = true; + } + else + if (key == "Failed" && m_parent) + { +DEB( fprintf(stderr, " ************ Resolve failed\n");) + if (Handler().Resolving(m_parent) || Handler().Valid(m_parent)) + { + m_parent -> OnResolveFailed(m_resolv_id); + } + // update cache + if (!m_cached) + { + Lock lock(m_cache_mutex); +DEB(fprintf(stderr, " *** Update cache for [%s][%s] = '%s'\n", m_query.c_str(), m_data.c_str(), value.c_str());) + m_cache[m_query][m_data] = value; + m_cache_to[m_query][m_data] = time(NULL); + } + m_parent = NULL; + } + else + if (key == "Name" && !m_resolv_host.size() && m_parent) + { + if (Handler().Resolving(m_parent) || Handler().Valid(m_parent)) + { + m_parent -> OnReverseResolved(m_resolv_id, value); + } + // update cache + if (!m_cached) + { + Lock lock(m_cache_mutex); +DEB(fprintf(stderr, " *** Update cache for [%s][%s] = '%s'\n", m_query.c_str(), m_data.c_str(), value.c_str());) + m_cache[m_query][m_data] = value; + m_cache_to[m_query][m_data] = time(NULL); + } + m_parent = NULL; + } + else + if (key == "A" && m_parent) + { + if (Handler().Resolving(m_parent) || Handler().Valid(m_parent)) + { + ipaddr_t l; + Utility::u2ip(value, l); // ip2ipaddr_t + m_parent -> OnResolved(m_resolv_id, l, m_resolv_port); + } + // update cache + if (!m_cached) + { + Lock lock(m_cache_mutex); +DEB(fprintf(stderr, " *** Update cache for [%s][%s] = '%s'\n", m_query.c_str(), m_data.c_str(), value.c_str());) + m_cache[m_query][m_data] = value; + m_cache_to[m_query][m_data] = time(NULL); + } + m_parent = NULL; // always use first ip in case there are several + } +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + else + if (key == "AAAA" && m_parent) + { + if (Handler().Resolving(m_parent) || Handler().Valid(m_parent)) + { + in6_addr a; + Utility::u2ip(value, a); + m_parent -> OnResolved(m_resolv_id, a, m_resolv_port); + } + // update cache + if (!m_cached) + { + Lock lock(m_cache_mutex); +DEB(fprintf(stderr, " *** Update cache for [%s][%s] = '%s'\n", m_query.c_str(), m_data.c_str(), value.c_str());) + m_cache[m_query][m_data] = value; + m_cache_to[m_query][m_data] = time(NULL); + } + m_parent = NULL; + } +#endif +#endif +} + + +void ResolvSocket::OnDetached() +{ +DEB( fprintf(stderr, " *** ResolvSocket::OnDetached(); query=%s, data=%s\n", m_query.c_str(), m_data.c_str());) + if (m_query == "gethostbyname") + { + struct sockaddr_in sa; + if (Utility::u2ip(m_data, sa)) + { + std::string ip; + Utility::l2ip(sa.sin_addr, ip); + Send("A: " + ip + "\n"); + } + else + { + Send("Failed\n"); + } + Send("\n"); + } + else +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + if (m_query == "gethostbyname2") + { + struct sockaddr_in6 sa; + if (Utility::u2ip(m_data, sa)) + { + std::string ip; + Utility::l2ip(sa.sin6_addr, ip); + Send("AAAA: " + ip + "\n"); + } + else + { + Send("Failed\n"); + } + Send("\n"); + } + else +#endif +#endif + if (m_query == "gethostbyaddr") + { + if (Utility::isipv4( m_data )) + { + struct sockaddr_in sa; + if (!Utility::u2ip(m_data, sa, AI_NUMERICHOST)) + { + Send("Failed: convert to sockaddr_in failed\n"); + } + else + { + std::string name; + if (!Utility::reverse( (struct sockaddr *)&sa, sizeof(sa), name)) + { + Send("Failed: ipv4 reverse lookup of " + m_data + "\n"); + } + else + { + Send("Name: " + name + "\n"); + } + } + } + else +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + if (Utility::isipv6( m_data )) + { + struct sockaddr_in6 sa; + if (!Utility::u2ip(m_data, sa, AI_NUMERICHOST)) + { + Send("Failed: convert to sockaddr_in6 failed\n"); + } + else + { + std::string name; + if (!Utility::reverse( (struct sockaddr *)&sa, sizeof(sa), name)) + { + Send("Failed: ipv6 reverse lookup of " + m_data + "\n"); + } + else + { + Send("Name: " + name + "\n"); + } + } + } + else +#endif +#endif + { + Send("Failed: malformed address\n"); + } + Send("\n"); + } + else + { + std::string msg = "Unknown query type: " + m_query; + Handler().LogError(this, "OnDetached", 0, msg); + Send("Unknown\n\n"); + } + SetCloseAndDelete(); +} + + +void ResolvSocket::OnConnect() +{ + if (!m_resolv_host.empty()) + { +#ifdef ENABLE_IPV6 + std::string msg = (m_resolve_ipv6 ? "gethostbyname2 " : "gethostbyname ") + m_resolv_host + "\n"; + m_query = m_resolve_ipv6 ? "gethostbyname2" : "gethostbyname"; +#else + std::string msg = "gethostbyname " + m_resolv_host + "\n"; + m_query = "gethostbyname"; +#endif + m_data = m_resolv_host; + Send( msg ); + return; + } +#ifdef ENABLE_IPV6 + if (m_resolve_ipv6) + { + std::string tmp; + Utility::l2ip(m_resolv_address6, tmp); + m_query = "gethostbyaddr"; + m_data = tmp; + std::string msg = "gethostbyaddr " + tmp + "\n"; + Send( msg ); + } +#endif + std::string tmp; + Utility::l2ip(m_resolv_address, tmp); + m_query = "gethostbyaddr"; + m_data = tmp; + std::string msg = "gethostbyaddr " + tmp + "\n"; + Send( msg ); +} + + +void ResolvSocket::OnDelete() +{ + if (m_parent) + { + if (Handler().Resolving(m_parent) || Handler().Valid(m_parent)) + { + m_parent -> OnResolveFailed(m_resolv_id); + } + // update cache + if (!m_cached) + { + Lock lock(m_cache_mutex); + std::string value; +DEB(fprintf(stderr, " *** Update cache for [%s][%s] = '%s'\n", m_query.c_str(), m_data.c_str(), value.c_str());) + m_cache[m_query][m_data] = value; + m_cache_to[m_query][m_data] = time(NULL); + } + m_parent = NULL; + } +} + + +#ifdef SOCKETS_NAMESPACE +} +#endif + +#endif // ENABLE_RESOLVER + diff --git a/dep/src/sockets/Socket.cpp b/dep/src/sockets/Socket.cpp new file mode 100644 index 00000000000..883363eb1dd --- /dev/null +++ b/dep/src/sockets/Socket.cpp @@ -0,0 +1,1898 @@ +/** \file Socket.cpp + ** \date 2004-02-13 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2004-2007 Anders Hedstrom + +This library is made available under the terms of the GNU GPL. + +If you would like to use this library in a closed-source application, +a separate license agreement is available. For information about +the closed-source license agreement for the C++ sockets library, +please visit http://www.alhem.net/Sockets/license.html and/or +email license@alhem.net. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#include "Socket.h" +#ifdef _WIN32 +#ifdef _MSC_VER +#pragma warning(disable:4786) +#endif +#include +#else +#include +#include +#endif +#include +#include + +#include "ISocketHandler.h" +#include "Utility.h" + +#include "SocketAddress.h" +#include "SocketHandler.h" +#ifdef ENABLE_EXCEPTIONS +#include "Exception.h" +#endif +#include "Ipv4Address.h" + +//#ifdef _DEBUG +//#define DEB(x) x; fflush(stderr); +//#else +#define DEB(x) +//#endif + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + + +// statics +#ifdef _WIN32 +WSAInitializer Socket::m_winsock_init; +#endif + + +Socket::Socket(ISocketHandler& h) +//:m_flags(0) +:m_handler(h) +,m_socket( INVALID_SOCKET ) +,m_bDel(false) +,m_bClose(false) +,m_tCreate(time(NULL)) +,m_parent(NULL) +,m_b_disable_read(false) +,m_connected(false) +,m_b_erased_by_handler(false) +,m_tClose(0) +,m_client_remote_address(NULL) +,m_remote_address(NULL) +,m_traffic_monitor(NULL) +,m_bLost(false) +#ifdef HAVE_OPENSSL +,m_b_enable_ssl(false) +,m_b_ssl(false) +,m_b_ssl_server(false) +#endif +#ifdef ENABLE_IPV6 +,m_ipv6(false) +#endif +#ifdef ENABLE_POOL +,m_socket_type(0) +,m_bClient(false) +,m_bRetain(false) +#endif +#ifdef ENABLE_SOCKS4 +,m_bSocks4(false) +,m_socks4_host(h.GetSocks4Host()) +,m_socks4_port(h.GetSocks4Port()) +,m_socks4_userid(h.GetSocks4Userid()) +#endif +#ifdef ENABLE_DETACH +,m_detach(false) +,m_detached(false) +,m_pThread(NULL) +,m_slave_handler(NULL) +#endif +{ +} + + +Socket::~Socket() +{ + Handler().Remove(this); + if (m_socket != INVALID_SOCKET +#ifdef ENABLE_POOL + && !m_bRetain +#endif + ) + { + Close(); + } +} + + +void Socket::Init() +{ +} + + +void Socket::OnRead() +{ +} + + +void Socket::OnWrite() +{ +} + + +void Socket::OnException() +{ + // %! exception doesn't always mean something bad happened, this code should be reworked + // errno valid here? + int err = SoError(); + Handler().LogError(this, "exception on select", err, StrError(err), LOG_LEVEL_FATAL); + SetCloseAndDelete(); +} + + +void Socket::OnDelete() +{ +} + + +void Socket::OnConnect() +{ +} + + +void Socket::OnAccept() +{ +} + + +int Socket::Close() +{ + if (m_socket == INVALID_SOCKET) // this could happen + { + Handler().LogError(this, "Socket::Close", 0, "file descriptor invalid", LOG_LEVEL_WARNING); + return 0; + } + int n; + if ((n = closesocket(m_socket)) == -1) + { + // failed... + Handler().LogError(this, "close", Errno, StrError(Errno), LOG_LEVEL_ERROR); + } + Handler().Set(m_socket, false, false, false); // remove from fd_set's + Handler().AddList(m_socket, LIST_CALLONCONNECT, false); +#ifdef ENABLE_DETACH + Handler().AddList(m_socket, LIST_DETACH, false); +#endif + Handler().AddList(m_socket, LIST_TIMEOUT, false); + Handler().AddList(m_socket, LIST_RETRY, false); + Handler().AddList(m_socket, LIST_CLOSE, false); + m_socket = INVALID_SOCKET; + return n; +} + + +SOCKET Socket::CreateSocket(int af,int type, const std::string& protocol) +{ + struct protoent *p = NULL; + SOCKET s; + +#ifdef ENABLE_POOL + m_socket_type = type; + m_socket_protocol = protocol; +#endif + if (!protocol.empty()) + { + p = getprotobyname( protocol.c_str() ); + if (!p) + { + Handler().LogError(this, "getprotobyname", Errno, StrError(Errno), LOG_LEVEL_FATAL); + SetCloseAndDelete(); +#ifdef ENABLE_EXCEPTIONS + throw Exception(std::string("getprotobyname() failed: ") + StrError(Errno)); +#endif + return INVALID_SOCKET; + } + } + int protno = p ? p -> p_proto : 0; + + s = socket(af, type, protno); + if (s == INVALID_SOCKET) + { + Handler().LogError(this, "socket", Errno, StrError(Errno), LOG_LEVEL_FATAL); + SetCloseAndDelete(); +#ifdef ENABLE_EXCEPTIONS + throw Exception(std::string("socket() failed: ") + StrError(Errno)); +#endif + return INVALID_SOCKET; + } + Attach(s); + OnOptions(af, type, protno, s); + Attach(INVALID_SOCKET); + return s; +} + + +void Socket::Attach(SOCKET s) +{ + m_socket = s; +} + + +SOCKET Socket::GetSocket() +{ + return m_socket; +} + + +void Socket::SetDeleteByHandler(bool x) +{ + m_bDel = x; +} + + +bool Socket::DeleteByHandler() +{ + return m_bDel; +} + + +void Socket::SetCloseAndDelete(bool x) +{ + if (x != m_bClose) + { + Handler().AddList(m_socket, LIST_CLOSE, x); + m_bClose = x; + if (x) + { + m_tClose = time(NULL); + } + } +} + + +bool Socket::CloseAndDelete() +{ + return m_bClose; +} + + +void Socket::SetRemoteAddress(SocketAddress& ad) //struct sockaddr* sa, socklen_t l) +{ + m_remote_address = ad.GetCopy(); +} + + +std::auto_ptr Socket::GetRemoteSocketAddress() +{ + return m_remote_address -> GetCopy(); +} + + +ISocketHandler& Socket::Handler() const +{ +#ifdef ENABLE_DETACH + if (IsDetached()) + return *m_slave_handler; +#endif + return m_handler; +} + + +ISocketHandler& Socket::MasterHandler() const +{ + return m_handler; +} + + +ipaddr_t Socket::GetRemoteIP4() +{ + ipaddr_t l = 0; +#ifdef ENABLE_IPV6 + if (m_ipv6) + { + Handler().LogError(this, "GetRemoteIP4", 0, "get ipv4 address for ipv6 socket", LOG_LEVEL_WARNING); + } +#endif + if (m_remote_address.get() != NULL) + { + struct sockaddr *p = *m_remote_address; + struct sockaddr_in *sa = (struct sockaddr_in *)p; + memcpy(&l, &sa -> sin_addr, sizeof(struct in_addr)); + } + return l; +} + + +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 +struct in6_addr Socket::GetRemoteIP6() +{ + if (!m_ipv6) + { + Handler().LogError(this, "GetRemoteIP6", 0, "get ipv6 address for ipv4 socket", LOG_LEVEL_WARNING); + } + struct sockaddr_in6 fail; + if (m_remote_address.get() != NULL) + { + struct sockaddr *p = *m_remote_address; + memcpy(&fail, p, sizeof(struct sockaddr_in6)); + } + else + { + memset(&fail, 0, sizeof(struct sockaddr_in6)); + } + return fail.sin6_addr; +} +#endif +#endif + + +port_t Socket::GetRemotePort() +{ + if (!m_remote_address.get()) + { + return 0; + } + return m_remote_address -> GetPort(); +} + + +std::string Socket::GetRemoteAddress() +{ + if (!m_remote_address.get()) + { + return ""; + } + return m_remote_address -> Convert(false); +} + + +std::string Socket::GetRemoteHostname() +{ + if (!m_remote_address.get()) + { + return ""; + } + return m_remote_address -> Reverse(); +} + + +bool Socket::SetNonblocking(bool bNb) +{ +#ifdef _WIN32 + unsigned long l = bNb ? 1 : 0; + int n = ioctlsocket(m_socket, FIONBIO, &l); + if (n != 0) + { + Handler().LogError(this, "ioctlsocket(FIONBIO)", Errno, ""); + return false; + } + return true; +#else + if (bNb) + { + if (fcntl(m_socket, F_SETFL, O_NONBLOCK) == -1) + { + Handler().LogError(this, "fcntl(F_SETFL, O_NONBLOCK)", Errno, StrError(Errno), LOG_LEVEL_ERROR); + return false; + } + } + else + { + if (fcntl(m_socket, F_SETFL, 0) == -1) + { + Handler().LogError(this, "fcntl(F_SETFL, 0)", Errno, StrError(Errno), LOG_LEVEL_ERROR); + return false; + } + } + return true; +#endif +} + + +bool Socket::SetNonblocking(bool bNb, SOCKET s) +{ +#ifdef _WIN32 + unsigned long l = bNb ? 1 : 0; + int n = ioctlsocket(s, FIONBIO, &l); + if (n != 0) + { + Handler().LogError(this, "ioctlsocket(FIONBIO)", Errno, ""); + return false; + } + return true; +#else + if (bNb) + { + if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) + { + Handler().LogError(this, "fcntl(F_SETFL, O_NONBLOCK)", Errno, StrError(Errno), LOG_LEVEL_ERROR); + return false; + } + } + else + { + if (fcntl(s, F_SETFL, 0) == -1) + { + Handler().LogError(this, "fcntl(F_SETFL, 0)", Errno, StrError(Errno), LOG_LEVEL_ERROR); + return false; + } + } + return true; +#endif +} + + +void Socket::Set(bool bRead, bool bWrite, bool bException) +{ + Handler().Set(m_socket, bRead, bWrite, bException); +} + + +bool Socket::Ready() +{ + if (m_socket != INVALID_SOCKET && !CloseAndDelete()) + return true; + return false; +} + + +void Socket::OnLine(const std::string& ) +{ +} + + +void Socket::OnConnectFailed() +{ +} + + +Socket *Socket::GetParent() +{ + return m_parent; +} + + +void Socket::SetParent(Socket *x) +{ + m_parent = x; +} + + +port_t Socket::GetPort() +{ + Handler().LogError(this, "GetPort", 0, "GetPort only implemented for ListenSocket", LOG_LEVEL_WARNING); + return 0; +} + + +bool Socket::OnConnectRetry() +{ + return true; +} + + +#ifdef ENABLE_RECONNECT +void Socket::OnReconnect() +{ +} +#endif + + +time_t Socket::Uptime() +{ + return time(NULL) - m_tCreate; +} + + +#ifdef ENABLE_IPV6 +void Socket::SetIpv6(bool x) +{ + m_ipv6 = x; +} + + +bool Socket::IsIpv6() +{ + return m_ipv6; +} +#endif + + +void Socket::DisableRead(bool x) +{ + m_b_disable_read = x; +} + + +bool Socket::IsDisableRead() +{ + return m_b_disable_read; +} + + +void Socket::SendBuf(const char *,size_t,int) +{ +} + + +void Socket::Send(const std::string&,int) +{ +} + + +void Socket::SetConnected(bool x) +{ + m_connected = x; +} + + +bool Socket::IsConnected() +{ + return m_connected; +} + + +void Socket::OnDisconnect() +{ +} + + +void Socket::SetLost() +{ + m_bLost = true; +} + + +bool Socket::Lost() +{ + return m_bLost; +} + + +void Socket::SetErasedByHandler(bool x) +{ + m_b_erased_by_handler = x; +} + + +bool Socket::ErasedByHandler() +{ + return m_b_erased_by_handler; +} + + +time_t Socket::TimeSinceClose() +{ + return time(NULL) - m_tClose; +} + + +void Socket::SetClientRemoteAddress(SocketAddress& ad) +{ + if (!ad.IsValid()) + { + Handler().LogError(this, "SetClientRemoteAddress", 0, "remote address not valid", LOG_LEVEL_ERROR); + } + m_client_remote_address = ad.GetCopy(); +} + + +std::auto_ptr Socket::GetClientRemoteAddress() +{ + if (!m_client_remote_address.get()) + { + Handler().LogError(this, "GetClientRemoteAddress", 0, "remote address not yet set", LOG_LEVEL_ERROR); + } + return m_client_remote_address -> GetCopy(); +} + + +uint64_t Socket::GetBytesSent(bool) +{ + return 0; +} + + +uint64_t Socket::GetBytesReceived(bool) +{ + return 0; +} + + +#ifdef HAVE_OPENSSL +void Socket::OnSSLConnect() +{ +} + + +void Socket::OnSSLAccept() +{ +} + + +bool Socket::SSLNegotiate() +{ + return false; +} + + +bool Socket::IsSSL() +{ + return m_b_enable_ssl; +} + + +void Socket::EnableSSL(bool x) +{ + m_b_enable_ssl = x; +} + + +bool Socket::IsSSLNegotiate() +{ + return m_b_ssl; +} + + +void Socket::SetSSLNegotiate(bool x) +{ + m_b_ssl = x; +} + + +bool Socket::IsSSLServer() +{ + return m_b_ssl_server; +} + + +void Socket::SetSSLServer(bool x) +{ + m_b_ssl_server = x; +} + + +void Socket::OnSSLConnectFailed() +{ +} + + +void Socket::OnSSLAcceptFailed() +{ +} +#endif // HAVE_OPENSSL + + +#ifdef ENABLE_POOL +void Socket::CopyConnection(Socket *sock) +{ + Attach( sock -> GetSocket() ); +#ifdef ENABLE_IPV6 + SetIpv6( sock -> IsIpv6() ); +#endif + SetSocketType( sock -> GetSocketType() ); + SetSocketProtocol( sock -> GetSocketProtocol() ); + + SetClientRemoteAddress( *sock -> GetClientRemoteAddress() ); + SetRemoteAddress( *sock -> GetRemoteSocketAddress() ); +} + + +void Socket::SetIsClient() +{ + m_bClient = true; +} + + +void Socket::SetSocketType(int x) +{ + m_socket_type = x; +} + + +int Socket::GetSocketType() +{ + return m_socket_type; +} + + +void Socket::SetSocketProtocol(const std::string& x) +{ + m_socket_protocol = x; +} + + +const std::string& Socket::GetSocketProtocol() +{ + return m_socket_protocol; +} + + +void Socket::SetRetain() +{ + if (m_bClient) m_bRetain = true; +} + + +bool Socket::Retain() +{ + return m_bRetain; +} + + +#endif // ENABLE_POOL + + +#ifdef ENABLE_SOCKS4 +void Socket::OnSocks4Connect() +{ + Handler().LogError(this, "OnSocks4Connect", 0, "Use with TcpSocket only"); +} + + +void Socket::OnSocks4ConnectFailed() +{ + Handler().LogError(this, "OnSocks4ConnectFailed", 0, "Use with TcpSocket only"); +} + + +bool Socket::OnSocks4Read() +{ + Handler().LogError(this, "OnSocks4Read", 0, "Use with TcpSocket only"); + return true; +} + + +void Socket::SetSocks4Host(const std::string& host) +{ + Utility::u2ip(host, m_socks4_host); +} + + +bool Socket::Socks4() +{ + return m_bSocks4; +} + + +void Socket::SetSocks4(bool x) +{ + m_bSocks4 = x; +} + + +void Socket::SetSocks4Host(ipaddr_t a) +{ + m_socks4_host = a; +} + + +void Socket::SetSocks4Port(port_t p) +{ + m_socks4_port = p; +} + + +void Socket::SetSocks4Userid(const std::string& x) +{ + m_socks4_userid = x; +} + + +ipaddr_t Socket::GetSocks4Host() +{ + return m_socks4_host; +} + + +port_t Socket::GetSocks4Port() +{ + return m_socks4_port; +} + + +const std::string& Socket::GetSocks4Userid() +{ + return m_socks4_userid; +} +#endif // ENABLE_SOCKS4 + + +#ifdef ENABLE_DETACH +bool Socket::Detach() +{ + if (!DeleteByHandler()) + return false; + if (m_pThread) + return false; + if (m_detached) + return false; + SetDetach(); + return true; +} + + +void Socket::DetachSocket() +{ + SetDetached(); + m_pThread = new SocketThread(this); + m_pThread -> SetRelease(true); +} + + +void Socket::OnDetached() +{ +} + + +void Socket::SetDetach(bool x) +{ + Handler().AddList(m_socket, LIST_DETACH, x); + m_detach = x; +} + + +bool Socket::IsDetach() +{ + return m_detach; +} + + +void Socket::SetDetached(bool x) +{ + m_detached = x; +} + + +const bool Socket::IsDetached() const +{ + return m_detached; +} + + +void Socket::SetSlaveHandler(ISocketHandler *p) +{ + m_slave_handler = p; +} + + +Socket::SocketThread::SocketThread(Socket *p) +:Thread(false) +,m_socket(p) +{ + // Creator will release +} + + +Socket::SocketThread::~SocketThread() +{ + if (IsRunning()) + { + SetRelease(true); + SetRunning(false); +#ifdef _WIN32 + Sleep(1000); +#else + sleep(1); +#endif + } +} + + +void Socket::SocketThread::Run() +{ + SocketHandler h; + h.SetSlave(); + h.Add(m_socket); + m_socket -> SetSlaveHandler(&h); + m_socket -> OnDetached(); + while (h.GetCount() && IsRunning()) + { + h.Select(0, 500000); + } + // m_socket now deleted oops + // yeah oops m_socket delete its socket thread, that means this + // so Socket will no longer delete its socket thread, instead we do this: + SetDeleteOnExit(); +} +#endif // ENABLE_DETACH + + +#ifdef ENABLE_RESOLVER +int Socket::Resolve(const std::string& host,port_t port) +{ + return Handler().Resolve(this, host, port); +} + + +#ifdef ENABLE_IPV6 +int Socket::Resolve6(const std::string& host,port_t port) +{ + return Handler().Resolve6(this, host, port); +} +#endif + + +int Socket::Resolve(ipaddr_t a) +{ + return Handler().Resolve(this, a); +} + + +#ifdef ENABLE_IPV6 +int Socket::Resolve(in6_addr& a) +{ + return Handler().Resolve(this, a); +} +#endif + + +void Socket::OnResolved(int,ipaddr_t,port_t) +{ +} + + +#ifdef ENABLE_IPV6 +void Socket::OnResolved(int,in6_addr&,port_t) +{ +} +#endif + + +void Socket::OnReverseResolved(int,const std::string&) +{ +} + + +void Socket::OnResolveFailed(int) +{ +} +#endif // ENABLE_RESOLVER + + +/* IP options */ + + +bool Socket::SetIpOptions(const void *p, socklen_t len) +{ +#ifdef IP_OPTIONS + if (setsockopt(GetSocket(), IPPROTO_IP, IP_OPTIONS, (char *)p, len) == -1) + { + Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_OPTIONS)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +#else + Handler().LogError(this, "ip option not available", 0, "IP_OPTIONS", LOG_LEVEL_INFO); + return false; +#endif +} + + +#ifdef IP_PKTINFO +bool Socket::SetIpPktinfo(bool x) +{ + int optval = x ? 1 : 0; + if (setsockopt(GetSocket(), IPPROTO_IP, IP_PKTINFO, (char *)&optval, sizeof(optval)) == -1) + { + Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_PKTINFO)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +} +#endif + + +#ifdef IP_RECVTOS +bool Socket::SetIpRecvTOS(bool x) +{ + int optval = x ? 1 : 0; + if (setsockopt(GetSocket(), IPPROTO_IP, IP_RECVTOS, (char *)&optval, sizeof(optval)) == -1) + { + Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_RECVTOS)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +} +#endif + + +#ifdef IP_RECVTTL +bool Socket::SetIpRecvTTL(bool x) +{ + int optval = x ? 1 : 0; + if (setsockopt(GetSocket(), IPPROTO_IP, IP_RECVTTL, (char *)&optval, sizeof(optval)) == -1) + { + Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_RECVTTL)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +} +#endif + + +#ifdef IP_RECVOPTS +bool Socket::SetIpRecvopts(bool x) +{ + int optval = x ? 1 : 0; + if (setsockopt(GetSocket(), IPPROTO_IP, IP_RECVOPTS, (char *)&optval, sizeof(optval)) == -1) + { + Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_RECVOPTS)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +} +#endif + + +#ifdef IP_RETOPTS +bool Socket::SetIpRetopts(bool x) +{ + int optval = x ? 1 : 0; + if (setsockopt(GetSocket(), IPPROTO_IP, IP_RETOPTS, (char *)&optval, sizeof(optval)) == -1) + { + Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_RETOPTS)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +} +#endif + + +bool Socket::SetIpTOS(unsigned char tos) +{ +#ifdef IP_TOS + if (setsockopt(GetSocket(), IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(tos)) == -1) + { + Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_TOS)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +#else + Handler().LogError(this, "ip option not available", 0, "IP_TOS", LOG_LEVEL_INFO); + return false; +#endif +} + + +unsigned char Socket::IpTOS() +{ + unsigned char tos = 0; +#ifdef IP_TOS + socklen_t len = sizeof(tos); + if (getsockopt(GetSocket(), IPPROTO_IP, IP_TOS, (char *)&tos, &len) == -1) + { + Handler().LogError(this, "getsockopt(IPPROTO_IP, IP_TOS)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + } +#else + Handler().LogError(this, "ip option not available", 0, "IP_TOS", LOG_LEVEL_INFO); +#endif + return tos; +} + + +bool Socket::SetIpTTL(int ttl) +{ +#ifdef IP_TTL + if (setsockopt(GetSocket(), IPPROTO_IP, IP_TTL, (char *)&ttl, sizeof(ttl)) == -1) + { + Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_TTL)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +#else + Handler().LogError(this, "ip option not available", 0, "IP_TTL", LOG_LEVEL_INFO); + return false; +#endif +} + + +int Socket::IpTTL() +{ + int ttl = 0; +#ifdef IP_TTL + socklen_t len = sizeof(ttl); + if (getsockopt(GetSocket(), IPPROTO_IP, IP_TTL, (char *)&ttl, &len) == -1) + { + Handler().LogError(this, "getsockopt(IPPROTO_IP, IP_TTL)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + } +#else + Handler().LogError(this, "ip option not available", 0, "IP_TTL", LOG_LEVEL_INFO); +#endif + return ttl; +} + + +bool Socket::SetIpHdrincl(bool x) +{ +#ifdef IP_HDRINCL + int optval = x ? 1 : 0; + if (setsockopt(GetSocket(), IPPROTO_IP, IP_HDRINCL, (char *)&optval, sizeof(optval)) == -1) + { + Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_HDRINCL)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +#else + Handler().LogError(this, "ip option not available", 0, "IP_HDRINCL", LOG_LEVEL_INFO); + return false; +#endif +} + + +#ifdef IP_RECVERR +bool Socket::SetIpRecverr(bool x) +{ + int optval = x ? 1 : 0; + if (setsockopt(GetSocket(), IPPROTO_IP, IP_RECVERR, (char *)&optval, sizeof(optval)) == -1) + { + Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_RECVERR)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +} +#endif + + +#ifdef IP_MTU_DISCOVER +bool Socket::SetIpMtudiscover(bool x) +{ + int optval = x ? 1 : 0; + if (setsockopt(GetSocket(), IPPROTO_IP, IP_MTU_DISCOVER, (char *)&optval, sizeof(optval)) == -1) + { + Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_MTU_DISCOVER)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +} +#endif + + +#ifdef IP_MTU +int Socket::IpMtu() +{ + int mtu = 0; + socklen_t len = sizeof(mtu); + if (getsockopt(GetSocket(), IPPROTO_IP, IP_MTU, (char *)&mtu, &len) == -1) + { + Handler().LogError(this, "getsockopt(IPPROTO_IP, IP_MTU)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + } + return mtu; +} +#endif + + +#ifdef IP_ROUTER_ALERT +bool Socket::SetIpRouterAlert(bool x) +{ + int optval = x ? 1 : 0; + if (setsockopt(GetSocket(), IPPROTO_IP, IP_ROUTER_ALERT, (char *)&optval, sizeof(optval)) == -1) + { + Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_ROUTER_ALERT)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +} +#endif + + +bool Socket::SetIpMulticastTTL(int ttl) +{ +#ifdef IP_MULTICAST_TTL + if (setsockopt(GetSocket(), IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttl, sizeof(ttl)) == -1) + { + Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_MULTICAST_TTL)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +#else + Handler().LogError(this, "ip option not available", 0, "IP_MULTICAST_TTL", LOG_LEVEL_INFO); + return false; +#endif +} + + +int Socket::IpMulticastTTL() +{ + int ttl = 0; +#ifdef IP_MULTICAST_TTL + socklen_t len = sizeof(ttl); + if (getsockopt(GetSocket(), IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttl, &len) == -1) + { + Handler().LogError(this, "getsockopt(IPPROTO_IP, IP_MULTICAST_TTL)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + } +#else + Handler().LogError(this, "ip option not available", 0, "IP_MULTICAST_TTL", LOG_LEVEL_INFO); +#endif + return ttl; +} + + +bool Socket::SetMulticastLoop(bool x) +{ +#ifdef IP_MULTICAST_LOOP + int optval = x ? 1 : 0; + if (setsockopt(GetSocket(), IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&optval, sizeof(optval)) == -1) + { + Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_MULTICAST_LOOP)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +#else + Handler().LogError(this, "ip option not available", 0, "IP_MULTICAST_LOOP", LOG_LEVEL_INFO); + return false; +#endif +} + + +#ifdef LINUX +bool Socket::IpAddMembership(struct ip_mreqn& ref) +{ +#ifdef IP_ADD_MEMBERSHIP + if (setsockopt(GetSocket(), IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&ref, sizeof(struct ip_mreqn)) == -1) + { + Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_ADD_MEMBERSHIP)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +#else + Handler().LogError(this, "ip option not available", 0, "IP_ADD_MEMBERSHIP", LOG_LEVEL_INFO); + return false; +#endif +} +#endif + + +bool Socket::IpAddMembership(struct ip_mreq& ref) +{ +#ifdef IP_ADD_MEMBERSHIP + if (setsockopt(GetSocket(), IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&ref, sizeof(struct ip_mreq)) == -1) + { + Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_ADD_MEMBERSHIP)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +#else + Handler().LogError(this, "ip option not available", 0, "IP_ADD_MEMBERSHIP", LOG_LEVEL_INFO); + return false; +#endif +} + + +#ifdef LINUX +bool Socket::IpDropMembership(struct ip_mreqn& ref) +{ +#ifdef IP_DROP_MEMBERSHIP + if (setsockopt(GetSocket(), IPPROTO_IP, IP_DROP_MEMBERSHIP, (char *)&ref, sizeof(struct ip_mreqn)) == -1) + { + Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_DROP_MEMBERSHIP)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +#else + Handler().LogError(this, "ip option not available", 0, "IP_DROP_MEMBERSHIP", LOG_LEVEL_INFO); + return false; +#endif +} +#endif + + +bool Socket::IpDropMembership(struct ip_mreq& ref) +{ +#ifdef IP_DROP_MEMBERSHIP + if (setsockopt(GetSocket(), IPPROTO_IP, IP_DROP_MEMBERSHIP, (char *)&ref, sizeof(struct ip_mreq)) == -1) + { + Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_DROP_MEMBERSHIP)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +#else + Handler().LogError(this, "ip option not available", 0, "IP_DROP_MEMBERSHIP", LOG_LEVEL_INFO); + return false; +#endif +} + + +/* SOCKET options */ + + +bool Socket::SetSoReuseaddr(bool x) +{ +#ifdef SO_REUSEADDR + int optval = x ? 1 : 0; + if (setsockopt(GetSocket(), SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval)) == -1) + { + Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_REUSEADDR)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +#else + Handler().LogError(this, "socket option not available", 0, "SO_REUSEADDR", LOG_LEVEL_INFO); + return false; +#endif +} + + +bool Socket::SetSoKeepalive(bool x) +{ +#ifdef SO_KEEPALIVE + int optval = x ? 1 : 0; + if (setsockopt(GetSocket(), SOL_SOCKET, SO_KEEPALIVE, (char *)&optval, sizeof(optval)) == -1) + { + Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_KEEPALIVE)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +#else + Handler().LogError(this, "socket option not available", 0, "SO_KEEPALIVE", LOG_LEVEL_INFO); + return false; +#endif +} + + +#ifdef SO_NOSIGPIPE +bool Socket::SetSoNosigpipe(bool x) +{ + int optval = x ? 1 : 0; + if (setsockopt(GetSocket(), SOL_SOCKET, SO_NOSIGPIPE, (char *)&optval, sizeof(optval)) == -1) + { + Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_NOSIGPIPE)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +} +#endif + + +bool Socket::SoAcceptconn() +{ + int value = 0; +#ifdef SO_ACCEPTCONN + socklen_t len = sizeof(value); + if (getsockopt(GetSocket(), SOL_SOCKET, SO_ACCEPTCONN, (char *)&value, &len) == -1) + { + Handler().LogError(this, "getsockopt(SOL_SOCKET, SO_ACCEPTCONN)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + } +#else + Handler().LogError(this, "socket option not available", 0, "SO_ACCEPTCONN", LOG_LEVEL_INFO); +#endif + return value ? true : false; +} + + +#ifdef SO_BSDCOMPAT +bool Socket::SetSoBsdcompat(bool x) +{ + int optval = x ? 1 : 0; + if (setsockopt(GetSocket(), SOL_SOCKET, SO_BSDCOMPAT, (char *)&optval, sizeof(optval)) == -1) + { + Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_BSDCOMPAT)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +} +#endif + + +#ifdef SO_BINDTODEVICE +bool Socket::SetSoBindtodevice(const std::string& intf) +{ + if (setsockopt(GetSocket(), SOL_SOCKET, SO_BINDTODEVICE, (char *)intf.c_str(), intf.size()) == -1) + { + Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_BINDTODEVICE)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +} +#endif + + +bool Socket::SetSoBroadcast(bool x) +{ +#ifdef SO_BROADCAST + int optval = x ? 1 : 0; + if (setsockopt(GetSocket(), SOL_SOCKET, SO_BROADCAST, (char *)&optval, sizeof(optval)) == -1) + { + Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_BROADCAST)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +#else + Handler().LogError(this, "socket option not available", 0, "SO_BROADCAST", LOG_LEVEL_INFO); + return false; +#endif +} + + +bool Socket::SetSoDebug(bool x) +{ +#ifdef SO_DEBUG + int optval = x ? 1 : 0; + if (setsockopt(GetSocket(), SOL_SOCKET, SO_DEBUG, (char *)&optval, sizeof(optval)) == -1) + { + Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_DEBUG)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +#else + Handler().LogError(this, "socket option not available", 0, "SO_DEBUG", LOG_LEVEL_INFO); + return false; +#endif +} + + +int Socket::SoError() +{ + int value = 0; +#ifdef SO_ERROR + socklen_t len = sizeof(value); + if (getsockopt(GetSocket(), SOL_SOCKET, SO_ERROR, (char *)&value, &len) == -1) + { + Handler().LogError(this, "getsockopt(SOL_SOCKET, SO_ERROR)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + } +#else + Handler().LogError(this, "socket option not available", 0, "SO_ERROR", LOG_LEVEL_INFO); +#endif + return value; +} + + +bool Socket::SetSoDontroute(bool x) +{ +#ifdef SO_DONTROUTE + int optval = x ? 1 : 0; + if (setsockopt(GetSocket(), SOL_SOCKET, SO_DONTROUTE, (char *)&optval, sizeof(optval)) == -1) + { + Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_DONTROUTE)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +#else + Handler().LogError(this, "socket option not available", 0, "SO_DONTROUTE", LOG_LEVEL_INFO); + return false; +#endif +} + + +bool Socket::SetSoLinger(int onoff, int linger) +{ +#ifdef SO_LINGER + struct linger stl; + stl.l_onoff = onoff; + stl.l_linger = linger; + if (setsockopt(GetSocket(), SOL_SOCKET, SO_LINGER, (char *)&stl, sizeof(stl)) == -1) + { + Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_LINGER)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +#else + Handler().LogError(this, "socket option not available", 0, "SO_LINGER", LOG_LEVEL_INFO); + return false; +#endif +} + + +bool Socket::SetSoOobinline(bool x) +{ +#ifdef SO_OOBINLINE + int optval = x ? 1 : 0; + if (setsockopt(GetSocket(), SOL_SOCKET, SO_OOBINLINE, (char *)&optval, sizeof(optval)) == -1) + { + Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_OOBINLINE)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +#else + Handler().LogError(this, "socket option not available", 0, "SO_OOBINLINE", LOG_LEVEL_INFO); + return false; +#endif +} + + +#ifdef SO_PASSCRED +bool Socket::SetSoPasscred(bool x) +{ + int optval = x ? 1 : 0; + if (setsockopt(GetSocket(), SOL_SOCKET, SO_PASSCRED, (char *)&optval, sizeof(optval)) == -1) + { + Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_PASSCRED)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +} +#endif + + +#ifdef SO_PEERCRED +bool Socket::SoPeercred(struct ucred& ucr) +{ + if (setsockopt(GetSocket(), SOL_SOCKET, SO_PEERCRED, (char *)&ucr, sizeof(ucr)) == -1) + { + Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_PEERCRED)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +} +#endif + + +#ifdef SO_PRIORITY +bool Socket::SetSoPriority(int x) +{ + if (setsockopt(GetSocket(), SOL_SOCKET, SO_PRIORITY, (char *)&x, sizeof(x)) == -1) + { + Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_PRIORITY)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +} +#endif + + +bool Socket::SetSoRcvlowat(int x) +{ +#ifdef SO_RCVLOWAT + if (setsockopt(GetSocket(), SOL_SOCKET, SO_RCVLOWAT, (char *)&x, sizeof(x)) == -1) + { + Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_RCVLOWAT)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +#else + Handler().LogError(this, "socket option not available", 0, "SO_RCVLOWAT", LOG_LEVEL_INFO); + return false; +#endif +} + + +bool Socket::SetSoSndlowat(int x) +{ +#ifdef SO_SNDLOWAT + if (setsockopt(GetSocket(), SOL_SOCKET, SO_SNDLOWAT, (char *)&x, sizeof(x)) == -1) + { + Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_SNDLOWAT)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +#else + Handler().LogError(this, "socket option not available", 0, "SO_SNDLOWAT", LOG_LEVEL_INFO); + return false; +#endif +} + + +bool Socket::SetSoRcvtimeo(struct timeval& tv) +{ +#ifdef SO_RCVTIMEO + if (setsockopt(GetSocket(), SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)) == -1) + { + Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_RCVTIMEO)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +#else + Handler().LogError(this, "socket option not available", 0, "SO_RCVTIMEO", LOG_LEVEL_INFO); + return false; +#endif +} + + +bool Socket::SetSoSndtimeo(struct timeval& tv) +{ +#ifdef SO_SNDTIMEO + if (setsockopt(GetSocket(), SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv)) == -1) + { + Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_SNDTIMEO)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +#else + Handler().LogError(this, "socket option not available", 0, "SO_SNDTIMEO", LOG_LEVEL_INFO); + return false; +#endif +} + + +bool Socket::SetSoRcvbuf(int x) +{ +#ifdef SO_RCVBUF + if (setsockopt(GetSocket(), SOL_SOCKET, SO_RCVBUF, (char *)&x, sizeof(x)) == -1) + { + Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_RCVBUF)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +#else + Handler().LogError(this, "socket option not available", 0, "SO_RCVBUF", LOG_LEVEL_INFO); + return false; +#endif +} + + +int Socket::SoRcvbuf() +{ + int value = 0; +#ifdef SO_RCVBUF + socklen_t len = sizeof(value); + if (getsockopt(GetSocket(), SOL_SOCKET, SO_RCVBUF, (char *)&value, &len) == -1) + { + Handler().LogError(this, "getsockopt(SOL_SOCKET, SO_RCVBUF)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + } +#else + Handler().LogError(this, "socket option not available", 0, "SO_RCVBUF", LOG_LEVEL_INFO); +#endif + return value; +} + + +#ifdef SO_RCVBUFFORCE +bool Socket::SetSoRcvbufforce(int x) +{ + if (setsockopt(GetSocket(), SOL_SOCKET, SO_RCVBUFFORCE, (char *)&x, sizeof(x)) == -1) + { + Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_RCVBUFFORCE)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +} +#endif + + +bool Socket::SetSoSndbuf(int x) +{ +#ifdef SO_SNDBUF + if (setsockopt(GetSocket(), SOL_SOCKET, SO_SNDBUF, (char *)&x, sizeof(x)) == -1) + { + Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_SNDBUF)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +#else + Handler().LogError(this, "socket option not available", 0, "SO_SNDBUF", LOG_LEVEL_INFO); + return false; +#endif +} + + +int Socket::SoSndbuf() +{ + int value = 0; +#ifdef SO_SNDBUF + socklen_t len = sizeof(value); + if (getsockopt(GetSocket(), SOL_SOCKET, SO_SNDBUF, (char *)&value, &len) == -1) + { + Handler().LogError(this, "getsockopt(SOL_SOCKET, SO_SNDBUF)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + } +#else + Handler().LogError(this, "socket option not available", 0, "SO_SNDBUF", LOG_LEVEL_INFO); +#endif + return value; +} + + +#ifdef SO_SNDBUFFORCE +bool Socket::SetSoSndbufforce(int x) +{ + if (setsockopt(GetSocket(), SOL_SOCKET, SO_SNDBUFFORCE, (char *)&x, sizeof(x)) == -1) + { + Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_SNDBUFFORCE)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +} +#endif + + +#ifdef SO_TIMESTAMP +bool Socket::SetSoTimestamp(bool x) +{ + int optval = x ? 1 : 0; + if (setsockopt(GetSocket(), SOL_SOCKET, SO_TIMESTAMP, (char *)&optval, sizeof(optval)) == -1) + { + Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_TIMESTAMP)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +} +#endif + + +int Socket::SoType() +{ + int value = 0; +#ifdef SO_TYPE + socklen_t len = sizeof(value); + if (getsockopt(GetSocket(), SOL_SOCKET, SO_TYPE, (char *)&value, &len) == -1) + { + Handler().LogError(this, "getsockopt(SOL_SOCKET, SO_TYPE)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + } +#else + Handler().LogError(this, "socket option not available", 0, "SO_TYPE", LOG_LEVEL_INFO); +#endif + return value; +} + + +#ifdef ENABLE_TRIGGERS +void Socket::Subscribe(int id) +{ + Handler().Subscribe(id, this); +} + + +void Socket::Unsubscribe(int id) +{ + Handler().Unsubscribe(id, this); +} + + +void Socket::OnTrigger(int, const TriggerData&) +{ +} + + +void Socket::OnCancelled(int) +{ +} +#endif + + +void Socket::SetTimeout(time_t secs) +{ + if (!secs) + { + Handler().AddList(m_socket, LIST_TIMEOUT, false); + return; + } + Handler().AddList(m_socket, LIST_TIMEOUT, true); + m_timeout_start = time(NULL); + m_timeout_limit = secs; +} + + +void Socket::OnTimeout() +{ +} + + +void Socket::OnConnectTimeout() +{ +} + + +bool Socket::Timeout(time_t tnow) +{ + if (tnow - m_timeout_start > m_timeout_limit) + return true; + return false; +} + + +/** Returns local port number for bound socket file descriptor. */ +port_t Socket::GetSockPort() +{ +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + if (IsIpv6()) + { + struct sockaddr_in6 sa; + socklen_t sockaddr_length = sizeof(struct sockaddr_in6); + if (getsockname(GetSocket(), (struct sockaddr *)&sa, (socklen_t*)&sockaddr_length) == -1) + memset(&sa, 0, sizeof(sa)); + return ntohs(sa.sin6_port); + } +#endif +#endif + struct sockaddr_in sa; + socklen_t sockaddr_length = sizeof(struct sockaddr_in); + if (getsockname(GetSocket(), (struct sockaddr *)&sa, (socklen_t*)&sockaddr_length) == -1) + memset(&sa, 0, sizeof(sa)); + return ntohs(sa.sin_port); +} + + +/** Returns local ipv4 address for bound socket file descriptor. */ +ipaddr_t Socket::GetSockIP4() +{ +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + if (IsIpv6()) + { + return 0; + } +#endif +#endif + struct sockaddr_in sa; + socklen_t sockaddr_length = sizeof(struct sockaddr_in); + if (getsockname(GetSocket(), (struct sockaddr *)&sa, (socklen_t*)&sockaddr_length) == -1) + memset(&sa, 0, sizeof(sa)); + ipaddr_t a; + memcpy(&a, &sa.sin_addr, 4); + return a; +} + + +/** Returns local ipv4 address as text for bound socket file descriptor. */ +std::string Socket::GetSockAddress() +{ +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + if (IsIpv6()) + { + return ""; + } +#endif +#endif + struct sockaddr_in sa; + socklen_t sockaddr_length = sizeof(struct sockaddr_in); + if (getsockname(GetSocket(), (struct sockaddr *)&sa, (socklen_t*)&sockaddr_length) == -1) + memset(&sa, 0, sizeof(sa)); + Ipv4Address addr( sa ); + return addr.Convert(); +} + + +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 +/** Returns local ipv6 address for bound socket file descriptor. */ +struct in6_addr Socket::GetSockIP6() +{ + if (IsIpv6()) + { + struct sockaddr_in6 sa; + socklen_t sockaddr_length = sizeof(struct sockaddr_in6); + if (getsockname(GetSocket(), (struct sockaddr *)&sa, (socklen_t*)&sockaddr_length) == -1) + memset(&sa, 0, sizeof(sa)); + return sa.sin6_addr; + } + struct in6_addr a; + memset(&a, 0, sizeof(a)); + return a; +} + + +/** Returns local ipv6 address as text for bound socket file descriptor. */ +std::string Socket::GetSockAddress6() +{ + if (IsIpv6()) + { + struct sockaddr_in6 sa; + socklen_t sockaddr_length = sizeof(struct sockaddr_in6); + if (getsockname(GetSocket(), (struct sockaddr *)&sa, (socklen_t*)&sockaddr_length) == -1) + memset(&sa, 0, sizeof(sa)); + Ipv6Address addr( sa ); + return addr.Convert(); + } + return ""; +} +#endif +#endif + + +#ifdef SOCKETS_NAMESPACE +} +#endif + diff --git a/dep/src/sockets/SocketHandler.cpp b/dep/src/sockets/SocketHandler.cpp new file mode 100644 index 00000000000..9ec5412af38 --- /dev/null +++ b/dep/src/sockets/SocketHandler.cpp @@ -0,0 +1,1422 @@ +/** \file SocketHandler.cpp + ** \date 2004-02-13 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2004-2007 Anders Hedstrom + +This library is made available under the terms of the GNU GPL. + +If you would like to use this library in a closed-source application, +a separate license agreement is available. For information about +the closed-source license agreement for the C++ sockets library, +please visit http://www.alhem.net/Sockets/license.html and/or +email license@alhem.net. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifdef _WIN32 +#ifdef _MSC_VER +#pragma warning(disable:4786) +#endif +#endif +#include +#include + +#include "SocketHandler.h" +#include "UdpSocket.h" +#include "ResolvSocket.h" +#include "ResolvServer.h" +#include "TcpSocket.h" +#include "Mutex.h" +#include "Utility.h" +#include "SocketAddress.h" + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + + +//#ifdef _DEBUG +//#define DEB(x) x; fflush(stderr); +//#else +#define DEB(x) +//#endif + + +SocketHandler::SocketHandler(StdLog *p) +:m_stdlog(p) +,m_mutex(m_mutex) +,m_b_use_mutex(false) +,m_maxsock(0) +,m_preverror(-1) +,m_errcnt(0) +,m_tlast(0) +#ifdef ENABLE_SOCKS4 +,m_socks4_host(0) +,m_socks4_port(0) +,m_bTryDirect(false) +#endif +#ifdef ENABLE_RESOLVER +,m_resolv_id(0) +,m_resolver(NULL) +#endif +#ifdef ENABLE_POOL +,m_b_enable_pool(false) +#endif +#ifdef ENABLE_TRIGGERS +,m_next_trigger_id(0) +#endif +#ifdef ENABLE_DETACH +,m_slave(false) +#endif +{ + FD_ZERO(&m_rfds); + FD_ZERO(&m_wfds); + FD_ZERO(&m_efds); +} + + +SocketHandler::SocketHandler(Mutex& mutex,StdLog *p) +:m_stdlog(p) +,m_mutex(mutex) +,m_b_use_mutex(true) +,m_maxsock(0) +,m_preverror(-1) +,m_errcnt(0) +,m_tlast(0) +#ifdef ENABLE_SOCKS4 +,m_socks4_host(0) +,m_socks4_port(0) +,m_bTryDirect(false) +#endif +#ifdef ENABLE_RESOLVER +,m_resolv_id(0) +,m_resolver(NULL) +#endif +#ifdef ENABLE_POOL +,m_b_enable_pool(false) +#endif +#ifdef ENABLE_TRIGGERS +,m_next_trigger_id(0) +#endif +#ifdef ENABLE_DETACH +,m_slave(false) +#endif +{ + m_mutex.Lock(); + FD_ZERO(&m_rfds); + FD_ZERO(&m_wfds); + FD_ZERO(&m_efds); +} + + +SocketHandler::~SocketHandler() +{ +#ifdef ENABLE_RESOLVER + if (m_resolver) + { + m_resolver -> Quit(); + } +#endif + { + while (m_sockets.size()) + { +DEB( fprintf(stderr, "Emptying sockets list in SocketHandler destructor, %d instances\n", (int)m_sockets.size());) + socket_m::iterator it = m_sockets.begin(); + Socket *p = it -> second; + if (p) + { +DEB( fprintf(stderr, " fd %d\n", p -> GetSocket());) + p -> Close(); +DEB( fprintf(stderr, " fd closed %d\n", p -> GetSocket());) +// p -> OnDelete(); // hey, I turn this back on. what's the worst that could happen??!! + // MinionSocket breaks, calling MinderHandler methods in OnDelete - + // MinderHandler is already gone when that happens... + + // only delete socket when controlled + // ie master sockethandler can delete non-detached sockets + // and a slave sockethandler can only delete a detach socket + if (p -> DeleteByHandler() +#ifdef ENABLE_DETACH + && !(m_slave ^ p -> IsDetached()) +#endif + ) + { + p -> SetErasedByHandler(); + delete p; + } + m_sockets.erase(it); + } + else + { + m_sockets.erase(it); + } +DEB( fprintf(stderr, "next\n");) + } +DEB( fprintf(stderr, "/Emptying sockets list in SocketHandler destructor, %d instances\n", (int)m_sockets.size());) + } +#ifdef ENABLE_RESOLVER + if (m_resolver) + { + delete m_resolver; + } +#endif + if (m_b_use_mutex) + { + m_mutex.Unlock(); + } +} + + +Mutex& SocketHandler::GetMutex() const +{ + return m_mutex; +} + + +#ifdef ENABLE_DETACH +void SocketHandler::SetSlave(bool x) +{ + m_slave = x; +} + + +bool SocketHandler::IsSlave() +{ + return m_slave; +} +#endif + + +void SocketHandler::RegStdLog(StdLog *log) +{ + m_stdlog = log; +} + + +void SocketHandler::LogError(Socket *p,const std::string& user_text,int err,const std::string& sys_err,loglevel_t t) +{ + if (m_stdlog) + { + m_stdlog -> error(this, p, user_text, err, sys_err, t); + } +} + + +void SocketHandler::Add(Socket *p) +{ + if (p -> GetSocket() == INVALID_SOCKET) + { + LogError(p, "Add", -1, "Invalid socket", LOG_LEVEL_WARNING); + if (p -> CloseAndDelete()) + { + m_delete.push_back(p); + } + return; + } + if (m_add.find(p -> GetSocket()) != m_add.end()) + { + LogError(p, "Add", (int)p -> GetSocket(), "Attempt to add socket already in add queue", LOG_LEVEL_FATAL); + m_delete.push_back(p); + return; + } + m_add[p -> GetSocket()] = p; +} + + +void SocketHandler::Get(SOCKET s,bool& r,bool& w,bool& e) +{ + if (s >= 0) + { + r = FD_ISSET(s, &m_rfds) ? true : false; + w = FD_ISSET(s, &m_wfds) ? true : false; + e = FD_ISSET(s, &m_efds) ? true : false; + } +} + + +void SocketHandler::Set(SOCKET s,bool bRead,bool bWrite,bool bException) +{ +DEB( fprintf(stderr, "Set(%d, %s, %s, %s)\n", s, bRead ? "true" : "false", bWrite ? "true" : "false", bException ? "true" : "false");) + if (s >= 0) + { + if (bRead) + { + if (!FD_ISSET(s, &m_rfds)) + { + FD_SET(s, &m_rfds); + } + } + else + { + FD_CLR(s, &m_rfds); + } + if (bWrite) + { + if (!FD_ISSET(s, &m_wfds)) + { + FD_SET(s, &m_wfds); + } + } + else + { + FD_CLR(s, &m_wfds); + } + if (bException) + { + if (!FD_ISSET(s, &m_efds)) + { + FD_SET(s, &m_efds); + } + } + else + { + FD_CLR(s, &m_efds); + } + } +} + + +int SocketHandler::Select(long sec,long usec) +{ + struct timeval tv; + tv.tv_sec = sec; + tv.tv_usec = usec; + return Select(&tv); +} + + +int SocketHandler::Select() +{ + if (!m_fds_callonconnect.empty() || +#ifdef ENABLE_DETACH + (!m_slave && !m_fds_detach.empty()) || +#endif + !m_fds_timeout.empty() || + !m_fds_retry.empty() || + !m_fds_close.empty() || + !m_fds_erase.empty()) + { + return Select(0, 200000); + } + return Select(NULL); +} + + +int SocketHandler::Select(struct timeval *tsel) +{ + size_t ignore = 0; + while (m_add.size() > ignore) + { + if (m_sockets.size() >= FD_SETSIZE) + { + LogError(NULL, "Select", (int)m_sockets.size(), "FD_SETSIZE reached", LOG_LEVEL_WARNING); + break; + } + socket_m::iterator it = m_add.begin(); + SOCKET s = it -> first; + Socket *p = it -> second; +DEB( fprintf(stderr, "Trying to add fd %d, m_add.size() %d, ignore %d\n", (int)s, (int)m_add.size(), (int)ignore);) + // + if (m_sockets.find(p -> GetSocket()) != m_sockets.end()) + { + LogError(p, "Add", (int)p -> GetSocket(), "Attempt to add socket already in controlled queue", LOG_LEVEL_FATAL); + // %! it's a dup, don't add to delete queue, just ignore it + m_delete.push_back(p); + m_add.erase(it); +// ignore++; + continue; + } + if (!p -> CloseAndDelete()) + { + StreamSocket *scp = dynamic_cast(p); + if (scp && scp -> Connecting()) // 'Open' called before adding socket + { + Set(s,false,true); + } + else + { + TcpSocket *tcp = dynamic_cast(p); + bool bWrite = tcp ? tcp -> GetOutputLength() != 0 : false; + if (p -> IsDisableRead()) + { + Set(s, false, bWrite); + } + else + { + Set(s, true, bWrite); + } + } + m_maxsock = (s > m_maxsock) ? s : m_maxsock; + } + else + { + LogError(p, "Add", (int)p -> GetSocket(), "Trying to add socket with SetCloseAndDelete() true", LOG_LEVEL_WARNING); + } + // only add to m_fds (process fd_set events) if + // slave handler and detached/detaching socket + // master handler and non-detached socket +#ifdef ENABLE_DETACH + if (!(m_slave ^ p -> IsDetach())) +#endif + { + m_fds.push_back(s); + } + m_sockets[s] = p; + // + m_add.erase(it); + } +#ifdef MACOSX + fd_set rfds; + fd_set wfds; + fd_set efds; + FD_COPY(&m_rfds, &rfds); + FD_COPY(&m_wfds, &wfds); + FD_COPY(&m_efds, &efds); +#else + fd_set rfds = m_rfds; + fd_set wfds = m_wfds; + fd_set efds = m_efds; +#endif + int n; + if (m_b_use_mutex) + { + m_mutex.Unlock(); + n = select( (int)(m_maxsock + 1),&rfds,&wfds,&efds,tsel); + m_mutex.Lock(); + } + else + { + n = select( (int)(m_maxsock + 1),&rfds,&wfds,&efds,tsel); + } + if (n == -1) + { + /* + EBADF An invalid file descriptor was given in one of the sets. + EINTR A non blocked signal was caught. + EINVAL n is negative. Or struct timeval contains bad time values (<0). + ENOMEM select was unable to allocate memory for internal tables. + */ + if (Errno != m_preverror || m_errcnt++ % 10000 == 0) + { + LogError(NULL, "select", Errno, StrError(Errno)); +DEB( fprintf(stderr, "m_maxsock: %d\n", m_maxsock); + fprintf(stderr, "%s\n", Errno == EINVAL ? "EINVAL" : + Errno == EINTR ? "EINTR" : + Errno == EBADF ? "EBADF" : + Errno == ENOMEM ? "ENOMEM" : ""); + // test bad fd + for (SOCKET i = 0; i <= m_maxsock; i++) + { + bool t = false; + FD_ZERO(&rfds); + FD_ZERO(&wfds); + FD_ZERO(&efds); + if (FD_ISSET(i, &m_rfds)) + { + FD_SET(i, &rfds); + t = true; + } + if (FD_ISSET(i, &m_wfds)) + { + FD_SET(i, &wfds); + t = true; + } + if (FD_ISSET(i, &m_efds)) + { + FD_SET(i, &efds); + t = true; + } + if (t && m_sockets.find(i) == m_sockets.end()) + { + fprintf(stderr, "Bad fd in fd_set: %d\n", i); + } + } +) // DEB + m_preverror = Errno; + } + /// \todo rebuild fd_set's from active sockets list (m_sockets) here + } + else + if (!n) + { + m_preverror = -1; + } + else + if (n > 0) + { + for (socket_v::iterator it2 = m_fds.begin(); it2 != m_fds.end() && n; it2++) + { + SOCKET i = *it2; + if (FD_ISSET(i, &rfds)) + { + socket_m::iterator itmp = m_sockets.find(i); + if (itmp != m_sockets.end()) // found + { + Socket *p = itmp -> second; + // new SSL negotiate method +#ifdef HAVE_OPENSSL + if (p -> IsSSLNegotiate()) + { + p -> SSLNegotiate(); + } + else +#endif + { + p -> OnRead(); + } + } + else + { + LogError(NULL, "GetSocket/handler/1", (int)i, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING); + } + n--; + } + if (FD_ISSET(i, &wfds)) + { + socket_m::iterator itmp = m_sockets.find(i); + if (itmp != m_sockets.end()) // found + { + Socket *p = itmp -> second; + // new SSL negotiate method +#ifdef HAVE_OPENSSL + if (p -> IsSSLNegotiate()) + { + p -> SSLNegotiate(); + } + else +#endif + { + p -> OnWrite(); + } + } + else + { + LogError(NULL, "GetSocket/handler/2", (int)i, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING); + } + n--; + } + if (FD_ISSET(i, &efds)) + { + socket_m::iterator itmp = m_sockets.find(i); + if (itmp != m_sockets.end()) // found + { + Socket *p = itmp -> second; + p -> OnException(); + } + else + { + LogError(NULL, "GetSocket/handler/3", (int)i, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING); + } + n--; + } + } // m_fds loop + m_preverror = -1; + } // if (n > 0) + + // check CallOnConnect - EVENT + if (!m_fds_callonconnect.empty()) + { + socket_v tmp = m_fds_callonconnect; + for (socket_v::iterator it = tmp.begin(); it != tmp.end(); it++) + { + Socket *p = NULL; + { + socket_m::iterator itmp = m_sockets.find(*it); + if (itmp != m_sockets.end()) // found + { + p = itmp -> second; + } + else + { + LogError(NULL, "GetSocket/handler/4", (int)*it, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING); + } + } + if (p) + { +// if (p -> CallOnConnect() && p -> Ready() ) + { + p -> SetConnected(); // moved here from inside if (tcp) check below +#ifdef HAVE_OPENSSL + if (p -> IsSSL()) // SSL Enabled socket + p -> OnSSLConnect(); + else +#endif +#ifdef ENABLE_SOCKS4 + if (p -> Socks4()) + p -> OnSocks4Connect(); + else +#endif + { + TcpSocket *tcp = dynamic_cast(p); + if (tcp) + { + if (tcp -> GetOutputLength()) + { + p -> OnWrite(); + } + } +#ifdef ENABLE_RECONNECT + if (tcp && tcp -> IsReconnect()) + p -> OnReconnect(); + else +#endif + { +// LogError(p, "Calling OnConnect", 0, "Because CallOnConnect", LOG_LEVEL_INFO); + p -> OnConnect(); + } + } +// p -> SetCallOnConnect( false ); + AddList(p -> GetSocket(), LIST_CALLONCONNECT, false); + } + } + } + } +#ifdef ENABLE_DETACH + // check detach of socket if master handler - EVENT + if (!m_slave && !m_fds_detach.empty()) + { + // %! why not using tmp list here??!? + for (socket_v::iterator it = m_fds_detach.begin(); it != m_fds_detach.end(); it++) + { + Socket *p = NULL; + { + socket_m::iterator itmp = m_sockets.find(*it); + if (itmp != m_sockets.end()) // found + { + p = itmp -> second; + } + else + { + LogError(NULL, "GetSocket/handler/5", (int)*it, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING); + } + } + if (p) + { +// if (p -> IsDetach()) + { + Set(p -> GetSocket(), false, false, false); + // After DetachSocket(), all calls to Handler() will return a reference + // to the new slave SocketHandler running in the new thread. + p -> DetachSocket(); + // Adding the file descriptor to m_fds_erase will now also remove the + // socket from the detach queue - tnx knightmad + m_fds_erase.push_back(p -> GetSocket()); + } + } + } + } +#endif + // check Connecting - connection timeout - conditional event + if (m_fds_timeout.size()) + { + time_t tnow = time(NULL); + if (tnow != m_tlast) + { + socket_v tmp = m_fds_timeout; +DEB( fprintf(stderr, "Checking %d socket(s) for timeout\n", tmp.size());) + for (socket_v::iterator it = tmp.begin(); it != tmp.end(); it++) + { + Socket *p = NULL; + { + socket_m::iterator itmp = m_sockets.find(*it); + if (itmp != m_sockets.end()) // found + { + p = itmp -> second; + } + else + { + itmp = m_add.find(*it); + if (itmp != m_add.end()) + { + p = itmp -> second; + } + else + { + LogError(NULL, "GetSocket/handler/6", (int)*it, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING); + } + } + } + if (p) + { + if (p -> Timeout(tnow)) + { + StreamSocket *scp = dynamic_cast(p); + if (scp && scp -> Connecting()) + p -> OnConnectTimeout(); + else + p -> OnTimeout(); + p -> SetTimeout(0); + } + } + } + m_tlast = tnow; + } // tnow != tlast + } + // check retry client connect - EVENT + if (!m_fds_retry.empty()) + { + socket_v tmp = m_fds_retry; + for (socket_v::iterator it = tmp.begin(); it != tmp.end(); it++) + { + Socket *p = NULL; + { + socket_m::iterator itmp = m_sockets.find(*it); + if (itmp != m_sockets.end()) // found + { + p = itmp -> second; + } + else + { + LogError(NULL, "GetSocket/handler/7", (int)*it, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING); + } + } + if (p) + { +// if (p -> RetryClientConnect()) + { + TcpSocket *tcp = dynamic_cast(p); + SOCKET nn = *it; //(*it3).first; + tcp -> SetRetryClientConnect(false); +DEB( fprintf(stderr, "Close() before retry client connect\n");) + p -> Close(); // removes from m_fds_retry + std::auto_ptr ad = p -> GetClientRemoteAddress(); + if (ad.get()) + { + tcp -> Open(*ad); + } + else + { + LogError(p, "RetryClientConnect", 0, "no address", LOG_LEVEL_ERROR); + } + Add(p); + m_fds_erase.push_back(nn); + } + } + } + } + // check close and delete - conditional event + if (!m_fds_close.empty()) + { + socket_v tmp = m_fds_close; +DEB( fprintf(stderr, "m_fds_close.size() == %d\n", (int)m_fds_close.size());) + for (socket_v::iterator it = tmp.begin(); it != tmp.end(); it++) + { + Socket *p = NULL; + { + socket_m::iterator itmp = m_sockets.find(*it); + if (itmp != m_sockets.end()) // found + { + p = itmp -> second; + } + else + { + itmp = m_add.find(*it); + if (itmp != m_add.end()) + { + p = itmp -> second; + } + else + { + LogError(NULL, "GetSocket/handler/8", (int)*it, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING); + } + } + } + if (p) + { +// if (p -> CloseAndDelete() ) + { + TcpSocket *tcp = dynamic_cast(p); + // new graceful tcp - flush and close timeout 5s + if (tcp && p -> IsConnected() && tcp -> GetFlushBeforeClose() && +#ifdef HAVE_OPENSSL + !tcp -> IsSSL() && +#endif + p -> TimeSinceClose() < 5) + { +DEB( fprintf(stderr, " close(1)\n");) + if (tcp -> GetOutputLength()) + { + LogError(p, "Closing", (int)tcp -> GetOutputLength(), "Sending all data before closing", LOG_LEVEL_INFO); + } + else // shutdown write when output buffer is empty + if (!(tcp -> GetShutdown() & SHUT_WR)) + { + SOCKET nn = *it; + if (nn != INVALID_SOCKET && shutdown(nn, SHUT_WR) == -1) + { + LogError(p, "graceful shutdown", Errno, StrError(Errno), LOG_LEVEL_ERROR); + } + tcp -> SetShutdown(SHUT_WR); + } + } + else +#ifdef ENABLE_RECONNECT + if (tcp && p -> IsConnected() && tcp -> Reconnect()) + { + SOCKET nn = *it; //(*it3).first; +DEB( fprintf(stderr, " close(2) fd %d\n", nn);) + p -> SetCloseAndDelete(false); + tcp -> SetIsReconnect(); + p -> SetConnected(false); +DEB( fprintf(stderr, "Close() before reconnect\n");) + p -> Close(); // dispose of old file descriptor (Open creates a new) + p -> OnDisconnect(); + std::auto_ptr ad = p -> GetClientRemoteAddress(); + if (ad.get()) + { + tcp -> Open(*ad); + } + else + { + LogError(p, "Reconnect", 0, "no address", LOG_LEVEL_ERROR); + } + tcp -> ResetConnectionRetries(); + Add(p); + m_fds_erase.push_back(nn); + } + else +#endif + { + SOCKET nn = *it; //(*it3).first; +DEB( fprintf(stderr, " close(3) fd %d GetSocket() %d\n", nn, p -> GetSocket());) + if (tcp && p -> IsConnected() && tcp -> GetOutputLength()) + { + LogError(p, "Closing", (int)tcp -> GetOutputLength(), "Closing socket while data still left to send", LOG_LEVEL_WARNING); + } +#ifdef ENABLE_POOL + if (p -> Retain() && !p -> Lost()) + { + PoolSocket *p2 = new PoolSocket(*this, p); + p2 -> SetDeleteByHandler(); + Add(p2); + // + p -> SetCloseAndDelete(false); // added - remove from m_fds_close + } + else +#endif // ENABLE_POOL + { + Set(p -> GetSocket(),false,false,false); +DEB( fprintf(stderr, "Close() before OnDelete\n");) + p -> Close(); + } + p -> OnDelete(); + if (p -> DeleteByHandler()) + { + p -> SetErasedByHandler(); + } + m_fds_erase.push_back(nn); + } + } + } + } + } + + // check erased sockets + bool check_max_fd = false; + while (!m_fds_erase.empty()) + { + socket_v::iterator it = m_fds_erase.begin(); + SOCKET nn = *it; +#ifdef ENABLE_DETACH + { + for (socket_v::iterator it = m_fds_detach.begin(); it != m_fds_detach.end(); it++) + { + if (*it == nn) + { + m_fds_detach.erase(it); + break; + } + } + } +#endif + { + for (socket_v::iterator it = m_fds.begin(); it != m_fds.end(); it++) + { + if (*it == nn) + { + m_fds.erase(it); + break; + } + } + } + { + socket_m::iterator it = m_sockets.find(nn); + if (it != m_sockets.end()) + { + Socket *p = it -> second; + /* Sometimes a SocketThread class can finish its run before the master + sockethandler gets here. In that case, the SocketThread has set the + 'ErasedByHandler' flag on the socket which will make us end up with a + double delete on the socket instance. + The fix is to make sure that the master sockethandler only can delete + non-detached sockets, and a slave sockethandler only can delete + detach sockets. */ + if (p -> ErasedByHandler() +#ifdef ENABLE_DETACH + && !(m_slave ^ p -> IsDetached()) +#endif + ) + { +#ifdef ENABLE_TRIGGERS + bool again = false; + do + { + again = false; + for (std::map::iterator it = m_trigger_src.begin(); it != m_trigger_src.end(); it++) + { + int id = it -> first; + Socket *src = it -> second; + if (src == p) + { + for (std::map::iterator it = m_trigger_dst[id].begin(); it != m_trigger_dst[id].end(); it++) + { + Socket *dst = it -> first; + if (Valid(dst)) + { + dst -> OnCancelled(id); + } + } + m_trigger_src.erase(m_trigger_src.find(id)); + m_trigger_dst.erase(m_trigger_dst.find(id)); + again = true; + break; + } + } + } while (again); +#endif + delete p; + } + m_sockets.erase(it); + } + } + m_fds_erase.erase(it); + check_max_fd = true; + } + // calculate max file descriptor for select() call + if (check_max_fd) + { + m_maxsock = 0; + for (socket_v::iterator it = m_fds.begin(); it != m_fds.end(); it++) + { + SOCKET s = *it; + m_maxsock = s > m_maxsock ? s : m_maxsock; + } + } + // remove Add's that fizzed + while (!m_delete.empty()) + { + std::list::iterator it = m_delete.begin(); + Socket *p = *it; + p -> OnDelete(); + m_delete.erase(it); + if (p -> DeleteByHandler() +#ifdef ENABLE_DETACH + && !(m_slave ^ p -> IsDetached()) +#endif + ) + { + p -> SetErasedByHandler(); +#ifdef ENABLE_TRIGGERS + bool again = false; + do + { + again = false; + for (std::map::iterator it = m_trigger_src.begin(); it != m_trigger_src.end(); it++) + { + int id = it -> first; + Socket *src = it -> second; + if (src == p) + { + for (std::map::iterator it = m_trigger_dst[id].begin(); it != m_trigger_dst[id].end(); it++) + { + Socket *dst = it -> first; + if (Valid(dst)) + { + dst -> OnCancelled(id); + } + } + m_trigger_src.erase(m_trigger_src.find(id)); + m_trigger_dst.erase(m_trigger_dst.find(id)); + again = true; + break; + } + } + } while (again); +#endif + delete p; + } + } + return n; +} + + +#ifdef ENABLE_RESOLVER +bool SocketHandler::Resolving(Socket *p0) +{ + std::map::iterator it = m_resolve_q.find(p0); + return it != m_resolve_q.end(); +} +#endif + + +bool SocketHandler::Valid(Socket *p0) +{ + for (socket_m::iterator it = m_sockets.begin(); it != m_sockets.end(); it++) + { + Socket *p = it -> second; + if (p0 == p) + return true; + } + return false; +} + + +bool SocketHandler::OkToAccept(Socket *) +{ + return true; +} + + +size_t SocketHandler::GetCount() +{ +/* +printf(" m_sockets : %d\n", m_sockets.size()); +printf(" m_add : %d\n", m_add.size()); +printf(" m_delete : %d\n", m_delete.size()); +*/ + return m_sockets.size() + m_add.size() + m_delete.size(); +} + + +#ifdef ENABLE_SOCKS4 +void SocketHandler::SetSocks4Host(ipaddr_t a) +{ + m_socks4_host = a; +} + + +void SocketHandler::SetSocks4Host(const std::string& host) +{ + Utility::u2ip(host, m_socks4_host); +} + + +void SocketHandler::SetSocks4Port(port_t port) +{ + m_socks4_port = port; +} + + +void SocketHandler::SetSocks4Userid(const std::string& id) +{ + m_socks4_userid = id; +} +#endif + + +#ifdef ENABLE_RESOLVER +int SocketHandler::Resolve(Socket *p,const std::string& host,port_t port) +{ + // check cache + ResolvSocket *resolv = new ResolvSocket(*this, p, host, port); + resolv -> SetId(++m_resolv_id); + resolv -> SetDeleteByHandler(); + ipaddr_t local; + Utility::u2ip("127.0.0.1", local); + if (!resolv -> Open(local, m_resolver_port)) + { + LogError(resolv, "Resolve", -1, "Can't connect to local resolve server", LOG_LEVEL_FATAL); + } + Add(resolv); + m_resolve_q[p] = true; +DEB( fprintf(stderr, " *** Resolve '%s:%d' id#%d m_resolve_q size: %d p: %p\n", host.c_str(), port, resolv -> GetId(), m_resolve_q.size(), p);) + return resolv -> GetId(); +} + + +#ifdef ENABLE_IPV6 +int SocketHandler::Resolve6(Socket *p,const std::string& host,port_t port) +{ + // check cache + ResolvSocket *resolv = new ResolvSocket(*this, p, host, port, true); + resolv -> SetId(++m_resolv_id); + resolv -> SetDeleteByHandler(); + ipaddr_t local; + Utility::u2ip("127.0.0.1", local); + if (!resolv -> Open(local, m_resolver_port)) + { + LogError(resolv, "Resolve", -1, "Can't connect to local resolve server", LOG_LEVEL_FATAL); + } + Add(resolv); + m_resolve_q[p] = true; + return resolv -> GetId(); +} +#endif + + +int SocketHandler::Resolve(Socket *p,ipaddr_t a) +{ + // check cache + ResolvSocket *resolv = new ResolvSocket(*this, p, a); + resolv -> SetId(++m_resolv_id); + resolv -> SetDeleteByHandler(); + ipaddr_t local; + Utility::u2ip("127.0.0.1", local); + if (!resolv -> Open(local, m_resolver_port)) + { + LogError(resolv, "Resolve", -1, "Can't connect to local resolve server", LOG_LEVEL_FATAL); + } + Add(resolv); + m_resolve_q[p] = true; + return resolv -> GetId(); +} + + +#ifdef ENABLE_IPV6 +int SocketHandler::Resolve(Socket *p,in6_addr& a) +{ + // check cache + ResolvSocket *resolv = new ResolvSocket(*this, p, a); + resolv -> SetId(++m_resolv_id); + resolv -> SetDeleteByHandler(); + ipaddr_t local; + Utility::u2ip("127.0.0.1", local); + if (!resolv -> Open(local, m_resolver_port)) + { + LogError(resolv, "Resolve", -1, "Can't connect to local resolve server", LOG_LEVEL_FATAL); + } + Add(resolv); + m_resolve_q[p] = true; + return resolv -> GetId(); +} +#endif + + +void SocketHandler::EnableResolver(port_t port) +{ + if (!m_resolver) + { + m_resolver_port = port; + m_resolver = new ResolvServer(port); + } +} + + +bool SocketHandler::ResolverReady() +{ + return m_resolver ? m_resolver -> Ready() : false; +} +#endif // ENABLE_RESOLVER + + +#ifdef ENABLE_SOCKS4 +void SocketHandler::SetSocks4TryDirect(bool x) +{ + m_bTryDirect = x; +} + + +ipaddr_t SocketHandler::GetSocks4Host() +{ + return m_socks4_host; +} + + +port_t SocketHandler::GetSocks4Port() +{ + return m_socks4_port; +} + + +const std::string& SocketHandler::GetSocks4Userid() +{ + return m_socks4_userid; +} + + +bool SocketHandler::Socks4TryDirect() +{ + return m_bTryDirect; +} +#endif + + +#ifdef ENABLE_RESOLVER +bool SocketHandler::ResolverEnabled() +{ + return m_resolver ? true : false; +} + + +port_t SocketHandler::GetResolverPort() +{ + return m_resolver_port; +} +#endif // ENABLE_RESOLVER + + +#ifdef ENABLE_POOL +ISocketHandler::PoolSocket *SocketHandler::FindConnection(int type,const std::string& protocol,SocketAddress& ad) +{ + for (socket_m::iterator it = m_sockets.begin(); it != m_sockets.end() && !m_sockets.empty(); it++) + { + PoolSocket *pools = dynamic_cast(it -> second); + if (pools) + { + if (pools -> GetSocketType() == type && + pools -> GetSocketProtocol() == protocol && +// %! pools -> GetClientRemoteAddress() && + *pools -> GetClientRemoteAddress() == ad) + { + m_sockets.erase(it); + pools -> SetRetain(); // avoid Close in Socket destructor + return pools; // Caller is responsible that this socket is deleted + } + } + } + return NULL; +} + + +void SocketHandler::EnablePool(bool x) +{ + m_b_enable_pool = x; +} + + +bool SocketHandler::PoolEnabled() +{ + return m_b_enable_pool; +} +#endif + + +void SocketHandler::Remove(Socket *p) +{ +#ifdef ENABLE_RESOLVER + std::map::iterator it4 = m_resolve_q.find(p); + if (it4 != m_resolve_q.end()) + m_resolve_q.erase(it4); +#endif + if (p -> ErasedByHandler()) + { + return; + } + for (socket_m::iterator it = m_sockets.begin(); it != m_sockets.end(); it++) + { + if (it -> second == p) + { + LogError(p, "Remove", -1, "Socket destructor called while still in use", LOG_LEVEL_WARNING); + m_sockets.erase(it); + return; + } + } + for (socket_m::iterator it2 = m_add.begin(); it2 != m_add.end(); it2++) + { + if ((*it2).second == p) + { + LogError(p, "Remove", -2, "Socket destructor called while still in use", LOG_LEVEL_WARNING); + m_add.erase(it2); + return; + } + } + for (std::list::iterator it3 = m_delete.begin(); it3 != m_delete.end(); it3++) + { + if (*it3 == p) + { + LogError(p, "Remove", -3, "Socket destructor called while still in use", LOG_LEVEL_WARNING); + m_delete.erase(it3); + return; + } + } +} + + +void SocketHandler::CheckSanity() +{ + CheckList(m_fds, "active sockets"); // active sockets + CheckList(m_fds_erase, "sockets to be erased"); // should always be empty anyway + CheckList(m_fds_callonconnect, "checklist CallOnConnect"); +#ifdef ENABLE_DETACH + CheckList(m_fds_detach, "checklist Detach"); +#endif + CheckList(m_fds_timeout, "checklist Timeout"); + CheckList(m_fds_retry, "checklist retry client connect"); + CheckList(m_fds_close, "checklist close and delete"); +} + + +void SocketHandler::CheckList(socket_v& ref,const std::string& listname) +{ + for (socket_v::iterator it = ref.begin(); it != ref.end(); it++) + { + SOCKET s = *it; + if (m_sockets.find(s) != m_sockets.end()) + continue; + if (m_add.find(s) != m_add.end()) + continue; + bool found = false; + for (std::list::iterator it = m_delete.begin(); it != m_delete.end(); it++) + { + Socket *p = *it; + if (p -> GetSocket() == s) + { + found = true; + break; + } + } + if (!found) + { + fprintf(stderr, "CheckList failed for \"%s\": fd %d\n", listname.c_str(), s); + } + } +} + + +void SocketHandler::AddList(SOCKET s,list_t which_one,bool add) +{ + if (s == INVALID_SOCKET) + { +DEB( fprintf(stderr, "AddList: invalid_socket\n");) + return; + } + socket_v& ref = + (which_one == LIST_CALLONCONNECT) ? m_fds_callonconnect : +#ifdef ENABLE_DETACH + (which_one == LIST_DETACH) ? m_fds_detach : +#endif + (which_one == LIST_TIMEOUT) ? m_fds_timeout : + (which_one == LIST_RETRY) ? m_fds_retry : + (which_one == LIST_CLOSE) ? m_fds_close : m_fds_close; + if (add) + { +#ifdef ENABLE_DETACH +DEB( fprintf(stderr, "AddList; %5d: %s: %s\n", s, (which_one == LIST_CALLONCONNECT) ? "CallOnConnect" : + (which_one == LIST_DETACH) ? "Detach" : + (which_one == LIST_TIMEOUT) ? "Timeout" : + (which_one == LIST_RETRY) ? "Retry" : + (which_one == LIST_CLOSE) ? "Close" : "", + add ? "Add" : "Remove");) +#else +DEB( fprintf(stderr, "AddList; %5d: %s: %s\n", s, (which_one == LIST_CALLONCONNECT) ? "CallOnConnect" : + (which_one == LIST_TIMEOUT) ? "Timeout" : + (which_one == LIST_RETRY) ? "Retry" : + (which_one == LIST_CLOSE) ? "Close" : "", + add ? "Add" : "Remove");) +#endif + } + if (add) + { + for (socket_v::iterator it = ref.begin(); it != ref.end(); it++) + { + if (*it == s) // already there + { + return; + } + } + ref.push_back(s); + return; + } + // remove + for (socket_v::iterator it = ref.begin(); it != ref.end(); it++) + { + if (*it == s) + { + ref.erase(it); + break; + } + } +//DEB( fprintf(stderr, "/AddList\n");) +} + + +#ifdef ENABLE_TRIGGERS +int SocketHandler::TriggerID(Socket *src) +{ + int id = m_next_trigger_id++; + m_trigger_src[id] = src; + return id; +} + + +bool SocketHandler::Subscribe(int id, Socket *dst) +{ + if (m_trigger_src.find(id) != m_trigger_src.end()) + { + std::map::iterator it = m_trigger_dst[id].find(dst); + if (it != m_trigger_dst[id].end()) + { + m_trigger_dst[id][dst] = true; + return true; + } + LogError(dst, "Subscribe", id, "Already subscribed", LOG_LEVEL_INFO); + return false; + } + LogError(dst, "Subscribe", id, "Trigger id not found", LOG_LEVEL_INFO); + return false; +} + + +bool SocketHandler::Unsubscribe(int id, Socket *dst) +{ + if (m_trigger_src.find(id) != m_trigger_src.end()) + { + std::map::iterator it = m_trigger_dst[id].find(dst); + if (it != m_trigger_dst[id].end()) + { + m_trigger_dst[id].erase(it); + return true; + } + LogError(dst, "Unsubscribe", id, "Not subscribed", LOG_LEVEL_INFO); + return false; + } + LogError(dst, "Unsubscribe", id, "Trigger id not found", LOG_LEVEL_INFO); + return false; +} + + +void SocketHandler::Trigger(int id, Socket::TriggerData& data, bool erase) +{ + if (m_trigger_src.find(id) != m_trigger_src.end()) + { + data.SetSource( m_trigger_src[id] ); + for (std::map::iterator it = m_trigger_dst[id].begin(); it != m_trigger_dst[id].end(); it++) + { + Socket *dst = it -> first; + if (Valid(dst)) + { + dst -> OnTrigger(id, data); + } + } + if (erase) + { + m_trigger_src.erase(m_trigger_src.find(id)); + m_trigger_dst.erase(m_trigger_dst.find(id)); + } + } + else + { + LogError(NULL, "Trigger", id, "Trigger id not found", LOG_LEVEL_INFO); + } +} +#endif // ENABLE_TRIGGERS + + +#ifdef SOCKETS_NAMESPACE +} +#endif + diff --git a/dep/src/sockets/StdoutLog.cpp b/dep/src/sockets/StdoutLog.cpp new file mode 100644 index 00000000000..c01d8b8c215 --- /dev/null +++ b/dep/src/sockets/StdoutLog.cpp @@ -0,0 +1,96 @@ +/** \file StdoutLog.cpp + ** \date 2004-06-01 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2004-2007 Anders Hedstrom + +This library is made available under the terms of the GNU GPL. + +If you would like to use this library in a closed-source application, +a separate license agreement is available. For information about +the closed-source license agreement for the C++ sockets library, +please visit http://www.alhem.net/Sockets/license.html and/or +email license@alhem.net. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifdef _MSC_VER +#pragma warning(disable:4786) +#endif +#include "ISocketHandler.h" +#include "Socket.h" +#include "StdoutLog.h" + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + + + + +void StdoutLog::error(ISocketHandler *,Socket *sock,const std::string& call,int err,const std::string& sys_err,loglevel_t lvl) +{ + time_t t = time(NULL); + struct tm tp; +#ifdef _WIN32 + memcpy(&tp, localtime(&t), sizeof(tp)); +#else + localtime_r(&t, &tp); +#endif + std::string level; + + switch (lvl) + { + case LOG_LEVEL_WARNING: + level = "Warning"; + break; + case LOG_LEVEL_ERROR: + level = "Error"; + break; + case LOG_LEVEL_FATAL: + level = "Fatal"; + break; + case LOG_LEVEL_INFO: + level = "Info"; + break; + } + if (sock) + { + printf("%d-%02d-%02d %02d:%02d:%02d :: fd %d :: %s: %d %s (%s)\n", + tp.tm_year + 1900, + tp.tm_mon + 1, + tp.tm_mday, + tp.tm_hour,tp.tm_min,tp.tm_sec, + sock -> GetSocket(), + call.c_str(),err,sys_err.c_str(),level.c_str()); + } + else + { + printf("%d-%02d-%02d %02d:%02d:%02d :: %s: %d %s (%s)\n", + tp.tm_year + 1900, + tp.tm_mon + 1, + tp.tm_mday, + tp.tm_hour,tp.tm_min,tp.tm_sec, + call.c_str(),err,sys_err.c_str(),level.c_str()); + } +} + + +#ifdef SOCKETS_NAMESPACE +} +#endif + + diff --git a/dep/src/sockets/StreamSocket.cpp b/dep/src/sockets/StreamSocket.cpp new file mode 100644 index 00000000000..5c5780e3085 --- /dev/null +++ b/dep/src/sockets/StreamSocket.cpp @@ -0,0 +1,169 @@ +#include "StreamSocket.h" +#include "ISocketHandler.h" + + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + + +StreamSocket::StreamSocket(ISocketHandler& h) : Socket(h) +,m_bConnecting(false) +,m_connect_timeout(5) +,m_flush_before_close(true) +,m_connection_retry(0) +,m_retries(0) +,m_call_on_connect(false) +,m_b_retry_connect(false) +,m_line_protocol(false) +,m_shutdown(0) +{ +} + + +StreamSocket::~StreamSocket() +{ +} + + +void StreamSocket::SetConnecting(bool x) +{ + if (x != m_bConnecting) + { + m_bConnecting = x; + if (x) + { + SetTimeout( GetConnectTimeout() ); + } + else + { + SetTimeout( 0 ); + } + } +} + + +bool StreamSocket::Connecting() +{ + return m_bConnecting; +} + + +bool StreamSocket::Ready() +{ + if (GetSocket() != INVALID_SOCKET && !Connecting() && !CloseAndDelete()) + return true; + return false; +} + + +void StreamSocket::SetConnectTimeout(int x) +{ + m_connect_timeout = x; +} + + +int StreamSocket::GetConnectTimeout() +{ + return m_connect_timeout; +} + + +void StreamSocket::SetFlushBeforeClose(bool x) +{ + m_flush_before_close = x; +} + + +bool StreamSocket::GetFlushBeforeClose() +{ + return m_flush_before_close; +} + + +int StreamSocket::GetConnectionRetry() +{ + return m_connection_retry; +} + + +void StreamSocket::SetConnectionRetry(int x) +{ + m_connection_retry = x; +} + + +int StreamSocket::GetConnectionRetries() +{ + return m_retries; +} + + +void StreamSocket::IncreaseConnectionRetries() +{ + m_retries++; +} + + +void StreamSocket::ResetConnectionRetries() +{ + m_retries = 0; +} + + +void StreamSocket::SetCallOnConnect(bool x) +{ + Handler().AddList(GetSocket(), LIST_CALLONCONNECT, x); + m_call_on_connect = x; +} + + +bool StreamSocket::CallOnConnect() +{ + return m_call_on_connect; +} + + +void StreamSocket::SetRetryClientConnect(bool x) +{ + Handler().AddList(GetSocket(), LIST_RETRY, x); + m_b_retry_connect = x; +} + + +bool StreamSocket::RetryClientConnect() +{ + return m_b_retry_connect; +} + + +void StreamSocket::SetLineProtocol(bool x) +{ + m_line_protocol = x; +} + + +bool StreamSocket::LineProtocol() +{ + return m_line_protocol; +} + + +void StreamSocket::SetShutdown(int x) +{ + m_shutdown = x; +} + + +int StreamSocket::GetShutdown() +{ + return m_shutdown; +} + + + + +#ifdef SOCKETS_NAMESPACE +} // namespace SOCKETS_NAMESPACE { +#endif + diff --git a/dep/src/sockets/TcpSocket.cpp b/dep/src/sockets/TcpSocket.cpp new file mode 100644 index 00000000000..36df37d5832 --- /dev/null +++ b/dep/src/sockets/TcpSocket.cpp @@ -0,0 +1,1745 @@ +/** \file TcpSocket.cpp + ** \date 2004-02-13 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2004-2007 Anders Hedstrom + +This library is made available under the terms of the GNU GPL. + +If you would like to use this library in a closed-source application, +a separate license agreement is available. For information about +the closed-source license agreement for the C++ sockets library, +please visit http://www.alhem.net/Sockets/license.html and/or +email license@alhem.net. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifdef _WIN32 +#ifdef _MSC_VER +#pragma warning(disable:4786) +#endif +#include +#else +#include +#endif +#include "ISocketHandler.h" +#include +#include +#include +#ifdef HAVE_OPENSSL +#include +#include +#endif +#include + +#include "TcpSocket.h" +#include "Utility.h" +#include "Ipv4Address.h" +#include "Ipv6Address.h" +#include "Mutex.h" +#include "IFile.h" + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + + +//#ifdef _DEBUG +//#define DEB(x) x +//#else +#define DEB(x) +//#endif + + +// statics +#ifdef HAVE_OPENSSL +SSLInitializer TcpSocket::m_ssl_init; +#endif + + +// thanks, q +#ifdef _MSC_VER +#pragma warning(disable:4355) +#endif +TcpSocket::TcpSocket(ISocketHandler& h) : StreamSocket(h) +,ibuf(TCP_BUFSIZE_READ) +,m_b_input_buffer_disabled(false) +,m_bytes_sent(0) +,m_bytes_received(0) +,m_skip_c(false) +#ifdef SOCKETS_DYNAMIC_TEMP +,m_buf(new char[TCP_BUFSIZE_READ + 1]) +#endif +,m_obuf_top(NULL) +,m_transfer_limit(0) +,m_output_length(0) +#ifdef HAVE_OPENSSL +,m_ssl_ctx(NULL) +,m_ssl(NULL) +,m_sbio(NULL) +#endif +#ifdef ENABLE_SOCKS4 +,m_socks4_state(0) +#endif +#ifdef ENABLE_RESOLVER +,m_resolver_id(0) +#endif +#ifdef ENABLE_RECONNECT +,m_b_reconnect(false) +,m_b_is_reconnect(false) +#endif +{ +} +#ifdef _MSC_VER +#pragma warning(default:4355) +#endif + + +#ifdef _MSC_VER +#pragma warning(disable:4355) +#endif +TcpSocket::TcpSocket(ISocketHandler& h,size_t isize,size_t osize) : StreamSocket(h) +,ibuf(isize) +,m_b_input_buffer_disabled(false) +,m_bytes_sent(0) +,m_bytes_received(0) +,m_skip_c(false) +#ifdef SOCKETS_DYNAMIC_TEMP +,m_buf(new char[TCP_BUFSIZE_READ + 1]) +#endif +,m_obuf_top(NULL) +,m_transfer_limit(0) +,m_output_length(0) +#ifdef HAVE_OPENSSL +,m_ssl_ctx(NULL) +,m_ssl(NULL) +,m_sbio(NULL) +#endif +#ifdef ENABLE_SOCKS4 +,m_socks4_state(0) +#endif +#ifdef ENABLE_RESOLVER +,m_resolver_id(0) +#endif +#ifdef ENABLE_RECONNECT +,m_b_reconnect(false) +,m_b_is_reconnect(false) +#endif +{ +} +#ifdef _MSC_VER +#pragma warning(default:4355) +#endif + + +TcpSocket::~TcpSocket() +{ +#ifdef SOCKETS_DYNAMIC_TEMP + delete[] m_buf; +#endif + // %! empty m_obuf + while (m_obuf.size()) + { + output_l::iterator it = m_obuf.begin(); + OUTPUT *p = *it; + delete p; + m_obuf.erase(it); + } +#ifdef HAVE_OPENSSL + if (m_ssl) + { + SSL_free(m_ssl); + } +#endif +} + + +bool TcpSocket::Open(ipaddr_t ip,port_t port,bool skip_socks) +{ + Ipv4Address ad(ip, port); + Ipv4Address local; + return Open(ad, local, skip_socks); +} + + +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 +bool TcpSocket::Open(in6_addr ip,port_t port,bool skip_socks) +{ + Ipv6Address ad(ip, port); + return Open(ad, skip_socks); +} +#endif +#endif + + +bool TcpSocket::Open(SocketAddress& ad,bool skip_socks) +{ + Ipv4Address bind_ad("0.0.0.0", 0); + return Open(ad, bind_ad, skip_socks); +} + + +bool TcpSocket::Open(SocketAddress& ad,SocketAddress& bind_ad,bool skip_socks) +{ + if (!ad.IsValid()) + { + Handler().LogError(this, "Open", 0, "Invalid SocketAddress", LOG_LEVEL_FATAL); + SetCloseAndDelete(); + return false; + } + if (Handler().GetCount() >= FD_SETSIZE) + { + Handler().LogError(this, "Open", 0, "no space left in fd_set", LOG_LEVEL_FATAL); + SetCloseAndDelete(); + return false; + } + SetConnecting(false); +#ifdef ENABLE_SOCKS4 + SetSocks4(false); +#endif + // check for pooling +#ifdef ENABLE_POOL + if (Handler().PoolEnabled()) + { + ISocketHandler::PoolSocket *pools = Handler().FindConnection(SOCK_STREAM, "tcp", ad); + if (pools) + { + CopyConnection( pools ); + delete pools; + + SetIsClient(); + SetCallOnConnect(); // ISocketHandler must call OnConnect + Handler().LogError(this, "SetCallOnConnect", 0, "Found pooled connection", LOG_LEVEL_INFO); + return true; + } + } +#endif + // if not, create new connection + SOCKET s = CreateSocket(ad.GetFamily(), SOCK_STREAM, "tcp"); + if (s == INVALID_SOCKET) + { + return false; + } + // socket must be nonblocking for async connect + if (!SetNonblocking(true, s)) + { + SetCloseAndDelete(); + closesocket(s); + return false; + } +#ifdef ENABLE_POOL + SetIsClient(); // client because we connect +#endif + SetClientRemoteAddress(ad); + int n = 0; + if (bind_ad.GetPort() != 0) + { + bind(s, bind_ad, bind_ad); + } +#ifdef ENABLE_SOCKS4 + if (!skip_socks && GetSocks4Host() && GetSocks4Port()) + { + Ipv4Address sa(GetSocks4Host(), GetSocks4Port()); + { + std::string sockshost; + Utility::l2ip(GetSocks4Host(), sockshost); + Handler().LogError(this, "Open", 0, "Connecting to socks4 server @ " + sockshost + ":" + + Utility::l2string(GetSocks4Port()), LOG_LEVEL_INFO); + } + SetSocks4(); + n = connect(s, sa, sa); + SetRemoteAddress(sa); + } + else +#endif + { + n = connect(s, ad, ad); + SetRemoteAddress(ad); + } + if (n == -1) + { + // check error code that means a connect is in progress +#ifdef _WIN32 + if (Errno == WSAEWOULDBLOCK) +#else + if (Errno == EINPROGRESS) +#endif + { + Attach(s); + SetConnecting( true ); // this flag will control fd_set's + } + else +#ifdef ENABLE_SOCKS4 + if (Socks4() && Handler().Socks4TryDirect() ) // retry + { + closesocket(s); + return Open(ad, true); + } + else +#endif +#ifdef ENABLE_RECONNECT + if (Reconnect()) + { + Handler().LogError(this, "connect: failed, reconnect pending", Errno, StrError(Errno), LOG_LEVEL_INFO); + Attach(s); + SetConnecting( true ); // this flag will control fd_set's + } + else +#endif + { + Handler().LogError(this, "connect: failed", Errno, StrError(Errno), LOG_LEVEL_FATAL); + SetCloseAndDelete(); + closesocket(s); + return false; + } + } + else + { + Attach(s); + SetCallOnConnect(); // ISocketHandler must call OnConnect + } + + // 'true' means connected or connecting(not yet connected) + // 'false' means something failed + return true; //!Connecting(); +} + + +bool TcpSocket::Open(const std::string &host,port_t port) +{ +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + if (IsIpv6()) + { +#ifdef ENABLE_RESOLVER + if (!Handler().ResolverEnabled() || Utility::isipv6(host) ) + { +#endif + in6_addr a; + if (!Utility::u2ip(host, a)) + { + SetCloseAndDelete(); + return false; + } + Ipv6Address ad(a, port); + Ipv6Address local; + return Open(ad, local); +#ifdef ENABLE_RESOLVER + } + m_resolver_id = Resolve6(host, port); + return true; +#endif + } +#endif +#endif +#ifdef ENABLE_RESOLVER + if (!Handler().ResolverEnabled() || Utility::isipv4(host) ) + { +#endif + ipaddr_t l; + if (!Utility::u2ip(host,l)) + { + SetCloseAndDelete(); + return false; + } + Ipv4Address ad(l, port); + Ipv4Address local; + return Open(ad, local); +#ifdef ENABLE_RESOLVER + } + // resolve using async resolver thread + m_resolver_id = Resolve(host, port); + return true; +#endif +} + + +#ifdef ENABLE_RESOLVER +void TcpSocket::OnResolved(int id,ipaddr_t a,port_t port) +{ +DEB( fprintf(stderr, "TcpSocket::OnResolved id %d addr %x port %d\n", id, a, port);) + if (id == m_resolver_id) + { + if (a && port) + { + Ipv4Address ad(a, port); + Ipv4Address local; + if (Open(ad, local)) + { + if (!Handler().Valid(this)) + { + Handler().Add(this); + } + } + } + else + { + Handler().LogError(this, "OnResolved", 0, "Resolver failed", LOG_LEVEL_FATAL); + SetCloseAndDelete(); + } + } + else + { + Handler().LogError(this, "OnResolved", id, "Resolver returned wrong job id", LOG_LEVEL_FATAL); + SetCloseAndDelete(); + } +} + + +#ifdef ENABLE_IPV6 +void TcpSocket::OnResolved(int id,in6_addr& a,port_t port) +{ + if (id == m_resolver_id) + { + Ipv6Address ad(a, port); + if (ad.IsValid()) + { + Ipv6Address local; + if (Open(ad, local)) + { + if (!Handler().Valid(this)) + { + Handler().Add(this); + } + } + } + } + else + { + Handler().LogError(this, "OnResolved", id, "Resolver returned wrong job id", LOG_LEVEL_FATAL); + SetCloseAndDelete(); + } +} +#endif +#endif + + +void TcpSocket::OnRead() +{ + int n = 0; +#ifdef SOCKETS_DYNAMIC_TEMP + char *buf = m_buf; +#else + char buf[TCP_BUFSIZE_READ]; +#endif +#ifdef HAVE_OPENSSL + if (IsSSL()) + { + if (!Ready()) + return; + n = SSL_read(m_ssl, buf, TCP_BUFSIZE_READ); + if (n == -1) + { + n = SSL_get_error(m_ssl, n); + switch (n) + { + case SSL_ERROR_NONE: + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + break; + case SSL_ERROR_ZERO_RETURN: +DEB( fprintf(stderr, "SSL_read() returns zero - closing socket\n");) + OnDisconnect(); + SetCloseAndDelete(true); + SetFlushBeforeClose(false); + SetLost(); + break; + default: +DEB( fprintf(stderr, "SSL read problem, errcode = %d\n",n);) + OnDisconnect(); + SetCloseAndDelete(true); + SetFlushBeforeClose(false); + SetLost(); + } + return; + } + else + if (!n) + { + OnDisconnect(); + SetCloseAndDelete(true); + SetFlushBeforeClose(false); + SetLost(); + SetShutdown(SHUT_WR); + return; + } + else + if (n > 0 && n <= TCP_BUFSIZE_READ) + { + m_bytes_received += n; + if (GetTrafficMonitor()) + { + GetTrafficMonitor() -> fwrite(buf, 1, n); + } + if (!m_b_input_buffer_disabled && !ibuf.Write(buf,n)) + { + Handler().LogError(this, "OnRead(ssl)", 0, "ibuf overflow", LOG_LEVEL_WARNING); + } + } + else + { + Handler().LogError(this, "OnRead(ssl)", n, "abnormal value from SSL_read", LOG_LEVEL_ERROR); + } + } + else +#endif // HAVE_OPENSSL + { + n = recv(GetSocket(), buf, TCP_BUFSIZE_READ, MSG_NOSIGNAL); + if (n == -1) + { + Handler().LogError(this, "read", Errno, StrError(Errno), LOG_LEVEL_FATAL); + OnDisconnect(); + SetCloseAndDelete(true); + SetFlushBeforeClose(false); + SetLost(); + return; + } + else + if (!n) + { + OnDisconnect(); + SetCloseAndDelete(true); + SetFlushBeforeClose(false); + SetLost(); + SetShutdown(SHUT_WR); + return; + } + else + if (n > 0 && n <= TCP_BUFSIZE_READ) + { + m_bytes_received += n; + if (GetTrafficMonitor()) + { + GetTrafficMonitor() -> fwrite(buf, 1, n); + } + if (!m_b_input_buffer_disabled && !ibuf.Write(buf,n)) + { + Handler().LogError(this, "OnRead", 0, "ibuf overflow", LOG_LEVEL_WARNING); + } + } + else + { + Handler().LogError(this, "OnRead", n, "abnormal value from recv", LOG_LEVEL_ERROR); + } + } + // + OnRead( buf, n ); +} + + +void TcpSocket::OnRead( char *buf, size_t n ) +{ + // unbuffered + if (n > 0 && n <= TCP_BUFSIZE_READ) + { + if (LineProtocol()) + { + buf[n] = 0; + size_t i = 0; + if (m_skip_c && (buf[i] == 13 || buf[i] == 10) && buf[i] != m_c) + { + m_skip_c = false; + i++; + } + size_t x = i; + for (; i < n && LineProtocol(); i++) + { + while ((buf[i] == 13 || buf[i] == 10) && LineProtocol()) + { + char c = buf[i]; + buf[i] = 0; + if (buf[x]) + { + m_line += (buf + x); + } + OnLine( m_line ); + i++; + m_skip_c = true; + m_c = c; + if (i < n && (buf[i] == 13 || buf[i] == 10) && buf[i] != c) + { + m_skip_c = false; + i++; + } + x = i; + m_line = ""; + } + if (!LineProtocol()) + { + break; + } + } + if (!LineProtocol()) + { + if (i < n) + { + OnRawData(buf + i, n - i); + } + } + else + if (buf[x]) + { + m_line += (buf + x); + } + } + else + { + OnRawData(buf, n); + } + } + if (m_b_input_buffer_disabled) + { + return; + } + // further processing: socks4 +#ifdef ENABLE_SOCKS4 + if (Socks4()) + { + bool need_more = false; + while (GetInputLength() && !need_more && !CloseAndDelete()) + { + need_more = OnSocks4Read(); + } + } +#endif +} + + +void TcpSocket::OnWriteComplete() +{ +} + + +void TcpSocket::OnWrite() +{ + if (Connecting()) + { + int err = SoError(); + + // don't reset connecting flag on error here, we want the OnConnectFailed timeout later on + if (!err) // ok + { + Set(!IsDisableRead(), false); + SetConnecting(false); + SetCallOnConnect(); + return; + } + Handler().LogError(this, "tcp: connect failed", err, StrError(err), LOG_LEVEL_FATAL); + Set(false, false); // no more monitoring because connection failed + + // failed +#ifdef ENABLE_SOCKS4 + if (Socks4()) + { + // %! leave 'Connecting' flag set? + OnSocks4ConnectFailed(); + return; + } +#endif + if (GetConnectionRetry() == -1 || + (GetConnectionRetry() && GetConnectionRetries() < GetConnectionRetry()) ) + { + // even though the connection failed at once, only retry after + // the connection timeout. + // should we even try to connect again, when CheckConnect returns + // false it's because of a connection error - not a timeout... + return; + } + SetConnecting(false); + SetCloseAndDelete( true ); + /// \todo state reason why connect failed + OnConnectFailed(); + return; + } + // try send next block in buffer + // if full block is sent, repeat + // if all blocks are sent, reset m_wfds + + bool repeat = false; + size_t sz = m_transfer_limit ? GetOutputLength() : 0; + do + { + output_l::iterator it = m_obuf.begin(); + OUTPUT *p = *it; + repeat = false; + int n = TryWrite(p -> Buf(), p -> Len()); + if (n > 0) + { + size_t left = p -> Remove(n); + m_output_length -= n; + if (!left) + { + delete p; + m_obuf.erase(it); + if (!m_obuf.size()) + { + m_obuf_top = NULL; + OnWriteComplete(); + } + else + { + repeat = true; + } + } + } + } while (repeat); + + if (m_transfer_limit && sz > m_transfer_limit && GetOutputLength() < m_transfer_limit) + { + OnTransferLimit(); + } + + // check output buffer set, set/reset m_wfds accordingly + { + bool br; + bool bw; + bool bx; + Handler().Get(GetSocket(), br, bw, bx); + if (m_obuf.size()) + Set(br, true); + else + Set(br, false); + } +} + + +int TcpSocket::TryWrite(const char *buf, size_t len) +{ + int n = 0; +#ifdef HAVE_OPENSSL + if (IsSSL()) + { + n = SSL_write(m_ssl, buf, (int)len); + if (n == -1) + { + int errnr = SSL_get_error(m_ssl, n); + if ( errnr != SSL_ERROR_WANT_READ && errnr != SSL_ERROR_WANT_WRITE ) + { + OnDisconnect(); + SetCloseAndDelete(true); + SetFlushBeforeClose(false); + SetLost(); + const char *errbuf = ERR_error_string(errnr, NULL); + Handler().LogError(this, "OnWrite/SSL_write", errnr, errbuf, LOG_LEVEL_FATAL); + } + return 0; + } + else + if (!n) + { + OnDisconnect(); + SetCloseAndDelete(true); + SetFlushBeforeClose(false); + SetLost(); +DEB( int errnr = SSL_get_error(m_ssl, n); + const char *errbuf = ERR_error_string(errnr, NULL); + fprintf(stderr, "SSL_write() returns 0: %d : %s\n",errnr, errbuf);) + } + } + else +#endif // HAVE_OPENSSL + { + n = send(GetSocket(), buf, (int)len, MSG_NOSIGNAL); + if (n == -1) + { + // normal error codes: + // WSAEWOULDBLOCK + // EAGAIN or EWOULDBLOCK +#ifdef _WIN32 + if (Errno != WSAEWOULDBLOCK) +#else + if (Errno != EWOULDBLOCK) +#endif + { + Handler().LogError(this, "send", Errno, StrError(Errno), LOG_LEVEL_FATAL); + OnDisconnect(); + SetCloseAndDelete(true); + SetFlushBeforeClose(false); + SetLost(); + } + return 0; + } + } + if (n > 0) + { + m_bytes_sent += n; + if (GetTrafficMonitor()) + { + GetTrafficMonitor() -> fwrite(buf, 1, n); + } + } + return n; +} + + +void TcpSocket::Buffer(const char *buf, size_t len) +{ + size_t ptr = 0; + m_output_length += len; + while (ptr < len) + { + // buf/len => pbuf/sz + size_t space = 0; + if (m_obuf_top && (space = m_obuf_top -> Space()) > 0) + { + const char *pbuf = buf + ptr; + size_t sz = len - ptr; + if (space >= sz) + { + m_obuf_top -> Add(pbuf, sz); + ptr += sz; + } + else + { + m_obuf_top -> Add(pbuf, space); + ptr += space; + } + } + else + { + m_obuf_top = new OUTPUT; + m_obuf.push_back( m_obuf_top ); + } + } +} + + +void TcpSocket::Send(const std::string &str,int i) +{ + SendBuf(str.c_str(),str.size(),i); +} + + +void TcpSocket::SendBuf(const char *buf,size_t len,int) +{ + if (!Ready() && !Connecting()) + { + Handler().LogError(this, "SendBuf", -1, "Attempt to write to a non-ready socket" ); // warning + if (GetSocket() == INVALID_SOCKET) + Handler().LogError(this, "SendBuf", 0, " * GetSocket() == INVALID_SOCKET", LOG_LEVEL_INFO); + if (Connecting()) + Handler().LogError(this, "SendBuf", 0, " * Connecting()", LOG_LEVEL_INFO); + if (CloseAndDelete()) + Handler().LogError(this, "SendBuf", 0, " * CloseAndDelete()", LOG_LEVEL_INFO); + return; + } + if (!IsConnected()) + { + Handler().LogError(this, "SendBuf", -1, "Attempt to write to a non-connected socket, will be sent on connect" ); // warning + Buffer(buf, len); + return; + } + if (m_obuf_top) + { + Buffer(buf, len); + return; + } + int n = TryWrite(buf, len); + if (n >= 0 && n < (int)len) + { + Buffer(buf + n, len - n); + } + // if ( data in buffer || !IsConnected ) + // { + // add to buffer + // } + // else + // try_send + // if any data is unsent, buffer it and set m_wfds + + // check output buffer set, set/reset m_wfds accordingly + { + bool br; + bool bw; + bool bx; + Handler().Get(GetSocket(), br, bw, bx); + if (m_obuf.size()) + Set(br, true); + else + Set(br, false); + } +} + + +void TcpSocket::OnLine(const std::string& ) +{ +} + + +#ifdef _MSC_VER +#pragma warning(disable:4355) +#endif +TcpSocket::TcpSocket(const TcpSocket& s) +:StreamSocket(s) +,ibuf(0) +{ +} +#ifdef _MSC_VER +#pragma warning(default:4355) +#endif + + +#ifdef ENABLE_SOCKS4 +void TcpSocket::OnSocks4Connect() +{ + char request[1000]; + memset(request, 0, sizeof(request)); + request[0] = 4; // socks v4 + request[1] = 1; // command code: CONNECT + { + std::auto_ptr ad = GetClientRemoteAddress(); + if (ad.get()) + { + struct sockaddr *p0 = (struct sockaddr *)*ad; + struct sockaddr_in *p = (struct sockaddr_in *)p0; + if (p -> sin_family == AF_INET) + { + memcpy(request + 2, &p -> sin_port, 2); // nwbo is ok here + memcpy(request + 4, &p -> sin_addr, sizeof(struct in_addr)); + } + else + { + /// \todo warn + } + } + else + { + /// \todo warn + } + } + strcpy(request + 8, GetSocks4Userid().c_str()); + size_t length = GetSocks4Userid().size() + 8 + 1; + SendBuf(request, length); + m_socks4_state = 0; +} + + +void TcpSocket::OnSocks4ConnectFailed() +{ + Handler().LogError(this,"OnSocks4ConnectFailed",0,"connection to socks4 server failed, trying direct connection",LOG_LEVEL_WARNING); + if (!Handler().Socks4TryDirect()) + { + SetConnecting(false); + SetCloseAndDelete(); + OnConnectFailed(); // just in case + } + else + { + SetRetryClientConnect(); + } +} + + +bool TcpSocket::OnSocks4Read() +{ + switch (m_socks4_state) + { + case 0: + ibuf.Read(&m_socks4_vn, 1); + m_socks4_state = 1; + break; + case 1: + ibuf.Read(&m_socks4_cd, 1); + m_socks4_state = 2; + break; + case 2: + if (GetInputLength() > 1) + { + ibuf.Read( (char *)&m_socks4_dstport, 2); + m_socks4_state = 3; + } + else + { + return true; + } + break; + case 3: + if (GetInputLength() > 3) + { + ibuf.Read( (char *)&m_socks4_dstip, 4); + SetSocks4(false); + + switch (m_socks4_cd) + { + case 90: + OnConnect(); + Handler().LogError(this, "OnSocks4Read", 0, "Connection established", LOG_LEVEL_INFO); + break; + case 91: + case 92: + case 93: + Handler().LogError(this,"OnSocks4Read",m_socks4_cd,"socks4 server reports connect failed",LOG_LEVEL_FATAL); + SetConnecting(false); + SetCloseAndDelete(); + OnConnectFailed(); + break; + default: + Handler().LogError(this,"OnSocks4Read",m_socks4_cd,"socks4 server unrecognized response",LOG_LEVEL_FATAL); + SetCloseAndDelete(); + break; + } + } + else + { + return true; + } + break; + } + return false; +} +#endif + + +void TcpSocket::Sendf(const char *format, ...) +{ + va_list ap; + va_start(ap, format); + char slask[5000]; // vsprintf / vsnprintf temporary +#ifdef _WIN32 + vsprintf(slask, format, ap); +#else + vsnprintf(slask, 5000, format, ap); +#endif + va_end(ap); + Send( slask ); +} + + +#ifdef HAVE_OPENSSL +void TcpSocket::OnSSLConnect() +{ + SetNonblocking(true); + { + if (m_ssl_ctx) + { +DEB( fprintf(stderr, "SSL Context already initialized - closing socket\n");) + SetCloseAndDelete(true); + return; + } + InitSSLClient(); + } + if (m_ssl_ctx) + { + /* Connect the SSL socket */ + m_ssl = SSL_new(m_ssl_ctx); + if (!m_ssl) + { +DEB( fprintf(stderr, " m_ssl is NULL\n");) + SetCloseAndDelete(true); + return; + } + SSL_set_mode(m_ssl, SSL_MODE_AUTO_RETRY); + m_sbio = BIO_new_socket((int)GetSocket(), BIO_NOCLOSE); + if (!m_sbio) + { +DEB( fprintf(stderr, " m_sbio is NULL\n");) + SetCloseAndDelete(true); + return; + } + SSL_set_bio(m_ssl, m_sbio, m_sbio); + if (!SSLNegotiate()) + { + SetSSLNegotiate(); + } + } + else + { + SetCloseAndDelete(); + } +} + + +void TcpSocket::OnSSLAccept() +{ + SetNonblocking(true); + { + if (m_ssl_ctx) + { +DEB( fprintf(stderr, "SSL Context already initialized - closing socket\n");) + SetCloseAndDelete(true); + return; + } + InitSSLServer(); + SetSSLServer(); + } + if (m_ssl_ctx) + { + m_ssl = SSL_new(m_ssl_ctx); + if (!m_ssl) + { +DEB( fprintf(stderr, " m_ssl is NULL\n");) + SetCloseAndDelete(true); + return; + } + SSL_set_mode(m_ssl, SSL_MODE_AUTO_RETRY); + m_sbio = BIO_new_socket((int)GetSocket(), BIO_NOCLOSE); + if (!m_sbio) + { +DEB( fprintf(stderr, " m_sbio is NULL\n");) + SetCloseAndDelete(true); + return; + } + SSL_set_bio(m_ssl, m_sbio, m_sbio); +// if (!SSLNegotiate()) + { + SetSSLNegotiate(); + } + } +} + + +bool TcpSocket::SSLNegotiate() +{ + if (!IsSSLServer()) // client + { + int r = SSL_connect(m_ssl); + if (r > 0) + { + SetSSLNegotiate(false); + /// \todo: resurrect certificate check... client +// CheckCertificateChain( "");//ServerHOST); + SetNonblocking(false); + // + { + SetConnected(); + if (GetOutputLength()) + { + OnWrite(); + } + } +#ifdef ENABLE_RECONNECT + if (IsReconnect()) + OnReconnect(); + else +#endif + { + OnConnect(); + } + Handler().LogError(this, "SSLNegotiate/SSL_connect", 0, "Connection established", LOG_LEVEL_INFO); + return true; + } + else + if (!r) + { + Handler().LogError(this, "SSLNegotiate/SSL_connect", 0, "Connection failed", LOG_LEVEL_INFO); + SetSSLNegotiate(false); + SetCloseAndDelete(); + OnSSLConnectFailed(); + } + else + { + r = SSL_get_error(m_ssl, r); + if (r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE) + { + Handler().LogError(this, "SSLNegotiate/SSL_connect", -1, "Connection failed", LOG_LEVEL_INFO); +DEB( fprintf(stderr, "SSL_connect() failed - closing socket, return code: %d\n",r);) + SetSSLNegotiate(false); + SetCloseAndDelete(true); + OnSSLConnectFailed(); + } + } + } + else // server + { + int r = SSL_accept(m_ssl); + if (r > 0) + { + SetSSLNegotiate(false); + /// \todo: resurrect certificate check... server +// CheckCertificateChain( "");//ClientHOST); + SetNonblocking(false); + // + { + SetConnected(); + if (GetOutputLength()) + { + OnWrite(); + } + } + OnAccept(); + Handler().LogError(this, "SSLNegotiate/SSL_accept", 0, "Connection established", LOG_LEVEL_INFO); + return true; + } + else + if (!r) + { + Handler().LogError(this, "SSLNegotiate/SSL_accept", 0, "Connection failed", LOG_LEVEL_INFO); + SetSSLNegotiate(false); + SetCloseAndDelete(); + OnSSLAcceptFailed(); + } + else + { + r = SSL_get_error(m_ssl, r); + if (r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE) + { + Handler().LogError(this, "SSLNegotiate/SSL_accept", -1, "Connection failed", LOG_LEVEL_INFO); +DEB( fprintf(stderr, "SSL_accept() failed - closing socket, return code: %d\n",r);) + SetSSLNegotiate(false); + SetCloseAndDelete(true); + OnSSLAcceptFailed(); + } + } + } + return false; +} + + +void TcpSocket::InitSSLClient() +{ + InitializeContext("", SSLv23_method()); +} + + +void TcpSocket::InitSSLServer() +{ + Handler().LogError(this, "InitSSLServer", 0, "You MUST implement your own InitSSLServer method", LOG_LEVEL_FATAL); + SetCloseAndDelete(); +} + + +void TcpSocket::InitializeContext(const std::string& context, SSL_METHOD *meth_in) +{ + /* Create our context*/ + static std::map client_contexts; + if (client_contexts.find(context) == client_contexts.end()) + { + SSL_METHOD *meth = meth_in ? meth_in : SSLv3_method(); + m_ssl_ctx = client_contexts[context] = SSL_CTX_new(meth); + SSL_CTX_set_mode(m_ssl_ctx, SSL_MODE_AUTO_RETRY); + } + else + { + m_ssl_ctx = client_contexts[context]; + } +} + + +void TcpSocket::InitializeContext(const std::string& context,const std::string& keyfile,const std::string& password,SSL_METHOD *meth_in) +{ + /* Create our context*/ + static std::map server_contexts; + if (server_contexts.find(context) == server_contexts.end()) + { + SSL_METHOD *meth = meth_in ? meth_in : SSLv3_method(); + m_ssl_ctx = server_contexts[context] = SSL_CTX_new(meth); + SSL_CTX_set_mode(m_ssl_ctx, SSL_MODE_AUTO_RETRY); + // session id + if (!context.empty()) + SSL_CTX_set_session_id_context(m_ssl_ctx, (const unsigned char *)context.c_str(), (unsigned int)context.size()); + else + SSL_CTX_set_session_id_context(m_ssl_ctx, (const unsigned char *)"--empty--", 9); + } + else + { + m_ssl_ctx = server_contexts[context]; + } + + /* Load our keys and certificates*/ + if (!(SSL_CTX_use_certificate_file(m_ssl_ctx, keyfile.c_str(), SSL_FILETYPE_PEM))) + { + Handler().LogError(this, "TcpSocket InitializeContext", 0, "Couldn't read certificate file " + keyfile, LOG_LEVEL_FATAL); + } + + m_password = password; + SSL_CTX_set_default_passwd_cb(m_ssl_ctx, SSL_password_cb); + SSL_CTX_set_default_passwd_cb_userdata(m_ssl_ctx, this); + if (!(SSL_CTX_use_PrivateKey_file(m_ssl_ctx, keyfile.c_str(), SSL_FILETYPE_PEM))) + { + Handler().LogError(this, "TcpSocket InitializeContext", 0, "Couldn't read private key file " + keyfile, LOG_LEVEL_FATAL); + } +} + + +void TcpSocket::InitializeContext(const std::string& context,const std::string& certfile,const std::string& keyfile,const std::string& password,SSL_METHOD *meth_in) +{ + /* Create our context*/ + static std::map server_contexts; + if (server_contexts.find(context) == server_contexts.end()) + { + SSL_METHOD *meth = meth_in ? meth_in : SSLv3_method(); + m_ssl_ctx = server_contexts[context] = SSL_CTX_new(meth); + SSL_CTX_set_mode(m_ssl_ctx, SSL_MODE_AUTO_RETRY); + // session id + if (context.size()) + SSL_CTX_set_session_id_context(m_ssl_ctx, (const unsigned char *)context.c_str(), (unsigned int)context.size()); + else + SSL_CTX_set_session_id_context(m_ssl_ctx, (const unsigned char *)"--empty--", 9); + } + else + { + m_ssl_ctx = server_contexts[context]; + } + + /* Load our keys and certificates*/ + if (!(SSL_CTX_use_certificate_file(m_ssl_ctx, certfile.c_str(), SSL_FILETYPE_PEM))) + { + Handler().LogError(this, "TcpSocket InitializeContext", 0, "Couldn't read certificate file " + keyfile, LOG_LEVEL_FATAL); + } + + m_password = password; + SSL_CTX_set_default_passwd_cb(m_ssl_ctx, SSL_password_cb); + SSL_CTX_set_default_passwd_cb_userdata(m_ssl_ctx, this); + if (!(SSL_CTX_use_PrivateKey_file(m_ssl_ctx, keyfile.c_str(), SSL_FILETYPE_PEM))) + { + Handler().LogError(this, "TcpSocket InitializeContext", 0, "Couldn't read private key file " + keyfile, LOG_LEVEL_FATAL); + } +} + + +int TcpSocket::SSL_password_cb(char *buf,int num,int rwflag,void *userdata) +{ + Socket *p0 = static_cast(userdata); + TcpSocket *p = dynamic_cast(p0); + std::string pw = p ? p -> GetPassword() : ""; + if ( (size_t)num < pw.size() + 1) + { + return 0; + } + strcpy(buf,pw.c_str()); + return (int)pw.size(); +} +#endif // HAVE_OPENSSL + + +int TcpSocket::Close() +{ + if (GetSocket() == INVALID_SOCKET) // this could happen + { + Handler().LogError(this, "Socket::Close", 0, "file descriptor invalid", LOG_LEVEL_WARNING); + return 0; + } + int n; + SetNonblocking(true); + if (!Lost() && IsConnected() && !(GetShutdown() & SHUT_WR)) + { + if (shutdown(GetSocket(), SHUT_WR) == -1) + { + // failed... + Handler().LogError(this, "shutdown", Errno, StrError(Errno), LOG_LEVEL_ERROR); + } + } + // + char tmp[1000]; + if (!Lost() && (n = recv(GetSocket(),tmp,1000,0)) >= 0) + { + if (n) + { + Handler().LogError(this, "read() after shutdown", n, "bytes read", LOG_LEVEL_WARNING); + } + } +#ifdef HAVE_OPENSSL + if (IsSSL() && m_ssl) + SSL_shutdown(m_ssl); + if (m_ssl) + { + SSL_free(m_ssl); + m_ssl = NULL; + } +#endif + return Socket::Close(); +} + + +#ifdef HAVE_OPENSSL +SSL_CTX *TcpSocket::GetSslContext() +{ + if (!m_ssl_ctx) + Handler().LogError(this, "GetSslContext", 0, "SSL Context is NULL; check InitSSLServer/InitSSLClient", LOG_LEVEL_WARNING); + return m_ssl_ctx; +} + +SSL *TcpSocket::GetSsl() +{ + if (!m_ssl) + Handler().LogError(this, "GetSsl", 0, "SSL is NULL; check InitSSLServer/InitSSLClient", LOG_LEVEL_WARNING); + return m_ssl; +} +#endif + + +#ifdef ENABLE_RECONNECT +void TcpSocket::SetReconnect(bool x) +{ + m_b_reconnect = x; +} +#endif + + +void TcpSocket::OnRawData(const char *buf_in,size_t len) +{ +} + + +size_t TcpSocket::GetInputLength() +{ + return ibuf.GetLength(); +} + + +size_t TcpSocket::GetOutputLength() +{ + return m_output_length; +} + + +uint64_t TcpSocket::GetBytesReceived(bool clear) +{ + uint64_t z = m_bytes_received; + if (clear) + m_bytes_received = 0; + return z; +} + + +uint64_t TcpSocket::GetBytesSent(bool clear) +{ + uint64_t z = m_bytes_sent; + if (clear) + m_bytes_sent = 0; + return z; +} + + +#ifdef ENABLE_RECONNECT +bool TcpSocket::Reconnect() +{ + return m_b_reconnect; +} + + +void TcpSocket::SetIsReconnect(bool x) +{ + m_b_is_reconnect = x; +} + + +bool TcpSocket::IsReconnect() +{ + return m_b_is_reconnect; +} +#endif + + +#ifdef HAVE_OPENSSL +const std::string& TcpSocket::GetPassword() +{ + return m_password; +} +#endif + + +void TcpSocket::DisableInputBuffer(bool x) +{ + m_b_input_buffer_disabled = x; +} + + +void TcpSocket::OnOptions(int family,int type,int protocol,SOCKET s) +{ +DEB( fprintf(stderr, "Socket::OnOptions()\n");) +#ifdef SO_NOSIGPIPE + SetSoNosigpipe(true); +#endif + SetSoReuseaddr(true); + SetSoKeepalive(true); +} + + +void TcpSocket::SetLineProtocol(bool x) +{ + StreamSocket::SetLineProtocol(x); + DisableInputBuffer(x); +} + + +bool TcpSocket::SetTcpNodelay(bool x) +{ +#ifdef TCP_NODELAY + int optval = x ? 1 : 0; + if (setsockopt(GetSocket(), IPPROTO_TCP, TCP_NODELAY, (char *)&optval, sizeof(optval)) == -1) + { + Handler().LogError(this, "setsockopt(IPPROTO_TCP, TCP_NODELAY)", Errno, StrError(Errno), LOG_LEVEL_FATAL); + return false; + } + return true; +#else + Handler().LogError(this, "socket option not available", 0, "TCP_NODELAY", LOG_LEVEL_INFO); + return false; +#endif +} + + +TcpSocket::CircularBuffer::CircularBuffer(size_t size) +:buf(new char[2 * size]) +,m_max(size) +,m_q(0) +,m_b(0) +,m_t(0) +,m_count(0) +{ +} + + +TcpSocket::CircularBuffer::~CircularBuffer() +{ + delete[] buf; +} + + +bool TcpSocket::CircularBuffer::Write(const char *s,size_t l) +{ + if (m_q + l > m_max) + { + return false; // overflow + } + m_count += (unsigned long)l; + if (m_t + l > m_max) // block crosses circular border + { + size_t l1 = m_max - m_t; // size left until circular border crossing + // always copy full block to buffer(buf) + top pointer(m_t) + // because we have doubled the buffer size for performance reasons + memcpy(buf + m_t, s, l); + memcpy(buf, s + l1, l - l1); + m_t = l - l1; + m_q += l; + } + else + { + memcpy(buf + m_t, s, l); + memcpy(buf + m_max + m_t, s, l); + m_t += l; + if (m_t >= m_max) + m_t -= m_max; + m_q += l; + } + return true; +} + + +bool TcpSocket::CircularBuffer::Read(char *s,size_t l) +{ + if (l > m_q) + { + return false; // not enough chars + } + if (m_b + l > m_max) // block crosses circular border + { + size_t l1 = m_max - m_b; + if (s) + { + memcpy(s, buf + m_b, l1); + memcpy(s + l1, buf, l - l1); + } + m_b = l - l1; + m_q -= l; + } + else + { + if (s) + { + memcpy(s, buf + m_b, l); + } + m_b += l; + if (m_b >= m_max) + m_b -= m_max; + m_q -= l; + } + if (!m_q) + { + m_b = m_t = 0; + } + return true; +} + +bool TcpSocket::CircularBuffer::SoftRead(char *s, size_t l) +{ + if (l > m_q) + { + return false; + } + if (m_b + l > m_max) // block crosses circular border + { + size_t l1 = m_max - m_b; + if (s) + { + memcpy(s, buf + m_b, l1); + memcpy(s + l1, buf, l - l1); + } + } + else + { + if (s) + { + memcpy(s, buf + m_b, l); + } + } + return true; +} + +bool TcpSocket::CircularBuffer::Remove(size_t l) +{ + return Read(NULL, l); +} + + +size_t TcpSocket::CircularBuffer::GetLength() +{ + return m_q; +} + + +const char *TcpSocket::CircularBuffer::GetStart() +{ + return buf + m_b; +} + + +size_t TcpSocket::CircularBuffer::GetL() +{ + return (m_b + m_q > m_max) ? m_max - m_b : m_q; +} + + +size_t TcpSocket::CircularBuffer::Space() +{ + return m_max - m_q; +} + + +unsigned long TcpSocket::CircularBuffer::ByteCounter(bool clear) +{ + if (clear) + { + unsigned long x = m_count; + m_count = 0; + return x; + } + return m_count; +} + + +std::string TcpSocket::CircularBuffer::ReadString(size_t l) +{ + char *sz = new char[l + 1]; + if (!Read(sz, l)) // failed, debug printout in Read() method + { + delete[] sz; + return ""; + } + sz[l] = 0; + std::string tmp = sz; + delete[] sz; + return tmp; +} + + +void TcpSocket::OnConnectTimeout() +{ + Handler().LogError(this, "connect", -1, "connect timeout", LOG_LEVEL_FATAL); +#ifdef ENABLE_SOCKS4 + if (Socks4()) + { + OnSocks4ConnectFailed(); + // retry direct connection + } + else +#endif + if (GetConnectionRetry() == -1 || + (GetConnectionRetry() && GetConnectionRetries() < GetConnectionRetry()) ) + { + IncreaseConnectionRetries(); + // ask socket via OnConnectRetry callback if we should continue trying + if (OnConnectRetry()) + { + SetRetryClientConnect(); + } + else + { + SetCloseAndDelete( true ); + /// \todo state reason why connect failed + OnConnectFailed(); + } + } + else + { + SetCloseAndDelete(true); + /// \todo state reason why connect failed + OnConnectFailed(); + } + // + SetConnecting(false); +} + + +#ifdef _WIN32 +void TcpSocket::OnException() +{ + if (Connecting()) + { +#ifdef ENABLE_SOCKS4 + if (Socks4()) + OnSocks4ConnectFailed(); + else +#endif + if (GetConnectionRetry() == -1 || + (GetConnectionRetry() && + GetConnectionRetries() < GetConnectionRetry() )) + { + // even though the connection failed at once, only retry after + // the connection timeout + // should we even try to connect again, when CheckConnect returns + // false it's because of a connection error - not a timeout... + } + else + { + SetConnecting(false); // tnx snibbe + SetCloseAndDelete(); + OnConnectFailed(); + } + return; + } + // %! exception doesn't always mean something bad happened, this code should be reworked + // errno valid here? + int err = SoError(); + Handler().LogError(this, "exception on select", err, StrError(err), LOG_LEVEL_FATAL); + SetCloseAndDelete(); +} +#endif // _WIN32 + + +int TcpSocket::Protocol() +{ + return IPPROTO_TCP; +} + + +void TcpSocket::SetTransferLimit(size_t sz) +{ + m_transfer_limit = sz; +} + + +void TcpSocket::OnTransferLimit() +{ +} + + +#ifdef SOCKETS_NAMESPACE +} +#endif + diff --git a/dep/src/sockets/Thread.cpp b/dep/src/sockets/Thread.cpp new file mode 100644 index 00000000000..2717e32d016 --- /dev/null +++ b/dep/src/sockets/Thread.cpp @@ -0,0 +1,166 @@ +/** \file Thread.cpp + ** \date 2004-10-30 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2004-2007 Anders Hedstrom + +This library is made available under the terms of the GNU GPL. + +If you would like to use this library in a closed-source application, +a separate license agreement is available. For information about +the closed-source license agreement for the C++ sockets library, +please visit http://www.alhem.net/Sockets/license.html and/or +email license@alhem.net. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#include +#ifdef _WIN32 +#include +#include "socket_include.h" +#else +#include +#endif + +#include "Thread.h" + + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + + +Thread::Thread(bool release) +:m_thread(0) +,m_running(true) +,m_release(false) +,m_b_delete_on_exit(false) +,m_b_destructor(false) +{ +#ifdef _WIN32 +// m_thread = ::CreateThread(NULL, 0, StartThread, this, 0, &m_dwThreadId); + m_thread = (HANDLE)_beginthreadex(NULL, 0, &StartThread, this, 0, &m_dwThreadId); +#else + pthread_attr_t attr; + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); + if (pthread_create(&m_thread,&attr, StartThread,this) == -1) + { + perror("Thread: create failed"); + SetRunning(false); + } +// pthread_attr_destroy(&attr); +#endif + m_release = release; +} + + +Thread::~Thread() +{ + m_b_destructor = true; + if (m_running) + { + SetRelease(true); + SetRunning(false); +#ifdef _WIN32 + Sleep(1000); +#else + sleep(1); +#endif + } +#ifdef _WIN32 + if (m_thread) + ::CloseHandle(m_thread); +#endif +} + + +threadfunc_t STDPREFIX Thread::StartThread(threadparam_t zz) +{ + Thread *p = (Thread *)zz; + + while (p -> m_running && !p -> m_release) + { +#ifdef _WIN32 + Sleep(1000); +#else + sleep(1); +#endif + } + if (p -> m_running) + { + p -> Run(); + } + p -> SetRunning(false); // if return + if (p -> DeleteOnExit() && !p -> IsDestructor()) + { + delete p; + } +#ifdef _WIN32 + _endthreadex(0); +#endif + return (threadfunc_t)NULL; +} + + +bool Thread::IsRunning() +{ + return m_running; +} + + +void Thread::SetRunning(bool x) +{ + m_running = x; +} + + +bool Thread::IsReleased() +{ + return m_release; +} + + +void Thread::SetRelease(bool x) +{ + m_release = x; +} + + +bool Thread::DeleteOnExit() +{ + return m_b_delete_on_exit; +} + + +void Thread::SetDeleteOnExit(bool x) +{ + m_b_delete_on_exit = x; +} + + +bool Thread::IsDestructor() +{ + return m_b_destructor; +} + + +#ifdef SOCKETS_NAMESPACE +} +#endif + + diff --git a/dep/src/sockets/UdpSocket.cpp b/dep/src/sockets/UdpSocket.cpp new file mode 100644 index 00000000000..5d949496b25 --- /dev/null +++ b/dep/src/sockets/UdpSocket.cpp @@ -0,0 +1,852 @@ +/** \file UdpSocket.cpp + ** \date 2004-02-13 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2004-2007 Anders Hedstrom + +This library is made available under the terms of the GNU GPL. + +If you would like to use this library in a closed-source application, +a separate license agreement is available. For information about +the closed-source license agreement for the C++ sockets library, +please visit http://www.alhem.net/Sockets/license.html and/or +email license@alhem.net. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifdef _WIN32 +#ifdef _MSC_VER +#pragma warning(disable:4786) +#endif +#include +#else +#include +#endif + +#include "ISocketHandler.h" +#include "UdpSocket.h" +#include "Utility.h" +#include "Ipv4Address.h" +#include "Ipv6Address.h" +#ifdef ENABLE_EXCEPTIONS +#include "Exception.h" +#endif +// include this to see strange sights +//#include + + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + + +UdpSocket::UdpSocket(ISocketHandler& h, int ibufsz, bool ipv6, int retries) : Socket(h) +, m_ibuf(new char[ibufsz]) +, m_ibufsz(ibufsz) +, m_bind_ok(false) +, m_port(0) +, m_last_size_written(-1) +, m_retries(retries) +, m_b_read_ts(false) +{ +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + SetIpv6(ipv6); +#endif +#endif +} + + +UdpSocket::~UdpSocket() +{ + Close(); + delete[] m_ibuf; +} + + +int UdpSocket::Bind(port_t &port, int range) +{ +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + if (IsIpv6()) + { + Ipv6Address ad(port); + return Bind(ad, range); + } +#endif +#endif + Ipv4Address ad(port); + return Bind(ad, range); +} + + +int UdpSocket::Bind(const std::string& intf, port_t &port, int range) +{ +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + if (IsIpv6()) + { + Ipv6Address ad(intf, port); + if (ad.IsValid()) + { + return Bind(ad, range); + } + SetCloseAndDelete(); + return -1; + } +#endif +#endif + Ipv4Address ad(intf, port); + if (ad.IsValid()) + { + return Bind(ad, range); + } + SetCloseAndDelete(); + return -1; +} + + +int UdpSocket::Bind(ipaddr_t a, port_t &port, int range) +{ + Ipv4Address ad(a, port); + return Bind(ad, range); +} + + +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 +int UdpSocket::Bind(in6_addr a, port_t &port, int range) +{ + Ipv6Address ad(a, port); + return Bind(ad, range); +} +#endif +#endif + + +int UdpSocket::Bind(SocketAddress& ad, int range) +{ + if (GetSocket() == INVALID_SOCKET) + { + Attach(CreateSocket(ad.GetFamily(), SOCK_DGRAM, "udp")); + } + if (GetSocket() != INVALID_SOCKET) + { + SetNonblocking(true); + int n = bind(GetSocket(), ad, ad); + int tries = range; + while (n == -1 && tries--) + { + ad.SetPort(ad.GetPort() + 1); + n = bind(GetSocket(), ad, ad); + } + if (n == -1) + { + Handler().LogError(this, "bind", Errno, StrError(Errno), LOG_LEVEL_FATAL); + SetCloseAndDelete(); +#ifdef ENABLE_EXCEPTIONS + throw Exception("bind() failed for UdpSocket, port:range: " + Utility::l2string(ad.GetPort()) + ":" + Utility::l2string(range)); +#endif + return -1; + } + m_bind_ok = true; + m_port = ad.GetPort(); + return 0; + } + return -1; +} + + +/** if you wish to use Send, first Open a connection */ +bool UdpSocket::Open(ipaddr_t l, port_t port) +{ + Ipv4Address ad(l, port); + return Open(ad); +} + + +bool UdpSocket::Open(const std::string& host, port_t port) +{ +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + if (IsIpv6()) + { + Ipv6Address ad(host, port); + if (ad.IsValid()) + { + return Open(ad); + } + return false; + } +#endif +#endif + Ipv4Address ad(host, port); + if (ad.IsValid()) + { + return Open(ad); + } + return false; +} + + +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 +bool UdpSocket::Open(struct in6_addr& a, port_t port) +{ + Ipv6Address ad(a, port); + return Open(ad); +} +#endif +#endif + + +bool UdpSocket::Open(SocketAddress& ad) +{ + if (GetSocket() == INVALID_SOCKET) + { + Attach(CreateSocket(ad.GetFamily(), SOCK_DGRAM, "udp")); + } + if (GetSocket() != INVALID_SOCKET) + { + SetNonblocking(true); + if (connect(GetSocket(), ad, ad) == -1) + { + Handler().LogError(this, "connect", Errno, StrError(Errno), LOG_LEVEL_FATAL); + SetCloseAndDelete(); + return false; + } + SetConnected(); + return true; + } + return false; +} + + +void UdpSocket::CreateConnection() +{ +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + if (IsIpv6()) + { + if (GetSocket() == INVALID_SOCKET) + { + SOCKET s = CreateSocket(AF_INET6, SOCK_DGRAM, "udp"); + if (s == INVALID_SOCKET) + { + return; + } + SetNonblocking(true, s); + Attach(s); + } + return; + } +#endif +#endif + if (GetSocket() == INVALID_SOCKET) + { + SOCKET s = CreateSocket(AF_INET, SOCK_DGRAM, "udp"); + if (s == INVALID_SOCKET) + { + return; + } + SetNonblocking(true, s); + Attach(s); + } +} + + +/** send to specified address */ +void UdpSocket::SendToBuf(const std::string& h, port_t p, const char *data, int len, int flags) +{ +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + if (IsIpv6()) + { + Ipv6Address ad(h, p); + if (ad.IsValid()) + { + SendToBuf(ad, data, len, flags); + } + return; + } +#endif +#endif + Ipv4Address ad(h, p); + if (ad.IsValid()) + { + SendToBuf(ad, data, len, flags); + } +} + + +/** send to specified address */ +void UdpSocket::SendToBuf(ipaddr_t a, port_t p, const char *data, int len, int flags) +{ + Ipv4Address ad(a, p); + SendToBuf(ad, data, len, flags); +} + + +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 +void UdpSocket::SendToBuf(in6_addr a, port_t p, const char *data, int len, int flags) +{ + Ipv6Address ad(a, p); + SendToBuf(ad, data, len, flags); +} +#endif +#endif + + +void UdpSocket::SendToBuf(SocketAddress& ad, const char *data, int len, int flags) +{ + if (GetSocket() == INVALID_SOCKET) + { + Attach(CreateSocket(ad.GetFamily(), SOCK_DGRAM, "udp")); + } + if (GetSocket() != INVALID_SOCKET) + { + SetNonblocking(true); + if ((m_last_size_written = sendto(GetSocket(), data, len, flags, ad, ad)) == -1) + { + Handler().LogError(this, "sendto", Errno, StrError(Errno), LOG_LEVEL_ERROR); + } + } +} + + +void UdpSocket::SendTo(const std::string& a, port_t p, const std::string& str, int flags) +{ + SendToBuf(a, p, str.c_str(), (int)str.size(), flags); +} + + +void UdpSocket::SendTo(ipaddr_t a, port_t p, const std::string& str, int flags) +{ + SendToBuf(a, p, str.c_str(), (int)str.size(), flags); +} + + +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 +void UdpSocket::SendTo(in6_addr a, port_t p, const std::string& str, int flags) +{ + SendToBuf(a, p, str.c_str(), (int)str.size(), flags); +} +#endif +#endif + + +void UdpSocket::SendTo(SocketAddress& ad, const std::string& str, int flags) +{ + SendToBuf(ad, str.c_str(), (int)str.size(), flags); +} + + +/** send to connected address */ +void UdpSocket::SendBuf(const char *data, size_t len, int flags) +{ + if (!IsConnected()) + { + Handler().LogError(this, "SendBuf", 0, "not connected", LOG_LEVEL_ERROR); + return; + } + if ((m_last_size_written = send(GetSocket(), data, (int)len, flags)) == -1) + { + Handler().LogError(this, "send", Errno, StrError(Errno), LOG_LEVEL_ERROR); + } +} + + +void UdpSocket::Send(const std::string& str, int flags) +{ + SendBuf(str.c_str(), (int)str.size(), flags); +} + + +#if defined(LINUX) || defined(MACOSX) +int UdpSocket::ReadTS(char *ioBuf, int inBufSize, struct sockaddr *from, socklen_t fromlen, struct timeval *ts) +{ + struct msghdr msg; + struct iovec vec[1]; + union { + struct cmsghdr cm; +#ifdef MACOSX +#ifdef __DARWIN_UNIX03 +#define ALIGNBYTES __DARWIN_ALIGNBYTES +#endif +#define myALIGN(p) (((unsigned int)(p) + ALIGNBYTES) &~ ALIGNBYTES) +#define myCMSG_SPACE(l) (myALIGN(sizeof(struct cmsghdr)) + myALIGN(l)) + char data[ myCMSG_SPACE(sizeof(struct timeval)) ]; +#else + char data[ CMSG_SPACE(sizeof(struct timeval)) ]; +#endif + } cmsg_un; + struct cmsghdr *cmsg; + struct timeval *tv; + + vec[0].iov_base = ioBuf; + vec[0].iov_len = inBufSize; + + memset(&msg, 0, sizeof(msg)); + memset(from, 0, fromlen); + memset(ioBuf, 0, inBufSize); + memset(&cmsg_un, 0, sizeof(cmsg_un)); + + msg.msg_name = (caddr_t)from; + msg.msg_namelen = fromlen; + msg.msg_iov = vec; + msg.msg_iovlen = 1; + msg.msg_control = cmsg_un.data; + msg.msg_controllen = sizeof(cmsg_un.data); + msg.msg_flags = 0; + + // Original version - for reference only + //int n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len); + + int n = recvmsg(GetSocket(), &msg, MSG_DONTWAIT); + + // now ioBuf will contain the data, as if we used recvfrom + + // Now get the time + if(n != -1 && msg.msg_controllen >= sizeof(struct cmsghdr) && !(msg.msg_flags & MSG_CTRUNC)) + { + tv = 0; + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) + { + if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_TIMESTAMP) + { + tv = (struct timeval *)CMSG_DATA(cmsg); + } + } + if (tv) + { + memcpy(ts, tv, sizeof(struct timeval)); + } + } + // The address is in network order, but that's OK right now + return n; +} +#endif + + +void UdpSocket::OnRead() +{ +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + if (IsIpv6()) + { + struct sockaddr_in6 sa; + socklen_t sa_len = sizeof(sa); + if (m_b_read_ts) + { + struct timeval ts; + Utility::GetTime(&ts); +#if !defined(LINUX) && !defined(MACOSX) + int n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len); +#else + int n = ReadTS(m_ibuf, m_ibufsz, (struct sockaddr *)&sa, sa_len, &ts); +#endif + if (n > 0) + { + this -> OnRawData(m_ibuf, n, (struct sockaddr *)&sa, sa_len, &ts); + } + else + if (n == -1) + { +#ifdef _WIN32 + if (Errno != WSAEWOULDBLOCK) +#else + if (Errno != EWOULDBLOCK) +#endif + Handler().LogError(this, "recvfrom", Errno, StrError(Errno), LOG_LEVEL_ERROR); + } + return; + } + int n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len); + int q = m_retries; // receive max 10 at one cycle + while (n > 0) + { + if (sa_len != sizeof(sa)) + { + Handler().LogError(this, "recvfrom", 0, "unexpected address struct size", LOG_LEVEL_WARNING); + } + this -> OnRawData(m_ibuf, n, (struct sockaddr *)&sa, sa_len); + if (!q--) + break; + // + n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len); + } + if (n == -1) + { +#ifdef _WIN32 + if (Errno != WSAEWOULDBLOCK) +#else + if (Errno != EWOULDBLOCK) +#endif + Handler().LogError(this, "recvfrom", Errno, StrError(Errno), LOG_LEVEL_ERROR); + } + return; + } +#endif +#endif + struct sockaddr_in sa; + socklen_t sa_len = sizeof(sa); + if (m_b_read_ts) + { + struct timeval ts; + Utility::GetTime(&ts); +#if !defined(LINUX) && !defined(MACOSX) + int n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len); +#else + int n = ReadTS(m_ibuf, m_ibufsz, (struct sockaddr *)&sa, sa_len, &ts); +#endif + if (n > 0) + { + this -> OnRawData(m_ibuf, n, (struct sockaddr *)&sa, sa_len, &ts); + } + else + if (n == -1) + { +#ifdef _WIN32 + if (Errno != WSAEWOULDBLOCK) +#else + if (Errno != EWOULDBLOCK) +#endif + Handler().LogError(this, "recvfrom", Errno, StrError(Errno), LOG_LEVEL_ERROR); + } + return; + } + int n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len); + int q = m_retries; + while (n > 0) + { + if (sa_len != sizeof(sa)) + { + Handler().LogError(this, "recvfrom", 0, "unexpected address struct size", LOG_LEVEL_WARNING); + } + this -> OnRawData(m_ibuf, n, (struct sockaddr *)&sa, sa_len); + if (!q--) + break; + // + n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len); + } + if (n == -1) + { +#ifdef _WIN32 + if (Errno != WSAEWOULDBLOCK) +#else + if (Errno != EWOULDBLOCK) +#endif + Handler().LogError(this, "recvfrom", Errno, StrError(Errno), LOG_LEVEL_ERROR); + } +} + + +void UdpSocket::SetBroadcast(bool b) +{ + int one = 1; + int zero = 0; + + if (GetSocket() == INVALID_SOCKET) + { + CreateConnection(); + } + if (b) + { + if (setsockopt(GetSocket(), SOL_SOCKET, SO_BROADCAST, (char *) &one, sizeof(one)) == -1) + { + Handler().LogError(this, "SetBroadcast", Errno, StrError(Errno), LOG_LEVEL_WARNING); + } + } + else + { + if (setsockopt(GetSocket(), SOL_SOCKET, SO_BROADCAST, (char *) &zero, sizeof(zero)) == -1) + { + Handler().LogError(this, "SetBroadcast", Errno, StrError(Errno), LOG_LEVEL_WARNING); + } + } +} + + +bool UdpSocket::IsBroadcast() +{ + int is_broadcast = 0; + socklen_t size; + + if (GetSocket() == INVALID_SOCKET) + { + CreateConnection(); + } + if (getsockopt(GetSocket(), SOL_SOCKET, SO_BROADCAST, (char *)&is_broadcast, &size) == -1) + { + Handler().LogError(this, "IsBroadcast", Errno, StrError(Errno), LOG_LEVEL_WARNING); + } + return is_broadcast != 0; +} + + +void UdpSocket::SetMulticastTTL(int ttl) +{ + if (GetSocket() == INVALID_SOCKET) + { + CreateConnection(); + } + if (setsockopt(GetSocket(), SOL_IP, IP_MULTICAST_TTL, (char *)&ttl, sizeof(int)) == -1) + { + Handler().LogError(this, "SetMulticastTTL", Errno, StrError(Errno), LOG_LEVEL_WARNING); + } +} + + +int UdpSocket::GetMulticastTTL() +{ + int ttl = 0; + socklen_t size = sizeof(int); + + if (GetSocket() == INVALID_SOCKET) + { + CreateConnection(); + } + if (getsockopt(GetSocket(), SOL_IP, IP_MULTICAST_TTL, (char *)&ttl, &size) == -1) + { + Handler().LogError(this, "GetMulticastTTL", Errno, StrError(Errno), LOG_LEVEL_WARNING); + } + return ttl; +} + + +void UdpSocket::SetMulticastLoop(bool x) +{ + if (GetSocket() == INVALID_SOCKET) + { + CreateConnection(); + } +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + if (IsIpv6()) + { + int val = x ? 1 : 0; + if (setsockopt(GetSocket(), IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char *)&val, sizeof(int)) == -1) + { + Handler().LogError(this, "SetMulticastLoop", Errno, StrError(Errno), LOG_LEVEL_WARNING); + } + return; + } +#endif +#endif + int val = x ? 1 : 0; + if (setsockopt(GetSocket(), SOL_IP, IP_MULTICAST_LOOP, (char *)&val, sizeof(int)) == -1) + { + Handler().LogError(this, "SetMulticastLoop", Errno, StrError(Errno), LOG_LEVEL_WARNING); + } +} + + +bool UdpSocket::IsMulticastLoop() +{ + if (GetSocket() == INVALID_SOCKET) + { + CreateConnection(); + } +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + if (IsIpv6()) + { + int is_loop = 0; + socklen_t size = sizeof(int); + if (getsockopt(GetSocket(), IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char *)&is_loop, &size) == -1) + { + Handler().LogError(this, "IsMulticastLoop", Errno, StrError(Errno), LOG_LEVEL_WARNING); + } + return is_loop ? true : false; + } +#endif +#endif + int is_loop = 0; + socklen_t size = sizeof(int); + if (getsockopt(GetSocket(), SOL_IP, IP_MULTICAST_LOOP, (char *)&is_loop, &size) == -1) + { + Handler().LogError(this, "IsMulticastLoop", Errno, StrError(Errno), LOG_LEVEL_WARNING); + } + return is_loop ? true : false; +} + + +void UdpSocket::AddMulticastMembership(const std::string& group, const std::string& local_if, int if_index) +{ + if (GetSocket() == INVALID_SOCKET) + { + CreateConnection(); + } +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + if (IsIpv6()) + { + struct ipv6_mreq x; + struct in6_addr addr; + if (Utility::u2ip( group, addr )) + { + x.ipv6mr_multiaddr = addr; + x.ipv6mr_interface = if_index; + if (setsockopt(GetSocket(), IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *)&x, sizeof(struct ipv6_mreq)) == -1) + { + Handler().LogError(this, "AddMulticastMembership", Errno, StrError(Errno), LOG_LEVEL_WARNING); + } + } + return; + } +#endif +#endif + struct ip_mreq x; // ip_mreqn + ipaddr_t addr; + if (Utility::u2ip( group, addr )) + { + memcpy(&x.imr_multiaddr.s_addr, &addr, sizeof(addr)); + Utility::u2ip( local_if, addr); + memcpy(&x.imr_interface.s_addr, &addr, sizeof(addr)); +// x.imr_ifindex = if_index; + if (setsockopt(GetSocket(), SOL_IP, IP_ADD_MEMBERSHIP, (char *)&x, sizeof(struct ip_mreq)) == -1) + { + Handler().LogError(this, "AddMulticastMembership", Errno, StrError(Errno), LOG_LEVEL_WARNING); + } + } +} + + +void UdpSocket::DropMulticastMembership(const std::string& group, const std::string& local_if, int if_index) +{ + if (GetSocket() == INVALID_SOCKET) + { + CreateConnection(); + } +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + if (IsIpv6()) + { + struct ipv6_mreq x; + struct in6_addr addr; + if (Utility::u2ip( group, addr )) + { + x.ipv6mr_multiaddr = addr; + x.ipv6mr_interface = if_index; + if (setsockopt(GetSocket(), IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, (char *)&x, sizeof(struct ipv6_mreq)) == -1) + { + Handler().LogError(this, "DropMulticastMembership", Errno, StrError(Errno), LOG_LEVEL_WARNING); + } + } + return; + } +#endif +#endif + struct ip_mreq x; // ip_mreqn + ipaddr_t addr; + if (Utility::u2ip( group, addr )) + { + memcpy(&x.imr_multiaddr.s_addr, &addr, sizeof(addr)); + Utility::u2ip( local_if, addr); + memcpy(&x.imr_interface.s_addr, &addr, sizeof(addr)); +// x.imr_ifindex = if_index; + if (setsockopt(GetSocket(), SOL_IP, IP_DROP_MEMBERSHIP, (char *)&x, sizeof(struct ip_mreq)) == -1) + { + Handler().LogError(this, "DropMulticastMembership", Errno, StrError(Errno), LOG_LEVEL_WARNING); + } + } +} + + +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 +void UdpSocket::SetMulticastHops(int hops) +{ + if (GetSocket() == INVALID_SOCKET) + { + CreateConnection(); + } + if (!IsIpv6()) + { + Handler().LogError(this, "SetMulticastHops", 0, "Ipv6 only", LOG_LEVEL_ERROR); + return; + } + if (setsockopt(GetSocket(), IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&hops, sizeof(int)) == -1) + { + Handler().LogError(this, "SetMulticastHops", Errno, StrError(Errno), LOG_LEVEL_WARNING); + } +} + + +int UdpSocket::GetMulticastHops() +{ + if (GetSocket() == INVALID_SOCKET) + { + CreateConnection(); + } + if (!IsIpv6()) + { + Handler().LogError(this, "SetMulticastHops", 0, "Ipv6 only", LOG_LEVEL_ERROR); + return -1; + } + int hops = 0; + socklen_t size = sizeof(int); + if (getsockopt(GetSocket(), IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&hops, &size) == -1) + { + Handler().LogError(this, "GetMulticastHops", Errno, StrError(Errno), LOG_LEVEL_WARNING); + } + return hops; +} +#endif // IPPROTO_IPV6 +#endif + + +bool UdpSocket::IsBound() +{ + return m_bind_ok; +} + + +void UdpSocket::OnRawData(const char *buf, size_t len, struct sockaddr *sa, socklen_t sa_len) +{ +} + + +void UdpSocket::OnRawData(const char *buf, size_t len, struct sockaddr *sa, socklen_t sa_len, struct timeval *ts) +{ +} + + +port_t UdpSocket::GetPort() +{ + return m_port; +} + + +int UdpSocket::GetLastSizeWritten() +{ + return m_last_size_written; +} + + +void UdpSocket::SetTimestamp(bool x) +{ + m_b_read_ts = x; +} + + +#ifdef SOCKETS_NAMESPACE +} +#endif + + diff --git a/dep/src/sockets/Utility.cpp b/dep/src/sockets/Utility.cpp new file mode 100644 index 00000000000..c1327035d7a --- /dev/null +++ b/dep/src/sockets/Utility.cpp @@ -0,0 +1,999 @@ +/** \file Utility.cpp + ** \date 2004-02-13 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2004-2007 Anders Hedstrom + +This library is made available under the terms of the GNU GPL. + +If you would like to use this library in a closed-source application, +a separate license agreement is available. For information about +the closed-source license agreement for the C++ sockets library, +please visit http://www.alhem.net/Sockets/license.html and/or +email license@alhem.net. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#include "Utility.h" +#include "Parse.h" +#include "Ipv4Address.h" +#include "Ipv6Address.h" +#include "Base64.h" +#include +#ifdef _WIN32 +#include +#else +#include +#include +#endif +#include + +#ifdef SOCKETS_NAMESPACE +namespace SOCKETS_NAMESPACE { +#endif + + +// defines for the random number generator +#define TWIST_IA 397 +#define TWIST_IB (TWIST_LEN - TWIST_IA) +#define UMASK 0x80000000 +#define LMASK 0x7FFFFFFF +#define MATRIX_A 0x9908B0DF +#define TWIST(b,i,j) ((b)[i] & UMASK) | ((b)[j] & LMASK) +#define MAGIC_TWIST(s) (((s) & 1) * MATRIX_A) + + +// statics +std::string Utility::m_host; +bool Utility::m_local_resolved = false; +ipaddr_t Utility::m_ip = 0; +std::string Utility::m_addr; +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 +struct in6_addr Utility::m_local_ip6; +std::string Utility::m_local_addr6; +#endif +#endif + + +std::string Utility::base64(const std::string& str_in) +{ + std::string str; + Base64 m_b; + m_b.encode(str_in, str, false); // , false == do not add cr/lf + return str; +} + + +std::string Utility::base64d(const std::string& str_in) +{ + std::string str; + Base64 m_b; + m_b.decode(str_in, str); + return str; +} + + +std::string Utility::l2string(long l) +{ + std::string str; + char tmp[100]; + sprintf(tmp,"%ld",l); + str = tmp; + return str; +} + + +std::string Utility::bigint2string(uint64_t l) +{ + std::string str; + uint64_t tmp = l; + while (tmp) + { + uint64_t a = tmp % 10; + str = (char)(a + 48) + str; + tmp /= 10; + } + if (str.empty()) + { + str = "0"; + } + return str; +} + + +uint64_t Utility::atoi64(const std::string& str) +{ + uint64_t l = 0; + for (size_t i = 0; i < str.size(); i++) + { + l = l * 10 + str[i] - 48; + } + return l; +} + + +unsigned int Utility::hex2unsigned(const std::string& str) +{ + unsigned int r = 0; + for (size_t i = 0; i < str.size(); i++) + { + r = r * 16 + str[i] - 48 - ((str[i] >= 'A') ? 7 : 0) - ((str[i] >= 'a') ? 32 : 0); + } + return r; +} + + +/* +* Encode string per RFC1738 URL encoding rules +* tnx rstaveley +*/ +std::string Utility::rfc1738_encode(const std::string& src) +{ +static char hex[] = "0123456789ABCDEF"; + std::string dst; + for (size_t i = 0; i < src.size(); i++) + { + if (isalnum(src[i])) + { + dst += src[i]; + } + else + if (src[i] == ' ') + { + dst += '+'; + } + else + { + unsigned char c = static_cast(src[i]); + dst += '%'; + dst += hex[c / 16]; + dst += hex[c % 16]; + } + } + return dst; +} // rfc1738_encode + + +/* +* Decode string per RFC1738 URL encoding rules +* tnx rstaveley +*/ +std::string Utility::rfc1738_decode(const std::string& src) +{ + std::string dst; + for (size_t i = 0; i < src.size(); i++) + { + if (src[i] == '%' && isxdigit(src[i + 1]) && isxdigit(src[i + 2])) + { + char c1 = src[++i]; + char c2 = src[++i]; + c1 = c1 - 48 - ((c1 >= 'A') ? 7 : 0) - ((c1 >= 'a') ? 32 : 0); + c2 = c2 - 48 - ((c2 >= 'A') ? 7 : 0) - ((c2 >= 'a') ? 32 : 0); + dst += (char)(c1 * 16 + c2); + } + else + if (src[i] == '+') + { + dst += ' '; + } + else + { + dst += src[i]; + } + } + return dst; +} // rfc1738_decode + + +bool Utility::isipv4(const std::string& str) +{ + int dots = 0; + // %! ignore :port? + for (size_t i = 0; i < str.size(); i++) + { + if (str[i] == '.') + dots++; + else + if (!isdigit(str[i])) + return false; + } + if (dots != 3) + return false; + return true; +} + + +bool Utility::isipv6(const std::string& str) +{ + size_t qc = 0; + size_t qd = 0; + for (size_t i = 0; i < str.size(); i++) + { + qc += (str[i] == ':') ? 1 : 0; + qd += (str[i] == '.') ? 1 : 0; + } + if (qc > 7) + { + return false; + } + if (qd && qd != 3) + { + return false; + } + Parse pa(str,":."); + std::string tmp = pa.getword(); + while (!tmp.empty()) + { + if (tmp.size() > 4) + { + return false; + } + for (size_t i = 0; i < tmp.size(); i++) + { + if (tmp[i] < '0' || (tmp[i] > '9' && tmp[i] < 'A') || + (tmp[i] > 'F' && tmp[i] < 'a') || tmp[i] > 'f') + { + return false; + } + } + // + tmp = pa.getword(); + } + return true; +} + + +bool Utility::u2ip(const std::string& str, ipaddr_t& l) +{ + struct sockaddr_in sa; + bool r = Utility::u2ip(str, sa); + memcpy(&l, &sa.sin_addr, sizeof(l)); + return r; +} + + +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 +bool Utility::u2ip(const std::string& str, struct in6_addr& l) +{ + struct sockaddr_in6 sa; + bool r = Utility::u2ip(str, sa); + l = sa.sin6_addr; + return r; +} +#endif +#endif + + +void Utility::l2ip(const ipaddr_t ip, std::string& str) +{ + struct sockaddr_in sa; + memset(&sa, 0, sizeof(sa)); + sa.sin_family = AF_INET; + memcpy(&sa.sin_addr, &ip, sizeof(sa.sin_addr)); + Utility::reverse( (struct sockaddr *)&sa, sizeof(sa), str, NI_NUMERICHOST); +} + + +void Utility::l2ip(const in_addr& ip, std::string& str) +{ + struct sockaddr_in sa; + memset(&sa, 0, sizeof(sa)); + sa.sin_family = AF_INET; + sa.sin_addr = ip; + Utility::reverse( (struct sockaddr *)&sa, sizeof(sa), str, NI_NUMERICHOST); +} + + +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 +void Utility::l2ip(const struct in6_addr& ip, std::string& str,bool mixed) +{ + char slask[100]; // l2ip temporary + *slask = 0; + unsigned int prev = 0; + bool skipped = false; + bool ok_to_skip = true; + if (mixed) + { + unsigned short x; + unsigned short addr16[8]; + memcpy(addr16, &ip, sizeof(addr16)); + for (size_t i = 0; i < 6; i++) + { + x = ntohs(addr16[i]); + if (*slask && (x || !ok_to_skip || prev)) + strcat(slask,":"); + if (x || !ok_to_skip) + { + sprintf(slask + strlen(slask),"%x", x); + if (x && skipped) + ok_to_skip = false; + } + else + { + skipped = true; + } + prev = x; + } + x = ntohs(addr16[6]); + sprintf(slask + strlen(slask),":%u.%u",x / 256,x & 255); + x = ntohs(addr16[7]); + sprintf(slask + strlen(slask),".%u.%u",x / 256,x & 255); + } + else + { + struct sockaddr_in6 sa; + memset(&sa, 0, sizeof(sa)); + sa.sin6_family = AF_INET6; + sa.sin6_addr = ip; + Utility::reverse( (struct sockaddr *)&sa, sizeof(sa), str, NI_NUMERICHOST); + return; + } + str = slask; +} + + +int Utility::in6_addr_compare(in6_addr a,in6_addr b) +{ + for (size_t i = 0; i < 16; i++) + { + if (a.s6_addr[i] < b.s6_addr[i]) + return -1; + if (a.s6_addr[i] > b.s6_addr[i]) + return 1; + } + return 0; +} +#endif +#endif + + +void Utility::ResolveLocal() +{ + char h[256]; + + // get local hostname and translate into ip-address + *h = 0; + gethostname(h,255); + { + if (Utility::u2ip(h, m_ip)) + { + Utility::l2ip(m_ip, m_addr); + } + } +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + memset(&m_local_ip6, 0, sizeof(m_local_ip6)); + { + if (Utility::u2ip(h, m_local_ip6)) + { + Utility::l2ip(m_local_ip6, m_local_addr6); + } + } +#endif +#endif + m_host = h; + m_local_resolved = true; +} + + +const std::string& Utility::GetLocalHostname() +{ + if (!m_local_resolved) + { + ResolveLocal(); + } + return m_host; +} + + +ipaddr_t Utility::GetLocalIP() +{ + if (!m_local_resolved) + { + ResolveLocal(); + } + return m_ip; +} + + +const std::string& Utility::GetLocalAddress() +{ + if (!m_local_resolved) + { + ResolveLocal(); + } + return m_addr; +} + + +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 +const struct in6_addr& Utility::GetLocalIP6() +{ + if (!m_local_resolved) + { + ResolveLocal(); + } + return m_local_ip6; +} + + +const std::string& Utility::GetLocalAddress6() +{ + if (!m_local_resolved) + { + ResolveLocal(); + } + return m_local_addr6; +} +#endif +#endif + + +void Utility::SetEnv(const std::string& var,const std::string& value) +{ +#if (defined(SOLARIS8) || defined(SOLARIS)) + { + static std::map vmap; + if (vmap.find(var) != vmap.end()) + { + delete[] vmap[var]; + } + vmap[var] = new char[var.size() + 1 + value.size() + 1]; + sprintf(vmap[var], "%s=%s", var.c_str(), value.c_str()); + putenv( vmap[var] ); + } +#elif defined _WIN32 + { + std::string slask = var + "=" + value; + _putenv( (char *)slask.c_str()); + } +#else + setenv(var.c_str(), value.c_str(), 1); +#endif +} + + +std::string Utility::Sa2String(struct sockaddr *sa) +{ +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + if (sa -> sa_family == AF_INET6) + { + struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; + std::string tmp; + Utility::l2ip(sa6 -> sin6_addr, tmp); + return tmp + ":" + Utility::l2string(ntohs(sa6 -> sin6_port)); + } +#endif +#endif + if (sa -> sa_family == AF_INET) + { + struct sockaddr_in *sa4 = (struct sockaddr_in *)sa; + ipaddr_t a; + memcpy(&a, &sa4 -> sin_addr, 4); + std::string tmp; + Utility::l2ip(a, tmp); + return tmp + ":" + Utility::l2string(ntohs(sa4 -> sin_port)); + } + return ""; +} + + +void Utility::GetTime(struct timeval *p) +{ +#ifdef _WIN32 + FILETIME ft; // Contains a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC). + GetSystemTimeAsFileTime(&ft); + uint64_t tt; + memcpy(&tt, &ft, sizeof(tt)); + tt /= 10; // make it usecs + p->tv_sec = (long)tt / 1000000; + p->tv_usec = (long)tt % 1000000; +#else + gettimeofday(p, NULL); +#endif +} + + +std::auto_ptr Utility::CreateAddress(struct sockaddr *sa,socklen_t sa_len) +{ + switch (sa -> sa_family) + { + case AF_INET: + if (sa_len == sizeof(struct sockaddr_in)) + { + struct sockaddr_in *p = (struct sockaddr_in *)sa; + return std::auto_ptr(new Ipv4Address(*p)); + } + break; +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 + case AF_INET6: + if (sa_len == sizeof(struct sockaddr_in6)) + { + struct sockaddr_in6 *p = (struct sockaddr_in6 *)sa; + return std::auto_ptr(new Ipv6Address(*p)); + } + break; +#endif +#endif + } + return std::auto_ptr(NULL); +} + + +bool Utility::u2ip(const std::string& host, struct sockaddr_in& sa, int ai_flags) +{ + memset(&sa, 0, sizeof(sa)); + sa.sin_family = AF_INET; +#ifdef NO_GETADDRINFO + if ((ai_flags & AI_NUMERICHOST) != 0 || isipv4(host)) + { + Parse pa((char *)host.c_str(), "."); + union { + struct { + unsigned char b1; + unsigned char b2; + unsigned char b3; + unsigned char b4; + } a; + ipaddr_t l; + } u; + u.a.b1 = static_cast(pa.getvalue()); + u.a.b2 = static_cast(pa.getvalue()); + u.a.b3 = static_cast(pa.getvalue()); + u.a.b4 = static_cast(pa.getvalue()); + memcpy(&sa.sin_addr, &u.l, sizeof(sa.sin_addr)); + return true; + } +#ifndef LINUX + struct hostent *he = gethostbyname( host.c_str() ); + if (!he) + { + return false; + } + memcpy(&sa.sin_addr, he -> h_addr, sizeof(sa.sin_addr)); +#else + struct hostent he; + struct hostent *result = NULL; + int myerrno = 0; + char buf[2000]; + int n = gethostbyname_r(host.c_str(), &he, buf, sizeof(buf), &result, &myerrno); + if (n || !result) + { + return false; + } + if (he.h_addr_list && he.h_addr_list[0]) + memcpy(&sa.sin_addr, he.h_addr, 4); + else + return false; +#endif + return true; +#else + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + // AI_NUMERICHOST + // AI_CANONNAME + // AI_PASSIVE - server + // AI_ADDRCONFIG + // AI_V4MAPPED + // AI_ALL + // AI_NUMERICSERV + hints.ai_flags = ai_flags; + hints.ai_family = AF_INET; + hints.ai_socktype = 0; + hints.ai_protocol = 0; + struct addrinfo *res; + if (Utility::isipv4(host)) + hints.ai_flags |= AI_NUMERICHOST; + int n = getaddrinfo(host.c_str(), NULL, &hints, &res); + if (!n) + { + std::vector vec; + struct addrinfo *ai = res; + while (ai) + { + if (ai -> ai_addrlen == sizeof(sa)) + vec.push_back( ai ); + ai = ai -> ai_next; + } + if (vec.empty()) + return false; + ai = vec[Utility::Rnd() % vec.size()]; + { + memcpy(&sa, ai -> ai_addr, ai -> ai_addrlen); + } + freeaddrinfo(res); + return true; + } + std::string error = "Error: "; +#ifndef __CYGWIN__ + error += gai_strerror(n); +#endif + return false; +#endif // NO_GETADDRINFO +} + + +#ifdef ENABLE_IPV6 +#ifdef IPPROTO_IPV6 +bool Utility::u2ip(const std::string& host, struct sockaddr_in6& sa, int ai_flags) +{ + memset(&sa, 0, sizeof(sa)); + sa.sin6_family = AF_INET6; +#ifdef NO_GETADDRINFO + if ((ai_flags & AI_NUMERICHOST) != 0 || isipv6(host)) + { + std::list vec; + size_t x = 0; + for (size_t i = 0; i <= host.size(); i++) + { + if (i == host.size() || host[i] == ':') + { + std::string s = host.substr(x, i - x); + // + if (strstr(s.c_str(),".")) // x.x.x.x + { + Parse pa(s,"."); + char slask[100]; // u2ip temporary hex2string conversion + unsigned long b0 = static_cast(pa.getvalue()); + unsigned long b1 = static_cast(pa.getvalue()); + unsigned long b2 = static_cast(pa.getvalue()); + unsigned long b3 = static_cast(pa.getvalue()); + sprintf(slask,"%lx",b0 * 256 + b1); + vec.push_back(slask); + sprintf(slask,"%lx",b2 * 256 + b3); + vec.push_back(slask); + } + else + { + vec.push_back(s); + } + // + x = i + 1; + } + } + size_t sz = vec.size(); // number of byte pairs + size_t i = 0; // index in in6_addr.in6_u.u6_addr16[] ( 0 .. 7 ) + unsigned short addr16[8]; + for (std::list::iterator it = vec.begin(); it != vec.end(); it++) + { + std::string bytepair = *it; + if (!bytepair.empty()) + { + addr16[i++] = htons(Utility::hex2unsigned(bytepair)); + } + else + { + addr16[i++] = 0; + while (sz++ < 8) + { + addr16[i++] = 0; + } + } + } + memcpy(&sa.sin6_addr, addr16, sizeof(addr16)); + return true; + } +#ifdef SOLARIS + int errnum = 0; + struct hostent *he = getipnodebyname( host.c_str(), AF_INET6, 0, &errnum ); +#else + struct hostent *he = gethostbyname2( host.c_str(), AF_INET6 ); +#endif + if (!he) + { + return false; + } + memcpy(&sa.sin6_addr,he -> h_addr_list[0],he -> h_length); +#ifdef SOLARIS + free(he); +#endif + return true; +#else + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = ai_flags; + hints.ai_family = AF_INET6; + hints.ai_socktype = 0; + hints.ai_protocol = 0; + struct addrinfo *res; + if (Utility::isipv6(host)) + hints.ai_flags |= AI_NUMERICHOST; + int n = getaddrinfo(host.c_str(), NULL, &hints, &res); + if (!n) + { + std::vector vec; + struct addrinfo *ai = res; + while (ai) + { + if (ai -> ai_addrlen == sizeof(sa)) + vec.push_back( ai ); + ai = ai -> ai_next; + } + if (vec.empty()) + return false; + ai = vec[Utility::Rnd() % vec.size()]; + { + memcpy(&sa, ai -> ai_addr, ai -> ai_addrlen); + } + freeaddrinfo(res); + return true; + } + std::string error = "Error: "; +#ifndef __CYGWIN__ + error += gai_strerror(n); +#endif + return false; +#endif // NO_GETADDRINFO +} +#endif // IPPROTO_IPV6 +#endif // ENABLE_IPV6 + + +bool Utility::reverse(struct sockaddr *sa, socklen_t sa_len, std::string& hostname, int flags) +{ + std::string service; + return Utility::reverse(sa, sa_len, hostname, service, flags); +} + + +bool Utility::reverse(struct sockaddr *sa, socklen_t sa_len, std::string& hostname, std::string& service, int flags) +{ + hostname = ""; + service = ""; +#ifdef NO_GETADDRINFO + switch (sa -> sa_family) + { + case AF_INET: + if (flags & NI_NUMERICHOST) + { + union { + struct { + unsigned char b1; + unsigned char b2; + unsigned char b3; + unsigned char b4; + } a; + ipaddr_t l; + } u; + struct sockaddr_in *sa_in = (struct sockaddr_in *)sa; + memcpy(&u.l, &sa_in -> sin_addr, sizeof(u.l)); + char tmp[100]; + sprintf(tmp, "%u.%u.%u.%u", u.a.b1, u.a.b2, u.a.b3, u.a.b4); + hostname = tmp; + return true; + } + else + { + struct sockaddr_in *sa_in = (struct sockaddr_in *)sa; + struct hostent *h = gethostbyaddr( (const char *)&sa_in -> sin_addr, sizeof(sa_in -> sin_addr), AF_INET); + if (h) + { + hostname = h -> h_name; + return true; + } + } + break; +#ifdef ENABLE_IPV6 + case AF_INET6: + if (flags & NI_NUMERICHOST) + { + char slask[100]; // l2ip temporary + *slask = 0; + unsigned int prev = 0; + bool skipped = false; + bool ok_to_skip = true; + { + unsigned short addr16[8]; + struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)sa; + memcpy(addr16, &sa_in6 -> sin6_addr, sizeof(addr16)); + for (size_t i = 0; i < 8; i++) + { + unsigned short x = ntohs(addr16[i]); + if (*slask && (x || !ok_to_skip || prev)) + strcat(slask,":"); + if (x || !ok_to_skip) + { + sprintf(slask + strlen(slask),"%x", x); + if (x && skipped) + ok_to_skip = false; + } + else + { + skipped = true; + } + prev = x; + } + } + if (!*slask) + strcpy(slask, "::"); + hostname = slask; + return true; + } + else + { + // %! TODO: ipv6 reverse lookup + struct sockaddr_in6 *sa_in = (struct sockaddr_in6 *)sa; + struct hostent *h = gethostbyaddr( (const char *)&sa_in -> sin6_addr, sizeof(sa_in -> sin6_addr), AF_INET6); + if (h) + { + hostname = h -> h_name; + return true; + } + } + break; +#endif + } + return false; +#else + char host[NI_MAXHOST]; + char serv[NI_MAXSERV]; + // NI_NOFQDN + // NI_NUMERICHOST + // NI_NAMEREQD + // NI_NUMERICSERV + // NI_DGRAM + int n = getnameinfo(sa, sa_len, host, sizeof(host), serv, sizeof(serv), flags); + if (n) + { + // EAI_AGAIN + // EAI_BADFLAGS + // EAI_FAIL + // EAI_FAMILY + // EAI_MEMORY + // EAI_NONAME + // EAI_OVERFLOW + // EAI_SYSTEM + return false; + } + hostname = host; + service = serv; + return true; +#endif // NO_GETADDRINFO +} + + +bool Utility::u2service(const std::string& name, int& service, int ai_flags) +{ +#ifdef NO_GETADDRINFO + // %! + return false; +#else + struct addrinfo hints; + service = 0; + memset(&hints, 0, sizeof(hints)); + // AI_NUMERICHOST + // AI_CANONNAME + // AI_PASSIVE - server + // AI_ADDRCONFIG + // AI_V4MAPPED + // AI_ALL + // AI_NUMERICSERV + hints.ai_flags = ai_flags; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = 0; + hints.ai_protocol = 0; + struct addrinfo *res; + int n = getaddrinfo(NULL, name.c_str(), &hints, &res); + if (!n) + { + service = res -> ai_protocol; + freeaddrinfo(res); + return true; + } + return false; +#endif // NO_GETADDRINFO +} + + +unsigned long Utility::ThreadID() +{ +#ifdef _WIN32 + return GetCurrentThreadId(); +#else + return (unsigned long)pthread_self(); +#endif +} + + +std::string Utility::ToLower(const std::string& str) +{ + std::string r; + for (size_t i = 0; i < str.size(); i++) + { + if (str[i] >= 'A' && str[i] <= 'Z') + r += str[i] | 32; + else + r += str[i]; + } + return r; +} + + +std::string Utility::ToUpper(const std::string& str) +{ + std::string r; + for (size_t i = 0; i < str.size(); i++) + { + if (str[i] >= 'a' && str[i] <= 'z') + r += (char)(str[i] - 32); + else + r += str[i]; + } + return r; +} + + +std::string Utility::ToString(double d) +{ + char tmp[100]; + sprintf(tmp, "%f", d); + return tmp; +} + + +unsigned long Utility::Rnd() +{ +static Utility::Rng generator( (unsigned long)time(NULL) ); + return generator.Get(); +} + + +Utility::Rng::Rng(unsigned long seed) : m_value( 0 ) +{ + m_tmp[0]= seed & 0xffffffffUL; + for (int i = 1; i < TWIST_LEN; i++) + { + m_tmp[i] = (1812433253UL * (m_tmp[i - 1] ^ (m_tmp[i - 1] >> 30)) + i); + } +} + + +unsigned long Utility::Rng::Get() +{ + unsigned long val = m_tmp[m_value]; + ++m_value; + if (m_value == TWIST_LEN) + { + for (int i = 0; i < TWIST_IB; ++i) + { + unsigned long s = TWIST(m_tmp, i, i + 1); + m_tmp[i] = m_tmp[i + TWIST_IA] ^ (s >> 1) ^ MAGIC_TWIST(s); + } + { + for (int i = 0; i < TWIST_LEN - 1; ++i) + { + unsigned long s = TWIST(m_tmp, i, i + 1); + m_tmp[i] = m_tmp[i - TWIST_IB] ^ (s >> 1) ^ MAGIC_TWIST(s); + } + } + unsigned long s = TWIST(m_tmp, TWIST_LEN - 1, 0); + m_tmp[TWIST_LEN - 1] = m_tmp[TWIST_IA - 1] ^ (s >> 1) ^ MAGIC_TWIST(s); + + m_value = 0; + } + return val; +} + +#ifdef SOCKETS_NAMESPACE +} +#endif + diff --git a/dep/src/sockets/network_kist.txt b/dep/src/sockets/network_kist.txt new file mode 100644 index 00000000000..f6597bf9c77 --- /dev/null +++ b/dep/src/sockets/network_kist.txt @@ -0,0 +1,20 @@ +The following are the only .cpp files used from the new network library (v2.2.8) This file is just for future reference. + +Base64.cpp +Exception.cpp +Ipv4Address.cpp +Ipv6Address.cpp +Lock.cpp +Mutex.cpp +Parse.cpp +ResolvServer.cpp +ResolvSocket.cpp +Socket.cpp +SocketHandler.cpp +socket_include.cpp +StdoutLog.cpp +StreamSocket.cpp +TcpSocket.cpp +Thread.cpp +UdpSocket.cpp +Utility.cpp diff --git a/dep/src/sockets/socket_include.cpp b/dep/src/sockets/socket_include.cpp new file mode 100644 index 00000000000..07b986b02b7 --- /dev/null +++ b/dep/src/sockets/socket_include.cpp @@ -0,0 +1,90 @@ +/** \file socket_include.cpp + ** \date 2004-11-28 + ** \author grymse@alhem.net +**/ +/* +Copyright (C) 2004-2007 Anders Hedstrom + +This library is made available under the terms of the GNU GPL. + +If you would like to use this library in a closed-source application, +a separate license agreement is available. For information about +the closed-source license agreement for the C++ sockets library, +please visit http://www.alhem.net/Sockets/license.html and/or +email license@alhem.net. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#include + +// only to be included in win32 projects +const char *StrError(int x) +{ +static char tmp[100]; + switch (x) + { + case 10004: return "Interrupted function call."; + case 10013: return "Permission denied."; + case 10014: return "Bad address."; + case 10022: return "Invalid argument."; + case 10024: return "Too many open files."; + case 10035: return "Resource temporarily unavailable."; + case 10036: return "Operation now in progress."; + case 10037: return "Operation already in progress."; + case 10038: return "Socket operation on nonsocket."; + case 10039: return "Destination address required."; + case 10040: return "Message too long."; + case 10041: return "Protocol wrong type for socket."; + case 10042: return "Bad protocol option."; + case 10043: return "Protocol not supported."; + case 10044: return "Socket type not supported."; + case 10045: return "Operation not supported."; + case 10046: return "Protocol family not supported."; + case 10047: return "Address family not supported by protocol family."; + case 10048: return "Address already in use."; + case 10049: return "Cannot assign requested address."; + case 10050: return "Network is down."; + case 10051: return "Network is unreachable."; + case 10052: return "Network dropped connection on reset."; + case 10053: return "Software caused connection abort."; + case 10054: return "Connection reset by peer."; + case 10055: return "No buffer space available."; + case 10056: return "Socket is already connected."; + case 10057: return "Socket is not connected."; + case 10058: return "Cannot send after socket shutdown."; + case 10060: return "Connection timed out."; + case 10061: return "Connection refused."; + case 10064: return "Host is down."; + case 10065: return "No route to host."; + case 10067: return "Too many processes."; + case 10091: return "Network subsystem is unavailable."; + case 10092: return "Winsock.dll version out of range."; + case 10093: return "Successful WSAStartup not yet performed."; + case 10101: return "Graceful shutdown in progress."; + case 10109: return "Class type not found."; + case 11001: return "Host not found."; + case 11002: return "Nonauthoritative host not found."; + case 11003: return "This is a nonrecoverable error."; + case 11004: return "Valid name, no data record of requested type."; + + default: + break; + } + sprintf(tmp, "Winsock error code: %d", x); + return tmp; +} + + + diff --git a/dep/src/zlib/Makefile.am b/dep/src/zlib/Makefile.am new file mode 100644 index 00000000000..2f7bf2373be --- /dev/null +++ b/dep/src/zlib/Makefile.am @@ -0,0 +1,56 @@ +## Modified for MaNGOS project +## +## 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. + +## Process this file with automake to produce Makefile.in + +## CPP flags for includes, defines, etc. +AM_CPPFLAGS = -I$(srcdir) -I$(srcdir)/../../include -I$(srcdir)/../../include/zlib + +## Build zlib as convenience library. +# libzlib conveniece library will later be reused by ... +noinst_LIBRARIES = libzlib.a +libzlib_a_SOURCES = \ + adler32.c \ + compress.c \ + crc32.c \ + deflate.c \ + example.c \ + gzio.c \ + infback.c \ + inffast.c \ + inflate.c \ + inftrees.c \ + trees.c \ + uncompr.c \ + zutil.c + +## Additional files to include when running 'make dist' +# Nothing yet. +EXTRA_DIST = \ + crc32.h \ + deflate.h \ + inffast.h \ + inffixed.h \ + inflate.h \ + inftrees.h \ + trees.h \ + zconf.h \ + zlib.h \ + zutil.h + diff --git a/dep/src/zlib/adler32.c b/dep/src/zlib/adler32.c new file mode 100644 index 00000000000..007ba26277c --- /dev/null +++ b/dep/src/zlib/adler32.c @@ -0,0 +1,149 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +#define BASE 65521UL /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* use NO_DIVIDE if your processor does not do division in hardware */ +#ifdef NO_DIVIDE +# define MOD(a) \ + do { \ + if (a >= (BASE << 16)) a -= (BASE << 16); \ + if (a >= (BASE << 15)) a -= (BASE << 15); \ + if (a >= (BASE << 14)) a -= (BASE << 14); \ + if (a >= (BASE << 13)) a -= (BASE << 13); \ + if (a >= (BASE << 12)) a -= (BASE << 12); \ + if (a >= (BASE << 11)) a -= (BASE << 11); \ + if (a >= (BASE << 10)) a -= (BASE << 10); \ + if (a >= (BASE << 9)) a -= (BASE << 9); \ + if (a >= (BASE << 8)) a -= (BASE << 8); \ + if (a >= (BASE << 7)) a -= (BASE << 7); \ + if (a >= (BASE << 6)) a -= (BASE << 6); \ + if (a >= (BASE << 5)) a -= (BASE << 5); \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +# define MOD4(a) \ + do { \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +# define MOD4(a) a %= BASE +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long sum2; + unsigned n; + + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (len == 1) { + adler += buf[0]; + if (adler >= BASE) + adler -= BASE; + sum2 += adler; + if (sum2 >= BASE) + sum2 -= BASE; + return adler | (sum2 << 16); + } + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (buf == Z_NULL) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (len < 16) { + while (len--) { + adler += *buf++; + sum2 += adler; + } + if (adler >= BASE) + adler -= BASE; + MOD4(sum2); /* only added so many BASE's */ + return adler | (sum2 << 16); + } + + /* do length NMAX blocks -- requires just one modulo operation */ + while (len >= NMAX) { + len -= NMAX; + n = NMAX / 16; /* NMAX is divisible by 16 */ + do { + DO16(buf); /* 16 sums unrolled */ + buf += 16; + } while (--n); + MOD(adler); + MOD(sum2); + } + + /* do remaining bytes (less than NMAX, still just one modulo) */ + if (len) { /* avoid modulos if none remaining */ + while (len >= 16) { + len -= 16; + DO16(buf); + buf += 16; + } + while (len--) { + adler += *buf++; + sum2 += adler; + } + MOD(adler); + MOD(sum2); + } + + /* return recombined sums */ + return adler | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32_combine(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off_t len2; +{ + unsigned long sum1; + unsigned long sum2; + unsigned rem; + + /* the derivation of this formula is left as an exercise for the reader */ + rem = (unsigned)(len2 % BASE); + sum1 = adler1 & 0xffff; + sum2 = rem * sum1; + MOD(sum2); + sum1 += (adler2 & 0xffff) + BASE - 1; + sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; + if (sum1 > BASE) sum1 -= BASE; + if (sum1 > BASE) sum1 -= BASE; + if (sum2 > (BASE << 1)) sum2 -= (BASE << 1); + if (sum2 > BASE) sum2 -= BASE; + return sum1 | (sum2 << 16); +} diff --git a/dep/src/zlib/compress.c b/dep/src/zlib/compress.c new file mode 100644 index 00000000000..df04f0148e6 --- /dev/null +++ b/dep/src/zlib/compress.c @@ -0,0 +1,79 @@ +/* compress.c -- compress a memory buffer + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ +int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; + int level; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; +#ifdef MAXSEG_64K + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; +#endif + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = deflateInit(&stream, level); + if (err != Z_OK) return err; + + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + deflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = deflateEnd(&stream); + return err; +} + +/* =========================================================================== + */ +int ZEXPORT compress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} + +/* =========================================================================== + If the default memLevel or windowBits for deflateInit() is changed, then + this function needs to be updated. + */ +uLong ZEXPORT compressBound (sourceLen) + uLong sourceLen; +{ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11; +} diff --git a/dep/src/zlib/crc32.c b/dep/src/zlib/crc32.c new file mode 100644 index 00000000000..f658a9ef55e --- /dev/null +++ b/dep/src/zlib/crc32.c @@ -0,0 +1,423 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results in about a + * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* @(#) $Id$ */ + +/* + Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore + protection on the static variables used to control the first-use generation + of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should + first call get_crc_table() to initialize the tables before allowing more than + one thread to use crc32(). + */ + +#ifdef MAKECRCH +# include +# ifndef DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE +# endif /* !DYNAMIC_CRC_TABLE */ +#endif /* MAKECRCH */ + +#include "zutil.h" /* for STDC and FAR definitions */ + +#define local static + +/* Find a four-byte integer type for crc32_little() and crc32_big(). */ +#ifndef NOBYFOUR +# ifdef STDC /* need ANSI C limits.h to determine sizes */ +# include +# define BYFOUR +# if (UINT_MAX == 0xffffffffUL) + typedef unsigned int u4; +# else +# if (ULONG_MAX == 0xffffffffUL) + typedef unsigned long u4; +# else +# if (USHRT_MAX == 0xffffffffUL) + typedef unsigned short u4; +# else +# undef BYFOUR /* can't find a four-byte integer type! */ +# endif +# endif +# endif +# endif /* STDC */ +#endif /* !NOBYFOUR */ + +/* Definitions for doing the crc four data bytes at a time. */ +#ifdef BYFOUR +# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \ + (((w)&0xff00)<<8)+(((w)&0xff)<<24)) + local unsigned long crc32_little OF((unsigned long, + const unsigned char FAR *, unsigned)); + local unsigned long crc32_big OF((unsigned long, + const unsigned char FAR *, unsigned)); +# define TBLS 8 +#else +# define TBLS 1 +#endif /* BYFOUR */ + +/* Local functions for crc concatenation */ +local unsigned long gf2_matrix_times OF((unsigned long *mat, + unsigned long vec)); +local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); + +#ifdef DYNAMIC_CRC_TABLE + +local volatile int crc_table_empty = 1; +local unsigned long FAR crc_table[TBLS][256]; +local void make_crc_table OF((void)); +#ifdef MAKECRCH + local void write_table OF((FILE *, const unsigned long FAR *)); +#endif /* MAKECRCH */ +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The first table is simply the CRC of all possible eight bit values. This is + all the information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. The remaining tables + allow for word-at-a-time CRC calculation for both big-endian and little- + endian machines, where a word is four bytes. +*/ +local void make_crc_table() +{ + unsigned long c; + int n, k; + unsigned long poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static volatile int first = 1; /* flag to limit concurrent making */ + static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* See if another task is already doing this (not thread-safe, but better + than nothing -- significantly reduces duration of vulnerability in + case the advice about DYNAMIC_CRC_TABLE is ignored) */ + if (first) { + first = 0; + + /* make exclusive-or pattern from polynomial (0xedb88320UL) */ + poly = 0UL; + for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) + poly |= 1UL << (31 - p[n]); + + /* generate a crc for every 8-bit value */ + for (n = 0; n < 256; n++) { + c = (unsigned long)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[0][n] = c; + } + +#ifdef BYFOUR + /* generate crc for each value followed by one, two, and three zeros, + and then the byte reversal of those as well as the first table */ + for (n = 0; n < 256; n++) { + c = crc_table[0][n]; + crc_table[4][n] = REV(c); + for (k = 1; k < 4; k++) { + c = crc_table[0][c & 0xff] ^ (c >> 8); + crc_table[k][n] = c; + crc_table[k + 4][n] = REV(c); + } + } +#endif /* BYFOUR */ + + crc_table_empty = 0; + } + else { /* not first */ + /* wait for the other guy to finish (not efficient, but rare) */ + while (crc_table_empty) + ; + } + +#ifdef MAKECRCH + /* write out CRC tables to crc32.h */ + { + FILE *out; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); + fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); + fprintf(out, "local const unsigned long FAR "); + fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); + write_table(out, crc_table[0]); +# ifdef BYFOUR + fprintf(out, "#ifdef BYFOUR\n"); + for (k = 1; k < 8; k++) { + fprintf(out, " },\n {\n"); + write_table(out, crc_table[k]); + } + fprintf(out, "#endif\n"); +# endif /* BYFOUR */ + fprintf(out, " }\n};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH +local void write_table(out, table) + FILE *out; + const unsigned long FAR *table; +{ + int n; + + for (n = 0; n < 256; n++) + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], + n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); +} +#endif /* MAKECRCH */ + +#else /* !DYNAMIC_CRC_TABLE */ +/* ======================================================================== + * Tables of CRC-32s of all single-byte values, made by make_crc_table(). + */ +#include "crc32.h" +#endif /* DYNAMIC_CRC_TABLE */ + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const unsigned long FAR * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + return (const unsigned long FAR *)crc_table; +} + +/* ========================================================================= */ +#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + if (buf == Z_NULL) return 0UL; + +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + +#ifdef BYFOUR + if (sizeof(void *) == sizeof(ptrdiff_t)) { + u4 endian; + + endian = 1; + if (*((unsigned char *)(&endian))) + return crc32_little(crc, buf, len); + else + return crc32_big(crc, buf, len); + } +#endif /* BYFOUR */ + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; +} + +#ifdef BYFOUR + +/* ========================================================================= */ +#define DOLIT4 c ^= *buf4++; \ + c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] +#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 + +/* ========================================================================= */ +local unsigned long crc32_little(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = (u4)crc; + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + len--; + } + + buf4 = (const u4 FAR *)(const void FAR *)buf; + while (len >= 32) { + DOLIT32; + len -= 32; + } + while (len >= 4) { + DOLIT4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + } while (--len); + c = ~c; + return (unsigned long)c; +} + +/* ========================================================================= */ +#define DOBIG4 c ^= *++buf4; \ + c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] +#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + +/* ========================================================================= */ +local unsigned long crc32_big(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = REV((u4)crc); + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + len--; + } + + buf4 = (const u4 FAR *)(const void FAR *)buf; + buf4--; + while (len >= 32) { + DOBIG32; + len -= 32; + } + while (len >= 4) { + DOBIG4; + len -= 4; + } + buf4++; + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + } while (--len); + c = ~c; + return (unsigned long)(REV(c)); +} + +#endif /* BYFOUR */ + +#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ + +/* ========================================================================= */ +local unsigned long gf2_matrix_times(mat, vec) + unsigned long *mat; + unsigned long vec; +{ + unsigned long sum; + + sum = 0; + while (vec) { + if (vec & 1) + sum ^= *mat; + vec >>= 1; + mat++; + } + return sum; +} + +/* ========================================================================= */ +local void gf2_matrix_square(square, mat) + unsigned long *square; + unsigned long *mat; +{ + int n; + + for (n = 0; n < GF2_DIM; n++) + square[n] = gf2_matrix_times(mat, mat[n]); +} + +/* ========================================================================= */ +uLong ZEXPORT crc32_combine(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off_t len2; +{ + int n; + unsigned long row; + unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ + unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ + + /* degenerate case */ + if (len2 == 0) + return crc1; + + /* put operator for one zero bit in odd */ + odd[0] = 0xedb88320L; /* CRC-32 polynomial */ + row = 1; + for (n = 1; n < GF2_DIM; n++) { + odd[n] = row; + row <<= 1; + } + + /* put operator for two zero bits in even */ + gf2_matrix_square(even, odd); + + /* put operator for four zero bits in odd */ + gf2_matrix_square(odd, even); + + /* apply len2 zeros to crc1 (first square will put the operator for one + zero byte, eight zero bits, in even) */ + do { + /* apply zeros operator for this bit of len2 */ + gf2_matrix_square(even, odd); + if (len2 & 1) + crc1 = gf2_matrix_times(even, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + if (len2 == 0) + break; + + /* another iteration of the loop with odd and even swapped */ + gf2_matrix_square(odd, even); + if (len2 & 1) + crc1 = gf2_matrix_times(odd, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + } while (len2 != 0); + + /* return combined crc */ + crc1 ^= crc2; + return crc1; +} diff --git a/dep/src/zlib/crc32.h b/dep/src/zlib/crc32.h new file mode 100644 index 00000000000..8053b6117c0 --- /dev/null +++ b/dep/src/zlib/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const unsigned long FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/dep/src/zlib/deflate.c b/dep/src/zlib/deflate.c new file mode 100644 index 00000000000..29ce1f64a57 --- /dev/null +++ b/dep/src/zlib/deflate.c @@ -0,0 +1,1736 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in http://www.ietf.org/rfc/rfc1951.txt + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id$ */ + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.2.3 Copyright 1995-2005 Jean-loup Gailly "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +#ifndef FASTEST +local block_state deflate_slow OF((deflate_state *s, int flush)); +#endif +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifndef FASTEST +#ifdef ASMV + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif +#endif +local uInt longest_match_fast OF((deflate_state *s, IPos cur_match)); + +#ifdef DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +#ifdef FASTEST +local const config configuration_table[2] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ +#else +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ +#endif + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +#ifndef NO_DUMMY_DECL +struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ +#endif + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of str are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + deflate_state *s; + int wrap = 1; + static const char my_version[] = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } +#ifdef GZIP + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } +#endif + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + + s->wrap = wrap; + s->gzhead = Z_NULL; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + s->status = FINISH_STATE; + strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; + + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || + strm->state->wrap == 2 || + (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) + return Z_STREAM_ERROR; + + s = strm->state; + if (s->wrap) + strm->adler = adler32(strm->adler, dictionary, dictLength); + + if (length < MIN_MATCH) return Z_OK; + if (length > MAX_DIST(s)) { + length = MAX_DIST(s); + dictionary += dictLength - length; /* use the tail of the dictionary */ + } + zmemcpy(s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; + + /* Insert all strings in the hash table (except for the last two bytes). + * s->lookahead stays null, so s->ins_h will be recomputed at the next + * call of fill_window. + */ + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { + return Z_STREAM_ERROR; + } + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->wrap < 0) { + s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ + } + s->status = s->wrap ? INIT_STATE : BUSY_STATE; + strm->adler = +#ifdef GZIP + s->wrap == 2 ? crc32(0L, Z_NULL, 0) : +#endif + adler32(0L, Z_NULL, 0); + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + lm_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateSetHeader (strm, head) + z_streamp strm; + gz_headerp head; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (strm->state->wrap != 2) return Z_STREAM_ERROR; + strm->state->gzhead = head; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflatePrime (strm, bits, value) + z_streamp strm; + int bits; + int value; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + strm->state->bi_valid = bits; + strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(strm, level, strategy) + z_streamp strm; + int level; + int strategy; +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if (func != configuration_table[level].func && strm->total_in != 0) { + /* Flush the last buffer: */ + err = deflate(strm, Z_PARTIAL_FLUSH); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} + +/* ========================================================================= */ +int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) + z_streamp strm; + int good_length; + int max_lazy; + int nice_length; + int max_chain; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + s->good_match = good_length; + s->max_lazy_match = max_lazy; + s->nice_match = nice_length; + s->max_chain_length = max_chain; + return Z_OK; +} + +/* ========================================================================= + * For the default windowBits of 15 and memLevel of 8, this function returns + * a close to exact, as well as small, upper bound on the compressed size. + * They are coded as constants here for a reason--if the #define's are + * changed, then this function needs to be changed as well. The return + * value for 15 and 8 only works for those exact settings. + * + * For any setting other than those defaults for windowBits and memLevel, + * the value returned is a conservative worst case for the maximum expansion + * resulting from using fixed blocks instead of stored blocks, which deflate + * can emit on compressed data for some combinations of the parameters. + * + * This function could be more sophisticated to provide closer upper bounds + * for every combination of windowBits and memLevel, as well as wrap. + * But even the conservative upper bound of about 14% expansion does not + * seem onerous for output buffer allocation. + */ +uLong ZEXPORT deflateBound(strm, sourceLen) + z_streamp strm; + uLong sourceLen; +{ + deflate_state *s; + uLong destLen; + + /* conservative upper bound */ + destLen = sourceLen + + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 11; + + /* if can't get parameters, return conservative bound */ + if (strm == Z_NULL || strm->state == Z_NULL) + return destLen; + + /* if not default parameters, return conservative bound */ + s = strm->state; + if (s->w_bits != 15 || s->hash_bits != 8 + 7) + return destLen; + + /* default settings: return tight bound for that case */ + return compressBound(sourceLen); +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->next_out buffer and copying into it. + * (See also read_buf()). + */ +local void flush_pending(strm) + z_streamp strm; +{ + unsigned len = strm->state->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } +} + +/* ========================================================================= */ +int ZEXPORT deflate (strm, flush) + z_streamp strm; + int flush; +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_FINISH || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the header */ + if (s->status == INIT_STATE) { +#ifdef GZIP + if (s->wrap == 2) { + strm->adler = crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (s->gzhead == NULL) { + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s->status = BUSY_STATE; + } + else { + put_byte(s, (s->gzhead->text ? 1 : 0) + + (s->gzhead->hcrc ? 2 : 0) + + (s->gzhead->extra == Z_NULL ? 0 : 4) + + (s->gzhead->name == Z_NULL ? 0 : 8) + + (s->gzhead->comment == Z_NULL ? 0 : 16) + ); + put_byte(s, (Byte)(s->gzhead->time & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, s->gzhead->os & 0xff); + if (s->gzhead->extra != NULL) { + put_byte(s, s->gzhead->extra_len & 0xff); + put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); + } + if (s->gzhead->hcrc) + strm->adler = crc32(strm->adler, s->pending_buf, + s->pending); + s->gzindex = 0; + s->status = EXTRA_STATE; + } + } + else +#endif + { + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags; + + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; + else + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = adler32(0L, Z_NULL, 0); + } + } +#ifdef GZIP + if (s->status == EXTRA_STATE) { + if (s->gzhead->extra != NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + + while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) + break; + } + put_byte(s, s->gzhead->extra[s->gzindex]); + s->gzindex++; + } + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (s->gzindex == s->gzhead->extra_len) { + s->gzindex = 0; + s->status = NAME_STATE; + } + } + else + s->status = NAME_STATE; + } + if (s->status == NAME_STATE) { + if (s->gzhead->name != NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; + + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->name[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) { + s->gzindex = 0; + s->status = COMMENT_STATE; + } + } + else + s->status = COMMENT_STATE; + } + if (s->status == COMMENT_STATE) { + if (s->gzhead->comment != NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; + + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->comment[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) + s->status = HCRC_STATE; + } + else + s->status = HCRC_STATE; + } + if (s->status == HCRC_STATE) { + if (s->gzhead->hcrc) { + if (s->pending + 2 > s->pending_buf_size) + flush_pending(strm); + if (s->pending + 2 <= s->pending_buf_size) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + strm->adler = crc32(0L, Z_NULL, 0); + s->status = BUSY_STATE; + } + } + else + s->status = BUSY_STATE; + } +#endif + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = (*(configuration_table[s->level].func))(s, flush); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->wrap <= 0) return Z_STREAM_END; + + /* Write the trailer */ +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); + put_byte(s, (Byte)(strm->total_in & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); + } + else +#endif + { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (strm) + z_streamp strm; +{ + int status; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + status = strm->state->status; + if (status != INIT_STATE && + status != EXTRA_STATE && + status != NAME_STATE && + status != COMMENT_STATE && + status != HCRC_STATE && + status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (dest, source) + z_streamp dest; + z_streamp source; +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + zmemcpy(dest, source, sizeof(z_stream)); + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + zmemcpy(ds, ss, sizeof(deflate_state)); + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif /* MAXSEG_64K */ +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local int read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + if (strm->state->wrap == 1) { + strm->adler = adler32(strm->adler, strm->next_in, len); + } +#ifdef GZIP + else if (strm->state->wrap == 2) { + strm->adler = crc32(strm->adler, strm->next_in, len); + } +#endif + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (s) + deflate_state *s; +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifndef FASTEST +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +#endif +} + +#ifndef FASTEST +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2. Note that the checks below + * for insufficient lookahead only occur occasionally for performance + * reasons. Therefore uninitialized memory will be accessed, and + * conditional jumps will be made that depend on those values. + * However the length of the match is limited to the lookahead, so + * the output of deflate is not affected by the uninitialized values. + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} +#endif /* ASMV */ +#endif /* FASTEST */ + +/* --------------------------------------------------------------------------- + * Optimized version for level == 1 or strategy == Z_RLE only + */ +local uInt longest_match_fast(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; +} + +#ifdef DEBUG +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(s, start, match, length) + deflate_state *s; + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif /* DEBUG */ + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(s) + deflate_state *s; +{ + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (sizeof(int) <= 2) { + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if + * strstart == 0 && lookahead == 1 (input done a byte at time) + */ + more--; + } + } + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + /* %%% avoid this when Z_RLE */ + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) return; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, eof) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (eof)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, eof) { \ + FLUSH_BLOCK_ONLY(s, eof); \ + if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +local block_state deflate_stored(s, flush) + deflate_state *s; + int flush; +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ +#ifdef FASTEST + if ((s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) || + (s->strategy == Z_RLE && s->strstart - hash_head == 1)) { + s->match_length = longest_match_fast (s, hash_head); + } +#else + if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } +#endif + /* longest_match() or longest_match_fast() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +#ifndef FASTEST +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } + /* longest_match() or longest_match_fast() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED +#if TOO_FAR <= 32767 + || (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR) +#endif + )) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} +#endif /* FASTEST */ + +#if 0 +/* =========================================================================== + * For Z_RLE, simply look for runs of bytes, generate matches only of distance + * one. Do not maintain a hash table. (It will be regenerated if this run of + * deflate switches away from Z_RLE.) + */ +local block_state deflate_rle(s, flush) + deflate_state *s; + int flush; +{ + int bflush; /* set if current block must be flushed */ + uInt run; /* length of run */ + uInt max; /* maximum length of run */ + uInt prev; /* byte at distance one to match */ + Bytef *scan; /* scan for end of run */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the longest encodable run. + */ + if (s->lookahead < MAX_MATCH) { + fill_window(s); + if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* See how many times the previous byte repeats */ + run = 0; + if (s->strstart > 0) { /* if there is a previous byte, that is */ + max = s->lookahead < MAX_MATCH ? s->lookahead : MAX_MATCH; + scan = s->window + s->strstart - 1; + prev = *scan++; + do { + if (*scan++ != prev) + break; + } while (++run < max); + } + + /* Emit match if have run of MIN_MATCH or longer, else emit literal */ + if (run >= MIN_MATCH) { + check_match(s, s->strstart, s->strstart - 1, run); + _tr_tally_dist(s, 1, run - MIN_MATCH, bflush); + s->lookahead -= run; + s->strstart += run; + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} +#endif diff --git a/dep/src/zlib/deflate.h b/dep/src/zlib/deflate.h new file mode 100644 index 00000000000..05a5ab3a2c1 --- /dev/null +++ b/dep/src/zlib/deflate.h @@ -0,0 +1,331 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2004 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef DEFLATE_H +#define DEFLATE_H + +#include "zutil.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define EXTRA_STATE 69 +#define NAME_STATE 73 +#define COMMENT_STATE 91 +#define HCRC_STATE 103 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + uInt pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + gz_headerp gzhead; /* gzip header information to write */ + uInt gzindex; /* where in extra, name, or comment */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + + /* in trees.c */ +void _tr_init OF((deflate_state *s)); +int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); +void _tr_align OF((deflate_state *s)); +void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch _length_code[]; + extern uch _dist_code[]; +#else + extern const uch _length_code[]; + extern const uch _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif /* DEFLATE_H */ diff --git a/dep/src/zlib/example.c b/dep/src/zlib/example.c new file mode 100644 index 00000000000..6c8a0ee7633 --- /dev/null +++ b/dep/src/zlib/example.c @@ -0,0 +1,565 @@ +/* example.c -- usage example of the zlib compression library + * Copyright (C) 1995-2004 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include +#include "zlib.h" + +#ifdef STDC +# include +# include +#endif + +#if defined(VMS) || defined(RISCOS) +# define TESTFILE "foo-gz" +#else +# define TESTFILE "foo.gz" +#endif + +#define CHECK_ERR(err, msg) { \ + if (err != Z_OK) { \ + fprintf(stderr, "%s error: %d\n", msg, err); \ + exit(1); \ + } \ +} + +const char hello[] = "hello, hello!"; +/* "hello world" would be more standard, but the repeated "hello" + * stresses the compression code better, sorry... + */ + +const char dictionary[] = "hello"; +uLong dictId; /* Adler32 value of the dictionary */ + +void test_compress OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_gzio OF((const char *fname, + Byte *uncompr, uLong uncomprLen)); +void test_deflate OF((Byte *compr, uLong comprLen)); +void test_inflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_large_deflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_large_inflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_flush OF((Byte *compr, uLong *comprLen)); +void test_sync OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_dict_deflate OF((Byte *compr, uLong comprLen)); +void test_dict_inflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +int main OF((int argc, char *argv[])); + +/* =========================================================================== + * Test compress() and uncompress() + */ +void test_compress(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + uLong len = (uLong)strlen(hello)+1; + + err = compress(compr, &comprLen, (const Bytef*)hello, len); + CHECK_ERR(err, "compress"); + + strcpy((char*)uncompr, "garbage"); + + err = uncompress(uncompr, &uncomprLen, compr, comprLen); + CHECK_ERR(err, "uncompress"); + + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad uncompress\n"); + exit(1); + } else { + printf("uncompress(): %s\n", (char *)uncompr); + } +} + +/* =========================================================================== + * Test read/write of .gz files + */ +void test_gzio(fname, uncompr, uncomprLen) + const char *fname; /* compressed file name */ + Byte *uncompr; + uLong uncomprLen; +{ +#ifdef NO_GZCOMPRESS + fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n"); +#else + int err; + int len = (int)strlen(hello)+1; + gzFile file; + z_off_t pos; + + file = gzopen(fname, "wb"); + if (file == NULL) { + fprintf(stderr, "gzopen error\n"); + exit(1); + } + gzputc(file, 'h'); + if (gzputs(file, "ello") != 4) { + fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err)); + exit(1); + } + if (gzprintf(file, ", %s!", "hello") != 8) { + fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err)); + exit(1); + } + gzseek(file, 1L, SEEK_CUR); /* add one zero byte */ + gzclose(file); + + file = gzopen(fname, "rb"); + if (file == NULL) { + fprintf(stderr, "gzopen error\n"); + exit(1); + } + strcpy((char*)uncompr, "garbage"); + + if (gzread(file, uncompr, (unsigned)uncomprLen) != len) { + fprintf(stderr, "gzread err: %s\n", gzerror(file, &err)); + exit(1); + } + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad gzread: %s\n", (char*)uncompr); + exit(1); + } else { + printf("gzread(): %s\n", (char*)uncompr); + } + + pos = gzseek(file, -8L, SEEK_CUR); + if (pos != 6 || gztell(file) != pos) { + fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n", + (long)pos, (long)gztell(file)); + exit(1); + } + + if (gzgetc(file) != ' ') { + fprintf(stderr, "gzgetc error\n"); + exit(1); + } + + if (gzungetc(' ', file) != ' ') { + fprintf(stderr, "gzungetc error\n"); + exit(1); + } + + gzgets(file, (char*)uncompr, (int)uncomprLen); + if (strlen((char*)uncompr) != 7) { /* " hello!" */ + fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err)); + exit(1); + } + if (strcmp((char*)uncompr, hello + 6)) { + fprintf(stderr, "bad gzgets after gzseek\n"); + exit(1); + } else { + printf("gzgets() after gzseek: %s\n", (char*)uncompr); + } + + gzclose(file); +#endif +} + +/* =========================================================================== + * Test deflate() with small buffers + */ +void test_deflate(compr, comprLen) + Byte *compr; + uLong comprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + uLong len = (uLong)strlen(hello)+1; + + c_stream.zalloc = (alloc_func)0; + c_stream.zfree = (free_func)0; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); + CHECK_ERR(err, "deflateInit"); + + c_stream.next_in = (Bytef*)hello; + c_stream.next_out = compr; + + while (c_stream.total_in != len && c_stream.total_out < comprLen) { + c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */ + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + } + /* Finish the stream, still forcing small buffers: */ + for (;;) { + c_stream.avail_out = 1; + err = deflate(&c_stream, Z_FINISH); + if (err == Z_STREAM_END) break; + CHECK_ERR(err, "deflate"); + } + + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); +} + +/* =========================================================================== + * Test inflate() with small buffers + */ +void test_inflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = (alloc_func)0; + d_stream.zfree = (free_func)0; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = 0; + d_stream.next_out = uncompr; + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) { + d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */ + err = inflate(&d_stream, Z_NO_FLUSH); + if (err == Z_STREAM_END) break; + CHECK_ERR(err, "inflate"); + } + + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad inflate\n"); + exit(1); + } else { + printf("inflate(): %s\n", (char *)uncompr); + } +} + +/* =========================================================================== + * Test deflate() with large buffers and dynamic change of compression level + */ +void test_large_deflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + + c_stream.zalloc = (alloc_func)0; + c_stream.zfree = (free_func)0; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_BEST_SPEED); + CHECK_ERR(err, "deflateInit"); + + c_stream.next_out = compr; + c_stream.avail_out = (uInt)comprLen; + + /* At this point, uncompr is still mostly zeroes, so it should compress + * very well: + */ + c_stream.next_in = uncompr; + c_stream.avail_in = (uInt)uncomprLen; + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + if (c_stream.avail_in != 0) { + fprintf(stderr, "deflate not greedy\n"); + exit(1); + } + + /* Feed in already compressed data and switch to no compression: */ + deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY); + c_stream.next_in = compr; + c_stream.avail_in = (uInt)comprLen/2; + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + + /* Switch back to compressing mode: */ + deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED); + c_stream.next_in = uncompr; + c_stream.avail_in = (uInt)uncomprLen; + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + + err = deflate(&c_stream, Z_FINISH); + if (err != Z_STREAM_END) { + fprintf(stderr, "deflate should report Z_STREAM_END\n"); + exit(1); + } + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); +} + +/* =========================================================================== + * Test inflate() with large buffers + */ +void test_large_inflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = (alloc_func)0; + d_stream.zfree = (free_func)0; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = (uInt)comprLen; + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + for (;;) { + d_stream.next_out = uncompr; /* discard the output */ + d_stream.avail_out = (uInt)uncomprLen; + err = inflate(&d_stream, Z_NO_FLUSH); + if (err == Z_STREAM_END) break; + CHECK_ERR(err, "large inflate"); + } + + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + if (d_stream.total_out != 2*uncomprLen + comprLen/2) { + fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out); + exit(1); + } else { + printf("large_inflate(): OK\n"); + } +} + +/* =========================================================================== + * Test deflate() with full flush + */ +void test_flush(compr, comprLen) + Byte *compr; + uLong *comprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + uInt len = (uInt)strlen(hello)+1; + + c_stream.zalloc = (alloc_func)0; + c_stream.zfree = (free_func)0; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); + CHECK_ERR(err, "deflateInit"); + + c_stream.next_in = (Bytef*)hello; + c_stream.next_out = compr; + c_stream.avail_in = 3; + c_stream.avail_out = (uInt)*comprLen; + err = deflate(&c_stream, Z_FULL_FLUSH); + CHECK_ERR(err, "deflate"); + + compr[3]++; /* force an error in first compressed block */ + c_stream.avail_in = len - 3; + + err = deflate(&c_stream, Z_FINISH); + if (err != Z_STREAM_END) { + CHECK_ERR(err, "deflate"); + } + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); + + *comprLen = c_stream.total_out; +} + +/* =========================================================================== + * Test inflateSync() + */ +void test_sync(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = (alloc_func)0; + d_stream.zfree = (free_func)0; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = 2; /* just read the zlib header */ + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + d_stream.next_out = uncompr; + d_stream.avail_out = (uInt)uncomprLen; + + inflate(&d_stream, Z_NO_FLUSH); + CHECK_ERR(err, "inflate"); + + d_stream.avail_in = (uInt)comprLen-2; /* read all compressed data */ + err = inflateSync(&d_stream); /* but skip the damaged part */ + CHECK_ERR(err, "inflateSync"); + + err = inflate(&d_stream, Z_FINISH); + if (err != Z_DATA_ERROR) { + fprintf(stderr, "inflate should report DATA_ERROR\n"); + /* Because of incorrect adler32 */ + exit(1); + } + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + printf("after inflateSync(): hel%s\n", (char *)uncompr); +} + +/* =========================================================================== + * Test deflate() with preset dictionary + */ +void test_dict_deflate(compr, comprLen) + Byte *compr; + uLong comprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + + c_stream.zalloc = (alloc_func)0; + c_stream.zfree = (free_func)0; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_BEST_COMPRESSION); + CHECK_ERR(err, "deflateInit"); + + err = deflateSetDictionary(&c_stream, + (const Bytef*)dictionary, sizeof(dictionary)); + CHECK_ERR(err, "deflateSetDictionary"); + + dictId = c_stream.adler; + c_stream.next_out = compr; + c_stream.avail_out = (uInt)comprLen; + + c_stream.next_in = (Bytef*)hello; + c_stream.avail_in = (uInt)strlen(hello)+1; + + err = deflate(&c_stream, Z_FINISH); + if (err != Z_STREAM_END) { + fprintf(stderr, "deflate should report Z_STREAM_END\n"); + exit(1); + } + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); +} + +/* =========================================================================== + * Test inflate() with a preset dictionary + */ +void test_dict_inflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = (alloc_func)0; + d_stream.zfree = (free_func)0; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = (uInt)comprLen; + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + d_stream.next_out = uncompr; + d_stream.avail_out = (uInt)uncomprLen; + + for (;;) { + err = inflate(&d_stream, Z_NO_FLUSH); + if (err == Z_STREAM_END) break; + if (err == Z_NEED_DICT) { + if (d_stream.adler != dictId) { + fprintf(stderr, "unexpected dictionary"); + exit(1); + } + err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary, + sizeof(dictionary)); + } + CHECK_ERR(err, "inflate with dict"); + } + + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad inflate with dict\n"); + exit(1); + } else { + printf("inflate with dictionary: %s\n", (char *)uncompr); + } +} + +/* =========================================================================== + * Usage: example [output.gz [input.gz]] + */ + +int main(argc, argv) + int argc; + char *argv[]; +{ + Byte *compr, *uncompr; + uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */ + uLong uncomprLen = comprLen; + static const char* myVersion = ZLIB_VERSION; + + if (zlibVersion()[0] != myVersion[0]) { + fprintf(stderr, "incompatible zlib version\n"); + exit(1); + + } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) { + fprintf(stderr, "warning: different zlib version\n"); + } + + printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n", + ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags()); + + compr = (Byte*)calloc((uInt)comprLen, 1); + uncompr = (Byte*)calloc((uInt)uncomprLen, 1); + /* compr and uncompr are cleared to avoid reading uninitialized + * data and to ensure that uncompr compresses well. + */ + if (compr == Z_NULL || uncompr == Z_NULL) { + printf("out of memory\n"); + exit(1); + } + test_compress(compr, comprLen, uncompr, uncomprLen); + + test_gzio((argc > 1 ? argv[1] : TESTFILE), + uncompr, uncomprLen); + + test_deflate(compr, comprLen); + test_inflate(compr, comprLen, uncompr, uncomprLen); + + test_large_deflate(compr, comprLen, uncompr, uncomprLen); + test_large_inflate(compr, comprLen, uncompr, uncomprLen); + + test_flush(compr, &comprLen); + test_sync(compr, comprLen, uncompr, uncomprLen); + comprLen = uncomprLen; + + test_dict_deflate(compr, comprLen); + test_dict_inflate(compr, comprLen, uncompr, uncomprLen); + + free(compr); + free(uncompr); + + return 0; +} diff --git a/dep/src/zlib/gzio.c b/dep/src/zlib/gzio.c new file mode 100644 index 00000000000..7e90f4928fc --- /dev/null +++ b/dep/src/zlib/gzio.c @@ -0,0 +1,1026 @@ +/* gzio.c -- IO on .gz files + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Compile this file with -DNO_GZCOMPRESS to avoid the compression code. + */ + +/* @(#) $Id$ */ + +#include + +#include "zutil.h" + +#ifdef NO_DEFLATE /* for compatibility with old definition */ +# define NO_GZCOMPRESS +#endif + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +#ifndef Z_BUFSIZE +# ifdef MAXSEG_64K +# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */ +# else +# define Z_BUFSIZE 16384 +# endif +#endif +#ifndef Z_PRINTF_BUFSIZE +# define Z_PRINTF_BUFSIZE 4096 +#endif + +#ifdef __MVS__ +# pragma map (fdopen , "\174\174FDOPEN") + FILE *fdopen(int, const char *); +#endif + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern void free OF((voidpf ptr)); +#endif + +#define ALLOC(size) malloc(size) +#define TRYFREE(p) {if (p) free(p);} + +static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define RESERVED 0xE0 /* bits 5..7: reserved */ + +typedef struct gz_stream { + z_stream stream; + int z_err; /* error code for last stream operation */ + int z_eof; /* set if end of input file */ + FILE *file; /* .gz file */ + Byte *inbuf; /* input buffer */ + Byte *outbuf; /* output buffer */ + uLong crc; /* crc32 of uncompressed data */ + char *msg; /* error message */ + char *path; /* path name for debugging only */ + int transparent; /* 1 if input file is not a .gz file */ + char mode; /* 'w' or 'r' */ + z_off_t start; /* start of compressed data in file (header skipped) */ + z_off_t in; /* bytes into deflate or inflate */ + z_off_t out; /* bytes out of deflate or inflate */ + int back; /* one character push-back */ + int last; /* true if push-back is last character */ +} gz_stream; + + +local gzFile gz_open OF((const char *path, const char *mode, int fd)); +local int do_flush OF((gzFile file, int flush)); +local int get_byte OF((gz_stream *s)); +local void check_header OF((gz_stream *s)); +local int destroy OF((gz_stream *s)); +local void putLong OF((FILE *file, uLong x)); +local uLong getLong OF((gz_stream *s)); + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb"). The file is given either by file descriptor + or path name (if fd == -1). + gz_open returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). +*/ +local gzFile gz_open (path, mode, fd) + const char *path; + const char *mode; + int fd; +{ + int err; + int level = Z_DEFAULT_COMPRESSION; /* compression level */ + int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */ + char *p = (char*)mode; + gz_stream *s; + char fmode[80]; /* copy of mode, without the compression level */ + char *m = fmode; + + if (!path || !mode) return Z_NULL; + + s = (gz_stream *)ALLOC(sizeof(gz_stream)); + if (!s) return Z_NULL; + + s->stream.zalloc = (alloc_func)0; + s->stream.zfree = (free_func)0; + s->stream.opaque = (voidpf)0; + s->stream.next_in = s->inbuf = Z_NULL; + s->stream.next_out = s->outbuf = Z_NULL; + s->stream.avail_in = s->stream.avail_out = 0; + s->file = NULL; + s->z_err = Z_OK; + s->z_eof = 0; + s->in = 0; + s->out = 0; + s->back = EOF; + s->crc = crc32(0L, Z_NULL, 0); + s->msg = NULL; + s->transparent = 0; + + s->path = (char*)ALLOC(strlen(path)+1); + if (s->path == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + strcpy(s->path, path); /* do this early for debugging */ + + s->mode = '\0'; + do { + if (*p == 'r') s->mode = 'r'; + if (*p == 'w' || *p == 'a') s->mode = 'w'; + if (*p >= '0' && *p <= '9') { + level = *p - '0'; + } else if (*p == 'f') { + strategy = Z_FILTERED; + } else if (*p == 'h') { + strategy = Z_HUFFMAN_ONLY; + } else if (*p == 'R') { + strategy = Z_RLE; + } else { + *m++ = *p; /* copy the mode */ + } + } while (*p++ && m != fmode + sizeof(fmode)); + if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + err = Z_STREAM_ERROR; +#else + err = deflateInit2(&(s->stream), level, + Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy); + /* windowBits is passed < 0 to suppress zlib header */ + + s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); +#endif + if (err != Z_OK || s->outbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } else { + s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); + + err = inflateInit2(&(s->stream), -MAX_WBITS); + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are + * present after the compressed stream. + */ + if (err != Z_OK || s->inbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } + s->stream.avail_out = Z_BUFSIZE; + + errno = 0; + s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode); + + if (s->file == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + if (s->mode == 'w') { + /* Write a very simple .gz header: + */ + fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], + Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); + s->start = 10L; + /* We use 10L instead of ftell(s->file) to because ftell causes an + * fflush on some systems. This version of the library doesn't use + * start anyway in write mode, so this initialization is not + * necessary. + */ + } else { + check_header(s); /* skip the .gz header */ + s->start = ftell(s->file) - s->stream.avail_in; + } + + return (gzFile)s; +} + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. +*/ +gzFile ZEXPORT gzopen (path, mode) + const char *path; + const char *mode; +{ + return gz_open (path, mode, -1); +} + +/* =========================================================================== + Associate a gzFile with the file descriptor fd. fd is not dup'ed here + to mimic the behavio(u)r of fdopen. +*/ +gzFile ZEXPORT gzdopen (fd, mode) + int fd; + const char *mode; +{ + char name[46]; /* allow for up to 128-bit integers */ + + if (fd < 0) return (gzFile)Z_NULL; + sprintf(name, "", fd); /* for debugging */ + + return gz_open (name, mode, fd); +} + +/* =========================================================================== + * Update the compression level and strategy + */ +int ZEXPORT gzsetparams (file, level, strategy) + gzFile file; + int level; + int strategy; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + /* Make room to allow flushing */ + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + } + s->stream.avail_out = Z_BUFSIZE; + } + + return deflateParams (&(s->stream), level, strategy); +} + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been sucessfully opened for reading. +*/ +local int get_byte(s) + gz_stream *s; +{ + if (s->z_eof) return EOF; + if (s->stream.avail_in == 0) { + errno = 0; + s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) s->z_err = Z_ERRNO; + return EOF; + } + s->stream.next_in = s->inbuf; + } + s->stream.avail_in--; + return *(s->stream.next_in)++; +} + +/* =========================================================================== + Check the gzip header of a gz_stream opened for reading. Set the stream + mode to transparent if the gzip magic header is not present; set s->err + to Z_DATA_ERROR if the magic header is present but the rest of the header + is incorrect. + IN assertion: the stream s has already been created sucessfully; + s->stream.avail_in is zero for the first time, but may be non-zero + for concatenated .gz files. +*/ +local void check_header(s) + gz_stream *s; +{ + int method; /* method byte */ + int flags; /* flags byte */ + uInt len; + int c; + + /* Assure two bytes in the buffer so we can peek ahead -- handle case + where first byte of header is at the end of the buffer after the last + gzip segment */ + len = s->stream.avail_in; + if (len < 2) { + if (len) s->inbuf[0] = s->stream.next_in[0]; + errno = 0; + len = (uInt)fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file); + if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO; + s->stream.avail_in += len; + s->stream.next_in = s->inbuf; + if (s->stream.avail_in < 2) { + s->transparent = s->stream.avail_in; + return; + } + } + + /* Peek ahead to check the gzip magic header */ + if (s->stream.next_in[0] != gz_magic[0] || + s->stream.next_in[1] != gz_magic[1]) { + s->transparent = 1; + return; + } + s->stream.avail_in -= 2; + s->stream.next_in += 2; + + /* Check the rest of the gzip header */ + method = get_byte(s); + flags = get_byte(s); + if (method != Z_DEFLATED || (flags & RESERVED) != 0) { + s->z_err = Z_DATA_ERROR; + return; + } + + /* Discard time, xflags and OS code: */ + for (len = 0; len < 6; len++) (void)get_byte(s); + + if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ + len = (uInt)get_byte(s); + len += ((uInt)get_byte(s))<<8; + /* len is garbage if EOF but the loop below will quit anyway */ + while (len-- != 0 && get_byte(s) != EOF) ; + } + if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ + for (len = 0; len < 2; len++) (void)get_byte(s); + } + s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK; +} + + /* =========================================================================== + * Cleanup then free the given gz_stream. Return a zlib error code. + Try freeing in the reverse order of allocations. + */ +local int destroy (s) + gz_stream *s; +{ + int err = Z_OK; + + if (!s) return Z_STREAM_ERROR; + + TRYFREE(s->msg); + + if (s->stream.state != NULL) { + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + err = Z_STREAM_ERROR; +#else + err = deflateEnd(&(s->stream)); +#endif + } else if (s->mode == 'r') { + err = inflateEnd(&(s->stream)); + } + } + if (s->file != NULL && fclose(s->file)) { +#ifdef ESPIPE + if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */ +#endif + err = Z_ERRNO; + } + if (s->z_err < 0) err = s->z_err; + + TRYFREE(s->inbuf); + TRYFREE(s->outbuf); + TRYFREE(s->path); + TRYFREE(s); + return err; +} + +/* =========================================================================== + Reads the given number of uncompressed bytes from the compressed file. + gzread returns the number of bytes actually read (0 for end of file). +*/ +int ZEXPORT gzread (file, buf, len) + gzFile file; + voidp buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + Bytef *start = (Bytef*)buf; /* starting point for crc computation */ + Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */ + + if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; + + if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; + if (s->z_err == Z_STREAM_END) return 0; /* EOF */ + + next_out = (Byte*)buf; + s->stream.next_out = (Bytef*)buf; + s->stream.avail_out = len; + + if (s->stream.avail_out && s->back != EOF) { + *next_out++ = s->back; + s->stream.next_out++; + s->stream.avail_out--; + s->back = EOF; + s->out++; + start++; + if (s->last) { + s->z_err = Z_STREAM_END; + return 1; + } + } + + while (s->stream.avail_out != 0) { + + if (s->transparent) { + /* Copy first the lookahead bytes: */ + uInt n = s->stream.avail_in; + if (n > s->stream.avail_out) n = s->stream.avail_out; + if (n > 0) { + zmemcpy(s->stream.next_out, s->stream.next_in, n); + next_out += n; + s->stream.next_out = next_out; + s->stream.next_in += n; + s->stream.avail_out -= n; + s->stream.avail_in -= n; + } + if (s->stream.avail_out > 0) { + s->stream.avail_out -= + (uInt)fread(next_out, 1, s->stream.avail_out, s->file); + } + len -= s->stream.avail_out; + s->in += len; + s->out += len; + if (len == 0) s->z_eof = 1; + return (int)len; + } + if (s->stream.avail_in == 0 && !s->z_eof) { + + errno = 0; + s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) { + s->z_err = Z_ERRNO; + break; + } + } + s->stream.next_in = s->inbuf; + } + s->in += s->stream.avail_in; + s->out += s->stream.avail_out; + s->z_err = inflate(&(s->stream), Z_NO_FLUSH); + s->in -= s->stream.avail_in; + s->out -= s->stream.avail_out; + + if (s->z_err == Z_STREAM_END) { + /* Check CRC and original size */ + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + start = s->stream.next_out; + + if (getLong(s) != s->crc) { + s->z_err = Z_DATA_ERROR; + } else { + (void)getLong(s); + /* The uncompressed length returned by above getlong() may be + * different from s->out in case of concatenated .gz files. + * Check for such files: + */ + check_header(s); + if (s->z_err == Z_OK) { + inflateReset(&(s->stream)); + s->crc = crc32(0L, Z_NULL, 0); + } + } + } + if (s->z_err != Z_OK || s->z_eof) break; + } + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + + if (len == s->stream.avail_out && + (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO)) + return -1; + return (int)(len - s->stream.avail_out); +} + + +/* =========================================================================== + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ +int ZEXPORT gzgetc(file) + gzFile file; +{ + unsigned char c; + + return gzread(file, &c, 1) == 1 ? c : -1; +} + + +/* =========================================================================== + Push one byte back onto the stream. +*/ +int ZEXPORT gzungetc(c, file) + int c; + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF; + s->back = c; + s->out--; + s->last = (s->z_err == Z_STREAM_END); + if (s->last) s->z_err = Z_OK; + s->z_eof = 0; + return c; +} + + +/* =========================================================================== + Reads bytes from the compressed file until len-1 characters are + read, or a newline character is read and transferred to buf, or an + end-of-file condition is encountered. The string is then terminated + with a null character. + gzgets returns buf, or Z_NULL in case of error. + + The current implementation is not optimized at all. +*/ +char * ZEXPORT gzgets(file, buf, len) + gzFile file; + char *buf; + int len; +{ + char *b = buf; + if (buf == Z_NULL || len <= 0) return Z_NULL; + + while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ; + *buf = '\0'; + return b == buf && len > 0 ? Z_NULL : b; +} + + +#ifndef NO_GZCOMPRESS +/* =========================================================================== + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of bytes actually written (0 in case of error). +*/ +int ZEXPORT gzwrite (file, buf, len) + gzFile file; + voidpc buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.next_in = (Bytef*)buf; + s->stream.avail_in = len; + + while (s->stream.avail_in != 0) { + + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + break; + } + s->stream.avail_out = Z_BUFSIZE; + } + s->in += s->stream.avail_in; + s->out += s->stream.avail_out; + s->z_err = deflate(&(s->stream), Z_NO_FLUSH); + s->in -= s->stream.avail_in; + s->out -= s->stream.avail_out; + if (s->z_err != Z_OK) break; + } + s->crc = crc32(s->crc, (const Bytef *)buf, len); + + return (int)(len - s->stream.avail_in); +} + + +/* =========================================================================== + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). +*/ +#ifdef STDC +#include + +int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...) +{ + char buf[Z_PRINTF_BUFSIZE]; + va_list va; + int len; + + buf[sizeof(buf) - 1] = 0; + va_start(va, format); +#ifdef NO_vsnprintf +# ifdef HAS_vsprintf_void + (void)vsprintf(buf, format, va); + va_end(va); + for (len = 0; len < sizeof(buf); len++) + if (buf[len] == 0) break; +# else + len = vsprintf(buf, format, va); + va_end(va); +# endif +#else +# ifdef HAS_vsnprintf_void + (void)vsnprintf(buf, sizeof(buf), format, va); + va_end(va); + len = strlen(buf); +# else + len = vsnprintf(buf, sizeof(buf), format, va); + va_end(va); +# endif +#endif + if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0) + return 0; + return gzwrite(file, buf, (unsigned)len); +} +#else /* not ANSI C */ + +int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + gzFile file; + const char *format; + int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; +{ + char buf[Z_PRINTF_BUFSIZE]; + int len; + + buf[sizeof(buf) - 1] = 0; +#ifdef NO_snprintf +# ifdef HAS_sprintf_void + sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + for (len = 0; len < sizeof(buf); len++) + if (buf[len] == 0) break; +# else + len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#else +# ifdef HAS_snprintf_void + snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = strlen(buf); +# else + len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#endif + if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0) + return 0; + return gzwrite(file, buf, len); +} +#endif + +/* =========================================================================== + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ +int ZEXPORT gzputc(file, c) + gzFile file; + int c; +{ + unsigned char cc = (unsigned char) c; /* required for big endian systems */ + + return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1; +} + + +/* =========================================================================== + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ +int ZEXPORT gzputs(file, s) + gzFile file; + const char *s; +{ + return gzwrite(file, (char*)s, (unsigned)strlen(s)); +} + + +/* =========================================================================== + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. +*/ +local int do_flush (file, flush) + gzFile file; + int flush; +{ + uInt len; + int done = 0; + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.avail_in = 0; /* should be zero already anyway */ + + for (;;) { + len = Z_BUFSIZE - s->stream.avail_out; + + if (len != 0) { + if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) { + s->z_err = Z_ERRNO; + return Z_ERRNO; + } + s->stream.next_out = s->outbuf; + s->stream.avail_out = Z_BUFSIZE; + } + if (done) break; + s->out += s->stream.avail_out; + s->z_err = deflate(&(s->stream), flush); + s->out -= s->stream.avail_out; + + /* Ignore the second of two consecutive flushes: */ + if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK; + + /* deflate has finished flushing only when it hasn't used up + * all the available space in the output buffer: + */ + done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END); + + if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; + } + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} + +int ZEXPORT gzflush (file, flush) + gzFile file; + int flush; +{ + gz_stream *s = (gz_stream*)file; + int err = do_flush (file, flush); + + if (err) return err; + fflush(s->file); + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} +#endif /* NO_GZCOMPRESS */ + +/* =========================================================================== + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error. + SEEK_END is not implemented, returns error. + In this version of the library, gzseek can be extremely slow. +*/ +z_off_t ZEXPORT gzseek (file, offset, whence) + gzFile file; + z_off_t offset; + int whence; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || whence == SEEK_END || + s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) { + return -1L; + } + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + return -1L; +#else + if (whence == SEEK_SET) { + offset -= s->in; + } + if (offset < 0) return -1L; + + /* At this point, offset is the number of zero bytes to write. */ + if (s->inbuf == Z_NULL) { + s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */ + if (s->inbuf == Z_NULL) return -1L; + zmemzero(s->inbuf, Z_BUFSIZE); + } + while (offset > 0) { + uInt size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (uInt)offset; + + size = gzwrite(file, s->inbuf, size); + if (size == 0) return -1L; + + offset -= size; + } + return s->in; +#endif + } + /* Rest of function is for reading only */ + + /* compute absolute position */ + if (whence == SEEK_CUR) { + offset += s->out; + } + if (offset < 0) return -1L; + + if (s->transparent) { + /* map to fseek */ + s->back = EOF; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + if (fseek(s->file, offset, SEEK_SET) < 0) return -1L; + + s->in = s->out = offset; + return offset; + } + + /* For a negative seek, rewind and use positive seek */ + if (offset >= s->out) { + offset -= s->out; + } else if (gzrewind(file) < 0) { + return -1L; + } + /* offset is now the number of bytes to skip. */ + + if (offset != 0 && s->outbuf == Z_NULL) { + s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); + if (s->outbuf == Z_NULL) return -1L; + } + if (offset && s->back != EOF) { + s->back = EOF; + s->out++; + offset--; + if (s->last) s->z_err = Z_STREAM_END; + } + while (offset > 0) { + int size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (int)offset; + + size = gzread(file, s->outbuf, (uInt)size); + if (size <= 0) return -1L; + offset -= size; + } + return s->out; +} + +/* =========================================================================== + Rewinds input file. +*/ +int ZEXPORT gzrewind (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r') return -1; + + s->z_err = Z_OK; + s->z_eof = 0; + s->back = EOF; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + s->crc = crc32(0L, Z_NULL, 0); + if (!s->transparent) (void)inflateReset(&s->stream); + s->in = 0; + s->out = 0; + return fseek(s->file, s->start, SEEK_SET); +} + +/* =========================================================================== + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. +*/ +z_off_t ZEXPORT gztell (file) + gzFile file; +{ + return gzseek(file, 0L, SEEK_CUR); +} + +/* =========================================================================== + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ +int ZEXPORT gzeof (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + /* With concatenated compressed files that can have embedded + * crc trailers, z_eof is no longer the only/best indicator of EOF + * on a gz_stream. Handle end-of-stream error explicitly here. + */ + if (s == NULL || s->mode != 'r') return 0; + if (s->z_eof) return 1; + return s->z_err == Z_STREAM_END; +} + +/* =========================================================================== + Returns 1 if reading and doing so transparently, otherwise zero. +*/ +int ZEXPORT gzdirect (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r') return 0; + return s->transparent; +} + +/* =========================================================================== + Outputs a long in LSB order to the given file +*/ +local void putLong (file, x) + FILE *file; + uLong x; +{ + int n; + for (n = 0; n < 4; n++) { + fputc((int)(x & 0xff), file); + x >>= 8; + } +} + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets z_err in case + of error. +*/ +local uLong getLong (s) + gz_stream *s; +{ + uLong x = (uLong)get_byte(s); + int c; + + x += ((uLong)get_byte(s))<<8; + x += ((uLong)get_byte(s))<<16; + c = get_byte(s); + if (c == EOF) s->z_err = Z_DATA_ERROR; + x += ((uLong)c)<<24; + return x; +} + +/* =========================================================================== + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. +*/ +int ZEXPORT gzclose (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return Z_STREAM_ERROR; + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + return Z_STREAM_ERROR; +#else + if (do_flush (file, Z_FINISH) != Z_OK) + return destroy((gz_stream*)file); + + putLong (s->file, s->crc); + putLong (s->file, (uLong)(s->in & 0xffffffff)); +#endif + } + return destroy((gz_stream*)file); +} + +#ifdef STDC +# define zstrerror(errnum) strerror(errnum) +#else +# define zstrerror(errnum) "" +#endif + +/* =========================================================================== + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ +const char * ZEXPORT gzerror (file, errnum) + gzFile file; + int *errnum; +{ + char *m; + gz_stream *s = (gz_stream*)file; + + if (s == NULL) { + *errnum = Z_STREAM_ERROR; + return (const char*)ERR_MSG(Z_STREAM_ERROR); + } + *errnum = s->z_err; + if (*errnum == Z_OK) return (const char*)""; + + m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg); + + if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err); + + TRYFREE(s->msg); + s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3); + if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR); + strcpy(s->msg, s->path); + strcat(s->msg, ": "); + strcat(s->msg, m); + return (const char*)s->msg; +} + +/* =========================================================================== + Clear the error and end-of-file flags, and do the same for the real file. +*/ +void ZEXPORT gzclearerr (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return; + if (s->z_err != Z_STREAM_END) s->z_err = Z_OK; + s->z_eof = 0; + clearerr(s->file); +} diff --git a/dep/src/zlib/infback.c b/dep/src/zlib/infback.c new file mode 100644 index 00000000000..455dbc9ee84 --- /dev/null +++ b/dep/src/zlib/infback.c @@ -0,0 +1,623 @@ +/* infback.c -- inflate using a call-back interface + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + This code is largely copied from inflate.c. Normally either infback.o or + inflate.o would be linked into an application--not both. The interface + with inffast.c is retained so that optimized assembler-coded versions of + inflate_fast() can be used with either inflate.c or infback.c. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); + +/* + strm provides memory allocation functions in zalloc and zfree, or + Z_NULL to use the library memory allocation functions. + + windowBits is in the range 8..15, and window is a user-supplied + window and output buffer that is 2**windowBits bytes. + */ +int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) +z_streamp strm; +int windowBits; +unsigned char FAR *window; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL || window == Z_NULL || + windowBits < 8 || windowBits > 15) + return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *)ZALLOC(strm, 1, + sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->dmax = 32768U; + state->wbits = windowBits; + state->wsize = 1U << windowBits; + state->window = window; + state->write = 0; + state->whave = 0; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +/* Macros for inflateBack(): */ + +/* Load returned state from inflate_fast() */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Set state from registers for inflate_fast() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Assure that some input is available. If input is requested, but denied, + then return a Z_BUF_ERROR from inflateBack(). */ +#define PULL() \ + do { \ + if (have == 0) { \ + have = in(in_desc, &next); \ + if (have == 0) { \ + next = Z_NULL; \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflateBack() + with an error if there is no input available. */ +#define PULLBYTE() \ + do { \ + PULL(); \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflateBack() with + an error. */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Assure that some output space is available, by writing out the window + if it's full. If the write fails, return from inflateBack() with a + Z_BUF_ERROR. */ +#define ROOM() \ + do { \ + if (left == 0) { \ + put = state->window; \ + left = state->wsize; \ + state->whave = left; \ + if (out(out_desc, put, left)) { \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* + strm provides the memory allocation functions and window buffer on input, + and provides information on the unused input on return. For Z_DATA_ERROR + returns, strm will also provide an error message. + + in() and out() are the call-back input and output functions. When + inflateBack() needs more input, it calls in(). When inflateBack() has + filled the window with output, or when it completes with data in the + window, it calls out() to write out the data. The application must not + change the provided input until in() is called again or inflateBack() + returns. The application must not change the window/output buffer until + inflateBack() returns. + + in() and out() are called with a descriptor parameter provided in the + inflateBack() call. This parameter can be a structure that provides the + information required to do the read or write, as well as accumulated + information on the input and output such as totals and check values. + + in() should return zero on failure. out() should return non-zero on + failure. If either in() or out() fails, than inflateBack() returns a + Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it + was in() or out() that caused in the error. Otherwise, inflateBack() + returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format + error, or Z_MEM_ERROR if it could not allocate memory for the state. + inflateBack() can also return Z_STREAM_ERROR if the input parameters + are not correct, i.e. strm is Z_NULL or the state was not initialized. + */ +int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc) +z_streamp strm; +in_func in; +void FAR *in_desc; +out_func out; +void FAR *out_desc; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + /* Check that the strm exists and that the state was initialized */ + if (strm == Z_NULL || strm->state == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* Reset the state */ + strm->msg = Z_NULL; + state->mode = TYPE; + state->last = 0; + state->whave = 0; + next = strm->next_in; + have = next != Z_NULL ? strm->avail_in : 0; + hold = 0; + bits = 0; + put = state->window; + left = state->wsize; + + /* Inflate until end of block marked as last */ + for (;;) + switch (state->mode) { + case TYPE: + /* determine and dispatch block type */ + if (state->last) { + BYTEBITS(); + state->mode = DONE; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + + case STORED: + /* get and verify stored block length */ + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + + /* copy stored block from input to output */ + while (state->length != 0) { + copy = state->length; + PULL(); + ROOM(); + if (copy > have) copy = have; + if (copy > left) copy = left; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + + case TABLE: + /* get dynamic table entries descriptor */ + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + + /* get code length code lengths (not a typo) */ + state->have = 0; + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + + /* get length and distance code code lengths */ + state->have = 0; + while (state->have < state->nlen + state->ndist) { + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.val < 16) { + NEEDBITS(this.bits); + DROPBITS(this.bits); + state->lens[state->have++] = this.val; + } + else { + if (this.val == 16) { + NEEDBITS(this.bits + 2); + DROPBITS(this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = (unsigned)(state->lens[state->have - 1]); + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (this.val == 17) { + NEEDBITS(this.bits + 3); + DROPBITS(this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(this.bits + 7); + DROPBITS(this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + + case LEN: + /* use inflate_fast() if we have enough input and output */ + if (have >= 6 && left >= 258) { + RESTORE(); + if (state->whave < state->wsize) + state->whave = state->wsize - left; + inflate_fast(strm, state->wsize); + LOAD(); + break; + } + + /* get a literal, length, or end-of-block code */ + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.op && (this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + state->length = (unsigned)this.val; + + /* process literal */ + if (this.op == 0) { + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + ROOM(); + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + } + + /* process end of block */ + if (this.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + + /* invalid code */ + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + + /* length code -- get extra bits, if any */ + state->extra = (unsigned)(this.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + + /* get distance code */ + for (;;) { + this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if ((this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + if (this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)this.val; + + /* get distance extra bits, if any */ + state->extra = (unsigned)(this.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } + if (state->offset > state->wsize - (state->whave < state->wsize ? + left : 0)) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + + /* copy match from window to output */ + do { + ROOM(); + copy = state->wsize - state->offset; + if (copy < left) { + from = put + copy; + copy = left - copy; + } + else { + from = put - state->offset; + copy = left; + } + if (copy > state->length) copy = state->length; + state->length -= copy; + left -= copy; + do { + *put++ = *from++; + } while (--copy); + } while (state->length != 0); + break; + + case DONE: + /* inflate stream terminated properly -- write leftover output */ + ret = Z_STREAM_END; + if (left < state->wsize) { + if (out(out_desc, state->window, state->wsize - left)) + ret = Z_BUF_ERROR; + } + goto inf_leave; + + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + + default: /* can't happen, but makes compilers happy */ + ret = Z_STREAM_ERROR; + goto inf_leave; + } + + /* Return unused input */ + inf_leave: + strm->next_in = next; + strm->avail_in = have; + return ret; +} + +int ZEXPORT inflateBackEnd(strm) +z_streamp strm; +{ + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} diff --git a/dep/src/zlib/inffast.c b/dep/src/zlib/inffast.c new file mode 100644 index 00000000000..bbee92ed1e6 --- /dev/null +++ b/dep/src/zlib/inffast.c @@ -0,0 +1,318 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifndef ASMINF + +/* Allow machine dependent optimization for post-increment or pre-increment. + Based on testing to date, + Pre-increment preferred for: + - PowerPC G3 (Adler) + - MIPS R5000 (Randers-Pehrson) + Post-increment preferred for: + - none + No measurable difference: + - Pentium III (Anderson) + - M68060 (Nikl) + */ +#ifdef POSTINC +# define OFF 0 +# define PUP(a) *(a)++ +#else +# define OFF 1 +# define PUP(a) *++(a) +#endif + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + unsigned char FAR *in; /* local strm->next_in */ + unsigned char FAR *last; /* while in < last, enough input available */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ +#ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ +#endif + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code this; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in - OFF; + last = in + (strm->avail_in - 5); + out = strm->next_out - OFF; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); +#ifdef INFLATE_STRICT + dmax = state->dmax; +#endif + wsize = state->wsize; + whave = state->whave; + write = state->write; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = lcode[hold & lmask]; + dolen: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op == 0) { /* literal */ + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + PUP(out) = (unsigned char)(this.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = dcode[hold & dmask]; + dodist: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); +#ifdef INFLATE_STRICT + if (dist > dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + from = window - OFF; + if (write == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (write < op) { /* wrap around window */ + from += wsize + write - op; + op -= write; + if (op < len) { /* some from end of window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = window - OFF; + if (write < len) { /* some from start of window */ + op = write; + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += write - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } while (len > 2); + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + this = dcode[this.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + this = lcode[this.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in + OFF; + strm->next_out = out + OFF; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and write == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/dep/src/zlib/inffast.h b/dep/src/zlib/inffast.h new file mode 100644 index 00000000000..1e88d2d97b5 --- /dev/null +++ b/dep/src/zlib/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/dep/src/zlib/inffixed.h b/dep/src/zlib/inffixed.h new file mode 100644 index 00000000000..75ed4b5978d --- /dev/null +++ b/dep/src/zlib/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. It + is part of the implementation of the compression library and + is subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/dep/src/zlib/inflate.c b/dep/src/zlib/inflate.c new file mode 100644 index 00000000000..792fdee8e9c --- /dev/null +++ b/dep/src/zlib/inflate.c @@ -0,0 +1,1368 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common write == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, unsigned out)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, + unsigned len)); + +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + strm->adler = 1; /* to support ill-conceived Java test suite */ + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->dmax = 32768U; + state->head = Z_NULL; + state->wsize = 0; + state->whave = 0; + state->write = 0; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflatePrime(strm, bits, value) +z_streamp strm; +int bits; +int value; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; + value &= (1L << bits) - 1; + state->hold += value << state->bits; + state->bits += bits; + return Z_OK; +} + +int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) +z_streamp strm; +int windowBits; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + if (windowBits < 0) { + state->wrap = 0; + windowBits = -windowBits; + } + else { + state->wrap = (windowBits >> 4) + 1; +#ifdef GUNZIP + if (windowBits < 48) windowBits &= 15; +#endif + } + if (windowBits < 8 || windowBits > 15) { + ZFREE(strm, state); + strm->state = Z_NULL; + return Z_STREAM_ERROR; + } + state->wbits = (unsigned)windowBits; + state->window = Z_NULL; + return inflateReset(strm); +} + +int ZEXPORT inflateInit_(strm, version, stream_size) +z_streamp strm; +const char *version; +int stream_size; +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, + state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(strm, out) +z_streamp strm; +unsigned out; +{ + struct inflate_state FAR *state; + unsigned copy, dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->write = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + copy = out - strm->avail_out; + if (copy >= state->wsize) { + zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); + state->write = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->write; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->write, strm->next_out - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, strm->next_out - copy, copy); + state->write = copy; + state->whave = state->wsize; + } + else { + state->write += dist; + if (state->write == state->wsize) state->write = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Reverse the bytes in a 32-bit value */ +#define REVERSE(q) \ + ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(strm, flush) +z_streamp strm; +int flush; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (state->head != Z_NULL) + state->head->done = -1; + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + len = BITS(4) + 8; + if (len > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + state->dmax = 1U << len; + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->head != Z_NULL) + state->head->text = (int)((hold >> 8) & 1); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->head != Z_NULL) + state->head->time = hold; + if (state->flags & 0x0200) CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->head != Z_NULL) { + state->head->xflags = (int)(hold & 0xff); + state->head->os = (int)(hold >> 8); + } + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->head != Z_NULL) + state->head->extra_len = (unsigned)hold; + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + } + else if (state->head != Z_NULL) + state->head->extra = Z_NULL; + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->head != Z_NULL && + state->head->extra != Z_NULL) { + len = state->head->extra_len - state->length; + zmemcpy(state->head->extra + len, next, + len + copy > state->head->extra_max ? + state->head->extra_max - len : copy); + } + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->length = 0; + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->name != Z_NULL && + state->length < state->head->name_max) + state->head->name[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->name = Z_NULL; + state->length = 0; + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->comment != Z_NULL && + state->length < state->head->comm_max) + state->head->comment[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->comment = Z_NULL; + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if (hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + if (state->head != Z_NULL) { + state->head->hcrc = (int)((state->flags >> 9) & 1); + state->head->done = 1; + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = REVERSE(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.val < 16) { + NEEDBITS(this.bits); + DROPBITS(this.bits); + state->lens[state->have++] = this.val; + } + else { + if (this.val == 16) { + NEEDBITS(this.bits + 2); + DROPBITS(this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (this.val == 17) { + NEEDBITS(this.bits + 3); + DROPBITS(this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(this.bits + 7); + DROPBITS(this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + break; + } + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.op && (this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + state->length = (unsigned)this.val; + if ((int)(this.op) == 0) { + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + state->mode = LIT; + break; + } + if (this.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(this.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->mode = DIST; + case DIST: + for (;;) { + this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if ((this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + if (this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)this.val; + state->extra = (unsigned)(this.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } +#ifdef INFLATE_STRICT + if (state->offset > state->dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + if (state->offset > state->whave + out - left) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->write) { + copy -= state->write; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->write - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if (out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if (( +#ifdef GUNZIP + state->flags ? hold : +#endif + REVERSE(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) + if (updatewindow(strm, out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if (state->wrap && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) +z_streamp strm; +const Bytef *dictionary; +uInt dictLength; +{ + struct inflate_state FAR *state; + unsigned long id; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; + + /* check for correct dictionary id */ + if (state->mode == DICT) { + id = adler32(0L, Z_NULL, 0); + id = adler32(id, dictionary, dictLength); + if (id != state->check) + return Z_DATA_ERROR; + } + + /* copy dictionary to window */ + if (updatewindow(strm, strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + if (dictLength > state->wsize) { + zmemcpy(state->window, dictionary + dictLength - state->wsize, + state->wsize); + state->whave = state->wsize; + } + else { + zmemcpy(state->window + state->wsize - dictLength, dictionary, + dictLength); + state->whave = dictLength; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +int ZEXPORT inflateGetHeader(strm, head) +z_streamp strm; +gz_headerp head; +{ + struct inflate_state FAR *state; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; + + /* save header structure */ + state->head = head; + head->done = 0; + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(have, buf, len) +unsigned FAR *have; +unsigned char FAR *buf; +unsigned len; +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(strm) +z_streamp strm; +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(dest, source) +z_streamp dest; +z_streamp source; +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + unsigned wsize; + + /* check input */ + if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || + source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + zmemcpy(dest, source, sizeof(z_stream)); + zmemcpy(copy, state, sizeof(struct inflate_state)); + if (state->lencode >= state->codes && + state->lencode <= state->codes + ENOUGH - 1) { + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + } + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) { + wsize = 1U << state->wbits; + zmemcpy(window, state->window, wsize); + } + copy->window = window; + dest->state = (struct internal_state FAR *)copy; + return Z_OK; +} diff --git a/dep/src/zlib/inflate.h b/dep/src/zlib/inflate.h new file mode 100644 index 00000000000..07bd3e78a7c --- /dev/null +++ b/dep/src/zlib/inflate.h @@ -0,0 +1,115 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN, /* i: waiting for length/lit code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to the BAD or MEM mode -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME + NAME -> COMMENT -> HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + Read deflate blocks: + TYPE -> STORED or TABLE or LEN or CHECK + STORED -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN + Read deflate codes: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 7K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + gz_headerp head; /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ +}; diff --git a/dep/src/zlib/inftrees.c b/dep/src/zlib/inftrees.c new file mode 100644 index 00000000000..8a9c13ff03d --- /dev/null +++ b/dep/src/zlib/inftrees.c @@ -0,0 +1,329 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.3 Copyright 1995-2005 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int inflate_table(type, lens, codes, table, bits, work) +codetype type; +unsigned short FAR *lens; +unsigned codes; +code FAR * FAR *table; +unsigned FAR *bits; +unsigned short FAR *work; +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code this; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) { /* no symbols to code at all */ + this.op = (unsigned char)64; /* invalid code marker */ + this.bits = (unsigned char)1; + this.val = (unsigned short)0; + *(*table)++ = this; /* make a table to force an error */ + *(*table)++ = this; + *bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min <= MAXBITS; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked when a LENS table is being made + against the space in *table, ENOUGH, minus the maximum space needed by + the worst case distance code, MAXD. This should never happen, but the + sufficiency of ENOUGH has not been proven exhaustively, hence the check. + This assumes that when type == LENS, bits == 9. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + this.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + this.op = (unsigned char)0; + this.val = work[sym]; + } + else if ((int)(work[sym]) > end) { + this.op = (unsigned char)(extra[work[sym]]); + this.val = base[work[sym]]; + } + else { + this.op = (unsigned char)(32 + 64); /* end of block */ + this.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + next[(huff >> drop) + fill] = this; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* + Fill in rest of table for incomplete codes. This loop is similar to the + loop above in incrementing huff for table indices. It is assumed that + len is equal to curr + drop, so there is no loop needed to increment + through high index bits. When the current sub-table is filled, the loop + drops back to the root table to fill in any remaining entries there. + */ + this.op = (unsigned char)64; /* invalid code marker */ + this.bits = (unsigned char)(len - drop); + this.val = (unsigned short)0; + while (huff != 0) { + /* when done with sub-table, drop back to root table */ + if (drop != 0 && (huff & mask) != low) { + drop = 0; + len = root; + next = *table; + this.bits = (unsigned char)len; + } + + /* put invalid code marker in table */ + next[huff >> drop] = this; + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/dep/src/zlib/inftrees.h b/dep/src/zlib/inftrees.h new file mode 100644 index 00000000000..b1104c87e76 --- /dev/null +++ b/dep/src/zlib/inftrees.h @@ -0,0 +1,55 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of dynamic tree. The maximum found in a long but non- + exhaustive search was 1444 code structures (852 for length/literals + and 592 for distances, the latter actually the result of an + exhaustive search). The true maximum is not known, but the value + below is more than safe. */ +#define ENOUGH 2048 +#define MAXD 592 + +/* Type of code to build for inftable() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +extern int inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/dep/src/zlib/trees.c b/dep/src/zlib/trees.c new file mode 100644 index 00000000000..395e4e16814 --- /dev/null +++ b/dep/src/zlib/trees.c @@ -0,0 +1,1219 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2005 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id$ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef DEBUG +# include +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local void set_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (value << s->bi_valid); + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (val << s->bi_valid);\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG */ + + +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG +# include +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if ((unsigned) tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? + s->depth[n] : s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void _tr_stored_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ +#ifdef DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + * The current inflate code requires 9 bits of lookahead. If the + * last two codes for the previous block (real code plus EOB) were coded + * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + * the last real code. In this case we send two empty static blocks instead + * of one. (There are no problems if the previous block is stored or fixed.) + * To simplify the code, we assume the worst case of last real code encoded + * on one bit only. + */ +void _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); + /* Of the 10 bits for the empty block, we have already sent + * (10 - bi_valid) bits. The lookahead for the last real code (before + * the EOB of the previous block) was thus at least one plus the length + * of the EOB plus what we have just sent of the empty static block. + */ + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; +#endif + bi_flush(s); + } + s->last_eob_len = 7; +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +void _tr_flush_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is binary or text */ + if (stored_len > 0 && s->strm->data_type == Z_UNKNOWN) + set_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, eof); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+eof, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+eof, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (eof) { + bi_windup(s); +#ifdef DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*eof)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(s, ltree, dtree) + deflate_state *s; + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +/* =========================================================================== + * Set the data type to BINARY or TEXT, using a crude approximation: + * set it to Z_TEXT if all symbols are either printable characters (33 to 255) + * or white spaces (9 to 13, or 32); or set it to Z_BINARY otherwise. + * IN assertion: the fields Freq of dyn_ltree are set. + */ +local void set_data_type(s) + deflate_state *s; +{ + int n; + + for (n = 0; n < 9; n++) + if (s->dyn_ltree[n].Freq != 0) + break; + if (n == 9) + for (n = 14; n < 32; n++) + if (s->dyn_ltree[n].Freq != 0) + break; + s->strm->data_type = (n == 32) ? Z_TEXT : Z_BINARY; +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +local void copy_block(s, buf, len, header) + deflate_state *s; + charf *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} diff --git a/dep/src/zlib/trees.h b/dep/src/zlib/trees.h new file mode 100644 index 00000000000..72facf900f7 --- /dev/null +++ b/dep/src/zlib/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/dep/src/zlib/uncompr.c b/dep/src/zlib/uncompr.c new file mode 100644 index 00000000000..b59e3d0defb --- /dev/null +++ b/dep/src/zlib/uncompr.c @@ -0,0 +1,61 @@ +/* uncompr.c -- decompress a memory buffer + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ +int ZEXPORT uncompress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + err = inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd(&stream); + if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) + return Z_DATA_ERROR; + return err; + } + *destLen = stream.total_out; + + err = inflateEnd(&stream); + return err; +} diff --git a/dep/src/zlib/zconf.h b/dep/src/zlib/zconf.h new file mode 100644 index 00000000000..03a9431c8be --- /dev/null +++ b/dep/src/zlib/zconf.h @@ -0,0 +1,332 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define deflatePrime z_deflatePrime +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table +# define zError z_zError + +# define alloc_func z_alloc_func +# define free_func z_free_func +# define in_func z_in_func +# define out_func z_out_func +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/dep/src/zlib/zlib.h b/dep/src/zlib/zlib.h new file mode 100644 index 00000000000..022817927ce --- /dev/null +++ b/dep/src/zlib/zlib.h @@ -0,0 +1,1357 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.3, July 18th, 2005 + + Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.3" +#define ZLIB_VERNUM 0x1230 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip streams in memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumualte before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + the value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, + Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() stop + if and when it gets to the next deflate block boundary. When decoding the + zlib or gzip format, this will cause inflate() to return immediately after + the header and before the first block. When doing a raw inflate, inflate() + will go ahead and process the first block, and will return when it gets to + the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 + if inflate() is currently decoding the last block in the deflate stream, + plus 128 if inflate() returned immediately after decoding an end-of-block + code or decoding the complete header up to just before the first byte of the + deflate stream. The end-of-block will not be indicated until all of the + uncompressed data from that block has been written to strm->next_out. The + number of unused bits may in general be greater than seven, except when + bit 7 of data_type is set, in which case the number of unused bits will be + less than eight. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster approach + may be used for the single inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() will decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically. Any information + contained in the gzip header is not retained, so applications that need that + information should instead use raw inflate, see inflateInit2() below, or + inflateBack() and perform their own processing of the gzip header and + trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may then + call inflateSync() to look for a good compression block if a partial recovery + of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), + no header crc, and the operating system will be set to 255 (unknown). If a + gzip stream is being written, strm->adler is a crc32 instead of an adler32. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as + Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy + parameter only affects the compression ratio but not the correctness of the + compressed output even if it is not set appropriately. Z_FIXED prevents the + use of dynamic Huffman codes, allowing for a simpler decoder for special + applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. In addition, the + current implementation of deflate will use at most the window size minus + 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() + or deflateInit2(). This would be used to allocate an output buffer + for deflation in a single pass, and so would be called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the + bits leftover from a previous deflate stream when appending to it. As such, + this function can only be used for raw deflate, and must be used before the + first deflate() call after a deflateInit2() or deflateReset(). bits must be + less than or equal to 16, and that many of the least significant bits of + value will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is + a crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg + is set to null if there is no error message. inflateInit2 does not perform + any decompression apart from reading the zlib header if present: this will + be done by inflate(). (So next_in and avail_in may be modified, but next_out + and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called + immediately after inflateInit2() or inflateReset() and before any call of + inflate() to set the dictionary. The application must insure that the + dictionary that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK can be used to + force inflate() to return immediately after header processing is complete + and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When + any of extra, name, or comment are not Z_NULL and the respective field is + not present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not + be allocated, or Z_VERSION_ERROR if the version of the library does not + match the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free + the allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects + only the raw deflate stream to decompress. This is different from the + normal behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format + error in the deflate stream (in which case strm->msg is set to indicate the + nature of the error), or Z_STREAM_ERROR if the stream was not properly + initialized. In the case of Z_BUF_ERROR, an input or output error can be + distinguished using strm->next_in which will be Z_NULL only if in() returned + an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to + out() returning non-zero. (in() will always be called before out(), so + strm->next_in is assured to be defined if out() returns non-zero.) Note + that inflateBack() cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least the value returned + by compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before + a compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h", or 'R' for run-length encoding + as in "wb1R". (See the description of deflateInit2 for more information + about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). The number of + uncompressed bytes written is limited to 4095. The caller should assure that + this limit is not exceeded. If it is exceeded, then gzprintf() will return + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read again later. + Only one character of push-back is allowed. gzungetc() returns the + character pushed, or -1 on failure. gzungetc() will fail if a + character has been pushed but not read yet, or if c is -1. The pushed + character will be discarded if the stream is repositioned with gzseek() + or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns 1 if file is being read directly without decompression, otherwise + zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); +/* + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is NULL, this function returns the required initial + value for the for the crc. Pre- and post-conditioning (one's complement) is + performed within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + +/* + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/dep/src/zlib/zutil.c b/dep/src/zlib/zutil.c new file mode 100644 index 00000000000..d55f5948a37 --- /dev/null +++ b/dep/src/zlib/zutil.c @@ -0,0 +1,318 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +const char * const z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch (sizeof(uInt)) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch (sizeof(uLong)) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch (sizeof(voidpf)) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch (sizeof(z_off_t)) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef DEBUG + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1L << 16; +#endif +#ifdef NO_GZIP + flags += 1L << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1L << 20; +#endif +#ifdef FASTEST + flags += 1L << 21; +#endif +#ifdef STDC +# ifdef NO_vsnprintf + flags += 1L << 25; +# ifdef HAS_vsprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1L << 26; +# endif +# endif +#else + flags += 1L << 24; +# ifdef NO_snprintf + flags += 1L << 25; +# ifdef HAS_sprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1L << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int z_verbose = verbose; + +void z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. + */ + int errno = 0; +#endif + +#ifndef HAVE_MEMCPY + +void zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} + +#endif /* __TURBOC__ */ + + +#ifdef M_I86 +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* M_I86 */ + +#endif /* SYS16BIT */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + if (opaque) items += size - size; /* make compiler happy */ + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); +} + +void zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ diff --git a/dep/src/zlib/zutil.h b/dep/src/zlib/zutil.h new file mode 100644 index 00000000000..b7d5eff81b6 --- /dev/null +++ b/dep/src/zlib/zutil.h @@ -0,0 +1,269 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#define ZLIB_INTERNAL +#include "zlib.h" + +#ifdef STDC +# ifndef _WIN32_WCE +# include +# endif +# include +# include +#endif +#ifdef NO_ERRNO_H +# ifdef _WIN32_WCE + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. We rename it to + * avoid conflict with other libraries that use the same workaround. + */ +# define errno z_errno +# endif + extern int errno; +#else +# ifndef _WIN32_WCE +# include +# endif +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +# ifdef M_I86 + #include +# endif +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#ifdef WIN32 +# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ +# define OS_CODE 0x0b +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0f +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS + /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 + /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# define vsnprintf _vsnprintf +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +#endif +#ifdef VMS +# define NO_vsnprintf +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + extern void zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int z_verbose; + extern void z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); +void zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* ZUTIL_H */ diff --git a/dep/src/zthread/AtomicCount.cxx b/dep/src/zthread/AtomicCount.cxx new file mode 100644 index 00000000000..ac0d0773b12 --- /dev/null +++ b/dep/src/zthread/AtomicCount.cxx @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTATOMICCOUNTSELECT_H__ +#define __ZTATOMICCOUNTSELECT_H__ + +#include "zthread/AtomicCount.h" +#include "zthread/Config.h" + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* +// Select the correct AtomicCount implementation based on +// what the compilation environment has defined + +#ifndef ZT_VANILLA + +#if defined(HAVE_ATOMIC_LINUX) +# include "linux/AtomicCount.cxx" +#elif defined(ZT_WIN32) +# include "win32/AtomicCount.cxx" +#elif defined(ZT_WIN9X) +# include "win9x/AtomicCount.cxx" +#endif + +#endif + +// Default to an AtomicCount that just uses a FastLock +#ifndef __ZTATOMICCOUNTIMPL_H__ +# include "vanilla/SimpleAtomicCount.cxx" +#endif +*/ + +# include "vanilla/SimpleAtomicCount.cxx" + +#endif // __ZTATOMICCOUNTSELECT_H__ diff --git a/dep/src/zthread/ConcurrentExecutor.cxx b/dep/src/zthread/ConcurrentExecutor.cxx new file mode 100644 index 00000000000..a65e9c5e909 --- /dev/null +++ b/dep/src/zthread/ConcurrentExecutor.cxx @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#include "zthread/ConcurrentExecutor.h" + +namespace ZThread { + + ConcurrentExecutor::ConcurrentExecutor() + : _executor(1) {} + + void ConcurrentExecutor::interrupt() { + _executor.interrupt(); + } + + void ConcurrentExecutor::execute(const Task& task) { + _executor.execute(task); + } + + void ConcurrentExecutor::cancel() { + _executor.cancel(); + } + + bool ConcurrentExecutor::isCanceled() { + return _executor.isCanceled(); + } + + void ConcurrentExecutor::wait() { + _executor.wait(); + } + + bool ConcurrentExecutor::wait(unsigned long timeout) { + return _executor.wait(timeout); + } + +} diff --git a/dep/src/zthread/Condition.cxx b/dep/src/zthread/Condition.cxx new file mode 100644 index 00000000000..39485fb5ca4 --- /dev/null +++ b/dep/src/zthread/Condition.cxx @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#include "zthread/Condition.h" +#include "ConditionImpl.h" + +namespace ZThread { + + class FifoConditionImpl : public ConditionImpl { + public: + FifoConditionImpl(Lockable& l) : ConditionImpl(l) {} + + }; + + Condition::Condition(Lockable& lock) { + + _impl = new FifoConditionImpl(lock); + + } + + + Condition::~Condition() { + + if(_impl != 0) + delete _impl; + + } + + + + void Condition::wait() { + + _impl->wait(); + + } + + + + bool Condition::wait(unsigned long ms) { + + return _impl->wait(ms); + + } + + + + void Condition::signal() { + + _impl->signal(); + + } + + + void Condition::broadcast() { + + _impl->broadcast(); + + } + +} // namespace ZThread + diff --git a/dep/src/zthread/ConditionImpl.h b/dep/src/zthread/ConditionImpl.h new file mode 100644 index 00000000000..eeeaba10bbc --- /dev/null +++ b/dep/src/zthread/ConditionImpl.h @@ -0,0 +1,377 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTCONDITIONIMPL_H__ +#define __ZTCONDITIONIMPL_H__ + +#include "zthread/Guard.h" + +#include "Debug.h" +#include "Scheduling.h" +#include "DeferredInterruptionScope.h" + +namespace ZThread { + +/** + * @class ConditionImpl + * @author Eric Crahen + * @date <2003-07-18T08:15:37-0400> + * @version 2.2.11 + * + * The ConditionImpl template allows how waiter lists are sorted + * to be parameteized + */ +template +class ConditionImpl { + + //! Waiters currently blocked + List _waiters; + + //! Serialize access to this object + FastLock _lock; + + //! External lock + Lockable& _predicateLock; + + public: + + /** + * Create a new ConditionImpl. + * + * @exception Initialization_Exception thrown if resources could not be + * allocated + */ + ConditionImpl(Lockable& predicateLock) : _predicateLock(predicateLock) { + + } + + /** + * Destroy this ConditionImpl, release its resources + */ + ~ConditionImpl(); + + void signal(); + + void broadcast(); + + void wait(); + + bool wait(unsigned long timeout); + +}; + + +template +ConditionImpl::~ConditionImpl() { + +#ifndef NDEBUG + + // It is an error to destroy a condition with threads waiting on it. + if(!_waiters.empty()) { + + ZTDEBUG("** You are destroying a condition variable which still has waiting threads. **\n"); + assert(0); + + } + +#endif + + } + + +/** + * Signal the condition variable, waking one thread if any. + */ +template +void ConditionImpl::signal() { + + Guard g1(_lock); + + // Try to find a waiter with a backoff & retry scheme + for(;;) { + + // Go through the list, attempt to notify() a waiter. + for(typename List::iterator i = _waiters.begin(); i != _waiters.end();) { + + // Try the monitor lock, if it cant be locked skip to the next waiter + ThreadImpl* impl = *i; + Monitor& m = impl->getMonitor(); + + if(m.tryAcquire()) { + + // Notify the monitor & remove from the waiter list so time isn't + // wasted checking it again. + i = _waiters.erase(i); + + // If notify() is not sucessful, it is because the wait() has already + // been ended (killed/interrupted/notify'd) + bool woke = m.notify(); + + m.release(); + + // Once notify() succeeds, return + if(woke) + return; + + } else ++i; + + } + + if(_waiters.empty()) + return; + + { // Backoff and try again + + Guard g2(g1); + ThreadImpl::yield(); + + } + + } + + } + +/** + * Broadcast to the condition variable, waking all threads waiting at the time of + * the broadcast. + */ +template +void ConditionImpl::broadcast() { + + Guard g1(_lock); + + // Try to find a waiter with a backoff & retry scheme + for(;;) { + + // Go through the list, attempt to notify() a waiter. + for(typename List::iterator i = _waiters.begin(); i != _waiters.end();) { + + // Try the monitor lock, if it cant be locked skip to the next waiter + ThreadImpl* impl = *i; + Monitor& m = impl->getMonitor(); + + if(m.tryAcquire()) { + + // Notify the monitor & remove from the waiter list so time isn't + // wasted checking it again. + i = _waiters.erase(i); + + // Try to wake the waiter, it doesn't matter if this is successful + // or not (only fails when the monitor is already going to stop waiting). + m.notify(); + + m.release(); + + } else ++i; + + } + + if(_waiters.empty()) + return; + + { // Backoff and try again + + Guard g2(g1); + ThreadImpl::yield(); + + } + + } + + } + +/** + * Cause the currently executing thread to block until this ConditionImpl has + * been signaled, the threads state changes. + * + * @param predicate Lockable& + * + * @exception Interrupted_Exception thrown when the caller status is interrupted + * @exception Synchronization_Exception thrown if there is some other error. + */ +template +void ConditionImpl::wait() { + + // Get the monitor for the current thread + ThreadImpl* self = ThreadImpl::current(); + Monitor& m = self->getMonitor(); + + Monitor::STATE state; + + { + + Guard g1(_lock); + + // Release the _predicateLock + _predicateLock.release(); + + // Stuff the waiter into the list + _waiters.insert(self); + + // Move to the monitor's lock + m.acquire(); + + { + + Guard g2(g1); + state = m.wait(); + + } + + // Move back to the Condition's lock + m.release(); + + // Remove from waiter list, regarless of weather release() is called or + // not. The monitor is sticky, so its possible a state 'stuck' from a + // previous operation and will leave the wait() w/o release() having + // been called. + typename List::iterator i = std::find(_waiters.begin(), _waiters.end(), self); + if(i != _waiters.end()) + _waiters.erase(i); + + } + + // Defer interruption until the external lock is acquire()d + Guard g3(m); + { + +#if !defined(NDEBUG) + try { +#endif + _predicateLock.acquire(); // Should not throw +#if !defined(NDEBUG) + } catch(...) { assert(0); } +#endif + + } + + switch(state) { + + case Monitor::SIGNALED: + break; + + case Monitor::INTERRUPTED: + throw Interrupted_Exception(); + + default: + throw Synchronization_Exception(); + } + + } + + +/** + * Cause the currently executing thread to block until this ConditionImpl has + * been signaled, or the timeout expires or the threads state changes. + * + * @param _predicateLock Lockable& + * @param timeout maximum milliseconds to block. + * + * @return bool + * + * @exception Interrupted_Exception thrown when the caller status is interrupted + * @exception Synchronization_Exception thrown if there is some other error. + */ +template +bool ConditionImpl::wait(unsigned long timeout) { + + // Get the monitor for the current thread + ThreadImpl* self = ThreadImpl::current(); + Monitor& m = self->getMonitor(); + + Monitor::STATE state; + + { + + Guard g1(_lock); + + // Release the _predicateLock + _predicateLock.release(); + + // Stuff the waiter into the list + _waiters.insert(self); + + state = Monitor::TIMEDOUT; + + // Don't bother waiting if the timeout is 0 + if(timeout) { + + m.acquire(); + + { + + Guard g2(g1); + state = m.wait(timeout); + + } + + m.release(); + + } + + // Remove from waiter list, regarless of weather release() is called or + // not. The monitor is sticky, so its possible a state 'stuck' from a + // previous operation and will leave the wait() w/o release() having + // been called. + typename List::iterator i = std::find(_waiters.begin(), _waiters.end(), self); + if(i != _waiters.end()) + _waiters.erase(i); + + } + + + // Defer interruption until the external lock is acquire()d + Guard g3(m); + { + +#if !defined(NDEBUG) + try { +#endif + _predicateLock.acquire(); // Should not throw +#if !defined(NDEBUG) + } catch(...) { assert(0); } +#endif + + } + + switch(state) { + + case Monitor::SIGNALED: + break; + + case Monitor::INTERRUPTED: + throw Interrupted_Exception(); + + case Monitor::TIMEDOUT: + return false; + + default: + throw Synchronization_Exception(); + } + + return true; + + } + +} // namespace ZThread + +#endif // __ZTCONDITIONIMPL_H__ diff --git a/dep/src/zthread/CountingSemaphore.cxx b/dep/src/zthread/CountingSemaphore.cxx new file mode 100644 index 00000000000..43e8b8cfba7 --- /dev/null +++ b/dep/src/zthread/CountingSemaphore.cxx @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#include "zthread/CountingSemaphore.h" +#include "SemaphoreImpl.h" + +using namespace ZThread; + +namespace ZThread { + + + CountingSemaphore::CountingSemaphore(int initialCount) { + + _impl = new FifoSemaphoreImpl(initialCount, 0 , false); + + } + + + CountingSemaphore::~CountingSemaphore() { + + try { + + if(_impl != 0) + delete _impl; + + } catch(...) { } + + } + + + void CountingSemaphore::wait() { + _impl->acquire(); + } + + + bool CountingSemaphore::tryWait(unsigned long ms) { + + return _impl->tryAcquire(ms); + + } + + + void CountingSemaphore::post() { + + _impl->release(); + + } + + int CountingSemaphore::count() { + + return _impl->count(); + + } + + void CountingSemaphore::acquire() { + + _impl->acquire(); + + } + + bool CountingSemaphore::tryAcquire(unsigned long ms) { + + return _impl->tryAcquire(ms); + + } + + void CountingSemaphore::release() { + + _impl->release(); + + } + +} // namespace ZThread diff --git a/dep/src/zthread/Debug.h b/dep/src/zthread/Debug.h new file mode 100644 index 00000000000..484b37f7d6f --- /dev/null +++ b/dep/src/zthread/Debug.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef ZTDEBUG + +#ifndef NDEBUG +# include +# define ZTDEBUG printf +#else +# define ZTDEBUG(x) +#endif + +#endif diff --git a/dep/src/zthread/DeferredInterruptionScope.h b/dep/src/zthread/DeferredInterruptionScope.h new file mode 100644 index 00000000000..041d1e427f6 --- /dev/null +++ b/dep/src/zthread/DeferredInterruptionScope.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTDEFERREDINTERRUPTIONSCOPE_H__ +#define __ZTDEFERREDINTERRUPTIONSCOPE_H__ + +#include "ThreadImpl.h" +#include + +namespace ZThread { + +/** + * @class DeferredInterruptionScope + * @author Eric Crahen + * @date <2003-07-16T19:45:18-0400> + * @version 2.3.0 + * + * Locking policy for a Guard that will defer any state reported + * for the reported Status of a thread except SIGNALED until the + * scope has ended. This allows a Guard to be used to create an + * uninterruptible region in code. + */ +class DeferredInterruptionScope { + public: + + template + static void createScope(LockHolder& l) { + + l.getLock().interest(Monitor::SIGNALED); + + } + + template + static void destroyScope(LockHolder& l) { + + l.getLock().interest(Monitor::ANYTHING); + + } + +}; + +} + +#endif // __ZTDEFERREDINTERRUPTIONSCOPE_H__ diff --git a/dep/src/zthread/FastLock.h b/dep/src/zthread/FastLock.h new file mode 100644 index 00000000000..4d7f34a086d --- /dev/null +++ b/dep/src/zthread/FastLock.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTFASTLOCKSELECT_H__ +#define __ZTFASTLOCKSELECT_H__ + +#include "zthread/Config.h" + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +// Select the correct FastLock implementation based on +// what the compilation environment has defined + +#if defined(ZT_POSIX) + +# if defined(HAVE_ATOMIC_LINUX) + +# if defined(ZTHREAD_USE_SPIN_LOCKS) +# include "linux/AtomicFastLock.h" +# endif + +# endif + +# include "posix/FastLock.h" + +// Use spin locks +#elif defined(ZTHREAD_USE_SPIN_LOCKS) + +# if defined(ZT_WIN9X) +# include "win9x/AtomicFastLock.h" +# elif defined(ZT_WIN32) +# include "win32/AtomicFastLock.h" +# endif + +// Use normal Mutex objects +#elif defined(ZT_WIN9X) || defined(ZT_WIN32) + +# include "win32/FastLock.h" + +#elif defined(ZT_MACOS) + +# include "macos/FastLock.h" + +#endif + +#ifndef __ZTFASTLOCK_H__ +#error "No FastLock implementation could be selected" +#endif + +#endif // __ZTFASTLOCKSELECT_H__ diff --git a/dep/src/zthread/FastMutex.cxx b/dep/src/zthread/FastMutex.cxx new file mode 100644 index 00000000000..464dd83e5e0 --- /dev/null +++ b/dep/src/zthread/FastMutex.cxx @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#include "zthread/FastMutex.h" +#include "FastLock.h" + +namespace ZThread { + + FastMutex::FastMutex() : _lock(new FastLock) { } + + FastMutex::~FastMutex() { + delete _lock; + } + + + void FastMutex::acquire() { + + _lock->acquire(); + + } + + bool FastMutex::tryAcquire(unsigned long timeout) { + + return _lock->tryAcquire(timeout); + + } + + void FastMutex::release() { + + _lock->release(); + + } + +} // namespace ZThread diff --git a/dep/src/zthread/FastRecursiveLock.h b/dep/src/zthread/FastRecursiveLock.h new file mode 100644 index 00000000000..0a36f62d5f8 --- /dev/null +++ b/dep/src/zthread/FastRecursiveLock.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTFASTRECURSIVELOCKSELECT_H__ +#define __ZTFASTRECURSIVELOCKSELECT_H__ + +#include "zthread/Config.h" + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + + +// Select the correct FastRecusriveLock implementation based on +// what the compilation environment has defined + +#if defined(ZTHREAD_DUAL_LOCKS) +# include "vanilla/DualMutexRecursiveLock.h" +#else + +# ifndef ZT_VANILLA + +# if defined(ZT_POSIX) + +// Linux and Solaris have working pthreads recursive locks. These +// are created differently, and there are some system don't seem to +// include recursive locks at all. Several recursive implementations +// are provided + +# if defined(__linux__) +# include "linux/FastRecursiveLock.h" +# elif defined(HAVE_MUTEXATTR_SETTYPE) +# include "solaris/FastRecursiveLock.h" +# elif defined(ZTHREAD_CONDITION_LOCKS) +# include "posix/ConditionRecursiveLock.h" +# endif + +// Use spin locks +# elif defined(ZT_WIN32) && defined(ZTHREAD_USE_SPIN_LOCKS) +# include "win32/AtomicFastRecursiveLock.h" + +// Use normal Mutex objects +# elif defined(ZT_WIN32) || defined(ZT_WIN9X) +# include "win32/FastRecursiveLock.h" +# endif + +# endif + +#endif + +#ifndef __ZTFASTRECURSIVELOCK_H__ +#include "vanilla/SimpleRecursiveLock.h" +#endif + +#endif // __ZTFASTRECURSIVELOCKSELECT_H__ diff --git a/dep/src/zthread/FastRecursiveMutex.cxx b/dep/src/zthread/FastRecursiveMutex.cxx new file mode 100644 index 00000000000..5ca677a654d --- /dev/null +++ b/dep/src/zthread/FastRecursiveMutex.cxx @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#include "zthread/FastRecursiveMutex.h" +#include "FastRecursiveLock.h" + +namespace ZThread { + + FastRecursiveMutex::FastRecursiveMutex() + : _lock(new FastRecursiveLock) { } + + FastRecursiveMutex::~FastRecursiveMutex() + { delete _lock; } + + + void FastRecursiveMutex::acquire() { + + _lock->acquire(); + + } + + bool FastRecursiveMutex::tryAcquire(unsigned long timeout) { + + return _lock->tryAcquire(timeout); + + } + + void FastRecursiveMutex::release() { + + _lock->release(); + + } + +} // namespace ZThread diff --git a/dep/src/zthread/IntrusivePtr.h b/dep/src/zthread/IntrusivePtr.h new file mode 100644 index 00000000000..47d5afbfcb8 --- /dev/null +++ b/dep/src/zthread/IntrusivePtr.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTINTRUSIVEPTR_H__ +#define __ZTINTRUSIVEPTR_H__ + +#include "zthread/Guard.h" +#include + +namespace ZThread { + +/** + * @class IntrusivePtr + * @author Eric Crahen + * @date <2003-07-16T17:54:23-0400> + * @version 2.2.0 + * + * This template creates an intrusively reference counted object + * an IntrusivePtr starts out with a 1 count, which is updated as references are + * added and removed. When the reference count drops to 0, the + * IntrusivePtr will delete itself. + */ +template +class IntrusivePtr : NonCopyable { + + //! Intrusive reference count + size_t _count; + + //! Synchornization object + LockType _lock; + +public: + + /** + * Create an IntrusivePtr with a count. + */ + IntrusivePtr(size_t InitialCount=1) : _count(InitialCount) { } + + /** + * Destroy an IntrusivePtr + */ + virtual ~IntrusivePtr() {} + + /** + * Add a reference to this object, it will take one more + * call to delReference() for it to be deleted. + */ + void addReference() { + + Guard g(_lock); + _count++; + + } + + /** + * Remove a reference from this object, if the reference count + * drops to 0 as a result, the object deletes itself. + */ + void delReference() { + + bool result = false; + + { + + Guard g(_lock); + result = (--_count == 0); + + } + + if(result) + delete this; + + } + +}; + + +}; + +#endif diff --git a/dep/src/zthread/Makefile.am b/dep/src/zthread/Makefile.am new file mode 100644 index 00000000000..a3c91195d51 --- /dev/null +++ b/dep/src/zthread/Makefile.am @@ -0,0 +1,132 @@ +## Copyright (c) 2005, Eric Crahen +## Modified for MaNGOS project +## +## 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. + +## Process this file with automake to produce Makefile.in + +## CPP flags for includes, defines, etc. +AM_CPPFLAGS = -I$(srcdir)/../../include -I$(srcdir)/../../include/zthread + +## Build ZThread as shared library. +# libZThread shared library will later be reused by realm list daemon +# and world server daemon. +lib_LTLIBRARIES = libZThread.la +libZThread_la_SOURCES = \ + AtomicCount.cxx \ + Condition.cxx \ + ConcurrentExecutor.cxx \ + CountingSemaphore.cxx \ + FastMutex.cxx \ + FastRecursiveMutex.cxx \ + Mutex.cxx \ + RecursiveMutexImpl.cxx \ + RecursiveMutex.cxx \ + Monitor.cxx \ + PoolExecutor.cxx \ + PriorityCondition.cxx \ + PriorityInheritanceMutex.cxx \ + PriorityMutex.cxx \ + PrioritySemaphore.cxx \ + Semaphore.cxx \ + SynchronousExecutor.cxx \ + Thread.cxx \ + ThreadedExecutor.cxx \ + ThreadImpl.cxx \ + ThreadLocalImpl.cxx \ + ThreadQueue.cxx \ + Time.cxx \ + ThreadOps.cxx + +## libtool settings +# API versioning +# Link against dependencies +# How to increase version info: +# - only bug fixes implemented: +# bump the version to LTZTHREAD_CURRENT:LTZTHREAD_REVISION+1:LTZTHREAD_AGE +# - augmented the interface: +# bump the version to LTZTHREAD_CURRENT+1:0:LTZTHREAD_AGE+1 +# - broken old interface: +# bump the version to LTZTHREAD_CURRENT+1:0:0 +LTZTHREAD_CURRENT = 2 +LTZTHREAD_REVISION = 3 +LTZTHREAD_AGE = 2 +libZThread_la_LDFLAGS = -version-info $(LTZTHREAD_CURRENT):$(LTZTHREAD_REVISION):$(LTZTHREAD_AGE) + +## Additional files to include when running 'make dist' +# Header files. +EXTRA_DIST = \ + ConditionImpl.h \ + Debug.h \ + DeferredInterruptionScope.h \ + FastLock.h \ + FastRecursiveLock.h \ + IntrusivePtr.h \ + Monitor.h \ + MutexImpl.h \ + RecursiveMutexImpl.h \ + Scheduling.h \ + SemaphoreImpl.h \ + State.h \ + Status.h \ + TSS.h \ + ThreadImpl.h \ + ThreadOps.h \ + ThreadQueue.h \ + TimeStrategy.h \ + config.h + +# Implementation specific files. +EXTRA_DIST += \ + linux/AtomicCount.cxx \ + linux/AtomicFastLock.h \ + linux/FastRecursiveLock.h \ + macos/FastLock.h \ + macos/Monitor.cxx \ + macos/Monitor.h \ + macos/TSS.h \ + macos/ThreadOps.cxx \ + macos/ThreadOps.h \ + macos/UpTimeStrategy.h \ + posix/ConditionRecursiveLock.h \ + posix/FastLock.h \ + posix/FtimeStrategy.h \ + posix/GetTimeOfDayStrategy.h \ + posix/Monitor.cxx \ + posix/Monitor.h \ + posix/PriorityOps.h \ + posix/TSS.h \ + posix/ThreadOps.cxx \ + posix/ThreadOps.h \ + solaris/FastRecursiveLock.h \ + vanilla/DualMutexRecursiveLock.h \ + vanilla/SimpleAtomicCount.cxx \ + vanilla/SimpleRecursiveLock.h \ + win32/AtomicCount.cxx \ + win32/AtomicFastLock.h \ + win32/AtomicFastRecursiveLock.h \ + win32/FastLock.h \ + win32/FastRecursiveLock.h \ + win32/Monitor.cxx \ + win32/Monitor.h \ + win32/PerformanceCounterStrategy.h \ + win32/TSS.h \ + win32/ThreadOps.cxx \ + win32/ThreadOps.h \ + win9x/AtomicCount.cxx \ + win9x/AtomicFastLock.h diff --git a/dep/src/zthread/Monitor.cxx b/dep/src/zthread/Monitor.cxx new file mode 100644 index 00000000000..9a578e796ed --- /dev/null +++ b/dep/src/zthread/Monitor.cxx @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTMONITORIMPLSELECT_CXX__ +#define __ZTMONITORIMPLSELECT_CXX__ + +#include "Monitor.h" + +// This file will select an implementation for a Monitor based on +// what Monitor.h selects. This method is for selecting the +// source files, to improve portability. Currently, the project is +// based on the autoconf tool-set, which doesn't support conditional +// compilation well. Additionally, this should make the library +// easier to port since its working around conditional compilation +// by using C++ features and people won't have to fiddle around with +// their make tool as much to compile the source + +#include ZT_MONITOR_IMPLEMENTATION + +#endif diff --git a/dep/src/zthread/Monitor.h b/dep/src/zthread/Monitor.h new file mode 100644 index 00000000000..6f9492fe32c --- /dev/null +++ b/dep/src/zthread/Monitor.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTMONITORSELECT_H__ +#define __ZTMONITORSELECT_H__ + +#include "zthread/Config.h" + +#if defined(ZT_MONITOR_IMPLEMENTATION) +# error "Reserved symbol defined" +#endif + +// Include the dependencies for a Montior +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +// Select the correct Monitor implementation based on +// what the compilation environment has defined +#if defined(ZT_POSIX) + +# include "posix/Monitor.h" +# define ZT_MONITOR_IMPLEMENTATION "posix/Monitor.cxx" + +#elif defined(ZT_WIN32) || defined(ZT_WIN9X) + +# include "win32/Monitor.h" +# define ZT_MONITOR_IMPLEMENTATION "win32/Monitor.cxx" + +#elif defined(ZT_MACOS) + +# include "macos/Monitor.h" +# define ZT_MONITOR_IMPLEMENTATION "macos/Monitor.cxx" + +#endif + +#ifndef __ZTMONITOR_H__ +#error "No Monitor implementation could be selected" +#endif + +#endif // __ZTMONITORSELECT_H__ diff --git a/dep/src/zthread/Mutex.cxx b/dep/src/zthread/Mutex.cxx new file mode 100644 index 00000000000..eca38ba89c6 --- /dev/null +++ b/dep/src/zthread/Mutex.cxx @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#include "zthread/Mutex.h" +#include "MutexImpl.h" + +namespace ZThread { + + class FifoMutexImpl : public MutexImpl { }; + + + Mutex::Mutex() { + + _impl = new FifoMutexImpl(); + + } + + Mutex::~Mutex() { + + if(_impl != 0) + delete _impl; + } + + // P + void Mutex::acquire() { + + _impl->acquire(); + + } + + + // P + bool Mutex::tryAcquire(unsigned long ms) { + + return _impl->tryAcquire(ms); + + } + + // V + void Mutex::release() { + + _impl->release(); + + } + + + +} // namespace ZThread + diff --git a/dep/src/zthread/MutexImpl.h b/dep/src/zthread/MutexImpl.h new file mode 100644 index 00000000000..10a9160ce5a --- /dev/null +++ b/dep/src/zthread/MutexImpl.h @@ -0,0 +1,377 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#include "zthread/Exceptions.h" +#include "zthread/Guard.h" + +#include "Debug.h" +#include "FastLock.h" +#include "Scheduling.h" + +#include +#include + +namespace ZThread { + + +/** + * @author Eric Crahen + * @date <2003-07-16T19:52:12-0400> + * @version 2.2.11 + * @class NullBehavior + */ +class NullBehavior { +protected: + + inline void waiterArrived(ThreadImpl*) { } + + inline void waiterDeparted(ThreadImpl*) { } + + inline void ownerAcquired(ThreadImpl*) { } + + inline void ownerReleased(ThreadImpl*) { } + +}; + +/** + * @author Eric Crahen + * @date <2003-07-16T19:52:12-0400> + * @version 2.2.11 + * @class MutexImpl + * + * The MutexImpl template allows how waiter lists are sorted, and + * what actions are taken when a thread interacts with the mutex + * to be parametized. + */ +template +class MutexImpl : Behavior { + + //! List of Events that are waiting for notification + List _waiters; + + //! Serialize access to this Mutex + FastLock _lock; + + //! Current owner + volatile ThreadImpl* _owner; + + public: + + + /** + * Create a new MutexImpl + * + * @exception Initialization_Exception thrown if resources could not be + * properly allocated + */ + MutexImpl() : _owner(0) { } + + ~MutexImpl(); + + void acquire(); + + void release(); + + bool tryAcquire(unsigned long timeout); + +}; + + /** + * Destroy this MutexImpl and release its resources + */ +template +MutexImpl::~MutexImpl() { + +#ifndef NDEBUG + + // It is an error to destroy a mutex that has not been released + if(_owner != 0) { + + ZTDEBUG("** You are destroying a mutex which was never released. **\n"); + assert(0); // Destroyed mutex while in use + + } + + if(!_waiters.empty()) { + + ZTDEBUG("** You are destroying a mutex which is blocking %d threads. **\n", _waiters.size()); + assert(0); // Destroyed mutex while in use + + } + +#endif + + } + + + /** + * Acquire a lock on the mutex. If this operation succeeds the calling + * thread holds an exclusive lock on this mutex, otherwise it is blocked + * until the lock can be acquired. + * + * @exception Deadlock_Exception thrown when the caller attempts to acquire() more + * than once, If the checking flag is set. + * @exception Interrupted_Exception thrown when the caller status is interrupted + * @exception Synchronization_Exception thrown if there is some other error. + */ +template +void MutexImpl::acquire() { + + ThreadImpl* self = ThreadImpl::current(); + Monitor& m = self->getMonitor(); + + Monitor::STATE state; + + Guard g1(_lock); + + // Deadlock will occur if the current thread is the owner + // and there is no entry count. + if(_owner == self) + throw Deadlock_Exception(); + + // Acquire the lock if it is free and there are no waiting threads + if(_owner == 0 && _waiters.empty()) { + + _owner = self; + + this->ownerAcquired(self); + + } + + // Otherwise, wait for a signal from a thread releasing its + // ownership of the lock + else { + + _waiters.insert(self); + m.acquire(); + + this->waiterArrived(self); + + { + + Guard g2(g1); + state = m.wait(); + + } + + this->waiterDeparted(self); + + m.release(); + + // Remove from waiter list, regardless of wether release() is called or + // not. The monitor is sticky, so its possible a state 'stuck' from a + // previous operation and will leave the wait() w/o release() having + // been called (e.g. interrupted) + typename List::iterator i = std::find(_waiters.begin(), _waiters.end(), self); + if(i != _waiters.end()) + _waiters.erase(i); + + // If awoke due to a notify(), take ownership. + switch(state) { + case Monitor::SIGNALED: + + assert(_owner == 0); + _owner = self; + + this->ownerAcquired(self); + + break; + + case Monitor::INTERRUPTED: + throw Interrupted_Exception(); + + default: + throw Synchronization_Exception(); + } + + } + + } + + + /** + * Acquire a lock on the mutex. If this operation succeeds the calling + * thread holds an exclusive lock on this mutex. If the lock cannot be + * obtained before the timeout expires, the caller returns false. + * + * @exception Deadlock_Exception thrown when the caller attempts to acquire() more + * than once, If the checking flag is set. + * @exception Interrupted_Exception thrown when the caller status is interrupted + * @exception Synchronization_Exception thrown if there is some other error. + */ +template +bool MutexImpl::tryAcquire(unsigned long timeout) { + + ThreadImpl* self = ThreadImpl::current(); + Monitor& m = self->getMonitor(); + + Guard g1(_lock); + + // Deadlock will occur if the current thread is the owner + // and there is no entry count. + if(_owner == self) + throw Deadlock_Exception(); + + // Acquire the lock if it is free and there are no waiting threads + if(_owner == 0 && _waiters.empty()) { + + _owner = self; + + this->ownerAcquired(self); + + } + + // Otherwise, wait for a signal from a thread releasing its + // ownership of the lock + else { + + _waiters.insert(self); + + Monitor::STATE state = Monitor::TIMEDOUT; + + // Don't bother waiting if the timeout is 0 + if(timeout) { + + m.acquire(); + + this->waiterArrived(self); + + { + + Guard g2(g1); + state = m.wait(timeout); + + } + + this->waiterDeparted(self); + + m.release(); + + } + + + // Remove from waiter list, regarless of weather release() is called or + // not. The monitor is sticky, so its possible a state 'stuck' from a + // previous operation and will leave the wait() w/o release() having + // been called. + typename List::iterator i = std::find(_waiters.begin(), _waiters.end(), self); + if(i != _waiters.end()) + _waiters.erase(i); + + // If awoke due to a notify(), take ownership. + switch(state) { + case Monitor::SIGNALED: + + assert(0 == _owner); + _owner = self; + + this->ownerAcquired(self); + + break; + + case Monitor::INTERRUPTED: + throw Interrupted_Exception(); + + case Monitor::TIMEDOUT: + return false; + + default: + throw Synchronization_Exception(); + } + + } + + return true; + + } + + /** + * Release a lock on the mutex. If this operation succeeds the calling + * thread no longer holds an exclusive lock on this mutex. If there are + * waiting threads, one will be selected, assigned ownership and specifically + * awakened. + * + * @exception InvalidOp_Exception - thrown if an attempt is made to + * release a mutex not owned by the calling thread. + */ +template +void MutexImpl::release() { + + ThreadImpl* impl = ThreadImpl::current(); + + Guard g1(_lock); + + // Make sure the operation is valid + if(_owner != impl) + throw InvalidOp_Exception(); + + _owner = 0; + + this->ownerReleased(impl); + + // Try to find a waiter with a backoff & retry scheme + for(;;) { + + // Go through the list, attempt to notify() a waiter. + for(typename List::iterator i = _waiters.begin(); i != _waiters.end();) { + + // Try the monitor lock, if it cant be locked skip to the next waiter + impl = *i; + Monitor& m = impl->getMonitor(); + + if(m.tryAcquire()) { + + // If notify() is not sucessful, it is because the wait() has already + // been ended (killed/interrupted/notify'd) + bool woke = m.notify(); + + m.release(); + + // Once notify() succeeds, return + if(woke) + return; + + } else ++i; + + } + + if(_waiters.empty()) + return; + + { // Backoff and try again + + Guard g2(g1); + ThreadImpl::yield(); + + } + + } + + } + +} // namespace ZThread + + + + + + diff --git a/dep/src/zthread/PoolExecutor.cxx b/dep/src/zthread/PoolExecutor.cxx new file mode 100644 index 00000000000..cf84e145453 --- /dev/null +++ b/dep/src/zthread/PoolExecutor.cxx @@ -0,0 +1,629 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#include "ThreadImpl.h" +#include "zthread/PoolExecutor.h" +#include "zthread/MonitoredQueue.h" +#include "zthread/FastMutex.h" +#include "ThreadImpl.h" +#include "ThreadQueue.h" + +#include +#include +#include + +using namespace ZThread; + +namespace ZThread { + + namespace { + + /** + */ + class WaiterQueue { + + typedef std::deque ThreadList; + + typedef struct group_t { + size_t id; + size_t count; + ThreadList waiters; + group_t(size_t n) : id(n), count(0) {} + } Group; + + typedef std::deque GroupList; + + //! Predicate to find a specific group + struct by_id : public std::unary_function { + size_t id; + by_id(size_t n) : id(n) {} + bool operator()(const Group& grp) { + return grp.id == id; + } + }; + + //! Functor to count groups + struct counter : public std::unary_function { + size_t count; + counter() : count(0) {} + void operator()(const Group& grp) { count += grp.count; } + operator size_t() { return count; } + }; + + FastMutex _lock; + GroupList _list; + size_t _id; + size_t _generation; + + public: + + WaiterQueue() : _id(0), _generation(0) { + // At least one empty-group exists + _list.push_back( Group(_id++) ); + } + + /** + * Insert the current thread into the current waiter list + * + * @pre At least one empty group exists + * @post At least one empty group exists + */ + bool wait(unsigned long timeout) { + + ThreadImpl* current = ThreadImpl::current(); + Monitor& m = current->getMonitor(); + + Monitor::STATE state; + + Guard g1(_lock); + + // At least one empty-group exists + assert(!_list.empty()); + + // Return w/o waiting if there are no executing tasks + if((size_t)std::for_each(_list.begin(), _list.end(), counter()) < 1) + return true; + + // Update the waiter list for the active group + _list.back().waiters.push_back(current); + size_t n = _list.back().id; + + m.acquire(); + + { + + Guard g2(g1); + state = timeout == 0 ? m.wait() : m.wait(timeout); + + } + + m.release(); + + // If awoke due to a reason other than the last task in the group 'n' completing, + // then then find the group 'current' is waiting in + GroupList::iterator i = std::find_if(_list.begin(), _list.end(), by_id(n)); + if(i != _list.end()) { + + // Remove 'current' from that list if it is still a member + ThreadList::iterator j = std::find(i->waiters.begin(), i->waiters.end(), current); + if(j != i->waiters.end()) + i->waiters.erase(j); + + } + + // At least one empty-group exists + assert(!_list.empty()); + + switch(state) { + case Monitor::SIGNALED: + break; + case Monitor::TIMEDOUT: + return false; + case Monitor::INTERRUPTED: + throw Interrupted_Exception(); + default: + throw Synchronization_Exception(); + } + + return true; + + } + + /** + * Increment the active group count + * + * @pre at least 1 empty group exists + * @post at least 1 non-empty group exists + */ + std::pair increment() { + + Guard g(_lock); + + // At least one empty-group exists + assert(!_list.empty()); + + GroupList::iterator i = --_list.end(); + size_t n = i->id; + + if(i == _list.end()) { + + // A group should never have been removed until + // the final task in that group completed + assert(0); + + } + + i->count++; + + // When the active group is being incremented, insert a new active group + // to replace it if there were waiting threads + if(i == --_list.end() && !i->waiters.empty()) + _list.push_back(Group(_id++)); + + // At least 1 non-empty group exists + assert((size_t)std::for_each(_list.begin(), _list.end(), counter()) > 0); + + return std::make_pair(n, _generation); + + } + + + /** + * Decrease the count for the group with the given id. + * + * @param n group id + * + * @pre At least 1 non-empty group exists + * @post At least 1 empty group exists + */ + void decrement(size_t n) { + + Guard g1(_lock); + + // At least 1 non-empty group exists + assert((size_t)std::for_each(_list.begin(), _list.end(), counter()) > 0); + + // Find the requested group + GroupList::iterator i = std::find_if(_list.begin(), _list.end(), by_id(n)); + if(i == _list.end()) { + + // A group should never have been removed until + // the final task in that group completed + assert(0); + + } + + // Decrease the count for tasks in this group, + if(--i->count == 0 && i == _list.begin()) { + + do { + + // When the first group completes, wake all waiters for every + // group, starting from the first until a group that is not + // complete is reached + + /* + // Don't remove the empty active group + if(i == --_list.end() && i->waiters.empty()) + break; + */ + + if( awaken(*i) ) { + + // If all waiters were awakened, remove the group + i = _list.erase(i); + + } else { + + { + + // Otherwise, unlock and yield allowing the waiter + // lists to be updated if other threads are busy + Guard g2(g1); + ThreadImpl::yield(); + + } + + i = _list.begin(); + + } + + } while(i != _list.end() && i->count == 0); + + // Ensure that an active group exists + if(_list.empty()) + _list.push_back( Group(++_id) ); + + } + + // At least one group exists + assert(!_list.empty()); + + } + + /** + */ + size_t generation(bool next = false) { + + Guard g(_lock); + return next ? _generation++ : _generation; + + } + + private: + + /** + * Awaken all the waiters remaining in the given group + * + * @return + * - true if all the waiting threads were successfully awakened. + * - false if there were one or more threads that could not be awakened. + */ + bool awaken(Group& grp) { + + // Go through the waiter list in the given group; + for(ThreadList::iterator i = grp.waiters.begin(); i != grp.waiters.end();) { + + ThreadImpl* impl = *i; + Monitor& m = impl->getMonitor(); + + // Try the monitor lock, if it cant be locked skip to the next waiter + if(m.tryAcquire()) { + + // Notify the monitor & remove from the waiter list so time isn't + // wasted checking it again. + i = grp.waiters.erase(i); + + // Try to wake the waiter, it doesn't matter if this is successful + // or not (only fails when the monitor is already going to stop waiting). + m.notify(); + m.release(); + + } else ++i; + + } + + return grp.waiters.empty(); + + } + + }; + + /** + * @class GroupedRunnable + * + * Wrap a task with group and generation information. + * + * - 'group' allows tasks to be grouped together so that lists of waiting + * threads can be managed. + * + * - 'generation' allows tasks to be interrupted + */ + class GroupedRunnable : public Runnable { + + Task _task; + WaiterQueue& _queue; + + size_t _group; + size_t _generation; + + public: + + GroupedRunnable(const Task& task, WaiterQueue& queue) + : _task(task), _queue(queue) { + + std::pair pr( _queue.increment() ); + + _group = pr.first; + _generation = pr.second; + + } + + size_t group() const { + return _group; + } + + size_t generation() const { + return _generation; + } + + void run() { + + try { + + _task->run(); + + } catch(...) { + + } + + _queue.decrement( group() ); + + } + + }; + + typedef CountedPtr ExecutorTask; + + /** + * + */ + class ExecutorImpl { + + typedef MonitoredQueue TaskQueue; + typedef std::deque ThreadList; + + TaskQueue _taskQueue; + WaiterQueue _waitingQueue; + + ThreadList _threads; + volatile size_t _size; + + + public: + + ExecutorImpl() : _size(0) {} + + + void registerThread() { + + Guard g(_taskQueue); + + ThreadImpl* impl = ThreadImpl::current(); + _threads.push_back(impl); + + // current cancel if too many threads are being created + if(_threads.size() > _size) + impl->cancel(); + + } + + void unregisterThread() { + + Guard g(_taskQueue); + std::remove(_threads.begin(), _threads.end(), ThreadImpl::current()); + + } + + void execute(const Task& task) { + + // Wrap the task with a grouped task + GroupedRunnable* runnable = new GroupedRunnable(task, _waitingQueue); + + try { + + _taskQueue.add( ExecutorTask(runnable) ); + + } catch(...) { + + // Incase the queue is canceled between the time the WaiterQueue is + // updated and the task is added to the TaskQueue + _waitingQueue.decrement( runnable->group() ); + throw; + + } + + } + + void interrupt() { + + // Bump the generation number + _waitingQueue.generation(true); + + Guard g(_taskQueue); + + // Interrupt all threads currently running, thier tasks would be + // from an older generation + for(ThreadList::iterator i = _threads.begin(); i != _threads.end(); ++i) + (*i)->interrupt(); + + } + + //! Adjust the number of desired workers and return the number of Threads needed + size_t workers(size_t n) { + + Guard g(_taskQueue); + + size_t m = (_size < n) ? (n - _size) : 0; + _size = n; + + return m; + + } + + size_t workers() { + + Guard g(_taskQueue); + return _size; + + } + + ExecutorTask next() { + + ExecutorTask task; + + // Draw the task from the queue + for(;;) { + + try { + + task = _taskQueue.next(); + break; + + } catch(Interrupted_Exception&) { + + // Ignore interruption here, it can only come from + // another thread interrupt()ing the executor. The + // thread was interrupted in the hopes it was busy + // with a task + + } + + } + + // Interrupt the thread running the tasks when the generation + // does not match the current generation + if( task->generation() != _waitingQueue.generation() ) + ThreadImpl::current()->interrupt(); + + // Otherwise, clear the interrupted status for the thread and + // give it a clean slate to start with + else + ThreadImpl::current()->isInterrupted(); + + return task; + + } + + bool isCanceled() { + return _taskQueue.isCanceled(); + } + + void cancel() { + _taskQueue.cancel(); + } + + bool wait(unsigned long timeout) { + return _waitingQueue.wait(timeout); + } + + }; + + //! Executor job + class Worker : public Runnable { + + CountedPtr< ExecutorImpl > _impl; + + public: + + //! Create a Worker that draws upon the given Queue + Worker(const CountedPtr< ExecutorImpl >& impl) + : _impl(impl) { } + + //! Run until Thread or Queue are canceled + void run() { + + _impl->registerThread(); + + // Run until the Queue is canceled + while(!Thread::canceled()) { + + // Draw tasks from the queue + ExecutorTask task( _impl->next() ); + task->run(); + + } + + _impl->unregisterThread(); + + } + + }; /* Worker */ + + + //! Helper + class Shutdown : public Runnable { + + CountedPtr< ExecutorImpl > _impl; + + public: + + Shutdown(const CountedPtr< ExecutorImpl >& impl) + : _impl(impl) { } + + void run() { + _impl->cancel(); + } + + }; /* Shutdown */ + + } + + PoolExecutor::PoolExecutor(size_t n) + : _impl( new ExecutorImpl() ), _shutdown( new Shutdown(_impl) ) { + + size(n); + + // Request cancelation when main() exits + ThreadQueue::instance()->insertShutdownTask(_shutdown); + + } + + PoolExecutor::~PoolExecutor() { + + try { + + /** + * If the shutdown task for this executor has not already been + * selected to run, then run it locally + */ + if(ThreadQueue::instance()->removeShutdownTask(_shutdown)) + _shutdown->run(); + + } catch(...) { } + + } + + void PoolExecutor::interrupt() { + _impl->interrupt(); + } + + void PoolExecutor::size(size_t n) { + + if(n < 1) + throw InvalidOp_Exception(); + + for(size_t m = _impl->workers(n); m > 0; --m) + Thread t(new Worker(_impl)); + + } + + size_t PoolExecutor::size() { + return _impl->workers(); + } + + + void PoolExecutor::execute(const Task& task) { + + // Enqueue the task, the Queue will reject it with a + // Cancelation_Exception if the Executor has been canceled + _impl->execute(task); + + } + + void PoolExecutor::cancel() { + _impl->cancel(); + } + + bool PoolExecutor::isCanceled() { + return _impl->isCanceled(); + } + + void PoolExecutor::wait() { + _impl->wait(0); + } + + bool PoolExecutor::wait(unsigned long timeout) { + return _impl->wait(timeout == 0 ? 1 : timeout); + } + +} diff --git a/dep/src/zthread/PriorityCondition.cxx b/dep/src/zthread/PriorityCondition.cxx new file mode 100644 index 00000000000..c43953ff73b --- /dev/null +++ b/dep/src/zthread/PriorityCondition.cxx @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#include "zthread/PriorityCondition.h" +#include "ConditionImpl.h" + +namespace ZThread { + + class PriorityConditionImpl : public ConditionImpl { + public: + PriorityConditionImpl(Lockable& l) : ConditionImpl(l) {} + + }; + + PriorityCondition::PriorityCondition(Lockable& lock) { + + _impl = new PriorityConditionImpl(lock); + + } + + + PriorityCondition::~PriorityCondition() { + + if(_impl != 0) + delete _impl; + + } + + + + void PriorityCondition::wait() { + + _impl->wait(); + + } + + + + bool PriorityCondition::wait(unsigned long ms) { + + return _impl->wait(ms); + + } + + + + void PriorityCondition::signal() { + + _impl->signal(); + + } + + + void PriorityCondition::broadcast() { + + _impl->broadcast(); + + } + +} // namespace ZThread + diff --git a/dep/src/zthread/PriorityInheritanceMutex.cxx b/dep/src/zthread/PriorityInheritanceMutex.cxx new file mode 100644 index 00000000000..108e4a74370 --- /dev/null +++ b/dep/src/zthread/PriorityInheritanceMutex.cxx @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#include "zthread/PriorityInheritanceMutex.h" +#include "MutexImpl.h" +#include "ThreadOps.h" + + +namespace ZThread { + + class InheritPriorityBehavior : public NullBehavior { + + ThreadImpl* owner; + Priority p; + + protected: + + // Temporarily raise the effective priority of the owner + inline void waiterArrived(ThreadImpl* impl) { + + Priority q = impl->getPriority(); + if((int)q > (int)p) { + + ThreadOps::setPriority(impl, p); + p = q; + + } + + } + + + // Note the owners priority + inline void ownerAcquired(ThreadImpl* impl) { + + p = impl->getPriority(); + owner = impl; + + } + + // Restore its original priority + inline void ownerReleased(ThreadImpl* impl) { + + if(p > owner->getPriority()) + ThreadOps::setPriority(impl, impl->getPriority()); + + } + + }; + + class PriorityInheritanceMutexImpl : + public MutexImpl { }; + + PriorityInheritanceMutex::PriorityInheritanceMutex() { + + _impl = new PriorityInheritanceMutexImpl(); + + } + + PriorityInheritanceMutex::~PriorityInheritanceMutex() { + + if(_impl != 0) + delete _impl; + + } + + // P + void PriorityInheritanceMutex::acquire() { + + _impl->acquire(); + + } + + + // P + bool PriorityInheritanceMutex::tryAcquire(unsigned long ms) { + + return _impl->tryAcquire(ms); + + } + + // V + void PriorityInheritanceMutex::release() { + + _impl->release(); + + } + + +} // namespace ZThread + diff --git a/dep/src/zthread/PriorityMutex.cxx b/dep/src/zthread/PriorityMutex.cxx new file mode 100644 index 00000000000..c25eaebc46c --- /dev/null +++ b/dep/src/zthread/PriorityMutex.cxx @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#include "zthread/PriorityMutex.h" +#include "MutexImpl.h" +#include "ThreadOps.h" + + +namespace ZThread { + + class PriorityMutexImpl : public MutexImpl { }; + + PriorityMutex::PriorityMutex() { + + _impl = new PriorityMutexImpl(); + + } + + PriorityMutex::~PriorityMutex() { + + if(_impl != 0) + delete _impl; + + } + + // P + void PriorityMutex::acquire() { + + _impl->acquire(); + + } + + + // P + bool PriorityMutex::tryAcquire(unsigned long ms) { + + return _impl->tryAcquire(ms); + + } + + // V + void PriorityMutex::release() { + + _impl->release(); + + } + + +} // namespace ZThread + diff --git a/dep/src/zthread/PrioritySemaphore.cxx b/dep/src/zthread/PrioritySemaphore.cxx new file mode 100644 index 00000000000..15138b5f426 --- /dev/null +++ b/dep/src/zthread/PrioritySemaphore.cxx @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#include "Debug.h" +#include "zthread/PrioritySemaphore.h" +#include "SemaphoreImpl.h" + +namespace ZThread { + + class PrioritySemaphoreImpl : public SemaphoreImpl { + public: + + PrioritySemaphoreImpl(int count, unsigned int maxCount) + : SemaphoreImpl(count, maxCount, true) { } + + }; + + /** + * Create a new semaphore of a given size with a given count + * + * @param initialCount initial count to assign this semaphore + * @param maxCount maximum size of the semaphore count + */ + PrioritySemaphore::PrioritySemaphore(int count, unsigned int maxCount) { + + _impl = new PrioritySemaphoreImpl(count, maxCount); + + } + + PrioritySemaphore::~PrioritySemaphore() { + + if(_impl != 0) + delete _impl; + + } + + void PrioritySemaphore::wait() { + + _impl->acquire(); + + } + + + bool PrioritySemaphore::tryWait(unsigned long ms) { + + return _impl->tryAcquire(ms); + + } + + void PrioritySemaphore::post() { + + _impl->release(); + + } + + int PrioritySemaphore::count() { + + return _impl->count(); + + } + + /////////////////////////////////////////////////////////////////////////////// + // Locakable compatibility + // + + void PrioritySemaphore::acquire() { + + _impl->acquire(); + + } + + bool PrioritySemaphore::tryAcquire(unsigned long ms) { + + return _impl->tryAcquire(ms); + + + } + + void PrioritySemaphore::release() { + + _impl->release(); + + } + +} // namespace ZThread diff --git a/dep/src/zthread/RecursiveMutex.cxx b/dep/src/zthread/RecursiveMutex.cxx new file mode 100644 index 00000000000..57994f55b81 --- /dev/null +++ b/dep/src/zthread/RecursiveMutex.cxx @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#include "zthread/RecursiveMutex.h" +#include "RecursiveMutexImpl.h" + +namespace ZThread { + + RecursiveMutex::RecursiveMutex() { + + _impl = new RecursiveMutexImpl(); + + } + + RecursiveMutex::~RecursiveMutex() { + + if(_impl != (RecursiveMutexImpl*)0 ) + delete _impl; + + } + + + void RecursiveMutex::acquire() { + + _impl->acquire(); + + } + + + bool RecursiveMutex::tryAcquire(unsigned long ms) { + + return _impl->tryAcquire(ms); + + } + + void RecursiveMutex::release() { + + _impl->release(); + + } + +} // namespace ZThread diff --git a/dep/src/zthread/RecursiveMutexImpl.cxx b/dep/src/zthread/RecursiveMutexImpl.cxx new file mode 100644 index 00000000000..41ca03547f8 --- /dev/null +++ b/dep/src/zthread/RecursiveMutexImpl.cxx @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#include "Debug.h" + +#include "RecursiveMutexImpl.h" +#include "ThreadImpl.h" + +#include "zthread/Guard.h" + +#include +#include +#include + +namespace ZThread { + + /** + * Create a new RecursiveMutexImpl + * + * @exception Initialization_Exception thrown if resources could not be + * properly allocated + */ + RecursiveMutexImpl::RecursiveMutexImpl() + : _owner(0), _count(0) { + + } + + /** + * Destroy this RecursiveMutexImpl and release its resources + */ + RecursiveMutexImpl::~RecursiveMutexImpl() { + +#ifndef NDEBUG + + // It is an error to destroy a mutex that has not been released + if(_owner != 0) { + + ZTDEBUG("** You are destroying a mutex which was never released. **\n"); + assert(0); // Destroyed mutex while in use + + } + + if(!_waiters.empty()) { + + ZTDEBUG("** You are destroying a mutex which is blocking %d threads. **\n", _waiters.size()); + assert(0); // Destroyed mutex while in use + + } + +#endif + + } + + + void RecursiveMutexImpl::acquire() { + + // Get the monitor for the current thread + Monitor& m = ThreadImpl::current()->getMonitor(); + Monitor::STATE state; + + Guard g1(_lock); + + // If there is an entry count and the current thread is + // the owner, increment the count and continue. + if(_owner == &m) + _count++; + + else { + + // Acquire the lock if it is free and there are no waiting threads + if(_owner == 0 && _waiters.empty()) { + + assert(_count == 0); + + _owner = &m; + _count++; + + } else { // Otherwise, wait() + + _waiters.push_back(&m); + + m.acquire(); + + { + + Guard g2(g1); + state = m.wait(); + + } + + m.release(); + + // Remove from waiter list, regarless of weather release() is called or + // not. The monitor is sticky, so its possible a state 'stuck' from a + // previous operation and will leave the wait() w/o release() having + // been called. + List::iterator i = std::find(_waiters.begin(), _waiters.end(), &m); + if(i != _waiters.end()) + _waiters.erase(i); + + // If awoke due to a notify(), take ownership. + switch(state) { + case Monitor::SIGNALED: + + assert(_owner == 0); + assert(_count == 0); + + _owner = &m; + _count++; + + break; + + case Monitor::INTERRUPTED: + throw Interrupted_Exception(); + + default: + throw Synchronization_Exception(); + } + + } + + } + + } + + bool RecursiveMutexImpl::tryAcquire(unsigned long timeout) { + + // Get the monitor for the current thread + Monitor& m = ThreadImpl::current()->getMonitor(); + + Guard g1(_lock); + + // If there is an entry count and the current thread is + // the owner, increment the count and continue. + if(_owner == &m) + _count++; + + else { + + // Acquire the lock if it is free and there are no waiting threads + if(_owner == 0 && _waiters.empty()) { + + assert(_count == 0); + + _owner = &m; + _count++; + + } else { // Otherwise, wait() + + _waiters.push_back(&m); + + Monitor::STATE state = Monitor::TIMEDOUT; + + // Don't bother waiting if the timeout is 0 + if(timeout) { + + m.acquire(); + + { + + Guard g2(g1); + state = m.wait(timeout); + + } + + m.release(); + + } + + // Remove from waiter list, regarless of weather release() is called or + // not. The monitor is sticky, so its possible a state 'stuck' from a + // previous operation and will leave the wait() w/o release() having + // been called. + List::iterator i = std::find(_waiters.begin(), _waiters.end(), &m); + if(i != _waiters.end()) + _waiters.erase(i); + + // If awoke due to a notify(), take ownership. + switch(state) { + case Monitor::SIGNALED: + + assert(_count == 0); + assert(_owner == 0); + + _owner = &m; + _count++; + + break; + + case Monitor::INTERRUPTED: + throw Interrupted_Exception(); + + case Monitor::TIMEDOUT: + return false; + + default: + throw Synchronization_Exception(); + } + + } + + } + + return true; + + } + + void RecursiveMutexImpl::release() { + + // Get the monitor for the current thread + Monitor& m = ThreadImpl::current()->getMonitor(); + + Guard g1(_lock); + + // Make sure the operation is valid + if(!(_owner == &m)) + throw InvalidOp_Exception(); + + // Update the count, if it has reached 0, wake another waiter. + if(--_count == 0) { + + _owner = 0; + + // Try to find a waiter with a backoff & retry scheme + for(;;) { + + // Go through the list, attempt to notify() a waiter. + for(List::iterator i = _waiters.begin(); i != _waiters.end();) { + + // Try the monitor lock, if it cant be locked skip to the next waiter + Monitor* n = *i; + if(n->tryAcquire()) { + + // If notify() is not sucessful, it is because the wait() has already + // been ended (killed/interrupted/notify'd) + bool woke = n->notify(); + n->release(); + + // Once notify() succeeds, return + if(woke) + return; + + } else ++i; + + } + + if(_waiters.empty()) + return; + + { // Backoff and try again + + Guard g2(g1); + ThreadImpl::yield(); + + } + + } + + } + + } + +} // namespace ZThread + + + + diff --git a/dep/src/zthread/RecursiveMutexImpl.h b/dep/src/zthread/RecursiveMutexImpl.h new file mode 100644 index 00000000000..9e1ae050c5b --- /dev/null +++ b/dep/src/zthread/RecursiveMutexImpl.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTRECURSIVEMUTEXIMPL_H__ +#define __ZTRECURSIVEMUTEXIMPL_H__ + +#include "zthread/Exceptions.h" + +#include "FastLock.h" + +#include + +namespace ZThread { + + class Monitor; + + /** + * @class RecursiveMutexImpl + * @author Eric Crahen + * @date <2003-07-16T19:58:26-0400> + * @version 2.1.6 + * + * This synchronization object provides serialized access + * through an acquire/release protocol. + */ + class ZTHREAD_API RecursiveMutexImpl { + + typedef std::vector List; + + //! List of Events that are waiting for notification + List _waiters; + + //! Serialize access to this Mutex + FastLock _lock; + + //! Current owning Event object + Monitor* _owner; + + //! Entry count + size_t _count; + + public: + + RecursiveMutexImpl(); + + virtual ~RecursiveMutexImpl(); + + void acquire(); + + bool tryAcquire(unsigned long); + + void release(); + + }; /* RecursiveMutexImpl */ + + +}; + +#endif diff --git a/dep/src/zthread/Scheduling.h b/dep/src/zthread/Scheduling.h new file mode 100644 index 00000000000..b12f7fff0b6 --- /dev/null +++ b/dep/src/zthread/Scheduling.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTSCHEDULING_H__ +#define __ZTSCHEDULING_H__ + +#include "ThreadImpl.h" + +#include +#include +#include +#include + +namespace ZThread { + + /** + * @author Eric Crahen + * @date <2003-07-16T20:01:18-0400> + * @version 2.2.0 + * @class fifo_list + */ + class fifo_list : public std::deque { + public: + + void insert(const value_type& val) { push_back(val); } + + }; + + /** + * @author Eric Crahen + * @date <2003-07-16T20:01:18-0400> + * @version 2.2.0 + * @struct priority_order + */ + struct priority_order : public std::binary_function { + + std::less id; + + bool operator()(const ThreadImpl* t0, const ThreadImpl* t1) const { + + if(t0->getPriority() > t1->getPriority()) + return true; + + else if (t0->getPriority() < t1->getPriority()) + return false; + + return id(t0, t1); + + } + + }; + + + /** + * @author Eric Crahen + * @date <2003-07-16T20:01:18-0400> + * @version 2.2.0 + * @class priority_list + */ + class priority_list : public std::deque { + + priority_order comp; + + public: + + void insert(const value_type& val) { + + push_back(val); + std::sort(begin(), end(), comp); + + } + + }; + +} // namespace ZThread + +#endif // __ZTSCHEDULING_H__ diff --git a/dep/src/zthread/Semaphore.cxx b/dep/src/zthread/Semaphore.cxx new file mode 100644 index 00000000000..b9fb8d0f613 --- /dev/null +++ b/dep/src/zthread/Semaphore.cxx @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#include "zthread/Semaphore.h" +#include "SemaphoreImpl.h" + +namespace ZThread { + + /** + * Create a new semaphore of a given size with a given count + * + * @param initialCount initial count to assign this semaphore + * @param maxCount maximum size of the semaphore count + */ + Semaphore::Semaphore(int count, unsigned int maxCount) { + + _impl = new FifoSemaphoreImpl(count, maxCount, true); + + } + + Semaphore::~Semaphore() { + + if(_impl != 0) + delete _impl; + + } + + void Semaphore::wait() { + + _impl->acquire(); + + } + + + bool Semaphore::tryWait(unsigned long ms) { + + return _impl->tryAcquire(ms); + + } + + void Semaphore::post() { + + _impl->release(); + + } + + int Semaphore::count() { + + return _impl->count(); + + } + + /////////////////////////////////////////////////////////////////////////////// + // Locakable compatibility + // + + void Semaphore::acquire() { + + _impl->acquire(); + + } + + bool Semaphore::tryAcquire(unsigned long ms) { + + return _impl->tryAcquire(ms); + + + } + + void Semaphore::release() { + + _impl->release(); + + } + +} // namespace ZThread + + + + + + diff --git a/dep/src/zthread/SemaphoreImpl.h b/dep/src/zthread/SemaphoreImpl.h new file mode 100644 index 00000000000..086c4333fd0 --- /dev/null +++ b/dep/src/zthread/SemaphoreImpl.h @@ -0,0 +1,348 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTSEMAPHOREIMPL_H__ +#define __ZTSEMAPHOREIMPL_H__ + +#include "zthread/Guard.h" + +#include "Debug.h" +#include "FastLock.h" +#include "Scheduling.h" + +#include + +namespace ZThread { + + class Monitor; + + /** + * @class SemaphoreImpl + * @author Eric Crahen + * @date <2003-07-16T20:03:20-0400> + * @version 2.2.11 + * + * The SemaphoreImpl template allows how waiter lists are sorted + * to be parameteized + */ + template + class SemaphoreImpl { + + //! List of waiting events + List _waiters; + + //! Serialize access to this object + FastLock _lock; + + //! Current count + volatile int _count; + + //! Maximum count if any + volatile int _maxCount; + + //! Flag for bounded or unbounded count + volatile bool _checked; + + //! Entry count + volatile int _entryCount; + + public: + + + /** + * Create a new SemaphoreImpl. Initialzes one pthreads mutex for + * internal use. + * + * @exception Initialization_Exception thrown if resources could not be + * properly allocated + */ + SemaphoreImpl(int count, unsigned int maxCount, bool checked) + : _count(count), _maxCount(maxCount), _checked(checked), _entryCount(0) { } + + + ~SemaphoreImpl(); + + void acquire(); + + void release(); + + bool tryAcquire(unsigned long timeout); + + int count(); + + }; + + + /** + * Destroy this SemaphoreImpl and release its resources. + */ + template + SemaphoreImpl::~SemaphoreImpl() { + +#ifndef NDEBUG + + if(!_waiters.empty()) { + + ZTDEBUG("** You are destroying a semaphore which is blocking %d threads. **\n", _waiters.size()); + assert(0); // Destroyed semaphore while in use + + } + +#endif + + } + + + /** + * Get the count for the Semaphore + * + * @return int + */ + template + int SemaphoreImpl::count() { + + Guard g(_lock); + return _count; + + } + + /** + * Decrement the count, blocking when that count becomes 0 or less. + * + * @exception Interrupted_Exception thrown when the caller status is interrupted + * @exception Synchronization_Exception thrown if there is some other error. + */ + template + void SemaphoreImpl::acquire() { + + // Get the monitor for the current thread + ThreadImpl* self = ThreadImpl::current(); + Monitor& m = self->getMonitor(); + + Monitor::STATE state; + + Guard g1(_lock); + + // Update the count without waiting if possible. + if(_count > 0 && _entryCount == 0) + _count--; + + // Otherwise, wait() for the lock by placing the waiter in the list + else { + + ++_entryCount; + _waiters.insert(self); + + m.acquire(); + + { + + Guard g2(g1); + state = m.wait(); + + } + + m.release(); + + // Remove from waiter list, regarless of weather release() is called or + // not. The monitor is sticky, so its possible a state 'stuck' from a + // previous operation and will leave the wait() w/o release() having + // been called. + typename List::iterator i = std::find(_waiters.begin(), _waiters.end(), self); + if(i != _waiters.end()) + _waiters.erase(i); + + --_entryCount; + + switch(state) { + // If awoke due to a notify(), update the count + case Monitor::SIGNALED: + + _count--; + break; + + case Monitor::INTERRUPTED: + throw Interrupted_Exception(); + + default: + throw Synchronization_Exception(); + } + + } + + } + + /** + * Decrement the count, blocking when it that count is 0 or less. If the timeout + * expires before the count is raise above 0, the thread will stop blocking + * and return. + * + * @exception Interrupted_Exception thrown when the caller status is interrupted + * @exception Synchronization_Exception thrown if there is some other error. + */ + template + bool SemaphoreImpl::tryAcquire(unsigned long timeout) { + + // Get the monitor for the current thread + ThreadImpl* self = ThreadImpl::current(); + Monitor& m = self->getMonitor(); + + Guard g1(_lock); + + // Update the count without waiting if possible. + if(_count > 0 && _entryCount == 0) + _count--; + + // Otherwise, wait() for the lock by placing the waiter in the list + else { + + ++_entryCount; + _waiters.push_back(self); + + Monitor::STATE state = Monitor::TIMEDOUT; + + // Don't bother waiting if the timeout is 0 + if(timeout) { + + m.acquire(); + + { + + Guard g2(g1); + state = m.wait(timeout); + + } + + m.release(); + + } + + // Remove from waiter list, regarless of weather release() is called or + // not. The monitor is sticky, so its possible a state 'stuck' from a + // previous operation and will leave the wait() w/o release() having + // been called. + typename List::iterator i = std::find(_waiters.begin(), _waiters.end(), self); + if(i != _waiters.end()) + _waiters.erase(i); + + --_entryCount; + + switch(state) { + // If awoke due to a notify(), update the count + case Monitor::SIGNALED: + + _count--; + break; + + case Monitor::INTERRUPTED: + throw Interrupted_Exception(); + + case Monitor::TIMEDOUT: + return false; + + default: + throw Synchronization_Exception(); + } + + } + + return true; + + } + + /** + * Increment the count and release a waiter if there are any. If the semaphore + * is checked, then an exception will be raised if the maximum count is about to + * be exceeded. + * + * @exception InvalidOp_Exception thrown if the maximum count is exceeded while + * the checked flag is set. + */ + template + void SemaphoreImpl::release() { + + Guard g1(_lock); + + // Make sure the operation is valid + if(_checked && _count == _maxCount) + throw InvalidOp_Exception(); + + // Increment the count + _count++; + + // Try to find a waiter with a backoff & retry scheme + for(;;) { + + // Go through the list, attempt to notify() a waiter. + for(typename List::iterator i = _waiters.begin(); i != _waiters.end();) { + + // Try the monitor lock, if it cant be locked skip to the next waiter + ThreadImpl* impl = *i; + Monitor& m = impl->getMonitor(); + + if(m.tryAcquire()) { + + // Notify the monitor & remove from the waiter list so time isn't + // wasted checking it again. + i = _waiters.erase(i); + + // If notify() is not sucessful, it is because the wait() has already + // been ended (killed/interrupted/notify'd) + bool woke = m.notify(); + + m.release(); + + // Once notify() succeeds, return + if(woke) + return; + + } else ++i; + + } + + if(_waiters.empty()) + return; + + { // Backoff and try again + + Guard g2(g1); + ThreadImpl::yield(); + + } + + } + + } + + class FifoSemaphoreImpl : public SemaphoreImpl { + public: + + FifoSemaphoreImpl(int count, unsigned int maxCount, bool checked) + /* throw(Synchronization_Exception) */ + : SemaphoreImpl(count, maxCount, checked) { } + + }; + + +} // namespace ZThread + +#endif // __ZTSEMAPHOREIMPL_H__ diff --git a/dep/src/zthread/State.h b/dep/src/zthread/State.h new file mode 100644 index 00000000000..85279f4bde8 --- /dev/null +++ b/dep/src/zthread/State.h @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTSTATE_H__ +#define __ZTSTATE_H__ + +namespace ZThread { + +/** + * @class State + * @author Eric Crahen + * @date <2003-07-16T20:04:01-0400> + * @version 2.2.1 + * + * Class to encapsulate the current state of the threads life-cycle. + */ +class State { + public: + + //! Various states + typedef enum { REFERENCE, IDLE, RUNNING, JOINED } STATE; + + /** + * Create State with the given flag set. + */ + State(STATE initialState) : _state(initialState) {} + + /** + * Test for the IDLE state. No task has yet run. + */ + bool isIdle() const { + return _state == IDLE; + } + + /** + * Test for the JOINED state. A task has completed and + * the thread is join()ed. + * + * @return bool + */ + bool isJoined() const { + return _state == JOINED; + } + + /** + * Test for the RUNNING state. A task is in progress. + * + * @return bool + */ + bool isRunning() const { + return _state == RUNNING; + } + + /** + * Test for the REFERENCE state. A task is in progress but not + * under control of this library. + * + * @return bool + */ + bool isReference() const { + return _state == REFERENCE; + } + + /** + * Transition to the IDLE state. + * + * @return bool true if successful + */ + bool setIdle() { + + if(_state != RUNNING) + return false; + + _state = IDLE; + return true; + + } + + /** + * Transition to the RUNNING state. + * + * @return bool true if successful + */ + bool setRunning() { + + if(_state != IDLE) + return false; + + _state = RUNNING; + return true; + + } + + /** + * Transition to the REFERENCE state. + * + * @return bool true if successful + */ + bool setReference() { + + if(_state != IDLE) + return false; + + _state = REFERENCE; + return true; + + } + + + /** + * Transition to the JOINED state. + * + * @return bool true if successful + */ + bool setJoined() { + + _state = JOINED; + return true; + + } + + private: + + //! Current state + STATE _state; + +}; + + +}; + +#endif diff --git a/dep/src/zthread/Status.h b/dep/src/zthread/Status.h new file mode 100644 index 00000000000..4735e352861 --- /dev/null +++ b/dep/src/zthread/Status.h @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTBLOCKINGSTATE_H__ +#define __ZTBLOCKINGSTATE_H__ + +#include + +namespace ZThread { + + /** + * @class Status + * @version 2.3.0 + * + * A Status is associated with each Thread's Monitor. Monitors rely on a + * Status object for providing information that will affect a blocking operations. + */ + class Status { + public: + //! Aggregate of pending status changes + volatile unsigned short _pending; + + //! Interest mask + volatile unsigned short _mask; + + public: + + //! State for the monitor + typedef enum { + + // Default + INVALID = 0x00, + + // Valid states + SIGNALED = 0x01, + INTERRUPTED = 0x02, + TIMEDOUT = 0x04, + CANCELED = 0x08, + + // Mask + ANYTHING = (~INVALID & ~CANCELED) + + } STATE; + + Status() : _pending((unsigned short)INVALID), _mask((unsigned short)ANYTHING) { } + + /** + * Set the mask for the STATE's that next() will report. + * STATE's not covered by the interest mask can still be + * set, they just aren't reported until the mask is changed + * to cover that STATE. + * + * @param STATE + * @pre accessed ONLY by the owning thread. + */ + void interest(STATE mask) { + _mask = static_cast(mask); + } + + bool masked(STATE mask) { + return (_mask & static_cast(mask)) == 0; + } + + /** + * Return true if next() will return a STATE covered + * by the current interest mask and by the mask given + * to this function. + * + * @param unsigned short + * @pre accessed ONLY by the owning thread. + */ + bool pending(unsigned short mask) { + + assert(mask != INVALID); + return ((_pending & _mask) & mask) != INVALID; + + } + + /** + * Check the state without the interest mask. + * + * @param state + * @return true if the flag is set + * @pre access must be serial + */ + bool examine(STATE state) { + return (_pending & static_cast(state)) != INVALID; + } + + /** + * Add the flags to the current state. + * + * @param interest - the flags to add to the current state. + * @pre access must be serial + */ + void push(STATE interest) { + _pending |= interest; + } + + /** + * Clear the flags from the current state + * + * @param interest - the flags to clear from the current state. + * @pre access must be serial + */ + void clear(STATE interest) { + + assert(interest != INVALID); + assert(interest != ANYTHING); + assert(interest != CANCELED); + + _pending &= ~interest; + + } + + /** + * Get the next state from set that has accumulated. The order STATES are + * reported in is SIGNALED, TIMEOUT, or INTERRUPTED. Setting the + * intrest mask allows certain state to be selectively ignored for + * a time - but not lost. The states will become visible again as soon + * as the interest mask is changed appropriately. The interest mask is + * generally used to create uninterruptable waits (waiting for threads + * to start, reacquiring a conditions predicate lock, etc) + * + * @return STATE + * @pre access must be serial + */ + STATE next() { + + STATE state = INVALID; + + if(((_pending & _mask) & SIGNALED) != 0) { + + // Absorb the timeout if it happens when a signal + // is available at the same time + _pending &= ~(SIGNALED|TIMEDOUT); + state = SIGNALED; + + } else if(((_pending & _mask) & TIMEDOUT) != 0) { + + _pending &= ~TIMEDOUT; + state = TIMEDOUT; + + } else if(((_pending & _mask) & INTERRUPTED) != 0) { + + _pending &= ~INTERRUPTED; + state = INTERRUPTED; + + } + + assert(state != INVALID); + return state; + + } + + }; + +}; // namespace ZThread + +#endif diff --git a/dep/src/zthread/SynchronousExecutor.cxx b/dep/src/zthread/SynchronousExecutor.cxx new file mode 100644 index 00000000000..0dc75b5f676 --- /dev/null +++ b/dep/src/zthread/SynchronousExecutor.cxx @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#include "zthread/SynchronousExecutor.h" + +namespace ZThread { + + SynchronousExecutor::SynchronousExecutor() + : _canceled(false) {} + + SynchronousExecutor::~SynchronousExecutor() { + } + + void SynchronousExecutor::cancel() { + + Guard g(_lock); + _canceled = true; + + } + + bool SynchronousExecutor::isCanceled() { + + Guard g(_lock); + return _canceled; + + } + + void SynchronousExecutor::interrupt() { + } + + void SynchronousExecutor::execute(const Task& task) { + + // Canceled Executors will not accept new tasks, quick + // check to avoid excessive locking in the canceled state + if(_canceled) + throw Cancellation_Exception(); + + Guard g(_lock); + + if(_canceled) // Double check + throw Cancellation_Exception(); + + // Run the task. + Task(task)->run(); + + } + + void SynchronousExecutor::wait() { + + if(Thread::interrupted()) + throw Interrupted_Exception(); + + Guard g(_lock); + + } + + /** + * @see Executor::wait(unsigned long) + */ + bool SynchronousExecutor::wait(unsigned long) { + + if(Thread::interrupted()) + throw Interrupted_Exception(); + + Guard g(_lock); + return true; + + } + + +} diff --git a/dep/src/zthread/TSS.h b/dep/src/zthread/TSS.h new file mode 100644 index 00000000000..ed29230ec57 --- /dev/null +++ b/dep/src/zthread/TSS.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTTSSSELECT_H__ +#define __ZTTSSSELECT_H__ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +// Select the correct TSS implementation based on +// what the compilation environment has defined + +#if defined(ZT_POSIX) + +#include "posix/TSS.h" + +#elif defined(ZT_WIN32) || defined(ZT_WIN9X) + +#include "win32/TSS.h" + +#elif defined(ZT_MACOS) + +#include "macos/TSS.h" + +#endif + + +#ifndef __ZTTSS_H__ +#error "No TSS implementation could be selected" +#endif + +#endif // __ZTTSSSELECT_H__ diff --git a/dep/src/zthread/Thread.cxx b/dep/src/zthread/Thread.cxx new file mode 100644 index 00000000000..25cde79969c --- /dev/null +++ b/dep/src/zthread/Thread.cxx @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#include "zthread/Runnable.h" +#include "zthread/Thread.h" +#include "ThreadImpl.h" + +namespace ZThread { + + + Thread::Thread() + : _impl( ThreadImpl::current() ) { + + // ThreadImpl's start out life with a reference count + // of one, and the they are added to the ThreadQueue. + _impl->addReference(); + + } + + Thread::Thread(const Task& task, bool autoCancel) + : _impl( new ThreadImpl(task, autoCancel) ) { + + _impl->addReference(); + + } + + bool Thread::operator==(const Thread& t) const { + return (t._impl == _impl); + } + + Thread::~Thread() { + + _impl->delReference(); + + } + + void Thread::wait() { + _impl->join(0); + } + + bool Thread::wait(unsigned long timeout) { + + return _impl->join(timeout == 0 ? 1 : timeout); + + } + + bool Thread::interrupted() { + + return ThreadImpl::current()->isInterrupted(); + + } + + + bool Thread::canceled() { + + return ThreadImpl::current()->isCanceled(); + + } + + void Thread::setPriority(Priority n) { + + _impl->setPriority(n); + + } + + + Priority Thread::getPriority() { + + return _impl->getPriority(); + + } + + bool Thread::interrupt() { + + return _impl->interrupt(); + + } + + void Thread::cancel() { + + if(ThreadImpl::current() == _impl) + throw InvalidOp_Exception(); + + _impl->cancel(); + + } + + bool Thread::isCanceled() { + + return _impl->isCanceled(); + + } + + + void Thread::sleep(unsigned long ms) { + + ThreadImpl::sleep(ms); + + } + + + void Thread::yield() { + + ThreadImpl::yield(); + + } + +} // namespace ZThread diff --git a/dep/src/zthread/ThreadImpl.cxx b/dep/src/zthread/ThreadImpl.cxx new file mode 100644 index 00000000000..c7c22883b5e --- /dev/null +++ b/dep/src/zthread/ThreadImpl.cxx @@ -0,0 +1,470 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#include "Debug.h" + +#include "zthread/Runnable.h" +#include "ThreadImpl.h" +#include "ThreadQueue.h" +#include "DeferredInterruptionScope.h" + +#include + +namespace ZThread { + + TSS ThreadImpl::_threadMap; + + namespace { + + class Launcher : public Runnable { + + ThreadImpl* x; + ThreadImpl* y; + Task z; + + public: + + Launcher(ThreadImpl* a, ThreadImpl* b, const Task& c) : x(a), y(b), z(c) {} + + void run() { + y->dispatch(x,y,z); + } + + }; + + } + + ThreadImpl::ThreadImpl() + : _state(State::REFERENCE), _priority(Medium), _autoCancel(false) { + + ZTDEBUG("Reference thread created.\n"); + + } + + ThreadImpl::ThreadImpl(const Task& task, bool autoCancel) + : _state(State::IDLE), _priority(Medium), _autoCancel(autoCancel) { + + ZTDEBUG("User thread created.\n"); + + start(task); + + } + + + ThreadImpl::~ThreadImpl() { + + _tls.clear(); + + if(isActive()) { + + ZTDEBUG("You are destroying an executing thread!\n"); + abort(); + + } + + ZTDEBUG("Thread destroyed.\n"); + + } + + Monitor& ThreadImpl::getMonitor() { + return _monitor; + } + + void ThreadImpl::cancel(bool autoCancel) { + if(!autoCancel || _autoCancel) + _monitor.cancel(); + } + + bool ThreadImpl::interrupt() { + return _monitor.interrupt(); + } + + bool ThreadImpl::isInterrupted() { + return _monitor.isInterrupted(); + } + + bool ThreadImpl::isCanceled() { + return _monitor.isCanceled(); + } + + Priority ThreadImpl::getPriority() const { + return _priority; + } + + + + bool ThreadImpl::isReference() { + return _state.isReference(); + } + + /** + * Join the thread, blocking the caller until it is interrupted or until + * the thread represented by this object exits. + * + * Reference threads are not under the control of ZThreads and cannot be + * joined. + */ + bool ThreadImpl::join(unsigned long timeout) { + + // Serial access to this ThreadImpl's state + Guard g1(_monitor); + + // Make sure a thread is not trying to join() itself. + if(ThreadOps::isCurrent(this)) + throw Deadlock_Exception("Cannot join self."); + + // Reference threads can't be joined. + if(_state.isReference()) + throw InvalidOp_Exception("Can not join this thread."); + + /* + + TODO: Insert cyclic join check. + + */ + + // If the task has not completed yet, wait for completion + if(!_state.isJoined()) { + + // Add the current thread to the joiner list + ThreadImpl* impl = current(); + _joiners.push_back(impl); + + Monitor::STATE result; + + { // Release this ThreadImpl's lock while the joiner sleeps + + _monitor.release(); + Guard g3(impl->getMonitor()); + + result = impl->_monitor.wait(timeout); + + _monitor.acquire(); + + } + + // Update the joiner list + List::iterator i = std::find(_joiners.begin(), _joiners.end(), impl); + if(i != _joiners.end()) + _joiners.erase(i); + + + switch(result) { + + case Monitor::TIMEDOUT: + return false; + + case Monitor::INTERRUPTED: + throw Interrupted_Exception(); + + default: + break; + + } + + } + + return true; + + } + + + /** + * Translate the priority into a pthread value, and update the thread priority. + * + * This is not available on all platforms, and probably works differently + * the platforms that do support it. Pthreads does not have very portable + * priority support as far I am aware. + * + * If SCHED_OTHER is not supported priority values are still set but + * dont not actually in affect anything. + * + * @param prio PRIORITY value + * + * @exception Killed_Exception thrown by KILLED threads. + * @exception InvalidOp_Exception thrown by IDLE, JOINING or JOINED threads. + */ + void ThreadImpl::setPriority(Priority p) { + + Guard g(_monitor); + + // Only set the native priority when the thread is running + if(_state.isRunning()) + ThreadOps::setPriority(this, p); + + _priority = p; + + } + + + /** + * Test the state Monitor of this thread to determine if the thread + * is an active thread created by zthreads. + * + * @return bool indicating the activity of the thread. + */ + bool ThreadImpl::isActive() { + + Guard g(_monitor); + return _state.isRunning(); + + } + + + /** + * Get a reference to an implmenetation that maps to the current thread. + * Accomplished by checking the TLS map. This will always return a valid + * ThreadImpl instance. + * + * @return ThreadImpl* current implementation that maps to the + * executing thread. + */ + ThreadImpl* ThreadImpl::current() { + + // Get the ThreadImpl previously mapped onto the executing thread. + ThreadImpl* impl = _threadMap.get(); + + // Create a reference thread for any threads that have been 'discovered' + // because they are not created by ZThreads. + if(impl == 0) { + + // Create a ThreadImpl to represent this thread. + impl = new ThreadImpl(); + impl->_state.setReference(); + + ThreadOps::activate(impl); + + // Map a reference thread and insert it into the queue + _threadMap.set(impl); + + ThreadQueue::instance()->insertReferenceThread(impl); + + } + + assert(impl != 0); + return impl; + + } + + /** + * Make current thread sleep for the given number of milliseconds. + * This sleep can be interrupt()ed. + * + * @param ms timeout for the sleep. + * + * @post the calling thread is blocked by waiting on the internal condition + * variable. This can be signaled in the monitor of an interrupt + */ + void ThreadImpl::sleep(unsigned long ms) { + + // Make sleep()ing for 0 milliseconds equivalent to a yield. + if(ms == 0) { + + yield(); + return; + + } + + // Get the monitor for the current thread + Monitor& monitor = current()->getMonitor(); + + // Acquire that threads Monitor with a Guard + Guard g(monitor); + + for(;;) { + + switch(monitor.wait(ms)) { + + case Monitor::INTERRUPTED: + throw Interrupted_Exception(); + + default: + return; + + } + + } + + } + + + /** + * Yield the current timeslice to another thread. + * If sched_yield() is available it is used. + * Otherwise, the state Monitor for this thread is used to simiulate a + * yield by blocking for 1 millisecond, which should give the + * scheduler a chance to schedule another thread. + */ + void ThreadImpl::yield() { + + // Try to yield with the native operation. If it fails, then + // simulate with a short wait() on the monitor. + if(!ThreadOps::yield()) { + + // Get the monitor for the current thread + Monitor& monitor = current()->getMonitor(); + + // Attempt a wait(). + Guard g(monitor); + monitor.wait(1); + + } + + } + + void ThreadImpl::start(const Task& task) { + + Guard g1(_monitor); + + // A Thread must be idle in order to be eligable to run a task. + if(!_state.isIdle()) + throw InvalidOp_Exception("Thread is not idle."); + + _state.setRunning(); + + // Spawn a new thread, blocking the parent (current) thread until + // the child starts. + + ThreadImpl* parent = current(); + Launcher launch(parent, this, task); + + // Attempt to start the child thread + Guard g2(parent->_monitor); + + if(!spawn(&launch)) { + + // Return to the idle state & report the error if it doesn't work out. + _state.setIdle(); + throw Synchronization_Exception(); + + + } + + // Wait, uninterruptably, for the child's signal. The parent thread + // still can be interrupted and killed; it just won't take effect + // until the child has started. + + Guard g3(parent->_monitor); + + if(parent->_monitor.wait() != Monitor::SIGNALED) { + assert(0); + } + + + } + + + void ThreadImpl::dispatch(ThreadImpl* parent, ThreadImpl* impl, Task task) { + + // Map the implementation object onto the running thread. + _threadMap.set(impl); + + // Update the reference count on a ThreadImpl before the 'Thread' + // that owns it can go out of scope (by signaling the parent) + impl->addReference(); + + // Update the priority of the thread + if(parent->_state.isReference()) + ThreadOps::setPriority(impl, + parent->_state.isReference() ? impl->_priority : parent->_priority); + + // Inherit ThreadLocal values from the parent + typedef ThreadLocalMap::const_iterator It; + + for(It i = parent->getThreadLocalMap().begin(); i != parent->getThreadLocalMap().end(); ++i) + if( (i->second)->isInheritable() ) + impl->getThreadLocalMap()[ i->first ] = (i->second)->clone(); + + // Insert a user-thread mapping + ThreadQueue::instance()->insertUserThread(impl); + // Wake the parent once the thread is setup + parent->_monitor.notify(); + + ZTDEBUG("Thread starting...\n"); + + // not catch exceptions, let program terminate + //try { + + task->run(); + + //} catch(...) { + + // Result of running a task that threw an exception. + // ZTDEBUG("The task has thrown an unhandled exception\n"); + //assert(0); // UQ1: Go to debugger... + + //} + + ZTDEBUG("Thread joining...\n"); + + { // Update the state of the thread + + Guard g(impl->_monitor); + impl->_state.setJoined(); + + // Wake the joiners that will be easy to join first + for(List::iterator i = impl->_joiners.begin(); i != impl->_joiners.end();) { + + ThreadImpl* joiner = *i; + Monitor& m = joiner->getMonitor(); + + if(m.tryAcquire()) { + + m.notify(); + m.release(); + + i = impl->_joiners.erase(i); + + } else + ++i; + + } + + // Wake the joiners that might take a while next + for(List::iterator i = impl->_joiners.begin(); i != impl->_joiners.end(); ++i) { + + ThreadImpl* joiner = *i; + Monitor& m = joiner->getMonitor(); + + m.acquire(); + m.notify(); + m.release(); + + } + + } + + ZTDEBUG("Thread exiting...\n"); + + // Insert a pending-thread mapping, allowing the resources to be reclaimed + ThreadQueue::instance()->insertPendingThread(impl); + + // Cleanup ThreadLocal values + impl->getThreadLocalMap().clear(); + + // Update the reference count allowing it to be destroyed + impl->delReference(); + + } + + +} // namespace ZThread diff --git a/dep/src/zthread/ThreadImpl.h b/dep/src/zthread/ThreadImpl.h new file mode 100644 index 00000000000..ae2c8f23960 --- /dev/null +++ b/dep/src/zthread/ThreadImpl.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTTHREADIMPL_H__ +#define __ZTTHREADIMPL_H__ + +#include "zthread/ThreadLocalImpl.h" +#include "zthread/Thread.h" +#include "zthread/Exceptions.h" +#include "IntrusivePtr.h" + +#include "Monitor.h" +#include "TSS.h" +#include "ThreadOps.h" +#include "State.h" + +#include +#include + +namespace ZThread { + +/** + * @class ThreadImpl + * @author Eric Crahen + * @date <2003-07-27T13:39:03-0400> + * @version 2.3.0 + */ +class ThreadImpl : public IntrusivePtr, public ThreadOps { + + typedef std::deque List; + + //! TSS to store implementation to current thread mapping. + static TSS _threadMap; + + //! The Monitor for controlling this thread + Monitor _monitor; + + //! Current state for the thread + State _state; + + //! Joining threads + List _joiners; + + public: + + typedef std::map ThreadLocalMap; + + private: + + ThreadLocalMap _tls; + + //! Cached thread priority + Priority _priority; + + //! Request cancel() when main() goes out of scope + bool _autoCancel; + + void start(const Task& task); + + public: + + ThreadImpl(); + + ThreadImpl(const Task&, bool); + + ~ThreadImpl(); + + Monitor& getMonitor(); + + void cancel(bool autoCancel = false); + + bool interrupt(); + + bool isInterrupted(); + + bool isCanceled(); + + Priority getPriority() const; + + // ThreadLocalMap& getThreadLocalMap(); + ThreadLocalMap& getThreadLocalMap() { return _tls; } + + bool join(unsigned long); + + void setPriority(Priority); + + bool isActive(); + + bool isReference(); + + static void sleep(unsigned long); + + static void yield(); + + static ThreadImpl* current(); + + static void dispatch(ThreadImpl*, ThreadImpl*, Task); + +}; + +} // namespace ZThread + +#endif // __ZTTHREADIMPL_H__ diff --git a/dep/src/zthread/ThreadLocalImpl.cxx b/dep/src/zthread/ThreadLocalImpl.cxx new file mode 100644 index 00000000000..25682e66325 --- /dev/null +++ b/dep/src/zthread/ThreadLocalImpl.cxx @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#include "zthread/ThreadLocalImpl.h" +#include "ThreadImpl.h" + +namespace ZThread { + + ThreadLocalImpl::ThreadLocalImpl() {} + + ThreadLocalImpl::~ThreadLocalImpl() {} + + void ThreadLocalImpl::clearAll() { + + typedef ThreadImpl::ThreadLocalMap Map; + Map& m = ThreadImpl::current()->getThreadLocalMap(); + + m.clear(); + + } + + void ThreadLocalImpl::clear() const { + + typedef ThreadImpl::ThreadLocalMap Map; + Map& m = ThreadImpl::current()->getThreadLocalMap(); + + Map::iterator i = m.find(this); + if(i != m.end()) + m.erase(i); + + } + + ThreadLocalImpl::ValuePtr ThreadLocalImpl::value( ValuePtr(*pfn)() ) const { + + typedef ThreadImpl::ThreadLocalMap Map; + Map& m = ThreadImpl::current()->getThreadLocalMap(); + + Map::iterator i = m.find(this); + if(i != m.end()) + return i->second; + + m[ this ] = ValuePtr( pfn() ); + return m[ this ]; + + } + +} // namespace ZThread diff --git a/dep/src/zthread/ThreadOps.cxx b/dep/src/zthread/ThreadOps.cxx new file mode 100644 index 00000000000..53a3e4457bc --- /dev/null +++ b/dep/src/zthread/ThreadOps.cxx @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTTHREADOPSIMPLSELECT_CXX__ +#define __ZTTHREADOPSIMPLSELECT_CXX__ + +#include "ThreadOps.h" + +// This file will select an implementation for a ThreadOps based on +// what ThreadOps.h selects. This method is for selecting the +// source files, to improve portability. Currently, the project is +// based on the autoconf tool-set, which doesn't support conditional +// compilation well. Additionally, this should make the library +// easier to port since its working around conditional compilation +// by using C++ features and people won't have to fiddle around with +// their make tool as much to compile the source + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +// Check for sched_yield() + +#if !defined(HAVE_SCHED_YIELD) +# if defined(HAVE_UNISTD_H) +# include +# if defined(_POSIX_PRIORITY_SCHEDULING) +# define HAVE_SCHED_YIELD 1 +# endif +# endif +#endif + +#include ZT_THREADOPS_IMPLEMENTATION + +#endif diff --git a/dep/src/zthread/ThreadOps.h b/dep/src/zthread/ThreadOps.h new file mode 100644 index 00000000000..eef9f3c6e31 --- /dev/null +++ b/dep/src/zthread/ThreadOps.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTTHREADOPSSELECT_H__ +#define __ZTTHREADOPSSELECT_H__ + +#include "zthread/Config.h" + +#if defined(ZT_THREADOPS_IMPLEMENTATION) +# error "Reserved symbol defined" +#endif + + +// Select the correct implementation +#if defined(ZT_POSIX) + +# include "posix/ThreadOps.h" +# define ZT_THREADOPS_IMPLEMENTATION "posix/ThreadOps.cxx" + +#elif defined(ZT_WIN32) || defined(ZT_WIN9X) + +// Visual C provides the _beginthreadex function, other compilers +// might not have this if they don't use Microsoft's C runtime. +// _beginthreadex is similar to in effect defining REENTRANT on a +// POSIX system. CreateThreadEx doesn't use reentrant parts of the +// Microsfot C runtime, but if your not using that runtime, no problem. + +# if !defined(HAVE_BEGINTHREADEX) +# if defined(_MSC_VER) +# define HAVE_BEGINTHREADEX +# endif +# endif + +# include "win32/ThreadOps.h" +# define ZT_THREADOPS_IMPLEMENTATION "win32/ThreadOps.cxx" + +#elif defined(ZT_MACOS) + +# include "macos/ThreadOps.h" +# define ZT_THREADOPS_IMPLEMENTATION "macos/ThreadOps.cxx" + +#endif + +#ifndef __ZTTHREADOPS_H__ +#error "No ThreadOps implementation could be selected" +#endif + +#endif // __ZTTHREADOPSSELECT_H__ diff --git a/dep/src/zthread/ThreadQueue.cxx b/dep/src/zthread/ThreadQueue.cxx new file mode 100644 index 00000000000..02349504641 --- /dev/null +++ b/dep/src/zthread/ThreadQueue.cxx @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#include "DeferredInterruptionScope.h" +#include "Debug.h" +#include "ThreadImpl.h" +#include "ThreadQueue.h" + +#include +#include + +namespace ZThread { + + ThreadQueue::ThreadQueue() + : _waiter(0) { + + ZTDEBUG("ThreadQueue created\n"); + + } + + ThreadQueue::~ThreadQueue() { + + ZTDEBUG("ThreadQueue waiting on remaining threads...\n"); + + // Ensure the current thread is mapped. + ThreadImpl* impl = ThreadImpl::current(); + + bool threadsWaiting = false; + bool waitRequired = false; + + { + + TaskList shutdownTasks; + + { // Check the queue to for pending user threads + + Guard g(_lock); + + waitRequired = (_waiter != (ThreadImpl*)1); + _waiter = impl; + + threadsWaiting = !_userThreads.empty() || !_pendingThreads.empty(); + + //ZTDEBUG("Wait required: %d\n", waitRequired); + //ZTDEBUG("Threads waiting: %d\n", threadsWaiting); + + // Auto-cancel any active threads at the time main() goes out of scope + // "force" a gentle exit from the executing tasks; eventually the user- + // threads will transition into pending-threads + pollUserThreads(); + + // Remove all the tasks about to be run from the task list so an indication + // can be given to threads calling removeShutdownTask() too late. + std::remove_copy(_shutdownTasks.begin(), + _shutdownTasks.end(), + std::back_inserter(shutdownTasks), + Task((Runnable*)0)); + + //ZTDEBUG("Threads waiting: %d\n", threadsWaiting); + + } + + // Execute the shutdown tasks + for(TaskList::iterator i = shutdownTasks.begin(); i != shutdownTasks.end(); ++i) { + try { + (*i)->run(); + } catch(...) { } + } + + } + + // Wait for all the users threads to get into the appropriate state + if(threadsWaiting) { + + + Monitor& m = _waiter->getMonitor(); + + // Defer interruption while this thread waits for a signal from + // the last pending user thread + Guard > g(m); + //ZTDEBUG("Threads waiting: %d %d\n", _userThreads.size(), _pendingThreads.size()); + + // Avoid race-condition where the last threads are done with thier tasks, but + // only begin the final part of the clean up phase after this destructor begins + // to run. Takes advantage of the fact that if all remaining threads have transitioned + // into a pending state by the time execution reaches this point, then there is no + // need to wait. + waitRequired = waitRequired && !(_userThreads.empty() && !_pendingThreads.empty()); + + // Reference threads can't be interrupted or otherwise + // manipulated. The only signal this monitor will receive + // at this point will be from the last pending thread. + if(waitRequired && m.wait() != Monitor::SIGNALED) { + assert(0); + } + + // Join those pending threads + pollPendingThreads(); + + } + + // Clean up the reference threads + pollReferenceThreads(); + + ZTDEBUG("ThreadQueue destroyed\n"); + + } + + + void ThreadQueue::insertPendingThread(ThreadImpl* impl) { + ZTDEBUG("insertPendingThread()\n"); + Guard g(_lock); + + // Move from the user-thread list to the pending-thread list + ThreadList::iterator i = std::find(_userThreads.begin(), _userThreads.end(), impl); + if(i != _userThreads.end()) + _userThreads.erase(i); + + _pendingThreads.push_back(impl); + + // Wake the main thread,if its waiting, when the last pending-thread becomes available; + // Otherwise, take note that no wait for pending threads to finish is needed + if(_userThreads.empty()) + if(_waiter && _waiter != (ThreadImpl*)1) + _waiter->getMonitor().notify(); + else + _waiter = (ThreadImpl*)!_waiter; + + ZTDEBUG("1 pending-thread added.\n"); + + } + + void ThreadQueue::insertReferenceThread(ThreadImpl* impl) { + + Guard g(_lock); + _referenceThreads.push_back(impl); + + ZTDEBUG("1 reference-thread added.\n"); + + } + + void ThreadQueue::insertUserThread(ThreadImpl* impl) { + + Guard g(_lock); + _userThreads.push_back(impl); + + // Reclaim pending-threads + pollPendingThreads(); + + // Auto-cancel threads that are started when main() is out of scope + if(_waiter) + impl->cancel(true); + + ZTDEBUG("1 user-thread added.\n"); + + } + + + void ThreadQueue::pollPendingThreads() { + + ZTDEBUG("pollPendingThreads()\n"); + + for(ThreadList::iterator i = _pendingThreads.begin(); i != _pendingThreads.end();) { + + ThreadImpl* impl = (ThreadImpl*)*i; + ThreadOps::join(impl); + + impl->delReference(); + + i = _pendingThreads.erase(i); + + ZTDEBUG("1 pending-thread reclaimed.\n"); + + } + + } + + void ThreadQueue::pollReferenceThreads() { + + ZTDEBUG("pollReferenceThreads()\n"); + + for(ThreadList::iterator i = _referenceThreads.begin(); i != _referenceThreads.end(); ++i) { + + ThreadImpl* impl = (ThreadImpl*)*i; + impl->delReference(); + + ZTDEBUG("1 reference-thread reclaimed.\n"); + + } + + } + + void ThreadQueue::pollUserThreads() { + + ZTDEBUG("pollUserThreads()\n"); + + for(ThreadList::iterator i = _userThreads.begin(); i != _userThreads.end(); ++i) { + + ThreadImpl* impl = *i; + impl->cancel(true); + + ZTDEBUG("1 user-thread reclaimed.\n"); + + } + + } + + void ThreadQueue::insertShutdownTask(Task& task) { + + bool hasWaiter = false; + + { + + Guard g(_lock); + + // Execute later when the ThreadQueue is destroyed + if( !(hasWaiter = (_waiter != 0)) ) { + + _shutdownTasks.push_back(task); + //ZTDEBUG("1 shutdown task added. %d\n", _shutdownTasks.size()); + + } + + } + + // Execute immediately if things are shutting down + if(hasWaiter) + task->run(); + + } + + bool ThreadQueue::removeShutdownTask(const Task& task) { + + Guard g(_lock); + + TaskList::iterator i = std::find(_shutdownTasks.begin(), _shutdownTasks.end(), task); + bool removed = (i != _shutdownTasks.end()); + if(removed) + _shutdownTasks.erase(i); + + //ZTDEBUG("1 shutdown task removed (%d)-%d\n", removed, _shutdownTasks.size()); + + return removed; + + } + +}; diff --git a/dep/src/zthread/ThreadQueue.h b/dep/src/zthread/ThreadQueue.h new file mode 100644 index 00000000000..044f8263026 --- /dev/null +++ b/dep/src/zthread/ThreadQueue.h @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTTHREADQUEUE_H__ +#define __ZTTHREADQUEUE_H__ + +#include "zthread/Singleton.h" +#include "zthread/Guard.h" +#include "FastLock.h" + + +namespace ZThread { + + class ThreadImpl; + + /** + * @class ThreadQueue + * @version 2.3.0 + * @author Eric Crahen + * @date <2003-07-27T20:52:05-0400> + * + * A ThreadQueue accumulates references to user and reference threads. + * These are threads that are running outside the scope of the Thread + * object that created them. ZThreads doesn't have a central manager for + * all threads (partly why I renamed the ThreadManager to someting more + * appropriate). Instead, ZThreads will discover threads it did not create + * and create a reference thread that allows ZThreads to interact with it. + * Non user threads that are created by the user never have to touch the + * ThreadQueue. + */ + class ThreadQueue : public Singleton { + + typedef std::deque ThreadList; + typedef std::deque TaskList; + + //! Managed thread lists + ThreadList _pendingThreads; + ThreadList _referenceThreads; + ThreadList _userThreads; + + //! Shutdown handlers + TaskList _shutdownTasks; + + //! Serilize access to the thread list + FastLock _lock; + + //! Reference thread waiting to cleanup any user & reference threads + ThreadImpl* _waiter; + + public: + + ThreadQueue(); + + /** + * The thread destroys a ThreadQueue will be a reference thread, + * probably the main thread; but it could be another thread that + * started and loaded the library. + */ + ~ThreadQueue(); + + /** + * Insert a user-thread into the queue. User-threads are inserted as they + * begin thier task. Once that task completes, user-threads are automatically + * transitioned to pending-threads via insertPendingThread(). + * + * User-threads are known to be executing thier tasks and will be cancel()ed + * as the ThreadQueue is destroyed when main() goes out of scope. This sends + * a request to the task to complete soon. Once the task exits, the thread is + * transitioned to pending-thread status. + */ + void insertUserThread(ThreadImpl*); + + /** + * Insert a pending-thread into the queue. + * + * Pending-threads are known to have completed thier tasks and thier + * resources are reclaimed (lazily) as more threads are started or as the + * ThreadQueue is destroyed. + */ + void insertPendingThread(ThreadImpl*); + + + /** + * Insert reference thread. Reference threads are not removed until + * the ThreadQueue goes out of scope. + */ + void insertReferenceThread(ThreadImpl*); + + /** + * Insert a task to be run before threads are joined. + * Any items inserted after the ThreadQueue desctructor has begun to + * execute will be run() immediately. + */ + void insertShutdownTask(Task&); + + /** + * Remove an existing shutdown task. + */ + bool removeShutdownTask(const Task&); + + private: + + void pollPendingThreads(); + + void pollUserThreads(); + + void pollReferenceThreads(); + + }; + + +} // namespace ZThread + + +#endif // __ZTTHREADQUEUE_H__ diff --git a/dep/src/zthread/ThreadedExecutor.cxx b/dep/src/zthread/ThreadedExecutor.cxx new file mode 100644 index 00000000000..44a213e8daa --- /dev/null +++ b/dep/src/zthread/ThreadedExecutor.cxx @@ -0,0 +1,464 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#include "zthread/ThreadedExecutor.h" +#include "zthread/Guard.h" +#include "zthread/FastMutex.h" +#include "zthread/Time.h" + +#include "ThreadImpl.h" + +namespace ZThread { + + namespace { + + //! + class WaiterQueue { + + typedef std::deque ThreadList; + + typedef struct group_t { + size_t id; + size_t count; + ThreadList waiters; + group_t(size_t n) : id(n), count(0) {} + } Group; + + typedef std::deque GroupList; + + //! Predicate to find a specific group + struct by_id : public std::unary_function { + size_t id; + by_id(size_t n) : id(n) {} + bool operator()(const Group& grp) { + return grp.id == id; + } + }; + + //! Functor to count groups + struct counter : public std::unary_function { + size_t count; + counter() : count(0) {} + void operator()(const Group& grp) { count += grp.count; } + operator size_t() { return count; } + }; + + FastMutex _lock; + GroupList _list; + size_t _id; + size_t _generation; + + public: + + WaiterQueue() : _id(0), _generation(0) { + // At least one empty-group exists + _list.push_back( Group(_id++) ); + } + + /** + * Insert the current thread into the current waiter list + * + * @pre At least one empty group exists + * @post At least one empty group exists + */ + bool wait(unsigned long timeout) { + + ThreadImpl* self = ThreadImpl::current(); + Monitor& m = self->getMonitor(); + + Monitor::STATE state; + + Guard g1(_lock); + + // At least one empty-group exists + assert(!_list.empty()); + + // Return w/o waiting if there are no executing tasks + if((size_t)std::for_each(_list.begin(), _list.end(), counter()) < 1) + return true; + + // Update the waiter list for the active group + _list.back().waiters.push_back(self); + size_t n = _list.back().id; + + m.acquire(); + + { + + Guard g2(g1); + state = timeout == 0 ? m.wait() : m.wait(timeout); + + } + + m.release(); + + // If awoke due to a reason other than the last task in the group 'n' completing, + // then then find the group 'self' is waiting in + GroupList::iterator i = std::find_if(_list.begin(), _list.end(), by_id(n)); + if(i != _list.end()) { + + // Remove 'self' from that list if it is still a member + ThreadList::iterator j = std::find(i->waiters.begin(), i->waiters.end(), self); + if(j != i->waiters.end()) + i->waiters.erase(j); + + } + + // At least one empty-group exists + assert(!_list.empty()); + + switch(state) { + case Monitor::SIGNALED: + break; + case Monitor::TIMEDOUT: + return false; + case Monitor::INTERRUPTED: + throw Interrupted_Exception(); + default: + throw Synchronization_Exception(); + } + + return true; + + } + + /** + * Increment the active group count + * + * @pre at least 1 empty group exists + * @post at least 1 non-empty group exists + */ + std::pair increment() { + + Guard g(_lock); + + // At least one empty-group exists + assert(!_list.empty()); + + GroupList::iterator i = --_list.end(); + size_t n = i->id; + + if(i == _list.end()) { + + // A group should never have been removed until + // the final task in that group completed + assert(0); + + } + + i->count++; + + // When the active group is being incremented, insert a new active group + // to replace it if there were waiting threads + if(i == --_list.end() && !i->waiters.empty()) + _list.push_back(Group(_id++)); + + // At least 1 non-empty group exists + assert((size_t)std::for_each(_list.begin(), _list.end(), counter()) > 0); + + return std::make_pair(n, _generation); + + } + + + /** + * Decrease the count for the group with the given id. + * + * @param n group id + * + * @pre At least 1 non-empty group exists + * @post At least 1 empty group exists + */ + void decrement(size_t n) { + + Guard g1(_lock); + + // At least 1 non-empty group exists + assert((size_t)std::for_each(_list.begin(), _list.end(), counter()) > 0); + + // Find the requested group + GroupList::iterator i = std::find_if(_list.begin(), _list.end(), by_id(n)); + if(i == _list.end()) { + + // A group should never have been removed until + // the final task in that group completed + assert(0); + + } + + // Decrease the count for tasks in this group, + if(--i->count == 0 && i == _list.begin()) { + + do { + + // When the first group completes, wake all waiters for every + // group, starting from the first until a group that is not + // complete is reached + + /* + // Don't remove the empty active group + if(i == --_list.end() && i->waiters.empty()) + break; + */ + + if( awaken(*i) ) { + + // If all waiters were awakened, remove the group + i = _list.erase(i); + + } else { + + { + + // Otherwise, unlock and yield allowing the waiter + // lists to be updated if other threads are busy + Guard g2(g1); + ThreadImpl::yield(); + + } + + i = _list.begin(); + + } + + } while(i != _list.end() && i->count == 0); + + // Ensure that an active group exists + if(_list.empty()) + _list.push_back( Group(++_id) ); + + } + + // At least one group exists + assert(!_list.empty()); + + } + + /** + */ + size_t generation(bool next = false) { + + Guard g(_lock); + return next ? _generation++ : _generation; + + } + + private: + + /** + * Awaken all the waiters remaining in the given group + * + * @return + * - true if all the waiting threads were successfully awakened. + * - false if there were one or more threads that could not be awakened. + */ + bool awaken(Group& grp) { + + // Go through the waiter list in the given group; + for(ThreadList::iterator i = grp.waiters.begin(); i != grp.waiters.end();) { + + ThreadImpl* impl = *i; + Monitor& m = impl->getMonitor(); + + // Try the monitor lock, if it cant be locked skip to the next waiter + if(m.tryAcquire()) { + + // Notify the monitor & remove from the waiter list so time isn't + // wasted checking it again. + i = grp.waiters.erase(i); + + // Try to wake the waiter, it doesn't matter if this is successful + // or not (only fails when the monitor is already going to stop waiting). + m.notify(); + m.release(); + + } else ++i; + + } + + return grp.waiters.empty(); + + } + + }; + + //! Synchronization point for the Executor + class ExecutorImpl { + + typedef std::deque ThreadList; + + bool _canceled; + FastMutex _lock; + + //! Worker threads + ThreadList _threads; + + WaiterQueue _queue; + + public: + + ExecutorImpl() : _canceled(false) {} + + WaiterQueue& getWaiterQueue() { + return _queue; + } + + void registerThread(size_t generation) { + + // Interrupt slow starting threads + if(getWaiterQueue().generation() != generation) + ThreadImpl::current()->interrupt(); + + // Enqueue for possible future interrupt() + else { + + Guard g(_lock); + _threads.push_back( ThreadImpl::current() ); + + } + + } + + void unregisterThread() { + + Guard g(_lock); + std::remove(_threads.begin(), _threads.end(), ThreadImpl::current() ); + + } + + void cancel() { + + Guard g(_lock); + _canceled = true; + + } + + bool isCanceled() { + + if(_canceled) + return true; + + Guard g(_lock); + return _canceled; + + } + + void interrupt() { + + Guard g(_lock); + + // Interrupt all the registered threads + for(ThreadList::iterator i = _threads.begin(); i != _threads.end(); ++i) + (*i)->interrupt(); + + // Bump the generation up, ensuring slow starting threads get this interrupt + getWaiterQueue().generation( true ); + + } + + }; /* ExecutorImpl */ + + //! Wrap a generation and a group around a task + class Worker : public Runnable { + + CountedPtr< ExecutorImpl > _impl; + Task _task; + + size_t _generation; + size_t _group; + + public: + + Worker(const CountedPtr< ExecutorImpl >& impl, const Task& task) + : _impl(impl), _task(task) { + + std::pair pr( _impl->getWaiterQueue().increment() ); + + _group = pr.first; + _generation = pr.second; + + } + + size_t group() const { + return _group; + } + + size_t generation() const { + return _generation; + } + + void run() { + + // Register this thread once its begun; the generation is used to ensure + // threads that are slow starting are properly interrupted + + _impl->registerThread( generation() ); + + try { + _task->run(); + } catch(...) { + /* consume the exceptions the work propogates */ + } + + _impl->getWaiterQueue().decrement( group() ); + + // Unregister this thread + + _impl->unregisterThread(); + + } + + }; /* Worker */ + + } + + ThreadedExecutor::ThreadedExecutor() : _impl(new ExecutorImpl) {} + + ThreadedExecutor::~ThreadedExecutor() {} + + void ThreadedExecutor::execute(const Task& task) { + + Thread t( new Worker(_impl, task) ); + + } + + void ThreadedExecutor::interrupt() { + _impl->interrupt(); + } + + void ThreadedExecutor::cancel() { + _impl->cancel(); + } + + bool ThreadedExecutor::isCanceled() { + return _impl->isCanceled(); + } + + void ThreadedExecutor::wait() { + _impl->getWaiterQueue().wait(0); + } + + bool ThreadedExecutor::wait(unsigned long timeout) { + return _impl->getWaiterQueue().wait(timeout == 0 ? 1 : timeout); + } + +} diff --git a/dep/src/zthread/Time.cxx b/dep/src/zthread/Time.cxx new file mode 100644 index 00000000000..2409d93cb79 --- /dev/null +++ b/dep/src/zthread/Time.cxx @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#include "zthread/Time.h" +#include "TimeStrategy.h" + + +using namespace ZThread; + +Time::Time() { + + // System startup time + static TimeStrategy firstHelper; + TimeStrategy helper; + + Time then(firstHelper.seconds(), firstHelper.milliseconds()); + Time now(helper.seconds(), helper.milliseconds()); + + now -= then; + + _seconds = now.seconds(); + _milliseconds = now.milliseconds(); + +} + + diff --git a/dep/src/zthread/TimeStrategy.h b/dep/src/zthread/TimeStrategy.h new file mode 100644 index 00000000000..0b9ad1e22ba --- /dev/null +++ b/dep/src/zthread/TimeStrategy.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTTIMESELECT_H__ +#define __ZTTIMESELECT_H__ + +#include "zthread/Config.h" + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +// Select the correct TimeOps implementation based on +// what the complilation environment has defined + +#ifndef HAVE_FTIME + +# if defined(ZT_WIN32) || defined(ZT_WIN9X) + +# if !defined(__MWERKS__) + +# ifndef HAVE_FTIME +# define HAVE_FTIME +# endif + +# elif defined(__MWERKS__) + +# ifndef HAVE_PERFORMANCECOUNTER +# define HAVE_PERFORMANCECOUNTER +# endif + +# endif + +# endif + +#endif + +// Some systems require this to complete the definition of timespec +// which is needed by pthreads. +#if defined(HAVE_SYS_TYPES_H) +# include +#endif + +#if defined(ZT_MACOS) + +# include "macos/UpTimeStrategy.h" + +#elif defined(HAVE_PERFORMANCECOUNTER) + +# include "win32/PerformanceCounterStrategy.h" + +#elif defined(HAVE_FTIME) + +# include "posix/FtimeStrategy.h" + +#else + +# include "posix/GetTimeOfDayStrategy.h" + +#endif + + +#ifndef __ZTTIMESTRATEGY_H__ +#error "No TimeStrategy implementation could be selected" +#endif + +#endif // __ZTTIMESELECT_H__ diff --git a/dep/src/zthread/config.h b/dep/src/zthread/config.h new file mode 100644 index 00000000000..0b630dcc36c --- /dev/null +++ b/dep/src/zthread/config.h @@ -0,0 +1,95 @@ +/* src/config.h. Generated by configure. */ +/* src/config.h.in. Generated from configure.ac by autoheader. */ + +/* Defined if is usable */ +/* #undef HAVE_ATOMIC_GCC */ + +/* Defined if is usable */ +/* #undef HAVE_ATOMIC_LINUX */ + +/* _beginthreadex() */ +/* #undef HAVE_BEGINTHREADEX */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* defined when pthreads is available */ +#define HAVE_POSIX_THREADS + +/* Defined if pthread_keycreate() is available */ +/* #undef HAVE_PTHREADKEYCREATE */ + +/* Defined if pthread_key_create() is available */ +#define HAVE_PTHREADKEY_CREATE + +/* Defined if pthread_yield() is available */ +#define HAVE_PTHREAD_YIELD + +/* Defined if -lrt is needed for RT scheduling */ +#define HAVE_SCHED_RT + +/* Defined if sched_yield() is available */ +#define HAVE_SCHED_YIELD + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Name of package */ +//#define PACKAGE "ZThread" + +/* Define to the address where bug reports for this package should be sent. */ +//#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +//#define PACKAGE_NAME "" + +/* Define to the full name and version of this package. */ +//#define PACKAGE_STRING "" + +/* Define to the one symbol short name of this package. */ +//#define PACKAGE_TARNAME "" + +/* Define to the version of this package. */ +//#define PACKAGE_VERSION "" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Defined if ftime()/_ftime() is usable */ +#define SYSTEM_FTIME ftime + +/* Version number of package */ +//#define VERSION "2.3.2" + +/* No interrupt() hooks */ +/* #undef ZTHREAD_DISABLE_INTERRUPT */ + +/* No OS priority support */ +/* #undef ZTHREAD_DISABLE_PRIORITY */ diff --git a/dep/src/zthread/linux/AtomicCount.cxx b/dep/src/zthread/linux/AtomicCount.cxx new file mode 100644 index 00000000000..28c2381c3b4 --- /dev/null +++ b/dep/src/zthread/linux/AtomicCount.cxx @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTATOMICCOUNTIMPL_H__ +#define __ZTATOMICCOUNTIMPL_H__ + +#include +#include + +namespace ZThread { + +typedef struct atomic_count_t { + + atomic_t count; + + atomic_count_t() { + atomic_t init = ATOMIC_INIT(0); + count = init; + } + + ~atomic_count_t() { + assert(atomic_read(&count) == 0); + } + +} ATOMIC_COUNT; + + +AtomicCount::AtomicCount() { + + _value = reinterpret_cast(new ATOMIC_COUNT); + +} + +AtomicCount::~AtomicCount() { + + delete reinterpret_cast(_value); + +} + +void AtomicCount::increment() { + + atomic_inc(&reinterpret_cast(_value)->count); + +} + +bool AtomicCount::decrement() { + + return atomic_dec_and_test(&reinterpret_cast(_value)->count); + +} + +}; + +#endif // __ZTATOMICCOUNTIMPL_H__ diff --git a/dep/src/zthread/linux/AtomicFastLock.h b/dep/src/zthread/linux/AtomicFastLock.h new file mode 100644 index 00000000000..b9aa1babcd6 --- /dev/null +++ b/dep/src/zthread/linux/AtomicFastLock.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTFASTLOCK_H__ +#define __ZTFASTLOCK_H__ + +#include "zthread/NonCopyable.h" +#include "../ThreadOps.h" +#include +#include + +#if !defined(NDEBUG) +# include +#endif + +namespace ZThread { + +/** + * @class FastLock + * + * @author Eric Crahen + * @date <2003-07-16T23:27:03-0400> + * @version 2.2.0 + * + * This implementation of a FastLock uses the atomic operations that + * linux provides with its kernel sources. This demonstrates how to implement + * a spinlock with a decrement and test primative. + */ +class FastLock : private NonCopyable { + + atomic_t _value; + +#if !defined(NDEBUG) + pthread_t _owner; +#endif + +public: + + inline FastLock() { + + atomic_t tmp = ATOMIC_INIT(1); + _value = tmp; + + } + + inline ~FastLock() { + + assert(atomic_read(&_value) == 1); + assert(_owner == 0); + + } + + inline void acquire() { + + while(!atomic_dec_and_test(&_value)) { + + atomic_inc(&_value); + ThreadOps::yield(); + + } + +#if !defined(NDEBUG) + _owner = pthread_self(); +#endif + } + + inline void release() { + +#if !defined(NDEBUG) + assert(pthread_equal(_owner, pthread_self()) != 0); +#endif + + atomic_inc(&_value); + _owner = 0; + + } + + inline bool tryAcquire(unsigned long timeout=0) { + + bool wasLocked = atomic_dec_and_test(&_value); + if(!wasLocked) + atomic_inc(&_value); + +#if !defined(NDEBUG) + if(wasLocked) + _owner = pthread_self(); +#endif + + return wasLocked; + + } + +}; /* FastLock */ + + +} // namespace ZThread + +#endif diff --git a/dep/src/zthread/linux/FastRecursiveLock.h b/dep/src/zthread/linux/FastRecursiveLock.h new file mode 100644 index 00000000000..d253652cb53 --- /dev/null +++ b/dep/src/zthread/linux/FastRecursiveLock.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTFASTRECURSIVELOCK_H__ +#define __ZTFASTRECURSIVELOCK_H__ + +#include "zthread/NonCopyable.h" +#include + +namespace ZThread { + +/** + * @class FastRecursiveLock + * + * @author Eric Crahen + * @date <2003-07-16T23:27:14-0400> + * @version 2.2.0 + * + * This implementation of a FastRecursiveLock uses the recursive mutex + * that linux pthreads provides. + */ +class FastRecursiveLock : private NonCopyable { + + pthread_mutex_t _mtx; + +public: + + inline FastRecursiveLock() { + + static const pthread_mutexattr_t attr = { PTHREAD_MUTEX_RECURSIVE_NP }; + pthread_mutex_init(&_mtx, &attr); + + } + + inline ~FastRecursiveLock() { + + pthread_mutex_destroy(&_mtx); + + } + + inline void acquire() { + + pthread_mutex_lock(&_mtx); + + } + + inline void release() { + + pthread_mutex_unlock(&_mtx); + + } + + inline bool tryAcquire(unsigned long timeout=0) { + + return (pthread_mutex_trylock(&_mtx) == 0); + + } + +}; /* FastRecursiveLock */ + + +} // namespace ZThread + +#endif diff --git a/dep/src/zthread/macos/FastLock.h b/dep/src/zthread/macos/FastLock.h new file mode 100644 index 00000000000..bae5c482903 --- /dev/null +++ b/dep/src/zthread/macos/FastLock.h @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTFASTLOCK_H__ +#define __ZTFASTLOCK_H__ + +#include "zthread/NonCopyable.h" +#include "zthread/Exceptions.h" + +#include +#include +//#include + +namespace ZThread { + +/** + * @class FastLock + * + * @author Eric Crahen + * @date <2003-07-16T23:25:31-0400> + * @version 2.1.6 + * + */ +class FastLock : private NonCopyable { + + MPCriticalRegionID _mtx; + + public: + + /** + * Create a new FastLock. No safety or state checks are performed. + * + * @exception Initialization_Exception - not thrown + */ + inline FastLock() { + + // Apple TN1071 + static bool init = MPLibraryIsLoaded(); + + if(!init || MPCreateCriticalRegion(&_mtx) != noErr) { + assert(0); + throw Initialization_Exception(); + } + + } + + /** + * Destroy a FastLock. No safety or state checks are performed. + */ + inline ~FastLock() throw () { + + OSStatus status = MPDeleteCriticalRegion(_mtx); + if(status != noErr) + assert(false); + + } + + /** + * Acquire an exclusive lock. No safety or state checks are performed. + * + * @exception Synchronization_Exception - not thrown + */ + inline void acquire() { + + if(MPEnterCriticalRegion(_mtx, kDurationForever) != noErr) + throw Synchronization_Exception(); + + } + + /** + * Try to acquire an exclusive lock. No safety or state checks are performed. + * This function returns immediately regardless of the value of the timeout + * + * @param timeout Unused + * @return bool + * @exception Synchronization_Exception - not thrown + */ + inline bool tryAcquire(unsigned long timeout=0) { + + OSStatus status = + MPEnterCriticalRegion(_mtx, kDurationMillisecond * timeout); + + switch(status) { + case kMPTimeoutErr: + return false; + + case noErr: + return true; + + } + + assert(0); + throw Synchronization_Exception(); + + } + + /** + * Release an exclusive lock. No safety or state checks are performed. + * The caller should have already acquired the lock, and release it + * only once. + * + * @exception Synchronization_Exception - not thrown + */ + inline void release() { + + if(MPExitCriticalRegion(_mtx) != noErr) + throw Synchronization_Exception(); + + } + + +}; /* FastLock */ + + +}; + +#endif + + + diff --git a/dep/src/zthread/macos/Monitor.cxx b/dep/src/zthread/macos/Monitor.cxx new file mode 100644 index 00000000000..ab7806b13df --- /dev/null +++ b/dep/src/zthread/macos/Monitor.cxx @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#include "Monitor.h" + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +using namespace ZThread; + +Monitor::Monitor() : _owner(0), _waiting(false), _pending(false) { + + if(MPCreateSemaphore(1, 0, &_sema) != noErr) { + assert(0); + throw Initialization_Exception(); + } + +} + +Monitor::~Monitor() throw() { + + assert(!_waiting); + + OSStatus status = MPDeleteSemaphore(_sema); + if(status != noErr) + assert(false); + +} + +Monitor::STATE Monitor::wait(unsigned long timeout) { + + // Calcuate the time, taking into account Intertask Signaling Time + // http://developer.apple.com/techpubs/macosx/Carbon/oss/MultiPServices/Multiprocessing_Services/index.html?http://developer.apple.com/techpubs/macosx/Carbon/oss/MultiPServices/Multiprocessing_Services/Functions/Creating_and_ssage_Queues.html + + AbsoluteTime tTarget; + Duration waitDuration = + (timeout == 0) ? kDurationForever : (kDurationMillisecond * timeout); + + if(waitDuration != kDurationForever) + tTarget = AddDurationToAbsolute(waitDuration, UpTime()); + + // Update the owner on first use. The owner will not change, each + // thread waits only on a single Monitor and a Monitor is never + // shared + if(_owner == 0) + _owner = MPCurrentTaskID(); + + STATE state(INVALID); + + // Serialize access to the state of the Monitor + // and test the state to determine if a wait is needed. + _waitLock.acquire(); + + if(pending(ANYTHING)) { + + // Return without waiting when possible + state = next(); + + _waitLock.release(); + return state; + + } + // Unlock the external lock if a wait() is probably needed. + // Access to the state is still serial. + _lock.release(); + + // Wait for a transition in the state that is of interest, this + // allows waits to exclude certain flags (e.g. INTERRUPTED) + // for a single wait() w/o actually discarding those flags - + // they will remain set until a wait interested in those flags + // occurs. + + // Wait, ignoring signals + _waiting = true; + + _waitLock.release(); + + // Update the wait time + if(waitDuration != kDurationForever) + waitDuration = AbsoluteDeltaToDuration(tTarget, UpTime()); + + // Sleep until a signal arrives or a timeout occurs + OSStatus status = MPWaitOnSemaphore(_sema, waitDuration); + + // Reacquire serialized access to the state + _waitLock.acquire(); + + // Awaken only when the event is set or the timeout expired + assert(status == kMPTimeoutErr || status == noErr); + + if(status == kMPTimeoutErr) + push(TIMEDOUT); + + // Get the next available STATE + state = next(); + + _waiting = false; + + // Its possible that a timeout will wake the thread before a signal is + // delivered. Absorb that leftover so the next wait isn't aborted right away + if(status == kMPTimeoutErr && _pending) { + + status = MPWaitOnSemaphore(_sema, kDurationForever); + assert(status == noErr); + + } + + _pending = false; + + // Acquire the internal lock & release the external lock + _waitLock.release(); + + // Reaquire the external lock, keep from deadlocking threads calling + // notify(), interrupt(), etc. + _lock.acquire(); + + return state; + +} + + +bool Monitor::interrupt() { + + // Serialize access to the state + _waitLock.acquire(); + + bool wasInterruptable = !pending(INTERRUPTED); + bool hasWaiter = false; + + // Update the state & wake the waiter if there is one + if(wasInterruptable) { + + push(INTERRUPTED); + + wasInterruptable = false; + + if(_waiting && !_pending) { + + _pending = true; + hasWaiter = true; + + } else + wasInterruptable = !(_owner == MPCurrentTaskID()); + + } + + _waitLock.release(); + + if(hasWaiter && !masked(Monitor::INTERRUPTED)) + MPSignalSemaphore(_sema); + + return wasInterruptable; + +} + +bool Monitor::isInterrupted() { + + // Serialize access to the state + _waitLock.acquire(); + + bool wasInterrupted = pending(INTERRUPTED); + clear(INTERRUPTED); + + _waitLock.release(); + + return wasInterrupted; + +} + + +bool Monitor::notify() { + + // Serialize access to the state + _waitLock.acquire(); + + bool wasNotifyable = !pending(INTERRUPTED); + bool hasWaiter = false; + + // Set the flag if theres a waiter + if(wasNotifyable) { + + push(SIGNALED); + + if(_waiting && !_pending) { + + _pending = true; + hasWaiter = true; + + } + + } + + _waitLock.release(); + + if(hasWaiter) + MPSignalSemaphore(_sema); + + return wasNotifyable; + +} + + +bool Monitor::cancel() { + + // Serialize access to the state + _waitLock.acquire(); + + bool wasInterrupted = !pending(INTERRUPTED); + bool hasWaiter = false; + + push(CANCELED); + + // Update the state if theres a waiter + if(wasInterrupted) { + + push(INTERRUPTED); + + if(_waiting && !_pending) { + + _pending = true; + hasWaiter = true; + + } + + } + + _waitLock.release(); + + if(hasWaiter && !masked(Monitor::INTERRUPTED)) + MPSignalSemaphore(_sema); + + return wasInterrupted; + +} + +bool Monitor::isCanceled() { + + // Serialize access to the state + _waitLock.acquire(); + + bool wasCanceled = Status::examine(CANCELED); + + if(_owner == MPCurrentTaskID()) + clear(INTERRUPTED); + + _waitLock.release(); + + return wasCanceled; + +} + + + + + + + + + + diff --git a/dep/src/zthread/macos/Monitor.h b/dep/src/zthread/macos/Monitor.h new file mode 100644 index 00000000000..f4312d7b7ee --- /dev/null +++ b/dep/src/zthread/macos/Monitor.h @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTMONITOR_H__ +#define __ZTMONITOR_H__ + +#include "../Status.h" +#include "../FastLock.h" + +namespace ZThread { + +/** + * @class Monitor + * @author Eric Crahen + * @date <2003-07-29T11:24:58-0400> + * @version 2.2.1 + */ +class Monitor : public Status, private NonCopyable { + + //! Serialize access to external objects + FastLock _lock; + + //! Serialize access to internal state + FastLock _waitLock; + + //! Semaphore to control the owning thread + MPSemaphoreID _sema; + + //! Owning thread + MPTaskID _owner; + + //! Waiting flag, to avoid uneccessary signals + volatile bool _waiting; + + //! Waiting flag, to avoid too many signals + volatile bool _pending; + + //! State of the monitor + volatile int _state; + + public: + + //! Create a new monitor. + Monitor(); + + //! Destroy the monitor. + ~Monitor() throw(); + + //! Acquire the external lock for this monitor. + inline void acquire() { + _lock.acquire(); + } + + //! Try to acquire the external lock for this monitor. + inline bool tryAcquire() { + return _lock.tryAcquire(); + } + + //! Release the external lock for this monitor. + inline void release() { + _lock.release(); + } + + /** + * Wait for a state change and atomically unlock the external lock. + * Blocks for an indefinent amount of time. + * + * @return INTERRUPTED if the wait was ended by a interrupt() + * or SIGNALED if the wait was ended by a notify() + * + * @post the external lock is always acquired before this function returns + */ + inline STATE wait() { + return wait(0); + } + + /** + * Wait for a state change and atomically unlock the external lock. + * May blocks for an indefinent amount of time. + * + * @param timeout - maximum time to block (milliseconds) or 0 to + * block indefinently + * + * @return INTERRUPTED if the wait was ended by a interrupt() + * or TIMEDOUT if the maximum wait time expired. + * or SIGNALED if the wait was ended by a notify() + * + * @post the external lock is always acquired before this function returns + */ + STATE wait(unsigned long timeout); + + /** + * Interrupt this monitor. If there is a thread blocked on this monitor object + * it will be signaled and released. If there is no waiter, a flag is set and + * the next attempt to wait() will return INTERRUPTED w/o blocking. + * + * @return false if the thread was previously INTERRUPTED. + */ + bool interrupt(); + + /** + * Notify this monitor. If there is a thread blocked on this monitor object + * it will be signaled and released. If there is no waiter, a flag is set and + * the next attempt to wait() will return SIGNALED w/o blocking, if no other + * flag is set. + * + * @return false if the thread was previously INTERRUPTED. + */ + bool notify(); + + /** + * Check the state of this monitor, clearing the INTERRUPTED status if set. + * + * @return bool true if the monitor was INTERRUPTED. + * @post INTERRUPTED flag cleared if the calling thread owns the monitor. + */ + bool isInterrupted(); + + /** + * Mark the Status CANCELED, and INTERRUPT the montor. + * + * @see interrupt() + */ + bool cancel(); + + /** + * Test the CANCELED Status, clearing the INTERRUPTED status if set. + * + * @return bool + */ + bool isCanceled(); + +}; + +}; + +#endif diff --git a/dep/src/zthread/macos/TSS.h b/dep/src/zthread/macos/TSS.h new file mode 100644 index 00000000000..3f9805d0f7c --- /dev/null +++ b/dep/src/zthread/macos/TSS.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTTSS_H__ +#define __ZTTSS_H__ + +#include "zthread/NonCopyable.h" +#include "zthread/Exceptions.h" + +#include +#include +//#include + +namespace ZThread { + + /** + * @class TSS + * @author Eric Crahen + * @date <2003-07-27T14:19:10-0400> + * @version 2.1.6 + * + * An abstraction for dealing with POSIX thread specific storage (tss). + * Provides get/set and creation/destruction. + */ + template + class TSS : private NonCopyable { + + TaskStorageIndex _key; + + public: + + /** + * Create a new object for accessing tss. + */ + TSS() { + + // Apple TN1071 + static bool init = MPLibraryIsLoaded(); + + if(!init || MPAllocateTaskStorageIndex(&_key) != noErr) { + assert(0); + throw Initialization_Exception(); + } + + } + + /** + * Destroy the underlying supoprt for accessing tss with this + * object. + */ + ~TSS() { + + OSStatus status = MPDeallocateTaskStorageIndex(_key); + if(status != noErr) + assert(0); + + } + + /** + * Get the value stored in tss. + * + * @return T + * + * @exception InvalidOp_exception thrown when the tss is not properly initialized + */ + T get() const { + return reinterpret_cast(MPGetTaskStorageValue(_key)); + } + + + /** + * Store a value in tss. + * + * @param value T + * @return T old value + * + * @exception InvalidOp_exception thrown when the tss is not properly initialized + */ + T set(T value) const { + + T oldValue = get(); + + OSStatus status = + MPSetTaskStorageValue(_key, reinterpret_cast(value)); + + if(status != noErr) { + assert(0); + throw Synchronization_Exception(); + } + + return oldValue; + + } + + }; + +} + +#endif + + diff --git a/dep/src/zthread/macos/ThreadOps.cxx b/dep/src/zthread/macos/ThreadOps.cxx new file mode 100644 index 00000000000..6a1a4106877 --- /dev/null +++ b/dep/src/zthread/macos/ThreadOps.cxx @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + + +#include "ThreadOps.h" +#include "zthread/Exceptions.h" +#include "zthread/Runnable.h" + +namespace ZThread { + +const ThreadOps ThreadOps::INVALID(0); + +ThreadOps::ThreadOps() : _queue(0), _tid(0) { + + if(MPCreateQueue(&_queue) != noErr) + throw Initialization_Exception(); + +} + +ThreadOps::~ThreadOps() throw() { + + if(_queue != 0) { + + OSStatus status = MPDeleteQueue(_queue); + if(status != noErr) + assert(0); + + } + +} + +bool ThreadOps::join(ThreadOps* ops) { + + assert(ops); + assert(ops->_tid != 0); + + OSStatus status = MPWaitOnQueue(ops->_queue, NULL, NULL, NULL, kDurationForever); + + return status == noErr; + +} + +bool ThreadOps::yield() { + + MPYield(); + return true; + +} + +bool ThreadOps::setPriority(ThreadOps* impl, Priority p) { + return true; +} + +bool ThreadOps::getPriority(ThreadOps* impl, Priority& p) { + return true; +} + + +bool ThreadOps::spawn(Runnable* task) { + + OSStatus status = + MPCreateTask(&_dispatch, task, 0UL, _queue, NULL, NULL, 0UL, &_tid); + + return status == noErr; + +} + +OSStatus ThreadOps::_dispatch(void *arg) { + + Runnable* task = reinterpret_cast(arg); + assert(task); + + // Run the task from the correct context + task->run(); + + // Exit the thread + MPExit(noErr); + return noErr; + +} + +} // namespace ZThread + + diff --git a/dep/src/zthread/macos/ThreadOps.h b/dep/src/zthread/macos/ThreadOps.h new file mode 100644 index 00000000000..c100fcfefe5 --- /dev/null +++ b/dep/src/zthread/macos/ThreadOps.h @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTTHREADOPS_H__ +#define __ZTTHREADOPS_H__ + +#include "zthread/Priority.h" + +#include +#include +//#include +//#include + +namespace ZThread { + +class Runnable; + +/** + * @class ThreadOps + * @author Eric Crahen + * @date <2003-07-16T23:26:01-0400> + * @version 2.2.0 + * + * This class is an abstraction used to perform various operations on a + * native POSIX thread. + */ +class ThreadOps { + + //! Keep track of the pthreads handle for the native thread + MPQueueID _queue; + MPTaskID _tid; + + ThreadOps(MPTaskID tid) : _queue(0), _tid(tid) { } + + static OSStatus _dispatch(void*); + +public: + + const static ThreadOps INVALID; + + /** + * Create a new ThreadOps to manipulate a native thread. + */ + ThreadOps(); + + ThreadOps(const ThreadOps& ops) : _queue(0), _tid(ops._tid) {} + + ~ThreadOps() throw(); + + inline bool operator==(const ThreadOps& ops) const { + return ops._tid == _tid; + } + + const ThreadOps& operator=(const ThreadOps& ops) { + + assert(_queue == 0); + _tid = ops._tid; + + return *this; + + } + + static ThreadOps self() { + return ThreadOps(MPCurrentTaskID()); + } + + /** + * Activating an instance of ThreadOps will map it onto the currently + * executing thread. + */ + static void activate(ThreadOps* ops) { + + assert(ops); + assert(ops->_tid == 0); + + ops->_tid = MPCurrentTaskID(); + + } + + /** + * Test if this object represents the currently executing + * native thread. + * + * @return bool true if successful + */ + + static bool isCurrent(ThreadOps* ops) { + + assert(ops); + + return MPCurrentTaskID() == ops->_tid; + + } + + /** + * Join a native thread. + * + * @return bool true if successful + */ + static bool join(ThreadOps*); + + /** + * Force the current native thread to yield, letting the scheduler + * give the CPU time to another thread. + * + * @return bool true if successful, false if the operation can't + * be supported. + */ + static bool yield(); + + /** + * Set the priority for the native thread if supported by the + * system. + * + * @param PRIORITY requested priority + * @return bool false if unsuccessful + */ + static bool setPriority(ThreadOps*, Priority); + + /** + * Set the priority for the native thread if supported by the + * system. + * + * @param Thread::PRIORITY& current priority + * @return bool false if unsuccessful + */ + static bool getPriority(ThreadOps*, Priority&); + +protected: + + /** + * Spawn a native thread. + * + * @param ThreadImpl* parent thread + * @param ThreadImpl* child thread being started. + * @param Runnable* task being executed. + * + * @return bool true if successful + */ + bool spawn(Runnable*); + +}; + + +} + +#endif // __ZTTHREADOPS_H__ + diff --git a/dep/src/zthread/macos/UpTimeStrategy.h b/dep/src/zthread/macos/UpTimeStrategy.h new file mode 100644 index 00000000000..f2056e14ca2 --- /dev/null +++ b/dep/src/zthread/macos/UpTimeStrategy.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTTIMESTRATEGY_H__ +#define __ZTTIMESTRATEGY_H__ + +#include +//#include + +namespace ZThread { + + +/** + * @class TimeStrategy + * + * Implement a strategy for time operatons based on UpTime + */ +class TimeStrategy { + + unsigned long _ms; + unsigned long _s; + + public: + + TimeStrategy() { + + // Get the absolute time in milliseconds relative to the program startup + static AbsoluteTime sysUpTime(UpTime()); + AbsoluteTime delta = AbsoluteDeltaToNanoseconds(UpTime(), sysUpTime); + + uint64_t now = *reinterpret_cast(&delta) / 1000000; + + _s = now / 1000; + _ms = now % 1000; + + } + + inline unsigned long seconds() const { + return _s; + } + + inline unsigned long milliseconds() const { + return _ms; + } + + unsigned long seconds(unsigned long s) { + + unsigned long z = seconds(); + _s = s; + return z; + + } + + unsigned long milliseconds(unsigned long ms) { + + unsigned long z = milliseconds(); + _ms = ms; + + return z; + + } + +}; + +}; + +#endif // __ZTTIMESTRATEGY_H__ diff --git a/dep/src/zthread/posix/ConditionRecursiveLock.h b/dep/src/zthread/posix/ConditionRecursiveLock.h new file mode 100644 index 00000000000..a46ed35548c --- /dev/null +++ b/dep/src/zthread/posix/ConditionRecursiveLock.h @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTFASTRECURSIVELOCK_H__ +#define __ZTFASTRECURSIVELOCK_H__ + +#include "zthread/NonCopyable.h" +#include +#include +#include + +namespace ZThread { + +/** + * @class FastRecursiveLock + * + * @author Eric Crahen + * @date <2003-07-16T23:28:37-0400> + * @version 2.2.0 + * + * This is an implementation of a FastRecursiveLock for any vannila + * POSIX system. It is based on a condition variable and a mutex; + * because of this it is important to not that its waiting properties + * are not the same as other mutex implementations that generally + * based on spin locks. Under high contention, this implementation may + * be preferable to a spin lock, although refactoring the design of + * code that puts a mutex under alot of preasure may be worth investigating. + */ +class FastRecursiveLock : private NonCopyable { + + //! Serialize state + pthread_mutex_t _mtx; + + //! Wait for lock + pthread_cond_t _cond; + + //! Owner + pthread_t _owner; + + //! Count + volatile unsigned int _count; + +public: + + inline FastRecursiveLock() : _owner(0), _count(0) { + + pthread_mutex_init(&_mtx, 0); + if(pthread_cond_init(&_cond, 0) != 0) { + assert(0); + } + + } + + inline ~FastRecursiveLock() { + + pthread_mutex_destroy(&_mtx); + if(pthread_cond_destroy(&_cond) != 0) { + assert(0); + } + + } + + inline void acquire() { + + pthread_t self = pthread_self(); + pthread_mutex_lock(&_mtx); + + // If the caller does not own the lock, wait until there is no owner + if(_owner != 0 && !pthread_equal(_owner, self)) { + + int status = 0; + do { // ignore signals + status = pthread_cond_wait(&_cond, &_mtx); + } while(status == EINTR && _owner == 0); + + } + + _owner = self; + _count++; + + pthread_mutex_unlock(&_mtx); + + } + + inline bool tryAcquire(unsigned long timeout=0) { + + pthread_t self = pthread_self(); + pthread_mutex_lock(&_mtx); + + // If the caller owns the lock, or there is no owner update the count + bool success = (_owner == 0 || pthread_equal(_owner, self)); + if(success) { + + _owner = self; + _count++; + + } + + pthread_mutex_unlock(&_mtx); + + return success; + + } + + inline void release() { + + assert(pthread_equal(_owner, pthread_self())); + + pthread_mutex_lock(&_mtx); + if(--_count == 0) { + + _owner = 0; + pthread_cond_signal(&_cond); + + } + + pthread_mutex_unlock(&_mtx); + + } + + +}; /* FastRecursiveLock */ + + +} // namespace ZThread + +#endif diff --git a/dep/src/zthread/posix/FastLock.h b/dep/src/zthread/posix/FastLock.h new file mode 100644 index 00000000000..87faf34d4ff --- /dev/null +++ b/dep/src/zthread/posix/FastLock.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTFASTLOCK_H__ +#define __ZTFASTLOCK_H__ + +#include "zthread/Exceptions.h" +#include "zthread/NonCopyable.h" +#include +#include + +namespace ZThread { + +/** + * @class FastLock + * + * @author Eric Crahen + * @date <2003-07-16T23:28:07-0400> + * @version 2.2.8 + * + * This is the smallest and fastest synchronization object in the library. + * It is an implementation of fast mutex, an all or nothing exclusive + * lock. It should be used only where you need speed and are willing + * to sacrifice all the state & safety checking provided by the framework + * for speed. + */ +class FastLock : private NonCopyable { + + pthread_mutex_t _mtx; + + public: + + /** + * Create a new FastLock. No safety or state checks are performed. + * + * @exception Initialization_Exception - not thrown + */ + inline FastLock() { + + if(pthread_mutex_init(&_mtx, 0) != 0) + throw Initialization_Exception(); + + } + + /** + * Destroy a FastLock. No safety or state checks are performed. + */ + inline ~FastLock() { + + if(pthread_mutex_destroy(&_mtx) != 0) { + assert(0); + } + + } + + /** + * Acquire an exclusive lock. No safety or state checks are performed. + * + * @exception Synchronization_Exception - not thrown + */ + inline void acquire() { + + if(pthread_mutex_lock(&_mtx) != 0) + throw Synchronization_Exception(); + + } + + /** + * Try to acquire an exclusive lock. No safety or state checks are performed. + * This function returns immediately regardless of the value of the timeout + * + * @param timeout Unused + * @return bool + * @exception Synchronization_Exception - not thrown + */ + inline bool tryAcquire(unsigned long /*timeout*/=0) { + + return (pthread_mutex_trylock(&_mtx) == 0); + + } + + /** + * Release an exclusive lock. No safety or state checks are performed. + * The caller should have already acquired the lock, and release it + * only once. + * + * @exception Synchronization_Exception - not thrown + */ + inline void release() { + + if(pthread_mutex_unlock(&_mtx) != 0) + throw Synchronization_Exception(); + + } + + +}; /* FastLock */ + + +}; + +#endif diff --git a/dep/src/zthread/posix/FtimeStrategy.h b/dep/src/zthread/posix/FtimeStrategy.h new file mode 100644 index 00000000000..5e703970c5c --- /dev/null +++ b/dep/src/zthread/posix/FtimeStrategy.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTTIMESTRATEGY_H__ +#define __ZTTIMESTRATEGY_H__ + +#include + +#if defined(_MSC_VER) + +# include + +# define timeb _timeb +# define ftime _ftime + +#endif + +namespace ZThread { + +/** + * @class TimeStrategy + * + * Implement a strategy for time operatons based on ftime + */ +class TimeStrategy { + + struct timeb _value; + +public: + + TimeStrategy() { + ftime(&_value); + } + + inline unsigned long seconds() const { + return (unsigned long)_value.time; + } + + inline unsigned long milliseconds() const { + return _value.millitm; + } + + unsigned long seconds(unsigned long s) { + + unsigned long z = seconds(); + _value.time = s; + + return z; + + } + + unsigned long milliseconds(unsigned long ms) { + + unsigned long z = milliseconds(); + _value.millitm = (unsigned short)ms; + + return z; + + } + +}; + +}; + +#endif // __ZTTIMESTRATEGY_H__ diff --git a/dep/src/zthread/posix/GetTimeOfDayStrategy.h b/dep/src/zthread/posix/GetTimeOfDayStrategy.h new file mode 100644 index 00000000000..8588807f4f7 --- /dev/null +++ b/dep/src/zthread/posix/GetTimeOfDayStrategy.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTTIMESTRATEGY_H__ +#define __ZTTIMESTRATEGY_H__ + +#include + +namespace ZThread { + +/** + * @class TimeStrategy + * + * Implement a strategy for time operatons based on gettimeofday + */ +class TimeStrategy { + + struct timeval _value; + +public: + + TimeStrategy() { + gettimeofday(&_value, 0); + } + + inline unsigned long seconds() const { + return _value.tv_sec; + } + + inline unsigned long milliseconds() const { + return _value.tv_usec/1000; + } + + unsigned long seconds(unsigned long s) { + + unsigned long z = seconds(); + _value.tv_sec = s; + + return z; + + } + + unsigned long milliseconds(unsigned long ms) { + + unsigned long z = milliseconds(); + _value.tv_usec = ms*1000; + + return z; + + } + +}; + +}; + +#endif // __ZTTIMESTRATEGY_H__ diff --git a/dep/src/zthread/posix/Monitor.cxx b/dep/src/zthread/posix/Monitor.cxx new file mode 100644 index 00000000000..bb157dae0dc --- /dev/null +++ b/dep/src/zthread/posix/Monitor.cxx @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#include "Monitor.h" +#include "../Debug.h" +#include "../TimeStrategy.h" + +#include +#include +#include + +namespace ZThread { + +Monitor::Monitor() : _owner(0), _waiting(false) { + + pthread_cond_init(&_waitCond, 0); + pthread_mutex_init(&_waitLock, 0); + +} + +Monitor::~Monitor() { + + assert(!_waiting); + + pthread_cond_destroy(&_waitCond); + pthread_mutex_destroy(&_waitLock); + +} + +Monitor::STATE Monitor::wait(unsigned long ms) { + + // Update the owner on first use. The owner will not change, each + // thread waits only on a single Monitor and a Monitor is never + // shared + if(_owner == 0) + _owner = pthread_self(); + + STATE state(INVALID); + + // Serialize access to the state of the Monitor + // and test the state to determine if a wait is needed. + + pthread_mutex_lock(&_waitLock); + + if(pending(ANYTHING)) { + + // Return without waiting when possible + state = next(); + + pthread_mutex_unlock(&_waitLock); + return state; + + } + + // Unlock the external lock if a wait() is probably needed. + // Access to the state is still serial. + _lock.release(); + + // Wait for a transition in the state that is of interest, this + // allows waits to exclude certain flags (e.g. INTERRUPTED) + // for a single wait() w/o actually discarding those flags - + // they will remain set until a wait interested in those flags + // occurs. + // if(!currentState(interest)) { + + // Wait, ignoring signals + _waiting = true; + int status = 0; + + if(ms == 0) { // Wait forever + + do { // ignore signals unless the state is interesting + status = pthread_cond_wait(&_waitCond, &_waitLock); + } while(status == EINTR && !pending(ANYTHING)); + + // Akwaken only when a state is pending + assert(status == 0); + + } else { + + // Find the target time + TimeStrategy t; + + ms += t.milliseconds(); + + unsigned long s = t.seconds() + (ms / 1000); + ms %= 1000; + + // Convert to a timespec + struct ::timespec timeout; + + timeout.tv_sec = s; + timeout.tv_nsec = ms*1000000; + + // Wait ignoring signals until the state is interesting + do { + + // When a timeout occurs, update the state to reflect that. + status = pthread_cond_timedwait(&_waitCond, &_waitLock, &timeout); + + } while(status == EINTR && !pending(ANYTHING)); + + // Akwaken only when a state is pending or when the timeout expired + assert(status == 0 || status == ETIMEDOUT); + + if(status == ETIMEDOUT) + push(TIMEDOUT); + + } + + // Get the next available STATE + state = next(); + _waiting = false; + + pthread_mutex_unlock(&_waitLock); + + // Reaquire the external lock, keep from deadlocking threads calling + // notify(), interrupt(), etc. + + _lock.acquire(); + + return state; + +} + + +bool Monitor::interrupt() { + + // Serialize access to the state + pthread_mutex_lock(&_waitLock); + + bool wasInterruptable = !pending(INTERRUPTED); + bool hadWaiter = _waiting; + + if(wasInterruptable) { + + // Update the state & wake the waiter if there is one + push(INTERRUPTED); + + wasInterruptable = false; + + if(hadWaiter && !masked(Monitor::INTERRUPTED)) + pthread_cond_signal(&_waitCond); + else + wasInterruptable = !pthread_equal(_owner, pthread_self()); + + } + + pthread_mutex_unlock(&_waitLock); + + // Only returns true when an interrupted thread is not currently blocked + return wasInterruptable; + +} + +bool Monitor::isInterrupted() { + + // Serialize access to the state + pthread_mutex_lock(&_waitLock); + + bool wasInterrupted = pending(INTERRUPTED); + + clear(INTERRUPTED); + + pthread_mutex_unlock(&_waitLock); + + return wasInterrupted; + +} + +bool Monitor::isCanceled() { + + // Serialize access to the state + pthread_mutex_lock(&_waitLock); + + bool wasCanceled = examine(CANCELED); + + if(pthread_equal(_owner, pthread_self())) + clear(INTERRUPTED); + + pthread_mutex_unlock(&_waitLock); + + return wasCanceled; + +} + +bool Monitor::cancel() { + + // Serialize access to the state + pthread_mutex_lock(&_waitLock); + + bool wasInterrupted = !pending(INTERRUPTED); + bool hadWaiter = _waiting; + + push(CANCELED); + + if(wasInterrupted) { + + // Update the state & wake the waiter if there is one + push(INTERRUPTED); + + if(hadWaiter && !masked(Monitor::INTERRUPTED)) + pthread_cond_signal(&_waitCond); + + } + + pthread_mutex_unlock(&_waitLock); + + return wasInterrupted; + +} + +bool Monitor::notify() { + + // Serialize access to the state + pthread_mutex_lock(&_waitLock); + + bool wasNotifyable = !pending(INTERRUPTED); + + if(wasNotifyable) { + + // Set the flag and wake the waiter if there + // is one + push(SIGNALED); + + if(_waiting) + pthread_cond_signal(&_waitCond); + + } + + pthread_mutex_unlock(&_waitLock); + + return wasNotifyable; + +} + +} // namespace ZThread + diff --git a/dep/src/zthread/posix/Monitor.h b/dep/src/zthread/posix/Monitor.h new file mode 100644 index 00000000000..945c879f421 --- /dev/null +++ b/dep/src/zthread/posix/Monitor.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTMONITOR_H__ +#define __ZTMONITOR_H__ + +#include "../Status.h" +#include "../FastLock.h" + +namespace ZThread { + +/** + * @class Monitor + * @author Eric Crahen + * @date <2003-07-18T08:16:09-0400> + * @version 2.2.8 + */ +class Monitor : public Status, private NonCopyable { + private: + + //! Serialize access to external objects + FastLock _lock; + + //! Condition variable used to block a thread. + pthread_cond_t _waitCond; + + //! Serialize access to the internal state of the monitor + pthread_mutex_t _waitLock; + + //! Owning thread + pthread_t _owner; + + //! Waiting flag, to avoid uneccessary signals + volatile bool _waiting; + + public: + + typedef Status::STATE STATE; + + //! Create a new monitor. + Monitor(); + + //! Destroy the monitor. + ~Monitor(); + + //! Acquire the lock for this monitor. + inline void acquire() { + _lock.acquire(); + } + + //! Acquire the lock for this monitor. + inline bool tryAcquire() { + return _lock.tryAcquire(); + } + + //! Release the lock for this monitor + inline void release() { + _lock.release(); + } + + /** + * Wait for a state change and atomically unlock the external lock. + * Blocks for an indefinent amount of time. + * + * @return INTERRUPTED if the wait was ended by a interrupt() + * or SIGNALED if the wait was ended by a notify() + * + * @post the external lock is always acquired before this function returns + */ + inline STATE wait() { + return wait(0); + } + + /** + * Wait for a state change and atomically unlock the external lock. + * May blocks for an indefinent amount of time. + * + * @param timeout - maximum time to block (milliseconds) or 0 to + * block indefinently + * + * @return INTERRUPTED if the wait was ended by a interrupt() + * or TIMEDOUT if the maximum wait time expired. + * or SIGNALED if the wait was ended by a notify() + * + * @post the external lock is always acquired before this function returns + */ + STATE wait(unsigned long timeout); + + /** + * Interrupt this monitor. If there is a thread blocked on this monitor object + * it will be signaled and released. If there is no waiter, a flag is set and + * the next attempt to wait() will return INTERRUPTED w/o blocking. + * + * @return false if the thread was previously INTERRUPTED. + */ + bool interrupt(); + + /** + * Notify this monitor. If there is a thread blocked on this monitor object + * it will be signaled and released. If there is no waiter, a flag is set and + * the next attempt to wait() will return SIGNALED w/o blocking, if no other + * flag is set. + * + * @return false if the thread was previously INTERRUPTED. + */ + bool notify(); + + /** + * Check the state of this monitor, clearing the INTERRUPTED status if set. + * + * @return bool true if the monitor was INTERRUPTED. + * @post INTERRUPTED flag cleared if the calling thread owns the monitor. + */ + bool isInterrupted(); + + /** + * Mark the Status CANCELED, and INTERRUPT the montor. + * + * @see interrupt() + */ + bool cancel(); + + /** + * Test the CANCELED Status, clearing the INTERRUPTED status if set. + * + * @return bool + */ + bool isCanceled(); + +}; + +}; + +#endif diff --git a/dep/src/zthread/posix/PriorityOps.h b/dep/src/zthread/posix/PriorityOps.h new file mode 100644 index 00000000000..92da66a9cff --- /dev/null +++ b/dep/src/zthread/posix/PriorityOps.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTPRIORITYOPS_H__ +#define __ZTPRIORITYOPS_H__ + +#include "zthread/Priority.h" +#include "../ThreadOps.h" + +namespace ZThread { + +/** + * @class PriorityOps + * @author Eric Crahen + * @date <2003-07-16T23:30:00-0400> + * @version 2.2.0 + * + * This class is an abstraction used to perform various operations on a + * native POSIX thread. + */ +class PriorityOps { + + +public: + + +}; + + +} // namespace ZThread + +#endif // __ZTPRIORITYOPS_H__ diff --git a/dep/src/zthread/posix/TSS.h b/dep/src/zthread/posix/TSS.h new file mode 100644 index 00000000000..931ff348b3d --- /dev/null +++ b/dep/src/zthread/posix/TSS.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTTSS_H__ +#define __ZTTSS_H__ + +#include "zthread/NonCopyable.h" +#include +#include + +namespace ZThread { + + /** + * @class TSS + * @author Eric Crahen + * @date <2003-07-27T14:18:37-0400> + * @version 2.3.0 + * + * An abstraction for dealing with POSIX thread specific storage (tss). + * Provides get/set and creation/destruction. + */ + template + class TSS : private NonCopyable { + + pthread_key_t _key; + + public: + + /** + * Create a new object for accessing tss. + */ + TSS() { + + if(pthread_key_create(&_key, 0) != 0) { + assert(0); // Key creation failed + } + + } + + /** + * Destroy the underlying supoprt for accessing tss with this + * object. + */ + ~TSS() { + + pthread_key_delete(_key); + + } + + /** + * Get the value stored in tss. + * + * @return T + * + * @exception InvalidOp_exception thrown when the tss is not properly initialized + */ + T get() const { + return reinterpret_cast(pthread_getspecific(_key)); + } + + + /** + * Store a value in tss. + * + * @param value T + * @return T old value + * + * @exception InvalidOp_exception thrown when the tss is not properly initialized + */ + T set(T value) const { + + T oldValue = get(); + pthread_setspecific(_key, value); + + return oldValue; + + } + + }; + +} + +#endif + + diff --git a/dep/src/zthread/posix/ThreadOps.cxx b/dep/src/zthread/posix/ThreadOps.cxx new file mode 100644 index 00000000000..e72ef78ada3 --- /dev/null +++ b/dep/src/zthread/posix/ThreadOps.cxx @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#include "ThreadOps.h" +#include "zthread/Guard.h" +#include "zthread/Runnable.h" +#include + +#if defined(HAVE_SCHED_YIELD) +# include +#endif + +namespace ZThread { + +const ThreadOps ThreadOps::INVALID(0); + +bool ThreadOps::join(ThreadOps* ops) { + + assert(ops); + assert(ops->_tid != 0); + + int err = 0; + + do { + + err = pthread_join(ops->_tid, NULL); + + } while(err == EINTR); + + return err == 0; + +} + +bool ThreadOps::yield() { + + bool result = false; + +#if defined(HAVE_SCHED_YIELD) + result = sched_yield() == 0; +#endif + + return result; + +} + +bool ThreadOps::setPriority(ThreadOps* impl, Priority p) { + + assert(impl); + + bool result = true; + +#if !defined(ZTHREAD_DISABLE_PRIORITY) + + struct sched_param param; + + switch(p) { + case Low: + param.sched_priority = 0; + break; + case High: + param.sched_priority = 10; + break; + case Medium: + default: + param.sched_priority = 5; + } + + result = pthread_setschedparam(impl->_tid, SCHED_OTHER, ¶m) == 0; + +#endif + + return result; + +} + +bool ThreadOps::getPriority(ThreadOps* impl, Priority& p) { + + assert(impl); + + bool result = true; + +#if !defined(ZTHREAD_DISABLE_PRIORITY) + + struct sched_param param; + int policy = SCHED_OTHER; + + if(result = (pthread_getschedparam(impl->_tid, &policy, ¶m) == 0)) { + + // Convert to one of the PRIORITY values + if(param.sched_priority < 10) + p = Low; + else if(param.sched_priority == 10) + p = Medium; + else + p = High; + + } + +#endif + + return result; + +} + + +bool ThreadOps::spawn(Runnable* task) { + return pthread_create(&_tid, 0, _dispatch, task) == 0; +} + + + +extern "C" void *_dispatch(void *arg) { + + Runnable* task = reinterpret_cast(arg); + assert(task); + + // Run the task from the correct context + task->run(); + + // Exit the thread + pthread_exit((void**)0); + return (void*)0; + +} + +} // namespace ZThread + + diff --git a/dep/src/zthread/posix/ThreadOps.h b/dep/src/zthread/posix/ThreadOps.h new file mode 100644 index 00000000000..be754c2d659 --- /dev/null +++ b/dep/src/zthread/posix/ThreadOps.h @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTTHREADOPS_H__ +#define __ZTTHREADOPS_H__ + + +#include "zthread/Priority.h" +#include +#include + +namespace ZThread { + +class Runnable; + +//! Dispatch function for native pthreads required extern C +//! linkage. +extern "C" void* _dispatch(void*); + +/** + * @class ThreadOps + * @author Eric Crahen + * @date <2003-07-16T23:30:25-0400> + * @version 2.2.8 + * + * This class is an abstraction used to perform various operations on a + * native POSIX thread. + */ +class ThreadOps { + + //! Keep track of the pthreads handle for the native thread + pthread_t _tid; + + ThreadOps(pthread_t tid) : _tid(tid) { } + +public: + + const static ThreadOps INVALID; + + /** + * Create a new ThreadOps to manipulate a native thread. + */ + ThreadOps() : _tid(0) { } + + + inline bool operator==(const ThreadOps& ops) const { + return pthread_equal(_tid, ops._tid); + } + + + static ThreadOps self() { + return ThreadOps(pthread_self()); + } + + /** + * Activating an instance of ThreadOps will map it onto the currently + * executing thread. + */ + static void activate(ThreadOps* ops) { + + assert(ops); + assert(ops->_tid == 0); + + ops->_tid = pthread_self(); + + } + + /** + * Test if this object represents the currently executing + * native thread. + * + * @return bool true if successful + */ + + static bool isCurrent(ThreadOps* ops) { + + assert(ops); + + return pthread_equal(pthread_self(), ops->_tid); + + } + + /** + * Join a native thread. + * + * @return bool true if successful + */ + static bool join(ThreadOps*); + + /** + * Force the current native thread to yield, letting the scheduler + * give the CPU time to another thread. + * + * @return bool true if successful, false if the operation can't + * be supported. + */ + static bool yield(); + + /** + * Set the priority for the native thread if supported by the + * system. + * + * @param PRIORITY requested priority + * @return bool false if unsuccessful + */ + static bool setPriority(ThreadOps*, Priority); + + /** + * Set the priority for the native thread if supported by the + * system. + * + * @param Thread::PRIORITY& current priority + * @return bool false if unsuccessful + */ + static bool getPriority(ThreadOps*, Priority&); + +protected: + + /** + * Spawn a native thread. + * + * @param ThreadImpl* parent thread + * @param ThreadImpl* child thread being started. + * @param Runnable* task being executed. + * + * @return bool true if successful + */ + bool spawn(Runnable*); + +}; + + +} + +#endif // __ZTTHREADOPS_H__ diff --git a/dep/src/zthread/solaris/FastRecursiveLock.h b/dep/src/zthread/solaris/FastRecursiveLock.h new file mode 100644 index 00000000000..956e1dbd3ad --- /dev/null +++ b/dep/src/zthread/solaris/FastRecursiveLock.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTFASTRECURSIVELOCK_H__ +#define __ZTFASTRECURSIVELOCK_H__ + +#include "zthread/NonCopyable.h" +#include + +namespace ZThread { + +/** + * @class FastRecursiveLock + * + * @author Eric Crahen + * @date <2003-07-16T23:31:23-0400> + * @version 2.2.0 + * + * This FastRecursiveLock implementation uses pthreads mutex attribute + * functions to create a recursive lock. This implementation is not + * specific to solaris and will work on any system that supports + * pthread_mutexattr_settype(). + */ +class FastRecursiveLock : private NonCopyable { + + pthread_mutex_t _mtx; + + /** + * @class Attribute + * + * Utility class to maintain the attribute as long as it is needed. + */ + class Attribute { + + pthread_mutexattr_t _attr; + + public: + + Attribute() { + + if(pthread_mutexattr_init(&_attr) != 0) { + assert(0); + } + + if(pthread_mutexattr_settype(&_attr, PTHREAD_MUTEX_RECURSIVE) != 0) { + assert(0); + } + + } + + ~Attribute() { + + if(pthread_mutexattr_destroy(&_attr) != 0) { + assert(0); + } + + } + + operator pthread_mutexattr_t*() { + return &_attr; + } + + }; + +public: + + inline FastRecursiveLock() { + + static Attribute attr; + pthread_mutex_init(&_mtx, (pthread_mutexattr_t*)attr); + + } + + inline ~FastRecursiveLock() { + + pthread_mutex_destroy(&_mtx); + + } + + inline void acquire() { + + pthread_mutex_lock(&_mtx); + + } + + inline void release() { + + pthread_mutex_unlock(&_mtx); + + } + + inline bool tryAcquire(unsigned long timeout=0) { + + return (pthread_mutex_trylock(&_mtx) == 0); + + } + +}; /* FastRecursiveLock */ + + +} // namespace ZThread + +#endif diff --git a/dep/src/zthread/vanilla/DualMutexRecursiveLock.h b/dep/src/zthread/vanilla/DualMutexRecursiveLock.h new file mode 100644 index 00000000000..ddce7a3cd27 --- /dev/null +++ b/dep/src/zthread/vanilla/DualMutexRecursiveLock.h @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTFASTRECURSIVELOCK_H__ +#define __ZTFASTRECURSIVELOCK_H__ + +#include "../FastLock.h" +#include "../ThreadOps.h" +#include + +namespace ZThread { + +/** + * @class FastRecursiveLock + * + * @author Eric Crahen + * @date <2003-07-16T23:31:09-0400> + * @version 2.2.8 + * + * This is a vanilla FastRecursiveLock implementation for a + * system that doesn't provide recurisve locks. This implementation + * is based on using a pair of mutexes, because of this, it performs + * roughly the same as a spin lock would. + */ +class FastRecursiveLock : private NonCopyable { + + //! Lock for blocking + FastLock _blockingLock; + + //! Serialize state + FastLock _stateLock; + + //! Owner + ThreadOps _owner; + + //! Count + volatile unsigned int _count; + + public: + + inline FastRecursiveLock() : _owner(ThreadOps::INVALID), _count(0) { } + + inline ~FastRecursiveLock() { + + assert(_owner == ThreadOps::INVALID); + assert(_count == 0); + + } + + void acquire() { + + ThreadOps self(ThreadOps::self()); + + // Try to lock the blocking mutex first + bool wasLocked = _blockingLock.tryAcquire(); + if(!wasLocked) { + + // Otherwise, grab the lock for the state + _stateLock.acquire(); + + wasLocked = (_owner == self); + if(wasLocked) + _count++; + + _stateLock.release(); + + if(wasLocked) + return; + + // Try to be cooperative + ThreadOps::yield(); + _blockingLock.acquire(); + + } + + // Serialze access to the state + _stateLock.acquire(); + + // Take ownership + assert(_owner == ThreadOps::INVALID || _owner == self); + + _owner = self; + _count++; + + _stateLock.release(); + + } + + + bool tryAcquire(unsigned long timeout = 0) { + + ThreadOps self(ThreadOps::self()); + + // Try to lock the blocking mutex first + bool wasLocked = _blockingLock.tryAcquire(); + if(!wasLocked) { + + // Otherwise, grab the lock for the state + _stateLock.acquire(); + + wasLocked = (_owner == self); + if(wasLocked) + _count++; + + _stateLock.release(); + + return wasLocked; + + } + + // Serialze access to the state + _stateLock.acquire(); + + // Take ownership + assert(_owner == ThreadOps::INVALID || _owner == self); + + _owner = self; + _count++; + + _stateLock.release(); + + return true; + + } + + + void release() { + + // Assume that release is only used by the owning thread, as it + // should be. + assert(_count != 0); + assert(_owner == ThreadOps::self()); + + _stateLock.acquire(); + + // If the lock was owned and the count has reached 0, give up + // ownership and release the blocking lock + if(--_count == 0) { + + _owner = ThreadOps::INVALID; + _blockingLock.release(); + + } + + _stateLock.release(); + + } + + +}; /* FastRecursiveLock */ + +} // namespace ZThread + +#endif diff --git a/dep/src/zthread/vanilla/SimpleAtomicCount.cxx b/dep/src/zthread/vanilla/SimpleAtomicCount.cxx new file mode 100644 index 00000000000..fc63d141d6a --- /dev/null +++ b/dep/src/zthread/vanilla/SimpleAtomicCount.cxx @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTATOMICCOUNTIMPL_H__ +#define __ZTATOMICCOUNTIMPL_H__ + +#include "zthread/Guard.h" +#include "../FastLock.h" + +#include + +namespace ZThread { + +typedef struct atomic_count_t { + + FastLock lock; + unsigned long count; + + atomic_count_t() : count(0) {} + +} ATOMIC_COUNT; + +AtomicCount::AtomicCount() { + + ATOMIC_COUNT* c = new ATOMIC_COUNT; + _value = reinterpret_cast(c); + +} + +AtomicCount::~AtomicCount() { + + ATOMIC_COUNT* c = reinterpret_cast(_value); + assert(c->count == 0); + + delete c; + +} + +//! Postfix decrement and return the current value +size_t AtomicCount::operator--(int) { + + ATOMIC_COUNT* c = reinterpret_cast(_value); + + Guard g(c->lock); + return c->count--; + +} + +//! Postfix increment and return the current value +size_t AtomicCount::operator++(int) { + + ATOMIC_COUNT* c = reinterpret_cast(_value); + + Guard g(c->lock); + return c->count++; + +} + +//! Prefix decrement and return the current value +size_t AtomicCount::operator--() { + + ATOMIC_COUNT* c = reinterpret_cast(_value); + + Guard g(c->lock); + return --c->count; + +} + +//! Prefix increment and return the current value +size_t AtomicCount::operator++() { + + ATOMIC_COUNT* c = reinterpret_cast(_value); + + Guard g(c->lock); + return ++c->count; + +} + +}; + +#endif // __ZTATOMICCOUNTIMPL_H__ diff --git a/dep/src/zthread/vanilla/SimpleRecursiveLock.h b/dep/src/zthread/vanilla/SimpleRecursiveLock.h new file mode 100644 index 00000000000..f4f309218b6 --- /dev/null +++ b/dep/src/zthread/vanilla/SimpleRecursiveLock.h @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTFASTRECURSIVELOCK_H__ +#define __ZTFASTRECURSIVELOCK_H__ + +#include "../FastLock.h" +#include "../ThreadOps.h" +#include + +namespace ZThread { + +/** + * @class FastRecursiveLock + * + * @author Eric Crahen + * @date <2003-07-16T23:30:59-0400> + * @version 2.2.8 + * + * This implementation of a FastRecursiveLock uses the which ever FastLock + * that is selected to create a recursive spin lock. + */ +class FastRecursiveLock : private NonCopyable { + + FastLock _lock; + + ThreadOps _owner; + + volatile unsigned int _count; + +public: + + inline FastRecursiveLock() : _owner(ThreadOps::INVALID), _count(0) {} + + inline ~FastRecursiveLock() { + + assert(_owner == ThreadOps::INVALID); + assert(_count == 0); + + } + + inline void acquire() { + + ThreadOps self(ThreadOps::self()); + bool wasLocked = false; + + do { + + _lock.acquire(); + + // If there is no owner, or the owner is the caller + // update the count + if(_owner == ThreadOps::INVALID || _owner == self) { + + _owner = self; + _count++; + + wasLocked = true; + + } + + _lock.release(); + + } while(!wasLocked); + + assert(_owner == ThreadOps::self()); + + } + + inline void release() { + + assert(_owner == ThreadOps::self()); + + _lock.acquire(); + + if(--_count == 0) + _owner = ThreadOps::INVALID; + + _lock.release(); + + } + + inline bool tryAcquire(unsigned long timeout=0) { + + ThreadOps self(ThreadOps::self()); + bool wasLocked = false; + + _lock.acquire(); + + if(_owner == ThreadOps::INVALID || _owner == self) { + + _owner = self; + _count++; + + wasLocked = true; + + } + + _lock.release(); + + assert(!wasLocked || _owner == ThreadOps::self()); + return wasLocked; + + } + +}; /* FastRecursiveLock */ + + +} // namespace ZThread + +#endif diff --git a/dep/src/zthread/win32/AtomicCount.cxx b/dep/src/zthread/win32/AtomicCount.cxx new file mode 100644 index 00000000000..84cbf8c3ddc --- /dev/null +++ b/dep/src/zthread/win32/AtomicCount.cxx @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTATOMICCOUNTIMPL_H__ +#define __ZTATOMICCOUNTIMPL_H__ + +#include +#include + +namespace ZThread { + + +AtomicCount::AtomicCount() { + + _value = reinterpret_cast(new LONG(0)); + +} + +AtomicCount::~AtomicCount() { + + assert(*reinterpret_cast(_value) == 0); + delete reinterpret_cast(_value); + +} + +void AtomicCount::increment() { + + ::InterlockedIncrement(reinterpret_cast(_value)); + +} + +bool AtomicCount::decrement() { + + LONG v = ::InterlockedDecrement(reinterpret_cast(_value)); + return static_cast(v) == 0; + +} + +}; + +#endif // __ZTATOMICCOUNTIMPL_H__ diff --git a/dep/src/zthread/win32/AtomicFastLock.h b/dep/src/zthread/win32/AtomicFastLock.h new file mode 100644 index 00000000000..a714c03789f --- /dev/null +++ b/dep/src/zthread/win32/AtomicFastLock.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTFASTLOCK_H__ +#define __ZTFASTLOCK_H__ + +#include "zthread/NonCopyable.h" +#include +#include + +namespace ZThread { + + +/** + * @class FastLock + * + * @author Eric Crahen + * @date <2003-07-16T23:32:20-0400> + * @version 2.1.6 + * + * This is the smallest and fastest synchronization object in the library. + * It is an implementation of fast mutex, an all or nothing exclusive + * lock. It should be used only where you need speed and are willing + * to sacrifice all the state & safety checking provided by the framework + * for speed. + * + * The current Platform SDK defines: + * + * LONG InterlockedExchange(LPLONG, LONG) + * LONG InterlockedCompareExchange(LPLONG, LONG, LONG, LONG) + * + * If your compiler complains about LPLONG not being implicitly casted to + * a PVOID, then you should get the SDK update from microsoft or use the + * WIN9X implementation of this class. + * + * ---- + * Because Windows 95 and earlier can run on processors prior to the 486, they + * don't all support the CMPXCHG function, and so Windows 95 an earlier dont support + * InterlockedCompareExchange. For this, you should use the win9x implementation + * of this class + */ +class FastLock : private NonCopyable { + +#pragma pack(push, 8) + LONG volatile _lock; +#pragma pack(pop) + + public: + + /** + * Create a new FastLock + */ + inline FastLock() : _lock(0) { } + + + /** + * Destroy FastLock + */ + inline ~FastLock() { assert(_lock == 0); } + + /** + * Lock the fast Lock, no error check. + * + * @exception None + */ + inline void acquire() { + + while (::InterlockedCompareExchange(const_cast(&_lock), 1, 0) != 0) + ::Sleep(0); + + } + + + /** + * Release the fast Lock, no error check. + * + * @exception None + */ + inline void release() { + + ::InterlockedExchange(const_cast(&_lock), (LONG)0); + + } + + /** + * Try to acquire an exclusive lock. No safety or state checks are performed. + * This function returns immediately regardless of the value of the timeout + * + * @param timeout Unused + * @return bool + * @exception Synchronization_Exception - not thrown + */ + inline bool tryAcquire(unsigned long timeout=0) { + + return ::InterlockedCompareExchange(const_cast(&_lock), 1, 0) == 0; + + } + +}; /* FastLock */ + + +}; +#endif diff --git a/dep/src/zthread/win32/AtomicFastRecursiveLock.h b/dep/src/zthread/win32/AtomicFastRecursiveLock.h new file mode 100644 index 00000000000..c6a61b03b5d --- /dev/null +++ b/dep/src/zthread/win32/AtomicFastRecursiveLock.h @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTFASTRECURSIVELOCK_H__ +#define __ZTFASTRECURSIVELOCK_H__ + +#include "zthread/NonCopyable.h" +#include +#include + +namespace ZThread { + + +/** + * @class FastRecursiveLock + * + * @author Eric Crahen + * @date <2003-07-16T23:32:34-0400> + * @version 2.1.6 + * + * This is the smaller and faster implementation of a RecursiveLock. + * A single thread can acquire the mutex any number of times, but it + * must perform a release for each acquire(). Other threads are blocked + * until a thread has released all of its locks on the mutex. + * + * This particular implementation performs fewer safety checks. Like + * the FastLock implementation, any waiting caused by an acquire() request + * is not interruptable. This is so that the mutex can have the fastest + * response time for a time critical application while still having a good + * degree of reliability. + * + * TryEnterCriticalSection() does not work at all on some systems, so its + * not used. + * + * + * The current Platform SDK defines: + * + * LONG InterlockedExchange(LPLONG, LONG) + * LONG InterlockedCompareExchange(LPLONG, LONG, LONG, LONG) + * + * If your compiler complains about LPLONG not being implicitly casted to + * a PVOID, then you should get the SDK update from microsoft or use the + * WIN9X implementation of this class. + * + * ---- + * Because Windows 95 and earlier can run on processors prior to the 486, they + * don't all support the CMPXCHG function, and so Windows 95 an earlier dont support + * InterlockedCompareExchange. If you define ZT_WIN9X, you'll get a version of the + * FastLock that uses the XCHG instruction + */ +class FastRecursiveLock : private NonCopyable { + +// Add def for mingw32 or other non-ms compiler to align on 64-bit +// boundary +#pragma pack(push, 8) + LONG volatile _lock; +#pragma pack(pop) + LONG _count; + + public: + + /** + * Create a new FastRecursiveLock + */ + inline FastRecursiveLock() : _lock(0), _count(0) { } + + + /** + * Destroy FastLock + */ + inline ~FastRecursiveLock() { + assert(_lock == 0); + } + + /** + * Lock the fast Lock, no error check. + * + * @exception None + */ + inline void acquire() { + + DWORD id = ::GetCurrentThreadId(); + + // Take ownership if the lock is free or owned by the calling thread + do { + + DWORD owner = (DWORD)::InterlockedCompareExchange(const_cast(&_lock), id, 0); + if(owner == 0 || owner == id) + break; + + ::Sleep(0); + + } while(1); + + _count++; + + } + + + /** + * Release the fast Lock, no error check. + * + * @exception None + */ + inline void release() { + + if(--_count == 0) + ::InterlockedExchange(const_cast(&_lock), 0); + + } + + /** + * Try to acquire an exclusive lock. No safety or state checks are performed. + * This function returns immediately regardless of the value of the timeout + * + * @param timeout Unused + * @return bool + * @exception Synchronization_Exception - not thrown + */ + inline bool tryAcquire(unsigned long timeout=0) { + + DWORD id = ::GetCurrentThreadId(); + DWORD owner = (DWORD)::InterlockedCompareExchange(const_cast(&_lock), id, 0); + + if(owner == 0 || owner == id) { + _count++; + return true; + } + + return false; + + } + + +}; /* FastRecursiveLock */ + + +}; +#endif diff --git a/dep/src/zthread/win32/FastLock.h b/dep/src/zthread/win32/FastLock.h new file mode 100644 index 00000000000..2e9fe829af6 --- /dev/null +++ b/dep/src/zthread/win32/FastLock.h @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTFASTLOCK_H__ +#define __ZTFASTLOCK_H__ + +#include "zthread/Exceptions.h" +#include "zthread/NonCopyable.h" +#include "../ThreadOps.h" +#include +#include + +namespace ZThread { + + /** + * @class FastLock + * + * @author Eric Crahen + * @date <2003-07-16T23:32:44-0400> + * @version 2.2.11 + * + * This FastLock implementation is based on a Win32 Mutex + * object. This will perform better under high contention, + * but will not be as fast as the spin lock under reasonable + * circumstances. + */ + class FastLock : private NonCopyable { + + HANDLE _hMutex; +#ifndef NDEBUG + volatile bool _locked; +#endif + + public: + + /** + * Create a new FastLock + */ + FastLock() { + +#ifndef NDEBUG + _locked = false; +#endif + + _hMutex = ::CreateMutex(0, 0, 0); + assert(_hMutex != NULL); + if(_hMutex == NULL) + throw Initialization_Exception(); + + } + + + ~FastLock() { + ::CloseHandle(_hMutex); + } + + void acquire() { + + if(::WaitForSingleObject(_hMutex, INFINITE) != WAIT_OBJECT_0) { + assert(0); + throw Synchronization_Exception(); + } + +#ifndef NDEBUG + + // Simulate deadlock to provide consistent behavior. This + // will help avoid errors when porting. Avoiding situations + // where a FastMutex mistakenly behaves as a recursive lock. + + while(_locked) + ThreadOps::yield(); + + _locked = true; + +#endif + + } + + void release() { + +#ifndef NDEBUG + _locked = false; +#endif + + if(::ReleaseMutex(_hMutex) == 0) { + assert(0); + throw Synchronization_Exception(); + } + + } + + + bool tryAcquire(unsigned long timeout = 0) { + + switch(::WaitForSingleObject(_hMutex, timeout)) { + case WAIT_OBJECT_0: + +#ifndef NDEBUG + + // Simulate deadlock to provide consistent behavior. This + // will help avoid errors when porting. Avoiding situations + // where a FastMutex mistakenly behaves as a recursive lock. + + while(_locked) + ThreadOps::yield(); + + _locked = true; + +#endif + + return true; + case WAIT_TIMEOUT: + return false; + default: + break; + } + + assert(0); + throw Synchronization_Exception(); + + } + + }; + +} // namespace ZThread + +#endif diff --git a/dep/src/zthread/win32/FastRecursiveLock.h b/dep/src/zthread/win32/FastRecursiveLock.h new file mode 100644 index 00000000000..e1a6e7cd692 --- /dev/null +++ b/dep/src/zthread/win32/FastRecursiveLock.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTFASTRECURSIVELOCK_H__ +#define __ZTFASTRECURSIVELOCK_H__ + +#include "zthread/Exceptions.h" +#include "zthread/NonCopyable.h" +#include +#include + +namespace ZThread { + + +/** + * @class FastRecursiveLock + * + * @author Eric Crahen + * @date <2003-07-16T23:32:56-0400> + * @version 2.2.11 + * + * This FastRecursiveLock implementation is based on a Win32 Mutex + * object. This will perform better under high contention, + * but will not be as fast as the spin lock under reasonable + * circumstances. + */ +class FastRecursiveLock : private NonCopyable { + + HANDLE _hMutex; + volatile unsigned int _count; + + public: + + /** + * Create a new FastRecursiveLock + */ + FastRecursiveLock() : _count(0) { + + _hMutex = ::CreateMutex(0, 0, 0); + assert(_hMutex != NULL); + if(_hMutex == NULL) + throw Initialization_Exception(); + + } + + + ~FastRecursiveLock() { + ::CloseHandle(_hMutex); + } + + + void acquire() { + + if(::WaitForSingleObject(_hMutex, INFINITE) != WAIT_OBJECT_0) { + assert(0); + throw Synchronization_Exception(); + } + + } + + void release() { + + if(::ReleaseMutex(_hMutex) == 0) { + assert(0); + throw Synchronization_Exception(); + } + + } + + bool tryAcquire(unsigned long) { + + switch(::WaitForSingleObject(_hMutex, 0)) { + case WAIT_OBJECT_0: + return true; + case WAIT_TIMEOUT: + return false; + default: + break; + } + + assert(0); + throw Synchronization_Exception(); + + } + +}; /* FastRecursiveLock */ + +} // namespace ZThread + +#endif diff --git a/dep/src/zthread/win32/Monitor.cxx b/dep/src/zthread/win32/Monitor.cxx new file mode 100644 index 00000000000..6e69487c054 --- /dev/null +++ b/dep/src/zthread/win32/Monitor.cxx @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#include "Monitor.h" + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +using namespace ZThread; + +Monitor::Monitor() : _owner(0), _waiting(false) { + + _handle = ::CreateEvent(0, TRUE, FALSE, 0); + if(_handle == NULL) { + assert(0); + } + +} + +Monitor::~Monitor() { + + assert(!_waiting); + + ::CloseHandle(_handle); + +} + +Monitor::STATE Monitor::wait(unsigned long ms) { + + // Update the owner on first use. The owner will not change, each + // thread waits only on a single Monitor and a Monitor is never + // shared + if(_owner == 0) + _owner = ::GetCurrentThreadId(); + + STATE state; //(INVALID); + + // Serialize access to the state of the Monitor + // and test the state to determine if a wait is needed. + _waitLock.acquire(); + + if(pending(ANYTHING)) { + + // Return without waiting when possible + state = next(); + + _waitLock.release(); + return state; + + } + // Unlock the external lock if a wait() is probably needed. + // Access to the state is still serial. + _lock.release(); + + // Wait for a transition in the state that is of interest, this + // allows waits to exclude certain flags (e.g. INTERRUPTED) + // for a single wait() w/o actually discarding those flags - + // they will remain set until a wait interested in those flags + // occurs. + // if(!currentState(interest)) { + + // Wait, ignoring signals + _waiting = true; + + // Block until the event is set. + _waitLock.release(); + + // The event is manual reset so this lack of atmoicity will not + // be an issue + + DWORD dwResult = + ::WaitForSingleObject(_handle, ((ms == 0) ? INFINITE : (DWORD)ms)); + + // Reacquire serialized access to the state + _waitLock.acquire(); + + // Awaken only when the event is set or the timeout expired + assert(dwResult == WAIT_OBJECT_0 || dwResult == WAIT_TIMEOUT); + + if(dwResult == WAIT_TIMEOUT) + push(TIMEDOUT); + + // Get the next available STATE + state = next(); + _waiting = false; + + ::ResetEvent(_handle); + + // Acquire the internal lock & release the external lock + _waitLock.release(); + + // Reaquire the external lock, keep from deadlocking threads calling + // notify(), interrupt(), etc. + _lock.acquire(); + + return state; + +} + + +bool Monitor::interrupt() { + + // Serialize access to the state + _waitLock.acquire(); + + bool wasInterruptable = !pending(INTERRUPTED); + bool hadWaiter = _waiting; + + if(wasInterruptable) { + + // Update the state & wake the waiter if there is one + push(INTERRUPTED); + + wasInterruptable = false; + + if(hadWaiter && !masked(Monitor::INTERRUPTED)) { + + // Blocked on a synchronization object + if(::SetEvent(_handle) == FALSE) { + assert(0); + } + + } else + wasInterruptable = !(_owner == ::GetCurrentThreadId()); + + } + + _waitLock.release(); + + // Only returns true when an interrupted thread is not currently blocked + return wasInterruptable; + +} + +bool Monitor::isInterrupted() { + + // Serialize access to the state + _waitLock.acquire(); + + bool wasInterrupted = pending(INTERRUPTED); + clear(INTERRUPTED); + + _waitLock.release(); + + return wasInterrupted; + +} + + +bool Monitor::notify() { + + // Serialize access to the state + _waitLock.acquire(); + + bool wasNotifyable = !pending(INTERRUPTED); + + if(wasNotifyable) { + + // Set the flag and wake the waiter if there + // is one + push(SIGNALED); + + // If there is a waiter then send the signal. + if(_waiting) + if(::SetEvent(_handle) == FALSE) { + assert(0); + } + + } + + _waitLock.release(); + + return wasNotifyable; + +} + + +bool Monitor::cancel() { + + // Serialize access to the state + _waitLock.acquire(); + + bool wasInterrupted = !pending(INTERRUPTED); + bool hadWaiter = _waiting; + + push(CANCELED); + + if(wasInterrupted) { + + // Update the state & wake the waiter if there is one + push(INTERRUPTED); + + // If there is a waiter then send the signal. + if(hadWaiter && !masked(Monitor::INTERRUPTED)) + if(::SetEvent(_handle) == FALSE) { + assert(0); + } + + } + + _waitLock.release(); + + return wasInterrupted; + +} + +bool Monitor::isCanceled() { + + // Serialize access to the state + _waitLock.acquire(); + + bool wasCanceled = examine(CANCELED); + + if(_owner == ::GetCurrentThreadId()) + clear(INTERRUPTED); + + _waitLock.release(); + + return wasCanceled; + +} + diff --git a/dep/src/zthread/win32/Monitor.h b/dep/src/zthread/win32/Monitor.h new file mode 100644 index 00000000000..7073343b7f8 --- /dev/null +++ b/dep/src/zthread/win32/Monitor.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTMONITOR_H__ +#define __ZTMONITOR_H__ + +#include "../Status.h" +#include "../FastLock.h" + +namespace ZThread { + +/** + * @class Monitor + * @author Eric Crahen + * @date <2003-07-16T23:33:10-0400> + * @version 2.2.11 + */ +class Monitor : public Status, private NonCopyable { + + //! Serialize access to external objects + FastLock _lock; + + //! Event used to block thread + HANDLE _handle; + + //! Serialize access to the internal state of the monitor + FastLock _waitLock; + + //! Owning thread + DWORD _owner; + + //! Waiting flag, to avoid uneccessary signals + volatile bool _waiting; + + //! State of the monitor + volatile int _state; + + public: + + //! Create a new monitor. + Monitor(); + + //! Destroy the monitor. + ~Monitor(); + + //! Acquire the external lock for this monitor. + inline void acquire() { + _lock.acquire(); + } + + //! Try to acquire the external lock for this monitor. + inline bool tryAcquire() { + return _lock.tryAcquire(); + } + + //! Release the external lock for this monitor. + inline void release() { + _lock.release(); + } + + /** + * Wait for a state change and atomically unlock the external lock. + * Blocks for an indefinent amount of time. + * + * @return INTERRUPTED if the wait was ended by a interrupt() + * or SIGNALED if the wait was ended by a notify() + * + * @post the external lock is always acquired before this function returns + */ + inline STATE wait() { + return wait(0); + } + + /** + * Wait for a state change and atomically unlock the external lock. + * May blocks for an indefinent amount of time. + * + * @param timeout - maximum time to block (milliseconds) or 0 to + * block indefinently + * + * @return INTERRUPTED if the wait was ended by a interrupt() + * or TIMEDOUT if the maximum wait time expired. + * or SIGNALED if the wait was ended by a notify() + * + * @post the external lock is always acquired before this function returns + */ + STATE wait(unsigned long timeout); + + /** + * Interrupt this monitor. If there is a thread blocked on this monitor object + * it will be signaled and released. If there is no waiter, a flag is set and + * the next attempt to wait() will return INTERRUPTED w/o blocking. + * + * @return false if the thread was previously INTERRUPTED. + */ + bool interrupt(); + + /** + * Notify this monitor. If there is a thread blocked on this monitor object + * it will be signaled and released. If there is no waiter, a flag is set and + * the next attempt to wait() will return SIGNALED w/o blocking, if no other + * flag is set. + * + * @return false if the thread was previously INTERRUPTED. + */ + bool notify(); + + /** + * Check the state of this monitor, clearing the INTERRUPTED status if set. + * + * @return bool true if the monitor was INTERRUPTED. + * @post INTERRUPTED flag cleared if the calling thread owns the monitor. + */ + bool isInterrupted(); + + /** + * Mark the Status CANCELED, and INTERRUPT the montor. + * + * @see interrupt() + */ + bool cancel(); + + /** + * Test the CANCELED Status, clearing the INTERRUPTED status if set. + * + * @return bool + */ + bool isCanceled(); + +}; + +}; + +#endif diff --git a/dep/src/zthread/win32/PerformanceCounterStrategy.h b/dep/src/zthread/win32/PerformanceCounterStrategy.h new file mode 100644 index 00000000000..95b526830b3 --- /dev/null +++ b/dep/src/zthread/win32/PerformanceCounterStrategy.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTTIMESTRATEGY_H__ +#define __ZTTIMESTRATEGY_H__ + +#include +#include + +namespace ZThread { + +/** + * @class PerformanceCounterStrategy + * + * Implement a strategy for time operatons based on + * Windows QueryPerformanceXXX() functions. + * This only (erroneously) considers the lower 32 bits. + */ +class TimeStrategy { + + unsigned long _secs; + unsigned long _millis; + +public: + + TimeStrategy() { + + // Keep track of the relative time the program started + static LARGE_INTEGER i; + static BOOL valid(::QueryPerformanceCounter(&i)); + + assert(valid == TRUE); + + LARGE_INTEGER j; + ::QueryPerformanceCounter(&j); + + j.LowPart -= i.LowPart; + j.LowPart /= frequency(); + + // Mask off the high bits + _millis = (unsigned long)j.LowPart / 1000; + _secs = (unsigned long)j.LowPart - _millis; + + } + + unsigned long seconds() const { + return _secs; + } + + unsigned long milliseconds() const { + return _millis; + } + + unsigned long seconds(unsigned long s) { + + unsigned long z = seconds(); + + _secs = s; + return z; + + } + + unsigned long milliseconds(unsigned long ms) { + + unsigned long z = milliseconds(); + + _millis = ms; + return z; + + } + +private: + + // Get the frequency + static DWORD frequency() { + + static LARGE_INTEGER i; + static BOOL valid(::QueryPerformanceFrequency(&i)); + + assert(valid == TRUE); + return i.LowPart; + + } + +}; + +}; + +#endif // __ZTTIMESTRATEGY_H__ diff --git a/dep/src/zthread/win32/TSS.h b/dep/src/zthread/win32/TSS.h new file mode 100644 index 00000000000..2400830f06a --- /dev/null +++ b/dep/src/zthread/win32/TSS.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTTSS_H__ +#define __ZTTSS_H__ + +#include + +namespace ZThread { + + /** + * @class TSS + * @author Eric Crahen + * @date <2003-07-27T14:18:43-0400> + * @version 2.3.0 + * + * An abstraction for dealing with WIN32 thread specific storage (tss). + * Provides get/set and creation/destruction. + */ + template + class TSS { + + DWORD _key; + bool _valid; + + public: + + /** + * Create a new object for accessing tss. The def + */ + TSS() { + + _key = ::TlsAlloc(); + _valid = (_key != 0xFFFFFFFF); + + } + + /** + * Destroy the underlying supoprt for accessing tss with this + * object. + */ + virtual ~TSS() { + + if(_valid) + ::TlsFree(_key); + + } + + /** + * Get the value stored in tss. + * + * @return T + * + * @exception InvalidOp_exception thrown when the tss is not properly initialized + */ + inline T get() const { + + if(!_valid) + throw InvalidOp_Exception(); + + return static_cast(::TlsGetValue(_key)); + + } + + /** + * Store a value in tss. + * + * @param value T + * @return T old value + * + * @exception InvalidOp_exception thrown when the tss is not properly initialized + */ + inline T set(T value) const { + + T oldValue = get(); + ::TlsSetValue(_key, value); + + return oldValue; + + } + + + }; + +} + +#endif + + diff --git a/dep/src/zthread/win32/ThreadOps.cxx b/dep/src/zthread/win32/ThreadOps.cxx new file mode 100644 index 00000000000..6e8fb8d3b71 --- /dev/null +++ b/dep/src/zthread/win32/ThreadOps.cxx @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#include "ThreadOps.h" +#include "zthread/Runnable.h" +#include + +namespace ZThread { + +const ThreadOps ThreadOps::INVALID(0); + +/** + * Detect OS at runtime and attempt to locate the SwitchToThread + * function, which will assist in making the spin lock implementation + * which use ThreadOps::yield() a bit fairer. + */ +class YieldOps { + + typedef BOOL (*Yield)(void); + Yield _fnYield; + +public: + + YieldOps() : _fnYield(NULL) { + + OSVERSIONINFO v; + v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + + if(::GetVersionEx(&v) && (v.dwPlatformId == VER_PLATFORM_WIN32_NT)) { + + // Uses GetModuleHandle() so the reference count on the dll is + // not affected. There is a warning about race conditions involving + // this function being called as FreeLibrary() completes; however + // nearly all win32 applications load this particular and will keep it + // in memory until the process exits. + HINSTANCE hInst = ::GetModuleHandle("Kernel32.dll"); + if(hInst != NULL) + _fnYield = (Yield)::GetProcAddress(hInst, "SwitchToThread"); + + // REMIND: possibly need to use _T() macro for these strings + } + + } + + bool operator()() { + + // Attempt to yield using the best function available + if(!_fnYield || !_fnYield()) + ::Sleep(0); + + return true; + + } + +}; + +bool ThreadOps::join(ThreadOps* ops) { + + assert(ops); + assert(ops->_tid != 0); + assert(ops->_hThread != NULL); + + if(::WaitForSingleObjectEx(ops->_hThread, INFINITE, FALSE) != WAIT_OBJECT_0) + return false; + + ::CloseHandle(ops->_hThread); + ops->_hThread = NULL; + + return true; + +} + +bool ThreadOps::yield() { + + static YieldOps yielder; + + yielder(); + + return true; + +} + +bool ThreadOps::setPriority(ThreadOps* impl, Priority p) { + + assert(impl); + +#if !defined(ZTHREAD_DISABLE_PRIORITY) + + bool result; + + // Convert + int n; + switch(p) { + case Low: + n = THREAD_PRIORITY_BELOW_NORMAL; + break; + case High: + n = THREAD_PRIORITY_ABOVE_NORMAL; + break; + case Medium: + default: + n = THREAD_PRIORITY_NORMAL; + } + + + result = (::SetThreadPriority(impl->_hThread, n) != THREAD_PRIORITY_ERROR_RETURN); + return result; + +#else + + return true; + +#endif + +} + +bool ThreadOps::getPriority(ThreadOps* impl, Priority& p) { + + assert(impl); + bool result = true; + +#if !defined(ZTHREAD_DISABLE_PRIORITY) + + // Convert to one of the PRIORITY values + switch(::GetThreadPriority(impl->_hThread)) { + case THREAD_PRIORITY_ERROR_RETURN: + result = false; + case THREAD_PRIORITY_BELOW_NORMAL: + p = Low; + break; + case THREAD_PRIORITY_ABOVE_NORMAL: + p = High; + break; + case THREAD_PRIORITY_NORMAL: + default: + p = Medium; + } + +#endif + + return result; + +} + + +bool ThreadOps::spawn(Runnable* task) { + +// Start the thread. +#if defined(HAVE_BEGINTHREADEX) + _hThread = (HANDLE)::_beginthreadex(0, 0, &_dispatch, task, 0, (unsigned int*)&_tid); +#else + _hThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&_dispatch, task, 0, (DWORD*)&_tid); +#endif + + return _hThread != NULL; + +} + +unsigned int __stdcall ThreadOps::_dispatch(void *arg) { + + Runnable* task = reinterpret_cast(arg); + assert(task); + + // Run the task from the correct context + task->run(); + + // Exit the thread +#if defined(HAVE_BEGINTHREADEX) + ::_endthreadex(0); +#else + ExitThread(0); +#endif + + return 0; + +} + +} diff --git a/dep/src/zthread/win32/ThreadOps.h b/dep/src/zthread/win32/ThreadOps.h new file mode 100644 index 00000000000..4a3eeac2ed9 --- /dev/null +++ b/dep/src/zthread/win32/ThreadOps.h @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTTHREADOPS_H__ +#define __ZTTHREADOPS_H__ + +#include "zthread/Priority.h" +#include +#include + +namespace ZThread { + +class Runnable; + +/** + * @class ThreadOps + * @author Eric Crahen + * @date <2003-07-16T23:33:59-0400> + * @version 2.2.8 + * + * This class is an abstraction used to perform various operations on a + * native WIN32 thread. + */ +class ThreadOps { + + //! Dispatch function for native thread + static unsigned int __stdcall _dispatch(void*); + + //! TID while the thread is executing. + HANDLE _hThread; + DWORD _tid; + + ThreadOps(DWORD tid) : _tid(tid) { } + + public: + + const static ThreadOps INVALID; + + /** + * Create a new ThreadOps to represent a native thread. + */ + ThreadOps() : _tid(0), _hThread(NULL) {} + + + inline bool operator==(const ThreadOps& ops) const { + return _tid == ops._tid; + } + + + static ThreadOps self() { + return ThreadOps(::GetCurrentThreadId()); + } + + /** + * Update the native tid for this thread so it matches the current + * thread. + */ + static void activate(ThreadOps* ops) { + + assert(ops); + assert(ops->_tid == 0); + + ops->_tid = ::GetCurrentThreadId(); + + } + + /** + * Test if this object representative of the currently executing + * native thread. + * + * @return bool true if successful + */ + static bool isCurrent(ThreadOps* ops) { + + assert(ops); + + return ops->_tid == ::GetCurrentThreadId(); + + } + + /** + * Join a native thread. + * + * @return bool true if successful + */ + static bool join(ThreadOps*); + + /** + * Force the current native thread to yield, letting the scheduler + * give the CPU time to another thread. + * + * @return bool true if successful + */ + static bool yield(); + + /** + * Set the priority for the native thread if supported by the + * system. + * + * @param PRIORITY requested priority + * @return bool false if unsuccessful + */ + static bool setPriority(ThreadOps*, Priority); + + /** + * Set the priority for the native thread if supported by the + * system. + * + * @param Thread::PRIORITY& current priority + * @return bool false if unsuccessful + */ + static bool getPriority(ThreadOps*, Priority&); + +protected: + + /** + * Spawn a native thread. + * + * @param ThreadImpl* parent thread + * @param ThreadImpl* child thread being started. + * @param Runnable* task being executed. + * + * @return bool true if successful + */ + bool spawn(Runnable*); + + +}; + + +} + +#endif diff --git a/dep/src/zthread/win9x/AtomicCount.cxx b/dep/src/zthread/win9x/AtomicCount.cxx new file mode 100644 index 00000000000..2bf07dcd2e7 --- /dev/null +++ b/dep/src/zthread/win9x/AtomicCount.cxx @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTATOMICCOUNTIMPL_H__ +#define __ZTATOMICCOUNTIMPL_H__ + +#include +#include + +namespace ZThread { + +typedef struct atomic_count_t { + + CRITICAL_SECTION cs; + size_t count; + + atomic_count_t() : count(0) {} + +} ATOMIC_COUNT; + +AtomicCount::AtomicCount() { + + ATOMIC_COUNT* c = new ATOMIC_COUNT; + _value = reinterpret_cast(c); + ::InitializeCriticalSection(&c->cs); + +} + +AtomicCount::~AtomicCount() { + + ATOMIC_COUNT* c = reinterpret_cast(_value); + assert(c->count == 0); + ::DeleteCriticalSection(&c->cs); + delete c; + +} + +//! Postfix decrement and return the current value +size_t AtomicCount::operator--(int) { + + ATOMIC_COUNT* c = reinterpret_cast(_value); + size_t value; + + ::EnterCriticalSection(&c->cs); + value = c->count--; + ::LeaveCriticalSection(&c->cs); + + return value; + +} + +//! Postfix increment and return the current value +size_t AtomicCount::operator++(int) { + + ATOMIC_COUNT* c = reinterpret_cast(_value); + size_t value; + + ::EnterCriticalSection(&c->cs); + value = c->count++; + ::LeaveCriticalSection(&c->cs); + + return value; + +} + +//! Prefix decrement and return the current value +size_t AtomicCount::operator--() { + + ATOMIC_COUNT* c = reinterpret_cast(_value); + size_t value; + + ::EnterCriticalSection(&c->cs); + value = --c->count; + ::LeaveCriticalSection(&c->cs); + + return value; + +} + +//! Prefix increment and return the current value +size_t AtomicCount::operator++() { + + ATOMIC_COUNT* c = reinterpret_cast(_value); + size_t value; + + ::EnterCriticalSection(&c->cs); + value = ++c->count; + ::LeaveCriticalSection(&c->cs); + + return value; + +} + +}; + +#endif // __ZTATOMICCOUNTIMPL_H__ diff --git a/dep/src/zthread/win9x/AtomicFastLock.h b/dep/src/zthread/win9x/AtomicFastLock.h new file mode 100644 index 00000000000..5b50a9c7337 --- /dev/null +++ b/dep/src/zthread/win9x/AtomicFastLock.h @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2005, Eric Crahen + * + * 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. + * + */ + +#ifndef __ZTFASTLOCK_H__ +#define __ZTFASTLOCK_H__ + +#include "zthread/NonCopyable.h" +#include +#include + +namespace ZThread { + + +/** + * @class FastLock + * + * @author Eric Crahen + * @date <2003-07-16T23:31:51-0400> + * @version 2.2.0 + * + * This uses a custom spin lock based on the older swap & compare approach + * using the XCHG instruction. You should only use this is you *absolutely* need + * to use an older system, like Windows 95. If you can, use the Win32 version. + * + * Because Windows 95 and earlier can run on processors prior to the 486, they + * don't all support the CMPXCHG function, and so Windows 95 an earlier dont support + * InterlockedCompareExchange. + * + * This is asm inlined for microsoft visual c, it needs to be changed in order to + * compile with gcc, or another win32 compiler - but more likely than not you'll + * be using the Win32 version on those compilers and this won't be a problem. + */ +class FastLock : private NonCopyable { + +// Add def for mingw32 or other non-ms compiler to align on 32-bit boundary +#pragma pack(push, 4) + unsigned char volatile _lock; +#pragma pack(pop) + + public: + + /** + * Create a new FastLock + */ + inline FastLock() : _lock(0) { } + + + inline ~FastLock() { + assert(_lock == 0); + } + + inline void acquire() { + + DWORD dw = (DWORD)&_lock; + + _asm { // swap & compare + spin_lock: + + mov al, 1 + mov esi, dw + xchg [esi], al + and al,al + jz spin_locked + } + + ::Sleep(0); + + _asm { + jmp spin_lock + spin_locked: + } + + } + + inline void release() { + + DWORD dw = (DWORD)&_lock; + + _asm { + mov al, 0 + mov esi, dw + xchg [esi], al + } + + + } + + inline bool tryAcquire(unsigned long timeout=0) { + + volatile DWORD dw = (DWORD)&_lock; + volatile DWORD result; + + _asm { + + mov al, 1 + mov esi, dw + xchg [esi], al + and al,al + mov esi, result + xchg [esi], al + } + + return result == 0; + + } + +}; /* Fast Lock */ + +} // namespace ZThread + +#endif diff --git a/doc/DocStructure.dox b/doc/DocStructure.dox new file mode 100644 index 00000000000..dee8b5a0877 --- /dev/null +++ b/doc/DocStructure.dox @@ -0,0 +1,31 @@ +/*! \mainpage + * + * \section intro_sec Introduction and links + * This is the source documentation for the \b %MaNGOS (Massive Network Game %Object Server) project.\n + * %MaNGOS is an object-oriented Massively Multiplayer Online Role-Playing Game Server (MMORPGS).\n + * The project documentation and the bug tracker can be found on the %MaNGOS wiki. + * + * \section begin Where to begin? + * If you are interested in understanding the source code of this project you can begin + * - On the wiki to get an overview of the different modules of the server + * - In this source doumentation, starting at the module hierarchy + */ + +/*! \defgroup realmd Realm Daemon + */ + +/*! \defgroup mangos Mangos Deamon + */ + +/*! \defgroup mangosd Daemon starter + \ingroup mangos + */ + +/*! \defgroup u2w User Connections + \ingroup mangos + */ + +/*! \defgroup world The World + \ingroup mangos + */ + diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in new file mode 100644 index 00000000000..9893593751c --- /dev/null +++ b/doc/Doxyfile.in @@ -0,0 +1,1314 @@ +# Doxyfile 1.5.3 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file that +# follow. The default is UTF-8 which is also the encoding used for all text before +# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into +# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of +# possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = @PACKAGE@ + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = @VERSION@ + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = ./ + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian, +# Italian, Japanese, Japanese-en (Japanese with English messages), Korean, +# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian, +# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = @top_srcdir@/ + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +DETAILS_AT_TOP = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = "memo=\par Note:\n " \ + "draft=\xrefitem draft \"Draft\" \"Draft List\" This API may be changed in the future versions and was introduced in " \ + "stable=\xrefitem stable \"Stable\" \"Stable List\" " \ + "deprecated=\xrefitem deprecated \"Deprecated\" \"Deprecated List\" " \ + "obsolete=\xrefitem obsolete \"Obsolete\" \"Obsolete List\" " \ + "system=\xrefitem system \"System\" \"System List\" \n Do not use unless you know what you are doing. " \ + "internal=\xrefitem internal \"Internal\" \"Internal List\" Do not use. This API is for interal use only. " + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to +# include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = YES + +# If this flag is set to YES, the members of anonymous namespaces will be extracted +# and appear in the documentation as a namespace called 'anonymous_namespace{file}', +# where file will be replaced with the base name of the file that contains the anonymous +# namespace. By default anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = YES + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from the +# version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text " + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = @top_srcdir@/src/shared/ \ + @top_srcdir@/src/shared/Auth/ \ + @top_srcdir@/src/shared/Database/ \ + @top_srcdir@/src/game/ \ + @top_srcdir@/src/realmd/ \ + @top_srcdir@/src/mangosd/ \ + DocStructure.dox + +# This tag can be used to specify the character encoding of the source files that +# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default +# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding. +# See http://www.gnu.org/software/libiconv for the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py + +FILE_PATTERNS = *.cpp \ + *.h \ + *.hpp + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = config*.h + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the output. +# The symbol name can be a fully qualified name, a word, or if the wildcard * is used, +# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. If you have enabled CALL_GRAPH or CALLER_GRAPH +# then you must also enable this option. If you don't then doxygen will produce +# a warning and turn it on anyway + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentstion. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = YES + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = YES + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = YES + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = U_EXPORT2 \ + U_STABLE \ + U_DRAFT \ + U_INTERNAL \ + U_SYSTEM \ + U_DEPRECATED \ + U_OBSOLETE + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = "@srcdir@/html/mangos-ng-docs.tag " + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to +# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to +# specify the directory where the mscgen tool resides. If left empty the tool is assumed to +# be found in the default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will +# generate a caller dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable caller graphs for selected +# functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the number +# of direct children of the root node in a graph is already larger than +# MAX_DOT_GRAPH_NOTES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, which results in a white background. +# Warning: Depending on the platform used, enabling this option may lead to +# badly anti-aliased labels on the edges of a graph (i.e. they become hard to +# read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = YES diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 00000000000..e45e8220178 --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,49 @@ +# Copyright (C) 2005-2008 MaNGOS +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## Process this file with automake to produce Makefile.in + +## Sub-directories to parse + +## Additional files to include when running 'make dist' +# Nothing yet. +# Doxygen configuration files. +EXTRA_DIST = \ + DocStructure.dox \ + Doxyfile + +DOC_DIR = . +DOXYFILE = $(DOC_DIR)/Doxyfile +DOC_HTML = $(DOC_OUT)/index.html +DOC_OUT_HTML = $(DOC_DIR)/html +DOXYGEN = @DOXYGEN@ + +if DOXYGEN_ENABLED +doc: $(DOC_HTML) + @echo "" + @echo "Type \"firefox $(DOC_OUT_HTML)/index.html\" to see the html document." + @echo "" + +$(DOC_HTML): $(DOXYFILE) + $(DOXYGEN) $(DOXYFILE) +else +.PHONY: doc +doc: + @echo "You must enable at configure time: ./configure --enable-doxygen" +endif + +clean-local: + rm -rf $(DOC_OUT_HTML) diff --git a/sql/Makefile.am b/sql/Makefile.am new file mode 100644 index 00000000000..fe7aade1839 --- /dev/null +++ b/sql/Makefile.am @@ -0,0 +1,42 @@ +# Copyright (C) 2005-2008 MaNGOS +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## Process this file with automake to produce Makefile.in + +## Sub-directories to parse +SUBDIRS = updates tools + +## Change installation location +# datadir = mangos/sql +pkgdatadir = $(datadir)/mangos/sql + +## Files to be installed +# Install basic SQL files to datadir +pkgdata_DATA = \ + mangos.sql \ + realmd.sql \ + characters.sql \ + create_mysql.sql \ + drop_mysql.sql + +## Additional files to include when running 'make dist' +# SQL files for MaNGOS database +EXTRA_DIST = \ + create_mysql.sql \ + drop_mysql.sql \ + characters.sql \ + mangos.sql \ + realmd.sql diff --git a/sql/characters.sql b/sql/characters.sql new file mode 100644 index 00000000000..1c294e21a75 --- /dev/null +++ b/sql/characters.sql @@ -0,0 +1,1221 @@ +-- MySQL dump 10.11 +-- +-- Host: localhost Database: characters +-- ------------------------------------------------------ +-- Server version 5.0.45-Debian_1ubuntu3.1-log + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `arena_team` +-- + +DROP TABLE IF EXISTS `arena_team`; +CREATE TABLE `arena_team` ( + `arenateamid` int(10) unsigned NOT NULL default '0', + `name` char(255) NOT NULL, + `captainguid` int(10) unsigned NOT NULL default '0', + `type` tinyint(3) unsigned NOT NULL default '0', + `BackgroundColor` int(10) unsigned NOT NULL default '0', + `EmblemStyle` int(10) unsigned NOT NULL default '0', + `EmblemColor` int(10) unsigned NOT NULL default '0', + `BorderStyle` int(10) unsigned NOT NULL default '0', + `BorderColor` int(10) unsigned NOT NULL default '0', + PRIMARY KEY (`arenateamid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `arena_team` +-- + +LOCK TABLES `arena_team` WRITE; +/*!40000 ALTER TABLE `arena_team` DISABLE KEYS */; +/*!40000 ALTER TABLE `arena_team` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `arena_team_member` +-- + +DROP TABLE IF EXISTS `arena_team_member`; +CREATE TABLE `arena_team_member` ( + `arenateamid` int(10) unsigned NOT NULL default '0', + `guid` int(10) unsigned NOT NULL default '0', + `played_week` int(10) unsigned NOT NULL default '0', + `wons_week` int(10) unsigned NOT NULL default '0', + `played_season` int(10) unsigned NOT NULL default '0', + `wons_season` int(10) unsigned NOT NULL default '0' +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `arena_team_member` +-- + +LOCK TABLES `arena_team_member` WRITE; +/*!40000 ALTER TABLE `arena_team_member` DISABLE KEYS */; +/*!40000 ALTER TABLE `arena_team_member` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `arena_team_stats` +-- + +DROP TABLE IF EXISTS `arena_team_stats`; +CREATE TABLE `arena_team_stats` ( + `arenateamid` int(10) unsigned NOT NULL default '0', + `rating` int(10) unsigned NOT NULL default '0', + `games` int(10) unsigned NOT NULL default '0', + `wins` int(10) unsigned NOT NULL default '0', + `played` int(10) unsigned NOT NULL default '0', + `wins2` int(10) unsigned NOT NULL default '0', + `rank` int(10) unsigned NOT NULL default '0', + PRIMARY KEY (`arenateamid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `arena_team_stats` +-- + +LOCK TABLES `arena_team_stats` WRITE; +/*!40000 ALTER TABLE `arena_team_stats` DISABLE KEYS */; +/*!40000 ALTER TABLE `arena_team_stats` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `auctionhouse` +-- + +DROP TABLE IF EXISTS `auctionhouse`; +CREATE TABLE `auctionhouse` ( + `id` int(11) unsigned NOT NULL default '0', + `auctioneerguid` int(11) unsigned NOT NULL default '0', + `itemguid` int(11) unsigned NOT NULL default '0', + `item_template` int(11) unsigned NOT NULL default '0' COMMENT 'Item Identifier', + `itemowner` int(11) unsigned NOT NULL default '0', + `buyoutprice` int(11) NOT NULL default '0', + `time` bigint(40) NOT NULL default '0', + `buyguid` int(11) unsigned NOT NULL default '0', + `lastbid` int(11) NOT NULL default '0', + `startbid` int(11) NOT NULL default '0', + `deposit` int(11) NOT NULL default '0', + `location` tinyint(3) unsigned NOT NULL default '3', + PRIMARY KEY (`id`), + UNIQUE KEY `item_guid` (`itemguid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `auctionhouse` +-- + +LOCK TABLES `auctionhouse` WRITE; +/*!40000 ALTER TABLE `auctionhouse` DISABLE KEYS */; +/*!40000 ALTER TABLE `auctionhouse` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `bugreport` +-- + +DROP TABLE IF EXISTS `bugreport`; +CREATE TABLE `bugreport` ( + `id` int(11) NOT NULL auto_increment COMMENT 'Identifier', + `type` varchar(255) NOT NULL default '', + `content` varchar(255) NOT NULL default '', + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Debug System'; + +-- +-- Dumping data for table `bugreport` +-- + +LOCK TABLES `bugreport` WRITE; +/*!40000 ALTER TABLE `bugreport` DISABLE KEYS */; +/*!40000 ALTER TABLE `bugreport` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `characters` +-- + +DROP TABLE IF EXISTS `characters`; +CREATE TABLE `characters` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `account` int(11) unsigned NOT NULL default '0' COMMENT 'Account Identifier', + `data` longtext, + `name` varchar(12) NOT NULL default '', + `race` tinyint(3) unsigned NOT NULL default '0', + `class` tinyint(3) unsigned NOT NULL default '0', + `position_x` float NOT NULL default '0', + `position_y` float NOT NULL default '0', + `position_z` float NOT NULL default '0', + `map` int(11) unsigned NOT NULL default '0' COMMENT 'Map Identifier', + `dungeon_difficulty` tinyint(1) unsigned NOT NULL DEFAULT '0', + `orientation` float NOT NULL default '0', + `taximask` longtext, + `online` tinyint(3) unsigned NOT NULL default '0', + `cinematic` tinyint(3) unsigned NOT NULL default '0', + `totaltime` int(11) unsigned NOT NULL default '0', + `leveltime` int(11) unsigned NOT NULL default '0', + `logout_time` bigint(20) unsigned NOT NULL default '0', + `is_logout_resting` tinyint(3) unsigned NOT NULL default '0', + `rest_bonus` float NOT NULL default '0', + `resettalents_cost` int(11) unsigned NOT NULL default '0', + `resettalents_time` bigint(20) unsigned NOT NULL default '0', + `trans_x` float NOT NULL default '0', + `trans_y` float NOT NULL default '0', + `trans_z` float NOT NULL default '0', + `trans_o` float NOT NULL default '0', + `transguid` bigint(20) unsigned NOT NULL default '0', + `gmstate` tinyint(3) unsigned NOT NULL default '0', + `stable_slots` tinyint(1) unsigned NOT NULL default '0', + `at_login` int(11) unsigned NOT NULL default '0', + `zone` int(11) unsigned NOT NULL default '0', + `death_expire_time` bigint(20) unsigned NOT NULL default '0', + `taxi_path` text, + PRIMARY KEY (`guid`), + KEY `idx_account` (`account`), + KEY `idx_online` (`online`), + KEY `idx_name` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System'; + +-- +-- Dumping data for table `characters` +-- + +LOCK TABLES `characters` WRITE; +/*!40000 ALTER TABLE `characters` DISABLE KEYS */; +/*!40000 ALTER TABLE `characters` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `character_action` +-- + +DROP TABLE IF EXISTS `character_action`; +CREATE TABLE `character_action` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `button` tinyint(3) unsigned NOT NULL default '0', + `action` smallint(5) unsigned NOT NULL default '0', + `type` tinyint(3) unsigned NOT NULL default '0', + `misc` tinyint(3) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`,`button`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System'; + +-- +-- Dumping data for table `character_action` +-- + +LOCK TABLES `character_action` WRITE; +/*!40000 ALTER TABLE `character_action` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_action` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `character_aura` +-- + +DROP TABLE IF EXISTS `character_aura`; +CREATE TABLE `character_aura` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `caster_guid` bigint(20) unsigned NOT NULL default '0' COMMENT 'Full Global Unique Identifier', + `spell` int(11) unsigned NOT NULL default '0', + `effect_index` int(11) unsigned NOT NULL default '0', + `amount` int(11) NOT NULL default '0', + `maxduration` int(11) NOT NULL default '0', + `remaintime` int(11) NOT NULL default '0', + `remaincharges` int(11) NOT NULL default '0', + PRIMARY KEY (`guid`,`spell`,`effect_index`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System'; + +-- +-- Dumping data for table `character_aura` +-- + +LOCK TABLES `character_aura` WRITE; +/*!40000 ALTER TABLE `character_aura` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_aura` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `character_declinedname` +-- + +DROP TABLE IF EXISTS `character_declinedname`; +CREATE TABLE `character_declinedname` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `genitive` varchar(15) NOT NULL default '', + `dative` varchar(15) NOT NULL default '', + `accusative` varchar(15) NOT NULL default '', + `instrumental` varchar(15) NOT NULL default '', + `prepositional` varchar(15) NOT NULL default '', + PRIMARY KEY (`guid`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC; + +-- +-- Dumping data for table `character_declinedname` +-- + +LOCK TABLES `character_declinedname` WRITE; +/*!40000 ALTER TABLE `character_declinedname` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_declinedname` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `character_gifts` +-- + +DROP TABLE IF EXISTS `character_gifts`; +CREATE TABLE `character_gifts` ( + `guid` int(20) unsigned NOT NULL default '0', + `item_guid` int(11) unsigned NOT NULL default '0', + `entry` int(20) unsigned NOT NULL default '0', + `flags` int(20) unsigned NOT NULL default '0', + PRIMARY KEY (`item_guid`), + KEY `idx_guid` (`guid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `character_gifts` +-- + +LOCK TABLES `character_gifts` WRITE; +/*!40000 ALTER TABLE `character_gifts` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_gifts` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `character_homebind` +-- + +DROP TABLE IF EXISTS `character_homebind`; +CREATE TABLE `character_homebind` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `map` int(11) unsigned NOT NULL default '0' COMMENT 'Map Identifier', + `zone` int(11) unsigned NOT NULL default '0' COMMENT 'Zone Identifier', + `position_x` float NOT NULL default '0', + `position_y` float NOT NULL default '0', + `position_z` float NOT NULL default '0', + PRIMARY KEY (`guid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System'; + +-- +-- Dumping data for table `character_homebind` +-- + +LOCK TABLES `character_homebind` WRITE; +/*!40000 ALTER TABLE `character_homebind` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_homebind` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `character_instance` +-- + +DROP TABLE IF EXISTS `character_instance`; +CREATE TABLE `character_instance` ( + `guid` int(11) unsigned NOT NULL default '0', + `instance` int(11) unsigned NOT NULL default '0', + `permanent` tinyint(1) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`,`instance`), + KEY `instance` (`instance`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `character_instance` +-- + +LOCK TABLES `character_instance` WRITE; +/*!40000 ALTER TABLE `character_instance` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_instance` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `character_inventory` +-- + +DROP TABLE IF EXISTS `character_inventory`; +CREATE TABLE `character_inventory` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `bag` int(11) unsigned NOT NULL default '0', + `slot` tinyint(3) unsigned NOT NULL default '0', + `item` int(11) unsigned NOT NULL default '0' COMMENT 'Item Global Unique Identifier', + `item_template` int(11) unsigned NOT NULL default '0' COMMENT 'Item Identifier', + PRIMARY KEY (`item`), + KEY `idx_guid` (`guid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System'; + +-- +-- Dumping data for table `character_inventory` +-- + +LOCK TABLES `character_inventory` WRITE; +/*!40000 ALTER TABLE `character_inventory` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_inventory` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `character_pet` +-- + +DROP TABLE IF EXISTS `character_pet`; +CREATE TABLE `character_pet` ( + `id` int(11) unsigned NOT NULL default '0', + `entry` int(11) unsigned NOT NULL default '0', + `owner` int(11) unsigned NOT NULL default '0', + `modelid` int(11) unsigned default '0', + `CreatedBySpell` int(11) unsigned NOT NULL default '0', + `PetType` tinyint(3) unsigned NOT NULL default '0', + `level` int(11) unsigned NOT NULL default '1', + `exp` int(11) unsigned NOT NULL default '0', + `Reactstate` tinyint(1) unsigned NOT NULL default '0', + `loyaltypoints` int(11) NOT NULL default '0', + `loyalty` int(11) unsigned NOT NULL default '0', + `trainpoint` int(11) NOT NULL default '0', + `name` varchar(100) default 'Pet', + `renamed` tinyint(1) unsigned NOT NULL default '0', + `slot` int(11) unsigned NOT NULL default '0', + `curhealth` int(11) unsigned NOT NULL default '1', + `curmana` int(11) unsigned NOT NULL default '0', + `curhappiness` int(11) unsigned NOT NULL default '0', + `savetime` bigint(20) unsigned NOT NULL default '0', + `resettalents_cost` int(11) unsigned NOT NULL default '0', + `resettalents_time` bigint(20) unsigned NOT NULL default '0', + `abdata` longtext, + `teachspelldata` longtext, + PRIMARY KEY (`id`), + KEY `owner` (`owner`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Pet System'; + +-- +-- Dumping data for table `character_pet` +-- + +LOCK TABLES `character_pet` WRITE; +/*!40000 ALTER TABLE `character_pet` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_pet` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `character_pet_declinedname` +-- + +DROP TABLE IF EXISTS `character_pet_declinedname`; +CREATE TABLE `character_pet_declinedname` ( + `id` int(11) unsigned NOT NULL default '0', + `owner` int(11) unsigned NOT NULL default '0', + `genitive` varchar(12) NOT NULL default '', + `dative` varchar(12) NOT NULL default '', + `accusative` varchar(12) NOT NULL default '', + `instrumental` varchar(12) NOT NULL default '', + `prepositional` varchar(12) NOT NULL default '', + PRIMARY KEY (`id`), + KEY owner_key (`owner`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC; + +-- +-- Dumping data for table `character_pet_declinedname` +-- + +LOCK TABLES `character_pet_declinedname` WRITE; +/*!40000 ALTER TABLE `character_pet_declinedname` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_pet_declinedname` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `character_queststatus` +-- + +DROP TABLE IF EXISTS `character_queststatus`; +CREATE TABLE `character_queststatus` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `quest` int(11) unsigned NOT NULL default '0' COMMENT 'Quest Identifier', + `status` int(11) unsigned NOT NULL default '0', + `rewarded` tinyint(1) unsigned NOT NULL default '0', + `explored` tinyint(1) unsigned NOT NULL default '0', + `timer` bigint(20) unsigned NOT NULL default '0', + `mobcount1` int(11) unsigned NOT NULL default '0', + `mobcount2` int(11) unsigned NOT NULL default '0', + `mobcount3` int(11) unsigned NOT NULL default '0', + `mobcount4` int(11) unsigned NOT NULL default '0', + `itemcount1` int(11) unsigned NOT NULL default '0', + `itemcount2` int(11) unsigned NOT NULL default '0', + `itemcount3` int(11) unsigned NOT NULL default '0', + `itemcount4` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`,`quest`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System'; + +-- +-- Dumping data for table `character_queststatus` +-- + +LOCK TABLES `character_queststatus` WRITE; +/*!40000 ALTER TABLE `character_queststatus` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_queststatus` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `character_queststatus_daily` +-- + +DROP TABLE IF EXISTS `character_queststatus_daily`; +CREATE TABLE `character_queststatus_daily` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `quest` int(11) unsigned NOT NULL default '0' COMMENT 'Quest Identifier', + `time` bigint(20) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`,`quest`), + KEY `idx_guid` (`guid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System'; + +-- +-- Dumping data for table `character_queststatus_daily` +-- + +LOCK TABLES `character_queststatus_daily` WRITE; +/*!40000 ALTER TABLE `character_queststatus_daily` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_queststatus_daily` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `character_reputation` +-- + +DROP TABLE IF EXISTS `character_reputation`; +CREATE TABLE `character_reputation` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `faction` int(11) unsigned NOT NULL default '0', + `standing` int(11) NOT NULL default '0', + `flags` int(11) NOT NULL default '0', + PRIMARY KEY (`guid`,`faction`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System'; + +-- +-- Dumping data for table `character_reputation` +-- + +LOCK TABLES `character_reputation` WRITE; +/*!40000 ALTER TABLE `character_reputation` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_reputation` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `character_social` +-- + +DROP TABLE IF EXISTS `character_social`; +CREATE TABLE `character_social` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Character Global Unique Identifier', + `friend` int(11) unsigned NOT NULL default '0' COMMENT 'Friend Global Unique Identifier', + `flags` tinyint(1) unsigned NOT NULL default '0' COMMENT 'Friend Flags', + `note` varchar(48) NOT NULL DEFAULT '' COMMENT 'Friend Note', + PRIMARY KEY (`guid`,`friend`,`flags`), + KEY `guid` (`guid`), + KEY `friend` (`friend`), + KEY `guid_flags` (`guid`,`flags`), + KEY `friend_flags` (`friend`,`flags`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System'; + +-- +-- Dumping data for table `character_social` +-- + +LOCK TABLES `character_social` WRITE; +/*!40000 ALTER TABLE `character_social` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_social` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `character_spell` +-- + +DROP TABLE IF EXISTS `character_spell`; +CREATE TABLE `character_spell` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `spell` int(11) unsigned NOT NULL default '0' COMMENT 'Spell Identifier', + `slot` int(11) unsigned NOT NULL default '0', + `active` tinyint(3) unsigned NOT NULL default '1', + `disabled` tinyint(3) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`,`spell`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System'; + +-- +-- Dumping data for table `character_spell` +-- + +LOCK TABLES `character_spell` WRITE; +/*!40000 ALTER TABLE `character_spell` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_spell` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `character_spell_cooldown` +-- + +DROP TABLE IF EXISTS `character_spell_cooldown`; +CREATE TABLE `character_spell_cooldown` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier, Low part', + `spell` int(11) unsigned NOT NULL default '0' COMMENT 'Spell Identifier', + `item` int(11) unsigned NOT NULL default '0' COMMENT 'Item Identifier', + `time` bigint(20) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`,`spell`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `character_spell_cooldown` +-- + +LOCK TABLES `character_spell_cooldown` WRITE; +/*!40000 ALTER TABLE `character_spell_cooldown` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_spell_cooldown` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `character_ticket` +-- + +DROP TABLE IF EXISTS `character_ticket`; +CREATE TABLE `character_ticket` ( + `ticket_id` int(11) unsigned NOT NULL auto_increment, + `guid` int(11) unsigned NOT NULL default '0', + `ticket_text` text, + `ticket_lastchange` TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`ticket_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System'; + +-- +-- Dumping data for table `character_ticket` +-- + +LOCK TABLES `character_ticket` WRITE; +/*!40000 ALTER TABLE `character_ticket` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_ticket` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `character_tutorial` +-- + +DROP TABLE IF EXISTS `character_tutorial`; +CREATE TABLE `character_tutorial` ( + `account` bigint(20) unsigned NOT NULL auto_increment COMMENT 'Account Identifier', + `realmid` int(11) unsigned NOT NULL default '0' COMMENT 'Realm Identifier', + `tut0` int(11) unsigned NOT NULL default '0', + `tut1` int(11) unsigned NOT NULL default '0', + `tut2` int(11) unsigned NOT NULL default '0', + `tut3` int(11) unsigned NOT NULL default '0', + `tut4` int(11) unsigned NOT NULL default '0', + `tut5` int(11) unsigned NOT NULL default '0', + `tut6` int(11) unsigned NOT NULL default '0', + `tut7` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`account`,`realmid`), + KEY acc_key (`account`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System'; + +-- +-- Dumping data for table `character_tutorial` +-- + +LOCK TABLES `character_tutorial` WRITE; +/*!40000 ALTER TABLE `character_tutorial` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_tutorial` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `corpse` +-- + +DROP TABLE IF EXISTS `corpse`; +CREATE TABLE `corpse` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `player` int(11) unsigned NOT NULL default '0' COMMENT 'Character Global Unique Identifier', + `position_x` float NOT NULL default '0', + `position_y` float NOT NULL default '0', + `position_z` float NOT NULL default '0', + `orientation` float NOT NULL default '0', + `zone` int(11) unsigned NOT NULL default '38' COMMENT 'Zone Identifier', + `map` int(11) unsigned NOT NULL default '0' COMMENT 'Map Identifier', + `data` longtext, + `time` bigint(20) unsigned NOT NULL default '0', + `corpse_type` tinyint(3) unsigned NOT NULL default '0', + `instance` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`), + KEY `idx_type` (`corpse_type`), + KEY `instance` (`instance`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Death System'; + +-- +-- Dumping data for table `corpse` +-- + +LOCK TABLES `corpse` WRITE; +/*!40000 ALTER TABLE `corpse` DISABLE KEYS */; +/*!40000 ALTER TABLE `corpse` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `groups` +-- + +DROP TABLE IF EXISTS `groups`; +CREATE TABLE `groups` ( + `leaderGuid` int(11) unsigned NOT NULL, + `mainTank` int(11) unsigned NOT NULL, + `mainAssistant` int(11) unsigned NOT NULL, + `lootMethod` tinyint(4) unsigned NOT NULL, + `looterGuid` int(11) unsigned NOT NULL, + `lootThreshold` tinyint(4) unsigned NOT NULL, + `icon1` int(11) unsigned NOT NULL, + `icon2` int(11) unsigned NOT NULL, + `icon3` int(11) unsigned NOT NULL, + `icon4` int(11) unsigned NOT NULL, + `icon5` int(11) unsigned NOT NULL, + `icon6` int(11) unsigned NOT NULL, + `icon7` int(11) unsigned NOT NULL, + `icon8` int(11) unsigned NOT NULL, + `isRaid` tinyint(1) unsigned NOT NULL, + `difficulty` tinyint(3) unsigned NOT NULL default '0', + PRIMARY KEY (`leaderGuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Groups'; + +-- +-- Dumping data for table `groups` +-- + +LOCK TABLES `groups` WRITE; +/*!40000 ALTER TABLE `groups` DISABLE KEYS */; +/*!40000 ALTER TABLE `groups` ENABLE KEYS */; +UNLOCK TABLES; + +-- ---------------------------- +-- Table structure for group_instance +-- ---------------------------- +DROP TABLE IF EXISTS `group_instance`; +CREATE TABLE `group_instance` ( + `leaderGuid` int(11) unsigned NOT NULL default '0', + `instance` int(11) unsigned NOT NULL default '0', + `permanent` tinyint(1) unsigned NOT NULL default '0', + PRIMARY KEY (`leaderGuid`,`instance`), + KEY `instance` (`instance`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `group_instance` +-- + +LOCK TABLES `group_instance` WRITE; +/*!40000 ALTER TABLE `group_instance` DISABLE KEYS */; +/*!40000 ALTER TABLE `group_instance` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `group_member` +-- + +DROP TABLE IF EXISTS `group_member`; +CREATE TABLE `group_member` ( + `leaderGuid` int(11) unsigned NOT NULL, + `memberGuid` int(11) unsigned NOT NULL, + `assistant` tinyint(1) unsigned NOT NULL, + `subgroup` smallint(6) unsigned NOT NULL, + PRIMARY KEY (`leaderGuid`,`memberGuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Groups'; + +-- +-- Dumping data for table `group_member` +-- + +LOCK TABLES `group_member` WRITE; +/*!40000 ALTER TABLE `group_member` DISABLE KEYS */; +/*!40000 ALTER TABLE `group_member` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `guild` +-- + +DROP TABLE IF EXISTS `guild`; +CREATE TABLE `guild` ( + `guildid` int(6) unsigned NOT NULL default '0', + `name` varchar(255) NOT NULL default '', + `leaderguid` int(6) unsigned NOT NULL default '0', + `EmblemStyle` int(5) NOT NULL default '0', + `EmblemColor` int(5) NOT NULL default '0', + `BorderStyle` int(5) NOT NULL default '0', + `BorderColor` int(5) NOT NULL default '0', + `BackgroundColor` int(5) NOT NULL default '0', + `info` text NOT NULL, + `motd` varchar(255) NOT NULL default '', + `createdate` datetime default NULL, + `BankMoney` bigint(20) NOT NULL default '0', + PRIMARY KEY (`guildid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Guild System'; + +-- +-- Dumping data for table `guild` +-- + +LOCK TABLES `guild` WRITE; +/*!40000 ALTER TABLE `guild` DISABLE KEYS */; +/*!40000 ALTER TABLE `guild` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `guild_bank_eventlog` +-- + +DROP TABLE IF EXISTS `guild_bank_eventlog`; +CREATE TABLE `guild_bank_eventlog` ( + `guildid` int(11) unsigned NOT NULL default '0', + `LogGuid` int(11) unsigned NOT NULL default '0', + `LogEntry` tinyint(1) unsigned NOT NULL default '0', + `TabId` tinyint(1) unsigned NOT NULL default '0', + `PlayerGuid` int(11) unsigned NOT NULL default '0', + `ItemOrMoney` int(11) unsigned NOT NULL default '0', + `ItemStackCount` tinyint(3) unsigned NOT NULL default '0', + `DestTabId` tinyint(1) unsigned NOT NULL default '0', + `TimeStamp` bigint(20) unsigned NOT NULL default '0', + PRIMARY KEY (`guildid`,`LogGuid`), + KEY `guildid_key` (`guildid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `guild_bank_eventlog` +-- + +LOCK TABLES `guild_bank_eventlog` WRITE; +/*!40000 ALTER TABLE `guild_bank_eventlog` DISABLE KEYS */; +/*!40000 ALTER TABLE `guild_bank_eventlog` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `guild_bank_item` +-- + +DROP TABLE IF EXISTS `guild_bank_item`; +CREATE TABLE `guild_bank_item` ( + `guildid` int(11) unsigned NOT NULL default '0', + `TabId` tinyint(1) unsigned NOT NULL default '0', + `SlotId` tinyint(3) unsigned NOT NULL default '0', + `item_guid` int(11) unsigned NOT NULL default '0', + `item_entry` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`guildid`,`tabid`,`slotid`), + KEY `guildid_key` (`guildid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `guild_bank_item` +-- + +LOCK TABLES `guild_bank_item` WRITE; +/*!40000 ALTER TABLE `guild_bank_item` DISABLE KEYS */; +/*!40000 ALTER TABLE `guild_bank_item` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `guild_bank_right` +-- + +DROP TABLE IF EXISTS `guild_bank_right`; +CREATE TABLE `guild_bank_right` ( + `guildid` int(11) unsigned NOT NULL default '0', + `TabId` tinyint(1) unsigned NOT NULL default '0', + `rid` int(11) unsigned NOT NULL default '0', + `gbright` tinyint(3) unsigned NOT NULL default '0', + `SlotPerDay` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`guildid`,`TabId`,`rid`), + KEY `guildid_key` (`guildid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `guild_bank_right` +-- + +LOCK TABLES `guild_bank_right` WRITE; +/*!40000 ALTER TABLE `guild_bank_right` DISABLE KEYS */; +/*!40000 ALTER TABLE `guild_bank_right` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `guild_bank_tab` +-- + +DROP TABLE IF EXISTS `guild_bank_tab`; +CREATE TABLE `guild_bank_tab` ( + `guildid` int(11) unsigned NOT NULL default '0', + `TabId` tinyint(1) unsigned NOT NULL default '0', + `TabName` varchar(100) NOT NULL default '', + `TabIcon` varchar(100) NOT NULL default '', + `TabText` varchar(500) NOT NULL default '', + PRIMARY KEY (`guildid`,`TabId`), + KEY `guildid_key` (`guildid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `guild_bank_tab` +-- + +LOCK TABLES `guild_bank_tab` WRITE; +/*!40000 ALTER TABLE `guild_bank_tab` DISABLE KEYS */; +/*!40000 ALTER TABLE `guild_bank_tab` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `guild_eventlog` +-- + +DROP TABLE IF EXISTS `guild_eventlog`; +CREATE TABLE `guild_eventlog` ( + `guildid` int(11) NOT NULL COMMENT 'Guild Identificator', + `LogGuid` int(11) NOT NULL COMMENT 'Log entry identificator', + `EventType` tinyint(1) NOT NULL COMMENT 'Event type', + `PlayerGuid1` int(11) NOT NULL COMMENT 'Player 1', + `PlayerGuid2` int(11) NOT NULL COMMENT 'Player 2', + `NewRank` tinyint(2) NOT NULL COMMENT 'New rank(in case promotion/demotion)', + `TimeStamp` bigint(20) NOT NULL COMMENT 'Event UNIX time' +) ENGINE = InnoDB DEFAULT CHARSET = latin1 COMMENT 'Guild Eventlog'; + +-- +-- Dumping data for table `guild_eventlog` +-- + +LOCK TABLES `guild_eventlog` WRITE; +/*!40000 ALTER TABLE `guild_eventlog` DISABLE KEYS */; +/*!40000 ALTER TABLE `guild_eventlog` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `guild_member` +-- + +DROP TABLE IF EXISTS `guild_member`; +CREATE TABLE `guild_member` ( + `guildid` int(6) unsigned NOT NULL default '0', + `guid` int(11) unsigned NOT NULL default '0', + `rank` tinyint(2) unsigned NOT NULL default '0', + `pnote` varchar(255) NOT NULL default '', + `offnote` varchar(255) NOT NULL default '', + `BankResetTimeMoney` int(11) unsigned NOT NULL default '0', + `BankRemMoney` int(11) unsigned NOT NULL default '0', + `BankResetTimeTab0` int(11) unsigned NOT NULL default '0', + `BankRemSlotsTab0` int(11) unsigned NOT NULL default '0', + `BankResetTimeTab1` int(11) unsigned NOT NULL default '0', + `BankRemSlotsTab1` int(11) unsigned NOT NULL default '0', + `BankResetTimeTab2` int(11) unsigned NOT NULL default '0', + `BankRemSlotsTab2` int(11) unsigned NOT NULL default '0', + `BankResetTimeTab3` int(11) unsigned NOT NULL default '0', + `BankRemSlotsTab3` int(11) unsigned NOT NULL default '0', + `BankResetTimeTab4` int(11) unsigned NOT NULL default '0', + `BankRemSlotsTab4` int(11) unsigned NOT NULL default '0', + `BankResetTimeTab5` int(11) unsigned NOT NULL default '0', + `BankRemSlotsTab5` int(11) unsigned NOT NULL default '0', + KEY `guildid_key` (`guildid`), + KEY `guildid_rank_key` (`guildid`,`rank`), + KEY `guid_key` (`guid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Guild System'; + +-- +-- Dumping data for table `guild_member` +-- + +LOCK TABLES `guild_member` WRITE; +/*!40000 ALTER TABLE `guild_member` DISABLE KEYS */; +/*!40000 ALTER TABLE `guild_member` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `guild_rank` +-- + +DROP TABLE IF EXISTS `guild_rank`; +CREATE TABLE `guild_rank` ( + `guildid` int(6) unsigned NOT NULL default '0', + `rid` int(11) unsigned NOT NULL, + `rname` varchar(255) NOT NULL default '', + `rights` int(3) unsigned NOT NULL default '0', + `BankMoneyPerDay` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`guildid`,`rid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Guild System'; + +-- +-- Dumping data for table `guild_rank` +-- + +LOCK TABLES `guild_rank` WRITE; +/*!40000 ALTER TABLE `guild_rank` DISABLE KEYS */; +/*!40000 ALTER TABLE `guild_rank` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `instance` +-- + +DROP TABLE IF EXISTS `instance`; +CREATE TABLE `instance` ( + `id` int(11) unsigned NOT NULL default '0', + `map` int(11) unsigned NOT NULL default '0', + `resettime` bigint(40) NOT NULL default '0', + `difficulty` tinyint(1) unsigned NOT NULL default '0', + `data` longtext, + PRIMARY KEY (`id`), + KEY `map` (`map`), + KEY `resettime` (`resettime`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `instance` +-- + +LOCK TABLES `instance` WRITE; +/*!40000 ALTER TABLE `instance` DISABLE KEYS */; +/*!40000 ALTER TABLE `instance` ENABLE KEYS */; +UNLOCK TABLES; + +-- ---------------------------- +-- Table structure for instance_reset +-- ---------------------------- +DROP TABLE IF EXISTS `instance_reset`; +CREATE TABLE `instance_reset` ( + `mapid` int(11) unsigned NOT NULL default '0', + `resettime` bigint(40) NOT NULL default '0', + PRIMARY KEY (`mapid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `instance_reset` +-- + +LOCK TABLES `instance_reset` WRITE; +/*!40000 ALTER TABLE `instance_reset` DISABLE KEYS */; +/*!40000 ALTER TABLE `instance_reset` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `item_instance` +-- + +DROP TABLE IF EXISTS `item_instance`; +CREATE TABLE `item_instance` ( + `guid` int(11) unsigned NOT NULL default '0', + `owner_guid` int(11) unsigned NOT NULL default '0', + `data` longtext, + PRIMARY KEY (`guid`), + KEY `idx_owner_guid` (`owner_guid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Item System'; + +-- +-- Dumping data for table `item_instance` +-- + +LOCK TABLES `item_instance` WRITE; +/*!40000 ALTER TABLE `item_instance` DISABLE KEYS */; +/*!40000 ALTER TABLE `item_instance` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `item_text` +-- + +DROP TABLE IF EXISTS `item_text`; +CREATE TABLE `item_text` ( + `id` int(11) unsigned NOT NULL default '0', + `text` longtext, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Item System'; + +-- +-- Dumping data for table `item_text` +-- + +LOCK TABLES `item_text` WRITE; +/*!40000 ALTER TABLE `item_text` DISABLE KEYS */; +/*!40000 ALTER TABLE `item_text` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `mail` +-- + +DROP TABLE IF EXISTS `mail`; +CREATE TABLE `mail` ( + `id` int(11) unsigned NOT NULL default '0' COMMENT 'Identifier', + `messageType` tinyint(3) unsigned NOT NULL default '0', + `stationery` tinyint(3) NOT NULL default '41', + `mailTemplateId` mediumint(8) unsigned NOT NULL default '0', + `sender` int(11) unsigned NOT NULL default '0' COMMENT 'Character Global Unique Identifier', + `receiver` int(11) unsigned NOT NULL default '0' COMMENT 'Character Global Unique Identifier', + `subject` longtext, + `itemTextId` int(11) unsigned NOT NULL default '0', + `has_items` tinyint(3) unsigned NOT NULL default '0', + `expire_time` bigint(40) NOT NULL default '0', + `deliver_time` bigint(40) NOT NULL default '0', + `money` int(11) unsigned NOT NULL default '0', + `cod` int(11) unsigned NOT NULL default '0', + `checked` tinyint(3) unsigned NOT NULL default '0', + PRIMARY KEY (`id`), + KEY `idx_receiver` (`receiver`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Mail System'; + +-- +-- Dumping data for table `mail` +-- + +LOCK TABLES `mail` WRITE; +/*!40000 ALTER TABLE `mail` DISABLE KEYS */; +/*!40000 ALTER TABLE `mail` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `mail_items` +-- + +DROP TABLE IF EXISTS `mail_items`; +CREATE TABLE `mail_items` ( + `mail_id` int(11) NOT NULL default '0', + `item_guid` int(11) NOT NULL default '0', + `item_template` int(11) NOT NULL default '0', + `receiver` int(11) unsigned NOT NULL default '0' COMMENT 'Character Global Unique Identifier', + PRIMARY KEY (`mail_id`,`item_guid`), + KEY `idx_receiver` (`receiver`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC; + +-- +-- Dumping data for table `mail_items` +-- + +LOCK TABLES `mail_items` WRITE; +/*!40000 ALTER TABLE `mail_items` DISABLE KEYS */; +/*!40000 ALTER TABLE `mail_items` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `pet_aura` +-- + +DROP TABLE IF EXISTS `pet_aura`; +CREATE TABLE `pet_aura` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `caster_guid` bigint(20) unsigned NOT NULL default '0' COMMENT 'Full Global Unique Identifier', + `spell` int(11) unsigned NOT NULL default '0', + `effect_index` int(11) unsigned NOT NULL default '0', + `amount` int(11) NOT NULL default '0', + `maxduration` int(11) NOT NULL default '0', + `remaintime` int(11) NOT NULL default '0', + `remaincharges` int(11) NOT NULL default '0', + PRIMARY KEY (`guid`,`spell`,`effect_index`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Pet System'; + +-- +-- Dumping data for table `pet_aura` +-- + +LOCK TABLES `pet_aura` WRITE; +/*!40000 ALTER TABLE `pet_aura` DISABLE KEYS */; +/*!40000 ALTER TABLE `pet_aura` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `pet_spell` +-- + +DROP TABLE IF EXISTS `pet_spell`; +CREATE TABLE `pet_spell` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `spell` int(11) unsigned NOT NULL default '0' COMMENT 'Spell Identifier', + `slot` int(11) unsigned NOT NULL default '0', + `active` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`,`spell`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Pet System'; + +-- +-- Dumping data for table `pet_spell` +-- + +LOCK TABLES `pet_spell` WRITE; +/*!40000 ALTER TABLE `pet_spell` DISABLE KEYS */; +/*!40000 ALTER TABLE `pet_spell` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `pet_spell_cooldown` +-- + +DROP TABLE IF EXISTS `pet_spell_cooldown`; +CREATE TABLE `pet_spell_cooldown` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier, Low part', + `spell` int(11) unsigned NOT NULL default '0' COMMENT 'Spell Identifier', + `time` bigint(20) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`,`spell`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `pet_spell_cooldown` +-- + +LOCK TABLES `pet_spell_cooldown` WRITE; +/*!40000 ALTER TABLE `pet_spell_cooldown` DISABLE KEYS */; +/*!40000 ALTER TABLE `pet_spell_cooldown` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `petition` +-- + +DROP TABLE IF EXISTS `petition`; +CREATE TABLE `petition` ( + `ownerguid` int(10) unsigned NOT NULL, + `petitionguid` int(10) unsigned default '0', + `name` varchar(255) NOT NULL default '', + `type` int(10) unsigned NOT NULL default '0', + PRIMARY KEY (`ownerguid`,`type`), + UNIQUE KEY `index_ownerguid_petitionguid` (`ownerguid`,`petitionguid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Guild System'; + +-- +-- Dumping data for table `petition` +-- + +LOCK TABLES `petition` WRITE; +/*!40000 ALTER TABLE `petition` DISABLE KEYS */; +/*!40000 ALTER TABLE `petition` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `petition_sign` +-- + +DROP TABLE IF EXISTS `petition_sign`; +CREATE TABLE `petition_sign` ( + `ownerguid` int(10) unsigned NOT NULL, + `petitionguid` int(11) unsigned NOT NULL default '0', + `playerguid` int(11) unsigned NOT NULL default '0', + `player_account` int(11) unsigned NOT NULL default '0', + `type` int(10) unsigned NOT NULL default '0', + PRIMARY KEY (`petitionguid`,`playerguid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Guild System'; +-- +-- Dumping data for table `petition_sign` +-- + +LOCK TABLES `petition_sign` WRITE; +/*!40000 ALTER TABLE `petition_sign` DISABLE KEYS */; +/*!40000 ALTER TABLE `petition_sign` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2008-01-10 11:37:06 diff --git a/sql/create_mysql.sql b/sql/create_mysql.sql new file mode 100644 index 00000000000..5a39665d7e7 --- /dev/null +++ b/sql/create_mysql.sql @@ -0,0 +1,14 @@ +GRANT USAGE ON * . * TO 'mangos'@'localhost' IDENTIFIED BY 'mangos' WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 ; + +CREATE DATABASE `mangos` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; + +CREATE DATABASE `characters` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; + +CREATE DATABASE `realmd` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; + +GRANT ALL PRIVILEGES ON `mangos` . * TO 'mangos'@'localhost' WITH GRANT OPTION; + +GRANT ALL PRIVILEGES ON `characters` . * TO 'mangos'@'localhost' WITH GRANT OPTION; + +GRANT ALL PRIVILEGES ON `realmd` . * TO 'mangos'@'localhost' WITH GRANT OPTION; + diff --git a/sql/drop_mysql.sql b/sql/drop_mysql.sql new file mode 100644 index 00000000000..4ed3f55472e --- /dev/null +++ b/sql/drop_mysql.sql @@ -0,0 +1,21 @@ +REVOKE ALL PRIVILEGES ON * . * FROM 'mangos'@'localhost'; + +REVOKE ALL PRIVILEGES ON `mangos` . * FROM 'mangos'@'localhost'; + +REVOKE GRANT OPTION ON `mangos` . * FROM 'mangos'@'localhost'; + +REVOKE ALL PRIVILEGES ON `characters` . * FROM 'mangos'@'localhost'; + +REVOKE GRANT OPTION ON `characters` . * FROM 'mangos'@'localhost'; + +REVOKE ALL PRIVILEGES ON `realmd` . * FROM 'mangos'@'localhost'; + +REVOKE GRANT OPTION ON `realmd` . * FROM 'mangos'@'localhost'; + +DELETE FROM `user` WHERE CONVERT( User USING utf8 ) = CONVERT( 'mangos' USING utf8 ) AND CONVERT( Host USING utf8 ) = CONVERT( 'localhost' USING utf8 ) ; + +DROP DATABASE IF EXISTS `mangos` ; + +DROP DATABASE IF EXISTS `characters` ; + +DROP DATABASE IF EXISTS `realmd` ; diff --git a/sql/mangos.sql b/sql/mangos.sql new file mode 100644 index 00000000000..8955a959c69 --- /dev/null +++ b/sql/mangos.sql @@ -0,0 +1,15321 @@ +-- MySQL dump 10.11 +-- +-- Host: localhost Database: mangos +-- ------------------------------------------------------ +-- Server version 5.0.56-nt + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `areatrigger_involvedrelation` +-- + +DROP TABLE IF EXISTS `areatrigger_involvedrelation`; +CREATE TABLE `areatrigger_involvedrelation` ( + `id` mediumint(8) unsigned NOT NULL default '0' COMMENT 'Identifier', + `quest` mediumint(8) unsigned NOT NULL default '0' COMMENT 'Quest Identifier', + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Trigger System'; + +-- +-- Dumping data for table `areatrigger_involvedrelation` +-- + +LOCK TABLES `areatrigger_involvedrelation` WRITE; +/*!40000 ALTER TABLE `areatrigger_involvedrelation` DISABLE KEYS */; +/*!40000 ALTER TABLE `areatrigger_involvedrelation` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `areatrigger_scripts` +-- + +DROP TABLE IF EXISTS `areatrigger_scripts`; +CREATE TABLE `areatrigger_scripts` ( + `entry` MEDIUMINT( 8 ) NOT NULL , + `ScriptName` CHAR( 64 ) NOT NULL , + PRIMARY KEY ( `entry` ) +) ENGINE = MYISAM DEFAULT CHARSET=utf8; + +-- +-- Table structure for table `areatrigger_tavern` +-- + +DROP TABLE IF EXISTS `areatrigger_tavern`; +CREATE TABLE `areatrigger_tavern` ( + `id` mediumint(8) unsigned NOT NULL default '0' COMMENT 'Identifier', + `name` text, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Trigger System'; + +-- +-- Dumping data for table `areatrigger_tavern` +-- + +LOCK TABLES `areatrigger_tavern` WRITE; +/*!40000 ALTER TABLE `areatrigger_tavern` DISABLE KEYS */; +/*!40000 ALTER TABLE `areatrigger_tavern` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `areatrigger_teleport` +-- + +DROP TABLE IF EXISTS `areatrigger_teleport`; +CREATE TABLE `areatrigger_teleport` ( + `id` mediumint(8) unsigned NOT NULL default '0' COMMENT 'Identifier', + `name` text, + `required_level` tinyint(3) unsigned NOT NULL default '0', + `required_item` mediumint(8) unsigned NOT NULL default '0', + `required_item2` mediumint(8) unsigned NOT NULL default '0', + `heroic_key` mediumint(8) unsigned NOT NULL default '0', + `heroic_key2` mediumint(8) unsigned NOT NULL default '0', + `required_quest_done` int(11) unsigned NOT NULL default '0', + `required_failed_text` text, + `target_map` smallint(5) unsigned NOT NULL default '0', + `target_position_x` float NOT NULL default '0', + `target_position_y` float NOT NULL default '0', + `target_position_z` float NOT NULL default '0', + `target_orientation` float NOT NULL default '0', + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Trigger System'; + +-- +-- Dumping data for table `areatrigger_teleport` +-- + +LOCK TABLES `areatrigger_teleport` WRITE; +/*!40000 ALTER TABLE `areatrigger_teleport` DISABLE KEYS */; +/*!40000 ALTER TABLE `areatrigger_teleport` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `battleground_template` +-- + +DROP TABLE IF EXISTS `battleground_template`; +CREATE TABLE `battleground_template` ( + `id` mediumint(8) unsigned NOT NULL, + `MinPlayersPerTeam` smallint(5) unsigned NOT NULL default '0', + `MaxPlayersPerTeam` smallint(5) unsigned NOT NULL default '0', + `MinLvl` tinyint(3) unsigned NOT NULL default '0', + `MaxLvl` tinyint(3) unsigned NOT NULL default '0', + `AllianceStartLoc` mediumint(8) unsigned NOT NULL, + `AllianceStartO` float NOT NULL, + `HordeStartLoc` mediumint(8) unsigned NOT NULL, + `HordeStartO` float NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `battleground_template` +-- + +LOCK TABLES `battleground_template` WRITE; +/*!40000 ALTER TABLE `battleground_template` DISABLE KEYS */; +INSERT INTO `battleground_template` VALUES +(1,0,0,0,0,611,2.72532,610,2.27452), +(2,0,0,0,0,769,3.14159,770,3.14159), +(4,0,2,10,70,929,0,936,3.14159), +(3,0,0,0,0,890,3.40156,889,0.263892), +(5,0,2,10,70,939,0,940,3.14159), +(6,0,2,10,70,0,0,0,0), +(7,0,0,0,0,1103,3.40156,1104,0.263892), +(8,0,2,10,70,1258,0,1259,3.14159); +/*!40000 ALTER TABLE `battleground_template` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `battlemaster_entry` +-- + +DROP TABLE IF EXISTS `battlemaster_entry`; +CREATE TABLE `battlemaster_entry` ( + `entry` mediumint(8) unsigned NOT NULL default '0' COMMENT 'Entry of a creature', + `bg_template` mediumint(8) unsigned NOT NULL default '0' COMMENT 'Battleground template id', + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `battlemaster_entry` +-- + +LOCK TABLES `battlemaster_entry` WRITE; +/*!40000 ALTER TABLE `battlemaster_entry` DISABLE KEYS */; +/*!40000 ALTER TABLE `battlemaster_entry` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `command` +-- + +DROP TABLE IF EXISTS `command`; +CREATE TABLE `command` ( + `name` varchar(50) NOT NULL default '', + `security` tinyint(3) unsigned NOT NULL default '0', + `help` longtext, + PRIMARY KEY (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Chat System'; + +-- +-- Dumping data for table `command` +-- + +LOCK TABLES `command` WRITE; +/*!40000 ALTER TABLE `command` DISABLE KEYS */; +INSERT INTO `command` VALUES +('acct',0,'Syntax: .acct\r\n\r\nDisplay the access level of your account.'), +('additem',3,'Syntax: .additem #itemid/[#itemname]/#shift-click-item-link #itemcount\r\n\r\nAdds the specified number of items of id #itemid (or exact (!) name $itemname in brackets, or link created by shift-click at item in inventory or recipe) to your or selected character inventory. If #itemcount is omitted, only one item will be added.\r\n.'), +('additemset',3,'Syntax: .additemset #itemsetid\r\n\r\nAdd items from itemset of id #itemsetid to your or selected character inventory. Will add by one example each item from itemset.'), +('addmove',2,'Syntax: .addmove #creature_guid [#waittime]\r\n\r\nAdd your current location as a waypoint for creature with guid #creature_guid. And optional add wait time.'), +('announce',1,'Syntax: .announce $MessageToBroadcast\r\n\r\nSend a global message to all players online in chat log.'), +('aura',3,'Syntax: .aura #spellid\r\n\r\nAdd the aura from spell #spellid to the selected Unit.'), +('ban',3,'Syntax is: ban $NameOrIp $bantime $reason\r\nBan account or IP and kick player.\r\n$bantime: negative value leads to permban, otherwise use a timestring like \"4d20h3s\".'), +('baninfo',3,'Syntax is: baninfo \r\nWatch full information about a specific ban.'), +('bank',3,'Syntax: .bank\r\n\r\nShow your bank inventory.'), +('banlist',3,'Syntax is: banlist $NameOrIp\r\nsearches the banlist for a pattern.'), +('cast',3,'Syntax: .cast #spellid [triggered]\r\n Cast #spellid to selected target. If no target selected cast to self. If \'trigered\' or part provided then spell casted with triggered flag.'), +('cast back',3,'Syntax: .cast back #spellid [triggered]\r\n Selected target will cast #spellid to your character. If \'trigered\' or part provided then spell casted with triggered flag.'), +('cast dist',3,'Syntax: .cast dist #spellid [#dist [triggered]]\r\n You will cast spell to pint at distance #dist. If \'trigered\' or part provided then spell casted with triggered flag. Not all spells can be casted as area spells.'), +('cast self',3,'Syntax: .cast self #spellid [triggered]\r\nCast #spellid by target at target itself. If \'trigered\' or part provided then spell casted with triggered flag.'), +('cast target',3,'Syntax: .cast target #spellid [triggered]\r\n Selected target will cast #spellid to his victim. If \'trigered\' or part provided then spell casted with triggered flag.'), +('combatstop',2,'Syntax: .combatstop [$playername]\r\nStop combat for selected character. If selected non-player then command applied to self. If $playername provided then attempt applied to online player $playername.'), +('commands',0,'Syntax: .commands\r\n\r\nDisplay a list of available commands for your account level.'), +('cooldown',3,'Syntax: .cooldown [#spell_id]\r\n\r\nRemove all (if spell_id not provided) or #spel_id spell cooldown from selected character or you (if no selection).'), +('damage',3,'Syntax: .damage $damage_amount [$school [$spellid]]\r\n\r\nApply $damage to target. If not $school and $spellid provided then this flat clean melee damage without any modifiers. If $school provided then damage modified by armor reduction (if school physical), and target absorbing modifiers and result applied as melee damage to target. If spell provided then damage modified and applied as spell damage. $spellid can be shift-link.'), +('debug anim',2,'Syntax: .debug anim #emoteid\r\n\r\nPlay emote #emoteid for your character.'), +('debug getvalue',3,'Syntax: .debug getvalue #field #isInt\r\n\r\nGet the field #field of the selected creature. If no creature is selected, get the content of your field.\r\n\r\nUse a #isInt of value 1 if the expected field content is an integer.'), +('debug playsound',1,'Syntax: .debug playsound #soundid\r\n\r\nPlay sound with #soundid.\r\nSound will be play only for you. Other players do not hear this.\r\nWarning: client may have more 5000 sounds...'), +('debug setvalue',3,'Syntax: .debug setvalue #field #value #isInt\r\n\r\nSet the field #field of the selected creature with value #value. If no creature is selected, set the content of your field.\r\n\r\nUse a #isInt of value 1 if #value is an integer.'), +('debug standstate',2,'Syntax: .debug standstate #emoteid\r\n\r\nChange the emote of your character while standing to #emoteid.'), +('debug update',3,'Syntax: .debug update #field #value\r\n\r\nUpdate the field #field of the selected character or creature with value #value.\r\n\r\nIf no #value is provided, display the content of field #field.'), +('delticket',2,'Syntax: .delticket all\r\n .delticket #num\r\n .delticket $character_name\r\n\rall to dalete all tickets at server, $character_name to delete ticket of this character, #num to delete ticket #num.'), +('demorph',2,'Syntax: .demorph\r\n\r\nDemorph the selected player.'), +('die',3,'Syntax: .die\r\n\r\nKill the selected player. If no player is selected, it will kill you.'), +('dismount',0,'Syntax: .dismount\r\n\r\nDismount you, if you are mounted.'), +('distance',3,'Syntax: .distance\r\n\r\nDisplay the distance from your character to the selected creature.'), +('event',2,'Syntax: .event #event_id\r\nShow details about event with #event_id.'), +('event activelist',2,'Syntax: .event activelist\r\nShow list of currently active events.'), +('event start',2,'Syntax: .event start #event_id\r\nStart event #event_id. Set start time for event to current moment (change not saved in DB).'), +('event stop',2,'Syntax: .event stop #event_id\r\nStop event #event_id. Set start time for event to time in past that make current moment is event stop time (change not saved in DB).'), +('explorecheat',3,'Syntax: .explorecheat #flag\r\n\r\nReveal or hide all maps for the selected player. If no player is selected, hide or reveal maps to you.\r\n\r\nUse a #flag of value 1 to reveal, use a #flag value of 0 to hide all maps.'), +('gm',1,'Syntax: .gm on/off\r\n\r\nEnable or Disable GM MODE'), +('gm fly',3,'Syntax: .gm fly on/off\r\nEnable/disable gm fly mode.'), +('gm list',0,'Syntax: .gm list\r\n\r\nDisplay a list of available Game Masters.'), +('gm visible',1,'Syntax: .gm visible on/off\r\n\r\nOutput current visibility state or make GM visible(on) and invisible(off) for other players.'), +('go creature',2,'Syntax: .go creature #creature_guid\r\nTeleport your character to creature with guid #creature_guid.\r\n.gocreature #creature_name\r\nTeleport your character to creature with this name.\r\n.gocreature id #creature_id\r\nTeleport your character to a creature that was spawned from the template with this entry.\r\n*If* more than one creature is found, then you are teleported to the first that is found inside the database.'), +('go graveyard',2,'Syntax: .go graveyard #graveyardId\r\n Teleport to graveyard with the graveyardId specified.'), +('go grid',1,'Syntax: .go grid #gridX #gridY [#mapId]\r\n\r\nTeleport the gm to center of grid with provided indexes at map #mapId (or current map if it not provided).'), +('go object',1,'Syntax: .go object #object_guid\r\nTeleport your character to gameobject with guid #object_guid'), +('go trigger',2,'Syntax: .go trigger #trigger_id\r\n\r\nTeleport your character to areatrigger with id #trigger_id. Character will be teleported to trigger target if selected areatrigger is telporting trigger.'), +('go xy',1,'Syntax: .go xy #x #y [#mapid]\r\n\r\nTeleport player to point with (#x,#y) coordinates at ground(water) level at map #mapid or same map if #mapid not provided.'), +('go xyz',1,'Syntax: .go xyz #x #y #z [#mapid]\r\n\r\nTeleport player to point with (#x,#y,#z) coordinates at ground(water) level at map #mapid or same map if #mapid not provided.'), +('go zonexy',1,'Syntax: .go zonexy #x #y [#zone]\r\n\r\nTeleport player to point with (#x,#y) client coordinates at ground(water) level in zone #zoneid or current zone if #zoneid not provided. You can look up zone using .lookup area $namepart'), +('gobject add',2,'Syntax: .gobject add #id \r\n\r\nAdd a game object from game object templates to the world at your current location using the #id.\r\nspawntimesecs sets the spawntime, it is optional.\r\n\r\nNote: this is a copy of .gameobject.'), +('gobject delete',2,'Syntax: .gobject delete #go_guid\r\nDelete gameobject with guid #go_guid.'), +('gobject move',2,'Syntax: .gobject move #goguid [#x #y #z]\r\n\r\nMove gameobject #goguid to character coordinates (or to (#x,#y,#z) coordinates if its provide).'), +('gobject near ',3,'Syntax: .gobject near [#distance]\r\n\r\nOutput gameobjects at distance #distance from player. Output gameobject guids and coordinates sorted by distance from character. If #distance not provided use 10 as default value.'), +('gobject turn',2,'Syntax: .gobject turn #goguid \r\n\r\nSet for gameobject #goguid orientation same as current character orientation.'), +('gobject target',2,'Syntax: .gobject target [#go_id|#go_name_part]\r\n\r\nLocate and show position nearest gameobject. If #go_id or #go_name_part provide then locate and show position of nearest gameobject with gameobject template id #go_id or name included #go_name_part as part.'), +('goname',1,'Syntax: .goname $charactername\r\n\r\nTeleport to the given character. Either specify the character name or click on the character\'s portrait, e.g. when you are in a group.'), +('gps',1,'Syntax: .gps\r\n\r\nDisplay the position information for a selected character or creature. Position information includes X, Y, Z, and orientation, map Id and zone Id'), +('groupgo',1,'Syntax: .groupgo $charactername\r\n\r\nTeleport the given character and his group to you.'), +('guid',2,'Syntax: .guid\r\n\r\nDisplay the GUID for the selected character.'), +('guild create',2,'Syntax: .guild create $GuildLeaderName $GuildName\r\n\r\nCreate a guild named $GuildName with the player $GuildLeaderName as leader.'), +('guild delete',2,'Syntax: .guild delete $GuildName\r\n\r\nDelete guild $GuildName.'), +('guild invite',2,'Syntax: .guild invite $CharacterName $GuildName\r\n\r\nAdd $CharacterName into a guild $GuildName.'), +('guild rank',2,'Syntax: .guild rank $CharacterName #Rank\r\n\r\nSet for $CharacterName rank #Rank in a guild.'), +('guild uninvite',2,'Syntax: .guild uninvite $CharacterName\r\n\r\nRemove $CharacterName from a guild.'), +('help',0,'Syntax: .help $command\r\n\r\nDisplay usage instructions for the given $command.'), +('hidearea',3,'Syntax: .hidearea #areaid\r\n\r\nHide the area of #areaid to the selected character. If no character is selected, hide this area to you.'), +('honor add',2,'Syntax: .honor add $amount\r\n\r\nAdd a certain amount of honor (gained today) to the selected player.'), +('honor addkill',2,'Syntax: .honor addkikll\r\n\r\nAdd the targeted unit as one of your pvp kills today (you only get honor if it\'s a racial leader or a player)'), +('honor update',2,'Syntax: .honor update\r\n\r\nForce the yesterday\'s honor fields to be updated with today\'s data, which will get reset for the selected player.'), +('hover',3,'Syntax: .hover #flag\r\n\r\nEnable or disable hover mode for your character.\r\n\r\nUse a #flag of value 1 to enable, use a #flag value of 0 to disable hover.'), +('instance unbind',3,'Syntax: .instance unbind all\r\n All of the selected player\'s binds will be cleared.'), +('instance listbinds',3,'Syntax: .instance listbinds\r\n Lists the binds of the selected player.'), +('instance stats',3,'Syntax: .instance stats\r\n Shows statistics about instances.'), +('instance savedata',3,'Syntax: .instance savedata\r\n Save the InstanceData for the current player\'s map to the DB.'), +('itemmove',2,'Syntax: .itemmove #sourceslotid #destinationslotid\r\n\r\nMove an item from slots #sourceslotid to #destinationslotid in your inventory\r\n\r\nNot yet implemented'), +('kick',2,'Syntax: .kick [$charactername]\r\n\r\nKick the given character name from the world. If no character name is provided then the selected player (except for yourself) will be kicked.'), +('learn',3,'Syntax: .learn #parameter\r\n\r\nSelected character learn a spell of id #parameter.'), +('learn all',3,'Syntax: .learn all\r\n\r\nLearn all big set different spell maybe useful for Administaror.'), +('learn all_crafts',2,'Syntax: .learn crafts\r\n\r\nLearn all professions and recipes.'), +('learn all_default',1,'Syntax: .learn all_default [$playername]\r\n\r\nLearn for selected/$playername player all default spells for his race/class and spells rewarded by completed quests.'), +('learn all_gm',2,'Syntax: .learn all_gm\r\n\r\nLearn all default spells for Game Masters.'), +('learn all_lang',1,'Syntax: .learn all_lang\r\n\r\nLearn all languages'), +('learn all_myclass',3,'Syntax: .learn all_myclass\r\n\r\nLearn all spells and talents available for his class.'), +('learn all_myspells',3,'Syntax: .learn all_myspells\r\n\r\nLearn all spells (except talents and spells with first rank learned as talent) available for his class.'), +('learn all_mytalents',3,'Syntax: .learn all_mytalents\r\n\r\nLearn all talents (and spells with first rank learned as talent) available for his class.'), +('learn all_recipes',2,'Syntax: .learn all_recipes [$profession]\r\rLearns all recipes of specified profession and sets skill level to max.\rExample: .learn all_recipes enchanting'), +('levelup',3,'Syntax: .levelup [$playername] [#numberoflevels]\r\n\r\nIncrease/decrease the level of character with $playername (or the selected if not name provided) by #numberoflevels Or +1 if no #numberoflevels provided). If #numberoflevels is omitted, the level will be increase by 1. If #numberoflevels is 0, the same level will be restarted. If no character is selected and name not provided, increase your level. Command can be used for offline character. All stats and dependent VALUESrecalculated. At level decrease talents can be reset if need. Also at level decrease equipped items with greater level requirement can be lost.'), +('linkgrave',3,'Syntax: .linkgrave #graveyard_id [alliance|horde]\r\n\r\nLink current zone to graveyard for any (or alliance/horde faction ghosts). This let character ghost from zone teleport to graveyard after die if graveyard is nearest from linked to zone and accept ghost of this faction. Add only single graveyard at another map and only if no graveyards linked (or planned linked at same map).'), +('list creature',3,'Syntax: .list creature #creature_id [#max_count]\r\n\r\nOutput creatures with creature id #creature_id found in world. Output creature guids and coordinates sorted by distance from character. Will be output maximum #max_count creatures. If #max_count not provided use 10 as default value.'), +('list item',3,'Syntax: .list item #item_id [#max_count]\r\n\r\nOutput items with item id #item_id found in all character inventories, mails and auctions. Output item guids, item owner guid, owner account and owner name. Will be output maximum #max_count items. If #max_count not provided use 10 as default value.'), +('list object',3,'Syntax: .list object #gameobject_id [#max_count]\r\n\r\nOutput gameobjects with gameobject id #gameobject_id found in world. Output gameobject guids and coordinates sorted by distance from character. Will be output maximum #max_count gameobject. If #max_count not provided use 10 as default value.'), +('loadscripts',3,'Syntax: .loadscripts $scriptlibraryname\r\n\r\nUnload current and load the script library $scriptlibraryname or reload current if $scriptlibraryname omitted, in case you changed it while the server was running.'), +('lockaccount',0,'Syntax: .lockaccount [on|off]\r\n\r\nAllow login from account only from current used IP or remove this requirement.'), +('lookup area',1,'Syntax: .lookup area $namepart\r\n\r\nLooks up an area by $namepart, and returns all matches with their area ID\'s.'), +('lookup creature',3,'Syntax: .lookup creature $namepart\r\n\r\nLooks up a creature by $namepart, and returns all matches with their creature ID\'s.'), +('lookup event',2,'Syntax: .lookup event $name\r\nAttempts to find the ID of the event with the provided $name.'), +('lookup faction',3,'Syntax: .lookup faction $name\r\nAttempts to find the ID of the faction with the provided $name.'), +('lookup item',3,'Syntax: .lookup item $itemname\r\n\r\nLooks up an item by $itemname, and returns all matches with their Item ID\'s.'), +('lookup itemset',3,'Syntax: .lookup itemset $itemname\r\n\r\nLooks up an item set by $itemname, and returns all matches with their Item set ID\'s.'), +('lookup object',3,'Syntax: .lookup object $objname\r\n\r\nLooks up an gameobject by $objname, and returns all matches with their Gameobject ID\'s.'), +('lookup quest',3,'Syntax: .lookup quest $namepart\r\n\r\nLooks up a quest by $namepart, and returns all matches with their quest ID\'s.'), +('lookup skill',3,'Syntax: .lookup skill $$namepart\r\n\r\nLooks up a skill by $namepart, and returns all matches with their skill ID\'s.'), +('lookup spell',3,'Syntax: .lookup spell $namepart\r\n\r\nLooks up a spell by $namepart, and returns all matches with their spell ID\'s.'), +('lookup tele',1,'Syntax: .lookup tele $substring\r\n\r\nSearch and output all .tele command locations with provide $substring in name.'), +('maxskill',3,'Syntax: .maxskill\r\nSets all skills of the targeted player to their maximum VALUESfor its current level.'), +('Mod32Value',3,'Syntax: .Mod32Value #field #value\r\n\r\nAdd #value to field #field of your character.'), +('modify arena',3,'Syntax: .modify arena #value\r\nAdd $amount arena points to the selected player.'), +('modify aspeed',1,'Syntax: .modify aspeed #rate\r\n\r\nModify all speeds -run,swim,run back,swim back- of the selected player to \"normalbase speed for this move type\"*rate. If no player is selected, modify your speed.\r\n\r\n #rate may range from 0.1 to 10.'), +('modify bit',1,'Syntax: .modify bit #field #bit\r\n\r\nToggle the #bit bit of the #field field for the selected player. If no player is selected, modify your character.'), +('modify bwalk',1,'Syntax: .modify bwalk #rate\r\n\r\nModify the speed of the selected player while running backwards to \"normal walk back speed\"*rate. If no player is selected, modify your speed.\r\n\r\n #rate may range from 0.1 to 10.'), +('modify drunk',1,'Syntax: .modify drunk #value\r\n Set drunk level to #value (0..100). Value 0 remove drunk state, 100 is max drunked state.'), +('modify energy',1,'Syntax: .modify energy #energy\r\n\r\nModify the energy of the selected player. If no player is selected, modify your energy.'), +('modify faction',1,'Syntax: .modify faction #factionid #flagid #npcflagid #dynamicflagid\r\n\r\nModify the faction and flags of the selected creature. Without arguments, display the faction and flags of the selected creature.'), +('modify honor',1,'Syntax: .modify honor $amount\r\n\r\nAdd $amount honor points to the selected player.'), +('modify hp',1,'Syntax: .modify hp #newhp\r\n\r\nModify the hp of the selected player. If no player is selected, modify your hp.'), +('modify mana',1,'Syntax: .modify mana #newmana\r\n\r\nModify the mana of the selected player. If no player is selected, modify your mana.'), +('modify money',1,'Syntax:\r\n.modify money #money\r\n.money #money\r\n\r\nAdd or remove money to the selected player. If no player is selected, modify your money.\r\n\r\n #gold can be negative to remove money.'), +('modify morph',2,'Syntax: .modify morph #displayid\r\n\r\nChange your current model id to #displayid.'), +('modify mount',1,'Syntax:\r\n.modify mount #id #speed\r\nDisplay selected player as mounted at #id creature and set speed to #speed value.'), +('modify rage',1,'Syntax: .modify rage #newrage\r\n\r\nModify the rage of the selected player. If no player is selected, modify your rage.'), +('modify rep',2,'Syntax: .modify rep #repId (#repvalue | $rankname [#delta])\r\nSets the selected players reputation with faction #repId to #repvalue or to $reprank.\r\nIf the reputation rank name is provided, the resulting reputation will be the lowest reputation for that rank plus the delta amount, if specified.\r\nYou can use \'.pinfo rep\' to list all known reputation ids, or use \'.lookup faction $name\' to locate a specific faction id.'), +('modify scale',1,''), +('modify speed',1,'Syntax:\r\n.modify speed #rate\r\n.speed #rate\r\n\r\nModify the running speed of the selected player to \"normal base run speed\"*rate. If no player is selected, modify your speed.\r\n\r\n #rate may range from 0.1 to 10.'), +('modify spell',1,''), +('modify swim',1,'Syntax: .modify swim #rate\r\n\r\nModify the swim speed of the selected player to \"normal swim speed\"*rate. If no player is selected, modify your speed.\r\n\r\n #rate may range from 0.1 to 10.'), +('modify titles',1,'Syntax:\r\n.modify titles #mask\r\n\r\nAllows user to use all titles from #mask.\r\n\r\n #mask=0 disables the title-choose-field'), +('movegens',3,'Syntax: .movegens\r\n Show movement generators stack for selected creature or player.'), +('mute',1,'Syntax: .mute $playerName $timeInMinutes\r\n\r\nDisible chat messaging for any character from account of character $playerName at $timeInMinutes minutes.'), +('namego',1,'Syntax: .namego $charactername\r\n\r\nTeleport the given character to you.'), +('neargrave',3,'Syntax: .neargrave [alliance|horde]\r\n\r\nFind nearest graveyard linked to zone (or only nearest from accepts alliance or horde faction ghosts).'), +('notify',1,'Syntax: .notify $MessageToBroadcast\r\n\r\nSend a global message to all players online in screen.'), +('npc add',2,'Syntax: .npc add #creatureid\r\n\r\nSpawn a creature by the given template id of #creatureid.'), +('npc additem',2,'Syntax: .npc additem #itemId <#maxcount><#incrtime><#extendedcost>r\r\n\r\nAdd item #itemid to item list of selected vendor. Also optionally set max count item in vendor item list and time to item count restoring and items ExtendedCost.'), +('npc addweapon',3,'Not yet implemented.'), +('npc allowmove',3,'Syntax: .npc allowmove\r\n\r\nEnable or disable movement for the selected creature.'), +('npc changelevel',2,'Syntax: .npc changelevel #level\r\n\r\nChange the level of the selected creature to #level.\r\n\r\n#level may range from 1 to 63.'), +('npc delete',2,'Syntax: .npc delete [#guid]\r\n\r\nDelete creature with guid #guid (or the selected if no guid is provided)'), +('npc delitem',2,'Syntax: .npc delitem #itemId\r\n\r\nRemove item #itemid from item list of selected vendor.'), +('npc factionid',2,'Syntax: .npc factionid #factionid\r\n\r\nSet the faction of the selected creature to #factionid.'), +('npc flag',2,'Syntax: .npc flag #npcflag\r\n\r\nSet the NPC flags of creature template of the selected creature and selected creature to #npcflag. NPC flags will applied to all creatures of selected creature template after server restart or grid unload/load.'), +('npc info',3,'Syntax: .npc info\r\n\r\nDisplay a list of details for the selected creature.\r\n\r\nThe list includes:\r\n- GUID, Faction, NPC flags, Entry ID, Model ID,\r\n- Level,\r\n- Health (current/maximum),\r\n\r\n- Field flags, dynamic flags, faction template, \r\n- Position information,\r\n- and the creature type, e.g. if the creature is a vendor.'), +('npc move',2,'Syntax: .npc move [#creature_guid]\r\n\r\nMove the targeted creature spawn point to your coordinates.'), +('npc name',2,'Syntax: .npc name $name\r\n\r\nChange the name of the selected creature or character to $name.\r\n\r\nCommand disabled.'), +('npc playemote',3,'Syntax: .npc playemote #emoteid\r\n\r\nMake the selected creature emote with an emote of id #emoteid.'), +('npc setmodel',2,'Syntax: .npc setmodel #displayid\r\n\r\nChange the model id of the selected creature to #displayid.'), +('npc setmovetype',2,'Syntax: .npc setmovetype [#creature_guid] stay/random/way [NODEL]\r\n\r\nSet for creature pointed by #creature_guid (or selected if #creature_guid not provided) movement type and move it to respawn position (if creature alive). Any existing waypoints for creature will be removed from the database if you do not use NODEL. If the creature is dead then movement type will applied at creature respawn.\r\nMake sure you use NODEL, if you want to keep the waypoints.'), +('npc spawndist',2,'Syntax: .npc spawndist #dist\r\n\r\nAdjust spawndistance of selected creature to dist.'), +('npc spawntime',2,'Syntax: .npc spawntime #time \r\n\r\nAdjust spawntime of selected creature to time.'), +('npc subname',2,'Syntax: .npc subname $Name\r\n\r\nChange the subname of the selected creature or player to $Name.\r\n\r\nCommand disabled.'), +('npc textemote',3,'Syntax: .npc textemote #emoteid\r\n\r\nMake the selected creature to do textemote with an emote of id #emoteid.'), +('npc whisper',1,'Syntax: .npc whisper #playerguid #text\r\nMake the selected npc whisper #text to #playerguid.'), +('password',0,'Syntax: .password $old_password $new_password $new_password\r\n\r\nChange your account password.'), +('pinfo',2,'Syntax: .pinfo [$player_name] [rep]\r\n\r\nOutput account information for selected player or player find by $player_name. If \"rep\" parameter provided show reputation information for player.'), +('plimit',3,'Syntax: .plimit [#num|-1|-2|-3|reset|player|moderator|gamemaster|administrator]\r\n\r\nWithout arg show current player amount and security level limitations for login to server, with arg set player linit ($num > 0) or securiti limitation ($num < 0 or security leme name. With `reset` sets player limit to the one in the config file'), +('quest add',3,'Syntax: .quest add #quest_id\r\n\r\nAdd to character quest log quest #quest_id. Quest started from item can\'t be added by this command but correct .additem call provided in command output.'), +('quest complete',3,'Syntax: .quest complete #questid\r\nMark all quest objectives as completed for target character active quest. After this target character can go and get quest reward.'), +('quest remove',3,'Syntax: .quest remove #quest_id\r\n\r\nSet quest #quest_id state to not completed and not active (and remove from active quest list) for selected player.'), +('recall',1,'Syntax: .recall [$playername]\r\n\r\nTeleport $playername or selected player to the place where he has been before last use of a teleportation command. If no $playername is entered and no player is selected, it will teleport you.'), +('reload',3,'Syntax: .reload table_name\r\n\r\nReload table `table_name` if reload support added for this table and this table can be _safe_ reloaded.'), +('reload all',3,'Syntax: .reload all\r\n\r\nReload all tables with reload support added and that can be _safe_ reloaded.'), +('reload all_area',3,'Syntax: .reload all_area\r\n\r\nReload all `areatrigger_*` tables if reload support added for this table and this table can be _safe_ reloaded.'), +('reload all_loot',3,'Syntax: .reload all_loot\r\n\r\nReload all `*_loot_template` tables. This can be slow operation with lags for server run.'), +('reload all_quest',3,'Syntax: .reload all_quest\r\n\r\nReload all quest related tables if reload support added for this table and this table can be _safe_ reloaded.'), +('reload all_spell',3,'Syntax: .reload all\r\n\r\nReload all `spell_*` tables with reload support added and that can be _safe_ reloaded.'), +('reload config',3,'Syntax: .reload config\r\n\r\nReload config settings (by default stored in mangosd.conf). Not all settings can be change at reload: some new setting values will be ignored until restart, some values will applied with delay or only to new objects/maps, some values will explicitly rejected to change at reload.'), +('reset all',3,'Syntax: .reset all spells\r\n\r\nSyntax: .reset all talents\r\n\r\nRequest reset spells or talents at next login each existed character.'), +('reset honor',3,'Syntax:\r\n.reset honor [Playername]\r\n Reset all honor data for targeted character.'), +('reset level',3,'Syntax:\r\n.reset level [Playername]\r\n Reset level to 1 including reset stats and talents. Equipped items with greater level requirement can be lost.'), +('reset spells',3,'Syntax:\r\n.reset spells [Playername]\r\n Removes all non-original spells from spellbook.\r\n. Playername can be name of offline character.'), +('reset stats',3,'Syntax:\r\n.reset stats [Playername]\r\n Resets(recalculate) all stats of the targeted player to their original VALUESat current level.'), +('reset talents',3,'Syntax:\r\n.reset talents [Playername]\r\n Removes all talents of the targeted player. Playername can be name of offline character.'), +('respawn',3,'Syntax: .respawn\r\n\r\nRespawn all nearest creatures and GO without waiting respawn time expiration.'), +('revive',3,'Syntax: .revive\r\n\r\nRevive the selected player. If no player is selected, it will revive you.'), +('save',0,'Syntax: .save\r\n\r\nSaves your character.'), +('saveall',1,'Syntax: .saveall\r\n\r\nSave all characters in game.'), +('security',3,'Syntax: .security $name #level\r\n\r\nSet the security level of player $name to a level of #level.\r\n\r\n#level may range from 0 to 5.'), +('sendmail',1,'Syntax: .sendmail #playername #subject #text\r\n\r\nSend a mail to a player. Note: subject may not contain spaces.'), +('server info',0,'Syntax: .server info\r\n\r\nDisplay server version and the number of connected players.'), +('server idleshutdown',3,'Syntax: .server idleshutdown #delay|cancel\r\n\r\nShut the server down after #delay seconds if no active connections are present (no players) or cancel the restart/shutdown if cancel value is used.'), +('server idlerestart',3,'Syntax: .server idlerestart #delay|cancel\r\n\r\nRestart the server after #delay seconds if no active connections are present (no players) or cancel the restart/shutdown if cancel value is used.'), +('server restart',3,'Syntax: .server restart seconds\r\n\r\nRestart the server after given seconds and show "Restart server in X" or cancel the restart/shutdown if cancel value is used.'), +('server shutdown',3,'Syntax: .server shutdown seconds\r\n\r\nShut the server down after given seconds and show "Off server in X" or cancel the restart/shutdown if cancel value is used.'), +('setskill',3,'Syntax: .setskill #skill #level [#max]\r\n\r\nSet a skill of id #skill with a current skill value of #level and a maximum value of #max (or equal current maximum if not provide) for the selected character. If no character is selected, you learn the skill.'), +('showarea',3,'Syntax: .showarea #areaid\r\n\r\nReveal the area of #areaid to the selected character. If no character is selected, reveal this area to you.'), +('start',0,'Syntax: .start\r\n\r\nTeleport you to the starting area of your character.'), +('taxicheat',1,'Syntax: .taxicheat on/off\r\n\r\nTemporary grant access or remove to all taxi routes for the selected character. If no character is selected, hide or reveal all routes to you.\r\n\r\nVisited taxi nodes sill accessible after removing access.'), +('tele',1,'Syntax: .tele #location\r\n\r\nTeleport player to a given location.'), +('tele add',3,'Syntax: .tele add $name\r\n\r\nAdd current your position to .tele command target locations list with name $name.'), +('tele del',3,'Syntax: .tele del $name\r\n\r\nRemove location with name $name for .tele command locations list.'), +('tele group',1,'Syntax: .tele group#location\r\n\r\nTeleport a selected player and his group members to a given location.'), +('tele name',1,'Syntax: .tele name #playername #location\r\n\r\nTeleport a player to a given location.'), +('ticket',2,'Syntax: .ticket on\r\n .ticket off\r\n .ticket #num\r\n .ticket $character_name\r\n\r\non/off for GMs to show or not a new ticket directly, $character_name to show ticket of this character, #num to show ticket #num.'), +('transport',3,'Not yet implemented.'), +('unaura',3,'Syntax: .unaura #spellid\r\n\r\nRemove aura due to spell #spellid from the selected Unit.'), +('unban',3,'Syntax is: unban $NameOrIp\r\nUnban account or IP.'), +('unlearn',3,'Syntax: .unlearn #startspell #endspell\r\n\r\nUnlearn for selected player the range of spells between id #startspell and #endspell. If no #endspell is provided, just unlearn spell of id #startspell.'), +('unmute',1,'Syntax: .unmute $playerName\r\n\r\nRestore chat messaging for any character from account of character $playerName.'), +('wchange',3,'Syntax: .wchange #weathertype #status\r\n\r\nSet current weather to #weathertype with an intensity of #status.\r\n\r\n#weathertype can be 1 for rain, 2 for snow, and 3 for sand. #status can be 0 for disabled, and 1 for enabled.'), +('whispers',1,'Syntax: .whispers on|off\r\nEnable/disable accepting whispers by GM from players. By default use mangosd.conf setting.'), +('wp',2,'Using WP Command:\r\nEach Waypoint Command has it\'s own description!'), +('wp add',2,'Syntax: .wp add [#creature_guid or Select a Creature]'), +('wp export',3,'Syntax: .wp export [#creature_guid or Select a Creature] $filename'), +('wp import',3,'Syntax: .wp import $filename'), +('wp modify',2,'Syntax: .wp modify [#creature_guid or Select a Creature]\r\nadd - Add a waypoint after the selected visual\r\nwaittime $time\r\nemote ID\r\nspell ID\r\ntext1| text2| text3| text4| text5 \r\nmodel1 ID\r\nmodel2 ID\r\nmove(moves wp to player pos)\r\ndel (deletes the wp)\r\n\r\nOnly one parameter per time!'), +('wp show',2,'Syntax: .wp show [#creature_guid or Select a Creature]\r\non\r\nfirst\r\nlast\r\noff\r\ninfo\r\n\r\nFor using info you have to do first show on and than select a Visual-Waypoint and do the show info!'); +/*!40000 ALTER TABLE `command` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `creature` +-- + +DROP TABLE IF EXISTS `creature`; +CREATE TABLE `creature` ( + `guid` int(10) unsigned NOT NULL auto_increment COMMENT 'Global Unique Identifier', + `id` mediumint(8) unsigned NOT NULL default '0' COMMENT 'Creature Identifier', + `map` smallint(5) unsigned NOT NULL default '0' COMMENT 'Map Identifier', + `spawnMask` tinyint(3) unsigned NOT NULL default '1', + `modelid` mediumint(8) unsigned NOT NULL default '0', + `equipment_id` mediumint(9) NOT NULL default '0', + `position_x` float NOT NULL default '0', + `position_y` float NOT NULL default '0', + `position_z` float NOT NULL default '0', + `orientation` float NOT NULL default '0', + `spawntimesecs` int(10) unsigned NOT NULL default '120', + `spawndist` float NOT NULL default '5', + `currentwaypoint` mediumint(8) unsigned NOT NULL default '0', + `curhealth` int(10) unsigned NOT NULL default '1', + `curmana` int(10) unsigned NOT NULL default '0', + `DeathState` tinyint(3) unsigned NOT NULL default '0', + `MovementType` tinyint(3) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`), + KEY `idx_map` (`map`), + KEY `index_id` (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Creature System'; + +-- +-- Dumping data for table `creature` +-- + +LOCK TABLES `creature` WRITE; +/*!40000 ALTER TABLE `creature` DISABLE KEYS */; +/*!40000 ALTER TABLE `creature` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `creature_addon` +-- + +DROP TABLE IF EXISTS `creature_addon`; +CREATE TABLE `creature_addon` ( + `guid` int(11) NOT NULL default '0', + `mount` mediumint(8) unsigned NOT NULL default '0', + `bytes0` int(10) unsigned NOT NULL default '0', + `bytes1` int(10) unsigned NOT NULL default '0', + `bytes2` int(10) unsigned NOT NULL default '0', + `emote` int(10) unsigned NOT NULL default '0', + `moveflags` int(10) unsigned NOT NULL default '0', + `auras` text, + PRIMARY KEY (`guid`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `creature_addon` +-- + +LOCK TABLES `creature_addon` WRITE; +/*!40000 ALTER TABLE `creature_addon` DISABLE KEYS */; +/*!40000 ALTER TABLE `creature_addon` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `creature_equip_template` +-- + +DROP TABLE IF EXISTS `creature_equip_template`; +CREATE TABLE `creature_equip_template` ( + `entry` mediumint(8) unsigned NOT NULL default '0' COMMENT 'Unique entry', + `equipmodel1` mediumint(8) unsigned NOT NULL default '0', + `equipmodel2` mediumint(8) unsigned NOT NULL default '0', + `equipmodel3` mediumint(8) unsigned NOT NULL default '0', + `equipinfo1` int(10) unsigned NOT NULL default '0', + `equipinfo2` int(10) unsigned NOT NULL default '0', + `equipinfo3` int(10) unsigned NOT NULL default '0', + `equipslot1` int(11) NOT NULL default '0', + `equipslot2` int(11) NOT NULL default '0', + `equipslot3` int(11) NOT NULL default '0', + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Creature System (Equipment)'; + +-- +-- Dumping data for table `creature_equip_template` +-- + +LOCK TABLES `creature_equip_template` WRITE; +/*!40000 ALTER TABLE `creature_equip_template` DISABLE KEYS */; +/*!40000 ALTER TABLE `creature_equip_template` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `creature_involvedrelation` +-- + +DROP TABLE IF EXISTS `creature_involvedrelation`; +CREATE TABLE `creature_involvedrelation` ( + `id` mediumint(8) unsigned NOT NULL default '0' COMMENT 'Identifier', + `quest` mediumint(8) unsigned NOT NULL default '0' COMMENT 'Quest Identifier', + PRIMARY KEY (`id`,`quest`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Creature System'; + +-- +-- Dumping data for table `creature_involvedrelation` +-- + +LOCK TABLES `creature_involvedrelation` WRITE; +/*!40000 ALTER TABLE `creature_involvedrelation` DISABLE KEYS */; +/*!40000 ALTER TABLE `creature_involvedrelation` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `creature_loot_template` +-- + +DROP TABLE IF EXISTS `creature_loot_template`; +CREATE TABLE `creature_loot_template` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `item` mediumint(8) unsigned NOT NULL default '0', + `ChanceOrQuestChance` float NOT NULL default '100', + `groupid` tinyint(3) unsigned NOT NULL default '0', + `mincountOrRef` mediumint(9) NOT NULL default '1', + `maxcount` tinyint(3) unsigned NOT NULL default '1', + `lootcondition` tinyint(3) unsigned NOT NULL default '0', + `condition_value1` mediumint(8) unsigned NOT NULL default '0', + `condition_value2` mediumint(8) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`,`item`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Loot System'; + +-- +-- Dumping data for table `creature_loot_template` +-- + +LOCK TABLES `creature_loot_template` WRITE; +/*!40000 ALTER TABLE `creature_loot_template` DISABLE KEYS */; +/*!40000 ALTER TABLE `creature_loot_template` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `creature_model_info` +-- + +DROP TABLE IF EXISTS `creature_model_info`; +CREATE TABLE `creature_model_info` ( + `modelid` mediumint(8) unsigned NOT NULL default '0', + `bounding_radius` float NOT NULL default '0', + `combat_reach` float NOT NULL default '0', + `gender` tinyint(3) unsigned NOT NULL default '2', + `modelid_other_gender` mediumint(8) unsigned NOT NULL default '0', + PRIMARY KEY (`modelid`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Creature System (Model related info)'; + +-- +-- Dumping data for table `creature_model_info` +-- + +LOCK TABLES `creature_model_info` WRITE; +/*!40000 ALTER TABLE `creature_model_info` DISABLE KEYS */; +/*!40000 ALTER TABLE `creature_model_info` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `creature_movement` +-- + +DROP TABLE IF EXISTS `creature_movement`; +CREATE TABLE `creature_movement` ( + `id` int(10) unsigned NOT NULL COMMENT 'Creature GUID', + `point` mediumint(8) unsigned NOT NULL default '0', + `position_x` float NOT NULL default '0', + `position_y` float NOT NULL default '0', + `position_z` float NOT NULL default '0', + `waittime` int(10) unsigned NOT NULL default '0', + `text1` text, + `text2` text, + `text3` text, + `text4` text, + `text5` text, + `emote` mediumint(8) unsigned NOT NULL default '0', + `spell` mediumint(8) unsigned NOT NULL default '0', + `wpguid` int(11) NOT NULL default '0', + `orientation` float NOT NULL default '0', + `model1` mediumint(9) NOT NULL default '0', + `model2` mediumint(9) NOT NULL default '0', + PRIMARY KEY (`id`,`point`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Creature System'; + +-- +-- Dumping data for table `creature_movement` +-- + +LOCK TABLES `creature_movement` WRITE; +/*!40000 ALTER TABLE `creature_movement` DISABLE KEYS */; +/*!40000 ALTER TABLE `creature_movement` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `creature_onkill_reputation` +-- + +DROP TABLE IF EXISTS `creature_onkill_reputation`; +CREATE TABLE `creature_onkill_reputation` ( + `creature_id` mediumint(8) unsigned NOT NULL default '0' COMMENT 'Creature Identifier', + `RewOnKillRepFaction1` smallint(6) NOT NULL default '0', + `RewOnKillRepFaction2` smallint(6) NOT NULL default '0', + `MaxStanding1` tinyint(4) NOT NULL default '0', + `IsTeamAward1` tinyint(4) NOT NULL default '0', + `RewOnKillRepValue1` mediumint(9) NOT NULL default '0', + `MaxStanding2` tinyint(4) NOT NULL default '0', + `IsTeamAward2` tinyint(4) NOT NULL default '0', + `RewOnKillRepValue2` mediumint(9) NOT NULL default '0', + `TeamDependent` tinyint(3) unsigned NOT NULL default '0', + PRIMARY KEY (`creature_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Creature OnKill Reputation gain'; + +-- +-- Dumping data for table `creature_onkill_reputation` +-- + +LOCK TABLES `creature_onkill_reputation` WRITE; +/*!40000 ALTER TABLE `creature_onkill_reputation` DISABLE KEYS */; +/*!40000 ALTER TABLE `creature_onkill_reputation` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `creature_questrelation` +-- + +DROP TABLE IF EXISTS `creature_questrelation`; +CREATE TABLE `creature_questrelation` ( + `id` mediumint(8) unsigned NOT NULL default '0' COMMENT 'Identifier', + `quest` mediumint(8) unsigned NOT NULL default '0' COMMENT 'Quest Identifier', + PRIMARY KEY (`id`,`quest`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Creature System'; + +-- +-- Dumping data for table `creature_questrelation` +-- + +LOCK TABLES `creature_questrelation` WRITE; +/*!40000 ALTER TABLE `creature_questrelation` DISABLE KEYS */; +/*!40000 ALTER TABLE `creature_questrelation` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `creature_respawn` +-- + +DROP TABLE IF EXISTS `creature_respawn`; +CREATE TABLE `creature_respawn` ( + `guid` int(10) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `respawntime` bigint(20) NOT NULL default '0', + `instance` mediumint(8) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`,`instance`), + KEY `instance` (`instance`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Grid Loading System'; + +-- +-- Dumping data for table `creature_respawn` +-- + +LOCK TABLES `creature_respawn` WRITE; +/*!40000 ALTER TABLE `creature_respawn` DISABLE KEYS */; +/*!40000 ALTER TABLE `creature_respawn` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `creature_template` +-- + +DROP TABLE IF EXISTS `creature_template`; +CREATE TABLE `creature_template` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `heroic_entry` mediumint(8) unsigned NOT NULL default '0', + `modelid_A` mediumint(8) unsigned NOT NULL default '0', + `modelid_A2` mediumint(8) unsigned NOT NULL default '0', + `modelid_H` mediumint(8) unsigned NOT NULL default '0', + `modelid_H2` mediumint(8) unsigned NOT NULL default '0', + `name` char(100) NOT NULL default '0', + `subname` char(100) default NULL, + `IconName` char(100) default NULL, + `minlevel` tinyint(3) unsigned NOT NULL default '1', + `maxlevel` tinyint(3) unsigned NOT NULL default '1', + `minhealth` int(10) unsigned NOT NULL default '0', + `maxhealth` int(10) unsigned NOT NULL default '0', + `minmana` int(10) unsigned NOT NULL default '0', + `maxmana` int(10) unsigned NOT NULL default '0', + `armor` mediumint(8) unsigned NOT NULL default '0', + `faction_A` smallint(5) unsigned NOT NULL default '0', + `faction_H` smallint(5) unsigned NOT NULL default '0', + `npcflag` int(10) unsigned NOT NULL default '0', + `speed` float NOT NULL default '1', + `scale` float NOT NULL default '1', + `rank` tinyint(3) unsigned NOT NULL default '0', + `mindmg` float NOT NULL default '0', + `maxdmg` float NOT NULL default '0', + `dmgschool` tinyint(4) NOT NULL default '0', + `attackpower` int(10) unsigned NOT NULL default '0', + `baseattacktime` int(10) unsigned NOT NULL default '0', + `rangeattacktime` int(10) unsigned NOT NULL default '0', + `flags` int(10) unsigned NOT NULL default '0', + `dynamicflags` int(10) unsigned NOT NULL default '0', + `family` tinyint(4) NOT NULL default '0', + `trainer_type` tinyint(4) NOT NULL default '0', + `trainer_spell` mediumint(8) unsigned NOT NULL default '0', + `class` tinyint(3) unsigned NOT NULL default '0', + `race` tinyint(3) unsigned NOT NULL default '0', + `minrangedmg` float NOT NULL default '0', + `maxrangedmg` float NOT NULL default '0', + `rangedattackpower` smallint(5) unsigned NOT NULL default '0', + `type` tinyint(3) unsigned NOT NULL default '0', + `flag1` int(10) unsigned NOT NULL default '0', + `lootid` mediumint(8) unsigned NOT NULL default '0', + `pickpocketloot` mediumint(8) unsigned NOT NULL default '0', + `skinloot` mediumint(8) unsigned NOT NULL default '0', + `resistance1` smallint(5) NOT NULL default '0', + `resistance2` smallint(5) NOT NULL default '0', + `resistance3` smallint(5) NOT NULL default '0', + `resistance4` smallint(5) NOT NULL default '0', + `resistance5` smallint(5) NOT NULL default '0', + `resistance6` smallint(5) NOT NULL default '0', + `spell1` mediumint(8) unsigned NOT NULL default '0', + `spell2` mediumint(8) unsigned NOT NULL default '0', + `spell3` mediumint(8) unsigned NOT NULL default '0', + `spell4` mediumint(8) unsigned NOT NULL default '0', + `PetSpellDataId` mediumint(8) unsigned NOT NULL default '0', + `mingold` mediumint(8) unsigned NOT NULL default '0', + `maxgold` mediumint(8) unsigned NOT NULL default '0', + `AIName` char(64) NOT NULL default '', + `MovementType` tinyint(3) unsigned NOT NULL default '0', + `InhabitType` tinyint(3) unsigned NOT NULL default '3', + `RacialLeader` tinyint(3) unsigned NOT NULL default '0', + `RegenHealth` tinyint(3) unsigned NOT NULL default '1', + `equipment_id` mediumint(8) unsigned NOT NULL default '0', + `mechanic_immune_mask` int(10) unsigned NOT NULL default '0', + `flags_extra` int(10) unsigned NOT NULL default '0', + `ScriptName` char(64) NOT NULL default '', + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Creature System'; + +-- +-- Dumping data for table `creature_template` +-- + +LOCK TABLES `creature_template` WRITE; +/*!40000 ALTER TABLE `creature_template` DISABLE KEYS */; +INSERT INTO `creature_template` VALUES +(1,1,10045,0,10045,0,'Waypoint(Only GM can see it)','Visual',NULL,1,1,64,64,0,0,0,35,35,0,0.91,1,0,14,15,0,100,2000,2200,4096,0,8,0,0,0,0,1.76,2.42,100,8,5242886,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,3,0,1,0,0,2,''); +/*!40000 ALTER TABLE `creature_template` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `creature_template_addon` +-- + +DROP TABLE IF EXISTS `creature_template_addon`; +CREATE TABLE `creature_template_addon` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `mount` mediumint(8) unsigned NOT NULL default '0', + `bytes0` int(10) unsigned NOT NULL default '0', + `bytes1` int(10) unsigned NOT NULL default '0', + `bytes2` int(10) unsigned NOT NULL default '0', + `emote` mediumint(8) unsigned NOT NULL default '0', + `moveflags` int(10) unsigned NOT NULL default '0', + `auras` text, + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `creature_template_addon` +-- + +LOCK TABLES `creature_template_addon` WRITE; +/*!40000 ALTER TABLE `creature_template_addon` DISABLE KEYS */; +/*!40000 ALTER TABLE `creature_template_addon` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `db_version` +-- + +DROP TABLE IF EXISTS `db_version`; +CREATE TABLE `db_version` ( + `version` varchar(120) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; + +-- +-- Dumping data for table `db_version` +-- + +LOCK TABLES `db_version` WRITE; +/*!40000 ALTER TABLE `db_version` DISABLE KEYS */; +INSERT INTO `db_version` VALUES +('Mangos default database.'); +/*!40000 ALTER TABLE `db_version` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `disenchant_loot_template` +-- + +DROP TABLE IF EXISTS `disenchant_loot_template`; +CREATE TABLE `disenchant_loot_template` ( + `entry` mediumint(8) unsigned NOT NULL default '0' COMMENT 'Recommended id selection: item_level*100 + item_quality', + `item` mediumint(8) unsigned NOT NULL default '0', + `ChanceOrQuestChance` float NOT NULL default '100', + `groupid` tinyint(3) unsigned NOT NULL default '0', + `mincountOrRef` mediumint(9) NOT NULL default '1', + `maxcount` tinyint(3) unsigned NOT NULL default '1', + `lootcondition` tinyint(3) unsigned NOT NULL default '0', + `condition_value1` mediumint(8) unsigned NOT NULL default '0', + `condition_value2` mediumint(8) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`,`item`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Loot System'; + +-- +-- Dumping data for table `disenchant_loot_template` +-- + +LOCK TABLES `disenchant_loot_template` WRITE; +/*!40000 ALTER TABLE `disenchant_loot_template` DISABLE KEYS */; +/*!40000 ALTER TABLE `disenchant_loot_template` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `event_scripts` +-- + +DROP TABLE IF EXISTS `event_scripts`; +CREATE TABLE `event_scripts` ( + `id` mediumint(8) unsigned NOT NULL default '0', + `delay` int(10) unsigned NOT NULL default '0', + `command` mediumint(8) unsigned NOT NULL default '0', + `datalong` mediumint(8) unsigned NOT NULL default '0', + `datalong2` int(10) unsigned NOT NULL default '0', + `datatext` text NOT NULL, + `x` float NOT NULL default '0', + `y` float NOT NULL default '0', + `z` float NOT NULL default '0', + `o` float NOT NULL default '0' +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `event_scripts` +-- + +LOCK TABLES `event_scripts` WRITE; +/*!40000 ALTER TABLE `event_scripts` DISABLE KEYS */; +/*!40000 ALTER TABLE `event_scripts` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `exploration_basexp` +-- + +DROP TABLE IF EXISTS `exploration_basexp`; +CREATE TABLE `exploration_basexp` ( + `level` tinyint(4) NOT NULL default '0', + `basexp` mediumint(9) NOT NULL default '0', + PRIMARY KEY (`level`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Exploration System'; + +-- +-- Dumping data for table `exploration_basexp` +-- + +LOCK TABLES `exploration_basexp` WRITE; +/*!40000 ALTER TABLE `exploration_basexp` DISABLE KEYS */; +INSERT INTO `exploration_basexp` VALUES +(0,0), +(1,5), +(2,15), +(3,25), +(4,35), +(5,45), +(6,55), +(7,65), +(8,70), +(9,80), +(10,85), +(11,90), +(12,90), +(13,90), +(14,100), +(15,105), +(16,115), +(17,125), +(18,135), +(19,145), +(20,155), +(21,165), +(22,175), +(23,185), +(24,195), +(25,200), +(26,210), +(27,220), +(28,230), +(29,240), +(30,245), +(31,250), +(32,255), +(33,265), +(34,270), +(35,275), +(36,280), +(37,285), +(38,285), +(39,300), +(40,315), +(41,330), +(42,345), +(43,360), +(44,375), +(45,390), +(46,405), +(47,420), +(48,440), +(49,455), +(50,470), +(51,490), +(52,510), +(53,530), +(54,540), +(55,560), +(56,580), +(57,600), +(58,620), +(59,640), +(60,660), +(61,970), +(62,1000), +(63,1050), +(64,1080), +(65,1100), +(66,1130), +(67,1160), +(68,1200), +(69,1230), +(70,1250); +/*!40000 ALTER TABLE `exploration_basexp` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `fishing_loot_template` +-- + +DROP TABLE IF EXISTS `fishing_loot_template`; +CREATE TABLE `fishing_loot_template` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `item` mediumint(8) unsigned NOT NULL default '0', + `ChanceOrQuestChance` float NOT NULL default '100', + `groupid` tinyint(3) unsigned NOT NULL default '0', + `mincountOrRef` mediumint(9) NOT NULL default '1', + `maxcount` tinyint(3) unsigned NOT NULL default '1', + `lootcondition` tinyint(3) unsigned NOT NULL default '0', + `condition_value1` mediumint(8) unsigned NOT NULL default '0', + `condition_value2` mediumint(8) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`,`item`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Loot System'; + +-- +-- Dumping data for table `fishing_loot_template` +-- + +LOCK TABLES `fishing_loot_template` WRITE; +/*!40000 ALTER TABLE `fishing_loot_template` DISABLE KEYS */; +/*!40000 ALTER TABLE `fishing_loot_template` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `game_event` +-- + +DROP TABLE IF EXISTS `game_event`; +CREATE TABLE `game_event` ( + `entry` mediumint(8) unsigned NOT NULL COMMENT 'Entry of the game event', + `start_time` timestamp NOT NULL default '0000-00-00 00:00:00' COMMENT 'Absolute start date, the event will never start before', + `end_time` timestamp NOT NULL default '0000-00-00 00:00:00' COMMENT 'Absolute end date, the event will never start afler', + `occurence` bigint(20) unsigned NOT NULL default '86400' COMMENT 'Delay in hours between occurences of the event', + `length` bigint(20) unsigned NOT NULL default '43200' COMMENT 'Length in hours of the event', + `description` varchar(255) default NULL COMMENT 'Description of the event displayed in console', + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `game_event` +-- + +LOCK TABLES `game_event` WRITE; +/*!40000 ALTER TABLE `game_event` DISABLE KEYS */; +/*!40000 ALTER TABLE `game_event` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `game_event_creature` +-- + +DROP TABLE IF EXISTS `game_event_creature`; +CREATE TABLE `game_event_creature` ( + `guid` int(10) unsigned NOT NULL, + `event` smallint(6) NOT NULL default '0' COMMENT 'Put negatives values to remove during event', + PRIMARY KEY (`guid`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `game_event_creature` +-- + +LOCK TABLES `game_event_creature` WRITE; +/*!40000 ALTER TABLE `game_event_creature` DISABLE KEYS */; +/*!40000 ALTER TABLE `game_event_creature` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `game_event_creature_quest` +-- + +DROP TABLE IF EXISTS `game_event_creature_quest`; +CREATE TABLE `game_event_creature_quest` ( + `id` mediumint(8) unsigned NOT NULL default '0', + `quest` mediumint(8) unsigned NOT NULL default '0', + `event` smallint(5) unsigned NOT NULL default '0', + PRIMARY KEY (`id`,`quest`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `game_event_creature_quest` +-- + +LOCK TABLES `game_event_creature_quest` WRITE; +/*!40000 ALTER TABLE `game_event_creature_quest` DISABLE KEYS */; +/*!40000 ALTER TABLE `game_event_creature_quest` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `game_event_gameobject` +-- + +DROP TABLE IF EXISTS `game_event_gameobject`; +CREATE TABLE `game_event_gameobject` ( + `guid` int(10) unsigned NOT NULL, + `event` smallint(6) NOT NULL default '0' COMMENT 'Put negatives values to remove during event', + PRIMARY KEY (`guid`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `game_event_gameobject` +-- + +LOCK TABLES `game_event_gameobject` WRITE; +/*!40000 ALTER TABLE `game_event_gameobject` DISABLE KEYS */; +/*!40000 ALTER TABLE `game_event_gameobject` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `game_event_model_equip` +-- + +DROP TABLE IF EXISTS `game_event_model_equip`; +CREATE TABLE `game_event_model_equip` ( + `guid` int(10) unsigned NOT NULL default '0', + `modelid` mediumint(8) unsigned NOT NULL default '0', + `equipment_id` mediumint(8) unsigned NOT NULL default '0', + `event` smallint(5) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `game_event_model_equip` +-- + +LOCK TABLES `game_event_model_equip` WRITE; +/*!40000 ALTER TABLE `game_event_model_equip` DISABLE KEYS */; +/*!40000 ALTER TABLE `game_event_model_equip` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `game_graveyard_zone` +-- + +DROP TABLE IF EXISTS `game_graveyard_zone`; +CREATE TABLE `game_graveyard_zone` ( + `id` mediumint(8) unsigned NOT NULL default '0', + `ghost_zone` mediumint(8) unsigned NOT NULL default '0', + `faction` smallint(5) unsigned NOT NULL default '0', + PRIMARY KEY (`id`,`ghost_zone`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Trigger System'; + +-- +-- Dumping data for table `game_graveyard_zone` +-- + +LOCK TABLES `game_graveyard_zone` WRITE; +/*!40000 ALTER TABLE `game_graveyard_zone` DISABLE KEYS */; +/*!40000 ALTER TABLE `game_graveyard_zone` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `game_tele` +-- + +DROP TABLE IF EXISTS `game_tele`; +CREATE TABLE `game_tele` ( + `id` mediumint(8) unsigned NOT NULL auto_increment, + `position_x` float NOT NULL default '0', + `position_y` float NOT NULL default '0', + `position_z` float NOT NULL default '0', + `orientation` float NOT NULL default '0', + `map` smallint(5) unsigned NOT NULL default '0', + `name` varchar(100) NOT NULL default '', + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Tele Command'; + +-- +-- Dumping data for table `game_tele` +-- + +LOCK TABLES `game_tele` WRITE; +/*!40000 ALTER TABLE `game_tele` DISABLE KEYS */; +/*!40000 ALTER TABLE `game_tele` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `game_weather` +-- + +DROP TABLE IF EXISTS `game_weather`; +CREATE TABLE `game_weather` ( + `zone` mediumint(8) unsigned NOT NULL default '0', + `spring_rain_chance` tinyint(3) unsigned NOT NULL default '25', + `spring_snow_chance` tinyint(3) unsigned NOT NULL default '25', + `spring_storm_chance` tinyint(3) unsigned NOT NULL default '25', + `summer_rain_chance` tinyint(3) unsigned NOT NULL default '25', + `summer_snow_chance` tinyint(3) unsigned NOT NULL default '25', + `summer_storm_chance` tinyint(3) unsigned NOT NULL default '25', + `fall_rain_chance` tinyint(3) unsigned NOT NULL default '25', + `fall_snow_chance` tinyint(3) unsigned NOT NULL default '25', + `fall_storm_chance` tinyint(3) unsigned NOT NULL default '25', + `winter_rain_chance` tinyint(3) unsigned NOT NULL default '25', + `winter_snow_chance` tinyint(3) unsigned NOT NULL default '25', + `winter_storm_chance` tinyint(3) unsigned NOT NULL default '25', + PRIMARY KEY (`zone`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Weather System'; + +-- +-- Dumping data for table `game_weather` +-- + +LOCK TABLES `game_weather` WRITE; +/*!40000 ALTER TABLE `game_weather` DISABLE KEYS */; +/*!40000 ALTER TABLE `game_weather` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `gameobject` +-- + +DROP TABLE IF EXISTS `gameobject`; +CREATE TABLE `gameobject` ( + `guid` int(10) unsigned NOT NULL auto_increment COMMENT 'Global Unique Identifier', + `id` mediumint(8) unsigned NOT NULL default '0' COMMENT 'Gameobject Identifier', + `map` smallint(5) unsigned NOT NULL default '0' COMMENT 'Map Identifier', + `spawnMask` tinyint(3) unsigned NOT NULL default '1', + `position_x` float NOT NULL default '0', + `position_y` float NOT NULL default '0', + `position_z` float NOT NULL default '0', + `orientation` float NOT NULL default '0', + `rotation0` float NOT NULL default '0', + `rotation1` float NOT NULL default '0', + `rotation2` float NOT NULL default '0', + `rotation3` float NOT NULL default '0', + `spawntimesecs` int(11) NOT NULL default '0', + `animprogress` tinyint(3) unsigned NOT NULL default '0', + `state` tinyint(3) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Gameobject System'; + +-- +-- Dumping data for table `gameobject` +-- + +LOCK TABLES `gameobject` WRITE; +/*!40000 ALTER TABLE `gameobject` DISABLE KEYS */; +/*!40000 ALTER TABLE `gameobject` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `gameobject_involvedrelation` +-- + +DROP TABLE IF EXISTS `gameobject_involvedrelation`; +CREATE TABLE `gameobject_involvedrelation` ( + `id` mediumint(8) unsigned NOT NULL default '0', + `quest` mediumint(8) unsigned NOT NULL default '0' COMMENT 'Quest Identifier', + PRIMARY KEY (`id`,`quest`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `gameobject_involvedrelation` +-- + +LOCK TABLES `gameobject_involvedrelation` WRITE; +/*!40000 ALTER TABLE `gameobject_involvedrelation` DISABLE KEYS */; +/*!40000 ALTER TABLE `gameobject_involvedrelation` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `gameobject_loot_template` +-- + +DROP TABLE IF EXISTS `gameobject_loot_template`; +CREATE TABLE `gameobject_loot_template` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `item` mediumint(8) unsigned NOT NULL default '0', + `ChanceOrQuestChance` float NOT NULL default '100', + `groupid` tinyint(3) unsigned NOT NULL default '0', + `mincountOrRef` mediumint(9) NOT NULL default '1', + `maxcount` tinyint(3) unsigned NOT NULL default '1', + `lootcondition` tinyint(3) unsigned NOT NULL default '0', + `condition_value1` mediumint(8) unsigned NOT NULL default '0', + `condition_value2` mediumint(8) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`,`item`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Loot System'; + +-- +-- Dumping data for table `gameobject_loot_template` +-- + +LOCK TABLES `gameobject_loot_template` WRITE; +/*!40000 ALTER TABLE `gameobject_loot_template` DISABLE KEYS */; +/*!40000 ALTER TABLE `gameobject_loot_template` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `gameobject_questrelation` +-- + +DROP TABLE IF EXISTS `gameobject_questrelation`; +CREATE TABLE `gameobject_questrelation` ( + `id` mediumint(8) unsigned NOT NULL default '0', + `quest` mediumint(8) unsigned NOT NULL default '0' COMMENT 'Quest Identifier', + PRIMARY KEY (`id`,`quest`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `gameobject_questrelation` +-- + +LOCK TABLES `gameobject_questrelation` WRITE; +/*!40000 ALTER TABLE `gameobject_questrelation` DISABLE KEYS */; +/*!40000 ALTER TABLE `gameobject_questrelation` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `gameobject_respawn` +-- + +DROP TABLE IF EXISTS `gameobject_respawn`; +CREATE TABLE `gameobject_respawn` ( + `guid` int(10) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `respawntime` bigint(20) NOT NULL default '0', + `instance` mediumint(8) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`,`instance`), + KEY `instance` (`instance`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Grid Loading System'; + +-- +-- Dumping data for table `gameobject_respawn` +-- + +LOCK TABLES `gameobject_respawn` WRITE; +/*!40000 ALTER TABLE `gameobject_respawn` DISABLE KEYS */; +/*!40000 ALTER TABLE `gameobject_respawn` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `gameobject_scripts` +-- + +DROP TABLE IF EXISTS `gameobject_scripts`; +CREATE TABLE `gameobject_scripts` ( + `id` mediumint(8) unsigned NOT NULL default '0', + `delay` int(10) unsigned NOT NULL default '0', + `command` mediumint(8) unsigned NOT NULL default '0', + `datalong` mediumint(8) unsigned NOT NULL default '0', + `datalong2` int(10) unsigned NOT NULL default '0', + `datatext` text NOT NULL, + `x` float NOT NULL default '0', + `y` float NOT NULL default '0', + `z` float NOT NULL default '0', + `o` float NOT NULL default '0' +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `gameobject_scripts` +-- + +LOCK TABLES `gameobject_scripts` WRITE; +/*!40000 ALTER TABLE `gameobject_scripts` DISABLE KEYS */; +/*!40000 ALTER TABLE `gameobject_scripts` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `gameobject_template` +-- + +DROP TABLE IF EXISTS `gameobject_template`; +CREATE TABLE `gameobject_template` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `type` tinyint(3) unsigned NOT NULL default '0', + `displayId` mediumint(8) unsigned NOT NULL default '0', + `name` varchar(100) NOT NULL default '', + `castBarCaption` varchar(100) NOT NULL default '', + `faction` smallint(5) unsigned NOT NULL default '0', + `flags` int(10) unsigned NOT NULL default '0', + `size` float NOT NULL default '1', + `data0` int(10) unsigned NOT NULL default '0', + `data1` int(10) unsigned NOT NULL default '0', + `data2` int(10) unsigned NOT NULL default '0', + `data3` int(10) unsigned NOT NULL default '0', + `data4` int(10) unsigned NOT NULL default '0', + `data5` int(10) unsigned NOT NULL default '0', + `data6` int(10) unsigned NOT NULL default '0', + `data7` int(10) unsigned NOT NULL default '0', + `data8` int(10) unsigned NOT NULL default '0', + `data9` int(10) unsigned NOT NULL default '0', + `data10` int(10) unsigned NOT NULL default '0', + `data11` int(10) unsigned NOT NULL default '0', + `data12` int(10) unsigned NOT NULL default '0', + `data13` int(10) unsigned NOT NULL default '0', + `data14` int(10) unsigned NOT NULL default '0', + `data15` int(10) unsigned NOT NULL default '0', + `data16` int(10) unsigned NOT NULL default '0', + `data17` int(10) unsigned NOT NULL default '0', + `data18` int(10) unsigned NOT NULL default '0', + `data19` int(10) unsigned NOT NULL default '0', + `data20` int(10) unsigned NOT NULL default '0', + `data21` int(10) unsigned NOT NULL default '0', + `data22` int(10) unsigned NOT NULL default '0', + `data23` int(10) unsigned NOT NULL default '0', + `ScriptName` varchar(64) NOT NULL default '', + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Gameobject System'; + +-- +-- Dumping data for table `gameobject_template` +-- + +LOCK TABLES `gameobject_template` WRITE; +/*!40000 ALTER TABLE `gameobject_template` DISABLE KEYS */; +/*!40000 ALTER TABLE `gameobject_template` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `instance_template` +-- + +DROP TABLE IF EXISTS `instance_template`; +CREATE TABLE `instance_template` ( + `map` smallint(5) unsigned NOT NULL, + `parent` int(10) unsigned NOT NULL, + `levelMin` tinyint(3) unsigned NOT NULL default '0', + `levelMax` tinyint(3) unsigned NOT NULL default '0', + `maxPlayers` tinyint(3) unsigned NOT NULL default '0', + `reset_delay` int(10) unsigned NOT NULL default '0', + `startLocX` float default NULL, + `startLocY` float default NULL, + `startLocZ` float default NULL, + `startLocO` float default NULL, + `script` varchar(128) NOT NULL default '', + PRIMARY KEY (`map`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `instance_template` +-- + +LOCK TABLES `instance_template` WRITE; +/*!40000 ALTER TABLE `instance_template` DISABLE KEYS */; +INSERT INTO `instance_template` VALUES +(33,0,22,30,10,7200,NULL,NULL,NULL,NULL,''), +(34,0,24,32,10,7200,NULL,NULL,NULL,NULL,''), +(36,0,15,20,10,7200,NULL,NULL,NULL,NULL,''), +(43,0,15,21,10,7200,NULL,NULL,NULL,NULL,''), +(47,0,29,38,10,7200,NULL,NULL,NULL,NULL,''), +(48,0,24,32,10,7200,NULL,NULL,NULL,NULL,''), +(70,0,35,47,10,7200,NULL,NULL,NULL,NULL,''), +(90,0,29,38,10,7200,NULL,NULL,NULL,NULL,''), +(109,0,45,55,10,7200,NULL,NULL,NULL,NULL,''), +(129,0,37,46,10,7200,NULL,NULL,NULL,NULL,''), +(189,0,34,45,10,7200,NULL,NULL,NULL,NULL,''), +(209,0,44,54,10,7200,NULL,NULL,NULL,NULL,''), +(229,0,58,0,10,120000,78.5083,-225.044,49.839,5.1,''), +(230,0,52,0,5,7200,NULL,NULL,NULL,NULL,''), +(249,0,60,0,40,432000,NULL,NULL,NULL,NULL,''), +(289,0,57,0,5,7200,NULL,NULL,NULL,NULL,''), +(309,0,60,0,20,259200,NULL,NULL,NULL,NULL,''), +(329,0,58,60,5,7200,NULL,NULL,NULL,NULL,''), +(349,0,46,55,10,7200,NULL,NULL,NULL,NULL,''), +(389,0,13,18,10,7200,NULL,NULL,NULL,NULL,''), +(409,0,60,0,40,604800,NULL,NULL,NULL,NULL,''), +(429,0,55,60,5,7200,NULL,NULL,NULL,NULL,''), +(469,0,60,0,40,604800,NULL,NULL,NULL,NULL,''), +(509,0,60,0,20,259200,NULL,NULL,NULL,NULL,''), +(531,0,60,0,40,604800,NULL,NULL,NULL,NULL,''), +(533,0,60,0,40,604800,NULL,NULL,NULL,NULL,''); +/*!40000 ALTER TABLE `instance_template` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `item_enchantment_template` +-- + +DROP TABLE IF EXISTS `item_enchantment_template`; +CREATE TABLE `item_enchantment_template` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `ench` mediumint(8) unsigned NOT NULL default '0', + `chance` float unsigned NOT NULL default '0', + PRIMARY KEY (`entry`,`ench`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Item Random Enchantment System'; + +-- +-- Dumping data for table `item_enchantment_template` +-- + +LOCK TABLES `item_enchantment_template` WRITE; +/*!40000 ALTER TABLE `item_enchantment_template` DISABLE KEYS */; +/*!40000 ALTER TABLE `item_enchantment_template` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `item_loot_template` +-- + +DROP TABLE IF EXISTS `item_loot_template`; +CREATE TABLE `item_loot_template` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `item` mediumint(8) unsigned NOT NULL default '0', + `ChanceOrQuestChance` float NOT NULL default '100', + `groupid` tinyint(3) unsigned NOT NULL default '0', + `mincountOrRef` mediumint(9) NOT NULL default '1', + `maxcount` tinyint(3) unsigned NOT NULL default '1', + `lootcondition` tinyint(3) unsigned NOT NULL default '0', + `condition_value1` mediumint(8) unsigned NOT NULL default '0', + `condition_value2` mediumint(8) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`,`item`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Loot System'; + +-- +-- Dumping data for table `item_loot_template` +-- + +LOCK TABLES `item_loot_template` WRITE; +/*!40000 ALTER TABLE `item_loot_template` DISABLE KEYS */; +/*!40000 ALTER TABLE `item_loot_template` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `item_template` +-- + +DROP TABLE IF EXISTS `item_template`; +CREATE TABLE `item_template` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `class` tinyint(3) unsigned NOT NULL default '0', + `subclass` tinyint(3) unsigned NOT NULL default '0', + `unk0` int(11) NOT NULL default '-1', + `name` varchar(255) NOT NULL default '', + `displayid` mediumint(8) unsigned NOT NULL default '0', + `Quality` tinyint(3) unsigned NOT NULL default '0', + `Flags` int(10) unsigned NOT NULL default '0', + `BuyCount` tinyint(3) unsigned NOT NULL default '1', + `BuyPrice` int(10) unsigned NOT NULL default '0', + `SellPrice` int(10) unsigned NOT NULL default '0', + `InventoryType` tinyint(3) unsigned NOT NULL default '0', + `AllowableClass` mediumint(9) NOT NULL default '-1', + `AllowableRace` mediumint(9) NOT NULL default '-1', + `ItemLevel` tinyint(3) unsigned NOT NULL default '0', + `RequiredLevel` tinyint(3) unsigned NOT NULL default '0', + `RequiredSkill` smallint(5) unsigned NOT NULL default '0', + `RequiredSkillRank` smallint(5) unsigned NOT NULL default '0', + `requiredspell` mediumint(8) unsigned NOT NULL default '0', + `requiredhonorrank` mediumint(8) unsigned NOT NULL default '0', + `RequiredCityRank` mediumint(8) unsigned NOT NULL default '0', + `RequiredReputationFaction` smallint(5) unsigned NOT NULL default '0', + `RequiredReputationRank` smallint(5) unsigned NOT NULL default '0', + `maxcount` smallint(5) unsigned NOT NULL default '0', + `stackable` smallint(5) unsigned NOT NULL default '1', + `ContainerSlots` tinyint(3) unsigned NOT NULL default '0', + `stat_type1` tinyint(3) unsigned NOT NULL default '0', + `stat_value1` smallint(6) NOT NULL default '0', + `stat_type2` tinyint(3) unsigned NOT NULL default '0', + `stat_value2` smallint(6) NOT NULL default '0', + `stat_type3` tinyint(3) unsigned NOT NULL default '0', + `stat_value3` smallint(6) NOT NULL default '0', + `stat_type4` tinyint(3) unsigned NOT NULL default '0', + `stat_value4` smallint(6) NOT NULL default '0', + `stat_type5` tinyint(3) unsigned NOT NULL default '0', + `stat_value5` smallint(6) NOT NULL default '0', + `stat_type6` tinyint(3) unsigned NOT NULL default '0', + `stat_value6` smallint(6) NOT NULL default '0', + `stat_type7` tinyint(3) unsigned NOT NULL default '0', + `stat_value7` smallint(6) NOT NULL default '0', + `stat_type8` tinyint(3) unsigned NOT NULL default '0', + `stat_value8` smallint(6) NOT NULL default '0', + `stat_type9` tinyint(3) unsigned NOT NULL default '0', + `stat_value9` smallint(6) NOT NULL default '0', + `stat_type10` tinyint(3) unsigned NOT NULL default '0', + `stat_value10` smallint(6) NOT NULL default '0', + `dmg_min1` float NOT NULL default '0', + `dmg_max1` float NOT NULL default '0', + `dmg_type1` tinyint(3) unsigned NOT NULL default '0', + `dmg_min2` float NOT NULL default '0', + `dmg_max2` float NOT NULL default '0', + `dmg_type2` tinyint(3) unsigned NOT NULL default '0', + `dmg_min3` float NOT NULL default '0', + `dmg_max3` float NOT NULL default '0', + `dmg_type3` tinyint(3) unsigned NOT NULL default '0', + `dmg_min4` float NOT NULL default '0', + `dmg_max4` float NOT NULL default '0', + `dmg_type4` tinyint(3) unsigned NOT NULL default '0', + `dmg_min5` float NOT NULL default '0', + `dmg_max5` float NOT NULL default '0', + `dmg_type5` tinyint(3) unsigned NOT NULL default '0', + `armor` smallint(5) unsigned NOT NULL default '0', + `holy_res` tinyint(3) unsigned NOT NULL default '0', + `fire_res` tinyint(3) unsigned NOT NULL default '0', + `nature_res` tinyint(3) unsigned NOT NULL default '0', + `frost_res` tinyint(3) unsigned NOT NULL default '0', + `shadow_res` tinyint(3) unsigned NOT NULL default '0', + `arcane_res` tinyint(3) unsigned NOT NULL default '0', + `delay` smallint(5) unsigned NOT NULL default '1000', + `ammo_type` tinyint(3) unsigned NOT NULL default '0', + `RangedModRange` float NOT NULL default '0', + `spellid_1` mediumint(8) unsigned NOT NULL default '0', + `spelltrigger_1` tinyint(3) unsigned NOT NULL default '0', + `spellcharges_1` tinyint(4) NOT NULL default '0', + `spellppmRate_1` float NOT NULL default '0', + `spellcooldown_1` int(11) NOT NULL default '-1', + `spellcategory_1` smallint(5) unsigned NOT NULL default '0', + `spellcategorycooldown_1` int(11) NOT NULL default '-1', + `spellid_2` mediumint(8) unsigned NOT NULL default '0', + `spelltrigger_2` tinyint(3) unsigned NOT NULL default '0', + `spellcharges_2` tinyint(4) NOT NULL default '0', + `spellppmRate_2` float NOT NULL default '0', + `spellcooldown_2` int(11) NOT NULL default '-1', + `spellcategory_2` smallint(5) unsigned NOT NULL default '0', + `spellcategorycooldown_2` int(11) NOT NULL default '-1', + `spellid_3` mediumint(8) unsigned NOT NULL default '0', + `spelltrigger_3` tinyint(3) unsigned NOT NULL default '0', + `spellcharges_3` tinyint(4) NOT NULL default '0', + `spellppmRate_3` float NOT NULL default '0', + `spellcooldown_3` int(11) NOT NULL default '-1', + `spellcategory_3` smallint(5) unsigned NOT NULL default '0', + `spellcategorycooldown_3` int(11) NOT NULL default '-1', + `spellid_4` mediumint(8) unsigned NOT NULL default '0', + `spelltrigger_4` tinyint(3) unsigned NOT NULL default '0', + `spellcharges_4` tinyint(4) NOT NULL default '0', + `spellppmRate_4` float NOT NULL default '0', + `spellcooldown_4` int(11) NOT NULL default '-1', + `spellcategory_4` smallint(5) unsigned NOT NULL default '0', + `spellcategorycooldown_4` int(11) NOT NULL default '-1', + `spellid_5` mediumint(8) unsigned NOT NULL default '0', + `spelltrigger_5` tinyint(3) unsigned NOT NULL default '0', + `spellcharges_5` tinyint(4) NOT NULL default '0', + `spellppmRate_5` float NOT NULL default '0', + `spellcooldown_5` int(11) NOT NULL default '-1', + `spellcategory_5` smallint(5) unsigned NOT NULL default '0', + `spellcategorycooldown_5` int(11) NOT NULL default '-1', + `bonding` tinyint(3) unsigned NOT NULL default '0', + `description` varchar(255) NOT NULL default '', + `PageText` mediumint(8) unsigned NOT NULL default '0', + `LanguageID` tinyint(3) unsigned NOT NULL default '0', + `PageMaterial` tinyint(3) unsigned NOT NULL default '0', + `startquest` mediumint(8) unsigned NOT NULL default '0', + `lockid` mediumint(8) unsigned NOT NULL default '0', + `Material` tinyint(4) NOT NULL default '0', + `sheath` tinyint(3) unsigned NOT NULL default '0', + `RandomProperty` mediumint(8) unsigned NOT NULL default '0', + `RandomSuffix` mediumint(8) unsigned NOT NULL default '0', + `block` mediumint(8) unsigned NOT NULL default '0', + `itemset` mediumint(8) unsigned NOT NULL default '0', + `MaxDurability` smallint(5) unsigned NOT NULL default '0', + `area` mediumint(8) unsigned NOT NULL default '0', + `Map` smallint(6) NOT NULL default '0', + `BagFamily` mediumint(9) NOT NULL default '0', + `TotemCategory` tinyint(4) NOT NULL default '0', + `socketColor_1` tinyint(4) NOT NULL default '0', + `socketContent_1` mediumint(9) NOT NULL default '0', + `socketColor_2` tinyint(4) NOT NULL default '0', + `socketContent_2` mediumint(9) NOT NULL default '0', + `socketColor_3` tinyint(4) NOT NULL default '0', + `socketContent_3` mediumint(9) NOT NULL default '0', + `socketBonus` mediumint(9) NOT NULL default '0', + `GemProperties` mediumint(9) NOT NULL default '0', + `RequiredDisenchantSkill` smallint(6) NOT NULL default '-1', + `ArmorDamageModifier` float NOT NULL default '0', + `ScriptName` varchar(64) NOT NULL default '', + `DisenchantID` mediumint(8) unsigned NOT NULL default '0', + `FoodType` tinyint(3) unsigned NOT NULL default '0', + `minMoneyLoot` int(10) unsigned NOT NULL default '0', + `maxMoneyLoot` int(10) unsigned NOT NULL default '0', + `Duration` int(11) NOT NULL default '0' COMMENT 'Duration in seconds. Negative value means realtime, postive value ingame time', + PRIMARY KEY (`entry`), + KEY `items_index` (`class`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Item System'; + +-- +-- Dumping data for table `item_template` +-- + +LOCK TABLES `item_template` WRITE; +/*!40000 ALTER TABLE `item_template` DISABLE KEYS */; +INSERT INTO `item_template` VALUES +(25,2,7,-1,'Worn Shortsword',1542,1,0,1,35,7,21,32767,511,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1900,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,1,0,0,0,1,3,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(35,2,10,-1,'Bent Staff',472,1,0,1,47,9,17,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2900,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,2,2,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(36,2,4,-1,'Worn Mace',5194,1,0,1,38,7,21,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1900,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,2,3,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(37,2,0,-1,'Worn Axe',14029,1,0,1,38,7,21,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,3,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(38,4,0,-1,'Recruit\'s Shirt',9891,1,0,1,1,1,4,-1,-1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(39,4,1,-1,'Recruit\'s Pants',9892,0,0,1,5,1,7,32767,511,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(40,4,0,-1,'Recruit\'s Boots',10141,1,0,1,4,1,8,32767,511,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(43,4,0,-1,'Squire\'s Boots',9938,1,0,1,4,1,8,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(44,4,1,-1,'Squire\'s Pants',9937,0,0,1,4,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(45,4,0,-1,'Squire\'s Shirt',3265,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(47,4,0,-1,'Footpad\'s Shoes',9915,1,0,1,4,1,8,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(48,4,1,-1,'Footpad\'s Pants',9913,0,0,1,4,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(49,4,0,-1,'Footpad\'s Shirt',9906,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(51,4,0,-1,'Neophyte\'s Boots',9946,1,0,1,5,1,8,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(52,4,1,-1,'Neophyte\'s Pants',9945,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(53,4,0,-1,'Neophyte\'s Shirt',9944,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(55,4,0,-1,'Apprentice\'s Boots',9929,1,0,1,5,1,8,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(56,4,1,-1,'Apprentice\'s Robe',12647,0,0,1,5,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(57,4,1,-1,'Acolyte\'s Robe',12645,0,0,1,5,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(59,4,0,-1,'Acolyte\'s Shoes',3261,1,0,1,5,1,8,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(117,0,0,-1,'Tough Jerky',2473,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(120,4,1,-1,'Thug Pants',10006,0,0,1,4,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(121,4,0,-1,'Thug Boots',10008,1,0,1,4,1,8,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(127,4,0,-1,'Trapper\'s Shirt',9996,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(139,4,1,-1,'Brawler\'s Pants',9988,0,0,1,4,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(140,4,0,-1,'Brawler\'s Boots',9992,1,0,1,4,1,8,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(147,4,1,-1,'Rugged Trapper\'s Pants',9975,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(148,4,0,-1,'Rugged Trapper\'s Shirt',9976,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(153,4,2,-1,'Primitive Kilt',10050,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,8,0,0,0,0,0,30,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(154,4,0,-1,'Primitive Mantle',10058,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(159,0,0,-1,'Refreshing Spring Water',18084,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,430,0,-1,0,-1,59,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(1395,4,1,-1,'Apprentice\'s Pants',9924,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(1396,4,1,-1,'Acolyte\'s Pants',3260,0,0,1,4,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(2070,0,0,-1,'Darnassian Bleu',6353,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(2092,2,15,-1,'Worn Dagger',6442,1,0,1,35,7,13,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1600,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,3,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(2101,1,2,-1,'Light Quiver',21328,1,0,1,4,1,18,2047,255,1,1,0,0,0,0,0,0,0,0,1,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,14824,1,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(2102,1,3,-1,'Small Ammo Pouch',1816,1,0,1,4,1,18,2047,255,1,1,0,0,0,0,0,0,0,0,1,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,14824,1,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(2105,4,0,-1,'Thug Shirt',10005,1,0,1,5,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(2361,2,5,-1,'Battleworn Hammer',8690,1,0,1,45,9,17,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2900,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,2,1,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(2362,4,6,-1,'Worn Wooden Shield',18730,0,0,1,7,1,14,32767,511,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,4,0,0,1,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(2504,2,2,-1,'Worn Shortbow',8106,1,0,1,29,5,15,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2300,2,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,2,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(2508,2,3,-1,'Old Blunderbuss',6606,1,0,1,27,5,26,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2300,3,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(2512,6,2,-1,'Rough Arrow',5996,1,0,1,10,0,24,2047,255,5,1,0,0,0,0,0,0,0,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,2,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(2516,6,3,-1,'Light Shot',5998,1,0,1,10,0,24,2047,255,5,1,0,0,0,0,0,0,0,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,2,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(2947,2,16,-1,'Small Throwing Knife',16754,1,0,1,15,0,25,2047,255,3,1,0,0,0,0,0,0,0,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2000,4,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(3661,2,10,-1,'Handcrafted Staff',18530,1,0,1,45,9,17,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2900,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,2,2,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(4536,0,0,-1,'Shiny Red Apple',6410,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(4540,0,0,-1,'Tough Hunk of Bread',6399,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(4604,0,0,-1,'Forest Mushroom Cap',15852,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(6096,4,0,-1,'Apprentice\'s Shirt',2163,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(6097,4,0,-1,'Acolyte\'s Shirt',2470,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(6098,4,1,-1,'Neophyte\'s Robe',12679,0,0,1,4,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(6119,4,1,-1,'Neophyte\'s Robe',12681,0,0,1,4,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(6123,4,1,-1,'Novice\'s Robe',12683,0,0,1,4,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(6124,4,1,-1,'Novice\'s Pants',9987,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(6125,4,0,-1,'Brawler\'s Harness',9995,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(6126,4,1,-1,'Trapper\'s Pants',10002,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(6127,4,0,-1,'Trapper\'s Boots',10003,1,0,1,5,1,8,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(6129,4,1,-1,'Acolyte\'s Robe',12646,0,0,1,5,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(6134,4,0,-1,'Primitive Mantle',10108,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(6135,4,2,-1,'Primitive Kilt',10109,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,8,0,0,0,0,0,30,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(6139,4,1,-1,'Novice\'s Robe',12684,0,0,1,4,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(6140,4,1,-1,'Apprentice\'s Robe',12649,0,0,1,4,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(6144,4,1,-1,'Neophyte\'s Robe',12680,0,0,1,5,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(6948,15,0,-1,'Hearthstone',6418,1,64,1,0,0,0,32767,511,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8690,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(12282,2,1,-1,'Worn Battleaxe',22291,1,0,1,43,8,17,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2900,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,1,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(14646,12,0,-1,'Northshire Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5805,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(14647,12,0,-1,'Coldridge Valley Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5841,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(14648,12,0,-1,'Shadowglen Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5842,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(14649,12,0,-1,'Valley of Trials Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5843,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(14650,12,0,-1,'Camp Narache Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5844,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(14651,12,0,-1,'Deathknell Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5847,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), +(25861,2,16,-1,'Crude Throwing Axe',20777,1,0,1,15,0,25,2047,255,3,1,0,0,0,0,0,0,0,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2000,4,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0); +/*!40000 ALTER TABLE `item_template` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `locales_creature` +-- + +DROP TABLE IF EXISTS `locales_creature`; +CREATE TABLE `locales_creature` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `name_loc1` varchar(100) NOT NULL default '', + `name_loc2` varchar(100) NOT NULL default '', + `name_loc3` varchar(100) NOT NULL default '', + `name_loc4` varchar(100) NOT NULL default '', + `name_loc5` varchar(100) NOT NULL default '', + `name_loc6` varchar(100) NOT NULL default '', + `name_loc7` varchar(100) NOT NULL default '', + `name_loc8` varchar(100) NOT NULL default '', + `subname_loc1` varchar(100) default NULL, + `subname_loc2` varchar(100) default NULL, + `subname_loc3` varchar(100) default NULL, + `subname_loc4` varchar(100) default NULL, + `subname_loc5` varchar(100) default NULL, + `subname_loc6` varchar(100) default NULL, + `subname_loc7` varchar(100) default NULL, + `subname_loc8` varchar(100) default NULL, + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `locales_creature` +-- + +LOCK TABLES `locales_creature` WRITE; +/*!40000 ALTER TABLE `locales_creature` DISABLE KEYS */; +/*!40000 ALTER TABLE `locales_creature` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `locales_gameobject` +-- + +DROP TABLE IF EXISTS `locales_gameobject`; +CREATE TABLE `locales_gameobject` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `name_loc1` varchar(100) NOT NULL default '', + `name_loc2` varchar(100) NOT NULL default '', + `name_loc3` varchar(100) NOT NULL default '', + `name_loc4` varchar(100) NOT NULL default '', + `name_loc5` varchar(100) NOT NULL default '', + `name_loc6` varchar(100) NOT NULL default '', + `name_loc7` varchar(100) NOT NULL default '', + `name_loc8` varchar(100) NOT NULL default '', + `castbarcaption_loc1` varchar(100) NOT NULL default '', + `castbarcaption_loc2` varchar(100) NOT NULL default '', + `castbarcaption_loc3` varchar(100) NOT NULL default '', + `castbarcaption_loc4` varchar(100) NOT NULL default '', + `castbarcaption_loc5` varchar(100) NOT NULL default '', + `castbarcaption_loc6` varchar(100) NOT NULL default '', + `castbarcaption_loc7` varchar(100) NOT NULL default '', + `castbarcaption_loc8` varchar(100) NOT NULL default '', + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `locales_gameobject` +-- + +LOCK TABLES `locales_gameobject` WRITE; +/*!40000 ALTER TABLE `locales_gameobject` DISABLE KEYS */; +/*!40000 ALTER TABLE `locales_gameobject` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `locales_item` +-- + +DROP TABLE IF EXISTS `locales_item`; +CREATE TABLE `locales_item` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `name_loc1` varchar(100) NOT NULL default '', + `name_loc2` varchar(100) NOT NULL default '', + `name_loc3` varchar(100) NOT NULL default '', + `name_loc4` varchar(100) NOT NULL default '', + `name_loc5` varchar(100) NOT NULL default '', + `name_loc6` varchar(100) NOT NULL default '', + `name_loc7` varchar(100) NOT NULL default '', + `name_loc8` varchar(100) NOT NULL default '', + `description_loc1` varchar(255) default NULL, + `description_loc2` varchar(255) default NULL, + `description_loc3` varchar(255) default NULL, + `description_loc4` varchar(255) default NULL, + `description_loc5` varchar(255) default NULL, + `description_loc6` varchar(255) default NULL, + `description_loc7` varchar(255) default NULL, + `description_loc8` varchar(255) default NULL, + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `locales_item` +-- + +LOCK TABLES `locales_item` WRITE; +/*!40000 ALTER TABLE `locales_item` DISABLE KEYS */; +/*!40000 ALTER TABLE `locales_item` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `locales_npc_text` +-- + +DROP TABLE IF EXISTS `locales_npc_text`; +CREATE TABLE `locales_npc_text` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `Text0_0_loc1` longtext, + `Text0_0_loc2` longtext, + `Text0_0_loc3` longtext, + `Text0_0_loc4` longtext, + `Text0_0_loc5` longtext, + `Text0_0_loc6` longtext, + `Text0_0_loc7` longtext, + `Text0_0_loc8` longtext, + `Text0_1_loc1` longtext, + `Text0_1_loc2` longtext, + `Text0_1_loc3` longtext, + `Text0_1_loc4` longtext, + `Text0_1_loc5` longtext, + `Text0_1_loc6` longtext, + `Text0_1_loc7` longtext, + `Text0_1_loc8` longtext, + `Text1_0_loc1` longtext, + `Text1_0_loc2` longtext, + `Text1_0_loc3` longtext, + `Text1_0_loc4` longtext, + `Text1_0_loc5` longtext, + `Text1_0_loc6` longtext, + `Text1_0_loc7` longtext, + `Text1_0_loc8` longtext, + `Text1_1_loc1` longtext, + `Text1_1_loc2` longtext, + `Text1_1_loc3` longtext, + `Text1_1_loc4` longtext, + `Text1_1_loc5` longtext, + `Text1_1_loc6` longtext, + `Text1_1_loc7` longtext, + `Text1_1_loc8` longtext, + `Text2_0_loc1` longtext, + `Text2_0_loc2` longtext, + `Text2_0_loc3` longtext, + `Text2_0_loc4` longtext, + `Text2_0_loc5` longtext, + `Text2_0_loc6` longtext, + `Text2_0_loc7` longtext, + `Text2_0_loc8` longtext, + `Text2_1_loc1` longtext, + `Text2_1_loc2` longtext, + `Text2_1_loc3` longtext, + `Text2_1_loc4` longtext, + `Text2_1_loc5` longtext, + `Text2_1_loc6` longtext, + `Text2_1_loc7` longtext, + `Text2_1_loc8` longtext, + `Text3_0_loc1` longtext, + `Text3_0_loc2` longtext, + `Text3_0_loc3` longtext, + `Text3_0_loc4` longtext, + `Text3_0_loc5` longtext, + `Text3_0_loc6` longtext, + `Text3_0_loc7` longtext, + `Text3_0_loc8` longtext, + `Text3_1_loc1` longtext, + `Text3_1_loc2` longtext, + `Text3_1_loc3` longtext, + `Text3_1_loc4` longtext, + `Text3_1_loc5` longtext, + `Text3_1_loc6` longtext, + `Text3_1_loc7` longtext, + `Text3_1_loc8` longtext, + `Text4_0_loc1` longtext, + `Text4_0_loc2` longtext, + `Text4_0_loc3` longtext, + `Text4_0_loc4` longtext, + `Text4_0_loc5` longtext, + `Text4_0_loc6` longtext, + `Text4_0_loc7` longtext, + `Text4_0_loc8` longtext, + `Text4_1_loc1` longtext, + `Text4_1_loc2` longtext, + `Text4_1_loc3` longtext, + `Text4_1_loc4` longtext, + `Text4_1_loc5` longtext, + `Text4_1_loc6` longtext, + `Text4_1_loc7` longtext, + `Text4_1_loc8` longtext, + `Text5_0_loc1` longtext, + `Text5_0_loc2` longtext, + `Text5_0_loc3` longtext, + `Text5_0_loc4` longtext, + `Text5_0_loc5` longtext, + `Text5_0_loc6` longtext, + `Text5_0_loc7` longtext, + `Text5_0_loc8` longtext, + `Text5_1_loc1` longtext, + `Text5_1_loc2` longtext, + `Text5_1_loc3` longtext, + `Text5_1_loc4` longtext, + `Text5_1_loc5` longtext, + `Text5_1_loc6` longtext, + `Text5_1_loc7` longtext, + `Text5_1_loc8` longtext, + `Text6_0_loc1` longtext, + `Text6_0_loc2` longtext, + `Text6_0_loc3` longtext, + `Text6_0_loc4` longtext, + `Text6_0_loc5` longtext, + `Text6_0_loc6` longtext, + `Text6_0_loc7` longtext, + `Text6_0_loc8` longtext, + `Text6_1_loc1` longtext, + `Text6_1_loc2` longtext, + `Text6_1_loc3` longtext, + `Text6_1_loc4` longtext, + `Text6_1_loc5` longtext, + `Text6_1_loc6` longtext, + `Text6_1_loc7` longtext, + `Text6_1_loc8` longtext, + `Text7_0_loc1` longtext, + `Text7_0_loc2` longtext, + `Text7_0_loc3` longtext, + `Text7_0_loc4` longtext, + `Text7_0_loc5` longtext, + `Text7_0_loc6` longtext, + `Text7_0_loc7` longtext, + `Text7_0_loc8` longtext, + `Text7_1_loc1` longtext, + `Text7_1_loc2` longtext, + `Text7_1_loc3` longtext, + `Text7_1_loc4` longtext, + `Text7_1_loc5` longtext, + `Text7_1_loc6` longtext, + `Text7_1_loc7` longtext, + `Text7_1_loc8` longtext, + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `locales_npc_text` +-- + +LOCK TABLES `locales_npc_text` WRITE; +/*!40000 ALTER TABLE `locales_npc_text` DISABLE KEYS */; +/*!40000 ALTER TABLE `locales_npc_text` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `locales_page_text` +-- + +DROP TABLE IF EXISTS `locales_page_text`; +CREATE TABLE `locales_page_text` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `Text_loc1` longtext, + `Text_loc2` longtext, + `Text_loc3` longtext, + `Text_loc4` longtext, + `Text_loc5` longtext, + `Text_loc6` longtext, + `Text_loc7` longtext, + `Text_loc8` longtext, + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `locales_page_text` +-- + +LOCK TABLES `locales_page_text` WRITE; +/*!40000 ALTER TABLE `locales_page_text` DISABLE KEYS */; +/*!40000 ALTER TABLE `locales_page_text` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `locales_quest` +-- + +DROP TABLE IF EXISTS `locales_quest`; +CREATE TABLE `locales_quest` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `Title_loc1` text, + `Title_loc2` text, + `Title_loc3` text, + `Title_loc4` text, + `Title_loc5` text, + `Title_loc6` text, + `Title_loc7` text, + `Title_loc8` text, + `Details_loc1` text, + `Details_loc2` text, + `Details_loc3` text, + `Details_loc4` text, + `Details_loc5` text, + `Details_loc6` text, + `Details_loc7` text, + `Details_loc8` text, + `Objectives_loc1` text, + `Objectives_loc2` text, + `Objectives_loc3` text, + `Objectives_loc4` text, + `Objectives_loc5` text, + `Objectives_loc6` text, + `Objectives_loc7` text, + `Objectives_loc8` text, + `OfferRewardText_loc1` text, + `OfferRewardText_loc2` text, + `OfferRewardText_loc3` text, + `OfferRewardText_loc4` text, + `OfferRewardText_loc5` text, + `OfferRewardText_loc6` text, + `OfferRewardText_loc7` text, + `OfferRewardText_loc8` text, + `RequestItemsText_loc1` text, + `RequestItemsText_loc2` text, + `RequestItemsText_loc3` text, + `RequestItemsText_loc4` text, + `RequestItemsText_loc5` text, + `RequestItemsText_loc6` text, + `RequestItemsText_loc7` text, + `RequestItemsText_loc8` text, + `EndText_loc1` text, + `EndText_loc2` text, + `EndText_loc3` text, + `EndText_loc4` text, + `EndText_loc5` text, + `EndText_loc6` text, + `EndText_loc7` text, + `EndText_loc8` text, + `ObjectiveText1_loc1` text, + `ObjectiveText1_loc2` text, + `ObjectiveText1_loc3` text, + `ObjectiveText1_loc4` text, + `ObjectiveText1_loc5` text, + `ObjectiveText1_loc6` text, + `ObjectiveText1_loc7` text, + `ObjectiveText1_loc8` text, + `ObjectiveText2_loc1` text, + `ObjectiveText2_loc2` text, + `ObjectiveText2_loc3` text, + `ObjectiveText2_loc4` text, + `ObjectiveText2_loc5` text, + `ObjectiveText2_loc6` text, + `ObjectiveText2_loc7` text, + `ObjectiveText2_loc8` text, + `ObjectiveText3_loc1` text, + `ObjectiveText3_loc2` text, + `ObjectiveText3_loc3` text, + `ObjectiveText3_loc4` text, + `ObjectiveText3_loc5` text, + `ObjectiveText3_loc6` text, + `ObjectiveText3_loc7` text, + `ObjectiveText3_loc8` text, + `ObjectiveText4_loc1` text, + `ObjectiveText4_loc2` text, + `ObjectiveText4_loc3` text, + `ObjectiveText4_loc4` text, + `ObjectiveText4_loc5` text, + `ObjectiveText4_loc6` text, + `ObjectiveText4_loc7` text, + `ObjectiveText4_loc8` text, + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `locales_quest` +-- + +LOCK TABLES `locales_quest` WRITE; +/*!40000 ALTER TABLE `locales_quest` DISABLE KEYS */; +/*!40000 ALTER TABLE `locales_quest` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `mangos_string` +-- + +DROP TABLE IF EXISTS `mangos_string`; +CREATE TABLE `mangos_string` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `content_default` text NOT NULL, + `content_loc1` text, + `content_loc2` text, + `content_loc3` text, + `content_loc4` text, + `content_loc5` text, + `content_loc6` text, + `content_loc7` text, + `content_loc8` text, + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `mangos_string` +-- + +LOCK TABLES `mangos_string` WRITE; +/*!40000 ALTER TABLE `mangos_string` DISABLE KEYS */; +INSERT INTO `mangos_string` VALUES +(1,'You should select a character or a creature.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(2,'You should select a creature.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(3,'|cffff0000[System Message]: %s|r',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(4,'|cffff0000[Event Message]: %s|r',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(5,'There is no help for that command',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(6,'There is no such command',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(7,'There is no such subcommand',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(8,'Command %s have subcommands:%s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(9,'Commands available to you:',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(10,'Incorrect syntax.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(11,'Your account level is: %i',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(12,'Online players: %u (max: %u) Queued players: %u (max: %u)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(13,'Server uptime: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(14,'Player saved.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(15,'All players saved.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(16,'There are the following active GMs on this server:',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(17,'There are no GMs currently logged in on this server.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(18,'Cannot do that while flying.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(19,'Cannot do that in Battlegrounds.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(20,'Target is flying you can\'t do that.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(21,'%s is flying command failed.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(22,'You are not mounted so you can\'t dismount.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(23,'Cannot do that while fighting.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(24,'You used it recently.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(25,'Your password can\'t be longer than 16 characters (client limit), password not changed!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(26,'The password was changed',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(27,'The new passwords do not match or the old password is wrong',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(28,'Your account is now locked.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(29,'Your account is now unlocked.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(30,', rank ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(31,' [known]',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(32,' [learn]',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(33,' [passive]',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(34,' [talent]',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(35,' [active]',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(36,' [complete]',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(37,' (offline)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(38,'on',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(39,'off',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(40,'You are: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(41,'visible',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(42,'invisible',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(43,'done',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(44,'You',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(45,' ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(46,'',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(47,'',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(48,'UNKNOWN',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(49,'You must be at least level %u to enter.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(50,'You must be at least level %u and have item %s to enter.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(51,'Hello! Ready for some training?',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(100,'Global notify: ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(101,'Map: %u (%s) Zone: %u (%s) Area: %u (%s)\nX: %f Y: %f Z: %f Orientation: %f\ngrid[%u,%u]cell[%u,%u] InstanceID: %u\n ZoneX: %f ZoneY: %f\nGroundZ: %f FloorZ: %f Have height data (Map: %u VMap: %u)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(102,'%s is already being teleported.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(103,'You can summon a player to your instance only if he is in your party with you as leader.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(104,'You cannot go to the player\'s instance because you are in a party now.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(105,'You can go to the player\'s instance while not being in his party only if your GM mode is on.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(106,'You can not go to player %s from instance to instance.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(107,'You can not summon player %s from instance to instance.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(108,'You are summoning %s%s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(109,'You are being summoned by %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(110,'You are teleporting %s%s to %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(111,'You are being teleported by %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(112,'Player (%s) does not exist.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(113,'Appearing at %s\'s location.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(114,'%s is appearing to your location.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(115,'Incorrect values.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(116,'No character selected.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(117,'%s is not in a group.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(118,'You changed HP of %s to %i/%i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(119,'%s changed your HP to %i/%i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(120,'You changed MANA of %s to %i/%i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(121,'%s changed your MANA to %i/%i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(122,'You changed ENERGY of %s to %i/%i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(123,'%s changed your ENERGY to %i/%i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(124,'Current energy: %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(125,'You changed rage of %s to %i/%i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(126,'%s changed your rage to %i/%i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(127,'You changed level of %s to %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(128,'GUID %i, faction is %i, flags is %i, npcflag is %i, DY flag is %i',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(129,'Wrong faction: %u (not found in factiontemplate.dbc).',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(130,'You changed GUID=%i \'s Faction to %i, flags to %i, npcflag to %i, dyflag to %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(131,'You changed the spellflatid=%i, val= %i, mark =%i to %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(132,'%s changed your spellflatid=%i, val= %i, mark =%i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(133,'%s has access to all taxi nodes now (until logout).',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(134,'%s has no more access to all taxi nodes now (only visited accessible).',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(135,'%s has given you access to all taxi nodes (until logout).',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(136,'%s has removed access to all taxi nodes (only visited still accessible).',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(137,'You set all speeds to %2.2f from normal of %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(138,'%s set all your speeds to %2.2f from normal.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(139,'You set the speed to %2.2f from normal of %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(140,'%s set your speed to %2.2f from normal.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(141,'You set the swim speed to %2.2f from normal of %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(142,'%s set your swim speed to %2.2f from normal.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(143,'You set the backwards run speed to %2.2f from normal of %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(144,'%s set your backwards run speed to %2.2f from normal.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(145,'You set the fly speed to %2.2f from normal of %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(146,'%s set your fly speed to %2.2f from normal.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(147,'You set the size %2.2f of %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(148,'%s set your size to %2.2f.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(149,'There is no such mount.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(150,'You give a mount to %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(151,'%s gave you a mount.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(152,'USER1: %i, ADD: %i, DIF: %i\n',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(153,'You take all copper of %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(154,'%s took you all of your copper.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(155,'You take %i copper from %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(156,'%s took %i copper from you.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(157,'You give %i copper to %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(158,'%s gave you %i copper.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(159,'You hear sound %u.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(160,'USER2: %i, ADD: %i, RESULT: %i\n',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(161,'Removed bit %i in field %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(162,'Set bit %i in field %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(163,'Teleport location table is empty!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(164,'Teleport location not found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(165,'Requires search parameter.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(166,'There are no teleport locations matching your request.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(167,'No locations found.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(168,'Locations found are:\n',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(169,'Mail sent to %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(170,'You try to hear sound %u but it doesn\'t exist.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(200,'No selection.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(201,'Object GUID is: lowpart %u highpart %X',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(202,'The name was too long by %i characters.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(203,'Error, name can only contain characters A-Z and a-z.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(204,'The subname was too long by %i characters.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(205,'Not yet implemented',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(206,'Item \'%i\' \'%s\' added to list with maxcount \'%i\' and incrtime \'%i\' and extendedcost \'%i\'',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(207,'Item \'%i\' not found in database.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(208,'Item \'%i\' \'%s\' deleted from vendor list',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(209,'Item \'%i\' not found in vendor list.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(210,'Item \'%i\' already in vendor list.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(211,'Spells of %s reset.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(212,'Spells of %s will reset at next login.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(213,'Talents of %s reset.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(214,'Talents of %s will reset at next login.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(215,'Your spells have been reset.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(216,'Your talents have been reset.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(217,'Unknown case \'%s\' for .resetall command. Type full correct case name.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(218,'Spells will reset for all players at login. Strongly recommend re-login!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(219,'Talents will reset for all players at login. Strongly recommend re-login!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(220,'Creature (GUID: %u) No waypoint found.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(221,'Creature (GUID: %u) Last waypoint not found.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(222,'Creature (GUID: %u) No waypoint found - used \'wpguid\'. Now trying to find it by its position...',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(223,'Creature (GUID: %u) No waypoints found - This is a MaNGOS db problem (single float).',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(224,'Selected creature is ignored - provided GUID is used',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(225,'Creature (GUID: %u) not found',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(226,'You must select a visual waypoint.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(227,'No visual waypoints found',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(228,'Could not create visual waypoint with creatureID: %d',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(229,'All visual waypoints removed',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(230,'Could not create waypoint-creature with ID: %d',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(231,'No GUID provided.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(232,'No waypoint number provided.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(233,'Argument required for \'%s\'.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(234,'Waypoint %i added to GUID: %d',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(235,'Waypoint %d added.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(236,'Waypoint changed.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(237,'Waypoint %s modified.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(238,'WP export successfull.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(239,'No waypoints found inside the database.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(240,'File imported.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(241,'Waypoint removed.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(242,'Warning: Could not delete WP from the world with ID: %d',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(243,'This happens if the waypoint is too far away from your char.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(244,'The WP is deleted from the database, but not from the world here.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(245,'They will disappear after a server restart.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(246,'Waypoint %d: Info for creature: %s, GUID: %d',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(247,'Waittime: %d',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(248,'Model %d: %d',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(249,'Emote: %d',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(250,'Spell: %d',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(251,'Text %d: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(252,'AIScript: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(253,'Forced rename for player %s will be requested at next login.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(254,'Forced rename for player %s (GUID #%u) will be requested at next login.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(255,'Waypoint-Creature (GUID: %u) Not found',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(256,'Could not find NPC...',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(257,'Creature movement type set to \'%s\', waypoints removed (if any).',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(258,'Creature movement type set to \'%s\', waypoints were not removed.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(259,'Incorrect value, use on or off',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(260,'Value saved.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(261,'Value saved, you may need to rejoin or clean your client cache.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(262,'Areatrigger ID %u not found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(263,'Target map or coordinates is invalid (X: %f Y: %f MapId: %u)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(264,'Zone coordinates is invalid (X: %f Y: %f AreaId: %u)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(265,'Zone %u (%s) is part of instanceable map %u (%s)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(266,'Nothing found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(267,'Object not found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(268,'Creature not found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(269,'Warning: Mob found more than once - you will be teleported to the first one found in DB.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(270,'Creature Removed',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(271,'Creature moved.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(272,'Creature (GUID:%u) must be on the same map as player!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(273,'Game Object (GUID: %u) not found',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(274,'Game Object (GUID: %u) has references in not found creature %u GO list, can\'t be deleted.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(275,'Game Object (GUID: %u) removed',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(276,'Game Object (GUID: %u) turned',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(277,'Game Object (GUID: %u) moved',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(278,'You must select a vendor',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(279,'You must send id for item',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(280,'Vendor has too many items (max 128)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(281,'You can\'t kick self, logout instead',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(282,'Player %s kicked.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(283,'Player %s not found.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(284,'Accepting Whisper: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(285,'Accepting Whisper: ON',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(286,'Accepting Whisper: OFF',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(287,'Creature (GUID: %u) not found',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(288,'Tickets count: %i show new tickets: %s\n',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(289,'New ticket from %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(290,'Ticket of %s (Last updated: %s):\n%s ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(291,'New ticket show: ON',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(292,'New ticket show: OFF',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(293,'Ticket %i doesn\'t exist',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(294,'All tickets deleted.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(295,'Character %s ticket deleted.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(296,'Ticket deleted.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(297,'Spawn distance changed to: %f',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(298,'Spawn time changed to: %i',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(299,'The honor of %s was set to %u!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(300,'Your chat has been disabled for %u minutes.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(301,'You have disabled %s\'s chat for %u minutes.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(302,'Player\'s chat is already enabled.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(303,'Your chat has been enabled.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(304,'You have enabled %s\'s chat.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(305, 'Faction %s (%u) reputation of %s was set to %5d!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(306, 'The arena points of %s was set to %u!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(307, 'No faction found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(308, 'Faction %i unknown!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(309, 'Invalid parameter %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(310, 'delta must be between 0 and %d (inclusive)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(311, '%d - |cffffffff|Hfaction:%d|h[%s]|h|r',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(312, ' [visible]',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(313, ' [at war]',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(314, ' [peace forced]',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(315, ' [hidden]',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(316, ' [invisible forced]',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(317, ' [inactive]',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(318, 'Hated',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(319, 'Hostile',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(320, 'Unfriendly',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(321, 'Neutral',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(322, 'Friendly',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(323, 'Honored',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(324, 'Revered',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(325, 'Exalted',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(326, 'Faction %s (%u) can\'not have reputation.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(327, ' [no reputation]',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(400,'|cffff0000[System Message]:|rScripts reloaded',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(401,'You change security level of %s to %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(402,'%s changed your security level to %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(403,'You have low security level for this.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(404,'Creature movement disabled.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(405,'Creature movement enabled.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(406,'Weather can\'t be changed for this zone.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(407,'Weather system disabled at server.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(408,'%s is banned for %s. Reason: %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(409,'%s is banned permanently for %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(410,'%s %s not found',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(411,'%s unbanned.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(412,'There was an error removing the ban on %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(413,'There is no such account.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(414,'There is no such character.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(415,'There is no such IP in banlist.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(416,'Account %s has never been banned',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(417,'Ban history for account %s:',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(418,'Ban Date: %s Bantime: %s Still active: %s Reason: %s Set by: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(419,'Inf.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(420,'Never',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(421,'Yes',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(422,'No',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(423,'IP: %s\nBan Date: %s\nUnban Date: %s\nRemaining: %s\nReason: %s\nSet by: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(424,'There is no matching IPban.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(425,'There is no matching account.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(426,'There is no banned account owning a character matching this part.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(427,'The following IPs match your pattern:',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(428,'The following accounts match your query:',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(429,'You learned many spells/skills.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(430,'You learned all spells for class.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(431,'You learned all talents for class.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(432,'You learned all languages.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(433,'You learned all craft skills and recipes.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(434,'Could not find \'%s\'',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(435,'Invalid item id: %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(436,'No items found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(437,'Invalid gameobject id: %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(438,'Found items %u: %u ( inventory %u mail %u auction %u )',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(439,'Found gameobjects %u: %u ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(440,'Invalid creature id: %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(441,'Found creatures %u: %u ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(442,'No area found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(443,'No item sets found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(444,'No skills found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(445,'No spells found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(446,'No quests found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(447,'No creatures found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(448,'No gameobjects found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(449,'Graveyard #%u doesn\'t exist.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(450,'Graveyard #%u already linked to zone #%u (current).',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(451,'Graveyard #%u linked to zone #%u (current).',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(452,'Graveyard #%u can\'t be linked to subzone or not existed zone #%u (internal error).',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(453,'Graveyard can be linked to zone at another map only for all factions (no faction value).',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(454,'No faction in Graveyard with id= #%u , fix your DB',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(455,'invalid team, please fix database',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(456,'any',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(457,'alliance',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(458,'horde',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(459,'Graveyard #%u (faction: %s) is nearest from linked to zone #%u.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(460,'Zone #%u doesn\'t have linked graveyards.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(461,'Zone #%u doesn\'t have linked graveyards for faction: %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(462,'Teleport location already exists!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(463,'Teleport location added.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(464,'Teleport location NOT added: database error.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(465,'Teleport location deleted.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(466,'Teleport location NOT deleted: database error.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(467,'Target unit has %d auras:',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(468,'id: %d eff: %d type: %d duration: %d maxduration: %d name: %s%s%s caster: %s %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(469,'Target unit has %d auras of type %d:',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(470,'id: %d eff: %d name: %s%s%s caster: %s %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(471,'Quest %u not found.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(472,'Quest %u started from item. For correct work, please, add item to inventory and start quest in normal way: .additem %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(473,'Quest removed.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(474,' [rewarded]',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(475,' [complete]',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(476,' [active]',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(477,'%s\'s Fly Mode %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(478,'Opcode %u sent to %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(479,'Character loaded successfully!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(480,'Failed to load the character!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(481,'Character dumped successfully!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(482,'Character dump failed!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(483,'Spell %u broken and not allowed to cast or learn!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(484,'Skill %u (%s) for player %s set to %u and current maximum set to %u (without permanent (talent) bonuses).',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(485,'Player %s must have skill %u (%s) before using this command.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(486,'Invalid skill id (%u)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(487,'You learned default GM spells/skills.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(488,'You already know that spell.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(489,'Target(%s) already know that spell.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(490,'%s doesn\'t know that spell.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(491,'You already forgot that spell.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(492,'All spell cooldowns removed for %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(493,'Spell %u cooldown removed for %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(494,'Command : Additem, itemId = %i, amount = %i',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(495,'Command : Additemset, itemsetId = %i',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(496,'Removed itemID = %i, amount = %i from %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(497,'Cannot create item \'%i\' (amount: %i)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(498,'You need to provide a guild name!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(499,'Player not found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(500,'Player already has a guild!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(501,'Guild not created! (already exists?)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(502,'No items from itemset \'%u\' found.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(503,'The distance is: (3D) %f (2D) %f yards.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(504,'Item \'%i\' \'%s\' Item Slot %i',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(505,'Item \'%i\' doesn\'t exist.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(506,'Item \'%i\' \'%s\' Added to Slot %i',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(507,'Item save failed!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(508,'%d - owner: %s (guid: %u account: %u ) %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(509,'%d - sender: %s (guid: %u account: %u ) receiver: %s (guid: %u account: %u ) %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(510,'%d - owner: %s (guid: %u account: %u ) %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(511,'Wrong link type!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(512,'%d - |cffffffff|Hitem:%d:0:0:0:0:0:0:0|h[%s]|h|r ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(513,'%d - |cffffffff|Hquest:%d|h[%s]|h|r %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(514,'%d - |cffffffff|Hcreature_entry:%d|h[%s]|h|r ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(515,'%d - |cffffffff|Hcreature:%d|h[%s X:%f Y:%f Z:%f MapId:%d]|h|r ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(516,'%d - |cffffffff|Hgameobject_entry:%d|h[%s]|h|r ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(517,'%d - |cffffffff|Hgameobject:%d|h[%s X:%f Y:%f Z:%f MapId:%d]|h|r ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(518,'%d - |cffffffff|Hitemset:%d|h[%s %s]|h|r ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(519,'|cffffffff|Htele:%s|h[%s]|h|r ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(520,'%d - |cffffffff|Hspell:%d|h[%s]|h|r ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(521,'%d - |cffffffff|Hskill:%d|h[%s %s]|h|r %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(522,'Game Object (GUID: %u) not found',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(523,'>> Game Object %s (GUID: %u) at %f %f %f. Orientation %f.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(524,'Selected object:\n|cffffffff|Hitemset:%d|h[%s]|h|r\nGUID: %u ID: %u\nX: %f Y: %f Z: %f MapId: %u\nOrientation: %f',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(525,'>> Add Game Object \'%i\' (%s) (GUID: %i) added at \'%f %f %f\'.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(526,'%s (lowguid: %u) movement generators stack:',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(527,' Idle',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(528,' Random',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(529,' Waypoint',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(530,' Animal random',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(531,' Confused',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(532,' Targeted to player %s (lowguid %u)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(533,' Targeted to creature %s (lowguid %u)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(534,' Targeted to ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(535,' Home movement to (X:%f Y:%f Z:%f)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(536,' Home movement used for player?!?',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(537,' Taxi flight',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(538,' Unknown movement generator (%u)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(539,'Player selected NPC\nGUID: %u.\nFaction: %u.\nnpcFlags: %u.\nEntry: %u.\nDisplayID: %u (Native: %u).',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(540,'Level: %u.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(541,'Health (base): %u. (max): %u. (current): %u.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(542,'Field Flags: %u.\nDynamic Flags: %u.\nFaction Template: %u.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(543,'Loot: %u Pickpocket: %u Skinning: %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(544,'Position: %f %f %f.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(545,'*** Is a vendor!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(546,'*** Is a trainer!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(547,'InstanceID: %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(548,'Player%s %s (guid: %u) Account: %s (id: %u) GMLevel: %u Last IP: %s Last login: %s Latency: %ums',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(549,'Played time: %s Level: %u Money: %ug%us%uc',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(550,'Command .pinfo doesn\'t support \'rep\' option for offline players.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(551,'%s has explored all zones now.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(552,'%s has no more explored zones.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(553,'%s has explored all zones for you.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(554,'%s has hidden all zones from you.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(555,'Hover enabled',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(556,'Hover disabled',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(557,'You have been leveled up (%i)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(558,'You have been leveled down (%i)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(559,'Your level progress has been reset.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(560,'The area has been set as explored.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(561,'The area has been set as not explored.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(562,'GUID=%i \'s updateIndex: %i, value: %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(563,'You change GUID=%i \'s UpdateIndex: %i value to %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(564,'The value index %u is too big to %u(count: %u).',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(565,'Set %u uint32 Value:[OPCODE]:%u [VALUE]:%u',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(566,'You Set %u Field:%u to uint32 Value: %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(567,'Set %u float Value:[OPCODE]:%u [VALUE]:%f',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(568,'You Set %u Field:%i to float Value: %f',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(569,'Get %u uint32 Value:[OPCODE]:%u [VALUE]:%u',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(570,'The uint32 value of %u in %u is: %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(571,'Get %u float Value:[OPCODE]:%u [VALUE]:%f',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(572,'The float of %u value in %u is: %f',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(573,'.Set32Bit:[OPCODE]:%u [VALUE]:%u',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(574,'You set Bit of Field:%u to Value: %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(575,'.Mod32Value:[OPCODE]:%u [VALUE]:%i',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(576,'You modified the value of Field:%u to Value: %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(577,'You are now invisible.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(578,'You are now visible.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(579,'Selected player or creature not have victim.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(580,'You learned all default spells for race/class and completed quests rewarded spells.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(581,'Found near gameobjects (distance %f): %u ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(582,'SpawnTime: Full:%s Remain:%s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(583,'%d - |cffffffff|Hgameevent:%d|h[%s]|h|r%s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(584,'No event found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(585,'Event not exist!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(586,'Event %u: %s%s\nStart: %s End: %s Occurence: %s Length: %s\nNext state change: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(587,'Event %u already active!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(588,'Event %u not active!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(589,' Point movement to (X:%f Y:%f Z:%f)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(590,' Fear movement',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(591,' Distract movement',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(592,'You have learned all spells in craft: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(600,'The Alliance wins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(601,'The Horde wins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(602,'The battle for Warsong Gulch begins in 1 minute.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(603,'The battle for Warsong Gulch begins in 30 seconds. Prepare yourselves!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(604,'Let the battle for Warsong Gulch begin!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(605,'$n captured the Horde flag!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(606,'$n captured the Alliance flag!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(607,'The Horde flag was dropped by $n!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(608,'The Alliance Flag was dropped by $n!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(609,'The Alliance Flag was returned to its base by $n!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(610,'The Horde flag was returned to its base by $n!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(611,'The Horde flag was picked up by $n!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(612,'The Alliance Flag was picked up by $n!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(613,'The flags are now placed at their bases.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(636,'The Battle for Eye of the Storm begins in 1 minute.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(637,'The Battle for Eye of the Storm begins in 30 seconds.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(638,'The Battle for Eye of the Storm has begun!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(650,'Alliance',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(651,'Horde',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(652,'stables',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(653,'blacksmith',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(654,'farm',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(655,'lumber mill',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(656,'mine',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(657,'The %s has taken the %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(658,'$n has defended the %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(659,'$n has assaulted the %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(660,'$n claims the %s! If left unchallenged, the %s will control it in 1 minute!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(661,'The Battle for Arathi Basin begins in 1 minute.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(662,'The Battle for Arathi Basin begins in 30 seconds. Prepare yourselves!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(663,'The Battle for Arathi Basin has begun!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(664,'The Alliance has gathered $1776W resources, and is near victory!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(665,'The Horde has gathered $1777W resources, and is near victory!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(666,'After your recent battle in %s our best attempts to award you a Mark of Honor failed. Enclosed you will find the Mark of Honor we were not able to deliver to you at the time. Thanks for fighting in %s!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(700,'You must be level %u to form an arena team',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(701,'One minute until the Arena battle begins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(702,'Thirty seconds until the Arena battle begins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(703,'Fifteen seconds until the Arena battle begins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(704,'The Arena battle has begun!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(705,'You must wait %s before speaking again.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(706,'This item(s) have problems with equipping/storing in inventory.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(707,'%s wishes to not be disturbed and cannot receive whisper messages: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(708,'%s is Away from Keyboard: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(709,'Do not Disturb',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(710,'Away from Keyboard',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(711,'Queue status for %s (Lvl: %u to %u)\nQueued alliances: %u (Need at least %u more)\nQueued hordes: %u (Need at least %u more)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(712,'|cffff0000[BG Queue Announcer]:|r %s -- [%u-%u] A: %u (Need: %u), H: %u (Needs %u)|r',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); +/*!40000 ALTER TABLE `mangos_string` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `npc_gossip` +-- + +DROP TABLE IF EXISTS `npc_gossip`; +CREATE TABLE `npc_gossip` ( + `npc_guid` int(10) unsigned NOT NULL default '0', + `textid` mediumint(8) unsigned NOT NULL default '0', + PRIMARY KEY (`npc_guid`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `npc_gossip` +-- + +LOCK TABLES `npc_gossip` WRITE; +/*!40000 ALTER TABLE `npc_gossip` DISABLE KEYS */; +/*!40000 ALTER TABLE `npc_gossip` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `npc_gossip_textid` +-- + +DROP TABLE IF EXISTS `npc_gossip_textid`; +CREATE TABLE `npc_gossip_textid` ( + `zoneid` smallint(5) unsigned NOT NULL default '0', + `action` smallint(5) unsigned NOT NULL default '0', + `textid` mediumint(8) unsigned NOT NULL default '0', + KEY `zoneid` (`zoneid`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `npc_gossip_textid` +-- + +LOCK TABLES `npc_gossip_textid` WRITE; +/*!40000 ALTER TABLE `npc_gossip_textid` DISABLE KEYS */; +/*!40000 ALTER TABLE `npc_gossip_textid` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `npc_option` +-- + +DROP TABLE IF EXISTS `npc_option`; +CREATE TABLE `npc_option` ( + `id` tinyint(3) unsigned NOT NULL default '0', + `gossip_id` tinyint(3) unsigned NOT NULL default '0', + `npcflag` int(10) unsigned NOT NULL default '0', + `icon` tinyint(3) unsigned NOT NULL default '0', + `action` tinyint(3) unsigned NOT NULL default '0', + `option_text` text, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `npc_option` +-- + +LOCK TABLES `npc_option` WRITE; +/*!40000 ALTER TABLE `npc_option` DISABLE KEYS */; +/*!40000 ALTER TABLE `npc_option` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `npc_text` +-- + +DROP TABLE IF EXISTS `npc_text`; +CREATE TABLE `npc_text` ( + `ID` mediumint(8) unsigned NOT NULL default '0', + `text0_0` longtext, + `text0_1` longtext, + `lang0` tinyint(3) unsigned NOT NULL default '0', + `prob0` float NOT NULL default '0', + `em0_0` smallint(5) unsigned NOT NULL default '0', + `em0_1` smallint(5) unsigned NOT NULL default '0', + `em0_2` smallint(5) unsigned NOT NULL default '0', + `em0_3` smallint(5) unsigned NOT NULL default '0', + `em0_4` smallint(5) unsigned NOT NULL default '0', + `em0_5` smallint(5) unsigned NOT NULL default '0', + `text1_0` longtext, + `text1_1` longtext, + `lang1` tinyint(3) unsigned NOT NULL default '0', + `prob1` float NOT NULL default '0', + `em1_0` smallint(5) unsigned NOT NULL default '0', + `em1_1` smallint(5) unsigned NOT NULL default '0', + `em1_2` smallint(5) unsigned NOT NULL default '0', + `em1_3` smallint(5) unsigned NOT NULL default '0', + `em1_4` smallint(5) unsigned NOT NULL default '0', + `em1_5` smallint(5) unsigned NOT NULL default '0', + `text2_0` longtext, + `text2_1` longtext, + `lang2` tinyint(3) unsigned NOT NULL default '0', + `prob2` float NOT NULL default '0', + `em2_0` smallint(5) unsigned NOT NULL default '0', + `em2_1` smallint(5) unsigned NOT NULL default '0', + `em2_2` smallint(5) unsigned NOT NULL default '0', + `em2_3` smallint(5) unsigned NOT NULL default '0', + `em2_4` smallint(5) unsigned NOT NULL default '0', + `em2_5` smallint(5) unsigned NOT NULL default '0', + `text3_0` longtext, + `text3_1` longtext, + `lang3` tinyint(3) unsigned NOT NULL default '0', + `prob3` float NOT NULL default '0', + `em3_0` smallint(5) unsigned NOT NULL default '0', + `em3_1` smallint(5) unsigned NOT NULL default '0', + `em3_2` smallint(5) unsigned NOT NULL default '0', + `em3_3` smallint(5) unsigned NOT NULL default '0', + `em3_4` smallint(5) unsigned NOT NULL default '0', + `em3_5` smallint(5) unsigned NOT NULL default '0', + `text4_0` longtext, + `text4_1` longtext, + `lang4` tinyint(3) unsigned NOT NULL default '0', + `prob4` float NOT NULL default '0', + `em4_0` smallint(5) unsigned NOT NULL default '0', + `em4_1` smallint(5) unsigned NOT NULL default '0', + `em4_2` smallint(5) unsigned NOT NULL default '0', + `em4_3` smallint(5) unsigned NOT NULL default '0', + `em4_4` smallint(5) unsigned NOT NULL default '0', + `em4_5` smallint(5) unsigned NOT NULL default '0', + `text5_0` longtext, + `text5_1` longtext, + `lang5` tinyint(3) unsigned NOT NULL default '0', + `prob5` float NOT NULL default '0', + `em5_0` smallint(5) unsigned NOT NULL default '0', + `em5_1` smallint(5) unsigned NOT NULL default '0', + `em5_2` smallint(5) unsigned NOT NULL default '0', + `em5_3` smallint(5) unsigned NOT NULL default '0', + `em5_4` smallint(5) unsigned NOT NULL default '0', + `em5_5` smallint(5) unsigned NOT NULL default '0', + `text6_0` longtext, + `text6_1` longtext, + `lang6` tinyint(3) unsigned NOT NULL default '0', + `prob6` float NOT NULL default '0', + `em6_0` smallint(5) unsigned NOT NULL default '0', + `em6_1` smallint(5) unsigned NOT NULL default '0', + `em6_2` smallint(5) unsigned NOT NULL default '0', + `em6_3` smallint(5) unsigned NOT NULL default '0', + `em6_4` smallint(5) unsigned NOT NULL default '0', + `em6_5` smallint(5) unsigned NOT NULL default '0', + `text7_0` longtext, + `text7_1` longtext, + `lang7` tinyint(3) unsigned NOT NULL default '0', + `prob7` float NOT NULL default '0', + `em7_0` smallint(5) unsigned NOT NULL default '0', + `em7_1` smallint(5) unsigned NOT NULL default '0', + `em7_2` smallint(5) unsigned NOT NULL default '0', + `em7_3` smallint(5) unsigned NOT NULL default '0', + `em7_4` smallint(5) unsigned NOT NULL default '0', + `em7_5` smallint(5) unsigned NOT NULL default '0', + PRIMARY KEY (`ID`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `npc_text` +-- + +LOCK TABLES `npc_text` WRITE; +/*!40000 ALTER TABLE `npc_text` DISABLE KEYS */; +/*!40000 ALTER TABLE `npc_text` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `npc_trainer` +-- + +DROP TABLE IF EXISTS `npc_trainer`; +CREATE TABLE `npc_trainer` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `spell` mediumint(8) unsigned NOT NULL default '0', + `spellcost` int(10) unsigned NOT NULL default '0', + `reqskill` smallint(5) unsigned NOT NULL default '0', + `reqskillvalue` smallint(5) unsigned NOT NULL default '0', + `reqlevel` tinyint(3) unsigned NOT NULL default '0', + UNIQUE KEY `entry_spell` (`entry`,`spell`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `npc_trainer` +-- + +LOCK TABLES `npc_trainer` WRITE; +/*!40000 ALTER TABLE `npc_trainer` DISABLE KEYS */; +/*!40000 ALTER TABLE `npc_trainer` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `npc_vendor` +-- + +DROP TABLE IF EXISTS `npc_vendor`; +CREATE TABLE `npc_vendor` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `item` mediumint(8) unsigned NOT NULL default '0', + `maxcount` tinyint(3) unsigned NOT NULL default '0', + `incrtime` int(10) unsigned NOT NULL default '0', + `ExtendedCost` mediumint(8) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`,`item`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Npc System'; + +-- +-- Dumping data for table `npc_vendor` +-- + +LOCK TABLES `npc_vendor` WRITE; +/*!40000 ALTER TABLE `npc_vendor` DISABLE KEYS */; +/*!40000 ALTER TABLE `npc_vendor` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `page_text` +-- + +DROP TABLE IF EXISTS `page_text`; +CREATE TABLE `page_text` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `text` longtext NOT NULL, + `next_page` mediumint(8) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Item System'; + +-- +-- Dumping data for table `page_text` +-- + +LOCK TABLES `page_text` WRITE; +/*!40000 ALTER TABLE `page_text` DISABLE KEYS */; +/*!40000 ALTER TABLE `page_text` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `pet_levelstats` +-- + +DROP TABLE IF EXISTS `pet_levelstats`; +CREATE TABLE `pet_levelstats` ( + `creature_entry` mediumint(8) unsigned NOT NULL, + `level` tinyint(3) unsigned NOT NULL, + `hp` smallint(5) unsigned NOT NULL, + `mana` smallint(5) unsigned NOT NULL, + `armor` int(10) unsigned NOT NULL default '0', + `str` smallint(5) unsigned NOT NULL, + `agi` smallint(5) unsigned NOT NULL, + `sta` smallint(5) unsigned NOT NULL, + `inte` smallint(5) unsigned NOT NULL, + `spi` smallint(5) unsigned NOT NULL, + PRIMARY KEY (`creature_entry`,`level`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 PACK_KEYS=0 COMMENT='Stores pet levels stats.'; + +-- +-- Dumping data for table `pet_levelstats` +-- + +LOCK TABLES `pet_levelstats` WRITE; +/*!40000 ALTER TABLE `pet_levelstats` DISABLE KEYS */; +/*!40000 ALTER TABLE `pet_levelstats` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `pet_name_generation` +-- + +DROP TABLE IF EXISTS `pet_name_generation`; +CREATE TABLE `pet_name_generation` ( + `id` mediumint(8) unsigned NOT NULL auto_increment, + `word` tinytext NOT NULL, + `entry` mediumint(8) unsigned NOT NULL default '0', + `half` tinyint(4) NOT NULL default '0', + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `pet_name_generation` +-- + +LOCK TABLES `pet_name_generation` WRITE; +/*!40000 ALTER TABLE `pet_name_generation` DISABLE KEYS */; +INSERT INTO `pet_name_generation` (`word`,`entry`,`half`) VALUES +('Aba',416,0), +('Az',416,0), +('Bel',416,0), +('Biz',416,0), +('Cho',416,0), +('Dag',416,0), +('Gak',416,0), +('Gar',416,0), +('Gel',416,0), +('Gho',416,0), +('Gob',416,0), +('Gra',416,0), +('Jak',416,0), +('Jub',416,0), +('Kar',416,0), +('Kup',416,0), +('Laz',416,0), +('Nal',416,0), +('Nok',416,0), +('Pag',416,0), +('Pig',416,0), +('Pip',416,0), +('Piz',416,0), +('Quz',416,0), +('Rui',416,0), +('Rul',416,0), +('Rup',416,0), +('Tar',416,0), +('Vol',416,0), +('Yaz',416,0), +('Zep',416,0), +('Zig',416,0), +('Zil',416,0), +('Zor',416,0), +('bis',416,1), +('fip',416,1), +('gup',416,1), +('ham',416,1), +('jub',416,1), +('kin',416,1), +('kol',416,1), +('lop',416,1), +('loz',416,1), +('mat',416,1), +('mir',416,1), +('nam',416,1), +('nar',416,1), +('nik',416,1), +('nip',416,1), +('pad',416,1), +('pep',416,1), +('pit',416,1), +('qua',416,1), +('rai',416,1), +('rin',416,1), +('rot',416,1), +('tai',416,1), +('tal',416,1), +('tik',416,1), +('tip',416,1), +('tog',416,1), +('tuk',416,1), +('uri',416,1), +('yal',416,1), +('yap',416,1), +('Bhee',417,0), +('Bruu',417,0), +('Czaa',417,0), +('Droo',417,0), +('Flaa',417,0), +('Fzuu',417,0), +('Ghaa',417,0), +('Gree',417,0), +('Gzaa',417,0), +('Haa',417,0), +('Haad',417,0), +('Haag',417,0), +('Haap',417,0), +('Jhaa',417,0), +('Jhuu',417,0), +('Khaa',417,0), +('Khii',417,0), +('Khuu',417,0), +('Kree',417,0), +('Luu',417,0), +('Maa',417,0), +('Nhee',417,0), +('Phuu',417,0), +('Pryy',417,0), +('Rhuu',417,0), +('Shaa',417,0), +('Sloo',417,0), +('Sruu',417,0), +('Thoo',417,0), +('Traa',417,0), +('Wraa',417,0), +('Zhaa',417,0), +('dhon',417,1), +('dhum',417,1), +('dhun',417,1), +('dom',417,1), +('don',417,1), +('drom',417,1), +('dym',417,1), +('fenn',417,1), +('fum',417,1), +('fun',417,1), +('ghon',417,1), +('ghun',417,1), +('grom',417,1), +('grym',417,1), +('hom',417,1), +('hon',417,1), +('hun',417,1), +('jhom',417,1), +('kun',417,1), +('lum',417,1), +('mmon',417,1), +('mon',417,1), +('myn',417,1), +('nam',417,1), +('nem',417,1), +('nhym',417,1), +('nom',417,1), +('num',417,1), +('phom',417,1), +('roon',417,1), +('rym',417,1), +('shon',417,1), +('thun',417,1), +('tom',417,1), +('zhem',417,1), +('zhum',417,1), +('zun',417,1), +('Bar',1860,0), +('Bel',1860,0), +('Char',1860,0), +('Grak\'',1860,0), +('Graz\'',1860,0), +('Grim',1860,0), +('Hath',1860,0), +('Hel',1860,0), +('Hok',1860,0), +('Huk',1860,0), +('Jhaz',1860,0), +('Jhom',1860,0), +('Juk\'',1860,0), +('Kal\'',1860,0), +('Klath',1860,0), +('Kon',1860,0), +('Krag',1860,0), +('Krak',1860,0), +('Mak',1860,0), +('Mezz',1860,0), +('Orm',1860,0), +('Phan',1860,0), +('Sar',1860,0), +('Tang',1860,0), +('Than',1860,0), +('Thog',1860,0), +('Thok',1860,0), +('Thul',1860,0), +('Zag\'',1860,0), +('Zang',1860,0), +('Zhar\'',1860,0), +('kath',1860,1), +('doc',1860,1), +('dok',1860,1), +('gak',1860,1), +('garth',1860,1), +('gore',1860,1), +('gorg',1860,1), +('grave',1860,1), +('gron',1860,1), +('juk',1860,1), +('krast',1860,1), +('kresh',1860,1), +('krit',1860,1), +('los',1860,1), +('mon',1860,1), +('mos',1860,1), +('moth',1860,1), +('nagma',1860,1), +('nak',1860,1), +('nar',1860,1), +('nos',1860,1), +('nuz',1860,1), +('phog',1860,1), +('rath',1860,1), +('tast',1860,1), +('taz',1860,1), +('thak',1860,1), +('thang',1860,1), +('thyk',1860,1), +('vhug',1860,1), +('zazt',1860,1), +('Ael',1863,0), +('Aez',1863,0), +('Ang',1863,0), +('Ban',1863,0), +('Bet',1863,0), +('Bro',1863,0), +('Bry',1863,0), +('Cat',1863,0), +('Dir',1863,0), +('Dis',1863,0), +('Dom',1863,0), +('Drus',1863,0), +('Fie',1863,0), +('Fier',1863,0), +('Gly',1863,0), +('Hel',1863,0), +('Hes',1863,0), +('Kal',1863,0), +('Lyn',1863,0), +('Mir',1863,0), +('Nim',1863,0), +('Sar',1863,0), +('Sel',1863,0), +('Vil',1863,0), +('Zah',1863,0), +('aith',1863,1), +('anda',1863,1), +('antia',1863,1), +('evere',1863,1), +('lia',1863,1), +('lissa',1863,1), +('neri',1863,1), +('neth',1863,1), +('nia',1863,1), +('nlissa',1863,1), +('nora',1863,1), +('nva',1863,1), +('nys',1863,1), +('ola',1863,1), +('ona',1863,1), +('ora',1863,1), +('rah',1863,1), +('riana',1863,1), +('riel',1863,1), +('rona',1863,1), +('tai',1863,1), +('tevere',1863,1), +('thea',1863,1), +('vina',1863,1), +('wena',1863,1), +('wyn',1863,1), +('xia',1863,1), +('yla',1863,1), +('yssa',1863,1), +('Flaa',17252,0), +('Haa',17252,0), +('Jhuu',17252,0), +('Shaa',17252,0), +('Thoo',17252,0), +('dhun',17252,1), +('ghun',17252,1), +('roon',17252,1), +('thun',17252,1), +('tom',17252,1); + +/*!40000 ALTER TABLE `pet_name_generation` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `petcreateinfo_spell` +-- + +DROP TABLE IF EXISTS `petcreateinfo_spell`; +CREATE TABLE `petcreateinfo_spell` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `Spell1` mediumint(8) unsigned NOT NULL default '0', + `Spell2` mediumint(8) unsigned NOT NULL default '0', + `Spell3` mediumint(8) unsigned NOT NULL default '0', + `Spell4` mediumint(8) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Pet Create Spells'; + +-- +-- Dumping data for table `petcreateinfo_spell` +-- + +LOCK TABLES `petcreateinfo_spell` WRITE; +/*!40000 ALTER TABLE `petcreateinfo_spell` DISABLE KEYS */; +/*!40000 ALTER TABLE `petcreateinfo_spell` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `pickpocketing_loot_template` +-- + +DROP TABLE IF EXISTS `pickpocketing_loot_template`; +CREATE TABLE `pickpocketing_loot_template` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `item` mediumint(8) unsigned NOT NULL default '0', + `ChanceOrQuestChance` float NOT NULL default '100', + `groupid` tinyint(3) unsigned NOT NULL default '0', + `mincountOrRef` mediumint(9) NOT NULL default '1', + `maxcount` tinyint(3) unsigned NOT NULL default '1', + `lootcondition` tinyint(3) unsigned NOT NULL default '0', + `condition_value1` mediumint(8) unsigned NOT NULL default '0', + `condition_value2` mediumint(8) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`,`item`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Loot System'; + +-- +-- Dumping data for table `pickpocketing_loot_template` +-- + +LOCK TABLES `pickpocketing_loot_template` WRITE; +/*!40000 ALTER TABLE `pickpocketing_loot_template` DISABLE KEYS */; +/*!40000 ALTER TABLE `pickpocketing_loot_template` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `player_classlevelstats` +-- + +DROP TABLE IF EXISTS `player_classlevelstats`; +CREATE TABLE `player_classlevelstats` ( + `class` tinyint(3) unsigned NOT NULL, + `level` tinyint(3) unsigned NOT NULL, + `basehp` smallint(5) unsigned NOT NULL, + `basemana` smallint(5) unsigned NOT NULL, + PRIMARY KEY (`class`,`level`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 PACK_KEYS=0 COMMENT='Stores levels stats.'; + +-- +-- Dumping data for table `player_classlevelstats` +-- + +LOCK TABLES `player_classlevelstats` WRITE; +/*!40000 ALTER TABLE `player_classlevelstats` DISABLE KEYS */; +INSERT INTO `player_classlevelstats` VALUES +(1,1,20,0), +(1,2,29,0), +(1,3,38,0), +(1,4,47,0), +(1,5,56,0), +(1,6,65,0), +(1,7,74,0), +(1,8,83,0), +(1,9,92,0), +(1,10,101,0), +(1,11,100,0), +(1,12,109,0), +(1,13,118,0), +(1,14,128,0), +(1,15,139,0), +(1,16,151,0), +(1,17,154,0), +(1,18,168,0), +(1,19,183,0), +(1,20,199,0), +(1,21,206,0), +(1,22,224,0), +(1,23,243,0), +(1,24,253,0), +(1,25,274,0), +(1,26,296,0), +(1,27,309,0), +(1,28,333,0), +(1,29,348,0), +(1,30,374,0), +(1,31,401,0), +(1,32,419,0), +(1,33,448,0), +(1,34,468,0), +(1,35,499,0), +(1,36,521,0), +(1,37,545,0), +(1,38,581,0), +(1,39,609,0), +(1,40,649,0), +(1,41,681,0), +(1,42,715,0), +(1,43,761,0), +(1,44,799,0), +(1,45,839,0), +(1,46,881,0), +(1,47,935,0), +(1,48,981,0), +(1,49,1029,0), +(1,50,1079,0), +(1,51,1131,0), +(1,52,1185,0), +(1,53,1241,0), +(1,54,1299,0), +(1,55,1359,0), +(1,56,1421,0), +(1,57,1485,0), +(1,58,1551,0), +(1,59,1619,0), +(1,60,1689,0), +(1,61,1902,0), +(1,62,2129,0), +(1,63,2357,0), +(1,64,2612,0), +(1,65,2883,0), +(1,66,3169,0), +(1,67,3455,0), +(1,68,3774,0), +(1,69,4109,0), +(1,70,4444,0), +(2,1,28,60), +(2,2,36,78), +(2,3,44,98), +(2,4,52,104), +(2,5,60,111), +(2,6,68,134), +(2,7,76,143), +(2,8,84,153), +(2,9,92,179), +(2,10,100,192), +(2,11,108,205), +(2,12,116,219), +(2,13,124,249), +(2,14,132,265), +(2,15,131,282), +(2,16,141,315), +(2,17,152,334), +(2,18,164,354), +(2,19,177,390), +(2,20,191,412), +(2,21,206,435), +(2,22,222,459), +(2,23,239,499), +(2,24,247,525), +(2,25,266,552), +(2,26,286,579), +(2,27,307,621), +(2,28,329,648), +(2,29,342,675), +(2,30,366,702), +(2,31,391,729), +(2,32,407,756), +(2,33,434,798), +(2,34,462,825), +(2,35,481,852), +(2,36,511,879), +(2,37,542,906), +(2,38,564,933), +(2,39,597,960), +(2,40,621,987), +(2,41,656,1014), +(2,42,682,1041), +(2,43,719,1068), +(2,44,747,1110), +(2,45,786,1137), +(2,46,816,1164), +(2,47,857,1176), +(2,48,889,1203), +(2,49,922,1230), +(2,50,966,1257), +(2,51,1001,1284), +(2,52,1037,1311), +(2,53,1084,1338), +(2,54,1122,1365), +(2,55,1161,1392), +(2,56,1201,1419), +(2,57,1252,1446), +(2,58,1294,1458), +(2,59,1337,1485), +(2,60,1381,1512), +(2,61,1540,1656), +(2,62,1708,1800), +(2,63,1884,1944), +(2,64,2068,2088), +(2,65,2262,2232), +(2,66,2466,2377), +(2,67,2679,2521), +(2,68,2901,2665), +(2,69,3134,2809), +(2,70,3377,2953), +(3,1,46,65), +(3,2,53,70), +(3,3,60,76), +(3,4,67,98), +(3,5,74,106), +(3,6,81,130), +(3,7,88,140), +(3,8,95,166), +(3,9,102,193), +(3,10,109,206), +(3,11,116,235), +(3,12,123,250), +(3,13,130,266), +(3,14,138,298), +(3,15,147,316), +(3,16,157,350), +(3,17,168,370), +(3,18,180,391), +(3,19,193,428), +(3,20,207,451), +(3,21,222,475), +(3,22,238,515), +(3,23,255,541), +(3,24,273,568), +(3,25,292,611), +(3,26,312,640), +(3,27,333,670), +(3,28,355,715), +(3,29,378,745), +(3,30,402,775), +(3,31,417,805), +(3,32,443,850), +(3,33,470,880), +(3,34,498,910), +(3,35,527,940), +(3,36,547,970), +(3,37,578,1015), +(3,38,610,1045), +(3,39,643,1075), +(3,40,667,1105), +(3,41,702,1135), +(3,42,738,1180), +(3,43,775,1210), +(3,44,803,1240), +(3,45,842,1270), +(3,46,872,1300), +(3,47,913,1330), +(3,48,955,1360), +(3,49,994,1390), +(3,50,1047,1420), +(3,51,1067,1450), +(3,52,1113,1480), +(3,53,1150,1510), +(3,54,1198,1540), +(3,55,1237,1570), +(3,56,1287,1600), +(3,57,1328,1630), +(3,58,1370,1660), +(3,59,1423,1690), +(3,60,1467,1720), +(3,61,1633,1886), +(3,62,1819,2053), +(3,63,2003,2219), +(3,64,2195,2385), +(3,65,2397,2552), +(3,66,2623,2718), +(3,67,2844,2884), +(3,68,3075,3050), +(3,69,3316,3217), +(3,70,3568,3383), +(4,1,25,0), +(4,2,32,0), +(4,3,49,0), +(4,4,56,0), +(4,5,63,0), +(4,6,70,0), +(4,7,87,0), +(4,8,94,0), +(4,9,101,0), +(4,10,118,0), +(4,11,125,0), +(4,12,142,0), +(4,13,149,0), +(4,14,156,0), +(4,15,173,0), +(4,16,181,0), +(4,17,190,0), +(4,18,200,0), +(4,19,221,0), +(4,20,233,0), +(4,21,246,0), +(4,22,260,0), +(4,23,275,0), +(4,24,301,0), +(4,25,318,0), +(4,26,336,0), +(4,27,355,0), +(4,28,375,0), +(4,29,396,0), +(4,30,428,0), +(4,31,451,0), +(4,32,475,0), +(4,33,500,0), +(4,34,526,0), +(4,35,553,0), +(4,36,581,0), +(4,37,610,0), +(4,38,640,0), +(4,39,671,0), +(4,40,703,0), +(4,41,736,0), +(4,42,770,0), +(4,43,805,0), +(4,44,841,0), +(4,45,878,0), +(4,46,916,0), +(4,47,955,0), +(4,48,995,0), +(4,49,1026,0), +(4,50,1068,0), +(4,51,1111,0), +(4,52,1155,0), +(4,53,1200,0), +(4,54,1246,0), +(4,55,1283,0), +(4,56,1331,0), +(4,57,1380,0), +(4,58,1430,0), +(4,59,1471,0), +(4,60,1523,0), +(4,61,1702,0), +(4,62,1879,0), +(4,63,2077,0), +(4,64,2285,0), +(4,65,2489,0), +(4,66,2717,0), +(4,67,2941,0), +(4,68,3190,0), +(4,69,3450,0), +(4,70,3704,0), +(5,1,52,73), +(5,2,57,76), +(5,3,72,95), +(5,4,77,114), +(5,5,92,133), +(5,6,97,152), +(5,7,112,171), +(5,8,117,190), +(5,9,132,209), +(5,10,137,212), +(5,11,142,215), +(5,12,157,234), +(5,13,172,254), +(5,14,177,260), +(5,15,192,282), +(5,16,197,305), +(5,17,212,329), +(5,18,227,339), +(5,19,232,365), +(5,20,247,377), +(5,21,252,405), +(5,22,268,434), +(5,23,275,449), +(5,24,293,480), +(5,25,302,497), +(5,26,322,530), +(5,27,343,549), +(5,28,355,584), +(5,29,378,605), +(5,30,392,627), +(5,31,417,665), +(5,32,433,689), +(5,33,460,728), +(5,34,478,752), +(5,35,507,776), +(5,36,527,800), +(5,37,548,839), +(5,38,580,863), +(5,39,603,887), +(5,40,637,911), +(5,41,662,950), +(5,42,698,974), +(5,43,725,998), +(5,44,763,1022), +(5,45,792,1046), +(5,46,822,1070), +(5,47,863,1094), +(5,48,895,1118), +(5,49,928,1142), +(5,50,972,1166), +(5,51,1007,1190), +(5,52,1053,1214), +(5,53,1090,1238), +(5,54,1128,1262), +(5,55,1177,1271), +(5,56,1217,1295), +(5,57,1258,1319), +(5,58,1300,1343), +(5,59,1353,1352), +(5,60,1397,1376), +(5,61,1557,1500), +(5,62,1738,1625), +(5,63,1916,1749), +(5,64,2101,1873), +(5,65,2295,1998), +(5,66,2495,2122), +(5,67,2719,2247), +(5,68,2936,2371), +(5,69,3160,2495), +(5,70,3391,2620), +(7,1,37,85), +(7,2,44,91), +(7,3,51,98), +(7,4,58,106), +(7,5,65,115), +(7,6,72,125), +(7,7,79,136), +(7,8,86,148), +(7,9,93,161), +(7,10,100,175), +(7,11,107,190), +(7,12,114,206), +(7,13,121,223), +(7,14,128,241), +(7,15,135,260), +(7,16,142,280), +(7,17,150,301), +(7,18,159,323), +(7,19,169,346), +(7,20,180,370), +(7,21,192,395), +(7,22,205,421), +(7,23,219,448), +(7,24,234,476), +(7,25,240,505), +(7,26,257,535), +(7,27,275,566), +(7,28,294,598), +(7,29,314,631), +(7,30,335,665), +(7,31,347,699), +(7,32,370,733), +(7,33,394,767), +(7,34,419,786), +(7,35,435,820), +(7,36,462,854), +(7,37,490,888), +(7,38,509,922), +(7,39,539,941), +(7,40,570,975), +(7,41,592,1009), +(7,42,625,1028), +(7,43,649,1062), +(7,44,684,1096), +(7,45,710,1115), +(7,46,747,1149), +(7,47,775,1183), +(7,48,814,1202), +(7,49,844,1236), +(7,50,885,1255), +(7,51,917,1289), +(7,52,960,1323), +(7,53,994,1342), +(7,54,1029,1376), +(7,55,1075,1395), +(7,56,1112,1414), +(7,57,1150,1448), +(7,58,1199,1467), +(7,59,1239,1501), +(7,60,1330,1520), +(7,61,1428,1664), +(7,62,1583,1808), +(7,63,1760,1951), +(7,64,1932,2095), +(7,65,2114,2239), +(7,66,2304,2383), +(7,67,2504,2527), +(7,68,2713,2670), +(7,69,2931,2814), +(7,70,3159,2958), +(8,1,32,100), +(8,2,47,110), +(8,3,52,106), +(8,4,67,118), +(8,5,82,131), +(8,6,97,130), +(8,7,102,145), +(8,8,117,146), +(8,9,132,163), +(8,10,137,196), +(8,11,152,215), +(8,12,167,220), +(8,13,172,241), +(8,14,187,263), +(8,15,202,271), +(8,16,207,295), +(8,17,222,305), +(8,18,237,331), +(8,19,242,343), +(8,20,257,371), +(8,21,272,385), +(8,22,277,415), +(8,23,292,431), +(8,24,298,463), +(8,25,315,481), +(8,26,333,515), +(8,27,342,535), +(8,28,362,556), +(8,29,373,592), +(8,30,395,613), +(8,31,418,634), +(8,32,432,670), +(8,33,457,691), +(8,34,473,712), +(8,35,500,733), +(8,36,518,754), +(8,37,547,790), +(8,38,577,811), +(8,39,598,832), +(8,40,630,853), +(8,41,653,874), +(8,42,687,895), +(8,43,712,916), +(8,44,748,937), +(8,45,775,958), +(8,46,813,979), +(8,47,842,1000), +(8,48,882,1021), +(8,49,913,1042), +(8,50,955,1048), +(8,51,988,1069), +(8,52,1032,1090), +(8,53,1067,1111), +(8,54,1103,1117), +(8,55,1150,1138), +(8,56,1188,1159), +(8,57,1237,1165), +(8,58,1277,1186), +(8,59,1328,1192), +(8,60,1370,1213), +(8,61,1526,1316), +(8,62,1702,1419), +(8,63,1875,1521), +(8,64,2070,1624), +(8,65,2261,1727), +(8,66,2461,1830), +(8,67,2686,1932), +(8,68,2906,2035), +(8,69,3136,2138), +(8,70,3393,2241), +(9,1,23,90), +(9,2,28,98), +(9,3,43,107), +(9,4,48,102), +(9,5,63,113), +(9,6,68,126), +(9,7,83,144), +(9,8,88,162), +(9,9,93,180), +(9,10,108,198), +(9,11,123,200), +(9,12,128,218), +(9,13,143,237), +(9,14,148,257), +(9,15,153,278), +(9,16,168,300), +(9,17,173,308), +(9,18,189,332), +(9,19,196,357), +(9,20,204,383), +(9,21,223,395), +(9,22,233,423), +(9,23,244,452), +(9,24,266,467), +(9,25,279,498), +(9,26,293,530), +(9,27,318,548), +(9,28,334,582), +(9,29,351,602), +(9,30,379,638), +(9,31,398,674), +(9,32,418,695), +(9,33,439,731), +(9,34,471,752), +(9,35,494,788), +(9,36,518,809), +(9,37,543,830), +(9,38,569,866), +(9,39,606,887), +(9,40,634,923), +(9,41,663,944), +(9,42,693,965), +(9,43,724,1001), +(9,44,756,1022), +(9,45,799,1043), +(9,46,832,1064), +(9,47,868,1100), +(9,48,904,1121), +(9,49,941,1142), +(9,50,979,1163), +(9,51,1018,1184), +(9,52,1058,1205), +(9,53,1099,1226), +(9,54,1141,1247), +(9,55,1184,1268), +(9,56,1228,1289), +(9,57,1273,1310), +(9,58,1319,1331), +(9,59,1366,1352), +(9,60,1414,1373), +(9,61,1580,1497), +(9,62,1755,1621), +(9,63,1939,1745), +(9,64,2133,1870), +(9,65,2323,1994), +(9,66,2535,2118), +(9,67,2758,2242), +(9,68,2991,2366), +(9,69,3235,2490), +(9,70,3490,2615), +(11,1,44,60), +(11,2,51,66), +(11,3,58,73), +(11,4,75,81), +(11,5,82,90), +(11,6,89,100), +(11,7,106,111), +(11,8,113,123), +(11,9,120,136), +(11,10,137,150), +(11,11,144,165), +(11,12,151,182), +(11,13,168,200), +(11,14,175,219), +(11,15,182,239), +(11,16,199,260), +(11,17,206,282), +(11,18,214,305), +(11,19,233,329), +(11,20,243,354), +(11,21,254,380), +(11,22,266,392), +(11,23,289,420), +(11,24,303,449), +(11,25,318,479), +(11,26,334,509), +(11,27,361,524), +(11,28,379,554), +(11,29,398,584), +(11,30,418,614), +(11,31,439,629), +(11,32,461,659), +(11,33,494,689), +(11,34,518,704), +(11,35,543,734), +(11,36,569,749), +(11,37,596,779), +(11,38,624,809), +(11,39,653,824), +(11,40,683,854), +(11,41,714,869), +(11,42,746,899), +(11,43,779,914), +(11,44,823,944), +(11,45,858,959), +(11,46,894,989), +(11,47,921,1004), +(11,48,959,1019), +(11,49,998,1049), +(11,50,1038,1064), +(11,51,1079,1079), +(11,52,1121,1109), +(11,53,1164,1124), +(11,54,1208,1139), +(11,55,1253,1154), +(11,56,1299,1169), +(11,57,1346,1199), +(11,58,1384,1214), +(11,59,1433,1229), +(11,60,1483,1244), +(11,61,1657,1357), +(11,62,1840,1469), +(11,63,2020,1582), +(11,64,2222,1694), +(11,65,2433,1807), +(11,66,2640,1919), +(11,67,2872,2032), +(11,68,3114,2145), +(11,69,3351,2257), +(11,70,3614,2370); +/*!40000 ALTER TABLE `player_classlevelstats` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `player_levelstats` +-- + +DROP TABLE IF EXISTS `player_levelstats`; +CREATE TABLE `player_levelstats` ( + `race` tinyint(3) unsigned NOT NULL, + `class` tinyint(3) unsigned NOT NULL, + `level` tinyint(3) unsigned NOT NULL, + `str` tinyint(3) unsigned NOT NULL, + `agi` tinyint(3) unsigned NOT NULL, + `sta` tinyint(3) unsigned NOT NULL, + `inte` tinyint(3) unsigned NOT NULL, + `spi` tinyint(3) unsigned NOT NULL, + PRIMARY KEY (`race`,`class`,`level`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 PACK_KEYS=0 COMMENT='Stores levels stats.'; + +-- +-- Dumping data for table `player_levelstats` +-- + +LOCK TABLES `player_levelstats` WRITE; +/*!40000 ALTER TABLE `player_levelstats` DISABLE KEYS */; +INSERT INTO `player_levelstats` VALUES +(1,1,1,23,20,22,20,20), +(1,1,2,24,21,23,20,20), +(1,1,3,26,22,24,20,21), +(1,1,4,27,22,26,20,21), +(1,1,5,28,23,27,20,21), +(1,1,6,30,24,28,20,21), +(1,1,7,31,25,29,21,22), +(1,1,8,32,26,30,21,22), +(1,1,9,34,26,32,21,22), +(1,1,10,35,27,33,21,23), +(1,1,11,36,28,34,21,23), +(1,1,12,38,29,35,21,23), +(1,1,13,39,30,37,21,24), +(1,1,14,41,31,38,21,24), +(1,1,15,42,32,39,21,24), +(1,1,16,44,33,41,21,25), +(1,1,17,45,34,42,22,25), +(1,1,18,47,34,43,22,25), +(1,1,19,48,35,45,22,26), +(1,1,20,50,36,46,22,26), +(1,1,21,51,37,48,22,26), +(1,1,22,53,38,49,22,27), +(1,1,23,54,39,51,22,27), +(1,1,24,56,40,52,23,28), +(1,1,25,58,41,53,23,28), +(1,1,26,59,42,55,23,28), +(1,1,27,61,43,56,23,29), +(1,1,28,63,44,58,23,29), +(1,1,29,64,45,59,23,30), +(1,1,30,66,46,61,24,30), +(1,1,31,68,47,62,24,30), +(1,1,32,69,48,64,24,31), +(1,1,33,71,50,66,24,31), +(1,1,34,73,51,67,24,32), +(1,1,35,74,52,69,24,32), +(1,1,36,76,53,70,25,33), +(1,1,37,78,54,72,25,33), +(1,1,38,80,55,74,25,34), +(1,1,39,82,56,75,25,34), +(1,1,40,83,57,77,25,35), +(1,1,41,85,58,79,26,35), +(1,1,42,87,60,80,26,35), +(1,1,43,89,61,82,26,36), +(1,1,44,91,62,84,26,36), +(1,1,45,93,63,85,26,37), +(1,1,46,95,64,87,27,37), +(1,1,47,97,66,89,27,38), +(1,1,48,99,67,91,27,38), +(1,1,49,101,68,93,27,39), +(1,1,50,103,69,94,28,40), +(1,1,51,105,71,96,28,40), +(1,1,52,107,72,98,28,41), +(1,1,53,109,73,100,28,41), +(1,1,54,111,74,102,29,42), +(1,1,55,113,76,103,29,42), +(1,1,56,115,77,105,29,43), +(1,1,57,117,78,107,29,43), +(1,1,58,119,79,109,30,44), +(1,1,59,121,81,111,30,44), +(1,1,60,123,82,113,30,45), +(1,1,61,125,83,115,30,46), +(1,1,62,127,85,117,31,46), +(1,1,63,129,86,119,31,47), +(1,1,64,132,88,121,31,47), +(1,1,65,134,89,123,32,48), +(1,1,66,136,90,125,32,49), +(1,1,67,138,92,127,32,49), +(1,1,68,140,93,129,32,50), +(1,1,69,143,95,131,33,50), +(1,1,70,145,96,133,33,51), +(1,2,1,22,20,22,20,21), +(1,2,2,23,21,23,21,22), +(1,2,3,24,21,24,21,22), +(1,2,4,25,22,25,22,23), +(1,2,5,26,22,26,23,24), +(1,2,6,28,23,27,23,25), +(1,2,7,29,24,28,24,25), +(1,2,8,30,24,29,25,26), +(1,2,9,31,25,30,25,27), +(1,2,10,32,25,32,26,27), +(1,2,11,33,26,33,27,28), +(1,2,12,35,27,34,27,29), +(1,2,13,36,27,35,28,30), +(1,2,14,37,28,36,29,31), +(1,2,15,38,29,37,30,31), +(1,2,16,40,29,38,30,32), +(1,2,17,41,30,40,31,33), +(1,2,18,42,31,41,32,34), +(1,2,19,43,31,42,33,35), +(1,2,20,45,32,43,33,35), +(1,2,21,46,33,45,34,36), +(1,2,22,47,33,46,35,37), +(1,2,23,49,34,47,36,38), +(1,2,24,50,35,48,37,39), +(1,2,25,51,36,50,37,40), +(1,2,26,53,36,51,38,41), +(1,2,27,54,37,52,39,42), +(1,2,28,56,38,54,40,43), +(1,2,29,57,39,55,41,43), +(1,2,30,58,39,56,42,44), +(1,2,31,60,40,58,43,45), +(1,2,32,61,41,59,43,46), +(1,2,33,63,42,60,44,47), +(1,2,34,64,43,62,45,48), +(1,2,35,66,44,63,46,49), +(1,2,36,67,44,65,47,50), +(1,2,37,69,45,66,48,51), +(1,2,38,70,46,67,49,52), +(1,2,39,72,47,69,50,53), +(1,2,40,73,48,70,51,54), +(1,2,41,75,49,72,52,55), +(1,2,42,77,49,73,53,56), +(1,2,43,78,50,75,54,57), +(1,2,44,80,51,76,55,58), +(1,2,45,81,52,78,56,59), +(1,2,46,83,53,79,57,61), +(1,2,47,85,54,81,58,62), +(1,2,48,86,55,83,59,63), +(1,2,49,88,56,84,60,64), +(1,2,50,90,57,86,61,65), +(1,2,51,91,58,87,62,66), +(1,2,52,93,59,89,63,67), +(1,2,53,95,60,91,64,68), +(1,2,54,97,61,92,65,69), +(1,2,55,98,61,94,66,71), +(1,2,56,100,62,95,67,72), +(1,2,57,102,63,97,68,73), +(1,2,58,104,64,99,69,74), +(1,2,59,105,65,101,70,75), +(1,2,60,107,66,102,71,77), +(1,2,61,109,67,104,73,78), +(1,2,62,111,69,106,74,79), +(1,2,63,113,70,107,75,80), +(1,2,64,115,71,109,76,81), +(1,2,65,116,72,111,77,83), +(1,2,66,118,73,113,78,84), +(1,2,67,120,74,115,79,85), +(1,2,68,122,75,116,81,86), +(1,2,69,124,76,118,82,88), +(1,2,70,126,77,120,83,89), +(1,4,1,21,23,21,20,20), +(1,4,2,22,24,22,20,20), +(1,4,3,23,26,22,20,21), +(1,4,4,23,27,23,20,21), +(1,4,5,24,29,24,21,21), +(1,4,6,25,30,25,21,22), +(1,4,7,26,32,25,21,22), +(1,4,8,26,33,26,21,23), +(1,4,9,27,35,27,21,23), +(1,4,10,28,36,27,21,23), +(1,4,11,29,38,28,22,24), +(1,4,12,30,39,29,22,24), +(1,4,13,31,41,30,22,25), +(1,4,14,31,43,31,22,25), +(1,4,15,32,44,31,22,25), +(1,4,16,33,46,32,23,26), +(1,4,17,34,48,33,23,26), +(1,4,18,35,49,34,23,27), +(1,4,19,36,51,35,23,27), +(1,4,20,37,53,35,23,28), +(1,4,21,38,54,36,24,28), +(1,4,22,39,56,37,24,29), +(1,4,23,40,58,38,24,29), +(1,4,24,41,60,39,24,30), +(1,4,25,42,61,40,25,30), +(1,4,26,43,63,41,25,31), +(1,4,27,44,65,42,25,31), +(1,4,28,45,67,43,25,32), +(1,4,29,46,69,43,25,32), +(1,4,30,47,71,44,26,33), +(1,4,31,48,72,45,26,33), +(1,4,32,49,74,46,26,34), +(1,4,33,50,76,47,27,34), +(1,4,34,51,78,48,27,35), +(1,4,35,52,80,49,27,35), +(1,4,36,53,82,50,27,36), +(1,4,37,54,84,51,28,36), +(1,4,38,55,86,52,28,37), +(1,4,39,56,88,53,28,38), +(1,4,40,57,90,54,28,38), +(1,4,41,58,92,55,29,39), +(1,4,42,60,94,56,29,39), +(1,4,43,61,96,57,29,40), +(1,4,44,62,98,58,30,40), +(1,4,45,63,100,59,30,41), +(1,4,46,64,103,61,30,42), +(1,4,47,65,105,62,31,42), +(1,4,48,66,107,63,31,43), +(1,4,49,68,109,64,31,44), +(1,4,50,69,111,65,32,44), +(1,4,51,70,113,66,32,45), +(1,4,52,71,116,67,32,45), +(1,4,53,73,118,68,33,46), +(1,4,54,74,120,69,33,47), +(1,4,55,75,122,71,33,47), +(1,4,56,76,125,72,34,48), +(1,4,57,78,127,73,34,49), +(1,4,58,79,129,74,34,49), +(1,4,59,80,131,75,35,50), +(1,4,60,81,134,77,35,51), +(1,4,61,83,136,78,35,51), +(1,4,62,84,138,79,36,52), +(1,4,63,85,141,80,36,53), +(1,4,64,87,143,81,37,54), +(1,4,65,88,146,83,37,54), +(1,4,66,89,148,84,37,55), +(1,4,67,91,151,85,38,56), +(1,4,68,92,153,86,38,57), +(1,4,69,94,156,88,39,57), +(1,4,70,95,158,89,39,58), +(1,5,1,20,20,20,22,23), +(1,5,2,20,20,20,23,24), +(1,5,3,20,20,21,25,26), +(1,5,4,20,21,21,26,27), +(1,5,5,21,21,21,27,28), +(1,5,6,21,21,22,29,30), +(1,5,7,21,21,22,30,31), +(1,5,8,21,22,23,31,33), +(1,5,9,21,22,23,33,34), +(1,5,10,21,22,23,34,36), +(1,5,11,22,22,24,36,37), +(1,5,12,22,23,24,37,39), +(1,5,13,22,23,25,38,40), +(1,5,14,22,23,25,40,42), +(1,5,15,22,23,25,41,43), +(1,5,16,23,24,26,43,45), +(1,5,17,23,24,26,44,46), +(1,5,18,23,24,27,46,48), +(1,5,19,23,24,27,47,49), +(1,5,20,23,25,28,49,51), +(1,5,21,24,25,28,51,53), +(1,5,22,24,25,29,52,54), +(1,5,23,24,26,29,54,56), +(1,5,24,24,26,30,55,58), +(1,5,25,25,26,30,57,59), +(1,5,26,25,27,31,59,61), +(1,5,27,25,27,31,60,63), +(1,5,28,25,27,32,62,65), +(1,5,29,25,28,32,64,66), +(1,5,30,26,28,33,65,68), +(1,5,31,26,28,33,67,70), +(1,5,32,26,29,34,69,72), +(1,5,33,27,29,34,70,73), +(1,5,34,27,29,35,72,75), +(1,5,35,27,30,35,74,77), +(1,5,36,27,30,36,76,79), +(1,5,37,28,30,36,78,81), +(1,5,38,28,31,37,79,83), +(1,5,39,28,31,38,81,85), +(1,5,40,28,31,38,83,87), +(1,5,41,29,32,39,85,88), +(1,5,42,29,32,39,87,90), +(1,5,43,29,33,40,89,92), +(1,5,44,30,33,40,91,94), +(1,5,45,30,33,41,92,96), +(1,5,46,30,34,42,94,98), +(1,5,47,31,34,42,96,100), +(1,5,48,31,35,43,98,102), +(1,5,49,31,35,44,100,104), +(1,5,50,32,36,44,102,106), +(1,5,51,32,36,45,104,109), +(1,5,52,32,36,45,106,111), +(1,5,53,33,37,46,108,113), +(1,5,54,33,37,47,110,115), +(1,5,55,33,38,47,112,117), +(1,5,56,34,38,48,114,119), +(1,5,57,34,39,49,117,121), +(1,5,58,34,39,49,119,124), +(1,5,59,35,40,50,121,126), +(1,5,60,35,40,51,123,128), +(1,5,61,35,41,51,125,130), +(1,5,62,36,41,52,127,132), +(1,5,63,36,41,53,129,135), +(1,5,64,37,42,54,132,137), +(1,5,65,37,42,54,134,139), +(1,5,66,37,43,55,136,142), +(1,5,67,38,43,56,138,144), +(1,5,68,38,44,57,140,146), +(1,5,69,39,44,57,143,149), +(1,5,70,39,45,58,145,151), +(1,8,1,20,20,20,23,22), +(1,8,2,20,20,20,24,23), +(1,8,3,20,20,21,26,25), +(1,8,4,20,20,21,27,26), +(1,8,5,20,21,21,28,27), +(1,8,6,20,21,21,30,29), +(1,8,7,21,21,22,31,30), +(1,8,8,21,21,22,33,31), +(1,8,9,21,21,22,34,33), +(1,8,10,21,21,23,36,34), +(1,8,11,21,22,23,37,36), +(1,8,12,21,22,23,39,37), +(1,8,13,21,22,24,40,38), +(1,8,14,21,22,24,42,40), +(1,8,15,21,22,24,43,41), +(1,8,16,21,23,25,45,43), +(1,8,17,22,23,25,46,44), +(1,8,18,22,23,25,48,46), +(1,8,19,22,23,26,49,47), +(1,8,20,22,23,26,51,49), +(1,8,21,22,24,26,53,51), +(1,8,22,22,24,27,54,52), +(1,8,23,22,24,27,56,54), +(1,8,24,23,24,28,58,55), +(1,8,25,23,25,28,59,57), +(1,8,26,23,25,28,61,59), +(1,8,27,23,25,29,63,60), +(1,8,28,23,25,29,65,62), +(1,8,29,23,25,30,66,64), +(1,8,30,24,26,30,68,65), +(1,8,31,24,26,30,70,67), +(1,8,32,24,26,31,72,69), +(1,8,33,24,27,31,73,70), +(1,8,34,24,27,32,75,72), +(1,8,35,24,27,32,77,74), +(1,8,36,25,27,33,79,76), +(1,8,37,25,28,33,81,78), +(1,8,38,25,28,34,83,79), +(1,8,39,25,28,34,85,81), +(1,8,40,25,28,35,87,83), +(1,8,41,26,29,35,88,85), +(1,8,42,26,29,35,90,87), +(1,8,43,26,29,36,92,89), +(1,8,44,26,30,36,94,91), +(1,8,45,26,30,37,96,92), +(1,8,46,27,30,37,98,94), +(1,8,47,27,31,38,100,96), +(1,8,48,27,31,38,102,98), +(1,8,49,27,31,39,104,100), +(1,8,50,28,32,40,106,102), +(1,8,51,28,32,40,109,104), +(1,8,52,28,32,41,111,106), +(1,8,53,28,33,41,113,108), +(1,8,54,29,33,42,115,110), +(1,8,55,29,33,42,117,112), +(1,8,56,29,34,43,119,114), +(1,8,57,29,34,43,121,117), +(1,8,58,30,34,44,124,119), +(1,8,59,30,35,44,126,121), +(1,8,60,30,35,45,128,123), +(1,8,61,30,35,46,130,125), +(1,8,62,31,36,46,132,127), +(1,8,63,31,36,47,135,129), +(1,8,64,31,37,47,137,132), +(1,8,65,32,37,48,139,134), +(1,8,66,32,37,49,142,136), +(1,8,67,32,38,49,144,138), +(1,8,68,32,38,50,146,140), +(1,8,69,33,39,50,149,143), +(1,8,70,33,39,51,151,145), +(1,9,1,20,20,21,22,22), +(1,9,2,20,20,22,23,23), +(1,9,3,21,21,22,24,24), +(1,9,4,21,21,23,26,25), +(1,9,5,21,21,23,27,27), +(1,9,6,21,22,24,28,28), +(1,9,7,22,22,24,29,29), +(1,9,8,22,23,25,30,30), +(1,9,9,22,23,26,32,31), +(1,9,10,23,23,26,33,33), +(1,9,11,23,24,27,34,34), +(1,9,12,23,24,27,35,35), +(1,9,13,24,25,28,37,36), +(1,9,14,24,25,29,38,38), +(1,9,15,24,25,29,39,39), +(1,9,16,25,26,30,41,40), +(1,9,17,25,26,31,42,42), +(1,9,18,25,27,31,43,43), +(1,9,19,26,27,32,45,44), +(1,9,20,26,28,33,46,46), +(1,9,21,26,28,33,48,47), +(1,9,22,27,29,34,49,49), +(1,9,23,27,29,35,51,50), +(1,9,24,28,30,35,52,51), +(1,9,25,28,30,36,53,53), +(1,9,26,28,31,37,55,54), +(1,9,27,29,31,37,56,56), +(1,9,28,29,32,38,58,57), +(1,9,29,30,32,39,59,59), +(1,9,30,30,33,40,61,60), +(1,9,31,30,33,40,62,62), +(1,9,32,31,34,41,64,63), +(1,9,33,31,34,42,66,65), +(1,9,34,32,35,43,67,66), +(1,9,35,32,35,44,69,68), +(1,9,36,33,36,44,70,69), +(1,9,37,33,36,45,72,71), +(1,9,38,34,37,46,74,73), +(1,9,39,34,38,47,75,74), +(1,9,40,35,38,48,77,76), +(1,9,41,35,39,48,79,78), +(1,9,42,35,39,49,80,79), +(1,9,43,36,40,50,82,81), +(1,9,44,36,40,51,84,83), +(1,9,45,37,41,52,85,84), +(1,9,46,37,42,53,87,86), +(1,9,47,38,42,54,89,88), +(1,9,48,38,43,55,91,89), +(1,9,49,39,44,55,93,91), +(1,9,50,40,44,56,94,93), +(1,9,51,40,45,57,96,95), +(1,9,52,41,45,58,98,97), +(1,9,53,41,46,59,100,98), +(1,9,54,42,47,60,102,100), +(1,9,55,42,47,61,103,102), +(1,9,56,43,48,62,105,104), +(1,9,57,43,49,63,107,106), +(1,9,58,44,49,64,109,108), +(1,9,59,44,50,65,111,109), +(1,9,60,45,51,66,113,111), +(1,9,61,46,51,67,115,113), +(1,9,62,46,52,68,117,115), +(1,9,63,47,53,69,119,117), +(1,9,64,47,54,70,121,119), +(1,9,65,48,54,71,123,121), +(1,9,66,49,55,72,125,123), +(1,9,67,49,56,73,127,125), +(1,9,68,50,57,74,129,127), +(1,9,69,50,57,75,131,129), +(1,9,70,51,58,76,133,131), +(2,1,1,26,17,24,17,23), +(2,1,2,27,18,25,17,23), +(2,1,3,29,19,26,17,24), +(2,1,4,30,19,27,17,24), +(2,1,5,31,20,29,17,24), +(2,1,6,32,21,30,17,24), +(2,1,7,34,22,31,18,25), +(2,1,8,35,23,32,18,25), +(2,1,9,37,24,34,18,25), +(2,1,10,38,24,35,18,26), +(2,1,11,39,25,36,18,26), +(2,1,12,41,26,37,18,26), +(2,1,13,42,27,39,18,27), +(2,1,14,44,28,40,18,27), +(2,1,15,45,29,41,18,27), +(2,1,16,47,30,43,19,28), +(2,1,17,48,31,44,19,28), +(2,1,18,50,32,45,19,28), +(2,1,19,51,33,47,19,29), +(2,1,20,53,34,48,19,29), +(2,1,21,54,34,50,19,29), +(2,1,22,56,35,51,19,30), +(2,1,23,57,36,52,20,30), +(2,1,24,59,37,54,20,30), +(2,1,25,60,38,55,20,31), +(2,1,26,62,39,57,20,31), +(2,1,27,64,40,58,20,32), +(2,1,28,65,41,60,20,32), +(2,1,29,67,43,61,21,32), +(2,1,30,69,44,63,21,33), +(2,1,31,70,45,64,21,33), +(2,1,32,72,46,66,21,34), +(2,1,33,74,47,67,21,34), +(2,1,34,76,48,69,21,35), +(2,1,35,77,49,71,22,35), +(2,1,36,79,50,72,22,36), +(2,1,37,81,51,74,22,36), +(2,1,38,83,52,76,22,36), +(2,1,39,84,53,77,22,37), +(2,1,40,86,55,79,23,37), +(2,1,41,88,56,81,23,38), +(2,1,42,90,57,82,23,38), +(2,1,43,92,58,84,23,39), +(2,1,44,94,59,86,23,39), +(2,1,45,96,60,87,24,40), +(2,1,46,98,62,89,24,40), +(2,1,47,100,63,91,24,41), +(2,1,48,101,64,93,24,41), +(2,1,49,103,65,94,25,42), +(2,1,50,105,66,96,25,42), +(2,1,51,107,68,98,25,43), +(2,1,52,109,69,100,25,43), +(2,1,53,111,70,102,25,44), +(2,1,54,113,71,104,26,45), +(2,1,55,115,73,105,26,45), +(2,1,56,118,74,107,26,46), +(2,1,57,120,75,109,26,46), +(2,1,58,122,77,111,27,47), +(2,1,59,124,78,113,27,47), +(2,1,60,126,79,115,27,48), +(2,1,61,128,81,117,27,48), +(2,1,62,130,82,119,28,49), +(2,1,63,132,83,121,28,50), +(2,1,64,135,85,123,28,50), +(2,1,65,137,86,125,29,51), +(2,1,66,139,87,127,29,52), +(2,1,67,141,89,129,29,52), +(2,1,68,143,90,131,29,53), +(2,1,69,146,92,133,30,53), +(2,1,70,148,93,135,30,54), +(2,3,1,23,20,23,17,24), +(2,3,2,23,21,24,18,25), +(2,3,3,24,23,25,18,25), +(2,3,4,24,24,26,19,26), +(2,3,5,25,25,27,19,26), +(2,3,6,25,27,28,20,27), +(2,3,7,26,28,28,21,28), +(2,3,8,26,30,29,21,28), +(2,3,9,26,31,30,22,29), +(2,3,10,27,33,31,22,30), +(2,3,11,27,34,32,23,30), +(2,3,12,28,36,33,24,31), +(2,3,13,28,37,34,24,32), +(2,3,14,29,39,35,25,33), +(2,3,15,29,40,36,26,33), +(2,3,16,30,42,37,26,34), +(2,3,17,30,43,39,27,35), +(2,3,18,31,45,40,28,35), +(2,3,19,31,47,41,28,36), +(2,3,20,32,48,42,29,37), +(2,3,21,32,50,43,30,38), +(2,3,22,33,51,44,31,39), +(2,3,23,34,53,45,31,39), +(2,3,24,34,55,46,32,40), +(2,3,25,35,57,47,33,41), +(2,3,26,35,58,48,34,42), +(2,3,27,36,60,50,34,43), +(2,3,28,36,62,51,35,43), +(2,3,29,37,63,52,36,44), +(2,3,30,38,65,53,37,45), +(2,3,31,38,67,54,37,46), +(2,3,32,39,69,56,38,47), +(2,3,33,39,71,57,39,48), +(2,3,34,40,72,58,40,49), +(2,3,35,41,74,59,41,49), +(2,3,36,41,76,61,42,50), +(2,3,37,42,78,62,42,51), +(2,3,38,43,80,63,43,52), +(2,3,39,43,82,64,44,53), +(2,3,40,44,84,66,45,54), +(2,3,41,45,86,67,46,55), +(2,3,42,45,88,68,47,56), +(2,3,43,46,90,70,47,57), +(2,3,44,47,91,71,48,58), +(2,3,45,47,93,72,49,59), +(2,3,46,48,95,74,50,60), +(2,3,47,49,98,75,51,61), +(2,3,48,50,100,77,52,62), +(2,3,49,50,102,78,53,63), +(2,3,50,51,104,79,54,64), +(2,3,51,52,106,81,55,65), +(2,3,52,52,108,82,56,66), +(2,3,53,53,110,84,57,67), +(2,3,54,54,112,85,58,68), +(2,3,55,55,114,87,59,69), +(2,3,56,55,116,88,60,70), +(2,3,57,56,118,90,61,71), +(2,3,58,57,121,91,62,72), +(2,3,59,58,123,93,63,73), +(2,3,60,59,125,94,64,74), +(2,3,61,59,127,96,65,76), +(2,3,62,60,130,97,66,77), +(2,3,63,61,132,99,67,78), +(2,3,64,62,134,100,68,79), +(2,3,65,63,136,102,69,80), +(2,3,66,64,139,104,70,81), +(2,3,67,64,141,105,71,82), +(2,3,68,65,143,107,72,84), +(2,3,69,66,146,108,73,85), +(2,3,70,67,148,110,74,86), +(2,4,1,24,20,23,17,23), +(2,4,2,25,21,24,17,23), +(2,4,3,25,23,24,17,24), +(2,4,4,26,24,25,17,24), +(2,4,5,27,26,26,18,24), +(2,4,6,28,27,26,18,25), +(2,4,7,29,29,27,18,25), +(2,4,8,29,30,28,18,26), +(2,4,9,30,32,29,18,26), +(2,4,10,31,33,29,19,26), +(2,4,11,32,35,30,19,27), +(2,4,12,33,37,31,19,27), +(2,4,13,34,38,32,19,28), +(2,4,14,34,40,32,19,28), +(2,4,15,35,41,33,19,28), +(2,4,16,36,43,34,20,29), +(2,4,17,37,45,35,20,29), +(2,4,18,38,46,36,20,30), +(2,4,19,39,48,37,20,30), +(2,4,20,40,50,37,21,31), +(2,4,21,41,52,38,21,31), +(2,4,22,42,53,39,21,31), +(2,4,23,43,55,40,21,32), +(2,4,24,43,57,41,21,32), +(2,4,25,44,59,42,22,33), +(2,4,26,45,60,43,22,33), +(2,4,27,46,62,44,22,34), +(2,4,28,47,64,44,22,34), +(2,4,29,48,66,45,23,35), +(2,4,30,49,68,46,23,35), +(2,4,31,50,70,47,23,36), +(2,4,32,51,72,48,23,36), +(2,4,33,53,73,49,24,37), +(2,4,34,54,75,50,24,38), +(2,4,35,55,77,51,24,38), +(2,4,36,56,79,52,24,39), +(2,4,37,57,81,53,25,39), +(2,4,38,58,83,54,25,40), +(2,4,39,59,85,55,25,40), +(2,4,40,60,87,56,26,41), +(2,4,41,61,89,57,26,41), +(2,4,42,62,91,58,26,42), +(2,4,43,63,93,59,27,43), +(2,4,44,65,95,60,27,43), +(2,4,45,66,98,61,27,44), +(2,4,46,67,100,62,27,44), +(2,4,47,68,102,64,28,45), +(2,4,48,69,104,65,28,46), +(2,4,49,71,106,66,28,46), +(2,4,50,72,108,67,29,47), +(2,4,51,73,110,68,29,48), +(2,4,52,74,113,69,29,48), +(2,4,53,75,115,70,30,49), +(2,4,54,77,117,71,30,50), +(2,4,55,78,119,73,30,50), +(2,4,56,79,122,74,31,51), +(2,4,57,80,124,75,31,52), +(2,4,58,82,126,76,31,52), +(2,4,59,83,129,77,32,53), +(2,4,60,84,131,78,32,54), +(2,4,61,86,133,80,33,54), +(2,4,62,87,136,81,33,55), +(2,4,63,88,138,82,33,56), +(2,4,64,90,140,83,34,57), +(2,4,65,91,143,85,34,57), +(2,4,66,92,145,86,34,58), +(2,4,67,94,148,87,35,59), +(2,4,68,95,150,88,35,59), +(2,4,69,97,153,90,36,60), +(2,4,70,98,155,91,36,61), +(2,7,1,24,17,23,18,25), +(2,7,2,25,17,24,19,26), +(2,7,3,26,18,25,20,27), +(2,7,4,26,18,26,21,28), +(2,7,5,27,19,27,22,29), +(2,7,6,28,19,28,23,30), +(2,7,7,29,20,29,24,31), +(2,7,8,30,20,30,25,32), +(2,7,9,31,21,31,26,33), +(2,7,10,32,21,32,27,34), +(2,7,11,33,22,33,28,36), +(2,7,12,34,22,34,29,37), +(2,7,13,34,23,35,30,38), +(2,7,14,35,23,36,31,39), +(2,7,15,36,24,37,32,40), +(2,7,16,37,24,39,33,41), +(2,7,17,38,25,40,34,43), +(2,7,18,39,25,41,35,44), +(2,7,19,40,26,42,36,45), +(2,7,20,41,26,43,37,46), +(2,7,21,42,27,44,38,47), +(2,7,22,43,27,45,39,49), +(2,7,23,44,28,47,40,50), +(2,7,24,45,28,48,41,51), +(2,7,25,47,29,49,43,52), +(2,7,26,48,30,50,44,54), +(2,7,27,49,30,52,45,55), +(2,7,28,50,31,53,46,56), +(2,7,29,51,31,54,47,58), +(2,7,30,52,32,55,48,59), +(2,7,31,53,33,57,50,60), +(2,7,32,54,33,58,51,62), +(2,7,33,55,34,59,52,63), +(2,7,34,57,34,61,53,65), +(2,7,35,58,35,62,55,66), +(2,7,36,59,36,63,56,67), +(2,7,37,60,36,65,57,69), +(2,7,38,61,37,66,58,70), +(2,7,39,62,38,67,60,72), +(2,7,40,64,38,69,61,73), +(2,7,41,65,39,70,62,75), +(2,7,42,66,40,72,64,76), +(2,7,43,67,40,73,65,78), +(2,7,44,69,41,74,66,79), +(2,7,45,70,42,76,68,81), +(2,7,46,71,42,77,69,82), +(2,7,47,72,43,79,70,84), +(2,7,48,74,44,80,72,85), +(2,7,49,75,45,82,73,87), +(2,7,50,76,45,83,75,89), +(2,7,51,78,46,85,76,90), +(2,7,52,79,47,86,77,92), +(2,7,53,80,47,88,79,93), +(2,7,54,82,48,90,80,95), +(2,7,55,83,49,91,82,97), +(2,7,56,85,50,93,83,98), +(2,7,57,86,50,94,85,100), +(2,7,58,87,51,96,86,102), +(2,7,59,89,52,97,88,103), +(2,7,60,90,53,99,89,105), +(2,7,61,92,54,101,91,107), +(2,7,62,93,54,102,92,109), +(2,7,63,95,55,104,94,110), +(2,7,64,96,56,106,95,112), +(2,7,65,97,57,107,97,114), +(2,7,66,99,58,109,99,116), +(2,7,67,100,58,111,100,118), +(2,7,68,102,59,113,102,119), +(2,7,69,103,60,114,103,121), +(2,7,70,105,61,116,105,123), +(2,9,1,23,17,23,19,25), +(2,9,2,23,17,24,20,26), +(2,9,3,24,18,24,21,27), +(2,9,4,24,18,25,23,28), +(2,9,5,24,18,25,24,30), +(2,9,6,24,19,26,25,31), +(2,9,7,25,19,26,26,32), +(2,9,8,25,20,27,27,33), +(2,9,9,25,20,27,29,34), +(2,9,10,26,20,28,30,36), +(2,9,11,26,21,29,31,37), +(2,9,12,26,21,29,33,38), +(2,9,13,27,22,30,34,39), +(2,9,14,27,22,31,35,41), +(2,9,15,27,23,31,37,42), +(2,9,16,28,23,32,38,43), +(2,9,17,28,23,32,39,45), +(2,9,18,28,24,33,41,46), +(2,9,19,29,24,34,42,47), +(2,9,20,29,25,34,43,49), +(2,9,21,29,25,35,45,50), +(2,9,22,30,26,36,46,51), +(2,9,23,30,26,37,48,53), +(2,9,24,30,27,37,49,54), +(2,9,25,31,27,38,51,56), +(2,9,26,31,28,39,52,57), +(2,9,27,32,28,39,54,59), +(2,9,28,32,29,40,55,60), +(2,9,29,32,29,41,57,62), +(2,9,30,33,30,42,58,63), +(2,9,31,33,30,42,60,65), +(2,9,32,34,31,43,61,66), +(2,9,33,34,31,44,63,68), +(2,9,34,35,32,45,64,69), +(2,9,35,35,32,45,66,71), +(2,9,36,36,33,46,68,72), +(2,9,37,36,34,47,69,74), +(2,9,38,36,34,48,71,76), +(2,9,39,37,35,49,72,77), +(2,9,40,37,35,50,74,79), +(2,9,41,38,36,50,76,80), +(2,9,42,38,36,51,77,82), +(2,9,43,39,37,52,79,84), +(2,9,44,39,38,53,81,85), +(2,9,45,40,38,54,83,87), +(2,9,46,40,39,55,84,89), +(2,9,47,41,39,56,86,91), +(2,9,48,41,40,56,88,92), +(2,9,49,42,41,57,90,94), +(2,9,50,42,41,58,91,96), +(2,9,51,43,42,59,93,98), +(2,9,52,43,43,60,95,99), +(2,9,53,44,43,61,97,101), +(2,9,54,45,44,62,99,103), +(2,9,55,45,45,63,101,105), +(2,9,56,46,45,64,102,107), +(2,9,57,46,46,65,104,109), +(2,9,58,47,47,66,106,110), +(2,9,59,47,47,67,108,112), +(2,9,60,48,48,68,110,114), +(2,9,61,48,49,69,112,116), +(2,9,62,49,49,70,114,118), +(2,9,63,50,50,71,116,120), +(2,9,64,50,51,72,118,122), +(2,9,65,51,51,73,120,124), +(2,9,66,52,52,74,122,126), +(2,9,67,52,53,75,124,128), +(2,9,68,53,54,76,126,130), +(2,9,69,53,54,77,128,132), +(2,9,70,54,55,78,130,134), +(3,1,1,25,16,25,19,19), +(3,1,2,26,17,26,19,19), +(3,1,3,28,18,27,19,20), +(3,1,4,29,18,28,19,20), +(3,1,5,30,19,30,19,20), +(3,1,6,31,20,31,19,20), +(3,1,7,33,21,32,20,21), +(3,1,8,34,22,33,20,21), +(3,1,9,36,23,35,20,21), +(3,1,10,37,23,36,20,22), +(3,1,11,38,24,37,20,22), +(3,1,12,40,25,38,20,22), +(3,1,13,41,26,40,20,23), +(3,1,14,43,27,41,20,23), +(3,1,15,44,28,42,20,23), +(3,1,16,46,29,44,21,24), +(3,1,17,47,30,45,21,24), +(3,1,18,49,31,46,21,24), +(3,1,19,50,32,48,21,25), +(3,1,20,52,33,49,21,25), +(3,1,21,53,34,51,21,26), +(3,1,22,55,34,52,21,26), +(3,1,23,56,35,53,21,26), +(3,1,24,58,36,55,22,27), +(3,1,25,59,37,56,22,27), +(3,1,26,61,38,58,22,27), +(3,1,27,63,39,59,22,28), +(3,1,28,64,41,61,22,28), +(3,1,29,66,42,62,22,29), +(3,1,30,68,43,64,23,29), +(3,1,31,69,44,65,23,30), +(3,1,32,71,45,67,23,30), +(3,1,33,73,46,68,23,30), +(3,1,34,75,47,70,23,31), +(3,1,35,76,48,72,24,31), +(3,1,36,78,49,73,24,32), +(3,1,37,80,50,75,24,32), +(3,1,38,82,51,76,24,33), +(3,1,39,84,52,78,24,33), +(3,1,40,85,54,80,24,34), +(3,1,41,87,55,81,25,34), +(3,1,42,89,56,83,25,35), +(3,1,43,91,57,85,25,35), +(3,1,44,93,58,87,25,36), +(3,1,45,95,59,88,26,36), +(3,1,46,97,61,90,26,37), +(3,1,47,99,62,92,26,37), +(3,1,48,101,63,94,26,38), +(3,1,49,102,64,95,26,38), +(3,1,50,104,65,97,27,39), +(3,1,51,106,67,99,27,39), +(3,1,52,108,68,101,27,40), +(3,1,53,110,69,103,27,40), +(3,1,54,112,70,104,28,41), +(3,1,55,115,72,106,28,41), +(3,1,56,117,73,108,28,42), +(3,1,57,119,74,110,28,42), +(3,1,58,121,76,112,29,43), +(3,1,59,123,77,114,29,43), +(3,1,60,125,78,116,29,44), +(3,1,61,127,80,118,29,45), +(3,1,62,129,81,120,30,45), +(3,1,63,131,82,122,30,46), +(3,1,64,134,84,124,30,46), +(3,1,65,136,85,126,31,47), +(3,1,66,138,86,128,31,48), +(3,1,67,140,88,130,31,48), +(3,1,68,142,89,132,31,49), +(3,1,69,145,91,134,32,49), +(3,1,70,147,92,136,32,50), +(3,2,1,24,16,25,19,20), +(3,2,2,25,17,26,20,21), +(3,2,3,26,17,27,20,21), +(3,2,4,27,18,28,21,22), +(3,2,5,28,18,29,22,23), +(3,2,6,29,19,30,22,24), +(3,2,7,31,20,31,23,24), +(3,2,8,32,20,32,24,25), +(3,2,9,33,21,33,24,26), +(3,2,10,34,21,34,25,26), +(3,2,11,35,22,36,26,27), +(3,2,12,36,23,37,26,28), +(3,2,13,38,23,38,27,29), +(3,2,14,39,24,39,28,30), +(3,2,15,40,25,40,29,30), +(3,2,16,41,25,41,29,31), +(3,2,17,43,26,43,30,32), +(3,2,18,44,27,44,31,33), +(3,2,19,45,28,45,32,34), +(3,2,20,47,28,46,32,35), +(3,2,21,48,29,47,33,35), +(3,2,22,49,30,49,34,36), +(3,2,23,51,30,50,35,37), +(3,2,24,52,31,51,36,38), +(3,2,25,53,32,52,36,39), +(3,2,26,55,33,54,37,40), +(3,2,27,56,33,55,38,41), +(3,2,28,57,34,56,39,42), +(3,2,29,59,35,58,40,43), +(3,2,30,60,36,59,41,43), +(3,2,31,62,37,60,42,44), +(3,2,32,63,37,62,42,45), +(3,2,33,65,38,63,43,46), +(3,2,34,66,39,65,44,47), +(3,2,35,68,40,66,45,48), +(3,2,36,69,41,67,46,49), +(3,2,37,71,41,69,47,50), +(3,2,38,72,42,70,48,51), +(3,2,39,74,43,72,49,52), +(3,2,40,75,44,73,50,53), +(3,2,41,77,45,75,51,54), +(3,2,42,78,46,76,52,55), +(3,2,43,80,47,78,53,56), +(3,2,44,82,47,79,54,57), +(3,2,45,83,48,81,55,59), +(3,2,46,85,49,82,56,60), +(3,2,47,87,50,84,57,61), +(3,2,48,88,51,85,58,62), +(3,2,49,90,52,87,59,63), +(3,2,50,92,53,89,60,64), +(3,2,51,93,54,90,61,65), +(3,2,52,95,55,92,62,66), +(3,2,53,97,56,93,63,67), +(3,2,54,98,57,95,64,69), +(3,2,55,100,58,97,65,70), +(3,2,56,102,59,98,66,71), +(3,2,57,104,60,100,67,72), +(3,2,58,106,61,102,68,73), +(3,2,59,107,62,103,69,74), +(3,2,60,109,63,105,70,76), +(3,2,61,111,64,107,72,77), +(3,2,62,113,65,109,73,78), +(3,2,63,115,66,110,74,79), +(3,2,64,117,67,112,75,80), +(3,2,65,118,68,114,76,82), +(3,2,66,120,69,116,77,83), +(3,2,67,122,70,118,78,84), +(3,2,68,124,71,119,80,85), +(3,2,69,126,72,121,81,87), +(3,2,70,128,73,123,82,88), +(3,3,1,22,19,24,19,20), +(3,3,2,22,20,25,20,21), +(3,3,3,23,22,26,20,21), +(3,3,4,23,23,27,21,22), +(3,3,5,24,25,28,21,23), +(3,3,6,24,26,29,22,23), +(3,3,7,25,27,29,23,24), +(3,3,8,25,29,30,23,25), +(3,3,9,25,30,31,24,25), +(3,3,10,26,32,32,24,26), +(3,3,11,26,33,33,25,27), +(3,3,12,27,35,34,26,27), +(3,3,13,27,36,35,26,28), +(3,3,14,28,38,36,27,29), +(3,3,15,28,39,37,28,29), +(3,3,16,29,41,38,28,30), +(3,3,17,29,42,39,29,31), +(3,3,18,30,44,41,30,32), +(3,3,19,30,46,42,30,32), +(3,3,20,31,47,43,31,33), +(3,3,21,32,49,44,32,34), +(3,3,22,32,51,45,33,35), +(3,3,23,33,52,46,33,36), +(3,3,24,33,54,47,34,36), +(3,3,25,34,56,48,35,37), +(3,3,26,34,57,49,35,38), +(3,3,27,35,59,51,36,39), +(3,3,28,35,61,52,37,40), +(3,3,29,36,63,53,38,40), +(3,3,30,37,64,54,39,41), +(3,3,31,37,66,55,39,42), +(3,3,32,38,68,57,40,43), +(3,3,33,38,70,58,41,44), +(3,3,34,39,71,59,42,45), +(3,3,35,40,73,60,43,46), +(3,3,36,40,75,62,43,47), +(3,3,37,41,77,63,44,47), +(3,3,38,42,79,64,45,48), +(3,3,39,42,81,65,46,49), +(3,3,40,43,83,67,47,50), +(3,3,41,44,85,68,48,51), +(3,3,42,44,87,69,49,52), +(3,3,43,45,89,71,49,53), +(3,3,44,46,91,72,50,54), +(3,3,45,46,93,73,51,55), +(3,3,46,47,95,75,52,56), +(3,3,47,48,97,76,53,57), +(3,3,48,49,99,78,54,58), +(3,3,49,49,101,79,55,59), +(3,3,50,50,103,80,56,60), +(3,3,51,51,105,82,57,61), +(3,3,52,51,107,83,58,62), +(3,3,53,52,109,85,59,63), +(3,3,54,53,111,86,60,64), +(3,3,55,54,113,88,61,65), +(3,3,56,55,115,89,62,66), +(3,3,57,55,118,91,62,67), +(3,3,58,56,120,92,63,68), +(3,3,59,57,122,94,64,70), +(3,3,60,58,124,95,65,71), +(3,3,61,58,126,97,67,72), +(3,3,62,59,129,98,68,73), +(3,3,63,60,131,100,69,74), +(3,3,64,61,133,101,70,75), +(3,3,65,62,135,103,71,76), +(3,3,66,63,138,105,72,77), +(3,3,67,63,140,106,73,78), +(3,3,68,64,142,108,74,80), +(3,3,69,65,145,109,75,81), +(3,3,70,66,147,111,76,82), +(3,4,1,23,19,24,19,19), +(3,4,2,24,20,25,19,19), +(3,4,3,24,22,25,19,20), +(3,4,4,25,23,26,19,20), +(3,4,5,26,25,27,20,20), +(3,4,6,27,26,27,20,21), +(3,4,7,28,28,28,20,21), +(3,4,8,28,29,29,20,22), +(3,4,9,29,31,30,20,22), +(3,4,10,30,32,30,20,22), +(3,4,11,31,34,31,21,23), +(3,4,12,32,36,32,21,23), +(3,4,13,33,37,33,21,24), +(3,4,14,33,39,33,21,24), +(3,4,15,34,40,34,21,25), +(3,4,16,35,42,35,22,25), +(3,4,17,36,44,36,22,25), +(3,4,18,37,45,37,22,26), +(3,4,19,38,47,38,22,26), +(3,4,20,39,49,38,22,27), +(3,4,21,40,51,39,23,27), +(3,4,22,41,52,40,23,28), +(3,4,23,42,54,41,23,28), +(3,4,24,43,56,42,23,29), +(3,4,25,44,58,43,24,29), +(3,4,26,44,59,44,24,30), +(3,4,27,45,61,44,24,30), +(3,4,28,46,63,45,24,31), +(3,4,29,47,65,46,25,31), +(3,4,30,48,67,47,25,32), +(3,4,31,49,69,48,25,32), +(3,4,32,51,71,49,25,33), +(3,4,33,52,72,50,26,33), +(3,4,34,53,74,51,26,34), +(3,4,35,54,76,52,26,34), +(3,4,36,55,78,53,26,35), +(3,4,37,56,80,54,27,35), +(3,4,38,57,82,55,27,36), +(3,4,39,58,84,56,27,37), +(3,4,40,59,86,57,28,37), +(3,4,41,60,88,58,28,38), +(3,4,42,61,90,59,28,38), +(3,4,43,63,92,60,28,39), +(3,4,44,64,95,61,29,39), +(3,4,45,65,97,62,29,40), +(3,4,46,66,99,63,29,41), +(3,4,47,67,101,64,30,41), +(3,4,48,68,103,66,30,42), +(3,4,49,70,105,67,30,43), +(3,4,50,71,107,68,31,43), +(3,4,51,72,110,69,31,44), +(3,4,52,73,112,70,31,44), +(3,4,53,74,114,71,32,45), +(3,4,54,76,116,72,32,46), +(3,4,55,77,118,73,32,46), +(3,4,56,78,121,75,33,47), +(3,4,57,80,123,76,33,48), +(3,4,58,81,125,77,33,48), +(3,4,59,82,128,78,34,49), +(3,4,60,83,130,79,34,50), +(3,4,61,85,132,81,34,51), +(3,4,62,86,135,82,35,51), +(3,4,63,87,137,83,35,52), +(3,4,64,89,139,84,36,53), +(3,4,65,90,142,86,36,53), +(3,4,66,91,144,87,36,54), +(3,4,67,93,147,88,37,55), +(3,4,68,94,149,89,37,56), +(3,4,69,96,152,91,38,56), +(3,4,70,97,154,92,38,57), +(3,5,1,22,16,23,21,22), +(3,5,2,22,16,23,22,23), +(3,5,3,22,16,24,24,25), +(3,5,4,22,17,24,25,26), +(3,5,5,23,17,24,26,27), +(3,5,6,23,17,25,28,29), +(3,5,7,23,17,25,29,30), +(3,5,8,23,18,26,30,32), +(3,5,9,23,18,26,32,33), +(3,5,10,23,18,26,33,35), +(3,5,11,24,18,27,35,36), +(3,5,12,24,19,27,36,38), +(3,5,13,24,19,28,37,39), +(3,5,14,24,19,28,39,41), +(3,5,15,24,19,28,40,42), +(3,5,16,24,20,29,42,44), +(3,5,17,25,20,29,43,45), +(3,5,18,25,20,30,45,47), +(3,5,19,25,21,30,46,49), +(3,5,20,25,21,31,48,50), +(3,5,21,25,21,31,50,52), +(3,5,22,26,22,31,51,53), +(3,5,23,26,22,32,53,55), +(3,5,24,26,22,32,54,57), +(3,5,25,26,22,33,56,58), +(3,5,26,27,23,33,58,60), +(3,5,27,27,23,34,59,62), +(3,5,28,27,23,34,61,64), +(3,5,29,27,24,35,63,65), +(3,5,30,28,24,35,64,67), +(3,5,31,28,24,36,66,69), +(3,5,32,28,25,36,68,71), +(3,5,33,28,25,37,70,72), +(3,5,34,29,26,38,71,74), +(3,5,35,29,26,38,73,76), +(3,5,36,29,26,39,75,78), +(3,5,37,29,27,39,77,80), +(3,5,38,30,27,40,78,82), +(3,5,39,30,27,40,80,84), +(3,5,40,30,28,41,82,86), +(3,5,41,31,28,41,84,88), +(3,5,42,31,29,42,86,89), +(3,5,43,31,29,43,88,91), +(3,5,44,32,29,43,90,93), +(3,5,45,32,30,44,92,95), +(3,5,46,32,30,44,93,97), +(3,5,47,32,30,45,95,99), +(3,5,48,33,31,46,97,101), +(3,5,49,33,31,46,99,103), +(3,5,50,33,32,47,101,106), +(3,5,51,34,32,48,103,108), +(3,5,52,34,33,48,105,110), +(3,5,53,35,33,49,107,112), +(3,5,54,35,33,50,109,114), +(3,5,55,35,34,50,111,116), +(3,5,56,36,34,51,113,118), +(3,5,57,36,35,52,116,120), +(3,5,58,36,35,52,118,123), +(3,5,59,37,36,53,120,125), +(3,5,60,37,36,54,122,127), +(3,5,61,37,37,54,124,129), +(3,5,62,38,37,55,126,131), +(3,5,63,38,38,56,128,134), +(3,5,64,39,38,57,131,136), +(3,5,65,39,39,57,133,138), +(3,5,66,39,39,58,135,141), +(3,5,67,40,40,59,137,143), +(3,5,68,40,40,59,139,145), +(3,5,69,41,40,60,142,148), +(3,5,70,41,41,61,144,150), +(4,1,1,20,25,21,20,20), +(4,1,2,21,26,22,20,20), +(4,1,3,23,27,23,20,21), +(4,1,4,24,27,25,20,21), +(4,1,5,25,28,26,20,21), +(4,1,6,27,29,27,20,21), +(4,1,7,28,30,28,21,22), +(4,1,8,29,31,29,21,22), +(4,1,9,31,31,31,21,22), +(4,1,10,32,32,32,21,23), +(4,1,11,33,33,33,21,23), +(4,1,12,35,34,34,21,23), +(4,1,13,36,35,36,21,24), +(4,1,14,38,36,37,21,24), +(4,1,15,39,37,38,21,24), +(4,1,16,41,37,40,21,25), +(4,1,17,42,38,41,22,25), +(4,1,18,44,39,43,22,25), +(4,1,19,45,40,44,22,26), +(4,1,20,47,41,45,22,26), +(4,1,21,48,42,47,22,26), +(4,1,22,50,43,48,22,27), +(4,1,23,52,44,50,22,27), +(4,1,24,53,45,51,23,28), +(4,1,25,55,46,52,23,28), +(4,1,26,56,47,54,23,28), +(4,1,27,58,48,55,23,29), +(4,1,28,60,49,57,23,29), +(4,1,29,61,50,58,23,30), +(4,1,30,63,51,60,24,30), +(4,1,31,65,52,62,24,30), +(4,1,32,66,53,63,24,31), +(4,1,33,68,54,65,24,31), +(4,1,34,70,55,66,24,32), +(4,1,35,72,56,68,24,32), +(4,1,36,73,58,69,25,33), +(4,1,37,75,59,71,25,33), +(4,1,38,77,60,73,25,34), +(4,1,39,79,61,74,25,34), +(4,1,40,81,62,76,25,35), +(4,1,41,82,63,78,26,35), +(4,1,42,84,64,79,26,35), +(4,1,43,86,66,81,26,36), +(4,1,44,88,67,83,26,36), +(4,1,45,90,68,85,26,37), +(4,1,46,92,69,86,27,37), +(4,1,47,94,70,88,27,38), +(4,1,48,96,72,90,27,38), +(4,1,49,98,73,92,27,39), +(4,1,50,100,74,93,28,40), +(4,1,51,102,75,95,28,40), +(4,1,52,104,77,97,28,41), +(4,1,53,106,78,99,28,41), +(4,1,54,108,79,101,29,42), +(4,1,55,110,80,103,29,42), +(4,1,56,112,82,104,29,43), +(4,1,57,114,83,106,29,43), +(4,1,58,116,84,108,30,44), +(4,1,59,118,86,110,30,44), +(4,1,60,120,87,112,30,45), +(4,1,61,122,88,114,30,46), +(4,1,62,124,90,116,31,46), +(4,1,63,127,91,118,31,47), +(4,1,64,129,92,120,31,47), +(4,1,65,131,94,122,32,48), +(4,1,66,133,95,124,32,49), +(4,1,67,135,97,126,32,49), +(4,1,68,138,98,128,32,50), +(4,1,69,140,100,130,33,50), +(4,1,70,142,101,132,33,51), +(4,3,1,17,28,20,20,21), +(4,3,2,17,29,21,21,22), +(4,3,3,18,31,22,21,22), +(4,3,4,18,32,23,22,23), +(4,3,5,19,33,24,22,24), +(4,3,6,19,35,25,23,24), +(4,3,7,20,36,26,24,25), +(4,3,8,20,38,27,24,25), +(4,3,9,21,39,27,25,26), +(4,3,10,21,40,28,25,27), +(4,3,11,22,42,29,26,28), +(4,3,12,22,43,30,27,28), +(4,3,13,23,45,31,27,29), +(4,3,14,23,46,32,28,30), +(4,3,15,24,48,34,29,30), +(4,3,16,24,50,35,29,31), +(4,3,17,25,51,36,30,32), +(4,3,18,25,53,37,31,33), +(4,3,19,26,54,38,31,33), +(4,3,20,26,56,39,32,34), +(4,3,21,27,57,40,33,35), +(4,3,22,27,59,41,33,36), +(4,3,23,28,61,42,34,36), +(4,3,24,28,62,43,35,37), +(4,3,25,29,64,44,36,38), +(4,3,26,30,66,46,36,39), +(4,3,27,30,68,47,37,40), +(4,3,28,31,69,48,38,41), +(4,3,29,31,71,49,39,41), +(4,3,30,32,73,50,39,42), +(4,3,31,33,75,52,40,43), +(4,3,32,33,76,53,41,44), +(4,3,33,34,78,54,42,45), +(4,3,34,34,80,55,43,46), +(4,3,35,35,82,57,44,47), +(4,3,36,36,84,58,44,48), +(4,3,37,36,86,59,45,48), +(4,3,38,37,87,60,46,49), +(4,3,39,38,89,62,47,50), +(4,3,40,38,91,63,48,51), +(4,3,41,39,93,64,49,52), +(4,3,42,40,95,66,49,53), +(4,3,43,40,97,67,50,54), +(4,3,44,41,99,68,51,55), +(4,3,45,42,101,70,52,56), +(4,3,46,42,103,71,53,57), +(4,3,47,43,105,72,54,58), +(4,3,48,44,107,74,55,59), +(4,3,49,45,109,75,56,60), +(4,3,50,45,111,77,57,61), +(4,3,51,46,113,78,58,62), +(4,3,52,47,115,79,59,63), +(4,3,53,47,118,81,60,64), +(4,3,54,48,120,82,61,65), +(4,3,55,49,122,84,61,66), +(4,3,56,50,124,85,62,67), +(4,3,57,50,126,87,63,68), +(4,3,58,51,128,88,64,69), +(4,3,59,52,131,90,65,70), +(4,3,60,53,133,91,66,72), +(4,3,61,54,135,93,67,73), +(4,3,62,54,137,94,69,74), +(4,3,63,55,140,96,70,75), +(4,3,64,56,142,97,71,76), +(4,3,65,57,144,99,72,77), +(4,3,66,58,147,101,73,78), +(4,3,67,58,149,102,74,79), +(4,3,68,59,151,104,75,81), +(4,3,69,60,154,105,76,82), +(4,3,70,61,156,107,77,83), +(4,4,1,18,28,20,20,20), +(4,4,2,19,29,21,20,20), +(4,4,3,20,31,21,20,21), +(4,4,4,20,32,22,20,21), +(4,4,5,21,34,23,21,21), +(4,4,6,22,35,24,21,22), +(4,4,7,23,37,24,21,22), +(4,4,8,24,38,25,21,23), +(4,4,9,24,40,26,21,23), +(4,4,10,25,41,26,21,23), +(4,4,11,26,43,27,22,24), +(4,4,12,27,44,28,22,24), +(4,4,13,28,46,29,22,25), +(4,4,14,29,48,30,22,25), +(4,4,15,29,49,30,22,25), +(4,4,16,30,51,31,23,26), +(4,4,17,31,52,32,23,26), +(4,4,18,32,54,33,23,27), +(4,4,19,33,56,34,23,27), +(4,4,20,34,57,35,23,28), +(4,4,21,35,59,35,24,28), +(4,4,22,36,61,36,24,29), +(4,4,23,37,63,37,24,29), +(4,4,24,38,64,38,24,30), +(4,4,25,39,66,39,25,30), +(4,4,26,40,68,40,25,31), +(4,4,27,41,70,41,25,31), +(4,4,28,42,72,42,25,32), +(4,4,29,43,73,43,25,32), +(4,4,30,44,75,43,26,33), +(4,4,31,45,77,44,26,33), +(4,4,32,46,79,45,26,34), +(4,4,33,47,81,46,27,34), +(4,4,34,48,83,47,27,35), +(4,4,35,49,85,48,27,35), +(4,4,36,50,87,49,27,36), +(4,4,37,51,89,50,28,36), +(4,4,38,52,91,51,28,37), +(4,4,39,53,93,52,28,38), +(4,4,40,54,95,53,28,38), +(4,4,41,56,97,54,29,39), +(4,4,42,57,99,55,29,39), +(4,4,43,58,101,56,29,40), +(4,4,44,59,103,57,30,40), +(4,4,45,60,105,59,30,41), +(4,4,46,61,107,60,30,42), +(4,4,47,62,109,61,31,42), +(4,4,48,64,112,62,31,43), +(4,4,49,65,114,63,31,44), +(4,4,50,66,116,64,32,44), +(4,4,51,67,118,65,32,45), +(4,4,52,68,120,66,32,45), +(4,4,53,70,123,67,33,46), +(4,4,54,71,125,69,33,47), +(4,4,55,72,127,70,33,47), +(4,4,56,73,129,71,34,48), +(4,4,57,75,132,72,34,49), +(4,4,58,76,134,73,34,49), +(4,4,59,77,136,74,35,50), +(4,4,60,79,139,76,35,51), +(4,4,61,80,141,77,35,51), +(4,4,62,81,143,78,36,52), +(4,4,63,82,146,79,36,53), +(4,4,64,84,148,80,37,54), +(4,4,65,85,151,82,37,54), +(4,4,66,87,153,83,37,55), +(4,4,67,88,156,84,38,56), +(4,4,68,89,158,85,38,57), +(4,4,69,91,160,87,39,57), +(4,4,70,92,163,88,39,58), +(4,5,1,17,25,19,22,23), +(4,5,2,17,25,19,23,24), +(4,5,3,17,25,20,25,26), +(4,5,4,17,26,20,26,27), +(4,5,5,18,26,20,27,28), +(4,5,6,18,26,21,29,30), +(4,5,7,18,26,21,30,31), +(4,5,8,18,26,22,31,33), +(4,5,9,18,27,22,33,34), +(4,5,10,19,27,22,34,36), +(4,5,11,19,27,23,36,37), +(4,5,12,19,27,23,37,39), +(4,5,13,19,28,24,38,40), +(4,5,14,19,28,24,40,42), +(4,5,15,19,28,25,41,43), +(4,5,16,20,28,25,43,45), +(4,5,17,20,29,25,44,46), +(4,5,18,20,29,26,46,48), +(4,5,19,20,29,26,47,49), +(4,5,20,21,30,27,49,51), +(4,5,21,21,30,27,51,53), +(4,5,22,21,30,28,52,54), +(4,5,23,21,30,28,54,56), +(4,5,24,21,31,29,55,58), +(4,5,25,22,31,29,57,59), +(4,5,26,22,31,30,59,61), +(4,5,27,22,32,30,60,63), +(4,5,28,22,32,31,62,65), +(4,5,29,23,32,31,64,66), +(4,5,30,23,33,32,65,68), +(4,5,31,23,33,32,67,70), +(4,5,32,23,33,33,69,72), +(4,5,33,24,34,33,70,73), +(4,5,34,24,34,34,72,75), +(4,5,35,24,34,34,74,77), +(4,5,36,24,35,35,76,79), +(4,5,37,25,35,35,78,81), +(4,5,38,25,35,36,79,83), +(4,5,39,25,36,37,81,85), +(4,5,40,26,36,37,83,87), +(4,5,41,26,37,38,85,88), +(4,5,42,26,37,38,87,90), +(4,5,43,27,37,39,89,92), +(4,5,44,27,38,39,91,94), +(4,5,45,27,38,40,92,96), +(4,5,46,27,39,41,94,98), +(4,5,47,28,39,41,96,100), +(4,5,48,28,39,42,98,102), +(4,5,49,28,40,43,100,104), +(4,5,50,29,40,43,102,106), +(4,5,51,29,41,44,104,109), +(4,5,52,29,41,44,106,111), +(4,5,53,30,42,45,108,113), +(4,5,54,30,42,46,110,115), +(4,5,55,30,43,46,112,117), +(4,5,56,31,43,47,114,119), +(4,5,57,31,43,48,117,121), +(4,5,58,31,44,48,119,124), +(4,5,59,32,44,49,121,126), +(4,5,60,32,45,50,123,128), +(4,5,61,33,45,51,125,130), +(4,5,62,33,46,51,127,132), +(4,5,63,33,46,52,129,135), +(4,5,64,34,47,53,132,137), +(4,5,65,34,47,53,134,139), +(4,5,66,34,48,54,136,142), +(4,5,67,35,48,55,138,144), +(4,5,68,35,49,56,140,146), +(4,5,69,36,49,56,143,149), +(4,5,70,36,50,57,145,151), +(4,11,1,18,25,19,22,22), +(4,11,2,19,25,20,23,23), +(4,11,3,19,26,20,24,24), +(4,11,4,20,26,21,25,26), +(4,11,5,20,27,22,26,27), +(4,11,6,21,27,22,27,28), +(4,11,7,21,28,23,28,29), +(4,11,8,22,28,24,29,30), +(4,11,9,23,29,24,30,32), +(4,11,10,23,29,25,32,33), +(4,11,11,24,30,26,33,34), +(4,11,12,24,31,26,34,35), +(4,11,13,25,31,27,35,37), +(4,11,14,26,32,28,36,38), +(4,11,15,26,32,29,37,39), +(4,11,16,27,33,29,38,41), +(4,11,17,28,33,30,40,42), +(4,11,18,28,34,31,41,43), +(4,11,19,29,35,32,42,45), +(4,11,20,30,35,32,43,46), +(4,11,21,30,36,33,45,48), +(4,11,22,31,36,34,46,49), +(4,11,23,32,37,35,47,51), +(4,11,24,32,38,36,48,52), +(4,11,25,33,38,36,50,53), +(4,11,26,34,39,37,51,55), +(4,11,27,35,40,38,52,56), +(4,11,28,35,40,39,54,58), +(4,11,29,36,41,40,55,59), +(4,11,30,37,42,41,56,61), +(4,11,31,38,42,42,58,62), +(4,11,32,38,43,42,59,64), +(4,11,33,39,44,43,60,66), +(4,11,34,40,44,44,62,67), +(4,11,35,41,45,45,63,69), +(4,11,36,42,46,46,65,70), +(4,11,37,42,47,47,66,72), +(4,11,38,43,47,48,67,74), +(4,11,39,44,48,49,69,75), +(4,11,40,45,49,50,70,77), +(4,11,41,46,50,51,72,79), +(4,11,42,46,50,52,73,80), +(4,11,43,47,51,53,75,82), +(4,11,44,48,52,54,76,84), +(4,11,45,49,53,55,78,85), +(4,11,46,50,54,56,79,87), +(4,11,47,51,54,57,81,89), +(4,11,48,52,55,58,83,91), +(4,11,49,53,56,59,84,93), +(4,11,50,53,57,60,86,94), +(4,11,51,54,58,61,87,96), +(4,11,52,55,59,62,89,98), +(4,11,53,56,59,63,91,100), +(4,11,54,57,60,64,92,102), +(4,11,55,58,61,65,94,103), +(4,11,56,59,62,66,95,105), +(4,11,57,60,63,67,97,107), +(4,11,58,61,64,68,99,109), +(4,11,59,62,65,69,101,111), +(4,11,60,63,66,70,102,113), +(4,11,61,64,66,72,104,115), +(4,11,62,65,67,73,106,117), +(4,11,63,66,68,74,107,119), +(4,11,64,67,69,75,109,121), +(4,11,65,68,70,76,111,123), +(4,11,66,69,71,77,113,125), +(4,11,67,70,72,78,115,127), +(4,11,68,71,73,80,116,129), +(4,11,69,72,74,81,118,131), +(4,11,70,73,75,82,120,133), +(5,1,1,22,18,23,18,25), +(5,1,2,23,19,24,18,25), +(5,1,3,25,20,25,18,26), +(5,1,4,26,20,26,18,26), +(5,1,5,27,21,28,18,26), +(5,1,6,29,22,29,18,26), +(5,1,7,30,23,30,19,27), +(5,1,8,31,24,31,19,27), +(5,1,9,33,25,33,19,27), +(5,1,10,34,25,34,19,28), +(5,1,11,35,26,35,19,28), +(5,1,12,37,27,36,19,28), +(5,1,13,38,28,38,19,28), +(5,1,14,40,29,39,19,29), +(5,1,15,41,30,40,19,29), +(5,1,16,43,31,42,20,29), +(5,1,17,44,32,43,20,30), +(5,1,18,46,33,44,20,30), +(5,1,19,47,34,46,20,31), +(5,1,20,49,34,47,20,31), +(5,1,21,50,35,49,20,31), +(5,1,22,52,36,50,20,32), +(5,1,23,53,37,51,21,32), +(5,1,24,55,38,53,21,32), +(5,1,25,57,39,54,21,33), +(5,1,26,58,40,56,21,33), +(5,1,27,60,41,57,21,34), +(5,1,28,62,42,59,21,34), +(5,1,29,63,43,60,21,34), +(5,1,30,65,44,62,22,35), +(5,1,31,67,46,63,22,35), +(5,1,32,68,47,65,22,36), +(5,1,33,70,48,67,22,36), +(5,1,34,72,49,68,22,36), +(5,1,35,74,50,70,23,37), +(5,1,36,75,51,71,23,37), +(5,1,37,77,52,73,23,38), +(5,1,38,79,53,75,23,38), +(5,1,39,81,54,76,23,39), +(5,1,40,83,55,78,24,39), +(5,1,41,84,57,80,24,40), +(5,1,42,86,58,81,24,40), +(5,1,43,88,59,83,24,41), +(5,1,44,90,60,85,24,41), +(5,1,45,92,61,86,25,42), +(5,1,46,94,62,88,25,42), +(5,1,47,96,64,90,25,43), +(5,1,48,98,65,92,25,43), +(5,1,49,100,66,93,25,44), +(5,1,50,102,67,95,26,44), +(5,1,51,104,69,97,26,45), +(5,1,52,106,70,99,26,45), +(5,1,53,108,71,101,26,46), +(5,1,54,110,72,103,27,46), +(5,1,55,112,74,104,27,47), +(5,1,56,114,75,106,27,48), +(5,1,57,116,76,108,27,48), +(5,1,58,118,78,110,28,49), +(5,1,59,120,79,112,28,49), +(5,1,60,122,80,114,28,50), +(5,1,61,124,82,116,28,50), +(5,1,62,126,83,118,29,51), +(5,1,63,128,84,120,29,52), +(5,1,64,131,86,122,29,52), +(5,1,65,133,87,124,30,53), +(5,1,66,135,88,126,30,53), +(5,1,67,137,90,128,30,54), +(5,1,68,139,91,130,30,55), +(5,1,69,142,93,132,31,55), +(5,1,70,144,94,134,31,56), +(5,4,1,20,21,22,18,25), +(5,4,2,21,22,23,18,25), +(5,4,3,22,24,23,18,26), +(5,4,4,22,25,24,18,26), +(5,4,5,23,27,25,19,26), +(5,4,6,24,28,25,19,27), +(5,4,7,25,30,26,19,27), +(5,4,8,25,31,27,19,27), +(5,4,9,26,33,28,19,28), +(5,4,10,27,34,28,19,28), +(5,4,11,28,36,29,20,29), +(5,4,12,29,38,30,20,29), +(5,4,13,30,39,31,20,29), +(5,4,14,31,41,32,20,30), +(5,4,15,31,42,32,20,30), +(5,4,16,32,44,33,21,31), +(5,4,17,33,46,34,21,31), +(5,4,18,34,47,35,21,32), +(5,4,19,35,49,36,21,32), +(5,4,20,36,51,36,21,32), +(5,4,21,37,52,37,22,33), +(5,4,22,38,54,38,22,33), +(5,4,23,39,56,39,22,34), +(5,4,24,40,58,40,22,34), +(5,4,25,41,60,41,23,35), +(5,4,26,42,61,42,23,35), +(5,4,27,43,63,43,23,36), +(5,4,28,44,65,44,23,36), +(5,4,29,45,67,44,24,37), +(5,4,30,46,69,45,24,37), +(5,4,31,47,71,46,24,38), +(5,4,32,48,72,47,24,38), +(5,4,33,49,74,48,25,39), +(5,4,34,50,76,49,25,39), +(5,4,35,51,78,50,25,40), +(5,4,36,52,80,51,25,41), +(5,4,37,53,82,52,26,41), +(5,4,38,54,84,53,26,42), +(5,4,39,55,86,54,26,42), +(5,4,40,56,88,55,27,43), +(5,4,41,57,90,56,27,43), +(5,4,42,59,92,57,27,44), +(5,4,43,60,94,58,27,45), +(5,4,44,61,96,59,28,45), +(5,4,45,62,99,60,28,46), +(5,4,46,63,101,61,28,46), +(5,4,47,64,103,63,29,47), +(5,4,48,66,105,64,29,48), +(5,4,49,67,107,65,29,48), +(5,4,50,68,109,66,30,49), +(5,4,51,69,111,67,30,50), +(5,4,52,70,114,68,30,50), +(5,4,53,72,116,69,31,51), +(5,4,54,73,118,70,31,52), +(5,4,55,74,120,72,31,52), +(5,4,56,75,123,73,32,53), +(5,4,57,77,125,74,32,54), +(5,4,58,78,127,75,32,54), +(5,4,59,79,130,76,33,55), +(5,4,60,81,132,77,33,56), +(5,4,61,82,134,79,34,56), +(5,4,62,83,137,80,34,57), +(5,4,63,84,139,81,34,58), +(5,4,64,86,141,82,35,59), +(5,4,65,87,144,84,35,59), +(5,4,66,88,146,85,35,60), +(5,4,67,90,149,86,36,61), +(5,4,68,91,151,87,36,61), +(5,4,69,93,154,89,37,62), +(5,4,70,94,156,90,37,63), +(5,5,1,19,18,21,20,28), +(5,5,2,19,18,21,21,29), +(5,5,3,19,18,22,23,31), +(5,5,4,19,19,22,24,32), +(5,5,5,20,19,22,25,33), +(5,5,6,20,19,23,27,35), +(5,5,7,20,19,23,28,36), +(5,5,8,20,20,24,29,38), +(5,5,9,20,20,24,31,39), +(5,5,10,20,20,24,32,40), +(5,5,11,21,20,25,34,42), +(5,5,12,21,21,25,35,43), +(5,5,13,21,21,26,37,45), +(5,5,14,21,21,26,38,46), +(5,5,15,21,21,26,39,48), +(5,5,16,22,22,27,41,50), +(5,5,17,22,22,27,42,51), +(5,5,18,22,22,28,44,53), +(5,5,19,22,23,28,46,54), +(5,5,20,22,23,29,47,56), +(5,5,21,23,23,29,49,57), +(5,5,22,23,23,30,50,59), +(5,5,23,23,24,30,52,61), +(5,5,24,23,24,31,53,62), +(5,5,25,24,24,31,55,64), +(5,5,26,24,25,32,57,66), +(5,5,27,24,25,32,58,68), +(5,5,28,24,25,33,60,69), +(5,5,29,25,26,33,62,71), +(5,5,30,25,26,34,63,73), +(5,5,31,25,26,34,65,75), +(5,5,32,25,27,35,67,76), +(5,5,33,26,27,35,69,78), +(5,5,34,26,27,36,70,80), +(5,5,35,26,28,36,72,82), +(5,5,36,26,28,37,74,84), +(5,5,37,27,28,37,76,86), +(5,5,38,27,29,38,77,87), +(5,5,39,27,29,38,79,89), +(5,5,40,28,30,39,81,91), +(5,5,41,28,30,40,83,93), +(5,5,42,28,30,40,85,95), +(5,5,43,28,31,41,87,97), +(5,5,44,29,31,41,89,99), +(5,5,45,29,32,42,91,101), +(5,5,46,29,32,43,92,103), +(5,5,47,30,32,43,94,105), +(5,5,48,30,33,44,96,107), +(5,5,49,30,33,44,98,109), +(5,5,50,31,34,45,100,111), +(5,5,51,31,34,46,102,113), +(5,5,52,31,35,46,104,115), +(5,5,53,32,35,47,106,118), +(5,5,54,32,35,48,108,120), +(5,5,55,32,36,48,110,122), +(5,5,56,33,36,49,113,124), +(5,5,57,33,37,50,115,126), +(5,5,58,33,37,50,117,128), +(5,5,59,34,38,51,119,131), +(5,5,60,34,38,52,121,133), +(5,5,61,34,39,52,123,135), +(5,5,62,35,39,53,125,137), +(5,5,63,35,40,54,127,140), +(5,5,64,36,40,55,130,142), +(5,5,65,36,41,55,132,144), +(5,5,66,36,41,56,134,147), +(5,5,67,37,41,57,136,149), +(5,5,68,37,42,58,138,151), +(5,5,69,38,42,58,141,154), +(5,5,70,38,43,59,143,156), +(5,8,1,19,18,21,21,27), +(5,8,2,19,18,21,22,28), +(5,8,3,19,18,22,24,30), +(5,8,4,19,18,22,25,31), +(5,8,5,19,19,22,26,32), +(5,8,6,19,19,22,28,34), +(5,8,7,20,19,23,29,35), +(5,8,8,20,19,23,31,36), +(5,8,9,20,19,23,32,38), +(5,8,10,20,19,24,34,39), +(5,8,11,20,20,24,35,40), +(5,8,12,20,20,24,37,42), +(5,8,13,20,20,25,38,43), +(5,8,14,20,20,25,40,45), +(5,8,15,20,20,25,41,46), +(5,8,16,21,21,26,43,48), +(5,8,17,21,21,26,44,49), +(5,8,18,21,21,26,46,51), +(5,8,19,21,21,27,48,52), +(5,8,20,21,21,27,49,54), +(5,8,21,21,22,27,51,55), +(5,8,22,21,22,28,52,57), +(5,8,23,21,22,28,54,58), +(5,8,24,22,22,29,56,60), +(5,8,25,22,23,29,57,62), +(5,8,26,22,23,29,59,63), +(5,8,27,22,23,30,61,65), +(5,8,28,22,23,30,63,67), +(5,8,29,22,24,31,64,68), +(5,8,30,23,24,31,66,70), +(5,8,31,23,24,31,68,72), +(5,8,32,23,24,32,70,73), +(5,8,33,23,25,32,72,75), +(5,8,34,23,25,33,73,77), +(5,8,35,24,25,33,75,79), +(5,8,36,24,25,34,77,80), +(5,8,37,24,26,34,79,82), +(5,8,38,24,26,35,81,84), +(5,8,39,24,26,35,83,86), +(5,8,40,24,27,35,85,88), +(5,8,41,25,27,36,87,90), +(5,8,42,25,27,36,89,91), +(5,8,43,25,27,37,90,93), +(5,8,44,25,28,37,92,95), +(5,8,45,26,28,38,94,97), +(5,8,46,26,28,38,96,99), +(5,8,47,26,29,39,98,101), +(5,8,48,26,29,39,100,103), +(5,8,49,26,29,40,103,105), +(5,8,50,27,30,40,105,107), +(5,8,51,27,30,41,107,109), +(5,8,52,27,30,42,109,111), +(5,8,53,27,31,42,111,113), +(5,8,54,28,31,43,113,115), +(5,8,55,28,31,43,115,117), +(5,8,56,28,32,44,117,119), +(5,8,57,28,32,44,119,121), +(5,8,58,29,32,45,122,123), +(5,8,59,29,33,45,124,126), +(5,8,60,29,33,46,126,128), +(5,8,61,29,34,47,128,130), +(5,8,62,30,34,47,131,132), +(5,8,63,30,34,48,133,134), +(5,8,64,30,35,48,135,136), +(5,8,65,31,35,49,137,139), +(5,8,66,31,35,50,140,141), +(5,8,67,31,36,50,142,143), +(5,8,68,31,36,51,144,145), +(5,8,69,32,37,51,147,148), +(5,8,70,32,37,52,149,150), +(5,9,1,19,18,22,20,27), +(5,9,2,19,18,23,21,28), +(5,9,3,20,19,23,22,29), +(5,9,4,20,19,24,24,30), +(5,9,5,20,19,24,25,32), +(5,9,6,20,20,25,26,33), +(5,9,7,21,20,25,27,34), +(5,9,8,21,21,26,28,35), +(5,9,9,21,21,26,30,36), +(5,9,10,22,21,27,31,38), +(5,9,11,22,22,28,32,39), +(5,9,12,22,22,28,34,40), +(5,9,13,23,23,29,35,41), +(5,9,14,23,23,30,36,43), +(5,9,15,23,24,30,37,44), +(5,9,16,24,24,31,39,45), +(5,9,17,24,24,31,40,47), +(5,9,18,24,25,32,42,48), +(5,9,19,25,25,33,43,49), +(5,9,20,25,26,33,44,51), +(5,9,21,26,26,34,46,52), +(5,9,22,26,27,35,47,53), +(5,9,23,26,27,36,49,55), +(5,9,24,27,28,36,50,56), +(5,9,25,27,28,37,52,58), +(5,9,26,27,29,38,53,59), +(5,9,27,28,29,38,55,60), +(5,9,28,28,30,39,56,62), +(5,9,29,29,30,40,58,63), +(5,9,30,29,31,41,59,65), +(5,9,31,30,31,41,61,66), +(5,9,32,30,32,42,62,68), +(5,9,33,30,32,43,64,69), +(5,9,34,31,33,44,65,71), +(5,9,35,31,33,45,67,73), +(5,9,36,32,34,45,69,74), +(5,9,37,32,34,46,70,76), +(5,9,38,33,35,47,72,77), +(5,9,39,33,36,48,73,79), +(5,9,40,34,36,49,75,81), +(5,9,41,34,37,49,77,82), +(5,9,42,35,37,50,78,84), +(5,9,43,35,38,51,80,86), +(5,9,44,36,39,52,82,87), +(5,9,45,36,39,53,84,89), +(5,9,46,37,40,54,85,91), +(5,9,47,37,40,55,87,92), +(5,9,48,38,41,55,89,94), +(5,9,49,38,42,56,91,96), +(5,9,50,39,42,57,92,98), +(5,9,51,39,43,58,94,100), +(5,9,52,40,44,59,96,101), +(5,9,53,40,44,60,98,103), +(5,9,54,41,45,61,100,105), +(5,9,55,41,45,62,102,107), +(5,9,56,42,46,63,103,109), +(5,9,57,42,47,64,105,111), +(5,9,58,43,47,65,107,112), +(5,9,59,43,48,66,109,114), +(5,9,60,44,49,67,111,116), +(5,9,61,45,50,68,113,118), +(5,9,62,45,50,69,115,120), +(5,9,63,46,51,70,117,122), +(5,9,64,46,52,71,119,124), +(5,9,65,47,52,72,121,126), +(5,9,66,48,53,73,123,128), +(5,9,67,48,54,74,125,130), +(5,9,68,49,55,75,127,132), +(5,9,69,49,55,76,129,134), +(5,9,70,50,56,77,131,136), +(6,1,1,28,15,24,15,22), +(6,1,2,29,16,25,15,22), +(6,1,3,31,17,26,15,23), +(6,1,4,32,17,27,15,23), +(6,1,5,33,18,29,15,23), +(6,1,6,34,19,30,15,23), +(6,1,7,36,20,31,16,24), +(6,1,8,37,21,32,16,24), +(6,1,9,38,22,34,16,24), +(6,1,10,40,22,35,16,25), +(6,1,11,41,23,36,16,25), +(6,1,12,43,24,37,16,25), +(6,1,13,44,25,39,16,26), +(6,1,14,46,26,40,16,26), +(6,1,15,47,27,41,17,26), +(6,1,16,48,28,43,17,27), +(6,1,17,50,29,44,17,27), +(6,1,18,51,30,45,17,27), +(6,1,19,53,31,47,17,28), +(6,1,20,54,32,48,17,28), +(6,1,21,56,33,50,17,28), +(6,1,22,58,34,51,18,29), +(6,1,23,59,35,52,18,29), +(6,1,24,61,36,54,18,30), +(6,1,25,62,37,55,18,30), +(6,1,26,64,38,57,18,30), +(6,1,27,66,39,58,18,31), +(6,1,28,67,40,60,18,31), +(6,1,29,69,41,61,19,32), +(6,1,30,71,42,63,19,32), +(6,1,31,72,43,64,19,32), +(6,1,32,74,44,66,19,33), +(6,1,33,76,45,67,19,33), +(6,1,34,77,46,69,20,34), +(6,1,35,79,47,71,20,34), +(6,1,36,81,48,72,20,35), +(6,1,37,83,49,74,20,35), +(6,1,38,85,50,76,20,35), +(6,1,39,86,51,77,21,36), +(6,1,40,88,53,79,21,36), +(6,1,41,90,54,81,21,37), +(6,1,42,92,55,82,21,37), +(6,1,43,94,56,84,21,38), +(6,1,44,96,57,86,22,38), +(6,1,45,98,58,87,22,39), +(6,1,46,99,60,89,22,39), +(6,1,47,101,61,91,22,40), +(6,1,48,103,62,93,22,40), +(6,1,49,105,63,94,23,41), +(6,1,50,107,65,96,23,41), +(6,1,51,109,66,98,23,42), +(6,1,52,111,67,100,23,42), +(6,1,53,113,68,102,24,43), +(6,1,54,115,70,104,24,44), +(6,1,55,117,71,105,24,44), +(6,1,56,119,72,107,24,45), +(6,1,57,122,73,109,25,45), +(6,1,58,124,75,111,25,46), +(6,1,59,126,76,113,25,46), +(6,1,60,128,77,115,25,47), +(6,1,61,130,79,117,26,48), +(6,1,62,132,80,119,26,48), +(6,1,63,134,81,121,26,49), +(6,1,64,137,83,123,26,49), +(6,1,65,139,84,125,27,50), +(6,1,66,141,85,127,27,51), +(6,1,67,143,87,129,27,51), +(6,1,68,145,88,131,27,52), +(6,1,69,148,90,133,28,52), +(6,1,70,150,91,135,28,53), +(6,3,1,25,18,23,15,23), +(6,3,2,25,19,24,16,24), +(6,3,3,26,21,25,16,24), +(6,3,4,26,22,26,17,25), +(6,3,5,27,24,27,17,25), +(6,3,6,27,25,28,18,26), +(6,3,7,28,26,28,19,27), +(6,3,8,28,28,29,19,27), +(6,3,9,28,29,30,20,28), +(6,3,10,29,31,31,20,29), +(6,3,11,29,32,32,21,29), +(6,3,12,30,34,33,22,30), +(6,3,13,30,35,34,22,31), +(6,3,14,31,37,35,23,32), +(6,3,15,31,38,36,24,32), +(6,3,16,32,40,37,24,33), +(6,3,17,32,41,39,25,34), +(6,3,18,33,43,40,26,35), +(6,3,19,33,45,41,27,35), +(6,3,20,34,46,42,27,36), +(6,3,21,34,48,43,28,37), +(6,3,22,35,50,44,29,38), +(6,3,23,35,51,45,29,38), +(6,3,24,36,53,46,30,39), +(6,3,25,37,55,47,31,40), +(6,3,26,37,56,48,32,41), +(6,3,27,38,58,50,32,42), +(6,3,28,38,60,51,33,42), +(6,3,29,39,62,52,34,43), +(6,3,30,39,63,53,35,44), +(6,3,31,40,65,54,36,45), +(6,3,32,41,67,56,36,46), +(6,3,33,41,69,57,37,47), +(6,3,34,42,71,58,38,48), +(6,3,35,43,72,59,39,48), +(6,3,36,43,74,61,40,49), +(6,3,37,44,76,62,40,50), +(6,3,38,45,78,63,41,51), +(6,3,39,45,80,64,42,52), +(6,3,40,46,82,66,43,53), +(6,3,41,47,84,67,44,54), +(6,3,42,47,86,68,45,55), +(6,3,43,48,88,70,46,56), +(6,3,44,49,90,71,46,57), +(6,3,45,49,92,72,47,58), +(6,3,46,50,94,74,48,59), +(6,3,47,51,96,75,49,60), +(6,3,48,51,98,77,50,61), +(6,3,49,52,100,78,51,62), +(6,3,50,53,102,79,52,63), +(6,3,51,54,104,81,53,64), +(6,3,52,54,106,82,54,65), +(6,3,53,55,108,84,55,66), +(6,3,54,56,110,85,56,67), +(6,3,55,57,112,87,57,68), +(6,3,56,57,114,88,58,69), +(6,3,57,58,117,90,59,70), +(6,3,58,59,119,91,60,71), +(6,3,59,60,121,93,61,72), +(6,3,60,61,123,94,62,74), +(6,3,61,61,125,96,63,75), +(6,3,62,62,128,97,64,76), +(6,3,63,63,130,99,65,77), +(6,3,64,64,132,100,66,78), +(6,3,65,65,134,102,67,79), +(6,3,66,66,137,104,68,80), +(6,3,67,66,139,105,69,81), +(6,3,68,67,141,107,70,83), +(6,3,69,68,144,108,71,84), +(6,3,70,69,146,110,72,85), +(6,7,1,26,15,23,16,24), +(6,7,2,27,15,24,17,25), +(6,7,3,28,16,25,18,26), +(6,7,4,28,16,26,19,27), +(6,7,5,29,17,27,20,28), +(6,7,6,30,17,28,21,29), +(6,7,7,31,18,29,22,30), +(6,7,8,32,18,30,23,31), +(6,7,9,33,19,31,24,32), +(6,7,10,34,19,32,25,33), +(6,7,11,35,20,33,26,35), +(6,7,12,35,20,34,27,36), +(6,7,13,36,21,35,28,37), +(6,7,14,37,21,36,29,38), +(6,7,15,38,22,37,30,39), +(6,7,16,39,22,39,31,40), +(6,7,17,40,23,40,32,42), +(6,7,18,41,23,41,33,43), +(6,7,19,42,24,42,34,44), +(6,7,20,43,24,43,35,45), +(6,7,21,44,25,44,36,46), +(6,7,22,45,25,45,37,48), +(6,7,23,46,26,47,38,49), +(6,7,24,47,27,48,40,50), +(6,7,25,48,27,49,41,51), +(6,7,26,49,28,50,42,53), +(6,7,27,51,28,52,43,54), +(6,7,28,52,29,53,44,55), +(6,7,29,53,29,54,45,57), +(6,7,30,54,30,55,47,58), +(6,7,31,55,31,57,48,59), +(6,7,32,56,31,58,49,61), +(6,7,33,57,32,59,50,62), +(6,7,34,58,33,61,51,64), +(6,7,35,60,33,62,53,65), +(6,7,36,61,34,63,54,66), +(6,7,37,62,34,65,55,68), +(6,7,38,63,35,66,57,69), +(6,7,39,64,36,67,58,71), +(6,7,40,66,36,69,59,72), +(6,7,41,67,37,70,60,74), +(6,7,42,68,38,72,62,75), +(6,7,43,69,38,73,63,77), +(6,7,44,70,39,74,64,78), +(6,7,45,72,40,76,66,80), +(6,7,46,73,41,77,67,81), +(6,7,47,74,41,79,69,83), +(6,7,48,76,42,80,70,84), +(6,7,49,77,43,82,71,86), +(6,7,50,78,43,83,73,88), +(6,7,51,80,44,85,74,89), +(6,7,52,81,45,86,76,91), +(6,7,53,82,46,88,77,92), +(6,7,54,84,46,90,78,94), +(6,7,55,85,47,91,80,96), +(6,7,56,86,48,93,81,97), +(6,7,57,88,49,94,83,99), +(6,7,58,89,49,96,84,101), +(6,7,59,91,50,97,86,102), +(6,7,60,92,51,99,87,104), +(6,7,61,94,52,101,89,106), +(6,7,62,95,52,102,90,108), +(6,7,63,96,53,104,92,109), +(6,7,64,98,54,106,93,111), +(6,7,65,99,55,107,95,113), +(6,7,66,101,56,109,97,115), +(6,7,67,102,57,111,98,117), +(6,7,68,104,57,113,100,118), +(6,7,69,105,58,114,101,120), +(6,7,70,107,59,116,103,122), +(6,11,1,26,15,22,17,24), +(6,11,2,27,16,23,18,25), +(6,11,3,27,16,23,19,26), +(6,11,4,28,17,24,20,27), +(6,11,5,28,17,25,21,29), +(6,11,6,29,18,25,22,30), +(6,11,7,29,18,26,23,31), +(6,11,8,30,19,27,24,32), +(6,11,9,30,19,27,26,34), +(6,11,10,31,20,28,27,35), +(6,11,11,32,20,29,28,36), +(6,11,12,32,21,29,29,37), +(6,11,13,33,21,30,30,39), +(6,11,14,33,22,31,31,40), +(6,11,15,34,23,32,32,41), +(6,11,16,35,23,32,34,43), +(6,11,17,35,24,33,35,44), +(6,11,18,36,24,34,36,45), +(6,11,19,37,25,35,37,47), +(6,11,20,37,26,35,39,48), +(6,11,21,38,26,36,40,50), +(6,11,22,39,27,37,41,51), +(6,11,23,39,28,38,42,52), +(6,11,24,40,28,39,44,54), +(6,11,25,41,29,39,45,55), +(6,11,26,41,30,40,46,57), +(6,11,27,42,30,41,47,58), +(6,11,28,43,31,42,49,60), +(6,11,29,44,32,43,50,61), +(6,11,30,44,32,44,52,63), +(6,11,31,45,33,44,53,64), +(6,11,32,46,34,45,54,66), +(6,11,33,47,34,46,56,67), +(6,11,34,47,35,47,57,69), +(6,11,35,48,36,48,58,71), +(6,11,36,49,36,49,60,72), +(6,11,37,50,37,50,61,74), +(6,11,38,51,38,51,63,76), +(6,11,39,52,39,52,64,77), +(6,11,40,52,39,53,66,79), +(6,11,41,53,40,54,67,81), +(6,11,42,54,41,55,69,82), +(6,11,43,55,42,56,70,84), +(6,11,44,56,43,57,72,86), +(6,11,45,57,43,57,73,87), +(6,11,46,57,44,58,75,89), +(6,11,47,58,45,60,76,91), +(6,11,48,59,46,61,78,93), +(6,11,49,60,47,62,79,94), +(6,11,50,61,47,63,81,96), +(6,11,51,62,48,64,83,98), +(6,11,52,63,49,65,84,100), +(6,11,53,64,50,66,86,102), +(6,11,54,65,51,67,87,104), +(6,11,55,66,51,68,89,105), +(6,11,56,67,52,69,91,107), +(6,11,57,68,53,70,92,109), +(6,11,58,69,54,71,94,111), +(6,11,59,70,55,72,96,113), +(6,11,60,71,56,73,97,115), +(6,11,61,72,57,74,99,117), +(6,11,62,73,58,76,101,119), +(6,11,63,74,59,77,103,121), +(6,11,64,75,59,78,104,123), +(6,11,65,76,60,79,106,125), +(6,11,66,77,61,80,108,127), +(6,11,67,78,62,81,110,129), +(6,11,68,79,63,83,111,131), +(6,11,69,80,64,84,113,133), +(6,11,70,81,65,85,115,135), +(7,1,1,18,23,21,24,20), +(7,1,2,19,24,22,24,20), +(7,1,3,21,25,23,24,21), +(7,1,4,22,25,25,24,21), +(7,1,5,23,26,26,24,21), +(7,1,6,25,27,27,24,21), +(7,1,7,26,28,28,24,22), +(7,1,8,27,29,29,25,22), +(7,1,9,29,29,31,25,22), +(7,1,10,30,30,32,25,23), +(7,1,11,32,31,33,25,23), +(7,1,12,33,32,34,25,23), +(7,1,13,34,33,36,25,24), +(7,1,14,36,34,37,25,24), +(7,1,15,37,35,38,25,24), +(7,1,16,39,36,40,25,25), +(7,1,17,40,36,41,25,25), +(7,1,18,42,37,43,26,25), +(7,1,19,43,38,44,26,26), +(7,1,20,45,39,45,26,26), +(7,1,21,47,40,47,26,26), +(7,1,22,48,41,48,26,27), +(7,1,23,50,42,50,26,27), +(7,1,24,51,43,51,26,28), +(7,1,25,53,44,52,27,28), +(7,1,26,55,45,54,27,28), +(7,1,27,56,46,55,27,29), +(7,1,28,58,47,57,27,29), +(7,1,29,59,48,58,27,30), +(7,1,30,61,49,60,27,30), +(7,1,31,63,50,62,27,30), +(7,1,32,65,51,63,28,31), +(7,1,33,66,52,65,28,31), +(7,1,34,68,53,66,28,32), +(7,1,35,70,55,68,28,32), +(7,1,36,72,56,69,28,33), +(7,1,37,73,57,71,29,33), +(7,1,38,75,58,73,29,34), +(7,1,39,77,59,74,29,34), +(7,1,40,79,60,76,29,35), +(7,1,41,81,61,78,29,35), +(7,1,42,82,62,79,30,35), +(7,1,43,84,64,81,30,36), +(7,1,44,86,65,83,30,36), +(7,1,45,88,66,85,30,37), +(7,1,46,90,67,86,30,37), +(7,1,47,92,68,88,31,38), +(7,1,48,94,70,90,31,38), +(7,1,49,96,71,92,31,39), +(7,1,50,98,72,93,31,40), +(7,1,51,100,73,95,32,40), +(7,1,52,102,75,97,32,41), +(7,1,53,104,76,99,32,41), +(7,1,54,106,77,101,32,42), +(7,1,55,108,78,103,33,42), +(7,1,56,110,80,104,33,43), +(7,1,57,112,81,106,33,43), +(7,1,58,114,82,108,33,44), +(7,1,59,116,84,110,34,44), +(7,1,60,118,85,112,34,45), +(7,1,61,120,86,114,34,46), +(7,1,62,122,88,116,35,46), +(7,1,63,125,89,118,35,47), +(7,1,64,127,91,120,35,47), +(7,1,65,129,92,122,35,48), +(7,1,66,131,93,124,36,49), +(7,1,67,133,95,126,36,49), +(7,1,68,136,96,128,36,50), +(7,1,69,138,98,130,37,50), +(7,1,70,140,99,132,37,51), +(7,4,1,16,26,20,24,20), +(7,4,2,17,27,21,24,20), +(7,4,3,18,29,21,24,21), +(7,4,4,18,30,22,24,21), +(7,4,5,19,32,23,25,21), +(7,4,6,20,33,24,25,22), +(7,4,7,21,35,24,25,22), +(7,4,8,22,36,25,25,23), +(7,4,9,22,38,26,25,23), +(7,4,10,23,39,26,25,23), +(7,4,11,24,41,27,25,24), +(7,4,12,25,42,28,26,24), +(7,4,13,26,44,29,26,25), +(7,4,14,27,46,30,26,25), +(7,4,15,28,47,30,26,25), +(7,4,16,28,49,31,26,26), +(7,4,17,29,50,32,27,26), +(7,4,18,30,52,33,27,27), +(7,4,19,31,54,34,27,27), +(7,4,20,32,56,35,27,28), +(7,4,21,33,57,35,27,28), +(7,4,22,34,59,36,28,29), +(7,4,23,35,61,37,28,29), +(7,4,24,36,62,38,28,30), +(7,4,25,37,64,39,28,30), +(7,4,26,38,66,40,29,31), +(7,4,27,39,68,41,29,31), +(7,4,28,40,70,42,29,32), +(7,4,29,41,72,43,29,32), +(7,4,30,42,73,43,29,33), +(7,4,31,43,75,44,30,33), +(7,4,32,44,77,45,30,34), +(7,4,33,45,79,46,30,34), +(7,4,34,46,81,47,31,35), +(7,4,35,47,83,48,31,35), +(7,4,36,48,85,49,31,36), +(7,4,37,49,87,50,31,36), +(7,4,38,50,89,51,32,37), +(7,4,39,51,91,52,32,38), +(7,4,40,53,93,53,32,38), +(7,4,41,54,95,54,33,39), +(7,4,42,55,97,55,33,39), +(7,4,43,56,99,56,33,40), +(7,4,44,57,101,57,33,40), +(7,4,45,58,103,59,34,41), +(7,4,46,59,105,60,34,42), +(7,4,47,61,107,61,34,42), +(7,4,48,62,110,62,35,43), +(7,4,49,63,112,63,35,44), +(7,4,50,64,114,64,35,44), +(7,4,51,65,116,65,36,45), +(7,4,52,67,118,66,36,45), +(7,4,53,68,121,67,36,46), +(7,4,54,69,123,69,37,47), +(7,4,55,70,125,70,37,47), +(7,4,56,72,127,71,37,48), +(7,4,57,73,130,72,38,49), +(7,4,58,74,132,73,38,49), +(7,4,59,75,134,74,39,50), +(7,4,60,77,137,76,39,51), +(7,4,61,78,139,77,39,51), +(7,4,62,79,141,78,40,52), +(7,4,63,81,144,79,40,53), +(7,4,64,82,146,80,41,54), +(7,4,65,83,149,82,41,54), +(7,4,66,85,151,83,41,55), +(7,4,67,86,154,84,42,56), +(7,4,68,87,156,85,42,57), +(7,4,69,89,158,87,43,57), +(7,4,70,90,161,88,43,58), +(7,8,1,15,23,19,27,22), +(7,8,2,15,23,19,28,23), +(7,8,3,15,23,20,30,25), +(7,8,4,15,23,20,31,26), +(7,8,5,15,24,20,32,27), +(7,8,6,15,24,20,34,29), +(7,8,7,16,24,21,35,30), +(7,8,8,16,24,21,37,31), +(7,8,9,16,24,21,38,33), +(7,8,10,16,24,22,40,34), +(7,8,11,16,25,22,41,36), +(7,8,12,16,25,22,42,37), +(7,8,13,16,25,23,44,38), +(7,8,14,16,25,23,45,40), +(7,8,15,17,25,23,47,41), +(7,8,16,17,25,24,49,43), +(7,8,17,17,26,24,50,44), +(7,8,18,17,26,24,52,46), +(7,8,19,17,26,25,53,47), +(7,8,20,17,26,25,55,49), +(7,8,21,17,26,26,57,51), +(7,8,22,18,27,26,58,52), +(7,8,23,18,27,26,60,54), +(7,8,24,18,27,27,61,55), +(7,8,25,18,27,27,63,57), +(7,8,26,18,28,27,65,59), +(7,8,27,18,28,28,67,60), +(7,8,28,18,28,28,68,62), +(7,8,29,19,28,29,70,64), +(7,8,30,19,29,29,72,65), +(7,8,31,19,29,30,74,67), +(7,8,32,19,29,30,75,69), +(7,8,33,19,29,30,77,70), +(7,8,34,20,30,31,79,72), +(7,8,35,20,30,31,81,74), +(7,8,36,20,30,32,83,76), +(7,8,37,20,30,32,85,78), +(7,8,38,20,31,33,86,79), +(7,8,39,21,31,33,88,81), +(7,8,40,21,31,34,90,83), +(7,8,41,21,32,34,92,85), +(7,8,42,21,32,35,94,87), +(7,8,43,21,32,35,96,89), +(7,8,44,22,32,36,98,91), +(7,8,45,22,33,36,100,92), +(7,8,46,22,33,37,102,94), +(7,8,47,22,33,37,104,96), +(7,8,48,22,34,38,106,98), +(7,8,49,23,34,38,108,100), +(7,8,50,23,34,39,110,102), +(7,8,51,23,35,39,112,104), +(7,8,52,23,35,40,114,106), +(7,8,53,24,35,40,117,108), +(7,8,54,24,36,41,119,110), +(7,8,55,24,36,41,121,112), +(7,8,56,24,37,42,123,114), +(7,8,57,25,37,42,125,117), +(7,8,58,25,37,43,127,119), +(7,8,59,25,38,43,130,121), +(7,8,60,25,38,44,132,123), +(7,8,61,26,38,45,134,125), +(7,8,62,26,39,45,136,127), +(7,8,63,26,39,46,139,129), +(7,8,64,26,40,46,141,132), +(7,8,65,27,40,47,143,134), +(7,8,66,27,40,48,146,136), +(7,8,67,27,41,48,148,138), +(7,8,68,27,41,49,150,140), +(7,8,69,28,42,49,153,143), +(7,8,70,28,42,50,155,145), +(7,9,1,15,23,20,26,22), +(7,9,2,15,23,21,27,23), +(7,9,3,16,24,21,28,24), +(7,9,4,16,24,22,29,25), +(7,9,5,16,24,22,31,27), +(7,9,6,17,25,23,32,28), +(7,9,7,17,25,23,33,29), +(7,9,8,17,26,24,34,30), +(7,9,9,17,26,25,36,31), +(7,9,10,18,26,25,37,33), +(7,9,11,18,27,26,38,34), +(7,9,12,18,27,26,39,35), +(7,9,13,19,28,27,41,36), +(7,9,14,19,28,28,42,38), +(7,9,15,20,28,28,43,39), +(7,9,16,20,29,29,45,40), +(7,9,17,20,29,30,46,42), +(7,9,18,21,30,30,47,43), +(7,9,19,21,30,31,49,44), +(7,9,20,21,31,32,50,46), +(7,9,21,22,31,32,51,47), +(7,9,22,22,31,33,53,49), +(7,9,23,23,32,34,54,50), +(7,9,24,23,32,34,56,51), +(7,9,25,23,33,35,57,53), +(7,9,26,24,33,36,59,54), +(7,9,27,24,34,37,60,56), +(7,9,28,25,34,37,62,57), +(7,9,29,25,35,38,63,59), +(7,9,30,25,35,39,65,60), +(7,9,31,26,36,40,66,62), +(7,9,32,26,36,40,68,63), +(7,9,33,27,37,41,69,65), +(7,9,34,27,38,42,71,66), +(7,9,35,28,38,43,73,68), +(7,9,36,28,39,43,74,69), +(7,9,37,28,39,44,76,71), +(7,9,38,29,40,45,77,73), +(7,9,39,29,40,46,79,74), +(7,9,40,30,41,47,81,76), +(7,9,41,30,41,48,82,78), +(7,9,42,31,42,48,84,79), +(7,9,43,31,43,49,86,81), +(7,9,44,32,43,50,88,83), +(7,9,45,32,44,51,89,84), +(7,9,46,33,44,52,91,86), +(7,9,47,33,45,53,93,88), +(7,9,48,34,46,54,95,89), +(7,9,49,34,46,54,96,91), +(7,9,50,35,47,55,98,93), +(7,9,51,35,48,56,100,95), +(7,9,52,36,48,57,102,97), +(7,9,53,36,49,58,104,98), +(7,9,54,37,50,59,105,100), +(7,9,55,37,50,60,107,102), +(7,9,56,38,51,61,109,104), +(7,9,57,38,52,62,111,106), +(7,9,58,39,52,63,113,108), +(7,9,59,40,53,64,115,109), +(7,9,60,40,54,65,117,111), +(7,9,61,41,54,66,119,113), +(7,9,62,41,55,67,121,115), +(7,9,63,42,56,68,123,117), +(7,9,64,42,57,69,125,119), +(7,9,65,43,57,70,127,121), +(7,9,66,44,58,71,129,123), +(7,9,67,44,59,72,131,125), +(7,9,68,45,59,73,133,127), +(7,9,69,45,60,74,135,129), +(7,9,70,46,61,75,137,131), +(8,1,1,24,22,23,16,21), +(8,1,2,25,23,24,16,21), +(8,1,3,27,24,25,16,22), +(8,1,4,28,24,26,16,22), +(8,1,5,29,25,28,16,22), +(8,1,6,31,26,29,16,22), +(8,1,7,32,27,30,17,23), +(8,1,8,33,28,31,17,23), +(8,1,9,35,28,33,17,23), +(8,1,10,36,29,34,17,24), +(8,1,11,37,30,35,17,24), +(8,1,12,39,31,36,17,24), +(8,1,13,40,32,38,17,25), +(8,1,14,42,33,39,17,25), +(8,1,15,43,34,40,18,25), +(8,1,16,45,35,42,18,26), +(8,1,17,46,35,43,18,26), +(8,1,18,48,36,44,18,26), +(8,1,19,49,37,46,18,27), +(8,1,20,51,38,47,18,27), +(8,1,21,52,39,49,18,27), +(8,1,22,54,40,50,18,28), +(8,1,23,55,41,51,19,28), +(8,1,24,57,42,53,19,29), +(8,1,25,59,43,54,19,29), +(8,1,26,60,44,56,19,29), +(8,1,27,62,45,57,19,30), +(8,1,28,63,46,59,19,30), +(8,1,29,65,47,60,20,31), +(8,1,30,67,48,62,20,31), +(8,1,31,69,49,63,20,31), +(8,1,32,70,50,65,20,32), +(8,1,33,72,51,67,20,32), +(8,1,34,74,53,68,20,33), +(8,1,35,75,54,70,21,33), +(8,1,36,77,55,71,21,34), +(8,1,37,79,56,73,21,34), +(8,1,38,81,57,75,21,35), +(8,1,39,83,58,76,21,35), +(8,1,40,84,59,78,22,35), +(8,1,41,86,60,80,22,36), +(8,1,42,88,62,81,22,36), +(8,1,43,90,63,83,22,37), +(8,1,44,92,64,85,22,37), +(8,1,45,94,65,86,23,38), +(8,1,46,96,66,88,23,38), +(8,1,47,98,67,90,23,39), +(8,1,48,100,69,92,23,39), +(8,1,49,102,70,93,24,40), +(8,1,50,103,71,95,24,40), +(8,1,51,105,72,97,24,41), +(8,1,52,107,74,99,24,42), +(8,1,53,109,75,101,25,42), +(8,1,54,112,76,103,25,43), +(8,1,55,114,78,104,25,43), +(8,1,56,116,79,106,25,44), +(8,1,57,118,80,108,25,44), +(8,1,58,120,81,110,26,45), +(8,1,59,122,83,112,26,45), +(8,1,60,124,84,114,26,46), +(8,1,61,126,85,116,27,47), +(8,1,62,128,87,118,27,47), +(8,1,63,130,88,120,27,48), +(8,1,64,133,90,122,27,48), +(8,1,65,135,91,124,28,49), +(8,1,66,137,92,126,28,50), +(8,1,67,139,94,128,28,50), +(8,1,68,141,95,130,28,51), +(8,1,69,144,97,132,29,51), +(8,1,70,146,98,134,29,52), +(8,3,1,21,25,22,16,22), +(8,3,2,21,26,23,17,23), +(8,3,3,22,28,24,17,23), +(8,3,4,22,29,25,18,24), +(8,3,5,23,30,26,18,25), +(8,3,6,23,32,27,19,25), +(8,3,7,24,33,28,20,26), +(8,3,8,24,35,28,20,26), +(8,3,9,25,36,29,21,27), +(8,3,10,25,38,30,21,28), +(8,3,11,25,39,31,22,29), +(8,3,12,26,41,32,23,29), +(8,3,13,26,42,33,23,30), +(8,3,14,27,44,34,24,31), +(8,3,15,27,45,35,25,31), +(8,3,16,28,47,36,25,32), +(8,3,17,28,48,38,26,33), +(8,3,18,29,50,39,27,34), +(8,3,19,29,51,40,28,34), +(8,3,20,30,53,41,28,35), +(8,3,21,31,55,42,29,36), +(8,3,22,31,56,43,30,37), +(8,3,23,32,58,44,30,37), +(8,3,24,32,60,45,31,38), +(8,3,25,33,61,46,32,39), +(8,3,26,33,63,48,33,40), +(8,3,27,34,65,49,33,41), +(8,3,28,35,66,50,34,41), +(8,3,29,35,68,51,35,42), +(8,3,30,36,70,52,36,43), +(8,3,31,36,72,53,37,44), +(8,3,32,37,73,55,37,45), +(8,3,33,38,75,56,38,46), +(8,3,34,38,77,57,39,47), +(8,3,35,39,79,58,40,48), +(8,3,36,39,81,60,41,48), +(8,3,37,40,83,61,41,49), +(8,3,38,41,85,62,42,50), +(8,3,39,41,86,63,43,51), +(8,3,40,42,88,65,44,52), +(8,3,41,43,90,66,45,53), +(8,3,42,43,92,67,46,54), +(8,3,43,44,94,69,47,55), +(8,3,44,45,96,70,47,56), +(8,3,45,45,98,71,48,57), +(8,3,46,46,100,73,49,58), +(8,3,47,47,102,74,50,59), +(8,3,48,48,104,76,51,60), +(8,3,49,48,106,77,52,61), +(8,3,50,49,108,78,53,62), +(8,3,51,50,110,80,54,63), +(8,3,52,51,113,81,55,64), +(8,3,53,51,115,83,56,65), +(8,3,54,52,117,84,57,66), +(8,3,55,53,119,86,58,67), +(8,3,56,54,121,87,59,68), +(8,3,57,54,123,89,60,69), +(8,3,58,55,126,90,61,70), +(8,3,59,56,128,92,62,71), +(8,3,60,57,130,93,63,73), +(8,3,61,58,132,95,64,74), +(8,3,62,58,134,96,65,75), +(8,3,63,59,137,98,66,76), +(8,3,64,60,139,99,67,77), +(8,3,65,61,141,101,68,78), +(8,3,66,62,144,103,69,79), +(8,3,67,62,146,104,70,80), +(8,3,68,63,148,106,71,82), +(8,3,69,64,151,107,72,83), +(8,3,70,65,153,109,73,84), +(8,4,1,22,25,22,16,21), +(8,4,2,23,26,23,16,21), +(8,4,3,24,28,23,16,22), +(8,4,4,24,29,24,16,22), +(8,4,5,25,31,25,17,22), +(8,4,6,26,32,25,17,23), +(8,4,7,27,34,26,17,23), +(8,4,8,27,35,27,17,24), +(8,4,9,28,37,28,17,24), +(8,4,10,29,38,28,18,24), +(8,4,11,30,40,29,18,25), +(8,4,12,31,41,30,18,25), +(8,4,13,32,43,31,18,26), +(8,4,14,32,45,32,18,26), +(8,4,15,33,46,32,19,26), +(8,4,16,34,48,33,19,27), +(8,4,17,35,50,34,19,27), +(8,4,18,36,51,35,19,28), +(8,4,19,37,53,36,19,28), +(8,4,20,38,55,36,20,29), +(8,4,21,39,56,37,20,29), +(8,4,22,40,58,38,20,30), +(8,4,23,41,60,39,20,30), +(8,4,24,42,62,40,20,31), +(8,4,25,43,63,41,21,31), +(8,4,26,44,65,42,21,32), +(8,4,27,45,67,43,21,32), +(8,4,28,46,69,44,21,33), +(8,4,29,47,71,44,22,33), +(8,4,30,48,72,45,22,34), +(8,4,31,49,74,46,22,34), +(8,4,32,50,76,47,22,35), +(8,4,33,51,78,48,23,35), +(8,4,34,52,80,49,23,36), +(8,4,35,53,82,50,23,36), +(8,4,36,54,84,51,24,37), +(8,4,37,55,86,52,24,37), +(8,4,38,56,88,53,24,38), +(8,4,39,57,90,54,24,38), +(8,4,40,58,92,55,25,39), +(8,4,41,59,94,56,25,40), +(8,4,42,60,96,57,25,40), +(8,4,43,62,98,58,26,41), +(8,4,44,63,100,59,26,41), +(8,4,45,64,102,60,26,42), +(8,4,46,65,104,61,27,43), +(8,4,47,66,107,63,27,43), +(8,4,48,67,109,64,27,44), +(8,4,49,69,111,65,27,44), +(8,4,50,70,113,66,28,45), +(8,4,51,71,115,67,28,46), +(8,4,52,72,117,68,28,46), +(8,4,53,74,120,69,29,47), +(8,4,54,75,122,70,29,48), +(8,4,55,76,124,72,29,48), +(8,4,56,77,126,73,30,49), +(8,4,57,79,129,74,30,50), +(8,4,58,80,131,75,30,50), +(8,4,59,81,133,76,31,51), +(8,4,60,82,136,77,31,52), +(8,4,61,84,138,79,32,52), +(8,4,62,85,140,80,32,53), +(8,4,63,86,143,81,32,54), +(8,4,64,88,145,82,33,55), +(8,4,65,89,148,84,33,55), +(8,4,66,90,150,85,33,56), +(8,4,67,92,153,86,34,57), +(8,4,68,93,155,87,34,58), +(8,4,69,95,157,89,35,58), +(8,4,70,96,160,90,35,59), +(8,5,1,21,22,21,18,24), +(8,5,2,21,22,21,19,25), +(8,5,3,21,22,22,21,27), +(8,5,4,21,23,22,22,28), +(8,5,5,22,23,22,23,29), +(8,5,6,22,23,23,25,31), +(8,5,7,22,23,23,26,32), +(8,5,8,22,24,24,27,34), +(8,5,9,22,24,24,29,35), +(8,5,10,22,24,24,30,37), +(8,5,11,23,24,25,32,38), +(8,5,12,23,24,25,33,40), +(8,5,13,23,25,26,35,41), +(8,5,14,23,25,26,36,43), +(8,5,15,23,25,26,38,44), +(8,5,16,24,26,27,39,46), +(8,5,17,24,26,27,41,47), +(8,5,18,24,26,28,42,49), +(8,5,19,24,26,28,44,50), +(8,5,20,24,27,29,45,52), +(8,5,21,25,27,29,47,54), +(8,5,22,25,27,30,48,55), +(8,5,23,25,28,30,50,57), +(8,5,24,25,28,31,52,59), +(8,5,25,25,28,31,53,60), +(8,5,26,26,28,32,55,62), +(8,5,27,26,29,32,56,64), +(8,5,28,26,29,33,58,65), +(8,5,29,26,29,33,60,67), +(8,5,30,27,30,34,62,69), +(8,5,31,27,30,34,63,71), +(8,5,32,27,30,35,65,73), +(8,5,33,27,31,35,67,74), +(8,5,34,28,31,36,68,76), +(8,5,35,28,32,36,70,78), +(8,5,36,28,32,37,72,80), +(8,5,37,29,32,37,74,82), +(8,5,38,29,33,38,76,84), +(8,5,39,29,33,38,77,86), +(8,5,40,29,33,39,79,87), +(8,5,41,30,34,40,81,89), +(8,5,42,30,34,40,83,91), +(8,5,43,30,35,41,85,93), +(8,5,44,31,35,41,87,95), +(8,5,45,31,35,42,89,97), +(8,5,46,31,36,43,91,99), +(8,5,47,32,36,43,93,101), +(8,5,48,32,37,44,94,103), +(8,5,49,32,37,44,96,105), +(8,5,50,33,37,45,98,107), +(8,5,51,33,38,46,100,110), +(8,5,52,33,38,46,102,112), +(8,5,53,34,39,47,104,114), +(8,5,54,34,39,48,106,116), +(8,5,55,34,40,48,109,118), +(8,5,56,35,40,49,111,120), +(8,5,57,35,41,50,113,122), +(8,5,58,35,41,50,115,125), +(8,5,59,36,42,51,117,127), +(8,5,60,36,42,52,119,129), +(8,5,61,36,42,52,121,131), +(8,5,62,37,43,53,123,133), +(8,5,63,37,43,54,125,136), +(8,5,64,38,44,55,128,138), +(8,5,65,38,44,55,130,140), +(8,5,66,38,45,56,132,143), +(8,5,67,39,45,57,134,145), +(8,5,68,39,46,58,136,147), +(8,5,69,40,46,58,139,150), +(8,5,70,40,47,59,141,152), +(8,7,1,22,22,22,17,23), +(8,7,2,23,22,23,18,24), +(8,7,3,24,23,24,19,25), +(8,7,4,25,23,25,20,26), +(8,7,5,25,24,26,21,27), +(8,7,6,26,24,27,22,28), +(8,7,7,27,25,28,23,29), +(8,7,8,28,25,29,24,30), +(8,7,9,29,25,30,25,31), +(8,7,10,30,26,31,26,33), +(8,7,11,31,26,32,27,34), +(8,7,12,32,27,33,28,35), +(8,7,13,33,27,34,29,36), +(8,7,14,34,28,35,30,37), +(8,7,15,34,28,36,31,38), +(8,7,16,35,29,38,32,39), +(8,7,17,36,29,39,33,41), +(8,7,18,37,30,40,34,42), +(8,7,19,38,30,41,35,43), +(8,7,20,39,31,42,36,44), +(8,7,21,40,32,43,37,45), +(8,7,22,41,32,45,38,47), +(8,7,23,43,33,46,39,48), +(8,7,24,44,33,47,40,49), +(8,7,25,45,34,48,42,51), +(8,7,26,46,34,49,43,52), +(8,7,27,47,35,51,44,53), +(8,7,28,48,35,52,45,54), +(8,7,29,49,36,53,46,56), +(8,7,30,50,37,54,48,57), +(8,7,31,51,37,56,49,59), +(8,7,32,52,38,57,50,60), +(8,7,33,53,38,58,51,61), +(8,7,34,55,39,60,52,63), +(8,7,35,56,40,61,54,64), +(8,7,36,57,40,62,55,66), +(8,7,37,58,41,64,56,67), +(8,7,38,59,42,65,57,68), +(8,7,39,61,42,66,59,70), +(8,7,40,62,43,68,60,71), +(8,7,41,63,44,69,61,73), +(8,7,42,64,44,71,63,74), +(8,7,43,65,45,72,64,76), +(8,7,44,67,46,74,65,77), +(8,7,45,68,46,75,67,79), +(8,7,46,69,47,76,68,80), +(8,7,47,71,48,78,69,82), +(8,7,48,72,49,79,71,83), +(8,7,49,73,49,81,72,85), +(8,7,50,74,50,82,74,87), +(8,7,51,76,51,84,75,88), +(8,7,52,77,51,85,77,90), +(8,7,53,78,52,87,78,92), +(8,7,54,80,53,89,79,93), +(8,7,55,81,54,90,81,95), +(8,7,56,83,55,92,82,96), +(8,7,57,84,55,93,84,98), +(8,7,58,85,56,95,85,100), +(8,7,59,87,57,97,87,102), +(8,7,60,88,58,98,88,103), +(8,7,61,90,58,100,90,105), +(8,7,62,91,59,101,91,107), +(8,7,63,93,60,103,93,108), +(8,7,64,94,61,105,94,110), +(8,7,65,95,62,106,96,112), +(8,7,66,97,63,108,98,114), +(8,7,67,98,63,110,99,116), +(8,7,68,100,64,112,101,117), +(8,7,69,101,65,113,102,119), +(8,7,70,103,66,115,104,121), +(8,8,1,21,22,21,19,23), +(8,8,2,21,22,21,20,24), +(8,8,3,21,22,22,22,26), +(8,8,4,21,22,22,23,27), +(8,8,5,21,23,22,25,28), +(8,8,6,21,23,22,26,30), +(8,8,7,21,23,23,27,31), +(8,8,8,22,23,23,29,32), +(8,8,9,22,23,23,30,34), +(8,8,10,22,23,24,32,35), +(8,8,11,22,24,24,33,37), +(8,8,12,22,24,24,35,38), +(8,8,13,22,24,25,36,39), +(8,8,14,22,24,25,38,41), +(8,8,15,22,24,25,39,42), +(8,8,16,22,24,26,41,44), +(8,8,17,23,25,26,42,45), +(8,8,18,23,25,26,44,47), +(8,8,19,23,25,27,46,48), +(8,8,20,23,25,27,47,50), +(8,8,21,23,25,27,49,51), +(8,8,22,23,26,28,51,53), +(8,8,23,23,26,28,52,55), +(8,8,24,24,26,29,54,56), +(8,8,25,24,26,29,56,58), +(8,8,26,24,27,29,57,60), +(8,8,27,24,27,30,59,61), +(8,8,28,24,27,30,61,63), +(8,8,29,24,27,31,63,65), +(8,8,30,24,28,31,64,66), +(8,8,31,25,28,31,66,68), +(8,8,32,25,28,32,68,70), +(8,8,33,25,28,32,70,71), +(8,8,34,25,29,33,71,73), +(8,8,35,25,29,33,73,75), +(8,8,36,26,29,34,75,77), +(8,8,37,26,29,34,77,79), +(8,8,38,26,30,35,79,80), +(8,8,39,26,30,35,81,82), +(8,8,40,26,30,35,83,84), +(8,8,41,27,31,36,85,86), +(8,8,42,27,31,36,87,88), +(8,8,43,27,31,37,89,90), +(8,8,44,27,32,37,91,91), +(8,8,45,27,32,38,93,93), +(8,8,46,28,32,38,95,95), +(8,8,47,28,32,39,97,97), +(8,8,48,28,33,39,99,99), +(8,8,49,28,33,40,101,101), +(8,8,50,29,33,40,103,103), +(8,8,51,29,34,41,105,105), +(8,8,52,29,34,42,107,107), +(8,8,53,29,35,42,109,109), +(8,8,54,30,35,43,111,111), +(8,8,55,30,35,43,113,113), +(8,8,56,30,36,44,115,115), +(8,8,57,30,36,44,118,118), +(8,8,58,31,36,45,120,120), +(8,8,59,31,37,45,122,122), +(8,8,60,31,37,46,124,124), +(8,8,61,31,37,47,126,126), +(8,8,62,32,38,47,129,128), +(8,8,63,32,38,48,131,130), +(8,8,64,32,39,48,133,133), +(8,8,65,33,39,49,135,135), +(8,8,66,33,39,50,138,137), +(8,8,67,33,40,50,140,139), +(8,8,68,33,40,51,142,141), +(8,8,69,34,41,51,145,144), +(8,8,70,34,41,52,147,146), +(10,2,1,19,22,21,24,20), +(10,2,2,20,23,22,25,21), +(10,2,3,21,23,23,25,21), +(10,2,4,22,24,24,26,22), +(10,2,5,23,24,25,27,23), +(10,2,6,25,25,26,27,24), +(10,2,7,26,25,27,28,24), +(10,2,8,27,26,28,29,25), +(10,2,9,28,27,29,29,26), +(10,2,10,29,27,31,30,26), +(10,2,11,30,28,32,31,27), +(10,2,12,32,29,33,31,28), +(10,2,13,33,29,34,32,29), +(10,2,14,34,30,35,33,30), +(10,2,15,35,31,36,33,30), +(10,2,16,37,31,37,34,31), +(10,2,17,38,32,39,35,32), +(10,2,18,39,33,40,36,33), +(10,2,19,40,33,41,36,34), +(10,2,20,42,34,42,37,35), +(10,2,21,43,35,44,38,35), +(10,2,22,44,35,45,39,36), +(10,2,23,46,36,46,40,37), +(10,2,24,47,37,47,40,38), +(10,2,25,49,38,49,41,39), +(10,2,26,50,38,50,42,40), +(10,2,27,51,39,51,43,41), +(10,2,28,53,40,53,44,42), +(10,2,29,54,41,54,45,43), +(10,2,30,56,41,55,45,43), +(10,2,31,57,42,57,46,44), +(10,2,32,58,43,58,47,45), +(10,2,33,60,44,59,48,46), +(10,2,34,61,45,61,49,47), +(10,2,35,63,45,62,50,48), +(10,2,36,64,46,64,51,49), +(10,2,37,66,47,65,52,50), +(10,2,38,67,48,67,53,51), +(10,2,39,69,49,68,54,52), +(10,2,40,71,50,69,55,53), +(10,2,41,72,50,71,55,54), +(10,2,42,74,51,72,56,55), +(10,2,43,75,52,74,57,56), +(10,2,44,77,53,75,58,57), +(10,2,45,79,54,77,59,59), +(10,2,46,80,55,78,60,60), +(10,2,47,82,56,80,61,61), +(10,2,48,83,57,82,62,62), +(10,2,49,85,58,83,63,63), +(10,2,50,87,59,85,64,64), +(10,2,51,89,60,86,66,65), +(10,2,52,90,61,88,67,66), +(10,2,53,92,61,90,68,67), +(10,2,54,94,62,91,69,69), +(10,2,55,95,63,93,70,70), +(10,2,56,97,64,95,71,71), +(10,2,57,99,65,96,72,72), +(10,2,58,101,66,98,73,73), +(10,2,59,102,67,100,74,74), +(10,2,60,104,68,101,75,76), +(10,2,61,106,69,103,76,77), +(10,2,62,108,70,105,78,78), +(10,2,63,110,72,106,79,79), +(10,2,64,112,73,108,80,80), +(10,2,65,113,74,110,81,82), +(10,2,66,115,75,112,82,83), +(10,2,67,117,76,114,83,84), +(10,2,68,119,77,115,85,85), +(10,2,69,121,78,117,86,87), +(10,2,70,123,79,119,87,88), +(10,3,1,17,25,20,24,20), +(10,3,2,17,26,21,25,21), +(10,3,3,18,28,22,25,21), +(10,3,4,18,29,23,26,22), +(10,3,5,19,30,24,26,23), +(10,3,6,19,32,25,27,23), +(10,3,7,20,33,26,27,24), +(10,3,8,20,35,27,28,25), +(10,3,9,21,36,27,29,25), +(10,3,10,21,38,28,29,26), +(10,3,11,22,39,29,30,27), +(10,3,12,22,41,30,31,27), +(10,3,13,23,42,31,31,28), +(10,3,14,23,44,32,32,29), +(10,3,15,24,45,34,32,29), +(10,3,16,24,47,35,33,30), +(10,3,17,25,48,36,34,31), +(10,3,18,25,50,37,34,32), +(10,3,19,26,51,38,35,32), +(10,3,20,26,53,39,36,33), +(10,3,21,27,55,40,37,34), +(10,3,22,27,56,41,37,35), +(10,3,23,28,58,42,38,36), +(10,3,24,28,60,43,39,36), +(10,3,25,29,61,44,39,37), +(10,3,26,30,63,46,40,38), +(10,3,27,30,65,47,41,39), +(10,3,28,31,66,48,42,40), +(10,3,29,31,68,49,42,40), +(10,3,30,32,70,50,43,41), +(10,3,31,33,72,52,44,42), +(10,3,32,33,73,53,45,43), +(10,3,33,34,75,54,46,44), +(10,3,34,34,77,55,46,45), +(10,3,35,35,79,57,47,46), +(10,3,36,36,81,58,48,47), +(10,3,37,36,83,59,49,47), +(10,3,38,37,85,60,50,48), +(10,3,39,38,86,62,51,49), +(10,3,40,38,88,63,51,50), +(10,3,41,39,90,64,52,51), +(10,3,42,40,92,66,53,52), +(10,3,43,40,94,67,54,53), +(10,3,44,41,96,68,55,54), +(10,3,45,42,98,70,56,55), +(10,3,46,42,100,71,57,56), +(10,3,47,43,102,72,58,57), +(10,3,48,44,104,74,59,58), +(10,3,49,45,106,75,60,59), +(10,3,50,45,108,77,61,60), +(10,3,51,46,110,78,61,61), +(10,3,52,47,113,79,62,62), +(10,3,53,47,115,81,63,63), +(10,3,54,48,117,82,64,64), +(10,3,55,49,119,84,65,65), +(10,3,56,50,121,85,66,66), +(10,3,57,50,123,87,67,67), +(10,3,58,51,126,88,68,68), +(10,3,59,52,128,90,69,70), +(10,3,60,53,130,91,70,71), +(10,3,61,54,132,93,71,72), +(10,3,62,54,134,94,72,73), +(10,3,63,55,137,96,73,74), +(10,3,64,56,139,97,75,75), +(10,3,65,57,141,99,76,76), +(10,3,66,58,144,101,77,77), +(10,3,67,58,146,102,78,78), +(10,3,68,59,148,104,79,80), +(10,3,69,60,151,105,80,81), +(10,3,70,61,153,107,81,82), +(10,4,1,18,25,20,24,19), +(10,4,2,19,26,21,24,19), +(10,4,3,20,28,21,24,20), +(10,4,4,20,29,22,24,20), +(10,4,5,21,31,23,25,20), +(10,4,6,22,32,24,25,21), +(10,4,7,23,34,24,25,21), +(10,4,8,24,35,25,25,22), +(10,4,9,24,37,26,25,22), +(10,4,10,25,38,26,25,22), +(10,4,11,26,40,27,25,23), +(10,4,12,27,41,28,26,23), +(10,4,13,28,43,29,26,24), +(10,4,14,29,45,30,26,24), +(10,4,15,29,46,30,26,25), +(10,4,16,30,48,31,26,25), +(10,4,17,31,50,32,27,25), +(10,4,18,32,51,33,27,26), +(10,4,19,33,53,34,27,26), +(10,4,20,34,55,35,27,27), +(10,4,21,35,56,35,27,27), +(10,4,22,36,58,36,28,28), +(10,4,23,37,60,37,28,28), +(10,4,24,38,62,38,28,29), +(10,4,25,39,63,39,28,29), +(10,4,26,40,65,40,29,30), +(10,4,27,41,67,41,29,30), +(10,4,28,42,69,42,29,31), +(10,4,29,43,71,43,29,31), +(10,4,30,44,72,43,29,32), +(10,4,31,45,74,44,30,32), +(10,4,32,46,76,45,30,33), +(10,4,33,47,78,46,30,33), +(10,4,34,48,80,47,31,34), +(10,4,35,49,82,48,31,34), +(10,4,36,50,84,49,31,35), +(10,4,37,51,86,50,31,35), +(10,4,38,52,88,51,32,36), +(10,4,39,53,90,52,32,37), +(10,4,40,54,92,53,32,37), +(10,4,41,56,94,54,33,38), +(10,4,42,57,96,55,33,38), +(10,4,43,58,98,56,33,39), +(10,4,44,59,100,57,33,39), +(10,4,45,60,102,59,34,40), +(10,4,46,61,104,60,34,41), +(10,4,47,62,107,61,34,41), +(10,4,48,64,109,62,35,42), +(10,4,49,65,111,63,35,43), +(10,4,50,66,113,64,35,43), +(10,4,51,67,115,65,36,44), +(10,4,52,68,117,66,36,44), +(10,4,53,70,120,67,36,45), +(10,4,54,71,122,69,37,46), +(10,4,55,72,124,70,37,46), +(10,4,56,73,126,71,37,47), +(10,4,57,75,129,72,38,48), +(10,4,58,76,131,73,38,48), +(10,4,59,77,133,74,39,49), +(10,4,60,79,136,76,39,50), +(10,4,61,80,138,77,39,51), +(10,4,62,81,140,78,40,51), +(10,4,63,82,143,79,40,52), +(10,4,64,84,145,80,41,53), +(10,4,65,85,148,82,41,53), +(10,4,66,87,150,83,41,54), +(10,4,67,88,153,84,42,55), +(10,4,68,89,155,85,42,56), +(10,4,69,91,157,87,43,56), +(10,4,70,92,160,88,43,57), +(10,5,1,17,22,19,26,22), +(10,5,2,17,22,19,27,23), +(10,5,3,17,22,20,29,25), +(10,5,4,17,23,20,30,26), +(10,5,5,18,23,20,31,27), +(10,5,6,18,23,21,33,29), +(10,5,7,18,23,21,34,30), +(10,5,8,18,24,22,35,32), +(10,5,9,18,24,22,37,33), +(10,5,10,19,24,22,38,35), +(10,5,11,19,24,23,39,36), +(10,5,12,19,24,23,41,38), +(10,5,13,19,25,24,42,39), +(10,5,14,19,25,24,44,41), +(10,5,15,19,25,25,45,42), +(10,5,16,20,26,25,47,44), +(10,5,17,20,26,25,48,45), +(10,5,18,20,26,26,50,47), +(10,5,19,20,26,26,51,49), +(10,5,20,21,27,27,53,50), +(10,5,21,21,27,27,54,52), +(10,5,22,21,27,28,56,53), +(10,5,23,21,28,28,58,55), +(10,5,24,21,28,29,59,57), +(10,5,25,22,28,29,61,58), +(10,5,26,22,28,30,62,60), +(10,5,27,22,29,30,64,62), +(10,5,28,22,29,31,66,64), +(10,5,29,23,29,31,67,65), +(10,5,30,23,30,32,69,67), +(10,5,31,23,30,32,71,69), +(10,5,32,23,30,33,72,71), +(10,5,33,24,31,33,74,72), +(10,5,34,24,31,34,76,74), +(10,5,35,24,32,34,78,76), +(10,5,36,24,32,35,80,78), +(10,5,37,25,32,35,81,80), +(10,5,38,25,33,36,83,82), +(10,5,39,25,33,37,85,84), +(10,5,40,26,33,37,87,86), +(10,5,41,26,34,38,89,88), +(10,5,42,26,34,38,91,89), +(10,5,43,27,35,39,92,91), +(10,5,44,27,35,39,94,93), +(10,5,45,27,35,40,96,95), +(10,5,46,27,36,41,98,97), +(10,5,47,28,36,41,100,99), +(10,5,48,28,37,42,102,101), +(10,5,49,28,37,43,104,103), +(10,5,50,29,37,43,106,106), +(10,5,51,29,38,44,108,108), +(10,5,52,29,38,44,110,110), +(10,5,53,30,39,45,112,112), +(10,5,54,30,39,46,114,114), +(10,5,55,30,40,46,116,116), +(10,5,56,31,40,47,118,118), +(10,5,57,31,41,48,120,120), +(10,5,58,31,41,48,123,123), +(10,5,59,32,42,49,125,125), +(10,5,60,32,42,50,127,127), +(10,5,61,33,42,51,129,129), +(10,5,62,33,43,51,131,131), +(10,5,63,33,43,52,133,134), +(10,5,64,34,44,53,135,136), +(10,5,65,34,44,53,138,138), +(10,5,66,34,45,54,140,141), +(10,5,67,35,45,55,142,143), +(10,5,68,35,46,56,144,145), +(10,5,69,36,46,56,147,148), +(10,5,70,36,47,57,149,150), +(10,8,1,17,22,19,27,21), +(10,8,2,17,22,19,28,22), +(10,8,3,17,22,20,30,24), +(10,8,4,17,22,20,31,25), +(10,8,5,17,23,20,32,26), +(10,8,6,17,23,20,34,28), +(10,8,7,18,23,21,35,29), +(10,8,8,18,23,21,37,30), +(10,8,9,18,23,21,38,32), +(10,8,10,18,23,22,40,33), +(10,8,11,18,24,22,41,35), +(10,8,12,18,24,22,42,36), +(10,8,13,18,24,23,44,37), +(10,8,14,18,24,23,45,39), +(10,8,15,18,24,23,47,40), +(10,8,16,19,24,24,49,42), +(10,8,17,19,25,24,50,43), +(10,8,18,19,25,24,52,45), +(10,8,19,19,25,25,53,46), +(10,8,20,19,25,25,55,48), +(10,8,21,19,25,26,57,50), +(10,8,22,19,26,26,58,51), +(10,8,23,20,26,26,60,53), +(10,8,24,20,26,27,61,54), +(10,8,25,20,26,27,63,56), +(10,8,26,20,27,27,65,58), +(10,8,27,20,27,28,67,59), +(10,8,28,20,27,28,68,61), +(10,8,29,21,27,29,70,63), +(10,8,30,21,28,29,72,64), +(10,8,31,21,28,30,74,66), +(10,8,32,21,28,30,75,68), +(10,8,33,21,28,30,77,70), +(10,8,34,21,29,31,79,71), +(10,8,35,22,29,31,81,73), +(10,8,36,22,29,32,83,75), +(10,8,37,22,29,32,85,77), +(10,8,38,22,30,33,86,78), +(10,8,39,22,30,33,88,80), +(10,8,40,23,30,34,90,82), +(10,8,41,23,31,34,92,84), +(10,8,42,23,31,35,94,86), +(10,8,43,23,31,35,96,88), +(10,8,44,23,32,36,98,90), +(10,8,45,24,32,36,100,92), +(10,8,46,24,32,37,102,93), +(10,8,47,24,32,37,104,95), +(10,8,48,24,33,38,106,97), +(10,8,49,25,33,38,108,99), +(10,8,50,25,33,39,110,101), +(10,8,51,25,34,39,112,103), +(10,8,52,25,34,40,114,105), +(10,8,53,25,35,40,117,107), +(10,8,54,26,35,41,119,109), +(10,8,55,26,35,41,121,111), +(10,8,56,26,36,42,123,113), +(10,8,57,26,36,42,125,116), +(10,8,58,27,36,43,127,118), +(10,8,59,27,37,43,130,120), +(10,8,60,27,37,44,132,122), +(10,8,61,27,37,45,134,124), +(10,8,62,28,38,45,136,126), +(10,8,63,28,38,46,139,128), +(10,8,64,28,39,46,141,131), +(10,8,65,29,39,47,143,133), +(10,8,66,29,39,48,146,135), +(10,8,67,29,40,48,148,137), +(10,8,68,29,40,49,150,139), +(10,8,69,30,41,49,153,142), +(10,8,70,30,41,50,155,144), +(10,9,1,17,22,20,26,21), +(10,9,2,17,22,21,27,22), +(10,9,3,18,23,21,28,23), +(10,9,4,18,23,22,29,24), +(10,9,5,18,23,22,31,26), +(10,9,6,18,24,23,32,27), +(10,9,7,19,24,23,33,28), +(10,9,8,19,25,24,34,29), +(10,9,9,19,25,25,36,30), +(10,9,10,20,25,25,37,32), +(10,9,11,20,26,26,38,33), +(10,9,12,20,26,26,39,34), +(10,9,13,21,27,27,41,36), +(10,9,14,21,27,28,42,37), +(10,9,15,21,27,28,43,38), +(10,9,16,22,28,29,45,39), +(10,9,17,22,28,30,46,41), +(10,9,18,23,29,30,47,42), +(10,9,19,23,29,31,49,43), +(10,9,20,23,30,32,50,45), +(10,9,21,24,30,32,51,46), +(10,9,22,24,31,33,53,48), +(10,9,23,24,31,34,54,49), +(10,9,24,25,31,34,56,50), +(10,9,25,25,32,35,57,52), +(10,9,26,26,32,36,59,53), +(10,9,27,26,33,37,60,55), +(10,9,28,26,33,37,62,56), +(10,9,29,27,34,38,63,58), +(10,9,30,27,34,39,65,59), +(10,9,31,28,35,40,66,61), +(10,9,32,28,36,40,68,62), +(10,9,33,29,36,41,69,64), +(10,9,34,29,37,42,71,65), +(10,9,35,29,37,43,73,67), +(10,9,36,30,38,43,74,69), +(10,9,37,30,38,44,76,70), +(10,9,38,31,39,45,77,72), +(10,9,39,31,39,46,79,73), +(10,9,40,32,40,47,81,75), +(10,9,41,32,41,48,82,77), +(10,9,42,33,41,48,84,78), +(10,9,43,33,42,49,86,80), +(10,9,44,34,42,50,88,82), +(10,9,45,34,43,51,89,83), +(10,9,46,35,44,52,91,85), +(10,9,47,35,44,53,93,87), +(10,9,48,36,45,54,95,89), +(10,9,49,36,45,54,96,90), +(10,9,50,37,46,55,98,92), +(10,9,51,37,47,56,100,94), +(10,9,52,38,47,57,102,96), +(10,9,53,38,48,58,104,97), +(10,9,54,39,49,59,105,99), +(10,9,55,39,49,60,107,101), +(10,9,56,40,50,61,109,103), +(10,9,57,40,51,62,111,105), +(10,9,58,41,51,63,113,107), +(10,9,59,42,52,64,115,108), +(10,9,60,42,53,65,117,110), +(10,9,61,43,53,66,119,112), +(10,9,62,43,54,67,121,114), +(10,9,63,44,55,68,123,116), +(10,9,64,44,56,69,125,118), +(10,9,65,45,56,70,127,120), +(10,9,66,46,57,71,129,122), +(10,9,67,46,58,72,131,124), +(10,9,68,47,58,73,133,126), +(10,9,69,47,59,74,135,128), +(10,9,70,48,60,75,137,130), +(11,1,1,24,17,21,21,22), +(11,1,2,25,18,22,21,22), +(11,1,3,27,19,23,21,23), +(11,1,4,28,19,25,21,23), +(11,1,5,29,20,26,21,23), +(11,1,6,31,21,27,21,23), +(11,1,7,32,22,28,21,24), +(11,1,8,33,23,29,22,24), +(11,1,9,35,24,31,22,24), +(11,1,10,36,24,32,22,25), +(11,1,11,37,25,33,22,25), +(11,1,12,39,26,34,22,25), +(11,1,13,40,27,36,22,26), +(11,1,14,42,28,37,22,26), +(11,1,15,43,29,38,22,26), +(11,1,16,45,30,40,22,27), +(11,1,17,46,31,41,23,27), +(11,1,18,48,32,43,23,27), +(11,1,19,49,33,44,23,28), +(11,1,20,51,34,45,23,28), +(11,1,21,52,34,47,23,28), +(11,1,22,54,35,48,23,29), +(11,1,23,55,36,50,23,29), +(11,1,24,57,37,51,24,30), +(11,1,25,59,38,52,24,30), +(11,1,26,60,39,54,24,30), +(11,1,27,62,40,55,24,31), +(11,1,28,63,41,57,24,31), +(11,1,29,65,43,58,24,32), +(11,1,30,67,44,60,24,32), +(11,1,31,69,45,62,25,32), +(11,1,32,70,46,63,25,33), +(11,1,33,72,47,65,25,33), +(11,1,34,74,48,66,25,34), +(11,1,35,75,49,68,25,34), +(11,1,36,77,50,69,26,35), +(11,1,37,79,51,71,26,35), +(11,1,38,81,52,73,26,35), +(11,1,39,83,53,74,26,36), +(11,1,40,84,55,76,26,36), +(11,1,41,86,56,78,27,37), +(11,1,42,88,57,79,27,37), +(11,1,43,90,58,81,27,38), +(11,1,44,92,59,83,27,38), +(11,1,45,94,60,85,27,39), +(11,1,46,96,62,86,28,39), +(11,1,47,98,63,88,28,40), +(11,1,48,100,64,90,28,40), +(11,1,49,102,65,92,28,41), +(11,1,50,103,66,93,29,41), +(11,1,51,105,68,95,29,42), +(11,1,52,107,69,97,29,42), +(11,1,53,109,70,99,29,43), +(11,1,54,112,71,101,30,44), +(11,1,55,114,73,103,30,44), +(11,1,56,116,74,104,30,45), +(11,1,57,118,75,106,30,45), +(11,1,58,120,77,108,31,46), +(11,1,59,122,78,110,31,46), +(11,1,60,124,79,112,31,47), +(11,1,61,126,81,114,31,48), +(11,1,62,128,82,116,32,48), +(11,1,63,130,83,118,32,49), +(11,1,64,133,85,120,32,49), +(11,1,65,135,86,122,33,50), +(11,1,66,137,87,124,33,51), +(11,1,67,139,89,126,33,51), +(11,1,68,141,90,128,33,52), +(11,1,69,144,92,130,34,52), +(11,1,70,146,93,132,34,53), +(11,2,1,23,17,21,21,23), +(11,2,2,24,18,22,22,24), +(11,2,3,25,18,23,22,24), +(11,2,4,26,19,24,23,25), +(11,2,5,27,19,25,24,26), +(11,2,6,29,20,26,24,26), +(11,2,7,30,21,27,25,27), +(11,2,8,31,21,28,26,28), +(11,2,9,32,22,29,26,29), +(11,2,10,33,22,31,27,29), +(11,2,11,34,23,32,28,30), +(11,2,12,36,24,33,28,31), +(11,2,13,37,24,34,29,32), +(11,2,14,38,25,35,30,32), +(11,2,15,39,26,36,31,33), +(11,2,16,40,26,37,31,34), +(11,2,17,42,27,39,32,35), +(11,2,18,43,28,40,33,36), +(11,2,19,44,28,41,34,37), +(11,2,20,46,29,42,34,37), +(11,2,21,47,30,44,35,38), +(11,2,22,48,31,45,36,39), +(11,2,23,50,31,46,37,40), +(11,2,24,51,32,47,38,41), +(11,2,25,52,33,49,38,42), +(11,2,26,54,34,50,39,43), +(11,2,27,55,34,51,40,44), +(11,2,28,56,35,53,41,44), +(11,2,29,58,36,54,42,45), +(11,2,30,59,37,55,43,46), +(11,2,31,61,37,57,43,47), +(11,2,32,62,38,58,44,48), +(11,2,33,64,39,59,45,49), +(11,2,34,65,40,61,46,50), +(11,2,35,67,41,62,47,51), +(11,2,36,68,42,64,48,52), +(11,2,37,70,42,65,49,53), +(11,2,38,71,43,67,50,54), +(11,2,39,73,44,68,51,55), +(11,2,40,74,45,69,52,56), +(11,2,41,76,46,71,53,57), +(11,2,42,78,47,72,54,58), +(11,2,43,79,47,74,55,59), +(11,2,44,81,48,75,56,60), +(11,2,45,82,49,77,57,61), +(11,2,46,84,50,78,58,62), +(11,2,47,86,51,80,59,64), +(11,2,48,87,52,82,60,65), +(11,2,49,89,53,83,61,66), +(11,2,50,91,54,85,62,67), +(11,2,51,92,55,86,63,68), +(11,2,52,94,56,88,64,69), +(11,2,53,96,57,90,65,70), +(11,2,54,97,58,91,66,71), +(11,2,55,99,59,93,67,73), +(11,2,56,101,60,95,68,74), +(11,2,57,103,61,96,69,75), +(11,2,58,105,62,98,70,76), +(11,2,59,106,63,100,71,77), +(11,2,60,108,64,101,72,78), +(11,2,61,110,65,103,74,80), +(11,2,62,112,66,105,75,81), +(11,2,63,114,67,106,76,82), +(11,2,64,116,68,108,77,83), +(11,2,65,117,69,110,78,85), +(11,2,66,119,70,112,79,86), +(11,2,67,121,71,114,80,87), +(11,2,68,123,72,115,82,88), +(11,2,69,125,73,117,83,90), +(11,2,70,127,74,119,84,91), +(11,3,1,21,20,20,21,23), +(11,3,2,21,21,21,22,24), +(11,3,3,22,23,22,22,24), +(11,3,4,22,24,23,23,25), +(11,3,5,23,25,24,23,25), +(11,3,6,23,27,25,24,26), +(11,3,7,24,28,26,24,27), +(11,3,8,24,30,27,25,27), +(11,3,9,25,31,27,26,28), +(11,3,10,25,33,28,26,29), +(11,3,11,25,34,29,27,29), +(11,3,12,26,36,30,28,30), +(11,3,13,26,37,31,28,31), +(11,3,14,27,39,32,29,32), +(11,3,15,27,40,34,30,32), +(11,3,16,28,42,35,30,33), +(11,3,17,28,43,36,31,34), +(11,3,18,29,45,37,32,35), +(11,3,19,29,47,38,32,35), +(11,3,20,30,48,39,33,36), +(11,3,21,31,50,40,34,37), +(11,3,22,31,51,41,34,38), +(11,3,23,32,53,42,35,38), +(11,3,24,32,55,43,36,39), +(11,3,25,33,57,44,37,40), +(11,3,26,33,58,46,37,41), +(11,3,27,34,60,47,38,42), +(11,3,28,35,62,48,39,42), +(11,3,29,35,63,49,40,43), +(11,3,30,36,65,50,40,44), +(11,3,31,36,67,52,41,45), +(11,3,32,37,69,53,42,46), +(11,3,33,38,71,54,43,47), +(11,3,34,38,72,55,44,48), +(11,3,35,39,74,57,44,48), +(11,3,36,39,76,58,45,49), +(11,3,37,40,78,59,46,50), +(11,3,38,41,80,60,47,51), +(11,3,39,41,82,62,48,52), +(11,3,40,42,84,63,49,53), +(11,3,41,43,86,64,50,54), +(11,3,42,43,88,66,50,55), +(11,3,43,44,90,67,51,56), +(11,3,44,45,91,68,52,57), +(11,3,45,45,93,70,53,58), +(11,3,46,46,95,71,54,59), +(11,3,47,47,98,72,55,60), +(11,3,48,48,100,74,56,61), +(11,3,49,48,102,75,57,62), +(11,3,50,49,104,77,58,63), +(11,3,51,50,106,78,59,64), +(11,3,52,51,108,79,60,65), +(11,3,53,51,110,81,61,66), +(11,3,54,52,112,82,61,67), +(11,3,55,53,114,84,62,68), +(11,3,56,54,116,85,63,69), +(11,3,57,54,118,87,64,70), +(11,3,58,55,121,88,65,71), +(11,3,59,56,123,90,66,72), +(11,3,60,57,125,91,67,74), +(11,3,61,58,127,93,68,75), +(11,3,62,58,130,94,69,76), +(11,3,63,59,132,96,71,77), +(11,3,64,60,134,97,72,78), +(11,3,65,61,136,99,73,79), +(11,3,66,62,139,101,74,80), +(11,3,67,62,141,102,75,81), +(11,3,68,63,143,104,76,83), +(11,3,69,64,146,105,77,84), +(11,3,70,65,148,107,78,85), +(11,5,1,21,17,19,23,25), +(11,5,2,21,17,19,24,26), +(11,5,3,21,17,20,26,28), +(11,5,4,21,18,20,27,29), +(11,5,5,22,18,20,28,30), +(11,5,6,22,18,21,30,32), +(11,5,7,22,18,21,31,33), +(11,5,8,22,19,22,32,35), +(11,5,9,22,19,22,34,36), +(11,5,10,22,19,22,35,38), +(11,5,11,23,19,23,37,39), +(11,5,12,23,20,23,38,41), +(11,5,13,23,20,24,39,42), +(11,5,14,23,20,24,41,44), +(11,5,15,23,20,25,42,45), +(11,5,16,24,21,25,44,47), +(11,5,17,24,21,25,45,48), +(11,5,18,24,21,26,47,50), +(11,5,19,24,22,26,48,51), +(11,5,20,24,22,27,50,53), +(11,5,21,25,22,27,51,55), +(11,5,22,25,22,28,53,56), +(11,5,23,25,23,28,55,58), +(11,5,24,25,23,29,56,60), +(11,5,25,25,23,29,58,61), +(11,5,26,26,24,30,60,63), +(11,5,27,26,24,30,61,65), +(11,5,28,26,24,31,63,66), +(11,5,29,26,25,31,65,68), +(11,5,30,27,25,32,66,70), +(11,5,31,27,25,32,68,72), +(11,5,32,27,26,33,70,73), +(11,5,33,27,26,33,71,75), +(11,5,34,28,26,34,73,77), +(11,5,35,28,27,34,75,79), +(11,5,36,28,27,35,77,81), +(11,5,37,29,28,35,79,83), +(11,5,38,29,28,36,80,85), +(11,5,39,29,28,37,82,86), +(11,5,40,29,29,37,84,88), +(11,5,41,30,29,38,86,90), +(11,5,42,30,29,38,88,92), +(11,5,43,30,30,39,90,94), +(11,5,44,31,30,39,91,96), +(11,5,45,31,31,40,93,98), +(11,5,46,31,31,41,95,100), +(11,5,47,32,31,41,97,102), +(11,5,48,32,32,42,99,104), +(11,5,49,32,32,43,101,106), +(11,5,50,33,33,43,103,108), +(11,5,51,33,33,44,105,110), +(11,5,52,33,34,44,107,113), +(11,5,53,34,34,45,109,115), +(11,5,54,34,34,46,111,117), +(11,5,55,34,35,46,113,119), +(11,5,56,35,35,47,115,121), +(11,5,57,35,36,48,118,123), +(11,5,58,35,36,48,120,126), +(11,5,59,36,37,49,122,128), +(11,5,60,36,37,50,124,130), +(11,5,61,36,38,51,126,132), +(11,5,62,37,38,51,128,134), +(11,5,63,37,39,52,130,137), +(11,5,64,38,39,53,133,139), +(11,5,65,38,40,53,135,141), +(11,5,66,38,40,54,137,144), +(11,5,67,39,40,55,139,146), +(11,5,68,39,41,56,141,148), +(11,5,69,40,41,56,144,151), +(11,5,70,40,42,57,146,153), +(11,7,1,22,17,20,22,24), +(11,7,2,23,17,21,23,25), +(11,7,3,24,18,22,24,26), +(11,7,4,25,18,23,25,27), +(11,7,5,25,19,24,26,28), +(11,7,6,26,19,25,27,29), +(11,7,7,27,20,26,28,30), +(11,7,8,28,20,27,28,31), +(11,7,9,29,21,28,29,32), +(11,7,10,30,21,29,30,33), +(11,7,11,31,22,30,31,35), +(11,7,12,32,22,31,32,36), +(11,7,13,33,23,32,33,37), +(11,7,14,34,23,33,34,38), +(11,7,15,34,24,35,35,39), +(11,7,16,35,24,36,36,40), +(11,7,17,36,25,37,38,42), +(11,7,18,37,25,38,39,43), +(11,7,19,38,26,39,40,44), +(11,7,20,39,26,40,41,45), +(11,7,21,40,27,41,42,46), +(11,7,22,41,27,43,43,48), +(11,7,23,43,28,44,44,49), +(11,7,24,44,28,45,45,50), +(11,7,25,45,29,46,46,51), +(11,7,26,46,30,47,48,53), +(11,7,27,47,30,49,49,54), +(11,7,28,48,31,50,50,55), +(11,7,29,49,31,51,51,57), +(11,7,30,50,32,53,52,58), +(11,7,31,51,33,54,53,59), +(11,7,32,52,33,55,55,61), +(11,7,33,53,34,56,56,62), +(11,7,34,55,34,58,57,64), +(11,7,35,56,35,59,58,65), +(11,7,36,57,36,60,60,66), +(11,7,37,58,36,62,61,68), +(11,7,38,59,37,63,62,69), +(11,7,39,61,38,65,63,71), +(11,7,40,62,38,66,65,72), +(11,7,41,63,39,67,66,74), +(11,7,42,64,40,69,67,75), +(11,7,43,65,40,70,69,77), +(11,7,44,67,41,72,70,78), +(11,7,45,68,42,73,71,80), +(11,7,46,69,42,75,73,81), +(11,7,47,71,43,76,74,83), +(11,7,48,72,44,78,76,84), +(11,7,49,73,45,79,77,86), +(11,7,50,74,45,81,78,88), +(11,7,51,76,46,82,80,89), +(11,7,52,77,47,84,81,91), +(11,7,53,78,47,85,83,92), +(11,7,54,80,48,87,84,94), +(11,7,55,81,49,88,86,96), +(11,7,56,83,50,90,87,97), +(11,7,57,84,50,91,89,99), +(11,7,58,85,51,93,90,101), +(11,7,59,87,52,95,92,102), +(11,7,60,88,53,96,93,104), +(11,7,61,90,54,98,95,106), +(11,7,62,91,54,99,96,108), +(11,7,63,93,55,101,98,109), +(11,7,64,94,56,103,99,111), +(11,7,65,95,57,104,101,113), +(11,7,66,97,58,106,103,115), +(11,7,67,98,58,108,104,117), +(11,7,68,100,59,110,106,118), +(11,7,69,101,60,111,107,120), +(11,7,70,103,61,113,109,122), +(11,8,1,21,17,19,24,24), +(11,8,2,21,17,19,25,25), +(11,8,3,21,17,20,27,27), +(11,8,4,21,17,20,28,28), +(11,8,5,21,18,20,29,29), +(11,8,6,21,18,20,31,31), +(11,8,7,21,18,21,32,32), +(11,8,8,22,18,21,34,33), +(11,8,9,22,18,21,35,35), +(11,8,10,22,19,22,37,36), +(11,8,11,22,19,22,38,37), +(11,8,12,22,19,22,40,39), +(11,8,13,22,19,23,41,40), +(11,8,14,22,19,23,43,42), +(11,8,15,22,19,23,44,43), +(11,8,16,22,20,24,46,45), +(11,8,17,23,20,24,47,46), +(11,8,18,23,20,24,49,48), +(11,8,19,23,20,25,50,49), +(11,8,20,23,21,25,52,51), +(11,8,21,23,21,26,54,52), +(11,8,22,23,21,26,55,54), +(11,8,23,23,21,26,57,56), +(11,8,24,24,21,27,59,57), +(11,8,25,24,22,27,60,59), +(11,8,26,24,22,27,62,60), +(11,8,27,24,22,28,64,62), +(11,8,28,24,22,28,65,64), +(11,8,29,24,23,29,67,65), +(11,8,30,24,23,29,69,67), +(11,8,31,25,23,30,71,69), +(11,8,32,25,23,30,73,71), +(11,8,33,25,24,30,74,72), +(11,8,34,25,24,31,76,74), +(11,8,35,25,24,31,78,76), +(11,8,36,26,24,32,80,78), +(11,8,37,26,25,32,82,79), +(11,8,38,26,25,33,84,81), +(11,8,39,26,25,33,86,83), +(11,8,40,26,26,34,87,85), +(11,8,41,27,26,34,89,87), +(11,8,42,27,26,35,91,89), +(11,8,43,27,27,35,93,91), +(11,8,44,27,27,36,95,92), +(11,8,45,27,27,36,97,94), +(11,8,46,28,27,37,99,96), +(11,8,47,28,28,37,101,98), +(11,8,48,28,28,38,103,100), +(11,8,49,28,28,38,105,102), +(11,8,50,29,29,39,107,104), +(11,8,51,29,29,39,110,106), +(11,8,52,29,29,40,112,108), +(11,8,53,29,30,40,114,110), +(11,8,54,30,30,41,116,112), +(11,8,55,30,30,41,118,114), +(11,8,56,30,31,42,120,116), +(11,8,57,30,31,42,122,118), +(11,8,58,31,31,43,125,121), +(11,8,59,31,32,43,127,123), +(11,8,60,31,32,44,129,125), +(11,8,61,31,33,45,131,127), +(11,8,62,32,33,45,133,129), +(11,8,63,32,33,46,136,131), +(11,8,64,32,34,46,138,134), +(11,8,65,33,34,47,140,136), +(11,8,66,33,34,48,143,138), +(11,8,67,33,35,48,145,140), +(11,8,68,33,35,49,147,142), +(11,8,69,34,36,49,150,145), +(11,8,70,34,36,50,152,147); +/*!40000 ALTER TABLE `player_levelstats` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `playercreateinfo` +-- + +DROP TABLE IF EXISTS `playercreateinfo`; +CREATE TABLE `playercreateinfo` ( + `race` tinyint(3) unsigned NOT NULL default '0', + `class` tinyint(3) unsigned NOT NULL default '0', + `map` smallint(5) unsigned NOT NULL default '0', + `zone` mediumint(8) unsigned NOT NULL default '0', + `position_x` float NOT NULL default '0', + `position_y` float NOT NULL default '0', + `position_z` float NOT NULL default '0', + PRIMARY KEY (`race`,`class`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `playercreateinfo` +-- + +LOCK TABLES `playercreateinfo` WRITE; +/*!40000 ALTER TABLE `playercreateinfo` DISABLE KEYS */; +INSERT INTO `playercreateinfo` VALUES +(1,1,0,12,-8949,-132,84), +(1,2,0,12,-8949,-132,84), +(1,4,0,12,-8949,-132,84), +(1,5,0,12,-8949,-132,84), +(1,8,0,12,-8949,-132,84), +(1,9,0,12,-8949,-132,84), +(2,1,1,14,-618,-4251,39), +(2,3,1,14,-618,-4251,39), +(2,4,1,14,-618,-4251,39), +(2,7,1,14,-618,-4251,39), +(2,9,1,14,-618,-4251,39), +(3,1,0,1,-6240,331,383), +(3,2,0,1,-6240,331,383), +(3,3,0,1,-6240,331,383), +(3,4,0,1,-6240,331,383), +(3,5,0,1,-6240,331,383), +(4,1,1,141,10311,832,1327), +(4,3,1,141,10311,832,1327), +(4,4,1,141,10311,832,1327), +(4,5,1,141,10311,832,1327), +(4,11,1,141,10311,832,1327), +(5,1,0,85,1676,1677,122), +(5,4,0,85,1676,1677,122), +(5,5,0,85,1676,1677,122), +(5,8,0,85,1676,1677,122), +(5,9,0,85,1676,1677,122), +(6,1,1,215,-2917,-257,53), +(6,3,1,215,-2917,-257,53), +(6,7,1,215,-2917,-257,53), +(6,11,1,215,-2917,-257,53), +(7,1,0,1,-6240,331,383), +(7,4,0,1,-6340,331,383), +(7,8,0,1,-6340,331,383), +(7,9,0,1,-6340,331,383), +(8,1,1,14,-618,-4251,39), +(8,3,1,14,-618,-4251,39), +(8,4,1,14,-618,-4251,39), +(8,5,1,14,-618,-4251,39), +(8,7,1,14,-618,-4251,39), +(8,8,1,14,-618,-4251,39), +(10,2,530,3431,10349.6,-6357.29,33.4026), +(10,3,530,3431,10349.6,-6357.29,33.4026), +(10,4,530,3431,10349.6,-6357.29,33.4026), +(10,5,530,3431,10349.6,-6357.29,33.4026), +(10,8,530,3431,10349.6,-6357.29,33.4026), +(10,9,530,3431,10349.6,-6357.29,33.4026), +(11,1,530,3526,-3961.64,-13931.2,100.615), +(11,2,530,3526,-3961.64,-13931.2,100.615), +(11,3,530,3526,-3961.64,-13931.2,100.615), +(11,5,530,3526,-3961.64,-13931.2,100.615), +(11,7,530,3526,-3961.64,-13931.2,100.615), +(11,8,530,3526,-3961.64,-13931.2,100.615); +/*!40000 ALTER TABLE `playercreateinfo` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `playercreateinfo_action` +-- + +DROP TABLE IF EXISTS `playercreateinfo_action`; +CREATE TABLE `playercreateinfo_action` ( + `race` tinyint(3) unsigned NOT NULL default '0', + `class` tinyint(3) unsigned NOT NULL default '0', + `button` smallint(5) unsigned NOT NULL default '0', + `action` smallint(5) unsigned NOT NULL default '0', + `type` smallint(5) unsigned NOT NULL default '0', + `misc` smallint(5) unsigned NOT NULL default '0', + KEY `playercreateinfo_race_class_index` (`race`,`class`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `playercreateinfo_action` +-- + +LOCK TABLES `playercreateinfo_action` WRITE; +/*!40000 ALTER TABLE `playercreateinfo_action` DISABLE KEYS */; +INSERT INTO `playercreateinfo_action` VALUES +(1,1,1,78,0,0), +(1,1,0,6603,0,0), +(1,1,11,117,128,0), +(1,2,2,635,0,0), +(1,2,0,6603,0,0), +(1,2,1,21084,0,0), +(1,2,10,159,128,0), +(1,2,11,2070,128,0), +(1,4,1,1752,0,0), +(1,4,2,2098,0,0), +(1,4,3,2764,0,0), +(1,4,0,6603,0,0), +(1,4,11,2070,128,0), +(1,5,1,585,0,0), +(1,5,2,2050,0,0), +(1,5,0,6603,0,0), +(1,5,10,159,128,0), +(1,5,11,2070,128,0), +(1,8,1,133,0,0), +(1,8,2,168,0,0), +(1,8,0,6603,0,0), +(1,8,10,159,128,0), +(1,8,11,2070,128,0), +(1,9,1,686,0,0), +(1,9,2,687,0,0), +(1,9,0,6603,0,0), +(1,9,10,159,128,0), +(1,9,11,4604,128,0), +(2,1,1,78,0,0), +(2,1,0,6603,0,0), +(2,1,11,117,128,0), +(2,3,2,75,0,0), +(2,3,1,2973,0,0), +(2,3,0,6603,0,0), +(2,3,11,117,128,0), +(2,3,10,159,128,0), +(2,4,10,0,128,0), +(2,4,1,1752,0,0), +(2,4,2,2098,0,0), +(2,4,0,6603,0,0), +(2,4,11,117,128,0), +(2,7,2,331,0,0), +(2,7,1,403,0,0), +(2,7,0,6603,0,0), +(2,7,11,117,128,0), +(2,7,10,159,128,0), +(2,9,1,686,0,0), +(2,9,2,687,0,0), +(2,9,0,6603,0,0), +(2,9,11,117,128,0), +(2,9,10,159,128,0), +(3,1,1,78,0,0), +(3,1,0,6603,0,0), +(3,1,11,117,128,0), +(3,2,2,635,0,0), +(3,2,0,6603,0,0), +(3,2,1,21084,0,0), +(3,2,10,159,128,0), +(3,2,11,4540,128,0), +(3,3,2,75,0,0), +(3,3,1,2973,0,0), +(3,3,0,6603,0,0), +(3,3,11,117,128,0), +(3,3,10,159,128,0), +(3,4,1,1752,0,0), +(3,4,2,2098,0,0), +(3,4,3,2764,0,0), +(3,4,0,6603,0,0), +(3,4,11,4540,128,0), +(3,5,1,585,0,0), +(3,5,2,2050,0,0), +(3,5,0,6603,0,0), +(3,5,10,159,128,0), +(3,5,11,4540,128,0), +(4,1,1,78,0,0), +(4,1,0,6603,0,0), +(4,1,11,117,128,0), +(4,3,2,75,0,0), +(4,3,1,2973,0,0), +(4,3,0,6603,0,0), +(4,3,11,117,128,0), +(4,3,10,159,128,0), +(4,4,1,1752,0,0), +(4,4,2,2098,0,0), +(4,4,3,2764,0,0), +(4,4,0,6603,0,0), +(4,4,11,4540,128,0), +(4,5,1,585,0,0), +(4,5,2,2050,0,0), +(4,5,0,6603,0,0), +(4,5,10,159,128,0), +(4,5,11,2070,128,0), +(4,11,1,5176,0,0), +(4,11,2,5185,0,0), +(4,11,0,6603,0,0), +(4,11,10,159,128,0), +(4,11,11,4536,128,0), +(5,1,11,4604,128,0), +(5,1,0,6603,0,0), +(5,1,1,78,0,0), +(5,4,11,4604,128,0), +(5,4,3,2764,0,0), +(5,4,2,2098,0,0), +(5,4,1,1752,0,0), +(5,4,0,6603,0,0), +(5,5,10,159,128,0), +(5,5,2,2050,0,0), +(5,5,1,585,0,0), +(5,5,11,4604,128,0), +(5,5,0,6603,0,0), +(5,8,11,4604,128,0), +(5,8,10,159,128,0), +(5,8,2,168,0,0), +(5,8,1,133,0,0), +(5,8,0,6603,0,0), +(5,9,1,686,0,0), +(5,9,10,159,128,0), +(5,9,2,687,0,0), +(5,9,11,4604,128,0), +(5,9,0,6603,0,0), +(6,1,1,78,0,0), +(6,1,2,20549,0,0), +(6,1,11,4540,128,0), +(6,1,0,6603,0,0), +(6,3,1,2973,0,0), +(6,3,10,159,128,0), +(6,3,2,75,0,0), +(6,3,3,20549,0,0), +(6,3,11,117,128,0), +(6,3,0,6603,0,0), +(6,7,1,403,0,0), +(6,7,10,159,128,0), +(6,7,2,331,0,0), +(6,7,3,20549,0,0), +(6,7,11,4604,128,0), +(6,7,0,6603,0,0), +(6,11,1,5176,0,0), +(6,11,10,159,128,0), +(6,11,2,5185,0,0), +(6,11,3,20549,0,0), +(6,11,11,4536,128,0), +(6,11,0,6603,0,0), +(7,1,11,117,128,0), +(7,1,1,78,0,0), +(7,1,0,6603,0,0), +(7,4,11,117,128,0), +(7,4,3,2764,0,0), +(7,4,1,1752,0,0), +(7,4,2,2098,0,0), +(7,4,0,6603,0,0), +(7,8,11,4536,128,0), +(7,8,1,133,0,0), +(7,8,2,168,0,0), +(7,8,10,159,128,0), +(7,8,0,6603,0,0), +(7,9,11,4604,128,0), +(7,9,1,686,0,0), +(7,9,2,687,0,0), +(7,9,10,159,128,0), +(7,9,0,6603,0,0), +(8,1,11,117,128,0), +(8,1,1,78,0,0), +(8,1,3,2764,0,0), +(8,1,0,6603,0,0), +(8,3,10,159,128,0), +(8,3,11,4604,128,0), +(8,3,1,2973,0,0), +(8,3,2,75,0,0), +(8,3,0,6603,0,0), +(8,4,1,1752,0,0), +(8,4,3,2764,0,0), +(8,4,2,2098,0,0), +(8,4,11,117,128,0), +(8,4,0,6603,0,0), +(8,5,1,585,0,0), +(8,5,10,159,128,0), +(8,5,2,2050,0,0), +(8,5,11,4540,128,0), +(8,5,0,6603,0,0), +(8,7,1,403,0,0), +(8,7,10,159,128,0), +(8,7,2,331,0,0), +(8,7,11,117,128,0), +(8,7,0,6603,0,0), +(8,8,1,133,0,0), +(8,8,10,159,128,0), +(8,8,2,168,0,0), +(8,8,11,117,128,0), +(8,8,0,6603,0,0), +(10,2,0,6603,0,0), +(10,2,1,21084,0,0), +(10,2,2,635,0,0), +(10,2,3,28734,0,0), +(10,2,4,28730,0,0), +(10,2,10,159,128,0), +(10,2,11,20857,128,0), +(10,3,0,6603,0,0), +(10,3,1,2973,0,0), +(10,3,2,75,0,0), +(10,3,3,28734,0,0), +(10,3,4,28730,0,0), +(10,3,10,159,128,0), +(10,3,11,20857,128,0), +(10,4,0,6603,0,0), +(10,4,1,1752,0,0), +(10,4,2,2098,0,0), +(10,4,3,2764,0,0), +(10,4,4,28734,0,0), +(10,4,5,25046,0,0), +(10,4,11,20857,128,0), +(10,5,0,6603,0,0), +(10,5,1,585,0,0), +(10,5,2,2050,0,0), +(10,5,3,28734,0,0), +(10,5,4,28730,0,0), +(10,5,10,159,128,0), +(10,5,11,20857,128,0), +(10,8,0,6603,0,0), +(10,8,1,133,0,0), +(10,8,2,168,0,0), +(10,8,3,28734,0,0), +(10,8,4,28730,0,0), +(10,8,10,159,128,0), +(10,8,11,20857,128,0), +(10,9,11,20857,128,0), +(10,9,10,159,128,0), +(10,9,4,28730,0,0), +(10,9,3,28734,0,0), +(10,9,2,687,0,0), +(10,9,1,686,0,0), +(10,9,0,6603,0,0), +(11,1,0,6603,0,0), +(11,1,72,6603,0,0), +(11,1,73,78,0,0), +(11,1,74,28880,0,0), +(11,1,83,4540,128,0), +(11,1,84,6603,0,0), +(11,1,96,6603,0,0), +(11,1,108,6603,0,0), +(11,2,0,6603,0,0), +(11,2,1,21084,0,0), +(11,2,2,635,0,0), +(11,2,3,28880,0,0), +(11,2,10,159,128,0), +(11,2,11,4540,128,0), +(11,2,83,4540,128,0), +(11,3,0,6603,0,0), +(11,3,1,2973,0,0), +(11,3,2,75,0,0), +(11,3,3,28880,0,0), +(11,3,10,159,128,0), +(11,3,11,4540,128,0), +(11,3,72,6603,0,0), +(11,3,73,2973,0,0), +(11,3,74,75,0,0), +(11,3,82,159,128,0), +(11,3,83,4540,128,0), +(11,5,0,6603,0,0), +(11,5,1,585,0,0), +(11,5,2,2050,0,0), +(11,5,3,28880,0,0), +(11,5,10,159,128,0), +(11,5,11,4540,128,0), +(11,5,83,4540,128,0), +(11,7,0,6603,0,0), +(11,7,1,403,0,0), +(11,7,2,331,0,0), +(11,7,3,28880,0,0), +(11,7,10,159,128,0), +(11,7,11,4540,128,0), +(11,8,0,6603,0,0), +(11,8,1,133,0,0), +(11,8,2,168,0,0), +(11,8,3,28880,0,0), +(11,8,10,159,128,0), +(11,8,11,4540,128,0), +(11,8,83,4540,128,0); +/*!40000 ALTER TABLE `playercreateinfo_action` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `playercreateinfo_item` +-- + +DROP TABLE IF EXISTS `playercreateinfo_item`; +CREATE TABLE `playercreateinfo_item` ( + `race` tinyint(3) unsigned NOT NULL default '0', + `class` tinyint(3) unsigned NOT NULL default '0', + `itemid` mediumint(8) unsigned NOT NULL default '0', + `amount` tinyint(3) unsigned NOT NULL default '1', + KEY `playercreateinfo_race_class_index` (`race`,`class`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `playercreateinfo_item` +-- + +LOCK TABLES `playercreateinfo_item` WRITE; +/*!40000 ALTER TABLE `playercreateinfo_item` DISABLE KEYS */; +INSERT INTO `playercreateinfo_item` VALUES +(1,1,38,1), +(1,1,39,1), +(1,1,40,1), +(1,1,25,1), +(1,1,2362,1), +(1,1,117,4), +(1,1,6948,1), +(1,1,14646,1), +(1,2,45,1), +(1,2,44,1), +(1,2,43,1), +(1,2,2361,1), +(1,2,6948,1), +(1,2,159,2), +(1,2,2070,4), +(1,2,14646,1), +(1,4,49,1), +(1,4,48,1), +(1,4,47,1), +(1,4,2092,1), +(1,4,2947,100), +(1,4,2070,4), +(1,4,6948,1), +(1,4,14646,1), +(1,5,53,1), +(1,5,6098,1), +(1,5,52,1), +(1,5,51,1), +(1,5,36,1), +(1,5,159,2), +(1,5,2070,4), +(1,5,6948,1), +(1,5,14646,1), +(1,8,6096,1), +(1,8,56,1), +(1,8,1395,1), +(1,8,55,1), +(1,8,35,1), +(1,8,2070,4), +(1,8,159,2), +(1,8,6948,1), +(1,8,14646,1), +(1,9,6097,1), +(1,9,57,1), +(1,9,1396,1), +(1,9,59,1), +(1,9,2092,1), +(1,9,4604,4), +(1,9,159,2), +(1,9,6948,1), +(1,9,14646,1), +(2,1,6125,1), +(2,1,139,1), +(2,1,140,1), +(2,1,12282,1), +(2,1,6948,1), +(2,1,117,4), +(2,1,14649,1), +(2,3,127,1), +(2,3,6126,1), +(2,3,6127,1), +(2,3,37,1), +(2,3,2504,1), +(2,3,159,2), +(2,3,117,4), +(2,3,6948,1), +(2,3,14649,1), +(2,3,2512,200), +(2,3,2101,1), +(2,4,2105,1), +(2,4,120,1), +(2,4,121,1), +(2,4,2092,1), +(2,4,25861,100), +(2,4,117,4), +(2,4,6948,1), +(2,4,14649,1), +(2,7,154,1), +(2,7,153,1), +(2,7,36,1), +(2,7,6948,1), +(2,7,117,4), +(2,7,159,2), +(2,7,14649,1), +(2,9,6129,1), +(2,9,1396,1), +(2,9,59,1), +(2,9,2092,1), +(2,9,6948,1), +(2,9,117,4), +(2,9,159,2), +(2,9,14649,1), +(3,1,38,1), +(3,1,39,1), +(3,1,40,1), +(3,1,12282,1), +(3,1,6948,1), +(3,1,117,4), +(3,1,14647,1), +(3,2,45,1), +(3,2,44,1), +(3,2,43,1), +(3,2,2361,1), +(3,2,4540,4), +(3,2,159,2), +(3,2,6948,1), +(3,2,14647,1), +(3,3,148,1), +(3,3,147,1), +(3,3,129,1), +(3,3,37,1), +(3,3,2508,1), +(3,3,159,2), +(3,3,117,4), +(3,3,6948,1), +(3,3,14647,1), +(3,3,2516,200), +(3,3,2102,1), +(3,4,49,1), +(3,4,48,1), +(3,4,47,1), +(3,4,2092,1), +(3,4,25861,100), +(3,4,4540,4), +(3,4,6948,1), +(3,4,14647,1), +(3,5,53,1), +(3,5,6098,1), +(3,5,52,1), +(3,5,51,1), +(3,5,36,1), +(3,5,159,2), +(3,5,4540,4), +(3,5,6948,1), +(3,5,14647,1), +(4,1,38,1), +(4,1,39,1), +(4,1,40,1), +(4,1,25,1), +(4,1,2362,1), +(4,1,117,4), +(4,1,6948,1), +(4,1,14648,1), +(4,3,148,1), +(4,3,147,1), +(4,3,129,1), +(4,3,2092,1), +(4,3,2504,1), +(4,3,159,2), +(4,3,117,4), +(4,3,6948,1), +(4,3,14648,1), +(4,3,2512,200), +(4,3,2101,1), +(4,4,49,1), +(4,4,48,1), +(4,4,47,1), +(4,4,2092,1), +(4,4,2947,100), +(4,4,4540,4), +(4,4,6948,1), +(4,4,14648,1), +(4,5,53,1), +(4,5,6119,1), +(4,5,52,1), +(4,5,51,1), +(4,5,36,1), +(4,5,2070,4), +(4,5,159,2), +(4,5,6948,1), +(4,5,14648,1), +(4,11,6123,1), +(4,11,44,1), +(4,11,3661,1), +(4,11,159,2), +(4,11,4536,4), +(4,11,6948,1), +(4,11,14648,1), +(5,1,6125,1), +(5,1,139,1), +(5,1,140,1), +(5,1,25,1), +(5,1,2362,1), +(5,1,4604,4), +(5,1,6948,1), +(5,1,14651,1), +(5,4,2105,1), +(5,4,120,1), +(5,4,121,1), +(5,4,2092,1), +(5,4,2947,100), +(5,4,4604,4), +(5,4,6948,1), +(5,4,14651,1), +(5,5,53,1), +(5,5,6144,1), +(5,5,52,1), +(5,5,51,1), +(5,5,36,1), +(5,5,4604,4), +(5,5,159,2), +(5,5,6948,1), +(5,5,14651,1), +(5,8,6096,1), +(5,8,6140,1), +(5,8,1395,1), +(5,8,55,1), +(5,8,35,1), +(5,8,4604,4), +(5,8,159,2), +(5,8,6948,1), +(5,8,14651,1), +(5,9,6129,1), +(5,9,1396,1), +(5,9,59,1), +(5,9,2092,1), +(5,9,4604,4), +(5,9,159,2), +(5,9,6948,1), +(5,9,14651,1), +(6,1,6125,1), +(6,1,139,1), +(6,1,2361,1), +(6,1,6948,1), +(6,1,4540,4), +(6,1,14650,1), +(6,3,127,1), +(6,3,6126,1), +(6,3,37,1), +(6,3,2508,1), +(6,3,159,2), +(6,3,117,4), +(6,3,6948,1), +(6,3,14650,1), +(6,3,2516,200), +(6,3,2102,1), +(6,7,154,1), +(6,7,153,1), +(6,7,36,1), +(6,7,6948,1), +(6,7,4604,4), +(6,7,159,2), +(6,7,14650,1), +(6,11,6139,1), +(6,11,6124,1), +(6,11,35,1), +(6,11,159,2), +(6,11,4536,4), +(6,11,6948,1), +(6,11,14650,1), +(7,1,38,1), +(7,1,39,1), +(7,1,40,1), +(7,1,25,1), +(7,1,2362,1), +(7,1,117,4), +(7,1,6948,1), +(7,1,14647,1), +(7,4,49,1), +(7,4,48,1), +(7,4,47,1), +(7,4,2092,1), +(7,4,2947,100), +(7,4,117,4), +(7,4,6948,1), +(7,4,14647,1), +(7,8,6096,1), +(7,8,56,1), +(7,8,1395,1), +(7,8,55,1), +(7,8,35,1), +(7,8,4536,4), +(7,8,159,2), +(7,8,6948,1), +(7,8,14647,1), +(7,9,6097,1), +(7,9,57,1), +(7,9,1396,1), +(7,9,59,1), +(7,9,2092,1), +(7,9,159,2), +(7,9,4604,4), +(7,9,6948,1), +(7,9,14647,1), +(8,1,6125,1), +(8,1,139,1), +(8,1,140,1), +(8,1,37,1), +(8,1,2362,1), +(8,1,25861,100), +(8,1,117,4), +(8,1,6948,1), +(8,1,14649,1), +(8,3,127,1), +(8,3,6126,1), +(8,3,6127,1), +(8,3,37,1), +(8,3,2504,1), +(8,3,4604,4), +(8,3,159,2), +(8,3,2512,200), +(8,3,2101,1), +(8,3,14649,1), +(8,3,6948,1), +(8,4,2105,1), +(8,4,120,1), +(8,4,121,1), +(8,4,2092,1), +(8,4,25861,100), +(8,4,117,4), +(8,4,6948,1), +(8,4,14649,1), +(8,5,53,1), +(8,5,6144,1), +(8,5,52,1), +(8,5,36,1), +(8,5,4540,4), +(8,5,159,2), +(8,5,6948,1), +(8,5,14649,1), +(8,7,6134,1), +(8,7,6135,1), +(8,7,36,1), +(8,7,117,4), +(8,7,159,2), +(8,7,6948,1), +(8,7,14649,1), +(8,8,6096,1), +(8,8,6140,1), +(8,8,1395,1), +(8,8,55,1), +(8,8,35,1), +(8,8,117,4), +(8,8,159,2), +(8,8,6948,1), +(8,8,14649,1), +(10,2,159,5), +(10,2,2070,5), +(10,2,6948,1), +(10,2,23346,1), +(10,2,24143,1), +(10,2,24145,1), +(10,2,24146,1), +(10,3,159,5), +(10,3,2101,1), +(10,3,2512,200), +(10,3,6948,1), +(10,3,20857,5), +(10,3,20899,1), +(10,3,20900,1), +(10,3,20901,1), +(10,3,20980,1), +(10,3,20982,1), +(10,4,3111,100), +(10,4,6948,1), +(10,4,20857,10), +(10,4,20896,1), +(10,4,20897,1), +(10,4,20898,1), +(10,4,20982,1), +(10,5,51,1), +(10,5,52,1), +(10,5,53,1), +(10,5,159,5), +(10,5,6948,1), +(10,5,20891,1), +(10,5,20981,5), +(10,8,35,1), +(10,8,159,5), +(10,8,6096,1), +(10,8,6948,1), +(10,8,20857,5), +(10,8,20893,1), +(10,8,20894,1), +(10,8,20895,1), +(10,9,59,1), +(10,9,159,5), +(10,9,1396,1), +(10,9,6948,1), +(10,9,20857,5), +(10,9,20892,1), +(10,9,20983,1), +(11,1,4540,5), +(11,1,6948,1), +(11,1,23346,1), +(11,1,23473,1), +(11,1,23474,1), +(11,1,23475,1), +(11,2,159,5), +(11,2,2361,1), +(11,2,4540,5), +(11,2,6948,1), +(11,2,23476,1), +(11,2,23476,1), +(11,2,23477,1), +(11,3,25,1), +(11,3,159,5), +(11,3,2101,1), +(11,3,2504,1), +(11,3,2512,200), +(11,3,4540,5), +(11,3,6948,1), +(11,3,23344,1), +(11,3,23345,1), +(11,3,23348,1), +(11,5,36,1), +(11,5,59,1), +(11,5,159,5), +(11,5,1396,1), +(11,5,4540,5), +(11,5,6097,1), +(11,5,6948,1), +(11,5,23322,1), +(11,7,36,1), +(11,7,159,5), +(11,7,4540,5), +(11,7,6948,1), +(11,7,23344,1), +(11,7,23345,1), +(11,7,23348,1), +(11,8,35,1), +(11,8,159,5), +(11,8,4540,5), +(11,8,6948,1), +(11,8,23473,1), +(11,8,23475,1), +(11,8,23478,1), +(11,8,23479,1); +/*!40000 ALTER TABLE `playercreateinfo_item` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `playercreateinfo_spell` +-- + +DROP TABLE IF EXISTS `playercreateinfo_spell`; +CREATE TABLE `playercreateinfo_spell` ( + `race` tinyint(3) unsigned NOT NULL default '0', + `class` tinyint(3) unsigned NOT NULL default '0', + `Spell` mediumint(8) unsigned NOT NULL default '0', + `Note` varchar(255) default NULL, + `Active` tinyint(3) unsigned NOT NULL default '1', + PRIMARY KEY (`race`,`class`,`Spell`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `playercreateinfo_spell` +-- + +LOCK TABLES `playercreateinfo_spell` WRITE; +/*!40000 ALTER TABLE `playercreateinfo_spell` DISABLE KEYS */; +INSERT INTO `playercreateinfo_spell` VALUES +(1,1,78,'Heroic Strike',1), +(1,1,81,'Dodge',1), +(1,1,107,'Block',1), +(1,1,196,'One-Handed Axes',1), +(1,1,198,'One-Handed Maces',1), +(1,1,201,'One-Handed Swords',1), +(1,1,203,'Unarmed',1), +(1,1,204,'Defense',1), +(1,1,522,'SPELLDEFENSE(DND)',1), +(1,1,668,'Language Common',1), +(1,1,2382,'Generic',1), +(1,1,2457,'Battle Stance',1), +(1,1,2479,'Honorless Target',1), +(1,1,3050,'Detect',1), +(1,1,3365,'Opening',1), +(1,1,5301,'Defensive State(DND)',1), +(1,1,6233,'Closing',1), +(1,1,6246,'Closing',1), +(1,1,6247,'Opening',1), +(1,1,6477,'Opening',1), +(1,1,6478,'Opening',1), +(1,1,6603,'Attack',1), +(1,1,7266,'Duel',1), +(1,1,7267,'Grovel',1), +(1,1,7355,'Stuck',1), +(1,1,7376,'Defensive Stance Passive',0), +(1,1,7381,'Berserker Stance Passive',0), +(1,1,8386,'Attacking',1), +(1,1,8737,'Mail',1), +(1,1,9077,'Leather',1), +(1,1,9078,'Cloth',1), +(1,1,9116,'Shield',1), +(1,1,9125,'Generic',1), +(1,1,20597,'Sword Specialization',1), +(1,1,20598,'The Human Spirit',1), +(1,1,20599,'Diplomacy',1), +(1,1,20600,'Perception',1), +(1,1,20864,'Mace Specialization',1), +(1,1,21156,'Battle Stance Passive',0), +(1,1,21651,'Opening',1), +(1,1,21652,'Closing',1), +(1,1,22027,'Remove Insignia',1), +(1,1,22810,'Opening - No Text',1), +(1,1,32215,'Victorious State',1), +(1,2,81,'Dodge',1), +(1,2,107,'Block',1), +(1,2,198,'One-Handed Maces',1), +(1,2,199,'Two-Handed Maces',1), +(1,2,203,'Unarmed',1), +(1,2,204,'Defense',1), +(1,2,522,'SPELLDEFENSE(DND)',1), +(1,2,635,'Holy Light',1), +(1,2,668,'Language Common',1), +(1,2,2382,'Generic',1), +(1,2,2479,'Honorless Target',1), +(1,2,3050,'Detect',1), +(1,2,3365,'Opening',1), +(1,2,6233,'Closing',1), +(1,2,6246,'Closing',1), +(1,2,6247,'Opening',1), +(1,2,6477,'Opening',1), +(1,2,6478,'Opening',1), +(1,2,6603,'Attack',1), +(1,2,7266,'Duel',1), +(1,2,7267,'Grovel',1), +(1,2,7355,'Stuck',1), +(1,2,8386,'Attacking',1), +(1,2,8737,'Mail',1), +(1,2,9077,'Leather',1), +(1,2,9078,'Cloth',1), +(1,2,9116,'Shield',1), +(1,2,9125,'Generic',1), +(1,2,21084,'Seal of Righteousness',1), +(1,2,20597,'Sword Specialization',1), +(1,2,20598,'The Human Spirit',1), +(1,2,20599,'Diplomacy',1), +(1,2,20600,'Perception',1), +(1,2,20864,'Mace Specialization',1), +(1,2,21651,'Opening',1), +(1,2,21652,'Closing',1), +(1,2,22027,'Remove Insignia',1), +(1,2,22810,'Opening - No Text',1), +(1,2,27762,'Libram',1), +(1,4,81,'Dodge',1), +(1,4,203,'Unarmed',1), +(1,4,204,'Defense',1), +(1,4,522,'SPELLDEFENSE(DND)',1), +(1,4,668,'Language Common',1), +(1,4,1180,'Daggers',1), +(1,4,1752,'Sinister Strike',1), +(1,4,2098,'Eviscerate',1), +(1,4,2382,'Generic',1), +(1,4,2479,'Honorless Target',1), +(1,4,2567,'Thrown',1), +(1,4,2764,'Throw',1), +(1,4,3050,'Detect',1), +(1,4,3365,'Opening',1), +(1,4,6233,'Closing',1), +(1,4,6246,'Closing',1), +(1,4,6247,'Opening',1), +(1,4,6477,'Opening',1), +(1,4,6478,'Opening',1), +(1,4,6603,'Attack',1), +(1,4,7266,'Duel',1), +(1,4,7267,'Grovel',1), +(1,4,7355,'Stuck',1), +(1,4,8386,'Attacking',1), +(1,4,9077,'Leather',1), +(1,4,9078,'Cloth',1), +(1,4,9125,'Generic',1), +(1,4,16092,'Defensive State(DND)',1), +(1,4,20597,'Sword Specialization',1), +(1,4,20598,'The Human Spirit',1), +(1,4,20599,'Diplomacy',1), +(1,4,20600,'Perception',1), +(1,4,20864,'Mace Specialization',1), +(1,4,21184,'Rogue Passive(DND)',1), +(1,4,21651,'Opening',1), +(1,4,21652,'Closing',1), +(1,4,22027,'Remove Insignia',1), +(1,4,22810,'Opening - No Text',1), +(1,5,81,'Dodge',1), +(1,5,198,'One-Handed Maces',1), +(1,5,203,'Unarmed',1), +(1,5,204,'Defense',1), +(1,5,522,'SPELLDEFENSE(DND)',1), +(1,5,585,'Smite',1), +(1,5,668,'Language Common',1), +(1,5,2050,'Lesser Heal',1), +(1,5,2382,'Generic',1), +(1,5,2479,'Honorless Target',1), +(1,5,3050,'Detect',1), +(1,5,3365,'Opening',1), +(1,5,5009,'Wands',1), +(1,5,5019,'Shoot',1), +(1,5,6233,'Closing',1), +(1,5,6246,'Closing',1), +(1,5,6247,'Opening',1), +(1,5,6477,'Opening',1), +(1,5,6478,'Opening',1), +(1,5,6603,'Attack',1), +(1,5,7266,'Duel',1), +(1,5,7267,'Grovel',1), +(1,5,7355,'Stuck',1), +(1,5,8386,'Attacking',1), +(1,5,9078,'Cloth',1), +(1,5,9125,'Generic',1), +(1,5,20597,'Sword Specialization',1), +(1,5,20598,'The Human Spirit',1), +(1,5,20599,'Diplomacy',1), +(1,5,20600,'Perception',1), +(1,5,20864,'Mace Specialization',1), +(1,5,21651,'Opening',1), +(1,5,21652,'Closing',1), +(1,5,22027,'Remove Insignia',1), +(1,5,22810,'Opening - No Text',1), +(1,8,81,'Dodge',1), +(1,8,133,'Fireball',1), +(1,8,168,'Frost Armor',1), +(1,8,203,'Unarmed',1), +(1,8,204,'Defense',1), +(1,8,227,'Staves',1), +(1,8,522,'SPELLDEFENSE(DND)',1), +(1,8,668,'Language Common',1), +(1,8,2382,'Generic',1), +(1,8,2479,'Honorless Target',1), +(1,8,3050,'Detect',1), +(1,8,3365,'Opening',1), +(1,8,5009,'Wands',1), +(1,8,5019,'Shoot',1), +(1,8,6233,'Closing',1), +(1,8,6246,'Closing',1), +(1,8,6247,'Opening',1), +(1,8,6477,'Opening',1), +(1,8,6478,'Opening',1), +(1,8,6603,'Attack',1), +(1,8,7266,'Duel',1), +(1,8,7267,'Grovel',1), +(1,8,7355,'Stuck',1), +(1,8,8386,'Attacking',1), +(1,8,9078,'Cloth',1), +(1,8,9125,'Generic',1), +(1,8,20597,'Sword Specialization',1), +(1,8,20598,'The Human Spirit',1), +(1,8,20599,'Diplomacy',1), +(1,8,20600,'Perception',1), +(1,8,20864,'Mace Specialization',1), +(1,8,21651,'Opening',1), +(1,8,21652,'Closing',1), +(1,8,22027,'Remove Insignia',1), +(1,8,22810,'Opening - No Text',1), +(1,9,81,'Dodge',1), +(1,9,203,'Unarmed',1), +(1,9,204,'Defense',1), +(1,9,522,'SPELLDEFENSE(DND)',1), +(1,9,668,'Language Common',1), +(1,9,686,'Shadow Bolt',1), +(1,9,687,'Demon Skin',1), +(1,9,1180,'Daggers',1), +(1,9,2382,'Generic',1), +(1,9,2479,'Honorless Target',1), +(1,9,3050,'Detect',1), +(1,9,3365,'Opening',1), +(1,9,5009,'Wands',1), +(1,9,5019,'Shoot',1), +(1,9,6233,'Closing',1), +(1,9,6246,'Closing',1), +(1,9,6247,'Opening',1), +(1,9,6477,'Opening',1), +(1,9,6478,'Opening',1), +(1,9,6603,'Attack',1), +(1,9,7266,'Duel',1), +(1,9,7267,'Grovel',1), +(1,9,7355,'Stuck',1), +(1,9,8386,'Attacking',1), +(1,9,9078,'Cloth',1), +(1,9,9125,'Generic',1), +(1,9,20597,'Sword Specialization',1), +(1,9,20598,'The Human Spirit',1), +(1,9,20599,'Diplomacy',1), +(1,9,20600,'Perception',1), +(1,9,20864,'Mace Specialization',1), +(1,9,21651,'Opening',1), +(1,9,21652,'Closing',1), +(1,9,22027,'Remove Insignia',1), +(1,9,22810,'Opening - No Text',1), +(2,1,78,'Heroic Strike',1), +(2,1,81,'Dodge',1), +(2,1,107,'Block',1), +(2,1,196,'One-Handed Axes',1), +(2,1,197,'Two-Handed Axes',1), +(2,1,201,'One-Handed Swords',1), +(2,1,203,'Unarmed',1), +(2,1,204,'Defense',1), +(2,1,522,'SPELLDEFENSE(DND)',1), +(2,1,669,'Language Orcish',1), +(2,1,2382,'Generic',1), +(2,1,2457,'Battle Stance',1), +(2,1,2479,'Honorless Target',1), +(2,1,3050,'Detect',1), +(2,1,3365,'Opening',1), +(2,1,5301,'Defensive State(DND)',1), +(2,1,6233,'Closing',1), +(2,1,6246,'Closing',1), +(2,1,6247,'Opening',1), +(2,1,6477,'Opening',1), +(2,1,6478,'Opening',1), +(2,1,6603,'Attack',1), +(2,1,7266,'Duel',1), +(2,1,7267,'Grovel',1), +(2,1,7355,'Stuck',1), +(2,1,7376,'Defensive Stance Passive',0), +(2,1,7381,'Berserker Stance Passive',0), +(2,1,8386,'Attacking',1), +(2,1,8737,'Mail',1), +(2,1,9077,'Leather',1), +(2,1,9078,'Cloth',1), +(2,1,9116,'Shield',1), +(2,1,9125,'Generic',1), +(2,1,20572,'Blood Fury',1), +(2,1,20573,'Hardiness',1), +(2,1,20574,'Axe Specialization',1), +(2,1,21156,'Battle Stance Passive',0), +(2,1,21563,'Command',1), +(2,1,21651,'Opening',1), +(2,1,21652,'Closing',1), +(2,1,22027,'Remove Insignia',1), +(2,1,22810,'Opening - No Text',1), +(2,1,32215,'Victorious State',1), +(2,3,75,'Auto Shot',1), +(2,3,81,'Dodge',1), +(2,3,196,'One-Handed Axes',1), +(2,3,203,'Unarmed',1), +(2,3,204,'Defense',1), +(2,3,264,'Bows',1), +(2,3,522,'SPELLDEFENSE(DND)',1), +(2,3,669,'Language Orcish',1), +(2,3,2382,'Generic',1), +(2,3,2479,'Honorless Target',1), +(2,3,2973,'Raptor Strike',1), +(2,3,3050,'Detect',1), +(2,3,3365,'Opening',1), +(2,3,6233,'Closing',1), +(2,3,6246,'Closing',1), +(2,3,6247,'Opening',1), +(2,3,6477,'Opening',1), +(2,3,6478,'Opening',1), +(2,3,6603,'Attack',1), +(2,3,7266,'Duel',1), +(2,3,7267,'Grovel',1), +(2,3,7355,'Stuck',1), +(2,3,8386,'Attacking',1), +(2,3,9077,'Leather',1), +(2,3,9078,'Cloth',1), +(2,3,9125,'Generic',1), +(2,3,13358,'Defensive State(DND)',1), +(2,3,20572,'Blood Fury',1), +(2,3,20573,'Hardiness',1), +(2,3,20574,'Axe Specialization',1), +(2,3,20576,'Command',1), +(2,3,21651,'Opening',1), +(2,3,21652,'Closing',1), +(2,3,22027,'Remove Insignia',1), +(2,3,22810,'Opening - No Text',1), +(2,3,24949,'Defensive State 2(DND)',1), +(2,3,34082,'Advantaged State(DND)',1), +(2,4,81,'Dodge',1), +(2,4,203,'Unarmed',1), +(2,4,204,'Defense',1), +(2,4,522,'SPELLDEFENSE(DND)',1), +(2,4,669,'Language Orcish',1), +(2,4,1180,'Daggers',1), +(2,4,1752,'Sinister Strike',1), +(2,4,2098,'Eviscerate',1), +(2,4,2382,'Generic',1), +(2,4,2479,'Honorless Target',1), +(2,4,2567,'Thrown',1), +(2,4,2764,'Throw',1), +(2,4,3050,'Detect',1), +(2,4,3365,'Opening',1), +(2,4,6233,'Closing',1), +(2,4,6246,'Closing',1), +(2,4,6247,'Opening',1), +(2,4,6477,'Opening',1), +(2,4,6478,'Opening',1), +(2,4,6603,'Attack',1), +(2,4,7266,'Duel',1), +(2,4,7267,'Grovel',1), +(2,4,7355,'Stuck',1), +(2,4,8386,'Attacking',1), +(2,4,9077,'Leather',1), +(2,4,9078,'Cloth',1), +(2,4,9125,'Generic',1), +(2,4,16092,'Defensive State(DND)',1), +(2,4,20572,'Blood Fury',1), +(2,4,20573,'Hardiness',1), +(2,4,20574,'Axe Specialization',1), +(2,4,21184,'Rogue Passive(DND)',1), +(2,4,21563,'Command',1), +(2,4,21651,'Opening',1), +(2,4,21652,'Closing',1), +(2,4,22027,'Remove Insignia',1), +(2,4,22810,'Opening - No Text',1), +(2,7,81,'Dodge',1), +(2,7,107,'Block',1), +(2,7,198,'One-Handed Maces',1), +(2,7,203,'Unarmed',1), +(2,7,204,'Defense',1), +(2,7,227,'Staves',1), +(2,7,331,'Healing Wave',1), +(2,7,403,'Lightning Bolt',1), +(2,7,522,'SPELLDEFENSE(DND)',1), +(2,7,669,'Language Orcish',1), +(2,7,2382,'Generic',1), +(2,7,2479,'Honorless Target',1), +(2,7,3050,'Detect',1), +(2,7,3365,'Opening',1), +(2,7,6233,'Closing',1), +(2,7,6246,'Closing',1), +(2,7,6247,'Opening',1), +(2,7,6477,'Opening',1), +(2,7,6478,'Opening',1), +(2,7,6603,'Attack',1), +(2,7,7266,'Duel',1), +(2,7,7267,'Grovel',1), +(2,7,7355,'Stuck',1), +(2,7,8386,'Attacking',1), +(2,7,9077,'Leather',1), +(2,7,9078,'Cloth',1), +(2,7,9116,'Shield',1), +(2,7,9125,'Generic',1), +(2,7,20573,'Hardiness',1), +(2,7,20574,'Axe Specialization',1), +(2,7,21563,'Command',1), +(2,7,21651,'Opening',1), +(2,7,21652,'Closing',1), +(2,7,22027,'Remove Insignia',1), +(2,7,22810,'Opening - No Text',1), +(2,7,27763,'Totem',1), +(2,7,33697,'Blood Fury',1), +(2,9,81,'Dodge',1), +(2,9,203,'Unarmed',1), +(2,9,204,'Defense',1), +(2,9,522,'SPELLDEFENSE(DND)',1), +(2,9,669,'Language Orcish',1), +(2,9,686,'Shadow Bolt',1), +(2,9,687,'Demon Skin',1), +(2,9,1180,'Daggers',1), +(2,9,2382,'Generic',1), +(2,9,2479,'Honorless Target',1), +(2,9,3050,'Detect',1), +(2,9,3365,'Opening',1), +(2,9,5009,'Wands',1), +(2,9,5019,'Shoot',1), +(2,9,6233,'Closing',1), +(2,9,6246,'Closing',1), +(2,9,6247,'Opening',1), +(2,9,6477,'Opening',1), +(2,9,6478,'Opening',1), +(2,9,6603,'Attack',1), +(2,9,7266,'Duel',1), +(2,9,7267,'Grovel',1), +(2,9,7355,'Stuck',1), +(2,9,8386,'Attacking',1), +(2,9,9078,'Cloth',1), +(2,9,9125,'Generic',1), +(2,9,20573,'Hardiness',1), +(2,9,20574,'Axe Specialization',1), +(2,9,20575,'Command',1), +(2,9,21651,'Opening',1), +(2,9,21652,'Closing',1), +(2,9,22027,'Remove Insignia',1), +(2,9,22810,'Opening - No Text',1), +(2,9,33702,'Blood Fury',1), +(3,1,78,'Heroic Strike',1), +(3,1,81,'Dodge',1), +(3,1,107,'Block',1), +(3,1,196,'One-Handed Axes',1), +(3,1,197,'Two-Handed Axes',1), +(3,1,198,'One-Handed Maces',1), +(3,1,203,'Unarmed',1), +(3,1,204,'Defense',1), +(3,1,522,'SPELLDEFENSE(DND)',1), +(3,1,668,'Language Common',1), +(3,1,672,'Language Dwarven',1), +(3,1,2382,'Generic',1), +(3,1,2457,'Battle Stance',1), +(3,1,2479,'Honorless Target',1), +(3,1,2481,'Find Treasure',1), +(3,1,3050,'Detect',1), +(3,1,3365,'Opening',1), +(3,1,5301,'Defensive State(DND)',1), +(3,1,6233,'Closing',1), +(3,1,6246,'Closing',1), +(3,1,6247,'Opening',1), +(3,1,6477,'Opening',1), +(3,1,6478,'Opening',1), +(3,1,6603,'Attack',1), +(3,1,7266,'Duel',1), +(3,1,7267,'Grovel',1), +(3,1,7355,'Stuck',1), +(3,1,7376,'Defensive Stance Passive',0), +(3,1,7381,'Berserker Stance Passive',0), +(3,1,8386,'Attacking',1), +(3,1,8737,'Mail',1), +(3,1,9077,'Leather',1), +(3,1,9078,'Cloth',1), +(3,1,9116,'Shield',1), +(3,1,9125,'Generic',1), +(3,1,20594,'Stoneform',1), +(3,1,20595,'Gun Specialization',1), +(3,1,20596,'Frost Resistance',1), +(3,1,21156,'Battle Stance Passive',0), +(3,1,21651,'Opening',1), +(3,1,21652,'Closing',1), +(3,1,22027,'Remove Insignia',1), +(3,1,22810,'Opening - No Text',1), +(3,1,32215,'Victorious State',1), +(3,2,81,'Dodge',1), +(3,2,107,'Block',1), +(3,2,198,'One-Handed Maces',1), +(3,2,199,'Two-Handed Maces',1), +(3,2,203,'Unarmed',1), +(3,2,204,'Defense',1), +(3,2,522,'SPELLDEFENSE(DND)',1), +(3,2,635,'Holy Light',1), +(3,2,668,'Language Common',1), +(3,2,672,'Language Dwarven',1), +(3,2,2382,'Generic',1), +(3,2,2479,'Honorless Target',1), +(3,2,2481,'Find Treasure',1), +(3,2,3050,'Detect',1), +(3,2,3365,'Opening',1), +(3,2,6233,'Closing',1), +(3,2,6246,'Closing',1), +(3,2,6247,'Opening',1), +(3,2,6477,'Opening',1), +(3,2,6478,'Opening',1), +(3,2,6603,'Attack',1), +(3,2,7266,'Duel',1), +(3,2,7267,'Grovel',1), +(3,2,7355,'Stuck',1), +(3,2,8386,'Attacking',1), +(3,2,8737,'Mail',1), +(3,2,9077,'Leather',1), +(3,2,9078,'Cloth',1), +(3,2,9116,'Shield',1), +(3,2,9125,'Generic',1), +(3,2,21084,'Seal of Righteousness',1), +(3,2,20594,'Stoneform',1), +(3,2,20595,'Gun Specialization',1), +(3,2,20596,'Frost Resistance',1), +(3,2,21651,'Opening',1), +(3,2,21652,'Closing',1), +(3,2,22027,'Remove Insignia',1), +(3,2,22810,'Opening - No Text',1), +(3,2,27762,'Libram',1), +(3,3,75,'Auto Shot',1), +(3,3,81,'Dodge',1), +(3,3,196,'One-Handed Axes',1), +(3,3,203,'Unarmed',1), +(3,3,204,'Defense',1), +(3,3,266,'Guns',1), +(3,3,522,'SPELLDEFENSE(DND)',1), +(3,3,668,'Language Common',1), +(3,3,672,'Language Dwarven',1), +(3,3,2382,'Generic',1), +(3,3,2479,'Honorless Target',1), +(3,3,2481,'Find Treasure',1), +(3,3,2973,'Raptor Strike',1), +(3,3,3050,'Detect',1), +(3,3,3365,'Opening',1), +(3,3,6233,'Closing',1), +(3,3,6246,'Closing',1), +(3,3,6247,'Opening',1), +(3,3,6477,'Opening',1), +(3,3,6478,'Opening',1), +(3,3,6603,'Attack',1), +(3,3,7266,'Duel',1), +(3,3,7267,'Grovel',1), +(3,3,7355,'Stuck',1), +(3,3,8386,'Attacking',1), +(3,3,9077,'Leather',1), +(3,3,9078,'Cloth',1), +(3,3,9125,'Generic',1), +(3,3,13358,'Defensive State(DND)',1), +(3,3,20594,'Stoneform',1), +(3,3,20595,'Gun Specialization',1), +(3,3,20596,'Frost Resistance',1), +(3,3,21651,'Opening',1), +(3,3,21652,'Closing',1), +(3,3,22027,'Remove Insignia',1), +(3,3,22810,'Opening - No Text',1), +(3,3,24949,'Defensive State 2(DND)',1), +(3,3,34082,'Advantaged State(DND)',1), +(3,4,81,'Dodge',1), +(3,4,203,'Unarmed',1), +(3,4,204,'Defense',1), +(3,4,522,'SPELLDEFENSE(DND)',1), +(3,4,668,'Language Common',1), +(3,4,672,'Language Dwarven',1), +(3,4,1180,'Daggers',1), +(3,4,1752,'Sinister Strike',1), +(3,4,2098,'Eviscerate',1), +(3,4,2382,'Generic',1), +(3,4,2479,'Honorless Target',1), +(3,4,2481,'Find Treasure',1), +(3,4,2567,'Thrown',1), +(3,4,2764,'Throw',1), +(3,4,3050,'Detect',1), +(3,4,3365,'Opening',1), +(3,4,6233,'Closing',1), +(3,4,6246,'Closing',1), +(3,4,6247,'Opening',1), +(3,4,6477,'Opening',1), +(3,4,6478,'Opening',1), +(3,4,6603,'Attack',1), +(3,4,7266,'Duel',1), +(3,4,7267,'Grovel',1), +(3,4,7355,'Stuck',1), +(3,4,8386,'Attacking',1), +(3,4,9077,'Leather',1), +(3,4,9078,'Cloth',1), +(3,4,9125,'Generic',1), +(3,4,16092,'Defensive State(DND)',1), +(3,4,20594,'Stoneform',1), +(3,4,20595,'Gun Specialization',1), +(3,4,20596,'Frost Resistance',1), +(3,4,21184,'Rogue Passive(DND)',1), +(3,4,21651,'Opening',1), +(3,4,21652,'Closing',1), +(3,4,22027,'Remove Insignia',1), +(3,4,22810,'Opening - No Text',1), +(3,5,81,'Dodge',1), +(3,5,198,'One-Handed Maces',1), +(3,5,203,'Unarmed',1), +(3,5,204,'Defense',1), +(3,5,522,'SPELLDEFENSE(DND)',1), +(3,5,585,'Smite',1), +(3,5,668,'Language Common',1), +(3,5,672,'Language Dwarven',1), +(3,5,2050,'Lesser Heal',1), +(3,5,2382,'Generic',1), +(3,5,2479,'Honorless Target',1), +(3,5,2481,'Find Treasure',1), +(3,5,3050,'Detect',1), +(3,5,3365,'Opening',1), +(3,5,5009,'Wands',1), +(3,5,5019,'Shoot',1), +(3,5,6233,'Closing',1), +(3,5,6246,'Closing',1), +(3,5,6247,'Opening',1), +(3,5,6477,'Opening',1), +(3,5,6478,'Opening',1), +(3,5,6603,'Attack',1), +(3,5,7266,'Duel',1), +(3,5,7267,'Grovel',1), +(3,5,7355,'Stuck',1), +(3,5,8386,'Attacking',1), +(3,5,9078,'Cloth',1), +(3,5,9125,'Generic',1), +(3,5,20594,'Stoneform',1), +(3,5,20595,'Gun Specialization',1), +(3,5,20596,'Frost Resistance',1), +(3,5,21651,'Opening',1), +(3,5,21652,'Closing',1), +(3,5,22027,'Remove Insignia',1), +(3,5,22810,'Opening - No Text',1), +(4,1,78,'Heroic Strike',1), +(4,1,81,'Dodge',1), +(4,1,107,'Block',1), +(4,1,198,'One-Handed Maces',1), +(4,1,201,'One-Handed Swords',1), +(4,1,203,'Unarmed',1), +(4,1,204,'Defense',1), +(4,1,522,'SPELLDEFENSE(DND)',1), +(4,1,668,'Language Common',1), +(4,1,671,'Language Darnassian',1), +(4,1,1180,'Daggers',1), +(4,1,2382,'Generic',1), +(4,1,2457,'Battle Stance',1), +(4,1,2479,'Honorless Target',1), +(4,1,3050,'Detect',1), +(4,1,3365,'Opening',1), +(4,1,5301,'Defensive State(DND)',1), +(4,1,6233,'Closing',1), +(4,1,6246,'Closing',1), +(4,1,6247,'Opening',1), +(4,1,6477,'Opening',1), +(4,1,6478,'Opening',1), +(4,1,6603,'Attack',1), +(4,1,7266,'Duel',1), +(4,1,7267,'Grovel',1), +(4,1,7355,'Stuck',1), +(4,1,7376,'Defensive Stance Passive',0), +(4,1,7381,'Berserker Stance Passive',0), +(4,1,8386,'Attacking',1), +(4,1,8737,'Mail',1), +(4,1,9077,'Leather',1), +(4,1,9078,'Cloth',1), +(4,1,9116,'Shield',1), +(4,1,9125,'Generic',1), +(4,1,20580,'Shadowmeld',1), +(4,1,20582,'Quickness',1), +(4,1,20583,'Nature Resistance',1), +(4,1,20585,'Wisp Spirit',1), +(4,1,21009,'Shadowmeld Passive',1), +(4,1,21156,'Battle Stance Passive',0), +(4,1,21651,'Opening',1), +(4,1,21652,'Closing',1), +(4,1,22027,'Remove Insignia',1), +(4,1,22810,'Opening - No Text',1), +(4,1,32215,'Victorious State',1), +(4,3,75,'Auto Shot',1), +(4,3,81,'Dodge',1), +(4,3,203,'Unarmed',1), +(4,3,204,'Defense',1), +(4,3,264,'Bows',1), +(4,3,522,'SPELLDEFENSE(DND)',1), +(4,3,668,'Language Common',1), +(4,3,671,'Language Darnassian',1), +(4,3,1180,'Daggers',1), +(4,3,2382,'Generic',1), +(4,3,2479,'Honorless Target',1), +(4,3,2973,'Raptor Strike',1), +(4,3,3050,'Detect',1), +(4,3,3365,'Opening',1), +(4,3,6233,'Closing',1), +(4,3,6246,'Closing',1), +(4,3,6247,'Opening',1), +(4,3,6477,'Opening',1), +(4,3,6478,'Opening',1), +(4,3,6603,'Attack',1), +(4,3,7266,'Duel',1), +(4,3,7267,'Grovel',1), +(4,3,7355,'Stuck',1), +(4,3,8386,'Attacking',1), +(4,3,9077,'Leather',1), +(4,3,9078,'Cloth',1), +(4,3,9125,'Generic',1), +(4,3,13358,'Defensive State(DND)',1), +(4,3,20580,'Shadowmeld',1), +(4,3,20582,'Quickness',1), +(4,3,20583,'Nature Resistance',1), +(4,3,20585,'Wisp Spirit',1), +(4,3,21009,'Shadowmeld Passive',1), +(4,3,21651,'Opening',1), +(4,3,21652,'Closing',1), +(4,3,22027,'Remove Insignia',1), +(4,3,22810,'Opening - No Text',1), +(4,3,24949,'Defensive State 2(DND)',1), +(4,3,34082,'Advantaged State(DND)',1), +(4,4,81,'Dodge',1), +(4,4,203,'Unarmed',1), +(4,4,204,'Defense',1), +(4,4,522,'SPELLDEFENSE(DND)',1), +(4,4,668,'Language Common',1), +(4,4,671,'Language Darnassian',1), +(4,4,1180,'Daggers',1), +(4,4,1752,'Sinister Strike',1), +(4,4,2098,'Eviscerate',1), +(4,4,2382,'Generic',1), +(4,4,2479,'Honorless Target',1), +(4,4,2567,'Thrown',1), +(4,4,2764,'Throw',1), +(4,4,3050,'Detect',1), +(4,4,3365,'Opening',1), +(4,4,6233,'Closing',1), +(4,4,6246,'Closing',1), +(4,4,6247,'Opening',1), +(4,4,6477,'Opening',1), +(4,4,6478,'Opening',1), +(4,4,6603,'Attack',1), +(4,4,7266,'Duel',1), +(4,4,7267,'Grovel',1), +(4,4,7355,'Stuck',1), +(4,4,8386,'Attacking',1), +(4,4,9077,'Leather',1), +(4,4,9078,'Cloth',1), +(4,4,9125,'Generic',1), +(4,4,16092,'Defensive State(DND)',1), +(4,4,20580,'Shadowmeld',1), +(4,4,20582,'Quickness',1), +(4,4,20583,'Nature Resistance',1), +(4,4,20585,'Wisp Spirit',1), +(4,4,21009,'Shadowmeld Passive',1), +(4,4,21184,'Rogue Passive(DND)',1), +(4,4,21651,'Opening',1), +(4,4,21652,'Closing',1), +(4,4,22027,'Remove Insignia',1), +(4,4,22810,'Opening - No Text',1), +(4,5,81,'Dodge',1), +(4,5,198,'One-Handed Maces',1), +(4,5,203,'Unarmed',1), +(4,5,204,'Defense',1), +(4,5,522,'SPELLDEFENSE(DND)',1), +(4,5,585,'Smite',1), +(4,5,668,'Language Common',1), +(4,5,671,'Language Darnassian',1), +(4,5,2050,'Lesser Heal',1), +(4,5,2382,'Generic',1), +(4,5,2479,'Honorless Target',1), +(4,5,3050,'Detect',1), +(4,5,3365,'Opening',1), +(4,5,5009,'Wands',1), +(4,5,5019,'Shoot',1), +(4,5,6233,'Closing',1), +(4,5,6246,'Closing',1), +(4,5,6247,'Opening',1), +(4,5,6477,'Opening',1), +(4,5,6478,'Opening',1), +(4,5,6603,'Attack',1), +(4,5,7266,'Duel',1), +(4,5,7267,'Grovel',1), +(4,5,7355,'Stuck',1), +(4,5,8386,'Attacking',1), +(4,5,9078,'Cloth',1), +(4,5,9125,'Generic',1), +(4,5,20580,'Shadowmeld',1), +(4,5,20582,'Quickness',1), +(4,5,20583,'Nature Resistance',1), +(4,5,20585,'Wisp Spirit',1), +(4,5,21009,'Shadowmeld Passive',1), +(4,5,21651,'Opening',1), +(4,5,21652,'Closing',1), +(4,5,22027,'Remove Insignia',1), +(4,5,22810,'Opening - No Text',1), +(4,11,81,'Dodge',1), +(4,11,203,'Unarmed',1), +(4,11,204,'Defense',1), +(4,11,227,'Staves',1), +(4,11,522,'SPELLDEFENSE(DND)',1), +(4,11,668,'Language Common',1), +(4,11,671,'Language Darnassian',1), +(4,11,1178,'Bear Form(Passive)',0), +(4,11,1180,'Daggers',1), +(4,11,2382,'Generic',1), +(4,11,2479,'Honorless Target',1), +(4,11,3025,'Cat Form(Passive)',0), +(4,11,3050,'Detect',1), +(4,11,3365,'Opening',1), +(4,11,5176,'Wrath',1), +(4,11,5185,'Healing Touch',1), +(4,11,5419,'Travel Form(Passive)',0), +(4,11,5420,'Tree of Life',0), +(4,11,5421,'Aquatic Form(Passive)',0), +(4,11,6233,'Closing',1), +(4,11,6246,'Closing',1), +(4,11,6247,'Opening',1), +(4,11,6477,'Opening',1), +(4,11,6478,'Opening',1), +(4,11,6603,'Attack',1), +(4,11,7266,'Duel',1), +(4,11,7267,'Grovel',1), +(4,11,7355,'Stuck',1), +(4,11,8386,'Attacking',1), +(4,11,9077,'Leather',1), +(4,11,9078,'Cloth',1), +(4,11,9125,'Generic',1), +(4,11,9635,'Dire Bear Form(Passive)',0), +(4,11,20580,'Shadowmeld',1), +(4,11,20582,'Quickness',1), +(4,11,20583,'Nature Resistance',1), +(4,11,20585,'Wisp Spirit',1), +(4,11,21009,'Shadowmeld Passive',1), +(4,11,21178,'Bear Form(Passive2)',0), +(4,11,21651,'Opening',1), +(4,11,21652,'Closing',1), +(4,11,22027,'Remove Insignia',1), +(4,11,22810,'Opening - No Text',1), +(4,11,24905,'Moonkin Form(Passive)',0), +(4,11,27764,'Fetish',1), +(4,11,33948,'Flight Form(Passive)',0), +(4,11,34123,'Tree of Life(Passive)',0), +(4,11,40121,'Swift Flight Form(Passive)',0), +(5,1,78,'Heroic Strike',1), +(5,1,81,'Dodge',1), +(5,1,107,'Block',1), +(5,1,201,'One-Handed Swords',1), +(5,1,202,'Two-Handed Swords',1), +(5,1,203,'Unarmed',1), +(5,1,204,'Defense',1), +(5,1,522,'SPELLDEFENSE(DND)',1), +(5,1,669,'Language Orcish',1), +(5,1,1180,'Daggers',1), +(5,1,2382,'Generic',1), +(5,1,2457,'Battle Stance',1), +(5,1,2479,'Honorless Target',1), +(5,1,3050,'Detect',1), +(5,1,3365,'Opening',1), +(5,1,5227,'Underwater Breathing',1), +(5,1,5301,'Defensive State(DND)',1), +(5,1,6233,'Closing',1), +(5,1,6246,'Closing',1), +(5,1,6247,'Opening',1), +(5,1,6477,'Opening',1), +(5,1,6478,'Opening',1), +(5,1,6603,'Attack',1), +(5,1,7266,'Duel',1), +(5,1,7267,'Grovel',1), +(5,1,7355,'Stuck',1), +(5,1,7376,'Defensive Stance Passive',0), +(5,1,7381,'Berserker Stance Passive',0), +(5,1,7744,'Will of the Forsaken',1), +(5,1,8386,'Attacking',1), +(5,1,8737,'Mail',1), +(5,1,9077,'Leather',1), +(5,1,9078,'Cloth',1), +(5,1,9116,'Shield',1), +(5,1,9125,'Generic',1), +(5,1,17737,'Language Gutterspeak',1), +(5,1,20577,'Cannibalize',1), +(5,1,20579,'Shadow Resistance',1), +(5,1,21156,'Battle Stance Passive',0), +(5,1,21651,'Opening',1), +(5,1,21652,'Closing',1), +(5,1,22027,'Remove Insignia',1), +(5,1,22810,'Opening - No Text',1), +(5,1,32215,'Victorious State',1), +(5,4,81,'Dodge',1), +(5,4,203,'Unarmed',1), +(5,4,204,'Defense',1), +(5,4,522,'SPELLDEFENSE(DND)',1), +(5,4,669,'Language Orcish',1), +(5,4,1180,'Daggers',1), +(5,4,1752,'Sinister Strike',1), +(5,4,2098,'Eviscerate',1), +(5,4,2382,'Generic',1), +(5,4,2479,'Honorless Target',1), +(5,4,2567,'Thrown',1), +(5,4,2764,'Throw',1), +(5,4,3050,'Detect',1), +(5,4,3365,'Opening',1), +(5,4,5227,'Underwater Breathing',1), +(5,4,6233,'Closing',1), +(5,4,6246,'Closing',1), +(5,4,6247,'Opening',1), +(5,4,6477,'Opening',1), +(5,4,6478,'Opening',1), +(5,4,6603,'Attack',1), +(5,4,7266,'Duel',1), +(5,4,7267,'Grovel',1), +(5,4,7355,'Stuck',1), +(5,4,7744,'Will of the Forsaken',1), +(5,4,8386,'Attacking',1), +(5,4,9077,'Leather',1), +(5,4,9078,'Cloth',1), +(5,4,9125,'Generic',1), +(5,4,16092,'Defensive State(DND)',1), +(5,4,17737,'Language Gutterspeak',1), +(5,4,20577,'Cannibalize',1), +(5,4,20579,'Shadow Resistance',1), +(5,4,21184,'Rogue Passive(DND)',1), +(5,4,21651,'Opening',1), +(5,4,21652,'Closing',1), +(5,4,22027,'Remove Insignia',1), +(5,4,22810,'Opening - No Text',1), +(5,5,81,'Dodge',1), +(5,5,198,'One-Handed Maces',1), +(5,5,203,'Unarmed',1), +(5,5,204,'Defense',1), +(5,5,522,'SPELLDEFENSE(DND)',1), +(5,5,585,'Smite',1), +(5,5,669,'Language Orcish',1), +(5,5,2050,'Lesser Heal',1), +(5,5,2382,'Generic',1), +(5,5,2479,'Honorless Target',1), +(5,5,3050,'Detect',1), +(5,5,3365,'Opening',1), +(5,5,5009,'Wands',1), +(5,5,5019,'Shoot',1), +(5,5,5227,'Underwater Breathing',1), +(5,5,6233,'Closing',1), +(5,5,6246,'Closing',1), +(5,5,6247,'Opening',1), +(5,5,6477,'Opening',1), +(5,5,6478,'Opening',1), +(5,5,6603,'Attack',1), +(5,5,7266,'Duel',1), +(5,5,7267,'Grovel',1), +(5,5,7355,'Stuck',1), +(5,5,7744,'Will of the Forsaken',1), +(5,5,8386,'Attacking',1), +(5,5,9078,'Cloth',1), +(5,5,9125,'Generic',1), +(5,5,17737,'Language Gutterspeak',1), +(5,5,20577,'Cannibalize',1), +(5,5,20579,'Shadow Resistance',1), +(5,5,21651,'Opening',1), +(5,5,21652,'Closing',1), +(5,5,22027,'Remove Insignia',1), +(5,5,22810,'Opening - No Text',1), +(5,8,81,'Dodge',1), +(5,8,133,'Fireball',1), +(5,8,168,'Frost Armor',1), +(5,8,203,'Unarmed',1), +(5,8,204,'Defense',1), +(5,8,227,'Staves',1), +(5,8,522,'SPELLDEFENSE(DND)',1), +(5,8,669,'Language Orcish',1), +(5,8,2382,'Generic',1), +(5,8,2479,'Honorless Target',1), +(5,8,3050,'Detect',1), +(5,8,3365,'Opening',1), +(5,8,5009,'Wands',1), +(5,8,5019,'Shoot',1), +(5,8,5227,'Underwater Breathing',1), +(5,8,6233,'Closing',1), +(5,8,6246,'Closing',1), +(5,8,6247,'Opening',1), +(5,8,6477,'Opening',1), +(5,8,6478,'Opening',1), +(5,8,6603,'Attack',1), +(5,8,7266,'Duel',1), +(5,8,7267,'Grovel',1), +(5,8,7355,'Stuck',1), +(5,8,7744,'Will of the Forsaken',1), +(5,8,8386,'Attacking',1), +(5,8,9078,'Cloth',1), +(5,8,9125,'Generic',1), +(5,8,17737,'Language Gutterspeak',1), +(5,8,20577,'Cannibalize',1), +(5,8,20579,'Shadow Resistance',1), +(5,8,21651,'Opening',1), +(5,8,21652,'Closing',1), +(5,8,22027,'Remove Insignia',1), +(5,8,22810,'Opening - No Text',1), +(5,9,81,'Dodge',1), +(5,9,203,'Unarmed',1), +(5,9,204,'Defense',1), +(5,9,522,'SPELLDEFENSE(DND)',1), +(5,9,669,'Language Orcish',1), +(5,9,686,'Shadow Bolt',1), +(5,9,687,'Demon Skin',1), +(5,9,1180,'Daggers',1), +(5,9,2382,'Generic',1), +(5,9,2479,'Honorless Target',1), +(5,9,3050,'Detect',1), +(5,9,3365,'Opening',1), +(5,9,5009,'Wands',1), +(5,9,5019,'Shoot',1), +(5,9,5227,'Underwater Breathing',1), +(5,9,6233,'Closing',1), +(5,9,6246,'Closing',1), +(5,9,6247,'Opening',1), +(5,9,6477,'Opening',1), +(5,9,6478,'Opening',1), +(5,9,6603,'Attack',1), +(5,9,7266,'Duel',1), +(5,9,7267,'Grovel',1), +(5,9,7355,'Stuck',1), +(5,9,7744,'Will of the Forsaken',1), +(5,9,8386,'Attacking',1), +(5,9,9078,'Cloth',1), +(5,9,9125,'Generic',1), +(5,9,17737,'Language Gutterspeak',1), +(5,9,20577,'Cannibalize',1), +(5,9,20579,'Shadow Resistance',1), +(5,9,21651,'Opening',1), +(5,9,21652,'Closing',1), +(5,9,22027,'Remove Insignia',1), +(5,9,22810,'Opening - No Text',1), +(6,1,78,'Heroic Strike',1), +(6,1,81,'Dodge',1), +(6,1,107,'Block',1), +(6,1,196,'One-Handed Axes',1), +(6,1,198,'One-Handed Maces',1), +(6,1,199,'Two-Handed Maces',1), +(6,1,203,'Unarmed',1), +(6,1,204,'Defense',1), +(6,1,522,'SPELLDEFENSE(DND)',1), +(6,1,669,'Language Orcish',1), +(6,1,670,'Language Taurahe',1), +(6,1,2382,'Generic',1), +(6,1,2457,'Battle Stance',1), +(6,1,2479,'Honorless Target',1), +(6,1,3050,'Detect',1), +(6,1,3365,'Opening',1), +(6,1,5301,'Defensive State(DND)',1), +(6,1,6233,'Closing',1), +(6,1,6246,'Closing',1), +(6,1,6247,'Opening',1), +(6,1,6477,'Opening',1), +(6,1,6478,'Opening',1), +(6,1,6603,'Attack',1), +(6,1,7266,'Duel',1), +(6,1,7267,'Grovel',1), +(6,1,7355,'Stuck',1), +(6,1,7376,'Defensive Stance Passive',0), +(6,1,7381,'Berserker Stance Passive',0), +(6,1,8386,'Attacking',1), +(6,1,8737,'Mail',1), +(6,1,9077,'Leather',1), +(6,1,9078,'Cloth',1), +(6,1,9116,'Shield',1), +(6,1,9125,'Generic',1), +(6,1,20549,'War Stomp',1), +(6,1,20550,'Endurance',1), +(6,1,20551,'Nature Resistance',1), +(6,1,20552,'Cultivation',1), +(6,1,21156,'Battle Stance Passive',0), +(6,1,21651,'Opening',1), +(6,1,21652,'Closing',1), +(6,1,22027,'Remove Insignia',1), +(6,1,22810,'Opening - No Text',1), +(6,1,32215,'Victorious State',1), +(6,3,75,'Auto Shot',1), +(6,3,81,'Dodge',1), +(6,3,196,'One-Handed Axes',1), +(6,3,203,'Unarmed',1), +(6,3,204,'Defense',1), +(6,3,266,'Guns',1), +(6,3,522,'SPELLDEFENSE(DND)',1), +(6,3,669,'Language Orcish',1), +(6,3,670,'Language Taurahe',1), +(6,3,2382,'Generic',1), +(6,3,2479,'Honorless Target',1), +(6,3,2973,'Raptor Strike',1), +(6,3,3050,'Detect',1), +(6,3,3365,'Opening',1), +(6,3,6233,'Closing',1), +(6,3,6246,'Closing',1), +(6,3,6247,'Opening',1), +(6,3,6477,'Opening',1), +(6,3,6478,'Opening',1), +(6,3,6603,'Attack',1), +(6,3,7266,'Duel',1), +(6,3,7267,'Grovel',1), +(6,3,7355,'Stuck',1), +(6,3,8386,'Attacking',1), +(6,3,9077,'Leather',1), +(6,3,9078,'Cloth',1), +(6,3,9125,'Generic',1), +(6,3,13358,'Defensive State(DND)',1), +(6,3,20549,'War Stomp',1), +(6,3,20550,'Endurance',1), +(6,3,20551,'Nature Resistance',1), +(6,3,20552,'Cultivation',1), +(6,3,21651,'Opening',1), +(6,3,21652,'Closing',1), +(6,3,22027,'Remove Insignia',1), +(6,3,22810,'Opening - No Text',1), +(6,3,24949,'Defensive State 2(DND)',1), +(6,3,34082,'Advantaged State(DND)',1), +(6,7,81,'Dodge',1), +(6,7,107,'Block',1), +(6,7,198,'One-Handed Maces',1), +(6,7,203,'Unarmed',1), +(6,7,204,'Defense',1), +(6,7,227,'Staves',1), +(6,7,331,'Healing Wave',1), +(6,7,403,'Lightning Bolt',1), +(6,7,522,'SPELLDEFENSE(DND)',1), +(6,7,669,'Language Orcish',1), +(6,7,670,'Language Taurahe',1), +(6,7,2382,'Generic',1), +(6,7,2479,'Honorless Target',1), +(6,7,3050,'Detect',1), +(6,7,3365,'Opening',1), +(6,7,6233,'Closing',1), +(6,7,6246,'Closing',1), +(6,7,6247,'Opening',1), +(6,7,6477,'Opening',1), +(6,7,6478,'Opening',1), +(6,7,6603,'Attack',1), +(6,7,7266,'Duel',1), +(6,7,7267,'Grovel',1), +(6,7,7355,'Stuck',1), +(6,7,8386,'Attacking',1), +(6,7,9077,'Leather',1), +(6,7,9078,'Cloth',1), +(6,7,9116,'Shield',1), +(6,7,9125,'Generic',1), +(6,7,20549,'War Stomp',1), +(6,7,20550,'Endurance',1), +(6,7,20551,'Nature Resistance',1), +(6,7,20552,'Cultivation',1), +(6,7,21651,'Opening',1), +(6,7,21652,'Closing',1), +(6,7,22027,'Remove Insignia',1), +(6,7,22810,'Opening - No Text',1), +(6,7,27763,'Totem',1), +(6,11,81,'Dodge',1), +(6,11,198,'One-Handed Maces',1), +(6,11,203,'Unarmed',1), +(6,11,204,'Defense',1), +(6,11,227,'Staves',1), +(6,11,522,'SPELLDEFENSE(DND)',1), +(6,11,669,'Language Orcish',1), +(6,11,670,'Language Taurahe',1), +(6,11,1178,'Bear Form(Passive)',0), +(6,11,2382,'Generic',1), +(6,11,2479,'Honorless Target',1), +(6,11,3025,'Cat Form(Passive)',0), +(6,11,3050,'Detect',1), +(6,11,3365,'Opening',1), +(6,11,5176,'Wrath',1), +(6,11,5185,'Healing Touch',1), +(6,11,5419,'Travel Form(Passive)',0), +(6,11,5420,'Tree of Life',0), +(6,11,5421,'Aquatic Form(Passive)',0), +(6,11,6233,'Closing',1), +(6,11,6246,'Closing',1), +(6,11,6247,'Opening',1), +(6,11,6477,'Opening',1), +(6,11,6478,'Opening',1), +(6,11,6603,'Attack',1), +(6,11,7266,'Duel',1), +(6,11,7267,'Grovel',1), +(6,11,7355,'Stuck',1), +(6,11,8386,'Attacking',1), +(6,11,9077,'Leather',1), +(6,11,9078,'Cloth',1), +(6,11,9125,'Generic',1), +(6,11,9635,'Dire Bear Form(Passive)',0), +(6,11,20549,'War Stomp',1), +(6,11,20550,'Endurance',1), +(6,11,20551,'Nature Resistance',1), +(6,11,20552,'Cultivation',1), +(6,11,21178,'Bear Form(Passive2)',0), +(6,11,21651,'Opening',1), +(6,11,21652,'Closing',1), +(6,11,22027,'Remove Insignia',1), +(6,11,22810,'Opening - No Text',1), +(6,11,24905,'Moonkin Form(Passive)',0), +(6,11,27764,'Fetish',1), +(6,11,33948,'Flight Form(Passive)',0), +(6,11,34123,'Tree of Life(Passive)',0), +(6,11,40121,'Swift Flight Form(Passive)',0), +(7,1,78,'Heroic Strike',1), +(7,1,81,'Dodge',1), +(7,1,107,'Block',1), +(7,1,198,'One-Handed Maces',1), +(7,1,201,'One-Handed Swords',1), +(7,1,203,'Unarmed',1), +(7,1,204,'Defense',1), +(7,1,522,'SPELLDEFENSE(DND)',1), +(7,1,668,'Language Common',1), +(7,1,1180,'Daggers',1), +(7,1,2382,'Generic',1), +(7,1,2457,'Battle Stance',1), +(7,1,2479,'Honorless Target',1), +(7,1,3050,'Detect',1), +(7,1,3365,'Opening',1), +(7,1,5301,'Defensive State(DND)',1), +(7,1,6233,'Closing',1), +(7,1,6246,'Closing',1), +(7,1,6247,'Opening',1), +(7,1,6477,'Opening',1), +(7,1,6478,'Opening',1), +(7,1,6603,'Attack',1), +(7,1,7266,'Duel',1), +(7,1,7267,'Grovel',1), +(7,1,7340,'Language Gnomish',1), +(7,1,7355,'Stuck',1), +(7,1,7376,'Defensive Stance Passive',0), +(7,1,7381,'Berserker Stance Passive',0), +(7,1,8386,'Attacking',1), +(7,1,8737,'Mail',1), +(7,1,9077,'Leather',1), +(7,1,9078,'Cloth',1), +(7,1,9116,'Shield',1), +(7,1,9125,'Generic',1), +(7,1,20589,'Escape Artist',1), +(7,1,20591,'Expansive Mind',1), +(7,1,20592,'Arcane Resistance',1), +(7,1,20593,'Engineering Specialization',1), +(7,1,21156,'Battle Stance Passive',0), +(7,1,21651,'Opening',1), +(7,1,21652,'Closing',1), +(7,1,22027,'Remove Insignia',1), +(7,1,22810,'Opening - No Text',1), +(7,1,32215,'Victorious State',1), +(7,4,81,'Dodge',1), +(7,4,203,'Unarmed',1), +(7,4,204,'Defense',1), +(7,4,522,'SPELLDEFENSE(DND)',1), +(7,4,668,'Language Common',1), +(7,4,1180,'Daggers',1), +(7,4,1752,'Sinister Strike',1), +(7,4,2098,'Eviscerate',1), +(7,4,2382,'Generic',1), +(7,4,2479,'Honorless Target',1), +(7,4,2567,'Thrown',1), +(7,4,2764,'Throw',1), +(7,4,3050,'Detect',1), +(7,4,3365,'Opening',1), +(7,4,6233,'Closing',1), +(7,4,6246,'Closing',1), +(7,4,6247,'Opening',1), +(7,4,6477,'Opening',1), +(7,4,6478,'Opening',1), +(7,4,6603,'Attack',1), +(7,4,7266,'Duel',1), +(7,4,7267,'Grovel',1), +(7,4,7340,'Language Gnomish',1), +(7,4,7355,'Stuck',1), +(7,4,8386,'Attacking',1), +(7,4,9077,'Leather',1), +(7,4,9078,'Cloth',1), +(7,4,9125,'Generic',1), +(7,4,16092,'Defensive State(DND)',1), +(7,4,20589,'Escape Artist',1), +(7,4,20591,'Expansive Mind',1), +(7,4,20592,'Arcane Resistance',1), +(7,4,20593,'Engineering Specialization',1), +(7,4,21184,'Rogue Passive(DND)',1), +(7,4,21651,'Opening',1), +(7,4,21652,'Closing',1), +(7,4,22027,'Remove Insignia',1), +(7,4,22810,'Opening - No Text',1), +(7,8,81,'Dodge',1), +(7,8,133,'Fireball',1), +(7,8,168,'Frost Armor',1), +(7,8,203,'Unarmed',1), +(7,8,204,'Defense',1), +(7,8,227,'Staves',1), +(7,8,522,'SPELLDEFENSE(DND)',1), +(7,8,668,'Language Common',1), +(7,8,2382,'Generic',1), +(7,8,2479,'Honorless Target',1), +(7,8,3050,'Detect',1), +(7,8,3365,'Opening',1), +(7,8,5009,'Wands',1), +(7,8,5019,'Shoot',1), +(7,8,6233,'Closing',1), +(7,8,6246,'Closing',1), +(7,8,6247,'Opening',1), +(7,8,6477,'Opening',1), +(7,8,6478,'Opening',1), +(7,8,6603,'Attack',1), +(7,8,7266,'Duel',1), +(7,8,7267,'Grovel',1), +(7,8,7340,'Language Gnomish',1), +(7,8,7355,'Stuck',1), +(7,8,8386,'Attacking',1), +(7,8,9078,'Cloth',1), +(7,8,9125,'Generic',1), +(7,8,20589,'Escape Artist',1), +(7,8,20591,'Expansive Mind',1), +(7,8,20592,'Arcane Resistance',1), +(7,8,20593,'Engineering Specialization',1), +(7,8,21651,'Opening',1), +(7,8,21652,'Closing',1), +(7,8,22027,'Remove Insignia',1), +(7,8,22810,'Opening - No Text',1), +(7,9,81,'Dodge',1), +(7,9,203,'Unarmed',1), +(7,9,204,'Defense',1), +(7,9,522,'SPELLDEFENSE(DND)',1), +(7,9,668,'Language Common',1), +(7,9,686,'Shadow Bolt',1), +(7,9,687,'Demon Skin',1), +(7,9,1180,'Daggers',1), +(7,9,2382,'Generic',1), +(7,9,2479,'Honorless Target',1), +(7,9,3050,'Detect',1), +(7,9,3365,'Opening',1), +(7,9,5009,'Wands',1), +(7,9,5019,'Shoot',1), +(7,9,6233,'Closing',1), +(7,9,6246,'Closing',1), +(7,9,6247,'Opening',1), +(7,9,6477,'Opening',1), +(7,9,6478,'Opening',1), +(7,9,6603,'Attack',1), +(7,9,7266,'Duel',1), +(7,9,7267,'Grovel',1), +(7,9,7340,'Language Gnomish',1), +(7,9,7355,'Stuck',1), +(7,9,8386,'Attacking',1), +(7,9,9078,'Cloth',1), +(7,9,9125,'Generic',1), +(7,9,20589,'Escape Artist',1), +(7,9,20591,'Expansive Mind',1), +(7,9,20592,'Arcane Resistance',1), +(7,9,20593,'Engineering Specialization',1), +(7,9,21651,'Opening',1), +(7,9,21652,'Closing',1), +(7,9,22027,'Remove Insignia',1), +(7,9,22810,'Opening - No Text',1), +(8,1,78,'Heroic Strike',1), +(8,1,81,'Dodge',1), +(8,1,107,'Block',1), +(8,1,196,'One-Handed Axes',1), +(8,1,203,'Unarmed',1), +(8,1,204,'Defense',1), +(8,1,522,'SPELLDEFENSE(DND)',1), +(8,1,669,'Language Orcish',1), +(8,1,1180,'Daggers',1), +(8,1,2382,'Generic',1), +(8,1,2457,'Battle Stance',1), +(8,1,2479,'Honorless Target',1), +(8,1,2567,'Thrown',1), +(8,1,2764,'Throw',1), +(8,1,3050,'Detect',1), +(8,1,3365,'Opening',1), +(8,1,5301,'Defensive State(DND)',1), +(8,1,6233,'Closing',1), +(8,1,6246,'Closing',1), +(8,1,6247,'Opening',1), +(8,1,6477,'Opening',1), +(8,1,6478,'Opening',1), +(8,1,6603,'Attack',1), +(8,1,7266,'Duel',1), +(8,1,7267,'Grovel',1), +(8,1,7341,'Language Troll',1), +(8,1,7355,'Stuck',1), +(8,1,7376,'Defensive Stance Passive',0), +(8,1,7381,'Berserker Stance Passive',0), +(8,1,8386,'Attacking',1), +(8,1,8737,'Mail',1), +(8,1,9077,'Leather',1), +(8,1,9078,'Cloth',1), +(8,1,9116,'Shield',1), +(8,1,9125,'Generic',1), +(8,1,20555,'Regeneration',1), +(8,1,20557,'Beast Slaying',1), +(8,1,20558,'Throwing Specialization',1), +(8,1,21156,'Battle Stance Passive',0), +(8,1,21651,'Opening',1), +(8,1,21652,'Closing',1), +(8,1,22027,'Remove Insignia',1), +(8,1,22810,'Opening - No Text',1), +(8,1,26290,'Bow Specialization',1), +(8,1,26296,'Berserking',1), +(8,1,32215,'Victorious State',1), +(8,3,75,'Auto Shot',1), +(8,3,81,'Dodge',1), +(8,3,196,'One-Handed Axes',1), +(8,3,203,'Unarmed',1), +(8,3,204,'Defense',1), +(8,3,264,'Bows',1), +(8,3,522,'SPELLDEFENSE(DND)',1), +(8,3,669,'Language Orcish',1), +(8,3,2382,'Generic',1), +(8,3,2479,'Honorless Target',1), +(8,3,2973,'Raptor Strike',1), +(8,3,3050,'Detect',1), +(8,3,3365,'Opening',1), +(8,3,6233,'Closing',1), +(8,3,6246,'Closing',1), +(8,3,6247,'Opening',1), +(8,3,6477,'Opening',1), +(8,3,6478,'Opening',1), +(8,3,6603,'Attack',1), +(8,3,7266,'Duel',1), +(8,3,7267,'Grovel',1), +(8,3,7341,'Language Troll',1), +(8,3,7355,'Stuck',1), +(8,3,8386,'Attacking',1), +(8,3,9077,'Leather',1), +(8,3,9078,'Cloth',1), +(8,3,9125,'Generic',1), +(8,3,13358,'Defensive State(DND)',1), +(8,3,20554,'Berserking',1), +(8,3,20555,'Regeneration',1), +(8,3,20557,'Beast Slaying',1), +(8,3,20558,'Throwing Specialization',1), +(8,3,21651,'Opening',1), +(8,3,21652,'Closing',1), +(8,3,22027,'Remove Insignia',1), +(8,3,22810,'Opening - No Text',1), +(8,3,24949,'Defensive State 2(DND)',1), +(8,3,26290,'Bow Specialization',1), +(8,3,34082,'Advantaged State(DND)',1), +(8,4,81,'Dodge',1), +(8,4,203,'Unarmed',1), +(8,4,204,'Defense',1), +(8,4,522,'SPELLDEFENSE(DND)',1), +(8,4,669,'Language Orcish',1), +(8,4,1180,'Daggers',1), +(8,4,1752,'Sinister Strike',1), +(8,4,2098,'Eviscerate',1), +(8,4,2382,'Generic',1), +(8,4,2479,'Honorless Target',1), +(8,4,2567,'Thrown',1), +(8,4,2764,'Throw',1), +(8,4,3050,'Detect',1), +(8,4,3365,'Opening',1), +(8,4,6233,'Closing',1), +(8,4,6246,'Closing',1), +(8,4,6247,'Opening',1), +(8,4,6477,'Opening',1), +(8,4,6478,'Opening',1), +(8,4,6603,'Attack',1), +(8,4,7266,'Duel',1), +(8,4,7267,'Grovel',1), +(8,4,7341,'Language Troll',1), +(8,4,7355,'Stuck',1), +(8,4,8386,'Attacking',1), +(8,4,9077,'Leather',1), +(8,4,9078,'Cloth',1), +(8,4,9125,'Generic',1), +(8,4,16092,'Defensive State(DND)',1), +(8,4,20555,'Regeneration',1), +(8,4,20557,'Beast Slaying',1), +(8,4,20558,'Throwing Specialization',1), +(8,4,21184,'Rogue Passive(DND)',1), +(8,4,21651,'Opening',1), +(8,4,21652,'Closing',1), +(8,4,22027,'Remove Insignia',1), +(8,4,22810,'Opening - No Text',1), +(8,4,26290,'Bow Specialization',1), +(8,4,26297,'Berserking',1), +(8,5,81,'Dodge',1), +(8,5,198,'One-Handed Maces',1), +(8,5,203,'Unarmed',1), +(8,5,204,'Defense',1), +(8,5,522,'SPELLDEFENSE(DND)',1), +(8,5,585,'Smite',1), +(8,5,669,'Language Orcish',1), +(8,5,2050,'Lesser Heal',1), +(8,5,2382,'Generic',1), +(8,5,2479,'Honorless Target',1), +(8,5,3050,'Detect',1), +(8,5,3365,'Opening',1), +(8,5,5009,'Wands',1), +(8,5,5019,'Shoot',1), +(8,5,6233,'Closing',1), +(8,5,6246,'Closing',1), +(8,5,6247,'Opening',1), +(8,5,6477,'Opening',1), +(8,5,6478,'Opening',1), +(8,5,6603,'Attack',1), +(8,5,7266,'Duel',1), +(8,5,7267,'Grovel',1), +(8,5,7341,'Language Troll',1), +(8,5,7355,'Stuck',1), +(8,5,8386,'Attacking',1), +(8,5,9078,'Cloth',1), +(8,5,9125,'Generic',1), +(8,5,20554,'Berserking',1), +(8,5,20555,'Regeneration',1), +(8,5,20557,'Beast Slaying',1), +(8,5,20558,'Throwing Specialization',1), +(8,5,21651,'Opening',1), +(8,5,21652,'Closing',1), +(8,5,22027,'Remove Insignia',1), +(8,5,22810,'Opening - No Text',1), +(8,5,26290,'Bow Specialization',1), +(8,7,81,'Dodge',1), +(8,7,107,'Block',1), +(8,7,198,'One-Handed Maces',1), +(8,7,203,'Unarmed',1), +(8,7,204,'Defense',1), +(8,7,227,'Staves',1), +(8,7,331,'Healing Wave',1), +(8,7,403,'Lightning Bolt',1), +(8,7,522,'SPELLDEFENSE(DND)',1), +(8,7,669,'Language Orcish',1), +(8,7,2382,'Generic',1), +(8,7,2479,'Honorless Target',1), +(8,7,3050,'Detect',1), +(8,7,3365,'Opening',1), +(8,7,6233,'Closing',1), +(8,7,6246,'Closing',1), +(8,7,6247,'Opening',1), +(8,7,6477,'Opening',1), +(8,7,6478,'Opening',1), +(8,7,6603,'Attack',1), +(8,7,7266,'Duel',1), +(8,7,7267,'Grovel',1), +(8,7,7341,'Language Troll',1), +(8,7,7355,'Stuck',1), +(8,7,8386,'Attacking',1), +(8,7,9077,'Leather',1), +(8,7,9078,'Cloth',1), +(8,7,9116,'Shield',1), +(8,7,9125,'Generic',1), +(8,7,20554,'Berserking',1), +(8,7,20555,'Regeneration',1), +(8,7,20557,'Beast Slaying',1), +(8,7,20558,'Throwing Specialization',1), +(8,7,21651,'Opening',1), +(8,7,21652,'Closing',1), +(8,7,22027,'Remove Insignia',1), +(8,7,22810,'Opening - No Text',1), +(8,7,26290,'Bow Specialization',1), +(8,7,27763,'Totem',1), +(8,8,81,'Dodge',1), +(8,8,133,'Fireball',1), +(8,8,168,'Frost Armor',1), +(8,8,203,'Unarmed',1), +(8,8,204,'Defense',1), +(8,8,227,'Staves',1), +(8,8,522,'SPELLDEFENSE(DND)',1), +(8,8,669,'Language Orcish',1), +(8,8,2382,'Generic',1), +(8,8,2479,'Honorless Target',1), +(8,8,3050,'Detect',1), +(8,8,3365,'Opening',1), +(8,8,5009,'Wands',1), +(8,8,5019,'Shoot',1), +(8,8,6233,'Closing',1), +(8,8,6246,'Closing',1), +(8,8,6247,'Opening',1), +(8,8,6477,'Opening',1), +(8,8,6478,'Opening',1), +(8,8,6603,'Attack',1), +(8,8,7266,'Duel',1), +(8,8,7267,'Grovel',1), +(8,8,7341,'Language Troll',1), +(8,8,7355,'Stuck',1), +(8,8,8386,'Attacking',1), +(8,8,9078,'Cloth',1), +(8,8,9125,'Generic',1), +(8,8,20554,'Berserking',1), +(8,8,20555,'Regeneration',1), +(8,8,20557,'Beast Slaying',1), +(8,8,20558,'Throwing Specialization',1), +(8,8,21651,'Opening',1), +(8,8,21652,'Closing',1), +(8,8,22027,'Remove Insignia',1), +(8,8,22810,'Opening - No Text',1), +(8,8,26290,'Bow Specialization',1), +(10,2,81,'Dodge',1), +(10,2,107,'Block',1), +(10,2,201,'One-Handed Swords',1), +(10,2,202,'Two-Handed Swords',1), +(10,2,203,'Unarmed',1), +(10,2,204,'Defense',1), +(10,2,522,'SPELLDEFENSE(DND)',1), +(10,2,635,'Holy Light',1), +(10,2,669,'Language Orcish',1), +(10,2,813,'Language Thalassian',1), +(10,2,822,'Magic Resistance',1), +(10,2,2382,'Generic',1), +(10,2,2479,'Honorless Target',1), +(10,2,3050,'Detect',1), +(10,2,3365,'Opening',1), +(10,2,6233,'Closing',1), +(10,2,6246,'Closing',1), +(10,2,6247,'Opening',1), +(10,2,6477,'Opening',1), +(10,2,6478,'Opening',1), +(10,2,6603,'Attack',1), +(10,2,7266,'Duel',1), +(10,2,7267,'Grovel',1), +(10,2,7355,'Stuck',1), +(10,2,8386,'Attacking',1), +(10,2,8737,'Mail',1), +(10,2,9077,'Leather',1), +(10,2,9078,'Cloth',1), +(10,2,9116,'Shield',1), +(10,2,9125,'Generic',1), +(10,2,21084,'Seal of Righteousness',1), +(10,2,21651,'Opening',1), +(10,2,21652,'Closing',1), +(10,2,22027,'Remove Insignia',1), +(10,2,22810,'Opening - No Text',1), +(10,2,27762,'Libram',1), +(10,2,28730,'Arcane Torrent',1), +(10,2,28734,'Mana Tap',1), +(10,2,28877,'Arcane Affinity',1), +(10,3,75,'Auto Shot',1), +(10,3,81,'Dodge',1), +(10,3,203,'Unarmed',1), +(10,3,204,'Defense',1), +(10,3,264,'Bows',1), +(10,3,522,'SPELLDEFENSE(DND)',1), +(10,3,669,'Language Orcish',1), +(10,3,813,'Language Thalassian',1), +(10,3,822,'Magic Resistance',1), +(10,3,1180,'Daggers',1), +(10,3,2382,'Generic',1), +(10,3,2479,'Honorless Target',1), +(10,3,2973,'Raptor Strike',1), +(10,3,3050,'Detect',1), +(10,3,3365,'Opening',1), +(10,3,6233,'Closing',1), +(10,3,6246,'Closing',1), +(10,3,6247,'Opening',1), +(10,3,6477,'Opening',1), +(10,3,6478,'Opening',1), +(10,3,6603,'Attack',1), +(10,3,7266,'Duel',1), +(10,3,7267,'Grovel',1), +(10,3,7355,'Stuck',1), +(10,3,8386,'Attacking',1), +(10,3,9077,'Leather',1), +(10,3,9078,'Cloth',1), +(10,3,9125,'Generic',1), +(10,3,13358,'Defensive State(DND)',1), +(10,3,21651,'Opening',1), +(10,3,21652,'Closing',1), +(10,3,22027,'Remove Insignia',1), +(10,3,22810,'Opening - No Text',1), +(10,3,24949,'Defensive State 2(DND)',1), +(10,3,28730,'Arcane Torrent',1), +(10,3,28734,'Mana Tap',1), +(10,3,28877,'Arcane Affinity',1), +(10,3,34082,'Advantaged State(DND)',1), +(10,4,81,'Dodge',1), +(10,4,203,'Unarmed',1), +(10,4,204,'Defense',1), +(10,4,522,'SPELLDEFENSE(DND)',1), +(10,4,669,'Language Orcish',1), +(10,4,813,'Language Thalassian',1), +(10,4,822,'Magic Resistance',1), +(10,4,1180,'Daggers',1), +(10,4,1752,'Sinister Strike',1), +(10,4,2098,'Eviscerate',1), +(10,4,2382,'Generic',1), +(10,4,2479,'Honorless Target',1), +(10,4,2567,'Thrown',1), +(10,4,2764,'Throw',1), +(10,4,3050,'Detect',1), +(10,4,3365,'Opening',1), +(10,4,6233,'Closing',1), +(10,4,6246,'Closing',1), +(10,4,6247,'Opening',1), +(10,4,6477,'Opening',1), +(10,4,6478,'Opening',1), +(10,4,6603,'Attack',1), +(10,4,7266,'Duel',1), +(10,4,7267,'Grovel',1), +(10,4,7355,'Stuck',1), +(10,4,8386,'Attacking',1), +(10,4,9077,'Leather',1), +(10,4,9078,'Cloth',1), +(10,4,9125,'Generic',1), +(10,4,16092,'Defensive State(DND)',1), +(10,4,21184,'Rogue Passive(DND)',1), +(10,4,21651,'Opening',1), +(10,4,21652,'Closing',1), +(10,4,22027,'Remove Insignia',1), +(10,4,22810,'Opening - No Text',1), +(10,4,25046,'Arcane Torrent',1), +(10,4,28734,'Mana Tap',1), +(10,4,28877,'Arcane Affinity',1), +(10,5,81,'Dodge',1), +(10,5,198,'One-Handed Maces',1), +(10,5,203,'Unarmed',1), +(10,5,204,'Defense',1), +(10,5,522,'SPELLDEFENSE(DND)',1), +(10,5,585,'Smite',1), +(10,5,669,'Language Orcish',1), +(10,5,813,'Language Thalassian',1), +(10,5,822,'Magic Resistance',1), +(10,5,2050,'Lesser Heal',1), +(10,5,2382,'Generic',1), +(10,5,2479,'Honorless Target',1), +(10,5,3050,'Detect',1), +(10,5,3365,'Opening',1), +(10,5,5009,'Wands',1), +(10,5,5019,'Shoot',1), +(10,5,6233,'Closing',1), +(10,5,6246,'Closing',1), +(10,5,6247,'Opening',1), +(10,5,6477,'Opening',1), +(10,5,6478,'Opening',1), +(10,5,6603,'Attack',1), +(10,5,7266,'Duel',1), +(10,5,7267,'Grovel',1), +(10,5,7355,'Stuck',1), +(10,5,8386,'Attacking',1), +(10,5,9078,'Cloth',1), +(10,5,9125,'Generic',1), +(10,5,21651,'Opening',1), +(10,5,21652,'Closing',1), +(10,5,22027,'Remove Insignia',1), +(10,5,22810,'Opening - No Text',1), +(10,5,28730,'Arcane Torrent',1), +(10,5,28734,'Mana Tap',1), +(10,5,28877,'Arcane Affinity',1), +(10,8,81,'Dodge',1), +(10,8,133,'Fireball',1), +(10,8,168,'Frost Armor',1), +(10,8,203,'Unarmed',1), +(10,8,204,'Defense',1), +(10,8,227,'Staves',1), +(10,8,522,'SPELLDEFENSE(DND)',1), +(10,8,669,'Language Orcish',1), +(10,8,813,'Language Thalassian',1), +(10,8,822,'Magic Resistance',1), +(10,8,2382,'Generic',1), +(10,8,2479,'Honorless Target',1), +(10,8,3050,'Detect',1), +(10,8,3365,'Opening',1), +(10,8,5009,'Wands',1), +(10,8,5019,'Shoot',1), +(10,8,6233,'Closing',1), +(10,8,6246,'Closing',1), +(10,8,6247,'Opening',1), +(10,8,6477,'Opening',1), +(10,8,6478,'Opening',1), +(10,8,6603,'Attack',1), +(10,8,7266,'Duel',1), +(10,8,7267,'Grovel',1), +(10,8,7355,'Stuck',1), +(10,8,8386,'Attacking',1), +(10,8,9078,'Cloth',1), +(10,8,9125,'Generic',1), +(10,8,21651,'Opening',1), +(10,8,21652,'Closing',1), +(10,8,22027,'Remove Insignia',1), +(10,8,22810,'Opening - No Text',1), +(10,8,28730,'Arcane Torrent',1), +(10,8,28734,'Mana Tap',1), +(10,8,28877,'Arcane Affinity',1), +(10,9,81,'Dodge',1), +(10,9,203,'Unarmed',1), +(10,9,204,'Defense',1), +(10,9,522,'SPELLDEFENSE(DND)',1), +(10,9,669,'Language Orcish',1), +(10,9,686,'Shadow Bolt',1), +(10,9,687,'Demon Skin',1), +(10,9,813,'Language Thalassian',1), +(10,9,822,'Magic Resistance',1), +(10,9,1180,'Daggers',1), +(10,9,2382,'Generic',1), +(10,9,2479,'Honorless Target',1), +(10,9,3050,'Detect',1), +(10,9,3365,'Opening',1), +(10,9,5009,'Wands',1), +(10,9,5019,'Shoot',1), +(10,9,6233,'Closing',1), +(10,9,6246,'Closing',1), +(10,9,6247,'Opening',1), +(10,9,6477,'Opening',1), +(10,9,6478,'Opening',1), +(10,9,6603,'Attack',1), +(10,9,7266,'Duel',1), +(10,9,7267,'Grovel',1), +(10,9,7355,'Stuck',1), +(10,9,8386,'Attacking',1), +(10,9,9078,'Cloth',1), +(10,9,9125,'Generic',1), +(10,9,21651,'Opening',1), +(10,9,21652,'Closing',1), +(10,9,22027,'Remove Insignia',1), +(10,9,22810,'Opening - No Text',1), +(10,9,28730,'Arcane Torrent',1), +(10,9,28734,'Mana Tap',1), +(10,9,28877,'Arcane Affinity',1), +(11,1,78,'Heroic Strike',1), +(11,1,81,'Dodge',1), +(11,1,107,'Block',1), +(11,1,198,'One-Handed Maces',1), +(11,1,201,'One-Handed Swords',1), +(11,1,202,'Two-Handed Swords',1), +(11,1,203,'Unarmed',1), +(11,1,204,'Defense',1), +(11,1,522,'SPELLDEFENSE(DND)',1), +(11,1,668,'Language Common',1), +(11,1,2382,'Generic',1), +(11,1,2457,'Battle Stance',1), +(11,1,2479,'Honorless Target',1), +(11,1,3050,'Detect',1), +(11,1,3365,'Opening',1), +(11,1,5301,'Defensive State(DND)',1), +(11,1,6233,'Closing',1), +(11,1,6246,'Closing',1), +(11,1,6247,'Opening',1), +(11,1,6477,'Opening',1), +(11,1,6478,'Opening',1), +(11,1,6562,'Heroic Presence',1), +(11,1,6603,'Attack',1), +(11,1,7266,'Duel',1), +(11,1,7267,'Grovel',1), +(11,1,7355,'Stuck',1), +(11,1,7376,'Defensive Stance Passive',0), +(11,1,7381,'Berserker Stance Passive',0), +(11,1,8386,'Attacking',1), +(11,1,8737,'Mail',1), +(11,1,9077,'Leather',1), +(11,1,9078,'Cloth',1), +(11,1,9116,'Shield',1), +(11,1,9125,'Generic',1), +(11,1,20579,'Shadow Resistance',1), +(11,1,21156,'Battle Stance Passive',0), +(11,1,21651,'Opening',1), +(11,1,21652,'Closing',1), +(11,1,22027,'Remove Insignia',1), +(11,1,22810,'Opening - No Text',1), +(11,1,28875,'Gemcutting',1), +(11,1,28880,'Gift of the Naaru',1), +(11,1,29932,'Language Draenei',1), +(11,1,32215,'Victorious State',1), +(11,2,81,'Dodge',1), +(11,2,107,'Block',1), +(11,2,198,'One-Handed Maces',1), +(11,2,199,'Two-Handed Maces',1), +(11,2,203,'Unarmed',1), +(11,2,204,'Defense',1), +(11,2,522,'SPELLDEFENSE(DND)',1), +(11,2,635,'Holy Light',1), +(11,2,668,'Language Common',1), +(11,2,2382,'Generic',1), +(11,2,2479,'Honorless Target',1), +(11,2,3050,'Detect',1), +(11,2,3365,'Opening',1), +(11,2,6233,'Closing',1), +(11,2,6246,'Closing',1), +(11,2,6247,'Opening',1), +(11,2,6477,'Opening',1), +(11,2,6478,'Opening',1), +(11,2,6562,'Heroic Presence',1), +(11,2,6603,'Attack',1), +(11,2,7266,'Duel',1), +(11,2,7267,'Grovel',1), +(11,2,7355,'Stuck',1), +(11,2,8386,'Attacking',1), +(11,2,8737,'Mail',1), +(11,2,9077,'Leather',1), +(11,2,9078,'Cloth',1), +(11,2,9116,'Shield',1), +(11,2,9125,'Generic',1), +(11,2,21084,'Seal of Righteousness',1), +(11,2,20579,'Shadow Resistance',1), +(11,2,21651,'Opening',1), +(11,2,21652,'Closing',1), +(11,2,22027,'Remove Insignia',1), +(11,2,22810,'Opening - No Text',1), +(11,2,27762,'Libram',1), +(11,2,28875,'Gemcutting',1), +(11,2,28880,'Gift of the Naaru',1), +(11,2,29932,'Language Draenei',1), +(11,3,75,'Auto Shot',1), +(11,3,81,'Dodge',1), +(11,3,201,'One-Handed Swords',1), +(11,3,203,'Unarmed',1), +(11,3,204,'Defense',1), +(11,3,522,'SPELLDEFENSE(DND)',1), +(11,3,668,'Language Common',1), +(11,3,2382,'Generic',1), +(11,3,2479,'Honorless Target',1), +(11,3,2973,'Raptor Strike',1), +(11,3,3050,'Detect',1), +(11,3,3365,'Opening',1), +(11,3,5011,'Crossbows',1), +(11,3,6233,'Closing',1), +(11,3,6246,'Closing',1), +(11,3,6247,'Opening',1), +(11,3,6477,'Opening',1), +(11,3,6478,'Opening',1), +(11,3,6562,'Heroic Presence',1), +(11,3,6603,'Attack',1), +(11,3,7266,'Duel',1), +(11,3,7267,'Grovel',1), +(11,3,7355,'Stuck',1), +(11,3,8386,'Attacking',1), +(11,3,9077,'Leather',1), +(11,3,9078,'Cloth',1), +(11,3,9125,'Generic',1), +(11,3,13358,'Defensive State(DND)',1), +(11,3,20579,'Shadow Resistance',1), +(11,3,21651,'Opening',1), +(11,3,21652,'Closing',1), +(11,3,22027,'Remove Insignia',1), +(11,3,22810,'Opening - No Text',1), +(11,3,24949,'Defensive State 2(DND)',1), +(11,3,28875,'Gemcutting',1), +(11,3,28880,'Gift of the Naaru',1), +(11,3,29932,'Language Draenei',1), +(11,3,34082,'Advantaged State(DND)',1), +(11,5,81,'Dodge',1), +(11,5,198,'One-Handed Maces',1), +(11,5,203,'Unarmed',1), +(11,5,204,'Defense',1), +(11,5,522,'SPELLDEFENSE(DND)',1), +(11,5,585,'Smite',1), +(11,5,668,'Language Common',1), +(11,5,2050,'Lesser Heal',1), +(11,5,2382,'Generic',1), +(11,5,2479,'Honorless Target',1), +(11,5,3050,'Detect',1), +(11,5,3365,'Opening',1), +(11,5,5009,'Wands',1), +(11,5,5019,'Shoot',1), +(11,5,6233,'Closing',1), +(11,5,6246,'Closing',1), +(11,5,6247,'Opening',1), +(11,5,6477,'Opening',1), +(11,5,6478,'Opening',1), +(11,5,6603,'Attack',1), +(11,5,7266,'Duel',1), +(11,5,7267,'Grovel',1), +(11,5,7355,'Stuck',1), +(11,5,8386,'Attacking',1), +(11,5,9078,'Cloth',1), +(11,5,9125,'Generic',1), +(11,5,20579,'Shadow Resistance',1), +(11,5,21651,'Opening',1), +(11,5,21652,'Closing',1), +(11,5,22027,'Remove Insignia',1), +(11,5,22810,'Opening - No Text',1), +(11,5,28875,'Gemcutting',1), +(11,5,28878,'Inspiring Presence',1), +(11,5,28880,'Gift of the Naaru',1), +(11,5,29932,'Language Draenei',1), +(11,7,81,'Dodge',1), +(11,7,107,'Block',1), +(11,7,198,'One-Handed Maces',1), +(11,7,203,'Unarmed',1), +(11,7,204,'Defense',1), +(11,7,227,'Staves',1), +(11,7,331,'Healing Wave',1), +(11,7,403,'Lightning Bolt',1), +(11,7,522,'SPELLDEFENSE(DND)',1), +(11,7,668,'Language Common',1), +(11,7,2382,'Generic',1), +(11,7,2479,'Honorless Target',1), +(11,7,3050,'Detect',1), +(11,7,3365,'Opening',1), +(11,7,6233,'Closing',1), +(11,7,6246,'Closing',1), +(11,7,6247,'Opening',1), +(11,7,6477,'Opening',1), +(11,7,6478,'Opening',1), +(11,7,6603,'Attack',1), +(11,7,7266,'Duel',1), +(11,7,7267,'Grovel',1), +(11,7,7355,'Stuck',1), +(11,7,8386,'Attacking',1), +(11,7,9077,'Leather',1), +(11,7,9078,'Cloth',1), +(11,7,9116,'Shield',1), +(11,7,9125,'Generic',1), +(11,7,20579,'Shadow Resistance',1), +(11,7,21651,'Opening',1), +(11,7,21652,'Closing',1), +(11,7,22027,'Remove Insignia',1), +(11,7,22810,'Opening - No Text',1), +(11,7,27763,'Totem',1), +(11,7,28875,'Gemcutting',1), +(11,7,28878,'Inspiring Presence',1), +(11,7,28880,'Gift of the Naaru',1), +(11,7,29932,'Language Draenei',1), +(11,8,81,'Dodge',1), +(11,8,133,'Fireball',1), +(11,8,168,'Frost Armor',1), +(11,8,203,'Unarmed',1), +(11,8,204,'Defense',1), +(11,8,227,'Staves',1), +(11,8,522,'SPELLDEFENSE(DND)',1), +(11,8,668,'Language Common',1), +(11,8,2382,'Generic',1), +(11,8,2479,'Honorless Target',1), +(11,8,3050,'Detect',1), +(11,8,3365,'Opening',1), +(11,8,5009,'Wands',1), +(11,8,5019,'Shoot',1), +(11,8,6233,'Closing',1), +(11,8,6246,'Closing',1), +(11,8,6247,'Opening',1), +(11,8,6477,'Opening',1), +(11,8,6478,'Opening',1), +(11,8,6603,'Attack',1), +(11,8,7266,'Duel',1), +(11,8,7267,'Grovel',1), +(11,8,7355,'Stuck',1), +(11,8,8386,'Attacking',1), +(11,8,9078,'Cloth',1), +(11,8,9125,'Generic',1), +(11,8,20579,'Shadow Resistance',1), +(11,8,21651,'Opening',1), +(11,8,21652,'Closing',1), +(11,8,22027,'Remove Insignia',1), +(11,8,22810,'Opening - No Text',1), +(11,8,28875,'Gemcutting',1), +(11,8,28878,'Inspiring Presence',1), +(11,8,28880,'Gift of the Naaru',1), +(11,8,29932,'Language Draenei',1); +/*!40000 ALTER TABLE `playercreateinfo_spell` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `prospecting_loot_template` +-- + +DROP TABLE IF EXISTS `prospecting_loot_template`; +CREATE TABLE `prospecting_loot_template` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `item` mediumint(8) unsigned NOT NULL default '0', + `ChanceOrQuestChance` float NOT NULL default '100', + `groupid` tinyint(3) unsigned NOT NULL default '0', + `mincountOrRef` mediumint(9) NOT NULL default '1', + `maxcount` tinyint(3) unsigned NOT NULL default '1', + `lootcondition` tinyint(3) unsigned NOT NULL default '0', + `condition_value1` mediumint(8) unsigned NOT NULL default '0', + `condition_value2` mediumint(8) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`,`item`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Loot System'; + +-- +-- Dumping data for table `prospecting_loot_template` +-- + +LOCK TABLES `prospecting_loot_template` WRITE; +/*!40000 ALTER TABLE `prospecting_loot_template` DISABLE KEYS */; +/*!40000 ALTER TABLE `prospecting_loot_template` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `quest_end_scripts` +-- + +DROP TABLE IF EXISTS `quest_end_scripts`; +CREATE TABLE `quest_end_scripts` ( + `id` mediumint(8) unsigned NOT NULL default '0', + `delay` int(10) unsigned NOT NULL default '0', + `command` mediumint(8) unsigned NOT NULL default '0', + `datalong` mediumint(8) unsigned NOT NULL default '0', + `datalong2` int(10) unsigned NOT NULL default '0', + `datatext` text NOT NULL, + `x` float NOT NULL default '0', + `y` float NOT NULL default '0', + `z` float NOT NULL default '0', + `o` float NOT NULL default '0' +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `quest_end_scripts` +-- + +LOCK TABLES `quest_end_scripts` WRITE; +/*!40000 ALTER TABLE `quest_end_scripts` DISABLE KEYS */; +/*!40000 ALTER TABLE `quest_end_scripts` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `quest_start_scripts` +-- + +DROP TABLE IF EXISTS `quest_start_scripts`; +CREATE TABLE `quest_start_scripts` ( + `id` mediumint(8) unsigned NOT NULL default '0', + `delay` int(10) unsigned NOT NULL default '0', + `command` mediumint(8) unsigned NOT NULL default '0', + `datalong` mediumint(8) unsigned NOT NULL default '0', + `datalong2` int(10) unsigned NOT NULL default '0', + `datatext` text NOT NULL, + `x` float NOT NULL default '0', + `y` float NOT NULL default '0', + `z` float NOT NULL default '0', + `o` float NOT NULL default '0' +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `quest_start_scripts` +-- + +LOCK TABLES `quest_start_scripts` WRITE; +/*!40000 ALTER TABLE `quest_start_scripts` DISABLE KEYS */; +/*!40000 ALTER TABLE `quest_start_scripts` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `quest_mail_loot_template` +-- + +DROP TABLE IF EXISTS `quest_mail_loot_template`; +CREATE TABLE `quest_mail_loot_template` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `item` mediumint(8) unsigned NOT NULL default '0', + `ChanceOrQuestChance` float NOT NULL default '100', + `groupid` tinyint(3) unsigned NOT NULL default '0', + `mincountOrRef` mediumint(9) NOT NULL default '1', + `maxcount` tinyint(3) unsigned NOT NULL default '1', + `lootcondition` tinyint(3) unsigned NOT NULL default '0', + `condition_value1` mediumint(8) unsigned NOT NULL default '0', + `condition_value2` mediumint(8) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`,`item`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Loot System'; + +-- +-- Dumping data for table `quest_mail_loot_template` +-- + +LOCK TABLES `quest_mail_loot_template` WRITE; +/*!40000 ALTER TABLE `quest_mail_loot_template` DISABLE KEYS */; +/*!40000 ALTER TABLE `quest_mail_loot_template` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `quest_template` +-- + +DROP TABLE IF EXISTS `quest_template`; +CREATE TABLE `quest_template` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `ZoneOrSort` smallint(6) NOT NULL default '0', + `SkillOrClass` smallint(6) NOT NULL default '0', + `MinLevel` tinyint(3) unsigned NOT NULL default '0', + `QuestLevel` tinyint(3) unsigned NOT NULL default '0', + `Type` smallint(5) unsigned NOT NULL default '0', + `RequiredRaces` smallint(5) unsigned NOT NULL default '0', + `RequiredSkillValue` smallint(5) unsigned NOT NULL default '0', + `RepObjectiveFaction` smallint(5) unsigned NOT NULL default '0', + `RepObjectiveValue` mediumint(9) NOT NULL default '0', + `RequiredMinRepFaction` smallint(5) unsigned NOT NULL default '0', + `RequiredMinRepValue` mediumint(9) NOT NULL default '0', + `RequiredMaxRepFaction` smallint(5) unsigned NOT NULL default '0', + `RequiredMaxRepValue` mediumint(9) NOT NULL default '0', + `SuggestedPlayers` tinyint(3) unsigned NOT NULL default '0', + `LimitTime` int(10) unsigned NOT NULL default '0', + `QuestFlags` smallint(5) unsigned NOT NULL default '0', + `SpecialFlags` tinyint(3) unsigned NOT NULL default '0', + `CharTitleId` tinyint(3) unsigned NOT NULL default '0', + `PrevQuestId` mediumint(9) NOT NULL default '0', + `NextQuestId` mediumint(9) NOT NULL default '0', + `ExclusiveGroup` mediumint(9) NOT NULL default '0', + `NextQuestInChain` mediumint(8) unsigned NOT NULL default '0', + `SrcItemId` mediumint(8) unsigned NOT NULL default '0', + `SrcItemCount` tinyint(3) unsigned NOT NULL default '0', + `SrcSpell` mediumint(8) unsigned NOT NULL default '0', + `Title` text, + `Details` text, + `Objectives` text, + `OfferRewardText` text, + `RequestItemsText` text, + `EndText` text, + `ObjectiveText1` text, + `ObjectiveText2` text, + `ObjectiveText3` text, + `ObjectiveText4` text, + `ReqItemId1` mediumint(8) unsigned NOT NULL default '0', + `ReqItemId2` mediumint(8) unsigned NOT NULL default '0', + `ReqItemId3` mediumint(8) unsigned NOT NULL default '0', + `ReqItemId4` mediumint(8) unsigned NOT NULL default '0', + `ReqItemCount1` smallint(5) unsigned NOT NULL default '0', + `ReqItemCount2` smallint(5) unsigned NOT NULL default '0', + `ReqItemCount3` smallint(5) unsigned NOT NULL default '0', + `ReqItemCount4` smallint(5) unsigned NOT NULL default '0', + `ReqSourceId1` mediumint(8) unsigned NOT NULL default '0', + `ReqSourceId2` mediumint(8) unsigned NOT NULL default '0', + `ReqSourceId3` mediumint(8) unsigned NOT NULL default '0', + `ReqSourceId4` mediumint(8) unsigned NOT NULL default '0', + `ReqSourceCount1` smallint(5) unsigned NOT NULL default '0', + `ReqSourceCount2` smallint(5) unsigned NOT NULL default '0', + `ReqSourceCount3` smallint(5) unsigned NOT NULL default '0', + `ReqSourceCount4` smallint(5) unsigned NOT NULL default '0', + `ReqSourceRef1` tinyint(3) unsigned NOT NULL default '0', + `ReqSourceRef2` tinyint(3) unsigned NOT NULL default '0', + `ReqSourceRef3` tinyint(3) unsigned NOT NULL default '0', + `ReqSourceRef4` tinyint(3) unsigned NOT NULL default '0', + `ReqCreatureOrGOId1` mediumint(9) NOT NULL default '0', + `ReqCreatureOrGOId2` mediumint(9) NOT NULL default '0', + `ReqCreatureOrGOId3` mediumint(9) NOT NULL default '0', + `ReqCreatureOrGOId4` mediumint(9) NOT NULL default '0', + `ReqCreatureOrGOCount1` smallint(5) unsigned NOT NULL default '0', + `ReqCreatureOrGOCount2` smallint(5) unsigned NOT NULL default '0', + `ReqCreatureOrGOCount3` smallint(5) unsigned NOT NULL default '0', + `ReqCreatureOrGOCount4` smallint(5) unsigned NOT NULL default '0', + `ReqSpellCast1` mediumint(8) unsigned NOT NULL default '0', + `ReqSpellCast2` mediumint(8) unsigned NOT NULL default '0', + `ReqSpellCast3` mediumint(8) unsigned NOT NULL default '0', + `ReqSpellCast4` mediumint(8) unsigned NOT NULL default '0', + `RewChoiceItemId1` mediumint(8) unsigned NOT NULL default '0', + `RewChoiceItemId2` mediumint(8) unsigned NOT NULL default '0', + `RewChoiceItemId3` mediumint(8) unsigned NOT NULL default '0', + `RewChoiceItemId4` mediumint(8) unsigned NOT NULL default '0', + `RewChoiceItemId5` mediumint(8) unsigned NOT NULL default '0', + `RewChoiceItemId6` mediumint(8) unsigned NOT NULL default '0', + `RewChoiceItemCount1` smallint(5) unsigned NOT NULL default '0', + `RewChoiceItemCount2` smallint(5) unsigned NOT NULL default '0', + `RewChoiceItemCount3` smallint(5) unsigned NOT NULL default '0', + `RewChoiceItemCount4` smallint(5) unsigned NOT NULL default '0', + `RewChoiceItemCount5` smallint(5) unsigned NOT NULL default '0', + `RewChoiceItemCount6` smallint(5) unsigned NOT NULL default '0', + `RewItemId1` mediumint(8) unsigned NOT NULL default '0', + `RewItemId2` mediumint(8) unsigned NOT NULL default '0', + `RewItemId3` mediumint(8) unsigned NOT NULL default '0', + `RewItemId4` mediumint(8) unsigned NOT NULL default '0', + `RewItemCount1` smallint(5) unsigned NOT NULL default '0', + `RewItemCount2` smallint(5) unsigned NOT NULL default '0', + `RewItemCount3` smallint(5) unsigned NOT NULL default '0', + `RewItemCount4` smallint(5) unsigned NOT NULL default '0', + `RewRepFaction1` smallint(5) unsigned NOT NULL default '0' COMMENT 'faction id from Faction.dbc in this case', + `RewRepFaction2` smallint(5) unsigned NOT NULL default '0' COMMENT 'faction id from Faction.dbc in this case', + `RewRepFaction3` smallint(5) unsigned NOT NULL default '0' COMMENT 'faction id from Faction.dbc in this case', + `RewRepFaction4` smallint(5) unsigned NOT NULL default '0' COMMENT 'faction id from Faction.dbc in this case', + `RewRepFaction5` smallint(5) unsigned NOT NULL default '0' COMMENT 'faction id from Faction.dbc in this case', + `RewRepValue1` mediumint(9) NOT NULL default '0', + `RewRepValue2` mediumint(9) NOT NULL default '0', + `RewRepValue3` mediumint(9) NOT NULL default '0', + `RewRepValue4` mediumint(9) NOT NULL default '0', + `RewRepValue5` mediumint(9) NOT NULL default '0', + `RewOrReqMoney` int(11) NOT NULL default '0', + `RewMoneyMaxLevel` int(10) unsigned NOT NULL default '0', + `RewSpell` mediumint(8) unsigned NOT NULL default '0', + `RewSpellCast` mediumint(8) unsigned NOT NULL default '0', + `RewMailTemplateId` mediumint(8) unsigned NOT NULL default '0', + `RewMailDelaySecs` int(11) unsigned NOT NULL default '0', + `PointMapId` smallint(5) unsigned NOT NULL default '0', + `PointX` float NOT NULL default '0', + `PointY` float NOT NULL default '0', + `PointOpt` mediumint(8) unsigned NOT NULL default '0', + `DetailsEmote1` smallint(5) unsigned NOT NULL default '0', + `DetailsEmote2` smallint(5) unsigned NOT NULL default '0', + `DetailsEmote3` smallint(5) unsigned NOT NULL default '0', + `DetailsEmote4` smallint(5) unsigned NOT NULL default '0', + `IncompleteEmote` smallint(5) unsigned NOT NULL default '0', + `CompleteEmote` smallint(5) unsigned NOT NULL default '0', + `OfferRewardEmote1` smallint(5) unsigned NOT NULL default '0', + `OfferRewardEmote2` smallint(5) unsigned NOT NULL default '0', + `OfferRewardEmote3` smallint(5) unsigned NOT NULL default '0', + `OfferRewardEmote4` smallint(5) unsigned NOT NULL default '0', + `StartScript` mediumint(8) unsigned NOT NULL default '0', + `CompleteScript` mediumint(8) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Quest System'; + +-- +-- Dumping data for table `quest_template` +-- + +LOCK TABLES `quest_template` WRITE; +/*!40000 ALTER TABLE `quest_template` DISABLE KEYS */; +/*!40000 ALTER TABLE `quest_template` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `reference_loot_template` +-- + +DROP TABLE IF EXISTS `reference_loot_template`; +CREATE TABLE `reference_loot_template` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `item` mediumint(8) unsigned NOT NULL default '0', + `ChanceOrQuestChance` float NOT NULL default '100', + `groupid` tinyint(3) unsigned NOT NULL default '0', + `mincountOrRef` mediumint(9) NOT NULL default '1', + `maxcount` tinyint(3) unsigned NOT NULL default '1', + `lootcondition` tinyint(3) unsigned NOT NULL default '0', + `condition_value1` mediumint(8) unsigned NOT NULL default '0', + `condition_value2` mediumint(8) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`,`item`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Loot System'; + +-- +-- Dumping data for table `reference_loot_template` +-- + +LOCK TABLES `reference_loot_template` WRITE; +/*!40000 ALTER TABLE `reference_loot_template` DISABLE KEYS */; +/*!40000 ALTER TABLE `reference_loot_template` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `reserved_name` +-- + +DROP TABLE IF EXISTS `reserved_name`; +CREATE TABLE `reserved_name` ( + `name` varchar(12) NOT NULL default '', + PRIMARY KEY (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player Reserved Names'; + +-- +-- Dumping data for table `reserved_name` +-- + +LOCK TABLES `reserved_name` WRITE; +/*!40000 ALTER TABLE `reserved_name` DISABLE KEYS */; +/*!40000 ALTER TABLE `reserved_name` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `skill_discovery_template` +-- + +DROP TABLE IF EXISTS `skill_discovery_template`; +CREATE TABLE `skill_discovery_template` ( + `spellId` mediumint(8) unsigned NOT NULL default '0' COMMENT 'SpellId of the discoverable spell', + `reqSpell` mediumint(8) unsigned NOT NULL default '0' COMMENT 'spell requirement', + `chance` float NOT NULL default '0' COMMENT 'chance to discover', + PRIMARY KEY (`spellId`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Skill Discovery System'; + +-- +-- Dumping data for table `skill_discovery_template` +-- + +LOCK TABLES `skill_discovery_template` WRITE; +/*!40000 ALTER TABLE `skill_discovery_template` DISABLE KEYS */; +/*!40000 ALTER TABLE `skill_discovery_template` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `skill_extra_item_template` +-- + +DROP TABLE IF EXISTS `skill_extra_item_template`; +CREATE TABLE `skill_extra_item_template` ( + `spellId` mediumint(8) unsigned NOT NULL default '0' COMMENT 'SpellId of the item creation spell', + `requiredSpecialization` mediumint(8) unsigned NOT NULL default '0' COMMENT 'Specialization spell id', + `additionalCreateChance` float NOT NULL default '0' COMMENT 'chance to create add', + `additionalMaxNum` tinyint(3) unsigned NOT NULL default '0' COMMENT 'max num of adds', + PRIMARY KEY (`spellId`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Skill Specialization System'; + +-- +-- Dumping data for table `skill_extra_item_template` +-- + +LOCK TABLES `skill_extra_item_template` WRITE; +/*!40000 ALTER TABLE `skill_extra_item_template` DISABLE KEYS */; +/*!40000 ALTER TABLE `skill_extra_item_template` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `skill_fishing_base_level` +-- + +DROP TABLE IF EXISTS `skill_fishing_base_level`; +CREATE TABLE `skill_fishing_base_level` ( + `entry` mediumint(8) unsigned NOT NULL default '0' COMMENT 'Area identifier', + `skill` smallint(6) NOT NULL default '0' COMMENT 'Base skill level requirement', + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Fishing system'; + +-- +-- Dumping data for table `skill_fishing_base_level` +-- + +LOCK TABLES `skill_fishing_base_level` WRITE; +/*!40000 ALTER TABLE `skill_fishing_base_level` DISABLE KEYS */; +/*!40000 ALTER TABLE `skill_fishing_base_level` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `skinning_loot_template` +-- + +DROP TABLE IF EXISTS `skinning_loot_template`; +CREATE TABLE `skinning_loot_template` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `item` mediumint(8) unsigned NOT NULL default '0', + `ChanceOrQuestChance` float NOT NULL default '100', + `groupid` tinyint(3) unsigned NOT NULL default '0', + `mincountOrRef` mediumint(9) NOT NULL default '1', + `maxcount` tinyint(3) unsigned NOT NULL default '1', + `lootcondition` tinyint(3) unsigned NOT NULL default '0', + `condition_value1` mediumint(8) unsigned NOT NULL default '0', + `condition_value2` mediumint(8) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`,`item`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Loot System'; + +-- +-- Dumping data for table `skinning_loot_template` +-- + +LOCK TABLES `skinning_loot_template` WRITE; +/*!40000 ALTER TABLE `skinning_loot_template` DISABLE KEYS */; +/*!40000 ALTER TABLE `skinning_loot_template` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `spell_affect` +-- + +DROP TABLE IF EXISTS `spell_affect`; +CREATE TABLE `spell_affect` ( + `entry` smallint(5) unsigned NOT NULL default '0', + `effectId` tinyint(3) unsigned NOT NULL default '0', + `SpellFamilyMask` bigint(20) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`,`effectId`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `spell_affect` +-- + +LOCK TABLES `spell_affect` WRITE; +/*!40000 ALTER TABLE `spell_affect` DISABLE KEYS */; +INSERT INTO `spell_affect` VALUES +(5420,2,0x00001012100000D0), +(8875,1,0x0000040000000000), +(11069,0,0x0000000000000001), +(11070,0,0x0000000000000020), +(11071,0,0x0000000000100000), +(11083,0,0x0000000000C20017), +(11124,0,0x0000000008C20017), +(11151,0,0x00000000000202E0), +(11160,0,0x00000001020203E0), +(11175,1,0x0000000000100000), +(11207,0,0x00000000000202E0), +(11222,0,0x0000000020001800), +(11242,0,0x0000000020001000), +(11247,0,0x0000000000002000), +(12042,0,0x0000000020E01AF7), +(12042,1,0x0000000020E01AF7), +(12042,2,0x0000000020E01AF7), +(12043,0,0x0000000021400035), +(12285,0,0x0000000000000001), +(12286,0,0x0000000000000020), +(12287,1,0x0000000000000080), +(12295,1,0x0000000002000000), +(12295,2,0x0000040000000000), +(12301,0,0x0000000000000100), +(12303,1,0x0000100000000000), +(12308,0,0x0000000000004000), +(12318,0,0x0000008000010000), +(12321,0,0x0000008000030000), +(12321,1,0x0000008000030000), +(12330,0,0x0000000000200000), +(12338,0,0x0000000000000001), +(12339,0,0x0000000000000001), +(12340,0,0x0000000000000001), +(12341,0,0x0000000000000001), +(12351,0,0x0000000000C20017), +(12378,0,0x0000000008C20017), +(12398,0,0x0000000008C20017), +(12399,0,0x0000000008C20017), +(12400,0,0x0000000008C20017), +(12467,0,0x0000000020001000), +(12469,0,0x0000000020001000), +(12472,1,0x00000000E44008A5), +(12473,0,0x0000000000000020), +(12496,0,0x0000000000100000), +(12497,0,0x0000000000100000), +(12518,0,0x00000001020203E0), +(12519,0,0x00000001020203E0), +(12536,0,0x0000000020C01AF7), +(12569,1,0x0000000000100000), +(12571,1,0x0000000000100000), +(12606,0,0x0000000000002000), +(12658,0,0x0000000000000020), +(12659,0,0x0000000000000020), +(12665,1,0x0000000000000080), +(12666,1,0x0000000000000080), +(12672,0,0x00000000000202E0), +(12676,1,0x0000000002000000), +(12676,2,0x0000040000000000), +(12677,1,0x0000000002000000), +(12677,2,0x0000040000000000), +(12697,0,0x0000000000000001), +(12788,1,0x0000100000000000), +(12789,1,0x0000100000000000), +(12810,0,0x0000000000004000), +(12811,0,0x0000000000004000), +(12818,0,0x0000000000000100), +(12835,0,0x0000008000030000), +(12835,1,0x0000008000030000), +(12836,0,0x0000008000030000), +(12836,1,0x0000008000030000), +(12837,0,0x0000008000030000), +(12837,1,0x0000008000030000), +(12838,0,0x0000008000030000), +(12838,1,0x0000008000030000), +(12839,0,0x0000000020001800), +(12840,0,0x0000000020001800), +(12841,0,0x0000000020001800), +(12842,0,0x0000000020001800), +(12857,0,0x0000008000010000), +(12858,0,0x0000008000010000), +(12860,0,0x0000008000010000), +(12861,0,0x0000008000010000), +(12862,0,0x0000000000200000), +(12945,1,0x0000000000001000), +(12952,0,0x00000000000202E0), +(12953,0,0x00000000000202E0), +(12954,0,0x00000000000202E0), +(12957,0,0x00000000000202E0), +(13733,0,0x0000000000000004), +(13733,1,0x0000000400000000), +(13742,0,0x0000000000000060), +(13743,0,0x0000000000000040), +(13865,0,0x0000000000000004), +(13865,1,0x0000000400000000), +(13866,0,0x0000000000000004), +(13866,1,0x0000000400000000), +(13872,0,0x0000000000000060), +(13875,0,0x0000000000000040), +(13975,0,0x0000000000400000), +(13975,1,0x0000000000400000), +(13976,0,0x0000000000000700), +(13979,0,0x0000000000000700), +(13980,0,0x0000000000000700), +(13981,0,0x0000000001000000), +(13981,1,0x0000000000000800), +(14057,0,0x0000000600000304), +(14062,0,0x0000000000400000), +(14062,1,0x0000000000400000), +(14063,0,0x0000000000400000), +(14063,1,0x0000000000400000), +(14064,0,0x0000000000400000), +(14064,1,0x0000000000400000), +(14065,0,0x0000000000400000), +(14065,1,0x0000000000400000), +(14066,0,0x0000000001000000), +(14066,1,0x0000000000000800), +(14072,0,0x0000000600000304), +(14073,0,0x0000000600000304), +(14074,0,0x0000000600000304), +(14075,0,0x0000000600000304), +(14076,0,0x0000000001000080), +(14076,1,0x0000000001000080), +(14082,0,0x0000000000000500), +(14083,0,0x0000000000000500), +(14094,0,0x0000000001000080), +(14094,1,0x0000000001000080), +(14113,0,0x000000000001E000), +(14114,0,0x000000000001E000), +(14115,0,0x000000000001E000), +(14116,0,0x000000000001E000), +(14117,0,0x000000000001E000), +(14128,0,0x000000062600000E), +(14132,0,0x000000062600000E), +(14135,0,0x000000062600000E), +(14136,0,0x000000062600000E), +(14137,0,0x000000062600000E), +(14143,0,0x0000000004000206), +(14149,0,0x0000000004000206), +(14162,0,0x0000000000020000), +(14163,0,0x0000000000020000), +(14164,0,0x0000000000020000), +(14168,0,0x0000000000080000), +(14169,0,0x0000000000080000), +(14174,0,0x0000000000200000), +(14175,0,0x0000000000200000), +(14176,0,0x0000000000200000), +(14177,0,0x0000000C6012031E), +(14179,0,0x00000009003E0000), +(14520,0,0x00000963BF61C16F), +(14523,1,0x000000208030016B), +(14523,2,0x000000208030016B), +(14743,0,0x0000049440963E90), +(14747,0,0x0000000000000002), +(14750,0,0x0000000000000010), +(14751,0,0xFFFFFFFFFFFFFFFF), +(14751,1,0xFFFFFFFFFFFFFFFF), +(14770,0,0x0000000000000002), +(14771,0,0x0000000000000002), +(14772,0,0x0000000000000010), +(14780,0,0x00000963BF61C16F), +(14781,0,0x00000963BF61C16F), +(14782,0,0x00000963BF61C16F), +(14783,0,0x00000963BF61C16F), +(14784,1,0x000000208030016B), +(14784,2,0x000000208030016B), +(14785,1,0x000000208030016B), +(14785,2,0x000000208030016B), +(14786,1,0x000000208030016B), +(14786,2,0x000000208030016B), +(14787,1,0x000000208030016B), +(14787,2,0x000000208030016B), +(14908,0,0x0000000000000040), +(14909,1,0x0000000000100080), +(14911,0,0x0000002000000200), +(14912,0,0x0000000000041400), +(14913,0,0x0000000400041E00), +(15012,0,0x0000000400041E00), +(15013,0,0x0000000000041400), +(15014,0,0x0000000000041400), +(15017,1,0x0000000000100080), +(15018,0,0x0000002000000200), +(15020,0,0x0000000000000040), +(15047,0,0x00000000000202E0), +(15052,0,0x00000000000202E0), +(15053,0,0x00000000000202E0), +(15257,0,0x000004020288A010), +(15259,0,0x0000000202002000), +(15259,1,0x0000040000808000), +(15260,0,0x00000442068BA000), +(15272,0,0x00000D4A068BE104), +(15307,0,0x0000000202002000), +(15307,1,0x0000040000808000), +(15308,0,0x0000000202002000), +(15308,1,0x0000040000808000), +(15309,0,0x0000000202002000), +(15309,1,0x0000040000808000), +(15310,0,0x0000000202002000), +(15310,1,0x0000040000808000), +(15318,0,0x00000D4A068BE104), +(15320,0,0x00000D4A068BE104), +(15327,0,0x00000442068BA000), +(15328,0,0x00000442068BA000), +(15329,0,0x00000442068BA000), +(15330,0,0x00000442068BA000), +(15331,0,0x000004020288A010), +(15332,0,0x000004020288A010), +(15333,0,0x000004020288A010), +(15334,0,0x000004020288A010), +(16035,0,0x0000000090100003), +(16038,0,0x0000000040000000), +(16039,0,0x0000000090100003), +(16041,0,0x0000000000000003), +(16043,0,0x0000000000000008), +(16043,1,0x0000000100000000), +(16086,0,0x0000000000000020), +(16086,1,0x0000000000000020), +(16086,2,0x0000000000000004), +(16089,0,0x00000004D3300407), +(16105,0,0x0000000090100003), +(16106,0,0x0000000090100003), +(16106,1,0x0000000090100003), +(16107,0,0x0000000090100003), +(16108,0,0x0000000090100003), +(16109,0,0x0000000090100003), +(16110,0,0x0000000090100003), +(16111,0,0x0000000090100003), +(16112,0,0x0000000090100003), +(16117,0,0x0000000000000003), +(16118,0,0x0000000000000003), +(16119,0,0x0000000000000003), +(16120,0,0x0000000000000003), +(16130,0,0x0000000000000008), +(16130,1,0x0000000100000000), +(16160,0,0x0000000040000000), +(16161,0,0x0000000040000000), +(16166,0,0x0000000090100003), +(16166,1,0x0000000090100003), +(16173,0,0x0000000020081018), +(16179,0,0x00000000000000C0), +(16181,0,0x00000000000001C0), +(16184,0,0x0000000000000200), +(16184,1,0x0000000000000200), +(16187,0,0x0000000000006000), +(16187,1,0x0000000000006000), +(16188,0,0x00000000000009C3), +(16189,0,0x000001000403E000), +(16205,0,0x0000000000006000), +(16205,1,0x0000000000006000), +(16206,0,0x0000000000006000), +(16206,1,0x0000000000006000), +(16207,0,0x0000000000006000), +(16207,1,0x0000000000006000), +(16208,0,0x0000000000006000), +(16208,1,0x0000000000006000), +(16209,1,0x0000000000000200), +(16214,0,0x00000000000000C0), +(16215,0,0x00000000000000C0), +(16216,0,0x00000000000000C0), +(16217,0,0x00000000000000C0), +(16222,0,0x0000000020081018), +(16223,0,0x0000000020081018), +(16224,0,0x0000000020081018), +(16225,0,0x0000000020081018), +(16230,0,0x00000000000001C0), +(16232,0,0x00000000000001C0), +(16233,0,0x00000000000001C0), +(16234,0,0x00000000000001C0), +(16246,0,0x0000000090100003), +(16258,0,0x0000000000008000), +(16258,1,0x0000000000040000), +(16259,0,0x0000000000010000), +(16259,1,0x0000000000020000), +(16261,0,0x0000000000000400), +(16266,0,0x0000000000400000), +(16266,1,0x0000000001000000), +(16266,2,0x0000000000800000), +(16290,0,0x0000000000000400), +(16291,0,0x0000000000000400), +(16293,0,0x0000000000008000), +(16293,1,0x0000000000040000), +(16295,0,0x0000000000010000), +(16295,1,0x0000000000020000), +(16493,0,0x0000014D2A600CEF), +(16494,0,0x0000014D2A600CEF), +(16513,0,0x000000080001E000), +(16513,1,0x000000000001E000), +(16513,2,0x000000000001E000), +(16514,0,0x000000080001E000), +(16514,1,0x000000000001E000), +(16514,2,0x000000000001E000), +(16515,0,0x000000080001E000), +(16515,1,0x000000000001E000), +(16515,2,0x000000000001E000), +(16544,2,0x0000000000000004), +(16578,0,0x0000000000000003), +(16579,0,0x0000000000000003), +(16580,0,0x0000000000000003), +(16581,0,0x0000000000000003), +(16582,0,0x0000000000000003), +(16719,0,0x000000080001E000), +(16719,1,0x000000000001E000), +(16719,2,0x000000000001E000), +(16720,0,0x000000080001E000), +(16720,1,0x000000000001E000), +(16720,2,0x000000000001E000), +(16757,0,0x00000000000200A0), +(16757,1,0x0000000000000240), +(16758,0,0x00000000000200A0), +(16758,1,0x0000000000000240), +(16763,0,0x0000000000000020), +(16765,0,0x0000000000000020), +(16766,0,0x0000000000000020), +(16814,0,0x0000000000000005), +(16815,0,0x0000000000000005), +(16816,0,0x0000000000000005), +(16817,0,0x0000000000000005), +(16818,0,0x0000000000000005), +(16819,0,0x0002122000600707), +(16820,0,0x0002122000600707), +(16821,0,0x0000000000000002), +(16821,1,0x0000000000000002), +(16821,2,0x0000000000000002), +(16822,0,0x0000000000000002), +(16822,1,0x0000000000000002), +(16822,2,0x0000000000000002), +(16833,0,0x0000E000E2000000), +(16834,0,0x0000E000E2000000), +(16835,0,0x0000E000E2000000), +(16836,1,0x0000000000000300), +(16839,1,0x0000000000000300), +(16840,1,0x0000000000000300), +(16850,1,0x0000000000000001), +(16870,0,0x001007F100E3FEFF), +(16886,0,0x0000000001000265), +(16896,0,0x0000000000000007), +(16896,1,0x0000000000000007), +(16897,0,0x0000000000000007), +(16897,1,0x0000000000000007), +(16899,0,0x0000000000000007), +(16899,1,0x0000000000000007), +(16900,0,0x0000000000000007), +(16900,1,0x0000000000000007), +(16901,0,0x0000000000000007), +(16901,1,0x0000000000000007), +(16918,0,0x0000002000000200), +(16919,0,0x0000002000000200), +(16920,0,0x0000002000000200), +(16923,1,0x0000000000000001), +(16924,1,0x0000000000000001), +(16934,0,0x0010004000000800), +(16934,1,0x0000040000001000), +(16935,0,0x0010004000000800), +(16935,1,0x0000040000001000), +(16936,0,0x0010004000000800), +(16936,1,0x0000040000001000), +(16937,0,0x0010004000000800), +(16937,1,0x0000040000001000), +(16938,0,0x0010004000000800), +(16938,1,0x0000040000001000), +(16947,1,0x0000000002000000), +(16948,1,0x0000000002000000), +(16949,1,0x0000000002000000), +(16966,0,0x0000000000008000), +(16966,1,0x0000010000000000), +(16968,0,0x0000000000008000), +(16968,1,0x0000010000000000), +(16998,0,0x0000000000001000), +(16998,2,0x0000000000001000), +(16999,0,0x0000000000001000), +(16999,2,0x0000000000001000), +(17104,0,0x00000010000000F0), +(17104,1,0x00000010000000F0), +(17111,0,0x0000000000000010), +(17112,0,0x0000000000000010), +(17113,0,0x0000000000000010), +(17114,0,0x0000000000000010), +(17115,0,0x0000000000000010), +(17116,0,0x0002002010000261), +(17118,0,0x001005D000E193F7), +(17118,1,0x0004103000340750), +(17119,0,0x001005D000E193F7), +(17119,1,0x0004103000340750), +(17120,0,0x001005D000E193F7), +(17120,1,0x0004103000340750), +(17121,0,0x001005D000E193F7), +(17121,1,0x0004103000340750), +(17122,0,0x001005D000E193F7), +(17122,1,0x0004103000340750), +(17123,0,0x0000000000000080), +(17124,0,0x0000000000000080), +(17191,0,0x0000000000000040), +(17322,0,0x00000542068AA004), +(17323,0,0x00000542068AA004), +(17768,0,0x0000000040000000), +(17768,1,0x0000000080000000), +(17778,0,0x000010C0000003E5), +(17779,0,0x000010C0000003E5), +(17780,0,0x000010C0000003E5), +(17781,0,0x000010C0000003E5), +(17782,0,0x000010C0000003E5), +(17788,1,0x0000008000000000), +(17789,1,0x0000008000000000), +(17790,1,0x0000008000000000), +(17791,1,0x0000008000000000), +(17792,1,0x0000008000000000), +(17904,0,0x0000000000000000), +(17912,0,0x0000000000000000), +(17913,0,0x0000000000000000), +(17914,0,0x0000000000000000), +(17915,0,0x0000000000000000), +(17916,0,0x0000000000000000), +(17917,0,0x000010C0000003A5), +(17917,1,0x000010C0000003E5), +(17918,0,0x000010C0000003A5), +(17918,1,0x000010C0000003E5), +(17927,0,0x0000000000000100), +(17929,0,0x0000000000000100), +(17930,0,0x0000000000000100), +(17941,0,0x0000000000000001), +(17954,0,0x000000C000001364), +(17954,1,0x000000C000001364), +(17954,2,0x0000004000000000), +(17955,0,0x000000C000001364), +(17955,1,0x000000C000001364), +(17955,2,0x0000004000000000), +(17956,0,0x000000C000001364), +(17956,1,0x000000C000001364), +(17956,2,0x0000004000000000), +(17957,0,0x000000C000001364), +(17957,1,0x000000C000001364), +(17957,2,0x0000004000000000), +(17958,0,0x000000C000001364), +(17958,1,0x000000C000001364), +(17958,2,0x0000004000000000), +(17959,0,0x000010C0000003E5), +(18126,0,0x0000000000001000), +(18127,0,0x0000000000001000), +(18130,0,0x000010C0000003E5), +(18131,0,0x000010C0000003E5), +(18132,0,0x000010C0000003E5), +(18133,0,0x000010C0000003E5), +(18134,0,0x000010C0000003E5), +(18135,0,0x000010C0000003E5), +(18136,0,0x000010C0000003E5), +(18174,0,0x0000071B804CC41A), +(18175,0,0x0000071B804CC41A), +(18176,0,0x0000071B804CC41A), +(18177,0,0x0000071B804CC41A), +(18178,0,0x0000071B804CC41A), +(18179,0,0x0000000000008000), +(18180,0,0x0000000000008000), +(18213,0,0x0000000000004000), +(18213,1,0x0000871B804CC41A), +(18218,0,0x000007138048C41A), +(18219,0,0x000007138048C41A), +(18271,0,0x000011130008A48B), +(18271,1,0x000011130008A48B), +(18272,0,0x000011130008A48B), +(18272,1,0x000011130008A48B), +(18273,0,0x000011130008A48B), +(18273,1,0x000011130008A48B), +(18274,0,0x000011130008A48B), +(18274,1,0x000011130008A48B), +(18275,0,0x000011130008A48B), +(18275,1,0x000011130008A48B), +(18288,0,0x0000000200000400), +(18288,1,0x0000000000400000), +(18372,1,0x0000871B804CC41A), +(18427,0,0x0000000000020006), +(18428,0,0x0000000000020006), +(18429,0,0x0000000000020006), +(18544,0,0x0000041202F8A090), +(18544,1,0x0000001202582090), +(18544,2,0x0000040000A08000), +(18547,0,0x0000041202F8A090), +(18547,1,0x0000001202582090), +(18547,2,0x0000040000A08000), +(18548,0,0x0000041202F8A090), +(18548,1,0x0000001202582090), +(18548,2,0x0000040000A08000), +(18549,0,0x0000041202F8A090), +(18549,1,0x0000001202582090), +(18549,2,0x0000040000A08000), +(18550,0,0x0000041202F8A090), +(18550,1,0x0000001202582090), +(18550,2,0x0000040000A08000), +(18703,1,0x0000000001000000), +(18704,1,0x0000000001000000), +(18731,0,0x0000000010000000), +(18743,0,0x0000000010000000), +(18744,0,0x0000000010000000), +(18748,0,0x0000000008000000), +(18749,0,0x0000000008000000), +(18750,0,0x0000000008000000), +(18767,1,0x0000000000020000), +(18768,1,0x0000000000020000), +(18821,0,0x0000000000000800), +(18821,1,0x0000000000000800), +(18821,2,0x0000000000000800), +(18822,0,0x0000000000000800), +(18822,1,0x0000000000000800), +(18822,2,0x0000000000000800), +(18827,0,0x0000000000000400), +(18829,0,0x0000000000000400), +(19239,0,0x0000000000000018), +(19239,1,0x0000000000000004), +(19245,0,0x0000000000000018), +(19245,1,0x0000200000000004), +(19416,0,0x000210810007FA00), +(19417,0,0x000210810007FA00), +(19418,0,0x000210810007FA00), +(19419,0,0x000210810007FA00), +(19420,0,0x000210810007FA00), +(19461,0,0x0000000000003000), +(19461,1,0x0000000000003000), +(19462,0,0x0000000000003000), +(19462,1,0x0000000000003000), +(19464,0,0x0000010000004000), +(19464,1,0x0000008000000000), +(19464,2,0x000011800000C000), +(19465,0,0x0000010000004000), +(19465,1,0x0000008000000000), +(19465,2,0x000011800000C000), +(19466,0,0x0000010000004000), +(19466,1,0x0000008000000000), +(19466,2,0x000011800000C000), +(19467,0,0x0000010000004000), +(19467,1,0x0000008000000000), +(19467,2,0x000011800000C000), +(19468,0,0x0000010000004000), +(19468,1,0x0000008000000000), +(19468,2,0x000011800000C000), +(19485,0,0x0000000100061801), +(19487,0,0x0000000100061801), +(19488,0,0x0000000100061801), +(19489,0,0x0000000100061801), +(19490,0,0x0000000100061801), +(19498,0,0x000210810007FA01), +(19499,0,0x000210810007FA01), +(19500,0,0x000210810007FA01), +(19549,0,0x0000000000080000), +(19550,0,0x0000000000080000), +(19551,0,0x0000000000080000), +(19552,0,0x0000000000100000), +(19552,1,0x0000020000000000), +(19553,0,0x0000000000100000), +(19553,1,0x0000020000000000), +(19554,0,0x0000000000100000), +(19554,1,0x0000020000000000), +(19555,0,0x0000000000100000), +(19555,1,0x0000020000000000), +(19556,0,0x0000000000100000), +(19556,1,0x0000020000000000), +(19559,0,0x0000000000200000), +(19560,0,0x0000000000200000), +(19572,1,0x0000000000800000), +(19573,1,0x0000000000800000), +(19583,0,0x0000000008000000), +(19584,0,0x0000000008000000), +(19585,0,0x0000000008000000), +(19586,0,0x0000000008000000), +(19587,0,0x0000000008000000), +(19590,0,0x0000000020000000), +(19592,0,0x0000000020000000), +(19598,0,0x0000000040000000), +(19599,0,0x0000000040000000), +(19600,0,0x0000000040000000), +(19601,0,0x0000000040000000), +(19602,0,0x0000000040000000), +(19609,0,0x0000000004000000), +(19610,0,0x0000000004000000), +(19612,0,0x0000000004000000), +(20101,0,0x000004000A000200), +(20102,0,0x000004000A000200), +(20103,0,0x000004000A000200), +(20104,0,0x000004000A000200), +(20105,0,0x000004000A000200), +(20138,0,0x0000000000000040), +(20139,0,0x0000000000000040), +(20140,0,0x0000000000000040), +(20141,0,0x0000000000000040), +(20142,0,0x0000000000000040), +(20174,0,0x0000000000000080), +(20174,1,0x0000000000000010), +(20175,0,0x0000000000000080), +(20175,1,0x0000000000000010), +(20216,0,0x00010000C0200000), +(20224,0,0x0000000008000400), +(20225,0,0x0000000008000400), +(20237,0,0x00000000C0000000), +(20238,0,0x00000000C0000000), +(20239,0,0x00000000C0000000), +(20249,0,0x0000000040000000), +(20250,0,0x0000000040000000), +(20251,0,0x0000000040000000), +(20254,0,0x0000000000020000), +(20254,1,0x0000000000020000), +(20254,2,0x0000000000020000), +(20255,0,0x0000000000020000), +(20255,1,0x0000000000020000), +(20255,2,0x0000000000020000), +(20256,0,0x0000000000020000), +(20256,1,0x0000000000020000), +(20256,2,0x0000000000020000), +(20330,0,0x0000000008000400), +(20331,0,0x0000000008000400), +(20332,0,0x0000000008000400), +(20335,0,0x0000000020000000), +(20336,0,0x0000000020000000), +(20337,0,0x0000000020000000), +(20359,0,0x0000000080000000), +(20360,0,0x0000000080000000), +(20361,0,0x0000000080000000), +(20468,1,0x0000000000000001), +(20469,1,0x0000000000000001), +(20470,1,0x0000000000000001), +(20575,0,0x0000000004000000), +(20575,1,0x0000000004000000), +(20576,0,0x0000000002000000), +(21873,0,0x0000E000E2000000), +(21881,0,0x000000000001E000), +(21887,0,0x0000036C2A764EEF), +(21895,0,0x000000000403E000), +(21899,0,0x0000000000000100), +(21942,1,0x0000000008000000), +(22008,0,0x0000000021400035), +(23025,0,0x0000000000010000), +(23047,0,0x0000040000000000), +(23047,1,0x0000040000000000), +(23158,0,0x0000000000000200), +(23300,0,0x0000000020000000), +(23555,0,0x000010C0000003E5), +(23561,0,0x0000000000004000), +(23566,0,0x0000000000001000), +(23724,0,0x0000E000E2000000), +(23726,0,0x0000000000002000), +(23726,1,0x0000000000010000), +(24348,0,0x0000000000200000), +(24429,0,0x0000000000004000), +(24431,0,0x0000000400000000), +(24460,0,0x0000000010000180), +(24469,0,0x0000000001000000), +(24499,0,0x0000000000000400), +(24542,1,0x00000000000000F0), +(24546,1,0x0000000400041E00), +(24691,0,0x0000000000003000), +(24691,1,0x0000000000003000), +(24943,0,0x00000010000000F0), +(24943,1,0x00000010000000F0), +(24944,0,0x00000010000000F0), +(24944,1,0x00000010000000F0), +(24945,0,0x00000010000000F0), +(24945,1,0x00000010000000F0), +(24946,0,0x00000010000000F0), +(24946,1,0x00000010000000F0), +(26106,0,0x0000000010000000), +(26109,0,0x00000080000F0000), +(26112,0,0x0000000000000020), +(26118,0,0x0000000004000000), +(26118,1,0x0000000004000000), +(26174,0,0x0000000000000020), +(27789,1,0x0000000010400200), +(27790,1,0x0000000010400200), +(27828,0,0x0000049440963E90), +(27846,0,0x0000000000000020), +(27850,0,0x0000000000000040), +(27851,0,0x0000000000001000), +(28088,0,0x000000000001E000), +(28107,0,0x0000000000040000), +(28539,0,0x0000000000001000), +(28682,0,0x0000004008C20017), +(28743,0,0x00000000000000F0), +(28746,1,0x0000000100000406), +(28751,0,0x0000000000021000), +(28755,0,0x0000000000000020), +(28763,0,0x0000000004000000), +(28774,0,0x0000000000008000), +(28775,0,0x0000000100000000), +(28787,0,0x0000000000001000), +(28807,0,0x0000000000000040), +(28808,0,0x0000000411041E40), +(28811,0,0x0000000002020006), +(28814,0,0x0000000000020000), +(28815,0,0x0000000002000006), +(28818,0,0x0000000020081018), +(28821,0,0x0000000000000400), +(28829,0,0x0000000000000002), +(28831,0,0x0000000000000001), +(28842,0,0x0000000100004440), +(28843,0,0x0000000000088000), +(28844,0,0x0000000000000400), +(28852,0,0x0000000000000200), +(28852,1,0x0000000020000000), +(28855,0,0x0000000000000800), +(28855,1,0x0010000000000000), +(28999,0,0x0000000000000003), +(29000,0,0x0000000000000003), +(29005,0,0x0000000090100003), +(29063,0,0x00000000000009C3), +(29079,0,0x0000000000400000), +(29079,1,0x0000000001000000), +(29079,2,0x0000000000800000), +(29080,0,0x0000000000400000), +(29080,1,0x0000000001000000), +(29080,2,0x0000000000800000), +(29171,0,0x0000000000004000), +(29187,0,0x00000000000001C0), +(29187,1,0x0004103000340750), +(29189,0,0x00000000000001C0), +(29189,1,0x0004103000340750), +(29191,0,0x00000000000001C0), +(29191,1,0x0004103000340750), +(29202,0,0x0000000000000040), +(29205,0,0x0000000000000040), +(29206,0,0x0000000000000040), +(29438,0,0x0000000000D000D7), +(29439,0,0x0000000000D000D7), +(29440,0,0x0000000000D000D7), +(29721,0,0x0000000400000000), +(29723,0,0x0000000800002010), +(29723,1,0x0000000800002010), +(29724,0,0x0000000800002010), +(29724,1,0x0000000800002010), +(29725,0,0x0000000800002010), +(29725,1,0x0000000800002010), +(29759,1,0x0000075D6E6ECEEF), +(29760,1,0x0000075D6E6ECEEF), +(29761,1,0x0000075D6E6ECEEF), +(29762,1,0x0000075D6E6ECEEF), +(29763,1,0x0000075D6E6ECEEF), +(29776,0,0x0000000400000000), +(29787,0,0x0000036C2A764EEF), +(29790,0,0x0000036C2A764EEF), +(29792,0,0x0000036C2A764EEF), +(29836,0,0x0000001000000020), +(29859,0,0x0000001000000020), +(29888,0,0x0000000040000000), +(29889,0,0x0000000040000000), +(29976,0,0x0000000021400035), +(30049,0,0x0000000000080000), +(30051,0,0x0000000000080000), +(30052,0,0x0000000000080000), +(30054,0,0x0000000800000000), +(30057,0,0x0000000800000000), +(30060,0,0x0000001000000402), +(30060,1,0x0000001000000402), +(30060,2,0x0000871B804CC41A), +(30061,0,0x0000001000000402), +(30061,1,0x0000001000000402), +(30061,2,0x0000871B804CC41A), +(30062,0,0x0000001000000402), +(30062,1,0x0000001000000402), +(30062,2,0x0000871B804CC41A), +(30063,0,0x0000001000000402), +(30063,1,0x0000001000000402), +(30063,2,0x0000871B804CC41A), +(30064,0,0x0000001000000402), +(30064,1,0x0000001000000402), +(30064,2,0x0000871B804CC41A), +(30085,0,0x0000071B804CC41A), +(30085,1,0x0000000000000400), +(30085,2,0x0000000000000002), +(30086,0,0x0000071B804CC41A), +(30086,1,0x0000000000000400), +(30086,2,0x0000000000000002), +(30143,0,0x0000002000000000), +(30144,0,0x0000002000000000), +(30145,0,0x0000002000000000), +(30242,0,0x0000200000000000), +(30245,0,0x0000200000000000), +(30246,0,0x0000200000000000), +(30247,0,0x0000200000000000), +(30248,0,0x0000200000000000), +(30251,0,0x000010C000000125), +(30256,0,0x000010C000000125), +(30288,0,0x0000004000000001), +(30289,0,0x0000004000000001), +(30290,0,0x0000004000000001), +(30291,0,0x0000004000000001), +(30292,0,0x0000004000000001), +(30319,1,0x0000400000000000), +(30320,1,0x0000400000000000), +(30321,1,0x0000400000000000), +(30326,0,0x0000000000040010), +(30327,0,0x0000000000040010), +(30328,0,0x0000000000040010), +(30812,0,0x00000C78B018141B), +(30813,0,0x00000C78B018141B), +(30814,0,0x00000C78B018141B), +(30872,0,0x0000000000000100), +(30873,0,0x0000000000000100), +(30892,0,0x0000000008000000), +(30893,0,0x0000000008000000), +(31216,1,0x0000000002000004), +(31217,1,0x0000000002000004), +(31218,1,0x0000000002000004), +(31219,1,0x0000000002000004), +(31220,1,0x0000000002000004), +(31226,0,0x000000000001E000), +(31227,0,0x000000000001E000), +(31234,0,0x000001002612030F), +(31234,1,0x0000000000100100), +(31235,0,0x000001002612030F), +(31235,1,0x0000000000100100), +(31236,0,0x000001002612030F), +(31236,1,0x0000000000100100), +(31237,0,0x000001002612030F), +(31237,1,0x0000000000100100), +(31238,0,0x000001002612030F), +(31238,1,0x0000000000100100), +(31571,0,0x0000000200000000), +(31572,0,0x0000000200000000), +(31573,0,0x0000000200000000), +(31579,0,0x0000000000200000), +(31579,1,0x0000000000000800), +(31582,0,0x0000000000200000), +(31582,1,0x0000000000000800), +(31583,0,0x0000000000200000), +(31583,1,0x0000000000000800), +(31656,0,0x0000000000000001), +(31657,0,0x0000000000000001), +(31658,0,0x0000000000000001), +(31659,0,0x0000000000000001), +(31660,0,0x0000000000000001), +(31670,0,0x0000000500000200), +(31672,0,0x0000000500000200), +(31682,0,0x0000000000000020), +(31682,1,0x0000000000000020), +(31683,0,0x0000000000000020), +(31683,1,0x0000000000000020), +(31684,0,0x0000000000000020), +(31684,1,0x0000000000000020), +(31685,0,0x0000000000000020), +(31685,1,0x0000000000000020), +(31686,0,0x0000000000000020), +(31686,1,0x0000000000000020), +(31821,0,0x0000000004020048), +(31825,0,0x0000000000001020), +(31825,1,0x0000000200000000), +(31826,0,0x0000000000001020), +(31826,1,0x0000000200000000), +(31834,0,0x0000000080000000), +(31844,1,0x000005401A00038C), +(31845,1,0x000005401A00038C), +(31848,0,0x0000000000400000), +(31848,1,0x0000000000400000), +(31849,0,0x0000000000400000), +(31849,1,0x0000000000400000), +(31869,0,0x0000002000000000), +(31870,0,0x0000002000000000), +(31879,0,0x0000000800000400), +(31880,0,0x0000000800000400), +(31881,0,0x0000000800000400), +(31882,0,0x0000000800000400), +(31883,0,0x0000000800000400), +(32043,1,0x000004000A000000), +(32203,1,0x0001100001C22000), +(32381,0,0x0000000000000002), +(32382,0,0x0000000000000002), +(32383,0,0x0000000000000002), +(32412,0,0x0000000000000400), +(32477,0,0x0000020000000000), +(32483,0,0x0000020000000000), +(32484,0,0x0000020000000000), +(32601,1,0x0000000020800008), +(32743,0,0x0000000000000800), +(32973,0,0x0000000090100000), +(33018,0,0x0000001000000000), +(33020,0,0x0000000000000400), +(33063,0,0x0000040000000000), +(33066,0,0x0000000000000002), +(33151,0,0x0000000000000080), +(33151,1,0x0000000000000080), +(33151,2,0x0000000000000080), +(33158,0,0x0000000000001000), +(33158,1,0x0000000000000800), +(33159,0,0x0000000000001000), +(33159,1,0x0000000000000800), +(33160,0,0x0000000000001000), +(33160,1,0x0000000000000800), +(33161,0,0x0000000000001000), +(33161,1,0x0000000000000800), +(33162,0,0x0000000000001000), +(33162,1,0x0000000000000800), +(33167,0,0x0000008100000000), +(33171,0,0x0000008100000000), +(33172,0,0x0000008100000000), +(33174,0,0x0000000000000020), +(33174,1,0x0000000000000020), +(33182,0,0x0000000000000020), +(33182,1,0x0000000000000020), +(33186,0,0x0000008000000000), +(33186,1,0x0000008000002080), +(33190,0,0x0000008000000000), +(33190,1,0x0000008000002080), +(33213,0,0x0000000000822000), +(33214,0,0x0000000000822000), +(33215,0,0x0000000000822000), +(33221,0,0x0000000200002000), +(33222,0,0x0000000200002000), +(33223,0,0x0000000200002000), +(33224,0,0x0000000200002000), +(33225,0,0x0000000200002000), +(33333,0,0x0000000020000000), +(33421,0,0x0000000200000000), +(33557,0,0x0000000000000200), +(33557,1,0x0000000020000000), +(33565,0,0x0000000000001000), +(33600,0,0x0000000000000400), +(33600,1,0x0000000000000400), +(33601,0,0x0000000000000400), +(33601,1,0x0000000000000400), +(33602,0,0x0000000000000400), +(33602,1,0x0000000000000400), +(33603,0,0x0000000000000004), +(33603,1,0x0000000000000001), +(33604,0,0x0000000000000004), +(33604,1,0x0000000000000001), +(33605,0,0x0000000000000004), +(33605,1,0x0000000000000001), +(33606,0,0x0000000000000004), +(33606,1,0x0000000000000001), +(33607,0,0x0000000000000004), +(33607,1,0x0000000000000001), +(33693,0,0x0000000000008000), +(33696,0,0x0000000000000001), +(33713,0,0x0000000200000000), +(33714,0,0x0000000200000000), +(33830,0,0x0000002000000000), +(33830,1,0x0000002000000000), +(33877,0,0x0000000000000002), +(33879,0,0x0000000000000020), +(33880,0,0x0000000000000020), +(33886,0,0x00000010000000D0), +(33887,0,0x00000010000000D0), +(33888,0,0x00000010000000D0), +(33889,0,0x00000010000000D0), +(33890,0,0x00000010000000D0), +(34128,0,0x0000001000000000), +(34129,0,0x0000000040000000), +(34129,1,0x0000000040000000), +(34131,0,0x0000000000000080), +(34131,1,0x0000000000000080), +(34253,0,0x0000010000000000), +(34297,0,0x0000080000000000), +(34300,0,0x0000080000000000), +(34318,0,0x0000000000000400), +(34318,1,0x0000002000000000), +(34323,0,0x0000008000800000), +(34453,1,0x0000000400000000), +(34454,1,0x0000000400000000), +(34455,0,0x0000002000000000), +(34455,1,0x0000004000000000), +(34459,0,0x0000002000000000), +(34459,1,0x0000004000000000), +(34460,0,0x0000002000000000), +(34460,1,0x0000004000000000), +(34462,1,0x0000000800000000), +(34464,1,0x0000000800000000), +(34465,1,0x0000000800000000), +(34466,1,0x0000001000000000), +(34467,1,0x0000001000000000), +(34468,1,0x0000001000000000), +(34469,1,0x0000001000000000), +(34470,1,0x0000001000000000), +(34491,0,0x00004000000000C2), +(34491,1,0x0000000000000080), +(34492,0,0x00004000000000C2), +(34492,1,0x0000000000000080), +(34493,0,0x00004000000000C2), +(34493,1,0x0000000000000080), +(34754,0,0x0000000400001800), +(34936,0,0x0000004000000001), +(34948,1,0x0000000000000020), +(34949,1,0x0000000000000020), +(35029,1,0x0000080000000000), +(35030,1,0x0000080000000000), +(35098,0,0x0000000000020801), +(35099,0,0x0000000000020801), +(35104,0,0x0000000000001000), +(35104,1,0x0000000000002000), +(35110,0,0x0000000000001000), +(35110,1,0x0000000000002000), +(35111,0,0x0000000000001000), +(35111,1,0x0000000000002000), +(35363,0,0x0000000000000005), +(35364,0,0x0000000000000005), +(35396,1,0x000004000A000000), +(35397,1,0x000004000A000000), +(35446,0,0x0000000002000000), +(35446,1,0x0000000002000000), +(35448,0,0x0000000002000000), +(35448,1,0x0000000002000000), +(35449,0,0x0000000002000000), +(35449,1,0x0000000002000000), +(35450,0,0x0000000002000000), +(35450,1,0x0000000002000000), +(35451,0,0x0000000002000000), +(35451,1,0x0000000002000000), +(35578,0,0x0000000028E212F7), +(35581,0,0x0000000028E212F7), +(36032,0,0x0000000020000000), +(36032,1,0x0000000020000000), +(36413,0,0x0000000000000001), +(36563,1,0x0000000000000204), +(36563,2,0x0000000000000100), +(37166,0,0x0000000000800000), +(37167,0,0x0000000000040000), +(37171,0,0x00000009003E0000), +(37180,0,0x0000000000000020), +(37181,0,0x0000000400000000), +(37183,0,0x0000010000000000), +(37184,0,0x0000040008000000), +(37184,1,0x0000040008000000), +(37185,0,0x0000004000000000), +(37186,0,0x0000000020000000), +(37187,0,0x0000020000000000), +(37190,0,0x0000000000000008), +(37191,0,0x0000004000000000), +(37194,0,0x0000000000800000), +(37207,0,0x0000000000000002), +(37209,0,0x0000000000000400), +(37209,1,0x0000002000000000), +(37210,0,0x0000000000004000), +(37211,0,0x0000008000000000), +(37212,0,0x0000010000000000), +(37223,0,0x0000000000010000), +(37224,0,0x0000001000000000), +(37225,0,0x0000000000000080), +(37234,0,0x0000000000000080), +(37240,0,0x0000000000000080), +(37241,0,0x0000020000000000), +(37286,0,0x0000000000000010), +(37287,0,0x0000E000E2000000), +(37292,0,0x0008000000000000), +(37297,0,0x0000100000000000), +(37313,0,0x0000000000000040), +(37314,0,0x0000001000000000), +(37316,0,0x0000000000000040), +(37325,0,0x0000000000000040), +(37333,0,0x0000000000008000), +(37333,1,0x0000010000000000), +(37376,0,0x0000001000000000), +(37380,0,0x0000000000000006), +(37423,0,0x0000000000000004), +(37424,0,0x0000000000008000), +(37438,0,0x0000000000000021), +(37439,0,0x0000002000000000), +(37439,1,0x0000004000000000), +(37439,2,0x0000008000000000), +(37441,0,0x0000000020000000), +(37441,1,0x0000000020000000), +(37447,0,0x0000010000000000), +(37481,0,0x0000000000000080), +(37484,0,0x0000000000000100), +(37485,0,0x0000000000001000), +(37505,0,0x0000000100000000), +(37507,0,0x0000000000000800), +(37508,0,0x0000000100061800), +(37512,0,0x00000080000F0000), +(37513,0,0x0000000000000001), +(37517,0,0x0000014D2A600CEF), +(37518,0,0x0000000400000000), +(37522,0,0x0000000000001000), +(37535,0,0x0000000002000000), +(37536,0,0x0000000000010000), +(37556,0,0x0000000400000000), +(37564,0,0x0000000000000200), +(37565,0,0x0000000000001000), +(37570,1,0x0000010000000000), +(37571,0,0x0000000000000080), +(37571,1,0x0000000000800000), +(37593,0,0x0000000000000040), +(37706,0,0x0000000411041E40), +(37721,0,0x00000010000000F0), +(37722,0,0x00000000000001C0), +(37723,0,0x00000000C0000000), +(37736,0,0x0000040000000000), +(37736,1,0x0000004000000000), +(37737,0,0x0000000000000040), +(37738,0,0x0000000000000040), +(37739,0,0x0000000080000000), +(37740,0,0x0000000000000001), +(37742,0,0x0000004000000000), +(37760,0,0x0000000000000001), +(37762,0,0x0000001000000000), +(37763,0,0x0000800000000000), +(37878,0,0x00000010000000F0), +(37879,0,0x00000000C0000000), +(37880,0,0x0000000411041E40), +(37881,0,0x00000000000001C0), +(38314,0,0x0000E000E2000000), +(38321,0,0x0000000000000020), +(38322,0,0x0000000000000100), +(38388,0,0x0000000000040000), +(38389,0,0x0000000E00000006), +(38392,0,0x0000000100000000), +(38393,0,0x0000000000000001), +(38396,0,0x0000000004000000), +(38397,0,0x0000000000000821), +(38398,0,0x0000000020000000), +(38399,0,0x0000000002000000), +(38407,0,0x0000000100000000), +(38408,0,0x0000008000000000), +(38410,0,0x0000000000000200), +(38411,0,0x0000000000001000), +(38412,0,0x0000000000002000), +(38413,0,0x0000000000008000), +(38414,0,0x0000000000000002), +(38415,0,0x0000000000000004), +(38416,0,0x0010000000800000), +(38416,1,0x0010000000800000), +(38417,0,0x0000000200000000), +(38420,0,0x0000000000000020), +(38421,0,0x0000100000000000), +(38422,0,0x0000000000000020), +(38424,0,0x0000008000000000), +(38425,0,0x0000000040000000), +(38426,0,0x0000000080000000), +(38429,0,0x0000000090100000), +(38434,0,0x0000000000000100), +(38435,0,0x0000000000000080), +(38436,0,0x0000000000000001), +(38447,0,0x0000040000000000), +(38447,1,0x0000004000000000), +(38466,0,0x0008000000000000), +(38499,0,0x0000008000000000), +(38501,0,0x0000000000000080), +(38522,0,0x0000000040000000), +(39805,0,0x0000000000000003), +(39805,1,0x0000000000000003), +(39926,1,0x0000080000000000), +(39926,2,0x0000200000000000), +(39950,0,0x0000000000000040), +(40389,0,0x0000800000000000), +(40460,0,0x00000009003E0000), +(41021,0,0x0000004000000000), +(41021,1,0x0000004000000000), +(41026,0,0x0000004000000000), +(41026,1,0x0000004000000000), +(41037,0,0x0000044000000000), +(41042,0,0x0000000000800000), +(42367,0,0x0000001000000000), +(43339,0,0x0000000090100000), +(43725,0,0x0000001000000000), +(43736,0,0x0000000000000010), +(43743,1,0x0000000008000400), +(43752,0,0x0000000000000100), +(43837,0,0x0000000080000000), +(43840,0,0x0000044000000000), +(43841,0,0x0000000000000002), +(43842,0,0x0000044000000000), +(43843,0,0x0000044000000000), +(43844,0,0x0000000000000002), +(43845,0,0x0000000000000002), +(43850,0,0x0000000000800000), +(43851,0,0x0000000000800000), +(43852,0,0x0000000000800000), +(43854,0,0x0000004000000000), +(43855,0,0x0000004000000000), +(43856,0,0x0000004000000000), +(43857,0,0x0000001000000000), +(43858,0,0x0000001000000000), +(43859,0,0x0000001000000000), +(43860,0,0x0000000090100000), +(43861,0,0x0000000090100000), +(43862,0,0x0000000090100000), +(44292,0,0x0000000000001000), +(44293,0,0x0000000000000200), +(44295,0,0x0000000090100000), +(44296,0,0x0000000000000001), +(44297,0,0x0000000000010000), +(44299,0,0x0000000000040000), +(44300,0,0x0000800000000000), +(44301,0,0x0000000001000000), +(44302,0,0x0000000001000000), +(46088,0,0x0000044000000000), +(46090,0,0x0000000000000002), +(46091,0,0x0000000000800000), +(46095,0,0x0000004000000000), +(46096,0,0x0000001000000000), +(46097,0,0x0000000090100000), +(46100,0,0x0000001000000000), +(46833,0,0x0000000000000004), +(46834,0,0x0000000000000040), +(46851,0,0x0001000000000000); + +/*!40000 ALTER TABLE `spell_affect` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `spell_chain` +-- + +DROP TABLE IF EXISTS `spell_chain`; +CREATE TABLE `spell_chain` ( + `spell_id` mediumint(9) NOT NULL default '0', + `prev_spell` mediumint(9) NOT NULL default '0', + `first_spell` mediumint(9) NOT NULL default '0', + `rank` tinyint(4) NOT NULL default '0', + `req_spell` mediumint(9) NOT NULL default '0', + PRIMARY KEY (`spell_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Spell Additinal Data'; + +-- +-- Dumping data for table `spell_chain` +-- + +LOCK TABLES `spell_chain` WRITE; +/*!40000 ALTER TABLE `spell_chain` DISABLE KEYS */; +INSERT INTO `spell_chain` VALUES +(10,0,10,1,0), +(17,0,17,1,0), +(53,0,53,1,0), +(72,0,72,1,0), +(78,0,78,1,0), +(99,0,99,1,0), +(100,0,100,1,0), +(116,0,116,1,0), +(118,0,118,1,0), +(120,0,120,1,0), +(122,0,122,1,0), +(133,0,133,1,0), +(136,0,136,1,0), +(139,0,139,1,0), +(143,133,133,2,0), +(145,143,133,3,0), +(168,0,168,1,0), +(172,0,172,1,0), +(205,116,116,2,0), +(284,78,78,2,0), +(285,284,78,3,0), +(324,0,324,1,0), +(325,324,324,2,0), +(331,0,331,1,0), +(332,331,331,2,0), +(339,0,339,1,0), +(348,0,348,1,0), +(370,0,370,1,0), +(403,0,403,1,0), +(408,0,408,1,0), +(421,0,421,1,0), +(453,0,453,1,0), +(465,0,465,1,0), +(467,0,467,1,0), +(469,0,469,1,0), +(498,0,498,1,0), +(527,0,527,1,0), +(529,403,403,2,0), +(543,0,543,1,0), +(547,332,331,3,0), +(548,529,403,3,0), +(585,0,585,1,0), +(586,0,586,1,0), +(587,0,587,1,0), +(588,0,588,1,0), +(589,0,589,1,0), +(591,585,585,2,0), +(592,17,17,2,0), +(594,589,589,2,0), +(596,0,596,1,0), +(597,587,587,2,0), +(598,591,585,3,0), +(600,592,17,3,0), +(602,7128,588,3,0), +(603,0,603,1,0), +(604,0,604,1,0), +(605,0,605,1,0), +(633,0,633,1,0), +(635,0,635,1,0), +(639,635,635,2,0), +(642,0,642,1,0), +(643,10290,465,3,0), +(647,639,635,3,0), +(686,0,686,1,0), +(687,0,687,1,0), +(688,0,688,1,0), +(689,0,689,1,0), +(693,0,693,1,0), +(694,0,694,1,0), +(695,686,686,2,0), +(696,687,687,2,0), +(699,689,689,2,0), +(702,0,702,1,0), +(703,0,703,1,0), +(704,0,704,1,0), +(705,695,686,3,0), +(706,0,706,1,0), +(707,348,348,2,0), +(709,699,689,3,0), +(710,0,710,1,0), +(724,0,724,1,0), +(740,0,740,1,0), +(755,0,755,1,0), +(769,780,779,3,0), +(770,0,770,1,0), +(772,0,772,1,0), +(774,0,774,1,0), +(778,770,770,2,0), +(779,0,779,1,0), +(780,779,779,2,0), +(781,0,781,1,0), +(782,467,467,2,0), +(837,205,116,3,0), +(845,0,845,1,0), +(853,0,853,1,0), +(865,122,122,2,0), +(879,0,879,1,0), +(905,325,324,3,0), +(913,547,331,4,0), +(915,548,403,4,0), +(930,421,421,2,0), +(939,913,331,5,0), +(943,915,403,5,0), +(945,905,324,4,0), +(959,939,331,6,0), +(970,594,589,3,0), +(974,0,974,1,0), +(976,0,976,1,0), +(980,0,980,1,0), +(984,598,585,4,0), +(988,527,527,2,0), +(990,597,587,3,0), +(992,970,589,4,0), +(996,596,596,2,0), +(1004,984,585,5,0), +(1006,602,588,4,0), +(1008,0,1008,1,0), +(1014,980,980,2,0), +(1020,642,642,2,0), +(1022,0,1022,1,0), +(1026,647,635,4,0), +(1032,10291,465,5,0), +(1038,0,1038,1,0), +(1042,1026,635,5,0), +(1058,774,774,2,0), +(1062,339,339,2,0), +(1064,0,1064,1,0), +(1075,782,467,3,0), +(1079,0,1079,1,0), +(1082,0,1082,1,0), +(1086,706,706,2,0), +(1088,705,686,4,0), +(1094,707,348,3,0), +(1098,0,1098,1,0), +(1106,1088,686,5,0), +(1108,702,702,2,0), +(1120,0,1120,1,0), +(1126,0,1126,1,0), +(1130,0,1130,1,0), +(1160,0,1160,1,0), +(1243,0,1243,1,0), +(1244,1243,1243,2,0), +(1245,1244,1243,3,0), +(1329,0,1329,1,0), +(1430,1058,774,3,0), +(1449,0,1449,1,0), +(1454,0,1454,1,0), +(1455,1454,1454,2,0), +(1456,1455,1454,3,0), +(1459,0,1459,1,0), +(1460,1459,1459,2,0), +(1461,1460,1459,3,0), +(1463,0,1463,1,0), +(1464,0,1464,1,0), +(1490,0,1490,1,0), +(1495,0,1495,1,0), +(1499,0,1499,1,0), +(1510,0,1510,1,0), +(1513,0,1513,1,0), +(1535,0,1535,1,0), +(1608,285,78,4,0), +(1671,72,72,2,0), +(1672,1671,72,3,0), +(1714,0,1714,1,0), +(1715,0,1715,1,0), +(1735,99,99,2,0), +(1742,0,1742,1,0), +(1752,0,1752,1,0), +(1753,1742,1742,2,0), +(1754,1753,1742,3,0), +(1755,1754,1742,4,0), +(1756,1755,1742,5,0), +(1757,1752,1752,2,0), +(1758,1757,1752,3,0), +(1759,1758,1752,4,0), +(1760,1759,1752,5,0), +(1766,0,1766,1,0), +(1767,1766,1766,2,0), +(1768,1767,1766,3,0), +(1769,1768,1766,4,0), +(1776,0,1776,1,0), +(1777,1776,1776,2,0), +(1784,0,1784,1,0), +(1785,1784,1784,2,0), +(1786,1785,1784,3,0), +(1787,1786,1784,4,0), +(1804,0,1804,1,0), +(1822,0,1822,1,0), +(1823,1822,1822,2,0), +(1824,1823,1822,3,0), +(1850,0,1850,1,0), +(1856,0,1856,1,0), +(1857,1856,1856,2,0), +(1943,0,1943,1,0), +(1949,0,1949,1,0), +(1966,0,1966,1,0), +(1978,0,1978,1,0), +(2006,0,2006,1,0), +(2008,0,2008,1,0), +(2010,2006,2006,2,0), +(2018,0,2018,1,0), +(2048,25289,6673,8,0), +(2050,0,2050,1,0), +(2052,2050,2050,2,0), +(2053,2052,2050,3,0), +(2054,0,2054,1,0), +(2055,2054,2054,2,0), +(2060,0,2060,1,0), +(2061,0,2061,1,0), +(2062,0,2062,1,0), +(2070,6770,6770,2,0), +(2090,1430,774,4,0), +(2091,2090,774,5,0), +(2096,0,2096,1,0), +(2098,0,2098,1,0), +(2108,0,2108,1,0), +(2120,0,2120,1,0), +(2121,2120,2120,2,0), +(2136,0,2136,1,0), +(2137,2136,2136,2,0), +(2138,2137,2136,3,0), +(2259,0,2259,1,0), +(2362,0,2362,1,0), +(2366,0,2366,1,0), +(2368,2366,2366,2,0), +(2550,0,2550,1,0), +(2575,0,2575,1,0), +(2576,2575,2575,2,0), +(2589,53,53,2,0), +(2590,2589,53,3,0), +(2591,2590,53,4,0), +(2637,0,2637,1,0), +(2643,0,2643,1,0), +(2649,0,2649,1,0), +(2651,0,2651,1,0), +(2652,0,2652,1,0), +(2767,992,589,5,0), +(2791,1245,1243,4,0), +(2800,633,633,2,0), +(2812,0,2812,1,0), +(2825,0,2825,1,0), +(2835,0,2835,1,0), +(2837,2835,2835,2,0), +(2860,930,421,3,0), +(2878,0,2878,1,0), +(2894,0,2894,1,0), +(2908,0,2908,1,0), +(2912,0,2912,1,0), +(2941,1094,348,4,0), +(2944,0,2944,1,0), +(2947,0,2947,1,0), +(2948,0,2948,1,0), +(2973,0,2973,1,0), +(2974,0,2974,1,0), +(2983,0,2983,1,0), +(3009,3010,16827,8,0), +(3010,16832,16827,7,0), +(3029,1082,1082,2,0), +(3034,0,3034,1,0), +(3044,0,3044,1,0), +(3100,2018,2018,2,0), +(3101,2259,2259,2,0), +(3102,2550,2550,2,0), +(3104,2108,2108,2,0), +(3110,0,3110,1,0), +(3111,136,136,2,0), +(3140,145,133,4,0), +(3273,0,3273,1,0), +(3274,3273,3273,2,0), +(3413,3102,2550,3,0), +(3420,0,3420,1,0), +(3421,3420,3420,2,0), +(3464,3101,2259,3,0), +(3472,1042,635,6,0), +(3538,3100,2018,3,0), +(3564,2576,2575,3,0), +(3570,2368,2366,3,0), +(3599,0,3599,1,0), +(3627,2091,774,6,0), +(3661,3111,136,3,0), +(3662,3661,136,4,0), +(3698,755,755,2,0), +(3699,3698,755,3,0), +(3700,3699,755,4,0), +(3716,0,3716,1,0), +(3738,0,3738,1,0), +(3747,600,17,4,0), +(3811,3104,2108,3,0), +(3908,0,3908,1,0), +(3909,3908,3908,2,0), +(3910,3909,3908,3,0), +(4036,0,4036,1,0), +(4037,4036,4036,2,0), +(4038,4037,4036,3,0), +(4187,0,4187,1,0), +(4188,4187,4187,2,0), +(4189,4188,4187,3,0), +(4190,4189,4187,4,0), +(4191,4190,4187,5,0), +(4192,4191,4187,6,0), +(4193,4192,4187,7,0), +(4194,4193,4187,8,0), +(5041,4194,4187,9,0), +(5042,5041,4187,10,0), +(5138,0,5138,1,0), +(5143,0,5143,1,0), +(5144,5143,5143,2,0), +(5145,5144,5143,3,0), +(5171,0,5171,1,0), +(5176,0,5176,1,0), +(5177,5176,5176,2,0), +(5178,5177,5176,3,0), +(5179,5178,5176,4,0), +(5180,5179,5176,5,0), +(5185,0,5185,1,0), +(5186,5185,5185,2,0), +(5187,5186,5185,3,0), +(5188,5187,5185,4,0), +(5189,5188,5185,5,0), +(5195,1062,339,3,0), +(5196,5195,339,4,0), +(5201,3029,1082,3,0), +(5211,0,5211,1,0), +(5215,0,5215,1,0), +(5217,0,5217,1,0), +(5221,0,5221,1,0), +(5232,1126,1126,2,0), +(5234,6756,1126,4,0), +(5242,6673,6673,2,0), +(5277,0,5277,1,0), +(5308,0,5308,1,0), +(5394,0,5394,1,0), +(5484,0,5484,1,0), +(5487,0,5487,1,0), +(5504,0,5504,1,0), +(5505,5504,5504,2,0), +(5506,5505,5504,3,0), +(5570,0,5570,1,0), +(5573,498,498,2,0), +(5588,853,853,2,0), +(5589,5588,853,3,0), +(5599,1022,1022,2,0), +(5614,879,879,2,0), +(5615,5614,879,3,0), +(5627,2878,2878,2,0), +(5675,0,5675,1,0), +(5676,0,5676,1,0), +(5699,6202,6201,3,0), +(5730,0,5730,1,0), +(5740,0,5740,1,0), +(5763,0,5763,1,0), +(5782,0,5782,1,0), +(5938,0,5938,1,0), +(6041,943,403,6,0), +(6060,1004,585,6,0), +(6063,2055,2054,3,0), +(6064,6063,2054,4,0), +(6065,3747,17,5,0), +(6066,6065,17,6,0), +(6074,139,139,2,0), +(6075,6074,139,3,0), +(6076,6075,139,4,0), +(6077,6076,139,5,0), +(6078,6077,139,6,0), +(6117,0,6117,1,0), +(6127,5506,5504,4,0), +(6129,990,587,4,0), +(6131,865,122,3,0), +(6141,10,10,2,0), +(6143,0,6143,1,0), +(6178,100,100,2,0), +(6190,1160,1160,2,0), +(6192,5242,6673,3,0), +(6201,0,6201,1,0), +(6202,6201,6201,2,0), +(6205,1108,702,3,0), +(6213,5782,5782,2,0), +(6215,6213,5782,3,0), +(6217,1014,980,3,0), +(6219,5740,5740,2,0), +(6222,172,172,2,0), +(6223,6222,172,3,0), +(6226,5138,5138,2,0), +(6229,0,6229,1,0), +(6307,0,6307,1,0), +(6343,0,6343,1,0), +(6353,0,6353,1,0), +(6360,0,6360,1,0), +(6363,3599,3599,2,0), +(6364,6363,3599,3,0), +(6365,6364,3599,4,0), +(6366,0,6366,1,0), +(6375,5394,5394,2,0), +(6377,6375,5394,3,0), +(6390,5730,5730,2,0), +(6391,6390,5730,3,0), +(6392,6391,5730,4,0), +(6542,0,6542,1,0), +(6546,772,772,2,0), +(6547,6546,772,3,0), +(6548,6547,772,4,0), +(6552,0,6552,1,0), +(6554,6552,6552,2,0), +(6572,0,6572,1,0), +(6574,6572,6572,2,0), +(6673,0,6673,1,0), +(6756,5232,1126,3,0), +(6760,2098,2098,2,0), +(6761,6760,2098,3,0), +(6762,6761,2098,4,0), +(6768,1966,1966,2,0), +(6770,0,6770,1,0), +(6774,5171,5171,2,0), +(6778,5189,5185,6,0), +(6780,5180,5176,6,0), +(6783,5215,5215,2,0), +(6785,0,6785,1,0), +(6787,6785,6785,2,0), +(6789,0,6789,1,0), +(6793,5217,5217,2,0), +(6798,5211,5211,2,0), +(6800,5221,5221,2,0), +(6807,0,6807,1,0), +(6808,6807,6807,2,0), +(6809,6808,6807,3,0), +(6940,0,6940,1,0), +(7128,588,588,2,0), +(7294,0,7294,1,0), +(7300,168,168,2,0), +(7301,7300,168,3,0), +(7302,0,7302,1,0), +(7320,7302,7302,2,0), +(7322,837,116,4,0), +(7328,0,7328,1,0), +(7369,845,845,2,0), +(7371,0,7371,1,0), +(7372,1715,1715,2,0), +(7373,7372,1715,3,0), +(7379,6574,6572,3,0), +(7384,0,7384,1,0), +(7386,0,7386,1,0), +(7400,694,694,2,0), +(7402,7400,694,3,0), +(7405,7386,7386,2,0), +(7411,0,7411,1,0), +(7412,7411,7411,2,0), +(7413,7412,7411,3,0), +(7620,0,7620,1,0), +(7641,1106,686,6,0), +(7646,6205,702,4,0), +(7648,6223,172,4,0), +(7651,709,689,4,0), +(7658,704,704,2,0), +(7659,7658,704,3,0), +(7731,7620,7620,2,0), +(7732,7731,7620,3,0), +(7799,3110,3110,2,0), +(7800,7799,3110,3,0), +(7801,7800,3110,4,0), +(7802,7801,3110,5,0), +(7804,6307,6307,2,0), +(7805,7804,6307,3,0), +(7809,3716,3716,2,0), +(7810,7809,3716,3,0), +(7811,7810,3716,4,0), +(7812,0,7812,1,0), +(7813,6360,6360,2,0), +(7814,0,7814,1,0), +(7815,7814,7814,2,0), +(7816,7815,7814,3,0), +(7887,7384,7384,2,0), +(7924,3274,3273,3,0), +(8004,0,8004,1,0), +(8005,959,331,7,0), +(8008,8004,8004,2,0), +(8010,8008,8004,3,0), +(8012,370,370,2,0), +(8017,0,8017,1,0), +(8018,8017,8017,2,0), +(8019,8018,8017,3,0), +(8024,0,8024,1,0), +(8027,8024,8024,2,0), +(8030,8027,8024,3,0), +(8033,0,8033,1,0), +(8038,8033,8033,2,0), +(8042,0,8042,1,0), +(8044,8042,8042,2,0), +(8045,8044,8042,3,0), +(8046,8045,8042,4,0), +(8050,0,8050,1,0), +(8052,8050,8050,2,0), +(8053,8052,8050,3,0), +(8056,0,8056,1,0), +(8058,8056,8056,2,0), +(8071,0,8071,1,0), +(8075,0,8075,1,0), +(8092,0,8092,1,0), +(8102,8092,8092,2,0), +(8103,8102,8092,3,0), +(8104,8103,8092,4,0), +(8105,8104,8092,5,0), +(8106,8105,8092,6,0), +(8122,0,8122,1,0), +(8124,8122,8122,2,0), +(8129,0,8129,1,0), +(8131,8129,8129,2,0), +(8134,945,324,5,0), +(8154,8071,8071,2,0), +(8155,8154,8071,3,0), +(8160,8075,8075,2,0), +(8161,8160,8075,3,0), +(8181,0,8181,1,0), +(8184,0,8184,1,0), +(8190,0,8190,1,0), +(8192,453,453,2,0), +(8198,6343,6343,2,0), +(8204,8198,6343,3,0), +(8205,8204,6343,4,0), +(8227,0,8227,1,0), +(8232,0,8232,1,0), +(8235,8232,8232,2,0), +(8249,8227,8227,2,0), +(8288,1120,1120,2,0), +(8289,8288,1120,3,0), +(8316,2947,2947,2,0), +(8317,8316,2947,3,0), +(8380,7405,7386,3,0), +(8400,3140,133,5,0), +(8401,8400,133,6,0), +(8402,8401,133,7,0), +(8406,7322,116,5,0), +(8407,8406,116,6,0), +(8408,8407,116,7,0), +(8412,2138,2136,4,0), +(8413,8412,2136,5,0), +(8416,5145,5143,4,0), +(8417,8416,5143,5,0), +(8422,2121,2120,3,0), +(8423,8422,2120,4,0), +(8427,6141,10,3,0), +(8437,1449,1449,2,0), +(8438,8437,1449,3,0), +(8439,8438,1449,4,0), +(8444,2948,2948,2,0), +(8445,8444,2948,3,0), +(8446,8445,2948,4,0), +(8450,604,604,2,0), +(8451,8450,604,3,0), +(8455,1008,1008,2,0), +(8457,543,543,2,0), +(8458,8457,543,3,0), +(8461,6143,6143,2,0), +(8462,8461,6143,3,0), +(8492,120,120,2,0), +(8494,1463,1463,2,0), +(8495,8494,1463,3,0), +(8498,1535,1535,2,0), +(8499,8498,1535,3,0), +(8512,0,8512,1,0), +(8613,0,8613,1,0), +(8617,8613,8613,2,0), +(8618,8617,8613,3,0), +(8621,1760,1752,6,0), +(8623,6762,2098,5,0), +(8624,8623,2098,6,0), +(8629,1777,1776,3,0), +(8631,703,703,2,0), +(8632,8631,703,3,0), +(8633,8632,703,4,0), +(8637,6768,1966,3,0), +(8639,1943,1943,2,0), +(8640,8639,1943,3,0), +(8643,408,408,2,0), +(8647,0,8647,1,0), +(8649,8647,8647,2,0), +(8650,8649,8647,3,0), +(8676,0,8676,1,0), +(8681,0,8681,1,0), +(8687,8681,8681,2,0), +(8691,8687,8681,3,0), +(8694,5763,5763,2,0), +(8696,2983,2983,2,0), +(8721,2591,53,5,0), +(8724,8676,8676,2,0), +(8725,8724,8676,3,0), +(8820,1464,1464,2,0), +(8835,0,8835,1,0), +(8903,6778,5185,7,0), +(8905,6780,5176,7,0), +(8907,5234,1126,5,0), +(8910,3627,774,7,0), +(8914,1075,467,4,0), +(8918,740,740,2,0), +(8921,0,8921,1,0), +(8924,8921,8921,2,0), +(8925,8924,8921,3,0), +(8926,8925,8921,4,0), +(8927,8926,8921,5,0), +(8928,8927,8921,6,0), +(8929,8928,8921,7,0), +(8936,0,8936,1,0), +(8938,8936,8936,2,0), +(8939,8938,8936,3,0), +(8940,8939,8936,4,0), +(8941,8940,8936,5,0), +(8949,2912,2912,2,0), +(8950,8949,2912,3,0), +(8951,8950,2912,4,0), +(8955,2908,2908,2,0), +(8972,6809,6807,4,0), +(8983,6798,5211,3,0), +(8992,6800,5221,3,0), +(8998,0,8998,1,0), +(9000,8998,8998,2,0), +(9005,0,9005,1,0), +(9035,0,9035,1,0), +(9472,2061,2061,2,0), +(9473,9472,2061,3,0), +(9474,9473,2061,4,0), +(9484,0,9484,1,0), +(9485,9484,9484,2,0), +(9490,1735,99,3,0), +(9492,1079,1079,2,0), +(9493,9492,1079,3,0), +(9578,586,586,2,0), +(9579,9578,586,3,0), +(9592,9579,586,4,0), +(9634,5487,5487,2,0), +(9745,8972,6807,5,0), +(9747,9490,99,4,0), +(9749,778,770,3,0), +(9750,8941,8936,6,0), +(9752,9493,1079,4,0), +(9754,769,779,4,0), +(9756,8914,467,5,0), +(9758,8903,5185,8,0), +(9785,3538,2018,4,0), +(9787,9785,2018,5,0), +(9788,9785,2018,5,0), +(9821,1850,1850,2,0), +(9823,9005,9005,2,0), +(9827,9823,9005,3,0), +(9829,8992,5221,4,0), +(9830,9829,5221,5,0), +(9833,8929,8921,8,0), +(9834,9833,8921,9,0), +(9835,9834,8921,10,0), +(9839,8910,774,8,0), +(9840,9839,774,9,0), +(9841,9840,774,10,0), +(9845,6793,5217,3,0), +(9846,9845,5217,4,0), +(9849,5201,1082,4,0), +(9850,9849,1082,5,0), +(9852,5196,339,5,0), +(9853,9852,339,6,0), +(9856,9750,8936,7,0), +(9857,9856,8936,8,0), +(9858,9857,8936,9,0), +(9862,8918,740,3,0), +(9863,9862,740,4,0), +(9866,6787,6785,3,0), +(9867,9866,6785,4,0), +(9875,8951,2912,5,0), +(9876,9875,2912,6,0), +(9880,9745,6807,6,0), +(9881,9880,6807,7,0), +(9884,8907,1126,6,0), +(9885,9884,1126,7,0), +(9888,9758,5185,9,0), +(9889,9888,5185,10,0), +(9892,9000,8998,3,0), +(9894,9752,1079,5,0), +(9896,9894,1079,6,0), +(9898,9747,99,5,0), +(9901,8955,2908,3,0), +(9904,1824,1822,4,0), +(9907,9749,770,4,0), +(9908,9754,779,5,0), +(9910,9756,467,6,0), +(9912,8905,5176,8,0), +(9913,6783,5215,3,0), +(10138,6127,5504,5,0), +(10139,10138,5504,6,0), +(10140,10139,5504,7,0), +(10144,6129,587,5,0), +(10145,10144,587,6,0), +(10148,8402,133,8,0), +(10149,10148,133,9,0), +(10150,10149,133,10,0), +(10151,10150,133,11,0), +(10156,1461,1459,4,0), +(10157,10156,1459,5,0), +(10159,8492,120,3,0), +(10160,10159,120,4,0), +(10161,10160,120,5,0), +(10169,8455,1008,3,0), +(10170,10169,1008,4,0), +(10173,8451,604,4,0), +(10174,10173,604,5,0), +(10177,8462,6143,4,0), +(10179,8408,116,8,0), +(10180,10179,116,9,0), +(10181,10180,116,10,0), +(10185,8427,10,4,0), +(10186,10185,10,5,0), +(10187,10186,10,6,0), +(10191,8495,1463,4,0), +(10192,10191,1463,5,0), +(10193,10192,1463,6,0), +(10197,8413,2136,6,0), +(10199,10197,2136,7,0), +(10201,8439,1449,5,0), +(10202,10201,1449,6,0), +(10205,8446,2948,5,0), +(10206,10205,2948,6,0), +(10207,10206,2948,7,0), +(10211,8417,5143,6,0), +(10212,10211,5143,7,0), +(10215,8423,2120,5,0), +(10216,10215,2120,6,0), +(10219,7320,7302,3,0), +(10220,10219,7302,4,0), +(10223,8458,543,4,0), +(10225,10223,543,5,0), +(10230,6131,122,4,0), +(10248,3564,2575,4,0), +(10278,5599,1022,3,0), +(10290,465,465,2,0), +(10291,643,465,4,0), +(10292,1032,465,6,0), +(10293,10292,465,7,0), +(10298,7294,7294,2,0), +(10299,10298,7294,3,0), +(10300,10299,7294,4,0), +(10301,10300,7294,5,0), +(10308,5589,853,4,0), +(10310,2800,633,3,0), +(10312,5615,879,4,0), +(10313,10312,879,5,0), +(10314,10313,879,6,0), +(10318,2812,2812,2,0), +(10322,7328,7328,2,0), +(10324,10322,7328,3,0), +(10326,5627,2878,3,0), +(10328,3472,635,7,0), +(10329,10328,635,8,0), +(10391,6041,403,7,0), +(10392,10391,403,8,0), +(10395,8005,331,8,0), +(10396,10395,331,9,0), +(10399,8019,8017,4,0), +(10406,8155,8071,4,0), +(10407,10406,8071,5,0), +(10408,10407,8071,6,0), +(10412,8046,8042,5,0), +(10413,10412,8042,6,0), +(10414,10413,8042,7,0), +(10427,6392,5730,5,0), +(10428,10427,5730,6,0), +(10431,8134,324,6,0), +(10432,10431,324,7,0), +(10437,6365,3599,5,0), +(10438,10437,3599,6,0), +(10442,8161,8075,4,0), +(10447,8053,8050,4,0), +(10448,10447,8050,5,0), +(10456,8038,8033,3,0), +(10462,6377,5394,4,0), +(10463,10462,5394,5,0), +(10466,8010,8004,4,0), +(10467,10466,8004,5,0), +(10468,10467,8004,6,0), +(10472,8058,8056,3,0), +(10473,10472,8056,4,0), +(10478,8181,8181,2,0), +(10479,10478,8181,3,0), +(10486,8235,8232,3,0), +(10495,5675,5675,2,0), +(10496,10495,5675,3,0), +(10497,10496,5675,4,0), +(10526,8249,8227,3,0), +(10537,8184,8184,2,0), +(10538,10537,8184,3,0), +(10585,8190,8190,2,0), +(10586,10585,8190,3,0), +(10587,10586,8190,4,0), +(10595,0,10595,1,0), +(10600,10595,10595,2,0), +(10601,10600,10595,3,0), +(10605,2860,421,4,0), +(10613,8512,8512,2,0), +(10614,10613,8512,3,0), +(10622,1064,1064,2,0), +(10623,10622,1064,3,0), +(10627,8835,8835,2,0), +(10656,10662,2108,5,0), +(10658,10662,2108,5,0), +(10660,10662,2108,5,0), +(10662,3811,2108,4,0), +(10768,8618,8613,4,0), +(10797,0,10797,1,0), +(10846,7924,3273,4,0), +(10874,8131,8129,3,0), +(10875,10874,8129,4,0), +(10876,10875,8129,5,0), +(10880,2010,2006,3,0), +(10881,10880,2006,4,0), +(10888,8124,8122,3,0), +(10890,10888,8122,4,0), +(10892,2767,589,6,0), +(10893,10892,589,7,0), +(10894,10893,589,8,0), +(10898,6066,17,7,0), +(10899,10898,17,8,0), +(10900,10899,17,9,0), +(10901,10900,17,10,0), +(10909,2096,2096,2,0), +(10911,605,605,2,0), +(10912,10911,605,3,0), +(10915,9474,2061,5,0), +(10916,10915,2061,6,0), +(10917,10916,2061,7,0), +(10927,6078,139,7,0), +(10928,10927,139,8,0), +(10929,10928,139,9,0), +(10933,6060,585,7,0), +(10934,10933,585,8,0), +(10937,2791,1243,5,0), +(10938,10937,1243,6,0), +(10941,9592,586,5,0), +(10942,10941,586,6,0), +(10945,8106,8092,7,0), +(10946,10945,8092,8,0), +(10947,10946,8092,9,0), +(10951,1006,588,5,0), +(10952,10951,588,6,0), +(10953,8192,453,3,0), +(10955,9485,9484,3,0), +(10957,976,976,2,0), +(10958,10957,976,3,0), +(10960,996,596,3,0), +(10961,10960,596,4,0), +(10963,2060,2060,2,0), +(10964,10963,2060,3,0), +(10965,10964,2060,4,0), +(11113,0,11113,1,0), +(11197,8650,8647,4,0), +(11198,11197,8647,5,0), +(11267,8725,8676,4,0), +(11268,11267,8676,5,0), +(11269,11268,8676,6,0), +(11273,8640,1943,4,0), +(11274,11273,1943,5,0), +(11275,11274,1943,6,0), +(11279,8721,53,6,0), +(11280,11279,53,7,0), +(11281,11280,53,8,0), +(11285,8629,1776,4,0), +(11286,11285,1776,5,0), +(11289,8633,703,5,0), +(11290,11289,703,6,0), +(11293,8621,1752,7,0), +(11294,11293,1752,8,0), +(11297,2070,6770,3,0), +(11299,8624,2098,7,0), +(11300,11299,2098,8,0), +(11303,8637,1966,4,0), +(11305,8696,2983,3,0), +(11314,8499,1535,4,0), +(11315,11314,1535,5,0), +(11341,8691,8681,4,0), +(11342,11341,8681,5,0), +(11343,11342,8681,6,0), +(11357,2837,2835,3,0), +(11358,11357,2835,4,0), +(11366,0,11366,1,0), +(11400,8694,5763,3,0), +(11426,0,11426,1,0), +(11549,6192,6673,4,0), +(11550,11549,6673,5,0), +(11551,11550,6673,6,0), +(11554,6190,1160,3,0), +(11555,11554,1160,4,0), +(11556,11555,1160,5,0), +(11564,1608,78,5,0), +(11565,11564,78,6,0), +(11566,11565,78,7,0), +(11567,11566,78,8,0), +(11572,6548,772,5,0), +(11573,11572,772,6,0), +(11574,11573,772,7,0), +(11578,6178,100,3,0), +(11580,8205,6343,5,0), +(11581,11580,6343,6,0), +(11584,7887,7384,3,0), +(11585,11584,7384,4,0), +(11596,8380,7386,4,0), +(11597,11596,7386,5,0), +(11600,7379,6572,4,0), +(11601,11600,6572,5,0), +(11604,8820,1464,3,0), +(11605,11604,1464,4,0), +(11608,7369,845,3,0), +(11609,11608,845,4,0), +(11611,3464,2259,4,0), +(11659,7641,686,7,0), +(11660,11659,686,8,0), +(11661,11660,686,9,0), +(11665,2941,348,5,0), +(11667,11665,348,6,0), +(11668,11667,348,7,0), +(11671,7648,172,5,0), +(11672,11671,172,6,0), +(11675,8289,1120,4,0), +(11677,6219,5740,3,0), +(11678,11677,5740,4,0), +(11683,1949,1949,2,0), +(11684,11683,1949,3,0), +(11687,1456,1454,4,0), +(11688,11687,1454,5,0), +(11689,11688,1454,6,0), +(11693,3700,755,5,0), +(11694,11693,755,6,0), +(11695,11694,755,7,0), +(11699,7651,689,5,0), +(11700,11699,689,6,0), +(11703,6226,5138,3,0), +(11704,11703,5138,4,0), +(11707,7646,702,5,0), +(11708,11707,702,6,0), +(11711,6217,980,4,0), +(11712,11711,980,5,0), +(11713,11712,980,6,0), +(11717,7659,704,4,0), +(11719,1714,1714,2,0), +(11721,1490,1490,2,0), +(11722,11721,1490,3,0), +(11725,1098,1098,2,0), +(11726,11725,1098,3,0), +(11729,5699,6201,4,0), +(11730,11729,6201,5,0), +(11733,1086,706,3,0), +(11734,11733,706,4,0), +(11735,11734,706,5,0), +(11739,6229,6229,2,0), +(11740,11739,6229,3,0), +(11762,7802,3110,6,0), +(11763,11762,3110,7,0), +(11766,7805,6307,4,0), +(11767,11766,6307,5,0), +(11770,8317,2947,4,0), +(11771,11770,2947,5,0), +(11774,7811,3716,5,0), +(11775,11774,3716,6,0), +(11778,7816,7814,4,0), +(11779,11778,7814,5,0), +(11780,11779,7814,6,0), +(11784,7813,6360,3,0), +(11785,11784,6360,4,0), +(11993,3570,2366,4,0), +(12180,3910,3908,4,0), +(12656,4038,4036,4,0), +(12294,0,12294,1,0), +(12505,11366,11366,2,0), +(12522,12505,11366,3,0), +(12523,12522,11366,4,0), +(12524,12523,11366,5,0), +(12525,12524,11366,6,0), +(12526,12525,11366,7,0), +(12824,118,118,2,0), +(12825,12824,118,3,0), +(12826,12825,118,4,0), +(13018,11113,11113,2,0), +(13019,13018,11113,3,0), +(13020,13019,11113,4,0), +(13021,13020,11113,5,0), +(13031,11426,11426,2,0), +(13032,13031,11426,3,0), +(13033,13032,11426,4,0), +(13165,0,13165,1,0), +(13220,0,13220,1,0), +(13228,13220,13220,2,0), +(13229,13228,13220,3,0), +(13230,13229,13220,4,0), +(13542,3662,136,5,0), +(13543,13542,136,6,0), +(13544,13543,136,7,0), +(13549,1978,1978,2,0), +(13550,13549,1978,3,0), +(13551,13550,1978,4,0), +(13552,13551,1978,5,0), +(13553,13552,1978,6,0), +(13554,13553,1978,7,0), +(13555,13554,1978,8,0), +(13795,0,13795,1,0), +(13813,0,13813,1,0), +(13896,0,13896,1,0), +(13908,0,13908,1,0), +(13920,7413,7411,4,0), +(14260,2973,2973,2,0), +(14261,14260,2973,3,0), +(14262,14261,2973,4,0), +(14263,14262,2973,5,0), +(14264,14263,2973,6,0), +(14265,14264,2973,7,0), +(14266,14265,2973,8,0), +(14267,2974,2974,2,0), +(14268,14267,2974,3,0), +(14269,1495,1495,2,0), +(14270,14269,1495,3,0), +(14271,14270,1495,4,0), +(14272,781,781,2,0), +(14273,14272,781,3,0), +(14274,20736,20736,2,0), +(14279,3034,3034,2,0), +(14280,14279,3034,3,0), +(14281,3044,3044,2,0), +(14282,14281,3044,3,0), +(14283,14282,3044,4,0), +(14284,14283,3044,5,0), +(14285,14284,3044,6,0), +(14286,14285,3044,7,0), +(14287,14286,3044,8,0), +(14288,2643,2643,2,0), +(14289,14288,2643,3,0), +(14290,14289,2643,4,0), +(14294,1510,1510,2,0), +(14295,14294,1510,3,0), +(14302,13795,13795,2,0), +(14303,14302,13795,3,0), +(14304,14303,13795,4,0), +(14305,14304,13795,5,0), +(14310,1499,1499,2,0), +(14311,14310,1499,3,0), +(14316,13813,13813,2,0), +(14317,14316,13813,3,0), +(14318,13165,13165,2,0), +(14319,14318,13165,3,0), +(14320,14319,13165,4,0), +(14321,14320,13165,5,0), +(14322,14321,13165,6,0), +(14323,1130,1130,2,0), +(14324,14323,1130,3,0), +(14325,14324,1130,4,0), +(14326,1513,1513,2,0), +(14327,14326,1513,3,0), +(14752,0,14752,1,0), +(14818,14752,14752,2,0), +(14819,14818,14752,3,0), +(14914,0,14914,1,0), +(14916,2649,2649,2,0), +(14917,14916,2649,3,0), +(14918,14917,2649,4,0), +(14919,14918,2649,5,0), +(14920,14919,2649,6,0), +(14921,14920,2649,7,0), +(15107,0,15107,1,0), +(15111,15107,15107,2,0), +(15112,15111,15107,3,0), +(15207,10392,403,9,0), +(15208,15207,403,10,0), +(15237,0,15237,1,0), +(15261,15267,14914,8,0), +(15262,14914,14914,2,0), +(15263,15262,14914,3,0), +(15264,15263,14914,4,0), +(15265,15264,14914,5,0), +(15266,15265,14914,6,0), +(15267,15266,14914,7,0), +(15407,0,15407,1,0), +(15430,15237,15237,2,0), +(15431,15430,15237,3,0), +(15629,14274,20736,3,0), +(15630,15629,20736,4,0), +(15631,15630,20736,5,0), +(15632,15631,20736,6,0), +(16314,10399,8017,5,0), +(16315,16314,8017,6,0), +(16316,16315,8017,7,0), +(16339,8030,8024,4,0), +(16341,16339,8024,5,0), +(16342,16341,8024,6,0), +(16355,10456,8033,4,0), +(16356,16355,8033,5,0), +(16362,10486,8232,4,0), +(16387,10526,8227,4,0), +(16511,0,16511,1,0), +(16689,0,16689,1,339), +(16697,1756,1742,6,0), +(16810,16689,16689,2,1062), +(16811,16810,16689,3,5195), +(16812,16811,16689,4,5196), +(16813,16812,16689,5,9852), +(16827,0,16827,1,0), +(16828,16827,16827,2,0), +(16829,16828,16827,3,0), +(16830,16829,16827,4,0), +(16831,16830,16827,5,0), +(16832,16831,16827,6,0), +(16857,0,16857,1,0), +(16914,0,16914,1,0), +(17039,9787,2018,6,0), +(17040,9787,2018,6,0), +(17041,9787,2018,6,0), +(17253,0,17253,1,0), +(17255,17253,17253,2,0), +(17256,17255,17253,3,0), +(17257,17256,17253,4,0), +(17258,17257,17253,5,0), +(17259,17258,17253,6,0), +(17260,17259,17253,7,0), +(17261,17260,17253,8,0), +(17311,15407,15407,2,0), +(17312,17311,15407,3,0), +(17313,17312,15407,4,0), +(17314,17313,15407,5,0), +(17329,16813,16689,6,9853), +(17347,16511,16511,2,0), +(17348,17347,16511,3,0), +(17390,16857,16857,2,0), +(17391,17390,16857,3,0), +(17392,17391,16857,4,0), +(17401,16914,16914,2,0), +(17402,17401,16914,3,0), +(17727,2362,2362,2,0), +(17728,17727,2362,3,0), +(17735,0,17735,1,0), +(17750,17735,17735,2,0), +(17751,17750,17735,3,0), +(17752,17751,17735,4,0), +(17767,0,17767,1,0), +(17850,17767,17767,2,0), +(17851,17850,17767,3,0), +(17852,17851,17767,4,0), +(17853,17852,17767,5,0), +(17854,17853,17767,6,0), +(17862,0,17862,1,0), +(17877,0,17877,1,0), +(17919,5676,5676,2,0), +(17920,17919,5676,3,0), +(17921,17920,5676,4,0), +(17922,17921,5676,5,0), +(17923,17922,5676,6,0), +(17924,6353,6353,2,0), +(17925,6789,6789,2,0), +(17926,17925,6789,3,0), +(17928,5484,5484,2,0), +(17937,17862,17862,2,0), +(17951,6366,6366,2,0), +(17952,17951,6366,3,0), +(17953,17952,6366,4,0), +(17962,0,17962,1,0), +(18137,0,18137,1,0), +(18220,0,18220,1,0), +(18248,7732,7620,4,0), +(18260,3413,2550,4,0), +(18265,0,18265,1,0), +(18647,710,710,2,0), +(18657,2637,2637,2,0), +(18658,18657,2637,3,0), +(18807,17314,15407,6,0), +(18809,12526,11366,8,0), +(18867,17877,17877,2,0), +(18868,18867,17877,3,0), +(18869,18868,17877,4,0), +(18870,18869,17877,5,0), +(18871,18870,17877,6,0), +(18879,18265,18265,2,0), +(18880,18879,18265,3,0), +(18881,18880,18265,4,0), +(18930,17962,17962,2,0), +(18931,18930,17962,3,0), +(18932,18931,17962,4,0), +(18937,18220,18220,2,0), +(18938,18937,18220,3,0), +(19236,13908,13908,2,0), +(19238,19236,13908,3,0), +(19240,19238,13908,4,0), +(19241,19240,13908,5,0), +(19242,19241,13908,6,0), +(19243,19242,13908,7,0), +(19261,2652,2652,2,0), +(19262,19261,2652,3,0), +(19264,19262,2652,4,0), +(19265,19264,2652,5,0), +(19266,19265,2652,6,0), +(19271,13896,13896,2,0), +(19273,19271,13896,3,0), +(19274,19273,13896,4,0), +(19275,19274,13896,5,0), +(19276,2944,2944,2,0), +(19277,19276,2944,3,0), +(19278,19277,2944,4,0), +(19279,19278,2944,5,0), +(19280,19279,2944,6,0), +(19281,9035,9035,2,0), +(19282,19281,9035,3,0), +(19283,19282,9035,4,0), +(19284,19283,9035,5,0), +(19285,19284,9035,6,0), +(19296,10797,10797,2,0), +(19299,19296,10797,3,0), +(19302,19299,10797,4,0), +(19303,19302,10797,5,0), +(19304,19303,10797,6,0), +(19305,19304,10797,7,0), +(19306,0,19306,1,0), +(19308,18137,18137,2,0), +(19309,19308,18137,3,0), +(19310,19309,18137,4,0), +(19311,19310,18137,5,0), +(19312,19311,18137,6,0), +(19386,0,19386,1,0), +(19434,0,19434,1,0), +(19438,7812,7812,2,0), +(19440,19438,7812,3,0), +(19441,19440,7812,4,0), +(19442,19441,7812,5,0), +(19443,19442,7812,6,0), +(19244,0,19244,1,0), +(19478,0,19478,1,0), +(19505,0,19505,1,0), +(19506,0,19506,1,0), +(19647,19244,19244,2,0), +(19655,19478,19478,2,0), +(19656,19655,19478,3,0), +(19660,19656,19478,4,0), +(19731,19505,19505,2,0), +(19734,19731,19505,3,0), +(19736,19734,19505,4,0), +(19740,0,19740,1,0), +(19742,0,19742,1,0), +(19750,0,19750,1,0), +(19834,19740,19740,2,0), +(19835,19834,19740,3,0), +(19836,19835,19740,4,0), +(19837,19836,19740,5,0), +(19838,19837,19740,6,0), +(19850,19742,19742,2,0), +(19852,19850,19742,3,0), +(19853,19852,19742,4,0), +(19854,19853,19742,5,0), +(19876,0,19876,1,0), +(19888,0,19888,1,0), +(19891,0,19891,1,0), +(19895,19876,19876,2,0), +(19896,19895,19876,3,0), +(19897,19888,19888,2,0), +(19898,19897,19888,3,0), +(19899,19891,19891,2,0), +(19900,19899,19891,3,0), +(19939,19750,19750,2,0), +(19940,19939,19750,3,0), +(19941,19940,19750,4,0), +(19942,19941,19750,5,0), +(19943,19942,19750,6,0), +(19977,0,19977,1,0), +(19978,19977,19977,2,0), +(19979,19978,19977,3,0), +(20043,0,20043,1,0), +(20116,26573,26573,2,0), +(20162,21082,21082,2,0), +(20164,0,20164,1,0), +(20165,0,20165,1,0), +(20166,0,20166,1,0), +(20190,20043,20043,2,0), +(20217,0,20217,1,0), +(20219,12656,4036,5,0), +(20222,12656,4036,5,0), +(20243,0,20243,1,0), +(20252,0,20252,1,0), +(20287,21084,21084,2,0), +(20288,20287,21084,3,0), +(20289,20288,21084,4,0), +(20290,20289,21084,5,0), +(20291,20290,21084,6,0), +(20292,20291,21084,7,0), +(20293,20292,21084,8,0), +(20305,20162,21082,3,0), +(20306,20305,21082,4,0), +(20307,20306,21082,5,0), +(20308,20307,21082,6,0), +(20347,20165,20165,2,0), +(20348,20347,20165,3,0), +(20349,20348,20165,4,0), +(20356,20166,20166,2,0), +(20357,20356,20166,3,0), +(20375,0,20375,1,0), +(20473,0,20473,1,0), +(20484,0,20484,1,0), +(20559,7402,694,4,0), +(20560,20559,694,5,0), +(20569,11609,845,5,0), +(20609,2008,2008,2,0), +(20610,20609,2008,3,0), +(20616,20252,20252,2,0), +(20617,20616,20252,3,0), +(20658,5308,5308,2,0), +(20660,20658,5308,3,0), +(20661,20660,5308,4,0), +(20662,20661,5308,5,0), +(20729,6940,6940,2,0), +(20736,0,20736,1,0), +(20739,20484,20484,2,0), +(20742,20739,20484,3,0), +(20747,20742,20484,4,0), +(20748,20747,20484,5,0), +(20752,693,693,2,0), +(20755,20752,693,3,0), +(20756,20755,693,4,0), +(20757,20756,693,5,0), +(20770,10881,2006,5,0), +(20772,10324,7328,4,0), +(20773,20772,7328,5,0), +(20776,20610,2008,4,0), +(20777,20776,2008,5,0), +(20900,19434,19434,2,0), +(20901,20900,19434,3,0), +(20902,20901,19434,4,0), +(20903,20902,19434,5,0), +(20904,20903,19434,6,0), +(20905,19506,19506,2,0), +(20906,20905,19506,3,0), +(20909,19306,19306,2,0), +(20910,20909,19306,3,0), +(20911,0,20911,1,0), +(20912,20911,20911,2,0), +(20913,20912,20911,3,0), +(20914,20913,20911,4,0), +(20915,20375,20375,2,0), +(20918,20915,20375,3,0), +(20919,20918,20375,4,0), +(20920,20919,20375,5,0), +(20922,20116,26573,3,0), +(20923,20922,26573,4,0), +(20924,20923,26573,5,0), +(20925,0,20925,1,0), +(20927,20925,20925,2,0), +(20928,20927,20925,3,0), +(20929,20473,20473,2,0), +(20930,20929,20473,3,0), +(21082,0,21082,1,0), +(21084,0,21084,1,0), +(21551,12294,12294,2,0), +(21552,21551,12294,3,0), +(21553,21552,12294,4,0), +(21562,0,21562,1,0), +(21564,21562,21562,2,0), +(21849,0,21849,1,0), +(21850,21849,21849,2,0), +(22568,0,22568,1,0), +(22782,6117,6117,2,0), +(22783,22782,6117,3,0), +(22827,22568,22568,2,0), +(22828,22827,22568,3,0), +(22829,22828,22568,4,0), +(22842,0,22842,1,0), +(22895,22842,22842,2,0), +(22896,22895,22842,3,0), +(23028,0,23028,1,0), +(23099,0,23099,1,0), +(23109,23099,23099,2,0), +(23110,23109,23099,3,0), +(23145,0,23145,1,0), +(23147,23145,23145,2,0), +(23148,23147,23145,3,0), +(23881,0,23881,1,0), +(23892,23881,23881,2,0), +(23893,23892,23881,3,0), +(23894,23893,23881,4,0), +(23922,0,23922,1,0), +(23923,23922,23922,2,0), +(23924,23923,23922,3,0), +(23925,23924,23922,4,0), +(23992,0,23992,1,0), +(24132,19386,19386,2,0), +(24133,24132,19386,3,0), +(24224,0,24224,1,0), +(24239,24274,24275,3,0), +(24248,31018,22568,6,0), +(24274,24275,24275,2,0), +(24275,0,24275,1,0), +(24398,0,24398,1,0), +(24423,0,24423,1,0), +(24439,23992,23992,2,0), +(24444,24439,23992,3,0), +(24445,24444,23992,4,0), +(24446,0,24446,1,0), +(24447,24446,24446,2,0), +(24448,24447,24446,3,0), +(24449,24448,24446,4,0), +(24450,0,24450,1,0), +(24452,24450,24450,2,0), +(24453,24452,24450,3,0), +(24488,0,24488,1,0), +(24492,0,24492,1,0), +(24493,0,24493,1,0), +(24497,24493,24493,2,0), +(24500,24497,24493,3,0), +(24501,24500,24493,4,0), +(24502,24492,24492,2,0), +(24503,24502,24492,3,0), +(24504,24503,24492,4,0), +(24505,24488,24488,2,0), +(24506,24505,24488,3,0), +(24507,24506,24488,4,0), +(24545,0,24545,1,0), +(24549,24545,24545,2,0), +(24550,24549,24545,3,0), +(24551,24550,24545,4,0), +(24552,24551,24545,5,0), +(24553,24552,24545,6,0), +(24554,24553,24545,7,0), +(24555,24554,24545,8,0), +(24577,24423,24423,2,0), +(24578,24577,24423,3,0), +(24579,24578,24423,4,0), +(24583,24640,24640,2,0), +(24586,24583,24640,3,0), +(24587,24586,24640,4,0), +(24597,24603,24604,4,0), +(24604,0,24604,1,0), +(24605,24604,24604,2,0), +(24603,24605,24604,3,0), +(24629,24555,24545,9,0), +(24630,24629,24545,10,0), +(24640,0,24640,1,0), +(24844,0,24844,1,0), +(24974,5570,5570,2,0), +(24975,24974,5570,3,0), +(24976,24975,5570,4,0), +(24977,24976,5570,5,0), +(25008,24844,24844,2,0), +(25009,25008,24844,3,0), +(25010,25009,24844,4,0), +(25011,25010,24844,5,0), +(25012,25011,24844,6,0), +(25076,0,25076,1,0), +(25202,11556,1160,6,0), +(25203,25202,1160,7,0), +(25208,11574,772,8,0), +(25210,25314,2060,6,0), +(25212,7373,1715,4,0), +(25213,25210,2060,7,0), +(25217,10901,17,11,0), +(25218,25217,17,12,0), +(25221,25315,139,11,0), +(25222,25221,139,12,0), +(25225,11597,7386,6,0), +(25229,0,25229,1,0), +(25230,25229,25229,2,0), +(25231,20569,845,6,0), +(25233,10917,2061,8,0), +(25234,20662,5308,6,0), +(25235,25233,2061,9,0), +(25236,25234,5308,7,0), +(25241,11605,1464,5,0), +(25242,25241,1464,6,0), +(25248,21553,12294,5,0), +(25251,23894,23881,5,0), +(25258,23925,23922,5,0), +(25264,11581,6343,7,0), +(25266,20560,694,6,0), +(25269,25288,6572,7,0), +(25272,20617,20252,4,0), +(25275,25272,20252,5,0), +(25286,11567,78,9,0), +(25288,11601,6572,6,0), +(25289,11551,6673,7,0), +(25290,19854,19742,6,0), +(25291,19838,19740,7,0), +(25292,10329,635,9,0), +(25294,14290,2643,5,0), +(25295,13555,1978,9,0), +(25296,14322,13165,7,0), +(25297,9889,5185,11,0), +(25298,9876,2912,7,0), +(25299,9841,774,11,0), +(25300,11281,53,9,0), +(25302,11303,1966,5,0), +(25304,10181,116,11,0), +(25306,10151,133,12,0), +(25307,11661,686,10,0), +(25308,25316,596,6,0), +(25309,11668,348,8,0), +(25311,11672,172,7,0), +(25312,27841,14752,5,0), +(25314,10965,2060,5,0), +(25315,10929,139,10,0), +(25316,10961,596,5,0), +(25331,27801,15237,7,0), +(25345,10212,5143,8,0), +(25347,11358,2835,5,0), +(25357,10396,331,10,0), +(25359,10627,8835,3,0), +(25361,10442,8075,5,0), +(25363,10934,585,9,0), +(25364,25363,585,10,0), +(25367,10894,589,9,0), +(25368,25367,589,10,0), +(25372,10947,8092,10,0), +(25375,25372,8092,11,0), +(25379,10876,8129,6,0), +(25380,25379,8129,7,0), +(25384,15261,14914,9,0), +(25387,18807,15407,7,0), +(25389,10938,1243,7,0), +(25391,25357,331,11,0), +(25396,25391,331,12,0), +(25420,10468,8004,7,0), +(25422,10623,1064,4,0), +(25423,25422,1064,5,0), +(25429,10942,586,7,0), +(25431,10952,588,7,0), +(25433,10958,976,4,0), +(25435,20770,2006,6,0), +(25437,19243,13908,8,0), +(25439,10605,421,5,0), +(25441,19275,13896,6,0), +(25442,25439,421,6,0), +(25446,19305,10797,8,0), +(25448,15208,403,11,0), +(25449,25448,403,12,0), +(25454,10414,8042,8,0), +(25457,29228,8050,7,0), +(25464,10473,8056,5,0), +(25467,19280,2944,7,0), +(25469,10432,324,8,0), +(25470,19285,9035,7,0), +(25472,25469,324,9,0), +(25477,19312,18137,7,0), +(25479,16316,8017,8,0), +(25485,25479,8017,9,0), +(25489,16342,8024,7,0), +(25500,16356,8033,6,0), +(25505,16362,8232,5,0), +(25508,10408,8071,7,0), +(25509,25508,8071,8,0), +(25525,10428,5730,7,0), +(25528,25361,8075,6,0), +(25533,10438,3599,7,0), +(25546,11315,1535,6,0), +(25547,25546,1535,7,0), +(25552,10587,8190,5,0), +(25557,16387,8227,5,0), +(25560,10479,8181,4,0), +(25563,10538,8184,4,0), +(25567,10463,5394,6,0), +(25570,10497,5675,5,0), +(25574,10601,10595,4,0), +(25577,15112,15107,4,0), +(25585,10614,8512,4,0), +(25587,25585,8512,5,0), +(25596,10953,453,4,0), +(25782,0,25782,1,19838), +(25890,0,25890,1,19979), +(25894,0,25894,1,19854), +(25895,0,25895,1,1038), +(25898,0,25898,1,20217), +(25899,0,25899,1,20914), +(25916,25782,25782,2,25291), +(25918,25894,25894,2,25290), +(26064,0,26064,1,0), +(26090,0,26090,1,0), +(26177,7371,7371,2,0), +(26178,26177,7371,3,0), +(26179,26178,7371,4,0), +(26187,26090,26090,2,0), +(26188,26187,26090,3,0), +(26201,26179,7371,5,0), +(26573,0,26573,1,0), +(26790,12180,3908,5,0), +(26797,12180,3908,5,0), +(26798,12180,3908,5,0), +(26801,12180,3908,5,0), +(26839,11290,703,7,0), +(26861,11294,1752,9,0), +(26862,26861,1752,10,0), +(26863,25300,53,10,0), +(26864,17348,16511,4,0), +(26865,31016,2098,10,0), +(26866,11198,8647,6,0), +(26867,11275,1943,7,0), +(26884,26839,703,8,0), +(26889,1857,1856,3,0), +(26892,11343,8681,7,0), +(26969,25347,2835,6,0), +(26978,25297,5185,12,0), +(26979,26978,5185,13,0), +(26980,9858,8936,10,0), +(26981,25299,774,12,0), +(26982,26981,774,13,0), +(26983,9863,740,5,0), +(26984,9912,5176,9,0), +(26985,26984,5176,10,0), +(26986,25298,2912,8,0), +(26987,9835,8921,11,0), +(26988,26987,8921,12,0), +(26989,9853,339,7,0), +(26990,9885,1126,8,0), +(26992,9910,467,7,0), +(26993,9907,770,5,0), +(26994,20748,20484,6,0), +(26995,9901,2908,4,0), +(26996,9881,6807,8,0), +(26997,9908,779,6,0), +(26998,9898,99,6,0), +(26999,22896,22842,4,0), +(27001,9830,5221,6,0), +(27002,27001,5221,7,0), +(27003,9904,1822,5,0), +(27005,9867,6785,5,0), +(27006,9827,9005,4,0), +(27008,9896,1079,7,0), +(27009,17329,16689,7,26989), +(27011,17392,16857,5,0), +(27012,17402,16914,4,0), +(27013,24977,5570,6,0), +(27014,14266,2973,9,0), +(27015,14273,781,4,0), +(27016,25295,1978,10,0), +(27018,14280,3034,4,0), +(27019,14287,3044,9,0), +(27020,15632,20736,7,0), +(27021,25294,2643,6,0), +(27022,14295,1510,4,0), +(27023,14305,13795,6,0), +(27025,14317,13813,4,0), +(27028,10846,3273,5,0), +(27044,25296,13165,8,0), +(27045,20190,20043,3,0), +(27046,13544,136,8,0), +(27047,14921,2649,8,0), +(27048,16697,1742,7,0), +(27049,3009,16827,9,0), +(27050,17261,17253,9,0), +(27051,24579,24423,5,0), +(27052,24501,24493,5,0), +(27053,24445,23992,5,0), +(27054,24449,24446,5,0), +(27055,24504,24492,5,0), +(27056,24507,24488,5,0), +(27060,24587,24640,5,0), +(27061,24630,24545,11,0), +(27062,5042,4187,11,0), +(27063,26188,26090,4,0), +(27065,20904,19434,7,0), +(27066,20906,19506,4,0), +(27067,20910,19306,4,0), +(27068,24133,19386,4,0), +(27070,25306,133,13,0), +(27071,25304,116,12,0), +(27072,27071,116,13,0), +(27073,10207,2948,8,0), +(27074,27073,2948,9,0), +(27075,25345,5143,9,0), +(27078,10199,2136,8,0), +(27079,27078,2136,9,0), +(27080,10202,1449,7,0), +(27082,27080,1449,8,0), +(27085,10187,10,7,0), +(27086,10216,2120,7,0), +(27087,10161,120,6,0), +(27088,10230,122,5,0), +(27090,37420,5504,9,0), +(27124,10220,7302,5,0), +(27125,22783,6117,4,0), +(27126,10157,1459,6,0), +(27128,10225,543,6,0), +(27130,10170,1008,5,0), +(27131,10193,1463,7,0), +(27132,18809,11366,9,0), +(27133,13021,11113,6,0), +(27134,13033,11426,5,0), +(27135,25292,635,10,0), +(27136,27135,635,11,0), +(27137,19943,19750,7,0), +(27138,10314,879,7,0), +(27139,10318,2812,3,0), +(27140,25291,19740,8,0), +(27141,25916,25782,3,27140), +(27142,25290,19742,7,0), +(27143,25918,25894,3,27142), +(27144,19979,19977,4,0), +(27145,25890,25890,2,27144), +(27147,20729,6940,3,0), +(27148,27147,6940,4,0), +(27149,10293,465,8,0), +(27150,10301,7294,6,0), +(27151,19896,19876,4,0), +(27152,19898,19888,4,0), +(27153,19900,19891,4,0), +(27154,10310,633,4,0), +(27155,20293,21084,9,0), +(27158,20308,21082,7,0), +(27166,20357,20166,4,0), +(27168,20914,20911,5,0), +(27169,25899,25899,2,27168), +(27170,20920,20375,6,0), +(27173,20924,26573,6,0), +(27174,20930,20473,4,0), +(27179,20928,20925,4,0), +(27180,24239,24275,4,0), +(27209,25307,686,11,0), +(27210,17923,5676,7,0), +(27211,17924,6353,3,0), +(27212,11678,5740,5,0), +(27213,11684,1949,4,0), +(27215,25309,348,9,0), +(27216,25311,172,8,0), +(27217,11675,1120,5,0), +(27218,11713,980,7,0), +(27219,11700,689,7,0), +(27220,27219,689,8,0), +(27221,11704,5138,5,0), +(27222,11689,1454,7,0), +(27223,17926,6789,4,0), +(27224,11708,702,7,0), +(27226,11717,704,5,0), +(27228,11722,1490,4,0), +(27229,17937,17862,3,0), +(27230,11730,6201,6,0), +(27238,20757,693,6,0), +(27250,17953,6366,5,0), +(27259,11695,755,8,0), +(27260,11735,706,6,0), +(27263,18871,17877,7,0), +(27264,18881,18265,5,0), +(27265,18938,18220,4,0), +(27266,18932,17962,5,0), +(27267,11763,3110,8,0), +(27268,11767,6307,6,0), +(27269,11771,2947,6,0), +(27270,11775,3716,7,0), +(27271,17752,17735,5,0), +(27272,17854,17767,7,0), +(27273,19443,7812,7,0), +(27274,11780,7814,7,0), +(27275,11785,6360,5,0), +(27276,19736,19505,5,0), +(27277,27276,19505,6,0), +(27280,19660,19478,5,0), +(27282,26969,2835,7,0), +(27283,13230,13220,5,0), +(27441,11269,8676,7,0), +(27448,25302,1966,6,0), +(27681,14752,14752,2,0), +(27683,0,27683,1,0), +(27685,26201,7371,6,0), +(27799,15431,15237,4,0), +(27800,27799,15237,5,0), +(27801,27800,15237,6,0), +(27841,14819,14752,4,0), +(27870,724,724,2,0), +(27871,27870,724,3,0), +(28029,13920,7411,5,0), +(28172,17728,2362,4,0), +(28176,0,28176,1,0), +(28189,28176,28176,2,0), +(28275,27871,724,4,0), +(28596,11611,2259,5,0), +(28609,10177,6143,5,0), +(28610,11740,6229,4,0), +(28612,10145,587,7,0), +(28672,11611,2259,5,0), +(28675,11611,2259,5,0), +(28677,11611,2259,5,0), +(28695,11993,2366,5,0), +(28894,25230,25229,3,0), +(28895,28894,25229,4,0), +(28897,28895,25229,5,0), +(29228,10448,8050,6,0), +(29354,10248,2575,5,0), +(29704,1672,72,4,0), +(29707,25286,78,10,0), +(29722,0,29722,1,0), +(29801,0,29801,1,0), +(29844,9785,2018,5,0), +(30016,20243,20243,2,0), +(30022,30016,20243,3,0), +(30030,29801,29801,2,0), +(30033,30030,29801,3,0), +(30108,0,30108,1,0), +(30151,0,30151,1,0), +(30194,30151,30151,2,0), +(30198,30194,30151,3,0), +(30213,0,30213,1,0), +(30219,30213,30213,2,0), +(30223,30219,30213,3,0), +(30283,0,30283,1,0), +(30324,29707,78,11,0), +(30330,25248,12294,6,0), +(30335,25251,23881,6,0), +(30350,12656,4036,5,0), +(30356,25258,23922,6,0), +(30357,25269,6572,8,0), +(30404,30108,30108,2,0), +(30405,30404,30108,3,0), +(30413,30283,30283,2,0), +(30414,30413,30283,3,0), +(30459,27210,5676,8,0), +(30545,27211,6353,4,0), +(30546,27263,17877,8,0), +(30908,27221,5138,6,0), +(30909,27224,702,8,0), +(30910,603,603,2,0), +(30911,27264,18265,6,0), +(30912,27266,17962,6,0), +(31016,11300,2098,9,0), +(31018,22829,22568,5,0), +(31661,0,31661,1,0), +(31785,0,31785,1,0), +(31895,20164,20164,2,0), +(31935,0,31935,1,0), +(32231,29722,29722,2,0), +(32379,0,32379,1,0), +(32549,10662,2108,5,0), +(32593,974,974,2,0), +(32594,32593,974,3,0), +(32645,0,32645,1,0), +(32678,10768,8613,5,0), +(32684,32645,32645,2,0), +(32699,31935,31935,2,0), +(32700,32699,31935,3,0), +(32796,28609,6143,6,0), +(32996,32379,32379,2,0), +(32999,27681,14752,3,0), +(33041,31661,31661,2,0), +(33042,33041,31661,3,0), +(33043,33042,31661,4,0), +(33072,27174,20473,5,0), +(33095,18248,7620,5,0), +(33142,0,33142,1,0), +(33145,33142,33142,2,0), +(33146,33145,33142,3,0), +(33359,18260,2550,5,0), +(33388,0,33388,1,0), +(33391,33388,33388,2,0), +(33405,27134,11426,6,0), +(33698,0,33698,1,0), +(33699,33698,33698,2,0), +(33700,33699,33698,3,0), +(33701,27271,17735,6,0), +(33717,28612,587,8,0), +(33736,24398,24398,2,0), +(33776,31785,31785,2,0), +(33876,0,33876,1,0), +(33878,0,33878,1,0), +(33933,27133,11113,7,0), +(33938,27132,11366,10,0), +(33943,0,33943,1,0), +(33944,10174,604,6,0), +(33946,27130,1008,6,0), +(33982,33876,33876,2,0), +(33983,33982,33876,3,0), +(33986,33878,33878,2,0), +(33987,33986,33878,3,0), +(34411,1329,1329,2,0), +(34412,34411,1329,3,0), +(34413,34412,1329,4,0), +(34506,0,34506,1,0), +(34507,34506,34506,2,0), +(34508,34507,34506,3,0), +(34838,34508,34506,4,0), +(34839,34838,34506,5,0), +(34861,0,34861,1,0), +(34863,34861,34861,2,0), +(34864,34863,34861,3,0), +(34865,34864,34861,4,0), +(34866,34865,34861,5,0), +(34889,0,34889,1,0), +(34914,0,34914,1,0), +(34916,34914,34914,2,0), +(34917,34916,34914,3,0), +(34950,0,34950,1,0), +(34954,34950,34950,2,0), +(35323,34889,34889,2,0), +(35290,0,35290,1,0), +(35291,35290,35290,2,0), +(35292,35291,35290,3,0), +(35293,35292,35290,4,0), +(35294,35293,35290,5,0), +(35295,35294,35290,6,0), +(35296,35295,35290,7,0), +(35297,35296,35290,8,0), +(35298,35297,35290,9,0), +(35387,0,35387,1,0), +(35389,35387,35387,2,0), +(35392,35389,35387,3,0), +(35346,0,35346,1,0), +(35694,0,35694,1,0), +(35698,35694,35694,2,0), +(36916,14271,1495,5,0), +(37420,10140,5504,8,0), +(38692,27070,133,14,0), +(38697,27072,116,14,0), +(38699,27075,5143,10,0), +(38704,38699,5143,11,0), +(38764,11286,1776,6,0), +(38768,1769,1766,5,0), +(40120,33943,33943,2,0); +/*!40000 ALTER TABLE `spell_chain` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `spell_elixir` +-- + +DROP TABLE IF EXISTS `spell_elixir`; +CREATE TABLE `spell_elixir` ( + `entry` int(11) unsigned NOT NULL default '0' COMMENT 'SpellId of potion', + `mask` tinyint(1) unsigned NOT NULL default '0' COMMENT 'Mask 0x1 battle 0x2 guardian 0x3 flask 0x7 unstable flasks 0xB shattrath flasks', + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Spell System'; + +-- +-- Dumping data for table `spell_elixir` +-- + +LOCK TABLES `spell_elixir` WRITE; +/*!40000 ALTER TABLE `spell_elixir` DISABLE KEYS */; +INSERT INTO `spell_elixir` VALUES +( 673,0x2), +( 2367,0x1), +( 2374,0x1), +( 2378,0x2), +( 2380,0x2), +( 3160,0x1), +( 3164,0x1), +( 3166,0x2), +( 3219,0x2), +( 3220,0x2), +( 3222,0x2), +( 3223,0x2), +( 3593,0x2), +( 7844,0x1), +( 8212,0x1), +(10667,0x1), +(10668,0x2), +(10669,0x1), +(10692,0x2), +(10693,0x2), +(11319,0x2), +(11328,0x1), +(11334,0x1), +(11348,0x2), +(11349,0x2), +(11364,0x2), +(11371,0x2), +(11390,0x1), +(11396,0x2), +(11405,0x1), +(11406,0x1), +(11474,0x1), +(15231,0x2), +(15233,0x2), +(16321,0x2), +(16322,0x1), +(16323,0x1), +(16325,0x2), +(16326,0x2), +(16327,0x2), +(16329,0x1), +(17038,0x1), +(17535,0x2), +(17537,0x1), +(17538,0x1), +(17539,0x1), +(17624,0x3), +(17626,0x3), +(17627,0x3), +(17629,0x3), +(17628,0x3), +(21920,0x1), +(24361,0x2), +(24363,0x2), +(24382,0x2), +(24383,0x2), +(24417,0x2), +(26276,0x1), +(27652,0x2), +(27653,0x2), +(28486,0x1), +(28488,0x1), +(28490,0x1), +(28491,0x1), +(28493,0x1), +(28497,0x1), +(28501,0x1), +(28502,0x2), +(28503,0x1), +(28509,0x2), +(28514,0x2), +(28518,0x3), +(28519,0x3), +(28520,0x3), +(28521,0x3), +(28540,0x3), +(29348,0x2), +(33720,0x1), +(33721,0x1), +(33726,0x1), +(38954,0x1), +(39625,0x2), +(39626,0x2), +(39627,0x2), +(39628,0x2), +(40567,0x7), +(40568,0x7), +(40572,0x7), +(40573,0x7), +(40575,0x7), +(40576,0x7), +(41608,0xB), +(41609,0xB), +(41610,0xB), +(41611,0xB), +(42735,0x3), +(46837,0xB), +(46839,0xB); +/*!40000 ALTER TABLE `spell_elixir` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `spell_learn_spell` +-- + +DROP TABLE IF EXISTS `spell_learn_spell`; +CREATE TABLE `spell_learn_spell` ( + `entry` smallint(5) unsigned NOT NULL default '0', + `SpellID` smallint(5) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`,`SpellID`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Item System'; + +-- +-- Dumping data for table `spell_learn_spell` +-- + +LOCK TABLES `spell_learn_spell` WRITE; +/*!40000 ALTER TABLE `spell_learn_spell` DISABLE KEYS */; +INSERT INTO `spell_learn_spell` VALUES +(2842,8681), +(5784,33388), +(13819,33388), +(17002,24867), +(23161,33391), +(23214,33391), +(24866,24864), +(33872,47179), +(33873,47180), +(33943,34090), +(34767,33391), +(34769,33388); + +/*!40000 ALTER TABLE `spell_learn_spell` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `spell_pet_auras` +-- + +DROP TABLE IF EXISTS `spell_pet_auras`; +CREATE TABLE `spell_pet_auras` ( + `spell` mediumint(8) unsigned NOT NULL COMMENT 'dummy spell id', + `pet` mediumint(8) unsigned NOT NULL default '0' COMMENT 'pet id; 0 = all', + `aura` mediumint(8) unsigned NOT NULL COMMENT 'pet aura id', + PRIMARY KEY (`spell`,`pet`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +-- +-- Dumping data for table `spell_pet_auras` +-- + +LOCK TABLES `spell_pet_auras` WRITE; +/*!40000 ALTER TABLE `spell_pet_auras` DISABLE KEYS */; +INSERT INTO `spell_pet_auras` VALUES +(19028, 0, 25228), +(19578, 0, 19579), +(20895, 0, 24529), +(28757, 0, 28758), +(35029, 0, 35060), +(35030, 0, 35061), +(35691, 0, 35696), +(35692, 0, 35696), +(35693, 0, 35696), +(23785, 416, 23759), +(23822, 416, 23826), +(23823, 416, 23827), +(23824, 416, 23828), +(23825, 416, 23829), +(23785, 417, 23762), +(23822, 417, 23837), +(23823, 417, 23838), +(23824, 417, 23839), +(23825, 417, 23840), +(23785, 1860, 23760), +(23822, 1860, 23841), +(23823, 1860, 23842), +(23824, 1860, 23843), +(23825, 1860, 23844), +(23785, 1863, 23761), +(23822, 1863, 23833), +(23823, 1863, 23834), +(23824, 1863, 23835), +(23825, 1863, 23836), +(23785, 17252, 35702), +(23822, 17252, 35703), +(23823, 17252, 35704), +(23824, 17252, 35705), +(23825, 17252, 35706); + +/*!40000 ALTER TABLE `spell_pet_auras` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `spell_proc_event` +-- + +DROP TABLE IF EXISTS `spell_proc_event`; +CREATE TABLE `spell_proc_event` ( + `entry` smallint(5) unsigned NOT NULL default '0', + `SchoolMask` tinyint(4) NOT NULL default '0', + `Category` smallint(6) NOT NULL default '0', + `SkillID` smallint(6) NOT NULL default '0', + `SpellFamilyName` smallint(5) unsigned NOT NULL default '0', + `SpellFamilyMask` bigint(20) unsigned NOT NULL default '0', + `procFlags` int(10) unsigned NOT NULL default '0', + `ppmRate` float NOT NULL default '0', + `cooldown` int(10) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `spell_proc_event` +-- + +LOCK TABLES `spell_proc_event` WRITE; +/*!40000 ALTER TABLE `spell_proc_event` DISABLE KEYS */; +INSERT INTO `spell_proc_event` VALUES +(168,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(324,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(325,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(588,0,0,0,0,0x0000000000000000,0x00000402,0,0), +(602,0,0,0,0,0x0000000000000000,0x00000402,0,0), +(742,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(905,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(945,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(974,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(1006,0,0,0,0,0x0000000000000000,0x00000402,0,0), +(1120,0,0,0,0,0x0000000000000000,0x00000004,0,0), +(2565,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(2652,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(3235,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(3284,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(3338,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(3394,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(3417,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(3418,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(3424,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(3436,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(3439,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(3440,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(3509,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(3512,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(3582,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(3616,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(3637,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(4070,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(4112,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(4113,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(4114,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(4115,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(4133,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(4136,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(4138,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(4140,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(4142,0,0,0,0,0x0000000000000000,0x00000004,0,0), +(4144,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(4241,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(4242,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(4245,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(4279,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(4283,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(4284,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(4315,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(4317,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(4493,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(4525,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(4932,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(4951,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(5104,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(5118,0,0,0,0,0x0000000000000000,0x00008000,0,0), +(5202,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(5205,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(5262,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(5301,0,0,0,0,0x0000000000000000,0x00000000,0,0), +(5364,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(5368,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(5369,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(5370,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(5377,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(5427,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(5680,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(5728,0,0,0,0,0x0000000000000000,0x00100402,0,0), +(5811,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(6268,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(6397,0,0,0,0,0x0000000000000000,0x00100402,0,0), +(6398,0,0,0,0,0x0000000000000000,0x00100402,0,0), +(6399,0,0,0,0,0x0000000000000000,0x00100402,0,0), +(6433,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(6645,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(6750,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(6752,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(6866,0,0,0,0,0x0000000000000000,0x00000072,0,0), +(6867,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(6870,0,0,0,0,0x0000000000000000,0x00000000,0,0), +(6871,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(6909,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(6921,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(6923,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(6947,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(6961,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(7095,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(7098,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(7102,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(7103,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(7128,0,0,0,0,0x0000000000000000,0x00000402,0,0), +(7131,0,0,0,0,0x0000000000000000,0x000A22A8,0,0), +(7137,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(7276,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(7300,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(7301,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(7302,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(7320,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(7445,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(7446,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(7486,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(7617,0,0,0,0,0x0000000000000000,0x00100002,0,0), +(7619,0,0,0,0,0x0000000000000000,0x00100002,0,0), +(7711,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(7721,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(7722,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(7723,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(7724,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(7725,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(7726,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(7806,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(7807,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(7808,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(7849,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(7999,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(8134,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(8224,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(8247,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(8260,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(8288,0,0,0,0,0x0000000000000000,0x00000004,0,0), +(8289,0,0,0,0,0x0000000000000000,0x00000004,0,0), +(8397,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(8601,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(8612,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(8788,0,0,0,0,0x0000000000000000,0x00000402,0,0), +(8852,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(8876,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(8981,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(9084,0,0,0,0,0x0000000000000000,0x00000008,0,0), +(9160,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(9233,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(9276,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(9452,0,0,0,0,0x0000000000000000,0x00000014,3,0), +(9460,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(9463,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(9778,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(9782,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(9784,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(9799,0,0,0,0,0x0000000000000000,0x00040000,0,0), +(10022,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(10092,0,0,0,0,0x0000000000000000,0x00000080,0,0), +(10219,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(10220,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(10425,0,0,0,0,0x0000000000000000,0x00100402,0,0), +(10426,0,0,0,0,0x0000000000000000,0x00100402,0,0), +(10431,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(10432,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(10951,0,0,0,0,0x0000000000000000,0x00000402,0,0), +(10952,0,0,0,0,0x0000000000000000,0x00000402,0,0), +(11103,4,0,0,0,0x0000000000000000,0x00020000,0,0), +(11119,4,0,0,0,0x0000000000000000,0x00010000,0,0), +(11120,4,0,0,0,0x0000000000000000,0x00010000,0,0), +(11129,4,0,0,0,0x0000000000000000,0x00020000,0,0), +(11180,16,0,0,0,0x0000000000000000,0x00020000,0,0), +(11185,0,0,0,3,0x0000000000000080,0x00020000,0,0), +(11213,0,0,0,0,0x0000000000000000,0x00020000,0,0), +(11255,0,0,0,3,0x0000000000004000,0x00004000,0,0), +(11371,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(11441,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(11675,0,0,0,0,0x0000000000000000,0x00000004,0,0), +(11919,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(11959,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(11964,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(11984,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(12099,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(12169,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(12246,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(12254,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(12281,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(12284,0,0,0,0,0x0000000000000000,0x00000001,0.33252,0), +(12289,0,0,26,0,0x0000000000000002,0x00020000,0,0), +(12292,0,0,0,0,0x0000000000000000,0x00000080,0,0), +(12298,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(12311,0,0,0,4,0x0000000000000800,0x00020000,0,0), +(12317,0,0,0,0,0x0000000000000000,0x00842000,0,0), +(12319,0,0,0,0,0x0000000000000000,0x00011000,0,0), +(12322,0,0,0,0,0x0000000000000000,0x00000001,2,0), +(12328,0,0,0,0,0x0000000000000000,0xC4000001,0,0), +(12357,4,0,0,0,0x0000000000000000,0x00020000,0,0), +(12358,4,0,0,0,0x0000000000000000,0x00020000,0,0), +(12359,4,0,0,0,0x0000000000000000,0x00020000,0,0), +(12360,4,0,0,0,0x0000000000000000,0x00020000,0,0), +(12487,0,0,0,3,0x0000000000000080,0x00020000,0,0), +(12488,0,0,0,3,0x0000000000000080,0x00020000,0,0), +(12529,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(12539,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(12544,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(12550,0,0,0,0,0x0000000000000000,0x00000402,0,0), +(12556,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(12574,0,0,0,0,0x0000000000000000,0x00020000,0,0), +(12575,0,0,0,0,0x0000000000000000,0x00020000,0,0), +(12576,0,0,0,0,0x0000000000000000,0x00020000,0,0), +(12577,0,0,0,0,0x0000000000000000,0x00020000,0,0), +(12598,0,0,0,3,0x0000000000004000,0x00004000,0,0), +(12668,0,0,26,0,0x0000000000000002,0x00020000,0,0), +(12701,0,0,0,0,0x0000000000000000,0x00000001,0.66504,0), +(12702,0,0,0,0,0x0000000000000000,0x00000001,0.99756,0), +(12703,0,0,0,0,0x0000000000000000,0x00000001,1.33008,0), +(12704,0,0,0,0,0x0000000000000000,0x00000001,1.6626,0), +(12724,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(12725,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(12726,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(12727,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(12782,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(12787,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(12797,0,0,0,0,0x0000000000000400,0x00020000,0,0), +(12799,0,0,0,0,0x0000000000000400,0x00020000,0,0), +(12800,0,0,0,0,0x0000000000000400,0x00020000,0,0), +(12812,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(12813,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(12814,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(12815,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(12834,0,0,0,0,0x0000000000000000,0x00011000,0,0), +(12846,4,0,0,0,0x0000000000000000,0x00010000,0,0), +(12847,4,0,0,0,0x0000000000000000,0x00010000,0,0), +(12848,4,0,0,0,0x0000000000000000,0x00010000,0,0), +(12849,0,0,0,0,0x0000000000000000,0x00011000,0,0), +(12867,0,0,0,0,0x0000000000000000,0x00011000,0,0), +(12947,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(12958,0,0,0,4,0x0000000000000800,0x00020000,0,0), +(12966,0,0,0,0,0x0000000000000000,0xC4000001,0,0), +(12967,0,0,0,0,0x0000000000000000,0xC4000001,0,0), +(12968,0,0,0,0,0x0000000000000000,0xC4000001,0,0), +(12969,0,0,0,0,0x0000000000000000,0xC4000001,0,0), +(12970,0,0,0,0,0x0000000000000000,0xC4000001,0,0), +(12971,0,0,0,0,0x0000000000000000,0x00011000,0,0), +(12972,0,0,0,0,0x0000000000000000,0x00011000,0,0), +(12973,0,0,0,0,0x0000000000000000,0x00011000,0,0), +(12974,0,0,0,0,0x0000000000000000,0x00011000,0,0), +(12999,0,0,0,0,0x0000000000000000,0x00000001,4,0), +(13000,0,0,0,0,0x0000000000000000,0x00000001,6,0), +(13001,0,0,0,0,0x0000000000000000,0x00000001,8,0), +(13002,0,0,0,0,0x0000000000000000,0x00000001,10,0), +(13045,0,0,0,0,0x0000000000000000,0x00842000,0,0), +(13046,0,0,0,0,0x0000000000000000,0x00842000,0,0), +(13047,0,0,0,0,0x0000000000000000,0x00842000,0,0), +(13048,0,0,0,0,0x0000000000000000,0x00842000,0,0), +(13159,0,0,0,0,0x0000000000000000,0x00008000,0,0), +(13165,0,0,0,0,0x0000000000000000,0x00080000,0,0), +(13299,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(13358,0,0,0,0,0x0000000000000000,0x00000000,0,0), +(13585,0,0,0,0,0x0000000000000000,0x00000402,0,0), +(13616,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(13709,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(13716,0,0,0,0,0x0000000000000000,0x00000402,0,0), +(13754,0,0,0,0,0x0000000000000010,0x00020000,0,0), +(13800,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(13801,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(13802,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(13803,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(13867,0,0,0,0,0x0000000000000010,0x00020000,0,0), +(13877,0,0,0,0,0x0000000000000000,0xC4000001,0,0), +(13879,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(13886,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(13896,0,0,0,0,0x0000000000000000,0x00100000,0,0), +(13959,0,0,0,0,0x0000000000000000,0x00100002,0,0), +(13960,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(13961,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(13962,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(13963,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(13964,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(13983,0,0,0,0,0x0000000000000000,0x01000010,0,0), +(14070,0,0,0,0,0x0000000000000000,0x01000010,0,0), +(14071,0,0,0,0,0x0000000000000000,0x01000010,0,0), +(14108,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(14111,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(14133,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(14144,0,0,0,0,0x0000000000000000,0x00000004,0,0), +(14148,0,0,0,0,0x0000000000000000,0x00000004,0,0), +(14156,0,0,0,0,0x00000000003E0000,0x00020000,0,0), +(14160,0,0,0,0,0x00000000003E0000,0x00020000,0,0), +(14161,0,0,0,0,0x00000000003E0000,0x00020000,0,0), +(14178,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(14186,0,0,0,8,0x0000000040800508,0x00010000,0,0), +(14190,0,0,0,8,0x0000000040800508,0x00010000,0,0), +(14193,0,0,0,8,0x0000000040800508,0x00010000,0,0), +(14194,0,0,0,8,0x0000000040800508,0x00010000,0,0), +(14195,0,0,0,8,0x0000000040800508,0x00010000,0,0), +(14318,0,0,0,0,0x0000000000000000,0x00080000,0,0), +(14319,0,0,0,0,0x0000000000000000,0x00080000,0,0), +(14320,0,0,0,0,0x0000000000000000,0x00080000,0,0), +(14321,0,0,0,0,0x0000000000000000,0x00080000,0,0), +(14322,0,0,0,0,0x0000000000000000,0x00080000,0,0), +(14531,0,0,0,0,0x0000000000000000,0x00002000,0,0), +(14774,0,0,0,0,0x0000000000000000,0x00002000,0,0), +(14796,0,0,0,0,0x0000000000000000,0x00000800,0,0), +(14869,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(14892,0,0,0,6,0x0000000410001E00,0x10000000,0,0), +(15088,0,0,0,0,0x0000000000000000,0x00001000,0,0), +(15097,0,0,0,0,0x0000000000000000,0x00002000,0,0), +(15268,32,0,0,0,0x0000000000000000,0x00020000,0,0), +(15270,0,0,0,0,0x0000000000000000,0x00000004,0,0), +(15277,0,0,0,0,0x0000000000000000,0x00000001,6,0), +(15286,32,0,0,0,0x0000000000000000,0x00008000,0,0), +(15323,32,0,0,0,0x0000000000000000,0x00020000,0,0), +(15324,32,0,0,0,0x0000000000000000,0x00020000,0,0), +(15325,32,0,0,0,0x0000000000000000,0x00020000,0,0), +(15326,32,0,0,0,0x0000000000000000,0x00020000,0,0), +(15335,0,0,0,0,0x0000000000000000,0x00000004,0,0), +(15336,0,0,0,0,0x0000000000000000,0x00000004,0,0), +(15337,0,0,0,0,0x0000000000000000,0x00000004,0,0), +(15338,0,0,0,0,0x0000000000000000,0x00000004,0,0), +(15346,0,0,0,0,0x0000000000000000,0x00000001,6,0), +(15362,0,0,0,6,0x0000000410001E00,0x10000000,0,0), +(15363,0,0,0,6,0x0000000410001E00,0x10000000,0,0), +(15506,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(15507,0,0,0,0,0x0000000000000000,0x00000402,0,0), +(15573,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(15594,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(15599,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(15600,0,0,0,0,0x0000000000000000,0x00000001,0.6,0), +(15603,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(15636,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(15641,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(15730,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(15733,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(15784,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(15849,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(15852,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(15876,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(15978,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(16092,0,0,0,0,0x0000000000000000,0x00000000,0,0), +(16142,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(16146,0,0,0,0,0x0000000000000000,0x00000800,0,0), +(16164,28,0,0,0,0x0000000000000000,0x00010000,0,0), +(16176,0,0,0,0,0x0000000000000000,0x10000000,0,0), +(16235,0,0,0,0,0x0000000000000000,0x10000000,0,0), +(16240,0,0,0,0,0x0000000000000000,0x10000000,0,0), +(16247,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(16256,0,0,0,0,0x0000000000000000,0x00001000,0,0), +(16257,0,0,0,0,0x0000000000000000,0xC4000001,0,0), +(16277,0,0,0,0,0x0000000000000000,0xC4000001,0,0), +(16278,0,0,0,0,0x0000000000000000,0xC4000001,0,0), +(16279,0,0,0,0,0x0000000000000000,0xC4000001,0,0), +(16280,0,0,0,0,0x0000000000000000,0xC4000001,0,0), +(16281,0,0,0,0,0x0000000000000000,0x00001000,0,0), +(16282,0,0,0,0,0x0000000000000000,0x00001000,0,0), +(16283,0,0,0,0,0x0000000000000000,0x00001000,0,0), +(16284,0,0,0,0,0x0000000000000000,0x00001000,0,0), +(16428,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(16487,0,0,0,0,0x0000000000000000,0x00842000,0,0), +(16489,0,0,0,0,0x0000000000000000,0x00842000,0,0), +(16492,0,0,0,0,0x0000000000000000,0x00842000,0,0), +(16550,0,0,0,0,0x0000000000000000,0x00002000,0,0), +(16574,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(16575,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(16611,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(16615,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(16620,0,0,0,0,0x0000000000000000,0x00100402,0,30), +(16624,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(16689,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(16792,0,0,0,0,0x0000000000000000,0x00002000,0,0), +(16800,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(16810,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(16811,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(16812,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(16813,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(16843,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(16850,0,0,0,0,0x0000000000000004,0x00020000,0,0), +(16864,0,0,0,0,0x0000000000000000,0x00000001,2,0), +(16880,0,0,0,0,0x0000000000000000,0x00010000,0,0), +(16923,0,0,0,0,0x0000000000000004,0x00020000,0,0), +(16924,0,0,0,0,0x0000000000000004,0x00020000,0,0), +(16952,0,0,0,0,0x0000040000039000,0x00010000,0,0), +(16954,0,0,0,0,0x0000040000039000,0x00010000,0,0), +(16958,0,0,0,0,0x0000000000000000,0x00011000,0,0), +(16961,0,0,0,0,0x0000000000000000,0x00011000,0,0), +(16982,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(17010,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(17106,0,0,0,7,0x0000000000080000,0x00004000,0,0), +(17107,0,0,0,7,0x0000000000080000,0x00004000,0,0), +(17108,0,0,0,7,0x0000000000080000,0x00004000,0,0), +(17329,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(17332,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(17350,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(17364,0,0,0,0,0x0000000000000000,0x00008000,0,0), +(17495,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(17670,0,0,0,0,0x0000000000000000,0x00000008,0,0), +(17687,0,0,0,0,0x0000000000000000,0xC4000001,0,0), +(17688,0,0,0,0,0x0000000000000000,0x00000080,0,0), +(17690,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(17793,0,0,0,5,0x0000000000000001,0x00010000,0,0), +(17794,0,0,0,0,0x0000000000000000,0x00008000,0,0), +(17796,0,0,0,5,0x0000000000000001,0x00010000,0,0), +(17797,0,0,0,0,0x0000000000000000,0x00008000,0,0), +(17798,0,0,0,0,0x0000000000000000,0x00008000,0,0), +(17799,0,0,0,0,0x0000000000000000,0x00008000,0,0), +(17800,0,0,0,0,0x0000000000000000,0x00008000,0,0), +(17801,0,0,0,5,0x0000000000000001,0x00010000,0,0), +(17802,0,0,0,5,0x0000000000000001,0x00010000,0,0), +(17803,0,0,0,5,0x0000000000000001,0x00010000,0,0), +(18073,0,0,0,0,0x0000008000000060,0x00020000,0,0), +(18094,0,0,0,5,0x000000000000000A,0x00020000,0,0), +(18095,0,0,0,5,0x000000000000000A,0x00020000,0,0), +(18096,0,0,0,0,0x0000008000000060,0x00020000,0,0), +(18097,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(18100,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(18119,0,0,593,0,0x0000000000000000,0x00020000,0,0), +(18120,0,0,593,0,0x0000000000000000,0x00020000,0,0), +(18121,0,0,593,0,0x0000000000000000,0x00020000,0,0), +(18122,0,0,593,0,0x0000000000000000,0x00020000,0,0), +(18123,0,0,593,0,0x0000000000000000,0x00020000,0,0), +(18137,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(18146,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(18167,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(18186,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(18189,0,0,0,0,0x0000000000000000,0x00020000,0,0), +(18542,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(18765,0,0,0,0,0x0000000000000000,0xC4000001,0,0), +(18799,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(18800,0,0,0,0,0x0000000000000000,0x00000008,0,0), +(18803,0,0,0,0,0x0000000000000000,0x00004000,0,0), +(18815,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(18816,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(18847,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(18943,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(18979,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(18983,0,0,0,0,0x0000000000000000,0x00000004,0,0), +(19184,0,0,0,0,0x0000000000000000,0x00200000,0,0), +(19194,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(19228,0,0,0,0,0x0000000000000040,0x00020000,0,0), +(19232,0,0,0,0,0x0000000000000040,0x00020000,0,0), +(19233,0,0,0,0,0x0000000000000040,0x00020000,0,0), +(19261,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(19262,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(19264,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(19265,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(19266,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(19271,0,0,0,0,0x0000000000000000,0x00100000,0,0), +(19273,0,0,0,0,0x0000000000000000,0x00100000,0,0), +(19274,0,0,0,0,0x0000000000000000,0x00100000,0,0), +(19275,0,0,0,0,0x0000000000000000,0x00100000,0,0), +(19308,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(19309,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(19310,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(19311,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(19312,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(19387,0,0,0,0,0x0000000000000000,0x00200000,0,0), +(19388,0,0,0,0,0x0000000000000000,0x00200000,0,0), +(19407,0,0,0,0,0x0000000000000200,0x00020000,0,0), +(19409,0,0,0,0,0x0000000000000000,0x00100002,0,0), +(19412,0,0,0,0,0x0000000000000200,0x00020000,0,0), +(19413,0,0,0,0,0x0000000000000200,0x00020000,0,0), +(19414,0,0,0,0,0x0000000000000200,0x00020000,0,0), +(19415,0,0,0,0,0x0000000000000200,0x00020000,0,0), +(19449,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(19478,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(19514,0,0,0,0,0x0000000000000000,0x00000402,0,0), +(19572,0,0,0,9,0x0000000000800000,0x08000000,0,0), +(19573,0,0,0,9,0x0000000000800000,0x08000000,0,0), +(19577,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(19655,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(19656,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(19660,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(19817,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(19818,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(20049,0,0,0,0,0x0000000000000000,0x00011000,0,0), +(20056,0,0,0,0,0x0000000000000000,0x00011000,0,0), +(20057,0,0,0,0,0x0000000000000000,0x00011000,0,0), +(20058,0,0,0,0,0x0000000000000000,0x00011000,0,0), +(20059,0,0,0,0,0x0000000000000000,0x00011000,0,0), +(20127,0,0,0,0,0x0000000000000000,0x00000402,0,0), +(20128,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(20130,0,0,0,0,0x0000000000000000,0x00000402,0,0), +(20131,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(20132,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(20133,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(20134,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(20135,0,0,0,0,0x0000000000000000,0x00000402,0,0), +(20136,0,0,0,0,0x0000000000000000,0x00000402,0,0), +(20137,0,0,0,0,0x0000000000000000,0x00000402,0,0), +(20154,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(20164,0,0,0,0,0x0000000000000000,0x00000001,5,0), +(20165,0,0,0,0,0x0000000000000000,0x00000001,20,0), +(20166,0,0,0,0,0x0000000000000000,0x00000001,20,0), +(20177,0,0,0,0,0x0000000000000000,0x00100402,0,0), +(20178,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(20179,0,0,0,0,0x0000000000000000,0x00100402,0,0), +(20180,0,0,0,0,0x0000000000000000,0x00100402,0,0), +(20181,0,0,0,0,0x0000000000000000,0x00100402,0,0), +(20182,0,0,0,0,0x0000000000000000,0x00100402,0,0), +(20185,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(20186,0,0,0,0,0x0000000000000000,0x00100402,0,0), +(20210,0,0,0,10,0x00010000C0000000,0x10000000,0,0), +(20212,0,0,0,10,0x00010000C0000000,0x10000000,0,0), +(20213,0,0,0,10,0x00010000C0000000,0x10000000,0,0), +(20214,0,0,0,10,0x00010000C0000000,0x10000000,0,0), +(20215,0,0,0,10,0x00010000C0000000,0x10000000,0,0), +(20230,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(20234,0,0,0,0,0x0000000000008000,0x00020000,0,0), +(20235,0,0,0,0,0x0000000000008000,0x00020000,0,0), +(20287,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(20288,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(20289,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(20290,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(20291,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(20292,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(20293,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(20344,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(20345,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(20346,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(20347,0,0,0,0,0x0000000000000000,0x00000001,20,0), +(20348,0,0,0,0,0x0000000000000000,0x00000001,20,0), +(20349,0,0,0,0,0x0000000000000000,0x00000001,20,0), +(20354,0,0,0,0,0x0000000000000000,0x00100402,0,0), +(20355,0,0,0,0,0x0000000000000000,0x00100402,0,0), +(20356,0,0,0,0,0x0000000000000000,0x00000001,20,0), +(20357,0,0,0,0,0x0000000000000000,0x00000001,20,0), +(20375,0,0,0,0,0x0000000000000000,0x00000001,7,0), +(20500,0,0,0,4,0x0000000010000000,0x00004000,0,0), +(20501,0,0,0,4,0x0000000010000000,0x00004000,0,0), +(20545,0,0,0,0,0x0000000000000000,0x00000402,0,0), +(20705,0,0,0,0,0x0000000000000000,0x00002000,0,0), +(20725,0,0,0,0,0x0000000000000000,0x00001000,0,0), +(20784,0,0,0,0,0x0000000000000000,0x00001000,0,0), +(20847,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(20884,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(20891,0,0,0,0,0x0000000000000000,0x00001000,0,0), +(20911,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(20912,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(20913,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(20914,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(20915,0,0,0,0,0x0000000000000000,0x00000001,7,0), +(20918,0,0,0,0,0x0000000000000000,0x00000001,7,0), +(20919,0,0,0,0,0x0000000000000000,0x00000001,7,0), +(20920,0,0,0,0,0x0000000000000000,0x00000001,7,0), +(20925,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(20927,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(20928,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(21053,0,0,0,0,0x0000000000000000,0x00000004,0,0), +(21061,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(21063,0,0,0,0,0x0000000000000000,0x00008000,0,0), +(21080,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(21084,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(21185,0,0,0,0,0x0000000000000000,0x00000004,0,10), +(21334,0,0,0,0,0x0000000000000000,0x00008000,0,0), +(21645,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(21747,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(21788,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(21838,0,0,0,0,0x0000000000000000,0x00008000,0,0), +(21841,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(21853,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(21882,0,0,0,0,0x0000000000000000,0x00001000,0,0), +(21890,0,0,0,4,0x0000036C2A764EEF,0x00082001,0,0), +(21893,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(21897,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(21911,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(21969,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(21978,0,0,0,0,0x0000000000000000,0x00020000,0,0), +(22007,0,0,0,0,0x0000000000200821,0x00004000,0,0), +(22413,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(22438,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(22618,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(22620,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(22648,0,0,0,0,0x0000000000000000,0x00001000,0,0), +(22835,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(22857,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(23340,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(23378,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(23547,0,0,0,0,0x0000000000000000,0x00000020,0,0), +(23548,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(23551,0,0,0,0,0x00000000000000C0,0x00004000,0,0), +(23552,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(23572,0,0,0,0,0x00000000000000C0,0x00004000,0,0), +(23578,0,0,0,0,0x0000000000000000,0x00080000,2,0), +(23581,0,0,0,0,0x0000000000000000,0x00000001,2,0), +(23686,0,0,0,0,0x0000000000000000,0x00000001,2,0), +(23688,0,0,0,0,0x0000000000000000,0x00004000,0,0), +(23689,0,0,0,0,0x0000000000000000,0x00000001,4,0), +(23695,0,0,0,0,0x0000000000000002,0x00020000,0,0), +(23721,0,0,0,0,0x0000000000000800,0x00020000,0,0), +(23771,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(23780,0,0,0,0,0x0000000000000000,0x00100002,0,0), +(23863,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(23867,0,0,0,0,0x0000000000000000,0x00000081,0,0), +(23885,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(23886,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(23887,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(23888,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(24051,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(24256,0,0,0,0,0x0000000000000000,0x00080001,0,0), +(24389,4,0,0,0,0x0000000000000000,0x00020000,0,0), +(24398,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(24574,0,0,0,0,0x0000000000000000,0x00100002,0,0), +(24596,0,0,0,0,0x0000000000000000,0x00000000,0,0), +(24597,0,0,0,0,0x0000000000000000,0x00080001,0,0), +(24603,0,0,0,0,0x0000000000000000,0x00080001,0,0), +(24604,0,0,0,0,0x0000000000000000,0x00080001,0,0), +(24605,0,0,0,0,0x0000000000000000,0x00080001,0,0), +(24658,0,0,0,0,0x0000000000000000,0x00004000,0,0), +(24661,0,0,0,0,0x0000000000000000,0x00080001,0,0), +(24905,0,0,0,0,0x0000000000000000,0x00000001,15,0), +(24932,0,0,0,0,0x0000000000000000,0x00001000,0,6), +(24949,0,0,0,0,0x0000000000000000,0x00000000,0,0), +(25020,0,0,0,0,0x0000000000000000,0x00000402,0,0), +(25023,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(25296,0,0,0,0,0x0000000000000000,0x00080000,0,0), +(25431,0,0,0,0,0x0000000000000000,0x00000402,0,0), +(25441,0,0,0,0,0x0000000000000000,0x00100000,0,0), +(25461,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(25469,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(25472,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(25477,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(25513,0,0,0,0,0x0000000000000000,0x00100402,0,0), +(25669,0,0,0,0,0x0000000000000000,0x00000001,1,0), +(25759,0,0,0,0,0x0000000000000000,0x00000000,0,0), +(25760,0,0,0,0,0x0000000000000000,0x00000000,0,0), +(25761,0,0,0,0,0x0000000000000000,0x00000000,0,0), +(25762,0,0,0,0,0x0000000000000000,0x00000000,0,0), +(25767,0,0,0,0,0x0000000000000000,0x00020000,0,0), +(25820,0,0,0,0,0x0000000000000000,0x00100402,0,0), +(25899,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(25906,0,0,0,0,0x0000000000000000,0x00020000,0,0), +(25937,0,0,0,0,0x0000000000000000,0x00000000,0,0), +(25988,0,0,0,0,0x0000000000000000,0x00040000,0,0), +(26016,0,0,0,0,0x0000000000000000,0x00000001,2,0), +(26021,0,0,0,0,0x0000000000000000,0x00000001,2,0), +(26107,0,0,0,7,0x0000008000800000,0xC4000000,0,0), +(26119,0,0,0,11,0x0000000090100003,0x00004000,0,0), +(26128,0,0,0,0,0x0000000000000000,0x02000000,0,0), +(26135,0,0,0,0,0x0000000000800000,0x00004000,0,0), +(26169,0,0,0,0,0x0000000000000000,0x08000000,0,0), +(26376,0,0,0,0,0x0000000000000000,0x00000000,0,0), +(26463,0,0,0,0,0x0000000000000000,0x00100000,0,0), +(26467,0,0,0,0,0x0000000000000000,0x08000000,0,0), +(26480,0,0,0,0,0x0000000000000000,0x00080001,3,0), +(27009,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(27044,0,0,0,0,0x0000000000000000,0x00080000,0,0), +(27124,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(27155,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(27160,0,0,0,0,0x0000000000000000,0x00000001,20,0), +(27162,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(27164,0,0,0,0,0x0000000000000000,0x00100402,0,0), +(27166,0,0,0,0,0x0000000000000000,0x00000001,20,0), +(27168,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(27169,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(27170,0,0,0,0,0x0000000000000000,0x00000001,7,0), +(27179,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(27200,0,0,0,0,0x0000000000000000,0x00000000,0,0), +(27217,0,0,0,0,0x0000000000000000,0x00000004,0,0), +(27243,0,0,0,0,0x0000000000000000,0x00008000,0,0), +(27280,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(27419,0,0,0,0,0x0000000000000000,0x00000001,3,0), +(27420,0,0,0,0,0x0000000000000000,0x00000000,0,0), +(27498,0,0,0,0,0x0000000000000000,0x00000001,3,0), +(27521,0,0,0,0,0x0000000000000000,0x00004000,0,0), +(27522,0,0,0,0,0x0000000000000000,0x00080001,0,0), +(27539,0,0,0,0,0x0000000000000000,0x00100000,0,0), +(27561,0,0,0,0,0x0000000000000000,0x00020000,0,0), +(27656,0,0,0,0,0x0000000000000000,0x00000001,3,0), +(27688,0,0,0,0,0x0000000000000000,0x00100402,0,0), +(27774,0,0,0,0,0x0000000000000000,0x00004000,0,0), +(27776,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(27778,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(27780,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(27781,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(27785,0,0,0,0,0x0000000000000000,0x00080000,0,0), +(27787,0,0,0,0,0x0000000000000000,0x00000001,3,0), +(27811,0,0,0,0,0x0000000000000000,0x00802000,0,0), +(27815,0,0,0,0,0x0000000000000000,0x00802000,0,0), +(27816,0,0,0,0,0x0000000000000000,0x00802000,0,0), +(27852,0,0,0,0,0x0000000000000000,0x00008000,0,0), +(27861,0,0,0,0,0x0000000000000000,0x00000000,0,0), +(27863,0,0,0,0,0x0000000000000000,0x00000000,0,0), +(27864,0,0,0,0,0x0000000000000000,0x00000000,0,0), +(27865,0,0,0,0,0x0000000000000000,0x00000000,0,0), +(27867,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(28200,0,0,0,0,0x0000000000000000,0x08000000,0,0), +(28305,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(28429,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(28458,0,0,0,0,0x0000000000000000,0x00000000,0,0), +(28460,0,0,0,0,0x0000000000000000,0x00000000,0,0), +(28592,16,0,0,0,0x0000000000000000,0x00020000,0,0), +(28593,16,0,0,0,0x0000000000000000,0x00020000,0,0), +(28594,16,0,0,0,0x0000000000000000,0x00020000,0,0), +(28595,16,0,0,0,0x0000000000000000,0x00020000,0,0), +(28716,0,0,0,7,0x0000000000000010,0x08000000,0,0), +(28719,0,0,0,7,0x0000000000000020,0x10000000,0,0), +(28744,0,0,0,7,0x0000000000000040,0x08000000,0,0), +(28752,0,0,0,0,0x0000000000000000,0x00400000,0,0), +(28761,0,0,0,0,0x0000000000000000,0x00020000,0,0), +(28764,0,0,0,0,0x0000000000000000,0x00100000,0,0), +(28771,0,0,0,0,0x0000000000000000,0x00020000,0,0), +(28780,0,0,0,0,0x0000000000000000,0x08020000,0,0), +(28789,0,0,0,10,0x0000000000006000,0x20000000,0,0), +(28802,0,0,0,0,0x0000000000000000,0x00004000,0,0), +(28809,0,0,0,0,0x0000000000001000,0x10000000,0,0), +(28812,0,0,0,0,0x0000000000000000,0x00010000,0,0), +(28816,0,0,0,0,0x0000000000000000,0x00000001,3,0), +(28823,0,0,0,0,0x00000000000000C0,0x08000000,0,0), +(28845,0,0,0,0,0x0000000000000000,0x00000200,0,0), +(28847,0,0,0,7,0x0000000000000020,0x00004000,0,0), +(28849,0,0,0,11,0x0000000000000080,0x00004000,0,0), +(29062,0,0,0,0,0x0000000000000000,0x00802000,0,0), +(29064,0,0,0,0,0x0000000000000000,0x00802000,0,0), +(29065,0,0,0,0,0x0000000000000000,0x00802000,0,0), +(29074,20,0,0,0,0x0000000000000000,0x00010000,0,0), +(29075,20,0,0,0,0x0000000000000000,0x00010000,0,0), +(29076,20,0,0,0,0x0000000000000000,0x00010000,0,0), +(29150,0,0,0,0,0x0000000000000000,0x00000001,3,0), +(29162,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(29179,0,0,0,0,0x0000000000000000,0x00010000,0,0), +(29180,0,0,0,0,0x0000000000000000,0x00010000,0,0), +(29185,0,0,0,0,0x0000000000000000,0x00000000,0,0), +(29194,0,0,0,0,0x0000000000000000,0x00000000,0,0), +(29196,0,0,0,0,0x0000000000000000,0x00000000,0,0), +(29198,0,0,0,0,0x0000000000000000,0x00000000,0,0), +(29220,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(29307,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(29441,0,0,0,0,0x0000000000000000,0x01000000,0,1), +(29444,0,0,0,0,0x0000000000000000,0x01000000,0,1), +(29445,0,0,0,0,0x0000000000000000,0x01000000,0,1), +(29446,0,0,0,0,0x0000000000000000,0x01000000,0,1), +(29447,0,0,0,0,0x0000000000000000,0x01000000,0,1), +(29448,0,0,0,0,0x0000000000000000,0xC4000001,0,0), +(29501,0,0,0,0,0x0000000000000000,0x00080000,3,0), +(29601,0,0,0,7,0x0000000000000000,0x00004000,0,0), +(29624,0,0,0,0,0x0000000000000000,0x00080000,3,0), +(29625,0,0,0,0,0x0000000000000000,0x00080000,3,0), +(29626,0,0,0,0,0x0000000000000000,0x00080000,3,0), +(29632,0,0,0,0,0x0000000000000000,0x00080000,3,0), +(29633,0,0,0,0,0x0000000000000000,0x00080000,3,0), +(29634,0,0,0,0,0x0000000000000000,0x00080000,3,0), +(29635,0,0,0,0,0x0000000000000000,0x00080000,3,0), +(29636,0,0,0,0,0x0000000000000000,0x00080000,3,0), +(29637,0,0,0,0,0x0000000000000000,0x00080000,3,0), +(29801,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(30030,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(30033,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(30079,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(30080,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(30081,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(30160,0,0,0,0,0x0000000000000000,0x00010000,0,0), +(30293,0,0,0,5,0x000000C000000381,0x00020000,0,0), +(30295,0,0,0,5,0x000000C000000381,0x00020000,0,0), +(30296,0,0,0,5,0x000000C000000381,0x00020000,0,0), +(30299,36,0,0,0,0x0000000000000000,0x00100000,0,0), +(30301,36,0,0,0,0x0000000000000000,0x00100000,0,0), +(30302,36,0,0,0,0x0000000000000000,0x00100000,0,0), +(30339,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(30482,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(30636,0,0,0,0,0x0000000000000000,0x00080001,0,0), +(30675,0,0,0,11,0x0000000000000003,0x00004000,0,0), +(30678,0,0,0,11,0x0000000000000003,0x00004000,0,0), +(30679,0,0,0,11,0x0000000000000003,0x00004000,0,0), +(30680,0,0,0,11,0x0000000000000003,0x00004000,0,0), +(30681,0,0,0,11,0x0000000000000003,0x00004000,0,0), +(30802,0,0,0,0,0x0000000000000000,0x00001000,0,0), +(30808,0,0,0,0,0x0000000000000000,0x00001000,0,0), +(30809,0,0,0,0,0x0000000000000000,0x00001000,0,0), +(30810,0,0,0,0,0x0000000000000000,0x00001000,0,0), +(30811,0,0,0,0,0x0000000000000000,0x00001000,0,0), +(30823,0,0,0,0,0x0000000000000000,0x00000001,10.5,0), +(30881,0,0,0,0,0x0000000000000000,0x00008000,0,5), +(30883,0,0,0,0,0x0000000000000000,0x00008000,0,5), +(30884,0,0,0,0,0x0000000000000000,0x00008000,0,5), +(30885,0,0,0,0,0x0000000000000000,0x00008000,0,5), +(30886,0,0,0,0,0x0000000000000000,0x00008000,0,5), +(31233,0,0,0,8,0x00000009003E0000,0x00020000,0,0), +(31239,0,0,0,8,0x00000009003E0000,0x00020000,0,0), +(31240,0,0,0,8,0x00000009003E0000,0x00020000,0,0), +(31241,0,0,0,8,0x00000009003E0000,0x00020000,0,0), +(31242,0,0,0,8,0x00000009003E0000,0x00020000,0,0), +(31244,0,0,0,0,0x0000000000000000,0x80000000,0,0), +(31245,0,0,0,0,0x0000000000000000,0x80000000,0,0), +(31255,0,0,0,0,0x0000000000000000,0x00000100,0,0), +(31316,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(31569,0,0,0,3,0x0000000000010000,0x00004000,0,0), +(31570,0,0,0,3,0x0000000000010000,0x00004000,0,0), +(31641,0,0,0,0,0x0000000000000000,0x00080002,0,0), +(31642,0,0,0,0,0x0000000000000000,0x00080002,0,0), +(31785,0,0,0,0,0x0000000000000000,0x20000000,0,0), +(31794,0,0,0,0,0x0000000000000000,0x00004000,0,0), +(31801,0,0,0,0,0x0000000000000000,0x00000001,20,0), +(31828,0,0,0,0,0x0000000000000000,0x00008000,0,0), +(31829,0,0,0,0,0x0000000000000000,0x00008000,0,0), +(31830,0,0,0,0,0x0000000000000000,0x00008000,0,0), +(31833,0,0,0,10,0x0000000080000000,0x00004000,0,0), +(31835,0,0,0,10,0x0000000080000000,0x00004000,0,0), +(31836,0,0,0,10,0x0000000080000000,0x00004000,0,0), +(31892,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(31895,0,0,0,0,0x0000000000000000,0x00000001,5,0), +(31896,0,0,0,0,0x0000000000000000,0x00000001,2,0), +(32215,0,0,0,0,0x0000000000000000,0x00000004,0,0), +(32385,0,0,0,5,0x0000001100000402,0x00020000,0,0), +(32387,0,0,0,5,0x0000001100000402,0x00020000,0,0), +(32392,0,0,0,5,0x0000001100000402,0x00020000,0,0), +(32393,0,0,0,5,0x0000001100000402,0x00020000,0,0), +(32394,0,0,0,5,0x0000001100000402,0x00020000,0,0), +(32587,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(32593,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(32594,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(32642,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(32734,0,0,0,0,0x0000000000000000,0x00000002,0,3), +(32748,0,0,0,8,0x0000000100000000,0x00080000,0,0), +(32776,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(32777,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(32837,0,0,0,0,0x0000000000000000,0x00004000,0,45), +(32850,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(32863,0,0,0,0,0x0000000000000000,0x00008000,0,0), +(33012,0,0,0,0,0x0000000000000000,0x00000004,0,0), +(33014,0,0,0,0,0x0000000000000000,0x00000004,0,0), +(33089,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(33142,0,0,0,0,0x0000000000000000,0x00842000,0,0), +(33145,0,0,0,0,0x0000000000000000,0x00842000,0,0), +(33146,0,0,0,0,0x0000000000000000,0x00842000,0,0), +(33150,0,0,0,0,0x0000000000000000,0x10010000,0,0), +(33154,0,0,0,0,0x0000000000000000,0x10010000,0,0), +(33191,0,0,0,6,0x0000040000808000,0x00020000,0,0), +(33192,0,0,0,6,0x0000040000808000,0x00020000,0,0), +(33193,0,0,0,6,0x0000040000808000,0x00020000,0,0), +(33194,0,0,0,6,0x0000040000808000,0x00020000,0,0), +(33195,0,0,0,6,0x0000040000808000,0x00020000,0,0), +(33297,0,0,0,0,0x0000000000000000,0x00020000,0,0), +(33299,0,0,0,0,0x0000000000000000,0x00004000,0,0), +(33493,0,0,0,0,0x0000000000000000,0x00000002,0,0), +(33510,0,0,0,0,0x0000000000000000,0x00080001,5,0), +(33511,0,0,0,0,0x0000000000000000,0x00020000,0,0), +(33522,0,0,0,0,0x0000000000000000,0x00020000,0,0), +(33648,0,0,0,0,0x0000000000000000,0x00401000,0,0), +(33727,0,0,0,0,0x0000000000000000,0x00000000,0,0), +(33735,0,0,0,0,0x0000000000000000,0xC4000001,0,0), +(33736,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(33746,0,0,0,0,0x0000000000000000,0x00000004,0,10), +(33754,0,0,0,0,0x0000000000000000,0x00000000,0,0), +(33755,0,0,0,0,0x0000000000000000,0x00000000,0,0), +(33756,0,0,0,0,0x0000000000000000,0x00000000,0,0), +(33757,0,0,0,0,0x0000000000000000,0x00000001,0,3), +(33759,0,0,0,0,0x0000000000000000,0x00000004,0,10), +(33776,0,0,0,0,0x0000000000000000,0x20000000,0,0), +(33881,0,0,0,0,0x0000000000000000,0x00842000,0,0), +(33882,0,0,0,0,0x0000000000000000,0x00842000,0,0), +(33883,0,0,0,0,0x0000000000000000,0x00842000,0,0), +(33953,0,0,0,0,0x0000000000000000,0x08000000,0,0), +(34082,0,0,0,0,0x0000000000000000,0x00000000,0,0), +(34138,0,0,0,11,0x0000000000000080,0x08000000,0,0), +(34303,0,0,0,0,0x0000000000000000,0x00000080,0,0), +(34320,0,0,0,0,0x0000000000000000,0x00010000,0,0), +(34355,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(34457,0,0,0,0,0x0000000000000000,0x00001000,0,0), +(34497,0,0,0,0,0x0000000000000000,0x00400000,0,0), +(34498,0,0,0,0,0x0000000000000000,0x00400000,0,0), +(34499,0,0,0,0,0x0000000000000000,0x00400000,0,0), +(34500,0,0,0,0,0x0000000000000000,0x00400000,0,0), +(34502,0,0,0,0,0x0000000000000000,0x00400000,0,0), +(34503,0,0,0,0,0x0000000000000000,0x00400000,0,0), +(34506,0,0,0,0,0x0000000000000000,0x00080000,0,0), +(34507,0,0,0,0,0x0000000000000000,0x00080000,0,0), +(34508,0,0,0,0,0x0000000000000000,0x00080000,0,0), +(34586,0,0,0,0,0x0000000000000000,0x00080001,1.5,0), +(34749,0,0,0,0,0x0000000000000000,0x02000000,0,0), +(34753,0,0,0,6,0x0000000000001800,0x08000000,0,0), +(34774,0,0,0,0,0x0000000000000000,0x00080001,1.5,20), +(34827,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(34838,0,0,0,0,0x0000000000000000,0x00080000,0,0), +(34839,0,0,0,0,0x0000000000000000,0x00080000,0,0), +(34859,0,0,0,6,0x0000000000001800,0x08000000,0,0), +(34860,0,0,0,6,0x0000000000001800,0x08000000,0,0), +(34914,32,0,0,0,0x0000000000000000,0x00008000,0,0), +(34916,32,0,0,0,0x0000000000000000,0x00008000,0,0), +(34917,32,0,0,0,0x0000000000000000,0x00008000,0,0), +(34935,0,0,0,0,0x0000000000000000,0x00000002,0,8), +(34938,0,0,0,0,0x0000000000000000,0x00000002,0,8), +(34939,0,0,0,0,0x0000000000000000,0x00000002,0,8), +(34948,0,0,0,0,0x0000000000000000,0x00000004,0,0), +(34949,0,0,0,0,0x0000000000000000,0x00000004,0,0), +(34950,0,0,0,0,0x0000000000000000,0x00400000,0,0), +(34954,0,0,0,0,0x0000000000000000,0x00400000,0,0), +(35077,0,0,0,0,0x0000000000000000,0x00008000,0,60), +(35080,0,0,0,0,0x0000000000000000,0x00000001,0,60), +(35083,0,0,0,0,0x0000000000000000,0x00020000,0,60), +(35086,0,0,0,0,0x0000000000000000,0x08020000,0,60), +(35100,0,0,0,0,0x0000000000000000,0x00080000,0,0), +(35102,0,0,0,0,0x0000000000000000,0x00080000,0,0), +(35103,0,0,0,0,0x0000000000000000,0x00080000,0,0), +(35205,0,0,0,0,0x0000000000000000,0xC4000001,0,0), +(35541,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(35550,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(35551,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(35552,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(35553,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(35942,0,0,0,0,0x0000000000000000,0x00080001,0,0), +(36111,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(36123,0,0,0,0,0x0000000000000000,0x00008000,0,0), +(36576,0,0,0,0,0x0000000000000000,0x00008000,0,0), +(37168,0,0,0,8,0x00000009003E0000,0x00020000,0,0), +(37169,0,0,0,8,0x0000000000020000,0x00000000,0,0), +(37170,0,0,0,0,0x0000000000000000,0x00000001,1,0), +(37173,0,0,0,8,0x000001062CBC0598,0x000A0001,0,30), +(37188,0,0,0,10,0x0000000000800000,0x00004000,0,0), +(37189,0,0,0,10,0x0000000000006000,0x10000000,0,60), +(37195,0,0,0,10,0x0000000000800000,0x00004000,0,0), +(37197,0,0,0,0,0x0000000000000000,0x00004000,0,45), +(37213,0,0,0,11,0x0000000090100007,0x00010000,0,0), +(37227,0,0,0,11,0x00000000000001C0,0x10000000,0,60), +(37228,0,0,0,11,0x0000000090100007,0x00020000,0,0), +(37237,0,0,0,11,0x0000000000000001,0x00010000,0,0), +(37239,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(37247,8,0,0,0,0x0000000000000000,0x00004000,0,45), +(37288,0,0,0,0,0x0000000000000000,0x08000000,0,0), +(37295,0,0,0,0,0x0000000000000000,0x00020000,0,0), +(37306,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(37311,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(37336,0,0,0,0,0x0000000000000000,0x00084001,0,0), +(37377,32,0,0,0,0x0000000000000000,0x00004000,0,0), +(37381,0,0,0,0,0x0000000000000000,0x000A0001,0,0), +(37443,0,0,0,0,0x0000000000000000,0x00010000,0,0), +(37447,0,0,0,3,0x0000010000000000,0x00004000,0,0), +(37514,0,0,0,0,0x0000000000000000,0x00000020,0,0), +(37519,0,0,0,0,0x0000000000000000,0x04000000,0,0), +(37525,0,0,0,0,0x0000000000000000,0x00100402,0,0), +(37528,0,0,0,4,0x0000000000000004,0x00000001,0,0), +(37604,0,0,0,0,0x0000000000000000,0x00004000,0,0), +(37617,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(37655,0,0,0,0,0x0000000000000000,0x00004000,0,60), +(37657,0,0,0,0,0x0000000000000000,0x00010000,0,0), +(37705,0,0,0,0,0x0000000000000000,0x08000000,0,0), +(37982,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(38031,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(38196,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(38252,0,0,0,0,0x0000000000000000,0x00008000,0,0), +(38290,0,0,0,0,0x0000000000000000,0x00080000,3,0), +(38299,0,0,0,0,0x0000000000000000,0x08000000,0,0), +(38319,0,0,0,0,0x0000000000000000,0x00004000,0,0), +(38332,0,0,0,0,0x0000000000000000,0x08000000,0,0), +(38334,0,0,0,0,0x0000000000000000,0x00004000,0,60), +(38347,0,0,0,0,0x0000000000000000,0x00010000,0,0), +(38350,0,0,0,0,0x0000000000000000,0x00401000,0,0), +(38394,0,0,0,5,0x0000000000000006,0x00020000,0,0), +(38427,0,0,0,0,0x0000000000000000,0x00000001,0,0), +(39027,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(39367,0,0,0,0,0x0000000000000000,0x00008000,0,0), +(39372,0,0,0,0,0x0000000000000000,0x00020000,0,0), +(39437,4,0,0,0,0x0000000000000000,0x00004000,0,0), +(39438,0,0,0,0,0x0000000000000000,0x00080001,0,0), +(39440,0,0,0,0,0x0000000000000000,0x00020000,0,0), +(39442,0,0,0,0,0x0000000000000000,0x00020001,0,0), +(39443,0,0,0,0,0x0000000000000000,0x00401000,0,0), +(39444,0,0,0,0,0x0000000000000000,0x00100002,0,0), +(39446,0,0,0,0,0x0000000000000000,0x00000004,0,0), +(39530,0,0,0,0,0x0000000000000000,0x00004000,0,0), +(39958,0,0,0,0,0x0000000000000000,0x00000001,0.7,40), +(40353,0,0,0,0,0x0000000000000000,0xC4000001,0,0), +(40407,0,0,0,0,0x0000000000000000,0x00000402,6,0), +(40438,0,0,0,6,0x0000000000008010,0x08020000,0,0), +(40442,0,0,0,7,0x0000044000000014,0x00004001,0,0), +(40444,0,0,0,0,0x0000000000000000,0x00000040,0,0), +(40458,0,0,0,4,0x0000060102000000,0x00000001,0,0), +(40463,0,0,0,11,0x0000001000000081,0x00004001,0,0), +(40470,0,0,0,10,0x00000000C0800000,0x00004000,0,0), +(40475,0,0,0,0,0x0000000000000000,0x00080001,3,0), +(40482,0,0,0,0,0x0000000000000000,0x00010000,0,0), +(40485,0,0,0,9,0x0000000100000000,0x00080000,0,0), +(40478,0,0,0,5,0x0000000000000002,0x00020000,0,0), +(40971,0,0,0,0,0x0000000000000000,0x08000000,0,0), +(41260,0,0,0,0,0x0000000000000000,0x00000004,0,10), +(41262,0,0,0,0,0x0000000000000000,0x00000004,0,10), +(41434,0,0,0,0,0x0000000000000000,0x00000001,2,45), +(41635,0,0,0,0,0x0000000000000000,0x00008000,0,0), +(41989,0,0,0,0,0x0000000000000000,0x00000001,3,0), +(42083,0,0,0,0,0x0000000000000000,0x00401000,0,0), +(42135,0,0,0,0,0x0000000000000000,0x00100402,0,90), +(42136,0,0,0,0,0x0000000000000000,0x00100402,0,90), +(42370,0,0,0,11,0x0000000000000080,0x08000000,0,0), +(43338,0,0,0,0,0x0000000000000000,0x00001000,0,0), +(43728,0,0,0,11,0x0000000000000080,0x08000000,0,0), +(43737,0,0,0,7,0x0000044000000000,0x00000001,0,10), +(43739,0,0,0,7,0x0000000000000002,0x00020000,0,0), +(43745,0,0,0,10,0x0000020000000000,0x00020000,0,0), +(43748,0,0,0,11,0x0000000090100000,0x00004000,0,0), +(43750,0,0,0,11,0x0000000000000001,0x00004000,0,0), +(43823,0,0,0,0,0x0000000000000000,0x00008000,0,0), +(44604,0,0,0,0,0x0000000000000000,0x00004000,0,0), +(44599,0,0,0,0,0x0000000000000000,0x00000001,0,5), +(44835,0,0,0,7,0x0000008000000000,0x00000001,0,0), +(45040,0,0,0,0,0x0000000000000000,0x00080001,0,0), +(45054,0,0,0,0,0x0000000000000000,0x00020000,0,15), +(45057,0,0,0,0,0x0000000000000000,0x00000002,0,30), +(45059,0,0,0,0,0x0000000000000000,0x08000000,0,0), +(45234,0,0,0,0,0x0000000000000000,0x00842000,0,0), +(45243,0,0,0,0,0x0000000000000000,0x00842000,0,0), +(45244,0,0,0,0,0x0000000000000000,0x00842000,0,0), +(45354,0,0,0,0,0x0000000000000000,0x00000001,0,45), +(45355,0,0,0,0,0x0000000000000000,0x00080001,0,0), +(45444,0,0,0,0,0x0000000000000000,0x00100402,0,0), +(45481,0,0,0,0,0x0000000000000000,0x08020000,0,45), +(45482,0,0,0,0,0x0000000000000000,0x00080001,0,45), +(45483,0,0,0,0,0x0000000000000000,0x00080001,0,45), +(45484,0,0,0,0,0x0000000000000000,0x08000000,0,45), +(46046,0,0,0,0,0x0000000000000000,0x00000001,0,5), +(46098,0,0,0,11,0x0000000000000080,0x08000000,0,0), +(46364,0,0,0,0,0x0000000000000000,0x00100402,0,0), +(46569,0,0,0,0,0x0000000000000000,0x00004000,0,45), +(46832,0,0,0,7,0x0000000000000001,0x00004000,0,0); +/*!40000 ALTER TABLE `spell_proc_event` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `spell_script_target` +-- + +DROP TABLE IF EXISTS `spell_script_target`; +CREATE TABLE `spell_script_target` ( + `entry` mediumint(8) unsigned NOT NULL, + `type` tinyint(3) unsigned NOT NULL default '0', + `targetEntry` mediumint(8) unsigned NOT NULL default '0', + UNIQUE KEY `entry_type_target` (`entry`,`type`,`targetEntry`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='Spell System'; + +-- +-- Dumping data for table `spell_script_target` +-- + +LOCK TABLES `spell_script_target` WRITE; +/*!40000 ALTER TABLE `spell_script_target` DISABLE KEYS */; +/*!40000 ALTER TABLE `spell_script_target` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `spell_scripts` +-- + +DROP TABLE IF EXISTS `spell_scripts`; +CREATE TABLE `spell_scripts` ( + `id` mediumint(8) unsigned NOT NULL default '0', + `delay` int(10) unsigned NOT NULL default '0', + `command` mediumint(8) unsigned NOT NULL default '0', + `datalong` mediumint(8) unsigned NOT NULL default '0', + `datalong2` int(10) unsigned NOT NULL default '0', + `datatext` text NOT NULL, + `x` float NOT NULL default '0', + `y` float NOT NULL default '0', + `z` float NOT NULL default '0', + `o` float NOT NULL default '0' +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `spell_scripts` +-- + +LOCK TABLES `spell_scripts` WRITE; +/*!40000 ALTER TABLE `spell_scripts` DISABLE KEYS */; +/*!40000 ALTER TABLE `spell_scripts` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `spell_target_position` +-- + +DROP TABLE IF EXISTS `spell_target_position`; +CREATE TABLE `spell_target_position` ( + `id` mediumint(8) unsigned NOT NULL default '0' COMMENT 'Identifier', + `target_map` smallint(5) unsigned NOT NULL default '0', + `target_position_x` float NOT NULL default '0', + `target_position_y` float NOT NULL default '0', + `target_position_z` float NOT NULL default '0', + `target_orientation` float NOT NULL default '0', + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Spell System'; + +-- +-- Dumping data for table `spell_target_position` +-- + +LOCK TABLES `spell_target_position` WRITE; +/*!40000 ALTER TABLE `spell_target_position` DISABLE KEYS */; +/*!40000 ALTER TABLE `spell_target_position` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `spell_threat` +-- + +DROP TABLE IF EXISTS `spell_threat`; +CREATE TABLE `spell_threat` ( + `entry` mediumint(8) unsigned NOT NULL, + `Threat` smallint(6) NOT NULL, + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED; + +-- +-- Dumping data for table `spell_threat` +-- + +LOCK TABLES `spell_threat` WRITE; +/*!40000 ALTER TABLE `spell_threat` DISABLE KEYS */; +INSERT INTO `spell_threat` VALUES +(78,20), +(284,39), +(285,59), +(770,108), +(778,108), +(1608,78), +(1672,180), +(1715,61), +(2139,300), +(6343,17), +(6572,155), +(6574,195), +(6809,89), +(7372,101), +(7373,141), +(7379,235), +(7386,100), +(7405,140), +(8198,40), +(8204,64), +(8205,96), +(8380,180), +(8972,118), +(9745,148), +(9749,108), +(9880,178), +(9881,207), +(9907,108), +(11556,43), +(11564,98), +(11565,118), +(11566,137), +(11567,145), +(11580,143), +(11581,180), +(11596,220), +(11597,261), +(11600,275), +(11601,315), +(11775,395), +(14274,200), +(14921,415), +(15629,300), +(15630,400), +(15631,500), +(15632,600), +(16857,108), +(17735,200), +(17750,300), +(17751,450), +(17752,600), +(17390,108), +(17391,108), +(17392,108), +(20569,100), +(20736,100), +(20925,20), +(20927,30), +(20928,40), +(23922,160), +(23923,190), +(23924,220), +(23925,250), +(24394,580), +(24583,5), +(25225,300), +(25231,130), +(25258,286), +(25264,215), +(25269,400), +(25286,175), +(25288,355), +(25289,60), +(26993,127), +(26996,176), +(27011,127), +(27179,54), +(29704,230), +(29707,196), +(30324,220), +(30356,323), +(30357,483), +(33745,285), +(33878,129), +(33986,180), +(33987,232); +/*!40000 ALTER TABLE `spell_threat` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `transports` +-- + +DROP TABLE IF EXISTS `transports`; +CREATE TABLE `transports` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `name` text, + `period` mediumint(8) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Transports'; + +-- +-- Dumping data for table `transports` +-- + +LOCK TABLES `transports` WRITE; +/*!40000 ALTER TABLE `transports` DISABLE KEYS */; +/*!40000 ALTER TABLE `transports` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `uptime` +-- + +DROP TABLE IF EXISTS `uptime`; +CREATE TABLE `uptime` ( + `starttime` bigint(20) unsigned NOT NULL default '0', + `startstring` varchar(64) NOT NULL default '', + `uptime` bigint(20) unsigned NOT NULL default '0', + `maxplayers` smallint(5) unsigned NOT NULL default '0', + PRIMARY KEY (`starttime`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Uptime system'; + +-- +-- Dumping data for table `uptime` +-- + +LOCK TABLES `uptime` WRITE; +/*!40000 ALTER TABLE `uptime` DISABLE KEYS */; +/*!40000 ALTER TABLE `uptime` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2008-03-30 15:34:54 diff --git a/sql/realmd.sql b/sql/realmd.sql new file mode 100644 index 00000000000..04edb0cd0d2 --- /dev/null +++ b/sql/realmd.sql @@ -0,0 +1,167 @@ +-- MySQL dump 10.11 +-- +-- Host: localhost Database: realmd +-- ------------------------------------------------------ +-- Server version 5.0.45-Debian_1ubuntu3.1-log + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `account` +-- + +DROP TABLE IF EXISTS `account`; +CREATE TABLE `account` ( + `id` bigint(20) unsigned NOT NULL auto_increment COMMENT 'Identifier', + `username` varchar(32) NOT NULL default '', + `sha_pass_hash` varchar(40) NOT NULL default '', + `gmlevel` tinyint(3) unsigned NOT NULL default '0', + `sessionkey` longtext, + `v` longtext, + `s` longtext, + `email` varchar(320) NOT NULL default '', + `joindate` timestamp NOT NULL default CURRENT_TIMESTAMP, + `last_ip` varchar(30) NOT NULL default '127.0.0.1', + `failed_logins` int(11) unsigned NOT NULL default '0', + `locked` tinyint(3) unsigned NOT NULL default '0', + `last_login` timestamp NOT NULL default '0000-00-00 00:00:00', + `online` tinyint(4) NOT NULL default '0', + `tbc` tinyint(3) unsigned NOT NULL default '0', + `mutetime` bigint(40) unsigned NOT NULL default '0', + `locale` tinyint(3) unsigned NOT NULL default '0', + PRIMARY KEY (`id`), + UNIQUE KEY `idx_username` (`username`), + KEY `idx_gmlevel` (`gmlevel`) +) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci ROW_FORMAT=DYNAMIC COMMENT='Account System'; + +-- +-- Dumping data for table `account` +-- + +LOCK TABLES `account` WRITE; +/*!40000 ALTER TABLE `account` DISABLE KEYS */; +INSERT INTO `account` VALUES +(1,'ADMINISTRATOR','a34b29541b87b7e4823683ce6c7bf6ae68beaaac',3,'','0','0','','2006-04-25 10:18:56','127.0.0.1',0,0,'0000-00-00 00:00:00',0,0,0,0), +(2,'GAMEMASTER','7841e21831d7c6bc0b57fbe7151eb82bd65ea1f9',2,'','0','0','','2006-04-25 10:18:56','127.0.0.1',0,0,'0000-00-00 00:00:00',0,0,0,0), +(3,'MODERATOR','a7f5fbff0b4eec2d6b6e78e38e8312e64d700008',1,'','0','0','','2006-04-25 10:19:35','127.0.0.1',0,0,'0000-00-00 00:00:00',0,0,0,0), +(4,'PLAYER','3ce8a96d17c5ae88a30681024e86279f1a38c041',0,'','0','0','','2006-04-25 10:19:35','127.0.0.1',0,0,'0000-00-00 00:00:00',0,0,0,0); +/*!40000 ALTER TABLE `account` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `account_banned` +-- + +DROP TABLE IF EXISTS `account_banned`; +CREATE TABLE `account_banned` ( + `id` int(11) NOT NULL default '0' COMMENT 'Account id', + `bandate` bigint(40) NOT NULL default '0', + `unbandate` bigint(40) NOT NULL default '0', + `bannedby` varchar(50) NOT NULL, + `banreason` varchar(255) NOT NULL, + `active` tinyint(4) NOT NULL default '1', + PRIMARY KEY (`id`,`bandate`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Ban List'; + +-- +-- Dumping data for table `account_banned` +-- + +LOCK TABLES `account_banned` WRITE; +/*!40000 ALTER TABLE `account_banned` DISABLE KEYS */; +/*!40000 ALTER TABLE `account_banned` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `ip_banned` +-- + +DROP TABLE IF EXISTS `ip_banned`; +CREATE TABLE `ip_banned` ( + `ip` varchar(32) NOT NULL default '127.0.0.1', + `bandate` bigint(40) NOT NULL, + `unbandate` bigint(40) NOT NULL, + `bannedby` varchar(50) NOT NULL default '[Console]', + `banreason` varchar(255) NOT NULL default 'no reason', + PRIMARY KEY (`ip`,`bandate`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Banned IPs'; + +-- +-- Dumping data for table `ip_banned` +-- + +LOCK TABLES `ip_banned` WRITE; +/*!40000 ALTER TABLE `ip_banned` DISABLE KEYS */; +/*!40000 ALTER TABLE `ip_banned` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `realmcharacters` +-- + +DROP TABLE IF EXISTS `realmcharacters`; +CREATE TABLE `realmcharacters` ( + `realmid` int(11) unsigned NOT NULL default '0', + `acctid` bigint(20) unsigned NOT NULL, + `numchars` tinyint(3) unsigned NOT NULL default '0', + PRIMARY KEY (`realmid`,`acctid`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Realm Character Tracker'; + +-- +-- Dumping data for table `realmcharacters` +-- + +LOCK TABLES `realmcharacters` WRITE; +/*!40000 ALTER TABLE `realmcharacters` DISABLE KEYS */; +/*!40000 ALTER TABLE `realmcharacters` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `realmlist` +-- + +DROP TABLE IF EXISTS `realmlist`; +CREATE TABLE `realmlist` ( + `id` int(11) unsigned NOT NULL auto_increment, + `name` varchar(32) NOT NULL default '', + `address` varchar(32) NOT NULL default '127.0.0.1', + `port` int(11) NOT NULL default '8085', + `icon` tinyint(3) unsigned NOT NULL default '0', + `color` tinyint(3) unsigned NOT NULL default '2', + `timezone` tinyint(3) unsigned NOT NULL default '0', + `allowedSecurityLevel` tinyint(3) unsigned NOT NULL default '0', + `population` float unsigned NOT NULL default '0', + PRIMARY KEY (`id`), + UNIQUE KEY `idx_name` (`name`) +) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Realm System'; + +-- +-- Dumping data for table `realmlist` +-- + +LOCK TABLES `realmlist` WRITE; +/*!40000 ALTER TABLE `realmlist` DISABLE KEYS */; +INSERT INTO `realmlist` VALUES +(1,'MaNGOS','127.0.0.1',8085,1,0,1,0,0); +/*!40000 ALTER TABLE `realmlist` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2008-01-10 11:37:06 diff --git a/sql/tools/Makefile.am b/sql/tools/Makefile.am new file mode 100644 index 00000000000..f489b83088b --- /dev/null +++ b/sql/tools/Makefile.am @@ -0,0 +1,36 @@ +# Copyright (C) 2005-2008 MaNGOS +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## Process this file with automake to produce Makefile.in + +## Sub-directories to parse + +## Change installation location +# datadir = mangos/sql/tools +pkgdatadir = $(datadir)/mangos/sql/tools + +## Files to be installed +# Install basic SQL files to datadir +pkgdata_DATA = \ + characters_item_duplicates_remove.sql \ + characters_pet_data_cleanup.sql \ + README + +## Additional files to include when running 'make dist' +EXTRA_DIST = \ + characters_item_duplicates_remove.sql \ + characters_pet_data_cleanup.sql \ + README diff --git a/sql/tools/README b/sql/tools/README new file mode 100644 index 00000000000..de60305cece --- /dev/null +++ b/sql/tools/README @@ -0,0 +1,10 @@ += MaNGOS -- README = + +Copyright (c) 2005-2008 MaNGOS + +See the COPYING file for copying conditions. + +== Database tools == +This folder contains SQL files which can be used for cleanup DB from corrupted or outdated data in safe way. +This tools must be used _only_ when mangos server stopped. +But you can safely use its any times while server shutdown. diff --git a/sql/tools/characters_item_duplicates_remove.sql b/sql/tools/characters_item_duplicates_remove.sql new file mode 100644 index 00000000000..9cdd8738ecd --- /dev/null +++ b/sql/tools/characters_item_duplicates_remove.sql @@ -0,0 +1,22 @@ +DROP TABLE IF EXISTS item_test; +CREATE TABLE item_test +SELECT w.`item_guid`,w.`source`,w.`count` FROM + (SELECT u.`item_guid`,u.`source`,COUNT(u.`item_guid`) as `count` FROM + ((SELECT c.`item` as `item_guid`, 'i' as `source` FROM character_inventory c) UNION + (SELECT a.`itemguid` as `item_guid`, 'a' as `source` FROM auctionhouse a) UNION + (SELECT m.`item_guid` as `item_guid`, 'm' as `source` FROM mail_items m) UNION + (SELECT g.`item_guid` as `item_guid`, 'g' as `source` FROM guild_bank_item g) + ) as u + GROUP BY u.`item_guid` + ) as w + WHERE w.`count` > 1; + +DELETE FROM auctionhouse WHERE itemguid IN (SELECT item_guid FROM item_test WHERE `source`='i'); +DELETE FROM mail_items WHERE item_guid IN (SELECT item_guid FROM item_test WHERE `source`='i'); +DELETE FROM guild_bank_item WHERE item_guid IN (SELECT item_guid FROM item_test WHERE `source`='i'); + +DELETE FROM mail_items WHERE item_guid IN (SELECT item_guid FROM item_test WHERE `source`='a'); +DELETE FROM guild_bank_item WHERE item_guid IN (SELECT item_guid FROM item_test WHERE `source`='a'); + +DELETE FROM guild_bank_item WHERE item_guid IN (SELECT item_guid FROM item_test WHERE `source`='m'); +DROP TABLE IF EXISTS item_test; diff --git a/sql/tools/characters_pet_data_cleanup.sql b/sql/tools/characters_pet_data_cleanup.sql new file mode 100644 index 00000000000..f4454ca856f --- /dev/null +++ b/sql/tools/characters_pet_data_cleanup.sql @@ -0,0 +1,3 @@ +DELETE FROM pet_aura WHERE guid NOT IN (SELECT id FROM character_pet); +DELETE FROM pet_spell WHERE guid NOT IN (SELECT id FROM character_pet); +DELETE FROM pet_spell_cooldown WHERE guid NOT IN (SELECT id FROM character_pet); diff --git a/sql/updates/0.10/4846_characters.sql b/sql/updates/0.10/4846_characters.sql new file mode 100644 index 00000000000..6e8ac96c680 --- /dev/null +++ b/sql/updates/0.10/4846_characters.sql @@ -0,0 +1,20 @@ +ALTER TABLE `mail` + ADD COLUMN `has_items` tinyint(3) unsigned NOT NULL default '0' AFTER `itemTextId`; + +UPDATE `mail` SET `has_items` = '1' WHERE `item_guid`<>'0'; + +DROP TABLE IF EXISTS `mail_items`; +CREATE TABLE `mail_items` ( + `mail_id` int(11) NOT NULL default '0', + `item_guid` int(11) NOT NULL default '0', + `item_template` int(11) NOT NULL default '0', + PRIMARY KEY (`mail_id`,`item_guid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC; + +INSERT INTO `mail_items` SELECT `id`,`item_guid`,`item_template` FROM `mail` WHERE `mail`.`has_items`>0; + +ALTER TABLE `mail` + DROP COLUMN `item_guid`, + DROP COLUMN `item_template`; + +UPDATE `character` SET data = CONCAT(SUBSTRING(data, 1, length(SUBSTRING_INDEX(data, ' ', 48))), " ", "0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ","0 ",SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 140))+2, length(SUBSTRING_INDEX(data, ' ', 225))- length(SUBSTRING_INDEX(data, ' ', 140)) - 1), " ", SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 226))+2, length(SUBSTRING_INDEX(data, ' ', 1249))- length(SUBSTRING_INDEX(data, ' ', 226)) - 1), " ", "0 ",SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 1249))+2, length(SUBSTRING_INDEX(data, ' ', 1259))- length(SUBSTRING_INDEX(data, ' ', 1249)) - 1), " ", "0 ",SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 1259))+2, length(SUBSTRING_INDEX(data, ' ', 1379))- length(SUBSTRING_INDEX(data, ' ', 1259)) - 1), " ", "0 ",SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 1380))+2, length(SUBSTRING_INDEX(data, ' ', 1405))- length(SUBSTRING_INDEX(data, ' ', 1380)) - 1), " ", "0 ",SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 1405))+2, length(SUBSTRING_INDEX(data, ' ', 1410))- length(SUBSTRING_INDEX(data, ' ', 1405)) - 1), " ", "0 ",SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 1410))+2, length(SUBSTRING_INDEX(data, ' ', 1415))- length(SUBSTRING_INDEX(data, ' ', 1410)) - 1), " ", "0 ",SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 1415))+2, length(SUBSTRING_INDEX(data, ' ', 1420))- length(SUBSTRING_INDEX(data, ' ', 1415)) - 1), " ", "0 ",SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 1420))+2, length(SUBSTRING_INDEX(data, ' ', 1436))- length(SUBSTRING_INDEX(data, ' ', 1420)) - 1)) WHERE length(SUBSTRING_INDEX(data, ' ', 1436)) < length(data) and length(SUBSTRING_INDEX(data, ' ', 1437)) >= length(data); diff --git a/sql/updates/0.10/4846_mangos_creature_template.sql b/sql/updates/0.10/4846_mangos_creature_template.sql new file mode 100644 index 00000000000..d97bf56c79e --- /dev/null +++ b/sql/updates/0.10/4846_mangos_creature_template.sql @@ -0,0 +1,52 @@ +-- custom +-- UNIT_NPC_FLAG_GUARD = 0x00010000, old +-- UNIT_NPC_FLAG_GUARD = 0x10000000, new +UPDATE `creature_template` SET `npcflag` = (`npcflag` | 0x10000000) & ~0x00010000 WHERE `npcflag` & 0x00010000; + +-- UNIT_NPC_FLAG_STABLEMASTER = 0x00002000, old +-- UNIT_NPC_FLAG_STABLEMASTER = 0x00400000, new +UPDATE `creature_template` SET `npcflag` = (`npcflag` | 0x00400000) & ~0x00002000 WHERE `npcflag` & 0x00002000; + +-- UNIT_NPC_FLAG_AUCTIONEER = 0x00001000, old +-- UNIT_NPC_FLAG_AUCTIONEER = 0x00200000, new +UPDATE `creature_template` SET `npcflag` = (`npcflag` | 0x00200000) & ~0x00001000 WHERE `npcflag` & 0x00001000; + +-- UNIT_NPC_FLAG_BATTLEFIELDPERSON = 0x00000800, old +-- UNIT_NPC_FLAG_BATTLEMASTER = 0x00100000, new +UPDATE `creature_template` SET `npcflag` = (`npcflag` | 0x00100000) & ~0x00000800 WHERE `npcflag` & 0x00000800; + +-- UNIT_NPC_FLAG_ARMORER = 0x00004000, old +-- UNIT_NPC_FLAG_REPAIR = 0x00001000, new +UPDATE `creature_template` SET `npcflag` = (`npcflag` | 0x00001000) & ~0x00004000 WHERE `npcflag` & 0x00004000; + +-- UNIT_NPC_FLAG_TABARDDESIGNER = 0x00000400, old +-- UNIT_NPC_FLAG_TABARDDESIGNER = 0x00080000, new +UPDATE `creature_template` SET `npcflag` = (`npcflag` | 0x00080000) & ~0x00000400 WHERE `npcflag` & 0x00000400; + +-- UNIT_NPC_FLAG_PETITIONER = 0x00000200, old +-- UNIT_NPC_FLAG_PETITIONER = 0x00040000, new +UPDATE `creature_template` SET `npcflag` = (`npcflag` | 0x00040000) & ~0x00000200 WHERE `npcflag` & 0x00000200; + +-- UNIT_NPC_FLAG_BANKER = 0x00000100, old +-- UNIT_NPC_FLAG_BANKER = 0x00020000, new +UPDATE `creature_template` SET `npcflag` = (`npcflag` | 0x00020000) & ~0x00000100 WHERE `npcflag` & 0x00000100; + +-- UNIT_NPC_FLAG_INNKEEPER = 0x00000080, old +-- UNIT_NPC_FLAG_INNKEEPER = 0x00010000, new +UPDATE `creature_template` SET `npcflag` = (`npcflag` | 0x00010000) & ~0x00000080 WHERE `npcflag` & 0x00000080; + +-- UNIT_NPC_FLAG_SPIRITGUIDE = 0x00000040, old +-- UNIT_NPC_FLAG_SPIRITGUIDE = 0x00008000, new +UPDATE `creature_template` SET `npcflag` = (`npcflag` | 0x00008000) & ~0x00000040 WHERE `npcflag` & 0x00000040; + +-- UNIT_NPC_FLAG_SPIRITHEALER = 0x00000020, old +-- UNIT_NPC_FLAG_SPIRITHEALER = 0x00004000, new +UPDATE `creature_template` SET `npcflag` = (`npcflag` | 0x00004000) & ~0x00000020 WHERE `npcflag` & 0x00000020; + +-- UNIT_NPC_FLAG_TAXIVENDOR = 0x00000008, old +-- UNIT_NPC_FLAG_FLIGHTMASTER = 0x00002000, new +UPDATE `creature_template` SET `npcflag` = (`npcflag` | 0x00002000) & ~0x00000008 WHERE `npcflag` & 0x00000008; + +-- UNIT_NPC_FLAG_VENDOR = 0x00000004, old +-- UNIT_NPC_FLAG_VENDOR = 0x00000080, new +UPDATE `creature_template` SET `npcflag` = (`npcflag` | 0x00000080) & ~0x00000004 WHERE `npcflag` & 0x00000004; diff --git a/sql/updates/0.10/4846_mangos_item_template.sql b/sql/updates/0.10/4846_mangos_item_template.sql new file mode 100644 index 00000000000..4c2aac5754d --- /dev/null +++ b/sql/updates/0.10/4846_mangos_item_template.sql @@ -0,0 +1,2 @@ +ALTER TABLE `item_template` + ADD COLUMN `RequiredArenaRank` INT(10) UNSIGNED NOT NULL DEFAULT 0 AFTER `ExtendedCost`; \ No newline at end of file diff --git a/sql/updates/0.10/4846_mangos_npc_option.sql b/sql/updates/0.10/4846_mangos_npc_option.sql new file mode 100644 index 00000000000..9b205447e55 --- /dev/null +++ b/sql/updates/0.10/4846_mangos_npc_option.sql @@ -0,0 +1,13 @@ +update `npc_option` set `npcflag`=0x00000010 where `id` in('5','49','50'); +update `npc_option` set `npcflag`=0x00000080 where `id` = '3'; +update `npc_option` set `npcflag`=0x00002000 where `id` = '4'; +update `npc_option` set `npcflag`=0x00004000 where `id` = '6'; +update `npc_option` set `npcflag`=0x00008000 where `id` = '7'; +update `npc_option` set `npcflag`=0x00010000 where `id` = '8'; +update `npc_option` set `npcflag`=0x00020000 where `id` = '9'; +update `npc_option` set `npcflag`=0x00040000 where `id` = '10'; +update `npc_option` set `npcflag`=0x00080000 where `id` = '11'; +update `npc_option` set `npcflag`=0x00100000 where `id` = '12'; +update `npc_option` set `npcflag`=0x00200000 where `id` = '13'; +update `npc_option` set `npcflag`=0x00400000 where `id` = '14'; +update `npc_option` set `npcflag`=0x00001000 where `id` = '15'; diff --git a/sql/updates/0.10/4875_mangos_quest_template.sql b/sql/updates/0.10/4875_mangos_quest_template.sql new file mode 100644 index 00000000000..d46e1698915 --- /dev/null +++ b/sql/updates/0.10/4875_mangos_quest_template.sql @@ -0,0 +1 @@ +ALTER TABLE `quest_template` CHANGE COLUMN `RewXpOrMoney` `RewMoneyMaxLevel` int(11) unsigned NOT NULL default '0'; diff --git a/sql/updates/0.10/4890_mangos_item_template.sql b/sql/updates/0.10/4890_mangos_item_template.sql new file mode 100644 index 00000000000..63f2a748b99 --- /dev/null +++ b/sql/updates/0.10/4890_mangos_item_template.sql @@ -0,0 +1,8 @@ +UPDATE `item_template` SET `BagFamily` = 0x00000400 WHERE `BagFamily` =11; +UPDATE `item_template` SET `BagFamily` = 0x00000200 WHERE `BagFamily` =10; +UPDATE `item_template` SET `BagFamily` = 0x00000100 WHERE `BagFamily` = 9; +UPDATE `item_template` SET `BagFamily` = 0x00000080 WHERE `BagFamily` = 8; +UPDATE `item_template` SET `BagFamily` = 0x00000040 WHERE `BagFamily` = 7; +UPDATE `item_template` SET `BagFamily` = 0x00000020 WHERE `BagFamily` = 6; +UPDATE `item_template` SET `BagFamily` = 0x00000008 WHERE `BagFamily` = 4; +UPDATE `item_template` SET `BagFamily` = 0x00000004 WHERE `BagFamily` = 3; diff --git a/sql/updates/0.10/4895_mangos_command.sql b/sql/updates/0.10/4895_mangos_command.sql new file mode 100644 index 00000000000..ed7b45a0628 --- /dev/null +++ b/sql/updates/0.10/4895_mangos_command.sql @@ -0,0 +1,4 @@ +DELETE FROM command WHERE name IN ('tele'); + +INSERT INTO `command` VALUES +('tele',1,'Syntax: .tele #location\r\n\r\nTeleport player to a given location.'); diff --git a/sql/updates/0.10/4896_characters_mail.sql b/sql/updates/0.10/4896_characters_mail.sql new file mode 100644 index 00000000000..94ecebcc8e1 --- /dev/null +++ b/sql/updates/0.10/4896_characters_mail.sql @@ -0,0 +1,2 @@ +ALTER TABLE `mail` + ADD COLUMN `stationery` tinyint(3) NOT NULL DEFAULT '41' AFTER `messageType`; \ No newline at end of file diff --git a/sql/updates/0.10/4898_mangos_playercreateinfo_item.sql b/sql/updates/0.10/4898_mangos_playercreateinfo_item.sql new file mode 100644 index 00000000000..f54742472ac --- /dev/null +++ b/sql/updates/0.10/4898_mangos_playercreateinfo_item.sql @@ -0,0 +1 @@ +INSERT IGNORE INTO `playercreateinfo_item` VALUES (11, 8, 6948, 1); \ No newline at end of file diff --git a/sql/updates/0.10/4904_mangos_item_template.sql b/sql/updates/0.10/4904_mangos_item_template.sql new file mode 100644 index 00000000000..976782abe8a --- /dev/null +++ b/sql/updates/0.10/4904_mangos_item_template.sql @@ -0,0 +1,10 @@ +UPDATE `item_template` SET `spellcooldown_1` = -1 WHERE `spellcooldown_1` = 0; +UPDATE `item_template` SET `spellcategorycooldown_1` = -1 WHERE `spellcategorycooldown_1` = 0; +UPDATE `item_template` SET `spellcooldown_2` = -1 WHERE `spellcooldown_2` = 0; +UPDATE `item_template` SET `spellcategorycooldown_2` = -1 WHERE `spellcategorycooldown_2` = 0; +UPDATE `item_template` SET `spellcooldown_3` = -1 WHERE `spellcooldown_3` = 0; +UPDATE `item_template` SET `spellcategorycooldown_3` = -1 WHERE `spellcategorycooldown_3` = 0; +UPDATE `item_template` SET `spellcooldown_4` = -1 WHERE `spellcooldown_4` = 0; +UPDATE `item_template` SET `spellcategorycooldown_4` = -1 WHERE `spellcategorycooldown_4` = 0; +UPDATE `item_template` SET `spellcooldown_5` = -1 WHERE `spellcooldown_5` = 0; +UPDATE `item_template` SET `spellcategorycooldown_5` = -1 WHERE `spellcategorycooldown_5` = 0; diff --git a/sql/updates/0.10/4908_mangos_spell_proc_event.sql b/sql/updates/0.10/4908_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..7b29b0d8e5b --- /dev/null +++ b/sql/updates/0.10/4908_mangos_spell_proc_event.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (38394); +INSERT INTO `spell_proc_event` VALUES +(38394,36,0,0,5,6,131072,0); diff --git a/sql/updates/0.10/4916_mangos_spell_affect.sql b/sql/updates/0.10/4916_mangos_spell_affect.sql new file mode 100644 index 00000000000..ef3c0b6bad5 --- /dev/null +++ b/sql/updates/0.10/4916_mangos_spell_affect.sql @@ -0,0 +1,60 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (43857,43858,43859); +INSERT INTO `spell_affect` VALUES +(43857,0,0,0,0,0,0,0x0000001000000000,0), +(43858,0,0,0,0,0,0,0x0000001000000000,0), +(43859,0,0,0,0,0,0,0x0000001000000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (43860,43861,43862); +INSERT INTO `spell_affect` VALUES +(43860,0,0,0,0,0,0,0x0000000090100000,0), +(43861,0,0,0,0,0,0,0x0000000090100000,0), +(43862,0,0,0,0,0,0,0x0000000090100000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (28787); +INSERT INTO `spell_affect` VALUES +(28787,0,0,0,0,0,0,0x0000000000001000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (41042,43850,43851,43852); +INSERT INTO `spell_affect` VALUES +(41042,0,0,0,0,0,0,0x0000000000800000,0), +(43850,0,0,0,0,0,0,0x0000000000800000,0), +(43851,0,0,0,0,0,0,0x0000000000800000,0), +(43852,0,0,0,0,0,0,0x0000000000800000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (43854,43855,43856); +INSERT INTO `spell_affect` VALUES +(43854,0,0,0,0,0,0,0x0000004000000000,0), +(43855,0,0,0,0,0,0,0x0000004000000000,0), +(43856,0,0,0,0,0,0,0x0000004000000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (41037,43840,43842,43843); +INSERT INTO `spell_affect` VALUES +(41037,0,0,0,0,0,0,0x0000044000000000,0), +(43840,0,0,0,0,0,0,0x0000044000000000,0), +(43842,0,0,0,0,0,0,0x0000044000000000,0), +(43843,0,0,0,0,0,0,0x0000044000000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (43841,43844,43845); +INSERT INTO `spell_affect` VALUES +(43841,0,0,0,0,0,0,0x0000000000000002,0), +(43844,0,0,0,0,0,0,0x0000000000000002,0), +(43845,0,0,0,0,0,0,0x0000000000000002,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (40460); +INSERT INTO `spell_affect` VALUES +(40460,0,0,0,0,0,0,0x00000009003E0000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (28814); +INSERT INTO `spell_affect` VALUES +(28814,0,0,0,0,0,0,0x0000000000020000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (17768); +INSERT INTO `spell_affect` VALUES +(17768,0,0,0,0,0,0,0x0000000040000000,0), +(17768,1,0,0,0,0,0,0x0000000080000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (29836,29859); +INSERT INTO `spell_affect` VALUES +(29836,0,0,0,0,0,0,0x0000001000000020,0), +(29859,0,0,0,0,0,0,0x0000001000000020,0); + diff --git a/sql/updates/0.10/4921_mangos_gameobject.sql b/sql/updates/0.10/4921_mangos_gameobject.sql new file mode 100644 index 00000000000..f678eae2f9b --- /dev/null +++ b/sql/updates/0.10/4921_mangos_gameobject.sql @@ -0,0 +1,2 @@ +ALTER TABLE `gameobject` CHANGE COLUMN `dynflags` `state` int(11) unsigned NOT NULL default '1'; +UPDATE `gameobject` SET `state` = 1; diff --git a/sql/updates/0.10/4926_mangos_spell_proc_event.sql b/sql/updates/0.10/4926_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..42fddf7ed50 --- /dev/null +++ b/sql/updates/0.10/4926_mangos_spell_proc_event.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (40458); +INSERT INTO `spell_proc_event` VALUES +(40458,0,971,0,4,0x60102000000,1,0); diff --git a/sql/updates/0.10/4937_mangos_spell_affect.sql b/sql/updates/0.10/4937_mangos_spell_affect.sql new file mode 100644 index 00000000000..ec3922919ea --- /dev/null +++ b/sql/updates/0.10/4937_mangos_spell_affect.sql @@ -0,0 +1,56 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (11069,12338,12339,12340,12341); +INSERT INTO `spell_affect` VALUES + (11069,0,0,0,0,0,0,0x0000000000000001,0), + (12338,0,0,0,0,0,0,0x0000000000000001,0), + (12339,0,0,0,0,0,0,0x0000000000000001,0), + (12340,0,0,0,0,0,0,0x0000000000000001,0), + (12341,0,0,0,0,0,0,0x0000000000000001,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (11070,12473,16763,16765,16766); +INSERT INTO `spell_affect` VALUES + (11070,0,0,0,0,0,0,0x0000000000000020,0), + (12473,0,0,0,0,0,0,0x0000000000000020,0), + (16763,0,0,0,0,0,0,0x0000000000000020,0), + (16765,0,0,0,0,0,0,0x0000000000000020,0), + (16766,0,0,0,0,0,0,0x0000000000000020,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (17941); +INSERT INTO `spell_affect` VALUES + (17941,0,0,0,0,0,0,0x0000000000000001,1); + +DELETE FROM `spell_affect` WHERE `entry` IN (20335,20336,20337); +INSERT INTO `spell_affect` VALUES + (20335,0,0,0,0,0,0,0x0000000020000000,0), + (20336,0,0,0,0,0,0,0x0000000020000000,0), + (20337,0,0,0,0,0,0,0x0000000020000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (32043,35396,35397); +INSERT INTO `spell_affect` VALUES + (32043,1,0,0,0,0,0,0x0000040008000000,0), + (35396,1,0,0,0,0,0,0x0000040008000000,0), + (35397,1,0,0,0,0,0,0x0000040008000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (36591); + +DELETE FROM `spell_affect` WHERE `entry` IN (28176); + +DELETE FROM `spell_affect` WHERE `entry` IN (28189); + +DELETE FROM `spell_affect` WHERE `entry` IN (31842); + +DELETE FROM `spell_affect` WHERE `entry` IN (38390); + +DELETE FROM `spell_affect` WHERE `entry` IN (37188); +DELETE FROM `spell_affect` WHERE `entry` IN (37189); +DELETE FROM `spell_affect` WHERE `entry` IN (37227); + +DELETE FROM `spell_affect` WHERE `entry` IN (43837); +INSERT INTO `spell_affect` VALUES + (43837,0,0,0,0,0,0,0x0000000080000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (39950); +INSERT INTO `spell_affect` VALUES + (39950,0,0,0,0,0,0,0x0000000000000040,0); + + + diff --git a/sql/updates/0.10/4937_mangos_spell_proc_event.sql b/sql/updates/0.10/4937_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..1788383317d --- /dev/null +++ b/sql/updates/0.10/4937_mangos_spell_proc_event.sql @@ -0,0 +1,5 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (37188,37189,37227); +INSERT INTO `spell_proc_event` VALUES + (37188,0,0,0,10,0x0000000000800000,0x00004000,0), + (37189,0,0,0,10,0x00000000C0000000,0x10000000,0), + (37227,0,0,0,11,0x00000000000001C0,0x10000000,0); diff --git a/sql/updates/0.10/4948_mangos_spell_affect.sql b/sql/updates/0.10/4948_mangos_spell_affect.sql new file mode 100644 index 00000000000..897fab3956d --- /dev/null +++ b/sql/updates/0.10/4948_mangos_spell_affect.sql @@ -0,0 +1,147 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (11095,12872,12873); +INSERT INTO `spell_affect` VALUES + (11095,0,0,0,0,0,0,0x0000000000000010,0), + (12872,0,0,0,0,0,0,0x0000000000000010,0), + (12873,0,0,0,0,0,0,0x0000000000000010,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (31821); +INSERT INTO `spell_affect` VALUES + (31821,0,0,0,0,0,0,0x0000000004020048,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (23565); +INSERT INTO `spell_affect` VALUES + (23565,0,0,0,0,0,0,0x0000000004020048,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (26130); +INSERT INTO `spell_affect` VALUES + (26130,0,0,0,0,0,0,0x0000000820180000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (20101,20102,20103,20104,20105); +INSERT INTO `spell_affect` VALUES + (20101,0,0,0,0,0,0,0x000004000A000200,0), + (20102,0,0,0,0,0,0,0x000004000A000200,0), + (20103,0,0,0,0,0,0,0x000004000A000200,0), + (20104,0,0,0,0,0,0,0x000004000A000200,0), + (20105,0,0,0,0,0,0,0x000004000A000200,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (27848); +INSERT INTO `spell_affect` VALUES + (27848,0,0,0,0,0,0,0x000004000A000200,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (33695); +INSERT INTO `spell_affect` VALUES + (33695,0,0,0,0,0,0,0x0000000200000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (31879,31880,31881,31882,31883); +INSERT INTO `spell_affect` VALUES + (31879,0,0,0,0,0,0,0x0000000800000400,0), + (31880,0,0,0,0,0,0,0x0000000800000400,0), + (31881,0,0,0,0,0,0,0x0000000800000400,0), + (31882,0,0,0,0,0,0,0x0000000800000400,0), + (31883,0,0,0,0,0,0,0x0000000800000400,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (38426); +INSERT INTO `spell_affect` VALUES + (38426,0,0,0,0,0,0,0x0000000080000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (37189); + +DELETE FROM `spell_affect` WHERE `entry` IN (37739); +INSERT INTO `spell_affect` VALUES + (37739,0,0,0,0,0,0,0x0000000080000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (20359,20360,20361); +INSERT INTO `spell_affect` VALUES + (20359,0,0,0,0,0,0,0x0000000080000000,0), + (20360,0,0,0,0,0,0,0x0000000080000000,0), + (20361,0,0,0,0,0,0,0x0000000080000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (20237,20238,20239); +INSERT INTO `spell_affect` VALUES + (20237,0,0,0,0,0,0,0x00000000C0000000,0), + (20238,0,0,0,0,0,0,0x00000000C0000000,0), + (20239,0,0,0,0,0,0,0x00000000C0000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (37723); +INSERT INTO `spell_affect` VALUES + (37723,0,0,0,0,0,0,0x00000000C0000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (38425,20249,20250,20251); +INSERT INTO `spell_affect` VALUES + (38425,0,0,0,0,0,0,0x0000000040000000,0), + (20249,0,0,0,0,0,0,0x0000000040000000,0), + (20250,0,0,0,0,0,0,0x0000000040000000,0), + (20251,0,0,0,0,0,0,0x0000000040000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (38522); +INSERT INTO `spell_affect` VALUES + (38522,0,0,0,0,0,0,0x0000000040000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (34129); +INSERT INTO `spell_affect` VALUES + (34129,0,0,0,0,0,0,0x0000000040000000,0), + (34129,1,0,0,0,0,0,0x0000000040000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (24460); +INSERT INTO `spell_affect` VALUES + (24460,0,0,0,0,0,0,0x0000000010000180,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (21744); +INSERT INTO `spell_affect` VALUES + (21744,0,0,0,0,0,0,0x0000000010000180,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (20254,20255,20256); +INSERT INTO `spell_affect` VALUES + (20254,0,0,0,0,0,0,0x0000000000020000,0), + (20254,1,0,0,0,0,0,0x0000000000020000,0), + (20254,2,0,0,0,0,0,0x0000000000020000,0), + (20255,0,0,0,0,0,0,0x0000000000020000,0), + (20255,1,0,0,0,0,0,0x0000000000020000,0), + (20255,2,0,0,0,0,0,0x0000000000020000,0), + (20256,0,0,0,0,0,0,0x0000000000020000,0), + (20256,1,0,0,0,0,0,0x0000000000020000,0), + (20256,2,0,0,0,0,0,0x0000000000020000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (38424); +INSERT INTO `spell_affect` VALUES + (38424,0,0,0,0,0,0,0x0000008000000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (41021,41026); +INSERT INTO `spell_affect` VALUES + (41021,0,0,0,0,0,0,0x0000004000000000,0), + (41021,1,0,0,0,0,0,0x0000004000000000,0), + (41026,0,0,0,0,0,0,0x0000004000000000,0), + (41026,1,0,0,0,0,0,0x0000004000000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (38421); +INSERT INTO `spell_affect` VALUES + (38421,0,0,0,0,0,0,0x0000100000000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (37187); +INSERT INTO `spell_affect` VALUES + (37187,0,0,0,0,0,0,0x0000020000000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (37182); +INSERT INTO `spell_affect` VALUES + (37182,0,0,0,0,0,0,0x0000000100000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (28775); +INSERT INTO `spell_affect` VALUES + (28775,0,0,0,0,0,0,0x0000000100000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (37184); +INSERT INTO `spell_affect` VALUES + (37184,0,0,0,0,0,0,0x0000040008000000,0), + (37184,1,0,0,0,0,0,0x0000040008000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (31825,31826); +INSERT INTO `spell_affect` VALUES + (31825,0,0,0,0,0,0,0x0000000000001020,0), + (31825,1,0,0,0,0,0,0x0000000200000000,0), + (31826,0,0,0,0,0,0,0x0000000000001020,0), + (31826,1,0,0,0,0,0,0x0000000200000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (31844,31845); +INSERT INTO `spell_affect` VALUES + (31844,1,0,0,0,0,0,0x000005401A00038C,0), + (31845,1,0,0,0,0,0,0x000005401A00038C,0); diff --git a/sql/updates/0.10/4951_mangos_spell_affect.sql b/sql/updates/0.10/4951_mangos_spell_affect.sql new file mode 100644 index 00000000000..85a9bb0d010 --- /dev/null +++ b/sql/updates/0.10/4951_mangos_spell_affect.sql @@ -0,0 +1,21 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (19498,19499,19500); +INSERT INTO `spell_affect` VALUES + (19498,0,0,0,0,0,0,0x00210810007FA01,0), + (19499,0,0,0,0,0,0,0x00210810007FA01,0), + (19500,0,0,0,0,0,0,0x00210810007FA01,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (19416,19417,19418,19419,19420); +INSERT INTO `spell_affect` VALUES + (19416,0,0,0,0,0,0,0x00210810007FA00,0), + (19417,0,0,0,0,0,0,0x00210810007FA00,0), + (19418,0,0,0,0,0,0,0x00210810007FA00,0), + (19419,0,0,0,0,0,0,0x00210810007FA00,0), + (19420,0,0,0,0,0,0,0x00210810007FA00,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (19485,19487,19488,19489,19490); +INSERT INTO `spell_affect` VALUES + (19485,0,0,0,0,0,0,0x000000100061801,0), + (19487,0,0,0,0,0,0,0x000000100061801,0), + (19488,0,0,0,0,0,0,0x000000100061801,0), + (19489,0,0,0,0,0,0,0x000000100061801,0), + (19490,0,0,0,0,0,0,0x000000100061801,0); diff --git a/sql/updates/0.10/4952_mangos_spell_proc_event.sql b/sql/updates/0.10/4952_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..0d45e5c8e26 --- /dev/null +++ b/sql/updates/0.10/4952_mangos_spell_proc_event.sql @@ -0,0 +1,10 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (13165,14318,14319,14320,14321,14322,25296,27044); +INSERT INTO `spell_proc_event` VALUES + (13165,0,0,0,0,0,0x00080000,0), + (14318,0,0,0,0,0,0x00080000,0), + (14319,0,0,0,0,0,0x00080000,0), + (14320,0,0,0,0,0,0x00080000,0), + (14321,0,0,0,0,0,0x00080000,0), + (14322,0,0,0,0,0,0x00080000,0), + (25296,0,0,0,0,0,0x00080000,0), + (27044,0,0,0,0,0,0x00080000,0); diff --git a/sql/updates/0.10/4971_characters_character_social.sql b/sql/updates/0.10/4971_characters_character_social.sql new file mode 100644 index 00000000000..76f10eee76f --- /dev/null +++ b/sql/updates/0.10/4971_characters_character_social.sql @@ -0,0 +1,15 @@ +ALTER TABLE `character_social` + ADD COLUMN `new_flags` tinyint(1) unsigned NOT NULL default '0'; + +UPDATE `character_social` SET `new_flags` = 1 WHERE `flags`='IGNORE'; + +ALTER TABLE `character_social` + DROP PRIMARY KEY, + DROP COLUMN `flags`, + CHANGE COLUMN `new_flags` `flags` tinyint(1) unsigned NOT NULL default '0', + ADD PRIMARY KEY (`guid`,`friend`,`flags`), + ADD KEY (`guid`), + ADD KEY (`friend`), + ADD KEY `guid_flags` (`guid`,`flags`), + ADD KEY `friend_flags` (`friend`,`flags`); + diff --git a/sql/updates/0.10/4975_mangos_spell_affect.sql b/sql/updates/0.10/4975_mangos_spell_affect.sql new file mode 100644 index 00000000000..7a251973b03 --- /dev/null +++ b/sql/updates/0.10/4975_mangos_spell_affect.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (20216); +INSERT INTO `spell_affect` VALUES + (20216,0,0,0,0,0,0,0x0000000000206000,0); diff --git a/sql/updates/0.10/4975_mangos_spell_proc_event.sql b/sql/updates/0.10/4975_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..8a175bc8a73 --- /dev/null +++ b/sql/updates/0.10/4975_mangos_spell_proc_event.sql @@ -0,0 +1,8 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (20210,20212,20213,20214,20215,37189); +INSERT INTO `spell_proc_event` VALUES + (20210,0,0,0,10,0x0000000000206000,0x10000000,0), + (20212,0,0,0,10,0x0000000000206000,0x10000000,0), + (20213,0,0,0,10,0x0000000000206000,0x10000000,0), + (20214,0,0,0,10,0x0000000000206000,0x10000000,0), + (20215,0,0,0,10,0x0000000000206000,0x10000000,0), + (37189,0,0,0,10,0x0000000000006000,0x10000000,0); diff --git a/sql/updates/0.10/4984_mangos_spell_proc_event.sql b/sql/updates/0.10/4984_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..2e1ce21ad26 --- /dev/null +++ b/sql/updates/0.10/4984_mangos_spell_proc_event.sql @@ -0,0 +1,20 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (12169,20128,20131,20132,20133,20134,32587,32776,32777,38031); +INSERT INTO `spell_proc_event` VALUES + (12169,0,0,0,0,0,0x00000040,0), + (20128,0,0,0,0,0,0x00000040,0), + (20131,0,0,0,0,0,0x00000040,0), + (20132,0,0,0,0,0,0x00000040,0), + (20133,0,0,0,0,0,0x00000040,0), + (20134,0,0,0,0,0,0x00000040,0), + (32587,0,0,0,0,0,0x00000040,0), + (32776,0,0,0,0,0,0x00000040,0), + (32777,0,0,0,0,0,0x00000040,0), + (38031,0,0,0,0,0,0x00000040,0); + + +DELETE FROM `spell_proc_event` WHERE `entry` IN (18803,33299,39530); +INSERT INTO `spell_proc_event` VALUES + (18803,0,0,0,0,0,0x00004000,0), + (33299,0,0,0,0,0,0x00004000,0), + (39530,0,0,0,0,0,0x00004000,0); + diff --git a/sql/updates/0.10/5019_mangos_spell_proc_event.sql b/sql/updates/0.10/5019_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..542359e14eb --- /dev/null +++ b/sql/updates/0.10/5019_mangos_spell_proc_event.sql @@ -0,0 +1,26 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (6268,7137,8260); +INSERT INTO `spell_proc_event` VALUES + (6268,0,0,0,0,0,0x00000001,0), + (8260,0,0,0,0,0,0x00000001,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (24597,24603,24604,24605,30636,35942); +INSERT INTO `spell_proc_event` VALUES + (24597,0,0,0,0,0,0x00080001,0), + (24603,0,0,0,0,0,0x00080001,0), + (24604,0,0,0,0,0,0x00080001,0), + (24605,0,0,0,0,0,0x00080001,0), + (30636,0,0,0,0,0,0x00080001,0), + (35942,0,0,0,0,0,0x00080001,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (37604); +INSERT INTO `spell_proc_event` VALUES + (37604,0,0,0,0,0,0x00004000,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (24389); +INSERT INTO `spell_proc_event` VALUES + (24389,0x04,0,0,0,0,0x00020000,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (28780); +INSERT INTO `spell_proc_event` VALUES + (28780,0,0,0,0,0,0x08020000,0); + diff --git a/sql/updates/0.10/5030_mangos_item_template.sql b/sql/updates/0.10/5030_mangos_item_template.sql new file mode 100644 index 00000000000..883fa5d82bc --- /dev/null +++ b/sql/updates/0.10/5030_mangos_item_template.sql @@ -0,0 +1,5 @@ +ALTER TABLE `item_template` CHANGE `AllowableClass` `AllowableClass` mediumint(9) not null default '-1'; +ALTER TABLE `item_template` CHANGE `AllowableRace` `AllowableRace` mediumint(9) not null default '-1'; + +UPDATE `item_template` SET `AllowableClass` = -1 WHERE `AllowableClass` = 0; +UPDATE `item_template` SET `AllowableRace` = -1 WHERE `AllowableRace` = 0; diff --git a/sql/updates/0.10/5036_mangos_spell_affect.sql b/sql/updates/0.10/5036_mangos_spell_affect.sql new file mode 100644 index 00000000000..07c99926ea1 --- /dev/null +++ b/sql/updates/0.10/5036_mangos_spell_affect.sql @@ -0,0 +1,52 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (12945); +INSERT INTO `spell_affect` VALUES + (12945,0,0,0,0,0,0,0x0000000000001000,0), + (12945,1,0,0,0,0,0,0x0000000000001000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (29787,29790,29792); +INSERT INTO `spell_affect` VALUES + (29787,0,0,0,0,0,0,0x0000036C2A764EEF,0), + (29790,0,0,0,0,0,0,0x0000036C2A764EEF,0), + (29792,0,0,0,0,0,0,0x0000036C2A764EEF,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (21887); +INSERT INTO `spell_affect` VALUES + (21887,0,0,0,0,0,0,0x0000036C2A764EEF,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (16493,16494); +INSERT INTO `spell_affect` VALUES + (16493,0,0,0,0,0,0,0x0000014D2A600CEF,0), + (16494,0,0,0,0,0,0,0x0000014D2A600CEF,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (37517); +INSERT INTO `spell_affect` VALUES + (37517,0,0,0,0,0,0,0x0000014D2A600CEF,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (12866,12865,12864,12863,12325); +INSERT INTO `spell_affect` VALUES + (12866,0,0,0,0,0,0,0x0000000000000000,0), + (12865,0,0,0,0,0,0,0x0000000000000000,0), + (12864,0,0,0,0,0,0,0x0000000000000000,0), + (12863,0,0,0,0,0,0,0x0000000000000000,0), + (12325,0,0,0,0,0,0,0x0000000000000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (35446,35448,35449,35450,35451); +INSERT INTO `spell_affect` VALUES + (35446,0,0,0,0,0,0,0x0000000002000000,0), + (35446,1,0,0,0,0,0,0x0000000002000000,0), + (35448,0,0,0,0,0,0,0x0000000002000000,0), + (35448,1,0,0,0,0,0,0x0000000002000000,0), + (35449,0,0,0,0,0,0,0x0000000002000000,0), + (35449,1,0,0,0,0,0,0x0000000002000000,0), + (35450,0,0,0,0,0,0,0x0000000002000000,0), + (35450,1,0,0,0,0,0,0x0000000002000000,0), + (35451,0,0,0,0,0,0,0x0000000002000000,0), + (35451,1,0,0,0,0,0,0x0000000002000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (38407); +INSERT INTO `spell_affect` VALUES + (38407,0,0,0,0,0,0,0x0000000100000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (28842); +INSERT INTO `spell_affect` VALUES + (28842,0,0,0,0,0,0,0x0000000100004440,0); diff --git a/sql/updates/0.10/5039_mangos_spell_proc_event.sql b/sql/updates/0.10/5039_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..785d9deabdb --- /dev/null +++ b/sql/updates/0.10/5039_mangos_spell_proc_event.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (21890); +INSERT INTO `spell_proc_event` VALUES + (21890,0,0,0,4,0x0000036C2A764EEF,0x00004001,0); diff --git a/sql/updates/0.10/5064_mangos_spell_proc_event.sql b/sql/updates/0.10/5064_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..67e395a3e06 --- /dev/null +++ b/sql/updates/0.10/5064_mangos_spell_proc_event.sql @@ -0,0 +1,15 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (31233,31239,31240,31241,31242); +INSERT INTO `spell_proc_event` VALUES + (31233,0,0,0,8,0x00000009003E0000,0x00020000,0), + (31239,0,0,0,8,0x00000009003E0000,0x00020000,0), + (31240,0,0,0,8,0x00000009003E0000,0x00020000,0), + (31241,0,0,0,8,0x00000009003E0000,0x00020000,0), + (31242,0,0,0,8,0x00000009003E0000,0x00020000,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (37168); +INSERT INTO `spell_proc_event` VALUES + (37168,0,0,0,8,0x00000009003E0000,0x00020000,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (26107); +INSERT INTO `spell_proc_event` VALUES + (26107,0,0,0,7,0x0000008000800000,0xC4000000,0); diff --git a/sql/updates/0.10/5070_mangos_spell_proc_event.sql b/sql/updates/0.10/5070_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..312fdac44ed --- /dev/null +++ b/sql/updates/0.10/5070_mangos_spell_proc_event.sql @@ -0,0 +1,5 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (5301,13358,16092); +INSERT INTO `spell_proc_event` VALUES + ( 5301,0,0,0,0,0x0000000000000000,0x00000000,0), + (13358,0,0,0,0,0x0000000000000000,0x00000000,0), + (16092,0,0,0,0,0x0000000000000000,0x00000000,0); diff --git a/sql/updates/0.10/5072_mangos_spell_proc_event.sql b/sql/updates/0.10/5072_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..522c451bacf --- /dev/null +++ b/sql/updates/0.10/5072_mangos_spell_proc_event.sql @@ -0,0 +1,4 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (12328,18765); +INSERT INTO `spell_proc_event` VALUES + (12328,0,0,0,0,0x0000000000000000,0xC4000001,0), + (18765,0,0,0,0,0x0000000000000000,0xC4000001,0); diff --git a/sql/updates/0.10/5075_mangos_spell_proc_event.sql b/sql/updates/0.10/5075_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..680b08c016e --- /dev/null +++ b/sql/updates/0.10/5075_mangos_spell_proc_event.sql @@ -0,0 +1,34 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (13877,33735); +INSERT INTO `spell_proc_event` VALUES + (13877,0,0,0,0,0x0000000000000000,0xC4000001,0), + (33735,0,0,0,0,0x0000000000000000,0xC4000001,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (12966,12967,12968,12969,12970,16257,16277,16278,16279,16280,17687); +INSERT INTO `spell_proc_event` VALUES + (12966,0,0,0,0,0x0000000000000000,0xC4000001,0), + (12967,0,0,0,0,0x0000000000000000,0xC4000001,0), + (12968,0,0,0,0,0x0000000000000000,0xC4000001,0), + (12969,0,0,0,0,0x0000000000000000,0xC4000001,0), + (12970,0,0,0,0,0x0000000000000000,0xC4000001,0), + (16257,0,0,0,0,0x0000000000000000,0xC4000001,0), + (16277,0,0,0,0,0x0000000000000000,0xC4000001,0), + (16278,0,0,0,0,0x0000000000000000,0xC4000001,0), + (16279,0,0,0,0,0x0000000000000000,0xC4000001,0), + (16280,0,0,0,0,0x0000000000000000,0xC4000001,0), + (17687,0,0,0,0,0x0000000000000000,0xC4000001,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (40353); +INSERT INTO `spell_proc_event` VALUES + (40353,0,0,0,0,0x0000000000000000,0xC4000001,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (29448,35205); +INSERT INTO `spell_proc_event` VALUES + (29448,0,0,0,0,0x0000000000000000,0xC4000001,0), + (35205,0,0,0,0,0x0000000000000000,0xC4000001,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (1328); +INSERT INTO `spell_proc_event` VALUES + (1328,0,0,0,0,0x0000000000000000,0xC4000001,0); + + + diff --git a/sql/updates/0.10/5084_mangos_command.sql b/sql/updates/0.10/5084_mangos_command.sql new file mode 100644 index 00000000000..7c280620e84 --- /dev/null +++ b/sql/updates/0.10/5084_mangos_command.sql @@ -0,0 +1,8 @@ +DELETE FROM command WHERE name IN ('createguild','guild create','guild delete','guild invite','guild rank','guild uninvite'); + +INSERT INTO `command` VALUES +('guild create',2,'Syntax: .guild create $GuildLeaderName $GuildName\r\n\r\nCreate a guild named $GuildName with the player $GuildLeaderName as leader.'), +('guild delete',2,'Syntax: .guild delete $GuildName\r\n\r\nDelete guild $GuildName.'), +('guild invite',2,'Syntax: .guild invite $CharacterName $GuildName\r\n\r\nAdd $CharacterName into a guild $GuildName.'), +('guild rank',2,'Syntax: .guild rank $CharacterName #Rank\r\n\r\nSet for $CharacterName rank #Rank in a guild.'), +('guild uninvite',2,'Syntax: .guild uninvite $CharacterName\r\n\r\nRemove $CharacterName from a guild.'); diff --git a/sql/updates/0.10/5085_mangos_spell_affect.sql b/sql/updates/0.10/5085_mangos_spell_affect.sql new file mode 100644 index 00000000000..f81ddc515c1 --- /dev/null +++ b/sql/updates/0.10/5085_mangos_spell_affect.sql @@ -0,0 +1,7 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (16179,16214,16215,16216,16217); +INSERT INTO `spell_affect` VALUES +(16179,0,0,0,0,0,0,0x00000000000000C0,0), +(16214,0,0,0,0,0,0,0x00000000000000C0,0), +(16215,0,0,0,0,0,0,0x00000000000000C0,0), +(16216,0,0,0,0,0,0,0x00000000000000C0,0), +(16217,0,0,0,0,0,0,0x00000000000000C0,0); diff --git a/sql/updates/0.10/5087_mangos_spell_affect.sql b/sql/updates/0.10/5087_mangos_spell_affect.sql new file mode 100644 index 00000000000..c39869832f0 --- /dev/null +++ b/sql/updates/0.10/5087_mangos_spell_affect.sql @@ -0,0 +1,4 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (20175); +INSERT INTO `spell_affect` VALUES + (20175,0,0,0,0,0,0,0x0000000000000080,0), + (20175,1,0,0,0,0,0,0x0000000000000010,0); diff --git a/sql/updates/0.10/5088_mangos_spell_proc_event.sql b/sql/updates/0.10/5088_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..b5c03ceb046 --- /dev/null +++ b/sql/updates/0.10/5088_mangos_spell_proc_event.sql @@ -0,0 +1,5 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (17106,17107,17108); +INSERT INTO `spell_proc_event` VALUES + (17106,0,0,0,7,0x0000000000080000,0x00004000,0), + (17107,0,0,0,7,0x0000000000080000,0x00004000,0), + (17108,0,0,0,7,0x0000000000080000,0x00004000,0); diff --git a/sql/updates/0.10/5092_mangos_item_template.sql b/sql/updates/0.10/5092_mangos_item_template.sql new file mode 100644 index 00000000000..91bf982dc47 --- /dev/null +++ b/sql/updates/0.10/5092_mangos_item_template.sql @@ -0,0 +1,2 @@ +ALTER TABLE `item_template` + ADD `Duration` int(11) NOT NULL DEFAULT '0' COMMENT 'Duration in seconds. Negative value means realtime, postive value ingame time'; diff --git a/sql/updates/0.10/5097_mangos_skill_extra_item_template.sql b/sql/updates/0.10/5097_mangos_skill_extra_item_template.sql new file mode 100644 index 00000000000..ef417ff60ba --- /dev/null +++ b/sql/updates/0.10/5097_mangos_skill_extra_item_template.sql @@ -0,0 +1,9 @@ +DROP TABLE IF EXISTS `skill_extra_item_template`; +CREATE TABLE `skill_extra_item_template` ( + `spellId` int(11) unsigned NOT NULL default '0' COMMENT 'SpellId of the item creation spell', + `requiredSpecialization` int(11) unsigned NOT NULL default '0' COMMENT 'Specialization spell id', + `additionalCreateChance` float NOT NULL default '0' COMMENT 'chance to create add', + `additionalMaxNum` int(11) unsigned NOT NULL default '0' COMMENT 'max num of adds', + + PRIMARY KEY (`spellId`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Skill Specialization System'; diff --git a/sql/updates/0.10/5106_mangos_spell_chain.sql b/sql/updates/0.10/5106_mangos_spell_chain.sql new file mode 100644 index 00000000000..2ce95bc05c4 --- /dev/null +++ b/sql/updates/0.10/5106_mangos_spell_chain.sql @@ -0,0 +1,15 @@ +DELETE FROM `spell_chain` WHERE `spell_id` IN (26790,27028,28029,28596,28695,28897,29354,29844,30350,32549,32678,33095,33359); +INSERT INTO `spell_chain` (`spell_id`, `prev_spell`, `first_spell`, `rank`) VALUES +(26790,12180,3908,5), +(27028,10846,3273,5), +(28029,13920,7411,5), +(28596,11611,2259,5), +(28695,11993,2366,5), +(28897,28895,25229,5), +(29354,10248,2575,5), +(29844,9785,2018,5), +(30350,12656,4036,5), +(32549,10662,2108,5), +(32678,10768,8613,5), +(33095,18248,7620,5), +(33359,18260,2550,5); diff --git a/sql/updates/0.10/5108_characters.sql b/sql/updates/0.10/5108_characters.sql new file mode 100644 index 00000000000..e8c8cae8279 --- /dev/null +++ b/sql/updates/0.10/5108_characters.sql @@ -0,0 +1,58 @@ +ALTER TABLE `guild` ADD COLUMN `BankMoney` bigint(20) NOT NULL DEFAULT 0 AFTER `createdate`; +ALTER TABLE `guild_rank` ADD COLUMN `BankMoneyPerDay` int(11) unsigned NOT NULL default '0' AFTER `rights`; +ALTER TABLE `guild_member` ADD COLUMN `BankResetTimeMoney` int(11) unsigned NOT NULL DEFAULT '0' AFTER `OFFnote`; +ALTER TABLE `guild_member` ADD COLUMN `BankRemMoney` int(11) unsigned NOT NULL DEFAULT '0' AFTER `BankResetTimeMoney`; +ALTER TABLE `guild_member` ADD COLUMN `BankResetTimeTab0` int(11) unsigned NOT NULL DEFAULT '0' AFTER `BankRemMoney`; +ALTER TABLE `guild_member` ADD COLUMN `BankRemSlotsTab0` int(11) unsigned NOT NULL DEFAULT '0' AFTER `BankResetTimeTab0`; +ALTER TABLE `guild_member` ADD COLUMN `BankResetTimeTab1` int(11) unsigned NOT NULL DEFAULT '0' AFTER `BankRemSlotsTab0`; +ALTER TABLE `guild_member` ADD COLUMN `BankRemSlotsTab1` int(11) unsigned NOT NULL DEFAULT '0' AFTER `BankResetTimeTab1`; +ALTER TABLE `guild_member` ADD COLUMN `BankResetTimeTab2` int(11) unsigned NOT NULL DEFAULT '0' AFTER `BankRemSlotsTab1`; +ALTER TABLE `guild_member` ADD COLUMN `BankRemSlotsTab2` int(11) unsigned NOT NULL DEFAULT '0' AFTER `BankResetTimeTab2`; +ALTER TABLE `guild_member` ADD COLUMN `BankResetTimeTab3` int(11) unsigned NOT NULL DEFAULT '0' AFTER `BankRemSlotsTab2`; +ALTER TABLE `guild_member` ADD COLUMN `BankRemSlotsTab3` int(11) unsigned NOT NULL DEFAULT '0' AFTER `BankResetTimeTab3`; +ALTER TABLE `guild_member` ADD COLUMN `BankResetTimeTab4` int(11) unsigned NOT NULL DEFAULT '0' AFTER `BankRemSlotsTab3`; +ALTER TABLE `guild_member` ADD COLUMN `BankRemSlotsTab4` int(11) unsigned NOT NULL DEFAULT '0' AFTER `BankResetTimeTab4`; +ALTER TABLE `guild_member` ADD COLUMN `BankResetTimeTab5` int(11) unsigned NOT NULL DEFAULT '0' AFTER `BankRemSlotsTab4`; +ALTER TABLE `guild_member` ADD COLUMN `BankRemSlotsTab5` int(11) unsigned NOT NULL DEFAULT '0' AFTER `BankResetTimeTab5`; + +DROP TABLE IF EXISTS `guild_bank_item`; +CREATE TABLE `guild_bank_item` ( + `guildid` int(11) unsigned NOT NULL default '0', + `TabId` tinyint(1) unsigned NOT NULL default '0', + `SlotId` tinyint(3) unsigned NOT NULL default '0', + `item_guid` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`guildid`,`tabid`,`slotid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `guild_bank_tab`; +CREATE TABLE `guild_bank_tab` ( + `guildid` int(11) unsigned NOT NULL default '0', + `TabId` tinyint(1) unsigned NOT NULL default '0', + `TabName` varchar(100) NOT NULL default '', + `TabIcon` varchar(100) NOT NULL default '', + PRIMARY KEY (`guildid`,`TabId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `guild_bank_right`; +CREATE TABLE `guild_bank_right` ( + `guildid` int(11) unsigned NOT NULL default '0', + `TabId` tinyint(1) unsigned NOT NULL default '0', + `rid` int(11) unsigned NOT NULL default '0', + `Right` tinyint(3) unsigned NOT NULL default '0', + `SlotPerDay` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`guildid`,`TabId`,`rid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `guild_bank_eventlog`; +CREATE TABLE `guild_bank_eventlog` ( + `guildid` int(11) unsigned NOT NULL default '0', + `LogGuid` int(11) unsigned NOT NULL default '0', + `LogEntry` tinyint(1) unsigned NOT NULL default '0', + `TabId` tinyint(1) unsigned NOT NULL default '0', + `PlayerGuid` int(11) unsigned NOT NULL default '0', + `ItemOrMoney` int(11) unsigned NOT NULL default '0', + `ItemStackCount` tinyint(3) unsigned NOT NULL default '0', + `DestTabId` tinyint(1) unsigned NOT NULL default '0', + `TimeStamp` bigint(20) unsigned NOT NULL default '0', + PRIMARY KEY (`guildid`,`LogGuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/sql/updates/0.10/5119_mangos_quest_template.sql b/sql/updates/0.10/5119_mangos_quest_template.sql new file mode 100644 index 00000000000..5769f7719b1 --- /dev/null +++ b/sql/updates/0.10/5119_mangos_quest_template.sql @@ -0,0 +1,3 @@ +ALTER TABLE `quest_template` + ADD `RepObjectiveFaction` int(10) unsigned NOT NULL default '0' AFTER `RequiredSkillValue`, + ADD `RepObjectiveValue` int(10) NOT NULL default '0' AFTER `RepObjectiveFaction`; \ No newline at end of file diff --git a/sql/updates/0.10/5120_mangos_spell_chain.sql b/sql/updates/0.10/5120_mangos_spell_chain.sql new file mode 100644 index 00000000000..c0bef0f2f1f --- /dev/null +++ b/sql/updates/0.10/5120_mangos_spell_chain.sql @@ -0,0 +1,15 @@ +DELETE FROM `spell_chain` WHERE `spell_id` IN (9787,9788,17039,17040,17041,10656,10658,10660,20219,20222,26797,26798,26801); +INSERT INTO `spell_chain` (`spell_id`, `prev_spell`, `first_spell`, `rank`) VALUES +(9787,29844,2018,6), +(9788,29844,2018,6), +(17039,9787,2018,7), +(17040,9787,2018,7), +(17041,9787,2018,7), +(10656,32549,2108,6), +(10658,32549,2108,6), +(10660,32549,2108,6), +(20219,30350,4036,6), +(20222,30350,4036,6), +(26797,26790,3908,6), +(26798,26790,3908,6), +(26801,26790,3908,6); diff --git a/sql/updates/0.10/5121_mangos_spell_affect.sql b/sql/updates/0.10/5121_mangos_spell_affect.sql new file mode 100644 index 00000000000..7f79fe19968 --- /dev/null +++ b/sql/updates/0.10/5121_mangos_spell_affect.sql @@ -0,0 +1,33 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (11071,12496); +INSERT INTO `spell_affect` VALUES + (11071,0,0,0,0,0,0,0x0000000000100000,0), + (12496,0,0,0,0,0,0,0x0000000000100000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (16578,16579,16580,16581,16582); +INSERT INTO `spell_affect` VALUES + (16578,0,0,0,0,0,0,0x0000000000000003,0), + (16579,0,0,0,0,0,0,0x0000000000000003,0), + (16580,0,0,0,0,0,0,0x0000000000000003,0), + (16581,0,0,0,0,0,0,0x0000000000000003,0), + (16582,0,0,0,0,0,0,0x0000000000000003,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (16194,16218,16219,16220,16221); +INSERT INTO `spell_affect` VALUES + (16194,0,0,0,0,0,0,0x00000000000001C3,0), + (16218,0,0,0,0,0,0,0x00000000000001C3,0), + (16219,0,0,0,0,0,0,0x00000000000001C3,0), + (16220,0,0,0,0,0,0,0x00000000000001C3,0), + (16221,0,0,0,0,0,0,0x00000000000001C3,0); + +DELETE FROM spell_affect WHERE entry IN (16934,16935,16936,16937,16938); +INSERT INTO `spell_affect` VALUES + (16934,0,0,0,0,0,0,0x0010004000000800,0), + (16934,1,0,0,0,0,0,0x0000040000001000,0), + (16935,0,0,0,0,0,0,0x0010004000000800,0), + (16935,1,0,0,0,0,0,0x0000040000001000,0), + (16936,0,0,0,0,0,0,0x0010004000000800,0), + (16936,1,0,0,0,0,0,0x0000040000001000,0), + (16937,0,0,0,0,0,0,0x0010004000000800,0), + (16937,1,0,0,0,0,0,0x0000040000001000,0), + (16938,0,0,0,0,0,0,0x0010004000000800,0), + (16938,1,0,0,0,0,0,0x0000040000001000,0); diff --git a/sql/updates/0.10/5123_mangos_spell_proc_event.sql b/sql/updates/0.10/5123_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..df839fcd158 --- /dev/null +++ b/sql/updates/0.10/5123_mangos_spell_proc_event.sql @@ -0,0 +1,27 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (34860,34859,34753); +INSERT INTO `spell_proc_event` VALUES + (34860,0,0,0,6,0x0000000000001800,0x08000000,0), + (34859,0,0,0,6,0x0000000000001800,0x08000000,0), + (34753,0,0,0,6,0x0000000000001800,0x08000000,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (45244,45243,45234); +INSERT INTO `spell_proc_event` VALUES + (45244,0,0,0,0,0x0000000000000000,0x00842000,0), + (45243,0,0,0,0,0x0000000000000000,0x00842000,0), + (45234,0,0,0,0,0x0000000000000000,0x00842000,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (35083); +INSERT INTO `spell_proc_event` VALUES + (35083,0,0,0,0,0x0000000000000000,0x00020000,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (35086); +INSERT INTO `spell_proc_event` VALUES + (35086,0,0,0,0,0x0000000000000000,0x08020000,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (35080); +INSERT INTO `spell_proc_event` VALUES + (35080,0,0,0,0,0x0000000000000000,0x00000001,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (35077); +INSERT INTO `spell_proc_event` VALUES + (35077,0,0,0,0,0x0000000000000000,0x00008000,0); diff --git a/sql/updates/0.10/5128_mangos_spell_proc_event.sql b/sql/updates/0.10/5128_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..fa48a51d01e --- /dev/null +++ b/sql/updates/0.10/5128_mangos_spell_proc_event.sql @@ -0,0 +1,4 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (24949,34082); +INSERT INTO `spell_proc_event` VALUES + (24949,0,0,0,0,0x0000000000000000,0x00000000,0), + (34082,0,0,0,0,0x0000000000000000,0x00000000,0); diff --git a/sql/updates/0.10/5130_mangos_spell_proc_event.sql b/sql/updates/0.10/5130_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..73c1bc5e256 --- /dev/null +++ b/sql/updates/0.10/5130_mangos_spell_proc_event.sql @@ -0,0 +1,53 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (21063,27539,28764,33493,38196); +INSERT INTO `spell_proc_event` VALUES + (21063,0,0,0,0,0x0000000000000000,0x00008000,0), + (27539,0,0,0,0,0x0000000000000000,0x00100000,0), + (28764,0,0,0,0,0x0000000000000000,0x00100000,0), + (33493,0,0,0,0,0x0000000000000000,0x00000002,0), + (38196,0,0,0,0,0x0000000000000000,0x00000001,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (29441,29444,29445,29446,29447); +INSERT INTO `spell_proc_event` VALUES + (29441,0,0,0,0,0x0000000000000000,0x01000000,0), + (29444,0,0,0,0,0x0000000000000000,0x01000000,0), + (29445,0,0,0,0,0x0000000000000000,0x01000000,0), + (29446,0,0,0,0,0x0000000000000000,0x01000000,0), + (29447,0,0,0,0,0x0000000000000000,0x01000000,0); + + +DELETE FROM `spell_proc_event` WHERE `entry` IN (27243); +INSERT INTO `spell_proc_event` VALUES + (27243,0,0,0,0,0x0000000000000000,0x00008000,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (40438); +INSERT INTO `spell_proc_event` VALUES + (40438,0,0,0,6,0x0000000000008010,0x08020000,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (26169); +INSERT INTO `spell_proc_event` VALUES + (26169,0,0,0,0,0x0000000000000000,0x08000000,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (40442); +INSERT INTO `spell_proc_event` VALUES + (40442,0,0,0,7,0x0000044000000014,0x00004000,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (28719); +INSERT INTO `spell_proc_event` VALUES + (28719,0,0,0,7,0x0000000000000020,0x10000000,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (28847); +INSERT INTO `spell_proc_event` VALUES + (28847,0,0,0,7,0x0000000000000020,0x00004000,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (37288,37295); +INSERT INTO `spell_proc_event` VALUES + (37288,0,0,0,0,0x0000000000000000,0x08000000,0), + (37295,0,0,0,0,0x0000000000000000,0x00020000,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (31892); +INSERT INTO `spell_proc_event` VALUES + (31892,0,0,0,0,0x0000000000000000,0x00000001,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (40470); +INSERT INTO `spell_proc_event` VALUES + (40470,0,0,0,10,0x0000000000806000,0x00004000,0); diff --git a/sql/updates/0.10/5146_mangos_spell_proc_event.sql b/sql/updates/0.10/5146_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..638d22c710e --- /dev/null +++ b/sql/updates/0.10/5146_mangos_spell_proc_event.sql @@ -0,0 +1,5 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (37169,43745); +INSERT INTO `spell_proc_event` VALUES + (37169,0,0,0,8,0x0000000000020000,0x00000000,0), + (43745,0,0,0,10,0x0000020000000000,0x00020000,0); + diff --git a/sql/updates/0.10/5147_mangos_spell_learn_spell.sql b/sql/updates/0.10/5147_mangos_spell_learn_spell.sql new file mode 100644 index 00000000000..f8f35a9917a --- /dev/null +++ b/sql/updates/0.10/5147_mangos_spell_learn_spell.sql @@ -0,0 +1,3 @@ +INSERT INTO `spell_learn_spell` ( `entry` , `SpellID` , `IfNoSpell` ) VALUES +('17002', '24867', '0'), +('24866', '24864', '0'); diff --git a/sql/updates/0.10/5156_mangos_spell_affect.sql b/sql/updates/0.10/5156_mangos_spell_affect.sql new file mode 100644 index 00000000000..f4560987c42 --- /dev/null +++ b/sql/updates/0.10/5156_mangos_spell_affect.sql @@ -0,0 +1,85 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (43339); +INSERT INTO `spell_affect` VALUES + (43339,0,0,0,0,0,0,0x0000000090100000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (16246); +INSERT INTO `spell_affect` VALUES + (16246,0,0,0,0,0,0,0x0000000090100003,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (38434); +INSERT INTO `spell_affect` VALUES + (38434,0,0,0,0,0,0,0x0000000000000100,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (16089); +INSERT INTO `spell_affect` VALUES + (16089,0,0,0,0,0,0,0x00000004D33005C7,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (16166); +INSERT INTO `spell_affect` VALUES + (16166,0,0,0,0,0,0,0x00000000901001C3,0), + (16166,1,0,0,0,0,0,0x00000000901001C3,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (29063); +INSERT INTO `spell_affect` VALUES + (29063,0,0,0,0,0,0,0x00000000000009C3,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (37241); +INSERT INTO `spell_affect` VALUES + (37241,0,0,0,0,0,0,0x0000020000000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (38435); +INSERT INTO `spell_affect` VALUES + (38435,0,0,0,0,0,0,0x0000000000000080,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (38436); +INSERT INTO `spell_affect` VALUES + (38436,0,0,0,0,0,0,0x0000000000000001,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (34318,37209); +INSERT INTO `spell_affect` VALUES + (34318,0,0,0,0,0,0,0x0000002000000000,0), + (37209,0,0,0,0,0,0,0x0000002000000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (21895); +INSERT INTO `spell_affect` VALUES + (21895,0,0,0,0,0,0,0x000000000403E000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (39805); +INSERT INTO `spell_affect` VALUES + (39805,0,0,0,0,0,0,0x0000000000000003,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (30812,30813,30814); +INSERT INTO `spell_affect` VALUES + (30812,0,0,0,0,0,0,0x00000C78B018141B,0), + (30813,0,0,0,0,0,0,0x00000C78B018141B,0), + (30814,0,0,0,0,0,0,0x00000C78B018141B,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (38501); +INSERT INTO `spell_affect` VALUES + (38501,0,0,0,0,0,0,0x0000000000000080,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (36591); +INSERT INTO `spell_affect` VALUES + (36591,1,0,0,0,0,0,0x00000410901005C3,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (28818); +INSERT INTO `spell_affect` VALUES + (28818,0,0,0,0,0,0,0x0000000020081018,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (16173,16222,16223,16224,16225); +INSERT INTO `spell_affect` VALUES + (16173,0,0,0,0,0,0,0x0000000020081018,0), + (16222,0,0,0,0,0,0,0x0000000020081018,0), + (16223,0,0,0,0,0,0,0x0000000020081018,0), + (16224,0,0,0,0,0,0,0x0000000020081018,0), + (16225,0,0,0,0,0,0,0x0000000020081018,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (16189); +INSERT INTO `spell_affect` VALUES + (16189,0,0,0,0,0,0,0x000001000403E000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (39950); +INSERT INTO `spell_affect` VALUES + (39950,0,0,0,0,0,0,0x0000000000000040,0); + + diff --git a/sql/updates/0.10/5156_mangos_spell_proc_event.sql b/sql/updates/0.10/5156_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..0941e54642b --- /dev/null +++ b/sql/updates/0.10/5156_mangos_spell_proc_event.sql @@ -0,0 +1,9 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (33746,40463); +INSERT INTO `spell_proc_event` VALUES + (33746,0,0,0,0,0x0000000000000000,0x00000004,0), + (40463,0,0,0,11,0x0000001000000081,0x00004001,0); + + +DELETE FROM `spell_proc_event` WHERE `entry` IN (43338); +INSERT INTO `spell_proc_event` VALUES + (43338,0,0,0,0,0x0000000000000000,0x00001000,0); diff --git a/sql/updates/0.10/5158_mangos_spell_affect.sql b/sql/updates/0.10/5158_mangos_spell_affect.sql new file mode 100644 index 00000000000..94867e6a47b --- /dev/null +++ b/sql/updates/0.10/5158_mangos_spell_affect.sql @@ -0,0 +1 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (36591); diff --git a/sql/updates/0.10/5159_characters_guild_bank_eventlog.sql b/sql/updates/0.10/5159_characters_guild_bank_eventlog.sql new file mode 100644 index 00000000000..e098bd9d9b5 --- /dev/null +++ b/sql/updates/0.10/5159_characters_guild_bank_eventlog.sql @@ -0,0 +1,3 @@ +ALTER TABLE `guild_bank_eventlog` + ADD KEY `guildid_key` (`guildid`); + diff --git a/sql/updates/0.10/5159_characters_guild_bank_item.sql b/sql/updates/0.10/5159_characters_guild_bank_item.sql new file mode 100644 index 00000000000..364c6ea2de5 --- /dev/null +++ b/sql/updates/0.10/5159_characters_guild_bank_item.sql @@ -0,0 +1,9 @@ +ALTER TABLE `guild_bank_item` + ADD COLUMN `item_entry` int(11) unsigned NOT NULL default '0', + ADD KEY `item_guid_key` (`item_guid`), + ADD KEY `guildid_key` (`guildid`); + +UPDATE `guild_bank_item` ,`item_instance` + SET `guild_bank_item`.`item_entry` = SUBSTRING_INDEX(SUBSTRING_INDEX(`item_instance`.`data`, ' ', 4), ' ', -1) + WHERE `guild_bank_item`.`item_guid` = `item_instance`.`guid`; + diff --git a/sql/updates/0.10/5159_characters_guild_bank_right.sql b/sql/updates/0.10/5159_characters_guild_bank_right.sql new file mode 100644 index 00000000000..6d64b15996f --- /dev/null +++ b/sql/updates/0.10/5159_characters_guild_bank_right.sql @@ -0,0 +1,3 @@ +ALTER TABLE `guild_bank_right` + ADD KEY `guildid_key` (`guildid`); + diff --git a/sql/updates/0.10/5159_characters_guild_bank_tab.sql b/sql/updates/0.10/5159_characters_guild_bank_tab.sql new file mode 100644 index 00000000000..6ab0de6f4b2 --- /dev/null +++ b/sql/updates/0.10/5159_characters_guild_bank_tab.sql @@ -0,0 +1,3 @@ +ALTER TABLE `guild_bank_tab` + ADD KEY `guildid_key` (`guildid`); + diff --git a/sql/updates/0.10/5159_characters_guild_memeber.sql b/sql/updates/0.10/5159_characters_guild_memeber.sql new file mode 100644 index 00000000000..396f2417d73 --- /dev/null +++ b/sql/updates/0.10/5159_characters_guild_memeber.sql @@ -0,0 +1,5 @@ +ALTER TABLE `guild_member` + ADD KEY `guildid_key` (`guildid`), + ADD KEY `guildid_rank_key` (`guildid`,`rank`), + ADD KEY `guid_key` (`guid`); + diff --git a/sql/updates/0.10/5160_mangos_command.sql b/sql/updates/0.10/5160_mangos_command.sql new file mode 100644 index 00000000000..fb10c4b8012 --- /dev/null +++ b/sql/updates/0.10/5160_mangos_command.sql @@ -0,0 +1,4 @@ +DELETE FROM command WHERE name IN ('info'); + +INSERT INTO `command` VALUES +('info',0,'Syntax: .info\r\n\r\nDisplay server version and the number of connected players.'); diff --git a/sql/updates/0.10/5163_mangos_spell_affect.sql b/sql/updates/0.10/5163_mangos_spell_affect.sql new file mode 100644 index 00000000000..69676ce313f --- /dev/null +++ b/sql/updates/0.10/5163_mangos_spell_affect.sql @@ -0,0 +1,8 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (16113,16114,16115,16116,16040,22804); +INSERT INTO `spell_affect` VALUES + (16113,0,0,0,0,0,0,0x0000000090100000,0), + (16114,0,0,0,0,0,0,0x0000000090100000,0), + (16115,0,0,0,0,0,0,0x0000000090100000,0), + (16116,0,0,0,0,0,0,0x0000000090100000,0), + (16040,0,0,0,0,0,0,0x0000000090100000,0), + (22804,0,0,0,0,0,0,0x0000000090100000,0); diff --git a/sql/updates/0.10/5163_mangos_spell_proc_event.sql b/sql/updates/0.10/5163_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..d85b344460a --- /dev/null +++ b/sql/updates/0.10/5163_mangos_spell_proc_event.sql @@ -0,0 +1,4 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (26119,43748); +INSERT INTO `spell_proc_event` VALUES + (26119,0,0,0,11,0x0000000090100003,0x00004000,0), + (43748,0,0,0,11,0x0000000090100000,0x00004000,0); diff --git a/sql/updates/0.10/5164_mangos_creature_movement.sql b/sql/updates/0.10/5164_mangos_creature_movement.sql new file mode 100644 index 00000000000..082845ffe11 --- /dev/null +++ b/sql/updates/0.10/5164_mangos_creature_movement.sql @@ -0,0 +1,5 @@ +ALTER TABLE `creature_movement` CHANGE COLUMN `text1` `text1` text; +ALTER TABLE `creature_movement` CHANGE COLUMN `text2` `text2` text; +ALTER TABLE `creature_movement` CHANGE COLUMN `text3` `text3` text; +ALTER TABLE `creature_movement` CHANGE COLUMN `text4` `text4` text; +ALTER TABLE `creature_movement` CHANGE COLUMN `text5` `text5` text; diff --git a/sql/updates/0.10/5165_mangos_mangos_string.sql b/sql/updates/0.10/5165_mangos_mangos_string.sql new file mode 100644 index 00000000000..1722148b4de --- /dev/null +++ b/sql/updates/0.10/5165_mangos_mangos_string.sql @@ -0,0 +1,468 @@ +-- +-- Table structure for table `mangos_string` +-- + +DROP TABLE IF EXISTS `mangos_string`; +CREATE TABLE `mangos_string` ( + `entry` int(11) unsigned NOT NULL default '0', + `content_default` text, + `content_loc1` text, + `content_loc2` text, + `content_loc3` text, + `content_loc4` text, + `content_loc5` text, + `content_loc6` text, + `content_loc7` text, + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `mangos_string` +-- + +LOCK TABLES `mangos_string` WRITE; +/*!40000 ALTER TABLE `mangos_string` DISABLE KEYS */; +INSERT INTO `mangos_string` VALUES +(1,'You should select a character or a creature.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(2,'You should select a creature.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(5,'There is no help for that command',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(6,'There is no such command',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(7,'There is no such subcommand',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(8,'Command %s have subcommands:%s',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(9,'Commands available to you:',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(10,'Incorrect syntax.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(11,'Your account level is: %i',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(12,'Number of users connected: %u (max since last restart: %u)',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(13,'Server uptime: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(14,'Player saved.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(15,'All players saved.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(16,'There are the following active GMs on this server:',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(17,'There are no GMs currently logged in on this server.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(18,'Cannot do that while flying.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(19,'Cannot do that in Battlegrounds.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(20,'Target is flying you can\'t do that.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(21,'%s is flying command failed.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(22,'You are not mounted so you can\'t dismount.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(23,'Cannot do that while fighting.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(24,'You used it recently.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(25,'Your password can\'t be longer than 16 characters (client limit), password not changed!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(26,'The password was changed',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(27,'The new passwords do not match or the old password is wrong',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(28,'Your account is now locked.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(29,'Your account is now unlocked.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(30,', rank ',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(31,' [known]',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(3,'|cffff0000[System Message]:|r',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(4,'|cffff0000[Event Message]: %s|r',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(32,' [learn]',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(33,' [passive]',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(34,' [talent]',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(35,' [active]',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(36,' [complete]',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(37,' (offline)',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(38,'on',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(39,'off',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(40,'You are: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(41,'visible',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(42,'invisible',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(43,'done',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(44,'You',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(45,' ',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(46,'',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(47,'',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(48,'UNKNOWN',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(49,'You must be at least level %u to enter.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(50,'You must be at least level %u and have item %s to enter.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(51,'Hello! Ready for some training?',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(100,'Global notify: ',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(101,'Map: %u (%s) Zone: %u (%s) Area: %u (%s)\\nX: %f Y: %f Z: %f Orientation: %f\\ngrid[%u,%u]cell[%u,%u] InstanceID: %u\\n ZoneX: %f ZoneY: %f\\nGroundZ: %f FloorZ: %f Have height data (Map: %u VMap: %u)',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(102,'%s is already being teleported.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(103,'You can summon a player to your instance only if he is in your party with you as leader.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(104,'You cannot go to the player\'s instance because you are in a party now.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(105,'You can go to the player\'s instance while not being in his party only if your GM mode is on.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(106,'You can not go to player %s from instance to instance.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(107,'You can not summon player %s from instance to instance.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(108,'You are summoning %s%s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(109,'You are being summoned by %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(110,'You are teleporting %s%s to %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(111,'You are being teleported by %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(112,'Player (%s) does not exist.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(113,'Appearing at %s\'s location.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(114,'%s is appearing to your location.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(115,'Incorrect values.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(116,'No character selected.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(117,'%s is not in a group.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(118,'You changed HP of %s to %i/%i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(119,'%s changed your HP to %i/%i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(120,'You changed MANA of %s to %i/%i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(121,'%s changed your MANA to %i/%i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(122,'You changed ENERGY of %s to %i/%i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(123,'%s changed your ENERGY to %i/%i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(124,'Current energy: %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(125,'You changed rage of %s to %i/%i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(126,'%s changed your rage to %i/%i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(127,'You changed level of %s to %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(128,'GUID %i, faction is %i, flags is %i, npcflag is %i, DY flag is %i',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(129,'Wrong faction: %u (not found in factiontemplate.dbc).',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(130,'You changed GUID=%i \'s Faction to %i, flags to %i, npcflag to %i, dyflag to %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(131,'You changed the spellflatid=%i, val= %i, mark =%i to %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(132,'%s changed your spellflatid=%i, val= %i, mark =%i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(133,'%s has access to all taxi nodes now (until logout).',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(134,'%s has no more access to all taxi nodes now (only visited accessible).',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(135,'%s has given you access to all taxi nodes (until logout).',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(136,'%s has removed access to all taxi nodes (only visited still accessible).',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(137,'You set all speeds to %2.2f from normal of %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(138,'%s set all your speeds to %2.2f from normal.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(139,'You set the speed to %2.2f from normal of %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(140,'%s set your speed to %2.2f from normal.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(141,'You set the swim speed to %2.2f from normal of %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(142,'%s set your swim speed to %2.2f from normal.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(143,'You set the backwards run speed to %2.2f from normal of %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(144,'%s set your backwards run speed to %2.2f from normal.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(145,'You set the fly speed to %2.2f from normal of %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(146,'%s set your fly speed to %2.2f from normal.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(147,'You set the size %2.2f of %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(148,'%s set your size to %2.2f.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(149,'There is no such mount.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(150,'You give a mount to %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(151,'%s gave you a mount.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(152,'USER1: %i, ADD: %i, DIF: %i\\n',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(153,'You take all copper of %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(154,'%s took you all of your copper.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(155,'You take %i copper from %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(156,'%s took %i copper from you.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(157,'You give %i copper to %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(158,'%s gave you %i copper.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(159,'You hear sound %u.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(160,'USER2: %i, ADD: %i, RESULT: %i\\n',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(161,'Removed bit %i in field %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(162,'Set bit %i in field %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(163,'Teleport location table is empty!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(164,'Teleport location not found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(165,'Requires search parameter.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(166,'There are no teleport locations matching your request.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(167,'No locations found.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(168,'Locations found are:\\n',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(169,'Mail sent to %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(200,'No selection.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(201,'Object GUID is: lowpart %u highpart %X',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(202,'The name was too long by %i characters.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(203,'Error, name can only contain characters A-Z and a-z.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(204,'The subname was too long by %i characters.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(205,'Not yet implemented',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(206,'Item \'%i\' \'%s\' added to list with maxcount \'%i\' and incrtime \'%i\'',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(207,'Item \'%i\' not found in database.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(208,'Item \'%i\' \'%s\' deleted from vendor list',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(209,'Item \'%i\' not found in vendor list.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(210,'Item \'%i\' already in vendor list.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(211,'Spells of %s reset.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(212,'Spells of %s will reset at next login.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(213,'Talents of %s reset.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(214,'Talents of %s will reset at next login.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(215,'Your spells have been reset.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(216,'Your talents have been reset.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(217,'Unknown case \'%s\' for .resetall command. Type full correct case name.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(218,'Spells will reset for all players at login. Strongly recommend re-login!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(219,'Talents will reset for all players at login. Strongly recommend re-login!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(220,'Creature (GUID: %u) No waypoint found.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(221,'Creature (GUID: %u) Last waypoint not found.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(222,'Creature (GUID: %u) No waypoint found - used \'wpguid\'. Now trying to find it by its position...',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(223,'Creature (GUID: %u) No waypoints found - This is a MaNGOS db problem (single float).',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(224,'Selected creature is ignored - provided GUID is used',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(225,'Creature (GUID: %u) not found',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(226,'You must select a visual waypoint.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(227,'No visual waypoints found',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(228,'Could not create visual waypoint with creatureID: %d',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(229,'All visual waypoints removed',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(230,'Could not create waypoint-creature with ID: %d',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(231,'No GUID provided.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(232,'No waypoint number provided.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(233,'Argument required for \'%s\'.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(234,'Waypoint %i added to GUID: %d',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(235,'Waypoint %d added.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(236,'Waypoint changed.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(237,'Waypoint %s modified.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(238,'WP export successfull.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(239,'No waypoints found inside the database.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(240,'File imported.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(241,'Waypoint removed.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(242,'Warning: Could not delete WP from the world with ID: %d',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(243,'This happens if the waypoint is too far away from your char.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(244,'The WP is deleted from the database, but not from the world here.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(245,'They will disappear after a server restart.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(246,'Waypoint %d: Info for creature: %s, GUID: %d',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(247,'Waittime: %d',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(248,'Model %d: %d',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(249,'Emote: %d',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(250,'Spell: %d',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(251,'Text %d: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(252,'AIScript: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(253,'Forced rename for player %s will be requested at next login.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(254,'Forced rename for player %s (GUID #%u) will be requested at next login.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(255,'Waypoint-Creature (GUID: %u) Not found',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(256,'Could not find NPC...',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(257,'Creature movement type set to \'%s\', waypoints removed (if any).',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(258,'Creature movement type set to \'%s\', waypoints were not removed.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(259,'Incorrect value, use on or off',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(260,'Value saved.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(261,'Value saved, you may need to rejoin or clean your client cache.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(262,'Areatrigger ID %u not found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(263,'Target map or coordinates is invalid (X: %f Y: %f MapId: %u)',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(264,'Zone coordinates is invalid (X: %f Y: %f AreaId: %u)',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(265,'Zone %u (%s) is part of instanceable map %u (%s)',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(266,'Nothing found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(267,'Object not found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(268,'Creature not found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(269,'Warning: Mob found more than once - you will be teleported to the first one found in DB.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(270,'Creature Removed',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(271,'Creature moved.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(272,'Creature (GUID:%u) must be on the same map as player!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(273,'Game Object (GUID: %u) not found',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(274,'Game Object (GUID: %u) has references in not found creature %u GO list, can\'t be deleted.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(275,'Game Object (GUID: %u) removed',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(276,'Game Object (GUID: %u) turned',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(277,'Game Object (GUID: %u) moved',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(278,'You must select a vendor',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(279,'You must send id for item',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(280,'Vendor has too many items (max 128)',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(281,'You can\'t kick self, logout instead',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(282,'Player %s kicked.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(283,'Player %s not found.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(284,'Accepting Whisper: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(285,'Accepting Whisper: ON',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(286,'Accepting Whisper: OFF',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(287,'Creature (GUID: %u) not found',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(288,'Tickets count: %i show new tickets: %s\\n',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(289,'New ticket from %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(290,'Ticket of %s (Category: %i):\\n%s\\n',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(291,'New ticket show: ON',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(292,'New ticket show: OFF',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(293,'Ticket %i doesn\'t exist',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(294,'All tickets deleted.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(295,'Character %s ticket deleted.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(296,'Ticket deleted.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(297,'Spawn distance changed to: %i',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(298,'Spawn time changed to: %i',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(299,'The honor of %s was set to %u!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(300,'Your chat has been disabled for %u minutes.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(301,'You have disabled %s\'s chat for %u minutes.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(302,'Player\'s chat is already enabled.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(303,'Your chat has been enabled.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(304,'You have enabled %s\'s chat.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(400,'|cffff0000[System Message]:|rScripts reloaded',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(401,'You change security level of %s to %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(402,'%s changed your security level to %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(403,'You have low security level for this.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(404,'Creature movement disabled.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(405,'Creature movement enabled.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(406,'Weather can\'t be changed for this zone.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(407,'Weather system disabled at server.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(408,'%s is banned for %s. Reason: %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(409,'%s is banned permanently for %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(410,'%s %s not found',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(411,'%s unbanned.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(412,'There was an error removing the ban on %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(413,'There is no such account.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(414,'There is no such character.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(415,'There is no such IP in banlist.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(416,'Account %s has never been banned',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(417,'Ban history for account %s:',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(418,'Ban Date: %s Bantime: %s Still active: %s Reason: %s Set by: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(419,'Inf.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(420,'Never',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(421,'Yes',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(422,'No',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(423,'IP: %s\\nBan Date: %s\\nUnban Date: %s\\nRemaining: %s\\nReason: %s\\nSet by: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(424,'There is no matching IPban.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(425,'There is no matching account.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(426,'There is no banned account owning a character matching this part.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(427,'The following IPs match your pattern:',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(428,'The following accounts match your query:',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(429,'You learned many spells/skills.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(430,'You learned all spells for class.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(431,'You learned all talents for class.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(432,'You learned all languages.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(433,'You learned all craft skills and recipes.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(434,'Could not find \'%s\'',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(435,'Invalid item id: %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(436,'No items found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(437,'Invalid gameobject id: %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(438,'Found items %u: %u ( inventory %u mail %u auction %u )',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(439,'Found gameobjects %u: %u ',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(440,'Invalid creature id: %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(441,'Found creatures %u: %u ',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(442,'No area found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(443,'No item sets found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(444,'No skills found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(445,'No spells found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(446,'No quests found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(447,'No creatures found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(448,'No gameobjects found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(449,'Graveyard #%u doesn\'t exist.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(450,'Graveyard #%u already linked to zone #%u (current).',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(451,'Graveyard #%u linked to zone #%u (current).',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(452,'Graveyard #%u can\'t be linked to subzone or not existed zone #%u (internal error).',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(453,'Graveyard can be linked to zone at another map only for all factions (no faction value).',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(454,'No faction in Graveyard with id= #%u , fix your DB',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(455,'invalid team, please fix database',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(456,'any',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(457,'alliance',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(458,'horde',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(459,'Graveyard #%u (faction: %s) is nearest from linked to zone #%u.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(460,'Zone #%u doesn\'t have linked graveyards.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(461,'Zone #%u doesn\'t have linked graveyards for faction: %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(462,'Teleport location already exists!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(463,'Teleport location added.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(464,'Teleport location NOT added: database error.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(465,'Teleport location deleted.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(466,'Teleport location NOT deleted: database error.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(467,'Target unit has %d auras:',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(468,'id: %d eff: %d type: %d duration: %d maxduration: %d name: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(469,'Target unit has %d auras of type %d:',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(470,'id: %d eff: %d name: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(471,'Quest %u not found.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(472,'Quest %u started from item. For correct work, please, add item to inventory and start quest in normal way: .additem %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(473,'Quest removed.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(474,' [rewarded]',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(475,' [complete]',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(476,' [active]',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(477,'%s\'s Fly Mode %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(478,'Opcode %u sent to %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(479,'Character loaded successfully!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(480,'Failed to load the character!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(481,'Character dumped successfully!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(482,'Character dump failed!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(483,'Spell %u broken and not allowed to cast or learn!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(484,'Skill %u (%s) for player %s set to %u and current maximum set to %u (without permanent (talent) bonuses).',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(485,'Player %s must have skill %u (%s) before using this command.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(486,'Invalid skill id (%u)',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(487,'You learned default GM spells/skills.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(488,'You already know that spell.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(489,'Target(%s) already know that spell.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(490,'%s doesn\'t know that spell.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(491,'You already forgot that spell.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(492,'All spell cooldowns removed for %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(493,'Spell %u cooldown removed for %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(494,'Command : Additem, itemId = %i, amount = %i',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(495,'Command : Additemset, itemsetId = %i',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(496,'Removed itemID = %i, amount = %i from %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(497,'Cannot create item \'%i\' (amount: %i)',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(498,'You need to provide a guild name!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(499,'Player not found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(500,'Player already has a guild!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(501,'Guild not created! (already exists?)',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(502,'No items from itemset \'%u\' found.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(503,'The distance is: (3D) %f (2D) %f yards.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(504,'Item \'%i\' \'%s\' Item Slot %i',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(505,'Item \'%i\' doesn\'t exist.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(506,'Item \'%i\' \'%s\' Added to Slot %i',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(507,'Item save failed!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(508,'%d - owner: %s (guid: %u account: %u ) %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(509,'%d - sender: %s (guid: %u account: %u ) receiver: %s (guid: %u account: %u ) %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(510,'%d - owner: %s (guid: %u account: %u ) %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(511,'Wrong link type!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(512,'%d - |cffffffff|Hitem:%d:0:0:0:0:0:0:0|h[%s]|h|r ',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(513,'%d - |cffffffff|Hquest:%d|h[%s]|h|r %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(514,'%d - |cffffffff|Hcreature_entry:%d|h[%s]|h|r ',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(515,'%d - |cffffffff|Hcreature:%d|h[%s X:%f Y:%f Z:%f MapId:%d]|h|r ',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(516,'%d - |cffffffff|Hgameobject_entry:%d|h[%s]|h|r ',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(517,'%d - |cffffffff|Hgameobject:%d|h[%s X:%f Y:%f Z:%f MapId:%d]|h|r ',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(518,'%d - |cffffffff|Hitemset:%d|h[%s]|h|r ',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(519,'|cffffffff|Htele:%s|h[%s]|h|r ',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(520,'%d - |cffffffff|Hspell:%d|h[%s]|h|r ',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(521,'%d - |cffffffff|Hskill:%d|h[%s]|h|r %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(522,'Game Object (GUID: %u) not found',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(523,'>> Game Object %s (GUID: %u) at %f %f %f. Orientation %f.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(524,'Selected object:\\n%s\\nGUID: %u ID: %u\\nX: %f Y: %f Z: %f MapId: %u\\nOrientation: %f',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(525,'>> Add Game Object \'%i\' (%s) (GUID: %i) added at \'%f %f %f\'.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(526,'%s (lowguid: %u) movement generators stack:',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(527,' Idle',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(528,' Random',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(529,' Waypoint',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(530,' Animal random',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(531,' Confused',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(532,' Targeted to player %s (lowguid %u)',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(533,' Targeted to creature %s (lowguid %u)',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(534,' Targeted to ',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(535,' Home movement to (X:%f Y:%f Z:%f)',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(536,' Home movement used for player?!?',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(537,' Taxi flight',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(538,' Unknown movement generator (%u)',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(539,'Player selected NPC\\nGUID: %u.\\nFaction: %u.\\nnpcFlags: %u.\\nEntry: %u.\\nDisplayID: %u (Native: %u).',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(540,'Level: %u.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(541,'Health (base): %u. (max): %u. (current): %u.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(542,'Field Flags: %u.\\nDynamic Flags: %u.\\nFaction Template: %u.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(543,'Loot: %u Pickpocket: %u Skinning: %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(544,'Position: %f %f %f.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(545,'*** Is a vendor!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(546,'*** Is a trainer!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(547,'InstanceID: %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(548,'Player%s %s (guid: %u) Account: %s (id: %u) GMLevel: %u Last IP: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(549,'Played time: %s Level: %u Money: %ug%us%uc',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(550,'Command .pinfo doesn\'t support \'rep\' option for offline players.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(551,'%s has explored all zones now.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(552,'%s has no more explored zones.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(553,'%s has explored all zones for you.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(554,'%s has hidden all zones from you.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(555,'Hover enabled',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(556,'Hover disabled',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(557,'You have been leveled up (%i)',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(558,'You have been leveled down (%i)',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(559,'Your level progress has been reset.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(560,'The area has been set as explored.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(561,'The area has been set as not explored.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(562,'GUID=%i \'s updateIndex: %i, value: %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(563,'You change GUID=%i \'s UpdateIndex: %i value to %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(564,'The value index %u is too big to %u(count: %u).',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(565,'Set %u uint32 Value:[OPCODE]:%u [VALUE]:%u',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(566,'You Set %u Field:%u to uint32 Value: %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(567,'Set %u float Value:[OPCODE]:%u [VALUE]:%f',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(568,'You Set %u Field:%i to float Value: %f',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(569,'Get %u uint32 Value:[OPCODE]:%u [VALUE]:%u',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(570,'The uint32 value of %u in %u is: %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(571,'Get %u float Value:[OPCODE]:%u [VALUE]:%f',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(572,'The float of %u value in %u is: %f',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(573,'.Set32Bit:[OPCODE]:%u [VALUE]:%u',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(574,'You set Bit of Field:%u to Value: %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(575,'.Mod32Value:[OPCODE]:%u [VALUE]:%i',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(576,'You modified the value of Field:%u to Value: %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(577,'You are now invisible.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(578,'You are now visible.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(600,'The Alliance wins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(601,'The Horde wins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(602,'The battle for Warsong Gulch begins in 1 minute.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(603,'The battle for Warsong Gulch begins in 30 seconds. Prepare yourselves!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(604,'Let the battle for Warsong Gulch begin!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(605,'$n captured the Horde flag!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(606,'$n captured the Alliance flag!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(607,'The Horde flag was dropped by $n!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(608,'The Alliance Flag was dropped by $n!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(609,'The Alliance Flag was returned to its base by $n!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(610,'The Horde flag was returned to its base by $n!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(611,'The Horde flag was picked up by $n!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(612,'The Alliance Flag was picked up by $n!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(613,'The flags are now placed at their bases.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(650,'Alliance',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(651,'Horde',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(652,'stables',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(653,'blacksmith',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(654,'farm',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(655,'lumber mill',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(656,'mine',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(657,'The %s has taken the %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(658,'$n has defended the %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(659,'$n has assaulted the %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(660,'$n claims the %s! If left unchallenged, the %s will control it in 1 minute!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(661,'The Battle for Arathi Basin begins in 1 minute.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(662,'The Battle for Arathi Basin begins in 30 seconds. Prepare yourselves!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(663,'The Battle for Arathi Basin has begun!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(664,'The Alliance has gathered $1776W resources, and is near victory!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(665,'The Horde has gathered $1777W resources, and is near victory!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(700,'You must be level %u to form an arena team',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(701,'One minute until the Arena battle begins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(702,'Thirty seconds until the Arena battle begins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(703,'Fifteen seconds until the Arena battle begins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(704,'The Arena battle has begun!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(705,'You must wait %s before speaking again.',NULL,NULL,NULL,NULL,NULL,NULL,NULL); +/*!40000 ALTER TABLE `mangos_string` ENABLE KEYS */; +UNLOCK TABLES; diff --git a/sql/updates/0.10/5166_mangos_mangos_string.sql b/sql/updates/0.10/5166_mangos_mangos_string.sql new file mode 100644 index 00000000000..f50f8983020 --- /dev/null +++ b/sql/updates/0.10/5166_mangos_mangos_string.sql @@ -0,0 +1,3 @@ +DELETE FROM `mangos_string` WHERE `entry`= 706; +INSERT INTO `mangos_string` VALUES +(706,'This item(s) have problems with equipping/storing in inventory.',NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/0.10/5172_mangos_mangos_string.sql b/sql/updates/0.10/5172_mangos_mangos_string.sql new file mode 100644 index 00000000000..a9423d997f3 --- /dev/null +++ b/sql/updates/0.10/5172_mangos_mangos_string.sql @@ -0,0 +1,12 @@ +DELETE FROM `mangos_string` WHERE `entry` in (101,152,160,168,288,290,423,524,539,542); +INSERT INTO `mangos_string` VALUES +(101,'Map: %u (%s) Zone: %u (%s) Area: %u (%s)\nX: %f Y: %f Z: %f Orientation: %f\ngrid[%u,%u]cell[%u,%u] InstanceID: %u\n ZoneX: %f ZoneY: %f\nGroundZ: %f FloorZ: %f Have height data (Map: %u VMap: %u)',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(152,'USER1: %i, ADD: %i, DIF: %i\n',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(160,'USER2: %i, ADD: %i, RESULT: %i\n',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(168,'Locations found are:\n',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(288,'Tickets count: %i show new tickets: %s\n',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(290,'Ticket of %s (Category: %i):\n%s\n',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(423,'IP: %s\nBan Date: %s\nUnban Date: %s\nRemaining: %s\nReason: %s\nSet by: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(524,'Selected object:\n%s\nGUID: %u ID: %u\nX: %f Y: %f Z: %f MapId: %u\nOrientation: %f',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(539,'Player selected NPC\nGUID: %u.\nFaction: %u.\nnpcFlags: %u.\nEntry: %u.\nDisplayID: %u (Native: %u).',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(542,'Field Flags: %u.\nDynamic Flags: %u.\nFaction Template: %u.',NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/0.10/5180_mangos_spell_affect.sql b/sql/updates/0.10/5180_mangos_spell_affect.sql new file mode 100644 index 00000000000..c4016284c50 --- /dev/null +++ b/sql/updates/0.10/5180_mangos_spell_affect.sql @@ -0,0 +1,6 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (12303,12788,12789); +INSERT INTO `spell_affect` VALUES + (12303,1,0,0,0,0,0,0x0000100000000000,0), + (12788,1,0,0,0,0,0,0x0000100000000000,0), + (12789,1,0,0,0,0,0,0x0000100000000000,0); + diff --git a/sql/updates/0.10/5181_mangos_mangos_string.sql b/sql/updates/0.10/5181_mangos_mangos_string.sql new file mode 100644 index 00000000000..492533f85a4 --- /dev/null +++ b/sql/updates/0.10/5181_mangos_mangos_string.sql @@ -0,0 +1,3 @@ +DELETE FROM `mangos_string` WHERE `entry` = 548; +INSERT INTO `mangos_string` VALUES + (548,'Player%s %s (guid: %u) Account: %s (id: %u) GMLevel: %u Last IP: %s Latency: %ums',NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/0.10/5185_mangos_spell_proc_event.sql b/sql/updates/0.10/5185_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..79c506857ba --- /dev/null +++ b/sql/updates/0.10/5185_mangos_spell_proc_event.sql @@ -0,0 +1,15 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (20185,20344,20345,20346,27162); +INSERT INTO `spell_proc_event` VALUES + (20185,0,0,0,0,0x0000000000000000,0x00000002,0), + (20344,0,0,0,0,0x0000000000000000,0x00000002,0), + (20345,0,0,0,0,0x0000000000000000,0x00000002,0), + (20346,0,0,0,0,0x0000000000000000,0x00000002,0), + (27162,0,0,0,0,0x0000000000000000,0x00000002,0); + + +DELETE FROM `spell_proc_event` WHERE `entry` IN (20186,20354,20355,27164); +INSERT INTO `spell_proc_event` VALUES + (20186,0,0,0,0,0x0000000000000000,0x00100402,0), + (20354,0,0,0,0,0x0000000000000000,0x00100402,0), + (20355,0,0,0,0,0x0000000000000000,0x00100402,0), + (27164,0,0,0,0,0x0000000000000000,0x00100402,0); diff --git a/sql/updates/0.10/5191_mangos_spell_threat.sql b/sql/updates/0.10/5191_mangos_spell_threat.sql new file mode 100644 index 00000000000..c7afd17384b --- /dev/null +++ b/sql/updates/0.10/5191_mangos_spell_threat.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_threat` WHERE `entry` = 2139; +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES +(2139, 300); \ No newline at end of file diff --git a/sql/updates/0.10/5197_mangos_spell_affect.sql b/sql/updates/0.10/5197_mangos_spell_affect.sql new file mode 100644 index 00000000000..1b113b4a180 --- /dev/null +++ b/sql/updates/0.10/5197_mangos_spell_affect.sql @@ -0,0 +1,175 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (33167); +INSERT INTO `spell_affect` VALUES (33167, 0, 0, 0x00, 0, 0, 0, 0x0000000100000000, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (33171); +INSERT INTO `spell_affect` VALUES (33171, 0, 0, 0x00, 0, 0, 0, 0x0000000100000000, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (33172); +INSERT INTO `spell_affect` VALUES (33172, 0, 0, 0x00, 0, 0, 0, 0x0000000100000000, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (23236); +INSERT INTO `spell_affect` VALUES (23236, 0, 0, 0x00, 0, 0, 0, 0x0000003419541EC0, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (37880); +INSERT INTO `spell_affect` VALUES (37880, 0, 0, 0x00, 0, 0, 0, 0x0000000411041E40, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (15259); +INSERT INTO `spell_affect` VALUES (15259, 0, 0, 0x00, 0, 0, 0, 0x0000000202002000, 0); +INSERT INTO `spell_affect` VALUES (15259, 1, 0, 0x00, 0, 0, 0, 0x0000040000808000, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (15307); +INSERT INTO `spell_affect` VALUES (15307, 0, 0, 0x00, 0, 0, 0, 0x0000000202002000, 0); +INSERT INTO `spell_affect` VALUES (15307, 1, 0, 0x00, 0, 0, 0, 0x0000040000808000, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (15308); +INSERT INTO `spell_affect` VALUES (15308, 0, 0, 0x00, 0, 0, 0, 0x0000000202002000, 0); +INSERT INTO `spell_affect` VALUES (15308, 1, 0, 0x00, 0, 0, 0, 0x0000040000808000, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (15309); +INSERT INTO `spell_affect` VALUES (15309, 0, 0, 0x00, 0, 0, 0, 0x0000000202002000, 0); +INSERT INTO `spell_affect` VALUES (15309, 1, 0, 0x00, 0, 0, 0, 0x0000040000808000, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (15310); +INSERT INTO `spell_affect` VALUES (15310, 0, 0, 0x00, 0, 0, 0, 0x0000000202002000, 0); +INSERT INTO `spell_affect` VALUES (15310, 1, 0, 0x00, 0, 0, 0, 0x0000040000808000, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (14743); +INSERT INTO `spell_affect` VALUES (14743, 0, 0, 0x00, 0, 0, 0, 0x0000049440963E90, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (27828); +INSERT INTO `spell_affect` VALUES (27828, 0, 0, 0x00, 0, 0, 0, 0x0000049440963E90, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (33186); +INSERT INTO `spell_affect` VALUES (33186, 0, 0, 0x00, 0, 0, 0, 0x0000008000000000, 0); +INSERT INTO `spell_affect` VALUES (33186, 1, 0, 0x00, 0, 0, 0, 0x0000008000002080, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (33190); +INSERT INTO `spell_affect` VALUES (33190, 0, 0, 0x00, 0, 0, 0, 0x0000008000000000, 0); +INSERT INTO `spell_affect` VALUES (33190, 1, 0, 0x00, 0, 0, 0, 0x0000008000002080, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (18544); +INSERT INTO `spell_affect` VALUES (18544, 0, 0, 0x00, 0, 0, 0, 0x0000041202F8A090, 0); +INSERT INTO `spell_affect` VALUES (18544, 1, 0, 0x00, 0, 0, 0, 0x0000001202582090, 0); +INSERT INTO `spell_affect` VALUES (18544, 2, 0, 0x00, 0, 0, 0, 0x0000040000A08000, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (18547); +INSERT INTO `spell_affect` VALUES (18547, 0, 0, 0x00, 0, 0, 0, 0x0000041202F8A090, 0); +INSERT INTO `spell_affect` VALUES (18547, 1, 0, 0x00, 0, 0, 0, 0x0000001202582090, 0); +INSERT INTO `spell_affect` VALUES (18547, 2, 0, 0x00, 0, 0, 0, 0x0000040000A08000, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (18548); +INSERT INTO `spell_affect` VALUES (18548, 0, 0, 0x00, 0, 0, 0, 0x0000041202F8A090, 0); +INSERT INTO `spell_affect` VALUES (18548, 1, 0, 0x00, 0, 0, 0, 0x0000001202582090, 0); +INSERT INTO `spell_affect` VALUES (18548, 2, 0, 0x00, 0, 0, 0, 0x0000040000A08000, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (18549); +INSERT INTO `spell_affect` VALUES (18549, 0, 0, 0x00, 0, 0, 0, 0x0000041202F8A090, 0); +INSERT INTO `spell_affect` VALUES (18549, 1, 0, 0x00, 0, 0, 0, 0x0000001202582090, 0); +INSERT INTO `spell_affect` VALUES (18549, 2, 0, 0x00, 0, 0, 0, 0x0000040000A08000, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (18550); +INSERT INTO `spell_affect` VALUES (18550, 0, 0, 0x00, 0, 0, 0, 0x0000041202F8A090, 0); +INSERT INTO `spell_affect` VALUES (18550, 1, 0, 0x00, 0, 0, 0, 0x0000001202582090, 0); +INSERT INTO `spell_affect` VALUES (18550, 2, 0, 0x00, 0, 0, 0, 0x0000040000A08000, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (14913); +INSERT INTO `spell_affect` VALUES (14913, 0, 0, 0x00, 0, 0, 0, 0x0000000400041E00, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (15012); +INSERT INTO `spell_affect` VALUES (15012, 0, 0, 0x00, 0, 0, 0, 0x0000000400041E00, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (37706); +INSERT INTO `spell_affect` VALUES (37706, 0, 0, 0x00, 0, 0, 0, 0x0000000411041E40, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (37571); +INSERT INTO `spell_affect` VALUES (37571, 0, 0, 0x00, 0, 0, 0, 0x0000000000000080, 0); +INSERT INTO `spell_affect` VALUES (37571, 1, 0, 0x00, 0, 0, 0, 0x0000000000800000, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (14751); +INSERT INTO `spell_affect` VALUES (14751, 0, 0, 0x00, 0, 0, 0, 0xFFFFFFFFFFFFFFFF, 0); +INSERT INTO `spell_affect` VALUES (14751, 1, 0, 0x00, 0, 0, 0, 0xFFFFFFFFFFFFFFFF, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (14520); +INSERT INTO `spell_affect` VALUES (14520, 0, 0, 0x00, 0, 0, 0, 0x00000963BF61C16F, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (14780); +INSERT INTO `spell_affect` VALUES (14780, 0, 0, 0x00, 0, 0, 0, 0x00000963BF61C16F, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (14781); +INSERT INTO `spell_affect` VALUES (14781, 0, 0, 0x00, 0, 0, 0, 0x00000963BF61C16F, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (14782); +INSERT INTO `spell_affect` VALUES (14782, 0, 0, 0x00, 0, 0, 0, 0x00000963BF61C16F, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (14783); +INSERT INTO `spell_affect` VALUES (14783, 0, 0, 0x00, 0, 0, 0, 0x00000963BF61C16F, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (28808); +INSERT INTO `spell_affect` VALUES (28808, 0, 0, 0x00, 0, 0, 0, 0x0000000411041E40, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (15318); +INSERT INTO `spell_affect` VALUES (15318, 0, 0, 0x00, 0, 0, 0, 0x00000D4A068BE104, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (15272); +INSERT INTO `spell_affect` VALUES (15272, 0, 0, 0x00, 0, 0, 0, 0x00000D4A068BE104, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (15320); +INSERT INTO `spell_affect` VALUES (15320, 0, 0, 0x00, 0, 0, 0, 0x00000D4A068BE104, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (15260); +INSERT INTO `spell_affect` VALUES (15260, 0, 0, 0x00, 0, 0, 0, 0x00000442068BA000, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (15327); +INSERT INTO `spell_affect` VALUES (15327, 0, 0, 0x00, 0, 0, 0, 0x00000442068BA000, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (15328); +INSERT INTO `spell_affect` VALUES (15328, 0, 0, 0x00, 0, 0, 0, 0x00000442068BA000, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (15329); +INSERT INTO `spell_affect` VALUES (15329, 0, 0, 0x00, 0, 0, 0, 0x00000442068BA000, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (15330); +INSERT INTO `spell_affect` VALUES (15330, 0, 0, 0x00, 0, 0, 0, 0x00000442068BA000, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (17322); +INSERT INTO `spell_affect` VALUES (17322, 0, 0, 0x00, 0, 0, 0, 0x00000542068AA004, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (17323); +INSERT INTO `spell_affect` VALUES (17323, 0, 0, 0x00, 0, 0, 0, 0x00000542068AA004, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (14523); +INSERT INTO `spell_affect` VALUES (14523, 1, 0, 0x00, 0, 0, 0, 0xFFFFFFFFFFFFFFFF, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (14784); +INSERT INTO `spell_affect` VALUES (14784, 1, 0, 0x00, 0, 0, 0, 0xFFFFFFFFFFFFFFFF, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (14785); +INSERT INTO `spell_affect` VALUES (14785, 1, 0, 0x00, 0, 0, 0, 0xFFFFFFFFFFFFFFFF, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (14786); +INSERT INTO `spell_affect` VALUES (14786, 1, 0, 0x00, 0, 0, 0, 0xFFFFFFFFFFFFFFFF, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (14787); +INSERT INTO `spell_affect` VALUES (14787, 1, 0, 0x00, 0, 0, 0, 0xFFFFFFFFFFFFFFFF, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (14912); +INSERT INTO `spell_affect` VALUES (14912, 0, 0, 0x00, 0, 0, 0, 0x0000000000041400, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (15013); +INSERT INTO `spell_affect` VALUES (15013, 0, 0, 0x00, 0, 0, 0, 0x0000000000041400, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (15014); +INSERT INTO `spell_affect` VALUES (15014, 0, 0, 0x00, 0, 0, 0, 0x0000000000041400, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (14747); +INSERT INTO `spell_affect` VALUES (14747, 0, 0, 0x00, 0, 0, 0, 0x0000000000000002, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (14770); +INSERT INTO `spell_affect` VALUES (14770, 0, 0, 0x00, 0, 0, 0, 0x0000000000000002, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (14771); +INSERT INTO `spell_affect` VALUES (14771, 0, 0, 0x00, 0, 0, 0, 0x0000000000000002, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (44297); +INSERT INTO `spell_affect` VALUES (44297, 0, 0, 0x00, 0, 0, 0, 0x0000000000010000, 0); + diff --git a/sql/updates/0.10/5199_characters_guild_bank_eventlog.sql b/sql/updates/0.10/5199_characters_guild_bank_eventlog.sql new file mode 100644 index 00000000000..27867c0ff6e --- /dev/null +++ b/sql/updates/0.10/5199_characters_guild_bank_eventlog.sql @@ -0,0 +1 @@ +DELETE FROM `guild_bank_eventlog` WHERE `LogGuid`=0; diff --git a/sql/updates/0.10/5201_mangos_spell_affect.sql b/sql/updates/0.10/5201_mangos_spell_affect.sql new file mode 100644 index 00000000000..3a8eb9a937f --- /dev/null +++ b/sql/updates/0.10/5201_mangos_spell_affect.sql @@ -0,0 +1,53 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (30288); +INSERT INTO `spell_affect` VALUES (30288, 0, 0, 0x00, 0, 0, 0, 0x0000004000000001, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (30289); +INSERT INTO `spell_affect` VALUES (30289, 0, 0, 0x00, 0, 0, 0, 0x0000004000000001, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (30290); +INSERT INTO `spell_affect` VALUES (30290, 0, 0, 0x00, 0, 0, 0, 0x0000004000000001, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (30291); +INSERT INTO `spell_affect` VALUES (30291, 0, 0, 0x00, 0, 0, 0, 0x0000004000000001, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (30292); +INSERT INTO `spell_affect` VALUES (30292, 0, 0, 0x00, 0, 0, 0, 0x0000004000000001, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (18427); +INSERT INTO `spell_affect` VALUES (18427, 0, 0, 0x00, 0, 0, 0, 0x0000000000020006, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (18428); +INSERT INTO `spell_affect` VALUES (18428, 0, 0, 0x00, 0, 0, 0, 0x0000000000020006, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (18429); +INSERT INTO `spell_affect` VALUES (18429, 0, 0, 0x00, 0, 0, 0, 0x0000000000020006, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (31216); +INSERT INTO `spell_affect` VALUES (31216, 1, 0, 0x00, 0, 0, 0, 0x0000000002000004, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (31217); +INSERT INTO `spell_affect` VALUES (31217, 1, 0, 0x00, 0, 0, 0, 0x0000000002000004, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (31218); +INSERT INTO `spell_affect` VALUES (31218, 1, 0, 0x00, 0, 0, 0, 0x0000000002000004, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (31219); +INSERT INTO `spell_affect` VALUES (31219, 1, 0, 0x00, 0, 0, 0, 0x0000000002000004, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (31220); +INSERT INTO `spell_affect` VALUES (31220, 1, 0, 0x00, 0, 0, 0, 0x0000000002000004, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (14171); +INSERT INTO `spell_affect` VALUES (14171, 0, 0, 0x00, 0, 0, 0, 0x0000000000100000, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (14172); +INSERT INTO `spell_affect` VALUES (14172, 0, 0, 0x00, 0, 0, 0, 0x0000000000100000, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (14173); +INSERT INTO `spell_affect` VALUES (14173, 0, 0, 0x00, 0, 0, 0, 0x0000000000100000, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (12290); +INSERT INTO `spell_affect` VALUES (12290, 0, 0, 0x00, 0, 0, 0, 0x0000000000000004, 0); + +DELETE FROM `spell_affect` WHERE `entry` IN (12963); +INSERT INTO `spell_affect` VALUES (12963, 0, 0, 0x00, 0, 0, 0, 0x0000000000000004, 0); \ No newline at end of file diff --git a/sql/updates/0.10/5212_mangos_command.sql b/sql/updates/0.10/5212_mangos_command.sql new file mode 100644 index 00000000000..51f5948ed90 --- /dev/null +++ b/sql/updates/0.10/5212_mangos_command.sql @@ -0,0 +1,4 @@ +DELETE FROM command WHERE name IN ('.casttarget'); + +INSERT INTO `command` VALUES +('casttarget',3,'Syntax: .casttarget #spellid\r\n Selected target will cast #spellid to his victim.'); diff --git a/sql/updates/0.10/5212_mangos_mangos_string.sql b/sql/updates/0.10/5212_mangos_mangos_string.sql new file mode 100644 index 00000000000..b84f7d59488 --- /dev/null +++ b/sql/updates/0.10/5212_mangos_mangos_string.sql @@ -0,0 +1,3 @@ +DELETE FROM `mangos_string` WHERE `entry` = 579; +INSERT INTO `mangos_string` VALUES + (579,'Selected player or creature not have victim.',NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/0.10/5217_characters_character.sql b/sql/updates/0.10/5217_characters_character.sql new file mode 100644 index 00000000000..61d6e105c11 --- /dev/null +++ b/sql/updates/0.10/5217_characters_character.sql @@ -0,0 +1,2 @@ +ALTER TABLE `character` + ADD COLUMN `taxi_path` text; diff --git a/sql/updates/0.10/5228_mangos_gameobject_scripts.sql b/sql/updates/0.10/5228_mangos_gameobject_scripts.sql new file mode 100644 index 00000000000..5c5fecb14ed --- /dev/null +++ b/sql/updates/0.10/5228_mangos_gameobject_scripts.sql @@ -0,0 +1,13 @@ +DROP TABLE IF EXISTS `gameobject_scripts`; +CREATE TABLE `gameobject_scripts` ( +`id` INT( 11 ) UNSIGNED NOT NULL DEFAULT '0', +`delay` INT( 11 ) UNSIGNED NOT NULL DEFAULT '0', +`command` INT( 11 ) UNSIGNED NOT NULL DEFAULT '0', +`datalong` INT( 11 ) UNSIGNED NOT NULL DEFAULT '0', +`datalong2` INT( 11 ) UNSIGNED NOT NULL DEFAULT '0', +`datatext` TEXT NOT NULL , +`x` FLOAT NOT NULL DEFAULT '0', +`y` FLOAT NOT NULL DEFAULT '0', +`z` FLOAT NOT NULL DEFAULT '0', +`o` FLOAT NOT NULL DEFAULT '0' +) ENGINE = MYISAM DEFAULT CHARSET = utf8; diff --git a/sql/updates/0.10/5233_mangos_event_scripts.sql b/sql/updates/0.10/5233_mangos_event_scripts.sql new file mode 100644 index 00000000000..1ab97a526d8 --- /dev/null +++ b/sql/updates/0.10/5233_mangos_event_scripts.sql @@ -0,0 +1 @@ +ALTER TABLE `gameobject_scripts` RENAME TO `event_scripts`; diff --git a/sql/updates/0.10/5234_mangos_spell_proc_event.sql b/sql/updates/0.10/5234_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..9ed803db866 --- /dev/null +++ b/sql/updates/0.10/5234_mangos_spell_proc_event.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (29601); +INSERT INTO `spell_proc_event` VALUES +(29601,0,0,0,7,0x0000000000000000,0x00004000,0); diff --git a/sql/updates/0.10/5238_mangos_spell_proc_event.sql b/sql/updates/0.10/5238_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..d6515853e98 --- /dev/null +++ b/sql/updates/0.10/5238_mangos_spell_proc_event.sql @@ -0,0 +1,7 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (33727,33754,33755,33756,33757); +INSERT INTO `spell_proc_event` VALUES +(33727,0,0,0,0,0x0000000000000000,0x00000000,0), /* not used*/ +(33754,0,0,0,0,0x0000000000000000,0x00000000,0), /* not used*/ +(33755,0,0,0,0,0x0000000000000000,0x00000000,0), /* not used*/ +(33756,0,0,0,0,0x0000000000000000,0x00000000,0), /* not used*/ +(33757,0,0,0,0,0x0000000000000000,0x00000001,0); diff --git a/sql/updates/0.10/5242_mangos_instance_template.sql b/sql/updates/0.10/5242_mangos_instance_template.sql new file mode 100644 index 00000000000..e0229a66cd2 --- /dev/null +++ b/sql/updates/0.10/5242_mangos_instance_template.sql @@ -0,0 +1,2 @@ +ALTER TABLE `instance_template` + ADD `parent` int(11) unsigned NOT NULL AFTER `map`; diff --git a/sql/updates/0.10/5243_mangos_spell_affect.sql b/sql/updates/0.10/5243_mangos_spell_affect.sql new file mode 100644 index 00000000000..21e9a0bea76 --- /dev/null +++ b/sql/updates/0.10/5243_mangos_spell_affect.sql @@ -0,0 +1,8 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (33886,33887,33888,33889,33890); +INSERT INTO `spell_affect` VALUES +(33886,0,0,0,0,0,0,0x00000010000000d0, 0), +(33887,0,0,0,0,0,0,0x00000010000000d0, 0), +(33888,0,0,0,0,0,0,0x00000010000000d0, 0), +(33889,0,0,0,0,0,0,0x00000010000000d0, 0), +(33890,0,0,0,0,0,0,0x00000010000000d0, 0); + diff --git a/sql/updates/0.10/5249_mangos_spell_learn_skill.sql b/sql/updates/0.10/5249_mangos_spell_learn_skill.sql new file mode 100644 index 00000000000..37d52b21e33 --- /dev/null +++ b/sql/updates/0.10/5249_mangos_spell_learn_skill.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_learn_skill` WHERE `entry` IN (29932); +INSERT INTO `spell_learn_skill` (`entry`, `SkillID`, `Value`, `MaxValue`) VALUE +(29932,759,-1,-1); diff --git a/sql/updates/0.10/5254_mangos_spell_affect.sql b/sql/updates/0.10/5254_mangos_spell_affect.sql new file mode 100644 index 00000000000..15225141898 --- /dev/null +++ b/sql/updates/0.10/5254_mangos_spell_affect.sql @@ -0,0 +1,11 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (31579,31582,31583) AND `effectId`=0; +INSERT INTO `spell_affect` VALUES + (31579,0,0,0,0,0,0,0x0000000000200000,0), + (31582,0,0,0,0,0,0,0x0000000000200000,0), + (31583,0,0,0,0,0,0,0x0000000000200000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (20237,20238,20239); +INSERT INTO `spell_affect` VALUES + (20237,0,0,0,0,0,0,0x0000000000006000,0), + (20238,0,0,0,0,0,0,0x0000000000006000,0), + (20239,0,0,0,0,0,0,0x0000000000006000,0); diff --git a/sql/updates/0.10/5254_mangos_spell_proc_event.sql b/sql/updates/0.10/5254_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..c7d27f41d96 --- /dev/null +++ b/sql/updates/0.10/5254_mangos_spell_proc_event.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (43750); +INSERT INTO `spell_proc_event` VALUES +(43750,0,0,0,11,0x0000000000000001,0x00004000,0); diff --git a/sql/updates/0.10/5258_characters_character.sql b/sql/updates/0.10/5258_characters_character.sql new file mode 100644 index 00000000000..a40b01fd0e6 --- /dev/null +++ b/sql/updates/0.10/5258_characters_character.sql @@ -0,0 +1 @@ +ALTER TABLE `character` ADD KEY `idx_name` (`name`); \ No newline at end of file diff --git a/sql/updates/0.10/5265_mangos_spell_proc_event.sql b/sql/updates/0.10/5265_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..9329b06b7a6 --- /dev/null +++ b/sql/updates/0.10/5265_mangos_spell_proc_event.sql @@ -0,0 +1,31 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (39446); +INSERT INTO `spell_proc_event` VALUES +(39446,0,0,0,0,0x0000000000000000,0x00000004,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (32863,36123,38252,39367); +INSERT INTO `spell_proc_event` VALUES +(32863,0,0,0,0,0x0000000000000000,0x00008000,0), +(36123,0,0,0,0,0x0000000000000000,0x00008000,0), +(38252,0,0,0,0,0x0000000000000000,0x00008000,0), +(39367,0,0,0,0,0x0000000000000000,0x00008000,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (37381); +INSERT INTO `spell_proc_event` VALUES +(37381,0,0,0,0,0x0000000000000000,0x000a0001,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (39372); +INSERT INTO `spell_proc_event` VALUES +(39372,0,0,0,0,0x0000000000000000,0x00020000,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (28789); +INSERT INTO `spell_proc_event` VALUES +(28789,0,0,0,10,0x0000000000006000,0x20000000,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (28849); +INSERT INTO `spell_proc_event` VALUES +(28849,0,0,0,11,0x0000000000000080,0x00004000,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (37655,38334); +INSERT INTO `spell_proc_event` VALUES +(37655,0,0,0,0,0x0000000000000000,0x00004000,0), +(38334,0,0,0,0,0x0000000000000000,0x00004000,0); diff --git a/sql/updates/0.10/5269_mangos_uptime.sql b/sql/updates/0.10/5269_mangos_uptime.sql new file mode 100644 index 00000000000..289da45efc5 --- /dev/null +++ b/sql/updates/0.10/5269_mangos_uptime.sql @@ -0,0 +1,2 @@ +ALTER TABLE `uptime` + ADD COLUMN `maxplayers` int(11) unsigned NOT NULL default '0'; diff --git a/sql/updates/0.10/5270_mangos_gameobject_scripts.sql b/sql/updates/0.10/5270_mangos_gameobject_scripts.sql new file mode 100644 index 00000000000..52f523aeba6 --- /dev/null +++ b/sql/updates/0.10/5270_mangos_gameobject_scripts.sql @@ -0,0 +1 @@ +ALTER TABLE `button_scripts` RENAME TO `gameobject_scripts`; diff --git a/sql/updates/0.10/5272_mangos_mangos_string.sql b/sql/updates/0.10/5272_mangos_mangos_string.sql new file mode 100644 index 00000000000..699ea9d003c --- /dev/null +++ b/sql/updates/0.10/5272_mangos_mangos_string.sql @@ -0,0 +1,6 @@ +DELETE FROM `mangos_string` WHERE `entry` in (707,708,709,710); +INSERT INTO `mangos_string` VALUES +(707,'%s wishes to not be disturbed and cannot receive whisper messages: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(708,'%s is Away from Keyboard: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(709,'Do not Disturb',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(710,'Away from Keyboard',NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/0.10/5286_characters_character_pet.sql b/sql/updates/0.10/5286_characters_character_pet.sql new file mode 100644 index 00000000000..37747b31962 --- /dev/null +++ b/sql/updates/0.10/5286_characters_character_pet.sql @@ -0,0 +1,2 @@ +ALTER TABLE `character_pet` + DROP `nextlvlexp`; diff --git a/sql/updates/0.10/5292_mangos_spell_proc_event.sql b/sql/updates/0.10/5292_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..d1277c8958f --- /dev/null +++ b/sql/updates/0.10/5292_mangos_spell_proc_event.sql @@ -0,0 +1,8 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (13743,13875); +INSERT INTO `spell_proc_event` VALUES +(13743,0,0,0,8,0x0000000000000040,0x00004000,0), +(13875,0,0,0,8,0x0000000000000040,0x00004000,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (16864); +INSERT INTO `spell_proc_event` VALUES +(16864,0,0,0,0,0x0000000000000000,0x00000001,2); diff --git a/sql/updates/0.10/5295_mangos_creature_template.sql b/sql/updates/0.10/5295_mangos_creature_template.sql new file mode 100644 index 00000000000..016b112e4d3 --- /dev/null +++ b/sql/updates/0.10/5295_mangos_creature_template.sql @@ -0,0 +1,2 @@ +ALTER TABLE `creature_template` +ADD `mechanic_immune_mask` int(11) signed NOT NULL default '0' AFTER `equipment_id` ; \ No newline at end of file diff --git a/sql/updates/0.10/5297_characters.sql b/sql/updates/0.10/5297_characters.sql new file mode 100644 index 00000000000..a2055b648db --- /dev/null +++ b/sql/updates/0.10/5297_characters.sql @@ -0,0 +1,16 @@ +ALTER TABLE `character` RENAME TO `characters`; +ALTER TABLE `group` RENAME TO `groups`; + +ALTER TABLE `character_pet` + CHANGE COLUMN `ABData` `abdata` longtext, + CHANGE COLUMN `TeachSpelldata` `teachspelldata` longtext; + +ALTER TABLE `guild` + CHANGE COLUMN `MOTD` `motd` varchar(255) NOT NULL default ''; + +ALTER TABLE `guild_member` + CHANGE COLUMN `Pnote` `pnote` varchar(255) NOT NULL default '', + CHANGE COLUMN `OFFnote` `offnote` varchar(255) NOT NULL default ''; + +ALTER TABLE `guild_bank_right` + CHANGE COLUMN `Right` `gbright` tinyint(3) unsigned NOT NULL default '0'; \ No newline at end of file diff --git a/sql/updates/0.10/5297_mangos.sql b/sql/updates/0.10/5297_mangos.sql new file mode 100644 index 00000000000..e009a5b13ae --- /dev/null +++ b/sql/updates/0.10/5297_mangos.sql @@ -0,0 +1,12 @@ +ALTER TABLE `game_event` + CHANGE COLUMN `start` `start_time` timestamp NOT NULL default '0000-00-00 00:00:00' COMMENT 'Absolute start date, the event will never start before', + CHANGE COLUMN `end` `end_time` timestamp NOT NULL default '0000-00-00 00:00:00' COMMENT 'Absolute end date, the event will never start afler'; + +ALTER TABLE `pet_levelstats` + CHANGE COLUMN `int` `inte` smallint(5) unsigned NOT NULL; + +ALTER TABLE `player_levelstats` + CHANGE COLUMN `int` `inte` smallint(5) unsigned NOT NULL; + +ALTER TABLE `npc_option` + CHANGE COLUMN `option` `option_text` text; \ No newline at end of file diff --git a/sql/updates/0.10/5297_realmd_account.sql b/sql/updates/0.10/5297_realmd_account.sql new file mode 100644 index 00000000000..771f4dcd7fa --- /dev/null +++ b/sql/updates/0.10/5297_realmd_account.sql @@ -0,0 +1,2 @@ +ALTER TABLE `account` + CHANGE COLUMN `I` `sha_pass_hash` VARCHAR(40) NOT NULL default ''; \ No newline at end of file diff --git a/sql/updates/0.10/5302_mangos_player_levelstats.sql b/sql/updates/0.10/5302_mangos_player_levelstats.sql new file mode 100644 index 00000000000..55f768f7886 --- /dev/null +++ b/sql/updates/0.10/5302_mangos_player_levelstats.sql @@ -0,0 +1,13 @@ +ALTER TABLE player_levelstats + ADD COLUMN basehp smallint(5) unsigned NOT NULL AFTER level, + ADD COLUMN basemana smallint(5) unsigned NOT NULL AFTER basehp; + +UPDATE player_levelstats SET basehp = hp - sta WHERE sta <= 20; +UPDATE player_levelstats SET basehp = hp - 20 - (sta-20)*10 WHERE sta > 20; + +UPDATE player_levelstats SET basemana = mana - inte WHERE mana > 0 and inte <= 20; +UPDATE player_levelstats SET basemana = mana - 20 - (inte-20)*15 WHERE mana > 0 and inte > 20; + +ALTER TABLE player_levelstats + DROP COLUMN hp, + DROP COLUMN mana; diff --git a/sql/updates/0.10/5311_mangos_spell_affect.sql b/sql/updates/0.10/5311_mangos_spell_affect.sql new file mode 100644 index 00000000000..7ef9608196f --- /dev/null +++ b/sql/updates/0.10/5311_mangos_spell_affect.sql @@ -0,0 +1,3 @@ +DELETE FROM spell_affect WHERE entry IN (28746); +INSERT INTO spell_affect VALUES + (28746,1,0,0,0,0,0,0x0000000100000406,0); diff --git a/sql/updates/0.10/5326_mangos_spell_affect.sql b/sql/updates/0.10/5326_mangos_spell_affect.sql new file mode 100644 index 00000000000..5f42e540919 --- /dev/null +++ b/sql/updates/0.10/5326_mangos_spell_affect.sql @@ -0,0 +1,8 @@ +DELETE FROM spell_affect WHERE entry IN (16858,16859,16860); +INSERT INTO spell_affect VALUES + (16858,0,0,0,0,0,0,0x0000000000000008,0), + (16858,1,0,0,0,0,0,0x0000000000800000,0), + (16859,0,0,0,0,0,0,0x0000000000000008,0), + (16859,1,0,0,0,0,0,0x0000000000800000,0), + (16860,0,0,0,0,0,0,0x0000000000000008,0), + (16860,1,0,0,0,0,0,0x0000000000800000,0); diff --git a/sql/updates/0.10/5335_mangos_mangos_string.sql b/sql/updates/0.10/5335_mangos_mangos_string.sql new file mode 100644 index 00000000000..f3f45926733 --- /dev/null +++ b/sql/updates/0.10/5335_mangos_mangos_string.sql @@ -0,0 +1,3 @@ +DELETE FROM mangos_string WHERE entry in (12); +INSERT INTO mangos_string VALUES +(12,'Online players: %u (max: %u) Queued players: %u (max: %u)',NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/0.10/5343_mangos_spell_proc_event.sql b/sql/updates/0.10/5343_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..21d73c6da49 --- /dev/null +++ b/sql/updates/0.10/5343_mangos_spell_proc_event.sql @@ -0,0 +1,7 @@ +DELETE FROM spell_proc_event WHERE entry IN (39958); +INSERT INTO spell_proc_event VALUES +(39958,0,0,0,0,0x0000000000000000,0x00000001,0.7); + +DELETE FROM spell_proc_event WHERE entry IN (33759); +INSERT INTO `spell_proc_event` VALUES +(33759,0,0,0,0,0x0000000000000000,0x00000004,0); diff --git a/sql/updates/0.10/5347_mangos_spell_affect.sql b/sql/updates/0.10/5347_mangos_spell_affect.sql new file mode 100644 index 00000000000..8ba845e9df7 --- /dev/null +++ b/sql/updates/0.10/5347_mangos_spell_affect.sql @@ -0,0 +1,3 @@ +DELETE FROM spell_affect WHERE entry IN (5420); +INSERT INTO spell_affect VALUES + (5420,2,0,0,0,0,0,0x00000010000000F0,0); diff --git a/sql/updates/0.10/5350_mangos_spell_affect.sql b/sql/updates/0.10/5350_mangos_spell_affect.sql new file mode 100644 index 00000000000..e712c312342 --- /dev/null +++ b/sql/updates/0.10/5350_mangos_spell_affect.sql @@ -0,0 +1,3 @@ +DELETE FROM spell_affect WHERE entry IN (5420); +INSERT INTO spell_affect VALUES + (5420,2,0,0,0,0,0,0x00001012100000D0,0); \ No newline at end of file diff --git a/sql/updates/0.10/5351_mangos_spell_proc_event.sql b/sql/updates/0.10/5351_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..22b96f63e9f --- /dev/null +++ b/sql/updates/0.10/5351_mangos_spell_proc_event.sql @@ -0,0 +1,10 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (14892,15362,15363); +INSERT INTO `spell_proc_event` VALUES +(14892,0,0,0,6,0x0000000410001E00,0x10000000,0), +(15362,0,0,0,6,0x0000000410001E00,0x10000000,0), +(15363,0,0,0,6,0x0000000410001E00,0x10000000,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (33150,33154); +INSERT INTO `spell_proc_event` VALUES +(33150,0,0,0,0,0x0000000000000000,0x10010000,0), +(33154,0,0,0,0,0x0000000000000000,0x10010000,0); diff --git a/sql/updates/0.10/5363_mangos_creature_template.sql b/sql/updates/0.10/5363_mangos_creature_template.sql new file mode 100644 index 00000000000..3435bd17b0b --- /dev/null +++ b/sql/updates/0.10/5363_mangos_creature_template.sql @@ -0,0 +1,2 @@ +ALTER TABLE `creature_template` + ADD `scale` float default '0' AFTER `speed`; \ No newline at end of file diff --git a/sql/updates/0.10/5366_mangos_spell_proc_event.sql b/sql/updates/0.10/5366_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..5993a00231a --- /dev/null +++ b/sql/updates/0.10/5366_mangos_spell_proc_event.sql @@ -0,0 +1,7 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (35541,35550,35551,35552,35553); +INSERT INTO `spell_proc_event` VALUES +(35541,0,0,0,0,0x0000000000000000,0x00000001,0), +(35550,0,0,0,0,0x0000000000000000,0x00000001,0), +(35551,0,0,0,0,0x0000000000000000,0x00000001,0), +(35552,0,0,0,0,0x0000000000000000,0x00000001,0), +(35553,0,0,0,0,0x0000000000000000,0x00000001,0); diff --git a/sql/updates/0.10/5367_mangos_spell_affect.sql b/sql/updates/0.10/5367_mangos_spell_affect.sql new file mode 100644 index 00000000000..19c081ca97a --- /dev/null +++ b/sql/updates/0.10/5367_mangos_spell_affect.sql @@ -0,0 +1,3 @@ +DELETE FROM spell_affect WHERE entry IN (32601); +INSERT INTO spell_affect VALUES + (32601,1,0,0,0,0,0,0x0000000020800008,0); diff --git a/sql/updates/0.10/5370_mangos_spell_affect.sql b/sql/updates/0.10/5370_mangos_spell_affect.sql new file mode 100644 index 00000000000..2adb3f1adc7 --- /dev/null +++ b/sql/updates/0.10/5370_mangos_spell_affect.sql @@ -0,0 +1,87 @@ +DELETE FROM spell_affect WHERE entry IN (14177); +INSERT INTO spell_affect VALUES + (14177,0,0,0,0,0,0,0x000000086012031E,0); + +DELETE FROM spell_affect WHERE entry IN (14082,14083); +INSERT INTO spell_affect VALUES + (14082,0,0,0,0,0,0,0x0000000000000500,0), + (14083,0,0,0,0,0,0,0x0000000000000500,0); + +DELETE FROM spell_affect WHERE entry IN (14076,14094); +INSERT INTO spell_affect VALUES + (14076,0,0,0,0,0,0,0x0000000001000080,0), + (14076,1,0,0,0,0,0,0x0000000001000080,0), + (14094,0,0,0,0,0,0,0x0000000001000080,0), + (14094,1,0,0,0,0,0,0x0000000001000080,0); + +DELETE FROM spell_affect WHERE entry IN (37166); +INSERT INTO spell_affect VALUES + (37166,0,0,0,0,0,0,0x0000000000800000,0); + +DELETE FROM spell_affect WHERE entry IN (31234,31235,31236,31237,31238); +INSERT INTO spell_affect VALUES + (31234,0,0,0,0,0,0,0x000001002612030F,0), + (31234,1,0,0,0,0,0,0x0000000000100100,0), + (31235,0,0,0,0,0,0,0x000001002612030F,0), + (31235,1,0,0,0,0,0,0x0000000000100100,0), + (31236,0,0,0,0,0,0,0x000001002612030F,0), + (31236,1,0,0,0,0,0,0x0000000000100100,0), + (31237,0,0,0,0,0,0,0x000001002612030F,0), + (31237,1,0,0,0,0,0,0x0000000000100100,0), + (31238,0,0,0,0,0,0,0x000001002612030F,0), + (31238,1,0,0,0,0,0,0x0000000000100100,0); + +DELETE FROM spell_affect WHERE entry IN (14128,14132,14135,14136,14137); +INSERT INTO spell_affect VALUES + (14128,0,0,0,0,0,0,0x000000062600000E,0), + (14132,0,0,0,0,0,0,0x000000062600000E,0), + (14135,0,0,0,0,0,0,0x000000062600000E,0), + (14136,0,0,0,0,0,0,0x000000062600000E,0), + (14137,0,0,0,0,0,0,0x000000062600000E,0); + +DELETE FROM spell_affect WHERE entry IN (14057,14072,14073,14074,14075); +INSERT INTO spell_affect VALUES + (14057,0,0,0,0,0,0,0x0000000600000304,0), + (14057,1,0,0,0,0,0,0x0000000000000100,0), + (14072,0,0,0,0,0,0,0x0000000600000304,0), + (14072,1,0,0,0,0,0,0x0000000000000100,0), + (14073,0,0,0,0,0,0,0x0000000600000304,0), + (14073,1,0,0,0,0,0,0x0000000000000100,0), + (14074,0,0,0,0,0,0,0x0000000600000304,0), + (14074,1,0,0,0,0,0,0x0000000000000100,0), + (14075,0,0,0,0,0,0,0x0000000600000304,0), + (14075,1,0,0,0,0,0,0x0000000000000100,0); + +DELETE FROM spell_affect WHERE entry IN (14143,14149,14151); +INSERT INTO spell_affect VALUES + (14143,0,0,0,0,0,0,0x0000000606000206,0), + (14149,0,0,0,0,0,0,0x0000000606000206,0), + (14151,0,0,0,0,0,0,0x0000000606000206,0); + +DELETE FROM spell_affect WHERE entry IN (28815); +INSERT INTO spell_affect VALUES + (28815,0,0,0,0,0,0,0x0000000002000006,0); + +DELETE FROM spell_affect WHERE entry IN (36563); +INSERT INTO spell_affect VALUES + (36563,1,0,0,0,0,0,0x0000000000000204,0), + (36563,2,0,0,0,0,0,0x0000000000000100,0); + +DELETE FROM spell_affect WHERE entry IN (16513,16514,16515,16719,16720); +INSERT INTO spell_affect VALUES + (16513,0,0,0,0,0,0,0x000000080001E000,0), + (16513,1,0,0,0,0,0,0x000000000001E000,0), + (16513,2,0,0,0,0,0,0x000000000001E000,0), + (16514,0,0,0,0,0,0,0x000000080001E000,0), + (16514,1,0,0,0,0,0,0x000000000001E000,0), + (16514,2,0,0,0,0,0,0x000000000001E000,0), + (16515,0,0,0,0,0,0,0x000000080001E000,0), + (16515,1,0,0,0,0,0,0x000000000001E000,0), + (16515,2,0,0,0,0,0,0x000000000001E000,0), + (16719,0,0,0,0,0,0,0x000000080001E000,0), + (16719,1,0,0,0,0,0,0x000000000001E000,0), + (16719,2,0,0,0,0,0,0x000000000001E000,0), + (16720,0,0,0,0,0,0,0x000000080001E000,0), + (16720,1,0,0,0,0,0,0x000000000001E000,0), + (16720,2,0,0,0,0,0,0x000000000001E000,0); + diff --git a/sql/updates/0.10/5374_mangos_spell_affect.sql b/sql/updates/0.10/5374_mangos_spell_affect.sql new file mode 100644 index 00000000000..77bb74fca5b --- /dev/null +++ b/sql/updates/0.10/5374_mangos_spell_affect.sql @@ -0,0 +1,4 @@ +DELETE FROM spell_affect WHERE entry IN (29888,29889); +INSERT INTO spell_affect VALUES + (29888,0,0,0,0,0,0,0x0000000040000000,0), + (29889,0,0,0,0,0,0,0x0000000040000000,0); diff --git a/sql/updates/0.10/5378_mangos_spell_proc_event.sql b/sql/updates/0.10/5378_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..2d85c46a9f9 --- /dev/null +++ b/sql/updates/0.10/5378_mangos_spell_proc_event.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (34580); +INSERT INTO `spell_proc_event` VALUES +(34580,0,0,0,0,0x0000000000000000,0x00000001,2); diff --git a/sql/updates/0.10/5379_mangos_spell_proc_event.sql b/sql/updates/0.10/5379_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..16aa74f8ca6 --- /dev/null +++ b/sql/updates/0.10/5379_mangos_spell_proc_event.sql @@ -0,0 +1 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (34580); diff --git a/sql/updates/0.10/5402_mangos_spell_proc_event.sql b/sql/updates/0.10/5402_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..eee94f6a3d6 --- /dev/null +++ b/sql/updates/0.10/5402_mangos_spell_proc_event.sql @@ -0,0 +1,8 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (41635,33280,35092,35093,35094); +INSERT INTO `spell_proc_event`VALUES +(41635,0,0,0,0,0x0000000000000000,0x00008000,0), +(33280,0,0,0,0,0x0000000000000000,0x00008000,0), +(35092,0,0,0,0,0x0000000000000000,0x00008000,0), +(35093,0,0,0,0,0x0000000000000000,0x00008000,0), +(35094,0,0,0,0,0x0000000000000000,0x00008000,0); + diff --git a/sql/updates/0.10/5408_characters_mail_items.sql b/sql/updates/0.10/5408_characters_mail_items.sql new file mode 100644 index 00000000000..cd0867c730e --- /dev/null +++ b/sql/updates/0.10/5408_characters_mail_items.sql @@ -0,0 +1,8 @@ +ALTER TABLE mail_items + ADD COLUMN receiver int(11) unsigned NOT NULL default 0 COMMENT 'Character Global Unique Identifier' AFTER item_template; + +UPDATE mail_items, mail + SET mail_items.receiver = mail.receiver WHERE mail_items.mail_id = mail.id; + +DELETE FROM item_instance WHERE guid IN (SELECT item_guid FROM mail_items WHERE mail_items.receiver = 0); +DELETE FROM mail_items WHERE mail_items.receiver = 0; diff --git a/sql/updates/0.10/5411_mangos_spell_affect.sql b/sql/updates/0.10/5411_mangos_spell_affect.sql new file mode 100644 index 00000000000..71409d0ee50 --- /dev/null +++ b/sql/updates/0.10/5411_mangos_spell_affect.sql @@ -0,0 +1,5 @@ +DELETE FROM spell_affect WHERE `entry` IN (33167, 33171, 33172); +INSERT INTO spell_affect VALUES + (33167,0,0,0,0,0,0,0x0000008100000000,0), + (33171,0,0,0,0,0,0,0x0000008100000000,0), + (33172,0,0,0,0,0,0,0x0000008100000000,0); diff --git a/sql/updates/0.10/5419_mangos_spell_affect.sql b/sql/updates/0.10/5419_mangos_spell_affect.sql new file mode 100644 index 00000000000..942e4a5f28f --- /dev/null +++ b/sql/updates/0.10/5419_mangos_spell_affect.sql @@ -0,0 +1,8 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (29723,29724,29725); +INSERT INTO `spell_affect` VALUES + (29723,0,0,0,0,0,0,0x0000000800002010,0), + (29723,1,0,0,0,0,0,0x0000000800002010,0), + (29724,0,0,0,0,0,0,0x0000000800002010,0), + (29724,1,0,0,0,0,0,0x0000000800002010,0), + (29725,0,0,0,0,0,0,0x0000000800002010,0), + (29725,1,0,0,0,0,0,0x0000000800002010,0); diff --git a/sql/updates/0.10/5420_characters_mail_items.sql b/sql/updates/0.10/5420_characters_mail_items.sql new file mode 100644 index 00000000000..f4df8f2a30f --- /dev/null +++ b/sql/updates/0.10/5420_characters_mail_items.sql @@ -0,0 +1 @@ +ALTER TABLE `mail_items` ADD KEY `idx_receiver` (`receiver`); \ No newline at end of file diff --git a/sql/updates/0.10/5422_mangos_spell_proc_event.sql b/sql/updates/0.10/5422_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..8a178935878 --- /dev/null +++ b/sql/updates/0.10/5422_mangos_spell_proc_event.sql @@ -0,0 +1,9 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 15600 ); +INSERT INTO `spell_proc_event` VALUES +(15600,0,0,0,0,0x0000000000000000,0x00000001,0.6); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (33881,33882,33883); +INSERT INTO `spell_proc_event` VALUES +(33881,0,0,0,0,0x0000000000000000,0x00842000,0), +(33882,0,0,0,0,0x0000000000000000,0x00842000,0), +(33883,0,0,0,0,0x0000000000000000,0x00842000,0); diff --git a/sql/updates/0.10/5441_characters_petition_petition_sign.sql b/sql/updates/0.10/5441_characters_petition_petition_sign.sql new file mode 100644 index 00000000000..214e3b7a389 --- /dev/null +++ b/sql/updates/0.10/5441_characters_petition_petition_sign.sql @@ -0,0 +1,5 @@ +ALTER TABLE `petition` +DROP PRIMARY KEY, +ADD PRIMARY KEY (`ownerguid`, `type`); + +ALTER TABLE `petition_sign` ADD COLUMN `type` int(10) UNSIGNED NOT NULL DEFAULT 0; diff --git a/sql/updates/0.10/5443_mangos_item_template.sql b/sql/updates/0.10/5443_mangos_item_template.sql new file mode 100644 index 00000000000..22502afb2c2 --- /dev/null +++ b/sql/updates/0.10/5443_mangos_item_template.sql @@ -0,0 +1,2 @@ +ALTER TABLE item_template + CHANGE COLUMN RequiredArenaRank CondExtendedCost int(10) unsigned NOT NULL default '0'; diff --git a/sql/updates/0.10/5445_mangos_spell_affect.sql b/sql/updates/0.10/5445_mangos_spell_affect.sql new file mode 100644 index 00000000000..83bef662b2a --- /dev/null +++ b/sql/updates/0.10/5445_mangos_spell_affect.sql @@ -0,0 +1,7 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (17815,17833,17834,17835,17836); +INSERT INTO `spell_affect` VALUES + (17815,0,0,0,0,0,0,0x0000000000000004,0), + (17833,0,0,0,0,0,0,0x0000000000000004,0), + (17834,0,0,0,0,0,0,0x0000000000000004,0), + (17835,0,0,0,0,0,0,0x0000000000000004,0), + (17836,0,0,0,0,0,0,0x0000000000000004,0); diff --git a/sql/updates/0.10/5446_mangos_creature_template.sql b/sql/updates/0.10/5446_mangos_creature_template.sql new file mode 100644 index 00000000000..1fff19e6411 --- /dev/null +++ b/sql/updates/0.10/5446_mangos_creature_template.sql @@ -0,0 +1,2 @@ +ALTER TABLE `creature_template` + ADD COLUMN IconName char(100) default NULL AFTER subname; diff --git a/sql/updates/0.10/5451_characters_petition_petition_sign.sql b/sql/updates/0.10/5451_characters_petition_petition_sign.sql new file mode 100644 index 00000000000..f16b07cd0a5 --- /dev/null +++ b/sql/updates/0.10/5451_characters_petition_petition_sign.sql @@ -0,0 +1,2 @@ +ALTER TABLE `petition` ENGINE = InnoDB; +ALTER TABLE `petition_sign` ENGINE = InnoDB; diff --git a/sql/updates/0.10/5457_realmd_account.sql b/sql/updates/0.10/5457_realmd_account.sql new file mode 100644 index 00000000000..9841ea54e7c --- /dev/null +++ b/sql/updates/0.10/5457_realmd_account.sql @@ -0,0 +1 @@ +UPDATE account SET username = UPPER(username); \ No newline at end of file diff --git a/sql/updates/0.10/5460_mangos_spell_proc_event.sql b/sql/updates/0.10/5460_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..2482ab292b0 --- /dev/null +++ b/sql/updates/0.10/5460_mangos_spell_proc_event.sql @@ -0,0 +1,11 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 37239 ); +INSERT INTO `spell_proc_event` VALUES +(37239,0,0,0,0,0x0000000000000000,0x00000001,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 43737 ); +INSERT INTO `spell_proc_event` VALUES +(43737,0,0,0,7,0x0000044000000000,0x00000001,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 43739 ); +INSERT INTO `spell_proc_event` VALUES +(43739,0,0,0,7,0x0000000000000002,0x00020000,0); diff --git a/sql/updates/0.10/5462_mangos_spell_affect.sql b/sql/updates/0.10/5462_mangos_spell_affect.sql new file mode 100644 index 00000000000..a0395be5780 --- /dev/null +++ b/sql/updates/0.10/5462_mangos_spell_affect.sql @@ -0,0 +1,144 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (17778,17779,17780,17781,17782); +INSERT INTO `spell_affect` VALUES + (17778,0,0,0,0,0,0,0x000010C0000003E5,0), + (17779,0,0,0,0,0,0,0x000010C0000003E5,0), + (17780,0,0,0,0,0,0,0x000010C0000003E5,0), + (17781,0,0,0,0,0,0,0x000010C0000003E5,0), + (17782,0,0,0,0,0,0,0x000010C0000003E5,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (23555); +INSERT INTO `spell_affect` VALUES + (23555,0,0,0,0,0,0,0x000010C0000003E5,0); + + +DELETE FROM `spell_affect` WHERE `entry` IN (18130,18131,18132,18133,18134); +INSERT INTO `spell_affect` VALUES + (18130,0,0,0,0,0,0,0x000010C0000003E5,0), + (18131,0,0,0,0,0,0,0x000010C0000003E5,0), + (18132,0,0,0,0,0,0,0x000010C0000003E5,0), + (18133,0,0,0,0,0,0,0x000010C0000003E5,0), + (18134,0,0,0,0,0,0,0x000010C0000003E5,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (18135,18136); +INSERT INTO `spell_affect` VALUES + (18135,0,0,0,0,0,0,0x000010C0000003E5,0), + (18136,0,0,0,0,0,0,0x000010C0000003E5,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (17959); +INSERT INTO `spell_affect` VALUES + (17959,0,0,0,0,0,0,0x000010C0000003E5,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (17917,17918); +INSERT INTO `spell_affect` VALUES + (17917,0,0,0,0,0,0,0x000010C0000003A5,0), + (17917,1,0,0,0,0,0,0x000010C0000003E5,0), + (17918,0,0,0,0,0,0,0x000010C0000003A5,0), + (17918,1,0,0,0,0,0,0x000010C0000003E5,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (30060,30061,30062,30063,30064); +INSERT INTO `spell_affect` VALUES + (30060,0,0,0,0,0,0,0x0000001000000402,0), + (30060,1,0,0,0,0,0,0x0000001000000402,0), + (30060,2,0,0,0,0,0,0x0000871B804CC41A,0), + (30061,0,0,0,0,0,0,0x0000001000000402,0), + (30061,1,0,0,0,0,0,0x0000001000000402,0), + (30061,2,0,0,0,0,0,0x0000871B804CC41A,0), + (30062,0,0,0,0,0,0,0x0000001000000402,0), + (30062,1,0,0,0,0,0,0x0000001000000402,0), + (30062,2,0,0,0,0,0,0x0000871B804CC41A,0), + (30063,0,0,0,0,0,0,0x0000001000000402,0), + (30063,1,0,0,0,0,0,0x0000001000000402,0), + (30063,2,0,0,0,0,0,0x0000871B804CC41A,0), + (30064,0,0,0,0,0,0,0x0000001000000402,0), + (30064,1,0,0,0,0,0,0x0000001000000402,0), + (30064,2,0,0,0,0,0,0x0000871B804CC41A,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (18218,18219); +INSERT INTO `spell_affect` VALUES + (18218,0,0,0,0,0,0,0x000007138048C41A,0), + (18219,0,0,0,0,0,0,0x000007138048C41A,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (30085,30086); +INSERT INTO `spell_affect` VALUES + (30085,0,0,0,0,0,0,0x0000071B804CC41A,0), + (30085,1,0,0,0,0,0,0x0000000000000400,0), + (30085,2,0,0,0,0,0,0x0000000000000002,0), + (30086,0,0,0,0,0,0,0x0000071B804CC41A,0), + (30086,1,0,0,0,0,0,0x0000000000000400,0), + (30086,2,0,0,0,0,0,0x0000000000000002,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (18174,18175,18176,18177,18178); +INSERT INTO `spell_affect` VALUES + (18174,0,0,0,0,0,0,0x0000071B804CC41A,0), + (18175,0,0,0,0,0,0,0x0000071B804CC41A,0), + (18176,0,0,0,0,0,0,0x0000071B804CC41A,0), + (18177,0,0,0,0,0,0,0x0000071B804CC41A,0), + (18178,0,0,0,0,0,0,0x0000071B804CC41A,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (30143,30144,30145); +INSERT INTO `spell_affect` VALUES + (30143,0,0,0,0,0,0,0x0000002000000000,0), + (30144,0,0,0,0,0,0,0x0000002000000000,0), + (30145,0,0,0,0,0,0,0x0000002000000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (30319,30320,30321); +INSERT INTO `spell_affect` VALUES + (30319,1,0,0,0,0,0,0x0000400000000000,0), + (30320,1,0,0,0,0,0,0x0000400000000000,0), + (30321,1,0,0,0,0,0,0x0000400000000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (33063); +INSERT INTO `spell_affect` VALUES + (33063,0,0,0,0,0,0,0x0000040000000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (30242,30245,30246,30247,30248); +INSERT INTO `spell_affect` VALUES + (30242,0,0,0,0,0,0,0x0000200000000000,0), + (30245,0,0,0,0,0,0,0x0000200000000000,0), + (30246,0,0,0,0,0,0,0x0000200000000000,0), + (30247,0,0,0,0,0,0,0x0000200000000000,0), + (30248,0,0,0,0,0,0,0x0000200000000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (32477,32483,32484); +INSERT INTO `spell_affect` VALUES + (32477,0,0,0,0,0,0,0x0000020000000000,0), + (32483,0,0,0,0,0,0,0x0000020000000000,0), + (32484,0,0,0,0,0,0,0x0000020000000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (30251,30256); +INSERT INTO `spell_affect` VALUES + (30251,0,0,0,0,0,0,0x000010C000000125,0), + (30256,0,0,0,0,0,0,0x000010C000000125,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (17954,17955,17956,17957,17958); +INSERT INTO `spell_affect` VALUES + (17954,0,0,0,0,0,0,0x000000C000001364,0), + (17954,1,0,0,0,0,0,0x000000C000001364,0), + (17955,0,0,0,0,0,0,0x000000C000001364,0), + (17955,1,0,0,0,0,0,0x000000C000001364,0), + (17956,0,0,0,0,0,0,0x000000C000001364,0), + (17956,1,0,0,0,0,0,0x000000C000001364,0), + (17957,0,0,0,0,0,0,0x000000C000001364,0), + (17957,1,0,0,0,0,0,0x000000C000001364,0), + (17958,0,0,0,0,0,0,0x000000C000001364,0), + (17958,1,0,0,0,0,0,0x000000C000001364,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (18213,18372); +INSERT INTO `spell_affect` VALUES + (18213,0,0,0,0,0,0,0x0000000000004000,0), + (18213,1,0,0,0,0,0,0x0000871B804CC41A,0), + (18372,0,0,0,0,0,0,0x0000000000004000,0), + (18372,1,0,0,0,0,0,0x0000871B804CC41A,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (18271,18272,18273,18274,18275); +INSERT INTO `spell_affect` VALUES + (18271,0,0,0,0,0,0,0x000011130008A48B,0), + (18271,1,0,0,0,0,0,0x000011130008A48B,0), + (18272,0,0,0,0,0,0,0x000011130008A48B,0), + (18272,1,0,0,0,0,0,0x000011130008A48B,0), + (18273,0,0,0,0,0,0,0x000011130008A48B,0), + (18273,1,0,0,0,0,0,0x000011130008A48B,0), + (18274,0,0,0,0,0,0,0x000011130008A48B,0), + (18274,1,0,0,0,0,0,0x000011130008A48B,0), + (18275,0,0,0,0,0,0,0x000011130008A48B,0), + (18275,1,0,0,0,0,0,0x000011130008A48B,0); diff --git a/sql/updates/0.10/5463_mangos_command.sql b/sql/updates/0.10/5463_mangos_command.sql new file mode 100644 index 00000000000..66ce5617e7a --- /dev/null +++ b/sql/updates/0.10/5463_mangos_command.sql @@ -0,0 +1,2 @@ +DELETE FROM `command` WHERE `name` = 'cshutdown'; +UPDATE `command` SET `help`='Syntax: .shutdown seconds\r\n\r\nShut the server down after given seconds or cancel the shutdown if cancel value is used.' WHERE `name` = 'shutdown'; diff --git a/sql/updates/0.10/5466_mangos_spell_affect.sql b/sql/updates/0.10/5466_mangos_spell_affect.sql new file mode 100644 index 00000000000..f23e2728909 --- /dev/null +++ b/sql/updates/0.10/5466_mangos_spell_affect.sql @@ -0,0 +1,67 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (12295,12676,12677); +INSERT INTO `spell_affect` VALUES + (12295,1,0,0,0,0,0,0x0000000002000000,0), + (12295,2,0,0,0,0,0,0x0000040000000000,0), + (12676,1,0,0,0,0,0,0x0000000002000000,0), + (12676,2,0,0,0,0,0,0x0000040000000000,0), + (12677,1,0,0,0,0,0,0x0000000002000000,0), + (12677,2,0,0,0,0,0,0x0000040000000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (12308,12810,12811); +INSERT INTO `spell_affect` VALUES + (12308,0,0,0,0,0,0,0x0000000000004000,0), + (12810,0,0,0,0,0,0,0x0000000000004000,0), + (12811,0,0,0,0,0,0,0x0000000000004000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (13981,14066); +INSERT INTO `spell_affect` VALUES + (13981,0,0,0,0,0,0,0x0000000001000000,0), + (13981,1,0,0,0,0,0,0x0000000000000800,0), + (14066,0,0,0,0,0,0,0x0000000001000000,0), + (14066,1,0,0,0,0,0,0x0000000000000800,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (14523,14784,14785,14786,14787); +INSERT INTO `spell_affect` VALUES + (14523,1,0,0,0,0,0,0x000000208030016B,0), + (14523,2,0,0,0,0,0,0x000000208030016B,0), + (14784,1,0,0,0,0,0,0x000000208030016B,0), + (14784,2,0,0,0,0,0,0x000000208030016B,0), + (14785,1,0,0,0,0,0,0x000000208030016B,0), + (14785,2,0,0,0,0,0,0x000000208030016B,0), + (14786,1,0,0,0,0,0,0x000000208030016B,0), + (14786,2,0,0,0,0,0,0x000000208030016B,0), + (14787,1,0,0,0,0,0,0x000000208030016B,0), + (14787,2,0,0,0,0,0,0x000000208030016B,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (29759,29760,29761,29762,29763); +INSERT INTO `spell_affect` VALUES + (29759,1,0,0,0,0,0,0x0000075D6E6ECEEF,0), + (29760,1,0,0,0,0,0,0x0000075D6E6ECEEF,0), + (29761,1,0,0,0,0,0,0x0000075D6E6ECEEF,0), + (29762,1,0,0,0,0,0,0x0000075D6E6ECEEF,0), + (29763,1,0,0,0,0,0,0x0000075D6E6ECEEF,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (34466,34467,34468,34469,34470); +INSERT INTO `spell_affect` VALUES + (34466,1,0,0,0,0,0,0x0000001000000000,0), + (34467,1,0,0,0,0,0,0x0000001000000000,0), + (34468,1,0,0,0,0,0,0x0000001000000000,0), + (34469,1,0,0,0,0,0,0x0000001000000000,0), + (34470,1,0,0,0,0,0,0x0000001000000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (34318,37209); +INSERT INTO `spell_affect` VALUES + (34318,0,0,0,0,0,0,0x0000000000000400,0), + (34318,1,0,0,0,0,0,0x0000002000000000,0), + (37209,0,0,0,0,0,0,0x0000000000000400,0), + (37209,1,0,0,0,0,0,0x0000002000000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (44301,44302); +INSERT INTO `spell_affect` VALUES + (44301,0,0,0,0,0,0,0x0000000001000000,0), + (44302,0,0,0,0,0,0,0x0000000001000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (37424); +INSERT INTO `spell_affect` VALUES + (37424,0,0,0,0,0,0,0x0000000000008000,0); + diff --git a/sql/updates/0.10/5471_mangos_spell_affect.sql b/sql/updates/0.10/5471_mangos_spell_affect.sql new file mode 100644 index 00000000000..ae3d5275c50 --- /dev/null +++ b/sql/updates/0.10/5471_mangos_spell_affect.sql @@ -0,0 +1,70 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (35578,35581); +INSERT INTO `spell_affect` VALUES + (35578,0,0,0,0,0,0,0x0000000028E212F7,0), + (35581,0,0,0,0,0,0,0x0000000028E212F7,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (23047); +INSERT INTO `spell_affect` VALUES + (23047,0,0,0,0,0,0,0x0000040000000000,0), + (23047,1,0,0,0,0,0,0x0000040000000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (23158); +INSERT INTO `spell_affect` VALUES + (23158,0,0,0,0,0,0,0x0000000000000200,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (23561); +INSERT INTO `spell_affect` VALUES + (23561,0,0,0,0,0,0,0x0000000000004000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (23566); +INSERT INTO `spell_affect` VALUES + (23566,0,0,0,0,0,0,0x0000000000001000,0), + (23566,1,0,0,0,0,0,0x0000000000002000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (24469); +INSERT INTO `spell_affect` VALUES + (24469,0,0,0,0,0,0,0x0000000001000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (26106); +INSERT INTO `spell_affect` VALUES + (26106,0,0,0,0,0,0,0x0000000010000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (26112); +INSERT INTO `spell_affect` VALUES + (26112,0,0,0,0,0,0,0x0000000000000020,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (44300); +INSERT INTO `spell_affect` VALUES + (44300,0,0,0,0,0,0,0x0000800000000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (37763); +INSERT INTO `spell_affect` VALUES + (37763,0,0,0,0,0,0,0x0000800000000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (43725); +INSERT INTO `spell_affect` VALUES + (43725,0,0,0,0,0,0,0x0000001000000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (43736); +INSERT INTO `spell_affect` VALUES + (43736,0,0,0,0,0,0,0x0000000000000010,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (43752); +INSERT INTO `spell_affect` VALUES + (43752,0,0,0,0,0,0,0x0000000000000100,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (44292); +INSERT INTO `spell_affect` VALUES + (44292,0,0,0,0,0,0,0x0000000000001000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (44295); +INSERT INTO `spell_affect` VALUES + (44295,0,0,0,0,0,0,0x0000000090100000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (44296); +INSERT INTO `spell_affect` VALUES + (44296,0,0,0,0,0,0,0x0000000000000001,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (44299); +INSERT INTO `spell_affect` VALUES + (44299,0,0,0,0,0,0,0x0000000000040000,0); diff --git a/sql/updates/0.10/5482_mangos_spell_affect.sql b/sql/updates/0.10/5482_mangos_spell_affect.sql new file mode 100644 index 00000000000..f6a476ad58b --- /dev/null +++ b/sql/updates/0.10/5482_mangos_spell_affect.sql @@ -0,0 +1,5 @@ +ALTER TABLE spell_affect + DROP SpellId, + DROP SchoolMask, + DROP Category, + DROP SkillID; diff --git a/sql/updates/0.10/5491_mangos_player_levelstats.sql b/sql/updates/0.10/5491_mangos_player_levelstats.sql new file mode 100644 index 00000000000..6cf36e5e286 --- /dev/null +++ b/sql/updates/0.10/5491_mangos_player_levelstats.sql @@ -0,0 +1,70 @@ +UPDATE `player_levelstats` SET `basehp` = 20 WHERE `class` = 1 AND `level`=1; +UPDATE `player_levelstats` SET `basehp` = 29 WHERE `class` = 1 AND `level`=2; +UPDATE `player_levelstats` SET `basehp` = 38 WHERE `class` = 1 AND `level`=3; +UPDATE `player_levelstats` SET `basehp` = 47 WHERE `class` = 1 AND `level`=4; +UPDATE `player_levelstats` SET `basehp` = 56 WHERE `class` = 1 AND `level`=5; +UPDATE `player_levelstats` SET `basehp` = 65 WHERE `class` = 1 AND `level`=6; +UPDATE `player_levelstats` SET `basehp` = 74 WHERE `class` = 1 AND `level`=7; +UPDATE `player_levelstats` SET `basehp` = 83 WHERE `class` = 1 AND `level`=8; +UPDATE `player_levelstats` SET `basehp` = 92 WHERE `class` = 1 AND `level`=9; +UPDATE `player_levelstats` SET `basehp` = 101 WHERE `class` = 1 AND `level`=10; +UPDATE `player_levelstats` SET `basehp` = 100 WHERE `class` = 1 AND `level`=11; +UPDATE `player_levelstats` SET `basehp` = 109 WHERE `class` = 1 AND `level`=12; +UPDATE `player_levelstats` SET `basehp` = 118 WHERE `class` = 1 AND `level`=13; +UPDATE `player_levelstats` SET `basehp` = 128 WHERE `class` = 1 AND `level`=14; +UPDATE `player_levelstats` SET `basehp` = 139 WHERE `class` = 1 AND `level`=15; +UPDATE `player_levelstats` SET `basehp` = 151 WHERE `class` = 1 AND `level`=16; +UPDATE `player_levelstats` SET `basehp` = 154 WHERE `class` = 1 AND `level`=17; +UPDATE `player_levelstats` SET `basehp` = 168 WHERE `class` = 1 AND `level`=18; +UPDATE `player_levelstats` SET `basehp` = 183 WHERE `class` = 1 AND `level`=19; +UPDATE `player_levelstats` SET `basehp` = 199 WHERE `class` = 1 AND `level`=20; +UPDATE `player_levelstats` SET `basehp` = 206 WHERE `class` = 1 AND `level`=21; +UPDATE `player_levelstats` SET `basehp` = 224 WHERE `class` = 1 AND `level`=22; +UPDATE `player_levelstats` SET `basehp` = 243 WHERE `class` = 1 AND `level`=23; +UPDATE `player_levelstats` SET `basehp` = 253 WHERE `class` = 1 AND `level`=24; +UPDATE `player_levelstats` SET `basehp` = 274 WHERE `class` = 1 AND `level`=25; +UPDATE `player_levelstats` SET `basehp` = 296 WHERE `class` = 1 AND `level`=26; +UPDATE `player_levelstats` SET `basehp` = 309 WHERE `class` = 1 AND `level`=27; +UPDATE `player_levelstats` SET `basehp` = 333 WHERE `class` = 1 AND `level`=28; +UPDATE `player_levelstats` SET `basehp` = 348 WHERE `class` = 1 AND `level`=29; +UPDATE `player_levelstats` SET `basehp` = 374 WHERE `class` = 1 AND `level`=30; +UPDATE `player_levelstats` SET `basehp` = 401 WHERE `class` = 1 AND `level`=31; +UPDATE `player_levelstats` SET `basehp` = 419 WHERE `class` = 1 AND `level`=32; +UPDATE `player_levelstats` SET `basehp` = 448 WHERE `class` = 1 AND `level`=33; +UPDATE `player_levelstats` SET `basehp` = 468 WHERE `class` = 1 AND `level`=34; +UPDATE `player_levelstats` SET `basehp` = 499 WHERE `class` = 1 AND `level`=35; +UPDATE `player_levelstats` SET `basehp` = 521 WHERE `class` = 1 AND `level`=36; +UPDATE `player_levelstats` SET `basehp` = 545 WHERE `class` = 1 AND `level`=37; +UPDATE `player_levelstats` SET `basehp` = 581 WHERE `class` = 1 AND `level`=38; +UPDATE `player_levelstats` SET `basehp` = 609 WHERE `class` = 1 AND `level`=39; +UPDATE `player_levelstats` SET `basehp` = 649 WHERE `class` = 1 AND `level`=40; +UPDATE `player_levelstats` SET `basehp` = 681 WHERE `class` = 1 AND `level`=41; +UPDATE `player_levelstats` SET `basehp` = 715 WHERE `class` = 1 AND `level`=42; +UPDATE `player_levelstats` SET `basehp` = 761 WHERE `class` = 1 AND `level`=43; +UPDATE `player_levelstats` SET `basehp` = 799 WHERE `class` = 1 AND `level`=44; +UPDATE `player_levelstats` SET `basehp` = 839 WHERE `class` = 1 AND `level`=45; +UPDATE `player_levelstats` SET `basehp` = 881 WHERE `class` = 1 AND `level`=46; +UPDATE `player_levelstats` SET `basehp` = 935 WHERE `class` = 1 AND `level`=47; +UPDATE `player_levelstats` SET `basehp` = 981 WHERE `class` = 1 AND `level`=48; +UPDATE `player_levelstats` SET `basehp` = 1029 WHERE `class` = 1 AND `level`=49; +UPDATE `player_levelstats` SET `basehp` = 1079 WHERE `class` = 1 AND `level`=50; +UPDATE `player_levelstats` SET `basehp` = 1131 WHERE `class` = 1 AND `level`=51; +UPDATE `player_levelstats` SET `basehp` = 1185 WHERE `class` = 1 AND `level`=52; +UPDATE `player_levelstats` SET `basehp` = 1241 WHERE `class` = 1 AND `level`=53; +UPDATE `player_levelstats` SET `basehp` = 1299 WHERE `class` = 1 AND `level`=54; +UPDATE `player_levelstats` SET `basehp` = 1359 WHERE `class` = 1 AND `level`=55; +UPDATE `player_levelstats` SET `basehp` = 1421 WHERE `class` = 1 AND `level`=56; +UPDATE `player_levelstats` SET `basehp` = 1485 WHERE `class` = 1 AND `level`=57; +UPDATE `player_levelstats` SET `basehp` = 1551 WHERE `class` = 1 AND `level`=58; +UPDATE `player_levelstats` SET `basehp` = 1619 WHERE `class` = 1 AND `level`=59; +UPDATE `player_levelstats` SET `basehp` = 1689 WHERE `class` = 1 AND `level`=60; +UPDATE `player_levelstats` SET `basehp` = 1902 WHERE `class` = 1 AND `level`=61; +UPDATE `player_levelstats` SET `basehp` = 2129 WHERE `class` = 1 AND `level`=62; +UPDATE `player_levelstats` SET `basehp` = 2357 WHERE `class` = 1 AND `level`=63; +UPDATE `player_levelstats` SET `basehp` = 2612 WHERE `class` = 1 AND `level`=64; +UPDATE `player_levelstats` SET `basehp` = 2883 WHERE `class` = 1 AND `level`=65; +UPDATE `player_levelstats` SET `basehp` = 3169 WHERE `class` = 1 AND `level`=66; +UPDATE `player_levelstats` SET `basehp` = 3455 WHERE `class` = 1 AND `level`=67; +UPDATE `player_levelstats` SET `basehp` = 3774 WHERE `class` = 1 AND `level`=68; +UPDATE `player_levelstats` SET `basehp` = 4109 WHERE `class` = 1 AND `level`=69; +UPDATE `player_levelstats` SET `basehp` = 4444 WHERE `class` = 1 AND `level`=70; diff --git a/sql/updates/0.10/5492_mangos_player_levelstats.sql b/sql/updates/0.10/5492_mangos_player_levelstats.sql new file mode 100644 index 00000000000..7a8220abdf3 --- /dev/null +++ b/sql/updates/0.10/5492_mangos_player_levelstats.sql @@ -0,0 +1,70 @@ +UPDATE `player_levelstats` SET `basehp` = 28, `basemana` = 60 WHERE `class` = 2 AND `level`=1; +UPDATE `player_levelstats` SET `basehp` = 36, `basemana` = 78 WHERE `class` = 2 AND `level`=2; +UPDATE `player_levelstats` SET `basehp` = 44, `basemana` = 98 WHERE `class` = 2 AND `level`=3; +UPDATE `player_levelstats` SET `basehp` = 52, `basemana` = 104 WHERE `class` = 2 AND `level`=4; +UPDATE `player_levelstats` SET `basehp` = 60, `basemana` = 111 WHERE `class` = 2 AND `level`=5; +UPDATE `player_levelstats` SET `basehp` = 68, `basemana` = 134 WHERE `class` = 2 AND `level`=6; +UPDATE `player_levelstats` SET `basehp` = 76, `basemana` = 143 WHERE `class` = 2 AND `level`=7; +UPDATE `player_levelstats` SET `basehp` = 84, `basemana` = 153 WHERE `class` = 2 AND `level`=8; +UPDATE `player_levelstats` SET `basehp` = 92, `basemana` = 179 WHERE `class` = 2 AND `level`=9; +UPDATE `player_levelstats` SET `basehp` = 100, `basemana` = 192 WHERE `class` = 2 AND `level`=10; +UPDATE `player_levelstats` SET `basehp` = 108, `basemana` = 205 WHERE `class` = 2 AND `level`=11; +UPDATE `player_levelstats` SET `basehp` = 116, `basemana` = 219 WHERE `class` = 2 AND `level`=12; +UPDATE `player_levelstats` SET `basehp` = 124, `basemana` = 249 WHERE `class` = 2 AND `level`=13; +UPDATE `player_levelstats` SET `basehp` = 132, `basemana` = 265 WHERE `class` = 2 AND `level`=14; +UPDATE `player_levelstats` SET `basehp` = 131, `basemana` = 282 WHERE `class` = 2 AND `level`=15; +UPDATE `player_levelstats` SET `basehp` = 141, `basemana` = 315 WHERE `class` = 2 AND `level`=16; +UPDATE `player_levelstats` SET `basehp` = 152, `basemana` = 334 WHERE `class` = 2 AND `level`=17; +UPDATE `player_levelstats` SET `basehp` = 164, `basemana` = 354 WHERE `class` = 2 AND `level`=18; +UPDATE `player_levelstats` SET `basehp` = 177, `basemana` = 390 WHERE `class` = 2 AND `level`=19; +UPDATE `player_levelstats` SET `basehp` = 191, `basemana` = 412 WHERE `class` = 2 AND `level`=20; +UPDATE `player_levelstats` SET `basehp` = 206, `basemana` = 435 WHERE `class` = 2 AND `level`=21; +UPDATE `player_levelstats` SET `basehp` = 222, `basemana` = 459 WHERE `class` = 2 AND `level`=22; +UPDATE `player_levelstats` SET `basehp` = 239, `basemana` = 499 WHERE `class` = 2 AND `level`=23; +UPDATE `player_levelstats` SET `basehp` = 247, `basemana` = 525 WHERE `class` = 2 AND `level`=24; +UPDATE `player_levelstats` SET `basehp` = 266, `basemana` = 552 WHERE `class` = 2 AND `level`=25; +UPDATE `player_levelstats` SET `basehp` = 286, `basemana` = 579 WHERE `class` = 2 AND `level`=26; +UPDATE `player_levelstats` SET `basehp` = 307, `basemana` = 621 WHERE `class` = 2 AND `level`=27; +UPDATE `player_levelstats` SET `basehp` = 329, `basemana` = 648 WHERE `class` = 2 AND `level`=28; +UPDATE `player_levelstats` SET `basehp` = 342, `basemana` = 675 WHERE `class` = 2 AND `level`=29; +UPDATE `player_levelstats` SET `basehp` = 366, `basemana` = 702 WHERE `class` = 2 AND `level`=30; +UPDATE `player_levelstats` SET `basehp` = 391, `basemana` = 729 WHERE `class` = 2 AND `level`=31; +UPDATE `player_levelstats` SET `basehp` = 407, `basemana` = 756 WHERE `class` = 2 AND `level`=32; +UPDATE `player_levelstats` SET `basehp` = 434, `basemana` = 798 WHERE `class` = 2 AND `level`=33; +UPDATE `player_levelstats` SET `basehp` = 462, `basemana` = 825 WHERE `class` = 2 AND `level`=34; +UPDATE `player_levelstats` SET `basehp` = 481, `basemana` = 852 WHERE `class` = 2 AND `level`=35; +UPDATE `player_levelstats` SET `basehp` = 511, `basemana` = 879 WHERE `class` = 2 AND `level`=36; +UPDATE `player_levelstats` SET `basehp` = 542, `basemana` = 906 WHERE `class` = 2 AND `level`=37; +UPDATE `player_levelstats` SET `basehp` = 564, `basemana` = 933 WHERE `class` = 2 AND `level`=38; +UPDATE `player_levelstats` SET `basehp` = 597, `basemana` = 960 WHERE `class` = 2 AND `level`=39; +UPDATE `player_levelstats` SET `basehp` = 621, `basemana` = 987 WHERE `class` = 2 AND `level`=40; +UPDATE `player_levelstats` SET `basehp` = 656, `basemana` =1014 WHERE `class` = 2 AND `level`=41; +UPDATE `player_levelstats` SET `basehp` = 682, `basemana` =1041 WHERE `class` = 2 AND `level`=42; +UPDATE `player_levelstats` SET `basehp` = 719, `basemana` =1068 WHERE `class` = 2 AND `level`=43; +UPDATE `player_levelstats` SET `basehp` = 747, `basemana` =1110 WHERE `class` = 2 AND `level`=44; +UPDATE `player_levelstats` SET `basehp` = 786, `basemana` =1137 WHERE `class` = 2 AND `level`=45; +UPDATE `player_levelstats` SET `basehp` = 816, `basemana` =1164 WHERE `class` = 2 AND `level`=46; +UPDATE `player_levelstats` SET `basehp` = 857, `basemana` =1176 WHERE `class` = 2 AND `level`=47; +UPDATE `player_levelstats` SET `basehp` = 889, `basemana` =1203 WHERE `class` = 2 AND `level`=48; +UPDATE `player_levelstats` SET `basehp` = 922, `basemana` =1230 WHERE `class` = 2 AND `level`=49; +UPDATE `player_levelstats` SET `basehp` = 966, `basemana` =1257 WHERE `class` = 2 AND `level`=50; +UPDATE `player_levelstats` SET `basehp` =1001, `basemana` =1284 WHERE `class` = 2 AND `level`=51; +UPDATE `player_levelstats` SET `basehp` =1037, `basemana` =1311 WHERE `class` = 2 AND `level`=52; +UPDATE `player_levelstats` SET `basehp` =1084, `basemana` =1338 WHERE `class` = 2 AND `level`=53; +UPDATE `player_levelstats` SET `basehp` =1122, `basemana` =1365 WHERE `class` = 2 AND `level`=54; +UPDATE `player_levelstats` SET `basehp` =1161, `basemana` =1392 WHERE `class` = 2 AND `level`=55; +UPDATE `player_levelstats` SET `basehp` =1201, `basemana` =1419 WHERE `class` = 2 AND `level`=56; +UPDATE `player_levelstats` SET `basehp` =1252, `basemana` =1446 WHERE `class` = 2 AND `level`=57; +UPDATE `player_levelstats` SET `basehp` =1294, `basemana` =1458 WHERE `class` = 2 AND `level`=58; +UPDATE `player_levelstats` SET `basehp` =1337, `basemana` =1485 WHERE `class` = 2 AND `level`=59; +UPDATE `player_levelstats` SET `basehp` =1381, `basemana` =1512 WHERE `class` = 2 AND `level`=60; +UPDATE `player_levelstats` SET `basehp` =1540, `basemana` =1656 WHERE `class` = 2 AND `level`=61; +UPDATE `player_levelstats` SET `basehp` =1708, `basemana` =1800 WHERE `class` = 2 AND `level`=62; +UPDATE `player_levelstats` SET `basehp` =1884, `basemana` =1944 WHERE `class` = 2 AND `level`=63; +UPDATE `player_levelstats` SET `basehp` =2068, `basemana` =2088 WHERE `class` = 2 AND `level`=64; +UPDATE `player_levelstats` SET `basehp` =2262, `basemana` =2232 WHERE `class` = 2 AND `level`=65; +UPDATE `player_levelstats` SET `basehp` =2466, `basemana` =2377 WHERE `class` = 2 AND `level`=66; +UPDATE `player_levelstats` SET `basehp` =2679, `basemana` =2521 WHERE `class` = 2 AND `level`=67; +UPDATE `player_levelstats` SET `basehp` =2901, `basemana` =2665 WHERE `class` = 2 AND `level`=68; +UPDATE `player_levelstats` SET `basehp` =3134, `basemana` =2809 WHERE `class` = 2 AND `level`=69; +UPDATE `player_levelstats` SET `basehp` =3377, `basemana` =2953 WHERE `class` = 2 AND `level`=70; diff --git a/sql/updates/0.10/5498_mangos_spell_affect.sql b/sql/updates/0.10/5498_mangos_spell_affect.sql new file mode 100644 index 00000000000..08ac34e931d --- /dev/null +++ b/sql/updates/0.10/5498_mangos_spell_affect.sql @@ -0,0 +1,8 @@ +-- Ice Shards +UPDATE spell_affect SET SpellFamilyMask = SpellFamilyMask | 0x20000 WHERE (entry = 11207) OR (entry = 12672) OR (entry = 15047) OR (entry = 15052) OR (entry = 15053); +-- Piercing Ice +UPDATE spell_affect SET SpellFamilyMask = SpellFamilyMask | 0x20000 WHERE ((entry = 11151) OR (entry = 12952) OR (entry = 12953) OR (entry = 12954) OR (entry = 12957)) AND (effectId = 0); +-- Arctic Reach +UPDATE spell_affect SET SpellFamilyMask = SpellFamilyMask | 0x20000 WHERE ((entry = 16757) OR (entry = 16758)) AND (effectId = 0); +-- Frost Channeling +UPDATE spell_affect SET SpellFamilyMask = SpellFamilyMask | 0x20000 WHERE ((entry = 11160) OR (entry = 12518) OR (entry = 12519)) AND (effectId = 0); \ No newline at end of file diff --git a/sql/updates/0.10/5505_mangos.sql b/sql/updates/0.10/5505_mangos.sql new file mode 100644 index 00000000000..3b8bc6f76bd --- /dev/null +++ b/sql/updates/0.10/5505_mangos.sql @@ -0,0 +1,801 @@ +-- Then update all tables +ALTER TABLE `areatrigger_involvedrelation` + CHANGE COLUMN `id` `id` mediumint unsigned NOT NULL DEFAULT 0 COMMENT 'Identifier', + CHANGE COLUMN `quest` `quest` mediumint unsigned NOT NULL DEFAULT 0 COMMENT 'Quest Identifier'; +ALTER TABLE `areatrigger_tavern` + CHANGE COLUMN `id` `id` mediumint unsigned NOT NULL DEFAULT 0 COMMENT 'Identifier'; +ALTER TABLE `areatrigger_teleport` + CHANGE COLUMN `id` `id` mediumint unsigned NOT NULL DEFAULT 0 COMMENT 'Identifier', + CHANGE COLUMN `required_level` `required_level` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `required_item` `required_item` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `target_map` `target_map` smallint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `battleground_template` + CHANGE COLUMN `id` `id` mediumint unsigned NOT NULL, + CHANGE COLUMN `MinPlayersPerTeam` `MinPlayersPerTeam` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `MaxPlayersPerTeam` `MaxPlayersPerTeam` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `MinLvl` `MinLvl` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `MaxLvl` `MaxLvl` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `AllianceStartLoc` `AllianceStartLoc` mediumint unsigned NOT NULL, + CHANGE COLUMN `HordeStartLoc` `HordeStartLoc` mediumint unsigned NOT NULL; +ALTER TABLE `battlemaster_entry` + CHANGE COLUMN `entry` `entry` mediumint unsigned NOT NULL DEFAULT 0 COMMENT 'Entry of a creature', + CHANGE COLUMN `bg_template` `bg_template` mediumint unsigned NOT NULL DEFAULT 0 COMMENT 'Battleground template id'; +ALTER TABLE `command` + CHANGE COLUMN `security` `security` tinyint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `creature` + CHANGE COLUMN `guid` `guid` integer unsigned NOT NULL auto_increment COMMENT 'Global Unique Identifier', + CHANGE COLUMN `id` `id` mediumint unsigned NOT NULL DEFAULT 0 COMMENT 'Creature Identifier', + CHANGE COLUMN `map` `map` smallint unsigned NOT NULL DEFAULT 0 COMMENT 'Map Identifier', + CHANGE COLUMN `modelid` `modelid` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `equipment_id` `equipment_id` mediumint NOT NULL DEFAULT 0, + CHANGE COLUMN `spawntimesecs` `spawntimesecs` integer unsigned NOT NULL DEFAULT 120, + CHANGE COLUMN `currentwaypoint` `currentwaypoint` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `curhealth` `curhealth` integer unsigned NOT NULL DEFAULT 1, + CHANGE COLUMN `curmana` `curmana` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `DeathState` `DeathState` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `MovementType` `MovementType` tinyint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `creature_addon` + CHANGE COLUMN `guid` `guid` integer NOT NULL DEFAULT 0, + CHANGE COLUMN `mount` `mount` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `bytes0` `bytes0` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `bytes1` `bytes1` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `bytes2` `bytes2` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `emote` `emote` integer unsigned NOT NULL DEFAULT 0; +ALTER TABLE `creature_equip_template` + CHANGE COLUMN `entry` `entry` mediumint unsigned NOT NULL DEFAULT 0 COMMENT 'Unique entry', + CHANGE COLUMN `equipmodel1` `equipmodel1` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `equipmodel2` `equipmodel2` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `equipmodel3` `equipmodel3` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `equipinfo1` `equipinfo1` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `equipinfo2` `equipinfo2` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `equipinfo3` `equipinfo3` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `equipslot1` `equipslot1` integer NOT NULL DEFAULT 0, + CHANGE COLUMN `equipslot2` `equipslot2` integer NOT NULL DEFAULT 0, + CHANGE COLUMN `equipslot3` `equipslot3` integer NOT NULL DEFAULT 0; +ALTER TABLE `creature_involvedrelation` + CHANGE COLUMN `id` `id` mediumint unsigned NOT NULL DEFAULT 0 COMMENT 'Identifier', + CHANGE COLUMN `quest` `quest` mediumint unsigned NOT NULL DEFAULT 0 COMMENT 'Quest Identifier'; +ALTER TABLE `creature_loot_template` + CHANGE COLUMN `entry` `entry` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `item` `item` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `QuestChanceOrGroup` `QuestChanceOrGroup` tinyint NOT NULL DEFAULT 0, + CHANGE COLUMN `mincount` `mincount` tinyint unsigned NOT NULL DEFAULT 1, + CHANGE COLUMN `maxcount` `maxcount` tinyint unsigned NOT NULL DEFAULT 1, + CHANGE COLUMN `freeforall` `freeforall` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `lootcondition` `lootcondition` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `condition_value1` `condition_value1` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `condition_value2` `condition_value2` mediumint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `creature_model_info` + CHANGE COLUMN `modelid` `modelid` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `gender` `gender` tinyint unsigned NOT NULL DEFAULT 2, + CHANGE COLUMN `modelid_other_gender` `modelid_other_gender` mediumint unsigned NOT NULL DEFAULT 0; +UPDATE `creature_movement` SET `orientation`=0 WHERE `orientation` IS NULL; +UPDATE `creature_movement` SET `model1`=0 WHERE `model1` IS NULL; +UPDATE `creature_movement` SET `model2`=0 WHERE `model2` IS NULL; +ALTER TABLE `creature_movement` + CHANGE COLUMN `id` `id` mediumint unsigned NOT NULL DEFAULT 0 COMMENT 'Identifier', + CHANGE COLUMN `point` `point` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `waittime` `waittime` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `aiscript` `aiscript` varchar(128), + CHANGE COLUMN `emote` `emote` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `spell` `spell` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `wpguid` `wpguid` integer NOT NULL DEFAULT 0, + CHANGE COLUMN `orientation` `orientation` float NOT NULL DEFAULT 0, + CHANGE COLUMN `model1` `model1` mediumint NOT NULL DEFAULT 0, + CHANGE COLUMN `model2` `model2` mediumint NOT NULL DEFAULT 0; +ALTER TABLE `creature_onkill_reputation` + CHANGE COLUMN `creature_id` `creature_id` mediumint unsigned NOT NULL DEFAULT 0 COMMENT 'Creature Identifier', + CHANGE COLUMN `RewOnKillRepFaction1` `RewOnKillRepFaction1` smallint NOT NULL DEFAULT 0, + CHANGE COLUMN `RewOnKillRepFaction2` `RewOnKillRepFaction2` smallint NOT NULL DEFAULT 0, + CHANGE COLUMN `MaxStanding1` `MaxStanding1` tinyint NOT NULL DEFAULT 0, + CHANGE COLUMN `IsTeamAward1` `IsTeamAward1` tinyint NOT NULL DEFAULT 0, + CHANGE COLUMN `RewOnKillRepValue1` `RewOnKillRepValue1` mediumint NOT NULL DEFAULT 0, + CHANGE COLUMN `MaxStanding2` `MaxStanding2` tinyint NOT NULL DEFAULT 0, + CHANGE COLUMN `IsTeamAward2` `IsTeamAward2` tinyint NOT NULL DEFAULT 0, + CHANGE COLUMN `RewOnKillRepValue2` `RewOnKillRepValue2` mediumint NOT NULL DEFAULT 0, + CHANGE COLUMN `TeamDependent` `TeamDependent` tinyint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `creature_questrelation` + CHANGE COLUMN `id` `id` mediumint unsigned NOT NULL DEFAULT 0 COMMENT 'Identifier', + CHANGE COLUMN `quest` `quest` mediumint unsigned NOT NULL DEFAULT 0 COMMENT 'Quest Identifier'; +ALTER TABLE `creature_respawn` + CHANGE COLUMN `guid` `guid` integer unsigned NOT NULL DEFAULT 0 COMMENT 'Global Unique Identifier', + CHANGE COLUMN `respawntime` `respawntime` bigint NOT NULL DEFAULT 0, + CHANGE COLUMN `instance` `instance` mediumint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `creature_template` + CHANGE COLUMN `entry` `entry` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `modelid_A` `modelid_A` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `modelid_A2` `modelid_A2` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `modelid_H` `modelid_H` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `modelid_H2` `modelid_H2` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `minlevel` `minlevel` tinyint unsigned NOT NULL DEFAULT 1, + CHANGE COLUMN `maxlevel` `maxlevel` tinyint unsigned NOT NULL DEFAULT 1, + CHANGE COLUMN `minhealth` `minhealth` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `maxhealth` `maxhealth` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `minmana` `minmana` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `maxmana` `maxmana` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `armor` `armor` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `faction_A` `faction_A` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `faction_H` `faction_H` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `npcflag` `npcflag` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `speed` `speed` float NOT NULL DEFAULT 1.0, + CHANGE COLUMN `scale` `scale` float NOT NULL DEFAULT 0, + CHANGE COLUMN `rank` `rank` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `mindmg` `mindmg` float NOT NULL DEFAULT 0, + CHANGE COLUMN `maxdmg` `maxdmg` float NOT NULL DEFAULT 0, + CHANGE COLUMN `dmgschool` `dmgschool` tinyint NOT NULL DEFAULT 0, + CHANGE COLUMN `attackpower` `attackpower` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `baseattacktime` `baseattacktime` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `rangeattacktime` `rangeattacktime` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `flags` `flags` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `dynamicflags` `dynamicflags` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `family` `family` tinyint NOT NULL DEFAULT 0, + CHANGE COLUMN `trainer_type` `trainer_type` tinyint NOT NULL DEFAULT 0, + CHANGE COLUMN `trainer_spell` `trainer_spell` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `class` `class` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `race` `race` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `rangedattackpower` `rangedattackpower` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `type` `type` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `civilian` `civilian` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `flag1` `flag1` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `lootid` `lootid` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `pickpocketloot` `pickpocketloot` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `skinloot` `skinloot` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `resistance1` `resistance1` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `resistance2` `resistance2` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `resistance3` `resistance3` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `resistance4` `resistance4` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `resistance5` `resistance5` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `resistance6` `resistance6` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `spell1` `spell1` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `spell2` `spell2` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `spell3` `spell3` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `spell4` `spell4` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `mingold` `mingold` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `maxgold` `maxgold` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `AIName` `AIName` char(64) NOT NULL DEFAULT '', + CHANGE COLUMN `MovementType` `MovementType` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `InhabitType` `InhabitType` tinyint unsigned NOT NULL DEFAULT 3, + CHANGE COLUMN `RacialLeader` `RacialLeader` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RegenHealth` `RegenHealth` tinyint unsigned NOT NULL DEFAULT 1, + CHANGE COLUMN `equipment_id` `equipment_id` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `mechanic_immune_mask` `mechanic_immune_mask` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ScriptName` `ScriptName` char(64) NOT NULL DEFAULT ''; +ALTER TABLE `creature_template_addon` + CHANGE COLUMN `entry` `entry` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `mount` `mount` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `bytes0` `bytes0` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `bytes1` `bytes1` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `bytes2` `bytes2` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `emote` `emote` mediumint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `disenchant_loot_template` + CHANGE COLUMN `entry` `entry` mediumint unsigned NOT NULL DEFAULT 0 COMMENT 'Recommended id selection: item_level*100 + item_quality', + CHANGE COLUMN `item` `item` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `QuestChanceOrGroup` `QuestChanceOrGroup` tinyint NOT NULL DEFAULT 0, + CHANGE COLUMN `mincount` `mincount` tinyint unsigned NOT NULL DEFAULT 1, + CHANGE COLUMN `maxcount` `maxcount` tinyint unsigned NOT NULL DEFAULT 1, + CHANGE COLUMN `freeforall` `freeforall` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `lootcondition` `lootcondition` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `condition_value1` `condition_value1` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `condition_value2` `condition_value2` mediumint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `event_scripts` + CHANGE COLUMN `id` `id` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `delay` `delay` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `command` `command` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `datalong` `datalong` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `datalong2` `datalong2` integer unsigned NOT NULL DEFAULT 0; +ALTER TABLE `exploration_basexp` + CHANGE COLUMN `level` `level` tinyint NOT NULL DEFAULT 0, + CHANGE COLUMN `basexp` `basexp` mediumint NOT NULL DEFAULT 0; +ALTER TABLE `fishing_loot_template` + CHANGE COLUMN `entry` `entry` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `item` `item` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `QuestChanceOrGroup` `QuestChanceOrGroup` tinyint NOT NULL DEFAULT 0, + CHANGE COLUMN `mincount` `mincount` tinyint unsigned NOT NULL DEFAULT 1, + CHANGE COLUMN `maxcount` `maxcount` tinyint unsigned NOT NULL DEFAULT 1, + CHANGE COLUMN `freeforall` `freeforall` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `lootcondition` `lootcondition` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `condition_value1` `condition_value1` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `condition_value2` `condition_value2` mediumint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `game_event_creature` + CHANGE COLUMN `guid` `guid` integer unsigned NOT NULL, + CHANGE COLUMN `event` `event` smallint NOT NULL DEFAULT 0 COMMENT 'Put negatives values to remove during event'; +ALTER TABLE `game_event_creature_quest` + CHANGE COLUMN `id` `id` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `quest` `quest` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `event` `event` smallint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `game_event_gameobject` + CHANGE COLUMN `guid` `guid` integer unsigned NOT NULL, + CHANGE COLUMN `event` `event` smallint NOT NULL DEFAULT 0 COMMENT 'Put negatives values to remove during event'; +ALTER TABLE `game_event_model_equip` + CHANGE COLUMN `guid` `guid` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `modelid` `modelid` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `equipment_id` `equipment_id` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `event` `event` smallint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `game_graveyard_zone` + CHANGE COLUMN `id` `id` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ghost_zone` `ghost_zone` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `faction` `faction` smallint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `game_tele` + CHANGE COLUMN `id` `id` mediumint unsigned NOT NULL auto_increment, + CHANGE COLUMN `map` `map` smallint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `game_weather` + CHANGE COLUMN `zone` `zone` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `spring_rain_chance` `spring_rain_chance` tinyint unsigned NOT NULL DEFAULT 25, + CHANGE COLUMN `spring_snow_chance` `spring_snow_chance` tinyint unsigned NOT NULL DEFAULT 25, + CHANGE COLUMN `spring_storm_chance` `spring_storm_chance` tinyint unsigned NOT NULL DEFAULT 25, + CHANGE COLUMN `summer_rain_chance` `summer_rain_chance` tinyint unsigned NOT NULL DEFAULT 25, + CHANGE COLUMN `summer_snow_chance` `summer_snow_chance` tinyint unsigned NOT NULL DEFAULT 25, + CHANGE COLUMN `summer_storm_chance` `summer_storm_chance` tinyint unsigned NOT NULL DEFAULT 25, + CHANGE COLUMN `fall_rain_chance` `fall_rain_chance` tinyint unsigned NOT NULL DEFAULT 25, + CHANGE COLUMN `fall_snow_chance` `fall_snow_chance` tinyint unsigned NOT NULL DEFAULT 25, + CHANGE COLUMN `fall_storm_chance` `fall_storm_chance` tinyint unsigned NOT NULL DEFAULT 25, + CHANGE COLUMN `winter_rain_chance` `winter_rain_chance` tinyint unsigned NOT NULL DEFAULT 25, + CHANGE COLUMN `winter_snow_chance` `winter_snow_chance` tinyint unsigned NOT NULL DEFAULT 25, + CHANGE COLUMN `winter_storm_chance` `winter_storm_chance` tinyint unsigned NOT NULL DEFAULT 25; +ALTER TABLE `gameobject` + CHANGE COLUMN `guid` `guid` integer unsigned NOT NULL auto_increment COMMENT 'Global Unique Identifier', + CHANGE COLUMN `id` `id` mediumint unsigned NOT NULL DEFAULT 0 COMMENT 'Gameobject Identifier', + CHANGE COLUMN `map` `map` smallint unsigned NOT NULL DEFAULT 0 COMMENT 'Map Identifier', + CHANGE COLUMN `spawntimesecs` `spawntimesecs` integer NOT NULL DEFAULT 0, + CHANGE COLUMN `animprogress` `animprogress` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `state` `state` tinyint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `gameobject_involvedrelation` + CHANGE COLUMN `id` `id` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `quest` `quest` mediumint unsigned NOT NULL DEFAULT 0 COMMENT 'Quest Identifier'; +ALTER TABLE `gameobject_loot_template` + CHANGE COLUMN `entry` `entry` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `item` `item` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `QuestChanceOrGroup` `QuestChanceOrGroup` tinyint NOT NULL DEFAULT 0, + CHANGE COLUMN `mincount` `mincount` tinyint unsigned NOT NULL DEFAULT 1, + CHANGE COLUMN `maxcount` `maxcount` tinyint unsigned NOT NULL DEFAULT 1, + CHANGE COLUMN `freeforall` `freeforall` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `lootcondition` `lootcondition` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `condition_value1` `condition_value1` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `condition_value2` `condition_value2` mediumint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `gameobject_questrelation` + CHANGE COLUMN `id` `id` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `quest` `quest` mediumint unsigned NOT NULL DEFAULT 0 COMMENT 'Quest Identifier'; +ALTER TABLE `gameobject_respawn` + CHANGE COLUMN `guid` `guid` integer unsigned NOT NULL DEFAULT 0 COMMENT 'Global Unique Identifier', + CHANGE COLUMN `respawntime` `respawntime` bigint NOT NULL DEFAULT 0, + CHANGE COLUMN `instance` `instance` mediumint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `gameobject_scripts` + CHANGE COLUMN `id` `id` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `delay` `delay` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `command` `command` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `datalong` `datalong` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `datalong2` `datalong2` integer unsigned NOT NULL DEFAULT 0; +ALTER TABLE `gameobject_template` + CHANGE COLUMN `entry` `entry` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `type` `type` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `displayId` `displayId` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `name` `name` varchar(100) NOT NULL DEFAULT '', + CHANGE COLUMN `faction` `faction` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `flags` `flags` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `data0` `data0` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `data1` `data1` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `data2` `data2` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `data3` `data3` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `data4` `data4` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `data5` `data5` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `data6` `data6` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `data7` `data7` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `data8` `data8` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `data9` `data9` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `data10` `data10` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `data11` `data11` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `data12` `data12` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `data13` `data13` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `data14` `data14` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `data15` `data15` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `data16` `data16` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `data17` `data17` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `data18` `data18` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `data19` `data19` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `data20` `data20` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `data21` `data21` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `data22` `data22` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `data23` `data23` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ScriptName` `ScriptName` varchar(64) NOT NULL DEFAULT ''; +ALTER TABLE `instance_template` + CHANGE COLUMN `map` `map` smallint unsigned NOT NULL, + CHANGE COLUMN `parent` `parent` integer unsigned NOT NULL, + CHANGE COLUMN `levelMin` `levelMin` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `levelMax` `levelMax` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `maxPlayers` `maxPlayers` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `reset_delay` `reset_delay` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `script` `script` varchar(128) NOT NULL DEFAULT ''; +ALTER TABLE `item_enchantment_template` + CHANGE COLUMN `entry` `entry` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ench` `ench` mediumint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `item_loot_template` + CHANGE COLUMN `entry` `entry` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `item` `item` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `QuestChanceOrGroup` `QuestChanceOrGroup` tinyint NOT NULL DEFAULT 0, + CHANGE COLUMN `mincount` `mincount` smallint unsigned NOT NULL DEFAULT 1, + CHANGE COLUMN `maxcount` `maxcount` smallint unsigned NOT NULL DEFAULT 1, + CHANGE COLUMN `freeforall` `freeforall` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `lootcondition` `lootcondition` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `condition_value1` `condition_value1` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `condition_value2` `condition_value2` mediumint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `item_template` + CHANGE COLUMN `entry` `entry` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `class` `class` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `subclass` `subclass` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `unk0` `unk0` integer NOT NULL DEFAULT -1, + CHANGE COLUMN `name` `name` varchar(255) NOT NULL DEFAULT '', + CHANGE COLUMN `displayid` `displayid` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `Quality` `Quality` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `Flags` `Flags` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `BuyCount` `BuyCount` tinyint unsigned NOT NULL DEFAULT 1, + CHANGE COLUMN `BuyPrice` `BuyPrice` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `SellPrice` `SellPrice` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `InventoryType` `InventoryType` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `AllowableClass` `AllowableClass` mediumint NOT NULL DEFAULT -1, + CHANGE COLUMN `AllowableRace` `AllowableRace` mediumint NOT NULL DEFAULT -1, + CHANGE COLUMN `ItemLevel` `ItemLevel` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RequiredLevel` `RequiredLevel` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RequiredSkill` `RequiredSkill` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RequiredSkillRank` `RequiredSkillRank` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `requiredspell` `requiredspell` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `requiredhonorrank` `requiredhonorrank` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RequiredCityRank` `RequiredCityRank` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RequiredReputationFaction` `RequiredReputationFaction` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RequiredReputationRank` `RequiredReputationRank` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `maxcount` `maxcount` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `stackable` `stackable` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ContainerSlots` `ContainerSlots` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `stat_type1` `stat_type1` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `stat_value1` `stat_value1` smallint NOT NULL DEFAULT 0, + CHANGE COLUMN `stat_type2` `stat_type2` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `stat_value2` `stat_value2` smallint NOT NULL DEFAULT 0, + CHANGE COLUMN `stat_type3` `stat_type3` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `stat_value3` `stat_value3` smallint NOT NULL DEFAULT 0, + CHANGE COLUMN `stat_type4` `stat_type4` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `stat_value4` `stat_value4` smallint NOT NULL DEFAULT 0, + CHANGE COLUMN `stat_type5` `stat_type5` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `stat_value5` `stat_value5` smallint NOT NULL DEFAULT 0, + CHANGE COLUMN `stat_type6` `stat_type6` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `stat_value6` `stat_value6` smallint NOT NULL DEFAULT 0, + CHANGE COLUMN `stat_type7` `stat_type7` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `stat_value7` `stat_value7` smallint NOT NULL DEFAULT 0, + CHANGE COLUMN `stat_type8` `stat_type8` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `stat_value8` `stat_value8` smallint NOT NULL DEFAULT 0, + CHANGE COLUMN `stat_type9` `stat_type9` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `stat_value9` `stat_value9` smallint NOT NULL DEFAULT 0, + CHANGE COLUMN `stat_type10` `stat_type10` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `stat_value10` `stat_value10` smallint NOT NULL DEFAULT 0, + CHANGE COLUMN `dmg_type1` `dmg_type1` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `dmg_type2` `dmg_type2` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `dmg_type3` `dmg_type3` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `dmg_type4` `dmg_type4` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `dmg_type5` `dmg_type5` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `armor` `armor` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `holy_res` `holy_res` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `fire_res` `fire_res` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `nature_res` `nature_res` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `frost_res` `frost_res` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `shadow_res` `shadow_res` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `arcane_res` `arcane_res` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `delay` `delay` smallint unsigned NOT NULL DEFAULT 1000, + CHANGE COLUMN `ammo_type` `ammo_type` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `spellid_1` `spellid_1` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `spelltrigger_1` `spelltrigger_1` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `spellcharges_1` `spellcharges_1` tinyint NOT NULL DEFAULT 0, + CHANGE COLUMN `spellcooldown_1` `spellcooldown_1` integer NOT NULL DEFAULT -1, + CHANGE COLUMN `spellcategory_1` `spellcategory_1` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `spellcategorycooldown_1` `spellcategorycooldown_1` integer NOT NULL DEFAULT -1, + CHANGE COLUMN `spellid_2` `spellid_2` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `spelltrigger_2` `spelltrigger_2` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `spellcharges_2` `spellcharges_2` tinyint NOT NULL DEFAULT 0, + CHANGE COLUMN `spellcooldown_2` `spellcooldown_2` integer NOT NULL DEFAULT -1, + CHANGE COLUMN `spellcategory_2` `spellcategory_2` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `spellcategorycooldown_2` `spellcategorycooldown_2` integer NOT NULL DEFAULT -1, + CHANGE COLUMN `spellid_3` `spellid_3` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `spelltrigger_3` `spelltrigger_3` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `spellcharges_3` `spellcharges_3` tinyint NOT NULL DEFAULT 0, + CHANGE COLUMN `spellcooldown_3` `spellcooldown_3` integer NOT NULL DEFAULT -1, + CHANGE COLUMN `spellcategory_3` `spellcategory_3` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `spellcategorycooldown_3` `spellcategorycooldown_3` integer NOT NULL DEFAULT -1, + CHANGE COLUMN `spellid_4` `spellid_4` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `spelltrigger_4` `spelltrigger_4` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `spellcharges_4` `spellcharges_4` tinyint NOT NULL DEFAULT 0, + CHANGE COLUMN `spellcooldown_4` `spellcooldown_4` integer NOT NULL DEFAULT -1, + CHANGE COLUMN `spellcategory_4` `spellcategory_4` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `spellcategorycooldown_4` `spellcategorycooldown_4` integer NOT NULL DEFAULT -1, + CHANGE COLUMN `spellid_5` `spellid_5` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `spelltrigger_5` `spelltrigger_5` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `spellcharges_5` `spellcharges_5` tinyint NOT NULL DEFAULT 0, + CHANGE COLUMN `spellcooldown_5` `spellcooldown_5` integer NOT NULL DEFAULT -1, + CHANGE COLUMN `spellcategory_5` `spellcategory_5` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `spellcategorycooldown_5` `spellcategorycooldown_5` integer NOT NULL DEFAULT -1, + CHANGE COLUMN `bonding` `bonding` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `PageText` `PageText` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `LanguageID` `LanguageID` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `PageMaterial` `PageMaterial` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `startquest` `startquest` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `lockid` `lockid` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `Material` `Material` tinyint NOT NULL DEFAULT 0, + CHANGE COLUMN `sheath` `sheath` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RandomProperty` `RandomProperty` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RandomSuffix` `RandomSuffix` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `block` `block` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `itemset` `itemset` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `MaxDurability` `MaxDurability` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `area` `area` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `Map` `Map` smallint NOT NULL DEFAULT 0, + CHANGE COLUMN `BagFamily` `BagFamily` mediumint NOT NULL DEFAULT 0, + CHANGE COLUMN `TotemCategory` `TotemCategory` tinyint NOT NULL DEFAULT 0, + CHANGE COLUMN `socketColor_1` `socketColor_1` tinyint NOT NULL DEFAULT 0, + CHANGE COLUMN `socketContent_1` `socketContent_1` mediumint NOT NULL DEFAULT 0, + CHANGE COLUMN `socketColor_2` `socketColor_2` tinyint NOT NULL DEFAULT 0, + CHANGE COLUMN `socketContent_2` `socketContent_2` mediumint NOT NULL DEFAULT 0, + CHANGE COLUMN `socketColor_3` `socketColor_3` tinyint NOT NULL DEFAULT 0, + CHANGE COLUMN `socketContent_3` `socketContent_3` mediumint NOT NULL DEFAULT 0, + CHANGE COLUMN `socketBonus` `socketBonus` mediumint NOT NULL DEFAULT 0, + CHANGE COLUMN `GemProperties` `GemProperties` mediumint NOT NULL DEFAULT 0, + CHANGE COLUMN `ExtendedCost` `ExtendedCost` mediumint NOT NULL DEFAULT 0, + CHANGE COLUMN `CondExtendedCost` `CondExtendedCost` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RequiredDisenchantSkill` `RequiredDisenchantSkill` smallint NOT NULL DEFAULT -1, + CHANGE COLUMN `ScriptName` `ScriptName` varchar(64) NOT NULL DEFAULT '', + CHANGE COLUMN `DisenchantID` `DisenchantID` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `FoodType` `FoodType` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `minMoneyLoot` `minMoneyLoot` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `maxMoneyLoot` `maxMoneyLoot` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `Duration` `Duration` integer NOT NULL DEFAULT 0 COMMENT 'Duration in seconds. Negative value means realtime, postive value ingame time'; +ALTER TABLE `locales_creature` + CHANGE COLUMN `entry` `entry` mediumint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `locales_gameobject` + CHANGE COLUMN `entry` `entry` mediumint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `locales_item` + CHANGE COLUMN `entry` `entry` mediumint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `locales_npc_text` + CHANGE COLUMN `entry` `entry` mediumint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `locales_page_text` + CHANGE COLUMN `entry` `entry` mediumint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `locales_quest` + CHANGE COLUMN `entry` `entry` mediumint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `mangos_string` + CHANGE COLUMN `content_default` `content_default` text NOT NULL, + CHANGE COLUMN `entry` `entry` mediumint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `npc_gossip` + CHANGE COLUMN `npc_guid` `npc_guid` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `textid` `textid` mediumint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `npc_gossip_textid` + CHANGE COLUMN `zoneid` `zoneid` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `action` `action` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `textid` `textid` mediumint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `npc_option` + CHANGE COLUMN `id` `id` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `gossip_id` `gossip_id` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `npcflag` `npcflag` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `icon` `icon` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `action` `action` tinyint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `npc_text` + CHANGE COLUMN `ID` `ID` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `lang0` `lang0` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em0_0` `em0_0` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em0_1` `em0_1` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em0_2` `em0_2` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em0_3` `em0_3` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em0_4` `em0_4` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em0_5` `em0_5` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `lang1` `lang1` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em1_0` `em1_0` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em1_1` `em1_1` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em1_2` `em1_2` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em1_3` `em1_3` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em1_4` `em1_4` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em1_5` `em1_5` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `lang2` `lang2` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em2_0` `em2_0` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em2_1` `em2_1` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em2_2` `em2_2` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em2_3` `em2_3` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em2_4` `em2_4` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em2_5` `em2_5` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `lang3` `lang3` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em3_0` `em3_0` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em3_1` `em3_1` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em3_2` `em3_2` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em3_3` `em3_3` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em3_4` `em3_4` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em3_5` `em3_5` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `lang4` `lang4` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em4_0` `em4_0` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em4_1` `em4_1` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em4_2` `em4_2` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em4_3` `em4_3` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em4_4` `em4_4` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em4_5` `em4_5` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `lang5` `lang5` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em5_0` `em5_0` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em5_1` `em5_1` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em5_2` `em5_2` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em5_3` `em5_3` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em5_4` `em5_4` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em5_5` `em5_5` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `lang6` `lang6` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em6_0` `em6_0` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em6_1` `em6_1` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em6_2` `em6_2` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em6_3` `em6_3` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em6_4` `em6_4` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em6_5` `em6_5` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `lang7` `lang7` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em7_0` `em7_0` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em7_1` `em7_1` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em7_2` `em7_2` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em7_3` `em7_3` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em7_4` `em7_4` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `em7_5` `em7_5` smallint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `npc_trainer` + CHANGE COLUMN `entry` `entry` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `spell` `spell` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `spellcost` `spellcost` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `reqskill` `reqskill` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `reqskillvalue` `reqskillvalue` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `reqlevel` `reqlevel` tinyint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `npc_vendor` + CHANGE COLUMN `entry` `entry` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `item` `item` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `maxcount` `maxcount` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `incrtime` `incrtime` integer unsigned NOT NULL DEFAULT 0; +ALTER TABLE `page_text` + CHANGE COLUMN `entry` `entry` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `text` `text` longtext NOT NULL, + CHANGE COLUMN `next_page` `next_page` mediumint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `pet_levelstats` + CHANGE COLUMN `creature_entry` `creature_entry` mediumint unsigned NOT NULL, + CHANGE COLUMN `level` `level` tinyint unsigned NOT NULL, + CHANGE COLUMN `hp` `hp` smallint unsigned NOT NULL, + CHANGE COLUMN `mana` `mana` smallint unsigned NOT NULL, + CHANGE COLUMN `armor` `armor` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `str` `str` smallint unsigned NOT NULL, + CHANGE COLUMN `agi` `agi` smallint unsigned NOT NULL, + CHANGE COLUMN `sta` `sta` smallint unsigned NOT NULL, + CHANGE COLUMN `inte` `inte` smallint unsigned NOT NULL, + CHANGE COLUMN `spi` `spi` smallint unsigned NOT NULL; +ALTER TABLE `pet_name_generation` + CHANGE COLUMN `id` `id` mediumint unsigned NOT NULL auto_increment, + CHANGE COLUMN `entry` `entry` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `half` `half` tinyint NOT NULL DEFAULT 0; +ALTER TABLE `petcreateinfo_spell` + CHANGE COLUMN `entry` `entry` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `Spell1` `Spell1` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `Spell2` `Spell2` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `Spell3` `Spell3` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `Spell4` `Spell4` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `FamilyPassive` `FamilyPassive` mediumint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `pickpocketing_loot_template` + CHANGE COLUMN `entry` `entry` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `item` `item` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `QuestChanceOrGroup` `QuestChanceOrGroup` tinyint NOT NULL DEFAULT 0, + CHANGE COLUMN `mincount` `mincount` tinyint unsigned NOT NULL DEFAULT 1, + CHANGE COLUMN `maxcount` `maxcount` tinyint unsigned NOT NULL DEFAULT 1, + CHANGE COLUMN `freeforall` `freeforall` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `lootcondition` `lootcondition` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `condition_value1` `condition_value1` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `condition_value2` `condition_value2` mediumint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `playercreateinfo` + CHANGE COLUMN `race` `race` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `class` `class` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `map` `map` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `zone` `zone` mediumint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `playercreateinfo_action` + CHANGE COLUMN `race` `race` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `class` `class` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `button` `button` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `action` `action` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `type` `type` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `misc` `misc` smallint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `playercreateinfo_item` + CHANGE COLUMN `race` `race` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `class` `class` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `itemid` `itemid` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `amount` `amount` tinyint unsigned NOT NULL DEFAULT 1; +ALTER TABLE `playercreateinfo_skill` + CHANGE COLUMN `race` `race` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `class` `class` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `Skill` `Skill` smallint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `playercreateinfo_spell` + CHANGE COLUMN `race` `race` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `class` `class` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `Spell` `Spell` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `Active` `Active` tinyint unsigned NOT NULL DEFAULT 1; +-- here posted +ALTER TABLE `prospecting_loot_template` + CHANGE COLUMN `entry` `entry` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `item` `item` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `QuestChanceOrGroup` `QuestChanceOrGroup` tinyint NOT NULL DEFAULT 0, + CHANGE COLUMN `mincount` `mincount` tinyint unsigned NOT NULL DEFAULT 1, + CHANGE COLUMN `maxcount` `maxcount` tinyint unsigned NOT NULL DEFAULT 1, + CHANGE COLUMN `freeforall` `freeforall` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `lootcondition` `lootcondition` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `condition_value1` `condition_value1` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `condition_value2` `condition_value2` mediumint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `quest_end_scripts` + CHANGE COLUMN `id` `id` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `delay` `delay` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `command` `command` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `datalong` `datalong` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `datalong2` `datalong2` integer unsigned NOT NULL DEFAULT 0; +ALTER TABLE `quest_start_scripts` + CHANGE COLUMN `id` `id` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `delay` `delay` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `command` `command` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `datalong` `datalong` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `datalong2` `datalong2` integer unsigned NOT NULL DEFAULT 0; +ALTER TABLE `quest_template` + CHANGE COLUMN `entry` `entry` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ZoneOrSort` `ZoneOrSort` smallint NOT NULL DEFAULT 0, + CHANGE COLUMN `MinLevel` `MinLevel` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `QuestLevel` `QuestLevel` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `Type` `Type` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RequiredRaces` `RequiredRaces` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RequiredSkillValue` `RequiredSkillValue` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RepObjectiveFaction` `RepObjectiveFaction` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RepObjectiveValue` `RepObjectiveValue` mediumint NOT NULL DEFAULT 0, + CHANGE COLUMN `RequiredMinRepFaction` `RequiredMinRepFaction` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RequiredMinRepValue` `RequiredMinRepValue` mediumint NOT NULL DEFAULT 0, + CHANGE COLUMN `RequiredMaxRepFaction` `RequiredMaxRepFaction` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RequiredMaxRepValue` `RequiredMaxRepValue` mediumint NOT NULL DEFAULT 0, + CHANGE COLUMN `SuggestedPlayers` `SuggestedPlayers` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `LimitTime` `LimitTime` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `QuestFlags` `QuestFlags` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `SpecialFlags` `SpecialFlags` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `PrevQuestId` `PrevQuestId` mediumint NOT NULL DEFAULT 0, + CHANGE COLUMN `NextQuestId` `NextQuestId` mediumint NOT NULL DEFAULT 0, + CHANGE COLUMN `ExclusiveGroup` `ExclusiveGroup` mediumint NOT NULL DEFAULT 0, + CHANGE COLUMN `NextQuestInChain` `NextQuestInChain` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `SrcItemId` `SrcItemId` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `SrcItemCount` `SrcItemCount` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `SrcSpell` `SrcSpell` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ReqItemId1` `ReqItemId1` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ReqItemId2` `ReqItemId2` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ReqItemId3` `ReqItemId3` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ReqItemId4` `ReqItemId4` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ReqItemCount1` `ReqItemCount1` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ReqItemCount2` `ReqItemCount2` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ReqItemCount3` `ReqItemCount3` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ReqItemCount4` `ReqItemCount4` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ReqSourceId1` `ReqSourceId1` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ReqSourceId2` `ReqSourceId2` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ReqSourceId3` `ReqSourceId3` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ReqSourceId4` `ReqSourceId4` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ReqSourceCount1` `ReqSourceCount1` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ReqSourceCount2` `ReqSourceCount2` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ReqSourceCount3` `ReqSourceCount3` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ReqSourceCount4` `ReqSourceCount4` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ReqSourceRef1` `ReqSourceRef1` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ReqSourceRef2` `ReqSourceRef2` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ReqSourceRef3` `ReqSourceRef3` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ReqSourceRef4` `ReqSourceRef4` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ReqCreatureOrGOId1` `ReqCreatureOrGOId1` mediumint NOT NULL DEFAULT 0, + CHANGE COLUMN `ReqCreatureOrGOId2` `ReqCreatureOrGOId2` mediumint NOT NULL DEFAULT 0, + CHANGE COLUMN `ReqCreatureOrGOId3` `ReqCreatureOrGOId3` mediumint NOT NULL DEFAULT 0, + CHANGE COLUMN `ReqCreatureOrGOId4` `ReqCreatureOrGOId4` mediumint NOT NULL DEFAULT 0, + CHANGE COLUMN `ReqCreatureOrGOCount1` `ReqCreatureOrGOCount1` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ReqCreatureOrGOCount2` `ReqCreatureOrGOCount2` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ReqCreatureOrGOCount3` `ReqCreatureOrGOCount3` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ReqCreatureOrGOCount4` `ReqCreatureOrGOCount4` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ReqSpellCast1` `ReqSpellCast1` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ReqSpellCast2` `ReqSpellCast2` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ReqSpellCast3` `ReqSpellCast3` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `ReqSpellCast4` `ReqSpellCast4` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RewChoiceItemId1` `RewChoiceItemId1` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RewChoiceItemId2` `RewChoiceItemId2` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RewChoiceItemId3` `RewChoiceItemId3` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RewChoiceItemId4` `RewChoiceItemId4` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RewChoiceItemId5` `RewChoiceItemId5` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RewChoiceItemId6` `RewChoiceItemId6` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RewChoiceItemCount1` `RewChoiceItemCount1` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RewChoiceItemCount2` `RewChoiceItemCount2` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RewChoiceItemCount3` `RewChoiceItemCount3` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RewChoiceItemCount4` `RewChoiceItemCount4` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RewChoiceItemCount5` `RewChoiceItemCount5` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RewChoiceItemCount6` `RewChoiceItemCount6` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RewItemId1` `RewItemId1` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RewItemId2` `RewItemId2` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RewItemId3` `RewItemId3` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RewItemId4` `RewItemId4` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RewItemCount1` `RewItemCount1` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RewItemCount2` `RewItemCount2` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RewItemCount3` `RewItemCount3` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RewItemCount4` `RewItemCount4` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RewRepFaction1` `RewRepFaction1` smallint unsigned NOT NULL DEFAULT 0 COMMENT 'faction id from Faction.dbc in this case', + CHANGE COLUMN `RewRepFaction2` `RewRepFaction2` smallint unsigned NOT NULL DEFAULT 0 COMMENT 'faction id from Faction.dbc in this case', + CHANGE COLUMN `RewRepFaction3` `RewRepFaction3` smallint unsigned NOT NULL DEFAULT 0 COMMENT 'faction id from Faction.dbc in this case', + CHANGE COLUMN `RewRepFaction4` `RewRepFaction4` smallint unsigned NOT NULL DEFAULT 0 COMMENT 'faction id from Faction.dbc in this case', + CHANGE COLUMN `RewRepFaction5` `RewRepFaction5` smallint unsigned NOT NULL DEFAULT 0 COMMENT 'faction id from Faction.dbc in this case', + CHANGE COLUMN `RewRepValue1` `RewRepValue1` mediumint NOT NULL DEFAULT 0, + CHANGE COLUMN `RewRepValue2` `RewRepValue2` mediumint NOT NULL DEFAULT 0, + CHANGE COLUMN `RewRepValue3` `RewRepValue3` mediumint NOT NULL DEFAULT 0, + CHANGE COLUMN `RewRepValue4` `RewRepValue4` mediumint NOT NULL DEFAULT 0, + CHANGE COLUMN `RewRepValue5` `RewRepValue5` mediumint NOT NULL DEFAULT 0, + CHANGE COLUMN `RewOrReqMoney` `RewOrReqMoney` integer NOT NULL DEFAULT 0, + CHANGE COLUMN `RewMoneyMaxLevel` `RewMoneyMaxLevel` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `RewSpell` `RewSpell` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `PointMapId` `PointMapId` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `PointOpt` `PointOpt` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `DetailsEmote1` `DetailsEmote1` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `DetailsEmote2` `DetailsEmote2` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `DetailsEmote3` `DetailsEmote3` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `DetailsEmote4` `DetailsEmote4` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `IncompleteEmote` `IncompleteEmote` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `CompleteEmote` `CompleteEmote` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `OfferRewardEmote1` `OfferRewardEmote1` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `OfferRewardEmote2` `OfferRewardEmote2` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `OfferRewardEmote3` `OfferRewardEmote3` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `OfferRewardEmote4` `OfferRewardEmote4` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `StartScript` `StartScript` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `CompleteScript` `CompleteScript` mediumint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `skill_discovery_template` + CHANGE COLUMN `spellId` `spellId` mediumint unsigned NOT NULL DEFAULT 0 COMMENT 'SpellId of the discoverable spell', + CHANGE COLUMN `reqSpell` `reqSpell` mediumint unsigned NOT NULL DEFAULT 0 COMMENT 'spell requirement'; +ALTER TABLE `skill_extra_item_template` + CHANGE COLUMN `spellId` `spellId` mediumint unsigned NOT NULL DEFAULT 0 COMMENT 'SpellId of the item creation spell', + CHANGE COLUMN `requiredSpecialization` `requiredSpecialization` mediumint unsigned NOT NULL DEFAULT 0 COMMENT 'Specialization spell id', + CHANGE COLUMN `additionalMaxNum` `additionalMaxNum` tinyint unsigned NOT NULL DEFAULT 0 COMMENT 'max num of adds'; +ALTER TABLE `skinning_loot_template` + CHANGE COLUMN `entry` `entry` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `item` `item` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `QuestChanceOrGroup` `QuestChanceOrGroup` tinyint NOT NULL DEFAULT 0, + CHANGE COLUMN `mincount` `mincount` tinyint unsigned NOT NULL DEFAULT 1, + CHANGE COLUMN `maxcount` `maxcount` tinyint unsigned NOT NULL DEFAULT 1, + CHANGE COLUMN `freeforall` `freeforall` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `lootcondition` `lootcondition` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `condition_value1` `condition_value1` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `condition_value2` `condition_value2` mediumint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `spell_affect` + CHANGE COLUMN `entry` `entry` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `effectId` `effectId` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `SpellFamily` `SpellFamily` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `SpellFamilyMask` `SpellFamilyMask` bigint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `Charges` `Charges` smallint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `spell_chain` + CHANGE COLUMN `spell_id` `spell_id` mediumint NOT NULL DEFAULT 0, + CHANGE COLUMN `prev_spell` `prev_spell` mediumint NOT NULL DEFAULT 0, + CHANGE COLUMN `first_spell` `first_spell` mediumint NOT NULL DEFAULT 0, + CHANGE COLUMN `rank` `rank` tinyint NOT NULL DEFAULT 0; +ALTER TABLE `spell_learn_skill` + CHANGE COLUMN `entry` `entry` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `SkillID` `SkillID` smallint NOT NULL DEFAULT 0, + CHANGE COLUMN `Value` `Value` smallint NOT NULL DEFAULT 0, + CHANGE COLUMN `MaxValue` `MaxValue` smallint NOT NULL DEFAULT 0; +ALTER TABLE `spell_learn_spell` + CHANGE COLUMN `entry` `entry` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `SpellID` `SpellID` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `IfNoSpell` `IfNoSpell` smallint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `spell_proc_event` + CHANGE COLUMN `entry` `entry` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `SchoolMask` `SchoolMask` tinyint NOT NULL DEFAULT 0, + CHANGE COLUMN `Category` `Category` smallint NOT NULL DEFAULT 0, + CHANGE COLUMN `SkillID` `SkillID` smallint NOT NULL DEFAULT 0, + CHANGE COLUMN `SpellFamilyName` `SpellFamilyName` smallint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `SpellFamilyMask` `SpellFamilyMask` bigint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `procFlags` `procFlags` integer unsigned NOT NULL DEFAULT 0; +ALTER TABLE `spell_script_target` + CHANGE COLUMN `entry` `entry` mediumint unsigned NOT NULL, + CHANGE COLUMN `type` `type` tinyint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `targetEntry` `targetEntry` mediumint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `spell_scripts` + CHANGE COLUMN `id` `id` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `delay` `delay` integer unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `command` `command` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `datalong` `datalong` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `datalong2` `datalong2` integer unsigned NOT NULL DEFAULT 0; +ALTER TABLE `spell_teleport` + CHANGE COLUMN `id` `id` mediumint unsigned NOT NULL DEFAULT 0 COMMENT 'Identifier', + CHANGE COLUMN `target_map` `target_map` smallint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `spell_threat` + CHANGE COLUMN `entry` `entry` mediumint unsigned NOT NULL, + CHANGE COLUMN `Threat` `Threat` smallint NOT NULL; +ALTER TABLE `transports` + CHANGE COLUMN `entry` `entry` mediumint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `period` `period` mediumint unsigned NOT NULL DEFAULT 0; +ALTER TABLE `uptime` + CHANGE COLUMN `starttime` `starttime` bigint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `startstring` `startstring` varchar(64) NOT NULL DEFAULT '', + CHANGE COLUMN `uptime` `uptime` bigint unsigned NOT NULL DEFAULT 0, + CHANGE COLUMN `maxplayers` `maxplayers` smallint unsigned NOT NULL DEFAULT 0; diff --git a/sql/updates/0.10/5505_mangos_npc_gossip.sql b/sql/updates/0.10/5505_mangos_npc_gossip.sql new file mode 100644 index 00000000000..778c9ed76f8 --- /dev/null +++ b/sql/updates/0.10/5505_mangos_npc_gossip.sql @@ -0,0 +1,8 @@ +-- Some unused columns left + +ALTER TABLE `npc_gossip` + DROP COLUMN `id`; +ALTER TABLE `npc_gossip` + DROP COLUMN `gossip_type`; +ALTER TABLE `npc_gossip` + DROP COLUMN `option_count`; diff --git a/sql/updates/0.10/5526_mangos_player_levelstats.sql b/sql/updates/0.10/5526_mangos_player_levelstats.sql new file mode 100644 index 00000000000..4a8c6a78004 --- /dev/null +++ b/sql/updates/0.10/5526_mangos_player_levelstats.sql @@ -0,0 +1,70 @@ +UPDATE `player_levelstats` SET `basehp` = 37, `basemana` = 85 WHERE `class` = 11 AND `level`= 1; +UPDATE `player_levelstats` SET `basehp` = 44, `basemana` = 91 WHERE `class` = 11 AND `level`= 2; +UPDATE `player_levelstats` SET `basehp` = 51, `basemana` = 98 WHERE `class` = 11 AND `level`= 3; +UPDATE `player_levelstats` SET `basehp` = 58, `basemana` = 106 WHERE `class` = 11 AND `level`= 4; +UPDATE `player_levelstats` SET `basehp` = 65, `basemana` = 115 WHERE `class` = 11 AND `level`= 5; +UPDATE `player_levelstats` SET `basehp` = 72, `basemana` = 125 WHERE `class` = 11 AND `level`= 6; +UPDATE `player_levelstats` SET `basehp` = 79, `basemana` = 136 WHERE `class` = 11 AND `level`= 7; +UPDATE `player_levelstats` SET `basehp` = 86, `basemana` = 148 WHERE `class` = 11 AND `level`= 8; +UPDATE `player_levelstats` SET `basehp` = 93, `basemana` = 161 WHERE `class` = 11 AND `level`= 9; +UPDATE `player_levelstats` SET `basehp` = 100, `basemana` = 175 WHERE `class` = 11 AND `level`= 10; +UPDATE `player_levelstats` SET `basehp` = 107, `basemana` = 190 WHERE `class` = 11 AND `level`= 11; +UPDATE `player_levelstats` SET `basehp` = 114, `basemana` = 206 WHERE `class` = 11 AND `level`= 12; +UPDATE `player_levelstats` SET `basehp` = 121, `basemana` = 223 WHERE `class` = 11 AND `level`= 13; +UPDATE `player_levelstats` SET `basehp` = 128, `basemana` = 241 WHERE `class` = 11 AND `level`= 14; +UPDATE `player_levelstats` SET `basehp` = 135, `basemana` = 260 WHERE `class` = 11 AND `level`= 15; +UPDATE `player_levelstats` SET `basehp` = 142, `basemana` = 280 WHERE `class` = 11 AND `level`= 16; +UPDATE `player_levelstats` SET `basehp` = 150, `basemana` = 301 WHERE `class` = 11 AND `level`= 17; +UPDATE `player_levelstats` SET `basehp` = 159, `basemana` = 323 WHERE `class` = 11 AND `level`= 18; +UPDATE `player_levelstats` SET `basehp` = 169, `basemana` = 346 WHERE `class` = 11 AND `level`= 19; +UPDATE `player_levelstats` SET `basehp` = 180, `basemana` = 370 WHERE `class` = 11 AND `level`= 20; +UPDATE `player_levelstats` SET `basehp` = 192, `basemana` = 395 WHERE `class` = 11 AND `level`= 21; +UPDATE `player_levelstats` SET `basehp` = 205, `basemana` = 421 WHERE `class` = 11 AND `level`= 22; +UPDATE `player_levelstats` SET `basehp` = 219, `basemana` = 448 WHERE `class` = 11 AND `level`= 23; +UPDATE `player_levelstats` SET `basehp` = 234, `basemana` = 476 WHERE `class` = 11 AND `level`= 24; +UPDATE `player_levelstats` SET `basehp` = 240, `basemana` = 505 WHERE `class` = 11 AND `level`= 25; +UPDATE `player_levelstats` SET `basehp` = 257, `basemana` = 535 WHERE `class` = 11 AND `level`= 26; +UPDATE `player_levelstats` SET `basehp` = 275, `basemana` = 566 WHERE `class` = 11 AND `level`= 27; +UPDATE `player_levelstats` SET `basehp` = 294, `basemana` = 598 WHERE `class` = 11 AND `level`= 28; +UPDATE `player_levelstats` SET `basehp` = 314, `basemana` = 631 WHERE `class` = 11 AND `level`= 29; +UPDATE `player_levelstats` SET `basehp` = 335, `basemana` = 665 WHERE `class` = 11 AND `level`= 30; +UPDATE `player_levelstats` SET `basehp` = 347, `basemana` = 699 WHERE `class` = 11 AND `level`= 31; +UPDATE `player_levelstats` SET `basehp` = 370, `basemana` = 733 WHERE `class` = 11 AND `level`= 32; +UPDATE `player_levelstats` SET `basehp` = 394, `basemana` = 767 WHERE `class` = 11 AND `level`= 33; +UPDATE `player_levelstats` SET `basehp` = 419, `basemana` = 786 WHERE `class` = 11 AND `level`= 34; +UPDATE `player_levelstats` SET `basehp` = 435, `basemana` = 820 WHERE `class` = 11 AND `level`= 35; +UPDATE `player_levelstats` SET `basehp` = 462, `basemana` = 854 WHERE `class` = 11 AND `level`= 36; +UPDATE `player_levelstats` SET `basehp` = 490, `basemana` = 888 WHERE `class` = 11 AND `level`= 37; +UPDATE `player_levelstats` SET `basehp` = 509, `basemana` = 922 WHERE `class` = 11 AND `level`= 38; +UPDATE `player_levelstats` SET `basehp` = 539, `basemana` = 941 WHERE `class` = 11 AND `level`= 39; +UPDATE `player_levelstats` SET `basehp` = 570, `basemana` = 975 WHERE `class` = 11 AND `level`= 40; +UPDATE `player_levelstats` SET `basehp` = 592, `basemana` = 1009 WHERE `class` = 11 AND `level`= 41; +UPDATE `player_levelstats` SET `basehp` = 625, `basemana` = 1028 WHERE `class` = 11 AND `level`= 42; +UPDATE `player_levelstats` SET `basehp` = 649, `basemana` = 1062 WHERE `class` = 11 AND `level`= 43; +UPDATE `player_levelstats` SET `basehp` = 684, `basemana` = 1096 WHERE `class` = 11 AND `level`= 44; +UPDATE `player_levelstats` SET `basehp` = 710, `basemana` = 1115 WHERE `class` = 11 AND `level`= 45; +UPDATE `player_levelstats` SET `basehp` = 747, `basemana` = 1149 WHERE `class` = 11 AND `level`= 46; +UPDATE `player_levelstats` SET `basehp` = 775, `basemana` = 1183 WHERE `class` = 11 AND `level`= 47; +UPDATE `player_levelstats` SET `basehp` = 814, `basemana` = 1202 WHERE `class` = 11 AND `level`= 48; +UPDATE `player_levelstats` SET `basehp` = 844, `basemana` = 1236 WHERE `class` = 11 AND `level`= 49; +UPDATE `player_levelstats` SET `basehp` = 885, `basemana` = 1255 WHERE `class` = 11 AND `level`= 50; +UPDATE `player_levelstats` SET `basehp` = 917, `basemana` = 1289 WHERE `class` = 11 AND `level`= 51; +UPDATE `player_levelstats` SET `basehp` = 960, `basemana` = 1323 WHERE `class` = 11 AND `level`= 52; +UPDATE `player_levelstats` SET `basehp` = 994, `basemana` = 1342 WHERE `class` = 11 AND `level`= 53; +UPDATE `player_levelstats` SET `basehp` = 1029, `basemana` = 1376 WHERE `class` = 11 AND `level`= 54; +UPDATE `player_levelstats` SET `basehp` = 1075, `basemana` = 1395 WHERE `class` = 11 AND `level`= 55; +UPDATE `player_levelstats` SET `basehp` = 1112, `basemana` = 1414 WHERE `class` = 11 AND `level`= 56; +UPDATE `player_levelstats` SET `basehp` = 1150, `basemana` = 1448 WHERE `class` = 11 AND `level`= 57; +UPDATE `player_levelstats` SET `basehp` = 1199, `basemana` = 1467 WHERE `class` = 11 AND `level`= 58; +UPDATE `player_levelstats` SET `basehp` = 1239, `basemana` = 1501 WHERE `class` = 11 AND `level`= 59; +UPDATE `player_levelstats` SET `basehp` = 1330, `basemana` = 1520 WHERE `class` = 11 AND `level`= 60; +UPDATE `player_levelstats` SET `basehp` = 1428, `basemana` = 1664 WHERE `class` = 11 AND `level`= 61; +UPDATE `player_levelstats` SET `basehp` = 1583, `basemana` = 1808 WHERE `class` = 11 AND `level`= 62; +UPDATE `player_levelstats` SET `basehp` = 1760, `basemana` = 1951 WHERE `class` = 11 AND `level`= 63; +UPDATE `player_levelstats` SET `basehp` = 1932, `basemana` = 2095 WHERE `class` = 11 AND `level`= 64; +UPDATE `player_levelstats` SET `basehp` = 2114, `basemana` = 2239 WHERE `class` = 11 AND `level`= 65; +UPDATE `player_levelstats` SET `basehp` = 2304, `basemana` = 2383 WHERE `class` = 11 AND `level`= 66; +UPDATE `player_levelstats` SET `basehp` = 2504, `basemana` = 2527 WHERE `class` = 11 AND `level`= 67; +UPDATE `player_levelstats` SET `basehp` = 2713, `basemana` = 2670 WHERE `class` = 11 AND `level`= 68; +UPDATE `player_levelstats` SET `basehp` = 2931, `basemana` = 2814 WHERE `class` = 11 AND `level`= 69; +UPDATE `player_levelstats` SET `basehp` = 3159, `basemana` = 2958 WHERE `class` = 11 AND `level`= 70; diff --git a/sql/updates/0.10/5529_mangos_spell_chain.sql b/sql/updates/0.10/5529_mangos_spell_chain.sql new file mode 100644 index 00000000000..c0acd8815ea --- /dev/null +++ b/sql/updates/0.10/5529_mangos_spell_chain.sql @@ -0,0 +1,30 @@ +DELETE FROM spell_chain WHERE spell_id IN (9787,9788,17039,17040,17041); +INSERT INTO spell_chain VALUES +(9787, 9785,2018,5), +(9788, 9785,2018,5), +(17039,9787,2018,6), +(17040,9787,2018,6), +(17041,9787,2018,6); + +DELETE FROM spell_chain WHERE spell_id IN (28672,28675,28677); +INSERT INTO spell_chain VALUES +(28672,11611,2259,5), +(28675,11611,2259,5), +(28677,11611,2259,5); + +DELETE FROM spell_chain WHERE spell_id IN (10656,10658,10660); +INSERT INTO spell_chain VALUES +(10656,10662,2108,5), +(10658,10662,2108,5), +(10660,10662,2108,5); + +DELETE FROM spell_chain WHERE spell_id IN (20219,20222); +INSERT INTO spell_chain VALUES +(20219,12656,4036,5), +(20222,12656,4036,5); + +DELETE FROM spell_chain WHERE spell_id IN (26797,26798,26801); +INSERT INTO spell_chain VALUES +(26797,12180,3908,5), +(26798,12180,3908,5), +(26801,12180,3908,5); diff --git a/sql/updates/0.10/5530_mangos_spell_learn_spell.sql b/sql/updates/0.10/5530_mangos_spell_learn_spell.sql new file mode 100644 index 00000000000..0fedce3f45e --- /dev/null +++ b/sql/updates/0.10/5530_mangos_spell_learn_spell.sql @@ -0,0 +1,2 @@ +DELETE FROM spell_learn_spell WHERE entry IN (33943); +INSERT INTO spell_learn_spell VALUES (33943,34090,0); diff --git a/sql/updates/0.10/5531_mangos_creature_movement.sql b/sql/updates/0.10/5531_mangos_creature_movement.sql new file mode 100644 index 00000000000..27c814ab888 --- /dev/null +++ b/sql/updates/0.10/5531_mangos_creature_movement.sql @@ -0,0 +1,2 @@ +ALTER TABLE `creature_movement` + CHANGE COLUMN `id` `id` int(10) unsigned NOT NULL auto_increment COMMENT 'Creature GUID'; diff --git a/sql/updates/0.10/5534_mangos_player_levelstats.sql b/sql/updates/0.10/5534_mangos_player_levelstats.sql new file mode 100644 index 00000000000..4401004286b --- /dev/null +++ b/sql/updates/0.10/5534_mangos_player_levelstats.sql @@ -0,0 +1,144 @@ +-- Druid update + +UPDATE `player_levelstats` SET `basehp` = 44, `basemana` = 60 WHERE `class` = 11 AND `level`= 1; +UPDATE `player_levelstats` SET `basehp` = 51, `basemana` = 66 WHERE `class` = 11 AND `level`= 2; +UPDATE `player_levelstats` SET `basehp` = 58, `basemana` = 73 WHERE `class` = 11 AND `level`= 3; +UPDATE `player_levelstats` SET `basehp` = 75, `basemana` = 81 WHERE `class` = 11 AND `level`= 4; +UPDATE `player_levelstats` SET `basehp` = 82, `basemana` = 90 WHERE `class` = 11 AND `level`= 5; +UPDATE `player_levelstats` SET `basehp` = 89, `basemana` = 100 WHERE `class` = 11 AND `level`= 6; +UPDATE `player_levelstats` SET `basehp` = 106, `basemana` = 111 WHERE `class` = 11 AND `level`= 7; +UPDATE `player_levelstats` SET `basehp` = 113, `basemana` = 123 WHERE `class` = 11 AND `level`= 8; +UPDATE `player_levelstats` SET `basehp` = 120, `basemana` = 136 WHERE `class` = 11 AND `level`= 9; +UPDATE `player_levelstats` SET `basehp` = 137, `basemana` = 150 WHERE `class` = 11 AND `level`= 10; +UPDATE `player_levelstats` SET `basehp` = 144, `basemana` = 165 WHERE `class` = 11 AND `level`= 11; +UPDATE `player_levelstats` SET `basehp` = 151, `basemana` = 182 WHERE `class` = 11 AND `level`= 12; +UPDATE `player_levelstats` SET `basehp` = 168, `basemana` = 200 WHERE `class` = 11 AND `level`= 13; +UPDATE `player_levelstats` SET `basehp` = 175, `basemana` = 219 WHERE `class` = 11 AND `level`= 14; +UPDATE `player_levelstats` SET `basehp` = 182, `basemana` = 239 WHERE `class` = 11 AND `level`= 15; +UPDATE `player_levelstats` SET `basehp` = 199, `basemana` = 260 WHERE `class` = 11 AND `level`= 16; +UPDATE `player_levelstats` SET `basehp` = 206, `basemana` = 282 WHERE `class` = 11 AND `level`= 17; +UPDATE `player_levelstats` SET `basehp` = 214, `basemana` = 305 WHERE `class` = 11 AND `level`= 18; +UPDATE `player_levelstats` SET `basehp` = 233, `basemana` = 329 WHERE `class` = 11 AND `level`= 19; +UPDATE `player_levelstats` SET `basehp` = 243, `basemana` = 354 WHERE `class` = 11 AND `level`= 20; +UPDATE `player_levelstats` SET `basehp` = 254, `basemana` = 380 WHERE `class` = 11 AND `level`= 21; +UPDATE `player_levelstats` SET `basehp` = 266, `basemana` = 392 WHERE `class` = 11 AND `level`= 22; +UPDATE `player_levelstats` SET `basehp` = 289, `basemana` = 420 WHERE `class` = 11 AND `level`= 23; +UPDATE `player_levelstats` SET `basehp` = 303, `basemana` = 449 WHERE `class` = 11 AND `level`= 24; +UPDATE `player_levelstats` SET `basehp` = 318, `basemana` = 479 WHERE `class` = 11 AND `level`= 25; +UPDATE `player_levelstats` SET `basehp` = 334, `basemana` = 509 WHERE `class` = 11 AND `level`= 26; +UPDATE `player_levelstats` SET `basehp` = 361, `basemana` = 524 WHERE `class` = 11 AND `level`= 27; +UPDATE `player_levelstats` SET `basehp` = 379, `basemana` = 554 WHERE `class` = 11 AND `level`= 28; +UPDATE `player_levelstats` SET `basehp` = 398, `basemana` = 584 WHERE `class` = 11 AND `level`= 29; +UPDATE `player_levelstats` SET `basehp` = 418, `basemana` = 614 WHERE `class` = 11 AND `level`= 30; +UPDATE `player_levelstats` SET `basehp` = 439, `basemana` = 629 WHERE `class` = 11 AND `level`= 31; +UPDATE `player_levelstats` SET `basehp` = 461, `basemana` = 659 WHERE `class` = 11 AND `level`= 32; +UPDATE `player_levelstats` SET `basehp` = 494, `basemana` = 689 WHERE `class` = 11 AND `level`= 33; +UPDATE `player_levelstats` SET `basehp` = 518, `basemana` = 704 WHERE `class` = 11 AND `level`= 34; +UPDATE `player_levelstats` SET `basehp` = 543, `basemana` = 734 WHERE `class` = 11 AND `level`= 35; +UPDATE `player_levelstats` SET `basehp` = 569, `basemana` = 749 WHERE `class` = 11 AND `level`= 36; +UPDATE `player_levelstats` SET `basehp` = 596, `basemana` = 779 WHERE `class` = 11 AND `level`= 37; +UPDATE `player_levelstats` SET `basehp` = 624, `basemana` = 809 WHERE `class` = 11 AND `level`= 38; +UPDATE `player_levelstats` SET `basehp` = 653, `basemana` = 824 WHERE `class` = 11 AND `level`= 39; +UPDATE `player_levelstats` SET `basehp` = 683, `basemana` = 854 WHERE `class` = 11 AND `level`= 40; +UPDATE `player_levelstats` SET `basehp` = 714, `basemana` = 869 WHERE `class` = 11 AND `level`= 41; +UPDATE `player_levelstats` SET `basehp` = 746, `basemana` = 899 WHERE `class` = 11 AND `level`= 42; +UPDATE `player_levelstats` SET `basehp` = 779, `basemana` = 914 WHERE `class` = 11 AND `level`= 43; +UPDATE `player_levelstats` SET `basehp` = 823, `basemana` = 944 WHERE `class` = 11 AND `level`= 44; +UPDATE `player_levelstats` SET `basehp` = 858, `basemana` = 959 WHERE `class` = 11 AND `level`= 45; +UPDATE `player_levelstats` SET `basehp` = 894, `basemana` = 989 WHERE `class` = 11 AND `level`= 46; +UPDATE `player_levelstats` SET `basehp` = 921, `basemana` = 1004 WHERE `class` = 11 AND `level`= 47; +UPDATE `player_levelstats` SET `basehp` = 959, `basemana` = 1019 WHERE `class` = 11 AND `level`= 48; +UPDATE `player_levelstats` SET `basehp` = 998, `basemana` = 1049 WHERE `class` = 11 AND `level`= 49; +UPDATE `player_levelstats` SET `basehp` = 1038, `basemana` = 1064 WHERE `class` = 11 AND `level`= 50; +UPDATE `player_levelstats` SET `basehp` = 1079, `basemana` = 1079 WHERE `class` = 11 AND `level`= 51; +UPDATE `player_levelstats` SET `basehp` = 1121, `basemana` = 1109 WHERE `class` = 11 AND `level`= 52; +UPDATE `player_levelstats` SET `basehp` = 1164, `basemana` = 1124 WHERE `class` = 11 AND `level`= 53; +UPDATE `player_levelstats` SET `basehp` = 1208, `basemana` = 1139 WHERE `class` = 11 AND `level`= 54; +UPDATE `player_levelstats` SET `basehp` = 1253, `basemana` = 1154 WHERE `class` = 11 AND `level`= 55; +UPDATE `player_levelstats` SET `basehp` = 1299, `basemana` = 1169 WHERE `class` = 11 AND `level`= 56; +UPDATE `player_levelstats` SET `basehp` = 1346, `basemana` = 1199 WHERE `class` = 11 AND `level`= 57; +UPDATE `player_levelstats` SET `basehp` = 1384, `basemana` = 1214 WHERE `class` = 11 AND `level`= 58; +UPDATE `player_levelstats` SET `basehp` = 1433, `basemana` = 1229 WHERE `class` = 11 AND `level`= 59; +UPDATE `player_levelstats` SET `basehp` = 1483, `basemana` = 1244 WHERE `class` = 11 AND `level`= 60; +UPDATE `player_levelstats` SET `basehp` = 1657, `basemana` = 1357 WHERE `class` = 11 AND `level`= 61; +UPDATE `player_levelstats` SET `basehp` = 1840, `basemana` = 1469 WHERE `class` = 11 AND `level`= 62; +UPDATE `player_levelstats` SET `basehp` = 2020, `basemana` = 1582 WHERE `class` = 11 AND `level`= 63; +UPDATE `player_levelstats` SET `basehp` = 2222, `basemana` = 1694 WHERE `class` = 11 AND `level`= 64; +UPDATE `player_levelstats` SET `basehp` = 2433, `basemana` = 1807 WHERE `class` = 11 AND `level`= 65; +UPDATE `player_levelstats` SET `basehp` = 2640, `basemana` = 1919 WHERE `class` = 11 AND `level`= 66; +UPDATE `player_levelstats` SET `basehp` = 2872, `basemana` = 2032 WHERE `class` = 11 AND `level`= 67; +UPDATE `player_levelstats` SET `basehp` = 3114, `basemana` = 2145 WHERE `class` = 11 AND `level`= 68; +UPDATE `player_levelstats` SET `basehp` = 3351, `basemana` = 2257 WHERE `class` = 11 AND `level`= 69; +UPDATE `player_levelstats` SET `basehp` = 3614, `basemana` = 2370 WHERE `class` = 11 AND `level`= 70; + +-- Shaman update +UPDATE `player_levelstats` SET `basehp` = 37, `basemana` = 85 WHERE `class` = 7 AND `level`= 1; +UPDATE `player_levelstats` SET `basehp` = 44, `basemana` = 91 WHERE `class` = 7 AND `level`= 2; +UPDATE `player_levelstats` SET `basehp` = 51, `basemana` = 98 WHERE `class` = 7 AND `level`= 3; +UPDATE `player_levelstats` SET `basehp` = 58, `basemana` = 106 WHERE `class` = 7 AND `level`= 4; +UPDATE `player_levelstats` SET `basehp` = 65, `basemana` = 115 WHERE `class` = 7 AND `level`= 5; +UPDATE `player_levelstats` SET `basehp` = 72, `basemana` = 125 WHERE `class` = 7 AND `level`= 6; +UPDATE `player_levelstats` SET `basehp` = 79, `basemana` = 136 WHERE `class` = 7 AND `level`= 7; +UPDATE `player_levelstats` SET `basehp` = 86, `basemana` = 148 WHERE `class` = 7 AND `level`= 8; +UPDATE `player_levelstats` SET `basehp` = 93, `basemana` = 161 WHERE `class` = 7 AND `level`= 9; +UPDATE `player_levelstats` SET `basehp` = 100, `basemana` = 175 WHERE `class` = 7 AND `level`= 10; +UPDATE `player_levelstats` SET `basehp` = 107, `basemana` = 190 WHERE `class` = 7 AND `level`= 11; +UPDATE `player_levelstats` SET `basehp` = 114, `basemana` = 206 WHERE `class` = 7 AND `level`= 12; +UPDATE `player_levelstats` SET `basehp` = 121, `basemana` = 223 WHERE `class` = 7 AND `level`= 13; +UPDATE `player_levelstats` SET `basehp` = 128, `basemana` = 241 WHERE `class` = 7 AND `level`= 14; +UPDATE `player_levelstats` SET `basehp` = 135, `basemana` = 260 WHERE `class` = 7 AND `level`= 15; +UPDATE `player_levelstats` SET `basehp` = 142, `basemana` = 280 WHERE `class` = 7 AND `level`= 16; +UPDATE `player_levelstats` SET `basehp` = 150, `basemana` = 301 WHERE `class` = 7 AND `level`= 17; +UPDATE `player_levelstats` SET `basehp` = 159, `basemana` = 323 WHERE `class` = 7 AND `level`= 18; +UPDATE `player_levelstats` SET `basehp` = 169, `basemana` = 346 WHERE `class` = 7 AND `level`= 19; +UPDATE `player_levelstats` SET `basehp` = 180, `basemana` = 370 WHERE `class` = 7 AND `level`= 20; +UPDATE `player_levelstats` SET `basehp` = 192, `basemana` = 395 WHERE `class` = 7 AND `level`= 21; +UPDATE `player_levelstats` SET `basehp` = 205, `basemana` = 421 WHERE `class` = 7 AND `level`= 22; +UPDATE `player_levelstats` SET `basehp` = 219, `basemana` = 448 WHERE `class` = 7 AND `level`= 23; +UPDATE `player_levelstats` SET `basehp` = 234, `basemana` = 476 WHERE `class` = 7 AND `level`= 24; +UPDATE `player_levelstats` SET `basehp` = 240, `basemana` = 505 WHERE `class` = 7 AND `level`= 25; +UPDATE `player_levelstats` SET `basehp` = 257, `basemana` = 535 WHERE `class` = 7 AND `level`= 26; +UPDATE `player_levelstats` SET `basehp` = 275, `basemana` = 566 WHERE `class` = 7 AND `level`= 27; +UPDATE `player_levelstats` SET `basehp` = 294, `basemana` = 598 WHERE `class` = 7 AND `level`= 28; +UPDATE `player_levelstats` SET `basehp` = 314, `basemana` = 631 WHERE `class` = 7 AND `level`= 29; +UPDATE `player_levelstats` SET `basehp` = 335, `basemana` = 665 WHERE `class` = 7 AND `level`= 30; +UPDATE `player_levelstats` SET `basehp` = 347, `basemana` = 699 WHERE `class` = 7 AND `level`= 31; +UPDATE `player_levelstats` SET `basehp` = 370, `basemana` = 733 WHERE `class` = 7 AND `level`= 32; +UPDATE `player_levelstats` SET `basehp` = 394, `basemana` = 767 WHERE `class` = 7 AND `level`= 33; +UPDATE `player_levelstats` SET `basehp` = 419, `basemana` = 786 WHERE `class` = 7 AND `level`= 34; +UPDATE `player_levelstats` SET `basehp` = 435, `basemana` = 820 WHERE `class` = 7 AND `level`= 35; +UPDATE `player_levelstats` SET `basehp` = 462, `basemana` = 854 WHERE `class` = 7 AND `level`= 36; +UPDATE `player_levelstats` SET `basehp` = 490, `basemana` = 888 WHERE `class` = 7 AND `level`= 37; +UPDATE `player_levelstats` SET `basehp` = 509, `basemana` = 922 WHERE `class` = 7 AND `level`= 38; +UPDATE `player_levelstats` SET `basehp` = 539, `basemana` = 941 WHERE `class` = 7 AND `level`= 39; +UPDATE `player_levelstats` SET `basehp` = 570, `basemana` = 975 WHERE `class` = 7 AND `level`= 40; +UPDATE `player_levelstats` SET `basehp` = 592, `basemana` = 1009 WHERE `class` = 7 AND `level`= 41; +UPDATE `player_levelstats` SET `basehp` = 625, `basemana` = 1028 WHERE `class` = 7 AND `level`= 42; +UPDATE `player_levelstats` SET `basehp` = 649, `basemana` = 1062 WHERE `class` = 7 AND `level`= 43; +UPDATE `player_levelstats` SET `basehp` = 684, `basemana` = 1096 WHERE `class` = 7 AND `level`= 44; +UPDATE `player_levelstats` SET `basehp` = 710, `basemana` = 1115 WHERE `class` = 7 AND `level`= 45; +UPDATE `player_levelstats` SET `basehp` = 747, `basemana` = 1149 WHERE `class` = 7 AND `level`= 46; +UPDATE `player_levelstats` SET `basehp` = 775, `basemana` = 1183 WHERE `class` = 7 AND `level`= 47; +UPDATE `player_levelstats` SET `basehp` = 814, `basemana` = 1202 WHERE `class` = 7 AND `level`= 48; +UPDATE `player_levelstats` SET `basehp` = 844, `basemana` = 1236 WHERE `class` = 7 AND `level`= 49; +UPDATE `player_levelstats` SET `basehp` = 885, `basemana` = 1255 WHERE `class` = 7 AND `level`= 50; +UPDATE `player_levelstats` SET `basehp` = 917, `basemana` = 1289 WHERE `class` = 7 AND `level`= 51; +UPDATE `player_levelstats` SET `basehp` = 960, `basemana` = 1323 WHERE `class` = 7 AND `level`= 52; +UPDATE `player_levelstats` SET `basehp` = 994, `basemana` = 1342 WHERE `class` = 7 AND `level`= 53; +UPDATE `player_levelstats` SET `basehp` = 1029, `basemana` = 1376 WHERE `class` = 7 AND `level`= 54; +UPDATE `player_levelstats` SET `basehp` = 1075, `basemana` = 1395 WHERE `class` = 7 AND `level`= 55; +UPDATE `player_levelstats` SET `basehp` = 1112, `basemana` = 1414 WHERE `class` = 7 AND `level`= 56; +UPDATE `player_levelstats` SET `basehp` = 1150, `basemana` = 1448 WHERE `class` = 7 AND `level`= 57; +UPDATE `player_levelstats` SET `basehp` = 1199, `basemana` = 1467 WHERE `class` = 7 AND `level`= 58; +UPDATE `player_levelstats` SET `basehp` = 1239, `basemana` = 1501 WHERE `class` = 7 AND `level`= 59; +UPDATE `player_levelstats` SET `basehp` = 1330, `basemana` = 1520 WHERE `class` = 7 AND `level`= 60; +UPDATE `player_levelstats` SET `basehp` = 1428, `basemana` = 1664 WHERE `class` = 7 AND `level`= 61; +UPDATE `player_levelstats` SET `basehp` = 1583, `basemana` = 1808 WHERE `class` = 7 AND `level`= 62; +UPDATE `player_levelstats` SET `basehp` = 1760, `basemana` = 1951 WHERE `class` = 7 AND `level`= 63; +UPDATE `player_levelstats` SET `basehp` = 1932, `basemana` = 2095 WHERE `class` = 7 AND `level`= 64; +UPDATE `player_levelstats` SET `basehp` = 2114, `basemana` = 2239 WHERE `class` = 7 AND `level`= 65; +UPDATE `player_levelstats` SET `basehp` = 2304, `basemana` = 2383 WHERE `class` = 7 AND `level`= 66; +UPDATE `player_levelstats` SET `basehp` = 2504, `basemana` = 2527 WHERE `class` = 7 AND `level`= 67; +UPDATE `player_levelstats` SET `basehp` = 2713, `basemana` = 2670 WHERE `class` = 7 AND `level`= 68; +UPDATE `player_levelstats` SET `basehp` = 2931, `basemana` = 2814 WHERE `class` = 7 AND `level`= 69; +UPDATE `player_levelstats` SET `basehp` = 3159, `basemana` = 2958 WHERE `class` = 7 AND `level`= 70; diff --git a/sql/updates/0.10/5541_mangos_command.sql b/sql/updates/0.10/5541_mangos_command.sql new file mode 100644 index 00000000000..bf248479b1f --- /dev/null +++ b/sql/updates/0.10/5541_mangos_command.sql @@ -0,0 +1,5 @@ +DELETE FROM `command` WHERE `name` = 'learn all_default'; + +INSERT INTO `command` VALUES +('learn all_default',1,'Syntax: .learn all_default [$playername]\r\n\r\nLearn for selected/$playername player all default spells for his race/class and spells rewarded by completed quests.'); + diff --git a/sql/updates/0.10/5541_mangos_mangos_string.sql b/sql/updates/0.10/5541_mangos_mangos_string.sql new file mode 100644 index 00000000000..ee5a1304439 --- /dev/null +++ b/sql/updates/0.10/5541_mangos_mangos_string.sql @@ -0,0 +1,3 @@ +DELETE FROM mangos_string WHERE entry in (580); +INSERT INTO mangos_string VALUES +(580,'Player %s learned all default spells for race/class and completed quests rewarded spells.',NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/0.10/5547_characters_character_ticket.sql b/sql/updates/0.10/5547_characters_character_ticket.sql new file mode 100644 index 00000000000..3c6cb216035 --- /dev/null +++ b/sql/updates/0.10/5547_characters_character_ticket.sql @@ -0,0 +1,2 @@ +ALTER TABLE `character_ticket` + ADD `ticket_lastchange` TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ; diff --git a/sql/updates/0.10/5547_mangos_mangos_string.sql b/sql/updates/0.10/5547_mangos_mangos_string.sql new file mode 100644 index 00000000000..88e2849e424 --- /dev/null +++ b/sql/updates/0.10/5547_mangos_mangos_string.sql @@ -0,0 +1,4 @@ +DELETE FROM mangos_string WHERE entry in (290); +INSERT INTO mangos_string VALUES +(290,'Ticket of %s (Last updated: %s) (Category: %i):\n%s ',NULL,NULL,NULL,NULL,NULL,NULL,NULL); + diff --git a/sql/updates/0.10/5554_mangos_locales_creature.sql b/sql/updates/0.10/5554_mangos_locales_creature.sql new file mode 100644 index 00000000000..f88e0517835 --- /dev/null +++ b/sql/updates/0.10/5554_mangos_locales_creature.sql @@ -0,0 +1,2 @@ +ALTER TABLE locales_creature + DROP subname_loc8; diff --git a/sql/updates/0.10/5558_mangos_player_levelstats.sql b/sql/updates/0.10/5558_mangos_player_levelstats.sql new file mode 100644 index 00000000000..70d231082c8 --- /dev/null +++ b/sql/updates/0.10/5558_mangos_player_levelstats.sql @@ -0,0 +1,70 @@ +UPDATE `player_levelstats` SET `basehp` = 52, `basemana` = 73 WHERE `class` = 5 AND `level`= 1; +UPDATE `player_levelstats` SET `basehp` = 57, `basemana` = 76 WHERE `class` = 5 AND `level`= 2; +UPDATE `player_levelstats` SET `basehp` = 72, `basemana` = 95 WHERE `class` = 5 AND `level`= 3; +UPDATE `player_levelstats` SET `basehp` = 77, `basemana` = 114 WHERE `class` = 5 AND `level`= 4; +UPDATE `player_levelstats` SET `basehp` = 92, `basemana` = 133 WHERE `class` = 5 AND `level`= 5; +UPDATE `player_levelstats` SET `basehp` = 97, `basemana` = 152 WHERE `class` = 5 AND `level`= 6; +UPDATE `player_levelstats` SET `basehp` = 112, `basemana` = 171 WHERE `class` = 5 AND `level`= 7; +UPDATE `player_levelstats` SET `basehp` = 117, `basemana` = 190 WHERE `class` = 5 AND `level`= 8; +UPDATE `player_levelstats` SET `basehp` = 132, `basemana` = 209 WHERE `class` = 5 AND `level`= 9; +UPDATE `player_levelstats` SET `basehp` = 137, `basemana` = 212 WHERE `class` = 5 AND `level`= 10; +UPDATE `player_levelstats` SET `basehp` = 142, `basemana` = 215 WHERE `class` = 5 AND `level`= 11; +UPDATE `player_levelstats` SET `basehp` = 157, `basemana` = 234 WHERE `class` = 5 AND `level`= 12; +UPDATE `player_levelstats` SET `basehp` = 172, `basemana` = 254 WHERE `class` = 5 AND `level`= 13; +UPDATE `player_levelstats` SET `basehp` = 177, `basemana` = 260 WHERE `class` = 5 AND `level`= 14; +UPDATE `player_levelstats` SET `basehp` = 192, `basemana` = 282 WHERE `class` = 5 AND `level`= 15; +UPDATE `player_levelstats` SET `basehp` = 197, `basemana` = 305 WHERE `class` = 5 AND `level`= 16; +UPDATE `player_levelstats` SET `basehp` = 212, `basemana` = 329 WHERE `class` = 5 AND `level`= 17; +UPDATE `player_levelstats` SET `basehp` = 227, `basemana` = 339 WHERE `class` = 5 AND `level`= 18; +UPDATE `player_levelstats` SET `basehp` = 232, `basemana` = 365 WHERE `class` = 5 AND `level`= 19; +UPDATE `player_levelstats` SET `basehp` = 247, `basemana` = 377 WHERE `class` = 5 AND `level`= 20; +UPDATE `player_levelstats` SET `basehp` = 252, `basemana` = 405 WHERE `class` = 5 AND `level`= 21; +UPDATE `player_levelstats` SET `basehp` = 268, `basemana` = 434 WHERE `class` = 5 AND `level`= 22; +UPDATE `player_levelstats` SET `basehp` = 275, `basemana` = 449 WHERE `class` = 5 AND `level`= 23; +UPDATE `player_levelstats` SET `basehp` = 293, `basemana` = 480 WHERE `class` = 5 AND `level`= 24; +UPDATE `player_levelstats` SET `basehp` = 302, `basemana` = 497 WHERE `class` = 5 AND `level`= 25; +UPDATE `player_levelstats` SET `basehp` = 322, `basemana` = 530 WHERE `class` = 5 AND `level`= 26; +UPDATE `player_levelstats` SET `basehp` = 343, `basemana` = 549 WHERE `class` = 5 AND `level`= 27; +UPDATE `player_levelstats` SET `basehp` = 355, `basemana` = 584 WHERE `class` = 5 AND `level`= 28; +UPDATE `player_levelstats` SET `basehp` = 378, `basemana` = 605 WHERE `class` = 5 AND `level`= 29; +UPDATE `player_levelstats` SET `basehp` = 392, `basemana` = 627 WHERE `class` = 5 AND `level`= 30; +UPDATE `player_levelstats` SET `basehp` = 417, `basemana` = 665 WHERE `class` = 5 AND `level`= 31; +UPDATE `player_levelstats` SET `basehp` = 433, `basemana` = 689 WHERE `class` = 5 AND `level`= 32; +UPDATE `player_levelstats` SET `basehp` = 460, `basemana` = 728 WHERE `class` = 5 AND `level`= 33; +UPDATE `player_levelstats` SET `basehp` = 478, `basemana` = 752 WHERE `class` = 5 AND `level`= 34; +UPDATE `player_levelstats` SET `basehp` = 507, `basemana` = 776 WHERE `class` = 5 AND `level`= 35; +UPDATE `player_levelstats` SET `basehp` = 527, `basemana` = 800 WHERE `class` = 5 AND `level`= 36; +UPDATE `player_levelstats` SET `basehp` = 548, `basemana` = 839 WHERE `class` = 5 AND `level`= 37; +UPDATE `player_levelstats` SET `basehp` = 580, `basemana` = 863 WHERE `class` = 5 AND `level`= 38; +UPDATE `player_levelstats` SET `basehp` = 603, `basemana` = 887 WHERE `class` = 5 AND `level`= 39; +UPDATE `player_levelstats` SET `basehp` = 637, `basemana` = 911 WHERE `class` = 5 AND `level`= 40; +UPDATE `player_levelstats` SET `basehp` = 662, `basemana` = 950 WHERE `class` = 5 AND `level`= 41; +UPDATE `player_levelstats` SET `basehp` = 698, `basemana` = 974 WHERE `class` = 5 AND `level`= 42; +UPDATE `player_levelstats` SET `basehp` = 725, `basemana` = 998 WHERE `class` = 5 AND `level`= 43; +UPDATE `player_levelstats` SET `basehp` = 763, `basemana` = 1022 WHERE `class` = 5 AND `level`= 44; +UPDATE `player_levelstats` SET `basehp` = 792, `basemana` = 1046 WHERE `class` = 5 AND `level`= 45; +UPDATE `player_levelstats` SET `basehp` = 822, `basemana` = 1070 WHERE `class` = 5 AND `level`= 46; +UPDATE `player_levelstats` SET `basehp` = 863, `basemana` = 1094 WHERE `class` = 5 AND `level`= 47; +UPDATE `player_levelstats` SET `basehp` = 895, `basemana` = 1118 WHERE `class` = 5 AND `level`= 48; +UPDATE `player_levelstats` SET `basehp` = 928, `basemana` = 1142 WHERE `class` = 5 AND `level`= 49; +UPDATE `player_levelstats` SET `basehp` = 972, `basemana` = 1166 WHERE `class` = 5 AND `level`= 50; +UPDATE `player_levelstats` SET `basehp` = 1007, `basemana` = 1190 WHERE `class` = 5 AND `level`= 51; +UPDATE `player_levelstats` SET `basehp` = 1053, `basemana` = 1214 WHERE `class` = 5 AND `level`= 52; +UPDATE `player_levelstats` SET `basehp` = 1090, `basemana` = 1238 WHERE `class` = 5 AND `level`= 53; +UPDATE `player_levelstats` SET `basehp` = 1128, `basemana` = 1262 WHERE `class` = 5 AND `level`= 54; +UPDATE `player_levelstats` SET `basehp` = 1177, `basemana` = 1271 WHERE `class` = 5 AND `level`= 55; +UPDATE `player_levelstats` SET `basehp` = 1217, `basemana` = 1295 WHERE `class` = 5 AND `level`= 56; +UPDATE `player_levelstats` SET `basehp` = 1258, `basemana` = 1319 WHERE `class` = 5 AND `level`= 57; +UPDATE `player_levelstats` SET `basehp` = 1300, `basemana` = 1343 WHERE `class` = 5 AND `level`= 58; +UPDATE `player_levelstats` SET `basehp` = 1353, `basemana` = 1352 WHERE `class` = 5 AND `level`= 59; +UPDATE `player_levelstats` SET `basehp` = 1397, `basemana` = 1376 WHERE `class` = 5 AND `level`= 60; +UPDATE `player_levelstats` SET `basehp` = 1557, `basemana` = 1500 WHERE `class` = 5 AND `level`= 61; +UPDATE `player_levelstats` SET `basehp` = 1738, `basemana` = 1625 WHERE `class` = 5 AND `level`= 62; +UPDATE `player_levelstats` SET `basehp` = 1916, `basemana` = 1749 WHERE `class` = 5 AND `level`= 63; +UPDATE `player_levelstats` SET `basehp` = 2101, `basemana` = 1873 WHERE `class` = 5 AND `level`= 64; +UPDATE `player_levelstats` SET `basehp` = 2295, `basemana` = 1998 WHERE `class` = 5 AND `level`= 65; +UPDATE `player_levelstats` SET `basehp` = 2495, `basemana` = 2122 WHERE `class` = 5 AND `level`= 66; +UPDATE `player_levelstats` SET `basehp` = 2719, `basemana` = 2247 WHERE `class` = 5 AND `level`= 67; +UPDATE `player_levelstats` SET `basehp` = 2936, `basemana` = 2371 WHERE `class` = 5 AND `level`= 68; +UPDATE `player_levelstats` SET `basehp` = 3160, `basemana` = 2495 WHERE `class` = 5 AND `level`= 69; +UPDATE `player_levelstats` SET `basehp` = 3391, `basemana` = 2620 WHERE `class` = 5 AND `level`= 70; diff --git a/sql/updates/0.10/5570_mangos_spell_elixir.sql b/sql/updates/0.10/5570_mangos_spell_elixir.sql new file mode 100644 index 00000000000..ce79ef1701c --- /dev/null +++ b/sql/updates/0.10/5570_mangos_spell_elixir.sql @@ -0,0 +1,118 @@ +DROP TABLE IF EXISTS `spell_elixir`; +CREATE TABLE `spell_elixir` ( + `entry` int(11) unsigned NOT NULL default '0' COMMENT 'SpellId of potion', + `mask` tinyint(1) unsigned NOT NULL default '0' COMMENT 'Mask 0x1 battle 0x2 guardian 0x3 flask 0x7 unstable flasks 0xB shattrath flasks', + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Spell System'; + + +/* shattrath */ +INSERT INTO `spell_elixir` VALUES +(41608,0xB), +(41609,0xB), +(41610,0xB), +(41611,0xB); +/* 2.4.0 +(46837,0xB), +(46839,0xB); +*/ +/* unstable */ +INSERT INTO `spell_elixir` VALUES +(40567,0x7), +(40568,0x7), +(40572,0x7), +(40573,0x7), +(40575,0x7), +(40576,0x7); +/* Normal Flask */ +INSERT INTO `spell_elixir` VALUES +(17624,0x3), +(17626,0x3), +(17627,0x3), +(17629,0x3), +(17628,0x3), +(28518,0x3), +(28519,0x3), +(28520,0x3), +(28521,0x3), +(28540,0x3), +(42735,0x3); +/* Battle Elixirs */ +INSERT INTO `spell_elixir` VALUES +( 2367,0x1), +( 2374,0x1), +( 3160,0x1), +( 3164,0x1), +( 7844,0x1), +( 8212,0x1), +(10667,0x1), +(10669,0x1), +(11328,0x1), +(11334,0x1), +(11390,0x1), +(11405,0x1), +(11406,0x1), +(11474,0x1), +(16322,0x1), +(16323,0x1), +(16329,0x1), +(17038,0x1), +(17537,0x1), +(17538,0x1), +(17539,0x1), +(21920,0x1),/**/ +(26276,0x1), +(28486,0x1), +(28488,0x1), +(28490,0x1), +(28491,0x1), +(28493,0x1), +(28497,0x1), +(28501,0x1), +(28503,0x1), +(33720,0x1), +(33721,0x1), +(33726,0x1), +(38954,0x1); +/* Guardian Elixirs */ +INSERT INTO `spell_elixir` VALUES +( 673,0x2), +( 2378,0x2), +( 2380,0x2), +( 3166,0x2), +( 3219,0x2), +( 3220,0x2), +( 3222,0x2), +( 3223,0x2), +( 3593,0x2), +(10668,0x2), +(10692,0x2), +(10693,0x2), +(11319,0x2), +(11348,0x2), +(11349,0x2), +(16321,0x2), +(11364,0x2), +(11371,0x2), +(11396,0x2), +(15231,0x2), +(15233,0x2), +(16325,0x2), +(16326,0x2), +(16327,0x2), +(17535,0x2), +(24361,0x2), +(24363,0x2), +(24382,0x2), +(24383,0x2), +(24417,0x2), +(27652,0x2), +(27653,0x2), +(28502,0x2), +(28509,0x2), +(28514,0x2), +(29348,0x2), +(39625,0x2), +(39626,0x2), +(39627,0x2), +(39628,0x2); diff --git a/sql/updates/0.10/5571_mangos_player_levelstats.sql b/sql/updates/0.10/5571_mangos_player_levelstats.sql new file mode 100644 index 00000000000..6962e0a1226 --- /dev/null +++ b/sql/updates/0.10/5571_mangos_player_levelstats.sql @@ -0,0 +1,70 @@ +UPDATE `player_levelstats` SET `basehp` = 46, `basemana` = 65 WHERE `class` = 3 AND `level`= 1; +UPDATE `player_levelstats` SET `basehp` = 53, `basemana` = 70 WHERE `class` = 3 AND `level`= 2; +UPDATE `player_levelstats` SET `basehp` = 60, `basemana` = 76 WHERE `class` = 3 AND `level`= 3; +UPDATE `player_levelstats` SET `basehp` = 67, `basemana` = 98 WHERE `class` = 3 AND `level`= 4; +UPDATE `player_levelstats` SET `basehp` = 74, `basemana` = 106 WHERE `class` = 3 AND `level`= 5; +UPDATE `player_levelstats` SET `basehp` = 81, `basemana` = 130 WHERE `class` = 3 AND `level`= 6; +UPDATE `player_levelstats` SET `basehp` = 88, `basemana` = 140 WHERE `class` = 3 AND `level`= 7; +UPDATE `player_levelstats` SET `basehp` = 95, `basemana` = 166 WHERE `class` = 3 AND `level`= 8; +UPDATE `player_levelstats` SET `basehp` = 102, `basemana` = 193 WHERE `class` = 3 AND `level`= 9; +UPDATE `player_levelstats` SET `basehp` = 109, `basemana` = 206 WHERE `class` = 3 AND `level`= 10; +UPDATE `player_levelstats` SET `basehp` = 116, `basemana` = 235 WHERE `class` = 3 AND `level`= 11; +UPDATE `player_levelstats` SET `basehp` = 123, `basemana` = 250 WHERE `class` = 3 AND `level`= 12; +UPDATE `player_levelstats` SET `basehp` = 130, `basemana` = 266 WHERE `class` = 3 AND `level`= 13; +UPDATE `player_levelstats` SET `basehp` = 138, `basemana` = 298 WHERE `class` = 3 AND `level`= 14; +UPDATE `player_levelstats` SET `basehp` = 147, `basemana` = 316 WHERE `class` = 3 AND `level`= 15; +UPDATE `player_levelstats` SET `basehp` = 157, `basemana` = 350 WHERE `class` = 3 AND `level`= 16; +UPDATE `player_levelstats` SET `basehp` = 168, `basemana` = 370 WHERE `class` = 3 AND `level`= 17; +UPDATE `player_levelstats` SET `basehp` = 180, `basemana` = 391 WHERE `class` = 3 AND `level`= 18; +UPDATE `player_levelstats` SET `basehp` = 193, `basemana` = 428 WHERE `class` = 3 AND `level`= 19; +UPDATE `player_levelstats` SET `basehp` = 207, `basemana` = 451 WHERE `class` = 3 AND `level`= 20; +UPDATE `player_levelstats` SET `basehp` = 222, `basemana` = 475 WHERE `class` = 3 AND `level`= 21; +UPDATE `player_levelstats` SET `basehp` = 238, `basemana` = 515 WHERE `class` = 3 AND `level`= 22; +UPDATE `player_levelstats` SET `basehp` = 255, `basemana` = 541 WHERE `class` = 3 AND `level`= 23; +UPDATE `player_levelstats` SET `basehp` = 273, `basemana` = 568 WHERE `class` = 3 AND `level`= 24; +UPDATE `player_levelstats` SET `basehp` = 292, `basemana` = 611 WHERE `class` = 3 AND `level`= 25; +UPDATE `player_levelstats` SET `basehp` = 312, `basemana` = 640 WHERE `class` = 3 AND `level`= 26; +UPDATE `player_levelstats` SET `basehp` = 333, `basemana` = 670 WHERE `class` = 3 AND `level`= 27; +UPDATE `player_levelstats` SET `basehp` = 355, `basemana` = 715 WHERE `class` = 3 AND `level`= 28; +UPDATE `player_levelstats` SET `basehp` = 378, `basemana` = 745 WHERE `class` = 3 AND `level`= 29; +UPDATE `player_levelstats` SET `basehp` = 402, `basemana` = 775 WHERE `class` = 3 AND `level`= 30; +UPDATE `player_levelstats` SET `basehp` = 417, `basemana` = 805 WHERE `class` = 3 AND `level`= 31; +UPDATE `player_levelstats` SET `basehp` = 443, `basemana` = 850 WHERE `class` = 3 AND `level`= 32; +UPDATE `player_levelstats` SET `basehp` = 470, `basemana` = 880 WHERE `class` = 3 AND `level`= 33; +UPDATE `player_levelstats` SET `basehp` = 498, `basemana` = 910 WHERE `class` = 3 AND `level`= 34; +UPDATE `player_levelstats` SET `basehp` = 527, `basemana` = 940 WHERE `class` = 3 AND `level`= 35; +UPDATE `player_levelstats` SET `basehp` = 547, `basemana` = 970 WHERE `class` = 3 AND `level`= 36; +UPDATE `player_levelstats` SET `basehp` = 578, `basemana` = 1015 WHERE `class` = 3 AND `level`= 37; +UPDATE `player_levelstats` SET `basehp` = 610, `basemana` = 1045 WHERE `class` = 3 AND `level`= 38; +UPDATE `player_levelstats` SET `basehp` = 643, `basemana` = 1075 WHERE `class` = 3 AND `level`= 39; +UPDATE `player_levelstats` SET `basehp` = 667, `basemana` = 1105 WHERE `class` = 3 AND `level`= 40; +UPDATE `player_levelstats` SET `basehp` = 702, `basemana` = 1135 WHERE `class` = 3 AND `level`= 41; +UPDATE `player_levelstats` SET `basehp` = 738, `basemana` = 1180 WHERE `class` = 3 AND `level`= 42; +UPDATE `player_levelstats` SET `basehp` = 775, `basemana` = 1210 WHERE `class` = 3 AND `level`= 43; +UPDATE `player_levelstats` SET `basehp` = 803, `basemana` = 1240 WHERE `class` = 3 AND `level`= 44; +UPDATE `player_levelstats` SET `basehp` = 842, `basemana` = 1270 WHERE `class` = 3 AND `level`= 45; +UPDATE `player_levelstats` SET `basehp` = 872, `basemana` = 1300 WHERE `class` = 3 AND `level`= 46; +UPDATE `player_levelstats` SET `basehp` = 913, `basemana` = 1330 WHERE `class` = 3 AND `level`= 47; +UPDATE `player_levelstats` SET `basehp` = 955, `basemana` = 1360 WHERE `class` = 3 AND `level`= 48; +UPDATE `player_levelstats` SET `basehp` = 994, `basemana` = 1390 WHERE `class` = 3 AND `level`= 49; +UPDATE `player_levelstats` SET `basehp` = 1047, `basemana` = 1420 WHERE `class` = 3 AND `level`= 50; +UPDATE `player_levelstats` SET `basehp` = 1067, `basemana` = 1450 WHERE `class` = 3 AND `level`= 51; +UPDATE `player_levelstats` SET `basehp` = 1113, `basemana` = 1480 WHERE `class` = 3 AND `level`= 52; +UPDATE `player_levelstats` SET `basehp` = 1150, `basemana` = 1510 WHERE `class` = 3 AND `level`= 53; +UPDATE `player_levelstats` SET `basehp` = 1198, `basemana` = 1540 WHERE `class` = 3 AND `level`= 54; +UPDATE `player_levelstats` SET `basehp` = 1237, `basemana` = 1570 WHERE `class` = 3 AND `level`= 55; +UPDATE `player_levelstats` SET `basehp` = 1287, `basemana` = 1600 WHERE `class` = 3 AND `level`= 56; +UPDATE `player_levelstats` SET `basehp` = 1328, `basemana` = 1630 WHERE `class` = 3 AND `level`= 57; +UPDATE `player_levelstats` SET `basehp` = 1370, `basemana` = 1660 WHERE `class` = 3 AND `level`= 58; +UPDATE `player_levelstats` SET `basehp` = 1423, `basemana` = 1690 WHERE `class` = 3 AND `level`= 59; +UPDATE `player_levelstats` SET `basehp` = 1467, `basemana` = 1720 WHERE `class` = 3 AND `level`= 60; +UPDATE `player_levelstats` SET `basehp` = 1633, `basemana` = 1886 WHERE `class` = 3 AND `level`= 61; +UPDATE `player_levelstats` SET `basehp` = 1819, `basemana` = 2053 WHERE `class` = 3 AND `level`= 62; +UPDATE `player_levelstats` SET `basehp` = 2003, `basemana` = 2219 WHERE `class` = 3 AND `level`= 63; +UPDATE `player_levelstats` SET `basehp` = 2195, `basemana` = 2385 WHERE `class` = 3 AND `level`= 64; +UPDATE `player_levelstats` SET `basehp` = 2397, `basemana` = 2552 WHERE `class` = 3 AND `level`= 65; +UPDATE `player_levelstats` SET `basehp` = 2623, `basemana` = 2718 WHERE `class` = 3 AND `level`= 66; +UPDATE `player_levelstats` SET `basehp` = 2844, `basemana` = 2884 WHERE `class` = 3 AND `level`= 67; +UPDATE `player_levelstats` SET `basehp` = 3075, `basemana` = 3050 WHERE `class` = 3 AND `level`= 68; +UPDATE `player_levelstats` SET `basehp` = 3316, `basemana` = 3217 WHERE `class` = 3 AND `level`= 69; +UPDATE `player_levelstats` SET `basehp` = 3568, `basemana` = 3383 WHERE `class` = 3 AND `level`= 70; diff --git a/sql/updates/0.10/5574_mangos_mangos_string.sql b/sql/updates/0.10/5574_mangos_mangos_string.sql new file mode 100644 index 00000000000..1775837cc4d --- /dev/null +++ b/sql/updates/0.10/5574_mangos_mangos_string.sql @@ -0,0 +1,4 @@ +DELETE FROM mangos_string WHERE entry in (468,470); +INSERT INTO mangos_string VALUES +(468,'id: %d eff: %d type: %d duration: %d maxduration: %d name: %s caster: %s %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(470,'id: %d eff: %d name: %s caster: %s %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/0.10/5574_mangos_spell_learn_spell.sql b/sql/updates/0.10/5574_mangos_spell_learn_spell.sql new file mode 100644 index 00000000000..a701f24a1c6 --- /dev/null +++ b/sql/updates/0.10/5574_mangos_spell_learn_spell.sql @@ -0,0 +1 @@ +DELETE FROM `spell_learn_spell` WHERE `entry` IN (264,266,5011,2018,2108,2259,2366,2550,2567,2575,3273,2842,3908,4036,7411,7620,25229); diff --git a/sql/updates/0.10/5576_mangos_spell_affect.sql b/sql/updates/0.10/5576_mangos_spell_affect.sql new file mode 100644 index 00000000000..4fe35128b36 --- /dev/null +++ b/sql/updates/0.10/5576_mangos_spell_affect.sql @@ -0,0 +1,10 @@ +DELETE FROM spell_affect WHERE entry = 16089; +INSERT INTO spell_affect (entry,effectId,SpellFamily,SpellFamilyMask,Charges) VALUES +(16089,0,0,0x00000004D3300407,0); + +DELETE FROM spell_affect WHERE entry = 16166; +INSERT INTO spell_affect (entry,effectId,SpellFamily,SpellFamilyMask,Charges) VALUES +(16166,0,0,0x0000000090100003,0), +(16166,1,0,0x0000000090100003,0); + + diff --git a/sql/updates/0.10/5576_mangos_spell_proc_event.sql b/sql/updates/0.10/5576_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..2a5daf63586 --- /dev/null +++ b/sql/updates/0.10/5576_mangos_spell_proc_event.sql @@ -0,0 +1 @@ +UPDATE spell_proc_event SET ppmRate = '10.5' WHERE entry = 30823; \ No newline at end of file diff --git a/sql/updates/0.10/5585_mangos_gameobject_template.sql b/sql/updates/0.10/5585_mangos_gameobject_template.sql new file mode 100644 index 00000000000..9a22e2f7e3a --- /dev/null +++ b/sql/updates/0.10/5585_mangos_gameobject_template.sql @@ -0,0 +1 @@ +ALTER TABLE `gameobject_template` ADD COLUMN `castBarCaption` varchar(100) NOT NULL default '' AFTER name; diff --git a/sql/updates/0.10/5585_mangos_locales_gameobject.sql b/sql/updates/0.10/5585_mangos_locales_gameobject.sql new file mode 100644 index 00000000000..d0137e81a81 --- /dev/null +++ b/sql/updates/0.10/5585_mangos_locales_gameobject.sql @@ -0,0 +1,7 @@ +ALTER TABLE `locales_gameobject` ADD COLUMN `castbarcaption_loc1` varchar(100) NOT NULL default '' AFTER name_loc7; +ALTER TABLE `locales_gameobject` ADD COLUMN `castbarcaption_loc2` varchar(100) NOT NULL default '' AFTER castbarcaption_loc1; +ALTER TABLE `locales_gameobject` ADD COLUMN `castbarcaption_loc3` varchar(100) NOT NULL default '' AFTER castbarcaption_loc2; +ALTER TABLE `locales_gameobject` ADD COLUMN `castbarcaption_loc4` varchar(100) NOT NULL default '' AFTER castbarcaption_loc3; +ALTER TABLE `locales_gameobject` ADD COLUMN `castbarcaption_loc5` varchar(100) NOT NULL default '' AFTER castbarcaption_loc4; +ALTER TABLE `locales_gameobject` ADD COLUMN `castbarcaption_loc6` varchar(100) NOT NULL default '' AFTER castbarcaption_loc5; +ALTER TABLE `locales_gameobject` ADD COLUMN `castbarcaption_loc7` varchar(100) NOT NULL default '' AFTER castbarcaption_loc6; \ No newline at end of file diff --git a/sql/updates/0.10/5586_mangos_spell_proc_event.sql b/sql/updates/0.10/5586_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..f6be26460bc --- /dev/null +++ b/sql/updates/0.10/5586_mangos_spell_proc_event.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_proc_event` WHERE `entry`=28305; +INSERT INTO `spell_proc_event` (`entry`, `SchoolMask`, `Category`, `SkillID`, `SpellFamilyName`, `SpellFamilyMask`, `procFlags`, `ppmRate`) VALUE +(28305,0,0,0,0,0x0000000000000000,0x00000001,0); diff --git a/sql/updates/0.10/5589_mangos_spell_proc_event.sql b/sql/updates/0.10/5589_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..32b6041ef43 --- /dev/null +++ b/sql/updates/0.10/5589_mangos_spell_proc_event.sql @@ -0,0 +1,6 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (16952,16954); +INSERT INTO `spell_proc_event` (`entry`, `SchoolMask`, `Category`, `SkillID`, `SpellFamilyName`, `SpellFamilyMask`, `procFlags`, `ppmRate`) VALUE +(16952,0,0,0,0,0x0000040000039000,0x00010000,0), +(16954,0,0,0,0,0x0000040000039000,0x00010000,0); + + diff --git a/sql/updates/0.10/5593_mangos_spell_proc_event.sql b/sql/updates/0.10/5593_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..f45979dc2f1 --- /dev/null +++ b/sql/updates/0.10/5593_mangos_spell_proc_event.sql @@ -0,0 +1,2 @@ +UPDATE spell_proc_event SET ppmRate = 20 WHERE entry IN (20166,20356,20357,27166); +UPDATE spell_proc_event SET ppmRate = 20 WHERE entry IN (20165,20347,20348,20349,27160); diff --git a/sql/updates/0.10/5628_mangos_creature_movement.sql b/sql/updates/0.10/5628_mangos_creature_movement.sql new file mode 100644 index 00000000000..b4903bb1dd5 --- /dev/null +++ b/sql/updates/0.10/5628_mangos_creature_movement.sql @@ -0,0 +1,2 @@ +ALTER TABLE creature_movement + DROP aiscript; diff --git a/sql/updates/0.10/5632_characters.sql b/sql/updates/0.10/5632_characters.sql new file mode 100644 index 00000000000..9cdd8738ecd --- /dev/null +++ b/sql/updates/0.10/5632_characters.sql @@ -0,0 +1,22 @@ +DROP TABLE IF EXISTS item_test; +CREATE TABLE item_test +SELECT w.`item_guid`,w.`source`,w.`count` FROM + (SELECT u.`item_guid`,u.`source`,COUNT(u.`item_guid`) as `count` FROM + ((SELECT c.`item` as `item_guid`, 'i' as `source` FROM character_inventory c) UNION + (SELECT a.`itemguid` as `item_guid`, 'a' as `source` FROM auctionhouse a) UNION + (SELECT m.`item_guid` as `item_guid`, 'm' as `source` FROM mail_items m) UNION + (SELECT g.`item_guid` as `item_guid`, 'g' as `source` FROM guild_bank_item g) + ) as u + GROUP BY u.`item_guid` + ) as w + WHERE w.`count` > 1; + +DELETE FROM auctionhouse WHERE itemguid IN (SELECT item_guid FROM item_test WHERE `source`='i'); +DELETE FROM mail_items WHERE item_guid IN (SELECT item_guid FROM item_test WHERE `source`='i'); +DELETE FROM guild_bank_item WHERE item_guid IN (SELECT item_guid FROM item_test WHERE `source`='i'); + +DELETE FROM mail_items WHERE item_guid IN (SELECT item_guid FROM item_test WHERE `source`='a'); +DELETE FROM guild_bank_item WHERE item_guid IN (SELECT item_guid FROM item_test WHERE `source`='a'); + +DELETE FROM guild_bank_item WHERE item_guid IN (SELECT item_guid FROM item_test WHERE `source`='m'); +DROP TABLE IF EXISTS item_test; diff --git a/sql/updates/0.10/5634_mangos_mangos_string.sql b/sql/updates/0.10/5634_mangos_mangos_string.sql new file mode 100644 index 00000000000..8542cd081de --- /dev/null +++ b/sql/updates/0.10/5634_mangos_mangos_string.sql @@ -0,0 +1,3 @@ +DELETE FROM mangos_string WHERE entry in (666); +INSERT INTO mangos_string VALUES +(666,'After your recent battle in %s our best attempts to award you a Mark of Honor failed. Enclosed you will find the Mark of Honor we were not able to deliver to you at the time. Thanks for fighting in %s!',NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/0.10/5636_mangos_loot_template.sql b/sql/updates/0.10/5636_mangos_loot_template.sql new file mode 100644 index 00000000000..987d33dae6f --- /dev/null +++ b/sql/updates/0.10/5636_mangos_loot_template.sql @@ -0,0 +1,134 @@ +ALTER TABLE `creature_loot_template` + ADD `ChanceOrQuestChance` FLOAT NOT NULL default '100' AFTER `ChanceOrRef`, + ADD `group` tinyint unsigned NOT NULL default '0' AFTER `QuestChanceOrGroup`, + ADD `mincountOrRef` mediumint NOT NULL default '1' AFTER `mincount`; + +UPDATE `creature_loot_template` SET + `ChanceOrQuestChance` = if(`QuestChanceOrGroup` > 0, -`QuestChanceOrGroup`, if(`ChanceOrRef` < 0, 100, `ChanceOrRef`)), + `group` = if(`QuestChanceOrGroup` > 0, 0, -`QuestChanceOrGroup`), + `mincountOrRef` = if(`ChanceOrRef` < 0, `ChanceOrRef`, `mincount`), + `maxcount` = if(`ChanceOrRef` < 0, 1, `maxcount`); + +ALTER TABLE `creature_loot_template` + DROP `ChanceOrRef`, + DROP `QuestChanceOrGroup`, + DROP `mincount`; + + +ALTER TABLE `disenchant_loot_template` + ADD `ChanceOrQuestChance` FLOAT NOT NULL default '100' AFTER `ChanceOrRef`, + ADD `group` tinyint unsigned NOT NULL default '0' AFTER `QuestChanceOrGroup`, + ADD `mincountOrRef` mediumint NOT NULL default '1' AFTER `mincount`; + +UPDATE `disenchant_loot_template` SET + `ChanceOrQuestChance` = if(`QuestChanceOrGroup` > 0, -`QuestChanceOrGroup`, if(`ChanceOrRef` < 0, 100, `ChanceOrRef`)), + `group` = if(`QuestChanceOrGroup` > 0, 0, -`QuestChanceOrGroup`), + `mincountOrRef` = if(`ChanceOrRef` < 0, `ChanceOrRef`, `mincount`), + `maxcount` = if(`ChanceOrRef` < 0, 1, `maxcount`); + +ALTER TABLE `disenchant_loot_template` + DROP `ChanceOrRef`, + DROP `QuestChanceOrGroup`, + DROP `mincount`; + + +ALTER TABLE `fishing_loot_template` + ADD `ChanceOrQuestChance` FLOAT NOT NULL default '100' AFTER `ChanceOrRef`, + ADD `group` tinyint unsigned NOT NULL default '0' AFTER `QuestChanceOrGroup`, + ADD `mincountOrRef` mediumint NOT NULL default '1' AFTER `mincount`; + +UPDATE `fishing_loot_template` SET + `ChanceOrQuestChance` = if(`QuestChanceOrGroup` > 0, -`QuestChanceOrGroup`, if(`ChanceOrRef` < 0, 100, `ChanceOrRef`)), + `group` = if(`QuestChanceOrGroup` > 0, 0, -`QuestChanceOrGroup`), + `mincountOrRef` = if(`ChanceOrRef` < 0, `ChanceOrRef`, `mincount`), + `maxcount` = if(`ChanceOrRef` < 0, 1, `maxcount`); + +ALTER TABLE `fishing_loot_template` + DROP `ChanceOrRef`, + DROP `QuestChanceOrGroup`, + DROP `mincount`; + + +ALTER TABLE `gameobject_loot_template` + ADD `ChanceOrQuestChance` FLOAT NOT NULL default '100' AFTER `ChanceOrRef`, + ADD `group` tinyint unsigned NOT NULL default '0' AFTER `QuestChanceOrGroup`, + ADD `mincountOrRef` mediumint NOT NULL default '1' AFTER `mincount`; + +UPDATE `gameobject_loot_template` SET + `ChanceOrQuestChance` = if(`QuestChanceOrGroup` > 0, -`QuestChanceOrGroup`, if(`ChanceOrRef` < 0, 100, `ChanceOrRef`)), + `group` = if(`QuestChanceOrGroup` > 0, 0, -`QuestChanceOrGroup`), + `mincountOrRef` = if(`ChanceOrRef` < 0, `ChanceOrRef`, `mincount`), + `maxcount` = if(`ChanceOrRef` < 0, 1, `maxcount`); + +ALTER TABLE `gameobject_loot_template` + DROP `ChanceOrRef`, + DROP `QuestChanceOrGroup`, + DROP `mincount`; + + +ALTER TABLE `item_loot_template` + ADD `ChanceOrQuestChance` FLOAT NOT NULL default '100' AFTER `ChanceOrRef`, + ADD `group` tinyint unsigned NOT NULL default '0' AFTER `QuestChanceOrGroup`, + ADD `mincountOrRef` mediumint NOT NULL default '1' AFTER `mincount`; + +UPDATE `item_loot_template` SET + `ChanceOrQuestChance` = if(`QuestChanceOrGroup` > 0, -`QuestChanceOrGroup`, if(`ChanceOrRef` < 0, 100, `ChanceOrRef`)), + `group` = if(`QuestChanceOrGroup` > 0, 0, -`QuestChanceOrGroup`), + `mincountOrRef` = if(`ChanceOrRef` < 0, `ChanceOrRef`, `mincount`), + `maxcount` = if(`ChanceOrRef` < 0, 1, `maxcount`); + +ALTER TABLE `item_loot_template` + DROP `ChanceOrRef`, + DROP `QuestChanceOrGroup`, + DROP `mincount`; + + +ALTER TABLE `pickpocketing_loot_template` + ADD `ChanceOrQuestChance` FLOAT NOT NULL default '100' AFTER `ChanceOrRef`, + ADD `group` tinyint unsigned NOT NULL default '0' AFTER `QuestChanceOrGroup`, + ADD `mincountOrRef` mediumint NOT NULL default '1' AFTER `mincount`; + +UPDATE `pickpocketing_loot_template` SET + `ChanceOrQuestChance` = if(`QuestChanceOrGroup` > 0, -`QuestChanceOrGroup`, if(`ChanceOrRef` < 0, 100, `ChanceOrRef`)), + `group` = if(`QuestChanceOrGroup` > 0, 0, -`QuestChanceOrGroup`), + `mincountOrRef` = if(`ChanceOrRef` < 0, `ChanceOrRef`, `mincount`), + `maxcount` = if(`ChanceOrRef` < 0, 1, `maxcount`); + +ALTER TABLE `pickpocketing_loot_template` + DROP `ChanceOrRef`, + DROP `QuestChanceOrGroup`, + DROP `mincount`; + + +ALTER TABLE `prospecting_loot_template` + ADD `ChanceOrQuestChance` FLOAT NOT NULL default '100' AFTER `ChanceOrRef`, + ADD `group` tinyint unsigned NOT NULL default '0' AFTER `QuestChanceOrGroup`, + ADD `mincountOrRef` mediumint NOT NULL default '1' AFTER `mincount`; + +UPDATE `prospecting_loot_template`SET + `ChanceOrQuestChance` = if(`QuestChanceOrGroup` > 0, -`QuestChanceOrGroup`, if(`ChanceOrRef` < 0, 100, `ChanceOrRef`)), + `group` = if(`QuestChanceOrGroup` > 0, 0, -`QuestChanceOrGroup`), + `mincountOrRef` = if(`ChanceOrRef` < 0, `ChanceOrRef`, `mincount`), + `maxcount` = if(`ChanceOrRef` < 0, 1, `maxcount`); + +ALTER TABLE `prospecting_loot_template` + DROP `ChanceOrRef`, + DROP `QuestChanceOrGroup`, + DROP `mincount`; + + +ALTER TABLE `skinning_loot_template` + ADD `ChanceOrQuestChance` FLOAT NOT NULL default '100' AFTER `ChanceOrRef`, + ADD `group` tinyint unsigned NOT NULL default '0' AFTER `QuestChanceOrGroup`, + ADD `mincountOrRef` mediumint NOT NULL default '1' AFTER `mincount`; + +UPDATE `skinning_loot_template` SET + `ChanceOrQuestChance` = if(`QuestChanceOrGroup` > 0, -`QuestChanceOrGroup`, if(`ChanceOrRef` < 0, 100, `ChanceOrRef`)), + `group` = if(`QuestChanceOrGroup` > 0, 0, -`QuestChanceOrGroup`), + `mincountOrRef` = if(`ChanceOrRef` < 0, `ChanceOrRef`, `mincount`), + `maxcount` = if(`ChanceOrRef` < 0, 1, `maxcount`); + +ALTER TABLE `skinning_loot_template` + DROP `ChanceOrRef`, + DROP `QuestChanceOrGroup`, + DROP `mincount`; diff --git a/sql/updates/0.10/5640_mangos_spell_proc_event.sql b/sql/updates/0.10/5640_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..4cc48723d2b --- /dev/null +++ b/sql/updates/0.10/5640_mangos_spell_proc_event.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_proc_event` WHERE `entry`=24905; +INSERT INTO `spell_proc_event` ( `entry` , `SchoolMask` , `Category` , `SkillID` , `SpellFamilyName` , `SpellFamilyMask` , `procFlags` , `ppmRate` ) VALUES +('24905', '0', '0', '0', '0', '0', '1', '15'); \ No newline at end of file diff --git a/sql/updates/0.10/5642_mangos_mangos_string.sql b/sql/updates/0.10/5642_mangos_mangos_string.sql new file mode 100644 index 00000000000..77c05b720f6 --- /dev/null +++ b/sql/updates/0.10/5642_mangos_mangos_string.sql @@ -0,0 +1,3 @@ +DELETE FROM mangos_string WHERE entry in (548); +INSERT INTO mangos_string VALUES +(548,'Player%s %s (guid: %u) Account: %s (id: %u) GMLevel: %u Last IP: %s Last login: %s Latency: %ums',NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/0.5/1150_character_aura.sql b/sql/updates/0.5/1150_character_aura.sql new file mode 100644 index 00000000000..c12e074c54d --- /dev/null +++ b/sql/updates/0.5/1150_character_aura.sql @@ -0,0 +1,8 @@ +DROP TABLE IF EXISTS `character_aura`; +CREATE TABLE `character_aura` ( + `guid` bigint(20) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `spell` int(11) unsigned NOT NULL default '0', + `effect_index` int(11) unsigned NOT NULL default '0', + `remaintime` int(11) NOT NULL default '0', + KEY (`guid`,`spell`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System'; diff --git a/sql/updates/0.5/1155_commands.sql b/sql/updates/0.5/1155_commands.sql new file mode 100644 index 00000000000..83295c1eae3 --- /dev/null +++ b/sql/updates/0.5/1155_commands.sql @@ -0,0 +1 @@ +ALTER TABLE `command` CHANGE `help` `help` LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ; diff --git a/sql/updates/0.5/1155_npc_option.sql b/sql/updates/0.5/1155_npc_option.sql new file mode 100644 index 00000000000..58f6ebb8f4b --- /dev/null +++ b/sql/updates/0.5/1155_npc_option.sql @@ -0,0 +1,10 @@ +DROP TABLE IF EXISTS `npc_option`; +CREATE TABLE `npc_option` ( +`id` int(11) unsigned NOT NULL default '0', +`gossip_id` int(11) unsigned NOT NULL default '0', +`npcflag` int(11) unsigned NOT NULL default '0', +`icon` int(11) unsigned NOT NULL default '0', +`action` int(11) unsigned NOT NULL default '0', +`option` text NOT NULL, +PRIMARY KEY (`ID`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; diff --git a/sql/updates/0.5/1158_character_inventory.sql b/sql/updates/0.5/1158_character_inventory.sql new file mode 100644 index 00000000000..174a3dd3d09 --- /dev/null +++ b/sql/updates/0.5/1158_character_inventory.sql @@ -0,0 +1,4 @@ +ALTER TABLE `character_inventory` ADD `bag` TINYINT( 3 ) DEFAULT '0' NOT NULL AFTER `guid` ; + +ALTER TABLE `character_inventory` DROP PRIMARY KEY , +ADD INDEX `idx_guid` ( `guid` , `bag` ) ; diff --git a/sql/updates/0.5/1186_game_weather.sql b/sql/updates/0.5/1186_game_weather.sql new file mode 100644 index 00000000000..2d634416ed8 --- /dev/null +++ b/sql/updates/0.5/1186_game_weather.sql @@ -0,0 +1,17 @@ +DROP TABLE IF EXISTS `game_weather`; +CREATE TABLE `game_weather` ( + `zone` int(11) unsigned NOT NULL default '0', + `spring_rain_chance` tinyint(3) unsigned NOT NULL default '25', + `spring_snow_chance` tinyint(3) unsigned NOT NULL default '25', + `spring_storm_chance` tinyint(3) unsigned NOT NULL default '25', + `summer_rain_chance` tinyint(3) unsigned NOT NULL default '25', + `summer_snow_chance` tinyint(3) unsigned NOT NULL default '25', + `summer_storm_chance` tinyint(3) unsigned NOT NULL default '25', + `fall_rain_chance` tinyint(3) unsigned NOT NULL default '25', + `fall_snow_chance` tinyint(3) unsigned NOT NULL default '25', + `fall_storm_chance` tinyint(3) unsigned NOT NULL default '25', + `winter_rain_chance` tinyint(3) unsigned NOT NULL default '25', + `winter_snow_chance` tinyint(3) unsigned NOT NULL default '25', + `winter_storm_chance` tinyint(3) unsigned NOT NULL default '25', + PRIMARY KEY (`zone`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Game System'; \ No newline at end of file diff --git a/sql/updates/0.5/1208_npc_trainer.sql b/sql/updates/0.5/1208_npc_trainer.sql new file mode 100644 index 00000000000..ac9692ff1d9 --- /dev/null +++ b/sql/updates/0.5/1208_npc_trainer.sql @@ -0,0 +1,6 @@ +ALTER TABLE `npc_trainer` CHANGE `guid` `entry` INT( 11 ) NOT NULL DEFAULT '0' ; + +ALTER TABLE `npc_trainer` +ADD `reqskill` INT( 11 ) DEFAULT '0' NOT NULL , +ADD `reqskillvalue` INT( 11 ) DEFAULT '0' NOT NULL ; + diff --git a/sql/updates/0.5/1250_item_template.sql b/sql/updates/0.5/1250_item_template.sql new file mode 100644 index 00000000000..f3c848d82c7 --- /dev/null +++ b/sql/updates/0.5/1250_item_template.sql @@ -0,0 +1 @@ +ALTER TABLE `item_template` CHANGE `RequiredRaputationRank` `RequiredReputationRank` INT( 30 ) unsigned NOT NULL DEFAULT '0' ; diff --git a/sql/updates/0.5/1262_areatrigger_tavern.sql b/sql/updates/0.5/1262_areatrigger_tavern.sql new file mode 100644 index 00000000000..bc50ddff8cc --- /dev/null +++ b/sql/updates/0.5/1262_areatrigger_tavern.sql @@ -0,0 +1,6 @@ +ALTER TABLE `areatrigger_tavern` + CHANGE `triggerid` `id` int(11) unsigned NOT NULL default '0' , + CHANGE `Triggername` `name` text , + DROP KEY `acct`, + DROP PRIMARY KEY , + ADD PRIMARY KEY (`id`) ; diff --git a/sql/updates/0.5/1262_game_graveyard.sql b/sql/updates/0.5/1262_game_graveyard.sql new file mode 100644 index 00000000000..6b832119439 --- /dev/null +++ b/sql/updates/0.5/1262_game_graveyard.sql @@ -0,0 +1 @@ +ALTER TABLE `game_graveyard` RENAME TO `areatrigger_graveyard`; diff --git a/sql/updates/0.5/1282_playercreateinfo.sql b/sql/updates/0.5/1282_playercreateinfo.sql new file mode 100644 index 00000000000..d32ee218a40 --- /dev/null +++ b/sql/updates/0.5/1282_playercreateinfo.sql @@ -0,0 +1,8 @@ +TRUNCATE `playercreateinfo` ; + +LOCK TABLES `playercreateinfo` WRITE; +INSERT INTO `playercreateinfo` VALUES (1,1,1,0,12,-8949,-132,84,49,23,20,22,20,21,40,60,0,1000,0,0,29,5,6,0,0),(2,1,2,0,12,-8949,-132,84,49,22,20,22,20,22,40,68,79,0,0,0,27,4,5,0,0),(3,1,4,0,12,-8949,-132,84,49,21,23,21,20,20,40,55,0,0,0,100,27,10,13,0,0),(4,1,5,0,12,-8949,-132,84,49,20,20,20,22,24,40,61,128,0,0,0,30,4,4,0,0),(5,1,8,0,12,-8949,-132,84,49,20,20,20,23,22,40,61,119,0,0,0,30,4,4,0,0),(6,1,9,0,12,-8949,-132,84,49,20,20,21,22,22,40,53,109,0,0,0,30,4,4,0,0),(7,2,1,1,14,-618,-4251,39,51,26,17,24,17,23,0,80,0,1000,0,0,35,6,6,0,0),(8,2,3,1,14,-618,-4251,39,51,23,20,23,17,24,0,76,80,0,0,0,25,4,5,0,0),(9,2,4,1,14,-618,-4251,39,51,24,20,23,17,23,0,75,0,0,0,100,30,4,4,0,0),(10,2,7,1,14,-618,-4251,39,51,24,17,23,18,25,0,97,71,0,0,0,30,4,4,0,0),(11,2,9,1,14,-618,-4251,39,51,23,17,23,19,25,0,73,109,0,0,0,30,4,4,0,0),(12,3,1,0,1,-6240,331,383,53,25,16,25,19,19,0,90,0,1000,0,0,33,5,6,0,0),(13,3,2,0,1,-6240,331,383,53,24,16,25,19,20,0,88,79,0,0,0,31,5,6,0,0),(14,3,3,0,1,-6240,331,383,53,22,19,24,19,20,0,86,80,0,0,0,24,4,5,0,0),(15,3,4,0,1,-6240,331,383,53,23,19,24,19,19,0,85,0,0,0,100,30,4,4,0,0),(16,3,5,0,1,-6240,331,383,53,22,16,23,21,22,0,91,128,0,0,0,30,4,4,0,0),(17,4,1,1,141,10311,832,1327,55,20,25,21,20,20,0,50,0,1000,0,0,21,4,4,0,0),(18,4,3,1,141,10311,832,1327,55,17,28,20,20,21,0,46,80,0,0,0,26,4,5,0,0),(19,4,4,1,141,10311,832,1327,55,18,28,20,20,20,0,45,0,0,0,100,30,4,4,0,0),(20,4,5,1,141,10311,832,1327,55,17,25,19,22,23,0,51,128,0,0,0,30,4,4,0,0),(21,4,11,1,141,10311,832,1327,55,18,25,19,22,22,0,53,67,0,0,0,30,4,4,0,0),(22,5,1,0,85,1676,1677,122,57,22,18,23,18,25,0,70,0,1000,0,0,27,4,5,0,0),(23,5,4,0,85,1676,1677,122,57,20,21,22,18,25,0,65,0,0,0,100,30,4,4,0,0),(24,5,5,0,85,1676,1677,122,57,19,18,21,20,28,0,71,128,0,0,0,30,4,4,0,0),(25,5,8,0,85,1676,1677,122,57,19,18,21,21,27,0,71,119,0,0,0,30,4,4,0,0),(26,5,9,0,85,1676,1677,122,57,19,18,22,20,27,0,63,109,0,0,0,30,4,4,0,0),(27,6,1,1,215,-2917,-257,53,59,28,15,24,15,22,0,80,0,1000,0,0,39,6,7,0,0),(28,6,3,1,215,-2917,-257,53,59,25,18,23,15,23,0,76,80,0,0,0,16,5,7,0,0),(29,6,7,1,215,-2917,-257,53,59,26,15,23,16,24,0,97,71,0,0,0,30,4,4,0,0),(30,6,11,1,215,-2917,-257,53,59,26,15,22,17,24,0,97,67,0,0,0,30,4,4,0,0),(31,7,1,0,1,-6240,331,383,1563,18,23,21,23,20,0,50,0,1000,0,0,10,3,4,0,0),(32,7,4,0,1,-6340,331,383,1563,16,26,20,23,20,0,45,0,0,0,100,30,4,4,0,0),(33,7,8,0,1,-6340,331,383,1563,15,23,19,26,22,0,51,119,0,0,0,30,4,4,0,0),(34,7,9,0,1,-6340,331,383,1563,15,23,20,25,22,0,43,109,0,0,0,30,4,4,0,0),(35,8,1,1,14,-618,-4251,39,1478,24,22,23,16,21,0,70,0,1000,0,0,29,5,7,0,0),(36,8,3,1,14,-618,-4251,39,1478,21,25,22,16,22,0,66,80,0,0,0,16,5,7,0,0),(37,8,4,1,14,-618,-4251,39,1478,22,25,22,16,21,0,65,0,0,0,100,30,4,4,0,0),(38,8,5,1,14,-618,-4251,39,1478,21,22,21,18,24,0,71,128,0,0,0,30,4,4,0,0),(39,8,7,1,14,-618,-4251,39,1478,22,22,22,17,23,0,87,71,0,0,0,30,4,4,0,0),(40,8,8,1,14,-618,-4251,39,1478,21,22,21,19,23,0,71,119,0,0,0,30,4,4,0,0); +UNLOCK TABLES; + + + diff --git a/sql/updates/0.5/1282_playercreateinfo_item.sql b/sql/updates/0.5/1282_playercreateinfo_item.sql new file mode 100644 index 00000000000..73b2a516a26 --- /dev/null +++ b/sql/updates/0.5/1282_playercreateinfo_item.sql @@ -0,0 +1,10 @@ +TRUNCATE `playercreateinfo_item` ; + +LOCK TABLES `playercreateinfo_item` WRITE; +INSERT INTO `playercreateinfo_item` VALUES (1,38,255,3,1),(1,39,255,6,1),(1,40,255,7,1),(1,25,255,15,1),(1,2362,255,16,1),(1,65020,255,23,4),(1,6948,255,24,1),(1,14646,255,25,1),(2,45,255,3,1),(2,44,255,6,1),(2,43,255,7,1),(2,2361,255,15,1),(2,6948,255,23,1),(2,65021,255,24,2),(2,65022,255,25,4),(2,14646,255,26,1),(3,49,255,3,1),(3,48,255,6,1),(3,47,255,7,1),(3,2092,255,15,1),(3,65023,255,17,100),(3,65022,255,23,4),(3,6948,255,24,1),(3,14646,255,25,1),(4,53,255,3,1),(4,6098,255,4,1),(4,52,255,6,1),(4,51,255,7,1),(4,36,255,15,1),(4,65021,255,23,2),(4,65022,255,24,4),(4,6948,255,25,1),(4,14646,255,26,1),(5,6096,255,3,1),(5,56,255,4,1),(5,1395,255,6,1),(5,55,255,7,1),(5,35,255,15,1),(5,65022,255,23,4),(5,65021,255,24,2),(5,6948,255,25,1),(5,14646,255,26,1),(6,6097,255,3,1),(6,57,255,4,1),(6,1396,255,6,1),(6,59,255,7,1),(6,2092,255,15,1),(6,65027,255,23,4),(6,65021,255,24,2),(6,6948,255,25,1),(6,14646,255,26,1),(7,6125,255,3,1),(7,139,255,6,1),(7,140,255,7,1),(7,12282,255,15,1),(7,6948,255,23,1),(7,65020,255,24,4),(7,14649,255,25,1),(8,127,255,3,1),(8,6126,255,6,1),(8,6127,255,7,1),(8,37,255,15,1),(8,2504,255,17,1),(8,65021,255,23,2),(8,65020,255,24,4),(8,6948,255,25,1),(8,14649,255,26,1),(8,2512,255,27,200),(8,2101,255,28,1),(9,2105,255,3,1),(9,120,255,6,1),(9,121,255,7,1),(9,2092,255,15,1),(9,65024,255,17,100),(9,65020,255,23,4),(9,6948,255,24,1),(9,14649,255,25,1),(10,154,255,3,1),(10,153,255,6,1),(10,36,255,15,1),(10,6948,255,23,1),(10,65020,255,24,4),(10,65021,255,25,2),(10,14649,255,26,1),(11,6129,255,4,1),(11,1396,255,6,1),(11,59,255,7,1),(11,2092,255,15,1),(11,6948,255,23,1),(11,65020,255,24,4),(11,65021,255,25,2),(11,14649,255,26,1),(12,38,255,3,1),(12,39,255,6,1),(12,40,255,7,1),(12,12282,255,15,1),(12,6948,255,23,1),(12,65020,255,24,4),(12,14647,255,25,1),(13,45,255,3,1),(13,44,255,6,1),(13,43,255,7,1),(13,2361,255,15,1),(13,65026,255,23,4),(13,65021,255,24,2),(13,6948,255,25,1),(13,14647,255,26,1),(14,148,255,3,1),(14,147,255,6,1),(14,129,255,7,1),(14,37,255,15,1),(14,2508,255,17,1),(14,65021,255,23,2),(14,65020,255,24,4),(14,6948,255,25,1),(14,14647,255,26,1),(14,2516,255,27,200),(14,2102,255,28,1),(15,49,255,3,1),(15,48,255,6,1),(15,47,255,7,1),(15,2092,255,15,1),(15,65024,255,17,100),(15,65026,255,23,4),(15,6948,255,24,1),(15,14647,255,25,1),(16,53,255,3,1),(16,6098,255,4,1),(16,52,255,6,1),(16,51,255,7,1),(16,36,255,15,1),(16,65021,255,23,2),(16,65026,255,24,4),(16,6948,255,25,1),(16,14647,255,26,1),(17,38,255,3,1),(17,39,255,6,1),(17,40,255,7,1),(17,25,255,15,1),(17,2362,255,16,1),(17,65020,255,23,4),(17,6948,255,24,1),(17,14648,255,25,1),(18,148,255,3,1),(18,147,255,6,1),(18,129,255,7,1),(18,2092,255,15,1),(18,2504,255,17,1),(18,65021,255,23,2),(18,65020,255,24,4),(18,6948,255,25,1),(18,14648,255,26,1),(18,2512,255,27,200),(18,2101,255,28,1),(19,49,255,3,1),(19,48,255,6,1),(19,47,255,7,1),(19,2092,255,15,1),(19,65023,255,17,100),(19,65026,255,23,4),(19,6948,255,24,1),(19,14648,255,25,1),(20,53,255,3,1),(20,6119,255,4,1),(20,52,255,6,1),(20,51,255,7,1),(20,36,255,15,1),(20,65022,255,23,4),(20,65021,255,24,2),(20,6948,255,25,1),(20,14648,255,26,1),(21,6123,255,4,1),(21,44,255,6,1),(21,3661,255,15,1),(21,65021,255,23,2),(21,65025,255,24,4),(21,6948,255,25,1),(21,14648,255,26,1),(22,6125,255,3,1),(22,139,255,6,1),(22,140,255,7,1),(22,25,255,15,1),(22,2362,255,16,1),(22,65027,255,23,4),(22,6948,255,24,1),(22,14651,255,25,1),(23,2105,255,3,1),(23,120,255,6,1),(23,121,255,7,1),(23,2092,255,15,1),(23,65023,255,17,100),(23,65027,255,23,4),(23,6948,255,24,1),(23,14651,255,25,1),(24,53,255,3,1),(24,6144,255,4,1),(24,52,255,6,1),(24,51,255,7,1),(24,36,255,15,1),(24,65027,255,23,4),(24,65021,255,24,2),(24,6948,255,25,1),(24,14651,255,26,1),(25,6096,255,3,1),(25,6140,255,4,1),(25,1395,255,6,1),(25,55,255,7,1),(25,35,255,15,1),(25,65027,255,23,4),(25,65021,255,24,2),(25,6948,255,25,1),(25,14651,255,26,1),(26,6129,255,4,1),(26,1396,255,6,1),(26,59,255,7,1),(26,2092,255,15,1),(26,65027,255,23,4),(26,65021,255,24,2),(26,6948,255,25,1),(26,14651,255,26,1),(27,6125,255,3,1),(27,139,255,6,1),(27,2361,255,15,1),(27,6948,255,23,1),(27,65026,255,24,4),(27,14650,255,25,1),(28,127,255,3,1),(28,6126,255,6,1),(28,37,255,15,1),(28,2508,255,17,1),(28,65021,255,23,2),(28,65020,255,24,4),(28,6948,255,25,1),(28,14650,255,26,1),(28,2516,255,27,200),(28,2102,255,28,1),(29,154,255,3,1),(29,153,255,6,1),(29,36,255,15,1),(29,6948,255,23,1),(29,65027,255,24,4),(29,65021,255,25,2),(29,14650,255,26,1),(30,6139,255,4,1),(30,6124,255,6,1),(30,35,255,15,1),(30,65021,255,23,2),(30,65025,255,24,4),(30,6948,255,25,1),(30,14650,255,26,1),(31,38,255,4,1),(31,39,255,6,1),(31,40,255,7,1),(31,25,255,15,1),(31,2362,255,16,1),(31,65020,255,23,4),(31,6948,255,24,1),(31,14647,255,25,1),(32,49,255,3,1),(32,48,255,6,1),(32,47,255,7,1),(32,2092,255,15,1),(32,65023,255,17,100),(32,65020,255,23,4),(32,6948,255,24,1),(32,14647,255,25,1),(33,6096,255,3,1),(33,56,255,4,1),(33,1395,255,6,1),(33,55,255,7,1),(33,35,255,15,1),(33,65025,255,23,4),(33,65021,255,24,2),(33,6948,255,25,1),(33,14647,255,26,1),(34,6097,255,3,1),(34,57,255,4,1),(34,1396,255,6,1),(34,59,255,7,1),(34,2092,255,15,1),(34,65021,255,23,2),(34,65027,255,24,4),(34,6948,255,25,1),(34,14647,255,26,1),(35,6125,255,3,1),(35,139,255,6,1),(35,140,255,7,1),(35,37,255,15,1),(35,2362,255,16,1),(35,65024,255,17,100),(35,65020,255,23,4),(35,6948,255,24,1),(35,14649,255,25,1),(36,127,255,3,1),(36,6126,255,6,1),(36,6127,255,7,1),(36,37,255,15,1),(36,2504,255,17,1),(36,65027,255,23,4),(36,65021,255,24,2),(36,2512,255,27,200),(36,2101,255,28,1),(36,14649,255,26,1),(36,6948,255,25,1),(37,2105,255,3,1),(37,120,255,6,1),(37,121,255,7,1),(37,2092,255,15,1),(37,65024,255,17,100),(37,65020,255,23,4),(37,6948,255,24,1),(37,14649,255,25,1),(38,53,255,3,1),(38,6144,255,4,1),(38,52,255,6,1),(38,36,255,15,1),(38,65026,255,23,4),(38,65021,255,24,2),(38,6948,255,25,1),(38,14649,255,26,1),(39,6134,255,3,1),(39,6135,255,6,1),(39,36,255,15,1),(39,65020,255,23,4),(39,65021,255,24,2),(39,6948,255,25,1),(39,14649,255,26,1),(40,6096,255,3,1),(40,6140,255,4,1),(40,1395,255,6,1),(40,55,255,7,1),(40,35,255,15,1),(40,65020,255,23,4),(40,65021,255,24,2),(40,6948,255,25,1),(40,14649,255,26,1); +UNLOCK TABLES; + + + + + diff --git a/sql/updates/0.5/1292_loot_template.sql b/sql/updates/0.5/1292_loot_template.sql new file mode 100644 index 00000000000..97d18078362 --- /dev/null +++ b/sql/updates/0.5/1292_loot_template.sql @@ -0,0 +1,6 @@ +ALTER TABLE `loot_template` + CHANGE `itemid` `item` int(11) unsigned NOT NULL default '0' , + CHANGE `percentchance` `chance` float NOT NULL default '100' , + DROP KEY `i_creature_loot_creatureid` , + DROP KEY `creatureloot_index` , + ADD PRIMARY KEY (`entry`,`item`) ; diff --git a/sql/updates/0.5/1332_character_queststatus.sql b/sql/updates/0.5/1332_character_queststatus.sql new file mode 100644 index 00000000000..1a32a785463 --- /dev/null +++ b/sql/updates/0.5/1332_character_queststatus.sql @@ -0,0 +1,18 @@ +ALTER TABLE `character_queststatus` + CHANGE `playerid` `guid` bigint(20) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + CHANGE `questid` `quest` int(11) unsigned NOT NULL default '0' COMMENT 'Quest Identifier', + CHANGE `status` `status` int(11) unsigned NOT NULL default '0', + CHANGE `rewarded` `rewarded` int(11) unsigned NOT NULL default '0', + CHANGE `explored` `explored` int(11) unsigned NOT NULL default '0' AFTER `rewarded` , + CHANGE `timer` `timer` bigint(20) unsigned NOT NULL default '0' AFTER `explored` , + CHANGE `questMobCount1` `mobcount1` int(11) unsigned NOT NULL default '0', + CHANGE `questMobCount2` `mobcount2` int(11) unsigned NOT NULL default '0', + CHANGE `questMobCount3` `mobcount3` int(11) unsigned NOT NULL default '0', + CHANGE `questMobCount4` `mobcount4` int(11) unsigned NOT NULL default '0', + CHANGE `questItemCount1` `itemcount1` int(11) unsigned NOT NULL default '0', + CHANGE `questItemCount2` `itemcount2` int(11) unsigned NOT NULL default '0', + CHANGE `questItemCount3` `itemcount3` int(11) unsigned NOT NULL default '0', + CHANGE `questItemCount4` `itemcount4` int(11) unsigned NOT NULL default '0', + DROP `id` , + DROP PRIMARY KEY , + ADD PRIMARY KEY (`guid`,`quest`) ; diff --git a/sql/updates/0.5/1336_item_template.sql b/sql/updates/0.5/1336_item_template.sql new file mode 100644 index 00000000000..f200674af96 --- /dev/null +++ b/sql/updates/0.5/1336_item_template.sql @@ -0,0 +1 @@ +ALTER TABLE `item_template` ADD `RangedModRange` float NOT NULL default '0' AFTER `ammo_type` ; diff --git a/sql/updates/0.5/1339_areatrigger_city.sql b/sql/updates/0.5/1339_areatrigger_city.sql new file mode 100644 index 00000000000..4ca9eb0d85e --- /dev/null +++ b/sql/updates/0.5/1339_areatrigger_city.sql @@ -0,0 +1,6 @@ +DROP TABLE IF EXISTS `areatrigger_city`; +CREATE TABLE `areatrigger_city` ( + `id` int(11) unsigned NOT NULL default '0' COMMENT 'Identifier', + `name` text, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Trigger System'; diff --git a/sql/updates/0.5/1349_areatrigger_involvedrelation.sql b/sql/updates/0.5/1349_areatrigger_involvedrelation.sql new file mode 100644 index 00000000000..69d713c1490 --- /dev/null +++ b/sql/updates/0.5/1349_areatrigger_involvedrelation.sql @@ -0,0 +1 @@ +ALTER TABLE `areatrigger_involvedrelation` DROP `creature` ; diff --git a/sql/updates/0.5/1349_character_aura.sql b/sql/updates/0.5/1349_character_aura.sql new file mode 100644 index 00000000000..2290782d22e --- /dev/null +++ b/sql/updates/0.5/1349_character_aura.sql @@ -0,0 +1,3 @@ +ALTER TABLE `character_aura` + DROP KEY `guid` , + ADD PRIMARY KEY (`guid`,`spell`) ; diff --git a/sql/updates/0.5/1349_character_inventory.sql b/sql/updates/0.5/1349_character_inventory.sql new file mode 100644 index 00000000000..8e0f1c5a67c --- /dev/null +++ b/sql/updates/0.5/1349_character_inventory.sql @@ -0,0 +1,3 @@ +ALTER TABLE `character_inventory` + DROP KEY `idx_guid` , + ADD PRIMARY KEY (`guid`,`bag`,`slot`) ; diff --git a/sql/updates/0.5/1349_creature_template.sql b/sql/updates/0.5/1349_creature_template.sql new file mode 100644 index 00000000000..5f55848955c --- /dev/null +++ b/sql/updates/0.5/1349_creature_template.sql @@ -0,0 +1,3 @@ +ALTER TABLE `creature_template` + DROP KEY `entry` , + ADD PRIMARY KEY (`entry`) ; diff --git a/sql/updates/0.5/1349_gameobject_template.sql b/sql/updates/0.5/1349_gameobject_template.sql new file mode 100644 index 00000000000..f440fe36247 --- /dev/null +++ b/sql/updates/0.5/1349_gameobject_template.sql @@ -0,0 +1,3 @@ +ALTER TABLE `gameobject_template` + DROP KEY `id` , + ADD PRIMARY KEY (`entry`) ; diff --git a/sql/updates/0.5/1356_item_template.sql b/sql/updates/0.5/1356_item_template.sql new file mode 100644 index 00000000000..49cc91e7aec --- /dev/null +++ b/sql/updates/0.5/1356_item_template.sql @@ -0,0 +1,11 @@ +ALTER TABLE `item_template` + CHANGE `dmg_min1` `dmg_min1` float NOT NULL default '0', + CHANGE `dmg_max1` `dmg_max1` float NOT NULL default '0', + CHANGE `dmg_min2` `dmg_min2` float NOT NULL default '0', + CHANGE `dmg_max2` `dmg_max2` float NOT NULL default '0', + CHANGE `dmg_min3` `dmg_min3` float NOT NULL default '0', + CHANGE `dmg_max3` `dmg_max3` float NOT NULL default '0', + CHANGE `dmg_min4` `dmg_min4` float NOT NULL default '0', + CHANGE `dmg_max4` `dmg_max4` float NOT NULL default '0', + CHANGE `dmg_min5` `dmg_min5` float NOT NULL default '0', + CHANGE `dmg_max5` `dmg_max5` float NOT NULL default '0'; diff --git a/sql/updates/0.5/1411_item_template.sql b/sql/updates/0.5/1411_item_template.sql new file mode 100644 index 00000000000..eb9399fe082 --- /dev/null +++ b/sql/updates/0.5/1411_item_template.sql @@ -0,0 +1 @@ +ALTER TABLE `item_template` ADD `Unknown1` int(30) unsigned NOT NULL default '0' AFTER `area` ; diff --git a/sql/updates/0.5/1447_quest_template.sql b/sql/updates/0.5/1447_quest_template.sql new file mode 100644 index 00000000000..e3f8a9b7c34 --- /dev/null +++ b/sql/updates/0.5/1447_quest_template.sql @@ -0,0 +1,11 @@ +ALTER TABLE `quest_template` + CHANGE `Title` `Title` text, + CHANGE `Details` `Details` text, + CHANGE `Objectives` `Objectives` text, + CHANGE `CompletionText` `CompletionText` text, + CHANGE `IncompleteText` `IncompleteText` text, + CHANGE `EndText` `EndText` text, + CHANGE `ObjectiveText1` `ObjectiveText1` text, + CHANGE `ObjectiveText2` `ObjectiveText2` text, + CHANGE `ObjectiveText3` `ObjectiveText3` text, + CHANGE `ObjectiveText4` `ObjectiveText4` text; diff --git a/sql/updates/0.5/1465_build_realmd_db.sql b/sql/updates/0.5/1465_build_realmd_db.sql new file mode 100644 index 00000000000..1b52a8c6fc5 --- /dev/null +++ b/sql/updates/0.5/1465_build_realmd_db.sql @@ -0,0 +1,92 @@ +-- MySQL dump 10.10 +-- +-- Host: localhost Database: realmd +-- ------------------------------------------------------ +-- Server version 5.0.21 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `account` +-- + +DROP TABLE IF EXISTS `account`; +CREATE TABLE `account` ( + `id` bigint(20) unsigned NOT NULL auto_increment COMMENT 'Identifier', + `username` varchar(16) NOT NULL default '', + `password` varchar(28) NOT NULL default '', + `gmlevel` tinyint(3) unsigned NOT NULL default '0', + `sessionkey` longtext, + `email` varchar(50) NOT NULL default '', + `joindate` timestamp NOT NULL default CURRENT_TIMESTAMP, + `banned` tinyint(3) unsigned NOT NULL default '0', + `last_ip` varchar(30) NOT NULL default '127.0.0.1', + `failed_logins` int(11) unsigned NOT NULL default '0', + `locked` tinyint(3) unsigned NOT NULL default '0', + `last_login` timestamp NOT NULL default '0000-00-00 00:00:00', + `online` tinyint NOT NULL default 0, + PRIMARY KEY (`id`), + UNIQUE KEY `idx_username` (`username`), + KEY `idx_banned` (`banned`), + KEY `idx_gmlevel` (`gmlevel`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Account System'; + +-- +-- Table structure for table `realmcharacters` +-- + +DROP TABLE IF EXISTS `realmcharacters`; +CREATE TABLE `realmcharacters` ( + `realmid` integer(11) unsigned NOT NULL default '0', + `acctid` bigint(20) unsigned NOT NULL, + `numchars` tinyint(3) unsigned NOT NULL default '0', + PRIMARY KEY (`realmid`, `acctid`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Realm Character Tracker'; + + +-- +-- Table structure for table `ip_banned` +-- + +DROP TABLE IF EXISTS `ip_banned`; +CREATE TABLE `ip_banned` ( + `ip` varchar(32) NOT NULL default '127.0.0.1', + PRIMARY KEY (`ip`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Banned IPs'; + +-- +-- Dumping data for table `ip_banned` +-- + + +/*!40000 ALTER TABLE `ip_banned` DISABLE KEYS */; +LOCK TABLES `ip_banned` WRITE; +UNLOCK TABLES; +/*!40000 ALTER TABLE `ip_banned` ENABLE KEYS */; + + +-- +-- Table structure for table `realmlist` +-- + +DROP TABLE IF EXISTS `realmlist`; +CREATE TABLE `realmlist` ( + `id` int(11) unsigned NOT NULL auto_increment, + `name` varchar(32) NOT NULL default '', + `address` varchar(32) NOT NULL default '127.0.0.1', + `icon` tinyint(3) unsigned NOT NULL default '0', + `color` tinyint(3) unsigned NOT NULL default '0', + `timezone` tinyint(3) unsigned NOT NULL default '0', + PRIMARY KEY (`id`), + UNIQUE KEY `idx_name` (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Realm System'; + diff --git a/sql/updates/0.5/1465_create_realmd_db.sql b/sql/updates/0.5/1465_create_realmd_db.sql new file mode 100644 index 00000000000..8411114b208 --- /dev/null +++ b/sql/updates/0.5/1465_create_realmd_db.sql @@ -0,0 +1,4 @@ +GRANT USAGE ON * . * TO 'mangos'@'localhost' IDENTIFIED BY 'mangos' WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 ; +CREATE DATABASE `realmd` ; +GRANT ALL PRIVILEGES ON `realmd` . * TO 'mangos'@'localhost' WITH GRANT OPTION ; + diff --git a/sql/updates/0.5/1465_populate_realmd_db.sql b/sql/updates/0.5/1465_populate_realmd_db.sql new file mode 100644 index 00000000000..0aa78a7fbb5 --- /dev/null +++ b/sql/updates/0.5/1465_populate_realmd_db.sql @@ -0,0 +1,17 @@ +truncate realmd.realmlist; +insert into realmd.realmlist +select `id`, `name`, `address`, `icon`, `color`, `timezone` from mangos.realmlist; +drop table mangos.realmlist; + +truncate realmd.account; +insert into realmd.account +select *,0 from mangos.account; +drop table mangos.account; + +INSERT INTO RealmCharacters +SELECT realmlist.id, account.id, 0 from realmlist, account; + +truncate realmd.ip_banned; +insert into realmd.ip_banned +select * from mangos.ip_banned; +drop table mangos.ip_banned; diff --git a/sql/updates/0.5/1475_character_aura.sql b/sql/updates/0.5/1475_character_aura.sql new file mode 100644 index 00000000000..6a4c49dbefd --- /dev/null +++ b/sql/updates/0.5/1475_character_aura.sql @@ -0,0 +1,3 @@ +ALTER TABLE `character_aura` + DROP PRIMARY KEY , + ADD PRIMARY KEY (`guid`,`spell`,`effect_index`) ; diff --git a/sql/updates/0.5/1511_object_involvedrelation.sql b/sql/updates/0.5/1511_object_involvedrelation.sql new file mode 100644 index 00000000000..05839658a80 --- /dev/null +++ b/sql/updates/0.5/1511_object_involvedrelation.sql @@ -0,0 +1,7 @@ +ALTER TABLE `object_involvedrelation` + RENAME TO `gameobject_involvedrelation`, + DROP PRIMARY KEY, + DROP `Id`, + CHANGE `objectId` `id` int(11) unsigned NOT NULL default '0', + CHANGE `questId` `quest` int(11) unsigned NOT NULL default '0' COMMENT 'Quest Identifier' AFTER `id`, + ADD PRIMARY KEY (`id`,`quest`); diff --git a/sql/updates/0.5/1511_object_questrelation.sql b/sql/updates/0.5/1511_object_questrelation.sql new file mode 100644 index 00000000000..aac0e5679e6 --- /dev/null +++ b/sql/updates/0.5/1511_object_questrelation.sql @@ -0,0 +1,7 @@ +ALTER TABLE `object_questrelation` + RENAME TO `gameobject_questrelation`, + DROP PRIMARY KEY, + DROP `Id`, + CHANGE `objectId` `id` int(11) unsigned NOT NULL default '0', + CHANGE `questId` `quest` int(11) unsigned NOT NULL default '0' COMMENT 'Quest Identifier' AFTER `id`, + ADD PRIMARY KEY (`id`,`quest`); diff --git a/sql/updates/0.5/1526_npc_vendor.sql b/sql/updates/0.5/1526_npc_vendor.sql new file mode 100644 index 00000000000..36a331b75f6 --- /dev/null +++ b/sql/updates/0.5/1526_npc_vendor.sql @@ -0,0 +1,9 @@ +ALTER TABLE `npc_vendor` + DROP PRIMARY KEY, + DROP KEY `vendor_id` , + DROP `index_id`, + CHANGE `entry` `entry` int(11) unsigned NOT NULL default '0', + CHANGE `itemguid` `item` int(11) unsigned NOT NULL default '0', + CHANGE `amount` `buycount` int(11) unsigned NOT NULL default '1', + ADD `maxcount` int(11) unsigned NOT NULL default '0', + ADD `incrtime` int(11) unsigned NOT NULL default '0'; diff --git a/sql/updates/0.5/1562_creature_template.sql b/sql/updates/0.5/1562_creature_template.sql new file mode 100644 index 00000000000..529e027dac2 --- /dev/null +++ b/sql/updates/0.5/1562_creature_template.sql @@ -0,0 +1,3 @@ +ALTER TABLE `creature_template` + ADD `mingold` int(30) unsigned NOT NULL default '0' AFTER `spell4` , + ADD `maxgold` int(30) unsigned NOT NULL default '0' AFTER `mingold`; \ No newline at end of file diff --git a/sql/updates/0.5/1576_command.sql b/sql/updates/0.5/1576_command.sql new file mode 100644 index 00000000000..5c323794634 --- /dev/null +++ b/sql/updates/0.5/1576_command.sql @@ -0,0 +1 @@ +INSERT INTO `command` VALUES ('additemset',3,'Syntax: .additemset #itemsetid\r\n\r\nAdd items from itemset of id #itemsetid to your inventory. Will add by one example each item from itemset.'); diff --git a/sql/updates/0.5/1595_area_graveyard.sql b/sql/updates/0.5/1595_area_graveyard.sql new file mode 100644 index 00000000000..512762f464f --- /dev/null +++ b/sql/updates/0.5/1595_area_graveyard.sql @@ -0,0 +1,11 @@ +DROP TABLE IF EXISTS `areatrigger_graveyard_zone`; + +CREATE TABLE `areatrigger_graveyard_zone` AS SELECT + `areatrigger_graveyard`.`id` AS `id`, + `areatrigger_graveyard`.`map` AS `ghost_map`, + `areatrigger_graveyard`.`zone` AS `ghost_zone` +FROM `areatrigger_graveyard` ; + +ALTER TABLE `areatrigger_graveyard` + DROP `zone`; + diff --git a/sql/updates/0.5/1601_game_addons.sql b/sql/updates/0.5/1601_game_addons.sql new file mode 100644 index 00000000000..c9dbeb251a2 --- /dev/null +++ b/sql/updates/0.5/1601_game_addons.sql @@ -0,0 +1,7 @@ +DROP TABLE IF EXISTS `game_addons`; +CREATE TABLE `game_addons` ( + `addonname` char(255) NOT NULL default '', + `crc` bigint(20) NOT NULL default '0', + `enabled` tinyint(4) NOT NULL default '0', + PRIMARY KEY (`addonname`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Addons System'; diff --git a/sql/updates/0.5/1615_areatrigger_graveyard.sql b/sql/updates/0.5/1615_areatrigger_graveyard.sql new file mode 100644 index 00000000000..abe329b9c08 --- /dev/null +++ b/sql/updates/0.5/1615_areatrigger_graveyard.sql @@ -0,0 +1,3 @@ +ALTER TABLE `areatrigger_graveyard` + CHANGE `id` `id` int(11) unsigned NOT NULL auto_increment COMMENT 'Identifier'; + diff --git a/sql/updates/0.5/1635_character.sql b/sql/updates/0.5/1635_character.sql new file mode 100644 index 00000000000..c70fc62d8e4 --- /dev/null +++ b/sql/updates/0.5/1635_character.sql @@ -0,0 +1,3 @@ +ALTER TABLE `character` CHANGE `honor` `highest_rank` INT( 11 ) DEFAULT '0' NOT NULL , +CHANGE `last_week_honor` `standing` INT( 11 ) DEFAULT '0' NOT NULL ; +ALTER TABLE `character` ADD `rating` FLOAT( 11 ) DEFAULT '0' NOT NULL AFTER `standing` ; \ No newline at end of file diff --git a/sql/updates/0.5/1669_character_spell.sql b/sql/updates/0.5/1669_character_spell.sql new file mode 100644 index 00000000000..0bd65b34b3f --- /dev/null +++ b/sql/updates/0.5/1669_character_spell.sql @@ -0,0 +1,2 @@ +ALTER TABLE `character_spell` + ADD `active` int(11) unsigned NOT NULL default '1'; diff --git a/sql/updates/0.5/1676_game_graveyard.sql b/sql/updates/0.5/1676_game_graveyard.sql new file mode 100644 index 00000000000..c8349688291 --- /dev/null +++ b/sql/updates/0.5/1676_game_graveyard.sql @@ -0,0 +1,5 @@ +ALTER TABLE `areatrigger_graveyard` + RENAME TO `game_graveyard`; + +ALTER TABLE `areatrigger_graveyard_zone` + RENAME TO `game_graveyard_zone`; diff --git a/sql/updates/0.5/1676_game_tele.sql b/sql/updates/0.5/1676_game_tele.sql new file mode 100644 index 00000000000..73a5d448ae1 --- /dev/null +++ b/sql/updates/0.5/1676_game_tele.sql @@ -0,0 +1,10 @@ +CREATE TABLE `game_tele` ( + `id` int(11) unsigned NOT NULL auto_increment, + `position_x` float NOT NULL default '0', + `position_y` float NOT NULL default '0', + `position_z` float NOT NULL default '0', + `orientation` float NOT NULL default '0', + `map` int(11) unsigned NOT NULL default '0', + `name` varchar(100) NOT NULL default '', + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Tele Command'; diff --git a/sql/updates/0.5/1687_loot_template.sql b/sql/updates/0.5/1687_loot_template.sql new file mode 100644 index 00000000000..a9f8eb23362 --- /dev/null +++ b/sql/updates/0.5/1687_loot_template.sql @@ -0,0 +1,4 @@ +ALTER TABLE `loot_template` + ADD `questchance` float NOT NULL default '0'; + +UPDATE `loot_template` SET `questchance` = 100 WHERE `chance` = 0; diff --git a/sql/updates/0.5/1704_item_template.sql b/sql/updates/0.5/1704_item_template.sql new file mode 100644 index 00000000000..96079a6e410 --- /dev/null +++ b/sql/updates/0.5/1704_item_template.sql @@ -0,0 +1,9 @@ +ALTER TABLE `item_template` ADD COLUMN `BuyCount` TINYINT(3) UNSIGNED NOT NULL DEFAULT 1 AFTER `Flags`; +ALTER TABLE `npc_vendor` DROP COLUMN `buycount`; + +UPDATE `item_template` + SET `BuyCount` = (`BuyPrice` DIV (`SellPrice` * 4)) WHERE `SellPrice` > 0; + +UPDATE `item_template` + SET `BuyCount` = 1 WHERE `BuyCount` = 0; + diff --git a/sql/updates/0.5/1799_quest_template.sql b/sql/updates/0.5/1799_quest_template.sql new file mode 100644 index 00000000000..05a3ebd7fa6 --- /dev/null +++ b/sql/updates/0.5/1799_quest_template.sql @@ -0,0 +1,11 @@ +ALTER TABLE `quest_template` + ADD COLUMN `RequiredRepFaction` int(11) unsigned NOT NULL default '0' AFTER `RequiredTradeskill`, + ADD COLUMN `RequiredRepValue` int(11) unsigned NOT NULL default '0' AFTER `RequiredRepFaction`, + CHANGE `ReqKillMobId1` `ReqKillMobOrGOId1` int(11) NOT NULL default '0', + CHANGE `ReqKillMobId2` `ReqKillMobOrGOId2` int(11) NOT NULL default '0', + CHANGE `ReqKillMobId3` `ReqKillMobOrGOId3` int(11) NOT NULL default '0', + CHANGE `ReqKillMobId4` `ReqKillMobOrGOId4` int(11) NOT NULL default '0', + CHANGE `ReqKillMobCount1` `ReqKillMobOrGOCount1` int(11) unsigned NOT NULL default '0', + CHANGE `ReqKillMobCount2` `ReqKillMobOrGOCount2` int(11) unsigned NOT NULL default '0', + CHANGE `ReqKillMobCount3` `ReqKillMobOrGOCount3` int(11) unsigned NOT NULL default '0', + CHANGE `ReqKillMobCount4` `ReqKillMobOrGOCount4` int(11) unsigned NOT NULL default '0'; diff --git a/sql/updates/0.5/1825_game_corpse.sql b/sql/updates/0.5/1825_game_corpse.sql new file mode 100644 index 00000000000..eabad471e7d --- /dev/null +++ b/sql/updates/0.5/1825_game_corpse.sql @@ -0,0 +1 @@ +ALTER TABLE `game_corpse` DROP INDEX `idx_player`; diff --git a/sql/updates/0.5/1856_command.sql b/sql/updates/0.5/1856_command.sql new file mode 100644 index 00000000000..b644a0cfc92 --- /dev/null +++ b/sql/updates/0.5/1856_command.sql @@ -0,0 +1,3 @@ +insert into command values('shutdown','3','Syntax: .shutdown seconds'); +insert into command values('cshutdown','3','Syntax: .cshutdown Cancels shuttdown'); + diff --git a/sql/updates/0.5/1865_command.sql b/sql/updates/0.5/1865_command.sql new file mode 100644 index 00000000000..baa57731849 --- /dev/null +++ b/sql/updates/0.5/1865_command.sql @@ -0,0 +1,2 @@ +insert into command values('reset','3','Usage: .reset stats\r\nResets all stats of the targeted player to their original values at level 1.\r\nPlease unequip all items and debuff all auras from the player before using.'); + diff --git a/sql/updates/0.5/1880_command.sql b/sql/updates/0.5/1880_command.sql new file mode 100644 index 00000000000..e28e5748364 --- /dev/null +++ b/sql/updates/0.5/1880_command.sql @@ -0,0 +1,3 @@ +insert into command values('maxskill','3','Usage: .maxskill\r\nSets all skills of the targeted player to their maximum values for its current level.'); +UPDATE `command` SET `help` = 'Usage:\r\n.reset stats\r\n Resets all stats of the targeted player to their original values at level 1.\r\n Please unequip all items and debuff all auras from the player before using.\r\n.reset talents\r\n Removes all talents of the targeted player.' WHERE `name` = 'reset'; + diff --git a/sql/updates/0.5/1883_quest_template.sql b/sql/updates/0.5/1883_quest_template.sql new file mode 100644 index 00000000000..8c650cb065b --- /dev/null +++ b/sql/updates/0.5/1883_quest_template.sql @@ -0,0 +1,2 @@ +ALTER TABLE `quest_template` + ADD COLUMN `QuestSort` int(11) unsigned NOT NULL default '0' AFTER `ZoneId`; diff --git a/sql/updates/0.5/1915_loot_template.sql b/sql/updates/0.5/1915_loot_template.sql new file mode 100644 index 00000000000..d2893b61cb7 --- /dev/null +++ b/sql/updates/0.5/1915_loot_template.sql @@ -0,0 +1,30 @@ +CREATE TABLE `creature_loot_template` AS SELECT DISTINCT + `loot_template`.`entry` AS `entry`, + `loot_template`.`item` AS `item`, + `loot_template`.`chance` AS `chance`, + `loot_template`.`questchance` AS `questchance` +FROM `loot_template`, `creature_template` WHERE `loot_template`.`entry` = `creature_template`.`lootid`; + +CREATE TABLE `gameobject_loot_template` AS SELECT DISTINCT + `loot_template`.`entry` AS `entry`, + `loot_template`.`item` AS `item`, + `loot_template`.`chance` AS `chance`, + `loot_template`.`questchance` AS `questchance` +FROM `loot_template`, `gameobject` WHERE `loot_template`.`entry` = `gameobject`.`loot`; + +CREATE TABLE `fishing_loot_template` AS SELECT + (`loot_template`.`entry` - 30000) AS `entry`, + `loot_template`.`item` AS `item`, + `loot_template`.`chance` AS `chance`, + `loot_template`.`questchance` AS `questchance` +FROM `loot_template` WHERE `loot_template`.`entry` > 30000 AND `loot_template`.`entry` < 33000; + +CREATE TABLE `pickpocketing_loot_template` ( + `entry` int(11) unsigned NOT NULL default '0', + `item` int(11) unsigned NOT NULL default '0', + `chance` float NOT NULL default '100', + `questchance` float NOT NULL default '0', + PRIMARY KEY (`entry`,`item`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Loot System'; + +DROP TABLE `loot_template`; diff --git a/sql/updates/0.5/1935_command.sql b/sql/updates/0.5/1935_command.sql new file mode 100644 index 00000000000..a766fc34c31 --- /dev/null +++ b/sql/updates/0.5/1935_command.sql @@ -0,0 +1,2 @@ +INSERT INTO command VALUES('whispers','1','Usage: .whispers on|off\r\nEnable/disable accepting whispers by GM from players. By default use mangosd.conf setting.'); + diff --git a/sql/updates/0.5/1949_corpse.sql b/sql/updates/0.5/1949_corpse.sql new file mode 100644 index 00000000000..4e5e37c63d3 --- /dev/null +++ b/sql/updates/0.5/1949_corpse.sql @@ -0,0 +1,14 @@ +ALTER TABLE `game_corpse` + RENAME TO `corpse`; + +CREATE TABLE `corpse_grid` ( + `guid` bigint(20) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `position_x` int(11) NOT NULL default '0', + `position_y` int(11) NOT NULL default '0', + `cell_position_x` int(11) NOT NULL default '0', + `cell_position_y` int(11) NOT NULL default '0', + `grid` int(11) unsigned NOT NULL default '0' COMMENT 'Grid Identifier', + `cell` int(11) unsigned NOT NULL default '0' COMMENT 'Cell Identifier', + `map` int(11) unsigned NOT NULL default '0' COMMENT 'Map Identifier', + UNIQUE KEY `idx_search` (`grid`,`cell`,`map`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Grid System'; \ No newline at end of file diff --git a/sql/updates/0.5/1953_playercreateinfo_skill.sql b/sql/updates/0.5/1953_playercreateinfo_skill.sql new file mode 100644 index 00000000000..88a654ad4de --- /dev/null +++ b/sql/updates/0.5/1953_playercreateinfo_skill.sql @@ -0,0 +1,3 @@ +ALTER IGNORE TABLE `playercreateinfo_skill` + ADD PRIMARY KEY (`createid`,`Skill`); + diff --git a/sql/updates/0.5/1953_playercreateinfo_spell.sql b/sql/updates/0.5/1953_playercreateinfo_spell.sql new file mode 100644 index 00000000000..a7da2fc1f9f --- /dev/null +++ b/sql/updates/0.5/1953_playercreateinfo_spell.sql @@ -0,0 +1,3 @@ +ALTER IGNORE TABLE `playercreateinfo_spell` + ADD PRIMARY KEY (`createid`,`Spell`); + diff --git a/sql/updates/0.5/1956_command.sql b/sql/updates/0.5/1956_command.sql new file mode 100644 index 00000000000..5320edb5463 --- /dev/null +++ b/sql/updates/0.5/1956_command.sql @@ -0,0 +1,4 @@ +DELETE FROM `command` WHERE `name` = 'modify level'; + +UPDATE `command` SET `help` = 'Syntax: .die\r\n\r\nKill the selected player or creature. If no player or creature selected, it will kill you.' WHERE `name` = 'die'; + diff --git a/sql/updates/0.5/2017_quest_template.sql b/sql/updates/0.5/2017_quest_template.sql new file mode 100644 index 00000000000..24bf660eb4f --- /dev/null +++ b/sql/updates/0.5/2017_quest_template.sql @@ -0,0 +1,3 @@ +ALTER TABLE `quest_template` + CHANGE `MaxLevel` `QuestLevel` int(11) unsigned NOT NULL default '0', + CHANGE `RewMoney` `RewOrReqMoney` int(11) NOT NULL default '0'; diff --git a/sql/updates/0.5/2033_command.sql b/sql/updates/0.5/2033_command.sql new file mode 100644 index 00000000000..9310abacb3c --- /dev/null +++ b/sql/updates/0.5/2033_command.sql @@ -0,0 +1,2 @@ +UPDATE command SET `help` = 'Syntax: .learn #parameter\r\n\r\nSelected character learn a spell of id #parameter. If GM want to learn all default spells for Game Masters, use the syntax .learn all Character selection in this case ignored.' WHERE `name` = 'learn'; +UPDATE command SET `help` = 'Syntax: .unlearn #startspell #endspell\r\n\r\nUnlearn for selected player the range of spells between id #startspell and #endspell. If no #endspell is provided, just unlearn spell of id #startspell.' WHERE `name` = 'unlearn'; diff --git a/sql/updates/0.5/2041_auctionhouse_bid.sql b/sql/updates/0.5/2041_auctionhouse_bid.sql new file mode 100644 index 00000000000..98a4a67c3af --- /dev/null +++ b/sql/updates/0.5/2041_auctionhouse_bid.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS `auctionhouse_bid`; diff --git a/sql/updates/0.5/2041_game_spell.sql b/sql/updates/0.5/2041_game_spell.sql new file mode 100644 index 00000000000..a7033cf7479 --- /dev/null +++ b/sql/updates/0.5/2041_game_spell.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS `game_spell`; diff --git a/sql/updates/0.5/2041_game_talent.sql b/sql/updates/0.5/2041_game_talent.sql new file mode 100644 index 00000000000..de619644ad3 --- /dev/null +++ b/sql/updates/0.5/2041_game_talent.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS `game_talent`; diff --git a/sql/updates/0.5/2047_quest_template.sql b/sql/updates/0.5/2047_quest_template.sql new file mode 100644 index 00000000000..910c4fc5335 --- /dev/null +++ b/sql/updates/0.5/2047_quest_template.sql @@ -0,0 +1,5 @@ +UPDATE `quest_template` + SET `SpecialFlags` = `SpecialFlags` | `QuestFlags`; + +ALTER TABLE `quest_template` + DROP `QuestFlags`; diff --git a/sql/updates/0.5/2054_command.sql b/sql/updates/0.5/2054_command.sql new file mode 100644 index 00000000000..b99c2822d45 --- /dev/null +++ b/sql/updates/0.5/2054_command.sql @@ -0,0 +1,2 @@ +UPDATE command SET `help` = 'Syntax: .learn #parameter\r\n\r\nSelected character learn a spell of id #parameter. A GM can use .learn all if he wants to learn all default spells for Game Masters, and .learn all_myclass to learn all spells available for his class (Character selection in these cases ignored).' WHERE `name` = 'learn'; +UPDATE command SET `help` = 'Syntax: .additem #itemid [#itemcount] or .additem 0 #itemcount $itemname\r\n\r\nAdds the specified number of items of id #itemid to your inventory. If #itemcount is omitted, only one item will be added.\r\nWith the second syntax you can add an item with exact (!) name $itemname.' WHERE `name` = 'additem'; \ No newline at end of file diff --git a/sql/updates/0.5/2058_command.sql b/sql/updates/0.5/2058_command.sql new file mode 100644 index 00000000000..ff9ec86da4c --- /dev/null +++ b/sql/updates/0.5/2058_command.sql @@ -0,0 +1,2 @@ +UPDATE command SET `help` = 'Syntax: .additem #itemid [#itemcount] or .additem 0 #itemcount $itemname\r\n\r\nAdds the specified number of items of id #itemid to your or selected character inventory. If #itemcount is omitted, only one item will be added.\r\nWith the second syntax you can add an item with exact (!) name $itemname.' WHERE `name` = 'additem'; +UPDATE command SET `help` = 'Syntax: .additemset #itemsetid\r\n\r\nAdd items from itemset of id #itemsetid to your or selected character inventory. Will add by one example each item from itemset.' WHERE `name` = 'additemset'; \ No newline at end of file diff --git a/sql/updates/0.5/2066_creature_template.sql b/sql/updates/0.5/2066_creature_template.sql new file mode 100644 index 00000000000..0dd3ba8339e --- /dev/null +++ b/sql/updates/0.5/2066_creature_template.sql @@ -0,0 +1,3 @@ +ALTER TABLE `creature_template` + ADD `trainer_spell` int(11) unsigned default '0' AFTER `trainer_type`, + ADD `race` int(11) unsigned default '0' AFTER `class`; diff --git a/sql/updates/0.5/2069_quest_template.sql b/sql/updates/0.5/2069_quest_template.sql new file mode 100644 index 00000000000..f06edb9b352 --- /dev/null +++ b/sql/updates/0.5/2069_quest_template.sql @@ -0,0 +1,3 @@ +ALTER TABLE `quest_template` + CHANGE `RequiredTradeskill` `RequiredSkill` int(11) unsigned NOT NULL default '0', + ADD COLUMN `RequiredSkillValue` int(11) unsigned NOT NULL default '1' AFTER `RequiredSkill`; diff --git a/sql/updates/0.5/2079_command.sql b/sql/updates/0.5/2079_command.sql new file mode 100644 index 00000000000..5b5ad9d4c4c --- /dev/null +++ b/sql/updates/0.5/2079_command.sql @@ -0,0 +1,2 @@ +INSERT INTO command VALUES('gocreature','2','Usage: .gocreature #creature_guid\r\nTeleport your character to creature with guid #creature_guid.'); +INSERT INTO command VALUES('goobject','1','Usage: .goobject #object_guid\r\nTeleport your character to gameobject with guid #object_guid'); \ No newline at end of file diff --git a/sql/updates/0.5/2099_npc_trainer.sql b/sql/updates/0.5/2099_npc_trainer.sql new file mode 100644 index 00000000000..29421cb1ff3 --- /dev/null +++ b/sql/updates/0.5/2099_npc_trainer.sql @@ -0,0 +1,5 @@ +ALTER TABLE `npc_trainer` + CHANGE `reqspell` `reqspell` int(11) unsigned default '0', + CHANGE `reqskill` `reqskill` int(11) unsigned default '0', + CHANGE `reqskillvalue` `reqskillvalue` int(11) unsigned default '0', + ADD COLUMN `reqlevel` int(11) unsigned default '0'; diff --git a/sql/updates/0.5/2107_command.sql b/sql/updates/0.5/2107_command.sql new file mode 100644 index 00000000000..32bdf7cd730 --- /dev/null +++ b/sql/updates/0.5/2107_command.sql @@ -0,0 +1 @@ +INSERT INTO command VALUES('targetobject','2','Usage: .targetobject [#go_id|#go_name_part]\r\nLocate and show position nearest gameobject. If #go_id or #go_name_part provide then locate and show position of nearest gameobject with gameobject template id #go_id or name included #go_name_part as part.'); diff --git a/sql/updates/0.5/2113_command.sql b/sql/updates/0.5/2113_command.sql new file mode 100644 index 00000000000..857cd724b46 --- /dev/null +++ b/sql/updates/0.5/2113_command.sql @@ -0,0 +1 @@ +INSERT INTO command VALUES('delobject','2','Usage: .delobject #go_guid\r\nDelete gameobject with guid #go_guid.'); diff --git a/sql/updates/0.5/2118_playercreateinfo_spell.sql b/sql/updates/0.5/2118_playercreateinfo_spell.sql new file mode 100644 index 00000000000..60e389432cc --- /dev/null +++ b/sql/updates/0.5/2118_playercreateinfo_spell.sql @@ -0,0 +1,31 @@ +ALTER TABLE `playercreateinfo_spell` ADD COLUMN `Active` tinyint(3) unsigned NOT NULL default '1'; +INSERT INTO `playercreateinfo_spell` VALUES ('21', '3025', 'Cat Form Passive', '0'); +INSERT INTO `playercreateinfo_spell` VALUES ('21', '3122', 'Tree Form Passive', '0'); +INSERT INTO `playercreateinfo_spell` VALUES ('21', '5419', 'Travel Form Passive', '0'); +INSERT INTO `playercreateinfo_spell` VALUES ('21', '5421', 'Aqua Form Passive', '0'); +INSERT INTO `playercreateinfo_spell` VALUES ('21', '1178', 'Bear Form Passive', '0'); +INSERT INTO `playercreateinfo_spell` VALUES ('21', '9635', 'Dire Bear Form Passive', '0'); +INSERT INTO `playercreateinfo_spell` VALUES ('21', '24905', 'Moonkin Form Passive', '0'); +INSERT INTO `playercreateinfo_spell` VALUES ('30', '3025', 'Cat Form Passive', '0'); +INSERT INTO `playercreateinfo_spell` VALUES ('30', '3122', 'Tree Form Passive', '0'); +INSERT INTO `playercreateinfo_spell` VALUES ('30', '5419', 'Travel Form Passive', '0'); +INSERT INTO `playercreateinfo_spell` VALUES ('30', '5421', 'Aqua Form Passive', '0'); +INSERT INTO `playercreateinfo_spell` VALUES ('30', '1178', 'Bear Form Passive', '0'); +INSERT INTO `playercreateinfo_spell` VALUES ('30', '9635', 'Dire Bear Form Passive', '0'); +INSERT INTO `playercreateinfo_spell` VALUES ('30', '24905', 'Moonkin Form Passive', '0'); +INSERT INTO `playercreateinfo_spell` VALUES ('1', '7376', 'Defensive Stance Passive', '0'); +INSERT INTO `playercreateinfo_spell` VALUES ('1', '7381', 'Berserker Stance Passive', '0'); +INSERT INTO `playercreateinfo_spell` VALUES ('7', '7376', 'Defensive Stance Passive', '0'); +INSERT INTO `playercreateinfo_spell` VALUES ('7', '7381', 'Berserker Stance Passive', '0'); +INSERT INTO `playercreateinfo_spell` VALUES ('12', '7376', 'Defensive Stance Passive', '0'); +INSERT INTO `playercreateinfo_spell` VALUES ('12', '7381', 'Berserker Stance Passive', '0'); +INSERT INTO `playercreateinfo_spell` VALUES ('17', '7376', 'Defensive Stance Passive', '0'); +INSERT INTO `playercreateinfo_spell` VALUES ('17', '7381', 'Berserker Stance Passive', '0'); +INSERT INTO `playercreateinfo_spell` VALUES ('22', '7376', 'Defensive Stance Passive', '0'); +INSERT INTO `playercreateinfo_spell` VALUES ('22', '7381', 'Berserker Stance Passive', '0'); +INSERT INTO `playercreateinfo_spell` VALUES ('27', '7376', 'Defensive Stance Passive', '0'); +INSERT INTO `playercreateinfo_spell` VALUES ('27', '7381', 'Berserker Stance Passive', '0'); +INSERT INTO `playercreateinfo_spell` VALUES ('31', '7376', 'Defensive Stance Passive', '0'); +INSERT INTO `playercreateinfo_spell` VALUES ('31', '7381', 'Berserker Stance Passive', '0'); +INSERT INTO `playercreateinfo_spell` VALUES ('35', '7376', 'Defensive Stance Passive', '0'); +INSERT INTO `playercreateinfo_spell` VALUES ('35', '7381', 'Berserker Stance Passive', '0'); \ No newline at end of file diff --git a/sql/updates/0.5/2119_command.sql b/sql/updates/0.5/2119_command.sql new file mode 100644 index 00000000000..d9c9747ba2c --- /dev/null +++ b/sql/updates/0.5/2119_command.sql @@ -0,0 +1 @@ +UPDATE command SET `help` = 'Syntax: .learn #parameter\r\n\r\nSelected character learn a spell of id #parameter. A GM can use .learn all if he wants to learn all default spells for Game Masters, .learn all_lang to learn all languages, and .learn all_myclass to learn all spells available for his class (Character selection in these cases ignored).' WHERE `name` = 'learn'; diff --git a/sql/updates/0.5/2130_quest_template.sql b/sql/updates/0.5/2130_quest_template.sql new file mode 100644 index 00000000000..46ff557cc9d --- /dev/null +++ b/sql/updates/0.5/2130_quest_template.sql @@ -0,0 +1,3 @@ +ALTER TABLE `quest_template` + CHANGE `RewRepValue1` `RewRepValue1` int(11) NOT NULL default '0', + CHANGE `RewRepValue2` `RewRepValue2` int(11) NOT NULL default '0'; diff --git a/sql/updates/0.5/2131_command.sql b/sql/updates/0.5/2131_command.sql new file mode 100644 index 00000000000..7def5be834d --- /dev/null +++ b/sql/updates/0.5/2131_command.sql @@ -0,0 +1 @@ +UPDATE command SET `help` = 'Syntax: .addmove [#waittime]\r\n\r\nAdd your current location as a waypoint for the selected creature. And optional add wait time.' WHERE `name` = 'addmove'; diff --git a/sql/updates/0.5/2156_character.sql b/sql/updates/0.5/2156_character.sql new file mode 100644 index 00000000000..ffb5e76a82a --- /dev/null +++ b/sql/updates/0.5/2156_character.sql @@ -0,0 +1,3 @@ +ALTER TABLE `character` + ADD `totaltime` int(11) unsigned NOT NULL default '0', + ADD `leveltime` int(11) unsigned NOT NULL default '0'; diff --git a/sql/updates/0.5/2164_command.sql b/sql/updates/0.5/2164_command.sql new file mode 100644 index 00000000000..d04c38e0fe2 --- /dev/null +++ b/sql/updates/0.5/2164_command.sql @@ -0,0 +1 @@ +INSERT INTO command VALUES('searchtele','1','Syntax: .searchtele $substring\r\n\r\nSearch and output all .tele command locations with provide $substring in name.'); diff --git a/sql/updates/0.5/2191_npc_trainer.sql b/sql/updates/0.5/2191_npc_trainer.sql new file mode 100644 index 00000000000..6e76442d833 --- /dev/null +++ b/sql/updates/0.5/2191_npc_trainer.sql @@ -0,0 +1,4 @@ +ALTER TABLE `npc_trainer` + DROP PRIMARY KEY, + DROP `rowid`, + ADD UNIQUE KEY `entry_spell` (`entry`,`spell`); diff --git a/sql/updates/0.5/2191_playercreateinfo.sql b/sql/updates/0.5/2191_playercreateinfo.sql new file mode 100644 index 00000000000..cee1f2beeb7 --- /dev/null +++ b/sql/updates/0.5/2191_playercreateinfo.sql @@ -0,0 +1,6 @@ +ALTER TABLE `playercreateinfo` + DROP `attackpower`, + DROP `mindmg`, + DROP `maxdmg`, + DROP `ranmindmg`, + DROP `ranmaxdmg`; diff --git a/sql/updates/0.5/2220_command.sql b/sql/updates/0.5/2220_command.sql new file mode 100644 index 00000000000..d8c3b02442d --- /dev/null +++ b/sql/updates/0.5/2220_command.sql @@ -0,0 +1 @@ +UPDATE command SET `help` = 'Syntax: .addmove #creature_guid [#waittime]\r\n\r\nAdd your current location as a waypoint for creature with guid #creature_guid. And optional add wait time.' WHERE `name` = 'addmove'; diff --git a/sql/updates/0.6/2297_character_stable.sql b/sql/updates/0.6/2297_character_stable.sql new file mode 100644 index 00000000000..5df6b4d94f5 --- /dev/null +++ b/sql/updates/0.6/2297_character_stable.sql @@ -0,0 +1,20 @@ +DROP TABLE IF EXISTS `character_stable`; +CREATE TABLE `character_stable` ( + `owner` int(11) unsigned NOT NULL default '0', + `slot` int(11) unsigned NOT NULL default '0', + `petnumber` int(11) unsigned NOT NULL default '0', + `entry` int(11) unsigned NOT NULL default '0', + `level` int(11) unsigned NOT NULL default '0', + `loyalty` int(11) unsigned NOT NULL default '1', + `trainpoint` int(11) unsigned NOT NULL default '0', + KEY `petnumber` (`petnumber`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System'; + +-- +-- Dumping data for table `character_stable` +-- + +/*!40000 ALTER TABLE `character_stable` DISABLE KEYS */; +LOCK TABLES `character_stable` WRITE; +UNLOCK TABLES; +/*!40000 ALTER TABLE character_stable ENABLE KEYS */; \ No newline at end of file diff --git a/sql/updates/0.6/2302_player_levelupgains.sql b/sql/updates/0.6/2302_player_levelupgains.sql new file mode 100644 index 00000000000..cc336a6ea8c --- /dev/null +++ b/sql/updates/0.6/2302_player_levelupgains.sql @@ -0,0 +1,2397 @@ +-- phpMyAdmin SQL Dump +-- version 2.7.0-pl2 +-- http://www.phpmyadmin.net +-- +-- Host: localhost +-- Generation Time: Sep 04, 2006 at 05:27 AM +-- Server version: 5.0.22 +-- PHP Version: 5.2.0-dev +-- +-- Database: `mangos` +-- + +-- -------------------------------------------------------- + +-- +-- Table structure for table `player_levelupgains` +-- + +CREATE TABLE `player_levelupgains` ( + `entry` smallint(5) unsigned NOT NULL auto_increment, + `race` tinyint(3) unsigned NOT NULL, + `class` tinyint(3) unsigned NOT NULL, + `level` tinyint(3) unsigned NOT NULL, + `hp` smallint(5) unsigned NOT NULL, + `mana` smallint(5) unsigned NOT NULL, + `str` smallint(5) unsigned NOT NULL, + `agi` smallint(5) unsigned NOT NULL, + `sta` smallint(5) unsigned NOT NULL, + `int` smallint(5) unsigned NOT NULL, + `spi` smallint(5) unsigned NOT NULL, + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 PACK_KEYS=0 COMMENT='Stores level up stat gains.' AUTO_INCREMENT=2401 ; + +-- +-- Dumping data for table `player_levelupgains` +-- + +INSERT INTO `player_levelupgains` VALUES (2, 3, 3, 1, 17, 6, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (3, 3, 3, 2, 17, 21, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (4, 3, 3, 3, 17, 22, 0, 2, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (5, 3, 3, 4, 17, 23, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (6, 3, 3, 5, 17, 24, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (7, 3, 3, 6, 17, 25, 0, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (8, 3, 3, 7, 17, 26, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (9, 3, 3, 8, 17, 27, 0, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (10, 3, 3, 9, 17, 28, 1, 1, 0, 1, 0); +INSERT INTO `player_levelupgains` VALUES (11, 3, 3, 10, 17, 29, 0, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (12, 3, 3, 11, 17, 30, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (13, 3, 3, 12, 17, 31, 0, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (14, 3, 3, 13, 18, 32, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (15, 3, 3, 14, 19, 33, 0, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (16, 3, 3, 15, 20, 34, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (17, 3, 3, 16, 21, 35, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (18, 3, 3, 17, 22, 36, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (19, 3, 3, 18, 23, 37, 0, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (20, 3, 3, 19, 24, 38, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (21, 3, 3, 20, 25, 39, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (22, 3, 3, 21, 26, 40, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (23, 3, 3, 22, 27, 41, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (24, 3, 3, 23, 28, 42, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (25, 3, 3, 24, 29, 43, 0, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (26, 3, 3, 25, 30, 44, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (27, 3, 3, 26, 31, 45, 0, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (28, 3, 3, 27, 32, 45, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (29, 3, 3, 28, 33, 45, 0, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (30, 3, 3, 29, 34, 45, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (31, 3, 3, 30, 35, 45, 0, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (32, 3, 3, 31, 36, 45, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (33, 3, 3, 32, 37, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (34, 3, 3, 33, 38, 45, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (35, 3, 3, 34, 39, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (36, 3, 3, 35, 40, 45, 1, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (37, 3, 3, 36, 41, 45, 0, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (38, 3, 3, 37, 42, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (39, 3, 3, 38, 43, 45, 0, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (40, 3, 3, 39, 44, 45, 1, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (41, 3, 3, 40, 45, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (42, 3, 3, 41, 46, 45, 0, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (43, 3, 3, 42, 47, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (44, 3, 3, 43, 48, 45, 1, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (45, 3, 3, 44, 49, 45, 0, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (46, 3, 3, 45, 50, 45, 1, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (47, 3, 3, 46, 51, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (48, 3, 3, 47, 52, 45, 1, 3, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (49, 3, 3, 48, 53, 45, 0, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (50, 3, 3, 49, 54, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (51, 3, 3, 50, 55, 45, 1, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (52, 3, 3, 51, 56, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (53, 3, 3, 52, 57, 45, 0, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (54, 3, 3, 53, 58, 45, 1, 3, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (55, 3, 3, 54, 59, 45, 1, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (56, 3, 3, 55, 60, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (57, 3, 3, 56, 61, 45, 1, 3, 2, 1, 2); +INSERT INTO `player_levelupgains` VALUES (58, 3, 3, 57, 62, 45, 0, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (59, 3, 3, 58, 63, 45, 1, 3, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (60, 3, 3, 59, 64, 45, 1, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (62, 3, 2, 1, 18, 5, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (63, 3, 2, 2, 18, 20, 1, 0, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (64, 3, 2, 3, 18, 21, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (65, 3, 2, 4, 18, 22, 1, 0, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (66, 3, 2, 5, 18, 23, 1, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (67, 3, 2, 6, 18, 24, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (68, 3, 2, 7, 18, 25, 1, 1, 0, 0, 0); +INSERT INTO `player_levelupgains` VALUES (69, 3, 2, 8, 18, 26, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (70, 3, 2, 9, 18, 27, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (71, 3, 2, 10, 18, 28, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (72, 3, 2, 11, 18, 29, 1, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (73, 3, 2, 12, 18, 30, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (74, 3, 2, 13, 18, 31, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (75, 3, 2, 14, 19, 32, 1, 1, 2, 1, 0); +INSERT INTO `player_levelupgains` VALUES (76, 3, 2, 15, 20, 33, 2, 0, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (77, 3, 2, 16, 21, 34, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (78, 3, 2, 17, 22, 35, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (79, 3, 2, 18, 23, 36, 1, 0, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (80, 3, 2, 19, 24, 37, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (81, 3, 2, 20, 25, 38, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (82, 3, 2, 21, 26, 39, 2, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (83, 3, 2, 22, 27, 40, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (84, 3, 2, 23, 28, 41, 1, 1, 2, 1, 0); +INSERT INTO `player_levelupgains` VALUES (85, 3, 2, 24, 29, 42, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (86, 3, 2, 25, 30, 42, 2, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (87, 3, 2, 26, 31, 42, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (88, 3, 2, 27, 32, 42, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (89, 3, 2, 28, 33, 42, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (90, 3, 2, 29, 34, 42, 1, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (91, 3, 2, 30, 35, 42, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (92, 3, 2, 31, 36, 42, 2, 0, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (93, 3, 2, 32, 37, 42, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (94, 3, 2, 33, 38, 42, 2, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (95, 3, 2, 34, 39, 42, 1, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (96, 3, 2, 35, 40, 42, 2, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (97, 3, 2, 36, 41, 42, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (98, 3, 2, 37, 42, 42, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (99, 3, 2, 38, 43, 42, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (100, 3, 2, 39, 44, 42, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (101, 3, 2, 40, 45, 42, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (102, 3, 2, 41, 46, 42, 2, 0, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (103, 3, 2, 42, 47, 42, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (104, 3, 2, 43, 48, 42, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (105, 3, 2, 44, 49, 42, 2, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (106, 3, 2, 45, 50, 42, 1, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (107, 3, 2, 46, 51, 42, 2, 1, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (108, 3, 2, 47, 52, 42, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (109, 3, 2, 48, 53, 42, 1, 1, 2, 1, 2); +INSERT INTO `player_levelupgains` VALUES (110, 3, 2, 49, 54, 42, 2, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (111, 3, 2, 50, 55, 42, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (112, 3, 2, 51, 56, 42, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (113, 3, 2, 52, 57, 42, 2, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (114, 3, 2, 53, 58, 42, 1, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (115, 3, 2, 54, 59, 42, 2, 1, 2, 1, 2); +INSERT INTO `player_levelupgains` VALUES (116, 3, 2, 55, 60, 42, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (117, 3, 2, 56, 61, 42, 2, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (118, 3, 2, 57, 62, 42, 2, 1, 2, 2, 1); +INSERT INTO `player_levelupgains` VALUES (119, 3, 2, 58, 63, 42, 2, 1, 2, 1, 2); +INSERT INTO `player_levelupgains` VALUES (120, 3, 2, 59, 64, 42, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (122, 3, 5, 1, 15, 24, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (123, 3, 5, 2, 15, 25, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (124, 3, 5, 3, 15, 26, 1, 1, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (125, 3, 5, 4, 15, 27, 0, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (126, 3, 5, 5, 15, 28, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (127, 3, 5, 6, 15, 29, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (128, 3, 5, 7, 15, 30, 0, 1, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (129, 3, 5, 8, 15, 31, 0, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (130, 3, 5, 9, 15, 47, 1, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (131, 3, 5, 10, 15, 18, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (132, 3, 5, 11, 15, 34, 0, 1, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (133, 3, 5, 12, 15, 35, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (134, 3, 5, 13, 15, 36, 0, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (135, 3, 5, 14, 15, 37, 1, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (136, 3, 5, 15, 15, 38, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (137, 3, 5, 16, 15, 54, 0, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (138, 3, 5, 17, 15, 25, 0, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (139, 3, 5, 18, 15, 41, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (140, 3, 5, 19, 15, 42, 1, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (141, 3, 5, 20, 15, 43, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (142, 3, 5, 21, 16, 59, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (143, 3, 5, 22, 17, 30, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (144, 3, 5, 23, 18, 61, 1, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (145, 3, 5, 24, 19, 32, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (146, 3, 5, 25, 20, 63, 0, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (147, 3, 5, 26, 21, 34, 0, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (148, 3, 5, 27, 22, 65, 0, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (149, 3, 5, 28, 23, 36, 1, 1, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (150, 3, 5, 29, 24, 52, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (151, 3, 5, 30, 25, 68, 0, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (152, 3, 5, 31, 26, 39, 0, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (153, 3, 5, 32, 27, 69, 1, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (154, 3, 5, 33, 28, 54, 0, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (155, 3, 5, 34, 29, 39, 0, 1, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (156, 3, 5, 35, 30, 54, 1, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (157, 3, 5, 36, 31, 69, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (158, 3, 5, 37, 32, 54, 0, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (159, 3, 5, 38, 33, 39, 0, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (160, 3, 5, 39, 34, 54, 1, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (161, 3, 5, 40, 35, 69, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (162, 3, 5, 41, 36, 54, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (163, 3, 5, 42, 37, 54, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (164, 3, 5, 43, 38, 54, 1, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (165, 3, 5, 44, 39, 54, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (166, 3, 5, 45, 40, 54, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (167, 3, 5, 46, 41, 54, 1, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (168, 3, 5, 47, 42, 54, 0, 1, 1, 2, 3); +INSERT INTO `player_levelupgains` VALUES (169, 3, 5, 48, 43, 54, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (170, 3, 5, 49, 44, 54, 1, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (171, 3, 5, 50, 45, 54, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (172, 3, 5, 51, 46, 54, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (173, 3, 5, 52, 47, 54, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (174, 3, 5, 53, 48, 54, 0, 0, 1, 2, 3); +INSERT INTO `player_levelupgains` VALUES (175, 3, 5, 54, 49, 54, 0, 1, 0, 3, 2); +INSERT INTO `player_levelupgains` VALUES (176, 3, 5, 55, 50, 54, 1, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (177, 3, 5, 56, 51, 54, 0, 1, 1, 2, 3); +INSERT INTO `player_levelupgains` VALUES (178, 3, 5, 57, 52, 54, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (179, 3, 5, 58, 53, 54, 1, 1, 0, 3, 3); +INSERT INTO `player_levelupgains` VALUES (180, 3, 5, 59, 54, 54, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (182, 3, 4, 1, 17, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (183, 3, 4, 2, 17, 0, 0, 1, 0, 0, 1); +INSERT INTO `player_levelupgains` VALUES (184, 3, 4, 3, 17, 0, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (185, 3, 4, 4, 17, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (186, 3, 4, 5, 17, 0, 0, 1, 0, 0, 1); +INSERT INTO `player_levelupgains` VALUES (187, 3, 4, 6, 17, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (188, 3, 4, 7, 17, 0, 1, 1, 0, 0, 0); +INSERT INTO `player_levelupgains` VALUES (189, 3, 4, 8, 17, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (190, 3, 4, 9, 17, 0, 0, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (191, 3, 4, 10, 17, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (192, 3, 4, 11, 17, 0, 1, 1, 0, 0, 0); +INSERT INTO `player_levelupgains` VALUES (193, 3, 4, 12, 17, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (194, 3, 4, 13, 17, 0, 0, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (195, 3, 4, 14, 17, 0, 1, 2, 0, 1, 0); +INSERT INTO `player_levelupgains` VALUES (196, 3, 4, 15, 18, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (197, 3, 4, 16, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (198, 3, 4, 17, 20, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (199, 3, 4, 18, 21, 0, 1, 2, 0, 0, 1); +INSERT INTO `player_levelupgains` VALUES (200, 3, 4, 19, 22, 0, 0, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (201, 3, 4, 20, 23, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (202, 3, 4, 21, 24, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (203, 3, 4, 22, 25, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (204, 3, 4, 23, 26, 0, 1, 1, 0, 1, 0); +INSERT INTO `player_levelupgains` VALUES (205, 3, 4, 24, 27, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (206, 3, 4, 25, 28, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (207, 3, 4, 26, 29, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (208, 3, 4, 27, 30, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (209, 3, 4, 28, 31, 0, 0, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (210, 3, 4, 29, 32, 0, 1, 2, 0, 0, 1); +INSERT INTO `player_levelupgains` VALUES (211, 3, 4, 30, 33, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (212, 3, 4, 31, 34, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (213, 3, 4, 32, 35, 0, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (214, 3, 4, 33, 36, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (215, 3, 4, 34, 37, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (216, 3, 4, 35, 38, 0, 2, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (217, 3, 4, 36, 39, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (218, 3, 4, 37, 40, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (219, 3, 4, 38, 41, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (220, 3, 4, 39, 42, 0, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (221, 3, 4, 40, 43, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (222, 3, 4, 41, 44, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (223, 3, 4, 42, 45, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (224, 3, 4, 43, 46, 0, 1, 3, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (225, 3, 4, 44, 47, 0, 2, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (226, 3, 4, 45, 48, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (227, 3, 4, 46, 49, 0, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (228, 3, 4, 47, 50, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (229, 3, 4, 48, 51, 0, 1, 2, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (230, 3, 4, 49, 52, 0, 2, 3, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (231, 3, 4, 50, 53, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (232, 3, 4, 51, 54, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (233, 3, 4, 52, 55, 0, 1, 3, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (234, 3, 4, 53, 56, 0, 2, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (235, 3, 4, 54, 57, 0, 1, 2, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (236, 3, 4, 55, 58, 0, 1, 3, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (237, 3, 4, 56, 59, 0, 2, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (238, 3, 4, 57, 60, 0, 1, 3, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (239, 3, 4, 58, 61, 0, 2, 2, 2, 1, 0); +INSERT INTO `player_levelupgains` VALUES (240, 3, 4, 59, 62, 0, 1, 3, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (242, 3, 1, 1, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (243, 3, 1, 2, 19, 0, 1, 0, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (244, 3, 1, 3, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (245, 3, 1, 4, 19, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (246, 3, 1, 5, 19, 0, 1, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (247, 3, 1, 6, 19, 0, 1, 0, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (248, 3, 1, 7, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (249, 3, 1, 8, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (250, 3, 1, 9, 19, 0, 1, 0, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (251, 3, 1, 10, 19, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (252, 3, 1, 11, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (253, 3, 1, 12, 19, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (254, 3, 1, 13, 20, 0, 2, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (255, 3, 1, 14, 21, 0, 1, 0, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (256, 3, 1, 15, 22, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (257, 3, 1, 16, 23, 0, 1, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (258, 3, 1, 17, 24, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (259, 3, 1, 18, 25, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (260, 3, 1, 19, 26, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (261, 3, 1, 20, 27, 0, 1, 0, 2, 1, 0); +INSERT INTO `player_levelupgains` VALUES (262, 3, 1, 21, 28, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (263, 3, 1, 22, 29, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (264, 3, 1, 23, 30, 0, 1, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (265, 3, 1, 24, 31, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (266, 3, 1, 25, 32, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (267, 3, 1, 26, 33, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (268, 3, 1, 27, 34, 0, 1, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (269, 3, 1, 28, 35, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (270, 3, 1, 29, 36, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (271, 3, 1, 30, 37, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (272, 3, 1, 31, 38, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (273, 3, 1, 32, 39, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (274, 3, 1, 33, 40, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (275, 3, 1, 34, 41, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (276, 3, 1, 35, 42, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (277, 3, 1, 36, 44, 0, 1, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (278, 3, 1, 37, 46, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (279, 3, 1, 38, 48, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (280, 3, 1, 39, 50, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (281, 3, 1, 40, 52, 0, 1, 2, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (282, 3, 1, 41, 54, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (283, 3, 1, 42, 56, 0, 2, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (284, 3, 1, 43, 58, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (285, 3, 1, 44, 60, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (286, 3, 1, 45, 62, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (287, 3, 1, 46, 64, 0, 2, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (288, 3, 1, 47, 66, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (289, 3, 1, 48, 68, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (290, 3, 1, 49, 70, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (291, 3, 1, 50, 72, 0, 2, 2, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (292, 3, 1, 51, 74, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (293, 3, 1, 52, 76, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (294, 3, 1, 53, 78, 0, 2, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (295, 3, 1, 54, 80, 0, 3, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (296, 3, 1, 55, 82, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (297, 3, 1, 56, 84, 0, 2, 2, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (298, 3, 1, 57, 86, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (299, 3, 1, 58, 88, 0, 3, 2, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (300, 3, 1, 59, 90, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (302, 7, 8, 1, 15, 25, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (303, 7, 8, 2, 6, 26, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (304, 7, 8, 3, 15, 27, 0, 1, 0, 3, 1); +INSERT INTO `player_levelupgains` VALUES (305, 7, 8, 4, 15, 58, 0, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (306, 7, 8, 5, 15, 29, 1, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (307, 7, 8, 6, 15, 30, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (308, 7, 8, 7, 15, 16, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (309, 7, 8, 8, 15, 47, 0, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (310, 7, 8, 9, 15, 33, 0, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (311, 7, 8, 10, 15, 34, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (312, 7, 8, 11, 15, 35, 0, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (313, 7, 8, 12, 15, 21, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (314, 7, 8, 13, 15, 37, 1, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (315, 7, 8, 14, 15, 38, 0, 1, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (316, 7, 8, 15, 15, 39, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (317, 7, 8, 16, 15, 25, 0, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (318, 7, 8, 17, 15, 56, 0, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (319, 7, 8, 18, 15, 27, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (320, 7, 8, 19, 15, 88, 0, 1, 0, 3, 2); +INSERT INTO `player_levelupgains` VALUES (321, 7, 8, 20, 15, 29, 1, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (322, 7, 8, 21, 15, 60, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (323, 7, 8, 22, 15, 31, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (324, 7, 8, 23, 16, 62, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (325, 7, 8, 24, 17, 33, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (326, 7, 8, 25, 18, 64, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (327, 7, 8, 26, 19, 35, 0, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (328, 7, 8, 27, 20, 36, 1, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (329, 7, 8, 28, 21, 66, 0, 1, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (330, 7, 8, 29, 22, 51, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (331, 7, 8, 30, 23, 36, 0, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (332, 7, 8, 31, 24, 66, 0, 0, 1, 3, 1); +INSERT INTO `player_levelupgains` VALUES (333, 7, 8, 32, 25, 81, 0, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (334, 7, 8, 33, 26, 36, 1, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (335, 7, 8, 34, 27, 51, 0, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (336, 7, 8, 35, 28, 51, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (337, 7, 8, 36, 29, 66, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (338, 7, 8, 37, 30, 36, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (339, 7, 8, 38, 31, 51, 1, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (340, 7, 8, 39, 32, 36, 0, 1, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (341, 7, 8, 40, 33, 51, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (342, 7, 8, 41, 34, 51, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (343, 7, 8, 42, 35, 51, 0, 0, 1, 3, 2); +INSERT INTO `player_levelupgains` VALUES (344, 7, 8, 43, 36, 81, 0, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (345, 7, 8, 44, 37, 51, 1, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (346, 7, 8, 45, 38, 51, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (347, 7, 8, 46, 39, 51, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (348, 7, 8, 47, 40, 51, 0, 0, 0, 3, 2); +INSERT INTO `player_levelupgains` VALUES (349, 7, 8, 48, 41, 51, 1, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (350, 7, 8, 49, 42, 36, 0, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (351, 7, 8, 50, 43, 51, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (352, 7, 8, 51, 44, 51, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (353, 7, 8, 52, 45, 81, 0, 1, 1, 3, 2); +INSERT INTO `player_levelupgains` VALUES (354, 7, 8, 53, 46, 51, 1, 0, 1, 3, 2); +INSERT INTO `player_levelupgains` VALUES (355, 7, 8, 54, 47, 51, 0, 0, 0, 2, 3); +INSERT INTO `player_levelupgains` VALUES (356, 7, 8, 55, 48, 51, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (357, 7, 8, 56, 49, 36, 0, 0, 0, 3, 2); +INSERT INTO `player_levelupgains` VALUES (358, 7, 8, 57, 50, 51, 1, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (359, 7, 8, 58, 51, 51, 0, 1, 0, 3, 3); +INSERT INTO `player_levelupgains` VALUES (360, 7, 8, 59, 52, 51, 0, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (362, 7, 4, 1, 17, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (363, 7, 4, 2, 17, 0, 0, 1, 0, 0, 1); +INSERT INTO `player_levelupgains` VALUES (364, 7, 4, 3, 17, 0, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (365, 7, 4, 4, 17, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (366, 7, 4, 5, 17, 0, 0, 1, 0, 0, 1); +INSERT INTO `player_levelupgains` VALUES (367, 7, 4, 6, 17, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (368, 7, 4, 7, 17, 0, 1, 1, 0, 0, 0); +INSERT INTO `player_levelupgains` VALUES (369, 7, 4, 8, 17, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (370, 7, 4, 9, 17, 0, 0, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (371, 7, 4, 10, 17, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (372, 7, 4, 11, 17, 0, 1, 1, 0, 0, 0); +INSERT INTO `player_levelupgains` VALUES (373, 7, 4, 12, 17, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (374, 7, 4, 13, 17, 0, 0, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (375, 7, 4, 14, 17, 0, 1, 2, 0, 1, 0); +INSERT INTO `player_levelupgains` VALUES (376, 7, 4, 15, 18, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (377, 7, 4, 16, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (378, 7, 4, 17, 20, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (379, 7, 4, 18, 21, 0, 1, 2, 0, 0, 1); +INSERT INTO `player_levelupgains` VALUES (380, 7, 4, 19, 22, 0, 0, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (381, 7, 4, 20, 23, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (382, 7, 4, 21, 24, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (383, 7, 4, 22, 25, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (384, 7, 4, 23, 26, 0, 1, 1, 0, 1, 0); +INSERT INTO `player_levelupgains` VALUES (385, 7, 4, 24, 27, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (386, 7, 4, 25, 28, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (387, 7, 4, 26, 29, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (388, 7, 4, 27, 30, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (389, 7, 4, 28, 31, 0, 0, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (390, 7, 4, 29, 32, 0, 1, 2, 0, 0, 1); +INSERT INTO `player_levelupgains` VALUES (391, 7, 4, 30, 33, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (392, 7, 4, 31, 34, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (393, 7, 4, 32, 35, 0, 1, 2, 1, 2, 0); +INSERT INTO `player_levelupgains` VALUES (394, 7, 4, 33, 36, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (395, 7, 4, 34, 37, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (396, 7, 4, 35, 38, 0, 2, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (397, 7, 4, 36, 39, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (398, 7, 4, 37, 40, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (399, 7, 4, 38, 41, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (400, 7, 4, 39, 42, 0, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (401, 7, 4, 40, 43, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (402, 7, 4, 41, 44, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (403, 7, 4, 42, 45, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (404, 7, 4, 43, 46, 0, 1, 3, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (405, 7, 4, 44, 47, 0, 2, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (406, 7, 4, 45, 48, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (407, 7, 4, 46, 49, 0, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (408, 7, 4, 47, 50, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (409, 7, 4, 48, 51, 0, 1, 2, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (410, 7, 4, 49, 52, 0, 2, 3, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (411, 7, 4, 50, 53, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (412, 7, 4, 51, 54, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (413, 7, 4, 52, 55, 0, 1, 3, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (414, 7, 4, 53, 56, 0, 2, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (415, 7, 4, 54, 57, 0, 1, 2, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (416, 7, 4, 55, 58, 0, 1, 3, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (417, 7, 4, 56, 59, 0, 2, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (418, 7, 4, 57, 60, 0, 1, 3, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (419, 7, 4, 58, 61, 0, 2, 2, 2, 1, 0); +INSERT INTO `player_levelupgains` VALUES (420, 7, 4, 59, 62, 0, 1, 3, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (422, 7, 9, 1, 15, 23, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (423, 7, 9, 2, 15, 24, 1, 1, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (424, 7, 9, 3, 15, 25, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (425, 7, 9, 4, 15, 26, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (426, 7, 9, 5, 15, 27, 0, 1, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (427, 7, 9, 6, 15, 58, 1, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (428, 7, 9, 7, 15, 29, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (429, 7, 9, 8, 15, 30, 0, 1, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (430, 7, 9, 9, 15, 31, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (431, 7, 9, 10, 15, 32, 0, 1, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (432, 7, 9, 11, 15, 33, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (433, 7, 9, 12, 15, 34, 1, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (434, 7, 9, 13, 15, 35, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (435, 7, 9, 14, 15, 36, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (436, 7, 9, 15, 15, 22, 1, 1, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (437, 7, 9, 16, 15, 38, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (438, 7, 9, 17, 16, 39, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (439, 7, 9, 18, 17, 40, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (440, 7, 9, 19, 18, 41, 0, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (441, 7, 9, 20, 19, 42, 0, 1, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (442, 7, 9, 21, 20, 43, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (443, 7, 9, 22, 21, 44, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (444, 7, 9, 23, 22, 75, 1, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (445, 7, 9, 24, 23, 46, 0, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (446, 7, 9, 25, 24, 47, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (447, 7, 9, 26, 25, 48, 1, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (448, 7, 9, 27, 26, 49, 0, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (449, 7, 9, 28, 27, 50, 1, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (450, 7, 9, 29, 28, 51, 0, 1, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (451, 7, 9, 30, 19, 36, 0, 0, 0, 1, 3); +INSERT INTO `player_levelupgains` VALUES (452, 7, 9, 31, 40, 51, 1, 1, 2, 2, 0); +INSERT INTO `player_levelupgains` VALUES (453, 7, 9, 32, 31, 51, 0, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (454, 7, 9, 33, 32, 51, 1, 1, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (455, 7, 9, 34, 33, 51, 0, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (456, 7, 9, 35, 34, 51, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (457, 7, 9, 36, 35, 81, 0, 1, 1, 3, 0); +INSERT INTO `player_levelupgains` VALUES (458, 7, 9, 37, 36, 51, 0, 0, 1, 1, 3); +INSERT INTO `player_levelupgains` VALUES (459, 7, 9, 38, 37, 51, 1, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (460, 7, 9, 39, 38, 51, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (461, 7, 9, 40, 39, 51, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (462, 7, 9, 41, 40, 51, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (463, 7, 9, 42, 41, 51, 1, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (464, 7, 9, 43, 42, 36, 0, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (465, 7, 9, 44, 43, 51, 1, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (466, 7, 9, 45, 44, 51, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (467, 7, 9, 46, 45, 51, 1, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (468, 7, 9, 47, 36, 51, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (469, 7, 9, 48, 47, 81, 1, 1, 1, 3, 2); +INSERT INTO `player_levelupgains` VALUES (470, 7, 9, 49, 58, 51, 0, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (471, 7, 9, 50, 49, 51, 1, 1, 1, 2, 3); +INSERT INTO `player_levelupgains` VALUES (472, 7, 9, 51, 30, 51, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (473, 7, 9, 52, 71, 51, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (474, 7, 9, 53, 52, 36, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (475, 7, 9, 54, 43, 51, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (476, 7, 9, 55, 64, 51, 1, 1, 2, 2, 2); +INSERT INTO `player_levelupgains` VALUES (477, 7, 9, 56, 35, 51, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (478, 7, 9, 57, 76, 51, 1, 1, 1, 2, 3); +INSERT INTO `player_levelupgains` VALUES (479, 7, 9, 58, 57, 81, 0, 0, 1, 3, 0); +INSERT INTO `player_levelupgains` VALUES (480, 7, 9, 59, 58, 51, 1, 1, 1, 2, 4); +INSERT INTO `player_levelupgains` VALUES (482, 7, 1, 1, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (483, 7, 1, 2, 19, 0, 1, 0, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (484, 7, 1, 3, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (485, 7, 1, 4, 19, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (486, 7, 1, 5, 19, 0, 1, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (487, 7, 1, 6, 19, 0, 1, 0, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (488, 7, 1, 7, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (489, 7, 1, 8, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (490, 7, 1, 9, 19, 0, 1, 0, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (491, 7, 1, 10, 19, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (492, 7, 1, 11, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (493, 7, 1, 12, 19, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (494, 7, 1, 13, 20, 0, 2, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (495, 7, 1, 14, 21, 0, 1, 0, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (496, 7, 1, 15, 22, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (497, 7, 1, 16, 23, 0, 1, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (498, 7, 1, 17, 24, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (499, 7, 1, 18, 25, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (500, 7, 1, 19, 26, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (501, 7, 1, 20, 27, 0, 1, 0, 2, 1, 0); +INSERT INTO `player_levelupgains` VALUES (502, 7, 1, 21, 28, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (503, 7, 1, 22, 29, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (504, 7, 1, 23, 30, 0, 1, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (505, 7, 1, 24, 31, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (506, 7, 1, 25, 32, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (507, 7, 1, 26, 33, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (508, 7, 1, 27, 34, 0, 1, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (509, 7, 1, 28, 35, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (510, 7, 1, 29, 36, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (511, 7, 1, 30, 37, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (512, 7, 1, 31, 38, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (513, 7, 1, 32, 39, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (514, 7, 1, 33, 40, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (515, 7, 1, 34, 41, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (516, 7, 1, 35, 42, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (517, 7, 1, 36, 79, 0, 1, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (518, 7, 1, 37, 11, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (519, 7, 1, 38, 48, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (520, 7, 1, 39, 50, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (521, 7, 1, 40, 52, 0, 1, 2, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (522, 7, 1, 41, 54, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (523, 7, 1, 42, 56, 0, 2, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (524, 7, 1, 43, 58, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (525, 7, 1, 44, 60, 0, 2, 1, 2, 2, 1); +INSERT INTO `player_levelupgains` VALUES (526, 7, 1, 45, 62, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (527, 7, 1, 46, 64, 0, 2, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (528, 7, 1, 47, 66, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (529, 7, 1, 48, 68, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (530, 7, 1, 49, 70, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (531, 7, 1, 50, 72, 0, 2, 2, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (532, 7, 1, 51, 74, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (533, 7, 1, 52, 76, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (534, 7, 1, 53, 78, 0, 2, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (535, 7, 1, 54, 80, 0, 3, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (536, 7, 1, 55, 82, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (537, 7, 1, 56, 84, 0, 2, 2, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (538, 7, 1, 57, 86, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (539, 7, 1, 58, 88, 0, 3, 2, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (540, 7, 1, 59, 90, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (542, 1, 8, 1, 15, 25, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (543, 1, 8, 2, 15, 26, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (544, 1, 8, 3, 15, 27, 0, 1, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (545, 1, 8, 4, 15, 28, 0, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (546, 1, 8, 5, 15, 29, 1, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (547, 1, 8, 6, 15, 30, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (548, 1, 8, 7, 15, 16, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (549, 1, 8, 8, 15, 47, 0, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (550, 1, 8, 9, 15, 33, 0, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (551, 1, 8, 10, 15, 34, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (552, 1, 8, 11, 15, 35, 0, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (553, 1, 8, 12, 15, 36, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (554, 1, 8, 13, 15, 37, 1, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (555, 1, 8, 14, 15, 38, 0, 1, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (556, 1, 8, 15, 15, 39, 0, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (557, 1, 8, 16, 15, 25, 0, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (558, 1, 8, 17, 15, 56, 0, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (559, 1, 8, 18, 15, 27, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (560, 1, 8, 19, 15, 58, 0, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (561, 1, 8, 20, 15, 29, 1, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (562, 1, 8, 21, 15, 60, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (563, 1, 8, 22, 15, 31, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (564, 1, 8, 23, 16, 62, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (565, 1, 8, 24, 17, 33, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (566, 1, 8, 25, 18, 64, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (567, 1, 8, 26, 19, 50, 0, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (568, 1, 8, 27, 20, 36, 1, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (569, 1, 8, 28, 21, 66, 0, 1, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (570, 1, 8, 29, 22, 51, 0, 0, 0, 2, 3); +INSERT INTO `player_levelupgains` VALUES (571, 1, 8, 30, 23, 36, 0, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (572, 1, 8, 31, 24, 66, 0, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (573, 1, 8, 32, 25, 51, 0, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (574, 1, 8, 33, 26, 36, 1, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (575, 1, 8, 34, 27, 51, 0, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (576, 1, 8, 35, 28, 51, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (577, 1, 8, 36, 29, 66, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (578, 1, 8, 37, 30, 51, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (579, 1, 8, 38, 31, 51, 1, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (580, 1, 8, 39, 32, 36, 0, 1, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (581, 1, 8, 40, 33, 51, 0, 0, 1, 2, 3); +INSERT INTO `player_levelupgains` VALUES (582, 1, 8, 41, 34, 51, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (583, 1, 8, 42, 35, 51, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (584, 1, 8, 43, 36, 51, 0, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (585, 1, 8, 44, 37, 51, 1, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (586, 1, 8, 45, 38, 51, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (587, 1, 8, 46, 39, 51, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (588, 1, 8, 47, 40, 66, 0, 0, 0, 3, 2); +INSERT INTO `player_levelupgains` VALUES (589, 1, 8, 48, 41, 51, 1, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (590, 1, 8, 49, 42, 36, 0, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (591, 1, 8, 50, 43, 51, 0, 0, 1, 2, 3); +INSERT INTO `player_levelupgains` VALUES (592, 1, 8, 51, 44, 51, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (593, 1, 8, 52, 45, 51, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (594, 1, 8, 53, 46, 51, 1, 0, 1, 3, 2); +INSERT INTO `player_levelupgains` VALUES (595, 1, 8, 54, 47, 51, 0, 0, 0, 2, 3); +INSERT INTO `player_levelupgains` VALUES (596, 1, 8, 55, 48, 51, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (597, 1, 8, 56, 49, 51, 0, 0, 0, 3, 2); +INSERT INTO `player_levelupgains` VALUES (598, 1, 8, 57, 50, 51, 1, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (599, 1, 8, 58, 51, 51, 0, 1, 0, 3, 3); +INSERT INTO `player_levelupgains` VALUES (600, 1, 8, 59, 52, 51, 0, 0, 1, 2, 3); +INSERT INTO `player_levelupgains` VALUES (602, 1, 2, 1, 18, 19, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (603, 1, 2, 2, 18, 20, 1, 0, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (604, 1, 2, 3, 18, 21, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (605, 1, 2, 4, 18, 22, 1, 0, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (606, 1, 2, 5, 18, 23, 1, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (607, 1, 2, 6, 18, 24, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (608, 1, 2, 7, 18, 25, 1, 1, 0, 0, 0); +INSERT INTO `player_levelupgains` VALUES (609, 1, 2, 8, 18, 26, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (610, 1, 2, 9, 18, 27, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (611, 1, 2, 10, 18, 28, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (612, 1, 2, 11, 18, 29, 1, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (613, 1, 2, 12, 18, 30, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (614, 1, 2, 13, 18, 31, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (615, 1, 2, 14, 19, 32, 1, 1, 2, 1, 0); +INSERT INTO `player_levelupgains` VALUES (616, 1, 2, 15, 20, 33, 2, 0, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (617, 1, 2, 16, 21, 34, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (618, 1, 2, 17, 22, 35, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (619, 1, 2, 18, 23, 36, 1, 0, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (620, 1, 2, 19, 24, 37, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (621, 1, 2, 20, 25, 38, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (622, 1, 2, 21, 26, 39, 2, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (623, 1, 2, 22, 27, 40, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (624, 1, 2, 23, 28, 41, 1, 1, 2, 1, 0); +INSERT INTO `player_levelupgains` VALUES (625, 1, 2, 24, 29, 42, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (626, 1, 2, 25, 30, 42, 2, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (627, 1, 2, 26, 31, 42, 1, 1, 1, 0, 2); +INSERT INTO `player_levelupgains` VALUES (628, 1, 2, 27, 32, 42, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (629, 1, 2, 28, 33, 42, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (630, 1, 2, 29, 34, 42, 1, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (631, 1, 2, 30, 35, 42, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (632, 1, 2, 31, 36, 42, 2, 0, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (633, 1, 2, 32, 37, 42, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (634, 1, 2, 33, 38, 42, 2, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (635, 1, 2, 34, 39, 42, 1, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (636, 1, 2, 35, 40, 42, 2, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (637, 1, 2, 36, 41, 42, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (638, 1, 2, 37, 42, 42, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (639, 1, 2, 38, 43, 42, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (640, 1, 2, 39, 44, 42, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (641, 1, 2, 40, 45, 42, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (642, 1, 2, 41, 46, 42, 2, 0, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (643, 1, 2, 42, 47, 42, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (644, 1, 2, 43, 48, 42, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (645, 1, 2, 44, 49, 42, 2, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (646, 1, 2, 45, 50, 42, 1, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (647, 1, 2, 46, 51, 42, 2, 1, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (648, 1, 2, 47, 52, 42, 2, 1, 2, 1, 2); +INSERT INTO `player_levelupgains` VALUES (649, 1, 2, 48, 53, 42, 1, 1, 2, 1, 2); +INSERT INTO `player_levelupgains` VALUES (650, 1, 2, 49, 54, 42, 2, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (651, 1, 2, 50, 55, 42, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (652, 1, 2, 51, 56, 42, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (653, 1, 2, 52, 57, 42, 2, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (654, 1, 2, 53, 58, 42, 1, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (655, 1, 2, 54, 59, 42, 2, 1, 2, 1, 2); +INSERT INTO `player_levelupgains` VALUES (656, 1, 2, 55, 60, 42, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (657, 1, 2, 56, 61, 42, 2, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (658, 1, 2, 57, 62, 42, 2, 1, 2, 2, 1); +INSERT INTO `player_levelupgains` VALUES (659, 1, 2, 58, 63, 42, 2, 1, 2, 1, 2); +INSERT INTO `player_levelupgains` VALUES (660, 1, 2, 59, 64, 42, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (662, 1, 5, 1, 15, 24, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (663, 1, 5, 2, 15, 25, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (664, 1, 5, 3, 15, 26, 1, 1, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (665, 1, 5, 4, 15, 27, 0, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (666, 1, 5, 5, 15, 28, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (667, 1, 5, 6, 15, 29, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (668, 1, 5, 7, 15, 30, 0, 1, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (669, 1, 5, 8, 15, 31, 0, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (670, 1, 5, 9, 15, 47, 1, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (671, 1, 5, 10, 15, 18, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (672, 1, 5, 11, 15, 34, 0, 1, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (673, 1, 5, 12, 15, 35, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (674, 1, 5, 13, 15, 36, 0, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (675, 1, 5, 14, 15, 37, 1, 0, 0, 1, 3); +INSERT INTO `player_levelupgains` VALUES (676, 1, 5, 15, 15, 38, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (677, 1, 5, 16, 15, 54, 0, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (678, 1, 5, 17, 15, 25, 0, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (679, 1, 5, 18, 15, 41, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (680, 1, 5, 19, 15, 42, 1, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (681, 1, 5, 20, 15, 43, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (682, 1, 5, 21, 16, 59, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (683, 1, 5, 22, 17, 30, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (684, 1, 5, 23, 18, 61, 1, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (685, 1, 5, 24, 19, 32, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (686, 1, 5, 25, 20, 63, 0, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (687, 1, 5, 26, 21, 34, 0, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (688, 1, 5, 27, 22, 65, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (689, 1, 5, 28, 23, 36, 1, 1, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (690, 1, 5, 29, 24, 52, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (691, 1, 5, 30, 25, 68, 0, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (692, 1, 5, 31, 26, 39, 0, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (693, 1, 5, 32, 27, 69, 1, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (694, 1, 5, 33, 28, 54, 0, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (695, 1, 5, 34, 29, 39, 0, 1, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (696, 1, 5, 35, 30, 54, 1, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (697, 1, 5, 36, 31, 69, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (698, 1, 5, 37, 32, 54, 0, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (699, 1, 5, 38, 33, 39, 0, 0, 1, 1, 3); +INSERT INTO `player_levelupgains` VALUES (700, 1, 5, 39, 34, 54, 1, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (701, 1, 5, 40, 35, 69, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (702, 1, 5, 41, 36, 54, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (703, 1, 5, 42, 37, 54, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (704, 1, 5, 43, 38, 54, 1, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (705, 1, 5, 44, 39, 54, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (706, 1, 5, 45, 40, 54, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (707, 1, 5, 46, 41, 54, 1, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (708, 1, 5, 47, 42, 54, 0, 1, 1, 2, 3); +INSERT INTO `player_levelupgains` VALUES (709, 1, 5, 48, 43, 54, 0, 0, 1, 2, 3); +INSERT INTO `player_levelupgains` VALUES (710, 1, 5, 49, 44, 54, 1, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (711, 1, 5, 50, 45, 54, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (712, 1, 5, 51, 46, 54, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (713, 1, 5, 52, 47, 54, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (714, 1, 5, 53, 48, 54, 0, 0, 1, 2, 3); +INSERT INTO `player_levelupgains` VALUES (715, 1, 5, 54, 49, 54, 0, 1, 0, 3, 2); +INSERT INTO `player_levelupgains` VALUES (716, 1, 5, 55, 50, 54, 1, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (717, 1, 5, 56, 51, 54, 0, 1, 1, 2, 3); +INSERT INTO `player_levelupgains` VALUES (718, 1, 5, 57, 52, 54, 0, 0, 1, 2, 3); +INSERT INTO `player_levelupgains` VALUES (719, 1, 5, 58, 53, 54, 1, 1, 0, 3, 3); +INSERT INTO `player_levelupgains` VALUES (720, 1, 5, 59, 54, 54, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (722, 1, 4, 1, 17, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (723, 1, 4, 2, 17, 0, 0, 1, 0, 0, 1); +INSERT INTO `player_levelupgains` VALUES (724, 1, 4, 3, 17, 0, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (725, 1, 4, 4, 17, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (726, 1, 4, 5, 17, 0, 0, 1, 0, 0, 1); +INSERT INTO `player_levelupgains` VALUES (727, 1, 4, 6, 17, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (728, 1, 4, 7, 17, 0, 1, 1, 0, 0, 0); +INSERT INTO `player_levelupgains` VALUES (729, 1, 4, 8, 17, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (730, 1, 4, 9, 17, 0, 0, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (731, 1, 4, 10, 17, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (732, 1, 4, 11, 17, 0, 1, 1, 0, 0, 0); +INSERT INTO `player_levelupgains` VALUES (733, 1, 4, 12, 17, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (734, 1, 4, 13, 17, 0, 0, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (735, 1, 4, 14, 17, 0, 1, 2, 0, 1, 0); +INSERT INTO `player_levelupgains` VALUES (736, 1, 4, 15, 18, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (737, 1, 4, 16, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (738, 1, 4, 17, 20, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (739, 1, 4, 18, 21, 0, 1, 2, 0, 0, 1); +INSERT INTO `player_levelupgains` VALUES (740, 1, 4, 19, 22, 0, 0, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (741, 1, 4, 20, 23, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (742, 1, 4, 21, 24, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (743, 1, 4, 22, 25, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (744, 1, 4, 23, 26, 0, 1, 1, 0, 1, 0); +INSERT INTO `player_levelupgains` VALUES (745, 1, 4, 24, 27, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (746, 1, 4, 25, 28, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (747, 1, 4, 26, 29, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (748, 1, 4, 27, 30, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (749, 1, 4, 28, 31, 0, 0, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (750, 1, 4, 29, 32, 0, 1, 2, 0, 0, 1); +INSERT INTO `player_levelupgains` VALUES (751, 1, 4, 30, 33, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (752, 1, 4, 31, 34, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (753, 1, 4, 32, 35, 0, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (754, 1, 4, 33, 36, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (755, 1, 4, 34, 37, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (756, 1, 4, 35, 38, 0, 2, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (757, 1, 4, 36, 39, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (758, 1, 4, 37, 40, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (759, 1, 4, 38, 41, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (760, 1, 4, 39, 42, 0, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (761, 1, 4, 40, 43, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (762, 1, 4, 41, 44, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (763, 1, 4, 42, 45, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (764, 1, 4, 43, 46, 0, 1, 3, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (765, 1, 4, 44, 47, 0, 2, 2, 1, 0, 2); +INSERT INTO `player_levelupgains` VALUES (766, 1, 4, 45, 48, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (767, 1, 4, 46, 49, 0, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (768, 1, 4, 47, 50, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (769, 1, 4, 48, 51, 0, 1, 2, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (770, 1, 4, 49, 52, 0, 2, 3, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (771, 1, 4, 50, 53, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (772, 1, 4, 51, 54, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (773, 1, 4, 52, 55, 0, 1, 3, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (774, 1, 4, 53, 56, 0, 2, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (775, 1, 4, 54, 57, 0, 1, 2, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (776, 1, 4, 55, 58, 0, 1, 3, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (777, 1, 4, 56, 59, 0, 2, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (778, 1, 4, 57, 60, 0, 1, 3, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (779, 1, 4, 58, 61, 0, 2, 2, 2, 1, 0); +INSERT INTO `player_levelupgains` VALUES (780, 1, 4, 59, 62, 0, 1, 3, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (782, 1, 9, 1, 15, 23, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (783, 1, 9, 2, 15, 24, 1, 1, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (784, 1, 9, 3, 15, 25, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (785, 1, 9, 4, 15, 26, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (786, 1, 9, 5, 15, 27, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (787, 1, 9, 6, 15, 28, 1, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (788, 1, 9, 7, 15, 29, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (789, 1, 9, 8, 15, 30, 0, 1, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (790, 1, 9, 9, 15, 31, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (791, 1, 9, 10, 15, 32, 0, 1, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (792, 1, 9, 11, 15, 33, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (793, 1, 9, 12, 15, 34, 1, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (794, 1, 9, 13, 15, 35, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (795, 1, 9, 14, 15, 36, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (796, 1, 9, 15, 15, 37, 1, 1, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (797, 1, 9, 16, 15, 38, 0, 0, 1, 2, 3); +INSERT INTO `player_levelupgains` VALUES (798, 1, 9, 17, 16, 39, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (799, 1, 9, 18, 17, 40, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (800, 1, 9, 19, 18, 41, 0, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (801, 1, 9, 20, 19, 42, 0, 1, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (802, 1, 9, 21, 20, 43, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (803, 1, 9, 22, 21, 44, 0, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (804, 1, 9, 23, 22, 45, 1, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (805, 1, 9, 24, 23, 46, 0, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (806, 1, 9, 25, 24, 47, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (807, 1, 9, 26, 25, 48, 1, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (808, 1, 9, 27, 26, 49, 0, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (809, 1, 9, 28, 27, 50, 1, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (810, 1, 9, 29, 28, 51, 0, 1, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (811, 1, 9, 30, 29, 51, 0, 0, 1, 1, 3); +INSERT INTO `player_levelupgains` VALUES (812, 1, 9, 31, 30, 51, 1, 1, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (813, 1, 9, 32, 31, 51, 0, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (814, 1, 9, 33, 32, 51, 1, 1, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (815, 1, 9, 34, 33, 51, 0, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (816, 1, 9, 35, 34, 51, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (817, 1, 9, 36, 35, 51, 0, 1, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (818, 1, 9, 37, 36, 51, 0, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (819, 1, 9, 38, 37, 51, 1, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (820, 1, 9, 39, 38, 51, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (821, 1, 9, 40, 39, 51, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (822, 1, 9, 41, 40, 51, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (823, 1, 9, 42, 31, 51, 1, 1, 0, 1, 4); +INSERT INTO `player_levelupgains` VALUES (824, 1, 9, 43, 52, 51, 0, 0, 2, 2, 0); +INSERT INTO `player_levelupgains` VALUES (825, 1, 9, 44, 43, 51, 1, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (826, 1, 9, 45, 34, 51, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (827, 1, 9, 46, 55, 51, 1, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (828, 1, 9, 47, 46, 51, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (829, 1, 9, 48, 47, 51, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (830, 1, 9, 49, 48, 51, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (831, 1, 9, 50, 49, 51, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (832, 1, 9, 51, 50, 51, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (833, 1, 9, 52, 41, 51, 1, 1, 1, 2, 3); +INSERT INTO `player_levelupgains` VALUES (834, 1, 9, 53, 52, 51, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (835, 1, 9, 54, 63, 51, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (836, 1, 9, 55, 54, 51, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (837, 1, 9, 56, 55, 51, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (838, 1, 9, 57, 56, 51, 1, 1, 1, 2, 3); +INSERT INTO `player_levelupgains` VALUES (839, 1, 9, 58, 57, 51, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (840, 1, 9, 59, 58, 51, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (842, 1, 1, 1, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (843, 1, 1, 2, 19, 0, 1, 0, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (844, 1, 1, 3, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (845, 1, 1, 4, 19, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (846, 1, 1, 5, 19, 0, 1, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (847, 1, 1, 6, 19, 0, 1, 0, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (848, 1, 1, 7, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (849, 1, 1, 8, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (850, 1, 1, 9, 19, 0, 1, 0, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (851, 1, 1, 10, 19, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (852, 1, 1, 11, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (853, 1, 1, 12, 19, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (854, 1, 1, 13, 20, 0, 2, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (855, 1, 1, 14, 21, 0, 1, 0, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (856, 1, 1, 15, 22, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (857, 1, 1, 16, 23, 0, 1, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (858, 1, 1, 17, 24, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (859, 1, 1, 18, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `player_levelupgains` VALUES (860, 1, 1, 19, 51, 0, 3, 2, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (861, 1, 1, 20, 27, 0, 1, 0, 2, 1, 0); +INSERT INTO `player_levelupgains` VALUES (862, 1, 1, 21, 28, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (863, 1, 1, 22, 29, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (864, 1, 1, 23, 30, 0, 1, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (865, 1, 1, 24, 31, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (866, 1, 1, 25, 32, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (867, 1, 1, 26, 33, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (868, 1, 1, 27, 34, 0, 1, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (869, 1, 1, 28, 35, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (870, 1, 1, 29, 36, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (871, 1, 1, 30, 37, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (872, 1, 1, 31, 38, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (873, 1, 1, 32, 39, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (874, 1, 1, 33, 40, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (875, 1, 1, 34, 41, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (876, 1, 1, 35, 42, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (877, 1, 1, 36, 44, 0, 1, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (878, 1, 1, 37, 46, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (879, 1, 1, 38, 48, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (880, 1, 1, 39, 50, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (881, 1, 1, 40, 52, 0, 1, 2, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (882, 1, 1, 41, 54, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (883, 1, 1, 42, 56, 0, 2, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (884, 1, 1, 43, 58, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (885, 1, 1, 44, 60, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (886, 1, 1, 45, 62, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (887, 1, 1, 46, 64, 0, 2, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (888, 1, 1, 47, 66, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (889, 1, 1, 48, 68, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (890, 1, 1, 49, 70, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (891, 1, 1, 50, 72, 0, 2, 2, 2, 0, 2); +INSERT INTO `player_levelupgains` VALUES (892, 1, 1, 51, 74, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (893, 1, 1, 52, 76, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (894, 1, 1, 53, 78, 0, 2, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (895, 1, 1, 54, 80, 0, 3, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (896, 1, 1, 55, 82, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (897, 1, 1, 56, 84, 0, 2, 2, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (898, 1, 1, 57, 86, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (899, 1, 1, 58, 88, 0, 3, 2, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (900, 1, 1, 59, 90, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (902, 4, 11, 1, 8, 22, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (903, 4, 11, 2, 17, 23, 0, 1, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (904, 4, 11, 3, 17, 24, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (905, 4, 11, 4, 17, 25, 0, 1, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (906, 4, 11, 5, 17, 26, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (907, 4, 11, 6, 17, 27, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (908, 4, 11, 7, 17, 13, 1, 0, 0, 0, 1); +INSERT INTO `player_levelupgains` VALUES (909, 4, 11, 8, 17, 29, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (910, 4, 11, 9, 17, 30, 1, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (911, 4, 11, 10, 17, 31, 0, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (912, 4, 11, 11, 17, 32, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (913, 4, 11, 12, 17, 33, 0, 1, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (914, 4, 11, 13, 17, 34, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (915, 4, 11, 14, 17, 50, 1, 1, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (916, 4, 11, 15, 17, 36, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (917, 4, 11, 16, 17, 37, 1, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (918, 4, 11, 17, 18, 38, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (919, 4, 11, 18, 19, 39, 1, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (920, 4, 11, 19, 20, 40, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (921, 4, 11, 20, 21, 41, 0, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (922, 4, 11, 21, 22, 27, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (923, 4, 11, 22, 23, 43, 1, 1, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (924, 4, 11, 23, 24, 59, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (925, 4, 11, 24, 25, 45, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (926, 4, 11, 25, 26, 45, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (927, 4, 11, 26, 27, 30, 0, 1, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (928, 4, 11, 27, 28, 45, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (929, 4, 11, 28, 29, 60, 1, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (930, 4, 11, 29, 30, 45, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (931, 4, 11, 30, 31, 30, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (932, 4, 11, 31, 32, 60, 1, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (933, 4, 11, 32, 33, 45, 1, 1, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (934, 4, 11, 33, 34, 30, 0, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (935, 4, 11, 34, 35, 60, 1, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (936, 4, 11, 35, 36, 30, 1, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (937, 4, 11, 36, 37, 45, 1, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (938, 4, 11, 37, 38, 60, 1, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (939, 4, 11, 38, 39, 30, 0, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (940, 4, 11, 39, 40, 60, 1, 1, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (941, 4, 11, 40, 41, 30, 1, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (942, 4, 11, 41, 42, 60, 1, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (943, 4, 11, 42, 43, 30, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (944, 4, 11, 43, 44, 60, 1, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (945, 4, 11, 44, 45, 30, 0, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (946, 4, 11, 45, 46, 60, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (947, 4, 11, 46, 47, 30, 1, 0, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (948, 4, 11, 47, 48, 45, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (949, 4, 11, 48, 49, 60, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (950, 4, 11, 49, 50, 30, 1, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (951, 4, 11, 50, 51, 45, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (952, 4, 11, 51, 52, 60, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (953, 4, 11, 52, 53, 30, 1, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (954, 4, 11, 53, 54, 45, 1, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (955, 4, 11, 54, 55, 45, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (956, 4, 11, 55, 56, 45, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (957, 4, 11, 56, 57, 45, 1, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (958, 4, 11, 57, 58, 45, 1, 1, 2, 2, 2); +INSERT INTO `player_levelupgains` VALUES (959, 4, 11, 58, 59, 45, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (960, 4, 11, 59, 60, 45, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (962, 4, 3, 1, 17, 20, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (963, 4, 3, 2, 17, 21, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (964, 4, 3, 3, 17, 22, 0, 2, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (965, 4, 3, 4, 17, 23, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (966, 4, 3, 5, 17, 24, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (967, 4, 3, 6, 17, 25, 0, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (968, 4, 3, 7, 17, 26, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (969, 4, 3, 8, 17, 27, 0, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (970, 4, 3, 9, 17, 28, 1, 1, 0, 1, 0); +INSERT INTO `player_levelupgains` VALUES (971, 4, 3, 10, 17, 29, 0, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (972, 4, 3, 11, 17, 30, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (973, 4, 3, 12, 17, 31, 0, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (974, 4, 3, 13, 18, 32, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (975, 4, 3, 14, 19, 33, 0, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (976, 4, 3, 15, 20, 34, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (977, 4, 3, 16, 21, 35, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (978, 4, 3, 17, 22, 36, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (979, 4, 3, 18, 23, 37, 0, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (980, 4, 3, 19, 24, 38, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (981, 4, 3, 20, 25, 39, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (982, 4, 3, 21, 26, 40, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (983, 4, 3, 22, 27, 41, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (984, 4, 3, 23, 28, 42, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (985, 4, 3, 24, 29, 43, 0, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (986, 4, 3, 25, 30, 44, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (987, 4, 3, 26, 31, 45, 0, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (988, 4, 3, 27, 32, 45, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (989, 4, 3, 28, 33, 45, 0, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (990, 4, 3, 29, 34, 45, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (991, 4, 3, 30, 35, 45, 0, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (992, 4, 3, 31, 36, 45, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (993, 4, 3, 32, 37, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (994, 4, 3, 33, 38, 45, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (995, 4, 3, 34, 39, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (996, 4, 3, 35, 40, 45, 1, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (997, 4, 3, 36, 41, 45, 0, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (998, 4, 3, 37, 42, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (999, 4, 3, 38, 43, 45, 0, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1000, 4, 3, 39, 44, 45, 1, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1001, 4, 3, 40, 45, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1002, 4, 3, 41, 46, 45, 0, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1003, 4, 3, 42, 47, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1004, 4, 3, 43, 48, 45, 1, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1005, 4, 3, 44, 49, 45, 0, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1006, 4, 3, 45, 50, 45, 1, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1007, 4, 3, 46, 51, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1008, 4, 3, 47, 52, 45, 1, 3, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1009, 4, 3, 48, 53, 45, 0, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1010, 4, 3, 49, 54, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1011, 4, 3, 50, 55, 45, 1, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1012, 4, 3, 51, 56, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1013, 4, 3, 52, 57, 45, 0, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1014, 4, 3, 53, 58, 45, 1, 3, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1015, 4, 3, 54, 59, 45, 1, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1016, 4, 3, 55, 60, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1017, 4, 3, 56, 61, 45, 1, 3, 2, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1018, 4, 3, 57, 62, 45, 0, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1019, 4, 3, 58, 63, 45, 1, 3, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1020, 4, 3, 59, 64, 45, 1, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1022, 4, 5, 1, 15, 24, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1023, 4, 5, 2, 6, 25, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1024, 4, 5, 3, 15, 26, 1, 1, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1025, 4, 5, 4, 15, 27, 0, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1026, 4, 5, 5, 15, 28, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1027, 4, 5, 6, 15, 29, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1028, 4, 5, 7, 15, 30, 0, 1, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1029, 4, 5, 8, 15, 31, 0, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1030, 4, 5, 9, 15, 47, 1, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1031, 4, 5, 10, 15, 18, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1032, 4, 5, 11, 15, 34, 0, 1, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1033, 4, 5, 12, 15, 35, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1034, 4, 5, 13, 15, 36, 0, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1035, 4, 5, 14, 15, 37, 1, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1036, 4, 5, 15, 15, 38, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1037, 4, 5, 16, 15, 54, 0, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1038, 4, 5, 17, 15, 25, 0, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1039, 4, 5, 18, 15, 41, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1040, 4, 5, 19, 15, 42, 1, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1041, 4, 5, 20, 15, 43, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1042, 4, 5, 21, 16, 59, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1043, 4, 5, 22, 17, 30, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1044, 4, 5, 23, 18, 61, 1, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1045, 4, 5, 24, 19, 32, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1046, 4, 5, 25, 20, 63, 0, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1047, 4, 5, 26, 21, 34, 0, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1048, 4, 5, 27, 22, 65, 0, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1049, 4, 5, 28, 23, 36, 1, 1, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1050, 4, 5, 29, 24, 52, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1051, 4, 5, 30, 25, 68, 0, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1052, 4, 5, 31, 26, 39, 0, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1053, 4, 5, 32, 27, 69, 1, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1054, 4, 5, 33, 28, 54, 0, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1055, 4, 5, 34, 29, 39, 0, 1, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1056, 4, 5, 35, 30, 54, 1, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1057, 4, 5, 36, 31, 69, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1058, 4, 5, 37, 32, 54, 0, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1059, 4, 5, 38, 33, 39, 0, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1060, 4, 5, 39, 34, 54, 1, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1061, 4, 5, 40, 35, 69, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1062, 4, 5, 41, 36, 54, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1063, 4, 5, 42, 37, 54, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1064, 4, 5, 43, 38, 54, 1, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1065, 4, 5, 44, 39, 54, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1066, 4, 5, 45, 40, 54, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1067, 4, 5, 46, 41, 54, 1, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1068, 4, 5, 47, 42, 54, 0, 1, 1, 2, 3); +INSERT INTO `player_levelupgains` VALUES (1069, 4, 5, 48, 43, 54, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1070, 4, 5, 49, 44, 54, 1, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1071, 4, 5, 50, 45, 54, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1072, 4, 5, 51, 46, 54, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1073, 4, 5, 52, 47, 54, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1074, 4, 5, 53, 48, 54, 0, 0, 1, 2, 3); +INSERT INTO `player_levelupgains` VALUES (1075, 4, 5, 54, 49, 54, 0, 1, 0, 3, 2); +INSERT INTO `player_levelupgains` VALUES (1076, 4, 5, 55, 50, 54, 1, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1077, 4, 5, 56, 51, 54, 0, 1, 1, 2, 3); +INSERT INTO `player_levelupgains` VALUES (1078, 4, 5, 57, 52, 54, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1079, 4, 5, 58, 53, 54, 1, 1, 0, 3, 3); +INSERT INTO `player_levelupgains` VALUES (1080, 4, 5, 59, 54, 54, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1082, 4, 4, 1, 17, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1083, 4, 4, 2, 17, 0, 0, 1, 0, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1084, 4, 4, 3, 17, 0, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1085, 4, 4, 4, 17, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1086, 4, 4, 5, 17, 0, 0, 1, 0, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1087, 4, 4, 6, 17, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1088, 4, 4, 7, 17, 0, 1, 1, 0, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1089, 4, 4, 8, 17, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1090, 4, 4, 9, 17, 0, 0, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1091, 4, 4, 10, 17, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1092, 4, 4, 11, 17, 0, 1, 1, 0, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1093, 4, 4, 12, 17, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1094, 4, 4, 13, 17, 0, 0, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1095, 4, 4, 14, 17, 0, 1, 2, 0, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1096, 4, 4, 15, 18, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1097, 4, 4, 16, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1098, 4, 4, 17, 20, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1099, 4, 4, 18, 21, 0, 1, 2, 0, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1100, 4, 4, 19, 22, 0, 0, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1101, 4, 4, 20, 23, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1102, 4, 4, 21, 24, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1103, 4, 4, 22, 25, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1104, 4, 4, 23, 26, 0, 1, 1, 0, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1105, 4, 4, 24, 27, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1106, 4, 4, 25, 28, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1107, 4, 4, 26, 29, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1108, 4, 4, 27, 30, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1109, 4, 4, 28, 31, 0, 0, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1110, 4, 4, 29, 32, 0, 1, 2, 0, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1111, 4, 4, 30, 33, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1112, 4, 4, 31, 34, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1113, 4, 4, 32, 35, 0, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1114, 4, 4, 33, 36, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1115, 4, 4, 34, 37, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1116, 4, 4, 35, 38, 0, 2, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1117, 4, 4, 36, 39, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1118, 4, 4, 37, 40, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1119, 4, 4, 38, 41, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1120, 4, 4, 39, 42, 0, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1121, 4, 4, 40, 43, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1122, 4, 4, 41, 44, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1123, 4, 4, 42, 45, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1124, 4, 4, 43, 46, 0, 1, 3, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1125, 4, 4, 44, 47, 0, 2, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1126, 4, 4, 45, 48, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1127, 4, 4, 46, 49, 0, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1128, 4, 4, 47, 50, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1129, 4, 4, 48, 51, 0, 1, 2, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1130, 4, 4, 49, 52, 0, 2, 3, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1131, 4, 4, 50, 53, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1132, 4, 4, 51, 54, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1133, 4, 4, 52, 55, 0, 1, 3, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1134, 4, 4, 53, 56, 0, 2, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1135, 4, 4, 54, 57, 0, 1, 2, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1136, 4, 4, 55, 58, 0, 1, 3, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1137, 4, 4, 56, 59, 0, 2, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1138, 4, 4, 57, 60, 0, 1, 3, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1139, 4, 4, 58, 61, 0, 2, 2, 2, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1140, 4, 4, 59, 62, 0, 1, 3, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1142, 4, 1, 1, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1143, 4, 1, 2, 19, 0, 1, 0, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1144, 4, 1, 3, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1145, 4, 1, 4, 19, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1146, 4, 1, 5, 19, 0, 1, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1147, 4, 1, 6, 19, 0, 1, 0, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1148, 4, 1, 7, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1149, 4, 1, 8, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1150, 4, 1, 9, 19, 0, 1, 0, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1151, 4, 1, 10, 19, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1152, 4, 1, 11, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1153, 4, 1, 12, 19, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1154, 4, 1, 13, 20, 0, 2, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1155, 4, 1, 14, 21, 0, 1, 0, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1156, 4, 1, 15, 22, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1157, 4, 1, 16, 23, 0, 1, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1158, 4, 1, 17, 24, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1159, 4, 1, 18, 25, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1160, 4, 1, 19, 26, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1161, 4, 1, 20, 27, 0, 1, 0, 2, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1162, 4, 1, 21, 28, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1163, 4, 1, 22, 29, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1164, 4, 1, 23, 30, 0, 1, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1165, 4, 1, 24, 31, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1166, 4, 1, 25, 32, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1167, 4, 1, 26, 33, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1168, 4, 1, 27, 34, 0, 1, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1169, 4, 1, 28, 35, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1170, 4, 1, 29, 36, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1171, 4, 1, 30, 37, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1172, 4, 1, 31, 38, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1173, 4, 1, 32, 39, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1174, 4, 1, 33, 40, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1175, 4, 1, 34, 41, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1176, 4, 1, 35, 42, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1177, 4, 1, 36, 44, 0, 1, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1178, 4, 1, 37, 46, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1179, 4, 1, 38, 48, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1180, 4, 1, 39, 50, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1181, 4, 1, 40, 52, 0, 1, 2, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1182, 4, 1, 41, 54, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1183, 4, 1, 42, 56, 0, 2, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1184, 4, 1, 43, 58, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1185, 4, 1, 44, 60, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1186, 4, 1, 45, 62, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1187, 4, 1, 46, 64, 0, 2, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1188, 4, 1, 47, 66, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1189, 4, 1, 48, 68, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1190, 4, 1, 49, 70, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1191, 4, 1, 50, 72, 0, 2, 2, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1192, 4, 1, 51, 74, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1193, 4, 1, 52, 76, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1194, 4, 1, 53, 78, 0, 2, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1195, 4, 1, 54, 80, 0, 3, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1196, 4, 1, 55, 82, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1197, 4, 1, 56, 84, 0, 2, 2, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1198, 4, 1, 57, 86, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1199, 4, 1, 58, 88, 0, 3, 2, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1200, 4, 1, 59, 90, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1202, 2, 3, 1, 17, 6, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1203, 2, 3, 2, 17, 21, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1204, 2, 3, 3, 17, 8, 0, 2, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1205, 2, 3, 4, 17, 23, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1206, 2, 3, 5, 17, 10, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1207, 2, 3, 6, 17, 25, 0, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1208, 2, 3, 7, 17, 26, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1209, 2, 3, 8, 17, 27, 0, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1210, 2, 3, 9, 17, 28, 1, 1, 0, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1211, 2, 3, 10, 17, 29, 0, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1212, 2, 3, 11, 17, 30, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1213, 2, 3, 12, 17, 31, 0, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1214, 2, 3, 13, 18, 32, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1215, 2, 3, 14, 19, 33, 0, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1216, 2, 3, 15, 20, 34, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1217, 2, 3, 16, 21, 35, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1218, 2, 3, 17, 22, 36, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1219, 2, 3, 18, 23, 37, 0, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1220, 2, 3, 19, 24, 38, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1221, 2, 3, 20, 25, 39, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1222, 2, 3, 21, 26, 40, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1223, 2, 3, 22, 27, 41, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1224, 2, 3, 23, 28, 42, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1225, 2, 3, 24, 29, 43, 0, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1226, 2, 3, 25, 30, 44, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1227, 2, 3, 26, 31, 45, 0, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1228, 2, 3, 27, 32, 45, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1229, 2, 3, 28, 33, 45, 0, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1230, 2, 3, 29, 34, 45, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1231, 2, 3, 30, 35, 45, 0, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1232, 2, 3, 31, 36, 45, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1233, 2, 3, 32, 37, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1234, 2, 3, 33, 38, 45, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1235, 2, 3, 34, 39, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1236, 2, 3, 35, 40, 45, 1, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1237, 2, 3, 36, 41, 45, 0, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1238, 2, 3, 37, 42, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1239, 2, 3, 38, 43, 45, 0, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1240, 2, 3, 39, 44, 45, 1, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1241, 2, 3, 40, 45, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1242, 2, 3, 41, 46, 45, 0, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1243, 2, 3, 42, 47, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1244, 2, 3, 43, 48, 45, 1, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1245, 2, 3, 44, 49, 45, 0, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1246, 2, 3, 45, 50, 45, 1, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1247, 2, 3, 46, 51, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1248, 2, 3, 47, 52, 45, 1, 3, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1249, 2, 3, 48, 53, 45, 0, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1250, 2, 3, 49, 54, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1251, 2, 3, 50, 55, 45, 1, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1252, 2, 3, 51, 56, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1253, 2, 3, 52, 57, 45, 0, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1254, 2, 3, 53, 58, 45, 1, 3, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1255, 2, 3, 54, 59, 45, 1, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1256, 2, 3, 55, 60, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1257, 2, 3, 56, 61, 45, 1, 3, 2, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1258, 2, 3, 57, 62, 45, 0, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1259, 2, 3, 58, 63, 45, 1, 3, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1260, 2, 3, 59, 64, 45, 1, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1262, 2, 4, 1, 17, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1263, 2, 4, 2, 17, 0, 0, 1, 0, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1264, 2, 4, 3, 17, 0, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1265, 2, 4, 4, 17, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1266, 2, 4, 5, 17, 0, 0, 1, 0, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1267, 2, 4, 6, 17, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1268, 2, 4, 7, 17, 0, 1, 1, 0, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1269, 2, 4, 8, 17, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1270, 2, 4, 9, 17, 0, 0, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1271, 2, 4, 10, 17, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1272, 2, 4, 11, 17, 0, 1, 1, 0, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1273, 2, 4, 12, 17, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1274, 2, 4, 13, 17, 0, 0, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1275, 2, 4, 14, 17, 0, 1, 2, 0, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1276, 2, 4, 15, 18, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1277, 2, 4, 16, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1278, 2, 4, 17, 20, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1279, 2, 4, 18, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1280, 2, 4, 19, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1281, 2, 4, 20, 66, 0, 2, 5, 2, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1282, 2, 4, 21, 24, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1283, 2, 4, 22, 25, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1284, 2, 4, 23, 26, 0, 1, 1, 0, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1285, 2, 4, 24, 27, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1286, 2, 4, 25, 28, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1287, 2, 4, 26, 29, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1288, 2, 4, 27, 30, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1289, 2, 4, 28, 31, 0, 0, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1290, 2, 4, 29, 32, 0, 1, 2, 0, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1291, 2, 4, 30, 33, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1292, 2, 4, 31, 34, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1293, 2, 4, 32, 35, 0, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1294, 2, 4, 33, 36, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1295, 2, 4, 34, 37, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1296, 2, 4, 35, 38, 0, 2, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1297, 2, 4, 36, 39, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1298, 2, 4, 37, 45, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1299, 2, 4, 38, 36, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1300, 2, 4, 39, 42, 0, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1301, 2, 4, 40, 43, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1302, 2, 4, 41, 44, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1303, 2, 4, 42, 45, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1304, 2, 4, 43, 46, 0, 1, 3, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1305, 2, 4, 44, 47, 0, 2, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1306, 2, 4, 45, 48, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1307, 2, 4, 46, 49, 0, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1308, 2, 4, 47, 50, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1309, 2, 4, 48, 51, 0, 1, 2, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1310, 2, 4, 49, 52, 0, 2, 3, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1311, 2, 4, 50, 53, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1312, 2, 4, 51, 54, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1313, 2, 4, 52, 55, 0, 1, 3, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1314, 2, 4, 53, 56, 0, 2, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1315, 2, 4, 54, 57, 0, 1, 2, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1316, 2, 4, 55, 58, 0, 1, 3, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1317, 2, 4, 56, 59, 0, 2, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1318, 2, 4, 57, 60, 0, 1, 3, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1319, 2, 4, 58, 61, 0, 2, 2, 2, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1320, 2, 4, 59, 62, 0, 1, 3, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1322, 2, 7, 1, 17, 7, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1323, 2, 7, 2, 17, 8, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1324, 2, 7, 3, 17, 23, 1, 0, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1325, 2, 7, 4, 17, 24, 1, 1, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1326, 2, 7, 5, 17, 25, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1327, 2, 7, 6, 17, 26, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1328, 2, 7, 7, 17, 27, 0, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1329, 2, 7, 8, 17, 43, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1330, 2, 7, 9, 17, 14, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1331, 2, 7, 10, 17, 30, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1332, 2, 7, 11, 17, 31, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1333, 2, 7, 12, 17, 32, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1334, 2, 7, 13, 17, 33, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1335, 2, 7, 14, 17, 34, 1, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1336, 2, 7, 15, 17, 35, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1337, 2, 7, 16, 18, 36, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1338, 2, 7, 17, 19, 37, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1339, 2, 7, 18, 20, 38, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1340, 2, 7, 19, 21, 39, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1341, 2, 7, 20, 22, 40, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1342, 2, 7, 21, 23, 76, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1343, 2, 7, 22, 24, 7, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1344, 2, 7, 23, 25, 43, 1, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1345, 2, 7, 24, 26, 44, 1, 0, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1346, 2, 7, 25, 27, 89, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1347, 2, 7, 26, 28, 2, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1348, 2, 7, 27, 29, 47, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1349, 2, 7, 28, 30, 48, 1, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1350, 2, 7, 29, 31, 102, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1351, 2, 7, 30, 32, 11, 2, 0, 2, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1352, 2, 7, 31, 33, 108, 1, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1353, 2, 7, 32, 34, 51, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1354, 2, 7, 33, 35, 36, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1355, 2, 7, 34, 36, 51, 1, 1, 2, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1356, 2, 7, 35, 37, 68, 1, 1, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1357, 2, 7, 36, 38, 51, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1358, 2, 7, 37, 39, 52, 1, 1, 2, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1359, 2, 7, 38, 40, 52, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1360, 2, 7, 39, 41, 50, 2, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1361, 2, 7, 40, 42, 32, 1, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1362, 2, 7, 41, 43, 22, 1, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1363, 2, 7, 42, 44, 13, 1, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1364, 2, 7, 43, 45, 51, 2, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1365, 2, 7, 44, 46, 124, 1, 0, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1366, 2, 7, 45, 47, 67, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1367, 2, 7, 46, 48, 52, 1, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1368, 2, 7, 47, 49, 51, 2, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1369, 2, 7, 48, 50, 51, 1, 0, 2, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1370, 2, 7, 49, 51, 36, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1371, 2, 7, 50, 52, 68, 2, 1, 2, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1372, 2, 7, 51, 53, 51, 1, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1373, 2, 7, 52, 54, 51, 2, 0, 2, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1374, 2, 7, 53, 55, 22, 1, 1, 2, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1375, 2, 7, 54, 56, 30, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1376, 2, 7, 55, 57, 51, 2, 1, 2, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1377, 2, 7, 56, 58, 103, 1, 1, 2, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1378, 2, 7, 57, 59, 52, 2, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1379, 2, 7, 58, 60, 51, 1, 1, 2, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1380, 2, 7, 59, 61, 79, 2, 1, 2, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1382, 2, 9, 1, 15, 9, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1383, 2, 9, 2, 15, 24, 1, 1, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1384, 2, 9, 3, 15, 25, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1385, 2, 9, 4, 15, 26, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1386, 2, 9, 5, 15, 27, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1387, 2, 9, 6, 15, 28, 1, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1388, 2, 9, 7, 15, 29, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1389, 2, 9, 8, 15, 30, 0, 1, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1390, 2, 9, 9, 15, 31, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1391, 2, 9, 10, 15, 32, 0, 1, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1392, 2, 9, 11, 15, 33, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1393, 2, 9, 12, 15, 34, 1, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1394, 2, 9, 13, 15, 35, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1395, 2, 9, 14, 15, 36, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1396, 2, 9, 15, 15, 37, 1, 1, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1397, 2, 9, 16, 15, 38, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1398, 2, 9, 17, 16, 39, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1399, 2, 9, 18, 35, 40, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1400, 2, 9, 19, 12, 41, 0, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1401, 2, 9, 20, 32, 42, 0, 1, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1402, 2, 9, 21, 0, 43, 1, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1403, 2, 9, 22, 16, 44, 0, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1404, 2, 9, 23, 22, 45, 1, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1405, 2, 9, 24, 23, 46, 0, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1406, 2, 9, 25, 24, 47, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1407, 2, 9, 26, 25, 48, 1, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1408, 2, 9, 27, 26, 49, 0, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1409, 2, 9, 28, 27, 50, 1, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1410, 2, 9, 29, 28, 51, 0, 1, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1411, 2, 9, 30, 29, 51, 0, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1412, 2, 9, 31, 30, 51, 1, 1, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1413, 2, 9, 32, 21, 51, 0, 0, 0, 1, 3); +INSERT INTO `player_levelupgains` VALUES (1414, 2, 9, 33, 42, 51, 1, 1, 1, 2, 0); +INSERT INTO `player_levelupgains` VALUES (1415, 2, 9, 34, 33, 51, 0, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1416, 2, 9, 35, 34, 51, 1, 1, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1417, 2, 9, 36, 35, 51, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1418, 2, 9, 37, 36, 51, 0, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1419, 2, 9, 38, 37, 51, 1, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1420, 2, 9, 39, 38, 51, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1421, 2, 9, 40, 39, 51, 1, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1422, 2, 9, 41, 20, 51, 0, 0, 0, 2, 3); +INSERT INTO `player_levelupgains` VALUES (1423, 2, 9, 42, 61, 51, 1, 1, 3, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1424, 2, 9, 43, 42, 51, 0, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1425, 2, 9, 44, 43, 51, 1, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1426, 2, 9, 45, 44, 51, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1427, 2, 9, 46, 45, 51, 1, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1428, 2, 9, 47, 46, 51, 0, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1429, 2, 9, 48, 47, 51, 1, 1, 1, 2, 3); +INSERT INTO `player_levelupgains` VALUES (1430, 2, 9, 49, 48, 51, 0, 0, 2, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1431, 2, 9, 50, 39, 51, 1, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1432, 2, 9, 51, 60, 51, 0, 0, 2, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1433, 2, 9, 52, 51, 51, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1434, 2, 9, 53, 32, 51, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1435, 2, 9, 54, 73, 51, 0, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1436, 2, 9, 55, 54, 51, 1, 1, 1, 2, 3); +INSERT INTO `player_levelupgains` VALUES (1437, 2, 9, 56, 49, 51, 0, 1, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1438, 2, 9, 57, 52, 51, 1, 1, 2, 2, 4); +INSERT INTO `player_levelupgains` VALUES (1439, 2, 9, 58, 57, 51, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1440, 2, 9, 59, 68, 51, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1442, 2, 1, 1, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1443, 2, 1, 2, 19, 0, 1, 0, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1444, 2, 1, 3, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1445, 2, 1, 4, 19, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1446, 2, 1, 5, 19, 0, 1, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1447, 2, 1, 6, 19, 0, 1, 0, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1448, 2, 1, 7, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1449, 2, 1, 8, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1450, 2, 1, 9, 19, 0, 1, 0, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1451, 2, 1, 10, 19, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1452, 2, 1, 11, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1453, 2, 1, 12, 19, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1454, 2, 1, 13, 20, 0, 2, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1455, 2, 1, 14, 21, 0, 1, 0, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1456, 2, 1, 15, 22, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1457, 2, 1, 16, 23, 0, 1, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1458, 2, 1, 17, 24, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1459, 2, 1, 18, 25, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1460, 2, 1, 19, 26, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1461, 2, 1, 20, 27, 0, 1, 0, 2, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1462, 2, 1, 21, 28, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1463, 2, 1, 22, 29, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1464, 2, 1, 23, 30, 0, 1, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1465, 2, 1, 24, 31, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1466, 2, 1, 25, 32, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1467, 2, 1, 26, 33, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1468, 2, 1, 27, 34, 0, 1, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1469, 2, 1, 28, 35, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1470, 2, 1, 29, 36, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1471, 2, 1, 30, 37, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1472, 2, 1, 31, 38, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1473, 2, 1, 32, 39, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1474, 2, 1, 33, 40, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1475, 2, 1, 34, 41, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1476, 2, 1, 35, 42, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1477, 2, 1, 36, 44, 0, 1, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1478, 2, 1, 37, 46, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1479, 2, 1, 38, 48, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1480, 2, 1, 39, 50, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1481, 2, 1, 40, 52, 0, 1, 2, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1482, 2, 1, 41, 54, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1483, 2, 1, 42, 56, 0, 2, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1484, 2, 1, 43, 58, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1485, 2, 1, 44, 60, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1486, 2, 1, 45, 62, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1487, 2, 1, 46, 64, 0, 2, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1488, 2, 1, 47, 66, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1489, 2, 1, 48, 68, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1490, 2, 1, 49, 70, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1491, 2, 1, 50, 72, 0, 2, 2, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1492, 2, 1, 51, 74, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1493, 2, 1, 52, 76, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1494, 2, 1, 53, 78, 0, 2, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1495, 2, 1, 54, 80, 0, 3, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1496, 2, 1, 55, 82, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1497, 2, 1, 56, 84, 0, 2, 2, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1498, 2, 1, 57, 86, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1499, 2, 1, 58, 88, 0, 3, 2, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1500, 2, 1, 59, 90, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1502, 6, 11, 1, 19, 8, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1503, 6, 11, 2, 16, 9, 0, 1, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1504, 6, 11, 3, 19, 10, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1505, 6, 11, 4, 18, 25, 0, 1, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1506, 6, 11, 5, 18, 26, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1507, 6, 11, 6, 17, 27, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1508, 6, 11, 7, 18, 13, 1, 0, 0, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1509, 6, 11, 8, 18, 29, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1510, 6, 11, 9, 18, 30, 1, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1511, 6, 11, 10, 18, 31, 0, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1512, 6, 11, 11, 17, 32, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1513, 6, 11, 12, 18, 33, 0, 1, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1514, 6, 11, 13, 18, 34, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1515, 6, 11, 14, 19, 50, 1, 1, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1516, 6, 11, 15, 18, 36, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1517, 6, 11, 16, 18, 37, 1, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1518, 6, 11, 17, 18, 38, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1519, 6, 11, 18, 19, 39, 1, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1520, 6, 11, 19, 23, 40, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1521, 6, 11, 20, 22, 41, 0, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1522, 6, 11, 21, 23, 27, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1523, 6, 11, 22, 24, 43, 1, 1, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1524, 6, 11, 23, 24, 59, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1525, 6, 11, 24, 26, 45, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1526, 6, 11, 25, 29, 45, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1527, 6, 11, 26, 28, 30, 0, 1, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1528, 6, 11, 27, 29, 45, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1529, 6, 11, 28, 29, 60, 1, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1530, 6, 11, 29, 32, 45, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1531, 6, 11, 30, 32, 30, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1532, 6, 11, 31, 34, 60, 1, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1533, 6, 11, 32, 36, 45, 1, 1, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1534, 6, 11, 33, 34, 30, 0, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1535, 6, 11, 34, 37, 60, 1, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1536, 6, 11, 35, 39, 30, 1, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1537, 6, 11, 36, 38, 45, 1, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1538, 6, 11, 37, 41, 60, 1, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1539, 6, 11, 38, 40, 30, 0, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1540, 6, 11, 39, 42, 60, 1, 1, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1541, 6, 11, 40, 44, 30, 1, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1542, 6, 11, 41, 43, 60, 1, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1543, 6, 11, 42, 46, 30, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1544, 6, 11, 43, 46, 60, 1, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1545, 6, 11, 44, 47, 30, 0, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1546, 6, 11, 45, 49, 60, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1547, 6, 11, 46, 49, 30, 1, 0, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1548, 6, 11, 47, 49, 45, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1549, 6, 11, 48, 53, 60, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1550, 6, 11, 49, 52, 30, 1, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1551, 6, 11, 50, 54, 45, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1552, 6, 11, 51, 55, 60, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1553, 6, 11, 52, 55, 30, 1, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1554, 6, 11, 53, 57, 45, 1, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1555, 6, 11, 54, 57, 45, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1556, 6, 11, 55, 59, 45, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1557, 6, 11, 56, 61, 45, 1, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1558, 6, 11, 57, 60, 45, 1, 1, 2, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1559, 6, 11, 58, 63, 45, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1560, 6, 11, 59, 62, 45, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1562, 6, 3, 1, 17, 6, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1563, 6, 3, 2, 18, 21, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1564, 6, 3, 3, 18, 8, 0, 2, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1565, 6, 3, 4, 18, 23, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1566, 6, 3, 5, 17, 10, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1567, 6, 3, 6, 18, 25, 0, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1568, 6, 3, 7, 18, 12, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1569, 6, 3, 8, 19, 27, 0, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1570, 6, 3, 9, 16, 14, 1, 1, 0, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1571, 6, 3, 10, 18, 29, 0, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1572, 6, 3, 11, 18, 30, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1573, 6, 3, 12, 19, 31, 0, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1574, 6, 3, 13, 18, 32, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1575, 6, 3, 14, 21, 33, 0, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1576, 6, 3, 15, 21, 34, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1577, 6, 3, 16, 21, 35, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1578, 6, 3, 17, 24, 36, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1579, 6, 3, 18, 25, 37, 0, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1580, 6, 3, 19, 24, 38, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1581, 6, 3, 20, 27, 39, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1582, 6, 3, 21, 26, 40, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1583, 6, 3, 22, 29, 41, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1584, 6, 3, 23, 29, 42, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1585, 6, 3, 24, 31, 43, 0, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1586, 6, 3, 25, 32, 44, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1587, 6, 3, 26, 31, 45, 0, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1588, 6, 3, 27, 34, 45, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1589, 6, 3, 28, 35, 45, 0, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1590, 6, 3, 29, 36, 45, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1591, 6, 3, 30, 37, 45, 0, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1592, 6, 3, 31, 37, 45, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1593, 6, 3, 32, 39, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1594, 6, 3, 33, 39, 45, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1595, 6, 3, 34, 42, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1596, 6, 3, 35, 42, 45, 1, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1597, 6, 3, 36, 42, 45, 0, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1598, 6, 3, 37, 46, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1599, 6, 3, 38, 44, 45, 0, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1600, 6, 3, 39, 46, 45, 1, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1601, 6, 3, 40, 49, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1602, 6, 3, 41, 47, 45, 0, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1603, 6, 3, 42, 50, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1604, 6, 3, 43, 50, 45, 1, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1605, 6, 3, 44, 51, 45, 0, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1606, 6, 3, 45, 54, 45, 1, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1607, 6, 3, 46, 52, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1608, 6, 3, 47, 55, 45, 1, 3, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1609, 6, 3, 48, 56, 45, 0, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1610, 6, 3, 49, 56, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1611, 6, 3, 50, 58, 45, 1, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1612, 6, 3, 51, 59, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1613, 6, 3, 52, 60, 45, 0, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1614, 6, 3, 53, 61, 45, 1, 3, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1615, 6, 3, 54, 61, 45, 1, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1616, 6, 3, 55, 63, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1617, 6, 3, 56, 65, 45, 1, 3, 2, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1618, 6, 3, 57, 65, 45, 0, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1619, 6, 3, 58, 66, 45, 1, 3, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1620, 6, 3, 59, 68, 45, 1, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1622, 6, 7, 1, 17, 7, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1623, 6, 7, 2, 19, 8, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1624, 6, 7, 3, 16, 23, 1, 0, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1625, 6, 7, 4, 19, 10, 1, 1, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1626, 6, 7, 5, 18, 11, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1627, 6, 7, 6, 18, 26, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1628, 6, 7, 7, 17, 27, 0, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1629, 6, 7, 8, 18, 43, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1630, 6, 7, 9, 18, 14, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1631, 6, 7, 10, 18, 30, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1632, 6, 7, 11, 18, 31, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1633, 6, 7, 12, 17, 32, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1634, 6, 7, 13, 18, 33, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1635, 6, 7, 14, 18, 34, 1, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1636, 6, 7, 15, 19, 35, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1637, 6, 7, 16, 18, 36, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1638, 6, 7, 17, 21, 37, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1639, 6, 7, 18, 21, 38, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1640, 6, 7, 19, 21, 39, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1641, 6, 7, 20, 24, 40, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1642, 6, 7, 21, 23, 41, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1643, 6, 7, 22, 26, 42, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1644, 6, 7, 23, 27, 81, 1, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1645, 6, 7, 24, 26, 6, 1, 0, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1646, 6, 7, 25, 29, 45, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1647, 6, 7, 26, 29, 46, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1648, 6, 7, 27, 31, 47, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1649, 6, 7, 28, 32, 48, 1, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1650, 6, 7, 29, 31, 49, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1651, 6, 7, 30, 34, 119, 2, 0, 2, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1652, 6, 7, 31, 35, 52, 1, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1653, 6, 7, 32, 36, 49, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1654, 6, 7, 33, 35, 40, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1655, 6, 7, 34, 39, 49, 1, 1, 2, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1656, 6, 7, 35, 39, 0, 1, 1, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1657, 6, 7, 36, 40, 119, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1658, 6, 7, 37, 41, 13, 1, 1, 2, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1659, 6, 7, 38, 42, 38, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1660, 6, 7, 39, 43, 103, 2, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1661, 6, 7, 40, 45, 51, 1, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1662, 6, 7, 41, 44, 37, 1, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1663, 6, 7, 42, 45, 51, 1, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1664, 6, 7, 43, 49, 67, 2, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1665, 6, 7, 44, 48, 36, 1, 0, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1666, 6, 7, 45, 50, 67, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1667, 6, 7, 46, 50, 51, 1, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1668, 6, 7, 47, 51, 36, 2, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1669, 6, 7, 48, 53, 67, 1, 0, 2, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1670, 6, 7, 49, 52, 36, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1671, 6, 7, 50, 55, 67, 2, 1, 2, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1672, 6, 7, 51, 57, 52, 1, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1673, 6, 7, 52, 56, 51, 2, 0, 2, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1674, 6, 7, 53, 58, 23, 1, 1, 2, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1675, 6, 7, 54, 59, 29, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1676, 6, 7, 55, 59, 51, 2, 1, 2, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1677, 6, 7, 56, 60, 103, 1, 1, 2, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1678, 6, 7, 57, 62, 51, 2, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1679, 6, 7, 58, 64, 27, 1, 1, 2, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1680, 6, 7, 59, 65, 25, 2, 1, 2, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1682, 6, 1, 1, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1683, 6, 1, 2, 20, 0, 1, 0, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1684, 6, 1, 3, 21, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1685, 6, 1, 4, 19, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1686, 6, 1, 5, 20, 0, 1, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1687, 6, 1, 6, 21, 0, 1, 0, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1688, 6, 1, 7, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1689, 6, 1, 8, 21, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1690, 6, 1, 9, 20, 0, 1, 0, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1691, 6, 1, 10, 19, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1692, 6, 1, 11, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1693, 6, 1, 12, 20, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1694, 6, 1, 13, 22, 0, 2, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1695, 6, 1, 14, 21, 0, 1, 0, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1696, 6, 1, 15, 25, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1697, 6, 1, 16, 24, 0, 1, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1698, 6, 1, 17, 24, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1699, 6, 1, 18, 28, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1700, 6, 1, 19, 25, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1701, 6, 1, 20, 29, 0, 1, 0, 2, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1702, 6, 1, 21, 30, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1703, 6, 1, 22, 30, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1704, 6, 1, 23, 31, 0, 1, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1705, 6, 1, 24, 34, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1706, 6, 1, 25, 32, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1707, 6, 1, 26, 36, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1708, 6, 1, 27, 35, 0, 1, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1709, 6, 1, 28, 37, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1710, 6, 1, 29, 39, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1711, 6, 1, 30, 37, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1712, 6, 1, 31, 41, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1713, 6, 1, 32, 40, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1714, 6, 1, 33, 42, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1715, 6, 1, 34, 44, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1716, 6, 1, 35, 43, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1717, 6, 1, 36, 46, 0, 1, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1718, 6, 1, 37, 50, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1719, 6, 1, 38, 50, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1720, 6, 1, 39, 51, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1721, 6, 1, 40, 56, 0, 1, 2, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1722, 6, 1, 41, 57, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1723, 6, 1, 42, 59, 0, 2, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1724, 6, 1, 43, 60, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1725, 6, 1, 44, 63, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1726, 6, 1, 45, 66, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1727, 6, 1, 46, 67, 0, 2, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1728, 6, 1, 47, 68, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1729, 6, 1, 48, 72, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1730, 6, 1, 49, 74, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1731, 6, 1, 50, 76, 0, 2, 2, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1732, 6, 1, 51, 76, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1733, 6, 1, 52, 80, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1734, 6, 1, 53, 83, 0, 2, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1735, 6, 1, 54, 84, 0, 3, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1736, 6, 1, 55, 86, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1737, 6, 1, 56, 88, 0, 2, 2, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1738, 6, 1, 57, 91, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1739, 6, 1, 58, 92, 0, 3, 2, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1740, 6, 1, 59, 94, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1742, 8, 3, 1, 17, 6, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1743, 8, 3, 2, 17, 21, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1744, 8, 3, 3, 17, 8, 0, 2, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1745, 8, 3, 4, 17, 23, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1746, 8, 3, 5, 17, 10, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1747, 8, 3, 6, 17, 25, 0, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1748, 8, 3, 7, 17, 12, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1749, 8, 3, 8, 17, 27, 0, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1750, 8, 3, 9, 17, 28, 1, 1, 0, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1751, 8, 3, 10, 17, 29, 0, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1752, 8, 3, 11, 17, 30, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1753, 8, 3, 12, 17, 31, 0, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1754, 8, 3, 13, 18, 32, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1755, 8, 3, 14, 19, 33, 0, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1756, 8, 3, 15, 20, 34, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1757, 8, 3, 16, 21, 35, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1758, 8, 3, 17, 22, 36, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1759, 8, 3, 18, 23, 37, 0, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1760, 8, 3, 19, 24, 38, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1761, 8, 3, 20, 25, 39, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1762, 8, 3, 21, 26, 40, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1763, 8, 3, 22, 27, 41, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1764, 8, 3, 23, 28, 42, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1765, 8, 3, 24, 29, 43, 0, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1766, 8, 3, 25, 30, 44, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1767, 8, 3, 26, 31, 45, 0, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1768, 8, 3, 27, 32, 45, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1769, 8, 3, 28, 33, 45, 0, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1770, 8, 3, 29, 34, 45, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1771, 8, 3, 30, 35, 45, 0, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1772, 8, 3, 31, 36, 45, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1773, 8, 3, 32, 37, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1774, 8, 3, 33, 38, 45, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1775, 8, 3, 34, 39, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1776, 8, 3, 35, 40, 45, 1, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1777, 8, 3, 36, 41, 45, 0, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1778, 8, 3, 37, 42, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1779, 8, 3, 38, 43, 45, 0, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1780, 8, 3, 39, 44, 45, 1, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1781, 8, 3, 40, 45, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1782, 8, 3, 41, 46, 45, 0, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1783, 8, 3, 42, 47, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1784, 8, 3, 43, 48, 45, 1, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1785, 8, 3, 44, 49, 45, 0, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1786, 8, 3, 45, 50, 45, 1, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1787, 8, 3, 46, 51, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1788, 8, 3, 47, 52, 45, 1, 3, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1789, 8, 3, 48, 53, 45, 0, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1790, 8, 3, 49, 54, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1791, 8, 3, 50, 55, 45, 1, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1792, 8, 3, 51, 56, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1793, 8, 3, 52, 57, 45, 0, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1794, 8, 3, 53, 58, 45, 1, 3, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1795, 8, 3, 54, 59, 45, 1, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1796, 8, 3, 55, 60, 45, 1, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1797, 8, 3, 56, 61, 45, 1, 3, 2, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1798, 8, 3, 57, 62, 45, 0, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1799, 8, 3, 58, 63, 45, 1, 3, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1800, 8, 3, 59, 64, 45, 1, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1802, 8, 8, 1, 15, 11, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1803, 8, 8, 2, 15, 26, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1804, 8, 8, 3, 15, 27, 0, 1, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1805, 8, 8, 4, 15, 28, 0, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1806, 8, 8, 5, 15, 29, 1, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1807, 8, 8, 6, 15, 30, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1808, 8, 8, 7, 15, 16, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1809, 8, 8, 8, 15, 47, 0, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1810, 8, 8, 9, 15, 33, 0, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1811, 8, 8, 10, 15, 34, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1812, 8, 8, 11, 15, 35, 0, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1813, 8, 8, 12, 15, 36, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1814, 8, 8, 13, 15, 37, 1, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1815, 8, 8, 14, 15, 38, 0, 1, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1816, 8, 8, 15, 15, 39, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1817, 8, 8, 16, 15, 25, 0, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1818, 8, 8, 17, 15, 56, 0, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1819, 8, 8, 18, 15, 27, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1820, 8, 8, 19, 15, 58, 0, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1821, 8, 8, 20, 15, 29, 1, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1822, 8, 8, 21, 15, 60, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1823, 8, 8, 22, 15, 31, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1824, 8, 8, 23, 16, 62, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1825, 8, 8, 24, 17, 33, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1826, 8, 8, 25, 18, 64, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1827, 8, 8, 26, 19, 50, 0, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1828, 8, 8, 27, 20, 36, 1, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1829, 8, 8, 28, 21, 66, 0, 1, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1830, 8, 8, 29, 22, 51, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1831, 8, 8, 30, 23, 36, 0, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1832, 8, 8, 31, 24, 66, 0, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1833, 8, 8, 32, 25, 51, 0, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1834, 8, 8, 33, 26, 36, 1, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1835, 8, 8, 34, 27, 51, 0, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1836, 8, 8, 35, 28, 51, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1837, 8, 8, 36, 29, 66, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1838, 8, 8, 37, 30, 51, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1839, 8, 8, 38, 31, 51, 1, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1840, 8, 8, 39, 32, 36, 0, 1, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1841, 8, 8, 40, 33, 51, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1842, 8, 8, 41, 34, 51, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1843, 8, 8, 42, 35, 51, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1844, 8, 8, 43, 36, 51, 0, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1845, 8, 8, 44, 37, 51, 1, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1846, 8, 8, 45, 38, 51, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1847, 8, 8, 46, 79, 51, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1848, 8, 8, 47, 10, 66, 0, 0, 0, 3, 2); +INSERT INTO `player_levelupgains` VALUES (1849, 8, 8, 48, 31, 51, 1, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1850, 8, 8, 49, 42, 36, 0, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1851, 8, 8, 50, 43, 51, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1852, 8, 8, 51, 44, 51, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1853, 8, 8, 52, 45, 51, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1854, 8, 8, 53, 46, 51, 1, 0, 1, 3, 2); +INSERT INTO `player_levelupgains` VALUES (1855, 8, 8, 54, 47, 66, 0, 0, 0, 2, 3); +INSERT INTO `player_levelupgains` VALUES (1856, 8, 8, 55, 48, 39, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1857, 8, 8, 56, 49, 48, 0, 0, 0, 3, 2); +INSERT INTO `player_levelupgains` VALUES (1858, 8, 8, 57, 50, 51, 1, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1859, 8, 8, 58, 42, 51, 0, 1, 0, 3, 3); +INSERT INTO `player_levelupgains` VALUES (1860, 8, 8, 59, 61, 51, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1862, 8, 5, 1, 15, 10, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1863, 8, 5, 2, 15, 11, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1864, 8, 5, 3, 15, 26, 1, 1, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1865, 8, 5, 4, 15, 27, 0, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1866, 8, 5, 5, 15, 28, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1867, 8, 5, 6, 15, 29, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1868, 8, 5, 7, 15, 30, 0, 1, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1869, 8, 5, 8, 15, 31, 0, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1870, 8, 5, 9, 15, 47, 1, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1871, 8, 5, 10, 15, 18, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1872, 8, 5, 11, 15, 34, 0, 1, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1873, 8, 5, 12, 15, 35, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1874, 8, 5, 13, 15, 36, 0, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1875, 8, 5, 14, 15, 37, 1, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1876, 8, 5, 15, 15, 38, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1877, 8, 5, 16, 15, 54, 0, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1878, 8, 5, 17, 15, 25, 0, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1879, 8, 5, 18, 15, 41, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1880, 8, 5, 19, 15, 42, 1, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1881, 8, 5, 20, 15, 43, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1882, 8, 5, 21, 16, 59, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1883, 8, 5, 22, 17, 30, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1884, 8, 5, 23, 18, 61, 1, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1885, 8, 5, 24, 19, 32, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1886, 8, 5, 25, 20, 63, 0, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1887, 8, 5, 26, 21, 34, 0, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1888, 8, 5, 27, 22, 65, 0, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1889, 8, 5, 28, 23, 36, 1, 1, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1890, 8, 5, 29, 24, 52, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1891, 8, 5, 30, 25, 68, 0, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1892, 8, 5, 31, 26, 39, 0, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1893, 8, 5, 32, 27, 69, 1, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1894, 8, 5, 33, 28, 54, 0, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1895, 8, 5, 34, 29, 39, 0, 1, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1896, 8, 5, 35, 30, 54, 1, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1897, 8, 5, 36, 31, 69, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1898, 8, 5, 37, 32, 54, 0, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1899, 8, 5, 38, 33, 39, 0, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1900, 8, 5, 39, 34, 54, 1, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (1901, 8, 5, 40, 35, 69, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1902, 8, 5, 41, 36, 54, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1903, 8, 5, 42, 37, 54, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1904, 8, 5, 43, 38, 54, 1, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1905, 8, 5, 44, 39, 54, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1906, 8, 5, 45, 40, 54, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1907, 8, 5, 46, 41, 54, 1, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1908, 8, 5, 47, 42, 54, 0, 1, 1, 2, 3); +INSERT INTO `player_levelupgains` VALUES (1909, 8, 5, 48, 93, 54, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1910, 8, 5, 49, 14, 54, 1, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1911, 8, 5, 50, 25, 54, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1912, 8, 5, 51, 46, 54, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1913, 8, 5, 52, 47, 54, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1914, 8, 5, 53, 48, 54, 0, 0, 1, 2, 3); +INSERT INTO `player_levelupgains` VALUES (1915, 8, 5, 54, 49, 54, 0, 1, 0, 3, 2); +INSERT INTO `player_levelupgains` VALUES (1916, 8, 5, 55, 50, 54, 1, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1917, 8, 5, 56, 51, 54, 0, 1, 1, 2, 3); +INSERT INTO `player_levelupgains` VALUES (1918, 8, 5, 57, 52, 54, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1919, 8, 5, 58, 53, 54, 1, 1, 0, 3, 3); +INSERT INTO `player_levelupgains` VALUES (1920, 8, 5, 59, 54, 54, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (1922, 8, 4, 1, 17, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1923, 8, 4, 2, 17, 0, 0, 1, 0, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1924, 8, 4, 3, 17, 0, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1925, 8, 4, 4, 17, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1926, 8, 4, 5, 17, 0, 0, 1, 0, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1927, 8, 4, 6, 17, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1928, 8, 4, 7, 17, 0, 1, 1, 0, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1929, 8, 4, 8, 17, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1930, 8, 4, 9, 17, 0, 0, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1931, 8, 4, 10, 17, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1932, 8, 4, 11, 17, 0, 1, 1, 0, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1933, 8, 4, 12, 17, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1934, 8, 4, 13, 17, 0, 0, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1935, 8, 4, 14, 17, 0, 1, 2, 0, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1936, 8, 4, 15, 18, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1937, 8, 4, 16, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1938, 8, 4, 17, 20, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1939, 8, 4, 18, 21, 0, 1, 2, 0, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1940, 8, 4, 19, 22, 0, 0, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1941, 8, 4, 20, 23, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1942, 8, 4, 21, 24, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1943, 8, 4, 22, 25, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1944, 8, 4, 23, 26, 0, 1, 1, 0, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1945, 8, 4, 24, 27, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1946, 8, 4, 25, 28, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1947, 8, 4, 26, 29, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1948, 8, 4, 27, 30, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1949, 8, 4, 28, 31, 0, 0, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1950, 8, 4, 29, 32, 0, 1, 2, 0, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1951, 8, 4, 30, 33, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1952, 8, 4, 31, 34, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1953, 8, 4, 32, 35, 0, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1954, 8, 4, 33, 36, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1955, 8, 4, 34, 37, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1956, 8, 4, 35, 38, 0, 2, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1957, 8, 4, 36, 39, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1958, 8, 4, 37, 40, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1959, 8, 4, 38, 41, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1960, 8, 4, 39, 42, 0, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1961, 8, 4, 40, 43, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1962, 8, 4, 41, 44, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1963, 8, 4, 42, 45, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1964, 8, 4, 43, 46, 0, 1, 3, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1965, 8, 4, 44, 47, 0, 2, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1966, 8, 4, 45, 48, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1967, 8, 4, 46, 49, 0, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1968, 8, 4, 47, 50, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1969, 8, 4, 48, 51, 0, 1, 2, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1970, 8, 4, 49, 52, 0, 2, 3, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1971, 8, 4, 50, 53, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1972, 8, 4, 51, 54, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1973, 8, 4, 52, 55, 0, 1, 3, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1974, 8, 4, 53, 56, 0, 2, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1975, 8, 4, 54, 57, 0, 1, 2, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (1976, 8, 4, 55, 58, 0, 1, 3, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1977, 8, 4, 56, 59, 0, 2, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1978, 8, 4, 57, 60, 0, 1, 3, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1979, 8, 4, 58, 61, 0, 2, 2, 2, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1980, 8, 4, 59, 62, 0, 1, 3, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1982, 8, 7, 1, 17, 7, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1983, 8, 7, 2, 17, 8, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1984, 8, 7, 3, 17, 23, 1, 0, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1985, 8, 7, 4, 17, 10, 1, 1, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1986, 8, 7, 5, 17, 25, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1987, 8, 7, 6, 17, 26, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1988, 8, 7, 7, 17, 27, 0, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (1989, 8, 7, 8, 17, 43, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1990, 8, 7, 9, 17, 14, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (1991, 8, 7, 10, 17, 30, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1992, 8, 7, 11, 17, 31, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1993, 8, 7, 12, 17, 32, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1994, 8, 7, 13, 17, 33, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1995, 8, 7, 14, 17, 34, 1, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (1996, 8, 7, 15, 17, 35, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1997, 8, 7, 16, 18, 36, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1998, 8, 7, 17, 19, 37, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (1999, 8, 7, 18, 20, 66, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2000, 8, 7, 19, 21, 11, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2001, 8, 7, 20, 22, 40, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2002, 8, 7, 21, 23, 41, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2003, 8, 7, 22, 24, 42, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2004, 8, 7, 23, 25, 43, 1, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2005, 8, 7, 24, 26, 44, 1, 0, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2006, 8, 7, 25, 27, 88, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2007, 8, 7, 26, 28, 49, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2008, 8, 7, 27, 29, 49, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2009, 8, 7, 28, 30, 0, 1, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2010, 8, 7, 29, 31, 49, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2011, 8, 7, 30, 32, 120, 2, 0, 2, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2012, 8, 7, 31, 33, 51, 1, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2013, 8, 7, 32, 34, 61, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2014, 8, 7, 33, 35, 27, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2015, 8, 7, 34, 36, 51, 1, 1, 2, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2016, 8, 7, 35, 37, 57, 1, 1, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2017, 8, 7, 36, 38, 61, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2018, 8, 7, 37, 39, 52, 1, 1, 2, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2019, 8, 7, 38, 40, 36, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2020, 8, 7, 39, 41, 38, 2, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2021, 8, 7, 40, 42, 28, 1, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2022, 8, 7, 41, 43, 56, 1, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2023, 8, 7, 42, 44, 33, 1, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2024, 8, 7, 43, 45, 30, 2, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2025, 8, 7, 44, 46, 34, 1, 0, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2026, 8, 7, 45, 47, 64, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2027, 8, 7, 46, 48, 144, 1, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2028, 8, 7, 47, 49, 36, 2, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2029, 8, 7, 48, 50, 53, 1, 0, 2, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2030, 8, 7, 49, 51, 50, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2031, 8, 7, 50, 52, 50, 2, 1, 2, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2032, 8, 7, 51, 53, 27, 1, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2033, 8, 7, 52, 54, 31, 2, 0, 2, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2034, 8, 7, 53, 55, 21, 1, 1, 2, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2035, 8, 7, 54, 56, 30, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2036, 8, 7, 55, 57, 33, 2, 1, 2, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2037, 8, 7, 56, 58, 65, 1, 1, 2, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2038, 8, 7, 57, 59, 48, 2, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2039, 8, 7, 58, 60, 49, 1, 1, 2, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2040, 8, 7, 59, 61, 49, 2, 1, 2, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2042, 8, 1, 1, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2043, 8, 1, 2, 19, 0, 1, 0, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2044, 8, 1, 3, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2045, 8, 1, 4, 19, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2046, 8, 1, 5, 19, 0, 1, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (2047, 8, 1, 6, 19, 0, 1, 0, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2048, 8, 1, 7, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2049, 8, 1, 8, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2050, 8, 1, 9, 19, 0, 1, 0, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2051, 8, 1, 10, 19, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2052, 8, 1, 11, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2053, 8, 1, 12, 19, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2054, 8, 1, 13, 20, 0, 2, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (2055, 8, 1, 14, 21, 0, 1, 0, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2056, 8, 1, 15, 22, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2057, 8, 1, 16, 23, 0, 1, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2058, 8, 1, 17, 24, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2059, 8, 1, 18, 25, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2060, 8, 1, 19, 26, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2061, 8, 1, 20, 27, 0, 1, 0, 2, 1, 0); +INSERT INTO `player_levelupgains` VALUES (2062, 8, 1, 21, 28, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2063, 8, 1, 22, 29, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2064, 8, 1, 23, 30, 0, 1, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2065, 8, 1, 24, 31, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2066, 8, 1, 25, 32, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2067, 8, 1, 26, 33, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2068, 8, 1, 27, 34, 0, 1, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (2069, 8, 1, 28, 35, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2070, 8, 1, 29, 36, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2071, 8, 1, 30, 37, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2072, 8, 1, 31, 38, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2073, 8, 1, 32, 39, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2074, 8, 1, 33, 40, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2075, 8, 1, 34, 41, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2076, 8, 1, 35, 42, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2077, 8, 1, 36, 44, 0, 1, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2078, 8, 1, 37, 46, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2079, 8, 1, 38, 48, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2080, 8, 1, 39, 50, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2081, 8, 1, 40, 52, 0, 1, 2, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2082, 8, 1, 41, 59, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2083, 8, 1, 42, 51, 0, 2, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2084, 8, 1, 43, 58, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2085, 8, 1, 44, 110, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2086, 8, 1, 45, 12, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2087, 8, 1, 46, 64, 0, 2, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2088, 8, 1, 47, 66, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2089, 8, 1, 48, 68, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2090, 8, 1, 49, 70, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2091, 8, 1, 50, 72, 0, 2, 2, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2092, 8, 1, 51, 74, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2093, 8, 1, 52, 76, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2094, 8, 1, 53, 78, 0, 2, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2095, 8, 1, 54, 80, 0, 3, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2096, 8, 1, 55, 82, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2097, 8, 1, 56, 84, 0, 2, 2, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2098, 8, 1, 57, 86, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2099, 8, 1, 58, 88, 0, 3, 2, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2100, 8, 1, 59, 90, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2102, 5, 8, 1, 15, 25, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2103, 5, 8, 2, 15, 26, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2104, 5, 8, 3, 15, 27, 0, 1, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2105, 5, 8, 4, 15, 28, 0, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2106, 5, 8, 5, 15, 29, 1, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2107, 5, 8, 6, 15, 30, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2108, 5, 8, 7, 15, 16, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2109, 5, 8, 8, 15, 47, 0, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2110, 5, 8, 9, 15, 33, 0, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2111, 5, 8, 10, 15, 34, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2112, 5, 8, 11, 15, 35, 0, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2113, 5, 8, 12, 15, 36, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2114, 5, 8, 13, 15, 37, 1, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2115, 5, 8, 14, 15, 38, 0, 1, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2116, 5, 8, 15, 15, 39, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2117, 5, 8, 16, 15, 25, 0, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2118, 5, 8, 17, 15, 56, 0, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2119, 5, 8, 18, 15, 27, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2120, 5, 8, 19, 15, 58, 0, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2121, 5, 8, 20, 15, 29, 1, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2122, 5, 8, 21, 15, 60, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2123, 5, 8, 22, 15, 31, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2124, 5, 8, 23, 16, 62, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2125, 5, 8, 24, 17, 33, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2126, 5, 8, 25, 18, 64, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2127, 5, 8, 26, 19, 50, 0, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2128, 5, 8, 27, 20, 36, 1, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2129, 5, 8, 28, 21, 66, 0, 1, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2130, 5, 8, 29, 22, 51, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2131, 5, 8, 30, 23, 36, 0, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2132, 5, 8, 31, 24, 66, 0, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2133, 5, 8, 32, 25, 51, 0, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2134, 5, 8, 33, 26, 36, 1, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2135, 5, 8, 34, 27, 51, 0, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2136, 5, 8, 35, 28, 51, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2137, 5, 8, 36, 29, 66, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2138, 5, 8, 37, 30, 51, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2139, 5, 8, 38, 31, 51, 1, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2140, 5, 8, 39, 32, 36, 0, 1, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2141, 5, 8, 40, 33, 51, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2142, 5, 8, 41, 34, 51, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2143, 5, 8, 42, 35, 51, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2144, 5, 8, 43, 36, 51, 0, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2145, 5, 8, 44, 37, 51, 1, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2146, 5, 8, 45, 38, 51, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2147, 5, 8, 46, 39, 51, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2148, 5, 8, 47, 40, 66, 0, 0, 0, 3, 2); +INSERT INTO `player_levelupgains` VALUES (2149, 5, 8, 48, 41, 51, 1, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2150, 5, 8, 49, 42, 36, 0, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2151, 5, 8, 50, 43, 51, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2152, 5, 8, 51, 44, 51, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2153, 5, 8, 52, 45, 51, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2154, 5, 8, 53, 46, 51, 1, 0, 1, 3, 2); +INSERT INTO `player_levelupgains` VALUES (2155, 5, 8, 54, 47, 51, 0, 0, 0, 2, 3); +INSERT INTO `player_levelupgains` VALUES (2156, 5, 8, 55, 48, 51, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2157, 5, 8, 56, 49, 51, 0, 0, 0, 3, 2); +INSERT INTO `player_levelupgains` VALUES (2158, 5, 8, 57, 50, 51, 1, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2159, 5, 8, 58, 51, 51, 0, 1, 0, 3, 3); +INSERT INTO `player_levelupgains` VALUES (2160, 5, 8, 59, 52, 51, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2162, 5, 5, 1, 15, 24, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2163, 5, 5, 2, 15, 25, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2164, 5, 5, 3, 15, 26, 1, 1, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2165, 5, 5, 4, 15, 27, 0, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2166, 5, 5, 5, 15, 28, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2167, 5, 5, 6, 15, 29, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2168, 5, 5, 7, 15, 30, 0, 1, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2169, 5, 5, 8, 15, 31, 0, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2170, 5, 5, 9, 15, 47, 1, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2171, 5, 5, 10, 15, 18, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2172, 5, 5, 11, 15, 34, 0, 1, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2173, 5, 5, 12, 15, 35, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2174, 5, 5, 13, 15, 36, 0, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2175, 5, 5, 14, 15, 37, 1, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2176, 5, 5, 15, 15, 38, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2177, 5, 5, 16, 15, 54, 0, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2178, 5, 5, 17, 15, 25, 0, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2179, 5, 5, 18, 15, 41, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2180, 5, 5, 19, 15, 42, 1, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2181, 5, 5, 20, 15, 43, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2182, 5, 5, 21, 16, 59, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2183, 5, 5, 22, 17, 30, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2184, 5, 5, 23, 18, 61, 1, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2185, 5, 5, 24, 19, 32, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2186, 5, 5, 25, 20, 63, 0, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2187, 5, 5, 26, 21, 34, 0, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2188, 5, 5, 27, 22, 65, 0, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2189, 5, 5, 28, 23, 36, 1, 1, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2190, 5, 5, 29, 24, 52, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2191, 5, 5, 30, 25, 68, 0, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2192, 5, 5, 31, 26, 39, 0, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2193, 5, 5, 32, 27, 69, 1, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2194, 5, 5, 33, 28, 54, 0, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2195, 5, 5, 34, 29, 39, 0, 1, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2196, 5, 5, 35, 30, 54, 1, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2197, 5, 5, 36, 31, 69, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2198, 5, 5, 37, 32, 54, 0, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2199, 5, 5, 38, 33, 39, 0, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2200, 5, 5, 39, 34, 54, 1, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2201, 5, 5, 40, 35, 69, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2202, 5, 5, 41, 36, 54, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2203, 5, 5, 42, 37, 54, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2204, 5, 5, 43, 38, 54, 1, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2205, 5, 5, 44, 39, 54, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2206, 5, 5, 45, 40, 54, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2207, 5, 5, 46, 41, 54, 1, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2208, 5, 5, 47, 42, 54, 0, 1, 1, 2, 3); +INSERT INTO `player_levelupgains` VALUES (2209, 5, 5, 48, 43, 54, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2210, 5, 5, 49, 44, 54, 1, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2211, 5, 5, 50, 45, 54, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2212, 5, 5, 51, 46, 54, 0, 0, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2213, 5, 5, 52, 47, 54, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2214, 5, 5, 53, 48, 54, 0, 0, 1, 2, 3); +INSERT INTO `player_levelupgains` VALUES (2215, 5, 5, 54, 49, 54, 0, 1, 0, 3, 2); +INSERT INTO `player_levelupgains` VALUES (2216, 5, 5, 55, 50, 54, 1, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2217, 5, 5, 56, 51, 54, 0, 1, 1, 2, 3); +INSERT INTO `player_levelupgains` VALUES (2218, 5, 5, 57, 52, 54, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2219, 5, 5, 58, 53, 54, 1, 1, 0, 3, 3); +INSERT INTO `player_levelupgains` VALUES (2220, 5, 5, 59, 54, 54, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2222, 5, 4, 1, 17, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2223, 5, 4, 2, 17, 0, 0, 1, 0, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2224, 5, 4, 3, 17, 0, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (2225, 5, 4, 4, 17, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2226, 5, 4, 5, 17, 0, 0, 1, 0, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2227, 5, 4, 6, 17, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2228, 5, 4, 7, 17, 0, 1, 1, 0, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2229, 5, 4, 8, 17, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2230, 5, 4, 9, 17, 0, 0, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (2231, 5, 4, 10, 17, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2232, 5, 4, 11, 17, 0, 1, 1, 0, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2233, 5, 4, 12, 17, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2234, 5, 4, 13, 17, 0, 0, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2235, 5, 4, 14, 17, 0, 1, 2, 0, 1, 0); +INSERT INTO `player_levelupgains` VALUES (2236, 5, 4, 15, 18, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2237, 5, 4, 16, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2238, 5, 4, 17, 20, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2239, 5, 4, 18, 21, 0, 1, 2, 0, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2240, 5, 4, 19, 22, 0, 0, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (2241, 5, 4, 20, 23, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2242, 5, 4, 21, 24, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2243, 5, 4, 22, 25, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2244, 5, 4, 23, 26, 0, 1, 1, 0, 1, 0); +INSERT INTO `player_levelupgains` VALUES (2245, 5, 4, 24, 27, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2246, 5, 4, 25, 28, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2247, 5, 4, 26, 29, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2248, 5, 4, 27, 30, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2249, 5, 4, 28, 31, 0, 0, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (2250, 5, 4, 29, 32, 0, 1, 2, 0, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2251, 5, 4, 30, 33, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2252, 5, 4, 31, 34, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2253, 5, 4, 32, 35, 0, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (2254, 5, 4, 33, 36, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2255, 5, 4, 34, 37, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2256, 5, 4, 35, 38, 0, 2, 2, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2257, 5, 4, 36, 39, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2258, 5, 4, 37, 40, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2259, 5, 4, 38, 41, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2260, 5, 4, 39, 42, 0, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (2261, 5, 4, 40, 43, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2262, 5, 4, 41, 44, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2263, 5, 4, 42, 45, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2264, 5, 4, 43, 46, 0, 1, 3, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (2265, 5, 4, 44, 47, 0, 2, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2266, 5, 4, 45, 48, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2267, 5, 4, 46, 49, 0, 1, 2, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (2268, 5, 4, 47, 50, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2269, 5, 4, 48, 51, 0, 1, 2, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2270, 5, 4, 49, 52, 0, 2, 3, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (2271, 5, 4, 50, 53, 0, 1, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2272, 5, 4, 51, 54, 0, 1, 2, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2273, 5, 4, 52, 55, 0, 1, 3, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2274, 5, 4, 53, 56, 0, 2, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2275, 5, 4, 54, 57, 0, 1, 2, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2276, 5, 4, 55, 58, 0, 1, 3, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2277, 5, 4, 56, 59, 0, 2, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2278, 5, 4, 57, 60, 0, 1, 3, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2279, 5, 4, 58, 61, 0, 2, 2, 2, 1, 0); +INSERT INTO `player_levelupgains` VALUES (2280, 5, 4, 59, 62, 0, 1, 3, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2282, 5, 9, 1, 15, 23, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2283, 5, 9, 2, 15, 24, 1, 1, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2284, 5, 9, 3, 15, 25, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2285, 5, 9, 4, 15, 26, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2286, 5, 9, 5, 15, 27, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2287, 5, 9, 6, 15, 28, 1, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2288, 5, 9, 7, 15, 29, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2289, 5, 9, 8, 15, 30, 0, 1, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2290, 5, 9, 9, 15, 31, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2291, 5, 9, 10, 15, 32, 0, 1, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2292, 5, 9, 11, 15, 33, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2293, 5, 9, 12, 15, 34, 1, 0, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2294, 5, 9, 13, 15, 35, 0, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2295, 5, 9, 14, 15, 36, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2296, 5, 9, 15, 15, 37, 1, 1, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2297, 5, 9, 16, 15, 38, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2298, 5, 9, 17, 16, 39, 0, 0, 0, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2299, 5, 9, 18, 17, 40, 1, 1, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2300, 5, 9, 19, 18, 41, 0, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2301, 5, 9, 20, 19, 42, 0, 1, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2302, 5, 9, 21, 20, 43, 1, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2303, 5, 9, 22, 21, 44, 0, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2304, 5, 9, 23, 22, 45, 1, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2305, 5, 9, 24, 23, 46, 0, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2306, 5, 9, 25, 24, 47, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2307, 5, 9, 26, 25, 48, 1, 0, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2308, 5, 9, 27, 26, 49, 0, 1, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2309, 5, 9, 28, 27, 50, 1, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2310, 5, 9, 29, 28, 51, 0, 1, 0, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2311, 5, 9, 30, 29, 51, 0, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2312, 5, 9, 31, 30, 51, 1, 1, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2313, 5, 9, 32, 31, 51, 0, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2314, 5, 9, 33, 32, 51, 1, 1, 0, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2315, 5, 9, 34, 33, 51, 0, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2316, 5, 9, 35, 24, 51, 1, 1, 0, 2, 3); +INSERT INTO `player_levelupgains` VALUES (2317, 5, 9, 36, 45, 51, 0, 1, 2, 2, 0); +INSERT INTO `player_levelupgains` VALUES (2318, 5, 9, 37, 36, 51, 0, 0, 1, 1, 2); +INSERT INTO `player_levelupgains` VALUES (2319, 5, 9, 38, 37, 51, 1, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2320, 5, 9, 39, 38, 51, 0, 0, 1, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2321, 5, 9, 40, 39, 51, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2322, 5, 9, 41, 30, 51, 0, 0, 0, 2, 3); +INSERT INTO `player_levelupgains` VALUES (2323, 5, 9, 42, 51, 51, 1, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2324, 5, 9, 43, 42, 51, 0, 0, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2325, 5, 9, 44, 43, 51, 1, 1, 0, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2326, 5, 9, 45, 44, 51, 0, 1, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2327, 5, 9, 46, 45, 51, 1, 0, 1, 1, 3); +INSERT INTO `player_levelupgains` VALUES (2328, 5, 9, 47, 46, 51, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2329, 5, 9, 48, 47, 51, 1, 1, 1, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2330, 5, 9, 49, 28, 51, 0, 0, 1, 2, 3); +INSERT INTO `player_levelupgains` VALUES (2331, 5, 9, 50, 59, 51, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2332, 5, 9, 51, 60, 51, 0, 0, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2333, 5, 9, 52, 51, 51, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2334, 5, 9, 53, 42, 51, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2335, 5, 9, 54, 43, 51, 0, 0, 0, 2, 3); +INSERT INTO `player_levelupgains` VALUES (2336, 5, 9, 55, 74, 51, 1, 1, 2, 2, 1); +INSERT INTO `player_levelupgains` VALUES (2337, 5, 9, 56, 55, 51, 0, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2338, 5, 9, 57, 46, 51, 1, 1, 0, 2, 3); +INSERT INTO `player_levelupgains` VALUES (2339, 5, 9, 58, 67, 51, 0, 0, 2, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2340, 5, 9, 59, 58, 51, 1, 1, 1, 2, 2); +INSERT INTO `player_levelupgains` VALUES (2342, 5, 1, 1, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2343, 5, 1, 2, 19, 0, 1, 0, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2344, 5, 1, 3, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2345, 5, 1, 4, 19, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2346, 5, 1, 5, 19, 0, 1, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (2347, 5, 1, 6, 19, 0, 1, 0, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2348, 5, 1, 7, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2349, 5, 1, 8, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2350, 5, 1, 9, 19, 0, 1, 0, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2351, 5, 1, 10, 19, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2352, 5, 1, 11, 19, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2353, 5, 1, 12, 19, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2354, 5, 1, 13, 20, 0, 2, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (2355, 5, 1, 14, 21, 0, 1, 0, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2356, 5, 1, 15, 22, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2357, 5, 1, 16, 23, 0, 1, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2358, 5, 1, 17, 24, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2359, 5, 1, 18, 25, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2360, 5, 1, 19, 26, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2361, 5, 1, 20, 27, 0, 1, 0, 2, 1, 0); +INSERT INTO `player_levelupgains` VALUES (2362, 5, 1, 21, 28, 0, 1, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2363, 5, 1, 22, 29, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2364, 5, 1, 23, 30, 0, 1, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2365, 5, 1, 24, 31, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2366, 5, 1, 25, 32, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2367, 5, 1, 26, 33, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2368, 5, 1, 27, 34, 0, 1, 1, 1, 1, 0); +INSERT INTO `player_levelupgains` VALUES (2369, 5, 1, 28, 35, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2370, 5, 1, 29, 36, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2371, 5, 1, 30, 37, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2372, 5, 1, 31, 38, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2373, 5, 1, 32, 39, 0, 1, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2374, 5, 1, 33, 40, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2375, 5, 1, 34, 41, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2376, 5, 1, 35, 42, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2377, 5, 1, 36, 44, 0, 1, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2378, 5, 1, 37, 46, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2379, 5, 1, 38, 48, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2380, 5, 1, 39, 50, 0, 2, 1, 1, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2381, 5, 1, 40, 52, 0, 1, 2, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2382, 5, 1, 41, 54, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2383, 5, 1, 42, 56, 0, 2, 1, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2384, 5, 1, 43, 58, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2385, 5, 1, 44, 60, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2386, 5, 1, 45, 62, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2387, 5, 1, 46, 64, 0, 2, 2, 1, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2388, 5, 1, 47, 66, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2389, 5, 1, 48, 68, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2390, 5, 1, 49, 70, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2391, 5, 1, 50, 72, 0, 2, 2, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2392, 5, 1, 51, 74, 0, 2, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2393, 5, 1, 52, 76, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2394, 5, 1, 53, 78, 0, 2, 2, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2395, 5, 1, 54, 80, 0, 3, 1, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2396, 5, 1, 55, 82, 0, 2, 1, 2, 0, 1); +INSERT INTO `player_levelupgains` VALUES (2397, 5, 1, 56, 84, 0, 2, 2, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2398, 5, 1, 57, 86, 0, 2, 1, 2, 1, 1); +INSERT INTO `player_levelupgains` VALUES (2399, 5, 1, 58, 88, 0, 3, 2, 2, 0, 0); +INSERT INTO `player_levelupgains` VALUES (2400, 5, 1, 59, 90, 0, 2, 1, 2, 0, 1); diff --git a/sql/updates/0.6/2308_character_pet.sql b/sql/updates/0.6/2308_character_pet.sql new file mode 100644 index 00000000000..ceabb5db108 --- /dev/null +++ b/sql/updates/0.6/2308_character_pet.sql @@ -0,0 +1,4 @@ +ALTER TABLE `character_pet` + DROP `name`, + ADD `loyalty` int(11) unsigned NOT NULL default '1', + ADD `trainpoint` int(11) unsigned NOT NULL default '0'; diff --git a/sql/updates/0.6/2330_realmlist.sql b/sql/updates/0.6/2330_realmlist.sql new file mode 100644 index 00000000000..093e9ec726b --- /dev/null +++ b/sql/updates/0.6/2330_realmlist.sql @@ -0,0 +1,2 @@ +ALTER TABLE `realmd`.`realmlist` + ADD `port` int(11) NOT NULL default '8085' AFTER `address`; diff --git a/sql/updates/0.6/2343_areatrigger_template.sql b/sql/updates/0.6/2343_areatrigger_template.sql new file mode 100644 index 00000000000..7aa606fe4a4 --- /dev/null +++ b/sql/updates/0.6/2343_areatrigger_template.sql @@ -0,0 +1,14 @@ +ALTER TABLE `character` + ADD `logout_time` int(11) NOT NULL DEFAULT '0', + ADD `is_logout_resting` int(11) NOT NULL DEFAULT '0', + ADD `rest_bonus` FLOAT NOT NULL DEFAULT '0'; + +DROP TABLE IF EXISTS `areatrigger_city`; + +ALTER TABLE `areatrigger_template` + CHANGE `name` `name` text AFTER `id`, + ADD `trigger_map` int(11) unsigned NOT NULL DEFAULT '0' AFTER `name`, + ADD `trigger_postion_x` FLOAT NOT NULL DEFAULT '0' AFTER `trigger_map`, + ADD `trigger_position_y` FLOAT NOT NULL DEFAULT '0' AFTER `trigger_postion_x`, + ADD `trigger_position_z` FLOAT NOT NULL DEFAULT '0' AFTER `trigger_position_y`, + CHANGE `target_map` `target_map` int(11) unsigned NOT NULL DEFAULT '0' AFTER `trigger_position_z`; \ No newline at end of file diff --git a/sql/updates/0.6/2352_quest_template.sql b/sql/updates/0.6/2352_quest_template.sql new file mode 100644 index 00000000000..a44b92cc012 --- /dev/null +++ b/sql/updates/0.6/2352_quest_template.sql @@ -0,0 +1,13 @@ +ALTER TABLE `quest_template` + CHANGE `ReqKillMobOrGOId1` `ReqCreatureOrGOId1` int(11) NOT NULL default '0', + CHANGE `ReqKillMobOrGOId2` `ReqCreatureOrGOId2` int(11) NOT NULL default '0', + CHANGE `ReqKillMobOrGOId3` `ReqCreatureOrGOId3` int(11) NOT NULL default '0', + CHANGE `ReqKillMobOrGOId4` `ReqCreatureOrGOId4` int(11) NOT NULL default '0', + CHANGE `ReqKillMobOrGOCount1` `ReqCreatureOrGOCount1` int(11) unsigned NOT NULL default '0', + CHANGE `ReqKillMobOrGOCount2` `ReqCreatureOrGOCount2` int(11) unsigned NOT NULL default '0', + CHANGE `ReqKillMobOrGOCount3` `ReqCreatureOrGOCount3` int(11) unsigned NOT NULL default '0', + CHANGE `ReqKillMobOrGOCount4` `ReqCreatureOrGOCount4` int(11) unsigned NOT NULL default '0', + ADD COLUMN `ReqSpellCast1` int(11) unsigned NOT NULL default '0' AFTER `ReqCreatureOrGOCount4`, + ADD COLUMN `ReqSpellCast2` int(11) unsigned NOT NULL default '0' AFTER `ReqSpellCast1`, + ADD COLUMN `ReqSpellCast3` int(11) unsigned NOT NULL default '0' AFTER `ReqSpellCast2`, + ADD COLUMN `ReqSpellCast4` int(11) unsigned NOT NULL default '0' AFTER `ReqSpellCast3`; diff --git a/sql/updates/0.6/2357_playercreateinfo_action.sql b/sql/updates/0.6/2357_playercreateinfo_action.sql new file mode 100644 index 00000000000..5e0f59e7341 --- /dev/null +++ b/sql/updates/0.6/2357_playercreateinfo_action.sql @@ -0,0 +1,13 @@ +ALTER TABLE `playercreateinfo_action` + DROP KEY `playercreateinfo_actions_index`, + ADD KEY `playercreateinfo_actions_index` (`createid`,`button`); + +UPDATE `playercreateinfo_action` + SET `type` = `misc`; +UPDATE `playercreateinfo_action` + SET `misc` = '0'; + +UPDATE `character_action` + SET `type` = `misc`; +UPDATE `character_action` + SET `misc` = '0'; diff --git a/sql/updates/0.6/2359_command.sql b/sql/updates/0.6/2359_command.sql new file mode 100644 index 00000000000..f6705a385ef --- /dev/null +++ b/sql/updates/0.6/2359_command.sql @@ -0,0 +1 @@ +INSERT INTO command VALUES('shutdown','3','Syntax: .shutdown #delay|stop\r\n\r\nShutting down server after #delay seconds or stop shutting down if stop value used.'); diff --git a/sql/updates/0.6/2360_creature_template.sql b/sql/updates/0.6/2360_creature_template.sql new file mode 100644 index 00000000000..342f4d7cac3 --- /dev/null +++ b/sql/updates/0.6/2360_creature_template.sql @@ -0,0 +1,16 @@ +ALTER TABLE `creature_template` + ADD COLUMN `MovementType` int(11) unsigned NOT NULL default '0' AFTER `MoveName`; + +UPDATE `creature_template` + SET `MovementType` = '1' WHERE `MoveName` = 'Random'; +UPDATE `creature_template` + SET `MovementType` = '2' WHERE `MoveName` = 'Waypoint'; + +ALTER TABLE `creature_template` + DROP `MoveName`; + +ALTER TABLE `creature` + ADD COLUMN `MovementType` int(11) unsigned NOT NULL default '0' AFTER `faction`; + +UPDATE `creature`, `creature_template` + SET `creature`.`MovementType` = `creature_template`.`MovementType` WHERE `creature`.`id` = `creature_template`.`entry`; diff --git a/sql/updates/0.6/2362_areatrigger_template.sql b/sql/updates/0.6/2362_areatrigger_template.sql new file mode 100644 index 00000000000..e46de1fdd6a --- /dev/null +++ b/sql/updates/0.6/2362_areatrigger_template.sql @@ -0,0 +1,2 @@ +ALTER TABLE `areatrigger_template` + CHANGE `trigger_postion_x` `trigger_position_x` FLOAT NOT NULL DEFAULT '0'; diff --git a/sql/updates/0.6/2367_command.sql b/sql/updates/0.6/2367_command.sql new file mode 100644 index 00000000000..dbd325f6fc1 --- /dev/null +++ b/sql/updates/0.6/2367_command.sql @@ -0,0 +1,2 @@ +INSERT INTO command VALUES('goxy','3','Syntax: .goxy #x #y [#mapid]\r\n\r\nTeleport player to point with (#x,#y) coordinates at ground(water) level at map #mapid or same map if #mapid not provided.'); +UPDATE command SET `help` = 'Syntax: .taxicheat #flag\r\n\r\nTemporary grant access or remove to all taxi routes for the selected character. If no character is selected, hide or reveal all routes to you.\r\n\r\nUse a #flag of value 1 to add access, use a #flag value of 0 to remove access. Visited taxi nodes sill accessible after removing access.' WHERE `name` = 'taxicheat'; diff --git a/sql/updates/0.6/2369_creature_template.sql b/sql/updates/0.6/2369_creature_template.sql new file mode 100644 index 00000000000..eea90e12f4f --- /dev/null +++ b/sql/updates/0.6/2369_creature_template.sql @@ -0,0 +1,12 @@ +ALTER TABLE `creature_template` + CHANGE `level` `minlevel` int(3) unsigned default '1', + CHANGE `level_max` `maxlevel` int(3) unsigned default '1' AFTER `minlevel`, + ADD COLUMN `minhealth` int(5) unsigned default '0' AFTER `maxlevel`, + CHANGE `maxhealth` `maxhealth` int(5) unsigned default '0' AFTER `minhealth`, + ADD COLUMN `minmana` int(5) unsigned default '0' AFTER `maxhealth`, + CHANGE `maxmana` `maxmana` int(5) unsigned default '0' AFTER `minmana`; + +UPDATE `creature_template` + SET `maxlevel` = `minlevel` WHERE `maxlevel` < `minlevel`; +UPDATE `creature_template` + SET `minhealth` = `maxhealth`, `minmana` = `maxmana`; diff --git a/sql/updates/0.6/2370_character_queststatus.sql b/sql/updates/0.6/2370_character_queststatus.sql new file mode 100644 index 00000000000..df10601cca8 --- /dev/null +++ b/sql/updates/0.6/2370_character_queststatus.sql @@ -0,0 +1,4 @@ +ALTER TABLE `character_queststatus` + CHANGE `rewarded` `rewarded` tinyint(1) unsigned NOT NULL default '0', + CHANGE `explored` `explored` tinyint(1) unsigned NOT NULL default '0', + ADD COLUMN `completed_once` tinyint(1) unsigned NOT NULL default '0' AFTER `explored`; diff --git a/sql/updates/0.6/2372_creature_template.sql b/sql/updates/0.6/2372_creature_template.sql new file mode 100644 index 00000000000..38a5dbf4276 --- /dev/null +++ b/sql/updates/0.6/2372_creature_template.sql @@ -0,0 +1,6 @@ +ALTER TABLE `creature_template` + CHANGE `maxlevel` `maxlevel` int(3) unsigned default '1' AFTER `minlevel`, + CHANGE `minhealth` `minhealth` int(5) unsigned default '0' AFTER `maxlevel`, + CHANGE `maxhealth` `maxhealth` int(5) unsigned default '0' AFTER `minhealth`, + CHANGE `minmana` `minmana` int(5) unsigned default '0' AFTER `maxhealth`, + CHANGE `maxmana` `maxmana` int(5) unsigned default '0' AFTER `minmana`; diff --git a/sql/updates/0.6/2382_mail_item.sql b/sql/updates/0.6/2382_mail_item.sql new file mode 100644 index 00000000000..a67d9b2a722 --- /dev/null +++ b/sql/updates/0.6/2382_mail_item.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS `mail_item`; diff --git a/sql/updates/0.6/2383_auctionhouse_item.sql b/sql/updates/0.6/2383_auctionhouse_item.sql new file mode 100644 index 00000000000..8b4e52a4e44 --- /dev/null +++ b/sql/updates/0.6/2383_auctionhouse_item.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS `auctionhouse_item`; diff --git a/sql/updates/0.6/2418_quest_template.sql b/sql/updates/0.6/2418_quest_template.sql new file mode 100644 index 00000000000..618a920ac9a --- /dev/null +++ b/sql/updates/0.6/2418_quest_template.sql @@ -0,0 +1,9 @@ +ALTER TABLE `quest_template` + ADD `ReqSourceId1` int(11) unsigned NOT NULL default '0' AFTER `ReqItemCount4` , + ADD `ReqSourceId2` int(11) unsigned NOT NULL default '0' AFTER `ReqSourceId1` , + ADD `ReqSourceId3` int(11) unsigned NOT NULL default '0' AFTER `ReqSourceId2` , + ADD `ReqSourceId4` int(11) unsigned NOT NULL default '0' AFTER `ReqSourceId3` , + ADD `ReqSourceRef1` int(11) unsigned NOT NULL default '0' AFTER `ReqSourceId4` , + ADD `ReqSourceRef2` int(11) unsigned NOT NULL default '0' AFTER `ReqSourceRef1` , + ADD `ReqSourceRef3` int(11) unsigned NOT NULL default '0' AFTER `ReqSourceRef2` , + ADD `ReqSourceRef4` int(11) unsigned NOT NULL default '0' AFTER `ReqSourceRef3` ; diff --git a/sql/updates/0.6/2421_quest_template.sql b/sql/updates/0.6/2421_quest_template.sql new file mode 100644 index 00000000000..68966b7fc54 --- /dev/null +++ b/sql/updates/0.6/2421_quest_template.sql @@ -0,0 +1,4 @@ +ALTER TABLE `quest_template` + ADD `DetailsEmote` int(11) NOT NULL default '0', + ADD `IncompleteEmote` int(11) NOT NULL default '0', + ADD `CompleteEmote` int(11) NOT NULL default '0'; diff --git a/sql/updates/0.6/2424_gameobject_template.sql b/sql/updates/0.6/2424_gameobject_template.sql new file mode 100644 index 00000000000..fa117ab1de2 --- /dev/null +++ b/sql/updates/0.6/2424_gameobject_template.sql @@ -0,0 +1 @@ +ALTER TABLE `gameobject_template` ADD COLUMN `castsSpell` int(11) NOT NULL default '0' AFTER `ScriptName`; \ No newline at end of file diff --git a/sql/updates/0.6/2429_taxi.sql b/sql/updates/0.6/2429_taxi.sql new file mode 100644 index 00000000000..055562ef790 --- /dev/null +++ b/sql/updates/0.6/2429_taxi.sql @@ -0,0 +1,3 @@ +DROP TABLE IF EXISTS `taxi_node`; +DROP TABLE IF EXISTS `taxi_path`; +DROP TABLE IF EXISTS `taxi_pathnode`; diff --git a/sql/updates/0.6/2445_command.sql b/sql/updates/0.6/2445_command.sql new file mode 100644 index 00000000000..799fd26448d --- /dev/null +++ b/sql/updates/0.6/2445_command.sql @@ -0,0 +1 @@ +INSERT INTO command VALUES('pinfo','2','Syntax: .pinfo [$player_name]\r\n\r\nOutput account information for selected player or player find by $player_name.'); diff --git a/sql/updates/0.6/2448_command.sql b/sql/updates/0.6/2448_command.sql new file mode 100644 index 00000000000..89e491758f8 --- /dev/null +++ b/sql/updates/0.6/2448_command.sql @@ -0,0 +1,3 @@ +DELETE FROM command WHERE `name` = 'addgrave'; +UPDATE command SET `help` = 'Syntax: .neargrave [alliance|horde]\r\n\r\nFind nearest graveyard linked to zone (or only nearest from accepts alliance or horde faction ghosts).' WHERE `name` = 'neargrave'; +UPDATE command SET `help` = 'Syntax: .linkgrave #graveyard_id [alliance|horde]\r\n\r\nLink current zone to graveyard for any (or alliance/horde faction ghosts). This let character ghost from zone teleport to graveyard after die if graveyard is nearest from linked to zone and accept ghost of this faction. Add only single graveyard at another map and only if no graveyards linked (or planned linked at same map).' WHERE `name` = 'linkgrave'; diff --git a/sql/updates/0.6/2448_game_graveyard.sql b/sql/updates/0.6/2448_game_graveyard.sql new file mode 100644 index 00000000000..3a500c2bfbe --- /dev/null +++ b/sql/updates/0.6/2448_game_graveyard.sql @@ -0,0 +1,9 @@ +ALTER TABLE `game_graveyard_zone` + ADD COLUMN `faction` int(11) unsigned NOT NULL default '0' AFTER `ghost_zone`; + +UPDATE `game_graveyard_zone`,`game_graveyard` + SET `game_graveyard_zone`.`faction` = `game_graveyard`.`faction` + WHERE `game_graveyard_zone`.`id` = `game_graveyard`.`id`; + + +DROP TABLE IF EXISTS `game_graveyard`; diff --git a/sql/updates/0.6/2454_command.sql b/sql/updates/0.6/2454_command.sql new file mode 100644 index 00000000000..e5a7764ed2f --- /dev/null +++ b/sql/updates/0.6/2454_command.sql @@ -0,0 +1 @@ +INSERT INTO command VALUES('visible','1','Syntax: .visible [0||1]\r\n\r\nOutput current visibility state or make GM visible(1) and invisible(0) for other players.'); diff --git a/sql/updates/0.6/2467_quest_template.sql b/sql/updates/0.6/2467_quest_template.sql new file mode 100644 index 00000000000..ecc129eca2b --- /dev/null +++ b/sql/updates/0.6/2467_quest_template.sql @@ -0,0 +1,2 @@ +ALTER TABLE `quest_template` + ADD `ExclusiveGroup` int(11) unsigned NOT NULL default '0' AFTER `NextQuestId`; diff --git a/sql/updates/0.6/2468_command.sql b/sql/updates/0.6/2468_command.sql new file mode 100644 index 00000000000..7c19940adf8 --- /dev/null +++ b/sql/updates/0.6/2468_command.sql @@ -0,0 +1,3 @@ +INSERT INTO command VALUES('moveobject','2','Syntax: .moveobject #goguid [#x #y #z]\r\n\r\nMove gameobject #goguid to character coordinates (or to (#x,#y,#z) coordinates if its provide).'); +INSERT INTO command VALUES('turnobject','2','Syntax: .turnobject #goguid \r\n\r\nSet for gameobject #goguid orientation same as current character orientation.'); + diff --git a/sql/updates/0.6/2469_skinning_loot_template.sql b/sql/updates/0.6/2469_skinning_loot_template.sql new file mode 100644 index 00000000000..9597c7866dc --- /dev/null +++ b/sql/updates/0.6/2469_skinning_loot_template.sql @@ -0,0 +1,50 @@ +DROP TABLE IF EXISTS `skinning_loot_template`; +CREATE TABLE `skinning_loot_template` ( + `entry` int(11) unsigned NOT NULL default '0', + `item` int(11) unsigned NOT NULL default '0', + `chance` float NOT NULL default '100', + `questchance` float NOT NULL default '0', + PRIMARY KEY (`entry`,`item`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Loot System'; + +DROP TABLE IF EXISTS `skinning_loot_template_alternative`; +CREATE TABLE `skinning_loot_template_alternative` ( + `item` int(11) unsigned NOT NULL default '0', + `item2` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`item`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Loot System'; + +update `creature_template` set `skinloot` = +case `type` + when 2 then 100001 #CREATURE_TYPE_DRAGON + when 1 then #CREATURE_TYPE_BEAST + case `family` + when 7 then 0 #CREATURE_FAMILY_CARRION_BIRD + when 26 then 0 #CREATURE_FAMILY_OWL + when 21 then 100002 #CREATURE_FAMILY_TURTLE + else if (`minlevel` > 48, 100003, + if (`minlevel` > 36, 100004, + if (`minlevel` > 25, 100005, + if (`minlevel` > 15, 100006, + if (`minlevel` > 3, 100007, + 100008 ))))) + end + else 0 +end; + +insert into `skinning_loot_template` values + (100001, 8165,100, 0), + (100002, 8167,100, 0), + (100003, 8170,100, 0), + (100004, 4304,100, 0), + (100005, 4234,100, 0), + (100006, 2319,100, 0), + (100007, 2318,100, 0), + (100008, 2934,100, 0); + +insert into `skinning_loot_template_alternative` values + (8170,8171), + (4304,8169), + (4234,8235), + (2319,4232), + (2318, 783); diff --git a/sql/updates/0.6/2479_loot_template.sql b/sql/updates/0.6/2479_loot_template.sql new file mode 100644 index 00000000000..a02e5f6bda9 --- /dev/null +++ b/sql/updates/0.6/2479_loot_template.sql @@ -0,0 +1,15 @@ +ALTER TABLE `creature_loot_template` + ADD `maxcount` int(11) unsigned NOT NULL default '1'; + +ALTER TABLE `fishing_loot_template` + ADD `maxcount` int(11) unsigned NOT NULL default '1'; + +ALTER TABLE `gameobject_loot_template` + ADD `maxcount` int(11) unsigned NOT NULL default '1'; + +ALTER TABLE `pickpocketing_loot_template` + ADD `maxcount` int(11) unsigned NOT NULL default '1'; + +ALTER TABLE `skinning_loot_template` + ADD `maxcount` int(11) unsigned NOT NULL default '1'; + diff --git a/sql/updates/0.6/2494_command.sql b/sql/updates/0.6/2494_command.sql new file mode 100644 index 00000000000..3476cc8ca10 --- /dev/null +++ b/sql/updates/0.6/2494_command.sql @@ -0,0 +1 @@ +INSERT INTO `command` VALUES ('playsound',1,'Syntax: .playsound #soundid\r\n\r\nPlay sound with #soundid.\r\nSound will be play only for you. Other players do not hear this.\r\nWarning: client may have more 5000 sounds...'); diff --git a/sql/updates/0.6/2495_item_loot_template.sql b/sql/updates/0.6/2495_item_loot_template.sql new file mode 100644 index 00000000000..2c9af1cd7d6 --- /dev/null +++ b/sql/updates/0.6/2495_item_loot_template.sql @@ -0,0 +1,8 @@ +CREATE TABLE `item_loot_template` ( + `entry` int(11) unsigned NOT NULL default '0', + `item` int(11) unsigned NOT NULL default '0', + `chance` float NOT NULL default '100', + `questchance` float NOT NULL default '0', + `maxcount` int(11) unsigned NOT NULL default '1', + PRIMARY KEY (`entry`,`item`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Loot System'; diff --git a/sql/updates/0.6/2500_command.sql b/sql/updates/0.6/2500_command.sql new file mode 100644 index 00000000000..38b3b8af61d --- /dev/null +++ b/sql/updates/0.6/2500_command.sql @@ -0,0 +1 @@ +INSERT INTO `command` VALUES('lookupitem',3,'Syntax: .lookupitem $itemname\r\n\r\nLooks up an item by $itemname, and returns all matches with their Item ID\'s.'); diff --git a/sql/updates/0.6/2513_guild_rank.sql b/sql/updates/0.6/2513_guild_rank.sql new file mode 100644 index 00000000000..39c0ce7486d --- /dev/null +++ b/sql/updates/0.6/2513_guild_rank.sql @@ -0,0 +1,3 @@ +ALTER TABLE `guild_rank` + ADD `rid` int(11) unsigned NOT NULL AFTER `guildid`, + ADD PRIMARY KEY (`guildid`,`rid`); \ No newline at end of file diff --git a/sql/updates/0.6/2516_auctionhouse.sql b/sql/updates/0.6/2516_auctionhouse.sql new file mode 100644 index 00000000000..fe9e30a912a --- /dev/null +++ b/sql/updates/0.6/2516_auctionhouse.sql @@ -0,0 +1,5 @@ +DELETE FROM `auctionhouse`; +ALTER TABLE `auctionhouse` + DROP `id`, + ADD `id` bigint(20) unsigned NOT NULL default '0' FIRST, + ADD `location` tinyint(3) unsigned NOT NULL default '3'; diff --git a/sql/updates/0.6/2517_guild_charters.sql b/sql/updates/0.6/2517_guild_charters.sql new file mode 100644 index 00000000000..249842569d5 --- /dev/null +++ b/sql/updates/0.6/2517_guild_charters.sql @@ -0,0 +1,16 @@ +DROP TABLE IF EXISTS `guild_charter`; +CREATE TABLE `guild_charter` ( + `ownerguid` int(10) unsigned NOT NULL, + `charterguid` int(10) unsigned default '0', + `guildname` varchar(255) NOT NULL default '', + PRIMARY KEY (`ownerguid`), + UNIQUE KEY `index_ownerguid_charterguid` (`ownerguid`,`charterguid`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Guild System'; + +DROP TABLE IF EXISTS `guild_charter_sign`; +CREATE TABLE `guild_charter_sign` ( + `ownerguid` int(10) unsigned NOT NULL, + `charterguid` int(11) unsigned default '0', + `playerguid` int(11) unsigned default '0', + PRIMARY KEY (`charterguid`,`playerguid`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Guild System'; diff --git a/sql/updates/0.6/2518_guild.sql b/sql/updates/0.6/2518_guild.sql new file mode 100644 index 00000000000..04b84e3ebe4 --- /dev/null +++ b/sql/updates/0.6/2518_guild.sql @@ -0,0 +1,2 @@ +ALTER TABLE `guild` + ADD `info` TEXT NOT NULL AFTER `BackgroundColor` ; diff --git a/sql/updates/0.6/2530_loot_template.sql b/sql/updates/0.6/2530_loot_template.sql new file mode 100644 index 00000000000..5e21bcc2919 --- /dev/null +++ b/sql/updates/0.6/2530_loot_template.sql @@ -0,0 +1,6 @@ +ALTER TABLE creature_loot_template ADD COLUMN quest_freeforall int(1) unsigned NOT NULL default '1' AFTER `maxcount`; +ALTER TABLE gameobject_loot_template ADD COLUMN quest_freeforall int(1) unsigned NOT NULL default '1' AFTER `maxcount`; +ALTER TABLE fishing_loot_template ADD COLUMN quest_freeforall int(1) unsigned NOT NULL default '1' AFTER `maxcount`; +ALTER TABLE item_loot_template ADD COLUMN quest_freeforall int(1) unsigned NOT NULL default '1' AFTER `maxcount`; +ALTER TABLE pickpocketing_loot_template ADD COLUMN quest_freeforall int(1) unsigned NOT NULL default '1' AFTER `maxcount`; +ALTER TABLE skinning_loot_template ADD COLUMN quest_freeforall int(1) unsigned NOT NULL default '1' AFTER `maxcount`; \ No newline at end of file diff --git a/sql/updates/0.6/2549_character.sql b/sql/updates/0.6/2549_character.sql new file mode 100644 index 00000000000..f9acf66e61a --- /dev/null +++ b/sql/updates/0.6/2549_character.sql @@ -0,0 +1 @@ +UPDATE `character` SET `name` = CONCAT(UCASE(SUBSTRING(`name`,1,1)),LCASE(SUBSTRING(`name`,2))); diff --git a/sql/updates/0.6/2571_quest_template.sql b/sql/updates/0.6/2571_quest_template.sql new file mode 100644 index 00000000000..afcbec1a017 --- /dev/null +++ b/sql/updates/0.6/2571_quest_template.sql @@ -0,0 +1,3 @@ +ALTER TABLE `quest_template` + CHANGE `srcItem` `SrcItemId` int(11) unsigned NOT NULL default '0', + ADD `SrcSpell` int(11) unsigned NOT NULL default '0' AFTER `SrcItemCount`; diff --git a/sql/updates/0.6/2572_creature_template.sql b/sql/updates/0.6/2572_creature_template.sql new file mode 100644 index 00000000000..dee36d658ad --- /dev/null +++ b/sql/updates/0.6/2572_creature_template.sql @@ -0,0 +1,3 @@ +ALTER TABLE `creature_template` + CHANGE `modelid` `modelid_m` int(11) unsigned default '0', + ADD `modelid_f` int(11) unsigned default '0' AFTER `modelid_m`; diff --git a/sql/updates/0.6/2578_character.sql b/sql/updates/0.6/2578_character.sql new file mode 100644 index 00000000000..d5501c91e3f --- /dev/null +++ b/sql/updates/0.6/2578_character.sql @@ -0,0 +1,3 @@ +ALTER TABLE `character` + ADD `resettalents_cost` int(11) unsigned NOT NULL default '0', + ADD `resettalents_time` bigint(20) unsigned NOT NULL default '0'; diff --git a/sql/updates/0.6/2580_character.sql b/sql/updates/0.6/2580_character.sql new file mode 100644 index 00000000000..23103a40748 --- /dev/null +++ b/sql/updates/0.6/2580_character.sql @@ -0,0 +1,2 @@ +ALTER TABLE `character` + ADD `instanceid` int(11) unsigned NOT NULL default '0' AFTER `map`; diff --git a/sql/updates/0.6/2580_insatne.sql b/sql/updates/0.6/2580_insatne.sql new file mode 100644 index 00000000000..966f04a2a23 --- /dev/null +++ b/sql/updates/0.6/2580_insatne.sql @@ -0,0 +1,10 @@ +DROP TABLE IF EXISTS `instance`; +CREATE TABLE `instance` ( + `id` int(11) unsigned NOT NULL default '0' COMMENT 'instance id', + `mapid` int(11) unsigned NOT NULL default '0' COMMENT 'real mapid', + `state` int(11) NOT NULL default '0' COMMENT 'this instance state', + `players` int(11) NOT NULL COMMENT 'map creater guid who in this instance', + `lefttime` int(11) NOT NULL default '0' COMMENT 'this instance left time', + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + diff --git a/sql/updates/0.6/2584_character.sql b/sql/updates/0.6/2584_character.sql new file mode 100644 index 00000000000..7b534c44ede --- /dev/null +++ b/sql/updates/0.6/2584_character.sql @@ -0,0 +1,2 @@ +ALTER TABLE `character` + DROP `instanceid`; diff --git a/sql/updates/0.6/2584_instance.sql b/sql/updates/0.6/2584_instance.sql new file mode 100644 index 00000000000..1625876dd01 --- /dev/null +++ b/sql/updates/0.6/2584_instance.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS `instance`; \ No newline at end of file diff --git a/sql/updates/0.6/2597_playercreateinfo_action.sql b/sql/updates/0.6/2597_playercreateinfo_action.sql new file mode 100644 index 00000000000..7af5626fd79 --- /dev/null +++ b/sql/updates/0.6/2597_playercreateinfo_action.sql @@ -0,0 +1,13 @@ +ALTER TABLE `playercreateinfo_action` + ADD `race` tinyint(3) unsigned NOT NULL default '0' FIRST, + ADD `class` tinyint(3) unsigned NOT NULL default '0' AFTER `race`; + +UPDATE `playercreateinfo_action`,`playercreateinfo` + SET `playercreateinfo_action`.`race` = `playercreateinfo`.`race`, + `playercreateinfo_action`.`class` = `playercreateinfo`.`class` + WHERE `playercreateinfo_action`.`createid` = `playercreateinfo`.`createid`; + +ALTER TABLE `playercreateinfo_action` + DROP KEY `playercreateinfo_actions_index`, + DROP `createid`, + ADD KEY `playercreateinfo_race_class_index` (`race`,`class`); diff --git a/sql/updates/0.6/2597_playercreateinfo_item.sql b/sql/updates/0.6/2597_playercreateinfo_item.sql new file mode 100644 index 00000000000..9530deb8594 --- /dev/null +++ b/sql/updates/0.6/2597_playercreateinfo_item.sql @@ -0,0 +1,16 @@ +ALTER TABLE `playercreateinfo_item` + ADD `race` tinyint(3) unsigned NOT NULL default '0' FIRST, + ADD `class` tinyint(3) unsigned NOT NULL default '0' AFTER `race`; + +UPDATE `playercreateinfo_item`,`playercreateinfo` + SET `playercreateinfo_item`.`race` = `playercreateinfo`.`race`, + `playercreateinfo_item`.`class` = `playercreateinfo`.`class` + WHERE `playercreateinfo_item`.`createid` = `playercreateinfo`.`createid`; + +ALTER TABLE `playercreateinfo_item` + DROP KEY `playercreateinfo_items_index`, + DROP `createid`, + DROP `bagIndex`, + DROP `slot`, + ADD KEY `playercreateinfo_race_class_index` (`race`,`class`); + \ No newline at end of file diff --git a/sql/updates/0.6/2597_playercreateinfo_reputation.sql b/sql/updates/0.6/2597_playercreateinfo_reputation.sql new file mode 100644 index 00000000000..0368bb593cd --- /dev/null +++ b/sql/updates/0.6/2597_playercreateinfo_reputation.sql @@ -0,0 +1,14 @@ +ALTER TABLE `playercreateinfo_reputation` + ADD `race` tinyint(3) unsigned NOT NULL default '0' FIRST, + ADD `class` tinyint(3) unsigned NOT NULL default '0' AFTER `race`; + +UPDATE `playercreateinfo_reputation`,`playercreateinfo` + SET `playercreateinfo_reputation`.`race` = `playercreateinfo`.`race`, + `playercreateinfo_reputation`.`class` = `playercreateinfo`.`class` + WHERE `playercreateinfo_reputation`.`createid` = `playercreateinfo`.`createid`; + +ALTER TABLE `playercreateinfo_reputation` + DROP KEY `playercreateinfo_reputation_index`, + DROP `createid`, + ADD KEY `playercreateinfo_race_class_index` (`race`,`class`); + \ No newline at end of file diff --git a/sql/updates/0.6/2597_playercreateinfo_skill.sql b/sql/updates/0.6/2597_playercreateinfo_skill.sql new file mode 100644 index 00000000000..7d68bc9eb3a --- /dev/null +++ b/sql/updates/0.6/2597_playercreateinfo_skill.sql @@ -0,0 +1,14 @@ +ALTER TABLE `playercreateinfo_skill` + ADD `race` tinyint(3) unsigned NOT NULL default '0' FIRST, + ADD `class` tinyint(3) unsigned NOT NULL default '0' AFTER `race`; + +UPDATE `playercreateinfo_skill`,`playercreateinfo` + SET `playercreateinfo_skill`.`race` = `playercreateinfo`.`race`, + `playercreateinfo_skill`.`class` = `playercreateinfo`.`class` + WHERE `playercreateinfo_skill`.`createid` = `playercreateinfo`.`createid`; + +ALTER TABLE `playercreateinfo_skill` + DROP PRIMARY KEY, + DROP `createid`, + ADD PRIMARY KEY (`race`,`class`,`Skill`); + \ No newline at end of file diff --git a/sql/updates/0.6/2597_playercreateinfo_spell.sql b/sql/updates/0.6/2597_playercreateinfo_spell.sql new file mode 100644 index 00000000000..44e20d49f74 --- /dev/null +++ b/sql/updates/0.6/2597_playercreateinfo_spell.sql @@ -0,0 +1,14 @@ +ALTER TABLE `playercreateinfo_spell` + ADD `race` tinyint(3) unsigned NOT NULL default '0' FIRST, + ADD `class` tinyint(3) unsigned NOT NULL default '0' AFTER `race`; + +UPDATE `playercreateinfo_spell`,`playercreateinfo` + SET `playercreateinfo_spell`.`race` = `playercreateinfo`.`race`, + `playercreateinfo_spell`.`class` = `playercreateinfo`.`class` + WHERE `playercreateinfo_spell`.`createid` = `playercreateinfo`.`createid`; + +ALTER TABLE `playercreateinfo_spell` + DROP PRIMARY KEY, + DROP `createid`, + ADD PRIMARY KEY (`race`,`class`,`Spell`); + \ No newline at end of file diff --git a/sql/updates/0.6/2598_playercreateinfo.sql b/sql/updates/0.6/2598_playercreateinfo.sql new file mode 100644 index 00000000000..fd4d81d03ff --- /dev/null +++ b/sql/updates/0.6/2598_playercreateinfo.sql @@ -0,0 +1,6 @@ +ALTER TABLE `playercreateinfo` + DROP KEY `playercreateinfo_index`, + DROP PRIMARY KEY , + DROP `createId` , + ADD PRIMARY KEY `playercreateinfo_race_class_index` (`race`,`class`) ; + \ No newline at end of file diff --git a/sql/updates/0.6/2605_realmd_account.sql b/sql/updates/0.6/2605_realmd_account.sql new file mode 100644 index 00000000000..426fc2bb623 --- /dev/null +++ b/sql/updates/0.6/2605_realmd_account.sql @@ -0,0 +1,3 @@ +ALTER TABLE `realmd`.`account` + ADD `v` longtext AFTER `sessionkey`, + ADD `s` longtext AFTER `v`; \ No newline at end of file diff --git a/sql/updates/0.6/2610_character.sql b/sql/updates/0.6/2610_character.sql new file mode 100644 index 00000000000..c894767eb28 --- /dev/null +++ b/sql/updates/0.6/2610_character.sql @@ -0,0 +1 @@ +UPDATE `character` SET `logout_time` = '0', `rest_bonus` = '0'; diff --git a/sql/updates/0.6/2617_character_spell_cooldown.sql b/sql/updates/0.6/2617_character_spell_cooldown.sql new file mode 100644 index 00000000000..e41333ac911 --- /dev/null +++ b/sql/updates/0.6/2617_character_spell_cooldown.sql @@ -0,0 +1,9 @@ +DROP TABLE IF EXISTS `character_spell_cooldown`; +CREATE TABLE `character_spell_cooldown` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier, Low part', + `spell` int(11) unsigned NOT NULL default '0' COMMENT 'Spell Identifier', + `time` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`,`spell`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + diff --git a/sql/updates/0.6/2622_character.sql b/sql/updates/0.6/2622_character.sql new file mode 100644 index 00000000000..a4660480722 --- /dev/null +++ b/sql/updates/0.6/2622_character.sql @@ -0,0 +1,5 @@ +ALTER TABLE `character` ADD COLUMN `trans_x` float NOT NULL default '0'; +ALTER TABLE `character` ADD COLUMN `trans_y` float NOT NULL default '0'; +ALTER TABLE `character` ADD COLUMN `trans_z` float NOT NULL default '0'; +ALTER TABLE `character` ADD COLUMN `trans_o` float NOT NULL default '0'; +ALTER TABLE `character` ADD COLUMN `transguid` bigint(20) unsigned NOT NULL default '0'; diff --git a/sql/updates/0.6/2622_gameobject.sql b/sql/updates/0.6/2622_gameobject.sql new file mode 100644 index 00000000000..38822afd629 --- /dev/null +++ b/sql/updates/0.6/2622_gameobject.sql @@ -0,0 +1 @@ +ALTER TABLE gameobject ADD COLUMN `animprogress` int(11) unsigned NOT NULL default '0'; diff --git a/sql/updates/0.6/2622_transports.sql b/sql/updates/0.6/2622_transports.sql new file mode 100644 index 00000000000..471c7e2d9b5 --- /dev/null +++ b/sql/updates/0.6/2622_transports.sql @@ -0,0 +1,8 @@ +DROP TABLE IF EXISTS `transports`; +CREATE TABLE `transports` ( + `entry` int(11) unsigned NOT NULL default '0', + `name` text, + `period` int(11) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Transports'; + diff --git a/sql/updates/0.6/2630_command.sql b/sql/updates/0.6/2630_command.sql new file mode 100644 index 00000000000..c87fb272010 --- /dev/null +++ b/sql/updates/0.6/2630_command.sql @@ -0,0 +1 @@ +UPDATE `command` SET `help` = 'Syntax: .revive [$playername]\r\n\r\n Revive specified or selected player. If no player is selected, it will revive you.' WHERE `name` = 'revive'; diff --git a/sql/updates/0.6/2633_character_spell_cooldown.sql b/sql/updates/0.6/2633_character_spell_cooldown.sql new file mode 100644 index 00000000000..45a4e963208 --- /dev/null +++ b/sql/updates/0.6/2633_character_spell_cooldown.sql @@ -0,0 +1,2 @@ +ALTER TABLE `character_spell_cooldown` + CHANGE `time` `time` bigint(20) unsigned NOT NULL default '0'; diff --git a/sql/updates/0.6/2637_auctionhouse.sql b/sql/updates/0.6/2637_auctionhouse.sql new file mode 100644 index 00000000000..01b5c09ea73 --- /dev/null +++ b/sql/updates/0.6/2637_auctionhouse.sql @@ -0,0 +1,6 @@ +ALTER TABLE `auctionhouse` + ADD `item_template` int(11) unsigned NOT NULL default '0' AFTER `itemguid`; + +UPDATE `auctionhouse`,`item_instance` + SET `item_template` = SUBSTRING_INDEX(SUBSTRING_INDEX(`data`,' ',4),' ',-1) + WHERE `auctionhouse`.`itemguid` = `item_instance`.`guid`; diff --git a/sql/updates/0.6/2637_mail.sql b/sql/updates/0.6/2637_mail.sql new file mode 100644 index 00000000000..3727fc1384d --- /dev/null +++ b/sql/updates/0.6/2637_mail.sql @@ -0,0 +1,7 @@ +ALTER TABLE `mail` + ADD `item_template` int(11) unsigned NOT NULL default '0' AFTER `item`; + +UPDATE `mail`,`item_instance` + SET `item_template` = SUBSTRING_INDEX(SUBSTRING_INDEX(`data`,' ',4),' ',-1) + WHERE `mail`.`item` = `item_instance`.`guid`; + diff --git a/sql/updates/0.6/2641_command.sql b/sql/updates/0.6/2641_command.sql new file mode 100644 index 00000000000..09cc11e2cd6 --- /dev/null +++ b/sql/updates/0.6/2641_command.sql @@ -0,0 +1,2 @@ +INSERT INTO `command` VALUES('lookupmob',3,'Syntax: .lookupmob $namepart\r\n\r\nLooks up a creature by $namepart, and returns all matches with their creature ID\'s.'); +INSERT INTO `command` VALUES('lookupskill',3,'Syntax: .lookupskill $$namepart\r\n\r\nLooks up a skill by $namepart, and returns all matches with their skill ID\'s.'); diff --git a/sql/updates/0.6/2642_loot_template.sql b/sql/updates/0.6/2642_loot_template.sql new file mode 100644 index 00000000000..74dfb12a97f --- /dev/null +++ b/sql/updates/0.6/2642_loot_template.sql @@ -0,0 +1,34 @@ +ALTER TABLE `creature_loot_template` + CHANGE `chance` `ChanceOrRef` float NOT NULL default '100', + CHANGE `questchance` `QuestChanceOrGroup` tinyint(3) NOT NULL default '0'; + +ALTER TABLE `fishing_loot_template` + CHANGE `chance` `ChanceOrRef` float NOT NULL default '100', + CHANGE `questchance` `QuestChanceOrGroup` tinyint(3) NOT NULL default '0'; + +ALTER TABLE `gameobject_loot_template` + CHANGE `chance` `ChanceOrRef` float NOT NULL default '100', + CHANGE `questchance` `QuestChanceOrGroup` tinyint(3) NOT NULL default '0'; + +ALTER TABLE `item_loot_template` + CHANGE `chance` `ChanceOrRef` float NOT NULL default '100', + CHANGE `questchance` `QuestChanceOrGroup` tinyint(3) NOT NULL default '0'; + +ALTER TABLE `pickpocketing_loot_template` + CHANGE `chance` `ChanceOrRef` float NOT NULL default '100', + CHANGE `questchance` `QuestChanceOrGroup` tinyint(3) NOT NULL default '0'; + +ALTER TABLE `skinning_loot_template` + CHANGE `chance` `ChanceOrRef` float NOT NULL default '100', + CHANGE `questchance` `QuestChanceOrGroup` tinyint(3) NOT NULL default '0'; + +UPDATE `skinning_loot_template`,`skinning_loot_template_alternative` + SET `QuestChanceOrGroup` = '-1',`ChanceOrRef` = '80' + WHERE `skinning_loot_template`.`item` = `skinning_loot_template_alternative`.`item`; + +INSERT INTO `skinning_loot_template` + SELECT `skinning_loot_template`.`entry`, `skinning_loot_template_alternative`.`item2`, '20', '-1', `skinning_loot_template`.`maxcount`, '1' + FROM `skinning_loot_template`,`skinning_loot_template_alternative` + WHERE `skinning_loot_template`.`item` = `skinning_loot_template_alternative`.`item`; + +DROP TABLE `skinning_loot_template_alternative`; diff --git a/sql/updates/0.6/2649_command.sql b/sql/updates/0.6/2649_command.sql new file mode 100644 index 00000000000..08e2425d039 --- /dev/null +++ b/sql/updates/0.6/2649_command.sql @@ -0,0 +1,2 @@ +INSERT INTO `command` VALUES('saveall',1,'Syntax: .saveallr\n\r\nSave all characters in game.'); + diff --git a/sql/updates/0.6/2660_command.sql b/sql/updates/0.6/2660_command.sql new file mode 100644 index 00000000000..9a6b1281cf8 --- /dev/null +++ b/sql/updates/0.6/2660_command.sql @@ -0,0 +1,5 @@ +UPDATE `command` SET `help` = 'Syntax: .saveall\r\n\r\nSave all characters in game.' WHERE `name` = 'saveall'; +UPDATE `command` SET `help` = 'Syntax: .recall $place\r\n\r\nTeleport you to various towns around the world. $place defines the target location. Available places include sunr, thun, cross, orgr, neth, thel, storm, iron, under, and darn.' WHERE `name` = 'recall'; +UPDATE `command` SET `help` = 'Syntax: .createguild $GuildName $GuildLeaderName\r\n\r\nCreate a guild named $GuildName with the player $GuildLeaderName as leader.' WHERE `name` = 'createguild'; + + diff --git a/sql/updates/0.6/2663_command.sql b/sql/updates/0.6/2663_command.sql new file mode 100644 index 00000000000..3458a4ad782 --- /dev/null +++ b/sql/updates/0.6/2663_command.sql @@ -0,0 +1,2 @@ +UPDATE command SET help=replace(help,"Usage:","Syntax:") WHERE left(help,6)="Usage:"; + diff --git a/sql/updates/0.6/2670_command.sql b/sql/updates/0.6/2670_command.sql new file mode 100644 index 00000000000..a63b725332a --- /dev/null +++ b/sql/updates/0.6/2670_command.sql @@ -0,0 +1,8 @@ +DELETE FROM `command` WHERE `name` = 'modify gold'; +INSERT INTO `command` VALUES('modify money',1,'Syntax:\r\n.modify money #money\r\n.money #money\r\n\r\nAdd or remove money to the selected player. If no player is selected, modify your money.\r\n\r\n #gold can be negative to remove money.'); +INSERT INTO `command` VALUES('money',1,'Syntax:\r\n.modify money #money\r\n.money #money\r\n\r\nAdd or remove money to the selected player. If no player is selected, modify your money.\r\n\r\n #gold can be negative to remove money.'); +UPDATE `command` SET `help` = 'Syntax:\r\n.modify speed #speed\r\n.speed #speed\r\n\r\nModify the running speed of the selected player. If no player is selected, modify your speed.\r\n\r\n #speed may range from 0 to 50.' WHERE `name` = 'modify speed'; +INSERT INTO `command` VALUES('speed',1,'Syntax:\r\n.modify speed #speed\r\n.speed #speed\r\n\r\nModify the running speed of the selected player. If no player is selected, modify your speed.\r\n\r\n #speed may range from 0 to 50.'); +DELETE FROM `command` WHERE `name` = 'lookupmob'; +INSERT INTO `command` VALUES('lookupcreature',3,'Syntax: .lookupcreature $namepart\r\n\r\nLooks up a creature by $namepart, and returns all matches with their creature ID\'s.'); + diff --git a/sql/updates/0.6/2674_quest_template.sql b/sql/updates/0.6/2674_quest_template.sql new file mode 100644 index 00000000000..402dc8cb593 --- /dev/null +++ b/sql/updates/0.6/2674_quest_template.sql @@ -0,0 +1,11 @@ +alter table quest_template +add column + `OfferRewardEmote` int(11) unsigned NOT NULL default '0'; + +alter table quest_template +add column + `RequestItemsEmote` int(11) unsigned NOT NULL default '1'; + +alter table quest_template +add column + `CompleteScript` int(11) unsigned NOT NULL default '0'; diff --git a/sql/updates/0.6/2674_scripts.sql b/sql/updates/0.6/2674_scripts.sql new file mode 100644 index 00000000000..d5fa11d293e --- /dev/null +++ b/sql/updates/0.6/2674_scripts.sql @@ -0,0 +1,13 @@ +DROP TABLE IF EXISTS `scripts`; +CREATE TABLE `scripts` ( + `id` int(11) unsigned NOT NULL default '0', + `delay` int(11) unsigned NOT NULL default '0', + `command` int(11) unsigned NOT NULL default '0', + `datalong` int(11) unsigned NOT NULL default '0', + `datalong2` int(11) unsigned NOT NULL default '0', + `datatext` text NOT NULL default "", + `x` float NOT NULL default '0', + `y` float NOT NULL default '0', + `z` float NOT NULL default '0', + `o` float NOT NULL default '0' +); diff --git a/sql/updates/0.6/2680_game_addons.sql b/sql/updates/0.6/2680_game_addons.sql new file mode 100644 index 00000000000..6a54527644a --- /dev/null +++ b/sql/updates/0.6/2680_game_addons.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS `game_addons`; diff --git a/sql/updates/0.6/2684_gameobject.sql b/sql/updates/0.6/2684_gameobject.sql new file mode 100644 index 00000000000..e5ce705d550 --- /dev/null +++ b/sql/updates/0.6/2684_gameobject.sql @@ -0,0 +1,4 @@ +alter table gameobject + add column + `dynflags` int(11) unsigned NOT NULL default '0'; + \ No newline at end of file diff --git a/sql/updates/0.6/2684_quest_template.sql b/sql/updates/0.6/2684_quest_template.sql new file mode 100644 index 00000000000..bf2c1852276 --- /dev/null +++ b/sql/updates/0.6/2684_quest_template.sql @@ -0,0 +1,13 @@ +alter table quest_template + add column + `HaveQuestId` int(11) unsigned NOT NULL default '0'; + +alter table quest_template + change column `IncompleteText` `RequestItemsText` text; + +alter table quest_template + change column `CompletionText` `OfferRewardText` text; + +alter table quest_template + add column + `Repeatable` int(11) unsigned NOT NULL default '0'; diff --git a/sql/updates/0.6/2688_command.sql b/sql/updates/0.6/2688_command.sql new file mode 100644 index 00000000000..3f61c87955b --- /dev/null +++ b/sql/updates/0.6/2688_command.sql @@ -0,0 +1,2 @@ +UPDATE `command` SET `help` = 'Syntax: .levelup #numberoflevels\r\n\r\nIncrease/decrease the level of the selected character by #numberoflevels. If #numberoflevels is omitted, the level will be increase by 1. If #numberoflevels is 0, the same level will be restarted. If no character is selected, increase your level. All stats and dependent values recalculated. At level decrease talents can be reset if need. Also at level decrease equipped items with greater level requirement can be lost.' WHERE `name` = 'levelup'; +UPDATE `command` SET `help` = 'Syntax:\r\n.reset level\r\n Reset level to 1 including reset stats and talents. Equipped items with greater level requirement can be lost.\r\n.reset spells\r\n Removes all non-original spells from spellbook.\r\n.reset stats\r\n Resets(recalculate) all stats of the targeted player to their original values at current level.\r\n.reset talents\r\n Removes all talents of the targeted player.' WHERE `name` = 'reset'; diff --git a/sql/updates/0.6/2688_player_levelstats.sql b/sql/updates/0.6/2688_player_levelstats.sql new file mode 100644 index 00000000000..0e5049686be --- /dev/null +++ b/sql/updates/0.6/2688_player_levelstats.sql @@ -0,0 +1,2422 @@ +-- ---------------------------- +-- Table structure for player_levelstats +-- ---------------------------- +DROP TABLE IF EXISTS `player_levelstats`; +CREATE TABLE `player_levelstats` ( + `race` tinyint(3) unsigned NOT NULL, + `class` tinyint(3) unsigned NOT NULL, + `level` tinyint(3) unsigned NOT NULL, + `hp` smallint(5) unsigned NOT NULL, + `mana` smallint(5) unsigned NOT NULL, + `str` tinyint(3) unsigned NOT NULL, + `agi` tinyint(3) unsigned NOT NULL, + `sta` tinyint(3) unsigned NOT NULL, + `int` tinyint(3) unsigned NOT NULL, + `spi` tinyint(3) unsigned NOT NULL, + PRIMARY KEY (`race`,`class`,`level`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 PACK_KEYS=0 COMMENT='Stores levels stats.'; + +-- ---------------------------- +-- Records +-- ---------------------------- +INSERT INTO `player_levelstats` VALUES +('1', '1', '1', '60', '0', '23', '20', '22', '21', '20'), +('1', '1', '2', '79', '0', '24', '21', '23', '20', '21'), +('1', '1', '3', '98', '0', '25', '21', '24', '20', '22'), +('1', '1', '4', '117', '0', '26', '22', '25', '20', '22'), +('1', '1', '5', '136', '0', '28', '23', '26', '20', '22'), +('1', '1', '6', '155', '0', '29', '24', '27', '21', '22'), +('1', '1', '7', '174', '0', '30', '24', '28', '21', '23'), +('1', '1', '8', '193', '0', '31', '25', '29', '21', '23'), +('1', '1', '9', '212', '0', '32', '26', '30', '21', '23'), +('1', '1', '10', '231', '0', '33', '26', '31', '21', '24'), +('1', '1', '11', '250', '0', '35', '27', '33', '21', '24'), +('1', '1', '12', '269', '0', '36', '28', '34', '21', '24'), +('1', '1', '13', '288', '0', '37', '29', '35', '21', '25'), +('1', '1', '14', '308', '0', '39', '30', '36', '22', '25'), +('1', '1', '15', '329', '0', '40', '30', '37', '22', '25'), +('1', '1', '16', '351', '0', '41', '31', '38', '22', '26'), +('1', '1', '17', '374', '0', '42', '32', '40', '22', '26'), +('1', '1', '18', '398', '0', '44', '33', '41', '22', '26'), +('1', '1', '19', '398', '0', '44', '33', '41', '22', '26'), +('1', '1', '20', '449', '0', '47', '35', '43', '22', '27'), +('1', '1', '21', '476', '0', '48', '35', '45', '23', '27'), +('1', '1', '22', '504', '0', '49', '36', '46', '23', '28'), +('1', '1', '23', '533', '0', '51', '37', '47', '23', '28'), +('1', '1', '24', '563', '0', '52', '38', '49', '23', '29'), +('1', '1', '25', '594', '0', '54', '39', '50', '23', '29'), +('1', '1', '26', '626', '0', '55', '40', '51', '23', '29'), +('1', '1', '27', '659', '0', '57', '41', '53', '23', '30'), +('1', '1', '28', '693', '0', '58', '42', '54', '24', '30'), +('1', '1', '29', '728', '0', '60', '43', '56', '24', '31'), +('1', '1', '30', '764', '0', '62', '44', '57', '24', '31'), +('1', '1', '31', '801', '0', '63', '45', '58', '24', '31'), +('1', '1', '32', '839', '0', '65', '46', '60', '24', '32'), +('1', '1', '33', '878', '0', '66', '47', '61', '24', '32'), +('1', '1', '34', '918', '0', '68', '48', '63', '25', '33'), +('1', '1', '35', '959', '0', '70', '49', '64', '25', '33'), +('1', '1', '36', '1001', '0', '72', '50', '66', '25', '34'), +('1', '1', '37', '1045', '0', '73', '51', '68', '25', '34'), +('1', '1', '38', '1091', '0', '75', '52', '69', '25', '34'), +('1', '1', '39', '1139', '0', '77', '53', '71', '26', '35'), +('1', '1', '40', '1189', '0', '79', '54', '72', '26', '35'), +('1', '1', '41', '1241', '0', '80', '56', '74', '26', '36'), +('1', '1', '42', '1295', '0', '82', '57', '76', '26', '36'), +('1', '1', '43', '1351', '0', '84', '58', '77', '26', '37'), +('1', '1', '44', '1409', '0', '86', '59', '79', '26', '37'), +('1', '1', '45', '1469', '0', '88', '60', '81', '27', '38'), +('1', '1', '46', '1531', '0', '90', '61', '83', '27', '38'), +('1', '1', '47', '1595', '0', '92', '63', '84', '27', '39'), +('1', '1', '48', '1661', '0', '94', '64', '86', '27', '39'), +('1', '1', '49', '1729', '0', '96', '65', '88', '28', '40'), +('1', '1', '50', '1799', '0', '98', '66', '90', '28', '40'), +('1', '1', '51', '1871', '0', '100', '68', '92', '28', '42'), +('1', '1', '52', '1945', '0', '102', '69', '94', '28', '42'), +('1', '1', '53', '2021', '0', '104', '70', '96', '28', '43'), +('1', '1', '54', '2099', '0', '106', '72', '98', '29', '44'), +('1', '1', '55', '2179', '0', '109', '73', '100', '29', '44'), +('1', '1', '56', '2261', '0', '111', '74', '102', '29', '45'), +('1', '1', '57', '2345', '0', '113', '76', '104', '29', '45'), +('1', '1', '58', '2431', '0', '115', '77', '106', '30', '46'), +('1', '1', '59', '2519', '0', '118', '79', '108', '30', '46'), +('1', '1', '60', '2609', '0', '120', '80', '110', '30', '47'), +('1', '2', '1', '58', '80', '22', '20', '22', '22', '20'), +('1', '2', '2', '76', '99', '23', '21', '23', '21', '23'), +('1', '2', '3', '94', '119', '24', '21', '24', '21', '23'), +('1', '2', '4', '112', '140', '25', '22', '25', '22', '24'), +('1', '2', '5', '130', '162', '26', '22', '26', '22', '25'), +('1', '2', '6', '148', '185', '27', '23', '27', '23', '25'), +('1', '2', '7', '166', '209', '28', '23', '28', '24', '26'), +('1', '2', '8', '184', '234', '29', '24', '28', '24', '26'), +('1', '2', '9', '202', '260', '30', '24', '29', '25', '27'), +('1', '2', '10', '220', '287', '31', '25', '30', '25', '28'), +('1', '2', '11', '238', '315', '32', '25', '31', '26', '29'), +('1', '2', '12', '256', '344', '33', '26', '32', '27', '29'), +('1', '2', '13', '274', '374', '34', '27', '33', '27', '30'), +('1', '2', '14', '292', '405', '35', '27', '34', '28', '31'), +('1', '2', '15', '311', '437', '36', '28', '36', '29', '31'), +('1', '2', '16', '331', '470', '38', '28', '37', '29', '32'), +('1', '2', '17', '352', '504', '39', '29', '38', '30', '33'), +('1', '2', '18', '374', '539', '40', '30', '39', '31', '34'), +('1', '2', '19', '397', '575', '41', '30', '40', '31', '34'), +('1', '2', '20', '421', '612', '42', '31', '41', '32', '35'), +('1', '2', '21', '446', '650', '43', '32', '42', '33', '36'), +('1', '2', '22', '472', '689', '45', '32', '43', '34', '37'), +('1', '2', '23', '499', '729', '46', '33', '44', '34', '38'), +('1', '2', '24', '527', '770', '47', '34', '46', '35', '38'), +('1', '2', '25', '556', '812', '48', '34', '47', '36', '39'), +('1', '2', '26', '586', '854', '50', '35', '48', '37', '40'), +('1', '2', '27', '617', '896', '51', '36', '49', '37', '42'), +('1', '2', '28', '649', '938', '52', '36', '50', '38', '43'), +('1', '2', '29', '682', '980', '54', '37', '52', '39', '44'), +('1', '2', '30', '716', '1022', '55', '38', '53', '40', '44'), +('1', '2', '31', '751', '1064', '56', '39', '54', '41', '45'), +('1', '2', '32', '787', '1106', '58', '39', '56', '42', '46'), +('1', '2', '33', '824', '1148', '59', '40', '57', '42', '47'), +('1', '2', '34', '862', '1190', '61', '41', '58', '43', '48'), +('1', '2', '35', '901', '1232', '62', '42', '60', '44', '49'), +('1', '2', '36', '941', '1274', '64', '43', '61', '45', '50'), +('1', '2', '37', '982', '1316', '65', '43', '62', '46', '51'), +('1', '2', '38', '1024', '1358', '67', '44', '64', '47', '52'), +('1', '2', '39', '1067', '1400', '68', '45', '65', '48', '53'), +('1', '2', '40', '1111', '1442', '70', '46', '67', '49', '54'), +('1', '2', '41', '1156', '1484', '71', '47', '68', '50', '55'), +('1', '2', '42', '1202', '1526', '73', '47', '70', '51', '56'), +('1', '2', '43', '1249', '1568', '74', '48', '71', '52', '57'), +('1', '2', '44', '1297', '1610', '76', '49', '73', '52', '58'), +('1', '2', '45', '1346', '1652', '78', '50', '74', '53', '59'), +('1', '2', '46', '1396', '1694', '79', '51', '76', '54', '60'), +('1', '2', '47', '1447', '1736', '81', '52', '77', '56', '61'), +('1', '2', '48', '1499', '1778', '83', '53', '79', '57', '63'), +('1', '2', '49', '1552', '1820', '84', '54', '81', '58', '65'), +('1', '2', '50', '1606', '1862', '86', '55', '82', '59', '66'), +('1', '2', '51', '1661', '1904', '88', '56', '84', '60', '67'), +('1', '2', '52', '1717', '1946', '90', '57', '86', '61', '68'), +('1', '2', '53', '1774', '1988', '92', '58', '87', '62', '69'), +('1', '2', '54', '1832', '2030', '93', '59', '89', '63', '70'), +('1', '2', '55', '1891', '2072', '95', '60', '91', '64', '72'), +('1', '2', '56', '1951', '2114', '97', '61', '93', '65', '73'), +('1', '2', '57', '2012', '2156', '99', '62', '94', '66', '74'), +('1', '2', '58', '2074', '2198', '101', '63', '96', '68', '75'), +('1', '2', '59', '2137', '2240', '103', '64', '98', '69', '77'), +('1', '2', '60', '2201', '2282', '105', '65', '100', '70', '78'), +('1', '4', '1', '55', '0', '21', '23', '21', '21', '20'), +('1', '4', '2', '72', '0', '22', '24', '22', '20', '21'), +('1', '4', '3', '89', '0', '22', '25', '22', '20', '22'), +('1', '4', '4', '106', '0', '23', '27', '23', '21', '22'), +('1', '4', '5', '123', '0', '24', '28', '24', '21', '22'), +('1', '4', '6', '140', '0', '24', '29', '24', '21', '23'), +('1', '4', '7', '157', '0', '25', '31', '25', '21', '23'), +('1', '4', '8', '174', '0', '26', '32', '25', '21', '23'), +('1', '4', '9', '191', '0', '27', '33', '26', '21', '24'), +('1', '4', '10', '208', '0', '27', '35', '27', '22', '24'), +('1', '4', '11', '225', '0', '28', '36', '28', '22', '25'), +('1', '4', '12', '242', '0', '29', '37', '28', '22', '25'), +('1', '4', '13', '259', '0', '30', '39', '29', '22', '25'), +('1', '4', '14', '276', '0', '30', '40', '30', '22', '26'), +('1', '4', '15', '293', '0', '31', '42', '30', '23', '26'), +('1', '4', '16', '311', '0', '32', '43', '31', '23', '27'), +('1', '4', '17', '330', '0', '33', '44', '32', '23', '27'), +('1', '4', '18', '350', '0', '34', '46', '33', '23', '27'), +('1', '4', '19', '371', '0', '35', '48', '33', '23', '28'), +('1', '4', '20', '393', '0', '35', '49', '34', '24', '28'), +('1', '4', '21', '416', '0', '36', '51', '35', '24', '29'), +('1', '4', '22', '440', '0', '37', '52', '36', '24', '29'), +('1', '4', '23', '465', '0', '38', '54', '37', '24', '30'), +('1', '4', '24', '491', '0', '39', '55', '37', '25', '30'), +('1', '4', '25', '518', '0', '40', '57', '38', '25', '31'), +('1', '4', '26', '546', '0', '41', '59', '39', '25', '31'), +('1', '4', '27', '575', '0', '42', '60', '40', '25', '31'), +('1', '4', '28', '605', '0', '43', '62', '41', '25', '32'), +('1', '4', '29', '636', '0', '43', '64', '42', '26', '32'), +('1', '4', '30', '668', '0', '44', '66', '42', '26', '33'), +('1', '4', '31', '701', '0', '45', '67', '43', '26', '33'), +('1', '4', '32', '735', '0', '46', '69', '44', '26', '34'), +('1', '4', '33', '770', '0', '47', '71', '45', '27', '34'), +('1', '4', '34', '806', '0', '48', '73', '46', '27', '35'), +('1', '4', '35', '843', '0', '49', '75', '47', '27', '35'), +('1', '4', '36', '881', '0', '51', '77', '48', '28', '36'), +('1', '4', '37', '920', '0', '52', '78', '49', '28', '37'), +('1', '4', '38', '960', '0', '53', '80', '50', '28', '37'), +('1', '4', '39', '1001', '0', '54', '82', '51', '28', '38'), +('1', '4', '40', '1043', '0', '55', '84', '52', '29', '38'), +('1', '4', '41', '1086', '0', '56', '86', '53', '29', '39'), +('1', '4', '42', '1130', '0', '57', '88', '54', '29', '39'), +('1', '4', '43', '1175', '0', '58', '90', '55', '29', '40'), +('1', '4', '44', '1221', '0', '59', '93', '56', '30', '40'), +('1', '4', '45', '1268', '0', '61', '95', '57', '30', '42'), +('1', '4', '46', '1316', '0', '62', '97', '58', '30', '43'), +('1', '4', '47', '1365', '0', '63', '99', '59', '31', '43'), +('1', '4', '48', '1415', '0', '64', '101', '60', '31', '44'), +('1', '4', '49', '1466', '0', '65', '103', '62', '31', '45'), +('1', '4', '50', '1518', '0', '67', '106', '63', '32', '45'), +('1', '4', '51', '1571', '0', '68', '108', '64', '32', '46'), +('1', '4', '52', '1625', '0', '69', '110', '65', '32', '46'), +('1', '4', '53', '1680', '0', '70', '113', '66', '33', '47'), +('1', '4', '54', '1736', '0', '72', '115', '67', '33', '48'), +('1', '4', '55', '1793', '0', '73', '117', '69', '33', '48'), +('1', '4', '56', '1851', '0', '74', '120', '70', '34', '49'), +('1', '4', '57', '1910', '0', '76', '122', '71', '34', '50'), +('1', '4', '58', '1970', '0', '77', '125', '72', '34', '51'), +('1', '4', '59', '2031', '0', '79', '127', '74', '35', '51'), +('1', '4', '60', '2093', '0', '80', '130', '75', '35', '52'), +('1', '5', '1', '52', '160', '20', '20', '20', '24', '22'), +('1', '5', '2', '67', '184', '20', '20', '20', '23', '25'), +('1', '5', '3', '82', '209', '20', '20', '21', '24', '26'), +('1', '5', '4', '97', '235', '21', '21', '21', '25', '28'), +('1', '5', '5', '112', '262', '21', '21', '21', '27', '29'), +('1', '5', '6', '127', '290', '21', '21', '22', '28', '30'), +('1', '5', '7', '142', '319', '21', '21', '22', '29', '31'), +('1', '5', '8', '157', '349', '21', '22', '22', '30', '32'), +('1', '5', '9', '172', '380', '21', '22', '23', '31', '34'), +('1', '5', '10', '187', '427', '22', '22', '23', '33', '35'), +('1', '5', '11', '202', '445', '22', '22', '24', '34', '36'), +('1', '5', '12', '217', '479', '22', '23', '24', '35', '38'), +('1', '5', '13', '232', '514', '22', '23', '24', '36', '39'), +('1', '5', '14', '247', '550', '22', '23', '25', '38', '40'), +('1', '5', '15', '262', '587', '23', '23', '25', '39', '43'), +('1', '5', '16', '277', '625', '23', '24', '26', '40', '44'), +('1', '5', '17', '292', '679', '23', '24', '26', '42', '45'), +('1', '5', '18', '307', '704', '23', '24', '26', '43', '47'), +('1', '5', '19', '322', '745', '23', '25', '27', '44', '48'), +('1', '5', '20', '337', '787', '24', '25', '27', '46', '50'), +('1', '5', '21', '352', '830', '24', '25', '28', '47', '51'), +('1', '5', '22', '368', '889', '24', '25', '28', '49', '53'), +('1', '5', '23', '385', '919', '24', '26', '29', '50', '54'), +('1', '5', '24', '403', '980', '25', '26', '29', '52', '56'), +('1', '5', '25', '422', '1012', '25', '26', '30', '53', '57'), +('1', '5', '26', '442', '1075', '25', '27', '30', '55', '59'), +('1', '5', '27', '463', '1109', '25', '27', '30', '56', '61'), +('1', '5', '28', '485', '1174', '25', '27', '31', '58', '63'), +('1', '5', '29', '508', '1210', '26', '28', '31', '59', '65'), +('1', '5', '30', '532', '1262', '26', '28', '32', '61', '67'), +('1', '5', '31', '557', '1330', '26', '28', '32', '63', '68'), +('1', '5', '32', '583', '1369', '26', '29', '33', '64', '70'), +('1', '5', '33', '610', '1438', '27', '29', '33', '66', '72'), +('1', '5', '34', '638', '1492', '27', '29', '34', '68', '73'), +('1', '5', '35', '667', '1531', '27', '30', '34', '69', '75'), +('1', '5', '36', '697', '1585', '28', '30', '35', '71', '77'), +('1', '5', '37', '728', '1654', '28', '30', '36', '73', '79'), +('1', '5', '38', '760', '1708', '28', '31', '36', '75', '81'), +('1', '5', '39', '793', '1747', '28', '31', '37', '76', '84'), +('1', '5', '40', '827', '1801', '29', '31', '37', '78', '85'), +('1', '5', '41', '862', '1870', '29', '32', '38', '80', '87'), +('1', '5', '42', '898', '1924', '29', '32', '38', '82', '89'), +('1', '5', '43', '935', '1978', '29', '33', '39', '84', '91'), +('1', '5', '44', '973', '2032', '30', '33', '39', '86', '93'), +('1', '5', '45', '1012', '2086', '30', '33', '40', '88', '95'), +('1', '5', '46', '1052', '2140', '30', '34', '41', '90', '97'), +('1', '5', '47', '1093', '2194', '31', '34', '41', '92', '99'), +('1', '5', '48', '1135', '2248', '31', '35', '42', '94', '102'), +('1', '5', '49', '1178', '2302', '31', '35', '43', '96', '105'), +('1', '5', '50', '1222', '2356', '32', '35', '43', '98', '107'), +('1', '5', '51', '1267', '2410', '32', '36', '44', '100', '109'), +('1', '5', '52', '1313', '2464', '32', '36', '44', '102', '111'), +('1', '5', '53', '1360', '2518', '33', '37', '45', '104', '113'), +('1', '5', '54', '1408', '2572', '33', '37', '46', '106', '116'), +('1', '5', '55', '1457', '2626', '33', '38', '46', '109', '118'), +('1', '5', '56', '1507', '2680', '34', '38', '47', '111', '120'), +('1', '5', '57', '1558', '2734', '34', '39', '48', '113', '123'), +('1', '5', '58', '1610', '2788', '34', '39', '49', '115', '126'), +('1', '5', '59', '1663', '2842', '35', '40', '49', '118', '129'), +('1', '5', '60', '1717', '2896', '35', '40', '50', '120', '131'), +('1', '8', '1', '52', '165', '20', '20', '20', '23', '23'), +('1', '8', '2', '67', '190', '20', '20', '20', '24', '24'), +('1', '8', '3', '82', '216', '20', '20', '21', '25', '25'), +('1', '8', '4', '97', '243', '20', '21', '21', '27', '26'), +('1', '8', '5', '112', '271', '20', '21', '21', '28', '28'), +('1', '8', '6', '127', '300', '21', '21', '21', '29', '29'), +('1', '8', '7', '142', '330', '21', '21', '22', '30', '30'), +('1', '8', '8', '157', '346', '21', '21', '22', '31', '31'), +('1', '8', '9', '172', '393', '21', '21', '22', '33', '32'), +('1', '8', '10', '187', '426', '21', '22', '23', '34', '34'), +('1', '8', '11', '202', '460', '21', '22', '23', '35', '35'), +('1', '8', '12', '217', '495', '21', '22', '23', '37', '36'), +('1', '8', '13', '232', '531', '21', '22', '24', '38', '37'), +('1', '8', '14', '247', '568', '22', '22', '24', '39', '39'), +('1', '8', '15', '262', '606', '22', '23', '24', '41', '40'), +('1', '8', '16', '277', '645', '22', '23', '25', '42', '42'), +('1', '8', '17', '292', '670', '22', '23', '25', '43', '44'), +('1', '8', '18', '307', '726', '22', '23', '25', '45', '45'), +('1', '8', '19', '322', '753', '22', '23', '26', '46', '46'), +('1', '8', '20', '337', '811', '22', '24', '26', '48', '48'), +('1', '8', '21', '352', '840', '23', '24', '26', '49', '49'), +('1', '8', '22', '367', '900', '23', '24', '27', '51', '51'), +('1', '8', '23', '382', '931', '23', '24', '27', '52', '52'), +('1', '8', '24', '398', '993', '23', '25', '28', '54', '54'), +('1', '8', '25', '415', '1026', '23', '25', '28', '55', '55'), +('1', '8', '26', '433', '1090', '23', '25', '28', '57', '57'), +('1', '8', '27', '452', '1140', '23', '25', '29', '59', '58'), +('1', '8', '28', '472', '1176', '24', '25', '29', '60', '60'), +('1', '8', '29', '493', '1242', '24', '26', '30', '62', '61'), +('1', '8', '30', '515', '1293', '24', '26', '30', '64', '64'), +('1', '8', '31', '538', '1329', '24', '26', '30', '65', '66'), +('1', '8', '32', '562', '1395', '24', '26', '31', '67', '67'), +('1', '8', '33', '587', '1446', '24', '27', '31', '69', '69'), +('1', '8', '34', '613', '1482', '25', '27', '32', '70', '71'), +('1', '8', '35', '640', '1533', '25', '27', '32', '72', '72'), +('1', '8', '36', '668', '1584', '25', '28', '33', '74', '74'), +('1', '8', '37', '697', '1650', '25', '28', '33', '76', '76'), +('1', '8', '38', '727', '1701', '25', '28', '33', '78', '78'), +('1', '8', '39', '758', '1752', '26', '28', '34', '80', '79'), +('1', '8', '40', '790', '1788', '26', '29', '34', '81', '81'), +('1', '8', '41', '823', '1839', '26', '29', '35', '83', '84'), +('1', '8', '42', '857', '1890', '26', '29', '35', '85', '86'), +('1', '8', '43', '892', '1941', '26', '29', '36', '87', '88'), +('1', '8', '44', '928', '1992', '26', '30', '36', '89', '90'), +('1', '8', '45', '965', '2043', '27', '30', '37', '91', '92'), +('1', '8', '46', '1003', '2094', '27', '30', '37', '93', '94'), +('1', '8', '47', '1042', '2145', '27', '31', '38', '95', '96'), +('1', '8', '48', '1082', '2211', '27', '31', '38', '98', '98'), +('1', '8', '49', '1123', '2262', '28', '31', '39', '100', '100'), +('1', '8', '50', '1165', '2298', '28', '32', '39', '102', '102'), +('1', '8', '51', '1208', '2349', '28', '32', '40', '104', '105'), +('1', '8', '52', '1252', '2400', '28', '32', '40', '106', '107'), +('1', '8', '53', '1297', '2451', '28', '33', '41', '108', '109'), +('1', '8', '54', '1343', '2502', '29', '33', '42', '111', '111'), +('1', '8', '55', '1390', '2553', '29', '33', '42', '113', '114'), +('1', '8', '56', '1438', '2604', '29', '34', '43', '115', '116'), +('1', '8', '57', '1487', '2655', '29', '34', '43', '118', '118'), +('1', '8', '58', '1537', '2706', '30', '34', '44', '120', '120'), +('1', '8', '59', '1588', '2757', '30', '35', '44', '123', '123'), +('1', '8', '60', '1640', '2808', '30', '35', '45', '125', '126'), +('1', '9', '1', '53', '140', '20', '20', '21', '23', '22'), +('1', '9', '2', '68', '163', '20', '20', '22', '23', '24'), +('1', '9', '3', '83', '187', '21', '21', '22', '24', '25'), +('1', '9', '4', '98', '212', '21', '21', '23', '25', '26'), +('1', '9', '5', '113', '238', '21', '21', '23', '26', '27'), +('1', '9', '6', '128', '265', '21', '22', '24', '27', '28'), +('1', '9', '7', '143', '293', '22', '22', '24', '28', '30'), +('1', '9', '8', '158', '322', '22', '22', '25', '29', '31'), +('1', '9', '9', '173', '352', '22', '23', '25', '30', '32'), +('1', '9', '10', '188', '383', '23', '23', '26', '31', '33'), +('1', '9', '11', '203', '415', '23', '24', '26', '33', '34'), +('1', '9', '12', '218', '448', '23', '24', '27', '34', '35'), +('1', '9', '13', '233', '482', '24', '24', '27', '35', '37'), +('1', '9', '14', '248', '517', '24', '25', '28', '36', '38'), +('1', '9', '15', '263', '553', '24', '25', '29', '37', '39'), +('1', '9', '16', '278', '590', '25', '26', '29', '38', '40'), +('1', '9', '17', '293', '628', '25', '26', '30', '40', '43'), +('1', '9', '18', '309', '667', '25', '26', '30', '41', '44'), +('1', '9', '19', '326', '707', '26', '27', '31', '42', '45'), +('1', '9', '20', '344', '748', '26', '27', '32', '43', '47'), +('1', '9', '21', '363', '790', '26', '28', '32', '45', '48'), +('1', '9', '22', '383', '833', '27', '28', '33', '46', '49'), +('1', '9', '23', '404', '877', '27', '29', '34', '47', '51'), +('1', '9', '24', '426', '922', '28', '29', '34', '49', '52'), +('1', '9', '25', '449', '968', '28', '30', '35', '50', '54'), +('1', '9', '26', '473', '1015', '28', '30', '36', '51', '55'), +('1', '9', '27', '498', '1063', '29', '30', '36', '53', '56'), +('1', '9', '28', '524', '1112', '29', '31', '37', '54', '58'), +('1', '9', '29', '551', '1162', '30', '31', '38', '56', '59'), +('1', '9', '30', '579', '1213', '30', '32', '38', '57', '61'), +('1', '9', '31', '608', '1264', '30', '32', '39', '58', '64'), +('1', '9', '32', '638', '1315', '31', '33', '40', '60', '65'), +('1', '9', '33', '669', '1366', '31', '33', '41', '61', '67'), +('1', '9', '34', '701', '1417', '32', '34', '41', '63', '68'), +('1', '9', '35', '734', '1468', '32', '34', '42', '64', '70'), +('1', '9', '36', '768', '1519', '33', '35', '43', '66', '72'), +('1', '9', '37', '803', '1570', '33', '36', '44', '68', '73'), +('1', '9', '38', '839', '1621', '33', '36', '45', '69', '75'), +('1', '9', '39', '876', '1672', '34', '37', '45', '71', '77'), +('1', '9', '40', '914', '1723', '34', '37', '46', '72', '78'), +('1', '9', '41', '953', '1774', '35', '38', '47', '74', '80'), +('1', '9', '42', '993', '1825', '35', '38', '48', '76', '82'), +('1', '9', '43', '1024', '1876', '36', '39', '48', '77', '86'), +('1', '9', '44', '1076', '1927', '36', '39', '50', '79', '86'), +('1', '9', '45', '1119', '1978', '37', '40', '50', '81', '88'), +('1', '9', '46', '1153', '2029', '37', '41', '51', '83', '90'), +('1', '9', '47', '1208', '2080', '38', '41', '52', '84', '92'), +('1', '9', '48', '1254', '2131', '38', '42', '53', '86', '94'), +('1', '9', '49', '1301', '2182', '39', '43', '54', '88', '96'), +('1', '9', '50', '1349', '2233', '39', '43', '55', '90', '98'), +('1', '9', '51', '1398', '2284', '40', '44', '56', '92', '100'), +('1', '9', '52', '1448', '2335', '40', '44', '57', '94', '102'), +('1', '9', '53', '1489', '2386', '41', '45', '58', '96', '105'), +('1', '9', '54', '1541', '2437', '42', '46', '59', '98', '107'), +('1', '9', '55', '1604', '2488', '42', '46', '60', '100', '109'), +('1', '9', '56', '1658', '2539', '43', '47', '61', '102', '111'), +('1', '9', '57', '1713', '2590', '43', '48', '62', '104', '113'), +('1', '9', '58', '1769', '2641', '44', '49', '63', '106', '116'), +('1', '9', '59', '1826', '2692', '44', '49', '64', '108', '118'), +('1', '9', '60', '1884', '2743', '45', '50', '65', '110', '120'), +('2', '1', '1', '80', '0', '26', '17', '24', '23', '17'), +('2', '1', '2', '99', '0', '27', '18', '25', '17', '23'), +('2', '1', '3', '118', '0', '28', '18', '26', '17', '24'), +('2', '1', '4', '137', '0', '29', '19', '27', '17', '24'), +('2', '1', '5', '156', '0', '31', '20', '28', '17', '24'), +('2', '1', '6', '175', '0', '32', '21', '29', '18', '24'), +('2', '1', '7', '194', '0', '33', '21', '30', '18', '25'), +('2', '1', '8', '213', '0', '34', '22', '31', '18', '25'), +('2', '1', '9', '232', '0', '35', '23', '32', '18', '25'), +('2', '1', '10', '251', '0', '36', '23', '33', '18', '26'), +('2', '1', '11', '270', '0', '38', '24', '35', '18', '26'), +('2', '1', '12', '289', '0', '39', '25', '36', '18', '26'), +('2', '1', '13', '308', '0', '40', '26', '37', '18', '27'), +('2', '1', '14', '328', '0', '42', '27', '38', '19', '27'), +('2', '1', '15', '349', '0', '43', '27', '39', '19', '27'), +('2', '1', '16', '371', '0', '44', '28', '40', '19', '28'), +('2', '1', '17', '394', '0', '45', '29', '42', '19', '28'), +('2', '1', '18', '418', '0', '47', '30', '43', '19', '28'), +('2', '1', '19', '443', '0', '48', '31', '44', '19', '29'), +('2', '1', '20', '469', '0', '50', '32', '45', '19', '29'), +('2', '1', '21', '496', '0', '51', '32', '47', '20', '29'), +('2', '1', '22', '524', '0', '52', '33', '48', '20', '30'), +('2', '1', '23', '553', '0', '54', '34', '49', '20', '30'), +('2', '1', '24', '583', '0', '55', '35', '51', '20', '31'), +('2', '1', '25', '614', '0', '57', '36', '52', '20', '31'), +('2', '1', '26', '646', '0', '58', '37', '53', '20', '31'), +('2', '1', '27', '679', '0', '60', '38', '55', '20', '32'), +('2', '1', '28', '713', '0', '61', '39', '56', '21', '32'), +('2', '1', '29', '748', '0', '63', '40', '58', '21', '33'), +('2', '1', '30', '784', '0', '65', '41', '59', '21', '33'), +('2', '1', '31', '821', '0', '66', '42', '60', '21', '33'), +('2', '1', '32', '859', '0', '68', '43', '62', '21', '34'), +('2', '1', '33', '898', '0', '69', '44', '63', '21', '34'), +('2', '1', '34', '938', '0', '71', '45', '65', '22', '35'), +('2', '1', '35', '979', '0', '73', '46', '66', '22', '35'), +('2', '1', '36', '1021', '0', '75', '47', '68', '22', '36'), +('2', '1', '37', '1065', '0', '76', '48', '70', '22', '36'), +('2', '1', '38', '1111', '0', '78', '49', '71', '22', '36'), +('2', '1', '39', '1159', '0', '80', '50', '73', '23', '37'), +('2', '1', '40', '1209', '0', '82', '51', '74', '23', '37'), +('2', '1', '41', '1261', '0', '83', '53', '76', '23', '38'), +('2', '1', '42', '1315', '0', '85', '54', '78', '23', '38'), +('2', '1', '43', '1371', '0', '87', '55', '79', '23', '39'), +('2', '1', '44', '1429', '0', '89', '56', '81', '23', '39'), +('2', '1', '45', '1489', '0', '91', '57', '83', '24', '40'), +('2', '1', '46', '1551', '0', '93', '58', '85', '24', '40'), +('2', '1', '47', '1615', '0', '95', '60', '86', '24', '41'), +('2', '1', '48', '1681', '0', '97', '61', '88', '24', '41'), +('2', '1', '49', '1749', '0', '99', '62', '90', '25', '42'), +('2', '1', '50', '1819', '0', '101', '63', '92', '25', '42'), +('2', '1', '51', '1891', '0', '103', '65', '94', '25', '43'), +('2', '1', '52', '1965', '0', '105', '66', '96', '25', '43'), +('2', '1', '53', '2041', '0', '107', '67', '98', '25', '44'), +('2', '1', '54', '2119', '0', '109', '69', '100', '26', '45'), +('2', '1', '55', '2199', '0', '112', '70', '102', '26', '45'), +('2', '1', '56', '2281', '0', '114', '71', '104', '26', '46'), +('2', '1', '57', '2365', '0', '116', '73', '106', '26', '46'), +('2', '1', '58', '2451', '0', '118', '74', '108', '27', '47'), +('2', '1', '59', '2539', '0', '121', '76', '110', '27', '47'), +('2', '1', '60', '2629', '0', '123', '77', '112', '27', '48'), +('2', '3', '1', '76', '82', '23', '20', '23', '24', '17'), +('2', '3', '2', '93', '88', '23', '21', '24', '18', '25'), +('2', '3', '3', '110', '109', '24', '22', '25', '18', '25'), +('2', '3', '4', '127', '117', '24', '24', '25', '19', '26'), +('2', '3', '5', '144', '140', '25', '25', '26', '19', '26'), +('2', '3', '6', '161', '150', '25', '26', '27', '20', '27'), +('2', '3', '7', '178', '175', '25', '27', '28', '20', '27'), +('2', '3', '8', '195', '201', '26', '28', '29', '21', '28'), +('2', '3', '9', '212', '228', '26', '30', '30', '21', '29'), +('2', '3', '10', '229', '256', '27', '31', '30', '22', '29'), +('2', '3', '11', '246', '285', '27', '32', '31', '22', '30'), +('2', '3', '12', '263', '315', '28', '34', '32', '23', '31'), +('2', '3', '13', '280', '346', '28', '35', '33', '24', '31'), +('2', '3', '14', '298', '378', '29', '36', '34', '24', '32'), +('2', '3', '15', '317', '411', '29', '38', '35', '25', '32'), +('2', '3', '16', '337', '445', '30', '39', '36', '25', '33'), +('2', '3', '17', '358', '480', '30', '40', '37', '26', '34'), +('2', '3', '18', '380', '516', '31', '42', '38', '27', '35'), +('2', '3', '19', '403', '553', '31', '43', '39', '27', '35'), +('2', '3', '20', '427', '591', '32', '45', '40', '28', '36'), +('2', '3', '21', '452', '630', '32', '46', '41', '29', '37'), +('2', '3', '22', '478', '670', '33', '48', '42', '29', '37'), +('2', '3', '23', '505', '711', '33', '49', '43', '30', '38'), +('2', '3', '24', '533', '753', '34', '51', '44', '31', '39'), +('2', '3', '25', '562', '796', '34', '52', '45', '31', '40'), +('2', '3', '26', '592', '840', '35', '54', '46', '32', '40'), +('2', '3', '27', '623', '885', '35', '56', '47', '33', '41'), +('2', '3', '28', '655', '930', '36', '57', '48', '33', '42'), +('2', '3', '29', '688', '975', '36', '59', '49', '34', '43'), +('2', '3', '30', '722', '1020', '37', '61', '50', '35', '43'), +('2', '3', '31', '757', '1065', '37', '62', '52', '36', '44'), +('2', '3', '32', '793', '1110', '38', '64', '53', '36', '45'), +('2', '3', '33', '830', '1155', '39', '66', '54', '37', '46'), +('2', '3', '34', '868', '1200', '39', '67', '55', '38', '47'), +('2', '3', '35', '907', '1245', '40', '69', '56', '39', '48'), +('2', '3', '36', '947', '1290', '41', '71', '58', '40', '49'), +('2', '3', '37', '988', '1335', '41', '73', '59', '40', '49'), +('2', '3', '38', '1030', '1380', '42', '75', '60', '41', '50'), +('2', '3', '39', '1073', '1425', '42', '77', '61', '42', '51'), +('2', '3', '40', '1117', '1470', '43', '78', '63', '43', '52'), +('2', '3', '41', '1162', '1515', '44', '80', '64', '44', '53'), +('2', '3', '42', '1208', '1560', '44', '82', '65', '44', '54'), +('2', '3', '43', '1255', '1605', '45', '84', '66', '45', '55'), +('2', '3', '44', '1303', '1650', '46', '86', '68', '46', '56'), +('2', '3', '45', '1352', '1695', '46', '88', '69', '47', '57'), +('2', '3', '46', '1402', '1740', '47', '90', '71', '48', '58'), +('2', '3', '47', '1453', '1785', '48', '92', '72', '49', '59'), +('2', '3', '48', '1505', '1830', '49', '95', '73', '50', '60'), +('2', '3', '49', '1558', '1875', '49', '97', '75', '51', '61'), +('2', '3', '50', '1612', '1920', '50', '99', '76', '52', '62'), +('2', '3', '51', '1667', '1965', '51', '101', '78', '53', '63'), +('2', '3', '52', '1723', '2010', '52', '103', '79', '54', '64'), +('2', '3', '53', '1780', '2055', '52', '105', '81', '55', '65'), +('2', '3', '54', '1838', '2100', '53', '108', '82', '56', '66'), +('2', '3', '55', '1897', '2145', '54', '110', '84', '57', '67'), +('2', '3', '56', '1957', '2190', '55', '112', '85', '58', '68'), +('2', '3', '57', '2018', '2235', '56', '115', '87', '59', '70'), +('2', '3', '58', '2080', '2280', '56', '117', '89', '60', '71'), +('2', '3', '59', '2143', '2325', '57', '120', '90', '61', '72'), +('2', '3', '60', '2207', '2370', '58', '122', '92', '62', '73'), +('2', '4', '1', '75', '0', '24', '20', '23', '23', '17'), +('2', '4', '2', '92', '0', '25', '21', '24', '17', '23'), +('2', '4', '3', '109', '0', '25', '22', '24', '17', '24'), +('2', '4', '4', '126', '0', '26', '24', '25', '18', '24'), +('2', '4', '5', '143', '0', '27', '25', '26', '18', '24'), +('2', '4', '6', '160', '0', '27', '26', '26', '18', '25'), +('2', '4', '7', '177', '0', '28', '28', '27', '18', '25'), +('2', '4', '8', '194', '0', '29', '29', '27', '18', '25'), +('2', '4', '9', '211', '0', '30', '30', '28', '18', '26'), +('2', '4', '10', '228', '0', '30', '32', '29', '19', '26'), +('2', '4', '11', '245', '0', '31', '33', '30', '19', '27'), +('2', '4', '12', '262', '0', '32', '34', '30', '19', '27'), +('2', '4', '13', '279', '0', '33', '36', '31', '19', '27'), +('2', '4', '14', '296', '0', '33', '37', '32', '19', '28'), +('2', '4', '15', '313', '0', '34', '39', '32', '20', '28'), +('2', '4', '16', '331', '0', '35', '40', '33', '20', '29'), +('2', '4', '17', '350', '0', '36', '41', '34', '20', '29'), +('2', '4', '18', '370', '0', '37', '43', '35', '20', '29'), +('2', '4', '19', '370', '0', '37', '43', '35', '20', '29'), +('2', '4', '20', '370', '0', '37', '43', '35', '20', '29'), +('2', '4', '21', '436', '0', '39', '48', '37', '21', '31'), +('2', '4', '22', '460', '0', '40', '49', '38', '21', '31'), +('2', '4', '23', '485', '0', '41', '51', '39', '21', '32'), +('2', '4', '24', '511', '0', '42', '52', '39', '22', '32'), +('2', '4', '25', '538', '0', '43', '54', '40', '22', '33'), +('2', '4', '26', '566', '0', '44', '56', '41', '22', '33'), +('2', '4', '27', '595', '0', '45', '57', '42', '22', '33'), +('2', '4', '28', '625', '0', '46', '59', '43', '22', '34'), +('2', '4', '29', '656', '0', '46', '61', '44', '23', '34'), +('2', '4', '30', '688', '0', '47', '63', '44', '23', '35'), +('2', '4', '31', '721', '0', '48', '64', '45', '23', '35'), +('2', '4', '32', '755', '0', '49', '66', '46', '23', '36'), +('2', '4', '33', '790', '0', '50', '68', '47', '24', '36'), +('2', '4', '34', '826', '0', '51', '70', '48', '24', '37'), +('2', '4', '35', '863', '0', '52', '72', '49', '24', '37'), +('2', '4', '36', '901', '0', '54', '74', '50', '25', '38'), +('2', '4', '37', '940', '0', '55', '75', '51', '25', '39'), +('2', '4', '38', '985', '0', '56', '77', '52', '25', '39'), +('2', '4', '39', '1021', '0', '57', '79', '53', '25', '40'), +('2', '4', '40', '1063', '0', '58', '81', '54', '26', '40'), +('2', '4', '41', '1106', '0', '59', '83', '55', '26', '41'), +('2', '4', '42', '1150', '0', '60', '85', '56', '26', '41'), +('2', '4', '43', '1195', '0', '61', '87', '57', '26', '42'), +('2', '4', '44', '1241', '0', '62', '90', '58', '27', '42'), +('2', '4', '45', '1288', '0', '64', '92', '59', '27', '43'), +('2', '4', '46', '1336', '0', '65', '94', '60', '27', '44'), +('2', '4', '47', '1385', '0', '66', '96', '61', '28', '44'), +('2', '4', '48', '1435', '0', '67', '98', '62', '28', '45'), +('2', '4', '49', '1486', '0', '68', '100', '64', '28', '46'), +('2', '4', '50', '1538', '0', '70', '103', '65', '29', '46'), +('2', '4', '51', '1591', '0', '71', '105', '66', '29', '47'), +('2', '4', '52', '1645', '0', '72', '107', '67', '29', '47'), +('2', '4', '53', '1700', '0', '73', '110', '68', '30', '48'), +('2', '4', '54', '1756', '0', '75', '112', '69', '30', '49'), +('2', '4', '55', '1813', '0', '76', '114', '71', '30', '49'), +('2', '4', '56', '1871', '0', '77', '117', '72', '31', '50'), +('2', '4', '57', '1930', '0', '79', '119', '73', '31', '51'), +('2', '4', '58', '1990', '0', '80', '122', '74', '31', '52'), +('2', '4', '59', '2051', '0', '82', '124', '76', '32', '52'), +('2', '4', '60', '2113', '0', '83', '127', '77', '32', '53'), +('2', '7', '1', '77', '73', '24', '17', '23', '25', '18'), +('2', '7', '2', '94', '80', '25', '17', '24', '19', '26'), +('2', '7', '3', '111', '88', '25', '18', '25', '20', '27'), +('2', '7', '4', '128', '111', '26', '18', '26', '20', '28'), +('2', '7', '5', '145', '135', '27', '19', '26', '21', '29'), +('2', '7', '6', '162', '160', '28', '19', '27', '22', '30'), +('2', '7', '7', '179', '186', '29', '19', '28', '23', '31'), +('2', '7', '8', '196', '213', '29', '20', '29', '24', '31'), +('2', '7', '9', '213', '256', '30', '20', '30', '25', '32'), +('2', '7', '10', '230', '270', '31', '21', '31', '25', '33'), +('2', '7', '11', '247', '300', '32', '21', '32', '26', '34'), +('2', '7', '12', '264', '331', '33', '22', '33', '27', '35'), +('2', '7', '13', '281', '363', '33', '22', '34', '28', '36'), +('2', '7', '14', '298', '396', '34', '23', '35', '29', '37'), +('2', '7', '15', '315', '430', '35', '23', '36', '30', '39'), +('2', '7', '16', '332', '465', '36', '24', '37', '31', '40'), +('2', '7', '17', '350', '501', '37', '24', '38', '32', '41'), +('2', '7', '18', '369', '538', '38', '25', '39', '33', '42'), +('2', '7', '19', '389', '576', '39', '25', '40', '34', '43'), +('2', '7', '20', '410', '615', '40', '26', '41', '35', '44'), +('2', '7', '21', '432', '655', '41', '26', '42', '36', '45'), +('2', '7', '22', '455', '731', '41', '27', '43', '37', '46'), +('2', '7', '23', '479', '738', '42', '27', '44', '38', '47'), +('2', '7', '24', '504', '781', '43', '28', '45', '39', '49'), +('2', '7', '25', '530', '825', '44', '28', '47', '40', '50'), +('2', '7', '26', '557', '914', '45', '29', '48', '41', '51'), +('2', '7', '27', '585', '916', '46', '29', '49', '42', '52'), +('2', '7', '28', '614', '963', '47', '30', '50', '43', '53'), +('2', '7', '29', '644', '1011', '48', '30', '51', '44', '55'), +('2', '7', '30', '675', '1113', '49', '31', '52', '45', '56'), +('2', '7', '31', '707', '1124', '51', '31', '54', '47', '57'), +('2', '7', '32', '740', '1232', '52', '32', '55', '48', '59'), +('2', '7', '33', '774', '1283', '53', '33', '56', '49', '60'), +('2', '7', '34', '809', '1319', '54', '33', '57', '50', '61'), +('2', '7', '35', '845', '1370', '55', '34', '59', '51', '63'), +('2', '7', '36', '882', '1438', '56', '35', '60', '53', '64'), +('2', '7', '37', '920', '1489', '57', '35', '61', '54', '65'), +('2', '7', '38', '959', '1541', '58', '36', '63', '55', '67'), +('2', '7', '39', '999', '1593', '59', '36', '64', '56', '68'), +('2', '7', '40', '1040', '1643', '61', '37', '65', '58', '70'), +('2', '7', '41', '1082', '1675', '62', '38', '67', '59', '71'), +('2', '7', '42', '1125', '1697', '63', '38', '68', '60', '73'), +('2', '7', '43', '1169', '1710', '64', '39', '70', '61', '74'), +('2', '7', '44', '1214', '1761', '66', '40', '71', '63', '76'), +('2', '7', '45', '1260', '1885', '67', '40', '73', '64', '77'), +('2', '7', '46', '1307', '1952', '68', '41', '74', '66', '79'), +('2', '7', '47', '1355', '2004', '69', '42', '76', '67', '80'), +('2', '7', '48', '1404', '2055', '71', '43', '77', '68', '82'), +('2', '7', '49', '1454', '2106', '72', '43', '79', '70', '84'), +('2', '7', '50', '1505', '2142', '73', '44', '80', '71', '85'), +('2', '7', '51', '1557', '2210', '75', '45', '82', '73', '87'), +('2', '7', '52', '1610', '2261', '76', '46', '83', '74', '89'), +('2', '7', '53', '1664', '2312', '78', '46', '85', '76', '90'), +('2', '7', '54', '1719', '2334', '79', '47', '87', '77', '92'), +('2', '7', '55', '1775', '2364', '80', '48', '88', '79', '94'), +('2', '7', '56', '1832', '2415', '82', '49', '90', '80', '96'), +('2', '7', '57', '1890', '2518', '83', '50', '92', '82', '97'), +('2', '7', '58', '1949', '2570', '85', '50', '93', '84', '99'), +('2', '7', '59', '2009', '2621', '86', '51', '95', '85', '101'), +('2', '7', '60', '2070', '2700', '88', '52', '97', '87', '103'), +('2', '9', '1', '73', '109', '23', '17', '23', '25', '19'), +('2', '9', '2', '88', '118', '23', '17', '24', '20', '26'), +('2', '9', '3', '103', '142', '24', '18', '24', '21', '27'), +('2', '9', '4', '118', '167', '24', '18', '25', '22', '28'), +('2', '9', '5', '133', '193', '24', '18', '25', '23', '29'), +('2', '9', '6', '148', '220', '24', '19', '26', '24', '30'), +('2', '9', '7', '163', '248', '25', '19', '26', '25', '32'), +('2', '9', '8', '178', '277', '25', '19', '27', '26', '33'), +('2', '9', '9', '193', '307', '25', '20', '27', '27', '34'), +('2', '9', '10', '208', '338', '26', '20', '28', '28', '35'), +('2', '9', '11', '223', '370', '26', '21', '28', '30', '36'), +('2', '9', '12', '238', '403', '26', '21', '29', '31', '37'), +('2', '9', '13', '253', '437', '27', '21', '29', '32', '39'), +('2', '9', '14', '268', '472', '27', '22', '30', '33', '40'), +('2', '9', '15', '283', '508', '27', '22', '31', '34', '41'), +('2', '9', '16', '298', '545', '28', '23', '31', '35', '42'), +('2', '9', '17', '313', '583', '28', '23', '32', '37', '44'), +('2', '9', '18', '329', '622', '28', '23', '32', '38', '45'), +('2', '9', '19', '364', '662', '29', '24', '33', '39', '46'), +('2', '9', '20', '376', '703', '29', '24', '34', '40', '48'), +('2', '9', '21', '408', '745', '29', '25', '34', '42', '49'), +('2', '9', '22', '408', '788', '30', '25', '34', '43', '50'), +('2', '9', '23', '424', '832', '30', '26', '35', '44', '52'), +('2', '9', '24', '446', '877', '31', '26', '35', '46', '53'), +('2', '9', '25', '469', '923', '31', '27', '36', '47', '55'), +('2', '9', '26', '493', '970', '31', '27', '37', '48', '56'), +('2', '9', '27', '518', '1018', '32', '27', '37', '50', '57'), +('2', '9', '28', '544', '1067', '32', '28', '38', '51', '59'), +('2', '9', '29', '571', '1117', '33', '28', '39', '53', '60'), +('2', '9', '30', '599', '1168', '33', '29', '39', '54', '62'), +('2', '9', '31', '628', '1219', '33', '29', '40', '55', '64'), +('2', '9', '32', '658', '1270', '34', '30', '41', '57', '65'), +('2', '9', '33', '679', '1321', '34', '30', '41', '58', '68'), +('2', '9', '34', '721', '1372', '35', '31', '42', '60', '68'), +('2', '9', '35', '754', '1423', '35', '31', '43', '61', '70'), +('2', '9', '36', '788', '1474', '36', '32', '44', '63', '71'), +('2', '9', '37', '823', '1525', '36', '33', '45', '65', '73'), +('2', '9', '38', '859', '1576', '36', '33', '46', '66', '75'), +('2', '9', '39', '896', '1627', '37', '34', '46', '68', '77'), +('2', '9', '40', '934', '1678', '37', '34', '47', '69', '78'), +('2', '9', '41', '973', '1729', '38', '35', '47', '71', '80'), +('2', '9', '42', '993', '1780', '38', '35', '47', '73', '83'), +('2', '9', '43', '1054', '1831', '39', '36', '50', '74', '84'), +('2', '9', '44', '1096', '1882', '39', '36', '51', '76', '85'), +('2', '9', '45', '1139', '1933', '40', '37', '51', '78', '87'), +('2', '9', '46', '1183', '1984', '40', '38', '52', '80', '89'), +('2', '9', '47', '1228', '2035', '41', '38', '53', '81', '91'), +('2', '9', '48', '1274', '2086', '41', '39', '53', '83', '93'), +('2', '9', '49', '1321', '2137', '42', '40', '54', '85', '96'), +('2', '9', '50', '1369', '2188', '42', '40', '56', '87', '97'), +('2', '9', '51', '1408', '2239', '43', '41', '56', '89', '99'), +('2', '9', '52', '1468', '2290', '43', '41', '58', '91', '101'), +('2', '9', '53', '1519', '2341', '44', '42', '59', '93', '103'), +('2', '9', '54', '1551', '2392', '45', '43', '60', '95', '105'), +('2', '9', '55', '1624', '2443', '45', '43', '61', '97', '106'), +('2', '9', '56', '1678', '2494', '46', '44', '62', '99', '109'), +('2', '9', '57', '1727', '2545', '46', '45', '62', '101', '110'), +('2', '9', '58', '1779', '2596', '47', '46', '64', '103', '114'), +('2', '9', '59', '1836', '2647', '47', '46', '65', '105', '116'), +('2', '9', '60', '1904', '2698', '48', '47', '66', '107', '118'), +('3', '1', '1', '90', '0', '25', '16', '25', '19', '19'), +('3', '1', '2', '109', '0', '26', '17', '26', '19', '19'), +('3', '1', '3', '128', '0', '27', '17', '27', '19', '20'), +('3', '1', '4', '147', '0', '28', '18', '28', '19', '20'), +('3', '1', '5', '166', '0', '30', '19', '29', '19', '20'), +('3', '1', '6', '185', '0', '31', '20', '30', '20', '20'), +('3', '1', '7', '204', '0', '32', '20', '31', '20', '21'), +('3', '1', '8', '223', '0', '33', '21', '32', '20', '21'), +('3', '1', '9', '242', '0', '34', '22', '33', '20', '21'), +('3', '1', '10', '261', '0', '35', '22', '34', '20', '22'), +('3', '1', '11', '280', '0', '37', '23', '36', '20', '22'), +('3', '1', '12', '299', '0', '38', '24', '37', '20', '22'), +('3', '1', '13', '318', '0', '39', '25', '38', '20', '23'), +('3', '1', '14', '338', '0', '41', '26', '39', '21', '23'), +('3', '1', '15', '359', '0', '42', '26', '40', '21', '23'), +('3', '1', '16', '381', '0', '43', '27', '41', '21', '24'), +('3', '1', '17', '404', '0', '44', '28', '43', '21', '24'), +('3', '1', '18', '428', '0', '46', '29', '44', '21', '24'), +('3', '1', '19', '453', '0', '47', '30', '45', '21', '25'), +('3', '1', '20', '479', '0', '49', '31', '46', '21', '25'), +('3', '1', '21', '506', '0', '50', '31', '48', '22', '25'), +('3', '1', '22', '534', '0', '51', '32', '49', '22', '26'), +('3', '1', '23', '563', '0', '53', '33', '50', '22', '26'), +('3', '1', '24', '593', '0', '54', '34', '52', '22', '27'), +('3', '1', '25', '624', '0', '56', '35', '53', '22', '27'), +('3', '1', '26', '656', '0', '57', '36', '54', '22', '27'), +('3', '1', '27', '689', '0', '59', '37', '56', '22', '28'), +('3', '1', '28', '723', '0', '60', '38', '57', '23', '28'), +('3', '1', '29', '758', '0', '62', '39', '59', '23', '29'), +('3', '1', '30', '794', '0', '64', '40', '60', '23', '29'), +('3', '1', '31', '831', '0', '65', '41', '61', '23', '29'), +('3', '1', '32', '869', '0', '67', '42', '63', '23', '30'), +('3', '1', '33', '908', '0', '68', '43', '64', '23', '30'), +('3', '1', '34', '948', '0', '70', '44', '66', '24', '31'), +('3', '1', '35', '989', '0', '72', '45', '67', '24', '31'), +('3', '1', '36', '1031', '0', '74', '46', '69', '24', '32'), +('3', '1', '37', '1075', '0', '75', '47', '71', '24', '32'), +('3', '1', '38', '1121', '0', '77', '48', '72', '24', '32'), +('3', '1', '39', '1169', '0', '79', '49', '74', '25', '33'), +('3', '1', '40', '1219', '0', '81', '50', '75', '25', '33'), +('3', '1', '41', '1271', '0', '82', '52', '77', '25', '34'), +('3', '1', '42', '1325', '0', '84', '53', '79', '25', '34'), +('3', '1', '43', '1381', '0', '86', '54', '80', '25', '35'), +('3', '1', '44', '1439', '0', '88', '55', '82', '25', '35'), +('3', '1', '45', '1499', '0', '90', '56', '84', '26', '36'), +('3', '1', '46', '1561', '0', '92', '57', '86', '26', '36'), +('3', '1', '47', '1625', '0', '94', '59', '87', '26', '37'), +('3', '1', '48', '1691', '0', '96', '60', '89', '26', '37'), +('3', '1', '49', '1759', '0', '98', '61', '91', '27', '38'), +('3', '1', '50', '1829', '0', '100', '62', '93', '27', '38'), +('3', '1', '51', '1901', '0', '102', '64', '95', '27', '39'), +('3', '1', '52', '1975', '0', '104', '65', '97', '27', '39'), +('3', '1', '53', '2051', '0', '106', '66', '99', '27', '40'), +('3', '1', '54', '2129', '0', '108', '68', '101', '28', '41'), +('3', '1', '55', '2209', '0', '111', '69', '103', '28', '41'), +('3', '1', '56', '2291', '0', '113', '70', '105', '28', '42'), +('3', '1', '57', '2375', '0', '115', '72', '107', '28', '42'), +('3', '1', '58', '2461', '0', '117', '73', '109', '29', '43'), +('3', '1', '59', '2549', '0', '120', '75', '111', '29', '43'), +('3', '1', '60', '2639', '0', '122', '76', '113', '29', '44'), +('3', '2', '1', '88', '79', '24', '16', '25', '20', '19'), +('3', '2', '2', '106', '84', '25', '17', '26', '20', '21'), +('3', '2', '3', '124', '104', '26', '17', '27', '20', '21'), +('3', '2', '4', '142', '125', '27', '18', '28', '21', '22'), +('3', '2', '5', '160', '147', '28', '18', '29', '21', '23'), +('3', '2', '6', '178', '170', '29', '19', '30', '22', '23'), +('3', '2', '7', '196', '194', '30', '19', '31', '23', '24'), +('3', '2', '8', '214', '219', '31', '20', '31', '23', '24'), +('3', '2', '9', '232', '245', '32', '20', '32', '24', '25'), +('3', '2', '10', '250', '272', '33', '21', '33', '24', '26'), +('3', '2', '11', '268', '300', '34', '21', '34', '25', '27'), +('3', '2', '12', '286', '329', '35', '22', '35', '26', '27'), +('3', '2', '13', '304', '359', '36', '23', '36', '26', '28'), +('3', '2', '14', '322', '390', '37', '23', '37', '27', '29'), +('3', '2', '15', '341', '422', '38', '24', '39', '28', '29'), +('3', '2', '16', '361', '455', '40', '24', '40', '28', '30'), +('3', '2', '17', '382', '489', '41', '25', '41', '29', '31'), +('3', '2', '18', '404', '524', '42', '26', '42', '30', '32'), +('3', '2', '19', '427', '560', '43', '26', '43', '30', '32'), +('3', '2', '20', '451', '597', '44', '27', '44', '31', '33'), +('3', '2', '21', '476', '635', '45', '28', '45', '32', '34'), +('3', '2', '22', '502', '674', '47', '28', '46', '33', '35'), +('3', '2', '23', '529', '714', '48', '29', '47', '33', '36'), +('3', '2', '24', '557', '755', '49', '30', '49', '34', '36'), +('3', '2', '25', '586', '797', '50', '30', '50', '35', '37'), +('3', '2', '26', '616', '839', '52', '31', '51', '36', '38'), +('3', '2', '27', '647', '881', '53', '32', '52', '36', '39'), +('3', '2', '28', '679', '923', '54', '32', '53', '37', '40'), +('3', '2', '29', '712', '965', '56', '33', '55', '38', '41'), +('3', '2', '30', '746', '1007', '57', '34', '56', '39', '41'), +('3', '2', '31', '781', '1049', '58', '35', '57', '40', '42'), +('3', '2', '32', '817', '1091', '60', '35', '59', '41', '43'), +('3', '2', '33', '854', '1133', '61', '36', '60', '41', '44'), +('3', '2', '34', '892', '1175', '63', '37', '61', '42', '45'), +('3', '2', '35', '931', '1217', '64', '38', '63', '43', '46'), +('3', '2', '36', '971', '1259', '66', '39', '64', '44', '47'), +('3', '2', '37', '1012', '1301', '67', '39', '65', '45', '48'), +('3', '2', '38', '1054', '1343', '69', '40', '67', '46', '49'), +('3', '2', '39', '1097', '1385', '70', '41', '68', '47', '50'), +('3', '2', '40', '1141', '1427', '72', '42', '70', '48', '51'), +('3', '2', '41', '1186', '1469', '73', '43', '71', '49', '52'), +('3', '2', '42', '1232', '1511', '75', '43', '73', '50', '53'), +('3', '2', '43', '1279', '1553', '76', '44', '74', '51', '54'), +('3', '2', '44', '1327', '1595', '78', '45', '76', '51', '55'), +('3', '2', '45', '1376', '1637', '80', '46', '77', '52', '56'), +('3', '2', '46', '1426', '1679', '81', '47', '79', '53', '57'), +('3', '2', '47', '1477', '1721', '83', '48', '80', '55', '58'), +('3', '2', '48', '1529', '1763', '85', '49', '82', '56', '59'), +('3', '2', '49', '1582', '1805', '86', '50', '84', '57', '61'), +('3', '2', '50', '1636', '1847', '88', '51', '85', '58', '62'), +('3', '2', '51', '1691', '1889', '90', '52', '87', '59', '63'), +('3', '2', '52', '1747', '1931', '92', '53', '89', '60', '64'), +('3', '2', '53', '1804', '1973', '94', '54', '90', '61', '65'), +('3', '2', '54', '1862', '2015', '95', '55', '92', '62', '66'), +('3', '2', '55', '1921', '2057', '97', '56', '94', '63', '68'), +('3', '2', '56', '1981', '2099', '99', '57', '96', '64', '69'), +('3', '2', '57', '2042', '2141', '101', '58', '97', '65', '70'), +('3', '2', '58', '2104', '2183', '103', '59', '99', '67', '71'), +('3', '2', '59', '2167', '2225', '105', '60', '101', '68', '73'), +('3', '2', '60', '2231', '2267', '107', '61', '103', '69', '74'), +('3', '3', '1', '86', '84', '22', '19', '24', '20', '19'), +('3', '3', '2', '103', '90', '22', '20', '25', '20', '21'), +('3', '3', '3', '120', '111', '23', '21', '26', '20', '21'), +('3', '3', '4', '137', '133', '23', '23', '26', '21', '22'), +('3', '3', '5', '154', '156', '24', '24', '27', '21', '22'), +('3', '3', '6', '171', '180', '24', '25', '28', '22', '23'), +('3', '3', '7', '188', '205', '24', '26', '29', '22', '23'), +('3', '3', '8', '205', '231', '25', '27', '30', '23', '24'), +('3', '3', '9', '222', '258', '25', '29', '31', '23', '25'), +('3', '3', '10', '239', '286', '26', '30', '31', '24', '25'), +('3', '3', '11', '256', '315', '26', '31', '32', '24', '26'), +('3', '3', '12', '273', '345', '27', '33', '33', '25', '27'), +('3', '3', '13', '290', '376', '27', '34', '34', '26', '27'), +('3', '3', '14', '308', '408', '28', '35', '35', '26', '28'), +('3', '3', '15', '327', '441', '28', '37', '36', '27', '28'), +('3', '3', '16', '347', '475', '29', '38', '37', '27', '29'), +('3', '3', '17', '368', '510', '29', '39', '38', '28', '30'), +('3', '3', '18', '390', '546', '30', '41', '39', '29', '31'), +('3', '3', '19', '413', '583', '30', '42', '40', '29', '31'), +('3', '3', '20', '437', '621', '31', '44', '41', '30', '32'), +('3', '3', '21', '462', '660', '31', '45', '42', '31', '33'), +('3', '3', '22', '488', '700', '32', '47', '43', '31', '33'), +('3', '3', '23', '515', '741', '32', '48', '44', '32', '34'), +('3', '3', '24', '543', '783', '33', '50', '45', '33', '35'), +('3', '3', '25', '572', '826', '33', '51', '46', '33', '36'), +('3', '3', '26', '602', '870', '34', '53', '47', '34', '36'), +('3', '3', '27', '633', '915', '34', '55', '48', '35', '37'), +('3', '3', '28', '665', '960', '35', '56', '49', '35', '38'), +('3', '3', '29', '698', '1005', '35', '58', '50', '36', '39'), +('3', '3', '30', '732', '1050', '36', '60', '51', '37', '39'), +('3', '3', '31', '767', '1095', '36', '61', '53', '38', '40'), +('3', '3', '32', '803', '1140', '37', '63', '54', '38', '41'), +('3', '3', '33', '840', '1185', '38', '65', '55', '39', '42'), +('3', '3', '34', '878', '1230', '38', '66', '56', '40', '43'), +('3', '3', '35', '917', '1275', '39', '68', '57', '41', '44'), +('3', '3', '36', '957', '1320', '40', '70', '59', '42', '45'), +('3', '3', '37', '998', '1365', '40', '72', '60', '42', '45'), +('3', '3', '38', '1040', '1410', '41', '74', '61', '43', '46'), +('3', '3', '39', '1083', '1455', '41', '76', '62', '44', '47'), +('3', '3', '40', '1127', '1500', '42', '77', '64', '45', '48'), +('3', '3', '41', '1172', '1545', '43', '79', '65', '46', '49'), +('3', '3', '42', '1218', '1590', '43', '81', '66', '46', '50'), +('3', '3', '43', '1265', '1635', '44', '83', '67', '47', '51'), +('3', '3', '44', '1313', '1680', '45', '85', '69', '48', '52'), +('3', '3', '45', '1362', '1725', '45', '87', '70', '49', '53'), +('3', '3', '46', '1412', '1770', '46', '89', '72', '50', '54'), +('3', '3', '47', '1463', '1815', '47', '91', '73', '51', '55'), +('3', '3', '48', '1515', '1860', '48', '94', '74', '52', '56'), +('3', '3', '49', '1568', '1905', '48', '96', '76', '53', '57'), +('3', '3', '50', '1622', '1950', '49', '98', '77', '54', '58'), +('3', '3', '51', '1677', '1995', '50', '100', '79', '55', '59'), +('3', '3', '52', '1733', '2040', '51', '102', '80', '56', '60'), +('3', '3', '53', '1790', '2085', '51', '104', '82', '57', '61'), +('3', '3', '54', '1848', '2130', '52', '107', '83', '58', '62'), +('3', '3', '55', '1907', '2175', '53', '109', '85', '59', '63'), +('3', '3', '56', '1967', '2220', '54', '111', '86', '60', '64'), +('3', '3', '57', '2028', '2265', '55', '114', '88', '61', '66'), +('3', '3', '58', '2090', '2310', '55', '116', '90', '62', '67'), +('3', '3', '59', '2153', '2355', '56', '119', '91', '63', '68'), +('3', '3', '60', '2217', '2400', '57', '121', '93', '64', '69'), +('3', '4', '1', '85', '0', '23', '19', '24', '19', '19'), +('3', '4', '2', '102', '0', '24', '20', '25', '19', '19'), +('3', '4', '3', '119', '0', '24', '21', '25', '19', '20'), +('3', '4', '4', '136', '0', '25', '23', '26', '20', '20'), +('3', '4', '5', '153', '0', '26', '24', '27', '20', '20'), +('3', '4', '6', '170', '0', '26', '25', '27', '20', '21'), +('3', '4', '7', '187', '0', '27', '27', '28', '20', '21'), +('3', '4', '8', '204', '0', '28', '28', '28', '20', '21'), +('3', '4', '9', '221', '0', '29', '29', '29', '20', '22'), +('3', '4', '10', '238', '0', '29', '31', '30', '21', '22'), +('3', '4', '11', '255', '0', '30', '32', '31', '21', '23'), +('3', '4', '12', '272', '0', '31', '33', '31', '21', '23'), +('3', '4', '13', '289', '0', '32', '35', '32', '21', '23'), +('3', '4', '14', '306', '0', '32', '36', '33', '21', '24'), +('3', '4', '15', '323', '0', '33', '38', '33', '22', '24'), +('3', '4', '16', '341', '0', '34', '39', '34', '22', '25'), +('3', '4', '17', '360', '0', '35', '40', '35', '22', '25'), +('3', '4', '18', '380', '0', '36', '42', '36', '22', '25'), +('3', '4', '19', '401', '0', '37', '44', '36', '22', '26'), +('3', '4', '20', '423', '0', '37', '45', '37', '23', '26'), +('3', '4', '21', '446', '0', '38', '47', '38', '23', '27'), +('3', '4', '22', '470', '0', '39', '48', '39', '23', '27'), +('3', '4', '23', '495', '0', '40', '50', '40', '23', '28'), +('3', '4', '24', '521', '0', '41', '51', '40', '24', '28'), +('3', '4', '25', '548', '0', '42', '53', '41', '24', '29'), +('3', '4', '26', '576', '0', '43', '55', '42', '24', '29'), +('3', '4', '27', '605', '0', '44', '56', '43', '24', '29'), +('3', '4', '28', '635', '0', '45', '58', '44', '24', '30'), +('3', '4', '29', '666', '0', '45', '60', '45', '25', '30'), +('3', '4', '30', '698', '0', '46', '62', '45', '25', '31'), +('3', '4', '31', '731', '0', '47', '63', '46', '25', '31'), +('3', '4', '32', '765', '0', '48', '65', '47', '25', '32'), +('3', '4', '33', '800', '0', '49', '67', '48', '26', '32'), +('3', '4', '34', '836', '0', '50', '69', '49', '26', '33'), +('3', '4', '35', '873', '0', '51', '71', '50', '26', '33'), +('3', '4', '36', '911', '0', '53', '73', '51', '27', '34'), +('3', '4', '37', '950', '0', '54', '74', '52', '27', '35'), +('3', '4', '38', '990', '0', '55', '76', '53', '27', '35'), +('3', '4', '39', '1031', '0', '56', '78', '54', '27', '36'), +('3', '4', '40', '1073', '0', '57', '80', '55', '28', '36'), +('3', '4', '41', '1116', '0', '58', '82', '56', '28', '37'), +('3', '4', '42', '1160', '0', '59', '84', '57', '28', '37'), +('3', '4', '43', '1205', '0', '60', '86', '58', '28', '38'), +('3', '4', '44', '1251', '0', '61', '89', '59', '29', '38'), +('3', '4', '45', '1298', '0', '63', '91', '60', '29', '39'), +('3', '4', '46', '1346', '0', '64', '93', '61', '29', '40'), +('3', '4', '47', '1395', '0', '65', '95', '62', '30', '40'), +('3', '4', '48', '1445', '0', '66', '97', '63', '30', '41'), +('3', '4', '49', '1496', '0', '67', '99', '65', '30', '42'), +('3', '4', '50', '1548', '0', '69', '102', '66', '31', '42'), +('3', '4', '51', '1601', '0', '70', '104', '67', '31', '43'), +('3', '4', '52', '1655', '0', '71', '106', '68', '31', '43'), +('3', '4', '53', '1710', '0', '72', '109', '69', '32', '44'), +('3', '4', '54', '1766', '0', '74', '111', '70', '32', '45'), +('3', '4', '55', '1823', '0', '75', '113', '72', '32', '45'), +('3', '4', '56', '1881', '0', '76', '116', '73', '33', '46'), +('3', '4', '57', '1940', '0', '78', '118', '74', '33', '47'), +('3', '4', '58', '2000', '0', '79', '121', '75', '33', '48'), +('3', '4', '59', '2061', '0', '81', '123', '77', '34', '48'), +('3', '4', '60', '2123', '0', '82', '126', '78', '34', '49'), +('3', '5', '1', '82', '145', '22', '16', '23', '22', '21'), +('3', '5', '2', '97', '169', '22', '16', '23', '22', '23'), +('3', '5', '3', '112', '194', '22', '16', '24', '23', '24'), +('3', '5', '4', '127', '220', '23', '17', '24', '24', '26'), +('3', '5', '5', '142', '247', '23', '17', '24', '26', '27'), +('3', '5', '6', '157', '275', '23', '17', '25', '27', '28'), +('3', '5', '7', '172', '304', '23', '17', '25', '28', '29'), +('3', '5', '8', '187', '334', '23', '18', '25', '29', '30'), +('3', '5', '9', '202', '365', '23', '18', '26', '30', '32'), +('3', '5', '10', '217', '412', '24', '18', '26', '32', '33'), +('3', '5', '11', '232', '430', '24', '18', '27', '33', '34'), +('3', '5', '12', '247', '464', '24', '19', '27', '34', '36'), +('3', '5', '13', '262', '499', '24', '19', '27', '35', '37'), +('3', '5', '14', '277', '535', '24', '19', '28', '37', '38'), +('3', '5', '15', '292', '572', '25', '19', '28', '38', '40'), +('3', '5', '16', '307', '610', '25', '20', '29', '39', '41'), +('3', '5', '17', '322', '664', '25', '20', '29', '41', '42'), +('3', '5', '18', '337', '689', '25', '20', '29', '42', '44'), +('3', '5', '19', '352', '730', '25', '21', '30', '43', '45'), +('3', '5', '20', '367', '772', '26', '21', '30', '45', '47'), +('3', '5', '21', '382', '815', '26', '21', '31', '46', '48'), +('3', '5', '22', '398', '874', '26', '21', '31', '48', '50'), +('3', '5', '23', '415', '904', '26', '22', '32', '49', '51'), +('3', '5', '24', '433', '965', '27', '22', '32', '51', '53'), +('3', '5', '25', '452', '997', '27', '22', '33', '52', '54'), +('3', '5', '26', '472', '1060', '27', '23', '33', '54', '56'), +('3', '5', '27', '493', '1094', '27', '23', '33', '55', '58'), +('3', '5', '28', '515', '1159', '27', '23', '34', '57', '59'), +('3', '5', '29', '538', '1195', '28', '24', '34', '58', '61'), +('3', '5', '30', '562', '1247', '28', '24', '35', '60', '63'), +('3', '5', '31', '587', '1315', '28', '24', '35', '62', '64'), +('3', '5', '32', '613', '1354', '28', '25', '36', '63', '66'), +('3', '5', '33', '640', '1423', '29', '25', '36', '65', '68'), +('3', '5', '34', '668', '1477', '29', '25', '37', '67', '69'), +('3', '5', '35', '697', '1516', '29', '26', '37', '68', '71'), +('3', '5', '36', '727', '1570', '30', '26', '38', '70', '73'), +('3', '5', '37', '758', '1639', '30', '26', '39', '72', '75'), +('3', '5', '38', '790', '1693', '30', '27', '39', '74', '77'), +('3', '5', '39', '823', '1732', '30', '27', '40', '75', '79'), +('3', '5', '40', '857', '1786', '31', '27', '40', '77', '80'), +('3', '5', '41', '892', '1855', '31', '28', '41', '79', '82'), +('3', '5', '42', '928', '1909', '31', '28', '41', '81', '84'), +('3', '5', '43', '965', '1963', '31', '29', '42', '83', '86'), +('3', '5', '44', '1003', '2017', '32', '29', '42', '85', '88'), +('3', '5', '45', '1042', '2071', '32', '29', '43', '87', '90'), +('3', '5', '46', '1082', '2125', '32', '30', '44', '89', '92'), +('3', '5', '47', '1123', '2179', '33', '30', '44', '91', '94'), +('3', '5', '48', '1165', '2233', '33', '31', '45', '93', '97'), +('3', '5', '49', '1208', '2287', '33', '31', '46', '95', '99'), +('3', '5', '50', '1252', '2341', '34', '31', '46', '97', '101'), +('3', '5', '51', '1297', '2395', '34', '32', '47', '99', '103'), +('3', '5', '52', '1343', '2449', '34', '32', '47', '101', '105'), +('3', '5', '53', '1390', '2503', '35', '33', '48', '103', '107'), +('3', '5', '54', '1438', '2557', '35', '33', '49', '105', '110'), +('3', '5', '55', '1487', '2611', '35', '34', '49', '108', '112'), +('3', '5', '56', '1537', '2665', '36', '34', '50', '110', '114'), +('3', '5', '57', '1588', '2719', '36', '35', '51', '112', '117'), +('3', '5', '58', '1640', '2773', '36', '35', '52', '114', '119'), +('3', '5', '59', '1693', '2827', '37', '36', '52', '117', '122'), +('3', '5', '60', '1747', '2881', '37', '36', '53', '119', '124'), +('4', '1', '1', '50', '0', '20', '25', '21', '20', '20'), +('4', '1', '2', '69', '0', '21', '26', '22', '20', '20'), +('4', '1', '3', '88', '0', '22', '26', '23', '20', '21'), +('4', '1', '4', '107', '0', '23', '27', '24', '20', '21'), +('4', '1', '5', '126', '0', '25', '28', '25', '20', '21'), +('4', '1', '6', '145', '0', '26', '29', '26', '21', '21'), +('4', '1', '7', '164', '0', '27', '29', '27', '21', '22'), +('4', '1', '8', '183', '0', '28', '30', '28', '21', '22'), +('4', '1', '9', '202', '0', '29', '31', '29', '21', '22'), +('4', '1', '10', '221', '0', '30', '31', '30', '21', '23'), +('4', '1', '11', '240', '0', '32', '32', '32', '21', '23'), +('4', '1', '12', '259', '0', '33', '33', '33', '21', '23'), +('4', '1', '13', '278', '0', '34', '34', '34', '21', '24'), +('4', '1', '14', '298', '0', '36', '35', '35', '22', '24'), +('4', '1', '15', '319', '0', '37', '35', '36', '22', '24'), +('4', '1', '16', '341', '0', '38', '36', '37', '22', '25'), +('4', '1', '17', '364', '0', '39', '37', '39', '22', '25'), +('4', '1', '18', '388', '0', '41', '38', '40', '22', '25'), +('4', '1', '19', '413', '0', '42', '39', '41', '22', '26'), +('4', '1', '20', '439', '0', '44', '40', '42', '22', '26'), +('4', '1', '21', '466', '0', '45', '40', '44', '23', '26'), +('4', '1', '22', '494', '0', '46', '41', '45', '23', '27'), +('4', '1', '23', '523', '0', '48', '42', '46', '23', '27'), +('4', '1', '24', '553', '0', '49', '43', '48', '23', '28'), +('4', '1', '25', '584', '0', '51', '44', '49', '23', '28'), +('4', '1', '26', '616', '0', '52', '45', '50', '23', '28'), +('4', '1', '27', '649', '0', '54', '46', '52', '23', '29'), +('4', '1', '28', '683', '0', '55', '47', '53', '24', '29'), +('4', '1', '29', '718', '0', '57', '48', '55', '24', '30'), +('4', '1', '30', '754', '0', '59', '49', '56', '24', '30'), +('4', '1', '31', '791', '0', '60', '50', '57', '24', '30'), +('4', '1', '32', '829', '0', '62', '51', '59', '24', '31'), +('4', '1', '33', '868', '0', '63', '52', '60', '24', '31'), +('4', '1', '34', '908', '0', '65', '53', '62', '25', '32'), +('4', '1', '35', '949', '0', '67', '54', '63', '25', '32'), +('4', '1', '36', '991', '0', '69', '55', '65', '25', '33'), +('4', '1', '37', '1035', '0', '70', '56', '67', '25', '33'), +('4', '1', '38', '1081', '0', '72', '57', '68', '25', '33'), +('4', '1', '39', '1129', '0', '74', '58', '70', '26', '34'), +('4', '1', '40', '1179', '0', '76', '59', '71', '26', '34'), +('4', '1', '41', '1231', '0', '77', '61', '73', '26', '35'), +('4', '1', '42', '1285', '0', '79', '62', '75', '26', '35'), +('4', '1', '43', '1341', '0', '81', '63', '76', '26', '36'), +('4', '1', '44', '1399', '0', '83', '64', '78', '26', '36'), +('4', '1', '45', '1459', '0', '85', '65', '80', '27', '37'), +('4', '1', '46', '1521', '0', '87', '66', '82', '27', '37'), +('4', '1', '47', '1585', '0', '89', '68', '83', '27', '38'), +('4', '1', '48', '1651', '0', '91', '69', '85', '27', '38'), +('4', '1', '49', '1719', '0', '93', '70', '87', '28', '39'), +('4', '1', '50', '1789', '0', '95', '71', '89', '28', '39'), +('4', '1', '51', '1861', '0', '97', '73', '91', '28', '40'), +('4', '1', '52', '1935', '0', '99', '74', '93', '28', '40'), +('4', '1', '53', '2011', '0', '101', '75', '95', '28', '41'), +('4', '1', '54', '2089', '0', '103', '77', '97', '29', '42'), +('4', '1', '55', '2169', '0', '106', '78', '99', '29', '42'), +('4', '1', '56', '2251', '0', '108', '79', '101', '29', '43'), +('4', '1', '57', '2335', '0', '110', '81', '103', '29', '43'), +('4', '1', '58', '2421', '0', '112', '82', '105', '30', '44'), +('4', '1', '59', '2509', '0', '115', '84', '107', '30', '44'), +('4', '1', '60', '2599', '0', '117', '85', '109', '30', '45'), +('4', '3', '1', '46', '85', '17', '28', '20', '21', '20'), +('4', '3', '2', '63', '105', '17', '29', '21', '21', '22'), +('4', '3', '3', '80', '126', '18', '30', '22', '21', '22'), +('4', '3', '4', '97', '148', '18', '32', '22', '22', '23'), +('4', '3', '5', '114', '171', '19', '33', '23', '22', '23'), +('4', '3', '6', '131', '195', '19', '34', '24', '23', '24'), +('4', '3', '7', '148', '220', '19', '35', '25', '23', '24'), +('4', '3', '8', '165', '246', '20', '36', '26', '24', '25'), +('4', '3', '9', '182', '273', '20', '38', '27', '24', '26'), +('4', '3', '10', '199', '301', '21', '39', '27', '25', '26'), +('4', '3', '11', '216', '330', '21', '40', '28', '25', '27'), +('4', '3', '12', '233', '360', '22', '42', '29', '26', '28'), +('4', '3', '13', '250', '391', '22', '43', '30', '27', '28'), +('4', '3', '14', '268', '423', '23', '44', '31', '27', '29'), +('4', '3', '15', '287', '456', '23', '46', '32', '28', '29'), +('4', '3', '16', '307', '490', '24', '47', '33', '28', '30'), +('4', '3', '17', '328', '525', '24', '48', '34', '29', '31'), +('4', '3', '18', '350', '561', '25', '50', '35', '30', '32'), +('4', '3', '19', '373', '598', '25', '51', '36', '30', '32'), +('4', '3', '20', '397', '636', '26', '53', '37', '31', '33'), +('4', '3', '21', '422', '675', '26', '54', '38', '32', '34'), +('4', '3', '22', '448', '715', '27', '56', '39', '32', '34'), +('4', '3', '23', '475', '756', '27', '57', '40', '33', '35'), +('4', '3', '24', '503', '798', '28', '59', '41', '34', '36'), +('4', '3', '25', '532', '841', '28', '60', '42', '34', '37'), +('4', '3', '26', '562', '885', '29', '62', '43', '35', '37'), +('4', '3', '27', '593', '930', '29', '64', '44', '36', '38'), +('4', '3', '28', '625', '975', '30', '65', '45', '36', '39'), +('4', '3', '29', '658', '1020', '30', '67', '46', '37', '40'), +('4', '3', '30', '692', '1065', '31', '69', '47', '38', '40'), +('4', '3', '31', '727', '1110', '31', '70', '49', '39', '41'), +('4', '3', '32', '763', '1155', '32', '72', '50', '39', '42'), +('4', '3', '33', '800', '1200', '33', '74', '51', '40', '43'), +('4', '3', '34', '838', '1245', '33', '75', '52', '41', '44'), +('4', '3', '35', '877', '1290', '34', '77', '53', '42', '45'), +('4', '3', '36', '917', '1335', '35', '79', '55', '43', '46'), +('4', '3', '37', '958', '1380', '35', '81', '56', '43', '46'), +('4', '3', '38', '1000', '1425', '36', '83', '57', '44', '47'), +('4', '3', '39', '1043', '1470', '36', '85', '58', '45', '48'), +('4', '3', '40', '1087', '1515', '37', '86', '60', '46', '49'), +('4', '3', '41', '1132', '1560', '38', '88', '61', '47', '50'), +('4', '3', '42', '1178', '1605', '38', '90', '62', '47', '51'), +('4', '3', '43', '1225', '1650', '39', '92', '63', '48', '52'), +('4', '3', '44', '1273', '1695', '40', '94', '65', '49', '53'), +('4', '3', '45', '1322', '1740', '40', '96', '66', '50', '54'), +('4', '3', '46', '1372', '1785', '41', '98', '68', '51', '55'), +('4', '3', '47', '1423', '1830', '42', '100', '69', '52', '56'), +('4', '3', '48', '1475', '1875', '43', '103', '70', '53', '57'), +('4', '3', '49', '1528', '1920', '43', '105', '72', '54', '58'), +('4', '3', '50', '1582', '1965', '44', '107', '73', '55', '59'), +('4', '3', '51', '1637', '2010', '45', '109', '75', '56', '60'), +('4', '3', '52', '1693', '2055', '46', '111', '76', '57', '61'), +('4', '3', '53', '1750', '2100', '46', '113', '78', '58', '62'), +('4', '3', '54', '1808', '2145', '47', '116', '79', '59', '63'), +('4', '3', '55', '1867', '2190', '48', '118', '81', '60', '64'), +('4', '3', '56', '1927', '2235', '49', '120', '82', '61', '65'), +('4', '3', '57', '1988', '2280', '50', '123', '84', '62', '67'), +('4', '3', '58', '2050', '2325', '50', '125', '86', '63', '68'), +('4', '3', '59', '2113', '2370', '51', '128', '87', '64', '69'), +('4', '3', '60', '2177', '2415', '52', '130', '89', '65', '70'), +('4', '4', '1', '45', '0', '18', '28', '20', '20', '20'), +('4', '4', '2', '62', '0', '19', '29', '21', '20', '20'), +('4', '4', '3', '79', '0', '19', '30', '21', '20', '21'), +('4', '4', '4', '96', '0', '20', '32', '22', '21', '21'), +('4', '4', '5', '113', '0', '21', '33', '23', '21', '21'), +('4', '4', '6', '130', '0', '21', '34', '23', '21', '22'), +('4', '4', '7', '147', '0', '22', '36', '24', '21', '22'), +('4', '4', '8', '164', '0', '23', '37', '24', '21', '22'), +('4', '4', '9', '181', '0', '24', '38', '25', '21', '23'), +('4', '4', '10', '198', '0', '24', '40', '26', '22', '23'), +('4', '4', '11', '215', '0', '25', '41', '27', '22', '24'), +('4', '4', '12', '232', '0', '26', '42', '27', '22', '24'), +('4', '4', '13', '249', '0', '27', '44', '28', '22', '24'), +('4', '4', '14', '266', '0', '27', '45', '29', '22', '25'), +('4', '4', '15', '283', '0', '28', '47', '29', '23', '25'), +('4', '4', '16', '301', '0', '29', '48', '30', '23', '26'), +('4', '4', '17', '320', '0', '30', '49', '31', '23', '26'), +('4', '4', '18', '340', '0', '31', '51', '32', '23', '26'), +('4', '4', '19', '361', '0', '32', '53', '32', '23', '27'), +('4', '4', '20', '383', '0', '32', '54', '33', '24', '27'), +('4', '4', '21', '406', '0', '33', '56', '34', '24', '28'), +('4', '4', '22', '430', '0', '34', '57', '35', '24', '28'), +('4', '4', '23', '455', '0', '35', '59', '36', '24', '29'), +('4', '4', '24', '481', '0', '36', '60', '36', '25', '29'), +('4', '4', '25', '508', '0', '37', '62', '37', '25', '30'), +('4', '4', '26', '536', '0', '38', '64', '38', '25', '30'), +('4', '4', '27', '565', '0', '39', '65', '39', '25', '30'), +('4', '4', '28', '595', '0', '40', '67', '40', '25', '31'), +('4', '4', '29', '626', '0', '40', '69', '41', '26', '31'), +('4', '4', '30', '658', '0', '41', '71', '41', '26', '32'), +('4', '4', '31', '691', '0', '42', '72', '42', '26', '32'), +('4', '4', '32', '725', '0', '43', '74', '43', '26', '33'), +('4', '4', '33', '760', '0', '44', '76', '44', '27', '33'), +('4', '4', '34', '796', '0', '45', '78', '45', '27', '34'), +('4', '4', '35', '833', '0', '46', '80', '46', '27', '34'), +('4', '4', '36', '871', '0', '48', '82', '47', '28', '35'), +('4', '4', '37', '910', '0', '49', '83', '48', '28', '36'), +('4', '4', '38', '950', '0', '50', '85', '49', '28', '36'), +('4', '4', '39', '991', '0', '51', '87', '50', '28', '37'), +('4', '4', '40', '1033', '0', '52', '89', '51', '29', '37'), +('4', '4', '41', '1076', '0', '53', '91', '52', '29', '38'), +('4', '4', '42', '1120', '0', '54', '93', '53', '29', '38'), +('4', '4', '43', '1165', '0', '55', '95', '54', '29', '39'), +('4', '4', '44', '1211', '0', '56', '98', '55', '30', '39'), +('4', '4', '45', '1258', '0', '58', '100', '56', '30', '40'), +('4', '4', '46', '1306', '0', '59', '102', '57', '30', '41'), +('4', '4', '47', '1355', '0', '60', '104', '58', '31', '41'), +('4', '4', '48', '1405', '0', '61', '106', '59', '31', '42'), +('4', '4', '49', '1456', '0', '62', '108', '61', '31', '43'), +('4', '4', '50', '1508', '0', '64', '111', '62', '32', '43'), +('4', '4', '51', '1561', '0', '65', '113', '63', '32', '44'), +('4', '4', '52', '1615', '0', '66', '115', '64', '32', '44'), +('4', '4', '53', '1670', '0', '67', '118', '65', '33', '45'), +('4', '4', '54', '1726', '0', '69', '120', '66', '33', '46'), +('4', '4', '55', '1783', '0', '70', '122', '68', '33', '46'), +('4', '4', '56', '1841', '0', '71', '125', '69', '34', '47'), +('4', '4', '57', '1900', '0', '73', '127', '70', '34', '48'), +('4', '4', '58', '1960', '0', '74', '130', '71', '34', '49'), +('4', '4', '59', '2021', '0', '76', '132', '73', '35', '49'), +('4', '4', '60', '2083', '0', '77', '135', '74', '35', '50'), +('4', '5', '1', '51', '160', '17', '25', '19', '23', '22'), +('4', '5', '2', '66', '184', '17', '25', '19', '23', '24'), +('4', '5', '3', '72', '209', '17', '25', '20', '24', '25'), +('4', '5', '4', '87', '235', '18', '26', '20', '25', '27'), +('4', '5', '5', '102', '262', '18', '26', '20', '27', '28'), +('4', '5', '6', '117', '290', '18', '26', '21', '28', '29'), +('4', '5', '7', '132', '319', '18', '26', '21', '29', '30'), +('4', '5', '8', '147', '349', '18', '27', '21', '30', '31'), +('4', '5', '9', '162', '380', '18', '27', '22', '31', '33'), +('4', '5', '10', '177', '427', '19', '27', '22', '33', '34'), +('4', '5', '11', '192', '445', '19', '27', '23', '34', '35'), +('4', '5', '12', '207', '479', '19', '28', '23', '35', '37'), +('4', '5', '13', '222', '514', '19', '28', '23', '36', '38'), +('4', '5', '14', '237', '550', '19', '28', '24', '38', '39'), +('4', '5', '15', '252', '587', '20', '28', '24', '39', '41'), +('4', '5', '16', '267', '625', '20', '29', '25', '40', '42'), +('4', '5', '17', '282', '679', '20', '29', '25', '42', '43'), +('4', '5', '18', '297', '704', '20', '29', '25', '43', '45'), +('4', '5', '19', '312', '745', '20', '30', '26', '44', '46'), +('4', '5', '20', '327', '787', '21', '30', '26', '46', '48'), +('4', '5', '21', '342', '830', '21', '30', '27', '47', '49'), +('4', '5', '22', '358', '889', '21', '30', '27', '49', '51'), +('4', '5', '23', '375', '919', '21', '31', '28', '50', '52'), +('4', '5', '24', '393', '980', '22', '31', '28', '52', '54'), +('4', '5', '25', '412', '1012', '22', '31', '29', '53', '55'), +('4', '5', '26', '432', '1075', '22', '32', '29', '55', '57'), +('4', '5', '27', '453', '1109', '22', '32', '29', '56', '59'), +('4', '5', '28', '475', '1174', '22', '32', '30', '58', '60'), +('4', '5', '29', '498', '1210', '23', '33', '30', '59', '62'), +('4', '5', '30', '522', '1262', '23', '33', '31', '61', '64'), +('4', '5', '31', '547', '1330', '23', '33', '31', '63', '65'), +('4', '5', '32', '573', '1369', '23', '34', '32', '64', '67'), +('4', '5', '33', '600', '1438', '24', '34', '32', '66', '69'), +('4', '5', '34', '628', '1492', '24', '34', '33', '68', '70'), +('4', '5', '35', '657', '1531', '24', '35', '33', '69', '72'), +('4', '5', '36', '687', '1585', '25', '35', '34', '71', '74'), +('4', '5', '37', '718', '1654', '25', '35', '35', '73', '76'), +('4', '5', '38', '750', '1708', '25', '36', '35', '75', '78'), +('4', '5', '39', '783', '1747', '25', '36', '36', '76', '80'), +('4', '5', '40', '817', '1801', '26', '36', '36', '78', '81'), +('4', '5', '41', '852', '1870', '26', '37', '37', '80', '83'), +('4', '5', '42', '888', '1924', '26', '37', '37', '82', '85'), +('4', '5', '43', '925', '1978', '26', '38', '38', '84', '87'), +('4', '5', '44', '963', '2032', '27', '38', '38', '86', '89'), +('4', '5', '45', '1002', '2086', '27', '38', '39', '88', '91'), +('4', '5', '46', '1042', '2140', '27', '39', '40', '90', '93'), +('4', '5', '47', '1083', '2194', '28', '39', '40', '92', '95'), +('4', '5', '48', '1125', '2248', '28', '40', '41', '94', '98'), +('4', '5', '49', '1168', '2302', '28', '40', '42', '96', '100'), +('4', '5', '50', '1212', '2356', '29', '40', '42', '98', '102'), +('4', '5', '51', '1257', '2410', '29', '41', '43', '100', '104'), +('4', '5', '52', '1303', '2464', '29', '41', '43', '102', '106'), +('4', '5', '53', '1350', '2518', '30', '42', '44', '104', '108'), +('4', '5', '54', '1398', '2572', '30', '42', '45', '106', '111'), +('4', '5', '55', '1447', '2626', '30', '43', '45', '109', '113'), +('4', '5', '56', '1497', '2680', '31', '43', '46', '111', '115'), +('4', '5', '57', '1548', '2734', '31', '44', '47', '113', '118'), +('4', '5', '58', '1600', '2788', '31', '44', '48', '115', '120'), +('4', '5', '59', '1653', '2842', '32', '45', '48', '118', '123'), +('4', '5', '60', '1707', '2896', '32', '45', '49', '120', '125'), +('4', '11', '1', '53', '100', '18', '25', '19', '22', '22'), +('4', '11', '2', '61', '122', '19', '25', '20', '23', '23'), +('4', '11', '3', '78', '145', '19', '26', '20', '24', '24'), +('4', '11', '4', '95', '169', '20', '26', '21', '25', '25'), +('4', '11', '5', '112', '194', '20', '27', '21', '26', '26'), +('4', '11', '6', '129', '220', '21', '27', '22', '27', '27'), +('4', '11', '7', '146', '247', '21', '28', '23', '28', '28'), +('4', '11', '8', '163', '260', '22', '28', '23', '28', '29'), +('4', '11', '9', '180', '289', '22', '29', '24', '29', '30'), +('4', '11', '10', '197', '319', '23', '29', '24', '30', '31'), +('4', '11', '11', '214', '350', '23', '30', '25', '31', '33'), +('4', '11', '12', '231', '382', '24', '30', '26', '32', '34'), +('4', '11', '13', '248', '415', '24', '31', '26', '33', '35'), +('4', '11', '14', '265', '449', '25', '31', '27', '34', '36'), +('4', '11', '15', '282', '499', '26', '32', '28', '36', '37'), +('4', '11', '16', '299', '535', '26', '32', '28', '37', '38'), +('4', '11', '17', '316', '572', '27', '33', '29', '38', '40'), +('4', '11', '18', '334', '610', '27', '34', '30', '39', '41'), +('4', '11', '19', '353', '649', '28', '34', '30', '40', '42'), +('4', '11', '20', '373', '689', '29', '35', '31', '41', '43'), +('4', '11', '21', '394', '730', '29', '35', '32', '42', '45'), +('4', '11', '22', '416', '757', '30', '36', '33', '43', '46'), +('4', '11', '23', '439', '800', '31', '37', '33', '44', '47'), +('4', '11', '24', '463', '859', '31', '37', '34', '46', '49'), +('4', '11', '25', '488', '904', '32', '38', '35', '47', '50'), +('4', '11', '26', '514', '949', '33', '38', '36', '48', '51'), +('4', '11', '27', '541', '979', '33', '39', '36', '49', '53'), +('4', '11', '28', '569', '1024', '34', '40', '37', '50', '54'), +('4', '11', '29', '598', '1084', '35', '40', '38', '52', '56'), +('4', '11', '30', '628', '1129', '35', '41', '39', '53', '57'), +('4', '11', '31', '659', '1159', '36', '42', '40', '54', '58'), +('4', '11', '32', '691', '1219', '37', '42', '41', '56', '60'), +('4', '11', '33', '724', '1264', '38', '43', '41', '57', '61'), +('4', '11', '34', '758', '1294', '38', '44', '42', '58', '63'), +('4', '11', '35', '793', '1354', '39', '44', '43', '60', '64'), +('4', '11', '36', '829', '1384', '40', '45', '44', '61', '66'), +('4', '11', '37', '866', '1429', '41', '46', '45', '62', '68'), +('4', '11', '38', '904', '1489', '42', '46', '46', '64', '69'), +('4', '11', '39', '943', '1519', '42', '47', '47', '65', '71'), +('4', '11', '40', '983', '1579', '43', '48', '48', '67', '72'), +('4', '11', '41', '1024', '1609', '44', '49', '49', '68', '74'), +('4', '11', '42', '1066', '1669', '45', '49', '50', '70', '76'), +('4', '11', '43', '1109', '1699', '46', '50', '51', '71', '77'), +('4', '11', '44', '1153', '1759', '47', '51', '51', '73', '79'), +('4', '11', '45', '1198', '1789', '47', '52', '52', '74', '81'), +('4', '11', '46', '1244', '1849', '48', '53', '53', '76', '83'), +('4', '11', '47', '1291', '1879', '49', '53', '55', '77', '84'), +('4', '11', '48', '1339', '1924', '50', '54', '56', '79', '86'), +('4', '11', '49', '1388', '1984', '51', '55', '57', '81', '88'), +('4', '11', '50', '1438', '2014', '52', '56', '58', '82', '90'), +('4', '11', '51', '1489', '2059', '53', '57', '59', '84', '92'), +('4', '11', '52', '1541', '2119', '54', '58', '60', '86', '94'), +('4', '11', '53', '1594', '2149', '55', '59', '61', '87', '96'), +('4', '11', '54', '1648', '2194', '56', '59', '62', '89', '98'), +('4', '11', '55', '1703', '2239', '57', '60', '63', '91', '100'), +('4', '11', '56', '1759', '2284', '58', '61', '64', '93', '102'), +('4', '11', '57', '1816', '2329', '59', '62', '65', '94', '104'), +('4', '11', '58', '1874', '2374', '60', '63', '67', '96', '106'), +('4', '11', '59', '1933', '2419', '61', '64', '68', '98', '108'), +('4', '11', '60', '1993', '2464', '62', '65', '69', '100', '110'), +('5', '1', '1', '70', '0', '22', '18', '23', '25', '18'), +('5', '1', '2', '89', '0', '23', '19', '24', '18', '25'), +('5', '1', '3', '108', '0', '24', '19', '25', '18', '26'), +('5', '1', '4', '127', '0', '25', '20', '26', '18', '26'), +('5', '1', '5', '146', '0', '27', '21', '27', '18', '26'), +('5', '1', '6', '165', '0', '28', '22', '28', '19', '26'), +('5', '1', '7', '184', '0', '29', '22', '29', '19', '27'), +('5', '1', '8', '203', '0', '30', '23', '30', '19', '27'), +('5', '1', '9', '222', '0', '31', '24', '31', '19', '27'), +('5', '1', '10', '241', '0', '32', '24', '32', '19', '28'), +('5', '1', '11', '260', '0', '34', '25', '34', '19', '28'), +('5', '1', '12', '279', '0', '35', '26', '35', '19', '28'), +('5', '1', '13', '298', '0', '36', '27', '36', '19', '29'), +('5', '1', '14', '318', '0', '38', '28', '37', '20', '29'), +('5', '1', '15', '339', '0', '39', '28', '38', '20', '29'), +('5', '1', '16', '361', '0', '40', '29', '39', '20', '30'), +('5', '1', '17', '384', '0', '41', '30', '41', '20', '30'), +('5', '1', '18', '408', '0', '43', '31', '42', '20', '30'), +('5', '1', '19', '433', '0', '44', '32', '43', '20', '31'), +('5', '1', '20', '459', '0', '46', '33', '44', '20', '31'), +('5', '1', '21', '486', '0', '47', '33', '46', '21', '31'), +('5', '1', '22', '514', '0', '48', '34', '47', '21', '32'), +('5', '1', '23', '543', '0', '50', '35', '48', '21', '32'), +('5', '1', '24', '573', '0', '51', '36', '50', '21', '33'), +('5', '1', '25', '604', '0', '53', '37', '51', '21', '33'), +('5', '1', '26', '636', '0', '54', '38', '52', '21', '33'), +('5', '1', '27', '669', '0', '56', '39', '54', '21', '34'), +('5', '1', '28', '703', '0', '57', '40', '55', '22', '34'), +('5', '1', '29', '738', '0', '59', '41', '57', '22', '35'), +('5', '1', '30', '774', '0', '61', '42', '58', '22', '35'), +('5', '1', '31', '811', '0', '62', '43', '59', '22', '35'), +('5', '1', '32', '849', '0', '64', '44', '61', '22', '36'), +('5', '1', '33', '888', '0', '65', '45', '62', '22', '36'), +('5', '1', '34', '928', '0', '67', '46', '64', '23', '37'), +('5', '1', '35', '969', '0', '69', '47', '65', '23', '37'), +('5', '1', '36', '1011', '0', '71', '48', '67', '23', '38'), +('5', '1', '37', '1055', '0', '72', '49', '69', '23', '38'), +('5', '1', '38', '1101', '0', '74', '50', '70', '23', '38'), +('5', '1', '39', '1149', '0', '76', '51', '72', '24', '39'), +('5', '1', '40', '1199', '0', '78', '52', '73', '24', '39'), +('5', '1', '41', '1251', '0', '79', '54', '75', '24', '40'), +('5', '1', '42', '1305', '0', '81', '55', '77', '24', '40'), +('5', '1', '43', '1361', '0', '83', '56', '78', '24', '41'), +('5', '1', '44', '1419', '0', '85', '57', '80', '24', '41'), +('5', '1', '45', '1479', '0', '87', '58', '82', '25', '42'), +('5', '1', '46', '1541', '0', '89', '59', '84', '25', '42'), +('5', '1', '47', '1605', '0', '91', '61', '85', '25', '43'), +('5', '1', '48', '1671', '0', '93', '62', '87', '25', '43'), +('5', '1', '49', '1739', '0', '95', '63', '89', '26', '44'), +('5', '1', '50', '1809', '0', '97', '64', '91', '26', '44'), +('5', '1', '51', '1881', '0', '99', '66', '93', '26', '45'), +('5', '1', '52', '1955', '0', '101', '67', '95', '26', '45'), +('5', '1', '53', '2031', '0', '103', '68', '97', '26', '46'), +('5', '1', '54', '2109', '0', '105', '70', '99', '27', '47'), +('5', '1', '55', '2189', '0', '108', '71', '101', '27', '47'), +('5', '1', '56', '2271', '0', '110', '72', '103', '27', '48'), +('5', '1', '57', '2355', '0', '112', '74', '105', '27', '48'), +('5', '1', '58', '2441', '0', '114', '75', '107', '28', '49'), +('5', '1', '59', '2529', '0', '117', '77', '109', '28', '49'), +('5', '1', '60', '2619', '0', '119', '78', '111', '28', '50'), +('5', '4', '1', '65', '0', '20', '21', '22', '25', '18'), +('5', '4', '2', '82', '0', '21', '22', '23', '18', '25'), +('5', '4', '3', '99', '0', '21', '23', '23', '18', '26'), +('5', '4', '4', '116', '0', '22', '25', '24', '19', '26'), +('5', '4', '5', '133', '0', '23', '26', '25', '19', '26'), +('5', '4', '6', '150', '0', '23', '27', '25', '19', '27'), +('5', '4', '7', '167', '0', '24', '29', '26', '19', '27'), +('5', '4', '8', '184', '0', '25', '30', '26', '19', '27'), +('5', '4', '9', '201', '0', '26', '31', '27', '19', '28'), +('5', '4', '10', '218', '0', '26', '33', '28', '20', '28'), +('5', '4', '11', '235', '0', '27', '34', '29', '20', '29'), +('5', '4', '12', '252', '0', '28', '35', '29', '20', '29'), +('5', '4', '13', '269', '0', '29', '37', '30', '20', '29'), +('5', '4', '14', '286', '0', '29', '38', '31', '20', '30'), +('5', '4', '15', '303', '0', '30', '40', '31', '21', '30'), +('5', '4', '16', '321', '0', '31', '41', '32', '21', '31'), +('5', '4', '17', '340', '0', '32', '42', '33', '21', '31'), +('5', '4', '18', '360', '0', '33', '44', '34', '21', '31'), +('5', '4', '19', '381', '0', '34', '46', '34', '21', '32'), +('5', '4', '20', '403', '0', '34', '47', '35', '22', '32'), +('5', '4', '21', '426', '0', '35', '49', '36', '22', '33'), +('5', '4', '22', '450', '0', '36', '50', '37', '22', '33'), +('5', '4', '23', '475', '0', '37', '52', '38', '22', '34'), +('5', '4', '24', '501', '0', '38', '53', '38', '23', '34'), +('5', '4', '25', '528', '0', '39', '55', '39', '23', '35'), +('5', '4', '26', '556', '0', '40', '57', '40', '23', '35'), +('5', '4', '27', '585', '0', '41', '58', '41', '23', '35'), +('5', '4', '28', '615', '0', '42', '60', '42', '23', '36'), +('5', '4', '29', '646', '0', '42', '62', '43', '24', '36'), +('5', '4', '30', '678', '0', '43', '64', '43', '24', '37'), +('5', '4', '31', '711', '0', '44', '65', '44', '24', '37'), +('5', '4', '32', '745', '0', '45', '67', '45', '24', '38'), +('5', '4', '33', '780', '0', '46', '69', '46', '25', '38'), +('5', '4', '34', '816', '0', '47', '71', '47', '25', '39'), +('5', '4', '35', '853', '0', '48', '73', '48', '25', '39'), +('5', '4', '36', '891', '0', '50', '75', '49', '26', '40'), +('5', '4', '37', '930', '0', '51', '76', '50', '26', '41'), +('5', '4', '38', '970', '0', '52', '78', '51', '26', '41'), +('5', '4', '39', '1011', '0', '53', '80', '52', '26', '42'), +('5', '4', '40', '1053', '0', '54', '82', '53', '27', '42'), +('5', '4', '41', '1096', '0', '55', '84', '54', '27', '43'), +('5', '4', '42', '1140', '0', '56', '86', '55', '27', '43'), +('5', '4', '43', '1185', '0', '57', '88', '56', '27', '44'), +('5', '4', '44', '1231', '0', '58', '91', '57', '28', '44'), +('5', '4', '45', '1278', '0', '60', '93', '58', '28', '45'), +('5', '4', '46', '1326', '0', '61', '95', '59', '28', '46'), +('5', '4', '47', '1375', '0', '62', '97', '60', '29', '46'), +('5', '4', '48', '1425', '0', '63', '99', '61', '29', '47'), +('5', '4', '49', '1476', '0', '64', '101', '63', '29', '48'), +('5', '4', '50', '1528', '0', '66', '104', '64', '30', '48'), +('5', '4', '51', '1581', '0', '67', '106', '65', '30', '49'), +('5', '4', '52', '1635', '0', '68', '108', '66', '30', '49'), +('5', '4', '53', '1690', '0', '69', '111', '67', '31', '50'), +('5', '4', '54', '1746', '0', '71', '113', '68', '31', '51'), +('5', '4', '55', '1803', '0', '72', '115', '70', '31', '51'), +('5', '4', '56', '1861', '0', '73', '118', '71', '32', '52'), +('5', '4', '57', '1920', '0', '75', '120', '72', '32', '53'), +('5', '4', '58', '1980', '0', '76', '123', '73', '32', '54'), +('5', '4', '59', '2041', '0', '78', '125', '75', '33', '54'), +('5', '4', '60', '2103', '0', '79', '128', '76', '33', '55'), +('5', '5', '1', '62', '130', '19', '18', '21', '28', '20'), +('5', '5', '2', '77', '154', '19', '18', '21', '21', '29'), +('5', '5', '3', '92', '179', '19', '18', '22', '22', '30'), +('5', '5', '4', '107', '205', '20', '19', '22', '23', '32'), +('5', '5', '5', '122', '232', '20', '19', '22', '25', '33'), +('5', '5', '6', '137', '260', '20', '19', '23', '26', '34'), +('5', '5', '7', '152', '289', '20', '19', '23', '27', '35'), +('5', '5', '8', '167', '319', '20', '20', '23', '28', '36'), +('5', '5', '9', '182', '350', '20', '20', '24', '29', '38'), +('5', '5', '10', '197', '397', '21', '20', '24', '31', '39'), +('5', '5', '11', '212', '415', '21', '20', '25', '32', '40'), +('5', '5', '12', '227', '449', '21', '21', '25', '33', '42'), +('5', '5', '13', '242', '484', '21', '21', '25', '34', '43'), +('5', '5', '14', '257', '520', '21', '21', '26', '36', '44'), +('5', '5', '15', '272', '557', '22', '21', '26', '37', '46'), +('5', '5', '16', '287', '595', '22', '22', '27', '38', '47'), +('5', '5', '17', '302', '649', '22', '22', '27', '40', '48'), +('5', '5', '18', '317', '674', '22', '22', '27', '41', '50'), +('5', '5', '19', '332', '715', '22', '23', '28', '42', '51'), +('5', '5', '20', '347', '757', '23', '23', '28', '44', '53'), +('5', '5', '21', '362', '800', '23', '23', '29', '45', '54'), +('5', '5', '22', '378', '859', '23', '23', '29', '47', '56'), +('5', '5', '23', '395', '889', '23', '24', '30', '48', '57'), +('5', '5', '24', '413', '950', '24', '24', '30', '50', '59'), +('5', '5', '25', '432', '982', '24', '24', '31', '51', '60'), +('5', '5', '26', '452', '1045', '24', '25', '31', '53', '62'), +('5', '5', '27', '473', '1079', '24', '25', '31', '54', '64'), +('5', '5', '28', '495', '1144', '24', '25', '32', '56', '65'), +('5', '5', '29', '518', '1180', '25', '26', '32', '57', '67'), +('5', '5', '30', '542', '1232', '25', '26', '33', '59', '69'), +('5', '5', '31', '567', '1300', '25', '26', '33', '61', '70'), +('5', '5', '32', '593', '1339', '25', '27', '34', '62', '72'), +('5', '5', '33', '620', '1408', '26', '27', '34', '64', '74'), +('5', '5', '34', '648', '1462', '26', '27', '35', '66', '75'), +('5', '5', '35', '677', '1501', '26', '28', '35', '67', '77'), +('5', '5', '36', '707', '1555', '27', '28', '36', '69', '79'), +('5', '5', '37', '738', '1624', '27', '28', '37', '71', '81'), +('5', '5', '38', '770', '1678', '27', '29', '37', '73', '83'), +('5', '5', '39', '803', '1717', '27', '29', '38', '74', '85'), +('5', '5', '40', '837', '1771', '28', '29', '38', '76', '86'), +('5', '5', '41', '872', '1840', '28', '30', '39', '78', '88'), +('5', '5', '42', '908', '1894', '28', '30', '39', '80', '90'), +('5', '5', '43', '945', '1948', '28', '31', '40', '82', '92'), +('5', '5', '44', '983', '2002', '29', '31', '40', '84', '94'), +('5', '5', '45', '1022', '2056', '29', '31', '41', '86', '96'), +('5', '5', '46', '1062', '2110', '29', '32', '42', '88', '98'), +('5', '5', '47', '1103', '2164', '30', '32', '42', '90', '100'), +('5', '5', '48', '1145', '2218', '30', '33', '43', '92', '103'), +('5', '5', '49', '1188', '2272', '30', '33', '44', '94', '105'), +('5', '5', '50', '1232', '2326', '31', '33', '44', '96', '107'), +('5', '5', '51', '1277', '2380', '31', '34', '45', '98', '109'), +('5', '5', '52', '1323', '2434', '31', '34', '45', '100', '111'), +('5', '5', '53', '1370', '2488', '32', '35', '46', '102', '113'), +('5', '5', '54', '1418', '2542', '32', '35', '47', '104', '116'), +('5', '5', '55', '1467', '2596', '32', '36', '47', '107', '118'), +('5', '5', '56', '1517', '2650', '33', '36', '48', '109', '120'), +('5', '5', '57', '1568', '2704', '33', '37', '49', '111', '123'), +('5', '5', '58', '1620', '2758', '33', '37', '50', '113', '125'), +('5', '5', '59', '1673', '2812', '34', '38', '50', '116', '128'), +('5', '5', '60', '1727', '2866', '34', '38', '51', '118', '130'), +('5', '8', '1', '62', '135', '19', '18', '21', '27', '21'), +('5', '8', '2', '77', '160', '19', '18', '21', '22', '28'), +('5', '8', '3', '92', '186', '19', '18', '22', '23', '29'), +('5', '8', '4', '107', '213', '19', '19', '22', '25', '30'), +('5', '8', '5', '122', '241', '19', '19', '22', '26', '32'), +('5', '8', '6', '137', '270', '20', '19', '22', '27', '33'), +('5', '8', '7', '152', '300', '20', '19', '23', '28', '34'), +('5', '8', '8', '167', '316', '20', '19', '23', '29', '35'), +('5', '8', '9', '182', '363', '20', '19', '23', '31', '36'), +('5', '8', '10', '197', '396', '20', '20', '24', '32', '38'), +('5', '8', '11', '212', '430', '20', '20', '24', '33', '39'), +('5', '8', '12', '227', '465', '20', '20', '24', '35', '40'), +('5', '8', '13', '242', '501', '20', '20', '25', '36', '41'), +('5', '8', '14', '257', '538', '21', '20', '25', '37', '43'), +('5', '8', '15', '272', '576', '21', '21', '25', '39', '44'), +('5', '8', '16', '287', '615', '21', '21', '26', '40', '45'), +('5', '8', '17', '302', '640', '21', '21', '26', '41', '47'), +('5', '8', '18', '317', '696', '21', '21', '26', '43', '48'), +('5', '8', '19', '332', '723', '21', '21', '27', '44', '49'), +('5', '8', '20', '347', '781', '21', '22', '27', '46', '51'), +('5', '8', '21', '362', '810', '22', '22', '27', '47', '52'), +('5', '8', '22', '377', '870', '22', '22', '28', '49', '54'), +('5', '8', '23', '392', '901', '22', '22', '28', '50', '55'), +('5', '8', '24', '408', '963', '22', '23', '29', '52', '57'), +('5', '8', '25', '425', '996', '22', '23', '29', '53', '58'), +('5', '8', '26', '443', '1060', '22', '23', '29', '55', '60'), +('5', '8', '27', '462', '1110', '22', '23', '30', '57', '61'), +('5', '8', '28', '482', '1146', '23', '23', '30', '58', '63'), +('5', '8', '29', '503', '1212', '23', '24', '31', '60', '64'), +('5', '8', '30', '525', '1263', '23', '24', '31', '62', '66'), +('5', '8', '31', '548', '1299', '23', '24', '31', '63', '68'), +('5', '8', '32', '572', '1365', '23', '24', '32', '65', '69'), +('5', '8', '33', '597', '1416', '23', '25', '32', '67', '71'), +('5', '8', '34', '623', '1452', '24', '25', '33', '68', '73'), +('5', '8', '35', '650', '1503', '24', '25', '33', '70', '74'), +('5', '8', '36', '678', '1554', '24', '26', '34', '72', '76'), +('5', '8', '37', '707', '1620', '24', '26', '34', '74', '78'), +('5', '8', '38', '737', '1671', '24', '26', '34', '76', '80'), +('5', '8', '39', '768', '1722', '25', '26', '35', '78', '81'), +('5', '8', '40', '800', '1758', '25', '27', '35', '79', '83'), +('5', '8', '41', '833', '1809', '25', '27', '36', '81', '85'), +('5', '8', '42', '867', '1860', '25', '27', '36', '83', '87'), +('5', '8', '43', '902', '1911', '25', '27', '37', '85', '89'), +('5', '8', '44', '938', '1962', '25', '28', '37', '87', '91'), +('5', '8', '45', '975', '2013', '26', '28', '38', '89', '93'), +('5', '8', '46', '1013', '2064', '26', '28', '38', '91', '95'), +('5', '8', '47', '1052', '2115', '26', '29', '39', '93', '97'), +('5', '8', '48', '1092', '2181', '26', '29', '39', '96', '99'), +('5', '8', '49', '1133', '2232', '27', '29', '40', '98', '101'), +('5', '8', '50', '1175', '2268', '27', '30', '40', '100', '103'), +('5', '8', '51', '1218', '2319', '27', '30', '41', '102', '105'), +('5', '8', '52', '1262', '2370', '27', '30', '41', '104', '107'), +('5', '8', '53', '1307', '2421', '27', '31', '42', '106', '109'), +('5', '8', '54', '1353', '2472', '28', '31', '43', '109', '111'), +('5', '8', '55', '1400', '2523', '28', '31', '43', '111', '114'), +('5', '8', '56', '1448', '2574', '28', '32', '44', '113', '116'), +('5', '8', '57', '1497', '2625', '28', '32', '44', '116', '118'), +('5', '8', '58', '1547', '2676', '29', '32', '45', '118', '120'), +('5', '8', '59', '1598', '2727', '29', '33', '45', '121', '123'), +('5', '8', '60', '1650', '2778', '29', '33', '46', '123', '125'), +('5', '9', '1', '63', '110', '19', '18', '22', '27', '20'), +('5', '9', '2', '78', '133', '19', '18', '23', '21', '28'), +('5', '9', '3', '93', '157', '20', '19', '23', '22', '29'), +('5', '9', '4', '108', '182', '20', '19', '24', '23', '30'), +('5', '9', '5', '123', '208', '20', '19', '24', '24', '31'), +('5', '9', '6', '138', '235', '20', '20', '25', '25', '32'), +('5', '9', '7', '153', '263', '21', '20', '25', '26', '34'), +('5', '9', '8', '168', '292', '21', '20', '26', '27', '35'), +('5', '9', '9', '183', '322', '21', '21', '26', '28', '36'), +('5', '9', '10', '198', '353', '22', '21', '27', '29', '37'), +('5', '9', '11', '213', '385', '22', '22', '27', '31', '38'), +('5', '9', '12', '228', '418', '22', '22', '28', '32', '39'), +('5', '9', '13', '243', '452', '23', '22', '28', '33', '41'), +('5', '9', '14', '258', '487', '23', '23', '29', '34', '42'), +('5', '9', '15', '273', '523', '23', '23', '30', '35', '43'), +('5', '9', '16', '288', '560', '24', '24', '30', '36', '44'), +('5', '9', '17', '303', '598', '24', '24', '31', '38', '46'), +('5', '9', '18', '319', '637', '24', '24', '31', '39', '47'), +('5', '9', '19', '336', '677', '25', '25', '32', '40', '48'), +('5', '9', '20', '354', '718', '25', '25', '33', '41', '50'), +('5', '9', '21', '373', '760', '25', '26', '33', '43', '51'), +('5', '9', '22', '393', '803', '26', '26', '34', '44', '52'), +('5', '9', '23', '414', '847', '26', '27', '35', '45', '54'), +('5', '9', '24', '436', '892', '27', '27', '35', '47', '55'), +('5', '9', '25', '459', '938', '27', '28', '36', '48', '57'), +('5', '9', '26', '483', '985', '27', '28', '37', '49', '58'), +('5', '9', '27', '508', '1033', '28', '28', '37', '51', '59'), +('5', '9', '28', '534', '1082', '28', '29', '38', '52', '61'), +('5', '9', '29', '561', '1132', '29', '29', '39', '54', '62'), +('5', '9', '30', '589', '1183', '29', '30', '39', '55', '64'), +('5', '9', '31', '618', '1234', '29', '30', '40', '56', '66'), +('5', '9', '32', '648', '1285', '30', '31', '41', '58', '67'), +('5', '9', '33', '679', '1336', '30', '31', '42', '59', '69'), +('5', '9', '34', '711', '1387', '31', '32', '42', '61', '70'), +('5', '9', '35', '744', '1438', '31', '32', '43', '62', '72'), +('5', '9', '36', '768', '1489', '32', '33', '43', '64', '75'), +('5', '9', '37', '813', '1540', '32', '34', '45', '66', '75'), +('5', '9', '38', '849', '1591', '32', '34', '46', '67', '77'), +('5', '9', '39', '886', '1642', '33', '35', '46', '69', '79'), +('5', '9', '40', '924', '1693', '33', '35', '47', '70', '80'), +('5', '9', '41', '963', '1744', '34', '36', '48', '72', '82'), +('5', '9', '42', '993', '1795', '34', '36', '48', '74', '85'), +('5', '9', '43', '1044', '1846', '35', '37', '50', '75', '86'), +('5', '9', '44', '1086', '1897', '35', '37', '51', '77', '87'), +('5', '9', '45', '1129', '1948', '36', '38', '51', '79', '89'), +('5', '9', '46', '1173', '1999', '36', '39', '52', '81', '90'), +('5', '9', '47', '1218', '2050', '37', '39', '53', '82', '93'), +('5', '9', '48', '1264', '2101', '37', '40', '54', '84', '95'), +('5', '9', '49', '1311', '2152', '38', '41', '55', '86', '96'), +('5', '9', '50', '1339', '2203', '38', '41', '56', '88', '99'), +('5', '9', '51', '1398', '2254', '39', '42', '57', '90', '101'), +('5', '9', '52', '1458', '2305', '39', '42', '58', '92', '103'), +('5', '9', '53', '1509', '2356', '40', '43', '59', '94', '105'), +('5', '9', '54', '1551', '2407', '41', '44', '60', '96', '107'), +('5', '9', '55', '1594', '2458', '41', '44', '60', '98', '110'), +('5', '9', '56', '1668', '2509', '42', '45', '62', '100', '111'), +('5', '9', '57', '1723', '2560', '42', '46', '63', '102', '113'), +('5', '9', '58', '1769', '2611', '43', '47', '63', '104', '116'), +('5', '9', '59', '1836', '2662', '43', '47', '65', '106', '118'), +('5', '9', '60', '1894', '2713', '44', '48', '66', '108', '120'), +('6', '1', '1', '84', '0', '28', '15', '24', '22', '15'), +('6', '1', '2', '103', '0', '29', '16', '25', '15', '22'), +('6', '1', '3', '123', '0', '30', '16', '26', '15', '23'), +('6', '1', '4', '144', '0', '31', '17', '27', '15', '23'), +('6', '1', '5', '163', '0', '33', '18', '28', '15', '23'), +('6', '1', '6', '183', '0', '34', '19', '29', '16', '23'), +('6', '1', '7', '204', '0', '35', '19', '30', '16', '24'), +('6', '1', '8', '223', '0', '36', '20', '31', '16', '24'), +('6', '1', '9', '244', '0', '37', '21', '32', '16', '24'), +('6', '1', '10', '264', '0', '38', '21', '33', '16', '25'), +('6', '1', '11', '283', '0', '40', '22', '35', '16', '25'), +('6', '1', '12', '302', '0', '41', '23', '36', '16', '25'), +('6', '1', '13', '322', '0', '42', '24', '37', '16', '26'), +('6', '1', '14', '344', '0', '44', '25', '38', '17', '26'), +('6', '1', '15', '365', '0', '45', '25', '39', '17', '26'), +('6', '1', '16', '390', '0', '46', '26', '40', '17', '27'), +('6', '1', '17', '414', '0', '47', '27', '42', '17', '27'), +('6', '1', '18', '438', '0', '49', '28', '43', '17', '27'), +('6', '1', '19', '466', '0', '50', '29', '44', '17', '28'), +('6', '1', '20', '491', '0', '52', '30', '45', '17', '28'), +('6', '1', '21', '520', '0', '53', '30', '47', '18', '28'), +('6', '1', '22', '550', '0', '54', '31', '48', '18', '29'), +('6', '1', '23', '580', '0', '56', '32', '49', '18', '29'), +('6', '1', '24', '611', '0', '57', '33', '51', '18', '30'), +('6', '1', '25', '645', '0', '59', '34', '52', '18', '30'), +('6', '1', '26', '677', '0', '60', '35', '53', '18', '30'), +('6', '1', '27', '713', '0', '62', '36', '55', '18', '31'), +('6', '1', '28', '748', '0', '63', '37', '56', '19', '31'), +('6', '1', '29', '785', '0', '65', '38', '58', '19', '32'), +('6', '1', '30', '824', '0', '67', '39', '59', '19', '32'), +('6', '1', '31', '861', '0', '68', '40', '60', '19', '32'), +('6', '1', '32', '902', '0', '70', '41', '62', '19', '33'), +('6', '1', '33', '942', '0', '71', '42', '63', '19', '33'), +('6', '1', '34', '984', '0', '73', '43', '65', '20', '34'), +('6', '1', '35', '1028', '0', '75', '44', '66', '20', '34'), +('6', '1', '36', '1071', '0', '77', '45', '68', '20', '35'), +('6', '1', '37', '1117', '0', '78', '46', '70', '20', '35'), +('6', '1', '38', '1167', '0', '80', '47', '71', '20', '35'), +('6', '1', '39', '1217', '0', '82', '48', '73', '21', '36'), +('6', '1', '40', '1268', '0', '84', '49', '74', '21', '36'), +('6', '1', '41', '1324', '0', '85', '51', '76', '21', '37'), +('6', '1', '42', '1381', '0', '87', '52', '78', '21', '37'), +('6', '1', '43', '1440', '0', '89', '53', '79', '21', '38'), +('6', '1', '44', '1500', '0', '91', '54', '81', '21', '38'), +('6', '1', '45', '1563', '0', '93', '55', '83', '22', '39'), +('6', '1', '46', '1629', '0', '95', '56', '85', '22', '39'), +('6', '1', '47', '1696', '0', '97', '58', '86', '22', '40'), +('6', '1', '48', '1764', '0', '99', '59', '88', '22', '40'), +('6', '1', '49', '1836', '0', '101', '60', '90', '23', '41'), +('6', '1', '50', '1910', '0', '103', '61', '92', '23', '41'), +('6', '1', '51', '1986', '0', '105', '63', '94', '23', '42'), +('6', '1', '52', '2062', '0', '107', '64', '96', '23', '42'), +('6', '1', '53', '2142', '0', '109', '65', '98', '23', '43'), +('6', '1', '54', '2225', '0', '111', '67', '100', '24', '44'), +('6', '1', '55', '2309', '0', '114', '68', '102', '24', '44'), +('6', '1', '56', '2395', '0', '116', '69', '104', '24', '45'), +('6', '1', '57', '2483', '0', '118', '71', '106', '24', '45'), +('6', '1', '58', '2574', '0', '120', '72', '108', '25', '46'), +('6', '1', '59', '2666', '0', '123', '74', '110', '25', '46'), +('6', '1', '60', '2760', '0', '125', '75', '112', '25', '47'), +('6', '3', '1', '80', '80', '25', '18', '23', '23', '15'), +('6', '3', '2', '97', '86', '25', '19', '24', '16', '24'), +('6', '3', '3', '115', '107', '26', '20', '25', '16', '24'), +('6', '3', '4', '133', '115', '26', '22', '25', '17', '25'), +('6', '3', '5', '151', '138', '27', '23', '26', '17', '25'), +('6', '3', '6', '168', '148', '27', '24', '27', '18', '26'), +('6', '3', '7', '186', '173', '27', '25', '28', '18', '26'), +('6', '3', '8', '204', '185', '28', '26', '29', '19', '27'), +('6', '3', '9', '223', '212', '28', '28', '30', '19', '28'), +('6', '3', '10', '239', '226', '29', '29', '30', '20', '28'), +('6', '3', '11', '257', '255', '29', '30', '31', '20', '29'), +('6', '3', '12', '275', '285', '30', '32', '32', '21', '30'), +('6', '3', '13', '294', '316', '30', '33', '33', '22', '30'), +('6', '3', '14', '312', '348', '31', '34', '34', '22', '31'), +('6', '3', '15', '333', '381', '31', '36', '35', '23', '31'), +('6', '3', '16', '354', '415', '32', '37', '36', '23', '32'), +('6', '3', '17', '375', '450', '32', '38', '37', '24', '33'), +('6', '3', '18', '399', '486', '33', '40', '38', '25', '34'), +('6', '3', '19', '424', '523', '33', '41', '39', '25', '34'), +('6', '3', '20', '448', '561', '34', '43', '40', '26', '35'), +('6', '3', '21', '475', '600', '34', '44', '41', '27', '36'), +('6', '3', '22', '501', '640', '35', '46', '42', '27', '36'), +('6', '3', '23', '530', '681', '35', '47', '43', '28', '37'), +('6', '3', '24', '559', '723', '36', '49', '44', '29', '38'), +('6', '3', '25', '590', '766', '36', '50', '45', '29', '39'), +('6', '3', '26', '622', '810', '37', '52', '46', '30', '39'), +('6', '3', '27', '653', '855', '37', '54', '47', '31', '40'), +('6', '3', '28', '687', '900', '38', '55', '48', '31', '41'), +('6', '3', '29', '722', '945', '38', '57', '49', '32', '42'), +('6', '3', '30', '758', '990', '39', '59', '50', '33', '42'), +('6', '3', '31', '795', '1035', '39', '60', '52', '34', '43'), +('6', '3', '32', '832', '1080', '40', '62', '53', '34', '44'), +('6', '3', '33', '871', '1125', '41', '64', '54', '35', '45'), +('6', '3', '34', '910', '1170', '41', '65', '55', '36', '46'), +('6', '3', '35', '952', '1215', '42', '67', '56', '37', '47'), +('6', '3', '36', '994', '1260', '43', '69', '58', '38', '48'), +('6', '3', '37', '1036', '1305', '43', '71', '59', '38', '48'), +('6', '3', '38', '1082', '1350', '44', '73', '60', '39', '49'), +('6', '3', '39', '1126', '1395', '44', '75', '61', '40', '50'), +('6', '3', '40', '1172', '1440', '45', '76', '63', '41', '51'), +('6', '3', '41', '1221', '1485', '46', '78', '64', '42', '52'), +('6', '3', '42', '1268', '1530', '46', '80', '65', '42', '53'), +('6', '3', '43', '1318', '1575', '47', '82', '66', '43', '54'), +('6', '3', '44', '1368', '1620', '48', '84', '68', '44', '55'), +('6', '3', '45', '1419', '1665', '48', '86', '69', '45', '56'), +('6', '3', '46', '1473', '1710', '49', '88', '71', '46', '57'), +('6', '3', '47', '1525', '1755', '50', '90', '72', '47', '58'), +('6', '3', '48', '1580', '1800', '51', '93', '73', '48', '59'), +('6', '3', '49', '1636', '1845', '51', '95', '75', '49', '60'), +('6', '3', '50', '1692', '1890', '52', '97', '76', '50', '61'), +('6', '3', '51', '1750', '1935', '53', '99', '78', '51', '62'), +('6', '3', '52', '1809', '1980', '54', '101', '79', '52', '63'), +('6', '3', '53', '1869', '2025', '54', '103', '81', '53', '64'), +('6', '3', '54', '1930', '2070', '55', '106', '82', '54', '65'), +('6', '3', '55', '1991', '2115', '56', '108', '84', '55', '66'), +('6', '3', '56', '2054', '2160', '57', '110', '85', '56', '67'), +('6', '3', '57', '2119', '2205', '58', '113', '87', '57', '69'), +('6', '3', '58', '2184', '2250', '58', '115', '89', '58', '70'), +('6', '3', '59', '2250', '2295', '59', '118', '90', '59', '71'), +('6', '3', '60', '2318', '2340', '60', '120', '92', '60', '72'), +('6', '7', '1', '81', '71', '26', '15', '23', '24', '16'), +('6', '7', '2', '98', '78', '27', '15', '24', '17', '25'), +('6', '7', '3', '117', '86', '27', '16', '25', '18', '26'), +('6', '7', '4', '133', '109', '28', '16', '26', '18', '27'), +('6', '7', '5', '152', '119', '29', '17', '26', '19', '28'), +('6', '7', '6', '170', '130', '30', '17', '27', '20', '29'), +('6', '7', '7', '188', '156', '31', '17', '28', '21', '30'), +('6', '7', '8', '205', '183', '31', '18', '29', '22', '30'), +('6', '7', '9', '223', '226', '32', '18', '30', '23', '31'), +('6', '7', '10', '241', '240', '33', '19', '31', '23', '32'), +('6', '7', '11', '259', '270', '34', '19', '32', '24', '33'), +('6', '7', '12', '277', '301', '35', '20', '33', '25', '34'), +('6', '7', '13', '294', '333', '35', '20', '34', '26', '35'), +('6', '7', '14', '312', '366', '36', '21', '35', '27', '36'), +('6', '7', '15', '330', '400', '37', '21', '36', '28', '38'), +('6', '7', '16', '349', '435', '38', '22', '37', '29', '39'), +('6', '7', '17', '367', '471', '39', '22', '38', '30', '40'), +('6', '7', '18', '388', '508', '40', '23', '39', '31', '41'), +('6', '7', '19', '409', '546', '41', '23', '40', '32', '42'), +('6', '7', '20', '430', '585', '42', '24', '41', '33', '43'), +('6', '7', '21', '454', '625', '43', '24', '42', '34', '44'), +('6', '7', '22', '477', '666', '43', '25', '43', '35', '45'), +('6', '7', '23', '503', '708', '44', '25', '44', '36', '46'), +('6', '7', '24', '530', '789', '45', '26', '45', '37', '48'), +('6', '7', '25', '556', '795', '46', '26', '47', '38', '49'), +('6', '7', '26', '585', '840', '47', '27', '48', '39', '50'), +('6', '7', '27', '614', '886', '48', '27', '49', '40', '51'), +('6', '7', '28', '645', '933', '49', '28', '50', '41', '52'), +('6', '7', '29', '677', '981', '50', '28', '51', '42', '54'), +('6', '7', '30', '708', '1030', '51', '29', '52', '43', '55'), +('6', '7', '31', '742', '1149', '53', '29', '54', '45', '56'), +('6', '7', '32', '777', '1201', '54', '30', '55', '46', '58'), +('6', '7', '33', '813', '1250', '55', '31', '56', '47', '59'), +('6', '7', '34', '848', '1290', '56', '31', '57', '48', '60'), +('6', '7', '35', '887', '1339', '57', '32', '59', '49', '62'), +('6', '7', '36', '926', '1339', '58', '33', '60', '51', '63'), +('6', '7', '37', '966', '1458', '59', '33', '61', '52', '64'), +('6', '7', '38', '1007', '1471', '60', '34', '63', '53', '66'), +('6', '7', '39', '1049', '1509', '61', '34', '64', '54', '67'), +('6', '7', '40', '1092', '1612', '63', '35', '65', '56', '69'), +('6', '7', '41', '1137', '1663', '64', '36', '67', '57', '70'), +('6', '7', '42', '1181', '1700', '65', '36', '68', '58', '72'), +('6', '7', '43', '1226', '1751', '66', '37', '70', '59', '73'), +('6', '7', '44', '1275', '1818', '68', '38', '71', '61', '75'), +('6', '7', '45', '1323', '1854', '69', '38', '73', '62', '76'), +('6', '7', '46', '1373', '1921', '70', '39', '74', '64', '78'), +('6', '7', '47', '1423', '1972', '71', '40', '76', '65', '79'), +('6', '7', '48', '1474', '2008', '73', '41', '77', '66', '81'), +('6', '7', '49', '1527', '2075', '74', '41', '79', '68', '83'), +('6', '7', '50', '1579', '2111', '75', '42', '80', '69', '84'), +('6', '7', '51', '1634', '2178', '77', '43', '82', '71', '86'), +('6', '7', '52', '1691', '2230', '78', '44', '83', '72', '88'), +('6', '7', '53', '1747', '2281', '80', '44', '85', '74', '89'), +('6', '7', '54', '1805', '2304', '81', '45', '87', '75', '91'), +('6', '7', '55', '1864', '2333', '82', '46', '88', '77', '93'), +('6', '7', '56', '1923', '2384', '84', '47', '90', '78', '95'), +('6', '7', '57', '1983', '2487', '85', '48', '92', '80', '96'), +('6', '7', '58', '2045', '2538', '87', '48', '93', '82', '98'), +('6', '7', '59', '2109', '2565', '88', '49', '95', '83', '100'), +('6', '7', '60', '2174', '2590', '90', '50', '97', '85', '102'), +('6', '11', '1', '78', '67', '26', '15', '22', '24', '17'), +('6', '11', '2', '97', '75', '27', '15', '23', '18', '25'), +('6', '11', '3', '113', '84', '27', '16', '23', '19', '26'), +('6', '11', '4', '132', '94', '28', '16', '24', '20', '27'), +('6', '11', '5', '150', '119', '28', '17', '24', '21', '28'), +('6', '11', '6', '168', '145', '29', '17', '25', '22', '29'), +('6', '11', '7', '185', '172', '29', '18', '26', '23', '30'), +('6', '11', '8', '203', '185', '30', '18', '26', '23', '31'), +('6', '11', '9', '221', '214', '30', '19', '27', '24', '32'), +('6', '11', '10', '239', '244', '31', '19', '27', '25', '33'), +('6', '11', '11', '257', '275', '31', '20', '28', '26', '35'), +('6', '11', '12', '274', '307', '32', '20', '29', '27', '36'), +('6', '11', '13', '292', '340', '32', '21', '29', '28', '37'), +('6', '11', '14', '310', '374', '33', '21', '30', '29', '38'), +('6', '11', '15', '329', '424', '34', '22', '31', '31', '39'), +('6', '11', '16', '347', '460', '34', '22', '31', '32', '40'), +('6', '11', '17', '365', '497', '35', '23', '32', '33', '42'), +('6', '11', '18', '383', '535', '35', '24', '33', '34', '43'), +('6', '11', '19', '402', '574', '36', '24', '33', '35', '44'), +('6', '11', '20', '425', '614', '37', '25', '34', '36', '45'), +('6', '11', '21', '447', '655', '37', '25', '35', '37', '47'), +('6', '11', '22', '470', '682', '38', '26', '36', '38', '48'), +('6', '11', '23', '494', '725', '39', '27', '36', '39', '49'), +('6', '11', '24', '518', '784', '39', '27', '37', '41', '51'), +('6', '11', '25', '544', '829', '40', '28', '38', '42', '52'), +('6', '11', '26', '573', '874', '41', '28', '39', '43', '53'), +('6', '11', '27', '601', '904', '41', '29', '39', '44', '55'), +('6', '11', '28', '630', '949', '42', '30', '40', '45', '56'), +('6', '11', '29', '659', '1009', '43', '30', '41', '47', '58'), +('6', '11', '30', '691', '1054', '43', '31', '42', '48', '59'), +('6', '11', '31', '723', '1084', '44', '32', '43', '49', '60'), +('6', '11', '32', '757', '1144', '45', '32', '44', '51', '62'), +('6', '11', '33', '793', '1189', '46', '33', '44', '52', '63'), +('6', '11', '34', '827', '1219', '46', '34', '45', '53', '65'), +('6', '11', '35', '864', '1279', '47', '34', '46', '55', '66'), +('6', '11', '36', '903', '1309', '48', '35', '47', '56', '68'), +('6', '11', '37', '941', '1354', '49', '36', '48', '57', '70'), +('6', '11', '38', '982', '1414', '50', '36', '49', '59', '71'), +('6', '11', '39', '1022', '1444', '50', '37', '50', '60', '73'), +('6', '11', '40', '1064', '1504', '51', '38', '51', '62', '74'), +('6', '11', '41', '1108', '1534', '52', '39', '52', '63', '76'), +('6', '11', '42', '1151', '1594', '53', '39', '53', '65', '78'), +('6', '11', '43', '1197', '1624', '54', '40', '54', '66', '79'), +('6', '11', '44', '1243', '1684', '55', '41', '54', '68', '81'), +('6', '11', '45', '1290', '1714', '55', '42', '55', '69', '83'), +('6', '11', '46', '1339', '1774', '56', '43', '56', '71', '85'), +('6', '11', '47', '1388', '1804', '57', '43', '58', '72', '86'), +('6', '11', '48', '1437', '1849', '58', '44', '59', '74', '88'), +('6', '11', '49', '1490', '1909', '59', '45', '60', '76', '90'), +('6', '11', '50', '1542', '1939', '60', '46', '61', '77', '92'), +('6', '11', '51', '1596', '1984', '61', '47', '62', '79', '94'), +('6', '11', '52', '1651', '2044', '62', '48', '63', '81', '96'), +('6', '11', '53', '1706', '2074', '63', '49', '64', '82', '98'), +('6', '11', '54', '1763', '2119', '64', '49', '65', '84', '100'), +('6', '11', '55', '1820', '2164', '65', '50', '66', '86', '102'), +('6', '11', '56', '1879', '2209', '66', '51', '67', '88', '104'), +('6', '11', '57', '1940', '2254', '67', '52', '68', '89', '106'), +('6', '11', '58', '2000', '2299', '68', '53', '70', '91', '108'), +('6', '11', '59', '2063', '2344', '69', '54', '71', '93', '110'), +('6', '11', '60', '2125', '2389', '70', '55', '72', '95', '112'), +('7', '1', '1', '50', '0', '18', '23', '21', '20', '24'), +('7', '1', '2', '69', '0', '19', '24', '22', '24', '20'), +('7', '1', '3', '88', '0', '20', '24', '23', '24', '21'), +('7', '1', '4', '107', '0', '21', '25', '24', '24', '21'), +('7', '1', '5', '126', '0', '23', '26', '25', '24', '21'), +('7', '1', '6', '145', '0', '24', '27', '26', '25', '21'), +('7', '1', '7', '164', '0', '25', '27', '27', '25', '22'), +('7', '1', '8', '183', '0', '26', '28', '28', '25', '22'), +('7', '1', '9', '202', '0', '27', '29', '29', '25', '22'), +('7', '1', '10', '221', '0', '28', '29', '30', '25', '23'), +('7', '1', '11', '240', '0', '30', '30', '32', '25', '23'), +('7', '1', '12', '259', '0', '31', '31', '33', '25', '23'), +('7', '1', '13', '278', '0', '32', '32', '34', '25', '24'), +('7', '1', '14', '298', '0', '34', '33', '35', '26', '24'), +('7', '1', '15', '319', '0', '35', '33', '36', '26', '24'), +('7', '1', '16', '341', '0', '36', '34', '37', '26', '25'), +('7', '1', '17', '364', '0', '37', '35', '39', '26', '25'), +('7', '1', '18', '388', '0', '39', '36', '40', '26', '25'), +('7', '1', '19', '413', '0', '40', '37', '41', '26', '26'), +('7', '1', '20', '439', '0', '42', '38', '42', '26', '26'), +('7', '1', '21', '466', '0', '43', '38', '44', '27', '26'), +('7', '1', '22', '494', '0', '44', '39', '45', '27', '27'), +('7', '1', '23', '523', '0', '46', '40', '46', '27', '27'), +('7', '1', '24', '553', '0', '47', '41', '48', '27', '28'), +('7', '1', '25', '584', '0', '49', '42', '49', '27', '28'), +('7', '1', '26', '616', '0', '50', '43', '50', '27', '28'), +('7', '1', '27', '649', '0', '52', '44', '52', '27', '29'), +('7', '1', '28', '683', '0', '53', '45', '53', '28', '29'), +('7', '1', '29', '718', '0', '55', '46', '55', '28', '30'), +('7', '1', '30', '754', '0', '57', '47', '56', '28', '30'), +('7', '1', '31', '791', '0', '58', '48', '57', '28', '30'), +('7', '1', '32', '829', '0', '60', '49', '59', '28', '31'), +('7', '1', '33', '868', '0', '61', '50', '60', '28', '31'), +('7', '1', '34', '908', '0', '63', '51', '62', '29', '32'), +('7', '1', '35', '949', '0', '65', '52', '63', '29', '32'), +('7', '1', '36', '991', '0', '67', '53', '65', '29', '33'), +('7', '1', '37', '1070', '0', '68', '54', '67', '29', '33'), +('7', '1', '38', '1081', '0', '70', '55', '68', '29', '33'), +('7', '1', '39', '1129', '0', '72', '56', '70', '30', '34'), +('7', '1', '40', '1179', '0', '74', '57', '71', '30', '34'), +('7', '1', '41', '1231', '0', '75', '59', '73', '30', '35'), +('7', '1', '42', '1285', '0', '77', '60', '75', '30', '35'), +('7', '1', '43', '1341', '0', '79', '61', '76', '30', '36'), +('7', '1', '44', '1399', '0', '81', '62', '78', '30', '36'), +('7', '1', '45', '1459', '0', '83', '63', '80', '32', '37'), +('7', '1', '46', '1521', '0', '85', '64', '82', '32', '37'), +('7', '1', '47', '1585', '0', '87', '66', '83', '32', '38'), +('7', '1', '48', '1651', '0', '89', '67', '85', '32', '38'), +('7', '1', '49', '1719', '0', '91', '68', '87', '33', '39'), +('7', '1', '50', '1789', '0', '93', '69', '89', '33', '39'), +('7', '1', '51', '1861', '0', '95', '71', '91', '33', '40'), +('7', '1', '52', '1935', '0', '97', '72', '93', '33', '40'), +('7', '1', '53', '2011', '0', '99', '73', '95', '33', '41'), +('7', '1', '54', '2089', '0', '101', '75', '97', '34', '42'), +('7', '1', '55', '2169', '0', '104', '76', '99', '34', '42'), +('7', '1', '56', '2251', '0', '106', '77', '101', '34', '43'), +('7', '1', '57', '2335', '0', '108', '79', '103', '34', '43'), +('7', '1', '58', '2421', '0', '110', '80', '105', '35', '44'), +('7', '1', '59', '2509', '0', '113', '82', '107', '35', '44'), +('7', '1', '60', '2599', '0', '115', '83', '109', '35', '45'), +('7', '4', '1', '45', '0', '16', '26', '20', '20', '24'), +('7', '4', '2', '62', '0', '17', '27', '21', '24', '20'), +('7', '4', '3', '79', '0', '17', '28', '21', '24', '21'), +('7', '4', '4', '96', '0', '18', '30', '22', '25', '21'), +('7', '4', '5', '113', '0', '19', '31', '23', '25', '21'), +('7', '4', '6', '130', '0', '19', '32', '23', '25', '22'), +('7', '4', '7', '147', '0', '20', '34', '24', '25', '22'), +('7', '4', '8', '164', '0', '21', '35', '24', '25', '22'), +('7', '4', '9', '181', '0', '22', '36', '25', '25', '23'), +('7', '4', '10', '198', '0', '22', '38', '26', '26', '23'), +('7', '4', '11', '215', '0', '23', '39', '27', '26', '24'), +('7', '4', '12', '232', '0', '24', '40', '27', '26', '24'), +('7', '4', '13', '249', '0', '25', '42', '28', '26', '24'), +('7', '4', '14', '266', '0', '25', '43', '29', '26', '25'), +('7', '4', '15', '283', '0', '26', '45', '29', '27', '25'), +('7', '4', '16', '301', '0', '27', '46', '30', '27', '26'), +('7', '4', '17', '320', '0', '28', '47', '31', '27', '26'), +('7', '4', '18', '340', '0', '29', '49', '32', '27', '26'), +('7', '4', '19', '361', '0', '30', '51', '32', '27', '27'), +('7', '4', '20', '383', '0', '30', '52', '33', '28', '27'), +('7', '4', '21', '406', '0', '31', '54', '34', '28', '28'), +('7', '4', '22', '430', '0', '32', '55', '35', '28', '28'), +('7', '4', '23', '455', '0', '33', '57', '36', '28', '29'), +('7', '4', '24', '481', '0', '34', '58', '36', '29', '29'), +('7', '4', '25', '508', '0', '35', '60', '37', '29', '30'), +('7', '4', '26', '536', '0', '36', '62', '38', '29', '30'), +('7', '4', '27', '565', '0', '37', '63', '39', '29', '30'), +('7', '4', '28', '595', '0', '38', '65', '40', '29', '31'), +('7', '4', '29', '626', '0', '38', '67', '41', '30', '31'), +('7', '4', '30', '658', '0', '39', '69', '41', '30', '32'), +('7', '4', '31', '691', '0', '40', '70', '42', '30', '32'), +('7', '4', '32', '725', '0', '41', '72', '43', '30', '33'), +('7', '4', '33', '760', '0', '42', '74', '44', '32', '33'), +('7', '4', '34', '796', '0', '43', '76', '45', '32', '34'), +('7', '4', '35', '833', '0', '44', '78', '46', '32', '34'), +('7', '4', '36', '871', '0', '46', '80', '47', '33', '35'), +('7', '4', '37', '910', '0', '47', '81', '48', '33', '36'), +('7', '4', '38', '950', '0', '48', '83', '49', '33', '36'), +('7', '4', '39', '991', '0', '49', '85', '50', '33', '37'), +('7', '4', '40', '1033', '0', '50', '87', '51', '34', '37'), +('7', '4', '41', '1076', '0', '51', '89', '52', '34', '38'), +('7', '4', '42', '1120', '0', '52', '91', '53', '34', '38'), +('7', '4', '43', '1165', '0', '53', '93', '54', '34', '39'), +('7', '4', '44', '1211', '0', '54', '96', '55', '35', '39'), +('7', '4', '45', '1258', '0', '56', '98', '56', '35', '40'), +('7', '4', '46', '1306', '0', '57', '100', '57', '35', '41'), +('7', '4', '47', '1355', '0', '58', '102', '58', '36', '41'), +('7', '4', '48', '1405', '0', '59', '104', '59', '36', '42'), +('7', '4', '49', '1456', '0', '60', '106', '61', '36', '43'), +('7', '4', '50', '1508', '0', '62', '109', '62', '37', '43'), +('7', '4', '51', '1561', '0', '63', '111', '63', '37', '44'), +('7', '4', '52', '1615', '0', '64', '113', '64', '37', '44'), +('7', '4', '53', '1670', '0', '65', '116', '65', '38', '45'), +('7', '4', '54', '1726', '0', '67', '118', '66', '38', '46'), +('7', '4', '55', '1783', '0', '68', '120', '68', '38', '46'), +('7', '4', '56', '1841', '0', '69', '123', '69', '39', '47'), +('7', '4', '57', '1900', '0', '71', '125', '70', '39', '48'), +('7', '4', '58', '1960', '0', '72', '128', '71', '39', '49'), +('7', '4', '59', '2021', '0', '74', '130', '73', '40', '49'), +('7', '4', '60', '2083', '0', '75', '133', '74', '40', '50'), +('7', '8', '1', '51', '255', '15', '23', '19', '22', '27'), +('7', '8', '2', '66', '280', '15', '23', '19', '28', '23'), +('7', '8', '3', '72', '306', '15', '23', '20', '29', '24'), +('7', '8', '4', '87', '333', '15', '24', '20', '32', '25'), +('7', '8', '5', '102', '391', '15', '24', '20', '33', '27'), +('7', '8', '6', '117', '420', '16', '24', '20', '34', '28'), +('7', '8', '7', '132', '450', '16', '24', '21', '35', '29'), +('7', '8', '8', '147', '466', '16', '24', '21', '36', '30'), +('7', '8', '9', '162', '513', '16', '24', '21', '38', '31'), +('7', '8', '10', '177', '546', '16', '25', '22', '39', '33'), +('7', '8', '11', '192', '580', '16', '25', '22', '40', '34'), +('7', '8', '12', '207', '615', '16', '25', '22', '42', '35'), +('7', '8', '13', '222', '636', '16', '25', '23', '43', '36'), +('7', '8', '14', '237', '673', '17', '25', '23', '44', '38'), +('7', '8', '15', '252', '711', '17', '26', '23', '46', '39'), +('7', '8', '16', '267', '750', '17', '26', '24', '47', '40'), +('7', '8', '17', '282', '775', '17', '26', '24', '48', '42'), +('7', '8', '18', '297', '831', '17', '26', '24', '50', '43'), +('7', '8', '19', '312', '858', '17', '26', '25', '51', '44'), +('7', '8', '20', '327', '946', '17', '27', '25', '54', '46'), +('7', '8', '21', '342', '975', '18', '27', '25', '55', '47'), +('7', '8', '22', '357', '1035', '18', '27', '26', '57', '49'), +('7', '8', '23', '372', '1066', '18', '27', '26', '58', '50'), +('7', '8', '24', '388', '1128', '18', '28', '27', '60', '52'), +('7', '8', '25', '405', '1161', '18', '28', '27', '61', '53'), +('7', '8', '26', '423', '1225', '18', '28', '27', '63', '55'), +('7', '8', '27', '442', '1260', '18', '28', '28', '65', '56'), +('7', '8', '28', '462', '1296', '19', '28', '28', '66', '58'), +('7', '8', '29', '483', '1362', '19', '29', '29', '68', '59'), +('7', '8', '30', '505', '1413', '19', '29', '29', '70', '61'), +('7', '8', '31', '528', '1449', '19', '29', '29', '71', '63'), +('7', '8', '32', '552', '1515', '19', '29', '30', '74', '64'), +('7', '8', '33', '577', '1596', '19', '30', '30', '76', '66'), +('7', '8', '34', '603', '1632', '20', '30', '31', '77', '68'), +('7', '8', '35', '630', '1683', '20', '30', '31', '79', '69'), +('7', '8', '36', '658', '1734', '20', '31', '32', '81', '71'), +('7', '8', '37', '687', '1800', '20', '31', '32', '83', '73'), +('7', '8', '38', '717', '1836', '20', '31', '32', '85', '75'), +('7', '8', '39', '748', '1887', '21', '31', '33', '87', '76'), +('7', '8', '40', '780', '1923', '21', '32', '33', '88', '78'), +('7', '8', '41', '813', '1974', '21', '32', '34', '90', '80'), +('7', '8', '42', '847', '2025', '21', '32', '34', '92', '82'), +('7', '8', '43', '882', '2076', '21', '32', '35', '95', '84'), +('7', '8', '44', '918', '2157', '21', '33', '35', '97', '86'), +('7', '8', '45', '955', '2208', '22', '33', '36', '99', '88'), +('7', '8', '46', '993', '2259', '22', '33', '36', '101', '90'), +('7', '8', '47', '1032', '2310', '22', '34', '37', '103', '92'), +('7', '8', '48', '1072', '2361', '22', '34', '37', '106', '94'), +('7', '8', '49', '1113', '2412', '23', '34', '38', '108', '96'), +('7', '8', '50', '1155', '2448', '23', '35', '38', '110', '98'), +('7', '8', '51', '1198', '2499', '23', '35', '39', '112', '100'), +('7', '8', '52', '1242', '2550', '23', '35', '39', '114', '102'), +('7', '8', '53', '1287', '2631', '23', '36', '40', '117', '104'), +('7', '8', '54', '1333', '2682', '24', '36', '41', '120', '106'), +('7', '8', '55', '1380', '2733', '24', '36', '41', '122', '109'), +('7', '8', '56', '1428', '2784', '24', '37', '42', '124', '111'), +('7', '8', '57', '1477', '2820', '24', '37', '42', '127', '113'), +('7', '8', '58', '1527', '2871', '25', '37', '43', '129', '115'), +('7', '8', '59', '1578', '2922', '25', '38', '43', '132', '118'), +('7', '8', '60', '1630', '2973', '25', '38', '44', '133', '120'), +('7', '9', '1', '43', '200', '15', '23', '20', '22', '26'), +('7', '9', '2', '58', '223', '15', '23', '21', '27', '23'), +('7', '9', '3', '73', '247', '16', '24', '21', '28', '24'), +('7', '9', '4', '88', '272', '16', '24', '22', '29', '25'), +('7', '9', '5', '103', '298', '16', '24', '22', '30', '26'), +('7', '9', '6', '118', '325', '16', '25', '23', '32', '27'), +('7', '9', '7', '133', '383', '17', '25', '23', '33', '29'), +('7', '9', '8', '148', '412', '17', '25', '24', '34', '30'), +('7', '9', '9', '163', '442', '17', '26', '24', '35', '31'), +('7', '9', '10', '178', '473', '18', '26', '25', '36', '32'), +('7', '9', '11', '193', '505', '18', '27', '25', '38', '33'), +('7', '9', '12', '208', '538', '18', '27', '26', '39', '34'), +('7', '9', '13', '223', '572', '19', '27', '26', '40', '36'), +('7', '9', '14', '238', '607', '19', '28', '27', '41', '37'), +('7', '9', '15', '253', '643', '19', '28', '28', '42', '38'), +('7', '9', '16', '268', '665', '20', '29', '28', '43', '39'), +('7', '9', '17', '283', '703', '20', '29', '29', '45', '41'), +('7', '9', '18', '299', '742', '20', '29', '29', '46', '42'), +('7', '9', '19', '316', '782', '21', '30', '30', '47', '43'), +('7', '9', '20', '334', '823', '21', '30', '31', '48', '45'), +('7', '9', '21', '353', '865', '21', '31', '31', '50', '46'), +('7', '9', '22', '373', '908', '22', '31', '32', '51', '47'), +('7', '9', '23', '394', '952', '22', '32', '33', '53', '49'), +('7', '9', '24', '416', '1027', '23', '32', '33', '55', '50'), +('7', '9', '25', '439', '1073', '23', '33', '34', '56', '52'), +('7', '9', '26', '463', '1120', '23', '33', '35', '57', '53'), +('7', '9', '27', '488', '1168', '24', '33', '35', '59', '54'), +('7', '9', '28', '514', '1217', '24', '34', '36', '60', '56'), +('7', '9', '29', '541', '1267', '25', '34', '37', '62', '57'), +('7', '9', '30', '569', '1318', '25', '35', '37', '63', '59'), +('7', '9', '31', '588', '1354', '25', '35', '37', '64', '62'), +('7', '9', '32', '628', '1405', '26', '36', '39', '66', '62'), +('7', '9', '33', '659', '1456', '26', '36', '40', '67', '64'), +('7', '9', '34', '691', '1507', '27', '37', '40', '69', '65'), +('7', '9', '35', '724', '1558', '27', '37', '41', '70', '67'), +('7', '9', '36', '758', '1609', '28', '38', '42', '72', '69'), +('7', '9', '37', '793', '1690', '28', '39', '43', '75', '69'), +('7', '9', '38', '829', '1741', '28', '39', '44', '76', '72'), +('7', '9', '39', '866', '1792', '29', '40', '44', '78', '74'), +('7', '9', '40', '904', '1843', '29', '40', '45', '79', '75'), +('7', '9', '41', '943', '1894', '30', '41', '46', '81', '77'), +('7', '9', '42', '983', '1945', '30', '41', '47', '83', '79'), +('7', '9', '43', '1024', '1996', '31', '42', '48', '84', '81'), +('7', '9', '44', '1066', '2032', '31', '42', '49', '86', '82'), +('7', '9', '45', '1109', '2083', '32', '43', '49', '88', '84'), +('7', '9', '46', '1153', '2134', '32', '44', '50', '90', '86'), +('7', '9', '47', '1198', '2185', '33', '44', '51', '91', '88'), +('7', '9', '48', '1234', '2236', '33', '45', '52', '93', '90'), +('7', '9', '49', '1281', '2317', '34', '46', '53', '96', '92'), +('7', '9', '50', '1339', '2368', '34', '46', '54', '98', '93'), +('7', '9', '51', '1388', '2419', '35', '47', '55', '100', '96'), +('7', '9', '52', '1418', '2470', '35', '47', '56', '102', '98'), +('7', '9', '53', '1489', '2521', '36', '48', '57', '104', '100'), +('7', '9', '54', '1541', '2557', '37', '49', '58', '106', '102'), +('7', '9', '55', '1584', '2608', '37', '49', '58', '108', '104'), +('7', '9', '56', '1648', '2659', '38', '50', '60', '110', '106'), +('7', '9', '57', '1683', '2710', '38', '51', '61', '112', '108'), +('7', '9', '58', '1759', '2761', '39', '52', '62', '114', '111'), +('7', '9', '59', '1816', '2842', '39', '52', '63', '117', '111'), +('7', '9', '60', '1874', '2893', '40', '53', '64', '119', '115'), +('8', '1', '1', '70', '0', '24', '22', '23', '21', '16'), +('8', '1', '2', '89', '0', '25', '23', '24', '16', '21'), +('8', '1', '3', '108', '0', '26', '23', '25', '16', '22'), +('8', '1', '4', '127', '0', '27', '24', '26', '16', '22'), +('8', '1', '5', '146', '0', '29', '25', '27', '16', '22'), +('8', '1', '6', '165', '0', '30', '26', '28', '17', '22'), +('8', '1', '7', '184', '0', '31', '26', '29', '17', '23'), +('8', '1', '8', '203', '0', '32', '27', '30', '17', '23'), +('8', '1', '9', '222', '0', '33', '28', '31', '17', '23'), +('8', '1', '10', '241', '0', '34', '28', '32', '17', '24'), +('8', '1', '11', '260', '0', '36', '29', '34', '17', '24'), +('8', '1', '12', '279', '0', '37', '30', '35', '17', '24'), +('8', '1', '13', '298', '0', '38', '31', '36', '17', '25'), +('8', '1', '14', '318', '0', '40', '32', '37', '18', '25'), +('8', '1', '15', '339', '0', '41', '32', '38', '18', '25'), +('8', '1', '16', '361', '0', '42', '33', '39', '18', '26'), +('8', '1', '17', '384', '0', '43', '34', '41', '18', '26'), +('8', '1', '18', '408', '0', '45', '35', '42', '18', '26'), +('8', '1', '19', '433', '0', '46', '36', '43', '18', '27'), +('8', '1', '20', '459', '0', '48', '37', '44', '18', '27'), +('8', '1', '21', '486', '0', '49', '37', '46', '19', '27'), +('8', '1', '22', '514', '0', '50', '38', '47', '19', '28'), +('8', '1', '23', '543', '0', '52', '39', '48', '19', '28'), +('8', '1', '24', '573', '0', '53', '40', '50', '19', '29'), +('8', '1', '25', '604', '0', '55', '41', '51', '19', '29'), +('8', '1', '26', '636', '0', '56', '42', '52', '19', '29'), +('8', '1', '27', '669', '0', '58', '43', '54', '19', '30'), +('8', '1', '28', '703', '0', '59', '44', '55', '20', '30'), +('8', '1', '29', '738', '0', '61', '45', '57', '20', '31'), +('8', '1', '30', '774', '0', '63', '46', '58', '20', '31'), +('8', '1', '31', '811', '0', '64', '47', '59', '20', '31'), +('8', '1', '32', '849', '0', '66', '48', '61', '20', '32'), +('8', '1', '33', '888', '0', '67', '49', '62', '20', '32'), +('8', '1', '34', '928', '0', '69', '50', '64', '21', '33'), +('8', '1', '35', '969', '0', '71', '51', '65', '21', '33'), +('8', '1', '36', '1011', '0', '73', '52', '67', '21', '34'), +('8', '1', '37', '1055', '0', '74', '53', '69', '21', '34'), +('8', '1', '38', '1101', '0', '76', '54', '70', '21', '34'), +('8', '1', '39', '1149', '0', '78', '55', '72', '22', '35'), +('8', '1', '40', '1199', '0', '80', '56', '73', '22', '35'), +('8', '1', '41', '1251', '0', '81', '58', '75', '22', '36'), +('8', '1', '42', '1310', '0', '83', '59', '77', '22', '36'), +('8', '1', '43', '1361', '0', '85', '60', '78', '22', '37'), +('8', '1', '44', '1419', '0', '87', '61', '80', '22', '37'), +('8', '1', '45', '1529', '0', '89', '62', '82', '23', '38'), +('8', '1', '46', '1541', '0', '91', '63', '84', '23', '38'), +('8', '1', '47', '1605', '0', '93', '65', '85', '23', '39'), +('8', '1', '48', '1671', '0', '95', '66', '87', '23', '39'), +('8', '1', '49', '1739', '0', '97', '67', '89', '24', '40'), +('8', '1', '50', '1809', '0', '99', '68', '91', '24', '40'), +('8', '1', '51', '1881', '0', '101', '70', '93', '24', '41'), +('8', '1', '52', '1955', '0', '103', '71', '95', '24', '41'), +('8', '1', '53', '2031', '0', '105', '72', '97', '24', '42'), +('8', '1', '54', '2109', '0', '107', '74', '99', '25', '43'), +('8', '1', '55', '2189', '0', '110', '75', '101', '25', '43'), +('8', '1', '56', '2271', '0', '112', '76', '103', '25', '44'), +('8', '1', '57', '2355', '0', '114', '78', '105', '25', '44'), +('8', '1', '58', '2441', '0', '116', '79', '107', '26', '45'), +('8', '1', '59', '2529', '0', '119', '81', '109', '26', '45'), +('8', '1', '60', '2619', '0', '121', '82', '111', '26', '46'), +('8', '3', '1', '66', '81', '21', '25', '22', '22', '16'), +('8', '3', '2', '83', '87', '21', '26', '23', '17', '23'), +('8', '3', '3', '100', '108', '22', '27', '24', '17', '23'), +('8', '3', '4', '117', '116', '22', '29', '24', '18', '24'), +('8', '3', '5', '134', '139', '23', '30', '25', '18', '24'), +('8', '3', '6', '151', '149', '23', '31', '26', '19', '25'), +('8', '3', '7', '168', '174', '23', '32', '27', '19', '25'), +('8', '3', '8', '185', '186', '24', '33', '28', '20', '26'), +('8', '3', '9', '202', '213', '24', '35', '29', '20', '27'), +('8', '3', '10', '219', '241', '25', '36', '29', '21', '27'), +('8', '3', '11', '236', '270', '25', '37', '30', '21', '28'), +('8', '3', '12', '253', '300', '26', '39', '31', '22', '29'), +('8', '3', '13', '270', '331', '26', '40', '32', '23', '29'), +('8', '3', '14', '288', '363', '27', '41', '33', '23', '30'), +('8', '3', '15', '307', '396', '27', '43', '34', '24', '30'), +('8', '3', '16', '327', '430', '28', '44', '35', '24', '31'), +('8', '3', '17', '348', '465', '28', '45', '36', '25', '32'), +('8', '3', '18', '370', '501', '29', '47', '37', '26', '33'), +('8', '3', '19', '393', '538', '29', '48', '38', '26', '33'), +('8', '3', '20', '417', '576', '30', '50', '39', '27', '34'), +('8', '3', '21', '442', '615', '30', '51', '40', '28', '35'), +('8', '3', '22', '468', '655', '31', '53', '41', '28', '35'), +('8', '3', '23', '495', '696', '31', '54', '42', '29', '36'), +('8', '3', '24', '523', '738', '32', '56', '43', '30', '37'), +('8', '3', '25', '552', '781', '32', '57', '44', '30', '38'), +('8', '3', '26', '582', '825', '33', '59', '45', '31', '38'), +('8', '3', '27', '613', '870', '33', '61', '46', '32', '39'), +('8', '3', '28', '645', '915', '34', '62', '47', '32', '40'), +('8', '3', '29', '678', '960', '34', '64', '48', '33', '41'), +('8', '3', '30', '712', '1005', '35', '66', '49', '34', '41'), +('8', '3', '31', '747', '1050', '35', '67', '51', '35', '42'), +('8', '3', '32', '783', '1095', '36', '69', '52', '35', '43'), +('8', '3', '33', '820', '1140', '37', '71', '53', '36', '44'), +('8', '3', '34', '858', '1185', '37', '72', '54', '37', '45'), +('8', '3', '35', '897', '1230', '38', '74', '55', '38', '46'), +('8', '3', '36', '937', '1275', '39', '76', '57', '39', '47'), +('8', '3', '37', '978', '1320', '39', '78', '58', '39', '47'), +('8', '3', '38', '1020', '1365', '40', '80', '59', '40', '48'), +('8', '3', '39', '1063', '1410', '40', '82', '60', '41', '49'), +('8', '3', '40', '1107', '1455', '41', '83', '62', '42', '50'), +('8', '3', '41', '1152', '1500', '42', '85', '63', '43', '51'), +('8', '3', '42', '1198', '1545', '42', '87', '64', '43', '52'), +('8', '3', '43', '1245', '1590', '43', '89', '65', '44', '53'), +('8', '3', '44', '1293', '1635', '44', '91', '67', '45', '54'), +('8', '3', '45', '1342', '1680', '44', '93', '68', '46', '55'), +('8', '3', '46', '1392', '1725', '45', '95', '70', '47', '56'), +('8', '3', '47', '1443', '1770', '46', '97', '71', '48', '57'), +('8', '3', '48', '1495', '1815', '47', '100', '72', '49', '58'), +('8', '3', '49', '1548', '1860', '47', '102', '74', '50', '59'), +('8', '3', '50', '1602', '1905', '48', '104', '75', '51', '60'), +('8', '3', '51', '1657', '1950', '49', '106', '77', '52', '61'), +('8', '3', '52', '1713', '1995', '50', '108', '78', '53', '62'), +('8', '3', '53', '1770', '2040', '50', '110', '80', '54', '63'), +('8', '3', '54', '1828', '2085', '51', '113', '81', '55', '64'), +('8', '3', '55', '1887', '2130', '52', '115', '83', '56', '65'), +('8', '3', '56', '1947', '2175', '53', '117', '84', '57', '66'), +('8', '3', '57', '2008', '2220', '54', '120', '86', '58', '68'), +('8', '3', '58', '2070', '2265', '54', '122', '88', '59', '69'), +('8', '3', '59', '2133', '2310', '55', '125', '89', '60', '70'), +('8', '3', '60', '2197', '2355', '56', '127', '91', '61', '71'), +('8', '4', '1', '65', '0', '22', '25', '22', '21', '16'), +('8', '4', '2', '82', '0', '23', '26', '23', '16', '21'), +('8', '4', '3', '99', '0', '23', '27', '23', '16', '22'), +('8', '4', '4', '116', '0', '24', '29', '24', '17', '22'), +('8', '4', '5', '133', '0', '25', '30', '25', '17', '22'), +('8', '4', '6', '150', '0', '25', '31', '25', '17', '23'), +('8', '4', '7', '167', '0', '26', '33', '26', '17', '23'), +('8', '4', '8', '184', '0', '27', '34', '26', '17', '23'), +('8', '4', '9', '201', '0', '28', '35', '27', '17', '24'), +('8', '4', '10', '218', '0', '28', '37', '28', '18', '24'), +('8', '4', '11', '235', '0', '29', '38', '29', '18', '25'), +('8', '4', '12', '252', '0', '30', '39', '29', '18', '25'), +('8', '4', '13', '269', '0', '31', '41', '30', '18', '25'), +('8', '4', '14', '286', '0', '31', '42', '31', '18', '26'), +('8', '4', '15', '303', '0', '32', '44', '31', '19', '26'), +('8', '4', '16', '321', '0', '33', '45', '32', '19', '27'), +('8', '4', '17', '340', '0', '34', '46', '33', '19', '27'), +('8', '4', '18', '360', '0', '35', '48', '34', '19', '27'), +('8', '4', '19', '381', '0', '36', '50', '34', '19', '28'), +('8', '4', '20', '403', '0', '36', '51', '35', '20', '28'), +('8', '4', '21', '426', '0', '37', '53', '36', '20', '29'), +('8', '4', '22', '450', '0', '38', '54', '37', '20', '29'), +('8', '4', '23', '475', '0', '39', '56', '38', '20', '30'), +('8', '4', '24', '501', '0', '40', '57', '38', '21', '30'), +('8', '4', '25', '528', '0', '41', '59', '39', '21', '31'), +('8', '4', '26', '556', '0', '42', '61', '40', '21', '31'), +('8', '4', '27', '585', '0', '43', '62', '41', '21', '31'), +('8', '4', '28', '615', '0', '44', '64', '42', '21', '32'), +('8', '4', '29', '646', '0', '44', '66', '43', '22', '32'), +('8', '4', '30', '678', '0', '45', '68', '43', '22', '33'), +('8', '4', '31', '711', '0', '46', '69', '44', '22', '33'), +('8', '4', '32', '745', '0', '47', '71', '45', '22', '34'), +('8', '4', '33', '780', '0', '48', '73', '46', '23', '34'), +('8', '4', '34', '816', '0', '49', '75', '47', '23', '35'), +('8', '4', '35', '853', '0', '50', '77', '48', '23', '35'), +('8', '4', '36', '891', '0', '52', '79', '49', '24', '36'), +('8', '4', '37', '930', '0', '53', '80', '50', '24', '37'), +('8', '4', '38', '970', '0', '54', '82', '51', '24', '37'), +('8', '4', '39', '1011', '0', '55', '84', '52', '24', '38'), +('8', '4', '40', '1053', '0', '56', '86', '53', '25', '38'), +('8', '4', '41', '1096', '0', '57', '88', '54', '25', '39'), +('8', '4', '42', '1140', '0', '58', '90', '55', '25', '39'), +('8', '4', '43', '1185', '0', '59', '92', '56', '25', '40'), +('8', '4', '44', '1231', '0', '60', '95', '57', '26', '40'), +('8', '4', '45', '1278', '0', '62', '97', '58', '26', '41'), +('8', '4', '46', '1326', '0', '63', '99', '59', '26', '42'), +('8', '4', '47', '1375', '0', '64', '101', '60', '27', '42'), +('8', '4', '48', '1425', '0', '65', '103', '61', '27', '43'), +('8', '4', '49', '1476', '0', '66', '105', '63', '27', '44'), +('8', '4', '50', '1528', '0', '68', '108', '64', '28', '44'), +('8', '4', '51', '1581', '0', '69', '110', '65', '28', '45'), +('8', '4', '52', '1635', '0', '70', '112', '66', '28', '45'), +('8', '4', '53', '1690', '0', '71', '115', '67', '29', '46'), +('8', '4', '54', '1746', '0', '73', '117', '68', '29', '47'), +('8', '4', '55', '1803', '0', '74', '119', '70', '29', '47'), +('8', '4', '56', '1861', '0', '75', '122', '71', '30', '48'), +('8', '4', '57', '1920', '0', '77', '124', '72', '30', '49'), +('8', '4', '58', '1980', '0', '78', '127', '73', '30', '50'), +('8', '4', '59', '2041', '0', '80', '129', '75', '31', '50'), +('8', '4', '60', '2103', '0', '81', '132', '76', '31', '51'), +('8', '5', '1', '62', '128', '21', '22', '21', '24', '18'), +('8', '5', '2', '77', '138', '21', '22', '21', '19', '25'), +('8', '5', '3', '92', '149', '21', '22', '22', '20', '26'), +('8', '5', '4', '107', '175', '22', '23', '22', '21', '28'), +('8', '5', '5', '122', '202', '22', '23', '22', '23', '29'), +('8', '5', '6', '137', '230', '22', '23', '23', '24', '30'), +('8', '5', '7', '152', '259', '22', '23', '23', '25', '31'), +('8', '5', '8', '167', '289', '22', '24', '23', '26', '32'), +('8', '5', '9', '182', '320', '22', '24', '24', '27', '34'), +('8', '5', '10', '197', '367', '23', '24', '24', '29', '35'), +('8', '5', '11', '212', '385', '23', '24', '25', '30', '36'), +('8', '5', '12', '227', '419', '23', '25', '25', '31', '38'), +('8', '5', '13', '242', '454', '23', '25', '25', '32', '39'), +('8', '5', '14', '257', '490', '23', '25', '26', '34', '40'), +('8', '5', '15', '272', '527', '24', '25', '26', '35', '42'), +('8', '5', '16', '287', '565', '24', '26', '27', '36', '43'), +('8', '5', '17', '302', '619', '24', '26', '27', '38', '44'), +('8', '5', '18', '317', '644', '24', '26', '27', '39', '46'), +('8', '5', '19', '332', '685', '24', '27', '28', '40', '47'), +('8', '5', '20', '347', '727', '25', '27', '28', '42', '49'), +('8', '5', '21', '362', '770', '25', '27', '29', '43', '50'), +('8', '5', '22', '378', '829', '25', '27', '29', '45', '52'), +('8', '5', '23', '395', '859', '25', '28', '30', '46', '53'), +('8', '5', '24', '413', '920', '26', '28', '30', '48', '55'), +('8', '5', '25', '432', '952', '26', '28', '31', '49', '56'), +('8', '5', '26', '452', '1015', '26', '29', '31', '51', '58'), +('8', '5', '27', '473', '1049', '26', '29', '31', '52', '60'), +('8', '5', '28', '495', '1114', '26', '29', '32', '54', '61'), +('8', '5', '29', '518', '1150', '27', '30', '32', '55', '63'), +('8', '5', '30', '542', '1202', '27', '30', '33', '57', '65'), +('8', '5', '31', '567', '1270', '27', '30', '33', '59', '66'), +('8', '5', '32', '593', '1309', '27', '31', '34', '60', '68'), +('8', '5', '33', '620', '1378', '28', '31', '34', '62', '70'), +('8', '5', '34', '648', '1432', '28', '31', '35', '64', '71'), +('8', '5', '35', '677', '1471', '28', '32', '35', '65', '73'), +('8', '5', '36', '707', '1525', '29', '32', '36', '67', '75'), +('8', '5', '37', '738', '1594', '29', '32', '37', '69', '77'), +('8', '5', '38', '770', '1648', '29', '33', '37', '71', '79'), +('8', '5', '39', '803', '1687', '29', '33', '38', '72', '81'), +('8', '5', '40', '837', '1741', '30', '33', '38', '74', '82'), +('8', '5', '41', '872', '1810', '30', '34', '39', '76', '84'), +('8', '5', '42', '908', '1864', '30', '34', '39', '78', '86'), +('8', '5', '43', '945', '1918', '30', '35', '40', '80', '88'), +('8', '5', '44', '983', '1972', '31', '35', '40', '82', '90'), +('8', '5', '45', '1022', '2026', '31', '35', '41', '84', '92'), +('8', '5', '46', '1062', '2080', '31', '36', '42', '86', '94'), +('8', '5', '47', '1103', '2134', '32', '36', '42', '88', '96'), +('8', '5', '48', '1145', '2188', '32', '37', '43', '90', '99'), +('8', '5', '49', '1238', '2242', '32', '37', '44', '92', '101'), +('8', '5', '50', '1252', '2296', '33', '37', '44', '94', '103'), +('8', '5', '51', '1277', '2350', '33', '38', '45', '96', '105'), +('8', '5', '52', '1323', '2404', '33', '38', '45', '98', '107'), +('8', '5', '53', '1370', '2458', '34', '39', '46', '100', '109'), +('8', '5', '54', '1418', '2512', '34', '39', '47', '102', '112'), +('8', '5', '55', '1467', '2566', '34', '40', '47', '105', '114'), +('8', '5', '56', '1517', '2620', '35', '40', '48', '107', '116'), +('8', '5', '57', '1568', '2674', '35', '41', '49', '109', '119'), +('8', '5', '58', '1620', '2728', '35', '41', '50', '111', '121'), +('8', '5', '59', '1673', '2782', '36', '42', '50', '114', '124'), +('8', '5', '60', '1727', '2836', '36', '42', '51', '116', '126'), +('8', '7', '1', '67', '72', '22', '22', '22', '23', '17'), +('8', '7', '2', '84', '79', '23', '22', '23', '18', '24'), +('8', '7', '3', '101', '87', '23', '23', '24', '19', '25'), +('8', '7', '4', '118', '110', '24', '23', '25', '19', '26'), +('8', '7', '5', '135', '120', '25', '24', '25', '20', '27'), +('8', '7', '6', '152', '145', '26', '24', '26', '21', '28'), +('8', '7', '7', '169', '171', '27', '24', '27', '22', '29'), +('8', '7', '8', '186', '198', '27', '25', '28', '23', '29'), +('8', '7', '9', '203', '241', '28', '25', '29', '24', '30'), +('8', '7', '10', '220', '255', '29', '26', '30', '24', '31'), +('8', '7', '11', '237', '285', '30', '26', '31', '25', '32'), +('8', '7', '12', '254', '316', '31', '27', '32', '26', '33'), +('8', '7', '13', '271', '348', '31', '27', '33', '27', '34'), +('8', '7', '14', '288', '381', '32', '28', '34', '28', '35'), +('8', '7', '15', '305', '415', '33', '28', '35', '29', '37'), +('8', '7', '16', '322', '450', '34', '29', '36', '30', '38'), +('8', '7', '17', '340', '486', '35', '29', '37', '31', '39'), +('8', '7', '18', '359', '523', '36', '30', '38', '32', '40'), +('8', '7', '19', '379', '589', '37', '30', '39', '33', '41'), +('8', '7', '20', '400', '600', '38', '31', '40', '34', '42'), +('8', '7', '21', '422', '640', '39', '31', '41', '35', '43'), +('8', '7', '22', '445', '681', '39', '32', '42', '36', '44'), +('8', '7', '23', '469', '723', '40', '32', '43', '37', '45'), +('8', '7', '24', '494', '766', '41', '33', '44', '38', '47'), +('8', '7', '25', '520', '810', '42', '33', '46', '39', '48'), +('8', '7', '26', '547', '898', '43', '34', '47', '40', '49'), +('8', '7', '27', '575', '947', '44', '34', '48', '41', '50'), +('8', '7', '28', '604', '996', '45', '35', '49', '42', '51'), +('8', '7', '29', '634', '996', '46', '35', '50', '43', '53'), +('8', '7', '30', '665', '1045', '47', '36', '51', '44', '54'), +('8', '7', '31', '697', '1165', '49', '36', '53', '46', '55'), +('8', '7', '32', '730', '1216', '50', '37', '54', '47', '57'), +('8', '7', '33', '764', '1277', '51', '38', '55', '48', '58'), +('8', '7', '34', '799', '1304', '52', '38', '56', '49', '59'), +('8', '7', '35', '835', '1355', '53', '39', '58', '50', '61'), +('8', '7', '36', '872', '1412', '54', '40', '59', '52', '62'), +('8', '7', '37', '910', '1473', '55', '40', '60', '53', '63'), +('8', '7', '38', '949', '1525', '56', '41', '62', '54', '65'), +('8', '7', '39', '989', '1561', '57', '41', '63', '55', '66'), +('8', '7', '40', '1030', '1599', '59', '42', '64', '57', '68'), +('8', '7', '41', '1072', '1627', '60', '43', '66', '58', '69'), +('8', '7', '42', '1115', '1683', '61', '43', '67', '59', '71'), +('8', '7', '43', '1159', '1716', '62', '44', '69', '60', '72'), +('8', '7', '44', '1204', '1746', '64', '45', '70', '62', '74'), +('8', '7', '45', '1250', '1780', '65', '45', '72', '63', '75'), +('8', '7', '46', '1297', '1844', '66', '46', '73', '65', '77'), +('8', '7', '47', '1345', '1988', '67', '47', '75', '66', '78'), +('8', '7', '48', '1394', '2024', '69', '48', '76', '67', '80'), +('8', '7', '49', '1444', '2077', '70', '48', '78', '69', '82'), +('8', '7', '50', '1495', '2127', '71', '49', '79', '70', '83'), +('8', '7', '51', '1547', '2177', '73', '50', '81', '72', '85'), +('8', '7', '52', '1600', '2204', '74', '51', '82', '73', '87'), +('8', '7', '53', '1654', '2235', '76', '51', '84', '75', '88'), +('8', '7', '54', '1709', '2256', '77', '52', '86', '76', '90'), +('8', '7', '55', '1765', '2286', '78', '53', '87', '78', '92'), +('8', '7', '56', '1822', '2319', '80', '54', '89', '79', '94'), +('8', '7', '57', '1880', '2384', '81', '55', '91', '81', '95'), +('8', '7', '58', '1939', '2432', '83', '55', '92', '83', '97'), +('8', '7', '59', '1999', '2481', '84', '56', '94', '84', '99'), +('8', '7', '60', '2060', '2530', '86', '57', '96', '86', '101'), +('8', '8', '1', '62', '119', '21', '22', '21', '23', '19'), +('8', '8', '2', '77', '130', '21', '22', '21', '20', '24'), +('8', '8', '3', '92', '156', '21', '22', '22', '21', '25'), +('8', '8', '4', '107', '183', '21', '23', '22', '23', '26'), +('8', '8', '5', '122', '211', '21', '23', '22', '24', '28'), +('8', '8', '6', '137', '240', '22', '23', '22', '25', '29'), +('8', '8', '7', '152', '270', '22', '23', '23', '26', '30'), +('8', '8', '8', '167', '286', '22', '23', '23', '27', '31'), +('8', '8', '9', '182', '333', '22', '23', '23', '29', '32'), +('8', '8', '10', '197', '366', '22', '24', '24', '30', '34'), +('8', '8', '11', '212', '400', '22', '24', '24', '31', '35'), +('8', '8', '12', '227', '435', '22', '24', '24', '33', '36'), +('8', '8', '13', '242', '471', '22', '24', '25', '34', '37'), +('8', '8', '14', '257', '508', '23', '24', '25', '35', '39'), +('8', '8', '15', '272', '546', '23', '25', '25', '37', '40'), +('8', '8', '16', '287', '585', '23', '25', '26', '38', '41'), +('8', '8', '17', '302', '610', '23', '25', '26', '39', '43'), +('8', '8', '18', '317', '666', '23', '25', '26', '41', '44'), +('8', '8', '19', '332', '693', '23', '25', '27', '42', '45'), +('8', '8', '20', '347', '751', '23', '26', '27', '44', '47'), +('8', '8', '21', '362', '780', '24', '26', '27', '45', '48'), +('8', '8', '22', '377', '840', '24', '26', '28', '47', '50'), +('8', '8', '23', '392', '871', '24', '26', '28', '48', '51'), +('8', '8', '24', '408', '933', '24', '27', '29', '50', '53'), +('8', '8', '25', '425', '966', '24', '27', '29', '51', '54'), +('8', '8', '26', '443', '1030', '24', '27', '29', '53', '56'), +('8', '8', '27', '462', '1080', '24', '27', '30', '55', '57'), +('8', '8', '28', '482', '1116', '25', '27', '30', '56', '59'), +('8', '8', '29', '503', '1182', '25', '28', '31', '58', '60'), +('8', '8', '30', '525', '1233', '25', '28', '31', '60', '62'), +('8', '8', '31', '548', '1269', '25', '28', '31', '61', '64'), +('8', '8', '32', '572', '1335', '25', '28', '32', '63', '65'), +('8', '8', '33', '597', '1386', '25', '29', '32', '65', '67'), +('8', '8', '34', '623', '1422', '26', '29', '33', '66', '69'), +('8', '8', '35', '650', '1473', '26', '29', '33', '68', '70'), +('8', '8', '36', '678', '1524', '26', '30', '34', '70', '72'), +('8', '8', '37', '707', '1590', '26', '30', '34', '72', '74'), +('8', '8', '38', '737', '1641', '26', '30', '34', '74', '76'), +('8', '8', '39', '768', '1692', '27', '30', '35', '76', '77'), +('8', '8', '40', '800', '1728', '27', '31', '35', '77', '79'), +('8', '8', '41', '833', '1779', '27', '31', '36', '79', '81'), +('8', '8', '42', '867', '1830', '27', '31', '36', '81', '83'), +('8', '8', '43', '902', '1881', '27', '31', '37', '83', '85'), +('8', '8', '44', '938', '1932', '27', '32', '37', '85', '87'), +('8', '8', '45', '975', '1983', '28', '32', '38', '87', '89'), +('8', '8', '46', '1013', '2034', '28', '32', '38', '89', '91'), +('8', '8', '47', '1092', '2085', '28', '33', '39', '91', '93'), +('8', '8', '48', '1102', '2151', '28', '33', '39', '94', '95'), +('8', '8', '49', '1133', '2202', '29', '33', '40', '96', '97'), +('8', '8', '50', '1175', '2238', '29', '34', '40', '98', '99'), +('8', '8', '51', '1218', '2289', '29', '34', '41', '100', '101'), +('8', '8', '52', '1262', '2340', '29', '34', '41', '102', '103'), +('8', '8', '53', '1307', '2391', '29', '35', '42', '104', '105'), +('8', '8', '54', '1353', '2442', '30', '35', '43', '107', '107'), +('8', '8', '55', '1400', '2508', '30', '35', '43', '109', '110'), +('8', '8', '56', '1448', '2547', '30', '36', '44', '111', '112'), +('8', '8', '57', '1497', '2595', '30', '36', '44', '114', '114'), +('8', '8', '58', '1547', '2646', '31', '36', '45', '116', '116'), +('8', '8', '59', '1589', '2697', '31', '37', '45', '119', '119'), +('8', '8', '60', '1650', '2748', '31', '37', '46', '121', '121'); diff --git a/sql/updates/0.6/2688_playercreateinfo.sql b/sql/updates/0.6/2688_playercreateinfo.sql new file mode 100644 index 00000000000..766e92b016e --- /dev/null +++ b/sql/updates/0.6/2688_playercreateinfo.sql @@ -0,0 +1,13 @@ +ALTER TABLE `playercreateinfo` + DROP `BaseStrength`, + DROP `BaseAgility`, + DROP `BaseStamina`, + DROP `BaseIntellect`, + DROP `BaseSpirit`, + DROP `BaseArmor`, + DROP `BaseHealth`, + DROP `BaseMana`, + DROP `BaseRage`, + DROP `BaseFocus`, + DROP `BaseEnergy`; + \ No newline at end of file diff --git a/sql/updates/0.6/2689_player_levelstats.sql b/sql/updates/0.6/2689_player_levelstats.sql new file mode 100644 index 00000000000..110f43327a0 --- /dev/null +++ b/sql/updates/0.6/2689_player_levelstats.sql @@ -0,0 +1,2422 @@ +-- ---------------------------- +-- Table structure for player_levelstats +-- ---------------------------- +DROP TABLE IF EXISTS `player_levelstats`; +CREATE TABLE `player_levelstats` ( + `race` tinyint(3) unsigned NOT NULL, + `class` tinyint(3) unsigned NOT NULL, + `level` tinyint(3) unsigned NOT NULL, + `hp` smallint(5) unsigned NOT NULL, + `mana` smallint(5) unsigned NOT NULL, + `str` tinyint(3) unsigned NOT NULL, + `agi` tinyint(3) unsigned NOT NULL, + `sta` tinyint(3) unsigned NOT NULL, + `int` tinyint(3) unsigned NOT NULL, + `spi` tinyint(3) unsigned NOT NULL, + PRIMARY KEY (`race`,`class`,`level`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 PACK_KEYS=0 COMMENT='Stores levels stats.'; + +-- ---------------------------- +-- Records +-- ---------------------------- +INSERT INTO `player_levelstats` VALUES +('1', '1', '1', '60', '0', '23', '20', '22', '20', '21'), +('1', '1', '2', '79', '0', '24', '21', '23', '20', '21'), +('1', '1', '3', '98', '0', '25', '21', '24', '20', '22'), +('1', '1', '4', '117', '0', '26', '22', '25', '20', '22'), +('1', '1', '5', '136', '0', '28', '23', '26', '20', '22'), +('1', '1', '6', '155', '0', '29', '24', '27', '21', '22'), +('1', '1', '7', '174', '0', '30', '24', '28', '21', '23'), +('1', '1', '8', '193', '0', '31', '25', '29', '21', '23'), +('1', '1', '9', '212', '0', '32', '26', '30', '21', '23'), +('1', '1', '10', '231', '0', '33', '26', '31', '21', '24'), +('1', '1', '11', '250', '0', '35', '27', '33', '21', '24'), +('1', '1', '12', '269', '0', '36', '28', '34', '21', '24'), +('1', '1', '13', '288', '0', '37', '29', '35', '21', '25'), +('1', '1', '14', '308', '0', '39', '30', '36', '22', '25'), +('1', '1', '15', '329', '0', '40', '30', '37', '22', '25'), +('1', '1', '16', '351', '0', '41', '31', '38', '22', '26'), +('1', '1', '17', '374', '0', '42', '32', '40', '22', '26'), +('1', '1', '18', '398', '0', '44', '33', '41', '22', '26'), +('1', '1', '19', '398', '0', '44', '33', '41', '22', '26'), +('1', '1', '20', '449', '0', '47', '35', '43', '22', '27'), +('1', '1', '21', '476', '0', '48', '35', '45', '23', '27'), +('1', '1', '22', '504', '0', '49', '36', '46', '23', '28'), +('1', '1', '23', '533', '0', '51', '37', '47', '23', '28'), +('1', '1', '24', '563', '0', '52', '38', '49', '23', '29'), +('1', '1', '25', '594', '0', '54', '39', '50', '23', '29'), +('1', '1', '26', '626', '0', '55', '40', '51', '23', '29'), +('1', '1', '27', '659', '0', '57', '41', '53', '23', '30'), +('1', '1', '28', '693', '0', '58', '42', '54', '24', '30'), +('1', '1', '29', '728', '0', '60', '43', '56', '24', '31'), +('1', '1', '30', '764', '0', '62', '44', '57', '24', '31'), +('1', '1', '31', '801', '0', '63', '45', '58', '24', '31'), +('1', '1', '32', '839', '0', '65', '46', '60', '24', '32'), +('1', '1', '33', '878', '0', '66', '47', '61', '24', '32'), +('1', '1', '34', '918', '0', '68', '48', '63', '25', '33'), +('1', '1', '35', '959', '0', '70', '49', '64', '25', '33'), +('1', '1', '36', '1001', '0', '72', '50', '66', '25', '34'), +('1', '1', '37', '1045', '0', '73', '51', '68', '25', '34'), +('1', '1', '38', '1091', '0', '75', '52', '69', '25', '34'), +('1', '1', '39', '1139', '0', '77', '53', '71', '26', '35'), +('1', '1', '40', '1189', '0', '79', '54', '72', '26', '35'), +('1', '1', '41', '1241', '0', '80', '56', '74', '26', '36'), +('1', '1', '42', '1295', '0', '82', '57', '76', '26', '36'), +('1', '1', '43', '1351', '0', '84', '58', '77', '26', '37'), +('1', '1', '44', '1409', '0', '86', '59', '79', '26', '37'), +('1', '1', '45', '1469', '0', '88', '60', '81', '27', '38'), +('1', '1', '46', '1531', '0', '90', '61', '83', '27', '38'), +('1', '1', '47', '1595', '0', '92', '63', '84', '27', '39'), +('1', '1', '48', '1661', '0', '94', '64', '86', '27', '39'), +('1', '1', '49', '1729', '0', '96', '65', '88', '28', '40'), +('1', '1', '50', '1799', '0', '98', '66', '90', '28', '40'), +('1', '1', '51', '1871', '0', '100', '68', '92', '28', '42'), +('1', '1', '52', '1945', '0', '102', '69', '94', '28', '42'), +('1', '1', '53', '2021', '0', '104', '70', '96', '28', '43'), +('1', '1', '54', '2099', '0', '106', '72', '98', '29', '44'), +('1', '1', '55', '2179', '0', '109', '73', '100', '29', '44'), +('1', '1', '56', '2261', '0', '111', '74', '102', '29', '45'), +('1', '1', '57', '2345', '0', '113', '76', '104', '29', '45'), +('1', '1', '58', '2431', '0', '115', '77', '106', '30', '46'), +('1', '1', '59', '2519', '0', '118', '79', '108', '30', '46'), +('1', '1', '60', '2609', '0', '120', '80', '110', '30', '47'), +('1', '2', '1', '68', '79', '22', '20', '22', '20', '22'), +('1', '2', '2', '76', '99', '23', '21', '23', '21', '23'), +('1', '2', '3', '94', '119', '24', '21', '24', '21', '23'), +('1', '2', '4', '112', '140', '25', '22', '25', '22', '24'), +('1', '2', '5', '130', '162', '26', '22', '26', '22', '25'), +('1', '2', '6', '148', '185', '27', '23', '27', '23', '25'), +('1', '2', '7', '166', '209', '28', '23', '28', '24', '26'), +('1', '2', '8', '184', '234', '29', '24', '28', '24', '26'), +('1', '2', '9', '202', '260', '30', '24', '29', '25', '27'), +('1', '2', '10', '220', '287', '31', '25', '30', '25', '28'), +('1', '2', '11', '238', '315', '32', '25', '31', '26', '29'), +('1', '2', '12', '256', '344', '33', '26', '32', '27', '29'), +('1', '2', '13', '274', '374', '34', '27', '33', '27', '30'), +('1', '2', '14', '292', '405', '35', '27', '34', '28', '31'), +('1', '2', '15', '311', '437', '36', '28', '36', '29', '31'), +('1', '2', '16', '331', '470', '38', '28', '37', '29', '32'), +('1', '2', '17', '352', '504', '39', '29', '38', '30', '33'), +('1', '2', '18', '374', '539', '40', '30', '39', '31', '34'), +('1', '2', '19', '397', '575', '41', '30', '40', '31', '34'), +('1', '2', '20', '421', '612', '42', '31', '41', '32', '35'), +('1', '2', '21', '446', '650', '43', '32', '42', '33', '36'), +('1', '2', '22', '472', '689', '45', '32', '43', '34', '37'), +('1', '2', '23', '499', '729', '46', '33', '44', '34', '38'), +('1', '2', '24', '527', '770', '47', '34', '46', '35', '38'), +('1', '2', '25', '556', '812', '48', '34', '47', '36', '39'), +('1', '2', '26', '586', '854', '50', '35', '48', '37', '40'), +('1', '2', '27', '617', '896', '51', '36', '49', '37', '42'), +('1', '2', '28', '649', '938', '52', '36', '50', '38', '43'), +('1', '2', '29', '682', '980', '54', '37', '52', '39', '44'), +('1', '2', '30', '716', '1022', '55', '38', '53', '40', '44'), +('1', '2', '31', '751', '1064', '56', '39', '54', '41', '45'), +('1', '2', '32', '787', '1106', '58', '39', '56', '42', '46'), +('1', '2', '33', '824', '1148', '59', '40', '57', '42', '47'), +('1', '2', '34', '862', '1190', '61', '41', '58', '43', '48'), +('1', '2', '35', '901', '1232', '62', '42', '60', '44', '49'), +('1', '2', '36', '941', '1274', '64', '43', '61', '45', '50'), +('1', '2', '37', '982', '1316', '65', '43', '62', '46', '51'), +('1', '2', '38', '1024', '1358', '67', '44', '64', '47', '52'), +('1', '2', '39', '1067', '1400', '68', '45', '65', '48', '53'), +('1', '2', '40', '1111', '1442', '70', '46', '67', '49', '54'), +('1', '2', '41', '1156', '1484', '71', '47', '68', '50', '55'), +('1', '2', '42', '1202', '1526', '73', '47', '70', '51', '56'), +('1', '2', '43', '1249', '1568', '74', '48', '71', '52', '57'), +('1', '2', '44', '1297', '1610', '76', '49', '73', '52', '58'), +('1', '2', '45', '1346', '1652', '78', '50', '74', '53', '59'), +('1', '2', '46', '1396', '1694', '79', '51', '76', '54', '60'), +('1', '2', '47', '1447', '1736', '81', '52', '77', '56', '61'), +('1', '2', '48', '1499', '1778', '83', '53', '79', '57', '63'), +('1', '2', '49', '1552', '1820', '84', '54', '81', '58', '65'), +('1', '2', '50', '1606', '1862', '86', '55', '82', '59', '66'), +('1', '2', '51', '1661', '1904', '88', '56', '84', '60', '67'), +('1', '2', '52', '1717', '1946', '90', '57', '86', '61', '68'), +('1', '2', '53', '1774', '1988', '92', '58', '87', '62', '69'), +('1', '2', '54', '1832', '2030', '93', '59', '89', '63', '70'), +('1', '2', '55', '1891', '2072', '95', '60', '91', '64', '72'), +('1', '2', '56', '1951', '2114', '97', '61', '93', '65', '73'), +('1', '2', '57', '2012', '2156', '99', '62', '94', '66', '74'), +('1', '2', '58', '2074', '2198', '101', '63', '96', '68', '75'), +('1', '2', '59', '2137', '2240', '103', '64', '98', '69', '77'), +('1', '2', '60', '2201', '2282', '105', '65', '100', '70', '78'), +('1', '4', '1', '55', '0', '21', '23', '21', '20', '20'), +('1', '4', '2', '72', '0', '22', '24', '22', '20', '21'), +('1', '4', '3', '89', '0', '22', '25', '22', '20', '22'), +('1', '4', '4', '106', '0', '23', '27', '23', '21', '22'), +('1', '4', '5', '123', '0', '24', '28', '24', '21', '22'), +('1', '4', '6', '140', '0', '24', '29', '24', '21', '23'), +('1', '4', '7', '157', '0', '25', '31', '25', '21', '23'), +('1', '4', '8', '174', '0', '26', '32', '25', '21', '23'), +('1', '4', '9', '191', '0', '27', '33', '26', '21', '24'), +('1', '4', '10', '208', '0', '27', '35', '27', '22', '24'), +('1', '4', '11', '225', '0', '28', '36', '28', '22', '25'), +('1', '4', '12', '242', '0', '29', '37', '28', '22', '25'), +('1', '4', '13', '259', '0', '30', '39', '29', '22', '25'), +('1', '4', '14', '276', '0', '30', '40', '30', '22', '26'), +('1', '4', '15', '293', '0', '31', '42', '30', '23', '26'), +('1', '4', '16', '311', '0', '32', '43', '31', '23', '27'), +('1', '4', '17', '330', '0', '33', '44', '32', '23', '27'), +('1', '4', '18', '350', '0', '34', '46', '33', '23', '27'), +('1', '4', '19', '371', '0', '35', '48', '33', '23', '28'), +('1', '4', '20', '393', '0', '35', '49', '34', '24', '28'), +('1', '4', '21', '416', '0', '36', '51', '35', '24', '29'), +('1', '4', '22', '440', '0', '37', '52', '36', '24', '29'), +('1', '4', '23', '465', '0', '38', '54', '37', '24', '30'), +('1', '4', '24', '491', '0', '39', '55', '37', '25', '30'), +('1', '4', '25', '518', '0', '40', '57', '38', '25', '31'), +('1', '4', '26', '546', '0', '41', '59', '39', '25', '31'), +('1', '4', '27', '575', '0', '42', '60', '40', '25', '31'), +('1', '4', '28', '605', '0', '43', '62', '41', '25', '32'), +('1', '4', '29', '636', '0', '43', '64', '42', '26', '32'), +('1', '4', '30', '668', '0', '44', '66', '42', '26', '33'), +('1', '4', '31', '701', '0', '45', '67', '43', '26', '33'), +('1', '4', '32', '735', '0', '46', '69', '44', '26', '34'), +('1', '4', '33', '770', '0', '47', '71', '45', '27', '34'), +('1', '4', '34', '806', '0', '48', '73', '46', '27', '35'), +('1', '4', '35', '843', '0', '49', '75', '47', '27', '35'), +('1', '4', '36', '881', '0', '51', '77', '48', '28', '36'), +('1', '4', '37', '920', '0', '52', '78', '49', '28', '37'), +('1', '4', '38', '960', '0', '53', '80', '50', '28', '37'), +('1', '4', '39', '1001', '0', '54', '82', '51', '28', '38'), +('1', '4', '40', '1043', '0', '55', '84', '52', '29', '38'), +('1', '4', '41', '1086', '0', '56', '86', '53', '29', '39'), +('1', '4', '42', '1130', '0', '57', '88', '54', '29', '39'), +('1', '4', '43', '1175', '0', '58', '90', '55', '29', '40'), +('1', '4', '44', '1221', '0', '59', '93', '56', '30', '40'), +('1', '4', '45', '1268', '0', '61', '95', '57', '30', '42'), +('1', '4', '46', '1316', '0', '62', '97', '58', '30', '43'), +('1', '4', '47', '1365', '0', '63', '99', '59', '31', '43'), +('1', '4', '48', '1415', '0', '64', '101', '60', '31', '44'), +('1', '4', '49', '1466', '0', '65', '103', '62', '31', '45'), +('1', '4', '50', '1518', '0', '67', '106', '63', '32', '45'), +('1', '4', '51', '1571', '0', '68', '108', '64', '32', '46'), +('1', '4', '52', '1625', '0', '69', '110', '65', '32', '46'), +('1', '4', '53', '1680', '0', '70', '113', '66', '33', '47'), +('1', '4', '54', '1736', '0', '72', '115', '67', '33', '48'), +('1', '4', '55', '1793', '0', '73', '117', '69', '33', '48'), +('1', '4', '56', '1851', '0', '74', '120', '70', '34', '49'), +('1', '4', '57', '1910', '0', '76', '122', '71', '34', '50'), +('1', '4', '58', '1970', '0', '77', '125', '72', '34', '51'), +('1', '4', '59', '2031', '0', '79', '127', '74', '35', '51'), +('1', '4', '60', '2093', '0', '80', '130', '75', '35', '52'), +('1', '5', '1', '61', '128', '20', '20', '20', '22', '24'), +('1', '5', '2', '67', '184', '20', '20', '20', '23', '25'), +('1', '5', '3', '82', '209', '20', '20', '21', '24', '26'), +('1', '5', '4', '97', '235', '21', '21', '21', '25', '28'), +('1', '5', '5', '112', '262', '21', '21', '21', '27', '29'), +('1', '5', '6', '127', '290', '21', '21', '22', '28', '30'), +('1', '5', '7', '142', '319', '21', '21', '22', '29', '31'), +('1', '5', '8', '157', '349', '21', '22', '22', '30', '32'), +('1', '5', '9', '172', '380', '21', '22', '23', '31', '34'), +('1', '5', '10', '187', '427', '22', '22', '23', '33', '35'), +('1', '5', '11', '202', '445', '22', '22', '24', '34', '36'), +('1', '5', '12', '217', '479', '22', '23', '24', '35', '38'), +('1', '5', '13', '232', '514', '22', '23', '24', '36', '39'), +('1', '5', '14', '247', '550', '22', '23', '25', '38', '40'), +('1', '5', '15', '262', '587', '23', '23', '25', '39', '43'), +('1', '5', '16', '277', '625', '23', '24', '26', '40', '44'), +('1', '5', '17', '292', '679', '23', '24', '26', '42', '45'), +('1', '5', '18', '307', '704', '23', '24', '26', '43', '47'), +('1', '5', '19', '322', '745', '23', '25', '27', '44', '48'), +('1', '5', '20', '337', '787', '24', '25', '27', '46', '50'), +('1', '5', '21', '352', '830', '24', '25', '28', '47', '51'), +('1', '5', '22', '368', '889', '24', '25', '28', '49', '53'), +('1', '5', '23', '385', '919', '24', '26', '29', '50', '54'), +('1', '5', '24', '403', '980', '25', '26', '29', '52', '56'), +('1', '5', '25', '422', '1012', '25', '26', '30', '53', '57'), +('1', '5', '26', '442', '1075', '25', '27', '30', '55', '59'), +('1', '5', '27', '463', '1109', '25', '27', '30', '56', '61'), +('1', '5', '28', '485', '1174', '25', '27', '31', '58', '63'), +('1', '5', '29', '508', '1210', '26', '28', '31', '59', '65'), +('1', '5', '30', '532', '1262', '26', '28', '32', '61', '67'), +('1', '5', '31', '557', '1330', '26', '28', '32', '63', '68'), +('1', '5', '32', '583', '1369', '26', '29', '33', '64', '70'), +('1', '5', '33', '610', '1438', '27', '29', '33', '66', '72'), +('1', '5', '34', '638', '1492', '27', '29', '34', '68', '73'), +('1', '5', '35', '667', '1531', '27', '30', '34', '69', '75'), +('1', '5', '36', '697', '1585', '28', '30', '35', '71', '77'), +('1', '5', '37', '728', '1654', '28', '30', '36', '73', '79'), +('1', '5', '38', '760', '1708', '28', '31', '36', '75', '81'), +('1', '5', '39', '793', '1747', '28', '31', '37', '76', '84'), +('1', '5', '40', '827', '1801', '29', '31', '37', '78', '85'), +('1', '5', '41', '862', '1870', '29', '32', '38', '80', '87'), +('1', '5', '42', '898', '1924', '29', '32', '38', '82', '89'), +('1', '5', '43', '935', '1978', '29', '33', '39', '84', '91'), +('1', '5', '44', '973', '2032', '30', '33', '39', '86', '93'), +('1', '5', '45', '1012', '2086', '30', '33', '40', '88', '95'), +('1', '5', '46', '1052', '2140', '30', '34', '41', '90', '97'), +('1', '5', '47', '1093', '2194', '31', '34', '41', '92', '99'), +('1', '5', '48', '1135', '2248', '31', '35', '42', '94', '102'), +('1', '5', '49', '1178', '2302', '31', '35', '43', '96', '105'), +('1', '5', '50', '1222', '2356', '32', '35', '43', '98', '107'), +('1', '5', '51', '1267', '2410', '32', '36', '44', '100', '109'), +('1', '5', '52', '1313', '2464', '32', '36', '44', '102', '111'), +('1', '5', '53', '1360', '2518', '33', '37', '45', '104', '113'), +('1', '5', '54', '1408', '2572', '33', '37', '46', '106', '116'), +('1', '5', '55', '1457', '2626', '33', '38', '46', '109', '118'), +('1', '5', '56', '1507', '2680', '34', '38', '47', '111', '120'), +('1', '5', '57', '1558', '2734', '34', '39', '48', '113', '123'), +('1', '5', '58', '1610', '2788', '34', '39', '49', '115', '126'), +('1', '5', '59', '1663', '2842', '35', '40', '49', '118', '129'), +('1', '5', '60', '1717', '2896', '35', '40', '50', '120', '131'), +('1', '8', '1', '61', '119', '20', '20', '20', '23', '22'), +('1', '8', '2', '67', '190', '20', '20', '20', '24', '24'), +('1', '8', '3', '82', '216', '20', '20', '21', '25', '25'), +('1', '8', '4', '97', '243', '20', '21', '21', '27', '26'), +('1', '8', '5', '112', '271', '20', '21', '21', '28', '28'), +('1', '8', '6', '127', '300', '21', '21', '21', '29', '29'), +('1', '8', '7', '142', '330', '21', '21', '22', '30', '30'), +('1', '8', '8', '157', '346', '21', '21', '22', '31', '31'), +('1', '8', '9', '172', '393', '21', '21', '22', '33', '32'), +('1', '8', '10', '187', '426', '21', '22', '23', '34', '34'), +('1', '8', '11', '202', '460', '21', '22', '23', '35', '35'), +('1', '8', '12', '217', '495', '21', '22', '23', '37', '36'), +('1', '8', '13', '232', '531', '21', '22', '24', '38', '37'), +('1', '8', '14', '247', '568', '22', '22', '24', '39', '39'), +('1', '8', '15', '262', '606', '22', '23', '24', '41', '40'), +('1', '8', '16', '277', '645', '22', '23', '25', '42', '42'), +('1', '8', '17', '292', '670', '22', '23', '25', '43', '44'), +('1', '8', '18', '307', '726', '22', '23', '25', '45', '45'), +('1', '8', '19', '322', '753', '22', '23', '26', '46', '46'), +('1', '8', '20', '337', '811', '22', '24', '26', '48', '48'), +('1', '8', '21', '352', '840', '23', '24', '26', '49', '49'), +('1', '8', '22', '367', '900', '23', '24', '27', '51', '51'), +('1', '8', '23', '382', '931', '23', '24', '27', '52', '52'), +('1', '8', '24', '398', '993', '23', '25', '28', '54', '54'), +('1', '8', '25', '415', '1026', '23', '25', '28', '55', '55'), +('1', '8', '26', '433', '1090', '23', '25', '28', '57', '57'), +('1', '8', '27', '452', '1140', '23', '25', '29', '59', '58'), +('1', '8', '28', '472', '1176', '24', '25', '29', '60', '60'), +('1', '8', '29', '493', '1242', '24', '26', '30', '62', '61'), +('1', '8', '30', '515', '1293', '24', '26', '30', '64', '64'), +('1', '8', '31', '538', '1329', '24', '26', '30', '65', '66'), +('1', '8', '32', '562', '1395', '24', '26', '31', '67', '67'), +('1', '8', '33', '587', '1446', '24', '27', '31', '69', '69'), +('1', '8', '34', '613', '1482', '25', '27', '32', '70', '71'), +('1', '8', '35', '640', '1533', '25', '27', '32', '72', '72'), +('1', '8', '36', '668', '1584', '25', '28', '33', '74', '74'), +('1', '8', '37', '697', '1650', '25', '28', '33', '76', '76'), +('1', '8', '38', '727', '1701', '25', '28', '33', '78', '78'), +('1', '8', '39', '758', '1752', '26', '28', '34', '80', '79'), +('1', '8', '40', '790', '1788', '26', '29', '34', '81', '81'), +('1', '8', '41', '823', '1839', '26', '29', '35', '83', '84'), +('1', '8', '42', '857', '1890', '26', '29', '35', '85', '86'), +('1', '8', '43', '892', '1941', '26', '29', '36', '87', '88'), +('1', '8', '44', '928', '1992', '26', '30', '36', '89', '90'), +('1', '8', '45', '965', '2043', '27', '30', '37', '91', '92'), +('1', '8', '46', '1003', '2094', '27', '30', '37', '93', '94'), +('1', '8', '47', '1042', '2145', '27', '31', '38', '95', '96'), +('1', '8', '48', '1082', '2211', '27', '31', '38', '98', '98'), +('1', '8', '49', '1123', '2262', '28', '31', '39', '100', '100'), +('1', '8', '50', '1165', '2298', '28', '32', '39', '102', '102'), +('1', '8', '51', '1208', '2349', '28', '32', '40', '104', '105'), +('1', '8', '52', '1252', '2400', '28', '32', '40', '106', '107'), +('1', '8', '53', '1297', '2451', '28', '33', '41', '108', '109'), +('1', '8', '54', '1343', '2502', '29', '33', '42', '111', '111'), +('1', '8', '55', '1390', '2553', '29', '33', '42', '113', '114'), +('1', '8', '56', '1438', '2604', '29', '34', '43', '115', '116'), +('1', '8', '57', '1487', '2655', '29', '34', '43', '118', '118'), +('1', '8', '58', '1537', '2706', '30', '34', '44', '120', '120'), +('1', '8', '59', '1588', '2757', '30', '35', '44', '123', '123'), +('1', '8', '60', '1640', '2808', '30', '35', '45', '125', '126'), +('1', '9', '1', '53', '109', '20', '20', '21', '22', '22'), +('1', '9', '2', '68', '163', '20', '20', '22', '23', '24'), +('1', '9', '3', '83', '187', '21', '21', '22', '24', '25'), +('1', '9', '4', '98', '212', '21', '21', '23', '25', '26'), +('1', '9', '5', '113', '238', '21', '21', '23', '26', '27'), +('1', '9', '6', '128', '265', '21', '22', '24', '27', '28'), +('1', '9', '7', '143', '293', '22', '22', '24', '28', '30'), +('1', '9', '8', '158', '322', '22', '22', '25', '29', '31'), +('1', '9', '9', '173', '352', '22', '23', '25', '30', '32'), +('1', '9', '10', '188', '383', '23', '23', '26', '31', '33'), +('1', '9', '11', '203', '415', '23', '24', '26', '33', '34'), +('1', '9', '12', '218', '448', '23', '24', '27', '34', '35'), +('1', '9', '13', '233', '482', '24', '24', '27', '35', '37'), +('1', '9', '14', '248', '517', '24', '25', '28', '36', '38'), +('1', '9', '15', '263', '553', '24', '25', '29', '37', '39'), +('1', '9', '16', '278', '590', '25', '26', '29', '38', '40'), +('1', '9', '17', '293', '628', '25', '26', '30', '40', '43'), +('1', '9', '18', '309', '667', '25', '26', '30', '41', '44'), +('1', '9', '19', '326', '707', '26', '27', '31', '42', '45'), +('1', '9', '20', '344', '748', '26', '27', '32', '43', '47'), +('1', '9', '21', '363', '790', '26', '28', '32', '45', '48'), +('1', '9', '22', '383', '833', '27', '28', '33', '46', '49'), +('1', '9', '23', '404', '877', '27', '29', '34', '47', '51'), +('1', '9', '24', '426', '922', '28', '29', '34', '49', '52'), +('1', '9', '25', '449', '968', '28', '30', '35', '50', '54'), +('1', '9', '26', '473', '1015', '28', '30', '36', '51', '55'), +('1', '9', '27', '498', '1063', '29', '30', '36', '53', '56'), +('1', '9', '28', '524', '1112', '29', '31', '37', '54', '58'), +('1', '9', '29', '551', '1162', '30', '31', '38', '56', '59'), +('1', '9', '30', '579', '1213', '30', '32', '38', '57', '61'), +('1', '9', '31', '608', '1264', '30', '32', '39', '58', '64'), +('1', '9', '32', '638', '1315', '31', '33', '40', '60', '65'), +('1', '9', '33', '669', '1366', '31', '33', '41', '61', '67'), +('1', '9', '34', '701', '1417', '32', '34', '41', '63', '68'), +('1', '9', '35', '734', '1468', '32', '34', '42', '64', '70'), +('1', '9', '36', '768', '1519', '33', '35', '43', '66', '72'), +('1', '9', '37', '803', '1570', '33', '36', '44', '68', '73'), +('1', '9', '38', '839', '1621', '33', '36', '45', '69', '75'), +('1', '9', '39', '876', '1672', '34', '37', '45', '71', '77'), +('1', '9', '40', '914', '1723', '34', '37', '46', '72', '78'), +('1', '9', '41', '953', '1774', '35', '38', '47', '74', '80'), +('1', '9', '42', '993', '1825', '35', '38', '48', '76', '82'), +('1', '9', '43', '1024', '1876', '36', '39', '48', '77', '86'), +('1', '9', '44', '1076', '1927', '36', '39', '50', '79', '86'), +('1', '9', '45', '1119', '1978', '37', '40', '50', '81', '88'), +('1', '9', '46', '1153', '2029', '37', '41', '51', '83', '90'), +('1', '9', '47', '1208', '2080', '38', '41', '52', '84', '92'), +('1', '9', '48', '1254', '2131', '38', '42', '53', '86', '94'), +('1', '9', '49', '1301', '2182', '39', '43', '54', '88', '96'), +('1', '9', '50', '1349', '2233', '39', '43', '55', '90', '98'), +('1', '9', '51', '1398', '2284', '40', '44', '56', '92', '100'), +('1', '9', '52', '1448', '2335', '40', '44', '57', '94', '102'), +('1', '9', '53', '1489', '2386', '41', '45', '58', '96', '105'), +('1', '9', '54', '1541', '2437', '42', '46', '59', '98', '107'), +('1', '9', '55', '1604', '2488', '42', '46', '60', '100', '109'), +('1', '9', '56', '1658', '2539', '43', '47', '61', '102', '111'), +('1', '9', '57', '1713', '2590', '43', '48', '62', '104', '113'), +('1', '9', '58', '1769', '2641', '44', '49', '63', '106', '116'), +('1', '9', '59', '1826', '2692', '44', '49', '64', '108', '118'), +('1', '9', '60', '1884', '2743', '45', '50', '65', '110', '120'), +('2', '1', '1', '80', '0', '26', '17', '24', '17', '23'), +('2', '1', '2', '99', '0', '27', '18', '25', '17', '23'), +('2', '1', '3', '118', '0', '28', '18', '26', '17', '24'), +('2', '1', '4', '137', '0', '29', '19', '27', '17', '24'), +('2', '1', '5', '156', '0', '31', '20', '28', '17', '24'), +('2', '1', '6', '175', '0', '32', '21', '29', '18', '24'), +('2', '1', '7', '194', '0', '33', '21', '30', '18', '25'), +('2', '1', '8', '213', '0', '34', '22', '31', '18', '25'), +('2', '1', '9', '232', '0', '35', '23', '32', '18', '25'), +('2', '1', '10', '251', '0', '36', '23', '33', '18', '26'), +('2', '1', '11', '270', '0', '38', '24', '35', '18', '26'), +('2', '1', '12', '289', '0', '39', '25', '36', '18', '26'), +('2', '1', '13', '308', '0', '40', '26', '37', '18', '27'), +('2', '1', '14', '328', '0', '42', '27', '38', '19', '27'), +('2', '1', '15', '349', '0', '43', '27', '39', '19', '27'), +('2', '1', '16', '371', '0', '44', '28', '40', '19', '28'), +('2', '1', '17', '394', '0', '45', '29', '42', '19', '28'), +('2', '1', '18', '418', '0', '47', '30', '43', '19', '28'), +('2', '1', '19', '443', '0', '48', '31', '44', '19', '29'), +('2', '1', '20', '469', '0', '50', '32', '45', '19', '29'), +('2', '1', '21', '496', '0', '51', '32', '47', '20', '29'), +('2', '1', '22', '524', '0', '52', '33', '48', '20', '30'), +('2', '1', '23', '553', '0', '54', '34', '49', '20', '30'), +('2', '1', '24', '583', '0', '55', '35', '51', '20', '31'), +('2', '1', '25', '614', '0', '57', '36', '52', '20', '31'), +('2', '1', '26', '646', '0', '58', '37', '53', '20', '31'), +('2', '1', '27', '679', '0', '60', '38', '55', '20', '32'), +('2', '1', '28', '713', '0', '61', '39', '56', '21', '32'), +('2', '1', '29', '748', '0', '63', '40', '58', '21', '33'), +('2', '1', '30', '784', '0', '65', '41', '59', '21', '33'), +('2', '1', '31', '821', '0', '66', '42', '60', '21', '33'), +('2', '1', '32', '859', '0', '68', '43', '62', '21', '34'), +('2', '1', '33', '898', '0', '69', '44', '63', '21', '34'), +('2', '1', '34', '938', '0', '71', '45', '65', '22', '35'), +('2', '1', '35', '979', '0', '73', '46', '66', '22', '35'), +('2', '1', '36', '1021', '0', '75', '47', '68', '22', '36'), +('2', '1', '37', '1065', '0', '76', '48', '70', '22', '36'), +('2', '1', '38', '1111', '0', '78', '49', '71', '22', '36'), +('2', '1', '39', '1159', '0', '80', '50', '73', '23', '37'), +('2', '1', '40', '1209', '0', '82', '51', '74', '23', '37'), +('2', '1', '41', '1261', '0', '83', '53', '76', '23', '38'), +('2', '1', '42', '1315', '0', '85', '54', '78', '23', '38'), +('2', '1', '43', '1371', '0', '87', '55', '79', '23', '39'), +('2', '1', '44', '1429', '0', '89', '56', '81', '23', '39'), +('2', '1', '45', '1489', '0', '91', '57', '83', '24', '40'), +('2', '1', '46', '1551', '0', '93', '58', '85', '24', '40'), +('2', '1', '47', '1615', '0', '95', '60', '86', '24', '41'), +('2', '1', '48', '1681', '0', '97', '61', '88', '24', '41'), +('2', '1', '49', '1749', '0', '99', '62', '90', '25', '42'), +('2', '1', '50', '1819', '0', '101', '63', '92', '25', '42'), +('2', '1', '51', '1891', '0', '103', '65', '94', '25', '43'), +('2', '1', '52', '1965', '0', '105', '66', '96', '25', '43'), +('2', '1', '53', '2041', '0', '107', '67', '98', '25', '44'), +('2', '1', '54', '2119', '0', '109', '69', '100', '26', '45'), +('2', '1', '55', '2199', '0', '112', '70', '102', '26', '45'), +('2', '1', '56', '2281', '0', '114', '71', '104', '26', '46'), +('2', '1', '57', '2365', '0', '116', '73', '106', '26', '46'), +('2', '1', '58', '2451', '0', '118', '74', '108', '27', '47'), +('2', '1', '59', '2539', '0', '121', '76', '110', '27', '47'), +('2', '1', '60', '2629', '0', '123', '77', '112', '27', '48'), +('2', '3', '1', '76', '80', '23', '20', '23', '17', '24'), +('2', '3', '2', '93', '88', '23', '21', '24', '18', '25'), +('2', '3', '3', '110', '109', '24', '22', '25', '18', '25'), +('2', '3', '4', '127', '117', '24', '24', '25', '19', '26'), +('2', '3', '5', '144', '140', '25', '25', '26', '19', '26'), +('2', '3', '6', '161', '150', '25', '26', '27', '20', '27'), +('2', '3', '7', '178', '175', '25', '27', '28', '20', '27'), +('2', '3', '8', '195', '201', '26', '28', '29', '21', '28'), +('2', '3', '9', '212', '228', '26', '30', '30', '21', '29'), +('2', '3', '10', '229', '256', '27', '31', '30', '22', '29'), +('2', '3', '11', '246', '285', '27', '32', '31', '22', '30'), +('2', '3', '12', '263', '315', '28', '34', '32', '23', '31'), +('2', '3', '13', '280', '346', '28', '35', '33', '24', '31'), +('2', '3', '14', '298', '378', '29', '36', '34', '24', '32'), +('2', '3', '15', '317', '411', '29', '38', '35', '25', '32'), +('2', '3', '16', '337', '445', '30', '39', '36', '25', '33'), +('2', '3', '17', '358', '480', '30', '40', '37', '26', '34'), +('2', '3', '18', '380', '516', '31', '42', '38', '27', '35'), +('2', '3', '19', '403', '553', '31', '43', '39', '27', '35'), +('2', '3', '20', '427', '591', '32', '45', '40', '28', '36'), +('2', '3', '21', '452', '630', '32', '46', '41', '29', '37'), +('2', '3', '22', '478', '670', '33', '48', '42', '29', '37'), +('2', '3', '23', '505', '711', '33', '49', '43', '30', '38'), +('2', '3', '24', '533', '753', '34', '51', '44', '31', '39'), +('2', '3', '25', '562', '796', '34', '52', '45', '31', '40'), +('2', '3', '26', '592', '840', '35', '54', '46', '32', '40'), +('2', '3', '27', '623', '885', '35', '56', '47', '33', '41'), +('2', '3', '28', '655', '930', '36', '57', '48', '33', '42'), +('2', '3', '29', '688', '975', '36', '59', '49', '34', '43'), +('2', '3', '30', '722', '1020', '37', '61', '50', '35', '43'), +('2', '3', '31', '757', '1065', '37', '62', '52', '36', '44'), +('2', '3', '32', '793', '1110', '38', '64', '53', '36', '45'), +('2', '3', '33', '830', '1155', '39', '66', '54', '37', '46'), +('2', '3', '34', '868', '1200', '39', '67', '55', '38', '47'), +('2', '3', '35', '907', '1245', '40', '69', '56', '39', '48'), +('2', '3', '36', '947', '1290', '41', '71', '58', '40', '49'), +('2', '3', '37', '988', '1335', '41', '73', '59', '40', '49'), +('2', '3', '38', '1030', '1380', '42', '75', '60', '41', '50'), +('2', '3', '39', '1073', '1425', '42', '77', '61', '42', '51'), +('2', '3', '40', '1117', '1470', '43', '78', '63', '43', '52'), +('2', '3', '41', '1162', '1515', '44', '80', '64', '44', '53'), +('2', '3', '42', '1208', '1560', '44', '82', '65', '44', '54'), +('2', '3', '43', '1255', '1605', '45', '84', '66', '45', '55'), +('2', '3', '44', '1303', '1650', '46', '86', '68', '46', '56'), +('2', '3', '45', '1352', '1695', '46', '88', '69', '47', '57'), +('2', '3', '46', '1402', '1740', '47', '90', '71', '48', '58'), +('2', '3', '47', '1453', '1785', '48', '92', '72', '49', '59'), +('2', '3', '48', '1505', '1830', '49', '95', '73', '50', '60'), +('2', '3', '49', '1558', '1875', '49', '97', '75', '51', '61'), +('2', '3', '50', '1612', '1920', '50', '99', '76', '52', '62'), +('2', '3', '51', '1667', '1965', '51', '101', '78', '53', '63'), +('2', '3', '52', '1723', '2010', '52', '103', '79', '54', '64'), +('2', '3', '53', '1780', '2055', '52', '105', '81', '55', '65'), +('2', '3', '54', '1838', '2100', '53', '108', '82', '56', '66'), +('2', '3', '55', '1897', '2145', '54', '110', '84', '57', '67'), +('2', '3', '56', '1957', '2190', '55', '112', '85', '58', '68'), +('2', '3', '57', '2018', '2235', '56', '115', '87', '59', '70'), +('2', '3', '58', '2080', '2280', '56', '117', '89', '60', '71'), +('2', '3', '59', '2143', '2325', '57', '120', '90', '61', '72'), +('2', '3', '60', '2207', '2370', '58', '122', '92', '62', '73'), +('2', '4', '1', '75', '0', '24', '20', '23', '17', '23'), +('2', '4', '2', '92', '0', '25', '21', '24', '17', '23'), +('2', '4', '3', '109', '0', '25', '22', '24', '17', '24'), +('2', '4', '4', '126', '0', '26', '24', '25', '18', '24'), +('2', '4', '5', '143', '0', '27', '25', '26', '18', '24'), +('2', '4', '6', '160', '0', '27', '26', '26', '18', '25'), +('2', '4', '7', '177', '0', '28', '28', '27', '18', '25'), +('2', '4', '8', '194', '0', '29', '29', '27', '18', '25'), +('2', '4', '9', '211', '0', '30', '30', '28', '18', '26'), +('2', '4', '10', '228', '0', '30', '32', '29', '19', '26'), +('2', '4', '11', '245', '0', '31', '33', '30', '19', '27'), +('2', '4', '12', '262', '0', '32', '34', '30', '19', '27'), +('2', '4', '13', '279', '0', '33', '36', '31', '19', '27'), +('2', '4', '14', '296', '0', '33', '37', '32', '19', '28'), +('2', '4', '15', '313', '0', '34', '39', '32', '20', '28'), +('2', '4', '16', '331', '0', '35', '40', '33', '20', '29'), +('2', '4', '17', '350', '0', '36', '41', '34', '20', '29'), +('2', '4', '18', '370', '0', '37', '43', '35', '20', '29'), +('2', '4', '19', '370', '0', '37', '43', '35', '20', '29'), +('2', '4', '20', '370', '0', '37', '43', '35', '20', '29'), +('2', '4', '21', '436', '0', '39', '48', '37', '21', '31'), +('2', '4', '22', '460', '0', '40', '49', '38', '21', '31'), +('2', '4', '23', '485', '0', '41', '51', '39', '21', '32'), +('2', '4', '24', '511', '0', '42', '52', '39', '22', '32'), +('2', '4', '25', '538', '0', '43', '54', '40', '22', '33'), +('2', '4', '26', '566', '0', '44', '56', '41', '22', '33'), +('2', '4', '27', '595', '0', '45', '57', '42', '22', '33'), +('2', '4', '28', '625', '0', '46', '59', '43', '22', '34'), +('2', '4', '29', '656', '0', '46', '61', '44', '23', '34'), +('2', '4', '30', '688', '0', '47', '63', '44', '23', '35'), +('2', '4', '31', '721', '0', '48', '64', '45', '23', '35'), +('2', '4', '32', '755', '0', '49', '66', '46', '23', '36'), +('2', '4', '33', '790', '0', '50', '68', '47', '24', '36'), +('2', '4', '34', '826', '0', '51', '70', '48', '24', '37'), +('2', '4', '35', '863', '0', '52', '72', '49', '24', '37'), +('2', '4', '36', '901', '0', '54', '74', '50', '25', '38'), +('2', '4', '37', '940', '0', '55', '75', '51', '25', '39'), +('2', '4', '38', '985', '0', '56', '77', '52', '25', '39'), +('2', '4', '39', '1021', '0', '57', '79', '53', '25', '40'), +('2', '4', '40', '1063', '0', '58', '81', '54', '26', '40'), +('2', '4', '41', '1106', '0', '59', '83', '55', '26', '41'), +('2', '4', '42', '1150', '0', '60', '85', '56', '26', '41'), +('2', '4', '43', '1195', '0', '61', '87', '57', '26', '42'), +('2', '4', '44', '1241', '0', '62', '90', '58', '27', '42'), +('2', '4', '45', '1288', '0', '64', '92', '59', '27', '43'), +('2', '4', '46', '1336', '0', '65', '94', '60', '27', '44'), +('2', '4', '47', '1385', '0', '66', '96', '61', '28', '44'), +('2', '4', '48', '1435', '0', '67', '98', '62', '28', '45'), +('2', '4', '49', '1486', '0', '68', '100', '64', '28', '46'), +('2', '4', '50', '1538', '0', '70', '103', '65', '29', '46'), +('2', '4', '51', '1591', '0', '71', '105', '66', '29', '47'), +('2', '4', '52', '1645', '0', '72', '107', '67', '29', '47'), +('2', '4', '53', '1700', '0', '73', '110', '68', '30', '48'), +('2', '4', '54', '1756', '0', '75', '112', '69', '30', '49'), +('2', '4', '55', '1813', '0', '76', '114', '71', '30', '49'), +('2', '4', '56', '1871', '0', '77', '117', '72', '31', '50'), +('2', '4', '57', '1930', '0', '79', '119', '73', '31', '51'), +('2', '4', '58', '1990', '0', '80', '122', '74', '31', '52'), +('2', '4', '59', '2051', '0', '82', '124', '76', '32', '52'), +('2', '4', '60', '2113', '0', '83', '127', '77', '32', '53'), +('2', '7', '1', '97', '71', '24', '17', '23', '18', '25'), +('2', '7', '2', '94', '80', '25', '17', '24', '19', '26'), +('2', '7', '3', '111', '88', '25', '18', '25', '20', '27'), +('2', '7', '4', '128', '111', '26', '18', '26', '20', '28'), +('2', '7', '5', '145', '135', '27', '19', '26', '21', '29'), +('2', '7', '6', '162', '160', '28', '19', '27', '22', '30'), +('2', '7', '7', '179', '186', '29', '19', '28', '23', '31'), +('2', '7', '8', '196', '213', '29', '20', '29', '24', '31'), +('2', '7', '9', '213', '256', '30', '20', '30', '25', '32'), +('2', '7', '10', '230', '270', '31', '21', '31', '25', '33'), +('2', '7', '11', '247', '300', '32', '21', '32', '26', '34'), +('2', '7', '12', '264', '331', '33', '22', '33', '27', '35'), +('2', '7', '13', '281', '363', '33', '22', '34', '28', '36'), +('2', '7', '14', '298', '396', '34', '23', '35', '29', '37'), +('2', '7', '15', '315', '430', '35', '23', '36', '30', '39'), +('2', '7', '16', '332', '465', '36', '24', '37', '31', '40'), +('2', '7', '17', '350', '501', '37', '24', '38', '32', '41'), +('2', '7', '18', '369', '538', '38', '25', '39', '33', '42'), +('2', '7', '19', '389', '576', '39', '25', '40', '34', '43'), +('2', '7', '20', '410', '615', '40', '26', '41', '35', '44'), +('2', '7', '21', '432', '655', '41', '26', '42', '36', '45'), +('2', '7', '22', '455', '731', '41', '27', '43', '37', '46'), +('2', '7', '23', '479', '738', '42', '27', '44', '38', '47'), +('2', '7', '24', '504', '781', '43', '28', '45', '39', '49'), +('2', '7', '25', '530', '825', '44', '28', '47', '40', '50'), +('2', '7', '26', '557', '914', '45', '29', '48', '41', '51'), +('2', '7', '27', '585', '916', '46', '29', '49', '42', '52'), +('2', '7', '28', '614', '963', '47', '30', '50', '43', '53'), +('2', '7', '29', '644', '1011', '48', '30', '51', '44', '55'), +('2', '7', '30', '675', '1113', '49', '31', '52', '45', '56'), +('2', '7', '31', '707', '1124', '51', '31', '54', '47', '57'), +('2', '7', '32', '740', '1232', '52', '32', '55', '48', '59'), +('2', '7', '33', '774', '1283', '53', '33', '56', '49', '60'), +('2', '7', '34', '809', '1319', '54', '33', '57', '50', '61'), +('2', '7', '35', '845', '1370', '55', '34', '59', '51', '63'), +('2', '7', '36', '882', '1438', '56', '35', '60', '53', '64'), +('2', '7', '37', '920', '1489', '57', '35', '61', '54', '65'), +('2', '7', '38', '959', '1541', '58', '36', '63', '55', '67'), +('2', '7', '39', '999', '1593', '59', '36', '64', '56', '68'), +('2', '7', '40', '1040', '1643', '61', '37', '65', '58', '70'), +('2', '7', '41', '1082', '1675', '62', '38', '67', '59', '71'), +('2', '7', '42', '1125', '1697', '63', '38', '68', '60', '73'), +('2', '7', '43', '1169', '1710', '64', '39', '70', '61', '74'), +('2', '7', '44', '1214', '1761', '66', '40', '71', '63', '76'), +('2', '7', '45', '1260', '1885', '67', '40', '73', '64', '77'), +('2', '7', '46', '1307', '1952', '68', '41', '74', '66', '79'), +('2', '7', '47', '1355', '2004', '69', '42', '76', '67', '80'), +('2', '7', '48', '1404', '2055', '71', '43', '77', '68', '82'), +('2', '7', '49', '1454', '2106', '72', '43', '79', '70', '84'), +('2', '7', '50', '1505', '2142', '73', '44', '80', '71', '85'), +('2', '7', '51', '1557', '2210', '75', '45', '82', '73', '87'), +('2', '7', '52', '1610', '2261', '76', '46', '83', '74', '89'), +('2', '7', '53', '1664', '2312', '78', '46', '85', '76', '90'), +('2', '7', '54', '1719', '2334', '79', '47', '87', '77', '92'), +('2', '7', '55', '1775', '2364', '80', '48', '88', '79', '94'), +('2', '7', '56', '1832', '2415', '82', '49', '90', '80', '96'), +('2', '7', '57', '1890', '2518', '83', '50', '92', '82', '97'), +('2', '7', '58', '1949', '2570', '85', '50', '93', '84', '99'), +('2', '7', '59', '2009', '2621', '86', '51', '95', '85', '101'), +('2', '7', '60', '2070', '2700', '88', '52', '97', '87', '103'), +('2', '9', '1', '73', '109', '23', '17', '23', '19', '25'), +('2', '9', '2', '88', '118', '23', '17', '24', '20', '26'), +('2', '9', '3', '103', '142', '24', '18', '24', '21', '27'), +('2', '9', '4', '118', '167', '24', '18', '25', '22', '28'), +('2', '9', '5', '133', '193', '24', '18', '25', '23', '29'), +('2', '9', '6', '148', '220', '24', '19', '26', '24', '30'), +('2', '9', '7', '163', '248', '25', '19', '26', '25', '32'), +('2', '9', '8', '178', '277', '25', '19', '27', '26', '33'), +('2', '9', '9', '193', '307', '25', '20', '27', '27', '34'), +('2', '9', '10', '208', '338', '26', '20', '28', '28', '35'), +('2', '9', '11', '223', '370', '26', '21', '28', '30', '36'), +('2', '9', '12', '238', '403', '26', '21', '29', '31', '37'), +('2', '9', '13', '253', '437', '27', '21', '29', '32', '39'), +('2', '9', '14', '268', '472', '27', '22', '30', '33', '40'), +('2', '9', '15', '283', '508', '27', '22', '31', '34', '41'), +('2', '9', '16', '298', '545', '28', '23', '31', '35', '42'), +('2', '9', '17', '313', '583', '28', '23', '32', '37', '44'), +('2', '9', '18', '329', '622', '28', '23', '32', '38', '45'), +('2', '9', '19', '364', '662', '29', '24', '33', '39', '46'), +('2', '9', '20', '376', '703', '29', '24', '34', '40', '48'), +('2', '9', '21', '408', '745', '29', '25', '34', '42', '49'), +('2', '9', '22', '408', '788', '30', '25', '34', '43', '50'), +('2', '9', '23', '424', '832', '30', '26', '35', '44', '52'), +('2', '9', '24', '446', '877', '31', '26', '35', '46', '53'), +('2', '9', '25', '469', '923', '31', '27', '36', '47', '55'), +('2', '9', '26', '493', '970', '31', '27', '37', '48', '56'), +('2', '9', '27', '518', '1018', '32', '27', '37', '50', '57'), +('2', '9', '28', '544', '1067', '32', '28', '38', '51', '59'), +('2', '9', '29', '571', '1117', '33', '28', '39', '53', '60'), +('2', '9', '30', '599', '1168', '33', '29', '39', '54', '62'), +('2', '9', '31', '628', '1219', '33', '29', '40', '55', '64'), +('2', '9', '32', '658', '1270', '34', '30', '41', '57', '65'), +('2', '9', '33', '679', '1321', '34', '30', '41', '58', '68'), +('2', '9', '34', '721', '1372', '35', '31', '42', '60', '68'), +('2', '9', '35', '754', '1423', '35', '31', '43', '61', '70'), +('2', '9', '36', '788', '1474', '36', '32', '44', '63', '71'), +('2', '9', '37', '823', '1525', '36', '33', '45', '65', '73'), +('2', '9', '38', '859', '1576', '36', '33', '46', '66', '75'), +('2', '9', '39', '896', '1627', '37', '34', '46', '68', '77'), +('2', '9', '40', '934', '1678', '37', '34', '47', '69', '78'), +('2', '9', '41', '973', '1729', '38', '35', '47', '71', '80'), +('2', '9', '42', '993', '1780', '38', '35', '47', '73', '83'), +('2', '9', '43', '1054', '1831', '39', '36', '50', '74', '84'), +('2', '9', '44', '1096', '1882', '39', '36', '51', '76', '85'), +('2', '9', '45', '1139', '1933', '40', '37', '51', '78', '87'), +('2', '9', '46', '1183', '1984', '40', '38', '52', '80', '89'), +('2', '9', '47', '1228', '2035', '41', '38', '53', '81', '91'), +('2', '9', '48', '1274', '2086', '41', '39', '53', '83', '93'), +('2', '9', '49', '1321', '2137', '42', '40', '54', '85', '96'), +('2', '9', '50', '1369', '2188', '42', '40', '56', '87', '97'), +('2', '9', '51', '1408', '2239', '43', '41', '56', '89', '99'), +('2', '9', '52', '1468', '2290', '43', '41', '58', '91', '101'), +('2', '9', '53', '1519', '2341', '44', '42', '59', '93', '103'), +('2', '9', '54', '1551', '2392', '45', '43', '60', '95', '105'), +('2', '9', '55', '1624', '2443', '45', '43', '61', '97', '106'), +('2', '9', '56', '1678', '2494', '46', '44', '62', '99', '109'), +('2', '9', '57', '1727', '2545', '46', '45', '62', '101', '110'), +('2', '9', '58', '1779', '2596', '47', '46', '64', '103', '114'), +('2', '9', '59', '1836', '2647', '47', '46', '65', '105', '116'), +('2', '9', '60', '1904', '2698', '48', '47', '66', '107', '118'), +('3', '1', '1', '90', '0', '25', '16', '25', '19', '19'), +('3', '1', '2', '109', '0', '26', '17', '26', '19', '19'), +('3', '1', '3', '128', '0', '27', '17', '27', '19', '20'), +('3', '1', '4', '147', '0', '28', '18', '28', '19', '20'), +('3', '1', '5', '166', '0', '30', '19', '29', '19', '20'), +('3', '1', '6', '185', '0', '31', '20', '30', '20', '20'), +('3', '1', '7', '204', '0', '32', '20', '31', '20', '21'), +('3', '1', '8', '223', '0', '33', '21', '32', '20', '21'), +('3', '1', '9', '242', '0', '34', '22', '33', '20', '21'), +('3', '1', '10', '261', '0', '35', '22', '34', '20', '22'), +('3', '1', '11', '280', '0', '37', '23', '36', '20', '22'), +('3', '1', '12', '299', '0', '38', '24', '37', '20', '22'), +('3', '1', '13', '318', '0', '39', '25', '38', '20', '23'), +('3', '1', '14', '338', '0', '41', '26', '39', '21', '23'), +('3', '1', '15', '359', '0', '42', '26', '40', '21', '23'), +('3', '1', '16', '381', '0', '43', '27', '41', '21', '24'), +('3', '1', '17', '404', '0', '44', '28', '43', '21', '24'), +('3', '1', '18', '428', '0', '46', '29', '44', '21', '24'), +('3', '1', '19', '453', '0', '47', '30', '45', '21', '25'), +('3', '1', '20', '479', '0', '49', '31', '46', '21', '25'), +('3', '1', '21', '506', '0', '50', '31', '48', '22', '25'), +('3', '1', '22', '534', '0', '51', '32', '49', '22', '26'), +('3', '1', '23', '563', '0', '53', '33', '50', '22', '26'), +('3', '1', '24', '593', '0', '54', '34', '52', '22', '27'), +('3', '1', '25', '624', '0', '56', '35', '53', '22', '27'), +('3', '1', '26', '656', '0', '57', '36', '54', '22', '27'), +('3', '1', '27', '689', '0', '59', '37', '56', '22', '28'), +('3', '1', '28', '723', '0', '60', '38', '57', '23', '28'), +('3', '1', '29', '758', '0', '62', '39', '59', '23', '29'), +('3', '1', '30', '794', '0', '64', '40', '60', '23', '29'), +('3', '1', '31', '831', '0', '65', '41', '61', '23', '29'), +('3', '1', '32', '869', '0', '67', '42', '63', '23', '30'), +('3', '1', '33', '908', '0', '68', '43', '64', '23', '30'), +('3', '1', '34', '948', '0', '70', '44', '66', '24', '31'), +('3', '1', '35', '989', '0', '72', '45', '67', '24', '31'), +('3', '1', '36', '1031', '0', '74', '46', '69', '24', '32'), +('3', '1', '37', '1075', '0', '75', '47', '71', '24', '32'), +('3', '1', '38', '1121', '0', '77', '48', '72', '24', '32'), +('3', '1', '39', '1169', '0', '79', '49', '74', '25', '33'), +('3', '1', '40', '1219', '0', '81', '50', '75', '25', '33'), +('3', '1', '41', '1271', '0', '82', '52', '77', '25', '34'), +('3', '1', '42', '1325', '0', '84', '53', '79', '25', '34'), +('3', '1', '43', '1381', '0', '86', '54', '80', '25', '35'), +('3', '1', '44', '1439', '0', '88', '55', '82', '25', '35'), +('3', '1', '45', '1499', '0', '90', '56', '84', '26', '36'), +('3', '1', '46', '1561', '0', '92', '57', '86', '26', '36'), +('3', '1', '47', '1625', '0', '94', '59', '87', '26', '37'), +('3', '1', '48', '1691', '0', '96', '60', '89', '26', '37'), +('3', '1', '49', '1759', '0', '98', '61', '91', '27', '38'), +('3', '1', '50', '1829', '0', '100', '62', '93', '27', '38'), +('3', '1', '51', '1901', '0', '102', '64', '95', '27', '39'), +('3', '1', '52', '1975', '0', '104', '65', '97', '27', '39'), +('3', '1', '53', '2051', '0', '106', '66', '99', '27', '40'), +('3', '1', '54', '2129', '0', '108', '68', '101', '28', '41'), +('3', '1', '55', '2209', '0', '111', '69', '103', '28', '41'), +('3', '1', '56', '2291', '0', '113', '70', '105', '28', '42'), +('3', '1', '57', '2375', '0', '115', '72', '107', '28', '42'), +('3', '1', '58', '2461', '0', '117', '73', '109', '29', '43'), +('3', '1', '59', '2549', '0', '120', '75', '111', '29', '43'), +('3', '1', '60', '2639', '0', '122', '76', '113', '29', '44'), +('3', '2', '1', '88', '79', '24', '16', '25', '19', '20'), +('3', '2', '2', '106', '84', '25', '17', '26', '20', '21'), +('3', '2', '3', '124', '104', '26', '17', '27', '20', '21'), +('3', '2', '4', '142', '125', '27', '18', '28', '21', '22'), +('3', '2', '5', '160', '147', '28', '18', '29', '21', '23'), +('3', '2', '6', '178', '170', '29', '19', '30', '22', '23'), +('3', '2', '7', '196', '194', '30', '19', '31', '23', '24'), +('3', '2', '8', '214', '219', '31', '20', '31', '23', '24'), +('3', '2', '9', '232', '245', '32', '20', '32', '24', '25'), +('3', '2', '10', '250', '272', '33', '21', '33', '24', '26'), +('3', '2', '11', '268', '300', '34', '21', '34', '25', '27'), +('3', '2', '12', '286', '329', '35', '22', '35', '26', '27'), +('3', '2', '13', '304', '359', '36', '23', '36', '26', '28'), +('3', '2', '14', '322', '390', '37', '23', '37', '27', '29'), +('3', '2', '15', '341', '422', '38', '24', '39', '28', '29'), +('3', '2', '16', '361', '455', '40', '24', '40', '28', '30'), +('3', '2', '17', '382', '489', '41', '25', '41', '29', '31'), +('3', '2', '18', '404', '524', '42', '26', '42', '30', '32'), +('3', '2', '19', '427', '560', '43', '26', '43', '30', '32'), +('3', '2', '20', '451', '597', '44', '27', '44', '31', '33'), +('3', '2', '21', '476', '635', '45', '28', '45', '32', '34'), +('3', '2', '22', '502', '674', '47', '28', '46', '33', '35'), +('3', '2', '23', '529', '714', '48', '29', '47', '33', '36'), +('3', '2', '24', '557', '755', '49', '30', '49', '34', '36'), +('3', '2', '25', '586', '797', '50', '30', '50', '35', '37'), +('3', '2', '26', '616', '839', '52', '31', '51', '36', '38'), +('3', '2', '27', '647', '881', '53', '32', '52', '36', '39'), +('3', '2', '28', '679', '923', '54', '32', '53', '37', '40'), +('3', '2', '29', '712', '965', '56', '33', '55', '38', '41'), +('3', '2', '30', '746', '1007', '57', '34', '56', '39', '41'), +('3', '2', '31', '781', '1049', '58', '35', '57', '40', '42'), +('3', '2', '32', '817', '1091', '60', '35', '59', '41', '43'), +('3', '2', '33', '854', '1133', '61', '36', '60', '41', '44'), +('3', '2', '34', '892', '1175', '63', '37', '61', '42', '45'), +('3', '2', '35', '931', '1217', '64', '38', '63', '43', '46'), +('3', '2', '36', '971', '1259', '66', '39', '64', '44', '47'), +('3', '2', '37', '1012', '1301', '67', '39', '65', '45', '48'), +('3', '2', '38', '1054', '1343', '69', '40', '67', '46', '49'), +('3', '2', '39', '1097', '1385', '70', '41', '68', '47', '50'), +('3', '2', '40', '1141', '1427', '72', '42', '70', '48', '51'), +('3', '2', '41', '1186', '1469', '73', '43', '71', '49', '52'), +('3', '2', '42', '1232', '1511', '75', '43', '73', '50', '53'), +('3', '2', '43', '1279', '1553', '76', '44', '74', '51', '54'), +('3', '2', '44', '1327', '1595', '78', '45', '76', '51', '55'), +('3', '2', '45', '1376', '1637', '80', '46', '77', '52', '56'), +('3', '2', '46', '1426', '1679', '81', '47', '79', '53', '57'), +('3', '2', '47', '1477', '1721', '83', '48', '80', '55', '58'), +('3', '2', '48', '1529', '1763', '85', '49', '82', '56', '59'), +('3', '2', '49', '1582', '1805', '86', '50', '84', '57', '61'), +('3', '2', '50', '1636', '1847', '88', '51', '85', '58', '62'), +('3', '2', '51', '1691', '1889', '90', '52', '87', '59', '63'), +('3', '2', '52', '1747', '1931', '92', '53', '89', '60', '64'), +('3', '2', '53', '1804', '1973', '94', '54', '90', '61', '65'), +('3', '2', '54', '1862', '2015', '95', '55', '92', '62', '66'), +('3', '2', '55', '1921', '2057', '97', '56', '94', '63', '68'), +('3', '2', '56', '1981', '2099', '99', '57', '96', '64', '69'), +('3', '2', '57', '2042', '2141', '101', '58', '97', '65', '70'), +('3', '2', '58', '2104', '2183', '103', '59', '99', '67', '71'), +('3', '2', '59', '2167', '2225', '105', '60', '101', '68', '73'), +('3', '2', '60', '2231', '2267', '107', '61', '103', '69', '74'), +('3', '3', '1', '86', '80', '22', '19', '24', '19', '20'), +('3', '3', '2', '103', '90', '22', '20', '25', '20', '21'), +('3', '3', '3', '120', '111', '23', '21', '26', '20', '21'), +('3', '3', '4', '137', '133', '23', '23', '26', '21', '22'), +('3', '3', '5', '154', '156', '24', '24', '27', '21', '22'), +('3', '3', '6', '171', '180', '24', '25', '28', '22', '23'), +('3', '3', '7', '188', '205', '24', '26', '29', '22', '23'), +('3', '3', '8', '205', '231', '25', '27', '30', '23', '24'), +('3', '3', '9', '222', '258', '25', '29', '31', '23', '25'), +('3', '3', '10', '239', '286', '26', '30', '31', '24', '25'), +('3', '3', '11', '256', '315', '26', '31', '32', '24', '26'), +('3', '3', '12', '273', '345', '27', '33', '33', '25', '27'), +('3', '3', '13', '290', '376', '27', '34', '34', '26', '27'), +('3', '3', '14', '308', '408', '28', '35', '35', '26', '28'), +('3', '3', '15', '327', '441', '28', '37', '36', '27', '28'), +('3', '3', '16', '347', '475', '29', '38', '37', '27', '29'), +('3', '3', '17', '368', '510', '29', '39', '38', '28', '30'), +('3', '3', '18', '390', '546', '30', '41', '39', '29', '31'), +('3', '3', '19', '413', '583', '30', '42', '40', '29', '31'), +('3', '3', '20', '437', '621', '31', '44', '41', '30', '32'), +('3', '3', '21', '462', '660', '31', '45', '42', '31', '33'), +('3', '3', '22', '488', '700', '32', '47', '43', '31', '33'), +('3', '3', '23', '515', '741', '32', '48', '44', '32', '34'), +('3', '3', '24', '543', '783', '33', '50', '45', '33', '35'), +('3', '3', '25', '572', '826', '33', '51', '46', '33', '36'), +('3', '3', '26', '602', '870', '34', '53', '47', '34', '36'), +('3', '3', '27', '633', '915', '34', '55', '48', '35', '37'), +('3', '3', '28', '665', '960', '35', '56', '49', '35', '38'), +('3', '3', '29', '698', '1005', '35', '58', '50', '36', '39'), +('3', '3', '30', '732', '1050', '36', '60', '51', '37', '39'), +('3', '3', '31', '767', '1095', '36', '61', '53', '38', '40'), +('3', '3', '32', '803', '1140', '37', '63', '54', '38', '41'), +('3', '3', '33', '840', '1185', '38', '65', '55', '39', '42'), +('3', '3', '34', '878', '1230', '38', '66', '56', '40', '43'), +('3', '3', '35', '917', '1275', '39', '68', '57', '41', '44'), +('3', '3', '36', '957', '1320', '40', '70', '59', '42', '45'), +('3', '3', '37', '998', '1365', '40', '72', '60', '42', '45'), +('3', '3', '38', '1040', '1410', '41', '74', '61', '43', '46'), +('3', '3', '39', '1083', '1455', '41', '76', '62', '44', '47'), +('3', '3', '40', '1127', '1500', '42', '77', '64', '45', '48'), +('3', '3', '41', '1172', '1545', '43', '79', '65', '46', '49'), +('3', '3', '42', '1218', '1590', '43', '81', '66', '46', '50'), +('3', '3', '43', '1265', '1635', '44', '83', '67', '47', '51'), +('3', '3', '44', '1313', '1680', '45', '85', '69', '48', '52'), +('3', '3', '45', '1362', '1725', '45', '87', '70', '49', '53'), +('3', '3', '46', '1412', '1770', '46', '89', '72', '50', '54'), +('3', '3', '47', '1463', '1815', '47', '91', '73', '51', '55'), +('3', '3', '48', '1515', '1860', '48', '94', '74', '52', '56'), +('3', '3', '49', '1568', '1905', '48', '96', '76', '53', '57'), +('3', '3', '50', '1622', '1950', '49', '98', '77', '54', '58'), +('3', '3', '51', '1677', '1995', '50', '100', '79', '55', '59'), +('3', '3', '52', '1733', '2040', '51', '102', '80', '56', '60'), +('3', '3', '53', '1790', '2085', '51', '104', '82', '57', '61'), +('3', '3', '54', '1848', '2130', '52', '107', '83', '58', '62'), +('3', '3', '55', '1907', '2175', '53', '109', '85', '59', '63'), +('3', '3', '56', '1967', '2220', '54', '111', '86', '60', '64'), +('3', '3', '57', '2028', '2265', '55', '114', '88', '61', '66'), +('3', '3', '58', '2090', '2310', '55', '116', '90', '62', '67'), +('3', '3', '59', '2153', '2355', '56', '119', '91', '63', '68'), +('3', '3', '60', '2217', '2400', '57', '121', '93', '64', '69'), +('3', '4', '1', '85', '0', '23', '19', '24', '19', '19'), +('3', '4', '2', '102', '0', '24', '20', '25', '19', '19'), +('3', '4', '3', '119', '0', '24', '21', '25', '19', '20'), +('3', '4', '4', '136', '0', '25', '23', '26', '20', '20'), +('3', '4', '5', '153', '0', '26', '24', '27', '20', '20'), +('3', '4', '6', '170', '0', '26', '25', '27', '20', '21'), +('3', '4', '7', '187', '0', '27', '27', '28', '20', '21'), +('3', '4', '8', '204', '0', '28', '28', '28', '20', '21'), +('3', '4', '9', '221', '0', '29', '29', '29', '20', '22'), +('3', '4', '10', '238', '0', '29', '31', '30', '21', '22'), +('3', '4', '11', '255', '0', '30', '32', '31', '21', '23'), +('3', '4', '12', '272', '0', '31', '33', '31', '21', '23'), +('3', '4', '13', '289', '0', '32', '35', '32', '21', '23'), +('3', '4', '14', '306', '0', '32', '36', '33', '21', '24'), +('3', '4', '15', '323', '0', '33', '38', '33', '22', '24'), +('3', '4', '16', '341', '0', '34', '39', '34', '22', '25'), +('3', '4', '17', '360', '0', '35', '40', '35', '22', '25'), +('3', '4', '18', '380', '0', '36', '42', '36', '22', '25'), +('3', '4', '19', '401', '0', '37', '44', '36', '22', '26'), +('3', '4', '20', '423', '0', '37', '45', '37', '23', '26'), +('3', '4', '21', '446', '0', '38', '47', '38', '23', '27'), +('3', '4', '22', '470', '0', '39', '48', '39', '23', '27'), +('3', '4', '23', '495', '0', '40', '50', '40', '23', '28'), +('3', '4', '24', '521', '0', '41', '51', '40', '24', '28'), +('3', '4', '25', '548', '0', '42', '53', '41', '24', '29'), +('3', '4', '26', '576', '0', '43', '55', '42', '24', '29'), +('3', '4', '27', '605', '0', '44', '56', '43', '24', '29'), +('3', '4', '28', '635', '0', '45', '58', '44', '24', '30'), +('3', '4', '29', '666', '0', '45', '60', '45', '25', '30'), +('3', '4', '30', '698', '0', '46', '62', '45', '25', '31'), +('3', '4', '31', '731', '0', '47', '63', '46', '25', '31'), +('3', '4', '32', '765', '0', '48', '65', '47', '25', '32'), +('3', '4', '33', '800', '0', '49', '67', '48', '26', '32'), +('3', '4', '34', '836', '0', '50', '69', '49', '26', '33'), +('3', '4', '35', '873', '0', '51', '71', '50', '26', '33'), +('3', '4', '36', '911', '0', '53', '73', '51', '27', '34'), +('3', '4', '37', '950', '0', '54', '74', '52', '27', '35'), +('3', '4', '38', '990', '0', '55', '76', '53', '27', '35'), +('3', '4', '39', '1031', '0', '56', '78', '54', '27', '36'), +('3', '4', '40', '1073', '0', '57', '80', '55', '28', '36'), +('3', '4', '41', '1116', '0', '58', '82', '56', '28', '37'), +('3', '4', '42', '1160', '0', '59', '84', '57', '28', '37'), +('3', '4', '43', '1205', '0', '60', '86', '58', '28', '38'), +('3', '4', '44', '1251', '0', '61', '89', '59', '29', '38'), +('3', '4', '45', '1298', '0', '63', '91', '60', '29', '39'), +('3', '4', '46', '1346', '0', '64', '93', '61', '29', '40'), +('3', '4', '47', '1395', '0', '65', '95', '62', '30', '40'), +('3', '4', '48', '1445', '0', '66', '97', '63', '30', '41'), +('3', '4', '49', '1496', '0', '67', '99', '65', '30', '42'), +('3', '4', '50', '1548', '0', '69', '102', '66', '31', '42'), +('3', '4', '51', '1601', '0', '70', '104', '67', '31', '43'), +('3', '4', '52', '1655', '0', '71', '106', '68', '31', '43'), +('3', '4', '53', '1710', '0', '72', '109', '69', '32', '44'), +('3', '4', '54', '1766', '0', '74', '111', '70', '32', '45'), +('3', '4', '55', '1823', '0', '75', '113', '72', '32', '45'), +('3', '4', '56', '1881', '0', '76', '116', '73', '33', '46'), +('3', '4', '57', '1940', '0', '78', '118', '74', '33', '47'), +('3', '4', '58', '2000', '0', '79', '121', '75', '33', '48'), +('3', '4', '59', '2061', '0', '81', '123', '77', '34', '48'), +('3', '4', '60', '2123', '0', '82', '126', '78', '34', '49'), +('3', '5', '1', '91', '128', '22', '16', '23', '21', '22'), +('3', '5', '2', '97', '169', '22', '16', '23', '22', '23'), +('3', '5', '3', '112', '194', '22', '16', '24', '23', '24'), +('3', '5', '4', '127', '220', '23', '17', '24', '24', '26'), +('3', '5', '5', '142', '247', '23', '17', '24', '26', '27'), +('3', '5', '6', '157', '275', '23', '17', '25', '27', '28'), +('3', '5', '7', '172', '304', '23', '17', '25', '28', '29'), +('3', '5', '8', '187', '334', '23', '18', '25', '29', '30'), +('3', '5', '9', '202', '365', '23', '18', '26', '30', '32'), +('3', '5', '10', '217', '412', '24', '18', '26', '32', '33'), +('3', '5', '11', '232', '430', '24', '18', '27', '33', '34'), +('3', '5', '12', '247', '464', '24', '19', '27', '34', '36'), +('3', '5', '13', '262', '499', '24', '19', '27', '35', '37'), +('3', '5', '14', '277', '535', '24', '19', '28', '37', '38'), +('3', '5', '15', '292', '572', '25', '19', '28', '38', '40'), +('3', '5', '16', '307', '610', '25', '20', '29', '39', '41'), +('3', '5', '17', '322', '664', '25', '20', '29', '41', '42'), +('3', '5', '18', '337', '689', '25', '20', '29', '42', '44'), +('3', '5', '19', '352', '730', '25', '21', '30', '43', '45'), +('3', '5', '20', '367', '772', '26', '21', '30', '45', '47'), +('3', '5', '21', '382', '815', '26', '21', '31', '46', '48'), +('3', '5', '22', '398', '874', '26', '21', '31', '48', '50'), +('3', '5', '23', '415', '904', '26', '22', '32', '49', '51'), +('3', '5', '24', '433', '965', '27', '22', '32', '51', '53'), +('3', '5', '25', '452', '997', '27', '22', '33', '52', '54'), +('3', '5', '26', '472', '1060', '27', '23', '33', '54', '56'), +('3', '5', '27', '493', '1094', '27', '23', '33', '55', '58'), +('3', '5', '28', '515', '1159', '27', '23', '34', '57', '59'), +('3', '5', '29', '538', '1195', '28', '24', '34', '58', '61'), +('3', '5', '30', '562', '1247', '28', '24', '35', '60', '63'), +('3', '5', '31', '587', '1315', '28', '24', '35', '62', '64'), +('3', '5', '32', '613', '1354', '28', '25', '36', '63', '66'), +('3', '5', '33', '640', '1423', '29', '25', '36', '65', '68'), +('3', '5', '34', '668', '1477', '29', '25', '37', '67', '69'), +('3', '5', '35', '697', '1516', '29', '26', '37', '68', '71'), +('3', '5', '36', '727', '1570', '30', '26', '38', '70', '73'), +('3', '5', '37', '758', '1639', '30', '26', '39', '72', '75'), +('3', '5', '38', '790', '1693', '30', '27', '39', '74', '77'), +('3', '5', '39', '823', '1732', '30', '27', '40', '75', '79'), +('3', '5', '40', '857', '1786', '31', '27', '40', '77', '80'), +('3', '5', '41', '892', '1855', '31', '28', '41', '79', '82'), +('3', '5', '42', '928', '1909', '31', '28', '41', '81', '84'), +('3', '5', '43', '965', '1963', '31', '29', '42', '83', '86'), +('3', '5', '44', '1003', '2017', '32', '29', '42', '85', '88'), +('3', '5', '45', '1042', '2071', '32', '29', '43', '87', '90'), +('3', '5', '46', '1082', '2125', '32', '30', '44', '89', '92'), +('3', '5', '47', '1123', '2179', '33', '30', '44', '91', '94'), +('3', '5', '48', '1165', '2233', '33', '31', '45', '93', '97'), +('3', '5', '49', '1208', '2287', '33', '31', '46', '95', '99'), +('3', '5', '50', '1252', '2341', '34', '31', '46', '97', '101'), +('3', '5', '51', '1297', '2395', '34', '32', '47', '99', '103'), +('3', '5', '52', '1343', '2449', '34', '32', '47', '101', '105'), +('3', '5', '53', '1390', '2503', '35', '33', '48', '103', '107'), +('3', '5', '54', '1438', '2557', '35', '33', '49', '105', '110'), +('3', '5', '55', '1487', '2611', '35', '34', '49', '108', '112'), +('3', '5', '56', '1537', '2665', '36', '34', '50', '110', '114'), +('3', '5', '57', '1588', '2719', '36', '35', '51', '112', '117'), +('3', '5', '58', '1640', '2773', '36', '35', '52', '114', '119'), +('3', '5', '59', '1693', '2827', '37', '36', '52', '117', '122'), +('3', '5', '60', '1747', '2881', '37', '36', '53', '119', '124'), +('4', '1', '1', '50', '0', '20', '25', '21', '20', '20'), +('4', '1', '2', '69', '0', '21', '26', '22', '20', '20'), +('4', '1', '3', '88', '0', '22', '26', '23', '20', '21'), +('4', '1', '4', '107', '0', '23', '27', '24', '20', '21'), +('4', '1', '5', '126', '0', '25', '28', '25', '20', '21'), +('4', '1', '6', '145', '0', '26', '29', '26', '21', '21'), +('4', '1', '7', '164', '0', '27', '29', '27', '21', '22'), +('4', '1', '8', '183', '0', '28', '30', '28', '21', '22'), +('4', '1', '9', '202', '0', '29', '31', '29', '21', '22'), +('4', '1', '10', '221', '0', '30', '31', '30', '21', '23'), +('4', '1', '11', '240', '0', '32', '32', '32', '21', '23'), +('4', '1', '12', '259', '0', '33', '33', '33', '21', '23'), +('4', '1', '13', '278', '0', '34', '34', '34', '21', '24'), +('4', '1', '14', '298', '0', '36', '35', '35', '22', '24'), +('4', '1', '15', '319', '0', '37', '35', '36', '22', '24'), +('4', '1', '16', '341', '0', '38', '36', '37', '22', '25'), +('4', '1', '17', '364', '0', '39', '37', '39', '22', '25'), +('4', '1', '18', '388', '0', '41', '38', '40', '22', '25'), +('4', '1', '19', '413', '0', '42', '39', '41', '22', '26'), +('4', '1', '20', '439', '0', '44', '40', '42', '22', '26'), +('4', '1', '21', '466', '0', '45', '40', '44', '23', '26'), +('4', '1', '22', '494', '0', '46', '41', '45', '23', '27'), +('4', '1', '23', '523', '0', '48', '42', '46', '23', '27'), +('4', '1', '24', '553', '0', '49', '43', '48', '23', '28'), +('4', '1', '25', '584', '0', '51', '44', '49', '23', '28'), +('4', '1', '26', '616', '0', '52', '45', '50', '23', '28'), +('4', '1', '27', '649', '0', '54', '46', '52', '23', '29'), +('4', '1', '28', '683', '0', '55', '47', '53', '24', '29'), +('4', '1', '29', '718', '0', '57', '48', '55', '24', '30'), +('4', '1', '30', '754', '0', '59', '49', '56', '24', '30'), +('4', '1', '31', '791', '0', '60', '50', '57', '24', '30'), +('4', '1', '32', '829', '0', '62', '51', '59', '24', '31'), +('4', '1', '33', '868', '0', '63', '52', '60', '24', '31'), +('4', '1', '34', '908', '0', '65', '53', '62', '25', '32'), +('4', '1', '35', '949', '0', '67', '54', '63', '25', '32'), +('4', '1', '36', '991', '0', '69', '55', '65', '25', '33'), +('4', '1', '37', '1035', '0', '70', '56', '67', '25', '33'), +('4', '1', '38', '1081', '0', '72', '57', '68', '25', '33'), +('4', '1', '39', '1129', '0', '74', '58', '70', '26', '34'), +('4', '1', '40', '1179', '0', '76', '59', '71', '26', '34'), +('4', '1', '41', '1231', '0', '77', '61', '73', '26', '35'), +('4', '1', '42', '1285', '0', '79', '62', '75', '26', '35'), +('4', '1', '43', '1341', '0', '81', '63', '76', '26', '36'), +('4', '1', '44', '1399', '0', '83', '64', '78', '26', '36'), +('4', '1', '45', '1459', '0', '85', '65', '80', '27', '37'), +('4', '1', '46', '1521', '0', '87', '66', '82', '27', '37'), +('4', '1', '47', '1585', '0', '89', '68', '83', '27', '38'), +('4', '1', '48', '1651', '0', '91', '69', '85', '27', '38'), +('4', '1', '49', '1719', '0', '93', '70', '87', '28', '39'), +('4', '1', '50', '1789', '0', '95', '71', '89', '28', '39'), +('4', '1', '51', '1861', '0', '97', '73', '91', '28', '40'), +('4', '1', '52', '1935', '0', '99', '74', '93', '28', '40'), +('4', '1', '53', '2011', '0', '101', '75', '95', '28', '41'), +('4', '1', '54', '2089', '0', '103', '77', '97', '29', '42'), +('4', '1', '55', '2169', '0', '106', '78', '99', '29', '42'), +('4', '1', '56', '2251', '0', '108', '79', '101', '29', '43'), +('4', '1', '57', '2335', '0', '110', '81', '103', '29', '43'), +('4', '1', '58', '2421', '0', '112', '82', '105', '30', '44'), +('4', '1', '59', '2509', '0', '115', '84', '107', '30', '44'), +('4', '1', '60', '2599', '0', '117', '85', '109', '30', '45'), +('4', '3', '1', '46', '80', '17', '28', '20', '20', '21'), +('4', '3', '2', '63', '105', '17', '29', '21', '21', '22'), +('4', '3', '3', '80', '126', '18', '30', '22', '21', '22'), +('4', '3', '4', '97', '148', '18', '32', '22', '22', '23'), +('4', '3', '5', '114', '171', '19', '33', '23', '22', '23'), +('4', '3', '6', '131', '195', '19', '34', '24', '23', '24'), +('4', '3', '7', '148', '220', '19', '35', '25', '23', '24'), +('4', '3', '8', '165', '246', '20', '36', '26', '24', '25'), +('4', '3', '9', '182', '273', '20', '38', '27', '24', '26'), +('4', '3', '10', '199', '301', '21', '39', '27', '25', '26'), +('4', '3', '11', '216', '330', '21', '40', '28', '25', '27'), +('4', '3', '12', '233', '360', '22', '42', '29', '26', '28'), +('4', '3', '13', '250', '391', '22', '43', '30', '27', '28'), +('4', '3', '14', '268', '423', '23', '44', '31', '27', '29'), +('4', '3', '15', '287', '456', '23', '46', '32', '28', '29'), +('4', '3', '16', '307', '490', '24', '47', '33', '28', '30'), +('4', '3', '17', '328', '525', '24', '48', '34', '29', '31'), +('4', '3', '18', '350', '561', '25', '50', '35', '30', '32'), +('4', '3', '19', '373', '598', '25', '51', '36', '30', '32'), +('4', '3', '20', '397', '636', '26', '53', '37', '31', '33'), +('4', '3', '21', '422', '675', '26', '54', '38', '32', '34'), +('4', '3', '22', '448', '715', '27', '56', '39', '32', '34'), +('4', '3', '23', '475', '756', '27', '57', '40', '33', '35'), +('4', '3', '24', '503', '798', '28', '59', '41', '34', '36'), +('4', '3', '25', '532', '841', '28', '60', '42', '34', '37'), +('4', '3', '26', '562', '885', '29', '62', '43', '35', '37'), +('4', '3', '27', '593', '930', '29', '64', '44', '36', '38'), +('4', '3', '28', '625', '975', '30', '65', '45', '36', '39'), +('4', '3', '29', '658', '1020', '30', '67', '46', '37', '40'), +('4', '3', '30', '692', '1065', '31', '69', '47', '38', '40'), +('4', '3', '31', '727', '1110', '31', '70', '49', '39', '41'), +('4', '3', '32', '763', '1155', '32', '72', '50', '39', '42'), +('4', '3', '33', '800', '1200', '33', '74', '51', '40', '43'), +('4', '3', '34', '838', '1245', '33', '75', '52', '41', '44'), +('4', '3', '35', '877', '1290', '34', '77', '53', '42', '45'), +('4', '3', '36', '917', '1335', '35', '79', '55', '43', '46'), +('4', '3', '37', '958', '1380', '35', '81', '56', '43', '46'), +('4', '3', '38', '1000', '1425', '36', '83', '57', '44', '47'), +('4', '3', '39', '1043', '1470', '36', '85', '58', '45', '48'), +('4', '3', '40', '1087', '1515', '37', '86', '60', '46', '49'), +('4', '3', '41', '1132', '1560', '38', '88', '61', '47', '50'), +('4', '3', '42', '1178', '1605', '38', '90', '62', '47', '51'), +('4', '3', '43', '1225', '1650', '39', '92', '63', '48', '52'), +('4', '3', '44', '1273', '1695', '40', '94', '65', '49', '53'), +('4', '3', '45', '1322', '1740', '40', '96', '66', '50', '54'), +('4', '3', '46', '1372', '1785', '41', '98', '68', '51', '55'), +('4', '3', '47', '1423', '1830', '42', '100', '69', '52', '56'), +('4', '3', '48', '1475', '1875', '43', '103', '70', '53', '57'), +('4', '3', '49', '1528', '1920', '43', '105', '72', '54', '58'), +('4', '3', '50', '1582', '1965', '44', '107', '73', '55', '59'), +('4', '3', '51', '1637', '2010', '45', '109', '75', '56', '60'), +('4', '3', '52', '1693', '2055', '46', '111', '76', '57', '61'), +('4', '3', '53', '1750', '2100', '46', '113', '78', '58', '62'), +('4', '3', '54', '1808', '2145', '47', '116', '79', '59', '63'), +('4', '3', '55', '1867', '2190', '48', '118', '81', '60', '64'), +('4', '3', '56', '1927', '2235', '49', '120', '82', '61', '65'), +('4', '3', '57', '1988', '2280', '50', '123', '84', '62', '67'), +('4', '3', '58', '2050', '2325', '50', '125', '86', '63', '68'), +('4', '3', '59', '2113', '2370', '51', '128', '87', '64', '69'), +('4', '3', '60', '2177', '2415', '52', '130', '89', '65', '70'), +('4', '4', '1', '45', '0', '18', '28', '20', '20', '20'), +('4', '4', '2', '62', '0', '19', '29', '21', '20', '20'), +('4', '4', '3', '79', '0', '19', '30', '21', '20', '21'), +('4', '4', '4', '96', '0', '20', '32', '22', '21', '21'), +('4', '4', '5', '113', '0', '21', '33', '23', '21', '21'), +('4', '4', '6', '130', '0', '21', '34', '23', '21', '22'), +('4', '4', '7', '147', '0', '22', '36', '24', '21', '22'), +('4', '4', '8', '164', '0', '23', '37', '24', '21', '22'), +('4', '4', '9', '181', '0', '24', '38', '25', '21', '23'), +('4', '4', '10', '198', '0', '24', '40', '26', '22', '23'), +('4', '4', '11', '215', '0', '25', '41', '27', '22', '24'), +('4', '4', '12', '232', '0', '26', '42', '27', '22', '24'), +('4', '4', '13', '249', '0', '27', '44', '28', '22', '24'), +('4', '4', '14', '266', '0', '27', '45', '29', '22', '25'), +('4', '4', '15', '283', '0', '28', '47', '29', '23', '25'), +('4', '4', '16', '301', '0', '29', '48', '30', '23', '26'), +('4', '4', '17', '320', '0', '30', '49', '31', '23', '26'), +('4', '4', '18', '340', '0', '31', '51', '32', '23', '26'), +('4', '4', '19', '361', '0', '32', '53', '32', '23', '27'), +('4', '4', '20', '383', '0', '32', '54', '33', '24', '27'), +('4', '4', '21', '406', '0', '33', '56', '34', '24', '28'), +('4', '4', '22', '430', '0', '34', '57', '35', '24', '28'), +('4', '4', '23', '455', '0', '35', '59', '36', '24', '29'), +('4', '4', '24', '481', '0', '36', '60', '36', '25', '29'), +('4', '4', '25', '508', '0', '37', '62', '37', '25', '30'), +('4', '4', '26', '536', '0', '38', '64', '38', '25', '30'), +('4', '4', '27', '565', '0', '39', '65', '39', '25', '30'), +('4', '4', '28', '595', '0', '40', '67', '40', '25', '31'), +('4', '4', '29', '626', '0', '40', '69', '41', '26', '31'), +('4', '4', '30', '658', '0', '41', '71', '41', '26', '32'), +('4', '4', '31', '691', '0', '42', '72', '42', '26', '32'), +('4', '4', '32', '725', '0', '43', '74', '43', '26', '33'), +('4', '4', '33', '760', '0', '44', '76', '44', '27', '33'), +('4', '4', '34', '796', '0', '45', '78', '45', '27', '34'), +('4', '4', '35', '833', '0', '46', '80', '46', '27', '34'), +('4', '4', '36', '871', '0', '48', '82', '47', '28', '35'), +('4', '4', '37', '910', '0', '49', '83', '48', '28', '36'), +('4', '4', '38', '950', '0', '50', '85', '49', '28', '36'), +('4', '4', '39', '991', '0', '51', '87', '50', '28', '37'), +('4', '4', '40', '1033', '0', '52', '89', '51', '29', '37'), +('4', '4', '41', '1076', '0', '53', '91', '52', '29', '38'), +('4', '4', '42', '1120', '0', '54', '93', '53', '29', '38'), +('4', '4', '43', '1165', '0', '55', '95', '54', '29', '39'), +('4', '4', '44', '1211', '0', '56', '98', '55', '30', '39'), +('4', '4', '45', '1258', '0', '58', '100', '56', '30', '40'), +('4', '4', '46', '1306', '0', '59', '102', '57', '30', '41'), +('4', '4', '47', '1355', '0', '60', '104', '58', '31', '41'), +('4', '4', '48', '1405', '0', '61', '106', '59', '31', '42'), +('4', '4', '49', '1456', '0', '62', '108', '61', '31', '43'), +('4', '4', '50', '1508', '0', '64', '111', '62', '32', '43'), +('4', '4', '51', '1561', '0', '65', '113', '63', '32', '44'), +('4', '4', '52', '1615', '0', '66', '115', '64', '32', '44'), +('4', '4', '53', '1670', '0', '67', '118', '65', '33', '45'), +('4', '4', '54', '1726', '0', '69', '120', '66', '33', '46'), +('4', '4', '55', '1783', '0', '70', '122', '68', '33', '46'), +('4', '4', '56', '1841', '0', '71', '125', '69', '34', '47'), +('4', '4', '57', '1900', '0', '73', '127', '70', '34', '48'), +('4', '4', '58', '1960', '0', '74', '130', '71', '34', '49'), +('4', '4', '59', '2021', '0', '76', '132', '73', '35', '49'), +('4', '4', '60', '2083', '0', '77', '135', '74', '35', '50'), +('4', '5', '1', '51', '128', '17', '25', '19', '22', '23'), +('4', '5', '2', '66', '184', '17', '25', '19', '23', '24'), +('4', '5', '3', '72', '209', '17', '25', '20', '24', '25'), +('4', '5', '4', '87', '235', '18', '26', '20', '25', '27'), +('4', '5', '5', '102', '262', '18', '26', '20', '27', '28'), +('4', '5', '6', '117', '290', '18', '26', '21', '28', '29'), +('4', '5', '7', '132', '319', '18', '26', '21', '29', '30'), +('4', '5', '8', '147', '349', '18', '27', '21', '30', '31'), +('4', '5', '9', '162', '380', '18', '27', '22', '31', '33'), +('4', '5', '10', '177', '427', '19', '27', '22', '33', '34'), +('4', '5', '11', '192', '445', '19', '27', '23', '34', '35'), +('4', '5', '12', '207', '479', '19', '28', '23', '35', '37'), +('4', '5', '13', '222', '514', '19', '28', '23', '36', '38'), +('4', '5', '14', '237', '550', '19', '28', '24', '38', '39'), +('4', '5', '15', '252', '587', '20', '28', '24', '39', '41'), +('4', '5', '16', '267', '625', '20', '29', '25', '40', '42'), +('4', '5', '17', '282', '679', '20', '29', '25', '42', '43'), +('4', '5', '18', '297', '704', '20', '29', '25', '43', '45'), +('4', '5', '19', '312', '745', '20', '30', '26', '44', '46'), +('4', '5', '20', '327', '787', '21', '30', '26', '46', '48'), +('4', '5', '21', '342', '830', '21', '30', '27', '47', '49'), +('4', '5', '22', '358', '889', '21', '30', '27', '49', '51'), +('4', '5', '23', '375', '919', '21', '31', '28', '50', '52'), +('4', '5', '24', '393', '980', '22', '31', '28', '52', '54'), +('4', '5', '25', '412', '1012', '22', '31', '29', '53', '55'), +('4', '5', '26', '432', '1075', '22', '32', '29', '55', '57'), +('4', '5', '27', '453', '1109', '22', '32', '29', '56', '59'), +('4', '5', '28', '475', '1174', '22', '32', '30', '58', '60'), +('4', '5', '29', '498', '1210', '23', '33', '30', '59', '62'), +('4', '5', '30', '522', '1262', '23', '33', '31', '61', '64'), +('4', '5', '31', '547', '1330', '23', '33', '31', '63', '65'), +('4', '5', '32', '573', '1369', '23', '34', '32', '64', '67'), +('4', '5', '33', '600', '1438', '24', '34', '32', '66', '69'), +('4', '5', '34', '628', '1492', '24', '34', '33', '68', '70'), +('4', '5', '35', '657', '1531', '24', '35', '33', '69', '72'), +('4', '5', '36', '687', '1585', '25', '35', '34', '71', '74'), +('4', '5', '37', '718', '1654', '25', '35', '35', '73', '76'), +('4', '5', '38', '750', '1708', '25', '36', '35', '75', '78'), +('4', '5', '39', '783', '1747', '25', '36', '36', '76', '80'), +('4', '5', '40', '817', '1801', '26', '36', '36', '78', '81'), +('4', '5', '41', '852', '1870', '26', '37', '37', '80', '83'), +('4', '5', '42', '888', '1924', '26', '37', '37', '82', '85'), +('4', '5', '43', '925', '1978', '26', '38', '38', '84', '87'), +('4', '5', '44', '963', '2032', '27', '38', '38', '86', '89'), +('4', '5', '45', '1002', '2086', '27', '38', '39', '88', '91'), +('4', '5', '46', '1042', '2140', '27', '39', '40', '90', '93'), +('4', '5', '47', '1083', '2194', '28', '39', '40', '92', '95'), +('4', '5', '48', '1125', '2248', '28', '40', '41', '94', '98'), +('4', '5', '49', '1168', '2302', '28', '40', '42', '96', '100'), +('4', '5', '50', '1212', '2356', '29', '40', '42', '98', '102'), +('4', '5', '51', '1257', '2410', '29', '41', '43', '100', '104'), +('4', '5', '52', '1303', '2464', '29', '41', '43', '102', '106'), +('4', '5', '53', '1350', '2518', '30', '42', '44', '104', '108'), +('4', '5', '54', '1398', '2572', '30', '42', '45', '106', '111'), +('4', '5', '55', '1447', '2626', '30', '43', '45', '109', '113'), +('4', '5', '56', '1497', '2680', '31', '43', '46', '111', '115'), +('4', '5', '57', '1548', '2734', '31', '44', '47', '113', '118'), +('4', '5', '58', '1600', '2788', '31', '44', '48', '115', '120'), +('4', '5', '59', '1653', '2842', '32', '45', '48', '118', '123'), +('4', '5', '60', '1707', '2896', '32', '45', '49', '120', '125'), +('4', '11', '1', '53', '67', '18', '25', '19', '22', '22'), +('4', '11', '2', '61', '122', '19', '25', '20', '23', '23'), +('4', '11', '3', '78', '145', '19', '26', '20', '24', '24'), +('4', '11', '4', '95', '169', '20', '26', '21', '25', '25'), +('4', '11', '5', '112', '194', '20', '27', '21', '26', '26'), +('4', '11', '6', '129', '220', '21', '27', '22', '27', '27'), +('4', '11', '7', '146', '247', '21', '28', '23', '28', '28'), +('4', '11', '8', '163', '260', '22', '28', '23', '28', '29'), +('4', '11', '9', '180', '289', '22', '29', '24', '29', '30'), +('4', '11', '10', '197', '319', '23', '29', '24', '30', '31'), +('4', '11', '11', '214', '350', '23', '30', '25', '31', '33'), +('4', '11', '12', '231', '382', '24', '30', '26', '32', '34'), +('4', '11', '13', '248', '415', '24', '31', '26', '33', '35'), +('4', '11', '14', '265', '449', '25', '31', '27', '34', '36'), +('4', '11', '15', '282', '499', '26', '32', '28', '36', '37'), +('4', '11', '16', '299', '535', '26', '32', '28', '37', '38'), +('4', '11', '17', '316', '572', '27', '33', '29', '38', '40'), +('4', '11', '18', '334', '610', '27', '34', '30', '39', '41'), +('4', '11', '19', '353', '649', '28', '34', '30', '40', '42'), +('4', '11', '20', '373', '689', '29', '35', '31', '41', '43'), +('4', '11', '21', '394', '730', '29', '35', '32', '42', '45'), +('4', '11', '22', '416', '757', '30', '36', '33', '43', '46'), +('4', '11', '23', '439', '800', '31', '37', '33', '44', '47'), +('4', '11', '24', '463', '859', '31', '37', '34', '46', '49'), +('4', '11', '25', '488', '904', '32', '38', '35', '47', '50'), +('4', '11', '26', '514', '949', '33', '38', '36', '48', '51'), +('4', '11', '27', '541', '979', '33', '39', '36', '49', '53'), +('4', '11', '28', '569', '1024', '34', '40', '37', '50', '54'), +('4', '11', '29', '598', '1084', '35', '40', '38', '52', '56'), +('4', '11', '30', '628', '1129', '35', '41', '39', '53', '57'), +('4', '11', '31', '659', '1159', '36', '42', '40', '54', '58'), +('4', '11', '32', '691', '1219', '37', '42', '41', '56', '60'), +('4', '11', '33', '724', '1264', '38', '43', '41', '57', '61'), +('4', '11', '34', '758', '1294', '38', '44', '42', '58', '63'), +('4', '11', '35', '793', '1354', '39', '44', '43', '60', '64'), +('4', '11', '36', '829', '1384', '40', '45', '44', '61', '66'), +('4', '11', '37', '866', '1429', '41', '46', '45', '62', '68'), +('4', '11', '38', '904', '1489', '42', '46', '46', '64', '69'), +('4', '11', '39', '943', '1519', '42', '47', '47', '65', '71'), +('4', '11', '40', '983', '1579', '43', '48', '48', '67', '72'), +('4', '11', '41', '1024', '1609', '44', '49', '49', '68', '74'), +('4', '11', '42', '1066', '1669', '45', '49', '50', '70', '76'), +('4', '11', '43', '1109', '1699', '46', '50', '51', '71', '77'), +('4', '11', '44', '1153', '1759', '47', '51', '51', '73', '79'), +('4', '11', '45', '1198', '1789', '47', '52', '52', '74', '81'), +('4', '11', '46', '1244', '1849', '48', '53', '53', '76', '83'), +('4', '11', '47', '1291', '1879', '49', '53', '55', '77', '84'), +('4', '11', '48', '1339', '1924', '50', '54', '56', '79', '86'), +('4', '11', '49', '1388', '1984', '51', '55', '57', '81', '88'), +('4', '11', '50', '1438', '2014', '52', '56', '58', '82', '90'), +('4', '11', '51', '1489', '2059', '53', '57', '59', '84', '92'), +('4', '11', '52', '1541', '2119', '54', '58', '60', '86', '94'), +('4', '11', '53', '1594', '2149', '55', '59', '61', '87', '96'), +('4', '11', '54', '1648', '2194', '56', '59', '62', '89', '98'), +('4', '11', '55', '1703', '2239', '57', '60', '63', '91', '100'), +('4', '11', '56', '1759', '2284', '58', '61', '64', '93', '102'), +('4', '11', '57', '1816', '2329', '59', '62', '65', '94', '104'), +('4', '11', '58', '1874', '2374', '60', '63', '67', '96', '106'), +('4', '11', '59', '1933', '2419', '61', '64', '68', '98', '108'), +('4', '11', '60', '1993', '2464', '62', '65', '69', '100', '110'), +('5', '1', '1', '70', '0', '22', '18', '23', '18', '25'), +('5', '1', '2', '89', '0', '23', '19', '24', '18', '25'), +('5', '1', '3', '108', '0', '24', '19', '25', '18', '26'), +('5', '1', '4', '127', '0', '25', '20', '26', '18', '26'), +('5', '1', '5', '146', '0', '27', '21', '27', '18', '26'), +('5', '1', '6', '165', '0', '28', '22', '28', '19', '26'), +('5', '1', '7', '184', '0', '29', '22', '29', '19', '27'), +('5', '1', '8', '203', '0', '30', '23', '30', '19', '27'), +('5', '1', '9', '222', '0', '31', '24', '31', '19', '27'), +('5', '1', '10', '241', '0', '32', '24', '32', '19', '28'), +('5', '1', '11', '260', '0', '34', '25', '34', '19', '28'), +('5', '1', '12', '279', '0', '35', '26', '35', '19', '28'), +('5', '1', '13', '298', '0', '36', '27', '36', '19', '29'), +('5', '1', '14', '318', '0', '38', '28', '37', '20', '29'), +('5', '1', '15', '339', '0', '39', '28', '38', '20', '29'), +('5', '1', '16', '361', '0', '40', '29', '39', '20', '30'), +('5', '1', '17', '384', '0', '41', '30', '41', '20', '30'), +('5', '1', '18', '408', '0', '43', '31', '42', '20', '30'), +('5', '1', '19', '433', '0', '44', '32', '43', '20', '31'), +('5', '1', '20', '459', '0', '46', '33', '44', '20', '31'), +('5', '1', '21', '486', '0', '47', '33', '46', '21', '31'), +('5', '1', '22', '514', '0', '48', '34', '47', '21', '32'), +('5', '1', '23', '543', '0', '50', '35', '48', '21', '32'), +('5', '1', '24', '573', '0', '51', '36', '50', '21', '33'), +('5', '1', '25', '604', '0', '53', '37', '51', '21', '33'), +('5', '1', '26', '636', '0', '54', '38', '52', '21', '33'), +('5', '1', '27', '669', '0', '56', '39', '54', '21', '34'), +('5', '1', '28', '703', '0', '57', '40', '55', '22', '34'), +('5', '1', '29', '738', '0', '59', '41', '57', '22', '35'), +('5', '1', '30', '774', '0', '61', '42', '58', '22', '35'), +('5', '1', '31', '811', '0', '62', '43', '59', '22', '35'), +('5', '1', '32', '849', '0', '64', '44', '61', '22', '36'), +('5', '1', '33', '888', '0', '65', '45', '62', '22', '36'), +('5', '1', '34', '928', '0', '67', '46', '64', '23', '37'), +('5', '1', '35', '969', '0', '69', '47', '65', '23', '37'), +('5', '1', '36', '1011', '0', '71', '48', '67', '23', '38'), +('5', '1', '37', '1055', '0', '72', '49', '69', '23', '38'), +('5', '1', '38', '1101', '0', '74', '50', '70', '23', '38'), +('5', '1', '39', '1149', '0', '76', '51', '72', '24', '39'), +('5', '1', '40', '1199', '0', '78', '52', '73', '24', '39'), +('5', '1', '41', '1251', '0', '79', '54', '75', '24', '40'), +('5', '1', '42', '1305', '0', '81', '55', '77', '24', '40'), +('5', '1', '43', '1361', '0', '83', '56', '78', '24', '41'), +('5', '1', '44', '1419', '0', '85', '57', '80', '24', '41'), +('5', '1', '45', '1479', '0', '87', '58', '82', '25', '42'), +('5', '1', '46', '1541', '0', '89', '59', '84', '25', '42'), +('5', '1', '47', '1605', '0', '91', '61', '85', '25', '43'), +('5', '1', '48', '1671', '0', '93', '62', '87', '25', '43'), +('5', '1', '49', '1739', '0', '95', '63', '89', '26', '44'), +('5', '1', '50', '1809', '0', '97', '64', '91', '26', '44'), +('5', '1', '51', '1881', '0', '99', '66', '93', '26', '45'), +('5', '1', '52', '1955', '0', '101', '67', '95', '26', '45'), +('5', '1', '53', '2031', '0', '103', '68', '97', '26', '46'), +('5', '1', '54', '2109', '0', '105', '70', '99', '27', '47'), +('5', '1', '55', '2189', '0', '108', '71', '101', '27', '47'), +('5', '1', '56', '2271', '0', '110', '72', '103', '27', '48'), +('5', '1', '57', '2355', '0', '112', '74', '105', '27', '48'), +('5', '1', '58', '2441', '0', '114', '75', '107', '28', '49'), +('5', '1', '59', '2529', '0', '117', '77', '109', '28', '49'), +('5', '1', '60', '2619', '0', '119', '78', '111', '28', '50'), +('5', '4', '1', '65', '0', '20', '21', '22', '18', '25'), +('5', '4', '2', '82', '0', '21', '22', '23', '18', '25'), +('5', '4', '3', '99', '0', '21', '23', '23', '18', '26'), +('5', '4', '4', '116', '0', '22', '25', '24', '19', '26'), +('5', '4', '5', '133', '0', '23', '26', '25', '19', '26'), +('5', '4', '6', '150', '0', '23', '27', '25', '19', '27'), +('5', '4', '7', '167', '0', '24', '29', '26', '19', '27'), +('5', '4', '8', '184', '0', '25', '30', '26', '19', '27'), +('5', '4', '9', '201', '0', '26', '31', '27', '19', '28'), +('5', '4', '10', '218', '0', '26', '33', '28', '20', '28'), +('5', '4', '11', '235', '0', '27', '34', '29', '20', '29'), +('5', '4', '12', '252', '0', '28', '35', '29', '20', '29'), +('5', '4', '13', '269', '0', '29', '37', '30', '20', '29'), +('5', '4', '14', '286', '0', '29', '38', '31', '20', '30'), +('5', '4', '15', '303', '0', '30', '40', '31', '21', '30'), +('5', '4', '16', '321', '0', '31', '41', '32', '21', '31'), +('5', '4', '17', '340', '0', '32', '42', '33', '21', '31'), +('5', '4', '18', '360', '0', '33', '44', '34', '21', '31'), +('5', '4', '19', '381', '0', '34', '46', '34', '21', '32'), +('5', '4', '20', '403', '0', '34', '47', '35', '22', '32'), +('5', '4', '21', '426', '0', '35', '49', '36', '22', '33'), +('5', '4', '22', '450', '0', '36', '50', '37', '22', '33'), +('5', '4', '23', '475', '0', '37', '52', '38', '22', '34'), +('5', '4', '24', '501', '0', '38', '53', '38', '23', '34'), +('5', '4', '25', '528', '0', '39', '55', '39', '23', '35'), +('5', '4', '26', '556', '0', '40', '57', '40', '23', '35'), +('5', '4', '27', '585', '0', '41', '58', '41', '23', '35'), +('5', '4', '28', '615', '0', '42', '60', '42', '23', '36'), +('5', '4', '29', '646', '0', '42', '62', '43', '24', '36'), +('5', '4', '30', '678', '0', '43', '64', '43', '24', '37'), +('5', '4', '31', '711', '0', '44', '65', '44', '24', '37'), +('5', '4', '32', '745', '0', '45', '67', '45', '24', '38'), +('5', '4', '33', '780', '0', '46', '69', '46', '25', '38'), +('5', '4', '34', '816', '0', '47', '71', '47', '25', '39'), +('5', '4', '35', '853', '0', '48', '73', '48', '25', '39'), +('5', '4', '36', '891', '0', '50', '75', '49', '26', '40'), +('5', '4', '37', '930', '0', '51', '76', '50', '26', '41'), +('5', '4', '38', '970', '0', '52', '78', '51', '26', '41'), +('5', '4', '39', '1011', '0', '53', '80', '52', '26', '42'), +('5', '4', '40', '1053', '0', '54', '82', '53', '27', '42'), +('5', '4', '41', '1096', '0', '55', '84', '54', '27', '43'), +('5', '4', '42', '1140', '0', '56', '86', '55', '27', '43'), +('5', '4', '43', '1185', '0', '57', '88', '56', '27', '44'), +('5', '4', '44', '1231', '0', '58', '91', '57', '28', '44'), +('5', '4', '45', '1278', '0', '60', '93', '58', '28', '45'), +('5', '4', '46', '1326', '0', '61', '95', '59', '28', '46'), +('5', '4', '47', '1375', '0', '62', '97', '60', '29', '46'), +('5', '4', '48', '1425', '0', '63', '99', '61', '29', '47'), +('5', '4', '49', '1476', '0', '64', '101', '63', '29', '48'), +('5', '4', '50', '1528', '0', '66', '104', '64', '30', '48'), +('5', '4', '51', '1581', '0', '67', '106', '65', '30', '49'), +('5', '4', '52', '1635', '0', '68', '108', '66', '30', '49'), +('5', '4', '53', '1690', '0', '69', '111', '67', '31', '50'), +('5', '4', '54', '1746', '0', '71', '113', '68', '31', '51'), +('5', '4', '55', '1803', '0', '72', '115', '70', '31', '51'), +('5', '4', '56', '1861', '0', '73', '118', '71', '32', '52'), +('5', '4', '57', '1920', '0', '75', '120', '72', '32', '53'), +('5', '4', '58', '1980', '0', '76', '123', '73', '32', '54'), +('5', '4', '59', '2041', '0', '78', '125', '75', '33', '54'), +('5', '4', '60', '2103', '0', '79', '128', '76', '33', '55'), +('5', '5', '1', '71', '128', '19', '18', '21', '20', '28'), +('5', '5', '2', '77', '154', '19', '18', '21', '21', '29'), +('5', '5', '3', '92', '179', '19', '18', '22', '22', '30'), +('5', '5', '4', '107', '205', '20', '19', '22', '23', '32'), +('5', '5', '5', '122', '232', '20', '19', '22', '25', '33'), +('5', '5', '6', '137', '260', '20', '19', '23', '26', '34'), +('5', '5', '7', '152', '289', '20', '19', '23', '27', '35'), +('5', '5', '8', '167', '319', '20', '20', '23', '28', '36'), +('5', '5', '9', '182', '350', '20', '20', '24', '29', '38'), +('5', '5', '10', '197', '397', '21', '20', '24', '31', '39'), +('5', '5', '11', '212', '415', '21', '20', '25', '32', '40'), +('5', '5', '12', '227', '449', '21', '21', '25', '33', '42'), +('5', '5', '13', '242', '484', '21', '21', '25', '34', '43'), +('5', '5', '14', '257', '520', '21', '21', '26', '36', '44'), +('5', '5', '15', '272', '557', '22', '21', '26', '37', '46'), +('5', '5', '16', '287', '595', '22', '22', '27', '38', '47'), +('5', '5', '17', '302', '649', '22', '22', '27', '40', '48'), +('5', '5', '18', '317', '674', '22', '22', '27', '41', '50'), +('5', '5', '19', '332', '715', '22', '23', '28', '42', '51'), +('5', '5', '20', '347', '757', '23', '23', '28', '44', '53'), +('5', '5', '21', '362', '800', '23', '23', '29', '45', '54'), +('5', '5', '22', '378', '859', '23', '23', '29', '47', '56'), +('5', '5', '23', '395', '889', '23', '24', '30', '48', '57'), +('5', '5', '24', '413', '950', '24', '24', '30', '50', '59'), +('5', '5', '25', '432', '982', '24', '24', '31', '51', '60'), +('5', '5', '26', '452', '1045', '24', '25', '31', '53', '62'), +('5', '5', '27', '473', '1079', '24', '25', '31', '54', '64'), +('5', '5', '28', '495', '1144', '24', '25', '32', '56', '65'), +('5', '5', '29', '518', '1180', '25', '26', '32', '57', '67'), +('5', '5', '30', '542', '1232', '25', '26', '33', '59', '69'), +('5', '5', '31', '567', '1300', '25', '26', '33', '61', '70'), +('5', '5', '32', '593', '1339', '25', '27', '34', '62', '72'), +('5', '5', '33', '620', '1408', '26', '27', '34', '64', '74'), +('5', '5', '34', '648', '1462', '26', '27', '35', '66', '75'), +('5', '5', '35', '677', '1501', '26', '28', '35', '67', '77'), +('5', '5', '36', '707', '1555', '27', '28', '36', '69', '79'), +('5', '5', '37', '738', '1624', '27', '28', '37', '71', '81'), +('5', '5', '38', '770', '1678', '27', '29', '37', '73', '83'), +('5', '5', '39', '803', '1717', '27', '29', '38', '74', '85'), +('5', '5', '40', '837', '1771', '28', '29', '38', '76', '86'), +('5', '5', '41', '872', '1840', '28', '30', '39', '78', '88'), +('5', '5', '42', '908', '1894', '28', '30', '39', '80', '90'), +('5', '5', '43', '945', '1948', '28', '31', '40', '82', '92'), +('5', '5', '44', '983', '2002', '29', '31', '40', '84', '94'), +('5', '5', '45', '1022', '2056', '29', '31', '41', '86', '96'), +('5', '5', '46', '1062', '2110', '29', '32', '42', '88', '98'), +('5', '5', '47', '1103', '2164', '30', '32', '42', '90', '100'), +('5', '5', '48', '1145', '2218', '30', '33', '43', '92', '103'), +('5', '5', '49', '1188', '2272', '30', '33', '44', '94', '105'), +('5', '5', '50', '1232', '2326', '31', '33', '44', '96', '107'), +('5', '5', '51', '1277', '2380', '31', '34', '45', '98', '109'), +('5', '5', '52', '1323', '2434', '31', '34', '45', '100', '111'), +('5', '5', '53', '1370', '2488', '32', '35', '46', '102', '113'), +('5', '5', '54', '1418', '2542', '32', '35', '47', '104', '116'), +('5', '5', '55', '1467', '2596', '32', '36', '47', '107', '118'), +('5', '5', '56', '1517', '2650', '33', '36', '48', '109', '120'), +('5', '5', '57', '1568', '2704', '33', '37', '49', '111', '123'), +('5', '5', '58', '1620', '2758', '33', '37', '50', '113', '125'), +('5', '5', '59', '1673', '2812', '34', '38', '50', '116', '128'), +('5', '5', '60', '1727', '2866', '34', '38', '51', '118', '130'), +('5', '8', '1', '62', '135', '19', '18', '21', '27', '21'), +('5', '8', '2', '77', '160', '19', '18', '21', '22', '28'), +('5', '8', '3', '92', '186', '19', '18', '22', '23', '29'), +('5', '8', '4', '107', '213', '19', '19', '22', '25', '30'), +('5', '8', '5', '122', '241', '19', '19', '22', '26', '32'), +('5', '8', '6', '137', '270', '20', '19', '22', '27', '33'), +('5', '8', '7', '152', '300', '20', '19', '23', '28', '34'), +('5', '8', '8', '167', '316', '20', '19', '23', '29', '35'), +('5', '8', '9', '182', '363', '20', '19', '23', '31', '36'), +('5', '8', '10', '197', '396', '20', '20', '24', '32', '38'), +('5', '8', '11', '212', '430', '20', '20', '24', '33', '39'), +('5', '8', '12', '227', '465', '20', '20', '24', '35', '40'), +('5', '8', '13', '242', '501', '20', '20', '25', '36', '41'), +('5', '8', '14', '257', '538', '21', '20', '25', '37', '43'), +('5', '8', '15', '272', '576', '21', '21', '25', '39', '44'), +('5', '8', '16', '287', '615', '21', '21', '26', '40', '45'), +('5', '8', '17', '302', '640', '21', '21', '26', '41', '47'), +('5', '8', '18', '317', '696', '21', '21', '26', '43', '48'), +('5', '8', '19', '332', '723', '21', '21', '27', '44', '49'), +('5', '8', '20', '347', '781', '21', '22', '27', '46', '51'), +('5', '8', '21', '362', '810', '22', '22', '27', '47', '52'), +('5', '8', '22', '377', '870', '22', '22', '28', '49', '54'), +('5', '8', '23', '392', '901', '22', '22', '28', '50', '55'), +('5', '8', '24', '408', '963', '22', '23', '29', '52', '57'), +('5', '8', '25', '425', '996', '22', '23', '29', '53', '58'), +('5', '8', '26', '443', '1060', '22', '23', '29', '55', '60'), +('5', '8', '27', '462', '1110', '22', '23', '30', '57', '61'), +('5', '8', '28', '482', '1146', '23', '23', '30', '58', '63'), +('5', '8', '29', '503', '1212', '23', '24', '31', '60', '64'), +('5', '8', '30', '525', '1263', '23', '24', '31', '62', '66'), +('5', '8', '31', '548', '1299', '23', '24', '31', '63', '68'), +('5', '8', '32', '572', '1365', '23', '24', '32', '65', '69'), +('5', '8', '33', '597', '1416', '23', '25', '32', '67', '71'), +('5', '8', '34', '623', '1452', '24', '25', '33', '68', '73'), +('5', '8', '35', '650', '1503', '24', '25', '33', '70', '74'), +('5', '8', '36', '678', '1554', '24', '26', '34', '72', '76'), +('5', '8', '37', '707', '1620', '24', '26', '34', '74', '78'), +('5', '8', '38', '737', '1671', '24', '26', '34', '76', '80'), +('5', '8', '39', '768', '1722', '25', '26', '35', '78', '81'), +('5', '8', '40', '800', '1758', '25', '27', '35', '79', '83'), +('5', '8', '41', '833', '1809', '25', '27', '36', '81', '85'), +('5', '8', '42', '867', '1860', '25', '27', '36', '83', '87'), +('5', '8', '43', '902', '1911', '25', '27', '37', '85', '89'), +('5', '8', '44', '938', '1962', '25', '28', '37', '87', '91'), +('5', '8', '45', '975', '2013', '26', '28', '38', '89', '93'), +('5', '8', '46', '1013', '2064', '26', '28', '38', '91', '95'), +('5', '8', '47', '1052', '2115', '26', '29', '39', '93', '97'), +('5', '8', '48', '1092', '2181', '26', '29', '39', '96', '99'), +('5', '8', '49', '1133', '2232', '27', '29', '40', '98', '101'), +('5', '8', '50', '1175', '2268', '27', '30', '40', '100', '103'), +('5', '8', '51', '1218', '2319', '27', '30', '41', '102', '105'), +('5', '8', '52', '1262', '2370', '27', '30', '41', '104', '107'), +('5', '8', '53', '1307', '2421', '27', '31', '42', '106', '109'), +('5', '8', '54', '1353', '2472', '28', '31', '43', '109', '111'), +('5', '8', '55', '1400', '2523', '28', '31', '43', '111', '114'), +('5', '8', '56', '1448', '2574', '28', '32', '44', '113', '116'), +('5', '8', '57', '1497', '2625', '28', '32', '44', '116', '118'), +('5', '8', '58', '1547', '2676', '29', '32', '45', '118', '120'), +('5', '8', '59', '1598', '2727', '29', '33', '45', '121', '123'), +('5', '8', '60', '1650', '2778', '29', '33', '46', '123', '125'), +('5', '9', '1', '63', '109', '19', '18', '22', '20', '27'), +('5', '9', '2', '78', '133', '19', '18', '23', '21', '28'), +('5', '9', '3', '93', '157', '20', '19', '23', '22', '29'), +('5', '9', '4', '108', '182', '20', '19', '24', '23', '30'), +('5', '9', '5', '123', '208', '20', '19', '24', '24', '31'), +('5', '9', '6', '138', '235', '20', '20', '25', '25', '32'), +('5', '9', '7', '153', '263', '21', '20', '25', '26', '34'), +('5', '9', '8', '168', '292', '21', '20', '26', '27', '35'), +('5', '9', '9', '183', '322', '21', '21', '26', '28', '36'), +('5', '9', '10', '198', '353', '22', '21', '27', '29', '37'), +('5', '9', '11', '213', '385', '22', '22', '27', '31', '38'), +('5', '9', '12', '228', '418', '22', '22', '28', '32', '39'), +('5', '9', '13', '243', '452', '23', '22', '28', '33', '41'), +('5', '9', '14', '258', '487', '23', '23', '29', '34', '42'), +('5', '9', '15', '273', '523', '23', '23', '30', '35', '43'), +('5', '9', '16', '288', '560', '24', '24', '30', '36', '44'), +('5', '9', '17', '303', '598', '24', '24', '31', '38', '46'), +('5', '9', '18', '319', '637', '24', '24', '31', '39', '47'), +('5', '9', '19', '336', '677', '25', '25', '32', '40', '48'), +('5', '9', '20', '354', '718', '25', '25', '33', '41', '50'), +('5', '9', '21', '373', '760', '25', '26', '33', '43', '51'), +('5', '9', '22', '393', '803', '26', '26', '34', '44', '52'), +('5', '9', '23', '414', '847', '26', '27', '35', '45', '54'), +('5', '9', '24', '436', '892', '27', '27', '35', '47', '55'), +('5', '9', '25', '459', '938', '27', '28', '36', '48', '57'), +('5', '9', '26', '483', '985', '27', '28', '37', '49', '58'), +('5', '9', '27', '508', '1033', '28', '28', '37', '51', '59'), +('5', '9', '28', '534', '1082', '28', '29', '38', '52', '61'), +('5', '9', '29', '561', '1132', '29', '29', '39', '54', '62'), +('5', '9', '30', '589', '1183', '29', '30', '39', '55', '64'), +('5', '9', '31', '618', '1234', '29', '30', '40', '56', '66'), +('5', '9', '32', '648', '1285', '30', '31', '41', '58', '67'), +('5', '9', '33', '679', '1336', '30', '31', '42', '59', '69'), +('5', '9', '34', '711', '1387', '31', '32', '42', '61', '70'), +('5', '9', '35', '744', '1438', '31', '32', '43', '62', '72'), +('5', '9', '36', '768', '1489', '32', '33', '43', '64', '75'), +('5', '9', '37', '813', '1540', '32', '34', '45', '66', '75'), +('5', '9', '38', '849', '1591', '32', '34', '46', '67', '77'), +('5', '9', '39', '886', '1642', '33', '35', '46', '69', '79'), +('5', '9', '40', '924', '1693', '33', '35', '47', '70', '80'), +('5', '9', '41', '963', '1744', '34', '36', '48', '72', '82'), +('5', '9', '42', '993', '1795', '34', '36', '48', '74', '85'), +('5', '9', '43', '1044', '1846', '35', '37', '50', '75', '86'), +('5', '9', '44', '1086', '1897', '35', '37', '51', '77', '87'), +('5', '9', '45', '1129', '1948', '36', '38', '51', '79', '89'), +('5', '9', '46', '1173', '1999', '36', '39', '52', '81', '90'), +('5', '9', '47', '1218', '2050', '37', '39', '53', '82', '93'), +('5', '9', '48', '1264', '2101', '37', '40', '54', '84', '95'), +('5', '9', '49', '1311', '2152', '38', '41', '55', '86', '96'), +('5', '9', '50', '1339', '2203', '38', '41', '56', '88', '99'), +('5', '9', '51', '1398', '2254', '39', '42', '57', '90', '101'), +('5', '9', '52', '1458', '2305', '39', '42', '58', '92', '103'), +('5', '9', '53', '1509', '2356', '40', '43', '59', '94', '105'), +('5', '9', '54', '1551', '2407', '41', '44', '60', '96', '107'), +('5', '9', '55', '1594', '2458', '41', '44', '60', '98', '110'), +('5', '9', '56', '1668', '2509', '42', '45', '62', '100', '111'), +('5', '9', '57', '1723', '2560', '42', '46', '63', '102', '113'), +('5', '9', '58', '1769', '2611', '43', '47', '63', '104', '116'), +('5', '9', '59', '1836', '2662', '43', '47', '65', '106', '118'), +('5', '9', '60', '1894', '2713', '44', '48', '66', '108', '120'), +('6', '1', '1', '80', '0', '28', '15', '24', '15', '22'), +('6', '1', '2', '103', '0', '29', '16', '25', '15', '22'), +('6', '1', '3', '123', '0', '30', '16', '26', '15', '23'), +('6', '1', '4', '144', '0', '31', '17', '27', '15', '23'), +('6', '1', '5', '163', '0', '33', '18', '28', '15', '23'), +('6', '1', '6', '183', '0', '34', '19', '29', '16', '23'), +('6', '1', '7', '204', '0', '35', '19', '30', '16', '24'), +('6', '1', '8', '223', '0', '36', '20', '31', '16', '24'), +('6', '1', '9', '244', '0', '37', '21', '32', '16', '24'), +('6', '1', '10', '264', '0', '38', '21', '33', '16', '25'), +('6', '1', '11', '283', '0', '40', '22', '35', '16', '25'), +('6', '1', '12', '302', '0', '41', '23', '36', '16', '25'), +('6', '1', '13', '322', '0', '42', '24', '37', '16', '26'), +('6', '1', '14', '344', '0', '44', '25', '38', '17', '26'), +('6', '1', '15', '365', '0', '45', '25', '39', '17', '26'), +('6', '1', '16', '390', '0', '46', '26', '40', '17', '27'), +('6', '1', '17', '414', '0', '47', '27', '42', '17', '27'), +('6', '1', '18', '438', '0', '49', '28', '43', '17', '27'), +('6', '1', '19', '466', '0', '50', '29', '44', '17', '28'), +('6', '1', '20', '491', '0', '52', '30', '45', '17', '28'), +('6', '1', '21', '520', '0', '53', '30', '47', '18', '28'), +('6', '1', '22', '550', '0', '54', '31', '48', '18', '29'), +('6', '1', '23', '580', '0', '56', '32', '49', '18', '29'), +('6', '1', '24', '611', '0', '57', '33', '51', '18', '30'), +('6', '1', '25', '645', '0', '59', '34', '52', '18', '30'), +('6', '1', '26', '677', '0', '60', '35', '53', '18', '30'), +('6', '1', '27', '713', '0', '62', '36', '55', '18', '31'), +('6', '1', '28', '748', '0', '63', '37', '56', '19', '31'), +('6', '1', '29', '785', '0', '65', '38', '58', '19', '32'), +('6', '1', '30', '824', '0', '67', '39', '59', '19', '32'), +('6', '1', '31', '861', '0', '68', '40', '60', '19', '32'), +('6', '1', '32', '902', '0', '70', '41', '62', '19', '33'), +('6', '1', '33', '942', '0', '71', '42', '63', '19', '33'), +('6', '1', '34', '984', '0', '73', '43', '65', '20', '34'), +('6', '1', '35', '1028', '0', '75', '44', '66', '20', '34'), +('6', '1', '36', '1071', '0', '77', '45', '68', '20', '35'), +('6', '1', '37', '1117', '0', '78', '46', '70', '20', '35'), +('6', '1', '38', '1167', '0', '80', '47', '71', '20', '35'), +('6', '1', '39', '1217', '0', '82', '48', '73', '21', '36'), +('6', '1', '40', '1268', '0', '84', '49', '74', '21', '36'), +('6', '1', '41', '1324', '0', '85', '51', '76', '21', '37'), +('6', '1', '42', '1381', '0', '87', '52', '78', '21', '37'), +('6', '1', '43', '1440', '0', '89', '53', '79', '21', '38'), +('6', '1', '44', '1500', '0', '91', '54', '81', '21', '38'), +('6', '1', '45', '1563', '0', '93', '55', '83', '22', '39'), +('6', '1', '46', '1629', '0', '95', '56', '85', '22', '39'), +('6', '1', '47', '1696', '0', '97', '58', '86', '22', '40'), +('6', '1', '48', '1764', '0', '99', '59', '88', '22', '40'), +('6', '1', '49', '1836', '0', '101', '60', '90', '23', '41'), +('6', '1', '50', '1910', '0', '103', '61', '92', '23', '41'), +('6', '1', '51', '1986', '0', '105', '63', '94', '23', '42'), +('6', '1', '52', '2062', '0', '107', '64', '96', '23', '42'), +('6', '1', '53', '2142', '0', '109', '65', '98', '23', '43'), +('6', '1', '54', '2225', '0', '111', '67', '100', '24', '44'), +('6', '1', '55', '2309', '0', '114', '68', '102', '24', '44'), +('6', '1', '56', '2395', '0', '116', '69', '104', '24', '45'), +('6', '1', '57', '2483', '0', '118', '71', '106', '24', '45'), +('6', '1', '58', '2574', '0', '120', '72', '108', '25', '46'), +('6', '1', '59', '2666', '0', '123', '74', '110', '25', '46'), +('6', '1', '60', '2760', '0', '125', '75', '112', '25', '47'), +('6', '3', '1', '76', '80', '25', '18', '23', '15', '23'), +('6', '3', '2', '97', '86', '25', '19', '24', '16', '24'), +('6', '3', '3', '115', '107', '26', '20', '25', '16', '24'), +('6', '3', '4', '133', '115', '26', '22', '25', '17', '25'), +('6', '3', '5', '151', '138', '27', '23', '26', '17', '25'), +('6', '3', '6', '168', '148', '27', '24', '27', '18', '26'), +('6', '3', '7', '186', '173', '27', '25', '28', '18', '26'), +('6', '3', '8', '204', '185', '28', '26', '29', '19', '27'), +('6', '3', '9', '223', '212', '28', '28', '30', '19', '28'), +('6', '3', '10', '239', '226', '29', '29', '30', '20', '28'), +('6', '3', '11', '257', '255', '29', '30', '31', '20', '29'), +('6', '3', '12', '275', '285', '30', '32', '32', '21', '30'), +('6', '3', '13', '294', '316', '30', '33', '33', '22', '30'), +('6', '3', '14', '312', '348', '31', '34', '34', '22', '31'), +('6', '3', '15', '333', '381', '31', '36', '35', '23', '31'), +('6', '3', '16', '354', '415', '32', '37', '36', '23', '32'), +('6', '3', '17', '375', '450', '32', '38', '37', '24', '33'), +('6', '3', '18', '399', '486', '33', '40', '38', '25', '34'), +('6', '3', '19', '424', '523', '33', '41', '39', '25', '34'), +('6', '3', '20', '448', '561', '34', '43', '40', '26', '35'), +('6', '3', '21', '475', '600', '34', '44', '41', '27', '36'), +('6', '3', '22', '501', '640', '35', '46', '42', '27', '36'), +('6', '3', '23', '530', '681', '35', '47', '43', '28', '37'), +('6', '3', '24', '559', '723', '36', '49', '44', '29', '38'), +('6', '3', '25', '590', '766', '36', '50', '45', '29', '39'), +('6', '3', '26', '622', '810', '37', '52', '46', '30', '39'), +('6', '3', '27', '653', '855', '37', '54', '47', '31', '40'), +('6', '3', '28', '687', '900', '38', '55', '48', '31', '41'), +('6', '3', '29', '722', '945', '38', '57', '49', '32', '42'), +('6', '3', '30', '758', '990', '39', '59', '50', '33', '42'), +('6', '3', '31', '795', '1035', '39', '60', '52', '34', '43'), +('6', '3', '32', '832', '1080', '40', '62', '53', '34', '44'), +('6', '3', '33', '871', '1125', '41', '64', '54', '35', '45'), +('6', '3', '34', '910', '1170', '41', '65', '55', '36', '46'), +('6', '3', '35', '952', '1215', '42', '67', '56', '37', '47'), +('6', '3', '36', '994', '1260', '43', '69', '58', '38', '48'), +('6', '3', '37', '1036', '1305', '43', '71', '59', '38', '48'), +('6', '3', '38', '1082', '1350', '44', '73', '60', '39', '49'), +('6', '3', '39', '1126', '1395', '44', '75', '61', '40', '50'), +('6', '3', '40', '1172', '1440', '45', '76', '63', '41', '51'), +('6', '3', '41', '1221', '1485', '46', '78', '64', '42', '52'), +('6', '3', '42', '1268', '1530', '46', '80', '65', '42', '53'), +('6', '3', '43', '1318', '1575', '47', '82', '66', '43', '54'), +('6', '3', '44', '1368', '1620', '48', '84', '68', '44', '55'), +('6', '3', '45', '1419', '1665', '48', '86', '69', '45', '56'), +('6', '3', '46', '1473', '1710', '49', '88', '71', '46', '57'), +('6', '3', '47', '1525', '1755', '50', '90', '72', '47', '58'), +('6', '3', '48', '1580', '1800', '51', '93', '73', '48', '59'), +('6', '3', '49', '1636', '1845', '51', '95', '75', '49', '60'), +('6', '3', '50', '1692', '1890', '52', '97', '76', '50', '61'), +('6', '3', '51', '1750', '1935', '53', '99', '78', '51', '62'), +('6', '3', '52', '1809', '1980', '54', '101', '79', '52', '63'), +('6', '3', '53', '1869', '2025', '54', '103', '81', '53', '64'), +('6', '3', '54', '1930', '2070', '55', '106', '82', '54', '65'), +('6', '3', '55', '1991', '2115', '56', '108', '84', '55', '66'), +('6', '3', '56', '2054', '2160', '57', '110', '85', '56', '67'), +('6', '3', '57', '2119', '2205', '58', '113', '87', '57', '69'), +('6', '3', '58', '2184', '2250', '58', '115', '89', '58', '70'), +('6', '3', '59', '2250', '2295', '59', '118', '90', '59', '71'), +('6', '3', '60', '2318', '2340', '60', '120', '92', '60', '72'), +('6', '7', '1', '97', '71', '26', '15', '23', '16', '24'), +('6', '7', '2', '98', '78', '27', '15', '24', '17', '25'), +('6', '7', '3', '117', '86', '27', '16', '25', '18', '26'), +('6', '7', '4', '133', '109', '28', '16', '26', '18', '27'), +('6', '7', '5', '152', '119', '29', '17', '26', '19', '28'), +('6', '7', '6', '170', '130', '30', '17', '27', '20', '29'), +('6', '7', '7', '188', '156', '31', '17', '28', '21', '30'), +('6', '7', '8', '205', '183', '31', '18', '29', '22', '30'), +('6', '7', '9', '223', '226', '32', '18', '30', '23', '31'), +('6', '7', '10', '241', '240', '33', '19', '31', '23', '32'), +('6', '7', '11', '259', '270', '34', '19', '32', '24', '33'), +('6', '7', '12', '277', '301', '35', '20', '33', '25', '34'), +('6', '7', '13', '294', '333', '35', '20', '34', '26', '35'), +('6', '7', '14', '312', '366', '36', '21', '35', '27', '36'), +('6', '7', '15', '330', '400', '37', '21', '36', '28', '38'), +('6', '7', '16', '349', '435', '38', '22', '37', '29', '39'), +('6', '7', '17', '367', '471', '39', '22', '38', '30', '40'), +('6', '7', '18', '388', '508', '40', '23', '39', '31', '41'), +('6', '7', '19', '409', '546', '41', '23', '40', '32', '42'), +('6', '7', '20', '430', '585', '42', '24', '41', '33', '43'), +('6', '7', '21', '454', '625', '43', '24', '42', '34', '44'), +('6', '7', '22', '477', '666', '43', '25', '43', '35', '45'), +('6', '7', '23', '503', '708', '44', '25', '44', '36', '46'), +('6', '7', '24', '530', '789', '45', '26', '45', '37', '48'), +('6', '7', '25', '556', '795', '46', '26', '47', '38', '49'), +('6', '7', '26', '585', '840', '47', '27', '48', '39', '50'), +('6', '7', '27', '614', '886', '48', '27', '49', '40', '51'), +('6', '7', '28', '645', '933', '49', '28', '50', '41', '52'), +('6', '7', '29', '677', '981', '50', '28', '51', '42', '54'), +('6', '7', '30', '708', '1030', '51', '29', '52', '43', '55'), +('6', '7', '31', '742', '1149', '53', '29', '54', '45', '56'), +('6', '7', '32', '777', '1201', '54', '30', '55', '46', '58'), +('6', '7', '33', '813', '1250', '55', '31', '56', '47', '59'), +('6', '7', '34', '848', '1290', '56', '31', '57', '48', '60'), +('6', '7', '35', '887', '1339', '57', '32', '59', '49', '62'), +('6', '7', '36', '926', '1339', '58', '33', '60', '51', '63'), +('6', '7', '37', '966', '1458', '59', '33', '61', '52', '64'), +('6', '7', '38', '1007', '1471', '60', '34', '63', '53', '66'), +('6', '7', '39', '1049', '1509', '61', '34', '64', '54', '67'), +('6', '7', '40', '1092', '1612', '63', '35', '65', '56', '69'), +('6', '7', '41', '1137', '1663', '64', '36', '67', '57', '70'), +('6', '7', '42', '1181', '1700', '65', '36', '68', '58', '72'), +('6', '7', '43', '1226', '1751', '66', '37', '70', '59', '73'), +('6', '7', '44', '1275', '1818', '68', '38', '71', '61', '75'), +('6', '7', '45', '1323', '1854', '69', '38', '73', '62', '76'), +('6', '7', '46', '1373', '1921', '70', '39', '74', '64', '78'), +('6', '7', '47', '1423', '1972', '71', '40', '76', '65', '79'), +('6', '7', '48', '1474', '2008', '73', '41', '77', '66', '81'), +('6', '7', '49', '1527', '2075', '74', '41', '79', '68', '83'), +('6', '7', '50', '1579', '2111', '75', '42', '80', '69', '84'), +('6', '7', '51', '1634', '2178', '77', '43', '82', '71', '86'), +('6', '7', '52', '1691', '2230', '78', '44', '83', '72', '88'), +('6', '7', '53', '1747', '2281', '80', '44', '85', '74', '89'), +('6', '7', '54', '1805', '2304', '81', '45', '87', '75', '91'), +('6', '7', '55', '1864', '2333', '82', '46', '88', '77', '93'), +('6', '7', '56', '1923', '2384', '84', '47', '90', '78', '95'), +('6', '7', '57', '1983', '2487', '85', '48', '92', '80', '96'), +('6', '7', '58', '2045', '2538', '87', '48', '93', '82', '98'), +('6', '7', '59', '2109', '2565', '88', '49', '95', '83', '100'), +('6', '7', '60', '2174', '2590', '90', '50', '97', '85', '102'), +('6', '11', '1', '97', '67', '26', '15', '22', '17', '24'), +('6', '11', '2', '97', '75', '27', '15', '23', '18', '25'), +('6', '11', '3', '113', '84', '27', '16', '23', '19', '26'), +('6', '11', '4', '132', '94', '28', '16', '24', '20', '27'), +('6', '11', '5', '150', '119', '28', '17', '24', '21', '28'), +('6', '11', '6', '168', '145', '29', '17', '25', '22', '29'), +('6', '11', '7', '185', '172', '29', '18', '26', '23', '30'), +('6', '11', '8', '203', '185', '30', '18', '26', '23', '31'), +('6', '11', '9', '221', '214', '30', '19', '27', '24', '32'), +('6', '11', '10', '239', '244', '31', '19', '27', '25', '33'), +('6', '11', '11', '257', '275', '31', '20', '28', '26', '35'), +('6', '11', '12', '274', '307', '32', '20', '29', '27', '36'), +('6', '11', '13', '292', '340', '32', '21', '29', '28', '37'), +('6', '11', '14', '310', '374', '33', '21', '30', '29', '38'), +('6', '11', '15', '329', '424', '34', '22', '31', '31', '39'), +('6', '11', '16', '347', '460', '34', '22', '31', '32', '40'), +('6', '11', '17', '365', '497', '35', '23', '32', '33', '42'), +('6', '11', '18', '383', '535', '35', '24', '33', '34', '43'), +('6', '11', '19', '402', '574', '36', '24', '33', '35', '44'), +('6', '11', '20', '425', '614', '37', '25', '34', '36', '45'), +('6', '11', '21', '447', '655', '37', '25', '35', '37', '47'), +('6', '11', '22', '470', '682', '38', '26', '36', '38', '48'), +('6', '11', '23', '494', '725', '39', '27', '36', '39', '49'), +('6', '11', '24', '518', '784', '39', '27', '37', '41', '51'), +('6', '11', '25', '544', '829', '40', '28', '38', '42', '52'), +('6', '11', '26', '573', '874', '41', '28', '39', '43', '53'), +('6', '11', '27', '601', '904', '41', '29', '39', '44', '55'), +('6', '11', '28', '630', '949', '42', '30', '40', '45', '56'), +('6', '11', '29', '659', '1009', '43', '30', '41', '47', '58'), +('6', '11', '30', '691', '1054', '43', '31', '42', '48', '59'), +('6', '11', '31', '723', '1084', '44', '32', '43', '49', '60'), +('6', '11', '32', '757', '1144', '45', '32', '44', '51', '62'), +('6', '11', '33', '793', '1189', '46', '33', '44', '52', '63'), +('6', '11', '34', '827', '1219', '46', '34', '45', '53', '65'), +('6', '11', '35', '864', '1279', '47', '34', '46', '55', '66'), +('6', '11', '36', '903', '1309', '48', '35', '47', '56', '68'), +('6', '11', '37', '941', '1354', '49', '36', '48', '57', '70'), +('6', '11', '38', '982', '1414', '50', '36', '49', '59', '71'), +('6', '11', '39', '1022', '1444', '50', '37', '50', '60', '73'), +('6', '11', '40', '1064', '1504', '51', '38', '51', '62', '74'), +('6', '11', '41', '1108', '1534', '52', '39', '52', '63', '76'), +('6', '11', '42', '1151', '1594', '53', '39', '53', '65', '78'), +('6', '11', '43', '1197', '1624', '54', '40', '54', '66', '79'), +('6', '11', '44', '1243', '1684', '55', '41', '54', '68', '81'), +('6', '11', '45', '1290', '1714', '55', '42', '55', '69', '83'), +('6', '11', '46', '1339', '1774', '56', '43', '56', '71', '85'), +('6', '11', '47', '1388', '1804', '57', '43', '58', '72', '86'), +('6', '11', '48', '1437', '1849', '58', '44', '59', '74', '88'), +('6', '11', '49', '1490', '1909', '59', '45', '60', '76', '90'), +('6', '11', '50', '1542', '1939', '60', '46', '61', '77', '92'), +('6', '11', '51', '1596', '1984', '61', '47', '62', '79', '94'), +('6', '11', '52', '1651', '2044', '62', '48', '63', '81', '96'), +('6', '11', '53', '1706', '2074', '63', '49', '64', '82', '98'), +('6', '11', '54', '1763', '2119', '64', '49', '65', '84', '100'), +('6', '11', '55', '1820', '2164', '65', '50', '66', '86', '102'), +('6', '11', '56', '1879', '2209', '66', '51', '67', '88', '104'), +('6', '11', '57', '1940', '2254', '67', '52', '68', '89', '106'), +('6', '11', '58', '2000', '2299', '68', '53', '70', '91', '108'), +('6', '11', '59', '2063', '2344', '69', '54', '71', '93', '110'), +('6', '11', '60', '2125', '2389', '70', '55', '72', '95', '112'), +('7', '1', '1', '50', '0', '18', '23', '21', '23', '20'), +('7', '1', '2', '69', '0', '19', '24', '22', '24', '20'), +('7', '1', '3', '88', '0', '20', '24', '23', '24', '21'), +('7', '1', '4', '107', '0', '21', '25', '24', '24', '21'), +('7', '1', '5', '126', '0', '23', '26', '25', '24', '21'), +('7', '1', '6', '145', '0', '24', '27', '26', '25', '21'), +('7', '1', '7', '164', '0', '25', '27', '27', '25', '22'), +('7', '1', '8', '183', '0', '26', '28', '28', '25', '22'), +('7', '1', '9', '202', '0', '27', '29', '29', '25', '22'), +('7', '1', '10', '221', '0', '28', '29', '30', '25', '23'), +('7', '1', '11', '240', '0', '30', '30', '32', '25', '23'), +('7', '1', '12', '259', '0', '31', '31', '33', '25', '23'), +('7', '1', '13', '278', '0', '32', '32', '34', '25', '24'), +('7', '1', '14', '298', '0', '34', '33', '35', '26', '24'), +('7', '1', '15', '319', '0', '35', '33', '36', '26', '24'), +('7', '1', '16', '341', '0', '36', '34', '37', '26', '25'), +('7', '1', '17', '364', '0', '37', '35', '39', '26', '25'), +('7', '1', '18', '388', '0', '39', '36', '40', '26', '25'), +('7', '1', '19', '413', '0', '40', '37', '41', '26', '26'), +('7', '1', '20', '439', '0', '42', '38', '42', '26', '26'), +('7', '1', '21', '466', '0', '43', '38', '44', '27', '26'), +('7', '1', '22', '494', '0', '44', '39', '45', '27', '27'), +('7', '1', '23', '523', '0', '46', '40', '46', '27', '27'), +('7', '1', '24', '553', '0', '47', '41', '48', '27', '28'), +('7', '1', '25', '584', '0', '49', '42', '49', '27', '28'), +('7', '1', '26', '616', '0', '50', '43', '50', '27', '28'), +('7', '1', '27', '649', '0', '52', '44', '52', '27', '29'), +('7', '1', '28', '683', '0', '53', '45', '53', '28', '29'), +('7', '1', '29', '718', '0', '55', '46', '55', '28', '30'), +('7', '1', '30', '754', '0', '57', '47', '56', '28', '30'), +('7', '1', '31', '791', '0', '58', '48', '57', '28', '30'), +('7', '1', '32', '829', '0', '60', '49', '59', '28', '31'), +('7', '1', '33', '868', '0', '61', '50', '60', '28', '31'), +('7', '1', '34', '908', '0', '63', '51', '62', '29', '32'), +('7', '1', '35', '949', '0', '65', '52', '63', '29', '32'), +('7', '1', '36', '991', '0', '67', '53', '65', '29', '33'), +('7', '1', '37', '1070', '0', '68', '54', '67', '29', '33'), +('7', '1', '38', '1081', '0', '70', '55', '68', '29', '33'), +('7', '1', '39', '1129', '0', '72', '56', '70', '30', '34'), +('7', '1', '40', '1179', '0', '74', '57', '71', '30', '34'), +('7', '1', '41', '1231', '0', '75', '59', '73', '30', '35'), +('7', '1', '42', '1285', '0', '77', '60', '75', '30', '35'), +('7', '1', '43', '1341', '0', '79', '61', '76', '30', '36'), +('7', '1', '44', '1399', '0', '81', '62', '78', '30', '36'), +('7', '1', '45', '1459', '0', '83', '63', '80', '32', '37'), +('7', '1', '46', '1521', '0', '85', '64', '82', '32', '37'), +('7', '1', '47', '1585', '0', '87', '66', '83', '32', '38'), +('7', '1', '48', '1651', '0', '89', '67', '85', '32', '38'), +('7', '1', '49', '1719', '0', '91', '68', '87', '33', '39'), +('7', '1', '50', '1789', '0', '93', '69', '89', '33', '39'), +('7', '1', '51', '1861', '0', '95', '71', '91', '33', '40'), +('7', '1', '52', '1935', '0', '97', '72', '93', '33', '40'), +('7', '1', '53', '2011', '0', '99', '73', '95', '33', '41'), +('7', '1', '54', '2089', '0', '101', '75', '97', '34', '42'), +('7', '1', '55', '2169', '0', '104', '76', '99', '34', '42'), +('7', '1', '56', '2251', '0', '106', '77', '101', '34', '43'), +('7', '1', '57', '2335', '0', '108', '79', '103', '34', '43'), +('7', '1', '58', '2421', '0', '110', '80', '105', '35', '44'), +('7', '1', '59', '2509', '0', '113', '82', '107', '35', '44'), +('7', '1', '60', '2599', '0', '115', '83', '109', '35', '45'), +('7', '4', '1', '45', '0', '16', '26', '20', '23', '20'), +('7', '4', '2', '62', '0', '17', '27', '21', '24', '20'), +('7', '4', '3', '79', '0', '17', '28', '21', '24', '21'), +('7', '4', '4', '96', '0', '18', '30', '22', '25', '21'), +('7', '4', '5', '113', '0', '19', '31', '23', '25', '21'), +('7', '4', '6', '130', '0', '19', '32', '23', '25', '22'), +('7', '4', '7', '147', '0', '20', '34', '24', '25', '22'), +('7', '4', '8', '164', '0', '21', '35', '24', '25', '22'), +('7', '4', '9', '181', '0', '22', '36', '25', '25', '23'), +('7', '4', '10', '198', '0', '22', '38', '26', '26', '23'), +('7', '4', '11', '215', '0', '23', '39', '27', '26', '24'), +('7', '4', '12', '232', '0', '24', '40', '27', '26', '24'), +('7', '4', '13', '249', '0', '25', '42', '28', '26', '24'), +('7', '4', '14', '266', '0', '25', '43', '29', '26', '25'), +('7', '4', '15', '283', '0', '26', '45', '29', '27', '25'), +('7', '4', '16', '301', '0', '27', '46', '30', '27', '26'), +('7', '4', '17', '320', '0', '28', '47', '31', '27', '26'), +('7', '4', '18', '340', '0', '29', '49', '32', '27', '26'), +('7', '4', '19', '361', '0', '30', '51', '32', '27', '27'), +('7', '4', '20', '383', '0', '30', '52', '33', '28', '27'), +('7', '4', '21', '406', '0', '31', '54', '34', '28', '28'), +('7', '4', '22', '430', '0', '32', '55', '35', '28', '28'), +('7', '4', '23', '455', '0', '33', '57', '36', '28', '29'), +('7', '4', '24', '481', '0', '34', '58', '36', '29', '29'), +('7', '4', '25', '508', '0', '35', '60', '37', '29', '30'), +('7', '4', '26', '536', '0', '36', '62', '38', '29', '30'), +('7', '4', '27', '565', '0', '37', '63', '39', '29', '30'), +('7', '4', '28', '595', '0', '38', '65', '40', '29', '31'), +('7', '4', '29', '626', '0', '38', '67', '41', '30', '31'), +('7', '4', '30', '658', '0', '39', '69', '41', '30', '32'), +('7', '4', '31', '691', '0', '40', '70', '42', '30', '32'), +('7', '4', '32', '725', '0', '41', '72', '43', '30', '33'), +('7', '4', '33', '760', '0', '42', '74', '44', '32', '33'), +('7', '4', '34', '796', '0', '43', '76', '45', '32', '34'), +('7', '4', '35', '833', '0', '44', '78', '46', '32', '34'), +('7', '4', '36', '871', '0', '46', '80', '47', '33', '35'), +('7', '4', '37', '910', '0', '47', '81', '48', '33', '36'), +('7', '4', '38', '950', '0', '48', '83', '49', '33', '36'), +('7', '4', '39', '991', '0', '49', '85', '50', '33', '37'), +('7', '4', '40', '1033', '0', '50', '87', '51', '34', '37'), +('7', '4', '41', '1076', '0', '51', '89', '52', '34', '38'), +('7', '4', '42', '1120', '0', '52', '91', '53', '34', '38'), +('7', '4', '43', '1165', '0', '53', '93', '54', '34', '39'), +('7', '4', '44', '1211', '0', '54', '96', '55', '35', '39'), +('7', '4', '45', '1258', '0', '56', '98', '56', '35', '40'), +('7', '4', '46', '1306', '0', '57', '100', '57', '35', '41'), +('7', '4', '47', '1355', '0', '58', '102', '58', '36', '41'), +('7', '4', '48', '1405', '0', '59', '104', '59', '36', '42'), +('7', '4', '49', '1456', '0', '60', '106', '61', '36', '43'), +('7', '4', '50', '1508', '0', '62', '109', '62', '37', '43'), +('7', '4', '51', '1561', '0', '63', '111', '63', '37', '44'), +('7', '4', '52', '1615', '0', '64', '113', '64', '37', '44'), +('7', '4', '53', '1670', '0', '65', '116', '65', '38', '45'), +('7', '4', '54', '1726', '0', '67', '118', '66', '38', '46'), +('7', '4', '55', '1783', '0', '68', '120', '68', '38', '46'), +('7', '4', '56', '1841', '0', '69', '123', '69', '39', '47'), +('7', '4', '57', '1900', '0', '71', '125', '70', '39', '48'), +('7', '4', '58', '1960', '0', '72', '128', '71', '39', '49'), +('7', '4', '59', '2021', '0', '74', '130', '73', '40', '49'), +('7', '4', '60', '2083', '0', '75', '133', '74', '40', '50'), +('7', '8', '1', '51', '119', '15', '23', '19', '26', '22'), +('7', '8', '2', '66', '280', '15', '23', '19', '28', '23'), +('7', '8', '3', '72', '306', '15', '23', '20', '29', '24'), +('7', '8', '4', '87', '333', '15', '24', '20', '32', '25'), +('7', '8', '5', '102', '391', '15', '24', '20', '33', '27'), +('7', '8', '6', '117', '420', '16', '24', '20', '34', '28'), +('7', '8', '7', '132', '450', '16', '24', '21', '35', '29'), +('7', '8', '8', '147', '466', '16', '24', '21', '36', '30'), +('7', '8', '9', '162', '513', '16', '24', '21', '38', '31'), +('7', '8', '10', '177', '546', '16', '25', '22', '39', '33'), +('7', '8', '11', '192', '580', '16', '25', '22', '40', '34'), +('7', '8', '12', '207', '615', '16', '25', '22', '42', '35'), +('7', '8', '13', '222', '636', '16', '25', '23', '43', '36'), +('7', '8', '14', '237', '673', '17', '25', '23', '44', '38'), +('7', '8', '15', '252', '711', '17', '26', '23', '46', '39'), +('7', '8', '16', '267', '750', '17', '26', '24', '47', '40'), +('7', '8', '17', '282', '775', '17', '26', '24', '48', '42'), +('7', '8', '18', '297', '831', '17', '26', '24', '50', '43'), +('7', '8', '19', '312', '858', '17', '26', '25', '51', '44'), +('7', '8', '20', '327', '946', '17', '27', '25', '54', '46'), +('7', '8', '21', '342', '975', '18', '27', '25', '55', '47'), +('7', '8', '22', '357', '1035', '18', '27', '26', '57', '49'), +('7', '8', '23', '372', '1066', '18', '27', '26', '58', '50'), +('7', '8', '24', '388', '1128', '18', '28', '27', '60', '52'), +('7', '8', '25', '405', '1161', '18', '28', '27', '61', '53'), +('7', '8', '26', '423', '1225', '18', '28', '27', '63', '55'), +('7', '8', '27', '442', '1260', '18', '28', '28', '65', '56'), +('7', '8', '28', '462', '1296', '19', '28', '28', '66', '58'), +('7', '8', '29', '483', '1362', '19', '29', '29', '68', '59'), +('7', '8', '30', '505', '1413', '19', '29', '29', '70', '61'), +('7', '8', '31', '528', '1449', '19', '29', '29', '71', '63'), +('7', '8', '32', '552', '1515', '19', '29', '30', '74', '64'), +('7', '8', '33', '577', '1596', '19', '30', '30', '76', '66'), +('7', '8', '34', '603', '1632', '20', '30', '31', '77', '68'), +('7', '8', '35', '630', '1683', '20', '30', '31', '79', '69'), +('7', '8', '36', '658', '1734', '20', '31', '32', '81', '71'), +('7', '8', '37', '687', '1800', '20', '31', '32', '83', '73'), +('7', '8', '38', '717', '1836', '20', '31', '32', '85', '75'), +('7', '8', '39', '748', '1887', '21', '31', '33', '87', '76'), +('7', '8', '40', '780', '1923', '21', '32', '33', '88', '78'), +('7', '8', '41', '813', '1974', '21', '32', '34', '90', '80'), +('7', '8', '42', '847', '2025', '21', '32', '34', '92', '82'), +('7', '8', '43', '882', '2076', '21', '32', '35', '95', '84'), +('7', '8', '44', '918', '2157', '21', '33', '35', '97', '86'), +('7', '8', '45', '955', '2208', '22', '33', '36', '99', '88'), +('7', '8', '46', '993', '2259', '22', '33', '36', '101', '90'), +('7', '8', '47', '1032', '2310', '22', '34', '37', '103', '92'), +('7', '8', '48', '1072', '2361', '22', '34', '37', '106', '94'), +('7', '8', '49', '1113', '2412', '23', '34', '38', '108', '96'), +('7', '8', '50', '1155', '2448', '23', '35', '38', '110', '98'), +('7', '8', '51', '1198', '2499', '23', '35', '39', '112', '100'), +('7', '8', '52', '1242', '2550', '23', '35', '39', '114', '102'), +('7', '8', '53', '1287', '2631', '23', '36', '40', '117', '104'), +('7', '8', '54', '1333', '2682', '24', '36', '41', '120', '106'), +('7', '8', '55', '1380', '2733', '24', '36', '41', '122', '109'), +('7', '8', '56', '1428', '2784', '24', '37', '42', '124', '111'), +('7', '8', '57', '1477', '2820', '24', '37', '42', '127', '113'), +('7', '8', '58', '1527', '2871', '25', '37', '43', '129', '115'), +('7', '8', '59', '1578', '2922', '25', '38', '43', '132', '118'), +('7', '8', '60', '1630', '2973', '25', '38', '44', '133', '120'), +('7', '9', '1', '43', '109', '15', '23', '20', '25', '22'), +('7', '9', '2', '58', '223', '15', '23', '21', '27', '23'), +('7', '9', '3', '73', '247', '16', '24', '21', '28', '24'), +('7', '9', '4', '88', '272', '16', '24', '22', '29', '25'), +('7', '9', '5', '103', '298', '16', '24', '22', '30', '26'), +('7', '9', '6', '118', '325', '16', '25', '23', '32', '27'), +('7', '9', '7', '133', '383', '17', '25', '23', '33', '29'), +('7', '9', '8', '148', '412', '17', '25', '24', '34', '30'), +('7', '9', '9', '163', '442', '17', '26', '24', '35', '31'), +('7', '9', '10', '178', '473', '18', '26', '25', '36', '32'), +('7', '9', '11', '193', '505', '18', '27', '25', '38', '33'), +('7', '9', '12', '208', '538', '18', '27', '26', '39', '34'), +('7', '9', '13', '223', '572', '19', '27', '26', '40', '36'), +('7', '9', '14', '238', '607', '19', '28', '27', '41', '37'), +('7', '9', '15', '253', '643', '19', '28', '28', '42', '38'), +('7', '9', '16', '268', '665', '20', '29', '28', '43', '39'), +('7', '9', '17', '283', '703', '20', '29', '29', '45', '41'), +('7', '9', '18', '299', '742', '20', '29', '29', '46', '42'), +('7', '9', '19', '316', '782', '21', '30', '30', '47', '43'), +('7', '9', '20', '334', '823', '21', '30', '31', '48', '45'), +('7', '9', '21', '353', '865', '21', '31', '31', '50', '46'), +('7', '9', '22', '373', '908', '22', '31', '32', '51', '47'), +('7', '9', '23', '394', '952', '22', '32', '33', '53', '49'), +('7', '9', '24', '416', '1027', '23', '32', '33', '55', '50'), +('7', '9', '25', '439', '1073', '23', '33', '34', '56', '52'), +('7', '9', '26', '463', '1120', '23', '33', '35', '57', '53'), +('7', '9', '27', '488', '1168', '24', '33', '35', '59', '54'), +('7', '9', '28', '514', '1217', '24', '34', '36', '60', '56'), +('7', '9', '29', '541', '1267', '25', '34', '37', '62', '57'), +('7', '9', '30', '569', '1318', '25', '35', '37', '63', '59'), +('7', '9', '31', '588', '1354', '25', '35', '37', '64', '62'), +('7', '9', '32', '628', '1405', '26', '36', '39', '66', '62'), +('7', '9', '33', '659', '1456', '26', '36', '40', '67', '64'), +('7', '9', '34', '691', '1507', '27', '37', '40', '69', '65'), +('7', '9', '35', '724', '1558', '27', '37', '41', '70', '67'), +('7', '9', '36', '758', '1609', '28', '38', '42', '72', '69'), +('7', '9', '37', '793', '1690', '28', '39', '43', '75', '69'), +('7', '9', '38', '829', '1741', '28', '39', '44', '76', '72'), +('7', '9', '39', '866', '1792', '29', '40', '44', '78', '74'), +('7', '9', '40', '904', '1843', '29', '40', '45', '79', '75'), +('7', '9', '41', '943', '1894', '30', '41', '46', '81', '77'), +('7', '9', '42', '983', '1945', '30', '41', '47', '83', '79'), +('7', '9', '43', '1024', '1996', '31', '42', '48', '84', '81'), +('7', '9', '44', '1066', '2032', '31', '42', '49', '86', '82'), +('7', '9', '45', '1109', '2083', '32', '43', '49', '88', '84'), +('7', '9', '46', '1153', '2134', '32', '44', '50', '90', '86'), +('7', '9', '47', '1198', '2185', '33', '44', '51', '91', '88'), +('7', '9', '48', '1234', '2236', '33', '45', '52', '93', '90'), +('7', '9', '49', '1281', '2317', '34', '46', '53', '96', '92'), +('7', '9', '50', '1339', '2368', '34', '46', '54', '98', '93'), +('7', '9', '51', '1388', '2419', '35', '47', '55', '100', '96'), +('7', '9', '52', '1418', '2470', '35', '47', '56', '102', '98'), +('7', '9', '53', '1489', '2521', '36', '48', '57', '104', '100'), +('7', '9', '54', '1541', '2557', '37', '49', '58', '106', '102'), +('7', '9', '55', '1584', '2608', '37', '49', '58', '108', '104'), +('7', '9', '56', '1648', '2659', '38', '50', '60', '110', '106'), +('7', '9', '57', '1683', '2710', '38', '51', '61', '112', '108'), +('7', '9', '58', '1759', '2761', '39', '52', '62', '114', '111'), +('7', '9', '59', '1816', '2842', '39', '52', '63', '117', '111'), +('7', '9', '60', '1874', '2893', '40', '53', '64', '119', '115'), +('8', '1', '1', '70', '0', '24', '22', '23', '16', '21'), +('8', '1', '2', '89', '0', '25', '23', '24', '16', '21'), +('8', '1', '3', '108', '0', '26', '23', '25', '16', '22'), +('8', '1', '4', '127', '0', '27', '24', '26', '16', '22'), +('8', '1', '5', '146', '0', '29', '25', '27', '16', '22'), +('8', '1', '6', '165', '0', '30', '26', '28', '17', '22'), +('8', '1', '7', '184', '0', '31', '26', '29', '17', '23'), +('8', '1', '8', '203', '0', '32', '27', '30', '17', '23'), +('8', '1', '9', '222', '0', '33', '28', '31', '17', '23'), +('8', '1', '10', '241', '0', '34', '28', '32', '17', '24'), +('8', '1', '11', '260', '0', '36', '29', '34', '17', '24'), +('8', '1', '12', '279', '0', '37', '30', '35', '17', '24'), +('8', '1', '13', '298', '0', '38', '31', '36', '17', '25'), +('8', '1', '14', '318', '0', '40', '32', '37', '18', '25'), +('8', '1', '15', '339', '0', '41', '32', '38', '18', '25'), +('8', '1', '16', '361', '0', '42', '33', '39', '18', '26'), +('8', '1', '17', '384', '0', '43', '34', '41', '18', '26'), +('8', '1', '18', '408', '0', '45', '35', '42', '18', '26'), +('8', '1', '19', '433', '0', '46', '36', '43', '18', '27'), +('8', '1', '20', '459', '0', '48', '37', '44', '18', '27'), +('8', '1', '21', '486', '0', '49', '37', '46', '19', '27'), +('8', '1', '22', '514', '0', '50', '38', '47', '19', '28'), +('8', '1', '23', '543', '0', '52', '39', '48', '19', '28'), +('8', '1', '24', '573', '0', '53', '40', '50', '19', '29'), +('8', '1', '25', '604', '0', '55', '41', '51', '19', '29'), +('8', '1', '26', '636', '0', '56', '42', '52', '19', '29'), +('8', '1', '27', '669', '0', '58', '43', '54', '19', '30'), +('8', '1', '28', '703', '0', '59', '44', '55', '20', '30'), +('8', '1', '29', '738', '0', '61', '45', '57', '20', '31'), +('8', '1', '30', '774', '0', '63', '46', '58', '20', '31'), +('8', '1', '31', '811', '0', '64', '47', '59', '20', '31'), +('8', '1', '32', '849', '0', '66', '48', '61', '20', '32'), +('8', '1', '33', '888', '0', '67', '49', '62', '20', '32'), +('8', '1', '34', '928', '0', '69', '50', '64', '21', '33'), +('8', '1', '35', '969', '0', '71', '51', '65', '21', '33'), +('8', '1', '36', '1011', '0', '73', '52', '67', '21', '34'), +('8', '1', '37', '1055', '0', '74', '53', '69', '21', '34'), +('8', '1', '38', '1101', '0', '76', '54', '70', '21', '34'), +('8', '1', '39', '1149', '0', '78', '55', '72', '22', '35'), +('8', '1', '40', '1199', '0', '80', '56', '73', '22', '35'), +('8', '1', '41', '1251', '0', '81', '58', '75', '22', '36'), +('8', '1', '42', '1310', '0', '83', '59', '77', '22', '36'), +('8', '1', '43', '1361', '0', '85', '60', '78', '22', '37'), +('8', '1', '44', '1419', '0', '87', '61', '80', '22', '37'), +('8', '1', '45', '1529', '0', '89', '62', '82', '23', '38'), +('8', '1', '46', '1541', '0', '91', '63', '84', '23', '38'), +('8', '1', '47', '1605', '0', '93', '65', '85', '23', '39'), +('8', '1', '48', '1671', '0', '95', '66', '87', '23', '39'), +('8', '1', '49', '1739', '0', '97', '67', '89', '24', '40'), +('8', '1', '50', '1809', '0', '99', '68', '91', '24', '40'), +('8', '1', '51', '1881', '0', '101', '70', '93', '24', '41'), +('8', '1', '52', '1955', '0', '103', '71', '95', '24', '41'), +('8', '1', '53', '2031', '0', '105', '72', '97', '24', '42'), +('8', '1', '54', '2109', '0', '107', '74', '99', '25', '43'), +('8', '1', '55', '2189', '0', '110', '75', '101', '25', '43'), +('8', '1', '56', '2271', '0', '112', '76', '103', '25', '44'), +('8', '1', '57', '2355', '0', '114', '78', '105', '25', '44'), +('8', '1', '58', '2441', '0', '116', '79', '107', '26', '45'), +('8', '1', '59', '2529', '0', '119', '81', '109', '26', '45'), +('8', '1', '60', '2619', '0', '121', '82', '111', '26', '46'), +('8', '3', '1', '66', '80', '21', '25', '22', '16', '22'), +('8', '3', '2', '83', '87', '21', '26', '23', '17', '23'), +('8', '3', '3', '100', '108', '22', '27', '24', '17', '23'), +('8', '3', '4', '117', '116', '22', '29', '24', '18', '24'), +('8', '3', '5', '134', '139', '23', '30', '25', '18', '24'), +('8', '3', '6', '151', '149', '23', '31', '26', '19', '25'), +('8', '3', '7', '168', '174', '23', '32', '27', '19', '25'), +('8', '3', '8', '185', '186', '24', '33', '28', '20', '26'), +('8', '3', '9', '202', '213', '24', '35', '29', '20', '27'), +('8', '3', '10', '219', '241', '25', '36', '29', '21', '27'), +('8', '3', '11', '236', '270', '25', '37', '30', '21', '28'), +('8', '3', '12', '253', '300', '26', '39', '31', '22', '29'), +('8', '3', '13', '270', '331', '26', '40', '32', '23', '29'), +('8', '3', '14', '288', '363', '27', '41', '33', '23', '30'), +('8', '3', '15', '307', '396', '27', '43', '34', '24', '30'), +('8', '3', '16', '327', '430', '28', '44', '35', '24', '31'), +('8', '3', '17', '348', '465', '28', '45', '36', '25', '32'), +('8', '3', '18', '370', '501', '29', '47', '37', '26', '33'), +('8', '3', '19', '393', '538', '29', '48', '38', '26', '33'), +('8', '3', '20', '417', '576', '30', '50', '39', '27', '34'), +('8', '3', '21', '442', '615', '30', '51', '40', '28', '35'), +('8', '3', '22', '468', '655', '31', '53', '41', '28', '35'), +('8', '3', '23', '495', '696', '31', '54', '42', '29', '36'), +('8', '3', '24', '523', '738', '32', '56', '43', '30', '37'), +('8', '3', '25', '552', '781', '32', '57', '44', '30', '38'), +('8', '3', '26', '582', '825', '33', '59', '45', '31', '38'), +('8', '3', '27', '613', '870', '33', '61', '46', '32', '39'), +('8', '3', '28', '645', '915', '34', '62', '47', '32', '40'), +('8', '3', '29', '678', '960', '34', '64', '48', '33', '41'), +('8', '3', '30', '712', '1005', '35', '66', '49', '34', '41'), +('8', '3', '31', '747', '1050', '35', '67', '51', '35', '42'), +('8', '3', '32', '783', '1095', '36', '69', '52', '35', '43'), +('8', '3', '33', '820', '1140', '37', '71', '53', '36', '44'), +('8', '3', '34', '858', '1185', '37', '72', '54', '37', '45'), +('8', '3', '35', '897', '1230', '38', '74', '55', '38', '46'), +('8', '3', '36', '937', '1275', '39', '76', '57', '39', '47'), +('8', '3', '37', '978', '1320', '39', '78', '58', '39', '47'), +('8', '3', '38', '1020', '1365', '40', '80', '59', '40', '48'), +('8', '3', '39', '1063', '1410', '40', '82', '60', '41', '49'), +('8', '3', '40', '1107', '1455', '41', '83', '62', '42', '50'), +('8', '3', '41', '1152', '1500', '42', '85', '63', '43', '51'), +('8', '3', '42', '1198', '1545', '42', '87', '64', '43', '52'), +('8', '3', '43', '1245', '1590', '43', '89', '65', '44', '53'), +('8', '3', '44', '1293', '1635', '44', '91', '67', '45', '54'), +('8', '3', '45', '1342', '1680', '44', '93', '68', '46', '55'), +('8', '3', '46', '1392', '1725', '45', '95', '70', '47', '56'), +('8', '3', '47', '1443', '1770', '46', '97', '71', '48', '57'), +('8', '3', '48', '1495', '1815', '47', '100', '72', '49', '58'), +('8', '3', '49', '1548', '1860', '47', '102', '74', '50', '59'), +('8', '3', '50', '1602', '1905', '48', '104', '75', '51', '60'), +('8', '3', '51', '1657', '1950', '49', '106', '77', '52', '61'), +('8', '3', '52', '1713', '1995', '50', '108', '78', '53', '62'), +('8', '3', '53', '1770', '2040', '50', '110', '80', '54', '63'), +('8', '3', '54', '1828', '2085', '51', '113', '81', '55', '64'), +('8', '3', '55', '1887', '2130', '52', '115', '83', '56', '65'), +('8', '3', '56', '1947', '2175', '53', '117', '84', '57', '66'), +('8', '3', '57', '2008', '2220', '54', '120', '86', '58', '68'), +('8', '3', '58', '2070', '2265', '54', '122', '88', '59', '69'), +('8', '3', '59', '2133', '2310', '55', '125', '89', '60', '70'), +('8', '3', '60', '2197', '2355', '56', '127', '91', '61', '71'), +('8', '4', '1', '65', '0', '22', '25', '22', '16', '21'), +('8', '4', '2', '82', '0', '23', '26', '23', '16', '21'), +('8', '4', '3', '99', '0', '23', '27', '23', '16', '22'), +('8', '4', '4', '116', '0', '24', '29', '24', '17', '22'), +('8', '4', '5', '133', '0', '25', '30', '25', '17', '22'), +('8', '4', '6', '150', '0', '25', '31', '25', '17', '23'), +('8', '4', '7', '167', '0', '26', '33', '26', '17', '23'), +('8', '4', '8', '184', '0', '27', '34', '26', '17', '23'), +('8', '4', '9', '201', '0', '28', '35', '27', '17', '24'), +('8', '4', '10', '218', '0', '28', '37', '28', '18', '24'), +('8', '4', '11', '235', '0', '29', '38', '29', '18', '25'), +('8', '4', '12', '252', '0', '30', '39', '29', '18', '25'), +('8', '4', '13', '269', '0', '31', '41', '30', '18', '25'), +('8', '4', '14', '286', '0', '31', '42', '31', '18', '26'), +('8', '4', '15', '303', '0', '32', '44', '31', '19', '26'), +('8', '4', '16', '321', '0', '33', '45', '32', '19', '27'), +('8', '4', '17', '340', '0', '34', '46', '33', '19', '27'), +('8', '4', '18', '360', '0', '35', '48', '34', '19', '27'), +('8', '4', '19', '381', '0', '36', '50', '34', '19', '28'), +('8', '4', '20', '403', '0', '36', '51', '35', '20', '28'), +('8', '4', '21', '426', '0', '37', '53', '36', '20', '29'), +('8', '4', '22', '450', '0', '38', '54', '37', '20', '29'), +('8', '4', '23', '475', '0', '39', '56', '38', '20', '30'), +('8', '4', '24', '501', '0', '40', '57', '38', '21', '30'), +('8', '4', '25', '528', '0', '41', '59', '39', '21', '31'), +('8', '4', '26', '556', '0', '42', '61', '40', '21', '31'), +('8', '4', '27', '585', '0', '43', '62', '41', '21', '31'), +('8', '4', '28', '615', '0', '44', '64', '42', '21', '32'), +('8', '4', '29', '646', '0', '44', '66', '43', '22', '32'), +('8', '4', '30', '678', '0', '45', '68', '43', '22', '33'), +('8', '4', '31', '711', '0', '46', '69', '44', '22', '33'), +('8', '4', '32', '745', '0', '47', '71', '45', '22', '34'), +('8', '4', '33', '780', '0', '48', '73', '46', '23', '34'), +('8', '4', '34', '816', '0', '49', '75', '47', '23', '35'), +('8', '4', '35', '853', '0', '50', '77', '48', '23', '35'), +('8', '4', '36', '891', '0', '52', '79', '49', '24', '36'), +('8', '4', '37', '930', '0', '53', '80', '50', '24', '37'), +('8', '4', '38', '970', '0', '54', '82', '51', '24', '37'), +('8', '4', '39', '1011', '0', '55', '84', '52', '24', '38'), +('8', '4', '40', '1053', '0', '56', '86', '53', '25', '38'), +('8', '4', '41', '1096', '0', '57', '88', '54', '25', '39'), +('8', '4', '42', '1140', '0', '58', '90', '55', '25', '39'), +('8', '4', '43', '1185', '0', '59', '92', '56', '25', '40'), +('8', '4', '44', '1231', '0', '60', '95', '57', '26', '40'), +('8', '4', '45', '1278', '0', '62', '97', '58', '26', '41'), +('8', '4', '46', '1326', '0', '63', '99', '59', '26', '42'), +('8', '4', '47', '1375', '0', '64', '101', '60', '27', '42'), +('8', '4', '48', '1425', '0', '65', '103', '61', '27', '43'), +('8', '4', '49', '1476', '0', '66', '105', '63', '27', '44'), +('8', '4', '50', '1528', '0', '68', '108', '64', '28', '44'), +('8', '4', '51', '1581', '0', '69', '110', '65', '28', '45'), +('8', '4', '52', '1635', '0', '70', '112', '66', '28', '45'), +('8', '4', '53', '1690', '0', '71', '115', '67', '29', '46'), +('8', '4', '54', '1746', '0', '73', '117', '68', '29', '47'), +('8', '4', '55', '1803', '0', '74', '119', '70', '29', '47'), +('8', '4', '56', '1861', '0', '75', '122', '71', '30', '48'), +('8', '4', '57', '1920', '0', '77', '124', '72', '30', '49'), +('8', '4', '58', '1980', '0', '78', '127', '73', '30', '50'), +('8', '4', '59', '2041', '0', '80', '129', '75', '31', '50'), +('8', '4', '60', '2103', '0', '81', '132', '76', '31', '51'), +('8', '5', '1', '71', '128', '21', '22', '21', '18', '24'), +('8', '5', '2', '77', '138', '21', '22', '21', '19', '25'), +('8', '5', '3', '92', '149', '21', '22', '22', '20', '26'), +('8', '5', '4', '107', '175', '22', '23', '22', '21', '28'), +('8', '5', '5', '122', '202', '22', '23', '22', '23', '29'), +('8', '5', '6', '137', '230', '22', '23', '23', '24', '30'), +('8', '5', '7', '152', '259', '22', '23', '23', '25', '31'), +('8', '5', '8', '167', '289', '22', '24', '23', '26', '32'), +('8', '5', '9', '182', '320', '22', '24', '24', '27', '34'), +('8', '5', '10', '197', '367', '23', '24', '24', '29', '35'), +('8', '5', '11', '212', '385', '23', '24', '25', '30', '36'), +('8', '5', '12', '227', '419', '23', '25', '25', '31', '38'), +('8', '5', '13', '242', '454', '23', '25', '25', '32', '39'), +('8', '5', '14', '257', '490', '23', '25', '26', '34', '40'), +('8', '5', '15', '272', '527', '24', '25', '26', '35', '42'), +('8', '5', '16', '287', '565', '24', '26', '27', '36', '43'), +('8', '5', '17', '302', '619', '24', '26', '27', '38', '44'), +('8', '5', '18', '317', '644', '24', '26', '27', '39', '46'), +('8', '5', '19', '332', '685', '24', '27', '28', '40', '47'), +('8', '5', '20', '347', '727', '25', '27', '28', '42', '49'), +('8', '5', '21', '362', '770', '25', '27', '29', '43', '50'), +('8', '5', '22', '378', '829', '25', '27', '29', '45', '52'), +('8', '5', '23', '395', '859', '25', '28', '30', '46', '53'), +('8', '5', '24', '413', '920', '26', '28', '30', '48', '55'), +('8', '5', '25', '432', '952', '26', '28', '31', '49', '56'), +('8', '5', '26', '452', '1015', '26', '29', '31', '51', '58'), +('8', '5', '27', '473', '1049', '26', '29', '31', '52', '60'), +('8', '5', '28', '495', '1114', '26', '29', '32', '54', '61'), +('8', '5', '29', '518', '1150', '27', '30', '32', '55', '63'), +('8', '5', '30', '542', '1202', '27', '30', '33', '57', '65'), +('8', '5', '31', '567', '1270', '27', '30', '33', '59', '66'), +('8', '5', '32', '593', '1309', '27', '31', '34', '60', '68'), +('8', '5', '33', '620', '1378', '28', '31', '34', '62', '70'), +('8', '5', '34', '648', '1432', '28', '31', '35', '64', '71'), +('8', '5', '35', '677', '1471', '28', '32', '35', '65', '73'), +('8', '5', '36', '707', '1525', '29', '32', '36', '67', '75'), +('8', '5', '37', '738', '1594', '29', '32', '37', '69', '77'), +('8', '5', '38', '770', '1648', '29', '33', '37', '71', '79'), +('8', '5', '39', '803', '1687', '29', '33', '38', '72', '81'), +('8', '5', '40', '837', '1741', '30', '33', '38', '74', '82'), +('8', '5', '41', '872', '1810', '30', '34', '39', '76', '84'), +('8', '5', '42', '908', '1864', '30', '34', '39', '78', '86'), +('8', '5', '43', '945', '1918', '30', '35', '40', '80', '88'), +('8', '5', '44', '983', '1972', '31', '35', '40', '82', '90'), +('8', '5', '45', '1022', '2026', '31', '35', '41', '84', '92'), +('8', '5', '46', '1062', '2080', '31', '36', '42', '86', '94'), +('8', '5', '47', '1103', '2134', '32', '36', '42', '88', '96'), +('8', '5', '48', '1145', '2188', '32', '37', '43', '90', '99'), +('8', '5', '49', '1238', '2242', '32', '37', '44', '92', '101'), +('8', '5', '50', '1252', '2296', '33', '37', '44', '94', '103'), +('8', '5', '51', '1277', '2350', '33', '38', '45', '96', '105'), +('8', '5', '52', '1323', '2404', '33', '38', '45', '98', '107'), +('8', '5', '53', '1370', '2458', '34', '39', '46', '100', '109'), +('8', '5', '54', '1418', '2512', '34', '39', '47', '102', '112'), +('8', '5', '55', '1467', '2566', '34', '40', '47', '105', '114'), +('8', '5', '56', '1517', '2620', '35', '40', '48', '107', '116'), +('8', '5', '57', '1568', '2674', '35', '41', '49', '109', '119'), +('8', '5', '58', '1620', '2728', '35', '41', '50', '111', '121'), +('8', '5', '59', '1673', '2782', '36', '42', '50', '114', '124'), +('8', '5', '60', '1727', '2836', '36', '42', '51', '116', '126'), +('8', '7', '1', '87', '71', '22', '22', '22', '17', '23'), +('8', '7', '2', '84', '79', '23', '22', '23', '18', '24'), +('8', '7', '3', '101', '87', '23', '23', '24', '19', '25'), +('8', '7', '4', '118', '110', '24', '23', '25', '19', '26'), +('8', '7', '5', '135', '120', '25', '24', '25', '20', '27'), +('8', '7', '6', '152', '145', '26', '24', '26', '21', '28'), +('8', '7', '7', '169', '171', '27', '24', '27', '22', '29'), +('8', '7', '8', '186', '198', '27', '25', '28', '23', '29'), +('8', '7', '9', '203', '241', '28', '25', '29', '24', '30'), +('8', '7', '10', '220', '255', '29', '26', '30', '24', '31'), +('8', '7', '11', '237', '285', '30', '26', '31', '25', '32'), +('8', '7', '12', '254', '316', '31', '27', '32', '26', '33'), +('8', '7', '13', '271', '348', '31', '27', '33', '27', '34'), +('8', '7', '14', '288', '381', '32', '28', '34', '28', '35'), +('8', '7', '15', '305', '415', '33', '28', '35', '29', '37'), +('8', '7', '16', '322', '450', '34', '29', '36', '30', '38'), +('8', '7', '17', '340', '486', '35', '29', '37', '31', '39'), +('8', '7', '18', '359', '523', '36', '30', '38', '32', '40'), +('8', '7', '19', '379', '589', '37', '30', '39', '33', '41'), +('8', '7', '20', '400', '600', '38', '31', '40', '34', '42'), +('8', '7', '21', '422', '640', '39', '31', '41', '35', '43'), +('8', '7', '22', '445', '681', '39', '32', '42', '36', '44'), +('8', '7', '23', '469', '723', '40', '32', '43', '37', '45'), +('8', '7', '24', '494', '766', '41', '33', '44', '38', '47'), +('8', '7', '25', '520', '810', '42', '33', '46', '39', '48'), +('8', '7', '26', '547', '898', '43', '34', '47', '40', '49'), +('8', '7', '27', '575', '947', '44', '34', '48', '41', '50'), +('8', '7', '28', '604', '996', '45', '35', '49', '42', '51'), +('8', '7', '29', '634', '996', '46', '35', '50', '43', '53'), +('8', '7', '30', '665', '1045', '47', '36', '51', '44', '54'), +('8', '7', '31', '697', '1165', '49', '36', '53', '46', '55'), +('8', '7', '32', '730', '1216', '50', '37', '54', '47', '57'), +('8', '7', '33', '764', '1277', '51', '38', '55', '48', '58'), +('8', '7', '34', '799', '1304', '52', '38', '56', '49', '59'), +('8', '7', '35', '835', '1355', '53', '39', '58', '50', '61'), +('8', '7', '36', '872', '1412', '54', '40', '59', '52', '62'), +('8', '7', '37', '910', '1473', '55', '40', '60', '53', '63'), +('8', '7', '38', '949', '1525', '56', '41', '62', '54', '65'), +('8', '7', '39', '989', '1561', '57', '41', '63', '55', '66'), +('8', '7', '40', '1030', '1599', '59', '42', '64', '57', '68'), +('8', '7', '41', '1072', '1627', '60', '43', '66', '58', '69'), +('8', '7', '42', '1115', '1683', '61', '43', '67', '59', '71'), +('8', '7', '43', '1159', '1716', '62', '44', '69', '60', '72'), +('8', '7', '44', '1204', '1746', '64', '45', '70', '62', '74'), +('8', '7', '45', '1250', '1780', '65', '45', '72', '63', '75'), +('8', '7', '46', '1297', '1844', '66', '46', '73', '65', '77'), +('8', '7', '47', '1345', '1988', '67', '47', '75', '66', '78'), +('8', '7', '48', '1394', '2024', '69', '48', '76', '67', '80'), +('8', '7', '49', '1444', '2077', '70', '48', '78', '69', '82'), +('8', '7', '50', '1495', '2127', '71', '49', '79', '70', '83'), +('8', '7', '51', '1547', '2177', '73', '50', '81', '72', '85'), +('8', '7', '52', '1600', '2204', '74', '51', '82', '73', '87'), +('8', '7', '53', '1654', '2235', '76', '51', '84', '75', '88'), +('8', '7', '54', '1709', '2256', '77', '52', '86', '76', '90'), +('8', '7', '55', '1765', '2286', '78', '53', '87', '78', '92'), +('8', '7', '56', '1822', '2319', '80', '54', '89', '79', '94'), +('8', '7', '57', '1880', '2384', '81', '55', '91', '81', '95'), +('8', '7', '58', '1939', '2432', '83', '55', '92', '83', '97'), +('8', '7', '59', '1999', '2481', '84', '56', '94', '84', '99'), +('8', '7', '60', '2060', '2530', '86', '57', '96', '86', '101'), +('8', '8', '1', '71', '119', '21', '22', '21', '19', '23'), +('8', '8', '2', '77', '130', '21', '22', '21', '20', '24'), +('8', '8', '3', '92', '156', '21', '22', '22', '21', '25'), +('8', '8', '4', '107', '183', '21', '23', '22', '23', '26'), +('8', '8', '5', '122', '211', '21', '23', '22', '24', '28'), +('8', '8', '6', '137', '240', '22', '23', '22', '25', '29'), +('8', '8', '7', '152', '270', '22', '23', '23', '26', '30'), +('8', '8', '8', '167', '286', '22', '23', '23', '27', '31'), +('8', '8', '9', '182', '333', '22', '23', '23', '29', '32'), +('8', '8', '10', '197', '366', '22', '24', '24', '30', '34'), +('8', '8', '11', '212', '400', '22', '24', '24', '31', '35'), +('8', '8', '12', '227', '435', '22', '24', '24', '33', '36'), +('8', '8', '13', '242', '471', '22', '24', '25', '34', '37'), +('8', '8', '14', '257', '508', '23', '24', '25', '35', '39'), +('8', '8', '15', '272', '546', '23', '25', '25', '37', '40'), +('8', '8', '16', '287', '585', '23', '25', '26', '38', '41'), +('8', '8', '17', '302', '610', '23', '25', '26', '39', '43'), +('8', '8', '18', '317', '666', '23', '25', '26', '41', '44'), +('8', '8', '19', '332', '693', '23', '25', '27', '42', '45'), +('8', '8', '20', '347', '751', '23', '26', '27', '44', '47'), +('8', '8', '21', '362', '780', '24', '26', '27', '45', '48'), +('8', '8', '22', '377', '840', '24', '26', '28', '47', '50'), +('8', '8', '23', '392', '871', '24', '26', '28', '48', '51'), +('8', '8', '24', '408', '933', '24', '27', '29', '50', '53'), +('8', '8', '25', '425', '966', '24', '27', '29', '51', '54'), +('8', '8', '26', '443', '1030', '24', '27', '29', '53', '56'), +('8', '8', '27', '462', '1080', '24', '27', '30', '55', '57'), +('8', '8', '28', '482', '1116', '25', '27', '30', '56', '59'), +('8', '8', '29', '503', '1182', '25', '28', '31', '58', '60'), +('8', '8', '30', '525', '1233', '25', '28', '31', '60', '62'), +('8', '8', '31', '548', '1269', '25', '28', '31', '61', '64'), +('8', '8', '32', '572', '1335', '25', '28', '32', '63', '65'), +('8', '8', '33', '597', '1386', '25', '29', '32', '65', '67'), +('8', '8', '34', '623', '1422', '26', '29', '33', '66', '69'), +('8', '8', '35', '650', '1473', '26', '29', '33', '68', '70'), +('8', '8', '36', '678', '1524', '26', '30', '34', '70', '72'), +('8', '8', '37', '707', '1590', '26', '30', '34', '72', '74'), +('8', '8', '38', '737', '1641', '26', '30', '34', '74', '76'), +('8', '8', '39', '768', '1692', '27', '30', '35', '76', '77'), +('8', '8', '40', '800', '1728', '27', '31', '35', '77', '79'), +('8', '8', '41', '833', '1779', '27', '31', '36', '79', '81'), +('8', '8', '42', '867', '1830', '27', '31', '36', '81', '83'), +('8', '8', '43', '902', '1881', '27', '31', '37', '83', '85'), +('8', '8', '44', '938', '1932', '27', '32', '37', '85', '87'), +('8', '8', '45', '975', '1983', '28', '32', '38', '87', '89'), +('8', '8', '46', '1013', '2034', '28', '32', '38', '89', '91'), +('8', '8', '47', '1092', '2085', '28', '33', '39', '91', '93'), +('8', '8', '48', '1102', '2151', '28', '33', '39', '94', '95'), +('8', '8', '49', '1133', '2202', '29', '33', '40', '96', '97'), +('8', '8', '50', '1175', '2238', '29', '34', '40', '98', '99'), +('8', '8', '51', '1218', '2289', '29', '34', '41', '100', '101'), +('8', '8', '52', '1262', '2340', '29', '34', '41', '102', '103'), +('8', '8', '53', '1307', '2391', '29', '35', '42', '104', '105'), +('8', '8', '54', '1353', '2442', '30', '35', '43', '107', '107'), +('8', '8', '55', '1400', '2508', '30', '35', '43', '109', '110'), +('8', '8', '56', '1448', '2547', '30', '36', '44', '111', '112'), +('8', '8', '57', '1497', '2595', '30', '36', '44', '114', '114'), +('8', '8', '58', '1547', '2646', '31', '36', '45', '116', '116'), +('8', '8', '59', '1589', '2697', '31', '37', '45', '119', '119'), +('8', '8', '60', '1650', '2748', '31', '37', '46', '121', '121'); diff --git a/sql/updates/0.6/2691_player_levelupgains.sql b/sql/updates/0.6/2691_player_levelupgains.sql new file mode 100644 index 00000000000..aef481763f3 --- /dev/null +++ b/sql/updates/0.6/2691_player_levelupgains.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS `player_levelupgains`; diff --git a/sql/updates/0.6/2699_character_inventory.sql b/sql/updates/0.6/2699_character_inventory.sql new file mode 100644 index 00000000000..5abfe595818 --- /dev/null +++ b/sql/updates/0.6/2699_character_inventory.sql @@ -0,0 +1,9 @@ +UPDATE character_inventory SET bag = 0 WHERE bag = 255; +CREATE TABLE character_bags SELECT guid, slot, item FROM character_inventory LEFT JOIN item_template ON character_inventory.item_template = item_template.entry WHERE ContainerSlots > 0 AND bag = 0; +CREATE INDEX idx_gs ON character_bags (`guid`,`slot`); +ALTER TABLE character_inventory CHANGE COLUMN `bag` `bag` bigint(20) unsigned NOT NULL default '0'; +UPDATE character_inventory As ci SET bag = (SELECT item FROM character_bags As cb WHERE ci.guid = cb.guid AND cb.slot = ci.bag LIMIT 1) WHERE bag != 0; +DROP TABLE character_bags; +ALTER TABLE character_inventory DROP PRIMARY KEY; +ALTER TABLE character_inventory ADD PRIMARY KEY (`item`); +CREATE INDEX idx_gb ON character_inventory (`guid`,`bag`); \ No newline at end of file diff --git a/sql/updates/0.6/2703_command.sql b/sql/updates/0.6/2703_command.sql new file mode 100644 index 00000000000..ec0f7c1e217 --- /dev/null +++ b/sql/updates/0.6/2703_command.sql @@ -0,0 +1,6 @@ +INSERT INTO `command` VALUES('idleshutdown','3','Syntax: .idleshutdown #delay\r\n\r\nShutting down server after #delay seconds if no active connections present (no players).'); +INSERT INTO `command` VALUES('banaccount','3','Syntax: .banaccount $name\r\n\r\nBan account $name (can be view for player using .pinfo command) and kick affected player if he loginned at server.'); +INSERT INTO `command` VALUES('banip','3','Syntax: .banip #ip\r\n\r\nBan loggining to server from computer with provide IP address and kick all affected players with equal last IP.'); +INSERT INTO `command` VALUES('unbanaccount','3','Syntax: .unbanaccount $name\r\n\r\nUnban account $name.'); +INSERT INTO `command` VALUES('unbanip','3','Syntax: .unbanip #ip\r\n\r\nUnban provide IP address.'); +UPDATE `command` SET `help` = 'Syntax: .kick [$charactername]\r\n\r\nKick the given character from the world. If no character name provide then selected player (except self) will be kicked.' WHERE `name` = 'kick'; diff --git a/sql/updates/0.6/2713_quest_template.sql b/sql/updates/0.6/2713_quest_template.sql new file mode 100644 index 00000000000..116632c8315 --- /dev/null +++ b/sql/updates/0.6/2713_quest_template.sql @@ -0,0 +1,6 @@ +alter table quest_template + drop column detailsemote; +alter table quest_template + drop column completeemote; +alter table quest_template + drop column incompleteemote; \ No newline at end of file diff --git a/sql/updates/0.6/2746_command.sql b/sql/updates/0.6/2746_command.sql new file mode 100644 index 00000000000..6946726f946 --- /dev/null +++ b/sql/updates/0.6/2746_command.sql @@ -0,0 +1 @@ +UPDATE `command` SET `help` = 'Syntax: .npcflag #npcflag\r\n\r\nSet the NPC flags of creature template of the selected creature and selected creature to #npcflag. NPC flags will applied to all creatures of selected creature template after server restart or grid unload/load.' WHERE `name` = 'npcflag'; diff --git a/sql/updates/0.6/2746_creature.sql b/sql/updates/0.6/2746_creature.sql new file mode 100644 index 00000000000..4304f728cba --- /dev/null +++ b/sql/updates/0.6/2746_creature.sql @@ -0,0 +1,3 @@ +ALTER TABLE `creature` + DROP `npcflags`, + DROP `faction`; diff --git a/sql/updates/0.6/2754_realmd.sql b/sql/updates/0.6/2754_realmd.sql new file mode 100644 index 00000000000..b7f6970a8c9 --- /dev/null +++ b/sql/updates/0.6/2754_realmd.sql @@ -0,0 +1 @@ +ALTER TABLE account CHANGE COLUMN `email` `email` varchar(255) NOT NULL default ''; diff --git a/sql/updates/0.6/2762_command.sql b/sql/updates/0.6/2762_command.sql new file mode 100644 index 00000000000..99fe7f64683 --- /dev/null +++ b/sql/updates/0.6/2762_command.sql @@ -0,0 +1 @@ +INSERT INTO `command` VALUES('addquest','3','Syntax: .addquest #quest_id\r\n\r\nAdd to character quest log quest #quest_id. Quest started from item can\'t be added by this command but correct .additem call provided in command output.'); diff --git a/sql/updates/0.6/2765_auctionHouse.sql b/sql/updates/0.6/2765_auctionHouse.sql new file mode 100644 index 00000000000..7b9b56ab03a --- /dev/null +++ b/sql/updates/0.6/2765_auctionHouse.sql @@ -0,0 +1,17 @@ +DROP TABLE IF EXISTS `auctionhouse`; +CREATE TABLE `auctionhouse` ( + `id` bigint(20) unsigned NOT NULL default '0', + `auctioneerguid` int(32) NOT NULL default '0', + `itemguid` int(32) NOT NULL default '0', + `item_template` int(11) unsigned NOT NULL default '0' COMMENT 'Item Identifier', + `itemowner` int(32) NOT NULL default '0', + `buyoutprice` int(32) NOT NULL default '0', + `time` bigint(40) NOT NULL default '0', + `buyguid` int(32) NOT NULL default '0', + `lastbid` int(32) NOT NULL default '0', + `startbid` int(32) NOT NULL default '0', + `deposit` int(11) NOT NULL default '0', + `location` tinyint(3) unsigned NOT NULL default '3', + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + diff --git a/sql/updates/0.6/2765_mail.sql b/sql/updates/0.6/2765_mail.sql new file mode 100644 index 00000000000..78e6dbdde22 --- /dev/null +++ b/sql/updates/0.6/2765_mail.sql @@ -0,0 +1,17 @@ +DROP TABLE IF EXISTS `mail`; +CREATE TABLE `mail` ( + `id` bigint(20) unsigned NOT NULL default '0' COMMENT 'Identifier', + `messageType` int(11) unsigned NOT NULL default '0', + `sender` bigint(20) unsigned NOT NULL default '0' COMMENT 'Character Global Unique Identifier', + `receiver` bigint(20) unsigned NOT NULL default '0' COMMENT 'Character Global Unique Identifier', + `subject` longtext, + `itemPageId` int(11) unsigned NOT NULL default '0', + `item_guid` bigint(20) unsigned NOT NULL default '0' COMMENT 'Mail Item Global Unique Identifier', + `item_template` int(11) unsigned NOT NULL default '0' COMMENT 'Item Identifier', + `time` int(11) unsigned NOT NULL default '0', + `money` int(11) unsigned NOT NULL default '0', + `cod` bigint(11) unsigned NOT NULL default '0', + `checked` tinyint(3) unsigned NOT NULL default '0', + PRIMARY KEY (`id`), + KEY `idx_receiver` (`receiver`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Mail System'; \ No newline at end of file diff --git a/sql/updates/0.6/2778_command.sql b/sql/updates/0.6/2778_command.sql new file mode 100644 index 00000000000..d70b558d417 --- /dev/null +++ b/sql/updates/0.6/2778_command.sql @@ -0,0 +1,2 @@ +UPDATE `command` SET `help` = 'Syntax: .idleshutdown #delay|cancel\r\n\r\nShut the server down after #delay seconds if no active connections are present (no players) or cancel the shutdown if cancel value is used.' WHERE `name` = 'idleshutdown'; +UPDATE `command` SET `help` = 'Syntax: .shutdown #delay|cancel\r\n\r\nShut the server down after #delay seconds or cancel the shutdown if cancel value is used.' WHERE `name` = 'shutdown'; diff --git a/sql/updates/0.6/2787_item_instance.sql b/sql/updates/0.6/2787_item_instance.sql new file mode 100644 index 00000000000..b6d97a87d03 --- /dev/null +++ b/sql/updates/0.6/2787_item_instance.sql @@ -0,0 +1,3 @@ +UPDATE `item_instance` + SET `data` = CONCAT(`data`,' 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ') + WHERE SUBSTRING_INDEX(SUBSTRING_INDEX(`data`,' ',3),' ',-1) = 7 AND SUBSTRING_INDEX(SUBSTRING_INDEX(`data`,' ',91),' ',-1) = ''; diff --git a/sql/updates/0.6/2798_command.sql b/sql/updates/0.6/2798_command.sql new file mode 100644 index 00000000000..03a7c16cd22 --- /dev/null +++ b/sql/updates/0.6/2798_command.sql @@ -0,0 +1 @@ +UPDATE `command` SET `help` = 'Syntax: .levelup [$playername] [#numberoflevels]\r\n\r\nIncrease/decrease the level of character with $playername (or the selected if not name provided) by #numberoflevels Or +1 if no #numberoflevels provided). If #numberoflevels is omitted, the level will be increase by 1. If #numberoflevels is 0, the same level will be restarted. If no character is selected and name not provided, increase your level. Command can be used for offline character. All stats and dependent values recalculated. At level decrease talents can be reset if need. Also at level decrease equipped items with greater level requirement can be lost.' WHERE `name` = 'levelup'; diff --git a/sql/updates/0.6/2803_command.sql b/sql/updates/0.6/2803_command.sql new file mode 100644 index 00000000000..6e36bcc40e7 --- /dev/null +++ b/sql/updates/0.6/2803_command.sql @@ -0,0 +1,11 @@ +DELETE FROM `command` WHERE `name` = 'setskill'; + +INSERT INTO command (name, security, help) VALUES ('setskill', 3,'Syntax: .setskill #skill #level [#max]\r\n\r\nSet a skill of id #skill with a current skill value of #level and a maximum value of #max (or equal current maximum if not provide) for the selected character. If no character is selected, you learn the skill.'); + +DELETE FROM `command` WHERE `name` = 'learnsk'; + +INSERT INTO command (name, security, help) VALUES ('learnskill', 3,'Syntax: .learnskill #skillId [#level [#max]]\r\n\r\nLearn a skill of id #skill with a current skill value of #level (or 1 if not provide) and a maximum value of #max (or equal #level or 1 if not provide) for the selected character. If no character is selected, you learn the skill.'); + +DELETE FROM `command` WHERE `name` = 'unlearnsk'; + +INSERT INTO command (name, security, help) VALUES ('unlearnskill',3,'Syntax: .unlearnskill #skill\r\n\r\nUnlearn a skill of id #skill for the selected character. If no character is selected, you unlearn the skill.'); diff --git a/sql/updates/0.6/2808_command.sql b/sql/updates/0.6/2808_command.sql new file mode 100644 index 00000000000..48ea2fa40ab --- /dev/null +++ b/sql/updates/0.6/2808_command.sql @@ -0,0 +1,2 @@ +DELETE FROM `command` WHERE `name` = 'password'; +INSERT INTO command (name, security, help) VALUES ('password', 0,'Syntax: .password $newpassword\r\n\r\nSet for your account $newpassword as new password.'); diff --git a/sql/updates/0.6/2812_character_pet.sql b/sql/updates/0.6/2812_character_pet.sql new file mode 100644 index 00000000000..1881a731186 --- /dev/null +++ b/sql/updates/0.6/2812_character_pet.sql @@ -0,0 +1,2 @@ +ALTER TABLE `character_pet` + ADD `name` varchar(12) default 'Pet' AFTER `trainpoint`; diff --git a/sql/updates/0.6/2812_pet_name_generation.sql b/sql/updates/0.6/2812_pet_name_generation.sql new file mode 100644 index 00000000000..8131cec00db --- /dev/null +++ b/sql/updates/0.6/2812_pet_name_generation.sql @@ -0,0 +1,211 @@ +DROP TABLE IF EXISTS `pet_name_generation`; +CREATE TABLE `pet_name_generation` ( + `id` int(11) NOT NULL auto_increment, + `word` tinytext NOT NULL, + `entry` int(11) NOT NULL default '0', + `half` int(11) NOT NULL default '0', + PRIMARY KEY (`id`) +); + +/*!40000 ALTER TABLE `pet_name_generation` DISABLE KEYS */; +LOCK TABLES `pet_name_generation` WRITE; +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Aba',416,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Az',416,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Bel',416,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Biz',416,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Cho',416,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Dag',416,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Gak',416,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Gar',416,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Gho',416,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Gob',416,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Gra',416,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Jak',416,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Jub',416,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Kar',416,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Laz',416,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Nal',416,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Nok',416,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Pag',416,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Pig',416,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Pip',416,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Piz',416,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Quz',416,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Rui',416,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Rul',416,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Rup',416,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Tar',416,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Vol',416,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Yaz',416,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Zep',416,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Zig',416,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Zil',416,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Zor',416,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('bis',416,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('gup',416,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('ham',416,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('jub',416,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('kin',416,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('kol',416,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('lop',416,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('loz',416,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('mat',416,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('mir',416,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('nam',416,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('nar',416,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('nik',416,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('nip',416,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('pad',416,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('pep',416,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('pit',416,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('qua',416,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('rai',416,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('rin',416,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('rot',416,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('tai',416,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('tal',416,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('tik',416,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('tip',416,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('tog',416,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('tuk',416,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('uri',416,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('yal',416,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('yap',416,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Bar',1860,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Bel',1860,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Char',1860,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Grak\'',1860,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Graz\'',1860,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Grim',1860,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Hath',1860,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Hel',1860,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Hok',1860,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Jhaz',1860,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Jhom',1860,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Kal\'',1860,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Klath',1860,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Krag',1860,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Krak',1860,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Mak',1860,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Mezz',1860,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Orm',1860,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Phan',1860,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Sar',1860,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Tang',1860,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Than',1860,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Thog',1860,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Thok',1860,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Zang',1860,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Zhar\'',1860,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('doc',1860,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('dok',1860,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('garth',1860,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('gore',1860,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('gorg',1860,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('grave',1860,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('gron',1860,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('juk',1860,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('kath',1860,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('kresh',1860,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('krit',1860,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('los',1860,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('mon',1860,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('mos',1860,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('moth',1860,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('nagma',1860,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('nak',1860,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('nar',1860,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('nos',1860,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('nuz',1860,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('phog',1860,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('rath',1860,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('tast',1860,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('taz',1860,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('thak',1860,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('thang',1860,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('thyk',1860,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('vhug',1860,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('zazt',1860,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Ael',1863,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Aez',1863,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Ang',1863,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Ban',1863,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Bet',1863,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Bro',1863,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Bry',1863,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Dir',1863,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Dom',1863,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Drus',1863,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Fier',1863,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Hel',1863,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Kal',1863,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Lyn',1863,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Mir',1863,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Nim',1863,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Sar',1863,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Sel',1863,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Vil',1863,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Zah',1863,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('aith',1863,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('anda',1863,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('antia',1863,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('lissa',1863,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('neri',1863,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('neth',1863,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('nia',1863,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('nva',1863,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('ola',1863,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('ona',1863,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('ora',1863,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('riana',1863,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('riel',1863,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('tai',1863,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('vina',1863,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('wena',1863,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('wyn',1863,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('yla',1863,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('yssa',1863,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Flaa',417,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Fzuu',417,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Ghaa',417,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Gree',417,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Haa',417,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Jhaa',417,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Jhuu',417,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Khaa',417,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Khii',417,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Khuu',417,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Kree',417,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Maa',417,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Nhee',417,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Phuu',417,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Pryy',417,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Sloo',417,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Sruu',417,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Traa',417,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('Zhaa',417,0); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('dhon',417,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('dhum',417,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('don',417,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('dym',417,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('fun',417,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('ghon',417,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('ghun',417,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('grom',417,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('grym',417,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('jhom',417,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('kun',417,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('mmon',417,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('mon',417,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('nam',417,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('nem',417,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('nhym',417,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('nom',417,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('phom',417,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('roon',417,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('tom',417,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('zhem',417,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('zhum',417,1); +INSERT INTO `pet_name_generation` (`word`, `entry`, `half`) VALUES ('zun',417,1); +UNLOCK TABLES; +/*!40000 ALTER TABLE `pet_name_generation` ENABLE KEYS */; diff --git a/sql/updates/0.6/2815_character_pet.sql b/sql/updates/0.6/2815_character_pet.sql new file mode 100644 index 00000000000..db834b55f2a --- /dev/null +++ b/sql/updates/0.6/2815_character_pet.sql @@ -0,0 +1,2 @@ +ALTER TABLE `character_pet` + CHANGE COLUMN `name` `name` varchar(100) NULL DEFAULT 'Pet'; diff --git a/sql/updates/0.6/2821_raidgroups.sql b/sql/updates/0.6/2821_raidgroups.sql new file mode 100644 index 00000000000..0507a17d266 --- /dev/null +++ b/sql/updates/0.6/2821_raidgroups.sql @@ -0,0 +1,24 @@ +DROP TABLE IF EXISTS `raidgroup`; +CREATE TABLE `raidgroup` ( + `leaderGuid` bigint(20) NOT NULL, + `lootMethod` int(11) NOT NULL, + `looterGuid` bigint(20) NOT NULL, + `icon1` bigint(20) NOT NULL, + `icon2` bigint(20) NOT NULL, + `icon3` bigint(20) NOT NULL, + `icon4` bigint(20) NOT NULL, + `icon5` bigint(20) NOT NULL, + `icon6` bigint(20) NOT NULL, + `icon7` bigint(20) NOT NULL, + `icon8` bigint(20) NOT NULL, + PRIMARY KEY (`leaderGuid`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='RaidGroups'; + +DROP TABLE IF EXISTS `raidgroup_member`; +CREATE TABLE `raidgroup_member` ( + `leaderGuid` bigint(20) NOT NULL, + `memberGuid` bigint(20) NOT NULL, + `assistant` tinyint(1) NOT NULL, + `subgroup` smallint(6) NOT NULL, + PRIMARY KEY (`leaderGuid`,`memberGuid`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='RaidGroups'; \ No newline at end of file diff --git a/sql/updates/0.6/2828_character.sql b/sql/updates/0.6/2828_character.sql new file mode 100644 index 00000000000..434a8d5d35b --- /dev/null +++ b/sql/updates/0.6/2828_character.sql @@ -0,0 +1,27 @@ +ALTER TABLE `auctionhouse` ENGINE = InnoDB; +ALTER TABLE `character` DROP KEY `idx_name`, ENGINE = InnoDB; +ALTER TABLE `character_action` ENGINE = InnoDB; +ALTER TABLE `character_aura` ENGINE = InnoDB; +ALTER TABLE `character_homebind` ENGINE = InnoDB; +ALTER TABLE `character_inventory` ENGINE = InnoDB; +ALTER TABLE `character_kill` ENGINE = InnoDB; +ALTER TABLE `character_pet` ENGINE = InnoDB; +ALTER TABLE `character_queststatus` ENGINE = InnoDB; +ALTER TABLE `character_reputation` ENGINE = InnoDB; +ALTER TABLE `character_social` ENGINE = InnoDB; +ALTER TABLE `character_spell` ENGINE = InnoDB; +ALTER TABLE `character_spell_cooldown` ENGINE = InnoDB; +ALTER TABLE `character_stable` ENGINE = InnoDB; +ALTER TABLE `character_ticket` ENGINE = InnoDB; +ALTER TABLE `character_tutorial` ENGINE = InnoDB; +ALTER TABLE `corpse` ENGINE = InnoDB; +ALTER TABLE `guild` ENGINE = InnoDB; +ALTER TABLE `guild_charter` ENGINE = InnoDB; +ALTER TABLE `guild_charter_sign` ENGINE = InnoDB; +ALTER TABLE `guild_member` ENGINE = InnoDB; +ALTER TABLE `guild_rank` ENGINE = InnoDB; +ALTER TABLE `item_instance` ENGINE = InnoDB; +ALTER TABLE `item_page` ENGINE = InnoDB; +ALTER TABLE `mail` ENGINE = InnoDB; +ALTER TABLE `raidgroup` ENGINE = InnoDB; +ALTER TABLE `raidgroup_member` ENGINE = InnoDB; diff --git a/sql/updates/0.6/2838_corpse_grid.sql b/sql/updates/0.6/2838_corpse_grid.sql new file mode 100644 index 00000000000..c7dee0d0d73 --- /dev/null +++ b/sql/updates/0.6/2838_corpse_grid.sql @@ -0,0 +1 @@ +ALTER TABLE `corpse_grid` ENGINE = MEMORY; diff --git a/sql/updates/0.6/2838_creature_grid.sql b/sql/updates/0.6/2838_creature_grid.sql new file mode 100644 index 00000000000..381934e5b70 --- /dev/null +++ b/sql/updates/0.6/2838_creature_grid.sql @@ -0,0 +1 @@ +ALTER TABLE `creature_grid` ENGINE = MEMORY; diff --git a/sql/updates/0.6/2838_gameobject_grid.sql b/sql/updates/0.6/2838_gameobject_grid.sql new file mode 100644 index 00000000000..099f1e56720 --- /dev/null +++ b/sql/updates/0.6/2838_gameobject_grid.sql @@ -0,0 +1 @@ +ALTER TABLE `gameobject_grid` ENGINE = MEMORY; diff --git a/sql/updates/0.6/2842_character_pet.sql b/sql/updates/0.6/2842_character_pet.sql new file mode 100644 index 00000000000..f306049007b --- /dev/null +++ b/sql/updates/0.6/2842_character_pet.sql @@ -0,0 +1,10 @@ +ALTER TABLE `character_pet` + ADD COLUMN `modelid` int(11) unsigned default '0' after `owner`; + +UPDATE `character_pet`,`creature_template` + SET `character_pet`.`modelid` = `creature_template`.`modelid_m` + WHERE `character_pet`.`modelid` = 0 AND `character_pet`.`entry` = `creature_template`.`entry`; + +UPDATE `character_pet`,`creature_template` + SET `character_pet`.`modelid` = `creature_template`.`modelid_f` + WHERE `character_pet`.`modelid` = 0 AND `character_pet`.`entry` = `creature_template`.`entry`; diff --git a/sql/updates/0.6/2843_character_pet.sql b/sql/updates/0.6/2843_character_pet.sql new file mode 100644 index 00000000000..9202f337f78 --- /dev/null +++ b/sql/updates/0.6/2843_character_pet.sql @@ -0,0 +1,2 @@ +ALTER TABLE `character_pet` + ADD COLUMN `renamed` tinyint(1) unsigned NOT NULL default '0' after `name`; diff --git a/sql/updates/0.6/2850_command.sql b/sql/updates/0.6/2850_command.sql new file mode 100644 index 00000000000..1b6f152ed17 --- /dev/null +++ b/sql/updates/0.6/2850_command.sql @@ -0,0 +1,5 @@ +UPDATE `command` SET `help` = 'Syntax:\r\n.modify speed #rate\r\n.speed #rate\r\n\r\nModify the running speed of the selected player to "normal base run speed"*rate. If no player is selected, modify your speed.\r\n\r\n #rate may range from 0.1 to 10.' WHERE `name` = 'speed'; +UPDATE `command` SET `help` = 'Syntax:\r\n.modify speed #rate\r\n.speed #rate\r\n\r\nModify the running speed of the selected player to "normal base run speed"*rate. If no player is selected, modify your speed.\r\n\r\n #rate may range from 0.1 to 10.' WHERE `name` = 'modify speed'; +UPDATE `command` SET `help` = 'Syntax: .modify swim #rate\r\n\r\nModify the swim speed of the selected player to "normal swim speed"*rate. If no player is selected, modify your speed.\r\n\r\n #rate may range from 0.1 to 10.' WHERE `name` = 'modify swim'; +UPDATE `command` SET `help` = 'Syntax: .modify aspeed #rate\r\n\r\nModify all speeds -run,swim,run back,swim back- of the selected player to "normalbase speed for this move type"*rate. If no player is selected, modify your speed.\r\n\r\n #rate may range from 0.1 to 10.' WHERE `name` = 'modify aspeed'; +UPDATE `command` SET `help` = 'Syntax: .modify bwalk #rate\r\n\r\nModify the speed of the selected player while running backwards to "normal walk back speed"*rate. If no player is selected, modify your speed.\r\n\r\n #speed may range from 0.1 to 10.' WHERE `name` = 'modify bwalk'; diff --git a/sql/updates/0.6/2869_command.sql b/sql/updates/0.6/2869_command.sql new file mode 100644 index 00000000000..5cc6ff5d01e --- /dev/null +++ b/sql/updates/0.6/2869_command.sql @@ -0,0 +1 @@ +UPDATE `command` SET `help` = 'Syntax: .pinfo [$player_name] [rep]\r\n\r\nOutput account information for selected player or player find by $player_name. If "rep" parameter provided show reputation information for player.' WHERE `name` = 'pinfo'; diff --git a/sql/updates/0.6/2875_npc_trainer.sql b/sql/updates/0.6/2875_npc_trainer.sql new file mode 100644 index 00000000000..ed90471d180 --- /dev/null +++ b/sql/updates/0.6/2875_npc_trainer.sql @@ -0,0 +1,2 @@ +ALTER TABLE `npc_trainer` + DROP `reqspell`; diff --git a/sql/updates/0.6/2875_spell_chain.sql b/sql/updates/0.6/2875_spell_chain.sql new file mode 100644 index 00000000000..0535fd5e4c1 --- /dev/null +++ b/sql/updates/0.6/2875_spell_chain.sql @@ -0,0 +1,1359 @@ +-- ---------------------------- +-- Table structure for spell_chain +-- ---------------------------- +DROP TABLE IF EXISTS `spell_chain`; +CREATE TABLE `spell_chain` ( + `spell_id` int(5) NOT NULL default '0', + `prev_spell` int(5) NOT NULL default '0', + `first_spell` int(5) NOT NULL default '0', + `rank` int(2) NOT NULL default '0', + PRIMARY KEY (`spell_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Spell Additinal Data'; + +-- ---------------------------- +-- Records (Proff. spells) +-- ---------------------------- +INSERT INTO `spell_chain` VALUES +('8613', '0', '8613', '1'), +('8617', '8613', '8613', '2'), +('8618', '8617', '8613', '3'), +('10768', '8618', '8613', '4'), + +('4036', '0', '4036', '1'), +('4037', '4036', '4036', '2'), +('4038', '4037', '4036', '3'), +('12656', '4038', '4036', '4'), + +('2259', '0', '2259', '1'), +('3101', '2259', '2259', '2'), +('3464', '3101', '2259', '3'), +('11611', '3464', '2259', '4'), + +('7411', '0', '7411', '1'), +('7412', '7411', '7411', '2'), +('7413', '7412', '7411', '3'), +('13920', '7413', '7411', '4'), + +('3908', '0', '3908', '1'), +('3909', '3908', '3908', '2'), +('3910', '3909', '3908', '3'), +('12180', '3910', '3908', '4'), + +('2108', '0', '2108', '1'), +('3104', '2108', '2108', '2'), +('3811', '3104', '2108', '3'), +('10662', '3811', '2108', '4'), + +('7620', '0', '7620', '1'), +('7731', '7620', '7620', '2'), +('7732', '7731', '7620', '3'), +('18248', '7732', '7620', '4'), + +('2575', '0', '2575', '1'), +('2576', '2575', '2575', '2'), +('3564', '2576', '2575', '3'), +('10248', '3564', '2575', '4'), + +('3273', '0', '3273', '1'), +('3274', '3273', '3273', '2'), +('7924', '3274', '3273', '3'), +('10846', '7924', '3273', '4'), + +('2018', '0', '2018', '1'), +('3100', '2018', '2018', '2'), +('3538', '3100', '2018', '3'), +('9785', '3538', '2018', '4'), +('9787', '9785', '2018', '5'), +('9788', '9785', '2018', '5'), + +('1804', '0', '1804', '1'), +('6461', '1804', '1804', '2'), +('6463', '6461', '1804', '3'), + +('2550', '0', '2550', '1'), +('3102', '2550', '2550', '2'), +('3413', '3102', '2550', '3'), +('18260', '3413', '2550', '4'), + +('2366', '0', '2366', '1'), +('2368', '2366', '2366', '2'), +('3570', '2368', '2366', '3'), +('11993', '3570', '2366', '4'), + +('33388', '0', '33388', '1'), +('33391', '33388', '33388', '2'); + +-- ---------------------------- +-- Records (Ranked spells) +-- ---------------------------- +INSERT INTO `spell_chain` VALUES ('10', '0', '10', '1'), +('17', '0', '17', '1'), +('53', '0', '53', '1'), +('72', '0', '72', '1'), +('78', '0', '78', '1'), +('99', '0', '99', '1'), +('100', '0', '100', '1'), +('116', '0', '116', '1'), +('118', '0', '118', '1'), +('120', '0', '120', '1'), +('122', '0', '122', '1'), +('133', '0', '133', '1'), +('136', '0', '136', '1'), +('139', '0', '139', '1'), +('143', '133', '133', '2'), +('145', '143', '133', '3'), +('168', '0', '168', '1'), +('172', '0', '172', '1'), +('205', '116', '116', '2'), +('284', '78', '78', '2'), +('285', '284', '78', '3'), +('324', '0', '324', '1'), +('325', '324', '324', '2'), +('331', '0', '331', '1'), +('332', '331', '331', '2'), +('339', '0', '339', '1'), +('348', '0', '348', '1'), +('370', '0', '370', '1'), +('403', '0', '403', '1'), +('408', '0', '408', '1'), +('421', '0', '421', '1'), +('453', '0', '453', '1'), +('465', '0', '465', '1'), +('467', '0', '467', '1'), +('469', '0', '469', '1'), +('498', '0', '498', '1'), +('527', '0', '527', '1'), +('529', '403', '403', '2'), +('543', '0', '543', '1'), +('547', '332', '331', '3'), +('548', '529', '403', '3'), +('585', '0', '585', '1'), +('586', '0', '586', '1'), +('587', '0', '587', '1'), +('588', '0', '588', '1'), +('589', '0', '589', '1'), +('591', '585', '585', '2'), +('592', '17', '17', '2'), +('594', '589', '589', '2'), +('596', '0', '596', '1'), +('597', '587', '587', '2'), +('598', '591', '585', '3'), +('600', '592', '17', '3'), +('602', '7128', '588', '3'), +('603', '0', '603', '1'), +('604', '0', '604', '1'), +('605', '0', '605', '1'), +('633', '0', '633', '1'), +('635', '0', '635', '1'), +('639', '635', '635', '2'), +('642', '0', '642', '1'), +('643', '10290', '465', '3'), +('647', '639', '635', '3'), +('686', '0', '686', '1'), +('687', '0', '687', '1'), +('688', '0', '688', '1'), +('689', '0', '689', '1'), +('693', '0', '693', '1'), +('694', '0', '694', '1'), +('695', '686', '686', '2'), +('696', '687', '687', '2'), +('699', '689', '689', '2'), +('702', '0', '702', '1'), +('703', '0', '703', '1'), +('704', '0', '704', '1'), +('705', '695', '686', '3'), +('706', '0', '706', '1'), +('707', '348', '348', '2'), +('709', '699', '689', '3'), +('710', '0', '710', '1'), +('724', '0', '724', '1'), +('740', '0', '740', '1'), +('755', '0', '755', '1'), +('769', '780', '779', '3'), +('770', '0', '770', '1'), +('772', '0', '772', '1'), +('774', '0', '774', '1'), +('778', '770', '770', '2'), +('779', '0', '779', '1'), +('780', '779', '779', '2'), +('781', '0', '781', '1'), +('782', '467', '467', '2'), +('837', '205', '116', '3'), +('845', '0', '845', '1'), +('853', '0', '853', '1'), +('865', '122', '122', '2'), +('879', '0', '879', '1'), +('905', '325', '324', '3'), +('913', '547', '331', '4'), +('915', '548', '403', '4'), +('930', '421', '421', '2'), +('939', '913', '331', '5'), +('943', '915', '403', '5'), +('945', '905', '324', '4'), +('959', '939', '331', '6'), +('970', '594', '589', '3'), +('974', '0', '974', '1'), +('976', '0', '976', '1'), +('980', '0', '980', '1'), +('984', '598', '585', '4'), +('988', '527', '527', '2'), +('990', '597', '587', '3'), +('992', '970', '589', '4'), +('996', '596', '596', '2'), +('1004', '984', '585', '5'), +('1006', '602', '588', '4'), +('1008', '0', '1008', '1'), +('1014', '980', '980', '2'), +('1020', '642', '642', '2'), +('1022', '0', '1022', '1'), +('1026', '647', '635', '4'), +('1032', '10291', '465', '5'), +('1042', '1026', '635', '5'), +('1058', '774', '774', '2'), +('1062', '339', '339', '2'), +('1064', '0', '1064', '1'), +('1075', '782', '467', '3'), +('1079', '0', '1079', '1'), +('1082', '0', '1082', '1'), +('1086', '706', '706', '2'), +('1088', '705', '686', '4'), +('1094', '707', '348', '3'), +('1098', '0', '1098', '1'), +('1106', '1088', '686', '5'), +('1108', '702', '702', '2'), +('1120', '0', '1120', '1'), +('1126', '0', '1126', '1'), +('1130', '0', '1130', '1'), +('1160', '0', '1160', '1'), +('1243', '0', '1243', '1'), +('1244', '1243', '1243', '2'), +('1245', '1244', '1243', '3'), +('1329', '0', '1329', '1'), +('1430', '1058', '774', '3'), +('1449', '0', '1449', '1'), +('1454', '0', '1454', '1'), +('1455', '1454', '1454', '2'), +('1456', '1455', '1454', '3'), +('1459', '0', '1459', '1'), +('1460', '1459', '1459', '2'), +('1461', '1460', '1459', '3'), +('1463', '0', '1463', '1'), +('1464', '0', '1464', '1'), +('1490', '0', '1490', '1'), +('1495', '0', '1495', '1'), +('1499', '0', '1499', '1'), +('1510', '0', '1510', '1'), +('1513', '0', '1513', '1'), +('1535', '0', '1535', '1'), +('1608', '285', '78', '4'), +('1671', '72', '72', '2'), +('1672', '1671', '72', '3'), +('1714', '0', '1714', '1'), +('1715', '0', '1715', '1'), +('1735', '99', '99', '2'), +('1752', '0', '1752', '1'), +('1757', '1752', '1752', '2'), +('1758', '1757', '1752', '3'), +('1759', '1758', '1752', '4'), +('1760', '1759', '1752', '5'), +('1766', '0', '1766', '1'), +('1767', '1766', '1766', '2'), +('1768', '1767', '1766', '3'), +('1769', '1768', '1766', '4'), +('1776', '0', '1776', '1'), +('1777', '1776', '1776', '2'), +('1784', '0', '1784', '1'), +('1785', '1784', '1784', '2'), +('1786', '1785', '1784', '3'), +('1787', '1786', '1784', '4'), +('1822', '0', '1822', '1'), +('1823', '1822', '1822', '2'), +('1824', '1823', '1822', '3'), +('1850', '0', '1850', '1'), +('1856', '0', '1856', '1'), +('1857', '1856', '1856', '2'), +('1943', '0', '1943', '1'), +('1949', '0', '1949', '1'), +('1966', '0', '1966', '1'), +('1978', '0', '1978', '1'), +('2006', '0', '2006', '1'), +('2008', '0', '2008', '1'), +('2010', '2006', '2006', '2'), +('2048', '25289', '6673', '8'), +('2050', '0', '2050', '1'), +('2052', '2050', '2050', '2'), +('2053', '2052', '2050', '3'), +('2054', '0', '2054', '1'), +('2055', '2054', '2054', '2'), +('2060', '0', '2060', '1'), +('2061', '0', '2061', '1'), +('2062', '0', '2062', '1'), +('2070', '6770', '6770', '2'), +('2090', '1430', '774', '4'), +('2091', '2090', '774', '5'), +('2096', '0', '2096', '1'), +('2098', '0', '2098', '1'), +('2120', '0', '2120', '1'), +('2121', '2120', '2120', '2'), +('2136', '0', '2136', '1'), +('2137', '2136', '2136', '2'), +('2138', '2137', '2136', '3'), +('2362', '0', '2362', '1'), +('2589', '53', '53', '2'), +('2590', '2589', '53', '3'), +('2591', '2590', '53', '4'), +('2637', '0', '2637', '1'), +('2643', '0', '2643', '1'), +('2651', '0', '2651', '1'), +('2652', '0', '2652', '1'), +('2767', '992', '589', '5'), +('2791', '1245', '1243', '4'), +('2800', '633', '633', '2'), +('2812', '0', '2812', '1'), +('2825', '0', '2825', '1'), +('2835', '0', '2835', '1'), +('2837', '2835', '2835', '2'), +('2860', '930', '421', '3'), +('2878', '0', '2878', '1'), +('2894', '0', '2894', '1'), +('2908', '0', '2908', '1'), +('2912', '0', '2912', '1'), +('2941', '1094', '348', '4'), +('2944', '0', '2944', '1'), +('2948', '0', '2948', '1'), +('2973', '0', '2973', '1'), +('2974', '0', '2974', '1'), +('2983', '0', '2983', '1'), +('3029', '1082', '1082', '2'), +('3034', '0', '3034', '1'), +('3044', '0', '3044', '1'), +('3111', '136', '136', '2'), +('3140', '145', '133', '4'), +('3420', '0', '3420', '1'), +('3421', '3420', '3420', '2'), +('3472', '1042', '635', '6'), +('3599', '0', '3599', '1'), +('3627', '2091', '774', '6'), +('3661', '3111', '136', '3'), +('3662', '3661', '136', '4'), +('3698', '755', '755', '2'), +('3699', '3698', '755', '3'), +('3700', '3699', '755', '4'), +('3738', '0', '3738', '1'), +('3747', '600', '17', '4'), +('5138', '0', '5138', '1'), +('5143', '0', '5143', '1'), +('5144', '5143', '5143', '2'), +('5145', '5144', '5143', '3'), +('5159', '1062', '339', '3'), +('5171', '0', '5171', '1'), +('5176', '0', '5176', '1'), +('5177', '5176', '5176', '2'), +('5178', '5177', '5176', '3'), +('5179', '5178', '5176', '4'), +('5180', '5179', '5176', '5'), +('5185', '0', '5185', '1'), +('5186', '5185', '5185', '2'), +('5187', '5186', '5185', '3'), +('5188', '5187', '5185', '4'), +('5189', '5188', '5185', '5'), +('5196', '5159', '339', '4'), +('5201', '3029', '1082', '3'), +('5211', '0', '5211', '1'), +('5215', '0', '5215', '1'), +('5217', '0', '5217', '1'), +('5221', '0', '5221', '1'), +('5232', '1126', '1126', '2'), +('5234', '6756', '1126', '4'), +('5242', '6673', '6673', '2'), +('5277', '0', '5277', '1'), +('5308', '0', '5308', '1'), +('5394', '0', '5394', '1'), +('5484', '0', '5484', '1'), +('5504', '0', '5504', '1'), +('5505', '5504', '5504', '2'), +('5506', '5505', '5504', '3'), +('5570', '0', '5570', '1'), +('5573', '498', '498', '2'), +('5588', '853', '853', '2'), +('5589', '5588', '853', '3'), +('5599', '1022', '1022', '2'), +('5614', '879', '879', '2'), +('5615', '5614', '879', '3'), +('5627', '2878', '2878', '2'), +('5675', '0', '5675', '1'), +('5676', '0', '5676', '1'), +('5699', '6202', '6201', '3'), +('5730', '0', '5730', '1'), +('5740', '0', '5740', '1'), +('5763', '0', '5763', '1'), +('5782', '0', '5782', '1'), +('5938', '0', '5938', '1'), +('6041', '943', '403', '6'), +('6060', '1004', '585', '6'), +('6063', '2055', '2054', '3'), +('6064', '6063', '2054', '4'), +('6065', '3747', '17', '5'), +('6066', '6065', '17', '6'), +('6074', '139', '139', '2'), +('6075', '6074', '139', '3'), +('6076', '6075', '139', '4'), +('6077', '6076', '139', '5'), +('6078', '6077', '139', '6'), +('6117', '0', '6117', '1'), +('6127', '5506', '5504', '4'), +('6129', '990', '587', '4'), +('6131', '865', '122', '3'), +('6141', '10', '10', '2'), +('6143', '0', '6143', '1'), +('6178', '100', '100', '2'), +('6190', '1160', '1160', '2'), +('6192', '5242', '6673', '3'), +('6201', '0', '6201', '1'), +('6202', '6201', '6201', '2'), +('6205', '1108', '702', '3'), +('6213', '5782', '5782', '2'), +('6215', '6213', '5782', '3'), +('6217', '1014', '980', '3'), +('6219', '5740', '5740', '2'), +('6222', '172', '172', '2'), +('6223', '6222', '172', '3'), +('6226', '5138', '5138', '2'), +('6229', '0', '6229', '1'), +('6343', '0', '6343', '1'), +('6353', '0', '6353', '1'), +('6363', '3599', '3599', '2'), +('6364', '6363', '3599', '3'), +('6365', '6364', '3599', '4'), +('6366', '0', '6366', '1'), +('6375', '5394', '5394', '2'), +('6377', '6375', '5394', '3'), +('6390', '5730', '5730', '2'), +('6391', '6390', '5730', '3'), +('6392', '6391', '5730', '4'), +('6542', '0', '6542', '1'), +('6546', '772', '772', '2'), +('6547', '6546', '772', '3'), +('6548', '6547', '772', '4'), +('6552', '0', '6552', '1'), +('6554', '6552', '6552', '2'), +('6572', '0', '6572', '1'), +('6574', '6572', '6572', '2'), +('6673', '0', '6673', '1'), +('6756', '5232', '1126', '3'), +('6760', '2098', '2098', '2'), +('6761', '6760', '2098', '3'), +('6762', '6761', '2098', '4'), +('6768', '1966', '1966', '2'), +('6770', '0', '6770', '1'), +('6774', '5171', '5171', '2'), +('6778', '5189', '5185', '6'), +('6780', '5180', '5176', '6'), +('6783', '5215', '5215', '2'), +('6785', '0', '6785', '1'), +('6787', '6785', '6785', '2'), +('6789', '0', '6789', '1'), +('6793', '5217', '5217', '2'), +('6798', '5211', '5211', '2'), +('6800', '5221', '5221', '2'), +('6807', '0', '6807', '1'), +('6808', '6807', '6807', '2'), +('6809', '6808', '6807', '3'), +('6940', '0', '6940', '1'), +('7128', '588', '588', '2'), +('7294', '0', '7294', '1'), +('7300', '168', '168', '2'), +('7301', '7300', '168', '3'), +('7302', '0', '7302', '1'), +('7320', '7302', '7302', '2'), +('7322', '837', '116', '4'), +('7328', '0', '7328', '1'), +('7369', '845', '845', '2'), +('7372', '1715', '1715', '2'), +('7373', '7372', '1715', '3'), +('7379', '6574', '6572', '3'), +('7384', '0', '7384', '1'), +('7386', '0', '7386', '1'), +('7400', '694', '694', '2'), +('7402', '7400', '694', '3'), +('7405', '7386', '7386', '2'), +('7641', '1106', '686', '6'), +('7646', '6205', '702', '4'), +('7648', '6223', '172', '4'), +('7651', '709', '689', '4'), +('7658', '704', '704', '2'), +('7659', '7658', '704', '3'), +('7887', '7384', '7384', '2'), +('8004', '0', '8004', '1'), +('8005', '959', '331', '7'), +('8008', '8004', '8004', '2'), +('8010', '8008', '8004', '3'), +('8012', '370', '370', '2'), +('8017', '0', '8017', '1'), +('8018', '8017', '8017', '2'), +('8019', '8018', '8017', '3'), +('8024', '0', '8024', '1'), +('8027', '8024', '8024', '2'), +('8030', '8027', '8024', '3'), +('8033', '0', '8033', '1'), +('8038', '8033', '8033', '2'), +('8042', '0', '8042', '1'), +('8044', '8042', '8042', '2'), +('8045', '8044', '8042', '3'), +('8046', '8045', '8042', '4'), +('8050', '0', '8050', '1'), +('8052', '8050', '8050', '2'), +('8053', '8052', '8050', '3'), +('8056', '0', '8056', '1'), +('8058', '8056', '8056', '2'), +('8071', '0', '8071', '1'), +('8075', '0', '8075', '1'), +('8092', '0', '8092', '1'), +('8102', '8092', '8092', '2'), +('8103', '8102', '8092', '3'), +('8104', '8103', '8092', '4'), +('8105', '8104', '8092', '5'), +('8106', '8105', '8092', '6'), +('8122', '0', '8122', '1'), +('8124', '8122', '8122', '2'), +('8129', '0', '8129', '1'), +('8131', '8129', '8129', '2'), +('8134', '945', '324', '5'), +('8154', '8071', '8071', '2'), +('8155', '8154', '8071', '3'), +('8160', '8075', '8075', '2'), +('8161', '8160', '8075', '3'), +('8181', '0', '8181', '1'), +('8184', '0', '8184', '1'), +('8190', '0', '8190', '1'), +('8192', '453', '453', '2'), +('8198', '6343', '6343', '2'), +('8204', '8198', '6343', '3'), +('8205', '8204', '6343', '4'), +('8227', '0', '8227', '1'), +('8232', '0', '8232', '1'), +('8235', '8232', '8232', '2'), +('8249', '8227', '8227', '2'), +('8288', '1120', '1120', '2'), +('8289', '8288', '1120', '3'), +('8380', '7405', '7386', '3'), +('8400', '3140', '133', '5'), +('8401', '8400', '133', '6'), +('8402', '8401', '133', '7'), +('8406', '7322', '116', '5'), +('8407', '8406', '116', '6'), +('8408', '8407', '116', '7'), +('8412', '2138', '2136', '4'), +('8413', '8412', '2136', '5'), +('8416', '5145', '5143', '4'), +('8417', '8416', '5143', '5'), +('8422', '2121', '2120', '3'), +('8423', '8422', '2120', '4'), +('8427', '6141', '10', '3'), +('8437', '1449', '1449', '2'), +('8438', '8437', '1449', '3'), +('8439', '8438', '1449', '4'), +('8444', '2948', '2948', '2'), +('8445', '8444', '2948', '3'), +('8446', '8445', '2948', '4'), +('8450', '604', '604', '2'), +('8451', '8450', '604', '3'), +('8455', '1008', '1008', '2'), +('8457', '543', '543', '2'), +('8458', '8457', '543', '3'), +('8461', '6143', '6143', '2'), +('8462', '8461', '6143', '3'), +('8492', '120', '120', '2'), +('8494', '1463', '1463', '2'), +('8495', '8494', '1463', '3'), +('8498', '1535', '1535', '2'), +('8499', '8498', '1535', '3'), +('8512', '0', '8512', '1'), +('8621', '1760', '1752', '6'), +('8623', '6762', '2098', '5'), +('8624', '8623', '2098', '6'), +('8629', '1777', '1776', '3'), +('8631', '703', '703', '2'), +('8632', '8631', '703', '3'), +('8633', '8632', '703', '4'), +('8637', '6768', '1966', '3'), +('8639', '1943', '1943', '2'), +('8640', '8639', '1943', '3'), +('8643', '408', '408', '2'), +('8647', '0', '8647', '1'), +('8649', '8647', '8647', '2'), +('8650', '8649', '8647', '3'), +('8676', '0', '8676', '1'), +('8681', '0', '8681', '1'), +('8687', '8681', '8681', '2'), +('8691', '8687', '8681', '3'), +('8694', '5763', '5763', '2'), +('8696', '2983', '2983', '2'), +('8721', '2591', '53', '5'), +('8724', '8676', '8676', '2'), +('8725', '8724', '8676', '3'), +('8820', '1464', '1464', '2'), +('8835', '0', '8835', '1'), +('8903', '6778', '5185', '7'), +('8905', '6780', '5176', '7'), +('8907', '5234', '1126', '5'), +('8910', '3627', '774', '7'), +('8914', '1075', '467', '4'), +('8918', '740', '740', '2'), +('8921', '0', '8921', '1'), +('8924', '8921', '8921', '2'), +('8925', '8924', '8921', '3'), +('8926', '8925', '8921', '4'), +('8927', '8926', '8921', '5'), +('8928', '8927', '8921', '6'), +('8929', '8928', '8921', '7'), +('8936', '0', '8936', '1'), +('8938', '8936', '8936', '2'), +('8939', '8938', '8936', '3'), +('8940', '8939', '8936', '4'), +('8941', '8940', '8936', '5'), +('8949', '2912', '2912', '2'), +('8950', '8949', '2912', '3'), +('8951', '8950', '2912', '4'), +('8955', '2908', '2908', '2'), +('8972', '6809', '6807', '4'), +('8983', '6798', '5211', '3'), +('8992', '6800', '5221', '3'), +('8998', '0', '8998', '1'), +('9000', '8998', '8998', '2'), +('9005', '0', '9005', '1'), +('9035', '0', '9035', '1'), +('9472', '2061', '2061', '2'), +('9473', '9472', '2061', '3'), +('9474', '9473', '2061', '4'), +('9484', '0', '9484', '1'), +('9485', '9484', '9484', '2'), +('9490', '1735', '99', '3'), +('9492', '1079', '1079', '2'), +('9493', '9492', '1079', '3'), +('9578', '586', '586', '2'), +('9579', '9578', '586', '3'), +('9592', '9579', '586', '4'), +('9745', '8972', '6807', '5'), +('9747', '9490', '99', '4'), +('9749', '778', '770', '3'), +('9750', '8941', '8936', '6'), +('9752', '9493', '1079', '4'), +('9754', '769', '779', '4'), +('9756', '8914', '467', '5'), +('9758', '8903', '5185', '8'), +('9821', '1850', '1850', '2'), +('9823', '9005', '9005', '2'), +('9827', '9823', '9005', '3'), +('9829', '8992', '5221', '4'), +('9830', '9829', '5221', '5'), +('9833', '8929', '8921', '8'), +('9834', '9833', '8921', '9'), +('9835', '9834', '8921', '10'), +('9839', '8910', '774', '8'), +('9840', '9839', '774', '9'), +('9841', '9840', '774', '10'), +('9845', '6793', '5217', '3'), +('9846', '9845', '5217', '4'), +('9849', '5201', '1082', '4'), +('9850', '9849', '1082', '5'), +('9852', '5196', '339', '5'), +('9853', '9852', '339', '6'), +('9856', '9750', '8936', '7'), +('9857', '9856', '8936', '8'), +('9858', '9857', '8936', '9'), +('9862', '8918', '740', '3'), +('9863', '9862', '740', '4'), +('9866', '6787', '6785', '3'), +('9867', '9866', '6785', '4'), +('9875', '8951', '2912', '5'), +('9876', '9875', '2912', '6'), +('9880', '9745', '6807', '6'), +('9881', '9880', '6807', '7'), +('9884', '8907', '1126', '6'), +('9885', '9884', '1126', '7'), +('9888', '9758', '5185', '9'), +('9889', '9888', '5185', '10'), +('9892', '9000', '8998', '3'), +('9894', '9752', '1079', '5'), +('9896', '9894', '1079', '6'), +('9898', '9747', '99', '5'), +('9901', '8955', '2908', '3'), +('9904', '1824', '1822', '4'), +('9907', '9749', '770', '4'), +('9908', '9754', '779', '5'), +('9910', '9756', '467', '6'), +('9912', '8905', '5176', '8'), +('9913', '6783', '5215', '3'), +('10138', '6127', '5504', '5'), +('10139', '10138', '5504', '6'), +('10140', '10139', '5504', '7'), +('10144', '6129', '587', '5'), +('10145', '10144', '587', '6'), +('10148', '8402', '133', '8'), +('10149', '10148', '133', '9'), +('10150', '10149', '133', '10'), +('10151', '10150', '133', '11'), +('10156', '1461', '1459', '4'), +('10157', '10156', '1459', '5'), +('10159', '8492', '120', '3'), +('10160', '10159', '120', '4'), +('10161', '10160', '120', '5'), +('10169', '8455', '1008', '3'), +('10170', '10169', '1008', '4'), +('10173', '8451', '604', '4'), +('10174', '10173', '604', '5'), +('10177', '8462', '6143', '4'), +('10179', '8408', '116', '8'), +('10180', '10179', '116', '9'), +('10181', '10180', '116', '10'), +('10185', '8427', '10', '4'), +('10186', '10185', '10', '5'), +('10187', '10186', '10', '6'), +('10191', '8495', '1463', '4'), +('10192', '10191', '1463', '5'), +('10193', '10192', '1463', '6'), +('10197', '8413', '2136', '6'), +('10199', '10197', '2136', '7'), +('10201', '8439', '1449', '5'), +('10202', '10201', '1449', '6'), +('10205', '8446', '2948', '5'), +('10206', '10205', '2948', '6'), +('10207', '10206', '2948', '7'), +('10211', '8417', '5143', '6'), +('10212', '10211', '5143', '7'), +('10215', '8423', '2120', '5'), +('10216', '10215', '2120', '6'), +('10219', '7320', '7302', '3'), +('10220', '10219', '7302', '4'), +('10223', '8458', '543', '4'), +('10225', '10223', '543', '5'), +('10230', '6131', '122', '4'), +('10278', '5599', '1022', '3'), +('10290', '465', '465', '2'), +('10291', '643', '465', '4'), +('10292', '1032', '465', '6'), +('10293', '10292', '465', '7'), +('10298', '7294', '7294', '2'), +('10299', '10298', '7294', '3'), +('10300', '10299', '7294', '4'), +('10301', '10300', '7294', '5'), +('10308', '5589', '853', '4'), +('10310', '2800', '633', '3'), +('10312', '5615', '879', '4'), +('10313', '10312', '879', '5'), +('10314', '10313', '879', '6'), +('10318', '2812', '2812', '2'), +('10322', '7328', '7328', '2'), +('10324', '10322', '7328', '3'), +('10326', '5627', '2878', '3'), +('10328', '3472', '635', '7'), +('10329', '10328', '635', '8'), +('10391', '6041', '403', '7'), +('10392', '10391', '403', '8'), +('10395', '8005', '331', '8'), +('10396', '10395', '331', '9'), +('10399', '8019', '8017', '4'), +('10406', '8155', '8071', '4'), +('10407', '10406', '8071', '5'), +('10408', '10407', '8071', '6'), +('10412', '8046', '8042', '5'), +('10413', '10412', '8042', '6'), +('10414', '10413', '8042', '7'), +('10427', '6392', '5730', '5'), +('10428', '10427', '5730', '6'), +('10431', '8134', '324', '6'), +('10432', '10431', '324', '7'), +('10437', '6365', '3599', '5'), +('10438', '10437', '3599', '6'), +('10442', '8161', '8075', '4'), +('10447', '8053', '8050', '4'), +('10448', '10447', '8050', '5'), +('10456', '8038', '8033', '3'), +('10462', '6377', '5394', '4'), +('10463', '10462', '5394', '5'), +('10466', '8010', '8004', '4'), +('10467', '10466', '8004', '5'), +('10468', '10467', '8004', '6'), +('10472', '8058', '8056', '3'), +('10473', '10472', '8056', '4'), +('10478', '8181', '8181', '2'), +('10479', '10478', '8181', '3'), +('10486', '8235', '8232', '3'), +('10495', '5675', '5675', '2'), +('10496', '10495', '5675', '3'), +('10497', '10496', '5675', '4'), +('10526', '8249', '8227', '3'), +('10537', '8184', '8184', '2'), +('10538', '10537', '8184', '3'), +('10585', '8190', '8190', '2'), +('10586', '10585', '8190', '3'), +('10587', '10586', '8190', '4'), +('10595', '0', '10595', '1'), +('10600', '10595', '10595', '2'), +('10601', '10600', '10595', '3'), +('10605', '2860', '421', '4'), +('10613', '8512', '8512', '2'), +('10614', '10613', '8512', '3'), +('10622', '1064', '1064', '2'), +('10623', '10622', '1064', '3'), +('10627', '8835', '8835', '2'), +('10797', '0', '10797', '1'), +('10874', '8131', '8129', '3'), +('10875', '10874', '8129', '4'), +('10876', '10875', '8129', '5'), +('10880', '2010', '2006', '3'), +('10881', '10880', '2006', '4'), +('10888', '8124', '8122', '3'), +('10890', '10888', '8122', '4'), +('10892', '2767', '589', '6'), +('10893', '10892', '589', '7'), +('10894', '10893', '589', '8'), +('10898', '6066', '17', '7'), +('10899', '10898', '17', '8'), +('10900', '10899', '17', '9'), +('10901', '10900', '17', '10'), +('10909', '2096', '2096', '2'), +('10911', '605', '605', '2'), +('10912', '10911', '605', '3'), +('10915', '9474', '2061', '5'), +('10916', '10915', '2061', '6'), +('10917', '10916', '2061', '7'), +('10927', '6078', '139', '7'), +('10928', '10927', '139', '8'), +('10929', '10928', '139', '9'), +('10933', '6060', '585', '7'), +('10934', '10933', '585', '8'), +('10937', '2791', '1243', '5'), +('10938', '10937', '1243', '6'), +('10941', '9592', '586', '5'), +('10942', '10941', '586', '6'), +('10945', '8106', '8092', '7'), +('10946', '10945', '8092', '8'), +('10947', '10946', '8092', '9'), +('10951', '1006', '588', '5'), +('10952', '10951', '588', '6'), +('10953', '8192', '453', '3'), +('10955', '9485', '9484', '3'), +('10957', '976', '976', '2'), +('10958', '10957', '976', '3'), +('10960', '996', '596', '3'), +('10961', '10960', '596', '4'), +('10963', '2060', '2060', '2'), +('10964', '10963', '2060', '3'), +('10965', '10964', '2060', '4'), +('11113', '0', '11113', '1'), +('11197', '8650', '8647', '4'), +('11198', '11197', '8647', '5'), +('11267', '8725', '8676', '4'), +('11268', '11267', '8676', '5'), +('11269', '11268', '8676', '6'), +('11273', '8640', '1943', '4'), +('11274', '11273', '1943', '5'), +('11275', '11274', '1943', '6'), +('11279', '8721', '53', '6'), +('11280', '11279', '53', '7'), +('11281', '11280', '53', '8'), +('11285', '8629', '1776', '4'), +('11286', '11285', '1776', '5'), +('11289', '8633', '703', '5'), +('11290', '11289', '703', '6'), +('11293', '8621', '1752', '7'), +('11294', '11293', '1752', '8'), +('11297', '2070', '6770', '3'), +('11299', '8624', '2098', '7'), +('11300', '11299', '2098', '8'), +('11303', '8637', '1966', '4'), +('11305', '8696', '2983', '3'), +('11314', '8499', '1535', '4'), +('11315', '11314', '1535', '5'), +('11341', '8691', '8681', '4'), +('11342', '11341', '8681', '5'), +('11343', '11342', '8681', '6'), +('11357', '2837', '2835', '3'), +('11358', '11357', '2835', '4'), +('11366', '0', '11366', '1'), +('11400', '8694', '5763', '3'), +('11426', '0', '11426', '1'), +('11549', '6192', '6673', '4'), +('11550', '11549', '6673', '5'), +('11551', '11550', '6673', '6'), +('11554', '6190', '1160', '3'), +('11555', '11554', '1160', '4'), +('11556', '11555', '1160', '5'), +('11564', '1608', '78', '5'), +('11565', '11564', '78', '6'), +('11566', '11565', '78', '7'), +('11567', '11566', '78', '8'), +('11572', '6548', '772', '5'), +('11573', '11572', '772', '6'), +('11574', '11573', '772', '7'), +('11578', '6178', '100', '3'), +('11580', '8205', '6343', '5'), +('11581', '11580', '6343', '6'), +('11584', '7887', '7384', '3'), +('11585', '11584', '7384', '4'), +('11596', '8380', '7386', '4'), +('11597', '11596', '7386', '5'), +('11600', '7379', '6572', '4'), +('11601', '11600', '6572', '5'), +('11604', '8820', '1464', '3'), +('11605', '11604', '1464', '4'), +('11608', '7369', '845', '3'), +('11609', '11608', '845', '4'), +('11659', '7641', '686', '7'), +('11660', '11659', '686', '8'), +('11661', '11660', '686', '9'), +('11665', '2941', '348', '5'), +('11667', '11665', '348', '6'), +('11668', '11667', '348', '7'), +('11671', '7648', '172', '5'), +('11672', '11671', '172', '6'), +('11675', '8289', '1120', '4'), +('11677', '6219', '5740', '3'), +('11678', '11677', '5740', '4'), +('11683', '1949', '1949', '2'), +('11684', '11683', '1949', '3'), +('11687', '1456', '1454', '4'), +('11688', '11687', '1454', '5'), +('11689', '11688', '1454', '6'), +('11693', '3700', '755', '5'), +('11694', '11693', '755', '6'), +('11695', '11694', '755', '7'), +('11699', '7651', '689', '5'), +('11700', '11699', '689', '6'), +('11703', '6226', '5138', '3'), +('11704', '11703', '5138', '4'), +('11707', '7646', '702', '5'), +('11708', '11707', '702', '6'), +('11711', '6217', '980', '4'), +('11712', '11711', '980', '5'), +('11713', '11712', '980', '6'), +('11717', '7659', '704', '4'), +('11719', '1714', '1714', '2'), +('11721', '1490', '1490', '2'), +('11722', '11721', '1490', '3'), +('11725', '1098', '1098', '2'), +('11726', '11725', '1098', '3'), +('11729', '5699', '6201', '4'), +('11730', '11729', '6201', '5'), +('11733', '1086', '706', '3'), +('11734', '11733', '706', '4'), +('11735', '11734', '706', '5'), +('11739', '6229', '6229', '2'), +('11740', '11739', '6229', '3'), +('12294', '0', '12294', '1'), +('12505', '11366', '11366', '2'), +('12522', '12505', '11366', '3'), +('12523', '12522', '11366', '4'), +('12524', '12523', '11366', '5'), +('12525', '12524', '11366', '6'), +('12526', '12525', '11366', '7'), +('12824', '118', '118', '2'), +('12825', '12824', '118', '3'), +('12826', '12825', '118', '4'), +('13018', '11113', '11113', '2'), +('13019', '13018', '11113', '3'), +('13020', '13019', '11113', '4'), +('13021', '13020', '11113', '5'), +('13031', '11426', '11426', '2'), +('13032', '13031', '11426', '3'), +('13033', '13032', '11426', '4'), +('13165', '0', '13165', '1'), +('13220', '0', '13220', '1'), +('13228', '13220', '13220', '2'), +('13229', '13228', '13220', '3'), +('13230', '13229', '13220', '4'), +('13542', '3662', '136', '5'), +('13543', '13542', '136', '6'), +('13544', '13543', '136', '7'), +('13549', '1978', '1978', '2'), +('13550', '13549', '1978', '3'), +('13551', '13550', '1978', '4'), +('13552', '13551', '1978', '5'), +('13553', '13552', '1978', '6'), +('13554', '13553', '1978', '7'), +('13555', '13554', '1978', '8'), +('13795', '0', '13795', '1'), +('13813', '0', '13813', '1'), +('13896', '0', '13896', '1'), +('13908', '0', '13908', '1'), +('14260', '2973', '2973', '2'), +('14261', '14260', '2973', '3'), +('14262', '14261', '2973', '4'), +('14263', '14262', '2973', '5'), +('14264', '14263', '2973', '6'), +('14265', '14264', '2973', '7'), +('14266', '14265', '2973', '8'), +('14267', '2974', '2974', '2'), +('14268', '14267', '2974', '3'), +('14269', '1495', '1495', '2'), +('14270', '14269', '1495', '3'), +('14271', '14270', '1495', '4'), +('14272', '781', '781', '2'), +('14273', '14272', '781', '3'), +('14274', '20736', '20736', '2'), +('14279', '3034', '3034', '2'), +('14280', '14279', '3034', '3'), +('14281', '3044', '3044', '2'), +('14282', '14281', '3044', '3'), +('14283', '14282', '3044', '4'), +('14284', '14283', '3044', '5'), +('14285', '14284', '3044', '6'), +('14286', '14285', '3044', '7'), +('14287', '14286', '3044', '8'), +('14288', '2643', '2643', '2'), +('14289', '14288', '2643', '3'), +('14290', '14289', '2643', '4'), +('14294', '1510', '1510', '2'), +('14295', '14294', '1510', '3'), +('14302', '13795', '13795', '2'), +('14303', '14302', '13795', '3'), +('14304', '14303', '13795', '4'), +('14305', '14304', '13795', '5'), +('14310', '1499', '1499', '2'), +('14311', '14310', '1499', '3'), +('14316', '13813', '13813', '2'), +('14317', '14316', '13813', '3'), +('14318', '13165', '13165', '2'), +('14319', '14318', '13165', '3'), +('14320', '14319', '13165', '4'), +('14321', '14320', '13165', '5'), +('14322', '14321', '13165', '6'), +('14323', '1130', '1130', '2'), +('14324', '14323', '1130', '3'), +('14325', '14324', '1130', '4'), +('14326', '1513', '1513', '2'), +('14327', '14326', '1513', '3'), +('14752', '0', '14752', '1'), +('14818', '14752', '14752', '2'), +('14819', '14818', '14752', '3'), +('14914', '0', '14914', '1'), +('15107', '0', '15107', '1'), +('15111', '15107', '15107', '2'), +('15112', '15111', '15107', '3'), +('15207', '10392', '403', '9'), +('15208', '15207', '403', '10'), +('15237', '0', '15237', '1'), +('15261', '15267', '14914', '8'), +('15262', '14914', '14914', '2'), +('15263', '15262', '14914', '3'), +('15264', '15263', '14914', '4'), +('15265', '15264', '14914', '5'), +('15266', '15265', '14914', '6'), +('15267', '15266', '14914', '7'), +('15407', '0', '15407', '1'), +('15430', '15237', '15237', '2'), +('15431', '15430', '15237', '3'), +('15629', '14274', '20736', '3'), +('15630', '15629', '20736', '4'), +('15631', '15630', '20736', '5'), +('15632', '15631', '20736', '6'), +('16314', '10399', '8017', '5'), +('16315', '16314', '8017', '6'), +('16316', '16315', '8017', '7'), +('16339', '8030', '8024', '4'), +('16341', '16339', '8024', '5'), +('16342', '16341', '8024', '6'), +('16355', '10456', '8033', '4'), +('16356', '16355', '8033', '5'), +('16362', '10486', '8232', '4'), +('16387', '10526', '8227', '4'), +('16511', '0', '16511', '1'), +('16689', '0', '16689', '1'), +('16810', '16689', '16689', '2'), +('16811', '16810', '16689', '3'), +('16812', '16811', '16689', '4'), +('16813', '16812', '16689', '5'), +('16857', '0', '16857', '1'), +('16914', '0', '16914', '1'), +('17311', '15407', '15407', '2'), +('17312', '17311', '15407', '3'), +('17313', '17312', '15407', '4'), +('17314', '17313', '15407', '5'), +('17329', '16813', '16689', '6'), +('17347', '16511', '16511', '2'), +('17348', '17347', '16511', '3'), +('17390', '16857', '16857', '2'), +('17391', '17390', '16857', '3'), +('17392', '17391', '16857', '4'), +('17401', '16914', '16914', '2'), +('17402', '17401', '16914', '3'), +('17727', '2362', '2362', '2'), +('17728', '17727', '2362', '3'), +('17862', '0', '17862', '1'), +('17877', '0', '17877', '1'), +('17919', '5676', '5676', '2'), +('17920', '17919', '5676', '3'), +('17921', '17920', '5676', '4'), +('17922', '17921', '5676', '5'), +('17923', '17922', '5676', '6'), +('17924', '6353', '6353', '2'), +('17925', '6789', '6789', '2'), +('17926', '17925', '6789', '3'), +('17928', '5484', '5484', '2'), +('17937', '17862', '17862', '2'), +('17951', '6366', '6366', '2'), +('17952', '17951', '6366', '3'), +('17953', '17952', '6366', '4'), +('17962', '0', '17962', '1'), +('18137', '0', '18137', '1'), +('18220', '0', '18220', '1'), +('18265', '0', '18265', '1'), +('18647', '710', '710', '2'), +('18657', '2637', '2637', '2'), +('18658', '18657', '2637', '3'), +('18807', '17314', '15407', '6'), +('18809', '12526', '11366', '8'), +('18867', '17877', '17877', '2'), +('18868', '18867', '17877', '3'), +('18869', '18868', '17877', '4'), +('18870', '18869', '17877', '5'), +('18871', '18870', '17877', '6'), +('18879', '18265', '18265', '2'), +('18880', '18879', '18265', '3'), +('18881', '18880', '18265', '4'), +('18930', '17962', '17962', '2'), +('18931', '18930', '17962', '3'), +('18932', '18931', '17962', '4'), +('18937', '18220', '18220', '2'), +('18938', '18937', '18220', '3'), +('19236', '13908', '13908', '2'), +('19238', '19236', '13908', '3'), +('19240', '19238', '13908', '4'), +('19241', '19240', '13908', '5'), +('19242', '19241', '13908', '6'), +('19243', '19242', '13908', '7'), +('19261', '2652', '2652', '2'), +('19262', '19261', '2652', '3'), +('19264', '19262', '2652', '4'), +('19265', '19264', '2652', '5'), +('19266', '19265', '2652', '6'), +('19271', '13896', '13896', '2'), +('19273', '19271', '13896', '3'), +('19274', '19273', '13896', '4'), +('19275', '19274', '13896', '5'), +('19276', '2944', '2944', '2'), +('19277', '19276', '2944', '3'), +('19278', '19277', '2944', '4'), +('19279', '19278', '2944', '5'), +('19280', '19279', '2944', '6'), +('19281', '9035', '9035', '2'), +('19282', '19281', '9035', '3'), +('19283', '19282', '9035', '4'), +('19284', '19283', '9035', '5'), +('19285', '19284', '9035', '6'), +('19289', '2651', '2651', '2'), +('19291', '19289', '2651', '3'), +('19292', '19291', '2651', '4'), +('19293', '19292', '2651', '5'), +('19296', '10797', '10797', '2'), +('19299', '19296', '10797', '3'), +('19302', '19299', '10797', '4'), +('19303', '19302', '10797', '5'), +('19304', '19303', '10797', '6'), +('19305', '19304', '10797', '7'), +('19306', '0', '19306', '1'), +('19308', '18137', '18137', '2'), +('19309', '19308', '18137', '3'), +('19310', '19309', '18137', '4'), +('19311', '19310', '18137', '5'), +('19312', '19311', '18137', '6'), +('19386', '0', '19386', '1'), +('19434', '0', '19434', '1'), +('19506', '0', '19506', '1'), +('19740', '0', '19740', '1'), +('19742', '0', '19742', '1'), +('19750', '0', '19750', '1'), +('19834', '19740', '19740', '2'), +('19835', '19834', '19740', '3'), +('19836', '19835', '19740', '4'), +('19837', '19836', '19740', '5'), +('19838', '19837', '19740', '6'), +('19850', '19742', '19742', '2'), +('19852', '19850', '19742', '3'), +('19853', '19852', '19742', '4'), +('19854', '19853', '19742', '5'), +('19876', '0', '19876', '1'), +('19888', '0', '19888', '1'), +('19891', '0', '19891', '1'), +('19895', '19876', '19876', '2'), +('19896', '19895', '19876', '3'), +('19897', '19888', '19888', '2'), +('19898', '19897', '19888', '3'), +('19899', '19891', '19891', '2'), +('19900', '19899', '19891', '3'), +('19939', '19750', '19750', '2'), +('19940', '19939', '19750', '3'), +('19941', '19940', '19750', '4'), +('19942', '19941', '19750', '5'), +('19943', '19942', '19750', '6'), +('19977', '0', '19977', '1'), +('19978', '19977', '19977', '2'), +('19979', '19978', '19977', '3'), +('20043', '0', '20043', '1'), +('20116', '26573', '26573', '2'), +('20162', '21082', '21082', '2'), +('20164', '0', '20164', '1'), +('20165', '0', '20165', '1'), +('20166', '0', '20166', '1'), +('20190', '20043', '20043', '2'), +('20243', '0', '20243', '1'), +('20252', '0', '20252', '1'), +('20287', '21084', '21084', '2'), +('20288', '20287', '21084', '3'), +('20289', '20288', '21084', '4'), +('20290', '20289', '21084', '5'), +('20291', '20290', '21084', '6'), +('20292', '20291', '21084', '7'), +('20293', '20292', '21084', '8'), +('20305', '20162', '21082', '3'), +('20306', '20305', '21082', '4'), +('20307', '20306', '21082', '5'), +('20308', '20307', '21082', '6'), +('20347', '20165', '20165', '2'), +('20348', '20347', '20165', '3'), +('20349', '20348', '20165', '4'), +('20356', '20166', '20166', '2'), +('20357', '20356', '20166', '3'), +('20375', '0', '20375', '1'), +('20473', '0', '20473', '1'), +('20484', '0', '20484', '1'), +('20559', '7402', '694', '4'), +('20560', '20559', '694', '5'), +('20569', '11609', '845', '5'), +('20609', '2008', '2008', '2'), +('20610', '20609', '2008', '3'), +('20616', '20252', '20252', '2'), +('20617', '20616', '20252', '3'), +('20658', '5308', '5308', '2'), +('20660', '20658', '5308', '3'), +('20661', '20660', '5308', '4'), +('20662', '20661', '5308', '5'), +('20729', '6940', '6940', '2'), +('20736', '0', '20736', '1'), +('20739', '20484', '20484', '2'), +('20742', '20739', '20484', '3'), +('20747', '20742', '20484', '4'), +('20748', '20747', '20484', '5'), +('20752', '693', '693', '2'), +('20755', '20752', '693', '3'), +('20756', '20755', '693', '4'), +('20757', '20756', '693', '5'), +('20770', '10881', '2006', '5'), +('20772', '10324', '7328', '4'), +('20773', '20772', '7328', '5'), +('20776', '20610', '2008', '4'), +('20777', '20776', '2008', '5'), +('20900', '19434', '19434', '2'), +('20901', '20900', '19434', '3'), +('20902', '20901', '19434', '4'), +('20903', '20902', '19434', '5'), +('20904', '20903', '19434', '6'), +('20905', '19506', '19506', '2'), +('20906', '20905', '19506', '3'), +('20909', '19306', '19306', '2'), +('20910', '20909', '19306', '3'), +('20911', '0', '20911', '1'), +('20912', '20911', '20911', '2'), +('20913', '20912', '20911', '3'), +('20914', '20913', '20911', '4'), +('20915', '20375', '20375', '2'), +('20918', '20915', '20375', '3'), +('20919', '20918', '20375', '4'), +('20920', '20919', '20375', '5'), +('20922', '20116', '26573', '3'), +('20923', '20922', '26573', '4'), +('20924', '20923', '26573', '5'), +('20925', '0', '20925', '1'), +('20927', '20925', '20925', '2'), +('20928', '20927', '20925', '3'), +('20929', '20473', '20473', '2'), +('20930', '20929', '20473', '3'), +('21082', '0', '21082', '1'), +('21084', '0', '21084', '1'), +('21551', '12294', '12294', '2'), +('21552', '21551', '12294', '3'), +('21553', '21552', '12294', '4'), +('21562', '0', '21562', '1'), +('21564', '21562', '21562', '2'), +('21849', '0', '21849', '1'), +('21850', '21849', '21849', '2'), +('22568', '0', '22568', '1'), +('22782', '6117', '6117', '2'), +('22783', '22782', '6117', '3'), +('22827', '22568', '22568', '2'), +('22828', '22827', '22568', '3'), +('22829', '22828', '22568', '4'), +('22842', '0', '22842', '1'), +('22895', '22842', '22842', '2'), +('22896', '22895', '22842', '3'), +('23028', '0', '23028', '1'), +('23881', '0', '23881', '1'), +('23892', '23881', '23881', '2'), +('23893', '23892', '23881', '3'), +('23894', '23893', '23881', '4'), +('23922', '0', '23922', '1'), +('23923', '23922', '23922', '2'), +('23924', '23923', '23922', '3'), +('23925', '23924', '23922', '4'), +('24132', '19386', '19386', '2'), +('24133', '24132', '19386', '3'), +('24224', '0', '24224', '1'), +('24239', '24274', '24275', '3'), +('24248', '31018', '22568', '6'), +('24274', '24275', '24275', '2'), +('24275', '0', '24275', '1'), +('24398', '0', '24398', '1'), +('24974', '5570', '5570', '2'), +('24975', '24974', '5570', '3'), +('24976', '24975', '5570', '4'), +('24977', '24976', '5570', '5'), +('25286', '11567', '78', '9'), +('25288', '11601', '6572', '6'), +('25289', '11551', '6673', '7'), +('25290', '19854', '19742', '6'), +('25291', '19838', '19740', '7'), +('25292', '10329', '635', '9'), +('25294', '14290', '2643', '5'), +('25295', '13555', '1978', '9'), +('25296', '14322', '13165', '7'), +('25297', '9889', '5185', '11'), +('25298', '9876', '2912', '7'), +('25299', '9841', '774', '11'), +('25300', '11281', '53', '9'), +('25302', '11303', '1966', '5'), +('25304', '10181', '116', '11'), +('25306', '10151', '133', '12'), +('25307', '11661', '686', '10'), +('25309', '11668', '348', '8'), +('25311', '11672', '172', '7'), +('25314', '10965', '2060', '5'), +('25315', '10929', '139', '10'), +('25316', '10961', '596', '5'), +('25345', '10212', '5143', '8'), +('25347', '11358', '2835', '5'), +('25357', '10396', '331', '10'), +('25359', '10627', '8835', '3'), +('25361', '10442', '8075', '5'), +('25782', '0', '25782', '1'), +('25890', '0', '25890', '1'), +('25894', '0', '25894', '1'), +('25899', '0', '25899', '1'), +('25916', '25782', '25782', '2'), +('25918', '25894', '25894', '2'), +('26573', '0', '26573', '1'), +('27681', '0', '27681', '1'), +('27683', '0', '27683', '1'), +('27799', '15431', '15237', '4'), +('27800', '27799', '15237', '5'), +('27801', '27800', '15237', '6'), +('27841', '14819', '14752', '4'), +('27870', '724', '724', '2'), +('27871', '27870', '724', '3'), +('28609', '10177', '6143', '5'), +('28610', '11740', '6229', '4'), +('28612', '10145', '587', '7'), +('29228', '10448', '8050', '6'), +('31016', '11300', '2098', '9'), +('31018', '22829', '22568', '5'); diff --git a/sql/updates/0.6/2881_spell_chain.sql b/sql/updates/0.6/2881_spell_chain.sql new file mode 100644 index 00000000000..215708c0ab0 --- /dev/null +++ b/sql/updates/0.6/2881_spell_chain.sql @@ -0,0 +1,7 @@ +-- ---------------------------- +-- Records (Proff. spells) +-- ---------------------------- +INSERT INTO `spell_chain` VALUES +('10660', '10662', '2108', '5'), +('10658', '10662', '2108', '5'), +('10656', '10662', '2108', '5'); diff --git a/sql/updates/0.6/2885_character.sql b/sql/updates/0.6/2885_character.sql new file mode 100644 index 00000000000..c5e63e73eb9 --- /dev/null +++ b/sql/updates/0.6/2885_character.sql @@ -0,0 +1,2 @@ +ALTER TABLE `character` + DROP `realm`; diff --git a/sql/updates/0.6/2912_areatrigger_template.sql b/sql/updates/0.6/2912_areatrigger_template.sql new file mode 100644 index 00000000000..e28b8638922 --- /dev/null +++ b/sql/updates/0.6/2912_areatrigger_template.sql @@ -0,0 +1 @@ +ALTER TABLE `areatrigger_template` ADD `required_level` SMALLINT NOT NULL DEFAULT '0' AFTER `name` ; \ No newline at end of file diff --git a/sql/updates/0.6/2916_character.sql b/sql/updates/0.6/2916_character.sql new file mode 100644 index 00000000000..e1b36178bf7 --- /dev/null +++ b/sql/updates/0.6/2916_character.sql @@ -0,0 +1,2 @@ +ALTER TABLE `character` + ADD `gmstate` tinyint(3) unsigned NOT NULL default '0'; diff --git a/sql/updates/0.6/2938_spell_scripts.sql b/sql/updates/0.6/2938_spell_scripts.sql new file mode 100644 index 00000000000..d4c376b1c0e --- /dev/null +++ b/sql/updates/0.6/2938_spell_scripts.sql @@ -0,0 +1,13 @@ +DROP TABLE IF EXISTS `spell_scripts`; +CREATE TABLE `spell_scripts` ( + `id` int(11) unsigned NOT NULL default '0', + `delay` int(11) unsigned NOT NULL default '0', + `command` int(11) unsigned NOT NULL default '0', + `datalong` int(11) unsigned NOT NULL default '0', + `datalong2` int(11) unsigned NOT NULL default '0', + `datatext` text NOT NULL, + `x` float NOT NULL default '0', + `y` float NOT NULL default '0', + `z` float NOT NULL default '0', + `o` float NOT NULL default '0' +); diff --git a/sql/updates/0.6/2940_playercreateinfo_skill.sql b/sql/updates/0.6/2940_playercreateinfo_skill.sql new file mode 100644 index 00000000000..fc403eede32 --- /dev/null +++ b/sql/updates/0.6/2940_playercreateinfo_skill.sql @@ -0,0 +1 @@ +DELETE FROM `playercreateinfo_skill` WHERE `Skill` = 633; diff --git a/sql/updates/0.6/2958_command.sql b/sql/updates/0.6/2958_command.sql new file mode 100644 index 00000000000..5ed78bac036 --- /dev/null +++ b/sql/updates/0.6/2958_command.sql @@ -0,0 +1,2 @@ +DELETE FROM `command` WHERE `name` = 'lockaccount'; +INSERT INTO command (name, security, help) VALUES ('lockaccount', 0,'Syntax: .lockaccount [on|off]\r\n\r\nAllow login from account only from current used IP or remove this requirement.'); diff --git a/sql/updates/0.6/2958_scripts.sql b/sql/updates/0.6/2958_scripts.sql new file mode 100644 index 00000000000..c0cf924333b --- /dev/null +++ b/sql/updates/0.6/2958_scripts.sql @@ -0,0 +1,2 @@ +ALTER TABLE `scripts` + CHANGE COLUMN `datatext` `datatext` text NOT NULL; diff --git a/sql/updates/0.6/2958_spell_scripts.sql b/sql/updates/0.6/2958_spell_scripts.sql new file mode 100644 index 00000000000..2a36c43a93d --- /dev/null +++ b/sql/updates/0.6/2958_spell_scripts.sql @@ -0,0 +1,2 @@ +ALTER TABLE `spell_scripts` + CHANGE COLUMN `datatext` `datatext` text NOT NULL; diff --git a/sql/updates/0.6/2982_command.sql b/sql/updates/0.6/2982_command.sql new file mode 100644 index 00000000000..8a4b8fbd464 --- /dev/null +++ b/sql/updates/0.6/2982_command.sql @@ -0,0 +1 @@ +UPDATE `command` SET `help` = 'Syntax: .additem #itemid/[#itemname]/#shift-click-item-link #itemcount\r\n\r\nAdds the specified number of items of id #itemid (or exact (!) name $itemname in brackets, or link created by shift-click at item in inventory or recipe) to your or selected character inventory. If #itemcount is omitted, only one item will be added.\r\n.' WHERE `name` = 'additem'; diff --git a/sql/updates/0.6/2993_command.sql b/sql/updates/0.6/2993_command.sql new file mode 100644 index 00000000000..3b184b492c1 --- /dev/null +++ b/sql/updates/0.6/2993_command.sql @@ -0,0 +1,20 @@ +delete from command where `name` = 'shuttdown'; +delete from command where `name` = 'cshuttdown'; +delete from command where `name` = 'shutdown'; +delete from command where `name` = 'cshutdown'; +insert into command values('shutdown','3','Syntax: .shutdown seconds'); +insert into command values('cshutdown','3','Syntax: .cshutdown Cancels shuttdown'); + +UPDATE `command` SET `help` = 'Syntax: .goobject #object_guid\r\nTeleport your character to gameobject with guid #object_guid' WHERE `name` = 'goobject'; +UPDATE `command` SET `help` = 'Syntax: .targetobject [#go_id|#go_name_part]\r\nLocate and show position nearest gameobject. If #go_id or #go_name_part provide then locate and show position of nearest gameobject with gameobject template id #go_id or name included #go_name_part as part.' WHERE `name` = 'targetobject'; +UPDATE `command` SET `help` = 'Syntax: .learn #parameter\r\n\r\nSelected character learn a spell of id #parameter. A GM can use .learn all if he wants to learn all default spells for Game Masters, .learn all_lang to learn all languages, and .learn all_myclass to learn all spells available for his class (Character selection in these cases ignored).' WHERE `name` = 'learn'; +UPDATE `command` SET `help` = 'Syntax: .taxicheat #flag\r\n\r\nTemporary grant access or remove to all taxi routes for the selected character. If no character is selected, hide or reveal all routes to you.\r\n\r\nUse a #flag of value 1 to add access, use a #flag value of 0 to remove access. Visited taxi nodes sill accessible after removing access.' WHERE `name` = 'taxicheat'; +UPDATE `command` SET `help` = 'Syntax: .visible [0||1]\r\n\r\nOutput current visibility state or make GM visible(1) and invisible(0) for other players.' WHERE `name` = 'visible'; +UPDATE `command` SET `help` = 'Syntax: .moveobject #goguid [#x #y #z]\r\n\r\nMove gameobject #goguid to character coordinates (or to (#x,#y,#z) coordinates if its provide).' WHERE `name` = 'moveobject'; +UPDATE `command` SET `help` = 'Syntax: .playsound #soundid\r\n\r\nPlay sound with #soundid.\r\nSound will be play only for you. Other players do not hear this.\r\nWarning: client may have more 5000 sounds...' WHERE `name` = 'playsound'; +UPDATE `command` SET `help` = 'Syntax:\r\n.reset level\r\n Reset level to 1 including reset stats and talents. Equipped items with greater level requirement can be lost.\r\n.reset spells\r\n Removes all non-original spells from spellbook.\r\n.reset stats\r\n Resets(recalculate) all stats of the targeted player to their original values at current level.\r\n.reset talents\r\n Removes all talents of the targeted player.' WHERE `name` = 'reset'; +UPDATE `command` SET `help` = 'Syntax: .unbanip #ip\r\n\r\nUnban provide IP address.' WHERE `name` = 'unbanip'; +UPDATE `command` SET `help` = 'Syntax: .kick [$charactername]\r\n\r\nKick the given character from the world. If no character name provide then selected player (except self) will be kicked.' WHERE `name` = 'kick'; +UPDATE `command` SET `help` = 'Syntax: .levelup [$playername] [#numberoflevels]\r\n\r\nIncrease/decrease the level of character with $playername (or the selected if not name provided) by #numberoflevels Or +1 if no #numberoflevels provided). If #numberoflevels is omitted, the level will be increase by 1. If #numberoflevels is 0, the same level will be restarted. If no character is selected and name not provided, increase your level. Command can be used for offline character. All stats and dependent values recalculated. At level decrease talents can be reset if need. Also at level decrease equipped items with greater level requirement can be lost.' WHERE `name` = 'levelup'; +UPDATE `command` SET `help` = 'Syntax: .setskill #skill #level [#max]\r\n\r\nSet a skill of id #skill with a current skill value of #level and a maximum value of #max (or equal current maximum if not provide) for the selected character. If no character is selected, you learn the skill.' WHERE `name` = 'setskill'; +UPDATE `command` SET `help` = 'Syntax: .learnskill #skillId [#level [#max]]\r\n\r\nLearn a skill of id #skill with a current skill value of #level (or 1 if not provide) and a maximum value of #max (or equal #level or 1 if not provide) for the selected character. If no character is selected, you learn the skill.' WHERE `name` = 'learnskill'; diff --git a/sql/updates/0.6/3005.sql b/sql/updates/0.6/3005.sql new file mode 100644 index 00000000000..55ae8f4a86b --- /dev/null +++ b/sql/updates/0.6/3005.sql @@ -0,0 +1,166 @@ + +ALTER TABLE `auctionhouse` MODIFY COLUMN `id` int(10) unsigned NOT NULL DEFAULT '0'; +ALTER TABLE `auctionhouse` MODIFY COLUMN `auctioneerguid` int(11) NOT NULL DEFAULT '0'; +ALTER TABLE `auctionhouse` MODIFY COLUMN `itemguid` int(11) NOT NULL DEFAULT '0'; +ALTER TABLE `auctionhouse` MODIFY COLUMN `buyoutprice` int(11) NOT NULL DEFAULT '0'; +ALTER TABLE `auctionhouse` MODIFY COLUMN `buyguid` int(11) NOT NULL DEFAULT '0'; +ALTER TABLE `auctionhouse` MODIFY COLUMN `lastbid` int(11) NOT NULL DEFAULT '0'; +ALTER TABLE `auctionhouse` MODIFY COLUMN `startbid` int(11) NOT NULL DEFAULT '0'; + +ALTER TABLE `character` MODIFY COLUMN `guid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier'; +ALTER TABLE `character` MODIFY COLUMN `account` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'Account Identifier'; +ALTER TABLE `character` MODIFY COLUMN `is_logout_resting` tinyint(3) NOT NULL DEFAULT '0'; + +ALTER TABLE `character_action` MODIFY COLUMN `guid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier'; +ALTER TABLE `character_action` MODIFY COLUMN `button` tinyint(3) unsigned NOT NULL DEFAULT '0'; +ALTER TABLE `character_action` MODIFY COLUMN `action` smallint(5) unsigned NOT NULL DEFAULT '0'; +ALTER TABLE `character_action` MODIFY COLUMN `type` tinyint(3) unsigned NOT NULL DEFAULT '0'; +ALTER TABLE `character_action` MODIFY COLUMN `misc` tinyint(3) unsigned NOT NULL DEFAULT '0'; + +ALTER TABLE `character_aura` MODIFY COLUMN `guid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier'; + +ALTER TABLE `character_homebind` MODIFY COLUMN `guid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier'; + +ALTER TABLE `character_inventory` MODIFY COLUMN `guid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier'; +ALTER TABLE `character_inventory` MODIFY COLUMN `bag` int(11) unsigned NOT NULL DEFAULT '0'; +ALTER TABLE `character_inventory` MODIFY COLUMN `item` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'Item Global Unique Identifier'; + +ALTER TABLE `character_kill` MODIFY COLUMN `guid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier'; +ALTER TABLE `character_kill` MODIFY COLUMN `type` tinyint(3) unsigned NOT NULL DEFAULT '0'; + +ALTER TABLE `character_queststatus` MODIFY COLUMN `guid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier'; + +ALTER TABLE `character_reputation` MODIFY COLUMN `guid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier'; + +ALTER TABLE `character_social` MODIFY COLUMN `guid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier'; +ALTER TABLE `character_social` MODIFY COLUMN `friend` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'Character Global Unique Identifier'; + +ALTER TABLE `character_spell` MODIFY COLUMN `guid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier'; +ALTER TABLE `character_spell` MODIFY COLUMN `active` tinyint(3) unsigned NOT NULL DEFAULT '1'; + +ALTER TABLE `character_ticket` MODIFY COLUMN `guid` int(11) unsigned NOT NULL DEFAULT '0'; + +ALTER TABLE `character_tutorial` MODIFY COLUMN `guid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier'; +ALTER TABLE `character_tutorial` MODIFY COLUMN `tut0` int(11) unsigned NOT NULL default '0'; +ALTER TABLE `character_tutorial` MODIFY COLUMN `tut1` int(11) unsigned NOT NULL default '0'; +ALTER TABLE `character_tutorial` MODIFY COLUMN `tut2` int(11) unsigned NOT NULL default '0'; +ALTER TABLE `character_tutorial` MODIFY COLUMN `tut3` int(11) unsigned NOT NULL default '0'; +ALTER TABLE `character_tutorial` MODIFY COLUMN `tut4` int(11) unsigned NOT NULL default '0'; +ALTER TABLE `character_tutorial` MODIFY COLUMN `tut5` int(11) unsigned NOT NULL default '0'; +ALTER TABLE `character_tutorial` MODIFY COLUMN `tut6` int(11) unsigned NOT NULL default '0'; +ALTER TABLE `character_tutorial` MODIFY COLUMN `tut7` int(11) unsigned NOT NULL default '0'; +ALTER TABLE `command` MODIFY COLUMN `name` varchar(50) NOT NULL default ''; +ALTER TABLE `command` MODIFY COLUMN `security` tinyint(3) unsigned NOT NULL DEFAULT '0'; + +ALTER TABLE `corpse` MODIFY COLUMN `guid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier'; +ALTER TABLE `corpse` MODIFY COLUMN `player` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'Character Global Unique Identifier'; + +ALTER TABLE `corpse_grid` MODIFY COLUMN `guid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier'; + +ALTER TABLE `creature` MODIFY COLUMN `guid` int(11) unsigned NOT NULL auto_increment COMMENT 'Global Unique Identifier'; +ALTER TABLE `creature` MODIFY COLUMN `state` tinyint(3) unsigned NOT NULL DEFAULT '0'; +ALTER TABLE `creature` MODIFY COLUMN `MovementType` tinyint(3) unsigned NOT NULL DEFAULT '0'; + + +ALTER TABLE `creature_grid` MODIFY COLUMN `guid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier'; + +ALTER TABLE `creature_loot_template` MODIFY COLUMN `maxcount` tinyint(3) unsigned NOT NULL DEFAULT '1'; +ALTER TABLE `creature_loot_template` MODIFY COLUMN `quest_freeforall` tinyint(3) unsigned NOT NULL DEFAULT '1'; + +ALTER TABLE `creature_template` MODIFY COLUMN `minlevel` tinyint(3) unsigned DEFAULT '1'; +ALTER TABLE `creature_template` MODIFY COLUMN `maxlevel` tinyint(3) unsigned DEFAULT '1'; +ALTER TABLE `creature_template` MODIFY COLUMN `rank` tinyint(3) unsigned DEFAULT '0'; +ALTER TABLE `creature_template` MODIFY COLUMN `trainer_type` tinyint(3) DEFAULT '0'; +ALTER TABLE `creature_template` MODIFY COLUMN `class` tinyint(3) unsigned DEFAULT '0'; +ALTER TABLE `creature_template` MODIFY COLUMN `race` tinyint(3) unsigned DEFAULT '0'; + +ALTER TABLE `creature_template` MODIFY COLUMN `rangedattackpower` smallint(5) unsigned NOT NULL DEFAULT '0'; +ALTER TABLE `creature_template` MODIFY COLUMN `type` tinyint(3) unsigned DEFAULT '0'; +ALTER TABLE `creature_template` MODIFY COLUMN `civilian` tinyint(3) unsigned NOT NULL DEFAULT '0'; +ALTER TABLE `creature_template` MODIFY COLUMN `MovementType` tinyint(3) unsigned NOT NULL DEFAULT '0'; + +ALTER TABLE `fishing_loot_template` MODIFY COLUMN `maxcount` tinyint(3) unsigned NOT NULL DEFAULT '1'; +ALTER TABLE `fishing_loot_template` MODIFY COLUMN `quest_freeforall` tinyint(3) unsigned NOT NULL DEFAULT '1'; + +ALTER TABLE `gameobject` MODIFY COLUMN `guid` int(11) unsigned NOT NULL auto_increment COMMENT 'Global Unique Identifier'; + +ALTER TABLE `gameobject_grid` MODIFY COLUMN `guid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier'; + +ALTER TABLE `gameobject_loot_template` MODIFY COLUMN `maxcount` tinyint(3) unsigned NOT NULL DEFAULT '1'; +ALTER TABLE `gameobject_loot_template` MODIFY COLUMN `quest_freeforall` tinyint(3) unsigned NOT NULL DEFAULT '1'; + +ALTER TABLE `item_instance` MODIFY COLUMN `guid` int(11) unsigned NOT NULL DEFAULT '0'; +ALTER TABLE `item_instance` ADD COLUMN `owner_guid` int(11) unsigned NOT NULL DEFAULT '0' AFTER `guid`; + + +UPDATE `item_instance` + SET `owner_guid` = SUBSTRING_INDEX(SUBSTRING_INDEX(`data`,' ',7),' ',-1); + +ALTER TABLE `item_loot_template` MODIFY COLUMN `maxcount` tinyint(3) unsigned NOT NULL DEFAULT '1'; +ALTER TABLE `item_loot_template` MODIFY COLUMN `quest_freeforall` tinyint(3) unsigned NOT NULL DEFAULT '1'; + +ALTER TABLE `item_template` MODIFY COLUMN `class` tinyint(3) unsigned NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `subclass` tinyint(3) unsigned NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `displayid` int(11) unsigned NOT NULL default '0'; +ALTER TABLE `item_template` MODIFY COLUMN `Quality` tinyint(3) unsigned NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `InventoryType` tinyint(3) unsigned NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `AllowableClass` mediumint(9) NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `RequiredLevel` tinyint(3) unsigned NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `maxcount` smallint(5) unsigned NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `stackable` smallint(5) unsigned NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `ContainerSlots` tinyint(3) unsigned NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `stat_type1` tinyint(4) NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `stat_value1` smallint(6) NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `stat_type2` tinyint(4) NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `stat_value2` smallint(6) NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `stat_type3` tinyint(4) NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `stat_value3` smallint(6) NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `stat_type4` tinyint(4) NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `stat_value4` smallint(6) NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `stat_type5` tinyint(4) NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `stat_value5` smallint(6) NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `stat_type6` tinyint(4) NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `stat_value6` smallint(6) NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `stat_type7` tinyint(4) NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `stat_value7` smallint(6) NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `stat_type8` tinyint(4) NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `stat_value8` smallint(6) NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `stat_type9` tinyint(4) NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `stat_value9` smallint(6) NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `stat_type10` tinyint(4) NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `stat_value10` smallint(6) NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `dmg_type1` tinyint(3) unsigned NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `dmg_type2` tinyint(3) unsigned NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `dmg_type3` tinyint(3) unsigned NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `dmg_type4` tinyint(3) unsigned NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `dmg_type5` tinyint(3) unsigned NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` MODIFY COLUMN `bonding` tinyint(3) unsigned NOT NULL DEFAULT '0'; + + +ALTER TABLE `mail` MODIFY COLUMN `id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'Identifier'; +ALTER TABLE `mail` MODIFY COLUMN `messageType` tinyint(3) unsigned NOT NULL DEFAULT '0'; +ALTER TABLE `mail` MODIFY COLUMN `sender` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'Character Global Unique Identifier'; +ALTER TABLE `mail` MODIFY COLUMN `receiver` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'Character Global Unique Identifier'; +ALTER TABLE `mail` MODIFY COLUMN `item_guid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'Mail Item Global Unique Identifier'; +ALTER TABLE `mail` MODIFY COLUMN `cod` int(11) unsigned NOT NULL DEFAULT '0'; + +DROP TABLE IF EXISTS `npc_spirithealer`; +DELETE FROM `command` WHERE `name` = 'addspirit'; +DELETE FROM `command` WHERE `name` = 'addsh'; + +ALTER TABLE `npc_vendor` MODIFY COLUMN `maxcount` tinyint(3) unsigned NOT NULL DEFAULT '0'; + +ALTER TABLE `pickpocketing_loot_template` MODIFY COLUMN `maxcount` tinyint(3) unsigned NOT NULL DEFAULT '1'; +ALTER TABLE `pickpocketing_loot_template` MODIFY COLUMN `quest_freeforall` tinyint(3) unsigned NOT NULL DEFAULT '1'; + +ALTER TABLE `raidgroup` MODIFY COLUMN `leaderGuid` int(11) NOT NULL; +ALTER TABLE `raidgroup` MODIFY COLUMN `lootMethod` tinyint(4) NOT NULL; +ALTER TABLE `raidgroup` MODIFY COLUMN `looterGuid` int(11) NOT NULL; + +ALTER TABLE `raidgroup_member` MODIFY COLUMN `leaderGuid` int(11) NOT NULL; +ALTER TABLE `raidgroup_member` MODIFY COLUMN `memberGuid` int(11) NOT NULL; + +ALTER TABLE `skinning_loot_template` MODIFY COLUMN `maxcount` tinyint(3) unsigned NOT NULL DEFAULT '1'; +ALTER TABLE `skinning_loot_template` MODIFY COLUMN `quest_freeforall` tinyint(3) unsigned NOT NULL DEFAULT '1'; + +ALTER TABLE `spell_chain` MODIFY COLUMN `rank` tinyint(4) NOT NULL DEFAULT '0'; diff --git a/sql/updates/0.6/3010_item_template.sql b/sql/updates/0.6/3010_item_template.sql new file mode 100644 index 00000000000..9fe8bf949e8 --- /dev/null +++ b/sql/updates/0.6/3010_item_template.sql @@ -0,0 +1 @@ +ALTER TABLE `item_template` ADD COLUMN `BagFamily` tinyint(3) unsigned NOT NULL default '0' AFTER `area`; diff --git a/sql/updates/0.6/3017_auctionhouse.sql b/sql/updates/0.6/3017_auctionhouse.sql new file mode 100644 index 00000000000..0125fc62212 --- /dev/null +++ b/sql/updates/0.6/3017_auctionhouse.sql @@ -0,0 +1,5 @@ +ALTER TABLE `auctionhouse` + MODIFY COLUMN `auctioneerguid` int(11) unsigned NOT NULL default '0', + MODIFY COLUMN `itemguid` int(11) unsigned NOT NULL default '0', + MODIFY COLUMN `itemowner` int(11) unsigned NOT NULL default '0', + MODIFY COLUMN `buyguid` int(11) unsigned NOT NULL default '0'; diff --git a/sql/updates/0.6/3020_command.sql b/sql/updates/0.6/3020_command.sql new file mode 100644 index 00000000000..5e27a86d4ff --- /dev/null +++ b/sql/updates/0.6/3020_command.sql @@ -0,0 +1,2 @@ +DELETE FROM `command` WHERE `name` = 'cooldown'; +INSERT INTO command (name, security, help) VALUES ('cooldown', 3,'Syntax: .cooldown [#spell_id]\r\n\r\nRemove all (if spell_id not provided) or #spel_id spell cooldown from selected character or you (if no selection).'); diff --git a/sql/updates/0.6/3032_creature.sql b/sql/updates/0.6/3032_creature.sql new file mode 100644 index 00000000000..7acf3578878 --- /dev/null +++ b/sql/updates/0.6/3032_creature.sql @@ -0,0 +1,7 @@ +/*delete redundant column from creature table*/ +ALTER TABLE `creature` ADD COLUMN `spawntimesecs` int(11) unsigned NOT NULL default '120' AFTER `spawntimemin`; + +UPDATE creature SET `spawntimesecs`= (spawntimemin + spawntimemax) /2; + +ALTER TABLE creature DROP COLUMN spawntimemax; +ALTER TABLE creature DROP COLUMN spawntimemin; \ No newline at end of file diff --git a/sql/updates/0.6/3044_gameobject_template.sql b/sql/updates/0.6/3044_gameobject_template.sql new file mode 100644 index 00000000000..aad97b09d7f --- /dev/null +++ b/sql/updates/0.6/3044_gameobject_template.sql @@ -0,0 +1,2 @@ +ALTER TABLE `gameobject_template` + DROP `castsSpell`; diff --git a/sql/updates/0.6/3054_command.sql b/sql/updates/0.6/3054_command.sql new file mode 100644 index 00000000000..347924f6555 --- /dev/null +++ b/sql/updates/0.6/3054_command.sql @@ -0,0 +1,5 @@ +DELETE FROM `command` WHERE `name` = 'searchtele'; +INSERT INTO `command` VALUES('lookuptele',1,'Syntax: .lookuptele $substring\r\n\r\nSearch and output all .tele command locations with provide $substring in name.'); +INSERT INTO `command` VALUES('lookupquest',3,'Syntax: .lookupquest $namepart\r\n\r\nLooks up a quest by $namepart, and returns all matches with their quest ID\'s.'); +INSERT INTO `command` VALUES('lookupspell',3,'Syntax: .lookupspell $namepart\r\n\r\nLooks up a spell by $namepart, and returns all matches with their spell ID\'s.'); + diff --git a/sql/updates/0.6/3059_pet_levelstats.sql b/sql/updates/0.6/3059_pet_levelstats.sql new file mode 100644 index 00000000000..e69e440cdf0 --- /dev/null +++ b/sql/updates/0.6/3059_pet_levelstats.sql @@ -0,0 +1,12 @@ +CREATE TABLE `pet_levelstats` ( + `creature_entry` int(11) unsigned NOT NULL, + `level` tinyint(3) unsigned NOT NULL, + `hp` smallint(5) unsigned NOT NULL, + `mana` smallint(5) unsigned NOT NULL, + `str` smallint(5) unsigned NOT NULL, + `agi` smallint(5) unsigned NOT NULL, + `sta` smallint(5) unsigned NOT NULL, + `int` smallint(5) unsigned NOT NULL, + `spi` smallint(5) unsigned NOT NULL, + PRIMARY KEY (`creature_entry`,`level`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 PACK_KEYS=0 COMMENT='Stores pet levels stats.'; diff --git a/sql/updates/0.6/3068_command.sql b/sql/updates/0.6/3068_command.sql new file mode 100644 index 00000000000..56cbfbd7613 --- /dev/null +++ b/sql/updates/0.6/3068_command.sql @@ -0,0 +1,2 @@ +INSERT INTO `command` (`name`,`security`,`help`) VALUES ('spawndist',2,'Syntax: .spawndist #dist\r\n\r\nAdjust spawndistance of selected creature to dist.'); +INSERT INTO `command` (`name`,`security`,`help`) VALUES ('spawntime',2,'Syntax: .spawntime #time \r\n\r\nAdjust spawntime of selected creature to time.'); \ No newline at end of file diff --git a/sql/updates/0.6/3075_creature.sql b/sql/updates/0.6/3075_creature.sql new file mode 100644 index 00000000000..74f1dbd35c6 --- /dev/null +++ b/sql/updates/0.6/3075_creature.sql @@ -0,0 +1,8 @@ +ALTER TABLE creature DROP COLUMN respawntimer; + +DROP TABLE IF EXISTS `creature_respawn`; +CREATE TABLE `creature_respawn` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `respawntime` bigint(40) NOT NULL default '0', + PRIMARY KEY (`guid`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Grid Loading System'; diff --git a/sql/updates/0.6/3075_gameobject.sql b/sql/updates/0.6/3075_gameobject.sql new file mode 100644 index 00000000000..9a576787d0d --- /dev/null +++ b/sql/updates/0.6/3075_gameobject.sql @@ -0,0 +1,12 @@ +ALTER TABLE `gameobject` + CHANGE `respawntimer` `spawntimesecs` int(11) unsigned NOT NULL default '0'; + +UPDATE `gameobject` SET `spawntimesecs` = `spawntimesecs` / 1000; + +DROP TABLE IF EXISTS `gameobject_respawn`; +CREATE TABLE `gameobject_respawn` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `respawntime` bigint(40) NOT NULL default '0', + PRIMARY KEY (`guid`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Grid Loading System'; + diff --git a/sql/updates/0.6/3090_command.sql b/sql/updates/0.6/3090_command.sql new file mode 100644 index 00000000000..29bb8b07a21 --- /dev/null +++ b/sql/updates/0.6/3090_command.sql @@ -0,0 +1 @@ +INSERT INTO `command` (`name`,`security`,`help`) VALUES ('respawn',3,'Syntax: .respawn\r\n\r\nRespawn all nearest creatures and GO without waiting respawn time expiration.'); diff --git a/sql/updates/0.6/3090_creature_template.sql b/sql/updates/0.6/3090_creature_template.sql new file mode 100644 index 00000000000..64bb0e610e2 --- /dev/null +++ b/sql/updates/0.6/3090_creature_template.sql @@ -0,0 +1,6 @@ +ALTER TABLE `creature_template` + ADD COLUMN `pickpocketloot` int(10) unsigned NOT NULL default '0' AFTER `lootid`; + +UPDATE `creature_template`,`pickpocketing_loot_template` + SET `creature_template`.`pickpocketloot` = `creature_template`.`lootid` + WHERE `creature_template`.`lootid` = `pickpocketing_loot_template`.`entry`; diff --git a/sql/updates/0.6/3090_loot_template.sql b/sql/updates/0.6/3090_loot_template.sql new file mode 100644 index 00000000000..ccfc7fa62f6 --- /dev/null +++ b/sql/updates/0.6/3090_loot_template.sql @@ -0,0 +1,17 @@ +ALTER TABLE `creature_loot_template` + ADD COLUMN `mincount` tinyint(3) unsigned NOT NULL default '1' AFTER `QuestChanceOrGroup`; + +ALTER TABLE `fishing_loot_template` + ADD COLUMN `mincount` tinyint(3) unsigned NOT NULL default '1' AFTER `QuestChanceOrGroup`; + +ALTER TABLE `gameobject_loot_template` + ADD COLUMN `mincount` tinyint(3) unsigned NOT NULL default '1' AFTER `QuestChanceOrGroup`; + +ALTER TABLE `item_loot_template` + ADD COLUMN `mincount` tinyint(3) unsigned NOT NULL default '1' AFTER `QuestChanceOrGroup`; + +ALTER TABLE `pickpocketing_loot_template` + ADD COLUMN `mincount` tinyint(3) unsigned NOT NULL default '1' AFTER `QuestChanceOrGroup`; + +ALTER TABLE `skinning_loot_template` + ADD COLUMN `mincount` tinyint(3) unsigned NOT NULL default '1' AFTER `QuestChanceOrGroup`; diff --git a/sql/updates/0.6/3091_spell_proc_event.sql b/sql/updates/0.6/3091_spell_proc_event.sql new file mode 100644 index 00000000000..298bab0f3e1 --- /dev/null +++ b/sql/updates/0.6/3091_spell_proc_event.sql @@ -0,0 +1,831 @@ +DROP TABLE IF EXISTS `spell_proc_event`; + +CREATE TABLE `spell_proc_event` ( + `entry` smallint(6) NOT NULL default '0', + `SchoolMask` tinyint(4) NOT NULL default '0', + `Category` smallint(6) NOT NULL default '0', + `SkillID` smallint(6) NOT NULL default '0', + `SpellFamilyMask` int(11) NOT NULL default '0', + `procFlags` int(11) NOT NULL default '0', + `ppmRate` float NOT NULL default '0', + PRIMARY KEY (`entry`) +); + +INSERT INTO `spell_proc_event` VALUES ('6866', '4', '0', '0', '0', '20564', '0'); +INSERT INTO `spell_proc_event` VALUES ('6870', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('7131', '0', '0', '0', '0', '664232', '0'); +INSERT INTO `spell_proc_event` VALUES ('9452', '0', '0', '0', '0', '20', '3'); +INSERT INTO `spell_proc_event` VALUES ('9799', '0', '0', '0', '0', '262144', '0'); +INSERT INTO `spell_proc_event` VALUES ('11119', '2', '0', '0', '0', '65536', '0'); +INSERT INTO `spell_proc_event` VALUES ('11120', '2', '0', '0', '0', '65536', '0'); +INSERT INTO `spell_proc_event` VALUES ('11129', '2', '0', '0', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('11180', '8', '0', '0', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('12846', '2', '0', '0', '0', '65536', '0'); +INSERT INTO `spell_proc_event` VALUES ('12847', '2', '0', '0', '0', '65536', '0'); +INSERT INTO `spell_proc_event` VALUES ('12848', '2', '0', '0', '0', '65536', '0'); +INSERT INTO `spell_proc_event` VALUES ('13896', '0', '0', '0', '0', '1048576', '0'); +INSERT INTO `spell_proc_event` VALUES ('14076', '0', '0', '39', '128', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('14094', '0', '0', '39', '128', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('14095', '0', '0', '39', '128', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('15286', '16', '0', '0', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('18073', '2', '0', '0', '96', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('18096', '2', '0', '0', '96', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('19271', '0', '0', '0', '0', '1048576', '0'); +INSERT INTO `spell_proc_event` VALUES ('19273', '0', '0', '0', '0', '1048576', '0'); +INSERT INTO `spell_proc_event` VALUES ('19274', '0', '0', '0', '0', '1048576', '0'); +INSERT INTO `spell_proc_event` VALUES ('19275', '0', '0', '0', '0', '1048576', '0'); +INSERT INTO `spell_proc_event` VALUES ('20183', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('20204', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('20411', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('20412', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('20413', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('20414', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('20911', '0', '0', '0', '0', '64', '0'); +INSERT INTO `spell_proc_event` VALUES ('20912', '0', '0', '0', '0', '64', '0'); +INSERT INTO `spell_proc_event` VALUES ('20913', '0', '0', '0', '0', '64', '0'); +INSERT INTO `spell_proc_event` VALUES ('20914', '0', '0', '0', '0', '64', '0'); +INSERT INTO `spell_proc_event` VALUES ('21063', '0', '0', '0', '0', '32768', '0'); +INSERT INTO `spell_proc_event` VALUES ('21893', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('21978', '0', '0', '0', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('22007', '0', '0', '0', '2099233', '16384', '0'); +INSERT INTO `spell_proc_event` VALUES ('22697', '32', '0', '0', '0', '664232', '0'); +INSERT INTO `spell_proc_event` VALUES ('23551', '4', '0', '0', '192', '16384', '0'); +INSERT INTO `spell_proc_event` VALUES ('23552', '0', '0', '0', '0', '1049602', '0'); +INSERT INTO `spell_proc_event` VALUES ('23572', '4', '0', '0', '192', '16384', '0'); +INSERT INTO `spell_proc_event` VALUES ('24596', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('25592', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('25669', '0', '0', '0', '0', '1', '1'); +INSERT INTO `spell_proc_event` VALUES ('25715', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('25727', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('25728', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('25729', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('25730', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('25731', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('25732', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('25733', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('25734', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('25745', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('25751', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('25752', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('25757', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('25759', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('25760', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('25761', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('25762', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('25767', '0', '0', '0', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('25820', '0', '0', '0', '0', '1049602', '0'); +INSERT INTO `spell_proc_event` VALUES ('25899', '0', '0', '0', '0', '64', '0'); +INSERT INTO `spell_proc_event` VALUES ('25906', '0', '0', '0', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('25926', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('25937', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('25942', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('25945', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('25988', '0', '0', '0', '0', '4263936', '0'); +INSERT INTO `spell_proc_event` VALUES ('26016', '0', '0', '0', '0', '1', '2'); +INSERT INTO `spell_proc_event` VALUES ('26021', '0', '0', '0', '0', '1', '2'); +INSERT INTO `spell_proc_event` VALUES ('26107', '0', '0', '0', '4063232', '67108864', '0'); +INSERT INTO `spell_proc_event` VALUES ('26119', '0', '0', '0', '-1877999613', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('26128', '0', '0', '0', '0', '33554432', '0'); +INSERT INTO `spell_proc_event` VALUES ('26135', '0', '0', '0', '8388608', '16384', '0'); +INSERT INTO `spell_proc_event` VALUES ('26169', '0', '0', '0', '0', '134217728', '0'); +INSERT INTO `spell_proc_event` VALUES ('26341', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('26376', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('26463', '0', '0', '0', '0', '1048576', '0'); +INSERT INTO `spell_proc_event` VALUES ('26467', '0', '0', '0', '0', '134217728', '0'); +INSERT INTO `spell_proc_event` VALUES ('26480', '0', '0', '0', '0', '524289', '3'); +INSERT INTO `spell_proc_event` VALUES ('27200', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('27419', '0', '0', '0', '0', '1', '3'); +INSERT INTO `spell_proc_event` VALUES ('27420', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('27498', '0', '0', '0', '0', '1', '3'); +INSERT INTO `spell_proc_event` VALUES ('27521', '0', '0', '0', '0', '16384', '0'); +INSERT INTO `spell_proc_event` VALUES ('27522', '0', '0', '0', '0', '524289', '0'); +INSERT INTO `spell_proc_event` VALUES ('27539', '0', '0', '0', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('27561', '0', '0', '0', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('27656', '0', '0', '0', '0', '1', '3'); +INSERT INTO `spell_proc_event` VALUES ('27688', '0', '0', '0', '0', '1049602', '0'); +INSERT INTO `spell_proc_event` VALUES ('27774', '0', '0', '0', '0', '16384', '0'); +INSERT INTO `spell_proc_event` VALUES ('27776', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('27778', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('27780', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('27781', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('27785', '0', '0', '0', '0', '524288', '0'); +INSERT INTO `spell_proc_event` VALUES ('27787', '0', '0', '0', '0', '1', '3'); +INSERT INTO `spell_proc_event` VALUES ('27811', '0', '0', '0', '0', '8396800', '0'); +INSERT INTO `spell_proc_event` VALUES ('27815', '0', '0', '0', '0', '8396800', '0'); +INSERT INTO `spell_proc_event` VALUES ('27816', '0', '0', '0', '0', '8396800', '0'); +INSERT INTO `spell_proc_event` VALUES ('27852', '0', '0', '0', '0', '32768', '0'); +INSERT INTO `spell_proc_event` VALUES ('27857', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('27861', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('27863', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('27864', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('27865', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('27867', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('28130', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('28200', '0', '0', '0', '0', '134217728', '0'); +INSERT INTO `spell_proc_event` VALUES ('28429', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('28458', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('28460', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('28592', '8', '0', '0', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('28593', '8', '0', '0', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('28594', '8', '0', '0', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('28595', '8', '0', '0', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('28719', '4', '0', '0', '32', '268435456', '0'); +INSERT INTO `spell_proc_event` VALUES ('28752', '0', '0', '0', '0', '4194304', '0'); +INSERT INTO `spell_proc_event` VALUES ('28761', '0', '0', '0', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('28764', '0', '0', '0', '0', '1048576', '0'); +INSERT INTO `spell_proc_event` VALUES ('28771', '0', '0', '0', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('28789', '0', '0', '0', '-1073717248', '134217728', '0'); +INSERT INTO `spell_proc_event` VALUES ('28802', '0', '0', '0', '0', '16384', '0'); +INSERT INTO `spell_proc_event` VALUES ('28809', '1', '0', '56', '4096', '268435456', '0'); +INSERT INTO `spell_proc_event` VALUES ('28812', '0', '0', '0', '0', '65536', '0'); +INSERT INTO `spell_proc_event` VALUES ('28816', '0', '0', '0', '0', '1', '3'); +INSERT INTO `spell_proc_event` VALUES ('28823', '4', '0', '374', '192', '134217728', '0'); +INSERT INTO `spell_proc_event` VALUES ('28845', '0', '0', '0', '0', '512', '0'); +INSERT INTO `spell_proc_event` VALUES ('28847', '4', '0', '573', '32', '16384', '0'); +INSERT INTO `spell_proc_event` VALUES ('28849', '4', '0', '374', '128', '16384', '0'); +INSERT INTO `spell_proc_event` VALUES ('28881', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('29062', '0', '0', '0', '0', '8396800', '0'); +INSERT INTO `spell_proc_event` VALUES ('29064', '0', '0', '0', '0', '8396800', '0'); +INSERT INTO `spell_proc_event` VALUES ('29065', '0', '0', '0', '0', '8396800', '0'); +INSERT INTO `spell_proc_event` VALUES ('29074', '10', '0', '0', '0', '65536', '0'); +INSERT INTO `spell_proc_event` VALUES ('29075', '10', '0', '0', '0', '65536', '0'); +INSERT INTO `spell_proc_event` VALUES ('29076', '10', '0', '0', '0', '65536', '0'); +INSERT INTO `spell_proc_event` VALUES ('29150', '0', '0', '0', '0', '1', '3'); +INSERT INTO `spell_proc_event` VALUES ('29162', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('29179', '0', '0', '0', '0', '65536', '0'); +INSERT INTO `spell_proc_event` VALUES ('29180', '0', '0', '0', '0', '65536', '0'); +INSERT INTO `spell_proc_event` VALUES ('29185', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('29194', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('29196', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('29198', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('29220', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('29307', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('29441', '0', '0', '0', '0', '16777216', '0'); +INSERT INTO `spell_proc_event` VALUES ('29444', '0', '0', '0', '0', '16777216', '0'); +INSERT INTO `spell_proc_event` VALUES ('29445', '0', '0', '0', '0', '16777216', '0'); +INSERT INTO `spell_proc_event` VALUES ('29446', '0', '0', '0', '0', '16777216', '0'); +INSERT INTO `spell_proc_event` VALUES ('29447', '0', '0', '0', '0', '16777216', '0'); +INSERT INTO `spell_proc_event` VALUES ('29501', '0', '0', '0', '0', '524288', '3'); +INSERT INTO `spell_proc_event` VALUES ('29526', '0', '0', '0', '0', '0', '0'); +INSERT INTO `spell_proc_event` VALUES ('29624', '0', '0', '0', '0', '524288', '3'); +INSERT INTO `spell_proc_event` VALUES ('29625', '0', '0', '0', '0', '524288', '3'); +INSERT INTO `spell_proc_event` VALUES ('29626', '0', '0', '0', '0', '524288', '3'); +INSERT INTO `spell_proc_event` VALUES ('29632', '0', '0', '0', '0', '524288', '3'); +INSERT INTO `spell_proc_event` VALUES ('29633', '0', '0', '0', '0', '524288', '3'); +INSERT INTO `spell_proc_event` VALUES ('29634', '0', '0', '0', '0', '524288', '3'); +INSERT INTO `spell_proc_event` VALUES ('29635', '0', '0', '0', '0', '524288', '3'); +INSERT INTO `spell_proc_event` VALUES ('29636', '0', '0', '0', '0', '524288', '3'); +INSERT INTO `spell_proc_event` VALUES ('29637', '0', '0', '0', '0', '524288', '3'); +INSERT INTO `spell_proc_event` VALUES ('30079', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('30080', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('30081', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('30160', '0', '0', '0', '0', '65536', '0'); +INSERT INTO `spell_proc_event` VALUES ('30802', '0', '0', '0', '0', '4096', '0'); +INSERT INTO `spell_proc_event` VALUES ('30808', '0', '0', '0', '0', '4096', '0'); +INSERT INTO `spell_proc_event` VALUES ('30809', '0', '0', '0', '0', '4096', '0'); +INSERT INTO `spell_proc_event` VALUES ('30810', '0', '0', '0', '0', '4096', '0'); +INSERT INTO `spell_proc_event` VALUES ('30811', '0', '0', '0', '0', '4096', '0'); +INSERT INTO `spell_proc_event` VALUES ('31255', '0', '0', '0', '0', '256', '0'); +INSERT INTO `spell_proc_event` VALUES ('31316', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('25020', '0', '0', '0', '0', '1026', '0'); +INSERT INTO `spell_proc_event` VALUES ('25023', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('24949', '0', '0', '0', '0', '32', '0'); +INSERT INTO `spell_proc_event` VALUES ('24658', '0', '0', '0', '0', '16384', '0'); +INSERT INTO `spell_proc_event` VALUES ('24661', '0', '0', '0', '0', '524289', '0'); +INSERT INTO `spell_proc_event` VALUES ('24574', '0', '0', '0', '0', '1048578', '0'); +INSERT INTO `spell_proc_event` VALUES ('24256', '0', '0', '0', '0', '524289', '0'); +INSERT INTO `spell_proc_event` VALUES ('24051', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('23888', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('23863', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('23867', '0', '0', '0', '0', '129', '0'); +INSERT INTO `spell_proc_event` VALUES ('23885', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('23886', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('23887', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('23771', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('23780', '0', '0', '0', '0', '1048578', '0'); +INSERT INTO `spell_proc_event` VALUES ('23721', '32', '0', '163', '2048', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('23686', '0', '0', '0', '0', '1', '2'); +INSERT INTO `spell_proc_event` VALUES ('23688', '0', '0', '0', '0', '16384', '0'); +INSERT INTO `spell_proc_event` VALUES ('23689', '0', '0', '0', '0', '1', '4'); +INSERT INTO `spell_proc_event` VALUES ('23695', '0', '0', '26', '2', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('23578', '0', '0', '0', '0', '524288', '2'); +INSERT INTO `spell_proc_event` VALUES ('23581', '0', '0', '0', '0', '1', '2'); +INSERT INTO `spell_proc_event` VALUES ('23548', '0', '0', '0', '0', '64', '0'); +INSERT INTO `spell_proc_event` VALUES ('23378', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('23305', '0', '0', '0', '0', '1048578', '0'); +INSERT INTO `spell_proc_event` VALUES ('23340', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('23255', '0', '0', '0', '0', '69632', '0'); +INSERT INTO `spell_proc_event` VALUES ('23301', '0', '0', '0', '0', '8192', '0'); +INSERT INTO `spell_proc_event` VALUES ('23303', '0', '0', '0', '0', '8192', '0'); +INSERT INTO `spell_proc_event` VALUES ('23306', '0', '0', '0', '0', '1048578', '0'); +INSERT INTO `spell_proc_event` VALUES ('22835', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('22857', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('22716', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('22618', '0', '0', '0', '0', '64', '0'); +INSERT INTO `spell_proc_event` VALUES ('22620', '0', '0', '0', '0', '64', '0'); +INSERT INTO `spell_proc_event` VALUES ('22648', '0', '0', '0', '0', '4096', '0'); +INSERT INTO `spell_proc_event` VALUES ('22438', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('22413', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('22283', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('22285', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('22286', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('22287', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('22288', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('21969', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('21911', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('21853', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('21882', '0', '0', '0', '0', '4096', '0'); +INSERT INTO `spell_proc_event` VALUES ('21890', '0', '0', '0', '-362127634', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('21788', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('21789', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('21897', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('21838', '0', '0', '0', '0', '32768', '0'); +INSERT INTO `spell_proc_event` VALUES ('21841', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('21645', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('21747', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('21387', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('21329', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('21334', '0', '0', '0', '0', '32768', '0'); +INSERT INTO `spell_proc_event` VALUES ('21185', '0', '0', '0', '0', '4', '0'); +INSERT INTO `spell_proc_event` VALUES ('21061', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('21080', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('21084', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('21053', '0', '0', '0', '0', '4', '0'); +INSERT INTO `spell_proc_event` VALUES ('20915', '0', '0', '0', '0', '1', '7'); +INSERT INTO `spell_proc_event` VALUES ('20918', '0', '0', '0', '0', '1', '7'); +INSERT INTO `spell_proc_event` VALUES ('20919', '0', '0', '0', '0', '1', '7'); +INSERT INTO `spell_proc_event` VALUES ('20920', '0', '0', '0', '0', '1', '7'); +INSERT INTO `spell_proc_event` VALUES ('20925', '0', '0', '0', '0', '64', '0'); +INSERT INTO `spell_proc_event` VALUES ('20927', '0', '0', '0', '0', '64', '0'); +INSERT INTO `spell_proc_event` VALUES ('20928', '0', '0', '0', '0', '64', '0'); +INSERT INTO `spell_proc_event` VALUES ('20884', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('20891', '0', '0', '0', '0', '4096', '0'); +INSERT INTO `spell_proc_event` VALUES ('20896', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('20847', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('20809', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('20705', '0', '0', '0', '0', '8192', '0'); +INSERT INTO `spell_proc_event` VALUES ('20725', '0', '0', '0', '0', '4096', '0'); +INSERT INTO `spell_proc_event` VALUES ('20563', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('20545', '0', '0', '0', '0', '1026', '0'); +INSERT INTO `spell_proc_event` VALUES ('20500', '0', '0', '0', '268435456', '16384', '0'); +INSERT INTO `spell_proc_event` VALUES ('20501', '0', '0', '0', '268435456', '16384', '0'); +INSERT INTO `spell_proc_event` VALUES ('20423', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('20422', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('20344', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('20345', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('20347', '0', '0', '0', '0', '1', '5'); +INSERT INTO `spell_proc_event` VALUES ('20348', '0', '0', '0', '0', '1', '5'); +INSERT INTO `spell_proc_event` VALUES ('20346', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('20349', '0', '0', '0', '0', '1', '5'); +INSERT INTO `spell_proc_event` VALUES ('20356', '0', '0', '0', '0', '1', '5'); +INSERT INTO `spell_proc_event` VALUES ('20357', '0', '0', '0', '0', '1', '5'); +INSERT INTO `spell_proc_event` VALUES ('20375', '0', '0', '0', '0', '1', '7'); +INSERT INTO `spell_proc_event` VALUES ('20354', '0', '0', '0', '0', '1049602', '0'); +INSERT INTO `spell_proc_event` VALUES ('20355', '0', '0', '0', '0', '1049602', '0'); +INSERT INTO `spell_proc_event` VALUES ('20419', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('20421', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('20287', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('20288', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('20289', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('20290', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('20291', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('20292', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('20293', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('20210', '0', '0', '0', '0', '65536', '0'); +INSERT INTO `spell_proc_event` VALUES ('20212', '0', '0', '0', '0', '65536', '0'); +INSERT INTO `spell_proc_event` VALUES ('20213', '0', '0', '0', '0', '65536', '0'); +INSERT INTO `spell_proc_event` VALUES ('20214', '0', '0', '0', '0', '65536', '0'); +INSERT INTO `spell_proc_event` VALUES ('20215', '0', '0', '0', '0', '65536', '0'); +INSERT INTO `spell_proc_event` VALUES ('20179', '0', '0', '0', '0', '270336', '0'); +INSERT INTO `spell_proc_event` VALUES ('20180', '0', '0', '0', '0', '270336', '0'); +INSERT INTO `spell_proc_event` VALUES ('20181', '0', '0', '0', '0', '270336', '0'); +INSERT INTO `spell_proc_event` VALUES ('20182', '0', '0', '0', '0', '270336', '0'); +INSERT INTO `spell_proc_event` VALUES ('20185', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('20186', '0', '0', '0', '0', '1049602', '0'); +INSERT INTO `spell_proc_event` VALUES ('20230', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('20234', '1', '0', '0', '32768', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('20235', '0', '0', '0', '32768', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('20135', '0', '0', '0', '0', '270336', '0'); +INSERT INTO `spell_proc_event` VALUES ('20136', '0', '0', '0', '0', '270336', '0'); +INSERT INTO `spell_proc_event` VALUES ('20137', '0', '0', '0', '0', '270336', '0'); +INSERT INTO `spell_proc_event` VALUES ('20154', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('20163', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('20164', '0', '0', '0', '0', '1', '2'); +INSERT INTO `spell_proc_event` VALUES ('20165', '0', '0', '0', '0', '1', '5'); +INSERT INTO `spell_proc_event` VALUES ('20166', '0', '0', '0', '0', '1', '5'); +INSERT INTO `spell_proc_event` VALUES ('20169', '0', '0', '0', '0', '64', '0'); +INSERT INTO `spell_proc_event` VALUES ('20127', '0', '0', '0', '0', '270336', '0'); +INSERT INTO `spell_proc_event` VALUES ('20130', '0', '0', '0', '0', '270336', '0'); +INSERT INTO `spell_proc_event` VALUES ('20049', '0', '0', '0', '0', '69632', '0'); +INSERT INTO `spell_proc_event` VALUES ('20056', '0', '0', '0', '0', '69632', '0'); +INSERT INTO `spell_proc_event` VALUES ('20057', '0', '0', '0', '0', '69632', '0'); +INSERT INTO `spell_proc_event` VALUES ('20058', '0', '0', '0', '0', '69632', '0'); +INSERT INTO `spell_proc_event` VALUES ('20059', '0', '0', '0', '0', '69632', '0'); +INSERT INTO `spell_proc_event` VALUES ('20177', '0', '0', '0', '0', '270336', '0'); +INSERT INTO `spell_proc_event` VALUES ('19817', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('19818', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('19640', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('19655', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('19656', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('19660', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('19577', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('19514', '0', '0', '0', '0', '1026', '0'); +INSERT INTO `spell_proc_event` VALUES ('19449', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('19396', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('19407', '32', '0', '0', '512', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('19409', '0', '0', '0', '0', '1048578', '0'); +INSERT INTO `spell_proc_event` VALUES ('19412', '32', '0', '0', '512', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('19413', '32', '0', '0', '512', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('19414', '32', '0', '0', '512', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('19415', '32', '0', '0', '512', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('19478', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('19387', '0', '0', '0', '0', '2097152', '0'); +INSERT INTO `spell_proc_event` VALUES ('19388', '0', '0', '0', '0', '2097152', '0'); +INSERT INTO `spell_proc_event` VALUES ('19389', '0', '0', '0', '0', '2097152', '0'); +INSERT INTO `spell_proc_event` VALUES ('19390', '0', '0', '0', '0', '2097152', '0'); +INSERT INTO `spell_proc_event` VALUES ('19308', '0', '0', '0', '0', '1049602', '0'); +INSERT INTO `spell_proc_event` VALUES ('19309', '0', '0', '0', '0', '1049602', '0'); +INSERT INTO `spell_proc_event` VALUES ('19310', '0', '0', '0', '0', '1049602', '0'); +INSERT INTO `spell_proc_event` VALUES ('19311', '0', '0', '0', '0', '1049602', '0'); +INSERT INTO `spell_proc_event` VALUES ('19312', '0', '0', '0', '0', '1049602', '0'); +INSERT INTO `spell_proc_event` VALUES ('19261', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('19262', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('19264', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('19265', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('19266', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('19194', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('19195', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('19233', '0', '0', '0', '64', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('19234', '0', '0', '0', '64', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('19235', '0', '0', '0', '64', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('19228', '0', '0', '0', '64', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('19232', '0', '0', '0', '64', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('19184', '0', '0', '0', '0', '2097152', '0'); +INSERT INTO `spell_proc_event` VALUES ('18979', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('18983', '0', '0', '0', '0', '4', '0'); +INSERT INTO `spell_proc_event` VALUES ('18943', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('18799', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('18800', '0', '0', '0', '0', '8', '0'); +INSERT INTO `spell_proc_event` VALUES ('18815', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('18816', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('18847', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('18765', '0', '0', '0', '0', '128', '0'); +INSERT INTO `spell_proc_event` VALUES ('18542', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('18186', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('18189', '6', '0', '0', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('18121', '0', '0', '593', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('18122', '0', '0', '593', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('18123', '0', '0', '593', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('18137', '0', '0', '0', '0', '1049602', '0'); +INSERT INTO `spell_proc_event` VALUES ('18146', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('18167', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('18119', '0', '0', '593', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('18120', '0', '0', '593', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('18097', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('18100', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('17793', '16', '0', '593', '1', '65536', '0'); +INSERT INTO `spell_proc_event` VALUES ('17796', '16', '0', '593', '1', '65536', '0'); +INSERT INTO `spell_proc_event` VALUES ('17801', '16', '0', '593', '1', '65536', '0'); +INSERT INTO `spell_proc_event` VALUES ('17802', '16', '0', '593', '1', '65536', '0'); +INSERT INTO `spell_proc_event` VALUES ('17803', '16', '0', '593', '1', '65536', '0'); +INSERT INTO `spell_proc_event` VALUES ('17688', '0', '0', '0', '0', '128', '0'); +INSERT INTO `spell_proc_event` VALUES ('17690', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('17670', '0', '0', '0', '0', '8', '0'); +INSERT INTO `spell_proc_event` VALUES ('17495', '0', '0', '0', '0', '64', '0'); +INSERT INTO `spell_proc_event` VALUES ('17329', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('17332', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('17350', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('17082', '0', '0', '0', '524288', '16384', '0'); +INSERT INTO `spell_proc_event` VALUES ('17079', '0', '0', '0', '524288', '16384', '0'); +INSERT INTO `spell_proc_event` VALUES ('17000', '0', '0', '0', '131072', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('17001', '0', '0', '0', '131072', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('17010', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('16956', '0', '0', '0', '0', '65536', '0'); +INSERT INTO `spell_proc_event` VALUES ('16957', '0', '0', '0', '0', '65536', '0'); +INSERT INTO `spell_proc_event` VALUES ('16958', '0', '0', '0', '0', '69632', '0'); +INSERT INTO `spell_proc_event` VALUES ('16961', '0', '0', '0', '0', '69632', '0'); +INSERT INTO `spell_proc_event` VALUES ('16962', '0', '0', '0', '0', '69632', '0'); +INSERT INTO `spell_proc_event` VALUES ('16963', '0', '0', '0', '0', '69632', '0'); +INSERT INTO `spell_proc_event` VALUES ('16964', '0', '0', '0', '0', '69632', '0'); +INSERT INTO `spell_proc_event` VALUES ('16982', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('16923', '0', '0', '574', '4', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('16924', '0', '0', '574', '4', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('16925', '0', '0', '574', '4', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('16926', '0', '0', '574', '4', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('16952', '0', '0', '0', '233472', '65536', '0'); +INSERT INTO `spell_proc_event` VALUES ('16954', '0', '0', '0', '233472', '65536', '0'); +INSERT INTO `spell_proc_event` VALUES ('16955', '0', '0', '0', '233472', '65536', '0'); +INSERT INTO `spell_proc_event` VALUES ('16880', '0', '0', '0', '0', '268500992', '0'); +INSERT INTO `spell_proc_event` VALUES ('16850', '0', '0', '574', '4', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('16864', '0', '0', '0', '0', '1', '6'); +INSERT INTO `spell_proc_event` VALUES ('16800', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('16810', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('16811', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('16812', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('16813', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('16792', '0', '0', '0', '0', '8192', '0'); +INSERT INTO `spell_proc_event` VALUES ('16843', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('16689', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('16624', '0', '0', '0', '0', '64', '0'); +INSERT INTO `spell_proc_event` VALUES ('16611', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('16615', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('16620', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('16550', '0', '0', '0', '0', '8192', '0'); +INSERT INTO `spell_proc_event` VALUES ('16563', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('16574', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('16575', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('16487', '0', '0', '0', '0', '8658944', '0'); +INSERT INTO `spell_proc_event` VALUES ('16489', '0', '0', '0', '0', '8658944', '0'); +INSERT INTO `spell_proc_event` VALUES ('16492', '0', '0', '0', '0', '8658944', '0'); +INSERT INTO `spell_proc_event` VALUES ('16423', '0', '0', '0', '0', '128', '0'); +INSERT INTO `spell_proc_event` VALUES ('16428', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('16281', '0', '0', '0', '0', '4096', '0'); +INSERT INTO `spell_proc_event` VALUES ('16282', '0', '0', '0', '0', '4096', '0'); +INSERT INTO `spell_proc_event` VALUES ('16283', '0', '0', '0', '0', '4096', '0'); +INSERT INTO `spell_proc_event` VALUES ('16284', '0', '0', '0', '0', '4096', '0'); +INSERT INTO `spell_proc_event` VALUES ('16311', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('16312', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('16313', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('16235', '0', '0', '0', '0', '268435456', '0'); +INSERT INTO `spell_proc_event` VALUES ('16240', '0', '0', '0', '0', '268435456', '0'); +INSERT INTO `spell_proc_event` VALUES ('16241', '0', '0', '0', '0', '268435456', '0'); +INSERT INTO `spell_proc_event` VALUES ('16242', '0', '0', '0', '0', '268435456', '0'); +INSERT INTO `spell_proc_event` VALUES ('16247', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('16256', '0', '0', '0', '0', '4096', '0'); +INSERT INTO `spell_proc_event` VALUES ('16164', '14', '0', '0', '0', '16384', '0'); +INSERT INTO `spell_proc_event` VALUES ('16176', '0', '0', '0', '0', '268435456', '0'); +INSERT INTO `spell_proc_event` VALUES ('16140', '0', '0', '0', '0', '128', '0'); +INSERT INTO `spell_proc_event` VALUES ('16142', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('16146', '0', '0', '0', '0', '2048', '0'); +INSERT INTO `spell_proc_event` VALUES ('16092', '0', '0', '0', '0', '32', '0'); +INSERT INTO `spell_proc_event` VALUES ('15978', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('15876', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('15852', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('15784', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('15730', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('15733', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('15849', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('15636', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('15641', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('15644', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('15650', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('15567', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('15568', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('15569', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('15573', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('15594', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('15599', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('15600', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('15506', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('15507', '0', '0', '0', '0', '1026', '0'); +INSERT INTO `spell_proc_event` VALUES ('15603', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('15362', '1', '0', '56', '7680', '268435456', '0'); +INSERT INTO `spell_proc_event` VALUES ('15363', '1', '0', '56', '7680', '268435456', '0'); +INSERT INTO `spell_proc_event` VALUES ('15364', '1', '0', '56', '7680', '268435456', '0'); +INSERT INTO `spell_proc_event` VALUES ('15365', '1', '0', '56', '7680', '268435456', '0'); +INSERT INTO `spell_proc_event` VALUES ('15323', '16', '0', '0', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('15324', '16', '0', '0', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('15325', '16', '0', '0', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('15326', '16', '0', '0', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('15335', '0', '0', '0', '0', '4', '0'); +INSERT INTO `spell_proc_event` VALUES ('15336', '0', '0', '0', '0', '4', '0'); +INSERT INTO `spell_proc_event` VALUES ('15337', '0', '0', '0', '0', '4', '0'); +INSERT INTO `spell_proc_event` VALUES ('15338', '0', '0', '0', '0', '4', '0'); +INSERT INTO `spell_proc_event` VALUES ('15346', '0', '0', '0', '0', '1', '6'); +INSERT INTO `spell_proc_event` VALUES ('15268', '16', '0', '0', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('15270', '0', '0', '0', '0', '4', '0'); +INSERT INTO `spell_proc_event` VALUES ('15277', '0', '0', '0', '0', '1', '6'); +INSERT INTO `spell_proc_event` VALUES ('15088', '0', '0', '0', '0', '4096', '0'); +INSERT INTO `spell_proc_event` VALUES ('15097', '0', '0', '0', '0', '8192', '0'); +INSERT INTO `spell_proc_event` VALUES ('14892', '1', '0', '56', '7680', '268435456', '0'); +INSERT INTO `spell_proc_event` VALUES ('14796', '0', '0', '0', '0', '2048', '0'); +INSERT INTO `spell_proc_event` VALUES ('14869', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('14774', '0', '0', '0', '0', '8192', '0'); +INSERT INTO `spell_proc_event` VALUES ('14531', '0', '0', '0', '0', '8192', '0'); +INSERT INTO `spell_proc_event` VALUES ('14186', '0', '0', '0', '1082131720', '65536', '0'); +INSERT INTO `spell_proc_event` VALUES ('14190', '0', '0', '0', '1082131720', '65536', '0'); +INSERT INTO `spell_proc_event` VALUES ('14193', '0', '0', '0', '1082131720', '65536', '0'); +INSERT INTO `spell_proc_event` VALUES ('14194', '0', '0', '0', '1082131720', '65536', '0'); +INSERT INTO `spell_proc_event` VALUES ('14195', '0', '0', '0', '1082131720', '65536', '0'); +INSERT INTO `spell_proc_event` VALUES ('14144', '0', '0', '0', '0', '4', '0'); +INSERT INTO `spell_proc_event` VALUES ('14148', '0', '0', '0', '0', '4', '0'); +INSERT INTO `spell_proc_event` VALUES ('14150', '0', '0', '0', '0', '4', '0'); +INSERT INTO `spell_proc_event` VALUES ('14152', '0', '0', '0', '0', '4', '0'); +INSERT INTO `spell_proc_event` VALUES ('14154', '0', '0', '0', '0', '4', '0'); +INSERT INTO `spell_proc_event` VALUES ('14156', '0', '0', '0', '4063232', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('14160', '0', '0', '0', '4063232', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('14161', '0', '0', '0', '4063232', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('14178', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('14108', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('14111', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('14133', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('14070', '0', '0', '0', '0', '16', '0'); +INSERT INTO `spell_proc_event` VALUES ('14071', '0', '0', '0', '0', '16', '0'); +INSERT INTO `spell_proc_event` VALUES ('13983', '0', '0', '0', '0', '16', '0'); +INSERT INTO `spell_proc_event` VALUES ('13987', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('13959', '0', '0', '0', '0', '1048578', '0'); +INSERT INTO `spell_proc_event` VALUES ('13960', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('13961', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('13962', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('13963', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('13964', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('13867', '0', '88', '0', '16', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('13879', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('13886', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('13754', '0', '88', '0', '16', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('13767', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('13800', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('13801', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('13802', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('13803', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('13709', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('13716', '0', '0', '0', '0', '1026', '0'); +INSERT INTO `spell_proc_event` VALUES ('13616', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('13585', '0', '0', '0', '0', '1026', '0'); +INSERT INTO `spell_proc_event` VALUES ('13483', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('13358', '0', '0', '0', '0', '16', '0'); +INSERT INTO `spell_proc_event` VALUES ('13260', '0', '0', '0', '0', '128', '0'); +INSERT INTO `spell_proc_event` VALUES ('13299', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('13320', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('13045', '0', '0', '0', '0', '8658944', '0'); +INSERT INTO `spell_proc_event` VALUES ('13046', '0', '0', '0', '0', '8658944', '0'); +INSERT INTO `spell_proc_event` VALUES ('13047', '0', '0', '0', '0', '8658944', '0'); +INSERT INTO `spell_proc_event` VALUES ('13048', '0', '0', '0', '0', '8658944', '0'); +INSERT INTO `spell_proc_event` VALUES ('13078', '0', '0', '0', '0', '4', '0'); +INSERT INTO `spell_proc_event` VALUES ('13159', '0', '0', '0', '0', '32768', '0'); +INSERT INTO `spell_proc_event` VALUES ('12999', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('13000', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('13001', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('13002', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('12947', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('12958', '0', '88', '257', '2048', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('12971', '0', '0', '0', '0', '69632', '0'); +INSERT INTO `spell_proc_event` VALUES ('12972', '0', '0', '0', '0', '69632', '0'); +INSERT INTO `spell_proc_event` VALUES ('12973', '0', '0', '0', '0', '69632', '0'); +INSERT INTO `spell_proc_event` VALUES ('12974', '0', '0', '0', '0', '69632', '0'); +INSERT INTO `spell_proc_event` VALUES ('12849', '0', '0', '0', '0', '69632', '0'); +INSERT INTO `spell_proc_event` VALUES ('12787', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('12799', '0', '65', '257', '1024', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('12800', '0', '65', '257', '1024', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('12812', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('12813', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('12814', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('12815', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('12834', '0', '0', '0', '0', '69632', '0'); +INSERT INTO `spell_proc_event` VALUES ('12782', '0', '0', '0', '0', '64', '0'); +INSERT INTO `spell_proc_event` VALUES ('12724', '0', '0', '0', '0', '64', '0'); +INSERT INTO `spell_proc_event` VALUES ('12725', '0', '0', '0', '0', '64', '0'); +INSERT INTO `spell_proc_event` VALUES ('12726', '0', '0', '0', '0', '64', '0'); +INSERT INTO `spell_proc_event` VALUES ('12727', '0', '0', '0', '0', '64', '0'); +INSERT INTO `spell_proc_event` VALUES ('12797', '0', '65', '257', '1024', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('12867', '0', '0', '0', '0', '69632', '0'); +INSERT INTO `spell_proc_event` VALUES ('12701', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('12702', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('12703', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('12704', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('12668', '0', '0', '26', '2', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('12598', '0', '88', '237', '16384', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('12544', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('12546', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('12550', '0', '0', '0', '0', '1026', '0'); +INSERT INTO `spell_proc_event` VALUES ('12552', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('12556', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('12574', '0', '0', '0', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('12575', '0', '0', '0', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('12576', '0', '0', '0', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('12577', '0', '0', '0', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('12529', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('12539', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('12357', '2', '0', '0', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('12358', '2', '0', '0', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('12359', '2', '0', '0', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('12360', '2', '0', '0', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('12311', '0', '88', '257', '2048', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('12317', '0', '0', '0', '0', '8658944', '0'); +INSERT INTO `spell_proc_event` VALUES ('12319', '0', '0', '0', '0', '69632', '0'); +INSERT INTO `spell_proc_event` VALUES ('12322', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('12246', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('12254', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('12281', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('12284', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('12289', '0', '0', '26', '2', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('12292', '0', '0', '0', '0', '128', '0'); +INSERT INTO `spell_proc_event` VALUES ('12298', '0', '0', '0', '0', '64', '0'); +INSERT INTO `spell_proc_event` VALUES ('12094', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('11984', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('12099', '0', '0', '0', '0', '64', '0'); +INSERT INTO `spell_proc_event` VALUES ('11919', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('11959', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('11961', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('11964', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('12002', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('12038', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('11830', '0', '0', '0', '0', '128', '0'); +INSERT INTO `spell_proc_event` VALUES ('11838', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('11441', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('11371', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('11255', '0', '0', '237', '16384', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('11213', '0', '0', '0', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('11103', '2', '0', '0', '0', '131072', '0'); +INSERT INTO `spell_proc_event` VALUES ('10868', '0', '0', '0', '0', '2048', '0'); +INSERT INTO `spell_proc_event` VALUES ('10727', '0', '0', '0', '0', '1026', '0'); +INSERT INTO `spell_proc_event` VALUES ('10431', '0', '0', '0', '0', '1049602', '0'); +INSERT INTO `spell_proc_event` VALUES ('10432', '0', '0', '0', '0', '1049602', '0'); +INSERT INTO `spell_proc_event` VALUES ('10400', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('10219', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('10220', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('10092', '0', '0', '0', '0', '128', '0'); +INSERT INTO `spell_proc_event` VALUES ('10095', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('10022', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('9793', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('9778', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('9782', '0', '0', '0', '0', '64', '0'); +INSERT INTO `spell_proc_event` VALUES ('9784', '0', '0', '0', '0', '64', '0'); +INSERT INTO `spell_proc_event` VALUES ('9797', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('9801', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('9808', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('9460', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('9463', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('9276', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('9205', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('9233', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('9160', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('9084', '0', '0', '0', '0', '8', '0'); +INSERT INTO `spell_proc_event` VALUES ('8981', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('8852', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('8876', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('8788', '0', '0', '0', '0', '1026', '0'); +INSERT INTO `spell_proc_event` VALUES ('8612', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('8601', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('8397', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('8247', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('8224', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('8134', '0', '0', '0', '0', '1049602', '0'); +INSERT INTO `spell_proc_event` VALUES ('7999', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('7849', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('7806', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('7807', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('7808', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('7721', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('7722', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('7723', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('7724', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('7725', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('7726', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('7711', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('7601', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('7614', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('7615', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('7616', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('7617', '0', '0', '0', '0', '1048578', '0'); +INSERT INTO `spell_proc_event` VALUES ('7618', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('7619', '0', '0', '0', '0', '1048578', '0'); +INSERT INTO `spell_proc_event` VALUES ('7445', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('7446', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('7276', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('7300', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('7301', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('7302', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('7320', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('7486', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('7095', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('7098', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('7102', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('7103', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('7137', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('6909', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('6921', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('6923', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('6947', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('6961', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('6867', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('6871', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('6750', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('6752', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('6645', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('6592', '0', '0', '0', '0', '1138', '0'); +INSERT INTO `spell_proc_event` VALUES ('6593', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('6433', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('6134', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('6135', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('5976', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5977', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5979', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5811', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('5751', '0', '0', '0', '0', '2048', '0'); +INSERT INTO `spell_proc_event` VALUES ('5752', '0', '0', '0', '0', '2049', '0'); +INSERT INTO `spell_proc_event` VALUES ('5753', '0', '0', '0', '0', '2048', '0'); +INSERT INTO `spell_proc_event` VALUES ('5754', '0', '0', '0', '0', '2048', '0'); +INSERT INTO `spell_proc_event` VALUES ('5755', '0', '0', '0', '0', '2048', '0'); +INSERT INTO `spell_proc_event` VALUES ('5756', '0', '0', '0', '0', '2048', '0'); +INSERT INTO `spell_proc_event` VALUES ('5680', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5638', '0', '0', '0', '0', '2048', '0'); +INSERT INTO `spell_proc_event` VALUES ('5639', '0', '0', '0', '0', '2048', '0'); +INSERT INTO `spell_proc_event` VALUES ('5640', '0', '0', '0', '0', '2048', '0'); +INSERT INTO `spell_proc_event` VALUES ('5641', '0', '0', '0', '0', '2048', '0'); +INSERT INTO `spell_proc_event` VALUES ('5642', '0', '0', '0', '0', '2048', '0'); +INSERT INTO `spell_proc_event` VALUES ('5643', '0', '0', '0', '0', '2048', '0'); +INSERT INTO `spell_proc_event` VALUES ('5549', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5550', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5551', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5552', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5553', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5554', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5575', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5580', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5513', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5429', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5430', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5431', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5432', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5433', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5352', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5353', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5354', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5364', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('5368', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('5369', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('5427', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5370', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('5377', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5301', '0', '0', '0', '0', '112', '0'); +INSERT INTO `spell_proc_event` VALUES ('5341', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5342', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5343', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5344', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5345', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5346', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5349', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5350', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5351', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5262', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5202', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5205', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('5104', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('5118', '0', '0', '0', '0', '32768', '0'); +INSERT INTO `spell_proc_event` VALUES ('4932', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('4951', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('4525', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('4495', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('4496', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('4512', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('4387', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('4388', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('4389', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('4390', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('4315', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('4317', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('4493', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('4494', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('4279', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('4283', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('4284', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('4241', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('4242', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('4245', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('4144', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('4161', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('4112', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('4113', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('4114', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('4115', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('4133', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('4136', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('4138', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('4140', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('4142', '0', '0', '0', '0', '4', '0'); +INSERT INTO `spell_proc_event` VALUES ('4070', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('4051', '0', '0', '0', '0', '128', '0'); +INSERT INTO `spell_proc_event` VALUES ('3637', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('3582', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('3616', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('3509', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('3512', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('3424', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('3440', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('3436', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('3439', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('3394', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('3417', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('3418', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('3338', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('3284', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('3235', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('114', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('168', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('324', '0', '0', '0', '0', '1049602', '0'); +INSERT INTO `spell_proc_event` VALUES ('325', '0', '0', '0', '0', '1049602', '0'); +INSERT INTO `spell_proc_event` VALUES ('637', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('646', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('648', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('742', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('905', '0', '0', '0', '0', '1049602', '0'); +INSERT INTO `spell_proc_event` VALUES ('945', '0', '0', '0', '0', '1049602', '0'); +INSERT INTO `spell_proc_event` VALUES ('1028', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('1034', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('1048', '0', '0', '0', '0', '2', '0'); +INSERT INTO `spell_proc_event` VALUES ('1707', '5', '99', '0', '0', '16384', '0'); +INSERT INTO `spell_proc_event` VALUES ('2095', '0', '0', '0', '0', '1139', '0'); +INSERT INTO `spell_proc_event` VALUES ('2652', '0', '0', '0', '0', '1', '0'); +INSERT INTO `spell_proc_event` VALUES ('2689', '0', '0', '0', '0', '4', '0'); +INSERT INTO `spell_proc_event` VALUES ('2852', '0', '0', '0', '0', '2', '0'); diff --git a/sql/updates/0.6/3092_quest_template.sql b/sql/updates/0.6/3092_quest_template.sql new file mode 100644 index 00000000000..fb547e8040e --- /dev/null +++ b/sql/updates/0.6/3092_quest_template.sql @@ -0,0 +1,2 @@ +ALTER TABLE `quest_template` CHANGE `PrevQuestId` `PrevQuestId` int(11) NOT NULL default '0'; +ALTER TABLE `quest_template` CHANGE `NextQuestId` `NextQuestId` int(11) NOT NULL default '0'; \ No newline at end of file diff --git a/sql/updates/0.6/3096_spell_proc_event.sql b/sql/updates/0.6/3096_spell_proc_event.sql new file mode 100644 index 00000000000..3ee8d4f66e7 --- /dev/null +++ b/sql/updates/0.6/3096_spell_proc_event.sql @@ -0,0 +1 @@ +UPDATE `spell_proc_event` set `procFlags`=524288 where `entry` in (5638, 5639, 5640, 5641, 5642, 5643, 5751, 5752, 5753, 5754, 5755, 5756); diff --git a/sql/updates/0.6/3106_command.sql b/sql/updates/0.6/3106_command.sql new file mode 100644 index 00000000000..1f48ab806ec --- /dev/null +++ b/sql/updates/0.6/3106_command.sql @@ -0,0 +1,5 @@ +UPDATE `command` SET `help` = 'Syntax: .banaccount $name\r\n\r\nBan account $name (can be viewed by players by using the .pinfo command) and kick affected players currently logged in.' WHERE `name` = 'banaccount'; +UPDATE `command` SET `help` = 'Syntax: .banip #ip\r\n\r\nBans logging into the server from computers with the provided IP address, and kicks all affected players.' WHERE `name` = 'banip'; +UPDATE `command` SET `help` = 'Syntax: .unbanaccount $name\r\n\r\nUnban account $name.' WHERE `name` = 'unbanaccount'; +UPDATE `command` SET `help` = 'Syntax: .unbanip #ip\r\n\r\nUnban the provided IP address from the server.' WHERE `name` = 'unbanip'; +UPDATE `command` SET `help` = 'Syntax: .kick [$charactername]\r\n\r\nKick the given character name from the world. If no character name is provided then the selected player (except for yourself) will be kicked.' WHERE `name` = 'kick'; diff --git a/sql/updates/0.6/3107_playercreateinfo_skill.sql b/sql/updates/0.6/3107_playercreateinfo_skill.sql new file mode 100644 index 00000000000..9d2978ce3f5 --- /dev/null +++ b/sql/updates/0.6/3107_playercreateinfo_skill.sql @@ -0,0 +1,6 @@ +ALTER TABLE `playercreateinfo_skill` + MODIFY COLUMN `SkillMin` smallint(5) NOT NULL default '0', + MODIFY COLUMN `SkillMax` smallint(5) NOT NULL default '0'; + +UPDATE `playercreateinfo_skill` SET `SkillMin` = '-1' WHERE `SkillMin` = 300; +UPDATE `playercreateinfo_skill` SET `SkillMax` = '-1' WHERE `SkillMax` = 300; diff --git a/sql/updates/0.6/3108_quest_template.sql b/sql/updates/0.6/3108_quest_template.sql new file mode 100644 index 00000000000..1ab760fd668 --- /dev/null +++ b/sql/updates/0.6/3108_quest_template.sql @@ -0,0 +1,5 @@ +UPDATE `quest_template` SET `PrevQuestId`=`HaveQuestId` * '-1' WHERE `HaveQuestId`!='0' AND `PrevQuestId`='0'; +ALTER TABLE `quest_template` DROP `HaveQuestId`; + +ALTER TABLE `quest_template` ADD COLUMN `NextQuestInChain` int(11) unsigned NOT NULL default '0' AFTER `ExclusiveGroup`; +UPDATE `quest_template` SET `NextQuestInChain`=`NextQuestId` WHERE `NextQuestId`>'0'; \ No newline at end of file diff --git a/sql/updates/0.6/3110_quest_template.sql b/sql/updates/0.6/3110_quest_template.sql new file mode 100644 index 00000000000..c7cc4d7a2f3 --- /dev/null +++ b/sql/updates/0.6/3110_quest_template.sql @@ -0,0 +1,98 @@ +update `quest_template` set `RewRepFaction1` = +case `RewRepFaction1` + when 0 then 0 + when 11 then 72 + when 12 then 72 + when 23 then 54 + when 29 then 76 + when 55 then 47 + when 64 then 54 + when 68 then 68 + when 69 then 470 + when 79 then 69 + when 80 then 69 + when 83 then 67 + when 85 then 76 + when 104 then 81 + when 105 then 81 + when 118 then 68 + when 119 then 87 + when 120 then 21 + when 121 then 21 + when 126 then 530 + when 132 then 92 + when 133 then 93 + when 414 then 576 + when 471 then 349 + when 474 then 369 + when 534 then 469 + when 635 then 609 + when 694 then 471 + when 776 then 910 + when 794 then 529 + when 854 then 577 + when 874 then 589 + when 994 then 609 + when 1214 then 729 + when 1216 then 730 + when 1514 then 890 + when 1515 then 889 + when 1555 then 909 + when 1574 then 270 + when 1577 then 509 + when 1598 then 510 + when 1601 then 910 + when 1635 then 169 + + else `RewRepFaction1`*'-1' +end; + +update `quest_template` set `RewRepFaction2` = +case `RewRepFaction2` + when 0 then 0 + when 11 then 72 + when 12 then 72 + when 23 then 54 + when 29 then 76 + when 55 then 47 + when 64 then 54 + when 68 then 68 + when 69 then 470 + when 79 then 69 + when 80 then 69 + when 83 then 67 + when 85 then 76 + when 104 then 81 + when 105 then 81 + when 118 then 68 + when 119 then 87 + when 120 then 21 + when 121 then 21 + when 126 then 530 + when 132 then 92 + when 133 then 93 + when 414 then 576 + when 471 then 349 + when 474 then 369 + when 534 then 469 + when 635 then 609 + when 694 then 471 + when 776 then 910 + when 794 then 529 + when 854 then 577 + when 874 then 589 + when 994 then 609 + when 1214 then 729 + when 1216 then 730 + when 1514 then 890 + when 1515 then 889 + when 1555 then 909 + when 1574 then 270 + when 1577 then 509 + when 1598 then 510 + when 1601 then 910 + when 1635 then 169 + + else `RewRepFaction2`*'-1' +end; + diff --git a/sql/updates/0.6/3115_quest_template.sql b/sql/updates/0.6/3115_quest_template.sql new file mode 100644 index 00000000000..13afbd32250 --- /dev/null +++ b/sql/updates/0.6/3115_quest_template.sql @@ -0,0 +1,7 @@ +ALTER TABLE `quest_template` + ADD COLUMN `RewRepFaction3` int(11) unsigned NOT NULL default '0' AFTER `RewRepFaction2`, + ADD COLUMN `RewRepFaction4` int(11) unsigned NOT NULL default '0' AFTER `RewRepFaction3`, + ADD COLUMN `RewRepFaction5` int(11) unsigned NOT NULL default '0' AFTER `RewRepFaction4`, + ADD COLUMN `RewRepValue3` int(11) NOT NULL default '0' AFTER `RewRepValue2`, + ADD COLUMN `RewRepValue4` int(11) NOT NULL default '0' AFTER `RewRepValue3`, + ADD COLUMN `RewRepValue5` int(11) NOT NULL default '0' AFTER `RewRepValue4`; diff --git a/sql/updates/0.7/3138_character_inventory.sql b/sql/updates/0.7/3138_character_inventory.sql new file mode 100644 index 00000000000..bd4bbc47d5b --- /dev/null +++ b/sql/updates/0.7/3138_character_inventory.sql @@ -0,0 +1,2 @@ +ALTER TABLE character_inventory + ADD UNIQUE KEY `idx_item` (`item`); diff --git a/sql/updates/0.7/3138_disenchaning_loot_template.sql b/sql/updates/0.7/3138_disenchaning_loot_template.sql new file mode 100644 index 00000000000..2145e913a32 --- /dev/null +++ b/sql/updates/0.7/3138_disenchaning_loot_template.sql @@ -0,0 +1,11 @@ +DROP TABLE IF EXISTS `disenchant_loot_template`; +CREATE TABLE `disenchant_loot_template` ( + `entry` int(11) unsigned NOT NULL default '0', + `item` int(11) unsigned NOT NULL default '0', + `ChanceOrRef` float NOT NULL default '100', + `QuestChanceOrGroup` tinyint(3) NOT NULL default '0', + `mincount` tinyint(3) unsigned NOT NULL default '1', + `maxcount` tinyint(3) unsigned NOT NULL default '1', + `quest_freeforall` tinyint(3) unsigned NOT NULL default '1', + PRIMARY KEY (`entry`,`item`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Loot System'; diff --git a/sql/updates/0.7/3138_item_template.sql b/sql/updates/0.7/3138_item_template.sql new file mode 100644 index 00000000000..a32dc187afe --- /dev/null +++ b/sql/updates/0.7/3138_item_template.sql @@ -0,0 +1,2 @@ +ALTER TABLE `item_template` + ADD `DisenchantID` int(11) unsigned NOT NULL default '0'; diff --git a/sql/updates/0.7/3141_spell_threat.sql b/sql/updates/0.7/3141_spell_threat.sql new file mode 100644 index 00000000000..0f9737ccf24 --- /dev/null +++ b/sql/updates/0.7/3141_spell_threat.sql @@ -0,0 +1,19 @@ +DROP TABLE IF EXISTS `spell_threat`; +CREATE TABLE `spell_threat` ( + `entry` int(10) unsigned NOT NULL, + `Threat` int(11) NOT NULL, + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED; + +-- +-- Dumping data for table `spell_threat` +-- + +/*!40000 ALTER TABLE `spell_threat` DISABLE KEYS */; +INSERT INTO `spell_threat` (`entry`,`Threat`) VALUES + (1672,180),(9881,207),(11556,43),(11567,145),(11597,261),(11601,315),(11775,395),(14921,415),(24394,580),(24583,5), + (25286,175),(25288,355),(25289,60),(78,20),(284,39),(285,59),(1608,78),(11564,98),(11565,118),(11566,137),(7386,100),(7405,140), + (8380,180),(11596,220),(1715,61),(7372,101),(7373,141),(6572,155),(6574,195),(7379,235),(11600,275),(23922,160),(23923,190), + (23924,220),(23925,250),(6809,89),(8972,118),(9745,148),(9880,178),(770,108),(778,108),(9749,108),(9907,108), + (17735,200),(17750,300),(17751,450),(17752,600),(20736,100),(14274,200),(15629,300),(15630,400),(15631,500),(15632,600); +/*!40000 ALTER TABLE `spell_threat` ENABLE KEYS */; diff --git a/sql/updates/0.7/3144_command.sql b/sql/updates/0.7/3144_command.sql new file mode 100644 index 00000000000..cf333ff6b85 --- /dev/null +++ b/sql/updates/0.7/3144_command.sql @@ -0,0 +1,5 @@ +INSERT INTO `command` (`name`,`security`,`help`) VALUES ('.lookupobject',3,'Syntax: .lookupobject $objname\r\n\r\nLooks up an gameobject by $objname, and returns all matches with their Gameobject ID\'s.'); +INSERT INTO `command` (`name`,`security`,`help`) VALUES ('.listcreature',3,'Syntax: .listcreature #creature_id [#max_count]\r\n\r\nOutput creatures with creature id #creature_id found in world. Output creature guids and coordinates sorted by distance from character. Will be output maximum #max_count creatures. If #max_count not provided use 10 as default value.'); +INSERT INTO `command` (`name`,`security`,`help`) VALUES ('.listobject',3,'Syntax: .listobject #gameobject_id [#max_count]\r\n\r\nOutput gameobjects with gameobject id #gameobject_id found in world. Output gameobject guids and coordinates sorted by distance from character. Will be output maximum #max_count gameobject. If #max_count not provided use 10 as default value.'); +INSERT INTO `command` (`name`,`security`,`help`) VALUES ('.listitem',3,'Syntax: .listitem #item_id [#max_count]\r\n\r\nOutput items with item id #item_id found in all character inventories, mails and auctions. Output item guids, item owner guid, owner account and owner name. Will be output maximum #max_count items. If #max_count not provided use 10 as default value.'); + diff --git a/sql/updates/0.7/3150_command.sql b/sql/updates/0.7/3150_command.sql new file mode 100644 index 00000000000..991744885d6 --- /dev/null +++ b/sql/updates/0.7/3150_command.sql @@ -0,0 +1,3 @@ +DELETE FROM `command` WHERE `name` = 'random'; +DELETE FROM `command` WHERE `name` = 'setmovetype'; +INSERT INTO `command` (`name`,`security`,`help`) VALUES ('setmovetype',2,'Syntax: .setmovetype [#creature_guid] stay/random/way\r\n\r\nSet for creature pointed by #creature_guid (or selected if #creature_guid not provided) movement type and move it to respawn position (if creature alive). Any existed waypoints for creature will be removed from database. If creature is dead then movement type will aplied at creature respawm.'); diff --git a/sql/updates/0.7/3162_character_queststatus.sql b/sql/updates/0.7/3162_character_queststatus.sql new file mode 100644 index 00000000000..6590539de92 --- /dev/null +++ b/sql/updates/0.7/3162_character_queststatus.sql @@ -0,0 +1,2 @@ +UPDATE `character_queststatus` SET `rewarded`='1' WHERE `completed_once`='1'; +ALTER TABLE `character_queststatus` DROP `completed_once`; \ No newline at end of file diff --git a/sql/updates/0.7/3162_command.sql b/sql/updates/0.7/3162_command.sql new file mode 100644 index 00000000000..052fb1f4cc9 --- /dev/null +++ b/sql/updates/0.7/3162_command.sql @@ -0,0 +1 @@ +UPDATE `command` SET `help`='Syntax: .recall\r\n\r\nTeleport you to the place where you have been before using the .tele command.' WHERE `name`='recall'; \ No newline at end of file diff --git a/sql/updates/0.7/3162_quest_template.sql b/sql/updates/0.7/3162_quest_template.sql new file mode 100644 index 00000000000..dfc9fc138ed --- /dev/null +++ b/sql/updates/0.7/3162_quest_template.sql @@ -0,0 +1,2 @@ +UPDATE `quest_template` SET `SpecialFlags`=`SpecialFlags`|'32' WHERE `Repeatable`='1'; +ALTER TABLE `quest_template` DROP `Repeatable`; \ No newline at end of file diff --git a/sql/updates/0.7/3174_command.sql b/sql/updates/0.7/3174_command.sql new file mode 100644 index 00000000000..c42c9b4874d --- /dev/null +++ b/sql/updates/0.7/3174_command.sql @@ -0,0 +1 @@ +UPDATE `command` SET `help`='Syntax: .recall [$playername]\r\n\r\nTeleport $playername or selected player to the place where he has been before last use of a teleportation command. If no $playername is entered and no player is selected, it will teleport you.' WHERE `name`='recall'; \ No newline at end of file diff --git a/sql/updates/0.7/3179_quest_template.sql b/sql/updates/0.7/3179_quest_template.sql new file mode 100644 index 00000000000..9dcc96bcd2e --- /dev/null +++ b/sql/updates/0.7/3179_quest_template.sql @@ -0,0 +1,3 @@ +ALTER TABLE `quest_template` ADD COLUMN `Repeatable` tinyint(1) unsigned NOT NULL default '0'; + +UPDATE `quest_template` SET `Repeatable`='1' WHERE `SpecialFlags`&'32'='32'; \ No newline at end of file diff --git a/sql/updates/0.7/3180_spell_proc_event.sql b/sql/updates/0.7/3180_spell_proc_event.sql new file mode 100644 index 00000000000..2058c104478 --- /dev/null +++ b/sql/updates/0.7/3180_spell_proc_event.sql @@ -0,0 +1,2 @@ +delete from `spell_proc_event` where `entry` = 23547; +insert into `spell_proc_event` values(23547,0,0,0,0,32,0); diff --git a/sql/updates/0.7/3183_command.sql b/sql/updates/0.7/3183_command.sql new file mode 100644 index 00000000000..434aac6675d --- /dev/null +++ b/sql/updates/0.7/3183_command.sql @@ -0,0 +1 @@ +INSERT INTO `command` VALUES('lookupitemset',3,'Syntax: .lookupitemset $itemname\r\n\r\nLooks up an item set by $itemname, and returns all matches with their Item set ID\'s.'); diff --git a/sql/updates/0.7/3186_command.sql b/sql/updates/0.7/3186_command.sql new file mode 100644 index 00000000000..c5cc1d798a4 --- /dev/null +++ b/sql/updates/0.7/3186_command.sql @@ -0,0 +1 @@ +INSERT INTO `command` VALUES('removequest',3,'Syntax: .removequest #quest_id\r\n\r\nSet quest #quest_id state to not completed and not active (and remove from active quest list) for selected player.'); diff --git a/sql/updates/0.7/3202_character_gifts.sql b/sql/updates/0.7/3202_character_gifts.sql new file mode 100644 index 00000000000..cdbbf97b020 --- /dev/null +++ b/sql/updates/0.7/3202_character_gifts.sql @@ -0,0 +1,10 @@ +DROP TABLE IF EXISTS `character_gifts`; + +CREATE TABLE `character_gifts` ( + `guid` int(20) unsigned NOT NULL default '0', + `item_guid` int(11) unsigned NOT NULL default '0', + `entry` int(20) unsigned NOT NULL default '0', + `flags` int(20) unsigned NOT NULL default '0', + KEY `idx_guid` (`guid`), + PRIMARY KEY (`item_guid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/sql/updates/0.7/3205_character_inventory.sql b/sql/updates/0.7/3205_character_inventory.sql new file mode 100644 index 00000000000..4672fc447d4 --- /dev/null +++ b/sql/updates/0.7/3205_character_inventory.sql @@ -0,0 +1,3 @@ +ALTER TABLE `character_inventory` DROP PRIMARY KEY, DROP KEY `idx_item`; + +ALTER TABLE `character_inventory` ADD PRIMARY KEY (`item`); diff --git a/sql/updates/0.7/3231_quest_template.sql b/sql/updates/0.7/3231_quest_template.sql new file mode 100644 index 00000000000..5090b0db03e --- /dev/null +++ b/sql/updates/0.7/3231_quest_template.sql @@ -0,0 +1,9 @@ +ALTER TABLE `quest_template` ADD COLUMN `ReqSourceCount1` int(11) unsigned NOT NULL default '0' AFTER `ReqSourceId4`; +ALTER TABLE `quest_template` ADD COLUMN `ReqSourceCount2` int(11) unsigned NOT NULL default '0' AFTER `ReqSourceCount1`; +ALTER TABLE `quest_template` ADD COLUMN `ReqSourceCount3` int(11) unsigned NOT NULL default '0' AFTER `ReqSourceCount2`; +ALTER TABLE `quest_template` ADD COLUMN `ReqSourceCount4` int(11) unsigned NOT NULL default '0' AFTER `ReqSourceCount3`; + +UPDATE `quest_template` SET `ReqSourceCount1`='1' WHERE `ReqSourceId1`!='0'; +UPDATE `quest_template` SET `ReqSourceCount2`='1' WHERE `ReqSourceId2`!='0'; +UPDATE `quest_template` SET `ReqSourceCount3`='1' WHERE `ReqSourceId3`!='0'; +UPDATE `quest_template` SET `ReqSourceCount4`='1' WHERE `ReqSourceId4`!='0'; \ No newline at end of file diff --git a/sql/updates/0.7/3245_item_text.sql b/sql/updates/0.7/3245_item_text.sql new file mode 100644 index 00000000000..f24390f5fc6 --- /dev/null +++ b/sql/updates/0.7/3245_item_text.sql @@ -0,0 +1,6 @@ +DROP TABLE IF EXISTS `item_text`; +CREATE TABLE `item_text` ( + `id` int(11) NOT NULL default '0', + `text` longtext, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Item System'; diff --git a/sql/updates/0.7/3245_mail.sql b/sql/updates/0.7/3245_mail.sql new file mode 100644 index 00000000000..ed73422325b --- /dev/null +++ b/sql/updates/0.7/3245_mail.sql @@ -0,0 +1,3 @@ +ALTER TABLE `mail` + CHANGE COLUMN `itemPageId` `itemTextId` int(11) unsigned NOT NULL default '0'; + diff --git a/sql/updates/0.7/3245_page_text.sql b/sql/updates/0.7/3245_page_text.sql new file mode 100644 index 00000000000..93045d1e038 --- /dev/null +++ b/sql/updates/0.7/3245_page_text.sql @@ -0,0 +1,7 @@ +ALTER TABLE `item_page` RENAME TO `page_text`; +ALTER TABLE `page_text` ENGINE = MyISAM; + +ALTER TABLE `page_text` + DROP PRIMARY KEY, + CHANGE COLUMN `id` `entry` int(11) NOT NULL default '0', + ADD PRIMARY KEY (`entry`); diff --git a/sql/updates/0.7/3246_character_reputation.sql b/sql/updates/0.7/3246_character_reputation.sql new file mode 100644 index 00000000000..806e5424bcf --- /dev/null +++ b/sql/updates/0.7/3246_character_reputation.sql @@ -0,0 +1,24 @@ +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 47 , 20, '0', '1' FROM `character` WHERE `race` = 1 OR `race` = 3 OR `race` = 4 OR `race` = 7; +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 47 , 20, '0', '2' FROM `character` WHERE `race` = 2 OR `race` = 5 OR `race` = 6 OR `race` = 8; + +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 54 , 18, '0', '1' FROM `character` WHERE `race` = 1 OR `race` = 3 OR `race` = 4 OR `race` = 7; +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 54 , 18, '0', '2' FROM `character` WHERE `race` = 2 OR `race` = 5 OR `race` = 6 OR `race` = 8; + +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 68 , 17, '0', '2' FROM `character` WHERE `race` = 1 OR `race` = 3 OR `race` = 4 OR `race` = 7; +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 68 , 17, '0', '1' FROM `character` WHERE `race` = 2 OR `race` = 5 OR `race` = 6 OR `race` = 8; + +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 69 , 21, '0', '1' FROM `character` WHERE `race` = 1 OR `race` = 3 OR `race` = 4 OR `race` = 7; +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 69 , 21, '0', '2' FROM `character` WHERE `race` = 2 OR `race` = 5 OR `race` = 6 OR `race` = 8; + +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 72 , 19, '0', '1' FROM `character` WHERE `race` = 1 OR `race` = 3 OR `race` = 4 OR `race` = 7; +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 72 , 19, '0', '2' FROM `character` WHERE `race` = 2 OR `race` = 5 OR `race` = 6 OR `race` = 8; + +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 76 , 14, '0', '2' FROM `character` WHERE `race` = 1 OR `race` = 3 OR `race` = 4 OR `race` = 7; +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 76 , 14, '0', '1' FROM `character` WHERE `race` = 2 OR `race` = 5 OR `race` = 6 OR `race` = 8; + +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 81 , 16, '0', '2' FROM `character` WHERE `race` = 1 OR `race` = 3 OR `race` = 4 OR `race` = 7; +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 81 , 16, '0', '1' FROM `character` WHERE `race` = 2 OR `race` = 5 OR `race` = 6 OR `race` = 8; + +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 530, 15, '0', '2' FROM `character` WHERE `race` = 1 OR `race` = 3 OR `race` = 4 OR `race` = 7; +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 530, 15, '0', '1' FROM `character` WHERE `race` = 2 OR `race` = 5 OR `race` = 6 OR `race` = 8; + diff --git a/sql/updates/0.7/3251_commands.sql b/sql/updates/0.7/3251_commands.sql new file mode 100644 index 00000000000..b5d2f029f0b --- /dev/null +++ b/sql/updates/0.7/3251_commands.sql @@ -0,0 +1,2 @@ +DELETE FROM `command` WHERE `name` = 'password'; +INSERT INTO `command` VALUES ('password',0,'Syntax: .password $old_password $new_password $new_password\r\n\r\nChange your account password.'); diff --git a/sql/updates/0.7/3252.sql b/sql/updates/0.7/3252.sql new file mode 100644 index 00000000000..09e01de6713 --- /dev/null +++ b/sql/updates/0.7/3252.sql @@ -0,0 +1,74 @@ +ALTER TABLE `areatrigger_template` MODIFY COLUMN `required_level` tinyint(3) unsigned NOT NULL default '0'; +ALTER TABLE `item_template` MODIFY COLUMN `DisenchantID` int(11) unsigned NOT NULL default '0'; + +ALTER TABLE `auctionhouse` MODIFY COLUMN `id` int(11) unsigned NOT NULL default '0'; + +ALTER TABLE `corpse` MODIFY COLUMN `player` int(11) unsigned NOT NULL default '0' COMMENT 'Character Global Unique Identifier'; + +ALTER TABLE `creature_template` + MODIFY COLUMN `rangedattackpower` smallint(5) unsigned NOT NULL default '0', + MODIFY COLUMN `type` tinyint(3) unsigned default '0'; + +ALTER TABLE `disenchant_loot_template` MODIFY COLUMN `entry` int(11) unsigned NOT NULL default '0' COMMENT 'Recommended id selection: item_level*100 + item_quality'; + +UPDATE `item_template` SET `stat_type1`='0' WHERE `stat_type1`<'0'; +UPDATE `item_template` SET `stat_type2`='0' WHERE `stat_type2`<'0'; +UPDATE `item_template` SET `stat_type3`='0' WHERE `stat_type3`<'0'; +UPDATE `item_template` SET `stat_type4`='0' WHERE `stat_type4`<'0'; +UPDATE `item_template` SET `stat_type5`='0' WHERE `stat_type5`<'0'; +UPDATE `item_template` SET `stat_type6`='0' WHERE `stat_type6`<'0'; +UPDATE `item_template` SET `stat_type7`='0' WHERE `stat_type7`<'0'; +UPDATE `item_template` SET `stat_type8`='0' WHERE `stat_type8`<'0'; +UPDATE `item_template` SET `stat_type9`='0' WHERE `stat_type9`<'0'; +UPDATE `item_template` SET `stat_type10`='0' WHERE `stat_type10`<'0'; + +ALTER TABLE `item_template` + MODIFY COLUMN `AllowableClass` mediumint(9) NOT NULL default '0', + MODIFY COLUMN `AllowableRace` mediumint(9) NOT NULL default '0', + MODIFY COLUMN `stat_type1` tinyint(4) unsigned NOT NULL default '0', + MODIFY COLUMN `stat_value1` smallint(6) NOT NULL default '0', + MODIFY COLUMN `stat_type2` tinyint(4) unsigned NOT NULL default '0', + MODIFY COLUMN `stat_value2` smallint(6) NOT NULL default '0', + MODIFY COLUMN `stat_type3` tinyint(4) unsigned NOT NULL default '0', + MODIFY COLUMN `stat_value3` smallint(6) NOT NULL default '0', + MODIFY COLUMN `stat_type4` tinyint(4) unsigned NOT NULL default '0', + MODIFY COLUMN `stat_value4` smallint(6) NOT NULL default '0', + MODIFY COLUMN `stat_type5` tinyint(4) unsigned NOT NULL default '0', + MODIFY COLUMN `stat_value5` smallint(6) NOT NULL default '0', + MODIFY COLUMN `stat_type6` tinyint(4) unsigned NOT NULL default '0', + MODIFY COLUMN `stat_value6` smallint(6) NOT NULL default '0', + MODIFY COLUMN `stat_type7` tinyint(4) unsigned NOT NULL default '0', + MODIFY COLUMN `stat_value7` smallint(6) NOT NULL default '0', + MODIFY COLUMN `stat_type8` tinyint(4) unsigned NOT NULL default '0', + MODIFY COLUMN `stat_value8` smallint(6) NOT NULL default '0', + MODIFY COLUMN `stat_type9` tinyint(4) unsigned NOT NULL default '0', + MODIFY COLUMN `stat_value9` smallint(6) NOT NULL default '0', + MODIFY COLUMN `stat_type10` tinyint(4) unsigned NOT NULL default '0', + MODIFY COLUMN `stat_value10` smallint(6) NOT NULL default '0', + MODIFY COLUMN `dmg_type1` tinyint(3) unsigned NOT NULL default '0', + MODIFY COLUMN `dmg_type2` tinyint(3) unsigned NOT NULL default '0', + MODIFY COLUMN `dmg_type3` tinyint(3) unsigned NOT NULL default '0', + MODIFY COLUMN `dmg_type4` tinyint(3) unsigned NOT NULL default '0', + MODIFY COLUMN `dmg_type5` tinyint(3) unsigned NOT NULL default '0', + MODIFY COLUMN `Material` int(30) NOT NULL default '0'; + +ALTER TABLE `pet_name_generation` ENGINE=MyISAM, DEFAULT CHARSET=utf8; +ALTER TABLE `pet_name_generation` MODIFY COLUMN `word` tinytext NOT NULL; + +ALTER TABLE `quest_template` + MODIFY COLUMN `ReqSourceId1` int(11) unsigned NOT NULL default '0', + MODIFY COLUMN `ReqSourceId2` int(11) unsigned NOT NULL default '0', + MODIFY COLUMN `ReqSourceId3` int(11) unsigned NOT NULL default '0', + MODIFY COLUMN `ReqSourceId4` int(11) unsigned NOT NULL default '0', + MODIFY COLUMN `RewRepFaction1` int(11) unsigned NOT NULL default '0' COMMENT 'faction id from Faction.dbc in this case', + MODIFY COLUMN `RewRepFaction2` int(11) unsigned NOT NULL default '0' COMMENT 'faction id from Faction.dbc in this case', + MODIFY COLUMN `RewRepFaction3` int(11) unsigned NOT NULL default '0' COMMENT 'faction id from Faction.dbc in this case', + MODIFY COLUMN `RewRepFaction4` int(11) unsigned NOT NULL default '0' COMMENT 'faction id from Faction.dbc in this case', + MODIFY COLUMN `RewRepFaction5` int(11) unsigned NOT NULL default '0' COMMENT 'faction id from Faction.dbc in this case'; + +ALTER TABLE `scripts` ENGINE=MyISAM, DEFAULT CHARSET=utf8; +ALTER TABLE `scripts` MODIFY COLUMN `datatext` text NOT NULL; + +ALTER TABLE `spell_proc_event` ENGINE=MyISAM, DEFAULT CHARSET=utf8; + +ALTER TABLE `spell_scripts` ENGINE=MyISAM, DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/sql/updates/0.7/3296_commands.sql b/sql/updates/0.7/3296_commands.sql new file mode 100644 index 00000000000..344d99b314f --- /dev/null +++ b/sql/updates/0.7/3296_commands.sql @@ -0,0 +1,4 @@ +DELETE FROM `command` WHERE `name` = 'learnskill'; +DELETE FROM `command` WHERE `name` = 'unlearnskill'; +DELETE FROM `command` WHERE `name` = 'fixunlearn'; + diff --git a/sql/updates/0.7/3296_playercreateinfo_skill.sql b/sql/updates/0.7/3296_playercreateinfo_skill.sql new file mode 100644 index 00000000000..788b8924308 --- /dev/null +++ b/sql/updates/0.7/3296_playercreateinfo_skill.sql @@ -0,0 +1,32 @@ +DROP TABLE IF EXISTS `playercreateinfo_skill`; +CREATE TABLE `playercreateinfo_skill` ( + `race` tinyint(3) unsigned NOT NULL default '0', + `class` tinyint(3) unsigned NOT NULL default '0', + `Skill` mediumint(8) unsigned NOT NULL default '0', + `Note` varchar(255) default NULL, + PRIMARY KEY (`race`,`class`,`Skill`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +INSERT INTO `playercreateinfo_skill` VALUES +(1,1,183,'GENERIC (DND)'),(1,2,183,'GENERIC (DND)'),(1,4,183,'GENERIC (DND)'),(1,5,183,'GENERIC (DND)'),(1,8,183,'GENERIC (DND)'),(1,9,183,'GENERIC (DND)'),(2,1,183,'GENERIC (DND)'),(2,3,183,'GENERIC (DND)'),(2,4,183,'GENERIC (DND)'),(2,7,183,'GENERIC (DND)'),(2,9,183,'GENERIC (DND)'),(3,1,183,'GENERIC (DND)'),(3,2,183,'GENERIC (DND)'),(3,3,183,'GENERIC (DND)'),(3,4,183,'GENERIC (DND)'),(3,5,183,'GENERIC (DND)'),(4,1,183,'GENERIC (DND)'),(4,3,183,'GENERIC (DND)'),(4,4,183,'GENERIC (DND)'),(4,5,183,'GENERIC (DND)'),(4,11,183,'GENERIC (DND)'),(5,1,183,'GENERIC (DND)'),(5,4,183,'GENERIC (DND)'),(5,5,183,'GENERIC (DND)'),(5,8,183,'GENERIC (DND)'),(5,9,183,'GENERIC (DND)'),(6,1,183,'GENERIC (DND)'),(6,3,183,'GENERIC (DND)'),(6,7,183,'GENERIC (DND)'),(6,11,183,'GENERIC (DND)'),(7,1,183,'GENERIC (DND)'),(7,4,183,'GENERIC (DND)'),(7,8,183,'GENERIC (DND)'),(7,9,183,'GENERIC (DND)'),(8,1,183,'GENERIC (DND)'),(8,3,183,'GENERIC (DND)'),(8,4,183,'GENERIC (DND)'),(8,5,183,'GENERIC (DND)'),(8,7,183,'GENERIC (DND)'),(8,8,183,'GENERIC (DND)'), +(1,8,6,'Frost'),(5,8,6,'Frost'),(7,8,6,'Frost'),(8,8,6,'Frost'), +(1,8,8,'Fire'),(5,8,8,'Fire'),(7,8,8,'Fire'),(8,8,8,'Fire'), +(1,1,26,'Arms'),(2,1,26,'Arms'),(3,1,26,'Arms'),(4,1,26,'Arms'),(5,1,26,'Arms'),(6,1,26,'Arms'),(7,1,26,'Arms'),(8,1,26,'Arms'), +(1,4,38,'Combat'),(2,4,38,'Combat'),(3,4,38,'Combat'),(4,4,38,'Combat'),(5,4,38,'Combat'),(7,4,38,'Combat'),(8,4,38,'Combat'), +(2,3,51,'Survival'),(3,3,51,'Survival'),(4,3,51,'Survival'),(6,3,51,'Survival'),(8,3,51,'Survival'), +(1,5,56,'Holy'),(3,5,56,'Holy'),(4,5,56,'Holy'),(5,5,56,'Holy'),(8,5,56,'Holy'),(1,2,594,'Holy'),(3,2,594,'Holy'), +(3,1,101,'Dwarven Racial'),(3,2,101,'Dwarven Racial'),(3,3,101,'Dwarven Racial'),(3,4,101,'Dwarven Racial'),(3,5,101,'Dwarven Racial'), +(6,1,124,'Tauren Racial'),(6,3,124,'Tauren Racial'),(6,7,124,'Tauren Racial'),(6,11,124,'Tauren Racial'), +(2,1,125,'Orc Racial'),(2,3,125,'Orc Racial'),(2,4,125,'Orc Racial'),(2,7,125,'Orc Racial'),(2,9,125,'Orc Racial'), +(4,1,126,'Night Elf Racial'),(4,3,126,'Night Elf Racial'),(4,4,126,'Night Elf Racial'),(4,5,126,'Night Elf Racial'),(4,11,126,'Night Elf Racial'), +(2,3,163,'Marksmanship'),(3,3,163,'Marksmanship'),(4,3,163,'Marksmanship'),(6,3,163,'Marksmanship'),(8,3,163,'Marksmanship'), +(5,1,220,'Racial - Undead'),(5,4,220,'Racial - Undead'),(5,5,220,'Racial - Undead'),(5,8,220,'Racial - Undead'),(5,9,220,'Racial - Undead'), +(1,4,253,'Assassination'),(2,4,253,'Assassination'),(3,4,253,'Assassination'),(4,4,253,'Assassination'),(5,4,253,'Assassination'),(7,4,253,'Assassination'),(8,4,253,'Assassination'), +(1,9,354,'Demonology'),(2,9,354,'Demonology'),(5,9,354,'Demonology'),(7,9,354,'Demonology'),(2,7,374,'Restoration'), +(6,7,374,'Restoration'),(8,7,374,'Restoration'),(4,11,573,'Restoration'),(6,11,573,'Restoration'), +(2,7,375,'Elemental Combat'),(6,7,375,'Elemental Combat'),(8,7,375,'Elemental Combat'), +(4,11,574,'Balance'),(6,11,574,'Balance'), +(1,9,593,'Destruction'),(2,9,593,'Destruction'),(5,9,593,'Destruction'),(7,9,593,'Destruction'), +(8,1,733,'Racial - Troll'),(8,3,733,'Racial - Troll'),(8,4,733,'Racial - Troll'),(8,5,733,'Racial - Troll'),(8,7,733,'Racial - Troll'),(8,8,733,'Racial - Troll'), +(7,1,753,'Racial - Gnome'),(7,4,753,'Racial - Gnome'),(7,8,753,'Racial - Gnome'),(7,9,753,'Racial - Gnome'), +(1,1,754,'Racial - Human'),(1,2,754,'Racial - Human'),(1,4,754,'Racial - Human'),(1,5,754,'Racial - Human'),(1,8,754,'Racial - Human'),(1,9,754,'Racial - Human'); diff --git a/sql/updates/0.7/3296_spell_learn_skill.sql b/sql/updates/0.7/3296_spell_learn_skill.sql new file mode 100644 index 00000000000..aafd633db9c --- /dev/null +++ b/sql/updates/0.7/3296_spell_learn_skill.sql @@ -0,0 +1,57 @@ +DROP TABLE IF EXISTS `spell_learn_skill`; +CREATE TABLE `spell_learn_skill` ( + `entry` smallint(6) unsigned NOT NULL default '0', + `SkillID` smallint(6) NOT NULL default '0', + `Value` int(11) default '0', + `MaxValue` int(11) default '0', + PRIMARY KEY (`entry`), + UNIQUE KEY spell_skill(`entry`,`SkillID`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Item System'; + +INSERT INTO `spell_learn_skill` VALUES +/*================== Armor ============*/ +/*Cloth */( 9078,415, 1, 1), +/*Leather */( 9077,414, 1, 1), +/*Mail */( 8737,413, 1, 1), +/*Plate Mail */( 750,293, 1, 1), +/*Shield */( 9116,433, 1, 1), +/*================== Melee Weapons ====*/ +/*Axes */( 196, 44, 1, 0), +/*Two-Handed Axes */( 197,172, 1, 0), +/*Staves */( 227,136, 1, 0), +/*Maces */( 198, 54, 1, 0), +/*Two-Handed Maces */( 199,160, 1, 0), +/*Swords */( 201, 43, 1, 0), +/*Two-Handed Swords*/( 202, 55, 1, 0), +/*Daggers */( 1180,173, 1, 0), +/*Fist Weapons */(15590,473, 1, 0), +/*Polearms */( 200,229, 1, 0), +/*Spears (Polearms)*/( 3386,229, 1, 0), +/*================== Range Weapons ====*/ +/*Bows */( 264, 45, 1, 0), +/*Crossbows */( 5011,226, 1, 0), +/*Guns */( 266, 46, 1, 0), +/*Thrown */( 2567,176, 1, 0), +/*Wands */( 5009,228, 1, 0), +/*================== Others ===========*/ +/*Poisons */( 2842, 40, 1, 0), +/*Min riding */(33388,762, 75, 75), +/*Mid riding */(33391,762,150,150), +/*Pick Lock(Rogue) */( 1804,633, 1, 0), +/*================== Languages ========*/ + ( 668, 98, -1, -1), + ( 669,109, -1, -1), + ( 670,115, -1, -1), + ( 671,113, -1, -1), + ( 672,111, -1, -1), + ( 813,137, -1, -1), + ( 814,138, -1, -1), + ( 815,139, -1, -1), + ( 816,140, -1, -1), + ( 817,141, -1, -1), + ( 7340,313, -1, -1), + ( 7341,315, -1, -1), + (17737,673, -1, -1), +/*================== Generic Skills ===*/ +/*Defense */( 204, 95, 1, 0), +/*Unarmed */( 203,162, 1, 0); diff --git a/sql/updates/0.7/3310_spell_learn_spell.sql b/sql/updates/0.7/3310_spell_learn_spell.sql new file mode 100644 index 00000000000..28bb02e2917 --- /dev/null +++ b/sql/updates/0.7/3310_spell_learn_spell.sql @@ -0,0 +1,61 @@ +DROP TABLE IF EXISTS `spell_learn_spell`; +CREATE TABLE `spell_learn_spell` ( + `entry` smallint(6) unsigned NOT NULL default '0', + `SpellID` smallint(6) unsigned NOT NULL default '0', + `IfNoSpell` smallint(6) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`,`SpellID`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Item System'; + +INSERT INTO `spell_learn_spell` VALUES +/*SKILL_ENGINERING*/ +(4036,3918,0), +(4036,3919,0), +(4036,3920,0), +/*SKILL_TAILORING*/ +(3908,2387,0), +(3908,2963,0), +/*SKILL_ENCHANTING*/ +(7411,7418,0), +(7411,7421,0), +(7411,13262,0), +/*SKILL_ALCHEMY*/ +(2259,2329,0), +(2259,7183,0), +(2259,2330,0), +/*SKILL_BLACKSMITHING*/ +(2018,2663,0), +(2018,12260,0), +(2018,2660,0), +(2018,3115,0), +/*SKILL_LEATHERWORKING*/ +(2108,2152,0), +(2108,9058,0), +(2108,9059,0), +(2108,2149,0), +(2108,7126,0), +(2108,2881,0), +/*SKILL_COOKING*/ +(2550,818,0), +(2550,2540,0), +(2550,2538,0), +(2550,8604,0), +/*SKILL_FIRST_AID*/ +(3273,3275,0), +/*SKILL_FISHING*/ +(7620,7738,0), +/*SKILL_MINING*/ +(2575,2580,0), +(2575,2656,0), +(2575,2657,0), +/*SKILL_HERBALISM*/ +(2366,2383,0), +/*SKILL_BOWS*/ +(264,2480,75), +/*SKILL_GUNS*/ +(266,7918,75), +/*SKILL_CROSSBOWS*/ +(5011,7919,75), +/*SKILL_THROWN*/ +(2567,2764,0), +/*SKILL_POISONS*/ +(2842,8681,0); diff --git a/sql/updates/0.7/3316_playercreateinfo_reputation.sql b/sql/updates/0.7/3316_playercreateinfo_reputation.sql new file mode 100644 index 00000000000..6ca054e3996 --- /dev/null +++ b/sql/updates/0.7/3316_playercreateinfo_reputation.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS `playercreateinfo_reputation`; diff --git a/sql/updates/0.7/3323.sql b/sql/updates/0.7/3323.sql new file mode 100644 index 00000000000..d0ea3e6c433 --- /dev/null +++ b/sql/updates/0.7/3323.sql @@ -0,0 +1,31 @@ +ALTER TABLE `character_pet` + ADD COLUMN `slot` tinyint(1) unsigned NOT NULL default '0', + CHANGE COLUMN `id` `id` int(11) unsigned NOT NULL default '0'; + +UPDATE `character_pet` + SET `slot` = 0 WHERE `current` = 1; + +/* slot 3 = for storing warlock and another not stabled pets */ +UPDATE `character_pet` + SET `slot` = 3 WHERE `current` = 0; + +/* current = (`slot`==0) */ +ALTER TABLE `character_pet` + DROP COLUMN `current`; + +UPDATE `character_pet`, `character_stable` + SET `character_pet`.`slot` =`character_stable`.`slot` + WHERE `character_pet`.`id`=`character_stable`.`petnumber` + AND `character_pet`.`owner`=`character_stable`.`owner` AND `character_pet`.`id`=`character_stable`.`petnumber`; + +ALTER TABLE `character` + ADD COLUMN `stable_slots` tinyint(1) unsigned NOT NULL default '0'; + +UPDATE `character`, ( + SELECT `character_stable`.`owner` as `owner_slots`, MAX(`character_stable`.`slot`) as `slots` FROM `character_stable` GROUP BY `character_stable`.`owner` + ) as `stable_slots` + SET `character`.`stable_slots`= `stable_slots`.`slots` + WHERE `character`.`guid` = `stable_slots`.`owner_slots`; + + +DROP TABLE IF EXISTS `character_stable`; diff --git a/sql/updates/0.7/3344_playercreateinfo_spell.sql b/sql/updates/0.7/3344_playercreateinfo_spell.sql new file mode 100644 index 00000000000..a43a903acea --- /dev/null +++ b/sql/updates/0.7/3344_playercreateinfo_spell.sql @@ -0,0 +1,13 @@ +INSERT INTO `playercreateinfo_spell` VALUES ('1','1','21156','Battle Stance Passive',0); +INSERT INTO `playercreateinfo_spell` VALUES ('2','1','21156','Battle Stance Passive',0); +INSERT INTO `playercreateinfo_spell` VALUES ('3','1','21156','Battle Stance Passive',0); +INSERT INTO `playercreateinfo_spell` VALUES ('4','1','21156','Battle Stance Passive',0); +INSERT INTO `playercreateinfo_spell` VALUES ('5','1','21156','Battle Stance Passive',0); +INSERT INTO `playercreateinfo_spell` VALUES ('6','1','21156','Battle Stance Passive',0); +INSERT INTO `playercreateinfo_spell` VALUES ('7','1','21156','Battle Stance Passive',0); +INSERT INTO `playercreateinfo_spell` VALUES ('8','1','21156','Battle Stance Passive',0); + +INSERT IGNORE INTO `character_spell` +SELECT `character`.`guid`,`playercreateinfo_spell`.`spell` AS `spell`, '65535' AS `slot`,`playercreateinfo_spell`.`Active` AS `active` +FROM `character`,`playercreateinfo_spell` +WHERE `character`.`class`=`playercreateinfo_spell`.`class` AND `character`.`race`=`playercreateinfo_spell`.`race`; \ No newline at end of file diff --git a/sql/updates/0.7/3346_command.sql b/sql/updates/0.7/3346_command.sql new file mode 100644 index 00000000000..39ae5e1825b --- /dev/null +++ b/sql/updates/0.7/3346_command.sql @@ -0,0 +1,4 @@ +UPDATE `command` SET `name`='lookupobject' WHERE `name`='.lookupobject'; +UPDATE `command` SET `name`='listcreature' WHERE `name`='.listcreature'; +UPDATE `command` SET `name`='listobject' WHERE `name`='.listobject'; +UPDATE `command` SET `name`='listitem' WHERE `name`='.listitem'; diff --git a/sql/updates/0.7/3348_playercreateinfo_spell.sql b/sql/updates/0.7/3348_playercreateinfo_spell.sql new file mode 100644 index 00000000000..d0f5410020f --- /dev/null +++ b/sql/updates/0.7/3348_playercreateinfo_spell.sql @@ -0,0 +1,7 @@ +INSERT INTO `playercreateinfo_spell` VALUES ('4','11','21178','Bear Form (Passive2)',0); +INSERT INTO `playercreateinfo_spell` VALUES ('6','11','21178','Bear Form (Passive2)',0); + +INSERT IGNORE INTO `character_spell` +SELECT `character`.`guid`,`playercreateinfo_spell`.`spell` AS `spell`, '65535' AS `slot`,`playercreateinfo_spell`.`Active` AS `active` +FROM `character`,`playercreateinfo_spell` +WHERE `character`.`class`=`playercreateinfo_spell`.`class` AND `character`.`race`=`playercreateinfo_spell`.`race`; \ No newline at end of file diff --git a/sql/updates/0.7/3350_command.sql b/sql/updates/0.7/3350_command.sql new file mode 100644 index 00000000000..eecf98014c5 --- /dev/null +++ b/sql/updates/0.7/3350_command.sql @@ -0,0 +1,7 @@ +DELETE FROM `command` WHERE `name` = 'item'; +DELETE FROM `command` WHERE `name` = 'itemrmv'; +DELETE FROM `command` WHERE `name` = 'addvendoritem'; +DELETE FROM `command` WHERE `name` = 'delvendoritem'; + +INSERT INTO `command` VALUES('addvendoritem',2,'Syntax: .addvendoritem #itemId <#maxcount><#incrtime>\r\n\r\nAdd item #itemid to item list of selected vendor. Also optionally set max count item in vendor item list and time to item count restoring.'); +INSERT INTO `command` VALUES('delvendoritem',2,'Syntax: .delvendoritem #itemId\r\n\r\nRemove item #itemid from item list of selected vendor.'); diff --git a/sql/updates/0.7/3351_character_pet.sql b/sql/updates/0.7/3351_character_pet.sql new file mode 100644 index 00000000000..2b7f4e634c2 --- /dev/null +++ b/sql/updates/0.7/3351_character_pet.sql @@ -0,0 +1,3 @@ +ALTER TABLE `character_pet` + ADD COLUMN `curhealth` int(11) unsigned NOT NULL default '1', + ADD COLUMN `curmana` int(11) unsigned NOT NULL default '0'; diff --git a/sql/updates/0.7/3397_creature_template.sql b/sql/updates/0.7/3397_creature_template.sql new file mode 100644 index 00000000000..4363e6bb23a --- /dev/null +++ b/sql/updates/0.7/3397_creature_template.sql @@ -0,0 +1,12 @@ +ALTER TABLE `creature_template` + ADD COLUMN `InhabitType` tinyint(1) unsigned NOT NULL default '3' AFTER `MovementType`; + +/* +0 - not used +1 - can walk (or fly above ground) +2 - can swim (or fly above water) +3 (= 1 | 2) - can walk and swim (and fly) +*/ + +UPDATE `creature_template` + SET `InhabitType` = 1 WHERE `family` > 0 AND `family` < 6 OR `family` = 8 OR `family` = 11 OR `family` > 14 AND `family` < 20 OR `family` = 25 OR `family` = 27; diff --git a/sql/updates/0.7/3400.sql b/sql/updates/0.7/3400.sql new file mode 100644 index 00000000000..3ef216430ef --- /dev/null +++ b/sql/updates/0.7/3400.sql @@ -0,0 +1,75 @@ +TRUNCATE TABLE `corpse`; +TRUNCATE TABLE `creature_respawn`; +TRUNCATE TABLE `gameobject_respawn`; + +DROP TABLE IF EXISTS `instance`; +CREATE TABLE `instance` ( + `id` int(11) unsigned NOT NULL default '0', + `map` int(11) unsigned NOT NULL default '0', + `resettime` bigint(40) NOT NULL default '0', + PRIMARY KEY (`id`), + KEY `map` (`map`), + KEY `resettime` (`resettime`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `character_instance`; +CREATE TABLE `character_instance` ( + `guid` int(11) unsigned NOT NULL default '0', + `map` int(11) unsigned NOT NULL default '0', + `instance` bigint(40) NOT NULL default '0', + `leader` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`,`map`), + KEY `instance` (`instance`), + KEY `leader` (`leader`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +ALTER TABLE `creature_respawn` ADD `instance` int(11) unsigned NOT NULL default '0'; +ALTER TABLE `creature_respawn` DROP PRIMARY KEY; +ALTER TABLE `creature_respawn` ADD PRIMARY KEY (`guid`, `instance`); + +ALTER TABLE `gameobject_respawn` ADD `instance` int(11) unsigned NOT NULL default '0'; +ALTER TABLE `gameobject_respawn` DROP PRIMARY KEY; +ALTER TABLE `gameobject_respawn` ADD PRIMARY KEY (`guid`, `instance`); + +ALTER TABLE `corpse` ADD `instance` int(11) unsigned NOT NULL default '0'; + +DROP TABLE IF EXISTS `instance_template`; +CREATE TABLE `instance_template` ( + `map` int(11) unsigned NOT NULL, + `levelMin` int(11) unsigned NOT NULL default '0', + `levelMax` int(11) unsigned NOT NULL default '0', + `maxPlayers` int(11) unsigned NOT NULL default '0', + `reset_delay` int(20) unsigned NOT NULL default '0', + `startLocX` float default NULL, + `startLocY` float default NULL, + `startLocZ` float default NULL, + `startLocO` float default NULL, + PRIMARY KEY (`map`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +INSERT INTO `instance_template` VALUES (33, 22, 30, 10, 7200, NULL, NULL, NULL, NULL); +INSERT INTO `instance_template` VALUES (34, 24, 32, 10, 7200, NULL, NULL, NULL, NULL); +INSERT INTO `instance_template` VALUES (36, 15, 20, 10, 7200, NULL, NULL, NULL, NULL); +INSERT INTO `instance_template` VALUES (43, 15, 21, 10, 7200, NULL, NULL, NULL, NULL); +INSERT INTO `instance_template` VALUES (47, 29, 38, 10, 7200, NULL, NULL, NULL, NULL); +INSERT INTO `instance_template` VALUES (48, 24, 32, 10, 7200, NULL, NULL, NULL, NULL); +INSERT INTO `instance_template` VALUES (70, 35, 47, 10, 7200, NULL, NULL, NULL, NULL); +INSERT INTO `instance_template` VALUES (90, 29, 38, 10, 7200, NULL, NULL, NULL, NULL); +INSERT INTO `instance_template` VALUES (109, 45, 55, 10, 7200, NULL, NULL, NULL, NULL); +INSERT INTO `instance_template` VALUES (129, 37, 46, 10, 7200, NULL, NULL, NULL, NULL); +INSERT INTO `instance_template` VALUES (189, 34, 45, 10, 7200, NULL, NULL, NULL, NULL); +INSERT INTO `instance_template` VALUES (209, 44, 54, 10, 7200, NULL, NULL, NULL, NULL); +INSERT INTO `instance_template` VALUES (229, 58, 0, 10, 120000, 78.5083, -225.044, 49.839, 5.1); +INSERT INTO `instance_template` VALUES (230, 52, 0, 5, 7200, NULL, NULL, NULL, NULL); +INSERT INTO `instance_template` VALUES (249, 60, 0, 40, 432000, NULL, NULL, NULL, NULL); +INSERT INTO `instance_template` VALUES (289, 57, 0, 5, 7200, NULL, NULL, NULL, NULL); +INSERT INTO `instance_template` VALUES (309, 60, 0, 20, 259200, NULL, NULL, NULL, NULL); +INSERT INTO `instance_template` VALUES (329, 58, 60, 5, 7200, NULL, NULL, NULL, NULL); +INSERT INTO `instance_template` VALUES (349, 46, 55, 10, 7200, NULL, NULL, NULL, NULL); +INSERT INTO `instance_template` VALUES (389, 13, 18, 10, 7200, NULL, NULL, NULL, NULL); +INSERT INTO `instance_template` VALUES (409, 60, 0, 40, 604800, NULL, NULL, NULL, NULL); +INSERT INTO `instance_template` VALUES (429, 55, 60, 5, 7200, NULL, NULL, NULL, NULL); +INSERT INTO `instance_template` VALUES (469, 60, 0, 40, 604800, NULL, NULL, NULL, NULL); +INSERT INTO `instance_template` VALUES (509, 60, 0, 20, 259200, NULL, NULL, NULL, NULL); +INSERT INTO `instance_template` VALUES (531, 60, 0, 40, 604800, NULL, NULL, NULL, NULL); +INSERT INTO `instance_template` VALUES (533, 60, 0, 40, 604800, NULL, NULL, NULL, NULL); diff --git a/sql/updates/0.7/3402_creature_onkill_reputation.sql b/sql/updates/0.7/3402_creature_onkill_reputation.sql new file mode 100644 index 00000000000..0fa7b80cd01 --- /dev/null +++ b/sql/updates/0.7/3402_creature_onkill_reputation.sql @@ -0,0 +1,13 @@ +DROP TABLE IF EXISTS `creature_onkill_reputation`; +CREATE TABLE `creature_onkill_reputation` ( + `creature_id` int(10) unsigned NOT NULL default '0' COMMENT 'Creature Identifier', + `RewOnKillRepFaction1` int(10) default '0', + `RewOnKillRepFaction2` int(10) default '0', + `MaxStanding1` int(1) default '0', + `IsTeamAward1` int(1) default '0', + `RewOnKillRepValue1` int(10) default '0', + `MaxStanding2` int(1) default '0', + `IsTeamAward2` int(1) default '0', + `RewOnKillRepValue2` int(10) default '0', + PRIMARY KEY (`creature_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Creature OnKill Reputation gain'; diff --git a/sql/updates/0.7/3410_group.sql b/sql/updates/0.7/3410_group.sql new file mode 100644 index 00000000000..c217cc965dd --- /dev/null +++ b/sql/updates/0.7/3410_group.sql @@ -0,0 +1,7 @@ +RENAME TABLE `raidgroup` TO `group` ; +ALTER TABLE `group` COMMENT = 'Groups'; +ALTER TABLE `group` ADD `isRaid` TINYINT( 1 ) NOT NULL; +UPDATE `group` SET `isRaid` = 1; + +RENAME TABLE `raidgroup_member` TO `group_member`; +ALTER TABLE `group_member` COMMENT = 'Groups'; diff --git a/sql/updates/0.7/3424_command.sql b/sql/updates/0.7/3424_command.sql new file mode 100644 index 00000000000..8bbab63116a --- /dev/null +++ b/sql/updates/0.7/3424_command.sql @@ -0,0 +1,11 @@ +UPDATE `command` + SET `help` = 'Syntax: .modify $parameter $value Modify the value of various parameters. Use .help modify $parameter to get help on specific parameter usage. Supported parameters include hp, mana, rage, energy, money, speed, swim, scale, bit, bwalk, aspeed, faction, spell and tp.' + WHERE `name` = 'modify' LIMIT 1 ; + +UPDATE `command` + SET `help` = 'Syntax: .aura #spellid Add the aura from spell #spellid to the selected Unit.' + WHERE `name` = 'aura' LIMIT 1 ; + +UPDATE `command` + SET `help` = 'Syntax: .unaura #spellid Remove aura due to spell #spellid from the selected Unit.' + WHERE `name` = 'unaura' LIMIT 1 ; diff --git a/sql/updates/0.7/3463_mangos.sql b/sql/updates/0.7/3463_mangos.sql new file mode 100644 index 00000000000..119650fc78e --- /dev/null +++ b/sql/updates/0.7/3463_mangos.sql @@ -0,0 +1,116 @@ +ALTER TABLE `guild` CHANGE `EmblemStyle` `EmblemStyle` INT( 5 ) NOT NULL DEFAULT '0', +CHANGE `EmblemColor` `EmblemColor` INT( 5 ) NOT NULL DEFAULT '0', +CHANGE `BorderStyle` `BorderStyle` INT( 5 ) NOT NULL DEFAULT '0', +CHANGE `BorderColor` `BorderColor` INT( 5 ) NOT NULL DEFAULT '0', +CHANGE `BackgroundColor` `BackgroundColor` INT( 5 ) NOT NULL DEFAULT '0'; + +ALTER TABLE `item_template` ADD `unk_203` INT(10) NOT NULL default '0' AFTER `sheath`; +ALTER TABLE `item_template` CHANGE `Unknown1` `Map` INT( 10 ) NOT NULL DEFAULT '0'; +ALTER TABLE `item_template` CHANGE `BagFamily` `BagFamily` INT( 10 ) NOT NULL DEFAULT '0' AFTER `Map`; +ALTER TABLE `item_template` ADD `TotemCategory` INT( 10 ) NOT NULL DEFAULT '0' AFTER `BagFamily`, +ADD `socketColor_1` INT( 10 ) NOT NULL DEFAULT '0' AFTER `TotemCategory`, +ADD `socketContent_1` INT( 10 ) NOT NULL DEFAULT '0' AFTER `socketColor_1`, +ADD `socketColor_2` INT( 10 ) NOT NULL DEFAULT '0' AFTER `socketContent_1`, +ADD `socketContent_2` INT( 10 ) NOT NULL DEFAULT '0' AFTER `socketColor_2`, +ADD `socketColor_3` INT( 10 ) NOT NULL DEFAULT '0' AFTER `socketContent_2`, +ADD `socketContent_3` INT( 10 ) NOT NULL DEFAULT '0' AFTER `socketColor_3`, +ADD `socketBonus` INT( 10 ) NOT NULL DEFAULT '0' AFTER `socketContent_3`, +ADD `GemProperties` INT( 10 ) NOT NULL DEFAULT '0' AFTER `socketBonus`, +ADD `ExtendedCost` INT( 10 ) NOT NULL DEFAULT '0' AFTER `GemProperties`, +ADD `RequiredDisenchantSkill` INT( 10 ) NOT NULL DEFAULT '-1' AFTER `ExtendedCost`; + +UPDATE `item_template` SET `TotemCategory` = '11' WHERE `entry` = '2901'; +UPDATE `item_template` SET `TotemCategory` = '1' WHERE `entry` = '7005'; +UPDATE `item_template` SET `TotemCategory` = '1' WHERE `entry` = '12709'; +UPDATE `item_template` SET `TotemCategory` = '2' WHERE `entry` = '5175'; +UPDATE `item_template` SET `TotemCategory` = '4' WHERE `entry` = '5176'; +UPDATE `item_template` SET `TotemCategory` = '5' WHERE `entry` = '5177'; +UPDATE `item_template` SET `TotemCategory` = '3' WHERE `entry` = '5178'; + +ALTER TABLE `character_kill` CHANGE `guid` `guid` SMALLINT( 4 ) UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier' ; +ALTER TABLE `character_kill` DROP `type` ; +ALTER TABLE `character` DROP `highest_rank` , DROP `standing` , DROP `rating` ; + +insert into `playercreateinfo_spell` values +(10,2,7355,'Stuck',1), +(10,3,7355,'Stuck',1), +(10,4,7355,'Stuck',1), +(10,5,7355,'Stuck',1), +(10,8,7355,'Stuck',1), +(10,9,7355,'Stuck',1), +(11,1,7355,'Stuck',1), +(11,2,7355,'Stuck',1), +(11,3,7355,'Stuck',1), +(11,5,7355,'Stuck',1), +(11,7,7355,'Stuck',1), +(11,8,7355,'Stuck',1); + +ALTER TABLE `group` CHANGE `leaderGuid` `leaderGuid` INT( 20 ) NOT NULL , +CHANGE `looterGuid` `looterGuid` INT( 20 ) NOT NULL ; +ALTER TABLE `group_member` CHANGE `leaderGuid` `leaderGuid` INT( 20 ) NOT NULL , +CHANGE `memberGuid` `memberGuid` INT( 20 ) NOT NULL ; +ALTER TABLE `group` ADD `mainTank` INT(20) NOT NULL AFTER `leaderGuid` , +ADD `mainAssistant` INT(20) NOT NULL AFTER `mainTank` ; + +CREATE TABLE `looking_for_group` ( + `guid` int(12) unsigned NOT NULL default '0', + `slot` smallint(2) unsigned NOT NULL default '0', + `entry` int(12) unsigned NOT NULL default '0', + `type` smallint(2) unsigned NOT NULL default '0', + `lfg_type` smallint(2) unsigned NOT NULL default '0', + `comment` text NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +UPDATE `creature_template` SET `npcflag`='33' WHERE `name`='Spirit Healer'; + +ALTER TABLE `playercreateinfo` DROP `displayID`; + +ALTER TABLE `quest_template` +CHANGE `OfferRewardEmote` `IncompleteEmote` int(11) unsigned NOT NULL default '0', +CHANGE `RequestItemsEmote` `CompleteEmote` int(11) unsigned NOT NULL default '1'; +ALTER TABLE `quest_template` +ADD `DetailsEmote1` int(11) NOT NULL default '0' AFTER `PointOpt`, +ADD `DetailsEmote2` int(11) NOT NULL default '0' AFTER `DetailsEmote1`, +ADD `DetailsEmote3` int(11) NOT NULL default '0' AFTER `DetailsEmote2`, +ADD `DetailsEmote4` int(11) NOT NULL default '0' AFTER `DetailsEmote3`, +ADD `OfferRewardEmote1` int(11) NOT NULL default '0' AFTER `CompleteEmote`, +ADD `OfferRewardEmote2` int(11) NOT NULL default '0' AFTER `OfferRewardEmote1`, +ADD `OfferRewardEmote3` int(11) NOT NULL default '0' AFTER `OfferRewardEmote2`, +ADD `OfferRewardEmote4` int(11) NOT NULL default '0' AFTER `OfferRewardEmote3`; + +ALTER TABLE `item_template` ADD `unk0` INT( 10 ) NOT NULL DEFAULT '-1' AFTER `subclass`; + +ALTER TABLE `group` ADD `lootThreshold` tinyint(4) NOT NULL AFTER `looterGuid`; + +ALTER TABLE `creature_template` CHANGE `equipslot1` `equipslot1` INTEGER NOT NULL DEFAULT '0'; +ALTER TABLE `creature_template` CHANGE `equipslot2` `equipslot2` INTEGER NOT NULL DEFAULT '0'; +ALTER TABLE `creature_template` CHANGE `equipslot3` `equipslot3` INTEGER NOT NULL DEFAULT '0'; + +CREATE TABLE `arena_team` ( + `guid` int(10) unsigned NOT NULL default '0', + `slot` tinyint(3) unsigned NOT NULL default '0', + `name` char(255) NOT NULL, + `type` tinyint(3) unsigned NOT NULL default '0', + `rank` int(10) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE `arena_team_member` ( + `guid` int(10) unsigned NOT NULL default '0', + `teamslot` tinyint(3) unsigned NOT NULL default '0', + `teamguid` int(10) unsigned NOT NULL default '0', + `rating` int(10) unsigned NOT NULL default '0', + `games` int(10) unsigned NOT NULL default '0', + `wins` int(10) unsigned NOT NULL default '0', + `played` int(10) unsigned NOT NULL default '0' +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +DELETE FROM `gameobject` WHERE `map`='489'; +UPDATE `gameobject_template` SET `flags` = '0', `type` = '26' WHERE `entry` IN (179785, 179786); +UPDATE `gameobject_template` SET `flags` = '0' WHERE `entry` IN (179830, 179831); + +alter table `creature` change `state` `DeathState` tinyint(3) unsigned not null default '0'; + +alter table `creature_template` drop `mount`; + +INSERT INTO `command` ( `name` , `security` , `help` ) VALUES ('modify titles', '1', 'Syntax:\n.modify titles #mask\n.titles #mask\n\nAllows user to use all titles from #mask.\n\n #mask=0 disables the title-choose-field'); +INSERT INTO `command` ( `name` , `security` , `help` ) VALUES ('titles', '1', 'Syntax:\n.modify titles #mask\n.titles #mask\n\nAllows user to use all titles from #mask.\n\n #mask=0 disables the title-choose-field'); diff --git a/sql/updates/0.7/3463_realm.sql b/sql/updates/0.7/3463_realm.sql new file mode 100644 index 00000000000..b33b92d6737 --- /dev/null +++ b/sql/updates/0.7/3463_realm.sql @@ -0,0 +1 @@ +ALTER TABLE `account` ADD `tbc` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0' AFTER `online`; diff --git a/sql/updates/0.7/3474_creature_addon.sql b/sql/updates/0.7/3474_creature_addon.sql new file mode 100644 index 00000000000..d03b65a53cc --- /dev/null +++ b/sql/updates/0.7/3474_creature_addon.sql @@ -0,0 +1,17 @@ +DROP TABLE IF EXISTS `creature_addon`; +CREATE TABLE `creature_addon` ( + `entry` int(11) NOT NULL default '0', + `RefId` int(11) NOT NULL default '0', + `mount` int(11) unsigned NOT NULL default '0', + `bytes0` int(11) unsigned NOT NULL default '0', + `bytes1` int(11) unsigned NOT NULL default '0', + `bytes2` int(11) unsigned NOT NULL default '0', + `emote` int(11) unsigned NOT NULL default '0', + `aura` int(11) unsigned NOT NULL default '0', + `auraflags` int(11) unsigned NOT NULL default '0', + `auralevels` int(11) unsigned NOT NULL default '0', + `auraapplications` int(11) unsigned NOT NULL default '0', + `aurastate` int(11) unsigned NOT NULL default '0', + UNIQUE KEY `guid` (`Entry`), + KEY `emote` (`emote`,`RefId`,`mount`,`aura`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/sql/updates/0.7/3501.sql b/sql/updates/0.7/3501.sql new file mode 100644 index 00000000000..6b88153e0f9 --- /dev/null +++ b/sql/updates/0.7/3501.sql @@ -0,0 +1,37 @@ +-- +-- Enhancements to the waypoint system +-- +-- text1..tex5 -> Mob can say up to five texts (one is choosen) +-- aiscript -> An AI script can be executed, when the mob reaches a waypoint, see wpAI.h +-- emote -> a mob can do an emote, eg cutting wood, laughing, etc (make sure you set a waittime, otherwise emote may be omitted) +-- spell -> mob can cast a spell, when he reaches a waypoint +-- wpguid -> if the GM wants to see the waypoints, whisps are spawned, which can only be seen by a GM +-- The GUID of the whisp is stored here +ALTER TABLE `creature_movement` ADD COLUMN `text1` varchar(255) default NULL AFTER `waittime`, +ADD COLUMN `text2` varchar(255) default NULL AFTER `text1`, +ADD COLUMN `text3` varchar(255) default NULL AFTER `text2`, +ADD COLUMN `text4` varchar(255) default NULL AFTER `text3`, +ADD COLUMN `text5` varchar(255) default NULL AFTER `text4`, +ADD COLUMN `aiscript` varchar(255) default NULL AFTER `text5`, +ADD COLUMN `emote` int(10) unsigned default '0' AFTER `aiscript`, +ADD COLUMN `spell` int(5) unsigned default '0' AFTER `emote`, +ADD COLUMN `wpguid` int(11) default '0' AFTER `spell`; + +-- The visual waypoint +DELETE FROM creature_template WHERE entry='1'; +INSERT INTO creature_template + (entry, modelid_m, modelid_f, name, subname, minlevel, maxlevel, minhealth, maxhealth, minmana, maxmana, armor, faction, npcflag, speed, rank, mindmg, maxdmg, attackpower, baseattacktime, rangeattacktime, flags, dynamicflags, size, family, bounding_radius, trainer_type, trainer_spell, class, race, minrangedmg, maxrangedmg, rangedattackpower, combat_reach, type, civilian, flag1, equipmodel1, equipmodel2, equipmodel3, equipinfo1, equipinfo2, equipinfo3, equipslot1, equipslot2, equipslot3, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, spell2, spell3, spell4, mingold, maxgold, AIName, MovementType, ScriptName) +VALUES + (1, 10045, 0, 'Waypoint (Only GM can see it)', 'Visual', 1, 1, 64, 64, 0, 0, 0, 35, 0, '0.91', 0, 14, 15, 100, 2000, 2200, 4096, 0, '0.5', 8, 2, 0, 0, 0, 0, '1.76', '2.42', 100, '2.56', 8, 1, 5242886, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, ''); + +-- New commands +DELETE FROM `command` where `name` = 'wp' and `security` = '2'; +DELETE FROM `command` where `name` = 'wp add' and `security` = '2'; +DELETE FROM `command` where `name` = 'wp modify' and `security` = '2'; +DELETE FROM `command` where `name` = 'wp show' and `security` = '2'; + +INSERT INTO command (name, security, help) VALUES +("wp", 2, "Using WP Command:\r\nEach Waypoint Command has it's own description!"), +("wp add", 2, "Syntax: .wp add [#creature_guid or Select a Creature]"), +("wp modify", 2, "Syntax: .wp modify [#creature_guid or Select a Creature]\r\nadd - Add a waypoint after the selected visual\r\nimport $filename for selected npc\r\nexport $filename for selected npc\r\nwaittime $time\r\nemote ID\r\nspell ID\r\ntext1| text2| text3| text4| text5 \r\nmodel1 ID\r\nmodel2 ID\r\naiscript $Name\r\nmove(moves wp to player pos)\r\ndel (deletes the wp)\r\n\r\nOnly one parameter per time!"), +("wp show", 2, "Syntax: .wp show [#creature_guid or Select a Creature]\r\non\r\nfirst\r\nlast\r\noff\r\ninfo\r\n\r\nFor using info you have to do first show on and than select a Visual-Waypoint and do the show info!"); diff --git a/sql/updates/0.7/3503_creature_movement.sql b/sql/updates/0.7/3503_creature_movement.sql new file mode 100644 index 00000000000..b92a5474691 --- /dev/null +++ b/sql/updates/0.7/3503_creature_movement.sql @@ -0,0 +1,7 @@ +-- +-- Enhancements to the waypoint system +-- +-- Sorry for having forgotten to add this to the svn. +ALTER TABLE `creature_movement` ADD COLUMN `orientation` float default 0 AFTER `wpguid`; +ALTER TABLE `creature_movement` ADD COLUMN `model1` int (11) default 0 AFTER `orientation`; +ALTER TABLE `creature_movement` ADD COLUMN `model2` int (11) default 0 AFTER `model1`; diff --git a/sql/updates/0.7/3512_character_spell_cooldown.sql b/sql/updates/0.7/3512_character_spell_cooldown.sql new file mode 100644 index 00000000000..8fc95b3da6a --- /dev/null +++ b/sql/updates/0.7/3512_character_spell_cooldown.sql @@ -0,0 +1 @@ +ALTER TABLE `character_spell_cooldown` ADD COLUMN `item` int(11) unsigned NOT NULL default '0' COMMENT 'Item Identifier' AFTER `spell`; diff --git a/sql/updates/0.7/3514_mail.sql b/sql/updates/0.7/3514_mail.sql new file mode 100644 index 00000000000..f3ebf9744f0 --- /dev/null +++ b/sql/updates/0.7/3514_mail.sql @@ -0,0 +1,3 @@ +ALTER TABLE `mail` + CHANGE COLUMN `time` `expire_time` bigint(40) NOT NULL default '0', + ADD `deliver_time` bigint(40) NOT NULL default '0' AFTER `expire_time`; diff --git a/sql/updates/0.7/3516_spell_learn_spell.sql b/sql/updates/0.7/3516_spell_learn_spell.sql new file mode 100644 index 00000000000..872be29cdfb --- /dev/null +++ b/sql/updates/0.7/3516_spell_learn_spell.sql @@ -0,0 +1,4 @@ +insert into `spell_learn_spell`(`entry`,`SpellID`,`IfNoSpell`) values (25229,25255,0); +insert into `spell_learn_spell`(`entry`,`SpellID`,`IfNoSpell`) values (25229,25493,0); +insert into `spell_learn_spell`(`entry`,`SpellID`,`IfNoSpell`) values (25229,26925,0); +insert into `spell_learn_spell`(`entry`,`SpellID`,`IfNoSpell`) values (25229,32259,0); diff --git a/sql/updates/0.7/3533_command.sql b/sql/updates/0.7/3533_command.sql new file mode 100644 index 00000000000..321c834e2a6 --- /dev/null +++ b/sql/updates/0.7/3533_command.sql @@ -0,0 +1 @@ +UPDATE `command` SET `help` = 'Syntax: .createguild $GuildLeaderName $GuildName\r\n\r\nCreate a guild named $GuildName with the player $GuildLeaderName as leader.' WHERE `name` ='createguild'; diff --git a/sql/updates/0.7/3538_guild_charter_sign.sql b/sql/updates/0.7/3538_guild_charter_sign.sql new file mode 100644 index 00000000000..ad2c482d3a8 --- /dev/null +++ b/sql/updates/0.7/3538_guild_charter_sign.sql @@ -0,0 +1,6 @@ +ALTER TABLE `guild_charter_sign` + ADD `player_account` int(11) unsigned NOT NULL default '0' AFTER `playerguid`; + +UPDATE `guild_charter_sign`,`character` + SET `guild_charter_sign`.`player_account` = `character`.`account` + WHERE `guild_charter_sign`.`playerguid` = `character`.`guid`; diff --git a/sql/updates/0.7/3539_item_template.sql b/sql/updates/0.7/3539_item_template.sql new file mode 100644 index 00000000000..c2e3c48801d --- /dev/null +++ b/sql/updates/0.7/3539_item_template.sql @@ -0,0 +1,12 @@ +ALTER TABLE `item_template` + CHANGE `spellcooldown_1` `spellcooldown_1` int(30) NOT NULL default '-1', + CHANGE `spellcategorycooldown_1` `spellcategorycooldown_1` int(30) NOT NULL default '-1', + CHANGE `spellcooldown_2` `spellcooldown_2` int(30) NOT NULL default '-1', + CHANGE `spellcategorycooldown_2` `spellcategorycooldown_2` int(30) NOT NULL default '-1', + CHANGE `spellcooldown_3` `spellcooldown_3` int(30) NOT NULL default '-1', + CHANGE `spellcategorycooldown_3` `spellcategorycooldown_3` int(30) NOT NULL default '-1', + CHANGE `spellcooldown_4` `spellcooldown_4` int(30) NOT NULL default '-1', + CHANGE `spellcategorycooldown_4` `spellcategorycooldown_4` int(30) NOT NULL default '-1', + CHANGE `spellcooldown_5` `spellcooldown_5` int(30) NOT NULL default '-1', + CHANGE `spellcategorycooldown_5` `spellcategorycooldown_5` int(30) NOT NULL default '-1', + CHANGE `unk_203` `unk_203` int(10) NOT NULL default '0' AFTER `Extra`; diff --git a/sql/updates/0.7/3545_creature_movement.sql b/sql/updates/0.7/3545_creature_movement.sql new file mode 100644 index 00000000000..93733295f81 --- /dev/null +++ b/sql/updates/0.7/3545_creature_movement.sql @@ -0,0 +1,2 @@ +-- tinyint can only hold values up to 255 - too small for a waittime in milliseconds +ALTER TABLE `creature_movement` CHANGE COLUMN `waittime` `waittime` int(5) unsigned NOT NULL default '0'; \ No newline at end of file diff --git a/sql/updates/0.7/3547_character_reputation.sql b/sql/updates/0.7/3547_character_reputation.sql new file mode 100644 index 00000000000..9bdaa860376 --- /dev/null +++ b/sql/updates/0.7/3547_character_reputation.sql @@ -0,0 +1,72 @@ +/* alliance */ +UPDATE `character_reputation`,`character` SET `character_reputation`.`flags` = 17 +WHERE `character_reputation`.`guid` = `character`.`guid` + AND (`character_reputation`.`faction` = 47 or `character_reputation`.`faction` = 54 or `character_reputation`.`faction` = 69 or `character_reputation`.`faction` = 72 or `character_reputation`.`faction` = 930 ) + AND (`character`.`race` = 1 OR `character`.`race` = 3 OR `character`.`race` = 4 OR `character`.`race` = 7 OR `character`.`race` = 11 ); + +/* horde */ +UPDATE `character_reputation`,`character` SET `character_reputation`.`flags` = 17 +WHERE `character_reputation`.`guid` = `character`.`guid` + AND (`character_reputation`.`faction` = 68 or `character_reputation`.`faction` = 76 or `character_reputation`.`faction` = 81 or `character_reputation`.`faction` = 530 or `character_reputation`.`faction` = 911 ) + AND (`character`.`race` = 2 OR `character`.`race` = 5 OR `character`.`race` = 6 OR `character`.`race` = 8 OR `character`.`race` = 10 ); + +/* faction 47 */ +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 47 , 20, '0', '17' +FROM `character` WHERE `race` = 1 OR `race` = 3 OR `race` = 4 OR `race` = 7 OR `race` = 11; +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 47 , 20, '0', '2' +FROM `character` WHERE `race` = 2 OR `race` = 5 OR `race` = 6 OR `race` = 8 OR `race` = 10; + +/* faction 54 */ +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 54 , 18, '0', '17' +FROM `character` WHERE `race` = 1 OR `race` = 3 OR `race` = 4 OR `race` = 7 OR `race` = 11; +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 54 , 18, '0', '2' +FROM `character` WHERE `race` = 2 OR `race` = 5 OR `race` = 6 OR `race` = 8 OR `race` = 10; + +/* faction 68 */ +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 68 , 17, '0', '2' +FROM `character` WHERE `race` = 1 OR `race` = 3 OR `race` = 4 OR `race` = 7 OR `race` = 11; +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 68 , 17, '0', '17' +FROM `character` WHERE `race` = 2 OR `race` = 5 OR `race` = 6 OR `race` = 8 OR `race` = 10; + +/* faction 69 */ +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 69 , 21, '0', '17' +FROM `character` WHERE `race` = 1 OR `race` = 3 OR `race` = 4 OR `race` = 7 OR `race` = 11; +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 69 , 21, '0', '2' +FROM `character` WHERE `race` = 2 OR `race` = 5 OR `race` = 6 OR `race` = 8 OR `race` = 10; + +/* faction 72 */ +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 72 , 19, '0', '17' +FROM `character` WHERE `race` = 1 OR `race` = 3 OR `race` = 4 OR `race` = 7 OR `race` = 11; +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 72 , 19, '0', '2' +FROM `character` WHERE `race` = 2 OR `race` = 5 OR `race` = 6 OR `race` = 8 OR `race` = 10; + +/* faction 76 */ +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 76 , 14, '0', '2' +FROM `character` WHERE `race` = 1 OR `race` = 3 OR `race` = 4 OR `race` = 7 OR `race` = 11; +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 76 , 14, '0', '17' +FROM `character` WHERE `race` = 2 OR `race` = 5 OR `race` = 6 OR `race` = 8 OR `race` = 10; + +/* faction 81 */ +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 81 , 16, '0', '2' +FROM `character` WHERE `race` = 1 OR `race` = 3 OR `race` = 4 OR `race` = 7 OR `race` = 11; +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 81 , 16, '0', '17' +FROM `character` WHERE `race` = 2 OR `race` = 5 OR `race` = 6 OR `race` = 8 OR `race` = 10; + +/* faction 530 */ +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 530, 15, '0', '2' +FROM `character` WHERE `race` = 1 OR `race` = 3 OR `race` = 4 OR `race` = 7 OR `race` = 11; +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 530, 15, '0', '17' +FROM `character` WHERE `race` = 2 OR `race` = 5 OR `race` = 6 OR `race` = 8 OR `race` = 10; + +/* faction 911 (B.Elf) */ +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 911, 15, '0', '2' +FROM `character` WHERE `race` = 1 OR `race` = 3 OR `race` = 4 OR `race` = 7 OR `race` = 11; +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 911, 15, '0', '17' +FROM `character` WHERE `race` = 2 OR `race` = 5 OR `race` = 6 OR `race` = 8 OR `race` = 10; + +/* faction 930 (Dra) */ +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 930 , 19, '0', '17' +FROM `character` WHERE `race` = 1 OR `race` = 3 OR `race` = 4 OR `race` = 7 OR `race` = 11; +INSERT IGNORE INTO `character_reputation` SELECT `character`.`guid`, 930 , 19, '0', '2' +FROM `character` WHERE `race` = 2 OR `race` = 5 OR `race` = 6 OR `race` = 8 OR `race` = 10; + diff --git a/sql/updates/0.7/3553_creature_onkill_reputation.sql b/sql/updates/0.7/3553_creature_onkill_reputation.sql new file mode 100644 index 00000000000..5d674ba26d2 --- /dev/null +++ b/sql/updates/0.7/3553_creature_onkill_reputation.sql @@ -0,0 +1,6 @@ +ALTER TABLE `creature_onkill_reputation` + CHANGE COLUMN `MaxStanding1` `MaxStanding1` tinyint(1) default '0', + CHANGE COLUMN `IsTeamAward1` `IsTeamAward1` tinyint(1) default '0', + CHANGE COLUMN `MaxStanding2` `MaxStanding2` tinyint(1) default '0', + CHANGE COLUMN `IsTeamAward2` `IsTeamAward2` tinyint(1) default '0', + ADD COLUMN `TeamDependent` tinyint(1) unsigned NOT NULL default '0' AFTER `RewOnKillRepValue2`; diff --git a/sql/updates/0.7/3562_player_levelstats.sql b/sql/updates/0.7/3562_player_levelstats.sql new file mode 100644 index 00000000000..473b9b082dd --- /dev/null +++ b/sql/updates/0.7/3562_player_levelstats.sql @@ -0,0 +1,5 @@ +DELETE FROM player_levelstats WHERE race=2 and class=4 and level=19; +DELETE FROM player_levelstats WHERE race=2 and class=4 and level=20; +INSERT INTO player_levelstats VALUES +('2', '4', '19', '391', '0', '38', '44', '35', '20', '30'), +('2', '4', '20', '414', '0', '38', '46', '36', '20', '30'); \ No newline at end of file diff --git a/sql/updates/0.7/3605_creature_addon.sql b/sql/updates/0.7/3605_creature_addon.sql new file mode 100644 index 00000000000..09389ec90db --- /dev/null +++ b/sql/updates/0.7/3605_creature_addon.sql @@ -0,0 +1,2 @@ +ALTER TABLE `creature_addon` + CHANGE COLUMN `entry` `guid` int(11) NOT NULL default '0'; diff --git a/sql/updates/0.7/3605_grid.sql b/sql/updates/0.7/3605_grid.sql new file mode 100644 index 00000000000..0b4bd425f88 --- /dev/null +++ b/sql/updates/0.7/3605_grid.sql @@ -0,0 +1,3 @@ +DROP TABLE IF EXISTS `corpse_grid`; +DROP TABLE IF EXISTS `creature_grid`; +DROP TABLE IF EXISTS `gameobject_grid`; diff --git a/sql/updates/0.7/3611_spell_learn_skill.sql b/sql/updates/0.7/3611_spell_learn_skill.sql new file mode 100644 index 00000000000..fd929a8746a --- /dev/null +++ b/sql/updates/0.7/3611_spell_learn_skill.sql @@ -0,0 +1,5 @@ +-- Add spell_skill for riding 225 and 300 skill +DELETE FROM `spell_learn_skill` WHERE `entry` IN ('34091', '34090'); +INSERT INTO `spell_learn_skill` VALUES ('34091', '762', '300', '300'); +INSERT INTO `spell_learn_skill` VALUES ('34090', '762', '225', '225'); + diff --git a/sql/updates/0.7/3616_commands.sql b/sql/updates/0.7/3616_commands.sql new file mode 100644 index 00000000000..f1c34fa5442 --- /dev/null +++ b/sql/updates/0.7/3616_commands.sql @@ -0,0 +1,6 @@ +-- Enhanced .addgo / .gameobject command +-- Now the user can also specify and +DELETE FROM `command` WHERE `name` = 'addgo'; +DELETE FROM `command` WHERE `name` = 'gameobject'; +insert into `command` values ('gameobject',3,'Syntax: .gameobject #id \r\n\r\nAdd a game object from game object templates to the world at your current location using the #id.\r\nlootID specifies the loot-template to be used and spawntimeSecs sets the spawntime, both are optional.'); +insert into `command` values ('addgo',3,'Syntax: .addgo #id \r\n\r\nAdd a game object from game object templates to the world at your current location using the #id.\r\nlootID specifies the loot-template to be used and spawntimesecs sets the spawntime, both are optional.\r\n\r\nNote: this is a copy of .gameobject.'); diff --git a/sql/updates/0.7/3627_quest_template.sql b/sql/updates/0.7/3627_quest_template.sql new file mode 100644 index 00000000000..790b680d370 --- /dev/null +++ b/sql/updates/0.7/3627_quest_template.sql @@ -0,0 +1,5 @@ +ALTER TABLE `quest_template` ADD COLUMN `ZoneOrSort` int(11) NOT NULL default '0' AFTER `entry` ; +UPDATE `quest_template` SET `ZoneOrSort` = `ZoneId` WHERE `ZoneId` < 2147483647 ; +UPDATE `quest_template` SET `ZoneOrSort` = -(4294967295 - `ZoneId` + 1 ) WHERE `ZoneId` >= 2147483647 ; +UPDATE `quest_template` SET `ZoneOrSort` = -`questsort` WHERE `questsort` > 0 ; +ALTER TABLE `quest_template` DROP `questsort`, DROP `ZoneId`; \ No newline at end of file diff --git a/sql/updates/0.7/3631_gameobject_template.sql b/sql/updates/0.7/3631_gameobject_template.sql new file mode 100644 index 00000000000..66f758d6fdd --- /dev/null +++ b/sql/updates/0.7/3631_gameobject_template.sql @@ -0,0 +1,15 @@ +ALTER TABLE `gameobject_template` +ADD COLUMN `sound10` int(11) unsigned NOT NULL default '0' AFTER `sound9`, +ADD COLUMN `sound11` int(11) unsigned NOT NULL default '0' AFTER `sound10`, +ADD COLUMN `sound12` int(11) unsigned NOT NULL default '0' AFTER `sound11`, +ADD COLUMN `sound13` int(11) unsigned NOT NULL default '0' AFTER `sound12`, +ADD COLUMN `sound14` int(11) unsigned NOT NULL default '0' AFTER `sound13`, +ADD COLUMN `sound15` int(11) unsigned NOT NULL default '0' AFTER `sound14`, +ADD COLUMN `sound16` int(11) unsigned NOT NULL default '0' AFTER `sound15`, +ADD COLUMN `sound17` int(11) unsigned NOT NULL default '0' AFTER `sound16`, +ADD COLUMN `sound18` int(11) unsigned NOT NULL default '0' AFTER `sound17`, +ADD COLUMN `sound19` int(11) unsigned NOT NULL default '0' AFTER `sound18`, +ADD COLUMN `sound20` int(11) unsigned NOT NULL default '0' AFTER `sound19`, +ADD COLUMN `sound21` int(11) unsigned NOT NULL default '0' AFTER `sound20`, +ADD COLUMN `sound22` int(11) unsigned NOT NULL default '0' AFTER `sound21`, +ADD COLUMN `sound23` int(11) unsigned NOT NULL default '0' AFTER `sound22`; diff --git a/sql/updates/0.7/3636_character_spell.sql b/sql/updates/0.7/3636_character_spell.sql new file mode 100644 index 00000000000..945180b29e1 --- /dev/null +++ b/sql/updates/0.7/3636_character_spell.sql @@ -0,0 +1,2 @@ +UPDATE `character_spell` + SET `spell` = 5420 WHERE `spell` = 3122; diff --git a/sql/updates/0.7/3636_playercreateinfo_spell.sql b/sql/updates/0.7/3636_playercreateinfo_spell.sql new file mode 100644 index 00000000000..5116fdd2806 --- /dev/null +++ b/sql/updates/0.7/3636_playercreateinfo_spell.sql @@ -0,0 +1,2 @@ +UPDATE `playercreateinfo_spell` + SET `Spell` = 5420 WHERE `Spell` = 3122; diff --git a/sql/updates/0.7/3646_spell_chain.sql b/sql/updates/0.7/3646_spell_chain.sql new file mode 100644 index 00000000000..5dfa78ffec4 --- /dev/null +++ b/sql/updates/0.7/3646_spell_chain.sql @@ -0,0 +1,6 @@ +INSERT INTO `spell_chain` VALUES +(25245, 0, 25245, 1), +(25246, 25245, 25245, 2), +(28896, 25246, 25245, 3), +(28899, 28896, 25245, 4), +(28901, 28899, 25245, 5); diff --git a/sql/updates/0.7/3648_command.sql b/sql/updates/0.7/3648_command.sql new file mode 100644 index 00000000000..08075757403 --- /dev/null +++ b/sql/updates/0.7/3648_command.sql @@ -0,0 +1 @@ +INSERT INTO `command` VALUES('sendmail',1,'Syntax: .sendmail #playername #subject #text\r\n\r\nSend a mail to a player. Note: subject may not contain spaces.'); \ No newline at end of file diff --git a/sql/updates/0.7/3649_spell_chain.sql b/sql/updates/0.7/3649_spell_chain.sql new file mode 100644 index 00000000000..fbb73a0286a --- /dev/null +++ b/sql/updates/0.7/3649_spell_chain.sql @@ -0,0 +1,8 @@ +DELETE FROM `spell_chain` WHERE `spell_id` IN (25245,25246,28896,28899,28901); + +INSERT INTO `spell_chain` VALUES +(25229, 0, 25229, 1), +(25230, 25229, 25229, 2), +(28894, 25230, 25229, 3), +(28895, 28894, 25229, 4), +(28897, 28895, 25229, 5); diff --git a/sql/updates/0.7/3653_spell.sql b/sql/updates/0.7/3653_spell.sql new file mode 100644 index 00000000000..87f5a1f4dea --- /dev/null +++ b/sql/updates/0.7/3653_spell.sql @@ -0,0 +1,4 @@ +DELETE FROM `spell_chain` WHERE `spell_id` = 27170; +INSERT INTO `spell_chain` VALUES (27170,20920,20375,6); +DELETE FROM `spell_proc_event` WHERE `entry` = 27170; +INSERT INTO `spell_proc_event` VALUES (27170, 0, 0, 0, 0, 1, 7); diff --git a/sql/updates/0.7/3655_quest_template.sql b/sql/updates/0.7/3655_quest_template.sql new file mode 100644 index 00000000000..8882fca15b2 --- /dev/null +++ b/sql/updates/0.7/3655_quest_template.sql @@ -0,0 +1,24 @@ +UPDATE `quest_template` SET `ZoneOrSort` = -61 WHERE `ZoneOrSort` = 0 AND `RequiredClass` = 9; +UPDATE `quest_template` SET `ZoneOrSort` = -81 WHERE `ZoneOrSort` = 0 AND `RequiredClass` = 1; +UPDATE `quest_template` SET `ZoneOrSort` = -82 WHERE `ZoneOrSort` = 0 AND `RequiredClass` = 7; +UPDATE `quest_template` SET `ZoneOrSort` = -141 WHERE `ZoneOrSort` = 0 AND `RequiredClass` = 2; +UPDATE `quest_template` SET `ZoneOrSort` = -161 WHERE `ZoneOrSort` = 0 AND `RequiredClass` = 8; +UPDATE `quest_template` SET `ZoneOrSort` = -162 WHERE `ZoneOrSort` = 0 AND `RequiredClass` = 4; +UPDATE `quest_template` SET `ZoneOrSort` = -261 WHERE `ZoneOrSort` = 0 AND `RequiredClass` = 3; +UPDATE `quest_template` SET `ZoneOrSort` = -262 WHERE `ZoneOrSort` = 0 AND `RequiredClass` = 5; +UPDATE `quest_template` SET `ZoneOrSort` = -263 WHERE `ZoneOrSort` = 0 AND `RequiredClass` = 11; + +UPDATE `quest_template` SET `ZoneOrSort` = -24 WHERE `ZoneOrSort` = 0 AND `RequiredSkill` = 182; +UPDATE `quest_template` SET `ZoneOrSort` = -101 WHERE `ZoneOrSort` = 0 AND `RequiredSkill` = 356; +UPDATE `quest_template` SET `ZoneOrSort` = -121 WHERE `ZoneOrSort` = 0 AND `RequiredSkill` = 164; +UPDATE `quest_template` SET `ZoneOrSort` = -181 WHERE `ZoneOrSort` = 0 AND `RequiredSkill` = 171; +UPDATE `quest_template` SET `ZoneOrSort` = -182 WHERE `ZoneOrSort` = 0 AND `RequiredSkill` = 165; +UPDATE `quest_template` SET `ZoneOrSort` = -201 WHERE `ZoneOrSort` = 0 AND `RequiredSkill` = 202; +UPDATE `quest_template` SET `ZoneOrSort` = -264 WHERE `ZoneOrSort` = 0 AND `RequiredSkill` = 197; +UPDATE `quest_template` SET `ZoneOrSort` = -304 WHERE `ZoneOrSort` = 0 AND `RequiredSkill` = 185; +UPDATE `quest_template` SET `ZoneOrSort` = -324 WHERE `ZoneOrSort` = 0 AND `RequiredSkill` = 129; + +ALTER TABLE `quest_template` + ADD COLUMN `SuggestedPlayers` int(11) unsigned NOT NULL DEFAULT 0 AFTER `RequiredRepValue`, + DROP COLUMN `RequiredClass`, + DROP COLUMN `RequiredSkill`; diff --git a/sql/updates/0.7/3657_command.sql b/sql/updates/0.7/3657_command.sql new file mode 100644 index 00000000000..10a69f6d25e --- /dev/null +++ b/sql/updates/0.7/3657_command.sql @@ -0,0 +1 @@ +DELETE FROM `command` WHERE `name` = 'NewMail' OR `name` = 'QNM'; diff --git a/sql/updates/0.7/3660_character_kill.sql b/sql/updates/0.7/3660_character_kill.sql new file mode 100644 index 00000000000..3ec00bde8f5 --- /dev/null +++ b/sql/updates/0.7/3660_character_kill.sql @@ -0,0 +1 @@ +ALTER TABLE `character_kill` MODIFY COLUMN `guid` INT(11); \ No newline at end of file diff --git a/sql/updates/0.7/3700_character.sql b/sql/updates/0.7/3700_character.sql new file mode 100644 index 00000000000..db01e501e4b --- /dev/null +++ b/sql/updates/0.7/3700_character.sql @@ -0,0 +1 @@ +alter table `character` add column `rename` tinyint (3) UNSIGNED DEFAULT '0' NOT NULL after `stable_slots`; diff --git a/sql/updates/0.7/3728_spell_proc_event.sql b/sql/updates/0.7/3728_spell_proc_event.sql new file mode 100644 index 00000000000..789ac7e1fee --- /dev/null +++ b/sql/updates/0.7/3728_spell_proc_event.sql @@ -0,0 +1,3 @@ +ALTER TABLE `spell_proc_event` + CHANGE COLUMN `entry` `entry` smallint(6) unsigned NOT NULL default '0'; + \ No newline at end of file diff --git a/sql/updates/0.7/3730_command.sql b/sql/updates/0.7/3730_command.sql new file mode 100644 index 00000000000..ac85abaa8ed --- /dev/null +++ b/sql/updates/0.7/3730_command.sql @@ -0,0 +1 @@ +INSERT INTO `command` VALUES('nametele',1,'Syntax: .nametele #playername #location\r\n\r\nTeleport a player to a given location.'); diff --git a/sql/updates/0.7/3732_spell_affect.sql b/sql/updates/0.7/3732_spell_affect.sql new file mode 100644 index 00000000000..1ce212f5a39 --- /dev/null +++ b/sql/updates/0.7/3732_spell_affect.sql @@ -0,0 +1,113 @@ +DROP TABLE IF EXISTS `spell_affect`; +CREATE TABLE `spell_affect` ( + `entry` smallint(5) unsigned NOT NULL default '0', + `effectId` tinyint(3) unsigned NOT NULL default '0', + `SpellId` smallint(5) unsigned NOT NULL default '0', + `SchoolMask` tinyint(3) unsigned NOT NULL default '0', + `Category` smallint(5) unsigned NOT NULL default '0', + `SkillID` smallint(5) unsigned NOT NULL default '0', + `SpellFamily` tinyint(3) unsigned NOT NULL default '0', + `SpellFamilyMask` int(10) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`,`effectId`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +INSERT INTO `spell_affect` VALUES +(11070, 1, 0, 0, 0, 0, 0, 32), +(11069, 1, 0, 0, 0, 0, 0, 1), +(11083, 0, 0, 0, 0, 8, 0, 0), +(11124, 0, 0, 0, 0, 8, 0, 0), +(11151, 0, 0, 0, 0, 6, 0, 0), +(11160, 0, 0, 0, 0, 6, 0, 0), +(11175, 1, 0, 0, 0, 0, 0, 1048576), +(11207, 0, 0, 0, 0, 6, 0, 0), +(11222, 0, 0, 0, 0, 237, 0, 0), +(11242, 0, 0, 0, 0, 0, 0, 536872960), +(11247, 0, 0, 0, 0, 0, 0, 8192), +(11370, 0, 0, 0, 0, 8, 0, 0), +(12042, 0, 0, 0, 0, 0, 3, 0), +(12042, 1, 0, 0, 0, 0, 3, 0), +(12042, 2, 0, 0, 0, 0, 3, 0), +(12043, 0, 0, 0, 0, 0, 3, 0), +(12338, 1, 0, 0, 0, 0, 0, 1), +(12339, 1, 0, 0, 0, 0, 0, 1), +(12340, 1, 0, 0, 0, 0, 0, 1), +(12341, 1, 0, 0, 0, 0, 0, 1), +(12351, 0, 0, 0, 0, 8, 0, 0), +(12378, 0, 0, 0, 0, 8, 0, 0), +(12398, 0, 0, 0, 0, 8, 0, 0), +(12399, 0, 0, 0, 0, 8, 0, 0), +(12400, 0, 0, 0, 0, 8, 0, 0), +(12467, 0, 0, 0, 0, 0, 0, 536872960), +(12469, 0, 0, 0, 0, 0, 0, 536872960), +(12473, 1, 0, 0, 0, 0, 0, 32), +(12497, 0, 0, 0, 0, 0, 0, 1048576), +(12518, 0, 0, 0, 0, 6, 0, 0), +(12519, 0, 0, 0, 0, 6, 0, 0), +(12536, 0, 0, 0, 0, 0, 3, 0), +(12569, 1, 0, 0, 0, 0, 0, 1048576), +(12571, 1, 0, 0, 0, 0, 0, 1048576), +(12672, 0, 0, 0, 0, 6, 0, 0), +(12839, 0, 0, 0, 0, 237, 0, 0), +(12840, 0, 0, 0, 0, 237, 0, 0), +(12841, 0, 0, 0, 0, 237, 0, 0), +(12842, 0, 0, 0, 0, 237, 0, 0), +(12952, 0, 0, 0, 0, 6, 0, 0), +(12953, 0, 0, 0, 0, 6, 0, 0), +(12954, 0, 0, 0, 0, 6, 0, 0), +(12957, 0, 0, 0, 0, 6, 0, 0), +(15047, 0, 0, 0, 0, 6, 0, 0), +(15052, 0, 0, 0, 0, 6, 0, 0), +(15053, 0, 0, 0, 0, 6, 0, 0), +(16757, 0, 0, 0, 0, 0, 0, 160), +(16758, 0, 0, 0, 0, 0, 0, 160), +(16763, 1, 0, 0, 0, 0, 0, 32), +(16765, 1, 0, 0, 0, 0, 0, 32), +(16766, 1, 0, 0, 0, 0, 0, 32), +(22008, 0, 0, 0, 0, 0, 3, 0), +(23025, 0, 0, 0, 0, 0, 0, 65536), +(28682, 0, 0, 0, 0, 8, 0, 0), +(28763, 0, 0, 0, 0, 0, 0, 67108864), +(29438, 0, 0, 20, 0, 0, 0, 0), +(29439, 0, 0, 20, 0, 0, 0, 0), +(29440, 0, 0, 20, 0, 0, 0, 0), +(29976, 0, 0, 0, 0, 0, 3, 0), +(31569, 0, 0, 0, 0, 0, 0, 65536), +(31570, 0, 0, 0, 0, 0, 0, 65536), +(31571, 0, 12536, 0, 0, 0, 0, 0), +(31572, 0, 12536, 0, 0, 0, 0, 0), +(31573, 0, 12536, 0, 0, 0, 0, 0), +(31579, 0, 0, 0, 0, 0, 0, 2048), +(31579, 1, 0, 0, 0, 0, 0, 2048), +(31582, 0, 0, 0, 0, 0, 0, 2048), +(31582, 1, 0, 0, 0, 0, 0, 2048), +(31583, 0, 0, 0, 0, 0, 0, 2048), +(31583, 1, 0, 0, 0, 0, 0, 2048), +(31656, 0, 0, 0, 0, 0, 0, 1), +(31657, 0, 0, 0, 0, 0, 0, 1), +(31658, 0, 0, 0, 0, 0, 0, 1), +(31659, 0, 0, 0, 0, 0, 0, 1), +(31660, 0, 0, 0, 0, 0, 0, 1), +(31682, 0, 0, 0, 0, 0, 0, 32), +(31682, 1, 0, 0, 0, 0, 0, 32), +(31683, 0, 0, 0, 0, 0, 0, 32), +(31683, 1, 0, 0, 0, 0, 0, 32), +(31684, 0, 0, 0, 0, 0, 0, 32), +(31684, 1, 0, 0, 0, 0, 0, 32), +(31685, 1, 0, 0, 0, 0, 0, 32), +(31686, 0, 0, 0, 0, 0, 0, 32), +(31686, 1, 0, 0, 0, 0, 0, 32), +(33066, 0, 0, 0, 0, 0, 0, 2), +(35578, 0, 0, 0, 0, 0, 3, 0), +(35581, 0, 0, 0, 0, 0, 3, 0), +(36032, 0, 0, 0, 0, 0, 0, 536870912), +(36032, 1, 0, 0, 0, 0, 0, 536870912), +(37423, 0, 0, 0, 0, 0, 0, 4), +(37438, 0, 0, 0, 0, 0, 0, 33), +(37439, 0, 12043, 0, 0, 0, 0, 0), +(37439, 1, 0, 0, 0, 0, 0, 8388608), +(37439, 2, 11958, 0, 0, 0, 0, 0), +(37441, 0, 0, 0, 0, 0, 0, 4096), +(37441, 1, 0, 0, 0, 0, 0, 4096), +(37447, 0, 0, 0, 30, 0, 0, 0), +(38396, 0, 0, 0, 0, 0, 0, 67108864), +(38397, 0, 0, 0, 0, 0, 0, 2081); diff --git a/sql/updates/0.7/3739_looking_for_group.sql b/sql/updates/0.7/3739_looking_for_group.sql new file mode 100644 index 00000000000..fc05c1fb529 --- /dev/null +++ b/sql/updates/0.7/3739_looking_for_group.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS `looking_for_group`; diff --git a/sql/updates/0.7/3746_spell_proc_event.sql b/sql/updates/0.7/3746_spell_proc_event.sql new file mode 100644 index 00000000000..3d7a91342ba --- /dev/null +++ b/sql/updates/0.7/3746_spell_proc_event.sql @@ -0,0 +1,2 @@ +INSERT INTO `spell_proc_event` (`entry` ,`SchoolMask` ,`Category` ,`SkillID` ,`SpellFamilyMask` ,`procFlags` ,`ppmRate`) +VALUES ('27155', '0', '0', '0', '0', '1', '0'); \ No newline at end of file diff --git a/sql/updates/0.7/3747_command.sql b/sql/updates/0.7/3747_command.sql new file mode 100644 index 00000000000..730f8080477 --- /dev/null +++ b/sql/updates/0.7/3747_command.sql @@ -0,0 +1 @@ +INSERT INTO `command` VALUES('modify mount',1,'Syntax:\r\n.modify mount #id #speed\r\nDisplay selected player as mounted at #id creature and set speed to #speed value.'); diff --git a/sql/updates/0.7/3748_command.sql b/sql/updates/0.7/3748_command.sql new file mode 100644 index 00000000000..15b722c4cd9 --- /dev/null +++ b/sql/updates/0.7/3748_command.sql @@ -0,0 +1,3 @@ +-- Enhanced .gocreature command +DELETE FROM `command` WHERE `name` = 'gocreature'; +INSERT INTO `command` VALUES('gocreature',2,'Syntax: .gocreature #creature_guid\r\nTeleport your character to creature with guid #creature_guid.\r\n.gocreature #creature_name\r\nTeleport your character to creature with this name.\r\n.gocreature id #creature_id\r\nTeleport your character to a creature that was spawned from the template with this entry.\r\n*If* more than one creature is found, then you are teleported to the first that is found inside the database.'); diff --git a/sql/updates/0.7/3753_battleground_template.sql b/sql/updates/0.7/3753_battleground_template.sql new file mode 100644 index 00000000000..40c5b2d358b --- /dev/null +++ b/sql/updates/0.7/3753_battleground_template.sql @@ -0,0 +1,24 @@ +-- ---------------------------- +-- Table structure for bg_template +-- ---------------------------- +DROP TABLE IF EXISTS `battleground_template`; +CREATE TABLE `battleground_template` ( + `id` int(11) unsigned NOT NULL, + `MaxPlayersPerTeam` int(11) NOT NULL, + `MinLvl` int(11) NOT NULL, + `MaxLvl` int(11) NOT NULL, + `AllianceStartLoc` int(11) unsigned NOT NULL, + `AllianceStartO` float NOT NULL, + `HordeStartLoc` int(11) unsigned NOT NULL, + `HordeStartO` float NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- ---------------------------- +-- Records +-- ---------------------------- + +INSERT INTO `battleground_template` VALUES ('1', '0', '0', '0', '611', '2.72532', '610','2.27452'); +INSERT INTO `battleground_template` VALUES ('2', '0', '0', '0', '769', '3.14159', '770','3.14159'); +INSERT INTO `battleground_template` VALUES ('3', '0', '0', '0', '890', '3.40156', '889','0.263892'); +INSERT INTO `battleground_template` VALUES ('7', '0', '0', '0', '1103', '3.40156', '1104','0.263892'); diff --git a/sql/updates/0.7/3763_spell_affect.sql b/sql/updates/0.7/3763_spell_affect.sql new file mode 100644 index 00000000000..2bc10ee1425 --- /dev/null +++ b/sql/updates/0.7/3763_spell_affect.sql @@ -0,0 +1,935 @@ +DROP TABLE IF EXISTS `spell_affect`; +CREATE TABLE `spell_affect` ( + `entry` smallint(5) unsigned NOT NULL default '0', + `effectId` tinyint(3) unsigned NOT NULL default '0', + `SpellId` smallint(5) unsigned NOT NULL default '0', + `SchoolMask` tinyint(3) unsigned NOT NULL default '0', + `Category` smallint(5) unsigned NOT NULL default '0', + `SkillID` smallint(5) unsigned NOT NULL default '0', + `SpellFamily` tinyint(3) unsigned NOT NULL default '0', + `SpellFamilyMask` int(10) unsigned NOT NULL default '0', + `Charges` smallint(5) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`,`effectId`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +INSERT INTO `spell_affect` VALUES +(11069, 1, 0, 0, 0, 0, 0, 1, 0), +(11070, 1, 0, 0, 0, 0, 0, 32, 0), +(11083, 0, 0, 0, 0, 8, 0, 0, 0), +(11124, 0, 0, 0, 0, 8, 0, 0, 0), +(11151, 0, 0, 0, 0, 6, 0, 0, 0), +(11160, 0, 0, 0, 0, 6, 0, 0, 0), +(11175, 1, 0, 0, 0, 0, 0, 1048576, 0), +(11207, 0, 0, 0, 0, 6, 0, 0, 0), +(11222, 0, 0, 0, 0, 237, 0, 0, 0), +(11242, 0, 0, 0, 0, 0, 0, 536872960, 0), +(11247, 0, 0, 0, 0, 0, 0, 8192, 0), +(11370, 0, 0, 0, 0, 8, 0, 0, 0), +(12042, 0, 0, 0, 0, 0, 3, 0, 0), +(12042, 1, 0, 0, 0, 0, 3, 0, 0), +(12042, 2, 0, 0, 0, 0, 3, 0, 0), +(12043, 0, 0, 0, 0, 0, 3, 0, 0), +(12285, 0, 0, 0, 0, 0, 0, 1, 0), +(12286, 0, 0, 0, 0, 0, 0, 32, 0), +(12287, 1, 0, 0, 0, 0, 0, 128, 0), +(12288, 0, 0, 0, 0, 0, 0, 8, 0), +(12288, 1, 0, 0, 0, 0, 0, 8, 0), +(12301, 0, 0, 0, 0, 0, 0, 256, 0), +(12318, 0, 469, 0, 0, 0, 0, 65536, 0), +(12321, 0, 469, 0, 0, 0, 0, 196608, 0), +(12321, 1, 469, 0, 0, 0, 0, 196608, 0), +(12330, 0, 0, 0, 0, 0, 0, 2097152, 0), +(12338, 1, 0, 0, 0, 0, 0, 1, 0), +(12339, 1, 0, 0, 0, 0, 0, 1, 0), +(12340, 1, 0, 0, 0, 0, 0, 1, 0), +(12341, 1, 0, 0, 0, 0, 0, 1, 0), +(12351, 0, 0, 0, 0, 8, 0, 0, 0), +(12378, 0, 0, 0, 0, 8, 0, 0, 0), +(12398, 0, 0, 0, 0, 8, 0, 0, 0), +(12399, 0, 0, 0, 0, 8, 0, 0, 0), +(12400, 0, 0, 0, 0, 8, 0, 0, 0), +(12467, 0, 0, 0, 0, 0, 0, 536872960, 0), +(12469, 0, 0, 0, 0, 0, 0, 536872960, 0), +(12473, 1, 0, 0, 0, 0, 0, 32, 0), +(12497, 0, 0, 0, 0, 0, 0, 1048576, 0), +(12518, 0, 0, 0, 0, 6, 0, 0, 0), +(12519, 0, 0, 0, 0, 6, 0, 0, 0), +(12536, 0, 0, 0, 0, 0, 3, 0, 0), +(12569, 1, 0, 0, 0, 0, 0, 1048576, 0), +(12571, 1, 0, 0, 0, 0, 0, 1048576, 0), +(12658, 0, 0, 0, 0, 0, 0, 32, 0), +(12659, 0, 0, 0, 0, 0, 0, 32, 0), +(12665, 1, 0, 0, 0, 0, 0, 128, 0), +(12666, 1, 0, 0, 0, 0, 0, 128, 0), +(12672, 0, 0, 0, 0, 6, 0, 0, 0), +(12697, 0, 0, 0, 0, 0, 0, 1, 0), +(12707, 0, 0, 0, 0, 0, 0, 8, 0), +(12707, 1, 0, 0, 0, 0, 0, 8, 0), +(12818, 0, 0, 0, 0, 0, 0, 256, 0), +(12835, 0, 469, 0, 0, 0, 0, 196608, 0), +(12835, 1, 469, 0, 0, 0, 0, 196608, 0), +(12836, 0, 469, 0, 0, 0, 0, 196608, 0), +(12836, 1, 469, 0, 0, 0, 0, 196608, 0), +(12837, 0, 469, 0, 0, 0, 0, 196608, 0), +(12837, 1, 469, 0, 0, 0, 0, 196608, 0), +(12838, 0, 469, 0, 0, 0, 0, 196608, 0), +(12838, 1, 469, 0, 0, 0, 0, 196608, 0), +(12839, 0, 0, 0, 0, 237, 0, 0, 0), +(12840, 0, 0, 0, 0, 237, 0, 0, 0), +(12841, 0, 0, 0, 0, 237, 0, 0, 0), +(12842, 0, 0, 0, 0, 237, 0, 0, 0), +(12857, 0, 469, 0, 0, 0, 0, 65536, 0), +(12858, 0, 469, 0, 0, 0, 0, 65536, 0), +(12860, 0, 469, 0, 0, 0, 0, 65536, 0), +(12861, 0, 469, 0, 0, 0, 0, 65536, 0), +(12862, 0, 0, 0, 0, 0, 0, 2097152, 0), +(12945, 1, 0, 0, 0, 0, 0, 4096, 0), +(12952, 0, 0, 0, 0, 6, 0, 0, 0), +(12953, 0, 0, 0, 0, 6, 0, 0, 0), +(12954, 0, 0, 0, 0, 6, 0, 0, 0), +(12957, 0, 0, 0, 0, 6, 0, 0, 0), +(13742, 0, 0, 0, 0, 0, 0, 96, 0), +(13743, 0, 0, 0, 0, 0, 0, 64, 0), +(13872, 0, 0, 0, 0, 0, 0, 96, 0), +(13875, 0, 0, 0, 0, 0, 0, 64, 0), +(13975, 0, 0, 0, 0, 0, 0, 4194304, 0), +(13975, 1, 0, 0, 0, 0, 0, 4194304, 0), +(13976, 0, 0, 0, 0, 0, 0, 1792, 0), +(13979, 0, 0, 0, 0, 0, 0, 1792, 0), +(13980, 0, 0, 0, 0, 0, 0, 1792, 0), +(13981, 0, 0, 0, 0, 0, 0, 16779264, 0), +(14057, 0, 0, 0, 0, 0, 0, 772, 0), +(14062, 0, 0, 0, 0, 0, 0, 4194304, 0), +(14062, 1, 0, 0, 0, 0, 0, 4194304, 0), +(14063, 0, 0, 0, 0, 0, 0, 4194304, 0), +(14063, 1, 0, 0, 0, 0, 0, 4194304, 0), +(14064, 0, 0, 0, 0, 0, 0, 4194304, 0), +(14064, 1, 0, 0, 0, 0, 0, 4194304, 0), +(14065, 0, 0, 0, 0, 0, 0, 4194304, 0), +(14065, 1, 0, 0, 0, 0, 0, 4194304, 0), +(14066, 0, 0, 0, 0, 0, 0, 16779264, 0), +(14067, 0, 0, 0, 0, 0, 0, 16779264, 0), +(14072, 0, 0, 0, 0, 0, 0, 772, 0), +(14073, 0, 0, 0, 0, 0, 0, 772, 0), +(14074, 0, 0, 0, 0, 0, 0, 772, 0), +(14075, 0, 0, 0, 0, 0, 0, 772, 0), +(14082, 0, 0, 0, 0, 0, 0, 258, 0), +(14083, 0, 0, 0, 0, 0, 0, 258, 0), +(14113, 0, 0, 0, 0, 0, 0, 122880, 0), +(14114, 0, 0, 0, 0, 0, 0, 122880, 0), +(14115, 0, 0, 0, 0, 0, 0, 122880, 0), +(14116, 0, 0, 0, 0, 0, 0, 122880, 0), +(14117, 0, 0, 0, 0, 0, 0, 122880, 0), +(14128, 0, 0, 0, 0, 0, 0, 603979790, 0), +(14132, 0, 0, 0, 0, 0, 0, 603979790, 0), +(14135, 0, 0, 0, 0, 0, 0, 603979790, 0), +(14136, 0, 0, 0, 0, 0, 0, 603979790, 0), +(14137, 0, 0, 0, 0, 0, 0, 603979790, 0), +(14143, 0, 0, 0, 0, 0, 0, 100663814, 0), +(14149, 0, 0, 0, 0, 0, 0, 100663814, 0), +(14162, 0, 0, 0, 0, 0, 0, 131072, 0), +(14163, 0, 0, 0, 0, 0, 0, 131072, 0), +(14164, 0, 0, 0, 0, 0, 0, 131072, 0), +(14168, 0, 0, 0, 0, 0, 0, 524288, 0), +(14169, 0, 0, 0, 0, 0, 0, 524288, 0), +(14174, 0, 0, 0, 0, 0, 0, 2097152, 0), +(14175, 0, 0, 0, 0, 0, 0, 2097152, 0), +(14176, 0, 0, 0, 0, 0, 0, 2097152, 0), +(14177, 0, 0, 0, 0, 0, 8, 0, 0), +(14179, 0, 0, 0, 0, 0, 0, 4063232, 0), +(14523, 1, 0, 66, 0, 0, 0, 0, 0), +(14743, 0, 0, 0, 0, 0, 6, 0, 0), +(14750, 0, 0, 0, 0, 0, 0, 16, 0), +(14751, 0, 0, 0, 0, 0, 6, 0, 0), +(14751, 1, 0, 0, 0, 0, 6, 0, 0), +(14772, 0, 0, 0, 0, 0, 0, 16, 0), +(14784, 1, 0, 66, 0, 0, 0, 0, 0), +(14785, 1, 0, 66, 0, 0, 0, 0, 0), +(14786, 1, 0, 66, 0, 0, 0, 0, 0), +(14787, 1, 0, 66, 0, 0, 0, 0, 0), +(14908, 0, 0, 0, 0, 0, 0, 64, 0), +(14909, 1, 0, 0, 0, 0, 0, 1048704, 0), +(14911, 0, 33076, 0, 0, 0, 0, 512, 0), +(15017, 1, 0, 0, 0, 0, 0, 1048704, 0), +(15018, 0, 33076, 0, 0, 0, 0, 512, 0), +(15019, 0, 33076, 0, 0, 0, 0, 512, 0), +(15020, 0, 0, 0, 0, 0, 0, 64, 0), +(15047, 0, 0, 0, 0, 6, 0, 0, 0), +(15052, 0, 0, 0, 0, 6, 0, 0, 0), +(15053, 0, 0, 0, 0, 6, 0, 0, 0), +(15257, 0, 0, 0, 0, 78, 0, 0, 0), +(15259, 0, 0, 0, 0, 78, 0, 0, 0), +(15259, 1, 0, 0, 0, 78, 0, 0, 0), +(15260, 0, 0, 0, 0, 78, 0, 0, 0), +(15272, 0, 0, 0, 0, 78, 0, 0, 0), +(15307, 0, 0, 0, 0, 78, 0, 0, 0), +(15307, 1, 0, 0, 0, 78, 0, 0, 0), +(15308, 0, 0, 0, 0, 78, 0, 0, 0), +(15308, 1, 0, 0, 0, 78, 0, 0, 0), +(15309, 0, 0, 0, 0, 78, 0, 0, 0), +(15309, 1, 0, 0, 0, 78, 0, 0, 0), +(15310, 0, 0, 0, 0, 78, 0, 0, 0), +(15310, 1, 0, 0, 0, 78, 0, 0, 0), +(15318, 0, 0, 0, 0, 78, 0, 0, 0), +(15320, 0, 0, 0, 0, 78, 0, 0, 0), +(15327, 0, 0, 0, 0, 78, 0, 0, 0), +(15328, 0, 0, 0, 0, 78, 0, 0, 0), +(15329, 0, 0, 0, 0, 78, 0, 0, 0), +(15330, 0, 0, 0, 0, 78, 0, 0, 0), +(15331, 0, 0, 0, 0, 78, 0, 0, 0), +(15332, 0, 0, 0, 0, 78, 0, 0, 0), +(15333, 0, 0, 0, 0, 78, 0, 0, 0), +(15334, 0, 0, 0, 0, 78, 0, 0, 0), +(16035, 0, 0, 0, 0, 0, 0, 2416967683, 0), +(16038, 0, 0, 0, 0, 0, 0, 1073741824, 0), +(16039, 0, 0, 0, 0, 0, 0, 2416967683, 0), +(16041, 0, 0, 0, 0, 0, 0, 3, 0), +(16043, 0, 0, 0, 0, 0, 0, 8, 0), +(16043, 1, 3600, 0, 0, 0, 0, 0, 0), +(16086, 0, 0, 0, 0, 0, 0, 134217728, 0), +(16086, 1, 0, 0, 0, 0, 0, 134217728, 0), +(16086, 2, 0, 0, 0, 0, 0, 4, 0), +(16089, 0, 0, 28, 0, 0, 0, 0, 0), +(16105, 0, 0, 0, 0, 0, 0, 2416967683, 0), +(16106, 0, 0, 0, 0, 0, 0, 2416967683, 0), +(16106, 1, 0, 0, 0, 0, 0, 2416967683, 0), +(16107, 0, 0, 0, 0, 0, 0, 2416967683, 0), +(16108, 0, 0, 0, 0, 0, 0, 2416967683, 0), +(16109, 0, 0, 0, 0, 0, 0, 2416967683, 0), +(16110, 0, 0, 0, 0, 0, 0, 2416967683, 0), +(16111, 0, 0, 0, 0, 0, 0, 2416967683, 0), +(16112, 0, 0, 0, 0, 0, 0, 2416967683, 0), +(16117, 0, 0, 0, 0, 0, 0, 3, 0), +(16118, 0, 0, 0, 0, 0, 0, 3, 0), +(16119, 0, 0, 0, 0, 0, 0, 3, 0), +(16120, 0, 0, 0, 0, 0, 0, 3, 0), +(16130, 0, 0, 0, 0, 0, 0, 8, 0), +(16130, 1, 3600, 0, 0, 0, 0, 0, 0), +(16160, 0, 0, 0, 0, 0, 0, 1073741824, 0), +(16161, 0, 0, 0, 0, 0, 0, 1073741824, 0), +(16166, 0, 0, 28, 0, 0, 0, 0, 0), +(16166, 1, 0, 28, 0, 0, 0, 0, 0), +(16173, 0, 0, 1, 0, 0, 0, 0, 0), +(16181, 0, 0, 0, 0, 0, 0, 448, 0), +(16183, 0, 0, 0, 0, 0, 0, 256, 0), +(16184, 0, 0, 0, 0, 0, 0, 512, 0), +(16184, 1, 0, 0, 0, 0, 0, 512, 0), +(16187, 0, 0, 0, 0, 0, 0, 24576, 0), +(16187, 1, 0, 0, 0, 0, 0, 24576, 0), +(16189, 0, 0, 0, 0, 0, 0, 67108864, 0), +(16205, 0, 0, 0, 0, 0, 0, 24576, 0), +(16205, 1, 0, 0, 0, 0, 0, 24576, 0), +(16206, 0, 0, 0, 0, 0, 0, 24576, 0), +(16206, 1, 0, 0, 0, 0, 0, 24576, 0), +(16207, 0, 0, 0, 0, 0, 0, 24576, 0), +(16207, 1, 0, 0, 0, 0, 0, 24576, 0), +(16208, 0, 0, 0, 0, 0, 0, 24576, 0), +(16208, 1, 0, 0, 0, 0, 0, 24576, 0), +(16209, 1, 0, 0, 0, 0, 0, 512, 0), +(16222, 0, 0, 0, 0, 0, 0, 536870912, 0), +(16223, 0, 0, 0, 0, 0, 0, 536870912, 0), +(16224, 0, 0, 0, 0, 0, 0, 536870912, 0), +(16225, 0, 0, 0, 0, 0, 0, 536870912, 0), +(16230, 0, 0, 0, 0, 0, 0, 448, 0), +(16232, 0, 0, 0, 0, 0, 0, 448, 0), +(16233, 0, 0, 0, 0, 0, 0, 448, 0), +(16234, 0, 0, 0, 0, 0, 0, 448, 0), +(16258, 0, 0, 0, 0, 0, 0, 32768, 0), +(16258, 1, 0, 0, 0, 0, 0, 262144, 0), +(16259, 0, 0, 0, 0, 0, 0, 65536, 0), +(16259, 1, 0, 0, 0, 0, 0, 131072, 0), +(16261, 0, 0, 0, 0, 0, 0, 1024, 0), +(16266, 0, 0, 0, 0, 0, 0, 4194304, 0), +(16266, 1, 0, 0, 0, 0, 0, 16777216, 0), +(16266, 2, 0, 0, 0, 0, 0, 8388608, 0), +(16290, 0, 0, 0, 0, 0, 0, 1024, 0), +(16291, 0, 0, 0, 0, 0, 0, 1024, 0), +(16293, 0, 0, 0, 0, 0, 0, 32768, 0), +(16293, 1, 0, 0, 0, 0, 0, 262144, 0), +(16295, 0, 0, 0, 0, 0, 0, 65536, 0), +(16295, 1, 0, 0, 0, 0, 0, 131072, 0), +(16493, 0, 0, 0, 0, 0, 4, 0, 0), +(16494, 0, 0, 0, 0, 0, 4, 0, 0), +(16513, 0, 0, 0, 0, 0, 0, 122880, 0), +(16513, 1, 0, 0, 0, 0, 0, 122880, 0), +(16513, 2, 0, 0, 0, 0, 0, 122880, 0), +(16514, 0, 0, 0, 0, 0, 0, 122880, 0), +(16514, 1, 0, 0, 0, 0, 0, 122880, 0), +(16514, 2, 0, 0, 0, 0, 0, 122880, 0), +(16515, 0, 0, 0, 0, 0, 0, 122880, 0), +(16515, 1, 0, 0, 0, 0, 0, 122880, 0), +(16515, 2, 0, 0, 0, 0, 0, 122880, 0), +(16544, 2, 0, 0, 0, 0, 0, 4, 0), +(16719, 0, 0, 0, 0, 0, 0, 122880, 0), +(16719, 1, 0, 0, 0, 0, 0, 122880, 0), +(16719, 2, 0, 0, 0, 0, 0, 122880, 0), +(16720, 0, 0, 0, 0, 0, 0, 122880, 0), +(16720, 1, 0, 0, 0, 0, 0, 122880, 0), +(16720, 2, 0, 0, 0, 0, 0, 122880, 0), +(16757, 0, 0, 0, 0, 0, 0, 160, 0), +(16758, 0, 0, 0, 0, 0, 0, 160, 0), +(16763, 1, 0, 0, 0, 0, 0, 32, 0), +(16765, 1, 0, 0, 0, 0, 0, 32, 0), +(16766, 1, 0, 0, 0, 0, 0, 32, 0), +(16814, 0, 0, 0, 0, 0, 0, 5, 0), +(16815, 0, 0, 0, 0, 0, 0, 5, 0), +(16816, 0, 0, 0, 0, 0, 0, 5, 0), +(16817, 0, 0, 0, 0, 0, 0, 5, 0), +(16818, 0, 0, 0, 0, 0, 0, 5, 0), +(16819, 0, 0, 0, 0, 574, 0, 1024, 0), +(16820, 0, 0, 0, 0, 574, 0, 1024, 0), +(16821, 0, 0, 0, 0, 0, 0, 2, 0), +(16821, 1, 0, 0, 0, 0, 0, 2, 0), +(16821, 2, 0, 0, 0, 0, 0, 2, 0), +(16822, 0, 0, 0, 0, 0, 0, 2, 0), +(16822, 1, 0, 0, 0, 0, 0, 2, 0), +(16822, 2, 0, 0, 0, 0, 0, 2, 0), +(16823, 1, 0, 0, 0, 0, 0, 2, 0), +(16823, 2, 0, 0, 0, 0, 0, 2, 0), +(16824, 1, 0, 0, 0, 0, 0, 2, 0), +(16824, 2, 0, 0, 0, 0, 0, 2, 0), +(16825, 1, 0, 0, 0, 0, 0, 2, 0), +(16825, 2, 0, 0, 0, 0, 0, 2, 0), +(16833, 0, 0, 0, 0, 0, 0, 3791650816, 0), +(16834, 0, 0, 0, 0, 0, 0, 3791650816, 0), +(16835, 0, 0, 0, 0, 0, 0, 3791650816, 0), +(16836, 1, 0, 0, 0, 0, 0, 768, 0), +(16839, 1, 0, 0, 0, 0, 0, 768, 0), +(16840, 1, 0, 0, 0, 0, 0, 768, 0), +(16850, 1, 0, 0, 0, 0, 0, 1, 0), +(16870, 0, 0, 0, 0, 0, 7, 0, 0), +(16896, 0, 0, 0, 0, 0, 0, 7, 0), +(16896, 1, 0, 0, 0, 0, 0, 7, 0), +(16897, 0, 0, 0, 0, 0, 0, 7, 0), +(16897, 1, 0, 0, 0, 0, 0, 7, 0), +(16899, 0, 0, 0, 0, 0, 0, 7, 0), +(16899, 1, 0, 0, 0, 0, 0, 7, 0), +(16900, 0, 0, 0, 0, 0, 0, 7, 0), +(16900, 1, 0, 0, 0, 0, 0, 7, 0), +(16901, 0, 0, 0, 0, 0, 0, 7, 0), +(16901, 1, 0, 0, 0, 0, 0, 7, 0), +(16918, 0, 33786, 0, 0, 0, 0, 512, 0), +(16919, 0, 33786, 0, 0, 0, 0, 512, 0), +(16920, 0, 33786, 0, 0, 0, 0, 512, 0), +(16923, 1, 0, 0, 0, 0, 0, 1, 0), +(16924, 1, 0, 0, 0, 0, 0, 1, 0), +(16934, 0, 0, 0, 0, 0, 0, 2048, 0), +(16934, 1, 0, 0, 0, 0, 0, 4096, 0), +(16935, 0, 0, 0, 0, 0, 0, 2048, 0), +(16935, 1, 0, 0, 0, 0, 0, 4096, 0), +(16936, 0, 0, 0, 0, 0, 0, 2048, 0), +(16936, 1, 0, 0, 0, 0, 0, 4096, 0), +(16937, 0, 0, 0, 0, 0, 0, 2048, 0), +(16937, 1, 0, 0, 0, 0, 0, 4096, 0), +(16938, 0, 0, 0, 0, 0, 0, 2048, 0), +(16938, 1, 0, 0, 0, 0, 0, 4096, 0), +(16966, 0, 0, 0, 0, 0, 0, 32768, 0), +(16966, 1, 33745, 0, 0, 0, 0, 0, 0), +(16968, 0, 0, 0, 0, 0, 0, 32768, 0), +(16968, 1, 33745, 0, 0, 0, 0, 0, 0), +(16998, 0, 0, 0, 0, 0, 0, 4096, 0), +(16998, 2, 0, 0, 0, 0, 0, 4096, 0), +(16999, 0, 0, 0, 0, 0, 0, 4096, 0), +(16999, 2, 0, 0, 0, 0, 0, 4096, 0), +(17111, 0, 0, 0, 0, 0, 0, 16, 0), +(17112, 0, 0, 0, 0, 0, 0, 16, 0), +(17113, 0, 0, 0, 0, 0, 0, 16, 0), +(17114, 0, 0, 0, 0, 0, 0, 16, 0), +(17115, 0, 0, 0, 0, 0, 0, 16, 0), +(17116, 0, 0, 8, 0, 0, 0, 0, 0), +(17118, 0, 0, 0, 0, 0, 7, 0, 0), +(17118, 1, 0, 0, 0, 0, 7, 0, 0), +(17119, 0, 0, 0, 0, 0, 7, 0, 0), +(17119, 1, 0, 0, 0, 0, 7, 0, 0), +(17120, 0, 0, 0, 0, 0, 7, 0, 0), +(17120, 1, 0, 0, 0, 0, 7, 0, 0), +(17121, 0, 0, 0, 0, 0, 7, 0, 0), +(17121, 1, 0, 0, 0, 0, 7, 0, 0), +(17122, 0, 0, 0, 0, 0, 7, 0, 0), +(17122, 1, 0, 0, 0, 0, 7, 0, 0), +(17123, 0, 0, 0, 0, 0, 0, 128, 0), +(17124, 0, 0, 0, 0, 0, 0, 128, 0), +(17191, 0, 0, 0, 0, 0, 0, 64, 0), +(17322, 0, 0, 0, 0, 78, 0, 0, 0), +(17323, 0, 0, 0, 0, 78, 0, 0, 0), +(17325, 0, 0, 0, 0, 78, 0, 0, 0), +(17778, 0, 0, 0, 0, 593, 0, 0, 0), +(17779, 0, 0, 0, 0, 593, 0, 0, 0), +(17780, 0, 0, 0, 0, 593, 0, 0, 0), +(17781, 0, 0, 0, 0, 593, 0, 0, 0), +(17782, 0, 0, 0, 0, 593, 0, 0, 0), +(17788, 1, 0, 0, 631, 0, 0, 0, 0), +(17789, 1, 0, 0, 631, 0, 0, 0, 0), +(17790, 1, 0, 0, 631, 0, 0, 0, 0), +(17791, 1, 0, 0, 631, 0, 0, 0, 0), +(17792, 1, 0, 0, 631, 0, 0, 0, 0), +(17917, 0, 0, 0, 0, 593, 0, 0, 0), +(17917, 1, 0, 0, 0, 593, 0, 0, 0), +(17918, 0, 0, 0, 0, 593, 0, 0, 0), +(17918, 1, 0, 0, 0, 593, 0, 0, 0), +(17927, 0, 0, 0, 0, 0, 0, 256, 0), +(17929, 0, 0, 0, 0, 0, 0, 256, 0), +(17930, 0, 0, 0, 0, 0, 0, 256, 0), +(17941, 255, 0, 0, 0, 0, 0, 1, 1), +(17954, 0, 0, 4, 0, 0, 0, 0, 0), +(17954, 1, 0, 4, 0, 0, 0, 0, 0), +(17955, 0, 0, 4, 0, 0, 0, 0, 0), +(17955, 1, 0, 4, 0, 0, 0, 0, 0), +(17956, 0, 0, 4, 0, 0, 0, 0, 0), +(17956, 1, 0, 4, 0, 0, 0, 0, 0), +(17957, 0, 0, 4, 0, 0, 0, 0, 0), +(17957, 1, 0, 4, 0, 0, 0, 0, 0), +(17958, 0, 0, 4, 0, 0, 0, 0, 0), +(17958, 1, 0, 4, 0, 0, 0, 0, 0), +(17959, 0, 0, 0, 0, 593, 0, 0, 0), +(18126, 0, 0, 0, 0, 0, 0, 4096, 0), +(18127, 0, 0, 0, 0, 0, 0, 4096, 0), +(18130, 0, 0, 0, 0, 593, 0, 0, 0), +(18131, 0, 0, 0, 0, 593, 0, 0, 0), +(18132, 0, 0, 0, 0, 593, 0, 0, 0), +(18133, 0, 0, 0, 0, 593, 0, 0, 0), +(18134, 0, 0, 0, 0, 593, 0, 0, 0), +(18135, 0, 0, 0, 0, 593, 0, 0, 0), +(18136, 0, 0, 0, 0, 593, 0, 0, 0), +(18174, 0, 0, 0, 0, 355, 0, 0, 0), +(18175, 0, 0, 0, 0, 355, 0, 0, 0), +(18176, 0, 0, 0, 0, 355, 0, 0, 0), +(18177, 0, 0, 0, 0, 355, 0, 0, 0), +(18178, 0, 0, 0, 0, 355, 0, 0, 0), +(18179, 0, 0, 0, 0, 0, 0, 32768, 0), +(18180, 0, 0, 0, 0, 0, 0, 32768, 0), +(18213, 0, 0, 0, 0, 0, 0, 16384, 0), +(18213, 1, 0, 0, 0, 355, 0, 0, 0), +(18218, 0, 0, 0, 0, 355, 0, 0, 0), +(18219, 0, 0, 0, 0, 355, 0, 0, 0), +(18271, 0, 0, 32, 0, 0, 0, 0, 0), +(18271, 1, 0, 32, 0, 0, 0, 0, 0), +(18272, 0, 0, 32, 0, 0, 0, 0, 0), +(18272, 1, 0, 32, 0, 0, 0, 0, 0), +(18273, 0, 0, 32, 0, 0, 0, 0, 0), +(18273, 1, 0, 32, 0, 0, 0, 0, 0), +(18274, 0, 0, 32, 0, 0, 0, 0, 0), +(18274, 1, 0, 32, 0, 0, 0, 0, 0), +(18275, 0, 0, 32, 0, 0, 0, 0, 0), +(18275, 1, 0, 32, 0, 0, 0, 0, 0), +(18288, 0, 0, 0, 1179, 0, 0, 1024, 0), +(18288, 1, 18223, 0, 0, 0, 0, 0, 0), +(18310, 0, 18223, 0, 0, 0, 0, 0, 0), +(18311, 0, 18223, 0, 0, 0, 0, 0, 0), +(18312, 0, 18223, 0, 0, 0, 0, 0, 0), +(18313, 0, 18223, 0, 0, 0, 0, 0, 0), +(18372, 1, 0, 0, 0, 355, 0, 0, 0), +(18544, 0, 0, 0, 0, 0, 6, 0, 0), +(18544, 1, 0, 0, 0, 0, 6, 0, 0), +(18544, 2, 0, 0, 0, 0, 6, 0, 0), +(18547, 0, 0, 0, 0, 0, 6, 0, 0), +(18547, 1, 0, 0, 0, 0, 6, 0, 0), +(18547, 2, 0, 0, 0, 0, 6, 0, 0), +(18548, 0, 0, 0, 0, 0, 6, 0, 0), +(18548, 1, 0, 0, 0, 0, 6, 0, 0), +(18548, 2, 0, 0, 0, 0, 6, 0, 0), +(18549, 0, 0, 0, 0, 0, 6, 0, 0), +(18549, 1, 0, 0, 0, 0, 6, 0, 0), +(18549, 2, 0, 0, 0, 0, 6, 0, 0), +(18550, 0, 0, 0, 0, 0, 6, 0, 0), +(18550, 1, 0, 0, 0, 0, 6, 0, 0), +(18550, 2, 0, 0, 0, 0, 6, 0, 0), +(18703, 1, 0, 0, 0, 0, 0, 16777216, 0), +(18704, 1, 0, 0, 0, 0, 0, 16777216, 0), +(18731, 0, 0, 0, 0, 0, 0, 268435456, 0), +(18743, 0, 0, 0, 0, 0, 0, 268435456, 0), +(18744, 0, 0, 0, 0, 0, 0, 268435456, 0), +(18748, 0, 0, 0, 0, 0, 0, 134217728, 0), +(18749, 0, 0, 0, 0, 0, 0, 134217728, 0), +(18750, 0, 0, 0, 0, 0, 0, 134217728, 0), +(18767, 1, 0, 0, 0, 0, 0, 131072, 0), +(18768, 1, 0, 0, 0, 0, 0, 131072, 0), +(18821, 0, 0, 0, 0, 0, 0, 2048, 0), +(18821, 1, 0, 0, 0, 0, 0, 2048, 0), +(18821, 2, 0, 0, 0, 0, 0, 2048, 0), +(18822, 0, 0, 0, 0, 0, 0, 2048, 0), +(18822, 1, 0, 0, 0, 0, 0, 2048, 0), +(18822, 2, 0, 0, 0, 0, 0, 2048, 0), +(18827, 0, 0, 0, 0, 0, 0, 1024, 0), +(18829, 0, 0, 0, 0, 0, 0, 1024, 0), +(19416, 0, 0, 0, 0, 0, 0, 252416, 0), +(19417, 0, 0, 0, 0, 0, 0, 252416, 0), +(19418, 0, 0, 0, 0, 0, 0, 252416, 0), +(19419, 0, 0, 0, 0, 0, 0, 252416, 0), +(19420, 0, 0, 0, 0, 0, 0, 252416, 0), +(19461, 0, 0, 0, 0, 0, 0, 12288, 0), +(19461, 1, 0, 0, 0, 0, 0, 12288, 0), +(19462, 0, 0, 0, 0, 0, 0, 12288, 0), +(19462, 1, 0, 0, 0, 0, 0, 12288, 0), +(19464, 0, 0, 0, 0, 0, 0, 16384, 0), +(19464, 1, 0, 0, 1175, 0, 0, 0, 0), +(19464, 2, 0, 0, 0, 0, 0, 252416, 0), +(19465, 0, 0, 0, 0, 0, 0, 16384, 0), +(19465, 1, 0, 0, 1175, 0, 0, 0, 0), +(19465, 2, 0, 0, 0, 0, 0, 252416, 0), +(19466, 0, 0, 0, 0, 0, 0, 16384, 0), +(19466, 1, 0, 0, 1175, 0, 0, 0, 0), +(19466, 2, 0, 0, 0, 0, 0, 252416, 0), +(19467, 0, 0, 0, 0, 0, 0, 16384, 0), +(19467, 1, 0, 0, 1175, 0, 0, 0, 0), +(19467, 2, 0, 0, 0, 0, 0, 252416, 0), +(19468, 0, 0, 0, 0, 0, 0, 16384, 0), +(19468, 1, 0, 0, 1175, 0, 0, 0, 0), +(19468, 2, 0, 0, 0, 0, 0, 252416, 0), +(19498, 0, 0, 0, 0, 0, 0, 1, 0), +(19499, 0, 0, 0, 0, 0, 0, 1, 0), +(19500, 0, 0, 0, 0, 0, 0, 1, 0), +(19549, 0, 0, 0, 0, 0, 0, 524288, 0), +(19550, 0, 0, 0, 0, 0, 0, 524288, 0), +(19551, 0, 0, 0, 0, 0, 0, 524288, 0), +(19552, 0, 0, 0, 0, 0, 0, 1048576, 0), +(19552, 1, 6150, 0, 0, 0, 0, 0, 0), +(19553, 0, 0, 0, 0, 0, 0, 1048576, 0), +(19553, 1, 6150, 0, 0, 0, 0, 0, 0), +(19554, 0, 0, 0, 0, 0, 0, 1048576, 0), +(19554, 1, 6150, 0, 0, 0, 0, 0, 0), +(19555, 0, 0, 0, 0, 0, 0, 1048576, 0), +(19555, 1, 6150, 0, 0, 0, 0, 0, 0), +(19556, 0, 0, 0, 0, 0, 0, 1048576, 0), +(19556, 1, 6150, 0, 0, 0, 0, 0, 0), +(19559, 0, 0, 0, 0, 0, 0, 2097152, 0), +(19560, 0, 0, 0, 0, 0, 0, 2097152, 0), +(19583, 0, 0, 0, 0, 0, 0, 134217728, 0), +(19584, 0, 0, 0, 0, 0, 0, 134217728, 0), +(19585, 0, 0, 0, 0, 0, 0, 134217728, 0), +(19586, 0, 0, 0, 0, 0, 0, 134217728, 0), +(19587, 0, 0, 0, 0, 0, 0, 134217728, 0), +(19590, 0, 0, 0, 0, 0, 0, 536870912, 0), +(19592, 0, 0, 0, 0, 0, 0, 536870912, 0), +(19598, 0, 0, 0, 0, 0, 0, 1073741824, 0), +(19599, 0, 0, 0, 0, 0, 0, 1073741824, 0), +(19600, 0, 0, 0, 0, 0, 0, 1073741824, 0), +(19601, 0, 0, 0, 0, 0, 0, 1073741824, 0), +(19602, 0, 0, 0, 0, 0, 0, 1073741824, 0), +(19609, 0, 0, 0, 0, 0, 0, 67108864, 0), +(19610, 0, 0, 0, 0, 0, 0, 67108864, 0), +(19612, 0, 0, 0, 0, 0, 0, 67108864, 0), +(20101, 0, 0, 0, 0, 0, 0, 402653184, 0), +(20102, 0, 0, 0, 0, 0, 0, 402653184, 0), +(20103, 0, 0, 0, 0, 0, 0, 402653184, 0), +(20104, 0, 0, 0, 0, 0, 0, 402653184, 0), +(20105, 0, 0, 0, 0, 0, 0, 402653184, 0), +(20138, 0, 0, 0, 0, 0, 0, 64, 0), +(20139, 0, 0, 0, 0, 0, 0, 64, 0), +(20140, 0, 0, 0, 0, 0, 0, 64, 0), +(20141, 0, 0, 0, 0, 0, 0, 64, 0), +(20142, 0, 0, 0, 0, 0, 0, 64, 0), +(20174, 0, 0, 0, 0, 0, 0, 128, 0), +(20174, 1, 0, 0, 0, 0, 0, 16, 0), +(20237, 0, 0, 0, 0, 0, 0, 3221225472, 0), +(20238, 0, 0, 0, 0, 0, 0, 3221225472, 0), +(20239, 0, 0, 0, 0, 0, 0, 3221225472, 0), +(20335, 1, 0, 0, 0, 0, 0, 536870912, 0), +(20336, 1, 0, 0, 0, 0, 0, 536870912, 0), +(20337, 1, 0, 0, 0, 0, 0, 536870912, 0), +(20359, 0, 0, 0, 0, 0, 0, 2147483648, 0), +(20360, 0, 0, 0, 0, 0, 0, 2147483648, 0), +(20361, 0, 0, 0, 0, 0, 0, 2147483648, 0), +(20468, 1, 0, 0, 0, 0, 0, 1, 0), +(20469, 1, 0, 0, 0, 0, 0, 1, 0), +(20470, 1, 0, 0, 0, 0, 0, 1, 0), +(20575, 0, 0, 0, 0, 0, 0, 67108864, 0), +(20575, 1, 0, 0, 0, 0, 0, 67108864, 0), +(20576, 0, 0, 0, 0, 0, 0, 33554432, 0), +(21873, 0, 0, 0, 0, 0, 0, 3791650816, 0), +(21881, 0, 0, 0, 0, 0, 0, 122880, 0), +(21887, 0, 0, 0, 0, 0, 4, 0, 0), +(21942, 1, 0, 0, 0, 0, 0, 134217728, 0), +(22008, 0, 0, 0, 0, 0, 3, 0, 1), +(23025, 0, 0, 0, 0, 0, 0, 65536, 0), +(23300, 0, 0, 0, 0, 0, 0, 536870912, 0), +(23555, 0, 0, 0, 0, 593, 0, 0, 0), +(23724, 0, 0, 0, 0, 0, 0, 3791650816, 0), +(23726, 0, 0, 0, 0, 0, 0, 8192, 0), +(23726, 1, 0, 0, 0, 0, 0, 65536, 0), +(24348, 0, 5118, 0, 0, 0, 0, 0, 0), +(24431, 0, 1680, 0, 0, 0, 0, 0, 0), +(24499, 0, 0, 0, 0, 0, 0, 1024, 0), +(24691, 0, 0, 0, 0, 0, 0, 12288, 0), +(24691, 1, 0, 0, 0, 0, 0, 12288, 0), +(26109, 0, 469, 0, 0, 0, 0, 983040, 0), +(26118, 0, 0, 0, 0, 0, 0, 67108864, 0), +(26118, 1, 0, 0, 0, 0, 0, 67108864, 0), +(26174, 0, 0, 0, 0, 0, 0, 32, 0), +(27789, 1, 0, 0, 0, 0, 0, 272630272, 0), +(27790, 1, 0, 0, 0, 0, 0, 272630272, 0), +(27828, 0, 0, 0, 0, 0, 6, 0, 0), +(27846, 0, 0, 0, 0, 0, 0, 32, 0), +(27850, 0, 0, 0, 0, 0, 0, 64, 0), +(27851, 0, 0, 0, 0, 0, 0, 4096, 0), +(28088, 0, 0, 0, 0, 0, 0, 122880, 0), +(28107, 0, 0, 0, 0, 0, 0, 262144, 0), +(28539, 0, 0, 0, 0, 0, 0, 4096, 0), +(28682, 0, 0, 0, 0, 8, 0, 0, 0), +(28743, 0, 0, 0, 0, 0, 0, 240, 0), +(28751, 0, 0, 0, 0, 0, 0, 135168, 0), +(28755, 0, 0, 0, 0, 0, 0, 32, 0), +(28763, 0, 0, 0, 0, 0, 0, 67108864, 0), +(28774, 0, 0, 0, 0, 0, 0, 32768, 0), +(28775, 0, 0, 0, 0, 0, 0, 524288, 0), +(28787, 0, 4987, 0, 0, 0, 0, 0, 0), +(28807, 0, 0, 0, 0, 0, 0, 64, 0), +(28811, 0, 0, 0, 0, 0, 0, 33685510, 0), +(28818, 0, 0, 0, 0, 0, 0, 1073741824, 0), +(28821, 0, 0, 0, 0, 0, 0, 1024, 0), +(28829, 0, 0, 0, 0, 0, 0, 2, 0), +(28830, 0, 0, 0, 0, 0, 0, 262144, 0), +(28831, 0, 0, 0, 0, 0, 0, 1, 0), +(28843, 0, 0, 0, 0, 0, 0, 557056, 0), +(28844, 0, 0, 0, 0, 0, 0, 1024, 0), +(28852, 0, 0, 0, 0, 0, 0, 512, 0), +(28852, 1, 0, 0, 0, 0, 0, 536870912, 0), +(28999, 0, 0, 0, 0, 0, 0, 3, 0), +(29000, 0, 0, 0, 0, 0, 0, 3, 0), +(29005, 0, 0, 0, 0, 0, 0, 2416967683, 0), +(29063, 0, 0, 0, 0, 0, 11, 0, 0), +(29079, 0, 0, 0, 0, 0, 0, 4194304, 0), +(29079, 1, 0, 0, 0, 0, 0, 16777216, 0), +(29079, 2, 0, 0, 0, 0, 0, 8388608, 0), +(29080, 0, 0, 0, 0, 0, 0, 4194304, 0), +(29080, 1, 0, 0, 0, 0, 0, 16777216, 0), +(29080, 2, 0, 0, 0, 0, 0, 8388608, 0), +(29171, 0, 0, 0, 0, 0, 0, 16384, 0), +(29187, 0, 0, 0, 0, 0, 0, 448, 0), +(29189, 0, 0, 0, 0, 0, 0, 448, 0), +(29191, 0, 0, 0, 0, 0, 0, 448, 0), +(29202, 0, 0, 0, 0, 0, 0, 64, 0), +(29205, 0, 0, 0, 0, 0, 0, 64, 0), +(29206, 0, 0, 0, 0, 0, 0, 64, 0), +(29438, 0, 0, 20, 0, 0, 0, 0, 0), +(29439, 0, 0, 20, 0, 0, 0, 0, 0), +(29440, 0, 0, 20, 0, 0, 0, 0, 0), +(29721, 0, 1680, 0, 0, 0, 0, 0, 0), +(29723, 0, 0, 0, 0, 0, 0, 2147491856, 0), +(29723, 1, 0, 0, 0, 0, 0, 2147491856, 0), +(29724, 0, 0, 0, 0, 0, 0, 2147491856, 0), +(29724, 1, 0, 0, 0, 0, 0, 2147491856, 0), +(29725, 0, 0, 0, 0, 0, 0, 2147491856, 0), +(29725, 1, 0, 0, 0, 0, 0, 2147491856, 0), +(29776, 0, 1680, 0, 0, 0, 0, 0, 0), +(29787, 0, 0, 0, 0, 0, 4, 0, 0), +(29790, 0, 0, 0, 0, 0, 4, 0, 0), +(29792, 0, 0, 0, 0, 0, 4, 0, 0), +(29836, 0, 0, 0, 0, 0, 0, 32, 0), +(29859, 0, 0, 0, 0, 0, 0, 32, 0), +(29860, 0, 0, 0, 0, 0, 0, 32, 0), +(29861, 0, 0, 0, 0, 0, 0, 32, 0), +(29862, 0, 0, 0, 0, 0, 0, 32, 0), +(29976, 0, 0, 0, 0, 0, 3, 0, 0), +(30049, 0, 0, 0, 0, 0, 0, 524288, 0), +(30051, 0, 0, 0, 0, 0, 0, 524288, 0), +(30052, 0, 0, 0, 0, 0, 0, 524288, 0), +(30054, 0, 0, 0, 634, 0, 0, 0, 0), +(30057, 0, 0, 0, 634, 0, 0, 0, 0), +(30060, 0, 27243, 0, 0, 0, 0, 1026, 0), +(30060, 1, 27243, 0, 0, 0, 0, 1026, 0), +(30060, 2, 0, 0, 0, 355, 0, 0, 0), +(30061, 0, 27243, 0, 0, 0, 0, 1026, 0), +(30061, 1, 27243, 0, 0, 0, 0, 1026, 0), +(30061, 2, 0, 0, 0, 355, 0, 0, 0), +(30062, 0, 27243, 0, 0, 0, 0, 1026, 0), +(30062, 1, 27243, 0, 0, 0, 0, 1026, 0), +(30062, 2, 0, 0, 0, 355, 0, 0, 0), +(30063, 0, 27243, 0, 0, 0, 0, 1026, 0), +(30063, 1, 27243, 0, 0, 0, 0, 1026, 0), +(30063, 2, 0, 0, 0, 355, 0, 0, 0), +(30064, 0, 27243, 0, 0, 0, 0, 1026, 0), +(30064, 1, 27243, 0, 0, 0, 0, 1026, 0), +(30064, 2, 0, 0, 0, 355, 0, 0, 0), +(30085, 0, 0, 0, 0, 355, 0, 0, 0), +(30085, 1, 0, 0, 0, 0, 0, 1024, 0), +(30085, 2, 0, 0, 0, 0, 0, 2, 0), +(30086, 0, 0, 0, 0, 355, 0, 0, 0), +(30086, 1, 0, 0, 0, 0, 0, 1024, 0), +(30086, 2, 0, 0, 0, 0, 0, 2, 0), +(30251, 0, 0, 0, 0, 593, 0, 0, 0), +(30256, 0, 0, 0, 0, 593, 0, 0, 0), +(30288, 0, 0, 0, 0, 0, 0, 1, 0), +(30289, 0, 0, 0, 0, 0, 0, 1, 0), +(30290, 0, 0, 0, 0, 0, 0, 1, 0), +(30291, 0, 0, 0, 0, 0, 0, 1, 0), +(30292, 0, 0, 0, 0, 0, 0, 1, 0), +(30326, 0, 0, 0, 0, 0, 0, 262160, 0), +(30327, 0, 0, 0, 0, 0, 0, 262160, 0), +(30328, 0, 0, 0, 0, 0, 0, 262160, 0), +(30440, 0, 0, 0, 0, 0, 0, 557056, 0), +(30640, 0, 0, 0, 0, 0, 0, 256, 0), +(30649, 0, 0, 0, 0, 0, 0, 256, 0), +(30872, 0, 0, 0, 0, 0, 0, 256, 0), +(30873, 0, 0, 0, 0, 0, 0, 256, 0), +(30892, 0, 0, 0, 0, 0, 0, 134217728, 0), +(30893, 0, 0, 0, 0, 0, 0, 134217728, 0), +(31226, 0, 0, 0, 0, 0, 0, 122880, 0), +(31227, 0, 0, 0, 0, 0, 0, 122880, 0), +(31234, 0, 0, 0, 0, 0, 8, 0, 0), +(31234, 1, 0, 0, 0, 0, 8, 0, 0), +(31235, 0, 0, 0, 0, 0, 8, 0, 0), +(31235, 1, 0, 0, 0, 0, 8, 0, 0), +(31236, 0, 0, 0, 0, 0, 8, 0, 0), +(31236, 1, 0, 0, 0, 0, 8, 0, 0), +(31237, 0, 0, 0, 0, 0, 8, 0, 0), +(31237, 1, 0, 0, 0, 0, 8, 0, 0), +(31238, 0, 0, 0, 0, 0, 8, 0, 0), +(31238, 1, 0, 0, 0, 0, 8, 0, 0), +(31569, 0, 0, 0, 0, 0, 0, 65536, 0), +(31570, 0, 0, 0, 0, 0, 0, 65536, 0), +(31571, 0, 12536, 0, 0, 0, 0, 0, 0), +(31572, 0, 12536, 0, 0, 0, 0, 0, 0), +(31573, 0, 12536, 0, 0, 0, 0, 0, 0), +(31579, 0, 0, 0, 0, 0, 0, 2048, 0), +(31579, 1, 0, 0, 0, 0, 0, 2048, 0), +(31582, 0, 0, 0, 0, 0, 0, 2048, 0), +(31582, 1, 0, 0, 0, 0, 0, 2048, 0), +(31583, 0, 0, 0, 0, 0, 0, 2048, 0), +(31583, 1, 0, 0, 0, 0, 0, 2048, 0), +(31656, 0, 0, 0, 0, 0, 0, 1, 0), +(31657, 0, 0, 0, 0, 0, 0, 1, 0), +(31658, 0, 0, 0, 0, 0, 0, 1, 0), +(31659, 0, 0, 0, 0, 0, 0, 1, 0), +(31660, 0, 0, 0, 0, 0, 0, 1, 0), +(31682, 0, 0, 0, 0, 0, 0, 32, 0), +(31682, 1, 0, 0, 0, 0, 0, 32, 0), +(31683, 0, 0, 0, 0, 0, 0, 32, 0), +(31683, 1, 0, 0, 0, 0, 0, 32, 0), +(31684, 0, 0, 0, 0, 0, 0, 32, 0), +(31684, 1, 0, 0, 0, 0, 0, 32, 0), +(31685, 1, 0, 0, 0, 0, 0, 32, 0), +(31686, 0, 0, 0, 0, 0, 0, 32, 0), +(31686, 1, 0, 0, 0, 0, 0, 32, 0), +(31821, 0, 0, 0, 0, 0, 0, 67108864, 0), +(31825, 0, 4987, 0, 0, 0, 0, 32, 0), +(31826, 0, 4987, 0, 0, 0, 0, 32, 0), +(31834, 0, 0, 0, 0, 0, 0, 16384, 0), +(31844, 1, 0, 0, 0, 0, 10, 0, 0), +(31845, 1, 0, 0, 0, 0, 10, 0, 0), +(31848, 0, 0, 0, 0, 0, 0, 4194304, 0), +(31848, 1, 0, 0, 0, 0, 0, 4194304, 0), +(31849, 0, 0, 0, 0, 0, 0, 4194304, 0), +(31849, 1, 0, 0, 0, 0, 0, 4194304, 0), +(31869, 0, 20218, 0, 0, 0, 0, 0, 0), +(31870, 0, 20218, 0, 0, 0, 0, 0, 0), +(31879, 0, 0, 0, 0, 0, 0, 8388608, 0), +(31880, 0, 0, 0, 0, 0, 0, 8388608, 0), +(31881, 0, 0, 0, 0, 0, 0, 8388608, 0), +(31882, 0, 0, 0, 0, 0, 0, 8388608, 0), +(31883, 0, 0, 0, 0, 0, 0, 8388608, 0), +(32043, 0, 0, 0, 0, 0, 0, 536870912, 0), +(32203, 1, 0, 0, 0, 0, 9, 0, 0), +(32381, 0, 0, 0, 0, 0, 0, 2, 0), +(32382, 0, 0, 0, 0, 0, 0, 2, 0), +(32383, 0, 0, 0, 0, 0, 0, 2, 0), +(32412, 0, 0, 0, 0, 0, 0, 1024, 0), +(32743, 0, 0, 0, 0, 0, 0, 2048, 0), +(32973, 0, 0, 0, 0, 0, 0, 2416967680, 0), +(33018, 0, 17364, 0, 0, 0, 0, 0, 0), +(33020, 0, 0, 0, 0, 0, 0, 1024, 0), +(33066, 0, 0, 0, 0, 0, 0, 2, 0), +(33151, 0, 0, 0, 0, 0, 0, 128, 1), +(33151, 1, 0, 0, 0, 0, 0, 128, 1), +(33151, 2, 0, 0, 0, 0, 0, 128, 1), +(33158, 0, 0, 0, 0, 0, 0, 4096, 0), +(33158, 1, 0, 0, 0, 0, 0, 2048, 0), +(33159, 0, 0, 0, 0, 0, 0, 4096, 0), +(33159, 1, 0, 0, 0, 0, 0, 2048, 0), +(33160, 0, 0, 0, 0, 0, 0, 4096, 0), +(33160, 1, 0, 0, 0, 0, 0, 2048, 0), +(33161, 0, 0, 0, 0, 0, 0, 4096, 0), +(33161, 1, 0, 0, 0, 0, 0, 2048, 0), +(33162, 0, 0, 0, 0, 0, 0, 4096, 0), +(33162, 1, 0, 0, 0, 0, 0, 2048, 0), +(33174, 0, 0, 0, 0, 0, 0, 32, 0), +(33174, 1, 0, 0, 0, 0, 0, 32, 0), +(33182, 0, 0, 0, 0, 0, 0, 32, 0), +(33182, 1, 0, 0, 0, 0, 0, 32, 0), +(33213, 0, 0, 0, 0, 0, 0, 8527872, 0), +(33214, 0, 0, 0, 0, 0, 0, 8527872, 0), +(33215, 0, 0, 0, 0, 0, 0, 8527872, 0), +(33216, 0, 0, 0, 0, 0, 0, 8527872, 0), +(33217, 0, 0, 0, 0, 0, 0, 8527872, 0), +(33221, 0, 0, 0, 1169, 0, 0, 8192, 0), +(33222, 0, 0, 0, 1169, 0, 0, 8192, 0), +(33223, 0, 0, 0, 1169, 0, 0, 8192, 0), +(33224, 0, 0, 0, 1169, 0, 0, 8192, 0), +(33225, 0, 0, 0, 1169, 0, 0, 8192, 0), +(33333, 0, 0, 0, 0, 0, 0, 536870912, 0), +(33557, 0, 0, 0, 0, 0, 0, 512, 0), +(33557, 1, 0, 0, 0, 0, 0, 536870912, 0), +(33565, 0, 0, 0, 0, 0, 0, 4096, 0), +(33600, 0, 0, 0, 0, 0, 0, 1024, 0), +(33600, 1, 0, 0, 0, 0, 0, 1024, 0), +(33601, 0, 0, 0, 0, 0, 0, 1024, 0), +(33601, 1, 0, 0, 0, 0, 0, 1024, 0), +(33602, 0, 0, 0, 0, 0, 0, 1024, 0), +(33602, 1, 0, 0, 0, 0, 0, 1024, 0), +(33603, 0, 0, 0, 0, 0, 0, 4, 0), +(33603, 1, 0, 0, 0, 0, 0, 1, 0), +(33604, 0, 0, 0, 0, 0, 0, 4, 0), +(33604, 1, 0, 0, 0, 0, 0, 1, 0), +(33605, 0, 0, 0, 0, 0, 0, 4, 0), +(33605, 1, 0, 0, 0, 0, 0, 1, 0), +(33606, 0, 0, 0, 0, 0, 0, 4, 0), +(33606, 1, 0, 0, 0, 0, 0, 1, 0), +(33607, 0, 0, 0, 0, 0, 0, 4, 0), +(33607, 1, 0, 0, 0, 0, 0, 1, 0), +(33693, 0, 0, 0, 0, 0, 0, 32768, 0), +(33696, 0, 0, 0, 0, 0, 0, 1, 0), +(33830, 0, 33786, 0, 0, 0, 0, 0, 0), +(33830, 1, 33786, 0, 0, 0, 0, 0, 0), +(33877, 0, 0, 0, 0, 0, 0, 2, 0), +(33879, 0, 0, 0, 0, 0, 0, 32, 0), +(33880, 0, 0, 0, 0, 0, 0, 32, 0), +(33886, 0, 0, 0, 0, 0, 0, 16, 0), +(33887, 0, 0, 0, 0, 0, 0, 16, 0), +(33888, 0, 0, 0, 0, 0, 0, 16, 0), +(33889, 0, 0, 0, 0, 0, 0, 16, 0), +(33890, 0, 0, 0, 0, 0, 0, 16, 0), +(34128, 0, 33763, 0, 0, 0, 0, 0, 0), +(34129, 0, 0, 0, 0, 0, 0, 8192, 0), +(34129, 1, 0, 0, 0, 0, 0, 8192, 0), +(34131, 0, 0, 0, 0, 0, 0, 128, 0), +(34131, 1, 0, 0, 0, 0, 0, 128, 0), +(34253, 0, 33745, 0, 0, 0, 0, 0, 0), +(34297, 0, 24932, 0, 0, 0, 0, 0, 0), +(34300, 0, 24932, 0, 0, 0, 0, 0, 0), +(34301, 0, 24932, 0, 0, 0, 0, 0, 0), +(34323, 0, 0, 0, 0, 0, 0, 8388608, 0), +(34491, 0, 0, 0, 0, 0, 0, 194, 0), +(34491, 1, 0, 0, 0, 0, 0, 128, 0), +(34492, 0, 0, 0, 0, 0, 0, 194, 0), +(34492, 1, 0, 0, 0, 0, 0, 128, 0), +(34493, 0, 0, 0, 0, 0, 0, 194, 0), +(34493, 1, 0, 0, 0, 0, 0, 128, 0), +(34754, 0, 32546, 0, 0, 0, 0, 6144, 0), +(34936, 0, 0, 0, 0, 0, 0, 1, 0), +(34948, 1, 0, 0, 0, 0, 0, 32, 0), +(34949, 1, 0, 0, 0, 0, 0, 32, 0), +(35098, 0, 0, 0, 0, 0, 0, 133121, 0), +(35099, 0, 0, 0, 0, 0, 0, 133121, 0), +(35104, 0, 0, 0, 0, 0, 0, 4096, 0), +(35104, 1, 0, 0, 0, 0, 0, 8192, 0), +(35110, 0, 0, 0, 0, 0, 0, 4096, 0), +(35110, 1, 0, 0, 0, 0, 0, 8192, 0), +(35111, 0, 0, 0, 0, 0, 0, 4096, 0), +(35111, 1, 0, 0, 0, 0, 0, 8192, 0), +(35363, 0, 0, 0, 0, 0, 0, 5, 0), +(35364, 0, 0, 0, 0, 0, 0, 5, 0), +(35396, 0, 0, 0, 0, 0, 0, 536870912, 0), +(35397, 0, 0, 0, 0, 0, 0, 536870912, 0), +(35578, 0, 0, 0, 0, 0, 3, 0, 0), +(35581, 0, 0, 0, 0, 0, 3, 0, 0), +(36032, 0, 0, 0, 0, 0, 0, 536870912, 0), +(36032, 1, 0, 0, 0, 0, 0, 536870912, 0), +(36413, 0, 0, 0, 0, 0, 0, 1, 0), +(36591, 2, 0, 0, 0, 0, 11, 0, 0), +(37166, 0, 0, 0, 0, 0, 0, 131072, 0), +(37167, 0, 0, 0, 0, 0, 0, 262144, 0), +(37171, 0, 0, 0, 0, 0, 0, 4063232, 0), +(37180, 0, 0, 0, 0, 0, 0, 32, 0), +(37181, 0, 31789, 0, 0, 0, 0, 0, 0), +(37182, 0, 0, 0, 0, 0, 0, 0, 0), +(37183, 0, 20216, 0, 0, 0, 0, 0, 0), +(37185, 0, 0, 0, 931, 0, 0, 0, 0), +(37186, 0, 0, 0, 0, 0, 0, 536870912, 0), +(37188, 0, 0, 0, 0, 0, 0, 64, 0), +(37189, 0, 0, 0, 0, 0, 0, 16384, 0), +(37190, 0, 0, 0, 0, 0, 0, 8, 0), +(37191, 0, 0, 0, 931, 0, 0, 0, 0), +(37194, 0, 0, 0, 0, 0, 0, 8388608, 0), +(37207, 0, 0, 0, 0, 0, 0, 2, 0), +(37210, 0, 0, 0, 0, 0, 0, 16384, 0), +(37211, 0, 16188, 0, 0, 0, 0, 0, 0), +(37212, 0, 2895, 0, 0, 0, 0, 0, 0), +(37223, 0, 0, 0, 0, 0, 0, 65536, 0), +(37224, 0, 32175, 0, 0, 0, 0, 0, 0), +(37225, 0, 0, 0, 0, 0, 0, 128, 0), +(37227, 0, 0, 0, 0, 0, 0, 64, 0), +(37234, 0, 0, 0, 0, 0, 0, 128, 0), +(37240, 0, 0, 0, 0, 0, 0, 128, 0), +(37286, 0, 0, 0, 0, 0, 0, 16, 0), +(37287, 0, 0, 0, 0, 0, 0, 3791650816, 0), +(37292, 0, 16188, 0, 0, 0, 0, 0, 0), +(37297, 0, 29166, 0, 0, 0, 0, 0, 0), +(37313, 0, 0, 0, 0, 0, 0, 64, 0), +(37314, 0, 33763, 0, 0, 0, 0, 0, 0), +(37316, 0, 0, 0, 0, 0, 0, 64, 0), +(37325, 0, 0, 0, 0, 0, 0, 64, 0), +(37333, 0, 0, 0, 0, 0, 0, 32768, 0), +(37333, 1, 33745, 0, 0, 0, 0, 0, 0), +(37376, 0, 27243, 0, 0, 0, 0, 0, 0), +(37380, 0, 0, 0, 0, 0, 0, 6, 0), +(37423, 0, 0, 0, 0, 0, 0, 4, 0), +(37438, 0, 0, 0, 0, 0, 0, 33, 0), +(37439, 0, 12043, 0, 0, 0, 0, 0, 0), +(37439, 1, 0, 0, 0, 0, 0, 8388608, 0), +(37439, 2, 11958, 0, 0, 0, 0, 0, 0), +(37441, 0, 0, 0, 0, 0, 0, 4096, 0), +(37441, 1, 0, 0, 0, 0, 0, 4096, 0), +(37447, 0, 0, 0, 30, 0, 0, 0, 0), +(37481, 0, 0, 0, 0, 0, 0, 128, 0), +(37484, 0, 0, 0, 0, 0, 0, 256, 0), +(37485, 0, 0, 0, 0, 0, 0, 4096, 0), +(37505, 0, 34120, 0, 0, 0, 0, 0, 0), +(37507, 0, 0, 0, 0, 0, 0, 2048, 0), +(37512, 0, 469, 0, 0, 0, 0, 983040, 0), +(37513, 0, 0, 0, 0, 0, 0, 1, 0), +(37517, 0, 0, 0, 0, 0, 4, 0, 0), +(37518, 0, 1680, 0, 0, 0, 0, 0, 0), +(37522, 0, 0, 0, 0, 0, 0, 4096, 0), +(37535, 0, 0, 0, 0, 0, 0, 33554432, 0), +(37536, 0, 0, 0, 0, 0, 0, 65536, 0), +(37556, 0, 32546, 0, 0, 0, 0, 0, 0), +(37564, 0, 0, 0, 0, 0, 0, 512, 0), +(37565, 0, 0, 0, 0, 0, 0, 4096, 0), +(37570, 1, 34433, 0, 0, 0, 0, 0, 0), +(37571, 0, 0, 0, 0, 0, 0, 8388736, 0), +(37593, 0, 0, 0, 0, 0, 0, 64, 0), +(37722, 0, 0, 0, 0, 0, 0, 448, 0), +(37723, 0, 0, 0, 0, 0, 0, 24576, 0), +(37737, 0, 0, 0, 0, 0, 0, 64, 0), +(37738, 0, 0, 0, 0, 0, 0, 64, 0), +(37739, 0, 0, 0, 0, 0, 0, 16384, 0), +(37740, 0, 0, 0, 0, 0, 0, 1, 0), +(37742, 0, 0, 0, 931, 0, 0, 0, 0), +(37760, 0, 0, 0, 0, 0, 0, 1, 0), +(37762, 0, 17364, 0, 0, 0, 0, 0, 0), +(37879, 0, 0, 0, 0, 0, 0, 24576, 0), +(37881, 0, 0, 0, 0, 0, 0, 448, 0), +(38314, 0, 0, 0, 0, 0, 0, 3791650816, 0), +(38321, 0, 0, 0, 0, 0, 0, 32, 0), +(38322, 0, 0, 0, 0, 0, 0, 256, 0), +(38388, 0, 0, 0, 0, 0, 0, 262144, 0), +(38389, 0, 0, 0, 0, 0, 0, 6, 0), +(38390, 0, 34074, 0, 0, 0, 0, 0, 0), +(38392, 0, 34120, 0, 0, 0, 0, 0, 0), +(38393, 0, 0, 0, 0, 0, 0, 1, 0), +(38396, 0, 0, 0, 0, 0, 0, 67108864, 0), +(38397, 0, 0, 0, 0, 0, 0, 2081, 0), +(38398, 0, 0, 0, 0, 0, 0, 4194304, 0), +(38399, 0, 0, 0, 0, 0, 0, 33554432, 0), +(38408, 0, 469, 0, 0, 0, 0, 0, 0), +(38410, 0, 0, 0, 0, 0, 0, 512, 0), +(38411, 0, 0, 0, 0, 0, 0, 4096, 0), +(38412, 0, 0, 0, 0, 0, 0, 8192, 0), +(38413, 0, 0, 0, 0, 0, 0, 32768, 0), +(38414, 0, 0, 0, 0, 0, 0, 2, 0), +(38415, 0, 0, 0, 0, 0, 0, 4, 0), +(38416, 0, 0, 0, 0, 0, 0, 8388608, 0), +(38416, 1, 0, 0, 0, 0, 0, 8388608, 0), +(38417, 0, 5375, 0, 0, 0, 0, 0, 0), +(38420, 0, 0, 0, 0, 0, 0, 32, 0), +(38422, 0, 0, 0, 0, 0, 0, 32, 0), +(38425, 0, 0, 0, 0, 0, 0, 1073741824, 0), +(38426, 0, 0, 0, 0, 0, 0, 2147483648, 0), +(38429, 0, 0, 0, 0, 0, 0, 2416967680, 0), +(38434, 0, 0, 0, 0, 0, 0, 1048832, 0), +(38435, 0, 0, 0, 0, 0, 0, 1048704, 0), +(38436, 0, 0, 0, 0, 0, 0, 1048577, 0), +(38466, 0, 16188, 0, 0, 0, 0, 0, 0), +(38499, 0, 16188, 0, 0, 0, 0, 0, 0), +(38501, 0, 0, 0, 0, 0, 0, 1048704, 0), +(38522, 0, 0, 0, 0, 0, 0, 1073741824, 0); diff --git a/sql/updates/0.7/3766_spell_proc_event.sql b/sql/updates/0.7/3766_spell_proc_event.sql new file mode 100644 index 00000000000..b045b7af485 --- /dev/null +++ b/sql/updates/0.7/3766_spell_proc_event.sql @@ -0,0 +1,4 @@ +REPLACE INTO `spell_proc_event` VALUES (15286, 16, 0, 0, 0, 32768, 0); +REPLACE INTO `spell_proc_event` VALUES (34914, 16, 0, 0, 0, 32768, 0); +REPLACE INTO `spell_proc_event` VALUES (34916, 16, 0, 0, 0, 32768, 0); +REPLACE INTO `spell_proc_event` VALUES (34917, 16, 0, 0, 0, 32768, 0); \ No newline at end of file diff --git a/sql/updates/0.7/3771_creature_template.sql b/sql/updates/0.7/3771_creature_template.sql new file mode 100644 index 00000000000..4240c80f562 --- /dev/null +++ b/sql/updates/0.7/3771_creature_template.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `npcflag` = (`npcflag` | 0x10000) & ~0x40 WHERE `npcflag` & 0x40 = 0x40 AND `name` NOT LIKE '%spirit guide%'; diff --git a/sql/updates/0.7/3773.sql b/sql/updates/0.7/3773.sql new file mode 100644 index 00000000000..6aa0b34b037 --- /dev/null +++ b/sql/updates/0.7/3773.sql @@ -0,0 +1,3 @@ +ALTER TABLE `corpse` ADD INDEX (`instance`); +ALTER TABLE `creature_respawn` ADD INDEX (`instance`); +ALTER TABLE `gameobject_respawn` ADD INDEX (`instance`); diff --git a/sql/updates/0.7/3774_playercreateinfo_spell.sql b/sql/updates/0.7/3774_playercreateinfo_spell.sql new file mode 100644 index 00000000000..aa658850fee --- /dev/null +++ b/sql/updates/0.7/3774_playercreateinfo_spell.sql @@ -0,0 +1,7 @@ +INSERT INTO `playercreateinfo_spell` VALUES ('4','11','33948','Flight Form (Passive)',0); +INSERT INTO `playercreateinfo_spell` VALUES ('6','11','33948','Flight Form (Passive)',0); + +INSERT IGNORE INTO `character_spell` +SELECT `character`.`guid`,`playercreateinfo_spell`.`spell` AS `spell`, '65535' AS `slot`,`playercreateinfo_spell`.`Active` AS `active` +FROM `character`,`playercreateinfo_spell` +WHERE `character`.`class`=`playercreateinfo_spell`.`class` AND `character`.`race`=`playercreateinfo_spell`.`race`; \ No newline at end of file diff --git a/sql/updates/0.7/3782_command.sql b/sql/updates/0.7/3782_command.sql new file mode 100644 index 00000000000..afacab3e7f4 --- /dev/null +++ b/sql/updates/0.7/3782_command.sql @@ -0,0 +1 @@ +UPDATE `command` SET help='Syntax:\r\n.reset level [Playername]\r\n Reset level to 1 including reset stats and talents. Equipped items with greater level requirement can be lost.\r\n.reset spells [Playername]\r\n Removes all non-original spells from spellbook.\r\n.reset stats [Playername]\r\n Resets(recalculate) all stats of the targeted player to their original values at current level.\r\n.reset talents [Playername]\r\n Removes all talents of the targeted player.' WHERE name='reset'; diff --git a/sql/updates/0.7/3784_command.sql b/sql/updates/0.7/3784_command.sql new file mode 100644 index 00000000000..840071d6c0f --- /dev/null +++ b/sql/updates/0.7/3784_command.sql @@ -0,0 +1,4 @@ +DELETE FROM `command` WHERE `name` = 'notify'; +INSERT INTO `command` VALUES('notify',1,'Syntax: .notify $MessageToBroadcast\r\n\r\nSend a global message to all players online in screen.'); +UPDATE `command` SET help='Syntax: .announce $MessageToBroadcast\r\n\r\nSend a global message to all players online in chat log.' WHERE name='announce'; + diff --git a/sql/updates/0.7/3787_spell_proc_event.sql b/sql/updates/0.7/3787_spell_proc_event.sql new file mode 100644 index 00000000000..4ab28992390 --- /dev/null +++ b/sql/updates/0.7/3787_spell_proc_event.sql @@ -0,0 +1,8 @@ +REPLACE INTO `spell_proc_event` VALUES (1120, 0, 0, 0, 0, 4, 0); +REPLACE INTO `spell_proc_event` VALUES (8288, 0, 0, 0, 0, 4, 0); +REPLACE INTO `spell_proc_event` VALUES (8289, 0, 0, 0, 0, 4, 0); +REPLACE INTO `spell_proc_event` VALUES (11675, 0, 0, 0, 0, 4, 0); +REPLACE INTO `spell_proc_event` VALUES (27217, 0, 0, 0, 0, 4, 0); +REPLACE INTO `spell_proc_event` VALUES (24932, 0, 0, 0, 0, 4096, 0); +REPLACE INTO `spell_proc_event` VALUES (31641, 0, 0, 0, 0, 524290, 0); +REPLACE INTO `spell_proc_event` VALUES (31642, 0, 0, 0, 0, 524290, 0); diff --git a/sql/updates/0.7/3801_banAccount.sql b/sql/updates/0.7/3801_banAccount.sql new file mode 100644 index 00000000000..5ae903542fa --- /dev/null +++ b/sql/updates/0.7/3801_banAccount.sql @@ -0,0 +1,33 @@ +ALTER TABLE `realmd`.`ip_banned` + ADD COLUMN `bandate` INT NOT NULL AFTER `ip`, + ADD COLUMN `unbandate` INT NOT NULL AFTER `bandate`, + ADD COLUMN `bannedby` VARCHAR(50) NOT NULL DEFAULT '[Console]' AFTER `unbandate`, + ADD COLUMN `banreason` VARCHAR(50) NOT NULL DEFAULT 'no reason' AFTER `bannedby`; + +ALTER TABLE `realmd`.`account` + DROP KEY `idx_banned`, + DROP COLUMN `banned`; + +-- +-- Table structure for table `account_banned` +-- + +DROP TABLE IF EXISTS `realmd`.`account_banned`; +CREATE TABLE `realmd`.`account_banned` ( + `id` int(11) NOT NULL COMMENT 'Account id' default '0', + `bandate` bigint(40) NOT NULL default '0', + `unbandate` bigint(40) NOT NULL default '0', + `bannedby` VARCHAR(50) NOT NULL, + `banreason` VARCHAR(255) NOT NULL, + `active` TINYINT NOT NULL DEFAULT 1, + PRIMARY KEY (`id`,`bandate`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Ban List'; + +-- +-- Dumping data for table `account_banned` +-- + +LOCK TABLES `realmd`.`account_banned` WRITE; +/*!40000 ALTER TABLE `realmd`.`account_banned` DISABLE KEYS */; +/*!40000 ALTER TABLE `realmd`.`account_banned` ENABLE KEYS */; +UNLOCK TABLES; diff --git a/sql/updates/0.7/3801_command.sql b/sql/updates/0.7/3801_command.sql new file mode 100644 index 00000000000..0cf5fefb29c --- /dev/null +++ b/sql/updates/0.7/3801_command.sql @@ -0,0 +1,6 @@ +DELETE FROM `command` WHERE name in ('banaccount', 'banip', 'unbanaccount', 'unbanip'); + +INSERT INTO `command` VALUES ('ban','3','Syntax is: ban $NameOrIp $bantime $reason\r\nBan account or IP and kick player.\r\n$bantime: negative value leads to permban, otherwise use a timestring like "4d20h3s".'); +INSERT INTO `command` VALUES ('unban','3','Syntax is: unban $NameOrIp\r\nUnban account or IP.'); +INSERT INTO `command` VALUES ('baninfo','3','Syntax is: baninfo \r\nWatch full information about a specific ban.'); +INSERT INTO `command` VALUES ('banlist','3','Syntax is: banlist $NameOrIp\r\nsearches the banlist for a pattern.'); \ No newline at end of file diff --git a/sql/updates/0.7/3802_arena_teams.sql b/sql/updates/0.7/3802_arena_teams.sql new file mode 100644 index 00000000000..def91e339e2 --- /dev/null +++ b/sql/updates/0.7/3802_arena_teams.sql @@ -0,0 +1,44 @@ +/*Table structure for table `arena_team` */ + +DROP TABLE IF EXISTS `arena_team`; + +CREATE TABLE `arena_team` ( + `arenateamid` int(10) unsigned NOT NULL default '0', + `name` char(255) NOT NULL, + `captainguid` int(10) unsigned NOT NULL default '0', + `type` tinyint(3) unsigned NOT NULL default '0', + `EmblemStyle` int(10) unsigned NOT NULL default '0', + `EmblemColor` int(10) unsigned NOT NULL default '0', + `BorderStyle` int(10) unsigned NOT NULL default '0', + `BorderColor` int(10) unsigned NOT NULL default '0', + `BackgroundColor` int(10) unsigned NOT NULL default '0', + PRIMARY KEY (`arenateamid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +/*Table structure for table `arena_team_member` */ + +DROP TABLE IF EXISTS `arena_team_member`; + +CREATE TABLE `arena_team_member` ( + `arenateamid` int(10) unsigned NOT NULL default '0', + `guid` int(10) unsigned NOT NULL default '0', + `played_week` int(10) unsigned NOT NULL default '0', + `wons_week` int(10) unsigned NOT NULL default '0', + `played_season` int(10) unsigned NOT NULL default '0', + `wons_season` int(10) unsigned NOT NULL default '0' +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +/*Table structure for table `arena_team_stats` */ + +DROP TABLE IF EXISTS `arena_team_stats`; + +CREATE TABLE `arena_team_stats` ( + `arenateamid` int(10) unsigned NOT NULL default '0', + `rating` int(10) unsigned NOT NULL default '0', + `games` int(10) unsigned NOT NULL default '0', + `wins` int(10) unsigned NOT NULL default '0', + `played` int(10) unsigned NOT NULL default '0', + `wins2` int(10) unsigned NOT NULL default '0', + `rank` int(10) unsigned NOT NULL default '0', + PRIMARY KEY (`arenateamid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/sql/updates/0.7/3802_petitions.sql b/sql/updates/0.7/3802_petitions.sql new file mode 100644 index 00000000000..7b4e9b8f25a --- /dev/null +++ b/sql/updates/0.7/3802_petitions.sql @@ -0,0 +1,6 @@ +RENAME TABLE `guild_charter` TO `petition`; +RENAME TABLE `guild_charter_sign` TO `petition_sign`; +ALTER TABLE `petition` + CHANGE COLUMN `guildname` `name` varchar(255) NOT NULL default '', + ADD `type` int(10) unsigned NOT NULL default '0' AFTER `name`; +UPDATE `petition` SET `type`='9'; diff --git a/sql/updates/0.7/3805_spell_proc_event.sql b/sql/updates/0.7/3805_spell_proc_event.sql new file mode 100644 index 00000000000..93347648dc5 --- /dev/null +++ b/sql/updates/0.7/3805_spell_proc_event.sql @@ -0,0 +1,5 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN ( '27155','27160','27166'); +INSERT INTO `spell_proc_event` VALUES +('27155', '0', '0', '0', '0', '1', '0'), +('27160', '0', '0', '0', '0', '1', '5'), +('27166', '0', '0', '0', '0', '1', '5'); diff --git a/sql/updates/0.7/3806_petitions.sql b/sql/updates/0.7/3806_petitions.sql new file mode 100644 index 00000000000..5763635faa3 --- /dev/null +++ b/sql/updates/0.7/3806_petitions.sql @@ -0,0 +1,8 @@ +ALTER TABLE `petition` + DROP KEY `index_ownerguid_charterguid`, + CHANGE COLUMN `charterguid` `petitionguid` int(10) unsigned default '0', + ADD UNIQUE KEY `index_ownerguid_petitionguid` (`ownerguid`,`petitionguid`); +ALTER TABLE `petition_sign` + DROP PRIMARY KEY, + CHANGE COLUMN `charterguid` `petitionguid` int(10) unsigned default '0', + ADD PRIMARY KEY (`petitionguid`,`playerguid`); diff --git a/sql/updates/0.7/3833_quest_template.sql b/sql/updates/0.7/3833_quest_template.sql new file mode 100644 index 00000000000..4d373c853bf --- /dev/null +++ b/sql/updates/0.7/3833_quest_template.sql @@ -0,0 +1 @@ +ALTER TABLE `quest_template` CHANGE COLUMN `RewXP` `RewXpOrMoney` int(11) unsigned not null default '0'; \ No newline at end of file diff --git a/sql/updates/0.7/3845_account.sql b/sql/updates/0.7/3845_account.sql new file mode 100644 index 00000000000..c014746eee4 --- /dev/null +++ b/sql/updates/0.7/3845_account.sql @@ -0,0 +1,2 @@ +ALTER TABLE `realmd`.`account` + ADD COLUMN `mutetime` bigint(40) unsigned NOT NULL default '0' AFTER `tbc`; diff --git a/sql/updates/0.7/3845_command.sql b/sql/updates/0.7/3845_command.sql new file mode 100644 index 00000000000..0eb5d32c7b7 --- /dev/null +++ b/sql/updates/0.7/3845_command.sql @@ -0,0 +1,3 @@ +INSERT INTO `command` VALUES('mute',1,'Syntax: .mute $playerName $timeInMinutes\r\n\r\nDisible chat messaging for any character from account of character $playerName at $timeInMinutes minutes.'); +INSERT INTO `command` VALUES('unmute',1,'Syntax: .unmute $playerName\r\n\r\nRestore chat messaging for any character from account of character $playerName.'); + diff --git a/sql/updates/0.7/3859_spell_affect.sql b/sql/updates/0.7/3859_spell_affect.sql new file mode 100644 index 00000000000..6b510b82fb1 --- /dev/null +++ b/sql/updates/0.7/3859_spell_affect.sql @@ -0,0 +1,79 @@ +ALTER TABLE `spell_affect` CHANGE `SpellFamilyMask` `SpellFamilyMask` BIGINT( 20 ) UNSIGNED NOT NULL DEFAULT '0'; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` + 549755813888 WHERE `SpellId` = 469; +UPDATE `spell_affect` SET `SpellId` = '0' WHERE `SpellId` = 469; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` + 17179869184 WHERE `SpellId` = 1680; +UPDATE `spell_affect` SET `SpellId` = '0' WHERE `SpellId` = 1680; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` + 1099511627776 WHERE `SpellId` = 2895; +UPDATE `spell_affect` SET `SpellId` = '0' WHERE `SpellId` = 2895; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` + 4294967296 WHERE `SpellId` = 3600; +UPDATE `spell_affect` SET `SpellId` = '0' WHERE `SpellId` = 3600; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` + 2199023255552 WHERE `SpellId` = 6150; +UPDATE `spell_affect` SET `SpellId` = '0' WHERE `SpellId` = 6150; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` + 549755813888 WHERE `SpellId` = 11958; +UPDATE `spell_affect` SET `SpellId` = '0' WHERE `SpellId` = 11958; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` + 137438953472 WHERE `SpellId` = 12043; +UPDATE `spell_affect` SET `SpellId` = '0' WHERE `SpellId` = 12043; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` + 8589934592 WHERE `SpellId` = 12536; +UPDATE `spell_affect` SET `SpellId` = '0' WHERE `SpellId` = 12536; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` + 549755813888 WHERE `SpellId` = 16188; +UPDATE `spell_affect` SET `SpellId` = '0' WHERE `SpellId` = 16188; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` + 68719476736 WHERE `SpellId` = 17364; +UPDATE `spell_affect` SET `SpellId` = '0' WHERE `SpellId` = 17364; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` + 4194304 WHERE `SpellId` = 18223; +UPDATE `spell_affect` SET `SpellId` = '0' WHERE `SpellId` = 18223; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` + 1099511627776 WHERE `SpellId` = 20216; +UPDATE `spell_affect` SET `SpellId` = '0' WHERE `SpellId` = 20216; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` + 137438953472 WHERE `SpellId` = 20218; +UPDATE `spell_affect` SET `SpellId` = '0' WHERE `SpellId` = 20218; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` + 8796093022208 WHERE `SpellId` = 24932; +UPDATE `spell_affect` SET `SpellId` = '0' WHERE `SpellId` = 24932; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` + 68719476736 WHERE `SpellId` = 27243; +UPDATE `spell_affect` SET `SpellId` = '0' WHERE `SpellId` = 27243; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` + 17592186044416 WHERE `SpellId` = 29166; +UPDATE `spell_affect` SET `SpellId` = '0' WHERE `SpellId` = 29166; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` + 17179869184 WHERE `SpellId` = 31789; +UPDATE `spell_affect` SET `SpellId` = '0' WHERE `SpellId` = 31789; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` + 68719476736 WHERE `SpellId` = 32175; +UPDATE `spell_affect` SET `SpellId` = '0' WHERE `SpellId` = 32175; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` + 17179869184 WHERE `SpellId` = 32546; +UPDATE `spell_affect` SET `SpellId` = '0' WHERE `SpellId` = 32546; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` + 137438953472 WHERE `SpellId` = 33076; +UPDATE `spell_affect` SET `SpellId` = '0' WHERE `SpellId` = 33076; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` + 1099511627776 WHERE `SpellId` = 33745; +UPDATE `spell_affect` SET `SpellId` = '0' WHERE `SpellId` = 33745; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` + 68719476736 WHERE `SpellId` = 33763; +UPDATE `spell_affect` SET `SpellId` = '0' WHERE `SpellId` = 33763; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` + 137438953472 WHERE `SpellId` = 33786; +UPDATE `spell_affect` SET `SpellId` = '0' WHERE `SpellId` = 33786; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` + 1125899906842624 WHERE `SpellId` = 34074; +UPDATE `spell_affect` SET `SpellId` = '0' WHERE `SpellId` = 34074; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` + 4294967296 WHERE `SpellId` = 34120; +UPDATE `spell_affect` SET `SpellId` = '0' WHERE `SpellId` = 34120; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` + 1099511627776 WHERE `SpellId` = 34433; +UPDATE `spell_affect` SET `SpellId` = '0' WHERE `SpellId` = 34433; diff --git a/sql/updates/0.7/3860_creature_template.sql b/sql/updates/0.7/3860_creature_template.sql new file mode 100644 index 00000000000..d30c075f722 --- /dev/null +++ b/sql/updates/0.7/3860_creature_template.sql @@ -0,0 +1,2 @@ +UPDATE `creature_template` SET `npcflag`=`npcflag`|1 WHERE `npcflag`&1024 and `npcflag`&512; +UPDATE `creature_template` SET `npcflag`=`npcflag`& ~1024 WHERE `npcflag`&1024 and (`npcflag`&512)=0; \ No newline at end of file diff --git a/sql/updates/0.7/3862_prospecting_loot_template.sql b/sql/updates/0.7/3862_prospecting_loot_template.sql new file mode 100644 index 00000000000..9d9fd925168 --- /dev/null +++ b/sql/updates/0.7/3862_prospecting_loot_template.sql @@ -0,0 +1,11 @@ +DROP TABLE IF EXISTS `prospecting_loot_template`; +CREATE TABLE `prospecting_loot_template` ( + `entry` int(11) unsigned NOT NULL default '0', + `item` int(11) unsigned NOT NULL default '0', + `ChanceOrRef` float NOT NULL default '100', + `QuestChanceOrGroup` tinyint(3) NOT NULL default '0', + `mincount` tinyint(3) unsigned NOT NULL default '1', + `maxcount` tinyint(3) unsigned NOT NULL default '1', + `quest_freeforall` tinyint(3) unsigned NOT NULL default '1', + PRIMARY KEY (`entry`,`item`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Loot System'; diff --git a/sql/updates/0.7/3874_spell_scripts.sql b/sql/updates/0.7/3874_spell_scripts.sql new file mode 100644 index 00000000000..085a6848ae2 --- /dev/null +++ b/sql/updates/0.7/3874_spell_scripts.sql @@ -0,0 +1 @@ +INSERT INTO `spell_scripts` VALUES ('25650', '0', '6', '530', '0', '', '-589.9764', '4078.306', '143.258', '4.483047'); \ No newline at end of file diff --git a/sql/updates/0.7/3875_item_template.sql b/sql/updates/0.7/3875_item_template.sql new file mode 100644 index 00000000000..1d57fc43f43 --- /dev/null +++ b/sql/updates/0.7/3875_item_template.sql @@ -0,0 +1,3 @@ +ALTER TABLE `item_template` + CHANGE COLUMN `Extra` `RandomProperty_1` int(30) unsigned NOT NULL default '0', + CHANGE COLUMN `unk_203` `RandomProperty_2` int(30) unsigned NOT NULL default '0'; diff --git a/sql/updates/0.7/3876_character_ticket.sql b/sql/updates/0.7/3876_character_ticket.sql new file mode 100644 index 00000000000..9fa78a1fc95 --- /dev/null +++ b/sql/updates/0.7/3876_character_ticket.sql @@ -0,0 +1 @@ +ALTER TABLE `character_ticket` CHANGE `ticket_text` `ticket_text` text; diff --git a/sql/updates/0.7/3884_quest_scripts.sql b/sql/updates/0.7/3884_quest_scripts.sql new file mode 100644 index 00000000000..d563dd56975 --- /dev/null +++ b/sql/updates/0.7/3884_quest_scripts.sql @@ -0,0 +1,2 @@ +ALTER TABLE `quest_template` ADD `StartScript` int(11) unsigned NOT NULL default '0' AFTER `OfferRewardEmote4`; +ALTER TABLE `scripts` ADD `StartOrFinish` int(11) unsigned NOT NULL default '0'; diff --git a/sql/updates/0.7/3891_quest_scripts.sql b/sql/updates/0.7/3891_quest_scripts.sql new file mode 100644 index 00000000000..4811d811442 --- /dev/null +++ b/sql/updates/0.7/3891_quest_scripts.sql @@ -0,0 +1,38 @@ +DROP TABLE IF EXISTS `quest_end_scripts`; +CREATE TABLE `quest_end_scripts` ( + `id` int(11) unsigned NOT NULL default '0', + `delay` int(11) unsigned NOT NULL default '0', + `command` int(11) unsigned NOT NULL default '0', + `datalong` int(11) unsigned NOT NULL default '0', + `datalong2` int(11) unsigned NOT NULL default '0', + `datatext` text NOT NULL, + `x` float NOT NULL default '0', + `y` float NOT NULL default '0', + `z` float NOT NULL default '0', + `o` float NOT NULL default '0' +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `quest_start_scripts`; +CREATE TABLE `quest_start_scripts` ( + `id` int(11) unsigned NOT NULL default '0', + `delay` int(11) unsigned NOT NULL default '0', + `command` int(11) unsigned NOT NULL default '0', + `datalong` int(11) unsigned NOT NULL default '0', + `datalong2` int(11) unsigned NOT NULL default '0', + `datatext` text NOT NULL, + `x` float NOT NULL default '0', + `y` float NOT NULL default '0', + `z` float NOT NULL default '0', + `o` float NOT NULL default '0' +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + +INSERT INTO `quest_end_scripts` +SELECT `id`,`delay`,`command`,`datalong`,`datalong2`,`datatext`,`x`,`y`,`z`,`o` +FROM `scripts` WHERE `StartOrFinish` = 0; + +INSERT INTO `quest_start_scripts` +SELECT `id`,`delay`,`command`,`datalong`,`datalong2`,`datatext`,`x`,`y`,`z`,`o` +FROM `scripts` WHERE `StartOrFinish` = 1; + +DROP TABLE IF EXISTS `scripts`; diff --git a/sql/updates/0.7/3906_areatrigger_template.sql b/sql/updates/0.7/3906_areatrigger_template.sql new file mode 100644 index 00000000000..2a20b349dcf --- /dev/null +++ b/sql/updates/0.7/3906_areatrigger_template.sql @@ -0,0 +1,2 @@ +ALTER TABLE `areatrigger_template` + ADD COLUMN `required_item` int(11) unsigned NOT NULL default '0' AFTER `required_level`; diff --git a/sql/updates/0.7/3929_spell_affect.sql b/sql/updates/0.7/3929_spell_affect.sql new file mode 100644 index 00000000000..4b5f9b40c6f --- /dev/null +++ b/sql/updates/0.7/3929_spell_affect.sql @@ -0,0 +1,38 @@ +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` | 549755813888 WHERE `Category` = 631; +UPDATE `spell_affect` SET `Category` = 0 WHERE `Category` = 631; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` | 549755813888 WHERE `Category` = 1175; +UPDATE `spell_affect` SET `Category` = 0 WHERE `Category` = 1175; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` | 8589934592 WHERE `Category` = 1169; +UPDATE `spell_affect` SET `Category` = 0 WHERE `Category` = 1169; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` | 8589934592 WHERE `Category` = 1179; +UPDATE `spell_affect` SET `Category` = 0 WHERE `Category` = 1179; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` | 34359738368 WHERE `Category` = 634; +UPDATE `spell_affect` SET `Category` = 0 WHERE `Category` = 634; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` | 274877906944 WHERE `Category` = 931; +UPDATE `spell_affect` SET `Category` = 0 WHERE `Category` = 931; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` | 1099511627776 WHERE `Category` = 30; +UPDATE `spell_affect` SET `Category` = 0 WHERE `Category` = 30; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` | 8589934592 WHERE `SpellId` = 5375; +UPDATE `spell_affect` SET `SpellId` = '0' WHERE `SpellId` = 5375; + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` | 68719476736 WHERE (entry=29836 OR entry=29859 OR entry=29860 OR entry=29861 OR entry=29862); + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` | 25769803776 WHERE (entry=14057 OR entry=14128 OR entry=14132 OR entry=14135 OR entry=14136 OR entry=14137 OR entry=14143 OR entry=14149 OR entry=38389); + +UPDATE `spell_affect` SET `SpellFamilyMask` = `SpellFamilyMask` | 34359738368 WHERE (entry=14057 OR entry=14128 OR entry=14132 OR entry=14135 OR entry=14136 OR entry=14137 OR entry=14143 OR entry=14149 OR entry=38389); + +UPDATE `spell_affect` SET `SpellFamilyMask` = '549764202496' WHERE `entry` =34323 AND `effectId` =0 LIMIT 1; + +UPDATE `spell_affect` SET `SpellFamilyMask` = 38658768896 WHERE (entry=14179 OR entry=37171); + +UPDATE `spell_affect` SET `SpellFamilyMask` = 4406678954000 WHERE (entry=15257 OR entry=15331 OR entry=15332 OR entry=15333 OR entry=15334); +UPDATE `spell_affect` SET `SkillID` = 0 WHERE (entry=15257 OR entry=15331 OR entry=15332 OR entry=15333 OR entry=15334); + +UPDATE `spell_affect` SET `SpellFamilyMask` = 0 WHERE (entry=29836 OR entry=29859); \ No newline at end of file diff --git a/sql/updates/0.7/3932_item_enchantment_template.sql b/sql/updates/0.7/3932_item_enchantment_template.sql new file mode 100644 index 00000000000..22970e2d4ba --- /dev/null +++ b/sql/updates/0.7/3932_item_enchantment_template.sql @@ -0,0 +1,7 @@ +DROP TABLE IF EXISTS `item_enchantment_template`; +CREATE TABLE `item_enchantment_template` ( + `entry` int(11) unsigned NOT NULL DEFAULT '0', + `ench` int(10) unsigned NOT NULL DEFAULT '0', + `chance` float unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`entry`,`ench`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Item Random Enchantment System'; diff --git a/sql/updates/0.7/3932_item_template.sql b/sql/updates/0.7/3932_item_template.sql new file mode 100644 index 00000000000..a2ea7b81bad --- /dev/null +++ b/sql/updates/0.7/3932_item_template.sql @@ -0,0 +1,3 @@ +ALTER TABLE `item_template` + CHANGE COLUMN `RandomProperty_1` `RandomProperty` int(30) unsigned NOT NULL default '0', + CHANGE COLUMN `RandomProperty_2` `RandomSuffix` int(30) unsigned NOT NULL default '0'; diff --git a/sql/updates/0.7/3939_realmd_account.sql b/sql/updates/0.7/3939_realmd_account.sql new file mode 100644 index 00000000000..f39240afa42 --- /dev/null +++ b/sql/updates/0.7/3939_realmd_account.sql @@ -0,0 +1,2 @@ +ALTER TABLE `realmd`.`account` CHANGE `password` `I` VARCHAR( 40 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'authentification hash'; +UPDATE `realmd`.`account` SET `I`=SHA1(CONCAT(UPPER(`username`),':',UPPER(`I`))); diff --git a/sql/updates/0.7/3948_realmd_account.sql b/sql/updates/0.7/3948_realmd_account.sql new file mode 100644 index 00000000000..2af4b4d0568 --- /dev/null +++ b/sql/updates/0.7/3948_realmd_account.sql @@ -0,0 +1 @@ +ALTER TABLE `realmd`.`account` CHANGE `username` `username` VARCHAR( 32 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL; diff --git a/sql/updates/0.7/3951_exploration_basexp.sql b/sql/updates/0.7/3951_exploration_basexp.sql new file mode 100644 index 00000000000..0b063249bd8 --- /dev/null +++ b/sql/updates/0.7/3951_exploration_basexp.sql @@ -0,0 +1,8 @@ +DROP TABLE IF EXISTS `exploration_basexp`; +CREATE TABLE `exploration_basexp` ( + `level` tinyint(2) NOT NULL default '0', + `basexp` int(11) NOT NULL default '0', + PRIMARY KEY (`level`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Exploration System'; + +INSERT INTO `exploration_basexp` VALUES (0,0),(1,5),(2,15),(3,25),(4,35),(5,45),(6,55),(7,65),(8,70),(9,80),(10,85),(11,90),(12,90),(13,90),(14,100),(15,105),(16,115),(17,125),(18,135),(19,145),(20,155),(21,165),(22,175),(23,185),(24,195),(25,200),(26,210),(27,220),(28,230),(29,240),(30,245),(31,250),(32,255),(33,265),(34,270),(35,275),(36,280),(37,285),(38,285),(39,300),(40,315),(41,330),(42,345),(43,360),(44,375),(45,390),(46,405),(47,420),(48,440),(49,455),(50,470),(51,490),(52,510),(53,530),(54,540),(55,560),(56,580),(57,600),(58,620),(59,640),(60,660),(61,970),(62,1000),(63,1050),(64,1080),(65,1100),(66,1130),(67,1160),(68,1200),(69,1230),(70,1300); \ No newline at end of file diff --git a/sql/updates/0.7/3961_uptime.sql b/sql/updates/0.7/3961_uptime.sql new file mode 100644 index 00000000000..aa04d1b6ba5 --- /dev/null +++ b/sql/updates/0.7/3961_uptime.sql @@ -0,0 +1,7 @@ +DROP TABLE IF EXISTS `uptime`; +CREATE TABLE `uptime` ( + `starttime` bigint(11) unsigned NOT NULL default '0', + `startstring` varchar(64) NOT NULL default '', + `uptime` bigint(11) unsigned NOT NULL default '0', + PRIMARY KEY (`starttime`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Uptime system'; diff --git a/sql/updates/0.7/3964_command.sql b/sql/updates/0.7/3964_command.sql new file mode 100644 index 00000000000..bf4f73ef022 --- /dev/null +++ b/sql/updates/0.7/3964_command.sql @@ -0,0 +1 @@ +INSERT INTO `command` VALUES ('movecreature',2,'Syntax: .movecreature [#creature_guid]\r\n\r\nMove the targeted creature spawn point to your coordinates.'); diff --git a/sql/updates/0.7/4010_spell_proc_event.sql b/sql/updates/0.7/4010_spell_proc_event.sql new file mode 100644 index 00000000000..d289b3bf85d --- /dev/null +++ b/sql/updates/0.7/4010_spell_proc_event.sql @@ -0,0 +1,10 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN ( '31830','31829','31828'); +INSERT INTO `spell_proc_event` VALUES +('31828', '0', '0', '0', '0', '32768', '0'), +('31829', '0', '0', '0', '0', '32768', '0'), +('31830', '0', '0', '0', '0', '32768', '0'); + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( '33776','31785'); +INSERT INTO `spell_proc_event` VALUES +('31785', '0', '0', '0', '0', '536870912', '0'), +('33776', '0', '0', '0', '0', '536870912', '0'); diff --git a/sql/updates/0.7/4012_spell_proc_event.sql b/sql/updates/0.7/4012_spell_proc_event.sql new file mode 100644 index 00000000000..6ec8225ddff --- /dev/null +++ b/sql/updates/0.7/4012_spell_proc_event.sql @@ -0,0 +1,4 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 9799, 25988 ); +INSERT INTO `spell_proc_event` VALUES +( 9799,0,0,0,0, 262144,0), +(25988,0,0,0,0, 262144,0); diff --git a/sql/updates/0.7/4018_spell_proc_event.sql b/sql/updates/0.7/4018_spell_proc_event.sql new file mode 100644 index 00000000000..2485ad24125 --- /dev/null +++ b/sql/updates/0.7/4018_spell_proc_event.sql @@ -0,0 +1,7 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 20210, 20212, 20213, 20214, 20215 ); +INSERT INTO `spell_proc_event` VALUES +(20210,0,0,0,0,268435456,0), +(20212,0,0,0,0,268435456,0), +(20213,0,0,0,0,268435456,0), +(20214,0,0,0,0,268435456,0), +(20215,0,0,0,0,268435456,0); diff --git a/sql/updates/0.7/4019_spell_chain.sql b/sql/updates/0.7/4019_spell_chain.sql new file mode 100644 index 00000000000..c12ef4c6ae2 --- /dev/null +++ b/sql/updates/0.7/4019_spell_chain.sql @@ -0,0 +1,5 @@ +DELETE FROM `spell_chain` WHERE `spell_id` IN (33776,31785); + +INSERT INTO `spell_chain` VALUES +(31785, 0, 31785, 1), +(33776, 31785, 31785, 2); diff --git a/sql/updates/0.7/4019_spell_proc_event.sql b/sql/updates/0.7/4019_spell_proc_event.sql new file mode 100644 index 00000000000..b462a1c9fe6 --- /dev/null +++ b/sql/updates/0.7/4019_spell_proc_event.sql @@ -0,0 +1,9 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 17106, 17107, 17108 ); +INSERT INTO `spell_proc_event` VALUES +(17106,0,0,0,0,16384,0), +(17107,0,0,0,0,16384,0), +(17108,0,0,0,0,16384,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 34303 ); +INSERT INTO `spell_proc_event` VALUES +(34303,0,0,0,0,128,0); diff --git a/sql/updates/0.7/4020_spell_chain.sql b/sql/updates/0.7/4020_spell_chain.sql new file mode 100644 index 00000000000..a9732bae48d --- /dev/null +++ b/sql/updates/0.7/4020_spell_chain.sql @@ -0,0 +1,4 @@ +DELETE FROM `spell_chain` WHERE `spell_id` IN (33736); + +INSERT INTO `spell_chain` VALUES +(33736,24398,24398,2); \ No newline at end of file diff --git a/sql/updates/0.7/4020_spell_proc_event.sql b/sql/updates/0.7/4020_spell_proc_event.sql new file mode 100644 index 00000000000..ce3239adcb2 --- /dev/null +++ b/sql/updates/0.7/4020_spell_proc_event.sql @@ -0,0 +1,21 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 34082 ); +INSERT INTO `spell_proc_event` VALUES +(34082,0,0,0,0,8192,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 24398, 33736 ); +INSERT INTO `spell_proc_event` VALUES +(24398,0,0,0,0,1049602,0), +(33736,0,0,0,0,1049602,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 324, 325, 905, 945, 8134, 10431, 10432, 25469, 25472 ); +INSERT INTO `spell_proc_event` VALUES +(324,0,0,0,0,1049602,0), +(325,0,0,0,0,1049602,0), +(905,0,0,0,0,1049602,0), +(945,0,0,0,0,1049602,0), +(8134,0,0,0,0,1049602,0), +(10431,0,0,0,0,1049602,0), +(10432,0,0,0,0,1049602,0), + +(25469,0,0,0,0,1049602,0), +(25472,0,0,0,0,1049602,0); diff --git a/sql/updates/0.7/4021_spell_chain.sql b/sql/updates/0.7/4021_spell_chain.sql new file mode 100644 index 00000000000..91c887a318d --- /dev/null +++ b/sql/updates/0.7/4021_spell_chain.sql @@ -0,0 +1,5 @@ +DELETE FROM `spell_chain` WHERE `spell_id` IN (25251, 30335); + +INSERT INTO `spell_chain` VALUES +(25251,23894,23881,5), +(30335,25251,23881,6); diff --git a/sql/updates/0.7/4021_spell_proc_event.sql b/sql/updates/0.7/4021_spell_proc_event.sql new file mode 100644 index 00000000000..c12c054b70b --- /dev/null +++ b/sql/updates/0.7/4021_spell_proc_event.sql @@ -0,0 +1,4 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 25252, 30339 ); +INSERT INTO `spell_proc_event` VALUES +(25252,0,0,0,0,1,0), +(30339,0,0,0,0,1,0); diff --git a/sql/updates/0.7/4023_spell_proc_event.sql b/sql/updates/0.7/4023_spell_proc_event.sql new file mode 100644 index 00000000000..a56d1b9ab17 --- /dev/null +++ b/sql/updates/0.7/4023_spell_proc_event.sql @@ -0,0 +1,11 @@ +ALTER TABLE `spell_proc_event` + CHANGE COLUMN `procFlags` `procFlags` int(11) unsigned NOT NULL default '0'; + +/* on attack miss,dodge,parry and block */ +UPDATE `spell_proc_event` + SET `procFlags` = 3288334336 WHERE `entry` = 26107; + +/* on attack dodge,parry */ +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 37519 ); +INSERT INTO `spell_proc_event` VALUES +(37519,0,0,0,0,67108864,0); diff --git a/sql/updates/0.7/4026_spell_proc_event.sql b/sql/updates/0.7/4026_spell_proc_event.sql new file mode 100644 index 00000000000..f4e4c3243d8 --- /dev/null +++ b/sql/updates/0.7/4026_spell_proc_event.sql @@ -0,0 +1,8 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 20177, 20179, 20181, 20180, 20182, 20178 ); +INSERT INTO `spell_proc_event` VALUES +(20177,0,0,0,0,1049602,0), +(20179,0,0,0,0,1049602,0), +(20180,0,0,0,0,1049602,0), +(20181,0,0,0,0,1049602,0), +(20182,0,0,0,0,1049602,0), +(20178,0,0,0,0,1,0); \ No newline at end of file diff --git a/sql/updates/0.7/4028_spell_chain.sql b/sql/updates/0.7/4028_spell_chain.sql new file mode 100644 index 00000000000..508bcb2aab7 --- /dev/null +++ b/sql/updates/0.7/4028_spell_chain.sql @@ -0,0 +1,18 @@ +DELETE FROM `spell_chain` WHERE `spell_id` IN (33142, 33145, 33146); +INSERT INTO `spell_chain` VALUES +(33142,0,33142,1), +(33145,33142,33142,2), +(33146,33145,33142,3); + +DELETE FROM `spell_chain` WHERE `spell_id` IN (34950, 34594); +INSERT INTO `spell_chain` VALUES +(34950,0,34950,1), +(34594,34950,34950,2); + +DELETE FROM `spell_chain` WHERE `spell_id` IN (34506, 34507, 34508, 34838, 34839); +INSERT INTO `spell_chain` VALUES +(34506,0,34506,1), +(34507,34506,34506,2), +(34508,34507,34506,3), +(34838,34508,34506,4), +(34839,34838,34506,5); \ No newline at end of file diff --git a/sql/updates/0.7/4028_spell_proc_event.sql b/sql/updates/0.7/4028_spell_proc_event.sql new file mode 100644 index 00000000000..daa9c491f77 --- /dev/null +++ b/sql/updates/0.7/4028_spell_proc_event.sql @@ -0,0 +1,35 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 15600 ); +INSERT INTO `spell_proc_event` VALUES +(15600,0,0,0,0,1,3); + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 33142, 33145, 33146 ); +INSERT INTO `spell_proc_event` VALUES +(33142,0,0,0,0,8658944,0), +(33145,0,0,0,0,8658944,0), +(33146,0,0,0,0,8658944,0); + + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 27179 ); +INSERT INTO `spell_proc_event` VALUES +(27179,0,0,0,0,64,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 37443 ); +INSERT INTO `spell_proc_event` VALUES +(37443,0,0,0,0,16384,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 34774 ); +INSERT INTO `spell_proc_event` VALUES +(34774,0,0,0,0,524289,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 34950, 34954 ); +INSERT INTO `spell_proc_event` VALUES +(34950,0,0,0,0,4194304,0), +(34954,0,0,0,0,4194304,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 34506, 34507, 34508, 34838, 34839 ); +INSERT INTO `spell_proc_event` VALUES +(34506,0,0,0,0,524288,0), +(34507,0,0,0,0,524288,0), +(34508,0,0,0,0,524288,0), +(34838,0,0,0,0,524288,0), +(34839,0,0,0,0,524288,0); diff --git a/sql/updates/0.7/4031_spell_chain.sql b/sql/updates/0.7/4031_spell_chain.sql new file mode 100644 index 00000000000..14a4cf23e81 --- /dev/null +++ b/sql/updates/0.7/4031_spell_chain.sql @@ -0,0 +1,10 @@ +DELETE FROM `spell_chain` WHERE `spell_id` IN (34594, 34954); +INSERT INTO `spell_chain` VALUES +(34954,34950,34950,2); + +DELETE FROM `spell_chain` WHERE `spell_id` IN ( 31833, 31835, 31836 ); +INSERT INTO `spell_chain` VALUES +(31833,0,31833,1), +(31835,31833,31833,2), +(31836,31835,31833,3); + diff --git a/sql/updates/0.7/4031_spell_proc_event.sql b/sql/updates/0.7/4031_spell_proc_event.sql new file mode 100644 index 00000000000..10e470e0679 --- /dev/null +++ b/sql/updates/0.7/4031_spell_proc_event.sql @@ -0,0 +1,45 @@ +ALTER TABLE `spell_proc_event` + ADD COLUMN `SpellFamilyName` smallint(6) unsigned NOT NULL default '0' AFTER `SkillID`, + ADD COLUMN `SpellFamilyMaskNew` bigint(11) unsigned NOT NULL default '0' AFTER `SpellFamilyMask`; + +UPDATE `spell_proc_event` + SET `SpellFamilyMaskNew` = `SpellFamilyMask` WHERE `SpellFamilyMask` > 0; + +UPDATE `spell_proc_event` + SET `SpellFamilyMaskNew` = 4294967295 + `SpellFamilyMask` + 1 WHERE `SpellFamilyMask` < 0; + +ALTER TABLE `spell_proc_event` + DROP COLUMN `SpellFamilyMask`, + CHANGE COLUMN `SpellFamilyMaskNew` `SpellFamilyMask` bigint(40) unsigned NOT NULL default '0'; + + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 31833, 31835, 31836 ); +INSERT INTO `spell_proc_event` VALUES +(31833,0,0,0,10,2147483648,16384,0), +(31835,0,0,0,10,2147483648,16384,0), +(31836,0,0,0,10,2147483648,16384,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 33648 ); +INSERT INTO `spell_proc_event` VALUES +(33648,0,0,0,0,0,4096,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 34749 ); +INSERT INTO `spell_proc_event` VALUES +(34749,0,0,0,0,0,33554432,0); + + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 28789 ); +INSERT INTO `spell_proc_event` VALUES +(28789,0,0,0,10,3221225472,16384,0); /* HL FoL */ + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 26119 ); +INSERT INTO `spell_proc_event` VALUES +(26119,0,0,0,10,2416967683,16384,0); /* LB CL and shaman shocks */ + +UPDATE `spell_proc_event` SET `spellFamilyName`=8 WHERE `entry` IN ( 14195,14194,14190,14193,14186 ); + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 20501, 20500 ); +INSERT INTO `spell_proc_event` VALUES +(20500,0,0,0,4,268435456,16384,0), /* BR */ +(20501,0,0,0,4,268435456,16384,0); /* BR */ + diff --git a/sql/updates/0.7/4035_spell_proc_event.sql b/sql/updates/0.7/4035_spell_proc_event.sql new file mode 100644 index 00000000000..b88a406bd14 --- /dev/null +++ b/sql/updates/0.7/4035_spell_proc_event.sql @@ -0,0 +1,10 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 21329, 27857 ); + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 33191, 33192, 33193, 33194, 33195 ); +INSERT INTO `spell_proc_event` VALUES +(33191,0,0,0,6,4398054932480,16384,0), +(33192,0,0,0,6,4398054932480,16384,0), +(33193,0,0,0,6,4398054932480,16384,0), +(33194,0,0,0,6,4398054932480,16384,0), +(33195,0,0,0,6,4398054932480,16384,0); + diff --git a/sql/updates/0.7/4036_spell_proc_event.sql b/sql/updates/0.7/4036_spell_proc_event.sql new file mode 100644 index 00000000000..b48b8811240 --- /dev/null +++ b/sql/updates/0.7/4036_spell_proc_event.sql @@ -0,0 +1 @@ +UPDATE spell_proc_event SET procflags=65536 where entry=16164; \ No newline at end of file diff --git a/sql/updates/0.7/4037_spell_proc_event.sql b/sql/updates/0.7/4037_spell_proc_event.sql new file mode 100644 index 00000000000..c977f74bc2a --- /dev/null +++ b/sql/updates/0.7/4037_spell_proc_event.sql @@ -0,0 +1,8 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 32385, 32387, 32392, 32393, 32394 ); +INSERT INTO `spell_proc_event` VALUES +(32385,0,0,0,6,73014445058,16384,0), +(32387,0,0,0,6,73014445058,16384,0), +(32392,0,0,0,6,73014445058,16384,0), +(32393,0,0,0,6,73014445058,16384,0), +(32394,0,0,0,6,73014445058,16384,0); + diff --git a/sql/updates/0.7/4096_pet.sql b/sql/updates/0.7/4096_pet.sql new file mode 100644 index 00000000000..6bf6536cef5 --- /dev/null +++ b/sql/updates/0.7/4096_pet.sql @@ -0,0 +1,290 @@ +DROP TABLE IF EXISTS `character_pet`; +CREATE TABLE `character_pet` ( + `id` int(11) unsigned NOT NULL default '0', + `entry` int(11) unsigned NOT NULL default '0', + `owner` int(11) unsigned NOT NULL default '0', + `modelid` int(11) unsigned default '0', + `level` int(11) unsigned NOT NULL default '1', + `exp` int(11) unsigned NOT NULL default '0', + `nextlvlexp` int(11) unsigned NOT NULL default '100', + `Reactstate` tinyint(1) unsigned NOT NULL default '0', + `Commandstate` tinyint(1) unsigned NOT NULL default '1', + `loyaltypoints` int(11) NOT NULL default '0', + `loyalty` int(11) unsigned NOT NULL default '0', + `trainpoint` int(11) NOT NULL default '0', + `name` varchar(100) default 'Pet', + `renamed` tinyint(1) unsigned NOT NULL default '0', + `slot` int(11) unsigned NOT NULL default '0', + `curhealth` int(11) unsigned NOT NULL default '1', + `curmana` int(11) unsigned NOT NULL default '0', + `curhappiness` int(11) unsigned NOT NULL default '0', + `savetime` bigint(20) unsigned NOT NULL default '0', + `resettalents_cost` int(11) unsigned NOT NULL default '0', + `resettalents_time` bigint(20) unsigned NOT NULL default '0', + `ABData` longtext, + `TeachSpelldata` longtext, + PRIMARY KEY (`id`), + KEY `owner` (`owner`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Pet System'; + +DROP TABLE IF EXISTS `pet_spell`; +CREATE TABLE `pet_spell` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `spell` int(11) unsigned NOT NULL default '0' COMMENT 'Spell Identifier', + `slot` int(11) unsigned NOT NULL default '0', + `active` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`,`spell`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Pet System'; + +DROP TABLE IF EXISTS `pet_spell_cooldown`; +CREATE TABLE `pet_spell_cooldown` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier, Low part', + `spell` int(11) unsigned NOT NULL default '0' COMMENT 'Spell Identifier', + `time` bigint(20) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`,`spell`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `pet_aura`; +CREATE TABLE `pet_aura` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `spell` int(11) unsigned NOT NULL default '0', + `effect_index` int(11) unsigned NOT NULL default '0', + `remaintime` int(11) NOT NULL default '0', + PRIMARY KEY (`guid`,`spell`,`effect_index`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Pet System'; + +-- ---------------------------- +-- Table structure for petcreateinfo_spell +-- ---------------------------- +DROP TABLE IF EXISTS `petcreateinfo_spell`; +CREATE TABLE `petcreateinfo_spell` ( + `entry` int(11) unsigned NOT NULL DEFAULT '0', + `Spell1` int(11) unsigned NOT NULL DEFAULT '0', + `Spell2` int(11) unsigned NOT NULL DEFAULT '0', + `Spell3` int(11) unsigned NOT NULL DEFAULT '0', + `Spell4` int(11) unsigned NOT NULL DEFAULT '0', + `FamilyPassive` int(11) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Pet Create Spells'; + +ALTER TABLE `pet_levelstats` ADD `armor` int(10) unsigned NOT NULL default '0' AFTER `mana`; + +INSERT INTO `spell_chain` VALUES ('17253', '0', '17253', '1'); +INSERT INTO `spell_chain` VALUES ('17255', '17253', '17253', '2'); +INSERT INTO `spell_chain` VALUES ('17256', '17255', '17253', '3'); +INSERT INTO `spell_chain` VALUES ('17257', '17256', '17253', '4'); +INSERT INTO `spell_chain` VALUES ('17258', '17257', '17253', '5'); +INSERT INTO `spell_chain` VALUES ('17259', '17258', '17253', '6'); +INSERT INTO `spell_chain` VALUES ('17260', '17259', '17253', '7'); +INSERT INTO `spell_chain` VALUES ('17261', '17260', '17253', '8'); +INSERT INTO `spell_chain` VALUES ('27050', '17261', '17253', '9'); +INSERT INTO `spell_chain` VALUES ('16827', '0', '16827', '1'); +INSERT INTO `spell_chain` VALUES ('16828', '16827', '16827', '2'); +INSERT INTO `spell_chain` VALUES ('16829', '16828', '16827', '3'); +INSERT INTO `spell_chain` VALUES ('16830', '16829', '16827', '4'); +INSERT INTO `spell_chain` VALUES ('16831', '16830', '16827', '5'); +INSERT INTO `spell_chain` VALUES ('16832', '16831', '16827', '6'); +INSERT INTO `spell_chain` VALUES ('3010', '16832', '16827', '7'); +INSERT INTO `spell_chain` VALUES ('3009', '3010', '16827', '8'); +INSERT INTO `spell_chain` VALUES ('27049', '3009', '16827', '9'); +INSERT INTO `spell_chain` VALUES ('1742', '0', '1742', '1'); +INSERT INTO `spell_chain` VALUES ('1753', '1742', '1742', '2'); +INSERT INTO `spell_chain` VALUES ('1754', '1753', '1742', '3'); +INSERT INTO `spell_chain` VALUES ('1755', '1754', '1742', '4'); +INSERT INTO `spell_chain` VALUES ('1756', '1755', '1742', '5'); +INSERT INTO `spell_chain` VALUES ('16697', '1756', '1742', '6'); +INSERT INTO `spell_chain` VALUES ('27048', '16697', '1742', '7'); +INSERT INTO `spell_chain` VALUES ('23099', '0', '23099', '1'); +INSERT INTO `spell_chain` VALUES ('23109', '23099', '23099', '2'); +INSERT INTO `spell_chain` VALUES ('23110', '23109', '23099', '3'); +INSERT INTO `spell_chain` VALUES ('23145', '0', '23145', '1'); +INSERT INTO `spell_chain` VALUES ('23147', '23145', '23145', '2'); +INSERT INTO `spell_chain` VALUES ('23148', '23147', '23145', '3'); +INSERT INTO `spell_chain` VALUES ('2649', '0', '2649', '1'); +INSERT INTO `spell_chain` VALUES ('14916', '2649', '2649', '2'); +INSERT INTO `spell_chain` VALUES ('14917', '14916', '2649', '3'); +INSERT INTO `spell_chain` VALUES ('14918', '14917', '2649', '4'); +INSERT INTO `spell_chain` VALUES ('14919', '14918', '2649', '5'); +INSERT INTO `spell_chain` VALUES ('14920', '14919', '2649', '6'); +INSERT INTO `spell_chain` VALUES ('14921', '14920', '2649', '7'); +INSERT INTO `spell_chain` VALUES ('27047', '14921', '2649', '8'); +INSERT INTO `spell_chain` VALUES ('7371', '0', '7371', '1'); +INSERT INTO `spell_chain` VALUES ('26177', '7371', '7371', '2'); +INSERT INTO `spell_chain` VALUES ('26178', '26177', '7371', '3'); +INSERT INTO `spell_chain` VALUES ('26179', '26178', '7371', '4'); +INSERT INTO `spell_chain` VALUES ('26201', '26179', '7371', '5'); +INSERT INTO `spell_chain` VALUES ('27685', '26201', '7371', '6'); +INSERT INTO `spell_chain` VALUES ('24604', '0', '24604', '1'); +INSERT INTO `spell_chain` VALUES ('24605', '24604', '24604', '2'); +INSERT INTO `spell_chain` VALUES ('24603', '24605', '24604', '3'); +INSERT INTO `spell_chain` VALUES ('24597', '24603', '24604', '4'); +INSERT INTO `spell_chain` VALUES ('24844', '0', '24844', '1'); +INSERT INTO `spell_chain` VALUES ('25008', '24844', '24844', '2'); +INSERT INTO `spell_chain` VALUES ('25009', '25008', '24844', '3'); +INSERT INTO `spell_chain` VALUES ('25010', '25009', '24844', '4'); +INSERT INTO `spell_chain` VALUES ('25011', '25010', '24844', '5'); +INSERT INTO `spell_chain` VALUES ('25012', '25011', '24844', '6'); +INSERT INTO `spell_chain` VALUES ('24450', '0', '24450', '1'); +INSERT INTO `spell_chain` VALUES ('24452', '24450', '24450', '2'); +INSERT INTO `spell_chain` VALUES ('24453', '24452', '24450', '3'); +INSERT INTO `spell_chain` VALUES ('24640', '0', '24640', '1'); +INSERT INTO `spell_chain` VALUES ('24583', '24640', '24640', '2'); +INSERT INTO `spell_chain` VALUES ('24586', '24583', '24640', '3'); +INSERT INTO `spell_chain` VALUES ('24587', '24586', '24640', '4'); +INSERT INTO `spell_chain` VALUES ('27060', '24587', '24640', '5'); +INSERT INTO `spell_chain` VALUES ('24423', '0', '24423', '1'); +INSERT INTO `spell_chain` VALUES ('24577', '24423', '24423', '2'); +INSERT INTO `spell_chain` VALUES ('24578', '24577', '24423', '3'); +INSERT INTO `spell_chain` VALUES ('24579', '24578', '24423', '4'); +INSERT INTO `spell_chain` VALUES ('27051', '24579', '24423', '5'); +INSERT INTO `spell_chain` VALUES ('26064', '0', '26064', '1'); +INSERT INTO `spell_chain` VALUES ('26090', '0', '26090', '1'); +INSERT INTO `spell_chain` VALUES ('26187', '26090', '26090', '2'); +INSERT INTO `spell_chain` VALUES ('26188', '26187', '26090', '3'); +INSERT INTO `spell_chain` VALUES ('27063', '26188', '26090', '4'); +INSERT INTO `spell_chain` VALUES ('34889', '0', '34889', '1'); +INSERT INTO `spell_chain` VALUES ('35323', '34889', '34889', '2'); +INSERT INTO `spell_chain` VALUES ('35290', '0', '35290', '1'); +INSERT INTO `spell_chain` VALUES ('35291', '35290', '35290', '2'); +INSERT INTO `spell_chain` VALUES ('35292', '35291', '35290', '3'); +INSERT INTO `spell_chain` VALUES ('35293', '35292', '35290', '4'); +INSERT INTO `spell_chain` VALUES ('35294', '35293', '35290', '5'); +INSERT INTO `spell_chain` VALUES ('35295', '35294', '35290', '6'); +INSERT INTO `spell_chain` VALUES ('35296', '35295', '35290', '7'); +INSERT INTO `spell_chain` VALUES ('35297', '35296', '35290', '8'); +INSERT INTO `spell_chain` VALUES ('35298', '35297', '35290', '9'); +INSERT INTO `spell_chain` VALUES ('35387', '0', '35387', '1'); +INSERT INTO `spell_chain` VALUES ('35389', '35387', '35387', '2'); +INSERT INTO `spell_chain` VALUES ('35392', '35389', '35387', '3'); +INSERT INTO `spell_chain` VALUES ('35346', '0', '35346', '1'); +INSERT INTO `spell_chain` VALUES ('25076', '0', '25076', '1'); +INSERT INTO `spell_chain` VALUES ('35694', '0', '35694', '1'); +INSERT INTO `spell_chain` VALUES ('35698', '35694', '35694', '2'); +INSERT INTO `spell_chain` VALUES ('4187', '0', '4187', '1'); +INSERT INTO `spell_chain` VALUES ('4188', '4187', '4187', '2'); +INSERT INTO `spell_chain` VALUES ('4189', '4188', '4187', '3'); +INSERT INTO `spell_chain` VALUES ('4190', '4189', '4187', '4'); +INSERT INTO `spell_chain` VALUES ('4191', '4190', '4187', '5'); +INSERT INTO `spell_chain` VALUES ('4192', '4191', '4187', '6'); +INSERT INTO `spell_chain` VALUES ('4193', '4192', '4187', '7'); +INSERT INTO `spell_chain` VALUES ('4194', '4193', '4187', '8'); +INSERT INTO `spell_chain` VALUES ('5041', '4194', '4187', '9'); +INSERT INTO `spell_chain` VALUES ('5042', '5041', '4187', '10'); +INSERT INTO `spell_chain` VALUES ('27062', '5042', '4187', '11'); +INSERT INTO `spell_chain` VALUES ('24545', '0', '24545', '1'); +INSERT INTO `spell_chain` VALUES ('24549', '24545', '24545', '2'); +INSERT INTO `spell_chain` VALUES ('24550', '24549', '24545', '3'); +INSERT INTO `spell_chain` VALUES ('24551', '24550', '24545', '4'); +INSERT INTO `spell_chain` VALUES ('24552', '24551', '24545', '5'); +INSERT INTO `spell_chain` VALUES ('24553', '24552', '24545', '6'); +INSERT INTO `spell_chain` VALUES ('24554', '24553', '24545', '7'); +INSERT INTO `spell_chain` VALUES ('24555', '24554', '24545', '8'); +INSERT INTO `spell_chain` VALUES ('24629', '24555', '24545', '9'); +INSERT INTO `spell_chain` VALUES ('24630', '24629', '24545', '10'); +INSERT INTO `spell_chain` VALUES ('27061', '24630', '24545', '11'); +INSERT INTO `spell_chain` VALUES ('24493', '0', '24493', '1'); +INSERT INTO `spell_chain` VALUES ('24497', '24493', '24493', '2'); +INSERT INTO `spell_chain` VALUES ('24500', '24497', '24493', '3'); +INSERT INTO `spell_chain` VALUES ('24501', '24500', '24493', '4'); +INSERT INTO `spell_chain` VALUES ('27052', '24501', '24493', '5'); +INSERT INTO `spell_chain` VALUES ('23992', '0', '23992', '1'); +INSERT INTO `spell_chain` VALUES ('24439', '23992', '23992', '2'); +INSERT INTO `spell_chain` VALUES ('24444', '24439', '23992', '3'); +INSERT INTO `spell_chain` VALUES ('24445', '24444', '23992', '4'); +INSERT INTO `spell_chain` VALUES ('27053', '24445', '23992', '5'); +INSERT INTO `spell_chain` VALUES ('24446', '0', '24446', '1'); +INSERT INTO `spell_chain` VALUES ('24447', '24446', '24446', '2'); +INSERT INTO `spell_chain` VALUES ('24448', '24447', '24446', '3'); +INSERT INTO `spell_chain` VALUES ('24449', '24448', '24446', '4'); +INSERT INTO `spell_chain` VALUES ('27054', '24449', '24446', '5'); +INSERT INTO `spell_chain` VALUES ('24492', '0', '24492', '1'); +INSERT INTO `spell_chain` VALUES ('24502', '24492', '24492', '2'); +INSERT INTO `spell_chain` VALUES ('24503', '24502', '24492', '3'); +INSERT INTO `spell_chain` VALUES ('24504', '24503', '24492', '4'); +INSERT INTO `spell_chain` VALUES ('27055', '24504', '24492', '5'); +INSERT INTO `spell_chain` VALUES ('24488', '0', '24488', '1'); +INSERT INTO `spell_chain` VALUES ('24505', '24488', '24488', '2'); +INSERT INTO `spell_chain` VALUES ('24506', '24505', '24488', '3'); +INSERT INTO `spell_chain` VALUES ('24507', '24506', '24488', '4'); +INSERT INTO `spell_chain` VALUES ('27056', '24507', '24488', '5'); +INSERT INTO `spell_chain` VALUES ('6307', '0', '6307', '1'); +INSERT INTO `spell_chain` VALUES ('7804', '6307', '6307', '2'); +INSERT INTO `spell_chain` VALUES ('7805', '7804', '6307', '3'); +INSERT INTO `spell_chain` VALUES ('11766', '7805', '6307', '4'); +INSERT INTO `spell_chain` VALUES ('11767', '11766', '6307', '5'); +INSERT INTO `spell_chain` VALUES ('27268', '11767', '6307', '6'); +INSERT INTO `spell_chain` VALUES ('2947', '0', '2947', '1'); +INSERT INTO `spell_chain` VALUES ('8316', '2947', '2947', '2'); +INSERT INTO `spell_chain` VALUES ('8317', '8316', '2947', '3'); +INSERT INTO `spell_chain` VALUES ('11770', '8317', '2947', '4'); +INSERT INTO `spell_chain` VALUES ('11771', '11770', '2947', '5'); +INSERT INTO `spell_chain` VALUES ('27269', '11771', '2947', '6'); +INSERT INTO `spell_chain` VALUES ('3110', '0', '3110', '1'); +INSERT INTO `spell_chain` VALUES ('7799', '3110', '3110', '2'); +INSERT INTO `spell_chain` VALUES ('7800', '7799', '3110', '3'); +INSERT INTO `spell_chain` VALUES ('7801', '7800', '3110', '4'); +INSERT INTO `spell_chain` VALUES ('7802', '7801', '3110', '5'); +INSERT INTO `spell_chain` VALUES ('11762', '7802', '3110', '6'); +INSERT INTO `spell_chain` VALUES ('11763', '11762', '3110', '7'); +INSERT INTO `spell_chain` VALUES ('27267', '11763', '3110', '8'); +INSERT INTO `spell_chain` VALUES ('17767', '0', '17767', '1'); +INSERT INTO `spell_chain` VALUES ('17850', '17767', '17767', '2'); +INSERT INTO `spell_chain` VALUES ('17851', '17850', '17767', '3'); +INSERT INTO `spell_chain` VALUES ('17852', '17851', '17767', '4'); +INSERT INTO `spell_chain` VALUES ('17853', '17852', '17767', '5'); +INSERT INTO `spell_chain` VALUES ('17854', '17853', '17767', '6'); +INSERT INTO `spell_chain` VALUES ('27272', '17854', '17767', '7'); +INSERT INTO `spell_chain` VALUES ('7812', '0', '7812', '1'); +INSERT INTO `spell_chain` VALUES ('19438', '7812', '7812', '2'); +INSERT INTO `spell_chain` VALUES ('19440', '19438', '7812', '3'); +INSERT INTO `spell_chain` VALUES ('19441', '19440', '7812', '4'); +INSERT INTO `spell_chain` VALUES ('19442', '19441', '7812', '5'); +INSERT INTO `spell_chain` VALUES ('19443', '19442', '7812', '6'); +INSERT INTO `spell_chain` VALUES ('27273', '19443', '7812', '7'); +INSERT INTO `spell_chain` VALUES ('17735', '0', '17735', '1'); +INSERT INTO `spell_chain` VALUES ('17750', '17735', '17735', '2'); +INSERT INTO `spell_chain` VALUES ('17751', '17750', '17735', '3'); +INSERT INTO `spell_chain` VALUES ('17752', '17751', '17735', '4'); +INSERT INTO `spell_chain` VALUES ('27271', '17752', '17735', '5'); +INSERT INTO `spell_chain` VALUES ('33701', '27271', '17735', '6'); +INSERT INTO `spell_chain` VALUES ('3716', '0', '3716', '1'); +INSERT INTO `spell_chain` VALUES ('7809', '3716', '3716', '2'); +INSERT INTO `spell_chain` VALUES ('7810', '7809', '3716', '3'); +INSERT INTO `spell_chain` VALUES ('7811', '7810', '3716', '4'); +INSERT INTO `spell_chain` VALUES ('11774', '7811', '3716', '5'); +INSERT INTO `spell_chain` VALUES ('11775', '11774', '3716', '6'); +INSERT INTO `spell_chain` VALUES ('27270', '11775', '3716', '7'); +INSERT INTO `spell_chain` VALUES ('7814', '0', '7814', '1'); +INSERT INTO `spell_chain` VALUES ('7815', '7814', '7814', '2'); +INSERT INTO `spell_chain` VALUES ('7816', '7815', '7814', '3'); +INSERT INTO `spell_chain` VALUES ('11778', '7816', '7814', '4'); +INSERT INTO `spell_chain` VALUES ('11779', '11778', '7814', '5'); +INSERT INTO `spell_chain` VALUES ('11780', '11779', '7814', '6'); +INSERT INTO `spell_chain` VALUES ('27274', '11780', '7814', '7'); +INSERT INTO `spell_chain` VALUES ('6360', '0', '6360', '1'); +INSERT INTO `spell_chain` VALUES ('7813', '6360', '6360', '2'); +INSERT INTO `spell_chain` VALUES ('11784', '7813', '6360', '3'); +INSERT INTO `spell_chain` VALUES ('11785', '11784', '6360', '4'); +INSERT INTO `spell_chain` VALUES ('27275', '11785', '6360', '5'); +INSERT INTO `spell_chain` VALUES ('19505', '0', '19505', '1'); +INSERT INTO `spell_chain` VALUES ('19731', '19505', '19505', '2'); +INSERT INTO `spell_chain` VALUES ('19734', '19731', '19505', '3'); +INSERT INTO `spell_chain` VALUES ('19736', '19734', '19505', '4'); +INSERT INTO `spell_chain` VALUES ('27276', '19736', '19505', '5'); +INSERT INTO `spell_chain` VALUES ('27277', '27276', '19505', '6'); +INSERT INTO `spell_chain` VALUES ('19244', '0', '19244', '1'); +INSERT INTO `spell_chain` VALUES ('19647', '19244', '19244', '2'); +INSERT INTO `spell_chain` VALUES ('19478', '0', '19478', '1'); +INSERT INTO `spell_chain` VALUES ('19655', '19478', '19478', '2'); +INSERT INTO `spell_chain` VALUES ('19656', '19655', '19478', '3'); +INSERT INTO `spell_chain` VALUES ('19660', '19656', '19478', '4'); +INSERT INTO `spell_chain` VALUES ('27280', '19660', '19478', '5'); +INSERT INTO `spell_chain` VALUES ('33698', '0', '33698', '1'); +INSERT INTO `spell_chain` VALUES ('33699', '33698', '33698', '2'); +INSERT INTO `spell_chain` VALUES ('33700', '33699', '33698', '3'); +INSERT INTO `spell_chain` VALUES ('30213', '0', '30213', '1'); +INSERT INTO `spell_chain` VALUES ('30219', '30213', '30213', '2'); +INSERT INTO `spell_chain` VALUES ('30223', '30219', '30213', '3'); +INSERT INTO `spell_chain` VALUES ('30151', '0', '30151', '1'); +INSERT INTO `spell_chain` VALUES ('30194', '30151', '30151', '2'); +INSERT INTO `spell_chain` VALUES ('30198', '30194', '30151', '3'); diff --git a/sql/updates/0.8/4058.sql b/sql/updates/0.8/4058.sql new file mode 100644 index 00000000000..e73798a03f5 --- /dev/null +++ b/sql/updates/0.8/4058.sql @@ -0,0 +1,4 @@ +ALTER TABLE `item_template` ADD COLUMN `ArmorDamageModifier` float NOT NULL default '0' AFTER `RequiredDisenchantSkill`; +ALTER TABLE `item_template` DROP COLUMN `name2`, DROP COLUMN `name3`, DROP COLUMN `name4`; +DELETE FROM `spell_affect` WHERE `entry` in(11370,12288,12288,12707,12707,14067,15019,16183,16823,16823,16825,16825,17325,18310,18311,18312,18313,29860,29861,29862,30440,30640,30649,33216,33217,34301); +DELETE FROM `spell_proc_event` WHERE `entry` in(114,637,646,648,1028,1034,1048,1707,2095,2852,4051,4161,4512,5575,5580,6134,6135,6592,6593,7601,7614,7615,7616,7618,9205,9793,9797,9801,9808,10095,10400,10727,10868,11830,11838,11961,12002,12038,12094,12546,12552,13078,13260,13320,13767,13987,14095,14150,14152,14154,15364,15365,15567,15568,15569,15644,15650,16140,16241,16242,16311,16312,16313,16423,16563,16925,16926,16955,16956,16957,16962,16963,16964,17000,17001,17079,17082,19195,19234,19235,19389,19390,19396,19640,20163,20169,20183,20204,20411,20412,20413,20414,20419,20421,20422,20423,20563,20809,20896,21387,21789,22283,22285,22286,22287,22288,22697,22716,23255,23301,23303,23305,23306,25592,25715,25727,25728,25729,25730,25731,25732,25733,25734,25745,25751,25752,25757,25926,25942,25945,26341,28130,28881,29526); \ No newline at end of file diff --git a/sql/updates/0.8/4059_spell_learn_skill.sql b/sql/updates/0.8/4059_spell_learn_skill.sql new file mode 100644 index 00000000000..55b5b893628 --- /dev/null +++ b/sql/updates/0.8/4059_spell_learn_skill.sql @@ -0,0 +1 @@ +DELETE FROM `spell_learn_skill` WHERE `entry` IN ( 3386 ); diff --git a/sql/updates/0.8/4059_spell_learn_spell.sql b/sql/updates/0.8/4059_spell_learn_spell.sql new file mode 100644 index 00000000000..b89ef4b1568 --- /dev/null +++ b/sql/updates/0.8/4059_spell_learn_spell.sql @@ -0,0 +1 @@ +DELETE FROM `spell_learn_spell` WHERE `SpellID` IN ( 2480, 7918, 7919 ); diff --git a/sql/updates/0.8/4076_character_spell.sql b/sql/updates/0.8/4076_character_spell.sql new file mode 100644 index 00000000000..eb11e0291e8 --- /dev/null +++ b/sql/updates/0.8/4076_character_spell.sql @@ -0,0 +1,6 @@ +DELETE FROM `character_spell` WHERE `spell` = '23301'; + +INSERT IGNORE INTO `character_spell` +SELECT `character`.`guid`,`playercreateinfo_spell`.`spell` AS `spell`, '65535' AS `slot`,`playercreateinfo_spell`.`Active` AS `active` +FROM `character`,`playercreateinfo_spell` +WHERE `character`.`class`=`playercreateinfo_spell`.`class` AND `character`.`race`=`playercreateinfo_spell`.`race`; \ No newline at end of file diff --git a/sql/updates/0.8/4076_playercreateinfo_spell.sql b/sql/updates/0.8/4076_playercreateinfo_spell.sql new file mode 100644 index 00000000000..168a7b580fd --- /dev/null +++ b/sql/updates/0.8/4076_playercreateinfo_spell.sql @@ -0,0 +1,2016 @@ +DROP TABLE IF EXISTS `playercreateinfo_spell`; +CREATE TABLE `playercreateinfo_spell` ( + `race` tinyint(3) unsigned NOT NULL default '0', + `class` tinyint(3) unsigned NOT NULL default '0', + `Spell` bigint(20) unsigned NOT NULL default '0', + `Note` varchar(255) default NULL, + `Active` tinyint(3) unsigned NOT NULL default '1', + PRIMARY KEY (`race`,`class`,`Spell`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +INSERT INTO `playercreateinfo_spell` VALUES +(1,1,78,'Heroic Strike',1), +(1,1,81,'Dodge',1), +(1,1,107,'Block',1), +(1,1,196,'One-Handed Axes',1), +(1,1,198,'One-Handed Maces',1), +(1,1,201,'One-Handed Swords',1), +(1,1,203,'Unarmed',1), +(1,1,204,'Defense',1), +(1,1,522,'SPELLDEFENSE(DND)',1), +(1,1,668,'Language Common',1), +(1,1,2382,'Generic',1), +(1,1,2457,'Battle Stance',1), +(1,1,2479,'Honorless Target',1), +(1,1,3050,'Detect',1), +(1,1,3365,'Opening',1), +(1,1,5301,'Defensive State(DND)',1), +(1,1,6233,'Closing',1), +(1,1,6246,'Closing',1), +(1,1,6247,'Opening',1), +(1,1,6477,'Opening',1), +(1,1,6478,'Opening',1), +(1,1,6603,'Attack',1), +(1,1,7266,'Duel',1), +(1,1,7267,'Grovel',1), +(1,1,7355,'Stuck',1), +(1,1,7376,'Defensive Stance Passive',0), +(1,1,7381,'Berserker Stance Passive',0), +(1,1,8386,'Attacking',1), +(1,1,8737,'Mail',1), +(1,1,9077,'Leather',1), +(1,1,9078,'Cloth',1), +(1,1,9116,'Shield',1), +(1,1,9125,'Generic',1), +(1,1,20597,'Sword Specialization',1), +(1,1,20598,'The Human Spirit',1), +(1,1,20599,'Diplomacy',1), +(1,1,20600,'Perception',1), +(1,1,20864,'Mace Specialization',1), +(1,1,21156,'Battle Stance Passive',0), +(1,1,21651,'Opening',1), +(1,1,21652,'Closing',1), +(1,1,22027,'Remove Insignia',1), +(1,1,22810,'Opening - No Text',1), +(1,1,32215,'Victorious State',1), +(1,2,81,'Dodge',1), +(1,2,107,'Block',1), +(1,2,198,'One-Handed Maces',1), +(1,2,199,'Two-Handed Maces',1), +(1,2,203,'Unarmed',1), +(1,2,204,'Defense',1), +(1,2,522,'SPELLDEFENSE(DND)',1), +(1,2,635,'Holy Light',1), +(1,2,668,'Language Common',1), +(1,2,2382,'Generic',1), +(1,2,2479,'Honorless Target',1), +(1,2,3050,'Detect',1), +(1,2,3365,'Opening',1), +(1,2,6233,'Closing',1), +(1,2,6246,'Closing',1), +(1,2,6247,'Opening',1), +(1,2,6477,'Opening',1), +(1,2,6478,'Opening',1), +(1,2,6603,'Attack',1), +(1,2,7266,'Duel',1), +(1,2,7267,'Grovel',1), +(1,2,7355,'Stuck',1), +(1,2,8386,'Attacking',1), +(1,2,8737,'Mail',1), +(1,2,9077,'Leather',1), +(1,2,9078,'Cloth',1), +(1,2,9116,'Shield',1), +(1,2,9125,'Generic',1), +(1,2,20154,'Seal of Righteousness',1), +(1,2,20597,'Sword Specialization',1), +(1,2,20598,'The Human Spirit',1), +(1,2,20599,'Diplomacy',1), +(1,2,20600,'Perception',1), +(1,2,20864,'Mace Specialization',1), +(1,2,21651,'Opening',1), +(1,2,21652,'Closing',1), +(1,2,22027,'Remove Insignia',1), +(1,2,22810,'Opening - No Text',1), +(1,2,27762,'Libram',1), +(1,4,81,'Dodge',1), +(1,4,203,'Unarmed',1), +(1,4,204,'Defense',1), +(1,4,522,'SPELLDEFENSE(DND)',1), +(1,4,668,'Language Common',1), +(1,4,1180,'Daggers',1), +(1,4,1752,'Sinister Strike',1), +(1,4,2098,'Eviscerate',1), +(1,4,2382,'Generic',1), +(1,4,2479,'Honorless Target',1), +(1,4,2567,'Thrown',1), +(1,4,2764,'Throw',1), +(1,4,3050,'Detect',1), +(1,4,3365,'Opening',1), +(1,4,6233,'Closing',1), +(1,4,6246,'Closing',1), +(1,4,6247,'Opening',1), +(1,4,6477,'Opening',1), +(1,4,6478,'Opening',1), +(1,4,6603,'Attack',1), +(1,4,7266,'Duel',1), +(1,4,7267,'Grovel',1), +(1,4,7355,'Stuck',1), +(1,4,8386,'Attacking',1), +(1,4,9077,'Leather',1), +(1,4,9078,'Cloth',1), +(1,4,9125,'Generic',1), +(1,4,16092,'Defensive State(DND)',1), +(1,4,20597,'Sword Specialization',1), +(1,4,20598,'The Human Spirit',1), +(1,4,20599,'Diplomacy',1), +(1,4,20600,'Perception',1), +(1,4,20864,'Mace Specialization',1), +(1,4,21184,'Rogue Passive(DND)',1), +(1,4,21651,'Opening',1), +(1,4,21652,'Closing',1), +(1,4,22027,'Remove Insignia',1), +(1,4,22810,'Opening - No Text',1), +(1,5,81,'Dodge',1), +(1,5,198,'One-Handed Maces',1), +(1,5,203,'Unarmed',1), +(1,5,204,'Defense',1), +(1,5,522,'SPELLDEFENSE(DND)',1), +(1,5,585,'Smite',1), +(1,5,668,'Language Common',1), +(1,5,2050,'Lesser Heal',1), +(1,5,2382,'Generic',1), +(1,5,2479,'Honorless Target',1), +(1,5,3050,'Detect',1), +(1,5,3365,'Opening',1), +(1,5,5009,'Wands',1), +(1,5,5019,'Shoot',1), +(1,5,6233,'Closing',1), +(1,5,6246,'Closing',1), +(1,5,6247,'Opening',1), +(1,5,6477,'Opening',1), +(1,5,6478,'Opening',1), +(1,5,6603,'Attack',1), +(1,5,7266,'Duel',1), +(1,5,7267,'Grovel',1), +(1,5,7355,'Stuck',1), +(1,5,8386,'Attacking',1), +(1,5,9078,'Cloth',1), +(1,5,9125,'Generic',1), +(1,5,20597,'Sword Specialization',1), +(1,5,20598,'The Human Spirit',1), +(1,5,20599,'Diplomacy',1), +(1,5,20600,'Perception',1), +(1,5,20864,'Mace Specialization',1), +(1,5,21651,'Opening',1), +(1,5,21652,'Closing',1), +(1,5,22027,'Remove Insignia',1), +(1,5,22810,'Opening - No Text',1), +(1,8,81,'Dodge',1), +(1,8,133,'Fireball',1), +(1,8,168,'Frost Armor',1), +(1,8,203,'Unarmed',1), +(1,8,204,'Defense',1), +(1,8,227,'Staves',1), +(1,8,522,'SPELLDEFENSE(DND)',1), +(1,8,668,'Language Common',1), +(1,8,2382,'Generic',1), +(1,8,2479,'Honorless Target',1), +(1,8,3050,'Detect',1), +(1,8,3365,'Opening',1), +(1,8,5009,'Wands',1), +(1,8,5019,'Shoot',1), +(1,8,6233,'Closing',1), +(1,8,6246,'Closing',1), +(1,8,6247,'Opening',1), +(1,8,6477,'Opening',1), +(1,8,6478,'Opening',1), +(1,8,6603,'Attack',1), +(1,8,7266,'Duel',1), +(1,8,7267,'Grovel',1), +(1,8,7355,'Stuck',1), +(1,8,8386,'Attacking',1), +(1,8,9078,'Cloth',1), +(1,8,9125,'Generic',1), +(1,8,20597,'Sword Specialization',1), +(1,8,20598,'The Human Spirit',1), +(1,8,20599,'Diplomacy',1), +(1,8,20600,'Perception',1), +(1,8,20864,'Mace Specialization',1), +(1,8,21651,'Opening',1), +(1,8,21652,'Closing',1), +(1,8,22027,'Remove Insignia',1), +(1,8,22810,'Opening - No Text',1), +(1,9,81,'Dodge',1), +(1,9,203,'Unarmed',1), +(1,9,204,'Defense',1), +(1,9,522,'SPELLDEFENSE(DND)',1), +(1,9,668,'Language Common',1), +(1,9,686,'Shadow Bolt',1), +(1,9,687,'Demon Skin',1), +(1,9,1180,'Daggers',1), +(1,9,2382,'Generic',1), +(1,9,2479,'Honorless Target',1), +(1,9,3050,'Detect',1), +(1,9,3365,'Opening',1), +(1,9,5009,'Wands',1), +(1,9,5019,'Shoot',1), +(1,9,6233,'Closing',1), +(1,9,6246,'Closing',1), +(1,9,6247,'Opening',1), +(1,9,6477,'Opening',1), +(1,9,6478,'Opening',1), +(1,9,6603,'Attack',1), +(1,9,7266,'Duel',1), +(1,9,7267,'Grovel',1), +(1,9,7355,'Stuck',1), +(1,9,8386,'Attacking',1), +(1,9,9078,'Cloth',1), +(1,9,9125,'Generic',1), +(1,9,20597,'Sword Specialization',1), +(1,9,20598,'The Human Spirit',1), +(1,9,20599,'Diplomacy',1), +(1,9,20600,'Perception',1), +(1,9,20864,'Mace Specialization',1), +(1,9,21651,'Opening',1), +(1,9,21652,'Closing',1), +(1,9,22027,'Remove Insignia',1), +(1,9,22810,'Opening - No Text',1), +(2,1,78,'Heroic Strike',1), +(2,1,81,'Dodge',1), +(2,1,107,'Block',1), +(2,1,196,'One-Handed Axes',1), +(2,1,197,'Two-Handed Axes',1), +(2,1,201,'One-Handed Swords',1), +(2,1,203,'Unarmed',1), +(2,1,204,'Defense',1), +(2,1,522,'SPELLDEFENSE(DND)',1), +(2,1,669,'Language Orcish',1), +(2,1,2382,'Generic',1), +(2,1,2457,'Battle Stance',1), +(2,1,2479,'Honorless Target',1), +(2,1,3050,'Detect',1), +(2,1,3365,'Opening',1), +(2,1,5301,'Defensive State(DND)',1), +(2,1,6233,'Closing',1), +(2,1,6246,'Closing',1), +(2,1,6247,'Opening',1), +(2,1,6477,'Opening',1), +(2,1,6478,'Opening',1), +(2,1,6603,'Attack',1), +(2,1,7266,'Duel',1), +(2,1,7267,'Grovel',1), +(2,1,7355,'Stuck',1), +(2,1,7376,'Defensive Stance Passive',0), +(2,1,7381,'Berserker Stance Passive',0), +(2,1,8386,'Attacking',1), +(2,1,8737,'Mail',1), +(2,1,9077,'Leather',1), +(2,1,9078,'Cloth',1), +(2,1,9116,'Shield',1), +(2,1,9125,'Generic',1), +(2,1,20572,'Blood Fury',1), +(2,1,20573,'Hardiness',1), +(2,1,20574,'Axe Specialization',1), +(2,1,21156,'Battle Stance Passive',0), +(2,1,21563,'Command',1), +(2,1,21651,'Opening',1), +(2,1,21652,'Closing',1), +(2,1,22027,'Remove Insignia',1), +(2,1,22810,'Opening - No Text',1), +(2,1,32215,'Victorious State',1), +(2,3,75,'Auto Shot',1), +(2,3,81,'Dodge',1), +(2,3,196,'One-Handed Axes',1), +(2,3,203,'Unarmed',1), +(2,3,204,'Defense',1), +(2,3,264,'Bows',1), +(2,3,522,'SPELLDEFENSE(DND)',1), +(2,3,669,'Language Orcish',1), +(2,3,2382,'Generic',1), +(2,3,2479,'Honorless Target',1), +(2,3,2973,'Raptor Strike',1), +(2,3,3050,'Detect',1), +(2,3,3365,'Opening',1), +(2,3,6233,'Closing',1), +(2,3,6246,'Closing',1), +(2,3,6247,'Opening',1), +(2,3,6477,'Opening',1), +(2,3,6478,'Opening',1), +(2,3,6603,'Attack',1), +(2,3,7266,'Duel',1), +(2,3,7267,'Grovel',1), +(2,3,7355,'Stuck',1), +(2,3,8386,'Attacking',1), +(2,3,9077,'Leather',1), +(2,3,9078,'Cloth',1), +(2,3,9125,'Generic',1), +(2,3,13358,'Defensive State(DND)',1), +(2,3,20572,'Blood Fury',1), +(2,3,20573,'Hardiness',1), +(2,3,20574,'Axe Specialization',1), +(2,3,20576,'Command',1), +(2,3,21651,'Opening',1), +(2,3,21652,'Closing',1), +(2,3,22027,'Remove Insignia',1), +(2,3,22810,'Opening - No Text',1), +(2,3,24949,'Defensive State 2(DND)',1), +(2,3,34082,'Advantaged State(DND)',1), +(2,4,81,'Dodge',1), +(2,4,203,'Unarmed',1), +(2,4,204,'Defense',1), +(2,4,522,'SPELLDEFENSE(DND)',1), +(2,4,669,'Language Orcish',1), +(2,4,1180,'Daggers',1), +(2,4,1752,'Sinister Strike',1), +(2,4,2098,'Eviscerate',1), +(2,4,2382,'Generic',1), +(2,4,2479,'Honorless Target',1), +(2,4,2567,'Thrown',1), +(2,4,2764,'Throw',1), +(2,4,3050,'Detect',1), +(2,4,3365,'Opening',1), +(2,4,6233,'Closing',1), +(2,4,6246,'Closing',1), +(2,4,6247,'Opening',1), +(2,4,6477,'Opening',1), +(2,4,6478,'Opening',1), +(2,4,6603,'Attack',1), +(2,4,7266,'Duel',1), +(2,4,7267,'Grovel',1), +(2,4,7355,'Stuck',1), +(2,4,8386,'Attacking',1), +(2,4,9077,'Leather',1), +(2,4,9078,'Cloth',1), +(2,4,9125,'Generic',1), +(2,4,16092,'Defensive State(DND)',1), +(2,4,20572,'Blood Fury',1), +(2,4,20573,'Hardiness',1), +(2,4,20574,'Axe Specialization',1), +(2,4,21184,'Rogue Passive(DND)',1), +(2,4,21563,'Command',1), +(2,4,21651,'Opening',1), +(2,4,21652,'Closing',1), +(2,4,22027,'Remove Insignia',1), +(2,4,22810,'Opening - No Text',1), +(2,7,81,'Dodge',1), +(2,7,107,'Block',1), +(2,7,198,'One-Handed Maces',1), +(2,7,203,'Unarmed',1), +(2,7,204,'Defense',1), +(2,7,227,'Staves',1), +(2,7,331,'Healing Wave',1), +(2,7,403,'Lightning Bolt',1), +(2,7,522,'SPELLDEFENSE(DND)',1), +(2,7,669,'Language Orcish',1), +(2,7,2382,'Generic',1), +(2,7,2479,'Honorless Target',1), +(2,7,3050,'Detect',1), +(2,7,3365,'Opening',1), +(2,7,6233,'Closing',1), +(2,7,6246,'Closing',1), +(2,7,6247,'Opening',1), +(2,7,6477,'Opening',1), +(2,7,6478,'Opening',1), +(2,7,6603,'Attack',1), +(2,7,7266,'Duel',1), +(2,7,7267,'Grovel',1), +(2,7,7355,'Stuck',1), +(2,7,8386,'Attacking',1), +(2,7,9077,'Leather',1), +(2,7,9078,'Cloth',1), +(2,7,9116,'Shield',1), +(2,7,9125,'Generic',1), +(2,7,20573,'Hardiness',1), +(2,7,20574,'Axe Specialization',1), +(2,7,21563,'Command',1), +(2,7,21651,'Opening',1), +(2,7,21652,'Closing',1), +(2,7,22027,'Remove Insignia',1), +(2,7,22810,'Opening - No Text',1), +(2,7,27763,'Totem',1), +(2,7,33697,'Blood Fury',1), +(2,9,81,'Dodge',1), +(2,9,203,'Unarmed',1), +(2,9,204,'Defense',1), +(2,9,522,'SPELLDEFENSE(DND)',1), +(2,9,669,'Language Orcish',1), +(2,9,686,'Shadow Bolt',1), +(2,9,687,'Demon Skin',1), +(2,9,1180,'Daggers',1), +(2,9,2382,'Generic',1), +(2,9,2479,'Honorless Target',1), +(2,9,3050,'Detect',1), +(2,9,3365,'Opening',1), +(2,9,5009,'Wands',1), +(2,9,5019,'Shoot',1), +(2,9,6233,'Closing',1), +(2,9,6246,'Closing',1), +(2,9,6247,'Opening',1), +(2,9,6477,'Opening',1), +(2,9,6478,'Opening',1), +(2,9,6603,'Attack',1), +(2,9,7266,'Duel',1), +(2,9,7267,'Grovel',1), +(2,9,7355,'Stuck',1), +(2,9,8386,'Attacking',1), +(2,9,9078,'Cloth',1), +(2,9,9125,'Generic',1), +(2,9,20573,'Hardiness',1), +(2,9,20574,'Axe Specialization',1), +(2,9,20575,'Command',1), +(2,9,21651,'Opening',1), +(2,9,21652,'Closing',1), +(2,9,22027,'Remove Insignia',1), +(2,9,22810,'Opening - No Text',1), +(2,9,33702,'Blood Fury',1), +(3,1,78,'Heroic Strike',1), +(3,1,81,'Dodge',1), +(3,1,107,'Block',1), +(3,1,196,'One-Handed Axes',1), +(3,1,197,'Two-Handed Axes',1), +(3,1,198,'One-Handed Maces',1), +(3,1,203,'Unarmed',1), +(3,1,204,'Defense',1), +(3,1,522,'SPELLDEFENSE(DND)',1), +(3,1,668,'Language Common',1), +(3,1,672,'Language Dwarven',1), +(3,1,2382,'Generic',1), +(3,1,2457,'Battle Stance',1), +(3,1,2479,'Honorless Target',1), +(3,1,2481,'Find Treasure',1), +(3,1,3050,'Detect',1), +(3,1,3365,'Opening',1), +(3,1,5301,'Defensive State(DND)',1), +(3,1,6233,'Closing',1), +(3,1,6246,'Closing',1), +(3,1,6247,'Opening',1), +(3,1,6477,'Opening',1), +(3,1,6478,'Opening',1), +(3,1,6603,'Attack',1), +(3,1,7266,'Duel',1), +(3,1,7267,'Grovel',1), +(3,1,7355,'Stuck',1), +(3,1,7376,'Defensive Stance Passive',0), +(3,1,7381,'Berserker Stance Passive',0), +(3,1,8386,'Attacking',1), +(3,1,8737,'Mail',1), +(3,1,9077,'Leather',1), +(3,1,9078,'Cloth',1), +(3,1,9116,'Shield',1), +(3,1,9125,'Generic',1), +(3,1,20594,'Stoneform',1), +(3,1,20595,'Gun Specialization',1), +(3,1,20596,'Frost Resistance',1), +(3,1,21156,'Battle Stance Passive',0), +(3,1,21651,'Opening',1), +(3,1,21652,'Closing',1), +(3,1,22027,'Remove Insignia',1), +(3,1,22810,'Opening - No Text',1), +(3,1,32215,'Victorious State',1), +(3,2,81,'Dodge',1), +(3,2,107,'Block',1), +(3,2,198,'One-Handed Maces',1), +(3,2,199,'Two-Handed Maces',1), +(3,2,203,'Unarmed',1), +(3,2,204,'Defense',1), +(3,2,522,'SPELLDEFENSE(DND)',1), +(3,2,635,'Holy Light',1), +(3,2,668,'Language Common',1), +(3,2,672,'Language Dwarven',1), +(3,2,2382,'Generic',1), +(3,2,2479,'Honorless Target',1), +(3,2,2481,'Find Treasure',1), +(3,2,3050,'Detect',1), +(3,2,3365,'Opening',1), +(3,2,6233,'Closing',1), +(3,2,6246,'Closing',1), +(3,2,6247,'Opening',1), +(3,2,6477,'Opening',1), +(3,2,6478,'Opening',1), +(3,2,6603,'Attack',1), +(3,2,7266,'Duel',1), +(3,2,7267,'Grovel',1), +(3,2,7355,'Stuck',1), +(3,2,8386,'Attacking',1), +(3,2,8737,'Mail',1), +(3,2,9077,'Leather',1), +(3,2,9078,'Cloth',1), +(3,2,9116,'Shield',1), +(3,2,9125,'Generic',1), +(3,2,20154,'Seal of Righteousness',1), +(3,2,20594,'Stoneform',1), +(3,2,20595,'Gun Specialization',1), +(3,2,20596,'Frost Resistance',1), +(3,2,21651,'Opening',1), +(3,2,21652,'Closing',1), +(3,2,22027,'Remove Insignia',1), +(3,2,22810,'Opening - No Text',1), +(3,2,27762,'Libram',1), +(3,3,75,'Auto Shot',1), +(3,3,81,'Dodge',1), +(3,3,196,'One-Handed Axes',1), +(3,3,203,'Unarmed',1), +(3,3,204,'Defense',1), +(3,3,266,'Guns',1), +(3,3,522,'SPELLDEFENSE(DND)',1), +(3,3,668,'Language Common',1), +(3,3,672,'Language Dwarven',1), +(3,3,2382,'Generic',1), +(3,3,2479,'Honorless Target',1), +(3,3,2481,'Find Treasure',1), +(3,3,2973,'Raptor Strike',1), +(3,3,3050,'Detect',1), +(3,3,3365,'Opening',1), +(3,3,6233,'Closing',1), +(3,3,6246,'Closing',1), +(3,3,6247,'Opening',1), +(3,3,6477,'Opening',1), +(3,3,6478,'Opening',1), +(3,3,6603,'Attack',1), +(3,3,7266,'Duel',1), +(3,3,7267,'Grovel',1), +(3,3,7355,'Stuck',1), +(3,3,8386,'Attacking',1), +(3,3,9077,'Leather',1), +(3,3,9078,'Cloth',1), +(3,3,9125,'Generic',1), +(3,3,13358,'Defensive State(DND)',1), +(3,3,20594,'Stoneform',1), +(3,3,20595,'Gun Specialization',1), +(3,3,20596,'Frost Resistance',1), +(3,3,21651,'Opening',1), +(3,3,21652,'Closing',1), +(3,3,22027,'Remove Insignia',1), +(3,3,22810,'Opening - No Text',1), +(3,3,24949,'Defensive State 2(DND)',1), +(3,3,34082,'Advantaged State(DND)',1), +(3,4,81,'Dodge',1), +(3,4,203,'Unarmed',1), +(3,4,204,'Defense',1), +(3,4,522,'SPELLDEFENSE(DND)',1), +(3,4,668,'Language Common',1), +(3,4,672,'Language Dwarven',1), +(3,4,1180,'Daggers',1), +(3,4,1752,'Sinister Strike',1), +(3,4,2098,'Eviscerate',1), +(3,4,2382,'Generic',1), +(3,4,2479,'Honorless Target',1), +(3,4,2481,'Find Treasure',1), +(3,4,2567,'Thrown',1), +(3,4,2764,'Throw',1), +(3,4,3050,'Detect',1), +(3,4,3365,'Opening',1), +(3,4,6233,'Closing',1), +(3,4,6246,'Closing',1), +(3,4,6247,'Opening',1), +(3,4,6477,'Opening',1), +(3,4,6478,'Opening',1), +(3,4,6603,'Attack',1), +(3,4,7266,'Duel',1), +(3,4,7267,'Grovel',1), +(3,4,7355,'Stuck',1), +(3,4,8386,'Attacking',1), +(3,4,9077,'Leather',1), +(3,4,9078,'Cloth',1), +(3,4,9125,'Generic',1), +(3,4,16092,'Defensive State(DND)',1), +(3,4,20594,'Stoneform',1), +(3,4,20595,'Gun Specialization',1), +(3,4,20596,'Frost Resistance',1), +(3,4,21184,'Rogue Passive(DND)',1), +(3,4,21651,'Opening',1), +(3,4,21652,'Closing',1), +(3,4,22027,'Remove Insignia',1), +(3,4,22810,'Opening - No Text',1), +(3,5,81,'Dodge',1), +(3,5,198,'One-Handed Maces',1), +(3,5,203,'Unarmed',1), +(3,5,204,'Defense',1), +(3,5,522,'SPELLDEFENSE(DND)',1), +(3,5,585,'Smite',1), +(3,5,668,'Language Common',1), +(3,5,672,'Language Dwarven',1), +(3,5,2050,'Lesser Heal',1), +(3,5,2382,'Generic',1), +(3,5,2479,'Honorless Target',1), +(3,5,2481,'Find Treasure',1), +(3,5,3050,'Detect',1), +(3,5,3365,'Opening',1), +(3,5,5009,'Wands',1), +(3,5,5019,'Shoot',1), +(3,5,6233,'Closing',1), +(3,5,6246,'Closing',1), +(3,5,6247,'Opening',1), +(3,5,6477,'Opening',1), +(3,5,6478,'Opening',1), +(3,5,6603,'Attack',1), +(3,5,7266,'Duel',1), +(3,5,7267,'Grovel',1), +(3,5,7355,'Stuck',1), +(3,5,8386,'Attacking',1), +(3,5,9078,'Cloth',1), +(3,5,9125,'Generic',1), +(3,5,20594,'Stoneform',1), +(3,5,20595,'Gun Specialization',1), +(3,5,20596,'Frost Resistance',1), +(3,5,21651,'Opening',1), +(3,5,21652,'Closing',1), +(3,5,22027,'Remove Insignia',1), +(3,5,22810,'Opening - No Text',1), +(4,1,78,'Heroic Strike',1), +(4,1,81,'Dodge',1), +(4,1,107,'Block',1), +(4,1,198,'One-Handed Maces',1), +(4,1,201,'One-Handed Swords',1), +(4,1,203,'Unarmed',1), +(4,1,204,'Defense',1), +(4,1,522,'SPELLDEFENSE(DND)',1), +(4,1,668,'Language Common',1), +(4,1,671,'Language Darnassian',1), +(4,1,1180,'Daggers',1), +(4,1,2382,'Generic',1), +(4,1,2457,'Battle Stance',1), +(4,1,2479,'Honorless Target',1), +(4,1,3050,'Detect',1), +(4,1,3365,'Opening',1), +(4,1,5301,'Defensive State(DND)',1), +(4,1,6233,'Closing',1), +(4,1,6246,'Closing',1), +(4,1,6247,'Opening',1), +(4,1,6477,'Opening',1), +(4,1,6478,'Opening',1), +(4,1,6603,'Attack',1), +(4,1,7266,'Duel',1), +(4,1,7267,'Grovel',1), +(4,1,7355,'Stuck',1), +(4,1,7376,'Defensive Stance Passive',0), +(4,1,7381,'Berserker Stance Passive',0), +(4,1,8386,'Attacking',1), +(4,1,8737,'Mail',1), +(4,1,9077,'Leather',1), +(4,1,9078,'Cloth',1), +(4,1,9116,'Shield',1), +(4,1,9125,'Generic',1), +(4,1,20580,'Shadowmeld',1), +(4,1,20582,'Quickness',1), +(4,1,20583,'Nature Resistance',1), +(4,1,20585,'Wisp Spirit',1), +(4,1,21009,'Shadowmeld Passive',1), +(4,1,21156,'Battle Stance Passive',0), +(4,1,21651,'Opening',1), +(4,1,21652,'Closing',1), +(4,1,22027,'Remove Insignia',1), +(4,1,22810,'Opening - No Text',1), +(4,1,32215,'Victorious State',1), +(4,3,75,'Auto Shot',1), +(4,3,81,'Dodge',1), +(4,3,203,'Unarmed',1), +(4,3,204,'Defense',1), +(4,3,264,'Bows',1), +(4,3,522,'SPELLDEFENSE(DND)',1), +(4,3,668,'Language Common',1), +(4,3,671,'Language Darnassian',1), +(4,3,1180,'Daggers',1), +(4,3,2382,'Generic',1), +(4,3,2479,'Honorless Target',1), +(4,3,2973,'Raptor Strike',1), +(4,3,3050,'Detect',1), +(4,3,3365,'Opening',1), +(4,3,6233,'Closing',1), +(4,3,6246,'Closing',1), +(4,3,6247,'Opening',1), +(4,3,6477,'Opening',1), +(4,3,6478,'Opening',1), +(4,3,6603,'Attack',1), +(4,3,7266,'Duel',1), +(4,3,7267,'Grovel',1), +(4,3,7355,'Stuck',1), +(4,3,8386,'Attacking',1), +(4,3,9077,'Leather',1), +(4,3,9078,'Cloth',1), +(4,3,9125,'Generic',1), +(4,3,13358,'Defensive State(DND)',1), +(4,3,20580,'Shadowmeld',1), +(4,3,20582,'Quickness',1), +(4,3,20583,'Nature Resistance',1), +(4,3,20585,'Wisp Spirit',1), +(4,3,21009,'Shadowmeld Passive',1), +(4,3,21651,'Opening',1), +(4,3,21652,'Closing',1), +(4,3,22027,'Remove Insignia',1), +(4,3,22810,'Opening - No Text',1), +(4,3,24949,'Defensive State 2(DND)',1), +(4,3,34082,'Advantaged State(DND)',1), +(4,4,81,'Dodge',1), +(4,4,203,'Unarmed',1), +(4,4,204,'Defense',1), +(4,4,522,'SPELLDEFENSE(DND)',1), +(4,4,668,'Language Common',1), +(4,4,671,'Language Darnassian',1), +(4,4,1180,'Daggers',1), +(4,4,1752,'Sinister Strike',1), +(4,4,2098,'Eviscerate',1), +(4,4,2382,'Generic',1), +(4,4,2479,'Honorless Target',1), +(4,4,2567,'Thrown',1), +(4,4,2764,'Throw',1), +(4,4,3050,'Detect',1), +(4,4,3365,'Opening',1), +(4,4,6233,'Closing',1), +(4,4,6246,'Closing',1), +(4,4,6247,'Opening',1), +(4,4,6477,'Opening',1), +(4,4,6478,'Opening',1), +(4,4,6603,'Attack',1), +(4,4,7266,'Duel',1), +(4,4,7267,'Grovel',1), +(4,4,7355,'Stuck',1), +(4,4,8386,'Attacking',1), +(4,4,9077,'Leather',1), +(4,4,9078,'Cloth',1), +(4,4,9125,'Generic',1), +(4,4,16092,'Defensive State(DND)',1), +(4,4,20580,'Shadowmeld',1), +(4,4,20582,'Quickness',1), +(4,4,20583,'Nature Resistance',1), +(4,4,20585,'Wisp Spirit',1), +(4,4,21009,'Shadowmeld Passive',1), +(4,4,21184,'Rogue Passive(DND)',1), +(4,4,21651,'Opening',1), +(4,4,21652,'Closing',1), +(4,4,22027,'Remove Insignia',1), +(4,4,22810,'Opening - No Text',1), +(4,5,81,'Dodge',1), +(4,5,198,'One-Handed Maces',1), +(4,5,203,'Unarmed',1), +(4,5,204,'Defense',1), +(4,5,522,'SPELLDEFENSE(DND)',1), +(4,5,585,'Smite',1), +(4,5,668,'Language Common',1), +(4,5,671,'Language Darnassian',1), +(4,5,2050,'Lesser Heal',1), +(4,5,2382,'Generic',1), +(4,5,2479,'Honorless Target',1), +(4,5,3050,'Detect',1), +(4,5,3365,'Opening',1), +(4,5,5009,'Wands',1), +(4,5,5019,'Shoot',1), +(4,5,6233,'Closing',1), +(4,5,6246,'Closing',1), +(4,5,6247,'Opening',1), +(4,5,6477,'Opening',1), +(4,5,6478,'Opening',1), +(4,5,6603,'Attack',1), +(4,5,7266,'Duel',1), +(4,5,7267,'Grovel',1), +(4,5,7355,'Stuck',1), +(4,5,8386,'Attacking',1), +(4,5,9078,'Cloth',1), +(4,5,9125,'Generic',1), +(4,5,20580,'Shadowmeld',1), +(4,5,20582,'Quickness',1), +(4,5,20583,'Nature Resistance',1), +(4,5,20585,'Wisp Spirit',1), +(4,5,21009,'Shadowmeld Passive',1), +(4,5,21651,'Opening',1), +(4,5,21652,'Closing',1), +(4,5,22027,'Remove Insignia',1), +(4,5,22810,'Opening - No Text',1), +(4,11,81,'Dodge',1), +(4,11,203,'Unarmed',1), +(4,11,204,'Defense',1), +(4,11,227,'Staves',1), +(4,11,522,'SPELLDEFENSE(DND)',1), +(4,11,668,'Language Common',1), +(4,11,671,'Language Darnassian',1), +(4,11,1178,'Bear Form(Passive)',0), +(4,11,1180,'Daggers',1), +(4,11,2382,'Generic',1), +(4,11,2479,'Honorless Target',1), +(4,11,3025,'Cat Form(Passive)',0), +(4,11,3050,'Detect',1), +(4,11,3365,'Opening',1), +(4,11,5176,'Wrath',1), +(4,11,5185,'Healing Touch',1), +(4,11,5419,'Travel Form(Passive)',0), +(4,11,5420,'Tree of Life',0), +(4,11,5421,'Aquatic Form(Passive)',0), +(4,11,6233,'Closing',1), +(4,11,6246,'Closing',1), +(4,11,6247,'Opening',1), +(4,11,6477,'Opening',1), +(4,11,6478,'Opening',1), +(4,11,6603,'Attack',1), +(4,11,7266,'Duel',1), +(4,11,7267,'Grovel',1), +(4,11,7355,'Stuck',1), +(4,11,8386,'Attacking',1), +(4,11,9077,'Leather',1), +(4,11,9078,'Cloth',1), +(4,11,9125,'Generic',1), +(4,11,9635,'Dire Bear Form(Passive)',0), +(4,11,20580,'Shadowmeld',1), +(4,11,20582,'Quickness',1), +(4,11,20583,'Nature Resistance',1), +(4,11,20585,'Wisp Spirit',1), +(4,11,21009,'Shadowmeld Passive',1), +(4,11,21178,'Bear Form(Passive2)',0), +(4,11,21651,'Opening',1), +(4,11,21652,'Closing',1), +(4,11,22027,'Remove Insignia',1), +(4,11,22810,'Opening - No Text',1), +(4,11,24905,'Moonkin Form(Passive)',0), +(4,11,27764,'Fetish',1), +(4,11,33948,'Flight Form(Passive)',0), +(4,11,34123,'Tree of Life(Passive)',0), +(4,11,40121,'Swift Flight Form(Passive)',0), +(5,1,78,'Heroic Strike',1), +(5,1,81,'Dodge',1), +(5,1,107,'Block',1), +(5,1,201,'One-Handed Swords',1), +(5,1,202,'Two-Handed Swords',1), +(5,1,203,'Unarmed',1), +(5,1,204,'Defense',1), +(5,1,522,'SPELLDEFENSE(DND)',1), +(5,1,669,'Language Orcish',1), +(5,1,1180,'Daggers',1), +(5,1,2382,'Generic',1), +(5,1,2457,'Battle Stance',1), +(5,1,2479,'Honorless Target',1), +(5,1,3050,'Detect',1), +(5,1,3365,'Opening',1), +(5,1,5227,'Underwater Breathing',1), +(5,1,5301,'Defensive State(DND)',1), +(5,1,6233,'Closing',1), +(5,1,6246,'Closing',1), +(5,1,6247,'Opening',1), +(5,1,6477,'Opening',1), +(5,1,6478,'Opening',1), +(5,1,6603,'Attack',1), +(5,1,7266,'Duel',1), +(5,1,7267,'Grovel',1), +(5,1,7355,'Stuck',1), +(5,1,7376,'Defensive Stance Passive',0), +(5,1,7381,'Berserker Stance Passive',0), +(5,1,7744,'Will of the Forsaken',1), +(5,1,8386,'Attacking',1), +(5,1,8737,'Mail',1), +(5,1,9077,'Leather',1), +(5,1,9078,'Cloth',1), +(5,1,9116,'Shield',1), +(5,1,9125,'Generic',1), +(5,1,17737,'Language Gutterspeak',1), +(5,1,20577,'Cannibalize',1), +(5,1,20579,'Shadow Resistance',1), +(5,1,21156,'Battle Stance Passive',0), +(5,1,21651,'Opening',1), +(5,1,21652,'Closing',1), +(5,1,22027,'Remove Insignia',1), +(5,1,22810,'Opening - No Text',1), +(5,1,32215,'Victorious State',1), +(5,4,81,'Dodge',1), +(5,4,203,'Unarmed',1), +(5,4,204,'Defense',1), +(5,4,522,'SPELLDEFENSE(DND)',1), +(5,4,669,'Language Orcish',1), +(5,4,1180,'Daggers',1), +(5,4,1752,'Sinister Strike',1), +(5,4,2098,'Eviscerate',1), +(5,4,2382,'Generic',1), +(5,4,2479,'Honorless Target',1), +(5,4,2567,'Thrown',1), +(5,4,2764,'Throw',1), +(5,4,3050,'Detect',1), +(5,4,3365,'Opening',1), +(5,4,5227,'Underwater Breathing',1), +(5,4,6233,'Closing',1), +(5,4,6246,'Closing',1), +(5,4,6247,'Opening',1), +(5,4,6477,'Opening',1), +(5,4,6478,'Opening',1), +(5,4,6603,'Attack',1), +(5,4,7266,'Duel',1), +(5,4,7267,'Grovel',1), +(5,4,7355,'Stuck',1), +(5,4,7744,'Will of the Forsaken',1), +(5,4,8386,'Attacking',1), +(5,4,9077,'Leather',1), +(5,4,9078,'Cloth',1), +(5,4,9125,'Generic',1), +(5,4,16092,'Defensive State(DND)',1), +(5,4,17737,'Language Gutterspeak',1), +(5,4,20577,'Cannibalize',1), +(5,4,20579,'Shadow Resistance',1), +(5,4,21184,'Rogue Passive(DND)',1), +(5,4,21651,'Opening',1), +(5,4,21652,'Closing',1), +(5,4,22027,'Remove Insignia',1), +(5,4,22810,'Opening - No Text',1), +(5,5,81,'Dodge',1), +(5,5,198,'One-Handed Maces',1), +(5,5,203,'Unarmed',1), +(5,5,204,'Defense',1), +(5,5,522,'SPELLDEFENSE(DND)',1), +(5,5,585,'Smite',1), +(5,5,669,'Language Orcish',1), +(5,5,2050,'Lesser Heal',1), +(5,5,2382,'Generic',1), +(5,5,2479,'Honorless Target',1), +(5,5,3050,'Detect',1), +(5,5,3365,'Opening',1), +(5,5,5009,'Wands',1), +(5,5,5019,'Shoot',1), +(5,5,5227,'Underwater Breathing',1), +(5,5,6233,'Closing',1), +(5,5,6246,'Closing',1), +(5,5,6247,'Opening',1), +(5,5,6477,'Opening',1), +(5,5,6478,'Opening',1), +(5,5,6603,'Attack',1), +(5,5,7266,'Duel',1), +(5,5,7267,'Grovel',1), +(5,5,7355,'Stuck',1), +(5,5,7744,'Will of the Forsaken',1), +(5,5,8386,'Attacking',1), +(5,5,9078,'Cloth',1), +(5,5,9125,'Generic',1), +(5,5,17737,'Language Gutterspeak',1), +(5,5,20577,'Cannibalize',1), +(5,5,20579,'Shadow Resistance',1), +(5,5,21651,'Opening',1), +(5,5,21652,'Closing',1), +(5,5,22027,'Remove Insignia',1), +(5,5,22810,'Opening - No Text',1), +(5,8,81,'Dodge',1), +(5,8,133,'Fireball',1), +(5,8,168,'Frost Armor',1), +(5,8,203,'Unarmed',1), +(5,8,204,'Defense',1), +(5,8,227,'Staves',1), +(5,8,522,'SPELLDEFENSE(DND)',1), +(5,8,669,'Language Orcish',1), +(5,8,2382,'Generic',1), +(5,8,2479,'Honorless Target',1), +(5,8,3050,'Detect',1), +(5,8,3365,'Opening',1), +(5,8,5009,'Wands',1), +(5,8,5019,'Shoot',1), +(5,8,5227,'Underwater Breathing',1), +(5,8,6233,'Closing',1), +(5,8,6246,'Closing',1), +(5,8,6247,'Opening',1), +(5,8,6477,'Opening',1), +(5,8,6478,'Opening',1), +(5,8,6603,'Attack',1), +(5,8,7266,'Duel',1), +(5,8,7267,'Grovel',1), +(5,8,7355,'Stuck',1), +(5,8,7744,'Will of the Forsaken',1), +(5,8,8386,'Attacking',1), +(5,8,9078,'Cloth',1), +(5,8,9125,'Generic',1), +(5,8,17737,'Language Gutterspeak',1), +(5,8,20577,'Cannibalize',1), +(5,8,20579,'Shadow Resistance',1), +(5,8,21651,'Opening',1), +(5,8,21652,'Closing',1), +(5,8,22027,'Remove Insignia',1), +(5,8,22810,'Opening - No Text',1), +(5,9,81,'Dodge',1), +(5,9,203,'Unarmed',1), +(5,9,204,'Defense',1), +(5,9,522,'SPELLDEFENSE(DND)',1), +(5,9,669,'Language Orcish',1), +(5,9,686,'Shadow Bolt',1), +(5,9,687,'Demon Skin',1), +(5,9,1180,'Daggers',1), +(5,9,2382,'Generic',1), +(5,9,2479,'Honorless Target',1), +(5,9,3050,'Detect',1), +(5,9,3365,'Opening',1), +(5,9,5009,'Wands',1), +(5,9,5019,'Shoot',1), +(5,9,5227,'Underwater Breathing',1), +(5,9,6233,'Closing',1), +(5,9,6246,'Closing',1), +(5,9,6247,'Opening',1), +(5,9,6477,'Opening',1), +(5,9,6478,'Opening',1), +(5,9,6603,'Attack',1), +(5,9,7266,'Duel',1), +(5,9,7267,'Grovel',1), +(5,9,7355,'Stuck',1), +(5,9,7744,'Will of the Forsaken',1), +(5,9,8386,'Attacking',1), +(5,9,9078,'Cloth',1), +(5,9,9125,'Generic',1), +(5,9,17737,'Language Gutterspeak',1), +(5,9,20577,'Cannibalize',1), +(5,9,20579,'Shadow Resistance',1), +(5,9,21651,'Opening',1), +(5,9,21652,'Closing',1), +(5,9,22027,'Remove Insignia',1), +(5,9,22810,'Opening - No Text',1), +(6,1,78,'Heroic Strike',1), +(6,1,81,'Dodge',1), +(6,1,107,'Block',1), +(6,1,196,'One-Handed Axes',1), +(6,1,198,'One-Handed Maces',1), +(6,1,199,'Two-Handed Maces',1), +(6,1,203,'Unarmed',1), +(6,1,204,'Defense',1), +(6,1,522,'SPELLDEFENSE(DND)',1), +(6,1,669,'Language Orcish',1), +(6,1,670,'Language Taurahe',1), +(6,1,2382,'Generic',1), +(6,1,2457,'Battle Stance',1), +(6,1,2479,'Honorless Target',1), +(6,1,3050,'Detect',1), +(6,1,3365,'Opening',1), +(6,1,5301,'Defensive State(DND)',1), +(6,1,6233,'Closing',1), +(6,1,6246,'Closing',1), +(6,1,6247,'Opening',1), +(6,1,6477,'Opening',1), +(6,1,6478,'Opening',1), +(6,1,6603,'Attack',1), +(6,1,7266,'Duel',1), +(6,1,7267,'Grovel',1), +(6,1,7355,'Stuck',1), +(6,1,7376,'Defensive Stance Passive',0), +(6,1,7381,'Berserker Stance Passive',0), +(6,1,8386,'Attacking',1), +(6,1,8737,'Mail',1), +(6,1,9077,'Leather',1), +(6,1,9078,'Cloth',1), +(6,1,9116,'Shield',1), +(6,1,9125,'Generic',1), +(6,1,20549,'War Stomp',1), +(6,1,20550,'Endurance',1), +(6,1,20551,'Nature Resistance',1), +(6,1,20552,'Cultivation',1), +(6,1,21156,'Battle Stance Passive',0), +(6,1,21651,'Opening',1), +(6,1,21652,'Closing',1), +(6,1,22027,'Remove Insignia',1), +(6,1,22810,'Opening - No Text',1), +(6,1,32215,'Victorious State',1), +(6,3,75,'Auto Shot',1), +(6,3,81,'Dodge',1), +(6,3,196,'One-Handed Axes',1), +(6,3,203,'Unarmed',1), +(6,3,204,'Defense',1), +(6,3,266,'Guns',1), +(6,3,522,'SPELLDEFENSE(DND)',1), +(6,3,669,'Language Orcish',1), +(6,3,670,'Language Taurahe',1), +(6,3,2382,'Generic',1), +(6,3,2479,'Honorless Target',1), +(6,3,2973,'Raptor Strike',1), +(6,3,3050,'Detect',1), +(6,3,3365,'Opening',1), +(6,3,6233,'Closing',1), +(6,3,6246,'Closing',1), +(6,3,6247,'Opening',1), +(6,3,6477,'Opening',1), +(6,3,6478,'Opening',1), +(6,3,6603,'Attack',1), +(6,3,7266,'Duel',1), +(6,3,7267,'Grovel',1), +(6,3,7355,'Stuck',1), +(6,3,8386,'Attacking',1), +(6,3,9077,'Leather',1), +(6,3,9078,'Cloth',1), +(6,3,9125,'Generic',1), +(6,3,13358,'Defensive State(DND)',1), +(6,3,20549,'War Stomp',1), +(6,3,20550,'Endurance',1), +(6,3,20551,'Nature Resistance',1), +(6,3,20552,'Cultivation',1), +(6,3,21651,'Opening',1), +(6,3,21652,'Closing',1), +(6,3,22027,'Remove Insignia',1), +(6,3,22810,'Opening - No Text',1), +(6,3,24949,'Defensive State 2(DND)',1), +(6,3,34082,'Advantaged State(DND)',1), +(6,7,81,'Dodge',1), +(6,7,107,'Block',1), +(6,7,198,'One-Handed Maces',1), +(6,7,203,'Unarmed',1), +(6,7,204,'Defense',1), +(6,7,227,'Staves',1), +(6,7,331,'Healing Wave',1), +(6,7,403,'Lightning Bolt',1), +(6,7,522,'SPELLDEFENSE(DND)',1), +(6,7,669,'Language Orcish',1), +(6,7,670,'Language Taurahe',1), +(6,7,2382,'Generic',1), +(6,7,2479,'Honorless Target',1), +(6,7,3050,'Detect',1), +(6,7,3365,'Opening',1), +(6,7,6233,'Closing',1), +(6,7,6246,'Closing',1), +(6,7,6247,'Opening',1), +(6,7,6477,'Opening',1), +(6,7,6478,'Opening',1), +(6,7,6603,'Attack',1), +(6,7,7266,'Duel',1), +(6,7,7267,'Grovel',1), +(6,7,7355,'Stuck',1), +(6,7,8386,'Attacking',1), +(6,7,9077,'Leather',1), +(6,7,9078,'Cloth',1), +(6,7,9116,'Shield',1), +(6,7,9125,'Generic',1), +(6,7,20549,'War Stomp',1), +(6,7,20550,'Endurance',1), +(6,7,20551,'Nature Resistance',1), +(6,7,20552,'Cultivation',1), +(6,7,21651,'Opening',1), +(6,7,21652,'Closing',1), +(6,7,22027,'Remove Insignia',1), +(6,7,22810,'Opening - No Text',1), +(6,7,27763,'Totem',1), +(6,11,81,'Dodge',1), +(6,11,198,'One-Handed Maces',1), +(6,11,203,'Unarmed',1), +(6,11,204,'Defense',1), +(6,11,227,'Staves',1), +(6,11,522,'SPELLDEFENSE(DND)',1), +(6,11,669,'Language Orcish',1), +(6,11,670,'Language Taurahe',1), +(6,11,1178,'Bear Form(Passive)',0), +(6,11,2382,'Generic',1), +(6,11,2479,'Honorless Target',1), +(6,11,3025,'Cat Form(Passive)',0), +(6,11,3050,'Detect',1), +(6,11,3365,'Opening',1), +(6,11,5176,'Wrath',1), +(6,11,5185,'Healing Touch',1), +(6,11,5419,'Travel Form(Passive)',0), +(6,11,5420,'Tree of Life',0), +(6,11,5421,'Aquatic Form(Passive)',0), +(6,11,6233,'Closing',1), +(6,11,6246,'Closing',1), +(6,11,6247,'Opening',1), +(6,11,6477,'Opening',1), +(6,11,6478,'Opening',1), +(6,11,6603,'Attack',1), +(6,11,7266,'Duel',1), +(6,11,7267,'Grovel',1), +(6,11,7355,'Stuck',1), +(6,11,8386,'Attacking',1), +(6,11,9077,'Leather',1), +(6,11,9078,'Cloth',1), +(6,11,9125,'Generic',1), +(6,11,9635,'Dire Bear Form(Passive)',0), +(6,11,20549,'War Stomp',1), +(6,11,20550,'Endurance',1), +(6,11,20551,'Nature Resistance',1), +(6,11,20552,'Cultivation',1), +(6,11,21178,'Bear Form(Passive2)',0), +(6,11,21651,'Opening',1), +(6,11,21652,'Closing',1), +(6,11,22027,'Remove Insignia',1), +(6,11,22810,'Opening - No Text',1), +(6,11,24905,'Moonkin Form(Passive)',0), +(6,11,27764,'Fetish',1), +(6,11,33948,'Flight Form(Passive)',0), +(6,11,34123,'Tree of Life(Passive)',0), +(6,11,40121,'Swift Flight Form(Passive)',0), +(7,1,78,'Heroic Strike',1), +(7,1,81,'Dodge',1), +(7,1,107,'Block',1), +(7,1,198,'One-Handed Maces',1), +(7,1,201,'One-Handed Swords',1), +(7,1,203,'Unarmed',1), +(7,1,204,'Defense',1), +(7,1,522,'SPELLDEFENSE(DND)',1), +(7,1,668,'Language Common',1), +(7,1,1180,'Daggers',1), +(7,1,2382,'Generic',1), +(7,1,2457,'Battle Stance',1), +(7,1,2479,'Honorless Target',1), +(7,1,3050,'Detect',1), +(7,1,3365,'Opening',1), +(7,1,5301,'Defensive State(DND)',1), +(7,1,6233,'Closing',1), +(7,1,6246,'Closing',1), +(7,1,6247,'Opening',1), +(7,1,6477,'Opening',1), +(7,1,6478,'Opening',1), +(7,1,6603,'Attack',1), +(7,1,7266,'Duel',1), +(7,1,7267,'Grovel',1), +(7,1,7340,'Language Gnomish',1), +(7,1,7355,'Stuck',1), +(7,1,7376,'Defensive Stance Passive',0), +(7,1,7381,'Berserker Stance Passive',0), +(7,1,8386,'Attacking',1), +(7,1,8737,'Mail',1), +(7,1,9077,'Leather',1), +(7,1,9078,'Cloth',1), +(7,1,9116,'Shield',1), +(7,1,9125,'Generic',1), +(7,1,20589,'Escape Artist',1), +(7,1,20591,'Expansive Mind',1), +(7,1,20592,'Arcane Resistance',1), +(7,1,20593,'Engineering Specialization',1), +(7,1,21156,'Battle Stance Passive',0), +(7,1,21651,'Opening',1), +(7,1,21652,'Closing',1), +(7,1,22027,'Remove Insignia',1), +(7,1,22810,'Opening - No Text',1), +(7,1,32215,'Victorious State',1), +(7,4,81,'Dodge',1), +(7,4,203,'Unarmed',1), +(7,4,204,'Defense',1), +(7,4,522,'SPELLDEFENSE(DND)',1), +(7,4,668,'Language Common',1), +(7,4,1180,'Daggers',1), +(7,4,1752,'Sinister Strike',1), +(7,4,2098,'Eviscerate',1), +(7,4,2382,'Generic',1), +(7,4,2479,'Honorless Target',1), +(7,4,2567,'Thrown',1), +(7,4,2764,'Throw',1), +(7,4,3050,'Detect',1), +(7,4,3365,'Opening',1), +(7,4,6233,'Closing',1), +(7,4,6246,'Closing',1), +(7,4,6247,'Opening',1), +(7,4,6477,'Opening',1), +(7,4,6478,'Opening',1), +(7,4,6603,'Attack',1), +(7,4,7266,'Duel',1), +(7,4,7267,'Grovel',1), +(7,4,7340,'Language Gnomish',1), +(7,4,7355,'Stuck',1), +(7,4,8386,'Attacking',1), +(7,4,9077,'Leather',1), +(7,4,9078,'Cloth',1), +(7,4,9125,'Generic',1), +(7,4,16092,'Defensive State(DND)',1), +(7,4,20589,'Escape Artist',1), +(7,4,20591,'Expansive Mind',1), +(7,4,20592,'Arcane Resistance',1), +(7,4,20593,'Engineering Specialization',1), +(7,4,21184,'Rogue Passive(DND)',1), +(7,4,21651,'Opening',1), +(7,4,21652,'Closing',1), +(7,4,22027,'Remove Insignia',1), +(7,4,22810,'Opening - No Text',1), +(7,8,81,'Dodge',1), +(7,8,133,'Fireball',1), +(7,8,168,'Frost Armor',1), +(7,8,203,'Unarmed',1), +(7,8,204,'Defense',1), +(7,8,227,'Staves',1), +(7,8,522,'SPELLDEFENSE(DND)',1), +(7,8,668,'Language Common',1), +(7,8,2382,'Generic',1), +(7,8,2479,'Honorless Target',1), +(7,8,3050,'Detect',1), +(7,8,3365,'Opening',1), +(7,8,5009,'Wands',1), +(7,8,5019,'Shoot',1), +(7,8,6233,'Closing',1), +(7,8,6246,'Closing',1), +(7,8,6247,'Opening',1), +(7,8,6477,'Opening',1), +(7,8,6478,'Opening',1), +(7,8,6603,'Attack',1), +(7,8,7266,'Duel',1), +(7,8,7267,'Grovel',1), +(7,8,7340,'Language Gnomish',1), +(7,8,7355,'Stuck',1), +(7,8,8386,'Attacking',1), +(7,8,9078,'Cloth',1), +(7,8,9125,'Generic',1), +(7,8,20589,'Escape Artist',1), +(7,8,20591,'Expansive Mind',1), +(7,8,20592,'Arcane Resistance',1), +(7,8,20593,'Engineering Specialization',1), +(7,8,21651,'Opening',1), +(7,8,21652,'Closing',1), +(7,8,22027,'Remove Insignia',1), +(7,8,22810,'Opening - No Text',1), +(7,9,81,'Dodge',1), +(7,9,203,'Unarmed',1), +(7,9,204,'Defense',1), +(7,9,522,'SPELLDEFENSE(DND)',1), +(7,9,668,'Language Common',1), +(7,9,686,'Shadow Bolt',1), +(7,9,687,'Demon Skin',1), +(7,9,1180,'Daggers',1), +(7,9,2382,'Generic',1), +(7,9,2479,'Honorless Target',1), +(7,9,3050,'Detect',1), +(7,9,3365,'Opening',1), +(7,9,5009,'Wands',1), +(7,9,5019,'Shoot',1), +(7,9,6233,'Closing',1), +(7,9,6246,'Closing',1), +(7,9,6247,'Opening',1), +(7,9,6477,'Opening',1), +(7,9,6478,'Opening',1), +(7,9,6603,'Attack',1), +(7,9,7266,'Duel',1), +(7,9,7267,'Grovel',1), +(7,9,7340,'Language Gnomish',1), +(7,9,7355,'Stuck',1), +(7,9,8386,'Attacking',1), +(7,9,9078,'Cloth',1), +(7,9,9125,'Generic',1), +(7,9,20589,'Escape Artist',1), +(7,9,20591,'Expansive Mind',1), +(7,9,20592,'Arcane Resistance',1), +(7,9,20593,'Engineering Specialization',1), +(7,9,21651,'Opening',1), +(7,9,21652,'Closing',1), +(7,9,22027,'Remove Insignia',1), +(7,9,22810,'Opening - No Text',1), +(8,1,78,'Heroic Strike',1), +(8,1,81,'Dodge',1), +(8,1,107,'Block',1), +(8,1,196,'One-Handed Axes',1), +(8,1,203,'Unarmed',1), +(8,1,204,'Defense',1), +(8,1,522,'SPELLDEFENSE(DND)',1), +(8,1,669,'Language Orcish',1), +(8,1,1180,'Daggers',1), +(8,1,2382,'Generic',1), +(8,1,2457,'Battle Stance',1), +(8,1,2479,'Honorless Target',1), +(8,1,2567,'Thrown',1), +(8,1,2764,'Throw',1), +(8,1,3050,'Detect',1), +(8,1,3365,'Opening',1), +(8,1,5301,'Defensive State(DND)',1), +(8,1,6233,'Closing',1), +(8,1,6246,'Closing',1), +(8,1,6247,'Opening',1), +(8,1,6477,'Opening',1), +(8,1,6478,'Opening',1), +(8,1,6603,'Attack',1), +(8,1,7266,'Duel',1), +(8,1,7267,'Grovel',1), +(8,1,7341,'Language Troll',1), +(8,1,7355,'Stuck',1), +(8,1,7376,'Defensive Stance Passive',0), +(8,1,7381,'Berserker Stance Passive',0), +(8,1,8386,'Attacking',1), +(8,1,8737,'Mail',1), +(8,1,9077,'Leather',1), +(8,1,9078,'Cloth',1), +(8,1,9116,'Shield',1), +(8,1,9125,'Generic',1), +(8,1,20555,'Regeneration',1), +(8,1,20557,'Beast Slaying',1), +(8,1,20558,'Throwing Specialization',1), +(8,1,21156,'Battle Stance Passive',0), +(8,1,21651,'Opening',1), +(8,1,21652,'Closing',1), +(8,1,22027,'Remove Insignia',1), +(8,1,22810,'Opening - No Text',1), +(8,1,26290,'Bow Specialization',1), +(8,1,26296,'Berserking',1), +(8,1,32215,'Victorious State',1), +(8,3,75,'Auto Shot',1), +(8,3,81,'Dodge',1), +(8,3,196,'One-Handed Axes',1), +(8,3,203,'Unarmed',1), +(8,3,204,'Defense',1), +(8,3,264,'Bows',1), +(8,3,522,'SPELLDEFENSE(DND)',1), +(8,3,669,'Language Orcish',1), +(8,3,2382,'Generic',1), +(8,3,2479,'Honorless Target',1), +(8,3,2973,'Raptor Strike',1), +(8,3,3050,'Detect',1), +(8,3,3365,'Opening',1), +(8,3,6233,'Closing',1), +(8,3,6246,'Closing',1), +(8,3,6247,'Opening',1), +(8,3,6477,'Opening',1), +(8,3,6478,'Opening',1), +(8,3,6603,'Attack',1), +(8,3,7266,'Duel',1), +(8,3,7267,'Grovel',1), +(8,3,7341,'Language Troll',1), +(8,3,7355,'Stuck',1), +(8,3,8386,'Attacking',1), +(8,3,9077,'Leather',1), +(8,3,9078,'Cloth',1), +(8,3,9125,'Generic',1), +(8,3,13358,'Defensive State(DND)',1), +(8,3,20554,'Berserking',1), +(8,3,20555,'Regeneration',1), +(8,3,20557,'Beast Slaying',1), +(8,3,20558,'Throwing Specialization',1), +(8,3,21651,'Opening',1), +(8,3,21652,'Closing',1), +(8,3,22027,'Remove Insignia',1), +(8,3,22810,'Opening - No Text',1), +(8,3,24949,'Defensive State 2(DND)',1), +(8,3,26290,'Bow Specialization',1), +(8,3,34082,'Advantaged State(DND)',1), +(8,4,81,'Dodge',1), +(8,4,203,'Unarmed',1), +(8,4,204,'Defense',1), +(8,4,522,'SPELLDEFENSE(DND)',1), +(8,4,669,'Language Orcish',1), +(8,4,1180,'Daggers',1), +(8,4,1752,'Sinister Strike',1), +(8,4,2098,'Eviscerate',1), +(8,4,2382,'Generic',1), +(8,4,2479,'Honorless Target',1), +(8,4,2567,'Thrown',1), +(8,4,2764,'Throw',1), +(8,4,3050,'Detect',1), +(8,4,3365,'Opening',1), +(8,4,6233,'Closing',1), +(8,4,6246,'Closing',1), +(8,4,6247,'Opening',1), +(8,4,6477,'Opening',1), +(8,4,6478,'Opening',1), +(8,4,6603,'Attack',1), +(8,4,7266,'Duel',1), +(8,4,7267,'Grovel',1), +(8,4,7341,'Language Troll',1), +(8,4,7355,'Stuck',1), +(8,4,8386,'Attacking',1), +(8,4,9077,'Leather',1), +(8,4,9078,'Cloth',1), +(8,4,9125,'Generic',1), +(8,4,16092,'Defensive State(DND)',1), +(8,4,20555,'Regeneration',1), +(8,4,20557,'Beast Slaying',1), +(8,4,20558,'Throwing Specialization',1), +(8,4,21184,'Rogue Passive(DND)',1), +(8,4,21651,'Opening',1), +(8,4,21652,'Closing',1), +(8,4,22027,'Remove Insignia',1), +(8,4,22810,'Opening - No Text',1), +(8,4,26290,'Bow Specialization',1), +(8,4,26297,'Berserking',1), +(8,5,81,'Dodge',1), +(8,5,198,'One-Handed Maces',1), +(8,5,203,'Unarmed',1), +(8,5,204,'Defense',1), +(8,5,522,'SPELLDEFENSE(DND)',1), +(8,5,585,'Smite',1), +(8,5,669,'Language Orcish',1), +(8,5,2050,'Lesser Heal',1), +(8,5,2382,'Generic',1), +(8,5,2479,'Honorless Target',1), +(8,5,3050,'Detect',1), +(8,5,3365,'Opening',1), +(8,5,5009,'Wands',1), +(8,5,5019,'Shoot',1), +(8,5,6233,'Closing',1), +(8,5,6246,'Closing',1), +(8,5,6247,'Opening',1), +(8,5,6477,'Opening',1), +(8,5,6478,'Opening',1), +(8,5,6603,'Attack',1), +(8,5,7266,'Duel',1), +(8,5,7267,'Grovel',1), +(8,5,7341,'Language Troll',1), +(8,5,7355,'Stuck',1), +(8,5,8386,'Attacking',1), +(8,5,9078,'Cloth',1), +(8,5,9125,'Generic',1), +(8,5,20554,'Berserking',1), +(8,5,20555,'Regeneration',1), +(8,5,20557,'Beast Slaying',1), +(8,5,20558,'Throwing Specialization',1), +(8,5,21651,'Opening',1), +(8,5,21652,'Closing',1), +(8,5,22027,'Remove Insignia',1), +(8,5,22810,'Opening - No Text',1), +(8,5,26290,'Bow Specialization',1), +(8,7,81,'Dodge',1), +(8,7,107,'Block',1), +(8,7,198,'One-Handed Maces',1), +(8,7,203,'Unarmed',1), +(8,7,204,'Defense',1), +(8,7,227,'Staves',1), +(8,7,331,'Healing Wave',1), +(8,7,403,'Lightning Bolt',1), +(8,7,522,'SPELLDEFENSE(DND)',1), +(8,7,669,'Language Orcish',1), +(8,7,2382,'Generic',1), +(8,7,2479,'Honorless Target',1), +(8,7,3050,'Detect',1), +(8,7,3365,'Opening',1), +(8,7,6233,'Closing',1), +(8,7,6246,'Closing',1), +(8,7,6247,'Opening',1), +(8,7,6477,'Opening',1), +(8,7,6478,'Opening',1), +(8,7,6603,'Attack',1), +(8,7,7266,'Duel',1), +(8,7,7267,'Grovel',1), +(8,7,7341,'Language Troll',1), +(8,7,7355,'Stuck',1), +(8,7,8386,'Attacking',1), +(8,7,9077,'Leather',1), +(8,7,9078,'Cloth',1), +(8,7,9116,'Shield',1), +(8,7,9125,'Generic',1), +(8,7,20554,'Berserking',1), +(8,7,20555,'Regeneration',1), +(8,7,20557,'Beast Slaying',1), +(8,7,20558,'Throwing Specialization',1), +(8,7,21651,'Opening',1), +(8,7,21652,'Closing',1), +(8,7,22027,'Remove Insignia',1), +(8,7,22810,'Opening - No Text',1), +(8,7,26290,'Bow Specialization',1), +(8,7,27763,'Totem',1), +(8,8,81,'Dodge',1), +(8,8,133,'Fireball',1), +(8,8,168,'Frost Armor',1), +(8,8,203,'Unarmed',1), +(8,8,204,'Defense',1), +(8,8,227,'Staves',1), +(8,8,522,'SPELLDEFENSE(DND)',1), +(8,8,669,'Language Orcish',1), +(8,8,2382,'Generic',1), +(8,8,2479,'Honorless Target',1), +(8,8,3050,'Detect',1), +(8,8,3365,'Opening',1), +(8,8,5009,'Wands',1), +(8,8,5019,'Shoot',1), +(8,8,6233,'Closing',1), +(8,8,6246,'Closing',1), +(8,8,6247,'Opening',1), +(8,8,6477,'Opening',1), +(8,8,6478,'Opening',1), +(8,8,6603,'Attack',1), +(8,8,7266,'Duel',1), +(8,8,7267,'Grovel',1), +(8,8,7341,'Language Troll',1), +(8,8,7355,'Stuck',1), +(8,8,8386,'Attacking',1), +(8,8,9078,'Cloth',1), +(8,8,9125,'Generic',1), +(8,8,20554,'Berserking',1), +(8,8,20555,'Regeneration',1), +(8,8,20557,'Beast Slaying',1), +(8,8,20558,'Throwing Specialization',1), +(8,8,21651,'Opening',1), +(8,8,21652,'Closing',1), +(8,8,22027,'Remove Insignia',1), +(8,8,22810,'Opening - No Text',1), +(8,8,26290,'Bow Specialization',1), +(10,2,81,'Dodge',1), +(10,2,107,'Block',1), +(10,2,201,'One-Handed Swords',1), +(10,2,202,'Two-Handed Swords',1), +(10,2,203,'Unarmed',1), +(10,2,204,'Defense',1), +(10,2,522,'SPELLDEFENSE(DND)',1), +(10,2,635,'Holy Light',1), +(10,2,669,'Language Orcish',1), +(10,2,813,'Language Thalassian',1), +(10,2,822,'Magic Resistance',1), +(10,2,2382,'Generic',1), +(10,2,2479,'Honorless Target',1), +(10,2,3050,'Detect',1), +(10,2,3365,'Opening',1), +(10,2,6233,'Closing',1), +(10,2,6246,'Closing',1), +(10,2,6247,'Opening',1), +(10,2,6477,'Opening',1), +(10,2,6478,'Opening',1), +(10,2,6603,'Attack',1), +(10,2,7266,'Duel',1), +(10,2,7267,'Grovel',1), +(10,2,7355,'Stuck',1), +(10,2,8386,'Attacking',1), +(10,2,8737,'Mail',1), +(10,2,9077,'Leather',1), +(10,2,9078,'Cloth',1), +(10,2,9116,'Shield',1), +(10,2,9125,'Generic',1), +(10,2,20154,'Seal of Righteousness',1), +(10,2,21651,'Opening',1), +(10,2,21652,'Closing',1), +(10,2,22027,'Remove Insignia',1), +(10,2,22810,'Opening - No Text',1), +(10,2,27762,'Libram',1), +(10,2,28730,'Arcane Torrent',1), +(10,2,28734,'Mana Tap',1), +(10,2,28877,'Arcane Affinity',1), +(10,3,75,'Auto Shot',1), +(10,3,81,'Dodge',1), +(10,3,203,'Unarmed',1), +(10,3,204,'Defense',1), +(10,3,264,'Bows',1), +(10,3,522,'SPELLDEFENSE(DND)',1), +(10,3,669,'Language Orcish',1), +(10,3,813,'Language Thalassian',1), +(10,3,822,'Magic Resistance',1), +(10,3,1180,'Daggers',1), +(10,3,2382,'Generic',1), +(10,3,2479,'Honorless Target',1), +(10,3,2973,'Raptor Strike',1), +(10,3,3050,'Detect',1), +(10,3,3365,'Opening',1), +(10,3,6233,'Closing',1), +(10,3,6246,'Closing',1), +(10,3,6247,'Opening',1), +(10,3,6477,'Opening',1), +(10,3,6478,'Opening',1), +(10,3,6603,'Attack',1), +(10,3,7266,'Duel',1), +(10,3,7267,'Grovel',1), +(10,3,7355,'Stuck',1), +(10,3,8386,'Attacking',1), +(10,3,9077,'Leather',1), +(10,3,9078,'Cloth',1), +(10,3,9125,'Generic',1), +(10,3,13358,'Defensive State(DND)',1), +(10,3,21651,'Opening',1), +(10,3,21652,'Closing',1), +(10,3,22027,'Remove Insignia',1), +(10,3,22810,'Opening - No Text',1), +(10,3,24949,'Defensive State 2(DND)',1), +(10,3,28730,'Arcane Torrent',1), +(10,3,28734,'Mana Tap',1), +(10,3,28877,'Arcane Affinity',1), +(10,3,34082,'Advantaged State(DND)',1), +(10,4,81,'Dodge',1), +(10,4,203,'Unarmed',1), +(10,4,204,'Defense',1), +(10,4,522,'SPELLDEFENSE(DND)',1), +(10,4,669,'Language Orcish',1), +(10,4,813,'Language Thalassian',1), +(10,4,822,'Magic Resistance',1), +(10,4,1180,'Daggers',1), +(10,4,1752,'Sinister Strike',1), +(10,4,2098,'Eviscerate',1), +(10,4,2382,'Generic',1), +(10,4,2479,'Honorless Target',1), +(10,4,2567,'Thrown',1), +(10,4,2764,'Throw',1), +(10,4,3050,'Detect',1), +(10,4,3365,'Opening',1), +(10,4,6233,'Closing',1), +(10,4,6246,'Closing',1), +(10,4,6247,'Opening',1), +(10,4,6477,'Opening',1), +(10,4,6478,'Opening',1), +(10,4,6603,'Attack',1), +(10,4,7266,'Duel',1), +(10,4,7267,'Grovel',1), +(10,4,7355,'Stuck',1), +(10,4,8386,'Attacking',1), +(10,4,9077,'Leather',1), +(10,4,9078,'Cloth',1), +(10,4,9125,'Generic',1), +(10,4,16092,'Defensive State(DND)',1), +(10,4,21184,'Rogue Passive(DND)',1), +(10,4,21651,'Opening',1), +(10,4,21652,'Closing',1), +(10,4,22027,'Remove Insignia',1), +(10,4,22810,'Opening - No Text',1), +(10,4,25046,'Arcane Torrent',1), +(10,4,28734,'Mana Tap',1), +(10,4,28877,'Arcane Affinity',1), +(10,5,81,'Dodge',1), +(10,5,198,'One-Handed Maces',1), +(10,5,203,'Unarmed',1), +(10,5,204,'Defense',1), +(10,5,522,'SPELLDEFENSE(DND)',1), +(10,5,585,'Smite',1), +(10,5,669,'Language Orcish',1), +(10,5,813,'Language Thalassian',1), +(10,5,822,'Magic Resistance',1), +(10,5,2050,'Lesser Heal',1), +(10,5,2382,'Generic',1), +(10,5,2479,'Honorless Target',1), +(10,5,3050,'Detect',1), +(10,5,3365,'Opening',1), +(10,5,5009,'Wands',1), +(10,5,5019,'Shoot',1), +(10,5,6233,'Closing',1), +(10,5,6246,'Closing',1), +(10,5,6247,'Opening',1), +(10,5,6477,'Opening',1), +(10,5,6478,'Opening',1), +(10,5,6603,'Attack',1), +(10,5,7266,'Duel',1), +(10,5,7267,'Grovel',1), +(10,5,7355,'Stuck',1), +(10,5,8386,'Attacking',1), +(10,5,9078,'Cloth',1), +(10,5,9125,'Generic',1), +(10,5,21651,'Opening',1), +(10,5,21652,'Closing',1), +(10,5,22027,'Remove Insignia',1), +(10,5,22810,'Opening - No Text',1), +(10,5,28730,'Arcane Torrent',1), +(10,5,28734,'Mana Tap',1), +(10,5,28877,'Arcane Affinity',1), +(10,8,81,'Dodge',1), +(10,8,133,'Fireball',1), +(10,8,168,'Frost Armor',1), +(10,8,203,'Unarmed',1), +(10,8,204,'Defense',1), +(10,8,227,'Staves',1), +(10,8,522,'SPELLDEFENSE(DND)',1), +(10,8,669,'Language Orcish',1), +(10,8,813,'Language Thalassian',1), +(10,8,822,'Magic Resistance',1), +(10,8,2382,'Generic',1), +(10,8,2479,'Honorless Target',1), +(10,8,3050,'Detect',1), +(10,8,3365,'Opening',1), +(10,8,5009,'Wands',1), +(10,8,5019,'Shoot',1), +(10,8,6233,'Closing',1), +(10,8,6246,'Closing',1), +(10,8,6247,'Opening',1), +(10,8,6477,'Opening',1), +(10,8,6478,'Opening',1), +(10,8,6603,'Attack',1), +(10,8,7266,'Duel',1), +(10,8,7267,'Grovel',1), +(10,8,7355,'Stuck',1), +(10,8,8386,'Attacking',1), +(10,8,9078,'Cloth',1), +(10,8,9125,'Generic',1), +(10,8,21651,'Opening',1), +(10,8,21652,'Closing',1), +(10,8,22027,'Remove Insignia',1), +(10,8,22810,'Opening - No Text',1), +(10,8,28730,'Arcane Torrent',1), +(10,8,28734,'Mana Tap',1), +(10,8,28877,'Arcane Affinity',1), +(10,9,81,'Dodge',1), +(10,9,203,'Unarmed',1), +(10,9,204,'Defense',1), +(10,9,522,'SPELLDEFENSE(DND)',1), +(10,9,669,'Language Orcish',1), +(10,9,686,'Shadow Bolt',1), +(10,9,687,'Demon Skin',1), +(10,9,813,'Language Thalassian',1), +(10,9,822,'Magic Resistance',1), +(10,9,1180,'Daggers',1), +(10,9,2382,'Generic',1), +(10,9,2479,'Honorless Target',1), +(10,9,3050,'Detect',1), +(10,9,3365,'Opening',1), +(10,9,5009,'Wands',1), +(10,9,5019,'Shoot',1), +(10,9,6233,'Closing',1), +(10,9,6246,'Closing',1), +(10,9,6247,'Opening',1), +(10,9,6477,'Opening',1), +(10,9,6478,'Opening',1), +(10,9,6603,'Attack',1), +(10,9,7266,'Duel',1), +(10,9,7267,'Grovel',1), +(10,9,7355,'Stuck',1), +(10,9,8386,'Attacking',1), +(10,9,9078,'Cloth',1), +(10,9,9125,'Generic',1), +(10,9,21651,'Opening',1), +(10,9,21652,'Closing',1), +(10,9,22027,'Remove Insignia',1), +(10,9,22810,'Opening - No Text',1), +(10,9,28730,'Arcane Torrent',1), +(10,9,28734,'Mana Tap',1), +(10,9,28877,'Arcane Affinity',1), +(11,1,78,'Heroic Strike',1), +(11,1,81,'Dodge',1), +(11,1,107,'Block',1), +(11,1,198,'One-Handed Maces',1), +(11,1,201,'One-Handed Swords',1), +(11,1,202,'Two-Handed Swords',1), +(11,1,203,'Unarmed',1), +(11,1,204,'Defense',1), +(11,1,522,'SPELLDEFENSE(DND)',1), +(11,1,668,'Language Common',1), +(11,1,2382,'Generic',1), +(11,1,2457,'Battle Stance',1), +(11,1,2479,'Honorless Target',1), +(11,1,3050,'Detect',1), +(11,1,3365,'Opening',1), +(11,1,5301,'Defensive State(DND)',1), +(11,1,6233,'Closing',1), +(11,1,6246,'Closing',1), +(11,1,6247,'Opening',1), +(11,1,6477,'Opening',1), +(11,1,6478,'Opening',1), +(11,1,6562,'Heroic Presence',1), +(11,1,6603,'Attack',1), +(11,1,7266,'Duel',1), +(11,1,7267,'Grovel',1), +(11,1,7355,'Stuck',1), +(11,1,7376,'Defensive Stance Passive',0), +(11,1,7381,'Berserker Stance Passive',0), +(11,1,8386,'Attacking',1), +(11,1,8737,'Mail',1), +(11,1,9077,'Leather',1), +(11,1,9078,'Cloth',1), +(11,1,9116,'Shield',1), +(11,1,9125,'Generic',1), +(11,1,20579,'Shadow Resistance',1), +(11,1,21156,'Battle Stance Passive',0), +(11,1,21651,'Opening',1), +(11,1,21652,'Closing',1), +(11,1,22027,'Remove Insignia',1), +(11,1,22810,'Opening - No Text',1), +(11,1,28875,'Gemcutting',1), +(11,1,28880,'Gift of the Naaru',1), +(11,1,29932,'Language Draenei',1), +(11,1,32215,'Victorious State',1), +(11,2,81,'Dodge',1), +(11,2,107,'Block',1), +(11,2,198,'One-Handed Maces',1), +(11,2,199,'Two-Handed Maces',1), +(11,2,203,'Unarmed',1), +(11,2,204,'Defense',1), +(11,2,522,'SPELLDEFENSE(DND)',1), +(11,2,635,'Holy Light',1), +(11,2,668,'Language Common',1), +(11,2,2382,'Generic',1), +(11,2,2479,'Honorless Target',1), +(11,2,3050,'Detect',1), +(11,2,3365,'Opening',1), +(11,2,6233,'Closing',1), +(11,2,6246,'Closing',1), +(11,2,6247,'Opening',1), +(11,2,6477,'Opening',1), +(11,2,6478,'Opening',1), +(11,2,6562,'Heroic Presence',1), +(11,2,6603,'Attack',1), +(11,2,7266,'Duel',1), +(11,2,7267,'Grovel',1), +(11,2,7355,'Stuck',1), +(11,2,8386,'Attacking',1), +(11,2,8737,'Mail',1), +(11,2,9077,'Leather',1), +(11,2,9078,'Cloth',1), +(11,2,9116,'Shield',1), +(11,2,9125,'Generic',1), +(11,2,20154,'Seal of Righteousness',1), +(11,2,20579,'Shadow Resistance',1), +(11,2,21651,'Opening',1), +(11,2,21652,'Closing',1), +(11,2,22027,'Remove Insignia',1), +(11,2,22810,'Opening - No Text',1), +(11,2,27762,'Libram',1), +(11,2,28875,'Gemcutting',1), +(11,2,28880,'Gift of the Naaru',1), +(11,2,29932,'Language Draenei',1), +(11,3,75,'Auto Shot',1), +(11,3,81,'Dodge',1), +(11,3,201,'One-Handed Swords',1), +(11,3,203,'Unarmed',1), +(11,3,204,'Defense',1), +(11,3,522,'SPELLDEFENSE(DND)',1), +(11,3,668,'Language Common',1), +(11,3,2382,'Generic',1), +(11,3,2479,'Honorless Target',1), +(11,3,2973,'Raptor Strike',1), +(11,3,3050,'Detect',1), +(11,3,3365,'Opening',1), +(11,3,5011,'Crossbows',1), +(11,3,6233,'Closing',1), +(11,3,6246,'Closing',1), +(11,3,6247,'Opening',1), +(11,3,6477,'Opening',1), +(11,3,6478,'Opening',1), +(11,3,6562,'Heroic Presence',1), +(11,3,6603,'Attack',1), +(11,3,7266,'Duel',1), +(11,3,7267,'Grovel',1), +(11,3,7355,'Stuck',1), +(11,3,8386,'Attacking',1), +(11,3,9077,'Leather',1), +(11,3,9078,'Cloth',1), +(11,3,9125,'Generic',1), +(11,3,13358,'Defensive State(DND)',1), +(11,3,20579,'Shadow Resistance',1), +(11,3,21651,'Opening',1), +(11,3,21652,'Closing',1), +(11,3,22027,'Remove Insignia',1), +(11,3,22810,'Opening - No Text',1), +(11,3,24949,'Defensive State 2(DND)',1), +(11,3,28875,'Gemcutting',1), +(11,3,28880,'Gift of the Naaru',1), +(11,3,29932,'Language Draenei',1), +(11,3,34082,'Advantaged State(DND)',1), +(11,5,81,'Dodge',1), +(11,5,198,'One-Handed Maces',1), +(11,5,203,'Unarmed',1), +(11,5,204,'Defense',1), +(11,5,522,'SPELLDEFENSE(DND)',1), +(11,5,585,'Smite',1), +(11,5,668,'Language Common',1), +(11,5,2050,'Lesser Heal',1), +(11,5,2382,'Generic',1), +(11,5,2479,'Honorless Target',1), +(11,5,3050,'Detect',1), +(11,5,3365,'Opening',1), +(11,5,5009,'Wands',1), +(11,5,5019,'Shoot',1), +(11,5,6233,'Closing',1), +(11,5,6246,'Closing',1), +(11,5,6247,'Opening',1), +(11,5,6477,'Opening',1), +(11,5,6478,'Opening',1), +(11,5,6603,'Attack',1), +(11,5,7266,'Duel',1), +(11,5,7267,'Grovel',1), +(11,5,7355,'Stuck',1), +(11,5,8386,'Attacking',1), +(11,5,9078,'Cloth',1), +(11,5,9125,'Generic',1), +(11,5,20579,'Shadow Resistance',1), +(11,5,21651,'Opening',1), +(11,5,21652,'Closing',1), +(11,5,22027,'Remove Insignia',1), +(11,5,22810,'Opening - No Text',1), +(11,5,28875,'Gemcutting',1), +(11,5,28878,'Inspiring Presence',1), +(11,5,28880,'Gift of the Naaru',1), +(11,5,29932,'Language Draenei',1), +(11,7,81,'Dodge',1), +(11,7,107,'Block',1), +(11,7,198,'One-Handed Maces',1), +(11,7,203,'Unarmed',1), +(11,7,204,'Defense',1), +(11,7,227,'Staves',1), +(11,7,331,'Healing Wave',1), +(11,7,403,'Lightning Bolt',1), +(11,7,522,'SPELLDEFENSE(DND)',1), +(11,7,668,'Language Common',1), +(11,7,2382,'Generic',1), +(11,7,2479,'Honorless Target',1), +(11,7,3050,'Detect',1), +(11,7,3365,'Opening',1), +(11,7,6233,'Closing',1), +(11,7,6246,'Closing',1), +(11,7,6247,'Opening',1), +(11,7,6477,'Opening',1), +(11,7,6478,'Opening',1), +(11,7,6603,'Attack',1), +(11,7,7266,'Duel',1), +(11,7,7267,'Grovel',1), +(11,7,7355,'Stuck',1), +(11,7,8386,'Attacking',1), +(11,7,9077,'Leather',1), +(11,7,9078,'Cloth',1), +(11,7,9116,'Shield',1), +(11,7,9125,'Generic',1), +(11,7,20579,'Shadow Resistance',1), +(11,7,21651,'Opening',1), +(11,7,21652,'Closing',1), +(11,7,22027,'Remove Insignia',1), +(11,7,22810,'Opening - No Text',1), +(11,7,27763,'Totem',1), +(11,7,28875,'Gemcutting',1), +(11,7,28878,'Inspiring Presence',1), +(11,7,28880,'Gift of the Naaru',1), +(11,7,29932,'Language Draenei',1), +(11,8,81,'Dodge',1), +(11,8,133,'Fireball',1), +(11,8,168,'Frost Armor',1), +(11,8,203,'Unarmed',1), +(11,8,204,'Defense',1), +(11,8,227,'Staves',1), +(11,8,522,'SPELLDEFENSE(DND)',1), +(11,8,668,'Language Common',1), +(11,8,2382,'Generic',1), +(11,8,2479,'Honorless Target',1), +(11,8,3050,'Detect',1), +(11,8,3365,'Opening',1), +(11,8,5009,'Wands',1), +(11,8,5019,'Shoot',1), +(11,8,6233,'Closing',1), +(11,8,6246,'Closing',1), +(11,8,6247,'Opening',1), +(11,8,6477,'Opening',1), +(11,8,6478,'Opening',1), +(11,8,6603,'Attack',1), +(11,8,7266,'Duel',1), +(11,8,7267,'Grovel',1), +(11,8,7355,'Stuck',1), +(11,8,8386,'Attacking',1), +(11,8,9078,'Cloth',1), +(11,8,9125,'Generic',1), +(11,8,20579,'Shadow Resistance',1), +(11,8,21651,'Opening',1), +(11,8,21652,'Closing',1), +(11,8,22027,'Remove Insignia',1), +(11,8,22810,'Opening - No Text',1), +(11,8,28875,'Gemcutting',1), +(11,8,28878,'Inspiring Presence',1), +(11,8,28880,'Gift of the Naaru',1), +(11,8,29932,'Language Draenei',1); \ No newline at end of file diff --git a/sql/updates/0.8/4081_command.sql b/sql/updates/0.8/4081_command.sql new file mode 100644 index 00000000000..b266bf32605 --- /dev/null +++ b/sql/updates/0.8/4081_command.sql @@ -0,0 +1,8 @@ +DELETE FROM `command` WHERE `name`='learn'; +INSERT INTO `command` VALUES +('learn',3,'Syntax: .learn #parameter\r\n\r\nSelected character learn a spell of id #parameter.'), +('learn all',3,'Syntax: .learn all\r\n\r\nLearn all big set different spell maybe useful for Administaror.'), +('learn all_crafts',2,'Syntax: .learn crafts\r\n\r\nLearn all professions and recipes.'), +('learn all_gm',2,'Syntax: .learn all_gm\r\n\r\nLearn all default spells for Game Masters.'), +('learn all_lang',1,'Syntax: .learn all_lang\r\n\r\nLearn all languages'), +('learn all_myclass',3,'Syntax: .learn all_myclass\r\n\r\nLearn all spells available for his class.'); diff --git a/sql/updates/0.8/4096_pet.sql b/sql/updates/0.8/4096_pet.sql new file mode 100644 index 00000000000..6bf6536cef5 --- /dev/null +++ b/sql/updates/0.8/4096_pet.sql @@ -0,0 +1,290 @@ +DROP TABLE IF EXISTS `character_pet`; +CREATE TABLE `character_pet` ( + `id` int(11) unsigned NOT NULL default '0', + `entry` int(11) unsigned NOT NULL default '0', + `owner` int(11) unsigned NOT NULL default '0', + `modelid` int(11) unsigned default '0', + `level` int(11) unsigned NOT NULL default '1', + `exp` int(11) unsigned NOT NULL default '0', + `nextlvlexp` int(11) unsigned NOT NULL default '100', + `Reactstate` tinyint(1) unsigned NOT NULL default '0', + `Commandstate` tinyint(1) unsigned NOT NULL default '1', + `loyaltypoints` int(11) NOT NULL default '0', + `loyalty` int(11) unsigned NOT NULL default '0', + `trainpoint` int(11) NOT NULL default '0', + `name` varchar(100) default 'Pet', + `renamed` tinyint(1) unsigned NOT NULL default '0', + `slot` int(11) unsigned NOT NULL default '0', + `curhealth` int(11) unsigned NOT NULL default '1', + `curmana` int(11) unsigned NOT NULL default '0', + `curhappiness` int(11) unsigned NOT NULL default '0', + `savetime` bigint(20) unsigned NOT NULL default '0', + `resettalents_cost` int(11) unsigned NOT NULL default '0', + `resettalents_time` bigint(20) unsigned NOT NULL default '0', + `ABData` longtext, + `TeachSpelldata` longtext, + PRIMARY KEY (`id`), + KEY `owner` (`owner`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Pet System'; + +DROP TABLE IF EXISTS `pet_spell`; +CREATE TABLE `pet_spell` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `spell` int(11) unsigned NOT NULL default '0' COMMENT 'Spell Identifier', + `slot` int(11) unsigned NOT NULL default '0', + `active` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`,`spell`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Pet System'; + +DROP TABLE IF EXISTS `pet_spell_cooldown`; +CREATE TABLE `pet_spell_cooldown` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier, Low part', + `spell` int(11) unsigned NOT NULL default '0' COMMENT 'Spell Identifier', + `time` bigint(20) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`,`spell`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `pet_aura`; +CREATE TABLE `pet_aura` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `spell` int(11) unsigned NOT NULL default '0', + `effect_index` int(11) unsigned NOT NULL default '0', + `remaintime` int(11) NOT NULL default '0', + PRIMARY KEY (`guid`,`spell`,`effect_index`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Pet System'; + +-- ---------------------------- +-- Table structure for petcreateinfo_spell +-- ---------------------------- +DROP TABLE IF EXISTS `petcreateinfo_spell`; +CREATE TABLE `petcreateinfo_spell` ( + `entry` int(11) unsigned NOT NULL DEFAULT '0', + `Spell1` int(11) unsigned NOT NULL DEFAULT '0', + `Spell2` int(11) unsigned NOT NULL DEFAULT '0', + `Spell3` int(11) unsigned NOT NULL DEFAULT '0', + `Spell4` int(11) unsigned NOT NULL DEFAULT '0', + `FamilyPassive` int(11) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Pet Create Spells'; + +ALTER TABLE `pet_levelstats` ADD `armor` int(10) unsigned NOT NULL default '0' AFTER `mana`; + +INSERT INTO `spell_chain` VALUES ('17253', '0', '17253', '1'); +INSERT INTO `spell_chain` VALUES ('17255', '17253', '17253', '2'); +INSERT INTO `spell_chain` VALUES ('17256', '17255', '17253', '3'); +INSERT INTO `spell_chain` VALUES ('17257', '17256', '17253', '4'); +INSERT INTO `spell_chain` VALUES ('17258', '17257', '17253', '5'); +INSERT INTO `spell_chain` VALUES ('17259', '17258', '17253', '6'); +INSERT INTO `spell_chain` VALUES ('17260', '17259', '17253', '7'); +INSERT INTO `spell_chain` VALUES ('17261', '17260', '17253', '8'); +INSERT INTO `spell_chain` VALUES ('27050', '17261', '17253', '9'); +INSERT INTO `spell_chain` VALUES ('16827', '0', '16827', '1'); +INSERT INTO `spell_chain` VALUES ('16828', '16827', '16827', '2'); +INSERT INTO `spell_chain` VALUES ('16829', '16828', '16827', '3'); +INSERT INTO `spell_chain` VALUES ('16830', '16829', '16827', '4'); +INSERT INTO `spell_chain` VALUES ('16831', '16830', '16827', '5'); +INSERT INTO `spell_chain` VALUES ('16832', '16831', '16827', '6'); +INSERT INTO `spell_chain` VALUES ('3010', '16832', '16827', '7'); +INSERT INTO `spell_chain` VALUES ('3009', '3010', '16827', '8'); +INSERT INTO `spell_chain` VALUES ('27049', '3009', '16827', '9'); +INSERT INTO `spell_chain` VALUES ('1742', '0', '1742', '1'); +INSERT INTO `spell_chain` VALUES ('1753', '1742', '1742', '2'); +INSERT INTO `spell_chain` VALUES ('1754', '1753', '1742', '3'); +INSERT INTO `spell_chain` VALUES ('1755', '1754', '1742', '4'); +INSERT INTO `spell_chain` VALUES ('1756', '1755', '1742', '5'); +INSERT INTO `spell_chain` VALUES ('16697', '1756', '1742', '6'); +INSERT INTO `spell_chain` VALUES ('27048', '16697', '1742', '7'); +INSERT INTO `spell_chain` VALUES ('23099', '0', '23099', '1'); +INSERT INTO `spell_chain` VALUES ('23109', '23099', '23099', '2'); +INSERT INTO `spell_chain` VALUES ('23110', '23109', '23099', '3'); +INSERT INTO `spell_chain` VALUES ('23145', '0', '23145', '1'); +INSERT INTO `spell_chain` VALUES ('23147', '23145', '23145', '2'); +INSERT INTO `spell_chain` VALUES ('23148', '23147', '23145', '3'); +INSERT INTO `spell_chain` VALUES ('2649', '0', '2649', '1'); +INSERT INTO `spell_chain` VALUES ('14916', '2649', '2649', '2'); +INSERT INTO `spell_chain` VALUES ('14917', '14916', '2649', '3'); +INSERT INTO `spell_chain` VALUES ('14918', '14917', '2649', '4'); +INSERT INTO `spell_chain` VALUES ('14919', '14918', '2649', '5'); +INSERT INTO `spell_chain` VALUES ('14920', '14919', '2649', '6'); +INSERT INTO `spell_chain` VALUES ('14921', '14920', '2649', '7'); +INSERT INTO `spell_chain` VALUES ('27047', '14921', '2649', '8'); +INSERT INTO `spell_chain` VALUES ('7371', '0', '7371', '1'); +INSERT INTO `spell_chain` VALUES ('26177', '7371', '7371', '2'); +INSERT INTO `spell_chain` VALUES ('26178', '26177', '7371', '3'); +INSERT INTO `spell_chain` VALUES ('26179', '26178', '7371', '4'); +INSERT INTO `spell_chain` VALUES ('26201', '26179', '7371', '5'); +INSERT INTO `spell_chain` VALUES ('27685', '26201', '7371', '6'); +INSERT INTO `spell_chain` VALUES ('24604', '0', '24604', '1'); +INSERT INTO `spell_chain` VALUES ('24605', '24604', '24604', '2'); +INSERT INTO `spell_chain` VALUES ('24603', '24605', '24604', '3'); +INSERT INTO `spell_chain` VALUES ('24597', '24603', '24604', '4'); +INSERT INTO `spell_chain` VALUES ('24844', '0', '24844', '1'); +INSERT INTO `spell_chain` VALUES ('25008', '24844', '24844', '2'); +INSERT INTO `spell_chain` VALUES ('25009', '25008', '24844', '3'); +INSERT INTO `spell_chain` VALUES ('25010', '25009', '24844', '4'); +INSERT INTO `spell_chain` VALUES ('25011', '25010', '24844', '5'); +INSERT INTO `spell_chain` VALUES ('25012', '25011', '24844', '6'); +INSERT INTO `spell_chain` VALUES ('24450', '0', '24450', '1'); +INSERT INTO `spell_chain` VALUES ('24452', '24450', '24450', '2'); +INSERT INTO `spell_chain` VALUES ('24453', '24452', '24450', '3'); +INSERT INTO `spell_chain` VALUES ('24640', '0', '24640', '1'); +INSERT INTO `spell_chain` VALUES ('24583', '24640', '24640', '2'); +INSERT INTO `spell_chain` VALUES ('24586', '24583', '24640', '3'); +INSERT INTO `spell_chain` VALUES ('24587', '24586', '24640', '4'); +INSERT INTO `spell_chain` VALUES ('27060', '24587', '24640', '5'); +INSERT INTO `spell_chain` VALUES ('24423', '0', '24423', '1'); +INSERT INTO `spell_chain` VALUES ('24577', '24423', '24423', '2'); +INSERT INTO `spell_chain` VALUES ('24578', '24577', '24423', '3'); +INSERT INTO `spell_chain` VALUES ('24579', '24578', '24423', '4'); +INSERT INTO `spell_chain` VALUES ('27051', '24579', '24423', '5'); +INSERT INTO `spell_chain` VALUES ('26064', '0', '26064', '1'); +INSERT INTO `spell_chain` VALUES ('26090', '0', '26090', '1'); +INSERT INTO `spell_chain` VALUES ('26187', '26090', '26090', '2'); +INSERT INTO `spell_chain` VALUES ('26188', '26187', '26090', '3'); +INSERT INTO `spell_chain` VALUES ('27063', '26188', '26090', '4'); +INSERT INTO `spell_chain` VALUES ('34889', '0', '34889', '1'); +INSERT INTO `spell_chain` VALUES ('35323', '34889', '34889', '2'); +INSERT INTO `spell_chain` VALUES ('35290', '0', '35290', '1'); +INSERT INTO `spell_chain` VALUES ('35291', '35290', '35290', '2'); +INSERT INTO `spell_chain` VALUES ('35292', '35291', '35290', '3'); +INSERT INTO `spell_chain` VALUES ('35293', '35292', '35290', '4'); +INSERT INTO `spell_chain` VALUES ('35294', '35293', '35290', '5'); +INSERT INTO `spell_chain` VALUES ('35295', '35294', '35290', '6'); +INSERT INTO `spell_chain` VALUES ('35296', '35295', '35290', '7'); +INSERT INTO `spell_chain` VALUES ('35297', '35296', '35290', '8'); +INSERT INTO `spell_chain` VALUES ('35298', '35297', '35290', '9'); +INSERT INTO `spell_chain` VALUES ('35387', '0', '35387', '1'); +INSERT INTO `spell_chain` VALUES ('35389', '35387', '35387', '2'); +INSERT INTO `spell_chain` VALUES ('35392', '35389', '35387', '3'); +INSERT INTO `spell_chain` VALUES ('35346', '0', '35346', '1'); +INSERT INTO `spell_chain` VALUES ('25076', '0', '25076', '1'); +INSERT INTO `spell_chain` VALUES ('35694', '0', '35694', '1'); +INSERT INTO `spell_chain` VALUES ('35698', '35694', '35694', '2'); +INSERT INTO `spell_chain` VALUES ('4187', '0', '4187', '1'); +INSERT INTO `spell_chain` VALUES ('4188', '4187', '4187', '2'); +INSERT INTO `spell_chain` VALUES ('4189', '4188', '4187', '3'); +INSERT INTO `spell_chain` VALUES ('4190', '4189', '4187', '4'); +INSERT INTO `spell_chain` VALUES ('4191', '4190', '4187', '5'); +INSERT INTO `spell_chain` VALUES ('4192', '4191', '4187', '6'); +INSERT INTO `spell_chain` VALUES ('4193', '4192', '4187', '7'); +INSERT INTO `spell_chain` VALUES ('4194', '4193', '4187', '8'); +INSERT INTO `spell_chain` VALUES ('5041', '4194', '4187', '9'); +INSERT INTO `spell_chain` VALUES ('5042', '5041', '4187', '10'); +INSERT INTO `spell_chain` VALUES ('27062', '5042', '4187', '11'); +INSERT INTO `spell_chain` VALUES ('24545', '0', '24545', '1'); +INSERT INTO `spell_chain` VALUES ('24549', '24545', '24545', '2'); +INSERT INTO `spell_chain` VALUES ('24550', '24549', '24545', '3'); +INSERT INTO `spell_chain` VALUES ('24551', '24550', '24545', '4'); +INSERT INTO `spell_chain` VALUES ('24552', '24551', '24545', '5'); +INSERT INTO `spell_chain` VALUES ('24553', '24552', '24545', '6'); +INSERT INTO `spell_chain` VALUES ('24554', '24553', '24545', '7'); +INSERT INTO `spell_chain` VALUES ('24555', '24554', '24545', '8'); +INSERT INTO `spell_chain` VALUES ('24629', '24555', '24545', '9'); +INSERT INTO `spell_chain` VALUES ('24630', '24629', '24545', '10'); +INSERT INTO `spell_chain` VALUES ('27061', '24630', '24545', '11'); +INSERT INTO `spell_chain` VALUES ('24493', '0', '24493', '1'); +INSERT INTO `spell_chain` VALUES ('24497', '24493', '24493', '2'); +INSERT INTO `spell_chain` VALUES ('24500', '24497', '24493', '3'); +INSERT INTO `spell_chain` VALUES ('24501', '24500', '24493', '4'); +INSERT INTO `spell_chain` VALUES ('27052', '24501', '24493', '5'); +INSERT INTO `spell_chain` VALUES ('23992', '0', '23992', '1'); +INSERT INTO `spell_chain` VALUES ('24439', '23992', '23992', '2'); +INSERT INTO `spell_chain` VALUES ('24444', '24439', '23992', '3'); +INSERT INTO `spell_chain` VALUES ('24445', '24444', '23992', '4'); +INSERT INTO `spell_chain` VALUES ('27053', '24445', '23992', '5'); +INSERT INTO `spell_chain` VALUES ('24446', '0', '24446', '1'); +INSERT INTO `spell_chain` VALUES ('24447', '24446', '24446', '2'); +INSERT INTO `spell_chain` VALUES ('24448', '24447', '24446', '3'); +INSERT INTO `spell_chain` VALUES ('24449', '24448', '24446', '4'); +INSERT INTO `spell_chain` VALUES ('27054', '24449', '24446', '5'); +INSERT INTO `spell_chain` VALUES ('24492', '0', '24492', '1'); +INSERT INTO `spell_chain` VALUES ('24502', '24492', '24492', '2'); +INSERT INTO `spell_chain` VALUES ('24503', '24502', '24492', '3'); +INSERT INTO `spell_chain` VALUES ('24504', '24503', '24492', '4'); +INSERT INTO `spell_chain` VALUES ('27055', '24504', '24492', '5'); +INSERT INTO `spell_chain` VALUES ('24488', '0', '24488', '1'); +INSERT INTO `spell_chain` VALUES ('24505', '24488', '24488', '2'); +INSERT INTO `spell_chain` VALUES ('24506', '24505', '24488', '3'); +INSERT INTO `spell_chain` VALUES ('24507', '24506', '24488', '4'); +INSERT INTO `spell_chain` VALUES ('27056', '24507', '24488', '5'); +INSERT INTO `spell_chain` VALUES ('6307', '0', '6307', '1'); +INSERT INTO `spell_chain` VALUES ('7804', '6307', '6307', '2'); +INSERT INTO `spell_chain` VALUES ('7805', '7804', '6307', '3'); +INSERT INTO `spell_chain` VALUES ('11766', '7805', '6307', '4'); +INSERT INTO `spell_chain` VALUES ('11767', '11766', '6307', '5'); +INSERT INTO `spell_chain` VALUES ('27268', '11767', '6307', '6'); +INSERT INTO `spell_chain` VALUES ('2947', '0', '2947', '1'); +INSERT INTO `spell_chain` VALUES ('8316', '2947', '2947', '2'); +INSERT INTO `spell_chain` VALUES ('8317', '8316', '2947', '3'); +INSERT INTO `spell_chain` VALUES ('11770', '8317', '2947', '4'); +INSERT INTO `spell_chain` VALUES ('11771', '11770', '2947', '5'); +INSERT INTO `spell_chain` VALUES ('27269', '11771', '2947', '6'); +INSERT INTO `spell_chain` VALUES ('3110', '0', '3110', '1'); +INSERT INTO `spell_chain` VALUES ('7799', '3110', '3110', '2'); +INSERT INTO `spell_chain` VALUES ('7800', '7799', '3110', '3'); +INSERT INTO `spell_chain` VALUES ('7801', '7800', '3110', '4'); +INSERT INTO `spell_chain` VALUES ('7802', '7801', '3110', '5'); +INSERT INTO `spell_chain` VALUES ('11762', '7802', '3110', '6'); +INSERT INTO `spell_chain` VALUES ('11763', '11762', '3110', '7'); +INSERT INTO `spell_chain` VALUES ('27267', '11763', '3110', '8'); +INSERT INTO `spell_chain` VALUES ('17767', '0', '17767', '1'); +INSERT INTO `spell_chain` VALUES ('17850', '17767', '17767', '2'); +INSERT INTO `spell_chain` VALUES ('17851', '17850', '17767', '3'); +INSERT INTO `spell_chain` VALUES ('17852', '17851', '17767', '4'); +INSERT INTO `spell_chain` VALUES ('17853', '17852', '17767', '5'); +INSERT INTO `spell_chain` VALUES ('17854', '17853', '17767', '6'); +INSERT INTO `spell_chain` VALUES ('27272', '17854', '17767', '7'); +INSERT INTO `spell_chain` VALUES ('7812', '0', '7812', '1'); +INSERT INTO `spell_chain` VALUES ('19438', '7812', '7812', '2'); +INSERT INTO `spell_chain` VALUES ('19440', '19438', '7812', '3'); +INSERT INTO `spell_chain` VALUES ('19441', '19440', '7812', '4'); +INSERT INTO `spell_chain` VALUES ('19442', '19441', '7812', '5'); +INSERT INTO `spell_chain` VALUES ('19443', '19442', '7812', '6'); +INSERT INTO `spell_chain` VALUES ('27273', '19443', '7812', '7'); +INSERT INTO `spell_chain` VALUES ('17735', '0', '17735', '1'); +INSERT INTO `spell_chain` VALUES ('17750', '17735', '17735', '2'); +INSERT INTO `spell_chain` VALUES ('17751', '17750', '17735', '3'); +INSERT INTO `spell_chain` VALUES ('17752', '17751', '17735', '4'); +INSERT INTO `spell_chain` VALUES ('27271', '17752', '17735', '5'); +INSERT INTO `spell_chain` VALUES ('33701', '27271', '17735', '6'); +INSERT INTO `spell_chain` VALUES ('3716', '0', '3716', '1'); +INSERT INTO `spell_chain` VALUES ('7809', '3716', '3716', '2'); +INSERT INTO `spell_chain` VALUES ('7810', '7809', '3716', '3'); +INSERT INTO `spell_chain` VALUES ('7811', '7810', '3716', '4'); +INSERT INTO `spell_chain` VALUES ('11774', '7811', '3716', '5'); +INSERT INTO `spell_chain` VALUES ('11775', '11774', '3716', '6'); +INSERT INTO `spell_chain` VALUES ('27270', '11775', '3716', '7'); +INSERT INTO `spell_chain` VALUES ('7814', '0', '7814', '1'); +INSERT INTO `spell_chain` VALUES ('7815', '7814', '7814', '2'); +INSERT INTO `spell_chain` VALUES ('7816', '7815', '7814', '3'); +INSERT INTO `spell_chain` VALUES ('11778', '7816', '7814', '4'); +INSERT INTO `spell_chain` VALUES ('11779', '11778', '7814', '5'); +INSERT INTO `spell_chain` VALUES ('11780', '11779', '7814', '6'); +INSERT INTO `spell_chain` VALUES ('27274', '11780', '7814', '7'); +INSERT INTO `spell_chain` VALUES ('6360', '0', '6360', '1'); +INSERT INTO `spell_chain` VALUES ('7813', '6360', '6360', '2'); +INSERT INTO `spell_chain` VALUES ('11784', '7813', '6360', '3'); +INSERT INTO `spell_chain` VALUES ('11785', '11784', '6360', '4'); +INSERT INTO `spell_chain` VALUES ('27275', '11785', '6360', '5'); +INSERT INTO `spell_chain` VALUES ('19505', '0', '19505', '1'); +INSERT INTO `spell_chain` VALUES ('19731', '19505', '19505', '2'); +INSERT INTO `spell_chain` VALUES ('19734', '19731', '19505', '3'); +INSERT INTO `spell_chain` VALUES ('19736', '19734', '19505', '4'); +INSERT INTO `spell_chain` VALUES ('27276', '19736', '19505', '5'); +INSERT INTO `spell_chain` VALUES ('27277', '27276', '19505', '6'); +INSERT INTO `spell_chain` VALUES ('19244', '0', '19244', '1'); +INSERT INTO `spell_chain` VALUES ('19647', '19244', '19244', '2'); +INSERT INTO `spell_chain` VALUES ('19478', '0', '19478', '1'); +INSERT INTO `spell_chain` VALUES ('19655', '19478', '19478', '2'); +INSERT INTO `spell_chain` VALUES ('19656', '19655', '19478', '3'); +INSERT INTO `spell_chain` VALUES ('19660', '19656', '19478', '4'); +INSERT INTO `spell_chain` VALUES ('27280', '19660', '19478', '5'); +INSERT INTO `spell_chain` VALUES ('33698', '0', '33698', '1'); +INSERT INTO `spell_chain` VALUES ('33699', '33698', '33698', '2'); +INSERT INTO `spell_chain` VALUES ('33700', '33699', '33698', '3'); +INSERT INTO `spell_chain` VALUES ('30213', '0', '30213', '1'); +INSERT INTO `spell_chain` VALUES ('30219', '30213', '30213', '2'); +INSERT INTO `spell_chain` VALUES ('30223', '30219', '30213', '3'); +INSERT INTO `spell_chain` VALUES ('30151', '0', '30151', '1'); +INSERT INTO `spell_chain` VALUES ('30194', '30151', '30151', '2'); +INSERT INTO `spell_chain` VALUES ('30198', '30194', '30151', '3'); diff --git a/sql/updates/0.8/4116_creature_template.sql b/sql/updates/0.8/4116_creature_template.sql new file mode 100644 index 00000000000..dfd710f8525 --- /dev/null +++ b/sql/updates/0.8/4116_creature_template.sql @@ -0,0 +1,2 @@ +ALTER TABLE `creature_template` +ADD COLUMN `RacialLeader` tinyint(1) unsigned NOT NULL default '0' AFTER `InhabitType`; diff --git a/sql/updates/0.8/4133_command.sql b/sql/updates/0.8/4133_command.sql new file mode 100644 index 00000000000..b50d320ac69 --- /dev/null +++ b/sql/updates/0.8/4133_command.sql @@ -0,0 +1,6 @@ +DELETE FROM `command` WHERE `name` = 'reload'; +DELETE FROM `command` WHERE `name` = 'reload all'; +DELETE FROM `command` WHERE `name` = 'reload all_spell'; +INSERT INTO `command` VALUES('reload',3,'Syntax: .reload table_name\r\n\r\nReload table `table_name` if reload support added for this table and this table can be _safe_ reloaded.'); +INSERT INTO `command` VALUES('reload all',3,'Syntax: .reload all\r\n\r\nReload all tables with reload support added and that can be _safe_ reloaded.'); +INSERT INTO `command` VALUES('reload all_spell',3,'Syntax: .reload all\r\n\r\nReload all `spell_*` tables with reload support added and that can be _safe_ reloaded.'); diff --git a/sql/updates/0.8/4133_spell_chain.sql b/sql/updates/0.8/4133_spell_chain.sql new file mode 100644 index 00000000000..ff5d35f0b3a --- /dev/null +++ b/sql/updates/0.8/4133_spell_chain.sql @@ -0,0 +1,7 @@ +DELETE FROM `spell_chain` WHERE `spell_id` IN (5487,9634,33943,40120); + +INSERT INTO `spell_chain` VALUES +(5487,0,5487,1), +(9634,5487,5487,2), +(33943,0,33943,1), +(40120,33943,33943,2); diff --git a/sql/updates/0.8/4134_command.sql b/sql/updates/0.8/4134_command.sql new file mode 100644 index 00000000000..e34ad40fddf --- /dev/null +++ b/sql/updates/0.8/4134_command.sql @@ -0,0 +1,6 @@ +DELETE FROM `command` WHERE `name` = 'reload all_area'; +DELETE FROM `command` WHERE `name` = 'reload all_loot'; +DELETE FROM `command` WHERE `name` = 'reload all_quest'; +INSERT INTO `command` VALUES('reload all_area',3,'Syntax: .reload all_area\r\n\r\nReload all `areatrigger_*` tables if reload support added for this table and this table can be _safe_ reloaded.'); +INSERT INTO `command` VALUES('reload all_loot',3,'Syntax: .reload all_loot\r\n\r\nReload all `*_loot_template` tables. This can be slow operation with lags for server run.'); +INSERT INTO `command` VALUES('reload all_quest',3,'Syntax: .reload all_quest\r\n\r\nReload all quest related tables if reload support added for this table and this table can be _safe_ reloaded.'); diff --git a/sql/updates/0.8/4139_spell_proc_event.sql b/sql/updates/0.8/4139_spell_proc_event.sql new file mode 100644 index 00000000000..fd83802c01e --- /dev/null +++ b/sql/updates/0.8/4139_spell_proc_event.sql @@ -0,0 +1,5 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 11255, 12598 ); +INSERT INTO `spell_proc_event` VALUES +(11255,32,0,0,3,0,16384,0), +(12598,32,0,0,3,0,16384,0); + diff --git a/sql/updates/0.8/4140_command.sql b/sql/updates/0.8/4140_command.sql new file mode 100644 index 00000000000..f70bb2ce1a8 --- /dev/null +++ b/sql/updates/0.8/4140_command.sql @@ -0,0 +1,4 @@ +INSERT INTO `command` ( `name` , `security` , `help` ) +VALUES ( +'tele', '1', 'Syntax: .tele $location\n\nTeleport the gm to the provided location. You can look up these locations using .lookuptele' +); \ No newline at end of file diff --git a/sql/updates/0.8/4145_character_reputation.sql b/sql/updates/0.8/4145_character_reputation.sql new file mode 100644 index 00000000000..b9849f11474 --- /dev/null +++ b/sql/updates/0.8/4145_character_reputation.sql @@ -0,0 +1 @@ +ALTER TABLE `character_reputation` DROP `reputation`; \ No newline at end of file diff --git a/sql/updates/0.8/4154_spell_proc_event.sql b/sql/updates/0.8/4154_spell_proc_event.sql new file mode 100644 index 00000000000..dbb1e1e04ca --- /dev/null +++ b/sql/updates/0.8/4154_spell_proc_event.sql @@ -0,0 +1,23 @@ +/* for reference +DROP TABLE IF EXISTS `spell_proc_event`; +CREATE TABLE `spell_proc_event` ( + `entry` smallint(6) unsigned NOT NULL default '0', + `SchoolMask` tinyint(4) NOT NULL default '0', + `Category` smallint(6) NOT NULL default '0', + `SkillID` smallint(6) NOT NULL default '0', + `SpellFamilyName` smallint(6) unsigned NOT NULL default '0', + `SpellFamilyMask` bigint(40) unsigned NOT NULL default '0', + `procFlags` int(11) unsigned NOT NULL default '0', + `ppmRate` float NOT NULL default '0', + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +*/ + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 30675, 30678, 30679, 30680, 30681 ); +INSERT INTO `spell_proc_event` VALUES +(30675,0,0,0,11,3,16384,0), +(30678,0,0,0,11,3,16384,0), +(30679,0,0,0,11,3,16384,0), +(30680,0,0,0,11,3,16384,0), +(30681,0,0,0,11,3,16384,0); + diff --git a/sql/updates/0.8/4176_character.sql b/sql/updates/0.8/4176_character.sql new file mode 100644 index 00000000000..5a7b106b2c1 --- /dev/null +++ b/sql/updates/0.8/4176_character.sql @@ -0,0 +1 @@ +ALTER TABLE `character` ADD `zone` INT(11) UNSIGNED NOT NULL DEFAULT '0'; diff --git a/sql/updates/0.8/4176_command.sql b/sql/updates/0.8/4176_command.sql new file mode 100644 index 00000000000..8e88e84c7e3 --- /dev/null +++ b/sql/updates/0.8/4176_command.sql @@ -0,0 +1,3 @@ +INSERT INTO `command` ( `name` , `security` , `help` ) VALUES +('gogrid', '3', 'Syntax: .gogrid #gridX #gridY [#mapId]\n\nTeleport the gm to center of grid with provided indexes at map #mapId (or current map if it not provided).'); + diff --git a/sql/updates/0.8/4187_command.sql b/sql/updates/0.8/4187_command.sql new file mode 100644 index 00000000000..75033a11ccb --- /dev/null +++ b/sql/updates/0.8/4187_command.sql @@ -0,0 +1,5 @@ +UPDATE `command` SET `help` = 'Syntax: .learn all_myclass\r\n\r\nLearn all spells and talents available for his class.' WHERE `name` = 'learn all_myclass'; +INSERT INTO `command` ( `name` , `security` , `help` ) VALUES +('learn all_myspells',3,'Syntax: .learn all_myspells\r\n\r\nLearn all spells (except talents and spells with first rank learned as talent) available for his class.'), +('learn all_mytalents',3,'Syntax: .learn all_mytalents\r\n\r\nLearn all talents (and spells with first rank learned as talent) available for his class.'); + diff --git a/sql/updates/0.8/4204_command.sql b/sql/updates/0.8/4204_command.sql new file mode 100644 index 00000000000..af8b8d37338 --- /dev/null +++ b/sql/updates/0.8/4204_command.sql @@ -0,0 +1,4 @@ +DELETE FROM `command` WHERE `name` = 'setmovetype'; + +INSERT INTO `command` ( `name` , `security` , `help` ) VALUES +('setmovetype',2,'Syntax: .setmovetype [#creature_guid] stay/random/way [NODEL]\r\n\r\nSet for creature pointed by #creature_guid (or selected if #creature_guid not provided) movement type and move it to respawn position (if creature alive). Any existing waypoints for creature will be removed from the database if you do not use NODEL. If the creature is dead then movement type will applied at creature respawn.\r\nMake sure you use NODEL, if you want to keep the waypoints.'); \ No newline at end of file diff --git a/sql/updates/0.8/4205_creature_template.sql b/sql/updates/0.8/4205_creature_template.sql new file mode 100644 index 00000000000..84a65b400cf --- /dev/null +++ b/sql/updates/0.8/4205_creature_template.sql @@ -0,0 +1,4 @@ +update creature_template set attackpower = round((maxdmg + mindmg) / 4 * 7); +update creature_template set mindmg = round(mindmg - attackpower / 7); +update creature_template set maxdmg = round(maxdmg - attackpower / 7); +update creature_template set mindmg = 1 where mindmg < 1; \ No newline at end of file diff --git a/sql/updates/0.8/4224_character_aura.sql b/sql/updates/0.8/4224_character_aura.sql new file mode 100644 index 00000000000..3daac525668 --- /dev/null +++ b/sql/updates/0.8/4224_character_aura.sql @@ -0,0 +1,6 @@ +ALTER TABLE `character_aura` + ADD `caster_guid` bigint(20) unsigned NOT NULL default '0' COMMENT 'Full Global Unique Identifier' AFTER `guid`, + ADD `amount` int(11) NOT NULL default '0' AFTER `effect_index`; + +UPDATE `character_aura` + SET `caster_guid` = `guid`; \ No newline at end of file diff --git a/sql/updates/0.8/4224_pet_aura.sql b/sql/updates/0.8/4224_pet_aura.sql new file mode 100644 index 00000000000..f185a65ce43 --- /dev/null +++ b/sql/updates/0.8/4224_pet_aura.sql @@ -0,0 +1,6 @@ +ALTER TABLE `pet_aura` + ADD `caster_guid` bigint(20) unsigned NOT NULL default '0' COMMENT 'Full Global Unique Identifier' AFTER `guid`, + ADD `amount` int(11) NOT NULL default '0' AFTER `effect_index`; + +UPDATE `pet_aura` + SET `caster_guid` = `guid`; \ No newline at end of file diff --git a/sql/updates/0.8/4235_spell_proc_event.sql b/sql/updates/0.8/4235_spell_proc_event.sql new file mode 100644 index 00000000000..f87f40b9b2d --- /dev/null +++ b/sql/updates/0.8/4235_spell_proc_event.sql @@ -0,0 +1,7 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 37514 ); +INSERT INTO `spell_proc_event` (`entry` ,`SchoolMask`,`Category`,`SkillID`,`SpellFamilyName`,`SpellFamilyMask`,`procFlags`,`ppmRate`) +VALUES ('37514', '0', '0', '0', '0', '0', '32', '0'); + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 37197 ); +INSERT INTO `spell_proc_event` (`entry` ,`SchoolMask`,`Category`,`SkillID`,`SpellFamilyName`,`SpellFamilyMask`,`procFlags`,`ppmRate`) +VALUES ('37197', '0', '0', '0', '0', '0', '16384', '0'); \ No newline at end of file diff --git a/sql/updates/0.8/4239_spell_chain.sql b/sql/updates/0.8/4239_spell_chain.sql new file mode 100644 index 00000000000..287a1de6f47 --- /dev/null +++ b/sql/updates/0.8/4239_spell_chain.sql @@ -0,0 +1,4 @@ +DELETE FROM `spell_chain` WHERE `spell_id` IN (25477); + +INSERT INTO `spell_chain` VALUES +(25477,19312,18137,7); diff --git a/sql/updates/0.8/4239_spell_proc_event.sql b/sql/updates/0.8/4239_spell_proc_event.sql new file mode 100644 index 00000000000..1e4852c335a --- /dev/null +++ b/sql/updates/0.8/4239_spell_proc_event.sql @@ -0,0 +1,9 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (18137,19308,19309,19310,19311,19312,25477); +INSERT INTO `spell_proc_event` VALUES +(18137,0,0,0,0,0,1049602,0), +(19308,0,0,0,0,0,1049602,0), +(19309,0,0,0,0,0,1049602,0), +(19310,0,0,0,0,0,1049602,0), +(19311,0,0,0,0,0,1049602,0), +(19312,0,0,0,0,0,1049602,0), +(25477,0,0,0,0,0,1049602,0); diff --git a/sql/updates/0.8/4242_spell_proc_event.sql b/sql/updates/0.8/4242_spell_proc_event.sql new file mode 100644 index 00000000000..5e00ec3d3e3 --- /dev/null +++ b/sql/updates/0.8/4242_spell_proc_event.sql @@ -0,0 +1,34 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (34948, 34949); +INSERT INTO `spell_proc_event` (entry, SchoolMask, Category, SkillID, SpellFamilyName, SpellFamilyMask, procFlags, ppmRate) VALUES +(34948, 0, 0, 0, 0, 0, 4, 0), +(34949, 0, 0, 0, 0, 0, 4, 0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (34497, 34498, 34499); +INSERT INTO `spell_proc_event` (entry, SchoolMask, Category, SkillID, SpellFamilyName, SpellFamilyMask, procFlags, ppmRate) VALUES +(34497, 0, 0, 0, 0, 0, 4194304, 0), +(34498, 0, 0, 0, 0, 0, 4194304, 0), +(34499, 0, 0, 0, 0, 0, 4194304, 0); + + +DELETE FROM `spell_proc_event` WHERE `entry` IN (34500, 34502, 34503); +INSERT INTO `spell_proc_event` (entry, SchoolMask, Category, SkillID, SpellFamilyName, SpellFamilyMask, procFlags, ppmRate) VALUES +(34500, 0, 0, 0, 0, 0, 4194304, 0), +(34502, 0, 0, 0, 0, 0, 4194304, 0), +(34503, 0, 0, 0, 0, 0, 4194304, 0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (30823); +INSERT INTO `spell_proc_event` (entry, SchoolMask, Category, SkillID, SpellFamilyName, SpellFamilyMask, procFlags, ppmRate) VALUES +(30823, 0, 0, 0, 0, 0, 1, 0); + + +DELETE FROM `spell_proc_event` WHERE `entry` IN (31244,31245); +INSERT INTO `spell_proc_event` (entry, SchoolMask, Category, SkillID, SpellFamilyName, SpellFamilyMask, procFlags, ppmRate) VALUES +(31244, 0, 0, 0, 0, 0, 2147483648, 0), +(31245, 0, 0, 0, 0, 0, 2147483648, 0); + + +DELETE FROM `spell_proc_event` WHERE `entry` IN (34935,34938,34939); +INSERT INTO `spell_proc_event` (entry, SchoolMask, Category, SkillID, SpellFamilyName, SpellFamilyMask, procFlags, ppmRate) VALUES +(34935, 0, 0, 0, 0, 0, 2, 0), +(34938, 0, 0, 0, 0, 0, 2, 0), +(34939, 0, 0, 0, 0, 0, 2, 0); diff --git a/sql/updates/0.8/4243_spell_affect.sql b/sql/updates/0.8/4243_spell_affect.sql new file mode 100644 index 00000000000..61c0ff8e615 --- /dev/null +++ b/sql/updates/0.8/4243_spell_affect.sql @@ -0,0 +1,19 @@ +/* +DROP TABLE IF EXISTS `spell_affect`; +CREATE TABLE `spell_affect` ( + `entry` smallint(5) unsigned NOT NULL default '0', + `effectId` tinyint(3) unsigned NOT NULL default '0', + `SpellId` smallint(5) unsigned NOT NULL default '0', + `SchoolMask` tinyint(3) unsigned NOT NULL default '0', + `Category` smallint(5) unsigned NOT NULL default '0', + `SkillID` smallint(5) unsigned NOT NULL default '0', + `SpellFamily` tinyint(3) unsigned NOT NULL default '0', + `SpellFamilyMask` bigint(20) unsigned NOT NULL default '0', + `Charges` smallint(5) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`,`effectId`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +*/ + +DELETE FROM `spell_affect` WHERE `entry` IN (34936); +INSERT INTO `spell_affect` VALUES +(34936,0,0,0,0,0,0,274877906945,1); diff --git a/sql/updates/0.8/4248_spell_chain.sql b/sql/updates/0.8/4248_spell_chain.sql new file mode 100644 index 00000000000..718126f95ad --- /dev/null +++ b/sql/updates/0.8/4248_spell_chain.sql @@ -0,0 +1,13 @@ +DELETE FROM `spell_chain` WHERE `spell_id` IN (33878,33986,33987); + +INSERT INTO `spell_chain` VALUES +(33878,0,33878,1), +(33986,33878,33878,2), +(33987,33986,33878,3); + +DELETE FROM `spell_chain` WHERE `spell_id` IN (33876,33982,33983); + +INSERT INTO `spell_chain` VALUES +(33876,0,33876,1), +(33982,33876,33876,2), +(33983,33982,33876,3); diff --git a/sql/updates/0.8/4248_spell_proc_event.sql b/sql/updates/0.8/4248_spell_proc_event.sql new file mode 100644 index 00000000000..e8252cd265e --- /dev/null +++ b/sql/updates/0.8/4248_spell_proc_event.sql @@ -0,0 +1,70 @@ +/* fix scholl mask */ +DELETE FROM `spell_proc_event` WHERE `entry` IN (11103,11119,11120,11129,11180,11255,12357,12358,12359,12360,12598,12846,12847,12848,14892,15268,15286,15323,15324,15325,15326,15362,15363,16164,17793,17796,17801,17802,17803,18073,18096,19407,19412,19413,19414,19415,20234,20235,23551,23572,23721,28592,28593,28594,28595,28719,28809,28823,28847,28849,29074,29075,29076,34914,34916,34917); +INSERT INTO `spell_proc_event` (entry, SchoolMask, Category, SkillID, SpellFamilyName, SpellFamilyMask, procFlags, ppmRate) VALUES +(11103,4,0,0,0,0,131072,0), +(11119,4,0,0,0,0,65536,0), +(11120,4,0,0,0,0,65536,0), +(11129,4,0,0,0,0,131072,0), +(11180,16,0,0,0,0,131072,0), +(11255,64,0,0,3,0,16384,0), +(12357,4,0,0,0,0,131072,0), +(12358,4,0,0,0,0,131072,0), +(12359,4,0,0,0,0,131072,0), +(12360,4,0,0,0,0,131072,0), +(12598,64,0,0,3,0,16384,0), +(12846,4,0,0,0,0,65536,0), +(12847,4,0,0,0,0,65536,0), +(12848,4,0,0,0,0,65536,0), +(14892,2,0,56,0,7680,268435456,0), +(15268,32,0,0,0,0,131072,0), +(15286,32,0,0,0,0,32768,0), +(15323,32,0,0,0,0,131072,0), +(15324,32,0,0,0,0,131072,0), +(15325,32,0,0,0,0,131072,0), +(15326,32,0,0,0,0,131072,0), +(15362,2,0,56,0,7680,268435456,0), +(15363,2,0,56,0,7680,268435456,0), +(16164,28,0,0,0,0,65536,0), +(17793,32,0,593,0,1,65536,0), +(17796,32,0,593,0,1,65536,0), +(17801,32,0,593,0,1,65536,0), +(17802,32,0,593,0,1,65536,0), +(17803,32,0,593,0,1,65536,0), +(18073,4,0,0,0,96,131072,0), +(18096,4,0,0,0,96,131072,0), +(19407,64,0,0,0,512,131072,0), +(19412,64,0,0,0,512,131072,0), +(19413,64,0,0,0,512,131072,0), +(19414,64,0,0,0,512,131072,0), +(19415,64,0,0,0,512,131072,0), +(20234,2,0,0,0,32768,131072,0), +(20235,2,0,0,0,32768,131072,0), +(23551,8,0,0,0,192,16384,0), +(23572,8,0,0,0,192,16384,0), +(23721,64,0,163,0,2048,131072,0), +(28592,16,0,0,0,0,131072,0), +(28593,16,0,0,0,0,131072,0), +(28594,16,0,0,0,0,131072,0), +(28595,16,0,0,0,0,131072,0), +(28719,8,0,0,0,32,268435456,0), +(28809,2,0,56,0,4096,268435456,0), +(28823,8,0,374,0,192,134217728,0), +(28847,8,0,573,0,32,16384,0), +(28849,8,0,374,0,128,16384,0), +(29074,20,0,0,0,0,65536,0), +(29075,20,0,0,0,0,65536,0), +(29076,20,0,0,0,0,65536,0), +(34914,32,0,0,0,0,32768,0), +(34916,32,0,0,0,0,32768,0), +(34917,32,0,0,0,0,32768,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (6866,18189); +INSERT INTO `spell_proc_event` (entry, SchoolMask, Category, SkillID, SpellFamilyName, SpellFamilyMask, procFlags, ppmRate) VALUES +(6866,0,0,0,0,0,114,0), +(18189,0,0,0,0,0,131072,0); + + +DELETE FROM `spell_proc_event` WHERE `entry` IN (37377,39437); +INSERT INTO `spell_proc_event` (entry, SchoolMask, Category, SkillID, SpellFamilyName, SpellFamilyMask, procFlags, ppmRate) VALUES +(37377,32,0,0,0,0,16384,0), +(39437,4,0,0,0,0,16384,0); diff --git a/sql/updates/0.8/4252_spell_threat.sql b/sql/updates/0.8/4252_spell_threat.sql new file mode 100644 index 00000000000..293388810a9 --- /dev/null +++ b/sql/updates/0.8/4252_spell_threat.sql @@ -0,0 +1,4 @@ +INSERT INTO spell_threat VALUES +(20243,101), +(30016,101), +(30022,101); \ No newline at end of file diff --git a/sql/updates/0.8/4255_spell_chain.sql b/sql/updates/0.8/4255_spell_chain.sql new file mode 100644 index 00000000000..13604da3b53 --- /dev/null +++ b/sql/updates/0.8/4255_spell_chain.sql @@ -0,0 +1,6 @@ +/* dependent from 14752 */ +DELETE FROM `spell_chain` WHERE `spell_id` IN (27681,32999); + +INSERT INTO `spell_chain` VALUES +(27681,14752,14752,2), +(32999,27681,14752,3); diff --git a/sql/updates/0.8/4258_command.sql b/sql/updates/0.8/4258_command.sql new file mode 100644 index 00000000000..0936503c3fd --- /dev/null +++ b/sql/updates/0.8/4258_command.sql @@ -0,0 +1,4 @@ +DELETE FROM `command` WHERE `name` = 'grouptele'; + +INSERT INTO `command` ( `name` , `security` , `help` ) VALUES +('grouptele',1,'Syntax: .grouptele #location\r\n\r\nTeleport a selected player and his group members to a given location.'); diff --git a/sql/updates/0.8/4259_spell_chain.sql b/sql/updates/0.8/4259_spell_chain.sql new file mode 100644 index 00000000000..763396693b1 --- /dev/null +++ b/sql/updates/0.8/4259_spell_chain.sql @@ -0,0 +1,7 @@ +DELETE FROM `spell_chain` WHERE `spell_id` IN (27168); +INSERT INTO `spell_chain` VALUES +(27168,20914,20911,5); + +DELETE FROM `spell_chain` WHERE `spell_id` IN (27169); +INSERT INTO `spell_chain` VALUES +(27169,25899,25899,2); diff --git a/sql/updates/0.8/4259_spell_proc_event.sql b/sql/updates/0.8/4259_spell_proc_event.sql new file mode 100644 index 00000000000..c5191b472b0 --- /dev/null +++ b/sql/updates/0.8/4259_spell_proc_event.sql @@ -0,0 +1,19 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (30299,30301,30302); +INSERT INTO `spell_proc_event` (entry, SchoolMask, Category, SkillID, SpellFamilyName, SpellFamilyMask, procFlags, ppmRate) VALUES +(30299,36,0,0,0,0,1048576,0), +(30301,36,0,0,0,0,1048576,0), +(30302,36,0,0,0,0,1048576,0); + + +DELETE FROM `spell_proc_event` WHERE `entry` IN (27168); +INSERT INTO `spell_proc_event` (entry, SchoolMask, Category, SkillID, SpellFamilyName, SpellFamilyMask, procFlags, ppmRate) VALUES +(27168,0,0,0,0,0,64,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (27169); +INSERT INTO `spell_proc_event` (entry, SchoolMask, Category, SkillID, SpellFamilyName, SpellFamilyMask, procFlags, ppmRate) VALUES +(27169,0,0,0,0,0,64,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (33150,33154); +INSERT INTO `spell_proc_event` (entry, SchoolMask, Category, SkillID, SpellFamilyName, SpellFamilyMask, procFlags, ppmRate) VALUES +(33150,0,0,0,0,0,65536,0), +(33154,0,0,0,0,0,65536,0); diff --git a/sql/updates/0.8/4262_spell_proc_event.sql b/sql/updates/0.8/4262_spell_proc_event.sql new file mode 100644 index 00000000000..d67fefa7c3b --- /dev/null +++ b/sql/updates/0.8/4262_spell_proc_event.sql @@ -0,0 +1,20 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 33191, 33192, 33193, 33194, 33195 ); +INSERT INTO `spell_proc_event` VALUES +(33191,0,0,0,6,4398054932480,131072,0), +(33192,0,0,0,6,4398054932480,131072,0), +(33193,0,0,0,6,4398054932480,131072,0), +(33194,0,0,0,6,4398054932480,131072,0), +(33195,0,0,0,6,4398054932480,131072,0); + + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 32385, 32387, 32392, 32393, 32394, 33191, 33192, 33193, 33194, 33195 ); +INSERT INTO `spell_proc_event` VALUES +(32385,0,0,0,5,73014445058,131072,0), +(32387,0,0,0,5,73014445058,131072,0), +(32392,0,0,0,5,73014445058,131072,0), +(32393,0,0,0,5,73014445058,131072,0), +(32394,0,0,0,5,73014445058,131072,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 30482 ); +INSERT INTO `spell_proc_event` VALUES +(30482,0,0,0,0,0,32768,0); diff --git a/sql/updates/0.8/4266_spell_proc_event.sql b/sql/updates/0.8/4266_spell_proc_event.sql new file mode 100644 index 00000000000..d53c9168bea --- /dev/null +++ b/sql/updates/0.8/4266_spell_proc_event.sql @@ -0,0 +1,7 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 20210, 20212, 20213, 20214, 20215 ); +INSERT INTO `spell_proc_event` VALUES +(20210,0,0,0,10,3223322624,268435456,0), +(20212,0,0,0,10,3223322624,268435456,0), +(20213,0,0,0,10,3223322624,268435456,0), +(20214,0,0,0,10,3223322624,268435456,0), +(20215,0,0,0,10,3223322624,268435456,0); diff --git a/sql/updates/0.8/4267_command.sql b/sql/updates/0.8/4267_command.sql new file mode 100644 index 00000000000..b702353e5f9 --- /dev/null +++ b/sql/updates/0.8/4267_command.sql @@ -0,0 +1,6 @@ +DELETE FROM `command` WHERE `name` = 'namego'; +DELETE FROM `command` WHERE `name` = 'groupgo'; + +INSERT INTO `command` ( `name` , `security` , `help` ) VALUES +('namego',1,'Syntax: .namego $charactername\r\n\r\nTeleport the given character to you.'), +('groupgo',1,'Syntax: .groupgo $charactername\r\n\r\nTeleport the given character and his group to you.'); diff --git a/sql/updates/0.8/4270_spell_proc_event.sql b/sql/updates/0.8/4270_spell_proc_event.sql new file mode 100644 index 00000000000..87d38c81a46 --- /dev/null +++ b/sql/updates/0.8/4270_spell_proc_event.sql @@ -0,0 +1,7 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 33191, 33192, 33193, 33194, 33195 ); +INSERT INTO `spell_proc_event` VALUES +(33191,0,0,0,6,4398054932480,131072,0), +(33192,0,0,0,6,4398054932480,131072,0), +(33193,0,0,0,6,4398054932480,131072,0), +(33194,0,0,0,6,4398054932480,131072,0), +(33195,0,0,0,6,4398054932480,131072,0); diff --git a/sql/updates/0.8/4272_spell_proc_event.sql b/sql/updates/0.8/4272_spell_proc_event.sql new file mode 100644 index 00000000000..1e57bfd0246 --- /dev/null +++ b/sql/updates/0.8/4272_spell_proc_event.sql @@ -0,0 +1,11 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 16880 ); +INSERT INTO `spell_proc_event` VALUES +(16880,0,0,0,0,0,65536,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 40475 ); +INSERT INTO `spell_proc_event` VALUES +(40475,0,0,0,0,0,524289,3); + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 41434 ); +INSERT INTO `spell_proc_event` VALUES +(41434,0,0,0,0,0,1,2); diff --git a/sql/updates/0.8/4274_character_pet.sql b/sql/updates/0.8/4274_character_pet.sql new file mode 100644 index 00000000000..bae4114fb1e --- /dev/null +++ b/sql/updates/0.8/4274_character_pet.sql @@ -0,0 +1,9 @@ +ALTER TABLE `character_pet` ADD `CreatedBySpell` int(11) unsigned NOT NULL default '0' AFTER `modelid`; +ALTER TABLE `character_pet` ADD `PetType` tinyint(3) unsigned NOT NULL default '0' AFTER `CreatedBySpell`; +UPDATE `character_pet` SET `PetType` = 1, `CreatedBySpell` = 1515 WHERE (`entry` <> 416 AND `entry` <> 417 AND `entry` <> 1860 AND `entry` <> 1863 AND `entry` <> 17252 AND `entry` <> 510); +UPDATE `character_pet` SET `CreatedBySpell` = 688 WHERE (`entry` = 416); +UPDATE `character_pet` SET `CreatedBySpell` = 691 WHERE (`entry` = 417); +UPDATE `character_pet` SET `CreatedBySpell` = 697 WHERE (`entry` = 1860); +UPDATE `character_pet` SET `CreatedBySpell` = 712 WHERE (`entry` = 1863); +UPDATE `character_pet` SET `CreatedBySpell` = 30146 WHERE (`entry` = 17252); +UPDATE `character_pet` SET `CreatedBySpell` = 31687 WHERE (`entry` = 510); \ No newline at end of file diff --git a/sql/updates/0.8/4275_game_event.sql b/sql/updates/0.8/4275_game_event.sql new file mode 100644 index 00000000000..5bf5a6f05f0 --- /dev/null +++ b/sql/updates/0.8/4275_game_event.sql @@ -0,0 +1,21 @@ +CREATE TABLE `game_event_gameobject` ( + `guid` int(10) unsigned NOT NULL, + `event` mediumint(9) NOT NULL DEFAULT '0' COMMENT 'Put negatives values to remove during event', + PRIMARY KEY (`guid`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +CREATE TABLE `game_event_creature` ( + `guid` int(10) unsigned NOT NULL, + `event` mediumint(9) NOT NULL DEFAULT '0' COMMENT 'Put negatives values to remove during event', + PRIMARY KEY (`guid`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +CREATE TABLE `game_event` ( + `entry` mediumint(8) unsigned NOT NULL COMMENT 'Entry of the game event', + `start` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'Absolute start date, the event will never start before', + `end` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'Absolute end date, the event will never start afler', + `occurence` bigint(20) unsigned NOT NULL DEFAULT '86400' COMMENT 'Delay in hours between occurences of the event', + `length` bigint(20) unsigned NOT NULL DEFAULT '43200' COMMENT 'Length in hours of the event', + `description` varchar(255) DEFAULT NULL COMMENT 'Description of the event displayed in console', + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; diff --git a/sql/updates/0.8/4288_spell_proc_event.sql b/sql/updates/0.8/4288_spell_proc_event.sql new file mode 100644 index 00000000000..0e3e6f89064 --- /dev/null +++ b/sql/updates/0.8/4288_spell_proc_event.sql @@ -0,0 +1,47 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 34320 ); +INSERT INTO `spell_proc_event` VALUES +(34320,0,0,0,0,0,65536,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 38347 ); +INSERT INTO `spell_proc_event` VALUES +(38347,0,0,0,0,0,65536,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 42083 ); +INSERT INTO `spell_proc_event` VALUES +(42083,0,0,0,0,0,4198400,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 33012 ); +INSERT INTO `spell_proc_event` VALUES +(33012,0,0,0,0,0,4,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 33014 ); +INSERT INTO `spell_proc_event` VALUES +(33014,0,0,0,0,0,4,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 31794 ); +INSERT INTO `spell_proc_event` VALUES +(31794,0,0,0,0,0,16384,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 33089 ); +INSERT INTO `spell_proc_event` VALUES +(33089,0,0,0,0,0,64,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 34586 ); +INSERT INTO `spell_proc_event` VALUES +(34586,0,0,0,0,0,524289,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 38332 ); +INSERT INTO `spell_proc_event` VALUES +(38332,0,0,0,0,0,134217728,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 37657 ); +INSERT INTO `spell_proc_event` VALUES +(37657,0,0,0,0,0,65536,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 37195 ); +INSERT INTO `spell_proc_event` VALUES +(37195,0,0,0,10,8388608,16384,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 37525 ); +INSERT INTO `spell_proc_event` VALUES +(37525,0,0,0,0,0,1049602,0); diff --git a/sql/updates/0.8/4294_spell_proc_event.sql b/sql/updates/0.8/4294_spell_proc_event.sql new file mode 100644 index 00000000000..bbf6f413c0a --- /dev/null +++ b/sql/updates/0.8/4294_spell_proc_event.sql @@ -0,0 +1,23 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 11255, 12598 ); +INSERT INTO `spell_proc_event` VALUES +(11255,0,0,0,3,16384,16384,0), +(12598,0,0,0,3,16384,16384,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 17793, 17796, 17801, 17802, 17803 ); +INSERT INTO `spell_proc_event` VALUES +(17793,0,0,593,5,1,65536,0), +(17796,0,0,593,5,1,65536,0), +(17801,0,0,593,5,1,65536,0), +(17802,0,0,593,5,1,65536,0), +(17803,0,0,593,5,1,65536,0); + + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 18094, 18095 ); +INSERT INTO `spell_proc_event` VALUES +(18094,0,0,0,5,10,131072,0), +(18095,0,0,0,5,10,131072,0); + + +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 37443 ); +INSERT INTO `spell_proc_event` VALUES +(37443,0,0,0,0,0,65536,0); diff --git a/sql/updates/0.8/4296_spell_proc_event.sql b/sql/updates/0.8/4296_spell_proc_event.sql new file mode 100644 index 00000000000..902a3f3ca10 --- /dev/null +++ b/sql/updates/0.8/4296_spell_proc_event.sql @@ -0,0 +1,4 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN ( 12958, 12311 ); +INSERT INTO `spell_proc_event` VALUES +(12958,0,0,0,4,0x800,0x20000,0), +(12311,0,0,0,4,0x800,0x20000,0); diff --git a/sql/updates/0.8/4317_spell_affect.sql b/sql/updates/0.8/4317_spell_affect.sql new file mode 100644 index 00000000000..6239feca4fe --- /dev/null +++ b/sql/updates/0.8/4317_spell_affect.sql @@ -0,0 +1,4 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (31670,31672); +INSERT INTO `spell_affect` VALUES +(31670,0,0,0,0,0,0,0x500080000,0), +(31672,0,0,0,0,0,0,0x500080000,0); diff --git a/sql/updates/0.8/4320_spell_affect.sql b/sql/updates/0.8/4320_spell_affect.sql new file mode 100644 index 00000000000..0018a669d6c --- /dev/null +++ b/sql/updates/0.8/4320_spell_affect.sql @@ -0,0 +1,4 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (31670,31672); +INSERT INTO `spell_affect` VALUES +(31670,0,0,0,0,0,0,0x500000200,0), +(31672,0,0,0,0,0,0,0x500000200,0); diff --git a/sql/updates/0.8/4331_spell_chain.sql b/sql/updates/0.8/4331_spell_chain.sql new file mode 100644 index 00000000000..4542e6411eb --- /dev/null +++ b/sql/updates/0.8/4331_spell_chain.sql @@ -0,0 +1,6 @@ +DELETE FROM `spell_chain` WHERE `spell_id` IN (974,32593,32594); +INSERT INTO `spell_chain` VALUES +(974,0,974,1), +(32593,974,974,2), +(32594,32593,974,3); + diff --git a/sql/updates/0.8/4331_spell_proc_event.sql b/sql/updates/0.8/4331_spell_proc_event.sql new file mode 100644 index 00000000000..cc91ec0c139 --- /dev/null +++ b/sql/updates/0.8/4331_spell_proc_event.sql @@ -0,0 +1,15 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (974,32593,32594); +INSERT INTO `spell_proc_event` VALUES +(974,0,0,0,0,0,0x100402,0), +(32593,0,0,0,0,0,0x100402,0), +(32594,0,0,0,0,0,0x100402,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (2652,19261,19262,19264,19265,19266,25461); +INSERT INTO `spell_proc_event` VALUES +(2652, 0,0,0,0,0,0x2,0), +(19261,0,0,0,0,0,0x2,0), +(19262,0,0,0,0,0,0x2,0), +(19264,0,0,0,0,0,0x2,0), +(19265,0,0,0,0,0,0x2,0), +(19266,0,0,0,0,0,0x2,0), +(25461,0,0,0,0,0,0x2,0); diff --git a/sql/updates/0.8/4341_game_event.sql b/sql/updates/0.8/4341_game_event.sql new file mode 100644 index 00000000000..f0fcd34d6ad --- /dev/null +++ b/sql/updates/0.8/4341_game_event.sql @@ -0,0 +1,4 @@ +ALTER TABLE `game_event` CHANGE `occurence` `occurence` bigint(20) unsigned NOT NULL default '5184000' COMMENT 'Delay in minutes between occurences of the event'; +ALTER TABLE `game_event` CHANGE `length` `length` bigint(20) unsigned NOT NULL default '2592000' COMMENT 'Length in minutes of the event'; +UPDATE `game_event` SET `occurence` = `occurence` * 60; +UPDATE `game_event` SET `length` = `length` * 60; \ No newline at end of file diff --git a/sql/updates/0.8/4356_command.sql b/sql/updates/0.8/4356_command.sql new file mode 100644 index 00000000000..57c6a0b4750 --- /dev/null +++ b/sql/updates/0.8/4356_command.sql @@ -0,0 +1 @@ +DELETE FROM `command` WHERE `name` = 'AddSpawn'; diff --git a/sql/updates/0.8/4369_battleground_template.sql b/sql/updates/0.8/4369_battleground_template.sql new file mode 100644 index 00000000000..4271a0ede2c --- /dev/null +++ b/sql/updates/0.8/4369_battleground_template.sql @@ -0,0 +1,2 @@ +DELETE FROM `battleground_template` WHERE `id`='4'; +INSERT INTO `battleground_template` VALUES ('4', '2', '10', '70', '929', '0', '936', '3.14159'); diff --git a/sql/updates/0.8/4376_battleground_template.sql b/sql/updates/0.8/4376_battleground_template.sql new file mode 100644 index 00000000000..46738725ace --- /dev/null +++ b/sql/updates/0.8/4376_battleground_template.sql @@ -0,0 +1,3 @@ +DELETE FROM `battleground_template` WHERE `id` IN ('5', '6'); +INSERT INTO `battleground_template` VALUES ('5', '2', '10', '70', '939', '0', '940', '3.14159'); +INSERT INTO `battleground_template` VALUES ('6', '2', '10', '70', '0', '0', '0', '0'); diff --git a/sql/updates/0.8/4392_battleground_template.sql b/sql/updates/0.8/4392_battleground_template.sql new file mode 100644 index 00000000000..7187f1cd226 --- /dev/null +++ b/sql/updates/0.8/4392_battleground_template.sql @@ -0,0 +1,2 @@ +DELETE FROM `battleground_template` WHERE `id`='8'; +INSERT INTO `battleground_template` VALUES ('8', '2', '10', '70', '1258', '0', '1259', '3.14159'); diff --git a/sql/updates/0.8/4395_spell_chain.sql b/sql/updates/0.8/4395_spell_chain.sql new file mode 100644 index 00000000000..fb5b7285581 --- /dev/null +++ b/sql/updates/0.8/4395_spell_chain.sql @@ -0,0 +1,20 @@ +DELETE FROM `spell_chain` WHERE `spell_id` IN (27149); +INSERT INTO `spell_chain` VALUES +(27149,10293,465,8); + +DELETE FROM `spell_chain` WHERE `spell_id` IN (27150); +INSERT INTO `spell_chain` VALUES +(27150,10301,7294,6); + +DELETE FROM `spell_chain` WHERE `spell_id` IN (27151); +INSERT INTO `spell_chain` VALUES +(27151,19896,19876,4); + +DELETE FROM `spell_chain` WHERE `spell_id` IN (27152); +INSERT INTO `spell_chain` VALUES +(27152,19898,19888,4); + +DELETE FROM `spell_chain` WHERE `spell_id` IN (27153); +INSERT INTO `spell_chain` VALUES +(27153,19900,19891,4); + diff --git a/sql/updates/0.8/4397_command.sql b/sql/updates/0.8/4397_command.sql new file mode 100644 index 00000000000..ad554c52767 --- /dev/null +++ b/sql/updates/0.8/4397_command.sql @@ -0,0 +1,15 @@ +delete from command where name in('whisper2', 'nyi', 'prog', 'run','go', 'object', 'gmon', 'gmoff', 'worldport'); + +update command set name='playemote' where name='emote'; +update command set name='setmodel' where name='displayid'; +update command set name='listgm' where name='gmlist'; + +update command set security=1 where name in ('gogrid', 'goxy') ; +update command set security=2 where name in ('addgo', 'standstate', 'anim', 'morph'); + +delete from command where name in('textemote', 'taxicheat','gm','visible'); +INSERT INTO `command` VALUES +('textemote',3,'Syntax: .text #emoteid\r\n\r\nMake the selected creature to do textemote with an emote of id #emoteid.'), +('taxicheat',1,'Syntax: .taxicheat on/off\r\n\r\nTemporary grant access or remove to all taxi routes for the selected character. If no character is selected, hide or reveal all routes to you.\r\n\r\nVisited taxi nodes sill accessible after removing access.'), +('visible',1,'Syntax: .visible on/off\r\n\r\nOutput current visibility state or make GM visible(on) and invisible(off) for other players.'), +('gm', 1, 'Syntax: .gm on/off\r\n\r\nEnable or Disable GM MODE'); diff --git a/sql/updates/0.8/4401_spell_chain.sql b/sql/updates/0.8/4401_spell_chain.sql new file mode 100644 index 00000000000..c67c5b50d27 --- /dev/null +++ b/sql/updates/0.8/4401_spell_chain.sql @@ -0,0 +1,11 @@ +DELETE FROM `spell_chain` WHERE `spell_id` IN (30283,30413,30414); +INSERT INTO `spell_chain` VALUES +(30283,0,30283,1), +(30413,30283,30283,2), +(30414,30413,30283,3); + +DELETE FROM `spell_chain` WHERE `spell_id` IN (30108,30404,30405); +INSERT INTO `spell_chain` VALUES +(30108,0,30108,1), +(30404,30108,30108,2), +(30405,30404,30108,3); diff --git a/sql/updates/0.8/4403_reserved_name.sql b/sql/updates/0.8/4403_reserved_name.sql new file mode 100644 index 00000000000..a72e9aace27 --- /dev/null +++ b/sql/updates/0.8/4403_reserved_name.sql @@ -0,0 +1,5 @@ +DROP TABLE IF EXISTS `reserved_name`; +CREATE TABLE `reserved_name` ( + `name` VARCHAR(12) NOT NULL DEFAULT '', + PRIMARY KEY (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player Reserved Names'; \ No newline at end of file diff --git a/sql/updates/0.8/4407_character.sql b/sql/updates/0.8/4407_character.sql new file mode 100644 index 00000000000..394740883e9 --- /dev/null +++ b/sql/updates/0.8/4407_character.sql @@ -0,0 +1,3 @@ +ALTER TABLE `character` ADD COLUMN `pending_honor` float NOT NULL default '0'; +ALTER TABLE `character` ADD COLUMN `last_honor_date` int(11) unsigned NOT NULL default '0'; +ALTER TABLE `character` ADD COLUMN `last_kill_date` int(11) unsigned NOT NULL default '0'; \ No newline at end of file diff --git a/sql/updates/0.8/4407_character_kill.sql b/sql/updates/0.8/4407_character_kill.sql new file mode 100644 index 00000000000..b477a8f4a8f --- /dev/null +++ b/sql/updates/0.8/4407_character_kill.sql @@ -0,0 +1,7 @@ +DROP TABLE IF EXISTS `character_kill`; +CREATE TABLE `character_kill` ( + `guid` int(11) NOT NULL default '0', + `victim_guid` int(11) NOT NULL default '0', + `count` tinyint(3) NOT NULL default '0', + PRIMARY KEY (`guid`,`victim_guid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Kills Yesterday'; \ No newline at end of file diff --git a/sql/updates/0.8/4407_command.sql b/sql/updates/0.8/4407_command.sql new file mode 100644 index 00000000000..4bf2dfa18cd --- /dev/null +++ b/sql/updates/0.8/4407_command.sql @@ -0,0 +1,11 @@ +delete from command where name in('honor', 'honor add', 'honor addkill', 'honor flushkills','honor update', 'modify honor'); + +update `command` set `help` = 'Syntax: .modify $parameter $value\r\n\r\nModify the value of various parameters. Use .help modify $parameter to get help on specific parameter usage.\r\n\r\nSupported parameters include hp, mana, rage, energy, money, speed, swim, scale, bit, bwalk, aspeed, faction, spell, tp and honor.' where `name` = 'modify'; + +INSERT INTO `command` ( `name` , `security` , `help` ) VALUES +('honor',2,'Syntax: .honor $command [$value] Various honor related commands. Use .help honor $command to get help on specific parameter usage. Supported parameters include add, addkill, flushkills, update'), +('honor add',2,'Syntax: .honor add $amount\r\n\r\nAdd a certain amount of honor (gained today) to the selected player.'), +('honor addkill',2,'Syntax: .honor addkikll\r\n\r\nAdd the targeted unit as one of your pvp kills today (you only get honor if it\'s a racial leader or a player)'), +('honor flushkills',2,'Syntax: .honor flushkills\r\n\r\nClear today\'s kills from the player limit storage (immediately) and from the DB (on next save) for the selected player.'), +('honor update',2,'Syntax: .honor update\r\n\r\nForce the yesterday\'s honor fields to be updated with today\'s data, which will get reset for the selected player.'), +('modify honor',1,'Syntax: .modify honor $amount\r\n\r\nAdded $amount to the selected player\'s total honor points.'); \ No newline at end of file diff --git a/sql/updates/0.8/4414_spell_chain.sql b/sql/updates/0.8/4414_spell_chain.sql new file mode 100644 index 00000000000..75ab4be0df9 --- /dev/null +++ b/sql/updates/0.8/4414_spell_chain.sql @@ -0,0 +1,312 @@ +DELETE FROM `spell_chain` WHERE `spell_id` IN ( +25202,25203,25208,25210,25212,25213,25217,25218,25221,25222,25225,25231,25233,25234,25235,25236,25241, +25242,25248,25258,25264,25266,25269,25272,25275,25308,25312,25331,25363,25364,25367,25368,25372,25375, +25379,25380,25384,25387,25389,25391,25396,25420,25422,25423,25429,25431,25433,25435,25437,25439,25441, +25442,25446,25448,25449,25450,25454,25457,25464,25467,25470,25479,25485,25489,25500,25505,25508,25509, +25525,25528,25533,25546,25547,25552,25557,25560,25563,25567,25570,25574,25577,25585,25587,25596,26839, +26861,26862,26863,26864,26865,26866,26867,26884,26889,26892,26969,26978,26979,26980,26981,26982,26983, +26984,26985,26986,26987,26988,26989,26990,26992,26993,26994,26995,26996,26997,26998,26999,27001,27002, +27003,27005,27006,27008,27009,27011,27012,27013,27014,27015,27016,27018,27019,27020,27021,27022,27023, +27025,27044,27045,27046,27065,27066,27067,27068,27070,27071,27072,27073,27074,27075,27078,27079,27080, +27082,27085,27086,27087,27088,27090,27124,27125,27126,27128,27130,27131,27132,27133,27134,27135,27136, +27137,27138,27139,27140,27141,27142,27143,27144,27145,27147,27148,27154,27155,27158,27166,27173,27174, +27180,27209,27210,27211,27212,27213,27215,27216,27217,27218,27219,27220,27221,27222,27223,27224,27226, +27228,27229,27230,27238,27250,27259,27260,27263,27264,27265,27266,27282,27283,27441,27448,28172,28176, +28189,28275,29704,29707,29722,30016,30022,30324,30330,30356,30357,30459,30545,30546,30908,30909,30910, +30911,30912,31661,31785,31935,32231,32379,32645,32684,32699,32700,32796,32996,33041,33042,33043,33072, +33405,33717,33776,33933,33938,33944,33946,34411,34412,34413,34861,34863,34864,34865,34866,34914,34916, +34917,36916,37420,38692,38697,38699,38704,38764,38768 +); + +INSERT INTO `spell_chain` VALUES +-- Druid +(26978,25297,5185,12), +(26979,26978,5185,13), +(26980,9858,8936,10), +(26981,25299,774,12), +(26982,26981,774,13), +(26983,9863,740,5), +(26984,9912,5176,9), +(26985,26984,5176,10), +(26986,25298,2912,8), +(26987,9835,8921,11), +(26988,26987,8921,12), +(26989,9853,339,7), +(26990,9885,1126,8), +(26992,9910,467,7), +(26993,9907,770,5), +(26994,20748,20484,6), +(26995,9901,2908,4), +(26996,9881,6807,8), +(26997,9908,779,6), +(26998,9898,99,6), +(26999,22896,22842,4), +(27001,9830,5221,6), +(27002,27001,5221,7), +(27003,9904,1822,5), +(27005,9867,6785,5), +(27006,9827,9005,4), +(27008,9896,1079,7), +(27009,17329,16689,7), +(27011,17392,16857,5), +(27012,17402,16914,4), +(27013,24977,5570,6), +-- Hunter +(27014,14266,2973,9), +(27015,14273,781,4), +(27016,25295,1978,10), +(27018,14280,3034,4), +(27019,14287,3044,9), +(27020,15632,20736,7), +(27021,25294,2643,6), +(27022,14295,1510,4), +(27023,14305,13795,6), +(27025,14317,13813,4), +(27044,25296,13165,8), +(27045,20190,20043,3), +(27046,13544,136,8), +(27065,20904,19434,7), +(27066,20906,19506,4), +(27067,20910,19306,4), +(27068,24133,19386,4), +(36916,14271,1495,5), +-- Mage +(27070,25306,133,13), +(27071,25304,116,12), +(27072,27071,116,13), +(27073,10207,2948,8), +(27074,27073,2948,9), +(27075,25345,5143,9), +(27078,10199,2136,8), +(27079,27078,2136,9), +(27080,10202,1449,7), +(27082,27080,1449,8), +(27085,10187,10,7), +(27086,10216,2120,7), +(27087,10161,120,6), +(27088,10230,122,5), +(27090,37420,5504,9), +(27124,10220,7302,5), +(27125,22783,6117,4), +(27126,10157,1459,6), +(27128,10225,543,6), +(27130,10170,1008,5), +(27131,10193,1463,7), +(27132,18809,11366,9), +(27133,13021,11113,6), +(27134,13033,11426,5), +(31661,0,31661,1), +(32796,28609,6143,6), +(33041,31661,31661,2), +(33042,33041,31661,3), +(33043,33042,31661,4), +(33405,27134,11426,6), +(33717,28612,587,8), +(33933,27133,11113,7), +(33938,27132,11366,10), +(33944,10174,604,6), +(33946,27130,1008,6), +(37420,10140,5504,8), +(38692,27070,133,14), +(38697,27072,116,14), +(38699,27075,5143,10), +(38704,38699,5143,11), +-- Paladin +(27135,25292,635,10), +(27136,27135,635,11), +(27137,19943,19750,7), +(27138,10314,879,7), +(27139,10318,2812,3), +(27140,25291,19740,8), +(27141,25916,25782,3), +(27142,25290,19742,7), +(27143,25918,25894,3), +(27144,19979,19977,4), +(27145,25890,25890,2), +(27147,20729,6940,3), +(27148,27147,6940,4), +(27154,10310,633,4), +(27155,20293,21084,9), +(27158,20308,21082,7), +(27166,20357,20166,4), +(27173,20924,26573,6), +(27174,20930,20473,4), +(27180,24239,24275,4), +(31785,0,31785,1), +(31935,0,31935,1), +(32699,31935,31935,2), +(32700,32699,31935,3), +(33072,27174,20473,5), +(33776,31785,31785,2), +-- Priest +(25210,25314,2060,6), +(25213,25210,2060,7), +(25217,10901,17,11), +(25218,25217,17,12), +(25221,25315,139,11), +(25222,25221,139,12), +(25233,10917,2061,8), +(25235,25233,2061,9), +(25308,25316,596,6), +(25312,27841,14752,5), +(25331,27801,15237,7), +(25363,10934,585,9), +(25364,25363,585,10), +(25367,10894,589,9), +(25368,25367,589,10), +(25372,10947,8092,10), +(25375,25372,8092,11), +(25379,10876,8129,6), +(25380,25379,8129,7), +(25384,15261,14914,9), +(25387,18807,15407,7), +(25389,10938,1243,7), +(25429,10942,586,7), +(25431,10952,588,7), +(25433,10958,976,4), +(25435,20770,2006,6), +(25437,19243,13908,8), +(25441,19275,13896,6), +(25446,19305,10797,8), +(25450,19293,2651,6), +(25467,19280,2944,7), +(25470,19285,9035,7), +(25596,10953,453,4), +(28275,27871,724,4), +(32379,0,32379,1), +(32996,32379,32379,2), +(34861,0,34861,1), +(34863,34861,34861,2), +(34864,34863,34861,3), +(34865,34864,34861,4), +(34866,34865,34861,5), +(34914,0,34914,1), +(34916,34914,34914,2), +(34917,34916,34914,3), +-- Rogue +(26839,11290,703,7), +(26861,11294,1752,9), +(26862,26861,1752,10), +(26863,25300,53,10), +(26864,17348,16511,4), +(26865,31016,2098,10), +(26866,11198,8647,6), +(26867,11275,1943,7), +(26884,26839,703,8), +(26889,1857,1856,3), +(26892,11343,8681,7), +(26969,25347,2835,6), +(27282,26969,2835,7), +(27283,13230,13220,5), +(27441,11269,8676,7), +(27448,25302,1966,6), +(32645,0,32645,1), +(32684,32645,32645,2), +(34411,1329,1329,2), +(34412,34411,1329,3), +(34413,34412,1329,4), +(38764,11286,1776,6), +(38768,1769,1766,5), +-- shaman +(25391,25357,331,11), +(25396,25391,331,12), +(25420,10468,8004,7), +(25422,10623,1064,4), +(25423,25422,1064,5), +(25439,10605,421,5), +(25442,25439,421,6), +(25448,15208,403,11), +(25449,25448,403,12), +(25454,10414,8042,8), +(25457,29228,8050,7), +(25464,10473,8056,5), +(25479,16316,8017,8), +(25485,25479,8017,9), +(25489,16342,8024,7), +(25500,16356,8033,6), +(25505,16362,8232,5), +(25508,10408,8071,7), +(25509,25508,8071,8), +(25525,10428,5730,7), +(25528,25361,8075,6), +(25533,10438,3599,7), +(25546,11315,1535,6), +(25547,25546,1535,7), +(25552,10587,8190,5), +(25557,16387,8227,5), +(25560,10479,8181,4), +(25563,10538,8184,4), +(25567,10463,5394,6), +(25570,10497,5675,5), +(25574,10601,10595,4), +(25577,15112,15107,4), +(25585,10614,8512,4), +(25587,25585,8512,5), +-- warlock +(27209,25307,686,11), +(27210,17923,5676,7), +(27211,17924,6353,3), +(27212,11678,5740,5), +(27213,11684,1949,4), +(27215,25309,348,9), +(27216,25311,172,8), +(27217,11675,1120,5), +(27218,11713,980,7), +(27219,11700,689,7), +(27220,27219,689,8), +(27221,11704,5138,5), +(27222,11689,1454,7), +(27223,17926,6789,4), +(27224,11708,702,7), +(27226,11717,704,5), +(27228,11722,1490,4), +(27229,17937,17862,3), +(27230,11730,6201,6), +(27238,20757,693,6), +(27250,17953,6366,5), +(27259,11695,755,8), +(27260,11735,706,6), +(27263,18871,17877,7), +(27264,18881,18265,5), +(27265,18938,18220,4), +(27266,18932,17962,5), +(28172,17728,2362,4), +(28176,0,28176,1), +(28189,28176,28176,2), +(29722,0,29722,1), +(30459,27210,5676,8), +(30545,27211,6353,4), +(30546,27263,17877,8), +(30908,27221,5138,6), +(30909,27224,702,8), +(30910,603,603,2), +(30911,27264,18265,6), +(30912,27266,17962,6), +(32231,29722,29722,2), +-- warrior +(25202,11556,1160,6), +(25203,25202,1160,7), +(25208,11574,772,8), +(25212,7373,1715,4), +(25225,11597,7386,6), +(25231,20569,845,6), +(25234,20662,5308,6), +(25236,25234,5308,7), +(25241,11605,1464,5), +(25242,25241,1464,6), +(25248,21553,12294,5), +(25258,23925,23922,5), +(25264,11581,6343,7), +(25266,20560,694,6), +(25269,25288,6572,7), +(25272,20617,20252,4), +(25275,25272,20252,5), +(29704,1672,72,4), +(29707,25286,78,10), +(30016,20243,20243,2), +(30022,30016,20243,3), +(30324,29707,78,11), +(30330,25248,12294,6), +(30356,25258,23922,6), +(30357,25269,6572,8); + diff --git a/sql/updates/0.8/4414_spell_proc_event.sql b/sql/updates/0.8/4414_spell_proc_event.sql new file mode 100644 index 00000000000..3109b44c999 --- /dev/null +++ b/sql/updates/0.8/4414_spell_proc_event.sql @@ -0,0 +1,8 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (25441,27009,27124,27280,31896); +INSERT INTO `spell_proc_event` VALUES +(25441,0,0,0,0,0,1048576,0), +(27009,0,0,0,0,0,2,0), +(27124,0,0,0,0,0,2,0), +(27280,0,0,0,0,0,2,0), +(31896,0,0,0,0,0,1,2); + diff --git a/sql/updates/0.8/4417_quest_template.sql b/sql/updates/0.8/4417_quest_template.sql new file mode 100644 index 00000000000..88a6d08200a --- /dev/null +++ b/sql/updates/0.8/4417_quest_template.sql @@ -0,0 +1,4 @@ +ALTER TABLE `quest_template` CHANGE `RequiredRepFaction` `RequiredMinRepFaction` int(10) unsigned NOT NULL default '0'; +ALTER TABLE `quest_template` CHANGE `RequiredRepValue` `RequiredMinRepValue` int(10) NOT NULL default '0'; +ALTER TABLE `quest_template` ADD `RequiredMaxRepFaction` int(10) unsigned NOT NULL default '0' AFTER `RequiredMinRepValue` ; +ALTER TABLE `quest_template` ADD `RequiredMaxRepValue` int(10) NOT NULL default '0' AFTER `RequiredMaxRepFaction` ; diff --git a/sql/updates/0.8/4420_spell_proc_event.sql b/sql/updates/0.8/4420_spell_proc_event.sql new file mode 100644 index 00000000000..c1ce08ceb69 --- /dev/null +++ b/sql/updates/0.8/4420_spell_proc_event.sql @@ -0,0 +1,10 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (35100,35102,35103); +INSERT INTO `spell_proc_event` VALUES +(35100,0,0,0,0,0,524288,0), +(35102,0,0,0,0,0,524288,0), +(35103,0,0,0,0,0,524288,0); + + +DELETE FROM `spell_proc_event` WHERE `entry` IN (33511); +INSERT INTO `spell_proc_event` VALUES +(33511,0,0,0,0,0,131072,0); diff --git a/sql/updates/0.8/4422_command.sql b/sql/updates/0.8/4422_command.sql new file mode 100644 index 00000000000..b2c71c17ca8 --- /dev/null +++ b/sql/updates/0.8/4422_command.sql @@ -0,0 +1 @@ +INSERT INTO `command` (`name`, `security`, `help`) VALUES ('npcwhisper', '1', 'Syntax: .npcwhisper #playerguid #text\r\nMake the selected npc whisper #text to #playerguid.'); diff --git a/sql/updates/0.8/4425_character.sql b/sql/updates/0.8/4425_character.sql new file mode 100644 index 00000000000..515ab151b5c --- /dev/null +++ b/sql/updates/0.8/4425_character.sql @@ -0,0 +1,7 @@ +ALTER TABLE `character` + ADD COLUMN `at_login` int(11) unsigned NOT NULL default '0' AFTER `rename`; + +UPDATE `character` SET `at_login` = 1 WHERE `rename` <> 0; + +ALTER TABLE `character` + DROP COLUMN `rename`; \ No newline at end of file diff --git a/sql/updates/0.8/4425_command.sql b/sql/updates/0.8/4425_command.sql new file mode 100644 index 00000000000..b4f61ccddda --- /dev/null +++ b/sql/updates/0.8/4425_command.sql @@ -0,0 +1,10 @@ +delete from command where name in('goxyz','resetall','reset','reset honor','reset level','reset spells','reset stats','reset talents'); +INSERT INTO `command` VALUES +('goxyz',1,'Syntax: .goxyz #x #y #z [#mapid]\r\n\r\nTeleport player to point with (#x,#y,#z) coordinates at ground(water) level at map #mapid or same map if #mapid not provided.'), +('resetall',3,'Syntax: .resetall spells\r\n\r\nSyntax: .resetall talents\r\n\r\nRequest reset spells or talents at next login each existed character.'), +('reset honor',3,'Syntax:\r\n.reset honor [Playername]\r\n Reset all honor data for targeted character.'), +('reset level',3,'Syntax:\r\n.reset level [Playername]\r\n Reset level to 1 including reset stats and talents. Equipped items with greater level requirement can be lost.'), +('reset spells',3,'Syntax:\r\n.reset spells [Playername]\r\n Removes all non-original spells from spellbook. Playername can be name of offline character.\r\n.'), +('reset stats',3,'Syntax:\r\n.reset stats [Playername]\r\n Resets(recalculate) all stats of the targeted player to their original values at current level.'), +('reset talents',3,'Syntax:\r\n.reset talents [Playername]\r\n Removes all talents of the targeted player. Playername can be name of offline character.'); + diff --git a/sql/updates/0.8/4426_creature_template.sql b/sql/updates/0.8/4426_creature_template.sql new file mode 100644 index 00000000000..b50b5ef6867 --- /dev/null +++ b/sql/updates/0.8/4426_creature_template.sql @@ -0,0 +1 @@ +ALTER TABLE `creature_template` ADD COLUMN dmgschool tinyint(1) not NULL default 0 after maxdmg; diff --git a/sql/updates/0.8/4430_spell_proc_event.sql b/sql/updates/0.8/4430_spell_proc_event.sql new file mode 100644 index 00000000000..368feb1b7b7 --- /dev/null +++ b/sql/updates/0.8/4430_spell_proc_event.sql @@ -0,0 +1,4 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (2565); +INSERT INTO `spell_proc_event` VALUES +(2565,0,0,0,0,0,64,0); + diff --git a/sql/updates/0.8/4432_item_template.sql b/sql/updates/0.8/4432_item_template.sql new file mode 100644 index 00000000000..efb28784fb2 --- /dev/null +++ b/sql/updates/0.8/4432_item_template.sql @@ -0,0 +1,6 @@ +ALTER TABLE `item_template` + ADD COLUMN `spellppmRate_1` float NOT NULL default '0' AFTER `spellcharges_1`, + ADD COLUMN `spellppmRate_2` float NOT NULL default '0' AFTER `spellcharges_2`, + ADD COLUMN `spellppmRate_3` float NOT NULL default '0' AFTER `spellcharges_3`, + ADD COLUMN `spellppmRate_4` float NOT NULL default '0' AFTER `spellcharges_4`, + ADD COLUMN `spellppmRate_5` float NOT NULL default '0' AFTER `spellcharges_5`; diff --git a/sql/updates/0.8/4432_spell_chain.sql b/sql/updates/0.8/4432_spell_chain.sql new file mode 100644 index 00000000000..25b7875a808 --- /dev/null +++ b/sql/updates/0.8/4432_spell_chain.sql @@ -0,0 +1,7 @@ +DELETE FROM `spell_chain` WHERE `spell_id` IN (29801,30030,30033); + +INSERT INTO `spell_chain` VALUES +(29801,0,29801,1), +(30030,29801,29801,2), +(30033,30030,29801,3); + diff --git a/sql/updates/0.8/4432_spell_proc_event.sql b/sql/updates/0.8/4432_spell_proc_event.sql new file mode 100644 index 00000000000..d84e417cfcc --- /dev/null +++ b/sql/updates/0.8/4432_spell_proc_event.sql @@ -0,0 +1,5 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (29801,30030,30033); +INSERT INTO `spell_proc_event` VALUES +(29801,0,0,0,0,0,0,0), +(30030,0,0,0,0,0,0,0), +(30033,0,0,0,0,0,0,0); diff --git a/sql/updates/0.8/4434_spell_proc_event.sql b/sql/updates/0.8/4434_spell_proc_event.sql new file mode 100644 index 00000000000..7d6d1f25b3b --- /dev/null +++ b/sql/updates/0.8/4434_spell_proc_event.sql @@ -0,0 +1,5 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (29801,30030,30033); +INSERT INTO `spell_proc_event` VALUES +(29801,0,0,0,0,0,1,0), +(30030,0,0,0,0,0,1,0), +(30033,0,0,0,0,0,1,0); diff --git a/sql/updates/0.8/4437_character_aura.sql b/sql/updates/0.8/4437_character_aura.sql new file mode 100644 index 00000000000..65dabddc4d9 --- /dev/null +++ b/sql/updates/0.8/4437_character_aura.sql @@ -0,0 +1,6 @@ +ALTER TABLE `character_aura` + ADD `maxduration` int(11) NOT NULL default '0' AFTER `amount`, + ADD `remaincharges` int(11) NOT NULL default '0' AFTER `remaintime`; + +UPDATE `character_aura` + SET `maxduration` = `remaintime`, `remaincharges` = -1; \ No newline at end of file diff --git a/sql/updates/0.8/4437_pet_aura.sql b/sql/updates/0.8/4437_pet_aura.sql new file mode 100644 index 00000000000..885adc90266 --- /dev/null +++ b/sql/updates/0.8/4437_pet_aura.sql @@ -0,0 +1,6 @@ +ALTER TABLE `pet_aura` + ADD `maxduration` int(11) NOT NULL default '0' AFTER `amount`, + ADD `remaincharges` int(11) NOT NULL default '0' AFTER `remaintime`; + +UPDATE `pet_aura` + SET `maxduration` = `remaintime`, `remaincharges` = -1; diff --git a/sql/updates/0.8/4439_spell_proc_event.sql b/sql/updates/0.8/4439_spell_proc_event.sql new file mode 100644 index 00000000000..00dde4fc8f9 --- /dev/null +++ b/sql/updates/0.8/4439_spell_proc_event.sql @@ -0,0 +1,5 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (30293,30295,30296); +INSERT INTO `spell_proc_event` VALUES +(30293, 0, 0, 0, 5, 824633721729, 131072, 0), +(30295, 0, 0, 0, 5, 824633721729, 131072, 0), +(30296, 0, 0, 0, 5, 824633721729, 131072, 0); diff --git a/sql/updates/0.8/4446_creature_template.sql b/sql/updates/0.8/4446_creature_template.sql new file mode 100644 index 00000000000..ac35882e79e --- /dev/null +++ b/sql/updates/0.8/4446_creature_template.sql @@ -0,0 +1 @@ +ALTER TABLE `creature_template` DROP COLUMN `size`; diff --git a/sql/updates/0.8/4464_instance.sql b/sql/updates/0.8/4464_instance.sql new file mode 100644 index 00000000000..6d2add41205 --- /dev/null +++ b/sql/updates/0.8/4464_instance.sql @@ -0,0 +1 @@ +ALTER TABLE `instance` ADD `data` LONGTEXT; \ No newline at end of file diff --git a/sql/updates/0.8/4464_instance_template.sql b/sql/updates/0.8/4464_instance_template.sql new file mode 100644 index 00000000000..5b5f370b0df --- /dev/null +++ b/sql/updates/0.8/4464_instance_template.sql @@ -0,0 +1 @@ +ALTER TABLE `instance_template` ADD `script` varchar(255) NOT NULL default ''; \ No newline at end of file diff --git a/sql/updates/0.8/4470_command.sql b/sql/updates/0.8/4470_command.sql new file mode 100644 index 00000000000..bbd104b7363 --- /dev/null +++ b/sql/updates/0.8/4470_command.sql @@ -0,0 +1,4 @@ +delete from command where name in('movegens'); +INSERT INTO `command` VALUES +('movegens',3,'Syntax: .movegens\r\n Show movement generators stack for selected creature or player.'); + diff --git a/sql/updates/0.8/4480_spell_affect.sql b/sql/updates/0.8/4480_spell_affect.sql new file mode 100644 index 00000000000..74fec20b906 --- /dev/null +++ b/sql/updates/0.8/4480_spell_affect.sql @@ -0,0 +1,9 @@ +-- Improved Fire Totems 1-2 Rangs +DELETE FROM `spell_affect` WHERE `entry` IN (16544,16086); +INSERT INTO `spell_affect` VALUES +(16544,0,0,0,0,0,0,32,0), +(16544,1,0,0,0,0,0,32,0), +(16544,2,0,0,0,0,0,1073741824,0), +(16086,0,0,0,0,0,0,32,0), +(16086,1,0,0,0,0,0,32,0), +(16086,2,0,0,0,0,0,1073741824,0); diff --git a/sql/updates/0.8/4481_spell_affect.sql b/sql/updates/0.8/4481_spell_affect.sql new file mode 100644 index 00000000000..cd1535c8e3c --- /dev/null +++ b/sql/updates/0.8/4481_spell_affect.sql @@ -0,0 +1,4 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (16544,16086) AND `effectId`=2; +INSERT INTO `spell_affect` VALUES +(16544,2,0,0,0,0,0,4,0), +(16086,2,0,0,0,0,0,4,0); diff --git a/sql/updates/0.8/4482_playercreateinfo.sql b/sql/updates/0.8/4482_playercreateinfo.sql new file mode 100644 index 00000000000..bd7c02fb555 --- /dev/null +++ b/sql/updates/0.8/4482_playercreateinfo.sql @@ -0,0 +1,11 @@ +UPDATE playercreateinfo_spell SET Spell = '21084' WHERE Spell = '20154'; +UPDATE playercreateinfo_action SET action = '21084' WHERE action = '20154'; +DELETE FROM `character_spell` WHERE spell='20154'; + +-- re-add all default spells if not have with from spell list +INSERT IGNORE INTO `character_spell` +SELECT `character`.`guid`,`playercreateinfo_spell`.`spell` AS `spell`, '65535' AS `slot`,`playercreateinfo_spell`.`Active` AS `active` +FROM `character`,`playercreateinfo_spell` +WHERE `character`.`class`=`playercreateinfo_spell`.`class` AND `character`.`race`=`playercreateinfo_spell`.`race`; + +UPDATE character_action SET action = '21084' WHERE action = '20154' AND `type` = 0; diff --git a/sql/updates/0.8/4482_spell_proc_event.sql b/sql/updates/0.8/4482_spell_proc_event.sql new file mode 100644 index 00000000000..bf1371d1546 --- /dev/null +++ b/sql/updates/0.8/4482_spell_proc_event.sql @@ -0,0 +1,7 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (12284,12701,12702,12703,12704); +INSERT INTO `spell_proc_event` VALUES +(12284,0,0,0,0,0,1,0.33252), +(12701,0,0,0,0,0,1,0.66504), +(12702,0,0,0,0,0,1,0.99756), +(12703,0,0,0,0,0,1,1.33008), +(12704,0,0,0,0,0,1,1.66260); diff --git a/sql/updates/0.8/4488_db_version.sql b/sql/updates/0.8/4488_db_version.sql new file mode 100644 index 00000000000..704942e97ee --- /dev/null +++ b/sql/updates/0.8/4488_db_version.sql @@ -0,0 +1,6 @@ +DROP TABLE IF EXISTS `db_version`; +CREATE TABLE `db_version` ( + `version` varchar(120) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; + +INSERT INTO `db_version` VALUES ( 'unknown world database.' ); diff --git a/sql/updates/0.8/4491_spell_affect.sql b/sql/updates/0.8/4491_spell_affect.sql new file mode 100644 index 00000000000..a6d530930bf --- /dev/null +++ b/sql/updates/0.8/4491_spell_affect.sql @@ -0,0 +1,9 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (28176, 28189); +INSERT INTO `spell_affect` VALUES +(28176,1,0,0,0,0,0,4295491592,0), +(28189,1,0,0,0,0,0,4295491592,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (11252, 12605); +INSERT INTO `spell_affect` VALUES +(11252,0,0,0,0,0,0,32768,0), +(12605,0,0,0,0,0,0,32768,0); diff --git a/sql/updates/0.8/4496_spell_script_target.sql b/sql/updates/0.8/4496_spell_script_target.sql new file mode 100644 index 00000000000..a759ac01169 --- /dev/null +++ b/sql/updates/0.8/4496_spell_script_target.sql @@ -0,0 +1,6 @@ +DROP TABLE IF EXISTS `spell_script_target`; +CREATE TABLE `spell_script_target` ( + `entry` int(6) unsigned NOT NULL, + `type` int(8) unsigned default '0', + `targetEntry` int(11) default '0' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='Spell System'; diff --git a/sql/updates/0.8/4498_spell_proc_event.sql b/sql/updates/0.8/4498_spell_proc_event.sql new file mode 100644 index 00000000000..fa3fbada1e4 --- /dev/null +++ b/sql/updates/0.8/4498_spell_proc_event.sql @@ -0,0 +1,8 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (40971); +INSERT INTO `spell_proc_event` VALUES +(40971,0,0,0,0,0,134217728,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (38427,40407); +INSERT INTO `spell_proc_event` VALUES +(38427,0,0,0,0,0,1,0), +(40407,0,0,0,0,0,1026,6); \ No newline at end of file diff --git a/sql/updates/0.8/4499_spell_script_target.sql b/sql/updates/0.8/4499_spell_script_target.sql new file mode 100644 index 00000000000..35926d83da9 --- /dev/null +++ b/sql/updates/0.8/4499_spell_script_target.sql @@ -0,0 +1,3 @@ +ALTER TABLE `spell_script_target` + CHANGE COLUMN `targetEntry` `targetEntry` int(11) unsigned default '0', + ADD UNIQUE KEY `entry_type_target` (`entry`,`type`,`targetEntry`); diff --git a/sql/updates/0.8/4501.sql b/sql/updates/0.8/4501.sql new file mode 100644 index 00000000000..e8e9cc73312 --- /dev/null +++ b/sql/updates/0.8/4501.sql @@ -0,0 +1,112 @@ +-- Add definitly a very usefull index to this creature table +-- If this sql file fails because the index already exists, comment the following line +ALTER TABLE `creature` ADD INDEX `index_id` (id); + +-- Add suport to creature table for equipment and model overwritting +ALTER TABLE `creature` + ADD COLUMN `equipment_id` int(11) NOT NULL default '0' AFTER `map`, + ADD COLUMN `modelid` int(11) unsigned default '0' AFTER `map`; + +-- Creation of creature_model_info table +DROP TABLE IF EXISTS `creature_model_info`; +CREATE TABLE `creature_model_info` ( + `modelid` int(11) unsigned NOT NULL default '0', + `bounding_radius` float NOT NULL default '0', + `combat_reach` float NOT NULL default '0', + `gender` tinyint(2) unsigned NOT NULL default '2', + `modelid_other_gender` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`modelid`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Creature System (Model related info)'; + +-- Correct possible db problems +UPDATE `creature_template` SET `bounding_radius`=0 WHERE `bounding_radius` IS NULL; +UPDATE `creature_template` SET `combat_reach`=0 WHERE `combat_reach` IS NULL; +UPDATE `creature_template` SET `modelid_m`=0 WHERE `modelid_m` IS NULL; +UPDATE `creature_template` SET `modelid_f`=0 WHERE `modelid_f` IS NULL; + +-- All models defined in creature_template are used to build the table +INSERT IGNORE INTO `creature_model_info` (`modelid`) SELECT DISTINCT `modelid_m` FROM `creature_template`; +INSERT IGNORE INTO `creature_model_info` (`modelid`) SELECT DISTINCT `modelid_f` FROM `creature_template`; + +-- Copy the data from creature_template to creature_model_info +UPDATE `creature_model_info`,`creature_template` SET + `creature_model_info`.`bounding_radius`=`creature_template`.`bounding_radius`, + `creature_model_info`.`combat_reach`=`creature_template`.`combat_reach`, + `creature_model_info`.`modelid_other_gender`=`creature_template`.`modelid_f` + WHERE `creature_model_info`.`modelid`=`creature_template`.`modelid_m`; + +UPDATE `creature_model_info`,`creature_template` SET + `creature_model_info`.`bounding_radius`=`creature_template`.`bounding_radius`, + `creature_model_info`.`combat_reach`=`creature_template`.`combat_reach`, + `creature_model_info`.`modelid_other_gender`=`creature_template`.`modelid_m` + WHERE `creature_model_info`.`modelid`=`creature_template`.`modelid_f`; + +-- Some changes in fields of creature_template +ALTER TABLE `creature_template` + CHANGE `modelid_m` `modelid_A` int(11) unsigned NOT NULL default '0', + CHANGE `modelid_f` `modelid_H` int(11) unsigned NOT NULL default '0', + ADD COLUMN `faction_H` int(4) unsigned NOT NULL default '0' AFTER `faction`, + ADD COLUMN `equipment_id` int(11) unsigned NOT NULL default '0' AFTER `RacialLeader`, + ADD COLUMN `RegenHealth` tinyint(1) unsigned NOT NULL default '1' AFTER `RacialLeader`, + DROP COLUMN `bounding_radius`, + DROP COLUMN `combat_reach`, + -- This index is temporary and enable the population of creature_equip_template to be fast + ADD INDEX `idx_tmp` (`equipmodel1`,`equipmodel2`,`equipmodel3`,`equipinfo1`,`equipinfo2`,`equipinfo3`,`equipslot1`,`equipslot2`,`equipslot3`); + +ALTER TABLE `creature_template` + CHANGE `faction` `faction_A` int(4) unsigned NOT NULL default '0'; + +-- Create table creature_equip_template with temporary auto-increment key +DROP TABLE IF EXISTS `creature_equip_template`; +CREATE TABLE `creature_equip_template` ( + `entry` int(11) unsigned NOT NULL auto_increment COMMENT 'Unique entry', + `equipmodel1` int(11) unsigned NOT NULL default '0', + `equipmodel2` int(11) unsigned NOT NULL default '0', + `equipmodel3` int(11) unsigned NOT NULL default '0', + `equipinfo1` int(11) unsigned NOT NULL default '0', + `equipinfo2` int(11) unsigned NOT NULL default '0', + `equipinfo3` int(11) unsigned NOT NULL default '0', + `equipslot1` int(11) NOT NULL default '0', + `equipslot2` int(11) NOT NULL default '0', + `equipslot3` int(11) NOT NULL default '0', + PRIMARY KEY (`entry`) +) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='Creature System (Equipment)'; + +-- Fill the creature_equip_template table with values from creature_template +INSERT INTO `creature_equip_template` (`equipmodel1`,`equipmodel2`,`equipmodel3`,`equipinfo1`,`equipinfo2`,`equipinfo3`,`equipslot1`,`equipslot2`,`equipslot3`) + (SELECT DISTINCT `equipmodel1`,`equipmodel2`,`equipmodel3`,`equipinfo1`,`equipinfo2`,`equipinfo3`,`equipslot1`,`equipslot2`,`equipslot3` FROM `creature_template` WHERE `equipmodel1`<>0 OR `equipmodel2`<>0 OR `equipmodel3`<>0); + +-- Then add to creature_template the id generated for equipements +UPDATE `creature_template`,`creature_equip_template` SET + `creature_template`.`equipment_id`=`creature_equip_template`.`entry` + WHERE `creature_template`.`equipmodel1`=`creature_equip_template`.`equipmodel1` AND + `creature_template`.`equipmodel2`=`creature_equip_template`.`equipmodel2` AND + `creature_template`.`equipmodel3`=`creature_equip_template`.`equipmodel3` AND + `creature_template`.`equipinfo1`=`creature_equip_template`.`equipinfo1` AND + `creature_template`.`equipinfo2`=`creature_equip_template`.`equipinfo2` AND + `creature_template`.`equipinfo3`=`creature_equip_template`.`equipinfo3` AND + `creature_template`.`equipslot1`=`creature_equip_template`.`equipslot1` AND + `creature_template`.`equipslot2`=`creature_equip_template`.`equipslot2` AND + `creature_template`.`equipslot3`=`creature_equip_template`.`equipslot3`; + +-- Remove all equipment fields from creature_template, this will remove the temporary index +ALTER TABLE `creature_template` + DROP COLUMN `equipmodel1`, + DROP COLUMN `equipmodel2`, + DROP COLUMN `equipmodel3`, + DROP COLUMN `equipinfo1`, + DROP COLUMN `equipinfo2`, + DROP COLUMN `equipinfo3`, + DROP COLUMN `equipslot1`, + DROP COLUMN `equipslot2`, + DROP COLUMN `equipslot3`; + +-- Make all modelid and faction fields filled +UPDATE `creature_template` SET `modelid_A`=`modelid_H` WHERE `modelid_A`=0 AND `modelid_H`<>0; +UPDATE `creature_template` SET `modelid_H`=`modelid_A` WHERE `modelid_H`=0 AND `modelid_A`<>0; +UPDATE `creature_template` SET `faction_A`=`faction_H` WHERE `faction_A`=0 AND `faction_H`<>0; +UPDATE `creature_template` SET `faction_H`=`faction_A` WHERE `faction_H`=0 AND `faction_A`<>0; + +-- Finaly remove the no more necessary auto-increment from creature_equip_template +ALTER TABLE `creature_equip_template` + CHANGE `entry` `entry` int(11) unsigned NOT NULL default '0' COMMENT 'Unique entry'; diff --git a/sql/updates/0.8/4503_spell_chain.sql b/sql/updates/0.8/4503_spell_chain.sql new file mode 100644 index 00000000000..8dd5cb49100 --- /dev/null +++ b/sql/updates/0.8/4503_spell_chain.sql @@ -0,0 +1,4 @@ +DELETE FROM `spell_chain` WHERE `spell_id` IN (31895); + +INSERT INTO `spell_chain` VALUES +(31895,20164,20164,2); diff --git a/sql/updates/0.8/4503_spell_proc_event.sql b/sql/updates/0.8/4503_spell_proc_event.sql new file mode 100644 index 00000000000..bdd37b94541 --- /dev/null +++ b/sql/updates/0.8/4503_spell_proc_event.sql @@ -0,0 +1,49 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (5728,6397,6398,6399,10425,10426,25513); +INSERT INTO `spell_proc_event` VALUES +(5728,0,0,0,0,0,1049602,0), +(6397,0,0,0,0,0,1049602,0), +(6398,0,0,0,0,0,1049602,0), +(6399,0,0,0,0,0,1049602,0), +(10425,0,0,0,0,0,1049602,0), +(10426,0,0,0,0,0,1049602,0), +(25513,0,0,0,0,0,1049602,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (31895); +INSERT INTO `spell_proc_event` VALUES +(31895,0,0,0,0,0,1,2); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (37705); +INSERT INTO `spell_proc_event` VALUES +(37705,0,0,0,0,0,134217728,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (37247); +INSERT INTO `spell_proc_event` VALUES +(37247,8,0,0,0,0,16384,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (40444); +INSERT INTO `spell_proc_event` VALUES +(40444,0,0,0,0,0,64,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (40482); +INSERT INTO `spell_proc_event` VALUES +(40482,0,0,0,0,0,65536,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (33297); +INSERT INTO `spell_proc_event` VALUES +(33297,0,0,0,0,0,131072,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (33953); +INSERT INTO `spell_proc_event` VALUES +(33953,0,0,0,0,0,134217728,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (38350); +INSERT INTO `spell_proc_event` VALUES +(38350,0,0,0,0,0,4198400,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (33510); +INSERT INTO `spell_proc_event` VALUES +(33510,0,0,0,0,0,524289,5); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (32215); +INSERT INTO `spell_proc_event` VALUES +(32215,0,0,0,0,0,4,0); diff --git a/sql/updates/0.8/4504_spell_affect.sql b/sql/updates/0.8/4504_spell_affect.sql new file mode 100644 index 00000000000..a9eeb98c86b --- /dev/null +++ b/sql/updates/0.8/4504_spell_affect.sql @@ -0,0 +1,24 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (20216) AND `effectId`=0; +INSERT INTO `spell_affect` VALUES +(20216,0,0,0,0,0,0,3223322624,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (31842) AND `effectId`=0; +INSERT INTO `spell_affect` VALUES +(31842,0,0,126,0,0,0,0,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (31834) AND `effectId`=0; +INSERT INTO `spell_affect` VALUES +(31834,0,0,0,0,0,0,2147483648,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (20224,20225,20330,20331,20332) AND `effectId`=0; +INSERT INTO `spell_affect` VALUES +(20224,0,0,0,0,0,0,134218752,0), +(20225,0,0,0,0,0,0,134218752,0), +(20330,0,0,0,0,0,0,134218752,0), +(20331,0,0,0,0,0,0,134218752,0), +(20332,0,0,0,0,0,0,134218752,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (20244,20245) AND `effectId`=0; +INSERT INTO `spell_affect` VALUES +(20244,0,0,0,0,0,0,65536,0), +(20245,0,0,0,0,0,0,65536,0); diff --git a/sql/updates/0.8/4504_spell_proc_event.sql b/sql/updates/0.8/4504_spell_proc_event.sql new file mode 100644 index 00000000000..d329b5b5cde --- /dev/null +++ b/sql/updates/0.8/4504_spell_proc_event.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (31801); +INSERT INTO `spell_proc_event` VALUES +(31801,0,0,0,0,0,1,20); diff --git a/sql/updates/0.8/4506_spell_learn_spell.sql b/sql/updates/0.8/4506_spell_learn_spell.sql new file mode 100644 index 00000000000..96c0c7226ba --- /dev/null +++ b/sql/updates/0.8/4506_spell_learn_spell.sql @@ -0,0 +1,6 @@ +INSERT IGNORE INTO `spell_learn_spell` VALUES +(71,355,0), +(71,7386,0), +(264,3018,0), +(266,3018,0), +(5011,3018,0); diff --git a/sql/updates/0.8/4507_quest_template.sql b/sql/updates/0.8/4507_quest_template.sql new file mode 100644 index 00000000000..2a39ae65bde --- /dev/null +++ b/sql/updates/0.8/4507_quest_template.sql @@ -0,0 +1,2 @@ +ALTER TABLE `quest_template` + CHANGE `ExclusiveGroup` `ExclusiveGroup` int(11) NOT NULL default '0'; diff --git a/sql/updates/0.8/4510_spell_proc_event.sql b/sql/updates/0.8/4510_spell_proc_event.sql new file mode 100644 index 00000000000..5d676b9b1ec --- /dev/null +++ b/sql/updates/0.8/4510_spell_proc_event.sql @@ -0,0 +1,13 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (32837); +INSERT INTO `spell_proc_event` VALUES +(32837,0,0,0,0,0,16384,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (588,7128,602,1006,10951,10952,25431); +INSERT INTO `spell_proc_event` VALUES +(588,0,0,0,0,0,1026,0), +(602,0,0,0,0,0,1026,0), +(1006,0,0,0,0,0,1026,0), +(7128,0,0,0,0,0,1026,0), +(10951,0,0,0,0,0,1026,0), +(10952,0,0,0,0,0,1026,0), +(25431,0,0,0,0,0,1026,0); diff --git a/sql/updates/0.8/4513_spell_proc_event.sql b/sql/updates/0.8/4513_spell_proc_event.sql new file mode 100644 index 00000000000..2e3569ce833 --- /dev/null +++ b/sql/updates/0.8/4513_spell_proc_event.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (30482); +INSERT INTO `spell_proc_event` VALUES +(30482,0,0,0,0,0,2,0); \ No newline at end of file diff --git a/sql/updates/0.8/4517_spell_affect.sql b/sql/updates/0.8/4517_spell_affect.sql new file mode 100644 index 00000000000..4f4ea253c22 --- /dev/null +++ b/sql/updates/0.8/4517_spell_affect.sql @@ -0,0 +1,6 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (41021,41026); +INSERT INTO `spell_affect` VALUES +(41021,0,0,0,0,0,0,274877906944,0), +(41021,1,0,0,0,0,0,274877906944,0), +(41026,0,0,0,0,0,0,274877906944,0), +(41026,1,0,0,0,0,0,274877906944,0); diff --git a/sql/updates/0.8/4524_spell_proc_event.sql b/sql/updates/0.8/4524_spell_proc_event.sql new file mode 100644 index 00000000000..013a117d186 --- /dev/null +++ b/sql/updates/0.8/4524_spell_proc_event.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (32642); +INSERT INTO `spell_proc_event` VALUES +(32642,0,0,0,0,0,64,0); diff --git a/sql/updates/0.8/4537_player_levelstats.sql b/sql/updates/0.8/4537_player_levelstats.sql new file mode 100644 index 00000000000..cf5030dd598 --- /dev/null +++ b/sql/updates/0.8/4537_player_levelstats.sql @@ -0,0 +1,3668 @@ +-- +-- Table structure for table `player_levelstats` +-- + +DROP TABLE IF EXISTS `player_levelstats`; +CREATE TABLE `player_levelstats` ( + `race` tinyint(3) unsigned NOT NULL, + `class` tinyint(3) unsigned NOT NULL, + `level` tinyint(3) unsigned NOT NULL, + `hp` smallint(5) unsigned NOT NULL, + `mana` smallint(5) unsigned NOT NULL, + `str` tinyint(3) unsigned NOT NULL, + `agi` tinyint(3) unsigned NOT NULL, + `sta` tinyint(3) unsigned NOT NULL, + `int` tinyint(3) unsigned NOT NULL, + `spi` tinyint(3) unsigned NOT NULL, + PRIMARY KEY (`race`,`class`,`level`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 PACK_KEYS=0 COMMENT='Stores levels stats.'; + +-- +-- Dumping data for table `player_levelstats` +-- + +LOCK TABLES `player_levelstats` WRITE; +/*!40000 ALTER TABLE `player_levelstats` DISABLE KEYS */; +INSERT INTO `player_levelstats` VALUES +(1,1,1,60,0,23,20,22,20,20), +(1,1,2,79,0,24,21,23,20,20), +(1,1,3,98,0,26,22,24,20,21), +(1,1,4,117,0,27,22,26,20,21), +(1,1,5,136,0,28,23,27,20,21), +(1,1,6,155,0,30,24,28,20,21), +(1,1,7,174,0,31,25,29,21,22), +(1,1,8,193,0,32,26,30,21,22), +(1,1,9,212,0,34,26,32,21,22), +(1,1,10,231,0,35,27,33,21,23), +(1,1,11,250,0,36,28,34,21,23), +(1,1,12,269,0,38,29,35,21,23), +(1,1,13,288,0,39,30,37,21,24), +(1,1,14,308,0,41,31,38,21,24), +(1,1,15,329,0,42,32,39,21,24), +(1,1,16,351,0,44,33,41,21,25), +(1,1,17,374,0,45,34,42,22,25), +(1,1,18,398,0,47,34,43,22,25), +(1,1,19,423,0,48,35,45,22,26), +(1,1,20,449,0,50,36,46,22,26), +(1,1,21,476,0,51,37,48,22,26), +(1,1,22,504,0,53,38,49,22,27), +(1,1,23,533,0,54,39,51,22,27), +(1,1,24,563,0,56,40,52,23,28), +(1,1,25,594,0,58,41,53,23,28), +(1,1,26,626,0,59,42,55,23,28), +(1,1,27,659,0,61,43,56,23,29), +(1,1,28,693,0,63,44,58,23,29), +(1,1,29,728,0,64,45,59,23,30), +(1,1,30,764,0,66,46,61,24,30), +(1,1,31,801,0,68,47,62,24,30), +(1,1,32,839,0,69,48,64,24,31), +(1,1,33,878,0,71,50,66,24,31), +(1,1,34,918,0,73,51,67,24,32), +(1,1,35,959,0,74,52,69,24,32), +(1,1,36,1001,0,76,53,70,25,33), +(1,1,37,1045,0,78,54,72,25,33), +(1,1,38,1091,0,80,55,74,25,34), +(1,1,39,1139,0,82,56,75,25,34), +(1,1,40,1189,0,83,57,77,25,35), +(1,1,41,1241,0,85,58,79,26,35), +(1,1,42,1295,0,87,60,80,26,35), +(1,1,43,1351,0,89,61,82,26,36), +(1,1,44,1409,0,91,62,84,26,36), +(1,1,45,1469,0,93,63,85,26,37), +(1,1,46,1531,0,95,64,87,27,37), +(1,1,47,1595,0,97,66,89,27,38), +(1,1,48,1661,0,99,67,91,27,38), +(1,1,49,1729,0,101,68,93,27,39), +(1,1,50,1799,0,103,69,94,28,40), +(1,1,51,1871,0,105,71,96,28,40), +(1,1,52,1945,0,107,72,98,28,41), +(1,1,53,2021,0,109,73,100,28,41), +(1,1,54,2099,0,111,74,102,29,42), +(1,1,55,2179,0,113,76,103,29,42), +(1,1,56,2261,0,115,77,105,29,43), +(1,1,57,2345,0,117,78,107,29,43), +(1,1,58,2431,0,119,79,109,30,44), +(1,1,59,2519,0,121,81,111,30,44), +(1,1,60,2609,0,123,82,113,30,45), +(1,1,61,2842,0,125,83,115,30,46), +(1,1,62,3089,0,127,85,117,31,46), +(1,1,63,3350,0,129,86,119,31,47), +(1,1,64,3625,0,132,88,121,31,47), +(1,1,65,3915,0,134,89,123,32,48), +(1,1,66,4220,0,136,90,125,32,49), +(1,1,67,4540,0,138,92,127,32,49), +(1,1,68,4876,0,140,93,129,32,50), +(1,1,69,5228,0,143,95,131,33,50), +(1,1,70,5596,0,145,96,133,33,51), +(1,2,1,58,80,22,20,22,20,21), +(1,2,2,76,99,23,21,23,21,22), +(1,2,3,94,119,24,21,24,21,22), +(1,2,4,112,140,25,22,25,22,23), +(1,2,5,130,162,26,22,26,23,24), +(1,2,6,148,185,28,23,27,23,25), +(1,2,7,166,209,29,24,28,24,25), +(1,2,8,184,234,30,24,29,25,26), +(1,2,9,202,260,31,25,30,25,27), +(1,2,10,220,287,32,25,32,26,27), +(1,2,11,238,315,33,26,33,27,28), +(1,2,12,256,344,35,27,34,27,29), +(1,2,13,274,374,36,27,35,28,30), +(1,2,14,292,405,37,28,36,29,31), +(1,2,15,311,437,38,29,37,30,31), +(1,2,16,331,470,40,29,38,30,32), +(1,2,17,352,504,41,30,40,31,33), +(1,2,18,374,539,42,31,41,32,34), +(1,2,19,397,575,43,31,42,33,35), +(1,2,20,421,612,45,32,43,33,35), +(1,2,21,446,650,46,33,45,34,36), +(1,2,22,472,689,47,33,46,35,37), +(1,2,23,499,729,49,34,47,36,38), +(1,2,24,527,770,50,35,48,37,39), +(1,2,25,556,812,51,36,50,37,40), +(1,2,26,586,854,53,36,51,38,41), +(1,2,27,617,896,54,37,52,39,42), +(1,2,28,649,938,56,38,54,40,43), +(1,2,29,682,980,57,39,55,41,43), +(1,2,30,716,1022,58,39,56,42,44), +(1,2,31,751,1064,60,40,58,43,45), +(1,2,32,787,1106,61,41,59,43,46), +(1,2,33,824,1148,63,42,60,44,47), +(1,2,34,862,1190,64,43,62,45,48), +(1,2,35,901,1232,66,44,63,46,49), +(1,2,36,941,1274,67,44,65,47,50), +(1,2,37,982,1316,69,45,66,48,51), +(1,2,38,1024,1358,70,46,67,49,52), +(1,2,39,1067,1400,72,47,69,50,53), +(1,2,40,1111,1442,73,48,70,51,54), +(1,2,41,1156,1484,75,49,72,52,55), +(1,2,42,1202,1526,77,49,73,53,56), +(1,2,43,1249,1568,78,50,75,54,57), +(1,2,44,1297,1610,80,51,76,55,58), +(1,2,45,1346,1652,81,52,78,56,59), +(1,2,46,1396,1694,83,53,79,57,61), +(1,2,47,1447,1736,85,54,81,58,62), +(1,2,48,1499,1778,86,55,83,59,63), +(1,2,49,1552,1820,88,56,84,60,64), +(1,2,50,1606,1862,90,57,86,61,65), +(1,2,51,1661,1904,91,58,87,62,66), +(1,2,52,1717,1946,93,59,89,63,67), +(1,2,53,1774,1988,95,60,91,64,68), +(1,2,54,1832,2030,97,61,92,65,69), +(1,2,55,1891,2072,98,61,94,66,71), +(1,2,56,1951,2114,100,62,95,67,72), +(1,2,57,2012,2156,102,63,97,68,73), +(1,2,58,2074,2198,104,64,99,69,74), +(1,2,59,2137,2240,105,65,101,70,75), +(1,2,60,2201,2282,107,66,102,71,77), +(1,2,61,2381,2441,109,67,104,73,78), +(1,2,62,2569,2600,111,69,106,74,79), +(1,2,63,2765,2774,113,70,107,75,80), +(1,2,64,2970,2933,115,71,109,76,81), +(1,2,65,3184,3092,116,72,111,77,83), +(1,2,66,3407,3266,118,73,113,78,84), +(1,2,67,3640,3425,120,74,115,79,85), +(1,2,68,3883,3584,122,75,116,81,86), +(1,2,69,4136,3758,124,76,118,82,88), +(1,2,70,4399,3917,126,77,120,83,89), +(1,4,1,55,0,21,23,21,20,20), +(1,4,2,72,0,22,24,22,20,20), +(1,4,3,89,0,23,26,22,20,21), +(1,4,4,106,0,23,27,23,20,21), +(1,4,5,123,0,24,29,24,21,21), +(1,4,6,140,0,25,30,25,21,22), +(1,4,7,157,0,26,32,25,21,22), +(1,4,8,174,0,26,33,26,21,23), +(1,4,9,191,0,27,35,27,21,23), +(1,4,10,208,0,28,36,27,21,23), +(1,4,11,225,0,29,38,28,22,24), +(1,4,12,242,0,30,39,29,22,24), +(1,4,13,259,0,31,41,30,22,25), +(1,4,14,276,0,31,43,31,22,25), +(1,4,15,293,0,32,44,31,22,25), +(1,4,16,311,0,33,46,32,23,26), +(1,4,17,330,0,34,48,33,23,26), +(1,4,18,350,0,35,49,34,23,27), +(1,4,19,371,0,36,51,35,23,27), +(1,4,20,393,0,37,53,35,23,28), +(1,4,21,416,0,38,54,36,24,28), +(1,4,22,440,0,39,56,37,24,29), +(1,4,23,465,0,40,58,38,24,29), +(1,4,24,491,0,41,60,39,24,30), +(1,4,25,518,0,42,61,40,25,30), +(1,4,26,546,0,43,63,41,25,31), +(1,4,27,575,0,44,65,42,25,31), +(1,4,28,605,0,45,67,43,25,32), +(1,4,29,636,0,46,69,43,25,32), +(1,4,30,668,0,47,71,44,26,33), +(1,4,31,701,0,48,72,45,26,33), +(1,4,32,735,0,49,74,46,26,34), +(1,4,33,770,0,50,76,47,27,34), +(1,4,34,806,0,51,78,48,27,35), +(1,4,35,843,0,52,80,49,27,35), +(1,4,36,881,0,53,82,50,27,36), +(1,4,37,920,0,54,84,51,28,36), +(1,4,38,960,0,55,86,52,28,37), +(1,4,39,1001,0,56,88,53,28,38), +(1,4,40,1043,0,57,90,54,28,38), +(1,4,41,1086,0,58,92,55,29,39), +(1,4,42,1130,0,60,94,56,29,39), +(1,4,43,1175,0,61,96,57,29,40), +(1,4,44,1221,0,62,98,58,30,40), +(1,4,45,1268,0,63,100,59,30,41), +(1,4,46,1316,0,64,103,61,30,42), +(1,4,47,1365,0,65,105,62,31,42), +(1,4,48,1415,0,66,107,63,31,43), +(1,4,49,1466,0,68,109,64,31,44), +(1,4,50,1518,0,69,111,65,32,44), +(1,4,51,1571,0,70,113,66,32,45), +(1,4,52,1625,0,71,116,67,32,45), +(1,4,53,1680,0,73,118,68,33,46), +(1,4,54,1736,0,74,120,69,33,47), +(1,4,55,1793,0,75,122,71,33,47), +(1,4,56,1851,0,76,125,72,34,48), +(1,4,57,1910,0,78,127,73,34,49), +(1,4,58,1970,0,79,129,74,34,49), +(1,4,59,2031,0,80,131,75,35,50), +(1,4,60,2093,0,81,134,77,35,51), +(1,4,61,2282,0,83,136,78,35,51), +(1,4,62,2480,0,84,138,79,36,52), +(1,4,63,2687,0,85,141,80,36,53), +(1,4,64,2903,0,87,143,81,37,54), +(1,4,65,3129,0,88,146,83,37,54), +(1,4,66,3365,0,89,148,84,37,55), +(1,4,67,3611,0,91,151,85,38,56), +(1,4,68,3868,0,92,153,86,38,57), +(1,4,69,4136,0,94,156,88,39,57), +(1,4,70,4415,0,95,158,89,39,58), +(1,5,1,52,160,20,20,20,22,23), +(1,5,2,67,184,20,20,20,23,24), +(1,5,3,82,209,20,20,21,25,26), +(1,5,4,97,235,20,21,21,26,27), +(1,5,5,112,262,21,21,21,27,28), +(1,5,6,127,290,21,21,22,29,30), +(1,5,7,142,319,21,21,22,30,31), +(1,5,8,157,349,21,22,23,31,33), +(1,5,9,172,380,21,22,23,33,34), +(1,5,10,187,412,21,22,23,34,36), +(1,5,11,202,445,22,22,24,36,37), +(1,5,12,217,479,22,23,24,37,39), +(1,5,13,232,514,22,23,25,38,40), +(1,5,14,247,550,22,23,25,40,42), +(1,5,15,262,587,22,23,25,41,43), +(1,5,16,277,625,23,24,26,43,45), +(1,5,17,292,664,23,24,26,44,46), +(1,5,18,307,704,23,24,27,46,48), +(1,5,19,322,745,23,24,27,47,49), +(1,5,20,337,787,23,25,28,49,51), +(1,5,21,352,830,24,25,28,51,53), +(1,5,22,368,874,24,25,29,52,54), +(1,5,23,385,919,24,26,29,54,56), +(1,5,24,403,965,24,26,30,55,58), +(1,5,25,422,1012,25,26,30,57,59), +(1,5,26,442,1060,25,27,31,59,61), +(1,5,27,463,1109,25,27,31,60,63), +(1,5,28,485,1159,25,27,32,62,65), +(1,5,29,508,1210,25,28,32,64,66), +(1,5,30,532,1262,26,28,33,65,68), +(1,5,31,557,1315,26,28,33,67,70), +(1,5,32,583,1369,26,29,34,69,72), +(1,5,33,610,1423,27,29,34,70,73), +(1,5,34,638,1477,27,29,35,72,75), +(1,5,35,667,1531,27,30,35,74,77), +(1,5,36,697,1585,27,30,36,76,79), +(1,5,37,728,1639,28,30,36,78,81), +(1,5,38,760,1693,28,31,37,79,83), +(1,5,39,793,1747,28,31,38,81,85), +(1,5,40,827,1801,28,31,38,83,87), +(1,5,41,862,1855,29,32,39,85,88), +(1,5,42,898,1909,29,32,39,87,90), +(1,5,43,935,1963,29,33,40,89,92), +(1,5,44,973,2017,30,33,40,91,94), +(1,5,45,1012,2071,30,33,41,92,96), +(1,5,46,1052,2125,30,34,42,94,98), +(1,5,47,1093,2179,31,34,42,96,100), +(1,5,48,1135,2233,31,35,43,98,102), +(1,5,49,1178,2287,31,35,44,100,104), +(1,5,50,1222,2341,32,36,44,102,106), +(1,5,51,1267,2395,32,36,45,104,109), +(1,5,52,1313,2449,32,36,45,106,111), +(1,5,53,1360,2503,33,37,46,108,113), +(1,5,54,1408,2557,33,37,47,110,115), +(1,5,55,1457,2611,33,38,47,112,117), +(1,5,56,1507,2665,34,38,48,114,119), +(1,5,57,1558,2719,34,39,49,117,121), +(1,5,58,1610,2773,34,39,49,119,124), +(1,5,59,1663,2827,35,40,50,121,126), +(1,5,60,1717,2881,35,40,51,123,128), +(1,5,61,1887,3050,35,41,51,125,130), +(1,5,62,2065,3204,36,41,52,127,132), +(1,5,63,2251,3373,36,41,53,129,135), +(1,5,64,2445,3527,37,42,54,132,137), +(1,5,65,2647,3696,37,42,54,134,139), +(1,5,66,2858,3850,37,43,55,136,142), +(1,5,67,3078,4019,38,43,56,138,144), +(1,5,68,3307,4173,38,44,57,140,146), +(1,5,69,3545,4342,39,44,57,143,149), +(1,5,70,3792,4511,39,45,58,145,151), +(1,8,1,52,165,20,20,20,23,22), +(1,8,2,67,190,20,20,20,24,23), +(1,8,3,82,216,20,20,21,26,25), +(1,8,4,97,243,20,20,21,27,26), +(1,8,5,112,271,20,21,21,28,27), +(1,8,6,127,300,20,21,21,30,29), +(1,8,7,142,330,21,21,22,31,30), +(1,8,8,157,361,21,21,22,33,31), +(1,8,9,172,393,21,21,22,34,33), +(1,8,10,187,426,21,21,23,36,34), +(1,8,11,202,460,21,22,23,37,36), +(1,8,12,217,495,21,22,23,39,37), +(1,8,13,232,531,21,22,24,40,38), +(1,8,14,247,568,21,22,24,42,40), +(1,8,15,262,606,21,22,24,43,41), +(1,8,16,277,645,21,23,25,45,43), +(1,8,17,292,685,22,23,25,46,44), +(1,8,18,307,726,22,23,25,48,46), +(1,8,19,322,768,22,23,26,49,47), +(1,8,20,337,811,22,23,26,51,49), +(1,8,21,352,855,22,24,26,53,51), +(1,8,22,367,900,22,24,27,54,52), +(1,8,23,382,946,22,24,27,56,54), +(1,8,24,398,993,23,24,28,58,55), +(1,8,25,415,1041,23,25,28,59,57), +(1,8,26,433,1090,23,25,28,61,59), +(1,8,27,452,1140,23,25,29,63,60), +(1,8,28,472,1191,23,25,29,65,62), +(1,8,29,493,1242,23,25,30,66,64), +(1,8,30,515,1293,24,26,30,68,65), +(1,8,31,538,1344,24,26,30,70,67), +(1,8,32,562,1395,24,26,31,72,69), +(1,8,33,587,1446,24,27,31,73,70), +(1,8,34,613,1497,24,27,32,75,72), +(1,8,35,640,1548,24,27,32,77,74), +(1,8,36,668,1599,25,27,33,79,76), +(1,8,37,697,1650,25,28,33,81,78), +(1,8,38,727,1701,25,28,34,83,79), +(1,8,39,758,1752,25,28,34,85,81), +(1,8,40,790,1803,25,28,35,87,83), +(1,8,41,823,1854,26,29,35,88,85), +(1,8,42,857,1905,26,29,35,90,87), +(1,8,43,892,1956,26,29,36,92,89), +(1,8,44,928,2007,26,30,36,94,91), +(1,8,45,965,2058,26,30,37,96,92), +(1,8,46,1003,2109,27,30,37,98,94), +(1,8,47,1042,2160,27,31,38,100,96), +(1,8,48,1082,2211,27,31,38,102,98), +(1,8,49,1123,2262,27,31,39,104,100), +(1,8,50,1165,2313,28,32,40,106,102), +(1,8,51,1208,2364,28,32,40,109,104), +(1,8,52,1252,2415,28,32,41,111,106), +(1,8,53,1297,2466,28,33,41,113,108), +(1,8,54,1343,2517,29,33,42,115,110), +(1,8,55,1390,2568,29,33,42,117,112), +(1,8,56,1438,2619,29,34,43,119,114), +(1,8,57,1487,2670,29,34,43,121,117), +(1,8,58,1537,2721,30,34,44,124,119), +(1,8,59,1588,2772,30,35,44,126,121), +(1,8,60,1640,2823,30,35,45,128,123), +(1,8,61,1806,2956,30,35,46,130,125), +(1,8,62,1981,3104,31,36,46,132,127), +(1,8,63,2165,3237,31,36,47,135,129), +(1,8,64,2358,3385,31,37,47,137,132), +(1,8,65,2560,3518,32,37,48,139,134), +(1,8,66,2772,3666,32,37,49,142,136), +(1,8,67,2994,3799,32,38,49,144,138), +(1,8,68,3226,3947,32,38,50,146,140), +(1,8,69,3469,4080,33,39,50,149,143), +(1,8,70,3723,4228,33,39,51,151,145), +(1,9,1,53,140,20,20,21,22,22), +(1,9,2,68,163,20,20,22,23,23), +(1,9,3,83,187,21,21,22,24,24), +(1,9,4,98,212,21,21,23,26,25), +(1,9,5,113,238,21,21,23,27,27), +(1,9,6,128,265,21,22,24,28,28), +(1,9,7,143,293,22,22,24,29,29), +(1,9,8,158,322,22,23,25,30,30), +(1,9,9,173,352,22,23,26,32,31), +(1,9,10,188,383,23,23,26,33,33), +(1,9,11,203,415,23,24,27,34,34), +(1,9,12,218,448,23,24,27,35,35), +(1,9,13,233,482,24,25,28,37,36), +(1,9,14,248,517,24,25,29,38,38), +(1,9,15,263,553,24,25,29,39,39), +(1,9,16,278,590,25,26,30,41,40), +(1,9,17,293,628,25,26,31,42,42), +(1,9,18,309,667,25,27,31,43,43), +(1,9,19,326,707,26,27,32,45,44), +(1,9,20,344,748,26,28,33,46,46), +(1,9,21,363,790,26,28,33,48,47), +(1,9,22,383,833,27,29,34,49,49), +(1,9,23,404,877,27,29,35,51,50), +(1,9,24,426,922,28,30,35,52,51), +(1,9,25,449,968,28,30,36,53,53), +(1,9,26,473,1015,28,31,37,55,54), +(1,9,27,498,1063,29,31,37,56,56), +(1,9,28,524,1112,29,32,38,58,57), +(1,9,29,551,1162,30,32,39,59,59), +(1,9,30,579,1213,30,33,40,61,60), +(1,9,31,608,1264,30,33,40,62,62), +(1,9,32,638,1315,31,34,41,64,63), +(1,9,33,669,1366,31,34,42,66,65), +(1,9,34,701,1417,32,35,43,67,66), +(1,9,35,734,1468,32,35,44,69,68), +(1,9,36,768,1519,33,36,44,70,69), +(1,9,37,803,1570,33,36,45,72,71), +(1,9,38,839,1621,34,37,46,74,73), +(1,9,39,876,1672,34,38,47,75,74), +(1,9,40,914,1723,35,38,48,77,76), +(1,9,41,953,1774,35,39,48,79,78), +(1,9,42,993,1825,35,39,49,80,79), +(1,9,43,1034,1876,36,40,50,82,81), +(1,9,44,1076,1927,36,40,51,84,83), +(1,9,45,1119,1978,37,41,52,85,84), +(1,9,46,1163,2029,37,42,53,87,86), +(1,9,47,1208,2080,38,42,54,89,88), +(1,9,48,1254,2131,38,43,55,91,89), +(1,9,49,1301,2182,39,44,55,93,91), +(1,9,50,1349,2233,40,44,56,94,93), +(1,9,51,1398,2284,40,45,57,96,95), +(1,9,52,1448,2335,41,45,58,98,97), +(1,9,53,1499,2386,41,46,59,100,98), +(1,9,54,1551,2437,42,47,60,102,100), +(1,9,55,1604,2488,42,47,61,103,102), +(1,9,56,1658,2539,43,48,62,105,104), +(1,9,57,1713,2590,43,49,63,107,106), +(1,9,58,1769,2641,44,49,64,109,108), +(1,9,59,1826,2692,44,50,65,111,109), +(1,9,60,1884,2743,45,51,66,113,111), +(1,9,61,2060,2897,46,51,67,115,113), +(1,9,62,2245,3051,46,52,68,117,115), +(1,9,63,2439,3220,47,53,69,119,117), +(1,9,64,2642,3374,47,54,70,121,119), +(1,9,65,2854,3528,48,54,71,123,121), +(1,9,66,3076,3697,49,55,72,125,123), +(1,9,67,3308,3851,49,56,73,127,125), +(1,9,68,3551,4005,50,57,74,129,127), +(1,9,69,3805,4174,50,57,75,131,129), +(1,9,70,4070,4328,51,58,76,133,131), +(2,1,1,80,0,26,17,24,17,23), +(2,1,2,99,0,27,18,25,17,23), +(2,1,3,118,0,29,19,26,17,24), +(2,1,4,137,0,30,19,27,17,24), +(2,1,5,156,0,31,20,29,17,24), +(2,1,6,175,0,32,21,30,17,24), +(2,1,7,194,0,34,22,31,18,25), +(2,1,8,213,0,35,23,32,18,25), +(2,1,9,232,0,37,24,34,18,25), +(2,1,10,251,0,38,24,35,18,26), +(2,1,11,270,0,39,25,36,18,26), +(2,1,12,289,0,41,26,37,18,26), +(2,1,13,308,0,42,27,39,18,27), +(2,1,14,328,0,44,28,40,18,27), +(2,1,15,349,0,45,29,41,18,27), +(2,1,16,371,0,47,30,43,19,28), +(2,1,17,394,0,48,31,44,19,28), +(2,1,18,418,0,50,32,45,19,28), +(2,1,19,443,0,51,33,47,19,29), +(2,1,20,469,0,53,34,48,19,29), +(2,1,21,496,0,54,34,50,19,29), +(2,1,22,524,0,56,35,51,19,30), +(2,1,23,553,0,57,36,52,20,30), +(2,1,24,583,0,59,37,54,20,30), +(2,1,25,614,0,60,38,55,20,31), +(2,1,26,646,0,62,39,57,20,31), +(2,1,27,679,0,64,40,58,20,32), +(2,1,28,713,0,65,41,60,20,32), +(2,1,29,748,0,67,43,61,21,32), +(2,1,30,784,0,69,44,63,21,33), +(2,1,31,821,0,70,45,64,21,33), +(2,1,32,859,0,72,46,66,21,34), +(2,1,33,898,0,74,47,67,21,34), +(2,1,34,938,0,76,48,69,21,35), +(2,1,35,979,0,77,49,71,22,35), +(2,1,36,1021,0,79,50,72,22,36), +(2,1,37,1065,0,81,51,74,22,36), +(2,1,38,1111,0,83,52,76,22,36), +(2,1,39,1159,0,84,53,77,22,37), +(2,1,40,1209,0,86,55,79,23,37), +(2,1,41,1261,0,88,56,81,23,38), +(2,1,42,1315,0,90,57,82,23,38), +(2,1,43,1371,0,92,58,84,23,39), +(2,1,44,1429,0,94,59,86,23,39), +(2,1,45,1489,0,96,60,87,24,40), +(2,1,46,1551,0,98,62,89,24,40), +(2,1,47,1615,0,100,63,91,24,41), +(2,1,48,1681,0,101,64,93,24,41), +(2,1,49,1749,0,103,65,94,25,42), +(2,1,50,1819,0,105,66,96,25,42), +(2,1,51,1891,0,107,68,98,25,43), +(2,1,52,1965,0,109,69,100,25,43), +(2,1,53,2041,0,111,70,102,25,44), +(2,1,54,2119,0,113,71,104,26,45), +(2,1,55,2199,0,115,73,105,26,45), +(2,1,56,2281,0,118,74,107,26,46), +(2,1,57,2365,0,120,75,109,26,46), +(2,1,58,2451,0,122,77,111,27,47), +(2,1,59,2539,0,124,78,113,27,47), +(2,1,60,2629,0,126,79,115,27,48), +(2,1,61,2862,0,128,81,117,27,48), +(2,1,62,3109,0,130,82,119,28,49), +(2,1,63,3370,0,132,83,121,28,50), +(2,1,64,3645,0,135,85,123,28,50), +(2,1,65,3935,0,137,86,125,29,51), +(2,1,66,4240,0,139,87,127,29,52), +(2,1,67,4560,0,141,89,129,29,52), +(2,1,68,4896,0,143,90,131,29,53), +(2,1,69,5248,0,146,92,133,30,53), +(2,1,70,5616,0,148,93,135,30,54), +(2,3,1,76,82,23,20,23,17,24), +(2,3,2,93,102,23,21,24,18,25), +(2,3,3,110,123,24,23,25,18,25), +(2,3,4,127,145,24,24,26,19,26), +(2,3,5,144,168,25,25,27,19,26), +(2,3,6,161,192,25,27,28,20,27), +(2,3,7,178,217,26,28,28,21,28), +(2,3,8,195,243,26,30,29,21,28), +(2,3,9,212,270,26,31,30,22,29), +(2,3,10,229,298,27,33,31,22,30), +(2,3,11,246,327,27,34,32,23,30), +(2,3,12,263,357,28,36,33,24,31), +(2,3,13,280,388,28,37,34,24,32), +(2,3,14,298,420,29,39,35,25,33), +(2,3,15,317,453,29,40,36,26,33), +(2,3,16,337,487,30,42,37,26,34), +(2,3,17,358,522,30,43,39,27,35), +(2,3,18,380,558,31,45,40,28,35), +(2,3,19,403,595,31,47,41,28,36), +(2,3,20,427,633,32,48,42,29,37), +(2,3,21,452,672,32,50,43,30,38), +(2,3,22,478,712,33,51,44,31,39), +(2,3,23,505,753,34,53,45,31,39), +(2,3,24,533,795,34,55,46,32,40), +(2,3,25,562,838,35,57,47,33,41), +(2,3,26,592,882,35,58,48,34,42), +(2,3,27,623,927,36,60,50,34,43), +(2,3,28,655,972,36,62,51,35,43), +(2,3,29,688,1017,37,63,52,36,44), +(2,3,30,722,1062,38,65,53,37,45), +(2,3,31,757,1107,38,67,54,37,46), +(2,3,32,793,1152,39,69,56,38,47), +(2,3,33,830,1197,39,71,57,39,48), +(2,3,34,868,1242,40,72,58,40,49), +(2,3,35,907,1287,41,74,59,41,49), +(2,3,36,947,1332,41,76,61,42,50), +(2,3,37,988,1377,42,78,62,42,51), +(2,3,38,1030,1422,43,80,63,43,52), +(2,3,39,1073,1467,43,82,64,44,53), +(2,3,40,1117,1512,44,84,66,45,54), +(2,3,41,1162,1557,45,86,67,46,55), +(2,3,42,1208,1602,45,88,68,47,56), +(2,3,43,1255,1647,46,90,70,47,57), +(2,3,44,1303,1692,47,91,71,48,58), +(2,3,45,1352,1737,47,93,72,49,59), +(2,3,46,1402,1782,48,95,74,50,60), +(2,3,47,1453,1827,49,98,75,51,61), +(2,3,48,1505,1872,50,100,77,52,62), +(2,3,49,1558,1917,50,102,78,53,63), +(2,3,50,1612,1962,51,104,79,54,64), +(2,3,51,1667,2007,52,106,81,55,65), +(2,3,52,1723,2052,52,108,82,56,66), +(2,3,53,1780,2097,53,110,84,57,67), +(2,3,54,1838,2142,54,112,85,58,68), +(2,3,55,1897,2187,55,114,87,59,69), +(2,3,56,1957,2232,55,116,88,60,70), +(2,3,57,2018,2277,56,118,90,61,71), +(2,3,58,2080,2322,57,121,91,62,72), +(2,3,59,2143,2367,58,123,93,63,73), +(2,3,60,2207,2412,59,125,94,64,74), +(2,3,61,2393,2593,59,127,96,65,76), +(2,3,62,2588,2774,60,130,97,66,77), +(2,3,63,2792,2955,61,132,99,67,78), +(2,3,64,3005,3136,62,134,100,68,79), +(2,3,65,3227,3332,63,136,102,69,80), +(2,3,66,3459,3513,64,139,104,70,81), +(2,3,67,3701,3694,64,141,105,71,82), +(2,3,68,3953,3875,65,143,107,72,84), +(2,3,69,4215,4056,66,146,108,73,85), +(2,3,70,4488,4252,67,148,110,74,86), +(2,4,1,75,0,24,20,23,17,23), +(2,4,2,92,0,25,21,24,17,23), +(2,4,3,109,0,25,23,24,17,24), +(2,4,4,126,0,26,24,25,17,24), +(2,4,5,143,0,27,26,26,18,24), +(2,4,6,160,0,28,27,26,18,25), +(2,4,7,177,0,29,29,27,18,25), +(2,4,8,194,0,29,30,28,18,26), +(2,4,9,211,0,30,32,29,18,26), +(2,4,10,228,0,31,33,29,19,26), +(2,4,11,245,0,32,35,30,19,27), +(2,4,12,262,0,33,37,31,19,27), +(2,4,13,279,0,34,38,32,19,28), +(2,4,14,296,0,34,40,32,19,28), +(2,4,15,313,0,35,41,33,19,28), +(2,4,16,331,0,36,43,34,20,29), +(2,4,17,350,0,37,45,35,20,29), +(2,4,18,370,0,38,46,36,20,30), +(2,4,19,391,0,39,48,37,20,30), +(2,4,20,413,0,40,50,37,21,31), +(2,4,21,436,0,41,52,38,21,31), +(2,4,22,460,0,42,53,39,21,31), +(2,4,23,485,0,43,55,40,21,32), +(2,4,24,511,0,43,57,41,21,32), +(2,4,25,538,0,44,59,42,22,33), +(2,4,26,566,0,45,60,43,22,33), +(2,4,27,595,0,46,62,44,22,34), +(2,4,28,625,0,47,64,44,22,34), +(2,4,29,656,0,48,66,45,23,35), +(2,4,30,688,0,49,68,46,23,35), +(2,4,31,721,0,50,70,47,23,36), +(2,4,32,755,0,51,72,48,23,36), +(2,4,33,790,0,53,73,49,24,37), +(2,4,34,826,0,54,75,50,24,38), +(2,4,35,863,0,55,77,51,24,38), +(2,4,36,901,0,56,79,52,24,39), +(2,4,37,940,0,57,81,53,25,39), +(2,4,38,980,0,58,83,54,25,40), +(2,4,39,1021,0,59,85,55,25,40), +(2,4,40,1063,0,60,87,56,26,41), +(2,4,41,1106,0,61,89,57,26,41), +(2,4,42,1150,0,62,91,58,26,42), +(2,4,43,1195,0,63,93,59,27,43), +(2,4,44,1241,0,65,95,60,27,43), +(2,4,45,1288,0,66,98,61,27,44), +(2,4,46,1336,0,67,100,62,27,44), +(2,4,47,1385,0,68,102,64,28,45), +(2,4,48,1435,0,69,104,65,28,46), +(2,4,49,1486,0,71,106,66,28,46), +(2,4,50,1538,0,72,108,67,29,47), +(2,4,51,1591,0,73,110,68,29,48), +(2,4,52,1645,0,74,113,69,29,48), +(2,4,53,1700,0,75,115,70,30,49), +(2,4,54,1756,0,77,117,71,30,50), +(2,4,55,1813,0,78,119,73,30,50), +(2,4,56,1871,0,79,122,74,31,51), +(2,4,57,1930,0,80,124,75,31,52), +(2,4,58,1990,0,82,126,76,31,52), +(2,4,59,2051,0,83,129,77,32,53), +(2,4,60,2113,0,84,131,78,32,54), +(2,4,61,2302,0,86,133,80,33,54), +(2,4,62,2500,0,87,136,81,33,55), +(2,4,63,2707,0,88,138,82,33,56), +(2,4,64,2923,0,90,140,83,34,57), +(2,4,65,3149,0,91,143,85,34,57), +(2,4,66,3385,0,92,145,86,34,58), +(2,4,67,3631,0,94,148,87,35,59), +(2,4,68,3888,0,95,150,88,35,59), +(2,4,69,4156,0,97,153,90,36,60), +(2,4,70,4435,0,98,155,91,36,61), +(2,7,1,77,73,24,17,23,18,25), +(2,7,2,94,94,25,17,24,19,26), +(2,7,3,111,116,26,18,25,20,27), +(2,7,4,128,139,26,18,26,21,28), +(2,7,5,145,163,27,19,27,22,29), +(2,7,6,162,188,28,19,28,23,30), +(2,7,7,179,214,29,20,29,24,31), +(2,7,8,196,241,30,20,30,25,32), +(2,7,9,213,269,31,21,31,26,33), +(2,7,10,230,298,32,21,32,27,34), +(2,7,11,247,328,33,22,33,28,36), +(2,7,12,264,359,34,22,34,29,37), +(2,7,13,281,391,34,23,35,30,38), +(2,7,14,298,424,35,23,36,31,39), +(2,7,15,315,458,36,24,37,32,40), +(2,7,16,332,493,37,24,39,33,41), +(2,7,17,350,529,38,25,40,34,43), +(2,7,18,369,566,39,25,41,35,44), +(2,7,19,389,604,40,26,42,36,45), +(2,7,20,410,643,41,26,43,37,46), +(2,7,21,432,683,42,27,44,38,47), +(2,7,22,455,724,43,27,45,39,49), +(2,7,23,479,766,44,28,47,40,50), +(2,7,24,504,809,45,28,48,41,51), +(2,7,25,530,853,47,29,49,43,52), +(2,7,26,557,898,48,30,50,44,54), +(2,7,27,585,944,49,30,52,45,55), +(2,7,28,614,991,50,31,53,46,56), +(2,7,29,644,1039,51,31,54,47,58), +(2,7,30,675,1088,52,32,55,48,59), +(2,7,31,707,1138,53,33,57,50,60), +(2,7,32,740,1189,54,33,58,51,62), +(2,7,33,774,1240,55,34,59,52,63), +(2,7,34,809,1291,57,34,61,53,65), +(2,7,35,845,1342,58,35,62,55,66), +(2,7,36,882,1393,59,36,63,56,67), +(2,7,37,920,1444,60,36,65,57,69), +(2,7,38,959,1495,61,37,66,58,70), +(2,7,39,999,1546,62,38,67,60,72), +(2,7,40,1040,1597,64,38,69,61,73), +(2,7,41,1082,1648,65,39,70,62,75), +(2,7,42,1125,1699,66,40,72,64,76), +(2,7,43,1169,1750,67,40,73,65,78), +(2,7,44,1214,1801,69,41,74,66,79), +(2,7,45,1260,1852,70,42,76,68,81), +(2,7,46,1307,1903,71,42,77,69,82), +(2,7,47,1355,1954,72,43,79,70,84), +(2,7,48,1404,2005,74,44,80,72,85), +(2,7,49,1454,2056,75,45,82,73,87), +(2,7,50,1505,2107,76,45,83,75,89), +(2,7,51,1557,2158,78,46,85,76,90), +(2,7,52,1610,2209,79,47,86,77,92), +(2,7,53,1664,2260,80,47,88,79,93), +(2,7,54,1719,2311,82,48,90,80,95), +(2,7,55,1775,2362,83,49,91,82,97), +(2,7,56,1832,2413,85,50,93,83,98), +(2,7,57,1890,2464,86,50,94,85,100), +(2,7,58,1949,2515,87,51,96,86,102), +(2,7,59,2009,2566,89,52,97,88,103), +(2,7,60,2070,2617,90,53,99,89,105), +(2,7,61,2238,2776,92,54,101,91,107), +(2,7,62,2414,2935,93,54,102,92,109), +(2,7,63,2598,3109,95,55,104,94,110), +(2,7,64,2790,3268,96,56,106,95,112), +(2,7,65,2991,3427,97,57,107,97,114), +(2,7,66,3201,3601,99,58,109,99,116), +(2,7,67,3421,3760,100,58,111,100,118), +(2,7,68,3651,3919,102,59,113,102,119), +(2,7,69,3891,4093,103,60,114,103,121), +(2,7,70,4141,4252,105,61,116,105,123), +(2,9,1,73,109,23,17,23,19,25), +(2,9,2,88,132,23,17,24,20,26), +(2,9,3,103,156,24,18,24,21,27), +(2,9,4,118,181,24,18,25,23,28), +(2,9,5,133,207,24,18,25,24,30), +(2,9,6,148,234,24,19,26,25,31), +(2,9,7,163,262,25,19,26,26,32), +(2,9,8,178,291,25,20,27,27,33), +(2,9,9,193,321,25,20,27,29,34), +(2,9,10,208,352,26,20,28,30,36), +(2,9,11,223,384,26,21,29,31,37), +(2,9,12,238,417,26,21,29,33,38), +(2,9,13,253,451,27,22,30,34,39), +(2,9,14,268,486,27,22,31,35,41), +(2,9,15,283,522,27,23,31,37,42), +(2,9,16,298,559,28,23,32,38,43), +(2,9,17,313,597,28,23,32,39,45), +(2,9,18,329,636,28,24,33,41,46), +(2,9,19,346,676,29,24,34,42,47), +(2,9,20,364,717,29,25,34,43,49), +(2,9,21,383,759,29,25,35,45,50), +(2,9,22,403,802,30,26,36,46,51), +(2,9,23,424,846,30,26,37,48,53), +(2,9,24,446,891,30,27,37,49,54), +(2,9,25,469,937,31,27,38,51,56), +(2,9,26,493,984,31,28,39,52,57), +(2,9,27,518,1032,32,28,39,54,59), +(2,9,28,544,1081,32,29,40,55,60), +(2,9,29,571,1131,32,29,41,57,62), +(2,9,30,599,1182,33,30,42,58,63), +(2,9,31,628,1233,33,30,42,60,65), +(2,9,32,658,1284,34,31,43,61,66), +(2,9,33,689,1335,34,31,44,63,68), +(2,9,34,721,1386,35,32,45,64,69), +(2,9,35,754,1437,35,32,45,66,71), +(2,9,36,788,1488,36,33,46,68,72), +(2,9,37,823,1539,36,34,47,69,74), +(2,9,38,859,1590,36,34,48,71,76), +(2,9,39,896,1641,37,35,49,72,77), +(2,9,40,934,1692,37,35,50,74,79), +(2,9,41,973,1743,38,36,50,76,80), +(2,9,42,1013,1794,38,36,51,77,82), +(2,9,43,1054,1845,39,37,52,79,84), +(2,9,44,1096,1896,39,38,53,81,85), +(2,9,45,1139,1947,40,38,54,83,87), +(2,9,46,1183,1998,40,39,55,84,89), +(2,9,47,1228,2049,41,39,56,86,91), +(2,9,48,1274,2100,41,40,56,88,92), +(2,9,49,1321,2151,42,41,57,90,94), +(2,9,50,1369,2202,42,41,58,91,96), +(2,9,51,1418,2253,43,42,59,93,98), +(2,9,52,1468,2304,43,43,60,95,99), +(2,9,53,1519,2355,44,43,61,97,101), +(2,9,54,1571,2406,45,44,62,99,103), +(2,9,55,1624,2457,45,45,63,101,105), +(2,9,56,1678,2508,46,45,64,102,107), +(2,9,57,1733,2559,46,46,65,104,109), +(2,9,58,1789,2610,47,47,66,106,110), +(2,9,59,1846,2661,47,47,67,108,112), +(2,9,60,1904,2712,48,48,68,110,114), +(2,9,61,2080,2866,48,49,69,112,116), +(2,9,62,2265,3020,49,49,70,114,118), +(2,9,63,2459,3189,50,50,71,116,120), +(2,9,64,2662,3343,50,51,72,118,122), +(2,9,65,2874,3497,51,51,73,120,124), +(2,9,66,3096,3666,52,52,74,122,126), +(2,9,67,3328,3820,52,53,75,124,128), +(2,9,68,3571,3974,53,54,76,126,130), +(2,9,69,3825,4143,53,54,77,128,132), +(2,9,70,4090,4297,54,55,78,130,134), +(3,1,1,90,0,25,16,25,19,19), +(3,1,2,109,0,26,17,26,19,19), +(3,1,3,128,0,28,18,27,19,20), +(3,1,4,147,0,29,18,28,19,20), +(3,1,5,166,0,30,19,30,19,20), +(3,1,6,185,0,31,20,31,19,20), +(3,1,7,204,0,33,21,32,20,21), +(3,1,8,223,0,34,22,33,20,21), +(3,1,9,242,0,36,23,35,20,21), +(3,1,10,261,0,37,23,36,20,22), +(3,1,11,280,0,38,24,37,20,22), +(3,1,12,299,0,40,25,38,20,22), +(3,1,13,318,0,41,26,40,20,23), +(3,1,14,338,0,43,27,41,20,23), +(3,1,15,359,0,44,28,42,20,23), +(3,1,16,381,0,46,29,44,21,24), +(3,1,17,404,0,47,30,45,21,24), +(3,1,18,428,0,49,31,46,21,24), +(3,1,19,453,0,50,32,48,21,25), +(3,1,20,479,0,52,33,49,21,25), +(3,1,21,506,0,53,34,51,21,26), +(3,1,22,534,0,55,34,52,21,26), +(3,1,23,563,0,56,35,53,21,26), +(3,1,24,593,0,58,36,55,22,27), +(3,1,25,624,0,59,37,56,22,27), +(3,1,26,656,0,61,38,58,22,27), +(3,1,27,689,0,63,39,59,22,28), +(3,1,28,723,0,64,41,61,22,28), +(3,1,29,758,0,66,42,62,22,29), +(3,1,30,794,0,68,43,64,23,29), +(3,1,31,831,0,69,44,65,23,30), +(3,1,32,869,0,71,45,67,23,30), +(3,1,33,908,0,73,46,68,23,30), +(3,1,34,948,0,75,47,70,23,31), +(3,1,35,989,0,76,48,72,24,31), +(3,1,36,1031,0,78,49,73,24,32), +(3,1,37,1075,0,80,50,75,24,32), +(3,1,38,1121,0,82,51,76,24,33), +(3,1,39,1169,0,84,52,78,24,33), +(3,1,40,1219,0,85,54,80,24,34), +(3,1,41,1271,0,87,55,81,25,34), +(3,1,42,1325,0,89,56,83,25,35), +(3,1,43,1381,0,91,57,85,25,35), +(3,1,44,1439,0,93,58,87,25,36), +(3,1,45,1499,0,95,59,88,26,36), +(3,1,46,1561,0,97,61,90,26,37), +(3,1,47,1625,0,99,62,92,26,37), +(3,1,48,1691,0,101,63,94,26,38), +(3,1,49,1759,0,102,64,95,26,38), +(3,1,50,1829,0,104,65,97,27,39), +(3,1,51,1901,0,106,67,99,27,39), +(3,1,52,1975,0,108,68,101,27,40), +(3,1,53,2051,0,110,69,103,27,40), +(3,1,54,2129,0,112,70,104,28,41), +(3,1,55,2209,0,115,72,106,28,41), +(3,1,56,2291,0,117,73,108,28,42), +(3,1,57,2375,0,119,74,110,28,42), +(3,1,58,2461,0,121,76,112,29,43), +(3,1,59,2549,0,123,77,114,29,43), +(3,1,60,2639,0,125,78,116,29,44), +(3,1,61,2872,0,127,80,118,29,45), +(3,1,62,3119,0,129,81,120,30,45), +(3,1,63,3380,0,131,82,122,30,46), +(3,1,64,3655,0,134,84,124,30,46), +(3,1,65,3945,0,136,85,126,31,47), +(3,1,66,4250,0,138,86,128,31,48), +(3,1,67,4570,0,140,88,130,31,48), +(3,1,68,4906,0,142,89,132,31,49), +(3,1,69,5258,0,145,91,134,32,49), +(3,1,70,5626,0,147,92,136,32,50), +(3,2,1,88,79,24,16,25,19,20), +(3,2,2,106,98,25,17,26,20,21), +(3,2,3,124,118,26,17,27,20,21), +(3,2,4,142,139,27,18,28,21,22), +(3,2,5,160,161,28,18,29,22,23), +(3,2,6,178,184,29,19,30,22,24), +(3,2,7,196,208,31,20,31,23,24), +(3,2,8,214,233,32,20,32,24,25), +(3,2,9,232,259,33,21,33,24,26), +(3,2,10,250,286,34,21,34,25,26), +(3,2,11,268,314,35,22,36,26,27), +(3,2,12,286,343,36,23,37,26,28), +(3,2,13,304,373,38,23,38,27,29), +(3,2,14,322,404,39,24,39,28,30), +(3,2,15,341,436,40,25,40,29,30), +(3,2,16,361,469,41,25,41,29,31), +(3,2,17,382,503,43,26,43,30,32), +(3,2,18,404,538,44,27,44,31,33), +(3,2,19,427,574,45,28,45,32,34), +(3,2,20,451,611,47,28,46,32,35), +(3,2,21,476,649,48,29,47,33,35), +(3,2,22,502,688,49,30,49,34,36), +(3,2,23,529,728,51,30,50,35,37), +(3,2,24,557,769,52,31,51,36,38), +(3,2,25,586,811,53,32,52,36,39), +(3,2,26,616,853,55,33,54,37,40), +(3,2,27,647,895,56,33,55,38,41), +(3,2,28,679,937,57,34,56,39,42), +(3,2,29,712,979,59,35,58,40,43), +(3,2,30,746,1021,60,36,59,41,43), +(3,2,31,781,1063,62,37,60,42,44), +(3,2,32,817,1105,63,37,62,42,45), +(3,2,33,854,1147,65,38,63,43,46), +(3,2,34,892,1189,66,39,65,44,47), +(3,2,35,931,1231,68,40,66,45,48), +(3,2,36,971,1273,69,41,67,46,49), +(3,2,37,1012,1315,71,41,69,47,50), +(3,2,38,1054,1357,72,42,70,48,51), +(3,2,39,1097,1399,74,43,72,49,52), +(3,2,40,1141,1441,75,44,73,50,53), +(3,2,41,1186,1483,77,45,75,51,54), +(3,2,42,1232,1525,78,46,76,52,55), +(3,2,43,1279,1567,80,47,78,53,56), +(3,2,44,1327,1609,82,47,79,54,57), +(3,2,45,1376,1651,83,48,81,55,59), +(3,2,46,1426,1693,85,49,82,56,60), +(3,2,47,1477,1735,87,50,84,57,61), +(3,2,48,1529,1777,88,51,85,58,62), +(3,2,49,1582,1819,90,52,87,59,63), +(3,2,50,1636,1861,92,53,89,60,64), +(3,2,51,1691,1903,93,54,90,61,65), +(3,2,52,1747,1945,95,55,92,62,66), +(3,2,53,1804,1987,97,56,93,63,67), +(3,2,54,1862,2029,98,57,95,64,69), +(3,2,55,1921,2071,100,58,97,65,70), +(3,2,56,1981,2113,102,59,98,66,71), +(3,2,57,2042,2155,104,60,100,67,72), +(3,2,58,2104,2197,106,61,102,68,73), +(3,2,59,2167,2239,107,62,103,69,74), +(3,2,60,2231,2281,109,63,105,70,76), +(3,2,61,2411,2440,111,64,107,72,77), +(3,2,62,2599,2599,113,65,109,73,78), +(3,2,63,2795,2773,115,66,110,74,79), +(3,2,64,3000,2932,117,67,112,75,80), +(3,2,65,3214,3091,118,68,114,76,82), +(3,2,66,3437,3265,120,69,116,77,83), +(3,2,67,3670,3424,122,70,118,78,84), +(3,2,68,3913,3583,124,71,119,80,85), +(3,2,69,4166,3757,126,72,121,81,87), +(3,2,70,4429,3916,128,73,123,82,88), +(3,3,1,86,84,22,19,24,19,20), +(3,3,2,103,104,22,20,25,20,21), +(3,3,3,120,125,23,22,26,20,21), +(3,3,4,137,147,23,23,27,21,22), +(3,3,5,154,170,24,25,28,21,23), +(3,3,6,171,194,24,26,29,22,23), +(3,3,7,188,219,25,27,29,23,24), +(3,3,8,205,245,25,29,30,23,25), +(3,3,9,222,272,25,30,31,24,25), +(3,3,10,239,300,26,32,32,24,26), +(3,3,11,256,329,26,33,33,25,27), +(3,3,12,273,359,27,35,34,26,27), +(3,3,13,290,390,27,36,35,26,28), +(3,3,14,308,422,28,38,36,27,29), +(3,3,15,327,455,28,39,37,28,29), +(3,3,16,347,489,29,41,38,28,30), +(3,3,17,368,524,29,42,39,29,31), +(3,3,18,390,560,30,44,41,30,32), +(3,3,19,413,597,30,46,42,30,32), +(3,3,20,437,635,31,47,43,31,33), +(3,3,21,462,674,32,49,44,32,34), +(3,3,22,488,714,32,51,45,33,35), +(3,3,23,515,755,33,52,46,33,36), +(3,3,24,543,797,33,54,47,34,36), +(3,3,25,572,840,34,56,48,35,37), +(3,3,26,602,884,34,57,49,35,38), +(3,3,27,633,929,35,59,51,36,39), +(3,3,28,665,974,35,61,52,37,40), +(3,3,29,698,1019,36,63,53,38,40), +(3,3,30,732,1064,37,64,54,39,41), +(3,3,31,767,1109,37,66,55,39,42), +(3,3,32,803,1154,38,68,57,40,43), +(3,3,33,840,1199,38,70,58,41,44), +(3,3,34,878,1244,39,71,59,42,45), +(3,3,35,917,1289,40,73,60,43,46), +(3,3,36,957,1334,40,75,62,43,47), +(3,3,37,998,1379,41,77,63,44,47), +(3,3,38,1040,1424,42,79,64,45,48), +(3,3,39,1083,1469,42,81,65,46,49), +(3,3,40,1127,1514,43,83,67,47,50), +(3,3,41,1172,1559,44,85,68,48,51), +(3,3,42,1218,1604,44,87,69,49,52), +(3,3,43,1265,1649,45,89,71,49,53), +(3,3,44,1313,1694,46,91,72,50,54), +(3,3,45,1362,1739,46,93,73,51,55), +(3,3,46,1412,1784,47,95,75,52,56), +(3,3,47,1463,1829,48,97,76,53,57), +(3,3,48,1515,1874,49,99,78,54,58), +(3,3,49,1568,1919,49,101,79,55,59), +(3,3,50,1622,1964,50,103,80,56,60), +(3,3,51,1677,2009,51,105,82,57,61), +(3,3,52,1733,2054,51,107,83,58,62), +(3,3,53,1790,2099,52,109,85,59,63), +(3,3,54,1848,2144,53,111,86,60,64), +(3,3,55,1907,2189,54,113,88,61,65), +(3,3,56,1967,2234,55,115,89,62,66), +(3,3,57,2028,2279,55,118,91,62,67), +(3,3,58,2090,2324,56,120,92,63,68), +(3,3,59,2153,2369,57,122,94,64,70), +(3,3,60,2217,2414,58,124,95,65,71), +(3,3,61,2403,2595,58,126,97,67,72), +(3,3,62,2598,2776,59,129,98,68,73), +(3,3,63,2802,2957,60,131,100,69,74), +(3,3,64,3015,3138,61,133,101,70,75), +(3,3,65,3237,3334,62,135,103,71,76), +(3,3,66,3469,3515,63,138,105,72,77), +(3,3,67,3711,3696,63,140,106,73,78), +(3,3,68,3963,3877,64,142,108,74,80), +(3,3,69,4225,4058,65,145,109,75,81), +(3,3,70,4498,4254,66,147,111,76,82), +(3,4,1,85,0,23,19,24,19,19), +(3,4,2,102,0,24,20,25,19,19), +(3,4,3,119,0,24,22,25,19,20), +(3,4,4,136,0,25,23,26,19,20), +(3,4,5,153,0,26,25,27,20,20), +(3,4,6,170,0,27,26,27,20,21), +(3,4,7,187,0,28,28,28,20,21), +(3,4,8,204,0,28,29,29,20,22), +(3,4,9,221,0,29,31,30,20,22), +(3,4,10,238,0,30,32,30,20,22), +(3,4,11,255,0,31,34,31,21,23), +(3,4,12,272,0,32,36,32,21,23), +(3,4,13,289,0,33,37,33,21,24), +(3,4,14,306,0,33,39,33,21,24), +(3,4,15,323,0,34,40,34,21,25), +(3,4,16,341,0,35,42,35,22,25), +(3,4,17,360,0,36,44,36,22,25), +(3,4,18,380,0,37,45,37,22,26), +(3,4,19,401,0,38,47,38,22,26), +(3,4,20,423,0,39,49,38,22,27), +(3,4,21,446,0,40,51,39,23,27), +(3,4,22,470,0,41,52,40,23,28), +(3,4,23,495,0,42,54,41,23,28), +(3,4,24,521,0,43,56,42,23,29), +(3,4,25,548,0,44,58,43,24,29), +(3,4,26,576,0,44,59,44,24,30), +(3,4,27,605,0,45,61,44,24,30), +(3,4,28,635,0,46,63,45,24,31), +(3,4,29,666,0,47,65,46,25,31), +(3,4,30,698,0,48,67,47,25,32), +(3,4,31,731,0,49,69,48,25,32), +(3,4,32,765,0,51,71,49,25,33), +(3,4,33,800,0,52,72,50,26,33), +(3,4,34,836,0,53,74,51,26,34), +(3,4,35,873,0,54,76,52,26,34), +(3,4,36,911,0,55,78,53,26,35), +(3,4,37,950,0,56,80,54,27,35), +(3,4,38,990,0,57,82,55,27,36), +(3,4,39,1031,0,58,84,56,27,37), +(3,4,40,1073,0,59,86,57,28,37), +(3,4,41,1116,0,60,88,58,28,38), +(3,4,42,1160,0,61,90,59,28,38), +(3,4,43,1205,0,63,92,60,28,39), +(3,4,44,1251,0,64,95,61,29,39), +(3,4,45,1298,0,65,97,62,29,40), +(3,4,46,1346,0,66,99,63,29,41), +(3,4,47,1395,0,67,101,64,30,41), +(3,4,48,1445,0,68,103,66,30,42), +(3,4,49,1496,0,70,105,67,30,43), +(3,4,50,1548,0,71,107,68,31,43), +(3,4,51,1601,0,72,110,69,31,44), +(3,4,52,1655,0,73,112,70,31,44), +(3,4,53,1710,0,74,114,71,32,45), +(3,4,54,1766,0,76,116,72,32,46), +(3,4,55,1823,0,77,118,73,32,46), +(3,4,56,1881,0,78,121,75,33,47), +(3,4,57,1940,0,80,123,76,33,48), +(3,4,58,2000,0,81,125,77,33,48), +(3,4,59,2061,0,82,128,78,34,49), +(3,4,60,2123,0,83,130,79,34,50), +(3,4,61,2312,0,85,132,81,34,51), +(3,4,62,2510,0,86,135,82,35,51), +(3,4,63,2717,0,87,137,83,35,52), +(3,4,64,2933,0,89,139,84,36,53), +(3,4,65,3159,0,90,142,86,36,53), +(3,4,66,3395,0,91,144,87,36,54), +(3,4,67,3641,0,93,147,88,37,55), +(3,4,68,3898,0,94,149,89,37,56), +(3,4,69,4166,0,96,152,91,38,56), +(3,4,70,4445,0,97,154,92,38,57), +(3,5,1,82,145,22,16,23,21,22), +(3,5,2,97,169,22,16,23,22,23), +(3,5,3,112,194,22,16,24,24,25), +(3,5,4,127,220,22,17,24,25,26), +(3,5,5,142,247,23,17,24,26,27), +(3,5,6,157,275,23,17,25,28,29), +(3,5,7,172,304,23,17,25,29,30), +(3,5,8,187,334,23,18,26,30,32), +(3,5,9,202,365,23,18,26,32,33), +(3,5,10,217,397,23,18,26,33,35), +(3,5,11,232,430,24,18,27,35,36), +(3,5,12,247,464,24,19,27,36,38), +(3,5,13,262,499,24,19,28,37,39), +(3,5,14,277,535,24,19,28,39,41), +(3,5,15,292,572,24,19,28,40,42), +(3,5,16,307,610,24,20,29,42,44), +(3,5,17,322,649,25,20,29,43,45), +(3,5,18,337,689,25,20,30,45,47), +(3,5,19,352,730,25,21,30,46,49), +(3,5,20,367,772,25,21,31,48,50), +(3,5,21,382,815,25,21,31,50,52), +(3,5,22,398,859,26,22,31,51,53), +(3,5,23,415,904,26,22,32,53,55), +(3,5,24,433,950,26,22,32,54,57), +(3,5,25,452,997,26,22,33,56,58), +(3,5,26,472,1045,27,23,33,58,60), +(3,5,27,493,1094,27,23,34,59,62), +(3,5,28,515,1144,27,23,34,61,64), +(3,5,29,538,1195,27,24,35,63,65), +(3,5,30,562,1247,28,24,35,64,67), +(3,5,31,587,1300,28,24,36,66,69), +(3,5,32,613,1354,28,25,36,68,71), +(3,5,33,640,1408,28,25,37,70,72), +(3,5,34,668,1462,29,26,38,71,74), +(3,5,35,697,1516,29,26,38,73,76), +(3,5,36,727,1570,29,26,39,75,78), +(3,5,37,758,1624,29,27,39,77,80), +(3,5,38,790,1678,30,27,40,78,82), +(3,5,39,823,1732,30,27,40,80,84), +(3,5,40,857,1786,30,28,41,82,86), +(3,5,41,892,1840,31,28,41,84,88), +(3,5,42,928,1894,31,29,42,86,89), +(3,5,43,965,1948,31,29,43,88,91), +(3,5,44,1003,2002,32,29,43,90,93), +(3,5,45,1042,2056,32,30,44,92,95), +(3,5,46,1082,2110,32,30,44,93,97), +(3,5,47,1123,2164,32,30,45,95,99), +(3,5,48,1165,2218,33,31,46,97,101), +(3,5,49,1208,2272,33,31,46,99,103), +(3,5,50,1252,2326,33,32,47,101,106), +(3,5,51,1297,2380,34,32,48,103,108), +(3,5,52,1343,2434,34,33,48,105,110), +(3,5,53,1390,2488,35,33,49,107,112), +(3,5,54,1438,2542,35,33,50,109,114), +(3,5,55,1487,2596,35,34,50,111,116), +(3,5,56,1537,2650,36,34,51,113,118), +(3,5,57,1588,2704,36,35,52,116,120), +(3,5,58,1640,2758,36,35,52,118,123), +(3,5,59,1693,2812,37,36,53,120,125), +(3,5,60,1747,2866,37,36,54,122,127), +(3,5,61,1917,3035,37,37,54,124,129), +(3,5,62,2095,3189,38,37,55,126,131), +(3,5,63,2281,3358,38,38,56,128,134), +(3,5,64,2475,3512,39,38,57,131,136), +(3,5,65,2677,3681,39,39,57,133,138), +(3,5,66,2888,3835,39,39,58,135,141), +(3,5,67,3108,4004,40,40,59,137,143), +(3,5,68,3337,4158,40,40,59,139,145), +(3,5,69,3575,4327,41,40,60,142,148), +(3,5,70,3822,4496,41,41,61,144,150), +(4,1,1,50,0,20,25,21,20,20), +(4,1,2,69,0,21,26,22,20,20), +(4,1,3,88,0,23,27,23,20,21), +(4,1,4,107,0,24,27,25,20,21), +(4,1,5,126,0,25,28,26,20,21), +(4,1,6,145,0,27,29,27,20,21), +(4,1,7,164,0,28,30,28,21,22), +(4,1,8,183,0,29,31,29,21,22), +(4,1,9,202,0,31,31,31,21,22), +(4,1,10,221,0,32,32,32,21,23), +(4,1,11,240,0,33,33,33,21,23), +(4,1,12,259,0,35,34,34,21,23), +(4,1,13,278,0,36,35,36,21,24), +(4,1,14,298,0,38,36,37,21,24), +(4,1,15,319,0,39,37,38,21,24), +(4,1,16,341,0,41,37,40,21,25), +(4,1,17,364,0,42,38,41,22,25), +(4,1,18,388,0,44,39,43,22,25), +(4,1,19,413,0,45,40,44,22,26), +(4,1,20,439,0,47,41,45,22,26), +(4,1,21,466,0,48,42,47,22,26), +(4,1,22,494,0,50,43,48,22,27), +(4,1,23,523,0,52,44,50,22,27), +(4,1,24,553,0,53,45,51,23,28), +(4,1,25,584,0,55,46,52,23,28), +(4,1,26,616,0,56,47,54,23,28), +(4,1,27,649,0,58,48,55,23,29), +(4,1,28,683,0,60,49,57,23,29), +(4,1,29,718,0,61,50,58,23,30), +(4,1,30,754,0,63,51,60,24,30), +(4,1,31,791,0,65,52,62,24,30), +(4,1,32,829,0,66,53,63,24,31), +(4,1,33,868,0,68,54,65,24,31), +(4,1,34,908,0,70,55,66,24,32), +(4,1,35,949,0,72,56,68,24,32), +(4,1,36,991,0,73,58,69,25,33), +(4,1,37,1035,0,75,59,71,25,33), +(4,1,38,1081,0,77,60,73,25,34), +(4,1,39,1129,0,79,61,74,25,34), +(4,1,40,1179,0,81,62,76,25,35), +(4,1,41,1231,0,82,63,78,26,35), +(4,1,42,1285,0,84,64,79,26,35), +(4,1,43,1341,0,86,66,81,26,36), +(4,1,44,1399,0,88,67,83,26,36), +(4,1,45,1459,0,90,68,85,26,37), +(4,1,46,1521,0,92,69,86,27,37), +(4,1,47,1585,0,94,70,88,27,38), +(4,1,48,1651,0,96,72,90,27,38), +(4,1,49,1719,0,98,73,92,27,39), +(4,1,50,1789,0,100,74,93,28,40), +(4,1,51,1861,0,102,75,95,28,40), +(4,1,52,1935,0,104,77,97,28,41), +(4,1,53,2011,0,106,78,99,28,41), +(4,1,54,2089,0,108,79,101,29,42), +(4,1,55,2169,0,110,80,103,29,42), +(4,1,56,2251,0,112,82,104,29,43), +(4,1,57,2335,0,114,83,106,29,43), +(4,1,58,2421,0,116,84,108,30,44), +(4,1,59,2509,0,118,86,110,30,44), +(4,1,60,2599,0,120,87,112,30,45), +(4,1,61,2832,0,122,88,114,30,46), +(4,1,62,3079,0,124,90,116,31,46), +(4,1,63,3340,0,127,91,118,31,47), +(4,1,64,3615,0,129,92,120,31,47), +(4,1,65,3905,0,131,94,122,32,48), +(4,1,66,4210,0,133,95,124,32,49), +(4,1,67,4530,0,135,97,126,32,49), +(4,1,68,4866,0,138,98,128,32,50), +(4,1,69,5218,0,140,100,130,33,50), +(4,1,70,5586,0,142,101,132,33,51), +(4,3,1,46,85,17,28,20,20,21), +(4,3,2,63,105,17,29,21,21,22), +(4,3,3,80,126,18,31,22,21,22), +(4,3,4,97,148,18,32,23,22,23), +(4,3,5,114,171,19,33,24,22,24), +(4,3,6,131,195,19,35,25,23,24), +(4,3,7,148,220,20,36,26,24,25), +(4,3,8,165,246,20,38,27,24,25), +(4,3,9,182,273,21,39,27,25,26), +(4,3,10,199,301,21,40,28,25,27), +(4,3,11,216,330,22,42,29,26,28), +(4,3,12,233,360,22,43,30,27,28), +(4,3,13,250,391,23,45,31,27,29), +(4,3,14,268,423,23,46,32,28,30), +(4,3,15,287,456,24,48,34,29,30), +(4,3,16,307,490,24,50,35,29,31), +(4,3,17,328,525,25,51,36,30,32), +(4,3,18,350,561,25,53,37,31,33), +(4,3,19,373,598,26,54,38,31,33), +(4,3,20,397,636,26,56,39,32,34), +(4,3,21,422,675,27,57,40,33,35), +(4,3,22,448,715,27,59,41,33,36), +(4,3,23,475,756,28,61,42,34,36), +(4,3,24,503,798,28,62,43,35,37), +(4,3,25,532,841,29,64,44,36,38), +(4,3,26,562,885,30,66,46,36,39), +(4,3,27,593,930,30,68,47,37,40), +(4,3,28,625,975,31,69,48,38,41), +(4,3,29,658,1020,31,71,49,39,41), +(4,3,30,692,1065,32,73,50,39,42), +(4,3,31,727,1110,33,75,52,40,43), +(4,3,32,763,1155,33,76,53,41,44), +(4,3,33,800,1200,34,78,54,42,45), +(4,3,34,838,1245,34,80,55,43,46), +(4,3,35,877,1290,35,82,57,44,47), +(4,3,36,917,1335,36,84,58,44,48), +(4,3,37,958,1380,36,86,59,45,48), +(4,3,38,1000,1425,37,87,60,46,49), +(4,3,39,1043,1470,38,89,62,47,50), +(4,3,40,1087,1515,38,91,63,48,51), +(4,3,41,1132,1560,39,93,64,49,52), +(4,3,42,1178,1605,40,95,66,49,53), +(4,3,43,1225,1650,40,97,67,50,54), +(4,3,44,1273,1695,41,99,68,51,55), +(4,3,45,1322,1740,42,101,70,52,56), +(4,3,46,1372,1785,42,103,71,53,57), +(4,3,47,1423,1830,43,105,72,54,58), +(4,3,48,1475,1875,44,107,74,55,59), +(4,3,49,1528,1920,45,109,75,56,60), +(4,3,50,1582,1965,45,111,77,57,61), +(4,3,51,1637,2010,46,113,78,58,62), +(4,3,52,1693,2055,47,115,79,59,63), +(4,3,53,1750,2100,47,118,81,60,64), +(4,3,54,1808,2145,48,120,82,61,65), +(4,3,55,1867,2190,49,122,84,61,66), +(4,3,56,1927,2235,50,124,85,62,67), +(4,3,57,1988,2280,50,126,87,63,68), +(4,3,58,2050,2325,51,128,88,64,69), +(4,3,59,2113,2370,52,131,90,65,70), +(4,3,60,2177,2415,53,133,91,66,72), +(4,3,61,2363,2596,54,135,93,67,73), +(4,3,62,2558,2777,54,137,94,69,74), +(4,3,63,2762,2958,55,140,96,70,75), +(4,3,64,2975,3139,56,142,97,71,76), +(4,3,65,3197,3335,57,144,99,72,77), +(4,3,66,3429,3516,58,147,101,73,78), +(4,3,67,3671,3697,58,149,102,74,79), +(4,3,68,3923,3878,59,151,104,75,81), +(4,3,69,4185,4059,60,154,105,76,82), +(4,3,70,4458,4255,61,156,107,77,83), +(4,4,1,45,0,18,28,20,20,20), +(4,4,2,62,0,19,29,21,20,20), +(4,4,3,79,0,20,31,21,20,21), +(4,4,4,96,0,20,32,22,20,21), +(4,4,5,113,0,21,34,23,21,21), +(4,4,6,130,0,22,35,24,21,22), +(4,4,7,147,0,23,37,24,21,22), +(4,4,8,164,0,24,38,25,21,23), +(4,4,9,181,0,24,40,26,21,23), +(4,4,10,198,0,25,41,26,21,23), +(4,4,11,215,0,26,43,27,22,24), +(4,4,12,232,0,27,44,28,22,24), +(4,4,13,249,0,28,46,29,22,25), +(4,4,14,266,0,29,48,30,22,25), +(4,4,15,283,0,29,49,30,22,25), +(4,4,16,301,0,30,51,31,23,26), +(4,4,17,320,0,31,52,32,23,26), +(4,4,18,340,0,32,54,33,23,27), +(4,4,19,361,0,33,56,34,23,27), +(4,4,20,383,0,34,57,35,23,28), +(4,4,21,406,0,35,59,35,24,28), +(4,4,22,430,0,36,61,36,24,29), +(4,4,23,455,0,37,63,37,24,29), +(4,4,24,481,0,38,64,38,24,30), +(4,4,25,508,0,39,66,39,25,30), +(4,4,26,536,0,40,68,40,25,31), +(4,4,27,565,0,41,70,41,25,31), +(4,4,28,595,0,42,72,42,25,32), +(4,4,29,626,0,43,73,43,25,32), +(4,4,30,658,0,44,75,43,26,33), +(4,4,31,691,0,45,77,44,26,33), +(4,4,32,725,0,46,79,45,26,34), +(4,4,33,760,0,47,81,46,27,34), +(4,4,34,796,0,48,83,47,27,35), +(4,4,35,833,0,49,85,48,27,35), +(4,4,36,871,0,50,87,49,27,36), +(4,4,37,910,0,51,89,50,28,36), +(4,4,38,950,0,52,91,51,28,37), +(4,4,39,991,0,53,93,52,28,38), +(4,4,40,1033,0,54,95,53,28,38), +(4,4,41,1076,0,56,97,54,29,39), +(4,4,42,1120,0,57,99,55,29,39), +(4,4,43,1165,0,58,101,56,29,40), +(4,4,44,1211,0,59,103,57,30,40), +(4,4,45,1258,0,60,105,59,30,41), +(4,4,46,1306,0,61,107,60,30,42), +(4,4,47,1355,0,62,109,61,31,42), +(4,4,48,1405,0,64,112,62,31,43), +(4,4,49,1456,0,65,114,63,31,44), +(4,4,50,1508,0,66,116,64,32,44), +(4,4,51,1561,0,67,118,65,32,45), +(4,4,52,1615,0,68,120,66,32,45), +(4,4,53,1670,0,70,123,67,33,46), +(4,4,54,1726,0,71,125,69,33,47), +(4,4,55,1783,0,72,127,70,33,47), +(4,4,56,1841,0,73,129,71,34,48), +(4,4,57,1900,0,75,132,72,34,49), +(4,4,58,1960,0,76,134,73,34,49), +(4,4,59,2021,0,77,136,74,35,50), +(4,4,60,2083,0,79,139,76,35,51), +(4,4,61,2272,0,80,141,77,35,51), +(4,4,62,2470,0,81,143,78,36,52), +(4,4,63,2677,0,82,146,79,36,53), +(4,4,64,2893,0,84,148,80,37,54), +(4,4,65,3119,0,85,151,82,37,54), +(4,4,66,3355,0,87,153,83,37,55), +(4,4,67,3601,0,88,156,84,38,56), +(4,4,68,3858,0,89,158,85,38,57), +(4,4,69,4126,0,91,160,87,39,57), +(4,4,70,4405,0,92,163,88,39,58), +(4,5,1,51,160,17,25,19,22,23), +(4,5,2,66,184,17,25,19,23,24), +(4,5,3,81,209,17,25,20,25,26), +(4,5,4,96,235,17,26,20,26,27), +(4,5,5,111,262,18,26,20,27,28), +(4,5,6,126,290,18,26,21,29,30), +(4,5,7,141,319,18,26,21,30,31), +(4,5,8,156,349,18,26,22,31,33), +(4,5,9,171,380,18,27,22,33,34), +(4,5,10,186,412,19,27,22,34,36), +(4,5,11,201,445,19,27,23,36,37), +(4,5,12,216,479,19,27,23,37,39), +(4,5,13,231,514,19,28,24,38,40), +(4,5,14,246,550,19,28,24,40,42), +(4,5,15,261,587,19,28,25,41,43), +(4,5,16,276,625,20,28,25,43,45), +(4,5,17,291,664,20,29,25,44,46), +(4,5,18,306,704,20,29,26,46,48), +(4,5,19,321,745,20,29,26,47,49), +(4,5,20,336,787,21,30,27,49,51), +(4,5,21,351,830,21,30,27,51,53), +(4,5,22,367,874,21,30,28,52,54), +(4,5,23,384,919,21,30,28,54,56), +(4,5,24,402,965,21,31,29,55,58), +(4,5,25,421,1012,22,31,29,57,59), +(4,5,26,441,1060,22,31,30,59,61), +(4,5,27,462,1109,22,32,30,60,63), +(4,5,28,484,1159,22,32,31,62,65), +(4,5,29,507,1210,23,32,31,64,66), +(4,5,30,531,1262,23,33,32,65,68), +(4,5,31,556,1315,23,33,32,67,70), +(4,5,32,582,1369,23,33,33,69,72), +(4,5,33,609,1423,24,34,33,70,73), +(4,5,34,637,1477,24,34,34,72,75), +(4,5,35,666,1531,24,34,34,74,77), +(4,5,36,696,1585,24,35,35,76,79), +(4,5,37,727,1639,25,35,35,78,81), +(4,5,38,759,1693,25,35,36,79,83), +(4,5,39,792,1747,25,36,37,81,85), +(4,5,40,826,1801,26,36,37,83,87), +(4,5,41,861,1855,26,37,38,85,88), +(4,5,42,897,1909,26,37,38,87,90), +(4,5,43,934,1963,27,37,39,89,92), +(4,5,44,972,2017,27,38,39,91,94), +(4,5,45,1011,2071,27,38,40,92,96), +(4,5,46,1051,2125,27,39,41,94,98), +(4,5,47,1092,2179,28,39,41,96,100), +(4,5,48,1134,2233,28,39,42,98,102), +(4,5,49,1177,2287,28,40,43,100,104), +(4,5,50,1221,2341,29,40,43,102,106), +(4,5,51,1266,2395,29,41,44,104,109), +(4,5,52,1312,2449,29,41,44,106,111), +(4,5,53,1359,2503,30,42,45,108,113), +(4,5,54,1407,2557,30,42,46,110,115), +(4,5,55,1456,2611,30,43,46,112,117), +(4,5,56,1506,2665,31,43,47,114,119), +(4,5,57,1557,2719,31,43,48,117,121), +(4,5,58,1609,2773,31,44,48,119,124), +(4,5,59,1662,2827,32,44,49,121,126), +(4,5,60,1716,2881,32,45,50,123,128), +(4,5,61,1886,3050,33,45,51,125,130), +(4,5,62,2064,3204,33,46,51,127,132), +(4,5,63,2250,3373,33,46,52,129,135), +(4,5,64,2444,3527,34,47,53,132,137), +(4,5,65,2646,3696,34,47,53,134,139), +(4,5,66,2857,3850,34,48,54,136,142), +(4,5,67,3077,4019,35,48,55,138,144), +(4,5,68,3306,4173,35,49,56,140,146), +(4,5,69,3544,4342,36,49,56,143,149), +(4,5,70,3791,4511,36,50,57,145,151), +(4,11,1,53,100,18,25,19,22,22), +(4,11,2,70,122,19,25,20,23,23), +(4,11,3,87,145,19,26,20,24,24), +(4,11,4,104,169,20,26,21,25,26), +(4,11,5,121,194,20,27,22,26,27), +(4,11,6,138,220,21,27,22,27,28), +(4,11,7,155,247,21,28,23,28,29), +(4,11,8,172,275,22,28,24,29,30), +(4,11,9,189,304,23,29,24,30,32), +(4,11,10,206,334,23,29,25,32,33), +(4,11,11,223,365,24,30,26,33,34), +(4,11,12,240,397,24,31,26,34,35), +(4,11,13,257,430,25,31,27,35,37), +(4,11,14,274,464,26,32,28,36,38), +(4,11,15,291,499,26,32,29,37,39), +(4,11,16,308,535,27,33,29,38,41), +(4,11,17,325,572,28,33,30,40,42), +(4,11,18,343,610,28,34,31,41,43), +(4,11,19,362,649,29,35,32,42,45), +(4,11,20,382,689,30,35,32,43,46), +(4,11,21,403,730,30,36,33,45,48), +(4,11,22,425,772,31,36,34,46,49), +(4,11,23,448,815,32,37,35,47,51), +(4,11,24,472,859,32,38,36,48,52), +(4,11,25,497,904,33,38,36,50,53), +(4,11,26,523,949,34,39,37,51,55), +(4,11,27,550,994,35,40,38,52,56), +(4,11,28,578,1039,35,40,39,54,58), +(4,11,29,607,1084,36,41,40,55,59), +(4,11,30,637,1129,37,42,41,56,61), +(4,11,31,668,1174,38,42,42,58,62), +(4,11,32,700,1219,38,43,42,59,64), +(4,11,33,733,1264,39,44,43,60,66), +(4,11,34,767,1309,40,44,44,62,67), +(4,11,35,802,1354,41,45,45,63,69), +(4,11,36,838,1399,42,46,46,65,70), +(4,11,37,875,1444,42,47,47,66,72), +(4,11,38,913,1489,43,47,48,67,74), +(4,11,39,952,1534,44,48,49,69,75), +(4,11,40,992,1579,45,49,50,70,77), +(4,11,41,1033,1624,46,50,51,72,79), +(4,11,42,1075,1669,46,50,52,73,80), +(4,11,43,1118,1714,47,51,53,75,82), +(4,11,44,1162,1759,48,52,54,76,84), +(4,11,45,1207,1804,49,53,55,78,85), +(4,11,46,1253,1849,50,54,56,79,87), +(4,11,47,1300,1894,51,54,57,81,89), +(4,11,48,1348,1939,52,55,58,83,91), +(4,11,49,1397,1984,53,56,59,84,93), +(4,11,50,1447,2029,53,57,60,86,94), +(4,11,51,1498,2074,54,58,61,87,96), +(4,11,52,1550,2119,55,59,62,89,98), +(4,11,53,1603,2164,56,59,63,91,100), +(4,11,54,1657,2209,57,60,64,92,102), +(4,11,55,1712,2254,58,61,65,94,103), +(4,11,56,1768,2299,59,62,66,95,105), +(4,11,57,1825,2344,60,63,67,97,107), +(4,11,58,1883,2389,61,64,68,99,109), +(4,11,59,1942,2434,62,65,69,101,111), +(4,11,60,2002,2479,63,66,70,102,113), +(4,11,61,2177,2607,64,66,72,104,115), +(4,11,62,2363,2750,65,67,73,106,117), +(4,11,63,2560,2893,66,68,74,107,119), +(4,11,64,2768,3036,67,69,75,109,121), +(4,11,65,2987,3179,68,70,76,111,123), +(4,11,66,3217,3322,69,71,77,113,125), +(4,11,67,3459,3465,70,72,78,115,127), +(4,11,68,3713,3608,71,73,80,116,129), +(4,11,69,3979,3751,72,74,81,118,131), +(4,11,70,4257,3894,73,75,82,120,133), +(5,1,1,70,0,22,18,23,18,25), +(5,1,2,89,0,23,19,24,18,25), +(5,1,3,108,0,25,20,25,18,26), +(5,1,4,127,0,26,20,26,18,26), +(5,1,5,146,0,27,21,28,18,26), +(5,1,6,165,0,29,22,29,18,26), +(5,1,7,184,0,30,23,30,19,27), +(5,1,8,203,0,31,24,31,19,27), +(5,1,9,222,0,33,25,33,19,27), +(5,1,10,241,0,34,25,34,19,28), +(5,1,11,260,0,35,26,35,19,28), +(5,1,12,279,0,37,27,36,19,28), +(5,1,13,298,0,38,28,38,19,28), +(5,1,14,318,0,40,29,39,19,29), +(5,1,15,339,0,41,30,40,19,29), +(5,1,16,361,0,43,31,42,20,29), +(5,1,17,384,0,44,32,43,20,30), +(5,1,18,408,0,46,33,44,20,30), +(5,1,19,433,0,47,34,46,20,31), +(5,1,20,459,0,49,34,47,20,31), +(5,1,21,486,0,50,35,49,20,31), +(5,1,22,514,0,52,36,50,20,32), +(5,1,23,543,0,53,37,51,21,32), +(5,1,24,573,0,55,38,53,21,32), +(5,1,25,604,0,57,39,54,21,33), +(5,1,26,636,0,58,40,56,21,33), +(5,1,27,669,0,60,41,57,21,34), +(5,1,28,703,0,62,42,59,21,34), +(5,1,29,738,0,63,43,60,21,34), +(5,1,30,774,0,65,44,62,22,35), +(5,1,31,811,0,67,46,63,22,35), +(5,1,32,849,0,68,47,65,22,36), +(5,1,33,888,0,70,48,67,22,36), +(5,1,34,928,0,72,49,68,22,36), +(5,1,35,969,0,74,50,70,23,37), +(5,1,36,1011,0,75,51,71,23,37), +(5,1,37,1055,0,77,52,73,23,38), +(5,1,38,1101,0,79,53,75,23,38), +(5,1,39,1149,0,81,54,76,23,39), +(5,1,40,1199,0,83,55,78,24,39), +(5,1,41,1251,0,84,57,80,24,40), +(5,1,42,1305,0,86,58,81,24,40), +(5,1,43,1361,0,88,59,83,24,41), +(5,1,44,1419,0,90,60,85,24,41), +(5,1,45,1479,0,92,61,86,25,42), +(5,1,46,1541,0,94,62,88,25,42), +(5,1,47,1605,0,96,64,90,25,43), +(5,1,48,1671,0,98,65,92,25,43), +(5,1,49,1739,0,100,66,93,25,44), +(5,1,50,1809,0,102,67,95,26,44), +(5,1,51,1881,0,104,69,97,26,45), +(5,1,52,1955,0,106,70,99,26,45), +(5,1,53,2031,0,108,71,101,26,46), +(5,1,54,2109,0,110,72,103,27,46), +(5,1,55,2189,0,112,74,104,27,47), +(5,1,56,2271,0,114,75,106,27,48), +(5,1,57,2355,0,116,76,108,27,48), +(5,1,58,2441,0,118,78,110,28,49), +(5,1,59,2529,0,120,79,112,28,49), +(5,1,60,2619,0,122,80,114,28,50), +(5,1,61,2852,0,124,82,116,28,50), +(5,1,62,3099,0,126,83,118,29,51), +(5,1,63,3360,0,128,84,120,29,52), +(5,1,64,3635,0,131,86,122,29,52), +(5,1,65,3925,0,133,87,124,30,53), +(5,1,66,4230,0,135,88,126,30,53), +(5,1,67,4550,0,137,90,128,30,54), +(5,1,68,4886,0,139,91,130,30,55), +(5,1,69,5238,0,142,93,132,31,55), +(5,1,70,5606,0,144,94,134,31,56), +(5,4,1,65,0,20,21,22,18,25), +(5,4,2,82,0,21,22,23,18,25), +(5,4,3,99,0,22,24,23,18,26), +(5,4,4,116,0,22,25,24,18,26), +(5,4,5,133,0,23,27,25,19,26), +(5,4,6,150,0,24,28,25,19,27), +(5,4,7,167,0,25,30,26,19,27), +(5,4,8,184,0,25,31,27,19,27), +(5,4,9,201,0,26,33,28,19,28), +(5,4,10,218,0,27,34,28,19,28), +(5,4,11,235,0,28,36,29,20,29), +(5,4,12,252,0,29,38,30,20,29), +(5,4,13,269,0,30,39,31,20,29), +(5,4,14,286,0,31,41,32,20,30), +(5,4,15,303,0,31,42,32,20,30), +(5,4,16,321,0,32,44,33,21,31), +(5,4,17,340,0,33,46,34,21,31), +(5,4,18,360,0,34,47,35,21,32), +(5,4,19,381,0,35,49,36,21,32), +(5,4,20,403,0,36,51,36,21,32), +(5,4,21,426,0,37,52,37,22,33), +(5,4,22,450,0,38,54,38,22,33), +(5,4,23,475,0,39,56,39,22,34), +(5,4,24,501,0,40,58,40,22,34), +(5,4,25,528,0,41,60,41,23,35), +(5,4,26,556,0,42,61,42,23,35), +(5,4,27,585,0,43,63,43,23,36), +(5,4,28,615,0,44,65,44,23,36), +(5,4,29,646,0,45,67,44,24,37), +(5,4,30,678,0,46,69,45,24,37), +(5,4,31,711,0,47,71,46,24,38), +(5,4,32,745,0,48,72,47,24,38), +(5,4,33,780,0,49,74,48,25,39), +(5,4,34,816,0,50,76,49,25,39), +(5,4,35,853,0,51,78,50,25,40), +(5,4,36,891,0,52,80,51,25,41), +(5,4,37,930,0,53,82,52,26,41), +(5,4,38,970,0,54,84,53,26,42), +(5,4,39,1011,0,55,86,54,26,42), +(5,4,40,1053,0,56,88,55,27,43), +(5,4,41,1096,0,57,90,56,27,43), +(5,4,42,1140,0,59,92,57,27,44), +(5,4,43,1185,0,60,94,58,27,45), +(5,4,44,1231,0,61,96,59,28,45), +(5,4,45,1278,0,62,99,60,28,46), +(5,4,46,1326,0,63,101,61,28,46), +(5,4,47,1375,0,64,103,63,29,47), +(5,4,48,1425,0,66,105,64,29,48), +(5,4,49,1476,0,67,107,65,29,48), +(5,4,50,1528,0,68,109,66,30,49), +(5,4,51,1581,0,69,111,67,30,50), +(5,4,52,1635,0,70,114,68,30,50), +(5,4,53,1690,0,72,116,69,31,51), +(5,4,54,1746,0,73,118,70,31,52), +(5,4,55,1803,0,74,120,72,31,52), +(5,4,56,1861,0,75,123,73,32,53), +(5,4,57,1920,0,77,125,74,32,54), +(5,4,58,1980,0,78,127,75,32,54), +(5,4,59,2041,0,79,130,76,33,55), +(5,4,60,2103,0,81,132,77,33,56), +(5,4,61,2292,0,82,134,79,34,56), +(5,4,62,2490,0,83,137,80,34,57), +(5,4,63,2697,0,84,139,81,34,58), +(5,4,64,2913,0,86,141,82,35,59), +(5,4,65,3139,0,87,144,84,35,59), +(5,4,66,3375,0,88,146,85,35,60), +(5,4,67,3621,0,90,149,86,36,61), +(5,4,68,3878,0,91,151,87,36,61), +(5,4,69,4146,0,93,154,89,37,62), +(5,4,70,4425,0,94,156,90,37,63), +(5,5,1,62,130,19,18,21,20,28), +(5,5,2,77,154,19,18,21,21,29), +(5,5,3,92,179,19,18,22,23,31), +(5,5,4,107,205,19,19,22,24,32), +(5,5,5,122,232,20,19,22,25,33), +(5,5,6,137,260,20,19,23,27,35), +(5,5,7,152,289,20,19,23,28,36), +(5,5,8,167,319,20,20,24,29,38), +(5,5,9,182,350,20,20,24,31,39), +(5,5,10,197,382,20,20,24,32,40), +(5,5,11,212,415,21,20,25,34,42), +(5,5,12,227,449,21,21,25,35,43), +(5,5,13,242,484,21,21,26,37,45), +(5,5,14,257,520,21,21,26,38,46), +(5,5,15,272,557,21,21,26,39,48), +(5,5,16,287,595,22,22,27,41,50), +(5,5,17,302,634,22,22,27,42,51), +(5,5,18,317,674,22,22,28,44,53), +(5,5,19,332,715,22,23,28,46,54), +(5,5,20,347,757,22,23,29,47,56), +(5,5,21,362,800,23,23,29,49,57), +(5,5,22,378,844,23,23,30,50,59), +(5,5,23,395,889,23,24,30,52,61), +(5,5,24,413,935,23,24,31,53,62), +(5,5,25,432,982,24,24,31,55,64), +(5,5,26,452,1030,24,25,32,57,66), +(5,5,27,473,1079,24,25,32,58,68), +(5,5,28,495,1129,24,25,33,60,69), +(5,5,29,518,1180,25,26,33,62,71), +(5,5,30,542,1232,25,26,34,63,73), +(5,5,31,567,1285,25,26,34,65,75), +(5,5,32,593,1339,25,27,35,67,76), +(5,5,33,620,1393,26,27,35,69,78), +(5,5,34,648,1447,26,27,36,70,80), +(5,5,35,677,1501,26,28,36,72,82), +(5,5,36,707,1555,26,28,37,74,84), +(5,5,37,738,1609,27,28,37,76,86), +(5,5,38,770,1663,27,29,38,77,87), +(5,5,39,803,1717,27,29,38,79,89), +(5,5,40,837,1771,28,30,39,81,91), +(5,5,41,872,1825,28,30,40,83,93), +(5,5,42,908,1879,28,30,40,85,95), +(5,5,43,945,1933,28,31,41,87,97), +(5,5,44,983,1987,29,31,41,89,99), +(5,5,45,1022,2041,29,32,42,91,101), +(5,5,46,1062,2095,29,32,43,92,103), +(5,5,47,1103,2149,30,32,43,94,105), +(5,5,48,1145,2203,30,33,44,96,107), +(5,5,49,1188,2257,30,33,44,98,109), +(5,5,50,1232,2311,31,34,45,100,111), +(5,5,51,1277,2365,31,34,46,102,113), +(5,5,52,1323,2419,31,35,46,104,115), +(5,5,53,1370,2473,32,35,47,106,118), +(5,5,54,1418,2527,32,35,48,108,120), +(5,5,55,1467,2581,32,36,48,110,122), +(5,5,56,1517,2635,33,36,49,113,124), +(5,5,57,1568,2689,33,37,50,115,126), +(5,5,58,1620,2743,33,37,50,117,128), +(5,5,59,1673,2797,34,38,51,119,131), +(5,5,60,1727,2851,34,38,52,121,133), +(5,5,61,1897,3020,34,39,52,123,135), +(5,5,62,2075,3174,35,39,53,125,137), +(5,5,63,2261,3343,35,40,54,127,140), +(5,5,64,2455,3497,36,40,55,130,142), +(5,5,65,2657,3666,36,41,55,132,144), +(5,5,66,2868,3820,36,41,56,134,147), +(5,5,67,3088,3989,37,41,57,136,149), +(5,5,68,3317,4143,37,42,58,138,151), +(5,5,69,3555,4312,38,42,58,141,154), +(5,5,70,3802,4481,38,43,59,143,156), +(5,8,1,62,135,19,18,21,21,27), +(5,8,2,77,160,19,18,21,22,28), +(5,8,3,92,186,19,18,22,24,30), +(5,8,4,107,213,19,18,22,25,31), +(5,8,5,122,241,19,19,22,26,32), +(5,8,6,137,270,19,19,22,28,34), +(5,8,7,152,300,20,19,23,29,35), +(5,8,8,167,331,20,19,23,31,36), +(5,8,9,182,363,20,19,23,32,38), +(5,8,10,197,396,20,19,24,34,39), +(5,8,11,212,430,20,20,24,35,40), +(5,8,12,227,465,20,20,24,37,42), +(5,8,13,242,501,20,20,25,38,43), +(5,8,14,257,538,20,20,25,40,45), +(5,8,15,272,576,20,20,25,41,46), +(5,8,16,287,615,21,21,26,43,48), +(5,8,17,302,655,21,21,26,44,49), +(5,8,18,317,696,21,21,26,46,51), +(5,8,19,332,738,21,21,27,48,52), +(5,8,20,347,781,21,21,27,49,54), +(5,8,21,362,825,21,22,27,51,55), +(5,8,22,377,870,21,22,28,52,57), +(5,8,23,392,916,21,22,28,54,58), +(5,8,24,408,963,22,22,29,56,60), +(5,8,25,425,1011,22,23,29,57,62), +(5,8,26,443,1060,22,23,29,59,63), +(5,8,27,462,1110,22,23,30,61,65), +(5,8,28,482,1161,22,23,30,63,67), +(5,8,29,503,1212,22,24,31,64,68), +(5,8,30,525,1263,23,24,31,66,70), +(5,8,31,548,1314,23,24,31,68,72), +(5,8,32,572,1365,23,24,32,70,73), +(5,8,33,597,1416,23,25,32,72,75), +(5,8,34,623,1467,23,25,33,73,77), +(5,8,35,650,1518,24,25,33,75,79), +(5,8,36,678,1569,24,25,34,77,80), +(5,8,37,707,1620,24,26,34,79,82), +(5,8,38,737,1671,24,26,35,81,84), +(5,8,39,768,1722,24,26,35,83,86), +(5,8,40,800,1773,24,27,35,85,88), +(5,8,41,833,1824,25,27,36,87,90), +(5,8,42,867,1875,25,27,36,89,91), +(5,8,43,902,1926,25,27,37,90,93), +(5,8,44,938,1977,25,28,37,92,95), +(5,8,45,975,2028,26,28,38,94,97), +(5,8,46,1013,2079,26,28,38,96,99), +(5,8,47,1052,2130,26,29,39,98,101), +(5,8,48,1092,2181,26,29,39,100,103), +(5,8,49,1133,2232,26,29,40,103,105), +(5,8,50,1175,2283,27,30,40,105,107), +(5,8,51,1218,2334,27,30,41,107,109), +(5,8,52,1262,2385,27,30,42,109,111), +(5,8,53,1307,2436,27,31,42,111,113), +(5,8,54,1353,2487,28,31,43,113,115), +(5,8,55,1400,2538,28,31,43,115,117), +(5,8,56,1448,2589,28,32,44,117,119), +(5,8,57,1497,2640,28,32,44,119,121), +(5,8,58,1547,2691,29,32,45,122,123), +(5,8,59,1598,2742,29,33,45,124,126), +(5,8,60,1650,2793,29,33,46,126,128), +(5,8,61,1816,2926,29,34,47,128,130), +(5,8,62,1991,3074,30,34,47,131,132), +(5,8,63,2175,3207,30,34,48,133,134), +(5,8,64,2368,3355,30,35,48,135,136), +(5,8,65,2570,3488,31,35,49,137,139), +(5,8,66,2782,3636,31,35,50,140,141), +(5,8,67,3004,3769,31,36,50,142,143), +(5,8,68,3236,3917,31,36,51,144,145), +(5,8,69,3479,4050,32,37,51,147,148), +(5,8,70,3733,4198,32,37,52,149,150), +(5,9,1,63,110,19,18,22,20,27), +(5,9,2,78,133,19,18,23,21,28), +(5,9,3,93,157,20,19,23,22,29), +(5,9,4,108,182,20,19,24,24,30), +(5,9,5,123,208,20,19,24,25,32), +(5,9,6,138,235,20,20,25,26,33), +(5,9,7,153,263,21,20,25,27,34), +(5,9,8,168,292,21,21,26,28,35), +(5,9,9,183,322,21,21,26,30,36), +(5,9,10,198,353,22,21,27,31,38), +(5,9,11,213,385,22,22,28,32,39), +(5,9,12,228,418,22,22,28,34,40), +(5,9,13,243,452,23,23,29,35,41), +(5,9,14,258,487,23,23,30,36,43), +(5,9,15,273,523,23,24,30,37,44), +(5,9,16,288,560,24,24,31,39,45), +(5,9,17,303,598,24,24,31,40,47), +(5,9,18,319,637,24,25,32,42,48), +(5,9,19,336,677,25,25,33,43,49), +(5,9,20,354,718,25,26,33,44,51), +(5,9,21,373,760,26,26,34,46,52), +(5,9,22,393,803,26,27,35,47,53), +(5,9,23,414,847,26,27,36,49,55), +(5,9,24,436,892,27,28,36,50,56), +(5,9,25,459,938,27,28,37,52,58), +(5,9,26,483,985,27,29,38,53,59), +(5,9,27,508,1033,28,29,38,55,60), +(5,9,28,534,1082,28,30,39,56,62), +(5,9,29,561,1132,29,30,40,58,63), +(5,9,30,589,1183,29,31,41,59,65), +(5,9,31,618,1234,30,31,41,61,66), +(5,9,32,648,1285,30,32,42,62,68), +(5,9,33,679,1336,30,32,43,64,69), +(5,9,34,711,1387,31,33,44,65,71), +(5,9,35,744,1438,31,33,45,67,73), +(5,9,36,778,1489,32,34,45,69,74), +(5,9,37,813,1540,32,34,46,70,76), +(5,9,38,849,1591,33,35,47,72,77), +(5,9,39,886,1642,33,36,48,73,79), +(5,9,40,924,1693,34,36,49,75,81), +(5,9,41,963,1744,34,37,49,77,82), +(5,9,42,1003,1795,35,37,50,78,84), +(5,9,43,1044,1846,35,38,51,80,86), +(5,9,44,1086,1897,36,39,52,82,87), +(5,9,45,1129,1948,36,39,53,84,89), +(5,9,46,1173,1999,37,40,54,85,91), +(5,9,47,1218,2050,37,40,55,87,92), +(5,9,48,1264,2101,38,41,55,89,94), +(5,9,49,1311,2152,38,42,56,91,96), +(5,9,50,1359,2203,39,42,57,92,98), +(5,9,51,1408,2254,39,43,58,94,100), +(5,9,52,1458,2305,40,44,59,96,101), +(5,9,53,1509,2356,40,44,60,98,103), +(5,9,54,1561,2407,41,45,61,100,105), +(5,9,55,1614,2458,41,45,62,102,107), +(5,9,56,1668,2509,42,46,63,103,109), +(5,9,57,1723,2560,42,47,64,105,111), +(5,9,58,1779,2611,43,47,65,107,112), +(5,9,59,1836,2662,43,48,66,109,114), +(5,9,60,1894,2713,44,49,67,111,116), +(5,9,61,2070,2867,45,50,68,113,118), +(5,9,62,2255,3021,45,50,69,115,120), +(5,9,63,2449,3190,46,51,70,117,122), +(5,9,64,2652,3344,46,52,71,119,124), +(5,9,65,2864,3498,47,52,72,121,126), +(5,9,66,3086,3667,48,53,73,123,128), +(5,9,67,3318,3821,48,54,74,125,130), +(5,9,68,3561,3975,49,55,75,127,132), +(5,9,69,3815,4144,49,55,76,129,134), +(5,9,70,4080,4298,50,56,77,131,136), +(6,1,1,80,0,28,15,24,15,22), +(6,1,2,99,0,29,16,25,15,22), +(6,1,3,118,0,31,17,26,15,23), +(6,1,4,137,0,32,17,27,15,23), +(6,1,5,156,0,33,18,29,15,23), +(6,1,6,175,0,34,19,30,15,23), +(6,1,7,194,0,36,20,31,16,24), +(6,1,8,213,0,37,21,32,16,24), +(6,1,9,232,0,38,22,34,16,24), +(6,1,10,251,0,40,22,35,16,25), +(6,1,11,270,0,41,23,36,16,25), +(6,1,12,289,0,43,24,37,16,25), +(6,1,13,308,0,44,25,39,16,26), +(6,1,14,328,0,46,26,40,16,26), +(6,1,15,349,0,47,27,41,17,26), +(6,1,16,371,0,48,28,43,17,27), +(6,1,17,394,0,50,29,44,17,27), +(6,1,18,418,0,51,30,45,17,27), +(6,1,19,443,0,53,31,47,17,28), +(6,1,20,469,0,54,32,48,17,28), +(6,1,21,496,0,56,33,50,17,28), +(6,1,22,524,0,58,34,51,18,29), +(6,1,23,553,0,59,35,52,18,29), +(6,1,24,583,0,61,36,54,18,30), +(6,1,25,614,0,62,37,55,18,30), +(6,1,26,646,0,64,38,57,18,30), +(6,1,27,679,0,66,39,58,18,31), +(6,1,28,713,0,67,40,60,18,31), +(6,1,29,748,0,69,41,61,19,32), +(6,1,30,784,0,71,42,63,19,32), +(6,1,31,821,0,72,43,64,19,32), +(6,1,32,859,0,74,44,66,19,33), +(6,1,33,898,0,76,45,67,19,33), +(6,1,34,938,0,77,46,69,20,34), +(6,1,35,979,0,79,47,71,20,34), +(6,1,36,1021,0,81,48,72,20,35), +(6,1,37,1065,0,83,49,74,20,35), +(6,1,38,1111,0,85,50,76,20,35), +(6,1,39,1159,0,86,51,77,21,36), +(6,1,40,1209,0,88,53,79,21,36), +(6,1,41,1261,0,90,54,81,21,37), +(6,1,42,1315,0,92,55,82,21,37), +(6,1,43,1371,0,94,56,84,21,38), +(6,1,44,1429,0,96,57,86,22,38), +(6,1,45,1489,0,98,58,87,22,39), +(6,1,46,1551,0,99,60,89,22,39), +(6,1,47,1615,0,101,61,91,22,40), +(6,1,48,1681,0,103,62,93,22,40), +(6,1,49,1749,0,105,63,94,23,41), +(6,1,50,1819,0,107,65,96,23,41), +(6,1,51,1891,0,109,66,98,23,42), +(6,1,52,1965,0,111,67,100,23,42), +(6,1,53,2041,0,113,68,102,24,43), +(6,1,54,2119,0,115,70,104,24,44), +(6,1,55,2199,0,117,71,105,24,44), +(6,1,56,2281,0,119,72,107,24,45), +(6,1,57,2365,0,122,73,109,25,45), +(6,1,58,2451,0,124,75,111,25,46), +(6,1,59,2539,0,126,76,113,25,46), +(6,1,60,2629,0,128,77,115,25,47), +(6,1,61,2862,0,130,79,117,26,48), +(6,1,62,3109,0,132,80,119,26,48), +(6,1,63,3370,0,134,81,121,26,49), +(6,1,64,3645,0,137,83,123,26,49), +(6,1,65,3935,0,139,84,125,27,50), +(6,1,66,4240,0,141,85,127,27,51), +(6,1,67,4560,0,143,87,129,27,51), +(6,1,68,4896,0,145,88,131,27,52), +(6,1,69,5248,0,148,90,133,28,52), +(6,1,70,5616,0,150,91,135,28,53), +(6,3,1,76,80,25,18,23,15,23), +(6,3,2,93,100,25,19,24,16,24), +(6,3,3,110,121,26,21,25,16,24), +(6,3,4,127,143,26,22,26,17,25), +(6,3,5,144,166,27,24,27,17,25), +(6,3,6,161,190,27,25,28,18,26), +(6,3,7,178,215,28,26,28,19,27), +(6,3,8,195,241,28,28,29,19,27), +(6,3,9,212,268,28,29,30,20,28), +(6,3,10,229,296,29,31,31,20,29), +(6,3,11,246,325,29,32,32,21,29), +(6,3,12,263,355,30,34,33,22,30), +(6,3,13,280,386,30,35,34,22,31), +(6,3,14,298,418,31,37,35,23,32), +(6,3,15,317,451,31,38,36,24,32), +(6,3,16,337,485,32,40,37,24,33), +(6,3,17,358,520,32,41,39,25,34), +(6,3,18,380,556,33,43,40,26,35), +(6,3,19,403,593,33,45,41,27,35), +(6,3,20,427,631,34,46,42,27,36), +(6,3,21,452,670,34,48,43,28,37), +(6,3,22,478,710,35,50,44,29,38), +(6,3,23,505,751,35,51,45,29,38), +(6,3,24,533,793,36,53,46,30,39), +(6,3,25,562,836,37,55,47,31,40), +(6,3,26,592,880,37,56,48,32,41), +(6,3,27,623,925,38,58,50,32,42), +(6,3,28,655,970,38,60,51,33,42), +(6,3,29,688,1015,39,62,52,34,43), +(6,3,30,722,1060,39,63,53,35,44), +(6,3,31,757,1105,40,65,54,36,45), +(6,3,32,793,1150,41,67,56,36,46), +(6,3,33,830,1195,41,69,57,37,47), +(6,3,34,868,1240,42,71,58,38,48), +(6,3,35,907,1285,43,72,59,39,48), +(6,3,36,947,1330,43,74,61,40,49), +(6,3,37,988,1375,44,76,62,40,50), +(6,3,38,1030,1420,45,78,63,41,51), +(6,3,39,1073,1465,45,80,64,42,52), +(6,3,40,1117,1510,46,82,66,43,53), +(6,3,41,1162,1555,47,84,67,44,54), +(6,3,42,1208,1600,47,86,68,45,55), +(6,3,43,1255,1645,48,88,70,46,56), +(6,3,44,1303,1690,49,90,71,46,57), +(6,3,45,1352,1735,49,92,72,47,58), +(6,3,46,1402,1780,50,94,74,48,59), +(6,3,47,1453,1825,51,96,75,49,60), +(6,3,48,1505,1870,51,98,77,50,61), +(6,3,49,1558,1915,52,100,78,51,62), +(6,3,50,1612,1960,53,102,79,52,63), +(6,3,51,1667,2005,54,104,81,53,64), +(6,3,52,1723,2050,54,106,82,54,65), +(6,3,53,1780,2095,55,108,84,55,66), +(6,3,54,1838,2140,56,110,85,56,67), +(6,3,55,1897,2185,57,112,87,57,68), +(6,3,56,1957,2230,57,114,88,58,69), +(6,3,57,2018,2275,58,117,90,59,70), +(6,3,58,2080,2320,59,119,91,60,71), +(6,3,59,2143,2365,60,121,93,61,72), +(6,3,60,2207,2410,61,123,94,62,74), +(6,3,61,2393,2591,61,125,96,63,75), +(6,3,62,2588,2772,62,128,97,64,76), +(6,3,63,2792,2953,63,130,99,65,77), +(6,3,64,3005,3134,64,132,100,66,78), +(6,3,65,3227,3330,65,134,102,67,79), +(6,3,66,3459,3511,66,137,104,68,80), +(6,3,67,3701,3692,66,139,105,69,81), +(6,3,68,3953,3873,67,141,107,70,83), +(6,3,69,4215,4054,68,144,108,71,84), +(6,3,70,4488,4250,69,146,110,72,85), +(6,7,1,77,71,26,15,23,16,24), +(6,7,2,94,92,27,15,24,17,25), +(6,7,3,111,114,28,16,25,18,26), +(6,7,4,128,137,28,16,26,19,27), +(6,7,5,145,161,29,17,27,20,28), +(6,7,6,162,186,30,17,28,21,29), +(6,7,7,179,212,31,18,29,22,30), +(6,7,8,196,239,32,18,30,23,31), +(6,7,9,213,267,33,19,31,24,32), +(6,7,10,230,296,34,19,32,25,33), +(6,7,11,247,326,35,20,33,26,35), +(6,7,12,264,357,35,20,34,27,36), +(6,7,13,281,389,36,21,35,28,37), +(6,7,14,298,422,37,21,36,29,38), +(6,7,15,315,456,38,22,37,30,39), +(6,7,16,332,491,39,22,39,31,40), +(6,7,17,350,527,40,23,40,32,42), +(6,7,18,369,564,41,23,41,33,43), +(6,7,19,389,602,42,24,42,34,44), +(6,7,20,410,641,43,24,43,35,45), +(6,7,21,432,681,44,25,44,36,46), +(6,7,22,455,722,45,25,45,37,48), +(6,7,23,479,764,46,26,47,38,49), +(6,7,24,504,807,47,27,48,40,50), +(6,7,25,530,851,48,27,49,41,51), +(6,7,26,557,896,49,28,50,42,53), +(6,7,27,585,942,51,28,52,43,54), +(6,7,28,614,989,52,29,53,44,55), +(6,7,29,644,1037,53,29,54,45,57), +(6,7,30,675,1086,54,30,55,47,58), +(6,7,31,707,1136,55,31,57,48,59), +(6,7,32,740,1187,56,31,58,49,61), +(6,7,33,774,1238,57,32,59,50,62), +(6,7,34,809,1289,58,33,61,51,64), +(6,7,35,845,1340,60,33,62,53,65), +(6,7,36,882,1391,61,34,63,54,66), +(6,7,37,920,1442,62,34,65,55,68), +(6,7,38,959,1493,63,35,66,57,69), +(6,7,39,999,1544,64,36,67,58,71), +(6,7,40,1040,1595,66,36,69,59,72), +(6,7,41,1082,1646,67,37,70,60,74), +(6,7,42,1125,1697,68,38,72,62,75), +(6,7,43,1169,1748,69,38,73,63,77), +(6,7,44,1214,1799,70,39,74,64,78), +(6,7,45,1260,1850,72,40,76,66,80), +(6,7,46,1307,1901,73,41,77,67,81), +(6,7,47,1355,1952,74,41,79,69,83), +(6,7,48,1404,2003,76,42,80,70,84), +(6,7,49,1454,2054,77,43,82,71,86), +(6,7,50,1505,2105,78,43,83,73,88), +(6,7,51,1557,2156,80,44,85,74,89), +(6,7,52,1610,2207,81,45,86,76,91), +(6,7,53,1664,2258,82,46,88,77,92), +(6,7,54,1719,2309,84,46,90,78,94), +(6,7,55,1775,2360,85,47,91,80,96), +(6,7,56,1832,2411,86,48,93,81,97), +(6,7,57,1890,2462,88,49,94,83,99), +(6,7,58,1949,2513,89,49,96,84,101), +(6,7,59,2009,2564,91,50,97,86,102), +(6,7,60,2070,2615,92,51,99,87,104), +(6,7,61,2238,2774,94,52,101,89,106), +(6,7,62,2414,2933,95,52,102,90,108), +(6,7,63,2598,3107,96,53,104,92,109), +(6,7,64,2790,3266,98,54,106,93,111), +(6,7,65,2991,3425,99,55,107,95,113), +(6,7,66,3201,3599,101,56,109,97,115), +(6,7,67,3421,3758,102,57,111,98,117), +(6,7,68,3651,3917,104,57,113,100,118), +(6,7,69,3891,4091,105,58,114,101,120), +(6,7,70,4141,4250,107,59,116,103,122), +(6,11,1,74,67,26,15,22,17,24), +(6,11,2,91,89,27,16,23,18,25), +(6,11,3,108,112,27,16,23,19,26), +(6,11,4,125,136,28,17,24,20,27), +(6,11,5,142,161,28,17,25,21,29), +(6,11,6,159,187,29,18,25,22,30), +(6,11,7,176,214,29,18,26,23,31), +(6,11,8,193,242,30,19,27,24,32), +(6,11,9,210,271,30,19,27,26,34), +(6,11,10,227,301,31,20,28,27,35), +(6,11,11,244,332,32,20,29,28,36), +(6,11,12,261,364,32,21,29,29,37), +(6,11,13,278,397,33,21,30,30,39), +(6,11,14,295,431,33,22,31,31,40), +(6,11,15,312,466,34,23,32,32,41), +(6,11,16,329,502,35,23,32,34,43), +(6,11,17,346,539,35,24,33,35,44), +(6,11,18,364,577,36,24,34,36,45), +(6,11,19,383,616,37,25,35,37,47), +(6,11,20,403,656,37,26,35,39,48), +(6,11,21,424,697,38,26,36,40,50), +(6,11,22,446,739,39,27,37,41,51), +(6,11,23,469,782,39,28,38,42,52), +(6,11,24,493,826,40,28,39,44,54), +(6,11,25,518,871,41,29,39,45,55), +(6,11,26,544,916,41,30,40,46,57), +(6,11,27,571,961,42,30,41,47,58), +(6,11,28,599,1006,43,31,42,49,60), +(6,11,29,628,1051,44,32,43,50,61), +(6,11,30,658,1096,44,32,44,52,63), +(6,11,31,689,1141,45,33,44,53,64), +(6,11,32,721,1186,46,34,45,54,66), +(6,11,33,754,1231,47,34,46,56,67), +(6,11,34,788,1276,47,35,47,57,69), +(6,11,35,823,1321,48,36,48,58,71), +(6,11,36,859,1366,49,36,49,60,72), +(6,11,37,896,1411,50,37,50,61,74), +(6,11,38,934,1456,51,38,51,63,76), +(6,11,39,973,1501,52,39,52,64,77), +(6,11,40,1013,1546,52,39,53,66,79), +(6,11,41,1054,1591,53,40,54,67,81), +(6,11,42,1096,1636,54,41,55,69,82), +(6,11,43,1139,1681,55,42,56,70,84), +(6,11,44,1183,1726,56,43,57,72,86), +(6,11,45,1228,1771,57,43,57,73,87), +(6,11,46,1274,1816,57,44,58,75,89), +(6,11,47,1321,1861,58,45,60,76,91), +(6,11,48,1369,1906,59,46,61,78,93), +(6,11,49,1418,1951,60,47,62,79,94), +(6,11,50,1468,1996,61,47,63,81,96), +(6,11,51,1519,2041,62,48,64,83,98), +(6,11,52,1571,2086,63,49,65,84,100), +(6,11,53,1624,2131,64,50,66,86,102), +(6,11,54,1678,2176,65,51,67,87,104), +(6,11,55,1733,2221,66,51,68,89,105), +(6,11,56,1789,2266,67,52,69,91,107), +(6,11,57,1846,2311,68,53,70,92,109), +(6,11,58,1904,2356,69,54,71,94,111), +(6,11,59,1963,2401,70,55,72,96,113), +(6,11,60,2023,2446,71,56,73,97,115), +(6,11,61,2198,2574,72,57,74,99,117), +(6,11,62,2384,2717,73,58,76,101,119), +(6,11,63,2581,2860,74,59,77,103,121), +(6,11,64,2789,3003,75,59,78,104,123), +(6,11,65,3008,3146,76,60,79,106,125), +(6,11,66,3238,3289,77,61,80,108,127), +(6,11,67,3480,3432,78,62,81,110,129), +(6,11,68,3734,3575,79,63,83,111,131), +(6,11,69,4000,3718,80,64,84,113,133), +(6,11,70,4278,3861,81,65,85,115,135), +(7,1,1,50,0,18,23,21,24,20), +(7,1,2,69,0,19,24,22,24,20), +(7,1,3,88,0,21,25,23,24,21), +(7,1,4,107,0,22,25,25,24,21), +(7,1,5,126,0,23,26,26,24,21), +(7,1,6,145,0,25,27,27,24,21), +(7,1,7,164,0,26,28,28,24,22), +(7,1,8,183,0,27,29,29,25,22), +(7,1,9,202,0,29,29,31,25,22), +(7,1,10,221,0,30,30,32,25,23), +(7,1,11,240,0,32,31,33,25,23), +(7,1,12,259,0,33,32,34,25,23), +(7,1,13,278,0,34,33,36,25,24), +(7,1,14,298,0,36,34,37,25,24), +(7,1,15,319,0,37,35,38,25,24), +(7,1,16,341,0,39,36,40,25,25), +(7,1,17,364,0,40,36,41,25,25), +(7,1,18,388,0,42,37,43,26,25), +(7,1,19,413,0,43,38,44,26,26), +(7,1,20,439,0,45,39,45,26,26), +(7,1,21,466,0,47,40,47,26,26), +(7,1,22,494,0,48,41,48,26,27), +(7,1,23,523,0,50,42,50,26,27), +(7,1,24,553,0,51,43,51,26,28), +(7,1,25,584,0,53,44,52,27,28), +(7,1,26,616,0,55,45,54,27,28), +(7,1,27,649,0,56,46,55,27,29), +(7,1,28,683,0,58,47,57,27,29), +(7,1,29,718,0,59,48,58,27,30), +(7,1,30,754,0,61,49,60,27,30), +(7,1,31,791,0,63,50,62,27,30), +(7,1,32,829,0,65,51,63,28,31), +(7,1,33,868,0,66,52,65,28,31), +(7,1,34,908,0,68,53,66,28,32), +(7,1,35,949,0,70,55,68,28,32), +(7,1,36,991,0,72,56,69,28,33), +(7,1,37,1035,0,73,57,71,29,33), +(7,1,38,1081,0,75,58,73,29,34), +(7,1,39,1129,0,77,59,74,29,34), +(7,1,40,1179,0,79,60,76,29,35), +(7,1,41,1231,0,81,61,78,29,35), +(7,1,42,1285,0,82,62,79,30,35), +(7,1,43,1341,0,84,64,81,30,36), +(7,1,44,1399,0,86,65,83,30,36), +(7,1,45,1459,0,88,66,85,30,37), +(7,1,46,1521,0,90,67,86,30,37), +(7,1,47,1585,0,92,68,88,31,38), +(7,1,48,1651,0,94,70,90,31,38), +(7,1,49,1719,0,96,71,92,31,39), +(7,1,50,1789,0,98,72,93,31,40), +(7,1,51,1861,0,100,73,95,32,40), +(7,1,52,1935,0,102,75,97,32,41), +(7,1,53,2011,0,104,76,99,32,41), +(7,1,54,2089,0,106,77,101,32,42), +(7,1,55,2169,0,108,78,103,33,42), +(7,1,56,2251,0,110,80,104,33,43), +(7,1,57,2335,0,112,81,106,33,43), +(7,1,58,2421,0,114,82,108,33,44), +(7,1,59,2509,0,116,84,110,34,44), +(7,1,60,2599,0,118,85,112,34,45), +(7,1,61,2832,0,120,86,114,34,46), +(7,1,62,3079,0,122,88,116,35,46), +(7,1,63,3340,0,125,89,118,35,47), +(7,1,64,3615,0,127,91,120,35,47), +(7,1,65,3905,0,129,92,122,35,48), +(7,1,66,4210,0,131,93,124,36,49), +(7,1,67,4530,0,133,95,126,36,49), +(7,1,68,4866,0,136,96,128,36,50), +(7,1,69,5218,0,138,98,130,37,50), +(7,1,70,5586,0,140,99,132,37,51), +(7,4,1,45,0,16,26,20,24,20), +(7,4,2,62,0,17,27,21,24,20), +(7,4,3,79,0,18,29,21,24,21), +(7,4,4,96,0,18,30,22,24,21), +(7,4,5,113,0,19,32,23,25,21), +(7,4,6,130,0,20,33,24,25,22), +(7,4,7,147,0,21,35,24,25,22), +(7,4,8,164,0,22,36,25,25,23), +(7,4,9,181,0,22,38,26,25,23), +(7,4,10,198,0,23,39,26,25,23), +(7,4,11,215,0,24,41,27,25,24), +(7,4,12,232,0,25,42,28,26,24), +(7,4,13,249,0,26,44,29,26,25), +(7,4,14,266,0,27,46,30,26,25), +(7,4,15,283,0,28,47,30,26,25), +(7,4,16,301,0,28,49,31,26,26), +(7,4,17,320,0,29,50,32,27,26), +(7,4,18,340,0,30,52,33,27,27), +(7,4,19,361,0,31,54,34,27,27), +(7,4,20,383,0,32,56,35,27,28), +(7,4,21,406,0,33,57,35,27,28), +(7,4,22,430,0,34,59,36,28,29), +(7,4,23,455,0,35,61,37,28,29), +(7,4,24,481,0,36,62,38,28,30), +(7,4,25,508,0,37,64,39,28,30), +(7,4,26,536,0,38,66,40,29,31), +(7,4,27,565,0,39,68,41,29,31), +(7,4,28,595,0,40,70,42,29,32), +(7,4,29,626,0,41,72,43,29,32), +(7,4,30,658,0,42,73,43,29,33), +(7,4,31,691,0,43,75,44,30,33), +(7,4,32,725,0,44,77,45,30,34), +(7,4,33,760,0,45,79,46,30,34), +(7,4,34,796,0,46,81,47,31,35), +(7,4,35,833,0,47,83,48,31,35), +(7,4,36,871,0,48,85,49,31,36), +(7,4,37,910,0,49,87,50,31,36), +(7,4,38,950,0,50,89,51,32,37), +(7,4,39,991,0,51,91,52,32,38), +(7,4,40,1033,0,53,93,53,32,38), +(7,4,41,1076,0,54,95,54,33,39), +(7,4,42,1120,0,55,97,55,33,39), +(7,4,43,1165,0,56,99,56,33,40), +(7,4,44,1211,0,57,101,57,33,40), +(7,4,45,1258,0,58,103,59,34,41), +(7,4,46,1306,0,59,105,60,34,42), +(7,4,47,1355,0,61,107,61,34,42), +(7,4,48,1405,0,62,110,62,35,43), +(7,4,49,1456,0,63,112,63,35,44), +(7,4,50,1508,0,64,114,64,35,44), +(7,4,51,1561,0,65,116,65,36,45), +(7,4,52,1615,0,67,118,66,36,45), +(7,4,53,1670,0,68,121,67,36,46), +(7,4,54,1726,0,69,123,69,37,47), +(7,4,55,1783,0,70,125,70,37,47), +(7,4,56,1841,0,72,127,71,37,48), +(7,4,57,1900,0,73,130,72,38,49), +(7,4,58,1960,0,74,132,73,38,49), +(7,4,59,2021,0,75,134,74,39,50), +(7,4,60,2083,0,77,137,76,39,51), +(7,4,61,2272,0,78,139,77,39,51), +(7,4,62,2470,0,79,141,78,40,52), +(7,4,63,2677,0,81,144,79,40,53), +(7,4,64,2893,0,82,146,80,41,54), +(7,4,65,3119,0,83,149,82,41,54), +(7,4,66,3355,0,85,151,83,41,55), +(7,4,67,3601,0,86,154,84,42,56), +(7,4,68,3858,0,87,156,85,42,57), +(7,4,69,4126,0,89,158,87,43,57), +(7,4,70,4405,0,90,161,88,43,58), +(7,8,1,51,225,15,23,19,27,22), +(7,8,2,66,250,15,23,19,28,23), +(7,8,3,81,276,15,23,20,30,25), +(7,8,4,96,303,15,23,20,31,26), +(7,8,5,111,331,15,24,20,32,27), +(7,8,6,126,360,15,24,20,34,29), +(7,8,7,141,390,16,24,21,35,30), +(7,8,8,156,421,16,24,21,37,31), +(7,8,9,171,453,16,24,21,38,33), +(7,8,10,186,486,16,24,22,40,34), +(7,8,11,201,520,16,25,22,41,36), +(7,8,12,216,555,16,25,22,42,37), +(7,8,13,231,591,16,25,23,44,38), +(7,8,14,246,628,16,25,23,45,40), +(7,8,15,261,666,17,25,23,47,41), +(7,8,16,276,705,17,25,24,49,43), +(7,8,17,291,745,17,26,24,50,44), +(7,8,18,306,786,17,26,24,52,46), +(7,8,19,321,828,17,26,25,53,47), +(7,8,20,336,871,17,26,25,55,49), +(7,8,21,351,915,17,26,26,57,51), +(7,8,22,366,960,18,27,26,58,52), +(7,8,23,381,1006,18,27,26,60,54), +(7,8,24,397,1053,18,27,27,61,55), +(7,8,25,414,1101,18,27,27,63,57), +(7,8,26,432,1150,18,28,27,65,59), +(7,8,27,451,1200,18,28,28,67,60), +(7,8,28,471,1251,18,28,28,68,62), +(7,8,29,492,1302,19,28,29,70,64), +(7,8,30,514,1353,19,29,29,72,65), +(7,8,31,537,1404,19,29,30,74,67), +(7,8,32,561,1455,19,29,30,75,69), +(7,8,33,586,1506,19,29,30,77,70), +(7,8,34,612,1557,20,30,31,79,72), +(7,8,35,639,1608,20,30,31,81,74), +(7,8,36,667,1659,20,30,32,83,76), +(7,8,37,696,1710,20,30,32,85,78), +(7,8,38,726,1761,20,31,33,86,79), +(7,8,39,757,1812,21,31,33,88,81), +(7,8,40,789,1863,21,31,34,90,83), +(7,8,41,822,1914,21,32,34,92,85), +(7,8,42,856,1965,21,32,35,94,87), +(7,8,43,891,2016,21,32,35,96,89), +(7,8,44,927,2067,22,32,36,98,91), +(7,8,45,964,2118,22,33,36,100,92), +(7,8,46,1002,2169,22,33,37,102,94), +(7,8,47,1041,2220,22,33,37,104,96), +(7,8,48,1081,2271,22,34,38,106,98), +(7,8,49,1122,2322,23,34,38,108,100), +(7,8,50,1164,2373,23,34,39,110,102), +(7,8,51,1207,2424,23,35,39,112,104), +(7,8,52,1251,2475,23,35,40,114,106), +(7,8,53,1296,2526,24,35,40,117,108), +(7,8,54,1342,2577,24,36,41,119,110), +(7,8,55,1389,2628,24,36,41,121,112), +(7,8,56,1437,2679,24,37,42,123,114), +(7,8,57,1486,2730,25,37,42,125,117), +(7,8,58,1536,2781,25,37,43,127,119), +(7,8,59,1587,2832,25,38,43,130,121), +(7,8,60,1639,2883,25,38,44,132,123), +(7,8,61,1805,3016,26,38,45,134,125), +(7,8,62,1980,3164,26,39,45,136,127), +(7,8,63,2164,3297,26,39,46,139,129), +(7,8,64,2357,3445,26,40,46,141,132), +(7,8,65,2559,3578,27,40,47,143,134), +(7,8,66,2771,3726,27,40,48,146,136), +(7,8,67,2993,3859,27,41,48,148,138), +(7,8,68,3225,4007,27,41,49,150,140), +(7,8,69,3468,4140,28,42,49,153,143), +(7,8,70,3722,4288,28,42,50,155,145), +(7,9,1,43,200,15,23,20,26,22), +(7,9,2,58,223,15,23,21,27,23), +(7,9,3,73,247,16,24,21,28,24), +(7,9,4,88,272,16,24,22,29,25), +(7,9,5,103,298,16,24,22,31,27), +(7,9,6,118,325,17,25,23,32,28), +(7,9,7,133,353,17,25,23,33,29), +(7,9,8,148,382,17,26,24,34,30), +(7,9,9,163,412,17,26,25,36,31), +(7,9,10,178,443,18,26,25,37,33), +(7,9,11,193,475,18,27,26,38,34), +(7,9,12,208,508,18,27,26,39,35), +(7,9,13,223,542,19,28,27,41,36), +(7,9,14,238,577,19,28,28,42,38), +(7,9,15,253,613,20,28,28,43,39), +(7,9,16,268,650,20,29,29,45,40), +(7,9,17,283,688,20,29,30,46,42), +(7,9,18,299,727,21,30,30,47,43), +(7,9,19,316,767,21,30,31,49,44), +(7,9,20,334,808,21,31,32,50,46), +(7,9,21,353,850,22,31,32,51,47), +(7,9,22,373,893,22,31,33,53,49), +(7,9,23,394,937,23,32,34,54,50), +(7,9,24,416,982,23,32,34,56,51), +(7,9,25,439,1028,23,33,35,57,53), +(7,9,26,463,1075,24,33,36,59,54), +(7,9,27,488,1123,24,34,37,60,56), +(7,9,28,514,1172,25,34,37,62,57), +(7,9,29,541,1222,25,35,38,63,59), +(7,9,30,569,1273,25,35,39,65,60), +(7,9,31,598,1324,26,36,40,66,62), +(7,9,32,628,1375,26,36,40,68,63), +(7,9,33,659,1426,27,37,41,69,65), +(7,9,34,691,1477,27,38,42,71,66), +(7,9,35,724,1528,28,38,43,73,68), +(7,9,36,758,1579,28,39,43,74,69), +(7,9,37,793,1630,28,39,44,76,71), +(7,9,38,829,1681,29,40,45,77,73), +(7,9,39,866,1732,29,40,46,79,74), +(7,9,40,904,1783,30,41,47,81,76), +(7,9,41,943,1834,30,41,48,82,78), +(7,9,42,983,1885,31,42,48,84,79), +(7,9,43,1024,1936,31,43,49,86,81), +(7,9,44,1066,1987,32,43,50,88,83), +(7,9,45,1109,2038,32,44,51,89,84), +(7,9,46,1153,2089,33,44,52,91,86), +(7,9,47,1198,2140,33,45,53,93,88), +(7,9,48,1244,2191,34,46,54,95,89), +(7,9,49,1291,2242,34,46,54,96,91), +(7,9,50,1339,2293,35,47,55,98,93), +(7,9,51,1388,2344,35,48,56,100,95), +(7,9,52,1438,2395,36,48,57,102,97), +(7,9,53,1489,2446,36,49,58,104,98), +(7,9,54,1541,2497,37,50,59,105,100), +(7,9,55,1594,2548,37,50,60,107,102), +(7,9,56,1648,2599,38,51,61,109,104), +(7,9,57,1703,2650,38,52,62,111,106), +(7,9,58,1759,2701,39,52,63,113,108), +(7,9,59,1816,2752,40,53,64,115,109), +(7,9,60,1874,2803,40,54,65,117,111), +(7,9,61,2050,2957,41,54,66,119,113), +(7,9,62,2235,3111,41,55,67,121,115), +(7,9,63,2429,3280,42,56,68,123,117), +(7,9,64,2632,3434,42,57,69,125,119), +(7,9,65,2844,3588,43,57,70,127,121), +(7,9,66,3066,3757,44,58,71,129,123), +(7,9,67,3298,3911,44,59,72,131,125), +(7,9,68,3541,4065,45,59,73,133,127), +(7,9,69,3795,4234,45,60,74,135,129), +(7,9,70,4060,4388,46,61,75,137,131), +(8,1,1,70,0,24,22,23,16,21), +(8,1,2,89,0,25,23,24,16,21), +(8,1,3,108,0,27,24,25,16,22), +(8,1,4,127,0,28,24,26,16,22), +(8,1,5,146,0,29,25,28,16,22), +(8,1,6,165,0,31,26,29,16,22), +(8,1,7,184,0,32,27,30,17,23), +(8,1,8,203,0,33,28,31,17,23), +(8,1,9,222,0,35,28,33,17,23), +(8,1,10,241,0,36,29,34,17,24), +(8,1,11,260,0,37,30,35,17,24), +(8,1,12,279,0,39,31,36,17,24), +(8,1,13,298,0,40,32,38,17,25), +(8,1,14,318,0,42,33,39,17,25), +(8,1,15,339,0,43,34,40,18,25), +(8,1,16,361,0,45,35,42,18,26), +(8,1,17,384,0,46,35,43,18,26), +(8,1,18,408,0,48,36,44,18,26), +(8,1,19,433,0,49,37,46,18,27), +(8,1,20,459,0,51,38,47,18,27), +(8,1,21,486,0,52,39,49,18,27), +(8,1,22,514,0,54,40,50,18,28), +(8,1,23,543,0,55,41,51,19,28), +(8,1,24,573,0,57,42,53,19,29), +(8,1,25,604,0,59,43,54,19,29), +(8,1,26,636,0,60,44,56,19,29), +(8,1,27,669,0,62,45,57,19,30), +(8,1,28,703,0,63,46,59,19,30), +(8,1,29,738,0,65,47,60,20,31), +(8,1,30,774,0,67,48,62,20,31), +(8,1,31,811,0,69,49,63,20,31), +(8,1,32,849,0,70,50,65,20,32), +(8,1,33,888,0,72,51,67,20,32), +(8,1,34,928,0,74,53,68,20,33), +(8,1,35,969,0,75,54,70,21,33), +(8,1,36,1011,0,77,55,71,21,34), +(8,1,37,1055,0,79,56,73,21,34), +(8,1,38,1101,0,81,57,75,21,35), +(8,1,39,1149,0,83,58,76,21,35), +(8,1,40,1199,0,84,59,78,22,35), +(8,1,41,1251,0,86,60,80,22,36), +(8,1,42,1305,0,88,62,81,22,36), +(8,1,43,1361,0,90,63,83,22,37), +(8,1,44,1419,0,92,64,85,22,37), +(8,1,45,1479,0,94,65,86,23,38), +(8,1,46,1541,0,96,66,88,23,38), +(8,1,47,1605,0,98,67,90,23,39), +(8,1,48,1671,0,100,69,92,23,39), +(8,1,49,1739,0,102,70,93,24,40), +(8,1,50,1809,0,103,71,95,24,40), +(8,1,51,1881,0,105,72,97,24,41), +(8,1,52,1955,0,107,74,99,24,42), +(8,1,53,2031,0,109,75,101,25,42), +(8,1,54,2109,0,112,76,103,25,43), +(8,1,55,2189,0,114,78,104,25,43), +(8,1,56,2271,0,116,79,106,25,44), +(8,1,57,2355,0,118,80,108,25,44), +(8,1,58,2441,0,120,81,110,26,45), +(8,1,59,2529,0,122,83,112,26,45), +(8,1,60,2619,0,124,84,114,26,46), +(8,1,61,2852,0,126,85,116,27,47), +(8,1,62,3099,0,128,87,118,27,47), +(8,1,63,3360,0,130,88,120,27,48), +(8,1,64,3635,0,133,90,122,27,48), +(8,1,65,3925,0,135,91,124,28,49), +(8,1,66,4230,0,137,92,126,28,50), +(8,1,67,4550,0,139,94,128,28,50), +(8,1,68,4886,0,141,95,130,28,51), +(8,1,69,5238,0,144,97,132,29,51), +(8,1,70,5606,0,146,98,134,29,52), +(8,3,1,66,81,21,25,22,16,22), +(8,3,2,83,101,21,26,23,17,23), +(8,3,3,100,122,22,28,24,17,23), +(8,3,4,117,144,22,29,25,18,24), +(8,3,5,134,167,23,30,26,18,25), +(8,3,6,151,191,23,32,27,19,25), +(8,3,7,168,216,24,33,28,20,26), +(8,3,8,185,242,24,35,28,20,26), +(8,3,9,202,269,25,36,29,21,27), +(8,3,10,219,297,25,38,30,21,28), +(8,3,11,236,326,25,39,31,22,29), +(8,3,12,253,356,26,41,32,23,29), +(8,3,13,270,387,26,42,33,23,30), +(8,3,14,288,419,27,44,34,24,31), +(8,3,15,307,452,27,45,35,25,31), +(8,3,16,327,486,28,47,36,25,32), +(8,3,17,348,521,28,48,38,26,33), +(8,3,18,370,557,29,50,39,27,34), +(8,3,19,393,594,29,51,40,28,34), +(8,3,20,417,632,30,53,41,28,35), +(8,3,21,442,671,31,55,42,29,36), +(8,3,22,468,711,31,56,43,30,37), +(8,3,23,495,752,32,58,44,30,37), +(8,3,24,523,794,32,60,45,31,38), +(8,3,25,552,837,33,61,46,32,39), +(8,3,26,582,881,33,63,48,33,40), +(8,3,27,613,926,34,65,49,33,41), +(8,3,28,645,971,35,66,50,34,41), +(8,3,29,678,1016,35,68,51,35,42), +(8,3,30,712,1061,36,70,52,36,43), +(8,3,31,747,1106,36,72,53,37,44), +(8,3,32,783,1151,37,73,55,37,45), +(8,3,33,820,1196,38,75,56,38,46), +(8,3,34,858,1241,38,77,57,39,47), +(8,3,35,897,1286,39,79,58,40,48), +(8,3,36,937,1331,39,81,60,41,48), +(8,3,37,978,1376,40,83,61,41,49), +(8,3,38,1020,1421,41,85,62,42,50), +(8,3,39,1063,1466,41,86,63,43,51), +(8,3,40,1107,1511,42,88,65,44,52), +(8,3,41,1152,1556,43,90,66,45,53), +(8,3,42,1198,1601,43,92,67,46,54), +(8,3,43,1245,1646,44,94,69,47,55), +(8,3,44,1293,1691,45,96,70,47,56), +(8,3,45,1342,1736,45,98,71,48,57), +(8,3,46,1392,1781,46,100,73,49,58), +(8,3,47,1443,1826,47,102,74,50,59), +(8,3,48,1495,1871,48,104,76,51,60), +(8,3,49,1548,1916,48,106,77,52,61), +(8,3,50,1602,1961,49,108,78,53,62), +(8,3,51,1657,2006,50,110,80,54,63), +(8,3,52,1713,2051,51,113,81,55,64), +(8,3,53,1770,2096,51,115,83,56,65), +(8,3,54,1828,2141,52,117,84,57,66), +(8,3,55,1887,2186,53,119,86,58,67), +(8,3,56,1947,2231,54,121,87,59,68), +(8,3,57,2008,2276,54,123,89,60,69), +(8,3,58,2070,2321,55,126,90,61,70), +(8,3,59,2133,2366,56,128,92,62,71), +(8,3,60,2197,2411,57,130,93,63,73), +(8,3,61,2383,2592,58,132,95,64,74), +(8,3,62,2578,2773,58,134,96,65,75), +(8,3,63,2782,2954,59,137,98,66,76), +(8,3,64,2995,3135,60,139,99,67,77), +(8,3,65,3217,3331,61,141,101,68,78), +(8,3,66,3449,3512,62,144,103,69,79), +(8,3,67,3691,3693,62,146,104,70,80), +(8,3,68,3943,3874,63,148,106,71,82), +(8,3,69,4205,4055,64,151,107,72,83), +(8,3,70,4478,4251,65,153,109,73,84), +(8,4,1,65,0,22,25,22,16,21), +(8,4,2,82,0,23,26,23,16,21), +(8,4,3,99,0,24,28,23,16,22), +(8,4,4,116,0,24,29,24,16,22), +(8,4,5,133,0,25,31,25,17,22), +(8,4,6,150,0,26,32,25,17,23), +(8,4,7,167,0,27,34,26,17,23), +(8,4,8,184,0,27,35,27,17,24), +(8,4,9,201,0,28,37,28,17,24), +(8,4,10,218,0,29,38,28,18,24), +(8,4,11,235,0,30,40,29,18,25), +(8,4,12,252,0,31,41,30,18,25), +(8,4,13,269,0,32,43,31,18,26), +(8,4,14,286,0,32,45,32,18,26), +(8,4,15,303,0,33,46,32,19,26), +(8,4,16,321,0,34,48,33,19,27), +(8,4,17,340,0,35,50,34,19,27), +(8,4,18,360,0,36,51,35,19,28), +(8,4,19,381,0,37,53,36,19,28), +(8,4,20,403,0,38,55,36,20,29), +(8,4,21,426,0,39,56,37,20,29), +(8,4,22,450,0,40,58,38,20,30), +(8,4,23,475,0,41,60,39,20,30), +(8,4,24,501,0,42,62,40,20,31), +(8,4,25,528,0,43,63,41,21,31), +(8,4,26,556,0,44,65,42,21,32), +(8,4,27,585,0,45,67,43,21,32), +(8,4,28,615,0,46,69,44,21,33), +(8,4,29,646,0,47,71,44,22,33), +(8,4,30,678,0,48,72,45,22,34), +(8,4,31,711,0,49,74,46,22,34), +(8,4,32,745,0,50,76,47,22,35), +(8,4,33,780,0,51,78,48,23,35), +(8,4,34,816,0,52,80,49,23,36), +(8,4,35,853,0,53,82,50,23,36), +(8,4,36,891,0,54,84,51,24,37), +(8,4,37,930,0,55,86,52,24,37), +(8,4,38,970,0,56,88,53,24,38), +(8,4,39,1011,0,57,90,54,24,38), +(8,4,40,1053,0,58,92,55,25,39), +(8,4,41,1096,0,59,94,56,25,40), +(8,4,42,1140,0,60,96,57,25,40), +(8,4,43,1185,0,62,98,58,26,41), +(8,4,44,1231,0,63,100,59,26,41), +(8,4,45,1278,0,64,102,60,26,42), +(8,4,46,1326,0,65,104,61,27,43), +(8,4,47,1375,0,66,107,63,27,43), +(8,4,48,1425,0,67,109,64,27,44), +(8,4,49,1476,0,69,111,65,27,44), +(8,4,50,1528,0,70,113,66,28,45), +(8,4,51,1581,0,71,115,67,28,46), +(8,4,52,1635,0,72,117,68,28,46), +(8,4,53,1690,0,74,120,69,29,47), +(8,4,54,1746,0,75,122,70,29,48), +(8,4,55,1803,0,76,124,72,29,48), +(8,4,56,1861,0,77,126,73,30,49), +(8,4,57,1920,0,79,129,74,30,50), +(8,4,58,1980,0,80,131,75,30,50), +(8,4,59,2041,0,81,133,76,31,51), +(8,4,60,2103,0,82,136,77,31,52), +(8,4,61,2292,0,84,138,79,32,52), +(8,4,62,2490,0,85,140,80,32,53), +(8,4,63,2697,0,86,143,81,32,54), +(8,4,64,2913,0,88,145,82,33,55), +(8,4,65,3139,0,89,148,84,33,55), +(8,4,66,3375,0,90,150,85,33,56), +(8,4,67,3621,0,92,153,86,34,57), +(8,4,68,3878,0,93,155,87,34,58), +(8,4,69,4146,0,95,157,89,35,58), +(8,4,70,4425,0,96,160,90,35,59), +(8,5,1,62,128,21,22,21,18,24), +(8,5,2,77,152,21,22,21,19,25), +(8,5,3,92,177,21,22,22,21,27), +(8,5,4,107,203,21,23,22,22,28), +(8,5,5,122,230,22,23,22,23,29), +(8,5,6,137,258,22,23,23,25,31), +(8,5,7,152,287,22,23,23,26,32), +(8,5,8,167,317,22,24,24,27,34), +(8,5,9,182,348,22,24,24,29,35), +(8,5,10,197,380,22,24,24,30,37), +(8,5,11,212,413,23,24,25,32,38), +(8,5,12,227,447,23,24,25,33,40), +(8,5,13,242,482,23,25,26,35,41), +(8,5,14,257,518,23,25,26,36,43), +(8,5,15,272,555,23,25,26,38,44), +(8,5,16,287,593,24,26,27,39,46), +(8,5,17,302,632,24,26,27,41,47), +(8,5,18,317,672,24,26,28,42,49), +(8,5,19,332,713,24,26,28,44,50), +(8,5,20,347,755,24,27,29,45,52), +(8,5,21,362,798,25,27,29,47,54), +(8,5,22,378,842,25,27,30,48,55), +(8,5,23,395,887,25,28,30,50,57), +(8,5,24,413,933,25,28,31,52,59), +(8,5,25,432,980,25,28,31,53,60), +(8,5,26,452,1028,26,28,32,55,62), +(8,5,27,473,1077,26,29,32,56,64), +(8,5,28,495,1127,26,29,33,58,65), +(8,5,29,518,1178,26,29,33,60,67), +(8,5,30,542,1230,27,30,34,62,69), +(8,5,31,567,1283,27,30,34,63,71), +(8,5,32,593,1337,27,30,35,65,73), +(8,5,33,620,1391,27,31,35,67,74), +(8,5,34,648,1445,28,31,36,68,76), +(8,5,35,677,1499,28,32,36,70,78), +(8,5,36,707,1553,28,32,37,72,80), +(8,5,37,738,1607,29,32,37,74,82), +(8,5,38,770,1661,29,33,38,76,84), +(8,5,39,803,1715,29,33,38,77,86), +(8,5,40,837,1769,29,33,39,79,87), +(8,5,41,872,1823,30,34,40,81,89), +(8,5,42,908,1877,30,34,40,83,91), +(8,5,43,945,1931,30,35,41,85,93), +(8,5,44,983,1985,31,35,41,87,95), +(8,5,45,1022,2039,31,35,42,89,97), +(8,5,46,1062,2093,31,36,43,91,99), +(8,5,47,1103,2147,32,36,43,93,101), +(8,5,48,1145,2201,32,37,44,94,103), +(8,5,49,1188,2255,32,37,44,96,105), +(8,5,50,1232,2309,33,37,45,98,107), +(8,5,51,1277,2363,33,38,46,100,110), +(8,5,52,1323,2417,33,38,46,102,112), +(8,5,53,1370,2471,34,39,47,104,114), +(8,5,54,1418,2525,34,39,48,106,116), +(8,5,55,1467,2579,34,40,48,109,118), +(8,5,56,1517,2633,35,40,49,111,120), +(8,5,57,1568,2687,35,41,50,113,122), +(8,5,58,1620,2741,35,41,50,115,125), +(8,5,59,1673,2795,36,42,51,117,127), +(8,5,60,1727,2849,36,42,52,119,129), +(8,5,61,1897,3018,36,42,52,121,131), +(8,5,62,2075,3172,37,43,53,123,133), +(8,5,63,2261,3341,37,43,54,125,136), +(8,5,64,2455,3495,38,44,55,128,138), +(8,5,65,2657,3664,38,44,55,130,140), +(8,5,66,2868,3818,38,45,56,132,143), +(8,5,67,3088,3987,39,45,57,134,145), +(8,5,68,3317,4141,39,46,58,136,147), +(8,5,69,3555,4310,40,46,58,139,150), +(8,5,70,3802,4479,40,47,59,141,152), +(8,7,1,67,72,22,22,22,17,23), +(8,7,2,84,93,23,22,23,18,24), +(8,7,3,101,115,24,23,24,19,25), +(8,7,4,118,138,25,23,25,20,26), +(8,7,5,135,162,25,24,26,21,27), +(8,7,6,152,187,26,24,27,22,28), +(8,7,7,169,213,27,25,28,23,29), +(8,7,8,186,240,28,25,29,24,30), +(8,7,9,203,268,29,25,30,25,31), +(8,7,10,220,297,30,26,31,26,33), +(8,7,11,237,327,31,26,32,27,34), +(8,7,12,254,358,32,27,33,28,35), +(8,7,13,271,390,33,27,34,29,36), +(8,7,14,288,423,34,28,35,30,37), +(8,7,15,305,457,34,28,36,31,38), +(8,7,16,322,492,35,29,38,32,39), +(8,7,17,340,528,36,29,39,33,41), +(8,7,18,359,565,37,30,40,34,42), +(8,7,19,379,603,38,30,41,35,43), +(8,7,20,400,642,39,31,42,36,44), +(8,7,21,422,682,40,32,43,37,45), +(8,7,22,445,723,41,32,45,38,47), +(8,7,23,469,765,43,33,46,39,48), +(8,7,24,494,808,44,33,47,40,49), +(8,7,25,520,852,45,34,48,42,51), +(8,7,26,547,897,46,34,49,43,52), +(8,7,27,575,943,47,35,51,44,53), +(8,7,28,604,990,48,35,52,45,54), +(8,7,29,634,1038,49,36,53,46,56), +(8,7,30,665,1087,50,37,54,48,57), +(8,7,31,697,1137,51,37,56,49,59), +(8,7,32,730,1188,52,38,57,50,60), +(8,7,33,764,1239,53,38,58,51,61), +(8,7,34,799,1290,55,39,60,52,63), +(8,7,35,835,1341,56,40,61,54,64), +(8,7,36,872,1392,57,40,62,55,66), +(8,7,37,910,1443,58,41,64,56,67), +(8,7,38,949,1494,59,42,65,57,68), +(8,7,39,989,1545,61,42,66,59,70), +(8,7,40,1030,1596,62,43,68,60,71), +(8,7,41,1072,1647,63,44,69,61,73), +(8,7,42,1115,1698,64,44,71,63,74), +(8,7,43,1159,1749,65,45,72,64,76), +(8,7,44,1204,1800,67,46,74,65,77), +(8,7,45,1250,1851,68,46,75,67,79), +(8,7,46,1297,1902,69,47,76,68,80), +(8,7,47,1345,1953,71,48,78,69,82), +(8,7,48,1394,2004,72,49,79,71,83), +(8,7,49,1444,2055,73,49,81,72,85), +(8,7,50,1495,2106,74,50,82,74,87), +(8,7,51,1547,2157,76,51,84,75,88), +(8,7,52,1600,2208,77,51,85,77,90), +(8,7,53,1654,2259,78,52,87,78,92), +(8,7,54,1709,2310,80,53,89,79,93), +(8,7,55,1765,2361,81,54,90,81,95), +(8,7,56,1822,2412,83,55,92,82,96), +(8,7,57,1880,2463,84,55,93,84,98), +(8,7,58,1939,2514,85,56,95,85,100), +(8,7,59,1999,2565,87,57,97,87,102), +(8,7,60,2060,2616,88,58,98,88,103), +(8,7,61,2228,2775,90,58,100,90,105), +(8,7,62,2404,2934,91,59,101,91,107), +(8,7,63,2588,3108,93,60,103,93,108), +(8,7,64,2780,3267,94,61,105,94,110), +(8,7,65,2981,3426,95,62,106,96,112), +(8,7,66,3191,3600,97,63,108,98,114), +(8,7,67,3411,3759,98,63,110,99,116), +(8,7,68,3641,3918,100,64,112,101,117), +(8,7,69,3881,4092,101,65,113,102,119), +(8,7,70,4131,4251,103,66,115,104,121), +(8,8,1,62,119,21,22,21,19,23), +(8,8,2,77,144,21,22,21,20,24), +(8,8,3,92,170,21,22,22,22,26), +(8,8,4,107,197,21,22,22,23,27), +(8,8,5,122,225,21,23,22,25,28), +(8,8,6,137,254,21,23,22,26,30), +(8,8,7,152,284,21,23,23,27,31), +(8,8,8,167,315,22,23,23,29,32), +(8,8,9,182,347,22,23,23,30,34), +(8,8,10,197,380,22,23,24,32,35), +(8,8,11,212,414,22,24,24,33,37), +(8,8,12,227,449,22,24,24,35,38), +(8,8,13,242,485,22,24,25,36,39), +(8,8,14,257,522,22,24,25,38,41), +(8,8,15,272,560,22,24,25,39,42), +(8,8,16,287,599,22,24,26,41,44), +(8,8,17,302,639,23,25,26,42,45), +(8,8,18,317,680,23,25,26,44,47), +(8,8,19,332,722,23,25,27,46,48), +(8,8,20,347,765,23,25,27,47,50), +(8,8,21,362,809,23,25,27,49,51), +(8,8,22,377,854,23,26,28,51,53), +(8,8,23,392,900,23,26,28,52,55), +(8,8,24,408,947,24,26,29,54,56), +(8,8,25,425,995,24,26,29,56,58), +(8,8,26,443,1044,24,27,29,57,60), +(8,8,27,462,1094,24,27,30,59,61), +(8,8,28,482,1145,24,27,30,61,63), +(8,8,29,503,1196,24,27,31,63,65), +(8,8,30,525,1247,24,28,31,64,66), +(8,8,31,548,1298,25,28,31,66,68), +(8,8,32,572,1349,25,28,32,68,70), +(8,8,33,597,1400,25,28,32,70,71), +(8,8,34,623,1451,25,29,33,71,73), +(8,8,35,650,1502,25,29,33,73,75), +(8,8,36,678,1553,26,29,34,75,77), +(8,8,37,707,1604,26,29,34,77,79), +(8,8,38,737,1655,26,30,35,79,80), +(8,8,39,768,1706,26,30,35,81,82), +(8,8,40,800,1757,26,30,35,83,84), +(8,8,41,833,1808,27,31,36,85,86), +(8,8,42,867,1859,27,31,36,87,88), +(8,8,43,902,1910,27,31,37,89,90), +(8,8,44,938,1961,27,32,37,91,91), +(8,8,45,975,2012,27,32,38,93,93), +(8,8,46,1013,2063,28,32,38,95,95), +(8,8,47,1052,2114,28,32,39,97,97), +(8,8,48,1092,2165,28,33,39,99,99), +(8,8,49,1133,2216,28,33,40,101,101), +(8,8,50,1175,2267,29,33,40,103,103), +(8,8,51,1218,2318,29,34,41,105,105), +(8,8,52,1262,2369,29,34,42,107,107), +(8,8,53,1307,2420,29,35,42,109,109), +(8,8,54,1353,2471,30,35,43,111,111), +(8,8,55,1400,2522,30,35,43,113,113), +(8,8,56,1448,2573,30,36,44,115,115), +(8,8,57,1497,2624,30,36,44,118,118), +(8,8,58,1547,2675,31,36,45,120,120), +(8,8,59,1598,2726,31,37,45,122,122), +(8,8,60,1650,2777,31,37,46,124,124), +(8,8,61,1816,2910,31,37,47,126,126), +(8,8,62,1991,3058,32,38,47,129,128), +(8,8,63,2175,3191,32,38,48,131,130), +(8,8,64,2368,3339,32,39,48,133,133), +(8,8,65,2570,3472,33,39,49,135,135), +(8,8,66,2782,3620,33,39,50,138,137), +(8,8,67,3004,3753,33,40,50,140,139), +(8,8,68,3236,3901,33,40,51,142,141), +(8,8,69,3479,4034,34,41,51,145,144), +(8,8,70,3733,4182,34,41,52,147,146), +(10,2,1,38,140,19,22,21,24,20), +(10,2,2,56,159,20,23,22,25,21), +(10,2,3,74,179,21,23,23,25,21), +(10,2,4,92,200,22,24,24,26,22), +(10,2,5,110,222,23,24,25,27,23), +(10,2,6,128,245,25,25,26,27,24), +(10,2,7,146,269,26,25,27,28,24), +(10,2,8,164,294,27,26,28,29,25), +(10,2,9,182,320,28,27,29,29,26), +(10,2,10,200,347,29,27,31,30,26), +(10,2,11,218,375,30,28,32,31,27), +(10,2,12,236,404,32,29,33,31,28), +(10,2,13,254,434,33,29,34,32,29), +(10,2,14,272,465,34,30,35,33,30), +(10,2,15,291,497,35,31,36,33,30), +(10,2,16,311,530,37,31,37,34,31), +(10,2,17,332,564,38,32,39,35,32), +(10,2,18,354,599,39,33,40,36,33), +(10,2,19,377,635,40,33,41,36,34), +(10,2,20,401,672,42,34,42,37,35), +(10,2,21,426,710,43,35,44,38,35), +(10,2,22,452,749,44,35,45,39,36), +(10,2,23,479,789,46,36,46,40,37), +(10,2,24,507,830,47,37,47,40,38), +(10,2,25,536,872,49,38,49,41,39), +(10,2,26,566,914,50,38,50,42,40), +(10,2,27,597,956,51,39,51,43,41), +(10,2,28,629,998,53,40,53,44,42), +(10,2,29,662,1040,54,41,54,45,43), +(10,2,30,696,1082,56,41,55,45,43), +(10,2,31,731,1124,57,42,57,46,44), +(10,2,32,767,1166,58,43,58,47,45), +(10,2,33,804,1208,60,44,59,48,46), +(10,2,34,842,1250,61,45,61,49,47), +(10,2,35,881,1292,63,45,62,50,48), +(10,2,36,921,1334,64,46,64,51,49), +(10,2,37,962,1376,66,47,65,52,50), +(10,2,38,1004,1418,67,48,67,53,51), +(10,2,39,1047,1460,69,49,68,54,52), +(10,2,40,1091,1502,71,50,69,55,53), +(10,2,41,1136,1544,72,50,71,55,54), +(10,2,42,1182,1586,74,51,72,56,55), +(10,2,43,1229,1628,75,52,74,57,56), +(10,2,44,1277,1670,77,53,75,58,57), +(10,2,45,1326,1712,79,54,77,59,59), +(10,2,46,1376,1754,80,55,78,60,60), +(10,2,47,1427,1796,82,56,80,61,61), +(10,2,48,1479,1838,83,57,82,62,62), +(10,2,49,1532,1880,85,58,83,63,63), +(10,2,50,1586,1922,87,59,85,64,64), +(10,2,51,1641,1964,89,60,86,66,65), +(10,2,52,1697,2006,90,61,88,67,66), +(10,2,53,1754,2048,92,61,90,68,67), +(10,2,54,1812,2090,94,62,91,69,69), +(10,2,55,1871,2132,95,63,93,70,70), +(10,2,56,1931,2174,97,64,95,71,71), +(10,2,57,1992,2216,99,65,96,72,72), +(10,2,58,2054,2258,101,66,98,73,73), +(10,2,59,2117,2300,102,67,100,74,74), +(10,2,60,2181,2342,104,68,101,75,76), +(10,2,61,2361,2501,106,69,103,76,77), +(10,2,62,2549,2660,108,70,105,78,78), +(10,2,63,2745,2834,110,72,106,79,79), +(10,2,64,2950,2993,112,73,108,80,80), +(10,2,65,3164,3152,113,74,110,81,82), +(10,2,66,3387,3326,115,75,112,82,83), +(10,2,67,3620,3485,117,76,114,83,84), +(10,2,68,3863,3644,119,77,115,85,85), +(10,2,69,4116,3818,121,78,117,86,87), +(10,2,70,4379,3977,123,79,119,87,88), +(10,3,1,45,145,17,25,20,24,20), +(10,3,2,62,165,17,26,21,25,21), +(10,3,3,79,186,18,28,22,25,21), +(10,3,4,96,208,18,29,23,26,22), +(10,3,5,113,231,19,30,24,26,23), +(10,3,6,130,255,19,32,25,27,23), +(10,3,7,147,280,20,33,26,27,24), +(10,3,8,164,306,20,35,27,28,25), +(10,3,9,181,333,21,36,27,29,25), +(10,3,10,198,361,21,38,28,29,26), +(10,3,11,215,390,22,39,29,30,27), +(10,3,12,232,420,22,41,30,31,27), +(10,3,13,249,451,23,42,31,31,28), +(10,3,14,267,483,23,44,32,32,29), +(10,3,15,286,516,24,45,34,32,29), +(10,3,16,306,550,24,47,35,33,30), +(10,3,17,327,585,25,48,36,34,31), +(10,3,18,349,621,25,50,37,34,32), +(10,3,19,372,658,26,51,38,35,32), +(10,3,20,396,696,26,53,39,36,33), +(10,3,21,421,735,27,55,40,37,34), +(10,3,22,447,775,27,56,41,37,35), +(10,3,23,474,816,28,58,42,38,36), +(10,3,24,502,858,28,60,43,39,36), +(10,3,25,531,901,29,61,44,39,37), +(10,3,26,561,945,30,63,46,40,38), +(10,3,27,592,990,30,65,47,41,39), +(10,3,28,624,1035,31,66,48,42,40), +(10,3,29,657,1080,31,68,49,42,40), +(10,3,30,691,1125,32,70,50,43,41), +(10,3,31,726,1170,33,72,52,44,42), +(10,3,32,762,1215,33,73,53,45,43), +(10,3,33,799,1260,34,75,54,46,44), +(10,3,34,837,1305,34,77,55,46,45), +(10,3,35,876,1350,35,79,57,47,46), +(10,3,36,916,1395,36,81,58,48,47), +(10,3,37,957,1440,36,83,59,49,47), +(10,3,38,999,1485,37,85,60,50,48), +(10,3,39,1042,1530,38,86,62,51,49), +(10,3,40,1086,1575,38,88,63,51,50), +(10,3,41,1131,1620,39,90,64,52,51), +(10,3,42,1177,1665,40,92,66,53,52), +(10,3,43,1224,1710,40,94,67,54,53), +(10,3,44,1272,1755,41,96,68,55,54), +(10,3,45,1321,1800,42,98,70,56,55), +(10,3,46,1371,1845,42,100,71,57,56), +(10,3,47,1422,1890,43,102,72,58,57), +(10,3,48,1474,1935,44,104,74,59,58), +(10,3,49,1527,1980,45,106,75,60,59), +(10,3,50,1581,2025,45,108,77,61,60), +(10,3,51,1636,2070,46,110,78,61,61), +(10,3,52,1692,2115,47,113,79,62,62), +(10,3,53,1749,2160,47,115,81,63,63), +(10,3,54,1807,2205,48,117,82,64,64), +(10,3,55,1866,2250,49,119,84,65,65), +(10,3,56,1926,2295,50,121,85,66,66), +(10,3,57,1987,2340,50,123,87,67,67), +(10,3,58,2049,2385,51,126,88,68,68), +(10,3,59,2112,2430,52,128,90,69,70), +(10,3,60,2176,2475,53,130,91,70,71), +(10,3,61,2362,2656,54,132,93,71,72), +(10,3,62,2557,2837,54,134,94,72,73), +(10,3,63,2761,3018,55,137,96,73,74), +(10,3,64,2974,3199,56,139,97,75,75), +(10,3,65,3196,3395,57,141,99,76,76), +(10,3,66,3428,3576,58,144,101,77,77), +(10,3,67,3670,3757,58,146,102,78,78), +(10,3,68,3922,3938,59,148,104,79,80), +(10,3,69,4184,4119,60,151,105,80,81), +(10,3,70,4457,4315,61,153,107,81,82), +(10,4,1,45,0,18,25,20,24,19), +(10,4,2,62,0,19,26,21,24,19), +(10,4,3,79,0,20,28,21,24,20), +(10,4,4,96,0,20,29,22,24,20), +(10,4,5,113,0,21,31,23,25,20), +(10,4,6,130,0,22,32,24,25,21), +(10,4,7,147,0,23,34,24,25,21), +(10,4,8,164,0,24,35,25,25,22), +(10,4,9,181,0,24,37,26,25,22), +(10,4,10,198,0,25,38,26,25,22), +(10,4,11,215,0,26,40,27,25,23), +(10,4,12,232,0,27,41,28,26,23), +(10,4,13,249,0,28,43,29,26,24), +(10,4,14,266,0,29,45,30,26,24), +(10,4,15,283,0,29,46,30,26,25), +(10,4,16,301,0,30,48,31,26,25), +(10,4,17,320,0,31,50,32,27,25), +(10,4,18,340,0,32,51,33,27,26), +(10,4,19,361,0,33,53,34,27,26), +(10,4,20,383,0,34,55,35,27,27), +(10,4,21,406,0,35,56,35,27,27), +(10,4,22,430,0,36,58,36,28,28), +(10,4,23,455,0,37,60,37,28,28), +(10,4,24,481,0,38,62,38,28,29), +(10,4,25,508,0,39,63,39,28,29), +(10,4,26,536,0,40,65,40,29,30), +(10,4,27,565,0,41,67,41,29,30), +(10,4,28,595,0,42,69,42,29,31), +(10,4,29,626,0,43,71,43,29,31), +(10,4,30,658,0,44,72,43,29,32), +(10,4,31,691,0,45,74,44,30,32), +(10,4,32,725,0,46,76,45,30,33), +(10,4,33,760,0,47,78,46,30,33), +(10,4,34,796,0,48,80,47,31,34), +(10,4,35,833,0,49,82,48,31,34), +(10,4,36,871,0,50,84,49,31,35), +(10,4,37,910,0,51,86,50,31,35), +(10,4,38,950,0,52,88,51,32,36), +(10,4,39,991,0,53,90,52,32,37), +(10,4,40,1033,0,54,92,53,32,37), +(10,4,41,1076,0,56,94,54,33,38), +(10,4,42,1120,0,57,96,55,33,38), +(10,4,43,1165,0,58,98,56,33,39), +(10,4,44,1211,0,59,100,57,33,39), +(10,4,45,1258,0,60,102,59,34,40), +(10,4,46,1306,0,61,104,60,34,41), +(10,4,47,1355,0,62,107,61,34,41), +(10,4,48,1405,0,64,109,62,35,42), +(10,4,49,1456,0,65,111,63,35,43), +(10,4,50,1508,0,66,113,64,35,43), +(10,4,51,1561,0,67,115,65,36,44), +(10,4,52,1615,0,68,117,66,36,44), +(10,4,53,1670,0,70,120,67,36,45), +(10,4,54,1726,0,71,122,69,37,46), +(10,4,55,1783,0,72,124,70,37,46), +(10,4,56,1841,0,73,126,71,37,47), +(10,4,57,1900,0,75,129,72,38,48), +(10,4,58,1960,0,76,131,73,38,48), +(10,4,59,2021,0,77,133,74,39,49), +(10,4,60,2083,0,79,136,76,39,50), +(10,4,61,2272,0,80,138,77,39,51), +(10,4,62,2470,0,81,140,78,40,51), +(10,4,63,2677,0,82,143,79,40,52), +(10,4,64,2893,0,84,145,80,41,53), +(10,4,65,3119,0,85,148,82,41,53), +(10,4,66,3355,0,87,150,83,41,54), +(10,4,67,3601,0,88,153,84,42,55), +(10,4,68,3858,0,89,155,85,42,56), +(10,4,69,4126,0,91,157,87,43,56), +(10,4,70,4405,0,92,160,88,43,57), +(10,5,1,55,220,17,22,19,26,22), +(10,5,2,70,244,17,22,19,27,23), +(10,5,3,85,269,17,22,20,29,25), +(10,5,4,100,295,17,23,20,30,26), +(10,5,5,115,322,18,23,20,31,27), +(10,5,6,130,350,18,23,21,33,29), +(10,5,7,145,379,18,23,21,34,30), +(10,5,8,160,409,18,24,22,35,32), +(10,5,9,175,440,18,24,22,37,33), +(10,5,10,190,472,19,24,22,38,35), +(10,5,11,205,505,19,24,23,39,36), +(10,5,12,220,539,19,24,23,41,38), +(10,5,13,235,574,19,25,24,42,39), +(10,5,14,250,610,19,25,24,44,41), +(10,5,15,265,647,19,25,25,45,42), +(10,5,16,280,685,20,26,25,47,44), +(10,5,17,295,724,20,26,25,48,45), +(10,5,18,310,764,20,26,26,50,47), +(10,5,19,325,805,20,26,26,51,49), +(10,5,20,340,847,21,27,27,53,50), +(10,5,21,355,890,21,27,27,54,52), +(10,5,22,371,934,21,27,28,56,53), +(10,5,23,388,979,21,28,28,58,55), +(10,5,24,406,1025,21,28,29,59,57), +(10,5,25,425,1072,22,28,29,61,58), +(10,5,26,445,1120,22,28,30,62,60), +(10,5,27,466,1169,22,29,30,64,62), +(10,5,28,488,1219,22,29,31,66,64), +(10,5,29,511,1270,23,29,31,67,65), +(10,5,30,535,1322,23,30,32,69,67), +(10,5,31,560,1375,23,30,32,71,69), +(10,5,32,586,1429,23,30,33,72,71), +(10,5,33,613,1483,24,31,33,74,72), +(10,5,34,641,1537,24,31,34,76,74), +(10,5,35,670,1591,24,32,34,78,76), +(10,5,36,700,1645,24,32,35,80,78), +(10,5,37,731,1699,25,32,35,81,80), +(10,5,38,763,1753,25,33,36,83,82), +(10,5,39,796,1807,25,33,37,85,84), +(10,5,40,830,1861,26,33,37,87,86), +(10,5,41,865,1915,26,34,38,89,88), +(10,5,42,901,1969,26,34,38,91,89), +(10,5,43,938,2023,27,35,39,92,91), +(10,5,44,976,2077,27,35,39,94,93), +(10,5,45,1015,2131,27,35,40,96,95), +(10,5,46,1055,2185,27,36,41,98,97), +(10,5,47,1096,2239,28,36,41,100,99), +(10,5,48,1138,2293,28,37,42,102,101), +(10,5,49,1181,2347,28,37,43,104,103), +(10,5,50,1225,2401,29,37,43,106,106), +(10,5,51,1270,2455,29,38,44,108,108), +(10,5,52,1316,2509,29,38,44,110,110), +(10,5,53,1363,2563,30,39,45,112,112), +(10,5,54,1411,2617,30,39,46,114,114), +(10,5,55,1460,2671,30,40,46,116,116), +(10,5,56,1510,2725,31,40,47,118,118), +(10,5,57,1561,2779,31,41,48,120,120), +(10,5,58,1613,2833,31,41,48,123,123), +(10,5,59,1666,2887,32,42,49,125,125), +(10,5,60,1720,2941,32,42,50,127,127), +(10,5,61,1890,3110,33,42,51,129,129), +(10,5,62,2068,3264,33,43,51,131,131), +(10,5,63,2254,3433,33,43,52,133,134), +(10,5,64,2448,3587,34,44,53,135,136), +(10,5,65,2650,3756,34,44,53,138,138), +(10,5,66,2861,3910,34,45,54,140,141), +(10,5,67,3081,4079,35,45,55,142,143), +(10,5,68,3310,4233,35,46,56,144,145), +(10,5,69,3548,4402,36,46,56,147,148), +(10,5,70,3795,4571,36,47,57,149,150), +(10,8,1,55,225,17,22,19,27,21), +(10,8,2,70,250,17,22,19,28,22), +(10,8,3,85,276,17,22,20,30,24), +(10,8,4,100,303,17,22,20,31,25), +(10,8,5,115,331,17,23,20,32,26), +(10,8,6,130,360,17,23,20,34,28), +(10,8,7,145,390,18,23,21,35,29), +(10,8,8,160,421,18,23,21,37,30), +(10,8,9,175,453,18,23,21,38,32), +(10,8,10,190,486,18,23,22,40,33), +(10,8,11,205,520,18,24,22,41,35), +(10,8,12,220,555,18,24,22,42,36), +(10,8,13,235,591,18,24,23,44,37), +(10,8,14,250,628,18,24,23,45,39), +(10,8,15,265,666,18,24,23,47,40), +(10,8,16,280,705,19,24,24,49,42), +(10,8,17,295,745,19,25,24,50,43), +(10,8,18,310,786,19,25,24,52,45), +(10,8,19,325,828,19,25,25,53,46), +(10,8,20,340,871,19,25,25,55,48), +(10,8,21,355,915,19,25,26,57,50), +(10,8,22,370,960,19,26,26,58,51), +(10,8,23,385,1006,20,26,26,60,53), +(10,8,24,401,1053,20,26,27,61,54), +(10,8,25,418,1101,20,26,27,63,56), +(10,8,26,436,1150,20,27,27,65,58), +(10,8,27,455,1200,20,27,28,67,59), +(10,8,28,475,1251,20,27,28,68,61), +(10,8,29,496,1302,21,27,29,70,63), +(10,8,30,518,1353,21,28,29,72,64), +(10,8,31,541,1404,21,28,30,74,66), +(10,8,32,565,1455,21,28,30,75,68), +(10,8,33,590,1506,21,28,30,77,70), +(10,8,34,616,1557,21,29,31,79,71), +(10,8,35,643,1608,22,29,31,81,73), +(10,8,36,671,1659,22,29,32,83,75), +(10,8,37,700,1710,22,29,32,85,77), +(10,8,38,730,1761,22,30,33,86,78), +(10,8,39,761,1812,22,30,33,88,80), +(10,8,40,793,1863,23,30,34,90,82), +(10,8,41,826,1914,23,31,34,92,84), +(10,8,42,860,1965,23,31,35,94,86), +(10,8,43,895,2016,23,31,35,96,88), +(10,8,44,931,2067,23,32,36,98,90), +(10,8,45,968,2118,24,32,36,100,92), +(10,8,46,1006,2169,24,32,37,102,93), +(10,8,47,1045,2220,24,32,37,104,95), +(10,8,48,1085,2271,24,33,38,106,97), +(10,8,49,1126,2322,25,33,38,108,99), +(10,8,50,1168,2373,25,33,39,110,101), +(10,8,51,1211,2424,25,34,39,112,103), +(10,8,52,1255,2475,25,34,40,114,105), +(10,8,53,1300,2526,25,35,40,117,107), +(10,8,54,1346,2577,26,35,41,119,109), +(10,8,55,1393,2628,26,35,41,121,111), +(10,8,56,1441,2679,26,36,42,123,113), +(10,8,57,1490,2730,26,36,42,125,116), +(10,8,58,1540,2781,27,36,43,127,118), +(10,8,59,1591,2832,27,37,43,130,120), +(10,8,60,1643,2883,27,37,44,132,122), +(10,8,61,1809,3016,27,37,45,134,124), +(10,8,62,1984,3164,28,38,45,136,126), +(10,8,63,2168,3297,28,38,46,139,128), +(10,8,64,2361,3445,28,39,46,141,131), +(10,8,65,2563,3578,29,39,47,143,133), +(10,8,66,2775,3726,29,39,48,146,135), +(10,8,67,2997,3859,29,40,48,148,137), +(10,8,68,3229,4007,29,40,49,150,139), +(10,8,69,3472,4140,30,41,49,153,142), +(10,8,70,3726,4288,30,41,50,155,144), +(10,9,1,42,197,17,22,20,26,21), +(10,9,2,57,220,17,22,21,27,22), +(10,9,3,72,244,18,23,21,28,23), +(10,9,4,87,269,18,23,22,29,24), +(10,9,5,102,295,18,23,22,31,26), +(10,9,6,117,322,18,24,23,32,27), +(10,9,7,132,350,19,24,23,33,28), +(10,9,8,147,379,19,25,24,34,29), +(10,9,9,162,409,19,25,25,36,30), +(10,9,10,177,440,20,25,25,37,32), +(10,9,11,192,472,20,26,26,38,33), +(10,9,12,207,505,20,26,26,39,34), +(10,9,13,222,539,21,27,27,41,36), +(10,9,14,237,574,21,27,28,42,37), +(10,9,15,252,610,21,27,28,43,38), +(10,9,16,267,647,22,28,29,45,39), +(10,9,17,282,685,22,28,30,46,41), +(10,9,18,298,724,23,29,30,47,42), +(10,9,19,315,764,23,29,31,49,43), +(10,9,20,333,805,23,30,32,50,45), +(10,9,21,352,847,24,30,32,51,46), +(10,9,22,372,890,24,31,33,53,48), +(10,9,23,393,934,24,31,34,54,49), +(10,9,24,415,979,25,31,34,56,50), +(10,9,25,438,1025,25,32,35,57,52), +(10,9,26,462,1072,26,32,36,59,53), +(10,9,27,487,1120,26,33,37,60,55), +(10,9,28,513,1169,26,33,37,62,56), +(10,9,29,540,1219,27,34,38,63,58), +(10,9,30,568,1270,27,34,39,65,59), +(10,9,31,597,1321,28,35,40,66,61), +(10,9,32,627,1372,28,36,40,68,62), +(10,9,33,658,1423,29,36,41,69,64), +(10,9,34,690,1474,29,37,42,71,65), +(10,9,35,723,1525,29,37,43,73,67), +(10,9,36,757,1576,30,38,43,74,69), +(10,9,37,792,1627,30,38,44,76,70), +(10,9,38,828,1678,31,39,45,77,72), +(10,9,39,865,1729,31,39,46,79,73), +(10,9,40,903,1780,32,40,47,81,75), +(10,9,41,942,1831,32,41,48,82,77), +(10,9,42,982,1882,33,41,48,84,78), +(10,9,43,1023,1933,33,42,49,86,80), +(10,9,44,1065,1984,34,42,50,88,82), +(10,9,45,1108,2035,34,43,51,89,83), +(10,9,46,1152,2086,35,44,52,91,85), +(10,9,47,1197,2137,35,44,53,93,87), +(10,9,48,1243,2188,36,45,54,95,89), +(10,9,49,1290,2239,36,45,54,96,90), +(10,9,50,1338,2290,37,46,55,98,92), +(10,9,51,1387,2341,37,47,56,100,94), +(10,9,52,1437,2392,38,47,57,102,96), +(10,9,53,1488,2443,38,48,58,104,97), +(10,9,54,1540,2494,39,49,59,105,99), +(10,9,55,1593,2545,39,49,60,107,101), +(10,9,56,1647,2596,40,50,61,109,103), +(10,9,57,1702,2647,40,51,62,111,105), +(10,9,58,1758,2698,41,51,63,113,107), +(10,9,59,1815,2749,42,52,64,115,108), +(10,9,60,1873,2800,42,53,65,117,110), +(10,9,61,2049,2954,43,53,66,119,112), +(10,9,62,2234,3108,43,54,67,121,114), +(10,9,63,2428,3277,44,55,68,123,116), +(10,9,64,2631,3431,44,56,69,125,118), +(10,9,65,2843,3585,45,56,70,127,120), +(10,9,66,3065,3754,46,57,71,129,122), +(10,9,67,3297,3908,46,58,72,131,124), +(10,9,68,3540,4062,47,58,73,133,126), +(10,9,69,3794,4231,47,59,74,135,128), +(10,9,70,4059,4385,48,60,75,137,130), +(11,1,1,50,0,24,17,21,21,22), +(11,1,2,69,0,25,18,22,21,22), +(11,1,3,88,0,27,19,23,21,23), +(11,1,4,107,0,28,19,25,21,23), +(11,1,5,126,0,29,20,26,21,23), +(11,1,6,145,0,31,21,27,21,23), +(11,1,7,164,0,32,22,28,21,24), +(11,1,8,183,0,33,23,29,22,24), +(11,1,9,202,0,35,24,31,22,24), +(11,1,10,221,0,36,24,32,22,25), +(11,1,11,240,0,37,25,33,22,25), +(11,1,12,259,0,39,26,34,22,25), +(11,1,13,278,0,40,27,36,22,26), +(11,1,14,298,0,42,28,37,22,26), +(11,1,15,319,0,43,29,38,22,26), +(11,1,16,341,0,45,30,40,22,27), +(11,1,17,364,0,46,31,41,23,27), +(11,1,18,388,0,48,32,43,23,27), +(11,1,19,413,0,49,33,44,23,28), +(11,1,20,439,0,51,34,45,23,28), +(11,1,21,466,0,52,34,47,23,28), +(11,1,22,494,0,54,35,48,23,29), +(11,1,23,523,0,55,36,50,23,29), +(11,1,24,553,0,57,37,51,24,30), +(11,1,25,584,0,59,38,52,24,30), +(11,1,26,616,0,60,39,54,24,30), +(11,1,27,649,0,62,40,55,24,31), +(11,1,28,683,0,63,41,57,24,31), +(11,1,29,718,0,65,43,58,24,32), +(11,1,30,754,0,67,44,60,24,32), +(11,1,31,791,0,69,45,62,25,32), +(11,1,32,829,0,70,46,63,25,33), +(11,1,33,868,0,72,47,65,25,33), +(11,1,34,908,0,74,48,66,25,34), +(11,1,35,949,0,75,49,68,25,34), +(11,1,36,991,0,77,50,69,26,35), +(11,1,37,1035,0,79,51,71,26,35), +(11,1,38,1081,0,81,52,73,26,35), +(11,1,39,1129,0,83,53,74,26,36), +(11,1,40,1179,0,84,55,76,26,36), +(11,1,41,1231,0,86,56,78,27,37), +(11,1,42,1285,0,88,57,79,27,37), +(11,1,43,1341,0,90,58,81,27,38), +(11,1,44,1399,0,92,59,83,27,38), +(11,1,45,1459,0,94,60,85,27,39), +(11,1,46,1521,0,96,62,86,28,39), +(11,1,47,1585,0,98,63,88,28,40), +(11,1,48,1651,0,100,64,90,28,40), +(11,1,49,1719,0,102,65,92,28,41), +(11,1,50,1789,0,103,66,93,29,41), +(11,1,51,1861,0,105,68,95,29,42), +(11,1,52,1935,0,107,69,97,29,42), +(11,1,53,2011,0,109,70,99,29,43), +(11,1,54,2089,0,112,71,101,30,44), +(11,1,55,2169,0,114,73,103,30,44), +(11,1,56,2251,0,116,74,104,30,45), +(11,1,57,2335,0,118,75,106,30,45), +(11,1,58,2421,0,120,77,108,31,46), +(11,1,59,2509,0,122,78,110,31,46), +(11,1,60,2599,0,124,79,112,31,47), +(11,1,61,2832,0,126,81,114,31,48), +(11,1,62,3079,0,128,82,116,32,48), +(11,1,63,3340,0,130,83,118,32,49), +(11,1,64,3615,0,133,85,120,32,49), +(11,1,65,3905,0,135,86,122,33,50), +(11,1,66,4210,0,137,87,124,33,51), +(11,1,67,4530,0,139,89,126,33,51), +(11,1,68,4866,0,141,90,128,33,52), +(11,1,69,5218,0,144,92,130,34,52), +(11,1,70,5586,0,146,93,132,34,53), +(11,2,1,48,95,23,17,21,21,23), +(11,2,2,66,114,24,18,22,22,24), +(11,2,3,84,134,25,18,23,22,24), +(11,2,4,102,155,26,19,24,23,25), +(11,2,5,120,177,27,19,25,24,26), +(11,2,6,138,200,29,20,26,24,26), +(11,2,7,156,224,30,21,27,25,27), +(11,2,8,174,249,31,21,28,26,28), +(11,2,9,192,275,32,22,29,26,29), +(11,2,10,210,302,33,22,31,27,29), +(11,2,11,228,330,34,23,32,28,30), +(11,2,12,246,359,36,24,33,28,31), +(11,2,13,264,389,37,24,34,29,32), +(11,2,14,282,420,38,25,35,30,32), +(11,2,15,301,452,39,26,36,31,33), +(11,2,16,321,485,40,26,37,31,34), +(11,2,17,342,519,42,27,39,32,35), +(11,2,18,364,554,43,28,40,33,36), +(11,2,19,387,590,44,28,41,34,37), +(11,2,20,411,627,46,29,42,34,37), +(11,2,21,436,665,47,30,44,35,38), +(11,2,22,462,704,48,31,45,36,39), +(11,2,23,489,744,50,31,46,37,40), +(11,2,24,517,785,51,32,47,38,41), +(11,2,25,546,827,52,33,49,38,42), +(11,2,26,576,869,54,34,50,39,43), +(11,2,27,607,911,55,34,51,40,44), +(11,2,28,639,953,56,35,53,41,44), +(11,2,29,672,995,58,36,54,42,45), +(11,2,30,706,1037,59,37,55,43,46), +(11,2,31,741,1079,61,37,57,43,47), +(11,2,32,777,1121,62,38,58,44,48), +(11,2,33,814,1163,64,39,59,45,49), +(11,2,34,852,1205,65,40,61,46,50), +(11,2,35,891,1247,67,41,62,47,51), +(11,2,36,931,1289,68,42,64,48,52), +(11,2,37,972,1331,70,42,65,49,53), +(11,2,38,1014,1373,71,43,67,50,54), +(11,2,39,1057,1415,73,44,68,51,55), +(11,2,40,1101,1457,74,45,69,52,56), +(11,2,41,1146,1499,76,46,71,53,57), +(11,2,42,1192,1541,78,47,72,54,58), +(11,2,43,1239,1583,79,47,74,55,59), +(11,2,44,1287,1625,81,48,75,56,60), +(11,2,45,1336,1667,82,49,77,57,61), +(11,2,46,1386,1709,84,50,78,58,62), +(11,2,47,1437,1751,86,51,80,59,64), +(11,2,48,1489,1793,87,52,82,60,65), +(11,2,49,1542,1835,89,53,83,61,66), +(11,2,50,1596,1877,91,54,85,62,67), +(11,2,51,1651,1919,92,55,86,63,68), +(11,2,52,1707,1961,94,56,88,64,69), +(11,2,53,1764,2003,96,57,90,65,70), +(11,2,54,1822,2045,97,58,91,66,71), +(11,2,55,1881,2087,99,59,93,67,73), +(11,2,56,1941,2129,101,60,95,68,74), +(11,2,57,2002,2171,103,61,96,69,75), +(11,2,58,2064,2213,105,62,98,70,76), +(11,2,59,2127,2255,106,63,100,71,77), +(11,2,60,2191,2297,108,64,101,72,78), +(11,2,61,2371,2456,110,65,103,74,80), +(11,2,62,2559,2615,112,66,105,75,81), +(11,2,63,2755,2789,114,67,106,76,82), +(11,2,64,2960,2948,116,68,108,77,83), +(11,2,65,3174,3107,117,69,110,78,85), +(11,2,66,3397,3281,119,70,112,79,86), +(11,2,67,3630,3440,121,71,114,80,87), +(11,2,68,3873,3599,123,72,115,82,88), +(11,2,69,4126,3773,125,73,117,83,90), +(11,2,70,4389,3932,127,74,119,84,91), +(11,3,1,46,100,21,20,20,21,23), +(11,3,2,63,120,21,21,21,22,24), +(11,3,3,80,141,22,23,22,22,24), +(11,3,4,97,163,22,24,23,23,25), +(11,3,5,114,186,23,25,24,23,25), +(11,3,6,131,210,23,27,25,24,26), +(11,3,7,148,235,24,28,26,24,27), +(11,3,8,165,261,24,30,27,25,27), +(11,3,9,182,288,25,31,27,26,28), +(11,3,10,199,316,25,33,28,26,29), +(11,3,11,216,345,25,34,29,27,29), +(11,3,12,233,375,26,36,30,28,30), +(11,3,13,250,406,26,37,31,28,31), +(11,3,14,268,438,27,39,32,29,32), +(11,3,15,287,471,27,40,34,30,32), +(11,3,16,307,505,28,42,35,30,33), +(11,3,17,328,540,28,43,36,31,34), +(11,3,18,350,576,29,45,37,32,35), +(11,3,19,373,613,29,47,38,32,35), +(11,3,20,397,651,30,48,39,33,36), +(11,3,21,422,690,31,50,40,34,37), +(11,3,22,448,730,31,51,41,34,38), +(11,3,23,475,771,32,53,42,35,38), +(11,3,24,503,813,32,55,43,36,39), +(11,3,25,532,856,33,57,44,37,40), +(11,3,26,562,900,33,58,46,37,41), +(11,3,27,593,945,34,60,47,38,42), +(11,3,28,625,990,35,62,48,39,42), +(11,3,29,658,1035,35,63,49,40,43), +(11,3,30,692,1080,36,65,50,40,44), +(11,3,31,727,1125,36,67,52,41,45), +(11,3,32,763,1170,37,69,53,42,46), +(11,3,33,800,1215,38,71,54,43,47), +(11,3,34,838,1260,38,72,55,44,48), +(11,3,35,877,1305,39,74,57,44,48), +(11,3,36,917,1350,39,76,58,45,49), +(11,3,37,958,1395,40,78,59,46,50), +(11,3,38,1000,1440,41,80,60,47,51), +(11,3,39,1043,1485,41,82,62,48,52), +(11,3,40,1087,1530,42,84,63,49,53), +(11,3,41,1132,1575,43,86,64,50,54), +(11,3,42,1178,1620,43,88,66,50,55), +(11,3,43,1225,1665,44,90,67,51,56), +(11,3,44,1273,1710,45,91,68,52,57), +(11,3,45,1322,1755,45,93,70,53,58), +(11,3,46,1372,1800,46,95,71,54,59), +(11,3,47,1423,1845,47,98,72,55,60), +(11,3,48,1475,1890,48,100,74,56,61), +(11,3,49,1528,1935,48,102,75,57,62), +(11,3,50,1582,1980,49,104,77,58,63), +(11,3,51,1637,2025,50,106,78,59,64), +(11,3,52,1693,2070,51,108,79,60,65), +(11,3,53,1750,2115,51,110,81,61,66), +(11,3,54,1808,2160,52,112,82,61,67), +(11,3,55,1867,2205,53,114,84,62,68), +(11,3,56,1927,2250,54,116,85,63,69), +(11,3,57,1988,2295,54,118,87,64,70), +(11,3,58,2050,2340,55,121,88,65,71), +(11,3,59,2113,2385,56,123,90,66,72), +(11,3,60,2177,2430,57,125,91,67,74), +(11,3,61,2363,2611,58,127,93,68,75), +(11,3,62,2558,2792,58,130,94,69,76), +(11,3,63,2762,2973,59,132,96,71,77), +(11,3,64,2975,3154,60,134,97,72,78), +(11,3,65,3197,3350,61,136,99,73,79), +(11,3,66,3429,3531,62,139,101,74,80), +(11,3,67,3671,3712,62,141,102,75,81), +(11,3,68,3923,3893,63,143,104,76,83), +(11,3,69,4185,4074,64,146,105,77,84), +(11,3,70,4458,4270,65,148,107,78,85), +(11,5,1,51,175,21,17,19,23,25), +(11,5,2,66,199,21,17,19,24,26), +(11,5,3,81,224,21,17,20,26,28), +(11,5,4,96,250,21,18,20,27,29), +(11,5,5,111,277,22,18,20,28,30), +(11,5,6,126,305,22,18,21,30,32), +(11,5,7,141,334,22,18,21,31,33), +(11,5,8,156,364,22,19,22,32,35), +(11,5,9,171,395,22,19,22,34,36), +(11,5,10,186,427,22,19,22,35,38), +(11,5,11,201,460,23,19,23,37,39), +(11,5,12,216,494,23,20,23,38,41), +(11,5,13,231,529,23,20,24,39,42), +(11,5,14,246,565,23,20,24,41,44), +(11,5,15,261,602,23,20,25,42,45), +(11,5,16,276,640,24,21,25,44,47), +(11,5,17,291,679,24,21,25,45,48), +(11,5,18,306,719,24,21,26,47,50), +(11,5,19,321,760,24,22,26,48,51), +(11,5,20,336,802,24,22,27,50,53), +(11,5,21,351,845,25,22,27,51,55), +(11,5,22,367,889,25,22,28,53,56), +(11,5,23,384,934,25,23,28,55,58), +(11,5,24,402,980,25,23,29,56,60), +(11,5,25,421,1027,25,23,29,58,61), +(11,5,26,441,1075,26,24,30,60,63), +(11,5,27,462,1124,26,24,30,61,65), +(11,5,28,484,1174,26,24,31,63,66), +(11,5,29,507,1225,26,25,31,65,68), +(11,5,30,531,1277,27,25,32,66,70), +(11,5,31,556,1330,27,25,32,68,72), +(11,5,32,582,1384,27,26,33,70,73), +(11,5,33,609,1438,27,26,33,71,75), +(11,5,34,637,1492,28,26,34,73,77), +(11,5,35,666,1546,28,27,34,75,79), +(11,5,36,696,1600,28,27,35,77,81), +(11,5,37,727,1654,29,28,35,79,83), +(11,5,38,759,1708,29,28,36,80,85), +(11,5,39,792,1762,29,28,37,82,86), +(11,5,40,826,1816,29,29,37,84,88), +(11,5,41,861,1870,30,29,38,86,90), +(11,5,42,897,1924,30,29,38,88,92), +(11,5,43,934,1978,30,30,39,90,94), +(11,5,44,972,2032,31,30,39,91,96), +(11,5,45,1011,2086,31,31,40,93,98), +(11,5,46,1051,2140,31,31,41,95,100), +(11,5,47,1092,2194,32,31,41,97,102), +(11,5,48,1134,2248,32,32,42,99,104), +(11,5,49,1177,2302,32,32,43,101,106), +(11,5,50,1221,2356,33,33,43,103,108), +(11,5,51,1266,2410,33,33,44,105,110), +(11,5,52,1312,2464,33,34,44,107,113), +(11,5,53,1359,2518,34,34,45,109,115), +(11,5,54,1407,2572,34,34,46,111,117), +(11,5,55,1456,2626,34,35,46,113,119), +(11,5,56,1506,2680,35,35,47,115,121), +(11,5,57,1557,2734,35,36,48,118,123), +(11,5,58,1609,2788,35,36,48,120,126), +(11,5,59,1662,2842,36,37,49,122,128), +(11,5,60,1716,2896,36,37,50,124,130), +(11,5,61,1886,3065,36,38,51,126,132), +(11,5,62,2064,3219,37,38,51,128,134), +(11,5,63,2250,3388,37,39,52,130,137), +(11,5,64,2444,3542,38,39,53,133,139), +(11,5,65,2646,3711,38,40,53,135,141), +(11,5,66,2857,3865,38,40,54,137,144), +(11,5,67,3077,4034,39,40,55,139,146), +(11,5,68,3306,4188,39,41,56,141,148), +(11,5,69,3544,4357,40,41,56,144,151), +(11,5,70,3791,4526,40,42,57,146,153), +(11,7,1,47,105,22,17,20,22,24), +(11,7,2,64,126,23,17,21,23,25), +(11,7,3,81,148,24,18,22,24,26), +(11,7,4,98,171,25,18,23,25,27), +(11,7,5,115,195,25,19,24,26,28), +(11,7,6,132,220,26,19,25,27,29), +(11,7,7,149,246,27,20,26,28,30), +(11,7,8,166,273,28,20,27,28,31), +(11,7,9,183,301,29,21,28,29,32), +(11,7,10,200,330,30,21,29,30,33), +(11,7,11,217,360,31,22,30,31,35), +(11,7,12,234,391,32,22,31,32,36), +(11,7,13,251,423,33,23,32,33,37), +(11,7,14,268,456,34,23,33,34,38), +(11,7,15,285,490,34,24,35,35,39), +(11,7,16,302,525,35,24,36,36,40), +(11,7,17,320,561,36,25,37,38,42), +(11,7,18,339,598,37,25,38,39,43), +(11,7,19,359,636,38,26,39,40,44), +(11,7,20,380,675,39,26,40,41,45), +(11,7,21,402,715,40,27,41,42,46), +(11,7,22,425,756,41,27,43,43,48), +(11,7,23,449,798,43,28,44,44,49), +(11,7,24,474,841,44,28,45,45,50), +(11,7,25,500,885,45,29,46,46,51), +(11,7,26,527,930,46,30,47,48,53), +(11,7,27,555,976,47,30,49,49,54), +(11,7,28,584,1023,48,31,50,50,55), +(11,7,29,614,1071,49,31,51,51,57), +(11,7,30,645,1120,50,32,53,52,58), +(11,7,31,677,1170,51,33,54,53,59), +(11,7,32,710,1221,52,33,55,55,61), +(11,7,33,744,1272,53,34,56,56,62), +(11,7,34,779,1323,55,34,58,57,64), +(11,7,35,815,1374,56,35,59,58,65), +(11,7,36,852,1425,57,36,60,60,66), +(11,7,37,890,1476,58,36,62,61,68), +(11,7,38,929,1527,59,37,63,62,69), +(11,7,39,969,1578,61,38,65,63,71), +(11,7,40,1010,1629,62,38,66,65,72), +(11,7,41,1052,1680,63,39,67,66,74), +(11,7,42,1095,1731,64,40,69,67,75), +(11,7,43,1139,1782,65,40,70,69,77), +(11,7,44,1184,1833,67,41,72,70,78), +(11,7,45,1230,1884,68,42,73,71,80), +(11,7,46,1277,1935,69,42,75,73,81), +(11,7,47,1325,1986,71,43,76,74,83), +(11,7,48,1374,2037,72,44,78,76,84), +(11,7,49,1424,2088,73,45,79,77,86), +(11,7,50,1475,2139,74,45,81,78,88), +(11,7,51,1527,2190,76,46,82,80,89), +(11,7,52,1580,2241,77,47,84,81,91), +(11,7,53,1634,2292,78,47,85,83,92), +(11,7,54,1689,2343,80,48,87,84,94), +(11,7,55,1745,2394,81,49,88,86,96), +(11,7,56,1802,2445,83,50,90,87,97), +(11,7,57,1860,2496,84,50,91,89,99), +(11,7,58,1919,2547,85,51,93,90,101), +(11,7,59,1979,2598,87,52,95,92,102), +(11,7,60,2040,2649,88,53,96,93,104), +(11,7,61,2208,2808,90,54,98,95,106), +(11,7,62,2384,2967,91,54,99,96,108), +(11,7,63,2568,3141,93,55,101,98,109), +(11,7,64,2760,3300,94,56,103,99,111), +(11,7,65,2961,3459,95,57,104,101,113), +(11,7,66,3171,3633,97,58,106,103,115), +(11,7,67,3391,3792,98,58,108,104,117), +(11,7,68,3621,3951,100,59,110,106,118), +(11,7,69,3861,4125,101,60,111,107,120), +(11,7,70,4111,4284,103,61,113,109,122), +(11,8,1,51,180,21,17,19,24,24), +(11,8,2,66,205,21,17,19,25,25), +(11,8,3,81,231,21,17,20,27,27), +(11,8,4,96,258,21,17,20,28,28), +(11,8,5,111,286,21,18,20,29,29), +(11,8,6,126,315,21,18,20,31,31), +(11,8,7,141,345,21,18,21,32,32), +(11,8,8,156,376,22,18,21,34,33), +(11,8,9,171,408,22,18,21,35,35), +(11,8,10,186,441,22,19,22,37,36), +(11,8,11,201,475,22,19,22,38,37), +(11,8,12,216,510,22,19,22,40,39), +(11,8,13,231,546,22,19,23,41,40), +(11,8,14,246,583,22,19,23,43,42), +(11,8,15,261,621,22,19,23,44,43), +(11,8,16,276,660,22,20,24,46,45), +(11,8,17,291,700,23,20,24,47,46), +(11,8,18,306,741,23,20,24,49,48), +(11,8,19,321,783,23,20,25,50,49), +(11,8,20,336,826,23,21,25,52,51), +(11,8,21,351,870,23,21,26,54,52), +(11,8,22,366,915,23,21,26,55,54), +(11,8,23,381,961,23,21,26,57,56), +(11,8,24,397,1008,24,21,27,59,57), +(11,8,25,414,1056,24,22,27,60,59), +(11,8,26,432,1105,24,22,27,62,60), +(11,8,27,451,1155,24,22,28,64,62), +(11,8,28,471,1206,24,22,28,65,64), +(11,8,29,492,1257,24,23,29,67,65), +(11,8,30,514,1308,24,23,29,69,67), +(11,8,31,537,1359,25,23,30,71,69), +(11,8,32,561,1410,25,23,30,73,71), +(11,8,33,586,1461,25,24,30,74,72), +(11,8,34,612,1512,25,24,31,76,74), +(11,8,35,639,1563,25,24,31,78,76), +(11,8,36,667,1614,26,24,32,80,78), +(11,8,37,696,1665,26,25,32,82,79), +(11,8,38,726,1716,26,25,33,84,81), +(11,8,39,757,1767,26,25,33,86,83), +(11,8,40,789,1818,26,26,34,87,85), +(11,8,41,822,1869,27,26,34,89,87), +(11,8,42,856,1920,27,26,35,91,89), +(11,8,43,891,1971,27,27,35,93,91), +(11,8,44,927,2022,27,27,36,95,92), +(11,8,45,964,2073,27,27,36,97,94), +(11,8,46,1002,2124,28,27,37,99,96), +(11,8,47,1041,2175,28,28,37,101,98), +(11,8,48,1081,2226,28,28,38,103,100), +(11,8,49,1122,2277,28,28,38,105,102), +(11,8,50,1164,2328,29,29,39,107,104), +(11,8,51,1207,2379,29,29,39,110,106), +(11,8,52,1251,2430,29,29,40,112,108), +(11,8,53,1296,2481,29,30,40,114,110), +(11,8,54,1342,2532,30,30,41,116,112), +(11,8,55,1389,2583,30,30,41,118,114), +(11,8,56,1437,2634,30,31,42,120,116), +(11,8,57,1486,2685,30,31,42,122,118), +(11,8,58,1536,2736,31,31,43,125,121), +(11,8,59,1587,2787,31,32,43,127,123), +(11,8,60,1639,2838,31,32,44,129,125), +(11,8,61,1805,2971,31,33,45,131,127), +(11,8,62,1980,3119,32,33,45,133,129), +(11,8,63,2164,3252,32,33,46,136,131), +(11,8,64,2357,3400,32,34,46,138,134), +(11,8,65,2559,3533,33,34,47,140,136), +(11,8,66,2771,3681,33,34,48,143,138), +(11,8,67,2993,3814,33,35,48,145,140), +(11,8,68,3225,3962,33,35,49,147,142), +(11,8,69,3468,4095,34,36,49,150,145), +(11,8,70,3722,4243,34,36,50,152,147); +/*!40000 ALTER TABLE `player_levelstats` ENABLE KEYS */; +UNLOCK TABLES; diff --git a/sql/updates/0.8/4540_battleground_template.sql b/sql/updates/0.8/4540_battleground_template.sql new file mode 100644 index 00000000000..4397f4d35bc --- /dev/null +++ b/sql/updates/0.8/4540_battleground_template.sql @@ -0,0 +1 @@ +ALTER TABLE `battleground_template` ADD `MinPlayersPerTeam` int(11) unsigned NOT NULL default '0' AFTER `id`; \ No newline at end of file diff --git a/sql/updates/0.8/4544_creature_addon.sql b/sql/updates/0.8/4544_creature_addon.sql new file mode 100644 index 00000000000..182b9362c98 --- /dev/null +++ b/sql/updates/0.8/4544_creature_addon.sql @@ -0,0 +1,2 @@ +ALTER TABLE `creature_addon` + DROP COLUMN `RefId`; diff --git a/sql/updates/0.8/4544_creature_template_addon.sql b/sql/updates/0.8/4544_creature_template_addon.sql new file mode 100644 index 00000000000..685a40434cc --- /dev/null +++ b/sql/updates/0.8/4544_creature_template_addon.sql @@ -0,0 +1,17 @@ +DROP TABLE IF EXISTS `creature_template_addon`; +CREATE TABLE `creature_template_addon` ( + `entry` int(11) NOT NULL default '0', + `mount` int(11) unsigned NOT NULL default '0', + `bytes0` int(11) unsigned NOT NULL default '0', + `bytes1` int(11) unsigned NOT NULL default '0', + `bytes2` int(11) unsigned NOT NULL default '0', + `emote` int(11) unsigned NOT NULL default '0', + `aura` int(11) unsigned NOT NULL default '0', + `auraflags` int(11) unsigned NOT NULL default '0', + `auralevels` int(11) unsigned NOT NULL default '0', + `auraapplications` int(11) unsigned NOT NULL default '0', + `aurastate` int(11) unsigned NOT NULL default '0', + UNIQUE KEY `entry` (`entry`), + KEY `emote` (`emote`,`mount`,`aura`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + diff --git a/sql/updates/0.8/4547_spell_affect.sql b/sql/updates/0.8/4547_spell_affect.sql new file mode 100644 index 00000000000..5d4b921464a --- /dev/null +++ b/sql/updates/0.8/4547_spell_affect.sql @@ -0,0 +1,4 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (23565, 31821); +INSERT INTO `spell_affect` VALUES +(31821,0,0,0,0,0,0,67240008,0), +(23565,0,0,0,0,0,0,67240008,0); diff --git a/sql/updates/0.8/4547_spell_proc_event.sql b/sql/updates/0.8/4547_spell_proc_event.sql new file mode 100644 index 00000000000..2acc33ca5fc --- /dev/null +++ b/sql/updates/0.8/4547_spell_proc_event.sql @@ -0,0 +1,7 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (20127,20130,20135,20136,20137); +INSERT INTO `spell_proc_event` VALUES +(20127,0,0,0,0,0,1026,0), +(20130,0,0,0,0,0,1026,0), +(20135,0,0,0,0,0,1026,0), +(20136,0,0,0,0,0,1026,0), +(20137,0,0,0,0,0,1026,0); diff --git a/sql/updates/0.8/4551_item_template.sql b/sql/updates/0.8/4551_item_template.sql new file mode 100644 index 00000000000..02f6f434240 --- /dev/null +++ b/sql/updates/0.8/4551_item_template.sql @@ -0,0 +1,2 @@ +ALTER TABLE `item_template` + ADD COLUMN `FoodType` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `DisenchantID`; diff --git a/sql/updates/0.8/4556_realmlist.sql b/sql/updates/0.8/4556_realmlist.sql new file mode 100644 index 00000000000..09a9477cecf --- /dev/null +++ b/sql/updates/0.8/4556_realmlist.sql @@ -0,0 +1,3 @@ +ALTER TABLE realmd.realmlist + ALTER COLUMN `color` SET DEFAULT '2', + ENGINE = MyISAM; diff --git a/sql/updates/0.8/4561_command.sql b/sql/updates/0.8/4561_command.sql new file mode 100644 index 00000000000..d9683a4feeb --- /dev/null +++ b/sql/updates/0.8/4561_command.sql @@ -0,0 +1,4 @@ +DELETE FROM command WHERE name IN ('plimit'); +INSERT INTO `command` VALUES +('plimit',3,'Syntax: .plimit [#num|-1|-2|-3|default|player|moderator|gamemaster|administrator]\r\n Without arg show current player amount and security level limitations for login to server, with arg set player linit ($num > 0) or securiti limitation ($num < 0 or security leme name. With `default` arg set default for server player limit (100)'); + diff --git a/sql/updates/0.8/4571_button_scripts.sql b/sql/updates/0.8/4571_button_scripts.sql new file mode 100644 index 00000000000..034bb8d0a57 --- /dev/null +++ b/sql/updates/0.8/4571_button_scripts.sql @@ -0,0 +1,17 @@ +-- +-- Table structure for table `button_scripts` +-- + +DROP TABLE IF EXISTS `button_scripts`; +CREATE TABLE `button_scripts` ( + `id` int(11) unsigned NOT NULL default '0', + `delay` int(11) unsigned NOT NULL default '0', + `command` int(11) unsigned NOT NULL default '0', + `datalong` int(11) unsigned NOT NULL default '0', + `datalong2` int(11) unsigned NOT NULL default '0', + `datatext` text NOT NULL, + `x` float NOT NULL default '0', + `y` float NOT NULL default '0', + `z` float NOT NULL default '0', + `o` float NOT NULL default '0' +) ENGINE=MyISAM DEFAULT CHARSET=utf8; diff --git a/sql/updates/0.8/4577_gameobject.sql b/sql/updates/0.8/4577_gameobject.sql new file mode 100644 index 00000000000..61b6a9f794d --- /dev/null +++ b/sql/updates/0.8/4577_gameobject.sql @@ -0,0 +1,2 @@ +ALTER TABLE `gameobject` + CHANGE COLUMN `spawntimesecs` `spawntimesecs` int(11) NOT NULL default '0'; diff --git a/sql/updates/0.8/4579.sql b/sql/updates/0.8/4579.sql new file mode 100644 index 00000000000..49b9ba70f1e --- /dev/null +++ b/sql/updates/0.8/4579.sql @@ -0,0 +1,274 @@ +DROP TABLE IF EXISTS `locales_creature`; +CREATE TABLE `locales_creature` ( + `entry` int(11) unsigned NOT NULL default '0', + `name_loc1` varchar(100) NOT NULL default '', + `name_loc2` varchar(100) NOT NULL default '', + `name_loc3` varchar(100) NOT NULL default '', + `name_loc4` varchar(100) NOT NULL default '', + `name_loc5` varchar(100) NOT NULL default '', + `name_loc6` varchar(100) NOT NULL default '', + `name_loc7` varchar(100) NOT NULL default '', + `subname_loc1` varchar(100) default NULL, + `subname_loc2` varchar(100) default NULL, + `subname_loc3` varchar(100) default NULL, + `subname_loc4` varchar(100) default NULL, + `subname_loc5` varchar(100) default NULL, + `subname_loc6` varchar(100) default NULL, + `subname_loc7` varchar(100) default NULL, + `subname_loc8` varchar(100) default NULL, + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `locales_gameobject`; +CREATE TABLE `locales_gameobject` ( + `entry` int(11) unsigned NOT NULL default '0', + `name_loc1` varchar(100) NOT NULL default '', + `name_loc2` varchar(100) NOT NULL default '', + `name_loc3` varchar(100) NOT NULL default '', + `name_loc4` varchar(100) NOT NULL default '', + `name_loc5` varchar(100) NOT NULL default '', + `name_loc6` varchar(100) NOT NULL default '', + `name_loc7` varchar(100) NOT NULL default '', + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `locales_item`; +CREATE TABLE `locales_item` ( + `entry` int(11) unsigned NOT NULL default '0', + `name_loc1` varchar(100) NOT NULL default '', + `name_loc2` varchar(100) NOT NULL default '', + `name_loc3` varchar(100) NOT NULL default '', + `name_loc4` varchar(100) NOT NULL default '', + `name_loc5` varchar(100) NOT NULL default '', + `name_loc6` varchar(100) NOT NULL default '', + `name_loc7` varchar(100) NOT NULL default '', + `description_loc1` varchar(255) default NULL, + `description_loc2` varchar(255) default NULL, + `description_loc3` varchar(255) default NULL, + `description_loc4` varchar(255) default NULL, + `description_loc5` varchar(255) default NULL, + `description_loc6` varchar(255) default NULL, + `description_loc7` varchar(255) default NULL, + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `locales_quest`; +CREATE TABLE `locales_quest` ( + `entry` int(11) unsigned NOT NULL default '0', + `Title_loc1` text, + `Title_loc2` text, + `Title_loc3` text, + `Title_loc4` text, + `Title_loc5` text, + `Title_loc6` text, + `Title_loc7` text, + `Details_loc1` text, + `Details_loc2` text, + `Details_loc3` text, + `Details_loc4` text, + `Details_loc5` text, + `Details_loc6` text, + `Details_loc7` text, + `Objectives_loc1` text, + `Objectives_loc2` text, + `Objectives_loc3` text, + `Objectives_loc4` text, + `Objectives_loc5` text, + `Objectives_loc6` text, + `Objectives_loc7` text, + `OfferRewardText_loc1` text, + `OfferRewardText_loc2` text, + `OfferRewardText_loc3` text, + `OfferRewardText_loc4` text, + `OfferRewardText_loc5` text, + `OfferRewardText_loc6` text, + `OfferRewardText_loc7` text, + `RequestItemsText_loc1` text, + `RequestItemsText_loc2` text, + `RequestItemsText_loc3` text, + `RequestItemsText_loc4` text, + `RequestItemsText_loc5` text, + `RequestItemsText_loc6` text, + `RequestItemsText_loc7` text, + `EndText_loc1` text, + `EndText_loc2` text, + `EndText_loc3` text, + `EndText_loc4` text, + `EndText_loc5` text, + `EndText_loc6` text, + `EndText_loc7` text, + `ObjectiveText1_loc1` text, + `ObjectiveText1_loc2` text, + `ObjectiveText1_loc3` text, + `ObjectiveText1_loc4` text, + `ObjectiveText1_loc5` text, + `ObjectiveText1_loc6` text, + `ObjectiveText1_loc7` text, + `ObjectiveText2_loc1` text, + `ObjectiveText2_loc2` text, + `ObjectiveText2_loc3` text, + `ObjectiveText2_loc4` text, + `ObjectiveText2_loc5` text, + `ObjectiveText2_loc6` text, + `ObjectiveText2_loc7` text, + `ObjectiveText3_loc1` text, + `ObjectiveText3_loc2` text, + `ObjectiveText3_loc3` text, + `ObjectiveText3_loc4` text, + `ObjectiveText3_loc5` text, + `ObjectiveText3_loc6` text, + `ObjectiveText3_loc7` text, + `ObjectiveText4_loc1` text, + `ObjectiveText4_loc2` text, + `ObjectiveText4_loc3` text, + `ObjectiveText4_loc4` text, + `ObjectiveText4_loc5` text, + `ObjectiveText4_loc6` text, + `ObjectiveText4_loc7` text, + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `locales_npc_text`; +CREATE TABLE `locales_npc_text` ( + `entry` int(11) unsigned NOT NULL default '0', + `Text0_0_loc1` longtext, + `Text0_0_loc2` longtext, + `Text0_0_loc3` longtext, + `Text0_0_loc4` longtext, + `Text0_0_loc5` longtext, + `Text0_0_loc6` longtext, + `Text0_0_loc7` longtext, + `Text0_1_loc1` longtext, + `Text0_1_loc2` longtext, + `Text0_1_loc3` longtext, + `Text0_1_loc4` longtext, + `Text0_1_loc5` longtext, + `Text0_1_loc6` longtext, + `Text0_1_loc7` longtext, + `Text1_0_loc1` longtext, + `Text1_0_loc2` longtext, + `Text1_0_loc3` longtext, + `Text1_0_loc4` longtext, + `Text1_0_loc5` longtext, + `Text1_0_loc6` longtext, + `Text1_0_loc7` longtext, + `Text1_1_loc1` longtext, + `Text1_1_loc2` longtext, + `Text1_1_loc3` longtext, + `Text1_1_loc4` longtext, + `Text1_1_loc5` longtext, + `Text1_1_loc6` longtext, + `Text1_1_loc7` longtext, + `Text2_0_loc1` longtext, + `Text2_0_loc2` longtext, + `Text2_0_loc3` longtext, + `Text2_0_loc4` longtext, + `Text2_0_loc5` longtext, + `Text2_0_loc6` longtext, + `Text2_0_loc7` longtext, + `Text2_1_loc1` longtext, + `Text2_1_loc2` longtext, + `Text2_1_loc3` longtext, + `Text2_1_loc4` longtext, + `Text2_1_loc5` longtext, + `Text2_1_loc6` longtext, + `Text2_1_loc7` longtext, + `Text3_0_loc1` longtext, + `Text3_0_loc2` longtext, + `Text3_0_loc3` longtext, + `Text3_0_loc4` longtext, + `Text3_0_loc5` longtext, + `Text3_0_loc6` longtext, + `Text3_0_loc7` longtext, + `Text3_1_loc1` longtext, + `Text3_1_loc2` longtext, + `Text3_1_loc3` longtext, + `Text3_1_loc4` longtext, + `Text3_1_loc5` longtext, + `Text3_1_loc6` longtext, + `Text3_1_loc7` longtext, + `Text4_0_loc1` longtext, + `Text4_0_loc2` longtext, + `Text4_0_loc3` longtext, + `Text4_0_loc4` longtext, + `Text4_0_loc5` longtext, + `Text4_0_loc6` longtext, + `Text4_0_loc7` longtext, + `Text4_1_loc1` longtext, + `Text4_1_loc2` longtext, + `Text4_1_loc3` longtext, + `Text4_1_loc4` longtext, + `Text4_1_loc5` longtext, + `Text4_1_loc6` longtext, + `Text4_1_loc7` longtext, + `Text5_0_loc1` longtext, + `Text5_0_loc2` longtext, + `Text5_0_loc3` longtext, + `Text5_0_loc4` longtext, + `Text5_0_loc5` longtext, + `Text5_0_loc6` longtext, + `Text5_0_loc7` longtext, + `Text5_1_loc1` longtext, + `Text5_1_loc2` longtext, + `Text5_1_loc3` longtext, + `Text5_1_loc4` longtext, + `Text5_1_loc5` longtext, + `Text5_1_loc6` longtext, + `Text5_1_loc7` longtext, + `Text6_0_loc1` longtext, + `Text6_0_loc2` longtext, + `Text6_0_loc3` longtext, + `Text6_0_loc4` longtext, + `Text6_0_loc5` longtext, + `Text6_0_loc6` longtext, + `Text6_0_loc7` longtext, + `Text6_1_loc1` longtext, + `Text6_1_loc2` longtext, + `Text6_1_loc3` longtext, + `Text6_1_loc4` longtext, + `Text6_1_loc5` longtext, + `Text6_1_loc6` longtext, + `Text6_1_loc7` longtext, + `Text7_0_loc1` longtext, + `Text7_0_loc2` longtext, + `Text7_0_loc3` longtext, + `Text7_0_loc4` longtext, + `Text7_0_loc5` longtext, + `Text7_0_loc6` longtext, + `Text7_0_loc7` longtext, + `Text7_1_loc1` longtext, + `Text7_1_loc2` longtext, + `Text7_1_loc3` longtext, + `Text7_1_loc4` longtext, + `Text7_1_loc5` longtext, + `Text7_1_loc6` longtext, + `Text7_1_loc7` longtext, + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `locales_page_text`; +CREATE TABLE `locales_page_text` ( + `entry` int(11) unsigned NOT NULL default '0', + `Text_loc1` longtext, + `Text_loc2` longtext, + `Text_loc3` longtext, + `Text_loc4` longtext, + `Text_loc5` longtext, + `Text_loc6` longtext, + `Text_loc7` longtext, + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `realmd`.`localization`; +CREATE TABLE `realmd`.`localization` ( + `locale` tinyint(3) unsigned NOT NULL default '0', + `string` char(2) NOT NULL DEFAULT '', + PRIMARY KEY (`locale`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +INSERT INTO `realmd`.`localization` VALUES + (0,'en'), + (2,'fr'), + (3,'de'); + +ALTER TABLE `realmd`.`account` ADD COLUMN `locale` tinyint(3) unsigned NOT NULL DEFAULT '0' AFTER `mutetime`; diff --git a/sql/updates/0.8/4582_spell_affect.sql b/sql/updates/0.8/4582_spell_affect.sql new file mode 100644 index 00000000000..1caa6788a5a --- /dev/null +++ b/sql/updates/0.8/4582_spell_affect.sql @@ -0,0 +1,9 @@ +-- Cleanup +DELETE FROM `spell_affect` WHERE `entry` IN (28787); + +-- Correct data +DELETE FROM `spell_affect` WHERE `entry` IN (37878,37879,37880); +INSERT INTO `spell_affect` VALUES +(37878, 0, 0, 0x00, 0, 0, 0, 0x00000010000000F0, 0), +(37879, 0, 0, 0x00, 0, 0, 0, 0x00000000C0006000, 0), +(37880, 0, 0, 0x00, 0, 0, 0, 0x0000000411041E40, 0); diff --git a/sql/updates/0.8/4584_character_inventory.sql b/sql/updates/0.8/4584_character_inventory.sql new file mode 100644 index 00000000000..5fa8cf13d09 --- /dev/null +++ b/sql/updates/0.8/4584_character_inventory.sql @@ -0,0 +1,2 @@ +ALTER TABLE `character_inventory` + ADD KEY `idx_guid` ( `guid` ); diff --git a/sql/updates/0.8/4585_item_instance.sql b/sql/updates/0.8/4585_item_instance.sql new file mode 100644 index 00000000000..a9e3bbbf22b --- /dev/null +++ b/sql/updates/0.8/4585_item_instance.sql @@ -0,0 +1,2 @@ +ALTER TABLE `item_instance` + ADD KEY `idx_owner_guid` ( `owner_guid`); diff --git a/sql/updates/0.8/4587_character_quest_daily.sql b/sql/updates/0.8/4587_character_quest_daily.sql new file mode 100644 index 00000000000..e9e9b72662c --- /dev/null +++ b/sql/updates/0.8/4587_character_quest_daily.sql @@ -0,0 +1,9 @@ +DROP TABLE IF EXISTS `character_queststatus_daily`; +CREATE TABLE `character_queststatus_daily` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `quest` int(11) unsigned NOT NULL default '0' COMMENT 'Quest Identifier', + `time` bigint(20) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`,`quest`), + KEY `idx_guid` (`guid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System'; + diff --git a/sql/updates/0.8/4588_command.sql b/sql/updates/0.8/4588_command.sql new file mode 100644 index 00000000000..4b26fcb1022 --- /dev/null +++ b/sql/updates/0.8/4588_command.sql @@ -0,0 +1 @@ +DELETE FROM command WHERE name IN ('gameobject'); diff --git a/sql/updates/0.8/4592_command.sql b/sql/updates/0.8/4592_command.sql new file mode 100644 index 00000000000..5a1bcd88889 --- /dev/null +++ b/sql/updates/0.8/4592_command.sql @@ -0,0 +1 @@ +UPDATE `command` set `help` = 'Syntax: .plimit [#num|-1|-2|-3|reset|player|moderator|gamemaster|administrator]\r\n\r\nWithout arg show current player amount and security level limitations for login to server, with arg set player linit ($num > 0) or securiti limitation ($num < 0 or security leme name. With `reset` sets player limit to the one in the config file' WHERE `name` = 'plimit'; diff --git a/sql/updates/0.8/4592_realmlist.sql b/sql/updates/0.8/4592_realmlist.sql new file mode 100644 index 00000000000..dbd8e89bf33 --- /dev/null +++ b/sql/updates/0.8/4592_realmlist.sql @@ -0,0 +1,2 @@ +ALTER TABLE realmd.realmlist + ADD COLUMN `allowedSecurityLevel` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `timezone`; diff --git a/sql/updates/0.8/4594_item_template.sql b/sql/updates/0.8/4594_item_template.sql new file mode 100644 index 00000000000..f9b8e3df790 --- /dev/null +++ b/sql/updates/0.8/4594_item_template.sql @@ -0,0 +1,3 @@ +ALTER TABLE `item_template` + ADD COLUMN `minMoneyLoot` int(11) unsigned NOT NULL default '0' AFTER `FoodType`, + ADD COLUMN `maxMoneyLoot` int(11) unsigned NOT NULL default '0' AFTER `minMoneyLoot`; diff --git a/sql/updates/0.8/4595_command.sql b/sql/updates/0.8/4595_command.sql new file mode 100644 index 00000000000..50eac0de3b8 --- /dev/null +++ b/sql/updates/0.8/4595_command.sql @@ -0,0 +1,5 @@ +DELETE FROM command WHERE name IN ('cast','castback'); +INSERT INTO `command` VALUES +('cast',3,'Syntax: .cast #spellid\r\n Cast #spellid to selected target. If no target selected cast to self.'), +('castback',3,'Syntax: .castback #spellid\r\n Selected target cast #spellid to your character.'); + diff --git a/sql/updates/0.8/4595_spell_affect.sql b/sql/updates/0.8/4595_spell_affect.sql new file mode 100644 index 00000000000..ba9274597f0 --- /dev/null +++ b/sql/updates/0.8/4595_spell_affect.sql @@ -0,0 +1,105 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (21873,38314); +INSERT INTO `spell_affect` VALUES +(21873,0,0,0,0,0,0,0x0000E000E2000000,0), -- ?? rare druid armor +(38314,0,0,0,0,0,0,0x0000E000E2000000,0); -- for item 31334 + +DELETE FROM `spell_affect` WHERE `entry` IN (16870); +INSERT INTO `spell_affect` VALUES +(16870,0,0,0,0,0,0,0x001007F100E3FEFF,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (16947,16948,16949); +INSERT INTO `spell_affect` VALUES +(16947,1,0,0,0,0,0,0x0000000002000000,0), +(16948,1,0,0,0,0,0,0x0000000002000000,0), +(16949,1,0,0,0,0,0,0x0000000002000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (17104,24943,24944,24945,24946); +INSERT INTO `spell_affect` VALUES +(17104,0,0,0,0,0,0,0x00000010000000F0,0), +(17104,1,0,0,0,0,0,0x00000010000000F0,0), +(24943,0,0,0,0,0,0,0x00000010000000F0,0), +(24943,1,0,0,0,0,0,0x00000010000000F0,0), +(24944,0,0,0,0,0,0,0x00000010000000F0,0), +(24944,1,0,0,0,0,0,0x00000010000000F0,0), +(24945,0,0,0,0,0,0,0x00000010000000F0,0), +(24945,1,0,0,0,0,0,0x00000010000000F0,0), +(24946,0,0,0,0,0,0,0x00000010000000F0,0), +(24946,1,0,0,0,0,0,0x00000010000000F0,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (37721); +INSERT INTO `spell_affect` VALUES +(37721,0,0,0,0,0,0,0x00000010000000F0,1); -- not used in 2.3.0 + +DELETE FROM `spell_affect` WHERE `entry` IN (42367); +INSERT INTO `spell_affect` VALUES +(42367,0,0,0,0,0,0,0x0000001000000000,0); -- not used in 2.3.0 (?) + +DELETE FROM `spell_affect` WHERE `entry` IN (38447); +INSERT INTO `spell_affect` VALUES +(38447,0,0,0,0,0,0,0x0000040000000000,0), +(38447,1,0,0,0,0,0,0x0000004000000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (37292); +INSERT INTO `spell_affect` VALUES +(37292,0,0,0,0,0,0,0x0008000000000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (39926); +INSERT INTO `spell_affect` VALUES +(39926,1,0,0,0,0,0,0x0000080000000000,0), +(39926,2,0,0,0,0,0,0x0000200000000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (38416); +INSERT INTO `spell_affect` VALUES +(38416,0,0,0,0,0,0,0x0010000000800000,0), +(38416,1,0,0,0,0,0,0x0010000000800000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (37736); +INSERT INTO `spell_affect` VALUES +(37736,0,0,0,0,0,0,0x0000040000000000,0), +(37736,1,0,0,0,0,0,0x0000004000000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (28855); +INSERT INTO `spell_affect` VALUES +(28855,0,0,0,0,0,0,0x0000000000000800,0), +(28855,1,0,0,0,0,0,0x0010000000000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (23724); +INSERT INTO `spell_affect` VALUES +(23724,0,0,0,0,0,0,0x0000E000E2000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (16833,16834,16835); +INSERT INTO `spell_affect` VALUES +(16833,0,0,0,0,0,0,0x0000E000E2000000,0), +(16834,0,0,0,0,0,0,0x0000E000E2000000,0), +(16835,0,0,0,0,0,0,0x0000E000E2000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (16886); +INSERT INTO `spell_affect` VALUES +(16886,0,0,0,0,0,0,0x0000000001000265,1); + +DELETE FROM `spell_affect` WHERE `entry` IN (16819,16820); +INSERT INTO `spell_affect` VALUES +(16819,0,0,0,0,0,0,0x0002122000600707,0), +(16820,0,0,0,0,0,0,0x0002122000600707,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (17116,38466); +INSERT INTO `spell_affect` VALUES +(17116,0,0,0,0,0,0,0x0002002010000261,0), +(38466,0,0,0,0,0,0,0x0008000000000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (37287); +INSERT INTO `spell_affect` VALUES +(37287,0,0,0,0,0,0,0x0000E000E2000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (17118,17119,17120,17121,17122); +INSERT INTO `spell_affect` VALUES +(17118,0,0,0,0,0,0,0x001005D000E193F7,0), +(17118,1,0,0,0,0,0,0x0004103000340750,0), +(17119,0,0,0,0,0,0,0x001005D000E193F7,0), +(17119,1,0,0,0,0,0,0x0004103000340750,0), +(17120,0,0,0,0,0,0,0x001005D000E193F7,0), +(17120,1,0,0,0,0,0,0x0004103000340750,0), +(17121,0,0,0,0,0,0,0x001005D000E193F7,0), +(17121,1,0,0,0,0,0,0x0004103000340750,0), +(17122,0,0,0,0,0,0,0x001005D000E193F7,0), +(17122,1,0,0,0,0,0,0x0004103000340750,0); diff --git a/sql/updates/0.8/4597_realmlist.sql b/sql/updates/0.8/4597_realmlist.sql new file mode 100644 index 00000000000..6cab83dfe1a --- /dev/null +++ b/sql/updates/0.8/4597_realmlist.sql @@ -0,0 +1,2 @@ +ALTER TABLE realmd.realmlist + ADD COLUMN `population` float(0) UNSIGNED NOT NULL DEFAULT 0.0 AFTER `allowedSecurityLevel`; diff --git a/sql/updates/0.8/4599_command.sql b/sql/updates/0.8/4599_command.sql new file mode 100644 index 00000000000..50eac0de3b8 --- /dev/null +++ b/sql/updates/0.8/4599_command.sql @@ -0,0 +1,5 @@ +DELETE FROM command WHERE name IN ('cast','castback'); +INSERT INTO `command` VALUES +('cast',3,'Syntax: .cast #spellid\r\n Cast #spellid to selected target. If no target selected cast to self.'), +('castback',3,'Syntax: .castback #spellid\r\n Selected target cast #spellid to your character.'); + diff --git a/sql/updates/0.8/4603_spell_affect.sql b/sql/updates/0.8/4603_spell_affect.sql new file mode 100644 index 00000000000..4d3c72283c6 --- /dev/null +++ b/sql/updates/0.8/4603_spell_affect.sql @@ -0,0 +1,83 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (34453,34454); +INSERT INTO `spell_affect` VALUES +(34453,1,0,0,0,0,0,0x0000000400000000,0), +(34454,1,0,0,0,0,0,0x0000000400000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (24348); +INSERT INTO `spell_affect` VALUES +(24348,0,0,0,0,0,0,0x0000000000200000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (34462,34464,34465); +INSERT INTO `spell_affect` VALUES +(34462,1,0,0,0,0,0,0x0000000800000000,0), +(34464,1,0,0,0,0,0,0x0000000800000000,0), +(34465,1,0,0,0,0,0,0x0000000800000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (19239,19245); +INSERT INTO `spell_affect` VALUES +(19239,0,0,0,0,0,0,0x0000000000000018,0), +(19239,1,0,0,0,0,0,0x0000000000000004,0), +(19245,0,0,0,0,0,0,0x0000000000000018,0), +(19245,1,0,0,0,0,0,0x0000000000000004,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (19416,19417,19418,19419,19420); +INSERT INTO `spell_affect` VALUES +(19416,0,0,0,0,0,0,0x000010810007DA00,0), +(19417,0,0,0,0,0,0,0x000010810007DA00,0), +(19418,0,0,0,0,0,0,0x000010810007DA00,0), +(19419,0,0,0,0,0,0,0x000010810007DA00,0), +(19420,0,0,0,0,0,0,0x000010810007DA00,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (34455,34459,34460); +INSERT INTO `spell_affect` VALUES +(34455,0,0,0,0,0,0,0x0000002000000000,0), +(34455,1,0,0,0,0,0,0x0000004000000000,0), +(34459,0,0,0,0,0,0,0x0000002000000000,0), +(34459,1,0,0,0,0,0,0x0000004000000000,0), +(34460,0,0,0,0,0,0,0x0000002000000000,0), +(34460,1,0,0,0,0,0,0x0000004000000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (35029,35030); +INSERT INTO `spell_affect` VALUES +(35029,1,0,0,0,0,0,0x0000080000000000,0), +(35030,1,0,0,0,0,0,0x0000080000000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (19572,19573); +INSERT INTO `spell_affect` VALUES +(19572,1,0,0,0,0,0,0x0000000000800000,0), +(19573,1,0,0,0,0,0,0x0000000000800000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (19464,19465,19466,19467,19468); +INSERT INTO `spell_affect` VALUES +(19464,0,0,0,0,0,0,0x0000010000004000,0), +(19464,1,0,0,0,0,0,0x0000008000000000,0), +(19464,2,0,0,0,0,0,0x000011800000C000,0), +(19465,0,0,0,0,0,0,0x0000010000004000,0), +(19465,1,0,0,0,0,0,0x0000008000000000,0), +(19465,2,0,0,0,0,0,0x000011800000C000,0), +(19466,0,0,0,0,0,0,0x0000010000004000,0), +(19466,1,0,0,0,0,0,0x0000008000000000,0), +(19466,2,0,0,0,0,0,0x000011800000C000,0), +(19467,0,0,0,0,0,0,0x0000010000004000,0), +(19467,1,0,0,0,0,0,0x0000008000000000,0), +(19467,2,0,0,0,0,0,0x000011800000C000,0), +(19468,0,0,0,0,0,0,0x0000010000004000,0), +(19468,1,0,0,0,0,0,0x0000008000000000,0), +(19468,2,0,0,0,0,0,0x000011800000C000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (19485,19487,19488,19489,19490); +INSERT INTO `spell_affect` VALUES +(19485,0,0,0,0,0,0,0x0000000000000001,0), +(19487,0,0,0,0,0,0,0x0000000000000001,0), +(19488,0,0,0,0,0,0,0x0000000000000001,0), +(19489,0,0,0,0,0,0,0x0000000000000001,0), +(19490,0,0,0,0,0,0,0x0000000000000001,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (32203,41660); +INSERT INTO `spell_affect` VALUES +(32203,1,0,0,0,0,0,0x0001100001C22000,0), +(41660,1,0,0,0,0,0,0x0001100001C22000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (37508); +INSERT INTO `spell_affect` VALUES +(37508,0,0,0,0,0,0,0x0000000100061800,0); diff --git a/sql/updates/0.8/4605_creature_addon.sql b/sql/updates/0.8/4605_creature_addon.sql new file mode 100644 index 00000000000..5f1bf1a1f49 --- /dev/null +++ b/sql/updates/0.8/4605_creature_addon.sql @@ -0,0 +1,3 @@ +ALTER TABLE `creature_addon` + DROP KEY `guid`, + ADD PRIMARY KEY (`guid`); diff --git a/sql/updates/0.8/4605_creature_template_addon.sql b/sql/updates/0.8/4605_creature_template_addon.sql new file mode 100644 index 00000000000..d49df079399 --- /dev/null +++ b/sql/updates/0.8/4605_creature_template_addon.sql @@ -0,0 +1,3 @@ +ALTER TABLE `creature_template_addon` + DROP KEY `entry`, + ADD PRIMARY KEY(`entry`); diff --git a/sql/updates/0.8/4608_game_graveyard_zone.sql b/sql/updates/0.8/4608_game_graveyard_zone.sql new file mode 100644 index 00000000000..1dcff5e11b0 --- /dev/null +++ b/sql/updates/0.8/4608_game_graveyard_zone.sql @@ -0,0 +1,25 @@ +ALTER TABLE `game_graveyard_zone` + DROP COLUMN `ghost_map`; + +UPDATE `game_graveyard_zone` as G1,`game_graveyard_zone` as G2 + SET G1.`faction` = 0 + WHERE G1.`id`=G2.`id` AND G1.`ghost_zone`=G2.`ghost_zone` AND G1.`faction`=67 AND (G2.`faction`=469 OR G2.`faction`=0); + +UPDATE `game_graveyard_zone` as G1,`game_graveyard_zone` as G2 + SET G1.`faction` = 0 + WHERE G1.`id`=G2.`id` AND G1.`ghost_zone`=G2.`ghost_zone` AND G1.`faction`=469 AND (G2.`faction`=67 OR G2.`faction`=0); + +DELETE FROM `game_graveyard_zone` WHERE `ghost_zone`= 0; + +DROP TABLE IF EXISTS `game_graveyard_zone_new`; +CREATE TABLE `game_graveyard_zone_new` ( + `id` int(11) unsigned NOT NULL default '0', + `ghost_zone` int(11) unsigned NOT NULL default '0', + `faction` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`id`,`ghost_zone`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Trigger System'; + +INSERT IGNORE INTO `game_graveyard_zone_new` SELECT `id`,`ghost_zone`,`faction` FROM `game_graveyard_zone`; + +DROP TABLE `game_graveyard_zone`; +RENAME TABLE `game_graveyard_zone_new` TO `game_graveyard_zone`; diff --git a/sql/updates/0.8/4615_creature_template.sql b/sql/updates/0.8/4615_creature_template.sql new file mode 100644 index 00000000000..6b1ebaa41fd --- /dev/null +++ b/sql/updates/0.8/4615_creature_template.sql @@ -0,0 +1,3 @@ +ALTER TABLE `creature_template` + ADD COLUMN `modelid_A2` INTEGER UNSIGNED NOT NULL DEFAULT 0 AFTER `modelid_A`, + ADD COLUMN `modelid_H2` INTEGER UNSIGNED NOT NULL DEFAULT 0 AFTER `modelid_H`; diff --git a/sql/updates/0.8/4627_game_event_model_equip.sql b/sql/updates/0.8/4627_game_event_model_equip.sql new file mode 100644 index 00000000000..53ceda5495d --- /dev/null +++ b/sql/updates/0.8/4627_game_event_model_equip.sql @@ -0,0 +1,8 @@ +DROP TABLE IF EXISTS `game_event_model_equip`; +CREATE TABLE `game_event_model_equip` ( + `guid` int(11) unsigned NOT NULL DEFAULT '0', + `modelid` int(11) unsigned NOT NULL DEFAULT '0', + `equipment_id` int(11) unsigned NOT NULL DEFAULT '0', + `event` mediumint(9) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`guid`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; diff --git a/sql/updates/0.9/4615_creature_template.sql b/sql/updates/0.9/4615_creature_template.sql new file mode 100644 index 00000000000..6b1ebaa41fd --- /dev/null +++ b/sql/updates/0.9/4615_creature_template.sql @@ -0,0 +1,3 @@ +ALTER TABLE `creature_template` + ADD COLUMN `modelid_A2` INTEGER UNSIGNED NOT NULL DEFAULT 0 AFTER `modelid_A`, + ADD COLUMN `modelid_H2` INTEGER UNSIGNED NOT NULL DEFAULT 0 AFTER `modelid_H`; diff --git a/sql/updates/0.9/4627_game_event_model_equip.sql b/sql/updates/0.9/4627_game_event_model_equip.sql new file mode 100644 index 00000000000..53ceda5495d --- /dev/null +++ b/sql/updates/0.9/4627_game_event_model_equip.sql @@ -0,0 +1,8 @@ +DROP TABLE IF EXISTS `game_event_model_equip`; +CREATE TABLE `game_event_model_equip` ( + `guid` int(11) unsigned NOT NULL DEFAULT '0', + `modelid` int(11) unsigned NOT NULL DEFAULT '0', + `equipment_id` int(11) unsigned NOT NULL DEFAULT '0', + `event` mediumint(9) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`guid`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; diff --git a/sql/updates/0.9/4628.sql b/sql/updates/0.9/4628.sql new file mode 100644 index 00000000000..a6a19aa8fa5 --- /dev/null +++ b/sql/updates/0.9/4628.sql @@ -0,0 +1,76 @@ +ALTER TABLE `character` + MODIFY COLUMN `logout_time` int(11) UNSIGNED NOT NULL DEFAULT 0, + MODIFY COLUMN `is_logout_resting` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0; + +ALTER TABLE `character_kill` + MODIFY COLUMN `guid` int(11) UNSIGNED NOT NULL DEFAULT 0, + MODIFY COLUMN `victim_guid` int(11) UNSIGNED NOT NULL DEFAULT 0, + MODIFY COLUMN `count` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0; + +ALTER TABLE `character_ticket` + MODIFY COLUMN `ticket_id` int(11) UNSIGNED NOT NULL DEFAULT NULL AUTO_INCREMENT; + +ALTER TABLE `guild_member` + MODIFY COLUMN `guid` int(11) UNSIGNED NOT NULL DEFAULT 0, ROW_FORMAT = FIXED; + +ALTER TABLE `group` + MODIFY COLUMN `leaderGuid` int(11) UNSIGNED NOT NULL, + MODIFY COLUMN `mainTank` int(11) UNSIGNED NOT NULL, + MODIFY COLUMN `mainAssistant` int(11) UNSIGNED NOT NULL, + MODIFY COLUMN `lootMethod` TINYINT(4) UNSIGNED NOT NULL, + MODIFY COLUMN `looterGuid` int(11) UNSIGNED NOT NULL, + MODIFY COLUMN `lootThreshold` TINYINT(4) UNSIGNED NOT NULL, + MODIFY COLUMN `icon1` int(11) UNSIGNED NOT NULL, + MODIFY COLUMN `icon2` int(11) UNSIGNED NOT NULL, + MODIFY COLUMN `icon3` int(11) UNSIGNED NOT NULL, + MODIFY COLUMN `icon4` int(11) UNSIGNED NOT NULL, + MODIFY COLUMN `icon5` int(11) UNSIGNED NOT NULL, + MODIFY COLUMN `icon6` int(11) UNSIGNED NOT NULL, + MODIFY COLUMN `icon7` int(11) unsigned NOT NULL, + MODIFY COLUMN `icon8` int(11) unsigned NOT NULL, + MODIFY COLUMN `isRaid` tinyint(1) unsigned NOT NULL; + +ALTER TABLE `group_member` + MODIFY COLUMN `leaderGuid` int(11) UNSIGNED NOT NULL, + MODIFY COLUMN `memberGuid` int(11) UNSIGNED NOT NULL, + MODIFY COLUMN `assistant` TINYINT(1) UNSIGNED NOT NULL, + MODIFY COLUMN `subgroup` SMALLINT(6) UNSIGNED NOT NULL, ROW_FORMAT = FIXED; + +ALTER TABLE `item_text` + MODIFY COLUMN `id` int(11) UNSIGNED NOT NULL DEFAULT 0, ROW_FORMAT = FIXED; + +ALTER TABLE `npc_gossip` + MODIFY COLUMN `id` int(11) UNSIGNED NOT NULL DEFAULT 0, + MODIFY COLUMN `npc_guid` int(11) UNSIGNED NOT NULL DEFAULT 0, + MODIFY COLUMN `gossip_type` int(11) UNSIGNED NOT NULL DEFAULT 0, + MODIFY COLUMN `textid` int(11) UNSIGNED NOT NULL DEFAULT 0, + MODIFY COLUMN `option_count` int(11) UNSIGNED DEFAULT NULL; + +ALTER TABLE `npc_text` + MODIFY COLUMN `ID` int(11) UNSIGNED NOT NULL DEFAULT 0; + +ALTER TABLE `npc_trainer` + MODIFY COLUMN `entry` int(11) UNSIGNED NOT NULL DEFAULT 0, + MODIFY COLUMN `spell` int(11) UNSIGNED NOT NULL DEFAULT 0, + MODIFY COLUMN `spellcost` int(11) UNSIGNED DEFAULT 0; + +ALTER TABLE `page_text` + MODIFY COLUMN `entry` int(11) UNSIGNED NOT NULL DEFAULT 0; + +ALTER TABLE `pet_name_generation` + MODIFY COLUMN `id` int(11) UNSIGNED NOT NULL DEFAULT NULL AUTO_INCREMENT, + MODIFY COLUMN `entry` int(11) UNSIGNED NOT NULL DEFAULT 0; + +ALTER TABLE `quest_template` + MODIFY COLUMN `SuggestedPlayers` int(11) UNSIGNED NOT NULL DEFAULT 0, + MODIFY COLUMN `DetailsEmote1` int(11) UNSIGNED NOT NULL DEFAULT 0, + MODIFY COLUMN `DetailsEmote2` int(11) UNSIGNED NOT NULL DEFAULT 0, + MODIFY COLUMN `DetailsEmote3` int(11) UNSIGNED NOT NULL DEFAULT 0, + MODIFY COLUMN `DetailsEmote4` int(11) UNSIGNED NOT NULL DEFAULT 0, + MODIFY COLUMN `IncompleteEmote` int(11) UNSIGNED NOT NULL DEFAULT 0, + MODIFY COLUMN `CompleteEmote` int(11) UNSIGNED NOT NULL DEFAULT 0, + MODIFY COLUMN `OfferRewardEmote1` int(11) UNSIGNED NOT NULL DEFAULT 0, + MODIFY COLUMN `OfferRewardEmote2` int(11) UNSIGNED NOT NULL DEFAULT 0, + MODIFY COLUMN `OfferRewardEmote3` int(11) UNSIGNED NOT NULL DEFAULT 0, + MODIFY COLUMN `OfferRewardEmote4` int(11) UNSIGNED NOT NULL DEFAULT 0, + MODIFY COLUMN `CompleteScript` int(11) UNSIGNED NOT NULL DEFAULT 0; diff --git a/sql/updates/0.9/4632_areatrigger_teleport.sql b/sql/updates/0.9/4632_areatrigger_teleport.sql new file mode 100644 index 00000000000..ef7a345f7c3 --- /dev/null +++ b/sql/updates/0.9/4632_areatrigger_teleport.sql @@ -0,0 +1,12 @@ +ALTER TABLE `areatrigger_template` + DROP COLUMN `trigger_map`, + DROP COLUMN `trigger_position_x`, + DROP COLUMN `trigger_position_y`, + DROP COLUMN `trigger_position_z`; + + +DELETE FROM `areatrigger_template` + WHERE `required_level` = 0 AND `required_item` = 0 + AND `target_map` = 0 AND `target_position_x` = 0 AND `target_position_y` = 0 AND `target_position_z` = 0 AND `target_orientation` = 0; + +ALTER TABLE `areatrigger_template` RENAME TO `areatrigger_teleport`; diff --git a/sql/updates/0.9/4633_spell_teleport.sql b/sql/updates/0.9/4633_spell_teleport.sql new file mode 100644 index 00000000000..055fadba14d --- /dev/null +++ b/sql/updates/0.9/4633_spell_teleport.sql @@ -0,0 +1,17 @@ + +DROP TABLE IF EXISTS `spell_teleport`; +CREATE TABLE `spell_teleport` ( + `id` int(11) unsigned NOT NULL default '0' COMMENT 'Identifier', + `target_map` int(11) unsigned NOT NULL default '0', + `target_position_x` float NOT NULL default '0', + `target_position_y` float NOT NULL default '0', + `target_position_z` float NOT NULL default '0', + `target_orientation` float NOT NULL default '0', + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Spell System'; + +INSERT INTO `spell_teleport` +SELECT `id`,`target_map`,`target_position_x`,`target_position_y`,`target_position_z`,`target_orientation` +FROM `areatrigger_teleport`; + +DELETE FROM `spell_teleport` WHERE `target_position_x` = 0 AND `target_position_y` = 0 AND `target_position_z` = 0; diff --git a/sql/updates/0.9/4640_command.sql b/sql/updates/0.9/4640_command.sql new file mode 100644 index 00000000000..01c7ecefbcf --- /dev/null +++ b/sql/updates/0.9/4640_command.sql @@ -0,0 +1,4 @@ +DELETE FROM command WHERE name IN ('gotrigger'); +INSERT INTO `command` (`name`,`security`,`help`) VALUES +('gotrigger',2,'Syntax: .gotrigger #trigger_id\r\n\r\nTeleport your character to areatrigger with id #trigger_id. Character will be teleported to trigger target if selected areatrigger is telporting trigger.'); + diff --git a/sql/updates/0.9/4656_game_event_creature_quest.sql b/sql/updates/0.9/4656_game_event_creature_quest.sql new file mode 100644 index 00000000000..9fcb04915e4 --- /dev/null +++ b/sql/updates/0.9/4656_game_event_creature_quest.sql @@ -0,0 +1,7 @@ +DROP TABLE IF EXISTS `game_event_creature_quest`; +CREATE TABLE `game_event_creature_quest` ( + `id` int(11) unsigned NOT NULL default '0', + `quest` int(11) unsigned NOT NULL default '0', + `event` mediumint(9) unsigned NOT NULL default '0', + PRIMARY KEY (`id`,`quest`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; diff --git a/sql/updates/0.9/4657_quest_template.sql b/sql/updates/0.9/4657_quest_template.sql new file mode 100644 index 00000000000..4f61a8846b5 --- /dev/null +++ b/sql/updates/0.9/4657_quest_template.sql @@ -0,0 +1,5 @@ +ALTER TABLE `quest_template` + CHANGE `RequiredSkillValue` `RequiredSkillValue` int(11) unsigned NOT NULL default '0'; + +UPDATE `quest_template` + SET `RequiredSkillValue` = 0 WHERE `RequiredSkillValue` = 1 AND `ZoneOrSort` >= 0; \ No newline at end of file diff --git a/sql/updates/0.9/4664.sql b/sql/updates/0.9/4664.sql new file mode 100644 index 00000000000..ee3a3a8eaa7 --- /dev/null +++ b/sql/updates/0.9/4664.sql @@ -0,0 +1,982 @@ +CREATE DATABASE `characters` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; +GRANT ALL PRIVILEGES ON `characters` . * TO 'mangos'@'localhost' WITH GRANT OPTION; + +DROP TABLE IF EXISTS `characters`.`arena_team`; +CREATE TABLE `characters`.`arena_team` ( + `arenateamid` int(10) unsigned NOT NULL default '0', + `name` char(255) NOT NULL, + `captainguid` int(10) unsigned NOT NULL default '0', + `type` tinyint(3) unsigned NOT NULL default '0', + `EmblemStyle` int(10) unsigned NOT NULL default '0', + `EmblemColor` int(10) unsigned NOT NULL default '0', + `BorderStyle` int(10) unsigned NOT NULL default '0', + `BorderColor` int(10) unsigned NOT NULL default '0', + `BackgroundColor` int(10) unsigned NOT NULL default '0', + PRIMARY KEY (`arenateamid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `arena_team` +-- + +/*!40000 ALTER TABLE `arena_team` DISABLE KEYS */; +/*!40000 ALTER TABLE `arena_team` ENABLE KEYS */; + + +-- +-- Definition of table `arena_team_member` +-- + +DROP TABLE IF EXISTS `characters`.`arena_team_member`; +CREATE TABLE `characters`.`arena_team_member` ( + `arenateamid` int(10) unsigned NOT NULL default '0', + `guid` int(10) unsigned NOT NULL default '0', + `played_week` int(10) unsigned NOT NULL default '0', + `wons_week` int(10) unsigned NOT NULL default '0', + `played_season` int(10) unsigned NOT NULL default '0', + `wons_season` int(10) unsigned NOT NULL default '0' +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `arena_team_member` +-- + +/*!40000 ALTER TABLE `arena_team_member` DISABLE KEYS */; +/*!40000 ALTER TABLE `arena_team_member` ENABLE KEYS */; + + +-- +-- Definition of table `arena_team_stats` +-- + +DROP TABLE IF EXISTS `characters`.`arena_team_stats`; +CREATE TABLE `characters`.`arena_team_stats` ( + `arenateamid` int(10) unsigned NOT NULL default '0', + `rating` int(10) unsigned NOT NULL default '0', + `games` int(10) unsigned NOT NULL default '0', + `wins` int(10) unsigned NOT NULL default '0', + `played` int(10) unsigned NOT NULL default '0', + `wins2` int(10) unsigned NOT NULL default '0', + `rank` int(10) unsigned NOT NULL default '0', + PRIMARY KEY (`arenateamid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `arena_team_stats` +-- + +/*!40000 ALTER TABLE `arena_team_stats` DISABLE KEYS */; +/*!40000 ALTER TABLE `arena_team_stats` ENABLE KEYS */; + + +-- +-- Definition of table `auctionhouse` +-- + +DROP TABLE IF EXISTS `characters`.`auctionhouse`; +CREATE TABLE `characters`.`auctionhouse` ( + `id` int(11) unsigned NOT NULL default '0', + `auctioneerguid` int(11) unsigned NOT NULL default '0', + `itemguid` int(11) unsigned NOT NULL default '0', + `item_template` int(11) unsigned NOT NULL default '0' COMMENT 'Item Identifier', + `itemowner` int(11) unsigned NOT NULL default '0', + `buyoutprice` int(11) NOT NULL default '0', + `time` bigint(40) NOT NULL default '0', + `buyguid` int(11) unsigned NOT NULL default '0', + `lastbid` int(11) NOT NULL default '0', + `startbid` int(11) NOT NULL default '0', + `deposit` int(11) NOT NULL default '0', + `location` tinyint(3) unsigned NOT NULL default '3', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `auctionhouse` +-- + +/*!40000 ALTER TABLE `auctionhouse` DISABLE KEYS */; +/*!40000 ALTER TABLE `auctionhouse` ENABLE KEYS */; + + +-- +-- Definition of table `bugreport` +-- + +DROP TABLE IF EXISTS `characters`.`bugreport`; +CREATE TABLE `characters`.`bugreport` ( + `id` int(11) NOT NULL auto_increment COMMENT 'Identifier', + `type` varchar(255) NOT NULL default '', + `content` varchar(255) NOT NULL default '', + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Debug System'; + +-- +-- Dumping data for table `bugreport` +-- + +/*!40000 ALTER TABLE `bugreport` DISABLE KEYS */; +/*!40000 ALTER TABLE `bugreport` ENABLE KEYS */; + + +-- +-- Definition of table `character` +-- + +DROP TABLE IF EXISTS `characters`.`character`; +CREATE TABLE `characters`.`character` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `account` int(11) unsigned NOT NULL default '0' COMMENT 'Account Identifier', + `data` longtext, + `name` varchar(12) NOT NULL default '', + `race` tinyint(3) unsigned NOT NULL default '0', + `class` tinyint(3) unsigned NOT NULL default '0', + `position_x` float NOT NULL default '0', + `position_y` float NOT NULL default '0', + `position_z` float NOT NULL default '0', + `map` int(11) unsigned NOT NULL default '0' COMMENT 'Map Identifier', + `orientation` float NOT NULL default '0', + `taximask` longtext, + `online` tinyint(3) unsigned NOT NULL default '0', + `cinematic` tinyint(3) unsigned NOT NULL default '0', + `totaltime` int(11) unsigned NOT NULL default '0', + `leveltime` int(11) unsigned NOT NULL default '0', + `logout_time` int(11) unsigned NOT NULL default '0', + `is_logout_resting` tinyint(3) unsigned NOT NULL default '0', + `rest_bonus` float NOT NULL default '0', + `resettalents_cost` int(11) unsigned NOT NULL default '0', + `resettalents_time` bigint(20) unsigned NOT NULL default '0', + `trans_x` float NOT NULL default '0', + `trans_y` float NOT NULL default '0', + `trans_z` float NOT NULL default '0', + `trans_o` float NOT NULL default '0', + `transguid` bigint(20) unsigned NOT NULL default '0', + `gmstate` tinyint(3) unsigned NOT NULL default '0', + `stable_slots` tinyint(1) unsigned NOT NULL default '0', + `at_login` int(11) unsigned NOT NULL default '0', + `zone` int(11) unsigned NOT NULL default '0', + `last_honor_date` int(11) unsigned NOT NULL default '0', + `pending_honor` float NOT NULL default '0', + `pending_kills` int(11) NOT NULL default '0', + `last_kill_date` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`), + KEY `idx_account` (`account`), + KEY `idx_online` (`online`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System'; + +-- +-- Dumping data for table `character` +-- + +/*!40000 ALTER TABLE `character` DISABLE KEYS */; +/*!40000 ALTER TABLE `character` ENABLE KEYS */; + + +-- +-- Definition of table `character_action` +-- + +DROP TABLE IF EXISTS `characters`.`character_action`; +CREATE TABLE `characters`.`character_action` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `button` tinyint(3) unsigned NOT NULL default '0', + `action` smallint(5) unsigned NOT NULL default '0', + `type` tinyint(3) unsigned NOT NULL default '0', + `misc` tinyint(3) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`,`button`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System'; + +-- +-- Dumping data for table `character_action` +-- + +/*!40000 ALTER TABLE `character_action` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_action` ENABLE KEYS */; + + +-- +-- Definition of table `character_aura` +-- + +DROP TABLE IF EXISTS `characters`.`character_aura`; +CREATE TABLE `characters`.`character_aura` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `caster_guid` bigint(20) unsigned NOT NULL default '0' COMMENT 'Full Global Unique Identifier', + `spell` int(11) unsigned NOT NULL default '0', + `effect_index` int(11) unsigned NOT NULL default '0', + `amount` int(11) NOT NULL default '0', + `maxduration` int(11) NOT NULL default '0', + `remaintime` int(11) NOT NULL default '0', + `remaincharges` int(11) NOT NULL default '0', + PRIMARY KEY (`guid`,`spell`,`effect_index`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System'; + +-- +-- Dumping data for table `character_aura` +-- + +/*!40000 ALTER TABLE `character_aura` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_aura` ENABLE KEYS */; + + +-- +-- Definition of table `character_gifts` +-- + +DROP TABLE IF EXISTS `characters`.`character_gifts`; +CREATE TABLE `characters`.`character_gifts` ( + `guid` int(20) unsigned NOT NULL default '0', + `item_guid` int(11) unsigned NOT NULL default '0', + `entry` int(20) unsigned NOT NULL default '0', + `flags` int(20) unsigned NOT NULL default '0', + PRIMARY KEY (`item_guid`), + KEY `idx_guid` (`guid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `character_gifts` +-- + +/*!40000 ALTER TABLE `character_gifts` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_gifts` ENABLE KEYS */; + + +-- +-- Definition of table `character_homebind` +-- + +DROP TABLE IF EXISTS `characters`.`character_homebind`; +CREATE TABLE `characters`.`character_homebind` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `map` int(11) unsigned NOT NULL default '0' COMMENT 'Map Identifier', + `zone` int(11) unsigned NOT NULL default '0' COMMENT 'Zone Identifier', + `position_x` float NOT NULL default '0', + `position_y` float NOT NULL default '0', + `position_z` float NOT NULL default '0', + PRIMARY KEY (`guid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System'; + +-- +-- Dumping data for table `character_homebind` +-- + +/*!40000 ALTER TABLE `character_homebind` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_homebind` ENABLE KEYS */; + + +-- +-- Definition of table `character_instance` +-- + +DROP TABLE IF EXISTS `characters`.`character_instance`; +CREATE TABLE `characters`.`character_instance` ( + `guid` int(11) unsigned NOT NULL default '0', + `map` int(11) unsigned NOT NULL default '0', + `instance` bigint(40) NOT NULL default '0', + `leader` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`,`map`), + KEY `instance` (`instance`), + KEY `leader` (`leader`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `character_instance` +-- + +/*!40000 ALTER TABLE `character_instance` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_instance` ENABLE KEYS */; + + +-- +-- Definition of table `character_inventory` +-- + +DROP TABLE IF EXISTS `characters`.`character_inventory`; +CREATE TABLE `characters`.`character_inventory` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `bag` int(11) unsigned NOT NULL default '0', + `slot` tinyint(3) unsigned NOT NULL default '0', + `item` int(11) unsigned NOT NULL default '0' COMMENT 'Item Global Unique Identifier', + `item_template` int(11) unsigned NOT NULL default '0' COMMENT 'Item Identifier', + PRIMARY KEY (`item`), + KEY `idx_guid` (`guid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System'; + +-- +-- Dumping data for table `character_inventory` +-- + +/*!40000 ALTER TABLE `character_inventory` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_inventory` ENABLE KEYS */; + + +-- +-- Definition of table `character_kill` +-- + +DROP TABLE IF EXISTS `characters`.`character_kill`; +CREATE TABLE `characters`.`character_kill` ( + `guid` int(11) unsigned NOT NULL default '0', + `victim_guid` int(11) unsigned NOT NULL default '0', + `count` tinyint(3) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`,`victim_guid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Kills Yesterday'; + +-- +-- Dumping data for table `character_kill` +-- + +/*!40000 ALTER TABLE `character_kill` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_kill` ENABLE KEYS */; + + +-- +-- Definition of table `character_pet` +-- + +DROP TABLE IF EXISTS `characters`.`character_pet`; +CREATE TABLE `characters`.`character_pet` ( + `id` int(11) unsigned NOT NULL default '0', + `entry` int(11) unsigned NOT NULL default '0', + `owner` int(11) unsigned NOT NULL default '0', + `modelid` int(11) unsigned default '0', + `CreatedBySpell` int(11) unsigned NOT NULL default '0', + `PetType` tinyint(3) unsigned NOT NULL default '0', + `level` int(11) unsigned NOT NULL default '1', + `exp` int(11) unsigned NOT NULL default '0', + `nextlvlexp` int(11) unsigned NOT NULL default '100', + `Reactstate` tinyint(1) unsigned NOT NULL default '0', + `Commandstate` tinyint(1) unsigned NOT NULL default '1', + `loyaltypoints` int(11) NOT NULL default '0', + `loyalty` int(11) unsigned NOT NULL default '0', + `trainpoint` int(11) NOT NULL default '0', + `name` varchar(100) default 'Pet', + `renamed` tinyint(1) unsigned NOT NULL default '0', + `slot` int(11) unsigned NOT NULL default '0', + `curhealth` int(11) unsigned NOT NULL default '1', + `curmana` int(11) unsigned NOT NULL default '0', + `curhappiness` int(11) unsigned NOT NULL default '0', + `savetime` bigint(20) unsigned NOT NULL default '0', + `resettalents_cost` int(11) unsigned NOT NULL default '0', + `resettalents_time` bigint(20) unsigned NOT NULL default '0', + `ABData` longtext, + `TeachSpelldata` longtext, + PRIMARY KEY (`id`), + KEY `owner` (`owner`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Pet System'; + +-- +-- Dumping data for table `character_pet` +-- + +/*!40000 ALTER TABLE `character_pet` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_pet` ENABLE KEYS */; + + +-- +-- Definition of table `character_queststatus` +-- + +DROP TABLE IF EXISTS `characters`.`character_queststatus`; +CREATE TABLE `characters`.`character_queststatus` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `quest` int(11) unsigned NOT NULL default '0' COMMENT 'Quest Identifier', + `status` int(11) unsigned NOT NULL default '0', + `rewarded` tinyint(1) unsigned NOT NULL default '0', + `explored` tinyint(1) unsigned NOT NULL default '0', + `timer` bigint(20) unsigned NOT NULL default '0', + `mobcount1` int(11) unsigned NOT NULL default '0', + `mobcount2` int(11) unsigned NOT NULL default '0', + `mobcount3` int(11) unsigned NOT NULL default '0', + `mobcount4` int(11) unsigned NOT NULL default '0', + `itemcount1` int(11) unsigned NOT NULL default '0', + `itemcount2` int(11) unsigned NOT NULL default '0', + `itemcount3` int(11) unsigned NOT NULL default '0', + `itemcount4` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`,`quest`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System'; + +-- +-- Dumping data for table `character_queststatus` +-- + +/*!40000 ALTER TABLE `character_queststatus` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_queststatus` ENABLE KEYS */; + + +-- +-- Definition of table `character_queststatus_daily` +-- + +DROP TABLE IF EXISTS `characters`.`character_queststatus_daily`; +CREATE TABLE `characters`.`character_queststatus_daily` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `quest` int(11) unsigned NOT NULL default '0' COMMENT 'Quest Identifier', + `time` bigint(20) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`,`quest`), + KEY `idx_guid` (`guid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System'; + +-- +-- Dumping data for table `character_queststatus_daily` +-- + +/*!40000 ALTER TABLE `character_queststatus_daily` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_queststatus_daily` ENABLE KEYS */; + + +-- +-- Definition of table `character_reputation` +-- + +DROP TABLE IF EXISTS `characters`.`character_reputation`; +CREATE TABLE `characters`.`character_reputation` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `faction` int(11) unsigned NOT NULL default '0', + `standing` int(11) NOT NULL default '0', + `flags` int(11) NOT NULL default '0', + PRIMARY KEY (`guid`,`faction`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System'; + +-- +-- Dumping data for table `character_reputation` +-- + +/*!40000 ALTER TABLE `character_reputation` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_reputation` ENABLE KEYS */; + + +-- +-- Definition of table `character_social` +-- + +DROP TABLE IF EXISTS `characters`.`character_social`; +CREATE TABLE `characters`.`character_social` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `name` varchar(21) NOT NULL default '', + `friend` int(11) unsigned NOT NULL default '0' COMMENT 'Character Global Unique Identifier', + `flags` varchar(21) NOT NULL default '', + PRIMARY KEY (`guid`,`friend`,`flags`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System'; + +-- +-- Dumping data for table `character_social` +-- + +/*!40000 ALTER TABLE `character_social` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_social` ENABLE KEYS */; + + +-- +-- Definition of table `character_spell` +-- + +DROP TABLE IF EXISTS `characters`.`character_spell`; +CREATE TABLE `characters`.`character_spell` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `spell` int(11) unsigned NOT NULL default '0' COMMENT 'Spell Identifier', + `slot` int(11) unsigned NOT NULL default '0', + `active` tinyint(3) unsigned NOT NULL default '1', + PRIMARY KEY (`guid`,`spell`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System'; + +-- +-- Dumping data for table `character_spell` +-- + +/*!40000 ALTER TABLE `character_spell` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_spell` ENABLE KEYS */; + + +-- +-- Definition of table `character_spell_cooldown` +-- + +DROP TABLE IF EXISTS `characters`.`character_spell_cooldown`; +CREATE TABLE `characters`.`character_spell_cooldown` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier, Low part', + `spell` int(11) unsigned NOT NULL default '0' COMMENT 'Spell Identifier', + `item` int(11) unsigned NOT NULL default '0' COMMENT 'Item Identifier', + `time` bigint(20) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`,`spell`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `character_spell_cooldown` +-- + +/*!40000 ALTER TABLE `character_spell_cooldown` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_spell_cooldown` ENABLE KEYS */; + + +-- +-- Definition of table `character_ticket` +-- + +DROP TABLE IF EXISTS `characters`.`character_ticket`; +CREATE TABLE `characters`.`character_ticket` ( + `ticket_id` int(11) unsigned NOT NULL auto_increment, + `guid` int(11) unsigned NOT NULL default '0', + `ticket_text` text, + `ticket_category` int(1) NOT NULL default '0', + PRIMARY KEY (`ticket_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System'; + +-- +-- Dumping data for table `character_ticket` +-- + +/*!40000 ALTER TABLE `character_ticket` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_ticket` ENABLE KEYS */; + + +-- +-- Definition of table `character_tutorial` +-- + +DROP TABLE IF EXISTS `characters`.`character_tutorial`; +CREATE TABLE `characters`.`character_tutorial` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `tut0` int(11) unsigned NOT NULL default '0', + `tut1` int(11) unsigned NOT NULL default '0', + `tut2` int(11) unsigned NOT NULL default '0', + `tut3` int(11) unsigned NOT NULL default '0', + `tut4` int(11) unsigned NOT NULL default '0', + `tut5` int(11) unsigned NOT NULL default '0', + `tut6` int(11) unsigned NOT NULL default '0', + `tut7` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System'; + +-- +-- Dumping data for table `character_tutorial` +-- + +/*!40000 ALTER TABLE `character_tutorial` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_tutorial` ENABLE KEYS */; + + +-- +-- Definition of table `corpse` +-- + +DROP TABLE IF EXISTS `characters`.`corpse`; +CREATE TABLE `characters`.`corpse` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `player` int(11) unsigned NOT NULL default '0' COMMENT 'Character Global Unique Identifier', + `position_x` float NOT NULL default '0', + `position_y` float NOT NULL default '0', + `position_z` float NOT NULL default '0', + `orientation` float NOT NULL default '0', + `zone` int(11) unsigned NOT NULL default '38' COMMENT 'Zone Identifier', + `map` int(11) unsigned NOT NULL default '0' COMMENT 'Map Identifier', + `data` longtext, + `time` timestamp NOT NULL default '0000-00-00 00:00:00', + `bones_flag` tinyint(3) NOT NULL default '0', + `instance` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`), + KEY `idx_bones_flag` (`bones_flag`), + KEY `instance` (`instance`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Death System'; + +-- +-- Dumping data for table `corpse` +-- + +/*!40000 ALTER TABLE `corpse` DISABLE KEYS */; +/*!40000 ALTER TABLE `corpse` ENABLE KEYS */; + + +-- +-- Definition of table `group` +-- + +DROP TABLE IF EXISTS `characters`.`group`; +CREATE TABLE `characters`.`group` ( + `leaderGuid` int(11) unsigned NOT NULL, + `mainTank` int(11) unsigned NOT NULL, + `mainAssistant` int(11) unsigned NOT NULL, + `lootMethod` tinyint(4) unsigned NOT NULL, + `looterGuid` int(11) unsigned NOT NULL, + `lootThreshold` tinyint(4) unsigned NOT NULL, + `icon1` int(11) unsigned NOT NULL, + `icon2` int(11) unsigned NOT NULL, + `icon3` int(11) unsigned NOT NULL, + `icon4` int(11) unsigned NOT NULL, + `icon5` int(11) unsigned NOT NULL, + `icon6` int(11) unsigned NOT NULL, + `icon7` int(11) unsigned NOT NULL, + `icon8` int(11) unsigned NOT NULL, + `isRaid` tinyint(1) unsigned NOT NULL, + PRIMARY KEY (`leaderGuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Groups'; + +-- +-- Dumping data for table `group` +-- + +/*!40000 ALTER TABLE `group` DISABLE KEYS */; +/*!40000 ALTER TABLE `group` ENABLE KEYS */; + + +-- +-- Definition of table `group_member` +-- + +DROP TABLE IF EXISTS `characters`.`group_member`; +CREATE TABLE `characters`.`group_member` ( + `leaderGuid` int(11) unsigned NOT NULL, + `memberGuid` int(11) unsigned NOT NULL, + `assistant` tinyint(1) unsigned NOT NULL, + `subgroup` smallint(6) unsigned NOT NULL, + PRIMARY KEY (`leaderGuid`,`memberGuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Groups'; + +-- +-- Dumping data for table `group_member` +-- + +/*!40000 ALTER TABLE `group_member` DISABLE KEYS */; +/*!40000 ALTER TABLE `group_member` ENABLE KEYS */; + + +-- +-- Definition of table `guild` +-- + +DROP TABLE IF EXISTS `characters`.`guild`; +CREATE TABLE `characters`.`guild` ( + `guildid` int(6) unsigned NOT NULL default '0', + `name` varchar(255) NOT NULL default '', + `leaderguid` int(6) unsigned NOT NULL default '0', + `EmblemStyle` int(5) NOT NULL default '0', + `EmblemColor` int(5) NOT NULL default '0', + `BorderStyle` int(5) NOT NULL default '0', + `BorderColor` int(5) NOT NULL default '0', + `BackgroundColor` int(5) NOT NULL default '0', + `info` text NOT NULL, + `MOTD` varchar(255) NOT NULL default '', + `createdate` datetime default NULL, + PRIMARY KEY (`guildid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Guild System'; + +-- +-- Dumping data for table `guild` +-- + +/*!40000 ALTER TABLE `guild` DISABLE KEYS */; +/*!40000 ALTER TABLE `guild` ENABLE KEYS */; + + +-- +-- Definition of table `guild_member` +-- + +DROP TABLE IF EXISTS `characters`.`guild_member`; +CREATE TABLE `characters`.`guild_member` ( + `guildid` int(6) unsigned NOT NULL default '0', + `guid` int(11) unsigned NOT NULL default '0', + `rank` tinyint(2) unsigned NOT NULL default '0', + `Pnote` varchar(255) NOT NULL default '', + `OFFnote` varchar(255) NOT NULL default '' +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Guild System'; + +-- +-- Dumping data for table `guild_member` +-- + +/*!40000 ALTER TABLE `guild_member` DISABLE KEYS */; +/*!40000 ALTER TABLE `guild_member` ENABLE KEYS */; + + +-- +-- Definition of table `guild_rank` +-- + +DROP TABLE IF EXISTS `characters`.`guild_rank`; +CREATE TABLE `characters`.`guild_rank` ( + `guildid` int(6) unsigned NOT NULL default '0', + `rid` int(11) unsigned NOT NULL, + `rname` varchar(255) NOT NULL default '', + `rights` int(3) unsigned NOT NULL default '0', + PRIMARY KEY (`guildid`,`rid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Guild System'; + +-- +-- Dumping data for table `guild_rank` +-- + +/*!40000 ALTER TABLE `guild_rank` DISABLE KEYS */; +/*!40000 ALTER TABLE `guild_rank` ENABLE KEYS */; + + +-- +-- Definition of table `instance` +-- + +DROP TABLE IF EXISTS `characters`.`instance`; +CREATE TABLE `characters`.`instance` ( + `id` int(11) unsigned NOT NULL default '0', + `map` int(11) unsigned NOT NULL default '0', + `resettime` bigint(40) NOT NULL default '0', + `data` longtext, + PRIMARY KEY (`id`), + KEY `map` (`map`), + KEY `resettime` (`resettime`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `instance` +-- + +/*!40000 ALTER TABLE `instance` DISABLE KEYS */; +/*!40000 ALTER TABLE `instance` ENABLE KEYS */; + + +-- +-- Definition of table `item_instance` +-- + +DROP TABLE IF EXISTS `characters`.`item_instance`; +CREATE TABLE `characters`.`item_instance` ( + `guid` int(11) unsigned NOT NULL default '0', + `owner_guid` int(11) unsigned NOT NULL default '0', + `data` longtext, + PRIMARY KEY (`guid`), + KEY `idx_owner_guid` (`owner_guid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Item System'; + +-- +-- Dumping data for table `item_instance` +-- + +/*!40000 ALTER TABLE `item_instance` DISABLE KEYS */; +/*!40000 ALTER TABLE `item_instance` ENABLE KEYS */; + + +-- +-- Definition of table `item_text` +-- + +DROP TABLE IF EXISTS `characters`.`item_text`; +CREATE TABLE `characters`.`item_text` ( + `id` int(11) unsigned NOT NULL default '0', + `text` longtext, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Item System'; + +-- +-- Dumping data for table `item_text` +-- + +/*!40000 ALTER TABLE `item_text` DISABLE KEYS */; +/*!40000 ALTER TABLE `item_text` ENABLE KEYS */; + + +-- +-- Definition of table `mail` +-- + +DROP TABLE IF EXISTS `characters`.`mail`; +CREATE TABLE `characters`.`mail` ( + `id` int(11) unsigned NOT NULL default '0' COMMENT 'Identifier', + `messageType` tinyint(3) unsigned NOT NULL default '0', + `sender` int(11) unsigned NOT NULL default '0' COMMENT 'Character Global Unique Identifier', + `receiver` int(11) unsigned NOT NULL default '0' COMMENT 'Character Global Unique Identifier', + `subject` longtext, + `itemTextId` int(11) unsigned NOT NULL default '0', + `item_guid` int(11) unsigned NOT NULL default '0' COMMENT 'Mail Item Global Unique Identifier', + `item_template` int(11) unsigned NOT NULL default '0' COMMENT 'Item Identifier', + `expire_time` bigint(40) NOT NULL default '0', + `deliver_time` bigint(40) NOT NULL default '0', + `money` int(11) unsigned NOT NULL default '0', + `cod` int(11) unsigned NOT NULL default '0', + `checked` tinyint(3) unsigned NOT NULL default '0', + PRIMARY KEY (`id`), + KEY `idx_receiver` (`receiver`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Mail System'; + +-- +-- Dumping data for table `mail` +-- + +/*!40000 ALTER TABLE `mail` DISABLE KEYS */; +/*!40000 ALTER TABLE `mail` ENABLE KEYS */; + + +-- +-- Definition of table `pet_aura` +-- + +DROP TABLE IF EXISTS `characters`.`pet_aura`; +CREATE TABLE `characters`.`pet_aura` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `caster_guid` bigint(20) unsigned NOT NULL default '0' COMMENT 'Full Global Unique Identifier', + `spell` int(11) unsigned NOT NULL default '0', + `effect_index` int(11) unsigned NOT NULL default '0', + `amount` int(11) NOT NULL default '0', + `maxduration` int(11) NOT NULL default '0', + `remaintime` int(11) NOT NULL default '0', + `remaincharges` int(11) NOT NULL default '0', + PRIMARY KEY (`guid`,`spell`,`effect_index`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Pet System'; + +-- +-- Dumping data for table `pet_aura` +-- + +/*!40000 ALTER TABLE `pet_aura` DISABLE KEYS */; +/*!40000 ALTER TABLE `pet_aura` ENABLE KEYS */; + + +-- +-- Definition of table `pet_spell` +-- + +DROP TABLE IF EXISTS `characters`.`pet_spell`; +CREATE TABLE `characters`.`pet_spell` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `spell` int(11) unsigned NOT NULL default '0' COMMENT 'Spell Identifier', + `slot` int(11) unsigned NOT NULL default '0', + `active` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`,`spell`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Pet System'; + +-- +-- Dumping data for table `pet_spell` +-- + +/*!40000 ALTER TABLE `pet_spell` DISABLE KEYS */; +/*!40000 ALTER TABLE `pet_spell` ENABLE KEYS */; + + +-- +-- Definition of table `pet_spell_cooldown` +-- + +DROP TABLE IF EXISTS `characters`.`pet_spell_cooldown`; +CREATE TABLE `characters`.`pet_spell_cooldown` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier, Low part', + `spell` int(11) unsigned NOT NULL default '0' COMMENT 'Spell Identifier', + `time` bigint(20) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`,`spell`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `pet_spell_cooldown` +-- + +/*!40000 ALTER TABLE `pet_spell_cooldown` DISABLE KEYS */; +/*!40000 ALTER TABLE `pet_spell_cooldown` ENABLE KEYS */; + + +-- +-- Definition of table `petition` +-- + +DROP TABLE IF EXISTS `characters`.`petition`; +CREATE TABLE `characters`.`petition` ( + `ownerguid` int(10) unsigned NOT NULL, + `petitionguid` int(10) unsigned default '0', + `name` varchar(255) NOT NULL default '', + `type` int(10) unsigned NOT NULL default '0', + PRIMARY KEY (`ownerguid`), + UNIQUE KEY `index_ownerguid_petitionguid` (`ownerguid`,`petitionguid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Guild System'; + +-- +-- Dumping data for table `petition` +-- + +/*!40000 ALTER TABLE `petition` DISABLE KEYS */; +/*!40000 ALTER TABLE `petition` ENABLE KEYS */; + + +-- +-- Definition of table `petition_sign` +-- + +DROP TABLE IF EXISTS `characters`.`petition_sign`; +CREATE TABLE `characters`.`petition_sign` ( + `ownerguid` int(10) unsigned NOT NULL, + `petitionguid` int(11) unsigned NOT NULL default '0', + `playerguid` int(11) unsigned NOT NULL default '0', + `player_account` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`petitionguid`,`playerguid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Guild System'; + + +INSERT INTO `characters`.`arena_team` SELECT * FROM `arena_team`; +INSERT INTO `characters`.`arena_team_member` SELECT * FROM `arena_team_member`; +INSERT INTO `characters`.`arena_team_stats` SELECT * FROM `arena_team_stats`; +INSERT INTO `characters`.`auctionhouse` SELECT * FROM `auctionhouse`; +INSERT INTO `characters`.`bugreport` SELECT * FROM `bugreport`; +INSERT INTO `characters`.`character` SELECT * FROM `character`; +INSERT INTO `characters`.`character_action` SELECT * FROM `character_action`; +INSERT INTO `characters`.`character_aura` SELECT * FROM `character_aura`; +INSERT INTO `characters`.`character_gifts` SELECT * FROM `character_gifts`; +INSERT INTO `characters`.`character_homebind` SELECT * FROM `character_homebind`; +INSERT INTO `characters`.`character_instance` SELECT * FROM `character_instance`; +INSERT INTO `characters`.`character_inventory` SELECT * FROM `character_inventory`; +INSERT INTO `characters`.`character_kill` SELECT * FROM `character_kill`; +INSERT INTO `characters`.`character_pet` SELECT * FROM `character_pet`; +INSERT INTO `characters`.`character_queststatus` SELECT * FROM `character_queststatus`; +INSERT INTO `characters`.`character_queststatus_daily` SELECT * FROM `character_queststatus_daily`; +INSERT INTO `characters`.`character_reputation` SELECT * FROM `character_reputation`; +INSERT INTO `characters`.`character_social` SELECT * FROM `character_social`; +INSERT INTO `characters`.`character_spell` SELECT * FROM `character_spell`; +INSERT INTO `characters`.`character_spell_cooldown` SELECT * FROM `character_spell_cooldown`; +INSERT INTO `characters`.`character_ticket` SELECT * FROM `character_ticket`; +INSERT INTO `characters`.`character_tutorial` SELECT * FROM `character_tutorial`; +INSERT INTO `characters`.`corpse` SELECT * FROM `corpse`; +INSERT INTO `characters`.`group` SELECT * FROM `group`; +INSERT INTO `characters`.`group_member` SELECT * FROM `group_member`; +INSERT INTO `characters`.`guild` SELECT * FROM `guild`; +INSERT INTO `characters`.`guild_member` SELECT * FROM `guild_member`; +INSERT INTO `characters`.`guild_rank` SELECT * FROM `guild_rank`; +INSERT INTO `characters`.`instance` SELECT * FROM `instance`; +INSERT INTO `characters`.`item_instance` SELECT * FROM `item_instance`; +INSERT INTO `characters`.`item_text` SELECT * FROM `item_text`; +INSERT INTO `characters`.`mail` SELECT * FROM `mail`; +INSERT INTO `characters`.`pet_aura` SELECT * FROM `pet_aura`; +INSERT INTO `characters`.`pet_spell` SELECT * FROM `pet_spell`; +INSERT INTO `characters`.`pet_spell_cooldown` SELECT * FROM `pet_spell_cooldown`; +INSERT INTO `characters`.`petition` SELECT * FROM `petition`; +INSERT INTO `characters`.`petition_sign` SELECT * FROM `petition_sign`; + +DROP TABLE `arena_team`; +DROP TABLE `arena_team_member`; +DROP TABLE `arena_team_stats`; +DROP TABLE `auctionhouse`; +DROP TABLE `bugreport`; +DROP TABLE `character`; +DROP TABLE `character_action`; +DROP TABLE `character_aura`; +DROP TABLE `character_gifts`; +DROP TABLE `character_homebind`; +DROP TABLE `character_instance`; +DROP TABLE `character_inventory`; +DROP TABLE `character_kill`; +DROP TABLE `character_pet`; +DROP TABLE `character_queststatus`; +DROP TABLE `character_queststatus_daily`; +DROP TABLE `character_reputation`; +DROP TABLE `character_social`; +DROP TABLE `character_spell`; +DROP TABLE `character_spell_cooldown`; +DROP TABLE `character_ticket`; +DROP TABLE `character_tutorial`; +DROP TABLE `corpse`; +DROP TABLE `group`; +DROP TABLE `group_member`; +DROP TABLE `guild`; +DROP TABLE `guild_member`; +DROP TABLE `guild_rank`; +DROP TABLE `instance`; +DROP TABLE `item_instance`; +DROP TABLE `item_text`; +DROP TABLE `mail`; +DROP TABLE `pet_aura`; +DROP TABLE `pet_spell`; +DROP TABLE `pet_spell_cooldown`; +DROP TABLE `petition`; +DROP TABLE `petition_sign`; \ No newline at end of file diff --git a/sql/updates/0.9/4667_characters_character.sql b/sql/updates/0.9/4667_characters_character.sql new file mode 100644 index 00000000000..0b547019777 --- /dev/null +++ b/sql/updates/0.9/4667_characters_character.sql @@ -0,0 +1,2 @@ +ALTER TABLE `character` + DROP COLUMN `pending_kills`; \ No newline at end of file diff --git a/sql/updates/0.9/4674_mangos_skill_discovery_template.sql b/sql/updates/0.9/4674_mangos_skill_discovery_template.sql new file mode 100644 index 00000000000..7358a3a2d32 --- /dev/null +++ b/sql/updates/0.9/4674_mangos_skill_discovery_template.sql @@ -0,0 +1,8 @@ +DROP TABLE IF EXISTS `skill_discovery_template`; +CREATE TABLE `skill_discovery_template` ( + `spellId` int(11) unsigned NOT NULL default '0' COMMENT 'SpellId of the discoverable spell', + `reqSpell` int(11) unsigned NOT NULL default '0' COMMENT 'spell requirement', + `chance` float NOT NULL default '0' COMMENT 'chance to discover', + + PRIMARY KEY (`spellId`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Skill Discovery System'; \ No newline at end of file diff --git a/sql/updates/0.9/4679_mangos_spell_proc_event.sql b/sql/updates/0.9/4679_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..d268b87e3e2 --- /dev/null +++ b/sql/updates/0.9/4679_mangos_spell_proc_event.sql @@ -0,0 +1,4 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (34774, 34586); +INSERT INTO `spell_proc_event` VALUES +(34586,0,0,0,0,0,524289,1.5), +(34774,0,0,0,0,0,524289,1.5); diff --git a/sql/updates/0.9/4687_mangos_loot_template.sql b/sql/updates/0.9/4687_mangos_loot_template.sql new file mode 100644 index 00000000000..f2be66d26a6 --- /dev/null +++ b/sql/updates/0.9/4687_mangos_loot_template.sql @@ -0,0 +1,86 @@ +-- +-- Table changes for `creature_loot_template` +-- +ALTER TABLE `creature_loot_template` CHANGE COLUMN `quest_freeforall` `QuestFFAorLootCondition` TINYINT(3) NOT NULL DEFAULT 1, +ADD COLUMN `condition_value1` int(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `QuestFFAorLootCondition`, +ADD COLUMN `condition_value2` int(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `condition_value1`; + +ALTER TABLE `creature_loot_template` DROP PRIMARY KEY, +ADD PRIMARY KEY(`entry`, `item`, `condition_value1`); + + +-- +-- Table changes for `disenchant_loot_template` +-- +ALTER TABLE `disenchant_loot_template` CHANGE COLUMN `quest_freeforall` `QuestFFAorLootCondition` TINYINT(3) NOT NULL DEFAULT 1, +ADD COLUMN `condition_value1` int(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `QuestFFAorLootCondition`, +ADD COLUMN `condition_value2` int(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `condition_value1`; + +ALTER TABLE `disenchant_loot_template` DROP PRIMARY KEY, +ADD PRIMARY KEY(`entry`, `item`, `condition_value1`); + + +-- +-- Table changes for `fishing_loot_template` +-- +ALTER TABLE `fishing_loot_template` CHANGE COLUMN `quest_freeforall` `QuestFFAorLootCondition` TINYINT(3) NOT NULL DEFAULT 1, +ADD COLUMN `condition_value1` int(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `QuestFFAorLootCondition`, +ADD COLUMN `condition_value2` int(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `condition_value1`; + +ALTER TABLE `fishing_loot_template` DROP PRIMARY KEY, +ADD PRIMARY KEY(`entry`, `item`, `condition_value1`); + + +-- +-- Table changes for `gameobject_loot_template` +-- +ALTER TABLE `gameobject_loot_template` CHANGE COLUMN `quest_freeforall` `QuestFFAorLootCondition` TINYINT(3) NOT NULL DEFAULT 1, +ADD COLUMN `condition_value1` int(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `QuestFFAorLootCondition`, +ADD COLUMN `condition_value2` int(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `condition_value1`; + +ALTER TABLE `gameobject_loot_template` DROP PRIMARY KEY, +ADD PRIMARY KEY(`entry`, `item`, `condition_value1`); + + +-- +-- Table changes for `item_loot_template` +-- +ALTER TABLE `item_loot_template` CHANGE COLUMN `quest_freeforall` `QuestFFAorLootCondition` TINYINT(3) NOT NULL DEFAULT 1, +ADD COLUMN `condition_value1` int(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `QuestFFAorLootCondition`, +ADD COLUMN `condition_value2` int(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `condition_value1`; + +ALTER TABLE `item_loot_template` DROP PRIMARY KEY, +ADD PRIMARY KEY(`entry`, `item`, `condition_value1`); + + +-- +-- Table changes for `pickpocketing_loot_template` +-- +ALTER TABLE `pickpocketing_loot_template` CHANGE COLUMN `quest_freeforall` `QuestFFAorLootCondition` TINYINT(3) NOT NULL DEFAULT 1, +ADD COLUMN `condition_value1` int(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `QuestFFAorLootCondition`, +ADD COLUMN `condition_value2` int(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `condition_value1`; + +ALTER TABLE `pickpocketing_loot_template` DROP PRIMARY KEY, +ADD PRIMARY KEY(`entry`, `item`, `condition_value1`); + + +-- +-- Table changes for `skinning_loot_template` +-- +ALTER TABLE `skinning_loot_template` CHANGE COLUMN `quest_freeforall` `QuestFFAorLootCondition` TINYINT(3) NOT NULL DEFAULT 1, +ADD COLUMN `condition_value1` int(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `QuestFFAorLootCondition`, +ADD COLUMN `condition_value2` int(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `condition_value1`; + +ALTER TABLE `skinning_loot_template` DROP PRIMARY KEY, +ADD PRIMARY KEY(`entry`, `item`, `condition_value1`); + + +-- +-- Table changes for `prospecting_loot_template` +-- +ALTER TABLE `prospecting_loot_template` CHANGE COLUMN `quest_freeforall` `QuestFFAorLootCondition` TINYINT(3) NOT NULL DEFAULT 1, +ADD COLUMN `condition_value1` int(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `QuestFFAorLootCondition`, +ADD COLUMN `condition_value2` int(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `condition_value1`; + +ALTER TABLE `prospecting_loot_template` DROP PRIMARY KEY, +ADD PRIMARY KEY(`entry`, `item`, `condition_value1`); \ No newline at end of file diff --git a/sql/updates/0.9/4689_mangos_loot_template.sql b/sql/updates/0.9/4689_mangos_loot_template.sql new file mode 100644 index 00000000000..1f17de6388b --- /dev/null +++ b/sql/updates/0.9/4689_mangos_loot_template.sql @@ -0,0 +1,23 @@ +ALTER TABLE `creature_loot_template` DROP PRIMARY KEY, +ADD PRIMARY KEY(`entry`, `item`); + +ALTER TABLE `disenchant_loot_template` DROP PRIMARY KEY, +ADD PRIMARY KEY(`entry`, `item`); + +ALTER TABLE `fishing_loot_template` DROP PRIMARY KEY, +ADD PRIMARY KEY(`entry`, `item`); + +ALTER TABLE `gameobject_loot_template` DROP PRIMARY KEY, +ADD PRIMARY KEY(`entry`, `item`); + +ALTER TABLE `item_loot_template` DROP PRIMARY KEY, +ADD PRIMARY KEY(`entry`, `item`); + +ALTER TABLE `pickpocketing_loot_template` DROP PRIMARY KEY, +ADD PRIMARY KEY(`entry`, `item`); + +ALTER TABLE `skinning_loot_template` DROP PRIMARY KEY, +ADD PRIMARY KEY(`entry`, `item`); + +ALTER TABLE `prospecting_loot_template` DROP PRIMARY KEY, +ADD PRIMARY KEY(`entry`, `item`); diff --git a/sql/updates/0.9/4695_mangos_loot_template.sql b/sql/updates/0.9/4695_mangos_loot_template.sql new file mode 100644 index 00000000000..d395dd3f1c5 --- /dev/null +++ b/sql/updates/0.9/4695_mangos_loot_template.sql @@ -0,0 +1,39 @@ +ALTER TABLE `creature_loot_template` + CHANGE `QuestFFAorLootCondition` `freeforall` tinyint(1) unsigned NOT NULL default 0 COMMENT '1 if everybody should get a copy'; +ALTER TABLE `creature_loot_template` + ADD COLUMN `lootcondition` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `freeforall`; + +ALTER TABLE `disenchant_loot_template` + CHANGE `QuestFFAorLootCondition` `freeforall` tinyint(1) unsigned NOT NULL default 0 COMMENT '1 if everybody should get a copy'; +ALTER TABLE `disenchant_loot_template` + ADD COLUMN `lootcondition` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `freeforall`; + +ALTER TABLE `fishing_loot_template` + CHANGE `QuestFFAorLootCondition` `freeforall` tinyint(1) unsigned NOT NULL default 0 COMMENT '1 if everybody should get a copy'; +ALTER TABLE `fishing_loot_template` + ADD COLUMN `lootcondition` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `freeforall`; + +ALTER TABLE `gameobject_loot_template` + CHANGE `QuestFFAorLootCondition` `freeforall` tinyint(1) unsigned NOT NULL default 0 COMMENT '1 if everybody should get a copy'; +ALTER TABLE `gameobject_loot_template` + ADD COLUMN `lootcondition` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `freeforall`; + +ALTER TABLE `item_loot_template` + CHANGE `QuestFFAorLootCondition` `freeforall` tinyint(1) unsigned NOT NULL default 0 COMMENT '1 if everybody should get a copy'; +ALTER TABLE `item_loot_template` + ADD COLUMN `lootcondition` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `freeforall`; + +ALTER TABLE `pickpocketing_loot_template` + CHANGE `QuestFFAorLootCondition` `freeforall` tinyint(1) unsigned NOT NULL default 0 COMMENT '1 if everybody should get a copy'; +ALTER TABLE `pickpocketing_loot_template` + ADD COLUMN `lootcondition` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `freeforall`; + +ALTER TABLE `skinning_loot_template` + CHANGE `QuestFFAorLootCondition` `freeforall` tinyint(1) unsigned NOT NULL default 0 COMMENT '1 if everybody should get a copy'; +ALTER TABLE `skinning_loot_template` + ADD COLUMN `lootcondition` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `freeforall`; + +ALTER TABLE `prospecting_loot_template` + CHANGE `QuestFFAorLootCondition` `freeforall` tinyint(1) unsigned NOT NULL default 0 COMMENT '1 if everybody should get a copy'; +ALTER TABLE `prospecting_loot_template` + ADD COLUMN `lootcondition` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `freeforall`; diff --git a/sql/updates/0.9/4704_mangos_battlemaster_entry.sql b/sql/updates/0.9/4704_mangos_battlemaster_entry.sql new file mode 100644 index 00000000000..9506494373b --- /dev/null +++ b/sql/updates/0.9/4704_mangos_battlemaster_entry.sql @@ -0,0 +1,11 @@ +-- +-- Definition of table `battlemaster_entry` +-- + +DROP TABLE IF EXISTS `battlemaster_entry`; +CREATE TABLE `battlemaster_entry` ( + `entry` int(11) unsigned NOT NULL default '0' COMMENT 'Entry of a creature', + `bg_template` int(11) unsigned NOT NULL default '0' COMMENT 'Battleground template id', + + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; diff --git a/sql/updates/0.9/4714_mangos_spell_threat.sql b/sql/updates/0.9/4714_mangos_spell_threat.sql new file mode 100644 index 00000000000..d5610262813 --- /dev/null +++ b/sql/updates/0.9/4714_mangos_spell_threat.sql @@ -0,0 +1,45 @@ +/*Heroic Strike*/ +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES ('29707', '196'); +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES ('30324', '220'); +/*Maul*/ +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES ('26996', '176'); +/*Shield Slam*/ +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES ('25258', '286'); +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES ('30356', '323'); +/*Revenge*/ +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES ('25269', '400'); +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES ('30357', '483'); +/*Shield Bash*/ +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES ('29704', '230'); +/*Sunder Armor*/ +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES ('25225', '300'); +/*Cleave*/ +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES ('20569', '100'); +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES ('25231', '130'); +/*Lacerate*/ +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES ('33745', '285'); +/*Faerie Fire*/ +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES ('26993', '127'); +/*Faerie Fire(feral)*/ +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES ('16857', '108'); +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES ('17390', '108'); +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES ('17391', '108'); +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES ('17392', '108'); +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES ('27011', '127'); +/*Thunder Clap: multiplier = 1.75*/ +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES ('6343', '17'); +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES ('8198', '40'); +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES ('8204', '64'); +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES ('8205', '96'); +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES ('11580', '143'); +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES ('11581', '180'); +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES ('25264', '215'); +/*Mangle (Bear): multiplier = 1.5*/ +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES ('33878', '129'); +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES ('33986', '180'); +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES ('33987', '232'); +/*Holy Shield: multiplier = 0.35*/ +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES ('20925', '20'); +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES ('20927', '30'); +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES ('20928', '40'); +INSERT INTO `spell_threat` (`entry`, `Threat`) VALUES ('27179', '54'); diff --git a/sql/updates/0.9/4718_mangos_uptime.sql b/sql/updates/0.9/4718_mangos_uptime.sql new file mode 100644 index 00000000000..9cc6bb1bd48 --- /dev/null +++ b/sql/updates/0.9/4718_mangos_uptime.sql @@ -0,0 +1 @@ +ALTER TABLE `uptime` ENGINE=MyISAM; diff --git a/sql/updates/0.9/4737_mangos_command.sql b/sql/updates/0.9/4737_mangos_command.sql new file mode 100644 index 00000000000..204430ae409 --- /dev/null +++ b/sql/updates/0.9/4737_mangos_command.sql @@ -0,0 +1,15 @@ + + +DELETE FROM command WHERE name IN ('lookupitem','lookupitemset','lookupcreature','lookupobject','lookupquest','lookupskill','lookupspell','lookuptele'); + + +INSERT INTO `command` VALUES + ('lookup creature',3,'Syntax: .lookup creature $namepart\r\n\r\nLooks up a creature by $namepart, and returns all matches with their creature ID\'s.'), + ('lookup item',3,'Syntax: .lookup item $itemname\r\n\r\nLooks up an item by $itemname, and returns all matches with their Item ID\'s.'), + ('lookup itemset',3,'Syntax: .lookup itemset $itemname\r\n\r\nLooks up an item set by $itemname, and returns all matches with their Item set ID\'s.'), + ('lookup object',3,'Syntax: .lookup object $objname\r\n\r\nLooks up an gameobject by $objname, and returns all matches with their Gameobject ID\'s.'), + ('lookup quest',3,'Syntax: .lookup quest $namepart\r\n\r\nLooks up a quest by $namepart, and returns all matches with their quest ID\'s.'), + ('lookup skill',3,'Syntax: .lookup skill $$namepart\r\n\r\nLooks up a skill by $namepart, and returns all matches with their skill ID\'s.'), + ('lookup spell',3,'Syntax: .lookup spell $namepart\r\n\r\nLooks up a spell by $namepart, and returns all matches with their spell ID\'s.'), + ('lookup tele',1,'Syntax: .lookup tele $substring\r\n\r\nSearch and output all .tele command locations with provide $substring in name.'); + diff --git a/sql/updates/0.9/4764_characters_auctionhouse.sql b/sql/updates/0.9/4764_characters_auctionhouse.sql new file mode 100644 index 00000000000..d481deb9ac5 --- /dev/null +++ b/sql/updates/0.9/4764_characters_auctionhouse.sql @@ -0,0 +1,2 @@ +ALTER TABLE `auctionhouse` + ADD UNIQUE KEY `item_guid` (`itemguid`); diff --git a/sql/updates/0.9/4772_mangos_item_template.sql b/sql/updates/0.9/4772_mangos_item_template.sql new file mode 100644 index 00000000000..73a81d12bb2 --- /dev/null +++ b/sql/updates/0.9/4772_mangos_item_template.sql @@ -0,0 +1 @@ +UPDATE `item_template` SET `subclass` = '0' where `class` = '0'; \ No newline at end of file diff --git a/sql/updates/0.9/4781_mangos_gameobject_loot_template.sql b/sql/updates/0.9/4781_mangos_gameobject_loot_template.sql new file mode 100644 index 00000000000..c7b39204a4b --- /dev/null +++ b/sql/updates/0.9/4781_mangos_gameobject_loot_template.sql @@ -0,0 +1,50 @@ +-- Addgo command change +DELETE FROM `command` WHERE `name`='addgo'; +INSERT INTO `command` (`name`,`security`,`help`) VALUES + ('addgo',2,'Syntax: .addgo #id \r\n\r\nAdd a game object from game object templates to the world at your current location using the #id.\r\nspawntimesecs sets the spawntime, it is optional.\r\n\r\nNote: this is a copy of .gameobject.'); + +-- Creation of first temp table +DROP TABLE IF EXISTS `goloot`; +CREATE TABLE `goloot` ( + `entry` int(11) unsigned NOT NULL default '0', + `loot` int(11) unsigned NOT NULL default '0', + `sound1` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`), + INDEX `idx_loot` (`loot`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Go Loot Errors'; + +-- Filling table +INSERT IGNORE INTO `goloot` (`entry`,`loot`,`sound1`) SELECT `entry`,`entry`,`sound1` FROM `gameobject_template` WHERE `type` IN (3,25); -- AND `sound1`!=0; +UPDATE `goloot` a,`gameobject` b SET a.`loot`=b.`loot` WHERE a.`entry`=b.`id` AND b.`loot`!=0; + +-- Second temp table +DROP TABLE IF EXISTS `goloot2`; +CREATE TABLE `goloot2` ( + `sound1` int(11) unsigned NOT NULL default '0', + `loot` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`sound1`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Temp Table'; + +-- Put data into +INSERT INTO `goloot2` (`sound1`,`loot`) SELECT DISTINCT `sound1`,MIN(`loot`) FROM `goloot` WHERE `loot`!=0 AND `sound1`!=0 AND `loot` IN (SELECT DISTINCT `entry` FROM `gameobject_loot_template`) GROUP BY `sound1`; + +-- Now update gameobject_loot_template with new ids +UPDATE IGNORE `gameobject_loot_template` a,`goloot2` b SET a.`entry`=b.`sound1`+1000000 WHERE a.`entry`=b.`loot`; + +-- Now remove remaining loots not binded (conflits in several update or just garbage) +DELETE FROM `gameobject_loot_template` WHERE `entry` NOT IN (SELECT DISTINCT `sound1`+1000000 FROM `goloot2` UNION SELECT DISTINCT `loot` FROM `goloot` WHERE `sound1`=0); +UPDATE `gameobject_loot_template` SET `entry`=`entry`-1000000 WHERE `entry`>1000000; + +-- Cleanup but let bad sound1 entries for later correction +DELETE FROM `goloot` WHERE `sound1`!=0; +DELETE FROM `goloot` WHERE `loot` NOT IN (SELECT DISTINCT `entry` FROM `gameobject_loot_template`); + +-- Inverse comments in following 3 lines to see generated errors on conversion for gameobjects type 3 with sound1=0 +-- DROP TABLE IF EXISTS `gameobject_loot_errors`; +-- RENAME TABLE `goloot` TO `gameobject_loot_errors`; +DROP TABLE IF EXISTS `goloot`; + +-- Remove second temp table +DROP TABLE IF EXISTS `goloot2`; +-- Remove now not usefull loot column +ALTER TABLE `gameobject` DROP COLUMN `loot`; diff --git a/sql/updates/0.9/4788_mangos_gameobject_template.sql b/sql/updates/0.9/4788_mangos_gameobject_template.sql new file mode 100644 index 00000000000..851cfcf804d --- /dev/null +++ b/sql/updates/0.9/4788_mangos_gameobject_template.sql @@ -0,0 +1,25 @@ +ALTER TABLE `gameobject_template` + CHANGE COLUMN `sound0` `data0` int(11) unsigned NOT NULL default '0', + CHANGE COLUMN `sound1` `data1` int(11) unsigned NOT NULL default '0', + CHANGE COLUMN `sound2` `data2` int(11) unsigned NOT NULL default '0', + CHANGE COLUMN `sound3` `data3` int(11) unsigned NOT NULL default '0', + CHANGE COLUMN `sound4` `data4` int(11) unsigned NOT NULL default '0', + CHANGE COLUMN `sound5` `data5` int(11) unsigned NOT NULL default '0', + CHANGE COLUMN `sound6` `data6` int(11) unsigned NOT NULL default '0', + CHANGE COLUMN `sound7` `data7` int(11) unsigned NOT NULL default '0', + CHANGE COLUMN `sound8` `data8` int(11) unsigned NOT NULL default '0', + CHANGE COLUMN `sound9` `data9` int(11) unsigned NOT NULL default '0', + CHANGE COLUMN `sound10` `data10` int(11) unsigned NOT NULL default '0', + CHANGE COLUMN `sound11` `data11` int(11) unsigned NOT NULL default '0', + CHANGE COLUMN `sound12` `data12` int(11) unsigned NOT NULL default '0', + CHANGE COLUMN `sound13` `data13` int(11) unsigned NOT NULL default '0', + CHANGE COLUMN `sound14` `data14` int(11) unsigned NOT NULL default '0', + CHANGE COLUMN `sound15` `data15` int(11) unsigned NOT NULL default '0', + CHANGE COLUMN `sound16` `data16` int(11) unsigned NOT NULL default '0', + CHANGE COLUMN `sound17` `data17` int(11) unsigned NOT NULL default '0', + CHANGE COLUMN `sound18` `data18` int(11) unsigned NOT NULL default '0', + CHANGE COLUMN `sound19` `data19` int(11) unsigned NOT NULL default '0', + CHANGE COLUMN `sound20` `data20` int(11) unsigned NOT NULL default '0', + CHANGE COLUMN `sound21` `data21` int(11) unsigned NOT NULL default '0', + CHANGE COLUMN `sound22` `data22` int(11) unsigned NOT NULL default '0', + CHANGE COLUMN `sound23` `data23` int(11) unsigned NOT NULL default '0'; diff --git a/sql/updates/0.9/4793_mangos_spell_affect.sql b/sql/updates/0.9/4793_mangos_spell_affect.sql new file mode 100644 index 00000000000..f59f9108840 --- /dev/null +++ b/sql/updates/0.9/4793_mangos_spell_affect.sql @@ -0,0 +1,109 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (37441); +INSERT INTO `spell_affect` VALUES +(37441,0,0,0,0,0,0,0x0000000020000000,0), +(37441,1,0,0,0,0,0,0x0000000020000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (33421,33713,33714); +INSERT INTO `spell_affect` VALUES +(33421,0,0,0,0,0,0,0x0000000200000000,0), +(33713,0,0,0,0,0,0,0x0000000200000000,0), +(33714,0,0,0,0,0,0,0x0000000200000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (11222,12839,12840,12841,12842); +INSERT INTO `spell_affect` VALUES +(11222,0,0,0,0,0,0,0x0000000020001800,0), +(12839,0,0,0,0,0,0,0x0000000020001800,0), +(12840,0,0,0,0,0,0,0x0000000020001800,0), +(12841,0,0,0,0,0,0,0x0000000020001800,0), +(12842,0,0,0,0,0,0,0x0000000020001800,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (11242,12467,12469); +INSERT INTO `spell_affect` VALUES +(11242,0,0,0,0,0,0,0x0000000020001000,0), +(12467,0,0,0,0,0,0,0x0000000020001000,0), +(12469,0,0,0,0,0,0,0x0000000020001000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (12042); +INSERT INTO `spell_affect` VALUES +(12042,0,0,0,0,0,0,0x0000000020E01AF7,0), +(12042,1,0,0,0,0,0,0x0000000020E01AF7,0), +(12042,2,0,0,0,0,0,0x0000000020E01AF7,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (11083,12351); +INSERT INTO `spell_affect` VALUES +(11083,0,0,0,0,0,0,0x0000000000C20017,0), +(12351,0,0,0,0,0,0,0x0000000000C20017,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (12536); +INSERT INTO `spell_affect` VALUES +(12536,0,0,0,0,0,0,0x0000000020C01AF7,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (28682); +INSERT INTO `spell_affect` VALUES +(28682,0,0,0,0,0,0,0x0000004008C20017,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (37439); +INSERT INTO `spell_affect` VALUES +(37439,0,0,0,0,0,0,0x0000002000000000,0), +(37439,1,0,0,0,0,0,0x0000004000000000,0), +(37439,2,0,0,0,0,0,0x0000008000000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (29438,29439,29440); +INSERT INTO `spell_affect` VALUES +(29438,0,0,0,0,0,0,0x0000000000D000D7,0), +(29439,0,0,0,0,0,0,0x0000000000D000D7,0), +(29440,0,0,0,0,0,0,0x0000000000D000D7,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (31685); +INSERT INTO `spell_affect` VALUES +(31685,0,0,0,0,0,0,0x0000000000000020,0), +(31685,1,0,0,0,0,0,0x0000000000000020,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (11124,12378,12398,12399,12400); +INSERT INTO `spell_affect` VALUES +(11124,0,0,0,0,0,0,0x0000000008C20017,0), +(12378,0,0,0,0,0,0,0x0000000008C20017,0), +(12398,0,0,0,0,0,0,0x0000000008C20017,0), +(12399,0,0,0,0,0,0,0x0000000008C20017,0), +(12400,0,0,0,0,0,0,0x0000000008C20017,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (11160,12518,12519); +INSERT INTO `spell_affect` VALUES +(11160,0,0,0,0,0,0,0x00000001020003E0,0), +(12518,0,0,0,0,0,0,0x00000001020003E0,0), +(12519,0,0,0,0,0,0,0x00000001020003E0,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (11207,12672,15047,15052,15053); +INSERT INTO `spell_affect` VALUES +(11207,0,0,0,0,0,0,0x00000000000002E0,0), +(12672,0,0,0,0,0,0,0x00000000000002E0,0), +(15047,0,0,0,0,0,0,0x00000000000002E0,0), +(15052,0,0,0,0,0,0,0x00000000000002E0,0), +(15053,0,0,0,0,0,0,0x00000000000002E0,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (24429); +INSERT INTO `spell_affect` VALUES +(24429,0,0,0,0,0,0,0x0000000000004000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (22008); +INSERT INTO `spell_affect` VALUES +(22008,0,0,0,0,0,0,0x0000000021400035,1); + +DELETE FROM `spell_affect` WHERE `entry` IN (11151,12952,12953,12954,12957); +INSERT INTO `spell_affect` VALUES +(11151,0,0,0,0,0,0,0x00000000000002E0,0), +(12952,0,0,0,0,0,0,0x00000000000002E0,0), +(12953,0,0,0,0,0,0,0x00000000000002E0,0), +(12954,0,0,0,0,0,0,0x00000000000002E0,0), +(12957,0,0,0,0,0,0,0x00000000000002E0,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (12043,29976); +INSERT INTO `spell_affect` VALUES +(12043,0,0,0,0,0,0,0x0000000021400035,0), +(29976,0,0,0,0,0,0,0x0000000021400035,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (35578,35581); +INSERT INTO `spell_affect` VALUES +(35578,0,0,0,0,0,0,0x0000000028C21AF7,0), +(35581,0,0,0,0,0,0,0x0000000028C21AF7,0); + diff --git a/sql/updates/0.9/4799_mangos_creature_addon.sql b/sql/updates/0.9/4799_mangos_creature_addon.sql new file mode 100644 index 00000000000..7a5971b7f0b --- /dev/null +++ b/sql/updates/0.9/4799_mangos_creature_addon.sql @@ -0,0 +1,37 @@ +-- create fields +ALTER TABLE `creature_addon` + ADD COLUMN `auras` text DEFAULT NULL AFTER `emote`; +ALTER TABLE `creature_template_addon` + ADD COLUMN `auras` text DEFAULT NULL AFTER `emote`; + +-- move data +UPDATE `creature_template_addon` SET `auras`=CONCAT(`aura`," 0") WHERE `aura`!=0; + +-- create missing records +INSERT IGNORE INTO `creature_addon` (`guid`) SELECT `guid` FROM `creature` WHERE `auras` IS NOT NULL AND TRIM(`auras`)!=""; +-- move data +UPDATE `creature_addon`,`creature` SET `creature_addon`.`auras`=`creature`.`auras` WHERE `creature_addon`.`guid`=`creature`.`guid` AND `creature`.`auras` IS NOT NULL AND TRIM(`creature`.`auras`)!=""; + +-- prepare fields +UPDATE `creature_addon` SET `auras`="" WHERE `auras` IS NULL AND `aura`!=0; +UPDATE `creature_addon` SET `auras`=CONCAT(`auras`," ") WHERE `auras`!="" AND `aura`!=0; +-- move data +UPDATE `creature_addon` SET `auras`=CONCAT(`auras`,`aura`," 0") WHERE `aura`!=0; + +-- Cleanup +ALTER TABLE `creature_addon` + DROP COLUMN `aura`, + DROP COLUMN `auraflags`, + DROP COLUMN `auralevels`, + DROP COLUMN `auraapplications`, + DROP COLUMN `aurastate`; + +ALTER TABLE `creature_template_addon` + DROP COLUMN `aura`, + DROP COLUMN `auraflags`, + DROP COLUMN `auralevels`, + DROP COLUMN `auraapplications`, + DROP COLUMN `aurastate`; + +ALTER TABLE `creature` + DROP COLUMN `auras`; diff --git a/sql/updates/0.9/4815_mangos_quest_template.sql b/sql/updates/0.9/4815_mangos_quest_template.sql new file mode 100644 index 00000000000..29d3a970487 --- /dev/null +++ b/sql/updates/0.9/4815_mangos_quest_template.sql @@ -0,0 +1,3 @@ +ALTER TABLE `quest_template` + CHANGE COLUMN `SpecialFlags` `QuestFlags` int(11) unsigned NOT NULL default '0'; +UPDATE `quest_template` SET `QuestFlags`=`QuestFlags`&4096; diff --git a/sql/updates/0.9/4829_mangos_command.sql b/sql/updates/0.9/4829_mangos_command.sql new file mode 100644 index 00000000000..1a20bcd87c8 --- /dev/null +++ b/sql/updates/0.9/4829_mangos_command.sql @@ -0,0 +1,5 @@ +DELETE FROM command WHERE name IN ('gozonexy','lookup area'); + +INSERT INTO `command` VALUES +('gozonexy',1,'Syntax: .gozonexy #x #y [#zone]\r\n\r\nTeleport player to point with (#x,#y) client coordinates at ground(water) level in zone #zoneid or current zone if #zoneid not provided. You can look up zone using .lookup area $namepart'), +('lookup area',1,'Syntax: .lookup area $namepart\r\n\r\nLooks up an area by $namepart, and returns all matches with their area ID\'s.'); diff --git a/sql/updates/0.9/4842_mangos_quest_template.sql b/sql/updates/0.9/4842_mangos_quest_template.sql new file mode 100644 index 00000000000..ce05a62c1fc --- /dev/null +++ b/sql/updates/0.9/4842_mangos_quest_template.sql @@ -0,0 +1,4 @@ +ALTER TABLE `quest_template` ADD COLUMN `SpecialFlags` tinyint(1) unsigned NOT NULL default '0' AFTER `QuestFlags`; +ALTER TABLE `quest_template` CHANGE COLUMN `QuestFlags` `QuestFlags` smallint(5) unsigned NOT NULL default '0'; +UPDATE `quest_template` SET `SpecialFlags`=1 WHERE `Repeatable`=1; +ALTER TABLE `quest_template` DROP COLUMN `Repeatable`; diff --git a/sql/updates/5651_characters_character_social.sql b/sql/updates/5651_characters_character_social.sql new file mode 100644 index 00000000000..a31270cd353 --- /dev/null +++ b/sql/updates/5651_characters_character_social.sql @@ -0,0 +1,5 @@ +alter table `character_social` +change `guid` `guid` int(11) unsigned NOT NULL DEFAULT '0' comment 'Character Global Unique Identifier' first, +change `friend` `friend` int(11) unsigned NOT NULL DEFAULT '0' comment 'Friend Global Unique Identifier' after `guid`, +change `flags` `flags` tinyint(1) unsigned NOT NULL DEFAULT '0' comment 'Friend flags' after `friend`, +change `name` `note` varchar(21) NOT NULL DEFAULT '' collate utf8_general_ci comment 'Friend Note' after `flags`; diff --git a/sql/updates/5651_characters_characters.sql b/sql/updates/5651_characters_characters.sql new file mode 100644 index 00000000000..e3f5e7cb370 --- /dev/null +++ b/sql/updates/5651_characters_characters.sql @@ -0,0 +1,19 @@ +UPDATE characters +SET data = CONCAT( + SUBSTRING_INDEX(data,' ',225+1), + ' 1 0 ', + SUBSTRING_INDEX(SUBSTRING_INDEX(data,' ',315+1),' ',225-315), + ' 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ', + SUBSTRING_INDEX(SUBSTRING_INDEX(data,' ',621+1),' ',315-621), + ' 0 ', + SUBSTRING_INDEX(SUBSTRING_INDEX(data,' ',822+1),' ',621-822), + ' 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ', + SUBSTRING_INDEX(SUBSTRING_INDEX(data,' ',1319+1),' ',822-1319), + ' 0 ', + SUBSTRING_INDEX(SUBSTRING_INDEX(data,' ',1351+1),' ',1319-1351), + ' 0 ', + SUBSTRING_INDEX(SUBSTRING_INDEX(data,' ',1447+1),' ',1351-1447), + ' 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ', + SUBSTRING_INDEX(data,' ',-1449+1447+1) +) +WHERE SUBSTRING_INDEX(data,' ',1448)=data; diff --git a/sql/updates/5651_characters_guild_bank_tab.sql b/sql/updates/5651_characters_guild_bank_tab.sql new file mode 100644 index 00000000000..88e5717e90e --- /dev/null +++ b/sql/updates/5651_characters_guild_bank_tab.sql @@ -0,0 +1 @@ +alter table guild_bank_tab add column TabText varchar(100) NOT NULL default '' COLLATE utf8_general_ci after TabIcon; diff --git a/sql/updates/5651_mangos_creature_template.sql b/sql/updates/5651_mangos_creature_template.sql new file mode 100644 index 00000000000..1e59274daf1 --- /dev/null +++ b/sql/updates/5651_mangos_creature_template.sql @@ -0,0 +1,2 @@ +update creature_template set speed=1 where speed=0; +alter table `creature_template` change `speed` `speed` float DEFAULT '1' NULL; diff --git a/sql/updates/5655_mangos_spell_affect.sql b/sql/updates/5655_mangos_spell_affect.sql new file mode 100644 index 00000000000..c9b4bd6ae3a --- /dev/null +++ b/sql/updates/5655_mangos_spell_affect.sql @@ -0,0 +1,39 @@ +-- (46090) Brutal Idol of Steadfastness () +DELETE FROM `spell_affect` WHERE `entry` IN (46090); +INSERT INTO `spell_affect` VALUES (46090, 0, 0, 0x0000000000000002, 0); + +-- (46100) Brutal Idol of Tenacity () +DELETE FROM `spell_affect` WHERE `entry` IN (46100); +INSERT INTO `spell_affect` VALUES (46100, 0, 0, 0x0000001000000000, 0); + +-- (46088) Brutall Idol of Resolve () +DELETE FROM `spell_affect` WHERE `entry` IN (46088); +INSERT INTO `spell_affect` VALUES (46088, 0, 0, 0x0000044000000000, 0); + +-- (46091) Brutal Libram of Fortitude () +DELETE FROM `spell_affect` WHERE `entry` IN (46091); +INSERT INTO `spell_affect` VALUES (46091, 0, 0, 0x0000000000800000, 0); + +-- (46095) Brutal Libram of Vengeance () +DELETE FROM `spell_affect` WHERE `entry` IN (46095); +INSERT INTO `spell_affect` VALUES (46095, 0, 0, 0x0000004000000000, 0); + +-- (46851) Holy Shock Bonus () +DELETE FROM `spell_affect` WHERE `entry` IN (46851); +INSERT INTO `spell_affect` VALUES (46851, 0, 0, 0x0001000000000000, 0); + +-- (46096) Brutal Totem of Indomitability () +DELETE FROM `spell_affect` WHERE `entry` IN (46096); +INSERT INTO `spell_affect` VALUES (46096, 0, 0, 0x0000001000000000, 0); + +-- (46097) Brutal Totem of Survival () +DELETE FROM `spell_affect` WHERE `entry` IN (46097); +INSERT INTO `spell_affect` VALUES (46097, 0, 0, 0x0000000090100000, 0); + +-- By triggers +DELETE FROM `spell_affect` WHERE `entry` IN (31569); +DELETE FROM `spell_affect` WHERE `entry` IN (31570); +-- By dummy +DELETE FROM `spell_affect` WHERE `entry` IN (28830); +DELETE FROM `spell_affect` WHERE `entry` IN (33695); +DELETE FROM `spell_affect` WHERE `entry` IN (37182); \ No newline at end of file diff --git a/sql/updates/5655_mangos_spell_chain.sql b/sql/updates/5655_mangos_spell_chain.sql new file mode 100644 index 00000000000..dfce10236aa --- /dev/null +++ b/sql/updates/5655_mangos_spell_chain.sql @@ -0,0 +1 @@ +DELETE FROM `spell_chain` WHERE `spell_id` IN (6461,6463,19289,19291,19292,19293,25450); \ No newline at end of file diff --git a/sql/updates/5655_mangos_spell_proc_event.sql b/sql/updates/5655_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..daac6ec5f1e --- /dev/null +++ b/sql/updates/5655_mangos_spell_proc_event.sql @@ -0,0 +1 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (1328,2689,4387,4388,4389,4390,4494,4495,4496,5341,5342,5343,5344,5345,5346,5349,5350,5351,5352,5353,5354,5429,5430,5431,5432,5433,5513,5549,5550,5551,5552,5553,5554,5638,5639,5640,5641,5642,5643,5751,5752,5753,5754,5755,5756,5976,5977,5979,13483); \ No newline at end of file diff --git a/sql/updates/5659_mangos_loot_template.sql b/sql/updates/5659_mangos_loot_template.sql new file mode 100644 index 00000000000..a52e182ea4b --- /dev/null +++ b/sql/updates/5659_mangos_loot_template.sql @@ -0,0 +1,23 @@ +ALTER TABLE `creature_loot_template` + CHANGE `group` groupid tinyint unsigned NOT NULL default '0'; + +ALTER TABLE `disenchant_loot_template` + CHANGE `group` groupid tinyint unsigned NOT NULL default '0'; + +ALTER TABLE `fishing_loot_template` + CHANGE `group` groupid tinyint unsigned NOT NULL default '0'; + +ALTER TABLE `gameobject_loot_template` + CHANGE `group` groupid tinyint unsigned NOT NULL default '0'; + +ALTER TABLE `item_loot_template` + CHANGE `group` groupid tinyint unsigned NOT NULL default '0'; + +ALTER TABLE `pickpocketing_loot_template` + CHANGE `group` groupid tinyint unsigned NOT NULL default '0'; + +ALTER TABLE `prospecting_loot_template` + CHANGE `group` groupid tinyint unsigned NOT NULL default '0'; + +ALTER TABLE `skinning_loot_template` + CHANGE `group` groupid tinyint unsigned NOT NULL default '0'; diff --git a/sql/updates/5660_mangos_spell_elixir.sql b/sql/updates/5660_mangos_spell_elixir.sql new file mode 100644 index 00000000000..aaa433a643f --- /dev/null +++ b/sql/updates/5660_mangos_spell_elixir.sql @@ -0,0 +1,4 @@ +DELETE FROM `spell_elixir` WHERE `entry` IN (46837,46839); +INSERT INTO `spell_elixir` VALUES +(46837,0xB), +(46839,0xB); diff --git a/sql/updates/5664_mangos.sql b/sql/updates/5664_mangos.sql new file mode 100644 index 00000000000..3f49b913a8c --- /dev/null +++ b/sql/updates/5664_mangos.sql @@ -0,0 +1,6 @@ +ALTER TABLE npc_vendor + ADD ExtendedCost mediumint(8) unsigned NOT NULL default '0'; +UPDATE npc_vendor,item_template SET npc_vendor.ExtendedCost = item_template.ExtendedCost WHERE npc_vendor.item = item_template.entry; +ALTER TABLE item_template + DROP ExtendedCost, + DROP CondExtendedCost; \ No newline at end of file diff --git a/sql/updates/5665_mangos_creature_template.sql b/sql/updates/5665_mangos_creature_template.sql new file mode 100644 index 00000000000..4a6fe057d08 --- /dev/null +++ b/sql/updates/5665_mangos_creature_template.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `scale` ='1'; \ No newline at end of file diff --git a/sql/updates/5679_mangos_creature_template.sql b/sql/updates/5679_mangos_creature_template.sql new file mode 100644 index 00000000000..7e2a3f3417b --- /dev/null +++ b/sql/updates/5679_mangos_creature_template.sql @@ -0,0 +1,9 @@ +ALTER TABLE creature_template + CHANGE resistance1 resistance1 smallint(5) NOT NULL default '0', + CHANGE resistance2 resistance2 smallint(5) NOT NULL default '0', + CHANGE resistance3 resistance3 smallint(5) NOT NULL default '0', + CHANGE resistance4 resistance4 smallint(5) NOT NULL default '0', + CHANGE resistance5 resistance5 smallint(5) NOT NULL default '0', + CHANGE resistance6 resistance6 smallint(5) NOT NULL default '0'; + + diff --git a/sql/updates/5680_mangos_spell_proc_event.sql b/sql/updates/5680_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..33f9c7cbda9 --- /dev/null +++ b/sql/updates/5680_mangos_spell_proc_event.sql @@ -0,0 +1,4 @@ +DELETE FROM spell_proc_event WHERE entry IN (37306,37311,32767); +INSERT IGNORE INTO spell_proc_event VALUES +(37306,0,0,0,0,0x0000000000000000,0x00000001,0), +(37311,0,0,0,0,0x0000000000000000,0x00000001,0); diff --git a/sql/updates/5698_mangos_item_template.sql b/sql/updates/5698_mangos_item_template.sql new file mode 100644 index 00000000000..41cbe8b670e --- /dev/null +++ b/sql/updates/5698_mangos_item_template.sql @@ -0,0 +1,2 @@ +ALTER TABLE item_template + CHANGE COLUMN stackable stackable smallint(5) unsigned NOT NULL default '1'; diff --git a/sql/updates/5708_mangos_player_levelstats.sql b/sql/updates/5708_mangos_player_levelstats.sql new file mode 100644 index 00000000000..a216ffca476 --- /dev/null +++ b/sql/updates/5708_mangos_player_levelstats.sql @@ -0,0 +1,70 @@ +UPDATE `player_levelstats` SET `basehp` = 23, `basemana` = 90 WHERE `class` = 9 AND `level`=1; +UPDATE `player_levelstats` SET `basehp` = 28, `basemana` = 98 WHERE `class` = 9 AND `level`=2; +UPDATE `player_levelstats` SET `basehp` = 43, `basemana` = 107 WHERE `class` = 9 AND `level`=3; +UPDATE `player_levelstats` SET `basehp` = 48, `basemana` = 102 WHERE `class` = 9 AND `level`=4; +UPDATE `player_levelstats` SET `basehp` = 63, `basemana` = 113 WHERE `class` = 9 AND `level`=5; +UPDATE `player_levelstats` SET `basehp` = 68, `basemana` = 126 WHERE `class` = 9 AND `level`=6; +UPDATE `player_levelstats` SET `basehp` = 83, `basemana` = 144 WHERE `class` = 9 AND `level`=7; +UPDATE `player_levelstats` SET `basehp` = 88, `basemana` = 162 WHERE `class` = 9 AND `level`=8; +UPDATE `player_levelstats` SET `basehp` = 93, `basemana` = 180 WHERE `class` = 9 AND `level`=9; +UPDATE `player_levelstats` SET `basehp` = 108, `basemana` = 198 WHERE `class` = 9 AND `level`=10; +UPDATE `player_levelstats` SET `basehp` = 123, `basemana` = 200 WHERE `class` = 9 AND `level`=11; +UPDATE `player_levelstats` SET `basehp` = 128, `basemana` = 218 WHERE `class` = 9 AND `level`=12; +UPDATE `player_levelstats` SET `basehp` = 143, `basemana` = 237 WHERE `class` = 9 AND `level`=13; +UPDATE `player_levelstats` SET `basehp` = 148, `basemana` = 257 WHERE `class` = 9 AND `level`=14; +UPDATE `player_levelstats` SET `basehp` = 153, `basemana` = 278 WHERE `class` = 9 AND `level`=15; +UPDATE `player_levelstats` SET `basehp` = 168, `basemana` = 300 WHERE `class` = 9 AND `level`=16; +UPDATE `player_levelstats` SET `basehp` = 173, `basemana` = 308 WHERE `class` = 9 AND `level`=17; +UPDATE `player_levelstats` SET `basehp` = 189, `basemana` = 332 WHERE `class` = 9 AND `level`=18; +UPDATE `player_levelstats` SET `basehp` = 196, `basemana` = 357 WHERE `class` = 9 AND `level`=19; +UPDATE `player_levelstats` SET `basehp` = 204, `basemana` = 383 WHERE `class` = 9 AND `level`=20; +UPDATE `player_levelstats` SET `basehp` = 223, `basemana` = 395 WHERE `class` = 9 AND `level`=21; +UPDATE `player_levelstats` SET `basehp` = 233, `basemana` = 423 WHERE `class` = 9 AND `level`=22; +UPDATE `player_levelstats` SET `basehp` = 244, `basemana` = 452 WHERE `class` = 9 AND `level`=23; +UPDATE `player_levelstats` SET `basehp` = 266, `basemana` = 467 WHERE `class` = 9 AND `level`=24; +UPDATE `player_levelstats` SET `basehp` = 279, `basemana` = 498 WHERE `class` = 9 AND `level`=25; +UPDATE `player_levelstats` SET `basehp` = 293, `basemana` = 530 WHERE `class` = 9 AND `level`=26; +UPDATE `player_levelstats` SET `basehp` = 318, `basemana` = 548 WHERE `class` = 9 AND `level`=27; +UPDATE `player_levelstats` SET `basehp` = 334, `basemana` = 582 WHERE `class` = 9 AND `level`=28; +UPDATE `player_levelstats` SET `basehp` = 351, `basemana` = 602 WHERE `class` = 9 AND `level`=29; +UPDATE `player_levelstats` SET `basehp` = 379, `basemana` = 638 WHERE `class` = 9 AND `level`=30; +UPDATE `player_levelstats` SET `basehp` = 398, `basemana` = 674 WHERE `class` = 9 AND `level`=31; +UPDATE `player_levelstats` SET `basehp` = 418, `basemana` = 695 WHERE `class` = 9 AND `level`=32; +UPDATE `player_levelstats` SET `basehp` = 439, `basemana` = 731 WHERE `class` = 9 AND `level`=33; +UPDATE `player_levelstats` SET `basehp` = 471, `basemana` = 752 WHERE `class` = 9 AND `level`=34; +UPDATE `player_levelstats` SET `basehp` = 494, `basemana` = 788 WHERE `class` = 9 AND `level`=35; +UPDATE `player_levelstats` SET `basehp` = 518, `basemana` = 809 WHERE `class` = 9 AND `level`=36; +UPDATE `player_levelstats` SET `basehp` = 543, `basemana` = 830 WHERE `class` = 9 AND `level`=37; +UPDATE `player_levelstats` SET `basehp` = 569, `basemana` = 866 WHERE `class` = 9 AND `level`=38; +UPDATE `player_levelstats` SET `basehp` = 606, `basemana` = 887 WHERE `class` = 9 AND `level`=39; +UPDATE `player_levelstats` SET `basehp` = 634, `basemana` = 923 WHERE `class` = 9 AND `level`=40; +UPDATE `player_levelstats` SET `basehp` = 663, `basemana` = 944 WHERE `class` = 9 AND `level`=41; +UPDATE `player_levelstats` SET `basehp` = 693, `basemana` = 965 WHERE `class` = 9 AND `level`=42; +UPDATE `player_levelstats` SET `basehp` = 724, `basemana` = 1001 WHERE `class` = 9 AND `level`=43; +UPDATE `player_levelstats` SET `basehp` = 756, `basemana` = 1022 WHERE `class` = 9 AND `level`=44; +UPDATE `player_levelstats` SET `basehp` = 799, `basemana` = 1043 WHERE `class` = 9 AND `level`=45; +UPDATE `player_levelstats` SET `basehp` = 832, `basemana` = 1064 WHERE `class` = 9 AND `level`=46; +UPDATE `player_levelstats` SET `basehp` = 868, `basemana` = 1100 WHERE `class` = 9 AND `level`=47; +UPDATE `player_levelstats` SET `basehp` = 904, `basemana` = 1121 WHERE `class` = 9 AND `level`=48; +UPDATE `player_levelstats` SET `basehp` = 941, `basemana` = 1142 WHERE `class` = 9 AND `level`=49; +UPDATE `player_levelstats` SET `basehp` = 979, `basemana` = 1163 WHERE `class` = 9 AND `level`=50; +UPDATE `player_levelstats` SET `basehp` = 1018, `basemana` = 1184 WHERE `class` = 9 AND `level`=51; +UPDATE `player_levelstats` SET `basehp` = 1058, `basemana` = 1205 WHERE `class` = 9 AND `level`=52; +UPDATE `player_levelstats` SET `basehp` = 1099, `basemana` = 1226 WHERE `class` = 9 AND `level`=53; +UPDATE `player_levelstats` SET `basehp` = 1141, `basemana` = 1247 WHERE `class` = 9 AND `level`=54; +UPDATE `player_levelstats` SET `basehp` = 1184, `basemana` = 1268 WHERE `class` = 9 AND `level`=55; +UPDATE `player_levelstats` SET `basehp` = 1228, `basemana` = 1289 WHERE `class` = 9 AND `level`=56; +UPDATE `player_levelstats` SET `basehp` = 1273, `basemana` = 1310 WHERE `class` = 9 AND `level`=57; +UPDATE `player_levelstats` SET `basehp` = 1319, `basemana` = 1331 WHERE `class` = 9 AND `level`=58; +UPDATE `player_levelstats` SET `basehp` = 1366, `basemana` = 1352 WHERE `class` = 9 AND `level`=59; +UPDATE `player_levelstats` SET `basehp` = 1414, `basemana` = 1373 WHERE `class` = 9 AND `level`=60; +UPDATE `player_levelstats` SET `basehp` = 1580, `basemana` = 1497 WHERE `class` = 9 AND `level`=61; +UPDATE `player_levelstats` SET `basehp` = 1755, `basemana` = 1621 WHERE `class` = 9 AND `level`=62; +UPDATE `player_levelstats` SET `basehp` = 1939, `basemana` = 1745 WHERE `class` = 9 AND `level`=63; +UPDATE `player_levelstats` SET `basehp` = 2133, `basemana` = 1870 WHERE `class` = 9 AND `level`=64; +UPDATE `player_levelstats` SET `basehp` = 2323, `basemana` = 1994 WHERE `class` = 9 AND `level`=65; +UPDATE `player_levelstats` SET `basehp` = 2535, `basemana` = 2118 WHERE `class` = 9 AND `level`=66; +UPDATE `player_levelstats` SET `basehp` = 2758, `basemana` = 2242 WHERE `class` = 9 AND `level`=67; +UPDATE `player_levelstats` SET `basehp` = 2991, `basemana` = 2366 WHERE `class` = 9 AND `level`=68; +UPDATE `player_levelstats` SET `basehp` = 3235, `basemana` = 2490 WHERE `class` = 9 AND `level`=69; +UPDATE `player_levelstats` SET `basehp` = 3490, `basemana` = 2615 WHERE `class` = 9 AND `level`=70; diff --git a/sql/updates/5711_characters_character_kill.sql b/sql/updates/5711_characters_character_kill.sql new file mode 100644 index 00000000000..0935ac421bc --- /dev/null +++ b/sql/updates/5711_characters_character_kill.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS `character_kill`; \ No newline at end of file diff --git a/sql/updates/5711_mangos_command.sql b/sql/updates/5711_mangos_command.sql new file mode 100644 index 00000000000..3310c22c3e1 --- /dev/null +++ b/sql/updates/5711_mangos_command.sql @@ -0,0 +1,5 @@ +DELETE FROM `command` WHERE `name` = "honor flushkills"; + +DELETE FROM `command` WHERE `name` = "honor"; +INSERT INTO `command` VALUES +("honor", 2, "Syntax: .honor $command [$value] Various honor related commands. Use .help honor $command to get help on specific parameter usage. Supported parameters include add, addkill, update"); \ No newline at end of file diff --git a/sql/updates/5714_mangos_command.sql b/sql/updates/5714_mangos_command.sql new file mode 100644 index 00000000000..2c6aba79eb9 --- /dev/null +++ b/sql/updates/5714_mangos_command.sql @@ -0,0 +1,3 @@ +DELETE FROM `command` WHERE `name` = "nearobjects"; +INSERT INTO `command` VALUES +('nearobjects',3,'Syntax: .nearobjects [#distance]\r\n\r\nOutput gameobjects at distance #distance from player. Output gameobject guids and coordinates sorted by distance from character. If #distance not provided use 10 as default value.'); diff --git a/sql/updates/5714_mangos_mangos_string.sql b/sql/updates/5714_mangos_mangos_string.sql new file mode 100644 index 00000000000..47ad4e3acd7 --- /dev/null +++ b/sql/updates/5714_mangos_mangos_string.sql @@ -0,0 +1,4 @@ +DELETE FROM mangos_string WHERE entry in (524,581); +INSERT INTO mangos_string VALUES +(524,'Selected object:\n|cffffffff|Hitemset:%d|h[%s]|h|r\nGUID: %u ID: %u\nX: %f Y: %f Z: %f MapId: %u\nOrientation: %f',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(581,'Found near gameobjects (distance %f): %u ',NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/5718_mangos_command.sql b/sql/updates/5718_mangos_command.sql new file mode 100644 index 00000000000..b2c0ae16e62 --- /dev/null +++ b/sql/updates/5718_mangos_command.sql @@ -0,0 +1,8 @@ +DELETE FROM `command` WHERE `name` = 'modify rep'; +DELETE FROM `command` WHERE `name` = 'modify arena'; +DELETE FROM `command` WHERE `name` = 'lookup faction'; + +INSERT INTO `command` VALUES +('modify rep',2,'Syntax: .modify rep #repId (#repvalue | $rankname [#delta])\r\nSets the selected player\s reputation with faction #repId to #repvalue or to $reprank.\r\nIf the reputation rank name is provided, the resulting reputation will be the lowest reputation for that rank plus the delta amount, if specified.\r\nYou can use \'.pinfo rep\' to list all known reputation ids, or use \'.lookup faction $name\' to locate a specific faction id.'), +('modify arena',3,'Syntax: .modify arena #value\r\nSets the arena points to the #value (0-999999).'), +('lookup faction','3','Syntax: .lookup faction $name\r\nAttempts to find the ID of the faction with the provided $name.'); diff --git a/sql/updates/5718_mangos_creature_template.sql b/sql/updates/5718_mangos_creature_template.sql new file mode 100644 index 00000000000..55eb1f40009 --- /dev/null +++ b/sql/updates/5718_mangos_creature_template.sql @@ -0,0 +1 @@ +ALTER TABLE `creature_template` CHANGE COLUMN `scale` `scale` float NOT NULL default '1'; diff --git a/sql/updates/5718_mangos_mangos_string.sql b/sql/updates/5718_mangos_mangos_string.sql new file mode 100644 index 00000000000..e371c3984bc --- /dev/null +++ b/sql/updates/5718_mangos_mangos_string.sql @@ -0,0 +1,26 @@ +DELETE FROM `mangos_string` WHERE `entry` IN (305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327); + +INSERT INTO `mangos_string` VALUES +(305, 'Faction %s (%u) reputation of %s was set to %5d!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(306, 'The arena points of %s was set to %u!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(307, 'No faction found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(308, 'Faction %i unknown!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(309, 'Invalid parameter %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(310, 'delta must be between 0 and %d (inclusive)',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(311, '%d - |cffffffff|Hfaction:%d|h[%s]|h|r',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(312, ' [visible]',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(313, ' [at war]',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(314, ' [own team]',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(315, ' [unknown]',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(316, ' [invisible]',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(317, ' [inactive]',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(318, 'Hated',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(319, 'Hostile',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(320, 'Unfriendly',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(321, 'Neutral',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(322, 'Friendly',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(323, 'Honored',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(324, 'Revered',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(325, 'Exalted',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(326, 'Faction %s (%u) can\'not have reputation.',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(327, ' [no reputation]',NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/5720_mangos_command.sql b/sql/updates/5720_mangos_command.sql new file mode 100644 index 00000000000..cbc153deb60 --- /dev/null +++ b/sql/updates/5720_mangos_command.sql @@ -0,0 +1,3 @@ +DELETE FROM `command` WHERE `name` = 'addvendoritem'; +INSERT INTO `command` VALUES +('addvendoritem',2,'Syntax: .addvendoritem #itemId <#maxcount><#incrtime><#extendedcost>r\n\r\nAdd item #itemid to item list of selected vendor. Also optionally set max count item in vendor item list and time to item count restoring and items ExtendedCost.'); diff --git a/sql/updates/5720_mangos_mangos_string.sql b/sql/updates/5720_mangos_mangos_string.sql new file mode 100644 index 00000000000..4092ffe4acf --- /dev/null +++ b/sql/updates/5720_mangos_mangos_string.sql @@ -0,0 +1,3 @@ +DELETE FROM mangos_string WHERE entry in (206); +INSERT INTO mangos_string VALUES +(206,'Item \'%i\' \'%s\' added to list with maxcount \'%i\' and incrtime \'%i\' and extendedcost \'%i\'',NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/5721_mangos_spell_affect.sql b/sql/updates/5721_mangos_spell_affect.sql new file mode 100644 index 00000000000..2fdd57d717c --- /dev/null +++ b/sql/updates/5721_mangos_spell_affect.sql @@ -0,0 +1,24 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (16188); +INSERT INTO `spell_affect` VALUES + (16188,0,0,0x00000000000009C3,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (43743); +INSERT INTO `spell_affect` VALUES + (43743,1,0,0x0000000000000400,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (13733,13865,13866); +INSERT INTO `spell_affect` VALUES + (13733,0,0,0x0000000000000004,0), + (13733,1,0,0x0000000400000000,0), + (13865,0,0,0x0000000000000004,0), + (13865,1,0,0x0000000400000000,0), + (13866,0,0,0x0000000000000004,0), + (13866,1,0,0x0000000400000000,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (46834); +INSERT INTO `spell_affect` VALUES + (46834,0,0,0x0000000000000040,0); + +DELETE FROM `spell_affect` WHERE `entry` IN (46833); +INSERT INTO `spell_affect` VALUES + (46833,0,0,0x0000000000000004,0); diff --git a/sql/updates/5733_mangos_creature.sql b/sql/updates/5733_mangos_creature.sql new file mode 100644 index 00000000000..e9947232fdc --- /dev/null +++ b/sql/updates/5733_mangos_creature.sql @@ -0,0 +1,5 @@ +ALTER TABLE `creature` + DROP `spawn_position_x`, + DROP `spawn_position_y`, + DROP `spawn_position_z`, + DROP `spawn_orientation`; diff --git a/sql/updates/5739_mangos_creature.sql b/sql/updates/5739_mangos_creature.sql new file mode 100644 index 00000000000..b48c80cc078 --- /dev/null +++ b/sql/updates/5739_mangos_creature.sql @@ -0,0 +1 @@ +ALTER TABLE `creature` ADD COLUMN `spawnMask` tinyint(3) unsigned NOT NULL default '1' AFTER `map`; \ No newline at end of file diff --git a/sql/updates/5739_mangos_gameobject.sql b/sql/updates/5739_mangos_gameobject.sql new file mode 100644 index 00000000000..e566cbcd623 --- /dev/null +++ b/sql/updates/5739_mangos_gameobject.sql @@ -0,0 +1 @@ +ALTER TABLE `gameobject` ADD COLUMN `spawnMask` tinyint(3) unsigned NOT NULL default '1' AFTER `map`; \ No newline at end of file diff --git a/sql/updates/5746_mangos_quest_template.sql b/sql/updates/5746_mangos_quest_template.sql new file mode 100644 index 00000000000..d62acfd9e73 --- /dev/null +++ b/sql/updates/5746_mangos_quest_template.sql @@ -0,0 +1,3 @@ +ALTER TABLE `quest_template` ADD COLUMN `CharTitleId` tinyint(3) unsigned NOT NULL default '0' AFTER `SpecialFlags`; +ALTER TABLE `quest_template` ADD COLUMN `RewSpellCast` mediumint(8) unsigned NOT NULL default '0' AFTER `RewSpell`; + diff --git a/sql/updates/5753_mangos_areatrigger_teleport.sql b/sql/updates/5753_mangos_areatrigger_teleport.sql new file mode 100644 index 00000000000..336077fb2fc --- /dev/null +++ b/sql/updates/5753_mangos_areatrigger_teleport.sql @@ -0,0 +1,6 @@ +ALTER TABLE `areatrigger_teleport` + ADD COLUMN `required_item2` mediumint(8) unsigned NOT NULL default '0' AFTER `required_item`, + ADD COLUMN `heroic_key` mediumint(8) unsigned NOT NULL default '0' AFTER `required_item2`, + ADD COLUMN `heroic_key2` mediumint(8) unsigned NOT NULL default '0' AFTER `heroic_key`, + ADD COLUMN `required_quest_done` int(11) unsigned NOT NULL default '0' AFTER `heroic_key2`, + ADD COLUMN `required_failed_text` text AFTER `required_quest_done`; \ No newline at end of file diff --git a/sql/updates/5758_mangos_creature_addon.sql b/sql/updates/5758_mangos_creature_addon.sql new file mode 100644 index 00000000000..01887760009 --- /dev/null +++ b/sql/updates/5758_mangos_creature_addon.sql @@ -0,0 +1,2 @@ +ALTER TABLE `creature_addon` ADD `moveflags` int(10) unsigned NOT NULL default '0' AFTER `emote`; +ALTER TABLE `creature_template_addon` ADD `moveflags` int(10) unsigned NOT NULL default '0' AFTER `emote`; \ No newline at end of file diff --git a/sql/updates/5759_mangos_command.sql b/sql/updates/5759_mangos_command.sql new file mode 100644 index 00000000000..14aa7c58cac --- /dev/null +++ b/sql/updates/5759_mangos_command.sql @@ -0,0 +1,4 @@ +DELETE FROM `command` WHERE `name` IN ('gograveyard','drunk'); +INSERT INTO `command` VALUES +('drunk',1,'Syntax: .drunk #value\r\n Set drunk level to #value (0..100). Value 0 remove drunk state, 100 is max drunked state.'), +('gograveyard',2,'Syntax: .gograveyard #graveyardId\r\n Teleport to graveyard with the graveyardId specified.'); diff --git a/sql/updates/5764_characters_characters.sql b/sql/updates/5764_characters_characters.sql new file mode 100644 index 00000000000..bc9ce105746 --- /dev/null +++ b/sql/updates/5764_characters_characters.sql @@ -0,0 +1,2 @@ +ALTER TABLE `characters` + DROP `pending_honor`; diff --git a/sql/updates/5764_mangos_command.sql b/sql/updates/5764_mangos_command.sql new file mode 100644 index 00000000000..d2086179014 --- /dev/null +++ b/sql/updates/5764_mangos_command.sql @@ -0,0 +1,4 @@ +DELETE FROM `command` WHERE `name` IN ('modify arena','modify honor'); +INSERT INTO `command` VALUES +('modify arena',3,'Syntax: .modify arena #value\r\nAdd $amount arena points to the selected player.'), +('modify honor',1,'Syntax: .modify honor $amount\r\n\r\nAdd $amount honor points to the selected player.'); diff --git a/sql/updates/5771_mangos_spell_learn_spell.sql b/sql/updates/5771_mangos_spell_learn_spell.sql new file mode 100644 index 00000000000..813c71f14a1 --- /dev/null +++ b/sql/updates/5771_mangos_spell_learn_spell.sql @@ -0,0 +1,9 @@ +ALTER TABLE spell_learn_spell + DROP IfNoSpell; + +DELETE FROM spell_learn_spell WHERE entry IN (34769,13819,5784); + +INSERT INTO spell_learn_spell (entry,spellID) VALUES + (34769,33388), + (13819,33388), + (5784,33388); diff --git a/sql/updates/5772_mangos_command.sql b/sql/updates/5772_mangos_command.sql new file mode 100644 index 00000000000..7e4c01b29a0 --- /dev/null +++ b/sql/updates/5772_mangos_command.sql @@ -0,0 +1,118 @@ +DELETE FROM `command` WHERE `name` = 'addgo'; +DELETE FROM `command` WHERE `name` = 'addquest'; +DELETE FROM `command` WHERE `name` = 'addspw'; +DELETE FROM `command` WHERE `name` = 'addtele'; +DELETE FROM `command` WHERE `name` = 'addvendoritem'; +DELETE FROM `command` WHERE `name` = 'addweapon'; +DELETE FROM `command` WHERE `name` = 'allowmove'; +DELETE FROM `command` WHERE `name` = 'anim'; +DELETE FROM `command` WHERE `name` = 'money'; +DELETE FROM `command` WHERE `name` = 'morph'; +DELETE FROM `command` WHERE `name` = 'movecreature'; +DELETE FROM `command` WHERE `name` = 'moveobject'; +DELETE FROM `command` WHERE `name` = 'name'; +DELETE FROM `command` WHERE `name` = 'nametele'; +DELETE FROM `command` WHERE `name` = 'nearobjects'; +DELETE FROM `command` WHERE `name` = 'npcflag'; +DELETE FROM `command` WHERE `name` = 'npcinfo'; +DELETE FROM `command` WHERE `name` = 'npcinfoset'; +DELETE FROM `command` WHERE `name` = 'npcwhisper'; +DELETE FROM `command` WHERE `name` = 'castback'; +DELETE FROM `command` WHERE `name` = 'casttarget'; +DELETE FROM `command` WHERE `name` = 'changelevel'; +DELETE FROM `command` WHERE `name` = 'delete'; +DELETE FROM `command` WHERE `name` = 'delobject'; +DELETE FROM `command` WHERE `name` = 'deltele'; +DELETE FROM `command` WHERE `name` = 'delvendoritem'; +DELETE FROM `command` WHERE `name` = 'drunk'; +DELETE FROM `command` WHERE `name` = 'factionid'; +DELETE FROM `command` WHERE `name` = 'getvalue'; +DELETE FROM `command` WHERE `name` = 'gocreature'; +DELETE FROM `command` WHERE `name` = 'gograveyard'; +DELETE FROM `command` WHERE `name` = 'gogrid'; +DELETE FROM `command` WHERE `name` = 'goobject'; +DELETE FROM `command` WHERE `name` = 'gotrigger'; +DELETE FROM `command` WHERE `name` = 'goxy'; +DELETE FROM `command` WHERE `name` = 'goxyz'; +DELETE FROM `command` WHERE `name` = 'gozonexy'; +DELETE FROM `command` WHERE `name` = 'grouptele'; +DELETE FROM `command` WHERE `name` = 'listcreature'; +DELETE FROM `command` WHERE `name` = 'listgm'; +DELETE FROM `command` WHERE `name` = 'listitem'; +DELETE FROM `command` WHERE `name` = 'listobject'; +DELETE FROM `command` WHERE `name` = 'playemote'; +DELETE FROM `command` WHERE `name` = 'playsound'; +DELETE FROM `command` WHERE `name` = 'removequest'; +DELETE FROM `command` WHERE `name` = 'resetall'; +DELETE FROM `command` WHERE `name` = 'setmodel'; +DELETE FROM `command` WHERE `name` = 'setmovetype'; +DELETE FROM `command` WHERE `name` = 'setvalue'; +DELETE FROM `command` WHERE `name` = 'spawndist'; +DELETE FROM `command` WHERE `name` = 'spawntime'; +DELETE FROM `command` WHERE `name` = 'speed'; +DELETE FROM `command` WHERE `name` = 'standstate'; +DELETE FROM `command` WHERE `name` = 'subname'; +DELETE FROM `command` WHERE `name` = 'targetobject'; +DELETE FROM `command` WHERE `name` = 'textemote'; +DELETE FROM `command` WHERE `name` = 'titles'; +DELETE FROM `command` WHERE `name` = 'turnobject'; +DELETE FROM `command` WHERE `name` = 'update'; +DELETE FROM `command` WHERE `name` = 'visible'; + +INSERT INTO `command` (`name`,`security`,`help`) VALUES +('cast back',3,'Syntax: .cast back #spellid\r\n Selected target will cast #spellid to your character.'), +('cast target',3,'Syntax: .cast target #spellid\r\n Selected target will cast #spellid to his victim.'), +('debug anim',2,'Syntax: .debug anim #emoteid\r\n\r\nPlay emote #emoteid for your character.'), +('debug getvalue',3,'Syntax: .debug getvalue #field #isInt\r\n\r\nGet the field #field of the selected creature. If no creature is selected, get the content of your field.\r\n\r\nUse a #isInt of value 1 if the expected field content is an integer.'), +('debug playsound',1,'Syntax: .debug playsound #soundid\r\n\r\nPlay sound with #soundid.\r\nSound will be play only for you. Other players do not hear this.\r\nWarning: client may have more 5000 sounds...'), +('debug setvalue',3,'Syntax: .debug setvalue #field #value #isInt\r\n\r\nSet the field #field of the selected creature with value #value. If no creature is selected, set the content of your field.\r\n\r\nUse a #isInt of value 1 if #value is an integer.'), +('debug standstate',2,'Syntax: .debug standstate #emoteid\r\n\r\nChange the emote of your character while standing to #emoteid.'), +('debug update',3,'Syntax: .debug update #field #value\r\n\r\nUpdate the field #field of the selected character or creature with value #value.\r\n\r\nIf no #value is provided, display the content of field #field.'), +('gm list',0,'Syntax: .gm list\r\n\r\nDisplay a list of available Game Masters.'), +('gm visible',1,'Syntax: .gm visible on/off\r\n\r\nOutput current visibility state or make GM visible(on) and invisible(off) for other players.'), +('go creature',2,'Syntax: .go creature #creature_guid\r\nTeleport your character to creature with guid #creature_guid.\r\n.gocreature #creature_name\r\nTeleport your character to creature with this name.\r\n.gocreature id #creature_id\r\nTeleport your character to a creature that was spawned from the template with this entry.\r\n*If* more than one creature is found, then you are teleported to the first that is found inside the database.'), +('go graveyard',2,'Syntax: .go graveyard #graveyardId\r\n Teleport to graveyard with the graveyardId specified.'), +('go grid',1,'Syntax: .go grid #gridX #gridY [#mapId]\r\n\r\nTeleport the gm to center of grid with provided indexes at map #mapId (or current map if it not provided).'), +('go object',1,'Syntax: .go object #object_guid\r\nTeleport your character to gameobject with guid #object_guid'), +('go trigger',2,'Syntax: .go trigger #trigger_id\r\n\r\nTeleport your character to areatrigger with id #trigger_id. Character will be teleported to trigger target if selected areatrigger is telporting trigger.'), +('go xy',1,'Syntax: .go xy #x #y [#mapid]\r\n\r\nTeleport player to point with (#x,#y) coordinates at ground(water) level at map #mapid or same map if #mapid not provided.'), +('go xyz',1,'Syntax: .go xyz #x #y #z [#mapid]\r\n\r\nTeleport player to point with (#x,#y,#z) coordinates at ground(water) level at map #mapid or same map if #mapid not provided.'), +('go zonexy',1,'Syntax: .go zonexy #x #y [#zone]\r\n\r\nTeleport player to point with (#x,#y) client coordinates at ground(water) level in zone #zoneid or current zone if #zoneid not provided. You can look up zone using .lookup area $namepart'), +('gobject add',2,'Syntax: .gobject add #id \r\n\r\nAdd a game object from game object templates to the world at your current location using the #id.\r\nspawntimesecs sets the spawntime, it is optional.\r\n\r\nNote: this is a copy of .gameobject.'), +('gobject delete',2,'Syntax: .gobject delete #go_guid\r\nDelete gameobject with guid #go_guid.'), +('gobject move',2,'Syntax: .gobject move #goguid [#x #y #z]\r\n\r\nMove gameobject #goguid to character coordinates (or to (#x,#y,#z) coordinates if its provide).'), +('gobject near ',3,'Syntax: .gobject near [#distance]\r\n\r\nOutput gameobjects at distance #distance from player. Output gameobject guids and coordinates sorted by distance from character. If #distance not provided use 10 as default value.'), +('gobject turn',2,'Syntax: .gobject turn #goguid \r\n\r\nSet for gameobject #goguid orientation same as current character orientation.'), +('list creature',3,'Syntax: .list creature #creature_id [#max_count]\r\n\r\nOutput creatures with creature id #creature_id found in world. Output creature guids and coordinates sorted by distance from character. Will be output maximum #max_count creatures. If #max_count not provided use 10 as default value.'), +('list item',3,'Syntax: .list item #item_id [#max_count]\r\n\r\nOutput items with item id #item_id found in all character inventories, mails and auctions. Output item guids, item owner guid, owner account and owner name. Will be output maximum #max_count items. If #max_count not provided use 10 as default value.'), +('list object',3,'Syntax: .list object #gameobject_id [#max_count]\r\n\r\nOutput gameobjects with gameobject id #gameobject_id found in world. Output gameobject guids and coordinates sorted by distance from character. Will be output maximum #max_count gameobject. If #max_count not provided use 10 as default value.'), +('modify drunk',1,'Syntax: .modify drunk #value\r\n Set drunk level to #value (0..100). Value 0 remove drunk state, 100 is max drunked state.'), +('modify morph',2,'Syntax: .modify morph #displayid\r\n\r\nChange your current model id to #displayid.'), +('npc add',2,'Syntax: .npc add #creatureid\r\n\r\nSpawn a creature by the given template id of #creatureid.'), +('npc additem',2,'Syntax: .npc additem #itemId <#maxcount><#incrtime><#extendedcost>r\r\n\r\nAdd item #itemid to item list of selected vendor. Also optionally set max count item in vendor item list and time to item count restoring and items ExtendedCost.'), +('npc addweapon',3,'Not yet implemented.'), +('npc allowmove',3,'Syntax: .npc allowmove\r\n\r\nEnable or disable movement for the selected creature.'), +('npc changelevel',2,'Syntax: .npc changelevel #level\r\n\r\nChange the level of the selected creature to #level.\r\n\r\n#level may range from 1 to 63.'), +('npc delete',2,'Syntax: .npc delete\r\n\r\nDelete the selected creature from the world.'), +('npc delitem',2,'Syntax: .npc delitem #itemId\r\n\r\nRemove item #itemid from item list of selected vendor.'), +('npc factionid',2,'Syntax: .npc factionid #factionid\r\n\r\nSet the faction of the selected creature to #factionid.'), +('npc flag',2,'Syntax: .npc flag #npcflag\r\n\r\nSet the NPC flags of creature template of the selected creature and selected creature to #npcflag. NPC flags will applied to all creatures of selected creature template after server restart or grid unload/load.'), +('npc info',3,'Syntax: .npc info\r\n\r\nDisplay a list of details for the selected creature.\r\n\r\nThe list includes:\r\n- GUID, Faction, NPC flags, Entry ID, Model ID,\r\n- Level,\r\n- Health (current/maximum),\r\n\r\n- Field flags, dynamic flags, faction template, \r\n- Position information,\r\n- and the creature type, e.g. if the creature is a vendor.'), +('npc move',2,'Syntax: .npc move [#creature_guid]\r\n\r\nMove the targeted creature spawn point to your coordinates.'), +('npc name',2,'Syntax: .npc name $name\r\n\r\nChange the name of the selected creature or character to $name.\r\n\r\nCommand disabled.'), +('npc playemote',3,'Syntax: .npc playemote #emoteid\r\n\r\nMake the selected creature emote with an emote of id #emoteid.'), +('npc setmodel',2,'Syntax: .npc setmodel #displayid\r\n\r\nChange the model id of the selected creature to #displayid.'), +('npc setmovetype',2,'Syntax: .npc setmovetype [#creature_guid] stay/random/way [NODEL]\r\n\r\nSet for creature pointed by #creature_guid (or selected if #creature_guid not provided) movement type and move it to respawn position (if creature alive). Any existing waypoints for creature will be removed from the database if you do not use NODEL. If the creature is dead then movement type will applied at creature respawn.\r\nMake sure you use NODEL, if you want to keep the waypoints.'), +('npc spawndist',2,'Syntax: .npc spawndist #dist\r\n\r\nAdjust spawndistance of selected creature to dist.'), +('npc spawntime',2,'Syntax: .npc spawntime #time \r\n\r\nAdjust spawntime of selected creature to time.'), +('npc subname',2,'Syntax: .npc subname $Name\r\n\r\nChange the subname of the selected creature or player to $Name.\r\n\r\nCommand disabled.'), +('npc textemote',3,'Syntax: .npc textemote #emoteid\r\n\r\nMake the selected creature to do textemote with an emote of id #emoteid.'), +('npc whisper',1,'Syntax: .npc whisper #playerguid #text\r\nMake the selected npc whisper #text to #playerguid.'), +('quest add',3,'Syntax: .quest add #quest_id\r\n\r\nAdd to character quest log quest #quest_id. Quest started from item can\'t be added by this command but correct .additem call provided in command output.'), +('quest remove',3,'Syntax: .quest remove #quest_id\r\n\r\nSet quest #quest_id state to not completed and not active (and remove from active quest list) for selected player.'), +('reset all',3,'Syntax: .reset all spells\r\n\r\nSyntax: .reset all talents\r\n\r\nRequest reset spells or talents at next login each existed character.'), +('targetobject',2,'Syntax: .gobject target[#go_id|#go_name_part]\r\n\r\nLocate and show position nearest gameobject. If #go_id or #go_name_part provide then locate and show position of nearest gameobject with gameobject template id #go_id or name included #go_name_part as part.'), +('tele add',3,'Syntax: .tele add $name\r\n\r\nAdd current your position to .tele command target locations list with name $name.'), +('tele del',3,'Syntax: .tele del $name\r\n\r\nRemove location with name $name for .tele command locations list.'), +('tele group',1,'Syntax: .tele group#location\r\n\r\nTeleport a selected player and his group members to a given location.'), +('tele name',1,'Syntax: .tele name #playername #location\r\n\r\nTeleport a player to a given location.'); \ No newline at end of file diff --git a/sql/updates/5773_mangos_spell_affect.sql b/sql/updates/5773_mangos_spell_affect.sql new file mode 100644 index 00000000000..954202438a3 --- /dev/null +++ b/sql/updates/5773_mangos_spell_affect.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (20216); +INSERT INTO `spell_affect` VALUES + (20216,0,0,0x0001000000006000,0); diff --git a/sql/updates/5773_mangos_spell_learn_spell.sql b/sql/updates/5773_mangos_spell_learn_spell.sql new file mode 100644 index 00000000000..507b1da95ad --- /dev/null +++ b/sql/updates/5773_mangos_spell_learn_spell.sql @@ -0,0 +1,6 @@ +DELETE FROM spell_learn_spell WHERE entry IN (23161,23214,34767); + +INSERT INTO spell_learn_spell (entry,spellID) VALUES +(23161,33391), +(23214,33391), +(34767,33391); \ No newline at end of file diff --git a/sql/updates/5774_mangos_command.sql b/sql/updates/5774_mangos_command.sql new file mode 100644 index 00000000000..c9f09b5efa0 --- /dev/null +++ b/sql/updates/5774_mangos_command.sql @@ -0,0 +1,5 @@ +DELETE FROM `command` WHERE `name` = 'targetobject'; +DELETE FROM `command` WHERE `name` = 'gobject target'; + +INSERT INTO `command` (`name`,`security`,`help`) VALUES +('gobject target',2,'Syntax: .gobject target [#go_id|#go_name_part]\r\n\r\nLocate and show position nearest gameobject. If #go_id or #go_name_part provide then locate and show position of nearest gameobject with gameobject template id #go_id or name included #go_name_part as part.'); diff --git a/sql/updates/5774_mangos_mangos_string.sql b/sql/updates/5774_mangos_mangos_string.sql new file mode 100644 index 00000000000..e5573f04bbe --- /dev/null +++ b/sql/updates/5774_mangos_mangos_string.sql @@ -0,0 +1,4 @@ +DELETE FROM `mangos_string` WHERE `entry` IN (582); + +INSERT INTO `mangos_string` VALUES +(582, 'SpawnTime: Full:%s Remain:%s',NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/5777_mangos_command.sql b/sql/updates/5777_mangos_command.sql new file mode 100644 index 00000000000..15b817f54ee --- /dev/null +++ b/sql/updates/5777_mangos_command.sql @@ -0,0 +1 @@ +DELETE FROM `command` WHERE `name` IN ('honor','modify'); diff --git a/sql/updates/5778_mangos_spell_affect.sql b/sql/updates/5778_mangos_spell_affect.sql new file mode 100644 index 00000000000..a4919d46b60 --- /dev/null +++ b/sql/updates/5778_mangos_spell_affect.sql @@ -0,0 +1,3 @@ +ALTER TABLE `spell_affect` + DROP `SpellFamily`, + DROP `Charges`; diff --git a/sql/updates/5779_mangos_quest_template.sql b/sql/updates/5779_mangos_quest_template.sql new file mode 100644 index 00000000000..e3353d5ee7d --- /dev/null +++ b/sql/updates/5779_mangos_quest_template.sql @@ -0,0 +1,21 @@ +ALTER TABLE `quest_template` ADD COLUMN `ClassOrSkill` smallint(6) NOT NULL default '0' AFTER `ZoneOrSort`; + +UPDATE `quest_template` SET `ClassOrSkill`=182 WHERE `ZoneOrSort`=-24; +UPDATE `quest_template` SET `ClassOrSkill`=356 WHERE `ZoneOrSort`=-101; +UPDATE `quest_template` SET `ClassOrSkill`=164 WHERE `ZoneOrSort`=-121; +UPDATE `quest_template` SET `ClassOrSkill`=171 WHERE `ZoneOrSort`=-181; +UPDATE `quest_template` SET `ClassOrSkill`=165 WHERE `ZoneOrSort`=-182; +UPDATE `quest_template` SET `ClassOrSkill`=202 WHERE `ZoneOrSort`=-201; +UPDATE `quest_template` SET `ClassOrSkill`=197 WHERE `ZoneOrSort`=-264; +UPDATE `quest_template` SET `ClassOrSkill`=185 WHERE `ZoneOrSort`=-304; +UPDATE `quest_template` SET `ClassOrSkill`=129 WHERE `ZoneOrSort`=-324; + +UPDATE `quest_template` SET `ClassOrSkill`=-9 WHERE `ZoneOrSort`=-61; +UPDATE `quest_template` SET `ClassOrSkill`=-1 WHERE `ZoneOrSort`=-81; +UPDATE `quest_template` SET `ClassOrSkill`=-7 WHERE `ZoneOrSort`=-82; +UPDATE `quest_template` SET `ClassOrSkill`=-2 WHERE `ZoneOrSort`=-141; +UPDATE `quest_template` SET `ClassOrSkill`=-8 WHERE `ZoneOrSort`=-161; +UPDATE `quest_template` SET `ClassOrSkill`=-4 WHERE `ZoneOrSort`=-162; +UPDATE `quest_template` SET `ClassOrSkill`=-3 WHERE `ZoneOrSort`=-261; +UPDATE `quest_template` SET `ClassOrSkill`=-5 WHERE `ZoneOrSort`=-262; +UPDATE `quest_template` SET `ClassOrSkill`=-11 WHERE `ZoneOrSort`=-263; diff --git a/sql/updates/5784_mangos_player_levelstats.sql b/sql/updates/5784_mangos_player_levelstats.sql new file mode 100644 index 00000000000..a107537d2f0 --- /dev/null +++ b/sql/updates/5784_mangos_player_levelstats.sql @@ -0,0 +1,70 @@ +UPDATE `player_levelstats` SET `basehp` = 32, `basemana` = 100 WHERE `class` = 8 AND `level`=1; +UPDATE `player_levelstats` SET `basehp` = 47, `basemana` = 110 WHERE `class` = 8 AND `level`=2; +UPDATE `player_levelstats` SET `basehp` = 52, `basemana` = 106 WHERE `class` = 8 AND `level`=3; +UPDATE `player_levelstats` SET `basehp` = 67, `basemana` = 118 WHERE `class` = 8 AND `level`=4; +UPDATE `player_levelstats` SET `basehp` = 82, `basemana` = 131 WHERE `class` = 8 AND `level`=5; +UPDATE `player_levelstats` SET `basehp` = 97, `basemana` = 130 WHERE `class` = 8 AND `level`=6; +UPDATE `player_levelstats` SET `basehp` = 102, `basemana` = 145 WHERE `class` = 8 AND `level`=7; +UPDATE `player_levelstats` SET `basehp` = 117, `basemana` = 146 WHERE `class` = 8 AND `level`=8; +UPDATE `player_levelstats` SET `basehp` = 132, `basemana` = 163 WHERE `class` = 8 AND `level`=9; +UPDATE `player_levelstats` SET `basehp` = 137, `basemana` = 196 WHERE `class` = 8 AND `level`=10; +UPDATE `player_levelstats` SET `basehp` = 152, `basemana` = 215 WHERE `class` = 8 AND `level`=11; +UPDATE `player_levelstats` SET `basehp` = 167, `basemana` = 220 WHERE `class` = 8 AND `level`=12; +UPDATE `player_levelstats` SET `basehp` = 172, `basemana` = 241 WHERE `class` = 8 AND `level`=13; +UPDATE `player_levelstats` SET `basehp` = 187, `basemana` = 263 WHERE `class` = 8 AND `level`=14; +UPDATE `player_levelstats` SET `basehp` = 202, `basemana` = 271 WHERE `class` = 8 AND `level`=15; +UPDATE `player_levelstats` SET `basehp` = 207, `basemana` = 295 WHERE `class` = 8 AND `level`=16; +UPDATE `player_levelstats` SET `basehp` = 222, `basemana` = 305 WHERE `class` = 8 AND `level`=17; +UPDATE `player_levelstats` SET `basehp` = 237, `basemana` = 331 WHERE `class` = 8 AND `level`=18; +UPDATE `player_levelstats` SET `basehp` = 242, `basemana` = 343 WHERE `class` = 8 AND `level`=19; +UPDATE `player_levelstats` SET `basehp` = 257, `basemana` = 371 WHERE `class` = 8 AND `level`=20; +UPDATE `player_levelstats` SET `basehp` = 272, `basemana` = 385 WHERE `class` = 8 AND `level`=21; +UPDATE `player_levelstats` SET `basehp` = 277, `basemana` = 415 WHERE `class` = 8 AND `level`=22; +UPDATE `player_levelstats` SET `basehp` = 292, `basemana` = 431 WHERE `class` = 8 AND `level`=23; +UPDATE `player_levelstats` SET `basehp` = 298, `basemana` = 463 WHERE `class` = 8 AND `level`=24; +UPDATE `player_levelstats` SET `basehp` = 315, `basemana` = 481 WHERE `class` = 8 AND `level`=25; +UPDATE `player_levelstats` SET `basehp` = 333, `basemana` = 515 WHERE `class` = 8 AND `level`=26; +UPDATE `player_levelstats` SET `basehp` = 342, `basemana` = 535 WHERE `class` = 8 AND `level`=27; +UPDATE `player_levelstats` SET `basehp` = 362, `basemana` = 556 WHERE `class` = 8 AND `level`=28; +UPDATE `player_levelstats` SET `basehp` = 373, `basemana` = 592 WHERE `class` = 8 AND `level`=29; +UPDATE `player_levelstats` SET `basehp` = 395, `basemana` = 613 WHERE `class` = 8 AND `level`=30; +UPDATE `player_levelstats` SET `basehp` = 418, `basemana` = 634 WHERE `class` = 8 AND `level`=31; +UPDATE `player_levelstats` SET `basehp` = 432, `basemana` = 670 WHERE `class` = 8 AND `level`=32; +UPDATE `player_levelstats` SET `basehp` = 457, `basemana` = 691 WHERE `class` = 8 AND `level`=33; +UPDATE `player_levelstats` SET `basehp` = 473, `basemana` = 712 WHERE `class` = 8 AND `level`=34; +UPDATE `player_levelstats` SET `basehp` = 500, `basemana` = 733 WHERE `class` = 8 AND `level`=35; +UPDATE `player_levelstats` SET `basehp` = 518, `basemana` = 754 WHERE `class` = 8 AND `level`=36; +UPDATE `player_levelstats` SET `basehp` = 547, `basemana` = 790 WHERE `class` = 8 AND `level`=37; +UPDATE `player_levelstats` SET `basehp` = 577, `basemana` = 811 WHERE `class` = 8 AND `level`=38; +UPDATE `player_levelstats` SET `basehp` = 598, `basemana` = 832 WHERE `class` = 8 AND `level`=39; +UPDATE `player_levelstats` SET `basehp` = 630, `basemana` = 853 WHERE `class` = 8 AND `level`=40; +UPDATE `player_levelstats` SET `basehp` = 653, `basemana` = 874 WHERE `class` = 8 AND `level`=41; +UPDATE `player_levelstats` SET `basehp` = 687, `basemana` = 895 WHERE `class` = 8 AND `level`=42; +UPDATE `player_levelstats` SET `basehp` = 712, `basemana` = 916 WHERE `class` = 8 AND `level`=43; +UPDATE `player_levelstats` SET `basehp` = 748, `basemana` = 937 WHERE `class` = 8 AND `level`=44; +UPDATE `player_levelstats` SET `basehp` = 775, `basemana` = 958 WHERE `class` = 8 AND `level`=45; +UPDATE `player_levelstats` SET `basehp` = 813, `basemana` = 979 WHERE `class` = 8 AND `level`=46; +UPDATE `player_levelstats` SET `basehp` = 842, `basemana` =1000 WHERE `class` = 8 AND `level`=47; +UPDATE `player_levelstats` SET `basehp` = 882, `basemana` =1021 WHERE `class` = 8 AND `level`=48; +UPDATE `player_levelstats` SET `basehp` = 913, `basemana` =1042 WHERE `class` = 8 AND `level`=49; +UPDATE `player_levelstats` SET `basehp` = 955, `basemana` =1048 WHERE `class` = 8 AND `level`=50; +UPDATE `player_levelstats` SET `basehp` = 988, `basemana` =1069 WHERE `class` = 8 AND `level`=51; +UPDATE `player_levelstats` SET `basehp` =1032, `basemana` =1090 WHERE `class` = 8 AND `level`=52; +UPDATE `player_levelstats` SET `basehp` =1067, `basemana` =1111 WHERE `class` = 8 AND `level`=53; +UPDATE `player_levelstats` SET `basehp` =1103, `basemana` =1117 WHERE `class` = 8 AND `level`=54; +UPDATE `player_levelstats` SET `basehp` =1150, `basemana` =1138 WHERE `class` = 8 AND `level`=55; +UPDATE `player_levelstats` SET `basehp` =1188, `basemana` =1159 WHERE `class` = 8 AND `level`=56; +UPDATE `player_levelstats` SET `basehp` =1237, `basemana` =1165 WHERE `class` = 8 AND `level`=57; +UPDATE `player_levelstats` SET `basehp` =1277, `basemana` =1186 WHERE `class` = 8 AND `level`=58; +UPDATE `player_levelstats` SET `basehp` =1328, `basemana` =1192 WHERE `class` = 8 AND `level`=59; +UPDATE `player_levelstats` SET `basehp` =1370, `basemana` =1213 WHERE `class` = 8 AND `level`=60; +UPDATE `player_levelstats` SET `basehp` =1526, `basemana` =1316 WHERE `class` = 8 AND `level`=61; +UPDATE `player_levelstats` SET `basehp` =1702, `basemana` =1419 WHERE `class` = 8 AND `level`=62; +UPDATE `player_levelstats` SET `basehp` =1875, `basemana` =1521 WHERE `class` = 8 AND `level`=63; +UPDATE `player_levelstats` SET `basehp` =2070, `basemana` =1624 WHERE `class` = 8 AND `level`=64; +UPDATE `player_levelstats` SET `basehp` =2261, `basemana` =1727 WHERE `class` = 8 AND `level`=65; +UPDATE `player_levelstats` SET `basehp` =2461, `basemana` =1830 WHERE `class` = 8 AND `level`=66; +UPDATE `player_levelstats` SET `basehp` =2686, `basemana` =1932 WHERE `class` = 8 AND `level`=67; +UPDATE `player_levelstats` SET `basehp` =2906, `basemana` =2035 WHERE `class` = 8 AND `level`=68; +UPDATE `player_levelstats` SET `basehp` =3136, `basemana` =2138 WHERE `class` = 8 AND `level`=69; +UPDATE `player_levelstats` SET `basehp` =3393, `basemana` =2241 WHERE `class` = 8 AND `level`=70; diff --git a/sql/updates/5787_mangos_player_levelstats.sql b/sql/updates/5787_mangos_player_levelstats.sql new file mode 100644 index 00000000000..15935dd99b0 --- /dev/null +++ b/sql/updates/5787_mangos_player_levelstats.sql @@ -0,0 +1,70 @@ +UPDATE `player_levelstats` SET `basehp` = 25 WHERE `class` = 4 AND `level`=1; +UPDATE `player_levelstats` SET `basehp` = 32 WHERE `class` = 4 AND `level`=2; +UPDATE `player_levelstats` SET `basehp` = 49 WHERE `class` = 4 AND `level`=3; +UPDATE `player_levelstats` SET `basehp` = 56 WHERE `class` = 4 AND `level`=4; +UPDATE `player_levelstats` SET `basehp` = 63 WHERE `class` = 4 AND `level`=5; +UPDATE `player_levelstats` SET `basehp` = 70 WHERE `class` = 4 AND `level`=6; +UPDATE `player_levelstats` SET `basehp` = 87 WHERE `class` = 4 AND `level`=7; +UPDATE `player_levelstats` SET `basehp` = 94 WHERE `class` = 4 AND `level`=8; +UPDATE `player_levelstats` SET `basehp` = 101 WHERE `class` = 4 AND `level`=9; +UPDATE `player_levelstats` SET `basehp` = 118 WHERE `class` = 4 AND `level`=10; +UPDATE `player_levelstats` SET `basehp` = 125 WHERE `class` = 4 AND `level`=11; +UPDATE `player_levelstats` SET `basehp` = 142 WHERE `class` = 4 AND `level`=12; +UPDATE `player_levelstats` SET `basehp` = 149 WHERE `class` = 4 AND `level`=13; +UPDATE `player_levelstats` SET `basehp` = 156 WHERE `class` = 4 AND `level`=14; +UPDATE `player_levelstats` SET `basehp` = 173 WHERE `class` = 4 AND `level`=15; +UPDATE `player_levelstats` SET `basehp` = 181 WHERE `class` = 4 AND `level`=16; +UPDATE `player_levelstats` SET `basehp` = 190 WHERE `class` = 4 AND `level`=17; +UPDATE `player_levelstats` SET `basehp` = 200 WHERE `class` = 4 AND `level`=18; +UPDATE `player_levelstats` SET `basehp` = 221 WHERE `class` = 4 AND `level`=19; +UPDATE `player_levelstats` SET `basehp` = 233 WHERE `class` = 4 AND `level`=20; +UPDATE `player_levelstats` SET `basehp` = 246 WHERE `class` = 4 AND `level`=21; +UPDATE `player_levelstats` SET `basehp` = 260 WHERE `class` = 4 AND `level`=22; +UPDATE `player_levelstats` SET `basehp` = 275 WHERE `class` = 4 AND `level`=23; +UPDATE `player_levelstats` SET `basehp` = 301 WHERE `class` = 4 AND `level`=24; +UPDATE `player_levelstats` SET `basehp` = 318 WHERE `class` = 4 AND `level`=25; +UPDATE `player_levelstats` SET `basehp` = 336 WHERE `class` = 4 AND `level`=26; +UPDATE `player_levelstats` SET `basehp` = 355 WHERE `class` = 4 AND `level`=27; +UPDATE `player_levelstats` SET `basehp` = 375 WHERE `class` = 4 AND `level`=28; +UPDATE `player_levelstats` SET `basehp` = 396 WHERE `class` = 4 AND `level`=29; +UPDATE `player_levelstats` SET `basehp` = 428 WHERE `class` = 4 AND `level`=30; +UPDATE `player_levelstats` SET `basehp` = 451 WHERE `class` = 4 AND `level`=31; +UPDATE `player_levelstats` SET `basehp` = 475 WHERE `class` = 4 AND `level`=32; +UPDATE `player_levelstats` SET `basehp` = 500 WHERE `class` = 4 AND `level`=33; +UPDATE `player_levelstats` SET `basehp` = 526 WHERE `class` = 4 AND `level`=34; +UPDATE `player_levelstats` SET `basehp` = 553 WHERE `class` = 4 AND `level`=35; +UPDATE `player_levelstats` SET `basehp` = 581 WHERE `class` = 4 AND `level`=36; +UPDATE `player_levelstats` SET `basehp` = 610 WHERE `class` = 4 AND `level`=37; +UPDATE `player_levelstats` SET `basehp` = 640 WHERE `class` = 4 AND `level`=38; +UPDATE `player_levelstats` SET `basehp` = 671 WHERE `class` = 4 AND `level`=39; +UPDATE `player_levelstats` SET `basehp` = 703 WHERE `class` = 4 AND `level`=40; +UPDATE `player_levelstats` SET `basehp` = 736 WHERE `class` = 4 AND `level`=41; +UPDATE `player_levelstats` SET `basehp` = 770 WHERE `class` = 4 AND `level`=42; +UPDATE `player_levelstats` SET `basehp` = 805 WHERE `class` = 4 AND `level`=43; +UPDATE `player_levelstats` SET `basehp` = 841 WHERE `class` = 4 AND `level`=44; +UPDATE `player_levelstats` SET `basehp` = 878 WHERE `class` = 4 AND `level`=45; +UPDATE `player_levelstats` SET `basehp` = 916 WHERE `class` = 4 AND `level`=46; +UPDATE `player_levelstats` SET `basehp` = 955 WHERE `class` = 4 AND `level`=47; +UPDATE `player_levelstats` SET `basehp` = 995 WHERE `class` = 4 AND `level`=48; +UPDATE `player_levelstats` SET `basehp` =1026 WHERE `class` = 4 AND `level`=49; +UPDATE `player_levelstats` SET `basehp` =1068 WHERE `class` = 4 AND `level`=50; +UPDATE `player_levelstats` SET `basehp` =1111 WHERE `class` = 4 AND `level`=51; +UPDATE `player_levelstats` SET `basehp` =1155 WHERE `class` = 4 AND `level`=52; +UPDATE `player_levelstats` SET `basehp` =1200 WHERE `class` = 4 AND `level`=53; +UPDATE `player_levelstats` SET `basehp` =1246 WHERE `class` = 4 AND `level`=54; +UPDATE `player_levelstats` SET `basehp` =1283 WHERE `class` = 4 AND `level`=55; +UPDATE `player_levelstats` SET `basehp` =1331 WHERE `class` = 4 AND `level`=56; +UPDATE `player_levelstats` SET `basehp` =1380 WHERE `class` = 4 AND `level`=57; +UPDATE `player_levelstats` SET `basehp` =1430 WHERE `class` = 4 AND `level`=58; +UPDATE `player_levelstats` SET `basehp` =1471 WHERE `class` = 4 AND `level`=59; +UPDATE `player_levelstats` SET `basehp` =1523 WHERE `class` = 4 AND `level`=60; +UPDATE `player_levelstats` SET `basehp` =1702 WHERE `class` = 4 AND `level`=61; +UPDATE `player_levelstats` SET `basehp` =1879 WHERE `class` = 4 AND `level`=62; +UPDATE `player_levelstats` SET `basehp` =2077 WHERE `class` = 4 AND `level`=63; +UPDATE `player_levelstats` SET `basehp` =2285 WHERE `class` = 4 AND `level`=64; +UPDATE `player_levelstats` SET `basehp` =2489 WHERE `class` = 4 AND `level`=65; +UPDATE `player_levelstats` SET `basehp` =2717 WHERE `class` = 4 AND `level`=66; +UPDATE `player_levelstats` SET `basehp` =2941 WHERE `class` = 4 AND `level`=67; +UPDATE `player_levelstats` SET `basehp` =3190 WHERE `class` = 4 AND `level`=68; +UPDATE `player_levelstats` SET `basehp` =3450 WHERE `class` = 4 AND `level`=69; +UPDATE `player_levelstats` SET `basehp` =3704 WHERE `class` = 4 AND `level`=70; diff --git a/sql/updates/5790_mangos_player_classlevelstats.sql b/sql/updates/5790_mangos_player_classlevelstats.sql new file mode 100644 index 00000000000..42714761dd7 --- /dev/null +++ b/sql/updates/5790_mangos_player_classlevelstats.sql @@ -0,0 +1,640 @@ +DROP TABLE IF EXISTS `player_classlevelstats`; +CREATE TABLE `player_classlevelstats` ( + `class` tinyint(3) unsigned NOT NULL, + `level` tinyint(3) unsigned NOT NULL, + `basehp` smallint(5) unsigned NOT NULL, + `basemana` smallint(5) unsigned NOT NULL, + PRIMARY KEY (`class`,`level`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 PACK_KEYS=0 COMMENT='Stores levels stats.'; + +INSERT INTO `player_classlevelstats` VALUES +(1,1,20,0), +(1,2,29,0), +(1,3,38,0), +(1,4,47,0), +(1,5,56,0), +(1,6,65,0), +(1,7,74,0), +(1,8,83,0), +(1,9,92,0), +(1,10,101,0), +(1,11,100,0), +(1,12,109,0), +(1,13,118,0), +(1,14,128,0), +(1,15,139,0), +(1,16,151,0), +(1,17,154,0), +(1,18,168,0), +(1,19,183,0), +(1,20,199,0), +(1,21,206,0), +(1,22,224,0), +(1,23,243,0), +(1,24,253,0), +(1,25,274,0), +(1,26,296,0), +(1,27,309,0), +(1,28,333,0), +(1,29,348,0), +(1,30,374,0), +(1,31,401,0), +(1,32,419,0), +(1,33,448,0), +(1,34,468,0), +(1,35,499,0), +(1,36,521,0), +(1,37,545,0), +(1,38,581,0), +(1,39,609,0), +(1,40,649,0), +(1,41,681,0), +(1,42,715,0), +(1,43,761,0), +(1,44,799,0), +(1,45,839,0), +(1,46,881,0), +(1,47,935,0), +(1,48,981,0), +(1,49,1029,0), +(1,50,1079,0), +(1,51,1131,0), +(1,52,1185,0), +(1,53,1241,0), +(1,54,1299,0), +(1,55,1359,0), +(1,56,1421,0), +(1,57,1485,0), +(1,58,1551,0), +(1,59,1619,0), +(1,60,1689,0), +(1,61,1902,0), +(1,62,2129,0), +(1,63,2357,0), +(1,64,2612,0), +(1,65,2883,0), +(1,66,3169,0), +(1,67,3455,0), +(1,68,3774,0), +(1,69,4109,0), +(1,70,4444,0), +(2,1,28,60), +(2,2,36,78), +(2,3,44,98), +(2,4,52,104), +(2,5,60,111), +(2,6,68,134), +(2,7,76,143), +(2,8,84,153), +(2,9,92,179), +(2,10,100,192), +(2,11,108,205), +(2,12,116,219), +(2,13,124,249), +(2,14,132,265), +(2,15,131,282), +(2,16,141,315), +(2,17,152,334), +(2,18,164,354), +(2,19,177,390), +(2,20,191,412), +(2,21,206,435), +(2,22,222,459), +(2,23,239,499), +(2,24,247,525), +(2,25,266,552), +(2,26,286,579), +(2,27,307,621), +(2,28,329,648), +(2,29,342,675), +(2,30,366,702), +(2,31,391,729), +(2,32,407,756), +(2,33,434,798), +(2,34,462,825), +(2,35,481,852), +(2,36,511,879), +(2,37,542,906), +(2,38,564,933), +(2,39,597,960), +(2,40,621,987), +(2,41,656,1014), +(2,42,682,1041), +(2,43,719,1068), +(2,44,747,1110), +(2,45,786,1137), +(2,46,816,1164), +(2,47,857,1176), +(2,48,889,1203), +(2,49,922,1230), +(2,50,966,1257), +(2,51,1001,1284), +(2,52,1037,1311), +(2,53,1084,1338), +(2,54,1122,1365), +(2,55,1161,1392), +(2,56,1201,1419), +(2,57,1252,1446), +(2,58,1294,1458), +(2,59,1337,1485), +(2,60,1381,1512), +(2,61,1540,1656), +(2,62,1708,1800), +(2,63,1884,1944), +(2,64,2068,2088), +(2,65,2262,2232), +(2,66,2466,2377), +(2,67,2679,2521), +(2,68,2901,2665), +(2,69,3134,2809), +(2,70,3377,2953), +(3,1,46,65), +(3,2,53,70), +(3,3,60,76), +(3,4,67,98), +(3,5,74,106), +(3,6,81,130), +(3,7,88,140), +(3,8,95,166), +(3,9,102,193), +(3,10,109,206), +(3,11,116,235), +(3,12,123,250), +(3,13,130,266), +(3,14,138,298), +(3,15,147,316), +(3,16,157,350), +(3,17,168,370), +(3,18,180,391), +(3,19,193,428), +(3,20,207,451), +(3,21,222,475), +(3,22,238,515), +(3,23,255,541), +(3,24,273,568), +(3,25,292,611), +(3,26,312,640), +(3,27,333,670), +(3,28,355,715), +(3,29,378,745), +(3,30,402,775), +(3,31,417,805), +(3,32,443,850), +(3,33,470,880), +(3,34,498,910), +(3,35,527,940), +(3,36,547,970), +(3,37,578,1015), +(3,38,610,1045), +(3,39,643,1075), +(3,40,667,1105), +(3,41,702,1135), +(3,42,738,1180), +(3,43,775,1210), +(3,44,803,1240), +(3,45,842,1270), +(3,46,872,1300), +(3,47,913,1330), +(3,48,955,1360), +(3,49,994,1390), +(3,50,1047,1420), +(3,51,1067,1450), +(3,52,1113,1480), +(3,53,1150,1510), +(3,54,1198,1540), +(3,55,1237,1570), +(3,56,1287,1600), +(3,57,1328,1630), +(3,58,1370,1660), +(3,59,1423,1690), +(3,60,1467,1720), +(3,61,1633,1886), +(3,62,1819,2053), +(3,63,2003,2219), +(3,64,2195,2385), +(3,65,2397,2552), +(3,66,2623,2718), +(3,67,2844,2884), +(3,68,3075,3050), +(3,69,3316,3217), +(3,70,3568,3383), +(4,1,25,0), +(4,2,32,0), +(4,3,49,0), +(4,4,56,0), +(4,5,63,0), +(4,6,70,0), +(4,7,87,0), +(4,8,94,0), +(4,9,101,0), +(4,10,118,0), +(4,11,125,0), +(4,12,142,0), +(4,13,149,0), +(4,14,156,0), +(4,15,173,0), +(4,16,181,0), +(4,17,190,0), +(4,18,200,0), +(4,19,221,0), +(4,20,233,0), +(4,21,246,0), +(4,22,260,0), +(4,23,275,0), +(4,24,301,0), +(4,25,318,0), +(4,26,336,0), +(4,27,355,0), +(4,28,375,0), +(4,29,396,0), +(4,30,428,0), +(4,31,451,0), +(4,32,475,0), +(4,33,500,0), +(4,34,526,0), +(4,35,553,0), +(4,36,581,0), +(4,37,610,0), +(4,38,640,0), +(4,39,671,0), +(4,40,703,0), +(4,41,736,0), +(4,42,770,0), +(4,43,805,0), +(4,44,841,0), +(4,45,878,0), +(4,46,916,0), +(4,47,955,0), +(4,48,995,0), +(4,49,1026,0), +(4,50,1068,0), +(4,51,1111,0), +(4,52,1155,0), +(4,53,1200,0), +(4,54,1246,0), +(4,55,1283,0), +(4,56,1331,0), +(4,57,1380,0), +(4,58,1430,0), +(4,59,1471,0), +(4,60,1523,0), +(4,61,1702,0), +(4,62,1879,0), +(4,63,2077,0), +(4,64,2285,0), +(4,65,2489,0), +(4,66,2717,0), +(4,67,2941,0), +(4,68,3190,0), +(4,69,3450,0), +(4,70,3704,0), +(5,1,52,73), +(5,2,57,76), +(5,3,72,95), +(5,4,77,114), +(5,5,92,133), +(5,6,97,152), +(5,7,112,171), +(5,8,117,190), +(5,9,132,209), +(5,10,137,212), +(5,11,142,215), +(5,12,157,234), +(5,13,172,254), +(5,14,177,260), +(5,15,192,282), +(5,16,197,305), +(5,17,212,329), +(5,18,227,339), +(5,19,232,365), +(5,20,247,377), +(5,21,252,405), +(5,22,268,434), +(5,23,275,449), +(5,24,293,480), +(5,25,302,497), +(5,26,322,530), +(5,27,343,549), +(5,28,355,584), +(5,29,378,605), +(5,30,392,627), +(5,31,417,665), +(5,32,433,689), +(5,33,460,728), +(5,34,478,752), +(5,35,507,776), +(5,36,527,800), +(5,37,548,839), +(5,38,580,863), +(5,39,603,887), +(5,40,637,911), +(5,41,662,950), +(5,42,698,974), +(5,43,725,998), +(5,44,763,1022), +(5,45,792,1046), +(5,46,822,1070), +(5,47,863,1094), +(5,48,895,1118), +(5,49,928,1142), +(5,50,972,1166), +(5,51,1007,1190), +(5,52,1053,1214), +(5,53,1090,1238), +(5,54,1128,1262), +(5,55,1177,1271), +(5,56,1217,1295), +(5,57,1258,1319), +(5,58,1300,1343), +(5,59,1353,1352), +(5,60,1397,1376), +(5,61,1557,1500), +(5,62,1738,1625), +(5,63,1916,1749), +(5,64,2101,1873), +(5,65,2295,1998), +(5,66,2495,2122), +(5,67,2719,2247), +(5,68,2936,2371), +(5,69,3160,2495), +(5,70,3391,2620), +(7,1,37,85), +(7,2,44,91), +(7,3,51,98), +(7,4,58,106), +(7,5,65,115), +(7,6,72,125), +(7,7,79,136), +(7,8,86,148), +(7,9,93,161), +(7,10,100,175), +(7,11,107,190), +(7,12,114,206), +(7,13,121,223), +(7,14,128,241), +(7,15,135,260), +(7,16,142,280), +(7,17,150,301), +(7,18,159,323), +(7,19,169,346), +(7,20,180,370), +(7,21,192,395), +(7,22,205,421), +(7,23,219,448), +(7,24,234,476), +(7,25,240,505), +(7,26,257,535), +(7,27,275,566), +(7,28,294,598), +(7,29,314,631), +(7,30,335,665), +(7,31,347,699), +(7,32,370,733), +(7,33,394,767), +(7,34,419,786), +(7,35,435,820), +(7,36,462,854), +(7,37,490,888), +(7,38,509,922), +(7,39,539,941), +(7,40,570,975), +(7,41,592,1009), +(7,42,625,1028), +(7,43,649,1062), +(7,44,684,1096), +(7,45,710,1115), +(7,46,747,1149), +(7,47,775,1183), +(7,48,814,1202), +(7,49,844,1236), +(7,50,885,1255), +(7,51,917,1289), +(7,52,960,1323), +(7,53,994,1342), +(7,54,1029,1376), +(7,55,1075,1395), +(7,56,1112,1414), +(7,57,1150,1448), +(7,58,1199,1467), +(7,59,1239,1501), +(7,60,1330,1520), +(7,61,1428,1664), +(7,62,1583,1808), +(7,63,1760,1951), +(7,64,1932,2095), +(7,65,2114,2239), +(7,66,2304,2383), +(7,67,2504,2527), +(7,68,2713,2670), +(7,69,2931,2814), +(7,70,3159,2958), +(8,1,32,100), +(8,2,47,110), +(8,3,52,106), +(8,4,67,118), +(8,5,82,131), +(8,6,97,130), +(8,7,102,145), +(8,8,117,146), +(8,9,132,163), +(8,10,137,196), +(8,11,152,215), +(8,12,167,220), +(8,13,172,241), +(8,14,187,263), +(8,15,202,271), +(8,16,207,295), +(8,17,222,305), +(8,18,237,331), +(8,19,242,343), +(8,20,257,371), +(8,21,272,385), +(8,22,277,415), +(8,23,292,431), +(8,24,298,463), +(8,25,315,481), +(8,26,333,515), +(8,27,342,535), +(8,28,362,556), +(8,29,373,592), +(8,30,395,613), +(8,31,418,634), +(8,32,432,670), +(8,33,457,691), +(8,34,473,712), +(8,35,500,733), +(8,36,518,754), +(8,37,547,790), +(8,38,577,811), +(8,39,598,832), +(8,40,630,853), +(8,41,653,874), +(8,42,687,895), +(8,43,712,916), +(8,44,748,937), +(8,45,775,958), +(8,46,813,979), +(8,47,842,1000), +(8,48,882,1021), +(8,49,913,1042), +(8,50,955,1048), +(8,51,988,1069), +(8,52,1032,1090), +(8,53,1067,1111), +(8,54,1103,1117), +(8,55,1150,1138), +(8,56,1188,1159), +(8,57,1237,1165), +(8,58,1277,1186), +(8,59,1328,1192), +(8,60,1370,1213), +(8,61,1526,1316), +(8,62,1702,1419), +(8,63,1875,1521), +(8,64,2070,1624), +(8,65,2261,1727), +(8,66,2461,1830), +(8,67,2686,1932), +(8,68,2906,2035), +(8,69,3136,2138), +(8,70,3393,2241), +(9,1,23,90), +(9,2,28,98), +(9,3,43,107), +(9,4,48,102), +(9,5,63,113), +(9,6,68,126), +(9,7,83,144), +(9,8,88,162), +(9,9,93,180), +(9,10,108,198), +(9,11,123,200), +(9,12,128,218), +(9,13,143,237), +(9,14,148,257), +(9,15,153,278), +(9,16,168,300), +(9,17,173,308), +(9,18,189,332), +(9,19,196,357), +(9,20,204,383), +(9,21,223,395), +(9,22,233,423), +(9,23,244,452), +(9,24,266,467), +(9,25,279,498), +(9,26,293,530), +(9,27,318,548), +(9,28,334,582), +(9,29,351,602), +(9,30,379,638), +(9,31,398,674), +(9,32,418,695), +(9,33,439,731), +(9,34,471,752), +(9,35,494,788), +(9,36,518,809), +(9,37,543,830), +(9,38,569,866), +(9,39,606,887), +(9,40,634,923), +(9,41,663,944), +(9,42,693,965), +(9,43,724,1001), +(9,44,756,1022), +(9,45,799,1043), +(9,46,832,1064), +(9,47,868,1100), +(9,48,904,1121), +(9,49,941,1142), +(9,50,979,1163), +(9,51,1018,1184), +(9,52,1058,1205), +(9,53,1099,1226), +(9,54,1141,1247), +(9,55,1184,1268), +(9,56,1228,1289), +(9,57,1273,1310), +(9,58,1319,1331), +(9,59,1366,1352), +(9,60,1414,1373), +(9,61,1580,1497), +(9,62,1755,1621), +(9,63,1939,1745), +(9,64,2133,1870), +(9,65,2323,1994), +(9,66,2535,2118), +(9,67,2758,2242), +(9,68,2991,2366), +(9,69,3235,2490), +(9,70,3490,2615), +(11,1,44,60), +(11,2,51,66), +(11,3,58,73), +(11,4,75,81), +(11,5,82,90), +(11,6,89,100), +(11,7,106,111), +(11,8,113,123), +(11,9,120,136), +(11,10,137,150), +(11,11,144,165), +(11,12,151,182), +(11,13,168,200), +(11,14,175,219), +(11,15,182,239), +(11,16,199,260), +(11,17,206,282), +(11,18,214,305), +(11,19,233,329), +(11,20,243,354), +(11,21,254,380), +(11,22,266,392), +(11,23,289,420), +(11,24,303,449), +(11,25,318,479), +(11,26,334,509), +(11,27,361,524), +(11,28,379,554), +(11,29,398,584), +(11,30,418,614), +(11,31,439,629), +(11,32,461,659), +(11,33,494,689), +(11,34,518,704), +(11,35,543,734), +(11,36,569,749), +(11,37,596,779), +(11,38,624,809), +(11,39,653,824), +(11,40,683,854), +(11,41,714,869), +(11,42,746,899), +(11,43,779,914), +(11,44,823,944), +(11,45,858,959), +(11,46,894,989), +(11,47,921,1004), +(11,48,959,1019), +(11,49,998,1049), +(11,50,1038,1064), +(11,51,1079,1079), +(11,52,1121,1109), +(11,53,1164,1124), +(11,54,1208,1139), +(11,55,1253,1154), +(11,56,1299,1169), +(11,57,1346,1199), +(11,58,1384,1214), +(11,59,1433,1229), +(11,60,1483,1244), +(11,61,1657,1357), +(11,62,1840,1469), +(11,63,2020,1582), +(11,64,2222,1694), +(11,65,2433,1807), +(11,66,2640,1919), +(11,67,2872,2032), +(11,68,3114,2145), +(11,69,3351,2257), +(11,70,3614,2370); diff --git a/sql/updates/5790_mangos_player_levelstats.sql b/sql/updates/5790_mangos_player_levelstats.sql new file mode 100644 index 00000000000..fa6454892cd --- /dev/null +++ b/sql/updates/5790_mangos_player_levelstats.sql @@ -0,0 +1,3 @@ +ALTER TABLE `player_levelstats` + DROP `basehp`, + DROP `basemana`; diff --git a/sql/updates/5799_mangos_spell_proc_event.sql b/sql/updates/5799_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..d2047e24276 --- /dev/null +++ b/sql/updates/5799_mangos_spell_proc_event.sql @@ -0,0 +1,6 @@ +DELETE FROM spell_proc_event WHERE entry IN (45481,45482,45483,45484); +INSERT INTO spell_proc_event VALUES +(45481,0,0,0,0,0x0000000000000000,0x08020000,0), +(45482,0,0,0,0,0x0000000000000000,0x00080001,0), +(45483,0,0,0,0,0x0000000000000000,0x00080001,0), +(45484,0,0,0,0,0x0000000000000000,0x08000000,0); diff --git a/sql/updates/5813_mangos_mangos_string.sql b/sql/updates/5813_mangos_mangos_string.sql new file mode 100644 index 00000000000..946db393e1c --- /dev/null +++ b/sql/updates/5813_mangos_mangos_string.sql @@ -0,0 +1,27 @@ +INSERT INTO `mangos_string` VALUES ('614', 'The Alliance flag has been respawned!', null, null, null, null, null, null, null); +INSERT INTO `mangos_string` VALUES ('615', 'The Horde flag has been respawned!', null, null, null, null, null, null, null); +INSERT INTO `mangos_string` VALUES ('636', 'The battle begins in 1 minute.', null, null, null, null, null, null, null); +INSERT INTO `mangos_string` VALUES ('637', 'The battle begins in 30 seconds.', null, null, null, null, null, null, null); +INSERT INTO `mangos_string` VALUES ('638', 'The battle has begun!', null, null, null, null, null, null, null); +INSERT INTO `mangos_string` VALUES ('667', 'The Alliance has taken control of the Mage Tower!', null, null, null, null, null, null, null); +INSERT INTO `mangos_string` VALUES ('668', 'The Horde has taken control of the Mage Tower!', null, null, null, null, null, null, null); +INSERT INTO `mangos_string` VALUES ('669', 'The Alliance has taken control of the Draenei Ruins!', null, null, null, null, null, null, null); +INSERT INTO `mangos_string` VALUES ('670', 'The Horde has taken control of the Draenei Ruins!', null, null, null, null, null, null, null); +INSERT INTO `mangos_string` VALUES ('671', 'The Alliance has taken control of the Blood Elf Tower!', null, null, null, null, null, null, null); +INSERT INTO `mangos_string` VALUES ('672', 'The Horde has taken control of the Blood Elf Tower!', null, null, null, null, null, null, null); +INSERT INTO `mangos_string` VALUES ('673', 'The Alliance has taken control of the Fel Reaver Ruins!', null, null, null, null, null, null, null); +INSERT INTO `mangos_string` VALUES ('674', 'The Horde has taken control of the Fel Reaver Ruins!', null, null, null, null, null, null, null); +INSERT INTO `mangos_string` VALUES ('675', 'The Alliance has lost control of the Mage Tower!', null, null, null, null, null, null, null); +INSERT INTO `mangos_string` VALUES ('676', 'The Horde has lost control of the Mage Tower!', null, null, null, null, null, null, null); +INSERT INTO `mangos_string` VALUES ('677', 'The Alliance has lost control of the Draenei Ruins!', null, null, null, null, null, null, null); +INSERT INTO `mangos_string` VALUES ('678', 'The Horde has lost control of the Draenei Ruins!', null, null, null, null, null, null, null); +INSERT INTO `mangos_string` VALUES ('679', 'The Alliance has lost control of the Blood Elf Tower!', null, null, null, null, null, null, null); +INSERT INTO `mangos_string` VALUES ('680', 'The Horde has lost control of the Blood Elf Tower!', null, null, null, null, null, null, null); +INSERT INTO `mangos_string` VALUES ('681', 'The Alliance has lost control of the Fel Reaver Ruins!', null, null, null, null, null, null, null); +INSERT INTO `mangos_string` VALUES ('682', 'The Horde has lost control of the Fel Reaver Ruins!', null, null, null, null, null, null, null); +INSERT INTO `mangos_string` VALUES ('683', '$N has taken the flag!', null, null, null, null, null, null, null); +INSERT INTO `mangos_string` VALUES ('684', 'The Alliance has captured the flag!', null, null, null, null, null, null, null); +INSERT INTO `mangos_string` VALUES ('685', 'The Horde has captured the flag!', null, null, null, null, null, null, null); +INSERT INTO `mangos_string` VALUES ('686', 'The Flag has been dropped!', null, null, null, null, null, null, null); +INSERT INTO `mangos_string` VALUES ('687', 'The flag has been reset', null, null, null, null, null, null, null); + diff --git a/sql/updates/5827_mangos_spell_affect.sql b/sql/updates/5827_mangos_spell_affect.sql new file mode 100644 index 00000000000..2477ec1c937 --- /dev/null +++ b/sql/updates/5827_mangos_spell_affect.sql @@ -0,0 +1,5 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (32043,35396,35397); +INSERT INTO `spell_affect` VALUES +(32043,1,0x000004000A000000), +(35396,1,0x000004000A000000), +(35397,1,0x000004000A000000); diff --git a/sql/updates/5827_mangos_spell_chain.sql b/sql/updates/5827_mangos_spell_chain.sql new file mode 100644 index 00000000000..271d692c13a --- /dev/null +++ b/sql/updates/5827_mangos_spell_chain.sql @@ -0,0 +1,8 @@ +-- wrong entry +DELETE FROM `spell_chain` WHERE `spell_id` IN (5159); + + +DELETE FROM `spell_chain` WHERE `spell_id` IN (5195,5196); +INSERT INTO `spell_chain` (`spell_id`, `prev_spell`, `first_spell`, `rank`) VALUES +(5195,1062,339,3), +(5196,5195,339,4); diff --git a/sql/updates/5827_mangos_spell_learn_spell.sql b/sql/updates/5827_mangos_spell_learn_spell.sql new file mode 100644 index 00000000000..59cb8608acd --- /dev/null +++ b/sql/updates/5827_mangos_spell_learn_spell.sql @@ -0,0 +1,5 @@ +DELETE FROM spell_learn_spell WHERE entry IN (33872,33873); + +INSERT INTO spell_learn_spell (entry,spellID) VALUES +(33872,47179), +(33873,47180); diff --git a/sql/updates/5827_mangos_spell_proc_event.sql b/sql/updates/5827_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..6f8701d159b --- /dev/null +++ b/sql/updates/5827_mangos_spell_proc_event.sql @@ -0,0 +1,7 @@ +DELETE FROM `spell_proc_event` WHERE `entry` = '33522'; +INSERT INTO `spell_proc_event` VALUES +(33522,0,0,0,0,0x0000000000000000,0x00020000,0); + +DELETE FROM `spell_proc_event` WHERE `entry` = '33648'; +INSERT INTO `spell_proc_event` VALUES +(33648,0,0,0,0,0x0000000000000000,0x00401000,0); diff --git a/sql/updates/5831_mangos_skill_fishing_base_level.sql b/sql/updates/5831_mangos_skill_fishing_base_level.sql new file mode 100644 index 00000000000..15665120422 --- /dev/null +++ b/sql/updates/5831_mangos_skill_fishing_base_level.sql @@ -0,0 +1,6 @@ +DROP TABLE IF EXISTS `skill_fishing_base_level`; +CREATE TABLE `skill_fishing_base_level` ( + `entry` mediumint(8) unsigned NOT NULL default '0' COMMENT 'Area identifier', + `skill` smallint(6) NOT NULL default '0' COMMENT 'Base skill level requirement', + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Fishing system'; diff --git a/sql/updates/5842_mangos_spell_affect.sql b/sql/updates/5842_mangos_spell_affect.sql new file mode 100644 index 00000000000..d3e77cf1269 --- /dev/null +++ b/sql/updates/5842_mangos_spell_affect.sql @@ -0,0 +1,4 @@ +DELETE FROM `spell_affect` WHERE `entry` = 19245; +INSERT INTO `spell_affect` VALUES +(19245,0,0x0000000000000018), +(19245,1,0x0000200000000004); diff --git a/sql/updates/5845_mangos_spell_proc_event.sql b/sql/updates/5845_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..72ba36c1a1f --- /dev/null +++ b/sql/updates/5845_mangos_spell_proc_event.sql @@ -0,0 +1,4 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (20164,31895); +INSERT INTO `spell_proc_event` VALUES +(20164,0,0,0,0,0x0000000000000000,0x00000001,5), +(31895,0,0,0,0,0x0000000000000000,0x00000001,5); diff --git a/sql/updates/5847_mangos_command.sql b/sql/updates/5847_mangos_command.sql new file mode 100644 index 00000000000..473385d9838 --- /dev/null +++ b/sql/updates/5847_mangos_command.sql @@ -0,0 +1,4 @@ +DELETE FROM `command` WHERE `name` = 'damage'; + +INSERT INTO `command` (`name`,`security`,`help`) VALUES +('damage',3,'Syntax: .damage $damage_amount [$school [$spellid]]\r\n\r\nApply $damage to target. If not $school and $spellid provided then this flat clean melee damage without any modifiers. If $school provided then damage modified by armor reduction (if school physical), and target absorbing modifiers and result applied as melee damage to target. If spell provided then damage modified and applied as spell damage. $spellid can be shift-link.'); diff --git a/sql/updates/5857_mangos_spell_proc_event.sql b/sql/updates/5857_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..b6af5986817 --- /dev/null +++ b/sql/updates/5857_mangos_spell_proc_event.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (32748); +INSERT INTO `spell_proc_event` VALUES +(32748,0,0,0,8,0x0000000100000000,0x00008000,0); diff --git a/sql/updates/5861_mangos_command.sql b/sql/updates/5861_mangos_command.sql new file mode 100644 index 00000000000..e6250d98dc2 --- /dev/null +++ b/sql/updates/5861_mangos_command.sql @@ -0,0 +1,10 @@ +DELETE FROM `command` WHERE `name` = 'wp import'; +DELETE FROM `command` WHERE `name` = 'wp export'; + +INSERT INTO `command` (`name`,`security`,`help`) VALUES +('wp import',3,'Syntax: .wp import $filename'); + +INSERT INTO `command` (`name`,`security`,`help`) VALUES +('wp export',3,'Syntax: .wp export [#creature_guid or Select a Creature] $filename'); + +UPDATE `command` SET `help` = 'Syntax: .wp modify [#creature_guid or Select a Creature]\r\nadd - Add a waypoint after the selected visual\r\nwaittime $time\r\nemote ID\r\nspell ID\r\ntext1| text2| text3| text4| text5 \r\nmodel1 ID\r\nmodel2 ID\r\nmove(moves wp to player pos)\r\ndel (deletes the wp)\r\n\r\nOnly one parameter per time!' WHERE `name` = 'wp modify'; \ No newline at end of file diff --git a/sql/updates/5865_mangos_command.sql b/sql/updates/5865_mangos_command.sql new file mode 100644 index 00000000000..d9004433a22 --- /dev/null +++ b/sql/updates/5865_mangos_command.sql @@ -0,0 +1,4 @@ +DELETE FROM `command` WHERE `name` = 'cast self'; + +INSERT INTO `command` (`name`,`security`,`help`) VALUES +('cast self',3,'Syntax: .cast self #spellid\r\nCast #spellid by target at target itself.'); diff --git a/sql/updates/5867_mangos_spell_affect.sql b/sql/updates/5867_mangos_spell_affect.sql new file mode 100644 index 00000000000..f801715d935 --- /dev/null +++ b/sql/updates/5867_mangos_spell_affect.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (12472); +INSERT INTO `spell_affect` VALUES + (12472, 1, 0x00000000E44008A5); diff --git a/sql/updates/5875_mangos_quest_template.sql b/sql/updates/5875_mangos_quest_template.sql new file mode 100644 index 00000000000..c10964130ed --- /dev/null +++ b/sql/updates/5875_mangos_quest_template.sql @@ -0,0 +1 @@ +ALTER TABLE `quest_template` CHANGE `ClassOrSkill` `SkillOrClass` smallint(6) NOT NULL default '0'; diff --git a/sql/updates/5880_mangos_mangos_string.sql b/sql/updates/5880_mangos_mangos_string.sql new file mode 100644 index 00000000000..74d5d92ac97 --- /dev/null +++ b/sql/updates/5880_mangos_mangos_string.sql @@ -0,0 +1,3 @@ +DELETE FROM mangos_string WHERE entry in (297); +INSERT INTO `mangos_string` VALUES +(297,'Spawn distance changed to: %f',NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/5882_mangos_spell_affect.sql b/sql/updates/5882_mangos_spell_affect.sql new file mode 100644 index 00000000000..e86c85016f3 --- /dev/null +++ b/sql/updates/5882_mangos_spell_affect.sql @@ -0,0 +1,29 @@ +-- (17954) Emberstorm (Rank 1) +DELETE FROM `spell_affect` WHERE `entry` IN (17954); +INSERT INTO `spell_affect` VALUES (17954, 0, 0x000000C000001364); +INSERT INTO `spell_affect` VALUES (17954, 1, 0x000000C000001364); +INSERT INTO `spell_affect` VALUES (17954, 2, 0x0000004000000000); + +-- (17955) Emberstorm (Rank 2) +DELETE FROM `spell_affect` WHERE `entry` IN (17955); +INSERT INTO `spell_affect` VALUES (17955, 0, 0x000000C000001364); +INSERT INTO `spell_affect` VALUES (17955, 1, 0x000000C000001364); +INSERT INTO `spell_affect` VALUES (17955, 2, 0x0000004000000000); + +-- (17956) Emberstorm (Rank 3) +DELETE FROM `spell_affect` WHERE `entry` IN (17956); +INSERT INTO `spell_affect` VALUES (17956, 0, 0x000000C000001364); +INSERT INTO `spell_affect` VALUES (17956, 1, 0x000000C000001364); +INSERT INTO `spell_affect` VALUES (17956, 2, 0x0000004000000000); + +-- (17957) Emberstorm (Rank 4) +DELETE FROM `spell_affect` WHERE `entry` IN (17957); +INSERT INTO `spell_affect` VALUES (17957, 0, 0x000000C000001364); +INSERT INTO `spell_affect` VALUES (17957, 1, 0x000000C000001364); +INSERT INTO `spell_affect` VALUES (17957, 2, 0x0000004000000000); + +-- (17958) Emberstorm (Rank 5) +DELETE FROM `spell_affect` WHERE `entry` IN (17958); +INSERT INTO `spell_affect` VALUES (17958, 0, 0x000000C000001364); +INSERT INTO `spell_affect` VALUES (17958, 1, 0x000000C000001364); +INSERT INTO `spell_affect` VALUES (17958, 2, 0x0000004000000000); diff --git a/sql/updates/5890_mangos_quest_template.sql b/sql/updates/5890_mangos_quest_template.sql new file mode 100644 index 00000000000..1cd69648820 --- /dev/null +++ b/sql/updates/5890_mangos_quest_template.sql @@ -0,0 +1 @@ +UPDATE `quest_template` SET `SkillOrClass`=0 WHERE `ZoneOrSort` IN (-61,-81,-82,-141,-161,-162,-261,-262,-263); diff --git a/sql/updates/5896_mangos_spell_proc_event.sql b/sql/updates/5896_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..641ea3470bc --- /dev/null +++ b/sql/updates/5896_mangos_spell_proc_event.sql @@ -0,0 +1,4 @@ +DELETE FROM spell_proc_event WHERE entry IN (45054,45354); +INSERT INTO spell_proc_event VALUES +(45054,0,0,0,0,0x0000000000000000,0x00020000,0), +(45354,0,0,0,0,0x0000000000000000,0x00000001,0); diff --git a/sql/updates/5923_mangos_spell_affect.sql b/sql/updates/5923_mangos_spell_affect.sql new file mode 100644 index 00000000000..836e1bad7ba --- /dev/null +++ b/sql/updates/5923_mangos_spell_affect.sql @@ -0,0 +1 @@ +DELETE FROM `spell_affect` WHERE `entry` IN (41660); diff --git a/sql/updates/5940_mangos_spell_affect.sql b/sql/updates/5940_mangos_spell_affect.sql new file mode 100644 index 00000000000..51f5c029a3f --- /dev/null +++ b/sql/updates/5940_mangos_spell_affect.sql @@ -0,0 +1,3 @@ +-- (14177) Cold Blood () +DELETE FROM `spell_affect` WHERE `entry` IN (14177); +INSERT INTO `spell_affect` VALUES (14177, 0, 0x0000000C6012031E); \ No newline at end of file diff --git a/sql/updates/5946_mangos_spell_affect.sql b/sql/updates/5946_mangos_spell_affect.sql new file mode 100644 index 00000000000..2f4fc5b7ad9 --- /dev/null +++ b/sql/updates/5946_mangos_spell_affect.sql @@ -0,0 +1,19 @@ +-- (20216) Divine Favor () +DELETE FROM `spell_affect` WHERE `entry` IN (20216); +INSERT INTO `spell_affect` VALUES (20216, 0, 0x00010000C0200000); + +-- (37879) Blessing of Lower City () +DELETE FROM `spell_affect` WHERE `entry` IN (37879); +INSERT INTO `spell_affect` VALUES (37879, 0, 0x00000000C0000000); + +-- (20237) Healing Light (Rank 1) +DELETE FROM `spell_affect` WHERE `entry` IN (20237); +INSERT INTO `spell_affect` VALUES (20237, 0, 0x00000000C0000000); + +-- (20238) Healing Light (Rank 2) +DELETE FROM `spell_affect` WHERE `entry` IN (20238); +INSERT INTO `spell_affect` VALUES (20238, 0, 0x00000000C0000000); + +-- (20239) Healing Light (Rank 3) +DELETE FROM `spell_affect` WHERE `entry` IN (20239); +INSERT INTO `spell_affect` VALUES (20239, 0, 0x00000000C0000000); diff --git a/sql/updates/5955_characters_guild_eventlog.sql b/sql/updates/5955_characters_guild_eventlog.sql new file mode 100644 index 00000000000..ea7a9892a9e --- /dev/null +++ b/sql/updates/5955_characters_guild_eventlog.sql @@ -0,0 +1,10 @@ +DROP TABLE IF EXISTS `guild_eventlog`; +CREATE TABLE `guild_eventlog` ( + `guildid` int(11) NOT NULL COMMENT 'Guild Identificator', + `LogGuid` int(11) NOT NULL COMMENT 'Log entry identificator', + `EventType` tinyint(1) NOT NULL COMMENT 'Event type', + `PlayerGuid1` int(11) NOT NULL COMMENT 'Player 1', + `PlayerGuid2` int(11) NOT NULL COMMENT 'Player 2', + `NewRank` tinyint(2) NOT NULL COMMENT 'New rank(in case promotion/demotion)', + `TimeStamp` bigint(20) NOT NULL COMMENT 'Event UNIX time' +) ENGINE = InnoDB DEFAULT CHARSET = latin1 COMMENT 'Guild Eventlog'; diff --git a/sql/updates/5965_mangos_mangos_string.sql b/sql/updates/5965_mangos_mangos_string.sql new file mode 100644 index 00000000000..f162006eb9a --- /dev/null +++ b/sql/updates/5965_mangos_mangos_string.sql @@ -0,0 +1,4 @@ +DELETE FROM mangos_string WHERE entry in (468,470); +INSERT INTO `mangos_string` VALUES +(468,'id: %d eff: %d type: %d duration: %d maxduration: %d name: %s%s%s caster: %s %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(470,'id: %d eff: %d name: %s%s%s caster: %s %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/5973_mangos_spell_proc_event.sql b/sql/updates/5973_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..5dc5601fc84 --- /dev/null +++ b/sql/updates/5973_mangos_spell_proc_event.sql @@ -0,0 +1,4 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (44835); +INSERT INTO `spell_proc_event` VALUES +(44835,0,0,0,7,0x0000008000000000,0x00008000,0); + diff --git a/sql/updates/5977_characters_pet.sql b/sql/updates/5977_characters_pet.sql new file mode 100644 index 00000000000..f4454ca856f --- /dev/null +++ b/sql/updates/5977_characters_pet.sql @@ -0,0 +1,3 @@ +DELETE FROM pet_aura WHERE guid NOT IN (SELECT id FROM character_pet); +DELETE FROM pet_spell WHERE guid NOT IN (SELECT id FROM character_pet); +DELETE FROM pet_spell_cooldown WHERE guid NOT IN (SELECT id FROM character_pet); diff --git a/sql/updates/5982_mangos.sql b/sql/updates/5982_mangos.sql new file mode 100644 index 00000000000..bea6150819d --- /dev/null +++ b/sql/updates/5982_mangos.sql @@ -0,0 +1,2 @@ +DROP TABLE playercreateinfo_skill; +DROP TABLE spell_learn_skill; \ No newline at end of file diff --git a/sql/updates/5986_mangos_spell_proc_event.sql b/sql/updates/5986_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..b544a1e1b50 --- /dev/null +++ b/sql/updates/5986_mangos_spell_proc_event.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (46832); +INSERT INTO `spell_proc_event` VALUES +(46832,0,0,0,7,0x0000000000000001,0x00004000,0); diff --git a/sql/updates/5999_mangos_spell_proc_event.sql b/sql/updates/5999_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..704af8c50f9 --- /dev/null +++ b/sql/updates/5999_mangos_spell_proc_event.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (37528); +INSERT INTO `spell_proc_event` VALUES +(37528,0,0,0,4,0x0000000000000004,0x00000001,0); diff --git a/sql/updates/6016_mangos_spell_proc_event.sql b/sql/updates/6016_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..5099da8ed16 --- /dev/null +++ b/sql/updates/6016_mangos_spell_proc_event.sql @@ -0,0 +1,12 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (37173); +INSERT INTO `spell_proc_event` VALUES +(37173,0,0,0,8,0x000001062cbc0598,0x000a0001,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (30881,30883,30884,30885,30886); +INSERT INTO `spell_proc_event` VALUES +(30881,0,0,0,0,0x0000000000000000,0x00008000,0), +(30883,0,0,0,0,0x0000000000000000,0x00008000,0), +(30884,0,0,0,0,0x0000000000000000,0x00008000,0), +(30885,0,0,0,0,0x0000000000000000,0x00008000,0), +(30886,0,0,0,0,0x0000000000000000,0x00008000,0); + diff --git a/sql/updates/6017_mangos_spell_proc_event.sql b/sql/updates/6017_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..a9c55a14b9d --- /dev/null +++ b/sql/updates/6017_mangos_spell_proc_event.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (37170); +INSERT INTO `spell_proc_event` VALUES +(37170,0,0,0,0,0x0000000000000000,0x00000001,1); diff --git a/sql/updates/6022_mangos_spell_proc_event.sql b/sql/updates/6022_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..2525a13c9de --- /dev/null +++ b/sql/updates/6022_mangos_spell_proc_event.sql @@ -0,0 +1,7 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (12322,12999,13000,13001,13002); +INSERT INTO `spell_proc_event` VALUES +(12322,0,0,0,0,0x0000000000000000,0x00000001,2), +(12999,0,0,0,0,0x0000000000000000,0x00000001,4), +(13000,0,0,0,0,0x0000000000000000,0x00000001,6), +(13001,0,0,0,0,0x0000000000000000,0x00000001,8), +(13002,0,0,0,0,0x0000000000000000,0x00000001,10); diff --git a/sql/updates/6023_mangos_mangos_string.sql b/sql/updates/6023_mangos_mangos_string.sql new file mode 100644 index 00000000000..c93d5ee988b --- /dev/null +++ b/sql/updates/6023_mangos_mangos_string.sql @@ -0,0 +1,6 @@ +DELETE FROM `mangos_string` WHERE `entry` IN (314,315,316); + +INSERT INTO `mangos_string` VALUES +(314, ' [peace forced]',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(315, ' [hidden]',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(316, ' [invisible forced]',NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/6027_mangos_spell_affect.sql b/sql/updates/6027_mangos_spell_affect.sql new file mode 100644 index 00000000000..877ca72150e --- /dev/null +++ b/sql/updates/6027_mangos_spell_affect.sql @@ -0,0 +1,12 @@ +DELETE FROM `spell_affect` WHERE `entry` IN +(12873,12872,11095,11252,12605,20244,20245,23565,16040,16113,16114,16115,16116,22804,14171,14172,14173,12290,12963,16858,16859,16860,16861,16862, +17815,17833,17834,17835,17836,21744,12866,12325,12863,12864,12865,12866,16194,16218,16219,16220,16221,23236,14143,14149,14151,26130,27848); + +DELETE FROM `spell_affect` WHERE `entry` IN (12945,16544,18372) AND `effectId` = 0; + +DELETE FROM `spell_affect` WHERE `entry` IN (14075,14074,14073,14072,14057,16544,23566) AND `effectId` = 1; + +INSERT INTO `spell_affect` VALUES +(14143,0,0x0000000004000206), +(14149,0,0x0000000004000206); + \ No newline at end of file diff --git a/sql/updates/6032_mangos_petcreateinfo_spell.sql b/sql/updates/6032_mangos_petcreateinfo_spell.sql new file mode 100644 index 00000000000..e7a8a67a4fa --- /dev/null +++ b/sql/updates/6032_mangos_petcreateinfo_spell.sql @@ -0,0 +1 @@ +ALTER TABLE `petcreateinfo_spell` DROP `FamilyPassive`; \ No newline at end of file diff --git a/sql/updates/6037_mangos_spell_affect.sql b/sql/updates/6037_mangos_spell_affect.sql new file mode 100644 index 00000000000..152824a2e95 --- /dev/null +++ b/sql/updates/6037_mangos_spell_affect.sql @@ -0,0 +1,7 @@ +-- (38398) Reduced Cleave Cost () +DELETE FROM `spell_affect` WHERE `entry` IN (38398); +INSERT INTO `spell_affect` VALUES (38398, 0, 0x0000000020000000); + +-- (40389) Crow Discount () +DELETE FROM `spell_affect` WHERE `entry` IN (40389); +INSERT INTO `spell_affect` VALUES (40389, 0, 0x0000800000000000); \ No newline at end of file diff --git a/sql/updates/6038_mangos_creature_template.sql b/sql/updates/6038_mangos_creature_template.sql new file mode 100644 index 00000000000..c672796b1e0 --- /dev/null +++ b/sql/updates/6038_mangos_creature_template.sql @@ -0,0 +1,2 @@ +ALTER TABLE `creature_template` + ADD COLUMN `PetSpellDataId` mediumint(8) unsigned NOT NULL default '0' AFTER `spell4`; \ No newline at end of file diff --git a/sql/updates/6047_characters_character_social.sql b/sql/updates/6047_characters_character_social.sql new file mode 100644 index 00000000000..c5ed55d942c --- /dev/null +++ b/sql/updates/6047_characters_character_social.sql @@ -0,0 +1,2 @@ +ALTER TABLE character_social + CHANGE COLUMN `note` `note` varchar(48) NOT NULL DEFAULT '' COMMENT 'Friend Note'; diff --git a/sql/updates/6047_characters_guild_bank_tab.sql b/sql/updates/6047_characters_guild_bank_tab.sql new file mode 100644 index 00000000000..d27efd2b375 --- /dev/null +++ b/sql/updates/6047_characters_guild_bank_tab.sql @@ -0,0 +1,2 @@ +ALTER TABLE guild_bank_tab + CHANGE COLUMN `TabText` `TabText` varchar(500) NOT NULL DEFAULT ''; \ No newline at end of file diff --git a/sql/updates/6049_mangos_spell_proc_event.sql b/sql/updates/6049_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..86547acc1af --- /dev/null +++ b/sql/updates/6049_mangos_spell_proc_event.sql @@ -0,0 +1,4 @@ +INSERT INTO `spell_proc_event` VALUES +(20784,0,0,0,0,0,4096,0), +(32850,0,0,0,0,0,1,0), +(34457,0,0,0,0,0,4096,0); \ No newline at end of file diff --git a/sql/updates/6052_mangos_loot_template.sql b/sql/updates/6052_mangos_loot_template.sql new file mode 100644 index 00000000000..3ecb7d1feec --- /dev/null +++ b/sql/updates/6052_mangos_loot_template.sql @@ -0,0 +1,23 @@ +ALTER TABLE `creature_loot_template` + DROP freeforall; + +ALTER TABLE `disenchant_loot_template` + DROP freeforall; + +ALTER TABLE `fishing_loot_template` + DROP freeforall; + +ALTER TABLE `gameobject_loot_template` + DROP freeforall; + +ALTER TABLE `item_loot_template` + DROP freeforall; + +ALTER TABLE `pickpocketing_loot_template` + DROP freeforall; + +ALTER TABLE `prospecting_loot_template` + DROP freeforall; + +ALTER TABLE `skinning_loot_template` + DROP freeforall; diff --git a/sql/updates/6058_mangos_spell_learn_spell.sql b/sql/updates/6058_mangos_spell_learn_spell.sql new file mode 100644 index 00000000000..33f3066da0f --- /dev/null +++ b/sql/updates/6058_mangos_spell_learn_spell.sql @@ -0,0 +1,4 @@ +DELETE FROM `spell_learn_spell` WHERE `entry` = 71; + +DELETE FROM `spell_learn_spell` WHERE `entry` = 2842; +INSERT INTO `spell_learn_spell` VALUES (2842,8681); \ No newline at end of file diff --git a/sql/updates/6061_characters_mail.sql b/sql/updates/6061_characters_mail.sql new file mode 100644 index 00000000000..8e9b0122419 --- /dev/null +++ b/sql/updates/6061_characters_mail.sql @@ -0,0 +1,2 @@ +ALTER TABLE mail + ADD COLUMN `mailTemplateId` mediumint(8) unsigned NOT NULL default '0' AFTER `stationery`; diff --git a/sql/updates/6061_mangos_quest_mail_loot_template.sql b/sql/updates/6061_mangos_quest_mail_loot_template.sql new file mode 100644 index 00000000000..e399bd23258 --- /dev/null +++ b/sql/updates/6061_mangos_quest_mail_loot_template.sql @@ -0,0 +1,13 @@ +DROP TABLE IF EXISTS `quest_mail_loot_template`; +CREATE TABLE `quest_mail_loot_template` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `item` mediumint(8) unsigned NOT NULL default '0', + `ChanceOrQuestChance` float NOT NULL default '100', + `groupid` tinyint(3) unsigned NOT NULL default '0', + `mincountOrRef` mediumint(9) NOT NULL default '1', + `maxcount` tinyint(3) unsigned NOT NULL default '1', + `lootcondition` tinyint(3) unsigned NOT NULL default '0', + `condition_value1` mediumint(8) unsigned NOT NULL default '0', + `condition_value2` mediumint(8) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`,`item`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Loot System'; diff --git a/sql/updates/6061_mangos_quest_template.sql b/sql/updates/6061_mangos_quest_template.sql new file mode 100644 index 00000000000..5e803338256 --- /dev/null +++ b/sql/updates/6061_mangos_quest_template.sql @@ -0,0 +1,3 @@ +ALTER TABLE quest_template + ADD COLUMN `RewMailTemplateId` mediumint(8) unsigned NOT NULL default '0' AFTER `RewSpellCast`, + ADD COLUMN `RewMailDelaySecs` int(11) unsigned NOT NULL default '0' AFTER `RewMailTemplateId`; diff --git a/sql/updates/6062_mangos_spell_proc_event.sql b/sql/updates/6062_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..e1ce9c86ae2 --- /dev/null +++ b/sql/updates/6062_mangos_spell_proc_event.sql @@ -0,0 +1,19 @@ +DELETE FROM spell_proc_event WHERE entry = 13743 OR entry = 13875; +DELETE FROM spell_proc_event WHERE entry = 14076 OR entry = 14094; + +UPDATE spell_proc_event SET Category = 0, SkillId = 0 WHERE entry = 12797 OR entry = 12799 OR entry = 12800; +UPDATE spell_proc_event SET Category = 0 WHERE entry = 13754 OR entry = 13867; +UPDATE spell_proc_event SET Category = 0 WHERE entry = 40458; + +UPDATE spell_proc_event SET SkillId = 0 WHERE entry = 16850 OR entry = 16923 OR entry = 16924; +UPDATE spell_proc_event SET SkillId = 0 WHERE entry = 17793 OR entry = 17796 OR entry = 17801 OR entry = 17802 OR entry = 17803; +UPDATE spell_proc_event SET SkillId = 0, SchoolMask = 0 WHERE entry = 23721; +UPDATE spell_proc_event SET SkillId = 0, SchoolMask = 0 WHERE entry = 28809; +UPDATE spell_proc_event SET SkillId = 0, SchoolMask = 0 WHERE entry = 28823; +UPDATE spell_proc_event SET SkillId = 0 WHERE entry = 23695; + +UPDATE spell_proc_event SET SchoolMask = 0, SpellFamilyMask = 0x8000000060 WHERE entry = 18073 OR entry = 18096; +UPDATE spell_proc_event SET SchoolMask = 0 WHERE entry = 19407 OR entry = 19412 OR entry = 19413 OR entry = 19414 OR entry = 19415; +UPDATE spell_proc_event SET SchoolMask = 0 WHERE entry = 20234 OR entry = 20235; +UPDATE spell_proc_event SET SchoolMask = 0 WHERE entry = 23551 OR entry = 23572; +UPDATE spell_proc_event SET SchoolMask = 0 WHERE entry = 38394; \ No newline at end of file diff --git a/sql/updates/6078_mangos_spell_proc_event.sql b/sql/updates/6078_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..19de716a443 --- /dev/null +++ b/sql/updates/6078_mangos_spell_proc_event.sql @@ -0,0 +1,7 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (20210,20212,20213,20214,20215); +INSERT INTO `spell_proc_event` VALUES +(20210,0,0,0,10,0x00010000C0000000,0x10000000,0), +(20212,0,0,0,10,0x00010000C0000000,0x10000000,0), +(20213,0,0,0,10,0x00010000C0000000,0x10000000,0), +(20214,0,0,0,10,0x00010000C0000000,0x10000000,0), +(20215,0,0,0,10,0x00010000C0000000,0x10000000,0); diff --git a/sql/updates/6090_mangos_command.sql b/sql/updates/6090_mangos_command.sql new file mode 100644 index 00000000000..34e2985b214 --- /dev/null +++ b/sql/updates/6090_mangos_command.sql @@ -0,0 +1,8 @@ +DELETE FROM `command` WHERE `name` IN ('lookup event','event','event activelist','event start','event stop'); + +INSERT INTO `command` (`name`,`security`,`help`) VALUES +('lookup event',2,'Syntax: .lookup event $name\r\nAttempts to find the ID of the event with the provided $name.'), +('event',2,'Syntax: .event #event_id\r\nShow details about event with #event_id.'), +('event activelist',2,'Syntax: .event activelist\r\nShow list of currently active events.'), +('event start',2,'Syntax: .event start #event_id\r\nStart event #event_id. Set start time for event to current moment (change not saved in DB).'), +('event stop',2,'Syntax: .event stop #event_id\r\nStop event #event_id. Set start time for event to time in past that make current moment is event stop time (change not saved in DB).'); diff --git a/sql/updates/6090_mangos_mangos_string.sql b/sql/updates/6090_mangos_mangos_string.sql new file mode 100644 index 00000000000..e9a91151da3 --- /dev/null +++ b/sql/updates/6090_mangos_mangos_string.sql @@ -0,0 +1,9 @@ +DELETE FROM `mangos_string` WHERE `entry` IN (583,584,585,586,587,588); + +INSERT INTO `mangos_string` VALUES +(583,'%d - |cffffffff|Hgameevent:%d|h[%s]|h|r%s',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(584,'No event found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(585,'Event not exist!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(586,'Event %u: %s%s\nStart: %s End: %s Occurence: %s Length: %s\nNext state change: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(587,'Event %u already active!',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(588,'Event %u not active!',NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/6151_mangos_spell_proc_event.sql b/sql/updates/6151_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..6f005b654f7 --- /dev/null +++ b/sql/updates/6151_mangos_spell_proc_event.sql @@ -0,0 +1,14 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (45444,46364); +INSERT INTO `spell_proc_event` VALUES +(45444,0,0,0,0,0x0000000000000000,0x00100402,0), +(46364,0,0,0,0,0x0000000000000000,0x00100402,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (34827); +INSERT INTO `spell_proc_event` VALUES +(34827,0,0,0,0,0x0000000000000000,0x00100402,0); + +-- Creature's Earth Shield proc on melee attacks +DELETE FROM `spell_proc_event` WHERE `entry` IN (32734); +INSERT INTO `spell_proc_event` VALUES +(32734,0,0,0,0,0x0000000000000000,0x00000002,0); + diff --git a/sql/updates/6164_mangos_command.sql b/sql/updates/6164_mangos_command.sql new file mode 100644 index 00000000000..a55ddd89b03 --- /dev/null +++ b/sql/updates/6164_mangos_command.sql @@ -0,0 +1,4 @@ +DELETE FROM `command` WHERE `name` IN ('gm fly'); + +INSERT INTO `command` (`name`,`security`,`help`) VALUES +('gm fly',3,'Syntax: .gm fly on/off\r\nEnable/disable gm fly mode.'); diff --git a/sql/updates/6171_mangos_spell_affect.sql b/sql/updates/6171_mangos_spell_affect.sql new file mode 100644 index 00000000000..62cb9c4d385 --- /dev/null +++ b/sql/updates/6171_mangos_spell_affect.sql @@ -0,0 +1,56 @@ +DELETE FROM spell_affect WHERE (entry = 16757 OR entry = 16758) AND effectId = 1; +INSERT INTO spell_affect ( `entry` , `effectId` , `SpellFamilyMask` ) +VALUES ( +16757, 1, 0x240 +), ( +16758, 1, 0x240 +); +DELETE FROM spell_affect WHERE (entry = 17904 OR (entry >= 17912 AND entry <= 17916)) AND effectId = 0; +INSERT INTO spell_affect ( `entry` , `effectId` , `SpellFamilyMask` ) +VALUES ( +17904, 0, 0 +), ( +17912, 0, 0 +), ( +17913, 0, 0 +), ( +17914, 0, 0 +), ( +17915, 0, 0 +), ( +17916, 0, 0 +); +DELETE FROM spell_affect WHERE entry = 21899 AND effectId = 0; +INSERT INTO spell_affect ( `entry` , `effectId` , `SpellFamilyMask` ) +VALUES ( +21899, 0, 0x100 +); +DELETE FROM spell_affect WHERE entry = 24542 AND effectId = 1; +INSERT INTO spell_affect ( `entry` , `effectId` , `SpellFamilyMask` ) +VALUES ( +24542, 1, 0xF0 +); +DELETE FROM spell_affect WHERE entry = 24546 AND effectId = 1; +INSERT INTO spell_affect ( `entry` , `effectId` , `SpellFamilyMask` ) +VALUES ( +24546, 1, 0x400041E00 +); +DELETE FROM spell_affect WHERE (entry = 29187 OR entry = 29189 OR entry = 29191) AND effectId = 1; +INSERT INTO spell_affect ( `entry` , `effectId` , `SpellFamilyMask` ) +VALUES ( +29187, 1, 0x4103000340750 +), ( +29189, 1, 0x4103000340750 +), ( +29191, 1, 0x4103000340750 +); +DELETE FROM spell_affect WHERE entry = 39805 AND effectId = 1; +INSERT INTO spell_affect ( `entry` , `effectId` , `SpellFamilyMask` ) +VALUES ( +39805, 1, 0x3 +); +DELETE FROM spell_affect WHERE entry = 44293 AND effectId = 0; +INSERT INTO spell_affect ( `entry` , `effectId` , `SpellFamilyMask` ) +VALUES ( +44293, 0, 0x200 +); \ No newline at end of file diff --git a/sql/updates/6179_mangos_mangos_string.sql b/sql/updates/6179_mangos_mangos_string.sql new file mode 100644 index 00000000000..1cb1ea7c0a9 --- /dev/null +++ b/sql/updates/6179_mangos_mangos_string.sql @@ -0,0 +1,6 @@ +DELETE FROM `mangos_string` WHERE `entry` IN (589,590,591); + +INSERT INTO `mangos_string` VALUES +(589,' Point movement to (X:%f Y:%f Z:%f)',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(590,' Fear movement',NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(591,' Distract movement',NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/6193_mangos_spell_proc_event.sql b/sql/updates/6193_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..98df85ab6b6 --- /dev/null +++ b/sql/updates/6193_mangos_spell_proc_event.sql @@ -0,0 +1,12 @@ + +DELETE FROM `spell_proc_event` WHERE `entry` IN (39442,39438,39440,39444); +INSERT INTO `spell_proc_event` VALUES +(39442,0,0,0,0,0x0000000000000000,0x00020001,0), +(39438,0,0,0,0,0x0000000000000000,0x00080001,0), +(39440,0,0,0,0,0x0000000000000000,0x00020000,0), +(39444,0,0,0,0,0x0000000000000000,0x00100002,0); + +DELETE FROM `spell_proc_event` WHERE `entry` IN (36111,39443); +INSERT INTO `spell_proc_event` VALUES +(36111,0,0,0,0,0x0000000000000000,0x00000001,0), +(39443,0,0,0,0,0x0000000000000000,0x00401000,0); diff --git a/sql/updates/6199_mangos_spell_proc_event.sql b/sql/updates/6199_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..d4526446be7 --- /dev/null +++ b/sql/updates/6199_mangos_spell_proc_event.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (32748); +INSERT INTO `spell_proc_event` VALUES +(32748,0,0,0,8,0x0000000100000000,0x00080000,0); diff --git a/sql/updates/6210_mangos_spell_proc_event.sql b/sql/updates/6210_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..0ca6f9bd3f6 --- /dev/null +++ b/sql/updates/6210_mangos_spell_proc_event.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (38299); +INSERT INTO `spell_proc_event` VALUES +(38299,0,0,0,0,0x0000000000000000,0x08000000,0); diff --git a/sql/updates/6213_mangos_spell_target_position.sql b/sql/updates/6213_mangos_spell_target_position.sql new file mode 100644 index 00000000000..c175e4170bb --- /dev/null +++ b/sql/updates/6213_mangos_spell_target_position.sql @@ -0,0 +1 @@ +RENAME TABLE `spell_teleport` TO `spell_target_position`; diff --git a/sql/updates/6219_mangos_spell_proc_event.sql b/sql/updates/6219_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..d8fd9740df9 --- /dev/null +++ b/sql/updates/6219_mangos_spell_proc_event.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (44835); +INSERT INTO `spell_proc_event` VALUES +(44835,0,0,0,7,0x0000008000000000,0x00000001,0); diff --git a/sql/updates/6246_mangos_spell_proc_event.sql b/sql/updates/6246_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..8dc2c5cecd3 --- /dev/null +++ b/sql/updates/6246_mangos_spell_proc_event.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (38290); +INSERT INTO `spell_proc_event` VALUES +(38290,0,0,0,0,0x0000000000000000,0x00080000,3); diff --git a/sql/updates/6251_mangos_spell_proc_event.sql b/sql/updates/6251_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..81d54f921e9 --- /dev/null +++ b/sql/updates/6251_mangos_spell_proc_event.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_proc_event` WHERE `entry` = 37336; +INSERT INTO `spell_proc_event` VALUES +(37336,0,0,0,0,0x0000000000000000,0x00084001,0); diff --git a/sql/updates/6255_mangos_spell_proc_event.sql b/sql/updates/6255_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..184bf953a2d --- /dev/null +++ b/sql/updates/6255_mangos_spell_proc_event.sql @@ -0,0 +1,15 @@ +DELETE FROM `spell_proc_event` WHERE `entry` = 40442; +INSERT INTO `spell_proc_event` VALUES +(40442,0,0,0,7,0x0000044000000014,0x00004001,0); + +DELETE FROM `spell_proc_event` WHERE `entry` = 40470; +INSERT INTO `spell_proc_event` VALUES +(40470,0,0,0,10,0x00000000C0800000,0x00004000,0); + +DELETE FROM `spell_proc_event` WHERE `entry` = 40485; +INSERT INTO `spell_proc_event` VALUES +(40485,0,0,0,9,0x0000000100000000,0x00080000,0); + +DELETE FROM `spell_proc_event` WHERE `entry` = 40478; +INSERT INTO `spell_proc_event` VALUES +(40478,0,0,0,5,0x0000000000000002,0x00020000,0); diff --git a/sql/updates/6265_mangos_pet_name_generation.sql b/sql/updates/6265_mangos_pet_name_generation.sql new file mode 100644 index 00000000000..45045d2912e --- /dev/null +++ b/sql/updates/6265_mangos_pet_name_generation.sql @@ -0,0 +1,270 @@ +DROP TABLE IF EXISTS `pet_name_generation`; +CREATE TABLE `pet_name_generation` ( + `id` mediumint(8) unsigned NOT NULL auto_increment, + `word` tinytext NOT NULL, + `entry` mediumint(8) unsigned NOT NULL default '0', + `half` tinyint(4) NOT NULL default '0', + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +INSERT INTO `pet_name_generation` (`word`,`entry`,`half`) VALUES +('Aba',416,0), +('Az',416,0), +('Bel',416,0), +('Biz',416,0), +('Cho',416,0), +('Dag',416,0), +('Gak',416,0), +('Gar',416,0), +('Gel',416,0), +('Gho',416,0), +('Gob',416,0), +('Gra',416,0), +('Jak',416,0), +('Jub',416,0), +('Kar',416,0), +('Kup',416,0), +('Laz',416,0), +('Nal',416,0), +('Nok',416,0), +('Pag',416,0), +('Pig',416,0), +('Pip',416,0), +('Piz',416,0), +('Quz',416,0), +('Rui',416,0), +('Rul',416,0), +('Rup',416,0), +('Tar',416,0), +('Vol',416,0), +('Yaz',416,0), +('Zep',416,0), +('Zig',416,0), +('Zil',416,0), +('Zor',416,0), +('bis',416,1), +('fip',416,1), +('gup',416,1), +('ham',416,1), +('jub',416,1), +('kin',416,1), +('kol',416,1), +('lop',416,1), +('loz',416,1), +('mat',416,1), +('mir',416,1), +('nam',416,1), +('nar',416,1), +('nik',416,1), +('nip',416,1), +('pad',416,1), +('pep',416,1), +('pit',416,1), +('qua',416,1), +('rai',416,1), +('rin',416,1), +('rot',416,1), +('tai',416,1), +('tal',416,1), +('tik',416,1), +('tip',416,1), +('tog',416,1), +('tuk',416,1), +('uri',416,1), +('yal',416,1), +('yap',416,1), +('Bhee',417,0), +('Bruu',417,0), +('Czaa',417,0), +('Droo',417,0), +('Flaa',417,0), +('Fzuu',417,0), +('Ghaa',417,0), +('Gree',417,0), +('Gzaa',417,0), +('Haa',417,0), +('Haad',417,0), +('Haag',417,0), +('Haap',417,0), +('Jhaa',417,0), +('Jhuu',417,0), +('Khaa',417,0), +('Khii',417,0), +('Khuu',417,0), +('Kree',417,0), +('Luu',417,0), +('Maa',417,0), +('Nhee',417,0), +('Phuu',417,0), +('Pryy',417,0), +('Rhuu',417,0), +('Shaa',417,0), +('Sloo',417,0), +('Sruu',417,0), +('Thoo',417,0), +('Traa',417,0), +('Wraa',417,0), +('Zhaa',417,0), +('dhon',417,1), +('dhum',417,1), +('dhun',417,1), +('dom',417,1), +('don',417,1), +('drom',417,1), +('dym',417,1), +('fenn',417,1), +('fum',417,1), +('fun',417,1), +('ghon',417,1), +('ghun',417,1), +('grom',417,1), +('grym',417,1), +('hom',417,1), +('hon',417,1), +('hun',417,1), +('jhom',417,1), +('kun',417,1), +('lum',417,1), +('mmon',417,1), +('mon',417,1), +('myn',417,1), +('nam',417,1), +('nem',417,1), +('nhym',417,1), +('nom',417,1), +('num',417,1), +('phom',417,1), +('roon',417,1), +('rym',417,1), +('shon',417,1), +('thun',417,1), +('tom',417,1), +('zhem',417,1), +('zhum',417,1), +('zun',417,1), +('Bar',1860,0), +('Bel',1860,0), +('Char',1860,0), +('Grak\'',1860,0), +('Graz\'',1860,0), +('Grim',1860,0), +('Hath',1860,0), +('Hel',1860,0), +('Hok',1860,0), +('Huk',1860,0), +('Jhaz',1860,0), +('Jhom',1860,0), +('Juk\'',1860,0), +('Kal\'',1860,0), +('Klath',1860,0), +('Kon',1860,0), +('Krag',1860,0), +('Krak',1860,0), +('Mak',1860,0), +('Mezz',1860,0), +('Orm',1860,0), +('Phan',1860,0), +('Sar',1860,0), +('Tang',1860,0), +('Than',1860,0), +('Thog',1860,0), +('Thok',1860,0), +('Thul',1860,0), +('Zag\'',1860,0), +('Zang',1860,0), +('Zhar\'',1860,0), +('kath',1860,1), +('doc',1860,1), +('dok',1860,1), +('gak',1860,1), +('garth',1860,1), +('gore',1860,1), +('gorg',1860,1), +('grave',1860,1), +('gron',1860,1), +('juk',1860,1), +('krast',1860,1), +('kresh',1860,1), +('krit',1860,1), +('los',1860,1), +('mon',1860,1), +('mos',1860,1), +('moth',1860,1), +('nagma',1860,1), +('nak',1860,1), +('nar',1860,1), +('nos',1860,1), +('nuz',1860,1), +('phog',1860,1), +('rath',1860,1), +('tast',1860,1), +('taz',1860,1), +('thak',1860,1), +('thang',1860,1), +('thyk',1860,1), +('vhug',1860,1), +('zazt',1860,1), +('Ael',1863,0), +('Aez',1863,0), +('Ang',1863,0), +('Ban',1863,0), +('Bet',1863,0), +('Bro',1863,0), +('Bry',1863,0), +('Cat',1863,0), +('Dir',1863,0), +('Dis',1863,0), +('Dom',1863,0), +('Drus',1863,0), +('Fie',1863,0), +('Fier',1863,0), +('Gly',1863,0), +('Hel',1863,0), +('Hes',1863,0), +('Kal',1863,0), +('Lyn',1863,0), +('Mir',1863,0), +('Nim',1863,0), +('Sar',1863,0), +('Sel',1863,0), +('Vil',1863,0), +('Zah',1863,0), +('aith',1863,1), +('anda',1863,1), +('antia',1863,1), +('evere',1863,1), +('lia',1863,1), +('lissa',1863,1), +('neri',1863,1), +('neth',1863,1), +('nia',1863,1), +('nlissa',1863,1), +('nora',1863,1), +('nva',1863,1), +('nys',1863,1), +('ola',1863,1), +('ona',1863,1), +('ora',1863,1), +('rah',1863,1), +('riana',1863,1), +('riel',1863,1), +('rona',1863,1), +('tai',1863,1), +('tevere',1863,1), +('thea',1863,1), +('vina',1863,1), +('wena',1863,1), +('wyn',1863,1), +('xia',1863,1), +('yla',1863,1), +('yssa',1863,1), +('Flaa',17252,0), +('Haa',17252,0), +('Jhuu',17252,0), +('Shaa',17252,0), +('Thoo',17252,0), +('dhun',17252,1), +('ghun',17252,1), +('roon',17252,1), +('thun',17252,1), +('tom',17252,1); diff --git a/sql/updates/6270_mangos_spell_proc_event.sql b/sql/updates/6270_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..a92da067bda --- /dev/null +++ b/sql/updates/6270_mangos_spell_proc_event.sql @@ -0,0 +1,4 @@ +DELETE FROM `spell_proc_event` WHERE `entry` in (31569,31570); +INSERT INTO `spell_proc_event` VALUES +(31569,0,0,0,3,0x0000000000010000,0x00004000,0), +(31570,0,0,0,3,0x0000000000010000,0x00004000,0); diff --git a/sql/updates/6291_characters_character_pet.sql b/sql/updates/6291_characters_character_pet.sql new file mode 100644 index 00000000000..f6506595312 --- /dev/null +++ b/sql/updates/6291_characters_character_pet.sql @@ -0,0 +1 @@ +ALTER TABLE `character_pet` DROP COLUMN `Commandstate`; \ No newline at end of file diff --git a/sql/updates/6297_characters_characters.sql b/sql/updates/6297_characters_characters.sql new file mode 100644 index 00000000000..0072d8345fc --- /dev/null +++ b/sql/updates/6297_characters_characters.sql @@ -0,0 +1,4 @@ +ALTER TABLE characters + CHANGE `logout_time` `logout_time` bigint(20) unsigned NOT NULL default '0', + DROP `last_honor_date`, + DROP `last_kill_date`; diff --git a/sql/updates/6298_characters_characters.sql b/sql/updates/6298_characters_characters.sql new file mode 100644 index 00000000000..55485470a03 --- /dev/null +++ b/sql/updates/6298_characters_characters.sql @@ -0,0 +1,2 @@ +ALTER TABLE characters + ADD COLUMN death_expire_time bigint(20) unsigned NOT NULL default '0' AFTER zone; diff --git a/sql/updates/6298_characters_corpse.sql b/sql/updates/6298_characters_corpse.sql new file mode 100644 index 00000000000..0cb34d26be3 --- /dev/null +++ b/sql/updates/6298_characters_corpse.sql @@ -0,0 +1,9 @@ +ALTER TABLE corpse + CHANGE time time_old timestamp NOT NULL default '0000-00-00 00:00:00', + ADD COLUMN time bigint(20) unsigned NOT NULL default '0' AFTER data; + +UPDATE corpse + SET time = UNIX_TIMESTAMP(time_old); + +ALTER TABLE corpse + DROP time_old; diff --git a/sql/updates/6304_mangos_spell_proc_event.sql b/sql/updates/6304_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..02a8e57cd1f --- /dev/null +++ b/sql/updates/6304_mangos_spell_proc_event.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_proc_event` WHERE `entry` = 45059; +INSERT INTO `spell_proc_event` VALUES +(45059,0,0,0,0,0x0000000000000000,0x08000000,0); diff --git a/sql/updates/6308_mangos_command.sql b/sql/updates/6308_mangos_command.sql new file mode 100644 index 00000000000..9fb1fb423ba --- /dev/null +++ b/sql/updates/6308_mangos_command.sql @@ -0,0 +1,4 @@ +DELETE FROM `command` WHERE `name` IN ('combatstop'); + +INSERT INTO `command` (`name`,`security`,`help`) VALUES +('combatstop',2,'Syntax: .combatstop\r\nStop combat for selected character. If selected non-player then command applied to self.'); diff --git a/sql/updates/6313_mangos_spell_proc_event.sql b/sql/updates/6313_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..164075c2298 --- /dev/null +++ b/sql/updates/6313_mangos_spell_proc_event.sql @@ -0,0 +1,12 @@ +DELETE FROM spell_proc_event WHERE entry IN (37982, 37617, 37213, 37237, 37228); +INSERT INTO spell_proc_event VALUES +-- Earthstun (Brutal Earthstorm-Diamond) +(37982,0,0,0,0,0x0000000000000000,0x00000001,0), +-- Desolation Battlegear 4 pieces +(37617,0,0,0,0,0x0000000000000000,0x00000001,0), +-- Shaman Nuker T4 3 pieces +(37213,0,0,0,11,0x0000000090100007,0x00010000,0), +-- Shaman Nuker T5 4 pieces +(37237,0,0,0,11,0x0000000000000001,0x00010000,0), +-- Shaman Nuker T5 2 pieces +(37228,0,0,0,11,0x0000000090100007,0x00020000,0); diff --git a/sql/updates/6314_mangos_command.sql b/sql/updates/6314_mangos_command.sql new file mode 100644 index 00000000000..c76561ba7ee --- /dev/null +++ b/sql/updates/6314_mangos_command.sql @@ -0,0 +1,4 @@ +DELETE FROM `command` WHERE `name` IN ('combatstop'); + +INSERT INTO `command` (`name`,`security`,`help`) VALUES +('combatstop',2,'Syntax: .combatstop [$playername]\r\nStop combat for selected character. If selected non-player then command applied to self. If $playername provided then attempt applied to online player $playername.'); diff --git a/sql/updates/6324_mangos_creature_template.sql b/sql/updates/6324_mangos_creature_template.sql new file mode 100644 index 00000000000..84a053e0278 --- /dev/null +++ b/sql/updates/6324_mangos_creature_template.sql @@ -0,0 +1 @@ +ALTER TABLE `creature_template` ADD COLUMN `flags_extra` int(10) unsigned NOT NULL default '0' after `mechanic_immune_mask`; \ No newline at end of file diff --git a/sql/updates/6325_mangos_creature_template.sql b/sql/updates/6325_mangos_creature_template.sql new file mode 100644 index 00000000000..9b47f8b9236 --- /dev/null +++ b/sql/updates/6325_mangos_creature_template.sql @@ -0,0 +1,5 @@ +UPDATE creature_template + SET flags_extra = flags_extra | 2 WHERE civilian <> 0; + +ALTER TABLE `creature_template` + DROP civilian; diff --git a/sql/updates/6326_characters_corpse.sql b/sql/updates/6326_characters_corpse.sql new file mode 100644 index 00000000000..0ff3d368e76 --- /dev/null +++ b/sql/updates/6326_characters_corpse.sql @@ -0,0 +1,8 @@ +ALTER TABLE corpse + ADD COLUMN corpse_type tinyint(3) unsigned NOT NULL default '0' AFTER bones_flag; + +UPDATE corpse + SET corpse_type = 1 WHERE bones_flag = 0; + +ALTER TABLE corpse + DROP bones_flag; diff --git a/sql/updates/6334_mangos_spell_affect.sql b/sql/updates/6334_mangos_spell_affect.sql new file mode 100644 index 00000000000..215a04d5cd2 --- /dev/null +++ b/sql/updates/6334_mangos_spell_affect.sql @@ -0,0 +1,8 @@ +DELETE FROM spell_affect WHERE entry = 34491 AND effectId = 0 LIMIT 1; +DELETE FROM spell_affect WHERE entry = 34492 AND effectId = 0 LIMIT 1; +DELETE FROM spell_affect WHERE entry = 34493 AND effectId = 0 LIMIT 1; + +INSERT INTO spell_affect ( entry , effectId , SpellFamilyMask ) VALUES +(34491, 0, 0x4000000000C2), +(34492, 0, 0x4000000000C2), +(34493, 0, 0x4000000000C2); \ No newline at end of file diff --git a/sql/updates/6335_characters_corpse.sql b/sql/updates/6335_characters_corpse.sql new file mode 100644 index 00000000000..ae1c6abfeec --- /dev/null +++ b/sql/updates/6335_characters_corpse.sql @@ -0,0 +1,5 @@ +ALTER TABLE corpse + ADD KEY idx_type (corpse_type); + +UPDATE corpse + SET corpse_type = 1 WHERE corpse_type = 2; diff --git a/sql/updates/6351_mangos_spell_proc_event.sql b/sql/updates/6351_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..37e3c84b014 --- /dev/null +++ b/sql/updates/6351_mangos_spell_proc_event.sql @@ -0,0 +1,19 @@ +DELETE FROM spell_proc_event WHERE entry IN (17364); +INSERT INTO spell_proc_event VALUES +(17364,0,0,0,0,0x0000000000000000,0x00008000,0); + +DELETE FROM spell_proc_event WHERE entry IN (17794, 17797, 17798, 17799, 17800); +INSERT INTO spell_proc_event VALUES +(17794,0,0,0,0,0x0000000000000000,0x00008000,0), +(17797,0,0,0,0,0x0000000000000000,0x00008000,0), +(17798,0,0,0,0,0x0000000000000000,0x00008000,0), +(17799,0,0,0,0,0x0000000000000000,0x00008000,0), +(17800,0,0,0,0,0x0000000000000000,0x00008000,0); + +DELETE FROM spell_proc_event WHERE entry IN (43823); +INSERT INTO spell_proc_event VALUES +(43823,0,0,0,0,0x0000000000000000,0x00008000,0); + +DELETE FROM spell_proc_event WHERE entry IN (36576); +INSERT INTO spell_proc_event VALUES +(36576,0,0,0,0,0x0000000000000000,0x00008000,0); diff --git a/sql/updates/6360_characters_characters.sql b/sql/updates/6360_characters_characters.sql new file mode 100644 index 00000000000..405682074eb --- /dev/null +++ b/sql/updates/6360_characters_characters.sql @@ -0,0 +1,6 @@ +UPDATE characters SET data = REPLACE(data,' ',' '); +UPDATE characters SET data = CONCAT(TRIM(data),' '); + +UPDATE characters +SET data=CONCAT(SUBSTRING_INDEX(SUBSTRING_INDEX(data,' ',1396),' ',-1396),' ','0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0',' ',SUBSTRING_INDEX(SUBSTRING_INDEX(data,' ',1529),' ',-133)) +WHERE SUBSTRING_INDEX(data,' ',1528) = data AND SUBSTRING_INDEX(data,' ',1527) <> data; diff --git a/sql/updates/6360_characters_corpse.sql b/sql/updates/6360_characters_corpse.sql new file mode 100644 index 00000000000..d841522a10e --- /dev/null +++ b/sql/updates/6360_characters_corpse.sql @@ -0,0 +1,6 @@ +UPDATE corpse SET data = REPLACE(data,' ',' '); +UPDATE corpse SET data = CONCAT(TRIM(data),' '); + +UPDATE corpse +SET data=CONCAT(SUBSTRING_INDEX(SUBSTRING_INDEX(`data`,' ',8),' ',-8),' ','0 0',' ',SUBSTRING_INDEX(SUBSTRING_INDEX(data,' ',39),' ',-31)) +WHERE SUBSTRING_INDEX(data,' ',38) = data AND SUBSTRING_INDEX(data,' ',37) <> data; diff --git a/sql/updates/6362_characters.sql b/sql/updates/6362_characters.sql new file mode 100644 index 00000000000..761a6ce4c65 --- /dev/null +++ b/sql/updates/6362_characters.sql @@ -0,0 +1,34 @@ +TRUNCATE `character_instance`; +TRUNCATE `instance`; + +ALTER TABLE `character_instance` + DROP KEY `leader`, + DROP PRIMARY KEY, + ADD PRIMARY KEY `guid` (`guid`,`instance`), + DROP COLUMN `map`, + DROP COLUMN `leader`, + MODIFY COLUMN `instance` int(11) unsigned NOT NULL default '0', + ADD COLUMN `permanent` tinyint(1) unsigned NOT NULL default '0'; + +ALTER TABLE `instance` + ADD COLUMN `difficulty` tinyint(1) unsigned NOT NULL default '0' AFTER `resettime`; + +CREATE TABLE `group_instance` ( + `leaderGuid` int(11) unsigned NOT NULL default '0', + `instance` int(11) unsigned NOT NULL default '0', + `permanent` tinyint(1) unsigned NOT NULL default '0', + PRIMARY KEY (`leaderGuid`,`instance`), + KEY `instance` (`instance`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE `instance_reset` ( + `mapid` int(11) unsigned NOT NULL default '0', + `resettime` bigint(40) NOT NULL default '0', + PRIMARY KEY (`mapid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +ALTER TABLE `groups` + ADD COLUMN `difficulty` tinyint(3) unsigned NOT NULL default '0' AFTER `isRaid`; + +ALTER TABLE `characters` + ADD COLUMN `dungeon_difficulty` tinyint(1) unsigned NOT NULL DEFAULT '0' AFTER `map`; \ No newline at end of file diff --git a/sql/updates/6362_mangos_instance_template.sql b/sql/updates/6362_mangos_instance_template.sql new file mode 100644 index 00000000000..f8f4f3c46bb --- /dev/null +++ b/sql/updates/6362_mangos_instance_template.sql @@ -0,0 +1 @@ +UPDATE `instance_template` SET `reset_delay` = 0; \ No newline at end of file diff --git a/sql/updates/6367_mangos_spell_proc_event.sql b/sql/updates/6367_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..f853306343a --- /dev/null +++ b/sql/updates/6367_mangos_spell_proc_event.sql @@ -0,0 +1 @@ +DELETE FROM spell_proc_event WHERE entry IN (33280,35092,35093,35094); diff --git a/sql/updates/6369_mangos_spell_affect.sql b/sql/updates/6369_mangos_spell_affect.sql new file mode 100644 index 00000000000..0d51c00d120 --- /dev/null +++ b/sql/updates/6369_mangos_spell_affect.sql @@ -0,0 +1 @@ +DELETE FROM spell_affect WHERE entry = 16824; diff --git a/sql/updates/6370_mangos_spell_affect.sql b/sql/updates/6370_mangos_spell_affect.sql new file mode 100644 index 00000000000..460c6141814 --- /dev/null +++ b/sql/updates/6370_mangos_spell_affect.sql @@ -0,0 +1,4 @@ +DELETE FROM spell_affect WHERE entry = 8875 AND effectId = 1 LIMIT 1; + +INSERT INTO spell_affect ( entry , effectId , SpellFamilyMask ) VALUES +(8875, 1, 0x40000000000); diff --git a/sql/updates/6381_mangos_command.sql b/sql/updates/6381_mangos_command.sql new file mode 100644 index 00000000000..13414b6c33b --- /dev/null +++ b/sql/updates/6381_mangos_command.sql @@ -0,0 +1,4 @@ +DELETE FROM `command` WHERE `name` IN ('quest complete'); + +INSERT INTO `command` (`name`,`security`,`help`) VALUES +('quest complete',3,'Syntax: .quest complete #questid\r\nMark all quest objectives as completed for target character active quest. After this target character can go and get quest reward.'); diff --git a/sql/updates/6387_characters_character_ticket.sql b/sql/updates/6387_characters_character_ticket.sql new file mode 100644 index 00000000000..72466ee7a53 --- /dev/null +++ b/sql/updates/6387_characters_character_ticket.sql @@ -0,0 +1,2 @@ +ALTER TABLE `character_ticket` + DROP `ticket_category`; diff --git a/sql/updates/6387_mangos_mangos_string.sql b/sql/updates/6387_mangos_mangos_string.sql new file mode 100644 index 00000000000..9216cb92240 --- /dev/null +++ b/sql/updates/6387_mangos_mangos_string.sql @@ -0,0 +1,3 @@ +DELETE FROM mangos_string WHERE entry = 290; +INSERT INTO mangos_string VALUES (290, 'Ticket of %s (Last updated: %s):\n%s', NULL, NULL, NULL, NULL, NULL, NULL, NULL); + diff --git a/sql/updates/6397_mangos_creature_template.sql b/sql/updates/6397_mangos_creature_template.sql new file mode 100644 index 00000000000..7bd062f2184 --- /dev/null +++ b/sql/updates/6397_mangos_creature_template.sql @@ -0,0 +1 @@ +UPDATE creature_template SET flags_extra = flags_extra | 1 WHERE rank = 3; \ No newline at end of file diff --git a/sql/updates/6398_mangos_creature_template.sql b/sql/updates/6398_mangos_creature_template.sql new file mode 100644 index 00000000000..0a1b41cc23b --- /dev/null +++ b/sql/updates/6398_mangos_creature_template.sql @@ -0,0 +1,2 @@ +ALTER TABLE `creature_template` + ADD COLUMN `heroic_entry` mediumint(8) unsigned NOT NULL default '0' AFTER entry; diff --git a/sql/updates/6412_characters_declinedname.sql b/sql/updates/6412_characters_declinedname.sql new file mode 100644 index 00000000000..50bf21f452d --- /dev/null +++ b/sql/updates/6412_characters_declinedname.sql @@ -0,0 +1,24 @@ +DROP TABLE IF EXISTS `character_declinedname`; +CREATE TABLE `character_declinedname` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `genitive` varchar(12) NOT NULL default '', + `dative` varchar(12) NOT NULL default '', + `accusative` varchar(12) NOT NULL default '', + `instrumental` varchar(12) NOT NULL default '', + `prepositional` varchar(12) NOT NULL default '', + PRIMARY KEY (`guid`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC; + +DROP TABLE IF EXISTS `character_pet_declinedname`; +CREATE TABLE `character_pet_declinedname` ( + `id` int(11) unsigned NOT NULL default '0', + `owner` int(11) unsigned NOT NULL default '0', + `genitive` varchar(12) NOT NULL default '', + `dative` varchar(12) NOT NULL default '', + `accusative` varchar(12) NOT NULL default '', + `instrumental` varchar(12) NOT NULL default '', + `prepositional` varchar(12) NOT NULL default '', + PRIMARY KEY (`id`), + KEY owner_key (`owner`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC; + diff --git a/sql/updates/6426_mangos_locales.sql b/sql/updates/6426_mangos_locales.sql new file mode 100644 index 00000000000..0424eaa8e28 --- /dev/null +++ b/sql/updates/6426_mangos_locales.sql @@ -0,0 +1,87 @@ + +ALTER TABLE locales_creature + ADD COLUMN name_loc8 varchar(100) NOT NULL default '' AFTER name_loc7, + ADD COLUMN subname_loc8 varchar(100) default NULL AFTER subname_loc7; + +UPDATE locales_creature SET name_loc8 = name_loc7, subname_loc8 = subname_loc7; + +ALTER TABLE locales_gameobject + ADD COLUMN name_loc8 varchar(100) NOT NULL default '' AFTER name_loc7, + ADD COLUMN castbarcaption_loc8 varchar(100) NOT NULL default '' AFTER castbarcaption_loc7; + +UPDATE locales_gameobject SET name_loc8 = name_loc7, castbarcaption_loc8 = castbarcaption_loc7; + +ALTER TABLE locales_item + ADD COLUMN name_loc8 varchar(100) NOT NULL default '' AFTER name_loc7, + ADD COLUMN description_loc8 varchar(255) default NULL AFTER description_loc7; + +UPDATE locales_item SET name_loc8 = name_loc7, description_loc8 = description_loc7; + +ALTER TABLE locales_page_text + ADD COLUMN Text_loc8 longtext AFTER Text_loc7; + +UPDATE locales_page_text SET Text_loc8 = Text_loc7; + +ALTER TABLE locales_quest + ADD COLUMN Title_loc8 text AFTER Title_loc7, + ADD COLUMN Details_loc8 text AFTER Details_loc7, + ADD COLUMN Objectives_loc8 text AFTER Objectives_loc7, + ADD COLUMN OfferRewardText_loc8 text AFTER OfferRewardText_loc7, + ADD COLUMN RequestItemsText_loc8 text AFTER RequestItemsText_loc7, + ADD COLUMN EndText_loc8 text AFTER EndText_loc7, + ADD COLUMN ObjectiveText1_loc8 text AFTER ObjectiveText1_loc7, + ADD COLUMN ObjectiveText2_loc8 text AFTER ObjectiveText2_loc7, + ADD COLUMN ObjectiveText3_loc8 text AFTER ObjectiveText3_loc7, + ADD COLUMN ObjectiveText4_loc8 text AFTER ObjectiveText4_loc7; + +UPDATE locales_quest SET Title_loc8 = Title_loc7, + Details_loc8 = Details_loc7, + Objectives_loc8 = Objectives_loc7, + OfferRewardText_loc8 = OfferRewardText_loc7, + RequestItemsText_loc8 = RequestItemsText_loc7, + EndText_loc8 = EndText_loc7, + ObjectiveText1_loc8 = ObjectiveText1_loc7, + ObjectiveText2_loc8 = ObjectiveText2_loc7, + ObjectiveText3_loc8 = ObjectiveText3_loc7, + ObjectiveText4_loc8 = ObjectiveText4_loc7; + +ALTER TABLE locales_npc_text + ADD COLUMN Text0_0_loc8 longtext AFTER Text0_0_loc7, + ADD COLUMN Text0_1_loc8 longtext AFTER Text0_1_loc7, + ADD COLUMN Text1_0_loc8 longtext AFTER Text1_0_loc7, + ADD COLUMN Text1_1_loc8 longtext AFTER Text1_1_loc7, + ADD COLUMN Text2_0_loc8 longtext AFTER Text2_0_loc7, + ADD COLUMN Text2_1_loc8 longtext AFTER Text2_1_loc7, + ADD COLUMN Text3_0_loc8 longtext AFTER Text3_0_loc7, + ADD COLUMN Text3_1_loc8 longtext AFTER Text3_1_loc7, + ADD COLUMN Text4_0_loc8 longtext AFTER Text4_0_loc7, + ADD COLUMN Text4_1_loc8 longtext AFTER Text4_1_loc7, + ADD COLUMN Text5_0_loc8 longtext AFTER Text5_0_loc7, + ADD COLUMN Text5_1_loc8 longtext AFTER Text5_1_loc7, + ADD COLUMN Text6_0_loc8 longtext AFTER Text6_0_loc7, + ADD COLUMN Text6_1_loc8 longtext AFTER Text6_1_loc7, + ADD COLUMN Text7_0_loc8 longtext AFTER Text7_0_loc7, + ADD COLUMN Text7_1_loc8 longtext AFTER Text7_1_loc7; + +UPDATE locales_npc_text SET Text0_0_loc8 = Text0_0_loc7, + Text0_1_loc8 = Text0_1_loc7, + Text1_0_loc8 = Text1_0_loc7, + Text1_1_loc8 = Text1_1_loc7, + Text2_0_loc8 = Text2_0_loc7, + Text2_1_loc8 = Text2_1_loc7, + Text3_0_loc8 = Text3_0_loc7, + Text3_1_loc8 = Text3_1_loc7, + Text4_0_loc8 = Text4_0_loc7, + Text4_1_loc8 = Text4_1_loc7, + Text5_0_loc8 = Text5_0_loc7, + Text5_1_loc8 = Text5_1_loc7, + Text6_0_loc8 = Text6_0_loc7, + Text6_1_loc8 = Text6_1_loc7, + Text7_0_loc8 = Text7_0_loc7, + Text7_1_loc8 = Text7_1_loc7; + +ALTER TABLE mangos_string + ADD COLUMN content_loc8 text AFTER content_loc7; + +UPDATE mangos_string SET content_loc8 = content_loc7; + diff --git a/sql/updates/6426_realmd_localization.sql b/sql/updates/6426_realmd_localization.sql new file mode 100644 index 00000000000..40cd288b87d --- /dev/null +++ b/sql/updates/6426_realmd_localization.sql @@ -0,0 +1 @@ +DROP TABLE localization; diff --git a/sql/updates/6431_mangos_mangos_string.sql b/sql/updates/6431_mangos_mangos_string.sql new file mode 100644 index 00000000000..27d3e2b26a8 --- /dev/null +++ b/sql/updates/6431_mangos_mangos_string.sql @@ -0,0 +1,5 @@ +DELETE FROM mangos_string WHERE entry IN (518,521); +INSERT INTO mangos_string VALUES +(518,'%d - |cffffffff|Hitemset:%d|h[%s %s]|h|r ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(521,'%d - |cffffffff|Hskill:%d|h[%s %s]|h|r %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); + diff --git a/sql/updates/6439_mangos_command.sql b/sql/updates/6439_mangos_command.sql new file mode 100644 index 00000000000..3e0587e9aed --- /dev/null +++ b/sql/updates/6439_mangos_command.sql @@ -0,0 +1,7 @@ +DELETE FROM `command` WHERE `name` IN ('cast','cast back','cast self','cast target'); + +INSERT INTO `command` (`name`,`security`,`help`) VALUES +('cast',3,'Syntax: .cast #spellid [triggered]\r\n Cast #spellid to selected target. If no target selected cast to self. If \'trigered\' or part provided then spell casted with triggered flag.'), +('cast back',3,'Syntax: .cast back #spellid [triggered]\r\n Selected target will cast #spellid to your character. If \'trigered\' or part provided then spell casted with triggered flag.'), +('cast self',3,'Syntax: .cast self #spellid [triggered]\r\nCast #spellid by target at target itself. If \'trigered\' or part provided then spell casted with triggered flag.'), +('cast target',3,'Syntax: .cast target #spellid [triggered]\r\n Selected target will cast #spellid to his victim. If \'trigered\' or part provided then spell casted with triggered flag.'); diff --git a/sql/updates/6456_mangos_command.sql b/sql/updates/6456_mangos_command.sql new file mode 100644 index 00000000000..da496969c59 --- /dev/null +++ b/sql/updates/6456_mangos_command.sql @@ -0,0 +1,7 @@ +DELETE FROM `command` WHERE `name` IN ('instance unbind','instance listbinds','instance stats','instance savedata'); + +INSERT INTO `command` (`name`,`security`,`help`) VALUES +('instance unbind',3,'Syntax: .instance unbind all\r\n All of the selected player\'s binds will be cleared.'), +('instance listbinds',3,'Syntax: .instance listbinds\r\n Lists the binds of the selected player.'), +('instance stats',3,'Syntax: .instance stats\r\n Shows statistics about instances.'), +('instance savedata',3,'Syntax: .instance savedata\r\n Save the InstanceData for the current player\'s map to the DB.'); diff --git a/sql/updates/6472_realmd_account.sql b/sql/updates/6472_realmd_account.sql new file mode 100644 index 00000000000..67ef4ce0164 --- /dev/null +++ b/sql/updates/6472_realmd_account.sql @@ -0,0 +1,2 @@ +ALTER TABLE account + CHARSET=utf8 COLLATE=utf8_general_ci; diff --git a/sql/updates/6492_mangos_spell_chain.sql b/sql/updates/6492_mangos_spell_chain.sql new file mode 100644 index 00000000000..840aa7cdb7a --- /dev/null +++ b/sql/updates/6492_mangos_spell_chain.sql @@ -0,0 +1,36 @@ +ALTER TABLE spell_chain + ADD COLUMN req_spell mediumint(9) NOT NULL default '0'; + +DELETE FROM `spell_chain` WHERE `spell_id` IN (20217,25898,25890,27145,25782,25916,27141,1038,25895,25899,27169,25894,25918,27143,16689,16810,16811,16812,16813,17329,27009); +INSERT INTO `spell_chain` (spell_id,prev_spell,first_spell,rank,req_spell) VALUES +/* Greater Blessing of Kings */ +(20217,0,20217,1,0), +(25898,0,25898,1,20217), +/* Greater Blessing of Light */ +(25890,0,25890,1,19979), +(27145,25890,25890,2,27144), +/* Greater Blessing of Might */ +(25782,0,25782,1,19838), +(25916,25782,25782,2,25291), +(27141,25916,25782,3,27140), +/* Greater Blessing of Salvation */ +(1038,0,1038,1,0), +(25895,0,25895,1,1038), +/* Greater Blessing of Sanctuary */ +(25899,0,25899,1,20914), +(27169,25899,25899,2,27168), +/* Greater Blessing of Wisdom */ +(25894,0,25894,1,19854), +(25918,25894,25894,2,25290), +(27143,25918,25894,3,27142), +/* Nature's Grasp */ +(16689,0,16689,1,339), +(16810,16689,16689,2,1062), +(16811,16810,16689,3,5195), +(16812,16811,16689,4,5196), +(16813,16812,16689,5,9852), +(17329,16813,16689,6,9853), +(27009,17329,16689,7,26989); + + + diff --git a/sql/updates/6496_mangos_spell_pet_auras.sql b/sql/updates/6496_mangos_spell_pet_auras.sql new file mode 100644 index 00000000000..152730a5a70 --- /dev/null +++ b/sql/updates/6496_mangos_spell_pet_auras.sql @@ -0,0 +1,56 @@ +-- +-- Table structure for table `spell_pet_auras` +-- + +DROP TABLE IF EXISTS `spell_pet_auras`; +CREATE TABLE `spell_pet_auras` ( + `spell` mediumint(8) unsigned NOT NULL COMMENT 'dummy spell id', + `pet` mediumint(8) unsigned NOT NULL default '0' COMMENT 'pet id; 0 = all', + `aura` mediumint(8) unsigned NOT NULL COMMENT 'pet aura id', + PRIMARY KEY (`spell`,`pet`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +-- +-- Dumping data for table `spell_pet_auras` +-- + +LOCK TABLES `spell_pet_auras` WRITE; +/*!40000 ALTER TABLE `spell_pet_auras` DISABLE KEYS */; +INSERT INTO `spell_pet_auras` VALUES +(19028, 0, 25228), +(19578, 0, 19579), +(20895, 0, 24529), +(28757, 0, 28758), +(35029, 0, 35060), +(35030, 0, 35061), +(35691, 0, 35696), +(35692, 0, 35696), +(35693, 0, 35696), +(23785, 416, 23759), +(23822, 416, 23826), +(23823, 416, 23827), +(23824, 416, 23828), +(23825, 416, 23829), +(23785, 417, 23762), +(23822, 417, 23837), +(23823, 417, 23838), +(23824, 417, 23839), +(23825, 417, 23840), +(23785, 1860, 23760), +(23822, 1860, 23841), +(23823, 1860, 23842), +(23824, 1860, 23843), +(23825, 1860, 23844), +(23785, 1863, 23761), +(23822, 1863, 23833), +(23823, 1863, 23834), +(23824, 1863, 23835), +(23825, 1863, 23836), +(23785, 17252, 35702), +(23822, 17252, 35703), +(23823, 17252, 35704), +(23824, 17252, 35705), +(23825, 17252, 35706); + +/*!40000 ALTER TABLE `spell_pet_auras` ENABLE KEYS */; +UNLOCK TABLES; \ No newline at end of file diff --git a/sql/updates/6506_mangos_spell_proc_event.sql b/sql/updates/6506_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..363274d51f0 --- /dev/null +++ b/sql/updates/6506_mangos_spell_proc_event.sql @@ -0,0 +1,7 @@ +DELETE FROM spell_proc_event WHERE entry IN (34138,42370,43728,46098); + +INSERT INTO spell_proc_event VALUES +(34138,0,0,0,11,0x0000000000000080,0x08000000,0), +(42370,0,0,0,11,0x0000000000000080,0x08000000,0), +(43728,0,0,0,11,0x0000000000000080,0x08000000,0), +(46098,0,0,0,11,0x0000000000000080,0x08000000,0); diff --git a/sql/updates/6509_mangos_command.sql b/sql/updates/6509_mangos_command.sql new file mode 100644 index 00000000000..408b98e7628 --- /dev/null +++ b/sql/updates/6509_mangos_command.sql @@ -0,0 +1,3 @@ +DELETE IGNORE FROM `command` WHERE `name` = 'learn all_recipes'; +INSERT IGNORE INTO `command` (`name`,`security`,`help`) VALUES +('learn all_recipes',2,'Syntax: .learn all_recipes [$profession]\r\rLearns all recipes of specified profession and sets skill level to max.\rExample: .learn all_recipes enchanting'); diff --git a/sql/updates/6509_mangos_mangos_string.sql b/sql/updates/6509_mangos_mangos_string.sql new file mode 100644 index 00000000000..5c6590e3aa5 --- /dev/null +++ b/sql/updates/6509_mangos_mangos_string.sql @@ -0,0 +1,4 @@ +DELETE FROM mangos_string WHERE entry IN (592); +INSERT INTO mangos_string VALUES +(592,'You have learned all spells in craft: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); + diff --git a/sql/updates/6513_mangos_command.sql b/sql/updates/6513_mangos_command.sql new file mode 100644 index 00000000000..a9b9d566a84 --- /dev/null +++ b/sql/updates/6513_mangos_command.sql @@ -0,0 +1,3 @@ +DELETE IGNORE FROM `command` WHERE `name` = 'cast dist'; +INSERT IGNORE INTO `command` (`name`,`security`,`help`) VALUES +('cast dist',3,'Syntax: .cast dist #spellid [#dist [triggered]]\r\n You will cast spell to pint at distance #dist. If \'trigered\' or part provided then spell casted with triggered flag. Not all spells can be casted as area spells.'); diff --git a/sql/updates/6515_mangos_spell_proc_event.sql b/sql/updates/6515_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..1609e37d462 --- /dev/null +++ b/sql/updates/6515_mangos_spell_proc_event.sql @@ -0,0 +1,4 @@ +DELETE FROM spell_proc_event WHERE entry IN(45355,45040); +INSERT INTO spell_proc_event VALUES +(45040,0,0,0,0,0x0000000000000000,0x00080001,0), +(45355,0,0,0,0,0x0000000000000000,0x00080001,0); diff --git a/sql/updates/6521_mangos_spell_proc_event.sql b/sql/updates/6521_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..97231e76bd5 --- /dev/null +++ b/sql/updates/6521_mangos_spell_proc_event.sql @@ -0,0 +1,3 @@ +DELETE FROM spell_proc_event WHERE entry IN(41260); +INSERT INTO `spell_proc_event` VALUES +(41260,0,0,0,0,0x0000000000000000,0x00000004,0); diff --git a/sql/updates/6523_mangos_spell_proc_event.sql b/sql/updates/6523_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..f9d93bbd94b --- /dev/null +++ b/sql/updates/6523_mangos_spell_proc_event.sql @@ -0,0 +1,10 @@ +DELETE FROM `spell_proc_event` WHERE `entry` IN (11185,12487,12488,19572,19573,28716,28744); +INSERT INTO `spell_proc_event` (`entry`, `SchoolMask`, `Category`, `SkillID`, `SpellFamilyName`, `SpellFamilyMask`, `procFlags`, `ppmRate`) + VALUES + (11185, 0, 0, 0, 3, 0x0000000000000080, 0x00020000, 0), + (12487, 0, 0, 0, 3, 0x0000000000000080, 0x00020000, 0), + (12488, 0, 0, 0, 3, 0x0000000000000080, 0x00020000, 0), + (19572, 0, 0, 0, 9, 0x0000000000800000, 0x08000000, 0), + (19573, 0, 0, 0, 9, 0x0000000000800000, 0x08000000, 0), + (28716, 0, 0, 0, 7, 0x0000000000000010, 0x08000000, 0), + (28744, 0, 0, 0, 7, 0x0000000000000040, 0x08000000, 0); diff --git a/sql/updates/6528_mangos_spell_affect.sql b/sql/updates/6528_mangos_spell_affect.sql new file mode 100644 index 00000000000..5ff9a8182ff --- /dev/null +++ b/sql/updates/6528_mangos_spell_affect.sql @@ -0,0 +1,3 @@ +DELETE FROM spell_affect WHERE entry IN (43743); +INSERT INTO spell_affect VALUES +(43743,1,0x0000000008000400); diff --git a/sql/updates/6528_mangos_spell_proc_event.sql b/sql/updates/6528_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..ff266cad2d6 --- /dev/null +++ b/sql/updates/6528_mangos_spell_proc_event.sql @@ -0,0 +1,85 @@ +ALTER TABLE spell_proc_event + ADD COLUMN cooldown int(10) unsigned NOT NULL default '0'; + +DELETE FROM spell_proc_event WHERE entry IN (324,325,905,945,974,8134,10431,10432,16620,18137, +19308,19309,19310,19311,19312,21185,23552,24398,24932,25469,25472,25477,29441,29444,29445,29446, +29447,30881,30883,30884,30885,30886,32593,32594,32734,32837,33736,33746,33757,33759,34355,34935, +34938,34939,34827,35077,35080,35083,35086,37173,37189,37197,37227,37655,38334,39027,39958,40899, +41260,41262,42135,42136,43737,45054,45057,45354,45481,45482,45483,45484,46569); + +INSERT INTO spell_proc_event (entry, SchoolMask, Category, SkillID, SpellFamilyName, SpellFamilyMask, procFlags, ppmRate, cooldown) VALUES +(324,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(325,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(905,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(945,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(974,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(8134,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(10431,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(10432,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(16620,0,0,0,0,0x0000000000000000,0x00100402,0,30), +(18137,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(19308,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(19309,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(19310,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(19311,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(19312,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(21185,0,0,0,0,0x0000000000000000,0x00000004,0,10), +(23552,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(24398,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(24932,0,0,0,0,0x0000000000000000,0x00001000,0,6), +(25469,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(25472,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(25477,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(29441,0,0,0,0,0x0000000000000000,0x01000000,0,1), +(29444,0,0,0,0,0x0000000000000000,0x01000000,0,1), +(29445,0,0,0,0,0x0000000000000000,0x01000000,0,1), +(29446,0,0,0,0,0x0000000000000000,0x01000000,0,1), +(29447,0,0,0,0,0x0000000000000000,0x01000000,0,1), +(30881,0,0,0,0,0x0000000000000000,0x00008000,0,5), +(30883,0,0,0,0,0x0000000000000000,0x00008000,0,5), +(30884,0,0,0,0,0x0000000000000000,0x00008000,0,5), +(30885,0,0,0,0,0x0000000000000000,0x00008000,0,5), +(30886,0,0,0,0,0x0000000000000000,0x00008000,0,5), +(32593,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(32594,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(32734,0,0,0,0,0x0000000000000000,0x00000002,0,3), +(32837,0,0,0,0,0x0000000000000000,0x00004000,0,45), +(33736,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(33746,0,0,0,0,0x0000000000000000,0x00000004,0,10), +(33757,0,0,0,0,0x0000000000000000,0x00000001,0,3), +(33759,0,0,0,0,0x0000000000000000,0x00000004,0,10), +(34355,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(34935,0,0,0,0,0x0000000000000000,0x00000002,0,8), +(34938,0,0,0,0,0x0000000000000000,0x00000002,0,8), +(34939,0,0,0,0,0x0000000000000000,0x00000002,0,8), +(34827,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(35077,0,0,0,0,0x0000000000000000,0x00008000,0,60), +(35080,0,0,0,0,0x0000000000000000,0x00000001,0,60), +(35083,0,0,0,0,0x0000000000000000,0x00020000,0,60), +(35086,0,0,0,0,0x0000000000000000,0x08020000,0,60), +(37173,0,0,0,8,0x000001062CBC0598,0x000A0001,0,30), +(37189,0,0,0,10,0x0000000000006000,0x10000000,0,60), +(37197,0,0,0,0,0x0000000000000000,0x00004000,0,45), +(37227,0,0,0,11,0x00000000000001C0,0x10000000,0,60), +(37655,0,0,0,0,0x0000000000000000,0x00004000,0,60), +(38334,0,0,0,0,0x0000000000000000,0x00004000,0,60), +(39027,0,0,0,0,0x0000000000000000,0x00100402,0,3), +(39958,0,0,0,0,0x0000000000000000,0x00000001,0.7,40), +(40899,0,0,0,0,0x0000000000000000,0x00000001,0,3), +(41260,0,0,0,0,0x0000000000000000,0x00000004,0,10), +(41262,0,0,0,0,0x0000000000000000,0x00000004,0,10), +(42135,0,0,0,7,0x0000044000000000,0x00100402,0,90), +(42136,0,0,0,7,0x0000044000000000,0x00100402,0,90), +(43737,0,0,0,7,0x0000044000000000,0x00000001,0,10), +(45054,0,0,0,0,0x0000000000000000,0x00020000,0,15), +(45057,0,0,0,0,0x0000000000000000,0x00000002,0,30), +(45354,0,0,0,0,0x0000000000000000,0x00000001,0,45), +(45481,0,0,0,0,0x0000000000000000,0x08020000,0,45), +(45482,0,0,0,0,0x0000000000000000,0x00080001,0,45), +(45483,0,0,0,0,0x0000000000000000,0x00080001,0,45), +(45484,0,0,0,0,0x0000000000000000,0x08000000,0,45), +(46569,0,0,0,0,0x0000000000000000,0x00004000,0,45); + +DELETE FROM spell_proc_event WHERE entry IN (43741); +INSERT INTO spell_proc_event (entry, SchoolMask, Category, SkillID, SpellFamilyName, SpellFamilyMask, procFlags, ppmRate, cooldown) VALUES +(43741,0,0,0,10,0x0000000080000000,0x00004000,0,0); diff --git a/sql/updates/6538_mangos_spell_proc_event.sql b/sql/updates/6538_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..f757fd77fac --- /dev/null +++ b/sql/updates/6538_mangos_spell_proc_event.sql @@ -0,0 +1,3 @@ +DELETE FROM spell_proc_event WHERE entry IN(34774); +INSERT INTO `spell_proc_event` VALUES +(34774,0,0,0,0,0x0000000000000000,0x00080001,1.5,20); diff --git a/sql/updates/6540_mangos_spell_proc_event.sql b/sql/updates/6540_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..cd9784cf938 --- /dev/null +++ b/sql/updates/6540_mangos_spell_proc_event.sql @@ -0,0 +1,3 @@ +DELETE FROM spell_proc_event WHERE entry IN(38319); +INSERT INTO `spell_proc_event` VALUES +(38319,0,0,0,0,0x0000000000000000,0x00004000,0,0); diff --git a/sql/updates/6544_mangos_spell_proc_event.sql b/sql/updates/6544_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..835ae6dc39c --- /dev/null +++ b/sql/updates/6544_mangos_spell_proc_event.sql @@ -0,0 +1,5 @@ +DELETE FROM spell_proc_event WHERE entry IN (13983, 14070, 14071); +INSERT INTO `spell_proc_event` VALUES +(13983,0,0,0,0,0x0000000000000000,0x01000010,0,0), +(14070,0,0,0,0,0x0000000000000000,0x01000010,0,0), +(14071,0,0,0,0,0x0000000000000000,0x01000010,0,0); diff --git a/sql/updates/6545_mangos_command.sql b/sql/updates/6545_mangos_command.sql new file mode 100644 index 00000000000..a6681fd230f --- /dev/null +++ b/sql/updates/6545_mangos_command.sql @@ -0,0 +1,7 @@ +DELETE FROM `command` WHERE name IN ('idleshutdown','info','shutdown','server info','server shutdown','server restart','server idleshutdown','server idlerestart'); +INSERT INTO `command` VALUES +('server info',0,'Syntax: .server info\r\n\r\nDisplay server version and the number of connected players.'), +('server shutdown',3,'Syntax: .server shutdown seconds\r\n\r\nShut the server down after given seconds and show "Off server in X" or cancel the restart/shutdown if cancel value is used.'), +('server restart',3,'Syntax: .server restart seconds\r\n\r\nRestart the server after given seconds and show "Restart server in X" or cancel the restart/shutdown if cancel value is used.'), +('server idleshutdown',3,'Syntax: .server idleshutdown #delay|cancel\r\n\r\nShut the server down after #delay seconds if no active connections are present (no players) or cancel the restart/shutdown if cancel value is used.'), +('server idlerestart',3,'Syntax: .server idlerestart #delay|cancel\r\n\r\nRestart the server after #delay seconds if no active connections are present (no players) or cancel the restart/shutdown if cancel value is used.'); diff --git a/sql/updates/6557_mangos_command.sql b/sql/updates/6557_mangos_command.sql new file mode 100644 index 00000000000..6881466792c --- /dev/null +++ b/sql/updates/6557_mangos_command.sql @@ -0,0 +1,3 @@ +DELETE FROM command WHERE name = 'npc delete'; +INSERT INTO `command` VALUES +('npc delete',2,'Syntax: .npc delete [#guid]\r\n\r\nDelete creature with guid #guid (or the selected if no guid is provided)'); diff --git a/sql/updates/6574_mangos_spell_proc_event.sql b/sql/updates/6574_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..7a09512f7b8 --- /dev/null +++ b/sql/updates/6574_mangos_spell_proc_event.sql @@ -0,0 +1,3 @@ +DELETE FROM spell_proc_event WHERE entry IN (41989); +INSERT INTO `spell_proc_event` VALUES +(41989,0,0,0,0,0x0000000000000000,0x00000001,3,0); diff --git a/sql/updates/6585_mangos_command.sql b/sql/updates/6585_mangos_command.sql new file mode 100644 index 00000000000..123d102ba3b --- /dev/null +++ b/sql/updates/6585_mangos_command.sql @@ -0,0 +1,3 @@ +DELETE FROM command WHERE name = 'reload config'; +INSERT INTO `command` VALUES +('reload config',3,'Syntax: .reload config\r\n\r\nReload config settings (by default stored in mangosd.conf). Not all settings can be change at reload: some new setting values will be ignored until restart, some values will applied with delay or only to new objects/maps, some values will explicitly rejected to change at reload.'); diff --git a/sql/updates/6588_mangos_spell_proc_event.sql b/sql/updates/6588_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..083a3524c71 --- /dev/null +++ b/sql/updates/6588_mangos_spell_proc_event.sql @@ -0,0 +1,3 @@ +DELETE FROM spell_proc_event WHERE entry = 41434; +INSERT INTO spell_proc_event (entry, SchoolMask, Category, SkillID, SpellFamilyName, SpellFamilyMask, procFlags, ppmRate, cooldown) VALUES +(41434,0,0,0,0,0x0000000000000000,0x00000001,2,45); diff --git a/sql/updates/6596_characters_arena_team.sql b/sql/updates/6596_characters_arena_team.sql new file mode 100644 index 00000000000..0e8afd58926 --- /dev/null +++ b/sql/updates/6596_characters_arena_team.sql @@ -0,0 +1,10 @@ +ALTER TABLE arena_team CHANGE EmblemStyle _BackgroundColor int(10) unsigned NOT NULL default '0'; +ALTER TABLE arena_team CHANGE EmblemColor _EmblemStyle int(10) unsigned NOT NULL default '0'; +ALTER TABLE arena_team CHANGE BorderStyle _EmblemColor int(10) unsigned NOT NULL default '0'; +ALTER TABLE arena_team CHANGE BorderColor _BorderStyle int(10) unsigned NOT NULL default '0'; +ALTER TABLE arena_team CHANGE BackgroundColor _BorderColor int(10) unsigned NOT NULL default '0'; +ALTER TABLE arena_team CHANGE _BackgroundColor BackgroundColor int(10) unsigned NOT NULL default '0'; +ALTER TABLE arena_team CHANGE _EmblemStyle EmblemStyle int(10) unsigned NOT NULL default '0'; +ALTER TABLE arena_team CHANGE _EmblemColor EmblemColor int(10) unsigned NOT NULL default '0'; +ALTER TABLE arena_team CHANGE _BorderStyle BorderStyle int(10) unsigned NOT NULL default '0'; +ALTER TABLE arena_team CHANGE _BorderColor BorderColor int(10) unsigned NOT NULL default '0'; \ No newline at end of file diff --git a/sql/updates/6598_character_spell.sql b/sql/updates/6598_character_spell.sql new file mode 100644 index 00000000000..bd5f6fdce84 --- /dev/null +++ b/sql/updates/6598_character_spell.sql @@ -0,0 +1,2 @@ +ALTER TABLE `character_spell` + ADD COLUMN `disabled` tinyint(3) unsigned NOT NULL default '0'; diff --git a/sql/updates/6609_mangos_mangos_string.sql b/sql/updates/6609_mangos_mangos_string.sql new file mode 100644 index 00000000000..be7814d96da --- /dev/null +++ b/sql/updates/6609_mangos_mangos_string.sql @@ -0,0 +1,3 @@ +DELETE FROM mangos_string WHERE entry = 170; +INSERT INTO mangos_string VALUES +(170,'You try to hear sound %u but it doesn\'t exist.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/6613_mangos_mangos_string.sql b/sql/updates/6613_mangos_mangos_string.sql new file mode 100644 index 00000000000..4b1635f4974 --- /dev/null +++ b/sql/updates/6613_mangos_mangos_string.sql @@ -0,0 +1,11 @@ +DELETE FROM `mangos_string` WHERE entry = 636; +INSERT INTO `mangos_string` VALUES +(636,'The Battle for Eye of the Storm begins in 1 minute.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); + +DELETE FROM `mangos_string` WHERE entry = 637; +INSERT INTO `mangos_string` VALUES +(637,'The Battle for Eye of the Storm begins in 30 seconds.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); + +DELETE FROM `mangos_string` WHERE entry = 638; +INSERT INTO `mangos_string` VALUES +(638,'The Battle for Eye of the Storm has begun!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/6627_mangos_creature_movement.sql b/sql/updates/6627_mangos_creature_movement.sql new file mode 100644 index 00000000000..05aa78e1240 --- /dev/null +++ b/sql/updates/6627_mangos_creature_movement.sql @@ -0,0 +1 @@ +ALTER TABLE creature_movement MODIFY COLUMN id int(10) unsigned NOT NULL COMMENT 'Creature GUID'; \ No newline at end of file diff --git a/sql/updates/6640_mangos_reference_loot_template.sql b/sql/updates/6640_mangos_reference_loot_template.sql new file mode 100644 index 00000000000..612af99309b --- /dev/null +++ b/sql/updates/6640_mangos_reference_loot_template.sql @@ -0,0 +1,27 @@ +-- +-- Table structure for table `reference_loot_template` +-- + +DROP TABLE IF EXISTS `reference_loot_template`; +CREATE TABLE `reference_loot_template` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `item` mediumint(8) unsigned NOT NULL default '0', + `ChanceOrQuestChance` float NOT NULL default '100', + `groupid` tinyint(3) unsigned NOT NULL default '0', + `mincountOrRef` mediumint(9) NOT NULL default '1', + `maxcount` tinyint(3) unsigned NOT NULL default '1', + `lootcondition` tinyint(3) unsigned NOT NULL default '0', + `condition_value1` mediumint(8) unsigned NOT NULL default '0', + `condition_value2` mediumint(8) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`,`item`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Loot System'; + +-- +-- Dumping data for table `reference_loot_template` +-- + +LOCK TABLES `reference_loot_template` WRITE; +/*!40000 ALTER TABLE `reference_loot_template` DISABLE KEYS */; +/*!40000 ALTER TABLE `reference_loot_template` ENABLE KEYS */; +UNLOCK TABLES; + diff --git a/sql/updates/6642_characters_declinedname.sql b/sql/updates/6642_characters_declinedname.sql new file mode 100644 index 00000000000..a81690de274 --- /dev/null +++ b/sql/updates/6642_characters_declinedname.sql @@ -0,0 +1,6 @@ +ALTER TABLE character_declinedname + MODIFY COLUMN genitive varchar(15) NOT NULL default '', + MODIFY COLUMN dative varchar(15) NOT NULL default '', + MODIFY COLUMN accusative varchar(15) NOT NULL default '', + MODIFY COLUMN instrumental varchar(15) NOT NULL default '', + MODIFY COLUMN prepositional varchar(15) NOT NULL default ''; diff --git a/sql/updates/6668_mangos_spell_proc_event.sql b/sql/updates/6668_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..f6ebc5edb9d --- /dev/null +++ b/sql/updates/6668_mangos_spell_proc_event.sql @@ -0,0 +1,5 @@ +DELETE FROM spell_proc_event WHERE entry IN (42135,42136); + +INSERT INTO spell_proc_event (entry, SchoolMask, Category, SkillID, SpellFamilyName, SpellFamilyMask, procFlags, ppmRate, cooldown) VALUES +(42135,0,0,0,0,0x0000000000000000,0x00100402,0,90), +(42136,0,0,0,0,0x0000000000000000,0x00100402,0,90); diff --git a/sql/updates/6673_mangos_areatrigger_scripts.sql b/sql/updates/6673_mangos_areatrigger_scripts.sql new file mode 100644 index 00000000000..91d3cc6d9b5 --- /dev/null +++ b/sql/updates/6673_mangos_areatrigger_scripts.sql @@ -0,0 +1,7 @@ +DROP TABLE IF EXISTS `areatrigger_scripts`; +CREATE TABLE `areatrigger_scripts` ( + `entry` MEDIUMINT( 8 ) NOT NULL , + `ScriptName` CHAR( 64 ) NOT NULL , + PRIMARY KEY ( `entry` ) +) ENGINE = MYISAM DEFAULT CHARSET=utf8; + diff --git a/sql/updates/6676_mangos_spell_proc_event.sql b/sql/updates/6676_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..2a81a9f3b20 --- /dev/null +++ b/sql/updates/6676_mangos_spell_proc_event.sql @@ -0,0 +1,3 @@ +DELETE FROM spell_proc_event where entry = 37447; +INSERT INTO spell_proc_event (entry, SchoolMask, Category, SkillID, SpellFamilyName, SpellFamilyMask, procFlags, ppmRate, cooldown) VALUES +(37447,0,0,0,3,0x0000010000000000,0x00004000,0,0); diff --git a/sql/updates/6681_mangos_mangos_string.sql b/sql/updates/6681_mangos_mangos_string.sql new file mode 100644 index 00000000000..1c66abd53ae --- /dev/null +++ b/sql/updates/6681_mangos_mangos_string.sql @@ -0,0 +1,5 @@ +DELETE FROM `mangos_string` WHERE entry IN (3,711,712); +INSERT INTO `mangos_string` VALUES +(3,'|cffff0000[System Message]: %s|r',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(711,'Queue status for %s (Lvl: %u to %u)\nQueued alliances: %u (Need at least %u more)\nQueued hordes: %u (Need at least %u more)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(712,'|cffff0000[BG Queue Announcer]:|r %s -- [%u-%u] A: %u (Need: %u), H: %u (Needs %u)|r',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/6691_mangos_spell_proc_event.sql b/sql/updates/6691_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..cbd57317b80 --- /dev/null +++ b/sql/updates/6691_mangos_spell_proc_event.sql @@ -0,0 +1,3 @@ +DELETE FROM spell_proc_event where entry = 37247; +INSERT INTO spell_proc_event (entry, SchoolMask, Category, SkillID, SpellFamilyName, SpellFamilyMask, procFlags, ppmRate, cooldown) VALUES +(37247,8,0,0,0,0x0000000000000000,0x00004000,0,45); diff --git a/sql/updates/6693_mangos_spell_affect.sql b/sql/updates/6693_mangos_spell_affect.sql new file mode 100644 index 00000000000..ea0fb9e96c9 --- /dev/null +++ b/sql/updates/6693_mangos_spell_affect.sql @@ -0,0 +1,3 @@ +DELETE FROM spell_affect WHERE entry = '12606'; +INSERT INTO spell_affect (entry, effectId, SpellFamilyMask) VALUES +(12606,0,0x0000000000002000); diff --git a/sql/updates/6693_mangos_spell_proc_event.sql b/sql/updates/6693_mangos_spell_proc_event.sql new file mode 100644 index 00000000000..fa4df63d537 --- /dev/null +++ b/sql/updates/6693_mangos_spell_proc_event.sql @@ -0,0 +1,11 @@ +DELETE FROM spell_proc_event where entry = 44604; +INSERT INTO spell_proc_event (entry, SchoolMask, Category, SkillID, SpellFamilyName, SpellFamilyMask, procFlags, ppmRate, cooldown) VALUES +(44604,0,0,0,0,0x0000000000000000,0x00004000,0,0); + +DELETE FROM spell_proc_event where entry = 44599; +INSERT INTO spell_proc_event (entry, SchoolMask, Category, SkillID, SpellFamilyName, SpellFamilyMask, procFlags, ppmRate, cooldown) VALUES +(44599,0,0,0,0,0x0000000000000000,0x00000001,0,5); + +DELETE FROM spell_proc_event where entry = 46046; +INSERT INTO spell_proc_event (entry, SchoolMask, Category, SkillID, SpellFamilyName, SpellFamilyMask, procFlags, ppmRate, cooldown) VALUES +(46046,0,0,0,0,0x0000000000000000,0x00000001,0,5); diff --git a/sql/updates/6698_characters_character_tutorial.sql b/sql/updates/6698_characters_character_tutorial.sql new file mode 100644 index 00000000000..78b6913fa48 --- /dev/null +++ b/sql/updates/6698_characters_character_tutorial.sql @@ -0,0 +1,15 @@ +DROP TABLE IF EXISTS `character_tutorial`; +CREATE TABLE `character_tutorial` ( + `account` bigint(20) unsigned NOT NULL auto_increment COMMENT 'Account Identifier', + `realmid` int(11) unsigned NOT NULL default '0' COMMENT 'Realm Identifier', + `tut0` int(11) unsigned NOT NULL default '0', + `tut1` int(11) unsigned NOT NULL default '0', + `tut2` int(11) unsigned NOT NULL default '0', + `tut3` int(11) unsigned NOT NULL default '0', + `tut4` int(11) unsigned NOT NULL default '0', + `tut5` int(11) unsigned NOT NULL default '0', + `tut6` int(11) unsigned NOT NULL default '0', + `tut7` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`account`,`realmid`), + KEY acc_key (`account`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System'; diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am new file mode 100644 index 00000000000..9559df48558 --- /dev/null +++ b/sql/updates/Makefile.am @@ -0,0 +1,384 @@ +# Copyright (C) 2005-2008 MaNGOS +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## Process this file with automake to produce Makefile.in + +## Sub-directories to parse + +## Change installation location +# datadir = mangos/sql/updates +pkgdatadir = $(datadir)/mangos/sql/updates + +## Files to be installed +# Install basic SQL files to datadir +pkgdata_DATA = \ + 5651_characters_guild_bank_tab.sql \ + 5651_characters_characters.sql \ + 5651_characters_character_social.sql \ + 5651_mangos_creature_template.sql \ + 5655_mangos_spell_affect.sql \ + 5655_mangos_spell_chain.sql \ + 5655_mangos_spell_proc_event.sql \ + 5659_mangos_loot_template.sql \ + 5660_mangos_spell_elixir.sql \ + 5664_mangos.sql \ + 5665_mangos_creature_template.sql \ + 5679_mangos_creature_template.sql \ + 5680_mangos_spell_proc_event.sql \ + 5698_mangos_item_template.sql \ + 5708_mangos_player_levelstats.sql \ + 5711_characters_character_kill.sql \ + 5711_mangos_command.sql \ + 5714_mangos_command.sql \ + 5714_mangos_mangos_string.sql \ + 5718_mangos_command.sql \ + 5718_mangos_creature_template.sql \ + 5718_mangos_mangos_string.sql \ + 5720_mangos_command.sql \ + 5720_mangos_mangos_string.sql \ + 5721_mangos_spell_affect.sql \ + 5733_mangos_creature.sql \ + 5739_mangos_creature.sql \ + 5739_mangos_gameobject.sql \ + 5746_mangos_quest_template.sql \ + 5753_mangos_areatrigger_teleport.sql \ + 5758_mangos_creature_addon.sql \ + 5759_mangos_command.sql \ + 5764_characters_characters.sql \ + 5764_mangos_command.sql \ + 5771_mangos_spell_learn_spell.sql \ + 5772_mangos_command.sql \ + 5773_mangos_spell_affect.sql \ + 5773_mangos_spell_learn_spell.sql \ + 5774_mangos_command.sql \ + 5774_mangos_mangos_string.sql \ + 5777_mangos_command.sql \ + 5778_mangos_spell_affect.sql \ + 5779_mangos_quest_template.sql \ + 5784_mangos_player_levelstats.sql \ + 5787_mangos_player_levelstats.sql \ + 5790_mangos_player_classlevelstats.sql \ + 5790_mangos_player_levelstats.sql \ + 5799_mangos_spell_proc_event.sql \ + 5813_mangos_mangos_string.sql \ + 5827_mangos_spell_affect.sql \ + 5827_mangos_spell_chain.sql \ + 5827_mangos_spell_learn_spell.sql \ + 5827_mangos_spell_proc_event.sql \ + 5831_mangos_skill_fishing_base_level.sql \ + 5842_mangos_spell_affect.sql \ + 5845_mangos_spell_proc_event.sql \ + 5847_mangos_command.sql \ + 5857_mangos_spell_proc_event.sql \ + 5861_mangos_command.sql \ + 5865_mangos_command.sql \ + 5867_mangos_spell_affect.sql \ + 5875_mangos_quest_template.sql \ + 5880_mangos_mangos_string.sql \ + 5882_mangos_spell_affect.sql \ + 5896_mangos_spell_proc_event.sql \ + 5923_mangos_spell_affect.sql \ + 5940_mangos_spell_affect.sql \ + 5946_mangos_spell_affect.sql \ + 5955_characters_guild_eventlog.sql \ + 5965_mangos_mangos_string.sql \ + 5973_mangos_spell_proc_event.sql \ + 5977_characters_pet.sql \ + 5982_mangos.sql \ + 5986_mangos_spell_proc_event.sql \ + 5999_mangos_spell_proc_event.sql \ + 6016_mangos_spell_proc_event.sql \ + 6017_mangos_spell_proc_event.sql \ + 6022_mangos_spell_proc_event.sql \ + 6023_mangos_mangos_string.sql \ + 6027_mangos_spell_affect.sql \ + 6032_mangos_petcreateinfo_spell.sql \ + 6037_mangos_spell_affect.sql \ + 6038_mangos_creature_template.sql \ + 6047_characters_character_social.sql \ + 6047_characters_guild_bank_tab.sql \ + 6049_mangos_spell_proc_event.sql \ + 6052_mangos_loot_template.sql \ + 6058_mangos_spell_learn_spell.sql \ + 6061_characters_mail.sql \ + 6061_mangos_quest_mail_loot_template.sql \ + 6061_mangos_quest_template.sql \ + 6062_mangos_spell_proc_event.sql \ + 6078_mangos_spell_proc_event.sql \ + 6090_mangos_command.sql \ + 6090_mangos_mangos_string.sql \ + 6151_mangos_spell_proc_event.sql \ + 6164_mangos_command.sql \ + 6171_mangos_spell_affect.sql \ + 6179_mangos_mangos_string.sql \ + 6193_mangos_spell_proc_event.sql \ + 6199_mangos_spell_proc_event.sql \ + 6210_mangos_spell_proc_event.sql \ + 6213_mangos_spell_target_position.sql \ + 6219_mangos_spell_proc_event.sql \ + 6246_mangos_spell_proc_event.sql \ + 6251_mangos_spell_proc_event.sql \ + 6255_mangos_spell_proc_event.sql \ + 6265_mangos_pet_name_generation.sql \ + 6270_mangos_spell_proc_event.sql \ + 6291_characters_character_pet.sql \ + 6297_characters_characters.sql \ + 6298_characters_characters.sql \ + 6298_characters_corpse.sql \ + 6304_mangos_spell_proc_event.sql \ + 6308_mangos_command.sql \ + 6313_mangos_spell_proc_event.sql \ + 6314_mangos_command.sql \ + 6324_mangos_creature_template.sql \ + 6325_mangos_creature_template.sql \ + 6326_characters_corpse.sql \ + 6334_mangos_spell_affect.sql \ + 6335_characters_corpse.sql \ + 6351_mangos_spell_proc_event.sql \ + 6360_characters_corpse.sql \ + 6360_characters_characters.sql \ + 6362_characters.sql \ + 6362_mangos_instance_template.sql \ + 6367_mangos_spell_proc_event.sql \ + 6369_mangos_spell_affect.sql \ + 6370_mangos_spell_affect.sql \ + 6381_mangos_command.sql \ + 6387_characters_character_ticket.sql \ + 6387_mangos_mangos_string.sql \ + 6397_mangos_creature_template.sql \ + 6398_mangos_creature_template.sql \ + 6412_characters_declinedname.sql \ + 6426_mangos_locales.sql \ + 6426_realmd_localization.sql \ + 6431_mangos_mangos_string.sql \ + 6439_mangos_command.sql \ + 6456_mangos_command.sql \ + 6472_realmd_account.sql \ + 6492_mangos_spell_chain.sql \ + 6496_mangos_spell_pet_auras.sql \ + 6506_mangos_spell_proc_event.sql \ + 6509_mangos_command.sql \ + 6509_mangos_mangos_string.sql \ + 6513_mangos_command.sql \ + 6515_mangos_spell_proc_event.sql \ + 6521_mangos_spell_proc_event.sql \ + 6523_mangos_spell_proc_event.sql \ + 6528_mangos_spell_affect.sql \ + 6528_mangos_spell_proc_event.sql \ + 6538_mangos_spell_proc_event.sql \ + 6540_mangos_spell_proc_event.sql \ + 6544_mangos_spell_proc_event.sql \ + 6545_mangos_command.sql \ + 6557_mangos_command.sql \ + 6574_mangos_spell_proc_event.sql \ + 6585_mangos_command.sql \ + 6588_mangos_spell_proc_event.sql \ + 6596_characters_arena_team.sql \ + 6598_character_spell.sql \ + 6609_mangos_mangos_string.sql \ + 6613_mangos_mangos_string.sql \ + 6627_mangos_creature_movement.sql \ + 6640_mangos_reference_loot_template.sql \ + 6642_characters_declinedname.sql \ + 6668_mangos_spell_proc_event.sql \ + 6676_mangos_spell_proc_event.sql \ + 6681_mangos_mangos_string.sql \ + 6691_mangos_spell_proc_event.sql \ + 6693_mangos_spell_affect.sql \ + 6693_mangos_spell_proc_event.sql \ + 6698_characters_character_tutorial.sql \ + README + +## Additional files to include when running 'make dist' +# SQL update files, to upgrade database schema from older revisions +EXTRA_DIST = \ + 5651_characters_guild_bank_tab.sql \ + 5651_characters_characters.sql \ + 5651_characters_character_social.sql \ + 5651_mangos_creature_template.sql \ + 5655_mangos_spell_affect.sql \ + 5655_mangos_spell_chain.sql \ + 5655_mangos_spell_proc_event.sql \ + 5659_mangos_loot_template.sql \ + 5660_mangos_spell_elixir.sql \ + 5664_mangos.sql \ + 5665_mangos_creature_template.sql \ + 5679_mangos_creature_template.sql \ + 5680_mangos_spell_proc_event.sql \ + 5698_mangos_item_template.sql \ + 5708_mangos_player_levelstats.sql \ + 5711_characters_character_kill.sql \ + 5711_mangos_command.sql \ + 5714_mangos_command.sql \ + 5714_mangos_mangos_string.sql \ + 5718_mangos_command.sql \ + 5718_mangos_creature_template.sql \ + 5718_mangos_mangos_string.sql \ + 5720_mangos_command.sql \ + 5720_mangos_mangos_string.sql \ + 5721_mangos_spell_affect.sql \ + 5733_mangos_creature.sql \ + 5739_mangos_creature.sql \ + 5739_mangos_gameobject.sql \ + 5746_mangos_quest_template.sql \ + 5753_mangos_areatrigger_teleport.sql \ + 5758_mangos_creature_addon.sql \ + 5759_mangos_command.sql \ + 5764_characters_characters.sql \ + 5764_mangos_command.sql \ + 5771_mangos_spell_learn_spell.sql \ + 5772_mangos_command.sql \ + 5773_mangos_spell_affect.sql \ + 5773_mangos_spell_learn_spell.sql \ + 5774_mangos_command.sql \ + 5774_mangos_mangos_string.sql \ + 5777_mangos_command.sql \ + 5778_mangos_spell_affect.sql \ + 5779_mangos_quest_template.sql \ + 5784_mangos_player_levelstats.sql \ + 5787_mangos_player_levelstats.sql \ + 5790_mangos_player_classlevelstats.sql \ + 5790_mangos_player_levelstats.sql \ + 5799_mangos_spell_proc_event.sql \ + 5813_mangos_mangos_string.sql \ + 5827_mangos_spell_affect.sql \ + 5827_mangos_spell_chain.sql \ + 5827_mangos_spell_learn_spell.sql \ + 5827_mangos_spell_proc_event.sql \ + 5831_mangos_skill_fishing_base_level.sql \ + 5842_mangos_spell_affect.sql \ + 5845_mangos_spell_proc_event.sql \ + 5847_mangos_command.sql \ + 5857_mangos_spell_proc_event.sql \ + 5861_mangos_command.sql \ + 5865_mangos_command.sql \ + 5867_mangos_spell_affect.sql \ + 5875_mangos_quest_template.sql \ + 5880_mangos_mangos_string.sql \ + 5882_mangos_spell_affect.sql \ + 5896_mangos_spell_proc_event.sql \ + 5923_mangos_spell_affect.sql \ + 5940_mangos_spell_affect.sql \ + 5946_mangos_spell_affect.sql \ + 5955_characters_guild_eventlog.sql \ + 5965_mangos_mangos_string.sql \ + 5973_mangos_spell_proc_event.sql \ + 5977_characters_pet.sql \ + 5982_mangos.sql \ + 5986_mangos_spell_proc_event.sql \ + 5999_mangos_spell_proc_event.sql \ + 6016_mangos_spell_proc_event.sql \ + 6017_mangos_spell_proc_event.sql \ + 6022_mangos_spell_proc_event.sql \ + 6023_mangos_mangos_string.sql \ + 6027_mangos_spell_affect.sql \ + 6032_mangos_petcreateinfo_spell.sql \ + 6037_mangos_spell_affect.sql \ + 6038_mangos_creature_template.sql \ + 6047_characters_character_social.sql \ + 6047_characters_guild_bank_tab.sql \ + 6049_mangos_spell_proc_event.sql \ + 6052_mangos_loot_template.sql \ + 6058_mangos_spell_learn_spell.sql \ + 6061_characters_mail.sql \ + 6061_mangos_quest_mail_loot_template.sql \ + 6061_mangos_quest_template.sql \ + 6062_mangos_spell_proc_event.sql \ + 6078_mangos_spell_proc_event.sql \ + 6090_mangos_command.sql \ + 6090_mangos_mangos_string.sql \ + 6151_mangos_spell_proc_event.sql \ + 6164_mangos_command.sql \ + 6171_mangos_spell_affect.sql \ + 6179_mangos_mangos_string.sql \ + 6193_mangos_spell_proc_event.sql \ + 6199_mangos_spell_proc_event.sql \ + 6210_mangos_spell_proc_event.sql \ + 6213_mangos_spell_target_position.sql \ + 6219_mangos_spell_proc_event.sql \ + 6246_mangos_spell_proc_event.sql \ + 6251_mangos_spell_proc_event.sql \ + 6255_mangos_spell_proc_event.sql \ + 6265_mangos_pet_name_generation.sql \ + 6270_mangos_spell_proc_event.sql \ + 6291_characters_character_pet.sql \ + 6297_characters_characters.sql \ + 6298_characters_characters.sql \ + 6298_characters_corpse.sql \ + 6304_mangos_spell_proc_event.sql \ + 6308_mangos_command.sql \ + 6313_mangos_spell_proc_event.sql \ + 6314_mangos_command.sql \ + 6324_mangos_creature_template.sql \ + 6325_mangos_creature_template.sql \ + 6326_characters_corpse.sql \ + 6334_mangos_spell_affect.sql \ + 6335_characters_corpse.sql \ + 6351_mangos_spell_proc_event.sql \ + 6360_characters_corpse.sql \ + 6360_characters_characters.sql \ + 6362_characters.sql \ + 6362_mangos_instance_template.sql \ + 6367_mangos_spell_proc_event.sql \ + 6369_mangos_spell_affect.sql \ + 6370_mangos_spell_affect.sql \ + 6381_mangos_command.sql \ + 6387_characters_character_ticket.sql \ + 6387_mangos_mangos_string.sql \ + 6397_mangos_creature_template.sql \ + 6398_mangos_creature_template.sql \ + 6412_characters_declinedname.sql \ + 6426_mangos_locales.sql \ + 6426_realmd_localization.sql \ + 6431_mangos_mangos_string.sql \ + 6439_mangos_command.sql \ + 6456_mangos_command.sql \ + 6472_realmd_account.sql \ + 6492_mangos_spell_chain.sql \ + 6496_mangos_spell_pet_auras.sql \ + 6506_mangos_spell_proc_event.sql \ + 6509_mangos_command.sql \ + 6509_mangos_mangos_string.sql \ + 6513_mangos_command.sql \ + 6515_mangos_spell_proc_event.sql \ + 6521_mangos_spell_proc_event.sql \ + 6523_mangos_spell_proc_event.sql \ + 6528_mangos_spell_affect.sql \ + 6528_mangos_spell_proc_event.sql \ + 6538_mangos_spell_proc_event.sql \ + 6540_mangos_spell_proc_event.sql \ + 6544_mangos_spell_proc_event.sql \ + 6545_mangos_command.sql \ + 6557_mangos_command.sql \ + 6574_mangos_spell_proc_event.sql \ + 6585_mangos_command.sql \ + 6588_mangos_spell_proc_event.sql \ + 6596_characters_arena_team.sql \ + 6598_character_spell.sql \ + 6609_mangos_mangos_string.sql \ + 6613_mangos_mangos_string.sql \ + 6627_mangos_creature_movement.sql \ + 6640_mangos_reference_loot_template.sql \ + 6642_characters_declinedname.sql \ + 6668_mangos_spell_proc_event.sql \ + 6673_mangos_areatrigger_scripts.sql \ + 6676_mangos_spell_proc_event.sql \ + 6681_mangos_mangos_string.sql \ + 6691_mangos_spell_proc_event.sql \ + 6693_mangos_spell_affect.sql \ + 6693_mangos_spell_proc_event.sql \ + 6698_characters_character_tutorial.sql \ + README diff --git a/sql/updates/README b/sql/updates/README new file mode 100644 index 00000000000..c3a5858b4b4 --- /dev/null +++ b/sql/updates/README @@ -0,0 +1,33 @@ += MaNGOS -- README = + +Copyright (c) 2005-2008 MaNGOS + +See the COPYING file for copying conditions. + +== Database Updates == +This folder contains SQL files which will apply required updates to your MySQL +database, whenever the MaNGOS database structure has been changed or extended. + +To see if you need an update, the file names have been given a fixed structure +that should enable you to see if you need an update or not. + +=== File name descriptin === +File names are divided into two parts. First part is the revision that will be +compatible with database after apply update. The second part of the name, +is the table that needs and update or has been added. See an example below: + + 1123_characters_character_spell.sql + | | | + | | | + | | The table character_spell + | | will need an update. + | | + | Name of affected DB (default recommended name) + | Can be: characters, mangos, realmd + | + MaNGOS revision older 1123 will need this update. + After appling this update DB compatiable with revision 1122 + will be compatibale with revision 1123. + Revision 1123 and any revision after 1123, e.g. 1124 or 1137, + already includes this update in the default database + file mangos.sql. diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 00000000000..e9dd1c61380 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,23 @@ +# Copyright (C) 2005-2008 MaNGOS +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## Process this file with automake to produce Makefile.in + +## Sub-directories to parse +SUBDIRS = framework shared trinityrealm game bindings trinitycore + +## Additional files to include when running 'make dist' +# Nothing yet. diff --git a/src/bindings/Makefile.am b/src/bindings/Makefile.am new file mode 100644 index 00000000000..69043c94dd4 --- /dev/null +++ b/src/bindings/Makefile.am @@ -0,0 +1,23 @@ +# Copyright (C) 2005-2008 MaNGOS +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +# interface folder is disabled for now + +if USE_TSCRIPTS +SUBDIRS = scripts +else +SUBDIRS = interface +endif diff --git a/src/bindings/interface/Makefile.am b/src/bindings/interface/Makefile.am new file mode 100644 index 00000000000..5da807d8a16 --- /dev/null +++ b/src/bindings/interface/Makefile.am @@ -0,0 +1,52 @@ +# Copyright (C) 2005-2008 MaNGOS +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## Process this file with automake to produce Makefile.in + +## Sub-directories to parse + +## Build MaNGOS script library as shared library. +# libmangosscript shared library will later be reused by world server daemon. +lib_LTLIBRARIES = libtrinityscript.la + +libtrinityscript_la_CPPFLAGS = \ +$(MYSQL_INCLUDES) \ +$(POSTGRE_INCLUDES) \ +-I$(top_srcdir)/dep/include \ +-I$(top_srcdir)/src/shared \ +-I$(top_srcdir)/src/framework \ +-I$(top_srcdir)/src/game + +libtrinityscript_la_SOURCES = \ + ScriptMgr.cpp \ + ScriptMgr.h \ + config.h \ + system.cpp \ + Scripts/sc_default.cpp \ + Scripts/sc_defines.cpp \ + Scripts/sc_defines.h + +## libtool settings +# API versioning +libtrinityscript_la_LIBFLAGS = -version-info 0:0:1 +libtrinityscript_la_LIBADD = $(MYSQL_LIBS) $(POSTGRE_LIBS) + +## Additional files to include when running 'make dist' +# Scripts defaults. +EXTRA_DIST = \ + Scripts/sc_default.cpp \ + Scripts/sc_defines.cpp \ + Scripts/sc_defines.h diff --git a/src/bindings/interface/Readme.txt b/src/bindings/interface/Readme.txt new file mode 100644 index 00000000000..e152162de8e --- /dev/null +++ b/src/bindings/interface/Readme.txt @@ -0,0 +1,32 @@ + +** HOW TO SCRIPT IN C++ ** + +1 - create a file myscript.cpp in scripts folder. +2 - copy the content of script_default.cpp, it as the structure on how the scripting fuctions are organized. + dont forget to change the name of fuctions, like GossipHello_default to GossipHello_myscript. + +3 - in fuction AddSC_default change to AddSC_myscript. +4 - newscript->Name="default"; change the string to "myscript" this name is the one to be called from the db +5 - dont forget to change the name in here to newscript->pGossipHello = &GossipHello_default; this is where the scripted fuctions are stored. +6 - and last thing is in ScriptMgr.cpp + +add your AddSC_myscript in here + +// -- Scripts to be added -- +extern void AddSC_default(); +// ------------------- + +and here + +// -- Inicialize the Scripts to be Added -- + AddSC_default(); + // ---------------------------------------- + +now start using the player fuctions to script ;) +see the sc_defines.h for some fuctions to use. + +hope it helps, any question use our forum. + +copy libscript.so and libscript.a to your server/lib path + +made by: mmcs. diff --git a/src/bindings/interface/ScriptMgr.cpp b/src/bindings/interface/ScriptMgr.cpp new file mode 100644 index 00000000000..100159803f5 --- /dev/null +++ b/src/bindings/interface/ScriptMgr.cpp @@ -0,0 +1,328 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" +#include "ScriptMgr.h" +#include "../../game/GossipDef.h" +#include "../../game/GameObject.h" +#include "../../game/Player.h" +#include "../../game/Map.h" +#include "../../game/ObjectMgr.h" + +//uint8 loglevel = 0; +int nrscripts; +Script *m_scripts[MAX_SCRIPTS]; +InstanceDataScript* m_instance_scripts[MAX_INSTANCE_SCRIPTS]; +int num_inst_scripts; + +// -- Scripts to be added -- +extern void AddSC_default(); +// ------------------- + +MANGOS_DLL_EXPORT +void ScriptsFree() +{ // Free resources before library unload + for(int i=0;iName == Name ) + return m_scripts[i]; + } + return NULL; +} + +MANGOS_DLL_EXPORT +bool GossipHello ( Player * player, Creature *_Creature ) +{ + Script *tmpscript = GetScriptByName(_Creature->GetScriptName()); + if(!tmpscript || !tmpscript->pGossipHello) return false; + + player->PlayerTalkClass->ClearMenus(); + return tmpscript->pGossipHello(player,_Creature); +} + +MANGOS_DLL_EXPORT +bool GossipSelect( Player *player, Creature *_Creature,uint32 sender, uint32 action ) +{ + debug_log("DEBUG: Gossip selection, sender: %d, action: %d",sender, action); + + Script *tmpscript = GetScriptByName(_Creature->GetScriptName()); + if(!tmpscript || !tmpscript->pGossipSelect) return false; + + player->PlayerTalkClass->ClearMenus(); + return tmpscript->pGossipSelect(player,_Creature,sender,action); +} + +MANGOS_DLL_EXPORT +bool GossipSelectWithCode( Player *player, Creature *_Creature, uint32 sender, uint32 action, const char* sCode ) +{ + debug_log("DEBUG: Gossip selection, sender: %d, action: %d",sender, action); + + Script *tmpscript = GetScriptByName(_Creature->GetScriptName()); + if(!tmpscript || !tmpscript->pGossipSelectWithCode) return false; + + player->PlayerTalkClass->ClearMenus(); + return tmpscript->pGossipSelectWithCode(player,_Creature,sender,action,sCode); +} + +MANGOS_DLL_EXPORT +bool QuestAccept( Player *player, Creature *_Creature, Quest *_Quest ) +{ + Script *tmpscript = GetScriptByName(_Creature->GetScriptName()); + if(!tmpscript || !tmpscript->pQuestAccept) return false; + + player->PlayerTalkClass->ClearMenus(); + return tmpscript->pQuestAccept(player,_Creature,_Quest); +} + +MANGOS_DLL_EXPORT +bool QuestSelect( Player *player, Creature *_Creature, Quest *_Quest ) +{ + Script *tmpscript = GetScriptByName(_Creature->GetScriptName()); + if(!tmpscript || !tmpscript->pQuestSelect) return false; + + player->PlayerTalkClass->ClearMenus(); + return tmpscript->pQuestSelect(player,_Creature,_Quest); +} + +MANGOS_DLL_EXPORT +bool QuestComplete( Player *player, Creature *_Creature, Quest *_Quest ) +{ + Script *tmpscript = GetScriptByName(_Creature->GetScriptName()); + if(!tmpscript || !tmpscript->pQuestComplete) return false; + + player->PlayerTalkClass->ClearMenus(); + return tmpscript->pQuestComplete(player,_Creature,_Quest); +} + +MANGOS_DLL_EXPORT +bool ChooseReward( Player *player, Creature *_Creature, Quest *_Quest, uint32 opt ) +{ + Script *tmpscript = GetScriptByName(_Creature->GetScriptName()); + if(!tmpscript || !tmpscript->pChooseReward) return false; + + player->PlayerTalkClass->ClearMenus(); + return tmpscript->pChooseReward(player,_Creature,_Quest,opt); +} + +MANGOS_DLL_EXPORT +uint32 NPCDialogStatus( Player *player, Creature *_Creature ) +{ + Script *tmpscript = GetScriptByName(_Creature->GetScriptName()); + if(!tmpscript || !tmpscript->pNPCDialogStatus) return 100; + + player->PlayerTalkClass->ClearMenus(); + return tmpscript->pNPCDialogStatus(player,_Creature); +} + +MANGOS_DLL_EXPORT +uint32 GODialogStatus( Player *player, GameObject *_GO ) +{ + Script *tmpscript = NULL; + + tmpscript = GetScriptByName(_GO->GetGOInfo()->ScriptName); + if(!tmpscript || !tmpscript->pGODialogStatus) return 100; + + player->PlayerTalkClass->ClearMenus(); + return tmpscript->pGODialogStatus(player,_GO); +} + +MANGOS_DLL_EXPORT +bool ItemHello( Player *player, Item *_Item, Quest *_Quest ) +{ + Script *tmpscript = NULL; + + tmpscript = GetScriptByName(_Item->GetProto()->ScriptName); + if(!tmpscript || !tmpscript->pItemHello) return false; + + player->PlayerTalkClass->ClearMenus(); + return tmpscript->pItemHello(player,_Item,_Quest); +} + +MANGOS_DLL_EXPORT +bool ItemQuestAccept( Player *player, Item *_Item, Quest *_Quest ) +{ + Script *tmpscript = NULL; + + tmpscript = GetScriptByName(_Item->GetProto()->ScriptName); + if(!tmpscript || !tmpscript->pItemQuestAccept) return false; + + player->PlayerTalkClass->ClearMenus(); + return tmpscript->pItemQuestAccept(player,_Item,_Quest); +} + +MANGOS_DLL_EXPORT +bool GOHello( Player *player, GameObject *_GO ) +{ + Script *tmpscript = NULL; + + tmpscript = GetScriptByName(_GO->GetGOInfo()->ScriptName); + if(!tmpscript || !tmpscript->pGOHello) return false; + + player->PlayerTalkClass->ClearMenus(); + return tmpscript->pGOHello(player,_GO); +} + +MANGOS_DLL_EXPORT +bool GOQuestAccept( Player *player, GameObject *_GO, Quest *_Quest ) +{ + Script *tmpscript = NULL; + + tmpscript = GetScriptByName(_GO->GetGOInfo()->ScriptName); + if(!tmpscript || !tmpscript->pGOQuestAccept) return false; + + player->PlayerTalkClass->ClearMenus(); + return tmpscript->pGOQuestAccept(player,_GO,_Quest); +} + +MANGOS_DLL_EXPORT +bool GOChooseReward( Player *player, GameObject *_GO, Quest *_Quest, uint32 opt ) +{ + Script *tmpscript = NULL; + + tmpscript = GetScriptByName(_GO->GetGOInfo()->ScriptName); + if(!tmpscript || !tmpscript->pGOChooseReward) return false; + + player->PlayerTalkClass->ClearMenus(); + return tmpscript->pGOChooseReward(player,_GO,_Quest,opt); +} + +MANGOS_DLL_EXPORT +bool AreaTrigger ( Player *player, AreaTriggerEntry* atEntry ) +{ + Script *tmpscript = NULL; + + tmpscript = GetScriptByName(GetAreaTriggerScriptNameById(atEntry->id)); + if(!tmpscript || !tmpscript->pAreaTrigger) return false; + + return tmpscript->pAreaTrigger(player, atEntry); +} + +MANGOS_DLL_EXPORT +bool ReceiveEmote ( Player *player, Creature *_Creature, uint32 emote ) +{ + Script *tmpscript = GetScriptByName(_Creature->GetScriptName()); + if(!tmpscript || !tmpscript->pReceiveEmote) return false; + + return tmpscript->pReceiveEmote(player,_Creature, emote); +} + +MANGOS_DLL_EXPORT +bool ItemUse( Player *player, Item* _Item, SpellCastTargets const& targets) +{ + Script *tmpscript = NULL; + + tmpscript = GetScriptByName(_Item->GetProto()->ScriptName); + if(!tmpscript || !tmpscript->pItemUse) return false; + + return tmpscript->pItemUse(player,_Item,targets); +} + +MANGOS_DLL_EXPORT +CreatureAI* GetAI(Creature *_Creature ) +{ + Script *tmpscript = GetScriptByName(_Creature->GetScriptName()); + if(!tmpscript || !tmpscript->GetAI) return NULL; + + return tmpscript->GetAI(_Creature); +} + +MANGOS_DLL_EXPORT +InstanceData* CreateInstanceData(Map *map) +{ + if(!map->IsDungeon()) return NULL; + std::string name = ((InstanceMap*)map)->GetScript(); + if(!name.empty()) + for(int i=0;iname == name) + return m_instance_scripts[i]->GetInstanceData(map); + return NULL; +} + +void ScriptedAI::UpdateAI(const uint32) +{ + //Check if we have a current target + if( m_creature->isAlive() && m_creature->SelectHostilTarget() && m_creature->getVictim()) + { + //If we are within range melee the target + if( m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE)) + { + if( m_creature->isAttackReady() ) + { + m_creature->AttackerStateUpdate(m_creature->getVictim()); + m_creature->resetAttackTimer(); + } + } + } +} + +void ScriptedAI::EnterEvadeMode() +{ + if( m_creature->isAlive() ) + DoGoHome(); +} + +void ScriptedAI::DoStartAttack(Unit* victim) +{ + if( m_creature->Attack(victim, true) ) + m_creature->GetMotionMaster()->MoveChase(victim); +} + +void ScriptedAI::DoStopAttack() +{ + if( m_creature->getVictim() != NULL ) + { + m_creature->AttackStop(); + } +} + +void ScriptedAI::DoGoHome() +{ + if( !m_creature->getVictim() && m_creature->isAlive() ) + m_creature->GetMotionMaster()->MoveTargetedHome(); +} diff --git a/src/bindings/interface/ScriptMgr.h b/src/bindings/interface/ScriptMgr.h new file mode 100644 index 00000000000..0cc0b4362b8 --- /dev/null +++ b/src/bindings/interface/ScriptMgr.h @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef SCRIPTMGR_H +#define SCRIPTMGR_H + +//Only required includes +#include "../../game/CreatureAI.h" +#include "../../game/Creature.h" +#include "../../game/InstanceData.h" + +class Player; +class Creature; +class Quest; +class Item; +class GameObject; +class SpellCastTargets; +class Map; + +#define MAX_SCRIPTS 1000 +#define MAX_INSTANCE_SCRIPTS 1000 + +struct Script +{ + Script() : + pGossipHello(NULL), pQuestAccept(NULL), pGossipSelect(NULL), pGossipSelectWithCode(NULL), + pQuestSelect(NULL), pQuestComplete(NULL), pNPCDialogStatus(NULL), pGODialogStatus(NULL), pChooseReward(NULL), + pItemHello(NULL), pGOHello(NULL), pAreaTrigger(NULL), pItemQuestAccept(NULL), pGOQuestAccept(NULL), + pGOChooseReward(NULL), pReceiveEmote(NULL), pItemUse(NULL), GetAI(NULL) + {} + + std::string Name; + + // -- Quest/gossip Methods to be scripted -- + bool (*pGossipHello )(Player *player, Creature *_Creature); + bool (*pQuestAccept )(Player *player, Creature *_Creature, Quest const*_Quest ); + bool (*pGossipSelect )(Player *player, Creature *_Creature, uint32 sender, uint32 action ); + bool (*pGossipSelectWithCode)(Player *player, Creature *_Creature, uint32 sender, uint32 action, const char* sCode ); + bool (*pQuestSelect )(Player *player, Creature *_Creature, Quest const*_Quest ); + bool (*pQuestComplete )(Player *player, Creature *_Creature, Quest const*_Quest ); + uint32 (*pNPCDialogStatus )(Player *player, Creature *_Creature ); + uint32 (*pGODialogStatus )(Player *player, GameObject * _GO ); + bool (*pChooseReward )(Player *player, Creature *_Creature, Quest const*_Quest, uint32 opt ); + bool (*pItemHello )(Player *player, Item *_Item, Quest const*_Quest ); + bool (*pGOHello )(Player *player, GameObject *_GO ); + bool (*pAreaTrigger )(Player *player, AreaTriggerEntry* at); + bool (*pItemQuestAccept )(Player *player, Item *_Item, Quest const*_Quest ); + bool (*pGOQuestAccept )(Player *player, GameObject *_GO, Quest const*_Quest ); + bool (*pGOChooseReward )(Player *player, GameObject *_GO, Quest const*_Quest, uint32 opt ); + bool (*pReceiveEmote )(Player *player, Creature *_Creature, uint32 emote ); + bool (*pItemUse )(Player *player, Item* _Item, SpellCastTargets const& targets); + + CreatureAI* (*GetAI)(Creature *_Creature); + // ----------------------------------------- + +}; + +class InstanceDataScript +{ + public: + InstanceDataScript() : GetInstanceData(NULL) {}; + + std::string name; + InstanceData* (*GetInstanceData)(Map *_Map); +}; + +extern int nrscripts; +extern Script *m_scripts[MAX_SCRIPTS]; +extern InstanceDataScript *m_instance_scripts[MAX_INSTANCE_SCRIPTS]; +extern int num_inst_scripts; + +#define VISIBLE_RANGE (50.0f) + +struct MANGOS_DLL_DECL ScriptedAI : public CreatureAI +{ + ScriptedAI(Creature* creature) : m_creature(creature) {} + ~ScriptedAI() {} + + // Called if IsVisible(Unit *who) is true at each *who move + void MoveInLineOfSight(Unit *) {} + + // Called at each attack of m_creature by any victim + void AttackStart(Unit *) {} + + // Called at stopping attack by any attacker + void EnterEvadeMode(); + + // Called at any heal cast/item used (call non implemented) + void HealBy(Unit* /*healer*/, uint32 /*amount_healed*/) {} + + // Called at any Damage to any victim (before damage apply) + void DamageDeal(Unit* /*done_to*/, uint32& /*damage*/) {} + + // Called at any Damage from any attacker (before damage apply) + void DamageTaken(Unit* /*done_by*/, uint32& /*damage*/) {} + + // Is unit visible for MoveInLineOfSight + bool IsVisible(Unit* who) const + { + return !who->HasStealthAura() && m_creature->GetDistance(who) <= VISIBLE_RANGE; + } + + // Called at World update tick + void UpdateAI(const uint32); + + // Called when the creature is killed + void JustDied(Unit *){} + + // Called when the creature kills a unit + void KilledUnit(Unit *){} + + // Called when hit by a spell + void SpellHit(Unit *, const SpellEntry*){} + + Creature* m_creature; + + //= Some useful helpers ========================= + + // Start attack of victim and go to him + void DoStartAttack(Unit* victim); + + // Stop attack of current victim + void DoStopAttack(); + + // Cast spell + void DoCast(Unit* victim, uint32 spelId) + { + m_creature->CastSpell(victim,spelId,true); + } + + void DoCastSpell(Unit* who,SpellEntry *spellInfo) + { + m_creature->CastSpell(who,spellInfo,true); + } + + void DoSay(char const* text, uint32 language) + { + m_creature->Say(text,language,0); + } + + void DoGoHome(); +}; + +#endif diff --git a/src/bindings/interface/Scripts/sc_default.cpp b/src/bindings/interface/Scripts/sc_default.cpp new file mode 100644 index 00000000000..a37ef14c796 --- /dev/null +++ b/src/bindings/interface/Scripts/sc_default.cpp @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "sc_defines.h" + +bool GossipHello_default(Player* /*player*/, Creature* /*_Creature*/) +{ + return false; +} + +bool GossipSelect_default(Player* /*player*/, Creature* /*_Creature*/, uint32 /*sender*/, uint32 /*action*/ ) +{ + return false; +} + +bool GossipSelectWithCode_default( Player* /*player*/, Creature* /*_Creature*/, uint32 /*sender*/, uint32 /*action*/, const char* /*sCode*/ ) +{ + return false; +} + +bool QuestAccept_default(Player* /*player*/, Creature* /*_Creature*/, Quest const* /*_Quest*/ ) +{ + return false; +} + +bool QuestSelect_default(Player* /*player*/, Creature* /*_Creature*/, Quest const* /*_Quest*/ ) +{ + return false; +} + +bool QuestComplete_default(Player* /*player*/, Creature* /*_Creature*/, Quest const* /*_Quest*/ ) +{ + return false; +} + +bool ChooseReward_default(Player* /*player*/, Creature* /*_Creature*/, Quest const* /*_Quest*/, uint32 /*opt*/ ) +{ + return false; +} + +uint32 NPCDialogStatus_default(Player* /*player*/, Creature* /*_Creature*/ ) +{ + return 128; +} + +uint32 GODialogStatus_default(Player* /*player*/, GameObject* /*_Creature*/ ) +{ + return 128; +} + +bool ItemHello_default(Player* /*player*/, Item* /*_Item*/, Quest const* /*_Quest*/ ) +{ + return false; +} + +bool ItemQuestAccept_default(Player* /*player*/, Item* /*_Item*/, Quest const* /*_Quest*/ ) +{ + return false; +} + +bool GOHello_default(Player* /*player*/, GameObject* /*_GO*/ ) +{ + return false; +} + +bool GOQuestAccept_default(Player* /*player*/, GameObject* /*_GO*/, Quest const* /*_Quest*/ ) +{ + return false; +} + +bool GOChooseReward_default(Player* /*player*/, GameObject* /*_GO*/, Quest const* /*_Quest*/, uint32 /*opt*/ ) +{ + return false; +} + +bool AreaTrigger_default(Player* /*player*/, AreaTriggerEntry* /*atEntry*/ ) +{ + return false; +} + +void AddSC_default() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="default"; + newscript->pGossipHello = &GossipHello_default; + newscript->pQuestAccept = &QuestAccept_default; + newscript->pGossipSelect = &GossipSelect_default; + newscript->pGossipSelectWithCode = &GossipSelectWithCode_default; + newscript->pQuestSelect = &QuestSelect_default; + newscript->pQuestComplete = &QuestComplete_default; + newscript->pNPCDialogStatus = &NPCDialogStatus_default; + newscript->pGODialogStatus = &GODialogStatus_default; + newscript->pChooseReward = &ChooseReward_default; + newscript->pItemHello = &ItemHello_default; + newscript->pGOHello = &GOHello_default; + newscript->pAreaTrigger = &AreaTrigger_default; + newscript->pItemQuestAccept = &ItemQuestAccept_default; + newscript->pGOQuestAccept = &GOQuestAccept_default; + newscript->pGOChooseReward = &GOChooseReward_default; + + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/interface/Scripts/sc_defines.cpp b/src/bindings/interface/Scripts/sc_defines.cpp new file mode 100644 index 00000000000..0c93b89649b --- /dev/null +++ b/src/bindings/interface/Scripts/sc_defines.cpp @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "sc_defines.h" + +#include "../../game/Player.h" + +uint32 GetSkillLevel(Player *player,uint32 trskill) +{ + // Returns the level of some tradetrskill known by player + // Need to add missing spells + + uint32 spell_apprentice = 0; + uint32 spell_journeyman = 0; + uint32 spell_expert = 0; + uint32 spell_artisan = 0; + uint32 spell_master = 0; + + switch(trskill) + { + case TRADESKILL_ALCHEMY: + spell_apprentice = 2259; + spell_journeyman = 3101; + spell_expert = 3464; + spell_artisan = 11611; + spell_master = 28596; // teached by 28597 + break; + case TRADESKILL_BLACKSMITHING: + spell_apprentice = 2018; + spell_journeyman = 3100; + spell_expert = 8768; + spell_artisan = 11454; + spell_master = 29844; // teached by 29845 + break; + case TRADESKILL_COOKING: + spell_apprentice = 2550; + spell_journeyman = 3102; + spell_expert = 3413; + spell_artisan = 18260; + spell_master = 33359; // teached by 33361 + break; + case TRADESKILL_ENCHANTING: + spell_apprentice = 7411; + spell_journeyman = 7412; + spell_expert = 7413; + spell_artisan = 13920; + spell_master = 28029; // teached by 28030 + break; + case TRADESKILL_ENGINEERING: + spell_apprentice = 4036; + spell_journeyman = 4037; + spell_expert = 4038; + spell_artisan = 12656; + spell_master = 30350; // teached by 30351 + break; + case TRADESKILL_FIRSTAID: + spell_apprentice = 3273; + spell_journeyman = 3274; + spell_expert = 7924; + spell_artisan = 10846; + spell_master = 27028; // teached by 27029 + break; + case TRADESKILL_HERBALISM: + spell_apprentice = 2372; + spell_journeyman = 2373; + spell_expert = 3571; + spell_artisan = 11994; + spell_master = 0; + break; + case TRADESKILL_LEATHERWORKING: + spell_apprentice = 2108; + spell_journeyman = 3104; + spell_expert = 20649; + spell_artisan = 10662; + spell_master = 32549; // teached by 32550 + break; + case TRADESKILL_POISONS: + spell_apprentice = 0; + spell_journeyman = 0; + spell_expert = 0; + spell_artisan = 0; + spell_master = 0; + break; + case TRADESKILL_TAILORING: + spell_apprentice = 3908; + spell_journeyman = 3909; + spell_expert = 3910; + spell_artisan = 12180; + spell_master = 26790; // teached by 26791 + break; + case TRADESKILL_MINING: + spell_apprentice = 2581; + spell_journeyman = 2582; + spell_expert = 3568; + spell_artisan = 10249; + spell_master = 29354; // teached by 29355 + break; + case TRADESKILL_FISHING: + spell_apprentice = 7733; + spell_journeyman = 7734; + spell_expert = 7736; + spell_artisan = 18249; + spell_master = 33098; // teached by 33100 + break; + case TRADESKILL_SKINNING: + spell_apprentice = 8615; + spell_journeyman = 8619; + spell_expert = 8620; + spell_artisan = 10769; + spell_master = 32679; // teached by 32678 + break; + case TRADESKILL_JEWELCRAFTING: + spell_apprentice = 25229; // teached by 25245 + spell_journeyman = 25230; // teached by 25246 + spell_expert = 28894; // teached by 28896 + spell_artisan = 28895; // teached by 28899 + spell_master = 28897; // teached by 28901 + break; + } + + if (player->HasSpell(spell_master)) + return TRADESKILL_LEVEL_MASTER; + + if (player->HasSpell(spell_artisan)) + return TRADESKILL_LEVEL_ARTISAN; + + if (player->HasSpell(spell_expert)) + return TRADESKILL_LEVEL_EXPERT; + + if (player->HasSpell(spell_journeyman)) + return TRADESKILL_LEVEL_JOURNEYMAN; + + if (player->HasSpell(spell_apprentice)) + return TRADESKILL_LEVEL_APPRENTICE; + + return TRADESKILL_LEVEL_NONE; +} diff --git a/src/bindings/interface/Scripts/sc_defines.h b/src/bindings/interface/Scripts/sc_defines.h new file mode 100644 index 00000000000..c906726f09d --- /dev/null +++ b/src/bindings/interface/Scripts/sc_defines.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef SC_DEFINES_H +#define SC_DEFINES_H + +#include "../ScriptMgr.h" + +// Skill defines + +#define TRADESKILL_ALCHEMY 1 +#define TRADESKILL_BLACKSMITHING 2 +#define TRADESKILL_COOKING 3 +#define TRADESKILL_ENCHANTING 4 +#define TRADESKILL_ENGINEERING 5 +#define TRADESKILL_FIRSTAID 6 +#define TRADESKILL_HERBALISM 7 +#define TRADESKILL_LEATHERWORKING 8 +#define TRADESKILL_POISONS 9 +#define TRADESKILL_TAILORING 10 +#define TRADESKILL_MINING 11 +#define TRADESKILL_FISHING 12 +#define TRADESKILL_SKINNING 13 +#define TRADESKILL_JEWELCRAFTING 14 + +#define TRADESKILL_LEVEL_NONE 0 +#define TRADESKILL_LEVEL_APPRENTICE 1 +#define TRADESKILL_LEVEL_JOURNEYMAN 2 +#define TRADESKILL_LEVEL_EXPERT 3 +#define TRADESKILL_LEVEL_ARTISAN 4 +#define TRADESKILL_LEVEL_MASTER 5 + +// Gossip defines + +#define GOSSIP_ACTION_TRADE 1 +#define GOSSIP_ACTION_TRAIN 2 +#define GOSSIP_ACTION_TAXI 3 +#define GOSSIP_ACTION_GUILD 4 +#define GOSSIP_ACTION_BATTLE 5 +#define GOSSIP_ACTION_BANK 6 +#define GOSSIP_ACTION_INN 7 +#define GOSSIP_ACTION_HEAL 8 +#define GOSSIP_ACTION_TABARD 9 +#define GOSSIP_ACTION_AUCTION 10 +#define GOSSIP_ACTION_INN_INFO 11 +#define GOSSIP_ACTION_UNLEARN 12 +#define GOSSIP_ACTION_INFO_DEF 1000 + +#define GOSSIP_SENDER_MAIN 1 +#define GOSSIP_SENDER_INN_INFO 2 +#define GOSSIP_SENDER_INFO 3 +#define GOSSIP_SENDER_SEC_PROFTRAIN 4 +#define GOSSIP_SENDER_SEC_CLASSTRAIN 5 +#define GOSSIP_SENDER_SEC_BATTLEINFO 6 + +#define DEFAULT_GOSSIP_MESSAGE 0xffffff + +extern uint32 GetSkillLevel(Player *player,uint32 skill); + +// Defined functions to use with player. + +#define ADD_GOSSIP_ITEM(a,b,c,d,e,f) PlayerTalkClass->GetGossipMenu()->AddMenuItem(a,b,c,d,e,f) +#define SEND_GOSSIP_MENU(a,b) PlayerTalkClass->SendGossipMenu(a,b) +#define SEND_POI(a,b,c,d,e,f) PlayerTalkClass->SendPointOfInterest(a,b,c,d,e,f) +#define CLOSE_GOSSIP_MENU() PlayerTalkClass->CloseGossip(); + +#define QUEST_DIALOG_STATUS(a,b,c) GetSession()->getDialogStatus(a,b,c) +#define SEND_QUEST_DETAILS(a,b,c) PlayerTalkClass->SendQuestDetails(a,b,c) +#define SEND_REQUESTEDITEMS(a,b,c,d) PlayerTalkClass->SendRequestedItems(a,b,c,d) + +#define SEND_VENDORLIST(a) GetSession()->SendListInventory(a) +#define SEND_TRAINERLIST(a) GetSession()->SendTrainerList(a) +#define SEND_BANKERLIST(a) GetSession()->SendShowBank(a) +#define SEND_TABARDLIST(a) GetSession()->SendTabardVendorActivate(a) +#define SEND_AUCTIONLIST(a) GetSession()->SendAuctionHello(a) +#define SEND_TAXILIST(a) GetSession()->SendTaxiStatus(a) +#define SEND_SPRESURRECT() GetSession()->SendSpiritResurrect() +#define GET_HONORRANK() GetHonorRank() + +// ----------------------------------- +#endif diff --git a/src/bindings/interface/config.h b/src/bindings/interface/config.h new file mode 100644 index 00000000000..68d428a3809 --- /dev/null +++ b/src/bindings/interface/config.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef CONFIG_H +#define CONFIG_H +#endif +//#define WIN32 + +#ifdef WIN32 +//#include +#define MANGOS_DLL_EXPORT extern "C" __declspec(dllexport) +#elif defined( __GNUC__ ) +#define MANGOS_DLL_EXPORT extern "C" +#else +#define MANGOS_DLL_EXPORT extern "C" export +#endif diff --git a/src/bindings/interface/system.cpp b/src/bindings/interface/system.cpp new file mode 100644 index 00000000000..ad5548072e6 --- /dev/null +++ b/src/bindings/interface/system.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef WIN32 +#include +BOOL APIENTRY DllMain( HANDLE /*hModule*/, DWORD /*ul_reason_for_call*/, LPVOID /*lpReserved*/) +{ + return true; +} +#endif diff --git a/src/bindings/scripts/How to install.txt b/src/bindings/scripts/How to install.txt new file mode 100644 index 00000000000..98fbf290c08 --- /dev/null +++ b/src/bindings/scripts/How to install.txt @@ -0,0 +1,32 @@ +--- How to install ScriptDev2 --- + +1) Download MaNGOS +2) Create a new folder under "src\bindings\" within the MaNGOS source called "ScriptDev2" +3) Checkout the ScriptDev2 trunk from "https://scriptdev2.svn.sourceforge.net/svnroot/scriptdev2" + +4a) On Win32: + - Compile MaNGOS + - Compile ScriptDev2 using the ScriptVC70, ScriptVC80, or ScriptVC90 Solution within the ScriptDev2 folder (this will overwrite the Mangoscript dll in the output directory) + +4b) On Linux: +- Apply MaNGOS-rXXXX-ScriptDev2.patch, where XXXX is the highest version to that of your MaNGOS revision, to Mangos Source +- Compile MaNGOS (ScriptDev2 will automatically be built when compiling Mangos from here on) + +5) Create the default ScriptDev2 database using "sql\created_database.sql", then execute "sql\scriptdev2_structure.sql" on that database. + +6) Execute the included "sql\scripts_mangosd_full.sql" and "sql\scripts_mangosd_additional_req.sql" on your MaNGOS database + +7) Place the included "scriptdev2.conf" file within the directory containing your "mangosd.conf" and "realmd.conf" files. You may need to change this file to match the database you created and any custom settings you wish to use (such as a different locale). + +8) Run mangosd from your output directory + + +To update ScriptDev2: +All you have to do is open src\bindings\ and right click on the ScriptDev2 folder and click "Update" and then follow steps 4, 6, 7, and 8 again. You must still compile MaNGOS before ScriptDev2 when on the Windows platform. + +To update your Database with new Scriptdev2 SQL changes you can either: +a) apply only the changes that were made during that revision by looking in the sql\update folder or (files named rXXX_scriptdev2.sql should be executed on the scriptdev2 db while rXXX_mangos.sql should be executed on your mangos db) +b) reapply "mangos_full_scripts.sql" to your MaNGOS database along with executing "mangos_additional_req.sql" on your MaNGOS database. + +You can view the ScriptDev2 Change Log at: +[url=http://scriptdev2.svn.sourceforge.net/viewvc/scriptdev2/?view=log]http://scriptdev2.svn.sourceforge.net/viewvc/scriptdev2/?view=log[/url] \ No newline at end of file diff --git a/src/bindings/scripts/LICENSE.txt b/src/bindings/scripts/LICENSE.txt new file mode 100644 index 00000000000..69cd8a1df6d --- /dev/null +++ b/src/bindings/scripts/LICENSE.txt @@ -0,0 +1,280 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/src/bindings/scripts/Makefile.am b/src/bindings/scripts/Makefile.am new file mode 100644 index 00000000000..22f4725e2f6 --- /dev/null +++ b/src/bindings/scripts/Makefile.am @@ -0,0 +1,421 @@ +# Copyright © 2005,2006,2007 MaNGOS +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## Process this file with automake to produce Makefile.in + +## Sub-directories to parse +## SUBDIRS = sql + +# build shared library +lib_LTLIBRARIES = libtrinityscript.la + +libtrinityscript_la_CPPFLAGS = \ +$(MYSQL_INCLUDES) \ +$(POSTGRE_INCLUDES) \ +-I$(top_srcdir)/dep/include \ +-I$(top_srcdir)/src/shared \ +-I$(top_srcdir)/src/framework \ +-I$(top_srcdir)/src/game \ +-I$(srcdir)/include \ +-D_TRINITY_SCRIPT_CONFIG='"$(sysconfdir)/trinityscript.conf"' + +libtrinityscript_la_SOURCES = \ +ScriptMgr.cpp \ +ScriptMgr.h \ +include/precompiled.cpp \ +include/precompiled.h \ +include/sc_creature.cpp \ +include/sc_creature.h \ +include/sc_gossip.h \ +include/sc_grid_searchers.h \ +include/sc_instance.h \ +include/sc_item.h \ +scripts/areatrigger/areatrigger_scripts.cpp \ +scripts/boss/boss_emeriss.cpp \ +scripts/boss/boss_lethon.cpp \ +scripts/boss/boss_taerar.cpp \ +scripts/boss/boss_ysondre.cpp \ +scripts/creature/mob_event_ai.cpp \ +scripts/creature/mob_event_ai.h \ +scripts/creature/mob_generic_creature.cpp \ +scripts/creature/simple_ai.cpp \ +scripts/creature/simple_ai.h \ +scripts/custom/custom_example.cpp \ +scripts/custom/custom_gossip_codebox.cpp \ +scripts/custom/test.cpp \ +scripts/go/go_scripts.cpp \ +scripts/guard/guard_ai.cpp \ +scripts/guard/guard_ai.h \ +scripts/guard/guards.cpp \ +scripts/item/item_scripts.cpp \ +scripts/item/item_test.cpp \ +scripts/npc/npc_escortAI.cpp \ +scripts/npc/npc_escortAI.h \ +scripts/npc/npc_innkeeper.cpp \ +scripts/npc/npc_professions.cpp \ +scripts/npc/npcs_special.cpp \ +scripts/zone/alterac_mountains/alterac_mountains.cpp \ +scripts/zone/aunchindoun/auchenai_crypts/boss_exarch_maladaar.cpp \ +scripts/zone/aunchindoun/mana_tombs/boss_nexusprince_shaffar.cpp \ +scripts/zone/aunchindoun/mana_tombs/boss_pandemonius.cpp \ +scripts/zone/aunchindoun/sethekk_halls/boss_darkweaver_syth.cpp \ +scripts/zone/aunchindoun/sethekk_halls/boss_tailonking_ikiss.cpp \ +scripts/zone/aunchindoun/sethekk_halls/def_sethekk_halls.h \ +scripts/zone/aunchindoun/sethekk_halls/instance_sethekk_halls.cpp \ +scripts/zone/aunchindoun/shadow_labyrinth/boss_ambassador_hellmaw.cpp \ +scripts/zone/aunchindoun/shadow_labyrinth/boss_blackheart_the_inciter.cpp \ +scripts/zone/aunchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp \ +scripts/zone/aunchindoun/shadow_labyrinth/boss_murmur.cpp \ +scripts/zone/aunchindoun/shadow_labyrinth/def_shadow_labyrinth.h \ +scripts/zone/aunchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp \ +scripts/zone/azshara/azshara.cpp \ +scripts/zone/azshara/boss_azuregos.cpp \ +scripts/zone/azuremyst_isle/azuremyst_isle.cpp \ +scripts/zone/barrens/the_barrens.cpp \ +scripts/zone/black_temple/black_temple.cpp \ +scripts/zone/black_temple/boss_bloodboil.cpp \ +scripts/zone/black_temple/boss_illidan.cpp \ +scripts/zone/black_temple/boss_mother_shahraz.cpp \ +scripts/zone/black_temple/boss_reliquary_of_souls.cpp \ +scripts/zone/black_temple/boss_shade_of_akama.cpp \ +scripts/zone/black_temple/boss_supremus.cpp \ +scripts/zone/black_temple/boss_teron_gorefiend.cpp \ +scripts/zone/black_temple/boss_warlord_najentus.cpp \ +scripts/zone/black_temple/def_black_temple.h \ +scripts/zone/black_temple/illidari_council.cpp \ +scripts/zone/black_temple/instance_black_temple.cpp \ +scripts/zone/blackrock_depths/blackrock_depths.cpp \ +scripts/zone/blackrock_depths/boss_ambassador_flamelash.cpp \ +scripts/zone/blackrock_depths/boss_angerrel.cpp \ +scripts/zone/blackrock_depths/boss_anubshiah.cpp \ +scripts/zone/blackrock_depths/boss_doomrel.cpp \ +scripts/zone/blackrock_depths/boss_doperel.cpp \ +scripts/zone/blackrock_depths/boss_emperor_dagran_thaurissan.cpp \ +scripts/zone/blackrock_depths/boss_general_angerforge.cpp \ +scripts/zone/blackrock_depths/boss_gloomrel.cpp \ +scripts/zone/blackrock_depths/boss_gorosh_the_dervish.cpp \ +scripts/zone/blackrock_depths/boss_grizzle.cpp \ +scripts/zone/blackrock_depths/boss_haterel.cpp \ +scripts/zone/blackrock_depths/boss_high_interrogator_gerstahn.cpp \ +scripts/zone/blackrock_depths/boss_magmus.cpp \ +scripts/zone/blackrock_depths/boss_moira_bronzebeard.cpp \ +scripts/zone/blackrock_depths/boss_seethrel.cpp \ +scripts/zone/blackrock_depths/boss_vilerel.cpp \ +scripts/zone/blackrock_spire/boss_drakkisath.cpp \ +scripts/zone/blackrock_spire/boss_gyth.cpp \ +scripts/zone/blackrock_spire/boss_halycon.cpp \ +scripts/zone/blackrock_spire/boss_highlord_omokk.cpp \ +scripts/zone/blackrock_spire/boss_mother_smolderweb.cpp \ +scripts/zone/blackrock_spire/boss_overlord_wyrmthalak.cpp \ +scripts/zone/blackrock_spire/boss_pyroguard_emberseer.cpp \ +scripts/zone/blackrock_spire/boss_quartermaster_zigris.cpp \ +scripts/zone/blackrock_spire/boss_rend_blackhand.cpp \ +scripts/zone/blackrock_spire/boss_shadow_hunter_voshgajin.cpp \ +scripts/zone/blackrock_spire/boss_the_beast.cpp \ +scripts/zone/blackrock_spire/boss_warmaster_voone.cpp \ +scripts/zone/blackwing_lair/boss_broodlord_lashlayer.cpp \ +scripts/zone/blackwing_lair/boss_chromaggus.cpp \ +scripts/zone/blackwing_lair/boss_ebonroc.cpp \ +scripts/zone/blackwing_lair/boss_firemaw.cpp \ +scripts/zone/blackwing_lair/boss_flamegor.cpp \ +scripts/zone/blackwing_lair/boss_nefarian.cpp \ +scripts/zone/blackwing_lair/boss_razorgore.cpp \ +scripts/zone/blackwing_lair/boss_vaelastrasz.cpp \ +scripts/zone/blackwing_lair/boss_victor_nefarius.cpp \ +scripts/zone/blackwing_lair/instance_blackwing_lair.cpp \ +scripts/zone/blades_edge_mountains/blades_edge_mountains.cpp \ +scripts/zone/blasted_lands/blasted_lands.cpp \ +scripts/zone/blasted_lands/boss_kruul.cpp \ +scripts/zone/bloodmyst_isle/bloodmyst_isle.cpp \ +scripts/zone/burning_steppes/burning_steppes.cpp \ +scripts/zone/caverns_of_time/dark_portal/boss_aeonus.cpp \ +scripts/zone/caverns_of_time/dark_portal/boss_chrono_lord_deja.cpp \ +scripts/zone/caverns_of_time/dark_portal/boss_temporus.cpp \ +scripts/zone/caverns_of_time/hyjal/boss_archimonde.cpp \ +scripts/zone/caverns_of_time/hyjal/def_hyjal.h \ +scripts/zone/caverns_of_time/hyjal/hyjal.cpp \ +scripts/zone/caverns_of_time/hyjal/hyjalAI.cpp \ +scripts/zone/caverns_of_time/hyjal/hyjalAI.h \ +scripts/zone/caverns_of_time/hyjal/instance_hyjal.cpp \ +scripts/zone/caverns_of_time/old_hillsbrad/boss_captain_skarloc.cpp \ +scripts/zone/caverns_of_time/old_hillsbrad/boss_epoch_hunter.cpp \ +scripts/zone/caverns_of_time/old_hillsbrad/boss_leutenant_drake.cpp \ +scripts/zone/caverns_of_time/old_hillsbrad/def_old_hillsbrad.h \ +scripts/zone/caverns_of_time/old_hillsbrad/instance_old_hillsbrad.cpp \ +scripts/zone/caverns_of_time/old_hillsbrad/old_hillsbrad.cpp \ +scripts/zone/coilfang_resevoir/serpent_shrine/boss_fathomlord_karathress.cpp \ +scripts/zone/coilfang_resevoir/serpent_shrine/boss_hydross_the_unstable.cpp \ +scripts/zone/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp \ +scripts/zone/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp \ +scripts/zone/coilfang_resevoir/serpent_shrine/boss_morogrim_tidewalker.cpp \ +scripts/zone/coilfang_resevoir/serpent_shrine/def_serpent_shrine.h \ +scripts/zone/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp \ +scripts/zone/coilfang_resevoir/steam_vault/boss_hydromancer_thespia.cpp \ +scripts/zone/coilfang_resevoir/steam_vault/boss_mekgineer_steamrigger.cpp \ +scripts/zone/coilfang_resevoir/steam_vault/boss_warlord_kalithresh.cpp \ +scripts/zone/coilfang_resevoir/steam_vault/def_steam_vault.h \ +scripts/zone/coilfang_resevoir/steam_vault/instance_steam_vault.cpp \ +scripts/zone/coilfang_resevoir/underbog/boss_hungarfen.cpp \ +scripts/zone/darkshore/darkshore.cpp \ +scripts/zone/deadmines/deadmines.cpp \ +scripts/zone/dun_morogh/dun_morogh.cpp \ +scripts/zone/dustwallow_marsh/dustwallow_marsh.cpp \ +scripts/zone/eastern_plaguelands/eastern_plaguelands.cpp \ +scripts/zone/elwynn_forest/elwynn_forest.cpp \ +scripts/zone/eversong_woods/eversong_woods.cpp \ +scripts/zone/felwood/felwood.cpp \ +scripts/zone/feralas/feralas.cpp \ +scripts/zone/ghostlands/ghostlands.cpp \ +scripts/zone/gruuls_lair/boss_gruul.cpp \ +scripts/zone/gruuls_lair/boss_high_king_maulgar.cpp \ +scripts/zone/gruuls_lair/def_gruuls_lair.h \ +scripts/zone/gruuls_lair/instance_gruuls_lair.cpp \ +scripts/zone/hellfire_citadel/blood_furnace/boss_broggok.cpp \ +scripts/zone/hellfire_citadel/blood_furnace/boss_kelidan_the_breaker.cpp \ +scripts/zone/hellfire_citadel/blood_furnace/boss_the_maker.cpp \ +scripts/zone/hellfire_citadel/hellfire_ramparts/boss_omor_the_unscarred.cpp \ +scripts/zone/hellfire_citadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp \ +scripts/zone/hellfire_citadel/magtheridons_lair/boss_magtheridon.cpp \ +scripts/zone/hellfire_citadel/magtheridons_lair/def_magtheridons_lair.h \ +scripts/zone/hellfire_citadel/magtheridons_lair/instance_magtheridons_lair.cpp \ +scripts/zone/hellfire_citadel/shattered_halls/boss_nethekurse.cpp \ +scripts/zone/hellfire_citadel/shattered_halls/boss_warbringer_omrogg.cpp \ +scripts/zone/hellfire_citadel/shattered_halls/def_shattered_halls.h \ +scripts/zone/hellfire_citadel/shattered_halls/instance_shattered_halls.cpp \ +scripts/zone/hellfire_peninsula/boss_doomlord_kazzak.cpp \ +scripts/zone/hellfire_peninsula/hellfire_peninsula.cpp \ +scripts/zone/ironforge/ironforge.cpp \ +scripts/zone/isle_of_queldanas/isle_of_queldanas.cpp \ +scripts/zone/karazhan/boss_curator.cpp \ +scripts/zone/karazhan/boss_maiden_of_virtue.cpp \ +scripts/zone/karazhan/boss_midnight.cpp \ +scripts/zone/karazhan/boss_moroes.cpp \ +scripts/zone/karazhan/boss_netherspite.cpp \ +scripts/zone/karazhan/boss_nightbane.cpp \ +scripts/zone/karazhan/boss_prince_malchezaar.cpp \ +scripts/zone/karazhan/boss_shade_of_aran.cpp \ +scripts/zone/karazhan/boss_terestian_illhoof.cpp \ +scripts/zone/karazhan/bosses_opera.cpp \ +scripts/zone/karazhan/def_karazhan.h \ +scripts/zone/karazhan/instance_karazhan.cpp \ +scripts/zone/karazhan/karazhan.cpp \ +scripts/zone/loch_modan/loch_modan.cpp \ +scripts/zone/magisters_terrace/boss_felblood_kaelthas.cpp \ +scripts/zone/magisters_terrace/boss_priestess_delrissa.cpp \ +scripts/zone/magisters_terrace/boss_selin_fireheart.cpp \ +scripts/zone/magisters_terrace/boss_vexallus.cpp \ +scripts/zone/magisters_terrace/def_magisters_terrace.h \ +scripts/zone/magisters_terrace/instance_magisters_terrace.cpp \ +scripts/zone/maraudon/boss_celebras_the_cursed.cpp \ +scripts/zone/maraudon/boss_landslide.cpp \ +scripts/zone/maraudon/boss_noxxion.cpp \ +scripts/zone/maraudon/boss_princess_theradras.cpp \ +scripts/zone/molten_core/boss_baron_geddon.cpp \ +scripts/zone/molten_core/boss_garr.cpp \ +scripts/zone/molten_core/boss_gehennas.cpp \ +scripts/zone/molten_core/boss_golemagg.cpp \ +scripts/zone/molten_core/boss_lucifron.cpp \ +scripts/zone/molten_core/boss_magmadar.cpp \ +scripts/zone/molten_core/boss_majordomo_executus.cpp \ +scripts/zone/molten_core/boss_ragnaros.cpp \ +scripts/zone/molten_core/boss_shazzrah.cpp \ +scripts/zone/molten_core/boss_sulfuron_harbinger.cpp \ +scripts/zone/molten_core/def_molten_core.h \ +scripts/zone/molten_core/instance_molten_core.cpp \ +scripts/zone/molten_core/molten_core.cpp \ +scripts/zone/moonglade/moonglade.cpp \ +scripts/zone/mulgore/mulgore.cpp \ +scripts/zone/nagrand/nagrand.cpp \ +scripts/zone/naxxramas/boss_anubrekhan.cpp \ +scripts/zone/naxxramas/boss_faerlina.cpp \ +scripts/zone/naxxramas/boss_feugen.cpp \ +scripts/zone/naxxramas/boss_gluth.cpp \ +scripts/zone/naxxramas/boss_gothik.cpp \ +scripts/zone/naxxramas/boss_grobbulus.cpp \ +scripts/zone/naxxramas/boss_heigan.cpp \ +scripts/zone/naxxramas/boss_highlord_mograine.cpp \ +scripts/zone/naxxramas/boss_kelthuzad.cpp \ +scripts/zone/naxxramas/boss_lady_blaumeux.cpp \ +scripts/zone/naxxramas/boss_loatheb.cpp \ +scripts/zone/naxxramas/boss_maexxna.cpp \ +scripts/zone/naxxramas/boss_noth.cpp \ +scripts/zone/naxxramas/boss_patchwerk.cpp \ +scripts/zone/naxxramas/boss_razuvious.cpp \ +scripts/zone/naxxramas/boss_sapphiron.cpp \ +scripts/zone/naxxramas/boss_sir_zeliek.cpp \ +scripts/zone/naxxramas/boss_stalagg.cpp \ +scripts/zone/naxxramas/boss_thaddius.cpp \ +scripts/zone/naxxramas/boss_thane_korthazz.cpp \ +scripts/zone/naxxramas/instance_naxxramas.cpp \ +scripts/zone/netherstorm/netherstorm.cpp \ +scripts/zone/onyxias_lair/boss_onyxia.cpp \ +scripts/zone/orgrimmar/orgrimmar.cpp \ +scripts/zone/razorfen_downs/boss_amnennar_the_coldbringer.cpp \ +scripts/zone/ruins_of_ahnqiraj/boss_ayamiss.cpp \ +scripts/zone/ruins_of_ahnqiraj/boss_buru.cpp \ +scripts/zone/ruins_of_ahnqiraj/boss_kurinnaxx.cpp \ +scripts/zone/ruins_of_ahnqiraj/boss_moam.cpp \ +scripts/zone/ruins_of_ahnqiraj/boss_ossirian.cpp \ +scripts/zone/ruins_of_ahnqiraj/boss_rajaxx.cpp \ +scripts/zone/ruins_of_ahnqiraj/instance_ruins_of_ahnqiraj.cpp \ +scripts/zone/scarlet_monastery/boss_arcanist_doan.cpp \ +scripts/zone/scarlet_monastery/boss_azshir_the_sleepless.cpp \ +scripts/zone/scarlet_monastery/boss_bloodmage_thalnos.cpp \ +scripts/zone/scarlet_monastery/boss_herod.cpp \ +scripts/zone/scarlet_monastery/boss_high_inquisitor_fairbanks.cpp \ +scripts/zone/scarlet_monastery/boss_high_inquisitor_whitemane.cpp \ +scripts/zone/scarlet_monastery/boss_houndmaster_loksey.cpp \ +scripts/zone/scarlet_monastery/boss_interrogator_vishas.cpp \ +scripts/zone/scarlet_monastery/boss_scarlet_commander_mograine.cpp \ +scripts/zone/scarlet_monastery/boss_scorn.cpp \ +scripts/zone/scholomance/boss_darkmaster_gandling.cpp \ +scripts/zone/scholomance/boss_death_knight_darkreaver.cpp \ +scripts/zone/scholomance/boss_doctor_theolen_krastinov.cpp \ +scripts/zone/scholomance/boss_illucia_barov.cpp \ +scripts/zone/scholomance/boss_instructor_malicia.cpp \ +scripts/zone/scholomance/boss_jandice_barov.cpp \ +scripts/zone/scholomance/boss_kormok.cpp \ +scripts/zone/scholomance/boss_lord_alexei_barov.cpp \ +scripts/zone/scholomance/boss_lorekeeper_polkelt.cpp \ +scripts/zone/scholomance/boss_ras_frostwhisper.cpp \ +scripts/zone/scholomance/boss_the_ravenian.cpp \ +scripts/zone/scholomance/boss_vectus.cpp \ +scripts/zone/scholomance/def_scholomance.h \ +scripts/zone/scholomance/instance_scholomance.cpp \ +scripts/zone/searing_gorge/searing_gorge.cpp \ +scripts/zone/shadowfang_keep/def_shadowfang_keep.h \ +scripts/zone/shadowfang_keep/instance_shadowfang_keep.cpp \ +scripts/zone/shadowfang_keep/shadowfang_keep.cpp \ +scripts/zone/shadowmoon_valley/boss_doomwalker.cpp \ +scripts/zone/shadowmoon_valley/shadowmoon_valley.cpp \ +scripts/zone/shattrath/shattrath_city.cpp \ +scripts/zone/silithus/silithus.cpp \ +scripts/zone/silvermoon/silvermoon_city.cpp \ +scripts/zone/silverpine_forest/silverpine_forest.cpp \ +scripts/zone/stonetalon_mountains/stonetalon_mountains.cpp \ +scripts/zone/stormwind/stormwind_city.cpp \ +scripts/zone/stranglethorn_vale/stranglethorn_vale.cpp \ +scripts/zone/stratholme/boss_baron_rivendare.cpp \ +scripts/zone/stratholme/boss_baroness_anastari.cpp \ +scripts/zone/stratholme/boss_cannon_master_willey.cpp \ +scripts/zone/stratholme/boss_dathrohan_balnazzar.cpp \ +scripts/zone/stratholme/boss_magistrate_barthilas.cpp \ +scripts/zone/stratholme/boss_maleki_the_pallid.cpp \ +scripts/zone/stratholme/boss_nerubenkan.cpp \ +scripts/zone/stratholme/boss_order_of_silver_hand.cpp \ +scripts/zone/stratholme/boss_postmaster_malown.cpp \ +scripts/zone/stratholme/boss_ramstein_the_gorger.cpp \ +scripts/zone/stratholme/boss_timmy_the_cruel.cpp \ +scripts/zone/stratholme/def_stratholme.h \ +scripts/zone/stratholme/instance_stratholme.cpp \ +scripts/zone/stratholme/stratholme.cpp \ +scripts/zone/sunwell_plateau/boss_brutallus.cpp \ +scripts/zone/sunwell_plateau/boss_kalecgos.cpp \ +scripts/zone/sunwell_plateau/def_sunwell_plateau.h \ +scripts/zone/sunwell_plateau/instance_sunwell_plateau.cpp \ +scripts/zone/tanaris/tanaris.cpp \ +scripts/zone/tempest_keep/arcatraz/arcatraz.cpp \ +scripts/zone/tempest_keep/arcatraz/boss_harbinger_skyriss.cpp \ +scripts/zone/tempest_keep/arcatraz/def_arcatraz.h \ +scripts/zone/tempest_keep/arcatraz/instance_arcatraz.cpp \ +scripts/zone/tempest_keep/botanica/boss_high_botanist_freywinn.cpp \ +scripts/zone/tempest_keep/botanica/boss_laj.cpp \ +scripts/zone/tempest_keep/botanica/boss_warp_splinter.cpp \ +scripts/zone/tempest_keep/the_eye/boss_astromancer.cpp \ +scripts/zone/tempest_keep/the_eye/boss_kaelthas.cpp \ +scripts/zone/tempest_keep/the_eye/boss_void_reaver.cpp \ +scripts/zone/tempest_keep/the_eye/def_the_eye.h \ +scripts/zone/tempest_keep/the_eye/instance_the_eye.cpp \ +scripts/zone/tempest_keep/the_eye/the_eye.cpp \ +scripts/zone/tempest_keep/the_mechanar/boss_gatewatcher_gyrokill.cpp \ +scripts/zone/tempest_keep/the_mechanar/boss_gatewatcher_ironhand.cpp \ +scripts/zone/tempest_keep/the_mechanar/boss_nethermancer_sepethrea.cpp \ +scripts/zone/temple_of_ahnqiraj/boss_bug_trio.cpp \ +scripts/zone/temple_of_ahnqiraj/boss_cthun.cpp \ +scripts/zone/temple_of_ahnqiraj/boss_fankriss.cpp \ +scripts/zone/temple_of_ahnqiraj/boss_huhuran.cpp \ +scripts/zone/temple_of_ahnqiraj/boss_ouro.cpp \ +scripts/zone/temple_of_ahnqiraj/boss_sartura.cpp \ +scripts/zone/temple_of_ahnqiraj/boss_skeram.cpp \ +scripts/zone/temple_of_ahnqiraj/boss_twinemperors.cpp \ +scripts/zone/temple_of_ahnqiraj/boss_viscidus.cpp \ +scripts/zone/temple_of_ahnqiraj/def_temple_of_ahnqiraj.h \ +scripts/zone/temple_of_ahnqiraj/instance_temple_of_ahnqiraj.cpp \ +scripts/zone/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp \ +scripts/zone/terokkar_forest/terokkar_forest.cpp \ +scripts/zone/thunder_bluff/thunder_bluff.cpp \ +scripts/zone/tirisfal_glades/tirisfal_glades.cpp \ +scripts/zone/uldaman/boss_ironaya.cpp \ +scripts/zone/uldaman/uldaman.cpp \ +scripts/zone/undercity/undercity.cpp \ +scripts/zone/wailing_caverns/instance_wailing_caverns.cpp \ +scripts/zone/western_plaguelands/western_plaguelands.cpp \ +scripts/zone/winterspring/winterspring.cpp \ +scripts/zone/zangarmarsh/zangarmarsh.cpp \ +scripts/zone/zulaman/boss_janalai.cpp \ +scripts/zone/zulaman/boss_nalorakk.cpp \ +scripts/zone/zulaman/def_zulaman.h \ +scripts/zone/zulaman/instance_zulaman.cpp \ +scripts/zone/zulaman/zulaman.cpp \ +scripts/zone/zulfarrak/zulfarrak.cpp \ +scripts/zone/zulgurub/boss_arlokk.cpp \ +scripts/zone/zulgurub/boss_gahzranka.cpp \ +scripts/zone/zulgurub/boss_grilek.cpp \ +scripts/zone/zulgurub/boss_hakkar.cpp \ +scripts/zone/zulgurub/boss_hazzarah.cpp \ +scripts/zone/zulgurub/boss_jeklik.cpp \ +scripts/zone/zulgurub/boss_jindo.cpp \ +scripts/zone/zulgurub/boss_mandokir.cpp \ +scripts/zone/zulgurub/boss_marli.cpp \ +scripts/zone/zulgurub/boss_renataki.cpp \ +scripts/zone/zulgurub/boss_thekal.cpp \ +scripts/zone/zulgurub/boss_venoxis.cpp \ +scripts/zone/zulgurub/boss_wushoolay.cpp \ +scripts/zone/zulgurub/def_zulgurub.h \ +scripts/zone/zulgurub/instance_zulgurub.cpp \ +system.cpp + +## libtool settings +# API versioning +# Increase the last number, if you do bug fixes only, no interface change. +# Increase the middle number when you augmented the interface ( aka add new exported functions ). +# Increase the first number when you break old interface. ( aka remove/change previously exported functions ). +libtrinityscript_la_LIBFLAGS = -version-info 0:0:1 +libtrinityscript_la_LIBADD = $(MYSQL_LIBS) $(POSTGRE_LIBS) + +## Additional files to include when running 'make dist' +# Scripts defaults. +EXTRA_DIST = \ + Scripts/sc_default.cpp \ + Scripts/sc_defines.cpp \ + Scripts/sc_defines.h + +## Additional files to install +sysconf_DATA = \ + trinityscript.conf.dist + +## Prevend overwrite of the config file, if its already installed +install-data-hook: + @list='$(sysconf_DATA)'; for p in $$list; do \ + dest=`echo $$p | sed -e s/.dist//`; \ + if test -f $(DESTDIR)$(sysconfdir)/$$dest; then \ + echo "$@ will not overwrite existing $(DESTDIR)$(sysconfdir)/$$dest"; \ + else \ + echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(sysconfdir)/$$dest"; \ + $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(sysconfdir)/$$dest; \ + fi; \ + done + diff --git a/src/bindings/scripts/ScriptMgr.cpp b/src/bindings/scripts/ScriptMgr.cpp new file mode 100644 index 00000000000..4768a614e5d --- /dev/null +++ b/src/bindings/scripts/ScriptMgr.cpp @@ -0,0 +1,2113 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#include "precompiled.h" +#include "Config/Config.h" +#include "ProgressBar.h" +#include "Database/DBCStores.h" +#include "Database/DatabaseMysql.h" +#include "ObjectMgr.h" +#include "scripts/creature/mob_event_ai.h" + +#define _FULLVERSION "TrinityScript" + +#ifndef _TSCRIPTCONFVERSION +# define _TSCRIPTCONFVERSION 2008100201 +#endif //_TSCRIPTCONFVERSION + +#ifndef _TRINITY_SCRIPT_CONFIG +# define _TRINITY_SCRIPT_CONFIG "trinityscript.conf" +#endif //_TRINITY_SCRIPT_CONFIG + +//*** Global data *** +int nrscripts; +Script *m_scripts[MAX_SCRIPTS]; + +// Text Map for Event AI +HM_NAMESPACE::hash_map EventAI_Text_Map; + +// Script Text used as says / yells / text emotes / whispers in scripts. +struct ScriptText +{ + uint32 SoundId; + uint8 Type; + uint32 Language; + std::string Text; +}; + +// Enums used by ScriptText::Type +enum ChatType +{ + CHAT_TYPE_SAY = 0, + CHAT_TYPE_YELL = 1, + CHAT_TYPE_TEXT_EMOTE = 2, + CHAT_TYPE_BOSS_EMOTE = 3, + CHAT_TYPE_WHISPER = 4, + CHAT_TYPE_BOSS_WHISPER = 5, +}; + +HM_NAMESPACE::hash_map Script_TextMap; + +// Localized Text structure for storing locales (for EAI and SD2 scripts). +struct Localized_Text +{ + std::string locale_1; + std::string locale_2; + std::string locale_3; + std::string locale_4; + std::string locale_5; + std::string locale_6; + std::string locale_7; + std::string locale_8; +}; +HM_NAMESPACE::hash_map EventAI_LocalizedTextMap; +HM_NAMESPACE::hash_map Script_LocalizedTextMap; + +//*** End Global data *** + +//*** EventAI data *** +//Event AI structure. Used exclusivly by mob_event_ai.cpp (60 bytes each) +std::list EventAI_Event_List; + +//Event AI summon structure. Used exclusivly by mob_event_ai.cpp. +HM_NAMESPACE::hash_map EventAI_Summon_Map; + +//Event AI error prevention structure. Used at runtime to prevent error log spam of same creature id. +//HM_NAMESPACE::hash_map EventAI_CreatureErrorPreventionList; + +uint32 EAI_ErrorLevel; + +//*** End EventAI data *** + +DatabaseMysql ScriptDev2DB; +Config SD2Config; +uint32 Locale; + +void FillSpellSummary(); + +// -- Scripts to be added -- + +// -- Areatrigger -- +extern void AddSC_areatrigger_scripts(); + +// -- Boss -- +extern void AddSC_boss_emeriss(); +extern void AddSC_boss_taerar(); +extern void AddSC_boss_ysondre(); + +// -- Creature -- +extern void AddSC_mob_event(); +extern void AddSC_generic_creature(); + +// -- Custom -- +extern void AddSC_custom_example(); +extern void AddSC_custom_gossip_codebox(); +extern void AddSC_test(); + +// -- GO -- +extern void AddSC_go_scripts(); + +// -- Guard -- +extern void AddSC_guards(); + +// -- Honor -- + +// -- Item -- +extern void AddSC_item_scripts(); +extern void AddSC_item_test(); + +// -- NPC -- +extern void AddSC_npc_professions(); +extern void AddSC_npcs_special(); + +// -- Servers -- + +//-------------------- +//------ ZONE -------- + +//Alterac Mountains +extern void AddSC_alterac_mountains(); + +//Arathi Highlands +//Ashenvale Forest +//Aunchindoun +//--Auchenai Crypts +extern void AddSC_boss_exarch_maladaar(); +//--Mana Tombs +extern void AddSC_boss_nexusprince_shaffar(); +extern void AddSC_boss_pandemonius(); + +//--Sekketh Halls +extern void AddSC_boss_darkweaver_syth(); +extern void AddSC_boss_talon_king_ikiss(); +extern void AddSC_instance_sethekk_halls(); + +//--Shadow Labyrinth +extern void AddSC_boss_ambassador_hellmaw(); +extern void AddSC_boss_blackheart_the_inciter(); +extern void AddSC_boss_grandmaster_vorpil(); +extern void AddSC_boss_murmur(); +extern void AddSC_instance_shadow_labyrinth(); + +//Azshara +extern void AddSC_boss_azuregos(); +extern void AddSC_azshara(); + +//Azuremyst Isle +extern void AddSC_azuremyst_isle(); + +//Badlands +//Barrens +extern void AddSC_the_barrens(); + +//Black Temple +extern void AddSC_black_temple(); +extern void AddSC_boss_illidan(); +extern void AddSC_boss_shade_of_akama(); +extern void AddSC_boss_supremus(); +extern void AddSC_boss_gurtogg_bloodboil(); +extern void AddSC_boss_mother_shahraz(); +extern void AddSC_boss_reliquary_of_souls(); +extern void AddSC_boss_teron_gorefiend(); +extern void AddSC_boss_najentus(); +extern void AddSC_boss_illidari_council(); +extern void AddSC_instance_black_temple(); + +//Blackfathom Depths +//Blackrock Depths +extern void AddSC_blackrock_depths(); +extern void AddSC_boss_ambassador_flamelash(); +extern void AddSC_boss_angerrel(); +extern void AddSC_boss_anubshiah(); +extern void AddSC_boss_doomrel(); +extern void AddSC_boss_doperel(); +extern void AddSC_boss_draganthaurissan(); +extern void AddSC_boss_general_angerforge(); +extern void AddSC_boss_gloomrel(); +extern void AddSC_boss_gorosh_the_dervish(); +extern void AddSC_boss_grizzle(); +extern void AddSC_boss_haterel(); +extern void AddSC_boss_high_interrogator_gerstahn(); +extern void AddSC_boss_magmus(); +extern void AddSC_boss_moira_bronzebeard(); +extern void AddSC_boss_seethrel(); +extern void AddSC_boss_vilerel(); + +//Blackrock Spire +extern void AddSC_boss_drakkisath(); +extern void AddSC_boss_halycon(); +extern void AddSC_boss_highlordomokk(); +extern void AddSC_boss_mothersmolderweb(); +extern void AddSC_boss_overlordwyrmthalak(); +extern void AddSC_boss_shadowvosh(); +extern void AddSC_boss_thebeast(); +extern void AddSC_boss_warmastervoone(); +extern void AddSC_boss_quatermasterzigris(); +extern void AddSC_boss_pyroguard_emberseer(); +extern void AddSC_boss_gyth(); +extern void AddSC_boss_rend_blackhand(); + +//Blackwing lair +extern void AddSC_boss_razorgore(); +extern void AddSC_boss_vael(); +extern void AddSC_boss_broodlord(); +extern void AddSC_boss_firemaw(); +extern void AddSC_boss_ebonroc(); +extern void AddSC_boss_flamegor(); +extern void AddSC_boss_chromaggus(); +extern void AddSC_boss_nefarian(); +extern void AddSC_boss_victor_nefarius(); + +//Blade's Edge Mountains +extern void AddSC_blades_edge_mountains(); + +//Blasted lands +extern void AddSC_boss_kruul(); +extern void AddSC_blasted_lands(); + +//Bloodmyst Isle +extern void AddSC_bloodmyst_isle(); + +//Burning steppes +extern void AddSC_burning_steppes(); + +//Caverns of Time +//--Battle for Mt. Hyjal +extern void AddSC_hyjal(); +extern void AddSC_boss_archimonde(); +extern void AddSC_instance_mount_hyjal(); + +//--Old Hillsbrad +extern void AddSC_boss_captain_skarloc(); +extern void AddSC_boss_epoch_hunter(); +extern void AddSC_boss_lieutenant_drake(); +extern void AddSC_instance_old_hillsbrad(); +extern void AddSC_old_hillsbrad(); + +//--The Dark Portal +extern void AddSC_boss_aeonus(); +extern void AddSC_boss_chrono_lord_deja(); +extern void AddSC_boss_temporus(); + +//Coilfang Resevoir +//--Serpent Shrine Cavern +extern void AddSC_boss_fathomlord_karathress(); +extern void AddSC_boss_hydross_the_unstable(); +extern void AddSC_boss_lady_vashj(); +extern void AddSC_boss_leotheras_the_blind(); +extern void AddSC_boss_morogrim_tidewalker(); +extern void AddSC_instance_serpentshrine_cavern(); + +//--Slave Pens + +//--Steam Vault +extern void AddSC_boss_hydromancer_thespia(); +extern void AddSC_boss_mekgineer_steamrigger(); +extern void AddSC_boss_warlord_kalithresh(); +extern void AddSC_instance_steam_vault(); + +//--Underbog +extern void AddSC_boss_hungarfen(); + +//Darkshore +//Darnassus +//Deadmines +//Deadwind pass +//Desolace +//Dire Maul +//Dun Morogh +extern void AddSC_dun_morogh(); + +//Durotar +//Duskwood +//Dustwallow marsh +extern void AddSC_dustwallow_marsh(); + +//Eversong Woods +extern void AddSC_eversong_woods(); + +//Exodar +//Eastern Plaguelands +extern void AddSC_eastern_plaguelands(); + +//Elwynn Forest +extern void AddSC_elwynn_forest(); + +//Felwood +extern void AddSC_felwood(); + +//Feralas +extern void AddSC_feralas(); + +//Ghostlands +extern void AddSC_ghostlands(); + +//Gnomeregan +//Gruul's Lair +extern void AddSC_boss_gruul(); +extern void AddSC_boss_high_king_maulgar(); +extern void AddSC_instance_gruuls_lair(); + +//Hellfire Citadel +//--Blood Furnace +extern void AddSC_boss_broggok(); +extern void AddSC_boss_kelidan_the_breaker(); +extern void AddSC_boss_the_maker(); + +//--Magtheridon's Lair +extern void AddSC_boss_magtheridon(); +extern void AddSC_instance_magtheridons_lair(); + +//--Shattered Halls +extern void AddSC_boss_grand_warlock_nethekurse(); +extern void AddSC_boss_warbringer_omrogg(); +extern void AddSC_instance_shattered_halls(); + +//--Ramparts +extern void AddSC_boss_watchkeeper_gargolmar(); +extern void AddSC_boss_omor_the_unscarred(); + +//Hellfire Peninsula +extern void AddSC_boss_doomlordkazzak(); +extern void AddSC_hellfire_peninsula(); + +//Hillsbrad Foothills +//Hinterlands +//Ironforge +extern void AddSC_ironforge(); + +//Isle of Quel'Danas +extern void AddSC_isle_of_queldanas(); + +//Karazhan +extern void AddSC_boss_attumen(); +extern void AddSC_boss_curator(); +extern void AddSC_boss_maiden_of_virtue(); +extern void AddSC_boss_shade_of_aran(); +extern void AddSC_boss_malchezaar(); +extern void AddSC_boss_terestian_illhoof(); +extern void AddSC_netherspite_infernal(); +extern void AddSC_boss_moroes(); +extern void AddSC_bosses_opera(); +extern void AddSC_instance_karazhan(); +extern void AddSC_karazhan(); + +//Loch Modan +extern void AddSC_loch_modan(); + +//Lower Blackrock Spire + +// Magister's Terrace +extern void AddSC_boss_felblood_kaelthas(); +extern void AddSC_boss_selin_fireheart(); +extern void AddSC_boss_vexallus(); +extern void AddSC_boss_priestess_delrissa(); +extern void AddSC_instance_magisters_terrace(); + +//Maraudon +extern void AddSC_boss_celebras_the_cursed(); +extern void AddSC_boss_landslide(); +extern void AddSC_boss_noxxion(); +extern void AddSC_boss_ptheradras(); + +//Molten core +extern void AddSC_boss_lucifron(); +extern void AddSC_boss_magmadar(); +extern void AddSC_boss_gehennas(); +extern void AddSC_boss_garr(); +extern void AddSC_boss_baron_geddon(); +extern void AddSC_boss_shazzrah(); +extern void AddSC_boss_golemagg(); +extern void AddSC_boss_sulfuron(); +extern void AddSC_boss_majordomo(); +extern void AddSC_boss_ragnaros(); +extern void AddSC_instance_molten_core(); +extern void AddSC_molten_core(); + +//Moonglade +extern void AddSC_moonglade(); + +//Mulgore +extern void AddSC_mulgore(); + +//Nagrand +extern void AddSC_nagrand(); + +//Naxxramas +extern void AddSC_boss_anubrekhan(); +extern void AddSC_boss_maexxna(); +extern void AddSC_boss_patchwerk(); +extern void AddSC_boss_razuvious(); +extern void AddSC_boss_highlord_mograine(); +extern void AddSC_boss_lady_blaumeux(); +extern void AddSC_boss_sir_zeliek(); +extern void AddSC_boss_thane_korthazz(); +extern void AddSC_boss_kelthuzad(); +extern void AddSC_boss_faerlina(); +extern void AddSC_boss_loatheb(); +extern void AddSC_boss_noth(); +extern void AddSC_boss_gluth(); +extern void AddSC_boss_sapphiron(); + +//Netherstorm +extern void AddSC_netherstorm(); + +//Onyxia's Lair +extern void AddSC_boss_onyxia(); + +//Orgrimmar +extern void AddSC_orgrimmar(); + +//Ragefire Chasm +//Razorfen Downs +extern void AddSC_boss_amnennar_the_coldbringer(); + +//Redridge Mountains +//Ruins of Ahn'Qiraj +//Scarlet Monastery +extern void AddSC_boss_arcanist_doan(); +extern void AddSC_boss_azshir_the_sleepless(); +extern void AddSC_boss_bloodmage_thalnos(); +extern void AddSC_boss_herod(); +extern void AddSC_boss_high_inquisitor_fairbanks(); +extern void AddSC_boss_high_inquisitor_whitemane(); +extern void AddSC_boss_houndmaster_loksey(); +extern void AddSC_boss_interrogator_vishas(); +extern void AddSC_boss_scarlet_commander_mograine(); +extern void AddSC_boss_scorn(); + +//Scholomance +extern void AddSC_boss_darkmaster_gandling(); +extern void AddSC_boss_death_knight_darkreaver(); +extern void AddSC_boss_theolenkrastinov(); +extern void AddSC_boss_illuciabarov(); +extern void AddSC_boss_instructormalicia(); +extern void AddSC_boss_jandicebarov(); +extern void AddSC_boss_kormok(); +extern void AddSC_boss_lordalexeibarov(); +extern void AddSC_boss_lorekeeperpolkelt(); +extern void AddSC_boss_rasfrost(); +extern void AddSC_boss_theravenian(); +extern void AddSC_boss_vectus(); +extern void AddSC_instance_scholomance(); + +//Searing gorge +extern void AddSC_searing_gorge(); + +//Shadowfang keep +extern void AddSC_shadowfang_keep(); +extern void AddSC_instance_shadowfang_keep(); + +//Shadowmoon Valley +extern void AddSC_boss_doomwalker(); +extern void AddSC_shadowmoon_valley(); + +//Shattrath +extern void AddSC_shattrath_city(); + +//Silithus +extern void AddSC_silithus(); + +//Silvermoon +extern void AddSC_silvermoon_city(); + +//Silverpine forest +extern void AddSC_silverpine_forest(); + +//Stockade +//Stonetalon mountains +extern void AddSC_stonetalon_mountains(); + +//Stormwind City +extern void AddSC_stormwind_city(); + +//Stranglethorn Vale +extern void AddSC_stranglethorn_vale(); + +//Stratholme +extern void AddSC_boss_magistrate_barthilas(); +extern void AddSC_boss_maleki_the_pallid(); +extern void AddSC_boss_nerubenkan(); +extern void AddSC_boss_cannon_master_willey(); +extern void AddSC_boss_baroness_anastari(); +extern void AddSC_boss_ramstein_the_gorger(); +extern void AddSC_boss_timmy_the_cruel(); +extern void AddSC_boss_postmaster_malown(); +extern void AddSC_boss_baron_rivendare(); +extern void AddSC_boss_dathrohan_balnazzar(); +extern void AddSC_boss_order_of_silver_hand(); +extern void AddSC_instance_stratholme(); +extern void AddSC_stratholme(); + +//Sunken Temple +//Tanaris +extern void AddSC_tanaris(); + +//Teldrassil +//Tempest Keep +//--Arcatraz +extern void AddSC_arcatraz(); +extern void AddSC_boss_harbinger_skyriss(); +extern void AddSC_instance_arcatraz(); + +//--Botanica +extern void AddSC_boss_high_botanist_freywinn(); +extern void AddSC_boss_laj(); +extern void AddSC_boss_warp_splinter(); + +//--The Eye +extern void AddSC_boss_kaelthas(); +extern void AddSC_boss_void_reaver(); +extern void AddSC_boss_high_astromancer_solarian(); +extern void AddSC_instance_the_eye(); +extern void AddSC_the_eye(); + +//--The Mechanar +extern void AddSC_boss_gatewatcher_iron_hand(); +extern void AddSC_boss_nethermancer_sepethrea(); + +//Temple of ahn'qiraj +extern void AddSC_boss_cthun(); +extern void AddSC_boss_fankriss(); +extern void AddSC_boss_huhuran(); +extern void AddSC_bug_trio(); +extern void AddSC_boss_sartura(); +extern void AddSC_boss_skeram(); +extern void AddSC_boss_twinemperors(); +extern void AddSC_mob_anubisath_sentinel(); +extern void AddSC_instance_temple_of_ahnqiraj(); + +//Terokkar Forest +extern void AddSC_terokkar_forest(); + +//Thousand Needles +//Thunder Bluff +extern void AddSC_thunder_bluff(); + +//Tirisfal Glades +extern void AddSC_tirisfal_glades(); + +//Uldaman +extern void AddSC_boss_ironaya(); +extern void AddSC_uldaman(); + +//Undercity +extern void AddSC_undercity(); + +//Un'Goro Crater +//Upper blackrock spire +//Wailing caverns + +//Western plaguelands +extern void AddSC_western_plaguelands(); + +//Westfall +//Wetlands +//Winterspring +extern void AddSC_winterspring(); + +//Zangarmarsh +extern void AddSC_zangarmarsh(); + +//Zul'Farrak +//Zul'Gurub +extern void AddSC_boss_jeklik(); +extern void AddSC_boss_venoxis(); +extern void AddSC_boss_marli(); +extern void AddSC_boss_mandokir(); +extern void AddSC_boss_gahzranka(); +extern void AddSC_boss_thekal(); +extern void AddSC_boss_arlokk(); +extern void AddSC_boss_jindo(); +extern void AddSC_boss_hakkar(); +extern void AddSC_boss_grilek(); +extern void AddSC_boss_hazzarah(); +extern void AddSC_boss_renataki(); +extern void AddSC_boss_wushoolay(); +extern void AddSC_instance_zulgurub(); +//Zul'Aman +extern void AddSC_boss_janalai(); +extern void AddSC_boss_nalorakk(); +extern void AddSC_instance_zulaman(); +extern void AddSC_zulaman(); + +// ------------------- +void LoadDatabase() +{ + //Get db string from file + char const* dbstring = NULL; + if (!SD2Config.GetString("ScriptDev2DatabaseInfo", &dbstring)) + error_log("SD2: Missing ScriptDev2 Database Info from configuration file"); + + //Initilize connection to DB + if (!dbstring || !ScriptDev2DB.Initialize(dbstring)) + error_db_log("SD2: Unable to connect to Database"); + else + { + //***Preform all DB queries here*** + QueryResult *result; + + //Get Version information + result = ScriptDev2DB.PQuery("SELECT `version`" + "FROM `sd2_db_version`"); + + if (result) + { + Field *fields = result->Fetch(); + outstring_log(" "); + outstring_log("SD2: Database version is: %s", fields[0].GetString()); + outstring_log(" "); + delete result; + + }else error_db_log("SD2: Missing sd2_db_version information."); + + // Drop existing Event AI Localized Text hash map + EventAI_LocalizedTextMap.clear(); + + // Gather EventAI Localized Texts + result = ScriptDev2DB.PQuery("SELECT `id`,`locale_1`,`locale_2`,`locale_3`,`locale_4`,`locale_5`,`locale_6`,`locale_7`,`locale_8`" + "FROM `eventai_localized_texts`"); + + if(result) + { + outstring_log("Loading EAI Localized Texts...."); + barGoLink bar(result->GetRowCount()); + uint32 count = 0; + + do + { + Localized_Text temp; + bar.step(); + + Field *fields = result->Fetch(); + + uint32 i = fields[0].GetInt32(); + + temp.locale_1 = fields[1].GetString(); + temp.locale_2 = fields[2].GetString(); + temp.locale_3 = fields[3].GetString(); + temp.locale_4 = fields[4].GetString(); + temp.locale_5 = fields[5].GetString(); + temp.locale_6 = fields[6].GetString(); + temp.locale_7 = fields[7].GetString(); + temp.locale_8 = fields[8].GetString(); + + EventAI_LocalizedTextMap[i] = temp; + ++count; + + }while(result->NextRow()); + + delete result; + + outstring_log(""); + outstring_log("SD2: Loaded %u EventAI Localized Texts", count); + }else outstring_log("SD2: WARNING >> Loaded 0 EventAI Localized Texts. Database table `eventai_localized_texts` is empty"); + + // Drop Existing Script Localized Text Hash Map + Script_LocalizedTextMap.clear(); + + // Gather Script Localized Texts + result = ScriptDev2DB.PQuery("SELECT `id`,`locale_1`,`locale_2`,`locale_3`,`locale_4`,`locale_5`,`locale_6`,`locale_7`,`locale_8`" + "FROM `script_localized_texts`"); + + if(result) + { + outstring_log("Loading Script Localized Texts...."); + barGoLink bar(result->GetRowCount()); + uint32 count = 0; + + do + { + Localized_Text temp; + bar.step(); + + Field *fields = result->Fetch(); + + uint32 i = fields[0].GetInt32(); + + temp.locale_1 = fields[1].GetString(); + temp.locale_2 = fields[2].GetString(); + temp.locale_3 = fields[3].GetString(); + temp.locale_4 = fields[4].GetString(); + temp.locale_5 = fields[5].GetString(); + temp.locale_6 = fields[6].GetString(); + temp.locale_7 = fields[7].GetString(); + temp.locale_8 = fields[8].GetString(); + + Script_LocalizedTextMap[i] = temp; + ++count; + + }while(result->NextRow()); + + delete result; + + outstring_log(""); + outstring_log("SD2: Loaded %u Script Localized Texts", count); + }else outstring_log("SD2: WARNING >> Loaded 0 Script Localized Texts. Database table `script_localized_texts` is empty"); + + //Drop existing EventAI Text hash map + EventAI_Text_Map.clear(); + + //Gather EventAI Text Entries + result = ScriptDev2DB.PQuery("SELECT `id`,`text` FROM `eventai_texts`"); + + if (result) + { + outstring_log( "SD2: Loading EventAI_Texts..."); + barGoLink bar(result->GetRowCount()); + uint32 Count = 0; + + do + { + bar.step(); + Field *fields = result->Fetch(); + + uint32 i = fields[0].GetInt32(); + + std::string text = fields[1].GetString(); + + if (!strlen(text.c_str())) + error_db_log("SD2: EventAI text %u is empty", i); + + EventAI_Text_Map[i] = text; + ++Count; + + }while (result->NextRow()); + + delete result; + + outstring_log(""); + outstring_log("SD2: >> Loaded %u EventAI_Texts", Count); + + }else outstring_log("SD2: WARNING >> Loaded 0 EventAI_Texts. DB table `EventAI_Texts` is empty."); + + //Gather event data + result = ScriptDev2DB.PQuery("SELECT `id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`" + "FROM `eventai_summons`"); + + //Drop Existing EventSummon Map + EventAI_Summon_Map.clear(); + + if (result) + { + outstring_log( "SD2: Loading EventAI_Summons..."); + barGoLink bar(result->GetRowCount()); + uint32 Count = 0; + + do + { + bar.step(); + Field *fields = result->Fetch(); + + EventAI_Summon temp; + + uint32 i = fields[0].GetUInt32(); + temp.position_x = fields[1].GetFloat(); + temp.position_y = fields[2].GetFloat(); + temp.position_z = fields[3].GetFloat(); + temp.orientation = fields[4].GetFloat(); + temp.SpawnTimeSecs = fields[5].GetUInt32(); + + //Add to map + EventAI_Summon_Map[i] = temp; + ++Count; + + }while (result->NextRow()); + + delete result; + outstring_log(""); + outstring_log("SD2: >> Loaded %u EventAI_Summons", Count); + + }else outstring_log("SD2: WARNING >> Loaded 0 EventAI_Summons. DB table `EventAI_Summons` is empty."); + + //Gather event data + result = ScriptDev2DB.PQuery("SELECT `id`,`creature_id`,`event_type`,`event_inverse_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action1_type`,`action1_param1`,`action1_param2`,`action1_param3`,`action2_type`,`action2_param1`,`action2_param2`,`action2_param3`,`action3_type`,`action3_param1`,`action3_param2`,`action3_param3`" + "FROM `eventai_scripts`"); + + //Drop Existing EventAI List + EventAI_Event_List.clear(); + + if (result) + { + outstring_log( "SD2: Loading EventAI_Scripts..."); + barGoLink bar(result->GetRowCount()); + uint32 Count = 0; + + do + { + bar.step(); + Field *fields = result->Fetch(); + + EventAI_Event temp; + + temp.event_id = fields[0].GetUInt32(); + uint32 i = temp.event_id; + temp.creature_id = fields[1].GetUInt32(); + temp.event_type = fields[2].GetUInt16(); + temp.event_inverse_phase_mask = fields[3].GetUInt32(); + temp.event_chance = fields[4].GetUInt8(); + temp.event_flags = fields[5].GetUInt8(); + temp.event_param1 = fields[6].GetUInt32(); + temp.event_param2 = fields[7].GetUInt32(); + temp.event_param3 = fields[8].GetUInt32(); + temp.event_param4 = fields[9].GetUInt32(); + + //Report any errors in event + if (temp.event_type >= EVENT_T_END) + error_db_log("SD2: Event %u has incorrect event type. Maybe DB requires updated version of SD2.", i); + + //No chance of this event occuring + if (temp.event_chance == 0) + error_db_log("SD2: Event %u has 0 percent chance. Event will never trigger!", i); + //Chance above 100, force it to be 100 + if (temp.event_chance > 100) + { + error_db_log("SD2: Creature %u are using event %u with more than 100 percent chance. Adjusting to 100 percent.", temp.creature_id, i); + temp.event_chance = 100; + } + + //Individual event checks + switch (temp.event_type) + { + case EVENT_T_HP: + case EVENT_T_MANA: + case EVENT_T_TARGET_HP: + { + if (temp.event_param2 > 100) + error_db_log("SD2: Creature %u are using percentage event(%u) with param2 (MinPercent) > 100. Event will never trigger! ", temp.creature_id, i); + + if (temp.event_param1 <= temp.event_param2) + error_db_log("SD2: Creature %u are using percentage event(%u) with param1 <= param2 (MaxPercent <= MinPercent). Event will never trigger! ", temp.creature_id, i); + + if (temp.event_flags & EFLAG_REPEATABLE && !temp.event_param3 && !temp.event_param4) + { + error_db_log("SD2: Creature %u has param3 and param4=0 (RepeatMin/RepeatMax) but cannot be repeatable without timers. Removing EFLAG_REPEATABLE for event %u.", temp.creature_id, i); + temp.event_flags &= ~EFLAG_REPEATABLE; + } + } + break; + + case EVENT_T_SPELLHIT: + { + if (temp.event_param1) + { + SpellEntry const* pSpell = GetSpellStore()->LookupEntry(temp.event_param1); + if (!pSpell) + { + error_db_log("SD2: Creature %u has non-existant SpellID(%u) defined in event %u.", temp.creature_id, temp.event_param1, i); + continue; + } + + if (temp.event_param2_s != -1 && temp.event_param2 != pSpell->SchoolMask) + error_db_log("SD2: Creature %u has param1(spellId %u) but param2 is not -1 and not equal to spell's school mask. Event %u can never trigger.", temp.creature_id, temp.event_param1, i); + } + + //TODO: fix this system with SPELL_SCHOOL_MASK. Current complicate things, using int32(-1) instead of just 0 + //SPELL_SCHOOL_MASK_NONE = 0 and does not exist, thus it can not ever trigger or be used in SpellHit() + if (temp.event_param2_s != -1 && temp.event_param2_s > SPELL_SCHOOL_MASK_ALL) + error_db_log("SD2: Creature %u is using invalid SpellSchoolMask(%u) defined in event %u.", temp.creature_id, temp.event_param2, i); + + if (temp.event_param4 < temp.event_param3) + error_db_log("SD2: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); + } + break; + + case EVENT_T_RANGE: + case EVENT_T_OOC_LOS: + case EVENT_T_FRIENDLY_HP: + case EVENT_T_FRIENDLY_IS_CC: + case EVENT_T_FRIENDLY_MISSING_BUFF: + { + if (temp.event_param4 < temp.event_param3) + error_db_log("SD2: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); + } + break; + + case EVENT_T_TIMER: + case EVENT_T_TIMER_OOC: + { + if (temp.event_param2 < temp.event_param1) + error_db_log("SD2: Creature %u are using timed event(%u) with param2 < param1 (InitialMax < InitialMin). Event will never repeat.", temp.creature_id, i); + + if (temp.event_param4 < temp.event_param3) + error_db_log("SD2: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); + } + break; + + case EVENT_T_KILL: + case EVENT_T_TARGET_CASTING: + { + if (temp.event_param2 < temp.event_param1) + error_db_log("SD2: Creature %u are using event(%u) with param2 < param1 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); + } + break; + + case EVENT_T_AGGRO: + case EVENT_T_DEATH: + case EVENT_T_EVADE: + case EVENT_T_SPAWNED: + { + if (temp.event_flags & EFLAG_REPEATABLE) + { + error_db_log("SD2: Creature %u has EFLAG_REPEATABLE set. Event can never be repeatable. Removing flag for event %u.", temp.creature_id, i); + temp.event_flags &= ~EFLAG_REPEATABLE; + } + } + break; + }; + + for (uint32 j = 0; j < MAX_ACTIONS; j++) + { + temp.action[j].type = fields[10+(j*4)].GetUInt16(); + temp.action[j].param1 = fields[11+(j*4)].GetUInt32(); + temp.action[j].param2 = fields[12+(j*4)].GetUInt32(); + temp.action[j].param3 = fields[13+(j*4)].GetUInt32(); + + //Report any errors in actions + switch (temp.action[j].type) + { + case ACTION_T_SAY: + case ACTION_T_YELL: + case ACTION_T_TEXTEMOTE: + if (GetEventAIText(temp.action[j].param1) == DEFAULT_TEXT) + error_db_log("SD2: Event %u Action %u refrences missing Localized_Text entry", i, j+1); + break; + + case ACTION_T_SOUND: + if (!GetSoundEntriesStore()->LookupEntry(temp.action[j].param1)) + error_db_log("SD2: Event %u Action %u uses non-existant SoundID %u.", i, j+1, temp.action[j].param1); + break; + + case ACTION_T_RANDOM_SAY: + case ACTION_T_RANDOM_YELL: + case ACTION_T_RANDOM_TEXTEMOTE: + if ((temp.action[j].param1 != 0xffffffff && GetEventAIText(temp.action[j].param1) == DEFAULT_TEXT) || + (temp.action[j].param2 != 0xffffffff && GetEventAIText(temp.action[j].param2) == DEFAULT_TEXT) || + (temp.action[j].param3 != 0xffffffff && GetEventAIText(temp.action[j].param3) == DEFAULT_TEXT)) + error_db_log("SD2: Event %u Action %u refrences missing Localized_Text entry", i, j+1); + break; + + case ACTION_T_CAST: + { + if (!GetSpellStore()->LookupEntry(temp.action[j].param1)) + error_db_log("SD2: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param1); + + if (temp.action[j].param2 >= TARGET_T_END) + error_db_log("SD2: Event %u Action %u uses incorrect Target type", i, j+1); + } + break; + + case ACTION_T_REMOVEAURASFROMSPELL: + { + if (!GetSpellStore()->LookupEntry(temp.action[j].param2)) + error_db_log("SD2: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param2); + + if (temp.action[j].param1 >= TARGET_T_END) + error_db_log("SD2: Event %u Action %u uses incorrect Target type", i, j+1); + } + break; + + case ACTION_T_CASTCREATUREGO: + { + if (!GetSpellStore()->LookupEntry(temp.action[j].param2)) + error_db_log("SD2: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param2); + + if (temp.action[j].param3 >= TARGET_T_END) + error_db_log("SD2: Event %u Action %u uses incorrect Target type", i, j+1); + } + break; + + //2nd param target + case ACTION_T_SUMMON_ID: + { + if (EventAI_Summon_Map.find(temp.action[j].param3) == EventAI_Summon_Map.end()) + error_db_log("SD2: Event %u Action %u summons missing EventAI_Summon %u", i, j+1, temp.action[j].param3); + + if (temp.action[j].param2 >= TARGET_T_END) + error_db_log("SD2: Event %u Action %u uses incorrect Target type", i, j+1); + } + break; + + case ACTION_T_SUMMON: + case ACTION_T_THREAT_SINGLE_PCT: + case ACTION_T_QUEST_EVENT: + case ACTION_T_SET_UNIT_FLAG: + case ACTION_T_REMOVE_UNIT_FLAG: + case ACTION_T_SET_INST_DATA64: + if (temp.action[j].param2 >= TARGET_T_END) + error_db_log("SD2: Event %u Action %u uses incorrect Target type", i, j+1); + break; + + //3rd param target + case ACTION_T_SET_UNIT_FIELD: + if (temp.action[j].param3 >= TARGET_T_END) + error_db_log("SD2: Event %u Action %u uses incorrect Target type", i, j+1); + break; + + case ACTION_T_SET_PHASE: + if (temp.action[j].param1 > 31) + error_db_log("SD2: Event %u Action %u attempts to set phase > 31. Phase mask cannot be used past phase 31.", i, j+1); + break; + + case ACTION_T_INC_PHASE: + if (!temp.action[j].param1) + error_db_log("SD2: Event %u Action %u is incrementing phase by 0. Was this intended?", i, j+1); + break; + + case ACTION_T_KILLED_MONSTER: + if (temp.event_type != EVENT_T_DEATH) + outstring_log("SD2 WARNING: Event %u Action %u calling ACTION_T_KILLED_MONSTER outside of EVENT_T_DEATH", i, j+1); + break; + + case ACTION_T_SET_INST_DATA: + if (temp.action[j].param2 > 3) + error_db_log("SD2: Event %u Action %u attempts to set instance data above encounter state 3. Custom case?", i, j+1); + break; + + default: + break; + } + + if (temp.action[j].type >= ACTION_T_END) + error_db_log("SD2: Event %u Action %u has incorrect action type. Maybe DB requires updated version of SD2.", i, j+1); + } + + //Add to list + EventAI_Event_List.push_back(temp); + ++Count; + + }while (result->NextRow()); + + delete result; + outstring_log(""); + outstring_log("SD2: >> Loaded %u EventAI_Events", Count); + + }else outstring_log("SD2: WARNING >> Loaded 0 EventAI_Scripts. DB table `EventAI_Scripts` is empty."); + + // Gather Script Text + result = ScriptDev2DB.PQuery("SELECT `id`, `sound`, `type`, `language`, `text`" + "FROM `script_texts`;"); + + // Drop Existing Script Text Map + Script_TextMap.clear(); + + if(result) + { + outstring_log("SD2: Loading Script Text..."); + barGoLink bar(result->GetRowCount()); + uint32 count = 0; + + do + { + bar.step(); + Field* fields = result->Fetch(); + ScriptText temp; + + uint32 i = fields[0].GetInt32(); + temp.SoundId = fields[1].GetInt32(); + temp.Type = fields[2].GetInt32(); + temp.Language = fields[3].GetInt32(); + temp.Text = fields[4].GetString(); + + if (temp.SoundId) + { + if (!GetSoundEntriesStore()->LookupEntry(temp.SoundId)) + error_db_log("SD2: Id %u in table script_texts has soundid %u but sound does not exist.",i,temp.SoundId); + } + + if(!strlen(temp.Text.c_str())) + error_db_log("SD2: Id %u in table script_texts has no text.", i); + + Script_TextMap[i] = temp; + ++count; + + }while(result->NextRow()); + + delete result; + + outstring_log(""); + outstring_log("SD2: Loaded %u Script Texts", count); + + }else outstring_log("SD2 WARNING >> Loaded 0 Script Texts. Database table `script_texts` is empty."); + + //Free database thread and resources + ScriptDev2DB.HaltDelayThread(); + + //***End DB queries*** + } +} + +struct TSpellSummary { + uint8 Targets; // set of enum SelectTarget + uint8 Effects; // set of enum SelectEffect +}extern *SpellSummary; + +MANGOS_DLL_EXPORT +void ScriptsFree() +{ + // Free Spell Summary + delete []SpellSummary; + + // Free resources before library unload + for(int i=0;i 8) + { + Locale = 0; + error_log("SD2: Locale set to invalid language id. Defaulting to 0."); + } + + outstring_log("SD2: Using locale %u", Locale); + outstring_log(""); + + EAI_ErrorLevel = SD2Config.GetIntDefault("EAIErrorLevel", 1); + + switch (EAI_ErrorLevel) + { + case 0: + outstring_log("SD2: EventAI Error Reporting level set to 0 (Startup Errors only)"); + break; + + case 1: + outstring_log("SD2: EventAI Error Reporting level set to 1 (Startup errors and Runtime event errors)"); + break; + + case 2: + outstring_log("SD2: EventAI Error Reporting level set to 2 (Startup errors, Runtime event errors, and Creation errors)"); + break; + + default: + outstring_log("SD2: Unknown EventAI Error Reporting level. Defaulting to 1 (Startup errors and Runtime event errors)"); + EAI_ErrorLevel = 1; + break; + } + outstring_log(""); + + //Load database (must be called after SD2Config.SetSource) + LoadDatabase(); + + nrscripts = 0; + for(int i=0;i::iterator i = EventAI_LocalizedTextMap.find(entry); + + if (i == EventAI_LocalizedTextMap.end()) + { + error_log("SD2: EventAI Localized Text %u not found", entry); + return DEFAULT_TEXT; + } + + switch (Locale) + { + case 1: + temp = (*i).second.locale_1.c_str(); + break; + + case 2: + temp = (*i).second.locale_2.c_str(); + break; + + case 3: + temp = (*i).second.locale_3.c_str(); + break; + + case 4: + temp = (*i).second.locale_4.c_str(); + break; + + case 5: + temp = (*i).second.locale_5.c_str(); + break; + + case 6: + temp = (*i).second.locale_6.c_str(); + break; + + case 7: + temp = (*i).second.locale_7.c_str(); + break; + + case 8: + temp = (*i).second.locale_8.c_str(); + break; + }; + + if (strlen(temp)) + return temp; + + return DEFAULT_TEXT; +} + +const char* GetScriptLocalizedText(uint32 entry) +{ + const char* temp = NULL; + + HM_NAMESPACE::hash_map::iterator i = Script_LocalizedTextMap.find(entry); + + if (i == Script_LocalizedTextMap.end()) + { + error_log("SD2: Script Localized Text %u not found", entry); + return DEFAULT_TEXT; + } + + switch (Locale) + { + case 1: + temp = (*i).second.locale_1.c_str(); + break; + + case 2: + temp = (*i).second.locale_2.c_str(); + break; + + case 3: + temp = (*i).second.locale_3.c_str(); + break; + + case 4: + temp = (*i).second.locale_4.c_str(); + break; + + case 5: + temp = (*i).second.locale_5.c_str(); + break; + + case 6: + temp = (*i).second.locale_6.c_str(); + break; + + case 7: + temp = (*i).second.locale_7.c_str(); + break; + + case 8: + temp = (*i).second.locale_8.c_str(); + break; + }; + + if (strlen(temp)) + return temp; + + return DEFAULT_TEXT; +} + +const char* GetEventAIText(uint32 entry) +{ + if(entry == 0xffffffff) + error_log("SD2: Entry = -1, GetEventAIText should not be called in this case."); + + const char* str = NULL; + + HM_NAMESPACE::hash_map::iterator itr = EventAI_Text_Map.find(entry); + if(itr == EventAI_Text_Map.end()) + { + error_log("SD2 ERROR: Unable to find EventAI Text %u", entry); + return DEFAULT_TEXT; + } + + str = (*itr).second.c_str(); + + if(strlen(str)) + return str; + + if(strlen((*itr).second.c_str())) + return (*itr).second.c_str(); + + return DEFAULT_TEXT; +} + +void ProcessScriptText(uint32 id, WorldObject* pSource, Unit* target) +{ + if (!pSource) + { + error_log("SD2: ProcessScriptText invalid Source pointer."); + return; + } + + HM_NAMESPACE::hash_map::iterator i = Script_TextMap.find(id); + + if (i == Script_TextMap.end()) + { + error_log("SD2: ProcessScriptText could not find id %u.",id); + return; + } + + if((*i).second.SoundId) + { + if(GetSoundEntriesStore()->LookupEntry((*i).second.SoundId)) + { + WorldPacket data(4); + data.SetOpcode(SMSG_PLAY_SOUND); + data << uint32((*i).second.SoundId); + pSource->SendMessageToSet(&data,false); + } + else + error_log("SD2: ProcessScriptText id %u tried to process invalid soundid %u.",id,(*i).second.SoundId); + } + + switch((*i).second.Type) + { + case CHAT_TYPE_SAY: + pSource->MonsterSay((*i).second.Text.c_str(), (*i).second.Language, target ? target->GetGUID() : 0); + break; + + case CHAT_TYPE_YELL: + pSource->MonsterYell((*i).second.Text.c_str(), (*i).second.Language, target ? target->GetGUID() : 0); + break; + + case CHAT_TYPE_TEXT_EMOTE: + pSource->MonsterTextEmote((*i).second.Text.c_str(), target ? target->GetGUID() : 0); + break; + + case CHAT_TYPE_BOSS_EMOTE: + pSource->MonsterTextEmote((*i).second.Text.c_str(), target ? target->GetGUID() : 0, true); + break; + + case CHAT_TYPE_WHISPER: + { + if (target && target->GetTypeId() == TYPEID_PLAYER) + pSource->MonsterWhisper((*i).second.Text.c_str(), target->GetGUID()); + else error_log("SD2: ProcessScriptText id %u cannot whisper without target unit (TYPEID_PLAYER).", id); + }break; + + case CHAT_TYPE_BOSS_WHISPER: + { + if (target && target->GetTypeId() == TYPEID_PLAYER) + pSource->MonsterWhisper((*i).second.Text.c_str(), target->GetGUID(), true); + else error_log("SD2: ProcessScriptText id %u cannot whisper without target unit (TYPEID_PLAYER).", id); + }break; + } +} + +Script* GetScriptByName(std::string Name) +{ + if(Name.empty()) + return NULL; + + for(int i=0;iName == Name ) + return m_scripts[i]; + } + return NULL; +} + +//******************************** +//*** Functions to be Exported *** + +MANGOS_DLL_EXPORT +bool GossipHello ( Player * player, Creature *_Creature ) +{ + Script *tmpscript = GetScriptByName(_Creature->GetScriptName()); + if(!tmpscript || !tmpscript->pGossipHello) return false; + + player->PlayerTalkClass->ClearMenus(); + return tmpscript->pGossipHello(player,_Creature); +} + +MANGOS_DLL_EXPORT +bool GossipSelect( Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + debug_log("SD2: Gossip selection, sender: %d, action: %d",sender, action); + + Script *tmpscript = GetScriptByName(_Creature->GetScriptName()); + if(!tmpscript || !tmpscript->pGossipSelect) return false; + + player->PlayerTalkClass->ClearMenus(); + return tmpscript->pGossipSelect(player,_Creature,sender,action); +} + +MANGOS_DLL_EXPORT +bool GossipSelectWithCode( Player *player, Creature *_Creature, uint32 sender, uint32 action, const char* sCode ) +{ + debug_log("SD2: Gossip selection with code, sender: %d, action: %d",sender, action); + + Script *tmpscript = GetScriptByName(_Creature->GetScriptName()); + if(!tmpscript || !tmpscript->pGossipSelectWithCode) return false; + + player->PlayerTalkClass->ClearMenus(); + return tmpscript->pGossipSelectWithCode(player,_Creature,sender,action,sCode); +} + +MANGOS_DLL_EXPORT +bool QuestAccept( Player *player, Creature *_Creature, Quest const *_Quest ) +{ + Script *tmpscript = GetScriptByName(_Creature->GetScriptName()); + if(!tmpscript || !tmpscript->pQuestAccept) return false; + + player->PlayerTalkClass->ClearMenus(); + return tmpscript->pQuestAccept(player,_Creature,_Quest); +} + +MANGOS_DLL_EXPORT +bool QuestSelect( Player *player, Creature *_Creature, Quest const *_Quest ) +{ + Script *tmpscript = GetScriptByName(_Creature->GetScriptName()); + if(!tmpscript || !tmpscript->pQuestSelect) return false; + + player->PlayerTalkClass->ClearMenus(); + return tmpscript->pQuestSelect(player,_Creature,_Quest); +} + +MANGOS_DLL_EXPORT +bool QuestComplete( Player *player, Creature *_Creature, Quest const *_Quest ) +{ + Script *tmpscript = GetScriptByName(_Creature->GetScriptName()); + if(!tmpscript || !tmpscript->pQuestComplete) return false; + + player->PlayerTalkClass->ClearMenus(); + return tmpscript->pQuestComplete(player,_Creature,_Quest); +} + +MANGOS_DLL_EXPORT +bool ChooseReward( Player *player, Creature *_Creature, Quest const *_Quest, uint32 opt ) +{ + Script *tmpscript = GetScriptByName(_Creature->GetScriptName()); + if(!tmpscript || !tmpscript->pChooseReward) return false; + + player->PlayerTalkClass->ClearMenus(); + return tmpscript->pChooseReward(player,_Creature,_Quest,opt); +} + +MANGOS_DLL_EXPORT +uint32 NPCDialogStatus( Player *player, Creature *_Creature ) +{ + Script *tmpscript = GetScriptByName(_Creature->GetScriptName()); + if(!tmpscript || !tmpscript->pNPCDialogStatus) return 100; + + player->PlayerTalkClass->ClearMenus(); + return tmpscript->pNPCDialogStatus(player,_Creature); +} + +MANGOS_DLL_EXPORT +uint32 GODialogStatus( Player *player, GameObject *_GO ) +{ + Script *tmpscript = GetScriptByName(_GO->GetGOInfo()->ScriptName); + if(!tmpscript || !tmpscript->pGODialogStatus) return 100; + + player->PlayerTalkClass->ClearMenus(); + return tmpscript->pGODialogStatus(player,_GO); +} + +MANGOS_DLL_EXPORT +bool ItemHello( Player *player, Item *_Item, Quest const *_Quest ) +{ + Script *tmpscript = GetScriptByName(_Item->GetProto()->ScriptName); + if(!tmpscript || !tmpscript->pItemHello) return false; + + player->PlayerTalkClass->ClearMenus(); + return tmpscript->pItemHello(player,_Item,_Quest); +} + +MANGOS_DLL_EXPORT +bool ItemQuestAccept( Player *player, Item *_Item, Quest const *_Quest ) +{ + Script *tmpscript = GetScriptByName(_Item->GetProto()->ScriptName); + if(!tmpscript || !tmpscript->pItemQuestAccept) return false; + + player->PlayerTalkClass->ClearMenus(); + return tmpscript->pItemQuestAccept(player,_Item,_Quest); +} + +MANGOS_DLL_EXPORT +bool GOHello( Player *player, GameObject *_GO ) +{ + Script *tmpscript = GetScriptByName(_GO->GetGOInfo()->ScriptName); + if(!tmpscript || !tmpscript->pGOHello) return false; + + player->PlayerTalkClass->ClearMenus(); + return tmpscript->pGOHello(player,_GO); +} + +MANGOS_DLL_EXPORT +bool GOQuestAccept( Player *player, GameObject *_GO, Quest const *_Quest ) +{ + Script *tmpscript = GetScriptByName(_GO->GetGOInfo()->ScriptName); + if(!tmpscript || !tmpscript->pGOQuestAccept) return false; + + player->PlayerTalkClass->ClearMenus(); + return tmpscript->pGOQuestAccept(player,_GO,_Quest); +} + +MANGOS_DLL_EXPORT +bool GOChooseReward( Player *player, GameObject *_GO, Quest const *_Quest, uint32 opt ) +{ + Script *tmpscript = GetScriptByName(_GO->GetGOInfo()->ScriptName); + if(!tmpscript || !tmpscript->pGOChooseReward) return false; + + player->PlayerTalkClass->ClearMenus(); + return tmpscript->pGOChooseReward(player,_GO,_Quest,opt); +} + +MANGOS_DLL_EXPORT +bool AreaTrigger( Player *player, AreaTriggerEntry * atEntry) +{ + Script *tmpscript = NULL; + + tmpscript = GetScriptByName(GetAreaTriggerScriptNameById(atEntry->id)); + if(!tmpscript || !tmpscript->pAreaTrigger) return false; + + return tmpscript->pAreaTrigger(player, atEntry); +} + +MANGOS_DLL_EXPORT +CreatureAI* GetAI(Creature *_Creature) +{ + Script *tmpscript = GetScriptByName(_Creature->GetScriptName()); + + if(!tmpscript || !tmpscript->GetAI) return NULL; + return tmpscript->GetAI(_Creature); +} + +MANGOS_DLL_EXPORT +bool ItemUse( Player *player, Item* _Item, SpellCastTargets const& targets) +{ + Script *tmpscript = GetScriptByName(_Item->GetProto()->ScriptName); + if(!tmpscript || !tmpscript->pItemUse) return false; + + return tmpscript->pItemUse(player,_Item,targets); +} + +MANGOS_DLL_EXPORT +bool ReceiveEmote( Player *player, Creature *_Creature, uint32 emote ) +{ + Script *tmpscript = GetScriptByName(_Creature->GetScriptName()); + if(!tmpscript || !tmpscript->pReceiveEmote) return false; + + return tmpscript->pReceiveEmote(player, _Creature, emote); +} + +MANGOS_DLL_EXPORT +InstanceData* CreateInstanceData(Map *map) +{ + Script *tmpscript = NULL; + + if(!map->IsDungeon()) return false; + + tmpscript = GetScriptByName(((InstanceMap*)map)->GetScript()); + if(!tmpscript || !tmpscript->GetInstanceData) return false; + + return tmpscript->GetInstanceData(map); +} diff --git a/src/bindings/scripts/ScriptMgr.h b/src/bindings/scripts/ScriptMgr.h new file mode 100644 index 00000000000..8f0f05afe3d --- /dev/null +++ b/src/bindings/scripts/ScriptMgr.h @@ -0,0 +1,94 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 +* This program is free software licensed under GPL version 2 +* Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef SCRIPTMGR_H +#define SCRIPTMGR_H + +#include "Common.h" +#include "Platform/CompilerDefs.h" +#include "Database/DBCStructure.h" + +class Player; +class Creature; +class CreatureAI; +class InstanceData; +class Quest; +class Item; +class GameObject; +class SpellCastTargets; +class Map; +class Unit; +class WorldObject; + +#define MAX_SCRIPTS 1000 //72 bytes each (approx 71kb) + +//MAX visible range (size of grid) +#define VISIBLE_RANGE (166.0f) + +#define DEFAULT_TEXT "" + +// +struct Script +{ + Script() : +pGossipHello(NULL), pQuestAccept(NULL), pGossipSelect(NULL), pGossipSelectWithCode(NULL), +pQuestSelect(NULL), pQuestComplete(NULL), pNPCDialogStatus(NULL), pGODialogStatus(NULL), pChooseReward(NULL), +pItemHello(NULL), pGOHello(NULL), pAreaTrigger(NULL), pItemQuestAccept(NULL), pGOQuestAccept(NULL), +pGOChooseReward(NULL),pReceiveEmote(NULL),pItemUse(NULL), GetAI(NULL), GetInstanceData(NULL) +{} + +std::string Name; + +// -- Quest/gossip Methods to be scripted -- +bool (*pGossipHello )(Player*, Creature*); +bool (*pQuestAccept )(Player*, Creature*, Quest const* ); +bool (*pGossipSelect )(Player*, Creature*, uint32 , uint32 ); +bool (*pGossipSelectWithCode)(Player*, Creature*, uint32 , uint32 , const char* ); +bool (*pQuestSelect )(Player*, Creature*, Quest const* ); +bool (*pQuestComplete )(Player*, Creature*, Quest const* ); +uint32 (*pNPCDialogStatus )(Player*, Creature* ); +uint32 (*pGODialogStatus )(Player *player, GameObject * _GO ); +bool (*pChooseReward )(Player*, Creature*, Quest const*, uint32 ); +bool (*pItemHello )(Player*, Item*, Quest const* ); +bool (*pGOHello )(Player*, GameObject* ); +bool (*pAreaTrigger )(Player*, AreaTriggerEntry* ); +bool (*pItemQuestAccept )(Player*, Item *, Quest const* ); +bool (*pGOQuestAccept )(Player*, GameObject*, Quest const* ); +bool (*pGOChooseReward )(Player*, GameObject*_GO, Quest const*, uint32 ); +bool (*pReceiveEmote )(Player*, Creature*, uint32 ); +bool (*pItemUse )(Player*, Item*, SpellCastTargets const& ); + +CreatureAI* (*GetAI)(Creature*); +InstanceData* (*GetInstanceData)(Map*); +// ----------------------------------------- +}; + +extern int nrscripts; +extern Script *m_scripts[MAX_SCRIPTS]; + +// Localized Text function +const char* GetEventAILocalizedText(uint32 entry); +const char* GetScriptLocalizedText(uint32 entry); + +//EventAI text function +const char* GetEventAIText(uint32 entry); // TODO: Locales + +// Script Text function +void ProcessScriptText(uint32 id, WorldObject* pSource, Unit* target = NULL); // TODO: Locales + +#if COMPILER == COMPILER_GNU +#define FUNC_PTR(name,callconvention,returntype,parameters) typedef returntype(*name)parameters __attribute__ ((callconvention)); +#else +#define FUNC_PTR(name, callconvention, returntype, parameters) typedef returntype(callconvention *name)parameters; +#endif + +#ifdef WIN32 + #define MANGOS_DLL_EXPORT extern "C" __declspec(dllexport) +#elif defined( __GNUC__ ) + #define MANGOS_DLL_EXPORT extern "C" +#else + #define MANGOS_DLL_EXPORT extern "C" export +#endif + +#endif diff --git a/src/bindings/scripts/VC71/71ScriptDev2.vcproj b/src/bindings/scripts/VC71/71ScriptDev2.vcproj new file mode 100644 index 00000000000..4b015248add --- /dev/null +++ b/src/bindings/scripts/VC71/71ScriptDev2.vcproj @@ -0,0 +1,1598 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/bindings/scripts/VC80/80ScriptDev2.vcproj b/src/bindings/scripts/VC80/80ScriptDev2.vcproj new file mode 100644 index 00000000000..c546b189e28 --- /dev/null +++ b/src/bindings/scripts/VC80/80ScriptDev2.vcproj @@ -0,0 +1,2347 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/bindings/scripts/VC90/90ScriptDev2.vcproj b/src/bindings/scripts/VC90/90ScriptDev2.vcproj new file mode 100644 index 00000000000..6a08eee143b --- /dev/null +++ b/src/bindings/scripts/VC90/90ScriptDev2.vcproj @@ -0,0 +1,2345 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/bindings/scripts/VCProjToLinuxMake.exe b/src/bindings/scripts/VCProjToLinuxMake.exe new file mode 100644 index 00000000000..1862fe32e3e Binary files /dev/null and b/src/bindings/scripts/VCProjToLinuxMake.exe differ diff --git a/src/bindings/scripts/docs/EventAI.txt b/src/bindings/scripts/docs/EventAI.txt new file mode 100644 index 00000000000..af4335655b8 --- /dev/null +++ b/src/bindings/scripts/docs/EventAI.txt @@ -0,0 +1,701 @@ +========================================= +Event AI documentation +========================================= + +Scriptdev2 Revision 220 introduces a new database defined AI named EventAI. +This system allows users to create new creature scripts entierly within the Database. +ScriptName must still be set to "mob_eventai" within the MaNGOS database creature_template.scriptname field. + +========================================= +Basic Structure of EventAI +========================================= +Event AI follows a basic if (Event) then do {Action} format. +Below is a the list of current fields within the Eventai_scripts table. + +(Field_Name Discription) +id This value is mearly an incrementing counter of the current Event number. Required for sql queries. +creature_id Creature id which this event should occur on. + +event_type Type of event (See Event Types below) +event_inverse_phase_mask Mask which phases this event should NOT trigger in* +event_chance Percent chance of this event occuring (1 - 100) +event_flags Event flags such as if the event is repeatable (see below) +event_param1 Variable for event (dependant on Event type) +event_param2 +event_param3 +event_param4 + +action1_type First Type of Action to take when event occurs (See Action Types below) +action1_param1 Variables used for Action1 (dependant on Action type) +action1_param2 +action1_param3 + +action2_type Second Type of Action to take when event occurs (See Action Types below) +action2_param1 Variables used for Action2 (dependant on Action type) +action2_param2 +action2_param3 + +action3_type Third Type of Action to take when event occurs (See Action Types below) +action3_param1 Variables used for Action3 (dependant on Action type) +action3_param2 +action3_param3 + +All params are signed 32 bit values (+/- 2147483647). If param specifies time then time is in milliseconds. If param specifies percentage then percentages are value/100 (ex: if param = 500 then that means 500%, -50 = -50%) + +*Phase mask is a bit mask of which phases this event should not trigger in. Example: Phase mask value of 12 (1100) would mean that this event would trigger 0, 1 and all other phases except for 2 and 3 (0 counts as the first phase). + +========================================= +Event Types +========================================= +Below is the list of current Event types that EventAI can handle. +Each event type has its own specific interpretation of the params that accompany it. +Params are always read from Param1, then Param2, then Param3. +Events will not repeat until the creature exits combat unless EFLAG_REPEATABLE is set. Some events such as EVENT_T_AGGRO, EVENT_T_DEATH, EVENT_T_SPAWNED, and EVENT_T_EVADE cannot repeat. + +# Internal Name Pamarm usage Description +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +0 EVENT_T_TIMER InitialMin, InitialMax, RepeatMin, RepeatMax Expires first between (Param1) and (Param2) and then between every (Param3) and (Param4). but only in combat. +1 EVENT_T_TIMER_OOC InitialMin, InitialMax, RepeatMin, RepeatMax Expires first between (Param1) and (Param2) and then between every (Param3) and (Param4). but only out of combat. +2 EVENT_T_HP HPMax%, HPMin%, RepeatMin, RepeatMax Expires when HP is between (Param1) and (Param2). Will repeat every (Param3) and (Param4). +3 EVENT_T_MANA ManaMax%,ManaMin% RepeatMin, RepeatMax Expires once Mana% is between (Param1) and (Param2). Will repeat every (Param3) and (Param4). +4 EVENT_T_AGGRO NONE Expires upon initial aggro (does not repeat). +5 EVENT_T_KILL RepeatMin, RepeatMax Expires upon killing a player. Will repeat between every (Param1) and (Param2). +6 EVENT_T_DEATH NONE Expires upon Death of the Creature. +7 EVENT_T_EVADE NONE Expires upon creature EnterEvadeMode(). +8 EVENT_T_SPELLHIT SpellID, School, RepeatMin, RepeatMax Expires upon Spell hit. If (param1) is set will only expire on that spell. If (param2) will only expire on spells of that school (-1 for all). Will repeat every (Param3) and (Param4) . +9 EVENT_T_RANGE MinDist, MaxDist, RepeatMin, RepeatMax Expires when the highest threat target distance is greater than (Param1) and less than (Param2). Will repeat every (Param3) and (Param4) . +10 EVENT_T_OOC_LOS NoHostile, NoFriendly, RepeatMin, RepeatMax Expires when a Player moves within visible distance to creature. Does not expire for Hostile Players if (Param1) is not 0. Does not expire for Friendly Players if (Param2) is not 0. Will repeat every (Param3) and (Param4) . Does not expire for creatures or pet or when the creature is in combat. +11 EVENT_T_SPAWNED NONE Expires at initial spawn and at creature respawn (useful for setting ranged movement type) +12 EVENT_T_TARGET_HP HPMax%, HPMin%, RepeatMin, RepeatMax Expires when Current Target's HP is between (Param1) and (Param2). Will repeat every (Param3) and (Param4) . +13 EVENT_T_TARGET_CASTING RepeatMin, RepeatatMax Expires when the current target is casting a spell. Will repeat every (Param1) and (Param2) . +14 EVENT_T_FRIENDLY_HP HPDeficit, Radius, RepeatMin, RepeatMax Expires when a friendly unit in radius has at least (param1) hp missing. Will repeat every (Param3) and (Param4) . +15 EVENT_T_FRIENDLY_IS_CC DispelType, Radius, RepeatMin, RepeatMax Expires when a friendly unit is Crowd controlled within the given radius (param2). Will repeat every (Param3) and (Param4) . +16 EVENT_T_MISSING_BUFF SpellId, Radius, RepeatMin, RepeatMax Expires when a friendly unit is missing aura's given by spell (param1) within radius (param2). Will repeat every (Param3) and (Param4) . +17 EVENT_T_SUMMONED_UNIT CreatureId, RepeatMin, RepeatMax Expires after creature with entry = (param1) is spawned or for all spawns if param1 = 0. Will repeat every (Param2) and (Param3) . + +========================================= +Action Types +========================================= +Below is the list of current Action types that EventAI can handle. +Each event type has its own specific interpretation of the params that accompany it. +Params are always read from Param1, then Param2, then Param3. + +(# Internal Name Param usage Discription) +0 ACTION_T_NONE No Action Does Nothing +1 ACTION_T_SAY TextId Says Text +2 ACTION_T_YELL TextId Yells Text +3 ACTION_T_TEXTEMOTE TextId Text Emotes Text +4 ACTION_T_SOUND SoundId Plays Sound +5 ACTION_T_EMOTE EmoteId Does emote +6 ACTION_T_RANDOM_SAY TextId1, TextId2, TextId3 Says random text between 3 params* +7 ACTION_T_RANDOM_YELL TextId1, TextId2, TextId3 Yells random text between 3 params* +8 ACTION_T_RANDOM_TEXTEMOTE TextId1, TextId2, TextId3 Text Emotes random text between 3 params* +9 ACTION_T_RANDOM_SOUND SoundId1, SoundId2, SoundId3 Plays random sound between 3 params* +10 ACTION_T_RANDOM_EMOTE EmoteId1, EmoteId2, EmoteId3 Emotes random emote between 3 params +11 ACTION_T_CAST SpellId, Target, CastFlags Casts spell (param1) on target type (param2). Uses Cast Flags (specified below target types) +12 ACTION_T_SUMMON CreatureID, Target, Duration Summons creature (param1) to attack target (param2) for (param3) duration. Spawns on top of current creature. +13 ACTION_T_THREAT_SINGLE_PCT Threat%, Target Modifies threat by (param1) on target type (param2) +14 ACTION_T_THREAT_ALL_PCT Threat% Modifies threat by (param1) on all targets (using -100% on all will result in full aggro dump) +15 ACTION_T_QUEST_EVENT QuestID, Target Calls AreaExploredOrEventHappens with (param1) for target type (Param2) +16 ACTION_T_QUEST_CASTCREATUREGO CreatureID, SpellId, Target Sends CastCreatureOrGo for CreatureId (param1) with SpellId (param2) for target (param3) +17 ACTION_T_SET_UNIT_FIELD Field_Number, Value, Target Sets Unit Field (param1) to Value (param2) on target type (param3) +18 ACTION_T_SET_UNIT_FLAG Flags, Target Sets flag (flags can be binary OR together to modify multiple flags at once) on for Target type (param2) +19 ACTION_T_REMOVE_UNIT_FLAG Flags, Target Removes flag (flags can be binary OR together to modify multiple flags at once) on for Target type (param2) +20 ACTION_T_AUTO_ATTACK AllowAutoAttack 0 = stop melee attack, anything else means continue attacking/allow melee attacking +21 ACTION_T_COMBAT_MOVEMENT AllowCombatMovement 0 = stop combat based movement, anything else continue/allow combat based movement (targeted movement generator) +22 ACTION_T_SET_PHASE Phase Sets the current phase to (param1) +23 ACTION_T_INC_PHASE Value Increments the phase by (param1). May be negative to decrement phase but should not be 0. +24 ACTION_T_EVADE No Params Forces the creature to evade. Wiping all threat and dropping combat. +25 ACTION_T_FLEE No Params Causes the .creature to flee. Please use this action instead of directly casting this spell so we may change this when a more correct approach is found. +26 ACTION_T_QUEST_EVENT_ALL QuestId Calls GroupEventHappens with (param1). Only used if it's _expected_ event should complete for all players in current party +27 ACTION_T_CASTCREATUREGO_ALL QuestId, SpellId Calls CastedCreatureOrGo for all players on the threat list with QuestID(Param1) and SpellId(Param2) +28 ACTION_T_REMOVEAURASFROMSPELL Target, Spellid Removes all auras on Target caused by Spellid +29 ACTION_T_RANGED_MOVEMENT Distance, Angle Changes the movement generator type to a ranged type. Note: Default melee type can still be done with this. Specify 0 angle and 0 distance. +30 ACTION_T_RANDOM_PHASE PhaseId1, PhaseId2, PhaseId3 Sets the phase to the id between 3 params* +31 ACTION_T_RANDOM_PHASE_RANGE PhaseMin, PhaseMax Sets the phase to a random id (Phase = PhaseMin + rnd % PhaseMin-PhaseMax). PhaseMax must be greater than PhaseMin. +32 ACTION_T_SUMMON CreatureID, Target, SummonID Summons creature (param1) to attack target (param2) at location specified by EventAI_Summons (param3). +33 ACTION_T_KILLED_MONSTER CreatureID, Target Calls KilledMonster (param1) for target of type (param2) +34 ACTION_T_SET_INST_DATA Field, Data Calls ScriptedInstance::SetData with field (param1) and data (param2) +35 ACTION_T_SET_INST_DATA64 Field, Target Calls ScriptedInstance::SetData64 with field (param1) and data (param2) target's GUID. +36 ACTION_T_UPDATE_TEMPLATE TemplateId, Team Changes the creature to a new creature template of (param1) with team = Alliance if (param2) = false or Horde if (param2) = true +37 ACTION_T_DIE No Params Kills the creature +38 ACTION_T_ZONE_COMBAT_PULSE No Params Places all players within the instance into combat with the creature. Only works in combat and only works inside of instances. + +* = Use -1 to specify that if this param is picked to do nothing. Random is constant between actions within an event. So if you have a random Yell and a random Sound they will match up (ex: param2 with param2) + +========================================= +Event Types +========================================= +Note: +COMBAT ONLY - Means that this event will only trigger durring combat. +OUT OF COMBAT ONLY - Means that this event will only trigger while out of combat. +BOTH - This event can trigger both in and out of combat. + +Events that do not have lables on them are events that are directly involved with the in and out of combat state. + +------------------ +0 = EVENT_T_TIMER: +------------------ +Parameter 1: InitialMin - Minumum Time used to calculate Random Initial Expire +Parameter 2: InitialMax - Maximum Time used to calculate Random Initial Expire +Parameter 3: RepeatMin - Minimum Time used to calculate Random Repeat Expire +Parameter 4: RepeatMax - Maximum Time used to calculate Random Repeat Expire + +COMBAT ONLY! - Expires first between (Param1) and (Param2) and then between every (Param3) and (Param4) from then on. +This is commonly used for spells that repeat cast during combat (Simulate Spell Cooldown). + +---------------------- +1 = EVENT_T_TIMER_OOC: +---------------------- +Parameter 1: InitialMin - Minumum Time used to calculate Random Initial Expire +Parameter 2: InitialMax - Maximum Time used to calculate Random Initial Expire +Parameter 3: RepeatMin - Minimum Time used to calculate Random Repeat Expire +Parameter 4: RepeatMax - Maximum Time used to calculate Random Repeat Expire + +OUT OF COMBAT ONLY! - Expires first between (Param1) and (Param2) and then between every (Param3) and (Param4) from then on. +This is commonly used for events that occur and repeat outside of combat. + +--------------- +2 = EVENT_T_HP: +--------------- +Parameter 1: HPMax% - Maximum HP% That this Event will Expire +Parameter 2: HPMin% - Minimum HP% That this Event will Expire +Parameter 3: RepeatMin - Minimum Time used to calculate Random Repeat Expire +Parameter 4: RepeatMax - Maximum Time used to calculate Random Repeat Expire + +BOTH - Expires when HP is between (Param1) and (Param2). Will repeat every (Param3) and (Param4). +This is commonly used for events that trigger at a specific HP% (Such as Heal/Enrage Spells or NPC's that Flee). + +----------------- +3 = EVENT_T_MANA: +----------------- +Parameter 1: ManaMax% - Maximum Mana% That this Event will Expire +Parameter 2: ManaMin% - Minimum Mana% That this Event will Expire +Parameter 3: RepeatMin - Minimum Time used to calculate Random Repeat Expire +Parameter 4: RepeatMax - Maximum Time used to calculate Random Repeat Expire + +BOTH - Expires once Mana% is between (Param1) and (Param2). Will repeat every (Param3) and (Param4). +This is commonly used for events where an NPC low on Mana will do something (Such as stop casting spells and switch to melee). + +------------------ +4 = EVENT_T_AGGRO: +------------------ +This Event Expires upon initial aggro (does not repeat). + +----------------- +5 = EVENT_T_KILL: +----------------- +Parameter 1: RepeatMin - Minimum Time used to calculate Random Repeat Expire +Parameter 2: RepeatMax - Maximum Time used to calculate Random Repeat Expire + +COMBAT ONLY! - Expires upon killing a player. Will repeat every (Param1) and (Param2). +This Event Expires upon killing a player. It is commonly used for NPC's who yell or do something after killing a player. + +------------------ +6 = EVENT_T_DEATH: +------------------ +This Event Expires upon Death of the Scripted NPC. +This is commonly used for NPC's who have a yell on death or cast some kind if summon spell when they die. + +------------------ +7 = EVENT_T_EVADE: +------------------ +This Event Expires upon the creature EnterEvadeMode(). +This is commonly used for NPC's who use phases, allows you to reset their phase to 0 upon evade to prevent possible strange behavior. + +--------------------- +8 = EVENT_T_SPELLHIT: +--------------------- +Parameter 1: SpellID - The Spell ID that will trigger the event to occur (NOTE: If you use Spell School as the trigger set this value to 0) +Parameter 2: School - Spell School to trigger the event (NOTE: If you use a SpellID then set this value to -1) - *See Below for Spell School Bitmask Values* +Parameter 3: RepeatMin - Minimum Time used to calculate Random Repeat Expire +Parameter 4: RepeatMax - Maximum Time used to calculate Random Repeat Expire + +BOTH - Expires upon Spell hit. If (param1) is set will only expire on that spell. If (param2) will only expire on spells of that school. Will repeat every (Param3) and (Param4). +This Event is commonly used for NPC's who can do special things when you cast a spell (Or specific spell) on them. + +------------------ +9 = EVENT_T_RANGE: +------------------ +Parameter 1: MinDist - This Distance is the Minimum Distance between the NPC and it's target to allow this Event to Expire +Parameter 2: MaxDist - This Distance is the Maximum Distance between the NPC and it's target to allow this Event to Expire +Parameter 3: RepeatMin - Minimum Time used to calculate Random Repeat Expire +Parameter 4: RepeatMax - Maximum Time used to calculate Random Repeat Expire + +COMBAT ONLY! - Expires when the highest threat target distance is greater than (Param1) and less than (Param2). Will repeat every (Param3) and (Param4). +This Event is commonly used for NPC's who have Ranged Combat and will Throw/Shoot between a certian distance. + +--------------------- +10 = EVENT_T_OOC_LOS: +--------------------- +Parameter 1: NoHostile - This Value is to Prevent this Action from Expiring When Caused by a Player/Creature Hostile to them (0 = Prevent Event from Expiring, 1 = Allow Event to Expire) +Parameter 2: NoFriendly - This Value is to Prevent this Action from Expiring When Caused by a Player/Creature Friendly to them (0 = Prevent Event from Expiring, 1 = Allow Event to Expire) +Parameter 3: RepeatMin - Minimum Time used to calculate Random Repeat Expire +Parameter 4: RepeatMax - Maximum Time used to calculate Random Repeat Expire + +OUT OF COMBAT ONLY! - Expires when a Player moves within visible distance to the NPC. Does not expire for Hostile Players if (Param1) is not 0. Does not expire for Friendly Players if (Param2) is not 0. Will repeat every (Param3) and (Param4). Does not expire for creatures or pets when they are in combat. +This Event is commonly used for NPC's who Do Something or Say Something when you walk past them Out of Combat. + +--------------------- +11 = EVENT_T_SPAWNED: +--------------------- +Expires at initial spawn and at creature respawn. +This Event is commonly used for setting ranged movement type or Summoning a Pet on Spawn + +----------------------- +12 = EVENT_T_TARGET_HP: +----------------------- +Parameter 1: HPMax% - Maximum HP% That this Event will Expire +Parameter 2: HPMin% - Minimum HP% That this Event will Expire +Parameter 3: RepeatMin - Minimum Time used to calculate Random Repeat Expire +Parameter 4: RepeatMax - Maximum Time used to calculate Random Repeat Expire + +COMBAT ONLY! - Expires when Current NPC's Target's HP is between (Param1) and (Param2). Will repeat every (Param3) and (Param4). +This Event is commonly used for NPC's who have a special ability (Like Execute) that only casts when a Player HP is low. + +---------------------------- +13 = EVENT_T_TARGET_CASTING: +---------------------------- +Parameter 1: RepeatMin - Minimum Time used to calculate Random Repeat Expire +Parameter 2: RepeatMax - Maximum Time used to calculate Random Repeat Expire + +COMBAT ONLY! - Expires when the current target is casting a spell. Will repeat every (Param1) and (Param2). +This event is commonly used for NPC's who will cast a counter spell when their target starts to cast a spell. + +------------------------- +14 = EVENT_T_FRIENDLY_HP: +------------------------- +Parameter 1: HPDeficit - This is the Amount of HP Missing from Full HP to trigger this event (You would need to calculate the amount of HP the event happens and subtract that from Full HP Value to get this number) +Parameter 2: Radius - This is the Range in Yards the NPC will scan for nearby Friendlies (Faction is Friendly To) for the missing amount of HP in Param1. +Parameter 3: RepeatMin - Minimum Time used to calculate Random Repeat Expire +Parameter 4: RepeatMax - Maximum Time used to calculate Random Repeat Expire + +COMBAT ONLY! - Expires when a friendly unit in radius(param2) has at least (param1) hp missing. Will repeat every (Param3) and (Param4). +This is commonly used when an NPC in Combat will heal a nearby Friendly NPC in Combat with a Heal/Renew Spell. + +---------------------------- +15 = EVENT_T_FRIENDLY_IS_CC: +---------------------------- +Parameter 1: DispelType - Dispel Type to trigger the event - *See Below for Dispel Bitmask Values* +Parameter 2: Radius - This is the Range in Yards the NPC will scan for nearby Friendlies being Crowd Controlled +Parameter 3: RepeatMin - Minimum Time used to calculate Random Repeat Expire +Parameter 4: RepeatMax - Maximum Time used to calculate Random Repeat Expire + +COMBAT ONLY! - Expires when a friendly unit is Crowd controlled within the given radius (param2). Will repeat every (Param3) and (Param4). +This is commonly used for NPC's who can come to the resule of other Friendly NPC's if being Crowd Controlled + +-------------------------- +16 = EVENT_T_MISSING_BUFF: +-------------------------- +Parameter 1: SpellId - This is the SpellID That the Aura Check will look for (If it is missing this Aura) +Parameter 2: Radius - This is the Range in Yards the NPC will scan for nearby Friendlies (Faction is Friendly To) for the missing Aura. +Parameter 3: RepeatMin - Minimum Time used to calculate Random Repeat Expire +Parameter 4: RepeatMax - Maximum Time used to calculate Random Repeat Expire + +BOTH - Expires when a friendly unit is missing aura's given by spell (param1) within radius (param2). Will repeat every (Param3) and (Param4). +This is commonly used for NPC's who watch friendly units for a debuff to end so they can recast it on them again. + +--------------------------- +17 = EVENT_T_SUMMONED_UNIT: +--------------------------- +Parameter 1: CreatureId - The CreatureID that the NPC is watching to spawn to trigger this event +Parameter 2: RepeatMin - Minimum Time used to calculate Random Repeat Expire +Parameter 3: RepeatMax - Maximum Time used to calculate Random Repeat Expire + +BOTH - Expires after creature with entry(Param1) is spawned or for all spawns if param1 = 0. Will repeat every (Param2) and (Param3) . +This is commonly used for NPC's who will do something special once another NPC is summoned. Usually used is Complex Scripts or Special Events. + + +========================================= +Action Types +========================================= + +----------------- +1 = ACTION_T_SAY: +----------------- +Parameter 1: The ID of the text that the NPC should SAY from the Localized_Texts Table. + +This action is pretty straightforward. When activated, the creature will SAY the specified text (Speech Bubble). + +------------------ +2 = ACTION_T_YELL: +------------------ +Parameter 1: The ID of the text that the NPC should YELL from the Localized_Texts Table. + +The creature will YELL the specified text (Red Speech Bubble). + +----------------------- +3 = ACTION_T_TEXTEMOTE: +----------------------- +Parameter 1: The ID of the text that the NPC should TEXTEMOTE from the Localized_Texts Table. + +When activated, the creature will do a text emote using the specified text. A text emote is what you would regularly see by using the /em slash command. +NOTE: The text should be written with the assumption that the creature's name is the first word or words in the sentence (for example, "is doing a text emote" would appear as "XYZ is doing a text emote" for a creature named XYZ). + +------------------- +4 = ACTION_T_SOUND: +------------------- +Parameter 1: The Sound ID to be played. (Sound IDs are contained in the DBC files.) + +The creature will play the specified sound. +This is commonly used for Bosses who Yell and then also have a Voice for the same thing. + +------------------- +5 = ACTION_T_EMOTE: +------------------- +Parameter 1: The Emote ID that the creature should perform. (Emote IDs are also contained in the DBC but they can be found in the mangos source as well). + +The creature will perform a visual emote. Unlike a text emote, a visual emote is one where the creature will actually move or perform a gesture. +This is commonly used for NPC's who may perform a special action (Salute, Roar, ect...). Not all player emotes work for creature models. + +------------------------ +6 = ACTION_T_RANDOM_SAY: +------------------------ +Parameter 1: The ID of the text that the NPC should SAY from the Localized_Texts Table (Random Choice #1). +Parameter 2: The ID of the text that the NPC should SAY from the Localized_Texts Table (Random Choice #2). +Parameter 3: The ID of the text that the NPC should SAY from the Localized_Texts Table (Random Choice #3). + +Similar to the ACTION_T_SAY action, it will choose at random a text entry to SAY. This action will pick a random entry from the three. +NOTE: If you want any of the options if selected to do nothing you set that Param to -1 value. Then if selected it will do nothing. +NOTE: When using Random Select Actions, ALL The Actions using Random in a Single Event (Action 1,2,3) will select the SAME Random Choice when it expires. This can come in handy if you are doing a ACTION_T_RANDOM_YELL for Action1 and then the corresponding sounds for ACTION_T_RANDOM_SOUND in Action2. If it selects Random Choice #2 for the Yell it will Select Random Choice #2 for the sound so you can match them up as required. +This is commonly used for NPC's who have several different Aggro Say's and you would like one of them selected at random. + +------------------------- +7 = ACTION_T_RANDOM_YELL: +------------------------- +Parameter 1: The ID of the text that the NPC should YELL from the Localized_Texts Table (Random Choice #1). +Parameter 2: The ID of the text that the NPC should YELL from the Localized_Texts Table (Random Choice #2). +Parameter 3: The ID of the text that the NPC should YELL from the Localized_Texts Table (Random Choice #3). + +Similar to the ACTION_T_YELL action, it will choose at random a text entry to YELL. + +------------------------------ +8 = ACTION_T_RANDOM_TEXTEMOTE: +------------------------------ +Parameter 1: The ID of the text that the NPC should TEXTEMOTE from the Localized_Texts Table (Random Choice #1). +Parameter 2: The ID of the text that the NPC should TEXTEMOTE from the Localized_Texts Table (Random Choice #2). +Parameter 3: The ID of the text that the NPC should TEXTEMOTE from the Localized_Texts Table (Random Choice #3). + +Similar to the ACTION_T_TEXTEMOTE action, it will choose at random a text entry to TEXTEMOTE. + +-------------------------- +9 = ACTION_T_RANDOM_SOUND: +-------------------------- +Parameter 1: The Sound ID to be played as Random Choice #1. +Parameter 2: The Sound ID to be played as Random Choice #2. +Parameter 3: The Sound ID to be played as Random Choice #3. + +Similar to the ACTION_T_SOUND action, it will choose at random a sound to play. + +--------------------------- +10 = ACTION_T_RANDOM_EMOTE: +--------------------------- +Parameter 1: The Emote ID to be played as Random Choice #1. +Parameter 2: The Emote ID to be played as Random Choice #2. +Parameter 3: The Emote ID to be played as Random Choice #3. + +Similar to the ACTION_T_EMOTE action, it will choose at random an Emote to Visually Perform. + +------------------- +11 = ACTION_T_CAST: +------------------- +Parameter 1: SpellId - The Spell ID to use for the NPC to cast. The value used in this field needs to be a valid Spell ID. +Parameter 2: Target - The Target Type defining who the creature should cast the spell at. The value in this field needs to be a valid Target Type as specified in the reference tables below. +Parameter 3: CastFlags - See Table Below for Cast Flag Bitmask Values. If you are unsure what to set this value at leave it at 0. + +The creature will cast a spell specified by a spell ID on a target specified by the target type. +This is commonly used for NPC's who cast spells. + +--------------------- +12 = ACTION_T_SUMMON: +--------------------- +Parameter 1: CreatureID - The Creature Template ID to be Summoned. The value here needs to be a valid Creature Template ID. +Parameter 2: Target - The Target Type defining who the Summoned creature will attack once spawned. The value in this field needs to be a valid Target Type as specified in the reference tables below. +Parameter 3: Duration - The duration until the summoned creature should be unsummoned AFTER Combat ends. The value in this field is in milliseconds or 0. + +The NPC will Summon another creature at the same spot as itself that will attack the specified target. +NOTE: Almost all Creature Summons have proper Summon Spells that should be used when possible. This Action is a powerful last resort option only to be used if nothing else works. +NOTE: Using Target Type 0 will cause the Summoned creature to not attack anyone. +NOTE: If Duration is set at 0, then the summoned creature will not despawn until it has died. +This is used as a manual way to force an NPC to Summon. +-------------------------------- +13 = ACTION_T_THREAT_SINGLE_PCT: +-------------------------------- +Parameter 1: Threat% - Threat percent that should be modified. The value in this field can range from -100 to +100. If it is negative, threat will be taken away and if positive, threat will be added. +Parameter 2: Target - The Target Type defining on whom the threat change should occur. The value in this field needs to be a valid target type as specified in the reference tables below. + +This action will modify the threat of a target in the creature's threat list by the specified percent. +This is commonly used to allow an NPC to adjust the Threat to a single player. + +----------------------------- +14 = ACTION_T_THREAT_ALL_PCT: +----------------------------- +Parameter 1: Threat% - The percent that should be used in modifying everyone's threat in the creature's threat list. The value here can range from -100 to +100. + +This action will modify the threat for everyone in the creature's threat list by the specified percent. +NOTE: Using -100 will cause the creature to reset everyone's threat to 0 so that everyone has the same amount of threat. It will NOT remove anyone from the threat list. +This is commonly used to allow an NPC to drop threat for all players to zero. + +-------------------------- +15 = ACTION_T_QUEST_EVENT: +-------------------------- +Parameter 1: QuestID - The Quest Template ID. The value here must be a valid quest template ID. Furthermore, the quest should have SpecialFlags | 2 as it would need to be completed by an external event which is the activation of this action. +Parameter 2: Target - The Target Type defining whom the quest should be completed for. The value in this field needs to be a valid target type as specified in the reference tables below. + +This action will satisfy the external completion requirement for the quest for the specified target defined by the target type. +NOTE: This action can only be used with player targets so it must be ensured that the target type will point to a player. +This is commonly used for Quests where only ONE player will gain credit for the quest. + +----------------------------- +16 = ACTION_T_CASTCREATUREGO: +----------------------------- +Parameter 1: CreatureID - The Creature Template ID to be Summoned. The value here needs to be a valid Creature Template ID. +Parameter 2: SpellId - The Spell ID to use to simulate the cast. The value used in this field needs to be a valid Spell ID. +Parameter 3: Target - The Target Type defining whom the quest credit should be given to. The value in this field needs to be a valid target type as specified in the reference tables below. + +This action will call CastedCreatureOrGO() function for the player. It can be used to give quest credit for casting a spell on the creature. +This is commonly used for NPC's who have a special requirement to have a Spell cast on them to complete a quest. + +----------------------------- +17 = ACTION_T_SET_UNIT_FIELD: +----------------------------- +Parameter 1: Field_Number - The index of the Field Number to be changed. Use (http://wiki.udbforums.org/index.php/Character_data) for a list of indeces and what they control. Creatures only contain the OBJECT_FIELD_* and UNIT_FIELD_* fields. They do not contain the PLAYER_FIELD_* fields. +Parameter 2: Value - The new value to be put in the field. +Parameter 3: Target - The Target Type defining for whom the unit field should be changed. The value in this field needs to be a valid target type as specified in the reference tables below. + +When activated, this action can change the target's unit field values. More information on the field value indeces can be found at (http://wiki.udbforums.org/index.php/Character_data) + +---------------------------- +18 = ACTION_T_SET_UNIT_FLAG: +---------------------------- +Parameter 1: Flags - The flag(s) to be set. Multiple flags can be set by using bitwise-OR on them (adding them together). +Parameter 2: Target - The Target Type defining for whom the flags should be changed. The value in this field needs to be a valid Target Type as specified in the reference tables below. + +When activated, this action changes the target's flags by adding (turning on) more flags. For example, this action can make the creature unattackable/unselectable if the right flags are used. + +------------------------------- +19 = ACTION_T_REMOVE_UNIT_FLAG: +------------------------------- +Parameter 1: Flags - The flag(s) to be removed. Multiple flags can be set by using bitwise-OR on them (adding them together). +Parameter 2: Target - The target type defining for whom the flags should be changed. The value in this field needs to be a valid Target Type as specified in the reference tables below. + +When activated, this action changes the target's flags by removing (turning off) flags. For example, this action can make the creature normal after it was unattackable/unselectable if the right flags are used. + +-------------------------- +20 = ACTION_T_AUTO_ATTACK: +-------------------------- +Parameter 1: AllowAutoAttack - If zero, then the creature will stop its melee attacks. If non-zero, then the creature will either continue its melee attacks (the action would then have no effect) or it will start its melee attacks on the target with the top threat if its melee attacks were previously stopped. + +This action controls whether or not the creature should stop or start the auto melee attack. +NOTE: The ACID Dev Team has conformed to using either 0 or 1 for the Param values (0 = Stop Melee, 1 = Start Melee). +This is commonly used in combination with EVENT_T_RANGE and ACTION_T_COMBAT_MOVEMENT for Ranged Combat for Mages and Spell Casters. + +------------------------------ +21 = ACTION_T_COMBAT_MOVEMENT: +------------------------------ +Parameter 1: If zero, then the creature will stop moving towards its victim (if its victim gets out of melee range) and will be stationary. If non-zero, then the creature will either continue to follow its victim (the action would have no effect) or it will start to follow the target with the top threat if its movement was disabled before. + +This action controls whether or not the creature will always move towards its target. +NOTE: The ACID Dev Team has conformed to using either 0 or 1 for the Param values. (0 = Stop Movement, 1 = Start Movement) +This is commonly used with EVENT_T_RANGE and ACTION_T_AUTO_ATTACK for NPC's who engage in Ranged Comabt (Either Spells or Ranged Attacks) + +------------------------ +22 = ACTION_T_SET_PHASE: +------------------------ +Parameter 1: The new phase to set the creature in. This number must be an integer between 0 and 31. Numbers outside of that range will result in an error. + +When activated, this action sets the creature's event to the specified value. +NOTE: The creature's current Phase is NOT reset at creature evade. You must manually set the phase back to 0 at EVENT_T_RESET. +NOTE: The value used for the Param is the actual Phase Number (Not The Event_Inverse_Phase_Mask) +This is commonly used for complex scripts with several phases and you need to switch to a different phase. + +------------------------ +23 = ACTION_T_INC_PHASE: +------------------------ +Parameter 1: Value - The number of phases to increase or decrease. Use negative values to decrease the current phase. + +When activated, this action will increase (or decrease) the current creature's phase. +NOTE: After increasing or decreasing the phase by this action, the current phase must NOT be lower than 0 or exceed 31. +This can be used instead of ACTION_T_SET_PHASE to change phases in scripts. Just a user friendly option for changing phases. + +-------------------- +24 = ACTION_T_EVADE: +-------------------- +When activated, the creature will immediately exit out of combat, clear its threat list, and move back to its spawn point. Basically, this action will reset the whole encounter. +NOTE: All Param Values Are 0 for this Action. + +------------------- +25 = ACTION_T_FLEE: +------------------- +When activated, the creature will try to flee from combat. Currently this is done by it casting a fear-like spell on itself called "Run Away". A Better Flee system is in Development but will take time before it is implimented. +NOTE: All Param Values Are 0 for this Action. + +------------------------------ +26 = ACTION_T_QUEST_EVENT_ALL: +------------------------------ +Parameter 1: QuestId - The quest ID to finish for everyone. + +This action does the same thing as the ACTION_T_QUEST_EVENT does but it does it for all players in the creature's threat list. +NOTE: If a player is not in the NPC's threat list for whatever reason, he/she won't get the quest completed. + +--------------------------------- +27 = ACTION_T_CASTCREATUREGO_ALL: +--------------------------------- +Parameter 1: QuestId - The quest template ID. +Parameter 2: SpellId - The spell ID used to simulate the cast. + +This action does the same thing as the ACTION_T_CASTCREATUREGO does but it does it for all players in the creature's threat list. +NOTE: If a player is not in its threat list for whatever reason, he/she won't receive the cast emulation. + +----------------------------------- +28 = ACTION_T_REMOVEAURASFROMSPELL: +----------------------------------- +Parameter 1: Target - The target type defining for whom the unit field should be changed. The value in this field needs to be a valid target type as specified in the reference tables below. +Parameter 2: SpellId - The spell ID whose auras will be removed. + +This action will remove all auras from a specific spell from the target. +This is commonly used for NPC's who have an OOC Aura that is removed at combat start or a similar idea (Like Stealth or Shape Shift) + +------------------------------ +29 = ACTION_T_RANGED_MOVEMENT: +------------------------------ +Parameter 1: Distance - The distance the mob should keep between it and its target. +Parameter 2: Angle - The angle the mob should use. + +This action changes the movement type generator to ranged type using the specified values for angle and distance. +NOTE: Specifying zero angle and distance will make it just melee instead. +This is commonly used for NPC's who always attack at range and you can specify the distance they will maintain from the target. + +--------------------------- +30 = ACTION_T_RANDOM_PHASE: +--------------------------- +Parameter 1: PhaseId1 - A possible random phase choice. +Parameter 2: PhaseId2 - A possible random phase choice. +Parameter 3: PhaseId3 - A possible random phase choice. + +Randomly sets the phase to one from the three parameter choices. +NOTE: Use -1 to specify that if this param is picked to do nothing. Random is constant between actions within an event. So if you have a random Yell and a random Sound they will match up (ex: param2 with param2) +NOTE 2: PLEASE NOTE THAT EACH OF THE PARAM VALUES ARE ACTUAL PHASE NUMBERS NOT THE INVERSE PHASE MASK VALUE. +This is commonly used for Spellcasting NPC's who on Aggro may select at random a school of spells to use for the fight. Use this if you have up to 3 phases used, otherwise use Action 31 for more then 3 phases. + +--------------------------------- +31 = ACTION_T_RANDOM_PHASE_RANGE: +--------------------------------- +Parameter 1: PhaseMin - The minimum of the phase range. +Parameter 2: PhaseMax - The maximum of the phase range. The number here must be greater than PhaseMin. + +Randomly sets the phase between a range of phases controlled by the parameters. Sets the phase to a random id (Phase = PhaseMin + rnd % PhaseMin-PhaseMax). +NOTE: PhaseMax must be greater than PhaseMin. +NOTE 2: PLEASE NOTE THAT EACH OF THE PARAM VALUES ARE ACTUAL PHASE NUMBERS NOT THE INVERSE PHASE MASK VALUE. +This is commonly used for Spellcasting NPC's who on Aggro may select at random a school of spells to use for the fight. Use this if you have MORE then 3 phases used, otherwise use Action 30. + +--------------------- +32 = ACTION_T_SUMMON: +--------------------- +Parameter 1: CreatureID - The creature template ID to be summoned. The value here needs to be a valid creature template ID. +Parameter 2: Target - The target type defining who the summoned creature will attack. The value in this field needs to be a valid target type as specified in the reference tables below. NOTE: Using target type 0 will cause the summoned creature to not attack anyone. +Parameter 3: SummonID - The summon ID from the eventai_summons table controlling the position (and spawntime) where the summoned mob should be spawned at. + +Summons creature (param1) to attack target (param2) at location specified by EventAI_Summons (param3). +NOTE: Param3 Value is the ID Value used for the entry used in EventAI_Summons for this action. You MUST have an EventAI_Summons entry to use this action. +This is commonly used for NPC's who need to Summon a creature at a specific location. (Normally used for complex events) + +----------------------------- +33 = ACTION_T_KILLED_MONSTER: +----------------------------- +Parameter 1: CreatureID - The creature template ID. The value here must be a valid creature template ID. +Parameter 2: Target - The target type defining whom the quest kill count should be given to. The value in this field needs to be a valid target type as specified in the reference tables below. + +When activated, this action will call KilledMonster() function for the player. It can be used to give creature credit for killing a creature. In general if the quest is set to be accompished on different creatures (e.g. "Credit" templates). +NOTE: It can be ANY creature including certain quest specific triggers +This is commonly used for giving the player Quest Credits for NPC kills (Many NPC's may use the same CreatureID for the Kill Credit) + +---------------------------- +34 = ACTION_T_SET_INST_DATA: +---------------------------- +Parameter 1: Field - The field to change in the instance script. Again, this field needs to be a valid field that has been already defined in the instance's script. +Parameter 2: Data - The value to put at that field index. + +Sets data for the instance. Note that this will only work when the creature is inside an instantiable zone that has a valid script (ScriptedInstance) assigned. +NOTE: Param1 Value is located in "def_.h" SD2 File and Param2 value is generally found in the "sc_instance.h" file in SD2 +This is commonly used to link an ACID script with a SD2 C++ Script. You make make things happen like opening doors on specific events that happen. ACID Just triggers the C++ Script to function. + +------------------------------ +35 = ACTION_T_SET_INST_DATA64: +------------------------------ +Parameter 1: Field - The field to change in the instance script. Again, this field needs to be a valid field that has been already defined in the instance's script. +Parameter 2: Target - The target type to use to get the GUID that will be stored at the field index. The value in this field needs to be a valid target type as specified in the reference tables below. + +Sets GUID (64 bits) data for the instance based on the target. Note that this will only work when the creature is inside an instantiable zone that has a valid script (ScriptedInstance) assigned. +Calls ScriptedInstance::SetData64 with field (param1) and data (param2) target's GUID. + +------------------------------ +36 = ACTION_T_UPDATE_TEMPLATE: +------------------------------ +Parameter 1: TemplateId - The creature template ID. The value here must be a valid creature template ID. +Parameter 2: Team - Use model_id from team : Alliance(0) or Horde (1). + +This function temporarily changes creature entry to new entry, display is changed, loot is changed, but AI is not changed. At respawn creature will be reverted to original entry. +Changes the creature to a new creature template of (param1) with team = Alliance if (param2) = false or Horde if (param2) = true + +------------------ +37 = ACTION_T_DIE: +------------------ +Kills the creature +This is commonly used if you need to Instakill the creature for one reason or another. + +-------------------------------- +38 = ACTION_T_ZONE_COMBAT_PULSE: +-------------------------------- +Places all players within the instance into combat with the creature. Only works in combat and only works inside of instances. + + +========================================= +Target Types +========================================= +Below is the list of current Target types that EventAI can handle. +Target types are used by certain actions and may effect actions differently + +(# Internal Name Discription) +0 TARGET_T_SELF Self cast +1 TARGET_T_HOSTILE Our current target (ie: highest aggro) +2 TARGET_T_HOSTILE_SECOND_AGGRO Second highest aggro (generaly used for cleaves and some special attacks) +3 TARGET_T_HOSTILE_LAST_AGGRO Dead last on aggro (no idea what this could be used for) +4 TARGET_T_HOSTILE_RANDOM Just any random target on our threat list +5 TARGET_T_HOSTILE_RANDOM_NOT_TOP Any random target except top threat +6 TARGET_T_ACTION_INVOKER Unit who caused this Event to occur (only works for EVENT_T_AGGRO, EVENT_T_KILL, EVENT_T_DEATH, EVENT_T_SPELLHIT, EVENT_T_OOC_LOS, EVENT_T_FRIENDLY_HP) + +========================================= +Cast Flags +========================================= +Below is the list of current Cast Flags that EventAI's spell casting can handle. +Cast flags are handled bitwise. Bit 0 is Interrupt Previous, bit 1 is triggered, etc. +So for example the number "3" (11 in Binary, selecting first 2 options) would mean that this cast has both CAST_INTURRUPT_PREVIOUS and CAST_TRIGGERED. +Another example: the number "5" (101 in Binary, selecting first and third options) would mean that this cast has CAST_INTURRUPT_PREVIOUS and CAST_FORCE_CAST. + +(bit# Decimal Internal Name Discription) +0 1 CAST_INTURRUPT_PREVIOUS Interrupts any previous spell casting (basicaly makes sure that this spell goes off) +1 2 CAST_TRIGGERED Forces the spell to be instant cast and require no mana/reagents. +2 4 CAST_FORCE_CAST Forces spell to cast even if the target is possibly out of range or the creature is possibly out of mana +3 8 CAST_NO_MELEE_IF_OOM Prevents creature from entering melee if out of mana or out of range +4 16 CAST_FORCE_TARGET_SELF Forces the target to cast this spell on itself + +NOTE: You can add the numbers in the decimal column to combine flags. + For example if you wanted to use CAST_NO_MELEE_IF_OOM(8) and CAST_TRIGGERED(2) you would simply use 10 in the cast flags field (8 + 2 = 10). + +========================================= +Event Flags +========================================= +Below is the list of current Event Flags that EventAI can handle. Event flags are handled bitwise. + +(bit# Decimal Internal Name Discription) +0 1 EFLAG_REPEATABLE Event repeats (Does not repeat if this flag is not set) +1 2 EFLAG_NORMAL Event occurs in Normal instance difficulty (will not occur in Normal if not set) +2 4 EFLAG_HEROIC Event occurs in Heroic instance difficulty (will not occur in Heroic if not set) +3 8 +4 16 +5 32 +6 64 +7 128 EFLAG_DEBUG_ONLY Prevents events from occuring on Release builds of ScriptDev2. Useful for testing new features. + +NOTE: You can add the numbers in the decimal column to combine flags. \ No newline at end of file diff --git a/src/bindings/scripts/docs/How to install.txt b/src/bindings/scripts/docs/How to install.txt new file mode 100644 index 00000000000..10efdf94de9 --- /dev/null +++ b/src/bindings/scripts/docs/How to install.txt @@ -0,0 +1,32 @@ +--- How to install ScriptDev2 --- + +1) Download MaNGOS +2) Create a new folder under "src\bindings\" within the MaNGOS source called "ScriptDev2" +3) Checkout the ScriptDev2 trunk from "https://scriptdev2.svn.sourceforge.net/svnroot/scriptdev2" + +4a) On Win32: + - Compile MaNGOS + - Compile ScriptDev2 using the ScriptVC70, ScriptVC80, or ScriptVC90 Solution within the ScriptDev2 folder (this will overwrite the Mangoscript dll in the output directory) + +4b) On Linux: +- Apply MaNGOS-rXXXX-ScriptDev2.patch, where XXXX is the highest version to that of your MaNGOS revision, to Mangos Source +- Compile MaNGOS (ScriptDev2 will automatically be built when compiling Mangos from here on) + +5) Create the default ScriptDev2 database using "sql\created_database.sql", then execute "sql\scriptdev2_structure.sql" on that database. + +6) Execute the included "sql\mangos_full_scripts.sql" on your MaNGOS database. + +7) Place the included "scriptdev2.conf" file within the directory containing your "mangosd.conf" and "realmd.conf" files. You may need to change this file to match the database you created and any custom settings you wish to use (such as a different locale). + +8) Run mangosd from your output directory + + +To update ScriptDev2: +All you have to do is open src\bindings\ and right click on the ScriptDev2 folder and click "Update" and then follow steps 4, 6, 7, and 8 again. You must still compile MaNGOS before ScriptDev2 when on the Windows platform. + +To update your Database with new Scriptdev2 SQL changes you can either: +a) apply only the changes that were made during that revision by looking in the sql\update folder or (files named rXXX_scriptdev2.sql should be executed on the scriptdev2 db while rXXX_mangos.sql should be executed on your mangos db) +b) reapply "mangos_full_scripts.sql" to your MaNGOS database. + +You can view the ScriptDev2 Change Log at: +[url=http://scriptdev2.svn.sourceforge.net/viewvc/scriptdev2/?view=log]http://scriptdev2.svn.sourceforge.net/viewvc/scriptdev2/?view=log[/url] \ No newline at end of file diff --git a/src/bindings/scripts/docs/LICENSE.txt b/src/bindings/scripts/docs/LICENSE.txt new file mode 100644 index 00000000000..69cd8a1df6d --- /dev/null +++ b/src/bindings/scripts/docs/LICENSE.txt @@ -0,0 +1,280 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/src/bindings/scripts/docs/Script Layout.txt b/src/bindings/scripts/docs/Script Layout.txt new file mode 100644 index 00000000000..2c749952f70 --- /dev/null +++ b/src/bindings/scripts/docs/Script Layout.txt @@ -0,0 +1,32 @@ +--- Script Layout --- +A quick explination of the layout I hope everyone will follow for scriptdev2. + +--- Sub Folders --- + +Area - Contains scripts used solely by area triggers + +Boss - Boss scripts for bosses that are not zone specific + +Mob - Generic Creature scripts for creatures that are not zone specific + +Custom - Intentionally empty folder from SVN. If you make a custom script please put it here. + +GO - Contains scripts used solely by Game Objects (GOs) that do not have a specific zone + +Guard - Scripts for Guard NPCs + +Honor - Honor npcs (currently a blank script as these npcs do nothing special) + +Item - Item scripts + +NPC - Scripts for individual NPCs who do not have a specific zone + +Servers - Generic NPC servers script for things such as flightmasters and guildmasters. + +Zone - ALL zone specific scripts should be written within these folders. This includes creature scripts, boss scripts, go scripts, area scripts, and npc scripts. + +--- Naming Conventions --- + +Please keep file names to "type_objectname.cpp" where type is replaced by the type of object and objectname is replaced by the name of the object, creature, item, or area that this script will be used by. + +AddSC functions should follow "void AddSC_creaturename(void);" format. Do not append AI or anything else. \ No newline at end of file diff --git a/src/bindings/scripts/docs/ToDo.txt b/src/bindings/scripts/docs/ToDo.txt new file mode 100644 index 00000000000..5df315da037 --- /dev/null +++ b/src/bindings/scripts/docs/ToDo.txt @@ -0,0 +1,14 @@ +--- TO DO --- +Simple list of things we need to do. + +--- ScriptDev2 Framework --- +Move all text out of C++ code and into SD2 database. + +--- Scripting with Priorities --- +1) Boss AI and Boss Event scripts +2) Specific NPC AI, Gossip, Quest, Event scripts +3) Spell and Item scripts + +--- Core Problems --- + +- Spell scripts are only scriptable within the core. Spell scripts should be done in SD2 since they are very specialized. \ No newline at end of file diff --git a/src/bindings/scripts/include/precompiled.cpp b/src/bindings/scripts/include/precompiled.cpp new file mode 100644 index 00000000000..8863d83ac06 --- /dev/null +++ b/src/bindings/scripts/include/precompiled.cpp @@ -0,0 +1,5 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 +* This program is free software licensed under GPL version 2 +* Please see the included DOCS/LICENSE.TXT for more information */ + +#include "precompiled.h" diff --git a/src/bindings/scripts/include/precompiled.h b/src/bindings/scripts/include/precompiled.h new file mode 100644 index 00000000000..dda4d672f38 --- /dev/null +++ b/src/bindings/scripts/include/precompiled.h @@ -0,0 +1,25 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 +* This program is free software licensed under GPL version 2 +* Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef SC_PRECOMPILED_H +#define SC_PRECOMPILED_H + +#include "../ScriptMgr.h" +#include "sc_creature.h" +#include "sc_gossip.h" +#include "sc_grid_searchers.h" +#include "sc_instance.h" + +#ifdef WIN32 +#include +BOOL APIENTRY DllMain( HANDLE hModule, +DWORD ul_reason_for_call, +LPVOID lpReserved +) +{ + return true; +} +#endif + +#endif diff --git a/src/bindings/scripts/include/sc_creature.cpp b/src/bindings/scripts/include/sc_creature.cpp new file mode 100644 index 00000000000..afdbf590c65 --- /dev/null +++ b/src/bindings/scripts/include/sc_creature.cpp @@ -0,0 +1,612 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#include "precompiled.h" +#include "Item.h" +#include "Spell.h" +#include "WorldPacket.h" + +// Spell summary for ScriptedAI::SelectSpell +struct TSpellSummary { + uint8 Targets; // set of enum SelectTarget + uint8 Effects; // set of enum SelectEffect +} *SpellSummary; + +bool ScriptedAI::IsVisible(Unit* who) const +{ + if (!who) + return false; + + return (m_creature->GetDistance(who) < VISIBLE_RANGE) && who->isVisibleForOrDetect(m_creature,true); +} + +void ScriptedAI::MoveInLineOfSight(Unit *who) +{ + if( !m_creature->getVictim() && who->isTargetableForAttack() && ( m_creature->IsHostileTo( who )) && who->isInAccessablePlaceFor(m_creature) ) + { + if (m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = m_creature->GetAttackDistance(who); + if( m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->IsWithinLOSInMap(who) ) + { + DoStartAttackAndMovement(who); + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + if (!InCombat) + { + Aggro(who); + InCombat = true; + } + } + } +} + +void ScriptedAI::AttackStart(Unit* who) +{ + if (!who) + return; + + if (who->isTargetableForAttack()) + { + //Begin attack + DoStartAttackAndMovement(who); + + if (!InCombat) + { + Aggro(who); + InCombat = true; + } + } +} + +void ScriptedAI::UpdateAI(const uint32 diff) +{ + //Check if we have a current target + if( m_creature->isAlive() && m_creature->SelectHostilTarget() && m_creature->getVictim()) + { + if( m_creature->isAttackReady() ) + { + //If we are within range melee the target + if( m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE)) + { + m_creature->AttackerStateUpdate(m_creature->getVictim()); + m_creature->resetAttackTimer(); + } + } + } +} + +void ScriptedAI::EnterEvadeMode() +{ + m_creature->InterruptNonMeleeSpells(true); + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); + m_creature->CombatStop(); + m_creature->LoadCreaturesAddon(); + + if( m_creature->isAlive() ) + m_creature->GetMotionMaster()->MoveTargetedHome(); + + m_creature->SetLootRecipient(NULL); + + InCombat = false; + Reset(); +} + +void ScriptedAI::JustRespawned() +{ + InCombat = false; + Reset(); +} + +void ScriptedAI::DoStartAttackAndMovement(Unit* victim, float distance, float angle) +{ + if (!victim) + return; + + if ( m_creature->Attack(victim, true) ) + { + m_creature->GetMotionMaster()->MoveChase(victim, distance, angle); + m_creature->AddThreat(victim, 0.0f); + } +} + +void ScriptedAI::DoStartAttackNoMovement(Unit* victim) +{ + if (!victim) + return; + + if ( m_creature->Attack(victim, true) ) + { + m_creature->AddThreat(victim, 0.0f); + } +} + + +void ScriptedAI::DoMeleeAttackIfReady() +{ + //Make sure our attack is ready and we aren't currently casting before checking distance + if( m_creature->isAttackReady() && !m_creature->IsNonMeleeSpellCasted(false)) + { + //If we are within range melee the target + if( m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE)) + { + m_creature->AttackerStateUpdate(m_creature->getVictim()); + m_creature->resetAttackTimer(); + } + } +} + +void ScriptedAI::DoStopAttack() +{ + if( m_creature->getVictim() != NULL ) + { + m_creature->AttackStop(); + } +} + +void ScriptedAI::DoCast(Unit* victim, uint32 spellId, bool triggered) +{ + if (!victim || m_creature->IsNonMeleeSpellCasted(false)) + return; + + m_creature->StopMoving(); + m_creature->CastSpell(victim, spellId, triggered); +} + +void ScriptedAI::DoCastSpell(Unit* who,SpellEntry const *spellInfo, bool triggered) +{ + if (!who || m_creature->IsNonMeleeSpellCasted(false)) + return; + + m_creature->StopMoving(); + m_creature->CastSpell(who, spellInfo, triggered); +} + +void ScriptedAI::DoSay(const char* text, uint32 language, Unit* target) +{ + if (target)m_creature->Say(text, language, target->GetGUID()); + else m_creature->Say(text, language, 0); +} + +void ScriptedAI::DoYell(const char* text, uint32 language, Unit* target) +{ + if (target)m_creature->Yell(text, language, target->GetGUID()); + else m_creature->Yell(text, language, 0); +} + +void ScriptedAI::DoTextEmote(const char* text, Unit* target, bool IsBossEmote) +{ + if (target)m_creature->TextEmote(text, target->GetGUID(), IsBossEmote); + else m_creature->TextEmote(text, 0, IsBossEmote); +} + +void ScriptedAI::DoWhisper(const char* text, Unit* reciever, bool IsBossWhisper) +{ + if (!reciever || reciever->GetTypeId() != TYPEID_PLAYER) + return; + + m_creature->Whisper(text, reciever->GetGUID(), IsBossWhisper); +} + +void ScriptedAI::DoPlaySoundToSet(Unit* unit, uint32 sound) +{ + if (!unit) + return; + + if (!GetSoundEntriesStore()->LookupEntry(sound)) + { + error_log("SD2: Invalid soundId %u used in DoPlaySoundToSet (by unit TypeId %u, guid %u)", sound, unit->GetTypeId(), unit->GetGUID()); + return; + } + + WorldPacket data(4); + data.SetOpcode(SMSG_PLAY_SOUND); + data << uint32(sound); + unit->SendMessageToSet(&data,false); +} + +Creature* ScriptedAI::DoSpawnCreature(uint32 id, float x, float y, float z, float angle, uint32 type, uint32 despawntime) +{ + return m_creature->SummonCreature(id,m_creature->GetPositionX() + x,m_creature->GetPositionY() + y,m_creature->GetPositionZ() + z, angle, (TempSummonType)type, despawntime); +} + +Unit* ScriptedAI::SelectUnit(SelectAggroTarget target, uint32 position) +{ + //ThreatList m_threatlist; + std::list& m_threatlist = m_creature->getThreatManager().getThreatList(); + std::list::iterator i = m_threatlist.begin(); + std::list::reverse_iterator r = m_threatlist.rbegin(); + + if (position >= m_threatlist.size() || !m_threatlist.size()) + return NULL; + + switch (target) + { + case SELECT_TARGET_RANDOM: + advance ( i , position + (rand() % (m_threatlist.size() - position ) )); + return Unit::GetUnit((*m_creature),(*i)->getUnitGuid()); + break; + + case SELECT_TARGET_TOPAGGRO: + advance ( i , position); + return Unit::GetUnit((*m_creature),(*i)->getUnitGuid()); + break; + + case SELECT_TARGET_BOTTOMAGGRO: + advance ( r , position); + return Unit::GetUnit((*m_creature),(*r)->getUnitGuid()); + break; + } + + return NULL; +} + +SpellEntry const* ScriptedAI::SelectSpell(Unit* Target, int32 School, int32 Mechanic, SelectTarget Targets, uint32 PowerCostMin, uint32 PowerCostMax, float RangeMin, float RangeMax, SelectEffect Effects) +{ + //No target so we can't cast + if (!Target) + return false; + + //Silenced so we can't cast + if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED)) + return false; + + //Using the extended script system we first create a list of viable spells + SpellEntry const* Spell[4]; + Spell[0] = 0; + Spell[1] = 0; + Spell[2] = 0; + Spell[3] = 0; + + uint32 SpellCount = 0; + + SpellEntry const* TempSpell; + SpellRangeEntry const* TempRange; + + //Check if each spell is viable(set it to null if not) + for (uint32 i = 0; i < 4; i++) + { + TempSpell = GetSpellStore()->LookupEntry(m_creature->m_spells[i]); + + //This spell doesn't exist + if (!TempSpell) + continue; + + // Targets and Effects checked first as most used restrictions + //Check the spell targets if specified + if ( Targets && !(SpellSummary[m_creature->m_spells[i]].Targets & (1 << (Targets-1))) ) + continue; + + //Check the type of spell if we are looking for a specific spell type + if ( Effects && !(SpellSummary[m_creature->m_spells[i]].Effects & (1 << (Effects-1))) ) + continue; + + //Check for school if specified + if (School >= 0 && TempSpell->SchoolMask & School) + continue; + + //Check for spell mechanic if specified + if (Mechanic >= 0 && TempSpell->Mechanic != Mechanic) + continue; + + //Make sure that the spell uses the requested amount of power + if (PowerCostMin && TempSpell->manaCost < PowerCostMin) + continue; + + if (PowerCostMax && TempSpell->manaCost > PowerCostMax) + continue; + + //Continue if we don't have the mana to actually cast this spell + if (TempSpell->manaCost > m_creature->GetPower((Powers)TempSpell->powerType)) + continue; + + //Get the Range + TempRange = GetSpellRangeStore()->LookupEntry(TempSpell->rangeIndex); + + //Spell has invalid range store so we can't use it + if (!TempRange) + continue; + + //Check if the spell meets our range requirements + if (RangeMin && TempRange->maxRange < RangeMin) + continue; + if (RangeMax && TempRange->maxRange > RangeMax) + continue; + + //Check if our target is in range + if (m_creature->IsWithinDistInMap(Target, TempRange->minRange) || !m_creature->IsWithinDistInMap(Target, TempRange->maxRange)) + continue; + + //All good so lets add it to the spell list + Spell[SpellCount] = TempSpell; + SpellCount++; + } + + //We got our usable spells so now lets randomly pick one + if (!SpellCount) + return NULL; + + return Spell[rand()%SpellCount]; +} + +bool ScriptedAI::CanCast(Unit* Target, SpellEntry const *Spell, bool Triggered) +{ + //No target so we can't cast + if (!Target || !Spell) + return false; + + //Silenced so we can't cast + if (!Triggered && m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED)) + return false; + + //Check for power + if (!Triggered && m_creature->GetPower((Powers)Spell->powerType) < Spell->manaCost) + return false; + + SpellRangeEntry const *TempRange = NULL; + + TempRange = GetSpellRangeStore()->LookupEntry(Spell->rangeIndex); + + //Spell has invalid range store so we can't use it + if (!TempRange) + return false; + + //Unit is out of range of this spell + if (m_creature->GetDistance(Target) > TempRange->maxRange || m_creature->GetDistance(Target) < TempRange->minRange) + return false; + + return true; +} + +void FillSpellSummary() +{ + SpellSummary = new TSpellSummary[GetSpellStore()->GetNumRows()]; + + SpellEntry const* TempSpell; + + for (int i=0; i < GetSpellStore()->GetNumRows(); i++ ) + { + SpellSummary[i].Effects = 0; + SpellSummary[i].Targets = 0; + + TempSpell = GetSpellStore()->LookupEntry(i); + //This spell doesn't exist + if (!TempSpell) + continue; + + for (int j=0; j<3; j++) + { + //Spell targets self + if ( TempSpell->EffectImplicitTargetA[j] == TARGET_SELF ) + SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SELF-1); + + //Spell targets a single enemy + if ( TempSpell->EffectImplicitTargetA[j] == TARGET_CHAIN_DAMAGE || + TempSpell->EffectImplicitTargetA[j] == TARGET_CURRENT_ENEMY_COORDINATES ) + SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SINGLE_ENEMY-1); + + //Spell targets AoE at enemy + if ( TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA || + TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_INSTANT || + TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_AROUND_CASTER || + TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_CHANNELED ) + SpellSummary[i].Targets |= 1 << (SELECT_TARGET_AOE_ENEMY-1); + + //Spell targets an enemy + if ( TempSpell->EffectImplicitTargetA[j] == TARGET_CHAIN_DAMAGE || + TempSpell->EffectImplicitTargetA[j] == TARGET_CURRENT_ENEMY_COORDINATES || + TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA || + TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_INSTANT || + TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_AROUND_CASTER || + TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_CHANNELED ) + SpellSummary[i].Targets |= 1 << (SELECT_TARGET_ANY_ENEMY-1); + + //Spell targets a single friend(or self) + if ( TempSpell->EffectImplicitTargetA[j] == TARGET_SELF || + TempSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_FRIEND || + TempSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_PARTY ) + SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SINGLE_FRIEND-1); + + //Spell targets aoe friends + if ( TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_PARTY_AROUND_CASTER || + TempSpell->EffectImplicitTargetA[j] == TARGET_AREAEFFECT_PARTY || + TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_AROUND_CASTER) + SpellSummary[i].Targets |= 1 << (SELECT_TARGET_AOE_FRIEND-1); + + //Spell targets any friend(or self) + if ( TempSpell->EffectImplicitTargetA[j] == TARGET_SELF || + TempSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_FRIEND || + TempSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_PARTY || + TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_PARTY_AROUND_CASTER || + TempSpell->EffectImplicitTargetA[j] == TARGET_AREAEFFECT_PARTY || + TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_AROUND_CASTER) + SpellSummary[i].Targets |= 1 << (SELECT_TARGET_ANY_FRIEND-1); + + //Make sure that this spell includes a damage effect + if ( TempSpell->Effect[j] == SPELL_EFFECT_SCHOOL_DAMAGE || + TempSpell->Effect[j] == SPELL_EFFECT_INSTAKILL || + TempSpell->Effect[j] == SPELL_EFFECT_ENVIRONMENTAL_DAMAGE || + TempSpell->Effect[j] == SPELL_EFFECT_HEALTH_LEECH ) + SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_DAMAGE-1); + + //Make sure that this spell includes a healing effect (or an apply aura with a periodic heal) + if ( TempSpell->Effect[j] == SPELL_EFFECT_HEAL || + TempSpell->Effect[j] == SPELL_EFFECT_HEAL_MAX_HEALTH || + TempSpell->Effect[j] == SPELL_EFFECT_HEAL_MECHANICAL || + (TempSpell->Effect[j] == SPELL_EFFECT_APPLY_AURA && TempSpell->EffectApplyAuraName[j]== 8 )) + SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_HEALING-1); + + //Make sure that this spell applies an aura + if ( TempSpell->Effect[j] == SPELL_EFFECT_APPLY_AURA ) + SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_AURA-1); + } + } +} + +void ScriptedAI::DoZoneInCombat(Unit* pUnit) +{ + if (!pUnit) + pUnit = m_creature; + + Map *map = pUnit->GetMap(); + + if (!map->IsDungeon()) //use IsDungeon instead of Instanceable, in case battlegrounds will be instantiated + { + error_log("SD2: DoZoneInCombat call for map that isn't an instance (pUnit entry = %d)", pUnit->GetTypeId() == TYPEID_UNIT ? ((Creature*)pUnit)->GetEntry() : 0); + return; + } + + if (!pUnit->CanHaveThreatList() || pUnit->getThreatManager().isThreatListEmpty()) + { + error_log("SD2: DoZoneInCombat called for creature that either cannot have threat list or has empty threat list (pUnit entry = %d)", pUnit->GetTypeId() == TYPEID_UNIT ? ((Creature*)pUnit)->GetEntry() : 0); + + return; + } + + InstanceMap::PlayerList const &PlayerList = ((InstanceMap*)map)->GetPlayers(); + InstanceMap::PlayerList::const_iterator i; + for (i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if(!(*i)->isGameMaster()) + pUnit->AddThreat(*i, 0.0f); + } +} + +void ScriptedAI::DoResetThreat() +{ + if (!m_creature->CanHaveThreatList() || m_creature->getThreatManager().isThreatListEmpty()) + { + error_log("SD2: DoResetThreat called for creature that either cannot have threat list or has empty threat list (m_creature entry = %d)", m_creature->GetEntry()); + + return; + } + + std::list& m_threatlist = m_creature->getThreatManager().getThreatList(); + std::list::iterator itr; + + for(itr = m_threatlist.begin(); itr != m_threatlist.end(); ++itr) + { + Unit* pUnit = NULL; + pUnit = Unit::GetUnit((*m_creature), (*itr)->getUnitGuid()); + if(pUnit && m_creature->getThreatManager().getThreat(pUnit)) + m_creature->getThreatManager().modifyThreatPercent(pUnit, -100); + } +} + +void ScriptedAI::DoTeleportPlayer(Unit* pUnit, float x, float y, float z, float o) +{ + if(!pUnit || pUnit->GetTypeId() != TYPEID_PLAYER) + { + if(pUnit) + error_log("SD2: Creature %u (Entry: %u) Tried to teleport non-player unit (Type: %u GUID: %u) to x: %f y:%f z: %f o: %f. Aborted.", m_creature->GetGUID(), m_creature->GetEntry(), pUnit->GetTypeId(), pUnit->GetGUID(), x, y, z, o); + return; + } + + ((Player*)pUnit)->TeleportTo(pUnit->GetMapId(), x, y, z, o, TELE_TO_NOT_LEAVE_COMBAT); +} + +Unit* ScriptedAI::DoSelectLowestHpFriendly(float range, uint32 MinHPDiff) +{ + CellPair p(MaNGOS::ComputeCellPair(m_creature->GetPositionX(), m_creature->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + Unit* pUnit = NULL; + + MostHPMissingInRange u_check(m_creature, range, MinHPDiff); + MaNGOS::UnitLastSearcher searcher(pUnit, u_check); + + /* + typedef TYPELIST_4(GameObject, Creature*except pets*, DynamicObject, Corpse*Bones*) AllGridObjectTypes; + This means that if we only search grid then we cannot possibly return pets or players so this is safe + */ + TypeContainerVisitor, GridTypeMapContainer > grid_unit_searcher(searcher); + + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, grid_unit_searcher, *(m_creature->GetMap())); + return pUnit; +} + +std::list ScriptedAI::DoFindFriendlyCC(float range) +{ + CellPair p(MaNGOS::ComputeCellPair(m_creature->GetPositionX(), m_creature->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + std::list pList; + + FriendlyCCedInRange u_check(m_creature, range); + MaNGOS::CreatureListSearcher searcher(pList, u_check); + + TypeContainerVisitor, GridTypeMapContainer > grid_creature_searcher(searcher); + + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, grid_creature_searcher, *(m_creature->GetMap())); + + return pList; +} + +std::list ScriptedAI::DoFindFriendlyMissingBuff(float range, uint32 spellid) +{ + CellPair p(MaNGOS::ComputeCellPair(m_creature->GetPositionX(), m_creature->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + std::list pList; + + FriendlyMissingBuffInRange u_check(m_creature, range, spellid); + MaNGOS::CreatureListSearcher searcher(pList, u_check); + + TypeContainerVisitor, GridTypeMapContainer > grid_creature_searcher(searcher); + + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, grid_creature_searcher, *(m_creature->GetMap())); + + return pList; +} + +void Scripted_NoMovementAI::MoveInLineOfSight(Unit *who) +{ + if( !m_creature->getVictim() && who->isTargetableForAttack() && ( m_creature->IsHostileTo( who )) && who->isInAccessablePlaceFor(m_creature) ) + { + if (m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = m_creature->GetAttackDistance(who); + if( m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->IsWithinLOSInMap(who) ) + { + DoStartAttackNoMovement(who); + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + if (!InCombat) + { + Aggro(who); + InCombat = true; + } + } + } +} + +void Scripted_NoMovementAI::AttackStart(Unit* who) +{ + if (!who) + return; + + if (who->isTargetableForAttack()) + { + //Begin attack + DoStartAttackNoMovement(who); + + if (!InCombat) + { + Aggro(who); + InCombat = true; + } + } +} diff --git a/src/bindings/scripts/include/sc_creature.h b/src/bindings/scripts/include/sc_creature.h new file mode 100644 index 00000000000..13d57a6e78b --- /dev/null +++ b/src/bindings/scripts/include/sc_creature.h @@ -0,0 +1,196 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef SC_CREATURE_H +#define SC_CREATURE_H + +#include "CreatureAI.h" +#include "Creature.h" + +//Spell targets used by SelectSpell +enum SelectTarget +{ + SELECT_TARGET_DONTCARE = 0, //All target types allowed + + SELECT_TARGET_SELF, //Only Self casting + + SELECT_TARGET_SINGLE_ENEMY, //Only Single Enemy + SELECT_TARGET_AOE_ENEMY, //Only AoE Enemy + SELECT_TARGET_ANY_ENEMY, //AoE or Single Enemy + + SELECT_TARGET_SINGLE_FRIEND, //Only Single Friend + SELECT_TARGET_AOE_FRIEND, //Only AoE Friend + SELECT_TARGET_ANY_FRIEND, //AoE or Single Friend +}; + +//Spell Effects used by SelectSpell +enum SelectEffect +{ + SELECT_EFFECT_DONTCARE = 0, //All spell effects allowed + SELECT_EFFECT_DAMAGE, //Spell does damage + SELECT_EFFECT_HEALING, //Spell does healing + SELECT_EFFECT_AURA, //Spell applies an aura +}; + +//Selection method used by SelectTarget +enum SelectAggroTarget +{ + SELECT_TARGET_RANDOM = 0, //Just selects a random target + SELECT_TARGET_TOPAGGRO, //Selects targes from top aggro to bottom + SELECT_TARGET_BOTTOMAGGRO, //Selects targets from bottom aggro to top +}; + +struct MANGOS_DLL_DECL ScriptedAI : public CreatureAI +{ + ScriptedAI(Creature* creature) : m_creature(creature), InCombat(false) {} + ~ScriptedAI() {} + + //************* + //CreatureAI Functions + //************* + + //Called if IsVisible(Unit *who) is true at each *who move + void MoveInLineOfSight(Unit *); + + //Called at each attack of m_creature by any victim + void AttackStart(Unit *); + + //Called at stoping attack by any attacker + void EnterEvadeMode(); + + //Called at any heal cast/item used (call non implemented in mangos) + void HealBy(Unit *healer, uint32 amount_healed) {} + + // Called at any Damage to any victim (before damage apply) + void DamageDeal(Unit *done_to, uint32 &damage) {} + + // Called at any Damage from any attacker (before damage apply) + void DamageTaken(Unit *done_by, uint32 &damage) {} + + //Is unit visible for MoveInLineOfSight + bool IsVisible(Unit *who) const; + + //Called at World update tick + void UpdateAI(const uint32); + + //Called at creature death + void JustDied(Unit*){} + + //Called at creature killing another unit + void KilledUnit(Unit*){} + + // Called when the creature summon successfully other creature + void JustSummoned(Creature* ) {} + + // Called when a summoned creature is despawned + void SummonedCreatureDespawn(Creature* /*unit*/) {} + + // Called when hit by a spell + void SpellHit(Unit*, const SpellEntry*) {} + + // Called when creature is spawned or respawned (for reseting variables) + void JustRespawned(); + + //Called at waypoint reached or PointMovement end + void MovementInform(uint32, uint32){} + + //************* + // Variables + //************* + + //Pointer to creature we are manipulating + Creature* m_creature; + + //Bool for if we are in combat or not + bool InCombat; + + //************* + //Pure virtual functions + //************* + + //Called at creature reset either by death or evade + virtual void Reset() = 0; + + //Called at creature aggro either by MoveInLOS or Attack Start + virtual void Aggro(Unit*) = 0; + + //************* + //AI Helper Functions + //************* + + //Start attack of victim and go to him + void DoStartAttackAndMovement(Unit* victim, float distance = 0, float angle = 0); + + //Start attack on victim but do not move + void DoStartAttackNoMovement(Unit* victim); + + //Do melee swing of current victim if in rnage and ready and not casting + void DoMeleeAttackIfReady(); + + //Stop attack of current victim + void DoStopAttack(); + + //Cast spell by Id + void DoCast(Unit* victim, uint32 spellId, bool triggered = false); + + //Cast spell by spell info + void DoCastSpell(Unit* who,SpellEntry const *spellInfo, bool triggered = false); + + //Creature say + void DoSay(const char* text, uint32 language, Unit* target); + + //Creature Yell + void DoYell(const char* text, uint32 language, Unit* target); + + //Creature Text emote, optional bool for boss emote text + void DoTextEmote(const char* text, Unit* target, bool IsBossEmote = false); + + //Creature whisper, optional bool for boss whisper + void DoWhisper(const char* text, Unit* reciever, bool IsBossWhisper = false); + + //Plays a sound to all nearby players + void DoPlaySoundToSet(Unit* unit, uint32 sound); + + //Places the entire map into combat with creature + void DoZoneInCombat(Unit* pUnit = 0); + + //Drops all threat to 0%. Does not remove players from the threat list + void DoResetThreat(); + + //Teleports a player without dropping threat (only teleports to same map) + void DoTeleportPlayer(Unit* pUnit, float x, float y, float z, float o); + + //Returns friendly unit with the most amount of hp missing from max hp + Unit* DoSelectLowestHpFriendly(float range, uint32 MinHPDiff = 1); + + //Returns a list of friendly CC'd units within range + std::list DoFindFriendlyCC(float range); + + //Returns a list of all friendly units missing a specific buff within range + std::list DoFindFriendlyMissingBuff(float range, uint32 spellid); + + //Spawns a creature relative to m_creature + Creature* DoSpawnCreature(uint32 id, float x, float y, float z, float angle, uint32 type, uint32 despawntime); + + //Selects a unit from the creature's current aggro list + Unit* SelectUnit(SelectAggroTarget target, uint32 position); + + //Returns spells that meet the specified criteria from the creatures spell list + SpellEntry const* SelectSpell(Unit* Target, int32 School, int32 Mechanic, SelectTarget Targets, uint32 PowerCostMin, uint32 PowerCostMax, float RangeMin, float RangeMax, SelectEffect Effect); + + //Checks if you can cast the specified spell + bool CanCast(Unit* Target, SpellEntry const *Spell, bool Triggered = false); +}; + +struct MANGOS_DLL_DECL Scripted_NoMovementAI : public ScriptedAI +{ + Scripted_NoMovementAI(Creature* creature) : ScriptedAI(creature) {} + + //Called if IsVisible(Unit *who) is true at each *who move + void MoveInLineOfSight(Unit *); + + //Called at each attack of m_creature by any victim + void AttackStart(Unit *); +}; +#endif diff --git a/src/bindings/scripts/include/sc_gossip.h b/src/bindings/scripts/include/sc_gossip.h new file mode 100644 index 00000000000..af304a2d63f --- /dev/null +++ b/src/bindings/scripts/include/sc_gossip.h @@ -0,0 +1,183 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 +* This program is free software licensed under GPL version 2 +* Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef SC_PLAYER_H +#define SC_PLAYER_H + +#include "Player.h" +#include "GossipDef.h" +#include "QuestDef.h" + +// Gossip Item Text +#define GOSSIP_TEXT_BROWSE_GOODS "I'd like to browse your goods." +#define GOSSIP_TEXT_TRAIN "Train me!" + +#define GOSSIP_TEXT_BANK "The Bank" +#define GOSSIP_TEXT_WINDRIDER "Wind rider master" +#define GOSSIP_TEXT_GRYPHON "Gryphon Master" +#define GOSSIP_TEXT_BATHANDLER "Bat Handler" +#define GOSSIP_TEXT_HIPPOGRYPH "Hippogryph Master" +#define GOSSIP_TEXT_FLIGHTMASTER "Flight Master" +#define GOSSIP_TEXT_AUCTIONHOUSE "Auction House" +#define GOSSIP_TEXT_GUILDMASTER "Guild Master" +#define GOSSIP_TEXT_INN "The Inn" +#define GOSSIP_TEXT_MAILBOX "Mailbox" +#define GOSSIP_TEXT_STABLEMASTER "Stable Master" +#define GOSSIP_TEXT_WEAPONMASTER "Weapons Trainer" +#define GOSSIP_TEXT_BATTLEMASTER "Battlemaster" +#define GOSSIP_TEXT_CLASSTRAINER "Class Trainer" +#define GOSSIP_TEXT_PROFTRAINER "Profession Trainer" +#define GOSSIP_TEXT_OFFICERS "The officers` lounge" + +#define GOSSIP_TEXT_ALTERACVALLEY "Alterac Valley" +#define GOSSIP_TEXT_ARATHIBASIN "Arathi Basin" +#define GOSSIP_TEXT_WARSONGULCH "Warsong Gulch" +#define GOSSIP_TEXT_ARENA "Arena" +#define GOSSIP_TEXT_EYEOFTHESTORM "Eye of The Storm" + +#define GOSSIP_TEXT_DRUID "Druid" +#define GOSSIP_TEXT_HUNTER "Hunter" +#define GOSSIP_TEXT_PRIEST "Priest" +#define GOSSIP_TEXT_ROGUE "Rogue" +#define GOSSIP_TEXT_WARRIOR "Warrior" +#define GOSSIP_TEXT_PALADIN "Paladin" +#define GOSSIP_TEXT_SHAMAN "Shaman" +#define GOSSIP_TEXT_MAGE "Mage" +#define GOSSIP_TEXT_WARLOCK "Warlock" + +#define GOSSIP_TEXT_ALCHEMY "Alchemy" +#define GOSSIP_TEXT_BLACKSMITHING "Blacksmithing" +#define GOSSIP_TEXT_COOKING "Cooking" +#define GOSSIP_TEXT_ENCHANTING "Enchanting" +#define GOSSIP_TEXT_ENGINEERING "Engineering" +#define GOSSIP_TEXT_FIRSTAID "First Aid" +#define GOSSIP_TEXT_HERBALISM "Herbalism" +#define GOSSIP_TEXT_LEATHERWORKING "Leatherworking" +#define GOSSIP_TEXT_POISONS "Poisons" +#define GOSSIP_TEXT_TAILORING "Tailoring" +#define GOSSIP_TEXT_MINING "Mining" +#define GOSSIP_TEXT_FISHING "Fishing" +#define GOSSIP_TEXT_SKINNING "Skinning" +#define GOSSIP_TEXT_JEWELCRAFTING "Jewelcrafting" + +#define GOSSIP_TEXT_IRONFORGE_BANK "Bank of Ironforge" +#define GOSSIP_TEXT_STORMWIND_BANK "Bank of Stormwind" +#define GOSSIP_TEXT_DEEPRUNTRAM "Deeprun Tram" +#define GOSSIP_TEXT_ZEPPLINMASTER "Zeppelin master" +#define GOSSIP_TEXT_FERRY "Rut'theran Ferry" + +// Skill defines + +#define TRADESKILL_ALCHEMY 1 +#define TRADESKILL_BLACKSMITHING 2 +#define TRADESKILL_COOKING 3 +#define TRADESKILL_ENCHANTING 4 +#define TRADESKILL_ENGINEERING 5 +#define TRADESKILL_FIRSTAID 6 +#define TRADESKILL_HERBALISM 7 +#define TRADESKILL_LEATHERWORKING 8 +#define TRADESKILL_POISONS 9 +#define TRADESKILL_TAILORING 10 +#define TRADESKILL_MINING 11 +#define TRADESKILL_FISHING 12 +#define TRADESKILL_SKINNING 13 +#define TRADESKILL_JEWLCRAFTING 14 + +#define TRADESKILL_LEVEL_NONE 0 +#define TRADESKILL_LEVEL_APPRENTICE 1 +#define TRADESKILL_LEVEL_JOURNEYMAN 2 +#define TRADESKILL_LEVEL_EXPERT 3 +#define TRADESKILL_LEVEL_ARTISAN 4 +#define TRADESKILL_LEVEL_MASTER 5 + +// Gossip defines + +#define GOSSIP_ACTION_TRADE 1 +#define GOSSIP_ACTION_TRAIN 2 +#define GOSSIP_ACTION_TAXI 3 +#define GOSSIP_ACTION_GUILD 4 +#define GOSSIP_ACTION_BATTLE 5 +#define GOSSIP_ACTION_BANK 6 +#define GOSSIP_ACTION_INN 7 +#define GOSSIP_ACTION_HEAL 8 +#define GOSSIP_ACTION_TABARD 9 +#define GOSSIP_ACTION_AUCTION 10 +#define GOSSIP_ACTION_INN_INFO 11 +#define GOSSIP_ACTION_UNLEARN 12 +#define GOSSIP_ACTION_INFO_DEF 1000 + +#define GOSSIP_SENDER_MAIN 1 +#define GOSSIP_SENDER_INN_INFO 2 +#define GOSSIP_SENDER_INFO 3 +#define GOSSIP_SENDER_SEC_PROFTRAIN 4 +#define GOSSIP_SENDER_SEC_CLASSTRAIN 5 +#define GOSSIP_SENDER_SEC_BATTLEINFO 6 +#define GOSSIP_SENDER_SEC_BANK 7 +#define GOSSIP_SENDER_SEC_INN 8 +#define GOSSIP_SENDER_SEC_MAILBOX 9 +#define GOSSIP_SENDER_SEC_STABLEMASTER 10 + +#define DEFAULT_GOSSIP_MESSAGE 0xffffff + +extern uint32 GetSkillLevel(Player *player,uint32 skill); + +// Defined fuctions to use with player. + +// This fuction add's a menu item, +// a - Icon Id +// b - Text +// c - Sender(this is to identify the current Menu with this item) +// d - Action (identifys this Menu Item) +// e - Text to be displayed in pop up box +// f - Money value in pop up box +#define ADD_GOSSIP_ITEM(a,b,c,d) PlayerTalkClass->GetGossipMenu()->AddMenuItem(a,b,c,d,"",0) +#define ADD_GOSSIP_ITEM_EXTENDED(a,b,c,d,e,f) PlayerTalkClass->GetGossipMenu()->AddMenuItem(a,b,c,d,e,f) + +// This fuction Sends the current menu to show to client, a - NPCTEXTID(uint32) , b - npc guid(uint64) +#define SEND_GOSSIP_MENU(a,b) PlayerTalkClass->SendGossipMenu(a,b) + +// This fuction shows POI(point of interest) to client. +// a - position X +// b - position Y +// c - Icon Id +// d - Flags +// e - Data +// f - Location Name +#define SEND_POI(a,b,c,d,e,f) PlayerTalkClass->SendPointOfInterest(a,b,c,d,e,f) + +// Closes the Menu +#define CLOSE_GOSSIP_MENU() PlayerTalkClass->CloseGossip() + +// Fuction to tell to client the details +// a - quest object +// b - npc guid(uint64) +// c - Activate accept(bool) +#define SEND_QUEST_DETAILS(a,b,c) PlayerTalkClass->SendQuestDetails(a,b,c) + +// Fuction to tell to client the requested items to complete quest +// a - quest object +// b - npc guid(uint64) +// c - Iscompletable(bool) +// d - close at cancel(bool) - in case single incomplite ques +#define SEND_REQUESTEDITEMS(a,b,c,d) PlayerTalkClass->SendRequestedItems(a,b,c,d) + +// Fuctions to send NPC lists, a - is always the npc guid(uint64) +#define SEND_VENDORLIST(a) GetSession()->SendListInventory(a) +#define SEND_TRAINERLIST(a) GetSession()->SendTrainerList(a) +#define SEND_BANKERLIST(a) GetSession()->SendShowBank(a) +#define SEND_TABARDLIST(a) GetSession()->SendTabardVendorActivate(a) +#define SEND_AUCTIONLIST(a) GetSession()->SendAuctionHello(a) +#define SEND_TAXILIST(a) GetSession()->SendTaxiStatus(a) + +// Ressurect's the player if is dead. +#define SEND_SPRESURRECT() GetSession()->SendSpiritResurrect() + +// Get the player's honor rank. +#define GET_HONORRANK() GetHonorRank() +// ----------------------------------- + +// defined fuctions to use with Creature + +#define QUEST_DIALOG_STATUS(a,b,c) GetSession()->getDialogStatus(a,b,c) +#endif diff --git a/src/bindings/scripts/include/sc_grid_searchers.h b/src/bindings/scripts/include/sc_grid_searchers.h new file mode 100644 index 00000000000..750f1d42fbe --- /dev/null +++ b/src/bindings/scripts/include/sc_grid_searchers.h @@ -0,0 +1,131 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 +* This program is free software licensed under GPL version 2 +* Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef SC_GRIDSEARCH_H +#define SC_GRIDSEARCH_H + +#include "Unit.h" +#include "GameObject.h" + +#include "Cell.h" +#include "CellImpl.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" + +//Used in: +//sc_creature.cpp - DoSelectLowestHpFriendly() +class MostHPMissingInRange +{ +public: + MostHPMissingInRange(Unit const* obj, float range, uint32 hp) : i_obj(obj), i_range(range), i_hp(hp) {} + bool operator()(Unit* u) + { + if(u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && u->GetMaxHealth() - u->GetHealth() > i_hp) + { + i_hp = u->GetMaxHealth() - u->GetHealth(); + return true; + } + return false; + } +private: + Unit const* i_obj; + float i_range; + uint32 i_hp; +}; + +//Used in: +//sc_creature.cpp - DoFindFriendlyCC() +class FriendlyCCedInRange +{ +public: + FriendlyCCedInRange(Unit const* obj, float range) : i_obj(obj), i_range(range) {} + bool operator()(Unit* u) + { + if(u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && + (u->isFeared() || u->isCharmed() || u->isFrozen() || u->hasUnitState(UNIT_STAT_STUNDED) || u->hasUnitState(UNIT_STAT_STUNDED) || u->hasUnitState(UNIT_STAT_CONFUSED))) + { + return true; + } + return false; + } +private: + Unit const* i_obj; + float i_range; +}; + +//Used in: +//sc_creature.cpp - DoFindFriendlyMissingBuff() +class FriendlyMissingBuffInRange +{ +public: + FriendlyMissingBuffInRange(Unit const* obj, float range, uint32 spellid) : i_obj(obj), i_range(range), i_spell(spellid) {} + bool operator()(Unit* u) + { + if(u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && + !(u->HasAura(i_spell, 0) || u->HasAura(i_spell, 1) || u->HasAura(i_spell, 2))) + { + return true; + } + return false; + } +private: + Unit const* i_obj; + float i_range; + uint32 i_spell; +}; + +//Used in: +//hyjalAI.cpp +class AllFriendlyCreaturesInGrid +{ +public: + AllFriendlyCreaturesInGrid(Unit const* obj) : pUnit(obj) {} + bool operator() (Unit* u) + { + if(u->isAlive() && u->GetVisibility() == VISIBILITY_ON && u->IsFriendlyTo(pUnit)) + return true; + + return false; + } + +private: + Unit const* pUnit; +}; + +//Used in: +//hyjalAI.cpp +class AllGameObjectsWithEntryInGrid +{ +public: + AllGameObjectsWithEntryInGrid(uint32 ent) : entry(ent) {} + bool operator() (GameObject* g) + { + if(g->GetEntry() == entry) + return true; + + return false; + } +private: + uint32 entry; +}; + +class AllCreaturesOfEntryInRange +{ +public: + AllCreaturesOfEntryInRange(Unit const* obj, uint32 ent, float ran) : pUnit(obj), entry(ent), range(ran) {} + bool operator() (Unit* u) + { + if(u->GetEntry() == entry && pUnit->IsWithinDistInMap(u, range)) + return true; + + return false; + } + +private: + Unit const* pUnit; + uint32 entry; + float range; +}; + +#endif diff --git a/src/bindings/scripts/include/sc_instance.h b/src/bindings/scripts/include/sc_instance.h new file mode 100644 index 00000000000..f16590f2a83 --- /dev/null +++ b/src/bindings/scripts/include/sc_instance.h @@ -0,0 +1,48 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 +* This program is free software licensed under GPL version 2 +* Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef SC_INSTANCE_H +#define SC_INSTANCE_H + +#include "InstanceData.h" +#include "Map.h" + +enum EncounterState +{ + NOT_STARTED = 0, + IN_PROGRESS = 1, + FAIL = 2, + DONE = 3 +}; + +#define OUT_SAVE_INST_DATA debug_log("SD2: Saving Instance Data for Instance %s (Map %d, Instance Id %d)", instance->GetMapName(), instance->GetId(), instance->GetInstanceId()) +#define OUT_SAVE_INST_DATA_COMPLETE debug_log("SD2: Saving Instance Data for Instance %s (Map %d, Instance Id %d) completed.", instance->GetMapName(), instance->GetId(), instance->GetInstanceId()) +#define OUT_LOAD_INST_DATA(a) debug_log("SD2: Loading Instance Data for Instance %s (Map %d, Instance Id %d). Input is '%s'", instance->GetMapName(), instance->GetId(), instance->GetInstanceId(), a) +#define OUT_LOAD_INST_DATA_COMPLETE debug_log("SD2: Instance Data Load for Instance %s (Map %d, Instance Id: %d) is complete.",instance->GetMapName(), instance->GetId(), instance->GetInstanceId()) +#define OUT_LOAD_INST_DATA_FAIL error_log("SD2: Unable to load Instance Data for Instance %s (Map %d, Instance Id: %d).",instance->GetMapName(), instance->GetId(), instance->GetInstanceId()) + +class MANGOS_DLL_DECL ScriptedInstance : public InstanceData +{ + public: + + ScriptedInstance(Map *map) : InstanceData(map) {} + ~ScriptedInstance() {} + + //All-purpose data storage 64 bit + virtual uint64 GetData64(uint32) {return 0; } + virtual void SetData64(uint32, uint64) { } + + //All-purpose data storage 32 bit + virtual uint32 GetData(uint32) { return 0; } + virtual void SetData(uint32, uint32 data) {} + + // Called every instance update + virtual void Update(uint32) {} + + // Save and Load instance data to the database + const char* Save() { return NULL; } + void Load(const char* in) { } +}; + +#endif diff --git a/src/bindings/scripts/patches/MaNGOS-r4106-ScriptDev2.patch b/src/bindings/scripts/patches/MaNGOS-r4106-ScriptDev2.patch new file mode 100644 index 00000000000..a4165b87524 --- /dev/null +++ b/src/bindings/scripts/patches/MaNGOS-r4106-ScriptDev2.patch @@ -0,0 +1,40 @@ +Index: configure.ac +=================================================================== +--- configure.ac (revision 4106) ++++ configure.ac (working copy) +@@ -192,7 +192,9 @@ + src/mangosd/Makefile + src/mangosd/mangosd.conf + src/bindings/Makefile +- src/bindings/universal/Makefile ++ src/bindings/ScriptDev2/Makefile ++ src/bindings/ScriptDev2/sql/Makefile ++ src/bindings/ScriptDev2/sql/Updates/Makefile + ]) + + ## Disabled Makefiles, until they are ready for a successful make and +Index: src/bindings/Makefile.am +=================================================================== +--- src/bindings/Makefile.am (revision 4106) ++++ src/bindings/Makefile.am (working copy) +@@ -14,4 +14,4 @@ + # along with this program; if not, write to the Free Software + # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +-SUBDIRS = universal ++SUBDIRS = ScriptDev2 +Index: src/mangosd/Makefile.am +=================================================================== +--- src/mangosd/Makefile.am (revision 4106) ++++ src/mangosd/Makefile.am (working copy) +@@ -33,8 +33,8 @@ + WorldRunnable.h + + ## Link world daemon against the shared library +-mangos_worldd_LDADD = ../bindings/universal/libmangosscript.la ../game/libmangosgame.a ../shared/libmangosdatabase.a ../shared/libmangosconfig.a ../shared/libmangosauth.a ../shared/libmangosshared.a ../shared/libmangosvmaps.a ../shared/libmangosnetwork.a ../framework/libmangosframework.a ../../dep/src/zthread/libZThread.la ../../dep/src/g3dlite/libg3dlite.a +-mangos_worldd_LDFLAGS = -L../../dep/src/zthread -L../../dep/src/g3dlite -L../bindings/universal/ $(MYSQL_LIBS) -L$(libdir) $(ZLIB) $(COMPATLIB) $(SSLLIB) -export-dynamic ++mangos_worldd_LDADD = ../bindings/ScriptDev2/libmangosscript.la ../game/libmangosgame.a ../shared/libmangosdatabase.a ../shared/libmangosconfig.a ../shared/libmangosauth.a ../shared/libmangosshared.a ../shared/libmangosvmaps.a ../shared/libmangosnetwork.a ../framework/libmangosframework.a ../../dep/src/zthread/libZThread.la ../../dep/src/g3dlite/libg3dlite.a ++mangos_worldd_LDFLAGS = -L../../dep/src/zthread -L../../dep/src/g3dlite -L../bindings/ScriptDev2/ $(MYSQL_LIBS) -L$(libdir) $(ZLIB) $(COMPATLIB) $(SSLLIB) -export-dynamic + + ## Additional files to include when running 'make dist' + # Include world daemon configuration diff --git a/src/bindings/scripts/patches/MaNGOS-r4203-ScriptDev2.patch b/src/bindings/scripts/patches/MaNGOS-r4203-ScriptDev2.patch new file mode 100644 index 00000000000..383607f1ad1 --- /dev/null +++ b/src/bindings/scripts/patches/MaNGOS-r4203-ScriptDev2.patch @@ -0,0 +1,40 @@ +Index: configure.ac +=================================================================== +--- configure.ac (revision 4241) ++++ configure.ac (working copy) +@@ -223,7 +223,9 @@ + src/mangosd/Makefile + src/mangosd/mangosd.conf + src/bindings/Makefile +- src/bindings/universal/Makefile ++ src/bindings/ScriptDev2/Makefile ++ src/bindings/ScriptDev2/sql/Makefile ++ src/bindings/ScriptDev2/sql/Updates/Makefile + ]) + + ## Disabled Makefiles, until they are ready for a successful make and +Index: src/bindings/Makefile.am +=================================================================== +--- src/bindings/Makefile.am (revision 4241) ++++ src/bindings/Makefile.am (working copy) +@@ -14,4 +14,4 @@ + # along with this program; if not, write to the Free Software + # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +-SUBDIRS = universal ++SUBDIRS = ScriptDev2 +Index: src/mangosd/Makefile.am +=================================================================== +--- src/mangosd/Makefile.am (revision 4241) ++++ src/mangosd/Makefile.am (working copy) +@@ -33,8 +33,8 @@ + WorldRunnable.h + + ## Link world daemon against the shared library +-mangos_worldd_LDADD = ../bindings/universal/libmangosscript.la ../game/libmangosgame.a ../shared/libmangosdatabase.a ../shared/libmangosconfig.a ../shared/libmangosauth.a ../shared/libmangosshared.a ../shared/libmangosvmaps.a ../shared/libmangosnetwork.a ../framework/libmangosframework.a ../../dep/src/zthread/libZThread.la ../../dep/src/g3dlite/libg3dlite.a +-mangos_worldd_LDFLAGS = -L../../dep/src/zthread -L../../dep/src/g3dlite -L../bindings/universal/ $(MYSQL_LIBS) $(POSTGRE_LIBS) -L$(libdir) $(ZLIB) $(COMPATLIB) $(SSLLIB) -export-dynamic ++mangos_worldd_LDADD = ../bindings/ScriptDev2/libmangosscript.la ../game/libmangosgame.a ../shared/libmangosdatabase.a ../shared/libmangosconfig.a ../shared/libmangosauth.a ../shared/libmangosshared.a ../shared/libmangosvmaps.a ../shared/libmangosnetwork.a ../framework/libmangosframework.a ../../dep/src/zthread/libZThread.la ../../dep/src/g3dlite/libg3dlite.a ++mangos_worldd_LDFLAGS = -L../../dep/src/zthread -L../../dep/src/g3dlite -L../bindings/ScriptDev2/ $(MYSQL_LIBS) $(POSTGRE_LIBS) -L$(libdir) $(ZLIB) $(COMPATLIB) $(SSLLIB) -export-dynamic + + ## Additional files to include when running 'make dist' + # Include world daemon configuration diff --git a/src/bindings/scripts/patches/MaNGOS-r4241-ScriptDev2.patch b/src/bindings/scripts/patches/MaNGOS-r4241-ScriptDev2.patch new file mode 100644 index 00000000000..383607f1ad1 --- /dev/null +++ b/src/bindings/scripts/patches/MaNGOS-r4241-ScriptDev2.patch @@ -0,0 +1,40 @@ +Index: configure.ac +=================================================================== +--- configure.ac (revision 4241) ++++ configure.ac (working copy) +@@ -223,7 +223,9 @@ + src/mangosd/Makefile + src/mangosd/mangosd.conf + src/bindings/Makefile +- src/bindings/universal/Makefile ++ src/bindings/ScriptDev2/Makefile ++ src/bindings/ScriptDev2/sql/Makefile ++ src/bindings/ScriptDev2/sql/Updates/Makefile + ]) + + ## Disabled Makefiles, until they are ready for a successful make and +Index: src/bindings/Makefile.am +=================================================================== +--- src/bindings/Makefile.am (revision 4241) ++++ src/bindings/Makefile.am (working copy) +@@ -14,4 +14,4 @@ + # along with this program; if not, write to the Free Software + # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +-SUBDIRS = universal ++SUBDIRS = ScriptDev2 +Index: src/mangosd/Makefile.am +=================================================================== +--- src/mangosd/Makefile.am (revision 4241) ++++ src/mangosd/Makefile.am (working copy) +@@ -33,8 +33,8 @@ + WorldRunnable.h + + ## Link world daemon against the shared library +-mangos_worldd_LDADD = ../bindings/universal/libmangosscript.la ../game/libmangosgame.a ../shared/libmangosdatabase.a ../shared/libmangosconfig.a ../shared/libmangosauth.a ../shared/libmangosshared.a ../shared/libmangosvmaps.a ../shared/libmangosnetwork.a ../framework/libmangosframework.a ../../dep/src/zthread/libZThread.la ../../dep/src/g3dlite/libg3dlite.a +-mangos_worldd_LDFLAGS = -L../../dep/src/zthread -L../../dep/src/g3dlite -L../bindings/universal/ $(MYSQL_LIBS) $(POSTGRE_LIBS) -L$(libdir) $(ZLIB) $(COMPATLIB) $(SSLLIB) -export-dynamic ++mangos_worldd_LDADD = ../bindings/ScriptDev2/libmangosscript.la ../game/libmangosgame.a ../shared/libmangosdatabase.a ../shared/libmangosconfig.a ../shared/libmangosauth.a ../shared/libmangosshared.a ../shared/libmangosvmaps.a ../shared/libmangosnetwork.a ../framework/libmangosframework.a ../../dep/src/zthread/libZThread.la ../../dep/src/g3dlite/libg3dlite.a ++mangos_worldd_LDFLAGS = -L../../dep/src/zthread -L../../dep/src/g3dlite -L../bindings/ScriptDev2/ $(MYSQL_LIBS) $(POSTGRE_LIBS) -L$(libdir) $(ZLIB) $(COMPATLIB) $(SSLLIB) -export-dynamic + + ## Additional files to include when running 'make dist' + # Include world daemon configuration diff --git a/src/bindings/scripts/patches/MaNGOS-r4798-ScriptDev2.patch b/src/bindings/scripts/patches/MaNGOS-r4798-ScriptDev2.patch new file mode 100644 index 00000000000..cb08bdc8222 --- /dev/null +++ b/src/bindings/scripts/patches/MaNGOS-r4798-ScriptDev2.patch @@ -0,0 +1,40 @@ +Index: src/mangosd/Makefile.am +=================================================================== +--- src/mangosd/Makefile.am (revision 4799) ++++ src/mangosd/Makefile.am (working copy) +@@ -33,8 +33,8 @@ + WorldRunnable.h + + ## Link world daemon against the shared library +-mangos_worldd_LDADD = ../bindings/universal/libmangosscript.la ../game/libmangosgame.a ../shared/Database/libmangosdatabase.a ../shared/Config/libmangosconfig.a ../shared/Auth/libmangosauth.a ../shared/libmangosshared.a ../shared/vmap/libmangosvmaps.a ../shared/Network/libmangosnetwork.a ../framework/libmangosframework.a ../../dep/src/zthread/libZThread.la ../../dep/src/g3dlite/libg3dlite.a +-mangos_worldd_LDFLAGS = -L../../dep/src/zthread -L../../dep/src/g3dlite -L../bindings/universal/ $(MYSQL_LIBS) $(POSTGRE_LIBS) -L$(libdir) $(ZLIB) $(COMPATLIB) $(SSLLIB) -export-dynamic ++mangos_worldd_LDADD = ../bindings/ScriptDev2/libmangosscript.la ../game/libmangosgame.a ../shared/Database/libmangosdatabase.a ../shared/Config/libmangosconfig.a ../shared/Auth/libmangosauth.a ../shared/libmangosshared.a ../shared/vmap/libmangosvmaps.a ../shared/Network/libmangosnetwork.a ../framework/libmangosframework.a ../../dep/src/zthread/libZThread.la ../../dep/src/g3dlite/libg3dlite.a ++mangos_worldd_LDFLAGS = -L../../dep/src/zthread -L../../dep/src/g3dlite -L../bindings/ScriptDev2/ $(MYSQL_LIBS) $(POSTGRE_LIBS) -L$(libdir) $(ZLIB) $(COMPATLIB) $(SSLLIB) -export-dynamic + + ## Additional files to include when running 'make dist' + # Include world daemon configuration +Index: src/bindings/Makefile.am +=================================================================== +--- src/bindings/Makefile.am (revision 4799) ++++ src/bindings/Makefile.am (working copy) +@@ -14,4 +14,4 @@ + # along with this program; if not, write to the Free Software + # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +-SUBDIRS = universal ++SUBDIRS = ScriptDev2 +Index: configure.ac +=================================================================== +--- configure.ac (revision 4799) ++++ configure.ac (working copy) +@@ -228,7 +228,9 @@ + src/mangosd/Makefile + src/mangosd/mangosd.conf + src/bindings/Makefile +- src/bindings/universal/Makefile ++ src/bindings/ScriptDev2/Makefile ++ src/bindings/ScriptDev2/sql/Makefile ++ src/bindings/ScriptDev2/sql/Updates/Makefile + ]) + + ## Disabled Makefiles, until they are ready for a successful make and diff --git a/src/bindings/scripts/patches/MaNGOS-r5049-Scriptdev2.patch b/src/bindings/scripts/patches/MaNGOS-r5049-Scriptdev2.patch new file mode 100644 index 00000000000..6602ea80cb3 --- /dev/null +++ b/src/bindings/scripts/patches/MaNGOS-r5049-Scriptdev2.patch @@ -0,0 +1,42 @@ + +Index: src/mangosd/Makefile.am +=================================================================== +--- src/mangosd/Makefile.am (revision 5049) ++++ src/mangosd/Makefile.am (working copy) +@@ -33,8 +33,8 @@ + WorldRunnable.h + + ## Link world daemon against the shared library +-mangos_worldd_LDADD = ../bindings/universal/libmangosscript.la ../game/libmangosgame.a ../shared/Database/libmangosdatabase.a ../shared/Config/libmangosconfig.a ../shared/Auth/libmangosauth.a ../shared/libmangosshared.a ../shared/vmap/libmangosvmaps.a ../framework/libmangosframework.a ../../dep/src/sockets/libmangossockets.a ../../dep/src/zthread/libZThread.la ../../dep/src/g3dlite/libg3dlite.a +-mangos_worldd_LDFLAGS = -L../../dep/src/sockets -L../../dep/src/zthread -L../../dep/src/g3dlite -L../bindings/universal/ $(MYSQL_LIBS) $(POSTGRE_LIBS) -L$(libdir) $(ZLIB) $(COMPATLIB) $(SSLLIB) -export-dynamic ++mangos_worldd_LDADD = ../bindings/ScriptDev2/libmangosscript.la ../game/libmangosgame.a ../shared/Database/libmangosdatabase.a ../shared/Config/libmangosconfig.a ../shared/Auth/libmangosauth.a ../shared/libmangosshared.a ../shared/vmap/libmangosvmaps.a ../framework/libmangosframework.a ../../dep/src/sockets/libmangossockets.a ../../dep/src/zthread/libZThread.la ../../dep/src/g3dlite/libg3dlite.a ++mangos_worldd_LDFLAGS = -L../../dep/src/sockets -L../../dep/src/zthread -L../../dep/src/g3dlite -L../bindings/ScriptDev2/ $(MYSQL_LIBS) $(POSTGRE_LIBS) -L$(libdir) $(ZLIB) $(COMPATLIB) $(SSLLIB) -export-dynamic + + ## Additional files to include when running 'make dist' + # Include world daemon configuration +Index: src/bindings/Makefile.am +=================================================================== +--- src/bindings/Makefile.am (revision 5049) ++++ src/bindings/Makefile.am (working copy) +@@ -14,4 +14,4 @@ + # along with this program; if not, write to the Free Software + # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +-SUBDIRS = universal ++SUBDIRS = ScriptDev2 +Index: configure.ac +=================================================================== +--- configure.ac (revision 5049) ++++ configure.ac (working copy) +@@ -228,7 +228,10 @@ + src/mangosd/Makefile + src/mangosd/mangosd.conf + src/bindings/Makefile +- src/bindings/universal/Makefile ++ src/bindings/ScriptDev2/Makefile ++ src/bindings/ScriptDev2/config.h ++ src/bindings/ScriptDev2/sql/Makefile ++ src/bindings/ScriptDev2/sql/Updates/Makefile + ]) + + ## Disabled Makefiles, until they are ready for a successful make and diff --git a/src/bindings/scripts/patches/MaNGOS-r6491-Scriptdev2.patch b/src/bindings/scripts/patches/MaNGOS-r6491-Scriptdev2.patch new file mode 100644 index 00000000000..2e98e250b91 --- /dev/null +++ b/src/bindings/scripts/patches/MaNGOS-r6491-Scriptdev2.patch @@ -0,0 +1,41 @@ +Index: configure.ac +=================================================================== +--- configure.ac (revision 6491) ++++ configure.ac (working copy) +@@ -238,7 +238,10 @@ + src/mangosd/Makefile + src/mangosd/mangosd.conf + src/bindings/Makefile +- src/bindings/universal/Makefile ++ src/bindings/ScriptDev2/Makefile ++ src/bindings/ScriptDev2/config.h ++ src/bindings/ScriptDev2/sql/Makefile ++ src/bindings/ScriptDev2/sql/Updates/Makefile + ]) + + ## Disabled Makefiles, until they are ready for a successful make and +Index: src/bindings/Makefile.am +=================================================================== +--- src/bindings/Makefile.am (revision 6491) ++++ src/bindings/Makefile.am (working copy) +@@ -14,4 +14,4 @@ + # along with this program; if not, write to the Free Software + # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +-SUBDIRS = universal ++SUBDIRS = ScriptDev2 +Index: src/mangosd/Makefile.am +=================================================================== +--- src/mangosd/Makefile.am (revision 6491) ++++ src/mangosd/Makefile.am (working copy) +@@ -33,8 +33,8 @@ + WorldRunnable.h + + ## Link world daemon against the shared library +-mangos_worldd_LDADD = ../bindings/universal/libmangosscript.la ../game/libmangosgame.a ../shared/Database/libmangosdatabase.a ../shared/Config/libmangosconfig.a ../shared/Auth/libmangosauth.a ../shared/libmangosshared.a ../shared/vmap/libmangosvmaps.a ../framework/libmangosframework.a ../../dep/src/sockets/libmangossockets.a ../../dep/src/zthread/libZThread.la ../../dep/src/g3dlite/libg3dlite.a +-mangos_worldd_LDFLAGS = -L../../dep/src/sockets -L../../dep/src/zthread -L../../dep/src/g3dlite -L../bindings/universal/ $(MYSQL_LIBS) $(POSTGRE_LIBS) -L$(libdir) $(ZLIB) $(COMPATLIB) $(SSLLIB) -export-dynamic ++mangos_worldd_LDADD = ../bindings/ScriptDev2/libmangosscript.la ../game/libmangosgame.a ../shared/Database/libmangosdatabase.a ../shared/Config/libmangosconfig.a ../shared/Auth/libmangosauth.a ../shared/libmangosshared.a ../shared/vmap/libmangosvmaps.a ../framework/libmangosframework.a ../../dep/src/sockets/libmangossockets.a ../../dep/src/zthread/libZThread.la ../../dep/src/g3dlite/libg3dlite.a ++mangos_worldd_LDFLAGS = -L../../dep/src/sockets -L../../dep/src/zthread -L../../dep/src/g3dlite -L../bindings/ScriptDev2/ $(MYSQL_LIBS) $(POSTGRE_LIBS) -L$(libdir) $(ZLIB) $(COMPATLIB) $(SSLLIB) -export-dynamic + + ## Additional files to include when running 'make dist' + # Include world daemon configuration diff --git a/src/bindings/scripts/patches/MaNGOS-r6657-Scriptdev2.patch b/src/bindings/scripts/patches/MaNGOS-r6657-Scriptdev2.patch new file mode 100644 index 00000000000..8cd5cc63c0f --- /dev/null +++ b/src/bindings/scripts/patches/MaNGOS-r6657-Scriptdev2.patch @@ -0,0 +1,42 @@ +Index: src/mangosd/Makefile.am +=================================================================== +--- src/mangosd/Makefile.am (revision 6657) ++++ src/mangosd/Makefile.am (working copy) +@@ -33,8 +33,8 @@ + WorldRunnable.h + + ## Link world daemon against the shared library +-mangos_worldd_LDADD = ../bindings/universal/libmangosscript.la ../game/libmangosgame.a ../shared/Database/libmangosdatabase.a ../shared/Config/libmangosconfig.a ../shared/Auth/libmangosauth.a ../shared/libmangosshared.a ../shared/vmap/libmangosvmaps.a ../framework/libmangosframework.a ../../dep/src/sockets/libmangossockets.a ../../dep/src/zthread/libZThread.la ../../dep/src/g3dlite/libg3dlite.a +-mangos_worldd_LDFLAGS = -L../../dep/src/sockets -L../../dep/src/zthread -L../../dep/src/g3dlite -L../bindings/universal/ $(MYSQL_LIBS) $(POSTGRE_LIBS) -L$(libdir) $(ZLIB) $(COMPATLIB) $(SSLLIB) -export-dynamic ++mangos_worldd_LDADD = ../bindings/ScriptDev2/libmangosscript.la ../game/libmangosgame.a ../shared/Database/libmangosdatabase.a ../shared/Config/libmangosconfig.a ../shared/Auth/libmangosauth.a ../shared/libmangosshared.a ../shared/vmap/libmangosvmaps.a ../framework/libmangosframework.a ../../dep/src/sockets/libmangossockets.a ../../dep/src/zthread/libZThread.la ../../dep/src/g3dlite/libg3dlite.a ++mangos_worldd_LDFLAGS = -L../../dep/src/sockets -L../../dep/src/zthread -L../../dep/src/g3dlite -L../bindings/ScriptDev2/ $(MYSQL_LIBS) $(POSTGRE_LIBS) -L$(libdir) $(ZLIB) $(COMPATLIB) $(SSLLIB) -export-dynamic + + ## Additional files to include when running 'make dist' + # Include world daemon configuration +Index: src/bindings/Makefile.am +=================================================================== +--- src/bindings/Makefile.am (revision 6656) ++++ src/bindings/Makefile.am (working copy) +@@ -14,4 +14,4 @@ + # along with this program; if not, write to the Free Software + # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +-SUBDIRS = universal ++SUBDIRS = ScriptDev2 +Index: configure.ac +=================================================================== +--- configure.ac (revision 6657) ++++ configure.ac (working copy) +@@ -238,7 +238,11 @@ + src/mangosd/Makefile + src/mangosd/mangosd.conf.dist + src/bindings/Makefile +- src/bindings/universal/Makefile ++ src/bindings/ScriptDev2/Makefile ++ src/bindings/ScriptDev2/scriptdev2.conf.dist ++ src/bindings/ScriptDev2/config.h ++ src/bindings/ScriptDev2/sql/Makefile ++ src/bindings/ScriptDev2/sql/Updates/Makefile + ]) + + ## Disabled Makefiles, until they are ready for a successful make and diff --git a/src/bindings/scripts/scripts/areatrigger/areatrigger_scripts.cpp b/src/bindings/scripts/scripts/areatrigger/areatrigger_scripts.cpp new file mode 100644 index 00000000000..c62d7c33bed --- /dev/null +++ b/src/bindings/scripts/scripts/areatrigger/areatrigger_scripts.cpp @@ -0,0 +1,44 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Areatrigger_Scripts +SD%Complete: 100 +SDComment: Scripts for areatriggers +SDCategory: Areatrigger +EndScriptData */ + +/* ContentData +at_test script test only +EndContentData */ + +#include "precompiled.h" + +bool ATtest(Player *player, AreaTriggerEntry *at) +{ + player->Say("Hi!",LANG_UNIVERSAL); + return true; +} + +void AddSC_areatrigger_scripts() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="at_test"; + newscript->pAreaTrigger = ATtest; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/boss/boss_emeriss.cpp b/src/bindings/scripts/scripts/boss/boss_emeriss.cpp new file mode 100644 index 00000000000..0870be567c5 --- /dev/null +++ b/src/bindings/scripts/scripts/boss/boss_emeriss.cpp @@ -0,0 +1,156 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Emeriss +SD%Complete: 90 +SDComment: Teleport function & Mark of Nature missing +SDCategory: Bosses +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_SLEEP 24777 +#define SPELL_NOXIOUSBREATH 24818 +#define SPELL_TAILSWEEP 15847 +//#define SPELL_MARKOFNATURE 25040 // Not working +#define SPELL_VOLATILEINFECTION 24928 +#define SPELL_CORRUPTIONOFEARTH 24910 + +struct MANGOS_DLL_DECL boss_emerissAI : public ScriptedAI +{ + boss_emerissAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Sleep_Timer; + uint32 NoxiousBreath_Timer; + uint32 TailSweep_Timer; + //uint32 MarkOfNature_Timer; + uint32 VolatileInfection_Timer; + uint32 CorruptionofEarth1_Timer; + uint32 CorruptionofEarth2_Timer; + uint32 CorruptionofEarth3_Timer; + + void Reset() + { + Sleep_Timer = 15000 + rand()%5000; + NoxiousBreath_Timer = 8000; + TailSweep_Timer = 4000; + //MarkOfNature_Timer = 45000; + VolatileInfection_Timer = 12000; + CorruptionofEarth1_Timer = 0; + CorruptionofEarth2_Timer = 0; + CorruptionofEarth3_Timer = 0; + } + + void Aggro(Unit *who) {} + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //Sleep_Timer + if (Sleep_Timer < diff) + { + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target,SPELL_SLEEP); + + Sleep_Timer = 8000 + rand()%8000; + }else Sleep_Timer -= diff; + + //NoxiousBreath_Timer + if (NoxiousBreath_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_NOXIOUSBREATH); + NoxiousBreath_Timer = 14000 + rand()%6000; + }else NoxiousBreath_Timer -= diff; + + //Tailsweep every 2 seconds + if (TailSweep_Timer < diff) + { + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target,SPELL_TAILSWEEP); + + TailSweep_Timer = 2000; + }else TailSweep_Timer -= diff; + + //MarkOfNature_Timer + //if (MarkOfNature_Timer < diff) + //{ + // DoCast(m_creature->getVictim(),SPELL_MARKOFNATURE); + // MarkOfNature_Timer = 45000; + //}else MarkOfNature_Timer -= diff; + + //VolatileInfection_Timer + if (VolatileInfection_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_VOLATILEINFECTION); + VolatileInfection_Timer = 7000 + rand()%5000; + }else VolatileInfection_Timer -= diff; + + //CorruptionofEarth_Timer + if ( (int) (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() +0.5) == 75) + { + if (CorruptionofEarth1_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CORRUPTIONOFEARTH); + + //1 minutes for next one. Means not again with this health value + CorruptionofEarth1_Timer = 60000; + } else CorruptionofEarth1_Timer -= diff; + } + + //CorruptionofEarth_Timer + if ( (int) (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() +0.5) == 50) + { + if (CorruptionofEarth2_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CORRUPTIONOFEARTH); + + //1 minutes for next one. Means not again with this health value + CorruptionofEarth2_Timer = 60000; + } else CorruptionofEarth2_Timer -= diff; + } + + //CorruptionofEarth_Timer + if ( (int) (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() +0.5) == 25) + { + if (CorruptionofEarth3_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CORRUPTIONOFEARTH); + + //1 minutes for next one. Means not again with this health value + CorruptionofEarth3_Timer = 60000; + } else CorruptionofEarth3_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_emeriss(Creature *_Creature) +{ + return new boss_emerissAI (_Creature); +} + +void AddSC_boss_emeriss() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_emeriss"; + newscript->GetAI = GetAI_boss_emeriss; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/boss/boss_lethon.cpp b/src/bindings/scripts/scripts/boss/boss_lethon.cpp new file mode 100644 index 00000000000..66822e5a920 --- /dev/null +++ b/src/bindings/scripts/scripts/boss/boss_lethon.cpp @@ -0,0 +1,24 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Lethon +SD%Complete: 0 +SDComment: Place Holder +SDCategory: Bosses +EndScriptData */ + +#include "precompiled.h" diff --git a/src/bindings/scripts/scripts/boss/boss_taerar.cpp b/src/bindings/scripts/scripts/boss/boss_taerar.cpp new file mode 100644 index 00000000000..8c7f8471880 --- /dev/null +++ b/src/bindings/scripts/scripts/boss/boss_taerar.cpp @@ -0,0 +1,306 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Taerar +SD%Complete: 90 +SDComment: Mark of Nature & Teleport NYI +SDCategory: Bosses +EndScriptData */ + +#include "precompiled.h" + +//Spells of Taerar + +#define SPELL_SLEEP 24777 +#define SPELL_NOXIOUSBREATH 24818 +#define SPELL_TAILSWEEP 15847 +//#define SPELL_MARKOFNATURE 25040 // Not working +#define SPELL_ARCANEBLAST 24857 +#define SPELL_BELLOWINGROAR 22686 +#define SPELL_SUMMONSHADE 24843 + +//Spells of Shades of Taerar + +#define SPELL_POSIONCLOUD 24840 +#define SPELL_POSIONBREATH 20667 + +struct MANGOS_DLL_DECL boss_taerarAI : public ScriptedAI +{ + boss_taerarAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Sleep_Timer; + uint32 NoxiousBreath_Timer; + uint32 TailSweep_Timer; + //uint32 MarkOfNature_Timer; + uint32 ArcaneBlast_Timer; + uint32 BellowingRoar_Timer; + uint32 Shades_Timer; + uint32 Summon1_Timer; + uint32 Summon2_Timer; + uint32 Summon3_Timer; + int Rand; + int RandX; + int RandY; + Creature* Summoned; + bool Shades; + + void Reset() + { + Sleep_Timer = 15000 + rand()%5000; + NoxiousBreath_Timer = 8000; + TailSweep_Timer = 4000; + //MarkOfNature_Timer = 45000; + ArcaneBlast_Timer = 12000; + BellowingRoar_Timer = 30000; + Summon1_Timer = 0; + Summon2_Timer = 0; + Summon3_Timer = 0; + Shades_Timer = 60000; //The time that Taerar is banished + Shades = false; + } + + void Aggro(Unit *who) + { + } + + void SummonShades(Unit* victim) + { + Rand = rand()%15; + switch (rand()%2) + { + case 0: RandX = 0 - Rand; break; + case 1: RandX = 0 + Rand; break; + } + Rand = 0; + Rand = rand()%15; + switch (rand()%2) + { + case 0: RandY = 0 - Rand; break; + case 1: RandY = 0 + Rand; break; + } + Rand = 0; + Summoned = DoSpawnCreature(15302, RandX, RandY, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); + if(Summoned) + ((CreatureAI*)Summoned->AI())->AttackStart(victim); + } + + void UpdateAI(const uint32 diff) + { + if (Shades && Shades_Timer < diff) + { + //Become unbanished again + m_creature->setFaction(14); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + //m_creature->m_canMove = true; + Shades = false; + } else if (Shades) + { + Shades_Timer -= diff; + //Do nothing while banished + return; + } + + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //Sleep_Timer + if (Sleep_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) DoCast(target,SPELL_SLEEP); + + Sleep_Timer = 8000 + rand()%7000; + }else Sleep_Timer -= diff; + + //NoxiousBreath_Timer + if (NoxiousBreath_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_NOXIOUSBREATH); + NoxiousBreath_Timer = 14000 + rand()%6000; + } else NoxiousBreath_Timer -= diff; + + //Tailsweep every 2 seconds + if (TailSweep_Timer < diff) + { + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target,SPELL_TAILSWEEP); + + TailSweep_Timer = 2000; + }else TailSweep_Timer -= diff; + + //MarkOfNature_Timer + //if (MarkOfNature_Timer < diff) + //{ + // DoCast(m_creature->getVictim(),SPELL_MARKOFNATURE); + // MarkOfNature_Timer = 45000; + //}else MarkOfNature_Timer -= diff; + + //ArcaneBlast_Timer + if (ArcaneBlast_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_ARCANEBLAST); + ArcaneBlast_Timer = 7000 + rand()%5000; + }else ArcaneBlast_Timer -= diff; + + //BellowingRoar_Timer + if (BellowingRoar_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_BELLOWINGROAR); + BellowingRoar_Timer = 20000 + rand()%10000; + } else BellowingRoar_Timer -= diff; + + //Summon 3 Shades + if ( !Shades && (int) (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() +0.5) == 75) + { + if (Summon1_Timer < diff) + { + //Inturrupt any spell casting + m_creature->InterruptNonMeleeSpells(false); + m_creature->setFaction(35); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + //m_creature->m_canMove = false; + + //Cast + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + SummonShades(target); + SummonShades(target); + SummonShades(target); + Summon1_Timer = 120000; + Shades = true; + Shades_Timer = 60000; + } else Summon1_Timer -= diff; + } + + //Summon 3 Shades + if ( !Shades && (int) (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() +0.5) == 50) + { + if (Summon2_Timer < diff) + { + //Inturrupt any spell casting + m_creature->InterruptNonMeleeSpells(false); + m_creature->setFaction(35); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + //m_creature->m_canMove = false; + + //Cast + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + SummonShades(target); + SummonShades(target); + SummonShades(target); + Summon2_Timer = 120000; + Shades = true; + Shades_Timer = 60000; + } else Summon2_Timer -= diff; + } + + //Summon 3 Shades + if ( !Shades && (int) (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() +0.5) == 25) + { + if (Summon3_Timer < diff) + { + //Inturrupt any spell casting + m_creature->InterruptNonMeleeSpells(false); + m_creature->setFaction(35); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + //m_creature->m_canMove = false; + + //Cast + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + SummonShades(target); + SummonShades(target); + SummonShades(target); + Summon3_Timer = 120000; + Shades = true; + Shades_Timer = 60000; + } else Summon3_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +// Shades of Taerar Script + +struct MANGOS_DLL_DECL boss_shadeoftaerarAI : public ScriptedAI +{ + boss_shadeoftaerarAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 PoisonCloud_Timer; + uint32 PosionBreath_Timer; + + void Reset() + { + PoisonCloud_Timer = 8000; + PosionBreath_Timer = 12000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //PoisonCloud_Timer + if (PoisonCloud_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_POSIONCLOUD); + PoisonCloud_Timer = 30000; + }else PoisonCloud_Timer -= diff; + + //PosionBreath_Timer + if (PosionBreath_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_POSIONBREATH); + PosionBreath_Timer = 12000; + }else PosionBreath_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_taerar(Creature *_Creature) +{ + return new boss_taerarAI (_Creature); +} + +CreatureAI* GetAI_boss_shadeoftaerar(Creature *_Creature) +{ + return new boss_shadeoftaerarAI (_Creature); +} + +void AddSC_boss_taerar() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_taerar"; + newscript->GetAI = GetAI_boss_taerar; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_shade_of_taerar"; + newscript->GetAI = GetAI_boss_shadeoftaerar; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/boss/boss_ysondre.cpp b/src/bindings/scripts/scripts/boss/boss_ysondre.cpp new file mode 100644 index 00000000000..a5348630af2 --- /dev/null +++ b/src/bindings/scripts/scripts/boss/boss_ysondre.cpp @@ -0,0 +1,246 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Ysondre +SD%Complete: 90 +SDComment: Mark of Nature & Teleport missing +SDCategory: Bosses +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_SLEEP 24777 +#define SPELL_NOXIOUSBREATH 24818 +#define SPELL_TAILSWEEP 15847 +//#define SPELL_MARKOFNATURE 25040 // Not working +#define SPELL_LIGHTNINGWAVE 24819 +#define SPELL_SUMMONDRUIDS 24795 + +//druid spells +#define SPELL_MOONFIRE 21669 + +// Ysondre script +struct MANGOS_DLL_DECL boss_ysondreAI : public ScriptedAI +{ + boss_ysondreAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Sleep_Timer; + uint32 NoxiousBreath_Timer; + uint32 TailSweep_Timer; + //uint32 MarkOfNature_Timer; + uint32 LightningWave_Timer; + uint32 SummonDruids1_Timer; + uint32 SummonDruids2_Timer; + uint32 SummonDruids3_Timer; + int Rand; + int RandX; + int RandY; + Creature* Summoned; + + void Reset() + { + Sleep_Timer = 15000 + rand()%5000; + NoxiousBreath_Timer = 8000; + TailSweep_Timer = 4000; + //MarkOfNature_Timer = 45000; + LightningWave_Timer = 12000; + SummonDruids1_Timer = 0; + SummonDruids2_Timer = 0; + SummonDruids3_Timer = 0; + } + + void Aggro(Unit *who) + { + } + + void SummonDruids(Unit* victim) + { + Rand = rand()%10; + switch (rand()%2) + { + case 0: RandX = 0 - Rand; break; + case 1: RandX = 0 + Rand; break; + } + Rand = 0; + Rand = rand()%10; + switch (rand()%2) + { + case 0: RandY = 0 - Rand; break; + case 1: RandY = 0 + Rand; break; + } + Rand = 0; + Summoned = DoSpawnCreature(15260, RandX, RandY, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); + if(Summoned) + ((CreatureAI*)Summoned->AI())->AttackStart(victim); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //Sleep_Timer + if (Sleep_Timer < diff) + { + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target,SPELL_SLEEP); + + Sleep_Timer = 8000 + rand()%7000; + }else Sleep_Timer -= diff; + + //NoxiousBreath_Timer + if (NoxiousBreath_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_NOXIOUSBREATH); + NoxiousBreath_Timer = 14000 + rand()%6000; + }else NoxiousBreath_Timer -= diff; + + //Tailsweep every 2 seconds + if (TailSweep_Timer < diff) + { + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target,SPELL_TAILSWEEP); + + TailSweep_Timer = 2000; + }else TailSweep_Timer -= diff; + + //MarkOfNature_Timer + //if (MarkOfNature_Timer < diff) + //{ + // DoCast(m_creature->getVictim(),SPELL_MARKOFNATURE); + // MarkOfNature_Timer = 45000; + //}else MarkOfNature_Timer -= diff; + + //LightningWave_Timer + if (LightningWave_Timer < diff) + { + //Cast LIGHTNINGWAVE on a Random target + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target,SPELL_LIGHTNINGWAVE); + + LightningWave_Timer = 7000 + rand()%5000; + }else LightningWave_Timer -= diff; + + //Summon Druids + if ( (int) (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() +0.5) == 75) + { + if (SummonDruids1_Timer < diff) + { + // summon 10 druids + Unit* target = NULL; + for(int i = 0; i < 10;i++) + { + target = SelectUnit(SELECT_TARGET_RANDOM,0); + SummonDruids(target); + } + + SummonDruids1_Timer = 60000; + } else SummonDruids1_Timer -= diff; + } + + //Summon Druids + if ( (int) (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() +0.5) == 50) + { + if (SummonDruids2_Timer < diff) + { + // summon 10 druids + Unit* target = NULL; + for(int i = 0; i < 10;i++) + { + target = SelectUnit(SELECT_TARGET_RANDOM,0); + SummonDruids(target); + } + + SummonDruids2_Timer = 60000; + } else SummonDruids2_Timer -= diff; + } + + //Summon Druids + if ( (int) (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() +0.5) == 25) + { + if (SummonDruids3_Timer < diff) + { + // summon 10 druids + Unit* target = NULL; + for(int i = 0; i < 10;i++) + { + target = SelectUnit(SELECT_TARGET_RANDOM,0); + SummonDruids(target); + } + + SummonDruids3_Timer = 60000; + } else SummonDruids3_Timer -= diff; + } + DoMeleeAttackIfReady(); + } +}; +// Summoned druid script +struct MANGOS_DLL_DECL mob_dementeddruidsAI : public ScriptedAI +{ + mob_dementeddruidsAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 MoonFire_Timer; + + void Reset() + { + MoonFire_Timer = 3000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //MoonFire_Timer + if (MoonFire_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_MOONFIRE); + MoonFire_Timer = 5000; + }else MoonFire_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_ysondre(Creature *_Creature) +{ + return new boss_ysondreAI (_Creature); +} + +CreatureAI* GetAI_mob_dementeddruids(Creature *_Creature) +{ + return new mob_dementeddruidsAI (_Creature); +} + +void AddSC_boss_ysondre() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_ysondre"; + newscript->GetAI = GetAI_boss_ysondre; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_dementeddruids"; + newscript->GetAI = GetAI_mob_dementeddruids; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/creature/mob_event_ai.cpp b/src/bindings/scripts/scripts/creature/mob_event_ai.cpp new file mode 100644 index 00000000000..f86931df766 --- /dev/null +++ b/src/bindings/scripts/scripts/creature/mob_event_ai.cpp @@ -0,0 +1,1389 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Mob_Event_AI +SD%Complete: 90 +SDComment: Database Event AI +SDCategory: Creatures +EndScriptData */ + +#include "precompiled.h" +#include "mob_event_ai.h" + +#define EVENT_UPDATE_TIME 500 +#define SPELL_RUN_AWAY 8225 + +struct EventHolder +{ + EventHolder(EventAI_Event p) : Event(p), Time(0), Enabled(true){} + + EventAI_Event Event; + uint32 Time; + bool Enabled; +}; + +struct MANGOS_DLL_DECL Mob_EventAI : public ScriptedAI +{ + Mob_EventAI(Creature *c, std::list pEventList) : ScriptedAI(c) + { + EventList = pEventList; + Phase = 0; + CombatMovementEnabled = true; + MeleeEnabled = true; + AttackDistance = 0; + AttackAngle = 0.0f; + + //Handle Spawned Events + for (std::list::iterator i = EventList.begin(); i != EventList.end(); ++i) + { + switch ((*i).Event.event_type) + { + case EVENT_T_SPAWNED: + ProcessEvent(*i); + break; + } + } + + Reset(); + } + + ~Mob_EventAI() + { + EventList.clear(); + } + + //Variables used by EventAI for handling events + std::list EventList; //Holder for events (stores enabled, time, and eventid) + uint32 EventUpdateTime; //Time between event updates + uint32 EventDiff; //Time between the last event call + + //Variables used by Events themselves + uint8 Phase; //Current phase, max 32 phases + bool CombatMovementEnabled; //If we allow targeted movment gen (movement twoards top threat) + bool MeleeEnabled; //If we allow melee auto attack + uint32 AttackDistance; //Distance to attack from + float AttackAngle; //Angle of attack + + void AttackTarget(Unit* pTarget, bool Follow) + { + if (!pTarget) + return; + + if ( m_creature->Attack(pTarget, true) ) + { + if (Follow) + { + m_creature->GetMotionMaster()->Clear(false); + m_creature->GetMotionMaster()->MoveChase(pTarget, AttackDistance, AttackAngle); + } + + m_creature->AddThreat(pTarget, 0.0f); + } + } + + bool ProcessEvent(EventHolder& pHolder, Unit* pActionInvoker = NULL) + { + if (!pHolder.Enabled || pHolder.Time) + return false; + + //Check the inverse phase mask (event doesn't trigger if current phase bit is set in mask) + if (pHolder.Event.event_inverse_phase_mask & (1 << Phase)) + return false; + + //Store random here so that all random actions match up + uint32 rnd = rand(); + + //Return if chance for event is not met + if (pHolder.Event.event_chance <= rnd % 100) + return false; + + union + { + uint32 param1; + int32 param1_s; + }; + + union + { + uint32 param2; + int32 param2_s; + }; + + union + { + uint32 param3; + int32 param3_s; + }; + + union + { + uint32 param4; + int32 param4_s; + }; + + param1 = pHolder.Event.event_param1; + param2 = pHolder.Event.event_param2; + param3 = pHolder.Event.event_param3; + param4 = pHolder.Event.event_param4; + + //Check event conditions based on the event type, also reset events + switch (pHolder.Event.event_type) + { + case EVENT_T_TIMER: + { + if (!InCombat) + return false; + + //Repeat Timers + if (param3 == param4) + { + pHolder.Time = param3; + + }else if (param4 > param3) + pHolder.Time = urand(param3, param4); + else + { + if (EAI_ErrorLevel > 0) + error_db_log("SD2: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); + pHolder.Enabled = false; + } + } + break; + case EVENT_T_TIMER_OOC: + { + if (InCombat) + return false; + + //Repeat Timers + if (param3 == param4) + { + pHolder.Time = param3; + + }else if (param4 > param3) + pHolder.Time = urand(param3, param4); + else + { + if (EAI_ErrorLevel > 0) + error_db_log("SD2: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); + pHolder.Enabled = false; + } + } + break; + case EVENT_T_HP: + { + if (!InCombat || !m_creature->GetMaxHealth()) + return false; + + uint32 perc = (m_creature->GetHealth()*100) / m_creature->GetMaxHealth(); + + if (perc > param1 || perc < param2) + return false; + + //Repeat Timers + if (param3 == param4) + { + pHolder.Time = param3; + + }else if (param4 > param3) + pHolder.Time = urand(param3, param4); + else + { + if (EAI_ErrorLevel > 0) + error_db_log("SD2: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); + pHolder.Enabled = false; + } + } + break; + case EVENT_T_MANA: + { + if (!InCombat || !m_creature->GetMaxPower(POWER_MANA)) + return false; + + uint32 perc = (m_creature->GetPower(POWER_MANA)*100) / m_creature->GetMaxPower(POWER_MANA); + + if (perc > param1 || perc < param2) + return false; + + //Repeat Timers + if (param3 == param4) + { + pHolder.Time = param3; + + }else if (param4 > param3) + pHolder.Time = urand(param3, param4); + else + { + if (EAI_ErrorLevel > 0) + error_db_log("SD2: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); + pHolder.Enabled = false; + } + } + break; + case EVENT_T_AGGRO: + { + } + break; + case EVENT_T_KILL: + { + //Repeat Timers + if (param1 == param2) + { + pHolder.Time = param1; + + }else if (param2 > param1) + pHolder.Time = urand(param1, param2); + else + { + if (EAI_ErrorLevel > 0) + error_db_log("SD2: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); + pHolder.Enabled = false; + } + } + case EVENT_T_DEATH: + { + } + break; + case EVENT_T_EVADE: + { + } + break; + case EVENT_T_SPELLHIT: + { + //Spell hit is special case, param1 and param2 handled within EventAI::SpellHit + + //Repeat Timers + if (param3 == param4) + { + pHolder.Time = param3; + + }else if (param4 > param3) + pHolder.Time = urand(param3, param4); + else + { + if (EAI_ErrorLevel > 0) + error_db_log("SD2: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); + pHolder.Enabled = false; + } + } + break; + case EVENT_T_RANGE: + { + //Repeat Timers + if (param3 == param4) + { + pHolder.Time = param3; + + }else if (param4 > param3) + pHolder.Time = urand(param3, param4); + else + { + if (EAI_ErrorLevel > 0) + error_db_log("SD2: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); + pHolder.Enabled = false; + } + } + break; + case EVENT_T_OOC_LOS: + { + //Repeat Timers + if (param3 == param4) + { + pHolder.Time = param3; + + }else if (param4 > param3) + pHolder.Time = urand(param3, param4); + else + { + if (EAI_ErrorLevel > 0) + error_db_log("SD2: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); + pHolder.Enabled = false; + } + } + break; + case EVENT_T_SPAWNED: + { + } + break; + case EVENT_T_TARGET_HP: + { + if (!InCombat || !m_creature->getVictim() || !m_creature->getVictim()->GetMaxHealth()) + return false; + + uint32 perc = (m_creature->getVictim()->GetHealth()*100) / m_creature->getVictim()->GetMaxHealth(); + + if (perc > param1 || perc < param2) + return false; + + //Repeat Timers + if (param3 == param4) + { + pHolder.Time = param3; + + }else if (param4 > param3) + pHolder.Time = urand(param3, param4); + else + { + if (EAI_ErrorLevel > 0) + error_db_log("SD2: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); + pHolder.Enabled = false; + } + } + break; + case EVENT_T_TARGET_CASTING: + { + if (!InCombat || !m_creature->getVictim() || !m_creature->getVictim()->IsNonMeleeSpellCasted(false, false, true)) + return false; + + //Repeat Timers + if (param1 == param2) + { + pHolder.Time = param1; + + }else if (param2 > param1) + pHolder.Time = urand(param1, param2); + else + { + if (EAI_ErrorLevel > 0) + error_db_log("SD2: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); + pHolder.Enabled = false; + } + } + break; + case EVENT_T_FRIENDLY_HP: + { + if (!InCombat) + return false; + + Unit* pUnit = DoSelectLowestHpFriendly(param2, param1); + + if (!pUnit) + return false; + + pActionInvoker = pUnit; + + //Repeat Timers + if (param3 == param4) + { + pHolder.Time = param3; + + }else if (param4 > param3) + pHolder.Time = urand(param3, param4); + else + { + if (EAI_ErrorLevel > 0) + error_db_log("SD2: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); + pHolder.Enabled = false; + } + } + break; + + case EVENT_T_FRIENDLY_IS_CC: + { + if (!InCombat) + return false; + + std::list pList = DoFindFriendlyCC(param2); + + //List is empty + if (pList.empty()) + return false; + + //We don't really care about the whole list, just return first available + pActionInvoker = *(pList.begin()); + + //Repeat Timers + if (param3 == param4) + { + pHolder.Time = param3; + + }else if (param4 > param3) + pHolder.Time = urand(param3, param4); + else + { + if (EAI_ErrorLevel > 0) + error_db_log("SD2: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); + pHolder.Enabled = false; + } + } + break; + + case EVENT_T_FRIENDLY_MISSING_BUFF: + { + std::list pList = DoFindFriendlyMissingBuff(param2, param1); + + //List is empty + if (pList.empty()) + return false; + + //We don't really care about the whole list, just return first available + pActionInvoker = *(pList.begin()); + + //Repeat Timers + if (param3 == param4) + { + pHolder.Time = param3; + + }else if (param4 > param3) + pHolder.Time = urand(param3, param4); + else + { + if (EAI_ErrorLevel > 0) + error_db_log("SD2: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); + pHolder.Enabled = false; + } + } + break; + + case EVENT_T_SUMMONED_UNIT: + { + //Prevent event from occuring on no unit or non creatures + if (!pActionInvoker || pActionInvoker->GetTypeId()!=TYPEID_UNIT) + return false; + + //Creature id doesn't match up + if (param1 && ((Creature*)pActionInvoker)->GetEntry() != param1) + return false; + + //Repeat Timers + if (param2 == param3) + { + pHolder.Time = param2; + + }else if (param3 > param2) + pHolder.Time = urand(param2, param3); + else + { + if (EAI_ErrorLevel > 0) + error_db_log("SD2: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); + pHolder.Enabled = false; + } + } + break; + default: + if (EAI_ErrorLevel > 0) + error_db_log("SD2: Creature %u using Event %u has invalid Event Type(%u), missing from ProcessEvent() Switch.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); + break; + } + + //Disable non-repeatable events + if (!(pHolder.Event.event_flags & EFLAG_REPEATABLE)) + pHolder.Enabled = false; + + //Process actions + for (uint32 j = 0; j < MAX_ACTIONS; j++) + ProcessAction(pHolder.Event.action[j].type, pHolder.Event.action[j].param1, pHolder.Event.action[j].param2, pHolder.Event.action[j].param3, rnd, pHolder.Event.event_id, pActionInvoker); + + return true; + } + + inline uint32 GetRandActionParam(uint32 rnd, uint32 param1, uint32 param2, uint32 param3) + { + switch (rnd % 3) + { + case 0: + return param1; + break; + + case 1: + return param2; + break; + + case 2: + return param3; + break; + } + return 0; + } + + inline Unit* GetTargetByType(uint32 Target, Unit* pActionInvoker) + { + switch (Target) + { + case TARGET_T_SELF: + return m_creature; + break; + case TARGET_T_HOSTILE: + return m_creature->getVictim(); + break; + case TARGET_T_HOSTILE_SECOND_AGGRO: + return SelectUnit(SELECT_TARGET_TOPAGGRO,1); + break; + case TARGET_T_HOSTILE_LAST_AGGRO: + return SelectUnit(SELECT_TARGET_BOTTOMAGGRO,0); + break; + case TARGET_T_HOSTILE_RANDOM: + return SelectUnit(SELECT_TARGET_RANDOM,0); + break; + case TARGET_T_HOSTILE_RANDOM_NOT_TOP: + return SelectUnit(SELECT_TARGET_RANDOM,1); + break; + case TARGET_T_ACTION_INVOKER: + return pActionInvoker; + break; + default: + return NULL; + break; + }; + } + + void ProcessAction(uint16 type, uint32 param1, uint32 param2, uint32 param3, uint32 rnd, uint32 EventId, Unit* pActionInvoker) + { + switch (type) + { + case ACTION_T_SAY: + DoSay(GetEventAIText(param1), LANG_UNIVERSAL, pActionInvoker ? pActionInvoker : m_creature->getVictim()); + break; + + case ACTION_T_YELL: + DoYell(GetEventAIText(param1), LANG_UNIVERSAL, pActionInvoker ? pActionInvoker : m_creature->getVictim()); + break; + + case ACTION_T_TEXTEMOTE: + DoTextEmote(GetEventAIText(param1), pActionInvoker ? pActionInvoker : m_creature->getVictim()); + break; + + case ACTION_T_SOUND: + DoPlaySoundToSet(m_creature, param1); + break; + + case ACTION_T_EMOTE: + m_creature->HandleEmoteCommand(param1); + break; + + case ACTION_T_RANDOM_SAY: + { + uint32 temp = GetRandActionParam(rnd, param1, param2, param3); + + if (temp != 0xffffffff) + DoSay(GetEventAIText(temp), LANG_UNIVERSAL, pActionInvoker ? pActionInvoker : m_creature->getVictim()); + } + break; + + case ACTION_T_RANDOM_YELL: + { + uint32 temp = GetRandActionParam(rnd, param1, param2, param3); + + if (temp != 0xffffffff) + DoYell(GetEventAIText(temp), LANG_UNIVERSAL, pActionInvoker ? pActionInvoker : m_creature->getVictim()); + } + break; + + case ACTION_T_RANDOM_TEXTEMOTE: + { + uint32 temp = GetRandActionParam(rnd, param1, param2, param3); + + if (temp != 0xffffffff) + DoTextEmote(GetEventAIText(temp), pActionInvoker ? pActionInvoker : m_creature->getVictim()); + } + break; + + case ACTION_T_RANDOM_SOUND: + { + uint32 temp = GetRandActionParam(rnd, param1, param2, param3); + + if (temp != 0xffffffff) + DoPlaySoundToSet(m_creature, temp); + } + break; + + case ACTION_T_RANDOM_EMOTE: + { + uint32 temp = GetRandActionParam(rnd, param1, param2, param3); + + if (temp != 0xffffffff) + m_creature->HandleEmoteCommand(temp); + } + break; + + case ACTION_T_CAST: + { + Unit* target = GetTargetByType(param2, pActionInvoker); + Unit* caster = m_creature; + + if (!target) + return; + + //Cast is always triggered if target is forced to cast on self + if (param3 & CAST_FORCE_TARGET_SELF) + { + param3 |= CAST_TRIGGERED; + caster = target; + } + + //Interrupt any previous spell + if (caster->IsNonMeleeSpellCasted(false) && param3 & CAST_INTURRUPT_PREVIOUS) + caster->InterruptNonMeleeSpells(false); + + //Cast only if not casting or if spell is triggered + if (param3 & CAST_TRIGGERED || !caster->IsNonMeleeSpellCasted(false)) + { + const SpellEntry* tSpell = GetSpellStore()->LookupEntry(param1); + + //Verify that spell exists + if (tSpell) + { + //Check if cannot cast spell + if (!(param3 & (CAST_FORCE_TARGET_SELF | CAST_FORCE_CAST)) && + !CanCast(target, tSpell, (param3 & CAST_TRIGGERED))) + { + //Melee current victim if flag not set + if (!(param3 & CAST_NO_MELEE_IF_OOM)) + { + AttackDistance = 0; + AttackAngle = 0; + + m_creature->GetMotionMaster()->Clear(false); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim(), AttackDistance, AttackAngle); + } + + }else caster->CastSpell(target, param1, (param3 & CAST_TRIGGERED)); + + }else if (EAI_ErrorLevel > 0) + error_db_log("SD2: EventAI event %d creature %d attempt to cast spell that doesn't exist %d", EventId, m_creature->GetEntry(), param1); + } + } + break; + + case ACTION_T_SUMMON: + { + Unit* target = GetTargetByType(param2, pActionInvoker); + + Creature* pCreature = NULL; + + if (param3) + pCreature = DoSpawnCreature(param1, 0, 0, 0, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, param3); + else pCreature = pCreature = DoSpawnCreature(param1, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); + + if (!pCreature) + { + if (EAI_ErrorLevel > 0) + error_db_log( "SD2: EventAI failed to spawn creature %u. Spawn event %d is on creature %d", param1, EventId, m_creature->GetEntry()); + } + else if (param2 != TARGET_T_SELF && target) + pCreature->AI()->AttackStart(target); + } + break; + + case ACTION_T_THREAT_SINGLE_PCT: + { + Unit* target = GetTargetByType(param2, pActionInvoker); + + if (target) + m_creature->getThreatManager().modifyThreatPercent(target, param1); + } + break; + + case ACTION_T_THREAT_ALL_PCT: + { + Unit* Temp = NULL; + + std::list::iterator i = m_creature->getThreatManager().getThreatList().begin(); + for (; i != m_creature->getThreatManager().getThreatList().end(); ++i) + { + Temp = Unit::GetUnit((*m_creature),(*i)->getUnitGuid()); + if (Temp) + m_creature->getThreatManager().modifyThreatPercent(Temp, param1); + } + } + break; + + case ACTION_T_QUEST_EVENT: + { + Unit* target = GetTargetByType(param2, pActionInvoker); + + if (target && target->GetTypeId() == TYPEID_PLAYER) + ((Player*)target)->AreaExploredOrEventHappens(param1); + } + break; + + case ACTION_T_CASTCREATUREGO: + { + Unit* target = GetTargetByType(param3, pActionInvoker); + + if (target && target->GetTypeId() == TYPEID_PLAYER) + ((Player*)target)->CastedCreatureOrGO(param1, m_creature->GetGUID(), param2); + } + break; + + case ACTION_T_SET_UNIT_FIELD: + { + Unit* target = GetTargetByType(param3, pActionInvoker); + + if (target) + target->SetUInt32Value(param1, param2); + } + break; + + case ACTION_T_SET_UNIT_FLAG: + { + Unit* target = GetTargetByType(param2, pActionInvoker); + + if (target) + target->SetFlag(UNIT_FIELD_FLAGS, param1); + } + break; + + case ACTION_T_REMOVE_UNIT_FLAG: + { + Unit* target = GetTargetByType(param2, pActionInvoker); + + if (target) + target->RemoveFlag(UNIT_FIELD_FLAGS, param1); + } + break; + + case ACTION_T_AUTO_ATTACK: + { + if (param1) + MeleeEnabled = true; + else MeleeEnabled = false; + } + break; + + case ACTION_T_COMBAT_MOVEMENT: + { + CombatMovementEnabled = param1; + + //Allow movement (create new targeted movement gen if none exist already) + if (CombatMovementEnabled) + { + if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE) + { + m_creature->GetMotionMaster()->Clear(false); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim(), AttackDistance, AttackAngle); + } + } + else + if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) + { + m_creature->GetMotionMaster()->Clear(false); + m_creature->GetMotionMaster()->MoveIdle(); + m_creature->StopMoving(); + } + } + break; + case ACTION_T_SET_PHASE: + { + Phase = param1; + } + break; + case ACTION_T_INC_PHASE: + { + Phase += param1; + + if (Phase > 31) + if (EAI_ErrorLevel > 0) + error_db_log( "SD2: Event %d incremented Phase above 31. Phase mask cannot be used with phases past 31. CreatureEntry = %d", EventId, m_creature->GetEntry()); + } + break; + + case ACTION_T_EVADE: + { + EnterEvadeMode(); + } + break; + case ACTION_T_FLEE: + { + //TODO: Replace with Flee movement generator + m_creature->CastSpell(m_creature, SPELL_RUN_AWAY, true); + } + break; + case ACTION_T_QUEST_EVENT_ALL: + { + Unit* Temp = NULL; + if( pActionInvoker && pActionInvoker->GetTypeId() == TYPEID_PLAYER ) + { + Temp = Unit::GetUnit((*m_creature),pActionInvoker->GetGUID()); + if( Temp ) + ((Player*)Temp)->GroupEventHappens(param1,m_creature); + } + } + break; + + case ACTION_T_CASTCREATUREGO_ALL: + { + Unit* Temp = NULL; + + std::list::iterator i = m_creature->getThreatManager().getThreatList().begin(); + for (; i != m_creature->getThreatManager().getThreatList().end(); ++i) + { + Temp = Unit::GetUnit((*m_creature),(*i)->getUnitGuid()); + if (Temp && Temp->GetTypeId() == TYPEID_PLAYER) + ((Player*)Temp)->CastedCreatureOrGO(param1, m_creature->GetGUID(), param2); + } + } + break; + + case ACTION_T_REMOVEAURASFROMSPELL: + { + Unit* target = GetTargetByType(param1, pActionInvoker); + + if (target) + target->RemoveAurasDueToSpell(param2); + } + break; + + case ACTION_T_RANGED_MOVEMENT: + { + AttackDistance = param1; + AttackAngle = ((float)param2/180)*M_PI; + + if (CombatMovementEnabled) + { + //Drop current movement gen + m_creature->GetMotionMaster()->Clear(false); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim(), AttackDistance, AttackAngle); + } + } + break; + + case ACTION_T_RANDOM_PHASE: + { + uint32 temp = GetRandActionParam(rnd, param1, param2, param3); + + Phase = temp; + } + break; + + case ACTION_T_RANDOM_PHASE_RANGE: + { + if (param2 > param1) + { + Phase = param1 + (rnd % (param2 - param1)); + } + else if (EAI_ErrorLevel > 0) + error_db_log( "SD2: ACTION_T_RANDOM_PHASE_RANGE cannot have Param2 <= Param1. Divide by Zero. Event = %d. CreatureEntry = %d", EventId, m_creature->GetEntry()); + } + break; + case ACTION_T_SUMMON_ID: + { + Unit* target = GetTargetByType(param2, pActionInvoker); + + //Duration + Creature* pCreature = NULL; + + HM_NAMESPACE::hash_map::iterator i = EventAI_Summon_Map.find(param3); + + if (i == EventAI_Summon_Map.end()) + { + if (EAI_ErrorLevel > 0) + error_db_log( "SD2: EventAI failed to spawn creature %u. Summon map index %u does not exist. EventID %d. CreatureID %d", param1, param3, EventId, m_creature->GetEntry()); + return; + } + + if ((*i).second.SpawnTimeSecs) + pCreature = m_creature->SummonCreature(param1, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, (*i).second.SpawnTimeSecs); + else pCreature = m_creature->SummonCreature(param1, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); + + if (!pCreature) + { + if (EAI_ErrorLevel > 0) + error_db_log( "SD2: EventAI failed to spawn creature %u. EventId %d.Creature %d", param1, EventId, m_creature->GetEntry()); + } + else if (param2 != TARGET_T_SELF && target) + pCreature->AI()->AttackStart(target); + } + break; + + case ACTION_T_KILLED_MONSTER: + { + Unit* target = GetTargetByType(param2, pActionInvoker); + + if (target && target->GetTypeId() == TYPEID_PLAYER) + ((Player*)target)->KilledMonster(param1, m_creature->GetGUID()); + } + break; + + case ACTION_T_SET_INST_DATA: + { + ScriptedInstance* pInst = (ScriptedInstance*)m_creature->GetInstanceData(); + if (!pInst) + { + if (EAI_ErrorLevel > 0) + error_db_log("SD2: Event %d attempt to set instance data without instance script. Creature %d", EventId, m_creature->GetEntry()); + return; + } + + pInst->SetData(param1, param2); + } + break; + + case ACTION_T_SET_INST_DATA64: + { + Unit* target = GetTargetByType(param2, pActionInvoker); + + if (!target) + { + if (EAI_ErrorLevel > 0) + error_db_log("SD2: Event %d attempt to set instance data64 but Target == NULL. Creature %d", EventId, m_creature->GetEntry()); + return; + } + + ScriptedInstance* pInst = (ScriptedInstance*)m_creature->GetInstanceData(); + + if (!pInst) + { + if (EAI_ErrorLevel > 0) + error_db_log("SD2: Event %d attempt to set instance data64 without instance script. Creature %d", EventId, m_creature->GetEntry()); + return; + } + + pInst->SetData64(param1, target->GetGUID()); + } + break; + + case ACTION_T_UPDATE_TEMPLATE: + { + if (m_creature->GetEntry() == param1) + { + if (EAI_ErrorLevel > 0) + error_db_log("SD2: Event %d ACTION_T_UPDATE_TEMPLATE call with param1 == current entry. Creature %d", EventId, m_creature->GetEntry()); + return; + } + + m_creature->UpdateEntry(param1, param2 ? HORDE : ALLIANCE); + } + break; + + case ACTION_T_DIE: + { + if (m_creature->isDead()) + { + if (EAI_ErrorLevel > 0) + error_db_log("SD2: Event %d ACTION_T_DIE on dead creature. Creature %d", EventId, m_creature->GetEntry()); + return; + } + m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + break; + + case ACTION_T_ZONE_COMBAT_PULSE: + { + if (!m_creature->isInCombat() || !m_creature->GetMap()->IsDungeon()) + { + if (EAI_ErrorLevel > 0) + error_db_log("SD2: Event %d ACTION_T_ZONE_COMBAT_PULSE on creature out of combat or in non-dungeon map. Creature %d", EventId, m_creature->GetEntry()); + return; + } + + DoZoneInCombat(); + } + break; + }; + } + + void JustRespawned() + { + InCombat = false; + Reset(); + + //Handle Spawned Events + for (std::list::iterator i = EventList.begin(); i != EventList.end(); ++i) + { + switch ((*i).Event.event_type) + { + case EVENT_T_SPAWNED: + ProcessEvent(*i); + break; + } + } + } + + void Reset() + { + EventUpdateTime = EVENT_UPDATE_TIME; + EventDiff = 0; + + //Handle Evade events and reset all events to enabled + for (std::list::iterator i = EventList.begin(); i != EventList.end(); ++i) + { + switch ((*i).Event.event_type) + { + //Reset all out of combat timers + case EVENT_T_TIMER_OOC: + { + if ((*i).Event.event_param2 == (*i).Event.event_param1) + { + (*i).Time = (*i).Event.event_param1; + (*i).Enabled = true; + + }else if ((*i).Event.event_param2 > (*i).Event.event_param1) + { + (*i).Time = urand((*i).Event.event_param1, (*i).Event.event_param2); + (*i).Enabled = true; + }else if (EAI_ErrorLevel > 0) + error_db_log("SD2: Creature %u using Event %u (Type = %u) has InitialMax < InitialMin. Event disabled.", m_creature->GetEntry(), (*i).Event.event_id, (*i).Event.event_type); + + }break; + } + } + } + + void EnterEvadeMode() + { + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); + m_creature->CombatStop(); + m_creature->LoadCreaturesAddon(); + if( m_creature->isAlive() ) + m_creature->GetMotionMaster()->MoveTargetedHome(); + + m_creature->SetLootRecipient(NULL); + + InCombat = false; + Reset(); + + //Handle Evade events + for (std::list::iterator i = EventList.begin(); i != EventList.end(); ++i) + { + switch ((*i).Event.event_type) + { + //Evade + case EVENT_T_EVADE: + ProcessEvent(*i); + break; + } + } + } + + void JustDied(Unit* killer) + { + InCombat = false; + Reset(); + + //Handle Evade events + for (std::list::iterator i = EventList.begin(); i != EventList.end(); ++i) + { + switch ((*i).Event.event_type) + { + //Evade + case EVENT_T_DEATH: + ProcessEvent(*i, killer); + break; + } + } + } + + void KilledUnit(Unit* victim) + { + if (victim->GetTypeId() != TYPEID_PLAYER) + return; + + for (std::list::iterator i = EventList.begin(); i != EventList.end(); ++i) + { + switch ((*i).Event.event_type) + { + //Kill + case EVENT_T_KILL: + ProcessEvent(*i, victim); + break; + } + } + + } + + void JustSummoned(Creature* pUnit) + { + if (!pUnit) + return; + + for (std::list::iterator i = EventList.begin(); i != EventList.end(); ++i) + { + switch ((*i).Event.event_type) + { + //Summoned + case EVENT_T_SUMMONED_UNIT: + ProcessEvent(*i, pUnit); + break; + } + } + } + + void Aggro(Unit *who) + { + //Check for on combat start events + for (std::list::iterator i = EventList.begin(); i != EventList.end(); ++i) + { + switch ((*i).Event.event_type) + { + case EVENT_T_AGGRO: + ProcessEvent(*i, who); + break; + + //Reset all in combat timers + case EVENT_T_TIMER: + + if ((*i).Event.event_param2 == (*i).Event.event_param1) + { + (*i).Time = (*i).Event.event_param1; + (*i).Enabled = true; + + }else if ((*i).Event.event_param2 > (*i).Event.event_param1) + { + (*i).Time = urand((*i).Event.event_param1, (*i).Event.event_param2); + (*i).Enabled = true; + }else if (EAI_ErrorLevel > 0) + error_db_log("SD2: Creature %u using Event %u (Type = %u) has InitialMax < InitialMin. Event disabled.", m_creature->GetEntry(), (*i).Event.event_id, (*i).Event.event_type); + + break; + + //All normal events need to be re-enabled and their time set to 0 + default: + (*i).Enabled = true; + (*i).Time = 0; + break; + } + } + + EventUpdateTime = EVENT_UPDATE_TIME; + EventDiff = 0; + } + + void AttackStart(Unit *who) + { + if (!who) + return; + + if (who->isTargetableForAttack()) + { + //Begin melee attack if we are within range + if (CombatMovementEnabled) + AttackTarget(who, true); + else AttackTarget(who, false); + + if (!InCombat) + { + Aggro(who); + InCombat = true; + } + } + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || InCombat) + return; + + //Check for OOC LOS Event + for (std::list::iterator i = EventList.begin(); i != EventList.end(); ++i) + { + switch ((*i).Event.event_type) + { + case EVENT_T_OOC_LOS: + { + if ((*i).Event.event_param1 && m_creature->IsHostileTo(who)) + break; + + if ((*i).Event.event_param2 && !m_creature->IsHostileTo(who)) + break; + + ProcessEvent(*i, who); + } + break; + } + } + + if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + float attackRadius = m_creature->GetAttackDistance(who); + if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) + { + if(who->HasStealthAura()) + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + //Begin melee attack if we are within range + if (CombatMovementEnabled) + AttackTarget(who, true); + else AttackTarget(who, false); + + if (!InCombat) + { + Aggro(who); + InCombat = true; + } + } + } + } + + void SpellHit(Unit* pUnit, const SpellEntry* pSpell) + { + for (std::list::iterator i = EventList.begin(); i != EventList.end(); ++i) + { + switch ((*i).Event.event_type) + { + //Spell hit + case EVENT_T_SPELLHIT: + { + //If spell id matches (or no spell id) & if spell school matches (or no spell school) + if (!(*i).Event.event_param1 || pSpell->Id == (*i).Event.event_param1) + if ((*i).Event.event_param2_s == -1 || pSpell->SchoolMask == (*i).Event.event_param2) + ProcessEvent(*i, pUnit); + } + break; + } + } + } + + void UpdateAI(const uint32 diff) + { + //Check if we are in combat (also updates calls threat update code) + bool Combat = InCombat ? (m_creature->SelectHostilTarget() && m_creature->getVictim()) : false; + + //Must return if creature isn't alive. Normally select hostil target and get victim prevent this + if (!m_creature->isAlive()) + return; + + //Events are only updated once every EVENT_UPDATE_TIME ms to prevent lag with large amount of events + if (EventUpdateTime < diff) + { + EventDiff += diff; + + //Check for range based events + //if (m_creature->GetDistance(m_creature->getVictim()) > + if (Combat) + for (std::list::iterator i = EventList.begin(); i != EventList.end(); ++i) + { + switch ((*i).Event.event_type) + { + case EVENT_T_RANGE: + float dist = m_creature->GetDistance(m_creature->getVictim()); + if (dist > (*i).Event.event_param1 && dist < (*i).Event.event_param2) + ProcessEvent(*i); + break; + } + } + + //Check for time based events + for (std::list::iterator i = EventList.begin(); i != EventList.end(); ++i) + { + //Decrement Timers + if ((*i).Time) + if ((*i).Time > EventDiff) + { + //Do not decrement timers if event cannot trigger in this phase + if (!((*i).Event.event_inverse_phase_mask & (1 << Phase))) + (*i).Time -= EventDiff; + + //Skip processing of events that have time remaining + continue; + } + else (*i).Time = 0; + + switch ((*i).Event.event_type) + { + //Events that are updated every EVENT_UPDATE_TIME + case EVENT_T_TIMER: + case EVENT_T_TIMER_OOC: + case EVENT_T_MANA: + case EVENT_T_HP: + case EVENT_T_TARGET_HP: + case EVENT_T_TARGET_CASTING: + case EVENT_T_FRIENDLY_HP: + ProcessEvent(*i); + break; + } + } + + EventDiff = 0; + EventUpdateTime = EVENT_UPDATE_TIME; + }else + { + EventDiff += diff; + EventUpdateTime -= diff; + } + + //Melee Auto-Attack + if (Combat && MeleeEnabled) + DoMeleeAttackIfReady(); + + } +}; + +CreatureAI* GetAI_Mob_EventAI(Creature *_Creature) +{ + //Select events by creature id + std::list EventList; + uint32 ID = _Creature->GetEntry(); + + std::list::iterator i; + + for (i = EventAI_Event_List.begin(); i != EventAI_Event_List.end(); ++i) + { + if ((*i).creature_id == ID) + { + //Debug check +#ifndef _DEBUG + if ((*i).event_flags & EFLAG_DEBUG_ONLY) + continue; +#endif + + //Heroic Instance Difficulty check + if ((*i).event_flags & EFLAG_HEROIC) + { + //Creature isn't even in a dungeon + if (!_Creature->GetMap() || !_Creature->GetMap()->IsDungeon()) + { + if (EAI_ErrorLevel > 1) + error_db_log("SD2: Creature %u, Event %u using EFLAG_HEROIC but creature is not inside of an instance. Event skipped.", _Creature->GetEntry(), (*i).event_id); + continue; + } + + if (!_Creature->GetMap()->IsHeroic()) + continue; + } else + + //Normal Instance Difficulty check + if ((*i).event_flags & EFLAG_NORMAL) + { + //Creature isn't even in a dungeon + if (!_Creature->GetMap() || !_Creature->GetMap()->IsDungeon()) + { + if (EAI_ErrorLevel > 1) + error_db_log("SD2: Creature %u, Event %u using EFLAG_NORMAL but creature is not inside of an instance. Event skipped.", _Creature->GetEntry(), (*i).event_id); + continue; + } + + if (_Creature->GetMap()->IsHeroic()) + continue; + } else if (_Creature->GetMap() && _Creature->GetMap()->IsDungeon() && EAI_ErrorLevel > 1) + error_db_log("SD2: Creature %u, Event %u. Creature is in instance but neither EFLAG_NORMAL or EFLAG_HEROIC are set.", _Creature->GetEntry(), (*i).event_id); + + //Push back event + EventList.push_back(EventHolder(*i)); + } + } + + //EventAI is pointless to use without events and may cause crashes + if (EventList.empty()) + { + if (EAI_ErrorLevel > 1) + error_db_log("SD2: Eventlist for Creature %u is empty but creature is using Mob_EventAI. Preventing EventAI on this creature.", _Creature->GetEntry()); + + return NULL; + } + + return new Mob_EventAI (_Creature, EventList); +} + +void AddSC_mob_event() +{ + Script *newscript; + newscript = new Script; + newscript->Name="mob_eventai"; + newscript->GetAI = GetAI_Mob_EventAI; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/creature/mob_event_ai.h b/src/bindings/scripts/scripts/creature/mob_event_ai.h new file mode 100644 index 00000000000..05b0b6d7b45 --- /dev/null +++ b/src/bindings/scripts/scripts/creature/mob_event_ai.h @@ -0,0 +1,215 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 +* This program is free software licensed under GPL version 2 +* Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef SC_EVENTAI_H +#define SC_EVENTAI_H + +#define MAX_ACTIONS 3 + +enum Event_Types +{ + EVENT_T_TIMER = 0, //InitialMin, InitialMax, RepeatMin, RepeatMax + EVENT_T_TIMER_OOC = 1, //InitialMin, InitialMax, RepeatMin, RepeatMax + EVENT_T_HP = 2, //HPMax%, HPMin%, RepeatMin, RepeatMax + EVENT_T_MANA = 3, //ManaMax%,ManaMin% RepeatMin, RepeatMax + EVENT_T_AGGRO = 4, //NONE + EVENT_T_KILL = 5, //RepeatMin, RepeatMax + EVENT_T_DEATH = 6, //NONE + EVENT_T_EVADE = 7, //NONE + EVENT_T_SPELLHIT = 8, //SpellID, School, RepeatMin, RepeatMax + EVENT_T_RANGE = 9, //MinDist, MaxDist, RepeatMin, RepeatMax + EVENT_T_OOC_LOS = 10, //NoHostile, NoFriendly, RepeatMin, RepeatMax + EVENT_T_SPAWNED = 11, //NONE + EVENT_T_TARGET_HP = 12, //HPMax%, HPMin%, RepeatMin, RepeatMax + EVENT_T_TARGET_CASTING = 13, //RepeatMin, RepeatMax + EVENT_T_FRIENDLY_HP = 14, //HPDeficit, Radius, RepeatMin, RepeatMax + EVENT_T_FRIENDLY_IS_CC = 15, //DispelType, Radius, RepeatMin, RepeatMax + EVENT_T_FRIENDLY_MISSING_BUFF = 16, //SpellId, Radius, RepeatMin, RepeatMax + EVENT_T_SUMMONED_UNIT = 17, //CreatureId, RepeatMin, RepeatMax + EVENT_T_TARGET_MANA = 18, //ManaMax%, ManaMin%, RepeatMin, RepeatMax + EVENT_T_QUEST_ACCEPT = 19, //QuestID + EVENT_T_QUEST_COMPLETE = 20, // + + EVENT_T_END, +}; + +enum Action_Types +{ + ACTION_T_NONE = 0, //No action + ACTION_T_SAY = 1, //TextId + ACTION_T_YELL = 2, //TextId + ACTION_T_TEXTEMOTE = 3, //TextId + ACTION_T_SOUND = 4, //SoundId + ACTION_T_EMOTE = 5, //EmoteId + ACTION_T_RANDOM_SAY = 6, //TextId1, TextId2, TextId3 (-1 in any field means no output if randomed that field) + ACTION_T_RANDOM_YELL = 7, //TextId1, TextId2, TextId3 (-1 in any field means no output if randomed that field) + ACTION_T_RANDOM_TEXTEMOTE = 8, //TextId1, TextId2, TextId3 (-1 in any field means no output if randomed that field) + ACTION_T_RANDOM_SOUND = 9, //SoundId1, SoundId2, SoundId3 (-1 in any field means no output if randomed that field) + ACTION_T_RANDOM_EMOTE = 10, //EmoteId1, EmoteId2, EmoteId3 (-1 in any field means no output if randomed that field) + ACTION_T_CAST = 11, //SpellId, Target, CastFlags + ACTION_T_SUMMON = 12, //CreatureID, Target, Duration in ms + ACTION_T_THREAT_SINGLE_PCT = 13, //Threat%, Target + ACTION_T_THREAT_ALL_PCT = 14, //Threat% + ACTION_T_QUEST_EVENT = 15, //QuestID, Target + ACTION_T_CASTCREATUREGO = 16, //QuestID, SpellId, Target + ACTION_T_SET_UNIT_FIELD = 17, //Field_Number, Value, Target + ACTION_T_SET_UNIT_FLAG = 18, //Flags (may be more than one field OR'd together), Target + ACTION_T_REMOVE_UNIT_FLAG = 19, //Flags (may be more than one field OR'd together), Target + ACTION_T_AUTO_ATTACK = 20, //AllowAttackState (0 = stop attack, anything else means continue attacking) + ACTION_T_COMBAT_MOVEMENT = 21, //AllowCombatMovement (0 = stop combat based movement, anything else continue attacking) + ACTION_T_SET_PHASE = 22, //Phase + ACTION_T_INC_PHASE = 23, //Value (may be negative to decrement phase, should not be 0) + ACTION_T_EVADE = 24, //No Params + ACTION_T_FLEE = 25, //No Params + ACTION_T_QUEST_EVENT_ALL = 26, //QuestID + ACTION_T_CASTCREATUREGO_ALL = 27, //QuestId, SpellId + ACTION_T_REMOVEAURASFROMSPELL = 28, //Target, Spellid + ACTION_T_RANGED_MOVEMENT = 29, //Distance, Angle + ACTION_T_RANDOM_PHASE = 30, //PhaseId1, PhaseId2, PhaseId3 + ACTION_T_RANDOM_PHASE_RANGE = 31, //PhaseMin, PhaseMax + ACTION_T_SUMMON_ID = 32, //CreatureId, Target, SpawnId + ACTION_T_KILLED_MONSTER = 33, //CreatureId, Target + ACTION_T_SET_INST_DATA = 34, //Field, Data + ACTION_T_SET_INST_DATA64 = 35, //Field, Target + ACTION_T_UPDATE_TEMPLATE = 36, //Entry, Team + ACTION_T_DIE = 37, //No Params + ACTION_T_ZONE_COMBAT_PULSE = 38, //No Params + + ACTION_T_END, +}; + +enum Target +{ + //Self (m_creature) + TARGET_T_SELF = 0, //Self cast + + //Hostile targets (if pet then returns pet owner) + TARGET_T_HOSTILE, //Our current target (ie: highest aggro) + TARGET_T_HOSTILE_SECOND_AGGRO, //Second highest aggro (generaly used for cleaves and some special attacks) + TARGET_T_HOSTILE_LAST_AGGRO, //Dead last on aggro (no idea what this could be used for) + TARGET_T_HOSTILE_RANDOM, //Just any random target on our threat list + TARGET_T_HOSTILE_RANDOM_NOT_TOP, //Any random target except top threat + + //Invoker targets (if pet then returns pet owner) + TARGET_T_ACTION_INVOKER, //Unit who caused this Event to occur (only works for EVENT_T_AGGRO, EVENT_T_KILL, EVENT_T_DEATH, EVENT_T_SPELLHIT, EVENT_T_OOC_LOS, EVENT_T_FRIENDLY_HP, EVENT_T_FRIENDLY_IS_CC, EVENT_T_FRIENDLY_MISSING_BUFF) + + //Hostile targets (including pets) + TARGET_T_HOSTILE_WPET, //Current target (can be a pet) + TARGET_T_HOSTILE_WPET_SECOND_AGGRO, //Second highest aggro (generaly used for cleaves and some special attacks) + TARGET_T_HOSTILE_WPET_LAST_AGGRO, //Dead last on aggro (no idea what this could be used for) + TARGET_T_HOSTILE_WPET_RANDOM, //Just any random target on our threat list + TARGET_T_HOSTILE_WPET_RANDOM_NOT_TOP, //Any random target except top threat + + TARGET_T_ACTION_INVOKER_WPET, + + TARGET_T_END +}; + +enum CastFlags +{ + CAST_INTURRUPT_PREVIOUS = 0x01, //Interrupt any spell casting + CAST_TRIGGERED = 0x02, //Triggered (this makes spell cost zero mana and have no cast time) + CAST_FORCE_CAST = 0x04, //Forces cast even if creature is out of mana or out of range + CAST_NO_MELEE_IF_OOM = 0x08, //Prevents creature from entering melee if out of mana or out of range + CAST_FORCE_TARGET_SELF = 0x10, //Forces the target to cast this spell on itself +}; + +enum EventFlags +{ + EFLAG_REPEATABLE = 0x01, //Event repeats + EFLAG_NORMAL = 0x02, //Event only occurs in Normal instance difficulty + EFLAG_HEROIC = 0x04, //Event only occurs in Heroic instance difficulty + EFLAG_RESERVED_3 = 0x08, + EFLAG_RESERVED_4 = 0x10, + EFLAG_RESERVED_5 = 0x20, + EFLAG_RESERVED_6 = 0x40, + EFLAG_DEBUG_ONLY = 0x80, //Event only occurs in debug build of SD2 only +}; + +struct EventAI_Event +{ + uint32 event_id; + + uint32 creature_id; + + uint16 event_type; + uint32 event_inverse_phase_mask; + uint8 event_chance; + uint8 event_flags; + union + { + uint32 event_param1; + int32 event_param1_s; + }; + union + { + uint32 event_param2; + int32 event_param2_s; + }; + union + { + uint32 event_param3; + int32 event_param3_s; + }; + union + { + uint32 event_param4; + int32 event_param4_s; + }; + + struct _action + { + uint16 type; + union + { + uint32 param1; + int32 param1_s; + }; + union + { + uint32 param2; + int32 param2_s; + }; + union + { + uint32 param3; + int32 param3_s; + }; + }action[MAX_ACTIONS]; +}; + +//Event_Map +extern std::list EventAI_Event_List; + +struct EventAI_Summon +{ + uint32 id; + + float position_x; + float position_y; + float position_z; + float orientation; + uint32 SpawnTimeSecs; +}; + +//EventSummon_Map +extern HM_NAMESPACE::hash_map EventAI_Summon_Map; + +//EventAI Error handling +extern uint32 EAI_ErrorLevel; +/* + +struct EventAI_CreatureError +{ + bool ListEmpty; + bool NoInstance; +}; + +//Error prevention list +extern HM_NAMESPACE::hash_map EventAI_CreatureErrorPreventionList; + +//Defines +#define EVENTAI_EMPTY_EVENTLIST "SD2: Eventlist for Creature %i is empty but creature is using Mob_EventAI. Preventing EventAI on this creature." +*/ +#endif diff --git a/src/bindings/scripts/scripts/creature/mob_generic_creature.cpp b/src/bindings/scripts/scripts/creature/mob_generic_creature.cpp new file mode 100644 index 00000000000..6c05ceffc80 --- /dev/null +++ b/src/bindings/scripts/scripts/creature/mob_generic_creature.cpp @@ -0,0 +1,172 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Generic_Creature +SD%Complete: 80 +SDComment: Should be replaced with core based AI +SDCategory: Creatures +EndScriptData */ + +#include "precompiled.h" + +#define GENERIC_CREATURE_COOLDOWN 5000 + +struct MANGOS_DLL_DECL generic_creatureAI : public ScriptedAI +{ + generic_creatureAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 GlobalCooldown; //This variable acts like the global cooldown that players have (1.5 seconds) + uint32 BuffTimer; //This variable keeps track of buffs + bool IsSelfRooted; + + void Reset() + { + GlobalCooldown = 0; + BuffTimer = 0; //Rebuff as soon as we can + IsSelfRooted = false; + } + + void Aggro(Unit *who) + { + if (!m_creature->IsWithinDistInMap(who, ATTACK_DISTANCE)) + { + IsSelfRooted = true; + } + } + + void UpdateAI(const uint32 diff) + { + //Always decrease our global cooldown first + if (GlobalCooldown > diff) + GlobalCooldown -= diff; + else GlobalCooldown = 0; + + //Buff timer (only buff when we are alive and not in combat + if (!InCombat && m_creature->isAlive()) + if (BuffTimer < diff ) + { + //Find a spell that targets friendly and applies an aura (these are generally buffs) + SpellEntry const *info = SelectSpell(m_creature, -1, -1, SELECT_TARGET_ANY_FRIEND, 0, 0, 0, 0, SELECT_EFFECT_AURA); + + if (info && !GlobalCooldown) + { + //Cast the buff spell + DoCastSpell(m_creature, info); + + //Set our global cooldown + GlobalCooldown = GENERIC_CREATURE_COOLDOWN; + + //Set our timer to 10 minutes before rebuff + BuffTimer = 600000; + }//Try agian in 30 seconds + else BuffTimer = 30000; + }else BuffTimer -= diff; + + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //If we are within range melee the target + if( m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE)) + { + //Make sure our attack is ready and we arn't currently casting + if( m_creature->isAttackReady() && !m_creature->IsNonMeleeSpellCasted(false)) + { + bool Healing = false; + SpellEntry const *info = NULL; + + //Select a healing spell if less than 30% hp + if (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 30) + info = SelectSpell(m_creature, -1, -1, SELECT_TARGET_ANY_FRIEND, 0, 0, 0, 0, SELECT_EFFECT_HEALING); + + //No healing spell available, select a hostile spell + if (info) Healing = true; + else info = SelectSpell(m_creature->getVictim(), -1, -1, SELECT_TARGET_ANY_ENEMY, 0, 0, 0, 0, SELECT_EFFECT_DONTCARE); + + //50% chance if elite or higher, 20% chance if not, to replace our white hit with a spell + if (info && (rand() % (m_creature->GetCreatureInfo()->rank > 1 ? 2 : 5) == 0) && !GlobalCooldown) + { + //Cast the spell + if (Healing)DoCastSpell(m_creature, info); + else DoCastSpell(m_creature->getVictim(), info); + + //Set our global cooldown + GlobalCooldown = GENERIC_CREATURE_COOLDOWN; + } + else m_creature->AttackerStateUpdate(m_creature->getVictim()); + + m_creature->resetAttackTimer(); + } + } + else + { + //Only run this code if we arn't already casting + if (!m_creature->IsNonMeleeSpellCasted(false)) + { + bool Healing = false; + SpellEntry const *info = NULL; + + //Select a healing spell if less than 30% hp ONLY 33% of the time + if (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 30 && rand() % 3 == 0) + info = SelectSpell(m_creature, -1, -1, SELECT_TARGET_ANY_FRIEND, 0, 0, 0, 0, SELECT_EFFECT_HEALING); + + //No healing spell available, See if we can cast a ranged spell (Range must be greater than ATTACK_DISTANCE) + if (info) Healing = true; + else info = SelectSpell(m_creature->getVictim(), -1, -1, SELECT_TARGET_ANY_ENEMY, 0, 0, ATTACK_DISTANCE, 0, SELECT_EFFECT_DONTCARE); + + //Found a spell, check if we arn't on cooldown + if (info && !GlobalCooldown) + { + //If we are currently moving stop us and set the movement generator + if (!IsSelfRooted) + { + IsSelfRooted = true; + } + + //Cast spell + if (Healing) DoCastSpell(m_creature,info); + else DoCastSpell(m_creature->getVictim(),info); + + //Set our global cooldown + GlobalCooldown = GENERIC_CREATURE_COOLDOWN; + + + }//If no spells available and we arn't moving run to target + else if (IsSelfRooted) + { + //Cancel our current spell and then allow movement agian + m_creature->InterruptNonMeleeSpells(false); + IsSelfRooted = false; + } + } + } + } +}; +CreatureAI* GetAI_generic_creature(Creature *_Creature) +{ + return new generic_creatureAI (_Creature); +} + + +void AddSC_generic_creature() +{ + Script *newscript; + newscript = new Script; + newscript->Name="generic_creature"; + newscript->GetAI = GetAI_generic_creature; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/creature/simple_ai.cpp b/src/bindings/scripts/scripts/creature/simple_ai.cpp new file mode 100644 index 00000000000..e93bfba6425 --- /dev/null +++ b/src/bindings/scripts/scripts/creature/simple_ai.cpp @@ -0,0 +1,294 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: SimpleAI +SD%Complete: 100 +SDComment: Base Class for SimpleAI creatures +SDCategory: Creatures +EndScriptData */ + +#include "precompiled.h" +#include "simple_ai.h" + +SimpleAI::SimpleAI(Creature *c) : ScriptedAI(c) +{ + //Clear all data + Aggro_Text[0] = NULL; + Aggro_Text[1] = NULL; + Aggro_Text[2] = NULL; + Aggro_Say[0] = false; + Aggro_Say[1] = false; + Aggro_Say[2] = false; + Aggro_Sound[0] = 0; + Aggro_Sound[1] = 0; + Aggro_Sound[2] = 0; + + Death_Text[0] = NULL; + Death_Text[1] = NULL; + Death_Text[2] = NULL; + Death_Say[0] = false; + Death_Say[1] = false; + Death_Say[2] = false; + Death_Sound[0] = 0; + Death_Sound[1] = 0; + Death_Sound[2] = 0; + Death_Spell = 0; + Death_Target_Type = 0; + + Kill_Text[0] = NULL; + Kill_Text[1] = NULL; + Kill_Text[2] = NULL; + Kill_Say[0] = false; + Kill_Say[1] = false; + Kill_Say[2] = false; + Kill_Sound[0] = 0; + Kill_Sound[1] = 0; + Kill_Sound[2] = 0; + Kill_Spell = 0; + Kill_Target_Type = 0; + + memset(Spell,0,sizeof(Spell)); + + EnterEvadeMode(); +} + +void SimpleAI::Reset() +{ +} + +void SimpleAI::Aggro(Unit *who) +{ + //Reset cast timers + if (Spell[0].First_Cast >= 0) + Spell_Timer[0] = Spell[0].First_Cast; + else Spell_Timer[0] = 1000; + if (Spell[1].First_Cast >= 0) + Spell_Timer[1] = Spell[1].First_Cast; + else Spell_Timer[1] = 1000; + if (Spell[2].First_Cast >= 0) + Spell_Timer[2] = Spell[2].First_Cast; + else Spell_Timer[2] = 1000; + if (Spell[3].First_Cast >= 0) + Spell_Timer[3] = Spell[3].First_Cast; + else Spell_Timer[3] = 1000; + if (Spell[4].First_Cast >= 0) + Spell_Timer[4] = Spell[4].First_Cast; + else Spell_Timer[4] = 1000; + if (Spell[5].First_Cast >= 0) + Spell_Timer[5] = Spell[5].First_Cast; + else Spell_Timer[5] = 1000; + if (Spell[6].First_Cast >= 0) + Spell_Timer[6] = Spell[6].First_Cast; + else Spell_Timer[6] = 1000; + if (Spell[7].First_Cast >= 0) + Spell_Timer[7] = Spell[7].First_Cast; + else Spell_Timer[7] = 1000; + if (Spell[8].First_Cast >= 0) + Spell_Timer[8] = Spell[8].First_Cast; + else Spell_Timer[8] = 1000; + if (Spell[9].First_Cast >= 0) + Spell_Timer[9] = Spell[9].First_Cast; + else Spell_Timer[9] = 1000; + + uint32 random_text = rand()%3; + + //Random yell + if (Aggro_Text[random_text]) + if (Aggro_Say[random_text]) + DoSay(Aggro_Text[random_text], LANG_UNIVERSAL, who); + else DoYell(Aggro_Text[random_text], LANG_UNIVERSAL, who); + + //Random sound + if (Aggro_Sound[random_text]) + DoPlaySoundToSet(m_creature, Aggro_Sound[random_text]); +} + +void SimpleAI::KilledUnit(Unit *victim) +{ + uint32 random_text = rand()%3; + + //Random yell + if (Kill_Text[random_text]) + if (Kill_Say[random_text]) + DoSay(Kill_Text[random_text], LANG_UNIVERSAL, victim); + else DoYell(Kill_Text[random_text], LANG_UNIVERSAL, victim); + + //Random sound + if (Kill_Sound[random_text]) + DoPlaySoundToSet(m_creature, Kill_Sound[random_text]); + + if (!Kill_Spell) + return; + + Unit* target = NULL; + + switch (Kill_Target_Type) + { + case CAST_SELF: + target = m_creature; + break; + case CAST_HOSTILE_TARGET: + target = m_creature->getVictim(); + break; + case CAST_HOSTILE_SECOND_AGGRO: + target = SelectUnit(SELECT_TARGET_TOPAGGRO,1); + break; + case CAST_HOSTILE_LAST_AGGRO: + target = SelectUnit(SELECT_TARGET_BOTTOMAGGRO,0); + break; + case CAST_HOSTILE_RANDOM: + target = SelectUnit(SELECT_TARGET_RANDOM,0); + break; + case CAST_KILLEDUNIT_VICTIM: + target = victim; + break; + } + + //Target is ok, cast a spell on it + if (target) + DoCast(target, Kill_Spell); +} + +void SimpleAI::DamageTaken(Unit *killer, uint32 &damage) +{ + //Return if damage taken won't kill us + if (m_creature->GetHealth() > damage) + return; + + uint32 random_text = rand()%3; + + //Random yell + if (Death_Text[random_text]) + if (Death_Say[random_text]) + DoSay(Death_Text[random_text], LANG_UNIVERSAL, killer); + else DoYell(Death_Text[random_text], LANG_UNIVERSAL, killer); + + //Random sound + if (Death_Sound[random_text]) + DoPlaySoundToSet(m_creature, Death_Sound[random_text]); + + if (!Death_Spell) + return; + + Unit* target = NULL; + + switch (Death_Target_Type) + { + case CAST_SELF: + target = m_creature; + break; + case CAST_HOSTILE_TARGET: + target = m_creature->getVictim(); + break; + case CAST_HOSTILE_SECOND_AGGRO: + target = SelectUnit(SELECT_TARGET_TOPAGGRO,1); + break; + case CAST_HOSTILE_LAST_AGGRO: + target = SelectUnit(SELECT_TARGET_BOTTOMAGGRO,0); + break; + case CAST_HOSTILE_RANDOM: + target = SelectUnit(SELECT_TARGET_RANDOM,0); + break; + case CAST_JUSTDIED_KILLER: + target = killer; + break; + } + + //Target is ok, cast a spell on it + if (target) + DoCast(target, Death_Spell); +} + +void SimpleAI::UpdateAI(const uint32 diff) +{ + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //Spells + for (uint32 i = 0; i < 10; ++i) + { + //Spell not valid + if (!Spell[i].Enabled || !Spell[i].Spell_Id) + continue; + + if (Spell_Timer[i] < diff) + { + //Check if this is a percentage based + if (Spell[i].First_Cast < 0 && Spell[i].First_Cast > -100 && m_creature->GetHealth()*100 / m_creature->GetMaxHealth() > -Spell[i].First_Cast) + continue; + + //Check Current spell + if (!(Spell[i].InterruptPreviousCast && m_creature->IsNonMeleeSpellCasted(false))) + { + Unit* target = NULL; + + switch (Spell[i].Cast_Target_Type) + { + case CAST_SELF: + target = m_creature; + break; + case CAST_HOSTILE_TARGET: + target = m_creature->getVictim(); + break; + case CAST_HOSTILE_SECOND_AGGRO: + target = SelectUnit(SELECT_TARGET_TOPAGGRO,1); + break; + case CAST_HOSTILE_LAST_AGGRO: + target = SelectUnit(SELECT_TARGET_BOTTOMAGGRO,0); + break; + case CAST_HOSTILE_RANDOM: + target = SelectUnit(SELECT_TARGET_RANDOM,0); + break; + } + + //Target is ok, cast a spell on it and then do our random yell + if (target) + { + if (m_creature->IsNonMeleeSpellCasted(false)) + m_creature->InterruptNonMeleeSpells(false); + + DoCast(target, Spell[i].Spell_Id); + + //Yell and sound use the same number so that you can make + //the creature yell with the correct sound effect attached + uint32 random_text = rand()%3; + + //Random yell + if (Spell[i].Text[random_text]) + if (Spell[i].Say[random_text]) + DoSay(Spell[i].Text[random_text], LANG_UNIVERSAL, target); + else DoYell(Spell[i].Text[random_text], LANG_UNIVERSAL, target); + + //Random sound + if (Spell[i].Text_Sound[random_text]) + DoPlaySoundToSet(m_creature, Spell[i].Text_Sound[random_text]); + } + + } + + //Spell will cast agian when the cooldown is up + if (Spell[i].CooldownRandomAddition) + Spell_Timer[i] = Spell[i].Cooldown + (rand() % Spell[i].CooldownRandomAddition); + else Spell_Timer[i] = Spell[i].Cooldown; + + }else Spell_Timer[i] -= diff; + + } + + DoMeleeAttackIfReady(); +} diff --git a/src/bindings/scripts/scripts/creature/simple_ai.h b/src/bindings/scripts/scripts/creature/simple_ai.h new file mode 100644 index 00000000000..0ac78dc1222 --- /dev/null +++ b/src/bindings/scripts/scripts/creature/simple_ai.h @@ -0,0 +1,74 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 +* This program is free software licensed under GPL version 2 +* Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef SC_SIMPLEAI_H +#define SC_SIMPLEAI_H + +enum CastTarget +{ + CAST_SELF = 0, //Self cast + CAST_HOSTILE_TARGET, //Our current target (ie: highest aggro) + CAST_HOSTILE_SECOND_AGGRO, //Second highest aggro (generaly used for cleaves and some special attacks) + CAST_HOSTILE_LAST_AGGRO, //Dead last on aggro (no idea what this could be used for) + CAST_HOSTILE_RANDOM, //Just any random target on our threat list + CAST_FRIENDLY_RANDOM, //NOT YET IMPLEMENTED + + //Special cases + CAST_KILLEDUNIT_VICTIM, //Only works within KilledUnit function + CAST_JUSTDIED_KILLER, //Only works within JustDied function +}; + +struct MANGOS_DLL_DECL SimpleAI : public ScriptedAI +{ + SimpleAI(Creature *c);// : ScriptedAI(c); + + void Reset(); + + void Aggro(Unit *who); + + void KilledUnit(Unit *victim); + + void DamageTaken(Unit *killer, uint32 &damage); + + void UpdateAI(const uint32 diff); + +public: + + char* Aggro_Text[3]; + bool Aggro_Say[3]; + uint32 Aggro_Sound[3]; + + char* Death_Text[3]; + bool Death_Say[3]; + uint32 Death_Sound[3]; + uint32 Death_Spell; + uint32 Death_Target_Type; + + char* Kill_Text[3]; + bool Kill_Say[3]; + uint32 Kill_Sound[3]; + uint32 Kill_Spell; + uint32 Kill_Target_Type; + + struct SimpleAI_Spell + { + uint32 Spell_Id; //Spell ID to cast + int32 First_Cast; //Delay for first cast + uint32 Cooldown; //Cooldown between casts + uint32 CooldownRandomAddition; //Random addition to cooldown (in range from 0 - CooldownRandomAddition) + uint32 Cast_Target_Type; //Target type (note that certain spells may ignore this) + bool InterruptPreviousCast; //Interrupt a previous cast if this spell needs to be cast + bool Enabled; //Spell enabled or disabled (default: false) + + //3 texts to many? + char* Text[3]; + bool Say[3]; + uint32 Text_Sound[3]; + }Spell[10]; + +protected: + uint32 Spell_Timer[10]; +}; + +#endif diff --git a/src/bindings/scripts/scripts/custom/custom_example.cpp b/src/bindings/scripts/scripts/custom/custom_example.cpp new file mode 100644 index 00000000000..e6cdd2f8e62 --- /dev/null +++ b/src/bindings/scripts/scripts/custom/custom_example.cpp @@ -0,0 +1,277 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Custom_Example +SD%Complete: 100 +SDComment: Short custom scripting example +SDCategory: Script Examples +EndScriptData */ + +#include "precompiled.h" + +// **** This script is designed as an example for others to build on **** +// **** Please modify whatever you'd like to as this script is only for developement **** + +// **** Script Info **** +// This script is written in a way that it can be used for both friendly and hostile monsters +// Its primary purpose is to show just how much you can really do with scripts +// I recommend trying it out on both an agressive NPC and on friendly npc + +// **** Quick Info **** +// Functions with Handled Function marked above them are functions that are called automatically by the core +// Functions that are marked Custom Function are functions I've created to simplify code + +#define SPELL_BUFF 25661 +#define SPELL_ONE 12555 +#define SPELL_ONE_ALT 24099 +#define SPELL_TWO 10017 +#define SPELL_THREE 26027 +#define SPELL_ENRAGE 23537 +#define SPELL_BESERK 32309 + +#define SAY_AGGRO "Let the games begin." +#define SAY_RANDOM_0 "I see endless suffering. I see torment. I see rage. I see everything." +#define SAY_RANDOM_1 "Muahahahaha" +#define SAY_RANDOM_2 "These mortal infedels my lord, they have invaded your sanctum and seek to steal your secrets." +#define SAY_RANDOM_3 "You are already dead." +#define SAY_RANDOM_4 "Where to go? What to do? So many choices that all end in pain, end in death." +#define SAY_BESERK "$N, I sentance you to death!" +#define SAY_PHASE "The suffering has just begun!" + +#define GOSSIP_ITEM "I'm looking for a fight" +#define SAY_DANCE "I always thought I was a good dancer" +#define SAY_SALUTE "Move out Soldier!" + +struct MANGOS_DLL_DECL custom_exampleAI : public ScriptedAI +{ + //*** HANDLED FUNCTION *** + //This is the constructor, called only once when the creature is first created + custom_exampleAI(Creature *c) : ScriptedAI(c) {Reset();} + + //*** CUSTOM VARIABLES **** + //These variables are for use only by this individual script. + //Nothing else will ever call them but us. + + uint32 Say_Timer; //Timer for random chat + uint32 Rebuff_Timer; //Timer for rebuffing + uint32 Spell_1_Timer; //Timer for spell 1 when in combat + uint32 Spell_2_Timer; //Timer for spell 1 when in combat + uint32 Spell_3_Timer; //Timer for spell 1 when in combat + uint32 Beserk_Timer; //Timer until we go into Beserk (enraged) mode + uint32 Phase; //The current battle phase we are in + uint32 Phase_Timer; //Timer until phase transition + + //*** HANDLED FUNCTION *** + //This is called whenever the core decides we need to evade + void Reset() + { + Phase = 1; //Start in phase 1 + Phase_Timer = 60000; //60 seconds + Spell_1_Timer = 5000; //5 seconds + Spell_2_Timer = 37000; //37 seconds + Spell_3_Timer = 19000; //19 seconds + Beserk_Timer = 120000; //2 minutes + } + + //*** HANDLED FUNCTION *** + //Attack Start is called whenever someone hits us. + void Aggro(Unit *who) + { + //Say some stuff + DoSay(SAY_AGGRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,8280); + } + + //*** HANDLED FUNCTION *** + //Update AI is called Every single map update (roughly once every 100ms if a player is within the grid) + void UpdateAI(const uint32 diff) + { + //Out of combat timers + if (!m_creature->getVictim()) + { + //Random Say timer + if (Say_Timer < diff) + { + //Random switch between 5 outcomes + switch (rand()%5) + { + case 0: + DoYell(SAY_RANDOM_0,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,8831); //8831 is the index of the sound we are playing. You find these numbers in SoundEntries.dbc + break; + + case 1: + DoYell(SAY_RANDOM_1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,8818); + break; + + case 2: + DoYell(SAY_RANDOM_2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,8041); + break; + + case 3: + DoYell(SAY_RANDOM_3,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,8581); + break; + + case 4: + DoYell(SAY_RANDOM_4,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,8791); + break; + } + + Say_Timer = 45000; //Say something agian in 45 seconds + }else Say_Timer -= diff; + + //Rebuff timer + if (Rebuff_Timer < diff) + { + DoCast(m_creature,SPELL_BUFF); + Rebuff_Timer = 900000; //Rebuff agian in 15 minutes + }else Rebuff_Timer -= diff; + } + + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //Spell 1 timer + if (Spell_1_Timer < diff) + { + //Cast spell one on our current target. + if (rand()%50 > 10) + DoCast(m_creature->getVictim(),SPELL_ONE_ALT); + else if (m_creature->GetDistance(m_creature->getVictim()) < 25) + DoCast(m_creature->getVictim(),SPELL_ONE); + + Spell_1_Timer = 5000; + }else Spell_1_Timer -= diff; + + //Spell 2 timer + if (Spell_2_Timer < diff) + { + //Cast spell one on our current target. + DoCast(m_creature->getVictim(),SPELL_TWO); + + Spell_2_Timer = 37000; + }else Spell_2_Timer -= diff; + + //Spell 3 timer + if (Phase > 1) + if (Spell_3_Timer < diff) + { + //Cast spell one on our current target. + DoCast(m_creature->getVictim(),SPELL_THREE); + + Spell_3_Timer = 19000; + }else Spell_3_Timer -= diff; + + //Beserk timer + if (Phase > 1) + if (Beserk_Timer < diff) + { + //Say our line then cast uber death spell + DoPlaySoundToSet(m_creature,8588); + DoYell(SAY_BESERK,LANG_UNIVERSAL,m_creature->getVictim()); + DoCast(m_creature->getVictim(),SPELL_BESERK); + + //Cast our beserk spell agian in 12 seconds if we didn't kill everyone + Beserk_Timer = 12000; + }else Beserk_Timer -= diff; + + //Phase timer + if (Phase == 1) + if (Phase_Timer < diff) + { + //Go to next phase + Phase++; + DoYell(SAY_PHASE,LANG_UNIVERSAL,NULL); + DoCast(m_creature,SPELL_ENRAGE); + }else Phase_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//This is the GetAI method used by all scripts that involve AI +//It is called every time a new creature using this script is created +CreatureAI* GetAI_custom_example(Creature *_Creature) +{ + return new custom_exampleAI (_Creature); +} + +//This function is called when the player clicks an option on the gossip menu +void SendDefaultMenu_custom_example(Player *player, Creature *_Creature, uint32 action) +{ + if (action == GOSSIP_ACTION_INFO_DEF + 1) //Fight time + { + //Set our faction to hostile twoards all + _Creature->setFaction(24); + _Creature->Attack(player, true); + player->PlayerTalkClass->CloseGossip(); + } +} + +//This function is called when the player clicks an option on the gossip menu +bool GossipSelect_custom_example(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if (sender == GOSSIP_SENDER_MAIN) + SendDefaultMenu_custom_example(player, _Creature, action); + + return true; +} + +//This function is called when the player opens the gossip menu +bool GossipHello_custom_example(Player *player, Creature *_Creature) +{ + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->PlayerTalkClass->SendGossipMenu(907,_Creature->GetGUID()); + + return true; +} + +//Our Recive emote function +bool ReceiveEmote_custom_example(Player *player, Creature *_Creature, uint32 emote) +{ + _Creature->HandleEmoteCommand(emote); + + if (emote == TEXTEMOTE_DANCE) + ((custom_exampleAI*)_Creature->AI())->DoSay(SAY_DANCE,LANG_UNIVERSAL,NULL); + + if (emote == TEXTEMOTE_SALUTE) + ((custom_exampleAI*)_Creature->AI())->DoSay(SAY_SALUTE,LANG_UNIVERSAL,NULL); + + return true; +} + +//This is the actual function called only once durring InitScripts() +//It must define all handled functions that are to be run in this script +//For example if you want this Script to handle Emotes you must include +//newscript->ReciveEmote = My_Emote_Function; +void AddSC_custom_example() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="custom_example"; + newscript->GetAI = GetAI_custom_example; + newscript->pGossipHello = &GossipHello_custom_example; + newscript->pGossipSelect = &GossipSelect_custom_example; + newscript->pReceiveEmote = &ReceiveEmote_custom_example; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/custom/custom_gossip_codebox.cpp b/src/bindings/scripts/scripts/custom/custom_gossip_codebox.cpp new file mode 100644 index 00000000000..a61871a71c3 --- /dev/null +++ b/src/bindings/scripts/scripts/custom/custom_gossip_codebox.cpp @@ -0,0 +1,81 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Custom_Gossip_Codebox +SD%Complete: 100 +SDComment: Show a codebox in gossip option +SDCategory: Script Examples +EndScriptData */ + +#include "precompiled.h" +#include + +//This function is called when the player opens the gossip menubool +bool GossipHello_custom_gossip_codebox(Player *player, Creature *_Creature) +{ + player->PlayerTalkClass->GetGossipMenu()->AddMenuItem(0, "A quiz: what's your name?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1, "", 0, true); + player->ADD_GOSSIP_ITEM(0, "I'm not interested", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + + player->PlayerTalkClass->SendGossipMenu(907,_Creature->GetGUID()); + return true; +} + +//This function is called when the player clicks an option on the gossip menubool +bool GossipSelect_custom_gossip_codebox(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if(action == GOSSIP_ACTION_INFO_DEF+2) + { + _Creature->Say("Normal select, guess you're not interested.", LANG_UNIVERSAL, 0); + player->CLOSE_GOSSIP_MENU(); + } + return true; +} + +bool GossipSelectWithCode_custom_gossip_codebox( Player *player, Creature *_Creature, uint32 sender, uint32 action, const char* sCode ) +{ + if(sender == GOSSIP_SENDER_MAIN) + { + if(action == GOSSIP_ACTION_INFO_DEF+1) + { + if(std::strcmp(sCode, player->GetName())!=0) + { + _Creature->Say("Wrong!", LANG_UNIVERSAL, 0); + _Creature->CastSpell(player, 12826, true); + } + else + { + _Creature->Say("You're right, you are allowed to see my inner secrets.", LANG_UNIVERSAL, 0); + _Creature->CastSpell(player, 26990, true); + } + player->CLOSE_GOSSIP_MENU(); + return true; + } + } + return false; +} + +void AddSC_custom_gossip_codebox() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="custom_gossip_codebox"; + newscript->pGossipHello = &GossipHello_custom_gossip_codebox; + newscript->pGossipSelect = &GossipSelect_custom_gossip_codebox; + newscript->pGossipSelectWithCode = &GossipSelectWithCode_custom_gossip_codebox; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/custom/test.cpp b/src/bindings/scripts/scripts/custom/test.cpp new file mode 100644 index 00000000000..97876ca0c90 --- /dev/null +++ b/src/bindings/scripts/scripts/custom/test.cpp @@ -0,0 +1,202 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Test +SD%Complete: 100 +SDComment: Script used for testing escortAI +SDCategory: Script Examples +EndScriptData */ + +#include "precompiled.h" +#include "../npc/npc_escortAI.h" + +struct MANGOS_DLL_DECL npc_testAI : public npc_escortAI +{ + public: + + // CreatureAI functions + npc_testAI(Creature *c) : npc_escortAI(c) {Reset();} + + uint32 DeathCoilTimer; + uint32 ChatTimer; + + // Pure Virtual Functions + void WaypointReached(uint32 i) + { + switch (i) + { + case 1: + m_creature->Say("Hmm a nice day for a walk alright", LANG_UNIVERSAL, 0); + break; + + case 3: + { + m_creature->Say("Wild Felboar attack!", LANG_UNIVERSAL, 0); + Creature* temp = m_creature->SummonCreature(21878, m_creature->GetPositionX()+5, m_creature->GetPositionY()+7, m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 3000); + + temp->AI()->AttackStart(m_creature); + } + break; + + case 4: + { + m_creature->Say("Time for me to go! See ya around $N!", LANG_UNIVERSAL, PlayerGUID); + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_WAVE); + + Unit* temp = Unit::GetUnit(*m_creature, PlayerGUID); + if (temp) + { + temp->MonsterSay("Bye Bye!", LANG_UNIVERSAL, 0); + temp->HandleEmoteCommand(EMOTE_ONESHOT_WAVE); + } + } + break; + } + } + + void Aggro(Unit*) + { + if (IsBeingEscorted) + m_creature->Say("Help $N! I'm under attack!", LANG_UNIVERSAL, PlayerGUID); + else m_creature->Say("Die scum!", LANG_UNIVERSAL, 0); + } + + void Reset() + { + DeathCoilTimer = 4000; + ChatTimer = 4000; + } + + void JustDied(Unit* killer) + { + if (IsBeingEscorted) + { + //killer = m_creature when player got to far from creature + if (killer == m_creature) + { + Unit *pTemp = Unit::GetUnit(*m_creature,PlayerGUID); + if( pTemp ) + DoWhisper("How dare you leave me like that! I hate you! =*(", pTemp); + } + else m_creature->Say("...no...how could you let me die $N", LANG_UNIVERSAL, PlayerGUID); + } + else m_creature->Say("ugh...", LANG_UNIVERSAL, 0); + } + + void UpdateAI(const uint32 diff) + { + //Must update npc_escortAI + npc_escortAI::UpdateAI(diff); + + //Combat check + if (InCombat && m_creature->getVictim()) + { + if (DeathCoilTimer < diff) + { + m_creature->Say("Taste death!", LANG_UNIVERSAL, 0); + m_creature->CastSpell(m_creature->getVictim(), 33130, false); + + DeathCoilTimer = 4000; + }else DeathCoilTimer -= diff; + }else + { + //Out of combat but being escorted + if (IsBeingEscorted) + if (ChatTimer < diff) + { + if (m_creature->HasAura(3593, 0)) + { + m_creature->Say("Fireworks!", LANG_UNIVERSAL, 0); + m_creature->CastSpell(m_creature, 11540, false); + }else + { + m_creature->Say("Hmm, I think I could use a buff", LANG_UNIVERSAL, 0); + m_creature->CastSpell(m_creature, 3593, false); + } + + ChatTimer = 12000; + }else ChatTimer -= diff; + } + } +}; + +CreatureAI* GetAI_test(Creature *_Creature) +{ + npc_testAI* testAI = new npc_testAI(_Creature); + + testAI->AddWaypoint(0, 1231, -4419, 23); + testAI->AddWaypoint(1, 1198, -4440, 23, 0); + testAI->AddWaypoint(2, 1208, -4392, 23); + testAI->AddWaypoint(3, 1231, -4419, 23, 5000); + testAI->AddWaypoint(4, 1208, -4392, 23, 5000); + + return (CreatureAI*)testAI; +} + +bool GossipHello_npc_test(Player *player, Creature *_Creature) +{ + player->TalkedToCreature(_Creature->GetEntry(),_Creature->GetGUID()); + _Creature->prepareGossipMenu(player,0); + + player->PlayerTalkClass->GetGossipMenu()->AddMenuItem(0, "Click to Test Escort(Attack, Defend, Run)", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1,"",0); + + player->PlayerTalkClass->GetGossipMenu()->AddMenuItem(0, "Click to Test Escort(NoAttack, NoDefend, Walk)", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2,"",0); + + player->PlayerTalkClass->GetGossipMenu()->AddMenuItem(0, "Click to Test Escort(NoAttack, Defend, Walk)", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3,"",0); + + _Creature->sendPreparedGossip( player ); + return true; +} + +bool GossipSelect_npc_test(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if (action == GOSSIP_ACTION_INFO_DEF+1) + { + player->CLOSE_GOSSIP_MENU(); + ((npc_escortAI*)(_Creature->AI()))->Start(true, true, true, player->GetGUID()); + + return true; // prevent mangos core handling + } + + if (action == GOSSIP_ACTION_INFO_DEF+2) + { + player->CLOSE_GOSSIP_MENU(); + ((npc_escortAI*)(_Creature->AI()))->Start(false, false, false, player->GetGUID()); + + return true; // prevent mangos core handling + } + + if (action == GOSSIP_ACTION_INFO_DEF+3) + { + player->CLOSE_GOSSIP_MENU(); + ((npc_escortAI*)(_Creature->AI()))->Start(false, true, false, player->GetGUID()); + + return true; // prevent mangos core handling + } + return false; +} + +void AddSC_test() +{ + Script *newscript; + newscript = new Script; + newscript->Name="test"; + newscript->GetAI = GetAI_test; + newscript->pGossipHello = &GossipHello_npc_test; + newscript->pGossipSelect = &GossipSelect_npc_test; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/go/go_scripts.cpp b/src/bindings/scripts/scripts/go/go_scripts.cpp new file mode 100644 index 00000000000..158f7fbca36 --- /dev/null +++ b/src/bindings/scripts/scripts/go/go_scripts.cpp @@ -0,0 +1,209 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: GO_Scripts +SD%Complete: 100 +SDComment: Quest support: 4285,4287,4288(crystal pylons), 4296. Field_Repair_Bot->Teaches spell 22704. Barov_journal->Teaches spell 26089 +SDCategory: Game Objects +EndScriptData */ + +/* ContentData +go_northern_crystal_pylon +go_eastern_crystal_pylon +go_western_crystal_pylon +go_barov_journal +go_field_repair_bot_74A +go_orb_of_command +go_tablet_of_madness +go_tablet_of_the_seven +go_teleporter +EndContentData */ + +#include "precompiled.h" + +/*###### +## go_crystal_pylons (3x) +######*/ + +bool GOHello_go_northern_crystal_pylon(Player *player, GameObject* _GO) +{ + if (_GO->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER) + { + player->PrepareQuestMenu(_GO->GetGUID()); + player->SendPreparedQuest(_GO->GetGUID()); + } + + if (player->GetQuestStatus(4285) == QUEST_STATUS_INCOMPLETE) + player->AreaExploredOrEventHappens(4285); + + return true; +} + +bool GOHello_go_eastern_crystal_pylon(Player *player, GameObject* _GO) +{ + if (_GO->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER) + { + player->PrepareQuestMenu(_GO->GetGUID()); + player->SendPreparedQuest(_GO->GetGUID()); + } + + if (player->GetQuestStatus(4287) == QUEST_STATUS_INCOMPLETE) + player->AreaExploredOrEventHappens(4287); + + return true; +} + +bool GOHello_go_western_crystal_pylon(Player *player, GameObject* _GO) +{ + if (_GO->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER) + { + player->PrepareQuestMenu(_GO->GetGUID()); + player->SendPreparedQuest(_GO->GetGUID()); + } + + if (player->GetQuestStatus(4288) == QUEST_STATUS_INCOMPLETE) + player->AreaExploredOrEventHappens(4288); + + return true; +} + +/*###### +## go_barov_journal +######*/ + +bool GOHello_go_barov_journal(Player *player, GameObject* _GO) +{ + if(player->HasSkill(SKILL_TAILORING) && player->GetBaseSkillValue(SKILL_TAILORING) >= 280 && !player->HasSpell(26086)) + { + player->CastSpell(player,26095,false); + } + return true; +} + +/*###### +## go_field_repair_bot_74A +######*/ + +bool GOHello_go_field_repair_bot_74A(Player *player, GameObject* _GO) +{ + if(player->HasSkill(SKILL_ENGINERING) && player->GetBaseSkillValue(SKILL_ENGINERING) >= 300 && !player->HasSpell(22704)) + { + player->CastSpell(player,22864,false); + } + return true; +} + +/*###### +## go_orb_of_command +######*/ + +bool GOHello_go_orb_of_command(Player *player, GameObject* _GO) +{ + if( player->GetQuestRewardStatus(7761) ) + player->CastSpell(player,23460,true); + + return true; +} + +/*###### +## go_tablet_of_madness +######*/ + +bool GOHello_go_tablet_of_madness(Player *player, GameObject* _GO) +{ + if (player->HasSkill(SKILL_ALCHEMY) && player->GetSkillValue(SKILL_ALCHEMY) >= 300 && !player->HasSpell(24266)) + { + player->CastSpell(player,24267,false); + } + return true; +} + +/*###### +## go_tablet_of_the_seven +######*/ + +//TODO: use gossip option ("Transcript the Tablet") instead, if Mangos adds support. +bool GOHello_go_tablet_of_the_seven(Player *player, GameObject* _GO) +{ + if (_GO->GetGoType() != GAMEOBJECT_TYPE_QUESTGIVER) + return true; + + if (player->GetQuestStatus(4296) == QUEST_STATUS_INCOMPLETE) + player->CastSpell(player,15065,false); + + return true; +} + +/*###### +## go_teleporter +######*/ + +bool GOHello_go_teleporter(Player *player, GameObject* _GO) +{ + player->TeleportTo(0, 1807.07f,336.105f,70.3975f,0.0f); + return false; +} + +void AddSC_go_scripts() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="go_northern_crystal_pylon"; + newscript->pGOHello = &GOHello_go_northern_crystal_pylon; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="go_eastern_crystal_pylon"; + newscript->pGOHello = &GOHello_go_eastern_crystal_pylon; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="go_western_crystal_pylon"; + newscript->pGOHello = &GOHello_go_western_crystal_pylon; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="go_barov_journal"; + newscript->pGOHello = &GOHello_go_barov_journal; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="go_field_repair_bot_74A"; + newscript->pGOHello = &GOHello_go_field_repair_bot_74A; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="go_orb_of_command"; + newscript->pGOHello = &GOHello_go_orb_of_command; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="go_tablet_of_madness"; + newscript->pGOHello = GOHello_go_tablet_of_madness; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="go_tablet_of_the_seven"; + newscript->pGOHello = GOHello_go_tablet_of_the_seven; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="go_teleporter"; + newscript->pGOHello = GOHello_go_teleporter; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/guard/guard_ai.cpp b/src/bindings/scripts/scripts/guard/guard_ai.cpp new file mode 100644 index 00000000000..7a9d1210bf1 --- /dev/null +++ b/src/bindings/scripts/scripts/guard/guard_ai.cpp @@ -0,0 +1,160 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Guard_AI +SD%Complete: 90 +SDComment: +SDCategory: Guards +EndScriptData */ + +#include "precompiled.h" +#include "guard_ai.h" + +// **** This script is for use within every single guard to save coding time **** + +#define GENERIC_CREATURE_COOLDOWN 5000 + +void guardAI::Reset() +{ + GlobalCooldown = 0; + BuffTimer = 0; //Rebuff as soon as we can +} + +void guardAI::Aggro(Unit *who) +{ +} + +void guardAI::JustDied(Unit *Killer) +{ + //Send Zone Under Attack message to the LocalDefense and WorldDefense Channels + if( Killer->GetTypeId() == TYPEID_PLAYER ) + m_creature->SendZoneUnderAttackMessage((Player*)Killer); + else if( Unit *owner = Killer->GetOwner() ) + { + if( owner->GetTypeId() == TYPEID_PLAYER ) + m_creature->SendZoneUnderAttackMessage((Player*)owner); + } +} + +void guardAI::UpdateAI(const uint32 diff) +{ + //Always decrease our global cooldown first + if (GlobalCooldown > diff) + GlobalCooldown -= diff; + else GlobalCooldown = 0; + + //Buff timer (only buff when we are alive and not in combat + if (m_creature->isAlive() && !InCombat) + if (BuffTimer < diff ) + { + //Find a spell that targets friendly and applies an aura (these are generally buffs) + SpellEntry const *info = SelectSpell(m_creature, -1, -1, SELECT_TARGET_ANY_FRIEND, 0, 0, 0, 0, SELECT_EFFECT_AURA); + + if (info && !GlobalCooldown) + { + //Cast the buff spell + DoCastSpell(m_creature, info); + + //Set our global cooldown + GlobalCooldown = GENERIC_CREATURE_COOLDOWN; + + //Set our timer to 10 minutes before rebuff + BuffTimer = 600000; + } //Try agian in 30 seconds + else BuffTimer = 30000; + }else BuffTimer -= diff; + + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + // Make sure our attack is ready and we arn't currently casting + if( m_creature->isAttackReady() && !m_creature->IsNonMeleeSpellCasted(false)) + { + //If we are within range melee the target + if( m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE)) + { + bool Healing = false; + SpellEntry const *info = NULL; + + //Select a healing spell if less than 30% hp + if (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 30) + info = SelectSpell(m_creature, -1, -1, SELECT_TARGET_ANY_FRIEND, 0, 0, 0, 0, SELECT_EFFECT_HEALING); + + //No healing spell available, select a hostile spell + if (info) Healing = true; + else info = SelectSpell(m_creature->getVictim(), -1, -1, SELECT_TARGET_ANY_ENEMY, 0, 0, 0, 0, SELECT_EFFECT_DONTCARE); + + //20% chance to replace our white hit with a spell + if (info && rand() % 5 == 0 && !GlobalCooldown) + { + //Cast the spell + if (Healing)DoCastSpell(m_creature, info); + else DoCastSpell(m_creature->getVictim(), info); + + //Set our global cooldown + GlobalCooldown = GENERIC_CREATURE_COOLDOWN; + } + else m_creature->AttackerStateUpdate(m_creature->getVictim()); + + m_creature->resetAttackTimer(); + } + } + else + { + //Only run this code if we arn't already casting + if (!m_creature->IsNonMeleeSpellCasted(false)) + { + bool Healing = false; + SpellEntry const *info = NULL; + + //Select a healing spell if less than 30% hp ONLY 33% of the time + if (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 30 && rand() % 3 == 0) + info = SelectSpell(m_creature, -1, -1, SELECT_TARGET_ANY_FRIEND, 0, 0, 0, 0, SELECT_EFFECT_HEALING); + + //No healing spell available, See if we can cast a ranged spell (Range must be greater than ATTACK_DISTANCE) + if (info) Healing = true; + else info = SelectSpell(m_creature->getVictim(), -1, -1, SELECT_TARGET_ANY_ENEMY, 0, 0, ATTACK_DISTANCE, 0, SELECT_EFFECT_DONTCARE); + + //Found a spell, check if we arn't on cooldown + if (info && !GlobalCooldown) + { + //If we are currently moving stop us and set the movement generator + if ((*m_creature).GetMotionMaster()->GetCurrentMovementGeneratorType()!=IDLE_MOTION_TYPE) + { + (*m_creature).GetMotionMaster()->Clear(false); + (*m_creature).GetMotionMaster()->MoveIdle(); + } + + //Cast spell + if (Healing) DoCastSpell(m_creature,info); + else DoCastSpell(m_creature->getVictim(),info); + + //Set our global cooldown + GlobalCooldown = GENERIC_CREATURE_COOLDOWN; + + } //If no spells available and we arn't moving run to target + else if ((*m_creature).GetMotionMaster()->GetCurrentMovementGeneratorType()!=TARGETED_MOTION_TYPE) + { + //Cancel our current spell and then mutate new movement generator + m_creature->InterruptNonMeleeSpells(false); + (*m_creature).GetMotionMaster()->Clear(false); + (*m_creature).GetMotionMaster()->MoveChase(m_creature->getVictim()); + } + } + } +} diff --git a/src/bindings/scripts/scripts/guard/guard_ai.h b/src/bindings/scripts/scripts/guard/guard_ai.h new file mode 100644 index 00000000000..80f88247945 --- /dev/null +++ b/src/bindings/scripts/scripts/guard/guard_ai.h @@ -0,0 +1,25 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef SC_GUARDAI_H +#define SC_GUARDAI_H + +#define GENERIC_CREATURE_COOLDOWN 5000 + +struct MANGOS_DLL_DECL guardAI : public ScriptedAI +{ + guardAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 GlobalCooldown; //This variable acts like the global cooldown that players have (1.5 seconds) + uint32 BuffTimer; //This variable keeps track of buffs + + void Reset(); + + void Aggro(Unit *who); + + void JustDied(Unit *Killer); + + void UpdateAI(const uint32 diff); +}; +#endif diff --git a/src/bindings/scripts/scripts/guard/guards.cpp b/src/bindings/scripts/scripts/guard/guards.cpp new file mode 100644 index 00000000000..ccd231fc166 --- /dev/null +++ b/src/bindings/scripts/scripts/guard/guards.cpp @@ -0,0 +1,4117 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Guards +SD%Complete: 100 +SDComment: All Guard gossip data, quite some npc_text-id's still missing, adding constantly as new id's are known. CombatAI should be organized better for future. +SDCategory: Guards +EndScriptData */ + +/* ContentData +guard_azuremyst +guard_bluffwatcher +guard_contested +guard_darnassus +guard_dunmorogh +guard_durotar +guard_elwynnforest +guard_eversong +guard_exodar +guard_ironforge +guard_mulgore +guard_orgrimmar +guard_shattrath +guard_shattrath_aldor +guard_shattrath_scryer +guard_silvermoon +guard_stormwind +guard_teldrassil +guard_tirisfal +guard_undercity +EndContentData */ + +#include "precompiled.h" +#include "guard_ai.h" + +//script spesific action +#define GOSSIP_ACTION_TAVERN 101 +#define GOSSIP_ACTION_GEMMERCHANT 102 +#define GOSSIP_ACTION_MANALOOM 103 + +//script spesific sender +#define GOSSIP_SENDER_SEC_GEMMERCHANT 101 +#define GOSSIP_SENDER_SEC_AUCTIONHOUSE 102 + +//script spesific gossip text +#define GOSSIP_TEXT_TAVERN "Worlds End Tavern" +#define GOSSIP_TEXT_BANKSCYERS "Scyers bank" +#define GOSSIP_TEXT_BANKALDOR "Aldor Bank" +#define GOSSIP_TEXT_INNSCYERS "Scyers Inn" +#define GOSSIP_TEXT_INNALDOR "Aldor Inn" +#define GOSSIP_TEXT_STABLESCYERS "Scyers Stable" +#define GOSSIP_TEXT_STABLEALDOR "Aldor Stable" +#define GOSSIP_TEXT_BATTLEMASTERALLIANCE "Alliance Battlemasters" +#define GOSSIP_TEXT_BATTLEMASTERHORDE "Horde Battlemasters" +#define GOSSIP_TEXT_BATTLEMASTERARENA "Arena Battlemasters" +#define GOSSIP_TEXT_MANALOOM "Mana Loom" +#define GOSSIP_TEXT_ALCHEMYLAB "Alchemy Lab" +#define GOSSIP_TEXT_GEMMERCHANT "Gem Merchant" +#define GOSSIP_TEXT_GEMSCYERS "Scyers Gem Merchant" +#define GOSSIP_TEXT_GEMALDOR "Aldor Gem Merchant" + +#define GOSSIP_TEXT_AH_SILVERMOON_1 "Western Auction House" +#define GOSSIP_TEXT_AH_SILVERMOON_2 "Royal Exchange Auction House" + +#define GOSSIP_TEXT_INN_SILVERMOON_1 "Silvermoon City Inn" +#define GOSSIP_TEXT_INN_SILVERMOON_2 "Wayfarer's Rest tavern" + +//common used for guards in main cities +void DoReplyToTextEmote(Creature *_Creature,uint32 em) +{ + switch(em) + { + case TEXTEMOTE_KISS: _Creature->HandleEmoteCommand(EMOTE_ONESHOT_BOW); break; + case TEXTEMOTE_WAVE: _Creature->HandleEmoteCommand(EMOTE_ONESHOT_WAVE); break; + case TEXTEMOTE_SALUTE: _Creature->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE); break; + case TEXTEMOTE_SHY: _Creature->HandleEmoteCommand(EMOTE_ONESHOT_FLEX); break; + case TEXTEMOTE_RUDE: + case TEXTEMOTE_CHICKEN: _Creature->HandleEmoteCommand(EMOTE_ONESHOT_POINT); break; + } +} + +/******************************************************* + * guard_azuremyst start + *******************************************************/ + +bool GossipHello_guard_azuremyst(Player *player, Creature *_Creature) +{ + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BANK , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HIPPOGRYPH , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_GUILDMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_INN , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_STABLEMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_CLASSTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PROFTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->SEND_GOSSIP_MENU(10066,_Creature->GetGUID()); + return true; +} + +void SendDefaultMenu_guard_azuremyst(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Bank + player->SEND_POI(-3918.95, -11544.7, 6, 6, 0, "Bank"); + player->SEND_GOSSIP_MENU(10067,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Hippogryph Master + player->SEND_POI(-4057.15, -11788.6, 6, 6, 0, "Stephanos"); + player->SEND_GOSSIP_MENU(10071,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Guild master + player->SEND_POI(-4092.43, -11626.6, 6, 6, 0, "Funaam"); + player->SEND_GOSSIP_MENU(10073,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Inn + player->SEND_POI(-4129.43, -12469, 6, 6, 0, "Caregiver Chellan"); + player->SEND_GOSSIP_MENU(10074,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Stable Master + player->SEND_POI(-4146.42, -12492.7, 6, 6, 0, "Esbina"); + player->SEND_GOSSIP_MENU(10075,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Class trainer + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_DRUID , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HUNTER , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MAGE , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PALADIN , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PRIEST , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_SHAMAN , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WARRIOR , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->SEND_GOSSIP_MENU(10076,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Profession trainer + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ALCHEMY , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BLACKSMITHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_COOKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ENCHANTING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ENGINEERING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FIRSTAID , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FISHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HERBALISM , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_JEWELCRAFTING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 9); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_LEATHERWORKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 10); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MINING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_SKINNING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 12); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_TAILORING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 13); + player->SEND_GOSSIP_MENU(10087,_Creature->GetGUID()); + break; + } +} + +void SendClassTrainerMenu_guard_azuremyst(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Druid + player->SEND_POI(-4274.81, -11495.3, 6, 6, 0, "Shalannius"); + player->SEND_GOSSIP_MENU(10077,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Hunter + player->SEND_POI(-4203.65, -12526.5, 6, 6, 0, "Acteon"); + player->SEND_GOSSIP_MENU(10078,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Mage + player->SEND_POI(-4149.62, -12530.1, 6, 6, 0, "Semid"); + player->SEND_GOSSIP_MENU(10081,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Paladin + player->SEND_POI(-4138.98, -12468.5, 6, 6, 0, "Tullas"); + player->SEND_GOSSIP_MENU(10083,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Priest + player->SEND_POI(-4131.66, -12478.6, 6, 6, 0, "Guvan"); + player->SEND_GOSSIP_MENU(10084,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Shaman + player->SEND_POI(-4162.33, -12456.1, 6, 6, 0, "Tuluun"); + player->SEND_GOSSIP_MENU(10085,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Warrior + player->SEND_POI(-4165.05, -12536.4, 6, 6, 0, "Ruada"); + player->SEND_GOSSIP_MENU(10086,_Creature->GetGUID()); + break; + } +} + +void SendProfTrainerMenu_guard_azuremyst(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Alchemy + player->SEND_POI(-4191.15, -12470, 6, 6, 0, "Daedal"); + player->SEND_GOSSIP_MENU(10088,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Blacksmithing + player->SEND_POI(-4726.29, -12387, 6, 6, 0, "Blacksmith Calypso"); + player->SEND_GOSSIP_MENU(10089,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Cooking + player->SEND_POI(-4710.87, -12400.6, 6, 6, 0, "'Cookie' McWeaksauce"); + player->SEND_GOSSIP_MENU(10090,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Enchanting + player->SEND_POI(-3882.85, -11496.7, 6, 6, 0, "Nahogg"); + player->SEND_GOSSIP_MENU(10091,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Engineering + player->SEND_POI(-4157.57, -12470.2, 6, 6, 0, "Artificer Daelo"); + player->SEND_GOSSIP_MENU(10092,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //First Aid + player->SEND_POI(-4199.11, -12469.9, 6, 6, 0, "Anchorite Fateema"); + player->SEND_GOSSIP_MENU(10093,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Fishing + player->SEND_POI(-4266.38, -12985.1, 6, 6, 0, "Diktynna"); + player->SEND_GOSSIP_MENU(10094,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Herbalism + player->SEND_GOSSIP_MENU(10095,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 9: //Jewelcrafting + player->SEND_POI(-3781.55, -11541.8, 6, 6, 0, "Farii"); + player->SEND_GOSSIP_MENU(10097,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 10: //Leatherworking + player->SEND_POI(-3442.68, -12322.2, 6, 6, 0, "Moordo"); + player->SEND_GOSSIP_MENU(10098,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 11: //Mining + player->SEND_POI(-4179.89, -12493.1, 6, 6, 0, "Dulvi"); + player->SEND_GOSSIP_MENU(10097,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 12: //Skinning + player->SEND_POI(-3431.17, -12316.5, 6, 6, 0, "Gurf"); + player->SEND_GOSSIP_MENU(10098,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 13: //Tailoring + player->SEND_POI(-4711.54, -12386.7, 6, 6, 0, "Erin Kelly"); + player->SEND_GOSSIP_MENU(10099,_Creature->GetGUID()); + break; + } +} + +bool GossipSelect_guard_azuremyst(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + switch (sender) + { + case GOSSIP_SENDER_MAIN: SendDefaultMenu_guard_azuremyst(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_CLASSTRAIN: SendClassTrainerMenu_guard_azuremyst(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_PROFTRAIN: SendProfTrainerMenu_guard_azuremyst(player, _Creature, action); break; + } + return true; +} + +/******************************************************* + * guard_azuremyst end + *******************************************************/ + +CreatureAI* GetAI_guard_azuremyst(Creature *_Creature) +{ + return new guardAI (_Creature); +} + +/******************************************************* + * guard_bluffwatcher start + *******************************************************/ + +bool GossipHello_guard_bluffwatcher(Player *player, Creature *_Creature) +{ + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BANK , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WINDRIDER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_GUILDMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_INN , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MAILBOX , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_AUCTIONHOUSE , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WEAPONMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_STABLEMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BATTLEMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 9); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_CLASSTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 10); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PROFTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->SEND_GOSSIP_MENU(3543,_Creature->GetGUID()); + return true; +} + +void SendDefaultMenu_guard_bluffwatcher(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Bank + player->SEND_POI(-1257.8, 24.14, 6, 6, 0, "Thunder Bluff Bank"); + player->SEND_GOSSIP_MENU(1292,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Wind master + player->SEND_POI(-1196.43, 28.26, 6, 6, 0, "Wind Rider Roost"); + player->SEND_GOSSIP_MENU(1293,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Guild master + player->SEND_POI(-1296.5, 127.57, 6, 6, 0, "Thunder Bluff Civic Information"); + player->SEND_GOSSIP_MENU(1291,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Inn + player->SEND_POI(-1296, 39.7, 6, 6, 0, "Thunder Bluff Inn"); + player->SEND_GOSSIP_MENU(3153,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Mailbox + player->SEND_POI(-1263.59, 44.36, 6, 6, 0, "Thunder Bluff Mailbox"); + player->SEND_GOSSIP_MENU(3154,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Auction House + player->SEND_POI(1381.77, -4371.16, 6, 6, 0, GOSSIP_TEXT_AUCTIONHOUSE); + player->SEND_GOSSIP_MENU(3155,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Weapon master + player->SEND_POI(-1282.31, 89.56, 6, 6, 0, "Ansekhwa"); + player->SEND_GOSSIP_MENU(4520,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Stable master + player->SEND_POI(-1270.19, 48.84, 6, 6, 0, "Bulrug"); + player->SEND_GOSSIP_MENU(5977,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 9: //battlemaster + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ALTERACVALLEY , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ARATHIBASIN , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WARSONGULCH , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 3); + player->SEND_GOSSIP_MENU(7527,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 10: //Class trainer + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_DRUID , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HUNTER , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MAGE , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PRIEST , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_SHAMAN , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WARRIOR , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->SEND_GOSSIP_MENU(3542,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 11: //Profession trainer + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ALCHEMY , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BLACKSMITHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_COOKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ENCHANTING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FIRSTAID , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FISHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HERBALISM , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_LEATHERWORKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MINING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 9); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_SKINNING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 10); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_TAILORING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->SEND_GOSSIP_MENU(3541,_Creature->GetGUID()); + break; + } +} + +void SendBattleMasterMenu_guard_bluffwatcher(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //AV + player->SEND_POI(-1387.82, -97.55, 6, 6, 0, "Taim Ragetotem"); + player->SEND_GOSSIP_MENU(7522,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //AB + player->SEND_POI(-997, 214.12, 6, 6, 0, "Martin Lindsey"); + player->SEND_GOSSIP_MENU(7648,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //WSG + player->SEND_POI(-1384.94, -75.91, 6, 6, 0, "Kergul Bloodaxe"); + player->SEND_GOSSIP_MENU(7523,_Creature->GetGUID()); + break; + } +} + +void SendClassTrainerMenu_guard_bluffwatcher(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Druid + player->SEND_POI(-1054.47, -285, 6, 6, 0, "Hall of Elders"); + player->SEND_GOSSIP_MENU(1294,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Hunter + player->SEND_POI(-1416.32, -114.28, 6, 6, 0, "Hunter's Hall"); + player->SEND_GOSSIP_MENU(1295,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Mage + player->SEND_POI(-1061.2, 195.5, 6, 6, 0, "Pools of Vision"); + player->SEND_GOSSIP_MENU(1296,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Priest + player->SEND_POI(-1061.2, 195.5, 6, 6, 0, "Pools of Vision"); + player->SEND_GOSSIP_MENU(1297,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Shaman + player->SEND_POI(-989.54, 278.25, 6, 6, 0, "Hall of Spirits"); + player->SEND_GOSSIP_MENU(1298,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Warrior + player->SEND_POI(-1416.32, -114.28, 6, 6, 0, "Hunter's Hall"); + player->SEND_GOSSIP_MENU(1299,_Creature->GetGUID()); + break; + } +} + +void SendProfTrainerMenu_guard_bluffwatcher(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Alchemy + player->SEND_POI(-1085.56, 27.29, 6, 6, 0, "Bena's Alchemy"); + player->SEND_GOSSIP_MENU(1332,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Blacksmithing + player->SEND_POI(-1239.75, 104.88, 6, 6, 0, "Karn's Smithy"); + player->SEND_GOSSIP_MENU(1333,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Cooking + player->SEND_POI(-1214.5, -21.23, 6, 6, 0, "Aska's Kitchen"); + player->SEND_GOSSIP_MENU(1334,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Enchanting + player->SEND_POI(-1112.65, 48.26, 6, 6, 0, "Dawnstrider Enchanters"); + player->SEND_GOSSIP_MENU(1335,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //First Aid + player->SEND_POI(-996.58, 200.5, 6, 6, 0, "Spiritual Healing"); + player->SEND_GOSSIP_MENU(1336,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Fishing + player->SEND_POI(-1169.35, -68.87, 6, 6, 0, "Mountaintop Bait & Tackle"); + player->SEND_GOSSIP_MENU(1337,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Herbalism + player->SEND_POI(-1137.7, -1.51, 6, 6, 0, "Holistic Herbalism"); + player->SEND_GOSSIP_MENU(1338,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Leatherworking + player->SEND_POI(-1156.22, 66.86, 6, 6, 0, "Thunder Bluff Armorers"); + player->SEND_GOSSIP_MENU(1339,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 9: //Mining + player->SEND_POI(-1249.17, 155, 6, 6, 0, "Stonehoof Geology"); + player->SEND_GOSSIP_MENU(1340,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 10: //Skinning + player->SEND_POI(-1148.56, 51.18, 6, 6, 0, "Mooranta"); + player->SEND_GOSSIP_MENU(1343,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 11: //Tailoring + player->SEND_POI(-1156.22, 66.86, 6, 6, 0, "Thunder Bluff Armorers"); + player->SEND_GOSSIP_MENU(1341,_Creature->GetGUID()); + break; + } +} + +bool GossipSelect_guard_bluffwatcher(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + switch (sender) + { + case GOSSIP_SENDER_MAIN: SendDefaultMenu_guard_bluffwatcher(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_CLASSTRAIN: SendClassTrainerMenu_guard_bluffwatcher(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_PROFTRAIN: SendProfTrainerMenu_guard_bluffwatcher(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_BATTLEINFO: SendBattleMasterMenu_guard_bluffwatcher(player, _Creature, action); break; + } + return true; +} + +/******************************************************* + * guard_bluffwatcher end + *******************************************************/ + +CreatureAI* GetAI_guard_bluffwatcher(Creature *_Creature) +{ + return new guardAI (_Creature); +} + +/******************************************************* + * guard_contested start + *******************************************************/ + +struct MANGOS_DLL_DECL guard_contested : public guardAI +{ + guard_contested(Creature *c) : guardAI(c) {} + + void MoveInLineOfSight(Unit *who) + { + if ( who->isAttackingPlayer() ) + { + if(who->GetTypeId() == TYPEID_PLAYER || who->GetOwnerGUID() && GUID_HIPART(who->GetOwnerGUID())==HIGHGUID_PLAYER) + { + m_creature->AddThreat(who, 0.0f); + if(Unit* owner = who->GetOwner()) + m_creature->AddThreat(owner, 0.0f); + + if(!m_creature->isInCombat()) + { + if (m_creature->GetEntry() == 15184) //Cenarion Hold Infantry + { + srand (time(NULL)); + if (rand()%100 <= 30) + { + DoSay("Taste blade, mongrel!", LANG_UNIVERSAL,NULL); + } + else if (rand()%100 > 30 && rand()%100 < 50) + { + DoSay("Please tell me that you didn`t just do what I think you just did. Please tell me that I`m not going to have to hurt you...", LANG_UNIVERSAL,NULL); + } + else if (rand()%100 >= 50) + { + DoSay("As if we don`t have enough problems, you go and create more!", LANG_UNIVERSAL,NULL); + } + } + else + { + SpellEntry const *spell = m_creature->reachWithSpellAttack(who); + DoCastSpell(who, spell); + } + } + DoStartAttackAndMovement(who); + } + } + } +}; +/******************************************************* + * guard_contested end + *******************************************************/ + +CreatureAI* GetAI_guard_contested(Creature *_Creature) +{ + return new guard_contested (_Creature); +} + +/******************************************************* + * guard_darnassus start + *******************************************************/ + +bool GossipHello_guard_darnassus(Player *player, Creature *_Creature) +{ + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_AUCTIONHOUSE , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BANK , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HIPPOGRYPH , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_GUILDMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_INN , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MAILBOX , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_STABLEMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WEAPONMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BATTLEMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 9); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_CLASSTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 10); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PROFTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->SEND_GOSSIP_MENU(3016, _Creature->GetGUID()); + return true; +} + +void SendDefaultMenu_guard_darnassus(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Auction house + player->SEND_POI(9861.23, 2334.55, 6, 6, 0, "Darnassus Auction House"); + player->SEND_GOSSIP_MENU(3833, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Bank + player->SEND_POI(9938.45, 2512.35, 6, 6, 0, "Darnassus Bank"); + player->SEND_GOSSIP_MENU(3017, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Wind master + player->SEND_POI(9945.65, 2618.94, 6, 6, 0, "Rut'theran Village"); + player->SEND_GOSSIP_MENU(3018, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Guild master + player->SEND_POI(10076.40, 2199.59, 6, 6, 0, "Darnassus Guild Master"); + player->SEND_GOSSIP_MENU(3019, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Inn + player->SEND_POI(10133.29, 2222.52, 6, 6, 0, "Darnassus Inn"); + player->SEND_GOSSIP_MENU(3020, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Mailbox + player->SEND_POI(9942.17, 2495.48, 6, 6, 0, "Darnassus Mailbox"); + player->SEND_GOSSIP_MENU(3021, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Stable master + player->SEND_POI(10167.20, 2522.66, 6, 6, 0, "Alassin"); + player->SEND_GOSSIP_MENU(5980, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Weapon trainer + player->SEND_POI(9907.11, 2329.70, 6, 6, 0, "Ilyenia Moonfire"); + player->SEND_GOSSIP_MENU(4517, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 9: //Battlemaster + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ALTERACVALLEY , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ARATHIBASIN , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WARSONGULCH , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 3); + player->SEND_GOSSIP_MENU(7519, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 10: //Class trainer + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_DRUID , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HUNTER , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PRIEST , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ROGUE , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WARRIOR , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->SEND_GOSSIP_MENU(4264, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 11: //Profession trainer + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ALCHEMY , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_COOKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ENCHANTING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FIRSTAID , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FISHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HERBALISM , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_LEATHERWORKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_SKINNING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_TAILORING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 9); + player->SEND_GOSSIP_MENU(4273, _Creature->GetGUID()); + break; + } +} + +void SendBattleMasterMenu_guard_darnassus(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //AV + player->SEND_POI(9923.61, 2327.43, 6, 6, 0, "Brogun Stoneshield"); + player->SEND_GOSSIP_MENU(7518, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //AB + player->SEND_POI(9977.37, 2324.39, 6, 6, 0, "Keras Wolfheart"); + player->SEND_GOSSIP_MENU(7651, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //WSG + player->SEND_POI(9979.84, 2315.79, 6, 6, 0, "Aethalas"); + player->SEND_GOSSIP_MENU(7482, _Creature->GetGUID()); + break; + } +} + +void SendClassTrainerMenu_guard_darnassus(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Druid + player->SEND_POI(10186, 2570.46, 6, 6, 0, "Darnassus Druid Trainer"); + player->SEND_GOSSIP_MENU(3024, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Hunter + player->SEND_POI(10177.29, 2511.10, 6, 6, 0, "Darnassus Hunter Trainer"); + player->SEND_GOSSIP_MENU(3023, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Priest + player->SEND_POI(9659.12, 2524.88, 6, 6, 0, "Temple of the Moon"); + player->SEND_GOSSIP_MENU(3025, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Rogue + player->SEND_POI(10122, 2599.12, 6, 6, 0, "Darnassus Rogue Trainer"); + player->SEND_GOSSIP_MENU(3026, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Warrior + player->SEND_POI(9951.91, 2280.38, 6, 6, 0, "Warrior's Terrace"); + player->SEND_GOSSIP_MENU(3033, _Creature->GetGUID()); + break; + } +} + +void SendProfTrainerMenu_guard_darnassus(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Alchemy + player->SEND_POI(10075.90, 2356.76, 6, 6, 0, "Darnassus Alchemy Trainer"); + player->SEND_GOSSIP_MENU(3035, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Cooking + player->SEND_POI(10088.59, 2419.21, 6, 6, 0, "Darnassus Cooking Trainer"); + player->SEND_GOSSIP_MENU(3036, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Enchanting + player->SEND_POI(10146.09, 2313.42, 6, 6, 0, "Darnassus Enchanting Trainer"); + player->SEND_GOSSIP_MENU(3337, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //First Aid + player->SEND_POI(10150.09, 2390.43, 6, 6, 0, "Darnassus First Aid Trainer"); + player->SEND_GOSSIP_MENU(3037, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Fishing + player->SEND_POI(9836.20, 2432.17, 6, 6, 0, "Darnassus Fishing Trainer"); + player->SEND_GOSSIP_MENU(3038, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Herbalism + player->SEND_POI(9757.17, 2430.16, 6, 6, 0, "Darnassus Herbalism Trainer"); + player->SEND_GOSSIP_MENU(3039, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Leatherworking + player->SEND_POI(10086.59, 2255.77, 6, 6, 0, "Darnassus Leatherworking Trainer"); + player->SEND_GOSSIP_MENU(3040, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Skinning + player->SEND_POI(10081.40, 2257.18, 6, 6, 0, "Darnassus Skinning Trainer"); + player->SEND_GOSSIP_MENU(3042, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 9: //Tailoring + player->SEND_POI(10079.70, 2268.19, 6, 6, 0, "Darnassus Tailor"); + player->SEND_GOSSIP_MENU(3044, _Creature->GetGUID()); + break; + } +} + +bool GossipSelect_guard_darnassus(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + switch (sender) + { + case GOSSIP_SENDER_MAIN: SendDefaultMenu_guard_darnassus(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_CLASSTRAIN: SendClassTrainerMenu_guard_darnassus(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_PROFTRAIN: SendProfTrainerMenu_guard_darnassus(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_BATTLEINFO: SendBattleMasterMenu_guard_darnassus(player, _Creature, action); break; + } + return true; +} + +/******************************************************* + * guard_darnassus end + *******************************************************/ + +CreatureAI* GetAI_guard_darnassus(Creature *_Creature) +{ + return new guardAI (_Creature); +} + +/******************************************************* + * guard_dunmorogh start + *******************************************************/ + +bool GossipHello_guard_dunmorogh(Player *player, Creature *_Creature) +{ + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BANK , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HIPPOGRYPH , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_GUILDMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_INN , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_STABLEMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_CLASSTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PROFTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->SEND_GOSSIP_MENU(4287,_Creature->GetGUID()); + + return true; +} + +void SendDefaultMenu_guard_dunmorogh(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Bank + player->SEND_GOSSIP_MENU(4288,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Gryphon master + player->SEND_GOSSIP_MENU(4289,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Guild master + player->SEND_GOSSIP_MENU(4290,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Inn + player->SEND_POI(-5582.66, -525.89, 6, 6, 0, "Thunderbrew Distillery"); + player->SEND_GOSSIP_MENU(4291,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Stable Master + player->SEND_POI(-5604, -509.58, 6, 6, 0, "Shelby Stoneflint"); + player->SEND_GOSSIP_MENU(5985,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Class trainer + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HUNTER , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MAGE , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PALADIN , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PRIEST , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ROGUE , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WARLOCK , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WARRIOR , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->SEND_GOSSIP_MENU(4292,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Profession trainer + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ALCHEMY , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BLACKSMITHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_COOKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ENCHANTING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ENGINEERING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FIRSTAID , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FISHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HERBALISM , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_LEATHERWORKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 9); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MINING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 10); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_SKINNING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_TAILORING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 12); + player->SEND_GOSSIP_MENU(4300,_Creature->GetGUID()); + break; + } +} + +void SendClassTrainerMenu_guard_dunmorogh(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Hunter + player->SEND_POI(-5618.29, -454.25, 6, 6, 0, "Grif Wildheart"); + player->SEND_GOSSIP_MENU(4293,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Mage + player->SEND_POI(-5585.6, -539.99, 6, 6, 0, "Magis Sparkmantle"); + player->SEND_GOSSIP_MENU(4294,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Paladin + player->SEND_POI(-5585.6, -539.99, 6, 6, 0, "Azar Stronghammer"); + player->SEND_GOSSIP_MENU(4295,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Priest + player->SEND_POI(-5591.74, -525.61, 6, 6, 0, "Maxan Anvol"); + player->SEND_GOSSIP_MENU(4296,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Rogue + player->SEND_POI(-5602.75, -542.4, 6, 6, 0, "Hogral Bakkan"); + player->SEND_GOSSIP_MENU(4297,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Warlock + player->SEND_POI(-5641.97, -523.76, 6, 6, 0, "Gimrizz Shadowcog"); + player->SEND_GOSSIP_MENU(4298,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Warrior + player->SEND_POI(-5604.79, -529.38, 6, 6, 0, "Granis Swiftaxe"); + player->SEND_GOSSIP_MENU(4299,_Creature->GetGUID()); + break; + } +} + +void SendProfTrainerMenu_guard_dunmorogh(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Alchemy + player->SEND_GOSSIP_MENU(4301,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Blacksmithing + player->SEND_POI(-5584.72, -428.41, 6, 6, 0, "Tognus Flintfire"); + player->SEND_GOSSIP_MENU(4302,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Cooking + player->SEND_POI(-5596.85, -541.43, 6, 6, 0, "Gremlock Pilsnor"); + player->SEND_GOSSIP_MENU(4303,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Enchanting + player->SEND_GOSSIP_MENU(4304,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Engineering + player->SEND_POI(-5531, -666.53, 6, 6, 0, "Bronk Guzzlegear"); + player->SEND_GOSSIP_MENU(4305,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //First Aid + player->SEND_POI(-5603.67, -523.57, 6, 6, 0, "Thamner Pol"); + player->SEND_GOSSIP_MENU(4306,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Fishing + player->SEND_POI(-5199.9, 58.58, 6, 6, 0, "Paxton Ganter"); + player->SEND_GOSSIP_MENU(4307,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Herbalism + player->SEND_GOSSIP_MENU(4308,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 9: //Leatherworking + player->SEND_GOSSIP_MENU(4310,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 10: //Mining + player->SEND_POI(-5531, -666.53, 6, 6, 0, "Yarr Hamerstone"); + player->SEND_GOSSIP_MENU(4311,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 11: //Skinning + player->SEND_GOSSIP_MENU(4312,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 12: //Tailoring + player->SEND_GOSSIP_MENU(4313,_Creature->GetGUID()); + break; + } +} + +bool GossipSelect_guard_dunmorogh(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + switch (sender) + { + case GOSSIP_SENDER_MAIN: SendDefaultMenu_guard_dunmorogh(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_CLASSTRAIN: SendClassTrainerMenu_guard_dunmorogh(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_PROFTRAIN: SendProfTrainerMenu_guard_dunmorogh(player, _Creature, action); break; + } + return true; +} + +/******************************************************* + * guard_dunmorogh end + *******************************************************/ + +CreatureAI* GetAI_guard_dunmorogh(Creature *_Creature) +{ + return new guardAI (_Creature); +} + +/******************************************************* + * guard_durotar start + *******************************************************/ + +bool GossipHello_guard_durotar(Player *player, Creature *_Creature) +{ + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BANK , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WINDRIDER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_INN , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_STABLEMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_CLASSTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PROFTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->SEND_GOSSIP_MENU(4037,_Creature->GetGUID()); + return true; +} + +void SendDefaultMenu_guard_durotar(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Bank + player->SEND_GOSSIP_MENU(4032,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Wind rider + player->SEND_GOSSIP_MENU(4033,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Inn + player->SEND_POI(338.7, -4688.87, 6, 6, 0, "Razor Hill Inn"); + player->SEND_GOSSIP_MENU(4034,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Stable master + player->SEND_POI(330.31, -4710.66, 6, 6, 0, "Shoja'my"); + player->SEND_GOSSIP_MENU(5973,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Class trainer + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HUNTER , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MAGE , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PRIEST , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ROGUE , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_SHAMAN , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WARLOCK , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WARRIOR , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->SEND_GOSSIP_MENU(4035,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Profession trainer + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ALCHEMY , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BLACKSMITHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_COOKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ENCHANTING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ENGINEERING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FIRSTAID , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FISHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HERBALISM , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_LEATHERWORKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 9); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MINING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 10); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_SKINNING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_TAILORING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 12); + player->SEND_GOSSIP_MENU(4036,_Creature->GetGUID()); + break; + } +} + +void SendClassTrainerMenu_guard_durotar(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Hunter + player->SEND_POI(276, -4706.72, 6, 6, 0, "Thotar"); + player->SEND_GOSSIP_MENU(4013,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Mage + player->SEND_POI(-839.33, -4935.6, 6, 6, 0, "Un'Thuwa"); + player->SEND_GOSSIP_MENU(4014,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Priest + player->SEND_POI(296.22, -4828.1, 6, 6, 0, "Tai'jin"); + player->SEND_GOSSIP_MENU(4015,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Rogue + player->SEND_POI(265.76, -4709, 6, 6, 0, "Kaplak"); + player->SEND_GOSSIP_MENU(4016,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Shaman + player->SEND_POI(307.79, -4836.97, 6, 6, 0, "Swart"); + player->SEND_GOSSIP_MENU(4017,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Warlock + player->SEND_POI(355.88, -4836.45, 6, 6, 0, "Dhugru Gorelust"); + player->SEND_GOSSIP_MENU(4018,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Warrior + player->SEND_POI(312.3, -4824.66, 6, 6, 0, "Tarshaw Jaggedscar"); + player->SEND_GOSSIP_MENU(4019,_Creature->GetGUID()); + break; + } +} + +void SendProfTrainerMenu_guard_durotar(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Alchemy + player->SEND_POI(-800.25, -4894.33, 6, 6, 0, "Miao'zan"); + player->SEND_GOSSIP_MENU(4020,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Blacksmithing + player->SEND_POI(373.24, -4716.45, 6, 6, 0, "Dwukk"); + player->SEND_GOSSIP_MENU(4021,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Cooking + player->SEND_GOSSIP_MENU(4022,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Enchanting + player->SEND_GOSSIP_MENU(4023,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Engineering + player->SEND_POI(368.95, -4723.95, 6, 6, 0, "Mukdrak"); + player->SEND_GOSSIP_MENU(4024,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //First Aid + player->SEND_POI(327.17, -4825.62, 6, 6, 0, "Rawrk"); + player->SEND_GOSSIP_MENU(4025,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Fishing + player->SEND_POI(-1065.48, -4777.43, 6, 6, 0, "Lau'Tiki"); + player->SEND_GOSSIP_MENU(4026,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Herbalism + player->SEND_POI(-836.25, -4896.89, 6, 6, 0, "Mishiki"); + player->SEND_GOSSIP_MENU(4027,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 9: //Leatherworking + player->SEND_GOSSIP_MENU(4028,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 10: //Mining + player->SEND_POI(366.94, -4705, 6, 6, 0, "Krunn"); + player->SEND_GOSSIP_MENU(4029,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 11: //Skinning + player->SEND_GOSSIP_MENU(4030,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 12: //Tailoring + player->SEND_GOSSIP_MENU(4031,_Creature->GetGUID()); + break; + } +} + +bool GossipSelect_guard_durotar(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + switch (sender) + { + case GOSSIP_SENDER_MAIN: SendDefaultMenu_guard_durotar(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_CLASSTRAIN: SendClassTrainerMenu_guard_durotar(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_PROFTRAIN: SendProfTrainerMenu_guard_durotar(player, _Creature, action); break; + } + return true; +} + +/******************************************************* + * guard_durotar end + *******************************************************/ + +CreatureAI* GetAI_guard_durotar(Creature *_Creature) +{ + return new guardAI (_Creature); +} + +/******************************************************* + * guard_elwynnforest start + *******************************************************/ + +bool GossipHello_guard_elwynnforest(Player *player, Creature *_Creature) +{ + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BANK , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_GRYPHON , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_GUILDMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_INN , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_STABLEMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_CLASSTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PROFTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->SEND_GOSSIP_MENU(933,_Creature->GetGUID()); + return true; +} + +void SendDefaultMenu_guard_elwynnforest(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Bank + player->SEND_GOSSIP_MENU(4260,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Gryphon master + player->SEND_GOSSIP_MENU(4261,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Guild master + player->SEND_GOSSIP_MENU(4262,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Inn + player->SEND_POI(-9459.34, 42.08, 6, 6, 0, "Lion's Pride Inn"); + player->SEND_GOSSIP_MENU(4263,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Stable Master + player->SEND_POI(-9466.62, 45.87, 6, 6, 0, "Erma"); + player->SEND_GOSSIP_MENU(5983,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Class trainer + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_DRUID , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HUNTER , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MAGE , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PALADIN , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PRIEST , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ROGUE , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WARLOCK , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WARRIOR , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->SEND_GOSSIP_MENU(4264,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Profession trainer + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ALCHEMY , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BLACKSMITHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_COOKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ENCHANTING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ENGINEERING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FIRSTAID , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FISHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HERBALISM , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_LEATHERWORKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 9); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MINING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 10); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_SKINNING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_TAILORING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 12); + player->SEND_GOSSIP_MENU(4273,_Creature->GetGUID()); + break; + } +} + +void SendClassTrainerMenu_guard_elwynnforest(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Druid + player->SEND_GOSSIP_MENU(4265,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Hunter + player->SEND_GOSSIP_MENU(4266,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Mage + player->SEND_POI(-9471.12, 33.44, 6, 6, 0, "Zaldimar Wefhellt"); + player->SEND_GOSSIP_MENU(4268,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Paladin + player->SEND_POI(-9469, 108.05, 6, 6, 0, "Brother Wilhelm"); + player->SEND_GOSSIP_MENU(4269,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Priest + player->SEND_POI(-9461.07, 32.6, 6, 6, 0, "Priestess Josetta"); + player->SEND_GOSSIP_MENU(4267,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Rogue + player->SEND_POI(-9465.13, 13.29, 6, 6, 0, "Keryn Sylvius"); + player->SEND_GOSSIP_MENU(4270,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Warlock + player->SEND_POI(-9473.21, -4.08, 6, 6, 0, "Maximillian Crowe"); + player->SEND_GOSSIP_MENU(4272,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Warrior + player->SEND_POI(-9461.82, 109.50, 6, 6, 0, "Lyria Du Lac"); + player->SEND_GOSSIP_MENU(4271,_Creature->GetGUID()); + break; + } +} + +void SendProfTrainerMenu_guard_elwynnforest(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Alchemy + player->SEND_POI(-9057.04, 153.63, 6, 6, 0, "Alchemist Mallory"); + player->SEND_GOSSIP_MENU(4274,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Blacksmithing + player->SEND_POI(-9456.58, 87.90, 6, 6, 0, "Smith Argus"); + player->SEND_GOSSIP_MENU(4275,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Cooking + player->SEND_POI(-9467.54, -3.16, 6, 6, 0, "Tomas"); + player->SEND_GOSSIP_MENU(4276,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Enchanting + player->SEND_GOSSIP_MENU(4277,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Engineering + player->SEND_GOSSIP_MENU(4278,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //First Aid + player->SEND_POI(-9456.82, 30.49, 6, 6, 0, "Michelle Belle"); + player->SEND_GOSSIP_MENU(4279,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Fishing + player->SEND_POI(-9386.54, -118.73, 6, 6, 0, "Lee Brown"); + player->SEND_GOSSIP_MENU(4280,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Herbalism + player->SEND_POI(-9060.70, 149.23, 6, 6, 0, "Herbalist Pomeroy"); + player->SEND_GOSSIP_MENU(4281,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 9: //Leatherworking + player->SEND_POI(-9376.12, -75.23, 6, 6, 0, "Adele Fielder"); + player->SEND_GOSSIP_MENU(4282,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 10: //Mining + player->SEND_GOSSIP_MENU(4283,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 11: //Skinning + player->SEND_POI(-9536.91, -1212.76, 6, 6, 0, "Helene Peltskinner"); + player->SEND_GOSSIP_MENU(4284,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 12: //Tailoring + player->SEND_POI(-9376.12, -75.23, 6, 6, 0, "Eldrin"); + player->SEND_GOSSIP_MENU(4285,_Creature->GetGUID()); + break; + } +} + +bool GossipSelect_guard_elwynnforest(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + switch (sender) + { + case GOSSIP_SENDER_MAIN: SendDefaultMenu_guard_elwynnforest(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_CLASSTRAIN: SendClassTrainerMenu_guard_elwynnforest(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_PROFTRAIN: SendProfTrainerMenu_guard_elwynnforest(player, _Creature, action); break; + } + return true; +} + +/******************************************************* + * guard_elwynnforest end + *******************************************************/ + +CreatureAI* GetAI_guard_elwynnforest(Creature *_Creature) +{ + return new guardAI (_Creature); +} + +/******************************************************* + * guard_eversong start + *******************************************************/ + +bool GossipHello_guard_eversong(Player *player, Creature *_Creature) +{ + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BATHANDLER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_GUILDMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_INN , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_STABLEMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_CLASSTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PROFTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->SEND_GOSSIP_MENU(10180,_Creature->GetGUID()); + return true; +} + +void SendDefaultMenu_guard_eversong(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Bat Handler + player->SEND_POI(9371.93, -7164.80, 6, 6, 0, "Skymistress Gloaming"); + player->SEND_GOSSIP_MENU(10181,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Guild master + player->SEND_GOSSIP_MENU(10182,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Inn + player->SEND_POI(9483.74, -6844.58, 6, 6, 0, "Delaniel's inn"); + player->SEND_GOSSIP_MENU(10183,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Stable Master + player->SEND_POI(9489.62, -6829.93, 6, 6, 0, "Anathos"); + player->SEND_GOSSIP_MENU(10184,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Class trainer + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_DRUID , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HUNTER , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MAGE , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PALADIN , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PRIEST , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ROGUE , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WARLOCK , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->SEND_GOSSIP_MENU(10180,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Profession trainer + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ALCHEMY , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BLACKSMITHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_COOKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ENGINEERING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FIRSTAID , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FISHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HERBALISM , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_JEWELCRAFTING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_LEATHERWORKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 9); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MINING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 10); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_SKINNING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_TAILORING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 12); + player->SEND_GOSSIP_MENU(10180,_Creature->GetGUID()); + break; + } +} + +void SendClassTrainerMenu_guard_eversong(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Druid + player->SEND_GOSSIP_MENU(10185,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Hunter + player->SEND_POI(9527.44, -6865.25, 6, 6, 0, "Hannovia"); + player->SEND_GOSSIP_MENU(10186,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Mage + player->SEND_POI(9464.24, -6855.52, 6, 6, 0, "Garridel"); + player->SEND_GOSSIP_MENU(10187,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Paladin + player->SEND_POI(9517.61, -6871.04, 6, 6, 0, "Noellene"); + player->SEND_GOSSIP_MENU(10189,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Priest + player->SEND_POI(9467.39, -6845.72, 6, 6, 0, "Ponaris"); + player->SEND_GOSSIP_MENU(10190,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Rogue + player->SEND_POI(9533.67, -6877.39, 6, 6, 0, "Tannaria"); + player->SEND_GOSSIP_MENU(10191,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Warlock + player->SEND_POI(9468.99, -6865.60, 6, 6, 0, "Celoenus"); + player->SEND_GOSSIP_MENU(10192,_Creature->GetGUID()); + break; + } +} + +void SendProfTrainerMenu_guard_eversong(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Alchemy + player->SEND_POI(8659.90, -6368.12, 6, 6, 0, "Arcanist Sheynathren"); + player->SEND_GOSSIP_MENU(10193,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Blacksmithing + player->SEND_POI(8984.21, -7419.21, 6, 6, 0, "Arathel Sunforge"); + player->SEND_GOSSIP_MENU(10194,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Cooking + player->SEND_POI(9494.04, -6881.51, 6, 6, 0, "Quarelestra"); + player->SEND_GOSSIP_MENU(10195,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Engineering + player->SEND_GOSSIP_MENU(10197,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //First Aid + player->SEND_POI(9479.46, -6879.16, 6, 6, 0, "Kanaria"); + player->SEND_GOSSIP_MENU(10198,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Fishing + player->SEND_GOSSIP_MENU(10199,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Herbalism + player->SEND_POI(8678.92, -6329.09, 6, 6, 0, "Botanist Tyniarrel"); + player->SEND_GOSSIP_MENU(10200,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Jewelcrafting + player->SEND_POI(9484.32, -6874.98, 6, 6, 0, "Aleinia"); + player->SEND_GOSSIP_MENU(10203,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 9: //Leatherworking + player->SEND_POI(9362.04, -7130.33, 6, 6, 0, "Sathein"); + player->SEND_GOSSIP_MENU(10204,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 10: //Mining + player->SEND_GOSSIP_MENU(10205,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 11: //Skinning + player->SEND_POI(9362.04, -7130.33, 6, 6, 0, "Mathreyn"); + player->SEND_GOSSIP_MENU(10206,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 12: //Tailoring + player->SEND_POI(8680.36, -6327.51, 6, 6, 0, "Sempstress Ambershine"); + player->SEND_GOSSIP_MENU(10207,_Creature->GetGUID()); + break; + } +} + +bool GossipSelect_guard_eversong(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + switch (sender) + { + case GOSSIP_SENDER_MAIN: SendDefaultMenu_guard_eversong(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_CLASSTRAIN: SendClassTrainerMenu_guard_eversong(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_PROFTRAIN: SendProfTrainerMenu_guard_eversong(player, _Creature, action); break; + } + return true; +} + +/******************************************************* + * guard_eversong end + *******************************************************/ + +CreatureAI* GetAI_guard_eversong(Creature *_Creature) +{ + return new guardAI (_Creature); +} + +/******************************************************* + * guard_exodar start + *******************************************************/ + +bool GossipHello_guard_exodar(Player *player, Creature *_Creature) +{ + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_AUCTIONHOUSE , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BANK , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_GUILDMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HIPPOGRYPH , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_INN , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MAILBOX , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_STABLEMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WEAPONMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BATTLEMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 9); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_CLASSTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 10); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PROFTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->SEND_GOSSIP_MENU(9551, _Creature->GetGUID()); + return true; +} + +void SendDefaultMenu_guard_exodar(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Auction house + player->SEND_POI(-4023.6, -11739.3, 6, 6, 0, "Exodar Auction House"); + player->SEND_GOSSIP_MENU(9528, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Bank + player->SEND_POI(-3923.89, -11544.5, 6, 6, 0, "Exodar Bank"); + player->SEND_GOSSIP_MENU(9529, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Guild master + player->SEND_POI(-4092.57, -11626.5, 6, 6, 0, "Exodar Guild Master"); + player->SEND_GOSSIP_MENU(9539, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Hippogryph master + player->SEND_POI(-4060.46, -11787.1, 6, 6, 0, "Exodar Hippogryph Master"); + player->SEND_GOSSIP_MENU(9530, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Inn + player->SEND_POI(-3741.87, -11695.1, 6, 6, 0, "Exodar Inn"); + player->SEND_GOSSIP_MENU(9545, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Mailbox + player->SEND_POI(-3972.5, -11696.0, 6, 6, 0, "Mailbox"); + player->SEND_GOSSIP_MENU(10254, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Stable master + player->SEND_POI(-3786.5, -11702.5, 6, 6, 0, "Stable Master Arthaid"); + player->SEND_GOSSIP_MENU(9558, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Weapon trainer + player->SEND_POI(-4215.68, -11628.9, 6, 6, 0, "Weapon Master Handiir"); + player->SEND_GOSSIP_MENU(9565, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 9: //Battlemaster + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ALTERACVALLEY , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ARATHIBASIN , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ARENA , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_EYEOFTHESTORM , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WARSONGULCH , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 5); + player->SEND_GOSSIP_MENU(9531, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 10: //Class trainer + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_DRUID , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HUNTER , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MAGE , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PALADIN , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PRIEST , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_SHAMAN , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WARRIOR , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->SEND_GOSSIP_MENU(9533, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 11: //Profession trainer + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ALCHEMY , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BLACKSMITHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_COOKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ENCHANTING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ENGINEERING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FIRSTAID , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FISHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_JEWELCRAFTING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HERBALISM , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 9); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_LEATHERWORKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 10); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MINING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_SKINNING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 12); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_TAILORING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 13); + player->SEND_GOSSIP_MENU(9555, _Creature->GetGUID()); + break; + } +} + +void SendBattleMasterMenu_guard_exodar(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //AV + player->SEND_POI(-3978.1, -11357, 6, 6, 0, "Alterac Valley Battlemaster"); + player->SEND_GOSSIP_MENU(9531, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //AB + player->SEND_POI(-3998.9, -11345.2, 6, 6, 0, "Arathi Basin Battlemaster"); + player->SEND_GOSSIP_MENU(9531, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //A + player->SEND_POI(-3759.27, -11695.63, 6, 6, 0, "Miglik Blotstrom"); + player->SEND_GOSSIP_MENU(10223, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //EOS + player->SEND_POI(-3978.1, -11357, 6, 6, 0, "Eye Of The Storm Battlemaster"); + player->SEND_GOSSIP_MENU(9531, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //WSG + player->SEND_POI(-3977.5, -11381.2, 6, 6, 0, "Warsong Gulch Battlemaster"); + player->SEND_GOSSIP_MENU(9531, _Creature->GetGUID()); + break; + } +} + +void SendClassTrainerMenu_guard_exodar(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Druid + player->SEND_POI(-4276.0, -11495, 6, 6, 0, "Exodar Druid Trainer"); + player->SEND_GOSSIP_MENU(9534, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Hunter + player->SEND_POI(-4210.6, -11575.2, 6, 6, 0, "Exodar Hunter Trainer"); + player->SEND_GOSSIP_MENU(9544, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Mage + player->SEND_POI(-4057.32, -11556.5, 6, 6, 0, "Exodar Mage Trainer"); + player->SEND_GOSSIP_MENU(9550, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Paladin + player->SEND_POI(-4191.2, -11470.4, 6, 6, 0, "Exodar Paladin Trainer"); + player->SEND_GOSSIP_MENU(9553, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Priest + player->SEND_POI(-3969.63, -11482.8, 6, 6, 0, "Exodar Priest Trainer"); + player->SEND_GOSSIP_MENU(9554, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Shaman + player->SEND_POI(-3805.5, -11380.7, 6, 6, 0, "Exodar Shaman Trainer"); + player->SEND_GOSSIP_MENU(9556, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Warrior + player->SEND_POI(-4189.43, -11653.7, 6, 6, 0, "Exodar Warrior Trainer"); + player->SEND_GOSSIP_MENU(9562, _Creature->GetGUID()); + break; + } +} + +void SendProfTrainerMenu_guard_exodar(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Alchemy + player->SEND_POI(-4040.6, -11364.5, 6, 6, 0, "Exodar Alchemy Trainer"); + player->SEND_GOSSIP_MENU(9527, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Blacksmithing + player->SEND_POI(-4229.5, -11706, 6, 6, 0, "Exodar Blacksmithing Trainer"); + player->SEND_GOSSIP_MENU(9532, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Cooking + player->SEND_POI(-3798.3, -11651.7, 6, 6, 0, "Exodar Cooking Trainer"); + player->SEND_GOSSIP_MENU(9551, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Enchanting + player->SEND_POI(-3889.3, -11495, 6, 6, 0, "Exodar Enchanting Trainer"); + player->SEND_GOSSIP_MENU(9535, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Engineering + player->SEND_POI(-4257.68, -11640.3, 6, 6, 0, "Exodar Engineering Trainer"); + player->SEND_GOSSIP_MENU(9536, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //First Aid + player->SEND_POI(-3769.5, -11479.6, 6, 6, 0, "Exodar First Aid Trainer"); + player->SEND_GOSSIP_MENU(9537, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Fishing + player->SEND_POI(-3725.5, -11385.2, 6, 6, 0, "Exodar Fishing Trainer"); + player->SEND_GOSSIP_MENU(9538, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Jewelcrafting + player->SEND_POI(-3783, -11546, 6, 6, 0, "Exodar Jewelcrafting Trainer"); + player->SEND_GOSSIP_MENU(9547, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 9: //Herbalism + player->SEND_POI(-4040.6, -11364.5, 6, 6, 0, "Exodar Herbalist Trainer"); + player->SEND_GOSSIP_MENU(9543, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 10: //Leatherworking + player->SEND_POI(-4140.6, -11776.7, 6, 6, 0, "Exodar Leatherworking Trainer"); + player->SEND_GOSSIP_MENU(9549, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 11: //Mining + player->SEND_POI(-4228, -11697, 6, 6, 0, "Exodar Mining Trainer"); + player->SEND_GOSSIP_MENU(9552, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 12: //Skinning + player->SEND_POI(-4134.97, -11760.5, 6, 6, 0, "Exodar Skinning Trainer"); + player->SEND_GOSSIP_MENU(9557, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 13: //Tailoring + player->SEND_POI(-4092.5, -11744.5, 6, 6, 0, "Exodar Tailor Trainer"); + player->SEND_GOSSIP_MENU(9559, _Creature->GetGUID()); + break; + } +} + +bool GossipSelect_guard_exodar(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + switch (sender) + { + case GOSSIP_SENDER_MAIN: SendDefaultMenu_guard_exodar(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_CLASSTRAIN: SendClassTrainerMenu_guard_exodar(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_PROFTRAIN: SendProfTrainerMenu_guard_exodar(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_BATTLEINFO: SendBattleMasterMenu_guard_exodar(player, _Creature, action); break; + } + return true; +} + +/******************************************************* + * guard_exodar end + *******************************************************/ + +CreatureAI* GetAI_guard_exodar(Creature *_Creature) +{ + return new guardAI (_Creature); +} + +/******************************************************* + * guard_ironforge start + *******************************************************/ + +bool GossipHello_guard_ironforge(Player *player, Creature *_Creature) +{ + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_AUCTIONHOUSE , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_IRONFORGE_BANK , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_DEEPRUNTRAM , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_GRYPHON , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_GUILDMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_INN , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MAILBOX , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_STABLEMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WEAPONMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 9); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BATTLEMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 10); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_CLASSTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PROFTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 12); + player->SEND_GOSSIP_MENU(2760, _Creature->GetGUID()); + return true; +} + +void SendDefaultMenu_guard_ironforge(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Auction House + player->SEND_POI(-4957.39, -911.6, 6, 6, 0, "Ironforge Auction House"); + player->SEND_GOSSIP_MENU(3014, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Bank + player->SEND_POI(-4891.91, -991.47, 6, 6, 0, "The Vault"); + player->SEND_GOSSIP_MENU(2761, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Tram + player->SEND_POI(-4835.27, -1294.69, 6, 6, 0, "Deeprun Tram"); + player->SEND_GOSSIP_MENU(3814, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Gryphon Master + player->SEND_POI(-4821.52, -1152.3, 6, 6, 0, "Ironforge Gryphon Master"); + player->SEND_GOSSIP_MENU(2762, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Guild Master + player->SEND_POI(-5021, -996.45, 6, 6, 0, "Ironforge Visitor's Center"); + player->SEND_GOSSIP_MENU(2764, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Inn + player->SEND_POI(-4850.47, -872.57, 6, 6, 0, "Stonefire Tavern"); + player->SEND_GOSSIP_MENU(2768, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Mailbox + player->SEND_POI(-4845.7, -880.55, 6, 6, 0, "Ironforge Mailbox"); + player->SEND_GOSSIP_MENU(2769, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Stable Master + player->SEND_POI(-5010.2, -1262, 6, 6, 0, "Ulbrek Firehand"); + player->SEND_GOSSIP_MENU(5986, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 9: //Weapons Trainer + player->SEND_POI(-5040, -1201.88, 6, 6, 0, "Bixi and Buliwyf"); + player->SEND_GOSSIP_MENU(4518, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 10: //Battlemaster + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ALTERACVALLEY , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ARATHIBASIN , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WARSONGULCH , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 3); + player->SEND_GOSSIP_MENU(7529, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 11: //Class Trainer + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HUNTER , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MAGE , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PALADIN , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PRIEST , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ROGUE , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WARLOCK , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WARRIOR , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_SHAMAN , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->SEND_GOSSIP_MENU(2766, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 12: //Profession Trainer + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ALCHEMY , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BLACKSMITHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_COOKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ENCHANTING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ENGINEERING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FIRSTAID , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FISHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HERBALISM , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_LEATHERWORKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 9); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MINING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 10); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_SKINNING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_TAILORING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 12); + player->SEND_GOSSIP_MENU(2793, _Creature->GetGUID()); + break; + } +} + +void SendBattleMasterMenu_guard_ironforge(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //AV + player->SEND_POI(-5047.87, -1263.77, 6, 6, 0, "Glordrum Steelbeard"); + player->SEND_GOSSIP_MENU(7483, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //AB + player->SEND_POI(-5038.37, -1266.39, 6, 6, 0, "Donal Osgood"); + player->SEND_GOSSIP_MENU(7649, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //WSG + player->SEND_POI(-5037.24, -1274.82, 6, 6, 0, "Lylandris"); + player->SEND_GOSSIP_MENU(7528, _Creature->GetGUID()); + break; + } +} + +void SendClassTrainerMenu_guard_ironforge(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Hunter + player->SEND_POI(-5023, -1253.68, 6, 6, 0, "Hall of Arms"); + player->SEND_GOSSIP_MENU(2770, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Mage + player->SEND_POI(-4627, -926.45, 6, 6, 0, "Hall of Mysteries"); + player->SEND_GOSSIP_MENU(2771, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Paladin + player->SEND_POI(-4627.02, -926.45, 6, 6, 0, "Hall of Mysteries"); + player->SEND_GOSSIP_MENU(2773, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Priest + player->SEND_POI(-4627, -926.45, 6, 6, 0, "Hall of Mysteries"); + player->SEND_GOSSIP_MENU(2772, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Rogue + player->SEND_POI(-4647.83, -1124, 6, 6, 0, "Ironforge Rogue Trainer"); + player->SEND_GOSSIP_MENU(2774, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Warlock + player->SEND_POI(-4605, -1110.45, 6, 6, 0, "Ironforge Warlock Trainer"); + player->SEND_GOSSIP_MENU(2775, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Warrior + player->SEND_POI(-5023.08, -1253.68, 6, 6, 0, "Hall of Arms"); + player->SEND_GOSSIP_MENU(2776, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Shaman + player->SEND_POI(-4732, -1147, 6, 6, 0, "Ironforge Shaman Trainer"); + //incorrect id + player->SEND_GOSSIP_MENU(2766, _Creature->GetGUID()); + break; + } +} + +void SendProfTrainerMenu_guard_ironforge(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Alchemy + player->SEND_POI(-4858.5, -1241.83, 6, 6, 0, "Berryfizz's Potions and Mixed Drinks"); + player->SEND_GOSSIP_MENU(2794, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Blacksmithing + player->SEND_POI(-4796.97, -1110.17, 6, 6, 0, "The Great Forge"); + player->SEND_GOSSIP_MENU(2795, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Cooking + player->SEND_POI(-4767.83, -1184.59, 6, 6, 0, "The Bronze Kettle"); + player->SEND_GOSSIP_MENU(2796, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Enchanting + player->SEND_POI(-4803.72, -1196.53, 6, 6, 0, "Thistlefuzz Arcanery"); + player->SEND_GOSSIP_MENU(2797, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Engineering + player->SEND_POI(-4799.56, -1250.23, 6, 6, 0, "Springspindle's Gadgets"); + player->SEND_GOSSIP_MENU(2798, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //First Aid + player->SEND_POI(-4881.6, -1153.13, 6, 6, 0, "Ironforge Physician"); + player->SEND_GOSSIP_MENU(2799, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Fishing + player->SEND_POI(-4597.91, -1091.93, 6, 6, 0, "Traveling Fisherman"); + player->SEND_GOSSIP_MENU(2800, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Herbalism + player->SEND_POI(-4876.9, -1151.92, 6, 6, 0, "Ironforge Physician"); + player->SEND_GOSSIP_MENU(2801, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 9: //Leatherworking + player->SEND_POI(-4745, -1027.57, 6, 6, 0, "Finespindle's Leather Goods"); + player->SEND_GOSSIP_MENU(2802, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 10: //Minning + player->SEND_POI(-4705.06, -1116.43, 6, 6, 0, "Deepmountain Mining Guild"); + player->SEND_GOSSIP_MENU(2804, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 11: //Skinning + player->SEND_POI(-4745, -1027.57, 6, 6, 0, "Finespindle's Leather Goods"); + player->SEND_GOSSIP_MENU(2805, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 12: //Tailoring + player->SEND_POI(-4719.60, -1056.96, 6, 6, 0, "Stonebrow's Clothier"); + player->SEND_GOSSIP_MENU(2807, _Creature->GetGUID()); + break; + } +} + +bool GossipSelect_guard_ironforge(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + switch (sender) + { + case GOSSIP_SENDER_MAIN: SendDefaultMenu_guard_ironforge(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_CLASSTRAIN: SendClassTrainerMenu_guard_ironforge(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_PROFTRAIN: SendProfTrainerMenu_guard_ironforge(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_BATTLEINFO: SendBattleMasterMenu_guard_ironforge(player, _Creature, action); break; + } + return true; +} + +/******************************************************* + * guard_ironforge end + *******************************************************/ + +CreatureAI* GetAI_guard_ironforge(Creature *_Creature) +{ + return new guardAI (_Creature); +} + +/******************************************************* + * guard_mulgore start + *******************************************************/ + +bool GossipHello_guard_mulgore(Player *player, Creature *_Creature) +{ + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BANK , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WINDRIDER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_INN , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_STABLEMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_CLASSTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PROFTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->SEND_GOSSIP_MENU(3543,_Creature->GetGUID()); + return true; +} + +void SendDefaultMenu_guard_mulgore(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Bank + player->SEND_GOSSIP_MENU(4051,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Wind rider + player->SEND_GOSSIP_MENU(4052,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Inn + player->SEND_POI(-2361.38, -349.19, 6, 6, 0, "Bloodhoof Village Inn"); + player->SEND_GOSSIP_MENU(4053,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Stable master + player->SEND_POI(-2338.86, -357.56, 6, 6, 0, "Seikwa"); + player->SEND_GOSSIP_MENU(5976,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Class trainer + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_DRUID , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HUNTER , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_SHAMAN , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WARRIOR , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->SEND_GOSSIP_MENU(4069,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Profession trainer + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ALCHEMY , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BLACKSMITHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_COOKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ENCHANTING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FIRSTAID , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FISHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HERBALISM , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_LEATHERWORKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MINING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 9); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_SKINNING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 10); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_TAILORING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->SEND_GOSSIP_MENU(4070,_Creature->GetGUID()); + break; + } +} + +void SendClassTrainerMenu_guard_mulgore(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Druid + player->SEND_POI(-2312.15, -443.69, 6, 6, 0, "Gennia Runetotem"); + player->SEND_GOSSIP_MENU(4054,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Hunter + player->SEND_POI(-2178.14, -406.14, 6, 6, 0, "Yaw Sharpmane"); + player->SEND_GOSSIP_MENU(4055,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Shaman + player->SEND_POI(-2301.5, -439.87, 6, 6, 0, "Narm Skychaser"); + player->SEND_GOSSIP_MENU(4056,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Warrior + player->SEND_POI(-2345.43, -494.11, 6, 6, 0, "Krang Stonehoof"); + player->SEND_GOSSIP_MENU(4057,_Creature->GetGUID()); + break; + } +} + +void SendProfTrainerMenu_guard_mulgore(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Alchemy + player->SEND_GOSSIP_MENU(4058,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Blacksmithing + player->SEND_GOSSIP_MENU(4059,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Cooking + player->SEND_POI(-2263.34, -287.91, 6, 6, 0, "Pyall Silentstride"); + player->SEND_GOSSIP_MENU(4060,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Enchanting + player->SEND_GOSSIP_MENU(4061,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //First Aid + player->SEND_POI(-2353.52, -355.82, 6, 6, 0, "Vira Younghoof"); + player->SEND_GOSSIP_MENU(4062,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Fishing + player->SEND_POI(-2349.21, -241.37, 6, 6, 0, "Uthan Stillwater"); + player->SEND_GOSSIP_MENU(4063,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Herbalism + player->SEND_GOSSIP_MENU(4064,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Leatherworking + player->SEND_POI(-2257.12, -288.63, 6, 6, 0, "Chaw Stronghide"); + player->SEND_GOSSIP_MENU(4065,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 9: //Mining + player->SEND_GOSSIP_MENU(4066,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 10: //Skinning + player->SEND_POI(-2252.94, -291.32, 6, 6, 0, "Yonn Deepcut"); + player->SEND_GOSSIP_MENU(4067,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 11: //Tailoring + player->SEND_GOSSIP_MENU(4068,_Creature->GetGUID()); + break; + } +} + +bool GossipSelect_guard_mulgore(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + switch (sender) + { + case GOSSIP_SENDER_MAIN: SendDefaultMenu_guard_mulgore(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_CLASSTRAIN: SendClassTrainerMenu_guard_mulgore(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_PROFTRAIN: SendProfTrainerMenu_guard_mulgore(player, _Creature, action); break; + } + return true; +} + +/******************************************************* + * guard_mulgore end + *******************************************************/ + +CreatureAI* GetAI_guard_mulgore(Creature *_Creature) +{ + return new guardAI (_Creature); +} + +/******************************************************* + * guard_orgrimmar start + *******************************************************/ + +bool GossipHello_guard_orgrimmar(Player *player, Creature *_Creature) +{ + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BANK , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WINDRIDER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_GUILDMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_INN , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MAILBOX , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_AUCTIONHOUSE , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ZEPPLINMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WEAPONMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_STABLEMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 9); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_OFFICERS , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 10); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BATTLEMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_CLASSTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 12); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PROFTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 13); + player->SEND_GOSSIP_MENU(2593,_Creature->GetGUID()); + + return true; +} + +void SendDefaultMenu_guard_orgrimmar(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Bank + player->SEND_POI(1631.51, -4375.33, 6, 6, 0, "Bank of Orgrimmar"); + player->SEND_GOSSIP_MENU(2554,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //wind rider + player->SEND_POI(1676.6, -4332.72, 6, 6, 0, "The Sky Tower"); + player->SEND_GOSSIP_MENU(2555,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //guild master + player->SEND_POI(1576.93, -4294.75, 6, 6, 0, "Horde Embassy"); + player->SEND_GOSSIP_MENU(2556,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Inn + player->SEND_POI(1644.51, -4447.27, 6, 6, 0, "Orgrimmar Inn"); + player->SEND_GOSSIP_MENU(2557,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //mailbox + player->SEND_POI(1622.53, -4388.79, 6, 6, 0, "Orgrimmar Mailbox"); + player->SEND_GOSSIP_MENU(2558,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //auction house + player->SEND_POI(1679.21, -4450.1, 6, 6, 0, "Orgrimmar Auction House"); + player->SEND_GOSSIP_MENU(3075,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //zeppelin + player->SEND_POI(1337.36, -4632.7, 6, 6, 0, "Orgrimmar Zeppelin Tower"); + player->SEND_GOSSIP_MENU(3173,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //weapon master + player->SEND_POI(2092.56, -4823.95, 6, 6, 0, "Sayoc & Hanashi"); + player->SEND_GOSSIP_MENU(4519,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 9: //stable master + player->SEND_POI(2133.12, -4663.93, 6, 6, 0, "Xon'cha"); + player->SEND_GOSSIP_MENU(5974,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 10: //officers lounge + player->SEND_POI(1633.56, -4249.37, 6, 6, 0, "Hall of Legends"); + player->SEND_GOSSIP_MENU(7046,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 11: //battlemaster + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ALTERACVALLEY , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ARATHIBASIN , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WARSONGULCH , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 3); + player->SEND_GOSSIP_MENU(7521,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 12: //class trainer + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HUNTER , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MAGE , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PRIEST , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_SHAMAN , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ROGUE , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WARLOCK , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WARRIOR , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PALADIN , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->SEND_GOSSIP_MENU(2599,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 13: //profession trainer + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ALCHEMY , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BLACKSMITHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_COOKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ENCHANTING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ENGINEERING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FIRSTAID , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FISHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HERBALISM , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_LEATHERWORKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 9); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MINING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 10); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_SKINNING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_TAILORING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 12); + player->SEND_GOSSIP_MENU(2594,_Creature->GetGUID()); + break; + } +} + +void SendBattleMasterMenu_guard_orgrimmar(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //AV + player->SEND_POI(1983.92, -4794.2, 6, 6, 0, "Hall of the Brave"); + player->SEND_GOSSIP_MENU(7484,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //AB + player->SEND_POI(1983.92, -4794.2, 6, 6, 0, "Hall of the Brave"); + player->SEND_GOSSIP_MENU(7644,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //WSG + player->SEND_POI(1983.92, -4794.2, 6, 6, 0, "Hall of the Brave"); + player->SEND_GOSSIP_MENU(7520,_Creature->GetGUID()); + break; + } +} + +void SendClassTrainerMenu_guard_orgrimmar(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Hunter + player->SEND_POI(2114.84, -4625.31, 6, 6, 0, "Orgrimmar Hunter's Hall"); + player->SEND_GOSSIP_MENU(2559,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Mage + player->SEND_POI(1451.26, -4223.33, 6, 6, 0, "Darkbriar Lodge"); + player->SEND_GOSSIP_MENU(2560,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Priest + player->SEND_POI(1442.21, -4183.24, 6, 6, 0, "Spirit Lodge"); + player->SEND_GOSSIP_MENU(2561,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Shaman + player->SEND_POI(1925.34, -4181.89, 6, 6, 0, "Thrall's Fortress"); + player->SEND_GOSSIP_MENU(2562,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Rogue + player->SEND_POI(1773.39, -4278.97, 6, 6, 0, "Shadowswift Brotherhood"); + player->SEND_GOSSIP_MENU(2563,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Warlock + player->SEND_POI(1849.57, -4359.68, 6, 6, 0, "Darkfire Enclave"); + player->SEND_GOSSIP_MENU(2564,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Warrior + player->SEND_POI(1983.92, -4794.2, 6, 6, 0, "Hall of the Brave"); + player->SEND_GOSSIP_MENU(2565,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Paladin + player->SEND_POI(1906.65, -4134.26, 6, 6, 0, "Valley of Wisdom"); + player->SEND_GOSSIP_MENU(10843,_Creature->GetGUID()); + break; + } +} + +void SendProfTrainerMenu_guard_orgrimmar(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Alchemy + player->SEND_POI(1955.17, -4475.79, 6, 6, 0, "Yelmak's Alchemy and Potions"); + player->SEND_GOSSIP_MENU(2497,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Blacksmithing + player->SEND_POI(2054.34, -4831.85, 6, 6, 0, "The Burning Anvil"); + player->SEND_GOSSIP_MENU(2499,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Cooking + player->SEND_POI(1780.96, -4481.31, 6, 6, 0, "Borstan's Firepit"); + player->SEND_GOSSIP_MENU(2500,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Enchanting + player->SEND_POI(1917.5, -4434.95, 6, 6, 0, "Godan's Runeworks"); + player->SEND_GOSSIP_MENU(2501,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Engineering + player->SEND_POI(2038.45, -4744.75, 6, 6, 0, "Nogg's Machine Shop"); + player->SEND_GOSSIP_MENU(2653,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //First Aid + player->SEND_POI(1485.21, -4160.91, 6, 6, 0, "Survival of the Fittest"); + player->SEND_GOSSIP_MENU(2502,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Fishing + player->SEND_POI(1994.15, -4655.7, 6, 6, 0, "Lumak's Fishing"); + player->SEND_GOSSIP_MENU(2503,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Herbalism + player->SEND_POI(1898.61, -4454.93, 6, 6, 0, "Jandi's Arboretum"); + player->SEND_GOSSIP_MENU(2504,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 9: //Leatherworking + player->SEND_POI(1852.82, -4562.31, 6, 6, 0, "Kodohide Leatherworkers"); + player->SEND_GOSSIP_MENU(2513,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 10: //Mining + player->SEND_POI(2029.79, -4704, 6, 6, 0, "Red Canyon Mining"); + player->SEND_GOSSIP_MENU(2515,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 11: //Skinning + player->SEND_POI(1852.82, -4562.31, 6, 6, 0, "Kodohide Leatherworkers"); + player->SEND_GOSSIP_MENU(2516,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 12: //Tailoring + player->SEND_POI(1802.66, -4560.66, 6, 6, 0, "Magar's Cloth Goods"); + player->SEND_GOSSIP_MENU(2518,_Creature->GetGUID()); + break; + } +} + +bool GossipSelect_guard_orgrimmar(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + switch (sender) + { + case GOSSIP_SENDER_MAIN: SendDefaultMenu_guard_orgrimmar(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_CLASSTRAIN: SendClassTrainerMenu_guard_orgrimmar(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_PROFTRAIN: SendProfTrainerMenu_guard_orgrimmar(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_BATTLEINFO: SendBattleMasterMenu_guard_orgrimmar(player, _Creature, action); break; + } + return true; +} + +bool ReceiveEmote_guard_orgrimmar(Player *player, Creature *_Creature, uint32 emote) +{ + if( player->GetTeam() == HORDE ) + DoReplyToTextEmote(_Creature,emote); + return true; +} + +/******************************************************* + * guard_orgrimmar end + *******************************************************/ + +CreatureAI* GetAI_guard_orgrimmar(Creature *_Creature) +{ + return new guardAI (_Creature); +} + +/******************************************************* + * guard_shattrath start + *******************************************************/ + +bool GossipHello_guard_shattrath(Player *player, Creature *_Creature) +{ + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_TAVERN , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BANK , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_INN , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FLIGHTMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MAILBOX , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_STABLEMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BATTLEMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PROFTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MANALOOM , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 9); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ALCHEMYLAB , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 10); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_GEMMERCHANT , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->SEND_GOSSIP_MENU(10321, _Creature->GetGUID()); + + return true; +} + +void SendDefaultMenu_guard_shattrath(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Tavern + player->SEND_POI(-1759.5, 5165, 6, 6, 0, "Worlds End Tavern"); + player->SEND_GOSSIP_MENU(10394, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Bank + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BANKALDOR , GOSSIP_SENDER_SEC_BANK, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BANKSCYERS , GOSSIP_SENDER_SEC_BANK, GOSSIP_ACTION_INFO_DEF + 2); + player->SEND_GOSSIP_MENU(10379, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Inn + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_INNALDOR , GOSSIP_SENDER_SEC_INN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_INNSCYERS , GOSSIP_SENDER_SEC_INN, GOSSIP_ACTION_INFO_DEF + 2); + player->SEND_GOSSIP_MENU(10382, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Flight master + player->SEND_POI(-1832, 5299, 6, 6, 0, "Flight Master"); + player->SEND_GOSSIP_MENU(10385, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Mailbox + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BANKALDOR , GOSSIP_SENDER_SEC_MAILBOX, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_INNALDOR , GOSSIP_SENDER_SEC_MAILBOX, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BANKSCYERS , GOSSIP_SENDER_SEC_MAILBOX, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_INNSCYERS , GOSSIP_SENDER_SEC_MAILBOX, GOSSIP_ACTION_INFO_DEF + 4); + player->SEND_GOSSIP_MENU(10386, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Stable master + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_STABLEALDOR , GOSSIP_SENDER_SEC_STABLEMASTER, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_STABLESCYERS , GOSSIP_SENDER_SEC_STABLEMASTER, GOSSIP_ACTION_INFO_DEF + 2); + player->SEND_GOSSIP_MENU(10387, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Battlemaster + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BATTLEMASTERALLIANCE , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BATTLEMASTERHORDE , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BATTLEMASTERARENA , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 3); + player->SEND_GOSSIP_MENU(10388, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Profession master + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ALCHEMY , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BLACKSMITHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_COOKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ENCHANTING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FIRSTAID , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_JEWELCRAFTING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_LEATHERWORKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_SKINNING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->SEND_GOSSIP_MENU(10391, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 9: //Mana Loom + player->SEND_POI(-2070, 5265.5, 6, 6, 0, "Mana Loom"); + player->SEND_GOSSIP_MENU(10503, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 10: //Alchemy Lab + player->SEND_POI(-1648.5, 5540, 6, 6, 0, "Alchemy Lab"); + player->SEND_GOSSIP_MENU(10321, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 11: //Gem Merchant + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_GEMALDOR , GOSSIP_SENDER_SEC_GEMMERCHANT, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_GEMSCYERS , GOSSIP_SENDER_SEC_GEMMERCHANT, GOSSIP_ACTION_INFO_DEF + 2); + player->SEND_GOSSIP_MENU(10697, _Creature->GetGUID()); + break; + } +} + +void SendBankMenu_guard_shattrath(Player *player, Creature *_Creature, uint32 action) +{ + if (action == GOSSIP_ACTION_INFO_DEF + 1) + { + player->SEND_POI(-1730.5, 5496, 6, 6, 0, "Aldor Bank"); + player->SEND_GOSSIP_MENU(10380, _Creature->GetGUID()); + } + if (action == GOSSIP_ACTION_INFO_DEF + 2) + { + player->SEND_POI(-1997.7, 5363, 6, 6, 0, "Scyers Bank"); + player->SEND_GOSSIP_MENU(10381, _Creature->GetGUID()); + } +} + +void SendInnMenu_guard_shattrath(Player *player, Creature *_Creature, uint32 action) +{ + if (action == GOSSIP_ACTION_INFO_DEF + 1) + { + player->SEND_POI(-1895, 5767, 6, 6, 0, "Aldor Inn"); + player->SEND_GOSSIP_MENU(10383, _Creature->GetGUID()); + } + if (action == GOSSIP_ACTION_INFO_DEF + 2) + { + player->SEND_POI(-2178, 5405, 6, 6, 0, "Scyers Inn"); + player->SEND_GOSSIP_MENU(10384, _Creature->GetGUID()); + } +} + +void SendMailboxMenu_guard_shattrath(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: + player->SEND_POI(-1730.5, 5496, 6, 6, 0, "Aldor Bank"); + player->SEND_GOSSIP_MENU(10380, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + player->SEND_POI(-1895, 5767, 6, 6, 0, "Aldor Inn"); + player->SEND_GOSSIP_MENU(10383, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: + player->SEND_POI(-1997.7, 5363, 6, 6, 0, "Scyers Bank"); + player->SEND_GOSSIP_MENU(10381, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: + player->SEND_POI(-2178, 5405, 6, 6, 0, "Scyers Inn"); + player->SEND_GOSSIP_MENU(10384, _Creature->GetGUID()); + break; + } +} + +void SendStableMasterMenu_guard_shattrath(Player *player, Creature *_Creature, uint32 action) +{ + if (action == GOSSIP_ACTION_INFO_DEF + 1) + { + player->SEND_POI(-1888.5, 5761, 6, 6, 0, "Aldor Stable"); + player->SEND_GOSSIP_MENU(10321, _Creature->GetGUID()); + } + if (action == GOSSIP_ACTION_INFO_DEF + 2) + { + player->SEND_POI(-2170, 5404, 6, 6, 0, "Scyers Stable"); + player->SEND_GOSSIP_MENU(10321, _Creature->GetGUID()); + } +} + +void SendBattleMasterMenu_guard_shattrath(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: + player->SEND_POI(-1774, 5251, 6, 6, 0, "Alliance Battlemasters"); + player->SEND_GOSSIP_MENU(10389, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + player->SEND_POI(-1963, 5263, 6, 6, 0, "Horde Battlemasters"); + player->SEND_GOSSIP_MENU(10390, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: + player->SEND_POI(-1960, 5175, 6, 6, 0, "Arena Battlemasters"); + player->SEND_GOSSIP_MENU(12510, _Creature->GetGUID()); + break; + } +} + +void SendProfTrainerMenu_guard_shattrath(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Alchemy + player->SEND_POI(-1648.5, 5534, 6, 6, 0, "Lorokeem"); + player->SEND_GOSSIP_MENU(10392, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Blacksmithing + player->SEND_POI(-1847, 5222, 6, 6, 0, "Kradu Grimblade and Zula Slagfury"); + player->SEND_GOSSIP_MENU(10400, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Cooking + player->SEND_POI(-2067.4, 5316.5, 6, 6, 0, "Jack Trapper"); + player->SEND_GOSSIP_MENU(10393, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Enchanting + player->SEND_POI(-2263.5, 5563.5, 6, 6, 0, "High Enchanter Bardolan"); + player->SEND_GOSSIP_MENU(10395, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //First Aid + player->SEND_POI(-1591, 5265.5, 6, 6, 0, "Mildred Fletcher"); + player->SEND_GOSSIP_MENU(10396, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Jewelcrafting + player->SEND_POI(-1654, 5667.5, 6, 6, 0, "Hamanar"); + player->SEND_GOSSIP_MENU(10397, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Leatherworking + player->SEND_POI(-2060.5, 5256.5, 6, 6, 0, "Darmari"); + player->SEND_GOSSIP_MENU(10399, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Skinning + player->SEND_POI(-2048, 5300, 6, 6, 0, "Seymour"); + player->SEND_GOSSIP_MENU(10398, _Creature->GetGUID()); + break; + } +} + +void SendGemMerchantMenu_guard_shattrath(Player *player, Creature *_Creature, uint32 action) +{ + if (action == GOSSIP_ACTION_INFO_DEF + 1) + { + player->SEND_POI(-1645, 5669.5, 6, 6, 0, "Aldor Gem Merchant"); + player->SEND_GOSSIP_MENU(10698, _Creature->GetGUID()); + } + if (action == GOSSIP_ACTION_INFO_DEF + 2) + { + player->SEND_POI(-2193, 5424.5, 6, 6, 0, "Scyers Gem Merchant"); + player->SEND_GOSSIP_MENU(10699, _Creature->GetGUID()); + } +} + +bool GossipSelect_guard_shattrath(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + switch (sender) + { + case GOSSIP_SENDER_MAIN: SendDefaultMenu_guard_shattrath(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_BANK: SendBankMenu_guard_shattrath(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_INN: SendInnMenu_guard_shattrath(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_STABLEMASTER: SendStableMasterMenu_guard_shattrath(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_GEMMERCHANT: SendGemMerchantMenu_guard_shattrath(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_MAILBOX: SendMailboxMenu_guard_shattrath(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_PROFTRAIN: SendProfTrainerMenu_guard_shattrath(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_BATTLEINFO: SendBattleMasterMenu_guard_shattrath(player, _Creature, action); break; + } + return true; +} + +/******************************************************* + * guard_shattrath end + *******************************************************/ + +CreatureAI* GetAI_guard_shattrath(Creature *_Creature) +{ + return new guardAI (_Creature); +} + +/******************************************************* + * guard_shattrath_aldor + *******************************************************/ + +#define SPELL_BANISHED_SHATTRATH_A 36642 +#define SPELL_BANISHED_SHATTRATH_S 36671 +#define SPELL_BANISH_TELEPORT 36643 +#define SPELL_EXILE 39533 + +struct MANGOS_DLL_DECL guard_shattrath_aldorAI : public guardAI +{ + guard_shattrath_aldorAI(Creature *c) : guardAI(c) { Reset(); } + + uint32 Exile_Timer; + uint32 Banish_Timer; + uint64 playerGUID; + bool CanTeleport; + + void Reset() + { + Banish_Timer = 5000; + Exile_Timer = 8500; + playerGUID = 0; + CanTeleport = false; + } + + void Aggro(Unit *who) {} + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if( CanTeleport ) + { + if( Exile_Timer < diff ) + { + if( Unit* temp = Unit::GetUnit(*m_creature,playerGUID) ) + { + temp->CastSpell(temp,SPELL_EXILE,true); + temp->CastSpell(temp,SPELL_BANISH_TELEPORT,true); + } + playerGUID = 0; + Exile_Timer = 8500; + CanTeleport = false; + }else Exile_Timer -= diff; + } + else if( Banish_Timer < diff ) + { + Unit* temp = m_creature->getVictim(); + if( temp && temp->GetTypeId() == TYPEID_PLAYER ) + { + DoCast(temp,SPELL_BANISHED_SHATTRATH_A); + Banish_Timer = 9000; + playerGUID = temp->GetGUID(); + if( playerGUID ) + CanTeleport = true; + } + }else Banish_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +bool GossipHello_guard_shattrath_aldor(Player *player, Creature *_Creature) +{ + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_TAVERN , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BANK , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_INN , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FLIGHTMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MAILBOX , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_STABLEMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BATTLEMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PROFTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MANALOOM , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 9); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ALCHEMYLAB , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 10); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_GEMMERCHANT , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->SEND_GOSSIP_MENU(10524, _Creature->GetGUID()); + return true; +} + +void SendDefaultMenu_guard_shattrath_aldor(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Tavern + player->SEND_POI(-1759.5, 5165, 6, 6, 0, "Worlds End Tavern"); + player->SEND_GOSSIP_MENU(10394, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Bank + player->SEND_POI(-1730.5, 5496, 6, 6, 0, "Aldor Bank"); + player->SEND_GOSSIP_MENU(10380, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Inn + player->SEND_POI(-1895, 5767, 6, 6, 0, "Aldor Inn"); + player->SEND_GOSSIP_MENU(10525, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Flight master + player->SEND_POI(-1832, 5299, 6, 6, 0, "Shattrath Flight Master"); + player->SEND_GOSSIP_MENU(10402, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Mailbox + player->SEND_POI(0, 0, 6, 6, 0, "Aldor Mailbox"); + //unknown + player->SEND_GOSSIP_MENU(10524, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Stable master + player->SEND_POI(-1888.5, 5761, 6, 6, 0, "Aldor Stable Master"); + player->SEND_GOSSIP_MENU(10527, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Battlemaster + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BATTLEMASTERALLIANCE , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BATTLEMASTERHORDE , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BATTLEMASTERARENA , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 3); + player->SEND_GOSSIP_MENU(10388, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Profession master + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ALCHEMY , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BLACKSMITHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_COOKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ENCHANTING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FIRSTAID , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_JEWELCRAFTING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_LEATHERWORKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_SKINNING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->SEND_GOSSIP_MENU(10391, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 9: //Mana Loom + player->SEND_POI(-2070, 5265.5, 6, 6, 0, "Mana Loom"); + player->SEND_GOSSIP_MENU(10522, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 10: //Alchemy Lab + player->SEND_POI(-1648.5, 5540, 6, 6, 0, "Alchemy Lab"); + player->SEND_GOSSIP_MENU(10696, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 11: //Gem Merchant + player->SEND_POI(-1645, 5669.5, 6, 6, 0, "Aldor Gem Merchant"); + player->SEND_GOSSIP_MENU(10411, _Creature->GetGUID()); + break; + } +} + +void SendProfTrainerMenu_guard_shattrath_aldor(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Alchemy + player->SEND_POI(-1648.5, 5534, 6, 6, 0, "Lorokeem"); + player->SEND_GOSSIP_MENU(10392, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Blacksmithing + player->SEND_POI(-1847, 5222, 6, 6, 0, "Kradu Grimblade and Zula Slagfury"); + player->SEND_GOSSIP_MENU(10400, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Cooking + player->SEND_POI(-2067.4, 5316.5, 6, 6, 0, "Jack Trapper"); + player->SEND_GOSSIP_MENU(10393, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Enchanting + player->SEND_POI(-2263.5, 5563.5, 6, 6, 0, "High Enchanter Bardolan"); + player->SEND_GOSSIP_MENU(10528, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //First Aid + player->SEND_POI(-1591, 5265.5, 6, 6, 0, "Mildred Fletcher"); + player->SEND_GOSSIP_MENU(10396, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Jewelcrafting + player->SEND_POI(-1654, 5667.5, 6, 6, 0, "Hamanar"); + player->SEND_GOSSIP_MENU(10529, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Leatherworking + player->SEND_POI(-2060.5, 5256.5, 6, 6, 0, "Darmari"); + player->SEND_GOSSIP_MENU(10399, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Skinning + player->SEND_POI(-2048, 5300, 6, 6, 0, "Seymour"); + player->SEND_GOSSIP_MENU(10419, _Creature->GetGUID()); + break; + } +} + +bool GossipSelect_guard_shattrath_aldor(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + switch (sender) + { + case GOSSIP_SENDER_MAIN: SendDefaultMenu_guard_shattrath_aldor(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_PROFTRAIN: SendProfTrainerMenu_guard_shattrath_aldor(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_BATTLEINFO: SendBattleMasterMenu_guard_shattrath(player, _Creature, action); break; + } + return true; +} + +/******************************************************* + * guard_shattrath_aldor end + *******************************************************/ + +CreatureAI* GetAI_guard_shattrath_aldor(Creature *_Creature) +{ + return new guard_shattrath_aldorAI (_Creature); +} + +/******************************************************* + * guard_shattrath_scryer + *******************************************************/ + +struct MANGOS_DLL_DECL guard_shattrath_scryerAI : public guardAI +{ + guard_shattrath_scryerAI(Creature *c) : guardAI(c) { Reset(); } + + uint32 Exile_Timer; + uint32 Banish_Timer; + uint64 playerGUID; + bool CanTeleport; + + void Reset() + { + Banish_Timer = 5000; + Exile_Timer = 8500; + playerGUID = 0; + CanTeleport = false; + } + + void Aggro(Unit *who) {} + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if( CanTeleport ) + { + if( Exile_Timer < diff ) + { + if( Unit* temp = Unit::GetUnit(*m_creature,playerGUID) ) + { + temp->CastSpell(temp,SPELL_EXILE,true); + temp->CastSpell(temp,SPELL_BANISH_TELEPORT,true); + } + playerGUID = 0; + Exile_Timer = 8500; + CanTeleport = false; + }else Exile_Timer -= diff; + } + else if( Banish_Timer < diff ) + { + Unit* temp = m_creature->getVictim(); + if( temp && temp->GetTypeId() == TYPEID_PLAYER ) + { + DoCast(temp,SPELL_BANISHED_SHATTRATH_S); + Banish_Timer = 9000; + playerGUID = temp->GetGUID(); + if( playerGUID ) + CanTeleport = true; + } + }else Banish_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +bool GossipHello_guard_shattrath_scryer(Player *player, Creature *_Creature) +{ + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_TAVERN , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BANK , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_INN , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FLIGHTMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MAILBOX , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_STABLEMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BATTLEMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PROFTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MANALOOM , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 9); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ALCHEMYLAB , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 10); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_GEMMERCHANT , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->SEND_GOSSIP_MENU(10430, _Creature->GetGUID()); + return true; +} + +void SendDefaultMenu_guard_shattrath_scryer(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Tavern + player->SEND_POI(-1759.5, 5165, 6, 6, 0, "Worlds End Tavern"); + player->SEND_GOSSIP_MENU(10431, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Bank + player->SEND_POI(-1996.6, 5363.7, 6, 6, 0, "Scryer Bank"); + player->SEND_GOSSIP_MENU(10432, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Inn + player->SEND_POI(-2176.6, 5405.8, 6, 6, 0, "Scryer Inn"); + player->SEND_GOSSIP_MENU(10433, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Flight master + player->SEND_POI(-1832, 5299, 6, 6, 0, "Shattrath Flight Master"); + player->SEND_GOSSIP_MENU(10435, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Mailbox + player->SEND_POI(-2174.3, 5411.4, 6, 6, 0, "Scryer Mailbox"); + player->SEND_GOSSIP_MENU(10436, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Stable master + player->SEND_POI(-2169.9, 5405.1, 6, 6, 0, "Scryer Stable Master"); + player->SEND_GOSSIP_MENU(10437, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Battlemaster + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BATTLEMASTERALLIANCE , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BATTLEMASTERHORDE , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BATTLEMASTERARENA , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 3); + player->SEND_GOSSIP_MENU(10438, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Profession master + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ALCHEMY , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BLACKSMITHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_COOKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ENCHANTING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FIRSTAID , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_JEWELCRAFTING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_LEATHERWORKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_SKINNING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->SEND_GOSSIP_MENU(10504, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 9: //Mana Loom + player->SEND_POI(-2070, 5265.5, 6, 6, 0, "Mana Loom"); + player->SEND_GOSSIP_MENU(10522, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 10: //Alchemy Lab + player->SEND_POI(-1648.5, 5540, 6, 6, 0, "Alchemy Lab"); + player->SEND_GOSSIP_MENU(10701, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 11: //Gem Merchant + player->SEND_POI(-1645, 5669.5, 6, 6, 0, "Scryer Gem Merchant"); + player->SEND_GOSSIP_MENU(10702, _Creature->GetGUID()); + break; + } +} + +void SendProfTrainerMenu_guard_shattrath_scryer(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Alchemy + player->SEND_POI(-1648.5, 5534, 6, 6, 0, "Lorokeem"); + player->SEND_GOSSIP_MENU(10516, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Blacksmithing + player->SEND_POI(-1847, 5222, 6, 6, 0, "Kradu Grimblade and Zula Slagfury"); + player->SEND_GOSSIP_MENU(10517, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Cooking + player->SEND_POI(-2067.4, 5316.5, 6, 6, 0, "Jack Trapper"); + player->SEND_GOSSIP_MENU(10518, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Enchanting + player->SEND_POI(-2263.5, 5563.5, 6, 6, 0, "High Enchanter Bardolan"); + player->SEND_GOSSIP_MENU(10519, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //First Aid + player->SEND_POI(-1591, 5265.5, 6, 6, 0, "Mildred Fletcher"); + player->SEND_GOSSIP_MENU(10520, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Jewelcrafting + player->SEND_POI(-1654, 5667.5, 6, 6, 0, "Hamanar"); + player->SEND_GOSSIP_MENU(10521, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Leatherworking + player->SEND_POI(-2060.5, 5256.5, 6, 6, 0, "Darmari"); + player->SEND_GOSSIP_MENU(10523, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Skinning + player->SEND_POI(-2048, 5300, 6, 6, 0, "Seymour"); + player->SEND_GOSSIP_MENU(10523, _Creature->GetGUID()); + break; + } +} + +bool GossipSelect_guard_shattrath_scryer(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + switch (sender) + { + case GOSSIP_SENDER_MAIN: SendDefaultMenu_guard_shattrath_scryer(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_PROFTRAIN: SendProfTrainerMenu_guard_shattrath_scryer(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_BATTLEINFO: SendBattleMasterMenu_guard_shattrath(player, _Creature, action); break; + } + return true; +} + +/******************************************************* + * guard_shattrath_scryer end + *******************************************************/ + +CreatureAI* GetAI_guard_shattrath_scryer(Creature *_Creature) +{ + return new guard_shattrath_scryerAI (_Creature); +} + +/******************************************************* + * guard_silvermoon start + *******************************************************/ + +bool GossipHello_guard_silvermoon(Player *player, Creature *_Creature) +{ + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_AUCTIONHOUSE , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BANK , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_GUILDMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_INN , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MAILBOX , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_STABLEMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WEAPONMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WINDRIDER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BATTLEMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 9); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_CLASSTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 10); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PROFTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->SEND_GOSSIP_MENU(9316, _Creature->GetGUID()); + return true; +} + +void SendDefaultMenu_guard_silvermoon(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Auction house + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_AH_SILVERMOON_1 , GOSSIP_SENDER_SEC_AUCTIONHOUSE, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_AH_SILVERMOON_2 , GOSSIP_SENDER_SEC_AUCTIONHOUSE, GOSSIP_ACTION_INFO_DEF + 2); + player->SEND_GOSSIP_MENU(9317, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Bank + player->SEND_POI(9808.4, -7488.16, 6, 6, 0, "Silvermoon Bank"); + player->SEND_GOSSIP_MENU(9322, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Guild master + player->SEND_POI(9474.97, -7345.21, 6, 6, 0, "Tandrine"); + player->SEND_GOSSIP_MENU(9324, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Inn + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_INN_SILVERMOON_1 , GOSSIP_SENDER_SEC_INN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_INN_SILVERMOON_2 , GOSSIP_SENDER_SEC_INN, GOSSIP_ACTION_INFO_DEF + 2); + player->SEND_GOSSIP_MENU(9602, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Mailbox + player->SEND_POI(9658.33, -7492.17, 6, 6, 0, "Silvermoon Mailbox"); + player->SEND_GOSSIP_MENU(9326, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Stable master + player->SEND_POI(9904.95, -7404.31, 6, 6, 0, "Shalenn"); + player->SEND_GOSSIP_MENU(9327, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Weapon trainer + player->SEND_POI(9841.17, -7505.13, 6, 6, 0, "Ileda"); + player->SEND_GOSSIP_MENU(9328, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Wind master + player->SEND_POI(9378.45, -7163.94, 6, 6, 0, "Silvermoon Wind Master"); + player->SEND_GOSSIP_MENU(10181, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 9: //Battlemaster + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ALTERACVALLEY , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ARATHIBASIN , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ARENA , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_EYEOFTHESTORM , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WARSONGULCH , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 5); + player->SEND_GOSSIP_MENU(9329, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 10: //Class trainer + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_DRUID , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HUNTER , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MAGE , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PALADIN , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PRIEST , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ROGUE , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WARLOCK , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->SEND_GOSSIP_MENU(9331, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 11: //Profession trainer + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ALCHEMY , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BLACKSMITHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_COOKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ENCHANTING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ENGINEERING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FIRSTAID , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FISHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_JEWELCRAFTING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HERBALISM , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 9); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_LEATHERWORKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 10); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MINING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_SKINNING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 12); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_TAILORING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 13); + player->SEND_GOSSIP_MENU(9338, _Creature->GetGUID()); + break; + } +} + +void SendAuctionhouseMenu_guard_silvermoon(Player *player, Creature *_Creature, uint32 action) +{ + if (action == GOSSIP_ACTION_INFO_DEF + 1) + { + player->SEND_POI(9644.47, -7140.22, 6, 6, 0, "Western Auction House"); + player->SEND_GOSSIP_MENU(9318, _Creature->GetGUID()); + } + if (action == GOSSIP_ACTION_INFO_DEF + 2) + { + player->SEND_POI(9683.27, -7521.22, 6, 6, 0, "Royal Exchange Auction House"); + player->SEND_GOSSIP_MENU(9319, _Creature->GetGUID()); + } +} + +void SendInnMenu_guard_silvermoon(Player *player, Creature *_Creature, uint32 action) +{ + if (action == GOSSIP_ACTION_INFO_DEF + 1) + { + player->SEND_POI(9677.7, -7368, 6, 6, 0, "Silvermoon City Inn"); + player->SEND_GOSSIP_MENU(9325, _Creature->GetGUID()); + } + if (action == GOSSIP_ACTION_INFO_DEF + 2) + { + player->SEND_POI(9561.1, -7517.5, 6, 6, 0, "Wayfarer's Rest tavern"); + player->SEND_GOSSIP_MENU(9603, _Creature->GetGUID()); + } +} + +void SendBattleMasterMenu_guard_silvermoon(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //AV + player->SEND_POI(9850.49, -7572.26, 6, 6, 0, "Gurak"); + player->SEND_GOSSIP_MENU(9329, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //AB + player->SEND_POI(9857.18, -7564.36, 6, 6, 0, "Karen Wentworth"); + player->SEND_GOSSIP_MENU(9329, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //A + player->SEND_POI(9850.6, -7559.25, 6, 6, 0, "Bipp Glizzitor"); + player->SEND_GOSSIP_MENU(9329, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //EOS + player->SEND_POI(9857.18, -7564.36, 6, 6, 0, "Karen Wentworth"); + player->SEND_GOSSIP_MENU(9329, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //WSG + player->SEND_POI(9845.45, -7562.58, 6, 6, 0, "Krukk"); + player->SEND_GOSSIP_MENU(9329, _Creature->GetGUID()); + break; + } +} + +void SendClassTrainerMenu_guard_silvermoon(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Druid + player->SEND_POI(9700.55, -7262.57, 6, 6, 0, "Harene Plainwalker"); + player->SEND_GOSSIP_MENU(9330, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Hunter + player->SEND_POI(9927.48, -7426.14, 6, 6, 0, "Zandine"); + player->SEND_GOSSIP_MENU(9332, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Mage + player->SEND_POI(9995.07, -7118.17, 6, 6, 0, "Quithas"); + player->SEND_GOSSIP_MENU(9333, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Paladin + player->SEND_POI(9850.22, -7516.93, 6, 6, 0, "Champion Bachi"); + player->SEND_GOSSIP_MENU(9334, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Priest + player->SEND_POI(9926.79, -7066.66, 6, 6, 0, "Belestra"); + player->SEND_GOSSIP_MENU(9335, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Rogue + player->SEND_POI(9739.88, -7374.33, 6, 6, 0, "Zelanis"); + player->SEND_GOSSIP_MENU(9336, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Warlock + player->SEND_POI(9787.57, -7284.63, 6, 6, 0, "Alamma"); + player->SEND_GOSSIP_MENU(9337, _Creature->GetGUID()); + break; + } +} + +void SendProfTrainerMenu_guard_silvermoon(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Alchemy + player->SEND_POI(9998.09, -7214.36, 6, 6, 0, "Silvermoon Alchemy Trainer"); + player->SEND_GOSSIP_MENU(9316, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Blacksmithing + player->SEND_POI(9841.43, -7361.53, 6, 6, 0, "Silvermoon Blacksmithing Trainer"); + player->SEND_GOSSIP_MENU(9340, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Cooking + player->SEND_POI(9577.26, -7243.6, 6, 6, 0, "Silvermoon Cooking Trainer"); + player->SEND_GOSSIP_MENU(9316, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Enchanting + player->SEND_POI(9962.57, -7246.18, 6, 6, 0, "Silvermoon Enchanting Trainer"); + player->SEND_GOSSIP_MENU(9341, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Engineering + player->SEND_POI(9820.18, -7329.56, 6, 6, 0, "Silvermoon Engineering Trainer"); + player->SEND_GOSSIP_MENU(9316, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //First Aid + player->SEND_POI(9579.8, -7343.71, 6, 6, 0, "Silvermoon First Aid Trainer"); + player->SEND_GOSSIP_MENU(9316, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Fishing + player->SEND_POI(9602.73, -7328.3, 6, 6, 0, "Silvermoon Fishing Trainer"); + player->SEND_GOSSIP_MENU(9316, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Jewelcrafting + player->SEND_POI(9553.54, -7506.43, 6, 6, 0, "Silvermoon Jewelcrafting Trainer"); + player->SEND_GOSSIP_MENU(9346, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 9: //Herbalism + player->SEND_POI(10004.4, -7216.86, 6, 6, 0, "Silvermoon Herbalism Trainer"); + player->SEND_GOSSIP_MENU(9316, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 10: //Leatherworking + player->SEND_POI(9503.72, -7430.16, 6, 6, 0, "Silvermoon Leatherworking Trainer"); + player->SEND_GOSSIP_MENU(9347, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 11: //Mining + player->SEND_POI(9805.1, -7355.56, 6, 6, 0, "Silvermoon Mining Trainer"); + player->SEND_GOSSIP_MENU(9348, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 12: //Skinning + player->SEND_POI(9513.37, -7429.4, 6, 6, 0, "Silvermoon Skinning Trainer"); + player->SEND_GOSSIP_MENU(9316, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 13: //Tailoring + player->SEND_POI(9750.55, -7095.28, 6, 6, 0, "Silvermoon Tailor"); + player->SEND_GOSSIP_MENU(9350, _Creature->GetGUID()); + break; + } +} + +bool GossipSelect_guard_silvermoon(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + switch (sender) + { + case GOSSIP_SENDER_MAIN: SendDefaultMenu_guard_silvermoon(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_AUCTIONHOUSE: SendAuctionhouseMenu_guard_silvermoon(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_INN: SendInnMenu_guard_silvermoon(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_CLASSTRAIN: SendClassTrainerMenu_guard_silvermoon(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_PROFTRAIN: SendProfTrainerMenu_guard_silvermoon(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_BATTLEINFO: SendBattleMasterMenu_guard_silvermoon(player, _Creature, action); break; + } + return true; +} + +/******************************************************* + * guard_silvermoon end + *******************************************************/ + +CreatureAI* GetAI_guard_silvermoon(Creature *_Creature) +{ + return new guardAI (_Creature); +} + +/******************************************************* + * guard_stormwind start + *******************************************************/ + +bool GossipHello_guard_stormwind(Player *player, Creature *_Creature) +{ + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_AUCTIONHOUSE , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_STORMWIND_BANK , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_DEEPRUNTRAM , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_INN , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_GRYPHON , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_GUILDMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MAILBOX , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_STABLEMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WEAPONMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 9); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_OFFICERS , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 10); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BATTLEMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_CLASSTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 12); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PROFTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 13); + player->SEND_GOSSIP_MENU(933,_Creature->GetGUID()); + return true; +} + +void SendDefaultMenu_guard_stormwind(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Auction House + player->SEND_POI(-8811.46, 667.46, 6, 6, 0, "Stormwind Auction House"); + player->SEND_GOSSIP_MENU(3834,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Bank + player->SEND_POI(-8916.87, 622.87, 6, 6, 0, "Stormwind Bank"); + player->SEND_GOSSIP_MENU(764,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Deeprun tram + player->SEND_POI(-8378.88, 554.23, 6, 6, 0, "The Deeprun Tram"); + player->SEND_GOSSIP_MENU(3813,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Inn + player->SEND_POI(-8869.0, 675.4, 6, 6, 0, "The Gilded Rose"); + player->SEND_GOSSIP_MENU(3860,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Gryphon Master + player->SEND_POI(-8837.0, 493.5, 6, 6, 0, "Stormwind Gryphon Master"); + player->SEND_GOSSIP_MENU(879,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Guild Master + player->SEND_POI(-8894.0, 611.2, 6, 6, 0, "Stormwind Vistor`s Center"); + player->SEND_GOSSIP_MENU(882,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Mailbox + player->SEND_POI(-8876.48, 649.18, 6, 6, 0, "Stormwind Mailbox"); + player->SEND_GOSSIP_MENU(3861,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Stable Master + player->SEND_POI(-8433.0, 554.7, 6, 6, 0, "Jenova Stoneshield"); + player->SEND_GOSSIP_MENU(5984,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 9: //Weapon Trainer + player->SEND_POI(-8797.0, 612.8, 6, 6, 0, "Woo Ping"); + player->SEND_GOSSIP_MENU(4516,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 10: //Officers Lounge + player->SEND_POI(-8759.92, 399.69, 6, 6, 0, "Champions` Hall"); + player->SEND_GOSSIP_MENU(7047,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 11: //Battlemasters + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ALTERACVALLEY , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ARATHIBASIN , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WARSONGULCH , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 3); + player->SEND_GOSSIP_MENU(7499,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 12: //Class trainers + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MAGE , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ROGUE , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WARRIOR , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_DRUID , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PRIEST , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PALADIN , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HUNTER , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WARLOCK , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_SHAMAN , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 9); + player->SEND_GOSSIP_MENU(898,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 13: //Profession trainers + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ALCHEMY , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BLACKSMITHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_COOKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ENCHANTING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ENGINEERING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FIRSTAID , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FISHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HERBALISM , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_LEATHERWORKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 9); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MINING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 10); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_SKINNING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_TAILORING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 12); + player->SEND_GOSSIP_MENU(918,_Creature->GetGUID()); + break; + } +} + +void SendBattleMasterMenu_guard_stormwind(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //AV + player->SEND_POI(-8443.88, 335.99, 6, 6, 0, "Thelman Slatefist"); + player->SEND_GOSSIP_MENU(7500, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //AB + player->SEND_POI(-8443.88, 335.99, 6, 6, 0, "Lady Hoteshem"); + player->SEND_GOSSIP_MENU(7650, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //WSG + player->SEND_POI(-8443.88, 335.99, 6, 6, 0, "Elfarran"); + player->SEND_GOSSIP_MENU(7501, _Creature->GetGUID()); + break; + } +} + +void SendClassTrainerMenu_guard_stormwind(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Mage + player->SEND_POI(-9012.0, 867.6, 6, 6, 0, "Wizard`s Sanctum"); + player->SEND_GOSSIP_MENU(899,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Rogue + player->SEND_POI(-8753.0, 367.8, 6, 6, 0, "Stormwind - Rogue House"); + player->SEND_GOSSIP_MENU(900,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Warrior + player->SEND_POI(-8624.54, 402.61, 6, 6, 0, "Pig and Whistle Tavern"); + player->SEND_GOSSIP_MENU(901,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Druid + player->SEND_POI(-8751.0, 1124.5, 6, 6, 0, "The Park"); + player->SEND_GOSSIP_MENU(902,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Priest + player->SEND_POI(-8512.0, 862.4, 6, 6, 0, "Catedral Of Light"); + player->SEND_GOSSIP_MENU(903,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Paladin + player->SEND_POI(-8577.0, 881.7, 6, 6, 0, "Catedral Of Light"); + player->SEND_GOSSIP_MENU(904,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Hunter + player->SEND_POI(-8413.0, 541.5, 6, 6, 0, "Hunter Lodge"); + player->SEND_GOSSIP_MENU(905,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Warlock + player->SEND_POI(-8948.91, 998.35, 6, 6, 0, "The Slaughtered Lamb"); + player->SEND_GOSSIP_MENU(906,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 9: //Shaman + player->SEND_POI(-9033, 550, 6, 6, 0, "Valley Of Heroes"); + //incorrect id + player->SEND_GOSSIP_MENU(2593,_Creature->GetGUID()); + break; + } +} + +void SendProfTrainerMenu_guard_stormwind(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Alchemy + player->SEND_POI(-8988.0, 759.60, 6, 6, 0, "Alchemy Needs"); + player->SEND_GOSSIP_MENU(919,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Blacksmithing + player->SEND_POI(-8424.0, 616.9, 6, 6, 0, "Therum Deepforge"); + player->SEND_GOSSIP_MENU(920,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Cooking + player->SEND_POI(-8611.0, 364.6, 6, 6, 0, "Pig and Whistle Tavern"); + player->SEND_GOSSIP_MENU(921,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Enchanting + player->SEND_POI(-8858.0, 803.7, 6, 6, 0, "Lucan Cordell"); + player->SEND_GOSSIP_MENU(941,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Engineering + player->SEND_POI(-8347.0, 644.1, 6, 6, 0, "Lilliam Sparkspindle"); + player->SEND_GOSSIP_MENU(922,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //First Aid + player->SEND_POI(-8513.0, 801.8, 6, 6, 0, "Shaina Fuller"); + player->SEND_GOSSIP_MENU(923,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Fishing + player->SEND_POI(-8803.0, 767.5, 6, 6, 0, "Arnold Leland"); + player->SEND_GOSSIP_MENU(940,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Herbalism + player->SEND_POI(-8967.0, 779.5, 6, 6, 0, "Alchemy Needs"); + player->SEND_GOSSIP_MENU(924,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 9: //Leatherworking + player->SEND_POI(-8726.0, 477.4, 6, 6, 0, "The Protective Hide"); + player->SEND_GOSSIP_MENU(925,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 10: //Mining + player->SEND_POI(-8434.0, 692.8, 6, 6, 0, "Gelman Stonehand"); + player->SEND_GOSSIP_MENU(927,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 11: //Skinning + player->SEND_POI(-8716.0, 469.4, 6, 6, 0, "The Protective Hide"); + player->SEND_GOSSIP_MENU(928,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 12: //Tailoring + player->SEND_POI(-8938.0, 800.7, 6, 6, 0, "Duncan`s Textiles"); + player->SEND_GOSSIP_MENU(929,_Creature->GetGUID()); + break; + } +} + +bool GossipSelect_guard_stormwind(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + switch (sender) + { + case GOSSIP_SENDER_MAIN: SendDefaultMenu_guard_stormwind(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_CLASSTRAIN: SendClassTrainerMenu_guard_stormwind(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_PROFTRAIN: SendProfTrainerMenu_guard_stormwind(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_BATTLEINFO: SendBattleMasterMenu_guard_stormwind(player, _Creature, action); break; + } + return true; +} + +bool ReceiveEmote_guard_stormwind(Player *player, Creature *_Creature, uint32 emote) +{ + if( player->GetTeam() == ALLIANCE ) + DoReplyToTextEmote(_Creature,emote); + return true; +} + +/******************************************************* + * guard_stormwind end + *******************************************************/ + +CreatureAI* GetAI_guard_stormwind(Creature *_Creature) +{ + return new guardAI (_Creature); +} + +/******************************************************* + * guard_teldrassil start + *******************************************************/ + +bool GossipHello_guard_teldrassil(Player *player, Creature *_Creature) +{ + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BANK , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FERRY , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_GUILDMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_INN , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_STABLEMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_CLASSTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PROFTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->SEND_GOSSIP_MENU(4316,_Creature->GetGUID()); + return true; +} + +void SendDefaultMenu_guard_teldrassil(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Bank + player->SEND_GOSSIP_MENU(4317,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Rut`theran + player->SEND_GOSSIP_MENU(4318,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Guild master + player->SEND_GOSSIP_MENU(4319,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Inn + player->SEND_POI(9821.49, 960.13, 6, 6, 0, "Dolanaar Inn"); + player->SEND_GOSSIP_MENU(4320,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //stable master + player->SEND_POI(9808.37, 931.1, 6, 6, 0, "Seriadne"); + player->SEND_GOSSIP_MENU(5982,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //class trainer + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_DRUID , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HUNTER , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PRIEST , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ROGUE , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WARRIOR , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->SEND_GOSSIP_MENU(4264,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //profession trainer + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ALCHEMY , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_COOKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ENCHANTING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FIRSTAID , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FISHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HERBALISM , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_LEATHERWORKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_SKINNING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_TAILORING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 9); + player->SEND_GOSSIP_MENU(4273,_Creature->GetGUID()); + break; + } +} + +void SendClassTrainerMenu_guard_teldrassil(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Druid + player->SEND_POI(9741.58, 963.7, 6, 6, 0, "Kal"); + player->SEND_GOSSIP_MENU(4323,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Hunter + player->SEND_POI(9815.12, 926.28, 6, 6, 0, "Dazalar"); + player->SEND_GOSSIP_MENU(4324,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Priest + player->SEND_POI(9906.16, 986.63, 6, 6, 0, "Laurna Morninglight"); + player->SEND_GOSSIP_MENU(4325,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Rogue + player->SEND_POI(9789, 942.86, 6, 6, 0, "Jannok Breezesong"); + player->SEND_GOSSIP_MENU(4326,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Warrior + player->SEND_POI(9821.96, 950.61, 6, 6, 0, "Kyra Windblade"); + player->SEND_GOSSIP_MENU(4327,_Creature->GetGUID()); + break; + } +} + +void SendProfTrainerMenu_guard_teldrassil(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Alchemy + player->SEND_POI(9767.59, 878.81, 6, 6, 0, "Cyndra Kindwhisper"); + player->SEND_GOSSIP_MENU(4329,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Cooking + player->SEND_POI(9751.19, 906.13, 6, 6, 0, "Zarrin"); + player->SEND_GOSSIP_MENU(4330,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Enchanting + player->SEND_POI(10677.59, 1946.56, 6, 6, 0, "Alanna Raveneye"); + player->SEND_GOSSIP_MENU(4331,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //First Aid + player->SEND_POI(9903.12, 999, 6, 6, 0, "Byancie"); + player->SEND_GOSSIP_MENU(4332,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Fishing + player->SEND_GOSSIP_MENU(4333,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Herbalism + player->SEND_POI(9773.78, 875.88, 6, 6, 0, "Malorne Bladeleaf"); + player->SEND_GOSSIP_MENU(4334,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Leatherworking + player->SEND_POI(10152.59, 1681.46, 6, 6, 0, "Nadyia Maneweaver"); + player->SEND_GOSSIP_MENU(4335,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Skinning + player->SEND_POI(10135.59, 1673.18, 6, 6, 0, "Radnaal Maneweaver"); + player->SEND_GOSSIP_MENU(4336,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 9: //Tailoring + player->SEND_GOSSIP_MENU(4337,_Creature->GetGUID()); + break; + } +} + +bool GossipSelect_guard_teldrassil(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + switch (sender) + { + case GOSSIP_SENDER_MAIN: SendDefaultMenu_guard_teldrassil(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_CLASSTRAIN: SendClassTrainerMenu_guard_teldrassil(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_PROFTRAIN: SendProfTrainerMenu_guard_teldrassil(player, _Creature, action); break; + } + return true; +} + +/******************************************************* + * guard_teldrassil end + *******************************************************/ + +CreatureAI* GetAI_guard_teldrassil(Creature *_Creature) +{ + return new guardAI (_Creature); +} + +/******************************************************* + * guard_tirisfal start + *******************************************************/ + +bool GossipHello_guard_tirisfal(Player *player, Creature *_Creature) +{ + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BANK , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BATHANDLER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_INN , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_STABLEMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_CLASSTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PROFTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->SEND_GOSSIP_MENU(4097,_Creature->GetGUID()); + return true; +} + +void SendDefaultMenu_guard_tirisfal(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Bank + player->SEND_GOSSIP_MENU(4074,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //bat handler + player->SEND_GOSSIP_MENU(4075,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Inn + player->SEND_POI(2246.68, 241.89, 6, 6, 0, "Gallows` End Tavern"); + player->SEND_GOSSIP_MENU(4076,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Stable Master + player->SEND_POI(2267.66, 319.32, 6, 6, 0, "Morganus"); + player->SEND_GOSSIP_MENU(5978,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Class trainer + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MAGE , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PRIEST , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ROGUE , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WARLOCK , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WARRIOR , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->SEND_GOSSIP_MENU(4292,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Profession trainer + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ALCHEMY , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BLACKSMITHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_COOKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ENCHANTING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ENGINEERING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FIRSTAID , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FISHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HERBALISM , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_LEATHERWORKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 9); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MINING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 10); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_SKINNING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_TAILORING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 12); + player->SEND_GOSSIP_MENU(4096,_Creature->GetGUID()); + break; + } +} + +void SendClassTrainerMenu_guard_tirisfal(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Mage + player->SEND_POI(2259.18, 240.93, 6, 6, 0, "Cain Firesong"); + player->SEND_GOSSIP_MENU(4077,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Priest + player->SEND_POI(2259.18, 240.93, 6, 6, 0, "Dark Cleric Beryl"); + player->SEND_GOSSIP_MENU(4078,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Rogue + player->SEND_POI(2259.18, 240.93, 6, 6, 0, "Marion Call"); + player->SEND_GOSSIP_MENU(4079,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Warlock + player->SEND_POI(2259.18, 240.93, 6, 6, 0, "Rupert Boch"); + player->SEND_GOSSIP_MENU(4080,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Warrior + player->SEND_POI(2256.48, 240.32, 6, 6, 0, "Austil de Mon"); + player->SEND_GOSSIP_MENU(4081,_Creature->GetGUID()); + break; + } +} + +void SendProfTrainerMenu_guard_tirisfal(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Alchemy + player->SEND_POI(2263.25, 344.23, 6, 6, 0, "Carolai Anise"); + player->SEND_GOSSIP_MENU(4082,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Blacksmithing + player->SEND_GOSSIP_MENU(4083,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Cooking + player->SEND_GOSSIP_MENU(4084,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Enchanting + player->SEND_POI(2250.35, 249.12, 6, 6, 0, "Vance Undergloom"); + player->SEND_GOSSIP_MENU(4085,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Engineering + player->SEND_GOSSIP_MENU(4086,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //First Aid + player->SEND_POI(2246.68, 241.89, 6, 6, 0, "Nurse Neela"); + player->SEND_GOSSIP_MENU(4087,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Fishing + player->SEND_POI(2292.37, -10.72, 6, 6, 0, "Clyde Kellen"); + player->SEND_GOSSIP_MENU(4088,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Herbalism + player->SEND_POI(2268.21, 331.69, 6, 6, 0, "Faruza"); + player->SEND_GOSSIP_MENU(4089,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 9: //Leatherworking + player->SEND_POI(2027, 78.72, 6, 6, 0, "Shelene Rhobart"); + player->SEND_GOSSIP_MENU(4090,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 10: //Mining + player->SEND_GOSSIP_MENU(4091,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 11: //Skinning + player->SEND_POI(2027, 78.72, 6, 6, 0, "Rand Rhobart"); + player->SEND_GOSSIP_MENU(4092,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 12: //Tailoring + player->SEND_POI(2160.45, 659.93, 6, 6, 0, "Bowen Brisboise"); + player->SEND_GOSSIP_MENU(4093,_Creature->GetGUID()); + break; + } +} + +bool GossipSelect_guard_tirisfal(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + switch (sender) + { + case GOSSIP_SENDER_MAIN: SendDefaultMenu_guard_tirisfal(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_CLASSTRAIN: SendClassTrainerMenu_guard_tirisfal(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_PROFTRAIN: SendProfTrainerMenu_guard_tirisfal(player, _Creature, action); break; + } + return true; +} + +/******************************************************* + * guard_tirisfal end + *******************************************************/ + +CreatureAI* GetAI_guard_tirisfal(Creature *_Creature) +{ + return new guardAI (_Creature); +} + +/******************************************************* + * guard_undercity start + *******************************************************/ + +bool GossipHello_guard_undercity(Player *player, Creature *_Creature) +{ + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BANK , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BATHANDLER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_GUILDMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_INN , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MAILBOX , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_AUCTIONHOUSE , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ZEPPLINMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WEAPONMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_STABLEMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 9); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BATTLEMASTER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 10); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_CLASSTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PROFTRAINER , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 12); + player->SEND_GOSSIP_MENU(3543,_Creature->GetGUID()); + return true; +} + +void SendDefaultMenu_guard_undercity(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Bank + player->SEND_POI(1595.64, 232.45, 6, 6, 0, "Undercity Bank"); + player->SEND_GOSSIP_MENU(3514,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Bat handler + player->SEND_POI(1565.9, 271.43, 6, 6, 0, "Undercity Bat Handler"); + player->SEND_GOSSIP_MENU(3515,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Guild master + player->SEND_POI(1594.17, 205.57, 6, 6, 0, "Undercity Guild Master"); + player->SEND_GOSSIP_MENU(3516,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Inn + player->SEND_POI(1639.43, 220.99, 6, 6, 0, "Undercity Inn"); + player->SEND_GOSSIP_MENU(3517,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Mailbox + player->SEND_POI(1632.68, 219.4, 6, 6, 0, "Undercity Mailbox"); + player->SEND_GOSSIP_MENU(3518,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //Auction House + player->SEND_POI(1647.9, 258.49, 6, 6, 0, "Undercity Auction House"); + player->SEND_GOSSIP_MENU(3519,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Zeppelin + player->SEND_POI(2059, 274.86, 6, 6, 0, "Undercity Zeppelin"); + player->SEND_GOSSIP_MENU(3520,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Weapon Master + player->SEND_POI(1670.31, 324.66, 6, 6, 0, "Archibald"); + player->SEND_GOSSIP_MENU(4521,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 9: //Stable master + player->SEND_POI(1634.18, 226.76, 6, 6, 0, "Anya Maulray"); + player->SEND_GOSSIP_MENU(5979,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 10: //Battlemaster + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ALTERACVALLEY , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ARATHIBASIN , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WARSONGULCH , GOSSIP_SENDER_SEC_BATTLEINFO, GOSSIP_ACTION_INFO_DEF + 3); + player->SEND_GOSSIP_MENU(7527,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 11: //Class trainer + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MAGE , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_PRIEST , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ROGUE , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WARLOCK , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_WARRIOR , GOSSIP_SENDER_SEC_CLASSTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->SEND_GOSSIP_MENU(3542,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 12: //Profession trainer + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ALCHEMY , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_BLACKSMITHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_COOKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ENCHANTING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_ENGINEERING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FIRSTAID , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_FISHING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_HERBALISM , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_LEATHERWORKING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 9); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_MINING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 10); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_SKINNING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->ADD_GOSSIP_ITEM( 0, GOSSIP_TEXT_TAILORING , GOSSIP_SENDER_SEC_PROFTRAIN, GOSSIP_ACTION_INFO_DEF + 12); + player->SEND_GOSSIP_MENU(3541,_Creature->GetGUID()); + break; + } +} + +void SendBattleMasterMenu_guard_undercity(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //AV + player->SEND_POI(1329, 333.92, 6, 6, 0, "Grizzle Halfmane"); + player->SEND_GOSSIP_MENU(7525,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //AB + player->SEND_POI(1283.3, 287.16, 6, 6, 0, "Sir Malory Wheeler"); + player->SEND_GOSSIP_MENU(7646,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //WSG + player->SEND_POI(1265, 351.18, 6, 6, 0, "Kurden Bloodclaw"); + player->SEND_GOSSIP_MENU(7526,_Creature->GetGUID()); + break; + } +} + +void SendClassTrainerMenu_guard_undercity(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Mage + player->SEND_POI(1781, 53, 6, 6, 0, "Undercity Mage Trainers"); + player->SEND_GOSSIP_MENU(3513,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Priest + player->SEND_POI(1758.33, 401.5, 6, 6, 0, "Undercity Priest Trainers"); + player->SEND_GOSSIP_MENU(3521,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Rogue + player->SEND_POI(1418.56, 65, 6, 6, 0, "Undercity Rogue Trainers"); + player->SEND_GOSSIP_MENU(3524,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Warlock + player->SEND_POI(1780.92, 53.16, 6, 6, 0, "Undercity Warlock Trainers"); + player->SEND_GOSSIP_MENU(3526,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Warrior + player->SEND_POI(1775.59, 418.19, 6, 6, 0, "Undercity Warrior Trainers"); + player->SEND_GOSSIP_MENU(3527,_Creature->GetGUID()); + break; + } +} + +void SendProfTrainerMenu_guard_undercity(Player *player, Creature *_Creature, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Alchemy + player->SEND_POI(1419.82, 417.19, 6, 6, 0, "The Apothecarium"); + player->SEND_GOSSIP_MENU(3528,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Blacksmithing + player->SEND_POI(1696, 285, 6, 6, 0, "Undercity Blacksmithing Trainer"); + player->SEND_GOSSIP_MENU(3529,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Cooking + player->SEND_POI(1596.34, 274.68, 6, 6, 0, "Undercity Cooking Trainer"); + player->SEND_GOSSIP_MENU(3530,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Enchanting + player->SEND_POI(1488.54, 280.19, 6, 6, 0, "Undercity Enchanting Trainer"); + player->SEND_GOSSIP_MENU(3531,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Engineering + player->SEND_POI(1408.58, 143.43, 6, 6, 0, "Undercity Engineering Trainer"); + player->SEND_GOSSIP_MENU(3532,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: //First Aid + player->SEND_POI(1519.65, 167.19, 6, 6, 0, "Undercity First Aid Trainer"); + player->SEND_GOSSIP_MENU(3533,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: //Fishing + player->SEND_POI(1679.9, 89, 6, 6, 0, "Undercity Fishing Trainer"); + player->SEND_GOSSIP_MENU(3534,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 8: //Herbalism + player->SEND_POI(1558, 349.36, 6, 6, 0, "Undercity Herbalism Trainer"); + player->SEND_GOSSIP_MENU(3535,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 9: //Leatherworking + player->SEND_POI(1498.76, 196.43, 6, 6, 0, "Undercity Leatherworking Trainer"); + player->SEND_GOSSIP_MENU(3536,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 10: //Mining + player->SEND_POI(1642.88, 335.58, 6, 6, 0, "Undercity Mining Trainer"); + player->SEND_GOSSIP_MENU(3537,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 11: //Skinning + player->SEND_POI(1498.6, 196.46, 6, 6, 0, "Undercity Skinning Trainer"); + player->SEND_GOSSIP_MENU(3538,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 12: //Tailoring + player->SEND_POI(1689.55, 193, 6, 6, 0, "Undercity Tailoring Trainer"); + player->SEND_GOSSIP_MENU(3539,_Creature->GetGUID()); + break; + } +} + +bool GossipSelect_guard_undercity(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + switch (sender) + { + case GOSSIP_SENDER_MAIN: SendDefaultMenu_guard_undercity(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_CLASSTRAIN: SendClassTrainerMenu_guard_undercity(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_PROFTRAIN: SendProfTrainerMenu_guard_undercity(player, _Creature, action); break; + case GOSSIP_SENDER_SEC_BATTLEINFO: SendBattleMasterMenu_guard_undercity(player, _Creature, action); break; + } + return true; +} + +/******************************************************* + * guard_undercity end + *******************************************************/ + +CreatureAI* GetAI_guard_undercity(Creature *_Creature) +{ + return new guardAI (_Creature); +} + +/******************************************************* + * AddSC + *******************************************************/ + +void AddSC_guards() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="guard_azuremyst"; + newscript->pGossipHello = &GossipHello_guard_azuremyst; + newscript->pGossipSelect = &GossipSelect_guard_azuremyst; + newscript->GetAI = GetAI_guard_azuremyst; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="guard_bluffwatcher"; + newscript->pGossipHello = &GossipHello_guard_bluffwatcher; + newscript->pGossipSelect = &GossipSelect_guard_bluffwatcher; + newscript->GetAI = GetAI_guard_bluffwatcher; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="guard_contested"; + newscript->GetAI = GetAI_guard_contested; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="guard_darnassus"; + newscript->pGossipHello = &GossipHello_guard_darnassus; + newscript->pGossipSelect = &GossipSelect_guard_darnassus; + newscript->GetAI = GetAI_guard_darnassus; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="guard_dunmorogh"; + newscript->pGossipHello = &GossipHello_guard_dunmorogh; + newscript->pGossipSelect = &GossipSelect_guard_dunmorogh; + newscript->GetAI = GetAI_guard_dunmorogh; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="guard_durotar"; + newscript->pGossipHello = &GossipHello_guard_durotar; + newscript->pGossipSelect = &GossipSelect_guard_durotar; + newscript->GetAI = GetAI_guard_durotar; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="guard_elwynnforest"; + newscript->pGossipHello = &GossipHello_guard_elwynnforest; + newscript->pGossipSelect = &GossipSelect_guard_elwynnforest; + newscript->GetAI = GetAI_guard_elwynnforest; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="guard_eversong"; + newscript->pGossipHello = &GossipHello_guard_eversong; + newscript->pGossipSelect = &GossipSelect_guard_eversong; + newscript->GetAI = GetAI_guard_eversong; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="guard_exodar"; + newscript->pGossipHello = &GossipHello_guard_exodar; + newscript->pGossipSelect = &GossipSelect_guard_exodar; + newscript->GetAI = GetAI_guard_exodar; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="guard_ironforge"; + newscript->pGossipHello = &GossipHello_guard_ironforge; + newscript->pGossipSelect = &GossipSelect_guard_ironforge; + newscript->GetAI = GetAI_guard_ironforge; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="guard_mulgore"; + newscript->pGossipHello = &GossipHello_guard_mulgore; + newscript->pGossipSelect = &GossipSelect_guard_mulgore; + newscript->GetAI = GetAI_guard_mulgore; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="guard_orgrimmar"; + newscript->pGossipHello = &GossipHello_guard_orgrimmar; + newscript->pGossipSelect = &GossipSelect_guard_orgrimmar; + newscript->pReceiveEmote = &ReceiveEmote_guard_orgrimmar; + newscript->GetAI = GetAI_guard_orgrimmar; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="guard_shattrath"; + newscript->pGossipHello = &GossipHello_guard_shattrath; + newscript->pGossipSelect = &GossipSelect_guard_shattrath; + newscript->GetAI = GetAI_guard_shattrath; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="guard_shattrath_aldor"; + newscript->GetAI = GetAI_guard_shattrath_aldor; + newscript->pGossipHello = &GossipHello_guard_shattrath_aldor; + newscript->pGossipSelect = &GossipSelect_guard_shattrath_aldor; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="guard_shattrath_scryer"; + newscript->GetAI = GetAI_guard_shattrath_scryer; + newscript->pGossipHello = &GossipHello_guard_shattrath_scryer; + newscript->pGossipSelect = &GossipSelect_guard_shattrath_scryer; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="guard_silvermoon"; + newscript->pGossipHello = &GossipHello_guard_silvermoon; + newscript->pGossipSelect = &GossipSelect_guard_silvermoon; + newscript->GetAI = GetAI_guard_silvermoon; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="guard_stormwind"; + newscript->pGossipHello = &GossipHello_guard_stormwind; + newscript->pGossipSelect = &GossipSelect_guard_stormwind; + newscript->pReceiveEmote = &ReceiveEmote_guard_stormwind; + newscript->GetAI = GetAI_guard_stormwind; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="guard_teldrassil"; + newscript->pGossipHello = &GossipHello_guard_teldrassil; + newscript->pGossipSelect = &GossipSelect_guard_teldrassil; + newscript->GetAI = GetAI_guard_teldrassil; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="guard_tirisfal"; + newscript->pGossipHello = &GossipHello_guard_tirisfal; + newscript->pGossipSelect = &GossipSelect_guard_tirisfal; + newscript->GetAI = GetAI_guard_tirisfal; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="guard_undercity"; + newscript->pGossipHello = &GossipHello_guard_undercity; + newscript->pGossipSelect = &GossipSelect_guard_undercity; + newscript->GetAI = GetAI_guard_undercity; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/item/item_scripts.cpp b/src/bindings/scripts/scripts/item/item_scripts.cpp new file mode 100644 index 00000000000..6d2bfe8d852 --- /dev/null +++ b/src/bindings/scripts/scripts/item/item_scripts.cpp @@ -0,0 +1,529 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Item_Scripts +SD%Complete: 100 +SDComment: Items for a range of different items. See content below (in script) +SDCategory: Items +EndScriptData */ + +/* ContentData +item_area_52_special(i28132) Prevents abuse of this item +item_attuned_crystal_cores(i34368) Prevent abuse(quest 11524 & 11525) +item_blackwhelp_net(i31129) Quest Whelps of the Wyrmcult (q10747). Prevents abuse +item_draenei_fishing_net(i23654) Hacklike implements chance to spawn item or creature +item_disciplinary_rod Prevents abuse +item_nether_wraith_beacon(i31742) Summons creatures for quest Becoming a Spellfire Tailor (q10832) +item_flying_machine(i34060,i34061) Engineering crafted flying machines +item_gor_dreks_ointment(i30175) Protecting Our Own(q10488) +item_muiseks_vessel Cast on creature, they must be dead(q 3123,3124,3125,3126,3127) +item_protovoltaic_magneto_collector Prevents abuse +item_razorthorn_flayer_gland Quest Discovering Your Roots (q11520) and Rediscovering Your Roots (q11521). Prevents abuse +item_tame_beast_rods(many) Prevent cast on any other creature than the intended (for all tame beast quests) +item_soul_cannon(i32825) Prevents abuse of this item +item_sparrowhawk_net(i32321) Quest To Catch A Sparrowhawk (q10987). Prevents abuse +item_voodoo_charm Provide proper error message and target(q2561) +item_vorenthals_presence(i30259) Prevents abuse of this item +item_yehkinyas_bramble(i10699) Allow cast spell on vale screecher only and remove corpse if cast sucessful (q3520) +item_zezzak_shard(i31463) Quest The eyes of Grillok (q10813). Prevents abuse +EndContentData */ + +#include "precompiled.h" +#include "SpellMgr.h" +#include "Spell.h" +#include "WorldPacket.h" + +/*##### +# item_area_52_special +#####*/ + +bool ItemUse_item_area_52_special(Player *player, Item* _Item, SpellCastTargets const& targets) +{ + if ( player->GetAreaId() == 3803 ) + { + return false; + } + else + { + player->SendEquipError(EQUIP_ERR_OUT_OF_RANGE,_Item,NULL); + return true; + } +} + +/*##### +# item_attuned_crystal_cores +#####*/ + +bool ItemUse_item_attuned_crystal_cores(Player *player, Item* _Item, SpellCastTargets const& targets) +{ + if( targets.getUnitTarget() && targets.getUnitTarget()->GetTypeId()==TYPEID_UNIT && + targets.getUnitTarget()->GetEntry() == 24972 && targets.getUnitTarget()->isDead() ) + return false; + + player->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,_Item,NULL); + return true; +} + +/*##### +# item_blackwhelp_net +#####*/ + +bool ItemUse_item_blackwhelp_net(Player *player, Item* _Item, SpellCastTargets const& targets) +{ + if( targets.getUnitTarget() && targets.getUnitTarget()->GetTypeId()==TYPEID_UNIT && + targets.getUnitTarget()->GetEntry() == 21387 ) + return false; + + player->SendEquipError(EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM,_Item,NULL); + return true; +} + +/*##### +# item_draenei_fishing_net +#####*/ + +//This is just a hack and should be removed from here. +//Creature/Item are in fact created before spell are sucessfully casted, without any checks at all to ensure proper/expected behavior. +bool ItemUse_item_draenei_fishing_net(Player *player, Item* _Item, SpellCastTargets const& targets) +{ + //if( targets.getGOTarget() && targets.getGOTarget()->GetTypeId() == TYPEID_GAMEOBJECT && + //targets.getGOTarget()->GetGOInfo()->type == GAMEOBJECT_TYPE_SPELL_FOCUS && targets.getGOTarget()->GetEntry() == 181616 ) + //{ + if( player->GetQuestStatus(9452) == QUEST_STATUS_INCOMPLETE ) + { + if( rand()%100 < 35 ) + { + Creature *Murloc = player->SummonCreature(17102,player->GetPositionX() ,player->GetPositionY()+20, player->GetPositionZ(), 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if( Murloc ) + Murloc->AI()->AttackStart(player); + } + else + { + ItemPosCountVec dest; + uint8 msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, 23614, 1); + if( msg == EQUIP_ERR_OK ) + { + Item* item = player->StoreNewItem(dest,23614,true); + if( item ) + player->SendNewItem(item,1,false,true); + }else + player->SendEquipError(msg,NULL,NULL); + } + } + //} + return false; +} + +/*##### +# item_disciplinary_rod +#####*/ + +bool ItemUse_item_disciplinary_rod(Player *player, Item* _Item, SpellCastTargets const& targets) +{ + if( targets.getUnitTarget() && targets.getUnitTarget()->GetTypeId()==TYPEID_UNIT && + (targets.getUnitTarget()->GetEntry() == 15941 || targets.getUnitTarget()->GetEntry() == 15945) ) + return false; + + player->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,_Item,NULL); + return true; +} + +/*##### +# item_nether_wraith_beacon +#####*/ + +bool ItemUse_item_nether_wraith_beacon(Player *player, Item* _Item, SpellCastTargets const& targets) +{ + if (player->GetQuestStatus(10832) == QUEST_STATUS_INCOMPLETE) + { + Creature *Nether; + Nether = player->SummonCreature(22408,player->GetPositionX() ,player->GetPositionY()+20, player->GetPositionZ(), 0,TEMPSUMMON_TIMED_DESPAWN,180000); + Nether = player->SummonCreature(22408,player->GetPositionX() ,player->GetPositionY()-20, player->GetPositionZ(), 0,TEMPSUMMON_TIMED_DESPAWN,180000); + if (Nether) + ((CreatureAI*)Nether->AI())->AttackStart(player); + } + return false; +} + +/*##### +# item_flying_machine +#####*/ + +bool ItemUse_item_flying_machine(Player *player, Item* _Item, SpellCastTargets const& targets) +{ + uint32 itemId = _Item->GetEntry(); + if( itemId == 34060 ) + if( player->GetBaseSkillValue(SKILL_RIDING) >= 225 ) + return false; + + if( itemId == 34061 ) + if( player->GetBaseSkillValue(SKILL_RIDING) == 300 ) + return false; + + debug_log("SD2: Player attempt to use item %u, but did not meet riding requirement",itemId); + player->SendEquipError(EQUIP_ERR_ERR_CANT_EQUIP_SKILL,_Item,NULL); + return true; +} + +/*##### +# item_gor_dreks_ointment +#####*/ + +bool ItemUse_item_gor_dreks_ointment(Player *player, Item* _Item, SpellCastTargets const& targets) +{ + if( targets.getUnitTarget() && targets.getUnitTarget()->GetTypeId()==TYPEID_UNIT && + targets.getUnitTarget()->GetEntry() == 20748 && !targets.getUnitTarget()->HasAura(32578,0) ) + return false; + + player->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,_Item,NULL); + return true; +} + +/*##### +# item_muiseks_vessel +#####*/ + +bool ItemUse_item_muiseks_vessel(Player *player, Item* _Item, SpellCastTargets const& targets) +{ + Unit* uTarget = targets.getUnitTarget(); + uint32 itemSpell = _Item->GetProto()->Spells[0].SpellId; + uint32 cEntry = 0; + uint32 cEntry2 = 0; + uint32 cEntry3 = 0; + uint32 cEntry4 = 0; + + if(itemSpell) + { + switch(itemSpell) + { + case 11885: //Wandering Forest Walker + cEntry = 7584; + break; + case 11886: //Owlbeasts + cEntry = 2927; + cEntry2 = 2928; + cEntry3 = 2929; + cEntry4 = 7808; + break; + case 11887: //Freyfeather Hippogryphs + cEntry = 5300; + cEntry2 = 5304; + cEntry3 = 5305; + cEntry4 = 5306; + break; + case 11888: //Sprite Dragon Sprite Darters + cEntry = 5276; + cEntry2 = 5278; + break; + case 11889: //Zapped Land Walker Land Walker Zapped Cliff Giant Cliff Giant + cEntry = 5357; + cEntry2 = 5358; + cEntry3 = 14640; + cEntry4 = 14604; + break; + } + if( uTarget && uTarget->GetTypeId()==TYPEID_UNIT && uTarget->isDead() && + (uTarget->GetEntry()==cEntry || uTarget->GetEntry()==cEntry2 || uTarget->GetEntry()==cEntry3 || uTarget->GetEntry()==cEntry4) ) + { + ((Creature*)uTarget)->RemoveCorpse(); + return false; + } + } + + WorldPacket data(SMSG_CAST_FAILED, (4+2)); // prepare packet error message + data << uint32(_Item->GetEntry()); // itemId + data << uint8(SPELL_FAILED_BAD_TARGETS); // reason + player->GetSession()->SendPacket(&data); // send message: Invalid target + + player->SendEquipError(EQUIP_ERR_NONE,_Item,NULL); // break spell + return true; +} + +/*##### +# item_razorthorn_flayer_gland +#####*/ + +bool ItemUse_item_razorthorn_flayer_gland(Player *player, Item* _Item, SpellCastTargets const& targets) +{ + if( targets.getUnitTarget() && targets.getUnitTarget()->GetTypeId()==TYPEID_UNIT && + targets.getUnitTarget()->GetEntry() == 24922 ) + return false; + + player->SendEquipError(EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM,_Item,NULL); + return true; +} + +/*##### +# item_tame_beast_rods +#####*/ + +bool ItemUse_item_tame_beast_rods(Player *player, Item* _Item, SpellCastTargets const& targets) +{ + uint32 itemSpell = _Item->GetProto()->Spells[0].SpellId; + uint32 cEntry = 0; + + if(itemSpell) + { + switch(itemSpell) + { + case 19548: cEntry = 1196; break; //Ice Claw Bear + case 19674: cEntry = 1126; break; //Large Crag Boar + case 19687: cEntry = 1201; break; //Snow Leopard + case 19688: cEntry = 2956; break; //Adult Plainstrider + case 19689: cEntry = 2959; break; //Prairie Stalker + case 19692: cEntry = 2970; break; //Swoop + case 19693: cEntry = 1998; break; //Webwood Lurker + case 19694: cEntry = 3099; break; //Dire Mottled Boar + case 19696: cEntry = 3107; break; //Surf Crawler + case 19697: cEntry = 3126; break; //Armored Scorpid + case 19699: cEntry = 2043; break; //Nightsaber Stalker + case 19700: cEntry = 1996; break; //Strigid Screecher + case 30646: cEntry = 17217; break; //Barbed Crawler + case 30653: cEntry = 17374; break; //Greater Timberstrider + case 30654: cEntry = 17203; break; //Nightstalker + case 30099: cEntry = 15650; break; //Crazed Dragonhawk + case 30102: cEntry = 15652; break; //Elder Springpaw + case 30105: cEntry = 16353; break; //Mistbat + } + if( targets.getUnitTarget() && targets.getUnitTarget()->GetTypeId()==TYPEID_UNIT && + targets.getUnitTarget()->GetEntry() == cEntry ) + return false; + } + + WorldPacket data(SMSG_CAST_FAILED, (4+2)); // prepare packet error message + data << uint32(_Item->GetEntry()); // itemId + data << uint8(SPELL_FAILED_BAD_TARGETS); // reason + player->GetSession()->SendPacket(&data); // send message: Invalid target + + player->SendEquipError(EQUIP_ERR_NONE,_Item,NULL); // break spell + return true; +} + +/*##### +# item_protovoltaic_magneto_collector +#####*/ + +bool ItemUse_item_protovoltaic_magneto_collector(Player *player, Item* _Item, SpellCastTargets const& targets) +{ + if( targets.getUnitTarget() && targets.getUnitTarget()->GetTypeId()==TYPEID_UNIT && + targets.getUnitTarget()->GetEntry() == 21729 ) + return false; + + player->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,_Item,NULL); + return true; +} + +/*##### +# item_soul_cannon +#####*/ + +bool ItemUse_item_soul_cannon(Player *player, Item* _Item, SpellCastTargets const& targets) +{ + // allow use + if( targets.getUnitTarget() && targets.getUnitTarget()->GetTypeId()==TYPEID_UNIT && + targets.getUnitTarget()->GetEntry() == 22357 ) + return false; + + // error + player->SendEquipError(EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM,_Item,NULL); + return true; +} + +/*##### +# item_sparrowhawk_net +#####*/ + +bool ItemUse_item_sparrowhawk_net(Player *player, Item* _Item, SpellCastTargets const& targets) +{ + if( targets.getUnitTarget() && targets.getUnitTarget()->GetTypeId()==TYPEID_UNIT && + targets.getUnitTarget()->GetEntry() == 22979 ) + return false; + + player->SendEquipError(EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM,_Item,NULL); + return true; +} + +/*##### +# item_voodoo_charm +#####*/ + +bool ItemUse_item_voodoo_charm(Player *player, Item* _Item, SpellCastTargets const& targets) +{ + if( targets.getUnitTarget() && targets.getUnitTarget()->GetTypeId()==TYPEID_UNIT && targets.getUnitTarget()->isDead() && + targets.getUnitTarget()->GetEntry()==7318 ) + return false; + + WorldPacket data(SMSG_CAST_FAILED, (4+2)); // prepare packet error message + data << uint32(_Item->GetEntry()); // itemId + data << uint8(SPELL_FAILED_BAD_TARGETS); // reason + player->GetSession()->SendPacket(&data); // send message: Invalid target + + player->SendEquipError(EQUIP_ERR_NONE,_Item,NULL); // break spell + return true; +} + +/*##### +# item_vorenthals_presence +#####*/ + +bool ItemUse_item_vorenthals_presence(Player *player, Item* _Item, SpellCastTargets const& targets) +{ + // allow use + if( targets.getUnitTarget() && targets.getUnitTarget()->GetTypeId()==TYPEID_UNIT && + targets.getUnitTarget()->GetEntry() == 20132 ) + return false; + + // error + player->SendEquipError(EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM,_Item,NULL); + return true; +} + +/*##### +# item_yehkinyas_bramble +#####*/ + +bool ItemUse_item_yehkinyas_bramble(Player *player, Item* _Item, SpellCastTargets const& targets) +{ + if (player->GetQuestStatus(3520) == QUEST_STATUS_INCOMPLETE) + { + Unit * unit_target = targets.getUnitTarget(); + if( unit_target && + unit_target->GetTypeId()==TYPEID_UNIT && + unit_target->isDead() && + // cast only on corpse 5307 or 5308 + (unit_target->GetEntry()==5307 || unit_target->GetEntry()==5308) ) + { + ((Creature*)unit_target)->RemoveCorpse(); // remove corpse for cancelling second use + return false; // all ok + } + } + WorldPacket data(SMSG_CAST_FAILED, (4+2)); // prepare packet error message + data << uint32(10699); // itemId + data << uint8(SPELL_FAILED_BAD_TARGETS); // reason + player->GetSession()->SendPacket(&data); // send message: Bad target + player->SendEquipError(EQUIP_ERR_NONE,_Item,NULL); // break spell + return true; +} + +/*##### +# item_zezzak_shard +#####*/ + +bool ItemUse_item_zezzak_shard(Player *player, Item* _Item, SpellCastTargets const& targets) +{ + if( targets.getUnitTarget() && targets.getUnitTarget()->GetTypeId()==TYPEID_UNIT && + targets.getUnitTarget()->GetEntry() == 19440 ) + return false; + + player->SendEquipError(EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM,_Item,NULL); + return true; +} + +void AddSC_item_scripts() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="item_area_52_special"; + newscript->pItemUse = ItemUse_item_area_52_special; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="item_attuned_crystal_cores"; + newscript->pItemUse = ItemUse_item_attuned_crystal_cores; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="item_blackwhelp_net"; + newscript->pItemUse = ItemUse_item_blackwhelp_net; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="item_disciplinary_rod"; + newscript->pItemUse = ItemUse_item_disciplinary_rod; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="item_draenei_fishing_net"; + newscript->pItemUse = ItemUse_item_draenei_fishing_net; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="item_nether_wraith_beacon"; + newscript->pItemUse = ItemUse_item_nether_wraith_beacon; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="item_flying_machine"; + newscript->pItemUse = ItemUse_item_flying_machine; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="item_gor_dreks_ointment"; + newscript->pItemUse = ItemUse_item_gor_dreks_ointment; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="item_muiseks_vessel"; + newscript->pItemUse = ItemUse_item_muiseks_vessel; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="item_razorthorn_flayer_gland"; + newscript->pItemUse = ItemUse_item_razorthorn_flayer_gland; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="item_tame_beast_rods"; + newscript->pItemUse = ItemUse_item_tame_beast_rods; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="item_protovoltaic_magneto_collector"; + newscript->pItemUse = ItemUse_item_protovoltaic_magneto_collector; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="item_soul_cannon"; + newscript->pItemUse = ItemUse_item_soul_cannon; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="item_sparrowhawk_net"; + newscript->pItemUse = ItemUse_item_sparrowhawk_net; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="item_voodoo_charm"; + newscript->pItemUse = ItemUse_item_voodoo_charm; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="item_vorenthals_presence"; + newscript->pItemUse = ItemUse_item_vorenthals_presence; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="item_yehkinyas_bramble"; + newscript->pItemUse = ItemUse_item_yehkinyas_bramble; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="item_zezzaks_shard"; + newscript->pItemUse = ItemUse_item_zezzak_shard; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/item/item_test.cpp b/src/bindings/scripts/scripts/item/item_test.cpp new file mode 100644 index 00000000000..e4f7285e52a --- /dev/null +++ b/src/bindings/scripts/scripts/item/item_test.cpp @@ -0,0 +1,42 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Item_Test +SD%Complete: 100 +SDComment: Used for Testing Item Scripts +SDCategory: Items +EndScriptData */ + +#include "precompiled.h" + +extern void LoadDatabase(); + +bool ItemUse_item_test(Player *player, Item* _Item, SpellCastTargets const& targets) +{ + LoadDatabase(); + return true; +} + +void AddSC_item_test() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="item_test"; + newscript->pItemUse = ItemUse_item_test; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/npc/npc_escortAI.cpp b/src/bindings/scripts/scripts/npc/npc_escortAI.cpp new file mode 100644 index 00000000000..d846727ac0a --- /dev/null +++ b/src/bindings/scripts/scripts/npc/npc_escortAI.cpp @@ -0,0 +1,304 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +/* ScriptData +SDName: Npc_EscortAI +SD%Complete: 100 +SDComment: +SDCategory: Npc +EndScriptData */ + +#include "precompiled.h" +#include "npc_escortAI.h" + +#define WP_LAST_POINT -1 +#define MAX_PLAYER_DISTANCE 50 + +bool npc_escortAI::IsVisible(Unit* who) const +{ + if (!who) + return false; + + return (m_creature->GetDistance(who) < VISIBLE_RANGE) && who->isVisibleForOrDetect(m_creature,true); +} + +void npc_escortAI::AttackStart(Unit *who) +{ + if (!who) + return; + + if (IsBeingEscorted && !Defend) + return; + + if (who->isTargetableForAttack()) + { + //Begin attack + if ( m_creature->Attack(who, true) ) + { + m_creature->GetMotionMaster()->MovementExpired(); + m_creature->GetMotionMaster()->MoveChase(who); + m_creature->AddThreat(who, 0.0f); + } + + if (!InCombat) + { + InCombat = true; + + //Store last position + m_creature->GetPosition(LastPos.x, LastPos.y, LastPos.z); + + debug_log("SD2: EscortAI has entered combat via Attack and stored last location"); + + Aggro(who); + } + } +} + +void npc_escortAI::MoveInLineOfSight(Unit *who) +{ + if (IsBeingEscorted && !Attack) + return; + + if( !m_creature->getVictim() && who->isTargetableForAttack() && ( m_creature->IsHostileTo( who )) && who->isInAccessablePlaceFor(m_creature) ) + { + if (m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = m_creature->GetAttackDistance(who); + if( m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->IsWithinLOSInMap(who) ) + { + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + //Begin attack + if ( m_creature->Attack(who, true) ) + { + m_creature->GetMotionMaster()->MovementExpired(); + m_creature->GetMotionMaster()->MoveChase(who); + m_creature->AddThreat(who, 0.0f); + } + + if (!InCombat) + { + InCombat = true; + + //Store last position + m_creature->GetPosition(LastPos.x, LastPos.y, LastPos.z); + debug_log("SD2: EscortAI has entered combat via LOS and stored last location"); + + Aggro(who); + } + } + } +} + +void npc_escortAI::JustRespawned() +{ + InCombat = false; + IsBeingEscorted = false; + IsOnHold = false; + + //Re-Enable gossip + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + + Reset(); +} + +void npc_escortAI::EnterEvadeMode() +{ + InCombat = false; + + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); + m_creature->CombatStop(); + m_creature->SetLootRecipient(NULL); + + if (IsBeingEscorted) + { + debug_log("SD2: EscortAI has left combat and is now returning to last point"); + Returning = true; + m_creature->GetMotionMaster()->MovementExpired(); + m_creature->GetMotionMaster()->MovePoint(WP_LAST_POINT, LastPos.x, LastPos.y, LastPos.z); + + }else + { + m_creature->GetMotionMaster()->MovementExpired(); + m_creature->GetMotionMaster()->MoveTargetedHome(); + } + + Reset(); +} + +void npc_escortAI::UpdateAI(const uint32 diff) +{ + //Waypoint Updating + if (IsBeingEscorted && !InCombat && WaitTimer && !Returning) + if (WaitTimer <= diff) + { + if (ReconnectWP) + { + //Correct movement speed + if (Run) + m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + else m_creature->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + + //Continue with waypoints + if( !IsOnHold ) + { + m_creature->GetMotionMaster()->MovePoint(CurrentWP->id, CurrentWP->x, CurrentWP->y, CurrentWP->z ); + debug_log("SD2: EscortAI Reconnect WP is: %d, %f, %f, %f", CurrentWP->id, CurrentWP->x, CurrentWP->y, CurrentWP->z); + WaitTimer = 0; + ReconnectWP = false; + return; + } + } + + //End of the line, Despawn self then immediatly respawn + if (CurrentWP == WaypointList.end()) + { + debug_log("SD2: EscortAI reached end of waypoints"); + + m_creature->setDeathState(JUST_DIED); + m_creature->SetHealth(0); + m_creature->CombatStop(); + m_creature->DeleteThreatList(); + m_creature->Respawn(); + m_creature->GetMotionMaster()->Clear(true); + + //Re-Enable gossip + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + + IsBeingEscorted = false; + WaitTimer = 0; + return; + } + + if( !IsOnHold ) + { + m_creature->GetMotionMaster()->MovePoint(CurrentWP->id, CurrentWP->x, CurrentWP->y, CurrentWP->z ); + debug_log("SD2: EscortAI Next WP is: %d, %f, %f, %f", CurrentWP->id, CurrentWP->x, CurrentWP->y, CurrentWP->z); + WaitTimer = 0; + } + }else WaitTimer -= diff; + + //Check if player is within range + if (IsBeingEscorted && !InCombat && PlayerGUID) + if (PlayerTimer < diff) + { + Unit* p = Unit::GetUnit(*m_creature, PlayerGUID); + + if (!p || m_creature->GetDistance(p) > MAX_PLAYER_DISTANCE) + { + JustDied(m_creature); + IsBeingEscorted = false; + + debug_log("SD2: EscortAI Evaded back to spawn point because player was to far away or not found"); + + m_creature->setDeathState(JUST_DIED); + m_creature->SetHealth(0); + m_creature->CombatStop(); + m_creature->DeleteThreatList(); + m_creature->Respawn(); + m_creature->GetMotionMaster()->Clear(true); + + //Re-Enable gossip + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + } + + PlayerTimer = 1000; + }else PlayerTimer -= diff; + + //Check if we have a current target + if( m_creature->isAlive() && m_creature->SelectHostilTarget() && m_creature->getVictim()) + { + //If we are within range melee the target + if( m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE)) + { + if( m_creature->isAttackReady() ) + { + m_creature->AttackerStateUpdate(m_creature->getVictim()); + m_creature->resetAttackTimer(); + } + } + } +} + +void npc_escortAI::MovementInform(uint32 type, uint32 id) +{ + if (type != POINT_MOTION_TYPE || !IsBeingEscorted) + return; + + //Original position reached, continue waypoint movement + if (id == WP_LAST_POINT) + { + debug_log("SD2: EscortAI has returned to original position before combat"); + ReconnectWP = true; + Returning = false; + WaitTimer = 1; + + }else + { + //Make sure that we are still on the right waypoint + if (CurrentWP->id != id) + { + debug_log("SD2 ERROR: EscortAI reached waypoint out of order %d, expected %d", id, CurrentWP->id); + return; + } + + debug_log("SD2: EscortAI Waypoint %d reached", CurrentWP->id); + + //Call WP function + WaypointReached(CurrentWP->id); + + WaitTimer = CurrentWP->WaitTimeMs + 1; + + ++CurrentWP; + } +} + +void npc_escortAI::AddWaypoint(uint32 id, float x, float y, float z, uint32 WaitTimeMs) +{ + Escort_Waypoint t(id, x, y, z, WaitTimeMs); + + WaypointList.push_back(t); +} + +void npc_escortAI::Start(bool bAttack, bool bDefend, bool bRun, uint64 pGUID) +{ + if (InCombat) + { + debug_log("SD2 ERROR: EscortAI attempt to Start while in combat"); + return; + } + + if (WaypointList.empty()) + { + debug_log("SD2 ERROR: Call to escortAI::Start with 0 waypoints"); + return; + } + + Attack = bAttack; + Defend = bDefend; + Run = bRun; + PlayerGUID = pGUID; + + debug_log("SD2: EscortAI started with %d waypoints. Attack = %d, Defend = %d, Run = %d, PlayerGUID = %d", WaypointList.size(), Attack, Defend, Run, PlayerGUID); + + CurrentWP = WaypointList.begin(); + + //Set initial speed + if (Run) + m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + else m_creature->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + + //Start WP + m_creature->GetMotionMaster()->MovePoint(CurrentWP->id, CurrentWP->x, CurrentWP->y, CurrentWP->z ); + debug_log("SD2: EscortAI Next WP is: %d, %f, %f, %f", CurrentWP->id, CurrentWP->x, CurrentWP->y, CurrentWP->z); + IsBeingEscorted = true; + ReconnectWP = false; + Returning = false; + IsOnHold = false; + + //Disable gossip + m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); +} diff --git a/src/bindings/scripts/scripts/npc/npc_escortAI.h b/src/bindings/scripts/scripts/npc/npc_escortAI.h new file mode 100644 index 00000000000..e1dbf186764 --- /dev/null +++ b/src/bindings/scripts/scripts/npc/npc_escortAI.h @@ -0,0 +1,85 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef SC_ESCORTAI_H +#define SC_ESCORTAI_H + +struct Escort_Waypoint +{ + Escort_Waypoint(uint32 _id, float _x, float _y, float _z, uint32 _w) + { + id = _id; + x = _x; + y = _y; + z = _z; + WaitTimeMs = _w; + } + + uint32 id; + float x; + float y; + float z; + uint32 WaitTimeMs; +}; + +struct MANGOS_DLL_DECL npc_escortAI : public ScriptedAI +{ + public: + + // Pure Virtual Functions + virtual void WaypointReached(uint32) = 0; + + virtual void Aggro(Unit*) = 0; + + virtual void Reset() = 0; + + // CreatureAI functions + npc_escortAI(Creature *c) : ScriptedAI(c), IsBeingEscorted(false), PlayerTimer(1000) {m_creature->GetPosition(LastPos.x, LastPos.y, LastPos.z);} + + bool IsVisible(Unit*) const; + + void AttackStart(Unit*); + + void MoveInLineOfSight(Unit*); + + void JustRespawned(); + + void EnterEvadeMode(); + + void UpdateAI(const uint32); + + void MovementInform(uint32, uint32); + + // EscortAI functions + void AddWaypoint(uint32 id, float x, float y, float z, uint32 WaitTimeMs = 0); + + void Start(bool bAttack, bool bDefend, bool bRun, uint64 pGUID = 0); + + // EscortAI variables + protected: + uint64 PlayerGUID; + bool IsBeingEscorted; + bool IsOnHold; + + private: + uint32 WaitTimer; + uint32 PlayerTimer; + + struct + { + float x; + float y; + float z; + }LastPos; + + std::list WaypointList; + std::list::iterator CurrentWP; + + bool Attack; + bool Defend; + bool Returning; + bool ReconnectWP; + bool Run; +}; +#endif diff --git a/src/bindings/scripts/scripts/npc/npc_innkeeper.cpp b/src/bindings/scripts/scripts/npc/npc_innkeeper.cpp new file mode 100644 index 00000000000..429d5b51115 --- /dev/null +++ b/src/bindings/scripts/scripts/npc/npc_innkeeper.cpp @@ -0,0 +1,144 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Npc_Innkeeper +SD%Complete: 50 +SDComment: This script are currently not in use. EventSystem cannot be used on Windows build of SD2 +SDCategory: NPCs +EndScriptData */ + +#include "precompiled.h" + +#define HALLOWEEN_EVENTID 12 +#define SPELL_TRICK_OR_TREATED 24755 +#define SPELL_TREAT 24715 + +#define LOCALE_TRICK_OR_TREAT_0 "Trick or Treat!" +#define LOCALE_TRICK_OR_TREAT_2 "Des bonbons ou des blagues!" +#define LOCALE_TRICK_OR_TREAT_3 "Süßes oder Saures!" +#define LOCALE_TRICK_OR_TREAT_6 "¡Truco o trato!" + +bool isEventActive() +{ + /* + const GameEvent::ActiveEvents *ActiveEventsList = gameeventmgr.GetActiveEventList(); + GameEvent::ActiveEvents::const_iterator itr; + for (itr = ActiveEventsList->begin(); itr != ActiveEventsList->end(); ++itr) + { + if (*itr==HALLOWEEN_EVENTID) + { + return true; + } + }*/ + return false; +} + +bool GossipHello_npc_innkeeper(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if (isEventActive()&& !player->GetAura(SPELL_TRICK_OR_TREATED,0)) + { + char* localizedEntry; + switch (player->GetSession()->GetSessionDbLocaleIndex()) + { + case 0: + localizedEntry=LOCALE_TRICK_OR_TREAT_0; + break; + case 2: + localizedEntry=LOCALE_TRICK_OR_TREAT_2; + break; + case 3: + localizedEntry=LOCALE_TRICK_OR_TREAT_3; + break; + case 6: + localizedEntry=LOCALE_TRICK_OR_TREAT_6; + break; + default: + localizedEntry=LOCALE_TRICK_OR_TREAT_0; + } + + player->ADD_GOSSIP_ITEM(0, localizedEntry, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+HALLOWEEN_EVENTID); + } + + player->TalkedToCreature(_Creature->GetEntry(),_Creature->GetGUID()); + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + return true; +} + +bool GossipSelect_npc_innkeeper(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if (action == GOSSIP_ACTION_INFO_DEF+HALLOWEEN_EVENTID && isEventActive() && !player->GetAura(SPELL_TRICK_OR_TREATED,0)) + { + player->CLOSE_GOSSIP_MENU(); + player->CastSpell(player, SPELL_TRICK_OR_TREATED, true); + + // either trick or treat, 50% chance + if(rand()%2) + { + player->CastSpell(player, SPELL_TREAT, true); + } + else + { + int32 trickspell=0; + switch (rand()%9) // note that female characters can get male costumes and vice versa + { + case 0: + trickspell=24753; // cannot cast, random 30sec + break; + case 1: + trickspell=24713; // lepper gnome costume + break; + case 2: + trickspell=24735; // male ghost costume + break; + case 3: + trickspell=24736; // female ghostcostume + break; + case 4: + trickspell=24710; // male ninja costume + break; + case 5: + trickspell=24711; // female ninja costume + break; + case 6: + trickspell=24708; // male pirate costume + break; + case 7: + trickspell=24709; // female pirate costume + break; + case 8: + trickspell=24723; // skeleton costume + break; + } + player->CastSpell(player, trickspell, true); + } + return true; // prevent mangos core handling + } + return false; // the player didn't select "trick or treat" or cheated, normal core handling +} + +void AddSC_npc_innkeeper() +{ + Script *newscript; + newscript = new Script; + newscript->Name="npc_innkeeper"; + newscript->pGossipHello = &GossipHello_npc_innkeeper; + newscript->pGossipSelect = &GossipSelect_npc_innkeeper; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/npc/npc_professions.cpp b/src/bindings/scripts/scripts/npc/npc_professions.cpp new file mode 100644 index 00000000000..65487786058 --- /dev/null +++ b/src/bindings/scripts/scripts/npc/npc_professions.cpp @@ -0,0 +1,1205 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Npc_Professions +SD%Complete: 80 +SDComment: Provides learn/unlearn/relearn-options for professions. Not supported: Unlearn engineering, re-learn engineering, re-learn leatherworking. +SDCategory: NPCs +EndScriptData */ + +#include "precompiled.h" + +/* +A few notes for future developement: +- A full implementation of gossip for GO's is required. They must have the same scripting capabilities as creatures. Basically, +there is no difference here (except that default text is chosen with `gameobject_template`.`data3` (for GO type2, different dataN for a few others) +- It's possible blacksmithing still require some tweaks and adjustments due to the way we _have_ to use reputation. +*/ + +/* +-- UPDATE `gameobject_template` SET `ScriptName` = 'go_soothsaying_for_dummies' WHERE `entry` = 177226; +*/ + +/*### +# to be removed from here (->ncp_text). This is data for database projects. +###*/ +#define TALK_MUST_UNLEARN_WEAPON "You must forget your weapon type specialty before I can help you. Go to Everlook in Winterspring and seek help there." + +#define TALK_HAMMER_LEARN "Ah, a seasoned veteran you once were. I know you are capable, you merely need to ask and I shall teach you the way of the hammersmith." +#define TALK_AXE_LEARN "Ah, a seasoned veteran you once were. I know you are capable, you merely need to ask and I shall teach you the way of the axesmith." +#define TALK_SWORD_LEARN "Ah, a seasoned veteran you once were. I know you are capable, you merely need to ask and I shall teach you the way of the swordsmith." + +#define TALK_HAMMER_UNLEARN "Forgetting your Hammersmithing skill is not something to do lightly. If you choose to abandon it you will forget all recipes that require Hammersmithing to create!" +#define TALK_AXE_UNLEARN "Forgetting your Axesmithing skill is not something to do lightly. If you choose to abandon it you will forget all recipes that require Axesmithing to create!" +#define TALK_SWORD_UNLEARN "Forgetting your Swordsmithing skill is not something to do lightly. If you choose to abandon it you will forget all recipes that require Swordsmithing to create!" + +/*### +# generic defines +###*/ + +#define GOSSIP_SENDER_LEARN 50 +#define GOSSIP_SENDER_UNLEARN 51 +#define GOSSIP_SENDER_CHECK 52 + +/*### +# gossip item and box texts +###*/ + +#define GOSSIP_LEARN_POTION "Please teach me how to become a Master of Potions, Lauranna" +#define GOSSIP_UNLEARN_POTION "I wish to unlearn Potion Mastery" +#define GOSSIP_LEARN_TRANSMUTE "Please teach me how to become a Master of Transmutations, Zarevhi" +#define GOSSIP_UNLEARN_TRANSMUTE "I wish to unlearn Transmutation Mastery" +#define GOSSIP_LEARN_ELIXIR "Please teach me how to become a Master of Elixirs, Lorokeem" +#define GOSSIP_UNLEARN_ELIXIR "I wish to unlearn Elixir Mastery" + +#define BOX_UNLEARN_ALCHEMY_SPEC "Do you really want to unlearn your alchemy specialty and lose all associated recipes? \n Cost: " + +#define GOSSIP_WEAPON_LEARN "Please teach me how to become a Weaponsmith" +#define GOSSIP_WEAPON_UNLEARN "I wish to unlearn the art of Weaponsmithing" +#define GOSSIP_ARMOR_LEARN "Please teach me how to become a Armorsmith" +#define GOSSIP_ARMOR_UNLEARN "I wish to unlearn the art of Armorsmithing" + +#define GOSSIP_UNLEARN_SMITH_SPEC "I wish to unlearn my blacksmith specialty" +#define BOX_UNLEARN_ARMORORWEAPON "Do you really want to unlearn your blacksmith specialty and lose all associated recipes? \n Cost: " + +#define GOSSIP_LEARN_HAMMER "Please teach me how to become a Hammersmith, Lilith" +#define GOSSIP_UNLEARN_HAMMER "I wish to unlearn Hammersmithing" +#define GOSSIP_LEARN_AXE "Please teach me how to become a Axesmith, Kilram" +#define GOSSIP_UNLEARN_AXE "I wish to unlearn Axesmithing" +#define GOSSIP_LEARN_SWORD "Please teach me how to become a Swordsmith, Seril" +#define GOSSIP_UNLEARN_SWORD "I wish to unlearn Swordsmithing" + +#define BOX_UNLEARN_WEAPON_SPEC "Do you really want to unlearn your weaponsmith specialty and lose all associated recipes? \n Cost: " + +#define GOSSIP_LEARN_DRAGON "I am absolutely certain that i want to learn dragonscale leatherworking" +#define GOSSIP_UNLEARN_DRAGON "I wish to unlearn Dragonscale Leatherworking" +#define GOSSIP_LEARN_ELEMENTAL "I am absolutely certain that i want to learn elemental leatherworking" +#define GOSSIP_UNLEARN_ELEMENTAL "I wish to unlearn Elemental Leatherworking" +#define GOSSIP_LEARN_TRIBAL "I am absolutely certain that i want to learn tribal leatherworking" +#define GOSSIP_UNLEARN_TRIBAL "I wish to unlearn Tribal Leatherworking" + +#define BOX_UNLEARN_LEATHER_SPEC "Do you really want to unlearn your leatherworking specialty and lose all associated recipes? \n Cost: " + +#define GOSSIP_LEARN_SPELLFIRE "Please teach me how to become a Spellcloth tailor" +#define GOSSIP_UNLEARN_SPELLFIRE "I wish to unlearn Spellfire Tailoring" +#define GOSSIP_LEARN_MOONCLOTH "Please teach me how to become a Mooncloth tailor" +#define GOSSIP_UNLEARN_MOONCLOTH "I wish to unlearn Mooncloth Tailoring" +#define GOSSIP_LEARN_SHADOWEAVE "Please teach me how to become a Shadoweave tailor" +#define GOSSIP_UNLEARN_SHADOWEAVE "I wish to unlearn Shadoweave Tailoring" + +#define BOX_UNLEARN_TAILOR_SPEC "Do you really want to unlearn your tailoring specialty and lose all associated recipes? \n Cost: " + +#define GOSSIP_LEARN_GOBLIN "I am absolutely certain that i want to learn Goblin engineering" +#define GOSSIP_LEARN_GNOMISH "I am absolutely certain that i want to learn Gnomish engineering" + +/*### +# spells defines +###*/ + +#define S_WEAPON 9787 +#define S_ARMOR 9788 +#define S_HAMMER 17040 +#define S_AXE 17041 +#define S_SWORD 17039 + +#define S_LEARN_WEAPON 9789 +#define S_LEARN_ARMOR 9790 +#define S_LEARN_HAMMER 39099 +#define S_LEARN_AXE 39098 +#define S_LEARN_SWORD 39097 + +#define S_UNLEARN_WEAPON 36436 +#define S_UNLEARN_ARMOR 36435 +#define S_UNLEARN_HAMMER 36441 +#define S_UNLEARN_AXE 36439 +#define S_UNLEARN_SWORD 36438 + +#define S_REP_ARMOR 17451 +#define S_REP_WEAPON 17452 + +#define REP_ARMOR 46 +#define REP_WEAPON 289 +#define REP_HAMMER 569 +#define REP_AXE 570 +#define REP_SWORD 571 + +#define S_DRAGON 10656 +#define S_ELEMENTAL 10658 +#define S_TRIBAL 10660 + +#define S_LEARN_DRAGON 10657 +#define S_LEARN_ELEMENTAL 10659 +#define S_LEARN_TRIBAL 10661 + +#define S_UNLEARN_DRAGON 36434 +#define S_UNLEARN_ELEMENTAL 36328 +#define S_UNLEARN_TRIBAL 36433 + +#define S_GOBLIN 20222 +#define S_GNOMISH 20219 + +#define S_LEARN_GOBLIN 20221 +#define S_LEARN_GNOMISH 20220 + +#define S_SPELLFIRE 26797 +#define S_MOONCLOTH 26798 +#define S_SHADOWEAVE 26801 + +#define S_LEARN_SPELLFIRE 26796 +#define S_LEARN_MOONCLOTH 26799 +#define S_LEARN_SHADOWEAVE 26800 + +#define S_UNLEARN_SPELLFIRE 41299 +#define S_UNLEARN_MOONCLOTH 41558 +#define S_UNLEARN_SHADOWEAVE 41559 + +#define S_TRANSMUTE 28672 +#define S_ELIXIR 28677 +#define S_POTION 28675 + +#define S_LEARN_TRANSMUTE 28674 +#define S_LEARN_ELIXIR 28678 +#define S_LEARN_POTION 28676 + +#define S_UNLEARN_TRANSMUTE 41565 +#define S_UNLEARN_ELIXIR 41564 +#define S_UNLEARN_POTION 41563 + +/*### +# formulas to calculate unlearning cost +###*/ + +int32 DoLearnCost(Player *player) //tailor, alchemy +{ + return 200000; +} + +int32 DoHighUnlearnCost(Player *player) //tailor, alchemy +{ + return 1500000; +} + +int32 DoMedUnlearnCost(Player *player) //blacksmith, leatherwork +{ + uint32 level = player->getLevel(); + if(level < 51) + return 250000; + else if (level < 66) + return 500000; + else + return 1000000; +} + +int32 DoLowUnlearnCost(Player *player) //blacksmith +{ + uint32 level = player->getLevel(); + if (level < 66) + return 50000; + else + return 100000; +} + +/*### +# unlearning related profession spells +###*/ + +bool EquippedOk(Player* player, uint32 spellId) +{ + SpellEntry const* spell = GetSpellStore()->LookupEntry(spellId); + + if( !spell ) + return false; + + for(int i=0; i<3; i++) + { + uint32 reqSpell = spell->EffectTriggerSpell[i]; + if( !reqSpell ) + continue; + + Item* pItem; + for(int j = EQUIPMENT_SLOT_START; j < EQUIPMENT_SLOT_END; j++) + { + pItem = player->GetItemByPos( INVENTORY_SLOT_BAG_0, j ); + if( pItem ) + if( pItem->GetProto()->RequiredSpell == reqSpell ) + { + //player has item equipped that require specialty. Not allow to unlearn, player has to unequip first + debug_log("SD2: player attempt to unlearn spell %u, but item %u is equipped.",reqSpell,pItem->GetProto()->ItemId); + return false; + } + } + } + return true; +} + +void ProfessionUnlearnSpells(Player *player, uint32 type) +{ + switch (type) + { + case 36436: // S_UNLEARN_WEAPON + player->removeSpell(36125); // Light Earthforged Blade + player->removeSpell(36128); // Light Emberforged Hammer + player->removeSpell(36126); // Light Skyforged Axe + break; + case 36435: // S_UNLEARN_ARMOR + player->removeSpell(36122); // Earthforged Leggings + player->removeSpell(36129); // Heavy Earthforged Breastplate + player->removeSpell(36130); // Stormforged Hauberk + player->removeSpell(34533); // Breastplate of Kings + player->removeSpell(34529); // Nether Chain Shirt + player->removeSpell(34534); // Bulwark of Kings + player->removeSpell(36257); // Bulwark of the Ancient Kings + player->removeSpell(36256); // Embrace of the Twisting Nether + player->removeSpell(34530); // Twisting Nether Chain Shirt + player->removeSpell(36124); // Windforged Leggings + break; + case 36441: // S_UNLEARN_HAMMER + player->removeSpell(36262); // Dragonstrike + player->removeSpell(34546); // Dragonmaw + player->removeSpell(34545); // Drakefist Hammer + player->removeSpell(36136); // Lavaforged Warhammer + player->removeSpell(34547); // Thunder + player->removeSpell(34567); // Deep Thunder + player->removeSpell(36263); // Stormherald + player->removeSpell(36137); // Great Earthforged Hammer + break; + case 36439: // S_UNLEARN_AXE + player->removeSpell(36260); // Wicked Edge of the Planes + player->removeSpell(34562); // Black Planar Edge + player->removeSpell(34541); // The Planar Edge + player->removeSpell(36134); // Stormforged Axe + player->removeSpell(36135); // Skyforged Great Axe + player->removeSpell(36261); // Bloodmoon + player->removeSpell(34543); // Lunar Crescent + player->removeSpell(34544); // Mooncleaver + break; + case 36438: // S_UNLEARN_SWORD + player->removeSpell(36258); // Blazefury + player->removeSpell(34537); // Blazeguard + player->removeSpell(34535); // Fireguard + player->removeSpell(36131); // Windforged Rapier + player->removeSpell(36133); // Stoneforged Claymore + player->removeSpell(34538); // Lionheart Blade + player->removeSpell(34540); // Lionheart Champion + player->removeSpell(36259); // Lionheart Executioner + break; + case 36434: // S_UNLEARN_DRAGON + player->removeSpell(36076); // Dragonstrike Leggings + player->removeSpell(36079); // Golden Dragonstrike Breastplate + player->removeSpell(35576); // Ebon Netherscale Belt + player->removeSpell(35577); // Ebon Netherscale Bracers + player->removeSpell(35575); // Ebon Netherscale Breastplate + player->removeSpell(35582); // Netherstrike Belt + player->removeSpell(35584); // Netherstrike Bracers + player->removeSpell(35580); // Netherstrike Breastplate + break; + case 36328: // S_UNLEARN_ELEMENTAL + player->removeSpell(36074); // Blackstorm Leggings + player->removeSpell(36077); // Primalstorm Breastplate + player->removeSpell(35590); // Primalstrike Belt + player->removeSpell(35591); // Primalstrike Bracers + player->removeSpell(35589); // Primalstrike Vest + break; + case 36433: // S_UNLEARN_TRIBAL + player->removeSpell(35585); // Windhawk Hauberk + player->removeSpell(35587); // Windhawk Belt + player->removeSpell(35588); // Windhawk Bracers + player->removeSpell(36075); // Wildfeather Leggings + player->removeSpell(36078); // Living Crystal Breastplate + break; + case 41299: // S_UNLEARN_SPELLFIRE + player->removeSpell(26752); // Spellfire Belt + player->removeSpell(26753); // Spellfire Gloves + player->removeSpell(26754); // Spellfire Robe + break; + case 41558: // S_UNLEARN_MOONCLOTH + player->removeSpell(26760); // Primal Mooncloth Belt + player->removeSpell(26761); // Primal Mooncloth Shoulders + player->removeSpell(26762); // Primal Mooncloth Robe + break; + case 41559: // S_UNLEARN_SHADOWEAVE + player->removeSpell(26756); // Frozen Shadoweave Shoulders + player->removeSpell(26757); // Frozen Shadoweave Boots + player->removeSpell(26758); // Frozen Shadoweave Robe + break; + } +} + +/*### +# start menues alchemy +###*/ + +bool HasAlchemySpell(Player *player) +{ + if(player->HasSpell(S_TRANSMUTE) || player->HasSpell(S_ELIXIR) || player->HasSpell(S_POTION)) + return true; + return false; +} + +bool GossipHello_npc_prof_alchemy(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + if (_Creature->isVendor()) + player->ADD_GOSSIP_ITEM(1, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + if(_Creature->isTrainer()) + player->ADD_GOSSIP_ITEM(2, GOSSIP_TEXT_TRAIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRAIN); + + uint32 eCreature = _Creature->GetEntry(); + + if (player->HasSkill(SKILL_ALCHEMY) && player->GetBaseSkillValue(SKILL_ALCHEMY)>=350 && player->getLevel() > 67) + { + if (player->GetQuestRewardStatus(10899) || player->GetQuestRewardStatus(10902) || player->GetQuestRewardStatus(10897)) + { + switch (eCreature) + { + case 22427: //Zarevhi + if (!HasAlchemySpell(player)) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_LEARN_TRANSMUTE, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 1); + if (player->HasSpell(S_TRANSMUTE)) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_UNLEARN_TRANSMUTE, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 4); + break; + case 19052: //Lorokeem + if (!HasAlchemySpell(player)) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_LEARN_ELIXIR, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 2); + if (player->HasSpell(S_ELIXIR)) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_UNLEARN_ELIXIR, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 5); + break; + case 17909: //Lauranna Thar'well + if (!HasAlchemySpell(player)) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_LEARN_POTION, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 3); + if (player->HasSpell(S_POTION)) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_UNLEARN_POTION, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 6); + break; + } + } + } + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + return true; +} + +void SendActionMenu_npc_prof_alchemy(Player *player, Creature *_Creature, uint32 action) +{ + switch(action) + { + case GOSSIP_ACTION_TRADE: + player->SEND_VENDORLIST( _Creature->GetGUID() ); + break; + case GOSSIP_ACTION_TRAIN: + player->SEND_TRAINERLIST( _Creature->GetGUID() ); + break; + //Learn Alchemy + case GOSSIP_ACTION_INFO_DEF + 1: + if(!player->HasSpell(S_TRANSMUTE) && player->GetMoney() >= DoLearnCost(player)) + { + player->CastSpell(player, S_LEARN_TRANSMUTE, true); + player->ModifyMoney(-DoLearnCost(player)); + } else + player->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, _Creature, 0, 0); + player->CLOSE_GOSSIP_MENU(); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + if(!player->HasSpell(S_ELIXIR) && player->GetMoney() >= DoLearnCost(player)) + { + player->CastSpell(player, S_LEARN_ELIXIR, true); + player->ModifyMoney(-DoLearnCost(player)); + } else + player->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, _Creature, 0, 0); + player->CLOSE_GOSSIP_MENU(); + break; + case GOSSIP_ACTION_INFO_DEF + 3: + if(!player->HasSpell(S_POTION) && player->GetMoney() >= DoLearnCost(player)) + { + player->CastSpell(player, S_LEARN_POTION, true); + player->ModifyMoney(-DoLearnCost(player)); + } else + player->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, _Creature, 0, 0); + player->CLOSE_GOSSIP_MENU(); + break; + //Unlearn Alchemy + case GOSSIP_ACTION_INFO_DEF + 4: + if(player->GetMoney() >= DoHighUnlearnCost(player)) + { + _Creature->CastSpell(player, S_UNLEARN_TRANSMUTE, true); + player->ModifyMoney(-DoHighUnlearnCost(player)); + } else + player->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, _Creature, 0, 0); + player->CLOSE_GOSSIP_MENU(); + break; + case GOSSIP_ACTION_INFO_DEF + 5: + if(player->GetMoney() >= DoHighUnlearnCost(player)) + { + _Creature->CastSpell(player, S_UNLEARN_ELIXIR, true); + player->ModifyMoney(-DoHighUnlearnCost(player)); + } else + player->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, _Creature, 0, 0); + player->CLOSE_GOSSIP_MENU(); + break; + case GOSSIP_ACTION_INFO_DEF + 6: + if(player->GetMoney() >= DoHighUnlearnCost(player)) + { + _Creature->CastSpell(player, S_UNLEARN_POTION, true); + player->ModifyMoney(-DoHighUnlearnCost(player)); + } else + player->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, _Creature, 0, 0); + player->CLOSE_GOSSIP_MENU(); + break; + } +} + +void SendConfirmLearn_npc_prof_alchemy(Player *player, Creature *_Creature, uint32 action) +{ + if(action) + { + uint32 eCreature = _Creature->GetEntry(); + switch(eCreature) + { + case 22427: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_LEARN_TRANSMUTE, GOSSIP_SENDER_CHECK, action); + //unknown textID () + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + case 19052: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_LEARN_ELIXIR, GOSSIP_SENDER_CHECK, action); + //unknown textID () + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + case 17909: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_LEARN_POTION, GOSSIP_SENDER_CHECK, action); + //unknown textID () + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + } + } +} + +void SendConfirmUnlearn_npc_prof_alchemy(Player *player, Creature *_Creature, uint32 action) +{ + if(action) + { + uint32 eCreature = _Creature->GetEntry(); + switch(eCreature) + { + case 22427: //Zarevhi + player->ADD_GOSSIP_ITEM_EXTENDED( 0, GOSSIP_UNLEARN_TRANSMUTE, GOSSIP_SENDER_CHECK, action, BOX_UNLEARN_ALCHEMY_SPEC, DoHighUnlearnCost(player)); + //unknown textID () + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + case 19052: //Lorokeem + player->ADD_GOSSIP_ITEM_EXTENDED( 0, GOSSIP_UNLEARN_ELIXIR, GOSSIP_SENDER_CHECK, action, BOX_UNLEARN_ALCHEMY_SPEC, DoHighUnlearnCost(player)); + //unknown textID () + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + case 17909: //Lauranna Thar'well + player->ADD_GOSSIP_ITEM_EXTENDED( 0, GOSSIP_UNLEARN_POTION, GOSSIP_SENDER_CHECK, action, BOX_UNLEARN_ALCHEMY_SPEC, DoHighUnlearnCost(player)); + //unknown textID () + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + } + } +} + +bool GossipSelect_npc_prof_alchemy(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + switch(sender) + { + case GOSSIP_SENDER_MAIN: SendActionMenu_npc_prof_alchemy(player, _Creature, action); break; + case GOSSIP_SENDER_LEARN: SendConfirmLearn_npc_prof_alchemy(player, _Creature, action); break; + case GOSSIP_SENDER_UNLEARN: SendConfirmUnlearn_npc_prof_alchemy(player, _Creature, action); break; + case GOSSIP_SENDER_CHECK: SendActionMenu_npc_prof_alchemy(player, _Creature, action); break; + } + return true; +} + +/*### +# start menues blacksmith +###*/ + +bool HasWeaponSub(Player *player) +{ + if (player->HasSpell(S_HAMMER) || player->HasSpell(S_AXE) || player->HasSpell(S_SWORD)) + return true; + return false; +} + +bool GossipHello_npc_prof_blacksmith(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + if (_Creature->isVendor()) + player->ADD_GOSSIP_ITEM(1, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + if(_Creature->isTrainer()) + player->ADD_GOSSIP_ITEM(2, GOSSIP_TEXT_TRAIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRAIN); + + uint32 eCreature = _Creature->GetEntry(); + //WEAPONSMITH & ARMORSMITH + if(player->GetBaseSkillValue(SKILL_BLACKSMITHING)>=225) + { + switch (eCreature) + { + case 11145: //Myolor Sunderfury + case 11176: //Krathok Moltenfist + if(!player->HasSpell(S_ARMOR) && !player->HasSpell(S_WEAPON) && player->GetReputationRank(REP_ARMOR) == REP_FRIENDLY) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ARMOR_LEARN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + if(!player->HasSpell(S_WEAPON) && !player->HasSpell(S_ARMOR) && player->GetReputationRank(REP_WEAPON) == REP_FRIENDLY) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_WEAPON_LEARN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + break; + case 11146: //Ironus Coldsteel + case 11178: //Borgosh Corebender + if(player->HasSpell(S_WEAPON)) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_WEAPON_UNLEARN, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 3); + break; + case 5164: //Grumnus Steelshaper + case 11177: //Okothos Ironrager + if(player->HasSpell(S_ARMOR)) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ARMOR_UNLEARN, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 4); + break; + } + } + //WEAPONSMITH SPEC + if(player->HasSpell(S_WEAPON) && player->getLevel() > 49 && player->GetBaseSkillValue(SKILL_BLACKSMITHING)>=250) + { + switch (eCreature) + { + case 11191: //Lilith the Lithe + if(!HasWeaponSub(player)) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_LEARN_HAMMER, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 5); + if(player->HasSpell(S_HAMMER)) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_UNLEARN_HAMMER, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 8); + break; + case 11192: //Kilram + if(!HasWeaponSub(player)) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_LEARN_AXE, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 6); + if(player->HasSpell(S_AXE)) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_UNLEARN_AXE, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 9); + break; + case 11193: //Seril Scourgebane + if(!HasWeaponSub(player)) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_LEARN_SWORD, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 7); + if(player->HasSpell(S_SWORD)) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_UNLEARN_SWORD, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 10); + break; + } + } + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + return true; +} + +void SendActionMenu_npc_prof_blacksmith(Player *player, Creature *_Creature, uint32 action) +{ + switch(action) + { + case GOSSIP_ACTION_TRADE: + player->SEND_VENDORLIST( _Creature->GetGUID() ); + break; + case GOSSIP_ACTION_TRAIN: + player->SEND_TRAINERLIST( _Creature->GetGUID() ); + break; + //Learn Armor/Weapon + case GOSSIP_ACTION_INFO_DEF + 1: + if(!player->HasSpell(S_ARMOR)) + { + player->CastSpell(player, S_LEARN_ARMOR, true); + //_Creature->CastSpell(player, S_REP_ARMOR, true); + } + player->CLOSE_GOSSIP_MENU(); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + if(!player->HasSpell(S_WEAPON)) + { + player->CastSpell(player, S_LEARN_WEAPON, true); + //_Creature->CastSpell(player, S_REP_WEAPON, true); + } + player->CLOSE_GOSSIP_MENU(); + break; + //Unlearn Armor/Weapon + case GOSSIP_ACTION_INFO_DEF + 3: + if(HasWeaponSub(player)) + { + //unknown textID (TALK_MUST_UNLEARN_WEAPON) + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + //Temporary, not offilike + _Creature->MonsterSay(TALK_MUST_UNLEARN_WEAPON,0,player->GetGUID()); + } + else if( EquippedOk(player,S_UNLEARN_WEAPON) ) + { + if( player->GetMoney() >= DoLowUnlearnCost(player) ) + { + player->CastSpell(player, S_UNLEARN_WEAPON, true); + ProfessionUnlearnSpells(player, S_UNLEARN_WEAPON); + player->ModifyMoney(-DoLowUnlearnCost(player)); + _Creature->CastSpell(player, S_REP_ARMOR, true); + player->CLOSE_GOSSIP_MENU(); + } else + player->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, _Creature, 0, 0); + } + else + { + player->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); + player->CLOSE_GOSSIP_MENU(); + } + break; + case GOSSIP_ACTION_INFO_DEF + 4: + if( EquippedOk(player,S_UNLEARN_ARMOR) ) + { + if( player->GetMoney() >= DoLowUnlearnCost(player) ) + { + player->CastSpell(player, S_UNLEARN_ARMOR, true); + ProfessionUnlearnSpells(player, S_UNLEARN_ARMOR); + player->ModifyMoney(-DoLowUnlearnCost(player)); + _Creature->CastSpell(player, S_REP_WEAPON, true); + } else + player->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, _Creature, 0, 0); + } else + player->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); + player->CLOSE_GOSSIP_MENU(); + break; + //Learn Hammer/Axe/Sword + case GOSSIP_ACTION_INFO_DEF + 5: + player->CastSpell(player, S_LEARN_HAMMER, true); + player->CLOSE_GOSSIP_MENU(); + break; + case GOSSIP_ACTION_INFO_DEF + 6: + player->CastSpell(player, S_LEARN_AXE, true); + player->CLOSE_GOSSIP_MENU(); + break; + case GOSSIP_ACTION_INFO_DEF + 7: + player->CastSpell(player, S_LEARN_SWORD, true); + player->CLOSE_GOSSIP_MENU(); + break; + //Unlearn Hammer/Axe/Sword + case GOSSIP_ACTION_INFO_DEF + 8: + if( EquippedOk(player,S_UNLEARN_HAMMER) ) + { + if( player->GetMoney() >= DoMedUnlearnCost(player)) + { + player->CastSpell(player, S_UNLEARN_HAMMER, true); + ProfessionUnlearnSpells(player, S_UNLEARN_HAMMER); + player->ModifyMoney(-DoMedUnlearnCost(player)); + } else + player->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, _Creature, 0, 0); + } else + player->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); + player->CLOSE_GOSSIP_MENU(); + break; + case GOSSIP_ACTION_INFO_DEF + 9: + if( EquippedOk(player,S_UNLEARN_AXE) ) + { + if( player->GetMoney() >= DoMedUnlearnCost(player)) + { + player->CastSpell(player, S_UNLEARN_AXE, true); + ProfessionUnlearnSpells(player, S_UNLEARN_AXE); + player->ModifyMoney(-DoMedUnlearnCost(player)); + } else + player->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, _Creature, 0, 0); + } else + player->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); + player->CLOSE_GOSSIP_MENU(); + break; + case GOSSIP_ACTION_INFO_DEF + 10: + if( EquippedOk(player,S_UNLEARN_SWORD) ) + { + if( player->GetMoney() >= DoMedUnlearnCost(player)) + { + player->CastSpell(player, S_UNLEARN_SWORD, true); + ProfessionUnlearnSpells(player, S_UNLEARN_SWORD); + player->ModifyMoney(-DoMedUnlearnCost(player)); + } else + player->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, _Creature, 0, 0); + } else + player->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); + player->CLOSE_GOSSIP_MENU(); + break; + } +} + +void SendConfirmLearn_npc_prof_blacksmith(Player *player, Creature *_Creature, uint32 action) +{ + if(action) + { + uint32 eCreature = _Creature->GetEntry(); + switch(eCreature) + { + case 11191: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_LEARN_HAMMER, GOSSIP_SENDER_CHECK, action); + //unknown textID (TALK_HAMMER_LEARN) + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + case 11192: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_LEARN_AXE, GOSSIP_SENDER_CHECK, action); + //unknown textID (TALK_AXE_LEARN) + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + case 11193: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_LEARN_SWORD, GOSSIP_SENDER_CHECK, action); + //unknown textID (TALK_SWORD_LEARN) + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + } + } +} + +void SendConfirmUnlearn_npc_prof_blacksmith(Player *player, Creature *_Creature, uint32 action) +{ + if(action) + { + uint32 eCreature = _Creature->GetEntry(); + switch(eCreature) + { + case 11146: //Ironus Coldsteel + case 11178: //Borgosh Corebender + case 5164: //Grumnus Steelshaper + case 11177: //Okothos Ironrager + player->ADD_GOSSIP_ITEM_EXTENDED( 0, GOSSIP_UNLEARN_SMITH_SPEC, GOSSIP_SENDER_CHECK, action, BOX_UNLEARN_ARMORORWEAPON, DoLowUnlearnCost(player)); + //unknown textID (TALK_UNLEARN_AXEORWEAPON) + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + + case 11191: + player->ADD_GOSSIP_ITEM_EXTENDED( 0, GOSSIP_UNLEARN_HAMMER, GOSSIP_SENDER_CHECK, action, BOX_UNLEARN_WEAPON_SPEC, DoMedUnlearnCost(player)); + //unknown textID (TALK_HAMMER_UNLEARN) + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + case 11192: + player->ADD_GOSSIP_ITEM_EXTENDED( 0, GOSSIP_UNLEARN_AXE, GOSSIP_SENDER_CHECK, action, BOX_UNLEARN_WEAPON_SPEC, DoMedUnlearnCost(player)); + //unknown textID (TALK_AXE_UNLEARN) + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + case 11193: + player->ADD_GOSSIP_ITEM_EXTENDED( 0, GOSSIP_UNLEARN_SWORD, GOSSIP_SENDER_CHECK, action, BOX_UNLEARN_WEAPON_SPEC, DoMedUnlearnCost(player)); + //unknown textID (TALK_SWORD_UNLEARN) + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + } + } +} + +bool GossipSelect_npc_prof_blacksmith(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + switch(sender) + { + case GOSSIP_SENDER_MAIN: SendActionMenu_npc_prof_blacksmith(player, _Creature, action); break; + case GOSSIP_SENDER_LEARN: SendConfirmLearn_npc_prof_blacksmith(player, _Creature, action); break; + case GOSSIP_SENDER_UNLEARN: SendConfirmUnlearn_npc_prof_blacksmith(player, _Creature, action); break; + case GOSSIP_SENDER_CHECK: SendActionMenu_npc_prof_blacksmith(player, _Creature, action); break; + } + return true; +} + +/*bool QuestComplete_npc_prof_blacksmith( Player *player, Creature *_Creature, Quest const *_Quest ) +{ + if ( (_Quest->GetQuestId() == 5283) || (_Quest->GetQuestId() == 5301) ) //armorsmith + _Creature->CastSpell(player, 17451, true); + + if ( (_Quest->GetQuestId() == 5284) || (_Quest->GetQuestId() == 5302) ) //weaponsmith + _Creature->CastSpell(player, 17452, true); + + return true; +}*/ + +/*### +# start menues leatherworking +###*/ + +bool GossipHello_npc_prof_leather(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + if (_Creature->isVendor()) + player->ADD_GOSSIP_ITEM(1, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + if(_Creature->isTrainer()) + player->ADD_GOSSIP_ITEM(2, GOSSIP_TEXT_TRAIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRAIN); + + uint32 eCreature = _Creature->GetEntry(); + + if(player->HasSkill(SKILL_LEATHERWORKING) && player->GetBaseSkillValue(SKILL_LEATHERWORKING)>=250 && player->getLevel() > 49 ) + { + switch (eCreature) + { + case 7866: //Peter Galen + case 7867: //Thorkaf Dragoneye + if(player->HasSpell(S_DRAGON)) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_UNLEARN_DRAGON, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 1); + break; + case 7868: //Sarah Tanner + case 7869: //Brumn Winterhoof + if(player->HasSpell(S_ELEMENTAL)) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_UNLEARN_ELEMENTAL, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 2); + break; + case 7870: //Caryssia Moonhunter + case 7871: //Se'Jib + if(player->HasSpell(S_TRIBAL)) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_UNLEARN_TRIBAL, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 3); + break; + } + } + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + return true; +} + +void SendActionMenu_npc_prof_leather(Player *player, Creature *_Creature, uint32 action) +{ + switch(action) + { + case GOSSIP_ACTION_TRADE: + player->SEND_VENDORLIST( _Creature->GetGUID() ); + break; + case GOSSIP_ACTION_TRAIN: + player->SEND_TRAINERLIST( _Creature->GetGUID() ); + break; + //Unlearn Leather + case GOSSIP_ACTION_INFO_DEF + 1: + if( EquippedOk(player,S_UNLEARN_DRAGON) ) + { + if( player->GetMoney() >= DoMedUnlearnCost(player) ) + { + player->CastSpell(player, S_UNLEARN_DRAGON, true); + ProfessionUnlearnSpells(player, S_UNLEARN_DRAGON); + player->ModifyMoney(-DoMedUnlearnCost(player)); + } else + player->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, _Creature, 0, 0); + } else + player->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); + player->CLOSE_GOSSIP_MENU(); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + if( EquippedOk(player,S_UNLEARN_ELEMENTAL) ) + { + if( player->GetMoney() >= DoMedUnlearnCost(player) ) + { + player->CastSpell(player, S_UNLEARN_ELEMENTAL, true); + ProfessionUnlearnSpells(player, S_UNLEARN_ELEMENTAL); + player->ModifyMoney(-DoMedUnlearnCost(player)); + } else + player->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, _Creature, 0, 0); + } else + player->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); + player->CLOSE_GOSSIP_MENU(); + break; + case GOSSIP_ACTION_INFO_DEF + 3: + if( EquippedOk(player,S_UNLEARN_TRIBAL) ) + { + if(player->GetMoney() >= DoMedUnlearnCost(player)) + { + player->CastSpell(player, S_UNLEARN_TRIBAL, true); + ProfessionUnlearnSpells(player, S_UNLEARN_TRIBAL); + player->ModifyMoney(-DoMedUnlearnCost(player)); + } else + player->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, _Creature, 0, 0); + } else + player->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); + player->CLOSE_GOSSIP_MENU(); + break; + } +} + +void SendConfirmUnlearn_npc_prof_leather(Player *player, Creature *_Creature, uint32 action) +{ + if(action) + { + uint32 eCreature = _Creature->GetEntry(); + switch(eCreature) + { + case 7866: //Peter Galen + case 7867: //Thorkaf Dragoneye + player->ADD_GOSSIP_ITEM_EXTENDED( 0, GOSSIP_UNLEARN_DRAGON, GOSSIP_SENDER_CHECK, action, BOX_UNLEARN_LEATHER_SPEC, DoMedUnlearnCost(player)); + //unknown textID () + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + case 7868: //Sarah Tanner + case 7869: //Brumn Winterhoof + player->ADD_GOSSIP_ITEM_EXTENDED( 0, GOSSIP_UNLEARN_ELEMENTAL, GOSSIP_SENDER_CHECK, action, BOX_UNLEARN_LEATHER_SPEC, DoMedUnlearnCost(player)); + //unknown textID () + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + case 7870: //Caryssia Moonhunter + case 7871: //Se'Jib + player->ADD_GOSSIP_ITEM_EXTENDED( 0, GOSSIP_UNLEARN_TRIBAL, GOSSIP_SENDER_CHECK, action, BOX_UNLEARN_LEATHER_SPEC, DoMedUnlearnCost(player)); + //unknown textID () + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + } + } +} + +bool GossipSelect_npc_prof_leather(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + switch(sender) + { + case GOSSIP_SENDER_MAIN: SendActionMenu_npc_prof_leather(player, _Creature, action); break; + case GOSSIP_SENDER_UNLEARN: SendConfirmUnlearn_npc_prof_leather(player, _Creature, action); break; + case GOSSIP_SENDER_CHECK: SendActionMenu_npc_prof_leather(player, _Creature, action); break; + } + return true; +} + +/*### +# start menues tailoring +###*/ + +bool HasTailorSpell(Player *player) +{ + if (player->HasSpell(S_MOONCLOTH) || player->HasSpell(S_SHADOWEAVE) || player->HasSpell(S_SPELLFIRE)) + return true; + return false; +} + +bool GossipHello_npc_prof_tailor(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + if (_Creature->isVendor()) + player->ADD_GOSSIP_ITEM(1, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + if (_Creature->isTrainer()) + player->ADD_GOSSIP_ITEM(2, GOSSIP_TEXT_TRAIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRAIN); + + uint32 eCreature = _Creature->GetEntry(); + //TAILORING SPEC + if (player->HasSkill(SKILL_TAILORING) && player->GetBaseSkillValue(SKILL_TAILORING)>=350 && player->getLevel() > 59) + { + if (player->GetQuestRewardStatus(10831) || player->GetQuestRewardStatus(10832) || player->GetQuestRewardStatus(10833)) + { + switch (eCreature) + { + case 22213: //Gidge Spellweaver + if (!HasTailorSpell(player)) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_LEARN_SPELLFIRE, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 1); + if (player->HasSpell(S_SPELLFIRE)) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_UNLEARN_SPELLFIRE, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 4); + break; + case 22208: //Nasmara Moonsong + if (!HasTailorSpell(player)) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_LEARN_MOONCLOTH, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 2); + if (player->HasSpell(S_MOONCLOTH)) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_UNLEARN_MOONCLOTH, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 5); + break; + case 22212: //Andrion Darkspinner + if (!HasTailorSpell(player)) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_LEARN_SHADOWEAVE, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 3); + if (player->HasSpell(S_SHADOWEAVE)) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_UNLEARN_SHADOWEAVE, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 6); + break; + } + } + } + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + return true; +} + +void SendActionMenu_npc_prof_tailor(Player *player, Creature *_Creature, uint32 action) +{ + switch(action) + { + case GOSSIP_ACTION_TRADE: + player->SEND_VENDORLIST( _Creature->GetGUID() ); + break; + case GOSSIP_ACTION_TRAIN: + player->SEND_TRAINERLIST( _Creature->GetGUID() ); + break; + //Learn Tailor + case GOSSIP_ACTION_INFO_DEF + 1: + if(!player->HasSpell(S_SPELLFIRE) && player->GetMoney() >= DoLearnCost(player)) + { + player->CastSpell(player, S_LEARN_SPELLFIRE, true); + player->ModifyMoney(-DoLearnCost(player)); + } else + player->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, _Creature, 0, 0); + player->CLOSE_GOSSIP_MENU(); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + if(!player->HasSpell(S_MOONCLOTH) && player->GetMoney() >= DoLearnCost(player)) + { + player->CastSpell(player, S_LEARN_MOONCLOTH, true); + player->ModifyMoney(-DoLearnCost(player)); + } else + player->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, _Creature, 0, 0); + player->CLOSE_GOSSIP_MENU(); + break; + case GOSSIP_ACTION_INFO_DEF + 3: + if(!player->HasSpell(S_SHADOWEAVE) && player->GetMoney() >= DoLearnCost(player)) + { + player->CastSpell(player, S_LEARN_SHADOWEAVE, true); + player->ModifyMoney(-DoLearnCost(player)); + } else + player->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, _Creature, 0, 0); + player->CLOSE_GOSSIP_MENU(); + break; + //Unlearn Tailor + case GOSSIP_ACTION_INFO_DEF + 4: + if( EquippedOk(player,S_UNLEARN_SPELLFIRE) ) + { + if( player->GetMoney() >= DoHighUnlearnCost(player) ) + { + player->CastSpell(player, S_UNLEARN_SPELLFIRE, true); + ProfessionUnlearnSpells(player, S_UNLEARN_SPELLFIRE); + player->ModifyMoney(-DoHighUnlearnCost(player)); + } else + player->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, _Creature, 0, 0); + } else + player->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); + player->CLOSE_GOSSIP_MENU(); + break; + case GOSSIP_ACTION_INFO_DEF + 5: + if( EquippedOk(player,S_UNLEARN_MOONCLOTH) ) + { + if( player->GetMoney() >= DoHighUnlearnCost(player) ) + { + player->CastSpell(player, S_UNLEARN_MOONCLOTH, true); + ProfessionUnlearnSpells(player, S_UNLEARN_MOONCLOTH); + player->ModifyMoney(-DoHighUnlearnCost(player)); + } else + player->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, _Creature, 0, 0); + } else + player->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); + player->CLOSE_GOSSIP_MENU(); + break; + case GOSSIP_ACTION_INFO_DEF + 6: + if( EquippedOk(player,S_UNLEARN_SHADOWEAVE) ) + { + if( player->GetMoney() >= DoHighUnlearnCost(player) ) + { + player->CastSpell(player, S_UNLEARN_SHADOWEAVE, true); + ProfessionUnlearnSpells(player, S_UNLEARN_SHADOWEAVE); + player->ModifyMoney(-DoHighUnlearnCost(player)); + } else + player->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, _Creature, 0, 0); + } else + player->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); + player->CLOSE_GOSSIP_MENU(); + break; + } +} + +void SendConfirmLearn_npc_prof_tailor(Player *player, Creature *_Creature, uint32 action) +{ + if(action) + { + uint32 eCreature = _Creature->GetEntry(); + switch(eCreature) + { + case 22213: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_LEARN_SPELLFIRE, GOSSIP_SENDER_CHECK, action); + //unknown textID () + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + case 22208: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_LEARN_MOONCLOTH, GOSSIP_SENDER_CHECK, action); + //unknown textID () + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + case 22212: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_LEARN_SHADOWEAVE, GOSSIP_SENDER_CHECK, action); + //unknown textID () + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + } + } +} + +void SendConfirmUnlearn_npc_prof_tailor(Player *player, Creature *_Creature, uint32 action) +{ + if(action) + { + uint32 eCreature = _Creature->GetEntry(); + switch(eCreature) + { + case 22213: //Gidge Spellweaver + player->ADD_GOSSIP_ITEM_EXTENDED( 0, GOSSIP_UNLEARN_SPELLFIRE, GOSSIP_SENDER_CHECK, action, BOX_UNLEARN_TAILOR_SPEC, DoHighUnlearnCost(player)); + //unknown textID () + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + case 22208: //Nasmara Moonsong + player->ADD_GOSSIP_ITEM_EXTENDED( 0, GOSSIP_UNLEARN_MOONCLOTH, GOSSIP_SENDER_CHECK, action, BOX_UNLEARN_TAILOR_SPEC, DoHighUnlearnCost(player)); + //unknown textID () + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + case 22212: //Andrion Darkspinner + player->ADD_GOSSIP_ITEM_EXTENDED( 0, GOSSIP_UNLEARN_SHADOWEAVE, GOSSIP_SENDER_CHECK, action,BOX_UNLEARN_TAILOR_SPEC, DoHighUnlearnCost(player)); + //unknown textID () + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + } + } +} + +bool GossipSelect_npc_prof_tailor(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + switch(sender) + { + case GOSSIP_SENDER_MAIN: SendActionMenu_npc_prof_tailor(player, _Creature, action); break; + case GOSSIP_SENDER_LEARN: SendConfirmLearn_npc_prof_tailor(player, _Creature, action); break; + case GOSSIP_SENDER_UNLEARN: SendConfirmUnlearn_npc_prof_tailor(player, _Creature, action); break; + case GOSSIP_SENDER_CHECK: SendActionMenu_npc_prof_tailor(player, _Creature, action); break; + } + return true; +} + +/*### +# start menues for GO (engineering and leatherworking) +###*/ + +/*bool GOHello_go_soothsaying_for_dummies(Player *player, GameObject* _GO) +{ + player->PlayerTalkClass->GetGossipMenu()->AddMenuItem(0,GOSSIP_LEARN_DRAGON, GOSSIP_SENDER_INFO, GOSSIP_ACTION_INFO_DEF, "", 0); + + player->SEND_GOSSIP_MENU(5584, _GO->GetGUID()); + + return true; +}*/ + +/*### +# +###*/ + +void AddSC_npc_professions() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npc_prof_alchemy"; + newscript->pGossipHello = &GossipHello_npc_prof_alchemy; + newscript->pGossipSelect = &GossipSelect_npc_prof_alchemy; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_prof_blacksmith"; + newscript->pGossipHello = &GossipHello_npc_prof_blacksmith; + newscript->pGossipSelect = &GossipSelect_npc_prof_blacksmith; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_prof_leather"; + newscript->pGossipHello = &GossipHello_npc_prof_leather; + newscript->pGossipSelect = &GossipSelect_npc_prof_leather; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_prof_tailor"; + newscript->pGossipHello = &GossipHello_npc_prof_tailor; + newscript->pGossipSelect = &GossipSelect_npc_prof_tailor; + m_scripts[nrscripts++] = newscript; + + /*newscript = new Script; + newscript->Name="go_soothsaying_for_dummies"; + newscript->pGOHello = &GOHello_go_soothsaying_for_dummies; + //newscript->pGossipSelect = &GossipSelect_go_soothsaying_for_dummies; + m_scripts[nrscripts++] = newscript;*/ +} diff --git a/src/bindings/scripts/scripts/npc/npcs_special.cpp b/src/bindings/scripts/scripts/npc/npcs_special.cpp new file mode 100644 index 00000000000..a8ea8612c58 --- /dev/null +++ b/src/bindings/scripts/scripts/npc/npcs_special.cpp @@ -0,0 +1,878 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Npcs_Special +SD%Complete: 100 +SDComment: To be used for special NPCs that are located globally. Support for quest 3861 (Cluck!), 6622 and 6624 (Triage) +SDCategory: NPCs +EndScriptData +*/ + +/* ContentData +npc_chicken_cluck 100% support for quest 3861 (Cluck!) +npc_dancing_flames 100% midsummer event NPC +npc_guardian 100% guardianAI used to prevent players from accessing off-limits areas. Not in use by SD2 +npc_injured_patient 100% patients for triage-quests (6622 and 6624) +npc_doctor 100% Gustaf Vanhowzen and Gregory Victor, quest 6622 and 6624 (Triage) +npc_mount_vendor 100% Regular mount vendors all over the world. Display gossip if player doesn't meet the requirements to buy +npc_rogue_trainer 80% Scripted trainers, so they are able to offer item 17126 for class quest 6681 +npc_sayge 100% Darkmoon event fortune teller, buff player based on answers given +EndContentData */ + +#include "precompiled.h" + +/*######## +# npc_chicken_cluck +#########*/ + +#define QUEST_CLUCK 3861 +#define EMOTE_A_HELLO "looks up at you quizzically. Maybe you should inspect it?" +#define EMOTE_H_HELLO "looks at you unexpectadly." +#define CLUCK_TEXT2 "starts pecking at the feed." +#define FACTION_FRIENDLY 84 +#define FACTION_CHICKEN 31 + +struct MANGOS_DLL_DECL npc_chicken_cluckAI : public ScriptedAI +{ + npc_chicken_cluckAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 ResetFlagTimer; + + void Reset() + { + ResetFlagTimer = 120000; + + m_creature->setFaction(FACTION_CHICKEN); + m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + } + + void Aggro(Unit *who) {} + + void UpdateAI(const uint32 diff) + { + // Reset flags after a certain time has passed so that the next player has to start the 'event' again + if(m_creature->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER)) + { + if(ResetFlagTimer < diff) + EnterEvadeMode(); + else ResetFlagTimer -= diff; + } + + if(m_creature->SelectHostilTarget() && m_creature->getVictim()) + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_chicken_cluck(Creature *_Creature) +{ + return new npc_chicken_cluckAI(_Creature); +} + +bool ReceiveEmote_npc_chicken_cluck( Player *player, Creature *_Creature, uint32 emote ) +{ + if( emote == TEXTEMOTE_CHICKEN ) + { + if( player->GetTeam() == ALLIANCE ) + { + if( rand()%30 == 1 ) + { + if( player->GetQuestStatus(QUEST_CLUCK) == QUEST_STATUS_NONE ) + { + _Creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + _Creature->setFaction(FACTION_FRIENDLY); + _Creature->MonsterTextEmote(EMOTE_A_HELLO, 0); + } + } + } else + _Creature->MonsterTextEmote(EMOTE_H_HELLO,0); + } + if( emote == TEXTEMOTE_CHEER && player->GetTeam() == ALLIANCE ) + if( player->GetQuestStatus(QUEST_CLUCK) == QUEST_STATUS_COMPLETE ) + { + _Creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + _Creature->setFaction(FACTION_FRIENDLY); + _Creature->MonsterTextEmote(CLUCK_TEXT2, 0); + } + + return true; +} + +bool QuestAccept_npc_chicken_cluck(Player *player, Creature *_Creature, const Quest *_Quest ) +{ + if(_Quest->GetQuestId() == QUEST_CLUCK) + ((npc_chicken_cluckAI*)_Creature->AI())->Reset(); + + return true; +} + +bool QuestComplete_npc_chicken_cluck(Player *player, Creature *_Creature, const Quest *_Quest) +{ + if(_Quest->GetQuestId() == QUEST_CLUCK) + ((npc_chicken_cluckAI*)_Creature->AI())->Reset(); + + return true; +} + +/*###### +## npc_dancing_flames +######*/ + +bool ReceiveEmote_npc_dancing_flames( Player *player, Creature *_Creature, uint32 emote ) +{ + if( emote == TEXTEMOTE_DANCE ) + _Creature->CastSpell(player,47057,false); + + return true; +} + +/*###### +## Triage quest +######*/ + +#define SAY_DOC1 "I'm saved! Thank you, doctor!" +#define SAY_DOC2 "HOORAY! I AM SAVED!" +#define SAY_DOC3 "Sweet, sweet embrace... take me..." + +struct Location +{ + float x, y, z, o; +}; + +#define DOCTOR_ALLIANCE 12939 + +static Location AllianceCoords[]= +{ + { // Top-far-right bunk as seen from entrance + -3757.38, -4533.05, 14.16, 3.62 + }, + { // Top-far-left bunk + -3754.36, -4539.13, 14.16, 5.13 + }, + { // Far-right bunk + -3749.54, -4540.25, 14.28, 3.34 + }, + { // Right bunk near entrance + -3742.10, -4536.85, 14.28, 3.64 + }, + { // Far-left bunk + -3755.89, -4529.07, 14.05, 0.57 + }, + { // Mid-left bunk + -3749.51, -4527.08, 14.07, 5.26 + }, + { // Left bunk near entrance + -3746.37, -4525.35, 14.16, 5.22 + }, +}; + +#define ALLIANCE_COORDS 7 + +//alliance run to where +#define A_RUNTOX -3742.96 +#define A_RUNTOY -4531.52 +#define A_RUNTOZ 11.91 + +#define DOCTOR_HORDE 12920 + +static Location HordeCoords[]= +{ + { // Left, Behind + -1013.75, -3492.59, 62.62, 4.34 + }, + { // Right, Behind + -1017.72, -3490.92, 62.62, 4.34 + }, + { // Left, Mid + -1015.77, -3497.15, 62.82, 4.34 + }, + { // Right, Mid + -1019.51, -3495.49, 62.82, 4.34 + }, + { // Left, front + -1017.25, -3500.85, 62.98, 4.34 + }, + { // Right, Front + -1020.95, -3499.21, 62.98, 4.34 + } +}; + +#define HORDE_COORDS 6 + +//horde run to where +#define H_RUNTOX -1016.44 +#define H_RUNTOY -3508.48 +#define H_RUNTOZ 62.96 + +const uint32 AllianceSoldierId[3] = +{ + 12938, // 12938 Injured Alliance Soldier + 12936, // 12936 Badly injured Alliance Soldier + 12937 // 12937 Critically injured Alliance Soldier +}; + +const uint32 HordeSoldierId[3] = +{ + 12923, //12923 Injured Soldier + 12924, //12924 Badly injured Soldier + 12925 //12925 Critically injured Soldier +}; + +/*###### +## npc_doctor (handles both Gustaf Vanhowzen and Gregory Victor) +######*/ + +struct MANGOS_DLL_DECL npc_doctorAI : public ScriptedAI +{ + uint64 Playerguid; + + uint32 SummonPatient_Timer; + uint32 SummonPatientCount; + uint32 PatientDiedCount; + uint32 PatientSavedCount; + + bool Event; + + std::list Patients; + std::vector Coordinates; + + npc_doctorAI(Creature *c) : ScriptedAI(c) {Reset();} + + void Reset(){} + + void BeginEvent(Player* player); + void PatientDied(Location* Point); + void PatientSaved(Creature* soldier, Player* player, Location* Point); + void UpdateAI(const uint32 diff); + + void Aggro(Unit* who){} +}; + +/*##### +## npc_injured_patient (handles all the patients, no matter Horde or Alliance) +#####*/ + +struct MANGOS_DLL_DECL npc_injured_patientAI : public ScriptedAI +{ + npc_injured_patientAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint64 Doctorguid; + + Location* Coord; + + void Reset() + { + Doctorguid = 0; + + Coord = NULL; + //no select + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + //no regen health + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); + //to make them lay with face down + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, PLAYER_STATE_DEAD); + + uint32 mobId = m_creature->GetEntry(); + + switch (mobId) + { //lower max health + case 12923: + case 12938: //Injured Soldier + m_creature->SetHealth(uint32(m_creature->GetMaxHealth()*.75)); + break; + case 12924: + case 12936: //Badly injured Soldier + m_creature->SetHealth(uint32(m_creature->GetMaxHealth()*.50)); + break; + case 12925: + case 12937: //Critically injured Soldier + m_creature->SetHealth(uint32(m_creature->GetMaxHealth()*.25)); + break; + } + } + + void Aggro(Unit* who){} + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if (caster->GetTypeId() == TYPEID_PLAYER && m_creature->isAlive() && spell->Id == 20804) + { + if( (((Player*)caster)->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE) || (((Player*)caster)->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE)) + { + if(Doctorguid) + { + Creature* Doctor = ((Creature*)Unit::GetUnit((*m_creature), Doctorguid)); + if(Doctor) + ((npc_doctorAI*)Doctor->AI())->PatientSaved(m_creature, ((Player*)caster), Coord); + } + } + //make not selectable + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + //regen health + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); + //stand up + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, PLAYER_STATE_NONE); + DoSay(SAY_DOC1,LANG_UNIVERSAL,NULL); + + uint32 mobId = m_creature->GetEntry(); + m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + switch (mobId) + { + case 12923: + case 12924: + case 12925: + m_creature->GetMotionMaster()->MovePoint(0, H_RUNTOX, H_RUNTOY, H_RUNTOZ); + break; + case 12936: + case 12937: + case 12938: + m_creature->GetMotionMaster()->MovePoint(0, A_RUNTOX, A_RUNTOY, A_RUNTOZ); + break; + } + } + return; + } + + void UpdateAI(const uint32 diff) + { + if (m_creature->isAlive() && m_creature->GetHealth() > 6) + { //lower HP on every world tick makes it a useful counter, not officlone though + m_creature->SetHealth(uint32(m_creature->GetHealth()-5) ); + } + + if (m_creature->isAlive() && m_creature->GetHealth() <= 6) + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->setDeathState(JUST_DIED); + m_creature->SetFlag(UNIT_DYNAMIC_FLAGS, 32); + + if(Doctorguid) + { + Creature* Doctor = ((Creature*)Unit::GetUnit((*m_creature), Doctorguid)); + if(Doctor) + ((npc_doctorAI*)Doctor->AI())->PatientDied(Coord); + } + } + } +}; + +CreatureAI* GetAI_npc_injured_patient(Creature *_Creature) +{ + return new npc_injured_patientAI (_Creature); +} + +/* +npc_doctor (continue) +*/ + +void npc_doctorAI::BeginEvent(Player* player) +{ + Playerguid = player->GetGUID(); + + SummonPatient_Timer = 10000; + SummonPatientCount = 0; + PatientDiedCount = 0; + PatientSavedCount = 0; + + switch(m_creature->GetEntry()) + { + case DOCTOR_ALLIANCE: + for(uint8 i = 0; i < ALLIANCE_COORDS; ++i) + Coordinates.push_back(&AllianceCoords[i]); + break; + + case DOCTOR_HORDE: + for(uint8 i = 0; i < HORDE_COORDS; ++i) + Coordinates.push_back(&HordeCoords[i]); + break; + } + + Event = true; + + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); +} + +void npc_doctorAI::PatientDied(Location* Point) +{ + Player* player = ((Player*)Unit::GetUnit((*m_creature), Playerguid)); + if(player && ((player->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE) || (player->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE))) + { + PatientDiedCount++; + if (PatientDiedCount > 5 && Event) + { + if(player->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE) + player->FailQuest(6624); + else if(player->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE) + player->FailQuest(6622); + + Event = false; + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + Coordinates.push_back(Point); + } +} + +void npc_doctorAI::PatientSaved(Creature* soldier, Player* player, Location* Point) +{ + if(player && Playerguid == player->GetGUID()) + { + if((player->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE) || (player->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE)) + { + PatientSavedCount++; + if(PatientSavedCount == 15) + { + if(!Patients.empty()) + { + std::list::iterator itr; + for(itr = Patients.begin(); itr != Patients.end(); ++itr) + { + Creature* Patient = ((Creature*)Unit::GetUnit((*m_creature), *itr)); + if( Patient ) + Patient->setDeathState(JUST_DIED); + } + } + + if(player->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE) + player->AreaExploredOrEventHappens(6624); + else if(player->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE) + player->AreaExploredOrEventHappens(6622); + + Event = false; + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + Coordinates.push_back(Point); + } + } +} + +void npc_doctorAI::UpdateAI(const uint32 diff) +{ + if(Event && SummonPatientCount >= 20) + { + Event = false; + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + if(Event) + if(SummonPatient_Timer < diff) + { + Creature* Patient = NULL; + Location* Point = NULL; + + if(Coordinates.empty()) + return; + + std::vector::iterator itr = Coordinates.begin()+rand()%Coordinates.size(); + uint32 patientEntry = 0; + + switch(m_creature->GetEntry()) + { + case DOCTOR_ALLIANCE: patientEntry = AllianceSoldierId[rand()%3]; break; + case DOCTOR_HORDE: patientEntry = HordeSoldierId[rand()%3]; break; + default: + error_log("SD2: Invalid entry for Triage doctor. Please check your database"); + return; + } + + Point = *itr; + + Patient = m_creature->SummonCreature(patientEntry, Point->x, Point->y, Point->z, Point->o, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + + if(Patient) + { + Patients.push_back(Patient->GetGUID()); + ((npc_injured_patientAI*)Patient->AI())->Doctorguid = m_creature->GetGUID(); + if(Point) + ((npc_injured_patientAI*)Patient->AI())->Coord = Point; + Coordinates.erase(itr); + } + SummonPatient_Timer = 10000; + SummonPatientCount++; + }else SummonPatient_Timer -= diff; +} + +bool QuestAccept_npc_doctor(Player *player, Creature *creature, Quest const *quest ) +{ + if((quest->GetQuestId() == 6624) || (quest->GetQuestId() == 6622)) + ((npc_doctorAI*)creature->AI())->BeginEvent(player); + + return true; +} + +CreatureAI* GetAI_npc_doctor(Creature *_Creature) +{ + return new npc_doctorAI (_Creature); +} + +/*###### +## npc_guardian +######*/ + +#define SPELL_DEATHTOUCH 5 +#define SAY_AGGRO "This area is closed!" + +struct MANGOS_DLL_DECL npc_guardianAI : public ScriptedAI +{ + npc_guardianAI(Creature *c) : ScriptedAI(c) {Reset();} + + void Reset() + { + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if (m_creature->isAttackReady()) + { + m_creature->CastSpell(m_creature->getVictim(),SPELL_DEATHTOUCH, true); + m_creature->resetAttackTimer(); + } + } +}; + +CreatureAI* GetAI_npc_guardian(Creature *_Creature) +{ + return new npc_guardianAI (_Creature); +} + +/*###### +## npc_mount_vendor +######*/ + +bool GossipHello_npc_mount_vendor(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + bool canBuy; + canBuy = false; + uint32 vendor = _Creature->GetEntry(); + uint8 race = player->getRace(); + + switch (vendor) + { + case 384: //Katie Hunter + case 1460: //Unger Statforth + case 2357: //Merideth Carlson + case 4885: //Gregor MacVince + if (player->GetReputationRank(72) != REP_EXALTED && race != RACE_HUMAN) + player->SEND_GOSSIP_MENU(5855, _Creature->GetGUID()); + else canBuy = true; + break; + case 1261: //Veron Amberstill + if (player->GetReputationRank(47) != REP_EXALTED && race != RACE_DWARF) + player->SEND_GOSSIP_MENU(5856, _Creature->GetGUID()); + else canBuy = true; + break; + case 3362: //Ogunaro Wolfrunner + if (player->GetReputationRank(76) != REP_EXALTED && race != RACE_ORC) + player->SEND_GOSSIP_MENU(5841, _Creature->GetGUID()); + else canBuy = true; + break; + case 3685: //Harb Clawhoof + if (player->GetReputationRank(81) != REP_EXALTED && race != RACE_TAUREN) + player->SEND_GOSSIP_MENU(5843, _Creature->GetGUID()); + else canBuy = true; + break; + case 4730: //Lelanai + if (player->GetReputationRank(69) != REP_EXALTED && race != RACE_NIGHTELF) + player->SEND_GOSSIP_MENU(5844, _Creature->GetGUID()); + else canBuy = true; + break; + case 4731: //Zachariah Post + if (player->GetReputationRank(68) != REP_EXALTED && race != RACE_UNDEAD_PLAYER) + player->SEND_GOSSIP_MENU(5840, _Creature->GetGUID()); + else canBuy = true; + break; + case 7952: //Zjolnir + if (player->GetReputationRank(530) != REP_EXALTED && race != RACE_TROLL) + player->SEND_GOSSIP_MENU(5842, _Creature->GetGUID()); + else canBuy = true; + break; + case 7955: //Milli Featherwhistle + if (player->GetReputationRank(54) != REP_EXALTED && race != RACE_GNOME) + player->SEND_GOSSIP_MENU(5857, _Creature->GetGUID()); + else canBuy = true; + break; + case 16264: //Winaestra + if (player->GetReputationRank(911) != REP_EXALTED && race != RACE_BLOODELF) + player->SEND_GOSSIP_MENU(10305, _Creature->GetGUID()); + else canBuy = true; + break; + case 17584: //Torallius the Pack Handler + if (player->GetReputationRank(930) != REP_EXALTED && race != RACE_DRAENEI) + player->SEND_GOSSIP_MENU(10239, _Creature->GetGUID()); + else canBuy = true; + break; + } + + if (canBuy) + { + if (_Creature->isVendor()) + player->ADD_GOSSIP_ITEM( 1, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + } + return true; +} + +bool GossipSelect_npc_mount_vendor(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + if (action == GOSSIP_ACTION_TRADE) + player->SEND_VENDORLIST( _Creature->GetGUID() ); + + return true; +} + +/*###### +## npc_rogue_trainer +######*/ + +bool GossipHello_npc_rogue_trainer(Player *player, Creature *_Creature) +{ + if( _Creature->isQuestGiver() ) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if( _Creature->isTrainer() ) + player->ADD_GOSSIP_ITEM(2, GOSSIP_TEXT_TRAIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRAIN); + + if( _Creature->isCanTrainingAndResetTalentsOf(player) ) + player->ADD_GOSSIP_ITEM(2, "I wish to unlearn my talents", GOSSIP_SENDER_MAIN, GOSSIP_OPTION_UNLEARNTALENTS); + + if( player->getClass() == CLASS_ROGUE && player->getLevel() >= 24 && !player->HasItemCount(17126,1) && !player->GetQuestRewardStatus(6681) ) + { + player->ADD_GOSSIP_ITEM(0, "", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + player->SEND_GOSSIP_MENU(5996, _Creature->GetGUID()); + } else + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_rogue_trainer(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + switch( action ) + { + case GOSSIP_ACTION_INFO_DEF+1: + player->CLOSE_GOSSIP_MENU(); + player->CastSpell(player,21100,false); + break; + case GOSSIP_ACTION_TRAIN: + player->SEND_TRAINERLIST( _Creature->GetGUID() ); + break; + case GOSSIP_OPTION_UNLEARNTALENTS: + player->CLOSE_GOSSIP_MENU(); + player->SendTalentWipeConfirm( _Creature->GetGUID() ); + break; + } + return true; +} + +/*###### +## npc_sayge +######*/ + +#define SPELL_DMG 23768 //dmg +#define SPELL_RES 23769 //res +#define SPELL_ARM 23767 //arm +#define SPELL_SPI 23738 //spi +#define SPELL_INT 23766 //int +#define SPELL_STM 23737 //stm +#define SPELL_STR 23735 //str +#define SPELL_AGI 23736 //agi +#define SPELL_FORTUNE 23765 //faire fortune + +bool GossipHello_npc_sayge(Player *player, Creature *_Creature) +{ + if(_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if( player->HasSpellCooldown(SPELL_INT) || + player->HasSpellCooldown(SPELL_ARM) || + player->HasSpellCooldown(SPELL_DMG) || + player->HasSpellCooldown(SPELL_RES) || + player->HasSpellCooldown(SPELL_STR) || + player->HasSpellCooldown(SPELL_AGI) || + player->HasSpellCooldown(SPELL_STM) || + player->HasSpellCooldown(SPELL_SPI) ) + player->SEND_GOSSIP_MENU(7393, _Creature->GetGUID()); + else + { + player->ADD_GOSSIP_ITEM(0, "Yes", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + player->SEND_GOSSIP_MENU(7339, _Creature->GetGUID()); + } + + return true; +} + +void SendAction_npc_sayge(Player *player, Creature *_Creature, uint32 action) +{ + switch(action) + { + case GOSSIP_ACTION_INFO_DEF+1: + player->ADD_GOSSIP_ITEM(0, "Slay the Man", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + player->ADD_GOSSIP_ITEM(0, "Turn him over to liege", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + player->ADD_GOSSIP_ITEM(0, "Confiscate the corn", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + player->ADD_GOSSIP_ITEM(0, "Let him go and have the corn", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + player->SEND_GOSSIP_MENU(7340, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + player->ADD_GOSSIP_ITEM(0, "Execute your friend painfully", GOSSIP_SENDER_MAIN+1, GOSSIP_ACTION_INFO_DEF); + player->ADD_GOSSIP_ITEM(0, "Execute your friend painlessly", GOSSIP_SENDER_MAIN+2, GOSSIP_ACTION_INFO_DEF); + player->ADD_GOSSIP_ITEM(0, "Let your friend go", GOSSIP_SENDER_MAIN+3, GOSSIP_ACTION_INFO_DEF); + player->SEND_GOSSIP_MENU(7341, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + player->ADD_GOSSIP_ITEM(0, "Confront the diplomat", GOSSIP_SENDER_MAIN+4, GOSSIP_ACTION_INFO_DEF); + player->ADD_GOSSIP_ITEM(0, "Show not so quiet defiance", GOSSIP_SENDER_MAIN+5, GOSSIP_ACTION_INFO_DEF); + player->ADD_GOSSIP_ITEM(0, "Remain quiet", GOSSIP_SENDER_MAIN+2, GOSSIP_ACTION_INFO_DEF); + player->SEND_GOSSIP_MENU(7361, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + player->ADD_GOSSIP_ITEM(0, "Speak against your brother openly", GOSSIP_SENDER_MAIN+6, GOSSIP_ACTION_INFO_DEF); + player->ADD_GOSSIP_ITEM(0, "Help your brother in", GOSSIP_SENDER_MAIN+7, GOSSIP_ACTION_INFO_DEF); + player->ADD_GOSSIP_ITEM(0, "Keep your brother out without letting him know", GOSSIP_SENDER_MAIN+8, GOSSIP_ACTION_INFO_DEF); + player->SEND_GOSSIP_MENU(7362, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + player->ADD_GOSSIP_ITEM(0, "Take credit, keep gold", GOSSIP_SENDER_MAIN+5, GOSSIP_ACTION_INFO_DEF); + player->ADD_GOSSIP_ITEM(0, "Take credit, share the gold", GOSSIP_SENDER_MAIN+4, GOSSIP_ACTION_INFO_DEF); + player->ADD_GOSSIP_ITEM(0, "Let the knight take credit", GOSSIP_SENDER_MAIN+3, GOSSIP_ACTION_INFO_DEF); + player->SEND_GOSSIP_MENU(7363, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF: + player->ADD_GOSSIP_ITEM(0, "Thanks", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); + player->SEND_GOSSIP_MENU(7364, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+6: + _Creature->CastSpell(player, SPELL_FORTUNE, false); + player->SEND_GOSSIP_MENU(7365, _Creature->GetGUID()); + break; + } +} + +bool GossipSelect_npc_sayge(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + switch(sender) + { + case GOSSIP_SENDER_MAIN: + SendAction_npc_sayge(player, _Creature, action); + break; + case GOSSIP_SENDER_MAIN+1: + _Creature->CastSpell(player, SPELL_DMG, false); + player->AddSpellCooldown(SPELL_DMG,0,time(NULL) + 7200); + SendAction_npc_sayge(player, _Creature, action); + break; + case GOSSIP_SENDER_MAIN+2: + _Creature->CastSpell(player, SPELL_RES, false); + player->AddSpellCooldown(SPELL_RES,0,time(NULL) + 7200); + SendAction_npc_sayge(player, _Creature, action); + break; + case GOSSIP_SENDER_MAIN+3: + _Creature->CastSpell(player, SPELL_ARM, false); + player->AddSpellCooldown(SPELL_ARM,0,time(NULL) + 7200); + SendAction_npc_sayge(player, _Creature, action); + break; + case GOSSIP_SENDER_MAIN+4: + _Creature->CastSpell(player, SPELL_SPI, false); + player->AddSpellCooldown(SPELL_SPI,0,time(NULL) + 7200); + SendAction_npc_sayge(player, _Creature, action); + break; + case GOSSIP_SENDER_MAIN+5: + _Creature->CastSpell(player, SPELL_INT, false); + player->AddSpellCooldown(SPELL_INT,0,time(NULL) + 7200); + SendAction_npc_sayge(player, _Creature, action); + break; + case GOSSIP_SENDER_MAIN+6: + _Creature->CastSpell(player, SPELL_STM, false); + player->AddSpellCooldown(SPELL_STM,0,time(NULL) + 7200); + SendAction_npc_sayge(player, _Creature, action); + break; + case GOSSIP_SENDER_MAIN+7: + _Creature->CastSpell(player, SPELL_STR, false); + player->AddSpellCooldown(SPELL_STR,0,time(NULL) + 7200); + SendAction_npc_sayge(player, _Creature, action); + break; + case GOSSIP_SENDER_MAIN+8: + _Creature->CastSpell(player, SPELL_AGI, false); + player->AddSpellCooldown(SPELL_AGI,0,time(NULL) + 7200); + SendAction_npc_sayge(player, _Creature, action); + break; + } + return true; +} + +void AddSC_npcs_special() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npc_chicken_cluck"; + newscript->GetAI = GetAI_npc_chicken_cluck; + newscript->pReceiveEmote = &ReceiveEmote_npc_chicken_cluck; + newscript->pQuestAccept = &QuestAccept_npc_chicken_cluck; + newscript->pQuestComplete = &QuestComplete_npc_chicken_cluck; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_dancing_flames"; + newscript->pReceiveEmote = &ReceiveEmote_npc_dancing_flames; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_injured_patient"; + newscript->GetAI = GetAI_npc_injured_patient; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_doctor"; + newscript->GetAI = GetAI_npc_doctor; + newscript->pQuestAccept = &QuestAccept_npc_doctor; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_guardian"; + newscript->GetAI = GetAI_npc_guardian; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_mount_vendor"; + newscript->pGossipHello = &GossipHello_npc_mount_vendor; + newscript->pGossipSelect = &GossipSelect_npc_mount_vendor; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_rogue_trainer"; + newscript->pGossipHello = &GossipHello_npc_rogue_trainer; + newscript->pGossipSelect = &GossipSelect_npc_rogue_trainer; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_sayge"; + newscript->pGossipHello = &GossipHello_npc_sayge; + newscript->pGossipSelect = &GossipSelect_npc_sayge; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/alterac_mountains/alterac_mountains.cpp b/src/bindings/scripts/scripts/zone/alterac_mountains/alterac_mountains.cpp new file mode 100644 index 00000000000..074bf2967b2 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/alterac_mountains/alterac_mountains.cpp @@ -0,0 +1,62 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Alterac_Mountains +SD%Complete: 100 +SDComment: Quest support: 6681 +SDCategory: Alterac Mountains +EndScriptData */ + +/* ContentData +npc_ravenholdt +EndContentData */ + +#include "precompiled.h" + +/*###### +## npc_ravenholdt +######*/ + +struct MANGOS_DLL_DECL npc_ravenholdtAI : public ScriptedAI +{ + npc_ravenholdtAI(Creature *c) : ScriptedAI(c) { Reset(); } + + void Reset() { } + + void MoveInLineOfSight(Unit *who) + { + if( who->GetTypeId() == TYPEID_PLAYER ) + if( ((Player*)who)->GetQuestStatus(6681) == QUEST_STATUS_INCOMPLETE ) + ((Player*)who)->KilledMonster(m_creature->GetEntry(),m_creature->GetGUID() ); + } + + void Aggro(Unit* who) { } +}; +CreatureAI* GetAI_npc_ravenholdt(Creature *_Creature) +{ + return new npc_ravenholdtAI (_Creature); +} + +void AddSC_alterac_mountains() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npc_ravenholdt"; + newscript->GetAI = GetAI_npc_ravenholdt; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/aunchindoun/auchenai_crypts/boss_exarch_maladaar.cpp b/src/bindings/scripts/scripts/zone/aunchindoun/auchenai_crypts/boss_exarch_maladaar.cpp new file mode 100644 index 00000000000..77b0d7eaedd --- /dev/null +++ b/src/bindings/scripts/scripts/zone/aunchindoun/auchenai_crypts/boss_exarch_maladaar.cpp @@ -0,0 +1,405 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Exarch_Maladaar +SD%Complete: 95 +SDComment: Most of event implemented, some adjustments to timers remain and possibly make some better code for switching his dark side in to better "images" of player. +SDCategory: Auchindoun, Auchenai Crypts +EndScriptData */ + +/* ContentData +mob_stolen_soul +boss_exarch_maladaar +mob_avatar_of_martyred +EndContentData */ + +#include "precompiled.h" + +#define SPELL_MOONFIRE 37328 +#define SPELL_FIREBALL 37329 +#define SPELL_MIND_FLAY 37330 +#define SPELL_HEMORRHAGE 37331 +#define SPELL_FROSTSHOCK 37332 +#define SPELL_CURSE_OF_AGONY 37334 +#define SPELL_MORTAL_STRIKE 37335 +#define SPELL_FREEZING_TRAP 37368 +#define SPELL_HAMMER_OF_JUSTICE 37369 + +struct MANGOS_DLL_DECL mob_stolen_soulAI : public ScriptedAI +{ + mob_stolen_soulAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint8 myClass; + uint32 Class_Timer; + + void Reset() + { + Class_Timer = 1000; + } + + void Aggro(Unit *who) + { } + + void SetMyClass(uint8 myclass) + { + myClass = myclass; + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if( Class_Timer < diff ) + { + switch( myClass ) + { + case CLASS_WARRIOR: + DoCast(m_creature->getVictim(), SPELL_MORTAL_STRIKE); + Class_Timer = 6000; + break; + case CLASS_PALADIN: + DoCast(m_creature->getVictim(), SPELL_HAMMER_OF_JUSTICE); + Class_Timer = 6000; + break; + case CLASS_HUNTER: + DoCast(m_creature->getVictim(), SPELL_FREEZING_TRAP); + Class_Timer = 20000; + break; + case CLASS_ROGUE: + DoCast(m_creature->getVictim(), SPELL_HEMORRHAGE); + Class_Timer = 10000; + break; + case CLASS_PRIEST: + DoCast(m_creature->getVictim(), SPELL_MIND_FLAY); + Class_Timer = 5000; + break; + case CLASS_SHAMAN: + DoCast(m_creature->getVictim(), SPELL_FROSTSHOCK); + Class_Timer = 8000; + break; + case CLASS_MAGE: + DoCast(m_creature->getVictim(), SPELL_FIREBALL); + Class_Timer = 5000; + break; + case CLASS_WARLOCK: + DoCast(m_creature->getVictim(), SPELL_CURSE_OF_AGONY); + Class_Timer = 20000; + break; + case CLASS_DRUID: + DoCast(m_creature->getVictim(), SPELL_MOONFIRE); + Class_Timer = 10000; + break; + default: + break; + } + }else Class_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_stolen_soul(Creature *_Creature) +{ + return new mob_stolen_soulAI (_Creature); +} + +#define SAY_INTRO "You have defiled the resting place of our ancestors. For this offense, there can be but one punishment. It is fitting that you have come to a place of the dead... for you will soon be joining them." +#define SOUND_INTRO 10509 +#define SAY_SUMMON "Rise my fallen brothers. Take form and fight!" +#define SOUND_SUMMON 10512 + +#define SAY_AGGRO_1 "You will pay with your life!" +#define SOUND_AGGRO_1 10513 +#define SAY_AGGRO_2 "There's no turning back now!" +#define SOUND_AGGRO_2 10514 +#define SAY_AGGRO_3 "Serve your penitence!" +#define SOUND_AGGRO_3 10515 + +#define SAY_ROAR "Let your mind be clouded." +#define SOUND_ROAR 10510 +#define SAY_SOUL_CLEAVE "Stare into the darkness of your soul." +#define SOUND_SOUL_CLEAVE 10511 + +#define SAY_SLAY_1 "These walls will be your doom." +#define SOUND_SLAY_1 10516 +#define SAY_SLAY_2 " Now, you'll stay for eternity!" +#define SOUND_SLAY_2 10517 + +#define SAY_DEATH "This is... where.. I belong..." +#define SOUND_DEATH 10518 + +#define SPELL_RIBBON_OF_SOULS 32422 +#define SPELL_SOUL_SCREAM 32421 + +#define SPELL_STOLEN_SOUL 32346 +#define SPELL_STOLEN_SOUL_VISUAL 32395 + +#define SPELL_SUMMON_AVATAR 32424 + +#define ENTRY_STOLEN_SOUL 18441 + +struct MANGOS_DLL_DECL boss_exarch_maladaarAI : public ScriptedAI +{ + boss_exarch_maladaarAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 soulmodel; + uint64 soulholder; + uint8 soulclass; + + uint32 Fear_timer; + uint32 Ribbon_of_Souls_timer; + uint32 StolenSoul_Timer; + + bool HasTaunted; + bool Avatar_summoned; + + void Reset() + { + soulmodel = 0; + soulholder = 0; + soulclass = 0; + + Fear_timer = 20000; + Ribbon_of_Souls_timer = 5000; + StolenSoul_Timer = 30000; + + HasTaunted = false; + Avatar_summoned = false; + } + + void MoveInLineOfSight(Unit *who) + { + if( !m_creature->getVictim() && who->isTargetableForAttack() && ( m_creature->IsHostileTo( who )) && who->isInAccessablePlaceFor(m_creature) ) + { + if( !HasTaunted && m_creature->IsWithinDistInMap(who, 150.0) ) + { + DoYell(SAY_INTRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_INTRO); + HasTaunted = true; + } + + if (m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = m_creature->GetAttackDistance(who); + if( m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->IsWithinLOSInMap(who) ) + { + DoStartAttackAndMovement(who); + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + if (!InCombat) + { + Aggro(who); + InCombat = true; + } + } + } + } + + void Aggro(Unit *who) + { + switch(rand()%3) + { + case 0: + DoYell(SAY_AGGRO_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO_1); + break; + case 1: + DoYell(SAY_AGGRO_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO_2); + break; + case 2: + DoYell(SAY_AGGRO_3, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO_3); + break; + } + } + + void JustSummoned(Creature *summoned) + { + if( summoned->GetEntry() == ENTRY_STOLEN_SOUL ) + { + //SPELL_STOLEN_SOUL_VISUAL has shapeshift effect, but not implemented feature in mangos for this spell. + summoned->SetDisplayId(soulmodel); + summoned->CastSpell(summoned,SPELL_STOLEN_SOUL_VISUAL,false); + + if( Unit *target = Unit::GetUnit(*m_creature,soulholder) ) + summoned->AI()->AttackStart(target); + + ((mob_stolen_soulAI*)summoned->AI())->SetMyClass(soulclass); + } + } + + void KilledUnit(Unit* victim) + { + if (rand()%2) + return; + + switch(rand()%2) + { + case 0: + DoYell(SAY_SLAY_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY_1); + break; + case 1: + DoYell(SAY_SLAY_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY_2); + break; + } + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_DEATH); + + //When Exarch Maladar is defeated D'ore appear. + DoSpawnCreature(19412,0,0,0,0, TEMPSUMMON_TIMED_DESPAWN, 600000); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if( !Avatar_summoned && ((m_creature->GetHealth()*100) / m_creature->GetMaxHealth() < 25) ) + { + if( m_creature->IsNonMeleeSpellCasted(false) ) + m_creature->InterruptNonMeleeSpells(true); + + DoYell(SAY_SUMMON, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_SUMMON); + + DoCast(m_creature, SPELL_SUMMON_AVATAR); + Avatar_summoned = true; + StolenSoul_Timer = 45000; + } + + if( StolenSoul_Timer < diff ) + { + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + { + if( target->GetTypeId() == TYPEID_PLAYER ) + { + if( m_creature->IsNonMeleeSpellCasted(false) ) + m_creature->InterruptNonMeleeSpells(true); + + uint32 i = urand(1,2); + if( i == 1 ) + { + DoYell(SAY_ROAR, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_ROAR); + } + else + { + DoYell(SAY_SOUL_CLEAVE, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_SOUL_CLEAVE); + } + + soulmodel = target->GetDisplayId(); + soulholder = target->GetGUID(); + soulclass = target->getClass(); + + DoCast(target,SPELL_STOLEN_SOUL); + DoSpawnCreature(ENTRY_STOLEN_SOUL,0,0,0,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + + StolenSoul_Timer = 45000; + } else StolenSoul_Timer = 1000; + } + }else StolenSoul_Timer -= diff; + + if( Ribbon_of_Souls_timer < diff ) + { + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target,SPELL_RIBBON_OF_SOULS); + + Ribbon_of_Souls_timer = 5000 + (rand()%20 * 1000); + }else Ribbon_of_Souls_timer -= diff; + + if( Fear_timer < diff ) + { + DoCast(m_creature,SPELL_SOUL_SCREAM); + Fear_timer = 25000 + rand()% 10000; + }else Fear_timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_exarch_maladaar(Creature *_Creature) +{ + return new boss_exarch_maladaarAI (_Creature); +} + +#define SPELL_MORTAL_STRIKE 16856 +#define SPELL_SUNDER_ARMOR 16145 + +struct MANGOS_DLL_DECL mob_avatar_of_martyredAI : public ScriptedAI +{ + mob_avatar_of_martyredAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Mortal_Strike_timer; + + void Reset() + { + Mortal_Strike_timer = 10000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(Mortal_Strike_timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_MORTAL_STRIKE); + Mortal_Strike_timer = 10000 + rand()%20 * 1000; + }else Mortal_Strike_timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_avatar_of_martyred(Creature *_Creature) +{ + return new mob_avatar_of_martyredAI (_Creature); +} + +void AddSC_boss_exarch_maladaar() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_exarch_maladaar"; + newscript->GetAI = GetAI_boss_exarch_maladaar; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_avatar_of_martyred"; + newscript->GetAI = GetAI_mob_avatar_of_martyred; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_stolen_soul"; + newscript->GetAI = GetAI_mob_stolen_soul; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/aunchindoun/mana_tombs/boss_nexusprince_shaffar.cpp b/src/bindings/scripts/scripts/zone/aunchindoun/mana_tombs/boss_nexusprince_shaffar.cpp new file mode 100644 index 00000000000..7191ea7a663 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/aunchindoun/mana_tombs/boss_nexusprince_shaffar.cpp @@ -0,0 +1,313 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_NexusPrince_Shaffar +SD%Complete: 80 +SDComment: Need more tuning of spell timers, it should not be as linear fight as current. Also should possibly find a better way to deal with his three initial beacons to make sure all aggro. +SDCategory: Auchindoun, Mana Tombs +EndScriptData */ + +/* ContentData +boss_nexusprince_shaffar +mob_ethereal_beacon +EndContentData */ + +#include "precompiled.h" + +#define SAY_INTRO "What is this? You must forgive me, but I was not expecting company. As you can see, we are somewhat preoccupied right now. But no matter. As I am a gracious host, I will tend to you... personally." +#define SOUND_INTRO 10539 + +#define SAY_AGGRO_1 "We have not yet been properly introduced." +#define SOUND_AGGRO_1 10541 +#define SAY_AGGRO_2 "An epic battle. How exciting!" +#define SOUND_AGGRO_2 10542 +#define SAY_AGGRO_3 "I have longed for a good adventure." +#define SOUND_AGGRO_3 10543 + +#define SAY_SLAY_1 "It has been... entertaining." +#define SOUND_SLAY_1 10544 +#define SAY_SLAY_2 "And now we part company." +#define SOUND_SLAY_2 10545 + +#define SAY_SUMMON "I have such fascinating things to show you." +#define SOUND_SUMMON 10540 + +#define SAY_DEAD "I must bid you... farewell." +#define SOUND_DEAD 10546 + +#define SPELL_BLINK 34605 +#define SPELL_FROSTBOLT 32364 +#define SPELL_FIREBALL 32363 +#define SPELL_FROSTNOVA 32365 + +#define SPELL_ETHEREAL_BEACON 32371 // Summon 18431 +#define SPELL_ETHEREAL_BEACON_VISUAL 32368 + +#define ENTRY_BEACON 18431 + +struct MANGOS_DLL_DECL boss_nexusprince_shaffarAI : public ScriptedAI +{ + boss_nexusprince_shaffarAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Blink_Timer; + uint32 Beacon_Timer; + uint32 FireBall_Timer; + uint32 Frostbolt_Timer; + uint32 FrostNova_Timer; + + bool HasTaunted; + bool CanBlink; + + void Reset() + { + Blink_Timer = 1500; + Beacon_Timer = 10000; + FireBall_Timer = 8000; + Frostbolt_Timer = 4000; + FrostNova_Timer = 15000; + + HasTaunted = false; + CanBlink = false; + } + + void MoveInLineOfSight(Unit *who) + { + if( !m_creature->getVictim() && who->isTargetableForAttack() && ( m_creature->IsHostileTo( who )) && who->isInAccessablePlaceFor(m_creature) ) + { + if( !HasTaunted && m_creature->IsWithinDistInMap(who, 100.0) ) + { + DoYell(SAY_INTRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_INTRO); + HasTaunted = true; + } + + if (m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = m_creature->GetAttackDistance(who); + if( m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->IsWithinLOSInMap(who) ) + { + DoStartAttackAndMovement(who); + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + if (!InCombat) + { + Aggro(who); + InCombat = true; + } + } + } + } + + void Aggro(Unit *who) + { + switch(rand()%3) + { + case 0: + DoYell(SAY_AGGRO_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO_1); + break; + case 1: + DoYell(SAY_AGGRO_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO_2); + break; + case 2: + DoYell(SAY_AGGRO_3, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO_3); + break; + } + } + + void JustSummoned(Creature *summoned) + { + if( summoned->GetEntry() == ENTRY_BEACON ) + { + summoned->CastSpell(summoned,SPELL_ETHEREAL_BEACON_VISUAL,false); + + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + summoned->AI()->AttackStart(target); + } + } + + void KilledUnit(Unit* victim) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_SLAY_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY_1); + break; + case 1: + DoYell(SAY_SLAY_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY_2); + break; + } + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DEAD, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_DEAD); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if( FrostNova_Timer < diff ) + { + if( m_creature->IsNonMeleeSpellCasted(false) ) + m_creature->InterruptNonMeleeSpells(true); + + DoCast(m_creature,SPELL_FROSTNOVA); + FrostNova_Timer = 17500 + rand()%7500; + CanBlink = true; + }else FrostNova_Timer -= diff; + + if( Frostbolt_Timer < diff ) + { + DoCast(m_creature->getVictim(),SPELL_FROSTBOLT); + Frostbolt_Timer = 4500 + rand()%1500; + }else Frostbolt_Timer -= diff; + + if( FireBall_Timer < diff ) + { + DoCast(m_creature->getVictim(),SPELL_FIREBALL); + FireBall_Timer = 4500 + rand()%1500; + }else FireBall_Timer -= diff; + + if( CanBlink ) + { + if( Blink_Timer < diff ) + { + if( m_creature->IsNonMeleeSpellCasted(false) ) + m_creature->InterruptNonMeleeSpells(true); + + DoCast(m_creature,SPELL_BLINK); + Blink_Timer = 1000 + rand()%1500; + CanBlink = false; + }else Blink_Timer -= diff; + } + + if( Beacon_Timer < diff) + { + if( m_creature->IsNonMeleeSpellCasted(false) ) + m_creature->InterruptNonMeleeSpells(true); + + if( !urand(0,3) ) + { + DoYell(SAY_SUMMON, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_SUMMON); + } + DoCast(m_creature,SPELL_ETHEREAL_BEACON); + + Beacon_Timer = 10000; + }else Beacon_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_nexusprince_shaffar(Creature *_Creature) +{ + return new boss_nexusprince_shaffarAI (_Creature); +} + +#define SPELL_ARCANE_BOLT 15254 +#define SPELL_ETHEREAL_APPRENTICE 32372 // Summon 18430 + +struct MANGOS_DLL_DECL mob_ethereal_beaconAI : public ScriptedAI +{ + mob_ethereal_beaconAI(Creature *c) : ScriptedAI(c) + { + HeroicMode = m_creature->GetMap()->IsHeroic(); + Reset(); + } + + bool HeroicMode; + bool CanEvade; + uint32 Apprentice_Timer; + uint32 ArcaneBolt_Timer; + + void Reset() + { + if( CanEvade ) + m_creature->SetVisibility(VISIBILITY_OFF); + + CanEvade = false; + Apprentice_Timer = (HeroicMode ? 10000 : 20000); + ArcaneBolt_Timer = 1000; + } + + void Aggro(Unit *who) + { + } + + void JustSummoned(Creature *summoned) + { + summoned->AI()->AttackStart(m_creature->getVictim()); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if( ArcaneBolt_Timer < diff ) + { + DoCast(m_creature->getVictim(),SPELL_ARCANE_BOLT); + ArcaneBolt_Timer = 2000 + rand()%2500; + }else ArcaneBolt_Timer -= diff; + + if( Apprentice_Timer < diff ) + { + if( m_creature->IsNonMeleeSpellCasted(false) ) + m_creature->InterruptNonMeleeSpells(true); + + m_creature->CastSpell(m_creature,SPELL_ETHEREAL_APPRENTICE,true); + if( m_creature->GetOwner() ) + ((Pet*)m_creature)->SetDuration(0); + CanEvade = true; + }else Apprentice_Timer -= diff; + + if( CanEvade ) + EnterEvadeMode(); + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_ethereal_beacon(Creature *_Creature) +{ + return new mob_ethereal_beaconAI (_Creature); +} + +void AddSC_boss_nexusprince_shaffar() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_nexusprince_shaffar"; + newscript->GetAI = GetAI_boss_nexusprince_shaffar; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_ethereal_beacon"; + newscript->GetAI = GetAI_mob_ethereal_beacon; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/aunchindoun/mana_tombs/boss_pandemonius.cpp b/src/bindings/scripts/scripts/zone/aunchindoun/mana_tombs/boss_pandemonius.cpp new file mode 100644 index 00000000000..25f26289e53 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/aunchindoun/mana_tombs/boss_pandemonius.cpp @@ -0,0 +1,159 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Pandemonius +SD%Complete: 75 +SDComment: Not known how void blast is done (amount of rapid cast seems to be related to players in party). All mobs remaining in surrounding area should aggro when engaged. +SDCategory: Auchindoun, Mana Tombs +EndScriptData */ + +#include "precompiled.h" + +#define SAY_AGGRO_1 "I will feed on your soul." +#define SOUND_AGGRO_1 10561 +#define SAY_AGGRO_2 "So... full of life!" +#define SOUND_AGGRO_2 10562 +#define SAY_AGGRO_3 "Do not... resist." +#define SOUND_AGGRO_3 10563 + +#define SAY_KILL_1 "Yes! I am... empowered!" +#define SOUND_KILL_1 10564 +#define SAY_KILL_2 "More... I must have more!" +#define SOUND_KILL_2 10565 + +#define SAY_DEATH "To the void... once... more.." +#define SOUND_DEATH 10566 + +#define EMOTE_DARK_SHELL "shifts into the void..." + +#define SPELL_VOID_BLAST 32325 +#define H_SPELL_VOID_BLAST 38760 +#define SPELL_DARK_SHELL 32358 +#define H_SPELL_DARK_SHELL 38759 + +struct MANGOS_DLL_DECL boss_pandemoniusAI : public ScriptedAI +{ + boss_pandemoniusAI(Creature *c) : ScriptedAI(c) + { + HeroicMode = m_creature->GetMap()->IsHeroic(); + Reset(); + } + + bool HeroicMode; + uint32 VoidBlast_Timer; + uint32 DarkShell_Timer; + uint32 VoidBlast_Counter; + + void Reset() + { + VoidBlast_Timer = 30000; + DarkShell_Timer = 20000; + VoidBlast_Counter = 0; + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_DEATH); + } + + void KilledUnit(Unit* victim) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_KILL_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_KILL_1); + break; + case 1: + DoYell(SAY_KILL_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_KILL_2); + break; + } + } + + void Aggro(Unit *who) + { + switch(rand()%3) + { + case 0: + DoYell(SAY_AGGRO_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO_1); + break; + case 1: + DoYell(SAY_AGGRO_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO_2); + break; + case 2: + DoYell(SAY_AGGRO_3, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO_3); + break; + } + + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if( VoidBlast_Timer < diff ) + { + if( Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0) ) + { + DoCast(target,HeroicMode ? H_SPELL_VOID_BLAST : SPELL_VOID_BLAST); + VoidBlast_Timer = 500; + ++VoidBlast_Counter; + } + + if( VoidBlast_Counter == 5 ) + { + VoidBlast_Timer = 25000+rand()%10000; + VoidBlast_Counter = 0; + } + }else VoidBlast_Timer -= diff; + + if( !VoidBlast_Counter ) + { + if( DarkShell_Timer < diff ) + { + if( m_creature->IsNonMeleeSpellCasted(false) ) + m_creature->InterruptNonMeleeSpells(true); + + DoTextEmote(EMOTE_DARK_SHELL,NULL,true); + DoCast(m_creature,HeroicMode ? H_SPELL_DARK_SHELL : SPELL_DARK_SHELL); + DarkShell_Timer = 20000; + }else DarkShell_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_pandemonius(Creature *_Creature) +{ + return new boss_pandemoniusAI (_Creature); +} + +void AddSC_boss_pandemonius() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_pandemonius"; + newscript->GetAI = GetAI_boss_pandemonius; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/aunchindoun/sethekk_halls/boss_darkweaver_syth.cpp b/src/bindings/scripts/scripts/zone/aunchindoun/sethekk_halls/boss_darkweaver_syth.cpp new file mode 100644 index 00000000000..2be88f661af --- /dev/null +++ b/src/bindings/scripts/scripts/zone/aunchindoun/sethekk_halls/boss_darkweaver_syth.cpp @@ -0,0 +1,441 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Darkweaver_Syth +SD%Complete: 85 +SDComment: Shock spells/times need more work. Heroic not implemented. +SDCategory: Auchindoun, Sethekk Halls +EndScriptData */ + +#include "precompiled.h" + +#define SAY_SUMMON "I have pets....of my own!" +#define SOUND_SUMMON 10502 + +#define SAY_AGGRO_1 "Hrrmm.. Time to.. hrrm.. make my move." +#define SOUND_AGGRO_1 10503 +#define SAY_AGGRO_2 "Nice pets..hrm.. Yes! " +#define SOUND_AGGRO_2 10504 +#define SAY_AGGRO_3 "Nice pets have.. weapons. No so....nice." +#define SOUND_AGGRO_3 10505 + +#define SAY_SLAY_1 "Death.. meeting life is.. " +#define SOUND_SLAY_1 10506 +#define SAY_SLAY_2 "Uhn.. Be free.." +#define SOUND_SLAY_2 10507 + +#define SAY_DEATH "No more life..hrm. No more pain. " +#define SOUND_DEATH 10508 + +#define SPELL_FROST_SHOCK 37865 +#define SPELL_FLAME_SHOCK 34354 +#define SPELL_SHADOW_SHOCK 30138 +#define SPELL_ARCANE_SHOCK 37132 + +#define SPELL_CHAIN_LIGHTNING 39945 + +#define SPELL_SUMMON_SYTH_FIRE 33537 // Spawns 19203 +#define SPELL_SUMMON_SYTH_ARCANE 33538 // Spawns 19205 +#define SPELL_SUMMON_SYTH_FROST 33539 // Spawns 19204 +#define SPELL_SUMMON_SYTH_SHADOW 33540 // Spawns 19206 + +#define SPELL_FLAME_BUFFET 33526 +#define H_SPELL_FLAME_BUFFET 38141 +#define SPELL_ARCANE_BUFFET 33527 +#define H_SPELL_ARCANE_BUFFET 38138 +#define SPELL_FROST_BUFFET 33528 +#define H_SPELL_FROST_BUFFET 38142 +#define SPELL_SHADOW_BUFFET 33529 +#define H_SPELL_SHADOW_BUFFET 38143 + +struct MANGOS_DLL_DECL boss_darkweaver_sythAI : public ScriptedAI +{ + boss_darkweaver_sythAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 flameshock_timer; + uint32 arcaneshock_timer; + uint32 frostshock_timer; + uint32 shadowshock_timer; + uint32 chainlightning_timer; + + bool summon90; + bool summon50; + bool summon10; + + void Reset() + { + flameshock_timer = 2000; + arcaneshock_timer = 4000; + frostshock_timer = 6000; + shadowshock_timer = 8000; + chainlightning_timer = 15000; + + summon90 = false; + summon50 = false; + summon10 = false; + } + + void Aggro(Unit *who) + { + switch(rand()%3) + { + case 0: + DoYell(SAY_AGGRO_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO_1); + break; + case 1: + DoYell(SAY_AGGRO_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO_2); + break; + case 2: + DoYell(SAY_AGGRO_3, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO_3); + break; + } + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_DEATH); + } + + void KilledUnit(Unit* victim) + { + if (rand()%2) + return; + + switch(rand()%2) + { + case 0: + DoYell(SAY_SLAY_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY_1); + break; + case 1: + DoYell(SAY_SLAY_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY_2); + break; + } + } + + void JustSummoned(Creature *summoned) + { + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + summoned->AI()->AttackStart(target); + + } + + void SythSummoning() + { + DoYell(SAY_SUMMON, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_SUMMON); + + if( m_creature->IsNonMeleeSpellCasted(false) ) + m_creature->InterruptNonMeleeSpells(false); + + DoCast(m_creature,SPELL_SUMMON_SYTH_ARCANE,true); //front + DoCast(m_creature,SPELL_SUMMON_SYTH_FIRE,true); //back + DoCast(m_creature,SPELL_SUMMON_SYTH_FROST,true); //left + DoCast(m_creature,SPELL_SUMMON_SYTH_SHADOW,true); //right + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if( ((m_creature->GetHealth()*100) / m_creature->GetMaxHealth() < 90) && !summon90) + { + SythSummoning(); + summon90 = true; + } + + if( ((m_creature->GetHealth()*100) / m_creature->GetMaxHealth() < 50) && !summon50) + { + SythSummoning(); + summon50 = true; + } + + if( ((m_creature->GetHealth()*100) / m_creature->GetMaxHealth() < 10) && !summon10) + { + SythSummoning(); + summon10 = true; + } + + if( flameshock_timer < diff ) + { + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target,SPELL_FLAME_SHOCK); + + flameshock_timer = 10000 + rand()%5000; + }else flameshock_timer -= diff; + + if( arcaneshock_timer < diff ) + { + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target,SPELL_ARCANE_SHOCK); + + arcaneshock_timer = 10000 + rand()%5000; + }else arcaneshock_timer -= diff; + + if( frostshock_timer < diff ) + { + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target,SPELL_FROST_SHOCK); + + frostshock_timer = 10000 + rand()%5000; + }else frostshock_timer -= diff; + + if( shadowshock_timer < diff ) + { + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target,SPELL_SHADOW_SHOCK); + + shadowshock_timer = 10000 + rand()%5000; + }else shadowshock_timer -= diff; + + if( chainlightning_timer < diff ) + { + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target,SPELL_CHAIN_LIGHTNING); + + chainlightning_timer = 25000; + }else chainlightning_timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_darkweaver_syth(Creature *_Creature) +{ + return new boss_darkweaver_sythAI (_Creature); +} + +/* ELEMENTALS */ + +struct MANGOS_DLL_DECL mob_syth_fireAI : public ScriptedAI +{ + mob_syth_fireAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 flameshock_timer; + uint32 flamebuffet_timer; + + void Reset() + { + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); + flameshock_timer = 2500; + flamebuffet_timer = 5000; + } + + void Aggro(Unit *who) { } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(flameshock_timer < diff) + { + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target,SPELL_FLAME_SHOCK); + + flameshock_timer = 5000; + }else flameshock_timer -= diff; + + if(flamebuffet_timer < diff) + { + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target,SPELL_FLAME_BUFFET); + + flamebuffet_timer = 5000; + }else flamebuffet_timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_syth_fire(Creature *_Creature) +{ + return new mob_syth_fireAI (_Creature); +} + +struct MANGOS_DLL_DECL mob_syth_arcaneAI : public ScriptedAI +{ + mob_syth_arcaneAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 arcaneshock_timer; + uint32 arcanebuffet_timer; + + void Reset() + { + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, true); + arcaneshock_timer = 2500; + arcanebuffet_timer = 5000; + } + + void Aggro(Unit *who) { } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(arcaneshock_timer < diff) + { + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target,SPELL_ARCANE_SHOCK); + + arcaneshock_timer = 5000; + }else arcaneshock_timer -= diff; + + if(arcanebuffet_timer < diff) + { + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target,SPELL_ARCANE_BUFFET); + + arcanebuffet_timer = 5000; + }else arcanebuffet_timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_syth_arcane(Creature *_Creature) +{ + return new mob_syth_arcaneAI (_Creature); +} + +struct MANGOS_DLL_DECL mob_syth_frostAI : public ScriptedAI +{ + mob_syth_frostAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 frostshock_timer; + uint32 frostbuffet_timer; + + void Reset() + { + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); + frostshock_timer = 2500; + frostbuffet_timer = 5000; + } + + void Aggro(Unit *who) { } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(frostshock_timer < diff) + { + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target,SPELL_FROST_SHOCK); + + frostshock_timer = 5000; + }else frostshock_timer -= diff; + + if(frostbuffet_timer < diff) + { + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target,SPELL_FROST_BUFFET); + + frostbuffet_timer = 5000; + }else frostbuffet_timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_syth_frost(Creature *_Creature) +{ + return new mob_syth_frostAI (_Creature); +} + +struct MANGOS_DLL_DECL mob_syth_shadowAI : public ScriptedAI +{ + mob_syth_shadowAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 shadowshock_timer; + uint32 shadowbuffet_timer; + + void Reset() + { + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, true); + shadowshock_timer = 2500; + shadowbuffet_timer = 5000; + } + + void Aggro(Unit *who) { } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(shadowshock_timer < diff) + { + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target,SPELL_SHADOW_SHOCK); + + shadowshock_timer = 5000; + }else shadowshock_timer -= diff; + + if(shadowbuffet_timer < diff) + { + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target,SPELL_SHADOW_BUFFET); + + shadowbuffet_timer = 5000; + }else shadowbuffet_timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_syth_shadow(Creature *_Creature) +{ + return new mob_syth_shadowAI (_Creature); +} + +void AddSC_boss_darkweaver_syth() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_darkweaver_syth"; + newscript->GetAI = GetAI_boss_darkweaver_syth; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_syth_fire"; + newscript->GetAI = GetAI_mob_syth_arcane; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_syth_arcane"; + newscript->GetAI = GetAI_mob_syth_arcane; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_syth_frost"; + newscript->GetAI = GetAI_mob_syth_frost; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_syth_shadow"; + newscript->GetAI = GetAI_mob_syth_shadow; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/aunchindoun/sethekk_halls/boss_tailonking_ikiss.cpp b/src/bindings/scripts/scripts/zone/aunchindoun/sethekk_halls/boss_tailonking_ikiss.cpp new file mode 100644 index 00000000000..4168458685d --- /dev/null +++ b/src/bindings/scripts/scripts/zone/aunchindoun/sethekk_halls/boss_tailonking_ikiss.cpp @@ -0,0 +1,256 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Talon_King_Ikiss +SD%Complete: 80 +SDComment: Heroic supported. Some details missing, but most are spell related. +SDCategory: Auchindoun, Sethekk Halls +EndScriptData */ + +#include "precompiled.h" +#include "def_sethekk_halls.h" + +#define SAY_INTRO "..Trinkets yes pretty Trinkets....power, great power...power in Trinkets.." +#define SOUND_INTRO 10557 + +#define SAY_AGGRO_1 "You make war on Ikiss?.." +#define SOUND_AGGRO_1 10554 +#define SAY_AGGRO_2 "Ikiss cut you pretty....slice you. Yes!" +#define SOUND_AGGRO_2 10555 +#define SAY_AGGRO_3 "No escape for....for you" +#define SOUND_AGGRO_3 10556 + +#define SAY_SLAY_1 "You die....stay away from Trinkets" +#define SOUND_SLAY_1 10558 +#define SAY_SLAY_2 "" +#define SOUND_SLAY_2 10559 + +#define SAY_DEATH "Ikiss will not....die" +#define SOUND_DEATH 10560 + +#define EMOTE_ARCANE_EXP "begins to channel arcane energy..." + +#define SPELL_BLINK 38194 +#define SPELL_BLINK_TELEPORT 38203 +#define SPELL_MANA_SHIELD 38151 +#define SPELL_ARCANE_BUBBLE 9438 +#define H_SPELL_SLOW 35032 + +#define SPELL_POLYMORPH 38245 +#define H_SPELL_POLYMORPH 43309 + +#define SPELL_ARCANE_VOLLEY 35059 +#define H_SPELL_ARCANE_VOLLEY 40424 + +#define SPELL_ARCANE_EXPLOSION 38197 +#define H_SPELL_ARCANE_EXPLOSION 40425 + +struct MANGOS_DLL_DECL boss_talon_king_ikissAI : public ScriptedAI +{ + boss_talon_king_ikissAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + + bool HeroicMode; + + uint32 ArcaneVolley_Timer; + uint32 Sheep_Timer; + uint32 Blink_Timer; + uint32 Slow_Timer; + + bool ManaShield; + bool Blink; + bool Intro; + + void Reset() + { + HeroicMode = m_creature->GetMap()->IsHeroic(); + + ArcaneVolley_Timer = 5000; + Sheep_Timer = 8000; + Blink_Timer = 35000; + Slow_Timer = 15000+rand()%15000; + Blink = false; + Intro = false; + ManaShield = false; + } + + void MoveInLineOfSight(Unit *who) + { + if( !m_creature->getVictim() && who->isTargetableForAttack() && ( m_creature->IsHostileTo( who )) && who->isInAccessablePlaceFor(m_creature) ) + { + if(!Intro && m_creature->IsWithinDistInMap(who, 100)) + { + Intro = true; + DoYell(SAY_INTRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_INTRO); + } + + if (m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = m_creature->GetAttackDistance(who); + if( m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->IsWithinLOSInMap(who) ) + { + DoStartAttackAndMovement(who); + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + if (!InCombat) + { + Aggro(who); + InCombat = true; + } + } + } + } + + void Aggro(Unit *who) + { + switch(rand()%3) + { + case 0: + DoYell(SAY_AGGRO_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO_1); + break; + + case 1: + DoYell(SAY_AGGRO_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO_2); + break; + + case 2: + DoYell(SAY_AGGRO_3, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO_3); + break; + } + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_DEATH); + + if( pInstance ) + pInstance->SetData(DATA_IKISSDOOREVENT, DONE); + } + + void KilledUnit(Unit* victim) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_SLAY_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY_1); + break; + + case 1: + DoYell(SAY_SLAY_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY_2); + break; + } + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if( Blink ) + { + DoCast(m_creature,HeroicMode ? H_SPELL_ARCANE_EXPLOSION : SPELL_ARCANE_EXPLOSION); + m_creature->CastSpell(m_creature,SPELL_ARCANE_BUBBLE,true); + Blink = false; + } + + if( ArcaneVolley_Timer < diff ) + { + DoCast(m_creature,HeroicMode ? H_SPELL_ARCANE_VOLLEY : SPELL_ARCANE_VOLLEY); + ArcaneVolley_Timer = 10000+rand()%5000; + }else ArcaneVolley_Timer -= diff; + + if( Sheep_Timer < diff ) + { + //second top aggro target in normal, random target in heroic correct? + Unit *target = NULL; + if( HeroicMode ? target = SelectUnit(SELECT_TARGET_RANDOM,0) : target = SelectUnit(SELECT_TARGET_TOPAGGRO,1) ) + DoCast(target,HeroicMode ? H_SPELL_POLYMORPH : SPELL_POLYMORPH); + Sheep_Timer = 15000+rand()%2500; + }else Sheep_Timer -= diff; + + //may not be correct time to cast + if( !ManaShield && ((m_creature->GetHealth()*100) / m_creature->GetMaxHealth() < 20) ) + { + DoCast(m_creature,SPELL_MANA_SHIELD); + ManaShield = true; + } + + if( HeroicMode ) + { + if( Slow_Timer < diff ) + { + DoCast(m_creature,H_SPELL_SLOW); + Slow_Timer = 15000+rand()%25000; + }else Slow_Timer -= diff; + } + + if( Blink_Timer < diff ) + { + DoTextEmote(EMOTE_ARCANE_EXP,NULL,true); + + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + { + if( m_creature->IsNonMeleeSpellCasted(false) ) + m_creature->InterruptNonMeleeSpells(false); + + //Spell doesn't work, but we use for visual effect at least + DoCast(target,SPELL_BLINK); + + float X = target->GetPositionX(); + float Y = target->GetPositionY(); + float Z = target->GetPositionZ(); + + m_creature->Relocate(X,Y,Z); + m_creature->SendMonsterMove(X, Y, Z, 0, 0, 0); + + DoCast(target,SPELL_BLINK_TELEPORT); + Blink = true; + } + Blink_Timer = 35000+rand()%5000; + }else Blink_Timer -= diff; + + if( !Blink ) + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_talon_king_ikiss(Creature *_Creature) +{ + return new boss_talon_king_ikissAI (_Creature); +} + +void AddSC_boss_talon_king_ikiss() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_talon_king_ikiss"; + newscript->GetAI = GetAI_boss_talon_king_ikiss; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/aunchindoun/sethekk_halls/def_sethekk_halls.h b/src/bindings/scripts/scripts/zone/aunchindoun/sethekk_halls/def_sethekk_halls.h new file mode 100644 index 00000000000..f609ecac1f2 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/aunchindoun/sethekk_halls/def_sethekk_halls.h @@ -0,0 +1,9 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_SETHEKK_HALLS_H +#define DEF_SETHEKK_HALLS_H + +#define DATA_IKISSDOOREVENT 1 +#endif diff --git a/src/bindings/scripts/scripts/zone/aunchindoun/sethekk_halls/instance_sethekk_halls.cpp b/src/bindings/scripts/scripts/zone/aunchindoun/sethekk_halls/instance_sethekk_halls.cpp new file mode 100644 index 00000000000..980717653c6 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/aunchindoun/sethekk_halls/instance_sethekk_halls.cpp @@ -0,0 +1,74 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance - Sethekk Halls +SD%Complete: 50 +SDComment: Instance Data for Sethekk Halls instance +SDCategory: Auchindoun, Sethekk Halls +EndScriptData */ + +#include "precompiled.h" +#include "def_sethekk_halls.h" + +#define IKISS_DOOR 177203 + +struct MANGOS_DLL_DECL instance_sethekk_halls : public ScriptedInstance +{ + instance_sethekk_halls(Map *Map) : ScriptedInstance(Map) {Initialize();}; + + GameObject *IkissDoor; + + void Initialize() + { + IkissDoor = NULL; + } + + void OnObjectCreate(GameObject *go) + { + switch(go->GetEntry()) + { + case IKISS_DOOR: + IkissDoor = go; + break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_IKISSDOOREVENT: + if( IkissDoor ) + IkissDoor->SetGoState(0); + break; + } + } +}; + +InstanceData* GetInstanceData_instance_sethekk_halls(Map* map) +{ + return new instance_sethekk_halls(map); +} + +void AddSC_instance_sethekk_halls() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_sethekk_halls"; + newscript->GetInstanceData = GetInstanceData_instance_sethekk_halls; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/boss_ambassador_hellmaw.cpp b/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/boss_ambassador_hellmaw.cpp new file mode 100644 index 00000000000..b575461dfaa --- /dev/null +++ b/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/boss_ambassador_hellmaw.cpp @@ -0,0 +1,223 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Ambassador_Hellmaw +SD%Complete: 75 +SDComment: Waypoints after Intro not implemented. Enrage spell missing/not known +SDCategory: Auchindoun, Shadow Labyrinth +EndScriptData */ + +#include "precompiled.h" +#include "def_shadow_labyrinth.h" + +#define SAY_INTRO "Infidels have invaded the sanctuary! Sniveling pests...You have yet to learn the true meaning of agony!" +#define SOUND_INTRO 10473 + +#define SAY_AGGRO1 "Pathetic mortals! You will pay dearly!" +#define SOUND_AGGRO1 10475 +#define SAY_AGGRO2 "I will break you!" +#define SOUND_AGGRO2 10476 +#define SAY_AGGRO3 "Finally! Something to relieve the tedium!" +#define SOUND_AGGRO3 10477 + +#define SAY_HELP "Aid me, you fools, before it's too late!" +#define SOUND_HELP 10474 + +#define SAY_SLAY1 "Do you fear death?" +#define SOUND_SLAY1 10478 +#define SAY_SLAY2 "This is the part I enjoy most." +#define SOUND_SLAY2 10479 + +#define SAY_DEATH "Do not...grow...overconfident, mortal." +#define SOUND_DEATH 10480 + +#define SPELL_BANISH 30231 +#define SPELL_CORROSIVE_ACID 23313 +#define SPELL_FEAR 33547 +#define SPELL_ENRAGE 0 //need to find proper spell + +struct MANGOS_DLL_DECL boss_ambassador_hellmawAI : public ScriptedAI +{ + boss_ambassador_hellmawAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + bool HeroicMode; + + uint32 EventCheck_Timer; + uint32 CorrosiveAcid_Timer; + uint32 Fear_Timer; + uint32 Enrage_Timer; + bool Intro; + bool IsBanished; + + void Reset() + { + HeroicMode = m_creature->GetMap()->IsHeroic(); + + EventCheck_Timer = 5000; + CorrosiveAcid_Timer = 25000; + Fear_Timer = 40000; + Enrage_Timer = 180000; + Intro = false; + IsBanished = false; + + if( pInstance ) + { + if( pInstance->GetData(TYPE_HELLMAW) == NOT_STARTED ) + { + DoCast(m_creature,SPELL_BANISH); + IsBanished = true; + } + else pInstance->SetData(TYPE_HELLMAW,FAIL); + + if( pInstance->GetData(TYPE_OVERSEER) == DONE ) + { + if( m_creature->HasAura(SPELL_BANISH,0) ) + m_creature->RemoveAurasDueToSpell(SPELL_BANISH); + Intro = true; + } + } + } + + void MovementInform(uint32 type, uint32 id) + { + if( type != POINT_MOTION_TYPE ) + return; + } + + void DoIntro() + { + DoYell(SAY_INTRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_INTRO); + + if( m_creature->HasAura(SPELL_BANISH,0) ) + m_creature->RemoveAurasDueToSpell(SPELL_BANISH); + + IsBanished = false; + Intro = true; + + if( pInstance ) + pInstance->SetData(TYPE_HELLMAW, IN_PROGRESS); + } + + void Aggro(Unit *who) + { + switch(rand()%3) + { + case 0: + DoYell(SAY_AGGRO1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO1); + break; + case 1: + DoYell(SAY_AGGRO2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO2); + break; + case 2: + DoYell(SAY_AGGRO3, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO3); + break; + } + } + + void KilledUnit(Unit *victim) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_SLAY1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY1); + break; + case 1: + DoYell(SAY_SLAY2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY2); + break; + } + } + + void JustDied(Unit *victim) + { + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_DEATH); + + if( pInstance ) + pInstance->SetData(TYPE_HELLMAW, DONE); + } + + void UpdateAI(const uint32 diff) + { + if( !Intro ) + { + if( EventCheck_Timer < diff ) + { + if( pInstance ) + { + if( pInstance->GetData(TYPE_OVERSEER) == DONE ) + DoIntro(); + } + EventCheck_Timer = 5000; + }else EventCheck_Timer -= diff; + } + + if( !InCombat && !IsBanished ) + { + //this is where we add MovePoint() + //DoWhine("I haz no mount!", LANG_UNIVERSAL, NULL); + } + + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if( CorrosiveAcid_Timer < diff ) + { + DoCast(m_creature,SPELL_CORROSIVE_ACID); + CorrosiveAcid_Timer = 25000; + }else CorrosiveAcid_Timer -= diff; + + if( Fear_Timer < diff ) + { + DoCast(m_creature,SPELL_FEAR); + Fear_Timer = 35000; + }else Fear_Timer -= diff; + + /*if( HeroicMode ) + { + if( Enrage_Timer < diff ) + { + DoCast(m_creature,SPELL_ENRAGE); + }else Enrage_Timer -= diff; + }*/ + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_ambassador_hellmaw(Creature *_Creature) +{ + return new boss_ambassador_hellmawAI (_Creature); +} + +void AddSC_boss_ambassador_hellmaw() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_ambassador_hellmaw"; + newscript->GetAI = GetAI_boss_ambassador_hellmaw; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/boss_blackheart_the_inciter.cpp b/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/boss_blackheart_the_inciter.cpp new file mode 100644 index 00000000000..0a8c446b15c --- /dev/null +++ b/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/boss_blackheart_the_inciter.cpp @@ -0,0 +1,191 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Blackheart_the_Inciter +SD%Complete: 75 +SDComment: Incite Chaos not functional since core lacks Mind Control support +SDCategory: Auchindoun, Shadow Labyrinth +EndScriptData */ + +#include "precompiled.h" +#include "def_shadow_labyrinth.h" + +#define SPELL_INCITE_CHAOS 33676 +#define SPELL_INCITE_CHAOS_B 33684 //debuff applied to each member of party +#define SPELL_CHARGE 33709 +#define SPELL_WAR_STOMP 33707 + +#define SAY_AGGRO1 "You be dead people!" +#define SAY_AGGRO2 "Time to kill!" +#define SAY_AGGRO3 "I see dead people!" +#define SAY_SLAY1 "No coming back for you!" +#define SAY_SLAY2 "Nice try!" +#define SAY_SLAY3 "Now you gone for good!" +#define SAY_DEATH "This...no...good.." + +#define SOUND_AGGRO1 10498 +#define SOUND_AGGRO2 10497 +#define SOUND_AGGRO3 10488 +#define SOUND_SLAY1 10489 +#define SOUND_SLAY2 10490 +#define SOUND_SLAY3 10499 +#define SOUND_DEATH 10491 + +struct MANGOS_DLL_DECL boss_blackheart_the_inciterAI : public ScriptedAI +{ + boss_blackheart_the_inciterAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance *pInstance; + + bool InciteChaos; + uint32 InciteChaos_Timer; + uint32 InciteChaosWait_Timer; + uint32 Charge_Timer; + uint32 Knockback_Timer; + + void Reset() + { + InciteChaos = false; + InciteChaos_Timer = 20000; + InciteChaosWait_Timer = 15000; + Charge_Timer = 5000; + Knockback_Timer = 15000; + + if( pInstance ) + pInstance->SetData(DATA_BLACKHEARTTHEINCITEREVENT, NOT_STARTED); + } + + void KilledUnit(Unit *victim) + { + switch(rand()%3) + { + case 0: + DoYell(SAY_SLAY1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY1); + break; + case 1: + DoYell(SAY_SLAY2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY2); + break; + case 2: + DoYell(SAY_SLAY3, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY3); + break; + } + } + + void JustDied(Unit *victim) + { + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_DEATH); + + if( pInstance ) + pInstance->SetData(DATA_BLACKHEARTTHEINCITEREVENT, DONE); + } + + void Aggro(Unit *who) + { + switch(rand()%3) + { + case 0: + DoYell(SAY_AGGRO1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO1); + break; + case 1: + DoYell(SAY_AGGRO2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO2); + break; + case 2: + DoYell(SAY_AGGRO3, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO3); + break; + } + + if( pInstance ) + pInstance->SetData(DATA_BLACKHEARTTHEINCITEREVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if( InciteChaos ) + { + if( InciteChaosWait_Timer < diff ) + { + InciteChaos = false; + InciteChaosWait_Timer = 15000; + }else InciteChaosWait_Timer -= diff; + + return; + } + + if( InciteChaos_Timer < diff ) + { + DoCast(m_creature, SPELL_INCITE_CHAOS); + + std::list t_list = m_creature->getThreatManager().getThreatList(); + for( std::list::iterator itr = t_list.begin(); itr!= t_list.end(); ++itr ) + { + Unit* target = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid()); + if( target && target->GetTypeId() == TYPEID_PLAYER ) + target->CastSpell(target,SPELL_INCITE_CHAOS_B,true); + } + + DoResetThreat(); + InciteChaos = true; + InciteChaos_Timer = 40000; + return; + }else InciteChaos_Timer -= diff; + + //Charge_Timer + if( Charge_Timer < diff ) + { + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 0) ) + DoCast(target, SPELL_CHARGE); + Charge_Timer = 25000; + }else Charge_Timer -= diff; + + //Knockback_Timer + if( Knockback_Timer < diff ) + { + DoCast(m_creature, SPELL_WAR_STOMP); + Knockback_Timer = 20000; + }else Knockback_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_blackheart_the_inciter(Creature *_Creature) +{ + return new boss_blackheart_the_inciterAI (_Creature); +} + +void AddSC_boss_blackheart_the_inciter() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_blackheart_the_inciter"; + newscript->GetAI = GetAI_boss_blackheart_the_inciter; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp b/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp new file mode 100644 index 00000000000..5e278c91fc5 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp @@ -0,0 +1,294 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Grandmaster_Vorpil +SD%Complete: 75 +SDComment: Despawn all summoned on death not implemented. Void Traveler effects not implemented. +SDCategory: Auchindoun, Shadow Labyrinth +EndScriptData */ + +#include "precompiled.h" +#include "def_shadow_labyrinth.h" + +#define SPELL_DRAW_SHADOWS 33563 +#define SPELL_VOID_PORTAL_A 33566 //spell only summon one unit, but we use it for the visual effect and summon the 4 other portals manual way(only one spell exist) +#define SPELL_VOID_PORTAL_VISUAL 33569 +#define SPELL_SHADOW_BOLT_VOLLEY 32963 +#define SPELL_SUMMON_VOIDWALKER_A 33582 +#define SPELL_SUMMON_VOIDWALKER_B 33583 +#define SPELL_SUMMON_VOIDWALKER_C 33584 +#define SPELL_SUMMON_VOIDWALKER_D 33585 +#define SPELL_SUMMON_VOIDWALKER_E 33586 +#define SPELL_RAIN_OF_FIRE 33617 +#define H_SPELL_RAIN_OF_FIRE 39363 +#define H_SPELL_BANISH 38791 + +#define SAY_INTRO "Keep your minds focused for the days of reckoning are close at hand. Soon, the destroyer of worlds will return to make good on his promise. Soon the destruction of all that is will begin!" +#define SAY_AGGRO1 "I'll make an offering of your blood!" +#define SAY_AGGRO2 "You'll be a fine example, for the others." +#define SAY_AGGRO3 "Good, a worthy sacrifice." +#define SAY_HELP "Come to my aid, heed your master now!" +#define SAY_SLAY1 "I serve with pride." +#define SAY_SLAY2 "Your death is for the greater cause!" +#define SAY_DEATH "I give my life... Gladly." + +#define SOUND_INTRO 10522 +#define SOUND_AGGRO1 10524 +#define SOUND_AGGRO2 10525 +#define SOUND_AGGRO3 10526 +#define SOUND_HELP 10523 +#define SOUND_SLAY1 10527 +#define SOUND_SLAY2 10528 +#define SOUND_DEATH 10529 + +#define ENTRY_VOID_PORTAL 19224 +#define ENTRY_VOID_TRAVELER 19226 + +#define LOCX -253.06f +#define LOCY -264.02f +#define LOCZ 17.08 + +struct MANGOS_DLL_DECL boss_grandmaster_vorpilAI : public ScriptedAI +{ + boss_grandmaster_vorpilAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + bool HeroicMode; + + uint32 ShadowBoltVolley_Timer; + uint32 DrawShadows_Timer; + uint32 Teleport_Timer; + uint32 VoidTraveler_Timer; + uint32 Banish_Timer; + bool Intro; + bool Teleport; + + void Reset() + { + HeroicMode = m_creature->GetMap()->IsHeroic(); + + ShadowBoltVolley_Timer = 15000; + DrawShadows_Timer = 40000; + Teleport_Timer = 1000; + VoidTraveler_Timer = 20000; + Banish_Timer = 25000; + Intro = false; + Teleport = false; + + if( pInstance ) + pInstance->SetData(DATA_GRANDMASTERVORPILEVENT, NOT_STARTED); + } + + void MoveInLineOfSight(Unit *who) + { + if( !m_creature->getVictim() && who->isTargetableForAttack() && ( m_creature->IsHostileTo( who )) && who->isInAccessablePlaceFor(m_creature) ) + { + //not sure about right radius + if(!Intro && m_creature->IsWithinDistInMap(who, 50)) + { + DoYell(SAY_INTRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_INTRO); + DoCast(m_creature, SPELL_VOID_PORTAL_A,true); + m_creature->SummonCreature(ENTRY_VOID_PORTAL,-262.40,-229.57,17.08,0,TEMPSUMMON_CORPSE_DESPAWN,0); + m_creature->SummonCreature(ENTRY_VOID_PORTAL,-260.35,-297.56,17.08,0,TEMPSUMMON_CORPSE_DESPAWN,0); + m_creature->SummonCreature(ENTRY_VOID_PORTAL,-292.05,-270.37,12.68,0,TEMPSUMMON_CORPSE_DESPAWN,0); + m_creature->SummonCreature(ENTRY_VOID_PORTAL,-301.64,-255.97,12.68,0,TEMPSUMMON_CORPSE_DESPAWN,0); + Intro = true; + } + + if (m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = m_creature->GetAttackDistance(who); + if( m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->IsWithinLOSInMap(who) ) + { + DoStartAttackAndMovement(who); + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + if (!InCombat) + { + Aggro(who); + InCombat = true; + } + } + } + } + + void Aggro(Unit *who) + { + switch(rand()%3) + { + case 0: + DoYell(SAY_AGGRO1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO1); + break; + case 1: + DoYell(SAY_AGGRO2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO2); + break; + case 2: + DoYell(SAY_AGGRO3, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO3); + break; + } + + if( pInstance ) + pInstance->SetData(DATA_GRANDMASTERVORPILEVENT, IN_PROGRESS); + } + + void KilledUnit(Unit *victim) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_SLAY1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY1); + break; + case 1: + DoYell(SAY_SLAY2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY2); + break; + } + } + + void JustSummoned(Creature *summoned) + { + if( summoned->GetEntry() == ENTRY_VOID_TRAVELER ) + { + summoned->GetMotionMaster()->MoveChase(m_creature); + summoned->SetSpeed(MOVE_WALK,0.8,true); + } + + if( summoned->GetEntry() == ENTRY_VOID_PORTAL ) + summoned->CastSpell(summoned,SPELL_VOID_PORTAL_VISUAL,true); + } + + void JustDied(Unit *victim) + { + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_DEATH); + + if( pInstance ) + pInstance->SetData(DATA_GRANDMASTERVORPILEVENT, DONE); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if( Teleport ) + { + if( Teleport_Timer <= diff ) + { + m_creature->Relocate(LOCX,LOCY,LOCZ); + m_creature->SendMonsterMove(LOCX,LOCY,LOCZ,0,true,0); + + float ranX = LOCX; + float ranY = LOCY; + float ranZ = LOCZ; + + std::list t_list = m_creature->getThreatManager().getThreatList(); + for( std::list::iterator itr = t_list.begin(); itr!= t_list.end(); ++itr ) + { + Unit* target = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid()); + if( target && target->GetTypeId() == TYPEID_PLAYER ) + { + target->GetRandomPoint(LOCX,LOCY,LOCZ,3.0,ranX,ranY,ranZ); + DoTeleportPlayer(target,ranX,ranY,ranZ,m_creature->GetAngle(m_creature->GetPositionX(),m_creature->GetPositionY())); + } + } + Teleport = false; + + if( HeroicMode ) DoCast(m_creature->getVictim(), H_SPELL_RAIN_OF_FIRE); + else DoCast(m_creature->getVictim(), SPELL_RAIN_OF_FIRE); + + Teleport_Timer = 1000; + }else Teleport_Timer -= diff; + } + + if( ShadowBoltVolley_Timer < diff ) + { + DoCast(m_creature->getVictim(), SPELL_SHADOW_BOLT_VOLLEY); + ShadowBoltVolley_Timer = 30000; + }else ShadowBoltVolley_Timer -= diff; + + if( DrawShadows_Timer < diff ) + { + DoCast(m_creature,SPELL_DRAW_SHADOWS); + DrawShadows_Timer = 35000; + Teleport = true; + }else DrawShadows_Timer -= diff; + + if( VoidTraveler_Timer < diff ) + { + DoYell(SAY_HELP, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_HELP); + + switch(rand()%5) + { + case 0: + DoCast(m_creature,SPELL_SUMMON_VOIDWALKER_A,true); + break; + case 1: + DoCast(m_creature,SPELL_SUMMON_VOIDWALKER_B,true); + break; + case 2: + DoCast(m_creature,SPELL_SUMMON_VOIDWALKER_C,true); + break; + case 3: + DoCast(m_creature,SPELL_SUMMON_VOIDWALKER_D,true); + break; + case 4: + DoCast(m_creature,SPELL_SUMMON_VOIDWALKER_E,true); + break; + } + //faster rate when below (X) health? + VoidTraveler_Timer = 35000; + }else VoidTraveler_Timer -= diff; + + if( HeroicMode ) + { + if( Banish_Timer < diff ) + { + if( Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1) ) + DoCast(target,H_SPELL_BANISH); + Banish_Timer = 35000; + }else Banish_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_grandmaster_vorpil(Creature *_Creature) +{ + return new boss_grandmaster_vorpilAI (_Creature); +} + +void AddSC_boss_grandmaster_vorpil() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_grandmaster_vorpil"; + newscript->GetAI = GetAI_boss_grandmaster_vorpil; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/boss_murmur.cpp b/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/boss_murmur.cpp new file mode 100644 index 00000000000..81aa6ee170d --- /dev/null +++ b/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/boss_murmur.cpp @@ -0,0 +1,192 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Murmur +SD%Complete: 75 +SDComment: Database should have `RegenHealth`=0 to prevent regen. Also, his shockwave triggered after magnetic pull may be incorrect. Murmur's Touch does not work properly. +SDCategory: Auchindoun, Shadow Labyrinth +EndScriptData */ + +#include "precompiled.h" + +#define EMOTE_SONIC_BOOM "draws energy from the air." + +#define SPELL_MAGNETIC_PULL 33689 +#define SPELL_SONIC_BOOM_PRE 33923 +#define SPELL_SONIC_BOOM_CAST 38795 +#define SPELL_MURMURS_TOUCH 33711 +#define SPELL_RESONANCE 33657 +#define SPELL_SHOCKWAVE 33686 + +struct MANGOS_DLL_DECL boss_murmurAI : public ScriptedAI +{ + boss_murmurAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 SonicBoom_Timer; + uint32 MurmursTouch_Timer; + uint32 Resonance_Timer; + uint32 MagneticPull_Timer; + bool CanSonicBoom; + bool CanShockWave; + uint64 pTarget; + + void Reset() + { + SonicBoom_Timer = 30000; + MurmursTouch_Timer = 20000; + Resonance_Timer = 10000; + MagneticPull_Timer = 45000; + CanSonicBoom = false; + CanShockWave = false; + pTarget = 0; + + //database should have `RegenHealth`=0 to prevent regen + uint32 hp = m_creature->GetMaxHealth()*0.4; + if( hp ) + m_creature->SetHealth(hp); + } + + void Aggro(Unit *who) { } + + void AttackStart(Unit* who) + { + if (!who) + return; + + if (who->isTargetableForAttack()) + { + //Begin attack + DoStartAttackNoMovement(who); + + if (!InCombat) + { + Aggro(who); + InCombat = true; + } + } + } + + void MoveInLineOfSight(Unit* who) + { + if( !m_creature->getVictim() && who->isTargetableForAttack() && ( m_creature->IsHostileTo( who )) && who->isInAccessablePlaceFor(m_creature) ) + { + if (m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = m_creature->GetAttackDistance(who); + if(m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->IsWithinLOSInMap(who)) + { + DoStartAttackNoMovement(who); + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + if (!InCombat) + { + Aggro(who); + InCombat = true; + } + } + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //SonicBoom_Timer + if(SonicBoom_Timer < diff) + { + if(CanSonicBoom) + { + DoCast(m_creature, SPELL_SONIC_BOOM_CAST,true); + CanSonicBoom = false; + SonicBoom_Timer = 30000; + } + else + { + DoTextEmote(EMOTE_SONIC_BOOM,NULL); + DoCast(m_creature,SPELL_SONIC_BOOM_PRE); + CanSonicBoom = true; + SonicBoom_Timer = 5000; + } + }else SonicBoom_Timer -= diff; + + //MurmursTouch_Timer + if(MurmursTouch_Timer < diff) + { + /*Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if(target) + DoCast(target, SPELL_MURMURS_TOUCH);*/ + DoCast(m_creature, SPELL_MURMURS_TOUCH); + MurmursTouch_Timer = 30000; + }else MurmursTouch_Timer -= diff; + + //Resonance_Timer + if(Resonance_Timer < diff) + { + if( !m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE) ) + DoCast(m_creature->getVictim(), SPELL_RESONANCE); + Resonance_Timer = 5000; + }else Resonance_Timer -= diff; + + //MagneticPull_Timer + if(MagneticPull_Timer < diff) + { + if( !CanShockWave ) + { + if( Unit* temp = SelectUnit(SELECT_TARGET_RANDOM,0) ) + { + if( temp->GetTypeId() == TYPEID_PLAYER ) + { + DoCast(temp, SPELL_MAGNETIC_PULL); + pTarget = temp->GetGUID(); + CanShockWave = true; + } + MagneticPull_Timer = 2500; + } + } + else + { + if( Unit* target = Unit::GetUnit(*m_creature,pTarget) ) + target->CastSpell(target,SPELL_SHOCKWAVE,true); + + MagneticPull_Timer = 35000; + CanShockWave = false; + pTarget = 0; + } + }else MagneticPull_Timer -= diff; + + //no meele if preparing for sonic boom + if(!CanSonicBoom) + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_murmur(Creature *_Creature) +{ + return new boss_murmurAI (_Creature); +} + +void AddSC_boss_murmur() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_murmur"; + newscript->GetAI = GetAI_boss_murmur; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/def_shadow_labyrinth.h b/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/def_shadow_labyrinth.h new file mode 100644 index 00000000000..77b0387af16 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/def_shadow_labyrinth.h @@ -0,0 +1,13 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_SHADOW_LABYRINTH_H +#define DEF_SHADOW_LABYRINTH_H + +#define TYPE_HELLMAW 1 +#define TYPE_OVERSEER 2 +#define DATA_BLACKHEARTTHEINCITEREVENT 3 +#define DATA_GRANDMASTERVORPILEVENT 4 +#define DATA_MURMUREVENT 5 +#endif diff --git a/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp b/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp new file mode 100644 index 00000000000..ea2c141b2e0 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp @@ -0,0 +1,168 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Shadow_Labyrinth +SD%Complete: 85 +SDComment: Some cleanup left along with save +SDCategory: Auchindoun, Shadow Labyrinth +EndScriptData */ + +#include "precompiled.h" +#include "def_shadow_labyrinth.h" + +#define ENCOUNTERS 5 + +#define REFECTORY_DOOR 183296 //door opened when blackheart the inciter dies +#define SCREAMING_HALL_DOOR 183295 //door opened when grandmaster vorpil dies + +/* Shadow Labyrinth encounters: +1 - Ambassador Hellmaw event +2 - Blackheart the Inciter event +3 - Grandmaster Vorpil event +4 - Murmur event +*/ + +struct MANGOS_DLL_DECL instance_shadow_labyrinth : public ScriptedInstance +{ + instance_shadow_labyrinth(Map *Map) : ScriptedInstance(Map) {Initialize();}; + + uint32 Encounter[ENCOUNTERS]; + + GameObject *RefectoryDoor; + GameObject *ScreamingHallDoor; + uint64 GrandmasterVorpil; + uint32 FelOverseerCount; + + void Initialize() + { + RefectoryDoor = NULL; + ScreamingHallDoor = NULL; + GrandmasterVorpil = 0; + FelOverseerCount = 0; + + for(uint8 i = 0; i < ENCOUNTERS; i++) + Encounter[i] = false; + } + + bool IsEncounterInProgress() const + { + for(uint8 i = 0; i < ENCOUNTERS; i++) + if(Encounter[i]) return true; + + return false; + } + + void OnObjectCreate(GameObject *go) + { + switch(go->GetEntry()) + { + case REFECTORY_DOOR: + RefectoryDoor = go; + break; + case SCREAMING_HALL_DOOR: + ScreamingHallDoor = go; + break; + } + } + + void OnCreatureCreate(Creature *creature, uint32 creature_entry) + { + switch(creature_entry) + { + case 18732: + GrandmasterVorpil = creature->GetGUID(); + break; + case 18796: + ++FelOverseerCount; + debug_log("SD2: Shadow Labyrinth: counting %u Fel Overseers.",FelOverseerCount); + break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case TYPE_HELLMAW: + Encounter[0] = data; + break; + + case TYPE_OVERSEER: + if( data != DONE ) + error_log("SD2: Shadow Labyrinth: TYPE_OVERSEER did not expect other data than DONE"); + if( FelOverseerCount ) + { + --FelOverseerCount; + debug_log("SD2: Shadow Labyrinth: %u Fel Overseers left to kill.",FelOverseerCount); + } + if( FelOverseerCount == 0 ) + { + Encounter[1] = DONE; + debug_log("SD2: Shadow Labyrinth: TYPE_OVERSEER == DONE"); + } + break; + + case DATA_BLACKHEARTTHEINCITEREVENT: + if( data == DONE ) + { + if( RefectoryDoor ) + RefectoryDoor->UseDoorOrButton(); + } + Encounter[2] = data; + break; + + case DATA_GRANDMASTERVORPILEVENT: + if( data == DONE ) + { + if( ScreamingHallDoor ) + ScreamingHallDoor->UseDoorOrButton(); + } + Encounter[3] = data; + break; + + case DATA_MURMUREVENT: + Encounter[4] = data; + break; + } + } + + uint32 GetData(uint32 type) + { + switch( type ) + { + case TYPE_HELLMAW: + return Encounter[0]; + case TYPE_OVERSEER: + return Encounter[1]; + } + return false; + } +}; + +InstanceData* GetInstanceData_instance_shadow_labyrinth(Map* map) +{ + return new instance_shadow_labyrinth(map); +} + +void AddSC_instance_shadow_labyrinth() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_shadow_labyrinth"; + newscript->GetInstanceData = GetInstanceData_instance_shadow_labyrinth; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/azshara/azshara.cpp b/src/bindings/scripts/scripts/zone/azshara/azshara.cpp new file mode 100644 index 00000000000..c892847bbc8 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/azshara/azshara.cpp @@ -0,0 +1,164 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Azshara +SD%Complete: 90 +SDComment: Quest support: 2744, 3141, 9364 +SDCategory: Azshara +EndScriptData */ + +/* ContentData +mobs_spitelashes +npc_loramus_thalipedes +EndContentData */ + +#include "precompiled.h" + +/*###### +## mobs_spitelashes +######*/ + +struct MANGOS_DLL_DECL mobs_spitelashesAI : public ScriptedAI +{ + mobs_spitelashesAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 morphtimer; + bool spellhit; + + void Reset() + { + morphtimer = 0; + spellhit = false; + } + + void Aggro(Unit *who) { } + + void SpellHit(Unit *Hitter, const SpellEntry *Spellkind) + { + if( !spellhit && + Hitter->GetTypeId() == TYPEID_PLAYER && + ((Player*)Hitter)->GetQuestStatus(9364) == QUEST_STATUS_INCOMPLETE && + (Spellkind->Id==118 || Spellkind->Id== 12824 || Spellkind->Id== 12825 || Spellkind->Id== 12826) ) + { + spellhit=true; + DoCast(m_creature,29124); //become a sheep + } + } + + void UpdateAI(const uint32 diff) + { + // we mustn't remove the creature in the same round in which we cast the summon spell, otherwise there will be no summons + if( spellhit && morphtimer>=5000 ) + { + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + m_creature->RemoveCorpse(); //you don't see any corpse on off. + EnterEvadeMode(); //spellhit will be set to false + } + // walk 5 seconds before summoning + if( spellhit && morphtimer<5000 ) + { + morphtimer+=diff; + if( morphtimer>=5000 ) + { + DoCast(m_creature,28406); //summon copies + DoCast(m_creature,6924); //visual explosion + } + } + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //TODO: add abilities for the different creatures + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_mobs_spitelashes(Creature *_Creature) +{ + return new mobs_spitelashesAI (_Creature); +} + +/*###### +## npc_loramus_thalipedes +######*/ + +bool GossipHello_npc_loramus_thalipedes(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if (player->GetQuestStatus(2744) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM( 0, "Can you help me?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + if (player->GetQuestStatus(3141) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM( 0, "Tell me your story", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_loramus_thalipedes(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF+1: + player->CLOSE_GOSSIP_MENU(); + player->AreaExploredOrEventHappens(2744); + break; + + case GOSSIP_ACTION_INFO_DEF+2: + player->ADD_GOSSIP_ITEM( 0, "Please continue", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 21); + player->SEND_GOSSIP_MENU(1813, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+21: + player->ADD_GOSSIP_ITEM( 0, "I do not understand", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 22); + player->SEND_GOSSIP_MENU(1814, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+22: + player->ADD_GOSSIP_ITEM( 0, "Indeed", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 23); + player->SEND_GOSSIP_MENU(1815, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+23: + player->ADD_GOSSIP_ITEM( 0, "I will do this with or your help, Loramus", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 24); + player->SEND_GOSSIP_MENU(1816, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+24: + player->ADD_GOSSIP_ITEM( 0, "Yes", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 25); + player->SEND_GOSSIP_MENU(1817, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+25: + player->CLOSE_GOSSIP_MENU(); + player->AreaExploredOrEventHappens(3141); + break; + } + return true; +} + +void AddSC_azshara() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="mobs_spitelashes"; + newscript->GetAI = GetAI_mobs_spitelashes; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_loramus_thalipedes"; + newscript->pGossipHello = &GossipHello_npc_loramus_thalipedes; + newscript->pGossipSelect = &GossipSelect_npc_loramus_thalipedes; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/azshara/boss_azuregos.cpp b/src/bindings/scripts/scripts/zone/azshara/boss_azuregos.cpp new file mode 100644 index 00000000000..5193fd841a1 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/azshara/boss_azuregos.cpp @@ -0,0 +1,153 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Azuregos +SD%Complete: 90 +SDComment: Teleport not included, spell reflect not effecting dots (Core problem) +SDCategory: Azshara +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_MARKOFFROST 23182 +#define SPELL_MANASTORM 21097 +#define SPELL_CHILL 21098 +#define SPELL_FROSTBREATH 21099 +#define SPELL_REFLECT 22067 //Old one was 30969 +#define SPELL_CLEAVE 8255 //Perhaps not right ID +#define SPELL_ENRAGE 23537 + +struct MANGOS_DLL_DECL boss_azuregosAI : public ScriptedAI +{ + boss_azuregosAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 MarkOfFrost_Timer; + uint32 ManaStorm_Timer; + uint32 Chill_Timer; + uint32 Breath_Timer; + uint32 Teleport_Timer; + uint32 Reflect_Timer; + uint32 Cleave_Timer; + uint32 Enrage_Timer; + bool Enraged; + + void Reset() + { + MarkOfFrost_Timer = 35000; + ManaStorm_Timer = 5000 + rand()%12000; + Chill_Timer = 10000 + rand()%20000; + Breath_Timer = 2000 + rand()%6000; + Teleport_Timer = 30000; + Reflect_Timer = 15000 + rand()%15000; + Cleave_Timer = 7000; + Enrage_Timer = 0; + Enraged = false; + } + + void Aggro(Unit *who) {} + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if(Teleport_Timer < diff) + { + std::list& m_threatlist = m_creature->getThreatManager().getThreatList(); + std::list::iterator i = m_threatlist.begin(); + for (i = m_threatlist.begin(); i!= m_threatlist.end();++i) + { + Unit* pUnit = Unit::GetUnit((*m_creature), (*i)->getUnitGuid()); + if(pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER)) + { + DoTeleportPlayer(pUnit, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ()+3, pUnit->GetOrientation()); + } + } + + DoResetThreat(); + Teleport_Timer = 30000; + }else Teleport_Timer -= diff; + + // //MarkOfFrost_Timer + // if (MarkOfFrost_Timer < diff) + // { + // DoCast(m_creature->getVictim(),SPELL_MARKOFFROST); + // MarkOfFrost_Timer = 25000; + // }else MarkOfFrost_Timer -= diff; + + //Chill_Timer + if (Chill_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CHILL); + Chill_Timer = 13000 + rand()%12000; + }else Chill_Timer -= diff; + + //Breath_Timer + if (Breath_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FROSTBREATH); + Breath_Timer = 10000 + rand()%5000; + }else Breath_Timer -= diff; + + //ManaStorm_Timer + if (ManaStorm_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) + DoCast(target,SPELL_MANASTORM); + ManaStorm_Timer = 7500 + rand()%5000; + }else ManaStorm_Timer -= diff; + + //Reflect_Timer + if (Reflect_Timer < diff) + { + DoCast(m_creature,SPELL_REFLECT); + Reflect_Timer = 20000 + rand()%15000; + }else Reflect_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CLEAVE); + Cleave_Timer = 7000; + }else Cleave_Timer -= diff; + + //Enrage_Timer + if (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 26 && !Enraged) + { + DoCast(m_creature, SPELL_ENRAGE); + Enraged = true; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_azuregos(Creature *_Creature) +{ + return new boss_azuregosAI (_Creature); +} + +void AddSC_boss_azuregos() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_azuregos"; + newscript->GetAI = GetAI_boss_azuregos; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/azuremyst_isle/azuremyst_isle.cpp b/src/bindings/scripts/scripts/zone/azuremyst_isle/azuremyst_isle.cpp new file mode 100644 index 00000000000..f1f68ff4ee3 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/azuremyst_isle/azuremyst_isle.cpp @@ -0,0 +1,372 @@ +/* Copyright (C) 2006,2007 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Azuremyst_Isle +SD%Complete: 75 +SDComment: Quest support: 9283, 9537, 9554(special flight path, proper model for mount missing). Injured Draenei cosmetic only +SDCategory: Azuremyst Isle +EndScriptData */ + +/* ContentData +npc_draenei_survivor +npc_engineer_spark_overgrind +npc_injured_draenei +npc_susurrus +EndContentData */ + +#include "precompiled.h" +#include + +/*###### +## npc_draenei_survivor +######*/ + +#define HEAL1 "The last thing I remember is the ship falling and us getting into the pods. I'll go see how I can help. Thank you!" +#define HEAL2 "$C, Where am I? Who are you? Oh no! What happened to the ship?." +#define HEAL3 "$C You saved me! I owe you a debt that I can never repay. I'll go see if I can help the others." +#define HEAL4 "Ugh... what is this place? Is that all that's left of the ship over there?" + +#define HELP1 "Oh, the pain..." +#define HELP2 "Everything hurts, Please make it stop..." +#define HELP3 "Ughhh... I hurt. Can you help me?" +#define HELP4 "I don't know if I can make it, please help me..." + +struct MANGOS_DLL_DECL npc_draenei_survivorAI : public ScriptedAI +{ + npc_draenei_survivorAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 UnSpawnTimer; + uint32 ResetlifeTimer; + uint32 SayingTimer; + uint32 HealSayTimer; + bool UnSpawn; + bool say; + bool HealSay; + bool isRun; + bool isMove; + + void Reset() + { + UnSpawnTimer = 2500; + ResetlifeTimer= 60000; + SayingTimer = 5000; + HealSayTimer = 6000; + say = false; + isRun = false; + isMove = false; + UnSpawn = false; + HealSay = false; + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); + //cast red shining + m_creature->CastSpell(m_creature, 29152, false, NULL); + //set creature health + m_creature->SetHealth(int(m_creature->GetMaxHealth()*.1)); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 3); + } + + void Aggro(Unit *who) {} + + void MoveInLineOfSight(Unit *who) //MoveInLineOfSight is called if creature could see you, updated all 100 ms + { + if (!who) + return; + + if(who->GetTypeId() == TYPEID_PLAYER && m_creature->IsFriendlyTo(who) && m_creature->IsWithinDistInMap(who, 15) && say && !isRun) + { + switch (rand()%4) //Random switch between 4 texts + { + case 0: + DoSay(HELP1, LANG_UNIVERSAL, NULL); + SayingTimer = 15000; + say = false; + break; + case 1: + DoSay(HELP2, LANG_UNIVERSAL, NULL); + SayingTimer = 15000; + say = false; + break; + case 2: + DoSay(HELP3, LANG_UNIVERSAL, NULL); + SayingTimer = 15000; + say = false; + break; + case 3: + DoSay(HELP4, LANG_UNIVERSAL, NULL); + SayingTimer = 15000; + say = false; + break; + } + } + else + { + isRun = false; + } + } + + void UpdateAI(const uint32 diff) //Is also called each ms for Creature AI Updates... + { + if (m_creature->GetHealth() > 50) + { + if(ResetlifeTimer < diff) + { + ResetlifeTimer = 60000; + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); + //set creature health + m_creature->SetHealth(int(m_creature->GetMaxHealth()*.1)); + // ley down + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1,3); + } + else ResetlifeTimer -= diff; + } + + if(HealSay) + { + if (HealSayTimer < diff) + { + UnSpawn = true; + isRun = true; + isMove = true; + }else HealSayTimer -= diff; + } + + if(UnSpawn) + { + if(isMove) + { + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MovePoint(0, -4115.053711f, -13754.831055f, 73.508949f); + isMove = false; + } + + if (UnSpawnTimer < diff) + { + m_creature->StopMoving(); + EnterEvadeMode(); + //set creature health + m_creature->SetHealth(int(m_creature->GetMaxHealth()*.1)); + + }else UnSpawnTimer -= diff; + } + + if(SayingTimer < diff) + { + say = true; + }else SayingTimer -= diff; + } + + void SpellHit(Unit *Hitter, const SpellEntry *Spellkind)//Called if you cast a spell and do some things if Specified spell is true! + { + if (Hitter && Spellkind->Id == 28880) + { + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + m_creature->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED); + m_creature->HandleEmoteCommand(ANIM_RISE); + switch (rand()%4) //This switch doesn't work at all, creature say nothing! + { + case 0: DoSay(HEAL1, LANG_UNIVERSAL, Hitter); break; + case 1: DoSay(HEAL2, LANG_UNIVERSAL, Hitter); break; + case 2: DoSay(HEAL3, LANG_UNIVERSAL, Hitter); break; + case 3: DoSay(HEAL4, LANG_UNIVERSAL, Hitter); break; + } + HealSay = true; + } + } +}; +CreatureAI* GetAI_npc_draenei_survivor(Creature *_Creature) +{ + return new npc_draenei_survivorAI (_Creature); +} + +/*###### +## npc_engineer_spark_overgrind +######*/ + +#define SAY_TEXT "Yes Master, all goes along as planned." +#define SAY_EMOTE "puts the shell to his ear." +#define GOSSIP_FIGHT "Traitor! You will be brought to justice!" +#define ATTACK_YELL "Now I cut you!" +#define SPELL_DYNAMITE 7978 + +struct MANGOS_DLL_DECL npc_engineer_spark_overgrindAI : public ScriptedAI +{ + npc_engineer_spark_overgrindAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Dynamite_Timer; + uint32 Emote_Timer; + + void Reset() + { + Dynamite_Timer = 8000; + Emote_Timer = 120000 + rand()%30000; + m_creature->setFaction(875); + } + + void Aggro(Unit *who) { } + + void UpdateAI(const uint32 diff) + { + if( !InCombat ) + { + if (Emote_Timer < diff) + { + DoSay(SAY_TEXT,LANG_UNIVERSAL,NULL); + DoTextEmote(SAY_EMOTE,NULL); + Emote_Timer = 120000 + rand()%30000; + }else Emote_Timer -= diff; + } + + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if (Dynamite_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_DYNAMITE); + Dynamite_Timer = 8000; + } else Dynamite_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_engineer_spark_overgrind(Creature *_Creature) +{ + return new npc_engineer_spark_overgrindAI (_Creature); +} + +bool GossipHello_npc_engineer_spark_overgrind(Player *player, Creature *_Creature) +{ + if( player->GetQuestStatus(9537) == QUEST_STATUS_INCOMPLETE ) + player->ADD_GOSSIP_ITEM(0, GOSSIP_FIGHT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + return true; +} + +bool GossipSelect_npc_engineer_spark_overgrind(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if( action == GOSSIP_ACTION_INFO_DEF ) + { + player->CLOSE_GOSSIP_MENU(); + _Creature->setFaction(14); + _Creature->Yell(ATTACK_YELL, LANG_UNIVERSAL, player->GetGUID()); + ((npc_engineer_spark_overgrindAI*)_Creature->AI())->AttackStart(player); + } + return true; +} + +/*###### +## npc_injured_draenei +######*/ + +struct MANGOS_DLL_DECL npc_injured_draeneiAI : public ScriptedAI +{ + npc_injured_draeneiAI(Creature *c) : ScriptedAI(c) {Reset();} + + void Reset() + { + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); + m_creature->SetHealth(int(m_creature->GetMaxHealth()*.15)); + switch (rand()%2) + { + case 0: m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 1); break; + case 1: m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 3); break; + } + } + + void Aggro(Unit *who) {} + + void MoveInLineOfSight(Unit *who) + { + return; //ignore everyone around them (won't aggro anything) + } + + void UpdateAI(const uint32 diff) + { + return; + } + +}; +CreatureAI* GetAI_npc_injured_draenei(Creature *_Creature) +{ + return new npc_injured_draeneiAI (_Creature); +} + +/*###### +## npc_susurrus +######*/ + +bool GossipHello_npc_susurrus(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if (player->HasItemCount(23843,1,true)) + player->ADD_GOSSIP_ITEM(0, "I am ready.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_susurrus(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if (action == GOSSIP_ACTION_INFO_DEF) + { + player->CLOSE_GOSSIP_MENU(); + player->CastSpell(player,32474,true); //apparently correct spell, possible not correct place to cast, or correct caster + + std::vector nodes; + + nodes.resize(2); + nodes[0] = 92; //from susurrus + nodes[1] = 91; //end at exodar + player->ActivateTaxiPathTo(nodes,11686); //TaxiPath 506. Using invisible model, possible mangos must allow 0(from dbc) for cases like this. + } + return true; +} + +/*###### +## +######*/ + +void AddSC_azuremyst_isle() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npc_draenei_survivor"; + newscript->GetAI = GetAI_npc_draenei_survivor; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_engineer_spark_overgrind"; + newscript->GetAI = GetAI_npc_engineer_spark_overgrind; + newscript->pGossipHello = &GossipHello_npc_engineer_spark_overgrind; + newscript->pGossipSelect = &GossipSelect_npc_engineer_spark_overgrind; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_injured_draenei"; + newscript->GetAI = GetAI_npc_injured_draenei; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_susurrus"; + newscript->pGossipHello = &GossipHello_npc_susurrus; + newscript->pGossipSelect = &GossipSelect_npc_susurrus; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/barrens/the_barrens.cpp b/src/bindings/scripts/scripts/zone/barrens/the_barrens.cpp new file mode 100644 index 00000000000..b09dd9222de --- /dev/null +++ b/src/bindings/scripts/scripts/zone/barrens/the_barrens.cpp @@ -0,0 +1,189 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: The_Barrens +SD%Complete: 90 +SDComment: Quest support: 2458, 4921, 6981 +SDCategory: Barrens +EndScriptData */ + +/* ContentData +npc_beaten_corpse +npc_sputtervalve +npc_taskmaster_fizzule remove hack when mangos implement feature/detect spell kind to not aggro +EndContentData */ + +#include "precompiled.h" + +/*###### +## npc_beaten_corpse +######*/ + +bool GossipHello_npc_beaten_corpse(Player *player, Creature *_Creature) +{ + if( player->GetQuestStatus(4921) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(4921) == QUEST_STATUS_COMPLETE) + player->ADD_GOSSIP_ITEM(0,"Examine corpse in detail...",GOSSIP_SENDER_MAIN,GOSSIP_ACTION_INFO_DEF+1); + + player->SEND_GOSSIP_MENU(3557,_Creature->GetGUID()); + return true; +} + +bool GossipSelect_npc_beaten_corpse(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if(action == GOSSIP_ACTION_INFO_DEF +1) + { + player->SEND_GOSSIP_MENU(3558,_Creature->GetGUID()); + player->KilledMonster( 10668,_Creature->GetGUID() ); + } + return true; +} + +/*###### +## npc_sputtervalve +######*/ + +bool GossipHello_npc_sputtervalve(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if( player->GetQuestStatus(6981) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM(0,"Can you tell me about this shard?",GOSSIP_SENDER_MAIN,GOSSIP_ACTION_INFO_DEF); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(),_Creature->GetGUID()); + return true; +} + +bool GossipSelect_npc_sputtervalve(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if(action == GOSSIP_ACTION_INFO_DEF) + { + player->SEND_GOSSIP_MENU(2013,_Creature->GetGUID()); + player->AreaExploredOrEventHappens(6981); + } + return true; +} + +/*###### +## npc_taskmaster_fizzule +######*/ + +//#define FACTION_HOSTILE_F 430 +#define FACTION_HOSTILE_F 16 +#define FACTION_FRIENDLY_F 35 + +#define SPELL_FLARE 10113 +#define SPELL_FOLLY 10137 + +struct MANGOS_DLL_DECL npc_taskmaster_fizzuleAI : public ScriptedAI +{ + npc_taskmaster_fizzuleAI(Creature* c) : ScriptedAI(c) { Reset(); } + + bool IsFriend; + uint32 Reset_Timer; + uint32 FlareCount; + + void Reset() + { + IsFriend = false; + Reset_Timer = 120000; + FlareCount = 0; + m_creature->setFaction(FACTION_HOSTILE_F); + m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + } + + //This is a hack. Spellcast will make creature aggro but that is not + //supposed to happen (mangos not implemented/not found way to detect this spell kind) + void DoUglyHack() + { + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); + m_creature->CombatStop(); + } + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if( spell->Id == SPELL_FLARE || spell->Id == SPELL_FOLLY ) + { + DoUglyHack(); + ++FlareCount; + if( FlareCount >= 2 ) + { + m_creature->setFaction(FACTION_FRIENDLY_F); + IsFriend = true; + } + } + } + + void Aggro(Unit* who) { } + + void UpdateAI(const uint32 diff) + { + if( IsFriend ) + { + if( Reset_Timer < diff ) + { + EnterEvadeMode(); + } else Reset_Timer -= diff; + } + + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_npc_taskmaster_fizzule(Creature *_Creature) +{ + return new npc_taskmaster_fizzuleAI (_Creature); +} + +bool ReciveEmote_npc_taskmaster_fizzule(Player *player, Creature *_Creature, uint32 emote) +{ + if( emote == TEXTEMOTE_SALUTE ) + { + if( ((npc_taskmaster_fizzuleAI*)_Creature->AI())->FlareCount >= 2 ) + { + _Creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + _Creature->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE); + } + } + return true; +} + +void AddSC_the_barrens() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npc_beaten_corpse"; + newscript->pGossipHello = &GossipHello_npc_beaten_corpse; + newscript->pGossipSelect = &GossipSelect_npc_beaten_corpse; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_sputtervalve"; + newscript->pGossipHello = &GossipHello_npc_sputtervalve; + newscript->pGossipSelect = &GossipSelect_npc_sputtervalve; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_taskmaster_fizzule"; + newscript->GetAI = GetAI_npc_taskmaster_fizzule; + newscript->pReceiveEmote = &ReciveEmote_npc_taskmaster_fizzule; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/black_temple/black_temple.cpp b/src/bindings/scripts/scripts/zone/black_temple/black_temple.cpp new file mode 100644 index 00000000000..137d87ed8a6 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/black_temple/black_temple.cpp @@ -0,0 +1,68 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Black_Temple +SD%Complete: 95 +SDComment: Spirit of Olum: Player Teleporter to Seer Kanai Teleport after defeating Naj'entus and Supremus. TODO: Find proper gossip. +SDCategory: Black Temple +EndScriptData */ + +/* ContentData +npc_spirit_of_olum +EndContentData */ + +#include "precompiled.h" +#include "def_black_temple.h" + +/*### +# npc_spirit_of_olum +####*/ + +#define SPELL_TELEPORT 41566 // s41566 - Teleport to Ashtongue NPC's +#define GOSSIP_OLUM1 "Teleport me to the other Ashtongue Deathsworn" + +bool GossipHello_npc_spirit_of_olum(Player* player, Creature* _Creature) +{ + ScriptedInstance* pInstance = ((ScriptedInstance*)_Creature->GetInstanceData()); + + if(pInstance && (pInstance->GetData(DATA_SUPREMUSEVENT) >= DONE) && (pInstance->GetData(DATA_HIGHWARLORDNAJENTUSEVENT) >= DONE)) + player->ADD_GOSSIP_ITEM(0, GOSSIP_OLUM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + return true; +} + +bool GossipSelect_npc_spirit_of_olum(Player* player, Creature* _Creature, uint32 sender, uint32 action) +{ + if(action == GOSSIP_ACTION_INFO_DEF + 1) + player->CLOSE_GOSSIP_MENU(); + + player->InterruptNonMeleeSpells(false); + player->CastSpell(player, SPELL_TELEPORT, false); + return true; +} + +void AddSC_black_temple() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_spirit_of_olum"; + newscript->pGossipHello = GossipHello_npc_spirit_of_olum; + newscript->pGossipSelect = GossipSelect_npc_spirit_of_olum; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/black_temple/boss_bloodboil.cpp b/src/bindings/scripts/scripts/zone/black_temple/boss_bloodboil.cpp new file mode 100644 index 00000000000..fba3f7fc36d --- /dev/null +++ b/src/bindings/scripts/scripts/zone/black_temple/boss_bloodboil.cpp @@ -0,0 +1,365 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Bloodboil +SD%Complete: 80 +SDComment: Bloodboil not working correctly, missing enrage +SDCategory: Black Temple +EndScriptData */ + +#include "precompiled.h" +#include "def_black_temple.h" + +//Spells +#define SPELL_ACID_GEYSER 40630 +#define SPELL_ACIDIC_WOUND 40481 +#define SPELL_ARCING_SMASH 40599 +#define SPELL_BLOODBOIL 42005 // This spell is AoE whereas it shouldn't be +#define SPELL_FEL_ACID 40508 +#define SPELL_FEL_RAGE_SELF 40594 +#define SPELL_FEL_RAGE_TARGET 40604 +#define SPELL_FEL_RAGE_2 40616 +#define SPELL_FEL_RAGE_3 41625 +#define SPELL_BEWILDERING_STRIKE 40491 +#define SPELL_EJECT1 40486 // 1000 Physical damage + knockback + script effect (should handle threat reduction I think) +#define SPELL_EJECT2 40597 // 1000 Physical damage + Stun (used in phase 2?) +#define SPELL_TAUNT_GURTOGG 40603 +#define SPELL_INSIGNIFIGANCE 40618 +#define SPELL_BERSERK 45078 + +//Speech'n'Sound +#define SAY_AGGRO "Horde will crush you!" +#define SOUND_AGGRO 11432 + +#define SAY_SLAY1 "Time to feast!" +#define SOUND_SLAY1 11433 + +#define SAY_SLAY2 "More! I want more!" +#define SOUND_SLAY2 11434 + +#define SAY_SPECIAL1 "Drink your blood! Eat your flesh!" +#define SOUND_SPECIAL1 11435 + +#define SAY_SPECIAL2 "I hunger!" +#define SOUND_SPECIAL2 11436 + +#define SAY_ENRAGE "I'll rip the meat from your bones!" +#define SOUND_ENRAGE 11437 + +#define SOUND_DEATH 11439 + +//This is used to sort the players by distance in preparation for the Bloodboil cast. +struct TargetDistanceOrder : public std::binary_function +{ + const Unit* MainTarget; + TargetDistanceOrder(const Unit* Target) : MainTarget(Target) {}; + // functor for operator ">" + bool operator()(const Unit* _Left, const Unit* _Right) const + { + return (MainTarget->GetDistance(_Left) > MainTarget->GetDistance(_Right)); + } +}; + +struct MANGOS_DLL_DECL boss_gurtogg_bloodboilAI : public ScriptedAI +{ + boss_gurtogg_bloodboilAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + + uint64 TargetGUID; + + float TargetThreat; + + uint32 BloodboilTimer; + uint32 BloodboilCount; + uint32 AcidGeyserTimer; + uint32 AcidicWoundTimer; + uint32 ArcingSmashTimer; + uint32 EnrageTimer; + uint32 FelAcidTimer; + uint32 EjectTimer; + uint32 BewilderingStrikeTimer; + uint32 PhaseChangeTimer; + + bool Phase1; + + void Reset() + { + if(pInstance) + pInstance->SetData(DATA_GURTOGGBLOODBOILEVENT, NOT_STARTED); + + TargetGUID = 0; + + TargetThreat = 0; + + BloodboilTimer = 10000; + BloodboilCount = 0; + AcidGeyserTimer = 1000; + AcidicWoundTimer = 6000; + ArcingSmashTimer = 19000; + EnrageTimer = 600000; + FelAcidTimer = 25000; + EjectTimer = 10000; + BewilderingStrikeTimer = 15000; + PhaseChangeTimer = 60000; + + Phase1 = true; + } + + void Aggro(Unit *who) + { + DoZoneInCombat(); + DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO); + if(pInstance) + pInstance->SetData(DATA_GURTOGGBLOODBOILEVENT, IN_PROGRESS); + } + + void KilledUnit(Unit *victim) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_SLAY1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY1); + break; + case 1: + DoYell(SAY_SLAY2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY2); + break; + } + } + + void JustDied(Unit *victim) + { + if(pInstance) + pInstance->SetData(DATA_GURTOGGBLOODBOILEVENT, DONE); + + DoPlaySoundToSet(m_creature,SOUND_DEATH); + } + + // Note: This seems like a very complicated fix. The fix needs to be handled by the core, as implementation of limited-target AoE spells are still not limited. + void CastBloodboil() + { + // Get the Threat List + std::list m_threatlist = m_creature->getThreatManager().getThreatList(); + + if(!m_threatlist.size()) return; // He doesn't have anyone in his threatlist, useless to continue + + std::list targets; + std::list::iterator itr = m_threatlist.begin(); + for( ; itr!= m_threatlist.end(); ++itr) //store the threat list in a different container + { + Unit *target = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid()); + //only on alive players + if(target && target->isAlive() && target->GetTypeId() == TYPEID_PLAYER ) + targets.push_back( target); + } + + //Sort the list of players + targets.sort(TargetDistanceOrder(m_creature)); + //Resize so we only get top 5 + targets.resize(5); + + //Aura each player in the targets list with Bloodboil. Aura code copied+pasted from Aura command in Level3.cpp + /*SpellEntry const *spellInfo = GetSpellStore()->LookupEntry( SPELL_BLOODBOIL ); + if(spellInfo) + { + for(std::list::iterator itr = targets.begin(); itr != targets.end(); ++itr) + { + Unit* target = *itr; + if(!target) return; + for(uint32 i = 0;i<3;i++) + { + uint8 eff = spellInfo->Effect[i]; + if (eff>=TOTAL_SPELL_EFFECTS) + continue; + + Aura *Aur = new Aura(spellInfo, i, NULL, target); + target->AddAura(Aur); + } + } + }*/ + } + + void RevertThreatOnTarget(uint64 guid) + { + Unit* pUnit = NULL; + pUnit = Unit::GetUnit((*m_creature), guid); + if(pUnit) + { + if(m_creature->getThreatManager().getThreat(pUnit)) + m_creature->getThreatManager().modifyThreatPercent(pUnit, -100); + if(TargetThreat) + m_creature->AddThreat(pUnit, TargetThreat); + } + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(ArcingSmashTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_ARCING_SMASH); + ArcingSmashTimer = 10000; + }else ArcingSmashTimer -= diff; + + if(FelAcidTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_FEL_ACID); + FelAcidTimer = 25000; + }else FelAcidTimer -= diff; + + if(!m_creature->HasAura(SPELL_BERSERK, 0)) + if(EnrageTimer < diff) + { + DoCast(m_creature, SPELL_BERSERK); + DoYell(SAY_ENRAGE,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_ENRAGE); + }else EnrageTimer -= diff; + + if(Phase1) + { + if(BewilderingStrikeTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_BEWILDERING_STRIKE); + float mt_threat = m_creature->getThreatManager().getThreat(m_creature->getVictim()); + Unit* target = SelectUnit(SELECT_TARGET_TOPAGGRO, 1); + m_creature->AddThreat(target, mt_threat); + BewilderingStrikeTimer = 20000; + }else BewilderingStrikeTimer -= diff; + + if(EjectTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_EJECT1); + m_creature->getThreatManager().modifyThreatPercent(m_creature->getVictim(), -40); + EjectTimer = 15000; + }else EjectTimer -= diff; + + if(AcidicWoundTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_ACIDIC_WOUND); + AcidicWoundTimer = 10000; + }else AcidicWoundTimer -= diff; + + if(BloodboilTimer < diff) + { + if(BloodboilCount < 5) // Only cast it five times. + { + //CastBloodboil(); // Causes issues on windows, so is commented out. + DoCast(m_creature->getVictim(), SPELL_BLOODBOIL); + ++BloodboilCount; + BloodboilTimer = 10000*BloodboilCount; + } + }else BloodboilTimer -= diff; + } + + if(!Phase1) + { + if(AcidGeyserTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_ACID_GEYSER); + AcidGeyserTimer = 30000; + }else AcidGeyserTimer -= diff; + + if(EjectTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_EJECT2); + EjectTimer = 15000; + }else EjectTimer -= diff; + } + + if(PhaseChangeTimer < diff) + { + if(Phase1) + { + Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target && target->isAlive()) + { + Phase1 = false; + + TargetThreat = m_creature->getThreatManager().getThreat(target); + TargetGUID = target->GetGUID(); + target->CastSpell(m_creature, SPELL_TAUNT_GURTOGG, true); + if(m_creature->getThreatManager().getThreat(target)) + m_creature->getThreatManager().modifyThreatPercent(target, -100); + m_creature->AddThreat(target, 50000000.0f); + // If VMaps are disabled, this spell can call the whole instance + DoCast(m_creature, SPELL_INSIGNIFIGANCE, true); + DoCast(target, SPELL_FEL_RAGE_TARGET, true); + DoCast(target,SPELL_FEL_RAGE_2, true); + /* These spells do not work, comment them out for now. + DoCast(target, SPELL_FEL_RAGE_2, true); + DoCast(target, SPELL_FEL_RAGE_3, true);*/ + + //Cast this without triggered so that it appears in combat logs and shows visual. + DoCast(m_creature, SPELL_FEL_RAGE_SELF); + + switch(rand()%2) + { + case 0: + DoYell(SAY_SPECIAL1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SPECIAL1); + break; + case 1: + DoYell(SAY_SPECIAL2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SPECIAL2); + break; + } + + AcidGeyserTimer = 1000; + PhaseChangeTimer = 30000; + } + }else // Encounter is a loop pretty much. Phase 1 -> Phase 2 -> Phase 1 -> Phase 2 till death or enrage + { + if(TargetGUID) + RevertThreatOnTarget(TargetGUID); + TargetGUID = 0; + Phase1 = true; + BloodboilTimer = 10000; + BloodboilCount = 0; + AcidicWoundTimer += 2000; + ArcingSmashTimer += 2000; + FelAcidTimer += 2000; + EjectTimer += 2000; + PhaseChangeTimer = 60000; + } + }else PhaseChangeTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_gurtogg_bloodboil(Creature *_Creature) +{ + return new boss_gurtogg_bloodboilAI (_Creature); +} + +void AddSC_boss_gurtogg_bloodboil() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_gurtogg_bloodboil"; + newscript->GetAI = GetAI_boss_gurtogg_bloodboil; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/black_temple/boss_illidan.cpp b/src/bindings/scripts/scripts/zone/black_temple/boss_illidan.cpp new file mode 100644 index 00000000000..ecf8ad427be --- /dev/null +++ b/src/bindings/scripts/scripts/zone/black_temple/boss_illidan.cpp @@ -0,0 +1,2465 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: boss_illidan_stormrage +SD%Complete: 90 +SDComment: +SDCategory: Black Temple +EndScriptData */ + +#include "precompiled.h" +#include "def_black_temple.h" +#include "WorldPacket.h" + +/************* Quotes and Sounds ***********************/ +// Gossip for when a player clicks Akama +#define GOSSIP_ITEM "We are ready to face Illidan" + +// Yells for/by Akama +#define SAY_AKAMA_BEWARE "Be wary friends, The Betrayer meditates in the court just beyond." +#define SOUND_AKAMA_BEWARE 11388 +#define SAY_AKAMA_MINION "Come, my minions. Deal with this traitor as he deserves!" +#define SOUND_AKAMA_MINION 11465 +#define SAY_AKAMA_LEAVE "I'll deal with these mongrels. Strike now, friends! Strike at the betrayer!" +#define SOUND_AKAMA_LEAVE 11390 + +// Self explanatory +#define SAY_KILL1 "Who shall be next to taste my blades?!" +#define SOUND_KILL1 11473 +#define SAY_KILL2 "This is too easy!" +#define SOUND_KILL2 11472 + +// I think I'll fly now and let my subordinates take you on +#define SAY_TAKEOFF "I will not be touched by rabble such as you!" +#define SOUND_TAKEOFF 11479 +#define SAY_SUMMONFLAMES "Behold the flames of Azzinoth!" +#define SOUND_SUMMONFLAMES 11480 + +// When casting Eye Blast. Demon Fire will be appear on places that he casts this +#define SAY_EYE_BLAST "Stare into the eyes of the Betrayer!" +#define SOUND_EYE_BLAST 11481 + +// kk, I go big, dark and demon on you. +#define SAY_MORPH "Behold the power... of the demon within!" +#define SOUND_MORPH 11475 + +// I KILL! +#define SAY_ENRAGE "You've wasted too much time mortals, now you shall fall!" +#define SOUND_ENRAGE 11474 + +/************** Spells *************/ +// Normal Form +#define SPELL_SHEAR 41032 // Reduces Max. Health by 60% for 7 seconds. Can stack 19 times. 1.5 second cast +#define SPELL_FLAME_CRASH 40832 // Summons an invis/unselect passive mob that has an aura of flame in a circle around him. +#define SPELL_DRAW_SOUL 40904 // 5k Shadow Damage in front of him. Heals Illidan for 100k health (script effect) +#define SPELL_PARASITIC_SHADOWFIEND 41917 // DoT of 3k Shadow every 2 seconds. Lasts 10 seconds. (Script effect: Summon 2 parasites once the debuff has ticked off) +#define SPELL_SUMMON_PARASITICS 41915 // Summons 2 Parasitic Shadowfiends on the target. It's supposed to be cast as soon as the Parasitic Shadowfiend debuff is gone, but the spells aren't linked :( +#define SPELL_AGONIZING_FLAMES 40932 // 4k fire damage initial to target and anyone w/i 5 yards. PHASE 3 ONLY +#define SPELL_ENRAGE 40683 // Increases damage by 50% and attack speed by 30%. 20 seconds, PHASE 5 ONLY +// Flying (Phase 2) +#define SPELL_THROW_GLAIVE 39635 // Throws a glaive on the ground +#define SPELL_THROW_GLAIVE2 39849 // Animation for the above spell +#define SPELL_GLAIVE_RETURNS 39873 // Glaive flies back to Illidan +#define SPELL_FIREBALL 40598 // 2.5k-3.5k damage in 10 yard radius. 2 second cast time. +#define SPELL_DARK_BARRAGE 40585 // 10 second channeled spell, 3k shadow damage per second. +// Demon Form +#define SPELL_DEMON_TRANSFORM_1 40511 // First phase of animations for transforming into Dark Illidan (fall to ground) +#define SPELL_DEMON_TRANSFORM_2 40398 // Second phase of animations (kneel) +#define SPELL_DEMON_TRANSFORM_3 40510 // Final phase of animations (stand up and roar) +#define SPELL_DEMON_FORM 40506 // Transforms into Demon Illidan. Has an Aura of Dread on him. +#define SPELL_SHADOW_BLAST 41078 // 8k - 11k Shadow Damage. Targets highest threat. Has a splash effect, damaging anyone in 20 yards of the target. +#define SPELL_FLAME_BURST 41126 // Hurls fire at entire raid for ~3.5k damage every 10 seconds. Resistable. (Does not work: Script effect) +#define SPELL_FLAME_BURST_EFFECT 41131 // The actual damage. Handled by core (41126 triggers 41131) +// Other Illidan spells +#define SPELL_KNEEL 39656 // Before beginning encounter, this is how he appears (talking to Wilson). +#define SPELL_SHADOW_PRISON 40647 // Illidan casts this spell to immobilize entire raid when he summons Maiev. +#define SPELL_DEATH 41220 // This spell doesn't do anything except stun Illidan and set him on his knees. +#define SPELL_BERSERK 45078 // Damage increased by 500%, attack speed by 150% + +// Non-Illidan spells +#define SPELL_AKAMA_DOOR_CHANNEL 41268 // Akama's channel spell on the door before the Temple Summit +#define SPELL_DEATHSWORN_DOOR_CHANNEL 41269 // Olum and Udalo's channel spell on the door before the Temple Summit +#define SPELL_AKAMA_DOOR_FAIL 41271 // Not sure where this is really used... +#define SPELL_HEALING_POTION 40535 // Akama uses this to heal himself to full. +#define SPELL_AZZINOTH_CHANNEL 39857 // Glaives cast it on Flames. Not sure if this is the right spell. +#define SPELL_SHADOW_DEMON_PASSIVE 41079 // Adds the "shadowform" aura to Shadow Demons. +#define SPELL_CONSUME_SOUL 41080 // Once the Shadow Demons reach their target, they use this to kill them +#define SPELL_PARALYZE 41083 // Shadow Demons cast this on their target +#define SPELL_PURPLE_BEAM 39123 // Purple Beam connecting Shadow Demon to their target +#define SPELL_CAGE_TRAP_DUMMY 40761 // Put this in DB for cage trap GO. +#define SPELL_EYE_BLAST_TRIGGER 40017 // This summons Demon Form every few seconds and deals ~20k damage in its radius +#define SPELL_EYE_BLAST 39908 // This does the blue flamey animation. +#define SPELL_FLAME_CRASH_EFFECT 40836 // Firey blue ring of circle that the other flame crash summons +#define SPELL_BLAZE_EFFECT 40610 // Green flame on the ground, triggers damage (5k) every few seconds +#define SPELL_BLAZE_SUMMON 40637 // Summons the Blaze creature +#define SPELL_DEMON_FIRE 40029 // Blue fire trail left by Eye Blast. Deals 2k per second if players stand on it. +#define SPELL_CAGED 40695 // Caged Trap triggers will cast this on Illidan if he is within 3 yards +#define SPELL_CAGE_TRAP_SUMMON 40694 // Summons a Cage Trap GO (bugged) on the ground along with a Cage Trap Disturb Trigger mob (working) +#define SPELL_CAGE_TRAP_BEAM 40713 // 8 Triggers on the ground in an octagon cast spells like this on Illidan 'caging him' +#define SPELL_FLAME_BLAST 40631 // Flames of Azzinoth use this. Frontal cone AoE 7k-9k damage. +#define SPELL_CHARGE 40602 // Flames of Azzinoth charges whoever is too far from them. They enrage after this. For simplicity, we'll use the same enrage as Illidan. +#define SPELL_TELEPORT_VISUAL 41232 // Teleport visual for Maiev +#define SPELL_SHADOWFIEND_PASSIVE 41913 // Passive aura for shadowfiends + +// Other defines +#define CENTER_X 676.740 +#define CENTER_Y 305.297 +#define CENTER_Z 353.192 + +/**** Creature Summon and Recognition IDs ****/ +enum CreatureEntry +{ + EMPTY = 0, + AKAMA = 22990, + ILLIDAN_STORMRAGE = 22917, + BLADE_OF_AZZINOTH = 22996, + FLAME_OF_AZZINOTH = 22997, + MAIEV_SHADOWSONG = 23197, + SHADOW_DEMON = 23375, + DEMON_FIRE = 23069, + FLAME_CRASH = 23336, + ILLIDAN_DOOR_TRIGGER = 23412, + SPIRIT_OF_OLUM = 23411, + SPIRIT_OF_UDALO = 23410, + ILLIDARI_ELITE = 23226, + PARASITIC_SHADOWFIEND = 23498, + CAGE_TRAP_TRIGGER = 23292, +}; + +/*** Phase Names ***/ +enum Phase +{ + PHASE_NORMAL = 1, + PHASE_FLIGHT = 2, + PHASE_NORMAL_2 = 3, + PHASE_DEMON = 4, + PHASE_NORMAL_MAIEV = 5, + PHASE_DEMON_SEQUENCE = 6, +}; + +struct Yells +{ + uint32 sound; + char* text; + uint32 creature, timer, emote; + bool Talk; +}; + +static Yells Conversation[]= +{ + {11463, "Akama... your duplicity is hardly surprising. I should have slaughtered you and your malformed brethren long ago.", ILLIDAN_STORMRAGE, 8000, 0, true}, + {0, NULL, ILLIDAN_STORMRAGE, 5000, 396, true}, + {11389, "We've come to end your reign, Illidan. My people and all of Outland shall be free!", AKAMA, 7000, 25, true}, + {0, NULL, AKAMA, 5000, 66, true}, + {11464, "Boldly said. But I remain unconvinced.", ILLIDAN_STORMRAGE, 8000, 396, true}, + {11380, "The time has come! The moment is at hand!", AKAMA, 3000, 22, true}, + {0, NULL, AKAMA, 2000, 15, true}, + {11466, "You are not prepared!", ILLIDAN_STORMRAGE, 3000, 406, true}, + {0, NULL, EMPTY, 1000, 0, true}, + {0, NULL, EMPTY, 0, 0, false}, + {11476, "Is this it, mortals? Is this all the fury you can muster?", ILLIDAN_STORMRAGE, 8000, 0, true}, + {11491, "Their fury pales before mine, Illidan. We have some unsettled business between us.", MAIEV_SHADOWSONG, 8000, 5, true}, + {11477, "Maiev... How is this even possible?", ILLIDAN_STORMRAGE, 7000, 1, true}, + {11492, "Ah... my long hunt is finally over. Today, Justice will be done!", MAIEV_SHADOWSONG, 8000, 15, true}, + {11470, "Feel the hatred of ten thousand years!", ILLIDAN_STORMRAGE, 1000, 0, false}, + {11496, "Ahh... It is finished. You are beaten.", MAIEV_SHADOWSONG, 6000, 0, true}, + { // Emote dead for now. Kill him later + 11478, "You have won... Maiev...but the huntress... is nothing...without the hunt... you... are nothing... without me..", ILLIDAN_STORMRAGE, 22000, 65, true + }, + {11497, "He is right. I feel nothing... I am nothing... Farewell, champions.", MAIEV_SHADOWSONG, 9000, 0, true}, + {11498, NULL, MAIEV_SHADOWSONG, 0, true}, + {11387, "The Light will fill these dismal halls once again. I swear it.", AKAMA, 8000, 0, true}, + {0, NULL, EMPTY, 1000, 0, false} +}; + +static Yells RandomTaunts[]= +{ + {11467, "I can feel your hatred.", ILLIDAN_STORMRAGE, 0, 0, false}, + {11468, "Give in to your fear!", ILLIDAN_STORMRAGE, 0, 0, false}, + {11469, "You know nothing of power!", ILLIDAN_STORMRAGE, 0, 0, false}, + {11471, "Such... arrogance!", ILLIDAN_STORMRAGE, 0, 0, false} +}; + +static Yells MaievTaunts[]= +{ + {11493, "That is for Naisha!", MAIEV_SHADOWSONG, 0, false}, + {11494, "Bleed as I have bled!", MAIEV_SHADOWSONG, 0, 0, false}, + {11495, "There shall be no prison for you this time!", MAIEV_SHADOWSONG, 0, 0, false}, + {11500, "Meet your end, demon!", MAIEV_SHADOWSONG, 0, 0, false} +}; + +struct Locations +{ + float x, y, z; + uint32 id; +}; + +static Locations GlaivePosition[]= +{ + {695.105, 305.303, 354.256}, + {659.338, 305.303, 354.256}, + {700.105, 305.303, 354.256}, + {664.338, 305.303, 354.256} +}; + +static Locations EyeBlast[]= +{ + {650.697, 320.128, 353.730}, + {652.799, 275.091, 353.367}, + {701.527, 273.815, 353.230}, + {709.865, 325.654, 353.322} +}; + +static Locations AkamaWP[]= +{ + { 770.01, 304.50, 312.29 }, // Bottom of the first stairs, at the doors + { 780.66, 304.50, 319.74 }, // Top of the first stairs + { 790.13, 319.68, 319.76 }, // Bottom of the second stairs (left from the entrance) + { 787.17, 347.38, 341.42 }, // Top of the second stairs + { 781.34, 350.31, 341.44 }, // Bottom of the third stairs + { 762.60, 361.06, 353.60 }, // Top of the third stairs + { 756.35, 360.52, 353.27 }, // Before the door-thingy + { 743.82, 342.21, 353.00 }, // Somewhere further + { 732.69, 305.13, 353.00 }, // In front of Illidan + { 738.11, 365.44, 353.00 }, // in front of the door-thingy (the other one!) + { 792.18, 366.62, 341.42 }, // Down the first flight of stairs + { 796.84, 304.89, 319.76 }, // Down the second flight of stairs + { 782.01, 304.55, 319.76 } // Final location - back at the initial gates. This is where he will fight the minions! +}; +// 755.762, 304.0747, 312.1769 -- This is where Akama should be spawned +static Locations SpiritSpawns[]= +{ + {755.5426, 309.9156, 312.2129, SPIRIT_OF_UDALO}, + {755.5426, 298.7923, 312.0834, SPIRIT_OF_OLUM} +}; + +struct WayPoints +{ + WayPoints(uint32 _id, float _x, float _y, float _z) + { + id = _id; + x = _x; + y = _y; + z = _z; + } + uint32 id; + float x, y, z; +}; + +struct Animation // For the demon transformation +{ + uint32 aura, unaura, timer, size, displayid, phase; + bool equip; +}; + +static Animation DemonTransformation[]= +{ + {SPELL_DEMON_TRANSFORM_1, 0, 1300, 0, 0, 6, true}, + {SPELL_DEMON_TRANSFORM_2, SPELL_DEMON_TRANSFORM_1, 4000, 0, 0, 6, true}, + {SPELL_DEMON_FORM, 0, 3000, 1073741824, 21322, 6, false}, + {SPELL_DEMON_TRANSFORM_3, SPELL_DEMON_TRANSFORM_2, 3500, 0, 0, 6, false}, + {0, 0, 0, 0, 0, 4, false}, + {SPELL_DEMON_TRANSFORM_1, 0, 1500, 0, 0, 6, false}, + {SPELL_DEMON_TRANSFORM_2, SPELL_DEMON_TRANSFORM_1, 4000, 0, 0, 6, false}, + {0, SPELL_DEMON_FORM, 3000, 1069547520, 21135, 6, false}, + {SPELL_DEMON_TRANSFORM_3, SPELL_DEMON_TRANSFORM_2, 3500, 0, 0, 6, true}, + {0, 0, 0, 0, 0, 8, true} +}; + +/**** Demon Fire will be used for Eye Blast. Illidan needs to have access to it's vars and functions, so we'll set it here ****/ +struct MANGOS_DLL_DECL demonfireAI : public ScriptedAI +{ + demonfireAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + + uint64 IllidanGUID; + + bool IsTrigger; + + uint32 CheckTimer; + uint32 DemonFireTimer; + uint32 DespawnTimer; + + void Reset() + { + IllidanGUID = 0; + + IsTrigger = false; + + CheckTimer = 2000; + DemonFireTimer = 0; + DespawnTimer = 45000; + } + + void Aggro(Unit *who) {} + void AttackStart(Unit* who) { } + void MoveInLineOfSight(Unit *who){ } + + void UpdateAI(const uint32 diff) + { + if(IsTrigger) + return; + + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + if(CheckTimer < diff) + { + if(!IllidanGUID && pInstance) + { + IllidanGUID = pInstance->GetData64(DATA_ILLIDANSTORMRAGE); + if(IllidanGUID) + { + Unit* Illidan = Unit::GetUnit((*m_creature), IllidanGUID); + if(Illidan && !Illidan->HasUnitMovementFlag(MOVEMENTFLAG_LEVITATING)) + m_creature->setDeathState(JUST_DIED); + } + } + CheckTimer = 2000; + }else CheckTimer -= diff; + + if(DemonFireTimer < diff) + { + DoCast(m_creature, SPELL_DEMON_FIRE); + DemonFireTimer = 30000; + }else DemonFireTimer -= diff; + + if(DespawnTimer < diff) + m_creature->setDeathState(JUST_DIED); + else DespawnTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +/******* Functions and vars for Akama's AI ******/ +struct MANGOS_DLL_SPEC npc_akama_illidanAI : public ScriptedAI +{ + npc_akama_illidanAI(Creature* c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + WayPointList.clear(); + Reset(); + } + + /* Instance Data */ + ScriptedInstance* pInstance; + + /* Timers */ + uint32 ChannelTimer; + uint32 TalkTimer; + uint32 WalkTimer; + uint32 SummonMinionTimer; + + /* GUIDs */ + uint64 IllidanGUID; + uint64 PlayerGUID; + uint64 SpiritGUID[2]; + uint64 ChannelGUID; + + bool IsTalking; + bool StartChanneling; + bool DoorOpen; + bool FightMinions; + bool IsReturningToIllidan; + bool IsWalking; + uint32 TalkCount; + uint32 ChannelCount; + + std::list WayPointList; + std::list::iterator WayPoint; + + void BeginEvent(uint64 PlayerGUID); + void Aggro(Unit *who) {} + + void Reset() + { + if(pInstance) + { + pInstance->SetData(DATA_ILLIDANSTORMRAGEEVENT, NOT_STARTED); + GameObject* Gate = GameObject::GetGameObject((*m_creature), pInstance->GetData64(DATA_GAMEOBJECT_ILLIDAN_GATE)); + if( Gate && !Gate->GetGoState() ) + Gate->SetGoState(1); // close door if already open (when raid wipes or something) + + for(uint8 i = DATA_GAMEOBJECT_ILLIDAN_DOOR_R; i < DATA_GAMEOBJECT_ILLIDAN_DOOR_L + 1; ++i) + { + GameObject* Door = GameObject::GetGameObject((*m_creature), pInstance->GetData64(i)); + if(Door) + Door->SetGoState(0); + } + } + + IllidanGUID = 0; + PlayerGUID = 0; + ChannelGUID = 0; + for(uint8 i = 0; i < 2; ++i) SpiritGUID[i] = 0; + + ChannelTimer = 0; + ChannelCount = 0; + SummonMinionTimer = 2000; + + WalkTimer = 0; + + TalkTimer = 0; + TalkCount = 0; + + KillAllElites(); + + IsReturningToIllidan = false; + FightMinions = false; + IsTalking = false; + StartChanneling = false; + DoorOpen = false; + + m_creature->SetUInt32Value(UNIT_NPC_FLAGS, 0); // Database sometimes has strange values.. + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetVisibility(VISIBILITY_ON); + } + + // Do not call reset in Akama's evade mode, as this will stop him from summoning minions after he kills the first bit + void EnterEvadeMode() + { + InCombat = false; + + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); + m_creature->CombatStop(); + } + + void KillAllElites() + { + std::list::iterator itr; + for(itr = m_creature->getThreatManager().getThreatList().begin(); itr != m_creature->getThreatManager().getThreatList().end(); ++itr) + { + Unit* pUnit = Unit::GetUnit((*m_creature), (*itr)->getUnitGuid()); + if(pUnit && (pUnit->GetTypeId() == TYPEID_UNIT) && (pUnit->GetEntry() == ILLIDARI_ELITE)) + pUnit->setDeathState(JUST_DIED); + } + } + + void ReturnToIllidan() + { + KillAllElites(); + InCombat = false; + FightMinions = false; + IsReturningToIllidan = true; + WayPoint = WayPointList.begin(); + m_creature->SetSpeed(MOVE_RUN, 2.0f); + m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + IsWalking = true; + } + + void AddWaypoint(uint32 id, float x, float y, float z) + { + WayPoints AkamaWP(id, x, y, z); + WayPointList.push_back(AkamaWP); + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if(damage > m_creature->GetHealth() && (done_by->GetGUID() != m_creature->GetGUID())) + { + damage = 0; + DoCast(m_creature, SPELL_HEALING_POTION); + } + } + + void BeginDoorEvent(Player* player) + { + if(!pInstance) + return; + + outstring_log("SD2: Akama - Door event initiated by player %s", player->GetName()); + PlayerGUID = player->GetGUID(); + + GameObject* Gate = GameObject::GetGameObject((*m_creature), pInstance->GetData64(DATA_GAMEOBJECT_ILLIDAN_GATE)); + if(Gate) + { + float x,y,z; + Gate->GetPosition(x, y, z); + Creature* Channel = m_creature->SummonCreature(ILLIDAN_DOOR_TRIGGER, x, y, z+5, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 360000); + if(Channel) + { + ChannelGUID = Channel->GetGUID(); + // Invisible but spell visuals can still be seen. + Channel->SetUInt32Value(UNIT_FIELD_DISPLAYID, 11686); + Channel->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + float PosX, PosY, PosZ; + m_creature->GetPosition(PosX, PosY, PosZ); + for(uint8 i = 0; i < 2; ++i) + { + Creature* Spirit = m_creature->SummonCreature(SpiritSpawns[i].id, SpiritSpawns[i].x, SpiritSpawns[i].y, SpiritSpawns[i].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 360000); + if(Spirit) + { + Spirit->SetVisibility(VISIBILITY_OFF); + SpiritGUID[i] = Spirit->GetGUID(); + } + } + StartChanneling = true; + m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + DoCast(Channel, SPELL_AKAMA_DOOR_FAIL); + } + } + } + + void MovementInform(uint32 type, uint32 id) + { + if(type != POINT_MOTION_TYPE || !IsWalking) + return; + + if(WayPoint->id != id) + return; + + switch(id) + { + case 6: + if(!IsReturningToIllidan) + { // open the doors that close the summit + for(uint32 i = DATA_GAMEOBJECT_ILLIDAN_DOOR_R; i < DATA_GAMEOBJECT_ILLIDAN_DOOR_L+1; ++i) + { + GameObject* Door = GameObject::GetGameObject((*m_creature), pInstance->GetData64(i)); + if(Door) + Door->SetGoState(0); + } + } + case 7: + if(IsReturningToIllidan) + { + IsWalking = false; + if(IllidanGUID) + { + Unit* Illidan = Unit::GetUnit((*m_creature), IllidanGUID); + if(Illidan) + { + float dx = Illidan->GetPositionX() + rand()%15; + float dy = Illidan->GetPositionY() + rand()%15; + m_creature->GetMotionMaster()->MovePoint(13, dx, dy, Illidan->GetPositionZ()); + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, IllidanGUID); + } + } + } + break; + case 8: + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if(!IsReturningToIllidan) + { + IsWalking = false; + BeginEvent(PlayerGUID); + } + break; + case 12: + IsWalking = false; + FightMinions = true; + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + break; + } + + ++WayPoint; + WalkTimer = 200; + } + + void DeleteFromThreatList() + { + if(!IllidanGUID) return; // If we do not have Illidan's GUID, do not proceed + // Create a pointer to Illidan + Creature* Illidan = ((Creature*)Unit::GetUnit((*m_creature), IllidanGUID)); + if(!Illidan) return; // No use to continue if Illidan does not exist + std::list::iterator itr = Illidan->getThreatManager().getThreatList().begin(); + for( ; itr != Illidan->getThreatManager().getThreatList().end(); ++itr) + { + // Loop through threatlist till our GUID is found in it. + if((*itr)->getUnitGuid() == m_creature->GetGUID()) + { + (*itr)->removeReference(); // Delete ourself from his threatlist. + return; // No need to continue anymore. + } + } + + // Now we delete our threatlist to prevent attacking anyone for now + m_creature->DeleteThreatList(); + } + + void UpdateAI(const uint32 diff) + { + if(IllidanGUID) + { + Creature* Illidan = ((Creature*)Unit::GetUnit((*m_creature), IllidanGUID)); + if(Illidan) + { + if(Illidan->IsInEvadeMode() && !m_creature->IsInEvadeMode()) + EnterEvadeMode(); + + if(((Illidan->GetHealth()*100 / Illidan->GetMaxHealth()) < 85) && InCombat && !FightMinions) + { + if(TalkTimer < diff) + { + switch(TalkCount) + { + case 0: + Illidan->Yell(SAY_AKAMA_MINION, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(Illidan, SOUND_AKAMA_MINION); + TalkTimer = 8000; + TalkCount = 1; + break; + case 1: + DoYell(SAY_AKAMA_LEAVE, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AKAMA_LEAVE); + TalkTimer = 3000; + TalkCount = 2; + break; + case 2: + IsTalking = true; + TalkTimer = 2000; + m_creature->RemoveAllAuras(); + m_creature->CombatStop(); + m_creature->AttackStop(); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + TalkCount = 3; + break; + case 3: + DeleteFromThreatList(); + IsWalking = true; + WayPoint = WayPointList.begin(); + std::advance(WayPoint, 9); + m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + break; + } + }else TalkTimer -= diff; + } + + if(((Illidan->GetHealth()*100 / Illidan->GetMaxHealth()) < 4) && !IsReturningToIllidan) + ReturnToIllidan(); + } + }else + { + if(pInstance) + IllidanGUID = pInstance->GetData64(DATA_ILLIDANSTORMRAGE); + } + + if(IsWalking && WalkTimer) + { + if(WalkTimer <= diff) + { + if(WayPoint == WayPointList.end()) + return; + m_creature->GetMotionMaster()->MovePoint(WayPoint->id, WayPoint->x, WayPoint->y,WayPoint->z); + WalkTimer = 0; + }else WalkTimer -= diff; + } + + if(StartChanneling) + { + if(ChannelTimer < diff) + { + switch(ChannelCount) + { + case 3: + if(!DoorOpen) + { + m_creature->InterruptNonMeleeSpells(true); + for(uint8 i = 0; i < 2; ++i) + { + if(SpiritGUID[i]) + { + Unit* Spirit = Unit::GetUnit((*m_creature), SpiritGUID[i]); + if(Spirit) + Spirit->InterruptNonMeleeSpells(true); + } + } + GameObject* Gate = GameObject::GetGameObject((*m_creature), pInstance->GetData64(DATA_GAMEOBJECT_ILLIDAN_GATE)); + if(Gate) + Gate->SetGoState(0); + ChannelCount++; + ChannelTimer = 5000; + } + break; + case 4: + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE); + ChannelTimer = 2000; + ChannelCount++; + break; + case 5: + DoYell(SAY_AKAMA_BEWARE, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AKAMA_BEWARE); + if(ChannelGUID) + { + Unit* ChannelTarget = Unit::GetUnit((*m_creature), ChannelGUID); + if(ChannelTarget) + ChannelTarget->setDeathState(JUST_DIED); + } + for(uint8 i = 0; i < 2; ++i) + { + if(SpiritGUID[i]) + { + Unit* Spirit = Unit::GetUnit((*m_creature), SpiritGUID[i]); + if(Spirit) + Spirit->setDeathState(JUST_DIED); + } + } + ChannelTimer = 6000; + ChannelCount++; + break; + case 6: + StartChanneling = false; + if(WayPointList.empty()) + { + error_log("SD2: Akama has no waypoints to start with!"); + return; + } + + WayPoint = WayPointList.begin(); + m_creature->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + m_creature->GetMotionMaster()->MovePoint(WayPoint->id, WayPoint->x, WayPoint->y, WayPoint->z); + IsWalking = true; + break; + default: + if(ChannelGUID) + { + Unit* Channel = Unit::GetUnit((*m_creature), ChannelGUID); + if(Channel) + { + m_creature->InterruptNonMeleeSpells(true); + + for(uint8 i = 0; i < 2; ++i) + { + if(SpiritGUID[i]) + { + Unit* Spirit = Unit::GetUnit((*m_creature), SpiritGUID[i]); + if(Spirit) + { + Spirit->InterruptNonMeleeSpells(true); + if(ChannelCount%2 == 0) + { + Spirit->CastSpell(Channel, SPELL_DEATHSWORN_DOOR_CHANNEL,false); + DoCast(Channel, SPELL_AKAMA_DOOR_CHANNEL); + } + else + { + if(Spirit->GetVisibility() == VISIBILITY_OFF) + Spirit->SetVisibility(VISIBILITY_ON); + } + } + } + } + if(ChannelCount < 3) + ChannelCount++; + ChannelTimer = 10000; + } + break; + } + } + }else ChannelTimer -= diff; + } + + if(FightMinions) + { + if(SummonMinionTimer < diff) + { + if(IllidanGUID) + { + Creature* Illidan = ((Creature*)Unit::GetUnit((*m_creature), IllidanGUID)); + if(!Illidan || Illidan->IsInEvadeMode()) + { + Reset(); + EnterEvadeMode(); + return; + } + } + + float x,y,z; + m_creature->GetPosition(x,y,z); + Creature* Elite = m_creature->SummonCreature(ILLIDARI_ELITE, x+rand()%10, y+rand()%10, z, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 30000); + if(Elite) + { + Elite->AI()->AttackStart(m_creature); + Elite->AddThreat(m_creature, 1000000.0f); + AttackStart(Elite); + } + SummonMinionTimer = 10000 + rand()%6000; + }else SummonMinionTimer -= diff; + } + + // If we don't have a target, or is talking, or has run away, return + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) return; + + DoMeleeAttackIfReady(); + } +}; + +/************* Custom check used for Agonizing Flames ***************/ +class AgonizingFlamesTargetCheck +{ + public: + AgonizingFlamesTargetCheck(Unit const* unit) : pUnit(unit) {} + bool operator() (Player* plr) + { + // Faster than square rooting + if(!plr->isGameMaster() && pUnit->GetDistance2d(plr) > 225) + return true; + + return false; + } + + private: + Unit const* pUnit; +}; + +/************************************** Illidan's AI ***************************************/ +struct MANGOS_DLL_SPEC boss_illidan_stormrageAI : public ScriptedAI +{ + boss_illidan_stormrageAI(Creature* c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + /** Instance Data **/ + ScriptedInstance* pInstance; + + /** Generic **/ + bool IsTalking; + bool HasSummoned; + bool RefaceVictim; + bool InformAkama; + uint32 Phase; + uint32 GlobalTimer; + uint32 TalkCount; + uint32 DemonFormSequence; + + /** GUIDs **/ + uint64 FlameGUID[2]; + uint64 GlaiveGUID[2]; + uint64 AkamaGUID; + uint64 MaievGUID; + + /** Timers **/ + uint32 ShearTimer; + uint32 DrawSoulTimer; + uint32 FlameCrashTimer; + uint32 ParasiticShadowFiendTimer; + uint32 FireballTimer; + uint32 EyeBlastTimer; + uint32 DarkBarrageTimer; + uint32 SummonBladesTimer; // Animate summoning the Blades of Azzinoth in Phase 2 + uint32 SummonFlamesTimer; // Summon Flames of Azzinoth in Phase 2 + uint32 CheckFlamesTimer; // This is used to check the status of the Flames to see if we should begin entering Phase 3 or not. + uint32 RetrieveBladesTimer; // Animate retrieving the Blades of Azzinoth in Phase 2 -> 3 transition + uint32 LandTimer; // This is used at the end of phase 2 to signal Illidan landing after Flames are dead + uint32 AgonizingFlamesTimer; + uint32 ShadowBlastTimer; + uint32 FlameBurstTimer; + uint32 ShadowDemonTimer; + uint32 TalkTimer; + uint32 TransformTimer; + uint32 EnrageTimer; + uint32 CageTimer; + uint32 LayTrapTimer; + uint32 AnimationTimer; + uint32 TauntTimer; // This is used for his random yells + uint32 FaceVictimTimer; + uint32 BerserkTimer; + + void Reset() + { + Phase = PHASE_NORMAL; + + // Check if any flames/glaives are alive/existing. Kill if alive and set GUIDs to 0 + for(uint8 i = 0; i < 2; i++) + { + if(FlameGUID[i]) + { + Unit* Flame = Unit::GetUnit((*m_creature), FlameGUID[i]); + if(Flame) + Flame->setDeathState(JUST_DIED); + FlameGUID[i] = 0; + } + + if(GlaiveGUID[i]) + { + Unit* Glaive = Unit::GetUnit((*m_creature), GlaiveGUID[i]); + if(Glaive) + Glaive->setDeathState(JUST_DIED); + GlaiveGUID[i] = 0; + } + } + + if(AkamaGUID) + { + Creature* Akama = ((Creature*)Unit::GetUnit((*m_creature), AkamaGUID)); + if(Akama) + { + if(!Akama->isAlive()) + Akama->Respawn(); + ((npc_akama_illidanAI*)Akama->AI())->Reset(); + ((npc_akama_illidanAI*)Akama->AI())->EnterEvadeMode(); + Akama->GetMotionMaster()->MoveTargetedHome(); + } + } + + InformAkama = false; + RefaceVictim = false; + HasSummoned = false; + AkamaGUID = 0; + MaievGUID = 0; + + FaceVictimTimer = 1000; + BerserkTimer = 1500000; + GlobalTimer = 0; + DemonFormSequence = 0; + + /** Normal Form **/ + ShearTimer = 20000 + (rand()%11 * 1000); // 20 to 30 seconds + FlameCrashTimer = 30000; //30 seconds + ParasiticShadowFiendTimer = 25000; // 25 seconds + DrawSoulTimer = 50000; // 50 seconds + + /** Phase 2 **/ + SummonBladesTimer = 10000; + SummonFlamesTimer = 20000; // Phase 2 timers may be incorrect + FireballTimer = 5000; + DarkBarrageTimer = 45000; + EyeBlastTimer = 30000; + CheckFlamesTimer = 5000; + RetrieveBladesTimer = 5000; + LandTimer = 0; + + /** Phase 3+ **/ + AgonizingFlamesTimer = 35000; // Phase 3+ timers may be incorrect + ShadowBlastTimer = 3000; + FlameBurstTimer = 10000; + ShadowDemonTimer = 30000; + TransformTimer = 90000; + EnrageTimer = 40000; + CageTimer = 30000; + LayTrapTimer = CageTimer + 2000; + AnimationTimer = 0; + + TauntTimer = 30000; // This timer may be off. + + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, 21135); + m_creature->InterruptNonMeleeSpells(false); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + // Unequip warglaives if needed + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 0); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 0); + m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + + IsTalking = false; + + TalkCount = 0; + TalkTimer = 0; + + if(pInstance) + pInstance->SetData(DATA_ILLIDANSTORMRAGEEVENT, NOT_STARTED); + } + + void Aggro(Unit *who) { DoZoneInCombat(); } + + void AttackStart(Unit *who) + { + if(!who || IsTalking || Phase == 2 || Phase == 4 || Phase == 6 || m_creature->HasAura(SPELL_KNEEL, 0)) + return; + + if (who->isTargetableForAttack() && who!= m_creature) + { + //Begin melee attack if we are within range + DoStartAttackAndMovement(who); + } + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || m_creature->getVictim() || IsTalking || m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + float attackRadius = m_creature->GetAttackDistance(who); + if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) + { + if(who->HasStealthAura()) + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + DoStartAttackAndMovement(who); + } + } + } + + void JustDied(Unit *killer) + { + IsTalking = false; + TalkCount = 0; + TalkTimer = 0; + + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + if(!pInstance) + return; + // Completed + pInstance->SetData(DATA_ILLIDANSTORMRAGEEVENT, DONE); + + for(uint8 i = DATA_GAMEOBJECT_ILLIDAN_DOOR_R; i < DATA_GAMEOBJECT_ILLIDAN_DOOR_L + 1; ++i) + { + GameObject* Door = GameObject::GetGameObject((*m_creature), pInstance->GetData64(i)); + if(Door) + Door->SetGoState(0); // Open Doors + } + + } + + void KilledUnit(Unit *victim) + { + if(victim == m_creature) return; + + switch(rand()%2) + { + case 0: + DoYell(SAY_KILL1, LANG_UNIVERSAL, victim); + DoPlaySoundToSet(m_creature, SOUND_KILL1); + break; + case 1: + DoYell(SAY_KILL2, LANG_UNIVERSAL, victim); + DoPlaySoundToSet(m_creature, SOUND_KILL2); + break; + } + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if(damage > m_creature->GetHealth()) // Don't let ourselves be slain before we do our death speech + { + damage = 0; + m_creature->SetHealth(m_creature->GetMaxHealth()/100); + } + } + + void Cast(Unit* victim, uint32 Spell, bool triggered = false) + { + if(!victim) + return; + + RefaceVictim = true; + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, victim->GetGUID()); + m_creature->CastSpell(victim, Spell, triggered); + } + + /** This will handle the cast of eye blast **/ + void CastEyeBlast() + { + m_creature->InterruptNonMeleeSpells(false); + + DarkBarrageTimer += 10000; + + DoYell(SAY_EYE_BLAST, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_EYE_BLAST); + + uint32 initial = rand()%4; + uint32 final = 0; + if(initial < 3) + final = initial+1; + + float initial_X = EyeBlast[initial].x; + float initial_Y = EyeBlast[initial].y; + float initial_Z = EyeBlast[initial].z; + + float final_X = EyeBlast[final].x; + float final_Y = EyeBlast[final].y; + float final_Z = EyeBlast[final].z; + + for(uint8 i = 0; i < 2; ++i) + { + Creature* Trigger = NULL; + Trigger = m_creature->SummonCreature(DEMON_FIRE, initial_X, initial_Y, initial_Z, 0, TEMPSUMMON_TIMED_DESPAWN, 20000); + if(Trigger) + { + ((demonfireAI*)Trigger->AI())->IsTrigger = true; + Trigger->GetMotionMaster()->MovePoint(0, final_X, final_Y, final_Z); + + if(!i) + Trigger->CastSpell(Trigger, SPELL_EYE_BLAST_TRIGGER, true); + else + { + Trigger->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, Trigger->GetGUID()); + DoCast(Trigger, SPELL_EYE_BLAST); + } + } + } + } + + // It's only cast on players that are greater than 15 yards away from Illidan. If no one is found, cast it on MT instead (since selecting someone in that 15 yard radius would cause the flames to hit the MT anyway). + void CastAgonizingFlames() + { + // We'll use grid searching for this, using a custom searcher that selects a player that is at a distance >15 yards + Player* target = NULL; + + CellPair pair(MaNGOS::ComputeCellPair(m_creature->GetPositionX(), m_creature->GetPositionY())); + Cell cell(pair); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + AgonizingFlamesTargetCheck check(m_creature); + MaNGOS::PlayerSearcher searcher(target, check); + TypeContainerVisitor + , GridTypeMapContainer> visitor(searcher); + + CellLock cell_lock(cell, pair); + cell_lock->Visit(cell_lock, visitor, *(m_creature->GetMap())); + + if(target) + DoCast(target, SPELL_AGONIZING_FLAMES); + else + DoCast(m_creature->getVictim(), SPELL_AGONIZING_FLAMES); + } + + void Talk(uint32 count) + { + if(!m_creature->isAlive()) return; + uint32 sound = Conversation[count].sound; + char* text = NULL; + if(Conversation[count].text) + text = Conversation[count].text; + TalkTimer = Conversation[count].timer; + uint32 emote = Conversation[count].emote; + IsTalking = Conversation[count].Talk; + Creature* creature = NULL; + uint64 GUID = 0; + if(Conversation[count].creature == ILLIDAN_STORMRAGE) + creature = m_creature; + else if(Conversation[count].creature == AKAMA) + { + if(!AkamaGUID) + { + if(pInstance) + { + AkamaGUID = pInstance->GetData64(DATA_AKAMA); + if(!AkamaGUID) + return; + GUID = AkamaGUID; + } + } + else GUID = AkamaGUID; + } + else if(Conversation[count].creature == MAIEV_SHADOWSONG) + { + if(!MaievGUID) + return; + GUID = MaievGUID; + } + else if(Conversation[count].creature == EMPTY) // This is just for special cases without speech/sounds/emotes. + return; + + if(GUID) // Now we check if we actually specified a GUID, if so: + // we grab a pointer to that creature + creature = ((Creature*)Unit::GetUnit((*m_creature), GUID)); + + if(creature) + { + creature->HandleEmoteCommand(emote); // Make the creature do some animation! + if(text) + creature->Yell(text, LANG_UNIVERSAL, 0); // Have the creature yell out some text + if(sound) + DoPlaySoundToSet(creature, sound); // Play some sound on the creature + } + } + + void Move(float X, float Y, float Z, Creature* _Creature) + { + _Creature->GetMotionMaster()->MovePoint(0, X, Y, Z); + } + + void HandleDemonTransformAnimation(uint32 count) + { + uint32 unaura = DemonTransformation[count].unaura; + uint32 aura = DemonTransformation[count].aura; + uint32 displayid = DemonTransformation[count].displayid; + AnimationTimer = DemonTransformation[count].timer; + uint32 size = DemonTransformation[count].size; + + m_creature->InterruptNonMeleeSpells(false); + + if(DemonTransformation[count].phase != 8) + { + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MoveIdle(); + } + + if(unaura) + m_creature->RemoveAurasDueToSpell(unaura); + + if(aura) + DoCast(m_creature, aura, true); + + if(displayid) + // It's morphin time! + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, displayid); + /*if(size) + m_creature->SetUInt32Value(OBJECT_FIELD_SCALE_X, size); // Let us grow! (or shrink)*/ + + if(DemonTransformation[count].equip) + { + // Requip warglaives if needed + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 45479); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 45481); + } + else + { + // Unequip warglaives if needed + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 0); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 0); + } + + if(DemonTransformation[count].phase != 8) + Phase = DemonTransformation[count].phase; // Set phase properly + else + { + // Refollow and attack our old victim + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + if(MaievGUID) Phase = PHASE_NORMAL_MAIEV; // Depending on whether we summoned Maiev, we switch to either phase 5 or 3 + else Phase = PHASE_NORMAL_2; + } + + if(count == 7) + { + DoResetThreat(); + m_creature->RemoveAurasDueToSpell( SPELL_DEMON_FORM ); + } + else if(count == 4) + { + DoResetThreat(); + if(!m_creature->HasAura(SPELL_DEMON_FORM, 0)) + DoCast(m_creature, SPELL_DEMON_FORM, true); + } + } + + /** To reduce the amount of code in UpdateAI, we can seperate them into different functions and simply call them from UpdateAI **/ + void EnterPhase2() + { + DoYell(SAY_TAKEOFF, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_TAKEOFF); + + SummonBladesTimer = 10000; // Summon Glaives when this decrements + SummonFlamesTimer = 20000; // Summon Flames when this decrements + GlobalTimer += 20000; + LandTimer = 0; + Phase = PHASE_FLIGHT; + m_creature->RemoveAllAuras(); + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0); + // So players don't shoot us down + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + // Animate our take off! + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); + // We now hover! + m_creature->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + m_creature->GetMotionMaster()->MovePoint(0, CENTER_X, CENTER_Y, CENTER_Z); + for(uint8 i = 0; i < 2; ++i) + { + Creature* Glaive = m_creature->SummonCreature(BLADE_OF_AZZINOTH, GlaivePosition[i].x, GlaivePosition[i].y, GlaivePosition[i].z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + if(Glaive) + { + GlaiveGUID[i] = Glaive->GetGUID(); // We need this to remove them later on + Glaive->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Glaive->SetVisibility(VISIBILITY_OFF); + Glaive->setFaction(m_creature->getFaction()); + } + } + } + + void SummonBladesOfAzzinoth() + { + m_creature->GetMotionMaster()->Clear(false); + + LandTimer = 0; + RetrieveBladesTimer = 0; + + DoCast(m_creature, SPELL_THROW_GLAIVE2); // Make it look like we're throwing the glaives on the ground + // We no longer wear the glaives! + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 0); + // since they are now channeling the flames (or will be) + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 0); + for(uint8 i = 0; i < 2; ++i) + { + Creature* Glaive = NULL; + Glaive = ((Creature*)Unit::GetUnit((*m_creature), GlaiveGUID[i])); + if(Glaive) + { + DoCast(Glaive, SPELL_THROW_GLAIVE, true); + Glaive->SetVisibility(VISIBILITY_ON); + } + } + } + + void SummonFlamesOfAzzinoth() + { + DoYell(SAY_SUMMONFLAMES, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SUMMONFLAMES); + + for(uint8 i = 0; i < 2; ++i) + { + Creature* Flame = NULL; + Creature* Glaive = NULL; + Glaive = ((Creature*)Unit::GetUnit((*m_creature), GlaiveGUID[i])); + if(Glaive) + { + Flame = m_creature->SummonCreature(FLAME_OF_AZZINOTH, GlaivePosition[i+2].x, GlaivePosition[i+2].y, GlaivePosition[i+2].z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); + if(Flame) + { + // Just in case the database has it as a different faction + Flame->setFaction(m_creature->getFaction()); + // Attack our target! + Flame->AI()->AttackStart(m_creature->getVictim()); + FlameGUID[i] = Flame->GetGUID(); // Record GUID in order to check if they're dead later on to move to the next phase + // Glaives do some random Beam type channel on it. + Glaive->CastSpell(Flame, SPELL_AZZINOTH_CHANNEL, true); + if(m_creature->getVictim()) + Flame->AI()->AttackStart(m_creature->getVictim()); + } + else + { + DoTextEmote("is unable to summon a Flame of Azzinoth.", NULL); + error_log("SD2 ERROR: Illidan Stormrage AI: Unable to summon Flame of Azzinoth (entry: 22997), please check your database"); + EnterEvadeMode(); + } + } + else + { + DoTextEmote("is unable to summon a Blade of Azzinoth.", NULL); + error_log("SD2 ERROR: Illidan Stormrage AI: Unable to summon Blade of Azzinoth (entry: 22996), please check your database"); + } + } + DoResetThreat(); // And now reset our threatlist + HasSummoned = true; + } + + void SummonMaiev() + { + TauntTimer += 4000; + GlobalTimer += 4000; + + m_creature->InterruptNonMeleeSpells(false); // Interrupt any of our spells + Creature* Maiev = NULL; // Summon Maiev near Illidan + Maiev = m_creature->SummonCreature(MAIEV_SHADOWSONG, m_creature->GetPositionX() + 10, m_creature->GetPositionY() + 5, m_creature->GetPositionZ()+2, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 45000); + if(Maiev) + { + m_creature->GetMotionMaster()->Clear(false); // Stop moving, it's rude to walk and talk! + m_creature->GetMotionMaster()->MoveIdle(); + // Just in case someone is unaffected by Shadow Prison + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + DoCast(m_creature, SPELL_SHADOW_PRISON, true); + TalkCount = 10; + IsTalking = true; // We are now talking/ + Maiev->SetVisibility(VISIBILITY_OFF); // Leave her invisible until she has to talk + Maiev->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + MaievGUID = Maiev->GetGUID(); + } + else // If Maiev cannot be summoned, reset the encounter and post some errors to the console. + { + EnterEvadeMode(); + DoTextEmote("is unable to summon Maiev Shadowsong and enter Phase 4. Resetting Encounter.", NULL); + error_log("SD2 ERROR: Unable to summon Maiev Shadowsong (entry: 23197). Check your database to see if you have the proper SQL for Maiev Shadowsong (entry: 23197)"); + } + } + + void InitializeDeath() + { + m_creature->RemoveAllAuras(); + DoCast(m_creature, SPELL_DEATH); // Animate his kneeling + stun him + // Don't let the players interrupt our talk! + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->GetMotionMaster()->Clear(false); // No moving! + m_creature->GetMotionMaster()->MoveIdle(); + if(MaievGUID) + { + Creature* Maiev = ((Creature*)Unit::GetUnit((*m_creature), MaievGUID)); + if(Maiev) + { + Maiev->CombatStop(); // Maiev shouldn't do anything either. No point in her attacking us =] + Maiev->GetMotionMaster()->Clear(false); // Stop her from moving as well + Maiev->GetMotionMaster()->MoveIdle(); + float distance = 10.0f; + float dx = m_creature->GetPositionX() + (distance*cos(m_creature->GetOrientation())); + float dy = m_creature->GetPositionY() + (distance*sin(m_creature->GetOrientation())); + Maiev->Relocate(dx,dy,Maiev->GetPositionZ()); + Maiev->SendMonsterMove(dx,dy,Maiev->GetPositionZ(), 0, 0, 0); + Maiev->CastSpell(Maiev, SPELL_TELEPORT_VISUAL, true); + Maiev->SetUInt64Value(UNIT_FIELD_TARGET, m_creature->GetGUID()); + } + } + IsTalking = true; + TalkCount++; + } + + void UpdateAI(const uint32 diff) + { + /*** This section will handle the conversations ***/ + if(IsTalking) // Somewhat more efficient using a function rather than a long switch + { + if(TalkTimer < diff) + { + switch(TalkCount) // This is only for specialized cases + { + case 0: + // Time to stand up! + m_creature->RemoveAurasDueToSpell( SPELL_KNEEL ); + break; + case 8: + // Equip our warglaives! + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 45479); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 45481); + m_creature->setFaction(14); // Hostile if we weren't before + break; + case 9: + if(AkamaGUID) + { + Creature* Akama = ((Creature*)Unit::GetUnit((*m_creature), AkamaGUID)); + if(Akama) + { + Akama->GetMotionMaster()->Clear(false); + // Akama runs to us! + Akama->GetMotionMaster()->MoveChase(m_creature); + m_creature->GetMotionMaster()->Clear(false); + // We run to Akama! + m_creature->GetMotionMaster()->MoveChase(Akama); + Akama->AddThreat(m_creature, 1000000.0f); + AttackStart(Akama); // Start attacking Akama + ((npc_akama_illidanAI*)Akama->AI())->IsTalking = false; + // Akama starts attacking us + ((npc_akama_illidanAI*)Akama->AI())->AttackStart(m_creature); + } + } + // We are now attackable! + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + break; + case 11: + if(MaievGUID) + { + Unit* Maiev = Unit::GetUnit((*m_creature), MaievGUID); + if(Maiev) + { + // Maiev is now visible + Maiev->SetVisibility(VISIBILITY_ON); + // onoz she looks like she teleported! + Maiev->CastSpell(Maiev, SPELL_TELEPORT_VISUAL, true); + // Have her face us + Maiev->SetUInt64Value(UNIT_FIELD_TARGET, m_creature->GetGUID()); + // Face her, so it's not rude =P + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, Maiev->GetGUID()); + } + } + break; + case 14: + if(MaievGUID) + { + Creature* Maiev = ((Creature*)Unit::GetUnit((*m_creature), MaievGUID)); + if(Maiev) + { + Maiev->GetMotionMaster()->Clear(false); + Maiev->GetMotionMaster()->MoveChase(m_creature); + // Have Maiev add a lot of threat on us so that players don't pull her off if they damage her via AOE + Maiev->AddThreat(m_creature, 10000000.0f); + // Force Maiev to attack us. + Maiev->AI()->AttackStart(m_creature); + Maiev->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + } + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + IsTalking = false; + FaceVictimTimer = 2000; + RefaceVictim = true; + break; + case 20: // Kill ourself. + if(MaievGUID) + { + Creature* Maiev = ((Creature*)Unit::GetUnit((*m_creature), MaievGUID)); + if(Maiev) // Make Maiev leave + { + Maiev->CastSpell(Maiev, SPELL_TELEPORT_VISUAL, true); + Maiev->setDeathState(JUST_DIED); + } + } + IsTalking = false; + if(m_creature->getVictim()) + m_creature->getVictim()->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE,SPELL_SCHOOL_MASK_NORMAL, NULL, false); + else + // Now we kill ourself + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + break; + } + Talk(TalkCount); // This function does most of the talking + TalkCount++; + }else TalkTimer -= diff; + } + + // If we don't have a target, return. + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim() || IsTalking) + return; + + // If we are 'caged', then we shouldn't do anything such as cast spells or transform into Demon Form. + if(m_creature->HasAura(SPELL_CAGED, 0)) + { + EnrageTimer = 40000; // Just so that he doesn't immediately enrage after he stops being caged. + CageTimer = 30000; + return; + } + + // Berserk Timer - flat 25 minutes + if(!m_creature->HasAura(SPELL_BERSERK, 0) && Phase != PHASE_DEMON_SEQUENCE) + if(BerserkTimer < diff) + { + DoYell(SAY_ENRAGE, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_ENRAGE); + DoCast(m_creature, SPELL_BERSERK, true); + }else BerserkTimer -= diff; + + if(RefaceVictim) + if(FaceVictimTimer < diff) + { + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, m_creature->getVictim()->GetGUID()); + FaceVictimTimer = 1000; + RefaceVictim = false; + }else FaceVictimTimer -= diff; + + /** Signal to change to phase 2 **/ + if(((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 65) && (Phase == PHASE_NORMAL)) + EnterPhase2(); + + /** Signal to summon Maiev **/ + if(((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 30) && !MaievGUID && + ((Phase != PHASE_DEMON) || (Phase != PHASE_DEMON_SEQUENCE))) + SummonMaiev(); + + /** Time for the death speech **/ + if((m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 1) && (!IsTalking) && + ((Phase != PHASE_DEMON) || (Phase != PHASE_DEMON_SEQUENCE))) + InitializeDeath(); + + /***** Spells for Phase 1, 3 and 5 (Normal Form) ******/ + if(Phase == PHASE_NORMAL || Phase == PHASE_NORMAL_2 || Phase == PHASE_NORMAL_MAIEV) + { + if(TauntTimer < diff) // His random taunt/yell timer. + { + uint32 random = rand()%4; + char* yell = RandomTaunts[random].text; + uint32 soundid = RandomTaunts[random].sound; + if(yell) + DoYell(yell, LANG_UNIVERSAL, NULL); + if(soundid) + DoPlaySoundToSet(m_creature, soundid); + TauntTimer = 32000; + }else TauntTimer -= diff; + + if(GlobalTimer < diff) // Global Timer so that spells do not overlap. + { + if(ShearTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_SHEAR); + ShearTimer = 25000 + (rand()%16 * 1000); + GlobalTimer += 2000; + }else ShearTimer -= diff; + + if(FlameCrashTimer < diff) + { + // It spawns multiple flames sometimes. Therefore, we'll do this manually. + //DoCast(m_creature->getVictim(), SPELL_FLAME_CRASH); + DoSpawnCreature(FLAME_CRASH, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 40000); + FlameCrashTimer = 35000; + GlobalTimer += 2000; + }else FlameCrashTimer -= diff; + + if(ParasiticShadowFiendTimer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,1); + if(target && target->isAlive() && !target->HasAura(SPELL_PARASITIC_SHADOWFIEND, 0)) + { + Cast(target, SPELL_PARASITIC_SHADOWFIEND); + ParasiticShadowFiendTimer = 40000; + } + }else ParasiticShadowFiendTimer -= diff; + + if(DrawSoulTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_DRAW_SOUL); + DrawSoulTimer = 55000; + GlobalTimer += 3000; + }else DrawSoulTimer -= diff; + }else GlobalTimer -= diff; + + if(!IsTalking) + DoMeleeAttackIfReady(); + } + + /*** Phase 2 ***/ + if(Phase == PHASE_FLIGHT) + { + // Check if we have summoned or not. + if(!HasSummoned) + { + if(SummonBladesTimer) + if(SummonBladesTimer <= diff) + { + SummonBladesOfAzzinoth(); + SummonBladesTimer = 0; + }else SummonBladesTimer -= diff; + + if(SummonFlamesTimer < diff) + { + SummonFlamesOfAzzinoth(); + }else SummonFlamesTimer -= diff; + } + + if(!m_creature->GetMotionMaster()->empty() && (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() != POINT_MOTION_TYPE)) + m_creature->GetMotionMaster()->Clear(false); + + if(HasSummoned) + { + if(CheckFlamesTimer) + if(CheckFlamesTimer <= diff) + { + // Check if flames are dead or non-existant. If so, set GUID to 0. + for(uint8 i = 0; i < 2; i++) + { + if(FlameGUID[i]) + { + Unit* Flame = NULL; + Flame = Unit::GetUnit((*m_creature), FlameGUID[i]); + + // If the flame dies, or somehow the pointer becomes invalid, reset GUID to 0. + if(!Flame || !Flame->isAlive()) + FlameGUID[i] = 0; + } + } + CheckFlamesTimer = 500; + }else CheckFlamesTimer -= diff; + + // If both flames are dead/non-existant, kill glaives and change to phase 3. + if(!FlameGUID[0] && !FlameGUID[1] && CheckFlamesTimer) + { + RetrieveBladesTimer = 5000; // Prepare for re-equipin! + CheckFlamesTimer = 0; + } + + if(RetrieveBladesTimer) + if(RetrieveBladesTimer <= diff) // Time to get back our glaives! + { + // Interrupt any spells we might be doing *cough* DArk Barrage *cough* + m_creature->InterruptNonMeleeSpells(false); + for(uint8 i = 0; i < 2; i++) + { + if(GlaiveGUID[i]) + { + Unit* Glaive = NULL; + Glaive = Unit::GetUnit((*m_creature), GlaiveGUID[i]); + if(Glaive) + { + // Make it look like the Glaive flies back up to us + Glaive->CastSpell(m_creature, SPELL_GLAIVE_RETURNS, true); + // Despawn the Glaive + Glaive->setDeathState(JUST_DIED); + } + GlaiveGUID[i] = 0; + } + } + // Re-equip our warblades! + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 45479); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 45481); + LandTimer = 5000; // Prepare for landin'! + RetrieveBladesTimer = 0; + }else RetrieveBladesTimer -= diff; + + if(LandTimer) + { + if(LandTimer <= diff) // Time to land! + { + DoResetThreat(); + // anndddd touchdown! + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LAND); + m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT + MOVEMENTFLAG_LEVITATING); + Phase = PHASE_NORMAL_2; + // We should let the raid fight us =) + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, m_creature->getVictim()->GetGUID()); + // Chase our victim! + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + }else LandTimer -= diff; + return; // Do not continue past this point if LandTimer is not 0 and we are in phase 2. + } + } + + if(GlobalTimer < diff) + { + if(FireballTimer < diff) + { + Cast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_FIREBALL); + FireballTimer = 5000; + }else FireballTimer -= diff; + + if(DarkBarrageTimer < diff) + { + m_creature->InterruptNonMeleeSpells(false); + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_DARK_BARRAGE); + DarkBarrageTimer = 35000; + GlobalTimer += 9000; + }else DarkBarrageTimer -= diff; + + if(EyeBlastTimer < diff) + { + CastEyeBlast(); + EyeBlastTimer = 30000; + }else EyeBlastTimer -= diff; + }else GlobalTimer -= diff; + } + + /** Phase 3,5 spells only**/ + if(Phase == PHASE_NORMAL_2 || Phase == PHASE_NORMAL_MAIEV) + { + if(GlobalTimer < diff) + { + if(AgonizingFlamesTimer < diff) + { + CastAgonizingFlames(); + AgonizingFlamesTimer = 60000; + }else AgonizingFlamesTimer -= diff; + }else GlobalTimer -= diff; + + if(TransformTimer < diff) + { + uint32 CurHealth = m_creature->GetHealth()*100 / m_creature->GetMaxHealth(); + // Prevent Illidan from morphing if less than 32% or 5%, as this may cause issues with the phase transition or death speech + if((CurHealth < 32 && !MaievGUID) || (CurHealth < 5)) + return; + + Phase = PHASE_DEMON_SEQUENCE; // Transform sequence + DemonFormSequence = 0; + AnimationTimer = 0; + DoYell(SAY_MORPH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_MORPH); + TransformTimer = 60000; + FlameBurstTimer = 10000; + ShadowDemonTimer = 30000; + m_creature->GetMotionMaster()->Clear(false);// Stop moving + }else TransformTimer -= diff; + } + + /** Phase 4 spells only (Demon Form) **/ + if(Phase == PHASE_DEMON) + { + // Stop moving if we are by clearing movement generators. + if(!m_creature->GetMotionMaster()->empty()) + m_creature->GetMotionMaster()->Clear(false); + + if(TransformTimer < diff) + { + Phase = PHASE_DEMON_SEQUENCE; + DemonFormSequence = 5; + AnimationTimer = 100; + TransformTimer = 60000; + }else TransformTimer -= diff; + + if(ShadowDemonTimer < diff) + { + m_creature->InterruptNonMeleeSpells(false); + Creature* ShadowDemon = NULL; + for(uint8 i = 0; i < 4; i++) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + // only on players. + if(target && target->GetTypeId() == TYPEID_PLAYER) + { + ShadowDemon = DoSpawnCreature(SHADOW_DEMON, 0,0,0,0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,25000); + if(ShadowDemon) + { + ShadowDemon->AddThreat(target, 5000000.0f); + ShadowDemon->AI()->AttackStart(target); + DoZoneInCombat(ShadowDemon); + } + } + } + ShadowDemonTimer = 60000; + }else ShadowDemonTimer -= diff; + + if(GlobalTimer < diff) + { + if(ShadowBlastTimer < diff) + { + Unit* target = SelectUnit(SELECT_TARGET_TOPAGGRO, 0); + if(target && target->isAlive()) + { + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, target->GetGUID()); + DoCast(target, SPELL_SHADOW_BLAST); + ShadowBlastTimer = 4000; + GlobalTimer += 1500; + } + if(!m_creature->HasAura(SPELL_DEMON_FORM, 0)) + DoCast(m_creature, SPELL_DEMON_FORM, true); + }else ShadowBlastTimer -= diff; + + if(FlameBurstTimer < diff) + { + DoCast(m_creature, SPELL_FLAME_BURST); + FlameBurstTimer = 15000; + }else FlameBurstTimer -= diff; + }else GlobalTimer -= diff; + } + + /** Phase 5 timers. Enrage spell **/ + if(Phase == PHASE_NORMAL_MAIEV) + { + if(EnrageTimer < diff) + { + DoCast(m_creature, SPELL_ENRAGE); + EnrageTimer = 40000; + CageTimer = 30000; + TransformTimer += 10000; + }else EnrageTimer -= diff; + + // We'll handle Cage Trap in Illidan's script for simplicity's sake + if(CageTimer < diff) + { + if(MaievGUID) + { + Unit* Maiev = Unit::GetUnit((*m_creature), MaievGUID); + Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(!Maiev || !target || (target->GetTypeId() != TYPEID_PLAYER)) + return; + float X, Y, Z; + target->GetPosition(X, Y, Z); + Maiev->Relocate(X, Y, Z, Maiev->GetOrientation()); + // Make it look like she 'teleported' + Maiev->CastSpell(Maiev, SPELL_TELEPORT_VISUAL, true); + // summon the trap! + Maiev->CastSpell(Maiev, SPELL_CAGE_TRAP_SUMMON, false); + } + CageTimer = 15000; + }else CageTimer -= diff; + } + + if(Phase == PHASE_DEMON_SEQUENCE) // Demonic Transformation + { + if(AnimationTimer < diff) + { + HandleDemonTransformAnimation(DemonFormSequence); + DemonFormSequence++; + }else AnimationTimer -= diff; + } + } +}; + +/*********************** End of Illidan AI ******************************************/ + +void npc_akama_illidanAI::BeginEvent(uint64 PlayerGUID) +{ + debug_log("SD2: Akama - Illidan Introduction started. Illidan event properly begun."); + if(pInstance) + { + IllidanGUID = pInstance->GetData64(DATA_ILLIDANSTORMRAGE); + pInstance->SetData(DATA_ILLIDANSTORMRAGEEVENT, IN_PROGRESS); + } + + if(pInstance) + for(uint8 i = DATA_GAMEOBJECT_ILLIDAN_DOOR_R; i < DATA_GAMEOBJECT_ILLIDAN_DOOR_L+1; ++i) + { + GameObject* Door = GameObject::GetGameObject((*m_creature), pInstance->GetData64(i)); + if(Door) + Door->SetGoState(1); + } + + if(IllidanGUID) + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Creature* Illidan = ((Creature*)Unit::GetUnit((*m_creature), IllidanGUID)); + if(Illidan) + { + Illidan->RemoveAurasDueToSpell(SPELL_KNEEL); // Time for Illidan to stand up. + // First line of Akama-Illidan convo + ((boss_illidan_stormrageAI*)Illidan->AI())->TalkCount = 0; + // Begin Talking + ((boss_illidan_stormrageAI*)Illidan->AI())->IsTalking = true; + ((boss_illidan_stormrageAI*)Illidan->AI())->AkamaGUID = m_creature->GetGUID(); + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, Illidan->GetGUID()); + Illidan->SetUInt64Value(UNIT_FIELD_TARGET, m_creature->GetGUID()); + IsTalking = true; // Prevent Akama from starting to attack him + // Prevent players from talking again + m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Illidan->GetMotionMaster()->Clear(false); + Illidan->GetMotionMaster()->MoveIdle(); + m_creature->GetMotionMaster()->Clear(false); + m_creature->GetMotionMaster()->MoveIdle(); + + if(PlayerGUID) + { + Unit* player = Unit::GetUnit((*m_creature), PlayerGUID); + if(player) + Illidan->AddThreat(player, 100.0f); + } + } + } +} + +bool GossipSelect_npc_akama_at_illidan(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + if(action == GOSSIP_ACTION_INFO_DEF) // Time to begin the event + { + player->CLOSE_GOSSIP_MENU(); + ((npc_akama_illidanAI*)_Creature->AI())->BeginDoorEvent(player); + } + return true; +} + +bool GossipHello_npc_akama_at_illidan(Player *player, Creature *_Creature) +{ + player->ADD_GOSSIP_ITEM(0, GOSSIP_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + player->SEND_GOSSIP_MENU(10465, _Creature->GetGUID()); + + return true; +} + +struct MANGOS_DLL_SPEC boss_maievAI : public ScriptedAI +{ + boss_maievAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + }; + + uint32 TauntTimer; + uint64 IllidanGUID; + + ScriptedInstance* pInstance; + + void Reset() + { + TauntTimer = 12000; + IllidanGUID = 0; + } + + void Aggro(Unit *who) {} + + void UpdateAI(const uint32 diff) + { + if(!IllidanGUID) + { + if(pInstance) + IllidanGUID = pInstance->GetData64(DATA_ILLIDANSTORMRAGE); + }else + { + Creature* Illidan = NULL; + Illidan = ((Creature*)Unit::GetUnit((*m_creature), IllidanGUID)); + if(!Illidan || !Illidan->isAlive() || Illidan->IsInEvadeMode()) + { + m_creature->SetVisibility(VISIBILITY_OFF); + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + else if(Illidan && ((Illidan->GetHealth()*100 / Illidan->GetMaxHealth()) < 2)) + return; + } + + // Return if we don't have a target + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(TauntTimer < diff) + { + uint32 random = rand()%4; + char* text = MaievTaunts[random].text; + uint32 sound = MaievTaunts[random].sound; + DoYell(text, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, sound); + TauntTimer = 22000 + rand()%21 * 1000; + }else TauntTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL cage_trap_triggerAI : public ScriptedAI +{ + cage_trap_triggerAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint64 IllidanGUID; + uint64 CageTrapGUID; + + uint32 DespawnTimer; + + bool Active; + bool SummonedBeams; + + void Reset() + { + IllidanGUID = 0; + CageTrapGUID = 0; + + Active = false; + SummonedBeams = false; + + DespawnTimer = 0; + + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void Aggro(Unit *who){} + + void MoveInLineOfSight(Unit *who) + { + if(!Active) + return; + + if(who && (who->GetTypeId() != TYPEID_PLAYER)) + { + if(who->GetEntry() == ILLIDAN_STORMRAGE) // Check if who is Illidan + { + if(!IllidanGUID && m_creature->IsWithinDistInMap(who, 3) && !who->HasAura(SPELL_CAGED, 0)) + { + IllidanGUID = who->GetGUID(); + who->CastSpell(who, SPELL_CAGED, true); + DespawnTimer = 5000; + if(who->HasAura(SPELL_ENRAGE, 0)) + // Dispel his enrage + who->RemoveAurasDueToSpell(SPELL_ENRAGE); + + if(GameObject* CageTrap = GameObject::GetGameObject(*m_creature, CageTrapGUID)) + CageTrap->SetLootState(GO_JUST_DEACTIVATED); + } + } + } + } + + void UpdateAI(const uint32 diff) + { + if(DespawnTimer) + if(DespawnTimer < diff) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + else DespawnTimer -= diff; + + //if(IllidanGUID && !SummonedBeams) + //{ + // if(Unit* Illidan = Unit::GetUnit(*m_creature, IllidanGUID) + // { + // //TODO: Find proper spells and properly apply 'caged' Illidan effect + // } + //} + } +}; + +bool GOHello_cage_trap(Player* plr, GameObject* go) +{ + float x, y, z; + plr->GetPosition(x, y, z); + + Creature* trigger = NULL; + + CellPair pair(MaNGOS::ComputeCellPair(x, y)); + Cell cell(pair); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + // Grid search for nearest live creature of entry 23304 within 10 yards + MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck check(*plr, 23304, true, 10); + MaNGOS::CreatureLastSearcher searcher(trigger, check); + + TypeContainerVisitor, GridTypeMapContainer> cSearcher(searcher); + + CellLock cell_lock(cell, pair); + cell_lock->Visit(cell_lock, cSearcher, *(plr->GetMap())); + + if(!trigger) + { + plr->GetSession()->SendNotification("SD2: Summon failed. This trap is now useless.", LANG_UNIVERSAL, 0); + error_log("SD2: Cage Trap- Unable to find trigger. This Cage Trap is now useless"); + return false; + } + + ((cage_trap_triggerAI*)trigger->AI())->Active = true; + go->SetGoState(0); + return true; +} + +//This is used to sort the players by distance in preparation for being charged by the flames. +struct TargetDistanceOrder : public std::binary_function +{ + const Unit* MainTarget; + TargetDistanceOrder(const Unit* Target) : MainTarget(Target) {}; + // functor for operator ">" + bool operator()(const Unit* _Left, const Unit* _Right) const + { + return (MainTarget->GetDistance(_Left) > MainTarget->GetDistance(_Right)); + } +}; + +struct MANGOS_DLL_DECL flame_of_azzinothAI : public ScriptedAI +{ + flame_of_azzinothAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 FlameBlastTimer; + uint32 SummonBlazeTimer; + uint32 ChargeTimer; + + void Reset() + { + FlameBlastTimer = 15000 + rand()%15000; + SummonBlazeTimer = 10000 + rand()%20000; + ChargeTimer = 5000; + } + + void Aggro(Unit *who) {} + + void Charge() + { + // Get the Threat List + std::list& m_threatlist = m_creature->getThreatManager().getThreatList(); + + if(!m_threatlist.size()) return; // He doesn't have anyone in his threatlist, useless to continue + + std::list targets; + std::list::iterator itr = m_threatlist.begin(); + for( ; itr!= m_threatlist.end(); ++itr) //store the threat list in a different container + { + Unit *target = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid()); + //only on alive players + if(target && target->isAlive() && target->GetTypeId() == TYPEID_PLAYER ) + targets.push_back( target); + } + + //Sort the list of players + targets.sort(TargetDistanceOrder(m_creature)); + //Resize so we only get the furthest target + targets.resize(1); + + Unit* target = (*targets.begin()); + if(target && (!m_creature->IsWithinDistInMap(target, 40))) + { + DoCast(m_creature, SPELL_ENRAGE, true); + DoCast(target, SPELL_CHARGE); + } + } + + void UpdateAI(const uint32 diff) + { + // Return if we don't have a target + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(FlameBlastTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_FLAME_BLAST); + FlameBlastTimer = 30000; + }else FlameBlastTimer -= diff; + + if(SummonBlazeTimer < diff) + { + DoCast(m_creature, SPELL_BLAZE_SUMMON); + SummonBlazeTimer = 30000 + rand()%20000; + }else SummonBlazeTimer -= diff; + + if(ChargeTimer < diff) + { + Charge(); + ChargeTimer = 5000; + }else ChargeTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL shadow_demonAI : public ScriptedAI +{ + shadow_demonAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint64 TargetGUID; + + void Reset() { TargetGUID = 0; } + + void Aggro(Unit *who) {} + + void JustDied(Unit *killer) + { + if(TargetGUID) + { + Unit* target = Unit::GetUnit((*m_creature), TargetGUID); + if(target) + target->RemoveAurasDueToSpell(SPELL_PARALYZE); + } + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) return; + + // Only cast the below on players. + if(m_creature->getVictim()->GetTypeId() != TYPEID_PLAYER) return; + + if(!m_creature->getVictim()->HasAura(SPELL_PARALYZE, 0)) + { + TargetGUID = m_creature->getVictim()->GetGUID(); + m_creature->AddThreat(m_creature->getVictim(), 10000000.0f); + DoCast(m_creature, SPELL_SHADOW_DEMON_PASSIVE, true); + DoCast(m_creature->getVictim(), SPELL_PURPLE_BEAM, true); + DoCast(m_creature->getVictim(), SPELL_PARALYZE, true); + } + // Kill our target if we're very close. + if(m_creature->IsWithinDistInMap(m_creature->getVictim(), 3)) + DoCast(m_creature->getVictim(), SPELL_CONSUME_SOUL); + } +}; + +struct MANGOS_DLL_DECL flamecrashAI : public ScriptedAI +{ + flamecrashAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 FlameCrashTimer; + uint32 DespawnTimer; + + void Reset() + { + FlameCrashTimer = 3000 +rand()%5000; + DespawnTimer = 60000; + } + + void Aggro(Unit *who){ return; } + + void AttackStart(Unit *who) { } + + void MoveInLineOfSight(Unit *who){ } + + void UpdateAI(const uint32 diff) + { + if(FlameCrashTimer < diff) + { + DoCast(m_creature, SPELL_FLAME_CRASH_EFFECT); + FlameCrashTimer = 15000; + }else FlameCrashTimer -= diff; + + if(DespawnTimer < diff) + { + m_creature->SetVisibility(VISIBILITY_OFF); // So that players don't see the sparkly effect when we die. + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + }else DespawnTimer -= diff; + } +}; + +// Shadowfiends interact with Illidan, setting more targets in Illidan's hashmap +struct MANGOS_DLL_SPEC mob_parasitic_shadowfiendAI : public ScriptedAI +{ + mob_parasitic_shadowfiendAI(Creature* c) : ScriptedAI(c) + { + Reset(); + } + + void Reset() {} + + void Aggro(Unit* who) {} + + void DoMeleeAttackIfReady() + { + //If we are within range melee the target + if( m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE)) + { + //Make sure our attack is ready and we aren't currently casting + if( m_creature->isAttackReady() && !m_creature->IsNonMeleeSpellCasted(false)) + { + if(!m_creature->getVictim()->HasAura(SPELL_PARASITIC_SHADOWFIEND, 0)) + DoCast(m_creature->getVictim(), SPELL_PARASITIC_SHADOWFIEND, true); + m_creature->AttackerStateUpdate(m_creature->getVictim()); + m_creature->resetAttackTimer(); + } + } + } +}; + +struct MANGOS_DLL_DECL blazeAI : public ScriptedAI +{ + blazeAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 BlazeTimer; + uint32 DespawnTimer; + + void Reset() + { + BlazeTimer = 2000; + DespawnTimer = 15000; + } + + void Aggro(Unit *who){ } + + void AttackStart(Unit* who) { } + + void MoveInLineOfSight(Unit *who){ } + + void UpdateAI(const uint32 diff) + { + if(BlazeTimer < diff) + { + DoCast(m_creature, SPELL_BLAZE_EFFECT); + BlazeTimer = 15000; + }else BlazeTimer -= diff; + + if(DespawnTimer < diff) + { + m_creature->SetVisibility(VISIBILITY_OFF); + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + }else DespawnTimer -= diff; + } +}; + +struct MANGOS_DLL_DECL blade_of_azzinothAI : public ScriptedAI +{ + blade_of_azzinothAI(Creature* c) : ScriptedAI(c) { Reset(); } + + void Reset() {} + // Do-Nothing-But-Stand-There + void Aggro(Unit* who) { } + void AttackStart(Unit* who) { } + void MoveInLineOfSight(Unit* who) { } + +}; + +CreatureAI* GetAI_boss_illidan_stormrage(Creature *_Creature) +{ + return new boss_illidan_stormrageAI (_Creature); +} + +CreatureAI* GetAI_npc_akama_at_illidan(Creature *_Creature) +{ + npc_akama_illidanAI* Akama_AI = new npc_akama_illidanAI(_Creature); + + for(uint8 i = 0; i < 13; ++i) + Akama_AI->AddWaypoint(i, AkamaWP[i].x, AkamaWP[i].y, AkamaWP[i].z); + + return ((CreatureAI*)Akama_AI); +} + +CreatureAI* GetAI_boss_maiev(Creature *_Creature) +{ + return new boss_maievAI (_Creature); +} + +CreatureAI* GetAI_mob_flame_of_azzinoth(Creature *_Creature) +{ + return new flame_of_azzinothAI (_Creature); +} + +CreatureAI* GetAI_cage_trap_trigger(Creature *_Creature) +{ + return new cage_trap_triggerAI (_Creature); +} + +CreatureAI* GetAI_shadow_demon(Creature *_Creature) +{ + return new shadow_demonAI (_Creature); +} + +CreatureAI* GetAI_flamecrash(Creature *_Creature) +{ + return new flamecrashAI (_Creature); +} + +CreatureAI* GetAI_demonfire(Creature *_Creature) +{ + return new demonfireAI (_Creature); +} + +CreatureAI* GetAI_blaze(Creature *_Creature) +{ + return new blazeAI (_Creature); +} + +CreatureAI* GetAI_blade_of_azzinoth(Creature *_Creature) +{ + return new blade_of_azzinothAI (_Creature); +} + +CreatureAI* GetAI_parasitic_shadowfiend(Creature *_Creature) +{ + return new mob_parasitic_shadowfiendAI (_Creature); +} + +void AddSC_boss_illidan() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "boss_illidan_stormrage"; + newscript->GetAI = GetAI_boss_illidan_stormrage; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name = "npc_akama_illidan"; + newscript->GetAI = GetAI_npc_akama_at_illidan; + newscript->pGossipHello = GossipHello_npc_akama_at_illidan; + newscript->pGossipSelect = GossipSelect_npc_akama_at_illidan; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name = "boss_maiev_shadowsong"; + newscript->GetAI = GetAI_boss_maiev; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name = "mob_flame_of_azzinoth"; + newscript->GetAI = GetAI_mob_flame_of_azzinoth; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name = "mob_blade_of_azzinoth"; + newscript->GetAI = GetAI_blade_of_azzinoth; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name = "gameobject_cage_trap"; + newscript->pGOHello = GOHello_cage_trap; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_cage_trap_trigger"; + newscript->GetAI = GetAI_cage_trap_trigger; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name = "mob_shadow_demon"; + newscript->GetAI = GetAI_shadow_demon; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_flame_crash"; + newscript->GetAI = GetAI_flamecrash; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_demon_fire"; + newscript->GetAI = GetAI_demonfire; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_blaze"; + newscript->GetAI = GetAI_blaze; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name = "mob_parasitic_shadowfiend"; + newscript->GetAI = GetAI_parasitic_shadowfiend; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/black_temple/boss_mother_shahraz.cpp b/src/bindings/scripts/scripts/zone/black_temple/boss_mother_shahraz.cpp new file mode 100644 index 00000000000..383e3b05656 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/black_temple/boss_mother_shahraz.cpp @@ -0,0 +1,353 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Mother_Shahraz +SD%Complete: 80 +SDComment: Saber Lash missing, Fatal Attraction slightly incorrect; need to damage only if affected players are within range of each other +SDCategory: Black Temple +EndScriptData */ + +#include "precompiled.h" +#include "def_black_temple.h" + +//Spells +#define SPELL_BEAM_SINISTER 40859 +#define SPELL_BEAM_VILE 40860 +#define SPELL_BEAM_WICKED 40861 +#define SPELL_BEAM_SINFUL 40827 +#define SPELL_ATTRACTION 40871 +#define SPELL_SILENCING_SHRIEK 40823 +#define SPELL_ENRAGE 23537 +#define SPELL_SABER_LASH 43267 +#define SPELL_SABER_LASH_IMM 43690 +#define SPELL_TELEPORT_VISUAL 40869 +#define SPELL_BERSERK 45078 + +uint32 PrismaticAuras[]= +{ + 40880, // Shadow + 40882, // Fire + 40883, // Nature + 40891, // Arcane + 40896, // Frost + 40897, // Holy +}; + +//Speech'n'Sounds +#define SAY_TAUNT1 "You play, you pay." +#define SOUND_TAUNT1 11501 + +#define SAY_TAUNT2 "I'm not impressed." +#define SOUND_TAUNT2 11502 + +#define SAY_TAUNT3 "Enjoying yourselves?" +#define SOUND_TAUNT3 11503 + +#define SAY_AGGRO "So, business... Or pleasure?" +#define SOUND_AGGRO 11504 + +#define SAY_SPELL1 "You seem a little tense." +#define SOUND_SPELL1 11505 + +#define SAY_SPELL2 "Don't be shy." +#define SOUND_SPELL2 11506 + +#define SAY_SPELL3 "I'm all... yours." +#define SOUND_SPELL3 11507 + +#define SAY_SLAY1 "Easy come, easy go." +#define SOUND_SLAY1 11508 + +#define SAY_SLAY2 "So much for a happy ending." +#define SOUND_SLAY2 11509 + +#define SAY_ENRAGE "Stop toying with my emotions!" +#define SOUND_ENRAGE 11510 + +#define SAY_DEATH "I wasn't... finished." +#define SOUND_DEATH 11511 + +struct Locations +{ + float x,y,z; +}; + +static Locations TeleportPoint[]= +{ + {959.996, 212.576, 193.843}, + {932.537, 231.813, 193.838}, + {958.675, 254.767, 193.822}, + {946.955, 201.316, 192.535}, + {944.294, 149.676, 197.551}, + {930.548, 284.888, 193.367}, + {965.997, 278.398, 195.777} +}; + +struct MANGOS_DLL_DECL boss_shahrazAI : public ScriptedAI +{ + boss_shahrazAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + + uint64 TargetGUID[3]; + uint32 BeamTimer; + uint32 BeamCount; + uint32 CurrentBeam; + uint32 PrismaticShieldTimer; + uint32 FatalAttractionTimer; + uint32 FatalAttractionExplodeTimer; + uint32 ShriekTimer; + uint32 RandomYellTimer; + uint32 EnrageTimer; + uint32 ExplosionCount; + + bool Enraged; + + void Reset() + { + if(pInstance) + pInstance->SetData(DATA_MOTHERSHAHRAZEVENT, NOT_STARTED); + + for(uint8 i = 0; i<3; i++) + TargetGUID[i] = 0; + + BeamTimer = 60000; // Timers may be incorrect + BeamCount = 0; + CurrentBeam = 0; // 0 - Sinister, 1 - Vile, 2 - Wicked, 3 - Sinful + PrismaticShieldTimer = 0; + FatalAttractionTimer = 60000; + FatalAttractionExplodeTimer = 70000; + ShriekTimer = 30000; + RandomYellTimer = 70000 + rand()%41 * 1000; + EnrageTimer = 600000; + ExplosionCount = 0; + + Enraged = false; + } + + void Aggro(Unit *who) + { + if(pInstance) + pInstance->SetData(DATA_MOTHERSHAHRAZEVENT, IN_PROGRESS); + + DoZoneInCombat(); + DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO); + } + + void KilledUnit(Unit *victim) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_SLAY1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY1); + break; + case 1: + DoYell(SAY_SLAY2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY2); + break; + } + } + + void JustDied(Unit *victim) + { + if(pInstance) + pInstance->SetData(DATA_MOTHERSHAHRAZEVENT, DONE); + + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_DEATH); + } + + void TeleportPlayers() + { + uint32 random = rand()%7; + float X = TeleportPoint[random].x; + float Y = TeleportPoint[random].y; + float Z = TeleportPoint[random].z; + for(uint8 i = 0; i < 3; i++) + { + Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 1); + if(pUnit && pUnit->isAlive() && (pUnit->GetTypeId() == TYPEID_PLAYER)) + { + TargetGUID[i] = pUnit->GetGUID(); + pUnit->CastSpell(pUnit, SPELL_TELEPORT_VISUAL, true); + DoTeleportPlayer(pUnit, X, Y, Z, pUnit->GetOrientation()); + } + } + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 10) && !Enraged) + { + Enraged = true; + DoCast(m_creature, SPELL_ENRAGE, true); + DoYell(SAY_ENRAGE, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_ENRAGE); + } + + //Randomly cast one beam. + if(BeamTimer < diff) + { + Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(!target || !target->isAlive()) + return; + + BeamTimer = 9000; + + switch(CurrentBeam) + { + case 0: + DoCast(target, SPELL_BEAM_SINISTER); + break; + case 1: + DoCast(target, SPELL_BEAM_VILE); + break; + case 2: + DoCast(target, SPELL_BEAM_WICKED); + break; + case 3: + DoCast(target, SPELL_BEAM_SINFUL); + break; + } + BeamCount++; + uint32 Beam = CurrentBeam; + if(BeamCount > 3) + while(CurrentBeam == Beam) + CurrentBeam = rand()%3; + + }else BeamTimer -= diff; + + // Random Prismatic Shield every 15 seconds. + if(PrismaticShieldTimer < diff) + { + uint32 random = rand()%6; + if(PrismaticAuras[random]) + DoCast(m_creature, PrismaticAuras[random]); + PrismaticShieldTimer = 15000; + }else PrismaticShieldTimer -= diff; + + // Select 3 random targets (can select same target more than once), teleport to a random location then make them cast explosions until they get away from each other. + if(FatalAttractionTimer < diff) + { + ExplosionCount = 0; + + TeleportPlayers(); + + switch(rand()%2) + { + case 0: + DoYell(SAY_SPELL2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SPELL2); + break; + case 1: + DoYell(SAY_SPELL3,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SPELL3); + break; + } + FatalAttractionExplodeTimer = 2000; + FatalAttractionTimer = 40000 + rand()%31 * 1000; + }else FatalAttractionTimer -= diff; + + if(FatalAttractionExplodeTimer < diff) + { + // Just make them explode three times... they're supposed to keep exploding while they are in range, but it'll take too much code. I'll try to think of an efficient way for it later. + if(ExplosionCount < 3) + { + for(uint8 i = 0; i < 4; i++) + { + Unit* pUnit = NULL; + if(TargetGUID[i]) + { + pUnit = Unit::GetUnit((*m_creature), TargetGUID[i]); + if(pUnit) + pUnit->CastSpell(pUnit, SPELL_ATTRACTION, true); + TargetGUID[i] = 0; + } + } + + ExplosionCount++; + FatalAttractionExplodeTimer = 1000; + } + else + { + FatalAttractionExplodeTimer = FatalAttractionTimer + 2000; + ExplosionCount = 0; + } + }else FatalAttractionExplodeTimer -= diff; + + if(ShriekTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_SILENCING_SHRIEK); + ShriekTimer = 30000; + }else ShriekTimer -= diff; + + //Enrage + if(!m_creature->HasAura(SPELL_BERSERK, 0)) + if(EnrageTimer < diff) + { + DoCast(m_creature, SPELL_BERSERK); + DoYell(SAY_ENRAGE,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_ENRAGE); + }else EnrageTimer -= diff; + + //Random taunts + if(RandomYellTimer < diff) + { + switch(rand()%3) + { + case 0: + DoYell(SAY_TAUNT1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_TAUNT1); + break; + case 1: + DoYell(SAY_TAUNT2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_TAUNT2); + break; + case 2: + DoYell(SAY_TAUNT3,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_TAUNT3); + break; + } + RandomYellTimer = 60000 + rand()%91 * 1000; + }else RandomYellTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_shahraz(Creature *_Creature) +{ + return new boss_shahrazAI (_Creature); +} + +void AddSC_boss_mother_shahraz() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_mother_shahraz"; + newscript->GetAI = GetAI_boss_shahraz; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/black_temple/boss_reliquary_of_souls.cpp b/src/bindings/scripts/scripts/zone/black_temple/boss_reliquary_of_souls.cpp new file mode 100644 index 00000000000..19ba2784880 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/black_temple/boss_reliquary_of_souls.cpp @@ -0,0 +1,1051 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Reliquary_of_Souls +SD%Complete: 90 +SDComment: Persistent Area Auras for each Essence (Aura of Suffering, Aura of Desire, Aura of Anger) requires core support. +SDCategory: Black Temple +EndScriptData */ + +#include "precompiled.h" +#include "def_black_temple.h" + +//Sound'n'speech +//Suffering +#define SUFF_SAY_FREED "Pain and suffering are all that await you!" +#define SUFF_SOUND_FREED 11415 +#define SUFF_SAY_AGGRO "Don't leave me alone!" +#define SUFF_SOUND_AGGRO 11416 +#define SUFF_SAY_SLAY1 "Look at what you make me do!" +#define SUFF_SOUND_SLAY1 11417 +#define SUFF_SAY_SLAY2 "I didn't ask for this!" +#define SUFF_SOUND_SLAY2 11418 +#define SUFF_SAY_SLAY3 "The pain is only beginning!" +#define SUFF_SOUND_SLAY3 11419 +#define SUFF_SAY_RECAP "I don't want to go back!" +#define SUFF_SOUND_RECAP 11420 +#define SUFF_SAY_AFTER "Now what do I do?" +#define SUFF_SOUND_AFTER 11421 + +//Desire +#define DESI_SAY_FREED "You can have anything you desire... for a price." +#define DESI_SOUND_FREED 11408 +#define DESI_SAY_SLAY1 "Fulfilment is at hand!" +#define DESI_SOUND_SLAY1 11409 +#define DESI_SAY_SLAY2 "Yes... you'll stay with us now..." +#define DESI_SOUND_SLAY2 11410 +#define DESI_SAY_SLAY3 "Your reach exceeds your grasp." +#define DESI_SOUND_SLAY3 11412 +#define DESI_SAY_SPEC "Be careful what you wish for..." +#define DESI_SOUND_SPEC 11411 +#define DESI_SAY_RECAP "I'll be waiting..." +#define DESI_SOUND_RECAP 11413 +#define DESI_SAY_AFTER "I won't be far..." +#define DESI_SOUND_AFTER 11414 + +//Anger +#define ANGER_SAY_FREED "Beware... I live." +#define ANGER_SOUND_FREED 11399 +#define ANGER_SAY_FREED2 "So... foolish." +#define ANGER_SOUND_FREED2 11400 +#define ANGER_SOUND_SLAY1 11401 +#define ANGER_SAY_SLAY2 "Enough. No more." +#define ANGER_SOUND_SLAY2 11402 +#define ANGER_SAY_SPEC "On your knees!" +#define ANGER_SOUND_SPEC 11403 +#define ANGER_SAY_BEFORE "Beware, coward." +#define ANGER_SOUND_BEFORE 11405 +#define ANGER_SAY_DEATH "I won't... be... ignored." +#define ANGER_SOUND_DEATH 11404 + +//Spells +#define AURA_OF_SUFFERING 41292 +#define AURA_OF_SUFFERING_ARMOR 42017 +#define ESSENCE_OF_SUFFERING_PASSIVE 41296 +#define SPELL_ENRAGE 41305 +#define SPELL_SOUL_DRAIN 41303 +#define SPELL_FIXATE 41295 + +#define AURA_OF_DESIRE 41350 +#define SPELL_RUNE_SHIELD 41431 +#define SPELL_DEADEN 41410 +#define SPELL_SOUL_SHOCK 41426 + +#define AURA_OF_ANGER 41337 +#define SPELL_SELF_SEETHE 41364 +#define SPELL_ENEMY_SEETHE 41520 +#define SPELL_SOUL_SCREAM 41545 +#define SPELL_SPITE 41377 + +#define ENSLAVED_SOUL_PASSIVE 41535 +#define SPELL_SOUL_RELEASE 41542 +#define SPELL_RESTORE_MANA 32848 +#define SPELL_RESTORE_HEALTH 25329 + +#define CREATURE_ENSLAVED_SOUL 23469 + +struct Position +{ + float x,y; +}; + +static Position Coords[]= +{ + {450.4, 212.3}, + {542.1, 212.3}, + {542.1, 168.3}, + {542.1, 137.4}, + {450.4, 137.4}, + {450.4, 168.3} +}; + +struct MANGOS_DLL_DECL npc_enslaved_soulAI : public ScriptedAI +{ + npc_enslaved_soulAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint64 ReliquaryGUID; + + void Reset() + { + ReliquaryGUID = 0; + } + + void Aggro(Unit* who) {} + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if(damage >= m_creature->GetHealth()) + { + if(done_by->GetTypeId() == TYPEID_PLAYER) + { + done_by->CastSpell(done_by, SPELL_RESTORE_HEALTH, true); + if(done_by->GetMaxPower(POWER_MANA) > 0) + { + if((done_by->GetPower(POWER_MANA) / done_by->GetMaxPower(POWER_MANA)) < 70) + { + uint32 mana = done_by->GetPower(POWER_MANA) + (uint32)(done_by->GetMaxPower(POWER_MANA)*0.3); + done_by->SetPower(POWER_MANA, mana); + }else done_by->SetPower(POWER_MANA, done_by->GetMaxPower(POWER_MANA)); + } + } + DoCast(done_by, SPELL_SOUL_RELEASE); + } + } + + void JustDied(Unit *killer); +}; + +struct MANGOS_DLL_DECL boss_reliquary_of_soulsAI : public ScriptedAI +{ + boss_reliquary_of_soulsAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + + uint64 SufferingGUID; + uint64 DesireGUID; + uint64 AngerGUID; + + uint32 SoulDeathCount; + // 0 = Out of Combat, 1 = Not started, 2 = Suffering, 3 = Souls, 4 = Desire, 5 = Souls, 6 = Anger + uint32 Phase; + uint32 SummonEssenceTimer; + uint32 DespawnEssenceTimer; + uint32 SoulCount; + uint32 SummonSoulTimer; + uint32 AnimationTimer; + + bool IsDead; + bool EndingPhase; + + void Reset() + { + if(pInstance) + pInstance->SetData(DATA_RELIQUARYOFSOULSEVENT, NOT_STARTED); + + DespawnEssences(); + + SufferingGUID = 0; + DesireGUID = 0; + AngerGUID = 0; + + SoulDeathCount = 0; + Phase = 0; + SummonEssenceTimer = 8000; + DespawnEssenceTimer = 2000; + SoulCount = 0; + SummonSoulTimer = 1000; + AnimationTimer = 8000; + + IsDead = false; + EndingPhase = false; + + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE,0); + m_creature->GetMotionMaster()->Clear(false); + } + + void Aggro(Unit* who) { } + + void AttackStart(Unit* who) { } + + void MoveInLineOfSight(Unit *who) + { + if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + float attackRadius = m_creature->GetAttackDistance(who); + if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) + { + if(who->HasStealthAura()) + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + if(!InCombat) + { + if(pInstance) + pInstance->SetData(DATA_RELIQUARYOFSOULSEVENT, IN_PROGRESS); + + Phase = 1; + // I R ANNNGRRRY! + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE,375); + SummonEssenceTimer = 8000; + AnimationTimer = 5100; + m_creature->AddThreat(who, 1.0f); + + InCombat = true; + } + } + } + } + + void SummonSoul() + { + uint32 random = rand()%6; + float x = Coords[random].x; + float y = Coords[random].y; + Creature* Soul = m_creature->SummonCreature(CREATURE_ENSLAVED_SOUL, x, y, m_creature->GetPositionZ(), m_creature->GetOrientation(), TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 45000); + Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (target && Soul) + { + ((npc_enslaved_soulAI*)Soul->AI())->ReliquaryGUID = m_creature->GetGUID(); + Soul->CastSpell(Soul, ENSLAVED_SOUL_PASSIVE, true); + Soul->AddThreat(target, 1.0f); + SoulCount++; + } + } + + void MergeThreatList(Creature* target) + { + if(!target) return; + + std::list& m_threatlist = target->getThreatManager().getThreatList(); + std::list::iterator itr = m_threatlist.begin(); + for( ; itr != m_threatlist.end(); itr++) + { + Unit* pUnit = Unit::GetUnit((*m_creature), (*itr)->getUnitGuid()); + if(pUnit) + { + m_creature->AddThreat(pUnit, 1.0f); // This is so that we make sure the unit is in Reliquary's threat list before we reset the unit's threat. + m_creature->getThreatManager().modifyThreatPercent(pUnit, -100); + float threat = target->getThreatManager().getThreat(pUnit); + m_creature->AddThreat(pUnit, threat); // This makes it so that the unit has the same amount of threat in Reliquary's threatlist as in the target creature's (One of the Essences). + } + } + } + + void DespawnEssences() + { + // Despawn Essences + Unit* Essence = NULL; + if(SufferingGUID) + Essence = ((Creature*)Unit::GetUnit((*m_creature), SufferingGUID)); + else if(DesireGUID) + Essence = ((Creature*)Unit::GetUnit((*m_creature), DesireGUID)); + else if(AngerGUID) + Essence = ((Creature*)Unit::GetUnit((*m_creature), AngerGUID)); + if(Essence && Essence->isAlive()) + Essence->setDeathState(JUST_DIED); + } + + void JustDied(Unit* killer) + { + if(pInstance) + pInstance->SetData(DATA_RELIQUARYOFSOULSEVENT, DONE); + + InCombat = false; + } + + void UpdateAI(const uint32 diff) + { + if(!Phase) + return; + + // Reset if event is begun and we don't have a threatlist + if(Phase && m_creature->getThreatManager().getThreatList().empty()) + EnterEvadeMode(); + + if(Phase == 1) + { + if(AnimationTimer < diff) + { + // Release the cube + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE,374); + AnimationTimer = 8300; + }else AnimationTimer -= diff; + + if(SummonEssenceTimer < diff) + { + // Ribs: open + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE,373); + Creature* EssenceSuffering = NULL; + EssenceSuffering = m_creature->SummonCreature(23418, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 1.57, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10000); + + if(EssenceSuffering) + { + EssenceSuffering->Yell(SUFF_SAY_FREED, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(m_creature, SUFF_SOUND_FREED); + Unit* target = SelectUnit(SELECT_TARGET_TOPAGGRO, 0); + if(target) + { + EssenceSuffering->AddThreat(target, 1.0f); + EssenceSuffering->AI()->AttackStart(target); + } + SufferingGUID = EssenceSuffering->GetGUID(); + } + + EndingPhase = false; + Phase = 2; + }else SummonEssenceTimer -= diff; + } + + if(Phase == 2) + { + if(SufferingGUID) + { + Creature* EssenceSuffering = NULL; + EssenceSuffering = ((Creature*)Unit::GetUnit((*m_creature), SufferingGUID)); + + if(!EssenceSuffering || (!EssenceSuffering->isAlive())) + EnterEvadeMode(); + + if(!EndingPhase) + { + if(EssenceSuffering) + { + if(EssenceSuffering->GetHealth() < (EssenceSuffering->GetMaxHealth()*0.1)) + { + MergeThreatList(EssenceSuffering); + EssenceSuffering->RemoveAllAuras(); + EssenceSuffering->DeleteThreatList(); + EssenceSuffering->GetMotionMaster()->MoveFollow(m_creature,0.0f,0.0f); + EssenceSuffering->Yell(SUFF_SAY_RECAP,LANG_UNIVERSAL,0); + DoPlaySoundToSet(m_creature, SUFF_SOUND_RECAP); + EssenceSuffering->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DespawnEssenceTimer = 4000; + AnimationTimer = 2200; + EndingPhase = true; + } + } + } + + if((EndingPhase) && (EssenceSuffering) && (EssenceSuffering->isAlive())) + { + if(AnimationTimer < diff) + { + // Return + EssenceSuffering->SetUInt32Value(UNIT_NPC_EMOTESTATE,374); + AnimationTimer = 10000; + }else AnimationTimer -= diff; + + if(DespawnEssenceTimer < diff) + { + EssenceSuffering->DeleteThreatList(); + EssenceSuffering->Yell(SUFF_SAY_AFTER,LANG_UNIVERSAL,0); + DoPlaySoundToSet(m_creature, SUFF_SOUND_AFTER); + EssenceSuffering->SetUInt32Value(UNIT_FIELD_DISPLAYID, 11686); + EssenceSuffering->setFaction(35); + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE,0); + SummonEssenceTimer = 20000; //60000; + AnimationTimer = 18200; //58100; + SoulDeathCount = 0; + SoulCount = 0; + SummonSoulTimer = 1000; + EndingPhase = false; + Phase = 3; + SufferingGUID = 0; + }else DespawnEssenceTimer -= diff; + } + } + } + + if(Phase == 3) + { + if(SoulCount < 36) + { + if(SummonSoulTimer < diff) + { + SummonSoul(); + SummonSoulTimer = 500; + }else SummonSoulTimer -= diff; + } + + if(SoulDeathCount >= SoulCount) + { + if(AnimationTimer < diff) + { + // Release the cube + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE,374); + AnimationTimer = 10000; + }else AnimationTimer -= diff; + + if(SummonEssenceTimer < diff) + { + // Ribs: open + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE,373); + Creature* EssenceDesire = NULL; + EssenceDesire = m_creature->SummonCreature(23419, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 1.57, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10000); + + if(EssenceDesire) + { + EssenceDesire->Yell(DESI_SAY_FREED, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, DESI_SOUND_FREED); + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target) + { + EssenceDesire->AddThreat(target, 1.0f); + EssenceDesire->AI()->AttackStart(target); + } + DesireGUID = EssenceDesire->GetGUID(); + SoulDeathCount = 0; + } + + Phase = 4; + }else SummonEssenceTimer -= diff; + } + } + + if(Phase == 4) + { + if(DesireGUID) + { + Creature* EssenceDesire = NULL; + EssenceDesire = ((Creature*)Unit::GetUnit((*m_creature), DesireGUID)); + + if(!EssenceDesire || !EssenceDesire->isAlive()) + EnterEvadeMode(); + + if(!EndingPhase && EssenceDesire) + { + if(EssenceDesire->GetHealth() < (EssenceDesire->GetMaxHealth()*0.1)) + { + MergeThreatList(EssenceDesire); + EssenceDesire->GetMotionMaster()->MoveFollow(m_creature,0.0f,0.0f); + EssenceDesire->RemoveAllAuras(); + EssenceDesire->DeleteThreatList(); + EssenceDesire->Yell(DESI_SAY_RECAP,LANG_UNIVERSAL,0); + DoPlaySoundToSet(m_creature, DESI_SOUND_RECAP); + EssenceDesire->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DespawnEssenceTimer = 4000; + AnimationTimer = 2200; + EndingPhase = true; + } + } + + if(EndingPhase && EssenceDesire) + { + if(EssenceDesire->isAlive()) + { + if(AnimationTimer < diff) + { + // Return + EssenceDesire->SetUInt32Value(UNIT_NPC_EMOTESTATE,374); + AnimationTimer = 10000; + }else AnimationTimer -= diff; + + if(DespawnEssenceTimer < diff) + { + EssenceDesire->DeleteThreatList(); + EssenceDesire->setFaction(35); + EssenceDesire->Yell(DESI_SAY_AFTER, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(m_creature, DESI_SOUND_AFTER); + EssenceDesire->SetUInt32Value(UNIT_FIELD_DISPLAYID, 11686); + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE,0); + SummonEssenceTimer = 20000; + AnimationTimer = 18200; + SoulDeathCount = 0; + SoulCount = 0; + SummonSoulTimer = 1000; + EndingPhase = false; + Phase = 5; + DesireGUID = 0; + }else DespawnEssenceTimer -= diff; + } + } + } + } + + if(Phase == 5) + { + if(SoulCount < 36) + { + if(SummonSoulTimer < diff) + { + SummonSoul(); + SummonSoulTimer = 500; + }else SummonSoulTimer -= diff; + } + + if(SoulDeathCount >= SoulCount) + { + if(AnimationTimer < diff) + { + // Release the cube + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE,374); + AnimationTimer = 10000; + }else AnimationTimer -= diff; + + if(SummonEssenceTimer < diff) + { + // Ribs: open + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE,373); + Creature* EssenceAnger = NULL; + EssenceAnger = m_creature->SummonCreature(23420, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 1.57, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 45000); + + if(EssenceAnger) + { + Unit* target = SelectUnit(SELECT_TARGET_TOPAGGRO, 0); + if(target) + { + EssenceAnger->AddThreat(target, 1.0f); + EssenceAnger->AI()->AttackStart(target); + } + AngerGUID = EssenceAnger->GetGUID(); + DoPlaySoundToSet(m_creature, ANGER_SOUND_FREED); + EssenceAnger->Yell(ANGER_SAY_FREED, LANG_UNIVERSAL, 0); + SoulDeathCount = 0; + } + + Phase = 6; + }else SummonEssenceTimer -= diff; + } + } + + if(Phase == 6) + { + if(AngerGUID) + { + Creature* EssenceAnger = NULL; + EssenceAnger = ((Creature*)Unit::GetUnit((*m_creature), AngerGUID)); + + if(!EssenceAnger) + EnterEvadeMode(); + + if(m_creature->isAlive() && EssenceAnger) + { + if(!EssenceAnger->isAlive()) + { + AngerGUID = 0; + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + } + } + } +}; + +//This is used to sort the players by distance in preparation for the Fixate cast. +struct TargetDistanceOrder : public std::binary_function +{ + const Unit* MainTarget; + TargetDistanceOrder(const Unit* Target) : MainTarget(Target) {}; + // functor for operator "<" + bool operator()(const Unit* _Left, const Unit* _Right) const + { + return (MainTarget->GetDistance(_Left) < MainTarget->GetDistance(_Right)); + } +}; + +struct MANGOS_DLL_DECL boss_essence_of_sufferingAI : public ScriptedAI +{ + boss_essence_of_sufferingAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint64 StatAuraGUID; + + uint32 AggroYellTimer; + uint32 FixateTimer; + uint32 EnrageTimer; + uint32 SoulDrainTimer; + + void Reset() + { + StatAuraGUID = 0; + + AggroYellTimer = 5000; + FixateTimer = 5000; + EnrageTimer = 30000; + SoulDrainTimer = 150000; + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if((damage >= m_creature->GetHealth()) && (done_by != m_creature)) + { + damage = 0; + // 10% of total health, signalling time to return + m_creature->SetHealth(m_creature->GetMaxHealth()/10); + if(StatAuraGUID) + { + Unit* pUnit = Unit::GetUnit((*m_creature), StatAuraGUID); + if(pUnit) + pUnit->RemoveAurasDueToSpell(AURA_OF_SUFFERING_ARMOR); + } + } + } + + void Aggro(Unit *who) + { + DoZoneInCombat(); + DoCast(who, AURA_OF_SUFFERING, true); + DoCast(m_creature, ESSENCE_OF_SUFFERING_PASSIVE, true); + } + + void KilledUnit(Unit *victim) + { + switch(rand()%3) + { + case 0: + DoYell(SUFF_SAY_SLAY1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SUFF_SOUND_SLAY1); + break; + case 1: + DoYell(SUFF_SAY_SLAY2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SUFF_SOUND_SLAY2); + break; + case 2: + DoYell(SUFF_SAY_SLAY3,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SUFF_SOUND_SLAY3); + break; + } + } + + void JustDied(Unit* killer) + { + } + + void CastFixate() + { + std::list& m_threatlist = m_creature->getThreatManager().getThreatList(); + if(m_threatlist.empty()) + return; // No point continuing if empty threatlist. + std::list targets; + std::list::iterator itr = m_threatlist.begin(); + for( ; itr != m_threatlist.end(); ++itr) + { + Unit* pUnit = Unit::GetUnit((*m_creature), (*itr)->getUnitGuid()); + // Only alive players + if(pUnit && pUnit->isAlive() && (pUnit->GetTypeId() == TYPEID_PLAYER)) + targets.push_back(pUnit); + } + if(targets.empty()) + return; // No targets added for some reason. No point continuing. + targets.sort(TargetDistanceOrder(m_creature)); // Sort players by distance. + targets.resize(1); // Only need closest target. + Unit* target = targets.front(); // Get the first target. + // Add threat equivalent to threat on victim. + m_creature->AddThreat(target, m_creature->getThreatManager().getThreat(m_creature->getVictim())); + DoCast(target, SPELL_FIXATE); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(m_creature->GetHealth() <= (m_creature->GetMaxHealth()*0.1)) + { + if(StatAuraGUID) + { + Unit* pUnit = NULL; + pUnit = Unit::GetUnit((*m_creature), StatAuraGUID); + if(pUnit) + pUnit->RemoveAurasDueToSpell(AURA_OF_SUFFERING_ARMOR); + } + } + + if(m_creature->GetHealth() <= (m_creature->GetMaxHealth()*0.1)) + { + if(m_creature->getVictim()) + m_creature->DeleteThreatList(); // Delete our threatlist if below 10% as we should no longer attack. + return; + } + + // Prevent overlapping yells + if(AggroYellTimer) + if(AggroYellTimer < diff) + { + DoYell(SUFF_SAY_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SUFF_SOUND_AGGRO); + AggroYellTimer = 0; + }else AggroYellTimer -= diff; + + //Supposed to be cast on nearest target + if(FixateTimer < diff) + { + CastFixate(); + FixateTimer = 5000; + }else FixateTimer -= diff; + + if(EnrageTimer < diff) + { + DoCast(m_creature, SPELL_ENRAGE); + EnrageTimer = 60000; + }else EnrageTimer -= diff; + + if(SoulDrainTimer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + + if(target) + DoCast(target, SPELL_SOUL_DRAIN); + SoulDrainTimer = 60000; + }else SoulDrainTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; +struct MANGOS_DLL_DECL boss_essence_of_desireAI : public ScriptedAI +{ + boss_essence_of_desireAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 AggroYellTimer; + uint32 RuneShieldTimer; + uint32 DeadenTimer; + uint32 SoulShockTimer; + + void Reset() + { + AggroYellTimer = 5000; + RuneShieldTimer = 60000; + DeadenTimer = 15000; + SoulShockTimer = 40000; + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if((damage >= m_creature->GetHealth()) && (done_by != m_creature)) + { + damage = 0; + // 10% of total health, signalling time to return + m_creature->SetHealth(m_creature->GetMaxHealth()/10); + } + else + { + if(done_by && (done_by->GetTypeId() == TYPEID_PLAYER) && done_by->isAlive()) + done_by->DealDamage(done_by, damage/2, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + + void Aggro(Unit *who) { DoZoneInCombat(); } + + void KilledUnit(Unit *victim) + { + switch(rand()%3) + { + case 0: + DoYell(DESI_SAY_SLAY1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, DESI_SOUND_SLAY1); + break; + case 1: + DoYell(DESI_SAY_SLAY2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, DESI_SOUND_SLAY2); + break; + case 2: + DoYell(DESI_SAY_SLAY3,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, DESI_SOUND_SLAY3); + break; + } + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || m_creature->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + float attackRadius = m_creature->GetAttackDistance(who); + if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) + { + if(who->HasStealthAura()) + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + //Begin melee attack if we are within range + DoStartAttackAndMovement(who); + + if (!InCombat) + { + DoCast(who, AURA_OF_DESIRE); + } + } + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(m_creature->GetHealth() <= (m_creature->GetMaxHealth()*0.1)) + { + if(m_creature->getVictim()) + m_creature->DeleteThreatList(); // Delete our threatlist if below 10% as we should no longer attack. + return; + } + + if(RuneShieldTimer < diff) + { + DoCast(m_creature, SPELL_RUNE_SHIELD); + RuneShieldTimer = 60000; + }else RuneShieldTimer -= diff; + + if(DeadenTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_DEADEN); + DeadenTimer = 30000 + rand()%30001; + }else DeadenTimer -= diff; + + if(SoulShockTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_SOUL_SHOCK); + SoulShockTimer = 40000; + if(rand()%2 == 0) + { + DoYell(DESI_SAY_SPEC,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, DESI_SOUND_SPEC); + } + + }else SoulShockTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL boss_essence_of_angerAI : public ScriptedAI +{ + boss_essence_of_angerAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint64 AggroTargetGUID; + + uint32 AggroYellTimer; + uint32 CheckTankTimer; + uint32 SoulScreamTimer; + uint32 SpiteTimer; + + bool CheckedAggro; + + void Reset() + { + AggroTargetGUID = 0; + + AggroYellTimer = 5000; + CheckTankTimer = 5000; + SoulScreamTimer = 10000; + SpiteTimer = 30000; + + CheckedAggro = false; + } + + void Aggro(Unit *who) + { + DoZoneInCombat(); + DoCast(m_creature->getVictim(), AURA_OF_ANGER, true); + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || m_creature->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + float attackRadius = m_creature->GetAttackDistance(who); + if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) + { + if(who->HasStealthAura()) + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + //Begin melee attack if we are within range + DoStartAttackAndMovement(who); + + if (!InCombat) + { + DoCast(who, AURA_OF_ANGER); + } + } + } + } + + void JustDied(Unit *victim) + { + DoYell(ANGER_SAY_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,ANGER_SOUND_DEATH); + } + + void KilledUnit(Unit *victim) + { + switch(rand()%2) + { + case 0: + DoPlaySoundToSet(m_creature, ANGER_SOUND_SLAY1); + break; + case 1: + DoYell(ANGER_SAY_SLAY2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, ANGER_SOUND_SLAY2); + break; + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(!CheckedAggro) + { + AggroTargetGUID = m_creature->getVictim()->GetGUID(); + CheckedAggro = true; + } + + if(AggroYellTimer) + if(AggroYellTimer < diff) + { + DoYell(ANGER_SAY_FREED2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, ANGER_SOUND_FREED2); + AggroYellTimer = 0; + }else AggroYellTimer -= diff; + + if(CheckTankTimer < diff) + { + if(m_creature->getVictim()->GetGUID() != AggroTargetGUID) + { + DoYell(ANGER_SAY_BEFORE,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, ANGER_SOUND_BEFORE); + DoCast(m_creature, SPELL_SELF_SEETHE); + DoCast(m_creature->getVictim(), SPELL_ENEMY_SEETHE, true); + AggroTargetGUID = m_creature->getVictim()->GetGUID(); + } + CheckTankTimer = 2000; + }else CheckTankTimer -= diff; + + if(SoulScreamTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_SOUL_SCREAM); + SoulScreamTimer = 10000; + }else SoulScreamTimer -= diff; + + if(SpiteTimer < diff) + { + for(uint8 i = 0; i < 4; i++) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + + if(target) + DoCast(target, SPELL_SPITE); + + } + + SpiteTimer = 30000; + DoYell(ANGER_SAY_SPEC,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, ANGER_SOUND_SPEC); + }else SpiteTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +void npc_enslaved_soulAI::JustDied(Unit *killer) +{ + if(ReliquaryGUID) + { + Creature* Reliquary = ((Creature*)Unit::GetUnit((*m_creature), ReliquaryGUID)); + if(Reliquary) + ((boss_reliquary_of_soulsAI*)Reliquary->AI())->SoulDeathCount++; + } +} + +CreatureAI* GetAI_boss_reliquary_of_souls(Creature *_Creature) +{ + return new boss_reliquary_of_soulsAI (_Creature); +} + +CreatureAI* GetAI_boss_essence_of_suffering(Creature *_Creature) +{ + return new boss_essence_of_sufferingAI (_Creature); +} + +CreatureAI* GetAI_boss_essence_of_desire(Creature *_Creature) +{ + return new boss_essence_of_desireAI (_Creature); +} + +CreatureAI* GetAI_boss_essence_of_anger(Creature *_Creature) +{ + return new boss_essence_of_angerAI (_Creature); +} + +CreatureAI* GetAI_npc_enslaved_soul(Creature *_Creature) +{ + return new npc_enslaved_soulAI (_Creature); +} + +void AddSC_boss_reliquary_of_souls() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_reliquary_of_souls"; + newscript->GetAI = GetAI_boss_reliquary_of_souls; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_essence_of_suffering"; + newscript->GetAI = GetAI_boss_essence_of_suffering; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_essence_of_desire"; + newscript->GetAI = GetAI_boss_essence_of_desire; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_essence_of_anger"; + newscript->GetAI = GetAI_boss_essence_of_anger; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_enslaved_soul"; + newscript->GetAI = GetAI_npc_enslaved_soul; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/black_temple/boss_shade_of_akama.cpp b/src/bindings/scripts/scripts/zone/black_temple/boss_shade_of_akama.cpp new file mode 100644 index 00000000000..2f1034e2c08 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/black_temple/boss_shade_of_akama.cpp @@ -0,0 +1,813 @@ +/* Copyright (C) 2006,2007 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Shade_of_Akama +SD%Complete: 99 +SDComment: Seems to be complete. +SDCategory: Black Temple +EndScriptData */ + +#include "precompiled.h" +#include "def_black_temple.h" +#include "sc_grid_searchers.h" + +struct Location +{ + float x, y, o, z; +}; + +static Location ChannelerLocations[]= +{ + {463.161285, 401.219757, 3.141592}, + {457.377625, 391.227661, 2.106461}, + {446.012421, 391.227661, 1.071904}, + {439.533783, 401.219757, 0.000000}, + {446.012421, 411.211853, 5.210546}, + {457.377625, 411.211853, 4.177494} +}; + +static Location SpawnLocations[]= +{ + {498.652740, 461.728119, 0}, + {498.505003, 339.619324, 0} +}; + +static Location AkamaWP[]= +{ + {482.352448, 401.162720, 0, 112.783928}, + {469.597443, 402.264404, 0, 118.537910} +}; + +static Location BrokenCoords[]= +{ + {541.375916, 401.439575, M_PI, 112.783997}, // The place where Akama channels + {534.130005, 352.394531, 2.164150, 112.783737}, // Behind a 'pillar' which is behind the east alcove + {499.621185, 341.534729, 1.652856, 112.783730}, // East Alcove + {499.151093, 461.036438, 4.770888, 112.78370}, // West Alcove +}; + +static Location BrokenWP[]= +{ + {492.491638, 400.744690, 3.122336, 112.783737}, + {494.335724, 382.221771, 2.676230, 112.783737}, + {489.555939, 373.507202, 2.416263, 112.783737}, + {491.136353, 427.868774, 3.519748, 112.783737}, +}; + +// Locations +#define Z1 118.543144 +#define Z2 120.783768 +#define Z_SPAWN 113.537949 +#define AGGRO_X 482.793182 +#define AGGRO_Y 401.270172 +#define AGGRO_Z 112.783928 +#define AKAMA_X 514.583984 +#define AKAMA_Y 400.601013 +#define AKAMA_Z 112.783997 + +// Texts +#define SOUND_DEATH 11386 +#define SAY_DEATH "No! Not yet..." +#define SOUND_LOW_HEALTH 11385 +#define SAY_LOW_HEALTH "I will not last much longer..." + +// Ending cinematic text +#define SAY_FREE "Come out from the shadows! I've returned to lead you against our true enemy! Shed your chains and raise your weapons against your Illidari masters!" +#define SAY_BROKEN_FREE_01 "Hail our leader! Hail Akama!" +#define SAY_BROKEN_FREE_02 "Hail Akama!" + +// Gossips +#define GOSSIP_ITEM "We are ready to fight alongside you, Akama" + +// Spells +#define SPELL_VERTEX_SHADE_BLACK 39833 +#define SPELL_SHADE_SOUL_CHANNEL 40401 +#define SPELL_DESTRUCTIVE_POISON 40874 +#define SPELL_LIGHTNING_BOLT 42024 +#define SPELL_AKAMA_SOUL_CHANNEL 40447 +#define SPELL_AKAMA_SOUL_RETRIEVE 40902 +#define AKAMA_SOUL_EXPEL 40855 +#define SPELL_SHADE_SOUL_CHANNEL_2 40520 + +// Channeler entry +#define CREATURE_CHANNELER 23421 +#define CREATURE_SORCERER 23215 +#define CREATURE_DEFENDER 23216 +#define CREATURE_BROKEN 23319 + +const uint32 spawnEntries[4]= { 23523, 23318, 23524 }; + +struct MANGOS_DLL_DECL mob_ashtongue_channelerAI : public ScriptedAI +{ + mob_ashtongue_channelerAI(Creature* c) : ScriptedAI(c) { Reset(); } + + uint64 ShadeGUID; + + void Reset() { ShadeGUID = 0; } + void JustDied(Unit* killer); + void Aggro(Unit* who) {} + void AttackStart(Unit* who) {} + void MoveInLineOfSight(Unit* who) {} + void UpdateAI(const uint32 diff) {} +}; + +struct MANGOS_DLL_DECL mob_ashtongue_sorcererAI : public ScriptedAI +{ + mob_ashtongue_sorcererAI(Creature* c) : ScriptedAI(c) { Reset(); } + + uint64 ShadeGUID; + uint32 CheckTimer; + bool StartBanishing; + + void Reset() + { + StartBanishing = false; + CheckTimer = 5000; + ShadeGUID = 0; + } + + void JustDied(Unit* killer); + void Aggro(Unit* who) {} + void AttackStart(Unit* who) {} + void MoveInLineOfSight(Unit* who) {} + void UpdateAI(const uint32 diff) + { + if(StartBanishing) + return; + + if(CheckTimer < diff) + { + Unit* Shade = Unit::GetUnit((*m_creature), ShadeGUID); + if(Shade && Shade->isAlive() && m_creature->isAlive()) + { + if(m_creature->GetDistance2d(Shade) < 20) + { + m_creature->GetMotionMaster()->Clear(false); + m_creature->GetMotionMaster()->MoveIdle(); + DoCast(Shade, SPELL_SHADE_SOUL_CHANNEL, true); + DoCast(Shade, SPELL_SHADE_SOUL_CHANNEL_2, true); + + StartBanishing = true; + } + } + CheckTimer = 2000; + }else CheckTimer -= diff; + } +}; + +struct MANGOS_DLL_DECL boss_shade_of_akamaAI : public ScriptedAI +{ + boss_shade_of_akamaAI(Creature* c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + AkamaGUID = pInstance ? pInstance->GetData64(DATA_AKAMA_SHADE) : 0; + Reset(); + } + + ScriptedInstance* pInstance; + + std::list Channelers; + std::list Sorcerers; + uint64 AkamaGUID; + + uint32 SorcererCount; + uint32 DeathCount; + + uint32 ReduceHealthTimer; + uint32 SummonTimer; + uint32 ResetTimer; + uint32 DefenderTimer; // They are on a flat 15 second timer, independant of the other summon creature timer. + + bool IsBanished; + bool HasKilledAkama; + + void Reset() + { + FindChannelers(); + + if(!Channelers.empty()) + for(std::list::iterator itr = Channelers.begin(); itr != Channelers.end(); ++itr) + { + Creature* Channeler = NULL; + Channeler = ((Creature*)Unit::GetUnit(*m_creature, *itr)); + if(Channeler) + { + if(Channeler->isDead()) + { + Channeler->RemoveCorpse(); + Channeler->Respawn(); + } + Channeler->CastSpell(m_creature, SPELL_SHADE_SOUL_CHANNEL, true); + Channeler->CastSpell(m_creature, SPELL_SHADE_SOUL_CHANNEL_2, true); + Channeler->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + } + else error_log("SD2 ERROR: No Channelers are stored in the list. This encounter will not work properly"); + + if(!Sorcerers.empty()) + for(std::list::iterator itr = Sorcerers.begin(); itr != Sorcerers.end(); ++itr) + if(Creature* Sorcerer = ((Creature*)Unit::GetUnit(*m_creature, *itr))) + if(Sorcerer->isAlive()) + { + Sorcerer->SetVisibility(VISIBILITY_OFF); + Sorcerer->DealDamage(Sorcerer, Sorcerer->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + Sorcerers.clear(); + + if(Unit* Akama = Unit::GetUnit(*m_creature, AkamaGUID)) + Akama->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + + SorcererCount = 0; + DeathCount = 0; + + SummonTimer = 10000; + ReduceHealthTimer = 0; + ResetTimer = 60000; + DefenderTimer = 15000; + + IsBanished = true; + HasKilledAkama = false; + + m_creature->SetVisibility(VISIBILITY_ON); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MoveIdle(); + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_STUN); + + if(pInstance && m_creature->isAlive()) + pInstance->SetData(DATA_SHADEOFAKAMAEVENT, NOT_STARTED); + } + + void Aggro(Unit* who) { } + + void AttackStart(Unit* who) + { + if(!who || IsBanished) return; + + if(who->isTargetableForAttack() && who != m_creature) + DoStartAttackAndMovement(who); + } + + void MoveInLineOfSight(Unit* who) + { + if(IsBanished) return; + + ScriptedAI::MoveInLineOfSight(who); + } + + void IncrementDeathCount(uint64 guid = 0) // If guid is set, will remove it from list of sorcerer + { + debug_log("SD2: Increasing Death Count for Shade of Akama encounter"); + ++DeathCount; + m_creature->RemoveSingleAuraFromStack(SPELL_SHADE_SOUL_CHANNEL_2, 0); + if(guid) + { + if(Sorcerers.empty()) + error_log("SD2 ERROR: Shade of Akama - attempt to remove guid %u from Sorcerers list but list is already empty", guid); + else Sorcerers.remove(guid); + } + } + + void SummonCreature() + { + uint32 random = rand()%2; + float X = SpawnLocations[random].x; + float Y = SpawnLocations[random].y; + // max of 6 sorcerers can be summoned + if((rand()%3 == 0) && (DeathCount > 0) && (SorcererCount < 7)) + { + Creature* Sorcerer = m_creature->SummonCreature(CREATURE_SORCERER, X, Y, Z_SPAWN, 0, TEMPSUMMON_DEAD_DESPAWN, 0); + if(Sorcerer) + { + ((mob_ashtongue_sorcererAI*)Sorcerer->AI())->ShadeGUID = m_creature->GetGUID(); + Sorcerer->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + Sorcerer->GetMotionMaster()->MovePoint(0, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ()); + Sorcerer->SetUInt64Value(UNIT_FIELD_TARGET, m_creature->GetGUID()); + Sorcerers.push_back(Sorcerer->GetGUID()); + --DeathCount; + ++SorcererCount; + } + } + else + { + for(uint8 i = 0; i < 3; ++i) + { + Creature* Spawn = m_creature->SummonCreature(spawnEntries[i], X, Y, Z_SPAWN, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 25000); + if(Spawn) + { + Spawn->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + Spawn->GetMotionMaster()->MovePoint(0, AGGRO_X, AGGRO_Y, AGGRO_Z); + } + } + } + } + + void FindChannelers() + { + CellPair pair(MaNGOS::ComputeCellPair(m_creature->GetPositionX(), m_creature->GetPositionY())); + Cell cell(pair); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + std::list ChannelerList; + + AllCreaturesOfEntryInRange check(m_creature, CREATURE_CHANNELER, 50); + MaNGOS::CreatureListSearcher searcher(ChannelerList, check); + TypeContainerVisitor, GridTypeMapContainer> visitor(searcher); + + CellLock cell_lock(cell, pair); + cell_lock->Visit(cell_lock, visitor, *(m_creature->GetMap())); + + if(!ChannelerList.empty()) + { + Channelers.clear(); + for(std::list::iterator itr = ChannelerList.begin(); itr != ChannelerList.end(); ++itr) + { + ((mob_ashtongue_channelerAI*)(*itr)->AI())->ShadeGUID = m_creature->GetGUID(); + Channelers.push_back((*itr)->GetGUID()); + debug_log("SD2: Shade of Akama Grid Search found channeler %u. Adding to list", (*itr)->GetGUID()); + } + } + else error_log("SD2 ERROR: Grid Search was unable to find any channelers. Shade of Akama encounter will be buggy"); + } + + void SetSelectableChannelers() + { + if(Channelers.empty()) + { + error_log("SD2 ERROR: Channeler List is empty, Shade of Akama encounter will be buggy"); + return; + } + + for(std::list::iterator itr = Channelers.begin(); itr != Channelers.end(); ++itr) + if(Creature* Channeler = ((Creature*)Unit::GetUnit(*m_creature, *itr))) + Channeler->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void SetAkamaGUID(uint64 guid) { AkamaGUID = guid; } + + void UpdateAI(const uint32 diff) + { + if(!InCombat) + return; + + if(IsBanished) + { + // Akama is set in the threatlist so when we reset, we make sure that he is not included in our check + if(m_creature->getThreatManager().getThreatList().size() < 2) + EnterEvadeMode(); + + if(DefenderTimer < diff) + { + uint32 ran = rand()%2; + Creature* Defender = m_creature->SummonCreature(CREATURE_DEFENDER, SpawnLocations[ran].x, SpawnLocations[ran].y, Z_SPAWN, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 25000); + if(Defender) + { + Defender->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + bool move = true; + if(AkamaGUID) + { + if(Unit* Akama = Unit::GetUnit(*m_creature, AkamaGUID)) + { + float x, y, z; + Akama->GetPosition(x,y,z); + // They move towards AKama + Defender->GetMotionMaster()->MovePoint(0, x, y, z); + }else move = false; + }else move = false; + if(!move) + Defender->GetMotionMaster()->MovePoint(0, AKAMA_X, AKAMA_Y, AKAMA_Z); + } + DefenderTimer = 15000; + }else DefenderTimer -= diff; + + if(SummonTimer < diff) + { + SummonCreature(); + SummonTimer = 35000; + }else SummonTimer -= diff; + + if(DeathCount >= 6) + { + if(AkamaGUID) + { + Unit* Akama = Unit::GetUnit((*m_creature), AkamaGUID); + if(Akama && Akama->isAlive()) + { + IsBanished = false; + m_creature->GetMotionMaster()->Clear(false); + m_creature->GetMotionMaster()->MoveChase(Akama); + Akama->GetMotionMaster()->Clear(); + // Shade should move to Akama, not the other way around + Akama->GetMotionMaster()->MoveIdle(); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + // Crazy amount of threat + m_creature->AddThreat(Akama, 10000000.0f); + Akama->AddThreat(m_creature, 10000000.0f); + m_creature->Attack(Akama, true); + Akama->Attack(m_creature, true); + } + } + } + } + else // No longer banished, let's fight Akama now + { + if(ReduceHealthTimer < diff) + { + if(AkamaGUID) + { + Unit* Akama = Unit::GetUnit((*m_creature), AkamaGUID); + if(Akama && Akama->isAlive()) + { + //10 % less health every few seconds. + m_creature->DealDamage(Akama, Akama->GetMaxHealth()/10, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + ReduceHealthTimer = 12000; + } + else + { + HasKilledAkama = true; // Akama is dead or missing, we stop fighting and disappear + m_creature->SetVisibility(VISIBILITY_OFF); + m_creature->SetHealth(m_creature->GetMaxHealth()); + m_creature->RemoveAllAuras(); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + } + }else ReduceHealthTimer -= diff; + + if(HasKilledAkama) + { + if(ResetTimer < diff) + { + InCombat = false; + EnterEvadeMode(); // Reset a little while after killing Akama + } + else ResetTimer -= diff; + } + + DoMeleeAttackIfReady(); + } + } +}; + +void mob_ashtongue_channelerAI::JustDied(Unit* killer) +{ + Creature* Shade = ((Creature*)Unit::GetUnit((*m_creature), ShadeGUID)); + if(Shade && Shade->isAlive()) + ((boss_shade_of_akamaAI*)Shade->AI())->IncrementDeathCount(); + else error_log("SD2 ERROR: Channeler dead but unable to increment DeathCount for Shade of Akama."); +} + +void mob_ashtongue_sorcererAI::JustDied(Unit* killer) +{ + Creature* Shade = ((Creature*)Unit::GetUnit((*m_creature), ShadeGUID)); + if(Shade && Shade->isAlive()) + ((boss_shade_of_akamaAI*)Shade->AI())->IncrementDeathCount(m_creature->GetGUID()); + else error_log("SD2 ERROR: Sorcerer dead but unable to increment DeathCount for Shade of Akama."); +} + +struct MANGOS_DLL_DECL npc_akamaAI : public ScriptedAI +{ + npc_akamaAI(Creature* c) : ScriptedAI(c) + { + ShadeHasDied = false; + StartCombat = false; + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + ShadeGUID = pInstance ? pInstance->GetData64(DATA_SHADEOFAKAMA) : 0; + Reset(); + } + + ScriptedInstance* pInstance; + + uint64 ShadeGUID; + + uint32 DestructivePoisonTimer; + uint32 LightningBoltTimer; + uint32 CheckTimer; + uint32 CastSoulRetrieveTimer; + uint32 SoulRetrieveTimer; + uint32 SummonBrokenTimer; + uint32 EndingTalkCount; + uint32 WayPointId; + uint32 BrokenSummonIndex; + + std::list BrokenList; + + bool EventBegun; + bool ShadeHasDied; + bool StartCombat; + bool HasYelledOnce; + + void Reset() + { + DestructivePoisonTimer = 15000; + LightningBoltTimer = 10000; + CheckTimer = 2000; + CastSoulRetrieveTimer = 0; + SoulRetrieveTimer = 0; + SummonBrokenTimer = 0; + EndingTalkCount = 0; + WayPointId = 0; + BrokenSummonIndex = 0; + + BrokenList.clear(); + + EventBegun = false; + HasYelledOnce = false; + + m_creature->SetUInt32Value(UNIT_NPC_FLAGS, 0); // Database sometimes has very very strange values + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + } + + void Aggro(Unit* who) {} + + void BeginEvent(Player* pl) + { + if(!pInstance) + return; + + ShadeGUID = pInstance->GetData64(DATA_SHADEOFAKAMA); + if(!ShadeGUID) + return; + + Creature* Shade = ((Creature*)Unit::GetUnit((*m_creature), ShadeGUID)); + if(Shade) + { + pInstance->SetData(DATA_SHADEOFAKAMAEVENT, IN_PROGRESS); + // Prevent players from trying to restart event + m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + ((boss_shade_of_akamaAI*)Shade->AI())->SetAkamaGUID(m_creature->GetGUID()); + ((boss_shade_of_akamaAI*)Shade->AI())->SetSelectableChannelers(); + ((boss_shade_of_akamaAI*)Shade->AI())->InCombat = true; + Shade->AddThreat(m_creature, 1000000.0f); + Shade->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); + Shade->SetUInt64Value(UNIT_FIELD_TARGET, m_creature->GetGUID()); + if(pl) Shade->AddThreat(pl, 1.0f); + DoZoneInCombat(Shade); + EventBegun = true; + } + } + + void MovementInform(uint32 type, uint32 id) + { + if(type != POINT_MOTION_TYPE) + return; + + switch(id) + { + case 0: ++WayPointId; break; + + case 1: + if(Unit* Shade = Unit::GetUnit(*m_creature, ShadeGUID)) + { + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, ShadeGUID); + DoCast(Shade, SPELL_AKAMA_SOUL_RETRIEVE); + EndingTalkCount = 0; + SoulRetrieveTimer = 16000; + } + break; + } + } + + void JustDied(Unit* killer) + { + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_DEATH); + } + + void UpdateAI(const uint32 diff) + { + if(!EventBegun) + return; + + if ((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 15 && !HasYelledOnce) + { + DoYell(SAY_LOW_HEALTH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_LOW_HEALTH); + HasYelledOnce = true; + } + + if(ShadeGUID && !StartCombat) + { + Creature* Shade = ((Creature*)Unit::GetUnit((*m_creature), ShadeGUID)); + if(Shade && Shade->isAlive()) + { + if(((boss_shade_of_akamaAI*)Shade->AI())->IsBanished) + { + if(CastSoulRetrieveTimer < diff) + { + DoCast(Shade, SPELL_AKAMA_SOUL_CHANNEL); + CastSoulRetrieveTimer = 500; + }else CastSoulRetrieveTimer -= diff; + } + else + { + m_creature->InterruptNonMeleeSpells(false); + StartCombat = true; + } + } + } + + if(ShadeHasDied && (WayPointId == 1)) + { + if(pInstance) pInstance->SetData(DATA_SHADEOFAKAMAEVENT, DONE); + m_creature->GetMotionMaster()->MovePoint(WayPointId, AkamaWP[1].x, AkamaWP[1].y, AkamaWP[1].z); + ++WayPointId; + } + + if(!ShadeHasDied && StartCombat) + { + if(CheckTimer < diff) + { + if(ShadeGUID) + { + Unit* Shade = Unit::GetUnit((*m_creature), ShadeGUID); + if(Shade && !Shade->isAlive()) + { + ShadeHasDied = true; + WayPointId = 0; + m_creature->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); + m_creature->GetMotionMaster()->MovePoint(WayPointId, AkamaWP[0].x, AkamaWP[0].y, AkamaWP[0].z); + } + } + CheckTimer = 5000; + }else CheckTimer -= diff; + } + + if(SummonBrokenTimer && BrokenSummonIndex < 4) + if(SummonBrokenTimer <= diff) + { + for(uint8 i = 0; i < 4; ++i) + { + float x = BrokenCoords[BrokenSummonIndex].x + (i*5); + float y = BrokenCoords[BrokenSummonIndex].y + (1*5); + float z = BrokenCoords[BrokenSummonIndex].z; + float o = BrokenCoords[BrokenSummonIndex].o; + Creature* Broken = m_creature->SummonCreature(CREATURE_BROKEN, x, y, z, o, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 360000); + if(Broken) + { + float wx = BrokenWP[BrokenSummonIndex].x + (i*5); + float wy = BrokenWP[BrokenSummonIndex].y + (i*5); + float wz = BrokenWP[BrokenSummonIndex].z; + Broken->GetMotionMaster()->MovePoint(0, wx, wy, wz); + Broken->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + BrokenList.push_back(Broken->GetGUID()); + } + } + ++BrokenSummonIndex; + SummonBrokenTimer = 1000; + }else SummonBrokenTimer -= diff; + + if(SoulRetrieveTimer) + if(SoulRetrieveTimer <= diff) + { + switch(EndingTalkCount) + { + case 0: + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); + ++EndingTalkCount; + SoulRetrieveTimer = 2000; + SummonBrokenTimer = 1; + case 1: + DoYell(SAY_FREE, LANG_UNIVERSAL, NULL); + ++EndingTalkCount; + SoulRetrieveTimer = 25000; + break; + case 2: + if(!BrokenList.empty()) + { + bool Yelled = false; + for(std::list::iterator itr = BrokenList.begin(); itr != BrokenList.end(); ++itr) + if(Unit* pUnit = Unit::GetUnit(*m_creature, *itr)) + { + if(!Yelled) + { + pUnit->MonsterYell(SAY_BROKEN_FREE_01, LANG_UNIVERSAL, 0); + Yelled = true; + } + pUnit->HandleEmoteCommand(EMOTE_ONESHOT_KNEEL); + } + } + ++EndingTalkCount; + SoulRetrieveTimer = 1500; + break; + case 3: + if(!BrokenList.empty()) + for(std::list::iterator itr = BrokenList.begin(); itr != BrokenList.end(); ++itr) + if(Unit* pUnit = Unit::GetUnit(*m_creature, *itr)) + // This is the incorrect spell, but can't seem to find the right one. + pUnit->CastSpell(pUnit, 39656, true); + ++EndingTalkCount; + SoulRetrieveTimer = 5000; + case 4: + if(!BrokenList.empty()) + for(std::list::iterator itr = BrokenList.begin(); itr != BrokenList.end(); ++itr) + if(Unit* pUnit = Unit::GetUnit((*m_creature), *itr)) + pUnit->MonsterYell(SAY_BROKEN_FREE_02, LANG_UNIVERSAL, 0); + SoulRetrieveTimer = 0; + break; + } + }else SoulRetrieveTimer -= diff; + + if(!m_creature->getVictim() || !m_creature->SelectHostilTarget()) + return; + + if(DestructivePoisonTimer < diff) + { + // SPELL_DESTRUCTIVE_POISON is self-cast only for some reason so we make our target cast it on itself + m_creature->getVictim()->CastSpell(m_creature->getVictim(), SPELL_DESTRUCTIVE_POISON, true); + DestructivePoisonTimer = 15000; + }else DestructivePoisonTimer -= diff; + + if(LightningBoltTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_LIGHTNING_BOLT); + LightningBoltTimer = 10000; + }else LightningBoltTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_shade_of_akama(Creature *_Creature) +{ + return new boss_shade_of_akamaAI (_Creature); +} + +CreatureAI* GetAI_mob_ashtongue_channeler(Creature *_Creature) +{ + return new mob_ashtongue_channelerAI (_Creature); +} + +CreatureAI* GetAI_mob_ashtongue_sorcerer(Creature *_Creature) +{ + return new mob_ashtongue_sorcererAI (_Creature); +} + +CreatureAI* GetAI_npc_akama_shade(Creature *_Creature) +{ + return new npc_akamaAI (_Creature); +} + +bool GossipSelect_npc_akama(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if (action == GOSSIP_ACTION_INFO_DEF + 1) //Fight time + { + player->CLOSE_GOSSIP_MENU(); + ((npc_akamaAI*)_Creature->AI())->BeginEvent(player); + } + + return true; +} + +bool GossipHello_npc_akama(Player *player, Creature *_Creature) +{ + if(player->isAlive()) + { + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->SEND_GOSSIP_MENU(907, _Creature->GetGUID()); + } + + return true; +} + +void AddSC_boss_shade_of_akama() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_shade_of_akama"; + newscript->GetAI = GetAI_boss_shade_of_akama; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_ashtongue_channeler"; + newscript->GetAI = GetAI_mob_ashtongue_channeler; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_ashtongue_sorcerer"; + newscript->GetAI = GetAI_mob_ashtongue_sorcerer; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_akama_shade"; + newscript->GetAI = GetAI_npc_akama_shade; + newscript->pGossipHello = &GossipHello_npc_akama; + newscript->pGossipSelect = &GossipSelect_npc_akama; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/black_temple/boss_supremus.cpp b/src/bindings/scripts/scripts/zone/black_temple/boss_supremus.cpp new file mode 100644 index 00000000000..f3b06ea6940 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/black_temple/boss_supremus.cpp @@ -0,0 +1,406 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Supremus +SD%Complete: 95 +SDComment: Need to implement doors. +SDCategory: Black Temple +EndScriptData */ + +#include "precompiled.h" +#include "def_black_temple.h" + +//Spells +#define SPELL_HURTFUL_STRIKE 41926 +#define SPELL_DEMON_FIRE 40029 +#define SPELL_MOLTEN_FLAME 40253 +#define SPELL_VOLCANIC_ERUPTION 40276 +#define SPELL_VOLCANIC_FIREBALL 40118 +#define SPELL_VOLCANIC_GEYSER 42055 +#define SPELL_MOLTEN_PUNCH 40126 +#define SPELL_BERSERK 45078 + +#define CREATURE_VOLCANO 23085 +#define CREATURE_STALKER 23095 + +struct MANGOS_DLL_DECL molten_flameAI : public ScriptedAI +{ + molten_flameAI(Creature *c) : ScriptedAI(c) + { + Reset(); + } + + uint64 SupremusGUID; + bool TargetLocked; + uint32 CheckTimer; + + void Reset() + { + SupremusGUID = 0; + TargetLocked = false; + + CheckTimer = 1000; + } + + void Aggro(Unit *who) {} + void AttackStart(Unit* who) {} + void MoveInLineOfSight(Unit *who) + { + if(TargetLocked) + return; // stop it from aggroing players who move in LOS if we have a target. + if(who && (who != m_creature) && (m_creature->IsWithinDistInMap(who, 10))) + StalkTarget(who); + } + + void SetSupremusGUID(uint64 GUID) { SupremusGUID = GUID; } + + void StalkTarget(Unit* target) + { + if(!target) return; + + m_creature->AddThreat(target, 50000000.0f); + m_creature->GetMotionMaster()->MoveChase(target); + DoCast(m_creature, SPELL_DEMON_FIRE, true); + // DoCast(m_creature, SPELL_MOLTEN_FLAME, true); // This spell damages self, so disabled for now + TargetLocked = true; + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget()) + return; + + if(m_creature->getVictim() && m_creature->isAlive()) + { + if(CheckTimer < diff) + { + if(SupremusGUID) + { + Unit* Supremus = NULL; + Supremus = Unit::GetUnit((*m_creature), SupremusGUID); + if(Supremus && (!Supremus->isAlive())) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), 0, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + CheckTimer = 2000; + }else CheckTimer -= diff; + } + } +}; + +struct MANGOS_DLL_DECL npc_volcanoAI : public ScriptedAI +{ + npc_volcanoAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 CheckTimer; + uint64 SupremusGUID; + uint32 FireballTimer; + uint32 GeyserTimer; + + void Reset() + { + CheckTimer = 1000; + SupremusGUID = 0; + FireballTimer = 500; + GeyserTimer = 0; + } + + void Aggro(Unit *who) {} + void AttackStart(Unit* who) {} + void MoveInLineOfSight(Unit* who) {} + void SetSupremusGUID(uint64 guid) { SupremusGUID = guid; } + + void UpdateAI(const uint32 diff) + { + if(CheckTimer < diff) + { + if(SupremusGUID) + { + Unit* Supremus = NULL; + Supremus = Unit::GetUnit((*m_creature), SupremusGUID); + if(Supremus && (!Supremus->isAlive())) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), 0, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + CheckTimer = 2000; + }else CheckTimer -= diff; + + if(GeyserTimer < diff) + { + DoCast(m_creature, SPELL_VOLCANIC_GEYSER); + GeyserTimer = 18000; + }else GeyserTimer -= diff; + } +}; + +struct MANGOS_DLL_DECL boss_supremusAI : public ScriptedAI +{ + boss_supremusAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + + uint32 SummonFlameTimer; + uint32 SwitchTargetTimer; + uint32 PhaseSwitchTimer; + uint32 SummonVolcanoTimer; + uint32 HurtfulStrikeTimer; + uint32 BerserkTimer; + + bool Phase1; + + void Reset() + { + if(pInstance) + { + if(m_creature->isAlive()) + { + pInstance->SetData(DATA_SUPREMUSEVENT, NOT_STARTED); + ToggleDoors(true); + } + else ToggleDoors(false); + } + + HurtfulStrikeTimer = 5000; + SummonFlameTimer = 20000; + SwitchTargetTimer = 90000; + PhaseSwitchTimer = 60000; + SummonVolcanoTimer = 5000; + BerserkTimer = 900000; // 15 minute enrage + + Phase1 = true; + } + + void Aggro(Unit *who) + { + DoZoneInCombat(); + + if(pInstance) + pInstance->SetData(DATA_SUPREMUSEVENT, IN_PROGRESS); + } + + void ToggleDoors(bool close) + { + if(GameObject* Doors = GameObject::GetGameObject(*m_creature, pInstance->GetData64(DATA_GAMEOBJECT_SUPREMUS_DOORS))) + { + if(close) Doors->SetGoState(1); // Closed + else Doors->SetGoState(0); // Open + } + } + + void JustDied(Unit *killer) + { + if(pInstance) + { + pInstance->SetData(DATA_SUPREMUSEVENT, DONE); + ToggleDoors(false); + } + } + + float CalculateRandomCoord(float initial) + { + float coord = 0; + + switch(rand()%2) + { + case 0: coord = initial + 20 + rand()%20; break; + case 1: coord = initial - 20 - rand()%20; break; + } + + return coord; + } + + Creature* SummonCreature(uint32 entry, Unit* target) + { + if(target && entry) + { + Creature* Summon = m_creature->SummonCreature(entry, CalculateRandomCoord(target->GetPositionX()), CalculateRandomCoord(target->GetPositionY()), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 20000); + if(Summon) + { + Summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Summon->setFaction(m_creature->getFaction()); + return Summon; + } + } + return NULL; + } + + Unit* CalculateHurtfulStrikeTarget() + { + uint32 health = 0; + Unit* target = NULL; + + std::list& m_threatlist = m_creature->getThreatManager().getThreatList(); + std::list::iterator i = m_threatlist.begin(); + for (i = m_threatlist.begin(); i!= m_threatlist.end();++i) + { + Unit* pUnit = Unit::GetUnit((*m_creature), (*i)->getUnitGuid()); + if(pUnit && m_creature->IsWithinDistInMap(pUnit, ATTACK_DISTANCE)) + { + if(pUnit->GetHealth() > health) + { + health = pUnit->GetHealth(); + target = pUnit; + } + } + } + + return target; + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(!m_creature->HasAura(SPELL_BERSERK, 0)) + if(BerserkTimer < diff) + DoCast(m_creature, SPELL_BERSERK); + else BerserkTimer -= diff; + + if(SummonFlameTimer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM, 1); + + if(!target) // someone is trying to solo, set target as current victim. + target = m_creature->getVictim(); + + if(target) + { + Creature* MoltenFlame = SummonCreature(CREATURE_STALKER, target); + if(MoltenFlame) + { + // Invisible model + MoltenFlame->SetUInt32Value(UNIT_FIELD_DISPLAYID, 11686); + ((molten_flameAI*)MoltenFlame->AI())->SetSupremusGUID(m_creature->GetGUID()); + ((molten_flameAI*)MoltenFlame->AI())->StalkTarget(target); + SummonFlameTimer = 20000; + } + } + }else SummonFlameTimer -= diff; + + if(Phase1) + { + if(HurtfulStrikeTimer < diff) + { + Unit* target = CalculateHurtfulStrikeTarget(); + if(target) + { + DoCast(target, SPELL_HURTFUL_STRIKE); + HurtfulStrikeTimer = 5000; + } + }else HurtfulStrikeTimer -= diff; + } + + if(!Phase1) + { + if(SwitchTargetTimer < diff) + { + Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target) + { + DoResetThreat(); + m_creature->AddThreat(target, 5000000.0f); + DoTextEmote("acquires a new target!", NULL); + SwitchTargetTimer = 10000; + } + + }else SwitchTargetTimer -= diff; + + if(SummonVolcanoTimer < diff) + { + Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1); + + if(!target) + target = m_creature->getVictim(); + + if(target) + { + Creature* Volcano = NULL; + Volcano = SummonCreature(CREATURE_VOLCANO, target); + + if(Volcano) + { + DoCast(target, SPELL_VOLCANIC_ERUPTION); + ((npc_volcanoAI*)Volcano->AI())->SetSupremusGUID(m_creature->GetGUID()); + } + + DoTextEmote("roars and the ground begins to crack open!", NULL); + SummonVolcanoTimer = 10000; + } + }else SummonVolcanoTimer -= diff; + } + + if(PhaseSwitchTimer < diff) + { + if(!Phase1) + { + Phase1 = true; + DoResetThreat(); + PhaseSwitchTimer = 60000; + m_creature->SetSpeed(MOVE_RUN, 1.0f); + } + else + { + Phase1 = false; + DoResetThreat(); + SwitchTargetTimer = 10000; + SummonVolcanoTimer = 2000; + PhaseSwitchTimer = 60000; + m_creature->SetSpeed(MOVE_RUN, 0.9f); + } + }else PhaseSwitchTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_supremus(Creature *_Creature) +{ + return new boss_supremusAI (_Creature); +} + +CreatureAI* GetAI_molten_flame(Creature *_Creature) +{ + return new molten_flameAI (_Creature); +} + +CreatureAI* GetAI_npc_volcano(Creature *_Creature) +{ + return new npc_volcanoAI (_Creature); +} + +void AddSC_boss_supremus() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_supremus"; + newscript->GetAI = GetAI_boss_supremus; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="molten_flame"; + newscript->GetAI = GetAI_molten_flame; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_volcano"; + newscript->GetAI = GetAI_npc_volcano; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/black_temple/boss_teron_gorefiend.cpp b/src/bindings/scripts/scripts/zone/black_temple/boss_teron_gorefiend.cpp new file mode 100644 index 00000000000..9c1182cfd0e --- /dev/null +++ b/src/bindings/scripts/scripts/zone/black_temple/boss_teron_gorefiend.cpp @@ -0,0 +1,589 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Teron_Gorefiend +SD%Complete: 60 +SDComment: Requires Mind Control support for Ghosts. +SDCategory: Black Temple +EndScriptData */ + +#include "precompiled.h" +#include "def_black_temple.h" + +//Spells +#define SPELL_INCINERATE 40239 +#define SPELL_CRUSHING_SHADOWS 40243 +#define SPELL_SHADOWBOLT 40185 +#define SPELL_PASSIVE_SHADOWFORM 40326 +#define SPELL_SHADOW_OF_DEATH 40251 +#define SPELL_BERSERK 45078 + +#define SPELL_ATROPHY 40327 // Shadowy Constructs use this when they get within melee range of a player + +//Speech'n'sound +#define SAY_INTRO "I was the first, you know. For me, the wheel of death has spun many times. So much time has passed. I have a lot of catching up to do..." +#define SOUND_INTRO 11512 + +#define SAY_AGGRO "Vengeance is mine!" +#define SOUND_AGGRO 11513 + +#define SAY_SLAY1 "I have use for you!" +#define SOUND_SLAY1 11514 + +#define SAY_SLAY2 "It gets worse..." +#define SOUND_SLAY2 11515 + +#define SAY_SPELL1 "What are you afraid of?" +#define SOUND_SPELL1 11517 + +#define SAY_SPELL2 "Death... really isn't so bad." +#define SOUND_SPELL2 11516 + +#define SAY_SPECIAL1 "Give in!" +#define SOUND_SPECIAL1 11518 + +#define SAY_SPECIAL2 "I have something for you..." +#define SOUND_SPECIAL2 11519 + +#define SAY_ENRAGE "YOU WILL SHOW THE PROPER RESPECT!" +#define SOUND_ENRAGE 11520 + +#define SAY_DEATH "The wheel...spins...again...." +#define SOUND_DEATH 11521 + +#define CREATURE_DOOM_BLOSSOM 23123 +#define CREATURE_SHADOWY_CONSTRUCT 23111 + +struct MANGOS_DLL_DECL mob_doom_blossomAI : public ScriptedAI +{ + mob_doom_blossomAI(Creature *c) : ScriptedAI(c) + { + Reset(); + } + + uint32 CheckTeronTimer; + uint32 ShadowBoltTimer; + uint64 TeronGUID; + + void Reset() + { + CheckTeronTimer = 5000; + ShadowBoltTimer = 12000; + TeronGUID = 0; + } + + void Aggro(Unit *who) { } + void AttackStart(Unit* who) { } + void MoveInLineOfSight(Unit* who) { } + + void UpdateAI(const uint32 diff) + { + if(CheckTeronTimer < diff) + { + if(TeronGUID) + { + DoZoneInCombat(); + + Creature* Teron = ((Creature*)Unit::GetUnit((*m_creature), TeronGUID)); + if((Teron) && (!Teron->isAlive() || Teron->IsInEvadeMode())) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + else + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + + CheckTeronTimer = 5000; + }else CheckTeronTimer -= diff; + + if(!m_creature->getVictim() || !m_creature->SelectHostilTarget()) + return; + + if(ShadowBoltTimer < diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_SHADOWBOLT); + ShadowBoltTimer = 10000; + }else ShadowBoltTimer -= diff; + } + + void SetTeronGUID(uint64 guid){ TeronGUID = guid; } +}; + +//This is used to sort the players by distance for Constructs to see who to cast Atrophy on +struct TargetDistanceOrder : public std::binary_function +{ + const Unit* MainTarget; + TargetDistanceOrder(const Unit* Target) : MainTarget(Target) {}; + // functor for operator "<" + bool operator()(const Unit* _Left, const Unit* _Right) const + { + return (MainTarget->GetDistance(_Left) < MainTarget->GetDistance(_Right)); + } +}; + +struct MANGOS_DLL_DECL mob_shadowy_constructAI : public ScriptedAI +{ + mob_shadowy_constructAI(Creature* c) : ScriptedAI(c) + { + Reset(); + } + + uint64 GhostGUID; + uint64 TeronGUID; + + uint32 CheckPlayerTimer; + uint32 CheckTeronTimer; + + void Reset() + { + GhostGUID = 0; + TeronGUID = 0; + + CheckPlayerTimer = 2000; + CheckTeronTimer = 5000; + } + + void Aggro(Unit* who) { } + + void MoveInLineOfSight(Unit *who) + { + if(!who || (!who->isAlive()) || (who->GetGUID() == GhostGUID)) + return; + + if(who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + float attackRadius = m_creature->GetAttackDistance(who); + + if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) + { + if(who->HasStealthAura()) + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + m_creature->AddThreat(who, 1.0f); + } + } + } + +/* Comment it out for now. NOTE TO FUTURE DEV: UNCOMMENT THIS OUT ONLY AFTER MIND CONTROL IS IMPLEMENTED + void DamageTaken(Unit* done_by, uint32 &damage) + { + if(done_by->GetGUID() != GhostGUID) + damage = 0; // Only the ghost can deal damage. + } + */ + + void CheckPlayers() + { + std::list& m_threatlist = m_creature->getThreatManager().getThreatList(); + if(m_threatlist.empty()) + return; // No threat list. Don't continue. + std::list::iterator itr = m_threatlist.begin(); + std::list targets; + for( ; itr != m_threatlist.end(); ++itr) + { + Unit* pUnit = Unit::GetUnit((*m_creature), (*itr)->getUnitGuid()); + if(pUnit && pUnit->isAlive()) + targets.push_back(pUnit); + } + targets.sort(TargetDistanceOrder(m_creature)); + Unit* target = targets.front(); + if(target && m_creature->IsWithinDistInMap(target, m_creature->GetAttackDistance(target))) + { + DoCast(target, SPELL_ATROPHY); + m_creature->AI()->AttackStart(target); + } + } + + void UpdateAI(const uint32 diff) + { + if(CheckPlayerTimer < diff) + { + CheckPlayers(); + CheckPlayerTimer = 3000; + }else CheckPlayerTimer -= diff; + + if(CheckTeronTimer < diff) + { + Creature* Teron = ((Creature*)Unit::GetUnit((*m_creature), TeronGUID)); + if(!Teron || !Teron->isAlive() || Teron->IsInEvadeMode()) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + + CheckTeronTimer = 5000; + }else CheckTeronTimer -= diff; + } +}; + +struct MANGOS_DLL_DECL boss_teron_gorefiendAI : public ScriptedAI +{ + boss_teron_gorefiendAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + + uint32 IncinerateTimer; + uint32 SummonDoomBlossomTimer; + uint32 EnrageTimer; + uint32 CrushingShadowsTimer; + uint32 ShadowOfDeathTimer; + uint32 SummonShadowsTimer; + uint32 RandomYellTimer; + uint32 AggroTimer; + + uint64 AggroTargetGUID; + uint64 GhostGUID; // Player that gets killed by Shadow of Death and gets turned into a ghost + + bool Intro; + + void Reset() + { + if(pInstance) + pInstance->SetData(DATA_TERONGOREFIENDEVENT, NOT_STARTED); + + IncinerateTimer = 20000 + rand()%11000; + SummonDoomBlossomTimer = 12000; + EnrageTimer = 600000; + CrushingShadowsTimer = 22000; + SummonShadowsTimer = 60000; + RandomYellTimer = 50000; + + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + // Start off unattackable so that the intro is done properly + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + AggroTimer = 20000; + AggroTargetGUID = 0; + Intro = false; + } + + void Aggro(Unit *who) {} + + void MoveInLineOfSight(Unit *who) + { + if(!who || (!who->isAlive())) return; + + if(who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + float attackRadius = m_creature->GetAttackDistance(who); + + if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) + { + if(who->HasStealthAura()) + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + m_creature->AddThreat(who, 1.0f); + } + + if(!InCombat && !Intro && m_creature->IsWithinDistInMap(who, 200.0f) && (who->GetTypeId() == TYPEID_PLAYER)) + { + if(pInstance) + pInstance->SetData(DATA_TERONGOREFIENDEVENT, IN_PROGRESS); + + m_creature->GetMotionMaster()->Clear(false); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoYell(SAY_INTRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_INTRO); + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_TALK); + AggroTargetGUID = who->GetGUID(); + Intro = true; + } + } + } + + void KilledUnit(Unit *victim) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_SLAY1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY1); + break; + case 1: + DoYell(SAY_SLAY2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY2); + break; + } + } + + void JustDied(Unit *victim) + { + if(pInstance) + pInstance->SetData(DATA_TERONGOREFIENDEVENT, DONE); + + DoYell(SAY_DEATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_DEATH); + } + + float CalculateRandomLocation(float Loc, uint32 radius) + { + float coord = Loc; + switch(rand()%2) + { + case 0: + coord += rand()%radius; + break; + case 1: + coord -= rand()%radius; + break; + } + return coord; + } + + void SetThreatList(Creature* Blossom) + { + if(!Blossom) return; + + std::list& m_threatlist = m_creature->getThreatManager().getThreatList(); + std::list::iterator i = m_threatlist.begin(); + for(i = m_threatlist.begin(); i != m_threatlist.end(); i++) + { + Unit* pUnit = Unit::GetUnit((*m_creature), (*i)->getUnitGuid()); + if(pUnit && pUnit->isAlive()) + { + float threat = m_creature->getThreatManager().getThreat(pUnit); + Blossom->AddThreat(pUnit, threat); + } + } + } + + void MindControlGhost() + { + /************************************************************************/ + /** NOTE FOR FUTURE DEVELOPER: PROPERLY IMPLEMENT THE GHOST PORTION *****/ + /** ONLY AFTER MaNGOS FULLY IMPLEMENTS MIND CONTROL ABILITIES *****/ + /** THE CURRENT CODE IN THIS FUNCTION IS ONLY THE BEGINNING OF *****/ + /** WHAT IS FULLY NECESSARY FOR GOREFIEND TO BE 100% COMPLETE *****/ + /************************************************************************/ + + Unit* Ghost = NULL; + if(GhostGUID) + Ghost = Unit::GetUnit((*m_creature), GhostGUID); + if(Ghost && Ghost->isAlive() && Ghost->HasAura(SPELL_SHADOW_OF_DEATH, 0)) + { + /*float x,y,z; + Ghost->GetPosition(x,y,z); + Creature* control = m_creature->SummonCreature(CREATURE_GHOST, x, y, z, 0, TEMPSUMMON_TIMED_DESAWN, 30000); + if(control) + { + ((Player*)Ghost)->Possess(control); + Ghost->DealDamage(Ghost, Ghost->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, + false); + }*/ + for(uint8 i = 0; i < 4; ++i) + { + Creature* Construct = NULL; + float X = CalculateRandomLocation(Ghost->GetPositionX(), 10); + float Y = CalculateRandomLocation(Ghost->GetPositionY(), 10); + Construct = m_creature->SummonCreature(CREATURE_SHADOWY_CONSTRUCT, X, Y, Ghost->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 45000); + if(Construct) + { + Construct->CastSpell(Construct, SPELL_PASSIVE_SHADOWFORM, true); + SetThreatList(Construct); // Use same function as Doom Blossom to set Threat List. + ((mob_shadowy_constructAI*)Construct->AI())->GhostGUID = GhostGUID; + Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1); + if(!target) // someone's trying to solo. + target = m_creature->getVictim(); + + if(target) + Construct->GetMotionMaster()->MoveChase(target); + } + } + } + } + + void UpdateAI(const uint32 diff) + { + if(Intro) + { + if(AggroTimer < diff) + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO); + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); + Intro = false; + if(AggroTargetGUID) + { + Unit* pUnit = Unit::GetUnit((*m_creature), AggroTargetGUID); + if(pUnit) + { + m_creature->GetMotionMaster()->MoveChase(pUnit); + AttackStart(pUnit); + } + DoZoneInCombat(); + }else EnterEvadeMode(); + + }else AggroTimer -= diff; + } + + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim() || Intro) + return; + + if(SummonShadowsTimer < diff) + { + //MindControlGhost(); + + for(uint8 i = 0; i < 2; ++i) + { + Creature* Shadow = NULL; + float X = CalculateRandomLocation(m_creature->GetPositionX(), 10); + Shadow = m_creature->SummonCreature(CREATURE_SHADOWY_CONSTRUCT, X, m_creature->GetPositionY(), m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 0); + if(Shadow) + { + Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1); + if(!target) + target = m_creature->getVictim(); + + if(target) + Shadow->AI()->AttackStart(target); + } + } + SummonShadowsTimer = 60000; + }else SummonShadowsTimer -= diff; + + if(SummonDoomBlossomTimer < diff) + { + Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target) + { + float X = CalculateRandomLocation(target->GetPositionX(), 20); + float Y = CalculateRandomLocation(target->GetPositionY(), 20); + Creature* DoomBlossom = m_creature->SummonCreature(CREATURE_DOOM_BLOSSOM, X, Y, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 20000); + if(DoomBlossom) + { + DoomBlossom->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoomBlossom->setFaction(m_creature->getFaction()); + DoomBlossom->AddThreat(target, 1.0f); + ((mob_doom_blossomAI*)DoomBlossom->AI())->SetTeronGUID(m_creature->GetGUID()); + ((mob_doom_blossomAI*)DoomBlossom->AI())->InCombat = true; + SetThreatList(DoomBlossom); + SummonDoomBlossomTimer = 35000; + } + } + }else SummonDoomBlossomTimer -= diff; + + if(IncinerateTimer < diff) + { + Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1); + if(!target) + target = m_creature->getVictim(); + + if(target) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_SPECIAL1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SPECIAL1); + break; + case 1: + DoYell(SAY_SPECIAL2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SPECIAL2); + break; + } + DoCast(target, SPELL_INCINERATE); + IncinerateTimer = 20000 + rand()%31 * 1000; + } + }else IncinerateTimer -= diff; + + if(CrushingShadowsTimer < diff) + { + Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target && target->isAlive()) + DoCast(target, SPELL_CRUSHING_SHADOWS); + CrushingShadowsTimer = 10000 + rand()%16 * 1000; + }else CrushingShadowsTimer -= diff; + + /*** NOTE FOR FUTURE DEV: UNCOMMENT BELOW ONLY IF MIND CONTROL IS FULLY IMPLEMENTED **/ + /*if(ShadowOfDeathTimer < diff) + { + Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1); + + if(!target) + target = m_creature->getVictim(); + + if(target && target->isAlive() && target->GetTypeId() == TYPEID_PLAYER) + { + DoCast(target, SPELL_SHADOW_OF_DEATH); + GhostGUID = target->GetGUID(); + ShadowOfDeathTimer = 30000; + SummonShadowsTimer = 53000; // Make it VERY close but slightly less so that we can check if the aura is still on the player + } + }else ShadowOfDeathTimer -= diff;*/ + + if(RandomYellTimer < diff) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_SPELL1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SPELL1); + break; + case 1: + DoYell(SAY_SPELL2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SPELL2); + break; + } + RandomYellTimer = 50000 + rand()%51 * 1000; + }else RandomYellTimer -= diff; + + if(!m_creature->HasAura(SPELL_BERSERK, 0)) + if(EnrageTimer < diff) + { + DoCast(m_creature, SPELL_BERSERK); + DoYell(SAY_ENRAGE,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_ENRAGE); + }else EnrageTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_doom_blossom(Creature *_Creature) +{ + return new mob_doom_blossomAI(_Creature); +} + +CreatureAI* GetAI_mob_shadowy_construct(Creature *_Creature) +{ + return new mob_shadowy_constructAI(_Creature); +} + +CreatureAI* GetAI_boss_teron_gorefiend(Creature *_Creature) +{ + return new boss_teron_gorefiendAI (_Creature); +} + +void AddSC_boss_teron_gorefiend() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "mob_doom_blossom"; + newscript->GetAI = GetAI_mob_doom_blossom; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name = "mob_shadowy_construct"; + newscript->GetAI = GetAI_mob_shadowy_construct; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_teron_gorefiend"; + newscript->GetAI = GetAI_boss_teron_gorefiend; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/black_temple/boss_warlord_najentus.cpp b/src/bindings/scripts/scripts/zone/black_temple/boss_warlord_najentus.cpp new file mode 100644 index 00000000000..93d27c3d0d1 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/black_temple/boss_warlord_najentus.cpp @@ -0,0 +1,435 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Warlord_Najentus +SD%Complete: 90 +SDComment: Using a creature workaround instead of a GO for Impaling Spine. +SDCategory: Black Temple +EndScriptData */ + +#include "precompiled.h" +#include "def_black_temple.h" + +//Aggro +#define SAY_AGGRO "You will die, in the name of Lady Vashj!" +#define SOUND_AGGRO 11450 + +//Needle (Random) +#define SAY_NEEDLE1 "Stick around!" +#define SOUND_NEEDLE1 11451 + +#define SAY_NEEDLE2 "I'll deal with you later!" +#define SOUND_NEEDLE2 11452 + +//Slay +#define SAY_SLAY1 "Your success was short lived!" +#define SOUND_SLAY1 11455 + +#define SAY_SLAY2 "Time for you to go!" +#define SOUND_SLAY2 11456 + +//Special +#define SAY_SPECIAL1 "Bel'anen dal'lorei!" +#define SOUND_SPECIAL1 11453 + +#define SAY_SPECIAL2 "Blood will flow!" +#define SOUND_SPECIAL2 11454 + +//Enrage +#define SAY_ENRAGE "My patience has ran out! Die, DIE!" +#define SOUND_ENRAGE 11458 + +//Death +#define SAY_DEATH "Lord Illidan will... crush you." +#define SOUND_DEATH 11459 + +//Spells +#define SPELL_CRASHINGWAVE 40100 +#define SPELL_NEEDLE_SPINE 39835 +#define SPELL_NEEDLE_AOE 39968 +#define SPELL_TIDAL_BURST 39878 +#define SPELL_TIDAL_SHIELD 39872 // Not going to use this since Hurl Spine doesn't dispel it. +#define SPELL_IMPALING_SPINE 39837 +#define SPELL_CREATE_NAJENTUS_SPINE 39956 +#define SPELL_HURL_SPINE 39948 +#define SPELL_SHIELD_VISUAL 37136 +#define SPELL_BERSERK 45078 + +#define DISPLAYID_SPINE 7362 + +struct MANGOS_DLL_DECL mob_najentus_spineAI : public ScriptedAI +{ + mob_najentus_spineAI(Creature *c) : ScriptedAI(c) + { + Reset(); + } + + uint64 SpineVictimGUID; + + void Reset() { SpineVictimGUID = 0; } + + void SetSpineVictimGUID(uint64 guid){ SpineVictimGUID = guid; } + + void JustDied(Unit *killer) + { + // Make the killer have the Najentus Spine item to pierce Tidal Shield + if(killer) + killer->CastSpell(killer, SPELL_CREATE_NAJENTUS_SPINE, true); + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if(damage < m_creature->GetHealth()) return; + + // Remove the Impaling Spine DoT from whoever was affected + if(SpineVictimGUID) + { + Unit* victim = Unit::GetUnit((*m_creature), SpineVictimGUID); + if(victim && ((victim->HasAura(SPELL_IMPALING_SPINE, 0)) || (victim->HasAura(SPELL_IMPALING_SPINE, 1)) || (victim->HasAura(SPELL_IMPALING_SPINE, 2)))) + victim->RemoveAurasDueToSpell(SPELL_IMPALING_SPINE); + } + } + + void Aggro(Unit* who) {} + void AttackStart(Unit* who) {} + void MoveInLineOfSight(Unit* who) {} + void UpdateAI(const uint32 diff) {} +}; + +struct MANGOS_DLL_DECL boss_najentusAI : public ScriptedAI +{ + boss_najentusAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + uint32 CrashingWaveTimer; + uint32 NeedleSpineTimer; + uint32 EnrageTimer; + uint32 SpecialYellTimer; + uint32 TidalShieldTimer; + uint32 ImpalingSpineTimer; + uint32 CheckTimer; // This timer checks if Najentus is Tidal Shielded and if so, regens health. If not, sets IsShielded to false + uint32 DispelShieldTimer; // This shield is only supposed to last 30 seconds, but the SPELL_SHIELD_VISUAL lasts forever + + uint64 SpineTargetGUID; + uint64 SpineGUID; + + bool IsShielded; + + void Reset() + { + IsShielded = false; + + CrashingWaveTimer = 28000; + NeedleSpineTimer = 10000; + EnrageTimer = 480000; + SpecialYellTimer = 45000 + (rand()%76)*1000; + TidalShieldTimer = 60000; + ImpalingSpineTimer = 45000; + CheckTimer = 2000; + DispelShieldTimer = 30000; + + SpineTargetGUID = 0; + SpineGUID = 0; + + if(pInstance) + { + if(m_creature->isAlive()) + { + pInstance->SetData(DATA_HIGHWARLORDNAJENTUSEVENT, NOT_STARTED); + ToggleGate(true); + } + else ToggleGate(false); + } + } + + void KilledUnit(Unit *victim) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_SLAY1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY1); + break; + case 1: + DoYell(SAY_SLAY2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY2); + break; + } + } + + void JustDied(Unit *victim) + { + if(pInstance) + { + pInstance->SetData(DATA_HIGHWARLORDNAJENTUSEVENT, DONE); + ToggleGate(false); + } + + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_DEATH); + } + + void ToggleGate(bool close) + { + if(GameObject* Gate = GameObject::GetGameObject(*m_creature, pInstance->GetData64(DATA_GAMEOBJECT_NAJENTUS_GATE))) + if(close) Gate->SetGoState(0); // Closed + else Gate->SetGoState(2); // Opened + } + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if(IsShielded) + { + if(spell->Id == SPELL_HURL_SPINE) + { + if(m_creature->HasAura(SPELL_SHIELD_VISUAL, 0)) + m_creature->RemoveAurasDueToSpell(SPELL_SHIELD_VISUAL); + if(m_creature->HasAura(SPELL_TIDAL_SHIELD, 0)) + m_creature->RemoveAurasDueToSpell(SPELL_TIDAL_SHIELD); + DoCast(m_creature->getVictim(), SPELL_TIDAL_BURST); + IsShielded = false; + } + } + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if(IsShielded) + damage = 0; + } + + void Aggro(Unit *who) + { + if(pInstance) + pInstance->SetData(DATA_HIGHWARLORDNAJENTUSEVENT, IN_PROGRESS); + + DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO); + + DoZoneInCombat(); + } + + // This is a workaround since we cannot summon GameObjects at will. + // Instead, we create a custom creature on top of the player. + // When someone kills the creature, the killer gets the "Naj'entus Spine" item. + // This item is the only item that should be able to pierce Tidal Shield + void DoImpalingSpineWorkaround(Unit* target) + { + Creature* Spine = NULL; + Spine = m_creature->SummonCreature(500000, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_DEAD_DESPAWN, 10000); + if(Spine) + { + Spine->setFaction(m_creature->getFaction()); + ((mob_najentus_spineAI*)Spine->AI())->SetSpineVictimGUID(target->GetGUID()); + SpineTargetGUID = target->GetGUID(); + } + } + + bool RemoveImpalingSpine(uint64 guid) + { + if(!IsShielded || guid == SpineTargetGUID) return false; + + if(SpineTargetGUID) + { + Unit* target = Unit::GetUnit((*m_creature), SpineTargetGUID); + if(target && target->HasAura(SPELL_IMPALING_SPINE, 0)) + { + target->RemoveAurasDueToSpell(SPELL_IMPALING_SPINE); + return true; + } + } + + return false; + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(CheckTimer < diff) + { + // if(m_creature->HasAura(SPELL_TIDAL_SHIELD, 0)) + if(m_creature->HasAura(SPELL_SHIELD_VISUAL, 0)) + m_creature->SetHealth(m_creature->GetHealth() + (m_creature->GetMaxHealth()/100)); + else + IsShielded = false; + + CheckTimer = 2000; + }else CheckTimer -= diff; + + if(IsShielded) + { + m_creature->GetMotionMaster()->Clear(false); + m_creature->GetMotionMaster()->MoveIdle(); + if(!m_creature->HasAura(SPELL_SHIELD_VISUAL, 0)) + DoCast(m_creature, SPELL_SHIELD_VISUAL); + if(DispelShieldTimer < diff) + { + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + if(m_creature->HasAura(SPELL_SHIELD_VISUAL, 0)) + m_creature->RemoveAurasDueToSpell(SPELL_SHIELD_VISUAL); + IsShielded = false; + }else DispelShieldTimer -= diff; + + return; // Don't cast or do anything while Shielded + } + + // Crashing Wave + if(CrashingWaveTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_CRASHINGWAVE); + CrashingWaveTimer = 28500; + }else CrashingWaveTimer -= diff; + + if(!m_creature->HasAura(SPELL_BERSERK, 0)) + if(EnrageTimer < diff) + { + DoYell(SAY_ENRAGE, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_ENRAGE); + DoCast(m_creature, SPELL_BERSERK); + }else EnrageTimer -= diff; + + // Needle + if(NeedleSpineTimer < diff) + { + for(uint8 i = 0; i < 3; ++i) + { + Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1); + if(!target) + target = m_creature->getVictim(); + + DoCast(target, SPELL_NEEDLE_AOE, true); + DoCast(target, SPELL_NEEDLE_SPINE); + } + + NeedleSpineTimer = 60000; + }else NeedleSpineTimer -= diff; + + if(SpecialYellTimer < diff) + { + switch(rand()%2) + { + case 0: + DoPlaySoundToSet(m_creature, SOUND_SPECIAL1); + break; + case 1: + DoYell(SAY_SPECIAL2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SPECIAL2); + break; + } + SpecialYellTimer = 25000 + (rand()%76)*1000; + }else SpecialYellTimer -= diff; + + if(ImpalingSpineTimer < diff) + { + Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1); + if(!target) + target = m_creature->getVictim(); + + if(target && (target->GetTypeId() == TYPEID_PLAYER)) + { + DoCast(target, SPELL_IMPALING_SPINE); + //DoImpalingSpineWorkaround(target); + SpineTargetGUID = target->GetGUID(); + ImpalingSpineTimer = 45000; + + switch(rand()%2) + { + case 0: + DoYell(SAY_NEEDLE1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_NEEDLE1); + break; + case 1: + DoYell(SAY_NEEDLE2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_NEEDLE2); + break; + } + } + }else ImpalingSpineTimer -= diff; + + if(TidalShieldTimer < diff) + { + m_creature->InterruptNonMeleeSpells(false); + DoCast(m_creature, SPELL_SHIELD_VISUAL, true); + // DoCast(m_creature, SPELL_TIDAL_SHIELD); + m_creature->GetMotionMaster()->Clear(false); + m_creature->GetMotionMaster()->MoveIdle(); + IsShielded = true; + TidalShieldTimer = 60000; + CheckTimer = 2000; + DispelShieldTimer = 30000; + }else TidalShieldTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +bool GOHello_go_najentus_spine(Player *player, GameObject* _GO) +{ + ScriptedInstance* pInstance = ((ScriptedInstance*)_GO->GetInstanceData()); + if(pInstance) + { + uint64 NajentusGUID = pInstance->GetData64(DATA_HIGHWARLORDNAJENTUS); + if(NajentusGUID) + { + Creature* Najentus = ((Creature*)Unit::GetUnit((*_GO), NajentusGUID)); + if(Najentus) + { + if(((boss_najentusAI*)Najentus->AI())->RemoveImpalingSpine(player->GetGUID())) + return true; + }else error_log("ERROR: Na'entus Spine GameObject unable to find Naj'entus"); + }else error_log("ERROR: Invalid GUID acquired for Naj'entus by Naj'entus Spine GameObject"); + } + else error_log("ERROR: Naj'entus Spine spawned in invalid instance or location"); + + return true; +} + +CreatureAI* GetAI_mob_najentus_spine(Creature *_Creature) +{ + return new mob_najentus_spineAI (_Creature); +} + +CreatureAI* GetAI_boss_najentus(Creature *_Creature) +{ + return new boss_najentusAI (_Creature); +} + +void AddSC_boss_najentus() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_najentus"; + newscript->GetAI = GetAI_boss_najentus; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name = "mob_najentus_spine"; + newscript->GetAI = GetAI_mob_najentus_spine; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name = "go_najentus_spine"; + newscript->pGOHello = &GOHello_go_najentus_spine; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/black_temple/def_black_temple.h b/src/bindings/scripts/scripts/zone/black_temple/def_black_temple.h new file mode 100644 index 00000000000..53e099f7835 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/black_temple/def_black_temple.h @@ -0,0 +1,34 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_BLACK_TEMPLE_H +#define DEF_BLACK_TEMPLE_H + +#define DATA_AKAMA 1 +#define DATA_AKAMA_SHADE 2 +#define DATA_GURTOGGBLOODBOILEVENT 3 +#define DATA_HIGHWARLORDNAJENTUS 4 +#define DATA_HIGHWARLORDNAJENTUSEVENT 5 +#define DATA_ILLIDANSTORMRAGE 6 +#define DATA_ILLIDANSTORMRAGEEVENT 7 +#define DATA_ILLIDARICOUNCILEVENT 8 +#define DATA_ILLIDARICOUNCIL 9 +#define DATA_LADYMALANDE 10 +#define DATA_HIGHNETHERMANCERZEREVOR 11 +#define DATA_GATHIOSTHESHATTERER 12 +#define DATA_VERASDARKSHADOW 13 +#define DATA_MOTHERSHAHRAZEVENT 14 +#define DATA_RELIQUARYOFSOULSEVENT 15 +#define DATA_SHADEOFAKAMA 16 +#define DATA_SHADEOFAKAMAEVENT 17 +#define DATA_SUPREMUS 18 +#define DATA_SUPREMUSEVENT 19 +#define DATA_TERONGOREFIENDEVENT 20 +#define DATA_GAMEOBJECT_NAJENTUS_GATE 21 +#define DATA_GAMEOBJECT_ILLIDAN_GATE 22 +#define DATA_GAMEOBJECT_ILLIDAN_DOOR_R 23 +#define DATA_GAMEOBJECT_ILLIDAN_DOOR_L 24 +#define DATA_GAMEOBJECT_SUPREMUS_DOORS 25 +#define DATA_BLOOD_ELF_COUNCIL_VOICE 26 +#endif diff --git a/src/bindings/scripts/scripts/zone/black_temple/illidari_council.cpp b/src/bindings/scripts/scripts/zone/black_temple/illidari_council.cpp new file mode 100644 index 00000000000..4169f1d764f --- /dev/null +++ b/src/bindings/scripts/scripts/zone/black_temple/illidari_council.cpp @@ -0,0 +1,885 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Illidari_Council +SD%Complete: 95 +SDComment: Circle of Healing not working properly. +SDCategory: Black Temple +EndScriptData */ + +#include "precompiled.h" +#include "def_black_temple.h" + +// High Nethermancer Zerevor's spells +#define SPELL_FLAMESTRIKE 41481 +#define SPELL_BLIZZARD 41482 +#define SPELL_ARCANE_BOLT 41483 +#define SPELL_ARCANE_EXPLOSION 41524 +#define SPELL_DAMPEN_MAGIC 41478 + +// Lady Malande's spells +#define SPELL_EMPOWERED_SMITE 41471 +#define SPELL_CIRCLE_OF_HEALING 41455 +#define SPELL_REFLECTIVE_SHIELD 41475 +#define SPELL_DIVINE_WRATH 41472 +#define SPELL_HEAL_VISUAL 24171 + +// Gathios the Shatterer's spells +#define SPELL_BLESS_PROTECTION 41450 +#define SPELL_BLESS_SPELLWARD 41451 +#define SPELL_CONSECRATION 41541 +#define SPELL_HAMMER_OF_JUSTICE 41468 +#define SPELL_SEAL_OF_COMMAND 41469 +#define SPELL_SEAL_OF_BLOOD 41459 +#define SPELL_CHROMATIC_AURA 41453 +#define SPELL_DEVOTION_AURA 41452 + +// Veras Darkshadow's spells +#define SPELL_DEADLY_POISON 41485 +#define SPELL_ENVENOM 41487 +#define SPELL_VANISH 41479 + +#define SPELL_BERSERK 45078 + +//Speech'n'Sounds +#define SAY_GATH_AGGRO "I have better things to do!" +#define SOUND_GATH_AGGRO 11422 +#define SAY_GATH_SLAY "Selama am'oronor!" +#define SOUND_GATH_SLAY 11423 +#define SAY_GATH_COMNT "Well done!" +#define SOUND_GATH_COMNT 11424 +#define SAY_GATH_DEATH "Lord Illidan... I..." +#define SOUND_GATH_DEATH 11425 +#define SAY_GATH_SPECIAL1 "Enjoy your final moments!" +#define SOUND_GATH_SPECIAL1 11426 +#define SAY_GATH_SPECIAL2 "You are mine!" +#define SOUND_GATH_SPECIAL2 11427 + +#define SAY_MALA_AGGRO "Flee, or die!" +#define SOUND_MALA_AGGRO 11482 +#define SAY_MALA_SLAY "My work is done." +#define SOUND_MALA_SLAY 11483 +#define SAY_MALA_COMNT "As it should be!" +#define SOUND_MALA_COMNT 11484 +#define SAY_MALA_DEATH "Destiny... awaits." +#define SOUND_MALA_DEATH 11485 +#define SAY_MALA_SPECIAL1 "No second chances!" +#define SOUND_MALA_SPECIAL1 11486 +#define SAY_MALA_SPECIAL2 "I'm full of surprises!" +#define SOUND_MALA_SPECIAL2 11487 + +#define SAY_ZERE_AGGRO "Common... such a crude language. Bandal!" +#define SOUND_ZERE_AGGRO 11440 +#define SAY_ZERE_SLAY "Shorel'aran." +#define SOUND_ZERE_SLAY 11441 +#define SAY_ZERE_COMNT "Belesa menoor!" +#define SOUND_ZERE_COMNT 11442 +#define SAY_ZERE_DEATH "Diel ma'ahn... oreindel'o" +#define SOUND_ZERE_DEATH 11443 +#define SAY_ZERE_SPECIAL1 "Diel fin'al" +#define SOUND_ZERE_SPECIAL1 11444 +#define SAY_ZERE_SPECIAL2 "Sha'amoor ara mashal?" +#define SOUND_ZERE_SPECIAL2 11445 + +#define SAY_VERA_AGGRO "You wish to test me?" +#define SOUND_VERA_AGGRO 11524 +#define SAY_VERA_SLAY "Valiant effort!" +#define SOUND_VERA_SLAY 11525 +#define SAY_VERA_COMNT "A glorious kill!" +#define SOUND_VERA_COMNT 11526 +#define SAY_VERA_DEATH "You got lucky!" +#define SOUND_VERA_DEATH 11527 +#define SAY_VERA_SPECIAL1 "You're not caught up for this!" +#define SOUND_VERA_SPECIAL1 11528 +#define SAY_VERA_SPECIAL2 "Anar'alah belore!" +#define SOUND_VERA_SPECIAL2 11529 + +#define ERROR_INST_DATA "SD2 ERROR: Instance Data for Black Temple not set properly; Illidari Council event will not function properly." + +struct CouncilYells +{ + char* text; + uint32 soundId, timer; +}; + +static CouncilYells CouncilAggro[]= +{ + {"I have better things to do!", 11422, 5000}, // Gathios + {"You wish to test me?", 11524, 5500}, // Veras + {"Flee, or die!", 11482, 5000}, // Malande + {"Common... such a crude language. Bandal!", 11440, 0}, // Zerevor +}; + +// Need to get proper timers for this later +static CouncilYells CouncilEnrage[]= +{ + {"Enough games!", 11428, 2000}, // Gathios + {"You wish to kill me? Hahaha, you first!", 11530, 6000},//Veras + {"For Quel'Thalas! For the Sunwell!", 11488, 5000}, // Malande + {"Sha'amoor sine menoor!", 11446, 0}, // Zerevor +}; + +struct MANGOS_DLL_DECL mob_blood_elf_council_voice_triggerAI : public ScriptedAI +{ + mob_blood_elf_council_voice_triggerAI(Creature* c) : ScriptedAI(c) + { + for(uint8 i = 0; i < 4; ++i) + Council[i] = 0; + Reset(); + } + + uint64 Council[4]; + + uint32 EnrageTimer; + uint32 AggroYellTimer; + + uint8 YellCounter; // Serves as the counter for both the aggro and enrage yells + + bool EventStarted; + + void Reset() + { + EnrageTimer = 900000; // 15 minutes + AggroYellTimer = 500; + + YellCounter = 0; + + EventStarted = false; + } + + // finds and stores the GUIDs for each Council member using instance data system. + void LoadCouncilGUIDs() + { + if(ScriptedInstance* pInstance = ((ScriptedInstance*)m_creature->GetInstanceData())) + { + Council[0] = pInstance->GetData64(DATA_GATHIOSTHESHATTERER); + Council[1] = pInstance->GetData64(DATA_VERASDARKSHADOW); + Council[2] = pInstance->GetData64(DATA_LADYMALANDE); + Council[3] = pInstance->GetData64(DATA_HIGHNETHERMANCERZEREVOR); + } + else error_log(ERROR_INST_DATA); + } + + void Aggro(Unit* who) {} + + void AttackStart(Unit* who) {} + void MoveInLineOfSight(Unit* who) {} + + void UpdateAI(const uint32 diff) + { + if(!EventStarted) + return; + + if(YellCounter > 3) + return; + + if(AggroYellTimer) + if(AggroYellTimer <= diff) + { + if(Unit* pMember = Unit::GetUnit(*m_creature, Council[YellCounter])) + { + pMember->MonsterYell(CouncilAggro[YellCounter].text, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(pMember, CouncilAggro[YellCounter].soundId); + AggroYellTimer = CouncilAggro[YellCounter].timer; + } + ++YellCounter; + if(YellCounter > 3) + YellCounter = 0; // Reuse for Enrage Yells + }else AggroYellTimer -= diff; + + if(EnrageTimer) + if(EnrageTimer <= diff) + { + if(Unit* pMember = Unit::GetUnit(*m_creature, Council[YellCounter])) + { + pMember->CastSpell(pMember, SPELL_BERSERK, true); + pMember->MonsterYell(CouncilEnrage[YellCounter].text, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(pMember, CouncilEnrage[YellCounter].soundId); + EnrageTimer = CouncilEnrage[YellCounter].timer; + } + ++YellCounter; + }else EnrageTimer -= diff; + } +}; + +struct MANGOS_DLL_DECL mob_illidari_councilAI : public ScriptedAI +{ + mob_illidari_councilAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + for(uint8 i = 0; i < 4; ++i) + Council[i] = 0; + + Reset(); + } + + ScriptedInstance* pInstance; + + uint64 Council[4]; + + uint32 CheckTimer; + uint32 EndEventTimer; + + uint8 DeathCount; + + bool EventBegun; + + void Reset() + { + CheckTimer = 2000; + EndEventTimer = 0; + + DeathCount = 0; + + Creature* pMember = NULL; + for(uint8 i = 0; i < 4; ++i) + { + if(pMember = ((Creature*)Unit::GetUnit((*m_creature), Council[i]))) + { + if(!pMember->isAlive()) + { + pMember->RemoveCorpse(); + pMember->Respawn(); + } + pMember->AI()->EnterEvadeMode(); + } + } + + if(pInstance) + { + pInstance->SetData(DATA_ILLIDARICOUNCILEVENT, NOT_STARTED); + if(Creature* VoiceTrigger = ((Creature*)Unit::GetUnit(*m_creature, pInstance->GetData64(DATA_BLOOD_ELF_COUNCIL_VOICE)))) + VoiceTrigger->AI()->EnterEvadeMode(); + } + + EventBegun = false; + + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, 11686); + } + + void Aggro(Unit *who) {} + void AttackStart(Unit* who) {} + void MoveInLineOfSight(Unit* who) {} + + void StartEvent(Unit *target) + { + if(!pInstance) return; + + if(target && target->isAlive()) + { + Council[0] = pInstance->GetData64(DATA_GATHIOSTHESHATTERER); + Council[1] = pInstance->GetData64(DATA_HIGHNETHERMANCERZEREVOR); + Council[2] = pInstance->GetData64(DATA_LADYMALANDE); + Council[3] = pInstance->GetData64(DATA_VERASDARKSHADOW); + + // Start the event for the Voice Trigger + if(Creature* VoiceTrigger = ((Creature*)Unit::GetUnit(*m_creature, pInstance->GetData64(DATA_BLOOD_ELF_COUNCIL_VOICE)))) + { + ((mob_blood_elf_council_voice_triggerAI*)VoiceTrigger->AI())->LoadCouncilGUIDs(); + ((mob_blood_elf_council_voice_triggerAI*)VoiceTrigger->AI())->EventStarted = true; + } + + for(uint8 i = 0; i < 4; ++i) + { + Unit* Member = NULL; + if(Council[i]) + { + Member = Unit::GetUnit((*m_creature), Council[i]); + if(Member && Member->isAlive()) + Member->AddThreat(target, 1.0f); + } + } + + pInstance->SetData(DATA_ILLIDARICOUNCILEVENT, IN_PROGRESS); + + EventBegun = true; + } + } + + void UpdateAI(const uint32 diff) + { + if(!EventBegun) return; + + if(EndEventTimer) + if(EndEventTimer <= diff) + { + if(DeathCount > 3) + { + if(pInstance) + { + if(Creature* VoiceTrigger = ((Creature*)Unit::GetUnit(*m_creature, pInstance->GetData64(DATA_BLOOD_ELF_COUNCIL_VOICE)))) + VoiceTrigger->DealDamage(VoiceTrigger, VoiceTrigger->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + pInstance->SetData(DATA_ILLIDARICOUNCILEVENT, DONE); + } + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + return; + } + + Creature* pMember = ((Creature*)Unit::GetUnit(*m_creature, Council[DeathCount])); + if(pMember && pMember->isAlive()) + pMember->DealDamage(pMember, pMember->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + ++DeathCount; + EndEventTimer = 1500; + }else EndEventTimer -= diff; + + if(CheckTimer) + if(CheckTimer <= diff) + { + uint8 EvadeCheck = 0; + for(uint8 i = 0; i < 4; ++i) + { + if(Council[i]) + { + if(Creature* Member = ((Creature*)Unit::GetUnit((*m_creature), Council[i]))) + { + // This is the evade/death check. + if(Member->isAlive() && !Member->SelectHostilTarget()) + ++EvadeCheck; //If all members evade, we reset so that players can properly reset the event + else if(!Member->isAlive()) // If even one member dies, kill the rest, set instance data, and kill self. + { + EndEventTimer = 1000; + CheckTimer = 0; + return; + } + } + } + } + + if(EvadeCheck > 3) + Reset(); + + CheckTimer = 2000; + }else CheckTimer -= diff; + + } +}; + +struct MANGOS_DLL_DECL boss_illidari_councilAI : public ScriptedAI +{ + boss_illidari_councilAI(Creature* c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + for(uint8 i = 0; i < 4; ++i) + Council[i] = 0; + LoadedGUIDs = false; + } + + uint64 Council[4]; + + ScriptedInstance* pInstance; + + bool LoadedGUIDs; + + void Aggro(Unit* who) + { + if(pInstance) + { + Creature* Controller = ((Creature*)Unit::GetUnit(*m_creature, pInstance->GetData64(DATA_ILLIDARICOUNCIL))); + if(Controller) + ((mob_illidari_councilAI*)Controller->AI())->StartEvent(who); + } + else + { + error_log(ERROR_INST_DATA); + EnterEvadeMode(); + } + DoZoneInCombat(); + // Load GUIDs on first aggro because the creature guids are only set as the creatures are created in world- + // this means that for each creature, it will attempt to LoadGUIDs even though some of the other creatures are + // not in world, and thus have no GUID set in the instance data system. Putting it in aggro ensures that all the creatures + // have been loaded and have their GUIDs set in the instance data system. + if(!LoadedGUIDs) + LoadGUIDs(); + } + + void DamageTaken(Unit* done_by, uint32 &damage) + { + if(done_by == m_creature) + return; + + damage /= 4; + for(uint8 i = 0; i < 4; ++i) + { + if(Unit* pUnit = Unit::GetUnit(*m_creature, Council[i])) + if(pUnit != m_creature && damage < pUnit->GetHealth()) + pUnit->SetHealth(pUnit->GetHealth() - damage); + } + } + + void LoadGUIDs() + { + if(!pInstance) + { + error_log(ERROR_INST_DATA); + return; + } + + Council[0] = pInstance->GetData64(DATA_LADYMALANDE); + Council[1] = pInstance->GetData64(DATA_HIGHNETHERMANCERZEREVOR); + Council[2] = pInstance->GetData64(DATA_GATHIOSTHESHATTERER); + Council[3] = pInstance->GetData64(DATA_VERASDARKSHADOW); + + LoadedGUIDs = true; + } +}; + +struct MANGOS_DLL_DECL boss_gathios_the_shattererAI : public boss_illidari_councilAI +{ + boss_gathios_the_shattererAI(Creature *c) : boss_illidari_councilAI(c) { Reset(); } + + uint32 ConsecrationTimer; + uint32 HammerOfJusticeTimer; + uint32 SealTimer; + uint32 AuraTimer; + uint32 BlessingTimer; + + void Reset() + { + ConsecrationTimer = 40000; + HammerOfJusticeTimer = 10000; + SealTimer = 40000; + AuraTimer = 90000; + BlessingTimer = 60000; + } + + void KilledUnit(Unit *victim) + { + DoYell(SAY_GATH_SLAY,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_GATH_SLAY); + } + + void JustDied(Unit *victim) + { + DoYell(SAY_GATH_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_GATH_DEATH); + } + + Unit* SelectCouncilMember() + { + Unit* pUnit = m_creature; + uint32 member = 0; // He chooses Lady Malande most often + + if(rand()%10 == 0) // But there is a chance he picks someone else. + member = urand(1, 3); + + if(member != 2) // No need to create another pointer to us using Unit::GetUnit + pUnit = Unit::GetUnit((*m_creature), Council[member]); + return pUnit; + } + + void CastAuraOnCouncil() + { + uint32 spellid = 0; + switch(rand()%2) + { + case 0: spellid = SPELL_DEVOTION_AURA; break; + case 1: spellid = SPELL_CHROMATIC_AURA; break; + } + for(uint8 i = 0; i < 4; ++i) + { + Unit* pUnit = Unit::GetUnit((*m_creature), Council[i]); + if(pUnit) + pUnit->CastSpell(pUnit, spellid, true, 0, 0, m_creature->GetGUID()); + } + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(BlessingTimer < diff) + { + if(Unit* pUnit = SelectCouncilMember()) + { + switch(rand()%2) + { + case 0: DoCast(pUnit, SPELL_BLESS_SPELLWARD); break; + case 1: DoCast(pUnit, SPELL_BLESS_PROTECTION); break; + } + } + BlessingTimer = 60000; + }else BlessingTimer -= diff; + + if(ConsecrationTimer < diff) + { + DoCast(m_creature, SPELL_CONSECRATION); + ConsecrationTimer = 40000; + }else ConsecrationTimer -= diff; + + if(HammerOfJusticeTimer < diff) + { + if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + // is in ~10-40 yd range + if(m_creature->GetDistance2d(target) > 10 && m_creature->GetDistance2d(target) < 40) + { + DoCast(target, SPELL_HAMMER_OF_JUSTICE); + HammerOfJusticeTimer = 20000; + } + } + }else HammerOfJusticeTimer -= diff; + + if(SealTimer < diff) + { + switch(rand()%2) + { + case 0: DoCast(m_creature, SPELL_SEAL_OF_COMMAND); break; + case 1: DoCast(m_creature, SPELL_SEAL_OF_BLOOD); break; + } + SealTimer = 40000; + }else SealTimer -= diff; + + if(AuraTimer < diff) + { + CastAuraOnCouncil(); + AuraTimer = 90000; + }else AuraTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL boss_high_nethermancer_zerevorAI : public boss_illidari_councilAI +{ + boss_high_nethermancer_zerevorAI(Creature *c) : boss_illidari_councilAI(c) { Reset(); } + + uint32 BlizzardTimer; + uint32 FlamestrikeTimer; + uint32 ArcaneBoltTimer; + uint32 DampenMagicTimer; + uint32 Cooldown; + uint32 ArcaneExplosionTimer; + + void Reset() + { + BlizzardTimer = 30000 + rand()%61 * 1000; + FlamestrikeTimer = 30000 + rand()%61 * 1000; + ArcaneBoltTimer = 10000; + DampenMagicTimer = 2000; + ArcaneExplosionTimer = 14000; + Cooldown = 0; + } + + void KilledUnit(Unit *victim) + { + DoYell(SAY_ZERE_SLAY,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_ZERE_SLAY); + } + + void JustDied(Unit *victim) + { + DoYell(SAY_ZERE_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_ZERE_DEATH); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(Cooldown) + { + if(Cooldown < diff) Cooldown = 0; + else + { + Cooldown -= diff; + return; // Don't cast any other spells if global cooldown is still ticking + } + } + + if(DampenMagicTimer < diff) + { + DoCast(m_creature, SPELL_DAMPEN_MAGIC); + Cooldown = 1000; + DampenMagicTimer = 110000; // almost 2 minutes + ArcaneBoltTimer += 1000; // Give the Mage some time to spellsteal Dampen. + }else DampenMagicTimer -= diff; + + if(ArcaneExplosionTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_ARCANE_EXPLOSION); + Cooldown = 1000; + ArcaneExplosionTimer = 14000; + }else ArcaneExplosionTimer -= diff; + + if(ArcaneBoltTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_ARCANE_BOLT); + ArcaneBoltTimer = 3000; + Cooldown = 2000; + }else ArcaneBoltTimer -= diff; + + if(BlizzardTimer < diff) + { + if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoCast(target, SPELL_BLIZZARD); + BlizzardTimer = 45000 + rand()%46 * 1000; + FlamestrikeTimer += 10000; + Cooldown = 1000; + } + }else BlizzardTimer -= diff; + + if(FlamestrikeTimer < diff) + { + if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoCast(target, SPELL_FLAMESTRIKE); + FlamestrikeTimer = 55000 + rand()%46 * 1000; + BlizzardTimer += 10000; + Cooldown = 2000; + } + }else FlamestrikeTimer -= diff; + } +}; + +struct MANGOS_DLL_DECL boss_lady_malandeAI : public boss_illidari_councilAI +{ + boss_lady_malandeAI(Creature *c) : boss_illidari_councilAI(c) { Reset(); } + + uint32 EmpoweredSmiteTimer; + uint32 CircleOfHealingTimer; + uint32 DivineWrathTimer; + uint32 ReflectiveShieldTimer; + + void Reset() + { + EmpoweredSmiteTimer = 38000; + CircleOfHealingTimer = 20000; + DivineWrathTimer = 40000; + ReflectiveShieldTimer = 0; + } + + void KilledUnit(Unit *victim) + { + DoYell(SAY_MALA_SLAY,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_MALA_SLAY); + } + + void JustDied(Unit *victim) + { + DoYell(SAY_MALA_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_MALA_DEATH); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(EmpoweredSmiteTimer < diff) + { + if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoCast(target, SPELL_EMPOWERED_SMITE); + EmpoweredSmiteTimer = 38000; + } + }else EmpoweredSmiteTimer -= diff; + + if(CircleOfHealingTimer < diff) + { + //Currently bugged and puts Malande on the threatlist of the other council members. It also heals players. + //DoCast(m_creature, SPELL_CIRCLE_OF_HEALING); + CircleOfHealingTimer = 60000; + }else CircleOfHealingTimer -= diff; + + if(DivineWrathTimer < diff) + { + if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoCast(target, SPELL_DIVINE_WRATH); + DivineWrathTimer = 40000 + rand()%41 * 1000; + } + }else DivineWrathTimer -= diff; + + if(ReflectiveShieldTimer < diff) + { + DoCast(m_creature, SPELL_REFLECTIVE_SHIELD); + ReflectiveShieldTimer = 65000; + }else ReflectiveShieldTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL boss_veras_darkshadowAI : public boss_illidari_councilAI +{ + boss_veras_darkshadowAI(Creature *c) : boss_illidari_councilAI(c) { Reset(); } + + uint64 EnvenomTargetGUID; + + uint32 DeadlyPoisonTimer; + uint32 VanishTimer; + uint32 AppearEnvenomTimer; + + bool HasVanished; + + void Reset() + { + EnvenomTargetGUID = 0; + + DeadlyPoisonTimer = 20000; + VanishTimer = 60000 + rand()%61 * 1000; + AppearEnvenomTimer = 150000; + + HasVanished = false; + m_creature->SetVisibility(VISIBILITY_ON); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void KilledUnit(Unit *victim) + { + DoYell(SAY_VERA_SLAY,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_VERA_SLAY); + } + + void JustDied(Unit *victim) + { + DoYell(SAY_VERA_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_VERA_DEATH); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(!HasVanished) + { + if(DeadlyPoisonTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_DEADLY_POISON); + DeadlyPoisonTimer = 15000 + rand()%31 * 1000; + }else DeadlyPoisonTimer -= diff; + + if(AppearEnvenomTimer < diff) // Cast Envenom. This is cast 4 seconds after Vanish is over + { + DoCast(m_creature->getVictim(), SPELL_ENVENOM); + AppearEnvenomTimer = 90000; + }else AppearEnvenomTimer -= diff; + + if(VanishTimer < diff) // Disappear and stop attacking, but follow a random unit + { + if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + VanishTimer = 30000; + AppearEnvenomTimer= 28000; + HasVanished = true; + m_creature->SetVisibility(VISIBILITY_OFF); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoResetThreat(); + // Chase a unit. Check before DoMeleeAttackIfReady prevents from attacking + m_creature->AddThreat(target, 500000.0f); + m_creature->GetMotionMaster()->MoveChase(target); + } + }else VanishTimer -= diff; + + DoMeleeAttackIfReady(); + } + else + { + if(VanishTimer < diff) // Become attackable and poison current target + { + Unit* target = m_creature->getVictim(); + DoCast(target, SPELL_DEADLY_POISON); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoResetThreat(); + m_creature->AddThreat(target, 3000.0f); // Make Veras attack his target for a while, he will cast Envenom 4 seconds after. + DeadlyPoisonTimer += 6000; + VanishTimer = 90000; + AppearEnvenomTimer = 4000; + HasVanished = false; + }else VanishTimer -= diff; + + if(AppearEnvenomTimer < diff) // Appear 2 seconds before becoming attackable (Shifting out of vanish) + { + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + m_creature->SetVisibility(VISIBILITY_ON); + AppearEnvenomTimer = 6000; + }else AppearEnvenomTimer -= diff; + } + } +}; + +CreatureAI* GetAI_mob_blood_elf_council_voice_trigger(Creature* c) +{ + return new mob_blood_elf_council_voice_triggerAI(c); +} + +CreatureAI* GetAI_mob_illidari_council(Creature *_Creature) +{ + return new mob_illidari_councilAI (_Creature); +} + +CreatureAI* GetAI_boss_gathios_the_shatterer(Creature *_Creature) +{ + return new boss_gathios_the_shattererAI (_Creature); +} + +CreatureAI* GetAI_boss_lady_malande(Creature *_Creature) +{ + return new boss_lady_malandeAI (_Creature); +} + +CreatureAI* GetAI_boss_veras_darkshadow(Creature *_Creature) +{ + return new boss_veras_darkshadowAI (_Creature); +} + +CreatureAI* GetAI_boss_high_nethermancer_zerevor(Creature *_Creature) +{ + return new boss_high_nethermancer_zerevorAI (_Creature); +} + +void AddSC_boss_illidari_council() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="mob_illidari_council"; + newscript->GetAI = GetAI_mob_illidari_council; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name = "mob_blood_elf_council_voice_trigger"; + newscript->GetAI = GetAI_mob_blood_elf_council_voice_trigger; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_gathios_the_shatterer"; + newscript->GetAI = GetAI_boss_gathios_the_shatterer; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_lady_malande"; + newscript->GetAI = GetAI_boss_lady_malande; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_veras_darkshadow"; + newscript->GetAI = GetAI_boss_veras_darkshadow; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_high_nethermancer_zerevor"; + newscript->GetAI = GetAI_boss_high_nethermancer_zerevor; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/black_temple/instance_black_temple.cpp b/src/bindings/scripts/scripts/zone/black_temple/instance_black_temple.cpp new file mode 100644 index 00000000000..3251c93cafa --- /dev/null +++ b/src/bindings/scripts/scripts/zone/black_temple/instance_black_temple.cpp @@ -0,0 +1,252 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Black_Temple +SD%Complete: 100 +SDComment: Instance Data Scripts and functions to acquire mobs and set encounter status for use in various Black Temple Scripts +SDCategory: Black Temple +EndScriptData */ + +#include "precompiled.h" +#include "def_black_temple.h" + +#define ENCOUNTERS 9 + +/* Black Temple encounters: +0 - High Warlord Naj'entus event +1 - Supremus Event +2 - Shade of Akama Event +3 - Teron Gorefiend Event +4 - Gurtogg Bloodboil Event +5 - Reliquary Of Souls Event +6 - Mother Shahraz Event +7 - Illidari Council Event +8 - Illidan Stormrage Event +*/ + +struct MANGOS_DLL_DECL instance_black_temple : public ScriptedInstance +{ + instance_black_temple(Map *Map) : ScriptedInstance(Map) {Initialize();}; + + uint64 Najentus; + uint64 Akama; // This is the Akama that starts the Illidan encounter. + uint64 Akama_Shade; // This is the Akama that starts the Shade of Akama encounter. + uint64 ShadeOfAkama; + uint64 Supremus; + uint64 LadyMalande; + uint64 GathiosTheShatterer; + uint64 HighNethermancerZerevor; + uint64 VerasDarkshadow; + uint64 IllidariCouncil; + uint64 BloodElfCouncilVoice; + uint64 IllidanStormrage; + + uint64 NajentusGate; + uint64 MainTempleDoors; + uint64 IllidanGate; + uint64 IllidanDoor[2]; + + uint32 Encounters[ENCOUNTERS]; + + void Initialize() + { + Najentus = 0; + Akama = 0; + Akama_Shade = 0; + ShadeOfAkama = 0; + Supremus = 0; + LadyMalande = 0; + GathiosTheShatterer = 0; + HighNethermancerZerevor = 0; + VerasDarkshadow = 0; + IllidariCouncil = 0; + BloodElfCouncilVoice = 0; + IllidanStormrage = 0; + + NajentusGate = 0; + MainTempleDoors = 0; + IllidanGate = 0; + IllidanDoor[0] = 0; + IllidanDoor[1] = 0; + + for(uint8 i = 0; i < ENCOUNTERS; i++) + Encounters[i] = NOT_STARTED; + } + + bool IsEncounterInProgress() const + { + for(uint8 i = 0; i < ENCOUNTERS; i++) + if(Encounters[i] == IN_PROGRESS) return true; + + return false; + } + + void OnCreatureCreate(Creature *creature, uint32 creature_entry) + { + switch(creature_entry) + { + case 22887: Najentus = creature->GetGUID(); break; + case 23089: Akama = creature->GetGUID(); break; + case 22990: Akama_Shade = creature->GetGUID(); break; + case 22841: ShadeOfAkama = creature->GetGUID(); break; + case 22898: Supremus = creature->GetGUID(); break; + case 22917: IllidanStormrage = creature->GetGUID(); break; + case 22949: GathiosTheShatterer = creature->GetGUID(); break; + case 22950: HighNethermancerZerevor = creature->GetGUID(); break; + case 22951: LadyMalande = creature->GetGUID(); break; + case 22952: VerasDarkshadow = creature->GetGUID(); break; + case 23426: IllidariCouncil = creature->GetGUID(); break; + case 23499: BloodElfCouncilVoice = creature->GetGUID(); break; + } + } + + void OnObjectCreate(GameObject* go) + { + switch(go->GetEntry()) + { + case 185483: // Gate past Naj'entus (at the entrance to Supermoose's courtyards) + NajentusGate = go->GetGUID(); + break; + case 185882: // Main Temple Doors - right past Supermoose (Supremus) + MainTempleDoors = go->GetGUID(); + break; + case 185905: // Gate leading to Temple Summit + IllidanGate = go->GetGUID(); + break; + case 186261: // Right door at Temple Summit + IllidanDoor[0] = go->GetGUID(); + break; + case 186262: // Left door at Temple Summit + IllidanDoor[1] = go->GetGUID(); + break; + } + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_HIGHWARLORDNAJENTUS: return Najentus; + case DATA_AKAMA: return Akama; + case DATA_AKAMA_SHADE: return Akama_Shade; + case DATA_SHADEOFAKAMA: return ShadeOfAkama; + case DATA_SUPREMUS: return Supremus; + case DATA_ILLIDANSTORMRAGE: return IllidanStormrage; + case DATA_GATHIOSTHESHATTERER: return GathiosTheShatterer; + case DATA_HIGHNETHERMANCERZEREVOR: return HighNethermancerZerevor; + case DATA_LADYMALANDE: return LadyMalande; + case DATA_VERASDARKSHADOW: return VerasDarkshadow; + case DATA_ILLIDARICOUNCIL: return IllidariCouncil; + case DATA_GAMEOBJECT_NAJENTUS_GATE: return NajentusGate; + case DATA_GAMEOBJECT_ILLIDAN_GATE: return IllidanGate; + case DATA_GAMEOBJECT_ILLIDAN_DOOR_R: return IllidanDoor[0]; + case DATA_GAMEOBJECT_ILLIDAN_DOOR_L: return IllidanDoor[1]; + case DATA_GAMEOBJECT_SUPREMUS_DOORS: return MainTempleDoors; + case DATA_BLOOD_ELF_COUNCIL_VOICE: return BloodElfCouncilVoice; + } + + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_HIGHWARLORDNAJENTUSEVENT: Encounters[0] = data; break; + case DATA_SUPREMUSEVENT: Encounters[1] = data; break; + case DATA_SHADEOFAKAMAEVENT: Encounters[2] = data; break; + case DATA_TERONGOREFIENDEVENT: Encounters[3] = data; break; + case DATA_GURTOGGBLOODBOILEVENT: Encounters[4] = data; break; + case DATA_RELIQUARYOFSOULSEVENT: Encounters[5] = data; break; + case DATA_MOTHERSHAHRAZEVENT: Encounters[6] = data; break; + case DATA_ILLIDARICOUNCILEVENT: Encounters[7] = data; break; + case DATA_ILLIDANSTORMRAGEEVENT: Encounters[8] = data; break; + } + + if(data == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_HIGHWARLORDNAJENTUSEVENT: return Encounters[0]; + case DATA_SUPREMUSEVENT: return Encounters[1]; + case DATA_SHADEOFAKAMAEVENT: return Encounters[2]; + case DATA_TERONGOREFIENDEVENT: return Encounters[3]; + case DATA_GURTOGGBLOODBOILEVENT: return Encounters[4]; + case DATA_RELIQUARYOFSOULSEVENT: return Encounters[5]; + case DATA_MOTHERSHAHRAZEVENT: return Encounters[6]; + case DATA_ILLIDARICOUNCILEVENT: return Encounters[7]; + case DATA_ILLIDANSTORMRAGEEVENT: return Encounters[8]; + } + + return 0; + } + + const char* Save() + { + OUT_SAVE_INST_DATA; + std::ostringstream stream; + stream << Encounters[0] << " " << Encounters[1] << " " << Encounters[2] << " " + << Encounters[3] << " " << Encounters[4] << " " << Encounters[5] << " " + << Encounters[6] << " " << Encounters[7] << " " << Encounters[8]; + char* out = new char[stream.str().length() + 1]; + strcpy(out, stream.str().c_str()); + if(out) + { + OUT_SAVE_INST_DATA_COMPLETE; + return out; + } + + return NULL; + } + + void Load(const char* in) + { + if(!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + std::istringstream stream(in); + stream >> Encounters[0] >> Encounters[1] >> Encounters[2] >> Encounters[3] + >> Encounters[4] >> Encounters[5] >> Encounters[6] >> Encounters[7] + >> Encounters[8]; + for(uint8 i = 0; i < ENCOUNTERS; ++i) + if(Encounters[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead. + Encounters[i] = NOT_STARTED; + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_black_temple(Map* map) +{ + return new instance_black_temple(map); +} + +void AddSC_instance_black_temple() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_black_temple"; + newscript->GetInstanceData = GetInstanceData_instance_black_temple; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackrock_depths/blackrock_depths.cpp b/src/bindings/scripts/scripts/zone/blackrock_depths/blackrock_depths.cpp new file mode 100644 index 00000000000..b4b2b177f19 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackrock_depths/blackrock_depths.cpp @@ -0,0 +1,237 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Blackrock_Depths +SD%Complete: 95 +SDComment: Quest support: 4001, 4342, 7604. Vendor Lokhtos Darkbargainer. +SDCategory: Blackrock Depths +EndScriptData */ + +/* ContentData +mob_phalanx +npc_kharan_mighthammer +npc_lokhtos_darkbargainer +EndContentData */ + +#include "precompiled.h" + +/*###### +## mob_phalanx +######*/ + +#define SPELL_THUNDERCLAP 8732 +#define SPELL_FIREBALLVOLLEY 22425 +#define SPELL_MIGHTYBLOW 14099 + +struct MANGOS_DLL_DECL mob_phalanxAI : public ScriptedAI +{ + mob_phalanxAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 ThunderClap_Timer; + uint32 FireballVolley_Timer; + uint32 MightyBlow_Timer; + + void Reset() + { + ThunderClap_Timer = 12000; + FireballVolley_Timer =0; + MightyBlow_Timer = 15000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //ThunderClap_Timer + if( ThunderClap_Timer < diff ) + { + DoCast(m_creature->getVictim(),SPELL_THUNDERCLAP); + ThunderClap_Timer = 10000; + }else ThunderClap_Timer -= diff; + + //FireballVolley_Timer + if( m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 51 ) + { + if (FireballVolley_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FIREBALLVOLLEY); + FireballVolley_Timer = 15000; + }else FireballVolley_Timer -= diff; + } + + //MightyBlow_Timer + if( MightyBlow_Timer < diff ) + { + DoCast(m_creature->getVictim(),SPELL_MIGHTYBLOW); + MightyBlow_Timer = 10000; + }else MightyBlow_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_mob_phalanx(Creature *_Creature) +{ + return new mob_phalanxAI (_Creature); +} + +/*###### +## npc_kharan_mighthammer +######*/ + +#define QUEST_4001 4001 +#define QUEST_4342 4342 + +bool GossipHello_npc_kharan_mighthammer(Player *player, Creature *_Creature) +{ + if( _Creature->isQuestGiver() ) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if( player->GetQuestStatus(QUEST_4001) == QUEST_STATUS_INCOMPLETE ) + player->ADD_GOSSIP_ITEM( 0, "I need to know where the princess are, Kharan!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + if( player->GetQuestStatus(4342) == QUEST_STATUS_INCOMPLETE ) + player->ADD_GOSSIP_ITEM( 0, "All is not lost, Kharan!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + + if( player->GetTeam() == HORDE ) player->SEND_GOSSIP_MENU(2473, _Creature->GetGUID()); + if( player->GetTeam() == ALLIANCE ) player->SEND_GOSSIP_MENU(2474, _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_kharan_mighthammer(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF+1: + player->ADD_GOSSIP_ITEM(0, "Gor'shak is my friend, you can trust me.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + player->SEND_GOSSIP_MENU(2475, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + player->ADD_GOSSIP_ITEM(0, "Not enough, you need to tell me more.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + player->SEND_GOSSIP_MENU(2476, _Creature->GetGUID()); + break; + + case GOSSIP_ACTION_INFO_DEF+3: + player->ADD_GOSSIP_ITEM(0, "So what happened?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + player->SEND_GOSSIP_MENU(2477, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + player->ADD_GOSSIP_ITEM(0, "Continue...", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + player->SEND_GOSSIP_MENU(2478, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + player->ADD_GOSSIP_ITEM(0, "So you suspect that someone on the inside was involved? That they were tipped off?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); + player->SEND_GOSSIP_MENU(2479, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+6: + player->ADD_GOSSIP_ITEM(0, "Continue with your story please.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+7); + player->SEND_GOSSIP_MENU(2480, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+7: + player->ADD_GOSSIP_ITEM(0, "Indeed.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+8); + player->SEND_GOSSIP_MENU(2481, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+8: + player->ADD_GOSSIP_ITEM(0, "The door is open, Kharan. You are a free man.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+9); + player->SEND_GOSSIP_MENU(2482, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+9: + player->CLOSE_GOSSIP_MENU(); + if( player->GetTeam() == HORDE ) player->AreaExploredOrEventHappens(QUEST_4001); + if( player->GetTeam() == ALLIANCE ) player->AreaExploredOrEventHappens(QUEST_4342); + break; + } + return true; +} + +/*###### +## npc_lokhtos_darkbargainer +######*/ + +#define ITEM_THRORIUM_BROTHERHOOD_CONTRACT 18628 +#define ITEM_SULFURON_INGOT 17203 +#define QUEST_A_BINDING_CONTRACT 7604 +#define SPELL_CREATE_THORIUM_BROTHERHOOD_CONTRACT_DND 23059 + +bool GossipHello_npc_lokhtos_darkbargainer(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if (_Creature->isVendor() && player->GetReputationRank(59) >= REP_FRIENDLY) + player->ADD_GOSSIP_ITEM( 1, "Show me what I have access to, Lothos.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + + if (player->GetQuestRewardStatus(QUEST_A_BINDING_CONTRACT) != 1 && + !player->HasItemCount(ITEM_THRORIUM_BROTHERHOOD_CONTRACT, 1, true) && + player->HasItemCount(ITEM_SULFURON_INGOT, 1)) + { + player->ADD_GOSSIP_ITEM(0, "Get Thorium Brotherhood Contract", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + } + + if (player->GetReputationRank(59) < REP_FRIENDLY) + player->SEND_GOSSIP_MENU(3673, _Creature->GetGUID()); + else + player->SEND_GOSSIP_MENU(3677, _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_lokhtos_darkbargainer(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if (action == GOSSIP_ACTION_INFO_DEF + 1) + { + player->CLOSE_GOSSIP_MENU(); + player->CastSpell(player, SPELL_CREATE_THORIUM_BROTHERHOOD_CONTRACT_DND, false); + } + if (action == GOSSIP_ACTION_TRADE) + { + player->SEND_VENDORLIST( _Creature->GetGUID() ); + } + return true; +} + +/*###### +## +######*/ + +void AddSC_blackrock_depths() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="phalanx"; + newscript->GetAI = GetAI_mob_phalanx; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_kharan_mighthammer"; + newscript->pGossipHello = &GossipHello_npc_kharan_mighthammer; + newscript->pGossipSelect = &GossipSelect_npc_kharan_mighthammer; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_lokhtos_darkbargainer"; + newscript->pGossipHello = &GossipHello_npc_lokhtos_darkbargainer; + newscript->pGossipSelect = &GossipSelect_npc_lokhtos_darkbargainer; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackrock_depths/boss_ambassador_flamelash.cpp b/src/bindings/scripts/scripts/zone/blackrock_depths/boss_ambassador_flamelash.cpp new file mode 100644 index 00000000000..613da72ef3a --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackrock_depths/boss_ambassador_flamelash.cpp @@ -0,0 +1,106 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Ambassador_Flamelash +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Depths +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_FIREBLAST 15573 + +struct MANGOS_DLL_DECL boss_ambassador_flamelashAI : public ScriptedAI +{ + boss_ambassador_flamelashAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 FireBlast_Timer; + uint32 Spirit_Timer; + int Rand; + int RandX; + int RandY; + Creature* Summoned; + + void Reset() + { + FireBlast_Timer = 2000; + Spirit_Timer = 24000; + } + + void Aggro(Unit *who) {} + + void SummonSpirits(Unit* victim) + { + Rand = rand()%10; + switch (rand()%2) + { + case 0: RandX -= Rand; break; + case 1: RandX += Rand; break; + } + Rand = 0; + Rand = rand()%10; + switch (rand()%2) + { + case 0: RandY -= Rand; break; + case 1: RandY += Rand; break; + } + Summoned = DoSpawnCreature(9178, RandX, RandY, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); + if(Summoned) + ((CreatureAI*)Summoned->AI())->AttackStart(victim); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //FireBlast_Timer + if (FireBlast_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FIREBLAST); + FireBlast_Timer = 7000; + }else FireBlast_Timer -= diff; + + //Spirit_Timer + if (Spirit_Timer < diff) + { + SummonSpirits(m_creature->getVictim()); + SummonSpirits(m_creature->getVictim()); + SummonSpirits(m_creature->getVictim()); + SummonSpirits(m_creature->getVictim()); + + Spirit_Timer = 30000; + }else Spirit_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_ambassador_flamelash(Creature *_Creature) +{ + return new boss_ambassador_flamelashAI (_Creature); +} + +void AddSC_boss_ambassador_flamelash() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_ambassador_flamelash"; + newscript->GetAI = GetAI_boss_ambassador_flamelash; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackrock_depths/boss_angerrel.cpp b/src/bindings/scripts/scripts/zone/blackrock_depths/boss_angerrel.cpp new file mode 100644 index 00000000000..98e382ae233 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackrock_depths/boss_angerrel.cpp @@ -0,0 +1,91 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Angerrel +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Depths +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_SUNDERARMOR 24317 +#define SPELL_SHIELDBLOCK 12169 +#define SPELL_STRIKE 15580 + +struct MANGOS_DLL_DECL boss_angerrelAI : public ScriptedAI +{ + boss_angerrelAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 SunderArmor_Timer; + uint32 ShieldBlock_Timer; + uint32 Strike_Timer; + + void Reset() + { + SunderArmor_Timer = 8000; + ShieldBlock_Timer = 15000; + Strike_Timer = 12000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //SunderArmor_Timer + if (SunderArmor_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SUNDERARMOR); + SunderArmor_Timer = 28000; + }else SunderArmor_Timer -= diff; + + //ShieldBlock_Timer + if (ShieldBlock_Timer < diff) + { + DoCast(m_creature,SPELL_SHIELDBLOCK); + ShieldBlock_Timer = 25000; + }else ShieldBlock_Timer -= diff; + + //Strike_Timer + if (Strike_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_STRIKE); + Strike_Timer = 10000; + }else Strike_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_angerrel(Creature *_Creature) +{ + return new boss_angerrelAI (_Creature); +} + +void AddSC_boss_angerrel() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_angerrel"; + newscript->GetAI = GetAI_boss_angerrel; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackrock_depths/boss_anubshiah.cpp b/src/bindings/scripts/scripts/zone/blackrock_depths/boss_anubshiah.cpp new file mode 100644 index 00000000000..1cf80bfc8ec --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackrock_depths/boss_anubshiah.cpp @@ -0,0 +1,115 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Anubshiah +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Depths +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_SHADOWBOLT 17228 +#define SPELL_CURSEOFTONGUES 15470 +#define SPELL_CURSEOFWEAKNESS 17227 +#define SPELL_DEMONARMOR 11735 +#define SPELL_ENVELOPINGWEB 15471 + +struct MANGOS_DLL_DECL boss_anubshiahAI : public ScriptedAI +{ + boss_anubshiahAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 ShadowBolt_Timer; + uint32 CurseOfTongues_Timer; + uint32 CurseOfWeakness_Timer; + uint32 DemonArmor_Timer; + uint32 EnvelopingWeb_Timer; + + void Reset() + { + ShadowBolt_Timer = 7000; + CurseOfTongues_Timer = 24000; + CurseOfWeakness_Timer = 12000; + DemonArmor_Timer = 3000; + EnvelopingWeb_Timer = 16000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //ShadowBolt_Timer + if (ShadowBolt_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SHADOWBOLT); + ShadowBolt_Timer = 7000; + }else ShadowBolt_Timer -= diff; + + //CurseOfTongues_Timer + if (CurseOfTongues_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) DoCast(target,SPELL_CURSEOFTONGUES); + CurseOfTongues_Timer = 18000; + }else CurseOfTongues_Timer -= diff; + + //CurseOfWeakness_Timer + if (CurseOfWeakness_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CURSEOFWEAKNESS); + CurseOfWeakness_Timer = 45000; + }else CurseOfWeakness_Timer -= diff; + + //DemonArmor_Timer + if (DemonArmor_Timer < diff) + { + DoCast(m_creature,SPELL_DEMONARMOR); + DemonArmor_Timer = 300000; + }else DemonArmor_Timer -= diff; + + //EnvelopingWeb_Timer + if (EnvelopingWeb_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) DoCast(target,SPELL_ENVELOPINGWEB); + EnvelopingWeb_Timer = 12000; + }else EnvelopingWeb_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_anubshiah(Creature *_Creature) +{ + return new boss_anubshiahAI (_Creature); +} + +void AddSC_boss_anubshiah() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_anubshiah"; + newscript->GetAI = GetAI_boss_anubshiah; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackrock_depths/boss_doomrel.cpp b/src/bindings/scripts/scripts/zone/blackrock_depths/boss_doomrel.cpp new file mode 100644 index 00000000000..2f70b4ee14c --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackrock_depths/boss_doomrel.cpp @@ -0,0 +1,139 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Doomrel +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Depths +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_SHADOWBOLTVOLLEY 17228 +#define SPELL_IMMOLATE 15505 +#define SPELL_CURSEOFWEAKNESS 17227 +#define SPELL_DEMONARMOR 11735 + +struct MANGOS_DLL_DECL boss_doomrelAI : public ScriptedAI +{ + boss_doomrelAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 ShadowVolley_Timer; + uint32 Immolate_Timer; + uint32 CurseOfWeakness_Timer; + uint32 DemonArmor_Timer; + bool Voidwalkers; + int Rand; + int RandX; + int RandY; + Creature* Summoned; + + void Reset() + { + ShadowVolley_Timer = 10000; + Immolate_Timer = 18000; + CurseOfWeakness_Timer = 5000; + DemonArmor_Timer = 16000; + Voidwalkers = false; + } + + void Aggro(Unit *who) + { + } + + void SummonVoidwalkers(Unit* victim) + { + Rand = rand()%5; + switch (rand()%2) + { + case 0: RandX = 0 - Rand; break; + case 1: RandX = 0 + Rand; break; + } + Rand = 0; + Rand = rand()%5; + switch (rand()%2) + { + case 0: RandY = 0 - Rand; break; + case 1: RandY = 0 + Rand; break; + } + Rand = 0; + Summoned = DoSpawnCreature(16119, RandX, RandY, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000); + if(Summoned) + ((CreatureAI*)Summoned->AI())->AttackStart(victim); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //ShadowVolley_Timer + if (ShadowVolley_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SHADOWBOLTVOLLEY); + ShadowVolley_Timer = 12000; + }else ShadowVolley_Timer -= diff; + + //Immolate_Timer + if (Immolate_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target)DoCast(target,SPELL_IMMOLATE); + Immolate_Timer = 25000; + }else Immolate_Timer -= diff; + + //CurseOfWeakness_Timer + if (CurseOfWeakness_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CURSEOFWEAKNESS); + CurseOfWeakness_Timer = 45000; + }else CurseOfWeakness_Timer -= diff; + + //DemonArmor_Timer + if (DemonArmor_Timer < diff) + { + DoCast(m_creature,SPELL_DEMONARMOR); + DemonArmor_Timer = 300000; + }else DemonArmor_Timer -= diff; + + //Summon Voidwalkers + if (!Voidwalkers && m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 51 ) + { + SummonVoidwalkers(m_creature->getVictim()); + SummonVoidwalkers(m_creature->getVictim()); + SummonVoidwalkers(m_creature->getVictim()); + Voidwalkers = true; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_doomrel(Creature *_Creature) +{ + return new boss_doomrelAI (_Creature); +} + +void AddSC_boss_doomrel() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_doomrel"; + newscript->GetAI = GetAI_boss_doomrel; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackrock_depths/boss_doperel.cpp b/src/bindings/scripts/scripts/zone/blackrock_depths/boss_doperel.cpp new file mode 100644 index 00000000000..3aae6cb1adf --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackrock_depths/boss_doperel.cpp @@ -0,0 +1,91 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Doperel +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Depths +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_SINISTERSTRIKE 15581 +#define SPELL_BACKSTAB 15582 +#define SPELL_GOUGE 13579 + +struct MANGOS_DLL_DECL boss_doperelAI : public ScriptedAI +{ + boss_doperelAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 SinisterStrike_Timer; + uint32 BackStab_Timer; + uint32 Gouge_Timer; + + void Reset() + { + SinisterStrike_Timer = 8000; + BackStab_Timer = 12000; + Gouge_Timer = 6000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //SinisterStrike_Timer + if (SinisterStrike_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SINISTERSTRIKE); + SinisterStrike_Timer = 7000; + }else SinisterStrike_Timer -= diff; + + //BackStab_Timer + if (BackStab_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_BACKSTAB); + BackStab_Timer = 6000; + }else BackStab_Timer -= diff; + + //Gouge_Timer + if (Gouge_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_GOUGE); + Gouge_Timer = 8000; + }else Gouge_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_doperel(Creature *_Creature) +{ + return new boss_doperelAI (_Creature); +} + +void AddSC_boss_doperel() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_doperel"; + newscript->GetAI = GetAI_boss_doperel; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackrock_depths/boss_emperor_dagran_thaurissan.cpp b/src/bindings/scripts/scripts/zone/blackrock_depths/boss_emperor_dagran_thaurissan.cpp new file mode 100644 index 00000000000..cd03b6c1894 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackrock_depths/boss_emperor_dagran_thaurissan.cpp @@ -0,0 +1,104 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Emperor_Dagran_Thaurissan +SD%Complete: 99 +SDComment: +SDCategory: Blackrock Depths +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_HANDOFTHAURISSAN 17492 +#define SPELL_AVATAROFFLAME 15636 + +#define SAY_AGGRO "Come to aid the Throne!" +#define SAY_SLAY "Hail to the king, baby!" + +struct MANGOS_DLL_DECL boss_draganthaurissanAI : public ScriptedAI +{ + boss_draganthaurissanAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 HandOfThaurissan_Timer; + uint32 AvatarOfFlame_Timer; + //uint32 Counter; + + void Reset() + { + HandOfThaurissan_Timer = 4000; + AvatarOfFlame_Timer = 25000; + //Counter= 0; + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); + } + + void KilledUnit(Unit* victim) + { + DoYell(SAY_SLAY, LANG_UNIVERSAL, NULL); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if (HandOfThaurissan_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) DoCast(target,SPELL_HANDOFTHAURISSAN); + + //3 Hands of Thaurissan will be casted + //if (Counter < 3) + //{ + // HandOfThaurissan_Timer = 1000; + // Counter++; + //} + //else + //{ + HandOfThaurissan_Timer = 5000; + //Counter=0; + //} + }else HandOfThaurissan_Timer -= diff; + + //AvatarOfFlame_Timer + if (AvatarOfFlame_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_AVATAROFFLAME); + AvatarOfFlame_Timer = 18000; + }else AvatarOfFlame_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_draganthaurissan(Creature *_Creature) +{ + return new boss_draganthaurissanAI (_Creature); +} + +void AddSC_boss_draganthaurissan() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_emperor_dagran_thaurissan"; + newscript->GetAI = GetAI_boss_draganthaurissan; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackrock_depths/boss_general_angerforge.cpp b/src/bindings/scripts/scripts/zone/blackrock_depths/boss_general_angerforge.cpp new file mode 100644 index 00000000000..2d481bdaeb0 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackrock_depths/boss_general_angerforge.cpp @@ -0,0 +1,167 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_General_Angerforge +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Depths +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_MIGHTYBLOW 14099 +#define SPELL_HAMSTRING 9080 +#define SPELL_CLEAVE 20691 + +struct MANGOS_DLL_DECL boss_general_angerforgeAI : public ScriptedAI +{ + boss_general_angerforgeAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 MightyBlow_Timer; + uint32 HamString_Timer; + uint32 Cleave_Timer; + uint32 Adds_Timer; + bool Medics; + int Rand1; + int Rand1X; + int Rand1Y; + int Rand2; + int Rand2X; + int Rand2Y; + Creature* SummonedAdds; + Creature* SummonedMedics; + + void Reset() + { + MightyBlow_Timer = 8000; + HamString_Timer = 12000; + Cleave_Timer = 16000; + Adds_Timer = 0; + Medics = false; + } + + void Aggro(Unit *who) + { + } + + void SummonAdds(Unit* victim) + { + Rand1 = rand()%15; + switch (rand()%2) + { + case 0: Rand1X = 0 - Rand1; break; + case 1: Rand1X = 0 + Rand1; break; + } + Rand1 = 0; + Rand1 = rand()%15; + switch (rand()%2) + { + case 0: Rand1Y = 0 - Rand1; break; + case 1: Rand1Y = 0 + Rand1; break; + } + Rand1 = 0; + SummonedAdds = DoSpawnCreature(8901, Rand1X, Rand1Y, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000); + if(SummonedAdds) + ((CreatureAI*)SummonedAdds->AI())->AttackStart(victim); + } + + void SummonMedics(Unit* victim) + { + Rand2 = rand()%10; + switch (rand()%2) + { + case 0: Rand2X = 0 - Rand2; break; + case 1: Rand2X = 0 + Rand2; break; + } + Rand2 = 0; + Rand2 = rand()%10; + switch (rand()%2) + { + case 0: Rand2Y = 0 - Rand2; break; + case 1: Rand2Y = 0 + Rand2; break; + } + Rand2 = 0; + SummonedMedics = DoSpawnCreature(8894, Rand2X, Rand2Y, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000); + if(SummonedMedics) + ((CreatureAI*)SummonedMedics->AI())->AttackStart(victim); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //MightyBlow_Timer + if (MightyBlow_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_MIGHTYBLOW); + MightyBlow_Timer = 18000; + }else MightyBlow_Timer -= diff; + + //HamString_Timer + if (HamString_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_HAMSTRING); + HamString_Timer = 15000; + }else HamString_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CLEAVE); + Cleave_Timer = 9000; + }else Cleave_Timer -= diff; + + //Adds_Timer + if ( m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 21 ) + { + if (Adds_Timer < diff) + { + // summon 3 Adds every 25s + SummonAdds(m_creature->getVictim()); + SummonAdds(m_creature->getVictim()); + SummonAdds(m_creature->getVictim()); + + Adds_Timer = 25000; + } else Adds_Timer -= diff; + } + + //Summon Medics + if ( !Medics && m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 21 ) + { + SummonMedics(m_creature->getVictim()); + SummonMedics(m_creature->getVictim()); + Medics = true; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_general_angerforge(Creature *_Creature) +{ + return new boss_general_angerforgeAI (_Creature); +} + +void AddSC_boss_general_angerforge() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_general_angerforge"; + newscript->GetAI = GetAI_boss_general_angerforge; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackrock_depths/boss_gloomrel.cpp b/src/bindings/scripts/scripts/zone/blackrock_depths/boss_gloomrel.cpp new file mode 100644 index 00000000000..cb87855ee53 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackrock_depths/boss_gloomrel.cpp @@ -0,0 +1,142 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Gloomrel +SD%Complete: 80 +SDComment: Learning Smelt Dark Iron if tribute quest rewarded. Missing event and re-spawn GO Spectral Chalice +SDCategory: Blackrock Depths +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_HAMSTRING 9080 +#define SPELL_CLEAVE 15579 +#define SPELL_MORTALSTRIKE 15708 + +struct MANGOS_DLL_DECL boss_gloomrelAI : public ScriptedAI +{ + boss_gloomrelAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 HamString_Timer; + uint32 Cleave_Timer; + uint32 MortalStrike_Timer; + + void Reset() + { + HamString_Timer = 19000; + Cleave_Timer = 6000; + MortalStrike_Timer = 10000; + + m_creature->setFaction(734); + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //HamString_Timer + if (HamString_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_HAMSTRING); + HamString_Timer = 14000; + }else HamString_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CLEAVE); + Cleave_Timer = 8000; + }else Cleave_Timer -= diff; + + //MortalStrike_Timer + if (MortalStrike_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_MORTALSTRIKE); + MortalStrike_Timer = 12000; + }else MortalStrike_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_gloomrel(Creature *_Creature) +{ + return new boss_gloomrelAI (_Creature); +} + +bool GossipHello_boss_gloomrel(Player *player, Creature *_Creature) +{ + if (player->GetQuestRewardStatus(4083) == 1 && player->GetSkillValue(SKILL_MINING) >= 230 && !player->HasSpell(14891) ) + player->ADD_GOSSIP_ITEM(0, "Teach me the art of smelting dark iron", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + + if (player->GetQuestRewardStatus(4083) == 0 && player->GetSkillValue(SKILL_MINING) >= 230) + player->ADD_GOSSIP_ITEM(0, "I want to pay tribute", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + + player->ADD_GOSSIP_ITEM(0, "Challenge", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->SEND_GOSSIP_MENU(2602, _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_boss_gloomrel(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF+1: + player->ADD_GOSSIP_ITEM( 0, "Continue...", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->SEND_GOSSIP_MENU(2606, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+11: + player->CLOSE_GOSSIP_MENU(); + _Creature->CastSpell(player, 14894, false); + break; + case GOSSIP_ACTION_INFO_DEF+2: + player->ADD_GOSSIP_ITEM( 0, "[PH] Continue...", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 22); + player->SEND_GOSSIP_MENU(2604, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+22: + player->CLOSE_GOSSIP_MENU(); + //re-spawn object here + break; + case GOSSIP_ACTION_INFO_DEF+3: + player->ADD_GOSSIP_ITEM( 0, "[PH] Continue...", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 33); + player->SEND_GOSSIP_MENU(2605, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+33: + player->CLOSE_GOSSIP_MENU(); + //start event here, below code just temporary + _Creature->setFaction(754); + break; + } + return true; +} + +void AddSC_boss_gloomrel() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_gloomrel"; + newscript->GetAI = GetAI_boss_gloomrel; + newscript->pGossipHello = &GossipHello_boss_gloomrel; + newscript->pGossipSelect = &GossipSelect_boss_gloomrel; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackrock_depths/boss_gorosh_the_dervish.cpp b/src/bindings/scripts/scripts/zone/blackrock_depths/boss_gorosh_the_dervish.cpp new file mode 100644 index 00000000000..df67093e61f --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackrock_depths/boss_gorosh_the_dervish.cpp @@ -0,0 +1,81 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Gorosh_the_Dervish +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Depths +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_WHIRLWIND 15589 +#define SPELL_MORTALSTRIKE 24573 + +struct MANGOS_DLL_DECL boss_gorosh_the_dervishAI : public ScriptedAI +{ + boss_gorosh_the_dervishAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 WhirlWind_Timer; + uint32 MortalStrike_Timer; + + void Reset() + { + WhirlWind_Timer = 12000; + MortalStrike_Timer = 22000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //WhirlWind_Timer + if (WhirlWind_Timer < diff) + { + DoCast(m_creature,SPELL_WHIRLWIND); + WhirlWind_Timer = 15000; + }else WhirlWind_Timer -= diff; + + //MortalStrike_Timer + if (MortalStrike_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_MORTALSTRIKE); + MortalStrike_Timer = 15000; + }else MortalStrike_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_gorosh_the_dervish(Creature *_Creature) +{ + return new boss_gorosh_the_dervishAI (_Creature); +} + +void AddSC_boss_gorosh_the_dervish() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_gorosh_the_dervish"; + newscript->GetAI = GetAI_boss_gorosh_the_dervish; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackrock_depths/boss_grizzle.cpp b/src/bindings/scripts/scripts/zone/blackrock_depths/boss_grizzle.cpp new file mode 100644 index 00000000000..7e248c2d17b --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackrock_depths/boss_grizzle.cpp @@ -0,0 +1,86 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Grizzle +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Depths +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_GROUNDTREMOR 6524 +#define SPELL_FRENZY 28371 + +struct MANGOS_DLL_DECL boss_grizzleAI : public ScriptedAI +{ + boss_grizzleAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 GroundTremor_Timer; + uint32 Frenzy_Timer; + + void Reset() + { + GroundTremor_Timer = 12000; + Frenzy_Timer =0; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //GroundTremor_Timer + if (GroundTremor_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_GROUNDTREMOR); + GroundTremor_Timer = 8000; + }else GroundTremor_Timer -= diff; + + //Frenzy_Timer + if ( m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 51 ) + { + if (Frenzy_Timer < diff) + { + DoCast(m_creature,SPELL_FRENZY); + DoTextEmote("goes into a killing frenzy!",NULL); + + Frenzy_Timer = 15000; + }else Frenzy_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_grizzle(Creature *_Creature) +{ + return new boss_grizzleAI (_Creature); +} + +void AddSC_boss_grizzle() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_grizzle"; + newscript->GetAI = GetAI_boss_grizzle; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackrock_depths/boss_haterel.cpp b/src/bindings/scripts/scripts/zone/blackrock_depths/boss_haterel.cpp new file mode 100644 index 00000000000..1392eb54943 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackrock_depths/boss_haterel.cpp @@ -0,0 +1,105 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Haterel +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Depths +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_SHADOWBOLT 17483 //Not sure if right ID +#define SPELL_MANABURN 10876 +#define SPELL_SHADOWSHIELD 22417 +#define SPELL_STRIKE 15580 + +struct MANGOS_DLL_DECL boss_haterelAI : public ScriptedAI +{ + boss_haterelAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 ShadowBolt_Timer; + uint32 ManaBurn_Timer; + uint32 ShadowShield_Timer; + uint32 Strike_Timer; + + void Reset() + { + ShadowBolt_Timer = 15000; + ManaBurn_Timer = 3000; + ShadowShield_Timer = 8000; + Strike_Timer = 12000; + } + + void Aggro(Unit *who) + { + } + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //ShadowBolt_Timer + if (ShadowBolt_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) DoCast(target,SPELL_SHADOWBOLT); + ShadowBolt_Timer = 7000; + }else ShadowBolt_Timer -= diff; + + //ManaBurn_Timer + if (ManaBurn_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) DoCast(target,SPELL_MANABURN); + ManaBurn_Timer = 13000; + }else ManaBurn_Timer -= diff; + + //ShadowShield_Timer + if (ShadowShield_Timer < diff) + { + DoCast(m_creature,SPELL_SHADOWSHIELD); + ShadowShield_Timer = 25000; + }else ShadowShield_Timer -= diff; + + //Strike_Timer + if (Strike_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_STRIKE); + Strike_Timer = 10000; + }else Strike_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_haterel(Creature *_Creature) +{ + return new boss_haterelAI (_Creature); +} + +void AddSC_boss_haterel() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_haterel"; + newscript->GetAI = GetAI_boss_haterel; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackrock_depths/boss_high_interrogator_gerstahn.cpp b/src/bindings/scripts/scripts/zone/blackrock_depths/boss_high_interrogator_gerstahn.cpp new file mode 100644 index 00000000000..c4393560d10 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackrock_depths/boss_high_interrogator_gerstahn.cpp @@ -0,0 +1,105 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_High_Interrogator_Gerstahn +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Depths +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_SHADOWWORDPAIN 10894 +#define SPELL_MANABURN 10876 +#define SPELL_PSYCHICSCREAM 8122 +#define SPELL_SHADOWSHIELD 22417 + +struct MANGOS_DLL_DECL boss_high_interrogator_gerstahnAI : public ScriptedAI +{ + boss_high_interrogator_gerstahnAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 ShadowWordPain_Timer; + uint32 ManaBurn_Timer; + uint32 PsychicScream_Timer; + uint32 ShadowShield_Timer; + + void Reset() + { + ShadowWordPain_Timer = 4000; + ManaBurn_Timer = 14000; + PsychicScream_Timer = 32000; + ShadowShield_Timer = 8000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //ShadowWordPain_Timer + if (ShadowWordPain_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target)DoCast(target,SPELL_SHADOWWORDPAIN); + ShadowWordPain_Timer = 7000; + }else ShadowWordPain_Timer -= diff; + + //ManaBurn_Timer + if (ManaBurn_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target)DoCast(target,SPELL_MANABURN); + ManaBurn_Timer = 10000; + }else ManaBurn_Timer -= diff; + + //PsychicScream_Timer + if (PsychicScream_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_PSYCHICSCREAM); + PsychicScream_Timer = 30000; + }else PsychicScream_Timer -= diff; + + //ShadowShield_Timer + if (ShadowShield_Timer < diff) + { + DoCast(m_creature,SPELL_SHADOWSHIELD); + ShadowShield_Timer = 25000; + }else ShadowShield_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_high_interrogator_gerstahn(Creature *_Creature) +{ + return new boss_high_interrogator_gerstahnAI (_Creature); +} + +void AddSC_boss_high_interrogator_gerstahn() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_high_interrogator_gerstahn"; + newscript->GetAI = GetAI_boss_high_interrogator_gerstahn; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackrock_depths/boss_magmus.cpp b/src/bindings/scripts/scripts/zone/blackrock_depths/boss_magmus.cpp new file mode 100644 index 00000000000..62d2f6d8147 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackrock_depths/boss_magmus.cpp @@ -0,0 +1,84 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Magmus +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Depths +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_FIERYBURST 13900 +#define SPELL_WARSTOMP 24375 + +struct MANGOS_DLL_DECL boss_magmusAI : public ScriptedAI +{ + boss_magmusAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 FieryBurst_Timer; + uint32 WarStomp_Timer; + + void Reset() + { + FieryBurst_Timer = 5000; + WarStomp_Timer =0; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //FieryBurst_Timer + if (FieryBurst_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FIERYBURST); + FieryBurst_Timer = 6000; + }else FieryBurst_Timer -= diff; + + //WarStomp_Timer + if ( m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 51 ) + { + if (WarStomp_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_WARSTOMP); + WarStomp_Timer = 8000; + }else WarStomp_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_magmus(Creature *_Creature) +{ + return new boss_magmusAI (_Creature); +} + +void AddSC_boss_magmus() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_magmus"; + newscript->GetAI = GetAI_boss_magmus; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackrock_depths/boss_moira_bronzebeard.cpp b/src/bindings/scripts/scripts/zone/blackrock_depths/boss_moira_bronzebeard.cpp new file mode 100644 index 00000000000..b7dfadd385d --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackrock_depths/boss_moira_bronzebeard.cpp @@ -0,0 +1,99 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Moira_Bronzbeard +SD%Complete: 90 +SDComment: Healing of Emperor NYI +SDCategory: Blackrock Depths +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_HEAL 10917 +#define SPELL_RENEW 10929 +#define SPELL_SHIELD 10901 +#define SPELL_MINDBLAST 10947 +#define SPELL_SHADOWWORDPAIN 10894 +#define SPELL_SMITE 10934 + +struct MANGOS_DLL_DECL boss_moira_bronzebeardAI : public ScriptedAI +{ + boss_moira_bronzebeardAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Heal_Timer; + uint32 MindBlast_Timer; + uint32 ShadowWordPain_Timer; + uint32 Smite_Timer; + Unit* PlayerHolder; + Unit* Target; + bool Heal; + + void Reset() + { + Target = NULL; + Heal_Timer = 12000; //These times are probably wrong + MindBlast_Timer = 16000; + ShadowWordPain_Timer = 2000; + Smite_Timer = 8000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //MindBlast_Timer + if (MindBlast_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_MINDBLAST); + MindBlast_Timer = 14000; + }else MindBlast_Timer -= diff; + + //ShadowWordPain_Timer + if (ShadowWordPain_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SHADOWWORDPAIN); + ShadowWordPain_Timer = 18000; + }else ShadowWordPain_Timer -= diff; + + //Smite_Timer + if (Smite_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SMITE); + Smite_Timer = 10000; + }else Smite_Timer -= diff; + + } +}; +CreatureAI* GetAI_boss_moira_bronzebeard(Creature *_Creature) +{ + return new boss_moira_bronzebeardAI (_Creature); +} + +void AddSC_boss_moira_bronzebeard() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_moira_bronzebeard"; + newscript->GetAI = GetAI_boss_moira_bronzebeard; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackrock_depths/boss_seethrel.cpp b/src/bindings/scripts/scripts/zone/blackrock_depths/boss_seethrel.cpp new file mode 100644 index 00000000000..f1d703924fb --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackrock_depths/boss_seethrel.cpp @@ -0,0 +1,115 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Seethrel +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Depths +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_FROSTBOLT 16799 +#define SPELL_FROSTARMOR 15784 //This is actually a buff he gives himself +#define SPELL_BLIZZARD 19099 +#define SPELL_FROSTNOVA 15063 +#define SPELL_FROSTWARD 15004 + +struct MANGOS_DLL_DECL boss_seethrelAI : public ScriptedAI +{ + boss_seethrelAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 FrostArmor_Timer; + uint32 Frostbolt_Timer; + uint32 Blizzard_Timer; + uint32 FrostNova_Timer; + uint32 FrostWard_Timer; + + void Reset() + { + FrostArmor_Timer = 2000; + Frostbolt_Timer = 6000; + Blizzard_Timer = 18000; + FrostNova_Timer = 12000; + FrostWard_Timer = 25000; + + m_creature->CastSpell(m_creature,SPELL_FROSTARMOR,true); + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //FrostArmor_Timer + if (FrostArmor_Timer < diff) + { + DoCast(m_creature, SPELL_FROSTARMOR); + FrostArmor_Timer = 180000; + }else FrostArmor_Timer -= diff; + + //Frostbolt_Timer + if (Frostbolt_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FROSTBOLT); + Frostbolt_Timer = 15000; + }else Frostbolt_Timer -= diff; + + //Blizzard_Timer + if (Blizzard_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) DoCast(target,SPELL_BLIZZARD); + Blizzard_Timer = 22000; + }else Blizzard_Timer -= diff; + + //FrostNova_Timer + if (FrostNova_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FROSTNOVA); + FrostNova_Timer = 14000; + }else FrostNova_Timer -= diff; + + //FrostWard_Timer + if (FrostWard_Timer < diff) + { + DoCast(m_creature,SPELL_FROSTWARD); + FrostWard_Timer = 68000; + }else FrostWard_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_seethrel(Creature *_Creature) +{ + return new boss_seethrelAI (_Creature); +} + +void AddSC_boss_seethrel() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_seethrel"; + newscript->GetAI = GetAI_boss_seethrel; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackrock_depths/boss_vilerel.cpp b/src/bindings/scripts/scripts/zone/blackrock_depths/boss_vilerel.cpp new file mode 100644 index 00000000000..2c7508a0311 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackrock_depths/boss_vilerel.cpp @@ -0,0 +1,101 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Vilerel +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Depths +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_MINDBLAST 15587 +#define SPELL_HEAL 15586 +#define SPELL_PRAYEROFHEALING 15585 +#define SPELL_SHIELD 10901 + +struct MANGOS_DLL_DECL boss_vilerelAI : public ScriptedAI +{ + boss_vilerelAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 MindBlast_Timer; + uint32 Heal_Timer; + uint32 PrayerOfHealing_Timer; + uint32 Shield_Timer; + + void Reset() + { + MindBlast_Timer = 10000; + Heal_Timer = 35000; + PrayerOfHealing_Timer = 25000; + Shield_Timer = 3000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //MindBlast_Timer + if (MindBlast_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_MINDBLAST); + MindBlast_Timer = 7000; + }else MindBlast_Timer -= diff; + + //Heal_Timer + if (Heal_Timer < diff) + { + DoCast(m_creature,SPELL_HEAL); + Heal_Timer = 20000; + }else Heal_Timer -= diff; + + //PrayerOfHealing_Timer + if (PrayerOfHealing_Timer < diff) + { + DoCast(m_creature,SPELL_PRAYEROFHEALING); + PrayerOfHealing_Timer = 30000; + }else PrayerOfHealing_Timer -= diff; + + //Shield_Timer + if (Shield_Timer < diff) + { + DoCast(m_creature,SPELL_SHIELD); + Shield_Timer = 30000; + }else Shield_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_vilerel(Creature *_Creature) +{ + return new boss_vilerelAI (_Creature); +} + +void AddSC_boss_vilerel() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_vilerel"; + newscript->GetAI = GetAI_boss_vilerel; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackrock_spire/boss_drakkisath.cpp b/src/bindings/scripts/scripts/zone/blackrock_spire/boss_drakkisath.cpp new file mode 100644 index 00000000000..a69334aeac8 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackrock_spire/boss_drakkisath.cpp @@ -0,0 +1,101 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Drakkisath +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Spire +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_FIRENOVA 23462 +#define SPELL_CLEAVE 20691 +#define SPELL_CONFLIGURATION 16805 +#define SPELL_THUNDERCLAP 15548 //Not sure if right ID. 23931 would be a harder possibility. + +struct MANGOS_DLL_DECL boss_drakkisathAI : public ScriptedAI +{ + boss_drakkisathAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 FireNova_Timer; + uint32 Cleave_Timer; + uint32 Confliguration_Timer; + uint32 Thunderclap_Timer; + + void Reset() + { + FireNova_Timer = 6000; + Cleave_Timer = 8000; + Confliguration_Timer = 15000; + Thunderclap_Timer = 17000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //FireNova_Timer + if (FireNova_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FIRENOVA); + FireNova_Timer = 10000; + }else FireNova_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CLEAVE); + Cleave_Timer = 8000; + }else Cleave_Timer -= diff; + + //Confliguration_Timer + if (Confliguration_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CONFLIGURATION); + Confliguration_Timer = 18000; + }else Confliguration_Timer -= diff; + + //Thunderclap_Timer + if (Thunderclap_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_THUNDERCLAP); + Thunderclap_Timer = 20000; + }else Thunderclap_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_drakkisath(Creature *_Creature) +{ + return new boss_drakkisathAI (_Creature); +} + +void AddSC_boss_drakkisath() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_drakkisath"; + newscript->GetAI = GetAI_boss_drakkisath; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackrock_spire/boss_gyth.cpp b/src/bindings/scripts/scripts/zone/blackrock_spire/boss_gyth.cpp new file mode 100644 index 00000000000..e2edaf7d07d --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackrock_spire/boss_gyth.cpp @@ -0,0 +1,205 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Gyth +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Spire +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_CORROSIVEACID 20667 +#define SPELL_FREEZE 18763 +#define SPELL_FLAMEBREATH 20712 + +struct MANGOS_DLL_DECL boss_gythAI : public ScriptedAI +{ + boss_gythAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Aggro_Timer; + uint32 Dragons_Timer; + uint32 Orc_Timer; + uint32 CorrosiveAcid_Timer; + uint32 Freeze_Timer; + uint32 Flamebreath_Timer; + uint32 Line1Count; + uint32 Line2Count; + + bool Event; + bool SummonedDragons; + bool SummonedOrcs; + bool SummonedRend; + bool bAggro; + bool RootSelf; + Creature *SummonedCreature; + + void Reset() + { + Dragons_Timer = 3000; + Orc_Timer = 60000; + Aggro_Timer = 60000; + CorrosiveAcid_Timer = 8000; + Freeze_Timer = 11000; + Flamebreath_Timer = 4000; + Event = false; + SummonedDragons = false; + SummonedOrcs= false; + SummonedRend = false; + bAggro = false; + RootSelf = false; + + // how many times should the two lines of summoned creatures be spawned + // min 2 x 2, max 7 lines of attack in total + Line1Count = rand() % 4 + 2; + if (Line1Count < 5) + Line2Count = rand() % (5 - Line1Count) + 2; + else + Line2Count = 2; + + //Invisible for event start + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, 11686); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void Aggro(Unit *who) + { + } + + void SummonCreatureWithRandomTarget(uint32 creatureId) + { + Unit* Summoned = m_creature->SummonCreature(creatureId, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 240000); + if (Summoned) + { + Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (target) + Summoned->AddThreat(target, 1.0f); + } + } + + void UpdateAI(const uint32 diff) + { + //char buf[200]; + + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if (!RootSelf) + { + //m_creature->m_canMove = true; + DoCast(m_creature, 33356); + RootSelf = true; + } + + if (!bAggro && Line1Count == 0 && Line2Count == 0) + { + if (Aggro_Timer < diff) + { + bAggro = true; + // Visible now! + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, 9723); + m_creature->setFaction(14); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } else Aggro_Timer -= diff; + } + + // Summon Dragon pack. 2 Dragons and 3 Whelps + if (!bAggro && !SummonedRend && Line1Count > 0) + { + if (Dragons_Timer < diff) + { + SummonCreatureWithRandomTarget(10372); + SummonCreatureWithRandomTarget(10372); + SummonCreatureWithRandomTarget(10442); + SummonCreatureWithRandomTarget(10442); + SummonCreatureWithRandomTarget(10442); + Line1Count = Line1Count - 1; + Dragons_Timer = 60000; + } else Dragons_Timer -= diff; + } + + //Summon Orc pack. 1 Orc Handler 1 Elite Dragonkin and 3 Whelps + if (!bAggro && !SummonedRend && Line1Count == 0 && Line2Count > 0) + { + if (Orc_Timer < diff) + { + SummonCreatureWithRandomTarget(10447); + SummonCreatureWithRandomTarget(10317); + SummonCreatureWithRandomTarget(10442); + SummonCreatureWithRandomTarget(10442); + SummonCreatureWithRandomTarget(10442); + Line2Count = Line2Count - 1; + Orc_Timer = 60000; + } else Orc_Timer -= diff; + } + + // we take part in the fight + if (bAggro) + { + // CorrosiveAcid_Timer + if (CorrosiveAcid_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_CORROSIVEACID); + CorrosiveAcid_Timer = 7000; + } else CorrosiveAcid_Timer -= diff; + + // Freeze_Timer + if (Freeze_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_FREEZE); + Freeze_Timer = 16000; + } else Freeze_Timer -= diff; + + // Flamebreath_Timer + if (Flamebreath_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FLAMEBREATH); + Flamebreath_Timer = 10500; + } else Flamebreath_Timer -= diff; + + //Summon Rend + if (!SummonedRend && m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 11 + && m_creature->GetHealth() > 0 ) + { + //summon Rend and Change model to normal Gyth + //Inturrupt any spell casting + m_creature->InterruptNonMeleeSpells(false); + //Gyth model + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, 9806); + m_creature->SummonCreature(10429, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 900000); + SummonedRend = true; + } + + DoMeleeAttackIfReady(); + } // end if Aggro + } +}; + +CreatureAI* GetAI_boss_gyth(Creature *_Creature) +{ + return new boss_gythAI (_Creature); +} + +void AddSC_boss_gyth() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_gyth"; + newscript->GetAI = GetAI_boss_gyth; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackrock_spire/boss_halycon.cpp b/src/bindings/scripts/scripts/zone/blackrock_spire/boss_halycon.cpp new file mode 100644 index 00000000000..27509b43355 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackrock_spire/boss_halycon.cpp @@ -0,0 +1,95 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Halycon +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Spire +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_CROWDPUMMEL 10887 +#define SPELL_MIGHTYBLOW 14099 + +#define ADD_1X -169.839203 +#define ADD_1Y -324.961395 +#define ADD_1Z 64.401443 +#define ADD_1O 3.124724 + +struct MANGOS_DLL_DECL boss_halyconAI : public ScriptedAI +{ + boss_halyconAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 CrowdPummel_Timer; + uint32 MightyBlow_Timer; + bool Summoned; + + void Reset() + { + CrowdPummel_Timer = 8000; + MightyBlow_Timer = 14000; + Summoned = false; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //CrowdPummel_Timer + if (CrowdPummel_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CROWDPUMMEL); + CrowdPummel_Timer = 14000; + }else CrowdPummel_Timer -= diff; + + //MightyBlow_Timer + if (MightyBlow_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_MIGHTYBLOW); + MightyBlow_Timer = 10000; + }else MightyBlow_Timer -= diff; + + //Summon Gizrul + if ( !Summoned && m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 25 ) + { + m_creature->SummonCreature(10268,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,300000); + Summoned = true; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_halycon(Creature *_Creature) +{ + return new boss_halyconAI (_Creature); +} + +void AddSC_boss_halycon() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_halycon"; + newscript->GetAI = GetAI_boss_halycon; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackrock_spire/boss_highlord_omokk.cpp b/src/bindings/scripts/scripts/zone/blackrock_spire/boss_highlord_omokk.cpp new file mode 100644 index 00000000000..b0fc6b3ac14 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackrock_spire/boss_highlord_omokk.cpp @@ -0,0 +1,131 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Highlord_Omokk +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Spire +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_WARSTOMP 24375 +#define SPELL_CLEAVE 15579 +#define SPELL_STRIKE 18368 +#define SPELL_REND 18106 +#define SPELL_SUNDERARMOR 24317 +#define SPELL_KNOCKAWAY 20686 +#define SPELL_SLOW 22356 + +struct MANGOS_DLL_DECL boss_highlordomokkAI : public ScriptedAI +{ + boss_highlordomokkAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 WarStomp_Timer; + uint32 Cleave_Timer; + uint32 Strike_Timer; + uint32 Rend_Timer; + uint32 SunderArmor_Timer; + uint32 KnockAway_Timer; + uint32 Slow_Timer; + + void Reset() + { + WarStomp_Timer = 15000; + Cleave_Timer = 6000; + Strike_Timer = 10000; + Rend_Timer = 14000; + SunderArmor_Timer = 2000; + KnockAway_Timer = 18000; + Slow_Timer = 24000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //WarStomp_Timer + if (WarStomp_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_WARSTOMP); + WarStomp_Timer = 14000; + }else WarStomp_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CLEAVE); + Cleave_Timer = 8000; + }else Cleave_Timer -= diff; + + //Strike_Timer + if (Strike_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_STRIKE); + Strike_Timer = 10000; + }else Strike_Timer -= diff; + + //Rend_Timer + if (Rend_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_REND); + Rend_Timer = 18000; + }else Rend_Timer -= diff; + + //SunderArmor_Timer + if (SunderArmor_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SUNDERARMOR); + SunderArmor_Timer = 25000; + }else SunderArmor_Timer -= diff; + + //KnockAway_Timer + if (KnockAway_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_KNOCKAWAY); + KnockAway_Timer = 12000; + }else KnockAway_Timer -= diff; + + //Slow_Timer + if (Slow_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SLOW); + Slow_Timer = 18000; + }else Slow_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_highlordomokk(Creature *_Creature) +{ + return new boss_highlordomokkAI (_Creature); +} + +void AddSC_boss_highlordomokk() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_highlord_omokk"; + newscript->GetAI = GetAI_boss_highlordomokk; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackrock_spire/boss_mother_smolderweb.cpp b/src/bindings/scripts/scripts/zone/blackrock_spire/boss_mother_smolderweb.cpp new file mode 100644 index 00000000000..04cef92dcc1 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackrock_spire/boss_mother_smolderweb.cpp @@ -0,0 +1,86 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Mother_Smolderweb +SD%Complete: 100 +SDComment: Uncertain how often mother's milk is casted +SDCategory: Blackrock Spire +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_CRYSTALIZE 16104 +#define SPELL_MOTHERSMILK 16468 +#define SPELL_SUMMON_SPIRE_SPIDERLING 16103 + +struct MANGOS_DLL_DECL boss_mothersmolderwebAI : public ScriptedAI +{ + boss_mothersmolderwebAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Crystalize_Timer; + uint32 MothersMilk_Timer; + + void Reset() + { + Crystalize_Timer = 20000; + MothersMilk_Timer = 10000; + } + + void Aggro(Unit *who) { } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if( m_creature->GetHealth() <= damage ) + m_creature->CastSpell(m_creature,SPELL_SUMMON_SPIRE_SPIDERLING,true); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //Crystalize_Timer + if( Crystalize_Timer < diff ) + { + DoCast(m_creature,SPELL_CRYSTALIZE); + Crystalize_Timer = 15000; + }else Crystalize_Timer -= diff; + + //MothersMilk_Timer + if( MothersMilk_Timer < diff ) + { + DoCast(m_creature,SPELL_MOTHERSMILK); + MothersMilk_Timer = 5000+rand()%7500; + }else MothersMilk_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_mothersmolderweb(Creature *_Creature) +{ + return new boss_mothersmolderwebAI (_Creature); +} + +void AddSC_boss_mothersmolderweb() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_mother_smolderweb"; + newscript->GetAI = GetAI_boss_mothersmolderweb; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackrock_spire/boss_overlord_wyrmthalak.cpp b/src/bindings/scripts/scripts/zone/blackrock_spire/boss_overlord_wyrmthalak.cpp new file mode 100644 index 00000000000..3eabd522ccc --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackrock_spire/boss_overlord_wyrmthalak.cpp @@ -0,0 +1,127 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Overlord_Wyrmthalak +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Spire +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_BLASTWAVE 11130 +#define SPELL_SHOUT 23511 +#define SPELL_CLEAVE 20691 +#define SPELL_KNOCKAWAY 20686 + +#define ADD_1X -39.355381 +#define ADD_1Y -513.456482 +#define ADD_1Z 88.472046 +#define ADD_1O 4.679872 + +#define ADD_2X -49.875881 +#define ADD_2Y -511.896942 +#define ADD_2Z 88.195160 +#define ADD_2O 4.613114 + +struct MANGOS_DLL_DECL boss_overlordwyrmthalakAI : public ScriptedAI +{ + boss_overlordwyrmthalakAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 BlastWave_Timer; + uint32 Shout_Timer; + uint32 Cleave_Timer; + uint32 Knockaway_Timer; + bool Summoned; + Creature *SummonedCreature; + + void Reset() + { + BlastWave_Timer = 20000; + Shout_Timer = 2000; + Cleave_Timer = 6000; + Knockaway_Timer = 12000; + Summoned = false; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //BlastWave_Timer + if (BlastWave_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_BLASTWAVE); + BlastWave_Timer = 20000; + }else BlastWave_Timer -= diff; + + //Shout_Timer + if (Shout_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SHOUT); + Shout_Timer = 10000; + }else Shout_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CLEAVE); + Cleave_Timer = 7000; + }else Cleave_Timer -= diff; + + //Knockaway_Timer + if (Knockaway_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_KNOCKAWAY); + Knockaway_Timer = 14000; + }else Knockaway_Timer -= diff; + + //Summon two Beserks + if ( !Summoned && m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 51 ) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + + SummonedCreature = m_creature->SummonCreature(9216,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,300000); + ((CreatureAI*)SummonedCreature->AI())->AttackStart(target); + SummonedCreature = m_creature->SummonCreature(9268,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,300000); + ((CreatureAI*)SummonedCreature->AI())->AttackStart(target); + Summoned = true; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_overlordwyrmthalak(Creature *_Creature) +{ + return new boss_overlordwyrmthalakAI (_Creature); +} + +void AddSC_boss_overlordwyrmthalak() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_overlord_wyrmthalak"; + newscript->GetAI = GetAI_boss_overlordwyrmthalak; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackrock_spire/boss_pyroguard_emberseer.cpp b/src/bindings/scripts/scripts/zone/blackrock_spire/boss_pyroguard_emberseer.cpp new file mode 100644 index 00000000000..248ea48f9e0 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackrock_spire/boss_pyroguard_emberseer.cpp @@ -0,0 +1,93 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Pyroguard_Emberseer +SD%Complete: 100 +SDComment: Event to activate Emberseer NYI +SDCategory: Blackrock Spire +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_FIRENOVA 23462 +#define SPELL_FLAMEBUFFET 23341 +#define SPELL_PYROBLAST 17274 + +struct MANGOS_DLL_DECL boss_pyroguard_emberseerAI : public ScriptedAI +{ + boss_pyroguard_emberseerAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 FireNova_Timer; + uint32 FlameBuffet_Timer; + uint32 PyroBlast_Timer; + + void Reset() + { + FireNova_Timer = 6000; + FlameBuffet_Timer = 3000; + PyroBlast_Timer = 14000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //FireNova_Timer + if (FireNova_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FIRENOVA); + FireNova_Timer = 6000; + }else FireNova_Timer -= diff; + + //FlameBuffet_Timer + if (FlameBuffet_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FLAMEBUFFET); + FlameBuffet_Timer = 14000; + }else FlameBuffet_Timer -= diff; + + //PyroBlast_Timer + if (PyroBlast_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) DoCast(target,SPELL_PYROBLAST); + PyroBlast_Timer = 15000; + }else PyroBlast_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_pyroguard_emberseer(Creature *_Creature) +{ + return new boss_pyroguard_emberseerAI (_Creature); +} + +void AddSC_boss_pyroguard_emberseer() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_pyroguard_emberseer"; + newscript->GetAI = GetAI_boss_pyroguard_emberseer; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackrock_spire/boss_quartermaster_zigris.cpp b/src/bindings/scripts/scripts/zone/blackrock_spire/boss_quartermaster_zigris.cpp new file mode 100644 index 00000000000..6955ae8ad71 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackrock_spire/boss_quartermaster_zigris.cpp @@ -0,0 +1,85 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Quartmaster_Zigris +SD%Complete: 100 +SDComment: Needs revision +SDCategory: Blackrock Spire +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_SHOOT 16496 +#define SPELL_STUNBOMB 16497 +#define SPELL_HEALING_POTION 15504 +#define SPELL_HOOKEDNET 15609 + +struct MANGOS_DLL_DECL boss_quatermasterzigrisAI : public ScriptedAI +{ + boss_quatermasterzigrisAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Shoot_Timer; + uint32 StunBomb_Timer; + //uint32 HelingPotion_Timer; + + void Reset() + { + Shoot_Timer = 1000; + StunBomb_Timer = 16000; + //HelingPotion_Timer = 25000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //Shoot_Timer + if (Shoot_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SHOOT); + Shoot_Timer = 500; + }else Shoot_Timer -= diff; + + //StunBomb_Timer + if (StunBomb_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_STUNBOMB); + StunBomb_Timer = 14000; + }else StunBomb_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_quatermasterzigris(Creature *_Creature) +{ + return new boss_quatermasterzigrisAI (_Creature); +} + +void AddSC_boss_quatermasterzigris() +{ + Script *newscript; + newscript = new Script; + newscript->Name="quartermaster_zigris"; + newscript->GetAI = GetAI_boss_quatermasterzigris; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackrock_spire/boss_rend_blackhand.cpp b/src/bindings/scripts/scripts/zone/blackrock_spire/boss_rend_blackhand.cpp new file mode 100644 index 00000000000..679f92a06b6 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackrock_spire/boss_rend_blackhand.cpp @@ -0,0 +1,91 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Rend_Blackhand +SD%Complete: 100 +SDComment: Intro event NYI +SDCategory: Blackrock Spire +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_WHIRLWIND 26038 +#define SPELL_CLEAVE 20691 +#define SPELL_THUNDERCLAP 23931 //Not sure if he cast this spell + +struct MANGOS_DLL_DECL boss_rend_blackhandAI : public ScriptedAI +{ + boss_rend_blackhandAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 WhirlWind_Timer; + uint32 Cleave_Timer; + uint32 Thunderclap_Timer; + + void Reset() + { + WhirlWind_Timer = 20000; + Cleave_Timer = 5000; + Thunderclap_Timer = 9000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //WhirlWind_Timer + if (WhirlWind_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_WHIRLWIND); + WhirlWind_Timer = 18000; + }else WhirlWind_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CLEAVE); + Cleave_Timer = 10000; + }else Cleave_Timer -= diff; + + //Thunderclap_Timer + if (Thunderclap_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_THUNDERCLAP); + Thunderclap_Timer = 16000; + }else Thunderclap_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_rend_blackhand(Creature *_Creature) +{ + return new boss_rend_blackhandAI (_Creature); +} + +void AddSC_boss_rend_blackhand() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_rend_blackhand"; + newscript->GetAI = GetAI_boss_rend_blackhand; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackrock_spire/boss_shadow_hunter_voshgajin.cpp b/src/bindings/scripts/scripts/zone/blackrock_spire/boss_shadow_hunter_voshgajin.cpp new file mode 100644 index 00000000000..bc43f2e223a --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackrock_spire/boss_shadow_hunter_voshgajin.cpp @@ -0,0 +1,95 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Shadow_Hunter_Voshgajin +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Spire +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_CURSEOFBLOOD 24673 +#define SPELL_HEX 16708 +#define SPELL_CLEAVE 20691 + +struct MANGOS_DLL_DECL boss_shadowvoshAI : public ScriptedAI +{ + boss_shadowvoshAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 CurseOfBlood_Timer; + uint32 Hex_Timer; + uint32 Cleave_Timer; + + void Reset() + { + CurseOfBlood_Timer = 2000; + Hex_Timer = 8000; + Cleave_Timer = 14000; + + //m_creature->CastSpell(m_creature,SPELL_ICEARMOR,true); + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //CurseOfBlood_Timer + if (CurseOfBlood_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CURSEOFBLOOD); + CurseOfBlood_Timer = 45000; + }else CurseOfBlood_Timer -= diff; + + //Hex_Timer + if (Hex_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) DoCast(target,SPELL_HEX); + Hex_Timer = 15000; + }else Hex_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CLEAVE); + Cleave_Timer = 7000; + }else Cleave_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_shadowvosh(Creature *_Creature) +{ + return new boss_shadowvoshAI (_Creature); +} + +void AddSC_boss_shadowvosh() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_shadow_hunter_voshgajin"; + newscript->GetAI = GetAI_boss_shadowvosh; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackrock_spire/boss_the_beast.cpp b/src/bindings/scripts/scripts/zone/blackrock_spire/boss_the_beast.cpp new file mode 100644 index 00000000000..93a30ecd204 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackrock_spire/boss_the_beast.cpp @@ -0,0 +1,93 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_The_Best +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Spire +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_FLAMEBREAK 16785 +#define SPELL_IMMOLATE 20294 +#define SPELL_TERRIFYINGROAR 14100 + +struct MANGOS_DLL_DECL boss_thebeastAI : public ScriptedAI +{ + boss_thebeastAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Flamebreak_Timer; + uint32 Immolate_Timer; + uint32 TerrifyingRoar_Timer; + + void Reset() + { + Flamebreak_Timer = 12000; + Immolate_Timer = 3000; + TerrifyingRoar_Timer = 23000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //Flamebreak_Timer + if (Flamebreak_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FLAMEBREAK); + Flamebreak_Timer = 10000; + }else Flamebreak_Timer -= diff; + + //Immolate_Timer + if (Immolate_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) DoCast(target,SPELL_IMMOLATE); + Immolate_Timer = 8000; + }else Immolate_Timer -= diff; + + //TerrifyingRoar_Timer + if (TerrifyingRoar_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_TERRIFYINGROAR); + TerrifyingRoar_Timer = 20000; + }else TerrifyingRoar_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_thebeast(Creature *_Creature) +{ + return new boss_thebeastAI (_Creature); +} + +void AddSC_boss_thebeast() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_the_beast"; + newscript->GetAI = GetAI_boss_thebeast; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackrock_spire/boss_warmaster_voone.cpp b/src/bindings/scripts/scripts/zone/blackrock_spire/boss_warmaster_voone.cpp new file mode 100644 index 00000000000..6621c4672a1 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackrock_spire/boss_warmaster_voone.cpp @@ -0,0 +1,121 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Warmaster_Voone +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Spire +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_SNAPKICK 15618 +#define SPELL_CLEAVE 15579 +#define SPELL_UPPERCUT 10966 +#define SPELL_MORTALSTRIKE 16856 +#define SPELL_PUMMEL 15615 +#define SPELL_THROWAXE 16075 + +struct MANGOS_DLL_DECL boss_warmastervooneAI : public ScriptedAI +{ + boss_warmastervooneAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Snapkick_Timer; + uint32 Cleave_Timer; + uint32 Uppercut_Timer; + uint32 MortalStrike_Timer; + uint32 Pummel_Timer; + uint32 ThrowAxe_Timer; + + void Reset() + { + Snapkick_Timer = 8000; + Cleave_Timer = 14000; + Uppercut_Timer = 20000; + MortalStrike_Timer = 12000; + Pummel_Timer = 32000; + ThrowAxe_Timer = 1000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //Snapkick_Timer + if (Snapkick_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SNAPKICK); + Snapkick_Timer = 6000; + }else Snapkick_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CLEAVE); + Cleave_Timer = 12000; + }else Cleave_Timer -= diff; + + //Uppercut_Timer + if (Uppercut_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_UPPERCUT); + Uppercut_Timer = 14000; + }else Uppercut_Timer -= diff; + + //MortalStrike_Timer + if (MortalStrike_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_MORTALSTRIKE); + MortalStrike_Timer = 10000; + }else MortalStrike_Timer -= diff; + + //Pummel_Timer + if (Pummel_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_PUMMEL); + Pummel_Timer = 16000; + }else Pummel_Timer -= diff; + + //ThrowAxe_Timer + if (ThrowAxe_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_THROWAXE); + ThrowAxe_Timer = 8000; + }else ThrowAxe_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_warmastervoone(Creature *_Creature) +{ + return new boss_warmastervooneAI (_Creature); +} + +void AddSC_boss_warmastervoone() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_warmaster_voone"; + newscript->GetAI = GetAI_boss_warmastervoone; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackwing_lair/boss_broodlord_lashlayer.cpp b/src/bindings/scripts/scripts/zone/blackwing_lair/boss_broodlord_lashlayer.cpp new file mode 100644 index 00000000000..a1f3260550b --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackwing_lair/boss_broodlord_lashlayer.cpp @@ -0,0 +1,130 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Broodlord_Lashlayer +SD%Complete: 100 +SDComment: +SDCategory: Blackwing Lair +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_CLEAVE 26350 +#define SPELL_BLASTWAVE 23331 +#define SPELL_MORTALSTRIKE 24573 +#define SPELL_KNOCKBACK 25778 + +#define SAY_AGGRO "None of your kind should be here! You've doomed only yourselves!" +#define SAY_LEASH "Clever Mortals but I am not so easily lured away from my sanctum!" +#define SOUND_AGGRO 8286 +#define SOUND_LEASH 8287 + +struct MANGOS_DLL_DECL boss_broodlordAI : public ScriptedAI +{ + boss_broodlordAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Cleave_Timer; + uint32 BlastWave_Timer; + uint32 MortalStrike_Timer; + uint32 KnockBack_Timer; + uint32 LeashCheck_Timer; + + void Reset() + { + Cleave_Timer = 8000; //These times are probably wrong + BlastWave_Timer = 12000; + MortalStrike_Timer = 20000; + KnockBack_Timer = 30000; + LeashCheck_Timer = 2000; + + m_creature->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); + m_creature->ApplySpellImmune(1, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true); + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO); + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //LeashCheck_Timer + if (LeashCheck_Timer < diff) + { + float rx,ry,rz; + m_creature->GetRespawnCoord(rx, ry, rz); + float spawndist = m_creature->GetDistance(rx,ry,rz); + if ( spawndist > 250 ) + { + EnterEvadeMode(); + return; + } + LeashCheck_Timer = 2000; + }else LeashCheck_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CLEAVE); + Cleave_Timer = 7000; + }else Cleave_Timer -= diff; + + // BlastWave + if (BlastWave_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_BLASTWAVE); + BlastWave_Timer = 8000 + rand()%8000; + }else BlastWave_Timer -= diff; + + //MortalStrike_Timer + if (MortalStrike_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_MORTALSTRIKE); + MortalStrike_Timer = 25000 + rand()%10000; + }else MortalStrike_Timer -= diff; + + if (KnockBack_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_KNOCKBACK); + //Drop 50% aggro + if(m_creature->getThreatManager().getThreat(m_creature->getVictim())) + m_creature->getThreatManager().modifyThreatPercent(m_creature->getVictim(),-50); + + KnockBack_Timer = 15000 + rand()%15000; + }else KnockBack_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_broodlord(Creature *_Creature) +{ + return new boss_broodlordAI (_Creature); +} + +void AddSC_boss_broodlord() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_broodlord"; + newscript->GetAI = GetAI_boss_broodlord; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackwing_lair/boss_chromaggus.cpp b/src/bindings/scripts/scripts/zone/blackwing_lair/boss_chromaggus.cpp new file mode 100644 index 00000000000..db05dab31b6 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackwing_lair/boss_chromaggus.cpp @@ -0,0 +1,320 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Chromaggus +SD%Complete: 95 +SDComment: Chromatic Mutation disabled due to lack of core support +SDCategory: Blackwing Lair +EndScriptData */ + +#include "precompiled.h" + +//These spells are actually called elemental shield +//What they do is decrease all damage by 75% then they increase +//One school of damage by 1100% +#define SPELL_FIRE_VURNALBILTY 22277 +#define SPELL_FROST_VURNALBILTY 22278 +#define SPELL_SHADOW_VURNALBILTY 22279 +#define SPELL_NATURE_VURNALBILTY 22280 +#define SPELL_ARCANE_VURNALBILTY 22281 + +#define EMOTE_FRENZY "goes into a killing frenzy!" +#define EMOTE_SHIMMER "flinches as its skin shimmers" + +#define SPELL_INCINERATE 23308 //Incinerate 23308,23309 +#define SPELL_TIMELAPSE 23310 //Time lapse 23310, 23311(old threat mod that was removed in 2.01) +#define SPELL_CORROSIVEACID 23313 //Corrosive Acid 23313, 23314 +#define SPELL_IGNITEFLESH 23315 //Ignite Flesh 23315,23316 +#define SPELL_FROSTBURN 23187 //Frost burn 23187, 23189 + +//Brood Affliction 23173 - Scripted Spell that cycles through all targets within 100 yards and has a chance to cast one of the afflictions on them +//Since Scripted spells arn't coded I'll just write a function that does the same thing + +#define SPELL_BROODAF_BLUE 23153 //Blue affliction 23153 +#define SPELL_BROODAF_BLACK 23154 //Black affliction 23154 +#define SPELL_BROODAF_RED 23155 //Red affliction 23155 (23168 on death) +#define SPELL_BROODAF_BRONZE 23170 //Bronze Affliction 23170 +#define SPELL_BROODAF_GREEN 23169 //Brood Affliction Green 23169 + +#define SPELL_CHROMATIC_MUT_1 23174 //Spell cast on player if they get all 5 debuffs + +#define SPELL_FRENZY 28371 //The frenzy spell may be wrong +#define SPELL_ENRAGE 28747 + +#define TEMP_MUTATE_WHISPER "[SD2 Debug] You would be mind controlled here!" + +struct MANGOS_DLL_DECL boss_chromaggusAI : public ScriptedAI +{ + boss_chromaggusAI(Creature *c) : ScriptedAI(c) + { + //Select the 2 breaths that we are going to use until despawned + //5 possiblities for the first breath, 4 for the second, 20 total possiblites + //This way we don't end up casting 2 of the same breath + //TL TL would be stupid + srand(time(NULL)); + switch (rand()%20) + { + //B1 - Incin + case 0: + Breath1_Spell = SPELL_INCINERATE; + Breath2_Spell = SPELL_TIMELAPSE; + break; + case 1: + Breath1_Spell = SPELL_INCINERATE; + Breath2_Spell = SPELL_CORROSIVEACID; + break; + case 2: + Breath1_Spell = SPELL_INCINERATE; + Breath2_Spell = SPELL_IGNITEFLESH; + break; + case 3: + Breath1_Spell = SPELL_INCINERATE; + Breath2_Spell = SPELL_FROSTBURN; + break; + + //B1 - TL + case 4: + Breath1_Spell = SPELL_TIMELAPSE; + Breath2_Spell = SPELL_INCINERATE; + break; + case 5: + Breath1_Spell = SPELL_TIMELAPSE; + Breath2_Spell = SPELL_CORROSIVEACID; + break; + case 6: + Breath1_Spell = SPELL_TIMELAPSE; + Breath2_Spell = SPELL_IGNITEFLESH; + break; + case 7: + Breath1_Spell = SPELL_TIMELAPSE; + Breath2_Spell = SPELL_FROSTBURN; + break; + + //B1 - Acid + case 8: + Breath1_Spell = SPELL_CORROSIVEACID; + Breath2_Spell = SPELL_INCINERATE; + break; + case 9: + Breath1_Spell = SPELL_CORROSIVEACID; + Breath2_Spell = SPELL_TIMELAPSE; + break; + case 10: + Breath1_Spell = SPELL_CORROSIVEACID; + Breath2_Spell = SPELL_IGNITEFLESH; + break; + case 11: + Breath1_Spell = SPELL_CORROSIVEACID; + Breath2_Spell = SPELL_FROSTBURN; + break; + + //B1 - Ignite + case 12: + Breath1_Spell = SPELL_IGNITEFLESH; + Breath2_Spell = SPELL_INCINERATE; + break; + case 13: + Breath1_Spell = SPELL_IGNITEFLESH; + Breath2_Spell = SPELL_CORROSIVEACID; + break; + case 14: + Breath1_Spell = SPELL_IGNITEFLESH; + Breath2_Spell = SPELL_TIMELAPSE; + break; + case 15: + Breath1_Spell = SPELL_IGNITEFLESH; + Breath2_Spell = SPELL_FROSTBURN; + break; + + //B1 - Frost + case 16: + Breath1_Spell = SPELL_FROSTBURN; + Breath2_Spell = SPELL_INCINERATE; + break; + case 17: + Breath1_Spell = SPELL_FROSTBURN; + Breath2_Spell = SPELL_TIMELAPSE; + break; + case 18: + Breath1_Spell = SPELL_FROSTBURN; + Breath2_Spell = SPELL_CORROSIVEACID; + break; + case 19: + Breath1_Spell = SPELL_FROSTBURN; + Breath2_Spell = SPELL_IGNITEFLESH; + break; + }; + + EnterEvadeMode(); + } + + uint32 Breath1_Spell; + uint32 Breath2_Spell; + uint32 CurrentVurln_Spell; + + uint32 Shimmer_Timer; + uint32 Breath1_Timer; + uint32 Breath2_Timer; + uint32 Affliction_Timer; + uint32 Frenzy_Timer; + bool Enraged; + + void Reset() + { + CurrentVurln_Spell = 0; //We use this to store our last vurlnability spell so we can remove it later + + Shimmer_Timer = 0; //Time till we change vurlnerabilites + Breath1_Timer = 30000; //First breath is 30 seconds + Breath2_Timer = 60000; //Second is 1 minute so that we can alternate + Affliction_Timer = 10000; //This is special - 5 seconds means that we cast this on 1 player every 5 sconds + Frenzy_Timer = 15000; + + Enraged = false; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //Shimmer_Timer Timer + if (Shimmer_Timer < diff) + { + //Remove old vurlnability spell + if (CurrentVurln_Spell) + m_creature->RemoveAurasDueToSpell(CurrentVurln_Spell); + + //Cast new random vurlnabilty on self + uint32 spell; + switch (rand()%5) + { + case 0: spell = SPELL_FIRE_VURNALBILTY; break; + case 1: spell = SPELL_FROST_VURNALBILTY; break; + case 2: spell = SPELL_SHADOW_VURNALBILTY; break; + case 3: spell = SPELL_NATURE_VURNALBILTY; break; + case 4: spell = SPELL_ARCANE_VURNALBILTY; break; + } + + DoCast(m_creature,spell); + CurrentVurln_Spell = spell; + + DoTextEmote(EMOTE_SHIMMER, NULL); + Shimmer_Timer = 45000; + }else Shimmer_Timer -= diff; + + //Breath1_Timer + if (Breath1_Timer < diff) + { + DoCast(m_creature->getVictim(),Breath1_Spell); + Breath1_Timer = 60000; + }else Breath1_Timer -= diff; + + //Breath2_Timer + if (Breath2_Timer < diff) + { + DoCast(m_creature->getVictim(),Breath2_Spell); + Breath2_Timer = 60000; + }else Breath2_Timer -= diff; + + //Affliction_Timer + if (Affliction_Timer < diff) + { + uint32 SpellAfflict = 0; + + switch (rand()%5) + { + case 0: SpellAfflict = SPELL_BROODAF_BLUE; break; + case 1: SpellAfflict = SPELL_BROODAF_BLACK; break; + case 2: SpellAfflict = SPELL_BROODAF_RED; break; + case 3: SpellAfflict = SPELL_BROODAF_BRONZE; break; + case 4: SpellAfflict = SPELL_BROODAF_GREEN; break; + } + + std::list::iterator i; + + for (i = m_creature->getThreatManager().getThreatList().begin();i != m_creature->getThreatManager().getThreatList().end(); ++i) + { + Unit* pUnit = NULL; + pUnit = Unit::GetUnit((*m_creature), (*i)->getUnitGuid()); + + if(pUnit) + { + //Cast affliction + DoCast(pUnit, SpellAfflict, true); + + //Chromatic mutation if target is effected by all afflictions + if (pUnit->HasAura(SPELL_BROODAF_BLUE,0) + && pUnit->HasAura(SPELL_BROODAF_BLACK,0) + && pUnit->HasAura(SPELL_BROODAF_RED,0) + && pUnit->HasAura(SPELL_BROODAF_BRONZE,0) + && pUnit->HasAura(SPELL_BROODAF_GREEN,0)) + { + //target->RemoveAllAuras(); + //DoCast(target,SPELL_CHROMATIC_MUT_1); + + //Chromatic mutation is causing issues + //Assuming it is caused by a lack of core support for Charm + //So instead we instant kill our target + + //WORKAROUND + if (pUnit->GetTypeId() == TYPEID_PLAYER) + { + DoWhisper(TEMP_MUTATE_WHISPER, pUnit); + pUnit->CastSpell(pUnit, 5, false); + } + } + } + } + + Affliction_Timer = 10000; + }else Affliction_Timer -= diff; + + //Frenzy_Timer + if (Frenzy_Timer < diff) + { + DoCast(m_creature,SPELL_FRENZY); + DoTextEmote(EMOTE_FRENZY,NULL); + Frenzy_Timer = 10000 + (rand() % 5000); + }else Frenzy_Timer -= diff; + + //Enrage if not already enraged and below 20% + if (!Enraged && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 20) + { + DoCast(m_creature,SPELL_ENRAGE); + Enraged = true; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_chromaggus(Creature *_Creature) +{ + return new boss_chromaggusAI (_Creature); +} + +void AddSC_boss_chromaggus() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_chromaggus"; + newscript->GetAI = GetAI_boss_chromaggus; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackwing_lair/boss_ebonroc.cpp b/src/bindings/scripts/scripts/zone/blackwing_lair/boss_ebonroc.cpp new file mode 100644 index 00000000000..91d57238f01 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackwing_lair/boss_ebonroc.cpp @@ -0,0 +1,103 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Ebonroc +SD%Complete: 50 +SDComment: Shadow of Ebonroc needs core support +SDCategory: Blackwing Lair +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_SHADOWFLAME 22539 +#define SPELL_WINGBUFFET 18500 +#define SPELL_SHADOWOFEBONROC 23340 +#define SPELL_HEAL 41386 //Thea Heal spell of his Shadow + +struct MANGOS_DLL_DECL boss_ebonrocAI : public ScriptedAI +{ + boss_ebonrocAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 ShadowFlame_Timer; + uint32 WingBuffet_Timer; + uint32 ShadowOfEbonroc_Timer; + uint32 Heal_Timer; + + void Reset() + { + ShadowFlame_Timer = 15000; //These times are probably wrong + WingBuffet_Timer = 30000; + ShadowOfEbonroc_Timer = 45000; + Heal_Timer = 1000; + } + + void Aggro(Unit *who) + { + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //Shadowflame Timer + if (ShadowFlame_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SHADOWFLAME); + ShadowFlame_Timer = 12000 + rand()%3000; + }else ShadowFlame_Timer -= diff; + + //Wing Buffet Timer + if (WingBuffet_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_WINGBUFFET); + WingBuffet_Timer = 25000; + }else WingBuffet_Timer -= diff; + + //Shadow of Ebonroc Timer + if (ShadowOfEbonroc_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SHADOWOFEBONROC); + ShadowOfEbonroc_Timer = 25000 + rand()%10000; + }else ShadowOfEbonroc_Timer -= diff; + + if (m_creature->getVictim()->HasAura(SPELL_SHADOWOFEBONROC,0)) + { + if (Heal_Timer < diff) + { + DoCast(m_creature, SPELL_HEAL); + Heal_Timer = 1000 + rand()%2000; + }else Heal_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_ebonroc(Creature *_Creature) +{ + return new boss_ebonrocAI (_Creature); +} + +void AddSC_boss_ebonroc() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_ebonroc"; + newscript->GetAI = GetAI_boss_ebonroc; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackwing_lair/boss_firemaw.cpp b/src/bindings/scripts/scripts/zone/blackwing_lair/boss_firemaw.cpp new file mode 100644 index 00000000000..f4b7848a3bb --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackwing_lair/boss_firemaw.cpp @@ -0,0 +1,94 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Firemaw +SD%Complete: 100 +SDComment: +SDCategory: Blackwing Lair +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_SHADOWFLAME 22539 +#define SPELL_WINGBUFFET 23339 +#define SPELL_FLAMEBUFFET 23341 + +struct MANGOS_DLL_DECL boss_firemawAI : public ScriptedAI +{ + boss_firemawAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 ShadowFlame_Timer; + uint32 WingBuffet_Timer; + uint32 FlameBuffet_Timer; + + void Reset() + { + ShadowFlame_Timer = 30000; //These times are probably wrong + WingBuffet_Timer = 24000; + FlameBuffet_Timer = 5000; + } + + void Aggro(Unit *who) + { + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //ShadowFlame_Timer + if (ShadowFlame_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SHADOWFLAME); + ShadowFlame_Timer = 15000 + rand()%3000; + }else ShadowFlame_Timer -= diff; + + //WingBuffet_Timer + if (WingBuffet_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_WINGBUFFET); + if(m_creature->getThreatManager().getThreat(m_creature->getVictim())) + m_creature->getThreatManager().modifyThreatPercent(m_creature->getVictim(),-75); + + WingBuffet_Timer = 25000; + }else WingBuffet_Timer -= diff; + + //FlameBuffet_Timer + if (FlameBuffet_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FLAMEBUFFET); + FlameBuffet_Timer = 5000; + }else FlameBuffet_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_firemaw(Creature *_Creature) +{ + return new boss_firemawAI (_Creature); +} + +void AddSC_boss_firemaw() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_firemaw"; + newscript->GetAI = GetAI_boss_firemaw; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackwing_lair/boss_flamegor.cpp b/src/bindings/scripts/scripts/zone/blackwing_lair/boss_flamegor.cpp new file mode 100644 index 00000000000..5bc6531c45a --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackwing_lair/boss_flamegor.cpp @@ -0,0 +1,94 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Flamegor +SD%Complete: 100 +SDComment: +SDCategory: Blackwing Lair +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_SHADOWFLAME 22539 +#define SPELL_WINGBUFFET 23339 +#define SPELL_FRENZY 23342 //This spell periodically triggers fire nova + +struct MANGOS_DLL_DECL boss_flamegorAI : public ScriptedAI +{ + boss_flamegorAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 ShadowFlame_Timer; + uint32 WingBuffet_Timer; + uint32 Frenzy_Timer; + + void Reset() + { + ShadowFlame_Timer = 21000; //These times are probably wrong + WingBuffet_Timer = 35000; + Frenzy_Timer = 10000; + } + + void Aggro(Unit *who) + { + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //ShadowFlame_Timer + if (ShadowFlame_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SHADOWFLAME); + ShadowFlame_Timer = 15000 + rand()%7000; + }else ShadowFlame_Timer -= diff; + + //WingBuffet_Timer + if (WingBuffet_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_WINGBUFFET); + if(m_creature->getThreatManager().getThreat(m_creature->getVictim())) + m_creature->getThreatManager().modifyThreatPercent(m_creature->getVictim(),-75); + + WingBuffet_Timer = 25000; + }else WingBuffet_Timer -= diff; + + //Frenzy_Timer + if (Frenzy_Timer < diff) + { + DoCast(m_creature,SPELL_FRENZY); + Frenzy_Timer = 8000 + (rand()%2000); + }else Frenzy_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_flamegor(Creature *_Creature) +{ + return new boss_flamegorAI (_Creature); +} + +void AddSC_boss_flamegor() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_flamegor"; + newscript->GetAI = GetAI_boss_flamegor; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackwing_lair/boss_nefarian.cpp b/src/bindings/scripts/scripts/zone/blackwing_lair/boss_nefarian.cpp new file mode 100644 index 00000000000..31495b35d9d --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackwing_lair/boss_nefarian.cpp @@ -0,0 +1,250 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Nefarian +SD%Complete: 100 +SDComment: Some issues with class calls effecting more than one class +SDCategory: Blackwing Lair +EndScriptData */ + +#include "precompiled.h" + +#define SAY_AGGRO "Well done, my minions. The mortals' courage begins to wane! Now, let's see how they contend with the true Lord of Blackrock Spire!" +#define SAY_DEATH "This cannot be! I am the Master here! You mortals are nothing to my kind! DO YOU HEAR? NOTHING!" +#define SAY_RAISE_SKELETONS "Impossible! Rise my minions! Serve your master once more!" +#define SAY_SHADOWFLAME "Burn, you wretches! Burn!" +#define SAY_SLAY "Worthless $N! Your friends will join you soon enough!" +#define SAY_XHEALTH "Enough! Now you vermin shall feel the force of my birthright, the fury of the earth itself." +#define SAY_GAMESBEGIN "Let the games begin!" +#define SAY_START "" + +#define SOUND_AGGRO 8288 +#define SOUND_DEATH 8292 +#define SOUND_RAISE_SKELETONS 8291 +#define SOUND_SHADOWFLAME 8290 +#define SOUND_SLAY 8293 +#define SOUND_XHEALTH 8289 +#define SOUND_GAMESBEGIN 8279 +#define SOUND_START 8280 + +#define SPELL_SHADOWFLAME_INITIAL 22972 +#define SPELL_SHADOWFLAME 22539 +#define SPELL_BELLOWINGROAR 22686 +#define SPELL_VEILOFSHADOW 7068 +#define SPELL_CLEAVE 20691 +#define SPELL_TAILLASH 23364 +#define SPELL_BONECONTRUST 23363 //23362, 23361 + +#define SPELL_MAGE 23410 //wild magic +#define SPELL_WARRIOR 23397 //beserk +#define SPELL_DRUID 23398 // cat form +#define SPELL_PRIEST 23401 // corrupted healing +#define SPELL_PALADIN 23418 //syphon blessing +#define SPELL_SHAMAN 23425 //totems +#define SPELL_WARLOCK 23427 //infernals +#define SPELL_HUNTER 23436 //bow broke +#define SPELL_ROGUE 23414 //Paralise + +#define SAY_MAGE "Mages too? You should be more careful when you play with magic..." +#define SAY_WARRIOR "Warriors, I know you can hit harder than that! Let's see it!" +#define SAY_DRUID "Druids and your silly shapeshifting. Let's see it in action!" +#define SAY_PRIEST "Priests! If you're going to keep healing like that, we might as well make it a little more interesting!" +#define SAY_PALADIN "Paladins, I've heard you have many lives. Show me." +#define SAY_SHAMAN "Shamans, show me what your totems can do!" +#define SAY_WARLOCK "Warlocks, you shouldn't be playing with magic you don't understand. See what happens?" +#define SAY_HUNTER "Hunters and your annoying pea-shooters!" +#define SAY_ROGUE "Rogues? Stop hiding and face me!" + +struct MANGOS_DLL_DECL boss_nefarianAI : public ScriptedAI +{ + boss_nefarianAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 ShadowFlame_Timer; + uint32 BellowingRoar_Timer; + uint32 VeilOfShadow_Timer; + uint32 Cleave_Timer; + uint32 TailLash_Timer; + uint32 ClassCall_Timer; + bool Phase3; + + void Reset() + { + ShadowFlame_Timer = 12000; //These times are probably wrong + BellowingRoar_Timer = 30000; + VeilOfShadow_Timer = 15000; + Cleave_Timer = 7000; + TailLash_Timer = 10000; + ClassCall_Timer = 35000; //35-40 seconds + Phase3 = false; + + m_creature->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); + m_creature->ApplySpellImmune(1, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true); + } + + void KilledUnit(Unit* Victim) + { + if (rand()%5) + return; + + DoYell(SAY_SLAY,LANG_UNIVERSAL,Victim); + DoPlaySoundToSet(m_creature, SOUND_SLAY); + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DEATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_DEATH); + } + + void Aggro(Unit *who) + { + switch (rand()%3) + { + case 0: + DoYell(SAY_XHEALTH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_XHEALTH); + break; + case 1: + DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO); + break; + case 2: + DoYell(SAY_SHADOWFLAME,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_SHADOWFLAME); + break; + } + + DoCast(who,SPELL_SHADOWFLAME_INITIAL); + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //ShadowFlame_Timer + if (ShadowFlame_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SHADOWFLAME); + ShadowFlame_Timer = 12000; + }else ShadowFlame_Timer -= diff; + + //BellowingRoar_Timer + if (BellowingRoar_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_BELLOWINGROAR); + BellowingRoar_Timer = 30000; + }else BellowingRoar_Timer -= diff; + + //VeilOfShadow_Timer + if (VeilOfShadow_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_VEILOFSHADOW); + VeilOfShadow_Timer = 15000; + }else VeilOfShadow_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CLEAVE); + Cleave_Timer = 7000; + }else Cleave_Timer -= diff; + + //TailLash_Timer + if (TailLash_Timer < diff) + { + //Cast NYI since we need a better check for behind target + //DoCast(m_creature->getVictim(),SPELL_TAILLASH); + + TailLash_Timer = 10000; + }else TailLash_Timer -= diff; + + //ClassCall_Timer + if (ClassCall_Timer < diff) + { + //Cast a random class call + //On official it is based on what classes are currently on the hostil list + //but we can't do that yet so just randomly call one + + switch (rand()%9) + { + case 0: + DoYell(SAY_MAGE,LANG_UNIVERSAL,NULL); + DoCast(m_creature,SPELL_MAGE); + break; + case 1: + DoYell(SAY_WARRIOR,LANG_UNIVERSAL,NULL); + DoCast(m_creature,SPELL_WARRIOR); + break; + case 2: + DoYell(SAY_DRUID,LANG_UNIVERSAL,NULL); + DoCast(m_creature,SPELL_DRUID); + break; + case 3: + DoYell(SAY_PRIEST,LANG_UNIVERSAL,NULL); + DoCast(m_creature,SPELL_PRIEST); + break; + case 4: + DoYell(SAY_PALADIN,LANG_UNIVERSAL,NULL); + DoCast(m_creature,SPELL_PALADIN); + break; + case 5: + DoYell(SAY_SHAMAN,LANG_UNIVERSAL,NULL); + DoCast(m_creature,SPELL_SHAMAN); + break; + case 6: + DoYell(SAY_WARLOCK,LANG_UNIVERSAL,NULL); + DoCast(m_creature,SPELL_WARLOCK); + break; + case 7: + DoYell(SAY_HUNTER,LANG_UNIVERSAL,NULL); + DoCast(m_creature,SPELL_HUNTER); + break; + case 8: + DoYell(SAY_ROGUE,LANG_UNIVERSAL,NULL); + DoCast(m_creature,SPELL_ROGUE); + break; + } + + ClassCall_Timer = 35000 + (rand() % 5000); + }else ClassCall_Timer -= diff; + + //Phase3 begins when we are below X health + if (!Phase3 && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 20) + { + Phase3 = true; + DoYell(SAY_RAISE_SKELETONS,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_RAISE_SKELETONS); + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_nefarian(Creature *_Creature) +{ + return new boss_nefarianAI (_Creature); +} + +void AddSC_boss_nefarian() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_nefarian"; + newscript->GetAI = GetAI_boss_nefarian; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackwing_lair/boss_razorgore.cpp b/src/bindings/scripts/scripts/zone/blackwing_lair/boss_razorgore.cpp new file mode 100644 index 00000000000..78441b63888 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackwing_lair/boss_razorgore.cpp @@ -0,0 +1,126 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Razorgore +SD%Complete: 50 +SDComment: Needs additional review. Phase 1 NYI +SDCategory: Blackwing Lair +EndScriptData */ + +#include "precompiled.h" + +//Razorgore Phase 2 Script + +#define SAY_NPC_DEATH "If I fall into the abyss I'll take all of you mortals with me..." +#define SOUND_NPC_DEATH 8278 +#define SAY_EGGS_BREAK3 "No! Not another one! I'll have your heads for this atrocity." +#define SOUND_EGGS_BREAK3 8277 + +#define SPELL_CLEAVE 22540 +#define SPELL_WARSTOMP 24375 +#define SPELL_FIREBALLVOLLEY 22425 +#define SPELL_CONFLAGRATION 23023 + +struct MANGOS_DLL_DECL boss_razorgoreAI : public ScriptedAI +{ + boss_razorgoreAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Cleave_Timer; + uint32 WarStomp_Timer; + uint32 FireballVolley_Timer; + uint32 Conflagration_Timer; + + void Reset() + { + Cleave_Timer = 15000; //These times are probably wrong + WarStomp_Timer = 35000; + FireballVolley_Timer = 7000; + Conflagration_Timer = 12000; + + m_creature->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); + m_creature->ApplySpellImmune(1, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true); + } + + void Aggro(Unit *who) + { + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //Cleave_Timer + if (Cleave_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CLEAVE); + Cleave_Timer = 7000 + rand()%3000; + }else Cleave_Timer -= diff; + + //WarStomp_Timer + if (WarStomp_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_WARSTOMP); + WarStomp_Timer = 15000 + rand()%10000; + }else WarStomp_Timer -= diff; + + //FireballVolley_Timer + if (FireballVolley_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FIREBALLVOLLEY); + FireballVolley_Timer = 12000 + rand()%3000; + }else FireballVolley_Timer -= diff; + + //Conflagration_Timer + if (Conflagration_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CONFLAGRATION); + //We will remove this threat reduction and add an aura check. + + //if(m_creature->getThreatManager().getThreat(m_creature->getVictim())) + //m_creature->getThreatManager().modifyThreatPercent(m_creature->getVictim(),-50); + + Conflagration_Timer = 12000; + }else Conflagration_Timer -= diff; + + // Aura Check. If the gamer is affected by confliguration we attack a random gamer. + if (m_creature->getVictim()->HasAura(SPELL_CONFLAGRATION,0)) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,1); + if (target) + m_creature->TauntApply(target); + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_razorgore(Creature *_Creature) +{ + return new boss_razorgoreAI (_Creature); +} + +void AddSC_boss_razorgore() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_razorgore"; + newscript->GetAI = GetAI_boss_razorgore; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackwing_lair/boss_vaelastrasz.cpp b/src/bindings/scripts/scripts/zone/blackwing_lair/boss_vaelastrasz.cpp new file mode 100644 index 00000000000..217eebfb852 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackwing_lair/boss_vaelastrasz.cpp @@ -0,0 +1,278 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Vaelastrasz +SD%Complete: 75 +SDComment: Burning Adrenaline not correctly implemented in core +SDCategory: Blackwing Lair +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_ESSENCEOFTHERED 23513 +#define SPELL_FLAMEBREATH 23461 +#define SPELL_FIRENOVA 23462 +#define SPELL_TAILSWIPE 15847 +#define SPELL_BURNINGADRENALINE 23620 +#define SPELL_CLEAVE 20684 //Chain cleave is most likely named something different and contains a dummy effect + +#define SAY_LINE1 "Too late...friends. Nefarius' corruption has taken hold. I cannot...control myself. " +#define SOUND_LINE1 8281 + +#define SAY_LINE2 "I beg you Mortals, flee! Flee before I lose all control. The Black Fire rages within my heart. I must release it!" +#define SOUND_LINE2 8282 + +#define SAY_LINE3 "FLAME! DEATH! DESTRUCTION! COWER MORTALS BEFORE THE WRATH OF LORD....NO! I MUST FIGHT THIS!" +#define SOUND_LINE3 8283 + +#define SAY_HALFLIFE "Nefarius' hate has made me stronger than ever before. You should have fled, while you could, mortals! The fury of Blackrock courses through my veins! " +#define SOUND_HALFLIFE 8285 + +#define SAY_KILLTARGET "Forgive me $N, your death only adds to my failure." +#define SOUND_KILLTARGET 8284 + +#define GOSSIP_ITEM "Start Event " + +struct MANGOS_DLL_DECL boss_vaelAI : public ScriptedAI +{ + boss_vaelAI(Creature *c) : ScriptedAI(c) + { + c->SetUInt32Value(UNIT_NPC_FLAGS,1); + c->setFaction(35); + c->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Reset(); + } + + uint64 PlayerGUID; + uint32 SpeachTimer; + uint32 SpeachNum; + uint32 Cleave_Timer; + uint32 FlameBreath_Timer; + uint32 FireNova_Timer; + uint32 BurningAdrenalineCaster_Timer; + uint32 BurningAdrenalineTank_Timer; + uint32 TailSwipe_Timer; + bool HasYelled; + bool DoingSpeach; + + void Reset() + { + PlayerGUID = 0; + SpeachTimer = 0; + SpeachNum = 0; + Cleave_Timer = 8000; //These times are probably wrong + FlameBreath_Timer = 11000; + BurningAdrenalineCaster_Timer = 15000; + BurningAdrenalineTank_Timer = 45000; + FireNova_Timer = 5000; + TailSwipe_Timer = 20000; + HasYelled = false; + DoingSpeach = false; + + m_creature->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); + m_creature->ApplySpellImmune(1, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true); + } + + void BeginSpeach(Unit* target) + { + //Stand up and begin speach + PlayerGUID = target->GetGUID(); + + //10 seconds + DoYell(SAY_LINE1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_LINE1); + SpeachTimer = 10000; + SpeachNum = 0; + DoingSpeach = true; + } + + void KilledUnit(Unit *victim) + { + if (rand()%5) + return; + + DoYell(SAY_KILLTARGET,LANG_UNIVERSAL,victim); + DoPlaySoundToSet(m_creature,SOUND_KILLTARGET); + } + + void Aggro(Unit *who) + { + DoCast(m_creature,SPELL_ESSENCEOFTHERED); + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + //Speach + if (DoingSpeach) + if (SpeachTimer < diff) + { + switch (SpeachNum) + { + case 0: + //16 seconds till next line + DoYell(SAY_LINE2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_LINE2); + SpeachTimer = 16000; + SpeachNum++; + break; + + case 1: + //This one is actually 16 seconds but we only go to 10 seconds because he starts attacking after he says "I must fight this!" + DoYell(SAY_LINE3,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_LINE3); + SpeachTimer = 10000; + SpeachNum++; + break; + + case 2: + default: + m_creature->setFaction(103); + m_creature->SetHealth(int(m_creature->GetMaxHealth()*.3)); + if (PlayerGUID && Unit::GetUnit((*m_creature),PlayerGUID)) + { + DoStartAttackAndMovement(Unit::GetUnit((*m_creature),PlayerGUID)); + DoCast(m_creature,SPELL_ESSENCEOFTHERED); + } + + SpeachTimer = 0; + DoingSpeach = false; + break; + } + }else SpeachTimer -= diff; + + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + // Yell if hp lower than 15% + if (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 15 && !HasYelled) + { + //Say our dialog + DoYell(SAY_HALFLIFE,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_HALFLIFE); + HasYelled = true; + } + + //Cleave_Timer + if (Cleave_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CLEAVE); + Cleave_Timer = 15000; + }else Cleave_Timer -= diff; + + //FlameBreath_Timer + if (FlameBreath_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FLAMEBREATH); + FlameBreath_Timer = 4000 + rand()%4000; + }else FlameBreath_Timer -= diff; + + //BurningAdrenalineCaster_Timer + if (BurningAdrenalineCaster_Timer < diff) + { + Unit* target = NULL; + + int i = 0 ; + while (i < 3) // max 3 tries to get a random target with power_mana + { + ++i; + target = SelectUnit(SELECT_TARGET_RANDOM,1);//not aggro leader + if (target) + if (target->getPowerType() == POWER_MANA) + i=3; + } + if (target) // cast on self (see below) + target->CastSpell(target,SPELL_BURNINGADRENALINE,1); + + BurningAdrenalineCaster_Timer = 15000; + }else BurningAdrenalineCaster_Timer -= diff; + + //BurningAdrenalineTank_Timer + if (BurningAdrenalineTank_Timer < diff) + { + // have the victim cast the spell on himself otherwise the third effect aura will be applied + // to Vael instead of the player + + m_creature->getVictim()->CastSpell(m_creature->getVictim(),SPELL_BURNINGADRENALINE,1); + + BurningAdrenalineTank_Timer = 45000; + }else BurningAdrenalineTank_Timer -= diff; + + //FireNova_Timer + if (FireNova_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FIRENOVA); + FireNova_Timer = 5000; + }else FireNova_Timer -= diff; + + //TailSwipe_Timer + if (TailSwipe_Timer < diff) + { + //Only cast if we are behind + /*if (!m_creature->HasInArc( M_PI, m_creature->getVictim())) + { + DoCast(m_creature->getVictim(),SPELL_TAILSWIPE); + }*/ + + TailSwipe_Timer = 20000; + }else TailSwipe_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +void SendDefaultMenu_boss_vael(Player *player, Creature *_Creature, uint32 action) +{ + if (action == GOSSIP_ACTION_INFO_DEF + 1) //Fight time + { + player->CLOSE_GOSSIP_MENU(); + ((boss_vaelAI*)_Creature->AI())->BeginSpeach((Unit*)player); + } +} + +bool GossipSelect_boss_vael(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if (sender == GOSSIP_SENDER_MAIN) + SendDefaultMenu_boss_vael(player, _Creature, action); + + return true; +} + +bool GossipHello_boss_vael(Player *player, Creature *_Creature) +{ + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->SEND_GOSSIP_MENU(907,_Creature->GetGUID()); + + return true; +} + +CreatureAI* GetAI_boss_vael(Creature *_Creature) +{ + return new boss_vaelAI (_Creature); +} + +void AddSC_boss_vael() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_vaelastrasz"; + newscript->GetAI = GetAI_boss_vael; + newscript->pGossipHello = &GossipHello_boss_vael; + newscript->pGossipSelect = &GossipSelect_boss_vael; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackwing_lair/boss_victor_nefarius.cpp b/src/bindings/scripts/scripts/zone/blackwing_lair/boss_victor_nefarius.cpp new file mode 100644 index 00000000000..3870a247fa0 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackwing_lair/boss_victor_nefarius.cpp @@ -0,0 +1,399 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Victor_Nefarius +SD%Complete: 75 +SDComment: Missing some text, Vael beginning event, and spawns Nef in wrong place +SDCategory: Blackwing Lair +EndScriptData */ + +#include "precompiled.h" + +#define SAY_GAMESBEGIN_1 "In this world where time is your enemy, it is my greatest ally. This grand game of life that you think you play in fact plays you. To that I say..." +#define SAY_GAMESBEGIN_2 "Let the games begin!" +#define SAY_VAEL_INTRO "" + +#define SOUND_GAMESBEGIN 8280 +#define SOUND_VAEL_INTRO 8279 + +#define GOSSIP_ITEM_1 "I've made no mistakes." +#define GOSSIP_ITEM_2 "You have lost your mind, Nefarius. You speak in riddles." +#define GOSSIP_ITEM_3 "Please do." + +#define CREATURE_BRONZE_DRAKANOID 14263 +#define CREATURE_BLUE_DRAKANOID 14261 +#define CREATURE_RED_DRAKANOID 14264 +#define CREATURE_GREEN_DRAKANOID 14262 +#define CREATURE_BLACK_DRAKANOID 14265 + +#define CREATURE_CHROMATIC_DRAKANOID 14302 + +#define CREATURE_NEFARIAN 11583 + +#define ADD_X1 -7591.151855 +#define ADD_X2 -7514.598633 +#define ADD_Y1 -1204.051880 +#define ADD_Y2 -1150.448853 +#define ADD_Z1 476.800476 +#define ADD_Z2 476.796570 + +#define NEF_X -7445 +#define NEF_Y -1332 +#define NEF_Z 536 + +#define HIDE_X -7592 +#define HIDE_Y -1264 +#define HIDE_Z 481 + +#define SPELL_SHADOWBOLT 21077 +#define SPELL_FEAR 26070 + +//This script is complicated +//Instead of morphing Victor Nefarius we will have him control phase 1 +//And then have him spawn "Nefarian" for phase 2 +//When phase 2 starts Victor Nefarius will go into hiding and stop attacking +//If Nefarian despawns because he killed the players then this guy will EnterEvadeMode +//and allow players to start the event over +//If nefarian dies then he will kill himself then he will kill himself in his hiding place +//To prevent players from doing the event twice + +struct MANGOS_DLL_DECL boss_victor_nefariusAI : public ScriptedAI +{ + boss_victor_nefariusAI(Creature *c) : ScriptedAI(c) + { + NefarianGUID = 0; + Reset(); + srand(time(NULL)); + switch (rand()%20) + { + case 0: + DrakType1 = CREATURE_BRONZE_DRAKANOID; + DrakType2 = CREATURE_BLUE_DRAKANOID; + break; + case 1: + DrakType1 = CREATURE_BRONZE_DRAKANOID; + DrakType2 = CREATURE_RED_DRAKANOID; + break; + case 2: + DrakType1 = CREATURE_BRONZE_DRAKANOID; + DrakType2 = CREATURE_GREEN_DRAKANOID; + break; + case 3: + DrakType1 = CREATURE_BRONZE_DRAKANOID; + DrakType2 = CREATURE_BLACK_DRAKANOID; + break; + case 4: + DrakType1 = CREATURE_BLUE_DRAKANOID; + DrakType2 = CREATURE_BRONZE_DRAKANOID; + break; + case 5: + DrakType1 = CREATURE_BLUE_DRAKANOID; + DrakType2 = CREATURE_RED_DRAKANOID; + break; + case 6: + DrakType1 = CREATURE_BLUE_DRAKANOID; + DrakType2 = CREATURE_GREEN_DRAKANOID; + break; + case 7: + DrakType1 = CREATURE_BLUE_DRAKANOID; + DrakType2 = CREATURE_BLACK_DRAKANOID; + break; + case 8: + DrakType1 = CREATURE_RED_DRAKANOID; + DrakType2 = CREATURE_BRONZE_DRAKANOID; + break; + case 9: + DrakType1 = CREATURE_RED_DRAKANOID; + DrakType2 = CREATURE_BLUE_DRAKANOID; + break; + case 10: + DrakType1 = CREATURE_RED_DRAKANOID; + DrakType2 = CREATURE_GREEN_DRAKANOID; + break; + case 11: + DrakType1 = CREATURE_RED_DRAKANOID; + DrakType2 = CREATURE_BLACK_DRAKANOID; + break; + case 12: + DrakType1 = CREATURE_GREEN_DRAKANOID; + DrakType2 = CREATURE_BRONZE_DRAKANOID; + break; + case 13: + DrakType1 = CREATURE_GREEN_DRAKANOID; + DrakType2 = CREATURE_BLUE_DRAKANOID; + break; + case 14: + DrakType1 = CREATURE_GREEN_DRAKANOID; + DrakType2 = CREATURE_RED_DRAKANOID; + break; + case 15: + DrakType1 = CREATURE_GREEN_DRAKANOID; + DrakType2 = CREATURE_BLACK_DRAKANOID; + break; + case 16: + DrakType1 = CREATURE_BLACK_DRAKANOID; + DrakType2 = CREATURE_BRONZE_DRAKANOID; + break; + case 17: + DrakType1 = CREATURE_BLACK_DRAKANOID; + DrakType2 = CREATURE_BLUE_DRAKANOID; + break; + case 18: + DrakType1 = CREATURE_BLACK_DRAKANOID; + DrakType2 = CREATURE_GREEN_DRAKANOID; + break; + case 19: + DrakType1 = CREATURE_BLACK_DRAKANOID; + DrakType2 = CREATURE_RED_DRAKANOID; + break; + } + } + + uint32 SpawnedAdds; + uint32 AddSpawnTimer; + uint32 ShadowBoltTimer; + uint32 FearTimer; + uint32 MindControlTimer; + uint32 ResetTimer; + uint32 DrakType1; + uint32 DrakType2; + uint64 NefarianGUID; + uint32 NefCheckTime; + + void Reset() + { + SpawnedAdds = 0; + AddSpawnTimer = 10000; + ShadowBoltTimer = 5000; + FearTimer = 8000; + ResetTimer = 900000; //On official it takes him 15 minutes(900 seconds) to reset. We are only doing 1 minute to make testing easier + NefarianGUID = 0; + NefCheckTime = 2000; + + m_creature->SetUInt32Value(UNIT_NPC_FLAGS,1); + m_creature->setFaction(35); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void BeginEvent(Player* target) + { + DoYell(SAY_GAMESBEGIN_2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_GAMESBEGIN); + + //MaNGOS::Singleton::Instance().GetMap(m_creature->GetMapId(), m_creature)->GetPlayers().begin(); + /* + list ::iterator i = MapManager::Instance().GetMap(m_creature->GetMapId(), m_creature)->GetPlayers().begin(); + + for (i = MapManager::Instance().GetMap(m_creature->GetMapId(), m_creature)->GetPlayers().begin(); i != MapManager::Instance().GetMap(m_creature->GetMapId(), m_creature)->GetPlayers().end(); ++i) + { + AttackStart((*i)); + } + */ + m_creature->SetUInt32Value(UNIT_NPC_FLAGS,0); + m_creature->setFaction(103); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + AttackStart(target); + } + + void Aggro(Unit *who) + { + } + + void MoveInLineOfSight(Unit *who) + { + //We simply use this function to find players until we can use Map->GetPlayers() + + if (who && who->GetTypeId() == TYPEID_PLAYER && m_creature->IsHostileTo(who)) + { + //Add them to our threat list + m_creature->AddThreat(who,0.0f); + } + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //Only do this if we haven't spawned nef yet + if (SpawnedAdds < 42) + { + //ShadowBoltTimer + if (ShadowBoltTimer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) + DoCast(target,SPELL_SHADOWBOLT); + + ShadowBoltTimer = 3000 + (rand()%7000); + }else ShadowBoltTimer -= diff; + + //FearTimer + if (FearTimer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) + DoCast(target,SPELL_FEAR); + + FearTimer = 10000 + (rand()%10000); + }else FearTimer -= diff; + + //Add spawning mechanism + if (AddSpawnTimer < diff) + { + //Spawn 2 random types of creatures at the 2 locations + uint32 CreatureID; + Creature* Spawned = NULL; + Unit* target = NULL; + + //1 in 3 chance it will be a chromatic + if (rand()%3 == 0) + CreatureID = CREATURE_CHROMATIC_DRAKANOID; + else CreatureID = DrakType1; + + SpawnedAdds++; + + //Spawn creature and force it to start attacking a random target + Spawned = m_creature->SummonCreature(CreatureID,ADD_X1,ADD_Y1,ADD_Z1,5.000,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target && Spawned) + { + Spawned->AI()->AttackStart(target); + Spawned->setFaction(103); + } + + //1 in 3 chance it will be a chromatic + if (rand()%3 == 0) + CreatureID = CREATURE_CHROMATIC_DRAKANOID; + else CreatureID = DrakType2; + + SpawnedAdds++; + + target = NULL; + Spawned = NULL; + Spawned = m_creature->SummonCreature(CreatureID,ADD_X2,ADD_Y2,ADD_Z2,5.000,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target && Spawned) + { + Spawned->AI()->AttackStart(target); + Spawned->setFaction(103); + } + + //Begin phase 2 by spawning Nefarian and what not + if (SpawnedAdds >= 42) + { + //Teleport Victor Nefarius way out of the map + //MapManager::Instance().GetMap(m_creature->GetMapId(), m_creature)->CreatureRelocation(m_creature,0,0,-5000,0); + + //Inturrupt any spell casting + m_creature->InterruptNonMeleeSpells(false); + + //Root self + DoCast(m_creature,33356); + + //Make super invis + DoCast(m_creature,8149); + + //Teleport self to a hiding spot (this causes errors in the mangos log but no real issues) + m_creature->Relocate(HIDE_X,HIDE_Y,HIDE_Z,0); + m_creature->SendMonsterMove(HIDE_X,HIDE_Y,HIDE_Z,0,true,0); + m_creature->addUnitState(UNIT_STAT_FLEEING); + + //Spawn nef and have him attack a random target + Creature* Nefarian = NULL; + Nefarian = m_creature->SummonCreature(CREATURE_NEFARIAN,NEF_X,NEF_Y,NEF_Z,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,120000); + target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target && Nefarian) + { + Nefarian->AI()->AttackStart(target); + Nefarian->setFaction(103); + NefarianGUID = Nefarian->GetGUID(); + } + else DoYell("UNABLE TO SPAWN NEF PROPERLY",LANG_UNIVERSAL,NULL); + } + + AddSpawnTimer = 4000; + }else AddSpawnTimer -= diff; + } + else if (NefarianGUID) + { + if (NefCheckTime < diff) + { + Unit* Nefarian = NULL; + Nefarian = Unit::GetUnit((*m_creature),NefarianGUID); + + //If nef is dead then we die to so the players get out of combat + //and cannot repeat the event + if (!Nefarian || !Nefarian->isAlive()) + { + NefarianGUID = 0; + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + NefCheckTime = 2000; + }else NefCheckTime -= diff; + } + } +}; + +CreatureAI* GetAI_boss_victor_nefarius(Creature *_Creature) +{ + return new boss_victor_nefariusAI (_Creature); +} + +bool GossipHello_boss_victor_nefarius(Player *player, Creature *_Creature) +{ + player->ADD_GOSSIP_ITEM(0, GOSSIP_ITEM_1 , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + player->SEND_GOSSIP_MENU(7134,_Creature->GetGUID()); + return true; +} + +bool GossipSelect_boss_victor_nefarius(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF+1: + player->ADD_GOSSIP_ITEM(0, GOSSIP_ITEM_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + player->SEND_GOSSIP_MENU(7198, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + player->ADD_GOSSIP_ITEM(0, GOSSIP_ITEM_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + player->SEND_GOSSIP_MENU(7199, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay(SAY_GAMESBEGIN_1,LANG_UNIVERSAL,0); + ((boss_victor_nefariusAI*)_Creature->AI())->BeginEvent(player); + break; + } + return true; +} + +void AddSC_boss_victor_nefarius() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_victor_nefarius"; + newscript->GetAI = GetAI_boss_victor_nefarius; + newscript->pGossipHello = &GossipHello_boss_victor_nefarius; + newscript->pGossipSelect = &GossipSelect_boss_victor_nefarius; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blackwing_lair/instance_blackwing_lair.cpp b/src/bindings/scripts/scripts/zone/blackwing_lair/instance_blackwing_lair.cpp new file mode 100644 index 00000000000..7bdd3250442 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blackwing_lair/instance_blackwing_lair.cpp @@ -0,0 +1,8 @@ +/* ScriptData +SDName: Instance_Blackwing_Lair +SD%Complete: 0 +SDComment: +SDCategory: Blackwing Lair +EndScriptData */ + +#include "precompiled.h" diff --git a/src/bindings/scripts/scripts/zone/blades_edge_mountains/blades_edge_mountains.cpp b/src/bindings/scripts/scripts/zone/blades_edge_mountains/blades_edge_mountains.cpp new file mode 100644 index 00000000000..c7cb250eab7 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blades_edge_mountains/blades_edge_mountains.cpp @@ -0,0 +1,441 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Blades_Edge_Mountains +SD%Complete: 90 +SDComment: Quest support: 10503, 10504, 10556, 10609, 10682, 10980. Ogri'la->Skettis Flight. (npc_daranelle needs bit more work before consider complete) +SDCategory: Blade's Edge Mountains +EndScriptData */ + +/* ContentData +mobs_bladespire_ogre +mobs_nether_drake +npc_daranelle +npc_overseer_nuaar +npc_saikkal_the_elder +npc_skyguard_handler_irena +EndContentData */ + +#include "precompiled.h" + +/*###### +## mobs_bladespire_ogre +######*/ + +//TODO: add support for quest 10512 + creature abilities +struct MANGOS_DLL_DECL mobs_bladespire_ogreAI : public ScriptedAI +{ + mobs_bladespire_ogreAI(Creature *c) : ScriptedAI(c) {Reset();} + + void Reset() + { + } + + void Aggro(Unit* who) + { + } + + void JustDied(Unit* Killer) + { + if (Killer->GetTypeId() == TYPEID_PLAYER) + ((Player*)Killer)->KilledMonster(19995, m_creature->GetGUID()); + } +}; +CreatureAI* GetAI_mobs_bladespire_ogre(Creature *_Creature) +{ + return new mobs_bladespire_ogreAI (_Creature); +} + +/*###### +## mobs_nether_drake +######*/ + +#define SAY_NIHIL_1 "Muahahahaha! You fool! You've released me from my banishment in the interstices between space and time!" +#define SAY_NIHIL_2 "All of Draenor shall quick beneath my feet! I will destroy this world and reshape it in my image!" +#define SAY_NIHIL_3 "Where shall I begin? I cannot bother myself with a worm such as yourself. There is a world to be conquered!" +#define SAY_NIHIL_4 "No doubt the fools that banished me are long dead. I shall take wing survey my demense. Pray to whatever gods you hold dear that we do not meet again." +#define SAY_NIHIL_INTERRUPT "NOOOOooooooo!" + +#define ENTRY_WHELP 20021 +#define ENTRY_PROTO 21821 +#define ENTRY_ADOLE 21817 +#define ENTRY_MATUR 21820 +#define ENTRY_NIHIL 21823 + +#define SPELL_T_PHASE_MODULATOR 37573 + +#define SPELL_ARCANE_BLAST 38881 +#define SPELL_MANA_BURN 38884 +#define SPELL_INTANGIBLE_PRESENCE 36513 + +struct MANGOS_DLL_DECL mobs_nether_drakeAI : public ScriptedAI +{ + mobs_nether_drakeAI(Creature *c) : ScriptedAI(c) {Reset();} + + bool IsNihil; + uint32 NihilSpeech_Timer; + uint32 NihilSpeech_Phase; + + uint32 ArcaneBlast_Timer; + uint32 ManaBurn_Timer; + uint32 IntangiblePresence_Timer; + + void Reset() + { + NihilSpeech_Timer = 2000; + IsNihil = false; + if( m_creature->GetEntry() == ENTRY_NIHIL ) + { + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + IsNihil = true; + } + NihilSpeech_Phase = 1; + + ArcaneBlast_Timer = 7500; + ManaBurn_Timer = 10000; + IntangiblePresence_Timer = 15000; + } + + void Aggro(Unit* who) { } + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if( spell->Id == SPELL_T_PHASE_MODULATOR && caster->GetTypeId() == TYPEID_PLAYER ) + { + uint32 cEntry = 0; + + switch( m_creature->GetEntry() ) + { + case ENTRY_WHELP: + switch(rand()%4) + { + case 0: cEntry = ENTRY_PROTO; break; + case 1: cEntry = ENTRY_ADOLE; break; + case 2: cEntry = ENTRY_MATUR; break; + case 3: cEntry = ENTRY_NIHIL; break; + } + break; + case ENTRY_PROTO: + switch(rand()%3) + { + case 0: cEntry = ENTRY_ADOLE; break; + case 1: cEntry = ENTRY_MATUR; break; + case 2: cEntry = ENTRY_NIHIL; break; + } + break; + case ENTRY_ADOLE: + switch(rand()%3) + { + case 0: cEntry = ENTRY_PROTO; break; + case 1: cEntry = ENTRY_MATUR; break; + case 2: cEntry = ENTRY_NIHIL; break; + } + break; + case ENTRY_MATUR: + switch(rand()%3) + { + case 0: cEntry = ENTRY_PROTO; break; + case 1: cEntry = ENTRY_ADOLE; break; + case 2: cEntry = ENTRY_NIHIL; break; + } + break; + case ENTRY_NIHIL: + if( NihilSpeech_Phase ) + { + DoYell(SAY_NIHIL_INTERRUPT,LANG_UNIVERSAL,NULL); + IsNihil = false; + switch(rand()%3) + { + case 0: cEntry = ENTRY_PROTO; break; + case 1: cEntry = ENTRY_ADOLE; break; + case 2: cEntry = ENTRY_MATUR; break; + } + } + break; + } + + if( cEntry ) + { + m_creature->UpdateEntry(cEntry); + + if( cEntry == ENTRY_NIHIL ) + { + m_creature->InterruptNonMeleeSpells(true); + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); + m_creature->CombatStop(); + InCombat = false; + Reset(); + } + } + } + } + + void UpdateAI(const uint32 diff) + { + if( IsNihil ) + { + if( NihilSpeech_Phase ) + { + if(NihilSpeech_Timer <= diff) + { + switch( NihilSpeech_Phase ) + { + case 1: + DoSay(SAY_NIHIL_1,LANG_UNIVERSAL,NULL); + ++NihilSpeech_Phase; + break; + case 2: + DoSay(SAY_NIHIL_2,LANG_UNIVERSAL,NULL); + ++NihilSpeech_Phase; + break; + case 3: + DoSay(SAY_NIHIL_3,LANG_UNIVERSAL,NULL); + ++NihilSpeech_Phase; + break; + case 4: + DoSay(SAY_NIHIL_4,LANG_UNIVERSAL,NULL); + ++NihilSpeech_Phase; + break; + case 5: + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + // + MOVEMENTFLAG_LEVITATING + m_creature->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT); + //then take off to random location. creature is initially summoned, so don't bother do anything else. + m_creature->GetMotionMaster()->MovePoint(0, m_creature->GetPositionX()+100, m_creature->GetPositionY(), m_creature->GetPositionZ()+100); + NihilSpeech_Phase = 0; + break; + } + NihilSpeech_Timer = 5000; + }else NihilSpeech_Timer -=diff; + } + return; //anything below here is not interesting for Nihil, so skip it + } + + if( !m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if( IntangiblePresence_Timer <= diff ) + { + DoCast(m_creature->getVictim(),SPELL_INTANGIBLE_PRESENCE); + IntangiblePresence_Timer = 15000+rand()%15000; + }else IntangiblePresence_Timer -= diff; + + if( ManaBurn_Timer <= diff ) + { + Unit* target = m_creature->getVictim(); + if( target && target->getPowerType() == POWER_MANA ) + DoCast(target,SPELL_MANA_BURN); + ManaBurn_Timer = 8000+rand()%8000; + }else ManaBurn_Timer -= diff; + + if( ArcaneBlast_Timer <= diff ) + { + DoCast(m_creature->getVictim(),SPELL_ARCANE_BLAST); + ArcaneBlast_Timer = 2500+rand()%5000; + }else ArcaneBlast_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_mobs_nether_drake(Creature *_Creature) +{ + return new mobs_nether_drakeAI (_Creature); +} + +/*###### +## npc_daranelle +######*/ + +struct MANGOS_DLL_DECL npc_daranelleAI : public ScriptedAI +{ + npc_daranelleAI(Creature *c) : ScriptedAI(c) {Reset();} + + void Reset() + { + } + + void Aggro(Unit* who) + { + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || m_creature->getVictim()) + return; + + if (who->GetTypeId() == TYPEID_PLAYER) + { + if(who->HasAura(36904,0)) + { + DoSay("Good $N, you are under the spell's influence. I must analyze it quickly, then we can talk.",LANG_COMMON,who); + //TODO: Move the below to updateAI and run if this statement == true + ((Player*)who)->KilledMonster(21511, m_creature->GetGUID()); + ((Player*)who)->RemoveAurasDueToSpell(36904); + } + } + + if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + float attackRadius = m_creature->GetAttackDistance(who); + if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) + { + if(who->HasStealthAura()) + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + //Begin melee attack if we are within range + DoStartAttackAndMovement(who); + } + } + } +}; + +CreatureAI* GetAI_npc_daranelle(Creature *_Creature) +{ + return new npc_daranelleAI (_Creature); +} + +/*###### +## npc_overseer_nuaar +######*/ + +bool GossipHello_npc_overseer_nuaar(Player *player, Creature *_Creature) +{ + if (player->GetQuestStatus(10682) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM( 0, "Overseer, I am here to negotiate on behalf of the Cenarion Expedition.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + player->SEND_GOSSIP_MENU(10532, _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_overseer_nuaar(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + if (action == GOSSIP_ACTION_INFO_DEF+1) + { + player->SEND_GOSSIP_MENU(10533, _Creature->GetGUID()); + player->AreaExploredOrEventHappens(10682); + } + return true; +} + +/*###### +## npc_saikkal_the_elder +######*/ + +bool GossipHello_npc_saikkal_the_elder(Player *player, Creature *_Creature) +{ + if (player->GetQuestStatus(10980) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM( 0, "Yes... yes, it's me.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + player->SEND_GOSSIP_MENU(10794, _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_saikkal_the_elder(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF+1: + player->ADD_GOSSIP_ITEM( 0, "Yes elder. Tell me more of the book.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + player->SEND_GOSSIP_MENU(10795, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + player->TalkedToCreature(_Creature->GetEntry(), _Creature->GetGUID()); + player->SEND_GOSSIP_MENU(10796, _Creature->GetGUID()); + break; + } + return true; +} + +/*###### +## npc_skyguard_handler_irena +######*/ + +#define GOSSIP_SKYGUARD "Fly me to Skettis please" + +bool GossipHello_npc_skyguard_handler_irena(Player *player, Creature *_Creature ) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if (player->GetReputationRank(1031) >= REP_HONORED) + player->ADD_GOSSIP_ITEM( 2, GOSSIP_SKYGUARD, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_skyguard_handler_irena(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if (action == GOSSIP_ACTION_INFO_DEF+1) + { + player->CLOSE_GOSSIP_MENU(); + + std::vector nodes; + + nodes.resize(2); + nodes[0] = 172; //from ogri'la + nodes[1] = 171; //end at skettis + player->ActivateTaxiPathTo(nodes); //TaxiPath 706 + } + return true; +} + +/*###### +## AddSC +######*/ + +void AddSC_blades_edge_mountains() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="mobs_bladespire_ogre"; + newscript->GetAI = GetAI_mobs_bladespire_ogre; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mobs_nether_drake"; + newscript->GetAI = GetAI_mobs_nether_drake; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_daranelle"; + newscript->GetAI = GetAI_npc_daranelle; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_overseer_nuaar"; + newscript->pGossipHello = &GossipHello_npc_overseer_nuaar; + newscript->pGossipSelect = &GossipSelect_npc_overseer_nuaar; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_saikkal_the_elder"; + newscript->pGossipHello = &GossipHello_npc_saikkal_the_elder; + newscript->pGossipSelect = &GossipSelect_npc_saikkal_the_elder; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_skyguard_handler_irena"; + newscript->pGossipHello = &GossipHello_npc_skyguard_handler_irena; + newscript->pGossipSelect = &GossipSelect_npc_skyguard_handler_irena; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blasted_lands/blasted_lands.cpp b/src/bindings/scripts/scripts/zone/blasted_lands/blasted_lands.cpp new file mode 100644 index 00000000000..4c84994c5b6 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blasted_lands/blasted_lands.cpp @@ -0,0 +1,159 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Blasted_Lands +SD%Complete: 90 +SDComment: Quest support: 2784, 2801, 3628. Missing some texts for Fallen Hero. Teleporter to Rise of the Defiler missing group support. +SDCategory: Blasted Lands +EndScriptData */ + +/* ContentData +npc_deathly_usher +npc_fallen_hero_of_horde +EndContentData */ + +#include "precompiled.h" + +/*###### +## npc_deathly_usher +######*/ + +#define GOSSIP_ITEM_USHER "I wish to to visit the Rise of the Defiler." + +#define SPELL_TELEPORT_SINGLE 12885 +#define SPELL_TELEPORT_SINGLE_IN_GROUP 13142 +#define SPELL_TELEPORT_GROUP 27686 + +bool GossipHello_npc_deathly_usher(Player *player, Creature *_Creature) +{ + if(player->GetQuestStatus(3628) == QUEST_STATUS_INCOMPLETE && player->HasItemCount(10757, 1)) + player->ADD_GOSSIP_ITEM(0, GOSSIP_ITEM_USHER, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_deathly_usher(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + if(action = GOSSIP_ACTION_INFO_DEF) + { + player->CLOSE_GOSSIP_MENU(); + _Creature->CastSpell(player, SPELL_TELEPORT_SINGLE, true); + } + + return true; +} + +/*###### +## npc_fallen_hero_of_horde +######*/ + +#define GOSSIP_ITEM_FALLEN "Continue..." + +#define GOSSIP_ITEM_FALLEN1 "What could be worse than death?" +#define GOSSIP_ITEM_FALLEN2 "Subordinates?" +#define GOSSIP_ITEM_FALLEN3 "What are the stones of binding?" +#define GOSSIP_ITEM_FALLEN4 "You can count on me, Hero" +#define GOSSIP_ITEM_FALLEN5 "I shall" + +bool GossipHello_npc_fallen_hero_of_horde(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if (player->GetQuestStatus(2784) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM( 0, "Why are you here?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + if (player->GetQuestStatus(2801) == QUEST_STATUS_INCOMPLETE && player->GetTeam() == HORDE) + player->ADD_GOSSIP_ITEM( 0, "Continue story...", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + + if (player->GetQuestStatus(2801) == QUEST_STATUS_INCOMPLETE && player->GetTeam() == ALLIANCE) + player->ADD_GOSSIP_ITEM( 0, "Why are you here?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_fallen_hero_of_horde(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF+1: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_FALLEN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->SEND_GOSSIP_MENU(1392, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+11: + player->SEND_GOSSIP_MENU(1411, _Creature->GetGUID()); + if (player->GetQuestStatus(2784) == QUEST_STATUS_INCOMPLETE) + player->AreaExploredOrEventHappens(2784); + if (player->GetTeam() == ALLIANCE) + { + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_FALLEN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->SEND_GOSSIP_MENU(1411, _Creature->GetGUID()); + } + break; + + case GOSSIP_ACTION_INFO_DEF+2: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_FALLEN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 21); + player->SEND_GOSSIP_MENU(1451, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+21: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_FALLEN1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 22); + player->SEND_GOSSIP_MENU(1452, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+22: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_FALLEN2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 23); + player->SEND_GOSSIP_MENU(1453, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+23: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_FALLEN3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 24); + player->SEND_GOSSIP_MENU(1454, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+24: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_FALLEN4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 25); + player->SEND_GOSSIP_MENU(1455, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+25: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_FALLEN5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 26); + player->SEND_GOSSIP_MENU(1456, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+26: + player->CLOSE_GOSSIP_MENU(); + player->AreaExploredOrEventHappens(2801); + break; + } + return true; +} + +void AddSC_blasted_lands() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npc_deathly_usher"; + newscript->pGossipHello = &GossipHello_npc_deathly_usher; + newscript->pGossipSelect = &GossipSelect_npc_deathly_usher; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_fallen_hero_of_horde"; + newscript->pGossipHello = &GossipHello_npc_fallen_hero_of_horde; + newscript->pGossipSelect = &GossipSelect_npc_fallen_hero_of_horde; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/blasted_lands/boss_kruul.cpp b/src/bindings/scripts/scripts/zone/blasted_lands/boss_kruul.cpp new file mode 100644 index 00000000000..fd8eb90ddf0 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/blasted_lands/boss_kruul.cpp @@ -0,0 +1,182 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Kruul +SD%Complete: 100 +SDComment: Highlord Kruul are presumably no longer in-game on regular bases, however future events could bring him back. +SDCategory: Bosses +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_SHADOWVOLLEY 21341 +#define SPELL_CLEAVE 20677 +#define SPELL_THUNDERCLAP 23931 +#define SPELL_TWISTEDREFLECTION 21063 +#define SPELL_VOIDBOLT 21066 +#define SPELL_RAGE 21340 +#define SPELL_CAPTURESOUL 21054 + +struct MANGOS_DLL_DECL boss_kruulAI : public ScriptedAI +{ + boss_kruulAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 ShadowVolley_Timer; + uint32 Cleave_Timer; + uint32 ThunderClap_Timer; + uint32 TwistedReflection_Timer; + uint32 VoidBolt_Timer; + uint32 Rage_Timer; + uint32 Hound_Timer; + int Rand; + int RandX; + int RandY; + Creature* Summoned; + + void Reset() + { + ShadowVolley_Timer = 10000; + Cleave_Timer = 14000; + ThunderClap_Timer = 20000; + TwistedReflection_Timer = 25000; + VoidBolt_Timer = 30000; + Rage_Timer = 60000; //Cast rage after 1 minute + Hound_Timer = 8000; + } + + void Aggro(Unit *who) + { + } + + void KilledUnit() + { + // When a player, pet or totem gets killed, Lord Kazzak casts this spell to instantly regenerate 70,000 health. + DoCast(m_creature,SPELL_CAPTURESOUL); + + } + + void SummonHounds(Unit* victim) + { + Rand = rand()%10; + switch (rand()%2) + { + case 0: RandX = 0 - Rand; break; + case 1: RandX = 0 + Rand; break; + } + Rand = 0; + Rand = rand()%10; + switch (rand()%2) + { + case 0: RandY = 0 - Rand; break; + case 1: RandY = 0 + Rand; break; + } + Rand = 0; + Summoned = DoSpawnCreature(19207, RandX, RandY, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); + if(Summoned) + ((CreatureAI*)Summoned->AI())->AttackStart(victim); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //ShadowVolley_Timer + if (ShadowVolley_Timer < diff) + { + if (rand()%100 < 46) + { + DoCast(m_creature->getVictim(),SPELL_SHADOWVOLLEY); + } + + ShadowVolley_Timer = 5000; + }else ShadowVolley_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer < diff) + { + if (rand()%100 < 50) + { + DoCast(m_creature->getVictim(),SPELL_CLEAVE); + } + + Cleave_Timer = 10000; + }else Cleave_Timer -= diff; + + //ThunderClap_Timer + if (ThunderClap_Timer < diff) + { + if (rand()%100 < 20) + { + DoCast(m_creature->getVictim(),SPELL_THUNDERCLAP); + } + + ThunderClap_Timer = 12000; + }else ThunderClap_Timer -= diff; + + //TwistedReflection_Timer + if (TwistedReflection_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_TWISTEDREFLECTION); + TwistedReflection_Timer = 30000; + }else TwistedReflection_Timer -= diff; + + //VoidBolt_Timer + if (VoidBolt_Timer < diff) + { + if (rand()%100 < 40) + { + DoCast(m_creature->getVictim(),SPELL_VOIDBOLT); + } + + VoidBolt_Timer = 18000; + }else VoidBolt_Timer -= diff; + + //Rage_Timer + if (Rage_Timer < diff) + { + DoCast(m_creature,SPELL_RAGE); + Rage_Timer = 70000; + }else Rage_Timer -= diff; + + //Hound_Timer + if (Hound_Timer < diff) + { + SummonHounds(m_creature->getVictim()); + SummonHounds(m_creature->getVictim()); + SummonHounds(m_creature->getVictim()); + + Hound_Timer = 45000; + }else Hound_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_kruul(Creature *_Creature) +{ + return new boss_kruulAI (_Creature); +} + +void AddSC_boss_kruul() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_kruul"; + newscript->GetAI = GetAI_boss_kruul; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/bloodmyst_isle/bloodmyst_isle.cpp b/src/bindings/scripts/scripts/zone/bloodmyst_isle/bloodmyst_isle.cpp new file mode 100644 index 00000000000..254d5082797 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/bloodmyst_isle/bloodmyst_isle.cpp @@ -0,0 +1,141 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Bloodmyst_Isle +SD%Complete: 80 +SDComment: Quest support: 9670, 9756(gossip items text needed). +SDCategory: Bloodmyst Isle +EndScriptData */ + +/* ContentData +mob_webbed_creature +npc_captured_sunhawk_agent +EndContentData */ + +#include "precompiled.h" + +/*###### +## mob_webbed_creature +######*/ + +//possible creatures to be spawned +const uint32 possibleSpawns[32] = {17322, 17661, 17496, 17522, 17340, 17352, 17333, 17524, 17654, 17348, 17339, 17345, 17359, 17353, 17336, 17550, 17330, 17701, 17321, 17680, 17325, 17320, 17683, 17342, 17715, 17334, 17341, 17338, 17337, 17346, 17344, 17327}; + +struct MANGOS_DLL_DECL mob_webbed_creatureAI : public ScriptedAI +{ + mob_webbed_creatureAI(Creature *c) : ScriptedAI(c) {Reset();} + + void Reset() + { + } + + void Aggro(Unit* who) + { + } + + void JustDied(Unit* Killer) + { + uint32 spawnCreatureID; + + switch(rand()%3) + { + case 0: + spawnCreatureID = 17681; + if (Killer->GetTypeId() == TYPEID_PLAYER) + ((Player*)Killer)->KilledMonster(spawnCreatureID, m_creature->GetGUID()); + break; + case 1: + case 2: + spawnCreatureID = possibleSpawns[rand()%31]; + break; + } + + if(spawnCreatureID) + DoSpawnCreature(spawnCreatureID,0,0,0,m_creature->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); + } +}; +CreatureAI* GetAI_mob_webbed_creature(Creature *_Creature) +{ + return new mob_webbed_creatureAI (_Creature); +} + +/*###### +## npc_captured_sunhawk_agent +######*/ + +#define C_SUNHAWK_TRIGGER 17974 + +bool GossipHello_npc_captured_sunhawk_agent(Player *player, Creature *_Creature) +{ + if (player->HasAura(31609,1) && player->GetQuestStatus(9756) == QUEST_STATUS_INCOMPLETE) + { + player->ADD_GOSSIP_ITEM( 0, "[PH] ", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + player->SEND_GOSSIP_MENU(9136, _Creature->GetGUID()); + } + else + player->SEND_GOSSIP_MENU(9134, _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_captured_sunhawk_agent(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF+1: + player->ADD_GOSSIP_ITEM( 0, "[PH] ", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + player->SEND_GOSSIP_MENU(9137, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + player->ADD_GOSSIP_ITEM( 0, "[PH] ", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + player->SEND_GOSSIP_MENU(9138, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + player->ADD_GOSSIP_ITEM( 0, "[PH] ", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + player->SEND_GOSSIP_MENU(9139, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + player->ADD_GOSSIP_ITEM( 0, "[PH] ", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + player->SEND_GOSSIP_MENU(9140, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + player->ADD_GOSSIP_ITEM( 0, "[PH] ", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); + player->SEND_GOSSIP_MENU(9141, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+6: + player->CLOSE_GOSSIP_MENU(); + player->TalkedToCreature(C_SUNHAWK_TRIGGER, _Creature->GetGUID()); + break; + } + return true; +} + +void AddSC_bloodmyst_isle() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="mob_webbed_creature"; + newscript->GetAI = GetAI_mob_webbed_creature; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_captured_sunhawk_agent"; + newscript->pGossipHello = &GossipHello_npc_captured_sunhawk_agent; + newscript->pGossipSelect = &GossipSelect_npc_captured_sunhawk_agent; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/burning_steppes/burning_steppes.cpp b/src/bindings/scripts/scripts/zone/burning_steppes/burning_steppes.cpp new file mode 100644 index 00000000000..0526163be56 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/burning_steppes/burning_steppes.cpp @@ -0,0 +1,157 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Burning_Steppes +SD%Complete: 100 +SDComment: Quest support: 4224, 4866 +SDCategory: Burning Steppes +EndScriptData */ + +/* ContentData +npc_ragged_john +EndContentData */ + +#include "precompiled.h" + +/*###### +## npc_ragged_john +######*/ + +struct MANGOS_DLL_DECL npc_ragged_johnAI : public ScriptedAI +{ + npc_ragged_johnAI(Creature *c) : ScriptedAI(c) { Reset(); } + + void Reset() {} + + void MoveInLineOfSight(Unit *who) + { + if( who->HasAura(16468,0) ) + { + if( who->GetTypeId() == TYPEID_PLAYER && m_creature->IsWithinDistInMap(who, 15) && who->isInAccessablePlaceFor(m_creature) ) + { + DoCast(who,16472); + ((Player*)who)->AreaExploredOrEventHappens(4866); + } + } + + if( !m_creature->getVictim() && who->isTargetableForAttack() && ( m_creature->IsHostileTo( who )) && who->isInAccessablePlaceFor(m_creature) ) + { + if (m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = m_creature->GetAttackDistance(who); + if( m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->IsWithinLOSInMap(who) ) + { + DoStartAttackAndMovement(who); + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + if (!InCombat) + { + Aggro(who); + InCombat = true; + } + } + } + } + + void Aggro(Unit *who) {} +}; + +CreatureAI* GetAI_npc_ragged_john(Creature *_Creature) +{ + return new npc_ragged_johnAI (_Creature); +} + +bool GossipHello_npc_ragged_john(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if (player->GetQuestStatus(4224) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM( 0, "Official buisness, John. I need some information about Marsha Windsor. Tell me about the last time you saw him.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + player->SEND_GOSSIP_MENU(2713, _Creature->GetGUID()); + return true; +} + +bool GossipSelect_npc_ragged_john(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF: + player->ADD_GOSSIP_ITEM( 0, "So what did you do?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->SEND_GOSSIP_MENU(2714, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+1: + player->ADD_GOSSIP_ITEM( 0, "Start making sense, dwarf. I don't want to have anything to do with your cracker, your pappy, or any sort of 'discreditin'.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->SEND_GOSSIP_MENU(2715, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + player->ADD_GOSSIP_ITEM( 0, "Ironfoe?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->SEND_GOSSIP_MENU(2716, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + player->ADD_GOSSIP_ITEM( 0, "Interesting... continue John.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->SEND_GOSSIP_MENU(2717, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + player->ADD_GOSSIP_ITEM( 0, "So that's how Windsor died...", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->SEND_GOSSIP_MENU(2718, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + player->ADD_GOSSIP_ITEM( 0, "So how did he die?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->SEND_GOSSIP_MENU(2719, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+6: + player->ADD_GOSSIP_ITEM( 0, "Ok so where the hell is he? Wait a minute! Are you drunk?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->SEND_GOSSIP_MENU(2720, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+7: + player->ADD_GOSSIP_ITEM( 0, "WHY is he in Blackrock Depths?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->SEND_GOSSIP_MENU(2721, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+8: + player->ADD_GOSSIP_ITEM( 0, "300? So the Dark Irons killed him and dragged him into the Depths?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 9); + player->SEND_GOSSIP_MENU(2722, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+9: + player->ADD_GOSSIP_ITEM( 0, "Ahh... Ironfoe", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 10); + player->SEND_GOSSIP_MENU(2723, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+10: + player->ADD_GOSSIP_ITEM( 0, "Thanks, Ragged John. Your story was very uplifting and informative", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->SEND_GOSSIP_MENU(2725, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+11: + player->CLOSE_GOSSIP_MENU(); + player->AreaExploredOrEventHappens(4224); + break; + } + return true; +} + +void AddSC_burning_steppes() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npc_ragged_john"; + newscript->GetAI = GetAI_npc_ragged_john; + newscript->pGossipHello = &GossipHello_npc_ragged_john; + newscript->pGossipSelect = &GossipSelect_npc_ragged_john; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/dark_portal/boss_aeonus.cpp b/src/bindings/scripts/scripts/zone/caverns_of_time/dark_portal/boss_aeonus.cpp new file mode 100644 index 00000000000..89e9ee31dfe --- /dev/null +++ b/src/bindings/scripts/scripts/zone/caverns_of_time/dark_portal/boss_aeonus.cpp @@ -0,0 +1,137 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Aeonus +SD%Complete: 100 +SDComment: +SDCategory: Caverns of Time, The Dark Portal +EndScriptData */ + +#include "precompiled.h" + +#define SAND_BREATH 31478 +#define TIME_STOP 31422 +#define FRENZY 19812 + +#define SAY_ENTER "The time has come to shatter this clockwork universe forever! Let us no longer be slaves of the hourglass! I warn you: those who do not embrace the greater path shall become victims of its passing!" +#define SAY_AGGRO "Let us see what fate lays in store..." +#define SAY_BANISH "Your time is up, slave of the past!" +#define SAY_SLAY1 "One less obstacle in our way!" +#define SAY_SLAY2 "No one can stop us! No one!" +#define SAY_DEATH "It is only a matter...of time." + +#define SOUND_ENTER 10400 +#define SOUND_AGGRO 10402 +#define SOUND_BANISH 10401 +#define SOUND_SLAY1 10403 +#define SOUND_SLAY2 10404 +#define SOUND_DEATH 10405 + +struct MANGOS_DLL_DECL boss_aeonusAI : public ScriptedAI +{ + boss_aeonusAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 SandBreath_Timer; + uint32 TimeStop_Timer; + uint32 Frenzy_Timer; + + void Reset() + { + SandBreath_Timer = 30000; + TimeStop_Timer = 40000; + Frenzy_Timer = 120000; + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO); + } + + void JustDied(Unit *victim) + { + //Just Died + DoYell(SAY_DEATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_DEATH); + } + + void KilledUnit(Unit *victim) + { + //Killed Unit + switch(rand()%2) + { + case 0: + DoYell(SAY_SLAY1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY1); + break; + case 1: + DoYell(SAY_SLAY2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY2); + break; + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //Sand Breath + if (SandBreath_Timer < diff) + { + Unit* target = NULL; + target = m_creature->getVictim(); + if (target) + DoCast(target, SAND_BREATH); + SandBreath_Timer = 30000; + }else SandBreath_Timer -= diff; + + //Time Stop + if (TimeStop_Timer < diff) + { + DoYell(SAY_BANISH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_BANISH); + + DoCast(m_creature->getVictim(), TIME_STOP); + TimeStop_Timer = 40000; + }else TimeStop_Timer -= diff; + + //Frenzy + if (Frenzy_Timer < diff) + { + DoCast(m_creature, FRENZY); + Frenzy_Timer = 120000; + }else Frenzy_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_aeonus(Creature *_Creature) +{ + return new boss_aeonusAI (_Creature); +} + +void AddSC_boss_aeonus() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_aeonus"; + newscript->GetAI = GetAI_boss_aeonus; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/dark_portal/boss_chrono_lord_deja.cpp b/src/bindings/scripts/scripts/zone/caverns_of_time/dark_portal/boss_chrono_lord_deja.cpp new file mode 100644 index 00000000000..1dcc7fcc5ee --- /dev/null +++ b/src/bindings/scripts/scripts/zone/caverns_of_time/dark_portal/boss_chrono_lord_deja.cpp @@ -0,0 +1,124 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Chrono_Lord_Deja +SD%Complete: 100 +SDComment: +SDCategory: Caverns of Time, The Dark Portal +EndScriptData */ + +#include "precompiled.h" + +#define ARCANE_BLAST 24857 +#define TIME_LAPSE 31467 +#define MAGNETIC_PULL 28337 //Not Implemented (Heroic mod) + +#define SAY_ENTER "Why do you aid the Magus? Just think of how many lives could be saved if the portal is never opened, if the resulting wars could be erased ..." +#define SAY_AGGRO "If you will not cease this foolish quest, then you will die!" +#define SAY_BANISH "You have outstayed your welcome, Timekeeper. Begone!" +#define SAY_SLAY1 "I told you it was a fool's quest!" +#define SAY_SLAY2 "Leaving so soon?" +#define SAY_DEATH "Time ... is on our side." + +#define SOUND_ENTER 10412 +#define SOUND_AGGRO 10414 +#define SOUND_BANISH 10413 +#define SOUND_SLAY1 10415 +#define SOUND_SLAY2 10416 +#define SOUND_DEATH 10417 + +struct MANGOS_DLL_DECL boss_chrono_lord_dejaAI : public ScriptedAI +{ + boss_chrono_lord_dejaAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 ArcaneBlast_Timer; + uint32 TimeLapse_Timer; + + void Reset() + { + ArcaneBlast_Timer = 20000; + TimeLapse_Timer = 15000; + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO); + + } + + void KilledUnit(Unit *victim) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_SLAY1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY1); + break; + case 1: + DoYell(SAY_SLAY2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY2); + break; + } + } + + void JustDied(Unit *victim) + { + DoYell(SAY_DEATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_DEATH); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //Arcane Blast + if (ArcaneBlast_Timer < diff) + { + DoCast(m_creature->getVictim(), ARCANE_BLAST); + ArcaneBlast_Timer = 20000+rand()%5000; + }else ArcaneBlast_Timer -= diff; + + //Time Lapse + if (TimeLapse_Timer < diff) + { + DoYell(SAY_BANISH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_BANISH); + DoCast(m_creature, TIME_LAPSE); + TimeLapse_Timer = 15000+rand()%10000; + }else TimeLapse_Timer -= diff; + + DoMeleeAttackIfReady(); + + } +}; + +CreatureAI* GetAI_boss_chrono_lord_deja(Creature *_Creature) +{ + return new boss_chrono_lord_dejaAI (_Creature); +} + +void AddSC_boss_chrono_lord_deja() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_chrono_lord_deja"; + newscript->GetAI = GetAI_boss_chrono_lord_deja; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/dark_portal/boss_temporus.cpp b/src/bindings/scripts/scripts/zone/caverns_of_time/dark_portal/boss_temporus.cpp new file mode 100644 index 00000000000..c95657634cf --- /dev/null +++ b/src/bindings/scripts/scripts/zone/caverns_of_time/dark_portal/boss_temporus.cpp @@ -0,0 +1,166 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Temporus +SD%Complete: 100 +SDComment: +SDCategory: Caverns of Time, The Dark Portal +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_TAUNT 355 +#define SPELL_HASTE 31458 +#define SPELL_MORTAL_WOUND 28467 +#define SPELL_REFLECT 23920 //Not Implemented (Heroic mod) + +#define SAY_ENTER "Why do you persist? Surely you can see the futility of it all. It is not too late! You may still leave with your lives ..." +#define SAY_AGGRO "So be it ... you have been warned." +#define SAY_BANISH "Time... sands of time is run out for you." +#define SAY_SLAY1 "You should have left when you had the chance." +#define SAY_SLAY2 "Your days are done." +#define SAY_DEATH "My death means ... little." + +#define SOUND_ENTER 10442 +#define SOUND_AGGRO 10444 +#define SOUND_BANISH 10443 +#define SOUND_SLAY1 10445 +#define SOUND_SLAY2 10446 +#define SOUND_DEATH 10447 + +struct MANGOS_DLL_DECL boss_temporusAI : public ScriptedAI +{ + boss_temporusAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Haste_Timer; + uint32 SpellReflection_Timer; + + void Reset() + { + Haste_Timer = 20000; + SpellReflection_Timer = 40000; + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO); + } + + void KilledUnit(Unit *victim) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_SLAY1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY1); + break; + case 1: + DoYell(SAY_SLAY2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY2); + break; + } + } + + void JustDied(Unit *victim) + { + DoYell(SAY_DEATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_DEATH); + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || m_creature->getVictim()) + return; + + //Despawn Time Keeper + if (who->GetTypeId() == TYPEID_UNIT) + { + if(((Creature*)who)->GetEntry() == 17918 && m_creature->IsWithinDistInMap(who,20)) + { + //This is the wrong yell & sound for despawning time keepers! + DoYell(SAY_ENTER, LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_ENTER); + + m_creature->DealDamage(who, who->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + + if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + float attackRadius = m_creature->GetAttackDistance(who); + if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) + { + if(who->HasStealthAura()) + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + DoStartAttackAndMovement(who); + if (!InCombat) + { + DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO); + } + } + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //Check if we have a current target + if( m_creature->getVictim() && m_creature->isAlive()) + { + + //Attack Haste + if (Haste_Timer < diff) + { + DoCast(m_creature, SPELL_HASTE); + Haste_Timer = 20000+rand()%5000; + }else Haste_Timer -= diff; + + //Spell Reflection + if (SpellReflection_Timer < diff) + { + DoYell(SAY_BANISH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_BANISH); + + DoCast(m_creature, SPELL_REFLECT); + SpellReflection_Timer = 40000+rand()%10000; + }else SpellReflection_Timer -= diff; + + DoMeleeAttackIfReady(); + + } + } +}; + +CreatureAI* GetAI_boss_temporus(Creature *_Creature) +{ + return new boss_temporusAI (_Creature); +} + +void AddSC_boss_temporus() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_temporus"; + newscript->GetAI = GetAI_boss_temporus; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_archimonde.cpp b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_archimonde.cpp new file mode 100644 index 00000000000..d6e24a30a9a --- /dev/null +++ b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_archimonde.cpp @@ -0,0 +1,788 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Archimonde +SD%Complete: 95 +SDComment: Doomfires not completely offlike due to core limitations for random moving. +SDCategory: Caverns of Time, Mount Hyjal +EndScriptData */ + +#include "precompiled.h" +#include "def_hyjal.h" +#include "SpellAuras.h" + +#define SPELL_DENOUEMENT_WISP 32124 +#define SPELL_ANCIENT_SPARK 39349 +#define SPELL_PROTECTION_OF_ELUNE 38528 + +#define SPELL_DRAIN_WORLD_TREE 39140 +#define SPELL_DRAIN_WORLD_TREE_2 39141 + +#define SPELL_FINGER_OF_DEATH 31984 +#define SPELL_HAND_OF_DEATH 35354 +#define SPELL_AIR_BURST 32014 +#define SPELL_GRIP_OF_THE_LEGION 31972 +#define SPELL_DOOMFIRE_SPAWN 32074 +#define SPELL_DOOMFIRE_VISUAL 42344 // This is actually a Zul'Aman spell, but the proper Doomfire spell sometimes freezes the server if a player stands in it for too long +#define SPELL_DOOMFIRE_DAMAGE 31944 +#define SPELL_SOUL_CHARGE_YELLOW 32045 +#define SPELL_SOUL_CHARGE_GREEN 32051 +#define SPELL_SOUL_CHARGE_RED 32052 +#define SPELL_UNLEASH_SOUL_YELLOW 32054 +#define SPELL_UNLEASH_SOUL_GREEN 32057 +#define SPELL_UNLEASH_SOUL_RED 32053 +#define SPELL_FEAR 31970 + +#define SAY_AGGRO "Your resistance is insignificant!" +#define SOUND_AGGRO 10987 + +#define SAY_DOOMFIRE1 "This world will burn!" +#define SOUND_DOOMFIRE1 10990 + +#define SAY_DOOMFIRE2 "Manach sheek-thrish!" +#define SOUND_DOOMFIRE2 11041 + +#define SAY_AIR_BURST "A-kreesh!" +#define SOUND_AIR_BURST 10989 + +#define SAY_AIR_BURST2 "Away vermin!" +#define SOUND_AIR_BURST2 11043 + +#define SAY_SLAY1 "All creation will be devoured!" +#define SOUND_SLAY1 11044 + +#define SAY_SLAY2 "Your soul will languish for eternity." +#define SOUND_SLAY2 10991 + +#define SAY_SLAY3 "I am the coming of the end!" +#define SOUND_SLAY3 11045 + +#define SAY_UNK1 "You are mine now." +#define SOUND_UNK1 10988 + +#define SAY_UNK2 "Bow to my will." +#define SOUND_UNK2 11042 + +#define SAY_ENRAGE "At last it is here. Mourn and lament the passing of all you have ever known and all that would have been! Akmin-kurai!" +#define SOUND_ENRAGE 10993 + +#define SAY_DEATH "No, it cannot be! Nooo!" +#define SOUND_DEATH 10992 + +#define CREATURE_ARCHIMONDE 17968 +#define CREATURE_DOOMFIRE 18095 +#define CREATURE_DOOMFIRE_TARGETING 18104 +#define CREATURE_ANCIENT_WISP 17946 +#define CREATURE_CHANNEL_TARGET 22418 + +#define NORDRASSIL_X 5503.713 +#define NORDRASSIL_Y -3523.436 +#define NORDRASSIL_Z 1608.781 + +struct mob_ancient_wispAI : public ScriptedAI +{ + mob_ancient_wispAI(Creature* c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + uint64 ArchimondeGUID; + uint32 CheckTimer; + + void Reset() + { + ArchimondeGUID = 0; + CheckTimer = 1000; + + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void Aggro(Unit* who) {} + + void DamageTaken(Unit* done_by, uint32 &damage) { damage = 0; } + + void UpdateAI(const uint32 diff) + { + if(!ArchimondeGUID) + { + if(pInstance) + ArchimondeGUID = pInstance->GetData64(DATA_ARCHIMONDE); + } + + if(CheckTimer < diff) + { + if(ArchimondeGUID) + { + Unit* Archimonde = Unit::GetUnit((*m_creature), ArchimondeGUID); + if(Archimonde) + { + if((((Archimonde->GetHealth()*100) / Archimonde->GetMaxHealth()) < 2) || !Archimonde->isAlive()) + DoCast(m_creature, SPELL_DENOUEMENT_WISP); + else + DoCast(Archimonde, SPELL_ANCIENT_SPARK); + } + } + CheckTimer = 1000; + }else CheckTimer -= diff; + } +}; + +/* This script controls the Doomfire mob. Unlike the other Doomfire mob, this one does not stalk players. + Instead, this doomfire will simply stand in one place after spawning and deal damage to any players that + are within 3 yards. Another creature called Doomfire Targetting spawns this creature as well as stalks. */ +struct MANGOS_DLL_DECL mob_doomfireAI : public ScriptedAI +{ + mob_doomfireAI(Creature* c) : ScriptedAI(c) + { + Reset(); + } + + uint32 CheckTimer; + uint32 RefreshTimer; + + bool TargetSelected; + + uint64 ArchimondeGUID; + uint64 TargetGUID; + + void Reset() + { + CheckTimer = 5000; + RefreshTimer = 0; + + TargetSelected = false; + + ArchimondeGUID = 0; + TargetGUID = 0; + } + + void DamageTaken(Unit *done_by, uint32 &damage) { damage = 0; } + + void Aggro(Unit* who) { } + + void MoveInLineOfSight(Unit* who) + { + // Do not do anything if who does not exist, or we are refreshing our timer, or who is Doomfire, Archimonde or Doomfire targetting + if(!who || who == m_creature || RefreshTimer || who->GetEntry() == CREATURE_ANCIENT_WISP || + who->GetEntry() == CREATURE_ARCHIMONDE || who->GetEntry() == CREATURE_DOOMFIRE || + who->GetEntry() == CREATURE_DOOMFIRE_TARGETING || !who->isTargetableForAttack()) + return; + + if(m_creature->IsWithinDistInMap(who, 3)) + { + TargetSelected = true; + TargetGUID = who->GetGUID(); + RefreshTimer = 2000; + } + } + + void KilledUnit(Unit* victim) + { + bool suicide = true; + if(ArchimondeGUID) + { + Creature* Archimonde = ((Creature*)Unit::GetUnit((*m_creature), ArchimondeGUID)); + if(Archimonde && Archimonde->isAlive()) + { + suicide = false; + Archimonde->AI()->KilledUnit(victim); + } + } + + if(suicide) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + void UpdateAI(const uint32 diff) + { + if(RefreshTimer < diff) + RefreshTimer = 0; + else RefreshTimer -= diff; + + if(TargetSelected && TargetGUID) + { + Unit* target = Unit::GetUnit((*m_creature), TargetGUID); + if(target && target->isAlive()) + { + target->CastSpell(target, SPELL_DOOMFIRE_DAMAGE, true); + TargetGUID = 0; + TargetSelected = false; + } + } + + if(CheckTimer < diff) + { + if(ArchimondeGUID) + { + Unit* Archimonde = Unit::GetUnit((*m_creature), ArchimondeGUID); + if(!Archimonde || !Archimonde->isAlive()) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + CheckTimer = 5000; + } + else m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + }else CheckTimer -= diff; + } +}; + +/* This is the script for the Doomfire Targetting Mob. This mob simply follows players and/or travels in random directions and spawns the actual Doomfire which does damage to anyone that moves close. */ +struct MANGOS_DLL_DECL mob_doomfire_targettingAI : public ScriptedAI +{ + mob_doomfire_targettingAI(Creature* c) : ScriptedAI(c) + { + Reset(); + } + + uint32 ChangeTargetTimer; + uint32 SummonTimer; // This timer will serve as both a summon timer for the doomfire that does damage as well as to check on Archionde + + uint64 ArchimondeGUID; + + void Reset() + { + ChangeTargetTimer = 5000; + SummonTimer = 1000; + + ArchimondeGUID = 0; + } + + void Aggro(Unit* who) {} + + void MoveInLineOfSight(Unit* who) + { + // Do not do anything if who does not exist, or who is Doomfire, Archimonde or Doomfire targetting + if(!who || who == m_creature || who->GetEntry() == CREATURE_ARCHIMONDE + || who->GetEntry() == CREATURE_DOOMFIRE || who->GetEntry() == CREATURE_DOOMFIRE_TARGETING || !who->isTargetableForAttack()) + return; + + m_creature->AddThreat(who, 1.0f); + } + + void DamageTaken(Unit *done_by, uint32 &damage) { damage = 0; } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(SummonTimer < diff) + { + if(ArchimondeGUID) + { + Unit* Archimonde = Unit::GetUnit((*m_creature), ArchimondeGUID); + if(Archimonde && Archimonde->isAlive()) + { + Creature* Doomfire = DoSpawnCreature(CREATURE_DOOMFIRE, 0, 0, 2, 0, TEMPSUMMON_TIMED_DESPAWN, 30000); + if(Doomfire) + { + Doomfire->CastSpell(Doomfire, SPELL_DOOMFIRE_VISUAL, true); + ((mob_doomfireAI*)Doomfire->AI())->ArchimondeGUID = ArchimondeGUID; + Doomfire->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + SummonTimer = 500; + } + else + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + else + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + }else SummonTimer -= diff; + + if(ChangeTargetTimer < diff) + { + Unit* target = NULL; + switch(rand()%2) + { + case 0: // stalk player + target = SelectUnit(SELECT_TARGET_RANDOM, 1); + if(target && target->isAlive()) + { + m_creature->AddThreat(target, m_creature->getThreatManager().getThreat(m_creature->getVictim())); + m_creature->GetMotionMaster()->MoveChase(target); + } + break; + + case 1: // random location + float x = 0; + float y = 0; + float z = 0; + m_creature->GetRandomPoint(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 40, x, y, z); + m_creature->GetMotionMaster()->MovePoint(0, x, y, z); + break; + } + ChangeTargetTimer = 5000; + }else ChangeTargetTimer -= diff; + } + +}; + +/* Finally, Archimonde's script. His script isn't extremely complex, most are simply spells on timers. + The only complicated aspect of the battle is Finger of Death and Doomfire, with Doomfire being the + hardest bit to code. Finger of Death is simply a distance check - if no one is in melee range, then + select a random target and cast the spell on them. However, if someone IS in melee range, and this + is NOT the main tank (creature's victim), then we aggro that player and they become the new victim. + For Doomfire, we summon a mob (Doomfire Targetting) that summons another mob (Doomfire every second) + Doomfire Targetting 'stalks' players whilst Doomfire damages player that are within range. */ + +// This is used to sort by distance in order to see who is the closest target, when checking for Finger of Death +struct TargetDistanceOrder : public std::binary_function +{ + const Unit* MainTarget; + TargetDistanceOrder(const Unit* Target) : MainTarget(Target) {}; + // functor for operator "<" + bool operator()(const Unit* _Left, const Unit* _Right) const + { + return (MainTarget->GetDistance(_Left) < MainTarget->GetDistance(_Right)); + } +}; + +struct MANGOS_DLL_DECL boss_archimondeAI : public ScriptedAI +{ + boss_archimondeAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + + uint32 DrainNordrassilTimer; + uint32 FearTimer; + uint32 AirBurstTimer; + uint32 GripOfTheLegionTimer; + uint32 DoomfireTimer; + uint32 SoulChargeTimer; + uint32 SoulChargeCount; + uint32 MeleeRangeCheckTimer; + uint32 HandOfDeathTimer; + uint32 SummonWispTimer; + uint32 WispCount; + uint32 EnrageTimer; + uint32 CheckDistanceTimer; + + bool Enraged; + bool BelowTenPercent; + bool HasProtected; + bool IsChanneling; + + void Reset() + { + if(pInstance) + pInstance->SetData(DATA_ARCHIMONDEEVENT, NOT_STARTED); + + DrainNordrassilTimer = 0; + FearTimer = 40000; + AirBurstTimer = 30000; + GripOfTheLegionTimer = 5000 + rand()%20000; + DoomfireTimer = 20000; + SoulChargeTimer = 2000 + rand()%27000; + SoulChargeCount = 0; + MeleeRangeCheckTimer = 15000; + HandOfDeathTimer = 2000; + WispCount = 0; // When ~30 wisps are summoned, Archimonde dies + EnrageTimer = 600000; // 10 minutes + CheckDistanceTimer = 30000; // This checks if he's too close to the World Tree (75 yards from a point on the tree), if true then he will enrage + + Enraged = false; + BelowTenPercent = false; + HasProtected = false; + IsChanneling = false; + } + + void Aggro(Unit *who) + { + m_creature->InterruptSpell(CURRENT_CHANNELED_SPELL); + DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO); + DoZoneInCombat(); + + if(pInstance) + pInstance->SetData(DATA_ARCHIMONDEEVENT, IN_PROGRESS); + } + + void KilledUnit(Unit *victim) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_SLAY1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY1); + break; + case 1: + DoYell(SAY_SLAY2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY2); + break; + case 2: + DoYell(SAY_SLAY3,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY3); + break; + } + + if(victim && (victim->GetTypeId() == TYPEID_PLAYER)) + GainSoulCharge(((Player*)victim)); + } + + void GainSoulCharge(Player* victim) + { + switch(victim->getClass()) + { + case CLASS_PRIEST: + case CLASS_PALADIN: + case CLASS_WARLOCK: + victim->CastSpell(m_creature, SPELL_SOUL_CHARGE_RED, true); + break; + case CLASS_MAGE: + case CLASS_ROGUE: + case CLASS_WARRIOR: + victim->CastSpell(m_creature, SPELL_SOUL_CHARGE_YELLOW, true); + break; + case CLASS_DRUID: + case CLASS_SHAMAN: + case CLASS_HUNTER: + victim->CastSpell(m_creature, SPELL_SOUL_CHARGE_GREEN, true); + break; + } + + SoulChargeTimer = 2000 + rand()%28000; + ++SoulChargeCount; + } + + void JustDied(Unit *victim) + { + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_DEATH); + + if(pInstance) + pInstance->SetData(DATA_ARCHIMONDEEVENT, DONE); + } + + bool CanUseFingerOfDeath() + { + // First we check if our current victim is in melee range or not. + Unit* victim = m_creature->getVictim(); + if(victim && m_creature->IsWithinDistInMap(victim, m_creature->GetAttackDistance(victim))) + return false; + + std::list& m_threatlist = m_creature->getThreatManager().getThreatList(); + if(m_threatlist.empty()) + return false; + + std::list targets; + std::list::iterator itr = m_threatlist.begin(); + for( ; itr != m_threatlist.end(); ++itr) + { + Unit* pUnit = Unit::GetUnit((*m_creature), (*itr)->getUnitGuid()); + if(pUnit && pUnit->isAlive()) + targets.push_back(pUnit); + } + + if(targets.empty()) + return false; + + targets.sort(TargetDistanceOrder(m_creature)); + Unit* target = targets.front(); + if(target) + { + if(!m_creature->IsWithinDistInMap(target, m_creature->GetAttackDistance(target))) + return true; // Cast Finger of Death + else // This target is closest, he is our new tank + m_creature->AddThreat(target, m_creature->getThreatManager().getThreat(m_creature->getVictim())); + } + + return false; + } + + void SummonDoomfire(Unit* target) + { + Creature* Doomfire = DoSpawnCreature(CREATURE_DOOMFIRE_TARGETING, rand()%30, rand()%30, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 30000); + if(Doomfire) + { + ((mob_doomfire_targettingAI*)Doomfire->AI())->ArchimondeGUID = m_creature->GetGUID(); + Doomfire->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + // Give Doomfire a taste of everyone in the threatlist = more targets to chase. + std::list::iterator itr; + for(itr = m_creature->getThreatManager().getThreatList().begin(); itr != m_creature->getThreatManager().getThreatList().end(); ++itr) + Doomfire->AddThreat(Unit::GetUnit(*m_creature, (*itr)->getUnitGuid()), 1.0f); + Doomfire->setFaction(m_creature->getFaction()); + DoCast(Doomfire, SPELL_DOOMFIRE_SPAWN); + Doomfire->CastSpell(Doomfire, SPELL_DOOMFIRE_VISUAL, true); + if(target) + Doomfire->AI()->AttackStart(target); + + if(rand()%2 == 0) + { + DoYell(SAY_DOOMFIRE1, LANG_UNIVERSAL, m_creature); + DoPlaySoundToSet(m_creature, SOUND_DOOMFIRE1); + }else + { + DoYell(SAY_DOOMFIRE2, LANG_UNIVERSAL, m_creature); + DoPlaySoundToSet(m_creature, SOUND_DOOMFIRE2); + } + } + } + + void UnleashSoulCharge() + { + m_creature->InterruptNonMeleeSpells(false); + bool HasCast = false; + uint32 chargeSpell = 0; + uint32 unleashSpell = 0; + switch(rand()%3) + { + case 0: + chargeSpell = SPELL_SOUL_CHARGE_RED; + unleashSpell = SPELL_UNLEASH_SOUL_RED; + break; + case 1: + chargeSpell = SPELL_SOUL_CHARGE_YELLOW; + unleashSpell = SPELL_UNLEASH_SOUL_YELLOW; + break; + case 2: + chargeSpell = SPELL_SOUL_CHARGE_GREEN; + unleashSpell = SPELL_UNLEASH_SOUL_GREEN; + break; + } + if(m_creature->HasAura(chargeSpell, 0)) + { + m_creature->RemoveSingleAuraFromStack(chargeSpell, 0); + DoCast(m_creature->getVictim(), unleashSpell); + HasCast = true; + SoulChargeCount--; + } + if(HasCast) + SoulChargeTimer = 2000 + rand()%28000; + } + + void UpdateAI(const uint32 diff) + { + if(!InCombat) + { + if(pInstance) + { + // Do not let the raid skip straight to Archimonde. Visible and hostile ONLY if Azagalor is finished. + if((pInstance->GetData(DATA_AZGALOREVENT) < DONE) && ((m_creature->GetVisibility() != VISIBILITY_OFF) || (m_creature->getFaction() != 35))) + { + m_creature->SetVisibility(VISIBILITY_OFF); + m_creature->setFaction(35); + } + else if((pInstance->GetData(DATA_AZGALOREVENT) >= DONE) && ((m_creature->GetVisibility() != VISIBILITY_ON) || (m_creature->getFaction() == 35))) + { + m_creature->setFaction(1720); + m_creature->SetVisibility(VISIBILITY_ON); + } + } + + if(DrainNordrassilTimer < diff) + { + if(!IsChanneling) + { + Creature* Nordrassil = m_creature->SummonCreature(CREATURE_CHANNEL_TARGET, NORDRASSIL_X, NORDRASSIL_Y, NORDRASSIL_Z, 0, TEMPSUMMON_TIMED_DESPAWN, 1200000); + if(Nordrassil) + { + Nordrassil->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Nordrassil->SetUInt32Value(UNIT_FIELD_DISPLAYID, 11686); + DoCast(Nordrassil, SPELL_DRAIN_WORLD_TREE); + IsChanneling = true; + } + } + Creature* Nordrassil = m_creature->SummonCreature(CREATURE_CHANNEL_TARGET, NORDRASSIL_X, NORDRASSIL_Y, NORDRASSIL_Z, 0, TEMPSUMMON_TIMED_DESPAWN, 5000); + if(Nordrassil) + { + Nordrassil->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Nordrassil->SetUInt32Value(UNIT_FIELD_DISPLAYID, 11686); + Nordrassil->CastSpell(m_creature, SPELL_DRAIN_WORLD_TREE_2, true); + DrainNordrassilTimer = 1000; + } + }else DrainNordrassilTimer -= diff; + } + + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 10) && !BelowTenPercent && !Enraged) + BelowTenPercent = true; + + if(!Enraged) + { + if(EnrageTimer < diff) + { + if((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) > 10) + { + m_creature->GetMotionMaster()->Clear(false); + m_creature->GetMotionMaster()->MoveIdle(); + Enraged = true; + DoYell(SAY_ENRAGE, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_ENRAGE); + } + }else EnrageTimer -= diff; + + if(CheckDistanceTimer < diff) + { // To simplify the check, we simply summon a creature in the location and then check how far we are from the creature + Creature* Check = m_creature->SummonCreature(CREATURE_CHANNEL_TARGET, NORDRASSIL_X, NORDRASSIL_Y, NORDRASSIL_Z, 0, TEMPSUMMON_TIMED_DESPAWN, 2000); + if(Check) + { + Check->SetVisibility(VISIBILITY_OFF); + if(m_creature->IsWithinDistInMap(Check, 75)) + { + m_creature->GetMotionMaster()->Clear(false); + m_creature->GetMotionMaster()->MoveIdle(); + Enraged = true; + DoYell(SAY_ENRAGE, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_ENRAGE); + } + } + CheckDistanceTimer = 5000; + }else CheckDistanceTimer -= diff; + } + + if(BelowTenPercent) + { + if(!HasProtected) + { + m_creature->GetMotionMaster()->Clear(false); + m_creature->GetMotionMaster()->MoveIdle(); + DoCast(m_creature->getVictim(), SPELL_PROTECTION_OF_ELUNE); + HasProtected = true; + Enraged = true; + } + + if(SummonWispTimer < diff) + { + Creature* Wisp = DoSpawnCreature(CREATURE_ANCIENT_WISP, rand()%40, rand()%40, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if(Wisp) + { + Wisp->AI()->AttackStart(m_creature); + ((mob_ancient_wispAI*)Wisp->AI())->ArchimondeGUID = m_creature->GetGUID(); + } + SummonWispTimer = 1500; + ++WispCount; + }else SummonWispTimer -= diff; + + if(WispCount >= 30) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + if(Enraged) + { + if(HandOfDeathTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_HAND_OF_DEATH); + HandOfDeathTimer = 2000; + }else HandOfDeathTimer -= diff; + return; // Don't do anything after this point. + } + + if(SoulChargeCount) + { + if(SoulChargeTimer < diff) + UnleashSoulCharge(); + else SoulChargeTimer -= diff; + } + + if(GripOfTheLegionTimer < diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_GRIP_OF_THE_LEGION); + GripOfTheLegionTimer = 5000 + rand()%20000; + }else GripOfTheLegionTimer -= diff; + + if(AirBurstTimer < diff) + { + if(rand()%2 == 0) + { + DoYell(SAY_AIR_BURST, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AIR_BURST); + }else + { + DoYell(SAY_AIR_BURST2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AIR_BURST2); + } + + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_AIR_BURST); + AirBurstTimer = 25000 + rand()%15000; + }else AirBurstTimer -= diff; + + if(FearTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_FEAR); + FearTimer = 40000; + }else FearTimer -= diff; + + if(DoomfireTimer < diff) + { + SummonDoomfire(SelectUnit(SELECT_TARGET_RANDOM, 1)); + DoomfireTimer = 40000; + }else DoomfireTimer -= diff; + + if(MeleeRangeCheckTimer < diff) + { + if(CanUseFingerOfDeath()) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_FINGER_OF_DEATH); + MeleeRangeCheckTimer = 1000; + } + + MeleeRangeCheckTimer = 5000; + }else MeleeRangeCheckTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_archimonde(Creature *_Creature) +{ + return new boss_archimondeAI (_Creature); +} + +CreatureAI* GetAI_mob_doomfire(Creature* _Creature) +{ + return new mob_doomfireAI(_Creature); +} + +CreatureAI* GetAI_mob_doomfire_targetting(Creature* _Creature) +{ + return new mob_doomfire_targettingAI(_Creature); +} + +CreatureAI* GetAI_mob_ancient_wisp(Creature* _Creature) +{ + return new mob_ancient_wispAI(_Creature); +} + +void AddSC_boss_archimonde() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_archimonde"; + newscript->GetAI = GetAI_boss_archimonde; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name = "mob_doomfire"; + newscript->GetAI = GetAI_mob_doomfire; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name = "mob_doomfire_targetting"; + newscript->GetAI = GetAI_mob_doomfire_targetting; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name = "mob_ancient_wisp"; + newscript->GetAI = GetAI_mob_ancient_wisp; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/def_hyjal.h b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/def_hyjal.h new file mode 100644 index 00000000000..1e28156857f --- /dev/null +++ b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/def_hyjal.h @@ -0,0 +1,25 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_HYJAL_H +#define DEF_HYJAL_H + +#define DATA_ANETHERON 1 +#define DATA_ANETHERONEVENT 2 +#define DATA_ARCHIMONDE 3 +#define DATA_ARCHIMONDEEVENT 4 +#define DATA_AZGALOR 5 +#define DATA_AZGALOREVENT 6 +#define DATA_JAINAPROUDMOORE 7 +#define DATA_KAZROGAL 8 +#define DATA_KAZROGALEVENT 9 +#define DATA_RAGEWINTERCHILL 10 +#define DATA_RAGEWINTERCHILLEVENT 11 +#define DATA_THRALL 12 +#define DATA_TYRANDEWHISPERWIND 13 +#define DATA_TRASH 14 +#define DATA_RESET_TRASH_COUNT 15 + +#define ERROR_INST_DATA "SD2: Instance data not set properly for Mount Hyjal. Encounters will be buggy" +#endif diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjal.cpp b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjal.cpp new file mode 100644 index 00000000000..14dbdf62736 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjal.cpp @@ -0,0 +1,217 @@ +/* Copyright (C) 2006,2007 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Hyjal +SD%Complete: 100 +SDComment: +SDCategory: Caverns of Time, Mount Hyjal +EndScriptData */ + +/* ContentData +npc_jaina_proudmoore +npc_thrall +npc_tyrande_whisperwind +EndContentData */ + +#include "precompiled.h" +#include "hyjalAI.h" + +#define GOSSIP_ITEM_BEGIN_ALLY "We are ready to defend the Alliance base." +#define GOSSIP_ITEM_ANETHERON "The defenses are holding up; we can continue." +#define GOSSIP_ITEM_RETREAT "We can't keep this up. Let's retreat!" + +#define GOSSIP_ITEM_BEGIN_HORDE "We're here to help! The Alliance are overrun." +#define GOSSIP_ITEM_AZGALOR "We're okay so far. Let's do this!" + +CreatureAI* GetAI_npc_jaina_proudmoore(Creature *_Creature) +{ + hyjalAI* ai = new hyjalAI(_Creature); + + ai->Reset(); + ai->EnterEvadeMode(); + + ai->Spell[0].SpellId = SPELL_BLIZZARD; + ai->Spell[0].Cooldown = 15000 + rand()%20000; + ai->Spell[0].TargetType = TARGETTYPE_RANDOM; + + ai->Spell[1].SpellId = SPELL_PYROBLAST; + ai->Spell[1].Cooldown = 2000 + rand()%7000; + ai->Spell[1].TargetType = TARGETTYPE_RANDOM; + + ai->Spell[2].SpellId = SPELL_SUMMON_ELEMENTALS; + ai->Spell[2].Cooldown = 15000 + rand()%30000; + ai->Spell[2].TargetType = TARGETTYPE_SELF; + + return ai; +} + +bool GossipHello_npc_jaina_proudmoore(Player *player, Creature *_Creature) +{ + hyjalAI* ai = ((hyjalAI*)_Creature->AI()); + if(ai->EventBegun) + return false; + + uint32 RageEncounter = ai->GetInstanceData(DATA_RAGEWINTERCHILLEVENT); + uint32 AnetheronEncounter = ai->GetInstanceData(DATA_ANETHERONEVENT); + if(RageEncounter == NOT_STARTED) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_BEGIN_ALLY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + else if(RageEncounter == DONE && AnetheronEncounter == NOT_STARTED) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_ANETHERON, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + else if(RageEncounter == DONE && AnetheronEncounter == DONE) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_RETREAT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + + if(player->isGameMaster()) + player->ADD_GOSSIP_ITEM(2, "[GM] Toggle Debug Timers", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + + player->SEND_GOSSIP_MENU(907, _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_jaina_proudmoore(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + player->PlayerTalkClass->GetGossipMenu(); + hyjalAI* ai = ((hyjalAI*)_Creature->AI()); + switch(action) + { + case GOSSIP_ACTION_INFO_DEF + 1: + ai->StartEvent(player); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + ai->FirstBossDead = true; + ai->WaveCount = 9; + ai->StartEvent(player); + break; + case GOSSIP_ACTION_INFO_DEF + 3: + ai->Retreat(); + break; + case GOSSIP_ACTION_INFO_DEF + 4: + ai->Debug = !ai->Debug; + outstring_log("SD2 : HyjalAI - Debug mode has been toggled"); + break; + } + + return true; +} + +CreatureAI* GetAI_npc_thrall(Creature *_Creature) +{ + hyjalAI* ai = new hyjalAI(_Creature); + + ai->Reset(); + ai->EnterEvadeMode(); + + ai->Spell[0].SpellId = SPELL_CHAIN_LIGHTNING; + ai->Spell[0].Cooldown = 2000 + rand()%5000; + ai->Spell[0].TargetType = TARGETTYPE_VICTIM; + + ai->Spell[1].SpellId = SPELL_SUMMON_DIRE_WOLF; + ai->Spell[1].Cooldown = 6000 + rand()%35000; + ai->Spell[1].TargetType = TARGETTYPE_RANDOM; + + return ai; +} + +bool GossipHello_npc_thrall(Player *player, Creature *_Creature) +{ + hyjalAI* ai = ((hyjalAI*)_Creature->AI()); + uint32 AnetheronEvent = ai->GetInstanceData(DATA_ANETHERONEVENT); + if(AnetheronEvent >= DONE && !ai->EventBegun) // Only let them start the Horde phase if Anetheron is dead. + { + uint32 KazrogalEvent = ai->GetInstanceData(DATA_KAZROGALEVENT); + uint32 AzgalorEvent = ai->GetInstanceData(DATA_AZGALOREVENT); + if(KazrogalEvent == NOT_STARTED) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_BEGIN_HORDE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + else if(KazrogalEvent == DONE && AzgalorEvent == NOT_STARTED) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_AZGALOR, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + else if(AzgalorEvent == DONE) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_RETREAT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + } + + if(player->isGameMaster()) + player->ADD_GOSSIP_ITEM(2, "[GM] Toggle Debug Timers", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + + player->SEND_GOSSIP_MENU(907, _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_thrall(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + player->PlayerTalkClass->GetGossipMenu(); + hyjalAI* ai = ((hyjalAI*)_Creature->AI()); + switch(action) + { + case GOSSIP_ACTION_INFO_DEF + 1: + ai->StartEvent(player); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + ai->FirstBossDead = true; + ai->WaveCount = 9; + ai->StartEvent(player); + break; + case GOSSIP_ACTION_INFO_DEF + 3: + ai->Retreat(); + break; + case GOSSIP_ACTION_INFO_DEF + 4: + ai->Debug = !ai->Debug; + outstring_log("SD2 : HyjalAI - Debug mode has been toggled"); + break; + } + + return true; +} + +bool GossipHello_npc_tyrande_whisperwind(Player* player, Creature* _Creature) +{ + player->ADD_GOSSIP_ITEM(1, "Aid us in defending Nordrassil", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + player->SEND_GOSSIP_MENU(907, _Creature->GetGUID()); + return true; +} + +bool GossipSelect_npc_tyrande_whisperwind(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + if(action == GOSSIP_ACTION_TRADE) + player->SEND_VENDORLIST( _Creature->GetGUID() ); + + return true; +} + +void AddSC_hyjal() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_jaina_proudmoore"; + newscript->GetAI = GetAI_npc_jaina_proudmoore; + newscript->pGossipHello = &GossipHello_npc_jaina_proudmoore; + newscript->pGossipSelect = &GossipSelect_npc_jaina_proudmoore; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name = "npc_thrall"; + newscript->GetAI = GetAI_npc_thrall; + newscript->pGossipHello = &GossipHello_npc_thrall; + newscript->pGossipSelect = &GossipSelect_npc_thrall; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name = "npc_tyrande_whisperwind"; + newscript->pGossipHello = &GossipHello_npc_tyrande_whisperwind; + newscript->pGossipSelect = &GossipSelect_npc_tyrande_whisperwind; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjalAI.cpp b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjalAI.cpp new file mode 100644 index 00000000000..0d18f0d9244 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjalAI.cpp @@ -0,0 +1,458 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: HyjalAI +SD%Complete: 99 +SDComment: World Packet workaround for World States +SDCategory: Caverns of Time, Mount Hyjal +EndScriptData */ + +#include "precompiled.h" +#include "hyjalAI.h" +#include "WorldPacket.h" + +float AllianceBase[4][3]= // Locations for summoning waves in Alliance base +{ + {4979.010, -1709.134, 1339.674}, + {4969.123, -1705.904, 1341.363}, + {4970.260, -1698.546, 1341.200}, + {4975.262, -1698.239, 1341.427} +}; + +float HordeBase[4][3]= // Locations for summoning waves in Horde base +{ + {5554.399, -2581.419, 1480.820}, + {5538.996, -2577.742, 1479.790}, + {5565.642, -2565.666, 1481.635}, + {5547.218, -2574.589, 1479.194} +}; + +float AttackArea[2][3]= // used to inform the wave where to move and attack to +{ + { // Alliance + 5042.9189, -1776.2562, 1323.0621 + }, + { // Horde + 5510.4815, -2676.7112, 1480.4314 + } +}; + +hyjalAI::hyjalAI(Creature *c) : ScriptedAI(c) +{ + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); +} + +void hyjalAI::Reset() +{ + /** GUIDs **/ + PlayerGUID = 0; + BossGUID[0] = 0; + BossGUID[1] = 0; + + /** Timers **/ + NextWaveTimer = 10000; + CheckTimer = 0; + RetreatTimer = 1000; + + /** Misc **/ + WaveCount = 0; + + /** Set faction properly based on creature entry**/ + switch(m_creature->GetEntry()) + { + case 17772: + Faction = 0; + DoCast(m_creature, SPELL_BRILLIANCE_AURA, true); + break; + + case 17852: Faction = 1; break; + } + + /** Bools **/ + EventBegun = false; + FirstBossDead = false; + SecondBossDead = false; + Summon = false; + bRetreat = false; + + /** Flags **/ + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + + /** Initialize spells **/ + memset(Spell, 0, sizeof(Spell)); + + /** Reset World States **/ + UpdateWorldState(WORLDSTATE_WAVES, 0); + UpdateWorldState(WORLDSTATE_ENEMY, 0); + UpdateWorldState(WORLDSTATE_ENEMYCOUNT, 0); + + /** Reset Instance Data for trash count **/ + if(pInstance) + pInstance->SetData(DATA_RESET_TRASH_COUNT, 0); + else error_log(ERROR_INST_DATA); + + /*** Visibility ***/ + m_creature->SetVisibility(VISIBILITY_ON); + + /** If Jaina evades, reset the visibility of all other creatures in the grid. **/ + if(CreatureList.empty()) + return; + + for(std::list::iterator itr = CreatureList.begin(); itr != CreatureList.end(); ++itr) + if(Creature* cr = ((Creature*)Unit::GetUnit(*m_creature, *itr))) + cr->SetVisibility(VISIBILITY_ON); + + CreatureList.clear(); +} + +void hyjalAI::EnterEvadeMode() +{ + m_creature->InterruptNonMeleeSpells(true); + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); + m_creature->CombatStop(); + m_creature->LoadCreaturesAddon(); + + if(m_creature->isAlive()) + m_creature->GetMotionMaster()->MoveTargetedHome(); + + InCombat = false; +} + +void hyjalAI::Aggro(Unit *who) +{ + for(uint8 i = 0; i < 2; ++i) + if(Spell[i].Cooldown) + SpellTimer[i] = Spell[i].Cooldown; + + Talk(ATTACKED); +} + +void hyjalAI::SummonCreature(uint32 entry, float Base[4][3]) +{ + uint32 random = rand()%4; + float SpawnLoc[3]; + float AttackLoc[3]; + + for(uint8 i = 0; i < 3; ++i) + { + SpawnLoc[i] = Base[random][i]; + AttackLoc[i] = AttackArea[Faction][i]; + } + + Creature* pCreature = m_creature->SummonCreature(entry, SpawnLoc[0], SpawnLoc[1], SpawnLoc[2], 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); + if(pCreature) + { + ++EnemyCount; // Increment Enemy Count to be used in World States and instance script + + pCreature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pCreature->GetMotionMaster()->MovePoint(0, AttackLoc[0],AttackLoc[1],AttackLoc[2]); + pCreature->AddThreat(m_creature, 1.0f); + DoZoneInCombat(pCreature); + + // Check if creature is a boss. + if(pCreature->GetCreatureInfo()->rank == 3) + { + if(!FirstBossDead) BossGUID[0] = pCreature->GetGUID(); + else BossGUID[1] = pCreature->GetGUID(); + CheckTimer = 5000; + } + } +} + +void hyjalAI::SummonNextWave(Wave wave[18], uint32 Count, float Base[4][3]) +{ + if(rand()%4 == 0) // 1 in 4 chance we give a rally yell. Not sure if the chance is Blizzlike. + Talk(RALLY); + + if(!pInstance) + { + error_log(ERROR_INST_DATA); + return; + } + + EnemyCount = pInstance->GetData(DATA_TRASH); + for(uint8 i = 0; i < 18; ++i) + { + if(wave[Count].Mob[i]) + SummonCreature(wave[Count].Mob[i], Base); + } + + if(!wave[Count].IsBoss) + { + uint32 stateValue = Count+1; + if(FirstBossDead) + stateValue -= 9; // Subtract 9 from it to give the proper wave number if we are greater than 8 + UpdateWorldState(WORLDSTATE_WAVES, stateValue); // Set world state to our current wave number + UpdateWorldState(WORLDSTATE_ENEMY, 1); + //UpdateWorldState(WORLDSTATE_ENEMYCOUNT, EnemyCount); // Let Instance Script handle this + pInstance->SetData(DATA_TRASH, EnemyCount); + if(!Debug) + NextWaveTimer = wave[Count].WaveTimer; + else + { + NextWaveTimer = 15000; + DoTextEmote(": Debug Mode is enabled. Next Wave in 15 seconds", NULL); + } + } + else + { + UpdateWorldState(WORLDSTATE_WAVES, 0); // Set world state for waves to 0 to disable it. + UpdateWorldState(WORLDSTATE_ENEMYCOUNT, 1); // Set World State for enemies invading to 1. + Summon = false; + } + CheckTimer = 5000; +} + +void hyjalAI::StartEvent(Player* player) +{ + if(!player) + return; + + Talk(BEGIN); + + EventBegun = true; + Summon = true; + + NextWaveTimer = 15000; + CheckTimer = 5000; + PlayerGUID = player->GetGUID(); + + m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + + UpdateWorldState(WORLDSTATE_WAVES, 0); + UpdateWorldState(WORLDSTATE_ENEMY, 0); + UpdateWorldState(WORLDSTATE_ENEMYCOUNT, 0); +} + +uint32 hyjalAI::GetInstanceData(uint32 Event) +{ + if(pInstance) + return pInstance->GetData(Event); + else error_log(ERROR_INST_DATA); + + return 0; +} + +void hyjalAI::Talk(uint32 id) +{ + std::list index; + for(uint8 i = 0; i < 10; i++) + { + if(Faction == 0) // Alliance + { + if(JainaQuotes[i].id == id) + index.push_back(i); + } + else if(Faction == 1) // Horde + { + if(ThrallQuotes[i].id == id) + index.push_back(i); + } + } + + if(index.empty()) + return; // No quotes found, no use to continue + + uint8 ind = *(index.begin()) + rand()%index.size(); + + char* Yell = NULL; + uint32 Sound = 0; + if(Faction == 0) // Alliance + { + Yell = JainaQuotes[ind].text; + Sound = JainaQuotes[ind].sound; + } + else if(Faction == 1) // Horde + { + Yell = ThrallQuotes[ind].text; + Sound = ThrallQuotes[ind].sound; + } + + if(Yell) + DoYell(Yell, LANG_UNIVERSAL, NULL); + if(Sound) + DoPlaySoundToSet(m_creature, Sound); +} + +// Slight workaround for now +void hyjalAI::UpdateWorldState(uint32 field, uint32 value) +{ + Map * map = m_creature->GetMap(); + if(!map->IsDungeon()) return; + + WorldPacket data(SMSG_UPDATE_WORLD_STATE, 8); + + data << field; + data << value; + + ((InstanceMap*)map)->SendToPlayers(&data); + + // TODO: Uncomment and remove everything above this line only when the core patch for this is accepted + //m_creature->GetMap()->UpdateWorldState(field, value); +} + +void hyjalAI::Retreat() +{ + CellPair pair(MaNGOS::ComputeCellPair(m_creature->GetPositionX(), m_creature->GetPositionY())); + Cell cell(pair); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + // First get all creatures. + std::list creatures; + AllFriendlyCreaturesInGrid creature_check(m_creature); + MaNGOS::CreatureListSearcher creature_searcher(creatures, creature_check); + TypeContainerVisitor + , + GridTypeMapContainer> creature_visitor(creature_searcher); + + // Then get all Ancient Gem Veins. NOTE: Grid Search will only be able to find those in the grid. + std::list goList; + AllGameObjectsWithEntryInGrid go_check(185557); + MaNGOS::GameObjectListSearcher go_search(goList, go_check); + TypeContainerVisitor + , GridTypeMapContainer> go_visit(go_search); + + CellLock cell_lock(cell, pair); + // Get Creatures + cell_lock->Visit(cell_lock, creature_visitor, *(m_creature->GetMap())); + // Get GOs + cell_lock->Visit(cell_lock, go_visit, *(m_creature->GetMap())); + + CreatureList.clear(); + if(!creatures.empty()) + { + for(std::list::iterator itr = creatures.begin(); itr != creatures.end(); ++itr) + { + (*itr)->CastSpell(*itr, SPELL_TELEPORT_VISUAL, true); + CreatureList.push_back((*itr)->GetGUID()); + } + + DoCast(m_creature, SPELL_TELEPORT_VISUAL); + bRetreat = true; + RetreatTimer = 1000; + } + + if(!goList.empty()) + { + for(std::list::iterator itr = goList.begin(); itr != goList.end(); ++itr) + (*itr)->SetRespawnTime(5000); + } +} + +void hyjalAI::UpdateAI(const uint32 diff) +{ + if(bRetreat) + if(RetreatTimer < diff) + { + bRetreat = false; + if(CreatureList.empty()) + return; + + for(std::list::iterator itr = CreatureList.begin(); itr != CreatureList.end(); ++itr) + if(Unit* pUnit = Unit::GetUnit(*m_creature, *itr)) + pUnit->SetVisibility(VISIBILITY_OFF); + + m_creature->SetVisibility(VISIBILITY_OFF); + }else RetreatTimer -= diff; + + if(!EventBegun) + return; + + if(Summon) + { + if(pInstance && EnemyCount) + { + EnemyCount = pInstance->GetData(DATA_TRASH); + if(!EnemyCount) + NextWaveTimer = 5000; + } + + if(NextWaveTimer < diff) + { + if(Faction == 0) + SummonNextWave(AllianceWaves, WaveCount, AllianceBase); + else if(Faction == 1) + SummonNextWave(HordeWaves, WaveCount, HordeBase); + ++WaveCount; + }else NextWaveTimer -= diff; + } + + if(CheckTimer < diff) + { + for(uint8 i = 0; i < 2; ++i) + { + if(BossGUID[i]) + { + Unit* pUnit = Unit::GetUnit((*m_creature), BossGUID[i]); + if(pUnit && (!pUnit->isAlive())) + { + if(BossGUID[i] == BossGUID[0]) + { + Talk(INCOMING); + FirstBossDead = true; + } + else if(BossGUID[i] == BossGUID[1]) + { + Talk(SUCCESS); + SecondBossDead = true; + } + EventBegun = false; + CheckTimer = 0; + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + BossGUID[i] = 0; + UpdateWorldState(WORLDSTATE_ENEMY, 0); // Reset world state for enemies to disable it + } + } + } + CheckTimer = 5000; + }else CheckTimer -= diff; + + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + for(uint8 i = 0; i < 3; ++i) + { + if(Spell[i].SpellId) + { + if(SpellTimer[i] < diff) + { + if(m_creature->IsNonMeleeSpellCasted(false)) + m_creature->InterruptNonMeleeSpells(false); + + Unit* target = NULL; + + switch(Spell[i].TargetType) + { + case TARGETTYPE_SELF: target = m_creature; break; + case TARGETTYPE_RANDOM: target = SelectUnit(SELECT_TARGET_RANDOM, 0); break; + case TARGETTYPE_VICTIM: target = m_creature->getVictim(); break; + } + + if(target && target->isAlive()) + { + DoCast(target, Spell[i].SpellId); + SpellTimer[i] = Spell[i].Cooldown; + } + }else SpellTimer[i] -= diff; + } + } + + DoMeleeAttackIfReady(); +} diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjalAI.h b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjalAI.h new file mode 100644 index 00000000000..46be6a83879 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjalAI.h @@ -0,0 +1,286 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef SC_HYJALAI_H +#define SC_HYJALAI_H + +#include "def_hyjal.h" + +// Trash Mobs summoned in waves +#define NECROMANCER 17899 +#define ABOMINATION 17898 +#define GHOUL 17895 +#define BANSHEE 17905 +#define CRYPT_FIEND 17897 +#define GARGOYLE 17906 +#define FROST_WYRM 17907 +#define GIANT_INFERNAL 17908 +#define FEL_STALKER 17916 + +// Bosses summoned after every 8 waves +#define RAGE_WINTERCHILL 17767 +#define ANETHERON 17808 +#define KAZROGAL 17888 +#define AZGALOR 17842 +#define ARCHIMONDE 17968 + +#define SPELL_TELEPORT_VISUAL 41232 + +#define WORLDSTATE_WAVES 2842 +#define WORLDSTATE_ENEMY 2453 +#define WORLDSTATE_ENEMYCOUNT 2454 + +/*** Spells for Jaina ***/ +#define SPELL_BRILLIANCE_AURA 31260 // The database must handle this spell via creature_addon +#define SPELL_BLIZZARD 31266 +#define SPELL_PYROBLAST 31263 +#define SPELL_SUMMON_ELEMENTALS 31264 + +/** Thrall spells **/ +#define SPELL_CHAIN_LIGHTNING 31330 +#define SPELL_SUMMON_DIRE_WOLF 31331 + +struct Wave +{ + uint32 Mob[18]; // Stores Creature Entries to be summoned in Waves + uint32 WaveTimer; // The timer before the next wave is summoned + bool IsBoss; // Simply used to inform the wave summoner that the next wave contains a boss to halt all waves after that +}; + +static Wave AllianceWaves[]= // Waves that will be summoned in the Alliance Base +{ + { // Wave 1 + GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, 0, 0, 0, 0, 0, 0, 0, 0, 120000, false + }, + { // Wave 2 + GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, 0, 0, 0, 0, 0, 0, 120000, false + }, + { // Wave 3 + GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, 0, 0, 0, 0, 0, 0, 120000, false + }, + { // Wave 4 + GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false + }, + { // Wave 5 + GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false + }, + { // Wave 6 + GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 120000, false + }, + { // Wave 7 + GHOUL, GHOUL, GHOUL, GHOUL, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 0, 120000, false + }, + { // Wave 8 + GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false + }, + { // All 8 Waves are summoned, summon Rage Winterchill, next few waves are for Anetheron + RAGE_WINTERCHILL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true + }, + { // Wave 1 + GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, 0, 0, 0, 0, 0, 0, 0, 0, 120000, false + }, + { // Wave 2 + GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 0, 120000, false + }, + { // Wave 3 + GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false + }, + { // Wave 4 + GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, BANSHEE, BANSHEE, BANSHEE, BANSHEE, 0, 0, 0, 0, 0, 0, 120000, false + }, + { // Wave 5 + CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, BANSHEE, BANSHEE, BANSHEE, BANSHEE, 0, 0, 0, 0, 0, 0, 120000, false + }, + { // Wave 6 + GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false + }, + { // Wave 7 + CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, BANSHEE, BANSHEE, BANSHEE, BANSHEE, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 0, 120000, false + }, + { // Wave 8 + GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false + }, + { // All 8 Waves are summoned, summon Anatheron + ANETHERON, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true + } +}; + +static Wave HordeWaves[]= // Waves that are summoned in the Horde base +{ + { // Wave 1 + GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false + }, + { // Wave 2 + GHOUL, GHOUL, GHOUL, GHOUL, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, 0, 0, 0, 0, 120000, false + }, + { // Wave 3 + GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 120000, false + }, + { // Wave 4 + CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, NECROMANCER, NECROMANCER , 0, 0, 0, 0, 120000, false + }, + { // Wave 5 + GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false + }, + { // Wave 6 + GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, FROST_WYRM, 0, 0, 120000, false + }, + { // Wave 7 + GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, FROST_WYRM, 0, 0, 120000, false + }, + { // Wave 8 + GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, BANSHEE, BANSHEE, 180000, false + }, + { // All 8 Waves are summoned, summon Kaz'Rogal, next few waves are for Azgalor + KAZROGAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true + }, + { // Wave 1 + ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false + }, + { // Wave 2 + GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, FROST_WYRM, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, 0, 0, 0, 0, 120000, false + }, + { // Wave 3 + GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, 0, 0, 0, 0, 120000, false + }, + { // Wave 4 + GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, 0, 0, 0, 0, 120000, false + }, + { // Wave 5 + FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 120000, false + }, + { // Wave 6 + NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, BANSHEE, BANSHEE, BANSHEE, BANSHEE, BANSHEE, BANSHEE, 0, 0, 0, 0, 120000, false + }, + { // Wave 7 + GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, FEL_STALKER, FEL_STALKER, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, 0, 0, 0, 0, 0, 0, 120000, false + }, + { // Wave 8 + CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, FEL_STALKER, FEL_STALKER, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, BANSHEE, BANSHEE, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0, 180000, false + }, + { // All 8 Waves are summoned, summon Azgalor + AZGALOR, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true + } +}; + +enum TargetType // Used in the spell cast system for the AI +{ + TARGETTYPE_SELF = 0, + TARGETTYPE_RANDOM = 1, + TARGETTYPE_VICTIM = 2, +}; + +struct Yells +{ + uint32 id; // Used to determine the type of yell (attack, rally, etc) + char* text; // The text to be yelled + uint32 sound; // Sound that corresponds to the text +}; + +enum YellId +{ + ATTACKED = 0, // Used when attacked and set in combat + BEGIN = 1, // Used when the event is begun + INCOMING = 2, // Used to warn the raid that another wave phase is coming + RALLY = 3, // Used to rally the raid and warn that the next wave has been summoned + FAILURE = 4, // Used when raid has failed (unsure where to place) + SUCCESS = 5, // Used when the raid has sucessfully defeated a wave phase + DEATH = 6, // Used on death +}; + +static Yells JainaQuotes[]= +{ + {ATTACKED, "I'm in jeopardy, help me if you can!", 11007}, + {ATTACKED, "They've broken through!", 11049}, + {INCOMING, "Stay alert! Another wave approaches.", 11008}, + {BEGIN, "Hold them back as long as possible", 11050}, + {RALLY, "Don't give up! We must prevail!", 11006}, + {RALLY, "We must hold strong!", 11051}, + {FAILURE, "We are lost. Fall back!", 11009}, + {SUCCESS, "We have won valuable time. Now we must pull back!", 11011}, + {DEATH, "I did... my best.", 11010}, +}; + +static Yells ThrallQuotes[]= +{ + {ATTACKED, "I will lie down for no one!", 11031}, + {ATTACKED, "Bring the fight to me and pay with your lives!", 11061}, + {INCOMING, "Make ready for another wave! LOK-TAR OGAR!", 11032}, + {BEGIN, "Do not give an inch of ground!", 11060}, + {RALLY, "Hold them back! Do not falter!", 11030}, + {RALLY, "Victory or death!", 11059}, + {RALLY, "Do not give an inch of ground!", 11060}, + {FAILURE, "It is over. Withdraw! We have failed.", 11033}, + {SUCCESS, "We have played our part and done well. It is up to the others now.", 11035}, + {DEATH, "Uraaa...", 11034}, +}; + +struct MANGOS_DLL_DECL hyjalAI : public ScriptedAI +{ + hyjalAI(Creature *c); + + void Reset(); // Generically used to reset our variables. Do *not* call in EnterEvadeMode as this may make problems if the raid is still in combat + + void EnterEvadeMode(); // Send creature back to spawn location and evade. + + void Aggro(Unit *who); // Used to reset cooldowns for our spells and to inform the raid that we're under attack + + void UpdateAI(const uint32 diff); // Called to summon waves, check for boss deaths and to cast our spells. + + void JustDied(Unit* killer) // Called on death, informs the raid that they have failed. + { + Talk(DEATH); + } + + void SetFaction(uint32 _faction) // Set the faction to either Alliance or Horde in Hyjal + { + Faction = _faction; + } + + void Retreat(); // "Teleport" (teleport visual + set invisible) all friendly creatures away from the base. + + void SummonCreature(uint32 entry, float Base[4][3]); // Summons a creature for that wave in that base + + // Summons the next wave, calls SummonCreature + void SummonNextWave(Wave wave[18], uint32 Count, float Base[4][3]); + + void StartEvent(Player* player); // Begins the event by gossip click + + uint32 GetInstanceData(uint32 Event); // Gets instance data for this instance, used to check if raid has gotten past a certain point and can access the next phase + + void Talk(uint32 id); // Searches for the appropriate yell and sound and uses it to inform the raid of various things + + void UpdateWorldState(uint32 field, uint32 value); // NYI: Requires core support. Updates the world state counter at the top of the UI. + public: + ScriptedInstance* pInstance; + + uint64 PlayerGUID; + uint64 BossGUID[2]; + + uint32 NextWaveTimer; + uint32 WaveCount; + uint32 CheckTimer; + uint32 Faction; + uint32 EnemyCount; + uint32 RetreatTimer; + + bool EventBegun; + bool FirstBossDead; + bool SecondBossDead; + bool Summon; + bool bRetreat; + bool Debug; + + struct Spell + { + uint32 SpellId; + uint32 Cooldown; + uint32 TargetType; + }Spell[3]; + + private: + uint32 SpellTimer[3]; + std::list CreatureList; +}; +#endif diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/instance_hyjal.cpp b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/instance_hyjal.cpp new file mode 100644 index 00000000000..796069ba81f --- /dev/null +++ b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/instance_hyjal.cpp @@ -0,0 +1,203 @@ +/* Copyright (C) 2006,2007 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Mount_Hyjal +SD%Complete: 100 +SDComment: Instance Data Scripts and functions to acquire mobs and set encounter status for use in various Hyjal Scripts +SDCategory: Caverns of Time, Mount Hyjal +EndScriptData */ + +#include "precompiled.h" +#include "def_hyjal.h" +#include "WorldPacket.h" + +#define ENCOUNTERS 5 + +/* Battle of Mount Hyjal encounters: +0 - Rage Winterchill event +1 - Anetheron event +2 - Kaz'rogal event +3 - Azgalor event +4 - Archimonde event +*/ + +struct MANGOS_DLL_DECL instance_mount_hyjal : public ScriptedInstance +{ + instance_mount_hyjal(Map *Map) : ScriptedInstance(Map) {Initialize();}; + + uint64 RageWinterchill; + uint64 Anetheron; + uint64 Kazrogal; + uint64 Azgalor; + uint64 Archimonde; + uint64 JainaProudmoore; + uint64 Thrall; + uint64 TyrandeWhisperwind; + + uint32 Trash; + uint32 Encounters[ENCOUNTERS]; + + void Initialize() + { + RageWinterchill = 0; + Anetheron = 0; + Kazrogal = 0; + Azgalor = 0; + Archimonde = 0; + JainaProudmoore = 0; + Thrall = 0; + TyrandeWhisperwind = 0; + + Trash = 0; + for(uint8 i = 0; i < ENCOUNTERS; ++i) + Encounters[i] = NOT_STARTED; + } + + bool IsEncounterInProgress() const + { + for(uint8 i = 0; i < ENCOUNTERS; ++i) + if(Encounters[i] == IN_PROGRESS) return true; + + return false; + } + + void OnCreatureCreate(Creature *creature, uint32 creature_entry) + { + switch(creature_entry) + { + case 17767: RageWinterchill = creature->GetGUID(); break; + case 17808: Anetheron = creature->GetGUID(); break; + case 17888: Kazrogal = creature->GetGUID(); break; + case 17842: Azgalor = creature->GetGUID(); break; + case 17968: Archimonde = creature->GetGUID(); break; + case 17772: JainaProudmoore = creature->GetGUID(); break; + case 17852: Thrall = creature->GetGUID(); break; + case 17948: TyrandeWhisperwind = creature->GetGUID(); break; + } + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_RAGEWINTERCHILL: return RageWinterchill; + case DATA_ANETHERON: return Anetheron; + case DATA_KAZROGAL: return Kazrogal; + case DATA_AZGALOR: return Azgalor; + case DATA_ARCHIMONDE: return Archimonde; + case DATA_JAINAPROUDMOORE: return JainaProudmoore; + case DATA_THRALL: return Thrall; + case DATA_TYRANDEWHISPERWIND: return TyrandeWhisperwind; + } + + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_RAGEWINTERCHILLEVENT: Encounters[0] = data; break; + case DATA_ANETHERONEVENT: Encounters[1] = data; break; + case DATA_KAZROGALEVENT: Encounters[2] = data; break; + case DATA_AZGALOREVENT: Encounters[3] = data; break; + case DATA_ARCHIMONDEEVENT: Encounters[4] = data; break; + case DATA_RESET_TRASH_COUNT: Trash = 0; break; + + case DATA_TRASH: + if(data) Trash = data; + else Trash--; + UpdateWorldState(2453, data); + break; + } + + if(data == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_RAGEWINTERCHILLEVENT: return Encounters[0]; + case DATA_ANETHERONEVENT: return Encounters[1]; + case DATA_KAZROGALEVENT: return Encounters[2]; + case DATA_AZGALOREVENT: return Encounters[3]; + case DATA_ARCHIMONDEEVENT: return Encounters[4]; + case DATA_TRASH: return Trash; + } + return 0; + } + + void UpdateWorldState(uint32 field, uint32 value) + { + WorldPacket data(SMSG_UPDATE_WORLD_STATE, 8); + data << field; + data << value; + + ((InstanceMap*)instance)->SendToPlayers(&data); + } + + const char* Save() + { + OUT_SAVE_INST_DATA; + std::ostringstream stream; + stream << Encounters[0] << " " << Encounters[1] << " " + << Encounters[2] << " " << Encounters[3] << " " + << Encounters[4]; + char* out = new char[stream.str().length() + 1]; + strcpy(out, stream.str().c_str()); + if(out) + { + OUT_SAVE_INST_DATA_COMPLETE; + return out; + } + + return NULL; + } + + void Load(const char* load) + { + if(!load) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(load); + std::istringstream stream; + stream >> Encounters[1] >> Encounters[2] >> Encounters[3] >> Encounters[4]; + for(uint8 i = 0; i < ENCOUNTERS; ++i) + if(Encounters[i] == IN_PROGRESS) // Do not load an encounter as IN_PROGRESS - reset it instead. + Encounters[i] = NOT_STARTED; + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_mount_hyjal(Map* map) +{ + return new instance_mount_hyjal(map); +} + +void AddSC_instance_mount_hyjal() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_hyjal"; + newscript->GetInstanceData = GetInstanceData_instance_mount_hyjal; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/old_hillsbrad/boss_captain_skarloc.cpp b/src/bindings/scripts/scripts/zone/caverns_of_time/old_hillsbrad/boss_captain_skarloc.cpp new file mode 100644 index 00000000000..2dbb79b02a1 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/caverns_of_time/old_hillsbrad/boss_captain_skarloc.cpp @@ -0,0 +1,177 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Captain_Skarloc +SD%Complete: 75 +SDComment: Missing adds, missing waypoints to move up to Thrall once spawned + speech before enter combat. +SDCategory: Caverns of Time, Old Hillsbrad Foothills +EndScriptData */ + +#include "precompiled.h" +#include "def_old_hillsbrad.h" + +#define HOLY_LIGHT 29562 +#define CLEANSE 39078 +#define HAMMER_OF_JUSTICE 13005 +#define HOLY_SHIELD 31904 +#define DEVOTION_AURA 41452 +#define CONSECRATION 41541 + +#define SAY_ENTER "Thrall! You didn't really think you would escape did you? You and your allies shall answer to Blackmoore - after I've had my fun!" +#define SAY_AGGRO1 "You're a slave. That's all you'll ever be.'" +#define SAY_AGGRO2 "I don't know what Blackmoore sees in you. For my money, you're just another ignorant savage!" +#define SAY_SLAY1 "Thrall will never be free!" +#define SAY_SLAY2 "Did you really think you would leave here alive?" +#define SAY_DEATH "Guards! Urgh..Guards..!'" + +#define SOUND_ENTER 10406 +#define SOUND_AGGRO1 10407 +#define SOUND_AGGRO2 10408 +#define SOUND_SLAY1 10409 +#define SOUND_SLAY2 10410 +#define SOUND_DEATH 10411 + +struct MANGOS_DLL_DECL boss_captain_skarlocAI : public ScriptedAI +{ + boss_captain_skarlocAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance *pInstance; + + uint32 Holy_Light_Timer; + uint32 Cleanse_Timer; + uint32 HammerOfJustice_Timer; + uint32 HolyShield_Timer; + uint32 DevotionAura_Timer; + uint32 Consecration_Timer; + + void Reset() + { + Holy_Light_Timer = 30000; + Cleanse_Timer = 10000; + HammerOfJustice_Timer = 60000; + HolyShield_Timer = 240000; + DevotionAura_Timer = 60000; + Consecration_Timer = 8000; + } + + void Aggro(Unit *who) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_AGGRO1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO1); + break; + case 1: + DoYell(SAY_AGGRO2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO2); + break; + } + } + + void KilledUnit(Unit *victim) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_SLAY1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY1); + break; + case 1: + DoYell(SAY_SLAY2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY2); + break; + } + } + + void JustDied(Unit *victim) + { + DoYell(SAY_DEATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_DEATH); + if( pInstance && pInstance->GetData(TYPE_THRALL_EVENT) == IN_PROGRESS ) + pInstance->SetData(TYPE_THRALL_PART1, DONE); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //Holy_Light + if (Holy_Light_Timer < diff) + { + DoCast(m_creature, HOLY_LIGHT); + Holy_Light_Timer = 30000; + }else Holy_Light_Timer -= diff; + + //Cleanse + if(Cleanse_Timer < diff) + { + DoCast(m_creature, CLEANSE); + Cleanse_Timer = 10000 ; + } else Cleanse_Timer -= diff; + + //Hammer of Justice + if (HammerOfJustice_Timer < diff) + { + DoCast(m_creature->getVictim(), HAMMER_OF_JUSTICE); + HammerOfJustice_Timer = 60000; + }else HammerOfJustice_Timer -= diff; + + //Holy Shield + if (HolyShield_Timer < diff) + { + DoCast(m_creature,HOLY_SHIELD); + HolyShield_Timer = 240000; + }else HolyShield_Timer -= diff; + + //Devotion_Aura + if (DevotionAura_Timer < diff) + { + DoCast(m_creature,DEVOTION_AURA); + DevotionAura_Timer = 60000; + }else DevotionAura_Timer -= diff; + + //Consecration + if (Consecration_Timer < diff) + { + //DoCast(m_creature->getVictim(),CONSECRATION); + Consecration_Timer = 8000; + }else Consecration_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_captain_skarloc(Creature *_Creature) +{ + return new boss_captain_skarlocAI (_Creature); +} + +void AddSC_boss_captain_skarloc() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_captain_skarloc"; + newscript->GetAI = GetAI_boss_captain_skarloc; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/old_hillsbrad/boss_epoch_hunter.cpp b/src/bindings/scripts/scripts/zone/caverns_of_time/old_hillsbrad/boss_epoch_hunter.cpp new file mode 100644 index 00000000000..bbcaec53407 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/caverns_of_time/old_hillsbrad/boss_epoch_hunter.cpp @@ -0,0 +1,183 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Epoch_Hunter +SD%Complete: 60 +SDComment: Missing spawns pre-event, missing speech to be coordinated with rest of escort event. +SDCategory: Caverns of Time, Old Hillsbrad Foothills +EndScriptData */ + +#include "precompiled.h" +#include "def_old_hillsbrad.h" + +#define SAY_ENTER1 "Thrall! Come outside and face your fate!" +#define SOUND_ENTER1 10418 +#define SAY_ENTER2 "Taretha's life hangs in the balance. Surely you care for her. Surely you wish to save her..." +#define SOUND_ENTER2 10419 +#define SAY_ENTER3 "Ah, there you are. I had hoped to accomplish this with a bit of subtlety, but I suppose direct confrontation was inevitable. Your future, Thrall, must not come to pass and so...you and your troublesome friends must die!" +#define SOUND_ENTER3 10420 + +#define SAY_AGGRO1 "Enough! I will erase your very existence!" +#define SOUND_AGGRO1 10421 +#define SAY_AGGRO2 "You cannot fight fate!" +#define SOUND_AGGRO2 10422 + +#define SAY_SLAY1 "You are...irrelevant." +#define SOUND_SLAY1 10425 +#define SAY_SLAY2 "Thrall will remain a slave. Taretha will die. You have failed." +#define SOUND_SLAY2 10426 + +#define SAY_BREATH1 "Not so fast!" +#define SOUND_BREATH1 10423 +#define SAY_BREATH2 "Struggle as much as you like!" +#define SOUND_BREATH2 10424 + +#define SAY_DEATH "No!...The master... will not... be pleased." +#define SOUND_DEATH 10427 + +#define SPELL_SAND_BREATH 31914 +#define SPELL_IMPENDING_DEATH 31916 +#define SPELL_MAGIC_DISRUPTION_AURA 33834 +#define SPELL_WING_BUFFET 31475 + +struct MANGOS_DLL_DECL boss_epoch_hunterAI : public ScriptedAI +{ + boss_epoch_hunterAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance *pInstance; + + uint32 SandBreath_Timer; + uint32 ImpendingDeath_Timer; + uint32 WingBuffet_Timer; + uint32 Mda_Timer; + + void Reset() + { + SandBreath_Timer = 25000; + ImpendingDeath_Timer = 30000; + WingBuffet_Timer = 35000; + Mda_Timer = 40000; + } + + void Aggro(Unit *who) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_AGGRO1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO1); + break; + case 1: + DoYell(SAY_AGGRO2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO2); + break; + } + } + + void KilledUnit(Unit *victim) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_SLAY1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY1); + break; + case 1: + DoYell(SAY_SLAY2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY2); + break; + } + } + + void JustDied(Unit *victim) + { + DoYell(SAY_DEATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_DEATH); + + if( pInstance && pInstance->GetData(TYPE_THRALL_EVENT) == IN_PROGRESS ) + pInstance->SetData(TYPE_THRALL_PART4, DONE); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //Sand Breath + if( SandBreath_Timer < diff ) + { + if( m_creature->IsNonMeleeSpellCasted(false) ) + m_creature->InterruptNonMeleeSpells(false); + + DoCast(m_creature->getVictim(),SPELL_SAND_BREATH); + + switch(rand()%2) + { + case 0: + DoYell(SAY_BREATH1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_BREATH1); + break; + case 1: + DoYell(SAY_BREATH2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_BREATH2); + break; + } + + SandBreath_Timer = 25000+rand()%5000; + }else SandBreath_Timer -= diff; + + if( ImpendingDeath_Timer < diff ) + { + DoCast(m_creature->getVictim(),SPELL_IMPENDING_DEATH); + ImpendingDeath_Timer = 30000+rand()%5000; + }else ImpendingDeath_Timer -= diff; + + if( WingBuffet_Timer < diff ) + { + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target,SPELL_WING_BUFFET); + WingBuffet_Timer = 25000+rand()%10000; + }else WingBuffet_Timer -= diff; + + if( Mda_Timer < diff ) + { + DoCast(m_creature,SPELL_MAGIC_DISRUPTION_AURA); + Mda_Timer = 15000; + }else Mda_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_epoch_hunter(Creature *_Creature) +{ + return new boss_epoch_hunterAI (_Creature); +} + +void AddSC_boss_epoch_hunter() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_epoch_hunter"; + newscript->GetAI = GetAI_boss_epoch_hunter; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/old_hillsbrad/boss_leutenant_drake.cpp b/src/bindings/scripts/scripts/zone/caverns_of_time/old_hillsbrad/boss_leutenant_drake.cpp new file mode 100644 index 00000000000..5a6ccb7dc97 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/caverns_of_time/old_hillsbrad/boss_leutenant_drake.cpp @@ -0,0 +1,246 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Luetenant_Drake +SD%Complete: 70 +SDComment: Missing proper code for patrolling area after being spawned. Also script for GO (barrels)(missing mangos support) +SDCategory: Caverns of Time, Old Hillsbrad Foothills +EndScriptData */ + +#include "precompiled.h" +#include "def_old_hillsbrad.h" +#include "../../../npc/npc_escortAI.h" + +/*###### +## go_barrel_old_hillsbrad +######*/ + +#define QUEST_ENTRY_DIVERSION 10283 +#define LODGE_QUEST_TRIGGER 20155 + +bool GOHello_go_barrel_old_hillsbrad(Player *player, GameObject* _GO) +{ + ScriptedInstance* pInstance = ((ScriptedInstance*)_GO->GetInstanceData()); + + if( pInstance ) + { + if( pInstance->GetData(TYPE_BARREL_DIVERSION) != DONE ) + { + pInstance->SetData(TYPE_BARREL_DIVERSION, IN_PROGRESS); + } + else if( pInstance->GetData(TYPE_BARREL_DIVERSION) == DONE ) + { + player->SummonCreature(17848,2128.43,71.01,64.42,1.74,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,1200000); + if( player->GetQuestStatus(QUEST_ENTRY_DIVERSION) == QUEST_STATUS_INCOMPLETE ) + player->KilledMonster(LODGE_QUEST_TRIGGER,0); + } + } + return false; +} + +/*###### +## boss_lieutenant_drake +######*/ + +#define WHIRLWIND 40236 +#define FEAR 33789 +#define MORTAL_STRIKE 40220 +#define EXPLODIG_SHOUT 33792 + +#define SAY_ENTER1 "You there, fetch water quickly!" +#define SAY_ENTER2 "Get these flames out before they spread to the rest of the keep!" +#define SAY_ENTER3 "Hurry, damn you!" +#define SAY_AGGRO "I know what you're up to, and I mean to put an end to it, permanently!" +#define SAY_SLAY1 "No more middling for you." +#define SAY_SLAY2 "You will not interfere!" +#define SAY_MORTAL "Time to bleed!" +#define SAY_SHOUT "Run, you blasted cowards!" +#define SAY_DEATH "Thrall... must not... go free." + +#define SOUND_ENTER 10428 +#define SOUND_AGGRO 10429 +#define SOUND_SLAY1 10432 +#define SOUND_SLAY2 10433 +#define SOUND_MORTAL 10430 +#define SOUND_SHOUT 10431 +#define SOUND_DEATH 10434 + +struct Location +{ + uint32 wpId; + float x; + float y; + float z; +}; + +static Location DrakeWP[]= +{ + {0, 2125.84, 88.2535, 54.8830}, + {1, 2111.01, 93.8022, 52.6356}, + {2, 2106.70, 114.753, 53.1965}, + {3, 2107.76, 138.746, 52.5109}, + {4, 2114.83, 160.142, 52.4738}, + {5, 2125.24, 178.909, 52.7283}, + {6, 2151.02, 208.901, 53.1551}, + {7, 2177.00, 233.069, 52.4409}, + {8, 2190.71, 227.831, 53.2742}, + {9, 2178.14, 214.219, 53.0779}, + {10, 2154.99, 202.795, 52.6446}, + {11, 2132.00, 191.834, 52.5709}, + {12, 2117.59, 166.708, 52.7686}, + {13, 2093.61, 139.441, 52.7616}, + {14, 2086.29, 104.950, 52.9246}, + {15, 2094.23, 81.2788, 52.6946}, + {16, 2108.70, 85.3075, 53.3294}, + {17, 2125.50, 88.9481, 54.7953}, + {18, 2128.20, 70.9763, 64.4221} +}; + +struct MANGOS_DLL_DECL boss_lieutenant_drakeAI : public ScriptedAI +{ + boss_lieutenant_drakeAI(Creature *c) : ScriptedAI(c) {Reset();} + + bool CanPatrol; + uint32 wpId; + + uint32 Whirlwind_Timer; + uint32 Fear_Timer; + uint32 MortalStrike_Timer; + uint32 ExplodingShout_Timer; + + void Reset() + { + CanPatrol = true; + wpId = 0; + + Whirlwind_Timer = 20000; + Fear_Timer = 30000; + MortalStrike_Timer = 45000; + ExplodingShout_Timer = 25000; + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO); + } + + void KilledUnit(Unit *victim) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_SLAY1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY1); + break; + case 1: + DoYell(SAY_SLAY2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY2); + break; + } + } + + void JustDied(Unit *victim) + { + DoYell(SAY_DEATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_DEATH); + } + + void UpdateAI(const uint32 diff) + { + //TODO: make this work + if( CanPatrol && wpId == 0 ) + { + m_creature->GetMotionMaster()->MovePoint(DrakeWP[0].wpId, DrakeWP[0].x, DrakeWP[0].y, DrakeWP[0].z); + wpId++; + } + + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //Whirlwind + if (Whirlwind_Timer < diff) + { + DoCast(m_creature->getVictim(), WHIRLWIND); + + Whirlwind_Timer = 20000+rand()%5000; + }else Whirlwind_Timer -= diff; + + //Fear + if (Fear_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (target) + DoCast(target, FEAR); + + Fear_Timer = 30000+rand()%10000; + }else Fear_Timer -= diff; + + //Mortal Strike + if (MortalStrike_Timer < diff) + { + DoYell(SAY_MORTAL, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_MORTAL); + + DoCast(m_creature->getVictim(), MORTAL_STRIKE); + + MortalStrike_Timer = 45000+rand()%5000; + }else MortalStrike_Timer -= diff; + + /* + //This only enabled on heroic? + //Exploding Shout + if (m_creature->IsHeroicCreature()) + { + if (ExplodingShout_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) + DoYell(SAY_SHOUT, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SHOUT); + DoCast(target,EXPLODING_SHOUT); + ExplodingShout_Timer = 25000+rand()%5000; + }else ExplodingShout_Timer -= diff; + } + */ + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_lieutenant_drake(Creature *_Creature) +{ + return new boss_lieutenant_drakeAI (_Creature); +} + +void AddSC_boss_lieutenant_drake() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="go_barrel_old_hillsbrad"; + newscript->pGOHello = GOHello_go_barrel_old_hillsbrad; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_lieutenant_drake"; + newscript->GetAI = GetAI_boss_lieutenant_drake; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/old_hillsbrad/def_old_hillsbrad.h b/src/bindings/scripts/scripts/zone/caverns_of_time/old_hillsbrad/def_old_hillsbrad.h new file mode 100644 index 00000000000..8a230919bbc --- /dev/null +++ b/src/bindings/scripts/scripts/zone/caverns_of_time/old_hillsbrad/def_old_hillsbrad.h @@ -0,0 +1,16 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_OLD_HILLSBRAD_H +#define DEF_OLD_HILLSBRAD_H + +#define TYPE_BARREL_DIVERSION 1 +#define TYPE_THRALL_EVENT 2 +#define TYPE_THRALL_PART1 3 +#define TYPE_THRALL_PART2 4 +#define TYPE_THRALL_PART3 5 +#define TYPE_THRALL_PART4 6 +#define DATA_THRALL 7 +#define DATA_TARETHA 8 +#endif diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/old_hillsbrad/instance_old_hillsbrad.cpp b/src/bindings/scripts/scripts/zone/caverns_of_time/old_hillsbrad/instance_old_hillsbrad.cpp new file mode 100644 index 00000000000..57d78f5d98f --- /dev/null +++ b/src/bindings/scripts/scripts/zone/caverns_of_time/old_hillsbrad/instance_old_hillsbrad.cpp @@ -0,0 +1,178 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Old_Hillsbrad +SD%Complete: 60 +SDComment: If thrall escort fail, all parts will reset. In future, save sub-parts and continue from last known. +SDCategory: Caverns of Time, Old Hillsbrad Foothills +EndScriptData */ + +/* +-- UPDATE `gameobject_template` SET `ScriptName`='go_barrel_old_hillsbrad' WHERE `entry`=182589; +*/ + +#include "precompiled.h" +#include "def_old_hillsbrad.h" + +#define ENCOUNTERS 6 + +#define THRALL_ENTRY 17876 +#define TARETHA_ENTRY 18887 + +struct MANGOS_DLL_DECL instance_old_hillsbrad : public ScriptedInstance +{ + instance_old_hillsbrad(Map *Map) : ScriptedInstance(Map) {Initialize();}; + + uint32 Encounter[ENCOUNTERS]; + uint32 mBarrelCount; + uint32 mThrallEventCount; + + uint64 ThrallGUID; + uint64 TarethaGUID; + + void Initialize() + { + mBarrelCount = 0; + mThrallEventCount = 0; + ThrallGUID = 0; + TarethaGUID = 0; + + for(uint8 i = 0; i < ENCOUNTERS; i++) + Encounter[i] = NOT_STARTED; + } + + void OnCreatureCreate(Creature *creature, uint32 creature_entry) + { + switch(creature_entry) + { + case THRALL_ENTRY: + ThrallGUID = creature->GetGUID(); + break; + case TARETHA_ENTRY: + TarethaGUID = creature->GetGUID(); + break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case TYPE_BARREL_DIVERSION: + { + if( mBarrelCount < 5 ) + { + mBarrelCount++; + debug_log("SD2: go_barrel_old_hillsbrad count %u",mBarrelCount); + } + else if( mBarrelCount >= 5 ) + Encounter[0] = DONE; + break; + } + case TYPE_THRALL_EVENT: + { + if( data == FAIL ) + { + if( mThrallEventCount <= 20 ) + { + mThrallEventCount++; + Encounter[1] = NOT_STARTED; + debug_log("SD2: Thrall event failed %u times. Resetting all sub-events.",mThrallEventCount); + Encounter[2] = NOT_STARTED; + Encounter[3] = NOT_STARTED; + Encounter[4] = NOT_STARTED; + Encounter[5] = NOT_STARTED; + } + else if( mThrallEventCount > 20 ) + { + Encounter[1] = data; + Encounter[2] = data; + Encounter[3] = data; + Encounter[4] = data; + Encounter[5] = data; + debug_log("SD2: Thrall event failed %u times. Reset instance required.",mThrallEventCount); + } + } + else + Encounter[1] = data; + debug_log("SD2: Thrall escort event adjusted to data %u.",data); + break; + } + case TYPE_THRALL_PART1: + Encounter[2] = data; + debug_log("SD2: Thrall event part I adjusted to data %u.",data); + break; + case TYPE_THRALL_PART2: + Encounter[3] = data; + debug_log("SD2: Thrall event part II adjusted to data %u.",data); + break; + case TYPE_THRALL_PART3: + Encounter[4] = data; + debug_log("SD2: Thrall event part III adjusted to data %u.",data); + break; + case TYPE_THRALL_PART4: + Encounter[5] = data; + debug_log("SD2: Thrall event part IV adjusted to data %u.",data); + break; + } + } + + uint32 GetData(uint32 data) + { + switch(data) + { + case TYPE_BARREL_DIVERSION: + return Encounter[0]; + case TYPE_THRALL_EVENT: + return Encounter[1]; + case TYPE_THRALL_PART1: + return Encounter[2]; + case TYPE_THRALL_PART2: + return Encounter[3]; + case TYPE_THRALL_PART3: + return Encounter[4]; + case TYPE_THRALL_PART4: + return Encounter[5]; + } + return 0; + } + + uint64 GetData64(uint32 data) + { + switch(data) + { + case DATA_THRALL: + return ThrallGUID; + case DATA_TARETHA: + return TarethaGUID; + } + return 0; + } +}; +InstanceData* GetInstanceData_instance_old_hillsbrad(Map* map) +{ + return new instance_old_hillsbrad(map); +} + +void AddSC_instance_old_hillsbrad() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_old_hillsbrad"; + newscript->GetInstanceData = GetInstanceData_instance_old_hillsbrad; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/old_hillsbrad/old_hillsbrad.cpp b/src/bindings/scripts/scripts/zone/caverns_of_time/old_hillsbrad/old_hillsbrad.cpp new file mode 100644 index 00000000000..a02715785fe --- /dev/null +++ b/src/bindings/scripts/scripts/zone/caverns_of_time/old_hillsbrad/old_hillsbrad.cpp @@ -0,0 +1,916 @@ +/* Copyright (C) 2006,2007 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Old_Hillsbrad +SD%Complete: 40 +SDComment: All friendly NPC's. Thrall waypoints fairly complete, missing many details, but possible to complete escort. +SDCategory: Caverns of Time, Old Hillsbrad Foothills +EndScriptData */ + +/* ContentData +npc_brazen +npc_erozion +npc_thrall_old_hillsbrad +npc_taretha +EndContentData */ + +#include "precompiled.h" +#include "../../../npc/npc_escortAI.h" +#include "def_old_hillsbrad.h" + +#define QUEST_ENTRY_HILLSBRAD 10282 +#define QUEST_ENTRY_DIVERSION 10283 +#define QUEST_ENTRY_ESCAPE 10284 +#define QUEST_ENTRY_RETURN 10285 +#define ITEM_ENTRY_BOMBS 25853 + +/*###### +## npc_brazen +######*/ + +bool GossipHello_npc_brazen(Player *player, Creature *_Creature) +{ + player->ADD_GOSSIP_ITEM(0, "I am ready to go to Durnholde Keep.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + return true; +} + +bool GossipSelect_npc_brazen(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if (action == GOSSIP_ACTION_INFO_DEF+1) + { + if( !player->HasItemCount(ITEM_ENTRY_BOMBS,1) ) + player->SEND_GOSSIP_MENU(9780, _Creature->GetGUID()); + else + { + player->CLOSE_GOSSIP_MENU(); + + std::vector nodes; + + nodes.resize(2); + nodes[0] = 115; //from brazen + nodes[1] = 116; //end outside durnholde + player->ActivateTaxiPathTo(nodes); //TaxiPath 534 + } + } + return true; +} + +/*###### +## npc_erozion +######*/ + +bool GossipHello_npc_erozion(Player *player, Creature *_Creature) +{ + if( _Creature->isQuestGiver() ) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + ScriptedInstance* pInstance = ((ScriptedInstance*)_Creature->GetInstanceData()); + if( pInstance && pInstance->GetData(TYPE_BARREL_DIVERSION) != DONE && !player->HasItemCount(ITEM_ENTRY_BOMBS,1) ) + player->ADD_GOSSIP_ITEM( 0, "I need a pack of Incendiary Bombs.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + if( !player->GetQuestRewardStatus(QUEST_ENTRY_RETURN) && player->GetQuestStatus(QUEST_ENTRY_RETURN) == QUEST_STATUS_COMPLETE ) + player->ADD_GOSSIP_ITEM( 0, "[PH] Teleport please, i'm tired.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + + player->SEND_GOSSIP_MENU(9778, _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_erozion(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + if( action == GOSSIP_ACTION_INFO_DEF+1 ) + { + ItemPosCountVec dest; + uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, ITEM_ENTRY_BOMBS, 1, false); + if( msg == EQUIP_ERR_OK ) + { + player->StoreNewItem( dest, ITEM_ENTRY_BOMBS, 1, true); + } + player->SEND_GOSSIP_MENU(9515, _Creature->GetGUID()); + } + if( action == GOSSIP_ACTION_INFO_DEF+2 ) + { + player->CLOSE_GOSSIP_MENU(); + } + return true; +} + +/*###### +## npc_thrall_old_hillsbrad +######*/ + +#define SPEED_WALK (0.5f) +#define SPEED_RUN (1.0f) +#define SPEED_MOUNT (1.6f) + +#define THRALL_WEAPON_MODEL 22106 +#define THRALL_WEAPON_INFO 218169346 +#define THRALL_SHIELD_MODEL 18662 +#define THRALL_SHIELD_INFO 234948100 +#define THRALL_MODEL_UNEQUIPPED 17292 +#define THRALL_MODEL_EQUIPPED 18165 + +#define MOB_ENTRY_RIFLE 17820 +#define MOB_ENTRY_WARDEN 17833 +#define MOB_ENTRY_VETERAN 17860 +#define MOB_ENTRY_WATCHMAN 17814 +#define MOB_ENTRY_SENTRY 17815 + +#define MOB_ENTRY_BARN_GUARDSMAN 18092 +#define MOB_ENTRY_BARN_PROTECTOR 18093 +#define MOB_ENTRY_BARN_LOOKOUT 18094 + +#define MOB_ENTRY_CHURCH_GUARDSMAN 23175 +#define MOB_ENTRY_CHURCH_PROTECTOR 23179 +#define MOB_ENTRY_CHURCH_LOOKOUT 23177 + +#define MOB_ENTRY_INN_GUARDSMAN 23176 +#define MOB_ENTRY_INN_PROTECTOR 23180 +#define MOB_ENTRY_INN_LOOKOUT 23178 + +#define SKARLOC_MOUNT 18798 +#define SKARLOC_MOUNT_MODEL 18223 +#define EROZION_ENTRY 18723 + +#define GOSSIP_ID_START 9568 +#define GOSSIP_ID_SKARLOC1 9614 //I'm glad Taretha is alive. We now must find a way to free her... +#define GOSSIP_ITEM_SKARLOC1 "Taretha cannot see you, Thrall." +#define GOSSIP_ID_SKARLOC2 9579 //What do you mean by this? Is Taretha in danger? +#define GOSSIP_ITEM_SKARLOC2 "The situation is rather complicated, Thrall. It would be best for you to head into the mountains now, before more of Blackmoore's men show up. We'll make sure Taretha is safe." +#define GOSSIP_ID_SKARLOC3 9580 + +#define GOSSIP_ID_TARREN 9597 //tarren mill is beyond these trees +#define GOSSIP_ITEM_TARREN "We're ready, Thrall." + +#define GOSSIP_ID_COMPLETE 9578 //Thank you friends, I owe my freedom to you. Where is Taretha? I hoped to see her + +#define THRALL_START_EVENT_PART1 "Very well then. Let's go!" +#define SOUND_START_EVENT 10465 + +#define THRALL_SAY_ARMOR "As long as we're going with a new plan, I may aswell pick up a weapon and some armor." + +#define THRALL_SKARLOC_MEET "A rider approaches!" +#define SOUND_SKARLOC_MEET 10466 +#define THRALL_SKARLOC_TAUNT "I'll never be chained again!" +#define SOUND_SKARLOC_TAUNT 10467 + +#define THRALL_START_EVENT_PART2 "Very well. Tarren Mill lies just west of here. Since time is of the essence..." +#define SOUND_START_EVENT_PART2 10468 +#define THRALL_MOUNTS_UP "Let's ride!" +#define SOUND_MOUNTS_UP 10469 + +#define THRALL_CHURCH_END "Taretha must be in the inn. Let's go." +#define THRALL_MEET_TARETHA "Taretha! What foul magic is this?" + +#define THRALL_EPOCH_WONDER "Who or what was that?" +#define SOUND_EPOCH_WONDER 10470 +#define THRALL_EPOCH_KILL_TARETHA "No!" +#define SOUND_EPOCH_KILL_TARETHA 10471 + +#define THRALL_EVENT_COMPLETE "Goodbye, Taretha. I will never forget your kindness." +#define SOUND_EVENT_COMPLETE 10472 + +#define THRALL_RANDOM_LOW_HP1 "Things are looking grim..." +#define SOUND_RANDOM_LOW_HP1 10458 +#define THRALL_RANDOM_LOW_HP2 "I will fight to the last!" +#define SOUND_RANDOM_LOW_HP2 10459 + +#define THRALL_RANDOM_DIE1 "Taretha..." +#define SOUND_RANDOM_DIE1 10460 +#define THRALL_RANDOM_DIE2 "A good day...to die..." +#define SOUND_RANDOM_DIE2 10461 + +#define THRALL_RANDOM_AGGRO1 "I have earned my freedom!" +#define SOUND_RANDOM_AGGRO1 10448 +#define THRALL_RANDOM_AGGRO2 "This day is long overdue. Out of my way!" +#define SOUND_RANDOM_AGGRO2 10449 +#define THRALL_RANDOM_AGGRO3 "I am a slave no longer!" +#define SOUND_RANDOM_AGGRO3 10450 +#define THRALL_RANDOM_AGGRO4 "Blackmoore has much to answer for!" +#define SOUND_RANDOM_AGGRO4 10451 + +#define THRALL_RANDOM_KILL1 "You have forced my hand!" +#define SOUND_RANDOM_KILL1 10452 +#define THRALL_RANDOM_KILL2 "It should not have come to this!" +#define SOUND_RANDOM_KILL2 10453 +#define THRALL_RANDOM_KILL3 "I did not ask for this!" +#define SOUND_RANDOM_KILL3 10454 + +#define THRALL_LEAVE_COMBAT1 "I am truly in your debt, strangers." +#define SOUND_LEAVE_COMBAT1 10455 +#define THRALL_LEAVE_COMBAT2 "Thank you, strangers. You have given me hope." +#define SOUND_LEAVE_COMBAT2 10456 +#define THRALL_LEAVE_COMBAT3 "I will not waste this chance. I will seek out my destiny." +#define SOUND_LEAVE_COMBAT3 10457 + +struct MANGOS_DLL_DECL npc_thrall_old_hillsbradAI : public npc_escortAI +{ + npc_thrall_old_hillsbradAI(Creature *c) : npc_escortAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance *pInstance; + Creature* sum; + uint64 TarethaGUID; + bool LowHp; + bool HadMount; + + void WaypointReached(uint32 i) + { + switch( i ) + { + case 8: + m_creature->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + sum = m_creature->SummonCreature(18764,2181.87,112.46,89.45,0.26,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + if( sum ) sum->AI()->AttackStart(m_creature); + break; + case 9: + m_creature->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + DoSay(THRALL_SAY_ARMOR, LANG_UNIVERSAL, NULL); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, THRALL_WEAPON_MODEL); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, THRALL_WEAPON_INFO); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+1, 781); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, THRALL_SHIELD_MODEL); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+2, THRALL_SHIELD_INFO); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+3, 1038); + break; + case 10: + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, THRALL_MODEL_EQUIPPED); + break; + case 11: + m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + break; + case 15: + sum = m_creature->SummonCreature(MOB_ENTRY_RIFLE,2200.28,137.37,87.93,5.07,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + if( sum ) sum->AI()->AttackStart(m_creature); + sum = m_creature->SummonCreature(MOB_ENTRY_WARDEN,2197.44,131.83,87.93,0.78,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + if( sum ) sum->AI()->AttackStart(m_creature); + sum = m_creature->SummonCreature(MOB_ENTRY_VETERAN,2203.62,135.40,87.93,3.70,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + if( sum ) sum->AI()->AttackStart(m_creature); + sum = m_creature->SummonCreature(MOB_ENTRY_VETERAN,2200.75,130.13,87.93,1.48,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + if( sum ) sum->AI()->AttackStart(m_creature); + break; + case 21: + sum = m_creature->SummonCreature(MOB_ENTRY_RIFLE,2135.80,154.01,67.45,4.98,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + if( sum ) sum->AI()->AttackStart(m_creature); + sum = m_creature->SummonCreature(MOB_ENTRY_WARDEN,2144.36,151.87,67.74,4.46,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + if( sum ) sum->AI()->AttackStart(m_creature); + sum = m_creature->SummonCreature(MOB_ENTRY_VETERAN,2142.12,154.41,67.12,4.56,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + if( sum ) sum->AI()->AttackStart(m_creature); + sum = m_creature->SummonCreature(MOB_ENTRY_VETERAN,2138.08,155.38,67.24,4.60,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + if( sum ) sum->AI()->AttackStart(m_creature); + break; + case 25: + sum = m_creature->SummonCreature(MOB_ENTRY_RIFLE,2102.98,192.17,65.24,6.02,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + if( sum ) sum->AI()->AttackStart(m_creature); + sum = m_creature->SummonCreature(MOB_ENTRY_WARDEN,2108.48,198.75,65.18,5.15,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + if( sum ) sum->AI()->AttackStart(m_creature); + sum = m_creature->SummonCreature(MOB_ENTRY_VETERAN,2106.11,197.29,65.18,5.63,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + if( sum ) sum->AI()->AttackStart(m_creature); + sum = m_creature->SummonCreature(MOB_ENTRY_VETERAN,2104.18,194.82,65.18,5.75,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + if( sum ) sum->AI()->AttackStart(m_creature); + break; + case 29: + DoSay(THRALL_SKARLOC_MEET, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_SKARLOC_MEET); + sum = m_creature->SummonCreature(17862,2036.48,271.22,63.43,5.27,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); + //temporary,skarloc should rather be triggered to walk up to thrall + if( sum ) sum->AI()->AttackStart(m_creature); + break; + case 30: + IsOnHold = true; + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + m_creature->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + break; + case 31: + DoSay(THRALL_MOUNTS_UP, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_MOUNTS_UP); + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_TALK); + DoMount(); + break; + case 37: + //possibly regular patrollers? If so, remove this and let database handle them + sum = m_creature->SummonCreature(MOB_ENTRY_WATCHMAN,2124.26,522.16,56.87,3.99,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + if( sum ) sum->AI()->AttackStart(m_creature); + sum = m_creature->SummonCreature(MOB_ENTRY_WATCHMAN,2121.69,525.37,57.11,4.01,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + if( sum ) sum->AI()->AttackStart(m_creature); + sum = m_creature->SummonCreature(MOB_ENTRY_SENTRY,2124.65,524.55,56.63,3.98,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + if( sum ) sum->AI()->AttackStart(m_creature); + break; + case 59: + m_creature->SummonCreature(SKARLOC_MOUNT,2488.64,625.77,58.26,4.71,TEMPSUMMON_TIMED_DESPAWN,10000); + DoUnmount(); + HadMount = false; + break; + case 60: + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); + //make horsie run off + IsOnHold = true; + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + if( pInstance ) + pInstance->SetData(TYPE_THRALL_PART2, DONE); + break; + case 64: + m_creature->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + break; + case 68: + m_creature->SummonCreature(MOB_ENTRY_BARN_PROTECTOR,2500.22,692.60,55.50,2.84,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + m_creature->SummonCreature(MOB_ENTRY_BARN_LOOKOUT,2500.13,696.55,55.51,3.38,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + m_creature->SummonCreature(MOB_ENTRY_BARN_GUARDSMAN,2500.55,693.64,55.50,3.14,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + m_creature->SummonCreature(MOB_ENTRY_BARN_GUARDSMAN,2500.94,695.81,55.50,3.14,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + break; + case 71: + m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + break; + case 81: + m_creature->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + break; + case 83: + sum = m_creature->SummonCreature(MOB_ENTRY_CHURCH_PROTECTOR,2627.33,646.82,56.03,4.28,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,5000); + if( sum ) sum->AI()->AttackStart(m_creature); + sum = m_creature->SummonCreature(MOB_ENTRY_CHURCH_LOOKOUT,2624.14,648.03,56.03,4.50,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,5000); + if( sum ) sum->AI()->AttackStart(m_creature); + sum = m_creature->SummonCreature(MOB_ENTRY_CHURCH_GUARDSMAN,2625.32,649.60,56.03,4.38,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,5000); + if( sum ) sum->AI()->AttackStart(m_creature); + sum = m_creature->SummonCreature(MOB_ENTRY_CHURCH_GUARDSMAN,2627.22,649.00,56.03,4.34,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,5000); + if( sum ) sum->AI()->AttackStart(m_creature); + break; + case 84: + DoSay(THRALL_CHURCH_END, LANG_UNIVERSAL, NULL); + break; + case 91: + m_creature->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + case 93: + sum = m_creature->SummonCreature(MOB_ENTRY_INN_PROTECTOR,2652.71,660.31,61.93,1.67,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + if( sum ) sum->AI()->AttackStart(m_creature); + sum = m_creature->SummonCreature(MOB_ENTRY_INN_LOOKOUT,2648.96,662.59,61.93,0.79,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + if( sum ) sum->AI()->AttackStart(m_creature); + sum = m_creature->SummonCreature(MOB_ENTRY_INN_GUARDSMAN,2657.36,662.34,61.93,2.68,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + if( sum ) sum->AI()->AttackStart(m_creature); + sum = m_creature->SummonCreature(MOB_ENTRY_INN_GUARDSMAN,2656.39,659.77,61.93,2.61,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + if( sum ) sum->AI()->AttackStart(m_creature); + break; + case 94: + m_creature->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + //trigger taretha Say("Thrall, you escaped!") + break; + case 95: + DoSay(THRALL_MEET_TARETHA, LANG_UNIVERSAL, NULL); + if( pInstance ) + pInstance->SetData(TYPE_THRALL_PART3,DONE); + IsOnHold = true; + break; + case 96: + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_TALK); + DoYell(THRALL_EPOCH_WONDER, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_EPOCH_WONDER); + break; + case 97: + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); + DoYell(THRALL_EPOCH_KILL_TARETHA, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_EPOCH_KILL_TARETHA); + m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + break; + case 98: + //trigger epoch Yell("Thrall! Come outside and face your fate! ....") + break; + case 106: + { + //trigger taretha to run down outside + /*if( pInstance ) + uint64 TarethaGUID = pInstance->GetData64(DATA_TARETHA); + if( TarethaGUID ) + { + Creature* Taretha = ((Creature*)Unit::GetUnit((*m_creature), TarethaGUID)); + if( Taretha ) + ((npc_escortAI*)(Taretha->AI()))->Start(false, false, true, 0); + }*/ + + if( PlayerGUID ) + { + Unit* player = ((Creature*)Unit::GetUnit((*m_creature), PlayerGUID)); + if( player && player->GetTypeId() == TYPEID_PLAYER ) + ((Player*)player)->KilledMonster(20156,m_creature->GetGUID()); + } + + //alot will happen here, thrall and taretha talk, erozion appear at spot to explain + m_creature->SummonCreature(EROZION_ENTRY,2646.47,680.416,55.38,4.16,TEMPSUMMON_TIMED_DESPAWN,120000); + } + break; + } + } + + void Reset() + { + sum = NULL; + LowHp = false; + + if( HadMount ) + DoMount(); + + if( !IsBeingEscorted ) + { + DoUnmount(); + HadMount = false; + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 0); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, 0); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+1, 0); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 0); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+2, 0); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+3, 0); + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, THRALL_MODEL_UNEQUIPPED); + } + if( IsBeingEscorted ) + { + switch(rand()%3) + { + case 0: + DoYell(THRALL_LEAVE_COMBAT1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_LEAVE_COMBAT1); + break; + case 1: + DoYell(THRALL_LEAVE_COMBAT2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_LEAVE_COMBAT2); + break; + case 2: + DoYell(THRALL_LEAVE_COMBAT3,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_LEAVE_COMBAT3); + break; + } + } + } + void StartWP() + { + m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + IsOnHold = false; + } + void DoMount() + { + m_creature->Mount(SKARLOC_MOUNT_MODEL); + m_creature->SetSpeed(MOVE_RUN,SPEED_MOUNT); + m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + } + void DoUnmount() + { + m_creature->Unmount(); + m_creature->SetSpeed(MOVE_RUN,SPEED_RUN); + } + void Aggro(Unit* who) + { + switch(rand()%4) + { + case 0: + DoYell(THRALL_RANDOM_AGGRO1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_RANDOM_AGGRO1); + break; + case 1: + DoYell(THRALL_RANDOM_AGGRO2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_RANDOM_AGGRO2); + break; + case 2: + DoYell(THRALL_RANDOM_AGGRO3,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_RANDOM_AGGRO3); + break; + case 3: + DoYell(THRALL_RANDOM_AGGRO4,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_RANDOM_AGGRO4); + break; + } + if( m_creature->IsMounted() ) + { + DoUnmount(); + HadMount = true; + } + } + void KilledUnit(Unit *victim) + { + switch(rand()%3) + { + case 0: + DoYell(THRALL_RANDOM_KILL1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_RANDOM_KILL1); + break; + case 1: + DoYell(THRALL_RANDOM_KILL2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_RANDOM_KILL2); + break; + case 2: + DoYell(THRALL_RANDOM_KILL3,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_RANDOM_KILL3); + break; + } + } + void JustDied(Unit *slayer) + { + if(slayer == m_creature) // Don't do a yell if he kills self (if player goes too far or at the end). + return; + + switch(rand()%2) + { + case 0: + DoYell(THRALL_RANDOM_DIE1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_RANDOM_DIE1); + break; + case 1: + DoYell(THRALL_RANDOM_DIE2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_RANDOM_DIE2); + break; + } + if( pInstance ) + pInstance->SetData(TYPE_THRALL_EVENT,FAIL); + } + void UpdateAI(const uint32 diff) + { + npc_escortAI::UpdateAI(diff); + + if( InCombat && m_creature->getVictim() ) + { + //add his abilities'n-crap here + + if( !LowHp && ((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 20) ) + { + switch(rand()%2) + { + case 0: + DoYell(THRALL_RANDOM_LOW_HP1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_RANDOM_LOW_HP1); + break; + case 1: + DoYell(THRALL_RANDOM_LOW_HP2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_RANDOM_LOW_HP2); + break; + } + LowHp = true; + } + } + } +}; + +CreatureAI* GetAI_npc_thrall_old_hillsbrad(Creature *_Creature) +{ + npc_thrall_old_hillsbradAI* thrall_walkAI = new npc_thrall_old_hillsbradAI(_Creature); + + thrall_walkAI->AddWaypoint(0, 2230.91, 118.765, 82.2947,5000); + thrall_walkAI->AddWaypoint(1, 2230.33, 114.980, 82.2946); + thrall_walkAI->AddWaypoint(2, 2233.36, 111.057, 82.2996); + thrall_walkAI->AddWaypoint(3, 2231.17, 108.486, 82.6624); + thrall_walkAI->AddWaypoint(4, 2220.22, 114.605, 89.4264); + thrall_walkAI->AddWaypoint(5, 2215.23, 115.990, 89.4549); + thrall_walkAI->AddWaypoint(6, 2210.00, 106.849, 89.4549); + thrall_walkAI->AddWaypoint(7, 2205.66, 105.234, 89.4549); + //spawn armorer + thrall_walkAI->AddWaypoint(8, 2192.26, 112.618, 89.4549); + + //get weapon + thrall_walkAI->AddWaypoint(9, 2181.28, 118.612, 89.4549,8000); + //get armor + thrall_walkAI->AddWaypoint(10, 2181.62, 120.385, 89.4549,5000); + + thrall_walkAI->AddWaypoint(11, 2189.44, 113.922, 89.4549); + thrall_walkAI->AddWaypoint(12, 2195.63, 110.584, 89.4549); + thrall_walkAI->AddWaypoint(13, 2201.09, 115.115, 89.4549); + thrall_walkAI->AddWaypoint(14, 2204.34, 121.036, 89.4355); + //first ambush + thrall_walkAI->AddWaypoint(15, 2208.66, 129.127, 87.9560); + thrall_walkAI->AddWaypoint(16, 2193.09, 137.940, 88.2164); + thrall_walkAI->AddWaypoint(17, 2173.39, 149.064, 87.9227); + thrall_walkAI->AddWaypoint(18, 2164.25, 137.965, 85.0595); + thrall_walkAI->AddWaypoint(19, 2149.31, 125.645, 77.0858); + thrall_walkAI->AddWaypoint(20, 2142.78, 127.173, 75.5954); + //second ambush + thrall_walkAI->AddWaypoint(21, 2139.28, 133.952, 73.6386); + thrall_walkAI->AddWaypoint(22, 2139.54, 155.235, 67.1269); + thrall_walkAI->AddWaypoint(23, 2145.38, 167.551, 64.8974); + thrall_walkAI->AddWaypoint(24, 2134.28, 175.304, 67.9446); + thrall_walkAI->AddWaypoint(25, 2118.08, 187.387, 68.8141); + //third ambush + thrall_walkAI->AddWaypoint(26, 2105.88, 195.461, 65.1854); + thrall_walkAI->AddWaypoint(27, 2096.77, 196.939, 65.2117); + thrall_walkAI->AddWaypoint(28, 2083.90, 209.395, 64.8736); + //in front of keeps gate, meeting scarloc + thrall_walkAI->AddWaypoint(29, 2067.84, 224.376, 64.8022,30000); + + //ref point after skarloc fight + thrall_walkAI->AddWaypoint(30, 2055.40, 242.90, 63.3418); + + //mount up! + thrall_walkAI->AddWaypoint(31, 2039.20, 266.460, 63.0182,10000); + thrall_walkAI->AddWaypoint(32, 2011.77, 278.478, 65.3388); + thrall_walkAI->AddWaypoint(33, 2005.08, 289.676, 66.1179); + thrall_walkAI->AddWaypoint(34, 2033.11, 337.450, 66.0948); + thrall_walkAI->AddWaypoint(35, 2070.30, 416.208, 66.0893); + thrall_walkAI->AddWaypoint(36, 2086.76, 469.768, 65.9182); + //possible road ambush + thrall_walkAI->AddWaypoint(37, 2101.70, 497.955, 61.7881); + + thrall_walkAI->AddWaypoint(38, 2133.39, 530.933, 55.3700,5000); + thrall_walkAI->AddWaypoint(39, 2157.91, 559.635, 48.5157); + thrall_walkAI->AddWaypoint(40, 2167.34, 586.191, 42.4394); + thrall_walkAI->AddWaypoint(41, 2174.17, 637.643, 33.9002); + thrall_walkAI->AddWaypoint(42, 2179.31, 656.053, 34.723); + thrall_walkAI->AddWaypoint(43, 2183.65, 670.941, 34.0318); + thrall_walkAI->AddWaypoint(44, 2201.50, 668.616, 36.1236); + thrall_walkAI->AddWaypoint(45, 2221.56, 652.747, 36.6153); + thrall_walkAI->AddWaypoint(46, 2238.97, 640.125, 37.2214); + thrall_walkAI->AddWaypoint(47, 2251.17, 620.574, 40.1473); + thrall_walkAI->AddWaypoint(48, 2261.98, 595.303, 41.4117); + thrall_walkAI->AddWaypoint(49, 2278.67, 560.172, 38.9090); + thrall_walkAI->AddWaypoint(50, 2336.72, 528.327, 40.9369); + thrall_walkAI->AddWaypoint(51, 2381.04, 519.612, 37.7312); + thrall_walkAI->AddWaypoint(52, 2412.20, 515.425, 39.2068); + thrall_walkAI->AddWaypoint(53, 2452.39, 516.174, 42.9387); + thrall_walkAI->AddWaypoint(54, 2467.38, 539.389, 47.4992); + thrall_walkAI->AddWaypoint(55, 2470.70, 554.333, 46.6668); + thrall_walkAI->AddWaypoint(56, 2478.07, 575.321, 55.4549); + thrall_walkAI->AddWaypoint(57, 2480.00, 585.408, 56.6921); + thrall_walkAI->AddWaypoint(58, 2482.67, 608.817, 55.6643); + //demount + thrall_walkAI->AddWaypoint(59, 2485.62, 626.061, 58.0132,2000); + //scare the shit out of horse, so it'll run off + thrall_walkAI->AddWaypoint(60, 2486.91, 626.356, 58.0761); + + thrall_walkAI->AddWaypoint(61, 2488.58, 660.940, 57.3913); + thrall_walkAI->AddWaypoint(62, 2502.56, 686.059, 55.6252); + thrall_walkAI->AddWaypoint(63, 2502.08, 694.360, 55.5083); + thrall_walkAI->AddWaypoint(64, 2491.46, 694.321, 55.7163); + thrall_walkAI->AddWaypoint(65, 2491.10, 703.300, 55.7630); + thrall_walkAI->AddWaypoint(66, 2485.64, 702.992, 55.7917); + + thrall_walkAI->AddWaypoint(67, 2479.10, 695.291, 55.7901,10000); + //spawn mobs + thrall_walkAI->AddWaypoint(68, 2476.75, 693.689, 55.7960); + thrall_walkAI->AddWaypoint(69, 2475.39, 695.983, 55.8146); + thrall_walkAI->AddWaypoint(70, 2477.75, 694.473, 55.7945); + //meet mobs in doorway + thrall_walkAI->AddWaypoint(71, 2481.27, 697.747, 55.7910); + + thrall_walkAI->AddWaypoint(72, 2486.31, 703.131, 55.7861,5000); + thrall_walkAI->AddWaypoint(73, 2490.76, 703.511, 55.7662); + thrall_walkAI->AddWaypoint(74, 2491.30, 694.792, 55.7195); + thrall_walkAI->AddWaypoint(75, 2518.69, 693.876, 55.1383); + thrall_walkAI->AddWaypoint(76, 2531.33, 681.914, 55.1383); + thrall_walkAI->AddWaypoint(77, 2568.25, 682.654, 55.1778); + thrall_walkAI->AddWaypoint(78, 2589.61, 689.981, 55.1421); + thrall_walkAI->AddWaypoint(79, 2634.74, 679.833, 54.6613); + thrall_walkAI->AddWaypoint(80, 2630.41, 661.464, 54.2761); + thrall_walkAI->AddWaypoint(81, 2629.00, 656.982, 56.0651); + //stop in church + thrall_walkAI->AddWaypoint(82, 2620.84, 633.007, 56.0300,3000); + //summon + thrall_walkAI->AddWaypoint(83, 2622.99, 639.178, 56.0300); + + thrall_walkAI->AddWaypoint(84, 2628.73, 656.693, 56.0610,5000); + thrall_walkAI->AddWaypoint(85, 2630.34, 661.135, 54.2738); + thrall_walkAI->AddWaypoint(86, 2635.38, 672.243, 54.4508); + thrall_walkAI->AddWaypoint(87, 2644.13, 668.158, 55.3797); + thrall_walkAI->AddWaypoint(88, 2646.82, 666.740, 56.9898); + thrall_walkAI->AddWaypoint(89, 2658.22, 665.432, 57.1725); + thrall_walkAI->AddWaypoint(90, 2661.88, 674.849, 57.1725); + thrall_walkAI->AddWaypoint(91, 2656.23, 677.208, 57.1725); + + thrall_walkAI->AddWaypoint(92, 2652.28, 670.270, 61.9353); + //summon inn + thrall_walkAI->AddWaypoint(93, 2650.79, 664.290, 61.9302); + thrall_walkAI->AddWaypoint(94, 2658.19, 660.454, 61.9320,5000); + //speak with Taretha + thrall_walkAI->AddWaypoint(95, 2660.57, 659.173, 61.9370); + + //epoch calls + thrall_walkAI->AddWaypoint(96, 2658.19, 660.454, 61.9320,5000); + //taretha "dies" + thrall_walkAI->AddWaypoint(97, 2659.84, 659.482, 61.9361,5000); + + thrall_walkAI->AddWaypoint(98, 2654.28, 662.722, 61.9313); + thrall_walkAI->AddWaypoint(99, 2652.37, 670.561, 61.9368); + thrall_walkAI->AddWaypoint(100, 2656.05, 676.761, 57.1727); + thrall_walkAI->AddWaypoint(101, 2658.49, 677.166, 57.1727); + thrall_walkAI->AddWaypoint(102, 2659.28, 667.117, 57.1727); + thrall_walkAI->AddWaypoint(103, 2649.71, 665.387, 57.1727); + //he's outside inn here + thrall_walkAI->AddWaypoint(104, 2634.79, 672.964, 54.4577); + + //getting ready here, must start attack before 30secs up + thrall_walkAI->AddWaypoint(105, 2635.06, 673.892, 54.4713,30000); + + //ref point, will move here when all dead and meet Taretha + thrall_walkAI->AddWaypoint(106, 2634.79, 672.964, 54.4577,60000); + + //run off + thrall_walkAI->AddWaypoint(107, 2631.72, 665.629, 54.2923); + thrall_walkAI->AddWaypoint(108, 2647.40, 640.530, 55.7634); + + return (CreatureAI*)thrall_walkAI; +} + +bool GossipHello_npc_thrall_old_hillsbrad(Player *player, Creature *_Creature) +{ + if( _Creature->isQuestGiver() ) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + ScriptedInstance* pInstance = ((ScriptedInstance*)_Creature->GetInstanceData()); + if( pInstance ) + { + //if( pInstance->GetData(TYPE_BARREL_DIVERSION) == DONE && pInstance->GetData(TYPE_THRALL_EVENT) == NOT_STARTED ) + if( pInstance->GetData(TYPE_THRALL_EVENT) == NOT_STARTED ) + { + player->ADD_GOSSIP_ITEM( 0, "[PH] Start walking.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + player->SEND_GOSSIP_MENU(GOSSIP_ID_START, _Creature->GetGUID()); + } + if( pInstance->GetData(TYPE_THRALL_PART1) == DONE && !pInstance->GetData(TYPE_THRALL_PART2) ) + { + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_SKARLOC1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + player->SEND_GOSSIP_MENU(GOSSIP_ID_SKARLOC1, _Creature->GetGUID()); + } + if( pInstance->GetData(TYPE_THRALL_PART2) == DONE && !pInstance->GetData(TYPE_THRALL_PART3) ) + { + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_TARREN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + player->SEND_GOSSIP_MENU(GOSSIP_ID_TARREN, _Creature->GetGUID()); + } + } + return true; +} + +bool GossipSelect_npc_thrall_old_hillsbrad(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + ScriptedInstance* pInstance = ((ScriptedInstance*)_Creature->GetInstanceData()); + switch( action ) + { + case GOSSIP_ACTION_INFO_DEF+1: + player->CLOSE_GOSSIP_MENU(); + pInstance->SetData(TYPE_THRALL_EVENT,IN_PROGRESS); + pInstance->SetData(TYPE_THRALL_PART1,IN_PROGRESS); + + _Creature->Say(THRALL_START_EVENT_PART1, LANG_UNIVERSAL, 0); + ((npc_thrall_old_hillsbradAI*)_Creature->AI())->DoPlaySoundToSet(_Creature,SOUND_START_EVENT); + + ((npc_escortAI*)(_Creature->AI()))->Start(true, true, true, player->GetGUID()); + break; + + case GOSSIP_ACTION_INFO_DEF+2: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_SKARLOC2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+20); + player->SEND_GOSSIP_MENU(GOSSIP_ID_SKARLOC2, _Creature->GetGUID()); + break; + + case GOSSIP_ACTION_INFO_DEF+20: + player->SEND_GOSSIP_MENU(GOSSIP_ID_SKARLOC3, _Creature->GetGUID()); + _Creature->SummonCreature(SKARLOC_MOUNT,2038.81,270.26,63.20,5.41,TEMPSUMMON_TIMED_DESPAWN,12000); + pInstance->SetData(TYPE_THRALL_PART2,IN_PROGRESS); + + _Creature->Say(THRALL_START_EVENT_PART2, LANG_UNIVERSAL, 0); + ((npc_thrall_old_hillsbradAI*)_Creature->AI())->DoPlaySoundToSet(_Creature,SOUND_START_EVENT_PART2); + + ((npc_thrall_old_hillsbradAI*)_Creature->AI())->StartWP(); + break; + + case GOSSIP_ACTION_INFO_DEF+3: + player->CLOSE_GOSSIP_MENU(); + pInstance->SetData(TYPE_THRALL_PART3,IN_PROGRESS); + ((npc_thrall_old_hillsbradAI*)_Creature->AI())->StartWP(); + break; + } + return true; +} + +/*###### +## npc_taretha +######*/ + +#define GOSSIP_ID_EPOCH1 9610 //Thank you for helping Thrall escape, friends. Now I only hope +#define GOSSIP_ITEM_EPOCH1 "Strange wizard?" +#define GOSSIP_ID_EPOCH2 9613 //Yes, friends. This man was no wizard of +#define GOSSIP_ITEM_EPOCH2 "We'll get you out. Taretha. Don't worry. I doubt the wizard would wander too far away." + +#define TARETHA_FREE "I'm free! Thank you all!" + +struct MANGOS_DLL_DECL npc_tarethaAI : public npc_escortAI +{ + npc_tarethaAI(Creature *c) : npc_escortAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance *pInstance; + + void WaypointReached(uint32 i) + { + switch( i ) + { + case 6: + m_creature->Say(TARETHA_FREE, LANG_UNIVERSAL, 0); + break; + case 7: + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_CHEER); + break; + } + } + void Reset() {} + void Aggro(Unit* who) {} + +}; +CreatureAI* GetAI_npc_taretha(Creature *_Creature) +{ + npc_tarethaAI* taretha_walkAI = new npc_tarethaAI(_Creature); + + taretha_walkAI->AddWaypoint(0, 2650.06, 665.473, 61.9305); + taretha_walkAI->AddWaypoint(1, 2652.44, 670.761, 61.9370); + taretha_walkAI->AddWaypoint(2, 2655.96, 676.913, 57.1725); + taretha_walkAI->AddWaypoint(3, 2659.40, 677.317, 57.1725); + taretha_walkAI->AddWaypoint(4, 2651.75, 664.482, 57.1725); + taretha_walkAI->AddWaypoint(5, 2647.49, 666.595, 57.0824); + taretha_walkAI->AddWaypoint(6, 2644.37, 668.167, 55.4182); + taretha_walkAI->AddWaypoint(7, 2640.96, 669.890, 54.7567,60000); + + return (CreatureAI*)taretha_walkAI; +} + +bool GossipHello_npc_taretha(Player *player, Creature *_Creature) +{ + ScriptedInstance* pInstance = ((ScriptedInstance*)_Creature->GetInstanceData()); + if( pInstance && pInstance->GetData(TYPE_THRALL_PART3) == DONE && pInstance->GetData(TYPE_THRALL_PART4) == NOT_STARTED) + { + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_EPOCH1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + player->SEND_GOSSIP_MENU(GOSSIP_ID_EPOCH1, _Creature->GetGUID()); + } + return true; +} + +bool GossipSelect_npc_taretha(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + ScriptedInstance* pInstance = ((ScriptedInstance*)_Creature->GetInstanceData()); + if( action == GOSSIP_ACTION_INFO_DEF+1 ) + { + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_EPOCH2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + player->SEND_GOSSIP_MENU(GOSSIP_ID_EPOCH2, _Creature->GetGUID()); + } + if( action == GOSSIP_ACTION_INFO_DEF+2 ) + { + player->CLOSE_GOSSIP_MENU(); + + if( pInstance->GetData(TYPE_THRALL_EVENT) == IN_PROGRESS ) + { + pInstance->SetData(TYPE_THRALL_PART4,IN_PROGRESS); + _Creature->SummonCreature(18096,2639.13,698.55,65.43,4.59,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,120000); + + uint64 ThrallGUID = pInstance->GetData64(DATA_THRALL); + if(ThrallGUID) + { + Creature* Thrall = ((Creature*)Unit::GetUnit((*_Creature), ThrallGUID)); + if(Thrall) + ((npc_thrall_old_hillsbradAI*)Thrall->AI())->StartWP(); + } + } + } + return true; +} + +/*###### +## AddSC +######*/ + +void AddSC_old_hillsbrad() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npc_brazen"; + newscript->pGossipHello = &GossipHello_npc_brazen; + newscript->pGossipSelect = &GossipSelect_npc_brazen; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_erozion"; + newscript->pGossipHello = &GossipHello_npc_erozion; + newscript->pGossipSelect = &GossipSelect_npc_erozion; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_thrall_old_hillsbrad"; + newscript->pGossipHello = &GossipHello_npc_thrall_old_hillsbrad; + newscript->pGossipSelect = &GossipSelect_npc_thrall_old_hillsbrad; + newscript->GetAI = GetAI_npc_thrall_old_hillsbrad; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_taretha"; + newscript->pGossipHello = &GossipHello_npc_taretha; + newscript->pGossipSelect = &GossipSelect_npc_taretha; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_fathomlord_karathress.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_fathomlord_karathress.cpp new file mode 100644 index 00000000000..d21c3836d00 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_fathomlord_karathress.cpp @@ -0,0 +1,559 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Fathomlord_Karathress +SD%Complete: 50 +SDComment: Missing Multishot, pet, Totems, Windfury, Whirlwind +SDCategory: Coilfang Resevoir, Serpent Shrine Cavern +EndScriptData */ + +#include "precompiled.h" +#include "def_serpent_shrine.h" + +//Karathress spells +#define SPELL_CATACLYSMIC_BOLT 38441 +#define SPELL_POWER_OF_SHARKKIS 38455 +#define SPELL_POWER_OF_TIDALVESS 38452 +#define SPELL_POWER_OF_CARIBDIS 38451 +#define SPELL_ENRAGE 24318 +//Sharkkis spells +#define SPELL_LEECHING_THROW 29436 +#define SPELL_THE_BEAST_WITHIN 38373 +//Tidalvess spells +#define SPELL_FROST_SHOCK 38234 +//Caribdis Spells +#define SPELL_WATER_BOLT_VOLLEY 38335 +#define SPELL_TIDAL_SURGE 38353 +#define SPELL_HEAL 41386 + +#define SAY_AGGRO "Guards, attention! We have visitors..." +#define SAY_SLAY1 "I am rid of you." +#define SAY_GAIN_ABILITY1 "I am more powerful than ever!" +#define SAY_GAIN_ABILITY2 "Go on, kill them! I'll be the better for it!" +#define SAY_GAIN_ABILITY3 "More knowledge, more power!" +#define SAY_DEATH "Her ... excellency ... awaits!" + +#define SOUND_AGGRO 11277 +#define SOUND_PLYR_ATTACK 11278 +#define SOUND_GAIN_ABILITY1 11279 +#define SOUND_GAIN_ABILITY2 11280 +#define SOUND_GAIN_ABILITY3 11281 +#define SOUND_SLAY1 11282 +#define SOUND_SLAY2 11283 +#define SOUND_SLAY3 11284 +#define SOUND_DEATH 11285 + +//entry and position for Seer Olum +#define SEER_OLUM 22820 +#define OLUM_X 446.78f +#define OLUM_Y -542.76f +#define OLUM_Z -7.54773f +#define OLUM_O 0.401581f + +//Fathom-Lord Karathress AI +struct MANGOS_DLL_DECL boss_fathomlord_karathressAI : public ScriptedAI +{ + boss_fathomlord_karathressAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Advisors[0] = 0; + Advisors[1] = 0; + Advisors[2] = 0; + Reset(); + } + + ScriptedInstance* pInstance; + + uint32 CataclysmicBolt_Timer; + uint32 Enrage_Timer; + + uint64 Advisors[3]; + + void Reset() + { + CataclysmicBolt_Timer = 10000; + Enrage_Timer = 600000; //10 minutes + + Creature* Advisor; + for(uint8 i = 0; i < 3; ++i) + if(Advisors[i]) + { + Advisor = ((Creature*)Unit::GetUnit(*m_creature, Advisors[i])); + if(Advisor) + { + if(Advisor->isAlive()) + { + Advisor->DealDamage(Advisor, Advisor->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + Advisor->RemoveCorpse(); + Advisor->Respawn(); + } + Advisor->AI()->EnterEvadeMode(); + } + } + + if( pInstance ) + pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); + } + + void EventSharkkisDeath() + { + DoPlaySoundToSet(m_creature, SOUND_GAIN_ABILITY1); + DoYell(SAY_GAIN_ABILITY1, LANG_UNIVERSAL, NULL); + DoCast(m_creature, SPELL_POWER_OF_SHARKKIS); + } + + void EventTidalvessDeath() + { + DoPlaySoundToSet(m_creature, SOUND_GAIN_ABILITY2); + DoYell(SAY_GAIN_ABILITY2, LANG_UNIVERSAL, NULL); + DoCast(m_creature, SPELL_POWER_OF_TIDALVESS); + } + + void EventCaribdisDeath() + { + DoPlaySoundToSet(m_creature, SOUND_GAIN_ABILITY3); + DoYell(SAY_GAIN_ABILITY3, LANG_UNIVERSAL, NULL); + DoCast(m_creature, SPELL_POWER_OF_CARIBDIS); + } + + void GetAdvisors() + { + if(!pInstance) + return; + + Advisors[0] = pInstance->GetData64(DATA_SHARKKIS); + Advisors[1] = pInstance->GetData64(DATA_TIDALVESS); + Advisors[2] = pInstance->GetData64(DATA_CARIBDIS); + } + + void StartEvent(Unit *who) + { + if(!pInstance) + return; + + GetAdvisors(); + + DoPlaySoundToSet(m_creature, SOUND_AGGRO); + DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL); + + pInstance->SetData64(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); + pInstance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); + } + + void KilledUnit(Unit *victim) + { + switch(rand()%3) + { + case 0: + DoPlaySoundToSet(m_creature, SOUND_SLAY1); + DoYell(SAY_SLAY1, LANG_UNIVERSAL, NULL); + break; + case 1: + DoPlaySoundToSet(m_creature, SOUND_SLAY2); + break; + case 2: + DoPlaySoundToSet(m_creature, SOUND_SLAY3); + break; + } + } + + void JustDied(Unit *killer) + { + DoPlaySoundToSet(m_creature, SOUND_DEATH); + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + + if( pInstance ) + pInstance->SetData(DATA_FATHOMLORDKARATHRESSEVENT, NOT_STARTED); + + //support for quest 10944 + m_creature->SummonCreature(SEER_OLUM, OLUM_X, OLUM_Y, OLUM_Z, OLUM_O, TEMPSUMMON_TIMED_DESPAWN, 3600000); + } + + void Aggro(Unit *who) + { + StartEvent(who); + } + + void UpdateAI(const uint32 diff) + { + //Only if not incombat check if the event is started + if(!InCombat && pInstance && pInstance->GetData(DATA_KARATHRESSEVENT)) + { + Unit* target = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_KARATHRESSEVENT_STARTER)); + + if(target) + { + DoStartAttackAndMovement(target); + + GetAdvisors(); + + DoPlaySoundToSet(m_creature, SOUND_AGGRO); + DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL); + } + } + + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //someone evaded! + if(pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) + EnterEvadeMode(); + + //CataclysmicBolt_Timer + if(CataclysmicBolt_Timer < diff) + { + //select a random unit other than the main tank + Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 1); + + //if there aren't other units, cast on the tank + if(!target) + target = m_creature->getVictim(); + + int32 dmg = target->GetMaxHealth() / 2; + m_creature->CastCustomSpell(target, SPELL_CATACLYSMIC_BOLT, &dmg, NULL, NULL, false, NULL, NULL, m_creature->GetGUID()); + + CataclysmicBolt_Timer = 10000; + }else CataclysmicBolt_Timer -= diff; + + //Enrage_Timer + if(Enrage_Timer < diff) + { + DoCast(m_creature, SPELL_ENRAGE); + Enrage_Timer = 90000; + }else Enrage_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Fathom-Guard Sharkkis AI +struct MANGOS_DLL_DECL boss_fathomguard_sharkkisAI : public ScriptedAI +{ + boss_fathomguard_sharkkisAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + + uint32 LeechingThrow_Timer; + uint32 TheBeastWithin_Timer; + + void Reset() + { + LeechingThrow_Timer = 20000; + TheBeastWithin_Timer = 30000; + + if( pInstance ) + pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); + } + + void JustDied(Unit *victim) + { + if(pInstance) + { + Creature *Karathress = NULL; + Karathress = (Creature*)(Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_KARATHRESS))); + + if(Karathress) + ((boss_fathomlord_karathressAI*)Karathress->AI())->EventSharkkisDeath(); + } + } + + void Aggro(Unit *who) + { + if(pInstance) + { + pInstance->SetData64(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); + pInstance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); + } + } + + void UpdateAI(const uint32 diff) + { + //Only if not incombat check if the event is started + if(!InCombat && pInstance && pInstance->GetData(DATA_KARATHRESSEVENT)) + { + Unit* target = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_KARATHRESSEVENT_STARTER)); + + if(target) + { + DoStartAttackAndMovement(target); + } + } + + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //someone evaded! + if(pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) + EnterEvadeMode(); + + //LeechingThrow_Timer + if(LeechingThrow_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_LEECHING_THROW); + LeechingThrow_Timer = 20000; + }else LeechingThrow_Timer -= diff; + + //TheBeastWithin_Timer + if(TheBeastWithin_Timer < diff) + { + DoCast(m_creature, SPELL_THE_BEAST_WITHIN); + TheBeastWithin_Timer = 30000; + }else TheBeastWithin_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Fathom-Guard Tidalvess AI +struct MANGOS_DLL_DECL boss_fathomguard_tidalvessAI : public ScriptedAI +{ + boss_fathomguard_tidalvessAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + + uint32 FrostShock_Timer; + + void Reset() + { + FrostShock_Timer = 25000; + + if( pInstance ) + pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); + } + + void JustDied(Unit *victim) + { + if(pInstance) + { + Creature *Karathress = NULL; + Karathress = (Creature*)(Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_KARATHRESS))); + + if(Karathress) + ((boss_fathomlord_karathressAI*)Karathress->AI())->EventTidalvessDeath(); + } + } + + void Aggro(Unit *who) + { + if(pInstance) + { + pInstance->SetData64(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); + pInstance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); + } + } + + void UpdateAI(const uint32 diff) + { + //Only if not incombat check if the event is started + if(!InCombat && pInstance && pInstance->GetData(DATA_KARATHRESSEVENT)) + { + Unit* target = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_KARATHRESSEVENT_STARTER)); + + if(target) + { + DoStartAttackAndMovement(target); + } + } + + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //someone evaded! + if(pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) + EnterEvadeMode(); + + //FrostShock_Timer + if(FrostShock_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_FROST_SHOCK); + FrostShock_Timer = 25000+rand()%5000; + }else FrostShock_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Fathom-Guard Caribdis AI +struct MANGOS_DLL_DECL boss_fathomguard_caribdisAI : public ScriptedAI +{ + boss_fathomguard_caribdisAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + + uint32 WaterBoltVolley_Timer; + uint32 TidalSurge_Timer; + uint32 Heal_Timer; + + void Reset() + { + WaterBoltVolley_Timer = 35000; + TidalSurge_Timer = 15000+rand()%5000; + Heal_Timer = 55000; + + if(pInstance) + pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); + } + + void JustDied(Unit *victim) + { + if(pInstance) + { + Creature *Karathress = NULL; + Karathress = (Creature*)(Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_KARATHRESS))); + + if(Karathress) + ((boss_fathomlord_karathressAI*)Karathress->AI())->EventCaribdisDeath(); + } + } + + void Aggro(Unit *who) + { + if(pInstance) + { + pInstance->SetData64(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); + pInstance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); + } + } + + void UpdateAI(const uint32 diff) + { + //Only if not incombat check if the event is started + if(!InCombat && pInstance && pInstance->GetData(DATA_KARATHRESSEVENT)) + { + Unit* target = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_KARATHRESSEVENT_STARTER)); + + if(target) + { + DoStartAttackAndMovement(target); + } + } + + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //someone evaded! + if(pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) + EnterEvadeMode(); + + //WaterBoltVolley_Timer + if(WaterBoltVolley_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_WATER_BOLT_VOLLEY); + WaterBoltVolley_Timer = 30000; + }else WaterBoltVolley_Timer -= diff; + + //TidalSurge_Timer + if(TidalSurge_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_TIDAL_SURGE); + TidalSurge_Timer = 15000+rand()%5000; + }else TidalSurge_Timer -= diff; + + //Heal_Timer + if(Heal_Timer < diff) + { + // It can be cast on any of the mobs + Unit *pUnit = NULL; + + if(pInstance) + { + switch(rand()%4) + { + case 0: + pUnit = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_KARATHRESS)); + break; + case 1: + pUnit = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_SHARKKIS)); + break; + case 2: + pUnit = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_TIDALVESS)); + break; + case 3: + pUnit = m_creature; + break; + } + }else pUnit = m_creature; + + if(pUnit && pUnit->isAlive()) + DoCast(pUnit, SPELL_HEAL); + + Heal_Timer = 60000; + }else Heal_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_fathomlord_karathress(Creature *_Creature) +{ + return new boss_fathomlord_karathressAI (_Creature); +} + +CreatureAI* GetAI_boss_fathomguard_sharkkis(Creature *_Creature) +{ + return new boss_fathomguard_sharkkisAI (_Creature); +} + +CreatureAI* GetAI_boss_fathomguard_tidalvess(Creature *_Creature) +{ + return new boss_fathomguard_tidalvessAI (_Creature); +} + +CreatureAI* GetAI_boss_fathomguard_caribdis(Creature *_Creature) +{ + return new boss_fathomguard_caribdisAI (_Creature); +} + +void AddSC_boss_fathomlord_karathress() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_fathomlord_karathress"; + newscript->GetAI = GetAI_boss_fathomlord_karathress; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_fathomguard_sharkkis"; + newscript->GetAI = GetAI_boss_fathomguard_sharkkis; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_fathomguard_tidalvess"; + newscript->GetAI = GetAI_boss_fathomguard_tidalvess; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_fathomguard_caribdis"; + newscript->GetAI = GetAI_boss_fathomguard_caribdis; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_hydross_the_unstable.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_hydross_the_unstable.cpp new file mode 100644 index 00000000000..d9bc9429d14 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_hydross_the_unstable.cpp @@ -0,0 +1,357 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Hydross_The_Unstable +SD%Complete: 90 +SDComment: Some details and adjustments left to do, probably nothing major. Spawns may be spawned in different way/location. +SDCategory: Coilfang Resevoir, Serpent Shrine Cavern +EndScriptData */ + +#include "precompiled.h" +#include "def_serpent_shrine.h" + +#define SWITCH_RADIUS 18 + +#define MODEL_CORRUPT 20609 +#define MODEL_CLEAN 20162 + +#define SPELL_WATER_TOMB 38235 +#define SPELL_MARK_OF_HYDROSS1 38215 +#define SPELL_MARK_OF_HYDROSS2 38216 +#define SPELL_MARK_OF_HYDROSS3 38217 +#define SPELL_MARK_OF_HYDROSS4 38218 +#define SPELL_MARK_OF_HYDROSS5 38231 +#define SPELL_MARK_OF_HYDROSS6 40584 +#define SPELL_MARK_OF_CORRUPTION1 38219 +#define SPELL_MARK_OF_CORRUPTION2 38220 +#define SPELL_MARK_OF_CORRUPTION3 38221 +#define SPELL_MARK_OF_CORRUPTION4 38222 +#define SPELL_MARK_OF_CORRUPTION5 38230 +#define SPELL_MARK_OF_CORRUPTION6 40583 +#define SPELL_VILE_SLUDGE 38246 +#define SPELL_ENRAGE 27680 //this spell need verification +#define SPELL_SUMMON_WATER_ELEMENT 36459 //not in use yet(in use ever?) +#define SPELL_ELEMENTAL_SPAWNIN 25035 +//#define SPELL_BLUE_BEAM 38015 //channeled Hydross Beam Helper (not in use yet) + +#define ENTRY_PURE_SPAWN 22035 +#define ENTRY_TAINTED_SPAWN 22036 + +#define SAY_AGGRO "I cannot allow you to interfere!" +#define SAY_SWITCH_TO_CLEAN "Better, much better." +#define SAY_CLEAN_SLAY1 "They have forced me to this..." +#define SAY_CLEAN_SLAY2 "I have no choice." +#define SAY_CLEAN_DEATH "I am... released..." +#define SAY_SWITCH_TO_CORRUPT "Aaghh, the poison..." +#define SAY_CORRUPT_SLAY1 "I will purge you from this place." +#define SAY_CORRUPT_SLAY2 "You are no better than they!" +#define SAY_CORRUPT_DEATH "You are the disease, not I" + +#define SOUND_AGGRO 11289 +#define SOUND_SWITCH_TO_CLEAN 11290 +#define SOUND_CLEAN_SLAY1 11291 +#define SOUND_CLEAN_SLAY2 11292 +#define SOUND_CLEAN_DEATH 11293 +#define SOUND_SWITCH_TO_CORRUPT 11297 +#define SOUND_CORRUPT_SLAY1 11298 +#define SOUND_CORRUPT_SLAY2 11299 +#define SOUND_CORRUPT_DEATH 11300 + +#define HYDROSS_X -239.439 +#define HYDROSS_Y -363.481 + +#define SPAWN_X_DIFF1 6.934003 +#define SPAWN_Y_DIFF1 -11.255012 +#define SPAWN_X_DIFF2 -6.934003 +#define SPAWN_Y_DIFF2 11.255012 +#define SPAWN_X_DIFF3 -12.577011 +#define SPAWN_Y_DIFF3 -4.72702 +#define SPAWN_X_DIFF4 12.577011 +#define SPAWN_Y_DIFF4 4.72702 + +struct MANGOS_DLL_DECL boss_hydross_the_unstableAI : public ScriptedAI +{ + boss_hydross_the_unstableAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + + uint32 PosCheck_Timer; + uint32 MarkOfHydross_Timer; + uint32 MarkOfCorruption_Timer; + uint32 WaterTomb_Timer; + uint32 VileSludge_Timer; + uint32 MarkOfHydross_Count; + uint32 MarkOfCorruption_Count; + uint32 EnrageTimer; + bool CorruptedForm; + + void Reset() + { + PosCheck_Timer = 2500; + MarkOfHydross_Timer = 15000; + MarkOfCorruption_Timer = 15000; + WaterTomb_Timer = 7000; + VileSludge_Timer = 7000; + MarkOfHydross_Count = 0; + MarkOfCorruption_Count = 0; + EnrageTimer = 600000; + + CorruptedForm = false; + m_creature->SetMeleeDamageSchool(SPELL_SCHOOL_FROST); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); + + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_CLEAN); + + if( pInstance ) + pInstance->SetData(DATA_HYDROSSTHEUNSTABLEEVENT, NOT_STARTED); + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO); + + if( pInstance ) + pInstance->SetData(DATA_HYDROSSTHEUNSTABLEEVENT, IN_PROGRESS); + } + + void KilledUnit(Unit *victim) + { + if(CorruptedForm) + switch(rand()%2) + { + case 0: + DoYell(SAY_CORRUPT_SLAY1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_CORRUPT_SLAY1); + break; + case 1: + DoYell(SAY_CORRUPT_SLAY2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_CORRUPT_SLAY2); + break; + } + else + { + switch(rand()%2) + { + case 0: + DoYell(SAY_CLEAN_SLAY1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_CLEAN_SLAY1); + break; + case 1: + DoYell(SAY_CLEAN_SLAY2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_CLEAN_SLAY2); + break; + } + } + } + + void JustSummoned(Creature* summoned) + { + if( summoned->GetEntry() == ENTRY_PURE_SPAWN ) + summoned->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); + if( summoned->GetEntry() == ENTRY_TAINTED_SPAWN ) + summoned->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true); + + summoned->CastSpell(summoned,SPELL_ELEMENTAL_SPAWNIN,true); + } + + void JustDied(Unit *victim) + { + if( CorruptedForm ) + { + DoYell(SAY_CORRUPT_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_CORRUPT_DEATH); + } + else + { + DoYell(SAY_CLEAN_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_CLEAN_DEATH); + } + + if( pInstance ) + pInstance->SetData(DATA_HYDROSSTHEUNSTABLEEVENT, NOT_STARTED); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + // corrupted form + if( CorruptedForm ) + { + //MarkOfCorruption_Timer + if( MarkOfCorruption_Timer < diff ) + { + if( MarkOfCorruption_Count <= 5 ) + { + uint32 mark_spell; + + switch(MarkOfCorruption_Count) + { + case 0: mark_spell = SPELL_MARK_OF_CORRUPTION1; break; + case 1: mark_spell = SPELL_MARK_OF_CORRUPTION2; break; + case 2: mark_spell = SPELL_MARK_OF_CORRUPTION3; break; + case 3: mark_spell = SPELL_MARK_OF_CORRUPTION4; break; + case 4: mark_spell = SPELL_MARK_OF_CORRUPTION5; break; + case 5: mark_spell = SPELL_MARK_OF_CORRUPTION6; break; + } + + DoCast(m_creature->getVictim(), mark_spell); + + if( MarkOfCorruption_Count < 5 ) + MarkOfCorruption_Count++; + } + + MarkOfCorruption_Timer = 15000; + }else MarkOfCorruption_Timer -= diff; + + //VileSludge_Timer + if( VileSludge_Timer < diff ) + { + Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if( target ) + DoCast(target, SPELL_VILE_SLUDGE); + + VileSludge_Timer = 15000; + }else VileSludge_Timer -= diff; + + //PosCheck_Timer + if( PosCheck_Timer < diff ) + { + if( m_creature->GetDistance2d(HYDROSS_X, HYDROSS_Y) < SWITCH_RADIUS ) + { + // switch to clean form + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_CLEAN); + CorruptedForm = false; + MarkOfHydross_Count = 0; + + DoYell(SAY_SWITCH_TO_CLEAN, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SWITCH_TO_CLEAN); + DoResetThreat(); + + // spawn 4 adds + DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF1, SPAWN_Y_DIFF1, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF2, SPAWN_Y_DIFF2, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF3, SPAWN_Y_DIFF3, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF4, SPAWN_Y_DIFF4, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + + m_creature->SetMeleeDamageSchool(SPELL_SCHOOL_FROST); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); + } + + PosCheck_Timer = 2500; + }else PosCheck_Timer -=diff; + } + // clean form + else + { + //MarkOfHydross_Timer + if( MarkOfHydross_Timer < diff ) + { + if( MarkOfHydross_Count <= 5 ) + { + uint32 mark_spell; + + switch(MarkOfHydross_Count) + { + case 0: mark_spell = SPELL_MARK_OF_HYDROSS1; break; + case 1: mark_spell = SPELL_MARK_OF_HYDROSS2; break; + case 2: mark_spell = SPELL_MARK_OF_HYDROSS3; break; + case 3: mark_spell = SPELL_MARK_OF_HYDROSS4; break; + case 4: mark_spell = SPELL_MARK_OF_HYDROSS5; break; + case 5: mark_spell = SPELL_MARK_OF_HYDROSS6; break; + } + + DoCast(m_creature->getVictim(), mark_spell); + + if( MarkOfHydross_Count < 5 ) + MarkOfHydross_Count++; + } + + MarkOfHydross_Timer = 15000; + }else MarkOfHydross_Timer -= diff; + + //WaterTomb_Timer + if( WaterTomb_Timer < diff ) + { + Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if( target ) + DoCast(target, SPELL_WATER_TOMB); + + WaterTomb_Timer = 7000; + }else WaterTomb_Timer -= diff; + + //PosCheck_Timer + if( PosCheck_Timer < diff ) + { + if( m_creature->GetDistance2d(HYDROSS_X, HYDROSS_Y) >= SWITCH_RADIUS ) + { + // switch to corrupted form + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_CORRUPT); + MarkOfCorruption_Count = 0; + CorruptedForm = true; + + DoYell(SAY_SWITCH_TO_CORRUPT, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SWITCH_TO_CORRUPT); + DoResetThreat(); + + // spawn 4 adds + DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF1, SPAWN_Y_DIFF1, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF2, SPAWN_Y_DIFF2, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF3, SPAWN_Y_DIFF3, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF4, SPAWN_Y_DIFF4, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + + m_creature->SetMeleeDamageSchool(SPELL_SCHOOL_NATURE); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); + } + + PosCheck_Timer = 2500; + }else PosCheck_Timer -=diff; + } + + //EnrageTimer + if( EnrageTimer < diff ) + { + DoCast(m_creature, SPELL_ENRAGE); + EnrageTimer = 60000; + }else EnrageTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_hydross_the_unstable(Creature *_Creature) +{ + return new boss_hydross_the_unstableAI (_Creature); +} + +void AddSC_boss_hydross_the_unstable() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_hydross_the_unstable"; + newscript->GetAI = GetAI_boss_hydross_the_unstable; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp new file mode 100644 index 00000000000..b078c332251 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp @@ -0,0 +1,940 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA + */ + +/* ScriptData +SDName: Boss_Lady_Vashj +SD%Complete: 99 +SDComment: Missing blizzlike Shield Generators coords +SDCategory: Coilfang Resevoir, Serpent Shrine Cavern +EndScriptData */ + +#include "precompiled.h" +#include "def_serpent_shrine.h" +#include "../../../creature/simple_ai.h" +#include "Item.h" +#include "Spell.h" + +#define SPELL_MULTI_SHOT 38310 +#define SPELL_SHOCK_BLAST 38509 +#define SPELL_ENTANGLE 38316 +#define SPELL_STATIC_CHARGE_TRIGGER 38280 +#define SPELL_FORKED_LIGHTNING 40088 +#define SPELL_SHOOT 40873 +#define SPELL_POISON_BOLT 40095 +#define SPELL_TOXIC_SPORES 38575 +#define SPELL_MAGIC_BARRIER 38112 + +#define SAY_INTRO "Water is life. It has become a rare commodity here in Outland. A commodity that we alone shall control. We are the Highborne, and the time has come at last for us to retake our rightful place in the world!" +#define SAY_AGGRO1 "I'll split you from stem to stern! " +#define SAY_AGGRO2 "Victory to Lord Illidan!" +#define SAY_AGGRO3 "I spit on you, surface filth!" +#define SAY_AGGRO4 "Death to the outsiders!" +#define SAY_PHASE1 "I did not wish to lower myself by engaging your kind, but you leave me little choice!" +#define SAY_PHASE2 "The time is now! Leave none standing!" +#define SAY_PHASE3 "You may want to take cover." +#define SAY_BOWSHOT1 "Straight to the heart!" +#define SAY_BOWSHOT2 "Seek your mark!" +#define SAY_SLAY1 "Your time ends now!" +#define SAY_SLAY2 "You have failed!" +#define SAY_DEATH "Lord Illidan, I... I am... sorry." + +#define SOUND_INTRO 11531 +#define SOUND_AGGRO1 11532 +#define SOUND_AGGRO2 11533 +#define SOUND_AGGRO3 11534 +#define SOUND_AGGRO4 11535 +#define SOUND_PHASE1 11538 +#define SOUND_PHASE2 11539 +#define SOUND_PHASE3 11540 +#define SOUND_BOWSHOT1 11536 +#define SOUND_BOWSHOT2 11537 +#define SOUND_SLAY1 11541 +#define SOUND_SLAY2 11542 +#define SOUND_DEATH 11544 + +#define MIDDLE_X 30.134 +#define MIDDLE_Y -923.65 +#define MIDDLE_Z 42.9 + +#define SPOREBAT_X 30.977156 +#define SPOREBAT_Y -925.297761 +#define SPOREBAT_Z 77.176567 +#define SPOREBAT_O 5.223932 + +#define SHIED_GENERATOR_CHANNEL 19870 +#define ENCHANTED_ELEMENTAL 21958 +#define TAINTED_ELEMENTAL 22009 +#define COILFANG_STRIDER 22056 +#define COILFANG_ELITE 22055 +#define FATHOM_SPOREBAT 22140 + +float ElementPos[8][4] = +{ + {8.3, -835.3, 21.9, 5}, + {53.4, -835.3, 21.9, 4.5}, + {96, -861.9, 21.8, 4}, + {96, -986.4, 21.4, 2.5}, + {54.4, -1010.6, 22, 1.8}, + {9.8, -1012, 21.7, 1.4}, + {-35, -987.6, 21.5, 0.8}, + {-58.9, -901.6, 21.5, 6} +}; + +float CoilfangElitePos[3][4] = +{ + {28.84, -923.28, 42.9, 6}, + {31.183281, -953.502625, 41.523602, 1.640957}, + {58.895180, -923.124268, 41.545307, 3.152848} +}; + +float CoilfangStriderPos[3][4] = +{ + {66.427010, -948.778503, 41.262245, 2.584220}, + {7.513962, -959.538208, 41.300422, 1.034629}, + {-12.843201, -907.798401, 41.239620, 6.087094} +}; + +float ShieldGeneratorChannelPos[4][4] = +{ + {49.6262, -902.181, 43.0975, 3.95683}, + {10.988, -901.616, 42.5371, 5.4373}, + {10.3859, -944.036, 42.5446, 0.779888}, + {49.3126, -943.398, 42.5501, 2.40174} +}; + +//Lady Vashj AI +struct MANGOS_DLL_DECL boss_lady_vashjAI : public ScriptedAI +{ + boss_lady_vashjAI (Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance *pInstance; + + uint64 ShieldGeneratorChannel[4]; + + uint32 ShockBlast_Timer; + uint32 Entangle_Timer; + uint32 StaticCharge_Timer; + uint32 ForkedLightning_Timer; + uint32 Check_Timer; + uint32 EnchantedElemental_Timer; + uint32 TaintedElemental_Timer; + uint32 CoilfangElite_Timer; + uint32 CoilfangStrider_Timer; + uint32 SummonSporebat_Timer; + uint32 SummonSporebat_StaticTimer; + uint8 EnchantedElemental_Pos; + uint8 Phase; + + bool Entangle; + + void Reset() + { + ShockBlast_Timer = 1+rand()%60000; + Entangle_Timer = 30000; + StaticCharge_Timer = 10000+rand()%15000; + ForkedLightning_Timer = 2000; + Check_Timer = 1000; + EnchantedElemental_Timer = 5000; + TaintedElemental_Timer = 50000; + CoilfangElite_Timer = 45000+rand()%5000; + CoilfangStrider_Timer = 60000+rand()%10000; + SummonSporebat_Timer = 10000; + SummonSporebat_StaticTimer = 30000; + EnchantedElemental_Pos = 0; + Phase = 0; + + Entangle = false; + + if(pInstance) + pInstance->SetData(DATA_LADYVASHJEVENT, 0); + + ShieldGeneratorChannel[0] = 0; + ShieldGeneratorChannel[1] = 0; + ShieldGeneratorChannel[2] = 0; + ShieldGeneratorChannel[3] = 0; + + } + + //Called when a tainted elemental dies + void EventTaintedElementalDeath() + { + //the next will spawn 50 seconds after the previous one's death + if(TaintedElemental_Timer > 50000) + TaintedElemental_Timer = 50000; + } + + void KilledUnit(Unit *victim) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_SLAY1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY1); + break; + + case 1: + DoPlaySoundToSet(m_creature, SOUND_SLAY1); + DoYell(SAY_SLAY2, LANG_UNIVERSAL, NULL); + break; + } + } + + void JustDied(Unit *victim) + { + DoPlaySoundToSet(m_creature, SOUND_DEATH); + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + + if(pInstance) + pInstance->SetData(DATA_LADYVASHJEVENT, 0); + } + + void StartEvent() + { + switch(rand()%4) + { + case 0: + DoPlaySoundToSet(m_creature, SOUND_AGGRO1); + DoYell(SAY_AGGRO1, LANG_UNIVERSAL, NULL); + break; + case 1: + DoPlaySoundToSet(m_creature, SOUND_AGGRO2); + DoYell(SAY_AGGRO2, LANG_UNIVERSAL, NULL); + break; + case 2: + DoPlaySoundToSet(m_creature, SOUND_AGGRO3); + DoYell(SAY_AGGRO3, LANG_UNIVERSAL, NULL); + break; + case 3: + DoPlaySoundToSet(m_creature, SOUND_AGGRO4); + DoYell(SAY_AGGRO4, LANG_UNIVERSAL, NULL); + break; + } + + Phase = 1; + + if(pInstance) + pInstance->SetData(DATA_LADYVASHJEVENT, 1); + } + + void Aggro(Unit *who) + { + //Begin melee attack if we are within range + if(Phase != 2) + DoStartAttackAndMovement(who); + + StartEvent(); + } + + void CastShootOrMultishot() + { + switch(rand()%2) + { + case 0: + //Shoot + //Used in Phases 1 and 3 after Entangle or while having nobody in melee range. A shot that hits her target for 4097-5543 Physical damage. + DoCast(m_creature->getVictim(), SPELL_SHOOT); + break; + case 1: + //Multishot + //Used in Phases 1 and 3 after Entangle or while having nobody in melee range. A shot that hits 1 person and 4 people around him for 6475-7525 physical damage. + DoCast(m_creature->getVictim(), SPELL_MULTI_SHOT); + break; + } + + if(rand()%3) + { + switch(rand()%2) + { + case 0: + DoPlaySoundToSet(m_creature, SOUND_BOWSHOT1); + DoYell(SAY_BOWSHOT1, LANG_UNIVERSAL, NULL); + break; + case 1: + DoPlaySoundToSet(m_creature, SOUND_BOWSHOT2); + DoYell(SAY_BOWSHOT2, LANG_UNIVERSAL, NULL); + break; + } + } + } + + void UpdateAI(const uint32 diff) + { + //to prevent abuses during phase 2 + if(Phase == 2 && !m_creature->getVictim() && InCombat) + EnterEvadeMode(); + + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if(Phase == 1 || Phase == 3) + { + //ShockBlast_Timer + if (ShockBlast_Timer < diff) + { + //Shock Burst + //Randomly used in Phases 1 and 3 on Vashj's target, it's a Shock spell doing 8325-9675 nature damage and stunning the target for 5 seconds, during which she will not attack her target but switch to the next person on the aggro list. + DoCast(m_creature->getVictim(), SPELL_SHOCK_BLAST); + m_creature->TauntApply(m_creature->getVictim()); + + ShockBlast_Timer = 1000+rand()%14000; //random cooldown + }else ShockBlast_Timer -= diff; + + //StaticCharge_Timer + if(StaticCharge_Timer < diff) + { + //Static Charge + //Used on random people (only 1 person at any given time) in Phases 1 and 3, it's a debuff doing 2775 to 3225 Nature damage to the target and everybody in about 5 yards around it, every 1 seconds for 30 seconds. It can be removed by Cloak of Shadows, Iceblock, Divine Shield, etc, but not by Cleanse or Dispel Magic. + Unit *target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + + if(target && !target->HasAura(SPELL_STATIC_CHARGE_TRIGGER, 0)) + //cast Static Charge every 2 seconds for 20 seconds + DoCast(target, SPELL_STATIC_CHARGE_TRIGGER); + + StaticCharge_Timer = 10000+rand()%20000; //blizzlike + }else StaticCharge_Timer -= diff; + + //Entangle_Timer + if (Entangle_Timer < diff) + { + if(!Entangle) + { + //Entangle + //Used in Phases 1 and 3, it casts Entangling Roots on everybody in a 15 yard radius of Vashj, immobilzing them for 10 seconds and dealing 500 damage every 2 seconds. It's not a magic effect so it cannot be dispelled, but is removed by various buffs such as Cloak of Shadows or Blessing of Freedom. + DoCast(m_creature->getVictim(), SPELL_ENTANGLE); + Entangle = true; + Entangle_Timer = 10000; + } + else + { + CastShootOrMultishot(); + Entangle = false; + Entangle_Timer = 20000+rand()%5000; + } + }else Entangle_Timer -= diff; + + //Phase 1 + if(Phase == 1) + { + //Start phase 2 + if ((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 70) + { + //Phase 2 begins when Vashj hits 70%. She will run to the middle of her platform and surround herself in a shield making her invulerable. + Phase = 2; + + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->GetMotionMaster()->Clear(); + m_creature->Relocate(MIDDLE_X, MIDDLE_Y, MIDDLE_Z); + m_creature->SendMonsterMove(MIDDLE_X, MIDDLE_Y, MIDDLE_Z, 0, 0, 0); + + m_creature->RemoveAllAuras(); + // This needs an entry in spell_script_target + DoCast(m_creature, SPELL_MAGIC_BARRIER, true); + + Creature *pCreature; + for(uint8 i = 0; i < 4; i++) + { + pCreature = m_creature->SummonCreature(SHIED_GENERATOR_CHANNEL, ShieldGeneratorChannelPos[i][0], ShieldGeneratorChannelPos[i][1], ShieldGeneratorChannelPos[i][2], ShieldGeneratorChannelPos[i][3], TEMPSUMMON_CORPSE_DESPAWN, 0); + if (pCreature) + ShieldGeneratorChannel[i] = pCreature->GetGUID(); + } + + DoPlaySoundToSet(m_creature, SOUND_PHASE2); + DoYell(SAY_PHASE2, LANG_UNIVERSAL, NULL); + } + } + //Phase 3 + else + { + //SummonSporebat_Timer + if(SummonSporebat_Timer < diff) + { + Creature *Sporebat = NULL; + Sporebat = m_creature->SummonCreature(FATHOM_SPOREBAT, SPOREBAT_X, SPOREBAT_Y, SPOREBAT_Z, SPOREBAT_O, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + + if(Sporebat) + { + Unit *target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target) + Sporebat->AI()->AttackStart(target); + } + + //summon sporebats faster and faster + if(SummonSporebat_StaticTimer > 1000) + SummonSporebat_StaticTimer -= 1000; + + SummonSporebat_Timer = SummonSporebat_StaticTimer; + }else SummonSporebat_Timer -= diff; + } + + //Melee attack + DoMeleeAttackIfReady(); + + //Check_Timer - used to check if somebody is in melee range + if(Check_Timer < diff) + { + bool InMeleeRange = false; + Unit *target; + std::list t_list = m_creature->getThreatManager().getThreatList(); + for(std::list::iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + target = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid()); + //if in melee range + if(target && target->IsWithinDistInMap(m_creature, 5)) + { + InMeleeRange = true; + break; + } + } + + //if nobody is in melee range + if(!InMeleeRange) + CastShootOrMultishot(); + + Check_Timer = 1000; + }else Check_Timer -= diff; + } + //Phase 2 + else + { + //ForkedLightning_Timer + if(ForkedLightning_Timer < diff) + { + //Forked Lightning + //Used constantly in Phase 2, it shoots out completely randomly targeted bolts of lightning which hit everybody in a roughtly 60 degree cone in front of Vashj for 2313-2687 nature damage. + Unit *target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + + if(!target) + target = m_creature->getVictim(); + + DoCast(target, SPELL_FORKED_LIGHTNING); + + ForkedLightning_Timer = 2000+rand()%6000; //blizzlike + }else ForkedLightning_Timer -= diff; + + //EnchantedElemental_Timer + if(EnchantedElemental_Timer < diff) + { + Creature *Elemental; + Elemental = m_creature->SummonCreature(ENCHANTED_ELEMENTAL, ElementPos[EnchantedElemental_Pos][0], ElementPos[EnchantedElemental_Pos][1], ElementPos[EnchantedElemental_Pos][2], ElementPos[EnchantedElemental_Pos][3], TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); + if(Elemental) + Elemental->GetMotionMaster()->MovePoint(0, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ()); + + if(EnchantedElemental_Pos == 7) + EnchantedElemental_Pos = 0; + else + EnchantedElemental_Pos++; + + EnchantedElemental_Timer = 10000+rand()%5000; + }else EnchantedElemental_Timer -= diff; + + //TaintedElemental_Timer + if(TaintedElemental_Timer < diff) + { + Creature *Tain_Elemental; + uint32 pos = rand()%8; + Tain_Elemental = m_creature->SummonCreature(TAINTED_ELEMENTAL, ElementPos[pos][0], ElementPos[pos][1], ElementPos[pos][2], ElementPos[pos][3], TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000); + if(Tain_Elemental) + { + Tain_Elemental->GetMotionMaster()->Clear(); + Tain_Elemental->GetMotionMaster()->MoveIdle(); + } + + TaintedElemental_Timer = 120000; + }else TaintedElemental_Timer -= diff; + + //CoilfangElite_Timer + if(CoilfangElite_Timer < diff) + { + Creature *CoilfangElite; + uint32 pos = rand()%3; + CoilfangElite = m_creature->SummonCreature(COILFANG_ELITE, CoilfangElitePos[pos][0], CoilfangElitePos[pos][1], CoilfangElitePos[pos][2], CoilfangElitePos[pos][3], TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 45000); + if(CoilfangElite) + { + Unit *target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target) + CoilfangElite->AI()->AttackStart(target); + } + + CoilfangElite_Timer = 45000+rand()%5000; //wowwiki says 50 seconds, bosskillers says 45 + }else CoilfangElite_Timer -= diff; + + //CoilfangStrider_Timer + if(CoilfangStrider_Timer < diff) + { + Creature *CoilfangStrider; + uint32 pos = rand()%3; + CoilfangStrider = m_creature->SummonCreature(COILFANG_STRIDER, CoilfangStriderPos[pos][0], CoilfangStriderPos[pos][1], CoilfangStriderPos[pos][2], CoilfangStriderPos[pos][3], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + if(CoilfangStrider) + { + Unit *target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target) + CoilfangStrider->AI()->AttackStart(target); + } + + CoilfangStrider_Timer = 60000+rand()%10000; //wowwiki says 60 seconds, bosskillers says 60-70 + }else CoilfangStrider_Timer -= diff; + + //Check_Timer + if(Check_Timer < diff) + { + //Start Phase 3 + if(pInstance && pInstance->GetData(DATA_CANSTARTPHASE3)) + { + //set life 50% + m_creature->SetHealth(m_creature->GetMaxHealth()/2); + + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->RemoveAurasDueToSpell(SPELL_MAGIC_BARRIER); + + DoPlaySoundToSet(m_creature, SOUND_PHASE3); + DoYell(SAY_PHASE3, LANG_UNIVERSAL, NULL); + + Phase = 3; + + //return to the tank + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + } + Check_Timer = 1000; + }else Check_Timer -= diff; + } + } +}; + +//Enchanted Elemental +//If one of them reaches Vashj he will increase her damage done by 5%. +struct MANGOS_DLL_DECL mob_enchanted_elementalAI : public ScriptedAI +{ + mob_enchanted_elementalAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance *pInstance; + + uint32 Check_Timer; + uint32 Movement_Timer; + + void Reset() + { + Check_Timer = 5000; + Movement_Timer = 500; + } + + void Aggro(Unit *who) { return; } + + void MoveInLineOfSight(Unit *who) { return; } + + void UpdateAI(const uint32 diff) + { + //Check_Timer + if(Check_Timer < diff) + { + if(pInstance) + { + Unit *Vashj = NULL; + Vashj = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_LADYVASHJ)); + if(Vashj) + { + if(Vashj->IsWithinDistInMap(m_creature, 5)) + { + //increase lady vashj damage (+5%) + const CreatureInfo *cinfo = m_creature->GetCreatureInfo(); + Vashj->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 5))); + Vashj->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 5))); + m_creature->UpdateDamagePhysical(BASE_ATTACK); + + //call Unsummon() + m_creature->setDeathState(JUST_DIED); + } + else if(((boss_lady_vashjAI*)((Creature*)Vashj)->AI())->InCombat == false) + { + //call Unsummon() + m_creature->setDeathState(JUST_DIED); + } + } + } + else error_log("ERROR: Instance Data for Serpentshrine Caverns not set"); + Check_Timer = 1000; + }else Check_Timer -= diff; + } +}; + +//Tainted Elemental +//This mob has 7,900 life, doesn't move, and shoots Poison Bolts at one person anywhere in the area, doing 3,000 nature damage and placing a posion doing 2,000 damage every 2 seconds. He will switch targets often, or sometimes just hang on a single player, but there is nothing you can do about it except heal the damage and kill the Tainted Elemental +struct MANGOS_DLL_DECL mob_tainted_elementalAI : public ScriptedAI +{ + mob_tainted_elementalAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance *pInstance; + + uint32 PoisonBolt_Timer; + + void Reset() + { + PoisonBolt_Timer = 5000+rand()%5000; + } + + void JustDied(Unit *killer) + { + if(pInstance) + { + Creature *Vashj = NULL; + Vashj = (Creature*)(Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_LADYVASHJ))); + + if(Vashj) + ((boss_lady_vashjAI*)Vashj->AI())->EventTaintedElementalDeath(); + } + } + + void Aggro(Unit *who) + { + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || m_creature->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + float attackRadius = m_creature->GetAttackDistance(who); + if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) + { + if(who->HasStealthAura()) + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + m_creature->AddThreat(who, 0.1f); + } + } + } + + void UpdateAI(const uint32 diff) + { + //PoisonBolt_Timer + if(PoisonBolt_Timer < diff) + { + Unit *target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + + if(target && target->IsWithinDistInMap(m_creature, 30)) + DoCast(target, SPELL_POISON_BOLT); + + PoisonBolt_Timer = 5000+rand()%5000; + }else PoisonBolt_Timer -= diff; + } +}; + +//Fathom Sporebat +//Toxic Spores: Used in Phase 3 by the Spore Bats, it creates a contaminated green patch of ground, dealing about 2775-3225 nature damage every second to anyone who stands in it. +struct MANGOS_DLL_DECL mob_fathom_sporebatAI : public ScriptedAI +{ + mob_fathom_sporebatAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance *pInstance; + + uint32 ToxicSpore_Timer; + uint32 Check_Timer; + + void Reset() + { + m_creature->setFaction(14); + ToxicSpore_Timer = 5000; + Check_Timer = 1000; + } + + void Aggro(Unit *who) {} + + void UpdateAI (const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //ToxicSpore_Timer + if(ToxicSpore_Timer < diff) + { + Unit *target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + + //The Spores will hit you anywhere in the instance: underwater, at the elevator, at the entrance, wherever. + if(target) + DoCast(target, SPELL_TOXIC_SPORES); + + ToxicSpore_Timer = 20000+rand()%5000; + }else ToxicSpore_Timer -= diff; + + //Check_Timer + if(Check_Timer < diff) + { + if(pInstance) + { + //check if vashj is death + Unit *Vashj = NULL; + Vashj = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_LADYVASHJ)); + if(!Vashj || (Vashj && !Vashj->isAlive())) + { + //remove + m_creature->setDeathState(DEAD); + m_creature->RemoveCorpse(); + m_creature->setFaction(35); + } + } + + Check_Timer = 1000; + }else Check_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Coilfang Elite +//It's an elite Naga mob with 170,000 HP. It does about 5000 damage on plate, and has a nasty cleave hitting for about 7500 damage +CreatureAI* GetAI_mob_coilfang_elite(Creature *_Creature) +{ + SimpleAI* ai = new SimpleAI (_Creature); + + ai->Spell[0].Enabled = true; + ai->Spell[0].Spell_Id = 31345; //Cleave + ai->Spell[0].Cooldown = 15000; + ai->Spell[0].CooldownRandomAddition = 5000; + ai->Spell[0].First_Cast = 5000; + ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_RANDOM; + + ai->EnterEvadeMode(); + + return ai; +} + +//Coilfang Strifer +//It hits plate for about 8000 damage, has a Mind Blast spell doing about 3000 shadow damage, and a Psychic Scream Aura, which fears everybody in a 8 yard range of it every 2-3 seconds , for 5 seconds and increasing their movement speed by 150% during the fear. +CreatureAI* GetAI_mob_coilfang_strider(Creature *_Creature) +{ + SimpleAI* ai = new SimpleAI (_Creature); + + ai->Spell[0].Enabled = true; + ai->Spell[0].Spell_Id = 41374; //Mind Blast + ai->Spell[0].Cooldown = 30000; + ai->Spell[0].CooldownRandomAddition = 10000; + ai->Spell[0].First_Cast = 8000; + ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_TARGET; + + //Scream aura not implemented + + ai->EnterEvadeMode(); + + return ai; +} + +struct MANGOS_DLL_DECL mob_shield_generator_channelAI : public ScriptedAI +{ + mob_shield_generator_channelAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance *pInstance; + + uint32 Check_Timer; + bool Channeled; + + void Reset() + { + Check_Timer = 1000; + Channeled = false; + //invisible + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID , 11686); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void Aggro(Unit *who) { return; } + + void MoveInLineOfSight(Unit *who) { return; } + + void UpdateAI (const uint32 diff) + { + if(!pInstance) + return; + + if(!Channeled) + { + Unit *Vashj = NULL; + Vashj = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_LADYVASHJ)); + + if(Vashj && Vashj->isAlive()) + { + //start visual channel + m_creature->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, Vashj->GetGUID()); + m_creature->SetUInt32Value(UNIT_CHANNEL_SPELL, SPELL_MAGIC_BARRIER); + Channeled = true; + } + } + } +}; + +bool ItemUse_item_tainted_core(Player *player, Item* _Item, SpellCastTargets const& targets) +{ + ScriptedInstance *pInstance = ((ScriptedInstance*)player->GetInstanceData()); + + if(!pInstance) + { + player->GetSession()->SendNotification("ERROR: Instance script not initialized. Notify your administrator."); + error_log("ERROR: Lady Vashj Tainted Core: Instance Script Not Initialized"); + return true; + } + + Creature *Vashj = NULL; + Vashj = (Creature*)(Unit::GetUnit((*player), pInstance->GetData64(DATA_LADYVASHJ))); + if(Vashj && ((boss_lady_vashjAI*)Vashj->AI())->Phase == 2) + { + if(targets.getGOTarget() && targets.getGOTarget()->GetTypeId()==TYPEID_GAMEOBJECT) + { + uint32 identifier; + uint8 channel_identifier; + switch(targets.getGOTarget()->GetEntry()) + { + case 185052: + identifier = DATA_SHIELDGENERATOR1; + channel_identifier = 0; + break; + case 185053: + identifier = DATA_SHIELDGENERATOR2; + channel_identifier = 1; + break; + case 185051: + identifier = DATA_SHIELDGENERATOR3; + channel_identifier = 2; + break; + case 185054: + identifier = DATA_SHIELDGENERATOR4; + channel_identifier = 3; + break; + default: + return true; + break; + } + + if(pInstance->GetData(identifier)) + { + player->GetSession()->SendNotification("Already deactivated"); + return true; + } + + //get and remove channel + Unit *Channel = NULL; + Channel = Unit::GetUnit((*Vashj), ((boss_lady_vashjAI*)Vashj->AI())->ShieldGeneratorChannel[channel_identifier]); + if(Channel) + { + //call Unsummon() + Channel->setDeathState(JUST_DIED); + } + + pInstance->SetData(identifier, 1); + + //remove this item + player->DestroyItemCount(31088, 1, true); + } + } + return true; +} + +CreatureAI* GetAI_boss_lady_vashj(Creature *_Creature) +{ + return new boss_lady_vashjAI (_Creature); +} + +CreatureAI* GetAI_mob_enchanted_elemental(Creature *_Creature) +{ + return new mob_enchanted_elementalAI (_Creature); +} + +CreatureAI* GetAI_mob_tainted_elemental(Creature *_Creature) +{ + return new mob_tainted_elementalAI (_Creature); +} + +CreatureAI* GetAI_mob_fathom_sporebat(Creature *_Creature) +{ + return new mob_fathom_sporebatAI (_Creature); +} + +CreatureAI* GetAI_mob_shield_generator_channel(Creature *_Creature) +{ + return new mob_shield_generator_channelAI (_Creature); +} + +void AddSC_boss_lady_vashj() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_lady_vashj"; + newscript->GetAI = GetAI_boss_lady_vashj; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_enchanted_elemental"; + newscript->GetAI = GetAI_mob_enchanted_elemental; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_tainted_elemental"; + newscript->GetAI = GetAI_mob_tainted_elemental; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_fathom_sporebat"; + newscript->GetAI = GetAI_mob_fathom_sporebat; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_coilfang_elite"; + newscript->GetAI = GetAI_mob_coilfang_elite; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_coilfang_strider"; + newscript->GetAI = GetAI_mob_coilfang_strider; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_shield_generator_channel"; + newscript->GetAI = GetAI_mob_shield_generator_channel; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="item_tainted_core"; + newscript->pItemUse = ItemUse_item_tainted_core; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp new file mode 100644 index 00000000000..ea54e5ffcab --- /dev/null +++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp @@ -0,0 +1,359 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Leotheras_The_Blind +SD%Complete: 50 +SDComment: Missing Inner Demons +SDCategory: Coilfang Resevoir, Serpent Shrine Cavern +EndScriptData */ + +#include "precompiled.h" +#include "def_serpent_shrine.h" + +#define SPELL_WHIRLWIND 40653 +#define SPELL_CHAOS_BLAST 37675 +//#define SPELL_INSIDIOUS_WHISPER 37676 // useless - dummy effect that can't be implemented + +#define SAY_AGGRO "Finally my banishment ends!" +#define SAY_SWITCH_TO_DEMON "Be gone trifling elf. I'm in control now." +#define SAY_INNER_DEMONS "We all have our demons..." +#define SAY_DEMON_SLAY1 "I have no equal." +#define SAY_DEMON_SLAY2 "Perish, mortal." +#define SAY_DEMON_SLAY3 "Yes, YES! Ahahah!" +#define SAY_NIGHTELF_SLAY1 "Kill! KILL!" +#define SAY_NIGHTELF_SLAY2 "That's right! Yes!" +#define SAY_NIGHTELF_SLAY3 "Who's the master now?" +#define SAY_FINAL_FORM "No! NO! What have you done?! I am the master, do you hear me? I... aaghh... Can't... contain him..." +#define SAY_FREE "At last I am liberated. It has been too long since I have tasted true freedom!" +#define SAY_DEATH "You cannot kill me! Fools, I'll be back! I'll... aarghh..." + +#define SOUND_AGGRO 11312 +#define SOUND_SWITCH_TO_DEMON 11304 +#define SOUND_INNER_DEMONS 11305 +#define SOUND_DEMON_SLAY1 11306 +#define SOUND_DEMON_SLAY2 11307 +#define SOUND_DEMON_SLAY3 11308 +#define SOUND_NIGHTELF_SLAY1 11314 +#define SOUND_NIGHTELF_SLAY2 11315 +#define SOUND_NIGHTELF_SLAY3 11316 +#define SOUND_FINAL_FORM 11313 +#define SOUND_FREE 11309 +#define SOUND_DEATH 11317 + +#define MODEL_DEMON 14555 +#define MODEL_NIGHTELF 20514 + +#define DEMON_FORM 21845 + +//Original Leotheras the Blind AI +struct MANGOS_DLL_DECL boss_leotheras_the_blindAI : public ScriptedAI +{ + boss_leotheras_the_blindAI(Creature *c) : ScriptedAI(c) + { + pInstance = (c->GetInstanceData()) ? ((ScriptedInstance*)c->GetInstanceData()) : NULL; + Demon = 0; + Reset(); + } + + ScriptedInstance *pInstance; + + uint32 Whirlwind_Timer; + uint32 ChaosBlast_Timer; + uint32 Switch_Timer; + + bool DemonForm; + bool IsFinalForm; + + uint64 Demon; + + void Reset() + { + Whirlwind_Timer = 20000; + ChaosBlast_Timer = 1000; + Switch_Timer = 45000; + + DemonForm = false; + IsFinalForm = false; + + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_NIGHTELF); + + if(pInstance) + pInstance->SetData(DATA_LEOTHERASTHEBLINDEVENT, 0); + } + + void StartEvent() + { + DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO); + + if(pInstance) + pInstance->SetData(DATA_LEOTHERASTHEBLINDEVENT, 1); + } + + void KilledUnit(Unit *victim) + { + if(victim->GetTypeId() != TYPEID_PLAYER) + return; + + if(DemonForm) + switch(rand()%3) + { + case 0: + DoYell(SAY_DEMON_SLAY1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_DEMON_SLAY1); + break; + case 1: + DoYell(SAY_DEMON_SLAY2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_DEMON_SLAY2); + break; + case 2: + DoYell(SAY_DEMON_SLAY3, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_DEMON_SLAY3); + break; + } + else + switch(rand()%3) + { + case 0: + DoYell(SAY_NIGHTELF_SLAY1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_NIGHTELF_SLAY1); + break; + case 1: + DoYell(SAY_NIGHTELF_SLAY2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_NIGHTELF_SLAY2); + break; + case 2: + DoYell(SAY_NIGHTELF_SLAY3, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_NIGHTELF_SLAY3); + break; + } + } + + void JustDied(Unit *victim) + { + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_DEATH); + + //despawn copy + if(Demon) + { + Unit *pUnit = NULL; + pUnit = Unit::GetUnit((*m_creature), Demon); + + if(pUnit) + pUnit->DealDamage(pUnit, pUnit->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + if(pInstance) + pInstance->SetData(DATA_LEOTHERASTHEBLINDEVENT, 0); + } + + void Aggro(Unit *who) + { + StartEvent(); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if(!DemonForm) + { + //Whirlwind_Timer + if(Whirlwind_Timer < diff) + { + DoCast(m_creature, SPELL_WHIRLWIND); + Whirlwind_Timer = 25000; + }else Whirlwind_Timer -= diff; + + //Switch_Timer + if(!IsFinalForm) + if(Switch_Timer < diff) + { + //switch to demon form + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_DEMON); + DoYell(SAY_SWITCH_TO_DEMON, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SWITCH_TO_DEMON); + DemonForm = true; + + Switch_Timer = 60000; + }else Switch_Timer -= diff; + + DoMeleeAttackIfReady(); + } + else + { + //ChaosBlast_Timer + if(ChaosBlast_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_CHAOS_BLAST); + ChaosBlast_Timer = 1500; + }else ChaosBlast_Timer -= diff; + + //Switch_Timer + if(Switch_Timer < diff) + { + //switch to nightelf form + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_NIGHTELF); + DemonForm = false; + + Switch_Timer = 45000; + }else Switch_Timer -= diff; + } + + if(!IsFinalForm && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 15) + { + //at this point he divides himself in two parts + Creature *Copy = NULL; + Copy = DoSpawnCreature(DEMON_FORM, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + + if(Copy) + { + Demon = Copy->GetGUID(); + Copy->AI()->AttackStart(m_creature->getVictim()); + } + + //set nightelf final form + IsFinalForm = true; + DemonForm = false; + + DoYell(SAY_FINAL_FORM, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_FINAL_FORM); + + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_NIGHTELF); + } + } +}; + +//Leotheras the Blind Demon Form AI +struct MANGOS_DLL_DECL boss_leotheras_the_blind_demonformAI : public ScriptedAI +{ + boss_leotheras_the_blind_demonformAI(Creature *c) : ScriptedAI(c) + { + Reset(); + } + + uint32 ChaosBlast_Timer; + + void Reset() + { + ChaosBlast_Timer = 1000; + } + + void StartEvent() + { + DoYell(SAY_FREE, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_FREE); + } + + void KilledUnit(Unit *victim) + { + if(victim->GetTypeId() != TYPEID_PLAYER) + return; + + switch(rand()%3) + { + case 0: + DoYell(SAY_DEMON_SLAY1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_DEMON_SLAY1); + break; + case 1: + DoYell(SAY_DEMON_SLAY2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_DEMON_SLAY2); + break; + case 2: + DoYell(SAY_DEMON_SLAY3, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_DEMON_SLAY3); + break; + } + } + + void JustDied(Unit *victim) + { + //invisibility (blizzlike, at the end of the fight he doesn't die, he disappears) + m_creature->CastSpell(m_creature, 8149, true); + } + + void Aggro(Unit *who) + { + StartEvent(); + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || m_creature->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + float attackRadius = m_creature->GetAttackDistance(who); + if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) + { + if(who->HasStealthAura()) + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + DoStartAttackAndMovement(who); + + if(!InCombat) + StartEvent(); + } + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //ChaosBlast_Timer + if(ChaosBlast_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_CHAOS_BLAST); + ChaosBlast_Timer = 1500; + }else ChaosBlast_Timer -= diff; + + //Do NOT deal any melee damage to the target. + } +}; + +CreatureAI* GetAI_boss_leotheras_the_blind(Creature *_Creature) +{ + return new boss_leotheras_the_blindAI (_Creature); +} + +CreatureAI* GetAI_boss_leotheras_the_blind_demonform(Creature *_Creature) +{ + return new boss_leotheras_the_blind_demonformAI (_Creature); +} + +void AddSC_boss_leotheras_the_blind() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_leotheras_the_blind"; + newscript->GetAI = GetAI_boss_leotheras_the_blind; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_leotheras_the_blind_demonform"; + newscript->GetAI = GetAI_boss_leotheras_the_blind_demonform; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_morogrim_tidewalker.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_morogrim_tidewalker.cpp new file mode 100644 index 00000000000..27ebaf4bd7e --- /dev/null +++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_morogrim_tidewalker.cpp @@ -0,0 +1,406 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Morogrim_Tidewalker +SD%Complete: 90 +SDComment: Water globules don't explode properly +SDCategory: Coilfang Resevoir, Serpent Shrine Cavern +EndScriptData */ + +#include "precompiled.h" +#include "def_serpent_shrine.h" + +#define SPELL_TIDAL_WAVE 37730 +#define SPELL_WATERY_GRAVE 38049 +#define SPELL_EARTHQUAKE 37764 +#define SPELL_WATERY_GRAVE_EXPLOSION 37852 + +#define SAY_AGGRO "Flood of the deep, take you!" +#define SAY_SUMMON1 "By the Tides, kill them at once!" +#define SAY_SUMMON2 "Destroy them my subjects!" +#define SAY_SLAY1 "It is done!" +#define SAY_SLAY2 "Strugging only makes it worse." +#define SAY_SLAY3 "Only the strong survive." +#define SAY_SUMMON_BUBL1 "There is nowhere to hide!" +#define SAY_SUMMON_BUBL2 "Soon it will be finished!" +#define SAY_DEATH "Great... currents of... Ageon." + +#define SOUND_AGGRO 11321 +#define SOUND_SUMMON1 11322 +#define SOUND_SUMMON2 11323 +#define SOUND_SLAY1 11326 +#define SOUND_SLAY2 11327 +#define SOUND_SLAY3 11328 +#define SOUND_SUMMON_BUBL1 11324 +#define SOUND_SUMMON_BUBL2 11325 +#define SOUND_DEATH 11329 + +#define WATERY_GRAVE_X1 334.64 +#define WATERY_GRAVE_Y1 -728.89 +#define WATERY_GRAVE_Z1 -14.42 +#define WATERY_GRAVE_X2 365.51 +#define WATERY_GRAVE_Y2 -737.14 +#define WATERY_GRAVE_Z2 -14.44 +#define WATERY_GRAVE_X3 366.19 +#define WATERY_GRAVE_Y3 -709.59 +#define WATERY_GRAVE_Z3 -14.36 +#define WATERY_GRAVE_X4 372.93 +#define WATERY_GRAVE_Y4 -690.96 +#define WATERY_GRAVE_Z4 -14.44 + +#define EMOTE_WATERY_GRAVE "sends his enemies to their watery graves!" +#define EMOTE_EARTHQUAKE "The violent earthquake has alerted nearby murlocs!" +#define EMOTE_WATERY_GLOBULES "summons Watery Globules!" + +#define WATER_GLOBULE 21913 +#define TIDEWALKER_LURKER 21920 + +//Morogrim Tidewalker AI +struct MANGOS_DLL_DECL boss_morogrim_tidewalkerAI : public ScriptedAI +{ + boss_morogrim_tidewalkerAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + + uint32 TidalWave_Timer; + uint32 WateryGrave_Timer; + uint32 Earthquake_Timer; + uint32 WateryGlobules_Timer; + + bool Earthquake; + bool Phase2; + + void Reset() + { + TidalWave_Timer = 10000; + WateryGrave_Timer = 30000; + Earthquake_Timer = 40000; + WateryGlobules_Timer = 0; + + Earthquake = false; + Phase2 = false; + + if(pInstance) + pInstance->SetData(DATA_MOROGRIMTIDEWALKEREVENT, NOT_STARTED); + } + + void StartEvent() + { + DoPlaySoundToSet(m_creature, SOUND_AGGRO); + DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL); + + if(pInstance) + pInstance->SetData(DATA_MOROGRIMTIDEWALKEREVENT, IN_PROGRESS); + } + + void KilledUnit(Unit *victim) + { + switch(rand()%3) + { + case 0: + DoPlaySoundToSet(m_creature, SOUND_SLAY1); + DoYell(SAY_SLAY1, LANG_UNIVERSAL, NULL); + break; + + case 1: + DoPlaySoundToSet(m_creature, SOUND_SLAY2); + DoYell(SAY_SLAY2, LANG_UNIVERSAL, NULL); + break; + + case 2: + DoPlaySoundToSet(m_creature, SOUND_SLAY3); + DoYell(SAY_SLAY3, LANG_UNIVERSAL, NULL); + break; + } + } + + void JustDied(Unit *victim) + { + DoPlaySoundToSet(m_creature, SOUND_DEATH); + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + + if(pInstance) + pInstance->SetData(DATA_MOROGRIMTIDEWALKEREVENT, NOT_STARTED); + } + + void Aggro(Unit *who) { StartEvent(); } + + void ApplyWateryGrave(Unit *player, uint8 pos) + { + float x, y, z; + + switch(pos) + { + case 0: + x = WATERY_GRAVE_X1; + y = WATERY_GRAVE_Y1; + z = WATERY_GRAVE_Z1; + break; + + case 1: + x = WATERY_GRAVE_X2; + y = WATERY_GRAVE_Y2; + z = WATERY_GRAVE_Z2; + break; + + case 2: + x = WATERY_GRAVE_X3; + y = WATERY_GRAVE_Y3; + z = WATERY_GRAVE_Z3; + break; + + case 3: + x = WATERY_GRAVE_X4; + y = WATERY_GRAVE_Y4; + z = WATERY_GRAVE_Z4; + break; + } + + DoTeleportPlayer(player, x, y, z+1, player->GetOrientation()); + DoCast(player, SPELL_WATERY_GRAVE); + } + + void SummonMurloc(float x, float y, float z) + { + Creature *Summoned; + + Summoned = m_creature->SummonCreature(TIDEWALKER_LURKER, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + if(Summoned) + { + Unit *target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target) + Summoned->AI()->AttackStart(target); + } + } + + void SummonWaterGlobule(float x, float y, float z) + { + Creature *Globule; + + Globule = m_creature->SummonCreature(WATER_GLOBULE, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN, 30000); //they despawn after 30 seconds + if(Globule) + { + Unit *target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target) + Globule->AI()->AttackStart(target); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //Earthquake_Timer + if(Earthquake_Timer < diff) + { + if(!Earthquake) + { + DoCast(m_creature->getVictim(), SPELL_EARTHQUAKE); + Earthquake = true; + Earthquake_Timer = 10000; + } + else + { + switch(rand()%2) + { + case 0: + DoPlaySoundToSet(m_creature, SOUND_SUMMON1); + DoYell(SAY_SUMMON1, LANG_UNIVERSAL, NULL); + break; + + case 1: + DoPlaySoundToSet(m_creature, SOUND_SUMMON2); + DoYell(SAY_SUMMON2, LANG_UNIVERSAL, NULL); + break; + } + + //north + SummonMurloc(486.10, -723.64, -7.14); + SummonMurloc(482.58, -723.78, -7.14); + SummonMurloc(479.38, -723.91, -7.14); + SummonMurloc(476.03, -723.86, -7.14); + SummonMurloc(472.69, -723.69, -7.14); + SummonMurloc(469.04, -723.63, -7.14); + + //south + SummonMurloc(311.63, -725.04, -13.15); + SummonMurloc(307.81, -725.34, -13.15); + SummonMurloc(303.91, -725.64, -13.06); + SummonMurloc(300.23, -726, -11.89); + SummonMurloc(296.82, -726.33, -10.82); + SummonMurloc(293.64, -726.64, -9.81); + + DoTextEmote(EMOTE_EARTHQUAKE, NULL); + + Earthquake = false; + Earthquake_Timer = 40000+rand()%5000; + } + }else Earthquake_Timer -= diff; + + //TidalWave_Timer + if(TidalWave_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_TIDAL_WAVE); + TidalWave_Timer = 20000; + }else TidalWave_Timer -= diff; + + if(!Phase2) + { + //WateryGrave_Timer + if(WateryGrave_Timer < diff) + { + //Teleport 4 players under the waterfalls + Unit *target; + for(uint8 i = 0; i < 4; i++) + { + target = SelectUnit(SELECT_TARGET_RANDOM, 1); + if(target && (target->GetTypeId() == TYPEID_PLAYER) && !target->HasAura(SPELL_WATERY_GRAVE, 0) && target->IsWithinDistInMap(m_creature, 50)) + ApplyWateryGrave(target, i); + } + + switch(rand()%2) + { + case 0: + DoPlaySoundToSet(m_creature, SOUND_SUMMON_BUBL1); + DoYell(SAY_SUMMON_BUBL1, LANG_UNIVERSAL, NULL); + break; + + case 1: + DoPlaySoundToSet(m_creature, SOUND_SUMMON_BUBL2); + DoYell(SAY_SUMMON_BUBL2, LANG_UNIVERSAL, NULL); + break; + + case 2: + break; + } + + DoTextEmote(EMOTE_WATERY_GRAVE, NULL); + + WateryGrave_Timer = 30000; + }else WateryGrave_Timer -= diff; + + //Start Phase2 + if((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 25) + Phase2 = true; + } + else + { + //WateryGlobules_Timer + if(WateryGlobules_Timer < diff) + { + SummonWaterGlobule(WATERY_GRAVE_X1, WATERY_GRAVE_Y1, WATERY_GRAVE_Z1); + SummonWaterGlobule(WATERY_GRAVE_X2, WATERY_GRAVE_Y2, WATERY_GRAVE_Z2); + SummonWaterGlobule(WATERY_GRAVE_X3, WATERY_GRAVE_Y3, WATERY_GRAVE_Z3); + SummonWaterGlobule(WATERY_GRAVE_X4, WATERY_GRAVE_Y4, WATERY_GRAVE_Z4); + + DoTextEmote(EMOTE_WATERY_GLOBULES, NULL); + + WateryGlobules_Timer = 25000; + }else WateryGlobules_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +//Water Globule AI +struct MANGOS_DLL_DECL mob_water_globuleAI : public ScriptedAI +{ + mob_water_globuleAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Check_Timer; + + void Reset() + { + Check_Timer = 1000; + + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->setFaction(14); + } + + void Aggro(Unit *who) {} + + void MoveInLineOfSight(Unit *who) + { + if (!who || m_creature->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + //no attack radius check - it attacks the first target that moves in his los + if(who->HasStealthAura()) + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + DoStartAttackAndMovement(who); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if(Check_Timer < diff) + { + if(m_creature->IsWithinDistInMap(m_creature->getVictim(), 5)) + { + uint32 damage = 4000+rand()%2000; + m_creature->DealDamage(m_creature->getVictim(), damage, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_FROST, NULL, false); + + //despawn + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + Check_Timer = 500; + }else Check_Timer -= diff; + + //do NOT deal any melee damage to the target. + } +}; + +CreatureAI* GetAI_boss_morogrim_tidewalker(Creature *_Creature) +{ + return new boss_morogrim_tidewalkerAI (_Creature); +} +CreatureAI* GetAI_mob_water_globule(Creature *_Creature) +{ + return new mob_water_globuleAI (_Creature); +} + +void AddSC_boss_morogrim_tidewalker() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_morogrim_tidewalker"; + newscript->GetAI = GetAI_boss_morogrim_tidewalker; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_water_globule"; + newscript->GetAI = GetAI_mob_water_globule; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/def_serpent_shrine.h b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/def_serpent_shrine.h new file mode 100644 index 00000000000..21d76d6854a --- /dev/null +++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/def_serpent_shrine.h @@ -0,0 +1,26 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_SERPENT_SHRINE_H +#define DEF_SERPENT_SHRINE_H + +#define DATA_CANSTARTPHASE3 1 +#define DATA_CARIBDIS 2 +#define DATA_HYDROSSTHEUNSTABLEEVENT 3 +#define DATA_KARATHRESS 4 +#define DATA_KARATHRESSEVENT 5 +#define DATA_KARATHRESSEVENT_STARTER 6 +#define DATA_LADYVASHJ 7 +#define DATA_LADYVASHJEVENT 8 +#define DATA_LEOTHERASTHEBLINDEVENT 9 +#define DATA_MOROGRIMTIDEWALKEREVENT 10 +#define DATA_SHARKKIS 11 +#define DATA_SHIELDGENERATOR1 12 +#define DATA_SHIELDGENERATOR2 13 +#define DATA_SHIELDGENERATOR3 14 +#define DATA_SHIELDGENERATOR4 15 +#define DATA_THELURKERBELOWEVENT 16 +#define DATA_TIDALVESS 17 +#define DATA_FATHOMLORDKARATHRESSEVENT 18 +#endif diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp new file mode 100644 index 00000000000..d1a90449abf --- /dev/null +++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp @@ -0,0 +1,227 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Serpent_Shrine +SD%Complete: 0 +SDComment: VERIFY SCRIPT +SDCategory: Coilfang Resevoir, Serpent Shrine Cavern +EndScriptData */ + +#include "precompiled.h" +#include "def_serpent_shrine.h" + +#define ENCOUNTERS 6 + +/* Serpentshrine cavern encounters: +0 - Hydross The Unstable event +1 - Leotheras The Blind Event +2 - The Lurker Below Event +3 - Fathom-Lord Karathress Event +4 - Morogrim Tidewalker Event +5 - Lady Vashj Event +*/ + +struct MANGOS_DLL_DECL instance_serpentshrine_cavern : public ScriptedInstance +{ + instance_serpentshrine_cavern(Map *Map) : ScriptedInstance(Map) {Initialize();}; + + uint64 Sharkkis; + uint64 Tidalvess; + uint64 Caribdis; + uint64 LadyVashj; + uint64 Karathress; + uint64 KarathressEvent_Starter; + + bool ShieldGeneratorDeactivated[4]; + + bool Encounters[ENCOUNTERS]; + + void Initialize() + { + Sharkkis = 0; + Tidalvess = 0; + Caribdis = 0; + LadyVashj = 0; + Karathress = 0; + KarathressEvent_Starter = 0; + + ShieldGeneratorDeactivated[0] = false; + ShieldGeneratorDeactivated[1] = false; + ShieldGeneratorDeactivated[2] = false; + ShieldGeneratorDeactivated[3] = false; + + for(uint8 i = 0; i < ENCOUNTERS; i++) + Encounters[i] = false; + } + + bool IsEncounterInProgress() const + { + for(uint8 i = 0; i < ENCOUNTERS; i++) + if(Encounters[i]) return true; + + return false; + } + + void OnCreatureCreate(Creature *creature, uint32 creature_entry) + { + switch(creature_entry) + { + case 21212: LadyVashj = creature->GetGUID(); break; + case 21214: Karathress = creature->GetGUID(); break; + case 21966: Sharkkis = creature->GetGUID(); break; + case 21965: Tidalvess = creature->GetGUID(); break; + case 21964: Caribdis = creature->GetGUID(); break; + } + } + + void SetData64(uint32 type, uint64 data) + { + if(type == DATA_KARATHRESSEVENT_STARTER) + KarathressEvent_Starter = data; + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_SHARKKIS: + return Sharkkis; + case DATA_TIDALVESS: + return Tidalvess; + case DATA_CARIBDIS: + return Caribdis; + case DATA_LADYVASHJ: + return LadyVashj; + case DATA_KARATHRESS: + return Karathress; + case DATA_KARATHRESSEVENT_STARTER: + return KarathressEvent_Starter; + } + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_HYDROSSTHEUNSTABLEEVENT: + Encounters[0] = (data) ? true : false; + break; + + case DATA_LEOTHERASTHEBLINDEVENT: + Encounters[1] = (data) ? true : false; + break; + + case DATA_THELURKERBELOWEVENT: + Encounters[2] = (data) ? true : false; + break; + + case DATA_KARATHRESSEVENT: + Encounters[3] = (data) ? true : false; + break; + + case DATA_MOROGRIMTIDEWALKEREVENT: + Encounters[4] = (data) ? true : false; + break; + //Lady Vashj + case DATA_LADYVASHJEVENT: + if(data == 0) + { + ShieldGeneratorDeactivated[0] = false; + ShieldGeneratorDeactivated[1] = false; + ShieldGeneratorDeactivated[2] = false; + ShieldGeneratorDeactivated[3] = false; + } + Encounters[5] = (data) ? true : false; + break; + + case DATA_SHIELDGENERATOR1: + ShieldGeneratorDeactivated[0] = (data) ? true : false; + break; + + case DATA_SHIELDGENERATOR2: + ShieldGeneratorDeactivated[1] = (data) ? true : false; + break; + + case DATA_SHIELDGENERATOR3: + ShieldGeneratorDeactivated[2] = (data) ? true : false; + break; + + case DATA_SHIELDGENERATOR4: + ShieldGeneratorDeactivated[3] = (data) ? true : false; + break; + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_HYDROSSTHEUNSTABLEEVENT: + return Encounters[0]; + + case DATA_LEOTHERASTHEBLINDEVENT: + return Encounters[1]; + + case DATA_THELURKERBELOWEVENT: + return Encounters[2]; + + case DATA_KARATHRESSEVENT: + return Encounters[3]; + + case DATA_MOROGRIMTIDEWALKEREVENT: + return Encounters[4]; + + //Lady Vashj + case DATA_LADYVASHJEVENT: + return Encounters[5]; + + case DATA_SHIELDGENERATOR1: + return ShieldGeneratorDeactivated[0]; + + case DATA_SHIELDGENERATOR2: + return ShieldGeneratorDeactivated[1]; + + case DATA_SHIELDGENERATOR3: + return ShieldGeneratorDeactivated[2]; + + case DATA_SHIELDGENERATOR4: + return ShieldGeneratorDeactivated[3]; + + case DATA_CANSTARTPHASE3: + if(ShieldGeneratorDeactivated[0] && ShieldGeneratorDeactivated[1] && ShieldGeneratorDeactivated[2] && ShieldGeneratorDeactivated[3]) + return 1; + break; + } + + return 0; + } +}; + +InstanceData* GetInstanceData_instance_serpentshrine_cavern(Map* map) +{ + return new instance_serpentshrine_cavern(map); +} + +void AddSC_instance_serpentshrine_cavern() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_serpent_shrine"; + newscript->GetInstanceData = GetInstanceData_instance_serpentshrine_cavern; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/slave_pens/boss_rokmar.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/slave_pens/boss_rokmar.cpp new file mode 100644 index 00000000000..7d0e9d72822 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/slave_pens/boss_rokmar.cpp @@ -0,0 +1,65 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Rokmar +SD%Complete: 100 +SDComment: +SDCategory: Coilfang Resevoir, Slave Pens +EndScriptData */ + +#include "../../../creature/simple_ai.h" + +#define SPELL_WATTER_SPIT 40086 +#define SPELL_GRIEVOUS_WOUND 31956 +#define SPELL_ENSARING_MOSS 31948 + +CreatureAI* GetAI_boss_rokmar_the_crackler(Creature *_Creature) +{ + SimpleAI* ai = new SimpleAI (_Creature); + + //Watter Spit + ai->Spell[0].Enabled = true; + ai->Spell[0].Spell_Id = SPELL_WATTER_SPIT; + ai->Spell[0].Cooldown = 15000; + ai->Spell[0].First_Cast = 15000; + ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_TARGET; + + //Grievous Wound + ai->Spell[1].Enabled = true; + ai->Spell[1].Spell_Id = SPELL_GRIEVOUS_WOUND; + ai->Spell[1].Cooldown = 25000; + ai->Spell[1].First_Cast = 15000; + ai->Spell[1].Cast_Target_Type = CAST_HOSTILE_TARGET; + + //Ensaring Moss + ai->Spell[2].Enabled = true; + ai->Spell[2].Spell_Id = SPELL_ENSARING_MOSS; + ai->Spell[2].Cooldown = 15000 + (rand()%10000); + ai->Spell[2].First_Cast = 25000; + ai->Spell[2].Cast_Target_Type = CAST_HOSTILE_TARGET; + + return ai; +} + +void AddSC_boss_rokmar_the_crackler() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_rokmar_the_crackler"; + newscript->GetAI = GetAI_boss_rokmar_the_crackler; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/steam_vault/boss_hydromancer_thespia.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/steam_vault/boss_hydromancer_thespia.cpp new file mode 100644 index 00000000000..74fb09726c7 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/steam_vault/boss_hydromancer_thespia.cpp @@ -0,0 +1,223 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Hydromancer_Thespia +SD%Complete: 80 +SDComment: Normal/heroic mode: to be tested. Needs additional adjustments (when instance script is adjusted) +SDCategory: Coilfang Resevoir, The Steamvault +EndScriptData */ + +/* ContentData +boss_hydromancer_thespia +mob_coilfang_waterelemental +EndContentData */ + +#include "precompiled.h" +#include "def_steam_vault.h" + +#define SAY_SUMMON "Surge forth my pets!" +#define SOUND_SUMMON 10360 + +#define SAY_AGGRO_1 "The depths will consume you!" +#define SOUND_AGGRO_1 10361 +#define SAY_AGGRO_2 "Meet your doom, surface dwellers!" +#define SOUND_AGGRO_2 10362 +#define SAY_AGGRO_3 "You will drown in blood!" +#define SOUND_AGGRO_3 10363 + +#define SAY_SLAY_1 "To the depths of oblivion with you!" +#define SOUND_SLAY_1 10364 +#define SAY_SLAY_2 "For my lady and master!" +#define SOUND_SLAY_2 10365 + +#define SAY_DEAD "Our matron will be.. the end of.. you.." +#define SOUND_DEAD 10366 + +#define SPELL_LIGHTNING_CLOUD 25033 +#define SPELL_LUNG_BURST 31481 +#define SPELL_ENVELOPING_WINDS 31718 + +struct MANGOS_DLL_DECL boss_thespiaAI : public ScriptedAI +{ + boss_thespiaAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance *pInstance; + bool HeroicMode; + + uint32 LightningCloud_Timer; + uint32 LungBurst_Timer; + uint32 EnvelopingWinds_Timer; + + void Reset() + { + HeroicMode = m_creature->GetMap()->IsHeroic(); + + LightningCloud_Timer = 28000; + LungBurst_Timer = 7000; + EnvelopingWinds_Timer = 9000; + + if( pInstance ) pInstance->SetData(TYPE_HYDROMANCER_THESPIA, NOT_STARTED); + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DEAD, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_DEAD); + + if( pInstance ) pInstance->SetData(TYPE_HYDROMANCER_THESPIA, DONE); + } + + void KilledUnit(Unit* victim) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_SLAY_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY_1); + break; + case 1: + DoYell(SAY_SLAY_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY_2); + break; + } + } + + void Aggro(Unit *who) + { + switch(rand()%3) + { + case 0: + DoYell(SAY_AGGRO_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO_1); + break; + case 1: + DoYell(SAY_AGGRO_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO_2); + break; + case 2: + DoYell(SAY_AGGRO_3, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO_3); + break; + } + + if( pInstance ) pInstance->SetData(TYPE_HYDROMANCER_THESPIA, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //LightningCloud_Timer + if( LightningCloud_Timer < diff ) + { + //cast twice in Heroic mode + if( Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target, SPELL_LIGHTNING_CLOUD); + if( HeroicMode ) + if( Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target, SPELL_LIGHTNING_CLOUD); + LightningCloud_Timer = 28000; + }else LightningCloud_Timer -=diff; + + //LungBurst_Timer + if( LungBurst_Timer < diff ) + { + if( Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target, SPELL_LUNG_BURST); + LungBurst_Timer = 10000+rand()%5000; + }else LungBurst_Timer -=diff; + + //EnvelopingWinds_Timer + if( EnvelopingWinds_Timer < diff ) + { + //cast twice in Heroic mode + if( Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target, SPELL_ENVELOPING_WINDS); + if( HeroicMode ) + if( Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target, SPELL_ENVELOPING_WINDS); + EnvelopingWinds_Timer = 10000+rand()%5000; + }else EnvelopingWinds_Timer -=diff; + + DoMeleeAttackIfReady(); + } +}; + +#define SPELL_WATER_BOLT_VOLLEY 34449 +#define H_SPELL_WATER_BOLT_VOLLEY 37924 + +struct MANGOS_DLL_DECL mob_coilfang_waterelementalAI : public ScriptedAI +{ + mob_coilfang_waterelementalAI(Creature *c) : ScriptedAI(c) {Reset();} + + bool HeroicMode; + uint32 WaterBoltVolley_Timer; + + void Reset() + { + HeroicMode = m_creature->GetMap()->IsHeroic(); + WaterBoltVolley_Timer = 3000+rand()%3000; + } + + void Aggro(Unit *who) { } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if( WaterBoltVolley_Timer < diff ) + { + if( HeroicMode ) DoCast(m_creature,H_SPELL_WATER_BOLT_VOLLEY); + else DoCast(m_creature,SPELL_WATER_BOLT_VOLLEY); + + WaterBoltVolley_Timer = 10000+rand()%5000; + }else WaterBoltVolley_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_thespiaAI(Creature *_Creature) +{ + return new boss_thespiaAI (_Creature); +} + +CreatureAI* GetAI_mob_coilfang_waterelementalAI(Creature *_Creature) +{ + return new mob_coilfang_waterelementalAI (_Creature); +} + +void AddSC_boss_hydromancer_thespia() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_hydromancer_thespia"; + newscript->GetAI = GetAI_boss_thespiaAI; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_coilfang_waterelemental"; + newscript->GetAI = GetAI_mob_coilfang_waterelementalAI; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/steam_vault/boss_mekgineer_steamrigger.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/steam_vault/boss_mekgineer_steamrigger.cpp new file mode 100644 index 00000000000..83177d88fa2 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/steam_vault/boss_mekgineer_steamrigger.cpp @@ -0,0 +1,297 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Mekgineer_Steamrigger +SD%Complete: 60 +SDComment: Mechanics' interrrupt heal doesn't work very well, also a proper movement needs to be implemented -> summon further away and move towards target to repair. +SDCategory: Coilfang Resevoir, The Steamvault +EndScriptData */ + +/* ContentData +boss_mekgineer_steamrigger +mob_steamrigger_mechanic +EndContentData */ + +#include "precompiled.h" +#include "def_steam_vault.h" + +#define SAY_MECHANICS "I'm bringin' the pain!" +#define SOUND_MECHANICS 10367 + +#define SAY_AGGRO_1 "You're in for a world of hurt!" +#define SOUND_AGGRO_1 10368 +#define SAY_AGGRO_2 "Eat hot metal, scumbag!" +#define SOUND_AGGRO_2 10369 +#define SAY_AGGRO_3 "I'll come over there!" +#define SOUND_AGGRO_3 10370 +#define SAY_AGGRO_4 "I'm bringin' the pain!" +#define SOUND_AGGRO_4 10371 + +#define SAY_SLAY_1 "You just got served, punk!" +#define SOUND_SLAY_1 10372 +#define SAY_SLAY_2 "I own you!" +#define SOUND_SLAY_2 10373 +#define SAY_SLAY_3 "Have fun dyin', cupcake!" +#define SOUND_SLAY_3 10374 + +#define SAY_DEATH "Mommy!" +#define SOUND_DEATH 10375 + +#define SPELL_SUPER_SHRINK_RAY 31485 +#define SPELL_SAW_BLADE 31486 +#define SPELL_ELECTRIFIED_NET 35107 +#define H_SPELL_ENRAGE 1 //corrent enrage spell not known + +#define ENTRY_STREAMRIGGER_MECHANIC 17951 + +struct MANGOS_DLL_DECL boss_mekgineer_steamriggerAI : public ScriptedAI +{ + boss_mekgineer_steamriggerAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance *pInstance; + + uint32 Shrink_Timer; + uint32 Saw_Blade_Timer; + uint32 Electrified_Net_Timer; + bool Summon75; + bool Summon50; + bool Summon25; + + void Reset() + { + Shrink_Timer = 20000; + Saw_Blade_Timer = 15000; + Electrified_Net_Timer = 10000; + + Summon75 = false; + Summon50 = false; + Summon25 = false; + + if( pInstance ) pInstance->SetData(TYPE_MEKGINEER_STEAMRIGGER, NOT_STARTED); + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_DEATH); + + if( pInstance ) pInstance->SetData(TYPE_MEKGINEER_STEAMRIGGER, DONE); + } + + void KilledUnit(Unit* victim) + { + switch(rand()%3) + { + case 0: + DoYell(SAY_SLAY_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY_1); + break; + case 1: + DoYell(SAY_SLAY_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY_2); + break; + case 2: + DoYell(SAY_SLAY_3, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY_3); + break; + } + } + + void Aggro(Unit *who) + { + switch(rand()%3) + { + case 0: + DoYell(SAY_AGGRO_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO_1); + break; + case 1: + DoYell(SAY_AGGRO_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO_2); + break; + case 2: + DoYell(SAY_AGGRO_3, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO_3); + break; + } + + if( pInstance ) pInstance->SetData(TYPE_MEKGINEER_STEAMRIGGER, IN_PROGRESS); + } + + //no known summon spells exist + void SummonMechanichs() + { + DoYell(SAY_MECHANICS, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_MECHANICS); + + DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,5,5,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); + DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,-5,5,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); + DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,-5,-5,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); + + if( rand()%2 ) + DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,5,-7,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); + if( rand()%2 ) + DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,7,-5,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if( Shrink_Timer < diff ) + { + DoCast(m_creature->getVictim(),SPELL_SUPER_SHRINK_RAY); + Shrink_Timer = 20000; + }else Shrink_Timer -= diff; + + if( Saw_Blade_Timer < diff ) + { + if( Unit* target = SelectUnit(SELECT_TARGET_RANDOM,1) ) DoCast(target,SPELL_SAW_BLADE); + else DoCast(m_creature->getVictim(),SPELL_SAW_BLADE); + Saw_Blade_Timer = 15000; + } else Saw_Blade_Timer -= diff; + + if( Electrified_Net_Timer < diff ) + { + DoCast(m_creature->getVictim(),SPELL_ELECTRIFIED_NET); + Electrified_Net_Timer = 10000; + } + else Electrified_Net_Timer -= diff; + + if( !Summon75 ) + if( (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 75 ) + { + SummonMechanichs(); + Summon75 = true; + } + if( !Summon50 ) + if( (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 50 ) + { + SummonMechanichs(); + Summon50 = true; + } + if( !Summon25 ) + if( (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 25 ) + { + SummonMechanichs(); + Summon25 = true; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_mekgineer_steamrigger(Creature *_Creature) +{ + return new boss_mekgineer_steamriggerAI (_Creature); +} + +#define SPELL_DISPEL_MAGIC 17201 +#define SPELL_REPAIR 31532 +#define H_SPELL_REPAIR 37936 + +#define MAX_REPAIR_RANGE (13.0f) //we should be at least at this range for repair +#define MIN_REPAIR_RANGE (7.0f) //we can stop movement at this range to repair but not required + +struct MANGOS_DLL_DECL mob_steamrigger_mechanicAI : public ScriptedAI +{ + mob_steamrigger_mechanicAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + + uint32 Repair_Timer; + bool HeroicMode; + + void Reset() + { + HeroicMode = m_creature->GetMap()->IsHeroic(); + Repair_Timer = 2000; + } + + void MoveInLineOfSight(Unit* who) + { + //react only if attacked + return; + } + + void Aggro(Unit *who) { } + + void UpdateAI(const uint32 diff) + { + if( Repair_Timer < diff ) + { + if( pInstance && pInstance->GetData64(DATA_MEKGINEERSTEAMRIGGER) && pInstance->GetData(TYPE_MEKGINEER_STEAMRIGGER) == IN_PROGRESS) + { + if( Unit* pMekgineer = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_MEKGINEERSTEAMRIGGER)) ) + { + if( m_creature->IsWithinDistInMap(pMekgineer, MAX_REPAIR_RANGE) ) + { + //are we already channeling? Doesn't work very well, find better check? + if( !m_creature->GetUInt32Value(UNIT_CHANNEL_SPELL) ) + { + //m_creature->GetMotionMaster()->MovementExpired(); + //m_creature->GetMotionMaster()->MoveIdle(); + + if( HeroicMode ) DoCast(m_creature,H_SPELL_REPAIR,true); + else DoCast(m_creature,SPELL_REPAIR,true); + } + Repair_Timer = 5000; + } + else + { + //m_creature->GetMotionMaster()->MovementExpired(); + //m_creature->GetMotionMaster()->MoveFollow(pMekgineer,0,0); + } + } + }else Repair_Timer = 5000; + }else Repair_Timer -= diff; + + if( !m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_steamrigger_mechanic(Creature *_Creature) +{ + return new mob_steamrigger_mechanicAI (_Creature); +} + +void AddSC_boss_mekgineer_steamrigger() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_mekgineer_steamrigger"; + newscript->GetAI = GetAI_boss_mekgineer_steamrigger; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_steamrigger_mechanic"; + newscript->GetAI = GetAI_mob_steamrigger_mechanic; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/steam_vault/boss_warlord_kalithresh.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/steam_vault/boss_warlord_kalithresh.cpp new file mode 100644 index 00000000000..49172341514 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/steam_vault/boss_warlord_kalithresh.cpp @@ -0,0 +1,255 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Warlord_Kalithres +SD%Complete: 65 +SDComment: Contains workarounds regarding warlord's rage spells not acting as expected. Both scripts here require review and fine tuning. +SDCategory: Coilfang Resevoir, The Steamvault +EndScriptData */ + +#include "precompiled.h" +#include "def_steam_vault.h" + +#define SAY_INTRO "You deem yourselves worthy simply because you bested my guards? Our work here will not be compromised!" +#define SOUND_INTRO 10390 + +#define SAY_REGEN "This is not nearly over..." +#define SOUND_REGEN 10391 + +#define SAY_AGGRO1 "Your head will roll!" +#define SOUND_AGGRO1 10392 +#define SAY_AGGRO2 "I despise all of your kind!" +#define SOUND_AGGRO2 10393 +#define SAY_AGGRO3 "Ba'ahntha sol'dorei!" +#define SOUND_AGGRO3 10394 + +#define SAY_SLAY1 "Scram, surface filth!" +#define SOUND_SLAY1 10395 +#define SAY_SLAY2 "Ah ha ha ha ha ha ha!" +#define SOUND_SLAY2 10396 + +#define SAY_DEATH "For her Excellency... for... Vashj!" +#define SOUND_DEATH 10397 + +#define SPELL_SPELL_REFLECTION 31534 +#define SPELL_IMPALE 39061 +#define SPELL_WARLORDS_RAGE 37081 +#define SPELL_WARLORDS_RAGE_NAGA 31543 + +#define SPELL_WARLORDS_RAGE_PROC 36453 + +struct MANGOS_DLL_DECL mob_naga_distillerAI : public ScriptedAI +{ + mob_naga_distillerAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance *pInstance; + + void Reset() + { + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + //hack, due to really weird spell behaviour :( + if( pInstance ) + if( pInstance->GetData(TYPE_DISTILLER) == IN_PROGRESS ) + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + } + + void Aggro(Unit *who) { } + + void StartRageGen(Unit *caster) + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + DoCast(m_creature,SPELL_WARLORDS_RAGE_NAGA,true); + if( pInstance ) pInstance->SetData(TYPE_DISTILLER,IN_PROGRESS); + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if( m_creature->GetHealth() <= damage ) + if( pInstance ) pInstance->SetData(TYPE_DISTILLER,DONE); + } +}; + +struct MANGOS_DLL_DECL boss_warlord_kalithreshAI : public ScriptedAI +{ + boss_warlord_kalithreshAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance *pInstance; + + uint32 Reflection_Timer; + uint32 Impale_Timer; + uint32 Rage_Timer; + bool CanRage; + + void Reset() + { + Reflection_Timer = 10000; + Impale_Timer = 30000; + Rage_Timer = 45000; + CanRage = false; + + if( pInstance ) pInstance->SetData(TYPE_WARLORD_KALITHRESH, NOT_STARTED); + } + + void Aggro(Unit *who) + { + switch(rand()%3) + { + case 0: + DoYell(SAY_AGGRO1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO1); + break; + case 1: + DoYell(SAY_AGGRO2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO2); + break; + case 2: + DoYell(SAY_AGGRO3, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO3); + break; + } + + if( pInstance ) pInstance->SetData(TYPE_WARLORD_KALITHRESH, IN_PROGRESS); + } + + void KilledUnit(Unit* victim) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_SLAY1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(victim, SOUND_SLAY1); + break; + case 1: + DoYell(SAY_SLAY2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(victim, SOUND_SLAY2); + break; + } + } + + Creature* SelectCreatureInGrid(uint32 entry, float range) + { + Creature* pCreature = NULL; + + CellPair pair(MaNGOS::ComputeCellPair(m_creature->GetPositionX(), m_creature->GetPositionY())); + Cell cell(pair); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck creature_check(*m_creature, entry, true, range); + MaNGOS::CreatureLastSearcher searcher(pCreature, creature_check); + + TypeContainerVisitor, GridTypeMapContainer> creature_searcher(searcher); + + CellLock cell_lock(cell, pair); + cell_lock->Visit(cell_lock, creature_searcher,*(m_creature->GetMap())); + + return pCreature; + } + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + //hack :( + if( spell->Id == SPELL_WARLORDS_RAGE_PROC ) + if( pInstance ) + if( pInstance->GetData(TYPE_DISTILLER) == DONE ) + m_creature->RemoveAurasDueToSpell(SPELL_WARLORDS_RAGE_PROC); + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_DEATH); + + if( pInstance ) pInstance->SetData(TYPE_WARLORD_KALITHRESH, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if( Rage_Timer < diff ) + { + Creature* distiller = SelectCreatureInGrid(17954, 100); + if( distiller ) + { + DoYell(SAY_REGEN, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_REGEN); + DoCast(m_creature,SPELL_WARLORDS_RAGE); + ((mob_naga_distillerAI*)distiller->AI())->StartRageGen(m_creature); + } + Rage_Timer = 45000; + }else Rage_Timer -= diff; + + //Reflection_Timer + if( Reflection_Timer < diff ) + { + DoCast(m_creature, SPELL_SPELL_REFLECTION); + Reflection_Timer = 20000+rand()%5000; + }else Reflection_Timer -= diff; + + //Impale_Timer + if( Impale_Timer < diff ) + { + if( Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target,SPELL_IMPALE); + + Impale_Timer = 7500+rand()%5000; + }else Impale_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_naga_distiller(Creature *_Creature) +{ + return new mob_naga_distillerAI (_Creature); +} + +CreatureAI* GetAI_boss_warlord_kalithresh(Creature *_Creature) +{ + return new boss_warlord_kalithreshAI (_Creature); +} + +void AddSC_boss_warlord_kalithresh() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="mob_naga_distiller"; + newscript->GetAI = GetAI_mob_naga_distiller; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_warlord_kalithresh"; + newscript->GetAI = GetAI_boss_warlord_kalithresh; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/steam_vault/def_steam_vault.h b/src/bindings/scripts/scripts/zone/coilfang_resevoir/steam_vault/def_steam_vault.h new file mode 100644 index 00000000000..0f8ae80fe2c --- /dev/null +++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/steam_vault/def_steam_vault.h @@ -0,0 +1,16 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_STEAM_VAULT_H +#define DEF_STEAM_VAULT_H + +#define TYPE_HYDROMANCER_THESPIA 1 +#define TYPE_MEKGINEER_STEAMRIGGER 2 +#define TYPE_WARLORD_KALITHRESH 3 +#define TYPE_DISTILLER 4 + +#define DATA_MEKGINEERSTEAMRIGGER 5 +#define DATA_KALITRESH 6 +#define DATA_THESPIA 7 +#endif diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/steam_vault/instance_steam_vault.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/steam_vault/instance_steam_vault.cpp new file mode 100644 index 00000000000..0e524f3d4b8 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/steam_vault/instance_steam_vault.cpp @@ -0,0 +1,170 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Steam_Vault +SD%Complete: 60 +SDComment: Workaround for opening of Main Chamber door. Mangos does not support scripting of Gameobject as this instance require. +SDCategory: Coilfang Resevoir, The Steamvault +EndScriptData */ + +#include "precompiled.h" +#include "def_steam_vault.h" + +#define ENCOUNTERS 4 + +#define MAIN_CHAMBERS_DOOR 183049 //door opened when hydromancer and mekgineer are died +#define ACCESS_PANEL_HYDRO 184125 +#define ACCESS_PANEL_MEK 184126 + +/* Steam Vaults encounters: +1 - Hydromancer Thespia Event +2 - Mekgineer Steamrigger Event +3 - Warlord Kalithresh Event +*/ + +struct MANGOS_DLL_DECL instance_steam_vault : public ScriptedInstance +{ + instance_steam_vault(Map *Map) : ScriptedInstance(Map) {Initialize();}; + + uint64 ThespiaGUID; + uint64 MekgineerGUID; + uint64 KalithreshGUID; + uint32 Encounter[ENCOUNTERS]; + + bool IsHydromancerDead, IsMekgineerDead; + GameObject *MainChambersDoor; + GameObject *AccessPanelHydro; + GameObject *AccessPanelMek; + + void Initialize() + { + ThespiaGUID = 0; + MekgineerGUID = 0; + KalithreshGUID = 0; + IsHydromancerDead = false; + IsMekgineerDead = false; + MainChambersDoor = NULL; + AccessPanelHydro = NULL; + AccessPanelMek = NULL; + + for(uint8 i = 0; i < ENCOUNTERS; i++) + Encounter[i] = false; + } + + bool IsEncounterInProgress() const + { + for(uint8 i = 0; i < ENCOUNTERS; i++) + if( Encounter[i] ) return true; + + return false; + } + + void OnCreatureCreate(Creature *creature, uint32 creature_entry) + { + switch(creature_entry) + { + case 17797: ThespiaGUID = creature->GetGUID(); break; + case 17796: MekgineerGUID = creature->GetGUID(); break; + case 17798: KalithreshGUID = creature->GetGUID(); break; + } + } + + void OnObjectCreate(GameObject *go) + { + switch(go->GetEntry()) + { + case MAIN_CHAMBERS_DOOR: MainChambersDoor = go; break; + case ACCESS_PANEL_HYDRO: AccessPanelHydro = go; break; + case ACCESS_PANEL_MEK: AccessPanelMek = go; break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case TYPE_HYDROMANCER_THESPIA: + if(data == DONE) + { + IsHydromancerDead = true; + if( IsMekgineerDead && MainChambersDoor ) + MainChambersDoor->SetGoState(0); + } + Encounter[0] = data; + break; + case TYPE_MEKGINEER_STEAMRIGGER: + if(data == DONE) + { + IsMekgineerDead = true; + if( IsHydromancerDead && MainChambersDoor ) + MainChambersDoor->SetGoState(0); + } + Encounter[1] = data; + break; + case TYPE_WARLORD_KALITHRESH: + Encounter[2] = data; + break; + case TYPE_DISTILLER: + Encounter[3] = data; + break; + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case TYPE_HYDROMANCER_THESPIA: + return Encounter[0]; + case TYPE_MEKGINEER_STEAMRIGGER: + return Encounter[1]; + case TYPE_WARLORD_KALITHRESH: + return Encounter[2]; + case TYPE_DISTILLER: + return Encounter[3]; + } + return 0; + } + + uint64 GetData64(uint32 data) + { + switch(data) + { + case DATA_THESPIA: + return ThespiaGUID; + case DATA_MEKGINEERSTEAMRIGGER: + return MekgineerGUID; + case DATA_KALITRESH: + return KalithreshGUID; + } + return 0; + } +}; + +InstanceData* GetInstanceData_instance_steam_vault(Map* map) +{ + return new instance_steam_vault(map); +} + +void AddSC_instance_steam_vault() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_steam_vault"; + newscript->GetInstanceData = GetInstanceData_instance_steam_vault; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/underbog/boss_ghazan.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/underbog/boss_ghazan.cpp new file mode 100644 index 00000000000..6bb2635fa7b --- /dev/null +++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/underbog/boss_ghazan.cpp @@ -0,0 +1,78 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Ghazan +SD%Complete: 100 +SDComment: +SDCategory: Coilfang Resevoir, Underbog +EndScriptData */ + +#include "../../../creature/simple_ai.h" + +/* +--== Ghaz'an ==-- +*Acid Spit - 34290; timer: 8sec +*Enrage - 20% hp; 40683 +*Tail Sweep - 34267; timer: ~10sec +*Acid Breath - 34268; timer: 5sec +*/ + +CreatureAI* GetAI_boss_ghazan(Creature *_Creature) +{ + SimpleAI* ai = new SimpleAI (_Creature); + + // Acid Spit - 34290; timer: 8sec + ai->Spell[0].Enabled = true; + ai->Spell[0].Spell_Id = 34290; + ai->Spell[0].Cooldown = 8000; + ai->Spell[0].First_Cast = 8000; + ai->Spell[0].Cast_Target_Type = CAST_SELF; + + // Acid Breath - 34268; timer: 5sec + ai->Spell[1].Enabled = true; + ai->Spell[1].Spell_Id = 34268; + ai->Spell[1].Cooldown = 5000; + ai->Spell[1].First_Cast = 5000; + ai->Spell[1].Cast_Target_Type = CAST_SELF; + + // Tail Sweep - 34267 + ai->Spell[2].Enabled = true; + ai->Spell[2].Spell_Id = 34267; + ai->Spell[2].Cooldown = 10000; + ai->Spell[2].First_Cast = 10000; + ai->Spell[2].Cast_Target_Type = CAST_SELF; + + // Enrage - 20% hp; 40683 + ai->Spell[3].Enabled = true; + ai->Spell[3].Spell_Id = 40683; + ai->Spell[3].Cooldown = -1; + ai->Spell[3].First_Cast = -80; + ai->Spell[3].Cast_Target_Type = CAST_SELF; + + ai->EnterEvadeMode(); + + return ai; +} + +void AddSC_boss_ghazan() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_ghazan"; + newscript->GetAI = GetAI_boss_ghazan; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/underbog/boss_hungarfen.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/underbog/boss_hungarfen.cpp new file mode 100644 index 00000000000..663db35a946 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/underbog/boss_hungarfen.cpp @@ -0,0 +1,156 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Hungarfen +SD%Complete: 95 +SDComment: Need confirmation if spell data are same in both modes. Summons should have faster rate in heroic +SDCategory: Coilfang Resevoir, Underbog +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_FOUL_SPORES 31673 +#define SPELL_ACID_GEYSER 38739 + +struct MANGOS_DLL_DECL boss_hungarfenAI : public ScriptedAI +{ + boss_hungarfenAI(Creature *c) : ScriptedAI(c) + { + HeroicMode = m_creature->GetMap()->IsHeroic(); + Reset(); + } + + bool HeroicMode; + bool Root; + uint32 Mushroom_Timer; + uint32 AcidGeyser_Timer; + + void Reset() + { + Root = false; + Mushroom_Timer = 5000; // 1 mushroom after 5s, then one per 10s. This should be different in heroic mode + AcidGeyser_Timer = 10000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if( (m_creature->GetHealth()*100) / m_creature->GetMaxHealth() <= 20 ) + { + if( !Root ) + { + DoCast(m_creature,SPELL_FOUL_SPORES); + Root = true; + } + } + + if( Mushroom_Timer < diff ) + { + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + m_creature->SummonCreature(17990, target->GetPositionX()+(rand()%8), target->GetPositionY()+(rand()%8), target->GetPositionZ(), (rand()%5), TEMPSUMMON_TIMED_DESPAWN, 22000); + else + m_creature->SummonCreature(17990, m_creature->GetPositionX()+(rand()%8), m_creature->GetPositionY()+(rand()%8), m_creature->GetPositionZ(), (rand()%5), TEMPSUMMON_TIMED_DESPAWN, 22000); + + Mushroom_Timer = 10000; + }else Mushroom_Timer -= diff; + + if( AcidGeyser_Timer < diff ) + { + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target,SPELL_ACID_GEYSER); + AcidGeyser_Timer = 10000+rand()%7500; + }else AcidGeyser_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_hungarfen(Creature *_Creature) +{ + return new boss_hungarfenAI (_Creature); +} + +#define SPELL_SPORE_CLOUD 34168 +#define SPELL_PUTRID_MUSHROOM 31690 +#define SPELL_GROW 31698 + +struct MANGOS_DLL_DECL mob_underbog_mushroomAI : public ScriptedAI +{ + mob_underbog_mushroomAI(Creature *c) : ScriptedAI(c) { Reset(); } + + bool Stop; + uint32 Grow_Timer; + uint32 Shrink_Timer; + + void Reset() + { + Stop = false; + Grow_Timer = 0; + Shrink_Timer = 20000; + + DoCast(m_creature,SPELL_PUTRID_MUSHROOM,true); + DoCast(m_creature,SPELL_SPORE_CLOUD,true); + } + + void MoveInLineOfSight(Unit *who) { return; } + + void AttackStart(Unit* who) { return; } + + void Aggro(Unit* who) { } + + void UpdateAI(const uint32 diff) + { + if( Stop ) + return; + + if( Grow_Timer <= diff ) + { + DoCast(m_creature,SPELL_GROW); + Grow_Timer = 3000; + }else Grow_Timer -= diff; + + if( Shrink_Timer <= diff ) + { + m_creature->RemoveAurasDueToSpell(SPELL_GROW); + Stop = true; + }else Shrink_Timer -= diff; + } +}; +CreatureAI* GetAI_mob_underbog_mushroom(Creature *_Creature) +{ + return new mob_underbog_mushroomAI (_Creature); +} + +void AddSC_boss_hungarfen() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_hungarfen"; + newscript->GetAI = GetAI_boss_hungarfen; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_underbog_mushroom"; + newscript->GetAI = GetAI_mob_underbog_mushroom; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/darkshore/darkshore.cpp b/src/bindings/scripts/scripts/zone/darkshore/darkshore.cpp new file mode 100644 index 00000000000..02acd88a491 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/darkshore/darkshore.cpp @@ -0,0 +1,24 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Darkshore +SD%Complete: 0 +SDComment: Placeholder +SDCategory: Darkshore +EndScriptData */ + +#include "precompiled.h" diff --git a/src/bindings/scripts/scripts/zone/deadmines/deadmines.cpp b/src/bindings/scripts/scripts/zone/deadmines/deadmines.cpp new file mode 100644 index 00000000000..535d8c86410 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/deadmines/deadmines.cpp @@ -0,0 +1,24 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Deadmines +SD%Complete: 0 +SDComment: Placeholder +SDCategory: Deadmines +EndScriptData */ + +#include "precompiled.h" diff --git a/src/bindings/scripts/scripts/zone/deadmines/instance_deadmines.cpp b/src/bindings/scripts/scripts/zone/deadmines/instance_deadmines.cpp new file mode 100644 index 00000000000..d97db663273 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/deadmines/instance_deadmines.cpp @@ -0,0 +1,22 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Deadmines +SD%Complete: 0 +SDComment: Placeholder +SDCategory: Deadmines +EndScriptData */ diff --git a/src/bindings/scripts/scripts/zone/dun_morogh/dun_morogh.cpp b/src/bindings/scripts/scripts/zone/dun_morogh/dun_morogh.cpp new file mode 100644 index 00000000000..d584dc0690e --- /dev/null +++ b/src/bindings/scripts/scripts/zone/dun_morogh/dun_morogh.cpp @@ -0,0 +1,98 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Dun_Morogh +SD%Complete: 50 +SDComment: Quest support: 1783 +SDCategory: Dun Morogh +EndScriptData */ + +/* ContentData +npc_narm_faulk +EndContentData */ + +#include "precompiled.h" + +/*###### +## npc_narm_faulk +######*/ + +#define SAY_HEAL "Thank you, dear Paladin, you just saved my life." + +struct MANGOS_DLL_DECL npc_narm_faulkAI : public ScriptedAI +{ + uint32 lifeTimer; + bool spellHit; + + npc_narm_faulkAI(Creature *c) : ScriptedAI(c) {Reset();} + + void Reset() + { + lifeTimer = 120000; + m_creature->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 32); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1,7); // lay down + spellHit = false; + } + + void Aggro(Unit *who) + { + } + + void MoveInLineOfSight(Unit *who) + { + return; + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->GetUInt32Value(UNIT_FIELD_BYTES_1)) + { + if(lifeTimer < diff) + m_creature->AI()->EnterEvadeMode(); + else + lifeTimer -= diff; + } + } + + void SpellHit(Unit *Hitter, const SpellEntry *Spellkind) + { + if(Spellkind->Id == 8593 && !spellHit) + { + DoCast(m_creature,32343); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1,0); + m_creature->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0); + //m_creature->RemoveAllAuras(); + DoSay(SAY_HEAL,LANG_COMMON,NULL); + spellHit = true; + } + } + +}; +CreatureAI* GetAI_npc_narm_faulk(Creature *_Creature) +{ + return new npc_narm_faulkAI (_Creature); +} + +void AddSC_dun_morogh() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npc_narm_faulk"; + newscript->GetAI = GetAI_npc_narm_faulk; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/dustwallow_marsh/dustwallow_marsh.cpp b/src/bindings/scripts/scripts/zone/dustwallow_marsh/dustwallow_marsh.cpp new file mode 100644 index 00000000000..a29dda1c811 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/dustwallow_marsh/dustwallow_marsh.cpp @@ -0,0 +1,231 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Dustwallow_Marsh +SD%Complete: 95 +SDComment: Quest support: 11180, 558, 11126. Vendor Nat Pagle +SDCategory: Dustwallow Marsh +EndScriptData */ + +/* ContentData +mobs_risen_husk_spirit +npc_restless_apparition +npc_deserter_agitator +npc_lady_jaina_proudmoore +npc_nat_pagle +EndContentData */ + +#include "precompiled.h" + +/*###### +## mobs_risen_husk_spirit +######*/ + +#define SPELL_SUMMON_RESTLESS_APPARITION 42511 +#define SPELL_CONSUME_FLESH 37933 //Risen Husk +#define SPELL_INTANGIBLE_PRESENCE 43127 //Risen Spirit + +struct MANGOS_DLL_DECL mobs_risen_husk_spiritAI : public ScriptedAI +{ + mobs_risen_husk_spiritAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 ConsumeFlesh_Timer; + uint32 IntangiblePresence_Timer; + + void Reset() + { + ConsumeFlesh_Timer = 10000; + IntangiblePresence_Timer = 5000; + } + + void Aggro(Unit* who) { } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if( done_by->GetTypeId() == TYPEID_PLAYER ) + if( damage >= m_creature->GetHealth() && ((Player*)done_by)->GetQuestStatus(11180) == QUEST_STATUS_INCOMPLETE ) + m_creature->CastSpell(done_by,SPELL_SUMMON_RESTLESS_APPARITION,false); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if( ConsumeFlesh_Timer < diff ) + { + if( m_creature->GetEntry() == 23555 ) + DoCast(m_creature->getVictim(),SPELL_CONSUME_FLESH); + ConsumeFlesh_Timer = 15000; + } else ConsumeFlesh_Timer -= diff; + + if( IntangiblePresence_Timer < diff ) + { + if( m_creature->GetEntry() == 23554 ) + DoCast(m_creature->getVictim(),SPELL_INTANGIBLE_PRESENCE); + IntangiblePresence_Timer = 20000; + } else IntangiblePresence_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_mobs_risen_husk_spirit(Creature *_Creature) +{ + return new mobs_risen_husk_spiritAI (_Creature); +} + +/*###### +## npc_restless_apparition +######*/ + +bool GossipHello_npc_restless_apparition(Player *player, Creature *_Creature) +{ + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + player->TalkedToCreature(_Creature->GetEntry(), _Creature->GetGUID()); + _Creature->SetInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + return true; +} + +/*###### +## npc_deserter_agitator +######*/ + +struct MANGOS_DLL_DECL npc_deserter_agitatorAI : public ScriptedAI +{ + npc_deserter_agitatorAI(Creature *c) : ScriptedAI(c) {Reset();} + + void Reset() + { + m_creature->setFaction(894); + } + + void Aggro(Unit* who) {} +}; + +CreatureAI* GetAI_npc_deserter_agitator(Creature *_Creature) +{ + return new npc_deserter_agitatorAI (_Creature); +} + +bool GossipHello_npc_deserter_agitator(Player *player, Creature *_Creature) +{ + if (player->GetQuestStatus(11126) == QUEST_STATUS_INCOMPLETE) + { + _Creature->setFaction(1883); + player->TalkedToCreature(_Creature->GetEntry(), _Creature->GetGUID()); + } + else + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + return true; +} + +/*###### +## npc_lady_jaina_proudmoore +######*/ + +#define GOSSIP_ITEM_JAINA "I know this is rather silly but i have a young ward who is a bit shy and would like your autograph." + +bool GossipHello_npc_lady_jaina_proudmoore(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if( player->GetQuestStatus(558) == QUEST_STATUS_INCOMPLETE ) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_JAINA, GOSSIP_SENDER_MAIN, GOSSIP_SENDER_INFO ); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_lady_jaina_proudmoore(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if( action == GOSSIP_SENDER_INFO ) + { + player->SEND_GOSSIP_MENU( 7012, _Creature->GetGUID() ); + player->CastSpell( player, 23122, false); + } + return true; +} + +/*###### +## npc_nat_pagle +######*/ + +bool GossipHello_npc_nat_pagle(Player *player, Creature *_Creature) +{ + if(_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if(_Creature->isVendor() && player->GetQuestRewardStatus(8227)) + { + player->ADD_GOSSIP_ITEM(1, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + player->SEND_GOSSIP_MENU( 7640, _Creature->GetGUID() ); + } + else + player->SEND_GOSSIP_MENU( 7638, _Creature->GetGUID() ); + + return true; +} + +bool GossipSelect_npc_nat_pagle(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + if(action == GOSSIP_ACTION_TRADE) + player->SEND_VENDORLIST( _Creature->GetGUID() ); + + return true; +} + +/*###### +## +######*/ + +void AddSC_dustwallow_marsh() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="mobs_risen_husk_spirit"; + newscript->GetAI = GetAI_mobs_risen_husk_spirit; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_restless_apparition"; + newscript->pGossipHello = &GossipHello_npc_restless_apparition; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_deserter_agitator"; + newscript->GetAI = GetAI_npc_deserter_agitator; + newscript->pGossipHello = &GossipHello_npc_deserter_agitator; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_lady_jaina_proudmoore"; + newscript->pGossipHello = &GossipHello_npc_lady_jaina_proudmoore; + newscript->pGossipSelect = &GossipSelect_npc_lady_jaina_proudmoore; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_nat_pagle"; + newscript->pGossipHello = &GossipHello_npc_nat_pagle; + newscript->pGossipSelect = &GossipSelect_npc_nat_pagle; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/eastern_plaguelands/eastern_plaguelands.cpp b/src/bindings/scripts/scripts/zone/eastern_plaguelands/eastern_plaguelands.cpp new file mode 100644 index 00000000000..aa7ae7b2879 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/eastern_plaguelands/eastern_plaguelands.cpp @@ -0,0 +1,180 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Eastern_Plaguelands +SD%Complete: 100 +SDComment: Quest support: 5211, 5742. Special vendor Augustus the Touched +SDCategory: Eastern Plaguelands +EndScriptData */ + +/* ContentData +mobs_ghoul_flayer +npc_augustus_the_touched +npc_darrowshire_spirit +npc_tirion_fordring +EndContentData */ + +#include "precompiled.h" + +//id8530 - cannibal ghoul +//id8531 - gibbering ghoul +//id8532 - diseased flayer + +struct MANGOS_DLL_DECL mobs_ghoul_flayerAI : public ScriptedAI +{ + mobs_ghoul_flayerAI(Creature *c) : ScriptedAI(c) {Reset();} + + void Reset() { } + + void Aggro(Unit* who) { } + + void JustDied(Unit* Killer) + { + if( Killer->GetTypeId() == TYPEID_PLAYER ) + DoSpawnCreature(11064,0,0,0,0,TEMPSUMMON_TIMED_DESPAWN,60000); + } + +}; + +CreatureAI* GetAI_mobs_ghoul_flayer(Creature *_Creature) +{ + return new mobs_ghoul_flayerAI (_Creature); +} + +/*###### +## npc_augustus_the_touched +######*/ + +bool GossipHello_npc_augustus_the_touched(Player *player, Creature *_Creature) +{ + if( _Creature->isQuestGiver() ) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if( _Creature->isVendor() && player->GetQuestRewardStatus(6164) ) + player->ADD_GOSSIP_ITEM(1, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(),_Creature->GetGUID()); + return true; +} + +bool GossipSelect_npc_augustus_the_touched(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if( action == GOSSIP_ACTION_TRADE ) + player->SEND_VENDORLIST( _Creature->GetGUID() ); + return true; +} + +/*###### +## npc_darrowshire_spirit +######*/ + +#define SPELL_SPIRIT_SPAWNIN 17321 + +struct MANGOS_DLL_DECL npc_darrowshire_spiritAI : public ScriptedAI +{ + npc_darrowshire_spiritAI(Creature *c) : ScriptedAI(c) {Reset();} + + void Reset() + { + DoCast(m_creature,SPELL_SPIRIT_SPAWNIN); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void Aggro(Unit *who) { } + +}; +CreatureAI* GetAI_npc_darrowshire_spirit(Creature *_Creature) +{ + return new npc_darrowshire_spiritAI (_Creature); +} + +bool GossipHello_npc_darrowshire_spirit(Player *player, Creature *_Creature) +{ + player->SEND_GOSSIP_MENU(3873,_Creature->GetGUID()); + player->TalkedToCreature(_Creature->GetEntry(), _Creature->GetGUID()); + _Creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + return true; +} + +/*###### +## npc_tirion_fordring +######*/ + +bool GossipHello_npc_tirion_fordring(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if (player->GetQuestStatus(5742) == QUEST_STATUS_INCOMPLETE && player->getStandState() == PLAYER_STATE_SIT ) + player->ADD_GOSSIP_ITEM( 0, "I am ready to hear your tale, Tirion.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_tirion_fordring(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF+1: + player->ADD_GOSSIP_ITEM( 0, "Thank you, Tirion. What of your identity?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->SEND_GOSSIP_MENU(4493, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + player->ADD_GOSSIP_ITEM( 0, "That is terrible.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->SEND_GOSSIP_MENU(4494, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + player->ADD_GOSSIP_ITEM( 0, "I will, Tirion.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->SEND_GOSSIP_MENU(4495, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + player->CLOSE_GOSSIP_MENU(); + player->AreaExploredOrEventHappens(5742); + break; + } + return true; +} + +void AddSC_eastern_plaguelands() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="mobs_ghoul_flayer"; + newscript->GetAI = GetAI_mobs_ghoul_flayer; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_augustus_the_touched"; + newscript->pGossipHello = &GossipHello_npc_augustus_the_touched; + newscript->pGossipSelect = &GossipSelect_npc_augustus_the_touched; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_darrowshire_spirit"; + newscript->GetAI = GetAI_npc_darrowshire_spirit; + newscript->pGossipHello = &GossipHello_npc_darrowshire_spirit; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_tirion_fordring"; + newscript->pGossipHello = &GossipHello_npc_tirion_fordring; + newscript->pGossipSelect = &GossipSelect_npc_tirion_fordring; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/elwynn_forest/elwynn_forest.cpp b/src/bindings/scripts/scripts/zone/elwynn_forest/elwynn_forest.cpp new file mode 100644 index 00000000000..0fc754f91c6 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/elwynn_forest/elwynn_forest.cpp @@ -0,0 +1,98 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Elwynn_Forest +SD%Complete: 50 +SDComment: Quest support: 1786 +SDCategory: Elwynn Forest +EndScriptData */ + +/* ContentData +npc_henze_faulk +EndContentData */ + +#include "precompiled.h" + +/*###### +## npc_henze_faulk +######*/ + +#define SAY_HEAL "Thank you, dear Paladin, you just saved my life." + +struct MANGOS_DLL_DECL npc_henze_faulkAI : public ScriptedAI +{ + uint32 lifeTimer; + bool spellHit; + + npc_henze_faulkAI(Creature *c) : ScriptedAI(c) {Reset();} + + void Reset() + { + lifeTimer = 120000; + m_creature->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 32); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1,7); // lay down + spellHit = false; + } + + void Aggro(Unit *who) + { + } + + void MoveInLineOfSight(Unit *who) + { + return; + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->GetUInt32Value(UNIT_FIELD_BYTES_1)) + { + if(lifeTimer < diff) + m_creature->AI()->EnterEvadeMode(); + else + lifeTimer -= diff; + } + } + + void SpellHit(Unit *Hitter, const SpellEntry *Spellkind) + { + if(Spellkind->Id == 8593 && !spellHit) + { + DoCast(m_creature,32343); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1,0); + m_creature->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0); + //m_creature->RemoveAllAuras(); + DoSay(SAY_HEAL,LANG_COMMON,NULL); + spellHit = true; + } + } + +}; +CreatureAI* GetAI_npc_henze_faulk(Creature *_Creature) +{ + return new npc_henze_faulkAI (_Creature); +} + +void AddSC_elwynn_forest() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npc_henze_faulk"; + newscript->GetAI = GetAI_npc_henze_faulk; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/eversong_woods/eversong_woods.cpp b/src/bindings/scripts/scripts/zone/eversong_woods/eversong_woods.cpp new file mode 100644 index 00000000000..aab21ed5cb3 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/eversong_woods/eversong_woods.cpp @@ -0,0 +1,163 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Eversong_Woods +SD%Complete: 100 +SDComment: Quest support: 8346, 8483 +SDCategory: Eversong Woods +EndScriptData */ + +/* ContentData +mobs_mana_tapped +npc_prospector_anvilward +EndContentData */ + +#include "precompiled.h" +#include "../../npc/npc_escortAI.h" + +/*###### +## mobs_mana_tapped +######*/ + +struct MANGOS_DLL_DECL mobs_mana_tappedAI : public ScriptedAI +{ + mobs_mana_tappedAI(Creature *c) : ScriptedAI(c) {Reset();} + + void Reset() { } + + void Aggro(Unit *who) { } + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if( caster->GetTypeId() == TYPEID_PLAYER) + if( ((Player*)caster)->GetQuestStatus(8346) == QUEST_STATUS_INCOMPLETE && !((Player*)caster)->GetReqKillOrCastCurrentCount(8346, m_creature->GetEntry()) && spell->Id == 28734) + ((Player*)caster)->CastedCreatureOrGO(15468, m_creature->GetGUID(), spell->Id); + return; + } +}; +CreatureAI* GetAI_mobs_mana_tapped(Creature *_Creature) +{ + return new mobs_mana_tappedAI (_Creature); +} + +/*###### +## npc_prospector_anvilward +######*/ + +#define QUEST_THE_DWARVEN_SPY 8483 + +struct MANGOS_DLL_DECL npc_prospector_anvilwardAI : public npc_escortAI +{ + // CreatureAI functions + npc_prospector_anvilwardAI(Creature *c) : npc_escortAI(c) {Reset();} + + // Pure Virtual Functions + void WaypointReached(uint32 i) + { + switch (i) + { + case 0: + m_creature->Say("Very well. Let's see what you have to show me, $N.", LANG_UNIVERSAL, PlayerGUID); + break; + case 5: + m_creature->Say("What manner of trick is this, $R? If you seek to ambush me, I warn you I will not go down quietly!", LANG_UNIVERSAL, PlayerGUID); + break; + case 6: + m_creature->setFaction(24); + break; + } + } + + void Aggro(Unit* who) { } + + void Reset() + { + //Default npc faction + m_creature->setFaction(35); + } + + void JustDied(Unit* killer) + { + //Default npc faction + m_creature->setFaction(35); + } + + void UpdateAI(const uint32 diff) + { + npc_escortAI::UpdateAI(diff); //Must update npc_escortAI + + } +}; + +CreatureAI* GetAI_npc_prospector_anvilward(Creature *_Creature) +{ + npc_prospector_anvilwardAI* thisAI = new npc_prospector_anvilwardAI(_Creature); + + thisAI->AddWaypoint(0, 9294.78, -6682.51, 22.42); + thisAI->AddWaypoint(1, 9298.27, -6667.99, 22.42); + thisAI->AddWaypoint(2, 9309.63, -6658.84, 22.43); + thisAI->AddWaypoint(3, 9304.43, -6649.31, 26.46); + thisAI->AddWaypoint(4, 9298.83, -6648.00, 28.61); + thisAI->AddWaypoint(5, 9291.06, -6653.46, 31.83,2500); + thisAI->AddWaypoint(6, 9289.08, -6660.17, 31.85,5000); + thisAI->AddWaypoint(7, 9291.06, -6653.46, 31.83); + + return (CreatureAI*)thisAI; +} + +bool GossipHello_npc_prospector_anvilward(Player *player, Creature *_Creature) +{ + if( player->GetQuestStatus(QUEST_THE_DWARVEN_SPY) == QUEST_STATUS_INCOMPLETE ) + player->ADD_GOSSIP_ITEM(0, "I need a moment of your time, sir.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + player->SEND_GOSSIP_MENU(8239, _Creature->GetGUID()); + return true; +} + +bool GossipSelect_npc_prospector_anvilward(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + switch(action) + { + case GOSSIP_ACTION_INFO_DEF+1: + player->ADD_GOSSIP_ITEM( 0, "Why... yes, of course. I've something to show you right inside this building, Mr. Anvilward.",GOSSIP_SENDER_MAIN,GOSSIP_ACTION_INFO_DEF+2); + player->SEND_GOSSIP_MENU(8240, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + player->CLOSE_GOSSIP_MENU(); + //attack,defend,walk + ((npc_escortAI*)(_Creature->AI()))->Start(true, true, false, player->GetGUID()); + break; + } + return true; +} + +void AddSC_eversong_woods() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="mobs_mana_tapped"; + newscript->GetAI = GetAI_mobs_mana_tapped; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name= "npc_prospector_anvilward"; + newscript->GetAI = GetAI_npc_prospector_anvilward; + newscript->pGossipHello = &GossipHello_npc_prospector_anvilward; + newscript->pGossipSelect = &GossipSelect_npc_prospector_anvilward; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/felwood/felwood.cpp b/src/bindings/scripts/scripts/zone/felwood/felwood.cpp new file mode 100644 index 00000000000..4e8b6e3cdc3 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/felwood/felwood.cpp @@ -0,0 +1,89 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Felwood +SD%Complete: 95 +SDComment: Quest support: related to 4101&4102 (To obtain Cenarion Beacon) +SDCategory: Felwood +EndScriptData */ + +/* ContentData +npcs_riverbreeze_and_silversky +EndContentData */ + +#include "precompiled.h" + +/*###### +## npcs_riverbreeze_and_silversky +######*/ + +#define GOSSIP_ITEM_BEACON "Please make me a Cenarion Beacon" + +bool GossipHello_npcs_riverbreeze_and_silversky(Player *player, Creature *_Creature) +{ + uint32 eCreature = _Creature->GetEntry(); + + if( _Creature->isQuestGiver() ) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if( eCreature==9528 ) + { + if( player->GetQuestRewardStatus(4101) ) + { + player->ADD_GOSSIP_ITEM(0, GOSSIP_ITEM_BEACON, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + player->SEND_GOSSIP_MENU(2848, _Creature->GetGUID()); + }else if( player->GetTeam()==HORDE ) + player->SEND_GOSSIP_MENU(2845, _Creature->GetGUID()); + else + player->SEND_GOSSIP_MENU(2844, _Creature->GetGUID()); + } + + if( eCreature==9529 ) + { + if( player->GetQuestRewardStatus(4102) ) + { + player->ADD_GOSSIP_ITEM(0, GOSSIP_ITEM_BEACON, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + player->SEND_GOSSIP_MENU(2849, _Creature->GetGUID()); + }else if( player->GetTeam()==ALLIANCE ) + player->SEND_GOSSIP_MENU(2843, _Creature->GetGUID()); + else + player->SEND_GOSSIP_MENU(2842, _Creature->GetGUID()); + } + + return true; +} + +bool GossipSelect_npcs_riverbreeze_and_silversky(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + if( action==GOSSIP_ACTION_INFO_DEF+1 ) + { + player->CLOSE_GOSSIP_MENU(); + _Creature->CastSpell(player, 15120, false); + } + return true; +} + +void AddSC_felwood() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npcs_riverbreeze_and_silversky"; + newscript->pGossipHello = &GossipHello_npcs_riverbreeze_and_silversky; + newscript->pGossipSelect = &GossipSelect_npcs_riverbreeze_and_silversky; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/feralas/feralas.cpp b/src/bindings/scripts/scripts/zone/feralas/feralas.cpp new file mode 100644 index 00000000000..ef886eadc65 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/feralas/feralas.cpp @@ -0,0 +1,85 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Feralas +SD%Complete: 100 +SDComment: Quest support: 3520. Special vendor Gregan Brewspewer +SDCategory: Feralas +EndScriptData */ + +#include "precompiled.h" + +/*###### +## npc_gregan_brewspewer +######*/ + +bool GossipHello_npc_gregan_brewspewer(Player *player, Creature *_Creature) +{ + if( _Creature->isQuestGiver() ) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if( _Creature->isVendor() && player->GetQuestStatus(3909) == QUEST_STATUS_INCOMPLETE ) + player->ADD_GOSSIP_ITEM(0, "Buy somethin', will ya?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + player->SEND_GOSSIP_MENU(2433,_Creature->GetGUID()); + return true; +} + +bool GossipSelect_npc_gregan_brewspewer(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if( action == GOSSIP_ACTION_INFO_DEF+1 ) + { + player->ADD_GOSSIP_ITEM(1, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + player->SEND_GOSSIP_MENU(2434,_Creature->GetGUID()); + } + if( action == GOSSIP_ACTION_TRADE ) + player->SEND_VENDORLIST( _Creature->GetGUID() ); + return true; +} + +/*###### +## npc_screecher_spirit +######*/ + +bool GossipHello_npc_screecher_spirit(Player *player, Creature *_Creature) +{ + player->SEND_GOSSIP_MENU(2039,_Creature->GetGUID() ); + player->TalkedToCreature(_Creature->GetEntry(), _Creature->GetGUID()); + _Creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + return true; +} + +/*###### +## AddSC +######*/ + +void AddSC_feralas() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npc_gregan_brewspewer"; + newscript->pGossipHello = &GossipHello_npc_gregan_brewspewer; + newscript->pGossipSelect = &GossipSelect_npc_gregan_brewspewer; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_screecher_spirit"; + newscript->pGossipHello = &GossipHello_npc_screecher_spirit; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/ghostlands/ghostlands.cpp b/src/bindings/scripts/scripts/zone/ghostlands/ghostlands.cpp new file mode 100644 index 00000000000..759da44db12 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/ghostlands/ghostlands.cpp @@ -0,0 +1,134 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Ghostlands +SD%Complete: 100 +SDComment: Quest support: 9692. Obtain Budd's Guise of Zul'aman. Vendor Rathis Tomber +SDCategory: Ghostlands +EndScriptData */ + +/* ContentData +npc_blood_knight_dawnstar +npc_budd_nedreck +npc_rathis_tomber +EndContentData */ + +#include "precompiled.h" + +/*###### +## npc_blood_knight_dawnstar +######*/ + +bool GossipHello_npc_blood_knight_dawnstar(Player *player, Creature *_Creature) +{ + if (player->GetQuestStatus(9692) == QUEST_STATUS_INCOMPLETE && !player->HasItemCount(24226,1,true)) + player->ADD_GOSSIP_ITEM( 0, "Take Blood Knight Insignia", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_blood_knight_dawnstar(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + if (action == GOSSIP_ACTION_INFO_DEF+1) + { + ItemPosCountVec dest; + uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, 24226, 1, false); + if( msg == EQUIP_ERR_OK ) + { + player->StoreNewItem( dest, 24226, 1, true); + player->PlayerTalkClass->ClearMenus(); + } + } + return true; +} + +/*###### +## npc_budd_nedreck +######*/ + +bool GossipHello_npc_budd_nedreck(Player *player, Creature *_Creature) +{ + if( _Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if( player->GetQuestStatus(11166) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM(0,"You gave the crew disguises?",GOSSIP_SENDER_MAIN,GOSSIP_ACTION_INFO_DEF); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(),_Creature->GetGUID()); + return true; +} + +bool GossipSelect_npc_budd_nedreck(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if( action==GOSSIP_ACTION_INFO_DEF ) + { + player->CLOSE_GOSSIP_MENU(); + _Creature->CastSpell(player, 42540, false); + } + return true; +} + +/*###### +## npc_rathis_tomber +######*/ + +bool GossipHello_npc_rathis_tomber(Player *player, Creature *_Creature) +{ + if( _Creature->isQuestGiver() ) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if( _Creature->isVendor() && player->GetQuestRewardStatus(9152) ) + { + player->ADD_GOSSIP_ITEM(1, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + player->SEND_GOSSIP_MENU(8432,_Creature->GetGUID()); + }else + player->SEND_GOSSIP_MENU(8431,_Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_rathis_tomber(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if( action == GOSSIP_ACTION_TRADE ) + player->SEND_VENDORLIST( _Creature->GetGUID() ); + return true; +} + +void AddSC_ghostlands() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npc_blood_knight_dawnstar"; + newscript->pGossipHello = &GossipHello_npc_blood_knight_dawnstar; + newscript->pGossipSelect = &GossipSelect_npc_blood_knight_dawnstar; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_budd_nedreck"; + newscript->pGossipHello = &GossipHello_npc_budd_nedreck; + newscript->pGossipSelect = &GossipSelect_npc_budd_nedreck; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_rathis_tomber"; + newscript->pGossipHello = &GossipHello_npc_rathis_tomber; + newscript->pGossipSelect = &GossipSelect_npc_rathis_tomber; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/gruuls_lair/boss_gruul.cpp b/src/bindings/scripts/scripts/zone/gruuls_lair/boss_gruul.cpp new file mode 100644 index 00000000000..d43ac25f08c --- /dev/null +++ b/src/bindings/scripts/scripts/zone/gruuls_lair/boss_gruul.cpp @@ -0,0 +1,281 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Gruul +SD%Complete: 25 +SDComment: Ground Slam seriously messed up due to core problem +SDCategory: Gruul's Lair +EndScriptData */ + +#include "precompiled.h" +#include "def_gruuls_lair.h" + +#define SPELL_GROWTH 36300 +#define SPELL_CAVE_IN 36240 +#define SPELL_GROUND_SLAM 33525 // AoE Ground Slam applying Ground Slam to everyone with a script effect (most likely the knock back, we can code it to a set knockback) +#define SPELL_SHATTER_EFFECT 33671 +#define SPELL_HURTFUL_STRIKE 33813 +#define SPELL_REVERBERATION 36297 //AoE Silence +#define SPELL_GRONN_LORDS_GRASP 33572 //Already handled in GroundSlam +#define SPELL_STONED 33652 //-- Spell is self cast +#define SPELL_SHATTER 33654 +#define SPELL_MAGNETIC_PULL 28337 +#define SPELL_KNOCK_BACK 24199 //Knockback spell until correct implementation is made + +#define EMOTE_GROW "grows in size!" +#define SAY_AGGRO "Come.... and die." + +struct MANGOS_DLL_DECL boss_gruulAI : public ScriptedAI +{ + boss_gruulAI(Creature *c) : ScriptedAI(c) { Reset(); } + + ScriptedInstance *pInstance; + + uint32 Growth_Timer; + uint32 CaveIn_Timer; + uint32 GroundSlamTimer; + uint32 GroundSlamStage; + uint32 PerformingGroundSlam; + uint32 HurtfulStrike_Timer; + uint32 Reverberation_Timer; + + void Reset() + { + pInstance = (ScriptedInstance*)m_creature->GetInstanceData(); + + Growth_Timer= 30000; + CaveIn_Timer= 40000; + GroundSlamTimer= 35000; + GroundSlamStage= 0; + PerformingGroundSlam= false; + HurtfulStrike_Timer= 8000; + Reverberation_Timer= 60000+45000; + + if(pInstance) + pInstance->SetData(DATA_GRUULEVENT, 0); + } + + void JustDied(Unit* Killer) + { + if(pInstance) + pInstance->SetData(DATA_GRUULEVENT, 1); + } + + void Aggro(Unit *who) + { + + DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); + + if(pInstance) + pInstance->SetData(DATA_GRUULEVENT, 1); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + // Growth + // Gruul can cast this spell up to 30 times + if (Growth_Timer < diff) + { + DoCast(m_creature,SPELL_GROWTH); + DoTextEmote(EMOTE_GROW,NULL); + Growth_Timer = 30000; + }else Growth_Timer -= diff; + + if(PerformingGroundSlam) + { + if(GroundSlamTimer < diff) + { + switch(GroundSlamStage) + { + case 0: + { + //Begin the whole ordeal + std::list& m_threatlist = m_creature->getThreatManager().getThreatList(); + + std::vector knockback_targets; + + //First limit the list to only players + for(std::list::iterator itr = m_threatlist.begin(); itr!= m_threatlist.end(); ++itr) + { + Unit *target = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid()); + + if(target && target->GetTypeId() == TYPEID_PLAYER) + knockback_targets.push_back(target); + } + + //Now to totally disoriend those players + for(std::vector::iterator itr = knockback_targets.begin(); itr!= knockback_targets.end(); ++itr) + { + Unit *target = *itr; + Unit *target2 = *(knockback_targets.begin() + rand()%knockback_targets.size()); + + if(target && target2) + { + switch(rand()%2) + { + case 0: target2->CastSpell(target, SPELL_MAGNETIC_PULL, true, NULL, NULL, m_creature->GetGUID()); break; + case 1: target2->CastSpell(target, SPELL_KNOCK_BACK, true, NULL, NULL, m_creature->GetGUID()); break; + } + } + } + + GroundSlamTimer = 7000; + } break; + + case 1: + { + //Players are going to get stoned + std::list& m_threatlist = m_creature->getThreatManager().getThreatList(); + + for(std::list::iterator itr = m_threatlist.begin(); itr!= m_threatlist.end(); ++itr) + { + Unit *target = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid()); + + if(target) + { + target->RemoveAurasDueToSpell(SPELL_GRONN_LORDS_GRASP); + target->CastSpell(target, SPELL_STONED, true, NULL, NULL, m_creature->GetGUID()); + } + } + + GroundSlamTimer = 5000; + + } break; + + case 2: + { + //The dummy shatter spell is cast + DoCast(m_creature, SPELL_SHATTER); + + GroundSlamTimer = 1000; + + } break; + + case 3: + { + //Shatter takes effect + std::list& m_threatlist = m_creature->getThreatManager().getThreatList(); + + for(std::list::iterator itr = m_threatlist.begin(); itr!= m_threatlist.end(); ++itr) + { + Unit *target = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid()); + + if(target) + { + target->RemoveAurasDueToSpell(SPELL_STONED); + + if(target->GetTypeId() == TYPEID_PLAYER) + target->CastSpell(target, SPELL_SHATTER_EFFECT, false, NULL, NULL, m_creature->GetGUID()); + } + + } + + m_creature->GetMotionMaster()->Clear(); + + Unit *victim = m_creature->getVictim(); + if(victim) + { + m_creature->GetMotionMaster()->MoveChase(victim); + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, victim->GetGUID()); + } + + PerformingGroundSlam = false; + + GroundSlamTimer =120000; + HurtfulStrike_Timer= 8000; + if(Reverberation_Timer < 10000) //Give a little time to the players to undo the damage from shatter + Reverberation_Timer += 10000; + + } break; + } + + GroundSlamStage++; + } + else + GroundSlamTimer-=diff; + } + else + { + // Hurtful Strike + if (HurtfulStrike_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_TOPAGGRO,1); + + if (target && m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE)) + DoCast(target,SPELL_HURTFUL_STRIKE); + else + DoCast(m_creature->getVictim(),SPELL_HURTFUL_STRIKE); + + HurtfulStrike_Timer= 8000; + }else HurtfulStrike_Timer -= diff; + + // Reverberation + if (Reverberation_Timer < diff) + { + m_creature->CastSpell(m_creature->getVictim(), SPELL_REVERBERATION, true); + + Reverberation_Timer = 30000; + }else Reverberation_Timer -= diff; + + // Cave In + if (CaveIn_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + + if(target) + DoCast(target,SPELL_CAVE_IN); + + CaveIn_Timer = 20000; + }else CaveIn_Timer -= diff; + + // Ground Slam, Gronn Lord's Grasp, Stoned, Shatter + if (GroundSlamTimer < diff) + { + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MoveIdle(); + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0); + + PerformingGroundSlam= true; + GroundSlamTimer = 0; + GroundSlamStage = 0; + DoCast(m_creature->getVictim(), SPELL_GROUND_SLAM); + } else GroundSlamTimer -=diff; + + DoMeleeAttackIfReady(); + } + } +}; + +CreatureAI* GetAI_boss_gruul(Creature *_Creature) +{ + return new boss_gruulAI (_Creature); +} + +void AddSC_boss_gruul() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_gruul"; + newscript->GetAI = GetAI_boss_gruul; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/gruuls_lair/boss_high_king_maulgar.cpp b/src/bindings/scripts/scripts/zone/gruuls_lair/boss_high_king_maulgar.cpp new file mode 100644 index 00000000000..e69a46104d3 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/gruuls_lair/boss_high_king_maulgar.cpp @@ -0,0 +1,687 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_High_King_Maulgar +SD%Complete: 80 +SDComment: Verify that the script is working properly +SDCategory: Gruul's Lair +EndScriptData */ + +#include "precompiled.h" +#include "def_gruuls_lair.h" + +#define SOUND_AGGRO 11367 //"Gronn are the real power in outland." + +#define SOUND_ENRAGE 11368 //"You will not defeat the hand of Gruul!" + +#define SOUND_OGRE_DEATH1 11369 //"You won't kill next one so easy!" +#define SOUND_OGRE_DEATH2 11370 //"Pah! Does not prove anything!" +#define SOUND_OGRE_DEATH3 11371 //"I'm not afraid of you." +#define SOUND_OGRE_DEATH4 11372 //"Good, now you fight me!" + +#define SOUND_SLAY1 11373 //"You not so tough afterall!" +#define SOUND_SLAY2 11374 //"Aha ha ha ha!" +#define SOUND_SLAY3 11375 //"Mulgar is king!" + +#define SOUND_DEATH 11376 //"Gruul ...will crush you..." + +// High King Maulgar +#define SPELL_ARCING_SMASH 39144 +#define SPELL_MIGHTY_BLOW 33230 +#define SPELL_WHIRLWIND 33238 +#define SPELL_ENRAGE 34970 + +// Council spells +#define SPELL_DARK_DECAY 33129 +#define SPELL_GREATER_POLYMORPH 33173 +#define SPELL_LIGHTNING_BOLT 36152 +#define SPELL_ARCANE_SHOCK 33175 +#define SPELL_ARCANE_EXPLOSION 33237 +#define SPELL_GREATER_PW_SHIELD 33147 +#define SPELL_HEAL 33144 +#define SPELL_GREATER_FIREBALL 33051 +#define SPELL_SPELLSHIELD 33054 +#define SPELL_BLAST_WAVE 33061 + +//High King Maulgar AI +struct MANGOS_DLL_DECL boss_high_king_maulgarAI : public ScriptedAI +{ + boss_high_king_maulgarAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + for(uint8 i = 0; i < 4; ++i) + Council[i] = 0; + Reset(); + } + + ScriptedInstance* pInstance; + + uint32 ArcingSmash_Timer; + uint32 MightyBlow_Timer; + uint32 Whirlwind_Timer; + uint32 Charging_Timer; + + bool Phase2; + + uint64 Council[4]; + + void Reset() + { + ArcingSmash_Timer = 10000; + MightyBlow_Timer = 40000; + Whirlwind_Timer = 30000; + Charging_Timer = 0; + Phase2 = false; + + Creature *pCreature = NULL; + for(uint8 i = 0; i < 4; i++) + { + if(Council[i]) + { + pCreature = (Creature*)(Unit::GetUnit((*m_creature), Council[i])); + if(pCreature && !pCreature->isAlive()) + { + pCreature->Respawn(); + pCreature->AI()->EnterEvadeMode(); + } + } + } + + //reset encounter + if (pInstance) + pInstance->SetData(DATA_MAULGAREVENT, 0); + } + + void KilledUnit() + { + switch(rand()%2) + { + case 0: DoPlaySoundToSet(m_creature, SOUND_SLAY1); break; + case 1: DoPlaySoundToSet(m_creature, SOUND_SLAY2); break; + case 2: DoPlaySoundToSet(m_creature, SOUND_SLAY3); break; + } + } + + void JustDied(Unit* Killer) + { + DoPlaySoundToSet(m_creature, SOUND_DEATH); + + if (pInstance) + pInstance->SetData(DATA_MAULGAREVENT, 0); + } + + void Aggro(Unit *who) { StartEvent(who); } + + void GetCouncil() + { + //get council member's guid to respawn them if needed + Council[0] = pInstance->GetData64(DATA_KIGGLERTHECRAZED); + Council[1] = pInstance->GetData64(DATA_BLINDEYETHESEER); + Council[2] = pInstance->GetData64(DATA_OLMTHESUMMONER); + Council[3] = pInstance->GetData64(DATA_KROSHFIREHAND); + } + + void StartEvent(Unit *who) + { + if(!pInstance) + return; + + GetCouncil(); + + DoPlaySoundToSet(m_creature, SOUND_AGGRO); + + pInstance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); + pInstance->SetData(DATA_MAULGAREVENT, 1); + } + + void UpdateAI(const uint32 diff) + { + //Only if not incombat check if the event is started + if(!InCombat && pInstance && pInstance->GetData(DATA_MAULGAREVENT)) + { + Unit* target = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_MAULGAREVENT_TANK)); + + if(target) + { + DoStartAttackAndMovement(target); + + GetCouncil(); + + DoPlaySoundToSet(m_creature, SOUND_AGGRO); + } + } + + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //someone evaded! + if(pInstance && !pInstance->GetData(DATA_MAULGAREVENT)) + EnterEvadeMode(); + + //ArcingSmash_Timer + if (ArcingSmash_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_ARCING_SMASH); + ArcingSmash_Timer = 10000; + }else ArcingSmash_Timer -= diff; + + //Whirlwind_Timer + if (Whirlwind_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_WHIRLWIND); + Whirlwind_Timer = 55000; + }else Whirlwind_Timer -= diff; + + //MightyBlow_Timer + if (MightyBlow_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_MIGHTY_BLOW); + MightyBlow_Timer = 30000+rand()%10000; + }else MightyBlow_Timer -= diff; + + //Entering Phase 2 + if(!Phase2 && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 50) + { + Phase2 = true; + DoPlaySoundToSet(m_creature, SOUND_ENRAGE); + } + + if(Phase2) + { + //Charging_Timer + if(Charging_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target) + DoStartAttackAndMovement(target); + + Charging_Timer = 20000; + }else Charging_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +//Olm The Summoner AI +struct MANGOS_DLL_DECL boss_olm_the_summonerAI : public ScriptedAI +{ + boss_olm_the_summonerAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + uint32 DarkDecay_Timer; + uint32 Summon_Timer; + + ScriptedInstance* pInstance; + + void Reset() + { + DarkDecay_Timer = 10000; + Summon_Timer = 15000; + + //reset encounter + if (pInstance) + pInstance->SetData(DATA_MAULGAREVENT, 0); + } + + void Aggro(Unit *who) + { + if(pInstance) + { + pInstance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); + pInstance->SetData(DATA_MAULGAREVENT, 1); + } + } + + float DoCalculateRandomLocation() + { + float Loc; + float Rand = rand()%8; + + switch(rand()%2) + { + case 0: Loc = 0 + Rand; break; + case 1: Loc = 0 - Rand; break; + } + return Loc; + } + + void UpdateAI(const uint32 diff) + { + //Only if not incombat check if the event is started + if(!InCombat && pInstance && pInstance->GetData(DATA_MAULGAREVENT)) + { + Unit* target = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_MAULGAREVENT_TANK)); + + if(target) + { + DoStartAttackAndMovement(target); + } + } + + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //someone evaded! + if(pInstance && !pInstance->GetData(DATA_MAULGAREVENT)) + EnterEvadeMode(); + + //DarkDecay_Timer + if(DarkDecay_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_DARK_DECAY); + DarkDecay_Timer = 20000; + }else DarkDecay_Timer -= diff; + + //Summon_Timer + if(Summon_Timer < diff) + { + Creature *Add = NULL; + Add = DoSpawnCreature(18847, DoCalculateRandomLocation(), DoCalculateRandomLocation(), 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + Summon_Timer = 30000; + }else Summon_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Kiggler The Crazed AI +struct MANGOS_DLL_DECL boss_kiggler_the_crazedAI : public ScriptedAI +{ + boss_kiggler_the_crazedAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + uint32 GreatherPolymorph_Timer; + uint32 LightningBolt_Timer; + uint32 ArcaneShock_Timer; + uint32 ArcaneExplosion_Timer; + + ScriptedInstance* pInstance; + + void Reset() + { + GreatherPolymorph_Timer = 5000; + LightningBolt_Timer = 10000; + ArcaneShock_Timer = 20000; + ArcaneExplosion_Timer = 30000; + + //reset encounter + if (pInstance) + pInstance->SetData(DATA_MAULGAREVENT, 0); + } + + void Aggro(Unit *who) + { + if(pInstance) + { + pInstance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); + pInstance->SetData(DATA_MAULGAREVENT, 1); + } + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || m_creature->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + float attackRadius = m_creature->GetAttackDistance(who); + if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) + { + if(who->HasStealthAura()) + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + if(!InCombat) + { + DoStartAttackAndMovement(who); + if(pInstance) + { + pInstance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); + pInstance->SetData(DATA_MAULGAREVENT, 1); + } + } + } + } + } + + void UpdateAI(const uint32 diff) + { + //Only if not incombat check if the event is started + if(!InCombat && pInstance && pInstance->GetData(DATA_MAULGAREVENT)) + { + Unit* target = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_MAULGAREVENT_TANK)); + + if(target) + { + DoStartAttackAndMovement(target); + } + } + + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //someone evaded! + if(pInstance && !pInstance->GetData(DATA_MAULGAREVENT)) + EnterEvadeMode(); + + //GreaterPolymorph_Timer / disabled: it makes you fall under the texture / if you've got vmaps feel free to uncomment this + /*if(GreaterPolymorph_Timer < diff) + { + Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target) + DoCast(target, SPELL_GREATER_POLYMORPH); + + GreaterPolymorph_Timer = 20000; + }else GreaterPolymorph_Timer -= diff;*/ + + //LightningBolt_Timer + if(LightningBolt_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_LIGHTNING_BOLT); + LightningBolt_Timer = 15000; + }else LightningBolt_Timer -= diff; + + //ArcaneShock_Timer + if(ArcaneShock_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_ARCANE_SHOCK); + ArcaneShock_Timer = 20000; + }else ArcaneShock_Timer -= diff; + + //ArcaneExplosion_Timer + if(ArcaneExplosion_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_ARCANE_EXPLOSION); + ArcaneExplosion_Timer = 30000; + }else ArcaneExplosion_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Blindeye The Seer AI +struct MANGOS_DLL_DECL boss_blindeye_the_seerAI : public ScriptedAI +{ + boss_blindeye_the_seerAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + uint32 GreaterPowerWordShield_Timer; + uint32 Heal_Timer; + + ScriptedInstance* pInstance; + + void Reset() + { + GreaterPowerWordShield_Timer = 5000; + Heal_Timer = 30000; + + //reset encounter + if (pInstance) + pInstance->SetData(DATA_MAULGAREVENT, 0); + } + + void Aggro(Unit *who) + { + if(pInstance) + { + pInstance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); + pInstance->SetData(DATA_MAULGAREVENT, 1); + } + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || m_creature->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + float attackRadius = m_creature->GetAttackDistance(who); + if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) + { + if(who->HasStealthAura()) + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + if(!InCombat) + { + DoStartAttackAndMovement(who); + if(pInstance) + { + pInstance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); + pInstance->SetData(DATA_MAULGAREVENT, 1); + } + } + } + } + } + + void UpdateAI(const uint32 diff) + { + //Only if not incombat check if the event is started + if(!InCombat && pInstance && pInstance->GetData(DATA_MAULGAREVENT)) + { + Unit* target = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_MAULGAREVENT_TANK)); + + if(target) + { + DoStartAttackAndMovement(target); + } + } + + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //someone evaded! + if(pInstance && !pInstance->GetData(DATA_MAULGAREVENT)) + EnterEvadeMode(); + + //GreaterPowerWordShield_Timer + if(GreaterPowerWordShield_Timer < diff) + { + DoCast(m_creature, SPELL_GREATER_PW_SHIELD); + GreaterPowerWordShield_Timer = 40000; + }else GreaterPowerWordShield_Timer -= diff; + + //Heal_Timer + if(Heal_Timer < diff) + { + DoCast(m_creature, SPELL_HEAL); + Heal_Timer = 60000; + }else Heal_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Krosh Firehand AI +struct MANGOS_DLL_DECL boss_krosh_firehandAI : public ScriptedAI +{ + boss_krosh_firehandAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + uint32 GreaterFireball_Timer; + uint32 SpellShield_Timer; + uint32 BlastWave_Timer; + + ScriptedInstance* pInstance; + + void Reset() + { + GreaterFireball_Timer = 1000; + SpellShield_Timer = 5000; + BlastWave_Timer = 20000; + + //reset encounter + if (pInstance) + pInstance->SetData(DATA_MAULGAREVENT, 0); + } + + void Aggro(Unit *who) + { + if(pInstance) + { + pInstance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); + pInstance->SetData(DATA_MAULGAREVENT, 1); + } + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || m_creature->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + float attackRadius = m_creature->GetAttackDistance(who); + if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) + { + if(who->HasStealthAura()) + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + if(!InCombat) + { + DoStartAttackAndMovement(who); + if(pInstance) + { + pInstance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); + pInstance->SetData(DATA_MAULGAREVENT, 1); + } + } + } + } + } + + void UpdateAI(const uint32 diff) + { + //Only if not incombat check if the event is started + if(!InCombat && pInstance && pInstance->GetData(DATA_MAULGAREVENT)) + { + Unit* target = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_MAULGAREVENT_TANK)); + + if(target) + { + DoStartAttackAndMovement(target); + } + } + + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //someone evaded! + if(pInstance && !pInstance->GetData(DATA_MAULGAREVENT)) + EnterEvadeMode(); + + //GreaterFireball_Timer + if(GreaterFireball_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_GREATER_FIREBALL); + GreaterFireball_Timer = 2000; + }else GreaterFireball_Timer -= diff; + + //SpellShield_Timer + if(SpellShield_Timer < diff) + { + m_creature->InterruptNonMeleeSpells(false); + DoCast(m_creature->getVictim(), SPELL_SPELLSHIELD); + SpellShield_Timer = 30000; + }else SpellShield_Timer -= diff; + + //BlastWave_Timer + if(BlastWave_Timer < diff) + { + m_creature->InterruptNonMeleeSpells(false); + DoCast(m_creature->getVictim(), SPELL_BLAST_WAVE); + BlastWave_Timer = 60000; + }else BlastWave_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_high_king_maulgar(Creature *_Creature) +{ + return new boss_high_king_maulgarAI (_Creature); +} + +CreatureAI* GetAI_boss_olm_the_summoner(Creature *_Creature) +{ + return new boss_olm_the_summonerAI (_Creature); +} + +CreatureAI *GetAI_boss_kiggler_the_crazed(Creature *_Creature) +{ + return new boss_kiggler_the_crazedAI (_Creature); +} + +CreatureAI *GetAI_boss_blindeye_the_seer(Creature *_Creature) +{ + return new boss_blindeye_the_seerAI (_Creature); +} + +CreatureAI *GetAI_boss_krosh_firehand(Creature *_Creature) +{ + return new boss_krosh_firehandAI (_Creature); +} + +void AddSC_boss_high_king_maulgar() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_high_king_maulgar"; + newscript->GetAI = GetAI_boss_high_king_maulgar; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_kiggler_the_crazed"; + newscript->GetAI = GetAI_boss_kiggler_the_crazed; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_blindeye_the_seer"; + newscript->GetAI = GetAI_boss_blindeye_the_seer; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_olm_the_summoner"; + newscript->GetAI = GetAI_boss_olm_the_summoner; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_krosh_firehand"; + newscript->GetAI = GetAI_boss_krosh_firehand; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/gruuls_lair/def_gruuls_lair.h b/src/bindings/scripts/scripts/zone/gruuls_lair/def_gruuls_lair.h new file mode 100644 index 00000000000..e2d780dabda --- /dev/null +++ b/src/bindings/scripts/scripts/zone/gruuls_lair/def_gruuls_lair.h @@ -0,0 +1,15 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_GRUULS_LAIR_H +#define DEF_GRUULS_LAIR_H + +#define DATA_BLINDEYETHESEER 1 +#define DATA_GRUULEVENT 2 +#define DATA_KIGGLERTHECRAZED 3 +#define DATA_KROSHFIREHAND 4 +#define DATA_MAULGAREVENT 5 +#define DATA_MAULGAREVENT_TANK 6 +#define DATA_OLMTHESUMMONER 7 +#endif diff --git a/src/bindings/scripts/scripts/zone/gruuls_lair/instance_gruuls_lair.cpp b/src/bindings/scripts/scripts/zone/gruuls_lair/instance_gruuls_lair.cpp new file mode 100644 index 00000000000..158af022905 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/gruuls_lair/instance_gruuls_lair.cpp @@ -0,0 +1,139 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Gruuls_Lair +SD%Complete: 100 +SDComment: +SDCategory: Gruul's Lair +EndScriptData */ + +#include "precompiled.h" +#include "def_gruuls_lair.h" + +#define ENCOUNTERS 2 + +/* Gruuls Lair encounters: +1 - High King Maulgar event +2 - Gruul event +*/ + +struct MANGOS_DLL_DECL instance_gruuls_lair : public ScriptedInstance +{ + instance_gruuls_lair(Map *Map) : ScriptedInstance(Map) {Initialize();}; + + bool Encounters[ENCOUNTERS]; + + uint64 MaulgarEvent_Tank; + uint64 KigglerTheCrazed; + uint64 BlindeyeTheSeer; + uint64 OlmTheSummoner; + uint64 KroshFirehand; + + void Initialize() + { + MaulgarEvent_Tank = 0; + KigglerTheCrazed = 0; + BlindeyeTheSeer = 0; + OlmTheSummoner = 0; + KroshFirehand = 0; + + for(uint8 i = 0; i < ENCOUNTERS; i++) + Encounters[i] = false; + } + + bool IsEncounterInProgress() const + { + for(uint8 i = 0; i < ENCOUNTERS; i++) + if(Encounters[i]) return true; + + return false; + } + + void OnCreatureCreate(Creature *creature, uint32 creature_entry) + { + switch(creature_entry) + { + case 18835: KigglerTheCrazed = creature->GetGUID(); break; + case 18836: BlindeyeTheSeer = creature->GetGUID(); break; + case 18834: OlmTheSummoner = creature->GetGUID(); break; + case 18832: KroshFirehand = creature->GetGUID(); break; + } + } + + void SetData64(uint32 type, uint64 data) + { + if(type == DATA_MAULGAREVENT_TANK) + MaulgarEvent_Tank = data; + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_MAULGAREVENT_TANK: + return MaulgarEvent_Tank; + case DATA_KIGGLERTHECRAZED: + return KigglerTheCrazed; + case DATA_BLINDEYETHESEER: + return BlindeyeTheSeer; + case DATA_OLMTHESUMMONER: + return OlmTheSummoner; + case DATA_KROSHFIREHAND: + return KroshFirehand; + } + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_MAULGAREVENT: + Encounters[0] = (data) ? true : false; + break; + case DATA_GRUULEVENT: + Encounters[1] = (data) ? true : false; + break; + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_MAULGAREVENT: + return Encounters[0]; + case DATA_GRUULEVENT: + return Encounters[1]; + } + return 0; + } +}; + +InstanceData* GetInstanceData_instance_gruuls_lair(Map* map) +{ + return new instance_gruuls_lair(map); +} + +void AddSC_instance_gruuls_lair() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_gruuls_lair"; + newscript->GetInstanceData = GetInstanceData_instance_gruuls_lair; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/hellfire_citadel/blood_furnace/boss_broggok.cpp b/src/bindings/scripts/scripts/zone/hellfire_citadel/blood_furnace/boss_broggok.cpp new file mode 100644 index 00000000000..86c300ff57a --- /dev/null +++ b/src/bindings/scripts/scripts/zone/hellfire_citadel/blood_furnace/boss_broggok.cpp @@ -0,0 +1,132 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Broggok +SD%Complete: 100 +SDComment: +SDCategory: Hellfire Citadel, Blood Furnace +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_SLIME_SPRAY 30913 +#define SPELL_POISON_CLOUD 30916 +#define SPELL_POISON_BOLT 30917 + +#define SPELL_POISON 30914 + +#define SAY_AGGRO "Come intruders...." + +struct MANGOS_DLL_DECL boss_broggokAI : public ScriptedAI +{ + boss_broggokAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 AcidSpray_Timer; + uint32 PoisonSpawn_Timer; + uint32 PoisonBolt_Timer; + + void Reset() + { + AcidSpray_Timer = 10000; + PoisonSpawn_Timer = 5000; + PoisonBolt_Timer = 7000; + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL); + } + + void UpdateAI(const uint32 diff) + { + + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(AcidSpray_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SLIME_SPRAY); + AcidSpray_Timer = 4000+rand()%8000; + }else AcidSpray_Timer -=diff; + + if(PoisonBolt_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_POISON_BOLT); + PoisonBolt_Timer = 4000+rand()%8000; + }else PoisonBolt_Timer -=diff; + + if(PoisonSpawn_Timer < diff) + { + DoCast(m_creature,SPELL_POISON_CLOUD); + PoisonSpawn_Timer = 20000; + }else PoisonSpawn_Timer -=diff; + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL mob_broggok_poisoncloudAI : public ScriptedAI +{ + mob_broggok_poisoncloudAI(Creature *c) : ScriptedAI(c) {Reset();} + + bool Start; + + void Reset() + { + Start = false; + } + + void Aggro(Unit* who) + { + } + + void UpdateAI(const uint32 diff) + { + if(!Start) + { + m_creature->SetUInt32Value(UNIT_NPC_FLAGS,0); + m_creature->setFaction(45); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Start = true; + DoCast(m_creature,SPELL_POISON); + } + } +}; + +CreatureAI* GetAI_boss_broggokAI(Creature *_Creature) +{ + return new boss_broggokAI (_Creature); +} + +CreatureAI* GetAI_mob_broggok_poisoncloudAI(Creature *_Creature) +{ + return new mob_broggok_poisoncloudAI (_Creature); +} + +void AddSC_boss_broggok() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_broggok"; + newscript->GetAI = GetAI_boss_broggokAI; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_broggok_poisoncloud"; + newscript->GetAI = GetAI_mob_broggok_poisoncloudAI; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/hellfire_citadel/blood_furnace/boss_kelidan_the_breaker.cpp b/src/bindings/scripts/scripts/zone/hellfire_citadel/blood_furnace/boss_kelidan_the_breaker.cpp new file mode 100644 index 00000000000..bf77b23d0b3 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/hellfire_citadel/blood_furnace/boss_kelidan_the_breaker.cpp @@ -0,0 +1,253 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Kelidan_The_Breaker +SD%Complete: 60 +SDComment: Event with channeleres vs. boss not implemented yet +SDCategory: Hellfire Citadel, Blood Furnace +EndScriptData */ + +/* ContentData +boss_kelidan_the_breaker +mob_shadowmoon_channeler +EndContentData */ + +#include "precompiled.h" + +#define SAY_WAKE "Who dares interrupt... What is this? What have you done? You ruin everything!" +#define SOUND_WAKE 10164 + +#define SAY_ADD_AGGRO_1 "You mustn't let him loose!" +#define SOUND_ADD_AGGRO_1 10166 +#define SAY_ADD_AGGRO_2 "Ignorant whelps!" +#define SOUND_ADD_AGGRO_2 10167 +#define SAY_ADD_AGGRO_3 "You fools! He'll kill us all!" +#define SOUND_ADD_AGGRO_3 10168 + +#define SAY_KILL_1 "Just as you deserve!" +#define SOUND_KILL_1 10169 +#define SAY_KILL_2 "Your friends will soon be joining you." +#define SOUND_KILL_2 10170 + +#define SAY_NOVA "Closer... Come closer.. and burn!" +#define SOUND_NOVA 10165 + +#define SAY_DIE "Good luck... you'll need it.." +#define SOUND_DIE 10171 + +#define SPELL_CORRUPTION 30938 + +#define SPELL_FIRE_NOVA 33775 +#define H_SPELL_FIRE_NOVA 37371 + +#define SPELL_SHADOW_BOLT_VOLLEY 17228 +#define H_SPELL_SHADOW_BOLT_VOLLEY 40070 + +#define SPELL_BURNING_NOVA 30940 +#define SPELL_VORTEX 37370 + +struct MANGOS_DLL_DECL boss_kelidan_the_breakerAI : public ScriptedAI +{ + boss_kelidan_the_breakerAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + HeroicMode = m_creature->GetMap()->IsHeroic(); + Reset(); + } + + ScriptedInstance* pInstance; + bool HeroicMode; + + uint32 ShadowVolley_Timer; + uint32 BurningNova_Timer; + uint32 Firenova_Timer; + uint32 Corruption_Timer; + bool Firenova; + + void Reset() + { + ShadowVolley_Timer = 1000; + BurningNova_Timer = 15000; + Corruption_Timer = 5000; + Firenova = false; + } + + void Aggro(Unit *who) + { + DoYell(SAY_WAKE, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_WAKE); + } + + void KilledUnit(Unit* victim) + { + if (rand()%2) + return; + + switch(rand()%2) + { + case 0: + DoYell(SAY_KILL_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_KILL_1); + break; + case 1: + DoYell(SAY_KILL_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_KILL_2); + break; + } + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DIE,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_DIE); + } + + void UpdateAI(const uint32 diff) + { + if( !m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if( Firenova ) + { + if( Firenova_Timer < diff ) + { + DoCast(m_creature,HeroicMode ? H_SPELL_FIRE_NOVA : SPELL_FIRE_NOVA); + Firenova = false; + ShadowVolley_Timer = 2000; + }else Firenova_Timer -=diff; + + return; + } + + if( ShadowVolley_Timer < diff ) + { + DoCast(m_creature,HeroicMode ? H_SPELL_SHADOW_BOLT_VOLLEY : SPELL_SHADOW_BOLT_VOLLEY); + ShadowVolley_Timer = 5000+rand()%8000; + }else ShadowVolley_Timer -=diff; + + if( Corruption_Timer < diff ) + { + DoCast(m_creature,SPELL_CORRUPTION); + Corruption_Timer = 30000+rand()%20000; + }else Corruption_Timer -=diff; + + if( BurningNova_Timer < diff ) + { + if( m_creature->IsNonMeleeSpellCasted(false) ) + m_creature->InterruptNonMeleeSpells(true); + + DoYell(SAY_NOVA, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_NOVA); + + if( HeroicMode ) + DoCast(m_creature,SPELL_VORTEX); + + DoCast(m_creature,SPELL_BURNING_NOVA); + + BurningNova_Timer = 20000+rand()%8000; + Firenova_Timer= 5000; + Firenova = true; + }else BurningNova_Timer -=diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_kelidan_the_breaker(Creature *_Creature) +{ + return new boss_kelidan_the_breakerAI (_Creature); +} + +/*###### +## mob_shadowmoon_channeler +######*/ + +#define SPELL_SHADOW_BOLT 12739 +#define H_SPELL_SHADOW_BOLT 15472 + +#define SPELL_MARK_OF_SHADOW 30937 + +#define SPELL_CHANNELING 0 //initial spell channeling boss/each other not known + //when engaged all channelers must stop, trigger yell (SAY_ADD_AGGRO_*), and engage. + +struct MANGOS_DLL_DECL mob_shadowmoon_channelerAI : public ScriptedAI +{ + mob_shadowmoon_channelerAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + HeroicMode = m_creature->GetMap()->IsHeroic(); + Reset(); + } + + ScriptedInstance* pInstance; + bool HeroicMode; + + uint32 ShadowBolt_Timer; + uint32 MarkOfShadow_Timer; + + void Reset() + { + ShadowBolt_Timer = 1000+rand()%1000; + MarkOfShadow_Timer = 5000+rand()%2000; + } + + void Aggro(Unit* who) + { + //trigger boss to yell + } + + void UpdateAI(const uint32 diff) + { + if( !m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if( MarkOfShadow_Timer < diff ) + { + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 0) ) + DoCast(target,SPELL_MARK_OF_SHADOW); + MarkOfShadow_Timer = 15000+rand()%5000; + }else MarkOfShadow_Timer -=diff; + + if( ShadowBolt_Timer < diff ) + { + DoCast(m_creature->getVictim(),HeroicMode ? H_SPELL_SHADOW_BOLT : SPELL_SHADOW_BOLT); + ShadowBolt_Timer = 5000+rand()%1000; + }else ShadowBolt_Timer -=diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_shadowmoon_channeler(Creature *_Creature) +{ + return new mob_shadowmoon_channelerAI (_Creature); +} + +void AddSC_boss_kelidan_the_breaker() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_kelidan_the_breaker"; + newscript->GetAI = GetAI_boss_kelidan_the_breaker; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_shadowmoon_channeler"; + newscript->GetAI = GetAI_mob_shadowmoon_channeler; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/hellfire_citadel/blood_furnace/boss_the_maker.cpp b/src/bindings/scripts/scripts/zone/hellfire_citadel/blood_furnace/boss_the_maker.cpp new file mode 100644 index 00000000000..fa5d22e33d1 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/hellfire_citadel/blood_furnace/boss_the_maker.cpp @@ -0,0 +1,160 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_The_Maker +SD%Complete: 80 +SDComment: Mind control no support +SDCategory: Hellfire Citadel, Blood Furnace +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_ACID_SPRAY 38153 // heroic 38973 ??? 38153 +#define SPELL_EXPLODING_BREAKER 30925 +#define SPELL_KNOCKDOWN 20276 +#define SPELL_DOMINATION 25772 // ??? + +#define SAY_KILL_1 "Let's see what I can make of you." +#define SOUND_KILL_1 10289 +#define SAY_KILL_2 "It is pointless to resist." +#define SOUND_KILL_2 10290 + +#define SAY_AGGRO_1 "My work must not be interrupted." +#define SOUND_AGGRO_1 10286 +#define SAY_AGGRO_2 "Perhaps I can find a use for you." +#define SOUND_AGGRO_2 10287 +#define SAY_AGGRO_3 "Anger... Hate... These are tools I can use." +#define SOUND_AGGRO_3 10288 + +#define SAY_DIE "Stay away from... me." +#define SOUND_DIE 10291 + +struct MANGOS_DLL_DECL boss_the_makerAI : public ScriptedAI +{ + boss_the_makerAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 AcidSpray_Timer; + uint32 ExplodingBreaker_Timer; + uint32 Domination_Timer; + uint32 Knockdown_Timer; + + void Reset() + { + AcidSpray_Timer = 10000; + ExplodingBreaker_Timer = 4000; + Domination_Timer = 120000; + Knockdown_Timer = 6000; + } + + void Aggro(Unit *who) + { + switch(rand()%3) + { + case 0: + DoYell(SAY_AGGRO_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO_1); + break; + case 1: + DoYell(SAY_AGGRO_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO_2); + break; + case 2: + DoYell(SAY_AGGRO_3, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO_3); + break; + } + } + + void KilledUnit(Unit* victim) + { + if (rand()%5) + return; + + switch(rand()%2) + { + case 0: + DoYell(SAY_KILL_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_KILL_1); + break; + case 1: + DoYell(SAY_KILL_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_KILL_2); + break; + } + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DIE,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_DIE); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(AcidSpray_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_ACID_SPRAY); + AcidSpray_Timer = 16000+rand()%8000; + }else AcidSpray_Timer -=diff; + + if(ExplodingBreaker_Timer < diff) + { + Unit* target; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + + DoCast(target,SPELL_EXPLODING_BREAKER); + ExplodingBreaker_Timer = 4000+rand()%8000; + }else ExplodingBreaker_Timer -=diff; + + /* // Disabled until Core Support for mind control + if(domination_timer_timer < diff) + { + Unit* target; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + + DoCast(target,SPELL_DOMINATION); + + domination_timer = 120000; + }else domination_timer -=diff; + */ + + if(Knockdown_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_KNOCKDOWN); + Knockdown_Timer = 4000+rand()%8000; + }else Knockdown_Timer -=diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_the_makerAI(Creature *_Creature) +{ + return new boss_the_makerAI (_Creature); +} + +void AddSC_boss_the_maker() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_the_maker"; + newscript->GetAI = GetAI_boss_the_makerAI; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/hellfire_citadel/hellfire_ramparts/boss_omor_the_unscarred.cpp b/src/bindings/scripts/scripts/zone/hellfire_citadel/hellfire_ramparts/boss_omor_the_unscarred.cpp new file mode 100644 index 00000000000..970a1774683 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/hellfire_citadel/hellfire_ramparts/boss_omor_the_unscarred.cpp @@ -0,0 +1,277 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Omar_The_Unscarred +SD%Complete: 90 +SDComment: Normal/Heroic support: both, to be tested. Temporary solution for orbital/shadow whip-ability. Needs more core support before making it more proper. +SDCategory: Hellfire Citadel, Hellfire Ramparts +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_ORBITAL_STRIKE 30637 +#define SPELL_SHADOW_WHIP 30638 +#define SPELL_TREACHEROUS_AURA 30695 +#define H_SPELL_BANE_OF_TREACHERY 37566 +#define SPELL_DEMONIC_SHIELD 31901 +#define SPELL_SHADOW_BOLT 30686 +#define H_SPELL_SHADOW_BOLT 39297 +#define SPELL_SUMMON_FIENDISH_HOUND 30707 + +#define SAY_AGGRO_1 "You dare stand against me?!" +#define SOUND_AGGRO_1 10280 +#define SAY_AGGRO_2 "I will not be defeated!" +#define SOUND_AGGRO_2 10279 +#define SAY_AGGRO_3 "Your insolence will be your death." +#define SOUND_AGGRO_3 10281 + +#define SAY_SUMMON "Achor-she-ki! Feast my pet! Eat your fill!" +#define SOUND_SUMMON 10277 + +#define SAY_CURSE "A-Kreesh!" +#define SOUND_CURSE 10278 + +#define SAY_KILL_1 "Die, weakling!" +#define SOUND_KILL_1 10282 + +#define SAY_DIE "It is... not over." +#define SOUND_DIE 10284 + +#define SAY_WIPE "I am victorious!" +#define SOUND_WIPE 10283 + +struct MANGOS_DLL_DECL boss_omor_the_unscarredAI : public ScriptedAI +{ + boss_omor_the_unscarredAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 OrbitalStrike_Timer; + uint32 ShadowWhip_Timer; + uint32 Aura_Timer; + uint32 DemonicShield_Timer; + uint32 Shadowbolt_Timer; + uint32 Summon_Timer; + uint32 SummonedCount; + uint64 playerGUID; + bool CanPullBack; + bool HeroicMode; + + void Reset() + { + HeroicMode = m_creature->GetMap()->IsHeroic(); + + DoYell(SAY_WIPE,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_WIPE); + + OrbitalStrike_Timer = 25000; + ShadowWhip_Timer = 2000; + Aura_Timer = 10000; + DemonicShield_Timer = 1000; + Shadowbolt_Timer = 2000; + Summon_Timer = 10000; + SummonedCount = 0; + playerGUID = 0; + CanPullBack = false; + } + + void Aggro(Unit *who) + { + switch(rand()%3) + { + case 0: + DoYell(SAY_AGGRO_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO_1); + break; + case 1: + DoYell(SAY_AGGRO_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO_2); + break; + case 2: + DoYell(SAY_AGGRO_3, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO_3); + break; + } + } + + void AttackStart(Unit* who) + { + if (!who) + return; + + if (who->isTargetableForAttack()) + { + DoStartAttackNoMovement(who); + + if (!InCombat) + { + Aggro(who); + InCombat = true; + } + } + } + + void MoveInLineOfSight(Unit* who) + { + if( !m_creature->getVictim() && who->isTargetableForAttack() && ( m_creature->IsHostileTo( who )) && who->isInAccessablePlaceFor(m_creature) ) + { + if (m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = m_creature->GetAttackDistance(who); + if(m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->IsWithinLOSInMap(who)) + { + DoStartAttackNoMovement(who); + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + if (!InCombat) + { + Aggro(who); + InCombat = true; + } + } + } + } + + void KilledUnit(Unit* victim) + { + if (rand()%2) + return; + + DoYell(SAY_KILL_1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_KILL_1); + } + + void JustSummoned(Creature* summoned) + { + DoYell(SAY_SUMMON,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_SUMMON); + + if( Unit* random = SelectUnit(SELECT_TARGET_RANDOM,0) ) + summoned->AI()->AttackStart(random); + + ++SummonedCount; + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DIE,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_DIE); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //only two may be wrong, perhaps increase timer and spawn periodically instead. + if( SummonedCount < 2 ) + { + if( Summon_Timer < diff ) + { + m_creature->InterruptNonMeleeSpells(false); + DoCast(m_creature,SPELL_SUMMON_FIENDISH_HOUND); + Summon_Timer = 15000+rand()%15000; + }else Summon_Timer -= diff; + } + + if( CanPullBack ) + { + if( ShadowWhip_Timer < diff ) + { + if( Unit* temp = Unit::GetUnit(*m_creature,playerGUID) ) + { + //if unit dosen't have this flag, then no pulling back (script will attempt cast, even if orbital strike was resisted) + if( temp->HasUnitMovementFlag(MOVEMENTFLAG_FALLING) ) + { + m_creature->InterruptNonMeleeSpells(false); + DoCast(temp,SPELL_SHADOW_WHIP); + } + } + playerGUID = 0; + ShadowWhip_Timer = 2000; + CanPullBack = false; + }else ShadowWhip_Timer -= diff; + } + else if( OrbitalStrike_Timer < diff ) + { + Unit* temp = NULL; + if( m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE) ) + temp = m_creature->getVictim(); + else temp = SelectUnit(SELECT_TARGET_RANDOM,0); + + if( temp && temp->GetTypeId() == TYPEID_PLAYER ) + { + DoCast(temp,SPELL_ORBITAL_STRIKE); + OrbitalStrike_Timer = 14000+rand()%2000; + playerGUID = temp->GetGUID(); + if( playerGUID ) + CanPullBack = true; + } + }else OrbitalStrike_Timer -= diff; + + if( (m_creature->GetHealth()*100) / m_creature->GetMaxHealth() < 20 ) + { + if( DemonicShield_Timer < diff ) + { + DoCast(m_creature,SPELL_DEMONIC_SHIELD); + DemonicShield_Timer = 15000; + }else DemonicShield_Timer -= diff; + } + + if( Aura_Timer < diff ) + { + DoYell(SAY_CURSE,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_CURSE); + + if( Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + { + if( HeroicMode ) DoCast(target,H_SPELL_BANE_OF_TREACHERY); + else DoCast(target,SPELL_TREACHEROUS_AURA); + + Aura_Timer = 8000+rand()%8000; + } + }else Aura_Timer -= diff; + + if( Shadowbolt_Timer < diff ) + { + if( Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + { + if( target ) + target = m_creature->getVictim(); + + if( HeroicMode ) DoCast(target,H_SPELL_SHADOW_BOLT); + else DoCast(target,SPELL_SHADOW_BOLT); + + Shadowbolt_Timer = 4000+rand()%2500; + } + }else Shadowbolt_Timer -= diff; + } +}; + +CreatureAI* GetAI_boss_omor_the_unscarredAI(Creature *_Creature) +{ + return new boss_omor_the_unscarredAI (_Creature); +} + +void AddSC_boss_omor_the_unscarred() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_omor_the_unscarred"; + newscript->GetAI = GetAI_boss_omor_the_unscarredAI; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/hellfire_citadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp b/src/bindings/scripts/scripts/zone/hellfire_citadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp new file mode 100644 index 00000000000..247af6545fd --- /dev/null +++ b/src/bindings/scripts/scripts/zone/hellfire_citadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp @@ -0,0 +1,200 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Watchkeeper_Gargolmar +SD%Complete: 80 +SDComment: Normal/Heroic support: both, to be tested. Missing adds to heal him. Surge should be used on target furthest away, not random. +SDCategory: Hellfire Citadel, Hellfire Ramparts +EndScriptData */ + +#include "precompiled.h" + +#define SAY_HEAL "Heal me! QUICKLY!" +#define SOUND_HEAL 10329 + +#define SAY_SURGE "Back off, pup!" +#define SOUND_SURGE 10330 + +#define SAY_TAUNT "Do you smell that? Fresh meat has somehow breached our citadel. Be wary of any intruders." + +#define SAY_AGGRO_1 "What have we here...?" +#define SOUND_AGGRO_1 10331 +#define SAY_AGGRO_2 "Heh... this may hurt a little." +#define SOUND_AGGRO_2 10332 +#define SAY_AGGRO_3 "I'm gonna enjoy this." +#define SOUND_AGGRO_3 10333 + +#define SAY_KILL_1 "Say farewell!" +#define SOUND_KILL_1 10334 +#define SAY_KILL_2 "Much too easy..." +#define SOUND_KILL_2 10335 + +#define SOUND_DIE 10336 + +#define SPELL_MORTAL_WOUND 30641 +#define H_SPELL_MORTAL_WOUND 36814 +#define SPELL_SURGE 34645 +#define SPELL_RETALIATION 22857 + +struct MANGOS_DLL_DECL boss_watchkeeper_gargolmarAI : public ScriptedAI +{ + boss_watchkeeper_gargolmarAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Surge_Timer; + uint32 MortalWound_Timer; + uint32 Retaliation_Timer; + + bool HasTaunted; + bool YelledForHeal; + bool HeroicMode; + + void Reset() + { + HeroicMode = m_creature->GetMap()->IsHeroic(); + + Surge_Timer = 5000; + MortalWound_Timer = 4000; + Retaliation_Timer = 0; + + HasTaunted = false; + YelledForHeal = false; + } + + void Aggro(Unit *who) + { + switch(rand()%3) + { + case 0: + DoYell(SAY_AGGRO_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO_1); + break; + case 1: + DoYell(SAY_AGGRO_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO_2); + break; + case 2: + DoYell(SAY_AGGRO_3, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO_3); + break; + } + } + + void MoveInLineOfSight(Unit* who) + { + if( !m_creature->getVictim() && who->isTargetableForAttack() && ( m_creature->IsHostileTo( who )) && who->isInAccessablePlaceFor(m_creature) ) + { + if (m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = m_creature->GetAttackDistance(who); + if(m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->IsWithinLOSInMap(who)) + { + DoStartAttackAndMovement(who); + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + if (!InCombat) + { + Aggro(who); + InCombat = true; + } + } + else if (!HasTaunted && m_creature->IsWithinDistInMap(who, 60.0f)) + { + DoYell(SAY_TAUNT, LANG_UNIVERSAL, NULL); + HasTaunted = true; + } + } + } + + void KilledUnit(Unit* victim) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_KILL_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_KILL_1); + break; + case 1: + DoYell(SAY_KILL_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_KILL_2); + break; + } + } + + void JustDied(Unit* Killer) + { + DoPlaySoundToSet(m_creature,SOUND_DIE); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if( MortalWound_Timer < diff ) + { + if( HeroicMode ) DoCast(m_creature->getVictim(),H_SPELL_MORTAL_WOUND); + else DoCast(m_creature->getVictim(),SPELL_MORTAL_WOUND); + + MortalWound_Timer = 5000+rand()%8000; + }else MortalWound_Timer -= diff; + + if( Surge_Timer < diff ) + { + DoYell(SAY_SURGE, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_SURGE); + + if( Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target,SPELL_SURGE); + + Surge_Timer = 5000+rand()%8000; + }else Surge_Timer -= diff; + + if((m_creature->GetHealth()*100) / m_creature->GetMaxHealth() < 20) + { + if( Retaliation_Timer < diff ) + { + DoCast(m_creature,SPELL_RETALIATION); + Retaliation_Timer = 30000; + }else Retaliation_Timer -= diff; + } + + if( !YelledForHeal ) + if((m_creature->GetHealth()*100) / m_creature->GetMaxHealth() < 40) + { + DoYell(SAY_HEAL, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_HEAL); + YelledForHeal = true; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_watchkeeper_gargolmarAI(Creature *_Creature) +{ + return new boss_watchkeeper_gargolmarAI (_Creature); +} + +void AddSC_boss_watchkeeper_gargolmar() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_watchkeeper_gargolmar"; + newscript->GetAI = GetAI_boss_watchkeeper_gargolmarAI; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/hellfire_citadel/magtheridons_lair/boss_magtheridon.cpp b/src/bindings/scripts/scripts/zone/hellfire_citadel/magtheridons_lair/boss_magtheridon.cpp new file mode 100644 index 00000000000..32da6416b79 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/hellfire_citadel/magtheridons_lair/boss_magtheridon.cpp @@ -0,0 +1,437 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Magtheridon +SD%Complete: 60 +SDComment: In Development +SDCategory: Hellfire Citadel, Magtheridon's lair +EndScriptData */ + +#include "precompiled.h" +#include "def_magtheridons_lair.h" +#include "WorldPacket.h" + +//Phase 2 Spells +#define SPELL_QUAKE_PROC 30571 +#define SPELL_QUAKE 30576 //must be cast with 30561 as the proc spell +#define SPELL_BLASTNOVA 30616 +#define SPELL_CLEAVE 30619 +#define SPELL_BERSERK 27680 +#define SPELL_DEBRIS 30631 +#define SPELL_CAMERA_SHAKE 36455 + +//Banish +#define SPELL_SHADOW_CAGE 30205 + +//Player version of the banish +#define SPELL_SHADOW_CAGE_2 30168 + +//Spell that is cast on players from the cube +#define SPELL_SHADOW_GRASP 30410 +#define SPELL_SHADOW_GRASP_UKN 30166 +#define SPELL_SHADOW_GRASP_VIS 30207 + +//Dialog +#define SAY_AGGRO "Thank you for releasing me. Now...die!" +#define SOUND_AGGRO 10254 + +#define SAY_BANISH "Not again...NOT AGAIN!" +#define SOUND_BANISH 10256 + +#define SAY_FREED "I...am...UNLEASHED!!!" +#define SOUND_FREED 10253 + +#define SAY_CHAMBER_DESTROY "I will not be taken so easily. Let the walls of this prison tremble...and FALL!!!" +#define SOUND_CHAMBER_DESTROY 10257 + +#define SAY_PLAYER_KILLED "Did you think me weak? Soft? Who is the weak one now?!" +#define SOUND_PLAYER_KILLED 10255 + +#define SAY_DEATH "The Legion...will consume you...all...." +#define SOUND_DEATH 10258 + +#define EMOTE_BERSERK "becomes enraged!" +#define EMOTE_BLASTNOVA "begins to cast Blast Nova!" +#define EMOTE_BEGIN "%s's bonds begin to weaken!" + +//Spawned objects +#define SPELL_COLLAPSE 34233 //This spell casted by the "cave in" type object + +#define SPELL_CONFLAGERATION 35840 //Actually casted by a creature or object spawned on the ground + +//Cubes +#define SPELL_MIND_EXHAUSTIOIN 30509 //Casted by the cubes when channeling ends + +//Channeler spells +//#define MOB_HELLFIRE_CHANNELLER 17256 + +#define SPELL_SOUL_TRANSFER 30531 +#define SPELL_SHADOW_BOLT_VOLLEY 30510 +#define SPELL_DARK_MENDING 30528 +#define SPELL_HELLFIRE_CHANNELING 31059 +#define SPELL_HELLFIRE_CAST_VISUAL 24207 +#define SPELL_FEAR 39176 + +#define SPELL_BURNING_ABYSSAL 30511 + +// Unkown sounds +uint32 RandomSound[] = {10247, 10248, 10249, 10250, 10251, 10252}; + +struct MANGOS_DLL_DECL boss_magtheridonAI : public ScriptedAI +{ + boss_magtheridonAI(Creature *c) : ScriptedAI(c) + { + pInst = (ScriptedInstance*)m_creature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* pInst; + + uint32 Phase1_Timer; + uint32 Cleave_Timer; + uint32 BlastNova_Timer; + uint32 Quake_Timer; + uint32 QuakePhase; + uint32 Collapse_Timer; + uint32 Berserk_Timer; + bool Banished; + bool Phase3; + + uint32 RandChat_Timer; + + void Reset() + { + RandChat_Timer = 90000; + + Phase1_Timer = 0; + Cleave_Timer = 15000; + Berserk_Timer = 1200000; //20 minutes + BlastNova_Timer = 60000; + Quake_Timer = 40000; + QuakePhase = 0; + Collapse_Timer = 0; + Banished = false; + + m_creature->setFaction(35); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->CastSpell(m_creature, SPELL_SHADOW_CAGE, false); + + if(pInst) + pInst->SetData(DATA_MAGTHERIDON_EVENT_ENDED, false); + } + + void KilledUnit(Unit* victim) + { + DoYell(SAY_PLAYER_KILLED, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_PLAYER_KILLED); + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DEATH,LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_DEATH); + } + + void Aggro(Unit *who) {} + + void MoveInLineOfSight(Unit* who) {} + + void UpdateAI(const uint32 diff) + { + if (!InCombat && !Phase1_Timer) + if (RandChat_Timer < diff) + { + DoPlaySoundToSet(m_creature, RandomSound[rand()%5]); + + RandChat_Timer = 90000; + }else RandChat_Timer -= diff; + + if (!InCombat && !Phase1_Timer && pInst && pInst->GetData64(DATA_EVENT_STARTER)) + { + //Unbanish self after 2 minutes + Phase1_Timer = 120000; + DoTextEmote(EMOTE_BEGIN, NULL); + return; + } + + //Phase timer + if (Phase1_Timer) + if (Phase1_Timer <= diff) + { + m_creature->setFaction(14); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + DoYell(SAY_FREED, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_FREED); + m_creature->RemoveAurasDueToSpell(SPELL_SHADOW_CAGE); + AttackStart(Unit::GetUnit(*m_creature, pInst->GetData64(DATA_EVENT_STARTER))); + + Phase1_Timer = 0; + }else + { + if (!Unit::GetUnit(*m_creature, pInst->GetData64(DATA_EVENT_STARTER))) + { + Phase1_Timer = 0; + return; + } + + Phase1_Timer -= diff; + return; + } + + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //Interrupt Blast Nova + if (m_creature->HasAura(SPELL_SHADOW_GRASP_VIS, 0) && m_creature->HasAura(SPELL_BLASTNOVA, 0) && !Banished) + { + DoYell(SAY_BANISH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_BANISH); + m_creature->RemoveAurasDueToSpell(SPELL_BLASTNOVA); + m_creature->InterruptNonMeleeSpells(false); + DoCast(m_creature, SPELL_SHADOW_CAGE_2); + Banished = true; + } + + if (Banished && !m_creature->HasAura(SPELL_SHADOW_GRASP_VIS, 0)) + { + Banished = false; + m_creature->RemoveAurasDueToSpell(SPELL_SHADOW_CAGE_2); + } + + //Berserk_Timer + if (Berserk_Timer < diff) + { + DoCast(m_creature, SPELL_BERSERK); + DoTextEmote(EMOTE_BERSERK, NULL); + + Berserk_Timer = 300000; + }else Berserk_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CLEAVE); + Cleave_Timer = 10000; + }else Cleave_Timer -= diff; + + //Quake_Timer + if (Quake_Timer < diff) + { + int32 i = SPELL_QUAKE_PROC; + m_creature->CastCustomSpell(m_creature, SPELL_QUAKE, &i, 0, 0, false); + + Quake_Timer = 40000; + }else Quake_Timer -= diff; + + //BlastNova_Timer + if (BlastNova_Timer < diff) + { + //Inturrupt Quake if it is casting + m_creature->InterruptNonMeleeSpells(false); + + DoTextEmote(EMOTE_BLASTNOVA, NULL); + DoCast(m_creature, SPELL_BLASTNOVA); + + BlastNova_Timer = 40000; + }else BlastNova_Timer -= diff; + + //Phase3 if not already enraged and below 30% + if (!Phase3 && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 30) + { + Phase3 = true; + + DoYell(SAY_CHAMBER_DESTROY, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_CHAMBER_DESTROY); + } + + //Melee + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL mob_hellfire_channelerAI : public ScriptedAI +{ + mob_hellfire_channelerAI(Creature *c) : ScriptedAI(c) + { + pInst = (ScriptedInstance*)m_creature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* pInst; + + uint32 ShadowBoltVolley_Timer; + uint32 DarkMending_Timer; + uint32 Fear_Timer; + uint32 Infernal_Timer; + + bool InfernalSpawned; + + void Reset() + { + ShadowBoltVolley_Timer = 8000 + rand()%2000; + DarkMending_Timer = 30000; + Fear_Timer = 15000 + rand()%5000; + Infernal_Timer = 20000 + rand()%5000; + + InfernalSpawned = false; + + //Suprisingly this works very well, but only if the channelers are spawned after magtheridon + DoCast(m_creature, SPELL_SHADOW_GRASP_VIS); + if(pInst) + pInst->SetData(DATA_MAGTHERIDON_EVENT_ENDED, false); + } + + void Aggro(Unit *who) + { + m_creature->InterruptNonMeleeSpells(false); + + if(!pInst || pInst->GetData64(DATA_EVENT_STARTER)) + return; + + pInst->SetData64(DATA_EVENT_STARTER, who->GetGUID()); + pInst->SetData(DATA_MAGTHERIDON_EVENT_STARTED, true); + } + + void MoveInLineOfSight(Unit*) + { + } + + void UpdateAI(const uint32 diff) + { + if (!InCombat && pInst && pInst->GetData64(DATA_EVENT_STARTER)) + { + m_creature->InterruptNonMeleeSpells(false); + AttackStart(Unit::GetUnit(*m_creature, pInst->GetData64(DATA_EVENT_STARTER))); + return; + } + + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //Shadow bolt volley + if (ShadowBoltVolley_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SHADOW_BOLT_VOLLEY); + + ShadowBoltVolley_Timer = 10000 + (rand()%10000); + }else ShadowBoltVolley_Timer -= diff; + + //Dark Mending + if (DarkMending_Timer < diff) + { + if ((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 50) + { + //Cast on ourselves if we are lower then lowest hp friendly unit + /*if (pLowestHPTarget && LowestHP < m_creature->GetHealth()) + DoCast(pLowestHPTarget, SPELL_DARK_MENDING); + else*/ + DoCast(m_creature, SPELL_DARK_MENDING); + } + + DarkMending_Timer = 10000 + (rand() % 10000); + }else DarkMending_Timer -= diff; + + //Fear + if (Fear_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM, 1); + + if (target) + DoCast(target,SPELL_FEAR); + + Fear_Timer = 25000 + (rand()%15000); + }else Fear_Timer -= diff; + + //Infernal spawning + if (!InfernalSpawned && Infernal_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + + if (target) + DoCast(target, SPELL_BURNING_ABYSSAL); + + InfernalSpawned = true; + }else Infernal_Timer -= diff; + + DoMeleeAttackIfReady(); + } + +}; + +//Manticron Cube +bool GOHello_go_Manticron_Cube(Player *player, GameObject* _GO) +{ + ScriptedInstance* pInst = (ScriptedInstance*)_GO->GetInstanceData(); + + Unit* pUnit = NULL; + if(pInst) + pUnit = Unit::GetUnit(*_GO, pInst->GetData64(DATA_MAGTHERIDON)); + else + { + _GO->TextEmote("Manticron Cube: NO INSTANCE", 0); + return true; + } + + if (!pUnit || !pUnit->isAlive() || !player) + { + _GO->TextEmote("Mantricon Cube: NO TARGET", 0); + return true; + } + + player->InterruptNonMeleeSpells(false); + player->CastSpell(pUnit, SPELL_SHADOW_GRASP, true); + player->CastSpell(pUnit, SPELL_SHADOW_GRASP_VIS, false); + + _GO->Say("Mantricon Cube Clicked", LANG_UNIVERSAL, 0); + return true; +} + +CreatureAI* GetAI_boss_magtheridon(Creature *_Creature) +{ + return new boss_magtheridonAI (_Creature); +} + +CreatureAI* GetAI_mob_hellfire_channeler(Creature *_Creature) +{ + return new mob_hellfire_channelerAI (_Creature); +} + +void AddSC_boss_magtheridon() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_magtheridon"; + newscript->GetAI = GetAI_boss_magtheridon; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_hellfire_channeler"; + newscript->GetAI = GetAI_mob_hellfire_channeler; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="go_manticron_cube"; + newscript->pGOHello = &GOHello_go_Manticron_Cube; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/hellfire_citadel/magtheridons_lair/def_magtheridons_lair.h b/src/bindings/scripts/scripts/zone/hellfire_citadel/magtheridons_lair/def_magtheridons_lair.h new file mode 100644 index 00000000000..dab98703c15 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/hellfire_citadel/magtheridons_lair/def_magtheridons_lair.h @@ -0,0 +1,13 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_MAGTHERIDONS_LAIR_H +#define DEF_MAGTHERIDONS_LAIR_H + +#define DATA_EVENT_STARTER 1 +#define DATA_MAGTHERIDON 2 +#define DATA_MAGTHERIDON_EVENT_ENDED 3 +#define DATA_MAGTHERIDON_EVENT_STARTED 4 +#define DATA_MAGTHERIDON_EVENT_STATUS 5 +#endif diff --git a/src/bindings/scripts/scripts/zone/hellfire_citadel/magtheridons_lair/instance_magtheridons_lair.cpp b/src/bindings/scripts/scripts/zone/hellfire_citadel/magtheridons_lair/instance_magtheridons_lair.cpp new file mode 100644 index 00000000000..91ce5ce453c --- /dev/null +++ b/src/bindings/scripts/scripts/zone/hellfire_citadel/magtheridons_lair/instance_magtheridons_lair.cpp @@ -0,0 +1,116 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Magtheridons_Lair +SD%Complete: 100 +SDComment: +SDCategory: Hellfire Citadel, Magtheridon's lair +EndScriptData */ + +#include "precompiled.h" +#include "def_magtheridons_lair.h" + +struct MANGOS_DLL_DECL instance_magtheridons_lair : public ScriptedInstance +{ + instance_magtheridons_lair(Map *Map) : ScriptedInstance(Map) {Initialize();}; + + bool EncounterInProgress; + uint64 Magtheridon; + uint64 EventStarter; + + void Initialize() + { + Magtheridon = 0; + EventStarter = 0; + EncounterInProgress = false; + } + + bool IsEncounterInProgress() const + { + return EncounterInProgress; + } + + void OnCreatureCreate(Creature *creature, uint32 creature_entry) + { + if (creature_entry == 17257) + Magtheridon = creature->GetGUID(); + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_MAGTHERIDON: + return Magtheridon; + + case DATA_EVENT_STARTER: + return EventStarter; + } + return 0; + } + + void SetData64(uint32 identifier, uint64 guid) + { + switch(identifier) + { + case DATA_MAGTHERIDON: + Magtheridon = guid; + break; + + case DATA_EVENT_STARTER: + EventStarter = guid; + break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_MAGTHERIDON_EVENT_STARTED: + EncounterInProgress = true; + break; + + case DATA_MAGTHERIDON_EVENT_ENDED: + EncounterInProgress = false; + EventStarter = 0; + break; + } + } + + uint32 GetData(uint32 type) + { + if(type == DATA_MAGTHERIDON_EVENT_STATUS) + return EncounterInProgress; + + return 0; + } +}; + +InstanceData* GetInstanceData_instance_magtheridons_lair(Map* map) +{ + return new instance_magtheridons_lair(map); +} + +void AddSC_instance_magtheridons_lair() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_magtheridons_lair"; + newscript->GetInstanceData = GetInstanceData_instance_magtheridons_lair; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/hellfire_citadel/shattered_halls/boss_nethekurse.cpp b/src/bindings/scripts/scripts/zone/hellfire_citadel/shattered_halls/boss_nethekurse.cpp new file mode 100644 index 00000000000..fa2619cc8fc --- /dev/null +++ b/src/bindings/scripts/scripts/zone/hellfire_citadel/shattered_halls/boss_nethekurse.cpp @@ -0,0 +1,505 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Grand_Warlock_Nethekurse +SD%Complete: 75 +SDComment: encounter not fully complete. missing part where boss kill minions. +SDCategory: Hellfire Citadel, Shattered Halls +EndScriptData */ + +/* ContentData +boss_grand_warlock_nethekurse +mob_fel_orc_convert +mob_lesser_shadow_fissure +EndContentData */ + +#include "precompiled.h" +#include "def_shattered_halls.h" + +struct Say +{ + const char* text; + uint32 sound; +}; + +#define SAY_INTRO "You wish to fight us all at once? This should be amusing!" +#define SOUND_INTRO 10262 + +static Say PeonAttacked[]= +{ + {"You can have that one. I no longer need him.", 10263}, + {"Yes, beat him mercilessly. His skull is a thick as an ogres.", 10264}, + {"Don't waste your time on that one. He's weak!", 10265}, + {"You want him? Very well, take him!", 10266}, +}; +static Say PeonDies[]= +{ + {"One pitiful wretch down. Go on, take another one.", 10267}, + {"Ahh, what a waste... Next!", 10268}, + {"I was going to kill him anyway!", 10269}, + {"Thank you for saving me the trouble! Now it's my turn to have some fun...", 10270}, +}; + +#define SAY_TAUNT_1 "Beg for your pittyfull life!" +#define SOUND_TAUNT_1 10259 +#define SAY_TAUNT_2 "Run covad, ruun!" +#define SOUND_TAUNT_2 10260 +#define SAY_TAUNT_3 "Your pain amuses me." +#define SOUND_TAUNT_3 10261 + +#define SAY_AGGRO_1 "I'm already bored." +#define SOUND_AGGRO_1 10271 +#define SAY_AGGRO_2 "Come on! ... Show me a real fight." +#define SOUND_AGGRO_2 10272 +#define SAY_AGGRO_3 "I had more fun torturing the peons." +#define SOUND_AGGRO_3 10273 + +#define SAY_SLAY_1 "You Loose." +#define SOUND_SLAY_1 10274 +#define SAY_SLAY_2 "Ohh! Just die." +#define SOUND_SLAY_2 10275 + +#define SAY_DIE "What a ... a shame." +#define SOUND_DIE 10276 + +#define SPELL_DEATH_COIL 30500 +#define SPELL_DARK_SPIN 30502 // core bug spell attack caster :D +#define SPELL_SHADOW_FISSURE 30496 // Summon the ShadowFissure NPC + +#define SPELL_SHADOW_CLEAVE 30495 +#define H_SPELL_SHADOW_SLAM 35953 + +#define SPELL_HEMORRHAGE 30478 + +#define SPELL_CONSUMPTION 30497 +#define SPELL_TEMPORARY_VISUAL 39312 // this is wrong, a temporary solution. spell consumption already has the purple visual, but doesn't display as it should + +struct MANGOS_DLL_DECL boss_grand_warlock_nethekurseAI : public ScriptedAI +{ + boss_grand_warlock_nethekurseAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + + bool HeroicMode; + bool IntroOnce; + bool IsIntroEvent; + bool IsMainEvent; + bool SpinOnce; + //bool HasTaunted; + bool Phase; + + uint32 PeonEngagedCount; + uint32 PeonKilledCount; + + uint32 IntroEvent_Timer; + uint32 DeathCoil_Timer; + uint32 ShadowFissure_Timer; + uint32 Cleave_Timer; + + void Reset() + { + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + HeroicMode = m_creature->GetMap()->IsHeroic(); + IsIntroEvent = false; + IntroOnce = false; + IsMainEvent = false; + //HasTaunted = false; + SpinOnce = false; + Phase = false; + + PeonEngagedCount = 0; + PeonKilledCount = 0; + + IntroEvent_Timer = 90000; //how long before getting bored and kills his minions? + DeathCoil_Timer = 20000; + ShadowFissure_Timer = 8000; + Cleave_Timer = 5000; + } + + void DoYellForPeonAggro() + { + if( PeonEngagedCount >= 4 ) + return; + + DoYell(PeonAttacked[PeonEngagedCount].text, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, PeonAttacked[PeonEngagedCount].sound); + ++PeonEngagedCount; + } + + void DoYellForPeonDeath() + { + if( PeonKilledCount >= 4 ) + return; + + DoYell(PeonDies[PeonKilledCount].text, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, PeonDies[PeonKilledCount].sound); + ++PeonKilledCount; + + if( PeonKilledCount == 4 ) + { + IsIntroEvent = false; + IsMainEvent = true; + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + } + + void DoTauntPeons() + { + switch(rand()%3) + { + case 0: + DoPlaySoundToSet(m_creature,SOUND_TAUNT_1); + DoYell(SAY_TAUNT_1,LANG_UNIVERSAL,NULL); + break; + case 1: + DoPlaySoundToSet(m_creature,SOUND_TAUNT_2); + DoYell(SAY_TAUNT_2,LANG_UNIVERSAL,NULL); + break; + case 2: + DoPlaySoundToSet(m_creature,SOUND_TAUNT_3); + DoYell(SAY_TAUNT_3,LANG_UNIVERSAL,NULL); + break; + } + + //TODO: kill the peons first + IsIntroEvent = false; + PeonEngagedCount = 4; + PeonKilledCount = 4; + IsMainEvent = true; + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void AttackStart(Unit* who) + { + if ( IsIntroEvent || !IsMainEvent ) + return; + + if( who->isTargetableForAttack() ) + { + if( Phase ) DoStartAttackNoMovement(who); + else DoStartAttackAndMovement(who); + + if( !InCombat ) + { + Aggro(who); + InCombat = true; + } + } + } + + void MoveInLineOfSight(Unit *who) + { + if( !m_creature->getVictim() && who->isTargetableForAttack() && ( m_creature->IsHostileTo( who )) && who->isInAccessablePlaceFor(m_creature) ) + { + if( !IntroOnce && m_creature->IsWithinDistInMap(who, 75) ) + { + DoYell(SAY_INTRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_INTRO); + IntroOnce = true; + IsIntroEvent = true; + + if( pInstance ) + pInstance->SetData(TYPE_NETHEKURSE,IN_PROGRESS); + } + + if( m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE ) + return; + + if( IsIntroEvent || !IsMainEvent ) + return; + + float attackRadius = m_creature->GetAttackDistance(who); + if( m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->IsWithinLOSInMap(who) ) + { + if( Phase ) DoStartAttackNoMovement(who); + else DoStartAttackAndMovement(who); + + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + if( !InCombat ) + { + Aggro(who); + InCombat = true; + } + } + } + } + + void Aggro(Unit *who) + { + switch(rand()%3) + { + case 0: + DoPlaySoundToSet(m_creature,SOUND_AGGRO_1); + DoYell(SAY_AGGRO_1,LANG_UNIVERSAL,NULL); + break; + case 1: + DoPlaySoundToSet(m_creature,SOUND_AGGRO_2); + DoYell(SAY_AGGRO_2,LANG_UNIVERSAL,NULL); + break; + case 2: + DoPlaySoundToSet(m_creature,SOUND_AGGRO_3); + DoYell(SAY_AGGRO_3,LANG_UNIVERSAL,NULL); + break; + } + } + + void JustSummoned(Creature *summoned) + { + summoned->setFaction(14); + summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void KilledUnit(Unit* victim) + { + switch(rand()%2) + { + case 0: + DoPlaySoundToSet(m_creature,SOUND_SLAY_1); + DoYell(SAY_SLAY_1,LANG_UNIVERSAL,NULL); + break; + case 1: + DoPlaySoundToSet(m_creature,SOUND_SLAY_2); + DoYell(SAY_SLAY_2,LANG_UNIVERSAL,NULL); + break; + } + } + + void JustDied(Unit* Killer) + { + DoPlaySoundToSet(m_creature,SOUND_DIE); + DoYell(SAY_DIE,LANG_UNIVERSAL,NULL); + + if( !pInstance ) + return; + + pInstance->SetData(TYPE_NETHEKURSE,DONE); + + if( pInstance->GetData64(DATA_NETHEKURSE_DOOR) ) + { + if( GameObject *Door = GameObject::GetGameObject(*m_creature,pInstance->GetData64(DATA_NETHEKURSE_DOOR)) ) + Door->SetGoState(0); + } + } + + void UpdateAI(const uint32 diff) + { + if( IsIntroEvent ) + { + if( !pInstance ) + return; + + if( pInstance->GetData(TYPE_NETHEKURSE) == IN_PROGRESS ) + { + if( IntroEvent_Timer < diff ) + { + DoTauntPeons(); + }else IntroEvent_Timer -= diff; + } + } + + if( !m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if( !IsMainEvent ) + return; + + if( Phase ) + { + if( !SpinOnce ) + { + DoCast(m_creature->getVictim(),SPELL_DARK_SPIN); + SpinOnce = true; + } + + if( Cleave_Timer < diff ) + { + DoCast(m_creature->getVictim(),(HeroicMode ? H_SPELL_SHADOW_SLAM : SPELL_SHADOW_CLEAVE)); + Cleave_Timer = 6000+rand()%2500; + }else Cleave_Timer -= diff; + } + else + { + if( ShadowFissure_Timer < diff ) + { + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target,SPELL_SHADOW_FISSURE); + ShadowFissure_Timer = 7500+rand()%7500; + }else ShadowFissure_Timer -= diff; + + if( DeathCoil_Timer < diff ) + { + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target,SPELL_DEATH_COIL); + DeathCoil_Timer = 15000+rand()%5000; + }else DeathCoil_Timer -= diff; + + if( (m_creature->GetHealth()*100) / m_creature->GetMaxHealth() <= 20 ) + Phase = true; + + DoMeleeAttackIfReady(); + } + } +}; + +struct MANGOS_DLL_DECL mob_fel_orc_convertAI : public ScriptedAI +{ + mob_fel_orc_convertAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + uint32 Hemorrhage_Timer; + + void Reset() + { + m_creature->SetNoCallAssistence(true); //we don't want any assistance (WE R HEROZ!) + Hemorrhage_Timer = 3000; + } + + void MoveInLineOfSight(Unit *who) + { + return; + } + + void Aggro(Unit* who) + { + if( pInstance ) + { + if( pInstance->GetData64(DATA_NETHEKURSE) ) + { + Creature *pKurse = (Creature*)Unit::GetUnit(*m_creature,pInstance->GetData64(DATA_NETHEKURSE)); + if( pKurse ) + ((boss_grand_warlock_nethekurseAI*)pKurse->AI())->DoYellForPeonAggro(); + } + + if( pInstance->GetData(TYPE_NETHEKURSE) == IN_PROGRESS ) + return; + else pInstance->SetData(TYPE_NETHEKURSE,IN_PROGRESS); + } + } + + void JustDied(Unit* Killer) + { + if( pInstance ) + { + if( pInstance->GetData64(DATA_NETHEKURSE) ) + { + Creature *pKurse = (Creature*)Unit::GetUnit(*m_creature,pInstance->GetData64(DATA_NETHEKURSE)); + if( pKurse ) + ((boss_grand_warlock_nethekurseAI*)pKurse->AI())->DoYellForPeonDeath(); + } + } + } + + void UpdateAI(const uint32 diff) + { + if( !m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if( Hemorrhage_Timer < diff ) + { + DoCast(m_creature->getVictim(),SPELL_HEMORRHAGE); + Hemorrhage_Timer = 15000; + }else Hemorrhage_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//NOTE: this creature are also summoned by other spells, for different creatures +struct MANGOS_DLL_DECL mob_lesser_shadow_fissureAI : public ScriptedAI +{ + mob_lesser_shadow_fissureAI(Creature *c) : ScriptedAI(c) {Reset();} + + bool Start; + uint32 Stop_Timer; + + void Reset() + { + Start = false; + Stop_Timer = 30000; + } + + void Aggro(Unit* who) { } + + void MoveInLineOfSight(Unit *who) { return; } + + void AttackStart(Unit* who) { return; } + + void UpdateAI(const uint32 diff) + { + if( !Start ) + { + //triggered spell of consumption does not properly show it's SpellVisual, hack it a bit + m_creature->CastSpell(m_creature,SPELL_TEMPORARY_VISUAL,true); + m_creature->CastSpell(m_creature,SPELL_CONSUMPTION,false); + Start = true; + } + + if( Stop_Timer < diff) + { + m_creature->setDeathState(JUST_DIED); + m_creature->SetHealth(0); + m_creature->CombatStop(); + m_creature->DeleteThreatList(); + }else Stop_Timer -= diff; + } +}; + +CreatureAI* GetAI_boss_grand_warlock_nethekurse(Creature *_Creature) +{ + return new boss_grand_warlock_nethekurseAI (_Creature); +} + +CreatureAI* GetAI_mob_fel_orc_convert(Creature *_Creature) +{ + return new mob_fel_orc_convertAI (_Creature); +} + +CreatureAI* GetAI_mob_lesser_shadow_fissure(Creature *_Creature) +{ + return new mob_lesser_shadow_fissureAI (_Creature); +} + +void AddSC_boss_grand_warlock_nethekurse() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_grand_warlock_nethekurse"; + newscript->GetAI = GetAI_boss_grand_warlock_nethekurse; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_fel_orc_convert"; + newscript->GetAI = GetAI_mob_fel_orc_convert; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_lesser_shadow_fissure"; + newscript->GetAI = GetAI_mob_lesser_shadow_fissure; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/hellfire_citadel/shattered_halls/boss_warbringer_omrogg.cpp b/src/bindings/scripts/scripts/zone/hellfire_citadel/shattered_halls/boss_warbringer_omrogg.cpp new file mode 100644 index 00000000000..96b4e6f29a0 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/hellfire_citadel/shattered_halls/boss_warbringer_omrogg.cpp @@ -0,0 +1,414 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Warbringer_Omrogg +SD%Complete: 85 +SDComment: Heroic enabled. Spell timing may need additional tweaks +SDCategory: Hellfire Citadel, Shattered Halls +EndScriptData */ + +/* ContentData +mob_omrogg_heads +boss_warbringer_omrogg +EndContentData */ + +#include "precompiled.h" +#include "def_shattered_halls.h" + +#define ENTRY_LEFT_HEAD 19523 +#define ENTRY_RIGHT_HEAD 19524 + +struct Yell +{ + const char* text; + uint32 sound; + uint32 creature; +}; + +static Yell GoCombat[]= +{ + {"Smash!", 10306, ENTRY_LEFT_HEAD}, + {"If you nice me let you live.", 10308, ENTRY_LEFT_HEAD}, + {"Me hungry!", 10309, ENTRY_LEFT_HEAD}, +}; +static Yell GoCombatDelay[]= +{ + {"Why don't you let me do the talking?", 10317, ENTRY_RIGHT_HEAD}, + {"No, we will NOT let you live!", 10318, ENTRY_RIGHT_HEAD}, + {"You always hungry. That why we so fat!", 10319, ENTRY_RIGHT_HEAD}, +}; + +static Yell Threat[]= +{ + {"You stay here. Me go kill someone else!", 10303, ENTRY_LEFT_HEAD}, + {"What are you doing!", 10315, ENTRY_RIGHT_HEAD}, + {"Me kill someone else...", 10302, ENTRY_LEFT_HEAD}, + {"Me not like this one...",10300, ENTRY_LEFT_HEAD}, +}; +static Yell ThreatDelay1[]= +{ + {"That's not funny!", 10314, ENTRY_RIGHT_HEAD}, + {"Me get bored...", 10305, ENTRY_LEFT_HEAD}, + {"I'm not done yet, idiot!", 10313, ENTRY_RIGHT_HEAD}, + {"Hey you numbskull!", 10312, ENTRY_RIGHT_HEAD}, +}; +static Yell ThreatDelay2[]= +{ + {"Ha ha ha.", 10304, ENTRY_LEFT_HEAD}, + {"Whhy! He almost dead!", 10316, ENTRY_RIGHT_HEAD}, + {"H'ey...", 10307, ENTRY_LEFT_HEAD}, + {"We kill his friend!", 10301, ENTRY_LEFT_HEAD}, +}; + +static Yell Killing[]= +{ + {"This one die easy!", 10310, ENTRY_LEFT_HEAD}, + {"I'm tired. You kill next one!", 10320, ENTRY_RIGHT_HEAD}, +}; +static Yell KillingDelay[]= +{ + {"That's because I do all the hard work!", 10321, ENTRY_RIGHT_HEAD}, + {"SD2 script error, should not see this.", 0, ENTRY_LEFT_HEAD}, +}; + +#define EMOTE_ENRAGE "enrages" + +#define YELL_DIE_L "This all...your fault!" +#define SOUND_DIE_L 10311 +#define YELL_DIE_R "I...hate...you..." +#define SOUND_DIE_R 10322 + +#define SPELL_BLAST_WAVE 30600 +#define SPELL_FEAR 30584 +#define SPELL_THUNDERCLAP 30633 + +#define SPELL_BURNING_MAUL 30598 +#define H_SPELL_BURNING_MAUL 36056 + +struct MANGOS_DLL_DECL mob_omrogg_headsAI : public ScriptedAI +{ + mob_omrogg_headsAI(Creature *c) : ScriptedAI(c) { Reset(); } + + bool DeathYell; + uint32 Death_Timer; + + void Reset() {} + void Aggro(Unit* who) { } + + void DoDeathYell() + { + Death_Timer = 4000; + DeathYell = true; + } + + void UpdateAI(const uint32 diff) + { + if( !DeathYell ) + return; + + if( Death_Timer < diff ) + { + DoYell(YELL_DIE_R,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_DIE_R); + DeathYell = false; + }else Death_Timer -= diff; + } +}; + +struct MANGOS_DLL_DECL boss_warbringer_omroggAI : public ScriptedAI +{ + boss_warbringer_omroggAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + HeroicMode = m_creature->GetMap()->IsHeroic(); + Reset(); + } + + ScriptedInstance* pInstance; + + uint64 LeftHead; + uint64 RightHead; + int iaggro; + int ithreat; + int ikilling; + + bool HeroicMode; + bool AggroYell; + bool ThreatYell; + bool ThreatYell2; + bool KillingYell; + + uint32 Delay_Timer; + uint32 BlastWave_Timer; + uint32 BlastCount; + uint32 Fear_Timer; + uint32 BurningMaul_Timer; + uint32 ThunderClap_Timer; + uint32 ResetThreat_Timer; + + void Reset() + { + m_creature->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); + m_creature->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true); + + LeftHead = 0; + RightHead = 0; + + AggroYell = false; + ThreatYell = false; + ThreatYell2 = false; + KillingYell = false; + + Delay_Timer = 4000; + BlastWave_Timer = 0; + BlastCount = 0; + Fear_Timer = 8000; + BurningMaul_Timer = 25000; + ThunderClap_Timer = 15000; + ResetThreat_Timer = 30000; + + if( pInstance ) + pInstance->SetData(TYPE_OMROGG, NOT_STARTED); //End boss can use this later. O'mrogg must be defeated(DONE) or he will come to aid. + } + + void DoYellForThreat() + { + if( LeftHead && RightHead ) + { + Unit *Left = Unit::GetUnit(*m_creature,LeftHead); + Unit *Right = Unit::GetUnit(*m_creature,RightHead); + + if( !Left && !Right ) + return; + + ithreat = rand()%4; + + Unit *source = (Left->GetEntry() == Threat[ithreat].creature ? Left : Right); + + source->MonsterYell(Threat[ithreat].text, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(source, Threat[ithreat].sound); + + Delay_Timer = 3500; + ThreatYell = true; + } + } + + void Aggro(Unit *who) + { + DoSpawnCreature(ENTRY_LEFT_HEAD,0,0,0,0,TEMPSUMMON_TIMED_DESPAWN,1800000); + DoSpawnCreature(ENTRY_RIGHT_HEAD,0,0,0,0,TEMPSUMMON_TIMED_DESPAWN,1800000); + + if( Unit *Left = Unit::GetUnit(*m_creature,LeftHead) ) + { + iaggro = rand()%3; + + Left->MonsterYell(GoCombat[iaggro].text, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(Left, GoCombat[iaggro].sound); + + Delay_Timer = 3500; + AggroYell = true; + } + if( pInstance ) + pInstance->SetData(TYPE_OMROGG, IN_PROGRESS); + } + + void JustSummoned(Creature *summoned) + { + if( summoned->GetEntry() == ENTRY_LEFT_HEAD ) + LeftHead = summoned->GetGUID(); + + if( summoned->GetEntry() == ENTRY_RIGHT_HEAD ) + RightHead = summoned->GetGUID(); + + //summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + //summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + summoned->SetVisibility(VISIBILITY_OFF); + } + + void KilledUnit(Unit* victim) + { + if( LeftHead && RightHead ) + { + Unit *Left = Unit::GetUnit(*m_creature,LeftHead); + Unit *Right = Unit::GetUnit(*m_creature,RightHead); + + if( !Left && !Right ) + return; + + ikilling = rand()%2; + + Unit *source = (Left->GetEntry() == Killing[ikilling].creature ? Left : Right); + + switch(ikilling) + { + case 0: + source->MonsterYell(Killing[ikilling].text, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(source, Killing[ikilling].sound); + Delay_Timer = 3500; + KillingYell = true; + break; + case 1: + source->MonsterYell(Killing[ikilling].text, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(source, Killing[ikilling].sound); + KillingYell = false; + break; + } + } + } + + void JustDied(Unit* Killer) + { + if( LeftHead && RightHead ) + { + Unit *Left = Unit::GetUnit(*m_creature,LeftHead); + Unit *Right = Unit::GetUnit(*m_creature,RightHead); + + if( !Left && !Right ) + return; + + Left->MonsterYell(YELL_DIE_L, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(Left,SOUND_DIE_L); + + ((mob_omrogg_headsAI*)((Creature*)Right)->AI())->DoDeathYell(); + } + if( pInstance ) + pInstance->SetData(TYPE_OMROGG, DONE); + } + + void UpdateAI(const uint32 diff) + { + if( Delay_Timer < diff ) + { + Delay_Timer = 3500; + + if( !LeftHead && !RightHead ) + return; + + Unit *Left = Unit::GetUnit(*m_creature,LeftHead); + Unit *Right = Unit::GetUnit(*m_creature,RightHead); + + if( !Left && !Right ) + return; + + if( AggroYell ) + { + Right->MonsterYell(GoCombatDelay[iaggro].text, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(Right, GoCombatDelay[iaggro].sound); + AggroYell = false; + } + + if( ThreatYell2 ) + { + Unit *source = (Left->GetEntry() == ThreatDelay2[ithreat].creature ? Left : Right); + + source->MonsterYell(ThreatDelay2[ithreat].text, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(source, ThreatDelay2[ithreat].sound); + ThreatYell2 = false; + } + + if( ThreatYell ) + { + Unit *source = (Left->GetEntry() == ThreatDelay1[ithreat].creature ? Left : Right); + + source->MonsterYell(ThreatDelay1[ithreat].text, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(source, ThreatDelay1[ithreat].sound); + ThreatYell = false; + ThreatYell2 = true; + } + + if( KillingYell ) + { + Unit *source = (Left->GetEntry() == KillingDelay[ikilling].creature ? Left : Right); + + source->MonsterYell(KillingDelay[ikilling].text, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(source, KillingDelay[ikilling].sound); + KillingYell = false; + } + }else Delay_Timer -= diff; + + if( !m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if( BlastCount && BlastWave_Timer <= diff ) + { + DoCast(m_creature,SPELL_BLAST_WAVE); + BlastWave_Timer = 5000; + ++BlastCount; + if( BlastCount == 3 ) + BlastCount = 0; + }else BlastWave_Timer -= diff; + + if( BurningMaul_Timer < diff ) + { + DoTextEmote(EMOTE_ENRAGE,NULL); + DoCast(m_creature,HeroicMode ? H_SPELL_BURNING_MAUL : SPELL_BURNING_MAUL); + BurningMaul_Timer = 40000; + BlastWave_Timer = 16000; + BlastCount = 1; + }else BurningMaul_Timer -= diff; + + if( ResetThreat_Timer < diff ) + { + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + { + DoYellForThreat(); + DoResetThreat(); + m_creature->AddThreat(target, 0.0f); + } + ResetThreat_Timer = 35000+rand()%10000; + }else ResetThreat_Timer -= diff; + + if( Fear_Timer < diff ) + { + DoCast(m_creature,SPELL_FEAR); + Fear_Timer = 15000+rand()%25000; + }else Fear_Timer -= diff; + + if( ThunderClap_Timer < diff ) + { + DoCast(m_creature,SPELL_THUNDERCLAP); + ThunderClap_Timer = 25000+rand()%15000; + }else ThunderClap_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_warbringer_omrogg(Creature *_Creature) +{ + return new boss_warbringer_omroggAI (_Creature); +} + +CreatureAI* GetAI_mob_omrogg_heads(Creature *_Creature) +{ + return new mob_omrogg_headsAI (_Creature); +} + +void AddSC_boss_warbringer_omrogg() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_warbringer_omrogg"; + newscript->GetAI = GetAI_boss_warbringer_omrogg; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_omrogg_heads"; + newscript->GetAI = GetAI_mob_omrogg_heads; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/hellfire_citadel/shattered_halls/def_shattered_halls.h b/src/bindings/scripts/scripts/zone/hellfire_citadel/shattered_halls/def_shattered_halls.h new file mode 100644 index 00000000000..602564d32f0 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/hellfire_citadel/shattered_halls/def_shattered_halls.h @@ -0,0 +1,13 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_SHATTERED_H +#define DEF_SHATTERED_H + +#define TYPE_NETHEKURSE 1 +#define DATA_NETHEKURSE 2 +#define DATA_NETHEKURSE_DOOR 3 + +#define TYPE_OMROGG 4 +#endif diff --git a/src/bindings/scripts/scripts/zone/hellfire_citadel/shattered_halls/instance_shattered_halls.cpp b/src/bindings/scripts/scripts/zone/hellfire_citadel/shattered_halls/instance_shattered_halls.cpp new file mode 100644 index 00000000000..8d068a4bb40 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/hellfire_citadel/shattered_halls/instance_shattered_halls.cpp @@ -0,0 +1,114 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Shattered_Halls +SD%Complete: 50 +SDComment: currently missing info about door. instance not complete +SDCategory: Hellfire Citadel, Shattered Halls +EndScriptData */ + +#include "precompiled.h" +#include "def_shattered_halls.h" + +#define ENCOUNTERS 2 + +#define DOOR_NETHEKURSE 1 + +struct MANGOS_DLL_DECL instance_shattered_halls : public ScriptedInstance +{ + instance_shattered_halls(Map *Map) : ScriptedInstance(Map) {Initialize();}; + + uint32 Encounter[ENCOUNTERS]; + uint64 nethekurseGUID; + uint64 nethekurseDoorGUID; + + void Initialize() + { + nethekurseGUID = 0; + nethekurseDoorGUID = 0; + + for(uint8 i = 0; i < ENCOUNTERS; i++) + Encounter[i] = NOT_STARTED; + } + + void OnObjectCreate(GameObject *go) + { + switch( go->GetEntry() ) + { + case DOOR_NETHEKURSE: nethekurseDoorGUID = go->GetGUID(); break; + } + } + + void OnCreatureCreate(Creature *creature, uint32 creature_entry) + { + switch( creature_entry ) + { + case 16807: nethekurseGUID = creature->GetGUID(); break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch( type ) + { + case TYPE_NETHEKURSE: + Encounter[0] = data; + break; + case TYPE_OMROGG: + Encounter[1] = data; + break; + } + } + + uint32 GetData(uint32 type) + { + switch( type ) + { + case TYPE_NETHEKURSE: + return Encounter[0]; + case TYPE_OMROGG: + return Encounter[1]; + } + return 0; + } + + uint64 GetData64(uint32 data) + { + switch(data) + { + case DATA_NETHEKURSE: + return nethekurseGUID; + case DATA_NETHEKURSE_DOOR: + return nethekurseDoorGUID; + } + return 0; + } +}; + +InstanceData* GetInstanceData_instance_shattered_halls(Map* map) +{ + return new instance_shattered_halls(map); +} + +void AddSC_instance_shattered_halls() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_shattered_halls"; + newscript->GetInstanceData = GetInstanceData_instance_shattered_halls; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/hellfire_peninsula/boss_doomlord_kazzak.cpp b/src/bindings/scripts/scripts/zone/hellfire_peninsula/boss_doomlord_kazzak.cpp new file mode 100644 index 00000000000..ccb36f9f350 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/hellfire_peninsula/boss_doomlord_kazzak.cpp @@ -0,0 +1,141 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Doomlord_Kazzak +SD%Complete: 70 +SDComment: Using incorrect spell for Mark of Kazzak +SDCategory: Hellfire Peninsula +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_SHADOWVOLLEY 32963 +#define SPELL_CLEAVE 31779 +#define SPELL_THUNDERCLAP 36706 +#define SPELL_VOIDBOLT 39329 +#define SPELL_MARKOFKAZZAK 32960 +#define SPELL_ENRAGE 32964 +#define SPELL_CAPTURESOUL 32966 +#define SPELL_TWISTEDREFLECTION 21063 + +struct MANGOS_DLL_DECL boss_doomlordkazzakAI : public ScriptedAI +{ + boss_doomlordkazzakAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 ShadowVolley_Timer; + uint32 Cleave_Timer; + uint32 ThunderClap_Timer; + uint32 VoidBolt_Timer; + uint32 MarkOfKazzak_Timer; + uint32 Enrage_Timer; + uint32 Twisted_Reflection_Timer; + + void Reset() + { + ShadowVolley_Timer = 8000 + rand()%4000; + Cleave_Timer = 7000; + ThunderClap_Timer = 16000 + rand()%4000; + VoidBolt_Timer = 30000; + MarkOfKazzak_Timer = 25000; + Enrage_Timer = 60000; + Twisted_Reflection_Timer = 33000; // Timer may be incorrect + } + + void Aggro(Unit *who) {} + + void KilledUnit(Unit* victim) + { + // When Kazzak kills a player (not pets/totems), he regens some health + if(victim->GetTypeId() == TYPEID_PLAYER) + DoCast(m_creature,SPELL_CAPTURESOUL); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //ShadowVolley_Timer + if (ShadowVolley_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_SHADOWVOLLEY); + ShadowVolley_Timer = 4000 + rand()%2000; + }else ShadowVolley_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CLEAVE); + Cleave_Timer = 8000 + rand()%4000; + }else Cleave_Timer -= diff; + + //ThunderClap_Timer + if (ThunderClap_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_THUNDERCLAP); + ThunderClap_Timer = 10000 + rand()%4000; + }else ThunderClap_Timer -= diff; + + //VoidBolt_Timer + if (VoidBolt_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_VOIDBOLT); + VoidBolt_Timer = 15000 + rand()%3000; + }else VoidBolt_Timer -= diff; + + //MarkOfKazzak_Timer + if (MarkOfKazzak_Timer < diff) + { + Unit* victim = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(victim->GetPower(POWER_MANA)) + { + DoCast(victim, SPELL_MARKOFKAZZAK); + MarkOfKazzak_Timer = 20000; + } + }else MarkOfKazzak_Timer -= diff; + + //Enrage_Timer + if (Enrage_Timer < diff) + { + DoCast(m_creature,SPELL_ENRAGE); + Enrage_Timer = 30000; + }else Enrage_Timer -= diff; + + if(Twisted_Reflection_Timer < diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_TWISTEDREFLECTION); + Twisted_Reflection_Timer = 15000; + }else Twisted_Reflection_Timer -= diff; + + DoMeleeAttackIfReady(); + } + +}; +CreatureAI* GetAI_boss_doomlordkazzak(Creature *_Creature) +{ + return new boss_doomlordkazzakAI (_Creature); +} + +void AddSC_boss_doomlordkazzak() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_doomlord_kazzak"; + newscript->GetAI = GetAI_boss_doomlordkazzak; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/hellfire_peninsula/hellfire_peninsula.cpp b/src/bindings/scripts/scripts/zone/hellfire_peninsula/hellfire_peninsula.cpp new file mode 100644 index 00000000000..ceedce42ea2 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/hellfire_peninsula/hellfire_peninsula.cpp @@ -0,0 +1,187 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Hellfire_Peninsula +SD%Complete: 100 +SDComment: Quest support: 10129, 10146, 10162, 10163, 10340, 10346, 10347, 10382 (Special flight paths) +SDCategory: Hellfire Peninsula +EndScriptData */ + +/* ContentData +npc_wing_commander_dabiree +npc_gryphoneer_windbellow +npc_wing_commander_brack +EndContentData */ + +#include "precompiled.h" + +/*###### +## npc_wing_commander_dabiree +######*/ + +#define GOSSIP_ITEM1_DAB "Fly me to Murketh and Shaadraz Gateways" +#define GOSSIP_ITEM2_DAB "Fly me to Shatter Point" + +bool GossipHello_npc_wing_commander_dabiree(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + //Mission: The Murketh and Shaadraz Gateways + if (player->GetQuestStatus(10146) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM(2, GOSSIP_ITEM1_DAB, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + + //Shatter Point + if (!player->GetQuestRewardStatus(10340)) + player->ADD_GOSSIP_ITEM(2, GOSSIP_ITEM2_DAB, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_wing_commander_dabiree(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if (action == GOSSIP_ACTION_INFO_DEF + 1) + { + player->CLOSE_GOSSIP_MENU(); + player->CastSpell(player,33768,true); //TaxiPath 585 (Gateways Murket and Shaadraz) + } + if (action == GOSSIP_ACTION_INFO_DEF + 2) + { + player->CLOSE_GOSSIP_MENU(); + player->CastSpell(player,35069,true); //TaxiPath 612 (Taxi - Hellfire Peninsula - Expedition Point to Shatter Point) + } + return true; +} + +/*###### +## npc_gryphoneer_windbellow +######*/ + +#define GOSSIP_ITEM1_WIN "Fly me to The Abyssal Shelf" +#define GOSSIP_ITEM2_WIN "Fly me to Honor Point" + +bool GossipHello_npc_gryphoneer_windbellow(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + //Mission: The Abyssal Shelf || Return to the Abyssal Shelf + if (player->GetQuestStatus(10163) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(10346) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM(2, GOSSIP_ITEM1_WIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + + //Go to the Front + if (player->GetQuestStatus(10382) != QUEST_STATUS_NONE && !player->GetQuestRewardStatus(10382)) + player->ADD_GOSSIP_ITEM(2, GOSSIP_ITEM2_WIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_gryphoneer_windbellow(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if (action == GOSSIP_ACTION_INFO_DEF + 1) + { + player->CLOSE_GOSSIP_MENU(); + player->CastSpell(player,33899,true); //TaxiPath 589 (Aerial Assault Flight (Alliance)) + } + if (action == GOSSIP_ACTION_INFO_DEF + 2) + { + player->CLOSE_GOSSIP_MENU(); + player->CastSpell(player,35065,true); //TaxiPath 607 (Taxi - Hellfire Peninsula - Shatter Point to Beach Head) + } + return true; +} + +/*###### +## npc_wing_commander_brack +######*/ + +#define GOSSIP_ITEM1_BRA "Fly me to Murketh and Shaadraz Gateways" +#define GOSSIP_ITEM2_BRA "Fly me to The Abyssal Shelf" +#define GOSSIP_ITEM3_BRA "Fly me to Spinebreaker Post" + +bool GossipHello_npc_wing_commander_brack(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + //Mission: The Murketh and Shaadraz Gateways + if (player->GetQuestStatus(10129) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM(2, GOSSIP_ITEM1_BRA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + + //Mission: The Abyssal Shelf || Return to the Abyssal Shelf + if (player->GetQuestStatus(10162) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(10347) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM(2, GOSSIP_ITEM2_BRA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + + //Spinebreaker Post + if (player->GetQuestStatus(10242) == QUEST_STATUS_COMPLETE && !player->GetQuestRewardStatus(10242)) + player->ADD_GOSSIP_ITEM(2, GOSSIP_ITEM3_BRA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_wing_commander_brack(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if (action == GOSSIP_ACTION_INFO_DEF + 1) + { + player->CLOSE_GOSSIP_MENU(); + player->CastSpell(player,33659,true); //TaxiPath 584 (Gateways Murket and Shaadraz) + } + if (action == GOSSIP_ACTION_INFO_DEF + 2) + { + player->CLOSE_GOSSIP_MENU(); + player->CastSpell(player,33825,true); //TaxiPath 587 (Aerial Assault Flight (Horde)) + } + if (action == GOSSIP_ACTION_INFO_DEF + 3) + { + player->CLOSE_GOSSIP_MENU(); + player->CastSpell(player,34578,true); //TaxiPath 604 (Taxi - Reaver's Fall to Spinebreaker Ridge) + } + return true; +} + +/*###### +## +######*/ + +void AddSC_hellfire_peninsula() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npc_wing_commander_dabiree"; + newscript->pGossipHello = &GossipHello_npc_wing_commander_dabiree; + newscript->pGossipSelect = &GossipSelect_npc_wing_commander_dabiree; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_gryphoneer_windbellow"; + newscript->pGossipHello = &GossipHello_npc_gryphoneer_windbellow; + newscript->pGossipSelect = &GossipSelect_npc_gryphoneer_windbellow; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_wing_commander_brack"; + newscript->pGossipHello = &GossipHello_npc_wing_commander_brack; + newscript->pGossipSelect = &GossipSelect_npc_wing_commander_brack; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/ironforge/ironforge.cpp b/src/bindings/scripts/scripts/zone/ironforge/ironforge.cpp new file mode 100644 index 00000000000..5ba9e4b3ae1 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/ironforge/ironforge.cpp @@ -0,0 +1,93 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Ironforge +SD%Complete: 100 +SDComment: Quest support: 3702 +SDCategory: Ironforge +EndScriptData */ + +/* ContentData +npc_royal_historian_archesonus +EndContentData */ + +#include "precompiled.h" + +/*###### +## npc_royal_historian_archesonus +######*/ + +#define GOSSIP_ITEM_ROYAL "I am ready to listen" +#define GOSSIP_ITEM_ROYAL_1 "That is tragic. How did this happen?" +#define GOSSIP_ITEM_ROYAL_2 "Interesting, continue please." +#define GOSSIP_ITEM_ROYAL_3 "Unbelievable! How dare they??" +#define GOSSIP_ITEM_ROYAL_4 "Of course I will help!" + +bool GossipHello_npc_royal_historian_archesonus(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if (player->GetQuestStatus(3702) == QUEST_STATUS_INCOMPLETE) + { + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_ROYAL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + player->SEND_GOSSIP_MENU(2235, _Creature->GetGUID()); + } + else + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_royal_historian_archesonus(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_ROYAL_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->SEND_GOSSIP_MENU(2236, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+1: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_ROYAL_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->SEND_GOSSIP_MENU(2237, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_ROYAL_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->SEND_GOSSIP_MENU(2238, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_ROYAL_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->SEND_GOSSIP_MENU(2239, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + player->CLOSE_GOSSIP_MENU(); + player->AreaExploredOrEventHappens(3702); + break; + } + return true; +} + +void AddSC_ironforge() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npc_royal_historian_archesonus"; + newscript->pGossipHello = &GossipHello_npc_royal_historian_archesonus; + newscript->pGossipSelect = &GossipSelect_npc_royal_historian_archesonus; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/isle_of_queldanas/isle_of_queldanas.cpp b/src/bindings/scripts/scripts/zone/isle_of_queldanas/isle_of_queldanas.cpp new file mode 100644 index 00000000000..06baf994a18 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/isle_of_queldanas/isle_of_queldanas.cpp @@ -0,0 +1,155 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Isle_of_Queldanas +SD%Complete: 100 +SDComment: Quest support: 11524, 11525, 11532, 11533, 11542, 11543 +SDCategory: Isle Of Quel'Danas +EndScriptData */ + +/* ContentData +npc_ayren_cloudbreaker +npc_converted_sentry +npc_unrestrained_dragonhawk +EndContentData */ + +#include "precompiled.h" + +/*###### +## npc_ayren_cloudbreaker +######*/ + +bool GossipHello_npc_ayren_cloudbreaker(Player *player, Creature *_Creature) +{ + if( player->GetQuestStatus(11532) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(11533) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM(0,"Speaking of action, I've been ordered to undertake an air strike.",GOSSIP_SENDER_MAIN,GOSSIP_ACTION_INFO_DEF+1); + + if( player->GetQuestStatus(11542) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(11543) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM(0,"I need to intercept the Dawnblade reinforcements.",GOSSIP_SENDER_MAIN,GOSSIP_ACTION_INFO_DEF+2); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(),_Creature->GetGUID()); + return true; +} + +bool GossipSelect_npc_ayren_cloudbreaker(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if (action == GOSSIP_ACTION_INFO_DEF+1) + { + player->CLOSE_GOSSIP_MENU(); + player->CastSpell(player,45071,true); //TaxiPath 779 + } + if (action == GOSSIP_ACTION_INFO_DEF+2) + { + player->CLOSE_GOSSIP_MENU(); + player->CastSpell(player,45113,true); //TaxiPath 784 + } + return true; +} + +/*###### +## npc_converted_sentry +######*/ + +#define SAY_CONVERTED_1 "Deployment sucessful. Trespassers will be neutralized." +#define SAY_CONVERTED_2 "Objective acquired. Initiating security routines." + +#define SPELL_CONVERT_CREDIT 45009 + +struct MANGOS_DLL_DECL npc_converted_sentryAI : public ScriptedAI +{ + npc_converted_sentryAI(Creature *c) : ScriptedAI(c) { Reset(); } + + bool Credit; + uint32 Timer; + + void Reset() + { + Credit = false; + Timer = 2500; + } + + void MoveInLineOfSight(Unit *who) + { return; } + void Aggro(Unit* who) + { } + + void UpdateAI(const uint32 diff) + { + if( !Credit ) + { + if( Timer <= diff ) + { + uint32 i = urand(1,2); + if( i=1 ) DoSay(SAY_CONVERTED_1,LANG_UNIVERSAL,NULL); + else DoSay(SAY_CONVERTED_2,LANG_UNIVERSAL,NULL); + + DoCast(m_creature,SPELL_CONVERT_CREDIT); + ((Pet*)m_creature)->SetDuration(7500); + Credit = true; + }else Timer -= diff; + } + } +}; +CreatureAI* GetAI_npc_converted_sentry(Creature *_Creature) +{ + return new npc_converted_sentryAI (_Creature); +} + +/*###### +## npc_unrestrained_dragonhawk +######*/ + +bool GossipHello_npc_unrestrained_dragonhawk(Player *player, Creature *_Creature) +{ + if( player->GetQuestStatus(11542) == QUEST_STATUS_COMPLETE || player->GetQuestStatus(11543) == QUEST_STATUS_COMPLETE ) + player->ADD_GOSSIP_ITEM(0,"",GOSSIP_SENDER_MAIN,GOSSIP_ACTION_INFO_DEF+1); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(),_Creature->GetGUID()); + return true; +} + +bool GossipSelect_npc_unrestrained_dragonhawk(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if (action == GOSSIP_ACTION_INFO_DEF+1) + { + player->CLOSE_GOSSIP_MENU(); + player->CastSpell(player,45353,true); //TaxiPath 788 + } + return true; +} + +void AddSC_isle_of_queldanas() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npc_ayren_cloudbreaker"; + newscript->pGossipHello = &GossipHello_npc_ayren_cloudbreaker; + newscript->pGossipSelect = &GossipSelect_npc_ayren_cloudbreaker; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_converted_sentry"; + newscript->GetAI = GetAI_npc_converted_sentry; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_unrestrained_dragonhawk"; + newscript->pGossipHello = &GossipHello_npc_unrestrained_dragonhawk; + newscript->pGossipSelect = &GossipSelect_npc_unrestrained_dragonhawk; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/karazhan/boss_curator.cpp b/src/bindings/scripts/scripts/zone/karazhan/boss_curator.cpp new file mode 100644 index 00000000000..b7c4af8dded --- /dev/null +++ b/src/bindings/scripts/scripts/zone/karazhan/boss_curator.cpp @@ -0,0 +1,200 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Curator +SD%Complete: 100 +SDComment: Evocation may cause client crash (Core related) +SDCategory: Karazhan +EndScriptData */ + +#include "precompiled.h" + +#define SAY_AGGRO "The Menagerie is for guests only." +#define SOUND_AGGRO 9183 + +#define SAY_SUMMON1 "Gallery rules will be strictly enforced." +#define SOUND_SUMMON1 9188 + +#define SAY_SUMMON2 "This curator is equipped for gallery protection." +#define SOUND_SUMMON2 9309 + +#define SAY_EVOCATE "Your request cannot be processed." +#define SOUND_EVOCATE 9186 + +#define SAY_ENRAGE "Failure to comply will result in offensive action." +#define SOUND_ENRAGE 9185 + +#define SAY_KILL1 "Do not touch the displays." +#define SOUND_KILL1 9187 + +#define SAY_KILL2 "You are not a guest." +#define SOUND_KILL2 9308 + +#define SAY_DEATH "This Curator is no longer op... er... ation... al." +#define SOUND_DEATH 9184 + +//Flare spell info +#define SPELL_ASTRAL_FLARE_PASSIVE 30234 +#define SPELL_ASTRAL_FLARE_NE 30236 +#define SPELL_ASTRAL_FLARE_NW 30239 +#define SPELL_ASTRAL_FLARE_SE 30240 +#define SPELL_ASTRAL_FLARE_SW 30241 + +//Curator spell info +#define SPELL_HATEFUL_BOLT 30383 +#define SPELL_EVOCATION 30254 +#define SPELL_ENRAGE 28131 +#define SPELL_BERSERK 26662 + +struct MANGOS_DLL_DECL boss_curatorAI : public ScriptedAI +{ + boss_curatorAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 AddTimer; + uint32 HatefulBoltTimer; + uint32 BerserkTimer; + + bool Enraged; + bool Evocating; + + void Reset() + { + AddTimer = 10000; + HatefulBoltTimer = 15000; // This time is probably wrong + BerserkTimer = 720000; //12 minutes + Enraged = false; + Evocating = false; + } + + void KilledUnit(Unit *victim) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_KILL1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(victim, SOUND_KILL1); + break; + case 1: + DoYell(SAY_KILL2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(victim, SOUND_KILL2); + break; + } + } + + void JustDied(Unit *victim) + { + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(NULL, SOUND_DEATH); + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if (Evocating && !m_creature->HasAura(SPELL_EVOCATION, 0)) + Evocating = false; + + if(m_creature->GetPower(POWER_MANA) <= 1000 && !Evocating) + { + DoYell(SAY_EVOCATE, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_EVOCATE); + m_creature->InterruptNonMeleeSpells(false); + DoCast(m_creature, SPELL_EVOCATION); + Evocating = true; + } + + if(!Enraged && !Evocating) + { + if(AddTimer < diff) + { + //Summon Astral Flare + Creature* AstralFlare = DoSpawnCreature(17096, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + + if (AstralFlare && target) + { + AstralFlare->CastSpell(AstralFlare, SPELL_ASTRAL_FLARE_PASSIVE, false); + AstralFlare->AI()->AttackStart(target); + } + + //Reduce Mana by 10% + int32 mana = (int32)(0.1f*(m_creature->GetMaxPower(POWER_MANA))); + m_creature->ModifyPower(POWER_MANA, -mana); + switch(rand()%4) + { + case 0: + DoYell(SAY_SUMMON1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SUMMON1); + break; + case 1: + DoYell(SAY_SUMMON2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SUMMON2); + break; + } + AddTimer = 10000; + }else AddTimer -= diff; + + if(HatefulBoltTimer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_TOPAGGRO, 1); + DoCast(target, SPELL_HATEFUL_BOLT); + + HatefulBoltTimer = 15000; + }else HatefulBoltTimer -= diff; + + if(m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 15) + { + Enraged = true; + DoCast(m_creature, SPELL_ENRAGE); + DoYell(SAY_ENRAGE, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_ENRAGE); + } + } + + if(BerserkTimer < diff) + { + DoCast(m_creature, SPELL_BERSERK); + DoYell(SAY_ENRAGE, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_ENRAGE); + }else BerserkTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_curator(Creature *_Creature) +{ + return new boss_curatorAI (_Creature); +} + +void AddSC_boss_curator() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_curator"; + newscript->GetAI = GetAI_boss_curator; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/karazhan/boss_maiden_of_virtue.cpp b/src/bindings/scripts/scripts/zone/karazhan/boss_maiden_of_virtue.cpp new file mode 100644 index 00000000000..45ee19c7999 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/karazhan/boss_maiden_of_virtue.cpp @@ -0,0 +1,176 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Maiden_of_Virtue +SD%Complete: 100 +SDComment: +SDCategory: Karazhan +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_REPENTANCE 29511 +#define SPELL_HOLYFIRE 29522 +#define SPELL_HOLYWRATH 32445 +#define SPELL_HOLYGROUND 29512 + +#define SAY_AGGRO "Your behavior will not be tolerated!" +#define SAY_SLAY1 "Ah ah ah..." +#define SAY_SLAY2 "This is for the best." +#define SAY_SLAY3 "Impure thoughts lead to profane actions." +#define SAY_REPENTANCE1 "Cast out your corrupt thoughts." +#define SAY_REPENTANCE2 "Your impurity must be cleansed." +#define SAY_DEATH "Death comes. Will your conscience be clear?" + +#define SOUND_AGGRO 9204 +#define SOUND_SLAY1 9207 +#define SOUND_SLAY2 9312 +#define SOUND_SLAY3 9311 +#define SOUND_REPENTANCE1 9313 +#define SOUND_REPENTANCE2 9208 +#define SOUND_DEATH 9206 + +struct MANGOS_DLL_DECL boss_maiden_of_virtueAI : public ScriptedAI +{ + boss_maiden_of_virtueAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Repentance_Timer; + uint32 Holyfire_Timer; + uint32 Holywrath_Timer; + uint32 Holyground_Timer; + + void Reset() + { + Repentance_Timer = 30000+(rand()%15000); + Holyfire_Timer = 8000+(rand()%17000); + Holywrath_Timer = 20000+(rand()%10000); + Holyground_Timer = 3000; + } + + void KilledUnit(Unit* Victim) + { + if(rand()%2) return; + + switch(rand()%3) + { + case 0: + DoYell(SAY_SLAY1,LANG_UNIVERSAL,Victim); + DoPlaySoundToSet(m_creature, SOUND_SLAY1); + break; + case 1: + DoYell(SAY_SLAY2,LANG_UNIVERSAL,Victim); + DoPlaySoundToSet(m_creature, SOUND_SLAY2); + break; + case 2: + DoYell(SAY_SLAY3,LANG_UNIVERSAL,Victim); + DoPlaySoundToSet(m_creature, SOUND_SLAY3); + break; + } + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DEATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_DEATH); + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if (Holyground_Timer < diff) + { + DoCast(m_creature, SPELL_HOLYGROUND, true); //Triggered so it doesn't interrupt her at all + Holyground_Timer = 3000; + }else Holyground_Timer -= diff; + + if (Repentance_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_REPENTANCE); + + switch(rand()%2) + { + case 0: + DoYell(SAY_REPENTANCE1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_REPENTANCE1); + break; + case 1: + DoYell(SAY_REPENTANCE2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_REPENTANCE2); + break; + } + Repentance_Timer = 30000 + rand()%15000; //A little randomness on that spell + }else Repentance_Timer -= diff; + + if (Holyfire_Timer < diff) + { + //Time for an omgwtfpwn code to make maiden cast holy fire only on units outside the holy ground's 18 yard range + Unit* target = NULL; + std::list t_list = m_creature->getThreatManager().getThreatList(); + std::vector target_list; + for(std::list::iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + target = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid()); + if(target && target->GetDistance2d(m_creature) > 12 ) + target_list.push_back(target); + target = NULL; + } + if(target_list.size()) + target = *(target_list.begin()+rand()%target_list.size()); + + DoCast(target,SPELL_HOLYFIRE); + + Holyfire_Timer = 8000 + rand()%17000; //Anywhere from 8 to 25 seconds, good luck having several of those in a row! + }else Holyfire_Timer -= diff; + + if (Holywrath_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + + if (target) + { + DoCast(target,SPELL_HOLYWRATH); + Holywrath_Timer = 20000+(rand()%10000); //20-30 secs sounds nice + } + }else Holywrath_Timer -= diff; + + DoMeleeAttackIfReady(); + } + +}; + +CreatureAI* GetAI_boss_maiden_of_virtue(Creature *_Creature) +{ + return new boss_maiden_of_virtueAI (_Creature); +} + +void AddSC_boss_maiden_of_virtue() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_maiden_of_virtue"; + newscript->GetAI = GetAI_boss_maiden_of_virtue; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/karazhan/boss_midnight.cpp b/src/bindings/scripts/scripts/zone/karazhan/boss_midnight.cpp new file mode 100644 index 00000000000..d70c25d15db --- /dev/null +++ b/src/bindings/scripts/scripts/zone/karazhan/boss_midnight.cpp @@ -0,0 +1,371 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Midnight +SD%Complete: 100 +SDComment: +SDCategory: Karazhan +EndScriptData */ + +#include "precompiled.h" + +#define SAY_MIDNIGHT_KILL "Well done Midnight!" +#define SOUND_MIDNIGHT_KILL 9173 + +#define SAY_APPEAR1 "Cowards! Wretches!" +#define SOUND_APPEAR1 9167 +#define SAY_APPEAR2 "Who dares attack the steed of the Huntsman?" +#define SOUND_APPEAR2 9298 +#define SAY_APPEAR3 "Perhaps you would rather test yourselves against a more formidable opponent?! " +#define SOUND_APPEAR3 9299 + +#define SAY_MOUNT "Come, Midnight, let\'s disperse this petty rabble! " +#define SOUND_MOUNT 9168 + +#define SAY_KILL1 "It was... inevitable." +#define SOUND_KILL1 9169 +#define SAY_KILL2 "Another trophy to add to my collection!" +#define SOUND_KILL2 9300 + +#define SAY_DISARMED "Weapons are merely a convenience for a warrior of my skill!" +#define SOUND_DISARMED 9166 + +#define SAY_DEATH "I always knew... someday I would become... the hunted." +#define SOUND_DEATH 9165 + +#define SAY_RANDOM1 "Such easy sport." +#define SOUND_RANDOM1 9170 +#define SAY_RANDOM2 "Amateurs! Do not think you can best me! I kill for a living." +#define SOUND_RANDOM2 9304 + +#define SPELL_SHADOWCLEAVE 29832 +#define SPELL_INTANGIBLE_PRESENCE 29833 +#define SPELL_BERSERKER_CHARGE 26561 //Only when mounted + +#define MOUNTED_DISPLAYID 16040 + +//Attumen (TODO: Use the summoning spell instead of creature id. It works , but is not convenient for us) +#define SUMMON_ATTUMEN 15550 + +struct MANGOS_DLL_DECL boss_midnightAI : public ScriptedAI +{ + boss_midnightAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint64 Attumen; + uint8 Phase; + uint32 Mount_Timer; + + void Reset() + { + Phase = 1; + Attumen = 0; + Mount_Timer = 0; + + m_creature->SetVisibility(VISIBILITY_ON); + } + + void Aggro(Unit* who) {} + + void KilledUnit(Unit *victim) + { + if(Phase == 2) + { + Unit *pUnit = Unit::GetUnit(*m_creature, Attumen); + if(pUnit) + { + pUnit->MonsterYell(SAY_MIDNIGHT_KILL, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(pUnit, SOUND_MIDNIGHT_KILL); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(Phase == 1 && (m_creature->GetHealth()*100)/m_creature->GetMaxHealth() < 95) + { + Phase = 2; + Creature *pAttumen = DoSpawnCreature(SUMMON_ATTUMEN, 0, 0, 0, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 45000); + if(pAttumen) + { + Attumen = pAttumen->GetGUID(); + pAttumen->AI()->AttackStart(m_creature->getVictim()); + SetMidnight(pAttumen, m_creature->GetGUID()); + switch(rand()%3) + { + case 0: + pAttumen->Yell(SAY_APPEAR1, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(m_creature, SOUND_APPEAR1); + break; + case 1: + pAttumen->Yell(SAY_APPEAR2, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(m_creature, SOUND_APPEAR2); + break; + case 2: + pAttumen->Yell(SAY_APPEAR3, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(m_creature, SOUND_APPEAR3); + break; + } + } + } + else if(Phase == 2 && (m_creature->GetHealth()*100)/m_creature->GetMaxHealth() < 25) + { + Unit *pAttumen = Unit::GetUnit(*m_creature, Attumen); + if(pAttumen) + Mount(pAttumen); + } + else if(Phase ==3) + { + if(Mount_Timer) + if(Mount_Timer <= diff) + { + Mount_Timer = 0; + m_creature->SetVisibility(VISIBILITY_OFF); + m_creature->GetMotionMaster()->MoveIdle(); + Unit *pAttumen = Unit::GetUnit(*m_creature, Attumen); + if(pAttumen) + { + pAttumen->SetUInt32Value(UNIT_FIELD_DISPLAYID, MOUNTED_DISPLAYID); + pAttumen->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if(pAttumen->getVictim()) + { + pAttumen->GetMotionMaster()->MoveChase(pAttumen->getVictim()); + pAttumen->SetUInt64Value(UNIT_FIELD_TARGET, pAttumen->getVictim()->GetGUID()); + } + pAttumen->SetFloatValue(OBJECT_FIELD_SCALE_X,1); + } + } else Mount_Timer -= diff; + } + + if(Phase != 3) + DoMeleeAttackIfReady(); + } + + void Mount(Unit *pAttumen) + { + DoPlaySoundToSet(pAttumen, SOUND_MOUNT); + pAttumen->MonsterYell(SAY_MOUNT, LANG_UNIVERSAL, 0); + Phase = 3; + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pAttumen->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + float angle = m_creature->GetAngle(pAttumen); + float distance = m_creature->GetDistance2d(pAttumen); + float newX = m_creature->GetPositionX() + cos(angle)*(distance/2) ; + float newY = m_creature->GetPositionY() + sin(angle)*(distance/2) ; + float newZ = 50; + //m_creature->Relocate(newX,newY,newZ,angle); + //m_creature->SendMonsterMove(newX, newY, newZ, 0, true, 1000); + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MovePoint(0, newX, newY, newZ); + distance += 10; + newX = m_creature->GetPositionX() + cos(angle)*(distance/2) ; + newY = m_creature->GetPositionY() + sin(angle)*(distance/2) ; + pAttumen->GetMotionMaster()->Clear(); + pAttumen->GetMotionMaster()->MovePoint(0, newX, newY, newZ); + //pAttumen->Relocate(newX,newY,newZ,-angle); + //pAttumen->SendMonsterMove(newX, newY, newZ, 0, true, 1000); + Mount_Timer = 1000; + } + + void SetMidnight(Creature *, uint64); //Below .. +}; + +CreatureAI* GetAI_boss_midnight(Creature *_Creature) +{ + return new boss_midnightAI(_Creature); +} + +struct MANGOS_DLL_DECL boss_attumenAI : public ScriptedAI +{ + boss_attumenAI(Creature *c) : ScriptedAI(c) + { + Reset(); + Phase = 1; + + CleaveTimer = 10000 + (rand()%6)*1000; + CurseTimer = 30000; + RandomYellTimer = 30000 + (rand()%31)*1000; //Occasionally yell + ChargeTimer = 20000; + ResetTimer = 0; + } + + uint64 Midnight; + uint8 Phase; + uint32 CleaveTimer; + uint32 CurseTimer; + uint32 RandomYellTimer; + uint32 ChargeTimer; //only when mounted + uint32 ResetTimer; + + void Reset() + { + ResetTimer = 2000; + } + + void Aggro(Unit* who) {} + + void KilledUnit(Unit *victim) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_KILL1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_KILL1); + case 1: + DoYell(SAY_KILL2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_KILL2); + } + } + + void JustDied(Unit *victim) + { + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_DEATH); + Unit *pMidnight = Unit::GetUnit(*m_creature, Midnight); + if(pMidnight) + { + pMidnight->DealDamage(pMidnight, pMidnight->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + + void UpdateAI(const uint32 diff) + { + if(ResetTimer) + if(ResetTimer <= diff) + { + ResetTimer = 0; + Unit *pMidnight = Unit::GetUnit(*m_creature, Midnight); + if(pMidnight) + { + pMidnight->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pMidnight->SetVisibility(VISIBILITY_ON); + } + Midnight = 0; + + m_creature->SetVisibility(VISIBILITY_OFF); + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + else ResetTimer -= diff; + + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE )) + return; + + if(CleaveTimer < diff) + { + Unit *target = m_creature->getVictim(); + DoCast(target, SPELL_SHADOWCLEAVE); + CleaveTimer = 10000 + (rand()%6)*1000; + } else CleaveTimer -= diff; + + if(CurseTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_INTANGIBLE_PRESENCE); + CurseTimer = 30000; + } else CurseTimer -= diff; + + if(RandomYellTimer < diff) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_RANDOM1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_RANDOM1); + break; + case 1: + DoYell(SAY_RANDOM2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_RANDOM2); + break; + } + RandomYellTimer = 30000 + (rand()%31)*1000; + } else RandomYellTimer -= diff; + + if(m_creature->GetUInt32Value(UNIT_FIELD_DISPLAYID) == MOUNTED_DISPLAYID) + { + if(ChargeTimer < diff) + { + Unit *target; + std::list t_list = m_creature->getThreatManager().getThreatList(); + std::vector target_list; + for(std::list::iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + target = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid()); + if(target && target->GetDistance2d(m_creature) > 5) + target_list.push_back(target); + target = NULL; + } + if(target_list.size()) + target = *(target_list.begin()+rand()%target_list.size()); + + DoCast(target, SPELL_BERSERKER_CHARGE); + ChargeTimer = 20000; + } else ChargeTimer -= diff; + } + else + { + if( (m_creature->GetHealth()*100)/m_creature->GetMaxHealth() < 25) + { + Creature *pMidnight = (Creature*)Unit::GetUnit(*m_creature, Midnight); + if(pMidnight && pMidnight->GetTypeId() == TYPEID_UNIT) + { + ((boss_midnightAI*)(pMidnight->AI()))->Mount(m_creature); + m_creature->SetHealth(pMidnight->GetHealth()); + } + } + } + + DoMeleeAttackIfReady(); + } + + void SpellHit(Unit *source, const SpellEntry *spell) + { + if(spell->Mechanic == MECHANIC_DISARM) + { + DoYell(SAY_DISARMED, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_DISARMED); + } + } +}; + +void boss_midnightAI::SetMidnight(Creature *pAttumen, uint64 value) +{ + ((boss_attumenAI*)pAttumen->AI())->Midnight = value; +} + +CreatureAI* GetAI_boss_attumen(Creature *_Creature) +{ + return new boss_attumenAI (_Creature); +} + +void AddSC_boss_attumen() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_attumen"; + newscript->GetAI = GetAI_boss_attumen; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_midnight"; + newscript->GetAI = GetAI_boss_midnight; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/karazhan/boss_moroes.cpp b/src/bindings/scripts/scripts/zone/karazhan/boss_moroes.cpp new file mode 100644 index 00000000000..538de015315 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/karazhan/boss_moroes.cpp @@ -0,0 +1,868 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Moroes +SD%Complete: 100 +SDComment: +SDCategory: Karazhan +EndScriptData */ + +#include "precompiled.h" +#include "def_karazhan.h" + +#define SAY_AGGRO "Hmm, unannounced visitors? Preparations must be made." +#define SOUND_AGGRO 9211 + +#define SAY_SPECIAL_1 "Now, where was I? Oh yes..." +#define SOUND_SPECIAL_1 9215 + +#define SAY_SPECIAL_2 "You rang?" +#define SOUND_SPECIAL_2 9316 + +#define SAY_KILL_1 "One more for dinner this evening" +#define SOUND_KILL_1 9214 + +#define SAY_KILL_2 "Time... Never enough time." +#define SOUND_KILL_2 9314 + +#define SAY_KILL_3 "I've gone and made a mess." +#define SOUND_KILL_3 9315 + +#define SAY_DEATH "How terribly clumsy of me..." +#define SOUND_DEATH 9213 + +#define SPELL_VANISH 24699 +#define SPELL_GARROTE 37066 +#define SPELL_BLIND 34654 +#define SPELL_GOUGE 28456 +#define SPELL_ENRAGE 37023 + +#define ORIENT 4.5784 +#define POS_Z 81.73 + +float Locations[4][2]= +{ + {-10976.2793, -1878.1736}, + {-10979.7587, -1877.8706}, + {-10985.6650, -1877.2458}, + {-10989.1367, -1876.8309}, +}; + +const uint32 Adds[6]= +{ + 17007, + 19872, + 19873, + 19874, + 19875, + 19876, +}; + +struct MANGOS_DLL_DECL boss_moroesAI : public ScriptedAI +{ + boss_moroesAI(Creature *c) : ScriptedAI(c) + { + FirstTime = true; + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance *pInstance; + + uint64 AddGUID[4]; + + uint32 Vanish_Timer; + uint32 Blind_Timer; + uint32 Gouge_Timer; + uint32 Wait_Timer; + uint32 CheckAdds_Timer; + uint32 AddId[4]; + + bool FirstTime; + bool InVanish; + bool Enrage; + + void Reset() + { + Vanish_Timer = 30000; + Blind_Timer = 35000; + Gouge_Timer = 23000; + Wait_Timer = 0; + CheckAdds_Timer = 5000; + + Enrage = false; + InVanish = false; + + SpawnAdds(); + + m_creature->setFaction(16); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if(pInstance) + pInstance->SetData(DATA_MOROES_EVENT, NOT_STARTED); + } + + void StartEvent() + { + if(!pInstance) + return; + + if(pInstance) + pInstance->SetData(DATA_MOROES_EVENT, IN_PROGRESS); + } + + void Aggro(Unit* who) + { + StartEvent(); + + DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO); + AddsAttack(); + } + + void KilledUnit(Unit* victim) + { + switch (rand()%3) + { + case 0: + DoYell(SAY_KILL_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_KILL_1); + break; + case 1: + DoYell(SAY_KILL_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_KILL_2); + break; + case 2: + DoYell(SAY_KILL_3, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_KILL_3); + break; + } + } + + void JustDied(Unit* victim) + { + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_DEATH); + + if(pInstance) + pInstance->SetData(DATA_MOROES_EVENT, DONE); + + DeSpawnAdds(); + } + + uint8 CheckAdd(uint64 guid) + { + Unit* pUnit = Unit::GetUnit((*m_creature), guid); + if(pUnit) + { + if(!pUnit->isAlive()) + return 1; // Exists but is dead + else + return 2; // Exists and is alive + } + + return 0; // Does not exist + } + + void SpawnAdds() + { + Creature *pCreature = NULL; + + if(FirstTime) + { + std::vector AddList; + + for(uint8 i = 0; i < 6; ++i) + AddList.push_back(Adds[i]); + + while(AddList.size() > 4) + AddList.erase((AddList.begin())+(rand()%AddList.size())); + + uint8 j = 0; + for(std::vector::iterator itr = AddList.begin(); itr != AddList.end(); ++itr) + { + uint32 entry = *itr; + + pCreature = m_creature->SummonCreature(entry, Locations[j][0], Locations[j][1], POS_Z, ORIENT, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); + if(pCreature) + { + AddGUID[j] = pCreature->GetGUID(); + AddId[j] = entry; + } + ++j; + } + + FirstTime = false; + } + else + { + for(uint8 i = 0; i < 5; ++i) + { + switch(CheckAdd(AddGUID[i])) + { + case 0: + pCreature = m_creature->SummonCreature(AddId[i], Locations[i][0], Locations[i][1], POS_Z, ORIENT, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); + if(pCreature) + AddGUID[i] = pCreature->GetGUID(); + break; + case 1: + pCreature = ((Creature*)Unit::GetUnit((*m_creature), AddGUID[i])); + if(pCreature) + { + pCreature->Respawn(); + pCreature->AI()->EnterEvadeMode(); + } + break; + case 2: + pCreature = ((Creature*)Unit::GetUnit((*m_creature), AddGUID[i])); + if(!pCreature->IsInEvadeMode()) + pCreature->AI()->EnterEvadeMode(); + break; + } + } + } + } + + void DeSpawnAdds() + { + for(uint8 i = 0; i < 4 ; ++i) + { + Unit* Temp = NULL; + if(AddGUID[i]) + { + Temp = Unit::GetUnit((*m_creature),AddGUID[i]); + if(Temp && Temp->isAlive()) + Temp->DealDamage(Temp, Temp->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + } + + void AddsAttack() + { + for(uint8 i = 0; i < 4; ++i) + { + Unit* Temp = NULL; + if(AddGUID[i]) + { + Temp = Unit::GetUnit((*m_creature),AddGUID[i]); + if(Temp && Temp->isAlive()) + ((Creature*)Temp)->AI()->AttackStart(m_creature->getVictim()); + else + EnterEvadeMode(); + } + } + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if(pInstance && !pInstance->GetData(DATA_MOROES_EVENT)) + EnterEvadeMode(); + + if(!Enrage && m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 30) + { + DoCast(m_creature, SPELL_ENRAGE); + Enrage = true; + } + + if(CheckAdds_Timer < diff) + { + for(uint8 i = 0; i < 4; ++i) + { + Unit* Temp = NULL; + if(AddGUID[i]) + { + Temp = Unit::GetUnit((*m_creature),AddGUID[i]); + if(Temp && Temp->isAlive()) + if(!Temp->SelectHostilTarget() || !Temp->getVictim() ) + ((Creature*)Temp)->AI()->AttackStart(m_creature->getVictim()); + } + } + CheckAdds_Timer = 5000; + }else CheckAdds_Timer -= diff; + + //Cast Vanish, then Garrote random victim + if(Vanish_Timer < diff) + { + m_creature->setFaction(35); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + DoCast(m_creature, SPELL_VANISH); + InVanish = true; + Vanish_Timer = 30000; + Wait_Timer = 5000; + }else Vanish_Timer -= diff; + + if(InVanish) + { + if(Wait_Timer < diff) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_SPECIAL_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SPECIAL_1); + break; + case 1: + DoYell(SAY_SPECIAL_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SPECIAL_2); + break; + } + + Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target) + target->CastSpell(target, SPELL_GARROTE,true); + + m_creature->setFaction(16); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->AI()->AttackStart(m_creature->getVictim()); + InVanish = false; + }else Wait_Timer -= diff; + } + + //Blind highest aggro, and attack second highest + if(Gouge_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_GOUGE); + if(m_creature->getThreatManager().getThreat(m_creature->getVictim())) + m_creature->getThreatManager().modifyThreatPercent(m_creature->getVictim(),-100); + Gouge_Timer = 40000; + }else Gouge_Timer -= diff; + + if(Blind_Timer < diff) + { + Unit* target = NULL; + std::list t_list = m_creature->getThreatManager().getThreatList(); + + if(t_list.empty()) + return; + + std::vector target_list; + for(std::list::iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + target = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid()); + if(target && target->GetDistance2d(m_creature) < 5) + target_list.push_back(target); + } + if(target_list.size()) + target = *(target_list.begin()+rand()%target_list.size()); + + if(target) + DoCast(target, SPELL_BLIND); + + Blind_Timer = 40000; + }else Blind_Timer -= diff; + + if(!InVanish) + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL boss_moroes_guestAI : public ScriptedAI +{ + ScriptedInstance* pInstance; + + uint64 GuestGUID[4]; + + boss_moroes_guestAI(Creature* c) : ScriptedAI(c) + { + for(uint8 i = 0; i < 4; ++i) + GuestGUID[i] = 0; + + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + void Reset() + { + if(pInstance) + pInstance->SetData(DATA_MOROES_EVENT, NOT_STARTED); + } + + void Aggro(Unit* who) {} + + void AcquireGUID() + { + if(!pInstance) + return; + + GuestGUID[0] = pInstance->GetData64(DATA_MOROES); + Creature* Moroes = ((Creature*)Unit::GetUnit((*m_creature), GuestGUID[0])); + if(Moroes) + { + for(uint8 i = 0; i < 3; ++i) + { + uint64 GUID = ((boss_moroesAI*)Moroes->AI())->AddGUID[i]; + if(GUID && GUID != m_creature->GetGUID()) + GuestGUID[i+1] = GUID; + } + } + } + + Unit* SelectTarget() + { + uint64 TempGUID = GuestGUID[rand()%5]; + if(TempGUID) + { + Unit* pUnit = Unit::GetUnit((*m_creature), TempGUID); + if(pUnit && pUnit->isAlive()) + return pUnit; + } + + return m_creature; + } + + void UpdateAI(const uint32 diff) + { + if(pInstance && !pInstance->GetData(DATA_MOROES_EVENT)) + EnterEvadeMode(); + + DoMeleeAttackIfReady(); + } +}; + +#define SPELL_MANABURN 29405 +#define SPELL_MINDFLY 29570 +#define SPELL_SWPAIN 34441 +#define SPELL_SHADOWFORM 29406 + +struct MANGOS_DLL_DECL boss_baroness_dorothea_millstipeAI : public boss_moroes_guestAI +{ + //Shadow Priest + boss_baroness_dorothea_millstipeAI(Creature *c) : boss_moroes_guestAI(c) {} + + uint32 ManaBurn_Timer; + uint32 MindFlay_Timer; + uint32 ShadowWordPain_Timer; + + void Reset() + { + ManaBurn_Timer = 7000; + MindFlay_Timer = 1000; + ShadowWordPain_Timer = 6000; + + DoCast(m_creature,SPELL_SHADOWFORM, true); + + boss_moroes_guestAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + boss_moroes_guestAI::UpdateAI(diff); + + if(MindFlay_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_MINDFLY); + MindFlay_Timer = 12000; //3sec channeled + }else MindFlay_Timer -= diff; + + if(ManaBurn_Timer < diff) + { + Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target && (target->getPowerType() == POWER_MANA)) + DoCast(target,SPELL_MANABURN); + ManaBurn_Timer = 5000; //3 sec cast + }else ManaBurn_Timer -= diff; + + if(ShadowWordPain_Timer < diff) + { + Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target) + { + DoCast(target,SPELL_SWPAIN); + ShadowWordPain_Timer = 7000; + } + }else ShadowWordPain_Timer -= diff; + } +}; + +#define SPELL_HAMMEROFJUSTICE 13005 +#define SPELL_JUDGEMENTOFCOMMAND 29386 +#define SPELL_SEALOFCOMMAND 29385 + +struct MANGOS_DLL_DECL boss_baron_rafe_dreugerAI : public boss_moroes_guestAI +{ + //Retr Pally + boss_baron_rafe_dreugerAI(Creature *c) : boss_moroes_guestAI(c){} + + uint32 HammerOfJustice_Timer; + uint32 SealOfCommand_Timer; + uint32 JudgementOfCommand_Timer; + + void Reset() + { + HammerOfJustice_Timer = 1000; + SealOfCommand_Timer = 7000; + JudgementOfCommand_Timer = SealOfCommand_Timer + 29000; + + boss_moroes_guestAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + boss_moroes_guestAI::UpdateAI(diff); + + if(SealOfCommand_Timer < diff) + { + DoCast(m_creature,SPELL_SEALOFCOMMAND); + SealOfCommand_Timer = 32000; + JudgementOfCommand_Timer = 29000; + }else SealOfCommand_Timer -= diff; + + if(JudgementOfCommand_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_JUDGEMENTOFCOMMAND); + JudgementOfCommand_Timer = SealOfCommand_Timer + 29000; + }else JudgementOfCommand_Timer -= diff; + + if(HammerOfJustice_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_HAMMEROFJUSTICE); + HammerOfJustice_Timer = 12000; + }else HammerOfJustice_Timer -= diff; + } +}; + +#define SPELL_DISPELMAGIC 15090 //Self or other guest+Moroes +#define SPELL_GREATERHEAL 29564 //Self or other guest+Moroes +#define SPELL_HOLYFIRE 29563 +#define SPELL_PWSHIELD 29408 + +struct MANGOS_DLL_DECL boss_lady_catriona_von_indiAI : public boss_moroes_guestAI +{ + //Holy Priest + boss_lady_catriona_von_indiAI(Creature *c) : boss_moroes_guestAI(c) {} + + uint32 DispelMagic_Timer; + uint32 GreaterHeal_Timer; + uint32 HolyFire_Timer; + uint32 PowerWordShield_Timer; + + void Reset() + { + DispelMagic_Timer = 11000; + GreaterHeal_Timer = 1500; + HolyFire_Timer = 5000; + PowerWordShield_Timer = 1000; + + AcquireGUID(); + + boss_moroes_guestAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + boss_moroes_guestAI::UpdateAI(diff); + + if(PowerWordShield_Timer < diff) + { + DoCast(m_creature,SPELL_PWSHIELD); + PowerWordShield_Timer = 15000; + }else PowerWordShield_Timer -= diff; + + if(GreaterHeal_Timer < diff) + { + Unit* target = SelectTarget(); + + DoCast(target, SPELL_GREATERHEAL); + GreaterHeal_Timer = 17000; + }else GreaterHeal_Timer -= diff; + + if(HolyFire_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_HOLYFIRE); + HolyFire_Timer = 22000; + }else HolyFire_Timer -= diff; + + if(DispelMagic_Timer < diff) + { + if(rand()%2) + { + Unit* target = SelectTarget(); + + DoCast(target, SPELL_DISPELMAGIC); + } + else + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_DISPELMAGIC); + + DispelMagic_Timer = 25000; + }else DispelMagic_Timer -= diff; + } +}; + +#define SPELL_CLEANSE 29380 //Self or other guest+Moroes +#define SPELL_GREATERBLESSOFMIGHT 29381 //Self or other guest+Moroes +#define SPELL_HOLYLIGHT 29562 //Self or other guest+Moroes +#define SPELL_DIVINESHIELD 41367 + +struct MANGOS_DLL_DECL boss_lady_keira_berrybuckAI : public boss_moroes_guestAI +{ + //Holy Pally + boss_lady_keira_berrybuckAI(Creature *c) : boss_moroes_guestAI(c) {} + + uint32 Cleanse_Timer; + uint32 GreaterBless_Timer; + uint32 HolyLight_Timer; + uint32 DivineShield_Timer; + + void Reset() + { + Cleanse_Timer = 13000; + GreaterBless_Timer = 1000; + HolyLight_Timer = 7000; + DivineShield_Timer = 31000; + + AcquireGUID(); + + boss_moroes_guestAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + boss_moroes_guestAI::UpdateAI(diff); + + if(DivineShield_Timer < diff) + { + DoCast(m_creature,SPELL_DIVINESHIELD); + DivineShield_Timer = 31000; + }else DivineShield_Timer -= diff; + + if(HolyLight_Timer < diff) + { + Unit* target = SelectTarget(); + + DoCast(target, SPELL_HOLYLIGHT); + HolyLight_Timer = 10000; + }else HolyLight_Timer -= diff; + + if(GreaterBless_Timer < diff) + { + Unit* target = SelectTarget(); + + DoCast(target, SPELL_GREATERBLESSOFMIGHT); + + GreaterBless_Timer = 50000; + }else GreaterBless_Timer -= diff; + + if(Cleanse_Timer < diff) + { + Unit* target = SelectTarget(); + + DoCast(target, SPELL_CLEANSE); + + Cleanse_Timer = 10000; + }else Cleanse_Timer -= diff; + } +}; + +#define SPELL_HAMSTRING 9080 +#define SPELL_MORTALSTRIKE 29572 +#define SPELL_WHIRLWIND 29573 + +struct MANGOS_DLL_DECL boss_lord_robin_darisAI : public boss_moroes_guestAI +{ + //Arms Warr + boss_lord_robin_darisAI(Creature *c) : boss_moroes_guestAI(c) {} + + uint32 Hamstring_Timer; + uint32 MortalStrike_Timer; + uint32 WhirlWind_Timer; + + void Reset() + { + Hamstring_Timer = 7000; + MortalStrike_Timer = 10000; + WhirlWind_Timer = 21000; + + boss_moroes_guestAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + boss_moroes_guestAI::UpdateAI(diff); + + if(Hamstring_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_HAMSTRING); + Hamstring_Timer = 12000; + }else Hamstring_Timer -= diff; + + if(MortalStrike_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_MORTALSTRIKE); + MortalStrike_Timer = 18000; + }else MortalStrike_Timer -= diff; + + if(WhirlWind_Timer < diff) + { + DoCast(m_creature,SPELL_WHIRLWIND); + WhirlWind_Timer = 21000; + }else WhirlWind_Timer -= diff; + } +}; + +#define SPELL_DISARM 8379 +#define SPELL_HEROICSTRIKE 29567 +#define SPELL_SHIELDBASH 11972 +#define SPELL_SHIELDWALL 29390 + +struct MANGOS_DLL_DECL boss_lord_crispin_ferenceAI : public boss_moroes_guestAI +{ + //Arms Warr + boss_lord_crispin_ferenceAI(Creature *c) : boss_moroes_guestAI(c) {} + + uint32 Disarm_Timer; + uint32 HeroicStrike_Timer; + uint32 ShieldBash_Timer; + uint32 ShieldWall_Timer; + + void Reset() + { + Disarm_Timer = 6000; + HeroicStrike_Timer = 10000; + ShieldBash_Timer = 8000; + ShieldWall_Timer = 4000; + + boss_moroes_guestAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + boss_moroes_guestAI::UpdateAI(diff); + + if(Disarm_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_DISARM); + Disarm_Timer = 12000; + }else Disarm_Timer -= diff; + + if(HeroicStrike_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_HEROICSTRIKE); + HeroicStrike_Timer = 10000; + }else HeroicStrike_Timer -= diff; + + if(ShieldBash_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SHIELDBASH); + ShieldBash_Timer = 13000; + }else ShieldBash_Timer -= diff; + + if(ShieldWall_Timer < diff) + { + DoCast(m_creature,SPELL_SHIELDWALL); + ShieldWall_Timer = 21000; + }else ShieldWall_Timer -= diff; + } +}; + +CreatureAI* GetAI_boss_moroes(Creature *_Creature) +{ + return new boss_moroesAI (_Creature); +} + +CreatureAI* GetAI_baroness_dorothea_millstipe(Creature *_Creature) +{ + return new boss_baroness_dorothea_millstipeAI (_Creature); +} + +CreatureAI* GetAI_baron_rafe_dreuger(Creature *_Creature) +{ + return new boss_baron_rafe_dreugerAI (_Creature); +} + +CreatureAI* GetAI_lady_catriona_von_indi(Creature *_Creature) +{ + return new boss_lady_catriona_von_indiAI (_Creature); +} + +CreatureAI* GetAI_lady_keira_berrybuck(Creature *_Creature) +{ + return new boss_lady_keira_berrybuckAI (_Creature); +} + +CreatureAI* GetAI_lord_robin_daris(Creature *_Creature) +{ + return new boss_lord_robin_darisAI (_Creature); +} + +CreatureAI* GetAI_lord_crispin_ference(Creature *_Creature) +{ + return new boss_lord_crispin_ferenceAI (_Creature); +} + +void AddSC_boss_moroes() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_moroes"; + newscript->GetAI = GetAI_boss_moroes; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_baroness_dorothea_millstipe"; + newscript->GetAI = GetAI_baroness_dorothea_millstipe; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_baron_rafe_dreuger"; + newscript->GetAI = GetAI_baron_rafe_dreuger; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_lady_catriona_von_indi"; + newscript->GetAI = GetAI_lady_catriona_von_indi; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_lady_keira_berrybuck"; + newscript->GetAI = GetAI_lady_keira_berrybuck; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_lord_robin_daris"; + newscript->GetAI = GetAI_lord_robin_daris; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_lord_crispin_ference"; + newscript->GetAI = GetAI_lord_crispin_ference; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/karazhan/boss_netherspite.cpp b/src/bindings/scripts/scripts/zone/karazhan/boss_netherspite.cpp new file mode 100644 index 00000000000..dfddad46aff --- /dev/null +++ b/src/bindings/scripts/scripts/zone/karazhan/boss_netherspite.cpp @@ -0,0 +1,37 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Netherspite +SD%Complete: 0 +SDComment: Place Holder +SDCategory: Karazhan +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_NETHERBURN_AURA 30522 +#define SPELL_VOIDZONE 37014 //Probably won't work +#define SPELL_BERSERK 26662 +#define SPELL_NETHERBREATH 36631 + +//Beams (no idea how these are going to work in Mangos) +#define SPELL_DOMINANCE_ENEMY 30423 +#define SPELL_DOMINANCE_SELF 30468 +#define SPELL_PERSEVERANCE_ENEMY 30421 +#define SPELL_PERSEVERANCE_SELF 30466 +#define SPELL_SERENITY_ENEMY 30422 +#define SPELL_SERENITY_SELF 30467 diff --git a/src/bindings/scripts/scripts/zone/karazhan/boss_nightbane.cpp b/src/bindings/scripts/scripts/zone/karazhan/boss_nightbane.cpp new file mode 100644 index 00000000000..8b84df3a7fd --- /dev/null +++ b/src/bindings/scripts/scripts/zone/karazhan/boss_nightbane.cpp @@ -0,0 +1,33 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Nightbane +SD%Complete: 0 +SDComment: Place holder +SDCategory: Karazhan +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_BELLOWING_ROAR 39427 +#define SPELL_CHARRED_EARTH 30129 //Also 30209 (Target Charred Earth) triggers this +#define SPELL_DISTRACTING_ASH 30130 +#define SPELL_SMOLDERING_BREATH 30210 +#define SPELL_TAIL_SWEEP 25653 +#define SPELL_RAIN_OF_BONES 37098 +#define SPELL_SMOKING_BLAST 37057 +#define SPELL_FIREBALL_BARRAGE 30282 diff --git a/src/bindings/scripts/scripts/zone/karazhan/boss_prince_malchezaar.cpp b/src/bindings/scripts/scripts/zone/karazhan/boss_prince_malchezaar.cpp new file mode 100644 index 00000000000..842321cfbff --- /dev/null +++ b/src/bindings/scripts/scripts/zone/karazhan/boss_prince_malchezaar.cpp @@ -0,0 +1,646 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Prince_Malchezzar +SD%Complete: 100 +SDComment: +SDCategory: Karazhan +EndScriptData */ + +#include "precompiled.h" + +#define SAY_AGGRO "Madness has brought you here to me. I shall be your undoing!" +#define SOUND_AGGRO 9218 +#define SAY_SUMMON1 "You face not Malchezaar alone, but the legions I command!" +#define SOUND_SUMMON1 9322 +#define SAY_SUMMON2 "All realities, all dimensions are open to me!" +#define SOUND_SUMMON2 9224 +#define SAY_PHASE2 "Simple fools! Time is the fire in which you'll burn!" +#define SOUND_PHASE2 9220 +#define SAY_PHASE3 "How can you hope to withstand against such overwhelming power?" +#define SOUND_PHASE3 9321 +#define SAY_PDEATH1 "You are, but a plaything, unfit even to amuse." +#define SOUND_PDEATH1 9319 +#define SAY_PDEATH2 "Your greed, your foolishness has brought you to this end." +#define SOUND_PDEATH2 9318 +#define SAY_PDEATH3 "Surely you did not think you could win." +#define SOUND_PDEATH3 9222 +#define SAY_DEATH "I refuse to concede defeat. I am a prince of the Eredar! I am..." +#define SOUND_DEATH 9221 + +// 19 Coordinates for Infernal spawns +struct InfernalPoint +{ + float x,y; +}; + +#define INFERNAL_Z 275.5 + +static InfernalPoint InfernalPoints[] = +{ + {-10922.8, -1985.2}, + {-10916.2, -1996.2}, + {-10932.2, -2008.1}, + {-10948.8, -2022.1}, + {-10958.7, -1997.7}, + {-10971.5, -1997.5}, + {-10990.8, -1995.1}, + {-10989.8, -1976.5}, + {-10971.6, -1973.0}, + {-10955.5, -1974.0}, + {-10939.6, -1969.8}, + {-10958.0, -1952.2}, + {-10941.7, -1954.8}, + {-10943.1, -1988.5}, + {-10948.8, -2005.1}, + {-10984.0, -2019.3}, + {-10932.8, -1979.6}, + {-10932.8, -1979.6}, + {-10935.7, -1996.0} +}; + +#define TOTAL_INFERNAL_POINTS 19 + +//Enfeeble is supposed to reduce hp to 1 and then heal player back to full when it ends +//Along with reducing healing and regen while enfeebled to 0% +//This spell effect will only reduce healing + +#define SPELL_ENFEEBLE 30843 //Enfeeble during phase 1 and 2 +#define SPELL_ENFEEBLE_EFFECT 41624 + +#define SPELL_SHADOWNOVA 30852 //Shadownova used during all phases +#define SPELL_SW_PAIN 30854 //Shadow word pain during phase 1 and 3 (different targeting rules though) +#define SPELL_THRASH_PASSIVE 12787 //Extra attack chance during phase 2 +#define SPELL_SUNDER_ARMOR 30901 //Sunder armor during phase 2 +#define SPELL_THRASH_AURA 3417 //Passive proc chance for thrash +#define SPELL_EQUIP_AXES 30857 //Visual for axe equiping +#define SPELL_AMPLIFY_DAMAGE 12738 //Amplifiy during phase 3 +#define SPELL_HELLFIRE 30859 //Infenals' hellfire aura +#define NETHERSPITE_INFERNAL 17646 //The netherspite infernal creature +#define MALCHEZARS_AXE 17650 //Malchezar's axes (creatures), summoned during phase 3 + +#define INFERNAL_MODEL_INVISIBLE 11686 //Infernal Effects +#define SPELL_INFERNAL_RELAY 30834 + +#define AXE_EQUIP_MODEL 40066 //Axes info +#define AXE_EQUIP_INFO 33448898 + +//---------Infernal code first +struct MANGOS_DLL_DECL netherspite_infernalAI : public ScriptedAI +{ + netherspite_infernalAI(Creature *c) : ScriptedAI(c) , + malchezaar(0), HellfireTimer(0), CleanupTimer(0), point(NULL) {Reset();} + + uint32 HellfireTimer; + uint32 CleanupTimer; + uint32 malchezaar; + InfernalPoint *point; + + void Reset() {} + void Aggro(Unit *who) {} + void MoveInLineOfSight(Unit *who) {} + + void UpdateAI(const uint32 diff) + { + if(HellfireTimer) + if(HellfireTimer <= diff) + { + DoCast(m_creature, SPELL_HELLFIRE); + HellfireTimer = 0; + } + else HellfireTimer -= diff; + + if(CleanupTimer) + if(CleanupTimer <= diff) + { + Cleanup(); + CleanupTimer = 0; + } else CleanupTimer -= diff; + } + + void KilledUnit(Unit *who) + { + Unit *pMalchezaar = Unit::GetUnit(*m_creature, malchezaar); + if(pMalchezaar) + ((Creature*)pMalchezaar)->AI()->KilledUnit(who); + } + + void SpellHit(Unit *who, const SpellEntry *spell) + { + if(spell->Id == SPELL_INFERNAL_RELAY) + { + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, m_creature->GetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID)); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + HellfireTimer = 4000; + CleanupTimer = 170000; + } + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if(done_by->GetGUID() != malchezaar) + damage = 0; + } + + void Cleanup(); //below ... +}; + +struct MANGOS_DLL_DECL boss_malchezaarAI : public ScriptedAI +{ + boss_malchezaarAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 EnfeebleTimer; + uint32 EnfeebleResetTimer; + uint32 ShadowNovaTimer; + uint32 SWPainTimer; + uint32 SunderArmorTimer; + uint32 AmplifyDamageTimer; + uint32 InfernalTimer; + uint32 AxesTargetSwitchTimer; + uint32 InfernalCleanupTimer; + + std::vector infernals; + std::vector positions; + + uint64 axes[2]; + uint64 enfeeble_targets[5]; + uint64 enfeeble_health[5]; + + uint32 phase; + + void Reset() + { + AxesCleanup(); + ClearWeapons(); + InfernalCleanup(); + positions.clear(); + + for(int i =0; i < 5; ++i) + enfeeble_targets[i] = 0; + + for(int i = 0; i < TOTAL_INFERNAL_POINTS; ++i) + positions.push_back(&InfernalPoints[i]); + + EnfeebleTimer = 30000; + EnfeebleResetTimer = 38000; + ShadowNovaTimer = 35000; + SWPainTimer = 20000; + AmplifyDamageTimer = 10000; + InfernalTimer = 45000; + InfernalCleanupTimer = 47000; + AxesTargetSwitchTimer = 7500 + rand()%12500; + phase = 1; + } + + void KilledUnit(Unit *victim) + { + switch(rand()%3) + { + case 0: + DoYell(SAY_PDEATH1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(victim, SOUND_PDEATH1); + break; + case 1: + DoYell(SAY_PDEATH2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(victim, SOUND_PDEATH2); + break; + case 2: + DoYell(SAY_PDEATH3, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(victim, SOUND_PDEATH3); + break; + } + } + + void JustDied(Unit *victim) + { + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_DEATH); + + AxesCleanup(); + ClearWeapons(); + InfernalCleanup(); + positions.clear(); + + for(int i = 0; i < TOTAL_INFERNAL_POINTS; ++i) + positions.push_back(&InfernalPoints[i]); + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO); + } + + void InfernalCleanup() + { + //Infernal Cleanup + for(std::vector::iterator itr = infernals.begin(); itr!= infernals.end(); ++itr) + { + Unit *pInfernal = Unit::GetUnit(*m_creature, *itr); + if(pInfernal && pInfernal->isAlive()) + { + pInfernal->SetVisibility(VISIBILITY_OFF); + pInfernal->setDeathState(JUST_DIED); + } + } + infernals.clear(); + } + + void AxesCleanup() + { + for(int i=0; i<2;++i) + { + Unit *axe = Unit::GetUnit(*m_creature, axes[i]); + if(axe && axe->isAlive()) + axe->DealDamage(axe, axe->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + axes[i] = 0; + } + } + + void ClearWeapons() + { + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 0); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, 0); + + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 0); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+2, 0); + + //damage + const CreatureInfo *cinfo = m_creature->GetCreatureInfo(); + m_creature->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, cinfo->mindmg); + m_creature->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, cinfo->maxdmg); + m_creature->UpdateDamagePhysical(BASE_ATTACK); + } + + void EnfeebleHealthEffect() + { + const SpellEntry *info = GetSpellStore()->LookupEntry(SPELL_ENFEEBLE_EFFECT); + if(!info) + return; + + std::list t_list = m_creature->getThreatManager().getThreatList(); + std::vector targets; + + if(!t_list.size()) + return; + + //begin + 1 , so we don't target the one with the highest threat + std::list::iterator itr = t_list.begin(); + std::advance(itr, 1); + for( ; itr!= t_list.end(); ++itr) //store the threat list in a different container + { + Unit *target = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid()); + //only on alive players + if(target && target->isAlive() && target->GetTypeId() == TYPEID_PLAYER ) + targets.push_back( target); + } + + //cut down to size if we have more than 5 targets + while(targets.size() > 5) + targets.erase(targets.begin()+rand()%targets.size()); + + int i = 0; + for(std::vector::iterator itr = targets.begin(); itr!= targets.end(); ++itr, ++i) + { + Unit *target = *itr; + if(target) + { + enfeeble_targets[i] = target->GetGUID(); + enfeeble_health[i] = target->GetHealth(); + + target->CastSpell(target, SPELL_ENFEEBLE, true, 0, 0, m_creature->GetGUID()); + target->SetHealth(1); + } + } + + } + + void EnfeebleResetHealth() + { + for(int i = 0; i < 5; ++i) + { + Unit *target = Unit::GetUnit(*m_creature, enfeeble_targets[i]); + if(target && target->isAlive()) + target->SetHealth(enfeeble_health[i]); + enfeeble_targets[i] = 0; + enfeeble_health[i] = 0; + } + } + + void SummonInfernal(const uint32 diff) + { + InfernalPoint *point = NULL; + float posX,posY,posZ; + if( (m_creature->GetMapId() != 532) || positions.empty()) + { + m_creature->GetRandomPoint(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 60, posX, posY, posZ); + } + else + { + std::vector::iterator itr = positions.begin()+rand()%positions.size(); + point = *itr; + positions.erase(itr); + + posX = point->x; + posY = point->y; + posZ = INFERNAL_Z; + } + + Creature *Infernal = m_creature->SummonCreature(NETHERSPITE_INFERNAL, posX, posY, posZ, 0, TEMPSUMMON_TIMED_DESPAWN, 180000); + + if (Infernal) + { + Infernal->SetUInt32Value(UNIT_FIELD_DISPLAYID, INFERNAL_MODEL_INVISIBLE); + Infernal->setFaction(m_creature->getFaction()); + if(point) + ((netherspite_infernalAI*)Infernal->AI())->point=point; + ((netherspite_infernalAI*)Infernal->AI())->malchezaar=m_creature->GetGUID(); + + infernals.push_back(Infernal->GetGUID()); + DoCast(Infernal, SPELL_INFERNAL_RELAY); + } + + switch(rand()%2) + { + case 0: + DoYell(SAY_SUMMON1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SUMMON1); + break; + case 1: + DoYell(SAY_SUMMON2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SUMMON2); + break; + } + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if(EnfeebleResetTimer) + if(EnfeebleResetTimer <= diff) //Let's not forget to reset that + { + EnfeebleResetHealth(); + EnfeebleResetTimer=0; + }else EnfeebleResetTimer -= diff; + + if(m_creature->hasUnitState(UNIT_STAT_STUNDED)) //While shifting to phase 2 malchezaar stuns himself + return; + + if(m_creature->GetUInt64Value(UNIT_FIELD_TARGET)!=m_creature->getVictim()->GetGUID()) + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, m_creature->getVictim()->GetGUID()); + + if(phase == 1) + { + if( (m_creature->GetHealth()*100) / m_creature->GetMaxHealth() < 60) + { + m_creature->InterruptNonMeleeSpells(false); + + phase = 2; + + //animation + DoCast(m_creature, SPELL_EQUIP_AXES); + + //text + DoYell(SAY_PHASE2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_PHASE2); + + //passive thrash aura + m_creature->CastSpell(m_creature, SPELL_THRASH_AURA, true); + + //models + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, AXE_EQUIP_MODEL); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, AXE_EQUIP_INFO); + + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, AXE_EQUIP_MODEL); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+2, AXE_EQUIP_INFO); + + //damage + const CreatureInfo *cinfo = m_creature->GetCreatureInfo(); + m_creature->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, 2*cinfo->mindmg); + m_creature->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, 2*cinfo->maxdmg); + m_creature->UpdateDamagePhysical(BASE_ATTACK); + + m_creature->SetBaseWeaponDamage(OFF_ATTACK, MINDAMAGE, cinfo->mindmg); + m_creature->SetBaseWeaponDamage(OFF_ATTACK, MAXDAMAGE, cinfo->maxdmg); + //Sigh, updating only works on main attack , do it manually .... + m_creature->SetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE, cinfo->mindmg); + m_creature->SetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE, cinfo->maxdmg); + + m_creature->SetAttackTime(OFF_ATTACK, (((uint32)m_creature->GetAttackTime(BASE_ATTACK)/1.5))); + } + } + else if(phase == 2) + { + if( (m_creature->GetHealth()*100) / m_creature->GetMaxHealth() < 30) + { + InfernalTimer = 15000; + + phase = 3; + + ClearWeapons(); + + //remove thrash + m_creature->RemoveAurasDueToSpell(SPELL_THRASH_AURA); + + DoYell(SAY_PHASE3, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_PHASE3); + + Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 0); + for(uint32 i=0; i<2; ++i) + { + Creature *axe = m_creature->SummonCreature(MALCHEZARS_AXE, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1000); + if(axe) + { + axe->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, AXE_EQUIP_MODEL); + axe->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, AXE_EQUIP_INFO); + + axe->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + axe->setFaction(m_creature->getFaction()); + axes[i] = axe->GetGUID(); + if(target) + { + axe->AI()->AttackStart(target); + // axe->getThreatManager().tauntApply(target); //Taunt Apply and fade out does not work properly + // So we'll use a hack to add a lot of threat to our target + axe->AddThreat(target, 10000000.0f); + } + } + } + + if(ShadowNovaTimer > 35000) + ShadowNovaTimer = EnfeebleTimer + 5000; + + return; + } + + if(SunderArmorTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_SUNDER_ARMOR); + SunderArmorTimer = 15000; + + }else SunderArmorTimer -= diff; + } + else + { + if(AxesTargetSwitchTimer < diff) + { + AxesTargetSwitchTimer = 7500 + rand()%12500 ; + + Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target) + { + for(int i = 0; i < 2; ++i) + { + Unit *axe = Unit::GetUnit(*m_creature, axes[i]); + if(axe) + { + float threat = 1000000.0f; + if(axe->getVictim() && m_creature->getThreatManager().getThreat(axe->getVictim())) + { + threat = axe->getThreatManager().getThreat(axe->getVictim()); + axe->getThreatManager().modifyThreatPercent(axe->getVictim(), -100); + } + if(target) + axe->AddThreat(target, threat); + //axe->getThreatManager().tauntFadeOut(axe->getVictim()); + //axe->getThreatManager().tauntApply(target); + } + } + } + } else AxesTargetSwitchTimer -= diff; + + if(AmplifyDamageTimer < diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_AMPLIFY_DAMAGE); + AmplifyDamageTimer = 20000 + rand()%10000; + }else AmplifyDamageTimer -= diff; + } + + //Time for global and double timers + if(InfernalTimer < diff) + { + SummonInfernal(diff); + InfernalTimer = phase == 3 ? 15000 : 45000; //15 secs in phase 3, 45 otherwise + }else InfernalTimer -= diff; + + if(ShadowNovaTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_SHADOWNOVA); + ShadowNovaTimer = phase == 3 ? 35000 : -1; + }else ShadowNovaTimer -= diff; + + if(phase != 2) + { + if(SWPainTimer < diff) + { + Unit *target; + if(phase == 1) + target = m_creature->getVictim(); // the tank + else //anyone but the tank + target = SelectUnit(SELECT_TARGET_RANDOM, 1); + + DoCast(target, SPELL_SW_PAIN); + SWPainTimer = 20000; + }else SWPainTimer -= diff; + } + + if(phase != 3) + { + if(EnfeebleTimer < diff) + { + EnfeebleHealthEffect(); + EnfeebleTimer = 30000; + ShadowNovaTimer = 5000; + EnfeebleResetTimer = 9000; + }else EnfeebleTimer -= diff; + } + + if(phase==2) + DoMeleeAttacksIfReady(); + else + DoMeleeAttackIfReady(); + } + + void DoMeleeAttacksIfReady() + { + if( m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE) && !m_creature->IsNonMeleeSpellCasted(false)) + { + //Check for base attack + if( m_creature->isAttackReady()) + { + m_creature->AttackerStateUpdate(m_creature->getVictim()); + m_creature->resetAttackTimer(); + } + //Check for offhand attack + if( m_creature->isAttackReady(OFF_ATTACK)) + { + m_creature->AttackerStateUpdate(m_creature->getVictim(), OFF_ATTACK); + m_creature->resetAttackTimer(OFF_ATTACK); + } + } + } + + void Cleanup(Creature *infernal, InfernalPoint *point) + { + for(std::vector::iterator itr = infernals.begin(); itr!= infernals.end(); ++itr) + if(*itr == infernal->GetGUID()) + { + infernals.erase(itr); + break; + } + + positions.push_back(point); + } +}; + +void netherspite_infernalAI::Cleanup() +{ + Unit *pMalchezaar = Unit::GetUnit(*m_creature, malchezaar); + + if(pMalchezaar && pMalchezaar->isAlive()) + ((boss_malchezaarAI*)((Creature*)pMalchezaar)->AI())->Cleanup(m_creature, point); +} + +CreatureAI* GetAI_netherspite_infernal(Creature *_Creature) +{ + return new netherspite_infernalAI (_Creature); +} + +CreatureAI* GetAI_boss_malchezaar(Creature *_Creature) +{ + return new boss_malchezaarAI (_Creature); +} + +void AddSC_netherspite_infernal() +{ + Script *newscript; + newscript = new Script; + newscript->Name="netherspite_infernal"; + newscript->GetAI = GetAI_netherspite_infernal; + m_scripts[nrscripts++] = newscript; +} + +void AddSC_boss_malchezaar() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_malchezaar"; + newscript->GetAI = GetAI_boss_malchezaar; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/karazhan/boss_shade_of_aran.cpp b/src/bindings/scripts/scripts/zone/karazhan/boss_shade_of_aran.cpp new file mode 100644 index 00000000000..c90620f04a7 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/karazhan/boss_shade_of_aran.cpp @@ -0,0 +1,673 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Shade_of_Aran +SD%Complete: 95 +SDComment: Flame wreath missing cast animation, mods won't triggere. Drinking may cause client crash (core related) +SDCategory: Karazhan +EndScriptData */ + +#include "precompiled.h" +#include "../../creature/simple_ai.h" +#include "def_karazhan.h" +#include "GameObject.h" + +//Aggro +#define SAY_AGGRO1 "Please, no more. My son... he's gone mad!" +#define SOUND_AGGRO1 9241 + +#define SAY_AGGRO2 "I'll not be tortured again!" +#define SOUND_AGGRO2 9323 + +#define SAY_AGGRO3 "Who are you? What do you want? Stay away from me!" +#define SOUND_AGGRO3 9324 + +//Flame Wreath +#define SAY_FLAMEWREATH1 "I'll show you this beaten dog still has some teeth!" +#define SOUND_FLAMEWREATH1 9245 +#define SAY_FLAMEWREATH2 "Burn you hellish fiends!" +#define SOUND_FLAMEWREATH2 9326 + +//Blizzard +#define SAY_BLIZZARD1 "I'll freeze you all!" +#define SOUND_BLIZZARD1 9246 +#define SAY_BLIZZARD2 "Back to the cold dark with you!" +#define SOUND_BLIZZARD2 9327 + +//Arcane Explosion +#define SAY_EXPLOSION1 "Yes, yes, my son is quite powerful... but I have powers of my own!" +#define SOUND_EXPLOSION1 9242 +#define SAY_EXPLOSION2 "I am not some simple jester! I am Nielas Aran!" +#define SOUND_EXPLOSION2 9325 + +//Low Mana / AoE Pyroblast +#define SAY_DRINK "Surely you would not deny an old man a replenishing drink? No, no I thought not." +#define SOUND_DRINK 9248 + +//Summon Water Elementals +#define SAY_ELEMENTALS "I'm not finished yet! No, I have a few more tricks up me sleeve." +#define SOUND_ELEMENTALS 9251 + +//Player Death +#define SAY_KILL1 "I want this nightmare to be over!" +#define SOUND_KILL1 9250 + +#define SAY_KILL2 "Torment me no more!" +#define SOUND_KILL2 9328 + +//Time over +#define SAY_TIMEOVER "You've wasted enough of my time. Let these games be finished!" +#define SOUND_TIMEOVER 9247 + +//Aran's death +#define SAY_DEATH "At last... The nightmare is.. over..." +#define SOUND_DEATH 9244 + +//Atiesh is equipped by a raid member +#define SAY_ATIESH "Where did you get that?! Did HE send you?!" +#define SOUND_ATIESH 9249 + +//Spells +#define SPELL_FROSTBOLT 29954 +#define SPELL_FIREBALL 29953 +#define SPELL_ARCMISSLE 29955 +#define SPELL_CHAINSOFICE 29991 +#define SPELL_DRAGONSBREATH 29964 +#define SPELL_MASSSLOW 30035 +#define SPELL_FLAME_WREATH 29946 +#define SPELL_AOE_CS 29961 +#define SPELL_PLAYERPULL 32265 +#define SPELL_AEXPLOSION 29973 +#define SPELL_MASS_POLY 29963 +#define SPELL_BLINK_CENTER 29967 +#define SPELL_ELEMENTALS 29962 +#define SPELL_CONJURE 29975 +#define SPELL_DRINK 30024 +#define SPELL_POTION 32453 +#define SPELL_AOE_PYROBLAST 29978 + +//Creature Spells +#define SPELL_CIRCULAR_BLIZZARD 29951 //29952 is the REAL circular blizzard that leaves persistant blizzards that last for 10 seconds +#define SPELL_WATERBOLT 31012 +#define SPELL_SHADOW_PYRO 29978 + +//Creatures +#define CREATURE_WATER_ELEMENTAL 17167 +#define CREATURE_SHADOW_OF_ARAN 18254 +#define CREATURE_ARAN_BLIZZARD 17161 + +enum SuperSpell +{ + SUPER_FLAME = 0, + SUPER_BLIZZARD, + SUPER_AE, +}; + +struct MANGOS_DLL_DECL boss_aranAI : public ScriptedAI +{ + boss_aranAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + + uint32 SecondarySpellTimer; + uint32 NormalCastTimer; + uint32 SuperCastTimer; + uint32 BerserkTimer; + uint32 CloseDoorTimer; // Don't close the door right on aggro in case some people are still entering. + + uint8 LastSuperSpell; + + uint32 FlameWreathTimer; + uint32 FlameWreathCheckTime; + uint64 FlameWreathTarget[3]; + float FWTargPosX[3]; + float FWTargPosY[3]; + + uint32 CurrentNormalSpell; + uint32 ArcaneCooldown; + uint32 FireCooldown; + uint32 FrostCooldown; + + uint32 DrinkInturruptTimer; + + bool ElementalsSpawned; + bool Drinking; + bool DrinkInturrupted; + + void Reset() + { + SecondarySpellTimer = 5000; + NormalCastTimer = 0; + SuperCastTimer = 35000; + BerserkTimer = 720000; + CloseDoorTimer = 15000; + + LastSuperSpell = rand()%3; + + FlameWreathTimer = 0; + FlameWreathCheckTime = 0; + + CurrentNormalSpell = 0; + ArcaneCooldown = 0; + FireCooldown = 0; + FrostCooldown = 0; + + DrinkInturruptTimer = 10000; + + ElementalsSpawned = false; + Drinking = false; + DrinkInturrupted = false; + + if(pInstance) + { + // Not in progress + pInstance->SetData(DATA_SHADEOFARAN_EVENT, NOT_STARTED); + + if(GameObject* Door = GameObject::GetGameObject(*m_creature, pInstance->GetData64(DATA_GAMEOBJECT_LIBRARY_DOOR))) + Door->SetGoState(0); + } + } + + void KilledUnit(Unit *victim) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_KILL1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(victim, SOUND_KILL1); + break; + case 1: + DoYell(SAY_KILL2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(victim, SOUND_KILL2); + break; + } + } + + void JustDied(Unit *victim) + { + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(NULL, SOUND_DEATH); + + if(pInstance) + { + pInstance->SetData(DATA_SHADEOFARAN_EVENT, DONE); + if(GameObject* Door = GameObject::GetGameObject(*m_creature, pInstance->GetData64(DATA_GAMEOBJECT_LIBRARY_DOOR))) + Door->SetGoState(0); + } + } + + void Aggro(Unit *who) + { + switch(rand()%3) + { + case 0: + DoYell(SAY_AGGRO1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO1); + break; + case 1: + DoYell(SAY_AGGRO2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO2); + break; + case 2: + DoYell(SAY_AGGRO3, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO3); + break; + } + + if(pInstance) + pInstance->SetData(DATA_SHADEOFARAN_EVENT, IN_PROGRESS); + } + + void FlameWreathEffect() + { + std::vector targets; + std::list t_list = m_creature->getThreatManager().getThreatList(); + + if(!t_list.size()) + return; + + //store the threat list in a different container + for(std::list::iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + Unit *target = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid()); + //only on alive players + if(target && target->isAlive() && target->GetTypeId() == TYPEID_PLAYER ) + targets.push_back( target); + } + + //cut down to size if we have more than 3 targets + while(targets.size() > 3) + targets.erase(targets.begin()+rand()%targets.size()); + + uint32 i = 0; + for(std::vector::iterator itr = targets.begin(); itr!= targets.end(); ++itr) + { + if(*itr) + { + FlameWreathTarget[i] = (*itr)->GetGUID(); + FWTargPosX[i] = (*itr)->GetPositionX(); + FWTargPosY[i] = (*itr)->GetPositionY(); + m_creature->CastSpell((*itr), SPELL_FLAME_WREATH, true); + i++; + } + } + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if(CloseDoorTimer) + if(CloseDoorTimer <= diff) + { + if(pInstance) + if(GameObject* Door = GameObject::GetGameObject(*m_creature, pInstance->GetData64(DATA_GAMEOBJECT_LIBRARY_DOOR))) + Door->SetGoState(1); + CloseDoorTimer = 0; + } + else CloseDoorTimer -= diff; + + //Cooldowns for casts + if (ArcaneCooldown) + if (ArcaneCooldown >= diff) + ArcaneCooldown -= diff; + else ArcaneCooldown = 0; + + if (FireCooldown) + if (FireCooldown >= diff) + FireCooldown -= diff; + else FireCooldown = 0; + + if (FrostCooldown) + if (FrostCooldown >= diff) + FrostCooldown -= diff; + else FrostCooldown = 0; + + if(!Drinking && m_creature->GetMaxPower(POWER_MANA) && (m_creature->GetPower(POWER_MANA)*100 / m_creature->GetMaxPower(POWER_MANA)) < 20) + { + Drinking = true; + m_creature->InterruptNonMeleeSpells(false); + + DoYell(SAY_DRINK, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_DRINK); + + if (!DrinkInturrupted) + { + m_creature->CastSpell(m_creature, SPELL_MASS_POLY, true); + m_creature->CastSpell(m_creature, SPELL_CONJURE, false); + m_creature->CastSpell(m_creature, SPELL_DRINK, false); + //Sitting down + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 1); + DrinkInturruptTimer = 10000; + } + } + + //Drink Inturrupt + if (Drinking && DrinkInturrupted) + { + Drinking = false; + m_creature->RemoveAurasDueToSpell(SPELL_DRINK); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + m_creature->SetPower(POWER_MANA, m_creature->GetMaxPower(POWER_MANA)-32000); + m_creature->CastSpell(m_creature, SPELL_POTION, false); + } + + //Drink Inturrupt Timer + if (Drinking && !DrinkInturrupted) + if (DrinkInturruptTimer >= diff) + DrinkInturruptTimer -= diff; + else + { + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + m_creature->CastSpell(m_creature, SPELL_POTION, true); + m_creature->CastSpell(m_creature, SPELL_AOE_PYROBLAST, false); + DrinkInturrupted = true; + Drinking = false; + } + + //Don't execute any more code if we are drinking + if (Drinking) + return; + + //Normal casts + if(NormalCastTimer < diff) + { + if (!m_creature->IsNonMeleeSpellCasted(false)) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (!target) + return; + + uint32 Spells[3]; + uint8 AvailableSpells = 0; + + //Check for what spells are not on cooldown + if (!ArcaneCooldown) + { + Spells[AvailableSpells] = SPELL_ARCMISSLE; + AvailableSpells++; + } + if (!FireCooldown) + { + Spells[AvailableSpells] = SPELL_FIREBALL; + AvailableSpells++; + } + if (!FrostCooldown) + { + Spells[AvailableSpells] = SPELL_FROSTBOLT; + AvailableSpells++; + } + + //If no available spells wait 1 second and try again + if (AvailableSpells) + { + CurrentNormalSpell = Spells[rand() % AvailableSpells]; + DoCast(target, CurrentNormalSpell); + } + } + NormalCastTimer = 1000; + }else NormalCastTimer -= diff; + + if(SecondarySpellTimer < diff) + { + switch (rand()%2) + { + + case 0: + DoCast(m_creature, SPELL_AOE_CS); + break; + case 1: + Unit* pUnit; + pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pUnit) + DoCast(pUnit, SPELL_CHAINSOFICE); + break; + } + SecondarySpellTimer = 5000 + (rand()%15000); + }else SecondarySpellTimer -= diff; + + if(SuperCastTimer < diff) + { + uint8 Available[2]; + + switch (LastSuperSpell) + { + case SUPER_AE: + Available[0] = SUPER_FLAME; + Available[1] = SUPER_BLIZZARD; + break; + case SUPER_FLAME: + Available[0] = SUPER_AE; + Available[1] = SUPER_BLIZZARD; + break; + case SUPER_BLIZZARD: + Available[0] = SUPER_FLAME; + Available[1] = SUPER_AE; + break; + } + + LastSuperSpell = Available[rand()%2]; + + switch (LastSuperSpell) + { + case SUPER_AE: + + if (rand()%2) + { + DoYell(SAY_EXPLOSION1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_EXPLOSION1); + }else + { + DoYell(SAY_EXPLOSION2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_EXPLOSION2); + } + + m_creature->CastSpell(m_creature, SPELL_BLINK_CENTER, true); + m_creature->CastSpell(m_creature, SPELL_PLAYERPULL, true); + m_creature->CastSpell(m_creature, SPELL_MASSSLOW, true); + m_creature->CastSpell(m_creature, SPELL_AEXPLOSION, false); + break; + + case SUPER_FLAME: + if (rand()%2) + { + DoYell(SAY_FLAMEWREATH1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_FLAMEWREATH1); + }else + { + DoYell(SAY_FLAMEWREATH2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_FLAMEWREATH2); + } + + FlameWreathTimer = 20000; + FlameWreathCheckTime = 500; + + FlameWreathTarget[0] = 0; + FlameWreathTarget[1] = 0; + FlameWreathTarget[2] = 0; + + FlameWreathEffect(); + break; + + case SUPER_BLIZZARD: + + if (rand()%2) + { + DoYell(SAY_BLIZZARD1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_BLIZZARD1); + }else + { + DoYell(SAY_BLIZZARD2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_BLIZZARD2); + } + + Creature* Spawn = NULL; + Spawn = DoSpawnCreature(CREATURE_ARAN_BLIZZARD, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 25000); + if (Spawn) + { + Spawn->setFaction(m_creature->getFaction()); + Spawn->CastSpell(Spawn, SPELL_CIRCULAR_BLIZZARD, false); + } + break; + } + + SuperCastTimer = 35000 + (rand()%5000); + }else SuperCastTimer -= diff; + + if(!ElementalsSpawned && m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 40) + { + ElementalsSpawned = true; + + for (uint32 i = 0; i < 4; i++) + { + Creature* pUnit = DoSpawnCreature(CREATURE_WATER_ELEMENTAL, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 90000); + if (pUnit) + { + pUnit->Attack(m_creature->getVictim(), true); + pUnit->setFaction(m_creature->getFaction()); + } + } + + DoYell(SAY_ELEMENTALS, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_ELEMENTALS); + } + + if(BerserkTimer < diff) + { + for (uint32 i = 0; i < 5; i++) + { + Creature* pUnit = DoSpawnCreature(CREATURE_SHADOW_OF_ARAN, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + if (pUnit) + { + pUnit->Attack(m_creature->getVictim(), true); + pUnit->setFaction(m_creature->getFaction()); + } + } + + DoYell(SAY_TIMEOVER, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_TIMEOVER); + + BerserkTimer = 60000; + }else BerserkTimer -= diff; + + //Flame Wreath check + if (FlameWreathTimer) + { + if (FlameWreathTimer >= diff) + FlameWreathTimer -= diff; + else FlameWreathTimer = 0; + + if (FlameWreathCheckTime < diff) + { + for (uint32 i = 0; i < 3; i++) + { + if (!FlameWreathTarget[i]) + continue; + + Unit* pUnit = Unit::GetUnit(*m_creature, FlameWreathTarget[i]); + if (pUnit && pUnit->GetDistance2d(FWTargPosX[i], FWTargPosY[i]) > 3) + { + pUnit->CastSpell(pUnit, 20476, true, 0, 0, m_creature->GetGUID()); + pUnit->CastSpell(pUnit, 11027, true); + FlameWreathTarget[i] = 0; + } + } + FlameWreathCheckTime = 500; + }else FlameWreathCheckTime -= diff; + } + + if (ArcaneCooldown && FireCooldown && FrostCooldown) + DoMeleeAttackIfReady(); + } + + void DamageTaken(Unit* pAttacker, uint32 &damage) + { + if (!DrinkInturrupted && Drinking && damage) + DrinkInturrupted = true; + } + + void SpellHit(Unit* pAttacker, const SpellEntry* Spell) + { + //We only care about inturrupt effects and only if they are durring a spell currently being casted + if ((Spell->Effect[0]!=SPELL_EFFECT_INTERRUPT_CAST && + Spell->Effect[1]!=SPELL_EFFECT_INTERRUPT_CAST && + Spell->Effect[2]!=SPELL_EFFECT_INTERRUPT_CAST) || !m_creature->IsNonMeleeSpellCasted(false)) + return; + + //Inturrupt effect + m_creature->InterruptNonMeleeSpells(false); + + //Normally we would set the cooldown equal to the spell duration + //but we do not have access to the DurationStore + + switch (CurrentNormalSpell) + { + case SPELL_ARCMISSLE: + ArcaneCooldown = 5000; + break; + case SPELL_FIREBALL: + FireCooldown = 5000; + break; + case SPELL_FROSTBOLT: + FrostCooldown = 5000; + break; + } + } +}; + +struct MANGOS_DLL_DECL water_elementalAI : public ScriptedAI +{ + water_elementalAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 CastTimer; + + void Reset() + { + CastTimer = 2000 + (rand()%3000); + } + + void Aggro(Unit* who) {} + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if(CastTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_WATERBOLT); + CastTimer = 2000 + (rand()%3000); + }else CastTimer -= diff; + } +}; + +CreatureAI* GetAI_boss_aran(Creature *_Creature) +{ + return new boss_aranAI (_Creature); +} + +CreatureAI* GetAI_water_elemental(Creature *_Creature) +{ + return new water_elementalAI (_Creature); +} + +// CONVERT TO ACID +CreatureAI* GetAI_shadow_of_aran(Creature *_Creature) +{ + outstring_log("SD2: Convert simpleAI script for Creature Entry %u to ACID", _Creature->GetEntry()); + SimpleAI* ai = new SimpleAI (_Creature); + + ai->Spell[0].Enabled = true; + ai->Spell[0].Spell_Id = SPELL_SHADOW_PYRO; + ai->Spell[0].Cooldown = 5000; + ai->Spell[0].First_Cast = 1000; + ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_TARGET; + + ai->EnterEvadeMode(); + + return ai; +} + +void AddSC_boss_shade_of_aran() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_shade_of_aran"; + newscript->GetAI = GetAI_boss_aran; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_shadow_of_aran"; + newscript->GetAI = GetAI_shadow_of_aran; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_aran_elemental"; + newscript->GetAI = GetAI_water_elemental; + m_scripts[nrscripts++] = newscript; + + //newscript = new Script; + //newscript->Name="mob_aran_blizzard"; + //newscript->GetAI = GetAI_boss_aran; + //m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/karazhan/boss_terestian_illhoof.cpp b/src/bindings/scripts/scripts/zone/karazhan/boss_terestian_illhoof.cpp new file mode 100644 index 00000000000..2fa5b3860a0 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/karazhan/boss_terestian_illhoof.cpp @@ -0,0 +1,454 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Terestian_Illhoof +SD%Complete: 100 +SDComment: Complete! +SDCategory: Karazhan +EndScriptData */ + +#include "precompiled.h" +#include "def_karazhan.h" + +#define SPELL_SUMMON_DEMONCHAINS 30120 // Summons demonic chains that maintain the ritual of sacrifice. +#define SPELL_DEMON_CHAINS 30206 // Instant - Visual Effect +#define SPELL_ENRAGE 23537 // Increases the caster's attack speed by 50% and the Physical damage it deals by 219 to 281 for 10 min. +#define SPELL_SHADOW_BOLT 30055 // Hurls a bolt of dark magic at an enemy, inflicting Shadow damage. +#define SPELL_SACRIFICE 30115 // Teleports and adds the debuff +#define SPELL_BERSERK 32965 // Increases attack speed by 75%. Periodically casts Shadow Bolt Volley. + +#define SPELL_FIREBOLT 18086 // Blasts a target for 150 Fire damage. + +#define SPELL_BROKEN_PACT 30065 // All damage taken increased by 25%. +#define SPELL_AMPLIFY_FLAMES 30053 // Increases the Fire damage taken by an enemy by 500 for 25 sec. +#define SPELL_FIREBOLT 18086 // Blasts a target for 150 Fire damage. + +#define SAY_SLAY1 "Your blood will anoint my circle." +#define SOUND_SLAY1 9264 +#define SAY_SLAY2 "The great one will be pleased." +#define SOUND_SLAY2 9329 + +#define SAY_DEATH "My life, is yours. Oh great one." +#define SOUND_DEATH 9262 + +#define SAY_AGGRO "Ah, you're just in time. The rituals are about to begin." +#define SOUND_AGGRO 9260 + +#define SAY_SACRIFICE1 "Please, accept this humble offering, oh great one." +#define SOUND_SACRIFICE1 9263 +#define SAY_SACRIFICE2 "Let the sacrifice serve his testament to my fealty." +#define SOUND_SACRIFICE2 9330 + +#define SAY_SUMMON1 "Come, you dwellers in the dark. Rally to my call!" +#define SOUND_SUMMON1 9265 +#define SAY_SUMMON2 "Gather, my pets. There is plenty for all." +#define SOUND_SUMMON2 9331 + +#define CREATURE_DEMONCHAINS 17248 +#define CREATURE_FIENDISHIMP 17267 +#define CREATURE_PORTAL 17265 + +#define SACRIFICE_X -11240.599 +#define SACRIFICE_Y -1694.2700 +#define SACRIFICE_Z 179.720007 + +#define PORTAL_Z 179.434 + +float PortalLocations[2][2]= +{ + {-11249.6933, -1704.61023}, + {-11242.1160, -1713.33325}, +}; + +struct MANGOS_DLL_DECL mob_kilrekAI : public ScriptedAI +{ + mob_kilrekAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + + uint64 TerestianGUID; + + uint32 AmplifyTimer; + + void Reset() + { + TerestianGUID = 0; + + AmplifyTimer = 0; + } + + void Aggro(Unit *who) + { + if(!pInstance) + { + ERROR_INST_DATA(m_creature); + return; + } + + Creature* Terestian = ((Creature*)Unit::GetUnit(*m_creature, pInstance->GetData64(DATA_TERESTIAN))); + if(Terestian && (!Terestian->SelectHostilTarget() && !Terestian->getVictim())) + Terestian->AddThreat(who, 1.0f); + } + + void JustDied(Unit* Killer) + { + if(pInstance) + { + uint64 TerestianGUID = pInstance->GetData64(DATA_TERESTIAN); + if(TerestianGUID) + { + Unit* Terestian = Unit::GetUnit((*m_creature), TerestianGUID); + if(Terestian && Terestian->isAlive()) + DoCast(Terestian, SPELL_BROKEN_PACT, true); + } + }else ERROR_INST_DATA(m_creature); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if (AmplifyTimer < diff) + { + m_creature->InterruptNonMeleeSpells(false); + DoCast(m_creature->getVictim(),SPELL_AMPLIFY_FLAMES); + + AmplifyTimer = 20000; + }else AmplifyTimer -= diff; + + //Chain cast + if (!m_creature->IsNonMeleeSpellCasted(false) && m_creature->IsWithinDistInMap(m_creature->getVictim(), 30)) + DoCast(m_creature->getVictim(),SPELL_FIREBOLT); + else DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL mob_demon_chainAI : public ScriptedAI +{ + mob_demon_chainAI(Creature *c) : ScriptedAI(c) + { + Reset(); + } + + uint64 SacrificeGUID; + + void Reset() + { + SacrificeGUID = 0; + } + + void Aggro(Unit* who) {} + void AttackStart(Unit* who) {} + void MoveInLineOfSight(Unit* who) {} + + void JustDied(Unit *killer) + { + if(SacrificeGUID) + { + Unit* Sacrifice = Unit::GetUnit((*m_creature),SacrificeGUID); + if(Sacrifice) + Sacrifice->RemoveAurasDueToSpell(SPELL_SACRIFICE); + } + } +}; + +struct MANGOS_DLL_DECL boss_terestianAI : public ScriptedAI +{ + boss_terestianAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance *pInstance; + + uint64 KilrekGUID; + uint64 PortalGUID[2]; + + uint32 CheckKilrekTimer; + uint32 SacrificeTimer; + uint32 ShadowboltTimer; + uint32 SummonTimer; + uint32 BerserkTimer; + + bool SummonKilrek; + bool SummonedPortals; + bool Berserk; + + void Reset() + { + for(uint8 i = 0; i < 2; ++i) + { + if(PortalGUID[i]) + { + Unit* Portal = Unit::GetUnit((*m_creature), PortalGUID[i]); + if(Portal) + Portal->DealDamage(Portal, Portal->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + + PortalGUID[i] = 0; + } + } + + CheckKilrekTimer = 5000; + SacrificeTimer = 30000; + ShadowboltTimer = 5000; + SummonTimer = 10000; + BerserkTimer = 600000; + + SummonedPortals = false; + Berserk = false; + + if(pInstance) + pInstance->SetData(DATA_TERESTIAN_EVENT, NOT_STARTED); + } + + void Aggro(Unit* who) + { + DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO); + + if(pInstance) + { + // Put Kil'rek in combat against our target so players don't skip him + Creature* Kilrek = ((Creature*)Unit::GetUnit(*m_creature, pInstance->GetData64(DATA_KILREK))); + if(Kilrek && (!Kilrek->SelectHostilTarget() && !Kilrek->getVictim())) + Kilrek->AddThreat(who, 1.0f); + + pInstance->SetData(DATA_TERESTIAN_EVENT, IN_PROGRESS); + }else ERROR_INST_DATA(m_creature); + } + + void KilledUnit(Unit *victim) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_SLAY1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY1); + break; + case 1: + DoYell(SAY_SLAY2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY2); + break; + } + } + + void JustDied(Unit *killer) + { + for(uint8 i = 0; i < 2; ++i) + { + if(PortalGUID[i]) + { + Unit* Portal = Unit::GetUnit((*m_creature), PortalGUID[i]); + if(Portal) + Portal->DealDamage(Portal, Portal->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + + PortalGUID[i] = 0; + } + } + + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_DEATH); + + if(pInstance) + pInstance->SetData(DATA_TERESTIAN_EVENT, DONE); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->getVictim() && !m_creature->SelectHostilTarget()) + return; + + if(CheckKilrekTimer < diff) + { + CheckKilrekTimer = 5000; + + if(pInstance) + uint64 KilrekGUID = pInstance->GetData64(DATA_KILREK); + else ERROR_INST_DATA(m_creature); + + Creature* Kilrek = ((Creature*)Unit::GetUnit((*m_creature), KilrekGUID)); + if(SummonKilrek && Kilrek) + { + Kilrek->Respawn(); + Kilrek->AI()->AttackStart(m_creature->getVictim()); + + SummonKilrek = false; + } + + if(!Kilrek || !Kilrek->isAlive()) + { + SummonKilrek = true; + CheckKilrekTimer = 45000; + } + }else CheckKilrekTimer -= diff; + + if(SacrificeTimer < diff) + { + Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1); + if(target && target->isAlive() && target->GetTypeId() == TYPEID_PLAYER) + { + DoCast(target, SPELL_SACRIFICE, true); + Creature* Chains = m_creature->SummonCreature(CREATURE_DEMONCHAINS, SACRIFICE_X, SACRIFICE_Y, SACRIFICE_Z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 21000); + if(Chains) + { + ((mob_demon_chainAI*)Chains->AI())->SacrificeGUID = target->GetGUID(); + Chains->CastSpell(Chains, SPELL_DEMON_CHAINS, true); + switch(rand()%2) + { + case 0: + DoYell(SAY_SACRIFICE1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SACRIFICE1); + break; + case 1: + DoYell(SAY_SACRIFICE2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SACRIFICE2); + break; + } + SacrificeTimer = 30000; + } + } + }else SacrificeTimer -= diff; + + if(ShadowboltTimer < diff) + { + DoCast(SelectUnit(SELECT_TARGET_TOPAGGRO, 0), SPELL_SHADOW_BOLT); + ShadowboltTimer = 10000; + }else ShadowboltTimer -= diff; + + if(SummonTimer < diff) + { + if(!SummonedPortals) + { + for(uint8 i = 0; i < 2; ++i) + { + Creature* Portal = m_creature->SummonCreature(CREATURE_PORTAL, PortalLocations[i][0], PortalLocations[i][1], PORTAL_Z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + if(Portal) + PortalGUID[i] = Portal->GetGUID(); + } + SummonedPortals = true; + switch(rand()%2) + { + case 0: + DoYell(SAY_SUMMON1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SUMMON1); + break; + case 1: + DoYell(SAY_SUMMON2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SUMMON2); + break; + } + } + uint32 random = rand()%2; + Creature* Imp = m_creature->SummonCreature(CREATURE_FIENDISHIMP, PortalLocations[random][0], PortalLocations[random][1], PORTAL_Z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 15000); + if(Imp) + { + Imp->AddThreat(m_creature->getVictim(), 1.0f); + Imp->AI()->AttackStart(SelectUnit(SELECT_TARGET_RANDOM, 1)); + } + SummonTimer = 5000; + }else SummonTimer -= diff; + + if(!Berserk) + if(BerserkTimer < diff) + { + DoCast(m_creature, SPELL_BERSERK); + Berserk = true; + }else BerserkTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL mob_karazhan_impAI : public ScriptedAI +{ + mob_karazhan_impAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 FireboltTimer; + + void Reset() + { + FireboltTimer = 3000; + } + + void Aggro(Unit *who) {} + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if(FireboltTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_FIREBOLT); + FireboltTimer = 1500; + }else FireboltTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_kilrek(Creature *_Creature) +{ + return new mob_kilrekAI (_Creature); +} + +CreatureAI* GetAI_mob_karazhan_imp(Creature *_Creature) +{ + return new mob_karazhan_impAI (_Creature); +} + +CreatureAI* GetAI_mob_demon_chain(Creature *_Creature) +{ + return new mob_demon_chainAI(_Creature); +} + +CreatureAI* GetAI_boss_terestian_illhoof(Creature *_Creature) +{ + return new boss_terestianAI (_Creature); +} + +void AddSC_boss_terestian_illhoof() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_terestian_illhoof"; + newscript->GetAI = GetAI_boss_terestian_illhoof; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_karazhan_imp"; + newscript->GetAI = GetAI_mob_karazhan_imp; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_kilrek"; + newscript->GetAI = GetAI_mob_kilrek; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name = "mob_demon_chain"; + newscript->GetAI = GetAI_mob_demon_chain; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/karazhan/bosses_opera.cpp b/src/bindings/scripts/scripts/zone/karazhan/bosses_opera.cpp new file mode 100644 index 00000000000..3caedb2dafa --- /dev/null +++ b/src/bindings/scripts/scripts/zone/karazhan/bosses_opera.cpp @@ -0,0 +1,1471 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Bosses_Opera +SD%Complete: 90 +SDComment: Oz, Hood, and RAJ event implemented. RAJ event requires more testing. +SDCategory: Karazhan +EndScriptData */ + +#include "precompiled.h" +#include "def_karazhan.h" + +/***********************************/ +/*** OPERA WIZARD OF OZ EVENT *****/ +/*********************************/ + +/**** Spells ****/ +// Dorothee +#define SPELL_WATERBOLT 31012 +#define SPELL_SCREAM 31013 +#define SPELL_SUMMONTITO 31014 + +// Tito +#define SPELL_YIPPING 31015 + +// Strawman +#define SPELL_BRAIN_BASH 31046 +#define SPELL_BRAIN_WIPE 31069 +#define SPELL_BURNING_STRAW 31075 + +// Tinhead +#define SPELL_CLEAVE 31043 +#define SPELL_RUST 31086 + +// Roar +#define SPELL_MANGLE 31041 +#define SPELL_SHRED 31042 +#define SPELL_FRIGHTENED_SCREAM 31013 + +// Crone +#define SPELL_CHAIN_LIGHTNING 32337 + +// Cyclone +#define SPELL_KNOCKBACK 32334 +#define SPELL_CYCLONE_VISUAL 32332 + +/** Creature Entries **/ +#define CREATURE_TITO 17548 +#define CREATURE_CYCLONE 18412 +#define CREATURE_CRONE 18168 + +/***** Speech and Sound *****/ +#define SAY_DOROTHEE_DEATH "Oh at last, at last. I can go home." +#define SOUND_DOROTHEE_DEATH 9190 +#define SAY_DOROTHEE_SUMMON "Don't let them hurt us, Tito! Oh, you won't, will you?" +#define SOUND_DOROTHEE_SUMMON 9191 +#define SAY_DOROTHEE_TITO_DEATH "Tito, oh Tito, no!" +#define SOUND_DOROTHEE_TITO_DEATH 9192 +#define SAY_DOROTHEE_AGGRO "Oh dear, we simply must find a way home! The old wizard could be our only hope! Strawman, Roar, Tinhead, will you... wait! Oh golly, look! We have visitors!" +#define SOUND_DOROTHEE_AGGRO 9195 + +#define SAY_ROAR_AGGRO "Wanna fight? Huh? Do ya? C'mon, I'll fight you with both claws behind my back!" +#define SOUND_ROAR_AGGRO 9227 +#define SAY_ROAR_DEATH "You didn't have to go and do that." +#define SOUND_ROAR_DEATH 9229 +#define SAY_ROAR_SLAY "I think I'm going to go take fourty winks" +#define SOUND_ROAR_SLAY 9230 + +#define SAY_STRAWMAN_AGGRO "Now what should I do with you? I simply can't make up my mind." +#define SOUND_STRAWMAN_AGGRO 9254 +#define SAY_STRAWMAN_DEATH "Don't let them make a mattress... out of me." +#define SOUND_STRAWMAN_DEATH 9256 +#define SAY_STRAWMAN_SLAY "I guess I'm not a failure after all." +#define SOUND_STRAWMAN_SLAY 9257 + +#define SAY_TINHEAD_AGGRO "I could really use a heart. Say, can I have yours?" +#define SOUND_TINHEAD_AGGRO 9268 +#define SAY_TINHEAD_DEATH "Back to being an old rustbucket." +#define SOUND_TINHEAD_DEATH 9270 +#define SAY_TINHEAD_SLAY "Guess I'm not so rusty, after all." +#define SOUND_TINHEAD_SLAY 9271 + +#define SAY_CRONE_AGGRO "Woe to each and every one of you my pretties!" +#define SOUND_CRONE_AGGRO 9179 +#define SAY_CRONE_AGGRO2 "It will all be over soon!" +#define SOUND_CRONE_AGGRO2 9307 +#define SAY_CRONE_DEATH "How could you? What a cruel, cruel world!" +#define SOUND_CRONE_DEATH 9178 +#define SAY_CRONE_SLAY "Fixed you, didn't I?" +#define SOUND_CRONE_SLAY 9180 + +void SummonCroneIfReady(ScriptedInstance* pInstance, Creature *_Creature) +{ + pInstance->SetData(DATA_OPERA_OZ_DEATHCOUNT, 0); // Increment DeathCount + if(pInstance->GetData(DATA_OPERA_OZ_DEATHCOUNT) == 4) + { + Creature* Crone = _Creature->SummonCreature(CREATURE_CRONE, -10891.96, -1755.95, _Creature->GetPositionZ(), 4.64, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 30000); + if(Crone) + { + if(_Creature->getVictim()) + Crone->AI()->AttackStart(_Creature->getVictim()); + + Crone->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + } +}; + +struct MANGOS_DLL_DECL boss_dorotheeAI : public ScriptedAI +{ + boss_dorotheeAI(Creature* c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + + uint32 AggroTimer; + + uint32 WaterBoltTimer; + uint32 FearTimer; + uint32 SummonTitoTimer; + + bool SummonedTito; + bool TitoDied; + bool InCombat; + + void Reset() + { + AggroTimer = 500; + + WaterBoltTimer = 5000; + FearTimer = 15000; + SummonTitoTimer = 47500; + + SummonedTito = false; + TitoDied = false; + InCombat = false; + } + + void Aggro(Unit* who) + { + DoYell(SAY_DOROTHEE_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_DOROTHEE_AGGRO); + } + + void SummonTito(); // See below + + void JustDied(Unit* killer) + { + DoYell(SAY_DOROTHEE_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_DOROTHEE_DEATH); + + if(pInstance) + SummonCroneIfReady(pInstance, m_creature); + } + + void AttackStart(Unit* who) + { + if(m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::AttackStart(who); + } + + void MoveInLineOfSight(Unit* who) + { + if(m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::MoveInLineOfSight(who); + } + + void UpdateAI(const uint32 diff) + { + if(AggroTimer) + if(AggroTimer <= diff) + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + AggroTimer = 0; + }else AggroTimer -= diff; + + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(WaterBoltTimer < diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_WATERBOLT); + WaterBoltTimer = TitoDied ? 1500 : 5000; + }else WaterBoltTimer -= diff; + + if(FearTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_SCREAM); + FearTimer = 30000; + }else FearTimer -= diff; + + if(!SummonedTito) + { + if(SummonTitoTimer < diff) + SummonTito(); + else SummonTitoTimer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL mob_titoAI : public ScriptedAI +{ + mob_titoAI(Creature* c) : ScriptedAI(c) + { + Reset(); + } + + uint64 DorotheeGUID; + + uint32 YipTimer; + + void Reset() + { + DorotheeGUID = 0; + + YipTimer = 10000; + } + + void Aggro(Unit* who) {} + + void JustDied(Unit* killer) + { + if(DorotheeGUID) + { + Creature* Dorothee = ((Creature*)Unit::GetUnit((*m_creature), DorotheeGUID)); + if(Dorothee && Dorothee->isAlive()) + { + ((boss_dorotheeAI*)Dorothee->AI())->TitoDied = true; + Dorothee->MonsterYell(SAY_DOROTHEE_TITO_DEATH, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(Dorothee, SOUND_DOROTHEE_TITO_DEATH); + } + } + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(YipTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_YIPPING); + YipTimer = 10000; + }else YipTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +void boss_dorotheeAI::SummonTito() +{ + Creature* Tito = DoSpawnCreature(CREATURE_TITO, 0, 0, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 45000); + if(Tito) + { + DoYell(SAY_DOROTHEE_SUMMON, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_DOROTHEE_SUMMON); + ((mob_titoAI*)Tito->AI())->DorotheeGUID = m_creature->GetGUID(); + Tito->AI()->AttackStart(m_creature->getVictim()); + SummonedTito = true; + TitoDied = false; + } +} + +struct MANGOS_DLL_DECL boss_strawmanAI : public ScriptedAI +{ + boss_strawmanAI(Creature* c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + + uint32 AggroTimer; + uint32 BrainBashTimer; + uint32 BrainWipeTimer; + + void Reset() + { + AggroTimer = 13000; + BrainBashTimer = 5000; + BrainWipeTimer = 7000; + } + + void AttackStart(Unit* who) + { + if(m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::AttackStart(who); + } + + void MoveInLineOfSight(Unit* who) + { + if(m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::MoveInLineOfSight(who); + } + + void Aggro(Unit* who) + { + DoYell(SAY_STRAWMAN_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_STRAWMAN_AGGRO); + } + + void SpellHit(Unit* caster, const SpellEntry *Spell) + { + if((Spell->SchoolMask == SPELL_SCHOOL_MASK_FIRE) && (!(rand()%10))) + DoCast(m_creature, SPELL_BURNING_STRAW, true); + } + + void JustDied(Unit* killer) + { + DoYell(SAY_STRAWMAN_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_STRAWMAN_DEATH); + + if(pInstance) + SummonCroneIfReady(pInstance, m_creature); + } + + void KilledUnit(Unit* victim) + { + DoYell(SAY_STRAWMAN_SLAY, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_STRAWMAN_SLAY); + } + + void UpdateAI(const uint32 diff) + { + if(AggroTimer) + if(AggroTimer <= diff) + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + AggroTimer = 0; + }else AggroTimer -= diff; + + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(BrainBashTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_BRAIN_BASH); + BrainBashTimer = 15000; + }else BrainBashTimer -= diff; + + if(BrainWipeTimer < diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_BRAIN_WIPE); + BrainWipeTimer = 20000; + }else BrainWipeTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL boss_tinheadAI : public ScriptedAI +{ + boss_tinheadAI(Creature* c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + + uint32 AggroTimer; + uint32 CleaveTimer; + uint32 RustTimer; + + uint8 RustCount; + + void Reset() + { + AggroTimer = 15000; + CleaveTimer = 5000; + RustTimer = 30000; + + RustCount = 0; + } + + void Aggro(Unit* who) + { + DoYell(SAY_TINHEAD_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_TINHEAD_AGGRO); + } + + void AttackStart(Unit* who) + { + if(m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::AttackStart(who); + } + + void MoveInLineOfSight(Unit* who) + { + if(m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::MoveInLineOfSight(who); + } + + void JustDied(Unit* killer) + { + DoYell(SAY_TINHEAD_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_TINHEAD_DEATH); + + if(pInstance) + SummonCroneIfReady(pInstance, m_creature); + } + + void KilledUnit(Unit* victim) + { + DoYell(SAY_TINHEAD_SLAY, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_TINHEAD_SLAY); + } + + void UpdateAI(const uint32 diff) + { + if(AggroTimer) + if(AggroTimer < diff) + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + AggroTimer = 0; + }else AggroTimer -= diff; + + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(CleaveTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_CLEAVE); + CleaveTimer = 5000; + }else CleaveTimer -= diff; + + if(RustCount < 8) + { + if(RustTimer < diff) + { + RustCount++; + DoTextEmote("begins to rust", NULL); + DoCast(m_creature, SPELL_RUST); + RustTimer = 6000; + }else RustTimer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL boss_roarAI : public ScriptedAI +{ + boss_roarAI(Creature* c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + + uint32 AggroTimer; + uint32 MangleTimer; + uint32 ShredTimer; + uint32 ScreamTimer; + + void Reset() + { + AggroTimer = 20000; + MangleTimer = 5000; + ShredTimer = 10000; + ScreamTimer = 15000; + } + + void MoveInLineOfSight(Unit* who) + { + if(m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::MoveInLineOfSight(who); + } + + void AttackStart(Unit* who) + { + if(m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::AttackStart(who); + } + + void Aggro(Unit* who) + { + DoYell(SAY_ROAR_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_ROAR_AGGRO); + } + + void JustDied(Unit* killer) + { + DoYell(SAY_ROAR_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_ROAR_DEATH); + + if(pInstance) + SummonCroneIfReady(pInstance, m_creature); + } + + void KilledUnit(Unit* victim) + { + DoYell(SAY_ROAR_SLAY, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_ROAR_SLAY); + } + + void UpdateAI(const uint32 diff) + { + if(AggroTimer) + if(AggroTimer <= diff) + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + AggroTimer = 0; + }else AggroTimer -= diff; + + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(MangleTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_MANGLE); + MangleTimer = 5000 + rand()%3000; + }else MangleTimer -= diff; + + if(ShredTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_SHRED); + ShredTimer = 10000 + rand()%5000; + }else ShredTimer -= diff; + + if(ScreamTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_FRIGHTENED_SCREAM); + ScreamTimer = 20000 + rand()%10000; + }else ScreamTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL boss_croneAI : public ScriptedAI +{ + boss_croneAI(Creature* c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + + uint32 CycloneTimer; + uint32 ChainLightningTimer; + + void Reset() + { + CycloneTimer = 30000; + ChainLightningTimer = 10000; + } + + void Aggro(Unit* who) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_CRONE_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_CRONE_AGGRO); + break; + case 1: + DoYell(SAY_CRONE_AGGRO2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_CRONE_AGGRO2); + break; + } + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void JustDied(Unit* killer) + { + DoYell(SAY_CRONE_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_CRONE_DEATH); + + if(pInstance) + { + pInstance->SetData(DATA_OPERA_EVENT, DONE); + GameObject* Door = GameObject::GetGameObject((*m_creature), pInstance->GetData64(DATA_GAMEOBJECT_STAGEDOORRIGHT)); + if(Door) + Door->UseDoorOrButton(); + } + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if(CycloneTimer < diff) + { + Creature* Cyclone = DoSpawnCreature(CREATURE_CYCLONE, rand()%10, rand()%10, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 15000); + if(Cyclone) + Cyclone->CastSpell(Cyclone, SPELL_CYCLONE_VISUAL, true); + CycloneTimer = 30000; + }else CycloneTimer -= diff; + + if(ChainLightningTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_CHAIN_LIGHTNING); + ChainLightningTimer = 15000; + }else ChainLightningTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL mob_cycloneAI : public ScriptedAI +{ + mob_cycloneAI(Creature* c) : ScriptedAI(c) + { + Reset(); + } + + uint32 MoveTimer; + + void Reset() + { + MoveTimer = 1000; + } + + void Aggro(Unit* who) {} + + void MoveInLineOfSight(Unit* who) + { + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->HasAura(SPELL_KNOCKBACK, 0)) + DoCast(m_creature, SPELL_KNOCKBACK, true); + + if(MoveTimer < diff) + { + float x,y,z; + m_creature->GetPosition(x,y,z); + float PosX, PosY, PosZ; + m_creature->GetRandomPoint(x,y,z,10, PosX, PosY, PosZ); + m_creature->GetMotionMaster()->MovePoint(0, PosX, PosY, PosZ); + MoveTimer = 5000 + rand()%3000; + }else MoveTimer -= diff; + } +}; + +CreatureAI* GetAI_boss_dorothee(Creature* _Creature) +{ + return new boss_dorotheeAI(_Creature); +} + +CreatureAI* GetAI_boss_strawman(Creature* _Creature) +{ + return new boss_strawmanAI(_Creature); +} + +CreatureAI* GetAI_boss_tinhead(Creature* _Creature) +{ + return new boss_tinheadAI(_Creature); +} + +CreatureAI* GetAI_boss_roar(Creature* _Creature) +{ + return new boss_roarAI(_Creature); +} + +CreatureAI* GetAI_boss_crone(Creature* _Creature) +{ + return new boss_croneAI(_Creature); +} + +CreatureAI* GetAI_mob_tito(Creature* _Creature) +{ + return new mob_titoAI(_Creature); +} + +CreatureAI* GetAI_mob_cyclone(Creature* _Creature) +{ + return new mob_cycloneAI(_Creature); +} + +/**************************************/ +/**** Opera Red Riding Hood Event ****/ +/************************************/ + +#define GOSSIP_GRANDMA "What phat lewtz you have grandmother?" + +/**** Spells For The Wolf ****/ +#define SPELL_LITTLE_RED_RIDING_HOOD 30768 +#define SPELL_TERRIFYING_HOWL 30752 +#define SPELL_WIDE_SWIPE 30761 + +/**** Yells for the Wolf ****/ +#define SAY_WOLF_AGGRO "All the better to own you with!" +#define SOUND_WOLF_AGGRO 9276 +#define SOUND_WOLF_DEATH 9275 // No speech +#define SAY_WOLF_SLAY "Mmmm... delicious." +#define SOUND_WOLF_SLAY 9277 +#define SAY_WOLF_HOOD "Run away little girl, run away!" +#define SOUND_WOLF_HOOD 9278 + +/**** The Wolf's Entry ****/ +#define CREATURE_BIG_BAD_WOLF 17521 + +bool GossipHello_npc_grandmother(Player* player, Creature* _Creature) +{ + player->ADD_GOSSIP_ITEM(0, GOSSIP_GRANDMA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + player->SEND_GOSSIP_MENU(8990, _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_grandmother(Player* player, Creature* _Creature, uint32 sender, uint32 action) +{ + if(action == GOSSIP_ACTION_INFO_DEF) + { + _Creature->SetVisibility(VISIBILITY_OFF); + float x,y,z; + _Creature->GetPosition(x,y,z); + Creature* BigBadWolf = _Creature->SummonCreature(CREATURE_BIG_BAD_WOLF, x, y, z, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 30000); + if(BigBadWolf) + { + BigBadWolf->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + BigBadWolf->AI()->AttackStart(player); + } + + _Creature->setDeathState(JUST_DIED); + } + + return true; +} + +struct MANGOS_DLL_DECL boss_bigbadwolfAI : public ScriptedAI +{ + boss_bigbadwolfAI(Creature* c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + + uint32 ChaseTimer; + uint32 FearTimer; + uint32 SwipeTimer; + + uint64 HoodGUID; + float TempThreat; + + bool IsChasing; + + void Reset() + { + ChaseTimer = 30000; + FearTimer = 25000 + rand()%10000; + SwipeTimer = 5000; + + HoodGUID = 0; + TempThreat = 0; + + IsChasing = false; + } + + void Aggro(Unit* who) + { + DoYell(SAY_WOLF_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_WOLF_AGGRO); + } + + void JustDied(Unit* killer) + { + DoPlaySoundToSet(m_creature, SOUND_WOLF_DEATH); + + if(pInstance) + { + pInstance->SetData(DATA_OPERA_EVENT, DONE); + GameObject* Door = GameObject::GetGameObject((*m_creature), pInstance->GetData64(DATA_GAMEOBJECT_STAGEDOORRIGHT)); + if(Door) + Door->UseDoorOrButton(); + } + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + DoMeleeAttackIfReady(); + + if(ChaseTimer < diff) + { + if(!IsChasing) + { + Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target && target->GetTypeId() == TYPEID_PLAYER) + { + DoYell(SAY_WOLF_HOOD, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_WOLF_HOOD); + + DoCast(target, SPELL_LITTLE_RED_RIDING_HOOD, true); + TempThreat = m_creature->getThreatManager().getThreat(target); + if(TempThreat) + m_creature->getThreatManager().modifyThreatPercent(target, -100); + HoodGUID = target->GetGUID(); + m_creature->AddThreat(target, 1000000.0f); + ChaseTimer = 20000; + IsChasing = true; + } + } + else + { + IsChasing = false; + Unit* target = Unit::GetUnit((*m_creature), HoodGUID); + if(target) + { + HoodGUID = 0; + if(m_creature->getThreatManager().getThreat(target)) + m_creature->getThreatManager().modifyThreatPercent(target, -100); + m_creature->AddThreat(target, TempThreat); + TempThreat = 0; + } + + ChaseTimer = 40000; + } + }else ChaseTimer -= diff; + + if(IsChasing) + return; + + if(FearTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_TERRIFYING_HOWL); + FearTimer = 25000 + rand()%35000; + }else FearTimer -= diff; + + if(SwipeTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_WIDE_SWIPE); + SwipeTimer = 25000 + rand()%5000; + }else SwipeTimer -= diff; + + } +}; + +CreatureAI* GetAI_boss_bigbadwolf(Creature* _Creature) +{ + return new boss_bigbadwolfAI(_Creature); +} + +/**********************************************/ +/******** Opera Romeo and Juliet Event *******/ +/********************************************/ + +/***** Spells For Julianne *****/ +#define SPELL_BLINDING_PASSION 30890 +#define SPELL_DEVOTION 30887 +#define SPELL_ETERNAL_AFFECTION 30878 +#define SPELL_POWERFUL_ATTRACTION 30889 +#define SPELL_DRINK_POISON 30907 + +/***** Spells For Romulo ****/ +#define SPELL_BACKWARD_LUNGE 30815 +#define SPELL_DARING 30841 +#define SPELL_DEADLY_SWATHE 30817 +#define SPELL_POISON_THRUST 30822 + +/**** Other Misc. Spells ****/ +#define SPELL_UNDYING_LOVE 30951 +#define SPELL_RES_VISUAL 24171 + +/**** Speech and Text *****/ +/****** Julianne *******/ +#define SAY_JULIANNE_AGGRO "What devil art thou, that dost torment me thus?" +#define SOUND_JULIANNE_AGGRO 9196 +#define SAY_JULIANNE_ENTER "Where is my lord? Where is my Romulo?" +#define SOUND_JULIANNE_ENTER 9199 +#define SAY_JULIANNE_DEATH01 "Romulo, I come! Oh... this do I drink to thee!" +#define SOUND_JULIANNE_DEATH01 9198 +#define SAY_JULIANNE_DEATH02 "Where is my Lord? Where is my Romulo? Ohh, happy dagger! This is thy sheath! There rust, and let me die!" +#define SOUND_JULIANNE_DEATH02 9310 +#define SAY_JULIANNE_RESURRECT "Come, gentle night; and give me back my Romulo!" +#define SOUND_JULIANNE_RESURRECT 9200 +#define SAY_JULIANNE_SLAY "Parting is such sweet sorrow." +#define SOUND_JULIANNE_SLAY 9201 + +/****** Romulo *******/ +#define SAY_ROMULO_AGGRO "Wilt thou provoke me? Then have at thee, boy!" +#define SOUND_ROMULO_AGGRO 9233 +#define SAY_ROMULO_DEATH "Thou smilest... upon the stroke that... murders me." +#define SOUND_ROMULO_DEATH 9235 +#define SAY_ROMULO_ENTER "This day's black fate on more days doth depend. This but begins the woe. Others must end." +#define SOUND_ROMULO_ENTER 9236 +#define SAY_ROMULO_RESURRECT "Thou detestable maw, thou womb of death; I enforce thy rotten jaws to open!" +#define SOUND_ROMULO_RESURRECT 9237 +#define SAY_ROMULO_SLAY "How well my comfort is revived by this!" +#define SOUND_ROMULO_SLAY 9238 + +/*** Misc. Information ****/ +#define CREATURE_ROMULO 17533 +#define ROMULO_X -10900 +#define ROMULO_Y -1758 + +enum RAJPhase +{ + PHASE_JULIANNE = 0, + PHASE_ROMULO = 1, + PHASE_BOTH = 2, +}; + +void PretendToDie(Creature* _Creature) +{ + _Creature->InterruptNonMeleeSpells(false); + _Creature->SetHealth(0); + _Creature->StopMoving(); + _Creature->ClearComboPointHolders(); + _Creature->RemoveAllAurasOnDeath(); + _Creature->ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false); + _Creature->ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false); + _Creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + _Creature->ClearAllReactives(); + _Creature->SetUInt64Value(UNIT_FIELD_TARGET,0); + _Creature->GetMotionMaster()->Clear(); + _Creature->GetMotionMaster()->MoveIdle(); + _Creature->SetUInt32Value(UNIT_FIELD_BYTES_1,PLAYER_STATE_DEAD); +}; + +void Resurrect(Creature* target) +{ + target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + target->SetHealth(target->GetMaxHealth()); + target->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + target->CastSpell(target, SPELL_RES_VISUAL, true); + if(target->getVictim()) + { + target->SetUInt64Value(UNIT_FIELD_TARGET, target->getVictim()->GetGUID()); + target->GetMotionMaster()->MoveChase(target->getVictim()); + target->AI()->AttackStart(target->getVictim()); + } +}; + +struct MANGOS_DLL_DECL boss_julianneAI : public ScriptedAI +{ + boss_julianneAI(Creature* c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + EntryYellTimer = 1000; + AggroYellTimer = 10000; + Reset(); + } + + ScriptedInstance* pInstance; + + uint64 RomuloGUID; + + uint32 Phase; + + uint32 EntryYellTimer; + uint32 AggroYellTimer; + uint32 BlindingPassionTimer; + uint32 DevotionTimer; + uint32 EternalAffectionTimer; + uint32 PowerfulAttractionTimer; + uint32 SummonRomuloTimer; + uint32 ResurrectTimer; + + bool IsFakingDeath; + bool SummonedRomulo; + bool RomuloDead; + + void Reset() + { + if(RomuloGUID) + { + if(Unit* Romulo = Unit::GetUnit(*m_creature, RomuloGUID)) + { + Romulo->SetVisibility(VISIBILITY_OFF); + Romulo->DealDamage(Romulo, Romulo->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + RomuloGUID = 0; + } + + Phase = PHASE_JULIANNE; + + BlindingPassionTimer = 30000; + DevotionTimer = 15000; + EternalAffectionTimer = 25000; + PowerfulAttractionTimer = 5000; + + if(IsFakingDeath) + Resurrect(m_creature); + + IsFakingDeath = false; + SummonedRomulo = false; + RomuloDead = false; + } + + void Aggro(Unit* who) {} + + void AttackStart(Unit* who) + { + if(m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::AttackStart(who); + } + + void MoveInLineOfSight(Unit* who) + { + if(m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::MoveInLineOfSight(who); + } + + void DamageTaken(Unit* done_by, uint32 &damage); + + void JustDied(Unit* killer) + { + DoYell(SAY_JULIANNE_DEATH02, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_JULIANNE_DEATH02); + + if(pInstance) + { + pInstance->SetData(DATA_OPERA_EVENT, DONE); + GameObject* Door = GameObject::GetGameObject((*m_creature), pInstance->GetData64(DATA_GAMEOBJECT_STAGEDOORRIGHT)); + if(Door) + Door->UseDoorOrButton(); + } + } + + void KilledUnit(Unit* victim) + { + DoYell(SAY_JULIANNE_SLAY, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_JULIANNE_SLAY); + } + + void UpdateAI(const uint32 diff); +}; + +struct MANGOS_DLL_DECL boss_romuloAI : public ScriptedAI +{ + boss_romuloAI(Creature* c) : ScriptedAI(c) + { + Reset(); + EntryYellTimer = 8000; + AggroYellTimer = 15000; + } + + uint64 JulianneGUID; + + uint32 Phase; + + uint32 EntryYellTimer; + uint32 AggroYellTimer; + uint32 BackwardLungeTimer; + uint32 DaringTimer; + uint32 DeadlySwatheTimer; + uint32 PoisonThrustTimer; + uint32 ResurrectTimer; + + bool JulianneDead; + bool IsFakingDeath; + + void Reset() + { + JulianneGUID = 0; + + Phase = PHASE_ROMULO; + + BackwardLungeTimer = 15000; + DaringTimer = 20000; + DeadlySwatheTimer = 25000; + PoisonThrustTimer = 10000; + + if(IsFakingDeath) + Resurrect(m_creature); + + IsFakingDeath = false; + JulianneDead = false; + } + + void DamageTaken(Unit* done_by, uint32 &damage); + + void Aggro(Unit* who) + { + DoYell(SAY_ROMULO_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_ROMULO_AGGRO); + if(JulianneGUID) + { + Creature* Julianne = ((Creature*)Unit::GetUnit((*m_creature), JulianneGUID)); + if(Julianne && Julianne->getVictim()) + { + m_creature->AddThreat(Julianne->getVictim(), 1.0f); + DoStartAttackAndMovement(Julianne->getVictim()); + } + } + } + + void MoveInLineOfSight(Unit* who) + { + if(m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::MoveInLineOfSight(who); + } + + void JustDied(Unit* killer) + { + DoYell(SAY_ROMULO_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_ROMULO_DEATH); + } + + void KilledUnit(Unit* victim) + { + DoYell(SAY_ROMULO_SLAY, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_ROMULO_SLAY); + } + + void UpdateAI(const uint32 diff); +}; + +void boss_julianneAI::DamageTaken(Unit* done_by, uint32 &damage) +{ + if(damage < m_creature->GetHealth() || done_by == m_creature || done_by->GetGUID() == RomuloGUID) + return; + + if(Phase == PHASE_JULIANNE) + { + DoYell(SAY_JULIANNE_DEATH01, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_JULIANNE_DEATH01); + m_creature->InterruptNonMeleeSpells(true); + DoCast(m_creature, SPELL_DRINK_POISON); + PretendToDie(m_creature); + Phase = PHASE_ROMULO; + damage = 0; + IsFakingDeath = true; + SummonRomuloTimer = 10000; + return; + } + + if(!IsFakingDeath) + { + Creature* Romulo = ((Creature*)Unit::GetUnit((*m_creature), RomuloGUID)); + if(Romulo && Romulo->isAlive() && !((boss_romuloAI*)Romulo->AI())->IsFakingDeath) + { + ((boss_romuloAI*)Romulo->AI())->ResurrectTimer = 10000; + ((boss_romuloAI*)Romulo->AI())->JulianneDead = true; + } + else + { + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + if(Romulo) + { + Romulo->DealDamage(Romulo, Romulo->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + Romulo->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + JustDied(done_by); + } + + IsFakingDeath = true; + PretendToDie(m_creature); + damage = 0; + } + else + damage = 0; +} + +void boss_romuloAI::DamageTaken(Unit* done_by, uint32 &damage) +{ + if(damage < m_creature->GetHealth() || done_by == m_creature || done_by->GetGUID() == JulianneGUID) + return; + + if(!IsFakingDeath) + { + IsFakingDeath = true; + PretendToDie(m_creature); + + if(Phase == PHASE_BOTH) + { + Creature* Julianne = ((Creature*)Unit::GetUnit((*m_creature), JulianneGUID)); + if(Julianne && Julianne->isAlive() && !((boss_julianneAI*)Julianne->AI())->IsFakingDeath) + { + ((boss_julianneAI*)Julianne->AI())->ResurrectTimer = 10000; + ((boss_julianneAI*)Julianne->AI())->RomuloDead = true; + } + else + { + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + if(Julianne) + { + Julianne->DealDamage(Julianne, Julianne->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + Julianne->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + JustDied(done_by); + } + } + else + { + Creature* Julianne = ((Creature*)Unit::GetUnit((*m_creature), JulianneGUID)); + if(Julianne) + { + Resurrect(Julianne); + m_creature->SetHealth(m_creature->GetMaxHealth()); + ((boss_julianneAI*)Julianne->AI())->ResurrectTimer = 4000; + ((boss_julianneAI*)Julianne->AI())->RomuloDead = true; + ((boss_julianneAI*)Julianne->AI())->Phase = PHASE_BOTH; + ((boss_julianneAI*)Julianne->AI())->IsFakingDeath = false; + } + Phase = PHASE_BOTH; + } + + damage = 0; + } + + if(IsFakingDeath) damage = 0; +} + +void boss_julianneAI::UpdateAI(const uint32 diff) +{ + if(EntryYellTimer) + if(EntryYellTimer < diff) + { + DoYell(SAY_JULIANNE_ENTER, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_JULIANNE_ENTER); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + EntryYellTimer = 0; + }else EntryYellTimer -= diff; + + if(AggroYellTimer) + if(AggroYellTimer < diff) + { + DoYell(SAY_JULIANNE_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_JULIANNE_AGGRO); + AggroYellTimer = 0; + }else AggroYellTimer -= diff; + + if(Phase == PHASE_ROMULO && !SummonedRomulo) + { + if(SummonRomuloTimer < diff) + { + Creature* Romulo = m_creature->SummonCreature(CREATURE_ROMULO, ROMULO_X, ROMULO_Y, m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 45000); + if(Romulo) + { + RomuloGUID = Romulo->GetGUID(); + ((boss_romuloAI*)Romulo->AI())->JulianneGUID = m_creature->GetGUID(); + ((boss_romuloAI*)Romulo->AI())->Phase = PHASE_ROMULO; + if(m_creature->getVictim()) + { + Romulo->AI()->AttackStart(m_creature->getVictim()); + Romulo->AddThreat(m_creature->getVictim(), 50.0f); + } + DoZoneInCombat(Romulo); + } + SummonedRomulo = true; + }else SummonRomuloTimer -= diff; + } + + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim() ||IsFakingDeath) + return; + + if(RomuloDead) + if(ResurrectTimer < diff) + { + Creature* Romulo = ((Creature*)Unit::GetUnit((*m_creature), RomuloGUID)); + if(Romulo && ((boss_romuloAI*)Romulo->AI())->IsFakingDeath) + { + DoYell(SAY_JULIANNE_RESURRECT, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_JULIANNE_RESURRECT); + Resurrect(Romulo); + ((boss_romuloAI*)Romulo->AI())->IsFakingDeath = false; + ResurrectTimer = 10000; + } + RomuloDead = false; + }else ResurrectTimer -= diff; + + if(BlindingPassionTimer < diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_BLINDING_PASSION); + BlindingPassionTimer = 30000 + rand()%15000; + }else BlindingPassionTimer -= diff; + + if(DevotionTimer < diff) + { + DoCast(m_creature, SPELL_DEVOTION); + DevotionTimer = 15000 + rand()%30000; + }else DevotionTimer -= diff; + + if(PowerfulAttractionTimer < diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_POWERFUL_ATTRACTION); + PowerfulAttractionTimer = 5000 + rand()%25000; + }else PowerfulAttractionTimer -= diff; + + if(EternalAffectionTimer < diff) + { + if(rand()%2 == 1 && SummonedRomulo) + { + Creature* Romulo = ((Creature*)Unit::GetUnit((*m_creature), RomuloGUID)); + if(Romulo && Romulo->isAlive() && !((boss_romuloAI*)Romulo->AI())->IsFakingDeath) + DoCast(Romulo, SPELL_ETERNAL_AFFECTION); + else + return; + } + else DoCast(m_creature, SPELL_ETERNAL_AFFECTION); + + EternalAffectionTimer = 45000 + rand()%15000; + }else EternalAffectionTimer -= diff; + + DoMeleeAttackIfReady(); +} + +void boss_romuloAI::UpdateAI(const uint32 diff) +{ + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim() || IsFakingDeath) + return; + + if(JulianneDead) + if(ResurrectTimer < diff) + { + Creature* Julianne = ((Creature*)Unit::GetUnit((*m_creature), JulianneGUID)); + if(Julianne && ((boss_julianneAI*)Julianne->AI())->IsFakingDeath) + { + DoYell(SAY_ROMULO_RESURRECT, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_ROMULO_RESURRECT); + Resurrect(Julianne); + ((boss_julianneAI*)Julianne->AI())->IsFakingDeath = false; + ResurrectTimer = 10000; + } + JulianneDead = false; + }else ResurrectTimer -= diff; + + if(BackwardLungeTimer < diff) + { + Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1); + if(target && !m_creature->HasInArc(M_PI, target)) + { + DoCast(target, SPELL_BACKWARD_LUNGE); + BackwardLungeTimer = 15000 + rand()%15000; + } + }else BackwardLungeTimer -= diff; + + if(DaringTimer < diff) + { + DoCast(m_creature, SPELL_DARING); + DaringTimer = 20000 + rand()%20000; + }else DaringTimer -= diff; + + if(DeadlySwatheTimer < diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_DEADLY_SWATHE); + DeadlySwatheTimer = 15000 + rand()%10000; + }else DeadlySwatheTimer -= diff; + + if(PoisonThrustTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_POISON_THRUST); + PoisonThrustTimer = 10000 + rand()%10000; + }else PoisonThrustTimer -= diff; + + DoMeleeAttackIfReady(); +} + +CreatureAI* GetAI_boss_julianne(Creature* _Creature) +{ + return new boss_julianneAI(_Creature); +} + +CreatureAI* GetAI_boss_romulo(Creature* _Creature) +{ + return new boss_romuloAI(_Creature); +} + +void AddSC_bosses_opera() +{ + Script* newscript; + + // Oz + newscript = new Script; + newscript->GetAI = GetAI_boss_dorothee; + newscript->Name = "boss_dorothee"; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->GetAI = GetAI_boss_strawman; + newscript->Name = "boss_strawman"; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->GetAI = GetAI_boss_tinhead; + newscript->Name = "boss_tinhead"; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->GetAI = GetAI_boss_roar; + newscript->Name = "boss_roar"; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->GetAI = GetAI_boss_crone; + newscript->Name = "boss_crone"; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->GetAI = GetAI_mob_tito; + newscript->Name = "mob_tito"; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->GetAI = GetAI_mob_cyclone; + newscript->Name = "mob_cyclone"; + m_scripts[nrscripts++] = newscript; + + // Hood + newscript = new Script; + newscript->pGossipHello = GossipHello_npc_grandmother; + newscript->pGossipSelect = GossipSelect_npc_grandmother; + newscript->Name = "npc_grandmother"; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->GetAI = GetAI_boss_bigbadwolf; + newscript->Name = "boss_bigbadwolf"; + m_scripts[nrscripts++] = newscript; + + // Romeo And Juliet + newscript = new Script; + newscript->GetAI = GetAI_boss_julianne; + newscript->Name = "boss_julianne"; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->GetAI = GetAI_boss_romulo; + newscript->Name = "boss_romulo"; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/karazhan/def_karazhan.h b/src/bindings/scripts/scripts/zone/karazhan/def_karazhan.h new file mode 100644 index 00000000000..938c0131b9c --- /dev/null +++ b/src/bindings/scripts/scripts/zone/karazhan/def_karazhan.h @@ -0,0 +1,40 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_KARAZHAN_H +#define DEF_KARAZHAN_H + +#define DATA_ATTUMEN_EVENT 1 +#define DATA_MOROES_EVENT 2 +#define DATA_MAIDENOFVIRTUE_EVENT 3 +#define DATA_OPTIONAL_BOSS_EVENT 4 +#define DATA_OPERA_EVENT 5 +#define DATA_CURATOR_EVENT 6 +#define DATA_SHADEOFARAN_EVENT 7 +#define DATA_TERESTIAN_EVENT 8 +#define DATA_NETHERSPITE_EVENT 9 +#define DATA_CHESS_EVENT 10 +#define DATA_MALCHEZZAR_EVENT 11 +#define DATA_NETHERBANE_EVENT 12 +#define DATA_OPERA_PERFORMANCE 13 +#define DATA_OPERA_OZ_DEATHCOUNT 14 +#define DATA_KILREK 15 +#define DATA_TERESTIAN 16 +#define DATA_MOROES 17 +#define DATA_GAMEOBJECT_CURTAINS 18 +#define DATA_GAMEOBJECT_STAGEDOORLEFT 19 +#define DATA_GAMEOBJECT_STAGEDOORRIGHT 20 +#define DATA_GAMEOBJECT_LIBRARY_DOOR 21 +#define DATA_GAMEOBJECT_MASSIVE_DOOR 22 +#define DATA_GAMEOBJECT_NETHER_DOOR 23 +#define DATA_GAMEOBJECT_GAME_DOOR 24 +#define DATA_GAMEOBJECT_GAME_EXIT_DOOR 25 + +// Opera Performances +#define EVENT_OZ 1 +#define EVENT_HOOD 2 +#define EVENT_RAJ 3 + +#define ERROR_INST_DATA(a) error_log("SD2: Instance Data for Karazhan not set properly. Encounter for Creature Entry %u may not work properly.", a->GetEntry()); +#endif diff --git a/src/bindings/scripts/scripts/zone/karazhan/instance_karazhan.cpp b/src/bindings/scripts/scripts/zone/karazhan/instance_karazhan.cpp new file mode 100644 index 00000000000..f7b2be1978f --- /dev/null +++ b/src/bindings/scripts/scripts/zone/karazhan/instance_karazhan.cpp @@ -0,0 +1,253 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Karazhan +SD%Complete: 70 +SDComment: Instance Script for Karazhan to help in various encounters. TODO: GameObject visibility for Opera event. +SDCategory: Karazhan +EndScriptData */ + +#include "precompiled.h" +#include "def_karazhan.h" + +#define ENCOUNTERS 11 + +/* +0 - Attumen + Midnight (optional) +1 - Moroes +2 - Maiden of Virtue (optional) +3 - Hyakiss the Lurker / Rokad the Ravager / Shadikith the Glider +4 - Opera Event +5 - Curator +6 - Shade of Aran (optional) +7 - Terestian Illhoof (optional) +8 - Netherspite (optional) +9 - Chess Event +10 - Prince Malchezzar +11 - Netherbane +*/ +struct MANGOS_DLL_DECL instance_karazhan : public ScriptedInstance +{ + instance_karazhan(Map* map) : ScriptedInstance(map) + { + Initialize(); + } + + uint32 Encounters[ENCOUNTERS]; + + uint32 OperaEvent; // 0 - OZ, 1 - HOOD, 2 - RAJ + uint32 OzDeathCount; + + uint64 CurtainGUID; + uint64 StageDoorLeftGUID; + uint64 StageDoorRightGUID; + uint64 KilrekGUID; + uint64 TerestianGUID; + uint64 MoroesGUID; + uint64 LibraryDoor; // Door at Shade of Aran + uint64 MassiveDoor; // Door at Netherspite + uint64 GamesmansDoor; // Door before Chess + uint64 GamesmansExitDoor; // Door after Chess + uint64 NetherspaceDoor; // Door at Malchezaar + + void Initialize() + { + for (uint8 i = 0; i < ENCOUNTERS; ++i) + Encounters[i] = NOT_STARTED; + + OperaEvent = rand()%3; // This never gets altered. + OzDeathCount = 0; + + CurtainGUID = 0; + StageDoorLeftGUID = 0; + StageDoorRightGUID = 0; + + KilrekGUID = 0; + TerestianGUID = 0; + MoroesGUID = 0; + + LibraryDoor = 0; + MassiveDoor = 0; + GamesmansDoor = 0; + GamesmansExitDoor = 0; + NetherspaceDoor = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < ENCOUNTERS; ++i) + if (Encounters[i] == IN_PROGRESS) return true; + + return false; + } + + uint32 GetData(uint32 identifier) + { + switch (identifier) + { + case DATA_ATTUMEN_EVENT: return Encounters[0]; + case DATA_MOROES_EVENT: return Encounters[1]; + case DATA_MAIDENOFVIRTUE_EVENT: return Encounters[2]; + case DATA_OPTIONAL_BOSS_EVENT: return Encounters[3]; + case DATA_OPERA_EVENT: return Encounters[4]; + case DATA_CURATOR_EVENT: return Encounters[5]; + case DATA_SHADEOFARAN_EVENT: return Encounters[6]; + case DATA_TERESTIAN_EVENT: return Encounters[7]; + case DATA_NETHERSPITE_EVENT: return Encounters[8]; + case DATA_CHESS_EVENT: return Encounters[9]; + case DATA_MALCHEZZAR_EVENT: return Encounters[10]; + case DATA_NETHERBANE_EVENT: return Encounters[11]; + case DATA_OPERA_PERFORMANCE: return OperaEvent; + case DATA_OPERA_OZ_DEATHCOUNT: return OzDeathCount; + } + + return 0; + } + + void OnCreatureCreate(Creature *creature, uint32 entry) + { + switch (entry) + { + case 17229: KilrekGUID = creature->GetGUID(); break; + case 15688: TerestianGUID = creature->GetGUID(); break; + case 15687: MoroesGUID = creature->GetGUID(); break; + } + } + + uint64 GetData64(uint32 identifier) + { + switch (identifier) + { + case DATA_KILREK: return KilrekGUID; + case DATA_TERESTIAN: return TerestianGUID; + case DATA_MOROES: return MoroesGUID; + case DATA_GAMEOBJECT_STAGEDOORLEFT: return StageDoorLeftGUID; + case DATA_GAMEOBJECT_STAGEDOORRIGHT: return StageDoorRightGUID; + case DATA_GAMEOBJECT_CURTAINS: return CurtainGUID; + case DATA_GAMEOBJECT_LIBRARY_DOOR: return LibraryDoor; + case DATA_GAMEOBJECT_MASSIVE_DOOR: return MassiveDoor; + case DATA_GAMEOBJECT_GAME_DOOR: return GamesmansDoor; + case DATA_GAMEOBJECT_GAME_EXIT_DOOR: return GamesmansExitDoor; + case DATA_GAMEOBJECT_NETHER_DOOR: return NetherspaceDoor; + } + + return 0; + } + + void SetData(uint32 identifier, uint32 data) + { + switch (identifier) + { + case DATA_ATTUMEN_EVENT: Encounters[0] = data; break; + case DATA_MOROES_EVENT: Encounters[1] = data; break; + case DATA_MAIDENOFVIRTUE_EVENT: Encounters[2] = data; break; + case DATA_OPTIONAL_BOSS_EVENT: Encounters[3] = data; break; + case DATA_OPERA_EVENT: Encounters[4] = data; break; + case DATA_CURATOR_EVENT: Encounters[5] = data; break; + case DATA_SHADEOFARAN_EVENT: Encounters[6] = data; break; + case DATA_TERESTIAN_EVENT: Encounters[7] = data; break; + case DATA_NETHERSPITE_EVENT: Encounters[8] = data; break; + case DATA_CHESS_EVENT: Encounters[9] = data; break; + case DATA_MALCHEZZAR_EVENT: Encounters[10] = data; break; + case DATA_NETHERBANE_EVENT: Encounters[11] = data; break; + + case DATA_OPERA_OZ_DEATHCOUNT: ++OzDeathCount; break; + } + + if(data == DONE) + SaveToDB(); + } + + void OnObjectCreate(GameObject* go) + { + switch(go->GetEntry()) + { + case 183932: CurtainGUID = go->GetGUID(); break; + case 184278: StageDoorLeftGUID = go->GetGUID(); break; + case 184279: StageDoorRightGUID = go->GetGUID(); break; + case 184517: LibraryDoor = go->GetGUID(); break; + case 185521: MassiveDoor = go->GetGUID(); break; + case 184276: GamesmansDoor = go->GetGUID(); break; + case 184277: GamesmansExitDoor = go->GetGUID(); break; + case 185134: NetherspaceDoor = go->GetGUID(); break; + } + + switch(OperaEvent) + { + //TODO: Set Object visibilities for Opera based on performance + case EVENT_OZ: + break; + + case EVENT_HOOD: + break; + + case EVENT_RAJ: + break; + } + } + + const char* Save() + { + OUT_SAVE_INST_DATA; + std::ostringstream stream; + stream << Encounters[0] << " " << Encounters[1] << " " << Encounters[2] << " " << Encounters[3] << " " + << Encounters[4] << " " << Encounters[5] << " " << Encounters[6] << " " << Encounters[7] << " " + << Encounters[8] << " " << Encounters[9] << " " << Encounters[10]; + char* out = new char[stream.str().length() + 1]; + strcpy(out, stream.str().c_str()); + if(out) + { + OUT_SAVE_INST_DATA_COMPLETE; + return out; + } + + return NULL; + } + + void Load(const char* in) + { + if(!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + std::istringstream stream(in); + stream >> Encounters[0] >> Encounters[1] >> Encounters[2] >> Encounters[3] + >> Encounters[4] >> Encounters[5] >> Encounters[6] >> Encounters[7] + >> Encounters[8] >> Encounters[9] >> Encounters[10]; + for(uint8 i = 0; i < ENCOUNTERS; ++i) + if(Encounters[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead. + Encounters[i] = NOT_STARTED; + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_karazhan(Map* map) +{ + return new instance_karazhan(map); +} + +void AddSC_instance_karazhan() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_karazhan"; + newscript->GetInstanceData = GetInstanceData_instance_karazhan; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/karazhan/karazhan.cpp b/src/bindings/scripts/scripts/zone/karazhan/karazhan.cpp new file mode 100644 index 00000000000..b12c3280f58 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/karazhan/karazhan.cpp @@ -0,0 +1,470 @@ +/* Copyright (C) 2006,2007 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Karazhan +SD%Complete: 100 +SDComment: Support for Barnes (Opera controller) and Berthold (Doorman). +SDCategory: Karazhan +EndScriptData */ + +/* ContentData +npc_barnes +npc_berthold +EndContentData */ + +#include "precompiled.h" +#include "def_karazhan.h" +#include "../../npc/npc_escortAI.h" + +/*###### +# npc_barnesAI +######*/ + +#define GOSSIP_READY "I'm not an actor." + +#define SAY_READY "Splendid, I'm going to get the audience ready. Break a leg!" +#define SAY_OZ_INTRO1 "Finally, everything is in place. Are you ready for your big stage debut?" +#define OZ_GOSSIP1 "I'm not an actor." +#define SAY_OZ_INTRO2 "Don't worry, you'll be fine. You look like a natural!" +#define OZ_GOSSIP2 "Ok, I'll give it a try, then." + +#define SAY_RAJ_INTRO1 "The romantic plays are really tough, but you'll do better this time. You have TALENT. Ready?" +#define RAJ_GOSSIP1 "I've never been more ready." + +struct Dialogue +{ + char* text; + uint32 soundid, timer; +}; + +static Dialogue OzDialogue[]= +{ + {"Welcome Ladies and Gentlemen, to this evening's presentation!", 9174, 6000}, + {"Tonight we plumb the depths of the human soul as we join a lost, lonely girl trying desperately -- with the help of her loyal companions -- to find her way home!", 9338, 18000}, + {"But she is pursued... by a wicked malevolent crone!", 9339, 9000}, + {"Will she survive? Will she prevail? Only time will tell. And now ... on with the show!", 9340, 15000} +}; + +static Dialogue HoodDialogue[]= +{ + {"Good evening, Ladies and Gentlemen! Welcome to this evening's presentation!", 9175, 6000}, + {"Tonight, things are not what they seem. For tonight, your eyes may not be trusted", 9335, 10000}, + {"Take for instance, this quiet, elderly woman, waiting for a visit from her granddaughter. Surely there is nothing to fear from this sweet, grey-haired, old lady.", 9336, 14000}, + {"But don't let me pull the wool over your eyes. See for yourself what lies beneath those covers! And now... on with the show!", 9337, 15000} +}; + +static Dialogue RAJDialogue[]= +{ + {"Welcome, Ladies and Gentlemen, to this evening's presentation!", 9176, 5000}, + {"Tonight, we explore a tale of forbidden love!", 9341, 7000}, + {"But beware, for not all love stories end happily, as you may find out. Sometimes, love pricks like a thorn.", 9342, 14000}, + {"But don't take it from me, see for yourself what tragedy lies ahead when the paths of star-crossed lovers meet. And now...on with the show!", 9343, 14000} +}; + +// Entries and spawn locations for creatures in Oz event +float Spawns[6][2]= +{ + {17535, -10896}, // Dorothee + {17546, -10891}, // Roar + {17547, -10884}, // Tinhead + {17543, -10902}, // Strawman + {17603, -10892}, // Grandmother + {17534, -10900}, // Julianne +}; + +float StageLocations[6][2]= +{ + {-10866.711, -1779.816}, // Open door, begin walking (0) + {-10894.917, -1775.467}, // (1) + {-10896.044, -1782.619}, // Begin Speech after this (2) + {-10894.917, -1775.467}, // Resume walking (back to spawn point now) after speech (3) + {-10866.711, -1779.816}, // (4) + {-10866.700, -1781.030} // Summon mobs, open curtains, close door (5) +}; + +#define CREATURE_SPOTLIGHT 19525 + +#define SPELL_SPOTLIGHT 25824 +#define SPELL_TUXEDO 32616 + +#define SPAWN_Z 90.5 +#define SPAWN_Y -1758 +#define SPAWN_O 4.738 + +struct MANGOS_DLL_DECL npc_barnesAI : public npc_escortAI +{ + npc_barnesAI(Creature* c) : npc_escortAI(c) + { + RaidWiped = false; + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + + uint64 SpotlightGUID; + + uint32 TalkCount; + uint32 TalkTimer; + uint32 CurtainTimer; + uint32 WipeTimer; + uint32 Event; + + bool PerformanceReady; + bool RaidWiped; + bool IsTalking; + + void Reset() + { + TalkCount = 0; + TalkTimer = 2000; + CurtainTimer = 5000; + WipeTimer = 5000; + + PerformanceReady = false; + IsTalking = false; + + if(pInstance) + { + pInstance->SetData(DATA_OPERA_EVENT, NOT_STARTED); + + Event = pInstance->GetData(DATA_OPERA_PERFORMANCE); + + GameObject* Door = GameObject::GetGameObject((*m_creature), pInstance->GetData64(DATA_GAMEOBJECT_STAGEDOORLEFT)); + if(Door) + Door->SetGoState(1); + + GameObject* Curtain = GameObject::GetGameObject((*m_creature), pInstance->GetData64(DATA_GAMEOBJECT_CURTAINS)); + if(Curtain) + Curtain->SetGoState(1); + } + } + + void Aggro(Unit* who) {} + + void WaypointReached(uint32 i) + { + switch(i) + { + case 2: + IsBeingEscorted = false; + TalkCount = 0; + IsTalking = true; + + float x,y,z; + m_creature->GetPosition(x, y, z); + Creature* Spotlight; + Spotlight = m_creature->SummonCreature(CREATURE_SPOTLIGHT, x, y, z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 50000); + if(Spotlight) + { + Spotlight->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Spotlight->CastSpell(Spotlight, SPELL_SPOTLIGHT, false); + SpotlightGUID = Spotlight->GetGUID(); + } + break; + + case 5: + if(pInstance) + { + GameObject* Door = GameObject::GetGameObject((*m_creature), pInstance->GetData64(DATA_GAMEOBJECT_STAGEDOORLEFT)); + if(Door) + Door->SetGoState(1); + } + IsBeingEscorted = false; + PerformanceReady = true; + break; + } + } + + void Talk(uint32 count) + { + char* text = NULL; + uint32 sound = 0; + + switch(Event) + { + case EVENT_OZ: + if(OzDialogue[count].text) + text = OzDialogue[count].text; + if(OzDialogue[count].soundid) + sound = OzDialogue[count].soundid; + if(OzDialogue[count].timer) + TalkTimer = OzDialogue[count].timer; + break; + + case EVENT_HOOD: + if(HoodDialogue[count].text) + text = HoodDialogue[count].text; + if(HoodDialogue[count].soundid) + sound = HoodDialogue[count].soundid; + if(HoodDialogue[count].timer) + TalkTimer = HoodDialogue[count].timer; + break; + + case EVENT_RAJ: + if(RAJDialogue[count].text) + text = RAJDialogue[count].text; + if(RAJDialogue[count].soundid) + sound = RAJDialogue[count].soundid; + if(RAJDialogue[count].timer) + TalkTimer = RAJDialogue[count].timer; + break; + } + + if(text) + DoYell(text, LANG_UNIVERSAL, 0); + if(sound) + DoPlaySoundToSet(m_creature, sound); + } + + void UpdateAI(const uint32 diff) + { + npc_escortAI::UpdateAI(diff); + + if(IsTalking) + { + if(TalkTimer < diff) + { + if(TalkCount > 3) + { + Unit* Spotlight = Unit::GetUnit((*m_creature), SpotlightGUID); + if(Spotlight) + { + Spotlight->RemoveAllAuras(); + Spotlight->SetVisibility(VISIBILITY_OFF); + } + + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_STAND); + IsTalking = false; + IsBeingEscorted = true; + return; + } + + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_TALK); + Talk(TalkCount); + ++TalkCount; + } + else TalkTimer -= diff; + } + + if(PerformanceReady) + { + if(CurtainTimer) + if(CurtainTimer <= diff) + { + PrepareEncounter(); + + if(!pInstance) + return; + + GameObject* Curtain = GameObject::GetGameObject((*m_creature), pInstance->GetData64(DATA_GAMEOBJECT_CURTAINS)); + if(Curtain) + Curtain->SetGoState(0); + + CurtainTimer = 0; + }else CurtainTimer -= diff; + + if(!RaidWiped) + { + if(WipeTimer < diff) + { + Map *map = m_creature->GetMap(); + if(!map->IsDungeon()) return; + + InstanceMap::PlayerList const &PlayerList = ((InstanceMap*)map)->GetPlayers(); + if(PlayerList.empty()) + return; + + RaidWiped = true; + for(InstanceMap::PlayerList::const_iterator i = PlayerList.begin();i != PlayerList.end(); ++i) + { + if((*i)->isAlive() && !(*i)->isGameMaster()) + { + RaidWiped = false; + break; + } + } + + if(RaidWiped) + { + RaidWiped = true; + EnterEvadeMode(); + } + + WipeTimer = 15000; + }else WipeTimer -= diff; + } + + } + + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + DoMeleeAttackIfReady(); + } + + void StartEvent() + { + if(!pInstance) + return; + + pInstance->SetData(DATA_OPERA_EVENT, IN_PROGRESS); + + GameObject* Door = GameObject::GetGameObject((*m_creature), pInstance->GetData64(DATA_GAMEOBJECT_STAGEDOORLEFT)); + if(Door) + Door->SetGoState(0); + + m_creature->CastSpell(m_creature, SPELL_TUXEDO, true); + m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + + Start(false, false, false); + } + + void PrepareEncounter() + { + debug_log("SD2: Barnes Opera Event - Introduction complete - preparing encounter %d", Event); + uint8 index = 0; + uint8 count = 0; + switch(Event) + { + case EVENT_OZ: + index = 0; + count = 4; + break; + + case EVENT_HOOD: + index = 4; + count = index+1; + break; + + case EVENT_RAJ: + index = 5; + count = index+1; + break; + } + + for( ; index < count; ++index) + { + uint32 entry = ((uint32)Spawns[index][0]); + float PosX = Spawns[index][1]; + Creature* pCreature = m_creature->SummonCreature(entry, PosX, SPAWN_Y, SPAWN_Z, SPAWN_O, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); + if(pCreature) + { + // In case database has bad flags + pCreature->SetUInt32Value(UNIT_FIELD_FLAGS, 0); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + } + + CurtainTimer = 10000; + PerformanceReady = true; + RaidWiped = false; + } +}; + +CreatureAI* GetAI_npc_barnesAI(Creature* _Creature) +{ + npc_barnesAI* Barnes_AI = new npc_barnesAI(_Creature); + + for(uint8 i = 0; i < 6; ++i) + Barnes_AI->AddWaypoint(i, StageLocations[i][0], StageLocations[i][1], 90.465); + + return ((CreatureAI*)Barnes_AI); +} + +bool GossipHello_npc_barnes(Player* player, Creature* _Creature) +{ + // Check for death of Moroes. + ScriptedInstance* pInstance = ((ScriptedInstance*)_Creature->GetInstanceData()); + if(pInstance && (pInstance->GetData(DATA_MOROES_EVENT) >= DONE)) + { + player->ADD_GOSSIP_ITEM(0, OZ_GOSSIP1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + + if(!((npc_barnesAI*)_Creature->AI())->RaidWiped) + player->SEND_GOSSIP_MENU(8970, _Creature->GetGUID()); + else + player->SEND_GOSSIP_MENU(8975, _Creature->GetGUID()); + } + else + player->SEND_GOSSIP_MENU(8978, _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_barnes(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + switch(action) + { + case GOSSIP_ACTION_INFO_DEF+1: + player->ADD_GOSSIP_ITEM(0, OZ_GOSSIP2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + player->SEND_GOSSIP_MENU(8971, _Creature->GetGUID()); + break; + + case GOSSIP_ACTION_INFO_DEF+2: + player->CLOSE_GOSSIP_MENU(); + ((npc_barnesAI*)_Creature->AI())->StartEvent(); + break; + } + + return true; +} + +/*### +# npc_berthold +####*/ + +#define SPELL_TELEPORT 39567 + +#define GOSSIP_ITEM_TELEPORT "Teleport me to the Guardian's Library" + +bool GossipHello_npc_berthold(Player* player, Creature* _Creature) +{ + ScriptedInstance* pInstance = ((ScriptedInstance*)_Creature->GetInstanceData()); + // Check if Shade of Aran is dead or not + if(pInstance && (pInstance->GetData(DATA_SHADEOFARAN_EVENT) >= DONE)) + player->ADD_GOSSIP_ITEM(0, GOSSIP_ITEM_TELEPORT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + return true; +} + +bool GossipSelect_npc_berthold(Player* player, Creature* _Creature, uint32 sender, uint32 action) +{ + if(action == GOSSIP_ACTION_INFO_DEF + 1) + player->CastSpell(player, SPELL_TELEPORT, true); + + player->CLOSE_GOSSIP_MENU(); + return true; +} + +void AddSC_karazhan() +{ + Script* newscript; + + newscript = new Script; + newscript->GetAI = GetAI_npc_barnesAI; + newscript->Name = "npc_barnes"; + newscript->pGossipHello = GossipHello_npc_barnes; + newscript->pGossipSelect = GossipSelect_npc_barnes; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name = "npc_berthold"; + newscript->pGossipHello = GossipHello_npc_berthold; + newscript->pGossipSelect = GossipSelect_npc_berthold; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/loch_modan/loch_modan.cpp b/src/bindings/scripts/scripts/zone/loch_modan/loch_modan.cpp new file mode 100644 index 00000000000..af335dba05f --- /dev/null +++ b/src/bindings/scripts/scripts/zone/loch_modan/loch_modan.cpp @@ -0,0 +1,91 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Loch_Modan +SD%Complete: 100 +SDComment: Quest support: 3181 (only to argue with pebblebitty to get to searing gorge, before quest rewarded) +SDCategory: Loch Modan +EndScriptData */ + +/* ContentData +npc_mountaineer_pebblebitty +EndContentData */ + +#include "precompiled.h" + +/*###### +## npc_mountaineer_pebblebitty +######*/ + +bool GossipHello_npc_mountaineer_pebblebitty(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if (!player->GetQuestRewardStatus(3181) == 1) + player->ADD_GOSSIP_ITEM( 0, "Open the gate please, i need to get to Searing Gorge", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_mountaineer_pebblebitty(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF+1: + player->ADD_GOSSIP_ITEM( 0, "But i need to get there, now open the gate!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->SEND_GOSSIP_MENU(1833, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + player->ADD_GOSSIP_ITEM( 0, "Ok, so what is this other way?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->SEND_GOSSIP_MENU(1834, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + player->ADD_GOSSIP_ITEM( 0, "Doesn't matter, i'm invulnerable.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->SEND_GOSSIP_MENU(1835, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + player->ADD_GOSSIP_ITEM( 0, "Yes...", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->SEND_GOSSIP_MENU(1836, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + player->ADD_GOSSIP_ITEM( 0, "Ok, i'll try to remember that.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->SEND_GOSSIP_MENU(1837, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+6: + player->ADD_GOSSIP_ITEM( 0, "A key? Ok!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->SEND_GOSSIP_MENU(1838, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+7: + player->CLOSE_GOSSIP_MENU(); + break; + } + return true; +} + +void AddSC_loch_modan() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npc_mountaineer_pebblebitty"; + newscript->pGossipHello = &GossipHello_npc_mountaineer_pebblebitty; + newscript->pGossipSelect = &GossipSelect_npc_mountaineer_pebblebitty; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/magisters_terrace/boss_felblood_kaelthas.cpp b/src/bindings/scripts/scripts/zone/magisters_terrace/boss_felblood_kaelthas.cpp new file mode 100644 index 00000000000..5783d1ac441 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/magisters_terrace/boss_felblood_kaelthas.cpp @@ -0,0 +1,591 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: boss_felblood_kaelthas +SD%Complete: 80 +SDComment: Normal and Heroic Support. Issues: Arcane Spheres do not initially follow targets. TODO: Convert Phoenix to ACID. +SDCategory: Magisters' Terrace +EndScriptData */ + +#include "precompiled.h" +#include "def_magisters_terrace.h" +#include "WorldPacket.h" + +/*** Spells ***/ + +// Phase 1 spells + +#define SPELL_FIREBALL_NORMAL 44189 // Deals 2700-3300 damage at current target +#define SPELL_FIREBALL_HEROIC 46164 // 4950-6050 + +#define SPELL_PHOENIX 44194 // Summons a phoenix (Doesn't work?) +#define SPELL_PHOENIX_BURN 44198 // A spell Phoenix uses to damage everything around + +#define SPELL_FLAMESTRIKE1_NORMAL 44190 // Damage part +#define SPELL_FLAMESTRIKE1_HEROIC 46163 // Heroic damage part +#define SPELL_FLAMESTRIKE2 44191 // Flamestrike indicator before the damage +#define SPELL_FLAMESTRIKE3 44192 // Summons the trigger + animation (projectile) + +#define SPELL_SHOCK_BARRIER 46165 // Heroic only; 10k damage shield, followed by Pyroblast +#define SPELL_PYROBLAST 36819 // Heroic only; 45-55k fire damage + +// Phase 2 spells + +#define SPELL_GRAVITY_LAPSE_INITIAL 44224 // Cast at the beginning of every Gravity Lapse +#define SPELL_GRAVITY_LAPSE_CHANNEL 44251 // Channeled; blue beam animation to every enemy in range +#define SPELL_TELEPORT_CENTER 44218 // Should teleport people to the center. Requires DB entry in spell_target_position. +#define SPELL_GRAVITY_LAPSE_FLY 44227 // Hastens flyspeed and allows flying for 1 minute. For some reason removes 44226. +#define SPELL_GRAVITY_LAPSE_DOT 44226 // Knocks up in the air and applies a 300 DPS DoT. +#define SPELL_ARCANE_SPHERE_PASSIVE 44263 // Passive auras on Arcane Spheres +#define SPELL_POWER_FEEDBACK 44233 // Stuns him, making him take 50% more damage for 10 seconds. Cast after Gravity Lapse + +/*** Creatures ***/ +#define CREATURE_PHOENIX 24674 +#define CREATURE_PHOENIX_EGG 24675 +#define CREATURE_ARCANE_SPHERE 24708 + +/*** Dialogues ***/ +#define SAY_AGGRO "Don't look so smug! I know what you're thinking, but Tempest Keep was merely a set back. Did you honestly believe I would trust the future to some blind, half-night elf mongrel? Oh no, he was merely an instrument, a stepping stone to a much larger plan! It has all led to this, and this time, you will not interfere!" +#define SOUND_AGGRO 12413 // This yell should be done when the room is cleared. For now, set it as aggro yell. + +#define SAY_PHOENIX "Vengeance burns!" +#define SOUND_PHOENIX 12415 + +#define SAY_FLAMESTRIKE "Felomin ashal!" +#define SOUND_FLAMESTRIKE 12417 + +#define SAY_GRAVITY_LAPSE "I'll turn your world... upside... down..." +#define SOUND_GRAVITY_LAPSE 12418 + +#define SAY_TIRED "Master... grant me strength." +#define SOUND_TIRED 12419 + +#define SAY_RECAST_GRAVITY "Do not... get too comfortable." +#define SOUND_RECAST_GRAVITY 12420 + +#define SAY_DEATH "My demise accomplishes nothing! The Master will have you! You will drown in your own blood! This world shall burn! Aaaghh!" +#define SOUND_DEATH 12421 + +/** Locations **/ +float KaelLocations[3][2]= +{ + {148.744659, 181.377426}, + {140.823883, 195.403046}, + {156.574188, 195.650482}, +}; +#define LOCATION_Z -16.727455 + +struct MANGOS_DLL_DECL boss_felblood_kaelthasAI : public ScriptedAI +{ + boss_felblood_kaelthasAI(Creature* c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + Heroic = c->GetMap()->IsHeroic() ? true : false; + } + + ScriptedInstance* pInstance; + + uint32 FireballTimer; + uint32 PhoenixTimer; + uint32 FlameStrikeTimer; + uint32 CombatPulseTimer; + + //Heroic only + uint32 PyroblastTimer; + + uint32 GravityLapseTimer; + uint32 GravityLapsePhase; + // 0 = No Gravity Lapse + // 1 = Casting Gravity Lapse visual + // 2 = Teleported people to self + // 3 = Knocked people up in the air + // 4 = Applied an aura that allows them to fly, channeling visual, relased Arcane Orbs. + + bool FirstGravityLapse; + bool Heroic; + + uint8 Phase; + // 0 = Not started + // 1 = Fireball; Summon Phoenix; Flamestrike + // 2 = Gravity Lapses + + void Reset() + { + // TODO: Timers + FireballTimer = 0; + PhoenixTimer = 30000; + FlameStrikeTimer = 25000; + CombatPulseTimer = 0; + + PyroblastTimer = 60000; + + GravityLapseTimer = 0; + GravityLapsePhase = 0; + + FirstGravityLapse = true; + + Phase = 0; + + if(pInstance) + pInstance->SetData(DATA_KAELTHAS_EVENT, 0); + } + + void JustDied(Unit *killer) + { + DoYell(SAY_DEATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_DEATH); + } + + void DamageTaken(Unit* done_by, uint32 &damage) + { + if(damage > m_creature->GetHealth()) + RemoveGravityLapse(); // Remove Gravity Lapse so that players fall to ground if they kill him when in air. + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO); + } + + void SetThreatList(Creature* SummonedUnit) + { + if(!SummonedUnit) return; + + std::list& m_threatlist = m_creature->getThreatManager().getThreatList(); + std::list::iterator i = m_threatlist.begin(); + for(i = m_threatlist.begin(); i != m_threatlist.end(); i++) + { + Unit* pUnit = Unit::GetUnit((*m_creature), (*i)->getUnitGuid()); + if(pUnit && pUnit->isAlive()) + { + float threat = m_creature->getThreatManager().getThreat(pUnit); + SummonedUnit->AddThreat(pUnit, threat); + } + } + } + + void TeleportPlayersToSelf() + { + float x = KaelLocations[0][0]; + float y = KaelLocations[0][1]; + m_creature->Relocate(x, y, LOCATION_Z, 0); + //m_creature->SendMonsterMove(x, y, LOCATION_Z, 0, 0, 0); // causes some issues... + std::list::iterator i = m_creature->getThreatManager().getThreatList().begin(); + for (i = m_creature->getThreatManager().getThreatList().begin(); i!= m_creature->getThreatManager().getThreatList().end();++i) + { + Unit* pUnit = Unit::GetUnit((*m_creature), (*i)->getUnitGuid()); + if(pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER)) + pUnit->CastSpell(pUnit, SPELL_TELEPORT_CENTER, true); + } + DoCast(m_creature, SPELL_TELEPORT_CENTER, true); + } + + void CastGravityLapseKnockUp() + { + std::list::iterator i = m_creature->getThreatManager().getThreatList().begin(); + for (i = m_creature->getThreatManager().getThreatList().begin(); i!= m_creature->getThreatManager().getThreatList().end();++i) + { + Unit* pUnit = Unit::GetUnit((*m_creature), (*i)->getUnitGuid()); + if(pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER)) + // Knockback into the air + pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE_DOT, true, 0, 0, m_creature->GetGUID()); + } + } + + void CastGravityLapseFly() // Use Fly Packet hack for now as players can't cast "fly" spells unless in map 530. Has to be done a while after they get knocked into the air... + { + std::list::iterator i = m_creature->getThreatManager().getThreatList().begin(); + for (i = m_creature->getThreatManager().getThreatList().begin(); i!= m_creature->getThreatManager().getThreatList().end();++i) + { + Unit* pUnit = Unit::GetUnit((*m_creature), (*i)->getUnitGuid()); + if(pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER)) + { + // Also needs an exception in spell system. + pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE_FLY, true, 0, 0, m_creature->GetGUID()); + // Use packet hack + WorldPacket data(12); + data.SetOpcode(SMSG_MOVE_SET_CAN_FLY); + data.append(pUnit->GetPackGUID()); + data << uint32(0); + pUnit->SendMessageToSet(&data, true); + } + } + } + + void RemoveGravityLapse() + { + std::list::iterator i = m_creature->getThreatManager().getThreatList().begin(); + for (i = m_creature->getThreatManager().getThreatList().begin(); i!= m_creature->getThreatManager().getThreatList().end();++i) + { + Unit* pUnit = Unit::GetUnit((*m_creature), (*i)->getUnitGuid()); + if(pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER)) + { + pUnit->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_FLY); + pUnit->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_DOT); + WorldPacket data(12); + data.SetOpcode(SMSG_MOVE_UNSET_CAN_FLY); + data.append(pUnit->GetPackGUID()); + data << uint32(0); + pUnit->SendMessageToSet(&data, true); + } + } + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->getVictim() && !m_creature->SelectHostilTarget()) + return; + + switch(Phase) + { + case 0: + { + // *Heroic mode only: + if(Heroic) + if(PyroblastTimer < diff) + { + DoCast(m_creature, SPELL_SHOCK_BARRIER, true); + DoCast(m_creature->getVictim(), SPELL_PYROBLAST); + PyroblastTimer = 60000; + }else PyroblastTimer -= diff; + + if(FireballTimer < diff) + { + // *Normal/Heroic mode support + if(Heroic) DoCast(m_creature->getVictim(), SPELL_FIREBALL_HEROIC); + else DoCast(m_creature->getVictim(), SPELL_FIREBALL_NORMAL); + FireballTimer = 2000 + rand()%4000; + }else FireballTimer -= diff; + + if(PhoenixTimer < diff) + { + uint32 random = rand()%2 + 1; + float x = KaelLocations[random][0]; + float y = KaelLocations[random][1]; + Creature* Phoenix = m_creature->SummonCreature(CREATURE_PHOENIX, x, y, LOCATION_Z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); + if(Phoenix) + { + Phoenix->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); + SetThreatList(Phoenix); + } + + DoYell(SAY_PHOENIX, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_PHOENIX); + + PhoenixTimer = 40000; + }else PhoenixTimer -= diff; + + if(FlameStrikeTimer < diff) + { + Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target) + { + DoCast(target, SPELL_FLAMESTRIKE3, true); + FlameStrikeTimer = 20000 + rand()%5000; + + DoYell(SAY_FLAMESTRIKE, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_FLAMESTRIKE); + } + }else FlameStrikeTimer -= diff; + + // Below 50% + if(m_creature->GetMaxHealth() * 0.5 > m_creature->GetHealth()) + { + m_creature->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, true); + m_creature->StopMoving(); + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MoveIdle(); + GravityLapseTimer = 0; + GravityLapsePhase = 0; + Phase = 1; + } + DoMeleeAttackIfReady(); + } + break; + + case 1: + { + if(GravityLapseTimer < diff) + { + switch(GravityLapsePhase) + { + case 0: + if(FirstGravityLapse) // Different yells at 50%, and at every following Gravity Lapse + { + DoYell(SAY_GRAVITY_LAPSE,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_GRAVITY_LAPSE); + FirstGravityLapse = false; + if(pInstance) + { + GameObject* KaelLeft = GameObject::GetGameObject(*m_creature, pInstance->GetData64(DATA_KAEL_STATUE_LEFT)); + if(KaelLeft) KaelLeft->SetGoState(0); + GameObject* KaelRight = GameObject::GetGameObject(*m_creature, pInstance->GetData64(DATA_KAEL_STATUE_RIGHT)); + if(KaelRight) KaelRight->SetGoState(0); + } + }else + { + DoYell(SAY_RECAST_GRAVITY,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_RECAST_GRAVITY); + } + DoCast(m_creature, SPELL_GRAVITY_LAPSE_INITIAL); + GravityLapseTimer = 2000 + diff;// Don't interrupt the visual spell + GravityLapsePhase = 1; + break; + + case 1: + TeleportPlayersToSelf(); + GravityLapseTimer = 1000; + GravityLapsePhase = 2; + break; + + case 2: + CastGravityLapseKnockUp(); + GravityLapseTimer = 1000; + GravityLapsePhase = 3; + break; + + case 3: + CastGravityLapseFly(); + GravityLapseTimer = 30000; + GravityLapsePhase = 4; + for(uint8 i = 0; i < 3; ++i) + { + Creature* Orb = DoSpawnCreature(CREATURE_ARCANE_SPHERE, 5, 5, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000); + if(Orb) SetThreatList(Orb); + } + DoCast(m_creature, SPELL_GRAVITY_LAPSE_CHANNEL); + break; + + case 4: + m_creature->InterruptNonMeleeSpells(false); + DoYell(SAY_TIRED,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_TIRED); + DoCast(m_creature, SPELL_POWER_FEEDBACK); + RemoveGravityLapse(); + GravityLapseTimer = 10000; + GravityLapsePhase = 0; + break; + } + }else GravityLapseTimer -= diff; + } + break; + } + } +}; + +struct MANGOS_DLL_DECL mob_felkael_flamestrikeAI : public ScriptedAI +{ + mob_felkael_flamestrikeAI(Creature *c) : ScriptedAI(c) + { + Reset(); + Heroic = c->GetMap()->IsHeroic() ? true : false; + } + + uint32 FlameStrikeTimer; + bool Heroic; + + void Reset() + { + FlameStrikeTimer = 5000; + + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->setFaction(14); + + DoCast(m_creature, SPELL_FLAMESTRIKE2, true); + } + + void Aggro(Unit *who) {} + void MoveInLineOfSight(Unit *who) {} + void UpdateAI(const uint32 diff) + { + if(FlameStrikeTimer < diff) + { + // *Normal/Heroic mode support + if(Heroic) DoCast(m_creature, SPELL_FLAMESTRIKE1_HEROIC, true); + else DoCast(m_creature, SPELL_FLAMESTRIKE1_NORMAL, true); + m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + }else FlameStrikeTimer -= diff; + } +}; + +struct MANGOS_DLL_DECL mob_felkael_phoenixAI : public ScriptedAI +{ + mob_felkael_phoenixAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 BurnTimer; + + void Reset() + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); + BurnTimer = 2000; + } + + void Aggro(Unit* who) {} + + void JustDied(Unit* slayer) + { + DoSpawnCreature(CREATURE_PHOENIX_EGG, 0, 0, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 45000); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if (BurnTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_PHOENIX_BURN); + BurnTimer = 2000; + }else BurnTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL mob_felkael_phoenix_eggAI : public ScriptedAI +{ + mob_felkael_phoenix_eggAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 HatchTimer; + + void Reset() { HatchTimer = 15000; } + + void Aggro(Unit* who) {} + void MoveInLineOfSight(Unit* who) {} + + void UpdateAI(const uint32 diff) + { + if(HatchTimer < diff) + { + DoSpawnCreature(CREATURE_PHOENIX, 0, 0, 0, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000); + m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + }else HatchTimer -= diff; + } +}; + +struct MANGOS_DLL_DECL mob_arcane_sphereAI : public ScriptedAI +{ + mob_arcane_sphereAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 DespawnTimer; + uint32 ChangeTargetTimer; + + bool TargetLocked; + + void Reset() + { + DespawnTimer = 30000; + ChangeTargetTimer = 5000; + TargetLocked = false; + + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->setFaction(14); + DoCast(m_creature, SPELL_ARCANE_SPHERE_PASSIVE, true); + } + + void MoveInLineOfSight(Unit* who) + { + if(TargetLocked) + return; + if(who && who->IsHostileTo(m_creature) && (m_creature->IsWithinDistInMap(who, 25))) + StalkTarget(who); + } + + void Aggro(Unit* who) {} + + void StalkTarget(Unit* target) + { + if(!target) + return; + + m_creature->GetMotionMaster()->MoveChase(target); + TargetLocked = true; + } + + void UpdateAI(const uint32 diff) + { + if(DespawnTimer < diff) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + else DespawnTimer -= diff; + + if(!m_creature->getVictim() || !m_creature->SelectHostilTarget()) + return; + + if(ChangeTargetTimer < diff) + { + TargetLocked = false; + ChangeTargetTimer = 10000; + }else ChangeTargetTimer -= diff; + } +}; + +CreatureAI* GetAI_boss_felblood_kaelthas(Creature* c) +{ + return new boss_felblood_kaelthasAI(c); +} + +CreatureAI* GetAI_mob_arcane_sphere(Creature* c) +{ + return new mob_arcane_sphereAI(c); +} + +CreatureAI* GetAI_mob_felkael_phoenix(Creature* c) +{ + return new mob_felkael_phoenixAI(c); +} + +CreatureAI* GetAI_mob_felkael_phoenix_egg(Creature* c) +{ + return new mob_felkael_phoenix_eggAI(c); +} + +CreatureAI* GetAI_mob_felkael_flamestrike(Creature* c) +{ + return new mob_felkael_flamestrikeAI(c); +} + +void AddSC_boss_felblood_kaelthas() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_felblood_kaelthas"; + newscript->GetAI = GetAI_boss_felblood_kaelthas; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name = "mob_arcane_sphere"; + newscript->GetAI = GetAI_mob_arcane_sphere; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_felkael_phoenix"; + newscript->GetAI = GetAI_mob_felkael_phoenix; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_felkael_phoenix_egg"; + newscript->GetAI = GetAI_mob_felkael_phoenix_egg; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_felkael_flamestrike"; + newscript->GetAI = GetAI_mob_felkael_flamestrike; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/magisters_terrace/boss_priestess_delrissa.cpp b/src/bindings/scripts/scripts/zone/magisters_terrace/boss_priestess_delrissa.cpp new file mode 100644 index 00000000000..94b13cd5cd5 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/magisters_terrace/boss_priestess_delrissa.cpp @@ -0,0 +1,1367 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Priestess_Delrissa +SD%Complete: 45 +SDComment: No Heroic support yet. Needs further testing. Several scripts for pets disabled, not seem to require any special script. +SDCategory: Magister's Terrace +EndScriptData */ + +#include "precompiled.h" +#include "def_magisters_terrace.h" + +#define SAY_AGGRO "Annihilate them!" +#define SOUND_AGGRO 12395 + +struct Speech +{ + const char* text; + uint32 sound; +}; + +static Speech LackeyDeath[]= +{ + {"Oh, the horror.", 12398}, + {"Well, aren't you lucky?", 12400}, + {"Now I'm getting annoyed.", 12401}, + {"Lackies be damned! I'll finish you myself!", 12403}, +}; + +static Speech PlayerDeath[]= +{ + {"I call that a good start.", 12405}, + {"I could have sworn there were more of you.", 12407}, + {"Not really much of a group, anymore, is it?", 12409}, + {"One is such a lonely number", 12410}, + {"It's been a kick, really", 12411}, +}; + +#define SAY_DEATH "Not what I had... planned..." +#define SOUND_DEATH 12397 + +#define SPELL_DISPEL_MAGIC 27609 +#define SPELL_FLASH_HEAL 17843 +#define SPELL_SW_PAIN_NORMAL 14032 +#define SPELL_SW_PAIN_HEROIC 15654 +#define SPELL_SHIELD 44291 +#define SPELL_RENEW_NORMAL 44174 +#define SPELL_RENEW_HEROIC 46192 + +#define ORIENT 4.98 +#define POS_Z -19.9215 + +float LackeyLocations[4][2]= +{ + {123.77, 17.6007}, + {131.731, 15.0827}, + {121.563, 15.6213}, + {129.988, 17.2355}, +}; + +const uint32 AddEntry[8]= +{ + 24557, //Kagani Nightstrike + 24558, //Elris Duskhallow + 24554, //Eramas Brightblaze + 24561, //Yazzaj + 24559, //Warlord Salaris + 24555, //Garaxxas + 24553, //Apoko + 24556, //Zelfan +}; + +struct Add +{ + Add(uint32 _entry, uint64 _guid) + { + entry = _entry; + guid = _guid; + } + + uint32 entry; + uint64 guid; +}; + +struct MANGOS_DLL_DECL boss_priestess_delrissaAI : public ScriptedAI +{ + boss_priestess_delrissaAI(Creature* c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Adds.clear(); + Reset(); + SummonAdds(); + Heroic = c->GetMap()->IsHeroic(); + } + + ScriptedInstance* pInstance; + + std::vector Adds; + + uint8 LackeysKilled; + uint8 PlayersKilled; + + uint32 HealTimer; + uint32 RenewTimer; + uint32 ShieldTimer; + uint32 SWPainTimer; + uint32 DispelTimer; + + uint32 CombatPulseTimer; // Periodically puts all players in the instance in combat + + bool Heroic; + + void Reset() + { + LackeysKilled = 0; + PlayersKilled = 0; + + HealTimer = 15000; + RenewTimer = 10000; + ShieldTimer = 2000; + SWPainTimer = 5000; + DispelTimer = 7500; + + CombatPulseTimer = 5000; + + CheckAdds(); + + if(pInstance) + { + pInstance->SetData(DATA_DELRISSA_EVENT, NOT_STARTED); + pInstance->SetData(DATA_DELRISSA_DEATH_COUNT, 0); + } + else error_log(ERROR_INST_DATA); + } + + void Aggro(Unit* who) + { + DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO); + + for(uint8 i = 0; i < Adds.size(); ++i) + if(Unit* pAdd = Unit::GetUnit(*m_creature, Adds[i]->guid)) + pAdd->AddThreat(who, 1.0f); + } + + void SummonAdds() + { + std::vector AddList; + for(uint8 i = 0; i < 8; ++i) + AddList.push_back(AddEntry[i]); + + while(AddList.size() > 4) + AddList.erase(AddList.begin() + rand()%AddList.size()); + + for(uint8 i = 0; i < AddList.size(); ++i) + { + Creature* pAdd = m_creature->SummonCreature(AddList[i], LackeyLocations[i][0], LackeyLocations[i][1], POS_Z, ORIENT, TEMPSUMMON_DEAD_DESPAWN, 0); + if(pAdd) + { + Add* nAdd = new Add(AddList[i], pAdd->GetGUID()); + Adds.push_back(nAdd); + } + } + } + + void CheckAdds() + { + if(Adds.empty()) + return; + + for(uint8 i = 0; i < Adds.size(); ++i) + { + bool resummon = true; + Creature* pAdd = ((Creature*)Unit::GetUnit(*m_creature, Adds[i]->guid)); + if(pAdd && pAdd->isAlive()) + { + pAdd->AI()->EnterEvadeMode(); // Force them out of combat and reset if they are in combat. + resummon = false; + } + if(resummon) + { + pAdd = m_creature->SummonCreature(Adds[i]->entry, LackeyLocations[i][0], LackeyLocations[i][1], POS_Z, ORIENT, TEMPSUMMON_DEAD_DESPAWN, 0); + Add* nAdd = new Add(Adds[i]->entry, pAdd->GetGUID()); + Adds.erase(Adds.begin() + i); + Adds.push_back(nAdd); + } + } + } + + void KilledUnit(Unit* victim) + { + if(victim->GetTypeId() != TYPEID_PLAYER) + return; + + DoYell(PlayerDeath[PlayersKilled].text, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, PlayerDeath[PlayersKilled].sound); + if( PlayersKilled < 4 ) + ++PlayersKilled; + } + + void KilledLackey() + { + DoYell(LackeyDeath[LackeysKilled].text, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, LackeyDeath[LackeysKilled].sound); + if( LackeysKilled < 3 ) + ++LackeysKilled; + } + + void JustDied(Unit* killer) + { + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_DEATH); + + CheckLootable(); + + if(!pInstance) + { + error_log(ERROR_INST_DATA); + return; + } + + pInstance->SetData(DATA_DELRISSA_DEATH_COUNT, 1); + pInstance->SetData(DATA_DELRISSA_EVENT, DONE); + if(GameObject* Door = GameObject::GetGameObject(*m_creature, pInstance->GetData64(DATA_DELRISSA_DOOR))) + Door->SetGoState(0); + } + + void CheckLootable() + { + if(LackeysKilled > 4) + m_creature->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + else + m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(HealTimer < diff) + { + uint32 health = m_creature->GetHealth(); + Unit* target = m_creature; + for(uint8 i = 0; i < Adds.size(); ++i) + if(Unit* pAdd = Unit::GetUnit(*m_creature, Adds[i]->guid)) + if(pAdd->isAlive() && pAdd->GetHealth() < health) + target = pAdd; + + DoCast(target, SPELL_FLASH_HEAL); + HealTimer = 15000; + }else HealTimer -= diff; + + if(RenewTimer < diff) + { + Unit* target = m_creature; + if(rand()%2 == 1) + { + std::vector::iterator itr = Adds.begin() + rand()%Adds.size(); + Unit* pAdd = Unit::GetUnit(*m_creature, (*itr)->guid); + if(pAdd && pAdd->isAlive()) + target = pAdd; + } + DoCast(target,Heroic ? SPELL_RENEW_HEROIC : SPELL_RENEW_NORMAL); + RenewTimer = 5000; + }else RenewTimer -= diff; + + if(ShieldTimer < diff) + { + Unit* target = m_creature; + if(rand()%2 == 1) + { + std::vector::iterator itr = Adds.begin() + rand()%Adds.size(); + if(Unit* pAdd = Unit::GetUnit(*m_creature, (*itr)->guid)) + if(!pAdd->HasAura(SPELL_SHIELD, 0) && pAdd->isAlive()) + target = pAdd; + } + DoCast(target, SPELL_SHIELD); + ShieldTimer = 7500; + }else ShieldTimer -= diff; + + if(DispelTimer < diff) + { + Unit* target = NULL; + bool friendly = false; + if(rand()%2 == 1) + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + else + { + friendly = true; + if(rand()%2 == 1) + target = m_creature; + else + { + std::vector::iterator itr = Adds.begin() + rand()%Adds.size(); + Unit* pAdd = Unit::GetUnit(*m_creature, (*itr)->guid); + if(pAdd && pAdd->isAlive()) + target = pAdd; + } + } + if(target) + { + DoCast(target, SPELL_DISPEL_MAGIC); + DispelTimer = 12000; + } + }else DispelTimer -= diff; + + if(SWPainTimer < diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0),Heroic ? SPELL_SW_PAIN_HEROIC : SPELL_SW_PAIN_NORMAL); + SWPainTimer = 10000; + }else SWPainTimer -= diff; + + /* + if(CombatPulseTimer < diff) + { + DoZoneInCombat(); + for(uint8 i = 0; i < Adds.size(); ++i) + { + if(Unit* pAdd = Unit::GetUnit(*m_creature, Add[i]->guid)) + if(pAdd->isAlive()) + DoZoneInCombat(pAdd); + } + + CombatPulseTimer = 10000; + }else CombatPulseTimer -= diff;*/ + + DoMeleeAttackIfReady(); + } +}; + +#define SPELL_HEALING_POTION 15503 + +struct MANGOS_DLL_DECL boss_priestess_guestAI : public ScriptedAI +{ + boss_priestess_guestAI(Creature* c) : ScriptedAI(c) + { + Group.clear(); + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + AcquireGUIDs(); + } + + ScriptedInstance* pInstance; + + std::vector Group; + + uint32 ResetThreatTimer; + + bool UsedPotion; + + void Reset() + { + UsedPotion = false; + + ResetThreatTimer = 5000 + rand()%15000; // These guys like to switch targets often, and are not meant to be tanked. + } + + void Aggro(Unit* who) {} + + void JustDied(Unit* killer) + { + if(!pInstance) + { + error_log(ERROR_INST_DATA); + return; + } + + Creature* Delrissa = ((Creature*)Unit::GetUnit(*m_creature, pInstance->GetData64(DATA_DELRISSA))); + if(Delrissa) + { + ((boss_priestess_delrissaAI*)Delrissa->AI())->KilledLackey(); + if(!Delrissa->isAlive() && pInstance->GetData(DATA_DELRISSA_DEATH_COUNT) > 3) + ((boss_priestess_delrissaAI*)Delrissa->AI())->CheckLootable(); + + pInstance->SetData(DATA_DELRISSA_DEATH_COUNT, 1); + } + } + + void KilledUnit(Unit* victim) + { + if(!pInstance) + { + error_log(ERROR_INST_DATA); + return; + } + + Creature* Delrissa = ((Creature*)Unit::GetUnit(*m_creature, pInstance->GetData64(DATA_DELRISSA))); + if(Delrissa) + Delrissa->AI()->KilledUnit(victim); + } + + void AcquireGUIDs() + { + if(!pInstance) + { + error_log(ERROR_INST_DATA); + return; + } + + Creature* Delrissa = ((Creature*)Unit::GetUnit(*m_creature, pInstance->GetData64(DATA_DELRISSA))); + if(Delrissa) + { + Group = ((boss_priestess_delrissaAI*)Delrissa->AI())->Adds; + Add* dAdd = new Add(Delrissa->GetEntry(), Delrissa->GetGUID()); + Group.push_back(dAdd); + } + } + + void UpdateAI(const uint32 diff) + { + if(((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 25) && !UsedPotion) + { + DoCast(m_creature, SPELL_HEALING_POTION, true); + UsedPotion = true; + } + + if(ResetThreatTimer < diff) + { + DoResetThreat(); + ResetThreatTimer = 5000 + rand()%15000; + }else ResetThreatTimer -= diff; + } +}; + +#define SPELL_KIDNEY_SHOT 27615 +#define SPELL_GOUGE 12540 +#define SPELL_KICK 27613 +#define SPELL_VANISH 44290 +#define SPELL_BACKSTAB 15657 +#define SPELL_EVISCERATE 27611 + +struct MANGOS_DLL_DECL boss_kagani_nightstrikeAI : public boss_priestess_guestAI +{ + //Rogue + boss_kagani_nightstrikeAI(Creature *c) : boss_priestess_guestAI(c) {} + + uint32 Gouge_Timer; + uint32 Kick_Timer; + uint32 Vanish_Timer; + uint32 Eviscerate_Timer; + uint32 Wait_Timer; + bool InVanish; + + void Reset() + { + Gouge_Timer = 5500; + Kick_Timer = 7000; + Vanish_Timer = 2000; + Eviscerate_Timer = 6000; + Wait_Timer = 5000; + InVanish = false; + m_creature->SetVisibility(VISIBILITY_ON); + + boss_priestess_guestAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + boss_priestess_guestAI::UpdateAI(diff); + + if(Vanish_Timer < diff) + { + m_creature->SetVisibility(VISIBILITY_OFF); // ...? Hacklike + DoCast(m_creature, SPELL_VANISH); + InVanish = true; + Vanish_Timer = 30000; + Wait_Timer = 10000; + DoResetThreat(); + m_creature->AddThreat(SelectUnit(SELECT_TARGET_RANDOM, 0), 1000.0f); + }else Vanish_Timer -= diff; + + if(InVanish) + if(Wait_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_BACKSTAB, true); + DoCast(m_creature->getVictim(), SPELL_KIDNEY_SHOT, true); + m_creature->SetVisibility(VISIBILITY_ON); // ...? Hacklike + InVanish = false; + }else Wait_Timer -= diff; + + if(Gouge_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_GOUGE); + m_creature->getThreatManager().modifyThreatPercent(m_creature->getVictim(),-100); + Gouge_Timer = 5500; + }else Gouge_Timer -= diff; + + if(Kick_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_KICK); + Kick_Timer = 7000; + }else Kick_Timer -= diff; + + if(Eviscerate_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_EVISCERATE); + Eviscerate_Timer = 4000; + }else Eviscerate_Timer -= diff; + + if(!InVanish) + DoMeleeAttackIfReady(); + } +}; + +#define SPELL_IMMOLATE 44267 +#define SPELL_SHADOW_BOLT 12471 +#define SPELL_SEED_OF_CORRUPTION 44141 +#define SPELL_CURSE_OF_AGONY 14875 +#define SPELL_FEAR 38595 +#define SPELL_IMP_FIREBALL 44164 +#define SPELL_SUMMON_IMP 44163 + +//#define CREATURE_IMP 44163 +//#define CREATURE_FIZZLE 24656 + +/*struct MANGOS_DLL_DECL mob_fizzleAI : public ScriptedAI +{ + mob_fizzleAI(Creature *c) : ScriptedAI(c) + { + Reset(); + } + + uint64 EllrisGUID; + uint32 Firebal_Timer; + + void Reset() { EllrisGUID = 0; } + + void KilledUnit(Unit* victim); + void JustDied(Unit* killer); + + void Aggro(Unit* who){} + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //Chain cast + if (!m_creature->IsNonMeleeSpellCasted(false)) + DoCast(m_creature->getVictim(),SPELL_IMP_FIREBALL); + else DoMeleeAttackIfReady(); + } +};*/ + +struct MANGOS_DLL_DECL boss_ellris_duskhallowAI : public boss_priestess_guestAI +{ + //Warlock + boss_ellris_duskhallowAI(Creature *c) : boss_priestess_guestAI(c) + { + } + + bool HasSummonedImp; + + uint32 Immolate_Timer; + uint32 Shadow_Bolt_Timer; + uint32 Seed_of_Corruption_Timer; + uint32 Curse_of_Agony_Timer; + uint32 Fear_Timer; + + void Reset() + { + //HasSummonedImp = false; + + Immolate_Timer = 6000; + Shadow_Bolt_Timer = 3000; + Seed_of_Corruption_Timer = 2000; + Curse_of_Agony_Timer = 1000; + Fear_Timer = 10000; + + boss_priestess_guestAI::Reset(); + } + + void JustDied(Unit* killer) + { + boss_priestess_guestAI::JustDied(killer); + } + + void UpdateAI(const uint32 diff) + { + if(!HasSummonedImp) + { + //Imp will not despawn unless it's killed, even if owner dies, this is correct way. + DoCast(m_creature,SPELL_SUMMON_IMP); + HasSummonedImp = true; + } + + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + boss_priestess_guestAI::UpdateAI(diff); + + if(Immolate_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_IMMOLATE); + Immolate_Timer = 6000; + }else Immolate_Timer -= diff; + + if(Shadow_Bolt_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SHADOW_BOLT); + Shadow_Bolt_Timer = 5000; + }else Shadow_Bolt_Timer -= diff; + + if(Seed_of_Corruption_Timer < diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_SEED_OF_CORRUPTION); + Seed_of_Corruption_Timer = 10000; + }else Seed_of_Corruption_Timer -= diff; + + if(Curse_of_Agony_Timer < diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_CURSE_OF_AGONY); + Curse_of_Agony_Timer = 13000; + }else Curse_of_Agony_Timer -= diff; + + if(Fear_Timer < diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_FEAR); + Fear_Timer = 10000; + }else Fear_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +/*void mob_fizzleAI::JustDied(Unit* killer) +{ + if(Creature* Ellris = ((Creature*)Unit::GetUnit(*m_creature, EllrisGUID))) + ((boss_ellris_duskhallowAI*)Ellris->AI())->ImpGUID = 0; +} + +void mob_fizzleAI::KilledUnit(Unit* victim) +{ + if(Creature* Ellris = ((Creature*)Unit::GetUnit(*m_creature, EllrisGUID))) + ((boss_ellris_duskhallowAI*)Ellris->AI())->KilledUnit(victim); +}*/ + +#define SPELL_KNOCKDOWN 11428 +#define SPELL_SNAP_KICK 46182 + +struct MANGOS_DLL_DECL boss_eramas_brightblazeAI : public boss_priestess_guestAI +{ + //Monk + boss_eramas_brightblazeAI(Creature *c) : boss_priestess_guestAI(c) {} + + uint32 Knockdown_Timer; + uint32 Snap_Kick_Timer; + + void Reset() + { + Knockdown_Timer = 6000; + Snap_Kick_Timer = 4500; + + boss_priestess_guestAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + boss_priestess_guestAI::UpdateAI(diff); + + if(Knockdown_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_KNOCKDOWN); + Knockdown_Timer = 6000; + }else Knockdown_Timer -= diff; + + if(Snap_Kick_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SNAP_KICK); + Snap_Kick_Timer = 4500; + }else Snap_Kick_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +#define SPELL_POLYMORPH 13323 +#define SPELL_ICE_BLOCK 27619 +#define SPELL_BLIZZARD 44178 +#define SPELL_ICE_LANCE 46194 +#define SPELL_CONE_OF_COLD 38384 +#define SPELL_FROSTBOLT 15043 +#define SPELL_BLINK 14514 + +struct MANGOS_DLL_DECL boss_yazzaiAI : public boss_priestess_guestAI +{ + //Mage + boss_yazzaiAI(Creature *c) : boss_priestess_guestAI(c) {} + + bool HasIceBlocked; + + uint32 Polymorph_Timer; + uint32 Ice_Block_Timer; + uint32 Wait_Timer; + uint32 Blizzard_Timer; + uint32 Ice_Lance_Timer; + uint32 Cone_of_Cold_Timer; + uint32 Frostbolt_Timer; + uint32 Blink_Timer; + + void Reset() + { + HasIceBlocked = false; + + Polymorph_Timer = 1000; + Ice_Block_Timer = 20000; + Wait_Timer = 10000; + Blizzard_Timer = 8000; + Ice_Lance_Timer = 12000; + Cone_of_Cold_Timer = 10000; + Frostbolt_Timer = 3000; + Blink_Timer = 8000; + + boss_priestess_guestAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + boss_priestess_guestAI::UpdateAI(diff); + + if(Polymorph_Timer < diff) + { + Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target) + { + DoCast(target, SPELL_POLYMORPH); + m_creature->getThreatManager().modifyThreatPercent(target,-100); + Polymorph_Timer = 20000; + } + }else Polymorph_Timer -= diff; + + if(((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 35) && !HasIceBlocked) + { + DoCast(m_creature, SPELL_ICE_BLOCK); + HasIceBlocked = true; + } + + if(Blizzard_Timer < diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_BLIZZARD); + Blizzard_Timer = 8000; + }else Blizzard_Timer -= diff; + + if(Ice_Lance_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_ICE_LANCE); + Ice_Lance_Timer = 12000; + }else Ice_Lance_Timer -= diff; + + if(Cone_of_Cold_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_CONE_OF_COLD); + Cone_of_Cold_Timer = 10000; + }else Cone_of_Cold_Timer -= diff; + + if(Frostbolt_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_FROSTBOLT); + Frostbolt_Timer = 8000; + }else Frostbolt_Timer -= diff; + + if(Blink_Timer < diff) + { + bool InMeleeRange = false; + std::list& t_list = m_creature->getThreatManager().getThreatList(); + for(std::list::iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + if(Unit* target = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid())) + //if in melee range + if (target->IsWithinDistInMap(m_creature, 5)) + { + InMeleeRange = true; + break; + } + } + //if anybody is in melee range than escape by blink + if(InMeleeRange) + DoCast(m_creature, SPELL_BLINK); + + Blink_Timer = 8000; + }else Blink_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +#define SPELL_INTERCEPT_STUN 27577 +#define SPELL_DISARM 27581 +#define SPELL_PIERCING_HOWL 23600 +#define SPELL_FRIGHTENING_SHOUT 19134 +#define SPELL_HAMSTRING 27584 +#define SPELL_BATTLE_SHOUT 27578 +#define SPELL_MORTAL_STRIKE 44268 + +struct MANGOS_DLL_DECL boss_warlord_salarisAI : public boss_priestess_guestAI +{ + //Warrior + boss_warlord_salarisAI(Creature *c) : boss_priestess_guestAI(c) {} + + uint32 Intercept_Stun_Timer; + uint32 Disarm_Timer; + uint32 Piercing_Howl_Timer; + uint32 Frightening_Shout_Timer; + uint32 Hamstring_Timer; + uint32 Mortal_Strike_Timer; + + void Reset() + { + Intercept_Stun_Timer = 500; + Disarm_Timer = 6000; + Piercing_Howl_Timer = 10000; + Frightening_Shout_Timer = 18000; + Hamstring_Timer = 4500; + Mortal_Strike_Timer = 8000; + DoCast(m_creature, SPELL_BATTLE_SHOUT); + boss_priestess_guestAI::Reset(); + } + + void Aggro(Unit* who) + { + DoCast(m_creature, SPELL_BATTLE_SHOUT); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + boss_priestess_guestAI::UpdateAI(diff); + + if(Intercept_Stun_Timer < diff) + { + bool InMeleeRange = false; + std::list& t_list = m_creature->getThreatManager().getThreatList(); + for(std::list::iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + if(Unit* target = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid())) + //if in melee range + if (target->IsWithinDistInMap(m_creature, 5)) + { + InMeleeRange = true; + break; + } + } + //if nobody is in melee range than try to use Intercept + if(!InMeleeRange) + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_INTERCEPT_STUN); + Intercept_Stun_Timer = 10000; + }else Intercept_Stun_Timer -= diff; + + if(Disarm_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_DISARM); + Disarm_Timer = 6000; + }else Disarm_Timer -= diff; + + if(Hamstring_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_HAMSTRING); + Hamstring_Timer = 4500; + }else Hamstring_Timer -= diff; + + if(Mortal_Strike_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_MORTAL_STRIKE); + Mortal_Strike_Timer = 4500; + }else Mortal_Strike_Timer -= diff; + + if(Piercing_Howl_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_PIERCING_HOWL); + Piercing_Howl_Timer = 10000; + }else Piercing_Howl_Timer -= diff; + + if(Frightening_Shout_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_FRIGHTENING_SHOUT); + Frightening_Shout_Timer = 18000; + }else Frightening_Shout_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +#define SPELL_AIMED_SHOT 44271 +#define SPELL_SHOOT 15620 +#define SPELL_CONCUSSIVE_SHOT 27634 +#define TRIGGER_CONCUSSIVE_SHOT 19410 +#define SPELL_MULTI_SHOT 31942 +#define SPELL_WING_CLIP 44286 +#define SPELL_FREEZING_TRAP 44136 + +#define CREATURE_SLIVER 24552 + +/*struct MANGOS_DLL_DECL mob_sliverAI : public ScriptedAI +{ + mob_sliverAI(Creature *c) : ScriptedAI(c) + { + Reset(); + } + + uint64 GaraxxasGUID; + + void Reset() { GaraxxasGUID = 0; } + + void KilledUnit(Unit* victim); + void JustDied(Unit* killer); + + void Aggro(Unit* who){} + +};*/ + +struct MANGOS_DLL_DECL boss_garaxxasAI : public boss_priestess_guestAI +{ + //Hunter + boss_garaxxasAI(Creature *c) : boss_priestess_guestAI(c) {} + + //uint64 SliverGUID; + bool HasSummonedSliver; + + uint32 Aimed_Shot_Timer; + uint32 Shoot_Timer; + uint32 Concussive_Shot_Timer; + uint32 Multi_Shot_Timer; + uint32 Wing_Clip_Timer; + uint32 Freezing_Trap_Timer; + + void Reset() + { + //SliverGUID = 0; + //HasSummonedSliver = false; + + Aimed_Shot_Timer = 6000; + Shoot_Timer = 2500; + Concussive_Shot_Timer = 8000; + Multi_Shot_Timer = 10000; + Wing_Clip_Timer = 4000; + Freezing_Trap_Timer = 15000; + + boss_priestess_guestAI::Reset(); + } + + void JustDied(Unit* killer) + { + boss_priestess_guestAI::JustDied(killer); + } + + void UpdateAI(const uint32 diff) + { + if(!HasSummonedSliver) + { + Creature* Sliver = m_creature->SummonCreature(CREATURE_SLIVER, 0, 0, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + if(Sliver) + { + //((mob_sliverAI*)Sliver->AI())->GaraxxasGUID = m_creature->GetGUID(); + //SliverGUID = Sliver->GetGUID(); + HasSummonedSliver = true; + } + } + + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + boss_priestess_guestAI::UpdateAI(diff); + + if(m_creature->IsWithinDistInMap(m_creature->getVictim(), 5)) + { + if(Wing_Clip_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_WING_CLIP); + Wing_Clip_Timer = 4000; + }else Wing_Clip_Timer -= diff; + + if(Freezing_Trap_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_FREEZING_TRAP); + m_creature->getThreatManager().modifyThreatPercent(m_creature->getVictim(),-100); + Freezing_Trap_Timer = 30000; + }else Freezing_Trap_Timer -= diff; + + if(!m_creature->getVictim()->hasUnitState(UNIT_STAT_STUNDED | UNIT_STAT_ROOT | UNIT_STAT_CONFUSED | UNIT_STAT_DISTRACTED)) + DoMeleeAttackIfReady(); + }else + { + if(Concussive_Shot_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_CONCUSSIVE_SHOT); + Concussive_Shot_Timer = 8000; + }else Concussive_Shot_Timer -= diff; + + if(Multi_Shot_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_MULTI_SHOT); + Multi_Shot_Timer = 10000; + }else Multi_Shot_Timer -= diff; + + if(Aimed_Shot_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_AIMED_SHOT); + Aimed_Shot_Timer = 6000; + }else Aimed_Shot_Timer -= diff; + + if(Shoot_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_SHOOT); + Shoot_Timer = 2500; + }else Shoot_Timer -= diff; + } + } +}; + +/*void mob_sliverAI::JustDied(Unit* killer) +{ + if(Creature* Garaxxas = ((Creature*)Unit::GetUnit(*m_creature, GaraxxasGUID))) + ((boss_garaxxasAI*)Garaxxas->AI())->SliverGUID = 0; +} + +void mob_sliverAI::KilledUnit(Unit* victim) +{ + if(Creature* Garaxxas = ((Creature*)Unit::GetUnit(*m_creature, GaraxxasGUID))) + ((boss_garaxxasAI*)Garaxxas->AI())->KilledUnit(victim); +}*/ + +#define SPELL_WINDFURY_TOTEM 27621 +#define SPELL_WAR_STOMP 46026 +#define SPELL_PURGE 27626 +#define SPELL_LESSER_HEALING_WAVE 44256 +#define SPELL_FROST_SHOCK 21401 +#define SPELL_FIRE_NOVA_TOTEM 44257 +#define SPELL_EARTHBIND_TOTEM 15786 + +struct MANGOS_DLL_DECL boss_apokoAI : public boss_priestess_guestAI +{ + //Shaman + boss_apokoAI(Creature *c) : boss_priestess_guestAI(c) {} + + uint32 Totem_Timer; + uint8 Totem_Amount; + uint32 War_Stomp_Timer; + uint32 Purge_Timer; + uint32 Healing_Wave_Timer; + uint32 Frost_Shock_Timer; + + void Reset() + { + Totem_Timer = 2000; + Totem_Amount = 1; + War_Stomp_Timer = 10000; + Purge_Timer = 8000; + Healing_Wave_Timer = 5000; + Frost_Shock_Timer = 7000; + + boss_priestess_guestAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + boss_priestess_guestAI::UpdateAI(diff); + + if(Totem_Timer < diff) + { + switch(rand()%3) + { + case 0: + DoCast(m_creature, SPELL_WINDFURY_TOTEM); + break; + case 1: + DoCast(m_creature, SPELL_FIRE_NOVA_TOTEM); + break; + case 2: + DoCast(m_creature, SPELL_EARTHBIND_TOTEM); + break; + } + ++Totem_Amount; + Totem_Timer = Totem_Amount*2000; + }else Totem_Timer -= diff; + + if(War_Stomp_Timer < diff) + { + DoCast(m_creature, SPELL_WAR_STOMP); + War_Stomp_Timer = 10000; + }else War_Stomp_Timer -= diff; + + if(Purge_Timer < diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_PURGE); + Purge_Timer = 15000; + }else Purge_Timer -= diff; + + if(Frost_Shock_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_FROST_SHOCK); + Frost_Shock_Timer = 7000; + }else Frost_Shock_Timer -= diff; + + if(Healing_Wave_Timer < diff) + { + // std::vector::iterator itr = Group.begin() + rand()%Group.size(); + // uint64 guid = (*itr)->guid; + // if(guid) + // { + // Unit* pAdd = Unit::GetUnit(*m_creature, (*itr)->guid); + // if(pAdd && pAdd->isAlive()) + // { + DoCast(m_creature, SPELL_LESSER_HEALING_WAVE); + Healing_Wave_Timer = 5000; + // } + // } + }else Healing_Wave_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +#define SPELL_GOBLIN_DRAGON_GUN 44272 +#define SPELL_ROCKET_LAUNCH 44137 +#define SPELL_RECOMBOBULATE 44274 +#define SPELL_HIGH_EXPLOSIVE_SHEEP 44276 +#define SPELL_FEL_IRON_BOMB 46024 +#define SPELL_SHEEP_EXPLOSION 44279 + +#define CREATURE_EXPLOSIVE_SHEEP 24715 + +struct MANGOS_DLL_DECL boss_zelfanAI : public boss_priestess_guestAI +{ + //Engineer + boss_zelfanAI(Creature *c) : boss_priestess_guestAI(c) {} + + uint32 Goblin_Dragon_Gun_Timer; + uint32 Rocket_Launch_Timer; + uint32 Recombobulate_Timer; + uint32 High_Explosive_Sheep_Timer; + uint32 Fel_Iron_Bomb_Timer; + + void Reset() + { + Goblin_Dragon_Gun_Timer = 20000; + Rocket_Launch_Timer = 7000; + Recombobulate_Timer = 4000; + High_Explosive_Sheep_Timer = 10000; + Fel_Iron_Bomb_Timer = 15000; + + boss_priestess_guestAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + boss_priestess_guestAI::UpdateAI(diff); + + if(Goblin_Dragon_Gun_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_GOBLIN_DRAGON_GUN); + Goblin_Dragon_Gun_Timer = 10000; + }else Goblin_Dragon_Gun_Timer -= diff; + + if(Rocket_Launch_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_ROCKET_LAUNCH); + Rocket_Launch_Timer = 9000; + }else Rocket_Launch_Timer -= diff; + + if(Fel_Iron_Bomb_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_FEL_IRON_BOMB); + Fel_Iron_Bomb_Timer = 15000; + }else Fel_Iron_Bomb_Timer -= diff; + + if(Recombobulate_Timer < diff) + { + for(uint8 i = 0; i < Group.size(); ++i) + if(Unit* pAdd = Unit::GetUnit(*m_creature, Group[i]->guid)) + if(pAdd->IsPolymorphed()) + { + DoCast(pAdd, SPELL_RECOMBOBULATE); + break; + } + }else Recombobulate_Timer -= diff; + + if(High_Explosive_Sheep_Timer < diff) + { + DoCast(m_creature, SPELL_HIGH_EXPLOSIVE_SHEEP); + High_Explosive_Sheep_Timer = 65000; + }else High_Explosive_Sheep_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//struct MANGOS_DLL_DECL mob_high_explosive_sheepAI : public ScriptedAI +//{ +// mob_high_explosive_sheepAI(Creature *c) : ScriptedAI(c) {Reset();} +// +// uint32 Explosion_Timer; +// +// void Reset() +// { +// Explosion_Timer = 60000; +// } +// +// void JustDied(Unit *Killer){} +// +// void Aggro(Unit *who){} +// +// void UpdateAI(const uint32 diff) +// { +// if(Explosion_Timer < diff) +// { +// DoCast(m_creature->getVictim(), SPELL_SHEEP_EXPLOSION); +// }else +// Explosion_Timer -= diff; +// } +//}; + +/*CreatureAI* GetAI_mob_sliver(Creature *_Creature) +{ + return new mob_sliverAI (_Creature); +};*/ + +//CreatureAI* GetAI_mob_high_explosive_sheep(Creature *_Creature) +//{ +// return new mob_high_explosive_sheepAI (_Creature); +//}; + +/*CreatureAI* GetAI_mob_fizzle(Creature *_Creature) +{ + return new mob_fizzleAI (_Creature); +};*/ + +CreatureAI* GetAI_boss_priestess_delrissa(Creature *_Creature) +{ + return new boss_priestess_delrissaAI (_Creature); +} + +CreatureAI* GetAI_boss_kagani_nightstrike(Creature *_Creature) +{ + return new boss_kagani_nightstrikeAI (_Creature); +} + +CreatureAI* GetAI_ellris_duskhallow(Creature *_Creature) +{ + return new boss_ellris_duskhallowAI (_Creature); +} + +CreatureAI* GetAI_eramas_brightblaze(Creature *_Creature) +{ + return new boss_eramas_brightblazeAI (_Creature); +} + +CreatureAI* GetAI_yazzai(Creature *_Creature) +{ + return new boss_yazzaiAI (_Creature); +} + +CreatureAI* GetAI_warlord_salaris(Creature *_Creature) +{ + return new boss_warlord_salarisAI (_Creature); +} + +CreatureAI* GetAI_garaxxas(Creature *_Creature) +{ + return new boss_garaxxasAI (_Creature); +} + +CreatureAI* GetAI_apoko(Creature *_Creature) +{ + return new boss_apokoAI (_Creature); +} + +CreatureAI* GetAI_zelfan(Creature *_Creature) +{ + return new boss_zelfanAI (_Creature); +} + +void AddSC_boss_priestess_delrissa() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_priestess_delrissa"; + newscript->GetAI = GetAI_boss_priestess_delrissa; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_kagani_nightstrike"; + newscript->GetAI = GetAI_boss_kagani_nightstrike; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_ellris_duskhallow"; + newscript->GetAI = GetAI_ellris_duskhallow; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_eramas_brightblaze"; + newscript->GetAI = GetAI_eramas_brightblaze; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_yazzai"; + newscript->GetAI = GetAI_yazzai; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_warlord_salaris"; + newscript->GetAI = GetAI_warlord_salaris; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_garaxxas"; + newscript->GetAI = GetAI_garaxxas; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_apoko"; + newscript->GetAI = GetAI_apoko; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_zelfan"; + newscript->GetAI = GetAI_zelfan; + m_scripts[nrscripts++] = newscript; + + /*newscript = new Script; + newscript->Name="mob_high_explosive_sheep"; + newscript->GetAI = GetAI_mob_high_explosive_sheep; + m_scripts[nrscripts++] = newscript;*/ + + /*newscript = new Script; + newscript->Name="mob_fizzle"; + newscript->GetAI = GetAI_mob_fizzle; + m_scripts[nrscripts++] = newscript;*/ + + /*newscript = new Script; + newscript->Name="mob_sliver"; + newscript->GetAI = GetAI_mob_sliver; + m_scripts[nrscripts++] = newscript;*/ +} diff --git a/src/bindings/scripts/scripts/zone/magisters_terrace/boss_selin_fireheart.cpp b/src/bindings/scripts/scripts/zone/magisters_terrace/boss_selin_fireheart.cpp new file mode 100644 index 00000000000..76d4faed15f --- /dev/null +++ b/src/bindings/scripts/scripts/zone/magisters_terrace/boss_selin_fireheart.cpp @@ -0,0 +1,385 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Selin_Fireheart +SD%Complete: 99 +SDComment: Heroic and Normal Support. Needs further testing. +SDCategory: Magister's Terrace +EndScriptData */ + +#include "precompiled.h" +#include "def_magisters_terrace.h" + +#define SAY_AGGRO "You only waste my time!" +#define SOUND_AGGRO 12378 + +#define SAY_ENERGY "My hunger knows no bounds! " +#define SOUND_ENERGY 12381 + +#define SAY_EMPOWERED "Yes! I am a god!" +#define SOUND_EMPOWERED 12382 + +#define SAY_KILL_1 "Enough distractions!" +#define SOUND_KILL_1 12388 + +#define SAY_KILL_2 "I am invincible!" +#define SOUND_KILL_2 12385 + +#define SAY_DEATH "No! More... I must have more!" +#define SOUND_DEATH 12383 + +//Crystal efect spells +#define SPELL_FEL_CRYSTAL_COSMETIC 44374 +#define SPELL_FEL_CRYSTAL_DUMMY 44329 +#define SPELL_FEL_CRYSTAL_VISUAL 44355 +#define SPELL_MANA_RAGE 44320 // This spell triggers 44321, which changes scale and regens mana Requires an entry in spell_script_target + +//Selin's spells +#define SPELL_DRAIN_LIFE 44294 +#define SPELL_FEL_EXPLOSION 44314 + +#define SPELL_DRAIN_MANA 46153 // Heroic only + +#define CRYSTALS_NUMBER 5 +#define DATA_CRYSTALS 6 + +#define CREATURE_FEL_CRYSTAL 24722 + +struct MANGOS_DLL_DECL boss_selin_fireheartAI : public ScriptedAI +{ + boss_selin_fireheartAI(Creature* c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + + Crystals.clear(); + // GUIDs per instance is static, so we only need to load them once. + if(pInstance) + { + uint32 size = pInstance->GetData(DATA_FEL_CRYSTAL_SIZE); + for(uint8 i = 0; i < size; ++i) + { + uint64 guid = pInstance->GetData64(DATA_FEL_CRYSTAL); + outstring_log("Selin: Adding Fel Crystal %u to list", guid); + Crystals.push_back(guid); + } + } + Reset(); + Heroic = c->GetMap()->IsHeroic() ? true : false; + } + + ScriptedInstance* pInstance; + + std::list Crystals; + + uint32 DrainLifeTimer; + uint32 DrainManaTimer; + uint32 FelExplosionTimer; + uint32 DrainCrystalTimer; + uint32 EmpowerTimer; + + bool IsDraining; + bool DrainingCrystal; + bool Heroic; + uint64 CrystalGUID; // This will help us create a pointer to the crystal we are draining. We store GUIDs, never units in case unit is deleted/offline (offline if player of course). + + void Reset() + { + if(pInstance) + { + //for(uint8 i = 0; i < CRYSTALS_NUMBER; ++i) + for(std::list::iterator itr = Crystals.begin(); itr != Crystals.end(); ++itr) + { + //Unit* pUnit = Unit::GetUnit(*m_creature, FelCrystals[i]); + Unit* pUnit = Unit::GetUnit(*m_creature, *itr); + if(pUnit) + { + if(!pUnit->isAlive()) + ((Creature*)pUnit)->Respawn(); // Let MaNGOS handle setting death state, etc. + + // Only need to set unselectable flag. You can't attack unselectable units so non_attackable flag is not necessary here. + pUnit->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + } + + GameObject* Door = GameObject::GetGameObject(*m_creature, pInstance->GetData64(DATA_SELIN_ENCOUNTER_DOOR)); + if(Door) + Door->SetGoState(0); // Close the door. Open it only in JustDied. + + // Set Inst data for encounter + pInstance->SetData(DATA_SELIN_EVENT, NOT_STARTED); + }else error_log(ERROR_INST_DATA); + + DrainLifeTimer = 3000 + rand()%4000; + DrainManaTimer = DrainLifeTimer + 5000; + FelExplosionTimer = 2100; + DrainCrystalTimer = 10000 + rand()%5000; + DrainCrystalTimer = 20000 + rand()%5000; + EmpowerTimer = 10000; + + IsDraining = false; + DrainingCrystal = false; + CrystalGUID = 0; + } + + void SelectNearestCrystal() + { + if(Crystals.empty()) + return; + + float ShortestDistance = 0; + CrystalGUID = 0; + Unit* pCrystal = NULL; + Unit* CrystalChosen = NULL; + //for(uint8 i = 0; i < CRYSTALS_NUMBER; ++i) + for(std::list::iterator itr = Crystals.begin(); itr != Crystals.end(); ++itr) + { + pCrystal = NULL; + //pCrystal = Unit::GetUnit(*m_creature, FelCrystals[i]); + pCrystal = Unit::GetUnit(*m_creature, *itr); + if(pCrystal && pCrystal->isAlive()) + { + if(!ShortestDistance || (ShortestDistance > m_creature->GetDistance2d(pCrystal))) + { + ShortestDistance = m_creature->GetDistance2d(pCrystal); + CrystalGUID = pCrystal->GetGUID(); + CrystalChosen = pCrystal; // Store a copy of pCrystal so we don't need to recreate a pointer to closest crystal for the movement and yell. + } + } + } + if(CrystalChosen) + { + DoYell(SAY_ENERGY, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_ENERGY); + CrystalChosen->CastSpell(CrystalChosen, SPELL_FEL_CRYSTAL_COSMETIC, true); + + float x, y, z; // coords that we move to, close to the crystal. + CrystalChosen->GetClosePoint(x, y, z, m_creature->GetObjectSize(), CONTACT_DISTANCE); + + m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + m_creature->GetMotionMaster()->MovePoint(1, x, y, z); + DrainingCrystal = true; + } + } + + void ShatterRemainingCrystals() + { + if(Crystals.empty()) + return; + + //for(uint8 i = 0; i < CRYSTALS_NUMBER; ++i) + for(std::list::iterator itr = Crystals.begin(); itr != Crystals.end(); ++itr) + { + //Creature* pCrystal = ((Creature*)Unit::GetUnit(*m_creature, FelCrystals[i])); + Creature* pCrystal = ((Creature*)Unit::GetUnit(*m_creature, *itr)); + if(pCrystal && pCrystal->isAlive()) + pCrystal->DealDamage(pCrystal, pCrystal->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + + void Aggro(Unit* who) + { + DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO); + } + + void KilledUnit(Unit* victim) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_KILL_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_KILL_1); + break; + case 1: + DoYell(SAY_KILL_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_KILL_2); + break; + } + } + + void MovementInform(uint32 type, uint32 id) + { + if(type == POINT_MOTION_TYPE && id == 1) + { + Unit* CrystalChosen = Unit::GetUnit(*m_creature, CrystalGUID); + if(CrystalChosen && CrystalChosen->isAlive()) + { + // Make the crystal attackable + // We also remove NON_ATTACKABLE in case the database has it set. + CrystalChosen->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); + CrystalChosen->CastSpell(m_creature, SPELL_MANA_RAGE, true); + IsDraining = true; + } + else + { + // Make an error message in case something weird happened here + error_log("SD2: Selin Fireheart unable to drain crystal as the crystal is either dead or despawned"); + DrainingCrystal = false; + } + } + } + + void JustDied(Unit* killer) + { + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_DEATH); + + if(!pInstance) + { + error_log(ERROR_INST_DATA); + return; + } + + pInstance->SetData(DATA_SELIN_EVENT, DONE); // Encounter complete! + GameObject* EncounterDoor = GameObject::GetGameObject((*m_creature), pInstance->GetData64(DATA_SELIN_ENCOUNTER_DOOR)); + if(EncounterDoor) + EncounterDoor->SetGoState(1); // Open the door + + ShatterRemainingCrystals(); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(!DrainingCrystal) + { + uint32 maxPowerMana = m_creature->GetMaxPower(POWER_MANA); + if( maxPowerMana && ((m_creature->GetPower(POWER_MANA)*100 / maxPowerMana) < 10) ) + { + if( DrainLifeTimer < diff ) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_DRAIN_LIFE); + DrainLifeTimer = 10000; + }else DrainLifeTimer -= diff; + + // Heroic only + if( Heroic ) + { + if( DrainManaTimer < diff ) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_DRAIN_MANA); + DrainManaTimer = 10000; + }else DrainManaTimer -= diff; + } + } + + if( FelExplosionTimer < diff ) + { + if(!m_creature->IsNonMeleeSpellCasted(false)) + { + DoCast(m_creature, SPELL_FEL_EXPLOSION); + FelExplosionTimer = 2000; + } + }else FelExplosionTimer -= diff; + + // If below 10% mana, start recharging + maxPowerMana = m_creature->GetMaxPower(POWER_MANA); + if( maxPowerMana && ((m_creature->GetPower(POWER_MANA)*100 / maxPowerMana) < 10) ) + { + if(DrainCrystalTimer < diff) + { + SelectNearestCrystal(); + if(Heroic) DrainCrystalTimer = 10000 + rand()%5000; + else DrainCrystalTimer = 20000 + rand()%5000; + }else DrainCrystalTimer -= diff; + } + + }else + { + if(IsDraining) + if(EmpowerTimer < diff) + { + IsDraining = false; + DrainingCrystal = false; + DoYell(SAY_EMPOWERED, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_EMPOWERED); + Unit* CrystalChosen = Unit::GetUnit(*m_creature, CrystalGUID); + if(CrystalChosen && CrystalChosen->isAlive()) + // Use Deal Damage to kill it, not setDeathState. + CrystalChosen->DealDamage(CrystalChosen, CrystalChosen->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + + CrystalGUID = 0; + + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + }else EmpowerTimer -= diff; + } + + DoMeleeAttackIfReady(); // No need to check if we are draining crystal here, as the spell has a stun. + } +}; + +CreatureAI* GetAI_boss_selin_fireheart(Creature *_Creature) +{ + return new boss_selin_fireheartAI (_Creature); +}; + +struct MANGOS_DLL_DECL mob_fel_crystalAI : public ScriptedAI +{ + mob_fel_crystalAI(Creature *c) : ScriptedAI(c) { Reset(); } + + void Reset() {} + void Aggro(Unit* who) {} + void AttackStart(Unit* who) {} + void MoveInLineOfSight(Unit* who) {} + void UpdateAI(const uint32 diff) {} + + void JustDied(Unit* killer) + { + if(ScriptedInstance* pInstance = ((ScriptedInstance*)m_creature->GetInstanceData())) + { + Creature* Selin = ((Creature*)Unit::GetUnit(*m_creature, pInstance->GetData64(DATA_SELIN))); + if(Selin && Selin->isAlive()) + { + if(((boss_selin_fireheartAI*)Selin->AI())->CrystalGUID == m_creature->GetGUID()) + { + // Set this to false if we are the creature that Selin is draining so his AI flows properly + ((boss_selin_fireheartAI*)Selin->AI())->DrainingCrystal = false; + ((boss_selin_fireheartAI*)Selin->AI())->IsDraining = false; + ((boss_selin_fireheartAI*)Selin->AI())->EmpowerTimer = 10000; + if(Selin->getVictim()) + { + Selin->AI()->AttackStart(Selin->getVictim()); + Selin->GetMotionMaster()->MoveChase(Selin->getVictim()); + } + } + } + }else error_log(ERROR_INST_DATA); + } +}; + +CreatureAI* GetAI_mob_fel_crystal(Creature *_Creature) +{ + return new mob_fel_crystalAI (_Creature); +}; + +void AddSC_boss_selin_fireheart() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_selin_fireheart"; + newscript->GetAI = GetAI_boss_selin_fireheart; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_fel_crystal"; + newscript->GetAI = GetAI_mob_fel_crystal; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/magisters_terrace/boss_vexallus.cpp b/src/bindings/scripts/scripts/zone/magisters_terrace/boss_vexallus.cpp new file mode 100644 index 00000000000..e815bde5cf2 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/magisters_terrace/boss_vexallus.cpp @@ -0,0 +1,233 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Vexallus +SD%Complete: 90 +SDComment: Heroic and Normal support. Needs further testing. +SDCategory: Magister's Terrace +EndScriptData */ + +#include "precompiled.h" +#include "def_magisters_terrace.h" + +#define SAY_AGGRO "Drain...life..." +#define SOUND_AGGRO 12389 + +#define SAY_ENERGY "Un...con...tainable." +#define SOUND_ENERGY 12392 + +#define SAY_OVERLOAD "Un...leash..." +#define SOUND_OVERLOAD 12390 + +#define SAY_KILL "Con...sume." +#define SOUND_KILL 12393 + +#define SAY_DEATH "What...happen...ed." + +//Pure energy spell info +#define SPELL_ENERGY_BOLT 44342 +#define SPELL_ENERGY_FEEDBACK 44335 + +//Vexallus spell info +#define SPELL_CHAIN_LIGHTNING 44318 +#define SPELL_SUMMON_PURE_ENERGY 44322 //not-working, this script summon this creatures without this spell +#define SPELL_OVERLOAD 44353 +#define SPELL_ARCANE_SHOCK 44319 + +//Creatures +#define CREATURE_PURE_ENERGY 24745 + +struct MANGOS_DLL_DECL boss_vexallusAI : public ScriptedAI +{ + boss_vexallusAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + Heroic = c->GetMap()->IsHeroic() ? true : false; + } + + ScriptedInstance* pInstance; + + uint32 ChainLightningTimer; + uint32 ArcaneShockTimer; + uint32 OverloadTimer; + uint32 SpawnAddInterval; + uint32 AlreadySpawnedAmount; + bool Enraged; + bool Heroic; + + void Reset() + { + ChainLightningTimer = 10000; + ArcaneShockTimer = 8000; + OverloadTimer = 2200; + SpawnAddInterval = 15; + AlreadySpawnedAmount = 0; + + Enraged = false; + + if(pInstance) + pInstance->SetData(DATA_VEXALLUS_EVENT, NOT_STARTED); + } + + void KilledUnit(Unit *victim) + { + DoYell(SAY_KILL, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(victim, SOUND_KILL); + } + + void JustDied(Unit *victim) + { + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + if (pInstance) + { + pInstance->SetData(DATA_VEXALLUS_EVENT, DONE); + + GameObject* Door = NULL; + Door = GameObject::GetGameObject((*m_creature), pInstance->GetData64(DATA_VEXALLUS_DOOR)); + if(Door) + Door->SetGoState(0); + } + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO); + if (pInstance) + pInstance->SetData(DATA_VEXALLUS_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if(m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 11) + { + Enraged = true; + } + + if(!Enraged) + { + //used for check, when Vexallus cast adds 85%, 70%, 55%, 40%, 25% + if ((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < (100-(SpawnAddInterval*(AlreadySpawnedAmount+1)))) + { + DoYell(SAY_ENERGY, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_ENERGY); + Creature* PureEnergyCreature = NULL; + PureEnergyCreature = DoSpawnCreature(CREATURE_PURE_ENERGY, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (PureEnergyCreature && target) + PureEnergyCreature->AI()->AttackStart(target); + + if(Heroic) // *Heroic mode only - he summons two instead of one. + { + PureEnergyCreature = DoSpawnCreature(CREATURE_PURE_ENERGY, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (PureEnergyCreature && target) + PureEnergyCreature->AI()->AttackStart(target); + } + + ++AlreadySpawnedAmount; + }; + + if(ChainLightningTimer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + DoCast(target, SPELL_CHAIN_LIGHTNING); + ChainLightningTimer = 10000; + }else ChainLightningTimer -= diff; + + if(ArcaneShockTimer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + DoCast(target, SPELL_ARCANE_SHOCK); + ArcaneShockTimer = 8000; + }else ArcaneShockTimer -= diff; + }else + { + if(OverloadTimer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + DoCast(target, SPELL_OVERLOAD); + OverloadTimer = 2200; + }else OverloadTimer -= diff; + } + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_vexallus(Creature *_Creature) +{ + return new boss_vexallusAI (_Creature); +}; + +struct MANGOS_DLL_DECL mob_pure_energyAI : public ScriptedAI +{ + mob_pure_energyAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 EnergyBoltTimer; + + void Reset() + { + EnergyBoltTimer = 1700; + } + + void JustDied(Unit* slayer) + { + slayer->CastSpell(slayer, SPELL_ENERGY_FEEDBACK, true, 0, 0, m_creature->GetGUID()); + } + + void Aggro(Unit *who){} + + void UpdateAI(const uint32 diff) + { + if(!m_creature->getVictim() || !m_creature->SelectHostilTarget()) + return; + + if(EnergyBoltTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_ENERGY_BOLT); + EnergyBoltTimer = 1700; + }else EnergyBoltTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_pure_energy(Creature *_Creature) +{ + return new mob_pure_energyAI (_Creature); +}; + +void AddSC_boss_vexallus() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_vexallus"; + newscript->GetAI = GetAI_boss_vexallus; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_pure_energy"; + newscript->GetAI = GetAI_mob_pure_energy; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/magisters_terrace/def_magisters_terrace.h b/src/bindings/scripts/scripts/zone/magisters_terrace/def_magisters_terrace.h new file mode 100644 index 00000000000..d064a50cc13 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/magisters_terrace/def_magisters_terrace.h @@ -0,0 +1,29 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_MAGISTERS_TERRACE_H +#define DEF_MAGISTERS_TERRACE_H + +#define DATA_SELIN_EVENT 1 +#define DATA_VEXALLUS_EVENT 2 +#define DATA_DELRISSA_EVENT 3 +#define DATA_KAELTHAS_EVENT 4 + +#define DATA_SELIN 5 +#define DATA_FEL_CRYSTAL 6 +#define DATA_FEL_CRYSTAL_SIZE 7 + +#define DATA_VEXALLUS_DOOR 8 +#define DATA_SELIN_DOOR 9 +#define DATA_DELRISSA 10 +#define DATA_DELRISSA_DOOR 11 +#define DATA_SELIN_ENCOUNTER_DOOR 12 + +#define DATA_KAEL_STATUE_LEFT 13 +#define DATA_KAEL_STATUE_RIGHT 14 + +#define DATA_DELRISSA_DEATH_COUNT 15 + +#define ERROR_INST_DATA "SD2 Error: Instance Data not set properly for Magister's Terrace instance (map 585). Encounters will be buggy." +#endif diff --git a/src/bindings/scripts/scripts/zone/magisters_terrace/instance_magisters_terrace.cpp b/src/bindings/scripts/scripts/zone/magisters_terrace/instance_magisters_terrace.cpp new file mode 100644 index 00000000000..39efb41ebbb --- /dev/null +++ b/src/bindings/scripts/scripts/zone/magisters_terrace/instance_magisters_terrace.cpp @@ -0,0 +1,195 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Magisters_Terrace +SD%Complete: 100 +SDComment: Designed only for Selin Fireheart +SDCategory: Magister's Terrace +EndScriptData */ + +#include "precompiled.h" +#include "def_magisters_terrace.h" + +#define NUMBER_OF_ENCOUNTERS 4 + +/* +0 - Selin Fireheart +1 - Vexallus +2 - Priestess Delrissa +3 - Kael'thas Sunstrider +*/ + +struct MANGOS_DLL_DECL instance_magisters_terrace : public ScriptedInstance +{ + instance_magisters_terrace(Map* map) : ScriptedInstance(map) + { + Initialize(); + } + + uint32 Encounters[NUMBER_OF_ENCOUNTERS]; + uint32 DelrissaDeathCount; + + std::list FelCrystals; + std::list::iterator CrystalItr; + + uint64 SelinGUID; + uint64 DelrissaGUID; + uint64 VexallusDoorGUID; + uint64 SelinDoorGUID; + uint64 SelinEncounterDoorGUID; + uint64 DelrissaDoorGUID; + uint64 KaelStatue[2]; + + bool InitializedItr; + + void Initialize() + { + for(uint8 i = 0; i < NUMBER_OF_ENCOUNTERS; i++) + Encounters[i] = NOT_STARTED; + + FelCrystals.clear(); + + DelrissaDeathCount = 0; + + SelinGUID = 0; + DelrissaGUID = 0; + VexallusDoorGUID = 0; + SelinDoorGUID = 0; + SelinEncounterDoorGUID = 0; + DelrissaDoorGUID = 0; + KaelStatue[0] = 0; + KaelStatue[1] = 0; + + InitializedItr = false; + } + + bool IsEncounterInProgress() const + { + for(uint8 i = 0; i < NUMBER_OF_ENCOUNTERS; i++) + if(Encounters[i] == IN_PROGRESS) + return true; + return false; + } + + uint32 GetData(uint32 identifier) + { + switch(identifier) + { + case DATA_SELIN_EVENT: return Encounters[0]; + case DATA_VEXALLUS_EVENT: return Encounters[1]; + case DATA_DELRISSA_EVENT: return Encounters[2]; + case DATA_KAELTHAS_EVENT: return Encounters[3]; + case DATA_DELRISSA_DEATH_COUNT: return DelrissaDeathCount; + case DATA_FEL_CRYSTAL_SIZE: return FelCrystals.size(); + } + return 0; + } + + void SetData(uint32 identifier, uint32 data) + { + switch(identifier) + { + case DATA_SELIN_EVENT: Encounters[0] = data; break; + case DATA_VEXALLUS_EVENT: Encounters[1] = data; break; + case DATA_DELRISSA_EVENT: Encounters[2] = data; break; + case DATA_KAELTHAS_EVENT: Encounters[3] = data; break; + + case DATA_DELRISSA_DEATH_COUNT: + if(data) ++DelrissaDeathCount; + else DelrissaDeathCount = 0; + } + } + + void OnCreatureCreate(Creature *creature, uint32 entry) + { + switch(entry) + { + case 24723: + SelinGUID = creature->GetGUID(); + break; + case 24560: + DelrissaGUID = creature->GetGUID(); + break; + case 24722: + FelCrystals.push_back(creature->GetGUID()); + break; + } + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_SELIN: return SelinGUID; + case DATA_DELRISSA: return DelrissaGUID; + case DATA_VEXALLUS_DOOR: return VexallusDoorGUID; + case DATA_SELIN_DOOR: return SelinDoorGUID; + case DATA_SELIN_ENCOUNTER_DOOR: return SelinEncounterDoorGUID; + case DATA_DELRISSA_DOOR: return DelrissaDoorGUID; + case DATA_KAEL_STATUE_LEFT: return KaelStatue[0]; + case DATA_KAEL_STATUE_RIGHT: return KaelStatue[1]; + + case DATA_FEL_CRYSTAL: + { + if(FelCrystals.empty()) + { + error_log("SD2: Magisters Terrace: No Fel Crystals loaded in Inst Data"); + return 0; + } + + if(!InitializedItr) + { + CrystalItr = FelCrystals.begin(); + InitializedItr = true; + } + + uint64 guid = *CrystalItr; + ++CrystalItr; + return guid; + } + } + return 0; + } + + void OnObjectCreate(GameObject* go) + { + switch(go->GetEntry()) + { + case 187896: VexallusDoorGUID = go->GetGUID(); break; + case 187979: SelinDoorGUID = go->GetGUID(); break; + case 188118: SelinEncounterDoorGUID = go->GetGUID(); break; + case 187770: DelrissaDoorGUID = go->GetGUID(); break; + case 188165: KaelStatue[0] = go->GetGUID(); break; + case 188166: KaelStatue[1] = go->GetGUID(); break; + } + } +}; + +InstanceData* GetInstanceData_instance_magisters_terrace(Map* map) +{ + return new instance_magisters_terrace(map); +} + +void AddSC_instance_magisters_terrace() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "instance_magisters_terrace"; + newscript->GetInstanceData = GetInstanceData_instance_magisters_terrace; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/maraudon/boss_celebras_the_cursed.cpp b/src/bindings/scripts/scripts/zone/maraudon/boss_celebras_the_cursed.cpp new file mode 100644 index 00000000000..6f3b92f5e5b --- /dev/null +++ b/src/bindings/scripts/scripts/zone/maraudon/boss_celebras_the_cursed.cpp @@ -0,0 +1,97 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Celebras_the_Cursed +SD%Complete: 100 +SDComment: +SDCategory: Maraudon +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_WRATH 21807 +#define SPELL_ENTANGLINGROOTS 12747 +#define SPELL_CORRUPT_FORCES 21968 + +struct MANGOS_DLL_DECL celebras_the_cursedAI : public ScriptedAI +{ + celebras_the_cursedAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Wrath_Timer; + uint32 EntanglingRoots_Timer; + uint32 CorruptForces_Timer; + + void Reset() + { + Wrath_Timer = 8000; + EntanglingRoots_Timer = 2000; + CorruptForces_Timer = 30000; + } + + void Aggro(Unit *who) { } + + void JustDied(Unit* Killer) + { + m_creature->SummonCreature(13716, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 600000); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //Wrath + if (Wrath_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if( target ) + DoCast(target,SPELL_WRATH); + Wrath_Timer = 8000; + }else Wrath_Timer -= diff; + + //EntanglingRoots + if (EntanglingRoots_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_ENTANGLINGROOTS); + EntanglingRoots_Timer = 20000; + }else EntanglingRoots_Timer -= diff; + + //CorruptForces + if (CorruptForces_Timer < diff) + { + m_creature->InterruptNonMeleeSpells(false); + DoCast(m_creature,SPELL_CORRUPT_FORCES); + CorruptForces_Timer = 20000; + }else CorruptForces_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_celebras_the_cursed(Creature *_Creature) +{ + return new celebras_the_cursedAI (_Creature); +} + +void AddSC_boss_celebras_the_cursed() +{ + Script *newscript; + newscript = new Script; + newscript->Name="celebras_the_cursed"; + newscript->GetAI = GetAI_celebras_the_cursed; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/maraudon/boss_landslide.cpp b/src/bindings/scripts/scripts/zone/maraudon/boss_landslide.cpp new file mode 100644 index 00000000000..466f35dbba7 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/maraudon/boss_landslide.cpp @@ -0,0 +1,94 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Landslide +SD%Complete: 100 +SDComment: +SDCategory: Maraudon +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_KNOCKAWAY 18670 +#define SPELL_TRAMPLE 5568 +#define SPELL_LANDSLIDE 21808 + +struct MANGOS_DLL_DECL boss_landslideAI : public ScriptedAI +{ + boss_landslideAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 KnockAway_Timer; + uint32 Trample_Timer; + uint32 Landslide_Timer; + + void Reset() + { + KnockAway_Timer = 8000; + Trample_Timer = 2000; + Landslide_Timer = 0; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //KnockAway_Timer + if (KnockAway_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_KNOCKAWAY); + KnockAway_Timer = 15000; + }else KnockAway_Timer -= diff; + + //Trample_Timer + if (Trample_Timer < diff) + { + DoCast(m_creature,SPELL_TRAMPLE); + Trample_Timer = 8000; + }else Trample_Timer -= diff; + + //Landslide + if ( m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 50 ) + { + if (Landslide_Timer < diff) + { + m_creature->InterruptNonMeleeSpells(false); + DoCast(m_creature,SPELL_LANDSLIDE); + Landslide_Timer = 60000; + } else Landslide_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_landslide(Creature *_Creature) +{ + return new boss_landslideAI (_Creature); +} + +void AddSC_boss_landslide() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_landslide"; + newscript->GetAI = GetAI_boss_landslide; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/maraudon/boss_noxxion.cpp b/src/bindings/scripts/scripts/zone/maraudon/boss_noxxion.cpp new file mode 100644 index 00000000000..b7bd6cc62fb --- /dev/null +++ b/src/bindings/scripts/scripts/zone/maraudon/boss_noxxion.cpp @@ -0,0 +1,149 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Noxxion +SD%Complete: 100 +SDComment: +SDCategory: Maraudon +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_TOXICVOLLEY 21687 +#define SPELL_UPPERCUT 22916 + +struct MANGOS_DLL_DECL boss_noxxionAI : public ScriptedAI +{ + boss_noxxionAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 ToxicVolley_Timer; + uint32 Uppercut_Timer; + uint32 Adds_Timer; + uint32 Invisible_Timer; + bool Invisible; + int Rand; + int RandX; + int RandY; + Creature* Summoned; + + void Reset() + { + ToxicVolley_Timer = 7000; + Uppercut_Timer = 16000; + Adds_Timer = 19000; + Invisible_Timer = 15000; //Too much too low? + Invisible = false; + } + + void Aggro(Unit *who) + { + } + + void SummonAdds(Unit* victim) + { + Rand = rand()%8; + switch (rand()%2) + { + case 0: RandX = 0 - Rand; break; + case 1: RandX = 0 + Rand; break; + } + Rand = 0; + Rand = rand()%8; + switch (rand()%2) + { + case 0: RandY = 0 - Rand; break; + case 1: RandY = 0 + Rand; break; + } + Rand = 0; + Summoned = DoSpawnCreature(13456, RandX, RandY, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 90000); + if(Summoned) + ((CreatureAI*)Summoned->AI())->AttackStart(victim); + } + + void UpdateAI(const uint32 diff) + { + if (Invisible && Invisible_Timer < diff) + { + //Become visible again + m_creature->setFaction(14); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + //Noxxion model + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID,11172); + Invisible = false; + //m_creature->m_canMove = true; + } else if (Invisible) + { + Invisible_Timer -= diff; + //Do nothing while invisible + return; + } + + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //ToxicVolley_Timer + if (ToxicVolley_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_TOXICVOLLEY); + ToxicVolley_Timer = 9000; + }else ToxicVolley_Timer -= diff; + + //Uppercut_Timer + if (Uppercut_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_UPPERCUT); + Uppercut_Timer = 12000; + }else Uppercut_Timer -= diff; + + //Adds_Timer + if (!Invisible && Adds_Timer < diff) + { + //Inturrupt any spell casting + //m_creature->m_canMove = true; + m_creature->InterruptNonMeleeSpells(false); + m_creature->setFaction(35); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + // Invisible Model + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID,11686); + SummonAdds(m_creature->getVictim()); + SummonAdds(m_creature->getVictim()); + SummonAdds(m_creature->getVictim()); + SummonAdds(m_creature->getVictim()); + SummonAdds(m_creature->getVictim()); + Invisible = true; + Invisible_Timer = 15000; + + Adds_Timer = 40000; + }else Adds_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_noxxion(Creature *_Creature) +{ + return new boss_noxxionAI (_Creature); +} + +void AddSC_boss_noxxion() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_noxxion"; + newscript->GetAI = GetAI_boss_noxxion; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/maraudon/boss_princess_theradras.cpp b/src/bindings/scripts/scripts/zone/maraudon/boss_princess_theradras.cpp new file mode 100644 index 00000000000..64215234ee5 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/maraudon/boss_princess_theradras.cpp @@ -0,0 +1,108 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Princess_Theradras +SD%Complete: 100 +SDComment: +SDCategory: Maraudon +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_DUSTFIELD 21909 +#define SPELL_BOULDER 21832 +#define SPELL_THRASH 3391 +#define SPELL_REPULSIVEGAZE 21869 + +struct MANGOS_DLL_DECL boss_ptheradrasAI : public ScriptedAI +{ + boss_ptheradrasAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Dustfield_Timer; + uint32 Boulder_Timer; + uint32 Thrash_Timer; + uint32 RepulsiveGaze_Timer; + + void Reset() + { + Dustfield_Timer = 8000; + Boulder_Timer = 2000; + Thrash_Timer = 5000; + RepulsiveGaze_Timer = 23000; + } + + void Aggro(Unit *who) + { + } + + void JustDied(Unit* Killer) + { + m_creature->SummonCreature(12238,28.067,61.875,-123.405,4.67,TEMPSUMMON_TIMED_DESPAWN,600000); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //Dustfield_Timer + if (Dustfield_Timer < diff) + { + DoCast(m_creature,SPELL_DUSTFIELD); + Dustfield_Timer = 14000; + }else Dustfield_Timer -= diff; + + //Boulder_Timer + if (Boulder_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if( target ) + DoCast(target,SPELL_BOULDER); + Boulder_Timer = 10000; + }else Boulder_Timer -= diff; + + //RepulsiveGaze_Timer + if (RepulsiveGaze_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_REPULSIVEGAZE); + RepulsiveGaze_Timer = 20000; + }else RepulsiveGaze_Timer -= diff; + + //Thrash_Timer + if (Thrash_Timer < diff) + { + DoCast(m_creature,SPELL_THRASH); + Thrash_Timer = 18000; + }else Thrash_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_ptheradras(Creature *_Creature) +{ + return new boss_ptheradrasAI (_Creature); +} + +void AddSC_boss_ptheradras() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_princess_theradras"; + newscript->GetAI = GetAI_boss_ptheradras; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/molten_core/boss_baron_geddon.cpp b/src/bindings/scripts/scripts/zone/molten_core/boss_baron_geddon.cpp new file mode 100644 index 00000000000..075ec15da19 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/molten_core/boss_baron_geddon.cpp @@ -0,0 +1,105 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Baron_Geddon +SD%Complete: 100 +SDComment: +SDCategory: Molten Core +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_INFERNO 19695 +#define SPELL_IGNITEMANA 19659 +#define SPELL_LIVINGBOMB 20475 +#define SPELL_ARMAGEDDOM 20479 + +struct MANGOS_DLL_DECL boss_baron_geddonAI : public ScriptedAI +{ + boss_baron_geddonAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Inferno_Timer; + uint32 IgniteMana_Timer; + uint32 LivingBomb_Timer; + + void Reset() + { + Inferno_Timer = 45000; //These times are probably wrong + IgniteMana_Timer = 30000; + LivingBomb_Timer = 35000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //If we are <2% hp cast Armageddom + if ( m_creature->GetHealth()*100 / m_creature->GetMaxHealth() <= 2 && !m_creature->IsNonMeleeSpellCasted(false)) + { + DoCast(m_creature,SPELL_ARMAGEDDOM); + DoTextEmote("performs one last service for Ragnaros.",NULL); + return; + } + + //Inferno_Timer + if (Inferno_Timer < diff) + { + DoCast(m_creature,SPELL_INFERNO); + Inferno_Timer = 45000; + }else Inferno_Timer -= diff; + + //IgniteMana_Timer + if (IgniteMana_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) DoCast(target,SPELL_IGNITEMANA); + + IgniteMana_Timer = 30000; + }else IgniteMana_Timer -= diff; + + //LivingBomb_Timer + if (LivingBomb_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) DoCast(target,SPELL_LIVINGBOMB); + + LivingBomb_Timer = 35000; + }else LivingBomb_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_baron_geddon(Creature *_Creature) +{ + return new boss_baron_geddonAI (_Creature); +} + +void AddSC_boss_baron_geddon() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_baron_geddon"; + newscript->GetAI = GetAI_boss_baron_geddon; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/molten_core/boss_garr.cpp b/src/bindings/scripts/scripts/zone/molten_core/boss_garr.cpp new file mode 100644 index 00000000000..82696672654 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/molten_core/boss_garr.cpp @@ -0,0 +1,168 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Garr +SD%Complete: 50 +SDComment: Adds NYI +SDCategory: Molten Core +EndScriptData */ + +#include "precompiled.h" + +// Garr spells +#define SPELL_ANTIMAGICPULSE 19492 +#define SPELL_MAGMASHACKLES 19496 +#define SPELL_ENRAGE 19516 //Stacking enrage (stacks to 10 times) + +//Add spells +#define SPELL_ERUPTION 19497 +#define SPELL_IMMOLATE 20294 + +struct MANGOS_DLL_DECL boss_garrAI : public ScriptedAI +{ + boss_garrAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 AntiMagicPulse_Timer; + uint32 MagmaShackles_Timer; + uint32 CheckAdds_Timer; + uint64 Add[8]; + bool Enraged[8]; + + void Reset() + { + AntiMagicPulse_Timer = 25000; //These times are probably wrong + MagmaShackles_Timer = 15000; + CheckAdds_Timer = 2000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //AntiMagicPulse_Timer + if (AntiMagicPulse_Timer < diff) + { + DoCast(m_creature,SPELL_ANTIMAGICPULSE); + AntiMagicPulse_Timer = 10000 + rand()%5000; + }else AntiMagicPulse_Timer -= diff; + + //MagmaShackles_Timer + if (MagmaShackles_Timer < diff) + { + DoCast(m_creature,SPELL_MAGMASHACKLES); + MagmaShackles_Timer = 8000 + rand()%4000; + }else MagmaShackles_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL mob_fireswornAI : public ScriptedAI +{ + mob_fireswornAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Immolate_Timer; + + void Reset() + { + Immolate_Timer = 4000; //These times are probably wrong + + //m_creature->RemoveAllAuras(); + //m_creature->DeleteThreatList(); + //m_creature->CombatStop(); + //DoGoHome(); + } + + void Aggro(Unit *who) + { + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || m_creature->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + float attackRadius = m_creature->GetAttackDistance(who); + if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) + { + if(who->HasStealthAura()) + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + DoStartAttackAndMovement(who); + + } + } + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //Immolate_Timer + if (Immolate_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) + DoCast(target,SPELL_IMMOLATE); + + Immolate_Timer = 5000 + rand()%5000; + }else Immolate_Timer -= diff; + + //Cast Erruption and let them die + if (m_creature->GetHealth() <= m_creature->GetMaxHealth() * 0.10) + { + DoCast(m_creature->getVictim(),SPELL_ERUPTION); + m_creature->setDeathState(JUST_DIED); + m_creature->RemoveCorpse(); + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_garr(Creature *_Creature) +{ + return new boss_garrAI (_Creature); +} + +CreatureAI* GetAI_mob_firesworn(Creature *_Creature) +{ + return new mob_fireswornAI (_Creature); +} + +void AddSC_boss_garr() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_garr"; + newscript->GetAI = GetAI_boss_garr; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_firesworn"; + newscript->GetAI = GetAI_mob_firesworn; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/molten_core/boss_gehennas.cpp b/src/bindings/scripts/scripts/zone/molten_core/boss_gehennas.cpp new file mode 100644 index 00000000000..96c02e77ea1 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/molten_core/boss_gehennas.cpp @@ -0,0 +1,91 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Gehennas +SD%Complete: 90 +SDComment: Adds MC NYI +SDCategory: Molten Core +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_SHADOWBOLT 19728 +#define SPELL_RAINOFFIRE 19717 +#define SPELL_GEHENNASCURSE 19716 + +struct MANGOS_DLL_DECL boss_gehennasAI : public ScriptedAI +{ + boss_gehennasAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 ShadowBolt_Timer; + uint32 RainOfFire_Timer; + uint32 GehennasCurse_Timer; + + void Reset() + { + ShadowBolt_Timer = 6000; + RainOfFire_Timer = 10000; + GehennasCurse_Timer = 12000; + } + + void Aggro(Unit *who) { } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //ShadowBolt_Timer + if (ShadowBolt_Timer < diff) + { + if( Unit* bTarget = SelectUnit(SELECT_TARGET_RANDOM,1) ) + DoCast(bTarget,SPELL_SHADOWBOLT); + ShadowBolt_Timer = 7000; + }else ShadowBolt_Timer -= diff; + + //RainOfFire_Timer + if (RainOfFire_Timer < diff) + { + if( Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target,SPELL_RAINOFFIRE); + + RainOfFire_Timer = 4000 + rand()%8000; + }else RainOfFire_Timer -= diff; + + //GehennasCurse_Timer + if (GehennasCurse_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_GEHENNASCURSE); + GehennasCurse_Timer = 22000 + rand()%8000; + }else GehennasCurse_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_gehennas(Creature *_Creature) +{ + return new boss_gehennasAI (_Creature); +} + +void AddSC_boss_gehennas() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_gehennas"; + newscript->GetAI = GetAI_boss_gehennas; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/molten_core/boss_golemagg.cpp b/src/bindings/scripts/scripts/zone/molten_core/boss_golemagg.cpp new file mode 100644 index 00000000000..08bb85201ca --- /dev/null +++ b/src/bindings/scripts/scripts/zone/molten_core/boss_golemagg.cpp @@ -0,0 +1,219 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Golemagg +SD%Complete: 90 +SDComment: +SDCategory: Molten Core +EndScriptData */ + +#include "precompiled.h" +#include "def_molten_core.h" + +#define SPELL_MAGMASPLASH 13879 +#define SPELL_PYROBLAST 20228 +#define SPELL_EARTHQUAKE 19798 +#define SPELL_ENRAGE 19953 +#define SPELL_BUFF 20553 + +//-- CoreRager Spells -- +#define SPELL_MANGLE 19820 +#define SPELL_AEGIS 20620 //This is self casted whenever we are below 50% + +#define EMOTE_AEGIS "refuses to die while its master is in trouble" + +struct MANGOS_DLL_DECL boss_golemaggAI : public ScriptedAI +{ + boss_golemaggAI(Creature *c) : ScriptedAI(c) + { + pInstance = (c->GetInstanceData()) ? ((ScriptedInstance*)c->GetInstanceData()) : NULL; + Reset(); + } + + uint32 Pyroblast_Timer; + uint32 EarthQuake_Timer; + uint32 Enrage_Timer; + uint32 Buff_Timer; + ScriptedInstance *pInstance; + + void Reset() + { + Pyroblast_Timer = 7000; //These times are probably wrong + EarthQuake_Timer = 3000; + Buff_Timer = 2500; + Enrage_Timer = 0; + + m_creature->CastSpell(m_creature,SPELL_MAGMASPLASH,true); + } + + void Aggro(Unit *who) + { + } + + void JustDied(Unit* Killer) + { + ScriptedInstance *pInstance = (m_creature->GetInstanceData()) ? ((ScriptedInstance*)m_creature->GetInstanceData()) : NULL; + if(pInstance) + pInstance->SetData(DATA_GOLEMAGG_DEATH, 0); + } + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //Pyroblast_Timer + if (Pyroblast_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) DoCast(target,SPELL_PYROBLAST); + + Pyroblast_Timer = 7000; + }else Pyroblast_Timer -= diff; + + //Enrage_Timer + if ( m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 11 ) + { + if (Enrage_Timer < diff) + { + DoCast(m_creature,SPELL_ENRAGE); + Enrage_Timer = 62000; + }else Enrage_Timer -= diff; + } + + //EarthQuake_Timer + if ( m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 11 ) + { + if (EarthQuake_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_EARTHQUAKE); + EarthQuake_Timer = 3000; + }else EarthQuake_Timer -= diff; + } + + //Casting Buff for Coreragers. Spell is not working right. Players get the buff... + // if(Buff_Timer < diff) + // { + // DoCast(m_creature, SPELL_BUFF); + // Buff_Timer = 2500; + // }else Buff_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL mob_core_ragerAI : public ScriptedAI +{ + mob_core_ragerAI(Creature *c) : ScriptedAI(c) + { + pInstance = (c->GetInstanceData()) ? ((ScriptedInstance*)c->GetInstanceData()) : NULL; + Reset(); + } + + uint32 Mangle_Timer; + uint32 Check_Timer; + ScriptedInstance *pInstance; + + void Reset() + { + Mangle_Timer = 7000; //These times are probably wrong + Check_Timer = 1000; + } + + void Aggro(Unit *who) + { + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || m_creature->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + float attackRadius = m_creature->GetAttackDistance(who); + if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) + { + if(who->HasStealthAura()) + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + DoStartAttackAndMovement(who); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //Mangle_Timer + if (Mangle_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_MANGLE); + Mangle_Timer = 10000; + }else Mangle_Timer -= diff; + + //Cast AEGIS + if ( m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 50 ) + { + DoCast(m_creature,SPELL_AEGIS); + DoTextEmote(EMOTE_AEGIS, NULL); + } + + //Check_Timer + if(Check_Timer < diff) + { + if(pInstance) + { + Unit *pGolemagg = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_GOLEMAGG)); + if(!pGolemagg || !pGolemagg->isAlive()) + { + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, true); + } + } + + Check_Timer = 1000; + }else Check_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_golemagg(Creature *_Creature) +{ + return new boss_golemaggAI (_Creature); +} + +CreatureAI* GetAI_mob_core_rager(Creature *_Creature) +{ + return new mob_core_ragerAI (_Creature); +} + +void AddSC_boss_golemagg() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_golemagg"; + newscript->GetAI = GetAI_boss_golemagg; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_core_rager"; + newscript->GetAI = GetAI_mob_core_rager; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/molten_core/boss_lucifron.cpp b/src/bindings/scripts/scripts/zone/molten_core/boss_lucifron.cpp new file mode 100644 index 00000000000..c0083fe1a7f --- /dev/null +++ b/src/bindings/scripts/scripts/zone/molten_core/boss_lucifron.cpp @@ -0,0 +1,90 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Lucifron +SD%Complete: 100 +SDComment: +SDCategory: Molten Core +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_IMPENDINGDOOM 19702 +#define SPELL_LUCIFRONCURSE 19703 +#define SPELL_SHADOWSHOCK 20603 + +struct MANGOS_DLL_DECL boss_lucifronAI : public ScriptedAI +{ + boss_lucifronAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 ImpendingDoom_Timer; + uint32 LucifronCurse_Timer; + uint32 ShadowShock_Timer; + + void Reset() + { + ImpendingDoom_Timer = 10000; //Initial cast after 10 seconds so the debuffs alternate + LucifronCurse_Timer = 20000; //Initial cast after 20 seconds + ShadowShock_Timer = 6000; //6 seconds + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //Impending doom timer + if (ImpendingDoom_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_IMPENDINGDOOM); + ImpendingDoom_Timer = 20000; + }else ImpendingDoom_Timer -= diff; + + //Lucifron's curse timer + if (LucifronCurse_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_LUCIFRONCURSE); + LucifronCurse_Timer = 15000; + }else LucifronCurse_Timer -= diff; + + //Shadowshock + if (ShadowShock_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SHADOWSHOCK); + ShadowShock_Timer = 6000; + }else ShadowShock_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_lucifron(Creature *_Creature) +{ + return new boss_lucifronAI (_Creature); +} + +void AddSC_boss_lucifron() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_lucifron"; + newscript->GetAI = GetAI_boss_lucifron; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/molten_core/boss_magmadar.cpp b/src/bindings/scripts/scripts/zone/molten_core/boss_magmadar.cpp new file mode 100644 index 00000000000..1d2d9fa1617 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/molten_core/boss_magmadar.cpp @@ -0,0 +1,97 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Magmadar +SD%Complete: 75 +SDComment: Conflag on ground nyi, fear causes issues without VMAPs +SDCategory: Molten Core +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_FRENZY 19451 +#define SPELL_MAGMASPIT 19449 //This is actually a buff he gives himself +#define SPELL_PANIC 19408 +#define SPELL_LAVABOMB 19411 //This calls a dummy server side effect that isn't implemented yet +#define SPELL_LAVABOMB_ALT 19428 //This is the spell that the lava bomb casts + +struct MANGOS_DLL_DECL boss_magmadarAI : public ScriptedAI +{ + boss_magmadarAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Frenzy_Timer; + uint32 Panic_Timer; + uint32 Lavabomb_Timer; + + void Reset() + { + Frenzy_Timer = 30000; + Panic_Timer = 20000; + Lavabomb_Timer = 12000; + + m_creature->CastSpell(m_creature,SPELL_MAGMASPIT,true); + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //Frenzy_Timer + if (Frenzy_Timer < diff) + { + DoTextEmote("goes into a killing frenzy!",NULL); + DoCast(m_creature,SPELL_FRENZY); + Frenzy_Timer = 15000; + }else Frenzy_Timer -= diff; + + //Panic_Timer + if (Panic_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_PANIC); + Panic_Timer = 35000; + }else Panic_Timer -= diff; + + //Lavabomb_Timer + if (Lavabomb_Timer < diff) + { + if( Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target,SPELL_LAVABOMB_ALT); + + Lavabomb_Timer = 12000; + }else Lavabomb_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_magmadar(Creature *_Creature) +{ + return new boss_magmadarAI (_Creature); +} + +void AddSC_boss_magmadar() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_magmadar"; + newscript->GetAI = GetAI_boss_magmadar; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/molten_core/boss_majordomo_executus.cpp b/src/bindings/scripts/scripts/zone/molten_core/boss_majordomo_executus.cpp new file mode 100644 index 00000000000..8c7129eb691 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/molten_core/boss_majordomo_executus.cpp @@ -0,0 +1,133 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_MajorDomo_Executus +SD%Complete: 30 +SDComment: Correct spawning and Event NYI +SDCategory: Molten Core +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_MAGICREFLECTION 20619 +#define SPELL_DAMAGEREFLECTION 21075 +#define SPELL_BLASTWAVE 20229 +#define SPELL_AEGIS 20620 //This is self casted whenever we are below 50% + +#define SAY_AGGRO "Reckless mortals, none may challenge the sons of the living flame!" +#define SOUND_AGGRO 8035 + +#define SAY_SPAWN "The runes of warding have been destroyed! Hunt down the infedels my bretheren." +#define SOUND_SPAWN 8039 + +#define SAY_DEFEAT "Impossible! Stay your attack mortals! I submitt! I submitt! Brashly you have come to rest the secrets of the living flame. You will soon regret the recklessness of your quest. I go now to summon the lord whos house this is. Should you seek an audiance with him your paltry lives will surly be forfit. Nevertheless seek out his lair if you dare!" +#define SOUND_DEFEAT 8038 + +#define SAY_KILL "Ashes to Ashes!" +#define SOUND_KILL 8037 + +#define SAY_SPECIAL "Burn mortals! Burn for this transgression!" +#define SOUND_SPECIAL 8036 + +#define SAY_SUMMON "Behold Ragnaros, the Firelord! He who was ancient when this world was young! Bow before him, mortals! Bow before your ending!" +#define SOUND_SUMMON 8040 + +#define SAY_ARRIVAL1 "These mortal infidels, my lord! They have invaded your sanctum, and seek to steal your secrets!" +#define SOUND_ARRIVAL1 8041 + +struct MANGOS_DLL_DECL boss_majordomoAI : public ScriptedAI +{ + boss_majordomoAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 MagicReflection_Timer; + uint32 DamageReflection_Timer; + uint32 Blastwave_Timer; + + void Reset() + { + MagicReflection_Timer = 30000; //Damage reflection first so we alternate + DamageReflection_Timer = 15000; + Blastwave_Timer = 10000; + } + + void KilledUnit(Unit* victim) + { + if (rand()%5) + return; + + DoYell(SAY_KILL,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_KILL); + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //Cast Ageis if less than 50% hp + if (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 50) + { + DoCast(m_creature,SPELL_AEGIS); + } + + //MagicReflection_Timer + // if (MagicReflection_Timer < diff) + // { + // DoCast(m_creature, SPELL_MAGICREFLECTION); + + //60 seconds until we should cast this agian + // MagicReflection_Timer = 30000; + // }else MagicReflection_Timer -= diff; + + //DamageReflection_Timer + // if (DamageReflection_Timer < diff) + // { + // DoCast(m_creature, SPELL_DAMAGEREFLECTION); + + //60 seconds until we should cast this agian + // DamageReflection_Timer = 30000; + // }else DamageReflection_Timer -= diff; + + //Blastwave_Timer + if (Blastwave_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_BLASTWAVE); + Blastwave_Timer = 10000; + }else Blastwave_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_majordomo(Creature *_Creature) +{ + return new boss_majordomoAI (_Creature); +} + +void AddSC_boss_majordomo() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_majordomo"; + newscript->GetAI = GetAI_boss_majordomo; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/molten_core/boss_ragnaros.cpp b/src/bindings/scripts/scripts/zone/molten_core/boss_ragnaros.cpp new file mode 100644 index 00000000000..3a043987cca --- /dev/null +++ b/src/bindings/scripts/scripts/zone/molten_core/boss_ragnaros.cpp @@ -0,0 +1,317 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Ragnaros +SD%Complete: 75 +SDComment: Intro Dialog and event NYI +SDCategory: Molten Core +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_HANDOFRAGNAROS 19780 +#define SPELL_WRATHOFRAGNAROS 20566 +#define SPELL_LAVABURST 21158 + +#define SPELL_MAGMABURST 20565 //Ranged attack + +#define SPELL_SONSOFFLAME_DUMMY 21108 //Server side effect +#define SPELL_RAGSUBMERGE 21107 //Stealth aura +#define SPELL_RAGEMERGE 20568 +#define SPELL_MELTWEAPON 21388 +#define SPELL_ELEMENTALFIRE 20564 +#define SPELL_ERRUPTION 17731 + +#define SAY_ARRIVAL_1 "TOO SOON! YOU HAVE AWAKENED ME TOO SOON, EXECUTUS! WHAT IS THE MEANING OF THIS INTRUSION?" +#define SAY_ARRIVAL_3 "FOOL! YOU ALLOWED THESE INSECTS TO RUN RAMPANT THROUGH THE HALLOWED CORE, AND NOW YOU LEAD THEM TO MY VERY LAIR? YOU HAVE FAILED ME, EXECUTUS! JUSTICE SHALL BE MET, INDEED!" +#define SAY_ARRIVAL_5 "NOW FOR YOU, INSECTS. BOLDLY YOU SAUGHT THE POWER OF RAGNAROS NOW YOU SHALL SEE IT FIRST HAND." +#define SAY_REINFORCEMENTS1 "COME FORTH, MY SERVANTS! DEFEND YOUR MASTER!" +#define SAY_REINFORCEMENTS2 "YOU CANNOT DEFEAT THE LIVING FLAME! COME YOU MINIONS OF FIRE! COME FORTH YOU CREATURES OF HATE! YOUR MASTER CALLS!" +#define SAY_HAND "BY FIRE BE PURGED!" +#define SAY_WRATH "TASTE THE FLAMES OF SULFURON!" +#define SAY_KILL "DIE INSECT!" +#define SAY_MAGMABURST "MY PATIENCE IS DWINDILING! COME NATS TO YOUR DEATH!" + +#define SOUND_ARRIVAL_1 8043 +#define SOUND_ARRIVAL_3 8044 +#define SOUND_ARRIVAL_5 8045 +#define SOUND_REINFORCEMENTS1 8049 +#define SOUND_REINFORCEMENTS2 8050 +#define SOUND_HAND 8046 +#define SOUND_WRATH 8047 +#define SOUND_KILL 8051 +#define SOUND_MAGMABURST 8048 + +#define ADD_1X 848.740356 +#define ADD_1Y -816.103455 +#define ADD_1Z -229.74327 +#define ADD_1O 2.615287 + +#define ADD_2X 852.560791 +#define ADD_2Y -849.861511 +#define ADD_2Z -228.560974 +#define ADD_2O 2.836073 + +#define ADD_3X 808.710632 +#define ADD_3Y -852.845764 +#define ADD_3Z -227.914963 +#define ADD_3O 0.964207 + +#define ADD_4X 786.597107 +#define ADD_4Y -821.132874 +#define ADD_4Z -226.350128 +#define ADD_4O 0.949377 + +#define ADD_5X 796.219116 +#define ADD_5Y -800.948059 +#define ADD_5Z -226.010361 +#define ADD_5O 0.560603 + +#define ADD_6X 821.602539 +#define ADD_6Y -782.744109 +#define ADD_6Z -226.023575 +#define ADD_6O 6.157440 + +#define ADD_7X 844.924744 +#define ADD_7Y -769.453735 +#define ADD_7Z -225.521698 +#define ADD_7O 4.4539958 + +#define ADD_8X 839.823364 +#define ADD_8Y -810.869385 +#define ADD_8Z -229.683182 +#define ADD_8O 4.693108 + +struct MANGOS_DLL_DECL boss_ragnarosAI : public Scripted_NoMovementAI +{ + boss_ragnarosAI(Creature *c) : Scripted_NoMovementAI(c) {Reset();} + + uint32 WrathOfRagnaros_Timer; + uint32 HandOfRagnaros_Timer; + uint32 LavaBurst_Timer; + uint32 MagmaBurst_Timer; + uint32 ElementalFire_Timer; + uint32 Erruption_Timer; + uint32 Submerge_Timer; + uint32 Attack_Timer; + Creature *Summoned; + bool HasYelledMagmaBurst; + bool HasSubmergedOnce; + bool WasBanished; + bool HasAura; + + void Reset() + { + WrathOfRagnaros_Timer = 30000; + HandOfRagnaros_Timer = 25000; + LavaBurst_Timer = 10000; + MagmaBurst_Timer = 2000; + Erruption_Timer = 15000; + ElementalFire_Timer = 3000; + Submerge_Timer = 180000; + Attack_Timer = 90000; + HasYelledMagmaBurst = false; + HasSubmergedOnce = false; + WasBanished = false; + + m_creature->CastSpell(m_creature,SPELL_MELTWEAPON,true); + HasAura = true; + } + + void KilledUnit(Unit* victim) + { + if (rand()%5) + return; + + DoYell(SAY_KILL, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_KILL); + } + + void Aggro(Unit *who) + { + DoYell(SAY_ARRIVAL_5,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_ARRIVAL_5); + } + + void UpdateAI(const uint32 diff) + { + if (WasBanished && Attack_Timer < diff) + { + //Become unbanished again + m_creature->setFaction(14); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoCast(m_creature,SPELL_RAGEMERGE); + WasBanished = false; + } else if (WasBanished) + { + Attack_Timer -= diff; + //Do nothing while banished + return; + } + + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //WrathOfRagnaros_Timer + if (WrathOfRagnaros_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_WRATHOFRAGNAROS); + + if (rand()%2 == 0) + { + DoYell(SAY_WRATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_WRATH); + } + + WrathOfRagnaros_Timer = 30000; + }else WrathOfRagnaros_Timer -= diff; + + //HandOfRagnaros_Timer + if (HandOfRagnaros_Timer < diff) + { + DoCast(m_creature,SPELL_HANDOFRAGNAROS); + + if (rand()%2==0) + { + DoYell(SAY_HAND,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_HAND); + } + + HandOfRagnaros_Timer = 25000; + }else HandOfRagnaros_Timer -= diff; + + //LavaBurst_Timer + if (LavaBurst_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_LAVABURST); + LavaBurst_Timer = 10000; + }else LavaBurst_Timer -= diff; + + //Erruption_Timer + if (LavaBurst_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_ERRUPTION); + Erruption_Timer = 20000 + rand()%25000; + }else Erruption_Timer -= diff; + + //ElementalFire_Timer + if (ElementalFire_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_ELEMENTALFIRE); + ElementalFire_Timer = 10000 + rand()%4000; + }else ElementalFire_Timer -= diff; + + //Submerge_Timer + if (!WasBanished && Submerge_Timer < diff) + { + //Creature spawning and ragnaros becomming unattackable + //is not very well supported in the core + //so added normaly spawning and banish workaround and attack again after 90 secs. + + m_creature->InterruptNonMeleeSpells(false); + //Root self + DoCast(m_creature,23973); + m_creature->setFaction(35); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_SUBMERGE); + + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + + if (!HasSubmergedOnce) + { + DoYell(SAY_REINFORCEMENTS1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_REINFORCEMENTS1); + + // summon 10 elementals + Unit* target = NULL; + for(int i = 0; i < 9;i++) + { + target = SelectUnit(SELECT_TARGET_RANDOM,0); + Summoned = m_creature->SummonCreature(12143,target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(),0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,900000); + ((CreatureAI*)Summoned->AI())->AttackStart(target); + } + + HasSubmergedOnce = true; + WasBanished = true; + DoCast(m_creature,SPELL_RAGSUBMERGE); + Attack_Timer = 90000; + + }else + { + DoYell(SAY_REINFORCEMENTS2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_REINFORCEMENTS2); + + Unit* target = NULL; + for(int i = 0; i < 9;i++) + { + target = SelectUnit(SELECT_TARGET_RANDOM,0); + Summoned = m_creature->SummonCreature(12143,target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(),0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,900000); + ((CreatureAI*)Summoned->AI())->AttackStart(target); + } + + WasBanished = true; + DoCast(m_creature,SPELL_RAGSUBMERGE); + Attack_Timer = 90000; + } + + Submerge_Timer = 180000; + }else Submerge_Timer -= diff; + + //If we are within range melee the target + if( m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE)) + { + //Make sure our attack is ready and we arn't currently casting + if( m_creature->isAttackReady() && !m_creature->IsNonMeleeSpellCasted(false)) + { + m_creature->AttackerStateUpdate(m_creature->getVictim()); + m_creature->resetAttackTimer(); + } + }else + { + //MagmaBurst_Timer + if (MagmaBurst_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_MAGMABURST); + + if (!HasYelledMagmaBurst) + { + //Say our dialog + DoYell(SAY_MAGMABURST,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_MAGMABURST); + HasYelledMagmaBurst = true; + } + + MagmaBurst_Timer = 2500; + }else MagmaBurst_Timer -= diff; + } + } +}; +CreatureAI* GetAI_boss_ragnaros(Creature *_Creature) +{ + return new boss_ragnarosAI (_Creature); +} + +void AddSC_boss_ragnaros() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_ragnaros"; + newscript->GetAI = GetAI_boss_ragnaros; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/molten_core/boss_shazzrah.cpp b/src/bindings/scripts/scripts/zone/molten_core/boss_shazzrah.cpp new file mode 100644 index 00000000000..5c8746b2567 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/molten_core/boss_shazzrah.cpp @@ -0,0 +1,121 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Shazzrah +SD%Complete: 75 +SDComment: Teleport NYI +SDCategory: Molten Core +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_ARCANEEXPLOSION 19712 +#define SPELL_SHAZZRAHCURSE 19713 +#define SPELL_DEADENMAGIC 19714 +#define SPELL_COUNTERSPELL 19715 + +struct MANGOS_DLL_DECL boss_shazzrahAI : public ScriptedAI +{ + boss_shazzrahAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 ArcaneExplosion_Timer; + uint32 ShazzrahCurse_Timer; + uint32 DeadenMagic_Timer; + uint32 Countspell_Timer; + uint32 Blink_Timer; + + void Reset() + { + ArcaneExplosion_Timer = 6000; //These times are probably wrong + ShazzrahCurse_Timer = 10000; + DeadenMagic_Timer = 24000; + Countspell_Timer = 15000; + Blink_Timer = 30000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //ArcaneExplosion_Timer + if (ArcaneExplosion_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_ARCANEEXPLOSION); + ArcaneExplosion_Timer = 5000 + rand()%4000; + }else ArcaneExplosion_Timer -= diff; + + //ShazzrahCurse_Timer + if (ShazzrahCurse_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) DoCast(target,SPELL_SHAZZRAHCURSE); + + ShazzrahCurse_Timer = 25000 + rand()%5000; + }else ShazzrahCurse_Timer -= diff; + + //DeadenMagic_Timer + if (DeadenMagic_Timer < diff) + { + DoCast(m_creature,SPELL_DEADENMAGIC); + DeadenMagic_Timer = 35000; + }else DeadenMagic_Timer -= diff; + + //Countspell_Timer + if (Countspell_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_COUNTERSPELL); + Countspell_Timer = 16000 + rand()%4000; + }else Countspell_Timer -= diff; + + //Blink_Timer + if (Blink_Timer < diff) + { + // Teleporting him to a random gamer and casting Arcane Explosion after that. + // Blink is not working cause of LoS System we need to do this hardcoded. + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + + m_creature->Relocate(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(),0); + m_creature->SendMonsterMove(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(),0,true,0); + DoCast(target,SPELL_ARCANEEXPLOSION); + DoResetThreat(); + + Blink_Timer = 45000; + }else Blink_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_shazzrah(Creature *_Creature) +{ + return new boss_shazzrahAI (_Creature); +} + +void AddSC_boss_shazzrah() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_shazzrah"; + newscript->GetAI = GetAI_boss_shazzrah; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/molten_core/boss_sulfuron_harbinger.cpp b/src/bindings/scripts/scripts/zone/molten_core/boss_sulfuron_harbinger.cpp new file mode 100644 index 00000000000..fd4affaa570 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/molten_core/boss_sulfuron_harbinger.cpp @@ -0,0 +1,215 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Sulfuron_Harbringer +SD%Complete: 80 +SDComment: Adds NYI +SDCategory: Molten Core +EndScriptData */ + +#include "precompiled.h" +#include "def_molten_core.h" + +#define SPELL_DARKSTRIKE 19777 +#define SPELL_DEMORALIZINGSHOUT 19778 +#define SPELL_INSPIRE 19779 +#define SPELL_KNOCKDOWN 19780 +#define SPELL_FLAMESPEAR 19781 + +//Adds Spells +#define SPELL_HEAL 19775 +#define SPELL_SHADOWWORDPAIN 19776 +#define SPELL_IMMOLATE 20294 + +struct MANGOS_DLL_DECL boss_sulfuronAI : public ScriptedAI +{ + boss_sulfuronAI(Creature *c) : ScriptedAI(c) + { + pInstance = (c->GetInstanceData()) ? ((ScriptedInstance*)c->GetInstanceData()) : NULL; + Reset(); + } + + uint32 Darkstrike_Timer; + uint32 DemoralizingShout_Timer; + uint32 Inspire_Timer; + uint32 Knockdown_Timer; + uint32 Flamespear_Timer; + ScriptedInstance *pInstance; + + void Reset() + { + Darkstrike_Timer=10000; //These times are probably wrong + DemoralizingShout_Timer = 15000; + Inspire_Timer = 13000; + Knockdown_Timer = 6000; + Flamespear_Timer = 2000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //DemoralizingShout_Timer + if (DemoralizingShout_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_DEMORALIZINGSHOUT); + DemoralizingShout_Timer = 15000 + rand()%5000; + }else DemoralizingShout_Timer -= diff; + + //Inspire_Timer + if (Inspire_Timer < diff) + { + Creature* target = NULL; + std::list pList = DoFindFriendlyMissingBuff(45.0f,SPELL_INSPIRE); + if (!pList.empty()) + { + std::list::iterator i = pList.begin(); + advance(i, (rand()%pList.size())); + target = (*i); + } + + if (target) + DoCast(target,SPELL_INSPIRE); + + DoCast(m_creature,SPELL_INSPIRE); + + Inspire_Timer = 20000 + rand()%6000; + }else Inspire_Timer -= diff; + + //Knockdown_Timer + if (Knockdown_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_KNOCKDOWN); + Knockdown_Timer = 12000 + rand()%3000; + }else Knockdown_Timer -= diff; + + //Flamespear_Timer + if (Flamespear_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) DoCast(target,SPELL_FLAMESPEAR); + + Flamespear_Timer = 12000 + rand()%4000; + }else Flamespear_Timer -= diff; + + //DarkStrike_Timer + if (Darkstrike_Timer < diff) + { + DoCast(m_creature, SPELL_DARKSTRIKE); + Darkstrike_Timer = 15000 + rand()%3000; + }else Darkstrike_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL mob_flamewaker_priestAI : public ScriptedAI +{ + mob_flamewaker_priestAI(Creature *c) : ScriptedAI(c) + { + pInstance = (c->GetInstanceData()) ? ((ScriptedInstance*)c->GetInstanceData()) : NULL; + Reset(); + } + + uint32 Heal_Timer; + uint32 ShadowWordPain_Timer; + uint32 Immolate_Timer; + + ScriptedInstance *pInstance; + + void Reset() + { + Heal_Timer = 15000+rand()%15000; + ShadowWordPain_Timer = 2000; + Immolate_Timer = 8000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //Casting Heal to Sulfuron or other Guards. + if(Heal_Timer < diff) + { + Unit* pUnit = DoSelectLowestHpFriendly(60.0f, 1); + if (!pUnit) + return; + + DoCast(pUnit, SPELL_HEAL); + + Heal_Timer = 15000+rand()%5000; + }else Heal_Timer -= diff; + + //ShadowWordPain_Timer + if (ShadowWordPain_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) DoCast(target,SPELL_SHADOWWORDPAIN); + + ShadowWordPain_Timer = 18000+rand()%8000; + }else ShadowWordPain_Timer -= diff; + + //Immolate_Timer + if (Immolate_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) DoCast(target,SPELL_IMMOLATE); + + Immolate_Timer = 15000+rand()%10000; + }else Immolate_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_sulfuron(Creature *_Creature) +{ + return new boss_sulfuronAI (_Creature); +} + +CreatureAI* GetAI_mob_flamewaker_priest(Creature *_Creature) +{ + return new mob_flamewaker_priestAI (_Creature); +} + +void AddSC_boss_sulfuron() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_sulfuron"; + newscript->GetAI = GetAI_boss_sulfuron; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_flamewaker_priest"; + newscript->GetAI = GetAI_mob_flamewaker_priest; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/molten_core/def_molten_core.h b/src/bindings/scripts/scripts/zone/molten_core/def_molten_core.h new file mode 100644 index 00000000000..584adce0d31 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/molten_core/def_molten_core.h @@ -0,0 +1,21 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_MOLTEN_CORE_H +#define DEF_MOLTEN_CORE_H + +#define DATA_FLAMEWAKERPRIEST 1 +#define DATA_GARRISDEAD 2 +#define DATA_GEDDONISDEAD 3 +#define DATA_GEHENNASISDEAD 4 +#define DATA_GOLEMAGGISDEAD 5 +#define DATA_GOLEMAGG_DEATH 6 +#define DATA_LUCIFRONISDEAD 7 +#define DATA_MAGMADARISDEAD 8 +#define DATA_MAJORDOMOISDEAD 9 +#define DATA_SHAZZRAHISDEAD 10 +#define DATA_SULFURON 11 +#define DATA_SULFURONISDEAD 12 +#define DATA_GOLEMAGG 13 +#endif diff --git a/src/bindings/scripts/scripts/zone/molten_core/instance_molten_core.cpp b/src/bindings/scripts/scripts/zone/molten_core/instance_molten_core.cpp new file mode 100644 index 00000000000..60521aa5f9c --- /dev/null +++ b/src/bindings/scripts/scripts/zone/molten_core/instance_molten_core.cpp @@ -0,0 +1,260 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Molten_Core +SD%Complete: 0 +SDComment: Place Holder +SDCategory: Molten Core +EndScriptData */ + +#include "precompiled.h" +#include "def_molten_core.h" + +#define ID_LUCIFRON 12118 +#define ID_MAGMADAR 11982 +#define ID_GEHENNAS 12259 +#define ID_GARR 12057 +#define ID_GEDDON 12056 +#define ID_SHAZZRAH 12264 +#define ID_GOLEMAGG 11988 +#define ID_SULFURON 12098 +#define ID_DOMO 12018 +#define ID_RAGNAROS 11502 +#define ID_FLAMEWAKERPRIEST 11662 + +class MANGOS_DLL_SPEC instance_molten_core : public ScriptedInstance +{ + public: + + instance_molten_core(Map *map) : ScriptedInstance(map) {} + + uint64 Lucifron, Magmadar, Gehennas, Garr, Geddon, Shazzrah, Sulfuron, Golemagg, Domo, Ragnaros, FlamewakerPriest; + uint64 RuneGUID[8]; + + //If all Bosses are dead. + bool IsBossDied[9]; + + uint32 CheckTimer; + + //On creation, NOT load. + void Initialize() + { + //Clear all GUIDs + Lucifron = 0; + Magmadar = 0; + Gehennas = 0; + Garr = 0; + Geddon = 0; + Shazzrah = 0; + Sulfuron = 0; + Golemagg = 0; + Domo = 0; + Ragnaros = 0; + FlamewakerPriest = 0; + + RuneGUID[0] = 0; + RuneGUID[1] = 0; + RuneGUID[2] = 0; + RuneGUID[3] = 0; + RuneGUID[4] = 0; + RuneGUID[5] = 0; + RuneGUID[6] = 0; + RuneGUID[7] = 0; + + IsBossDied[0] = false; + IsBossDied[1] = false; + IsBossDied[2] = false; + IsBossDied[3] = false; + IsBossDied[4] = false; + IsBossDied[5] = false; + IsBossDied[6] = false; + + IsBossDied[7] = false; + IsBossDied[8] = false; + + CheckTimer = 10000; + } + //Called every map update + void Update(uint32 diff) + { + + if (CheckTimer < diff) + { + //Check if all bosses are dead and activate Major Domo + + }else CheckTimer -= diff; + + } + + //Used by the map's CanEnter function. + //This is to prevent players from entering during boss encounters. + bool IsEncounterInProgress() const + { + return false; + }; + + //Called when a gameobject is created + void OnObjectCreate(GameObject *obj) + { + //Still searching for the individual rune ids. + //Currently they don't exist within most databases and are hard to find on websites + } + + //called on creature creation + void OnCreatureCreate(Creature *creature, uint32 creature_entry) + { + //Store specific creatures based on entry id + switch (creature_entry) + { + case ID_LUCIFRON: + Lucifron = creature->GetGUID(); + break; + + case ID_MAGMADAR: + Magmadar = creature->GetGUID(); + break; + + case ID_GEHENNAS: + Gehennas = creature->GetGUID(); + break; + + case ID_GARR: + Garr = creature->GetGUID(); + break; + + case ID_GEDDON: + Geddon = creature->GetGUID(); + break; + + case ID_SHAZZRAH: + Shazzrah = creature->GetGUID(); + break; + + case ID_SULFURON: + Sulfuron = creature->GetGUID(); + break; + + case ID_GOLEMAGG: + Golemagg = creature->GetGUID(); + break; + + case ID_DOMO: + Domo = creature->GetGUID(); + break; + + case ID_RAGNAROS: + Ragnaros = creature->GetGUID(); + break; + + case ID_FLAMEWAKERPRIEST: + FlamewakerPriest = creature->GetGUID(); + break; + + default: + return; + } + } + + uint64 GetData64 (uint32 identifier) + { + switch(identifier) + { + case DATA_SULFURON: + return Sulfuron; + case DATA_GOLEMAGG: + return Sulfuron; + + case DATA_FLAMEWAKERPRIEST: + return FlamewakerPriest; + } + + return 0; + } // end GetData64 + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_LUCIFRONISDEAD: + if(IsBossDied[0]) + return 1; + break; + + case DATA_MAGMADARISDEAD: + if(IsBossDied[1]) + return 1; + break; + + case DATA_GEHENNASISDEAD: + if(IsBossDied[2]) + return 1; + break; + + case DATA_GARRISDEAD: + if(IsBossDied[3]) + return 1; + break; + + case DATA_GEDDONISDEAD: + if(IsBossDied[4]) + return 1; + break; + + case DATA_SHAZZRAHISDEAD: + if(IsBossDied[5]) + return 1; + break; + + case DATA_SULFURONISDEAD: + if(IsBossDied[6]) + return 1; + break; + + case DATA_GOLEMAGGISDEAD: + if(IsBossDied[7]) + return 1; + break; + + case DATA_MAJORDOMOISDEAD: + if(IsBossDied[8]) + return 1; + break; + } + + return 0; + } + + void SetData(uint32 type, uint32 data) + { + if(type == DATA_GOLEMAGG_DEATH) + IsBossDied[7] = true; + } +}; + +InstanceData* GetInstance_instance_molten_core(Map *_Map) +{ + return new instance_molten_core (_Map); +} + +void AddSC_instance_molten_core() +{ + Script *newscript; + newscript = new Script; + newscript->Name="instance_molten_core"; + newscript->GetInstanceData = &GetInstance_instance_molten_core; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/molten_core/molten_core.cpp b/src/bindings/scripts/scripts/zone/molten_core/molten_core.cpp new file mode 100644 index 00000000000..c2aab542828 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/molten_core/molten_core.cpp @@ -0,0 +1,88 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Molten_Core +SD%Complete: 100 +SDComment: +SDCategory: Molten Core +EndScriptData */ + +/* ContentData +mob_ancient_core_hound +EndContentData */ + +#include "precompiled.h" +#include "../../creature/simple_ai.h" + +#define SPELL_CONE_OF_FIRE 19630 +#define SPELL_BITE 19771 + +//Random Debuff (each hound has only one of these) +#define SPELL_GROUND_STOMP 19364 +#define SPELL_ANCIENT_DREAD 19365 +#define SPELL_CAUTERIZING_FLAMES 19366 +#define SPELL_WITHERING_HEAT 19367 +#define SPELL_ANCIENT_DESPAIR 19369 +#define SPELL_ANCIENT_HYSTERIA 19372 + +CreatureAI* GetAI_mob_ancient_core_hound(Creature *_Creature) +{ + SimpleAI *ai = new SimpleAI(_Creature); + + ai->Spell[0].Enabled = true; + ai->Spell[0].Spell_Id = SPELL_CONE_OF_FIRE; + ai->Spell[0].Cooldown = 7000; + ai->Spell[0].First_Cast = 10000; + ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_TARGET; + + uint32 RandDebuff; + switch(rand()%6) + { + case 0 : RandDebuff = SPELL_GROUND_STOMP; break; + case 1 : RandDebuff = SPELL_ANCIENT_DREAD; break; + case 2 : RandDebuff = SPELL_CAUTERIZING_FLAMES; break; + case 3 : RandDebuff = SPELL_WITHERING_HEAT; break; + case 4 : RandDebuff = SPELL_ANCIENT_DESPAIR; break; + case 5 : RandDebuff = SPELL_ANCIENT_HYSTERIA; break; + } + + ai->Spell[1].Enabled = true; + ai->Spell[1].Spell_Id = RandDebuff; + ai->Spell[1].Cooldown = 24000; + ai->Spell[1].First_Cast = 15000; + ai->Spell[1].Cast_Target_Type = CAST_HOSTILE_TARGET; + + ai->Spell[2].Enabled = true; + ai->Spell[2].Spell_Id = SPELL_BITE; + ai->Spell[2].Cooldown = 6000; + ai->Spell[2].First_Cast = 4000; + ai->Spell[2].Cast_Target_Type = CAST_HOSTILE_TARGET; + + ai->EnterEvadeMode(); + + return ai; +} + +void AddSC_molten_core() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="mob_ancient_core_hound"; + newscript->GetAI = GetAI_mob_ancient_core_hound; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/moonglade/moonglade.cpp b/src/bindings/scripts/scripts/zone/moonglade/moonglade.cpp new file mode 100644 index 00000000000..d88aadf04ab --- /dev/null +++ b/src/bindings/scripts/scripts/zone/moonglade/moonglade.cpp @@ -0,0 +1,217 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Moonglade +SD%Complete: 100 +SDComment: Quest support: 30, 272, 5929, 5930. Special Flight Paths for Druid class. +SDCategory: Moonglade +EndScriptData */ + +/* ContentData +npc_bunthen_plainswind +npc_great_bear_spirit +npc_silva_filnaveth +EndContentData */ + +#include "precompiled.h" + +/*###### +## npc_bunthen_plainswind +######*/ + +bool GossipHello_npc_bunthen_plainswind(Player *player, Creature *_Creature) +{ + if(player->getClass() != CLASS_DRUID) + player->SEND_GOSSIP_MENU(4916,_Creature->GetGUID()); + else if(player->GetTeam() != HORDE) + { + if(player->GetQuestStatus(272) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM( 0, "Do you know where I can find Half Pendant of Aquatic Endurance?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + + player->SEND_GOSSIP_MENU(4917,_Creature->GetGUID()); + } + else if(player->getClass() == CLASS_DRUID && player->GetTeam() == HORDE) + { + player->ADD_GOSSIP_ITEM( 0, "I'd like to fly to Thunder Bluff.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + + if(player->GetQuestStatus(30) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM( 0, "Do you know where I can find Half Pendant of Aquatic Endurance?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + + player->SEND_GOSSIP_MENU(4918,_Creature->GetGUID()); + } + return true; +} + +bool GossipSelect_npc_bunthen_plainswind(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + switch(action) + { + case GOSSIP_ACTION_INFO_DEF + 1: + { + player->CLOSE_GOSSIP_MENU(); + if (player->getClass() == CLASS_DRUID && player->GetTeam() == HORDE) + { + std::vector nodes; + + nodes.resize(2); + nodes[0] = 63; // Nighthaven, Moonglade + nodes[1] = 22; // Thunder Bluff, Mulgore + player->ActivateTaxiPathTo(nodes); + } + break; + } + case GOSSIP_ACTION_INFO_DEF + 2: + player->SEND_GOSSIP_MENU(5373,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: + player->SEND_GOSSIP_MENU(5376,_Creature->GetGUID()); + break; + } + return true; +} + +/*###### +## npc_great_bear_spirit +######*/ + +#define GOSSIP_BEAR1 "What do you represent, spirit?" +#define GOSSIP_BEAR2 "I seek to understand the importance of strength of the body." +#define GOSSIP_BEAR3 "I seek to understand the importance of strength of the heart." +#define GOSSIP_BEAR4 "I have heard your words, Great Bear Spirit, and I understand. I now seek your blessings to fully learn the way of the Claw." + +bool GossipHello_npc_great_bear_spirit(Player *player, Creature *_Creature) +{ + //ally or horde quest + if (player->GetQuestStatus(5929) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(5930) == QUEST_STATUS_INCOMPLETE) + { + player->ADD_GOSSIP_ITEM( 0, GOSSIP_BEAR1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + player->SEND_GOSSIP_MENU(4719, _Creature->GetGUID()); + } + else + player->SEND_GOSSIP_MENU(4718, _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_great_bear_spirit(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_BEAR2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->SEND_GOSSIP_MENU(4721, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 1: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_BEAR3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->SEND_GOSSIP_MENU(4733, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_BEAR4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->SEND_GOSSIP_MENU(4734, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: + player->SEND_GOSSIP_MENU(4735, _Creature->GetGUID()); + if (player->GetQuestStatus(5929)==QUEST_STATUS_INCOMPLETE) + player->AreaExploredOrEventHappens(5929); + if (player->GetQuestStatus(5930)==QUEST_STATUS_INCOMPLETE) + player->AreaExploredOrEventHappens(5930); + break; + } + return true; +} + +/*###### +## npc_silva_filnaveth +######*/ + +bool GossipHello_npc_silva_filnaveth(Player *player, Creature *_Creature) +{ + if(player->getClass() != CLASS_DRUID) + player->SEND_GOSSIP_MENU(4913,_Creature->GetGUID()); + else if(player->GetTeam() != ALLIANCE) + { + if(player->GetQuestStatus(30) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM( 0, "Do you know where I can find Half Pendant of Aquatic Agility?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + + player->SEND_GOSSIP_MENU(4915,_Creature->GetGUID()); + } + else if(player->getClass() == CLASS_DRUID && player->GetTeam() == ALLIANCE) + { + player->ADD_GOSSIP_ITEM( 0, "I'd like to fly to Rut'theran Village.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + + if(player->GetQuestStatus(272) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM( 0, "Do you know where I can find Half Pendant of Aquatic Agility?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + + player->SEND_GOSSIP_MENU(4914,_Creature->GetGUID()); + } + return true; +} + +bool GossipSelect_npc_silva_filnaveth(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + switch(action) + { + case GOSSIP_ACTION_INFO_DEF + 1: + { + player->CLOSE_GOSSIP_MENU(); + if (player->getClass() == CLASS_DRUID && player->GetTeam() == ALLIANCE) + { + std::vector nodes; + + nodes.resize(2); + nodes[0] = 62; // Nighthaven, Moonglade + nodes[1] = 27; // Rut'theran Village, Teldrassil + player->ActivateTaxiPathTo(nodes); + } + break; + } + case GOSSIP_ACTION_INFO_DEF + 2: + player->SEND_GOSSIP_MENU(5374,_Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: + player->SEND_GOSSIP_MENU(5375,_Creature->GetGUID()); + break; + } + return true; +} + +/*###### +## +######*/ + +void AddSC_moonglade() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npc_bunthen_plainswind"; + newscript->pGossipHello = &GossipHello_npc_bunthen_plainswind; + newscript->pGossipSelect = &GossipSelect_npc_bunthen_plainswind; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_great_bear_spirit"; + newscript->pGossipHello = &GossipHello_npc_great_bear_spirit; + newscript->pGossipSelect = &GossipSelect_npc_great_bear_spirit; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_silva_filnaveth"; + newscript->pGossipHello = &GossipHello_npc_silva_filnaveth; + newscript->pGossipSelect = &GossipSelect_npc_silva_filnaveth; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/mulgore/mulgore.cpp b/src/bindings/scripts/scripts/zone/mulgore/mulgore.cpp new file mode 100644 index 00000000000..5e10e3500cb --- /dev/null +++ b/src/bindings/scripts/scripts/zone/mulgore/mulgore.cpp @@ -0,0 +1,64 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Mulgore +SD%Complete: 100 +SDComment: Skorn Whitecloud: Just a story if not rewarded for quest +SDCategory: Mulgore +EndScriptData */ + +/* ContentData +npc_skorn_whitecloud +EndContentData */ + +#include "precompiled.h" + +/*###### +# npc_skorn_whitecloud +######*/ + +bool GossipHello_npc_skorn_whitecloud(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if (!player->GetQuestRewardStatus(770)) + player->ADD_GOSSIP_ITEM( 0, "Tell me a story, Skorn.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF ); + + player->SEND_GOSSIP_MENU(522,_Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_skorn_whitecloud(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if (action == GOSSIP_ACTION_INFO_DEF) + player->SEND_GOSSIP_MENU(523,_Creature->GetGUID()); + + return true; +} + +void AddSC_mulgore() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npc_skorn_whitecloud"; + newscript->pGossipHello = &GossipHello_npc_skorn_whitecloud; + newscript->pGossipSelect = &GossipSelect_npc_skorn_whitecloud; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/nagrand/nagrand.cpp b/src/bindings/scripts/scripts/zone/nagrand/nagrand.cpp new file mode 100644 index 00000000000..2713d2b2d94 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/nagrand/nagrand.cpp @@ -0,0 +1,568 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Nagrand +SD%Complete: 90 +SDComment: Quest support: 9849, 9918, 9874, 9991, 10107, 10108, 10044, 10172, 10646, 10085. TextId's unknown for altruis_the_sufferer and greatmother_geyah (npc_text) +SDCategory: Nagrand +EndScriptData */ + +/* ContentData +mob_shattered_rumbler +mob_lump +mob_sunspring_villager +npc_altruis_the_sufferer +npc_greatmother_geyah +npc_lantresor_of_the_blade +npc_creditmarker_visit_with_ancestors +EndContentData */ + +#include "precompiled.h" + +/*###### +## mob_shattered_rumbler - this should be done with ACID +######*/ + +struct MANGOS_DLL_DECL mob_shattered_rumblerAI : public ScriptedAI +{ + bool Spawn; + + mob_shattered_rumblerAI(Creature *c) : ScriptedAI(c) {Reset();} + + void Reset() + { + Spawn = false; + } + + void Aggro(Unit* who) {} + + void SpellHit(Unit *Hitter, const SpellEntry *Spellkind) + { + if(Spellkind->Id == 32001 && !Spawn) + { + float x = m_creature->GetPositionX(); + float y = m_creature->GetPositionY(); + float z = m_creature->GetPositionZ(); + + Hitter->SummonCreature(18181,x+(0.7 * (rand()%30)),y+(rand()%5),z,0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,60000); + Hitter->SummonCreature(18181,x+(rand()%5),y-(rand()%5),z,0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,60000); + Hitter->SummonCreature(18181,x-(rand()%5),y+(0.5 *(rand()%60)),z,0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,60000); + m_creature->setDeathState(CORPSE); + Spawn = true; + } + return; + } +}; +CreatureAI* GetAI_mob_shattered_rumbler(Creature *_Creature) +{ + return new mob_shattered_rumblerAI (_Creature); +} + +/*###### +## mob_lump +######*/ + +#define SPELL_VISUAL_SLEEP 16093 +#define SPELL_SPEAR_THROW 32248 + +#define LUMP_SAY0 "In Nagrand, food hunt ogre!" +#define LUMP_SAY1 "You taste good with maybe a little salt and pepper." + +#define LUMP_DEFEAT "OK, OK! Lump give up!" + +struct MANGOS_DLL_DECL mob_lumpAI : public ScriptedAI +{ + mob_lumpAI(Creature *c) : ScriptedAI(c) + { + bReset = false; + Reset(); + } + + uint32 Reset_Timer; + uint32 Spear_Throw_Timer; + bool bReset; + + void Reset() + { + Reset_Timer = 60000; + Spear_Throw_Timer = 2000; + + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void DamageTaken(Unit *done_by, uint32 & damage) + { + if (done_by->GetTypeId() == TYPEID_PLAYER && (m_creature->GetHealth() - damage)*100 / m_creature->GetMaxHealth() < 30) + { + if (!bReset && ((Player*)done_by)->GetQuestStatus(9918) == QUEST_STATUS_INCOMPLETE) + { + //Take 0 damage + damage = 0; + + ((Player*)done_by)->AttackStop(); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); + m_creature->CombatStop(); + m_creature->setFaction(1080); //friendly + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, PLAYER_STATE_SIT); + m_creature->Say(LUMP_DEFEAT, LANG_UNIVERSAL, 0); + + bReset = true; + } + } + } + + void Aggro(Unit *who) + { + if (m_creature->HasAura(SPELL_VISUAL_SLEEP,0)) + m_creature->RemoveAura(SPELL_VISUAL_SLEEP,0); + + if (!m_creature->IsStandState()) + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, PLAYER_STATE_NONE); + + switch(rand()%2) + { + case 0: + DoSay(LUMP_SAY0,LANG_UNIVERSAL,NULL); + break; + case 1: + DoSay(LUMP_SAY1,LANG_UNIVERSAL,NULL); + break; + } + } + + void UpdateAI(const uint32 diff) + { + //check if we waiting for a reset + if (bReset) + { + if (Reset_Timer < diff) + { + EnterEvadeMode(); + bReset = false; + m_creature->setFaction(1711); //hostile + } + else Reset_Timer -= diff; + } + + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //Spear_Throw_Timer + if (Spear_Throw_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_SPEAR_THROW); + Spear_Throw_Timer = 20000; + }else Spear_Throw_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_lump(Creature *_creature) +{ + return new mob_lumpAI(_creature); +} + +bool GossipHello_mob_lump(Player *player, Creature *_Creature) +{ + if (player->GetQuestStatus(9918) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM( 0, "I need answers, ogre!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + player->SEND_GOSSIP_MENU(9352, _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_mob_lump(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF: + player->ADD_GOSSIP_ITEM( 0, "Why are Boulderfist out this far? You know that this is Kurenai territory.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->SEND_GOSSIP_MENU(9353, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+1: + player->ADD_GOSSIP_ITEM( 0, "And you think you can just eat anything you want? You're obviously trying to eat the Broken of Telaar.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->SEND_GOSSIP_MENU(9354, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + player->ADD_GOSSIP_ITEM( 0, "This means war, Lump! War I say!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->SEND_GOSSIP_MENU(9355, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + player->SEND_GOSSIP_MENU(9356, _Creature->GetGUID()); + player->TalkedToCreature(18354, _Creature->GetGUID()); + break; + } + return true; +} + +/*#### +# mob_sunspring_villager - should be done with ACID +####*/ + +struct MANGOS_DLL_DECL mob_sunspring_villagerAI : public ScriptedAI +{ + mob_sunspring_villagerAI(Creature *c) : ScriptedAI(c) {Reset();} + + void Reset() + { + m_creature->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 32); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1,7); // lay down + } + + void Aggro(Unit *who) {} + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if(spell->Id == 32146) + { + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + m_creature->RemoveCorpse(); + } + } +}; +CreatureAI* GetAI_mob_sunspring_villager(Creature *_Creature) +{ + return new mob_sunspring_villagerAI (_Creature); +} + +/*###### +## npc_altruis_the_sufferer +######*/ + +bool GossipHello_npc_altruis_the_sufferer(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + //gossip before obtaining Survey the Land + if ( player->GetQuestStatus(9991) == QUEST_STATUS_NONE ) + player->ADD_GOSSIP_ITEM( 0, "I see twisted steel and smell sundered earth.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+10); + + //gossip when Survey the Land is incomplete (technically, after the flight) + if (player->GetQuestStatus(9991) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM( 0, "Well...?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+20); + + //wowwiki.com/Varedis + if (player->GetQuestStatus(10646) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM( 0, "[PH] Story about Illidan's Pupil", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+30); + + player->SEND_GOSSIP_MENU(9419, _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_altruis_the_sufferer(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF+10: + player->ADD_GOSSIP_ITEM( 0, "Legion?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->SEND_GOSSIP_MENU(9420, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+11: + player->ADD_GOSSIP_ITEM( 0, "And now?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 12); + player->SEND_GOSSIP_MENU(9421, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+12: + player->ADD_GOSSIP_ITEM( 0, "How do you see them now?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 13); + player->SEND_GOSSIP_MENU(9422, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+13: + player->ADD_GOSSIP_ITEM( 0, "Forge camps?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 14); + player->SEND_GOSSIP_MENU(9423, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+14: + player->SEND_GOSSIP_MENU(9424, _Creature->GetGUID()); + break; + + case GOSSIP_ACTION_INFO_DEF+20: + player->ADD_GOSSIP_ITEM( 0, "Ok.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 21); + player->SEND_GOSSIP_MENU(9427, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+21: + player->CLOSE_GOSSIP_MENU(); + player->AreaExploredOrEventHappens(9991); + break; + + case GOSSIP_ACTION_INFO_DEF+30: + player->ADD_GOSSIP_ITEM( 0, "[PH] Story done", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31); + player->SEND_GOSSIP_MENU(384, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+31: + player->CLOSE_GOSSIP_MENU(); + player->AreaExploredOrEventHappens(10646); + break; + } + return true; +} + +bool QuestAccept_npc_altruis_the_sufferer(Player *player, Creature *creature, Quest const *quest ) +{ + if ( !player->GetQuestRewardStatus(9991) ) //Survey the Land, q-id 9991 + { + player->CLOSE_GOSSIP_MENU(); + + std::vector nodes; + + nodes.resize(2); + nodes[0] = 113; //from + nodes[1] = 114; //end at + player->ActivateTaxiPathTo(nodes); //TaxiPath 532 + } + return true; +} + +/*###### +## npc_greatmother_geyah +######*/ + +//all the textId's for the below is unknown, but i do believe the gossip item texts are proper. +bool GossipHello_npc_greatmother_geyah(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if (player->GetQuestStatus(10044) == QUEST_STATUS_INCOMPLETE) + { + player->ADD_GOSSIP_ITEM( 0, "Hello, Greatmother. Garrosh told me that you wanted to speak with me.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(),_Creature->GetGUID()); + } + else if (player->GetQuestStatus(10172) == QUEST_STATUS_INCOMPLETE) + { + player->ADD_GOSSIP_ITEM( 0, "Garrosh is beyond redemption, Greatmother. I fear that in helping the Mag'har, I have convinced Garrosh that he is unfit to lead.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 10); + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(),_Creature->GetGUID()); + } + else + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(),_Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_greatmother_geyah(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: + player->ADD_GOSSIP_ITEM( 0, "You raised all of the orcs here, Greatmother?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + player->ADD_GOSSIP_ITEM( 0, "Do you believe that?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: + player->ADD_GOSSIP_ITEM( 0, "What can be done? I have tried many different things. I have done my best to help the people of Nagrand. Each time I have approached Garrosh, he has dismissed me.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: + player->ADD_GOSSIP_ITEM( 0, "Left? How can you choose to leave?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: + player->ADD_GOSSIP_ITEM( 0, "What is this duty?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: + player->ADD_GOSSIP_ITEM( 0, "Is there anything I can do for you, Greatmother?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: + player->AreaExploredOrEventHappens(10044); + player->CLOSE_GOSSIP_MENU(); + break; + + case GOSSIP_ACTION_INFO_DEF + 10: + player->ADD_GOSSIP_ITEM( 0, "I have done all that I could, Greatmother. I thank you for your kind words.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 11: + player->ADD_GOSSIP_ITEM( 0, "Greatmother, you are the mother of Durotan?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 12); + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 12: + player->ADD_GOSSIP_ITEM( 0, "Greatmother, I never had the honor. Durotan died long before my time, but his heroics are known to all on my world. The orcs of Azeroth reside in a place known as Durotar, named after your son. And ... (You take a moment to breathe and think through what you are about to tell the Greatmother.)", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 13); + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 13: + player->ADD_GOSSIP_ITEM( 0, "It is my Warchief, Greatmother. The leader of my people. From my world. He ... He is the son of Durotan. He is your grandchild.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 14); + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 14: + player->ADD_GOSSIP_ITEM( 0, "I will return to Azeroth at once, Greatmother.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 15); + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 15: + player->AreaExploredOrEventHappens(10172); + player->CLOSE_GOSSIP_MENU(); + break; + } + return true; +} + +/*###### +## npc_lantresor_of_the_blade +######*/ + +bool GossipHello_npc_lantresor_of_the_blade(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if (player->GetQuestStatus(10107) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(10108) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM( 0, "I have killed many of your ogres, Lantresor. I have no fear.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + player->SEND_GOSSIP_MENU(9361, _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_lantresor_of_the_blade(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF: + player->ADD_GOSSIP_ITEM( 0, "Should I know? You look like an orc to me.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->SEND_GOSSIP_MENU(9362, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+1: + player->ADD_GOSSIP_ITEM( 0, "And the other half?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->SEND_GOSSIP_MENU(9363, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + player->ADD_GOSSIP_ITEM( 0, "I have heard of your kind, but I never thought to see the day when I would meet a half-breed.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->SEND_GOSSIP_MENU(9364, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + player->ADD_GOSSIP_ITEM( 0, "My apologies. I did not mean to offend. I am here on behalf of my people.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->SEND_GOSSIP_MENU(9365, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + player->ADD_GOSSIP_ITEM( 0, "My people ask that you pull back your Boulderfist ogres and cease all attacks on our territories. In return, we will also pull back our forces.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->SEND_GOSSIP_MENU(9366, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + player->ADD_GOSSIP_ITEM( 0, "We will fight you until the end, then, Lantresor. We will not stand idly by as you pillage our towns and kill our people.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->SEND_GOSSIP_MENU(9367, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+6: + player->ADD_GOSSIP_ITEM( 0, "What do I need to do?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->SEND_GOSSIP_MENU(9368, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+7: + player->SEND_GOSSIP_MENU(9369, _Creature->GetGUID()); + if (player->GetQuestStatus(10107) == QUEST_STATUS_INCOMPLETE) + player->AreaExploredOrEventHappens(10107); + if (player->GetQuestStatus(10108) == QUEST_STATUS_INCOMPLETE) + player->AreaExploredOrEventHappens(10108); + break; + } + return true; +} + +/*###### +## npc_creditmarker_visist_with_ancestors (Quest 10085) +######*/ + +struct MANGOS_DLL_DECL npc_creditmarker_visit_with_ancestorsAI : public ScriptedAI +{ + npc_creditmarker_visit_with_ancestorsAI(Creature* c) : ScriptedAI(c) { Reset(); } + + void Reset() {} + + void Aggro(Unit* who) {} + + void MoveInLineOfSight(Unit *who) + { + if(!who) + return; + + if(who->GetTypeId() == TYPEID_PLAYER) + { + if(((Player*)who)->GetQuestStatus(10085) == QUEST_STATUS_INCOMPLETE) + { + uint32 creditMarkerId = m_creature->GetEntry(); + if((creditMarkerId >= 18840) && (creditMarkerId <= 18843)) + { + // 18840: Sunspring, 18841: Laughing, 18842: Garadar, 18843: Bleeding + if(!((Player*)who)->GetReqKillOrCastCurrentCount(10085, creditMarkerId)) + ((Player*)who)->KilledMonster(creditMarkerId, m_creature->GetGUID()); + } + } + } + } +}; + +CreatureAI* GetAI_npc_creditmarker_visit_with_ancestors(Creature *_Creature) +{ + return new npc_creditmarker_visit_with_ancestorsAI (_Creature); +} + +/*###### +## AddSC +######*/ + +void AddSC_nagrand() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="mob_shattered_rumbler"; + newscript->GetAI = GetAI_mob_shattered_rumbler; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_lump"; + newscript->GetAI = GetAI_mob_lump; + newscript->pGossipHello = &GossipHello_mob_lump; + newscript->pGossipSelect = &GossipSelect_mob_lump; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_sunspring_villager"; + newscript->GetAI = GetAI_mob_sunspring_villager; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_altruis_the_sufferer"; + newscript->pGossipHello = &GossipHello_npc_altruis_the_sufferer; + newscript->pGossipSelect = &GossipSelect_npc_altruis_the_sufferer; + newscript->pQuestAccept = &QuestAccept_npc_altruis_the_sufferer; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_greatmother_geyah"; + newscript->pGossipHello = &GossipHello_npc_greatmother_geyah; + newscript->pGossipSelect = &GossipSelect_npc_greatmother_geyah; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_lantresor_of_the_blade"; + newscript->pGossipHello = &GossipHello_npc_lantresor_of_the_blade; + newscript->pGossipSelect = &GossipSelect_npc_lantresor_of_the_blade; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_creditmarker_visit_with_ancestors"; + newscript->GetAI = GetAI_npc_creditmarker_visit_with_ancestors; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_anubrekhan.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_anubrekhan.cpp new file mode 100644 index 00000000000..d2dbd710cc9 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_anubrekhan.cpp @@ -0,0 +1,215 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Anubrekhan +SD%Complete: 100 +SDComment: +SDCategory: Naxxramas +EndScriptData */ + +#include "precompiled.h" + +#define SAY_AGGRO1 "Just a little taste..." +#define SAY_AGGRO2 "There is no way out." +#define SAY_AGGRO3 "Yes, Run! It makes the blood pump faster!" +#define SAY_GREET "Ahh... welcome to my parlor" +#define SAY_TAUNT1 "I hear little hearts beating. Yesss... beating faster now. Soon the beating will stop." +#define SAY_TAUNT2 "Where to go? What to do? So many choices that all end in pain, end in death." +#define SAY_TAUNT3 "Which one shall I eat first? So difficult to choose... the all smell so delicious." +#define SAY_TAUNT4 "Closer now... tasty morsels. I've been too long without food. Without blood to drink." +#define SAY_SLAY "Shh... it will all be over soon." + +#define SOUND_AGGRO1 8785 +#define SOUND_AGGRO2 8786 +#define SOUND_AGGRO3 8787 +#define SOUND_GREET 8788 +#define SOUND_TAUNT1 8790 +#define SOUND_TAUNT2 8791 +#define SOUND_TAUNT3 8792 +#define SOUND_TAUNT4 8793 +#define SOUND_SLAY 8789 + +#define SPELL_IMPALE 28783 //May be wrong spell id. Causes more dmg than I expect +#define SPELL_LOCUSTSWARM 28785 //This is a self buff that triggers the dmg debuff +#define SPELL_SUMMONGUARD 29508 //Summons 1 crypt guard at targeted location + +#define SPELL_SELF_SPAWN_5 29105 //This spawns 5 corpse scarabs ontop of us (most likely the player casts this on death) +#define SPELL_SELF_SPAWN_10 28864 //This is used by the crypt guards when they die + +struct MANGOS_DLL_DECL boss_anubrekhanAI : public ScriptedAI +{ + boss_anubrekhanAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Impale_Timer; + uint32 LocustSwarm_Timer; + uint32 Summon_Timer; + bool HasTaunted; + + void Reset() + { + Impale_Timer = 15000; //15 seconds + LocustSwarm_Timer = 80000 + (rand()%40000); //Random time between 80 seconds and 2 minutes for initial cast + Summon_Timer = LocustSwarm_Timer + 45000; //45 seconds after initial locust swarm + } + + void KilledUnit(Unit* Victim) + { + //Force the player to spawn corpse scarabs via spell + Victim->CastSpell(Victim, SPELL_SELF_SPAWN_5, true); + + if (rand()%5) + return; + + DoYell(SAY_SLAY, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY); + } + + void Aggro(Unit *who) + { + switch(rand()%3) + { + case 0: + DoYell(SAY_AGGRO1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO1); + break; + case 1: + DoYell(SAY_AGGRO2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO2); + break; + case 2: + DoYell(SAY_AGGRO3, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO3); + break; + } + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || m_creature->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + float attackRadius = m_creature->GetAttackDistance(who); + if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) + { + if(who->HasStealthAura()) + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + //Begin melee attack if we are within range + DoStartAttackAndMovement(who); + + if (!InCombat) + { + switch(rand()%3) + { + case 0: + DoYell(SAY_AGGRO1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO1); + break; + case 1: + DoYell(SAY_AGGRO2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO2); + break; + case 2: + DoYell(SAY_AGGRO3, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO3); + break; + } + } + } + else if (!HasTaunted && m_creature->IsWithinDistInMap(who, 60.0f)) + { + switch(rand()%5) + { + case 0: + DoYell(SAY_TAUNT1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_TAUNT1); + break; + case 1: + DoYell(SAY_TAUNT2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_TAUNT2); + break; + case 2: + DoYell(SAY_TAUNT3, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_TAUNT3); + break; + case 3: + DoYell(SAY_TAUNT4, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_TAUNT4); + break; + case 4: + DoYell(SAY_GREET, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_GREET); + break; + } + HasTaunted = true; + } + } + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //Impale_Timer + if (Impale_Timer < diff) + { + //Cast Impale on a random target + //Do NOT cast it when we are afflicted by locust swarm + if (!m_creature->HasAura(SPELL_LOCUSTSWARM,1)) + { + Unit* target = NULL; + + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target)DoCast(target,SPELL_IMPALE); + } + + Impale_Timer = 15000; + }else Impale_Timer -= diff; + + //LocustSwarm_Timer + if (LocustSwarm_Timer < diff) + { + DoCast(m_creature, SPELL_LOCUSTSWARM); + LocustSwarm_Timer = 90000; + }else LocustSwarm_Timer -= diff; + + //Summon_Timer + if (Summon_Timer < diff) + { + DoCast(m_creature, SPELL_SUMMONGUARD); + Summon_Timer = 45000; + }else Summon_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_anubrekhan(Creature *_Creature) +{ + return new boss_anubrekhanAI (_Creature); +} + +void AddSC_boss_anubrekhan() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_anubrekhan"; + newscript->GetAI = GetAI_boss_anubrekhan; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_faerlina.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_faerlina.cpp new file mode 100644 index 00000000000..3faf9ad9634 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_faerlina.cpp @@ -0,0 +1,202 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Faerlina +SD%Complete: 50 +SDComment: Without Mindcontrol boss cannot be defeated +SDCategory: Naxxramas +EndScriptData */ + +#include "precompiled.h" + +#define SAY_GREET "Your old lives, your mortal desires, mean nothing. You are acolytes of the master now, and you will serve the cause without question! The greatest glory is to die in the master's service!" +#define SAY_AGGRO1 "Slay them in the master's name!" +#define SAY_AGGRO2 "You cannot hide from me!" +#define SAY_AGGRO3 "Kneel before me, worm!" +#define SAY_AGGRO4 "Run while you still can!" +#define SAY_SLAY1 "You have failed!" +#define SAY_SLAY2 "Pathetic wretch!" +#define SAY_DEATH "The master... will avenge me!" +#define SAY_RANDOM_AGGRO "???" + +#define SOUND_GREET 8799 +#define SOUND_AGGRO1 8794 +#define SOUND_AGGRO2 8795 +#define SOUND_AGGRO3 8796 +#define SOUND_AGGRO4 8797 +#define SOUND_SLAY1 8800 +#define SOUND_SLAY2 8801 +#define SOUND_DEATH 8798 +#define SOUND_RANDOM_AGGRO 8955 + +#define SPELL_POSIONBOLT_VOLLEY 28796 +#define SPELL_RAINOFFIRE 28794 //Not sure if targeted AoEs work if casted directly upon a player +#define SPELL_ENRAGE 26527 + +struct MANGOS_DLL_DECL boss_faerlinaAI : public ScriptedAI +{ + boss_faerlinaAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 PoisonBoltVolley_Timer; + uint32 RainOfFire_Timer; + uint32 Enrage_Timer; + bool HasTaunted; + + void Reset() + { + PoisonBoltVolley_Timer = 8000; + RainOfFire_Timer = 16000; + Enrage_Timer = 60000; + HasTaunted = false; + } + + void Aggro(Unit *who) + { + switch (rand()%4) + { + case 0: + DoYell(SAY_AGGRO1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO1); + break; + case 1: + DoYell(SAY_AGGRO2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO2); + break; + case 2: + DoYell(SAY_AGGRO3,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO3); + break; + case 3: + DoYell(SAY_AGGRO4,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO4); + break; + } + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || m_creature->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + float attackRadius = m_creature->GetAttackDistance(who); + if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE) + { + if(who->HasStealthAura()) + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + DoStartAttackAndMovement(who); + //Say our dialog on initial aggro + if (!InCombat) + { + switch (rand()%4) + { + case 0: + DoYell(SAY_AGGRO1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO1); + break; + case 1: + DoYell(SAY_AGGRO2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO2); + break; + case 2: + DoYell(SAY_AGGRO3,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO3); + break; + case 3: + DoYell(SAY_AGGRO4,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO4); + break; + } + } + } + else if (!HasTaunted && m_creature->IsWithinDistInMap(who, 60.0f)) + { + DoYell(SAY_GREET, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_GREET); + HasTaunted = true; + } + } + } + + void KilledUnit(Unit* victim) + { + switch (rand()%2) + { + case 0: + DoYell(SAY_SLAY1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY1); + break; + case 1: + DoYell(SAY_SLAY2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY2); + break; + } + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DEATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_DEATH); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //PoisonBoltVolley_Timer + if (PoisonBoltVolley_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_POSIONBOLT_VOLLEY); + PoisonBoltVolley_Timer = 11000; + }else PoisonBoltVolley_Timer -= diff; + + //RainOfFire_Timer + if (RainOfFire_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) DoCast(target,SPELL_RAINOFFIRE); + + RainOfFire_Timer = 16000; + }else RainOfFire_Timer -= diff; + + //Enrage_Timer + if (Enrage_Timer < diff) + { + DoCast(m_creature,SPELL_ENRAGE); + Enrage_Timer = 61000; + }else Enrage_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_faerlina(Creature *_Creature) +{ + return new boss_faerlinaAI (_Creature); +} + +void AddSC_boss_faerlina() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_faerlina"; + newscript->GetAI = GetAI_boss_faerlina; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_feugen.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_feugen.cpp new file mode 100644 index 00000000000..fd03b1757f5 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_feugen.cpp @@ -0,0 +1,33 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Feugen +SD%Complete: 0 +SDComment: Merge with Thaddius +SDCategory: Naxxramas +EndScriptData */ + +//Feugen +//8801 aggro Feed you to master! +//8804 slay Feugen make master happy! +//8803 death No... more... Feugen... + +#include "precompiled.h" + +#define SPELL_WARSTOMP 28125 +#define SPELL_MANABURN 28135 +#define SPELL_CHAIN_LIGHTNING 28900 diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_gluth.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_gluth.cpp new file mode 100644 index 00000000000..72b9b6628de --- /dev/null +++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_gluth.cpp @@ -0,0 +1,174 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Gluth +SD%Complete: 100 +SDComment: +SDCategory: Naxxramas +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_MORTALWOUND 25646 +#define SPELL_DECIMATE 28374 +#define SPELL_TERRIFYINGROAR 29685 +#define SPELL_FRENZY 19812 +#define SPELL_ENRAGE 28747 + +#define ADD_1X 3269.590 +#define ADD_1Y -3161.287 +#define ADD_1Z 297.423 + +#define ADD_2X 3277.797 +#define ADD_2Y -3170.352 +#define ADD_2Z 297.423 + +#define ADD_3X 3267.049 +#define ADD_3Y -3172.820 +#define ADD_3Z 297.423 + +#define ADD_4X 3252.157 +#define ADD_4Y -3132.135 +#define ADD_4Z 297.423 + +#define ADD_5X 3259.990 +#define ADD_5Y -3126.590 +#define ADD_5Z 297.423 + +#define ADD_6X 3259.815 +#define ADD_6Y -3137.576 +#define ADD_6Z 297.423 + +#define ADD_7X 3308.030 +#define ADD_7Y -3132.135 +#define ADD_7Z 297.423 + +#define ADD_8X 3303.046 +#define ADD_8Y -3180.682 +#define ADD_8Z 297.423 + +#define ADD_9X 3313.283 +#define ADD_9Y -3180.766 +#define ADD_9Z 297.423 + +struct MANGOS_DLL_DECL boss_gluthAI : public ScriptedAI +{ + boss_gluthAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 MortalWound_Timer; + uint32 Decimate_Timer; + uint32 TerrifyingRoar_Timer; + uint32 Frenzy_Timer; + uint32 Enrage_Timer; + uint32 Summon_Timer; + + void Reset() + { + MortalWound_Timer = 8000; + Decimate_Timer = 100000; + TerrifyingRoar_Timer = 21000; + Frenzy_Timer = 15000; + Enrage_Timer = 304000; + Summon_Timer = 10000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //MortalWound_Timer + if (MortalWound_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_MORTALWOUND); + MortalWound_Timer = 10000; + }else MortalWound_Timer -= diff; + + //Decimate_Timer + if (Decimate_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_DECIMATE); + Decimate_Timer = 100000; + }else Decimate_Timer -= diff; + + //TerrifyingRoar_Timer + if (TerrifyingRoar_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_TERRIFYINGROAR); + TerrifyingRoar_Timer = 20000; + }else TerrifyingRoar_Timer -= diff; + + //Frenzy_Timer + if (Frenzy_Timer < diff) + { + DoCast(m_creature,SPELL_FRENZY); + Frenzy_Timer = 10500; + }else Frenzy_Timer -= diff; + + //Enrage_Timer + if (Enrage_Timer < diff) + { + DoCast(m_creature,SPELL_ENRAGE); + Enrage_Timer = 61000; + }else Enrage_Timer -= diff; + + //Summon_Timer + if (Summon_Timer < diff) + { + Unit* target = NULL; + Unit* SummonedZombies = NULL; + + SummonedZombies = m_creature->SummonCreature(16360,ADD_1X,ADD_1Y,ADD_1Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000); + SummonedZombies = m_creature->SummonCreature(16360,ADD_2X,ADD_2Y,ADD_2Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000); + SummonedZombies = m_creature->SummonCreature(16360,ADD_3X,ADD_3Y,ADD_3Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000); + SummonedZombies = m_creature->SummonCreature(16360,ADD_4X,ADD_4Y,ADD_4Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000); + SummonedZombies = m_creature->SummonCreature(16360,ADD_5X,ADD_5Y,ADD_5Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000); + SummonedZombies = m_creature->SummonCreature(16360,ADD_6X,ADD_6Y,ADD_6Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000); + SummonedZombies = m_creature->SummonCreature(16360,ADD_7X,ADD_7Y,ADD_7Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000); + SummonedZombies = m_creature->SummonCreature(16360,ADD_8X,ADD_8Y,ADD_8Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000); + SummonedZombies = m_creature->SummonCreature(16360,ADD_9X,ADD_9Y,ADD_9Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000); + + if (SummonedZombies) + { + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) + SummonedZombies->AddThreat(target,1.0f); + } + + Summon_Timer = 28000; + } else Summon_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_gluth(Creature *_Creature) +{ + return new boss_gluthAI (_Creature); +} + +void AddSC_boss_gluth() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_gluth"; + newscript->GetAI = GetAI_boss_gluth; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_gothik.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_gothik.cpp new file mode 100644 index 00000000000..3be2727fe16 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_gothik.cpp @@ -0,0 +1,62 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Gothik +SD%Complete: 0 +SDComment: Placeholder +SDCategory: Naxxramas +EndScriptData */ + +//Gothik +//8806 spch - Foolishly you have sought your own demise. Brazenly you have disregarded powers beyond your understanding. You have fought hard to invade the realm of the harvester. Now there is only one way out - to walk the lonely path of the damned. +//8808 tlpt - I have waited long enough! Now, you face the harvester of souls! +//8806 slay - Death is the only escape. +//8805 death - I... am... undone! + +#include "precompiled.h" + +//Gothik +#define SPELL_HARVESTSOUL 28679 +#define SPELL_SHADOWBOLT 19729 + +//Unrelenting Trainee +#define SPELL_EAGLECLAW 30285 +#define SPELL_KNOCKDOWN_PASSIVE 6961 + +//Unrelenting Deathknight +#define SPELL_CHARGE 22120 +#define SPELL_SHADOW_MARK 27825 + +//Unrelenting Rider +#define SPELL_UNHOLY_AURA 28340 +#define SPELL_SHADOWBOLT 19729 //Search thru targets and find those who have the SHADOW_MARK to cast this on + +//Spectral Trainee +#define SPELL_ARCANE_EXPLOSION 27989 + +//Spectral Deathknight +#define SPELL_WHIRLWIND 28334 +#define SPELL_SUNDER_ARMOR 25051 //cannot find sunder that reduces armor by 2950 +#define SPELL_CLEAVE 20677 +#define SPELL_MANA_BURN 17631 + +//Spectral Rider +#define SPELL_LIFEDRAIN 24300 +//USES SAME UNHOLY AURA AS UNRELENTING RIDER + +//Spectral Horse +#define SPELL_STOMP 27993 diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_grobbulus.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_grobbulus.cpp new file mode 100644 index 00000000000..cbe7657ed57 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_grobbulus.cpp @@ -0,0 +1,30 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Grobbulus +SD%Complete: 0 +SDComment: Place holder +SDCategory: Naxxramas +EndScriptData */ + +/*Poison Cloud 26590 +Slime Spray 28157 +Fallout slime 28218 +Mutating Injection 28169 +Enrages 26527*/ + +#include "precompiled.h" diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_heigan.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_heigan.cpp new file mode 100644 index 00000000000..147eae49e22 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_heigan.cpp @@ -0,0 +1,46 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Heigan +SD%Complete: 0 +SDComment: Place Holder +SDCategory: Naxxramas +EndScriptData */ + +//Lotheb or Heigan? +//8825 aggro1 - You are mine now! +//8826 aggro2 - I see you! +//8827 aggro3 - You...are next! +//8828 death - +//8829 slay - close your eyes... sleep +//8830 taunt1 - The races of the world will perish. It is only a matter of time. +//8831 taunt2 - I see endless suffering, I see torment, I see rage. I see... everything! +//8832 taunt3 - Soon... the world will tremble! +//8833 taunt4 - The end is upon you. +//8834 taunt5 - Hungry worms will feast on your rotten flesh! + +#include "precompiled.h" + +//Spell used by floor peices to cause damage to players +#define SPELL_ERUPTION 29371 + +//Spells by boss +#define SPELL_WILT 23772 +#define SPELL_FEAVER 29998 + +//Spell by eye stalks +#define SPELL_MIND_FLAY 26143 diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_highlord_mograine.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_highlord_mograine.cpp new file mode 100644 index 00000000000..0641d6d66a3 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_highlord_mograine.cpp @@ -0,0 +1,178 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Highlord_Mograine +SD%Complete: 100 +SDComment: +SDCategory: Naxxramas +EndScriptData */ + +#include "precompiled.h" + +//All horsemen +#define SPELL_SHIELDWALL 29061 +#define SPELL_BESERK 26662 + +// highlord mograine +#define SPELL_MARK_OF_MOGRAINE 28834 +#define SPELL_RIGHTEOUS_FIRE 28882 // Applied as a 25% chance on melee hit to proc. m_creature->GetVictim() + +#define SAY_TAUNT1 "Enough prattling. Let them come! We shall grind their bones to dust." +#define SAY_TAUNT2 "Conserve your anger! Harness your rage! You will all have outlets for your frustration soon enough." +#define SAY_TAUNT3 "Life is meaningless. It is in death that we are truly tested." +#define SAY_AGGRO1 "You seek death?" +#define SAY_AGGRO2 "None shall pass!" +#define SAY_AGGRO3 "Be still!" +#define SAY_SLAY1 "You will find no peace in death." +#define SAY_SLAY2 "The master's will is done." +#define SAY_SPECIAL "Bow to the might of the Highlord!" +#define SAY_DEATH "I... am... released! Perhaps it's not too late to - noo! I need... more time..." + +#define SOUND_TAUNT1 8842 +#define SOUND_TAUNT2 8843 +#define SOUND_TAUNT3 8844 +#define SOUND_AGGRO1 8835 +#define SOUND_AGGRO2 8836 +#define SOUND_AGGRO3 8837 +#define SOUND_SLAY1 8839 +#define SOUND_SLAY2 8840 +#define SOUND_SPECIAL 8841 +#define SOUND_DEATH 8838 + +#define SPIRIT_OF_MOGRAINE 16775 + +struct MANGOS_DLL_DECL boss_highlord_mograineAI : public ScriptedAI +{ + boss_highlord_mograineAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Mark_Timer; + uint32 RighteousFire_Timer; + bool ShieldWall1; + bool ShieldWall2; + + void Reset() + { + Mark_Timer = 20000; // First Horsemen Mark is applied at 20 sec. + RighteousFire_Timer = 2000; // applied approx 1 out of 4 attacks + ShieldWall1 = true; + ShieldWall2 = true; + } + + void InitialYell() + { + if(!InCombat) + { + switch(rand()%3) + { + case 0: + DoYell(SAY_AGGRO1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO1); + break; + case 1: + DoYell(SAY_AGGRO2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO2); + break; + case 2: + DoYell(SAY_AGGRO3,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO3); + break; + } + } + } + + void KilledUnit() + { + switch(rand()%2) + { + case 0: + DoYell(SAY_SLAY1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY1); + break; + case 1: + DoYell(SAY_SLAY2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY2); + break; + } + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DEATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_DEATH); + } + + void Aggro(Unit *who) + { + InitialYell(); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + // Mark of Mograine + if(Mark_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_MARK_OF_MOGRAINE); + Mark_Timer = 12000; + }else Mark_Timer -= diff; + + // Shield Wall - All 4 horsemen will shield wall at 50% hp and 20% hp for 20 seconds + if(ShieldWall1 && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 50) + { + if(ShieldWall1) + { + DoCast(m_creature,SPELL_SHIELDWALL); + ShieldWall1 = false; + } + } + if(ShieldWall2 && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 20) + { + if(ShieldWall2) + { + DoCast(m_creature,SPELL_SHIELDWALL); + ShieldWall2 = false; + } + } + + // Righteous Fire + if(RighteousFire_Timer < diff) + { + if(rand()%4 == 1) // 1/4 + { + DoCast(m_creature->getVictim(),SPELL_RIGHTEOUS_FIRE); + } + RighteousFire_Timer = 2000; + }else RighteousFire_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_highlord_mograine(Creature *_Creature) +{ + return new boss_highlord_mograineAI (_Creature); +} + +void AddSC_boss_highlord_mograine() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_highlord_mograine"; + newscript->GetAI = GetAI_boss_highlord_mograine; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_kelthuzad.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_kelthuzad.cpp new file mode 100644 index 00000000000..4f8e2e9470f --- /dev/null +++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_kelthuzad.cpp @@ -0,0 +1,542 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_KelThuzud +SD%Complete: 0 +SDComment: VERIFY SCRIPT +SDCategory: Naxxramas +EndScriptData */ + +#include "precompiled.h" + +//***THIS SCRIPTS IS UNDER DEVELOPMENT*** +/* +DATA. +This script has been made with info taken from wowwikki... so there are things wrong... +like spell timers and Says. Also there's another major problem as there is no aggroed list +I cannot make Kel'thuzad to target specific party members, that is needed for spells like +Mana Detonation... so what I'm doing untill now is just to cast everything on my main aggroed +target. Sorry for him. +Another bug is that there are spells that are actually NOT working... I have to implement +them first. +Need DISPELL efect +I also don't know the emotes +*/ + +//Kel'thuzad. Still don't know where to use these... +//Dialog +//8878 dialog01 - Our preparations continue as planned, master. +//8881 lich_naxx_dialog01 - It is good that you serve me so faithfully. Soon, all will serve the Lich King and in the end, you shall be rewarded...so long as you do not falter. +//8879 dialog02 - I see no complications... Wait... What is this? +//8882 lich_naxx_dialog03 - Your security measures have failed! See to this interruption immediately! +//8880 dialog03 - Yes, master! +//Bigglesworth death +//No!!! A curse upon you, interlopers! The armies of the Lich King will hunt you down. You will not escape your fate... +//slay +//8818 + +//common needed defines +#define NAXXRAMAS_MAP 533 +//Positional defines +#define ADDX_LEFT_FAR 3783.272705 +#define ADDY_LEFT_FAR -5062.697266 +#define ADDZ_LEFT_FAR 143.711203 +#define ADDO_LEFT_FAR 3.617599 + +#define ADDX_LEFT_MIDDLE 3730.291260 +#define ADDY_LEFT_MIDDLE -5027.239258 +#define ADDZ_LEFT_MIDDLE 143.956909 +#define ADDO_LEFT_MIDDLE 4.461900 + +#define ADDX_LEFT_NEAR 3683.868652 +#define ADDY_LEFT_NEAR -5057.281250 +#define ADDZ_LEFT_NEAR 143.183884 +#define ADDO_LEFT_NEAR 5.237086 + +#define ADDX_RIGHT_FAR 3759.355225 +#define ADDY_RIGHT_FAR -5174.128418 +#define ADDZ_RIGHT_FAR 143.802383 +#define ADDO_RIGHT_FAR 2.170104 + +#define ADDX_RIGHT_MIDDLE 370.724365 +#define ADDY_RIGHT_MIDDLE -5185.123047 +#define ADDZ_RIGHT_MIDDLE 143.928024 +#define ADDO_RIGHT_MIDDLE 1.309310 + +#define ADDX_RIGHT_NEAR 3665.121094 +#define ADDY_RIGHT_NEAR -5138.679199 +#define ADDZ_RIGHT_NEAR 143.183212 +#define ADDO_RIGHT_NEAR 0.604023 + +#define WALKX_LEFT_FAR 3754.431396 +#define WALKY_LEFT_FAR -5080.727734 +#define WALKZ_LEFT_FAR 142.036316 +#define WALKO_LEFT_FAR 3.736189 + +#define WALKX_LEFT_MIDDLE 3724.396484 +#define WALKY_LEFT_MIDDLE -5061.330566 +#define WALKZ_LEFT_MIDDLE 142.032700 +#define WALKO_LEFT_MIDDLE 4.564785 + +#define WALKX_LEFT_NEAR 3687.158424 +#define WALKY_LEFT_NEAR -5076.834473 +#define WALKZ_LEFT_NEAR 142.017319 +#define WALKO_LEFT_NEAR 5.237086 + +#define WALKX_RIGHT_FAR 3687.571777 +#define WALKY_RIGHT_FAR -5126.831055 +#define WALKZ_RIGHT_FAR 142.017807 +#define WALKO_RIGHT_FAR 0.604023 + +#define WALKX_RIGHT_MIDDLE 3707.990733 +#define WALKY_RIGHT_MIDDLE -5151.450195 +#define WALKZ_RIGHT_MIDDLE 142.032562 +#define WALKO_RIGHT_MIDDLE 1.376855 + +#define WALKX_RIGHT_NEAR 3739.500000 +#define WALKY_RIGHT_NEAR -5141.883989 +#define WALKZ_RIGHT_NEAR 142.0141130 +#define WALKO_RIGHT_NEAR 2.121412 + +//spells to be casted +#define SPELL_FROST_BOLT 28478 +#define SPELL_FROST_BOLT_NOVA 28479 +#define SPELL_CHAINS_OF_KELTHUZAD 28410 +#define SPELL_MANA_DETONATION 27819 +#define SPELL_SHADOW_FISURE 27810 +#define SPELL_FROST_BLAST 27808 + +//On Aggro +#define SAY_ARRIVAL1 "PRAY FOR MERCY!" +#define SOUND_ARRIVAL1 8809 +#define SAY_ARRIVAL3 "SCREAM YOR DYING BREATH!" +#define SOUND_ARRIVAL3 8810 +#define SAY_ARRIVAL5 "THE END IS UPON YOU!" +#define SOUND_ARRIVAL5 8811 + +//On Summon +#define SAY_REINFORCEMENTS1 "MINIONS, SERVANTS, SOLDIERS OF THE COLD DARK, OBEY THE CALL OF KEL'THUZAD!" +#define SOUND_REINFORCEMENTS1 8819 +#define SAY_REINFORCEMENTS2 "MASTER, I REQUIRE AID!" +#define SOUND_REINFORCEMENTS2 8816 +#define SAY_LICH_NAXX_SUMMON "VERY WELL. WARRIORS OF THE FROZEN WASTES RISE UP!. I COMMAND YOU TO FIGHT, KILL AND DIE AND DIE FOR YOUR MASTER! LET NONE SURVIVE!" +#define SOUND_LICH_NAXX_SUMMON 8824 + +//Random 1/4 taunt said when player enters 300 yards +#define SAY_TAUNT01 "WHO DARES VIOLATE THE SACTITY OF MY DOMAIN? BE WARNED, ALL WHO TRASPASS HERE ARE DOOMED" +#define SOUND_TAUNT01 8820 +#define SAY_TAUNT02 "FOOLS, YOU THINK YOURSELVES TRIUMPHANT? YOU HAVE ONLY TAKEN ONE STEP CLOSER TO THE ABYSS!" +#define SOUND_TAUNT02 8821 +#define SAY_TAUNT03 "I GROW TIRED OF THESE GAMES. PROCEED, AND I WILL BANISH YOUR SOULS TO OBLIVION!" +#define SOUND_TAUNT03 8822 +#define SAY_TAUNT04 "YOU HAVE NO IDEA WHAT HORRORS LIE AHEAD. YOU HAVE SEEN NOTHING! THE FROZEN HEART OF NAXXRAMAS AWAITS YOU!" +#define SOUND_TAUNT04 8823 + +//On kill unit +#define SAY_SLAY "THE DARK VOID AWAITS YOU!" +#define SOUND_SLAY 8817 + +//Specials +#define SAY_FROST "I WILL FREEZE THE BLOOD IN YOUR VEINS!" +#define SOUND_FROST 8815 +#define SAY_CHAIN1 "YOUR SOUL IS BOUND TO ME NOW!" +#define SOUND_CHAIN1 8812 +#define SAY_CHAIN2 "THERE WILL BE NO ESCAPE!" +#define SOUND_CHAIN2 8813 +#define SAY_SPECIAL1 "YOUR PETTY MAGICS ARE NO CHALLENGE TO THE MIGTH OF THE SCOURGE" +#define SOUND_SPECIAL1 9088 +#define SAY_SPECIAL2 "ENOUGH! I GROW TIRED OF THESE DISTRACTIONS!" +#define SOUND_SPECIAL2 9090 +#define SAY_DISPEL "FOOLS, YOU HAVE SPREAD YOUR POWERS TOO THIN. BE FREE, MY MINIONS!" +#define SOUND_DISPEL 9089 + +//On death +#define SAY_DEATH "DO NOT REJOICE... YOUR VICTORY IS A HOLLOW ONE... FOR I SHALL RETURN WITH POWERS BEYOND YOUR IMAGINING!" +#define SOUND_DEATH 8814 + +struct MANGOS_DLL_DECL boss_kelthuzadAI : public ScriptedAI +{ + boss_kelthuzadAI(Creature* c) : ScriptedAI(c) + { + GuardiansOfIcecrown[0] = 0; + GuardiansOfIcecrown[1] = 0; + GuardiansOfIcecrown[2] = 0; + GuardiansOfIcecrown[3] = 0; + GuardiansOfIcecrown[4] = 0; + GuardiansOfIcecrown_Count = 0; + Reset(); + } + + uint64 GuardiansOfIcecrown[5]; + uint32 GuardiansOfIcecrown_Count; + uint32 GuardiansOfIcecrown_Timer; + uint32 FrostBolt_Timer; + uint32 FrostBoltNova_Timer; + uint32 ChainsOfKelthuzad_Timer; + uint32 ManaDetonation_Timer; + uint32 ShadowFisure_Timer; + uint32 FrostBlast_Timer; + uint32 ChainsOfKelthuzad_Targets; + uint32 Phase1_Timer; + bool Phase2; + bool Phase3; + + void Reset() + { + FrostBolt_Timer = (rand()%60)*1000; //It won't be more than a minute without cast it + FrostBoltNova_Timer = 15000; //Cast every 15 seconds + ChainsOfKelthuzad_Timer = (rand()%30+30)*1000; //Cast no sooner than once every 30 seconds + ManaDetonation_Timer = 20000; //Seems to cast about every 20 seconds + ShadowFisure_Timer = 25000; //25 seconds + FrostBlast_Timer = (rand()%30+30)*1000; //Random time between 30-60 seconds + GuardiansOfIcecrown_Timer = 5000; //5 seconds for summoning each Guardian of Icecrown in phase 3 + + for(int i=0; i<5; i++) + if(GuardiansOfIcecrown[i]) + { + //delete creature + Unit* pUnit = Unit::GetUnit((*m_creature), GuardiansOfIcecrown[i]); + if (pUnit && pUnit->isAlive()) + pUnit->DealDamage(pUnit, pUnit->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + GuardiansOfIcecrown[i] = 0; + } + + Phase1_Timer = 310000; //Phase 1 lasts 5 minutes and 10 seconds + Phase2 = false; + Phase3 = false; + } + + void KilledUnit() + { + if (rand()%5) + return; + + DoYell(SAY_SLAY, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY); + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DEATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_DEATH); + for(int i=0; i<5; i++) + if(GuardiansOfIcecrown[i]) + { + Unit* pUnit = Unit::GetUnit((*m_creature), GuardiansOfIcecrown[i]); + if (!pUnit || !pUnit->isAlive()) + continue; + + pUnit->CombatStop(); + float Walk_Pos_X; + float Walk_Pos_Y; + float Walk_Pos_Z; + switch(rand()%6) + { + case 0: + Walk_Pos_X = ADDX_LEFT_FAR; + Walk_Pos_Y = ADDY_LEFT_FAR; + Walk_Pos_Z = ADDZ_LEFT_FAR; + break; + case 1: + Walk_Pos_X = ADDX_LEFT_MIDDLE; + Walk_Pos_Y = ADDY_LEFT_MIDDLE; + Walk_Pos_Z = ADDZ_LEFT_MIDDLE; + break; + case 2: + Walk_Pos_X = ADDX_LEFT_NEAR; + Walk_Pos_Y = ADDY_LEFT_NEAR; + Walk_Pos_Z = ADDZ_LEFT_NEAR; + break; + case 3: + Walk_Pos_X = ADDX_RIGHT_FAR; + Walk_Pos_Y = ADDY_RIGHT_FAR; + Walk_Pos_Z = ADDZ_RIGHT_FAR; + break; + case 4: + Walk_Pos_X = ADDX_RIGHT_MIDDLE; + Walk_Pos_Y = ADDY_RIGHT_MIDDLE; + Walk_Pos_Z = ADDZ_RIGHT_MIDDLE; + break; + case 5: + Walk_Pos_X = ADDX_RIGHT_NEAR; + Walk_Pos_Y = ADDY_RIGHT_NEAR; + Walk_Pos_Z = ADDZ_RIGHT_NEAR; + break; + } + pUnit->SendMonsterMoveWithSpeed(Walk_Pos_X, Walk_Pos_Y, Walk_Pos_Z,MOVEMENTFLAG_WALK_MODE); + } + } + + void SayInitialAggro() //randomly select 1 of 3 say for aggro + { + switch(rand()%3) + { + case 0: + DoYell(SAY_ARRIVAL1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_ARRIVAL1); + break; + case 1: + DoYell(SAY_ARRIVAL3,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_ARRIVAL3); + break; + case 2: + DoYell(SAY_ARRIVAL5,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_ARRIVAL5); + break; + } + } + + void Aggro(Unit* who) + { + switch(rand()%3) + { + case 0: + DoYell(SAY_ARRIVAL1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_ARRIVAL1); + break; + case 1: + DoYell(SAY_ARRIVAL3,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_ARRIVAL3); + break; + case 2: + DoYell(SAY_ARRIVAL5,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_ARRIVAL5); + break; + } + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget()) + return; + + if(m_creature->getVictim() && m_creature->isAlive()) + { + //Check for Frost Bolt + if(FrostBolt_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FROST_BOLT); + + if(rand()%2 == 0) + { + DoYell(SAY_FROST,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_FROST); + } + //Cast again on time + FrostBolt_Timer = (rand()%60)*1000; + } + else FrostBolt_Timer -= diff; + + //Check for Frost Bolt Nova + if(FrostBoltNova_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FROST_BOLT_NOVA); + + if(rand()%2 == 0) + { + DoYell(SAY_FROST,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_FROST); + } + + FrostBoltNova_Timer = 15000; + } + else FrostBoltNova_Timer -= diff; + + //Check for Chains Of Kelthuzad + if(ChainsOfKelthuzad_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CHAINS_OF_KELTHUZAD); + + if(rand()%2 == 0) + if(rand()%2 == 0) + { + DoYell(SAY_CHAIN1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_CHAIN1); + } + else + { + DoYell(SAY_CHAIN2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_CHAIN2); + } + + //cast again on time + ChainsOfKelthuzad_Timer = (rand()%30+30)*1000; + } + else ChainsOfKelthuzad_Timer -= diff; + + //Check for Mana Detonation + if(ManaDetonation_Timer < diff) + { + //time to cast + //DoCast(m_creature->getVictim(),SPELL_MANA_DETONATION); + + if(rand()%2 == 0) + { + DoYell(SAY_SPECIAL1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_SPECIAL1); + } + ManaDetonation_Timer = 20000; + } + else ManaDetonation_Timer -= diff; + + //Check for Shadow Fissure + if(ShadowFisure_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SHADOW_FISURE); + + if(rand()%2 == 0) + { + DoYell(SAY_SPECIAL2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_SPECIAL2); + } + + ShadowFisure_Timer = 25000; + } + else ShadowFisure_Timer -= diff; + + //Check for Frost Blast + if(FrostBlast_Timer < diff) + { + //time to cast + //DoCast(m_creature->getVictim(),SPELL_FROST_BLAST); + + if(rand()%2 == 0) + { + DoYell(SAY_FROST,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_FROST); + } + + FrostBlast_Timer = (rand()%30+30)*1000; + } + else FrostBlast_Timer -= diff; + + //start phase 3 when we are 40% health + if(!Phase3 && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 40) + { + Phase3 = true; + switch(rand()%2) + { + case 1: + DoYell(SAY_REINFORCEMENTS1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_REINFORCEMENTS1); + break; + case 2: + DoYell(SAY_REINFORCEMENTS2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_REINFORCEMENTS2); + break; + } + //here Lich King should respond to KelThuzad but I don't know which creature to make talk + //so for now just make Kelthuzad says it. + DoPlaySoundToSet(m_creature,SOUND_LICH_NAXX_SUMMON); + } + + if(Phase3 && (GuardiansOfIcecrown_Count < 5)) + if(GuardiansOfIcecrown_Timer < diff) + { + //Summon a Guardian of Icecrown in a random alcove (Creature # 16441) + //uint32 TimeToWalk; + Unit* pUnit = NULL; + float Walk_Pos_X; + float Walk_Pos_Y; + float Walk_Pos_Z; + switch(rand()%6) + { + case 0: + pUnit = m_creature->SummonCreature(16441,ADDX_LEFT_FAR,ADDY_LEFT_FAR,ADDZ_LEFT_FAR,ADDO_LEFT_FAR,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,1000); + //Setting walk position + Walk_Pos_X = WALKX_LEFT_FAR; + Walk_Pos_Y = WALKY_LEFT_FAR; + Walk_Pos_Z = WALKZ_LEFT_FAR; + break; + case 1: + pUnit = m_creature->SummonCreature(16441,ADDX_LEFT_MIDDLE,ADDY_LEFT_MIDDLE,ADDZ_LEFT_MIDDLE,ADDO_LEFT_MIDDLE,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,1000); + //Start moving guardian towards the center of the room + Walk_Pos_X = WALKX_LEFT_MIDDLE; + Walk_Pos_Y = WALKY_LEFT_MIDDLE; + Walk_Pos_Z = WALKZ_LEFT_MIDDLE; + break; + case 2: + pUnit = m_creature->SummonCreature(16441,ADDX_LEFT_NEAR,ADDY_LEFT_NEAR,ADDZ_LEFT_NEAR,ADDO_LEFT_NEAR,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,1000); + //Start moving guardian towards the center of the room + Walk_Pos_X = WALKX_LEFT_NEAR; + Walk_Pos_Y = WALKY_LEFT_NEAR; + Walk_Pos_Z = WALKZ_LEFT_NEAR; + break; + case 3: + + pUnit = m_creature->SummonCreature(16441,ADDX_RIGHT_FAR,ADDY_RIGHT_FAR,ADDZ_RIGHT_FAR,ADDO_RIGHT_FAR,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,1000); + //Start moving guardian towards the center of the room + Walk_Pos_X = WALKX_RIGHT_FAR; + Walk_Pos_Y = WALKY_RIGHT_FAR; + Walk_Pos_Z = WALKZ_RIGHT_FAR; + break; + case 4: + pUnit = m_creature->SummonCreature(16441,ADDX_RIGHT_MIDDLE,ADDY_RIGHT_MIDDLE,ADDZ_RIGHT_MIDDLE,ADDO_RIGHT_MIDDLE,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,1000); + //Start moving guardian towards the center of the room + Walk_Pos_X = WALKX_RIGHT_MIDDLE; + Walk_Pos_Y = WALKY_RIGHT_MIDDLE; + Walk_Pos_Z = WALKZ_RIGHT_MIDDLE; + break; + case 5: + pUnit = m_creature->SummonCreature(16441,ADDX_RIGHT_NEAR,ADDY_RIGHT_NEAR,ADDZ_RIGHT_NEAR,ADDO_RIGHT_NEAR,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,1000); + //Start moving guardian towards the center of the room + Walk_Pos_X = WALKX_RIGHT_NEAR; + Walk_Pos_Y = WALKY_RIGHT_NEAR; + Walk_Pos_Z = WALKZ_RIGHT_NEAR; + break; + } + + if (pUnit) + { + //if we find no one to figth walk to the center + if(!pUnit->isInCombat()) + pUnit->SendMonsterMoveWithSpeed(Walk_Pos_X,Walk_Pos_Y,Walk_Pos_Z,MOVEMENTFLAG_WALK_MODE); + + //Safe storing of creatures + GuardiansOfIcecrown[GuardiansOfIcecrown_Count] = pUnit->GetGUID(); + + //Update guardian count + GuardiansOfIcecrown_Count++; + + } + //5 seconds until summoning next guardian + GuardiansOfIcecrown_Timer = 5000; + } + else GuardiansOfIcecrown_Timer -= diff; + + DoMeleeAttackIfReady(); + } + } +}; + +CreatureAI* GetAI_boss_kelthuzadAI(Creature *_Creature) +{ + return new boss_kelthuzadAI (_Creature); +} + +void AddSC_boss_kelthuzad() +{ + //This script is disabled until it has been throughly tested + + /* + Script *newscript; + newscript = new Script; + newscript->Name="boss_kelthuzad"; + newscript->GetAI = GetAI_boss_kelthuzadAI; + m_scripts[nrscripts++] = newscript; + */ +} diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_lady_blaumeux.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_lady_blaumeux.cpp new file mode 100644 index 00000000000..6946e962aae --- /dev/null +++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_lady_blaumeux.cpp @@ -0,0 +1,147 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Lady_Blaumeux +SD%Complete: 100 +SDComment: +SDCategory: Naxxramas +EndScriptData */ + +#include "precompiled.h" + +//All horsemen +#define SPELL_SHIELDWALL 29061 +#define SPELL_BESERK 26662 + +// lady blaumeux +#define SPELL_MARK_OF_BLAUMEUX 28833 +#define SPELL_VOIDZONE 28863 + +#define SAY_AGGRO "Defend youself!" +#define SAY_TAUNT1 "Come, Zeliek, do not drive them out. Not before we've had our fun." +#define SAY_TAUNT2 "I do hope they stay alive long enough for me to... introduce myself." +#define SAY_TAUNT3 "The first kill goes to me! Anyone care to wager?" +#define SAY_SPECIAL "Your life is mine!" +#define SAY_SLAY "Who's next?" +#define SAY_DEATH "Tou... che!" + +#define SOUND_AGGRO 8892 +#define SOUND_TAUNT1 8896 +#define SOUND_TAUNT2 8897 +#define SOUND_TAUNT3 8898 +#define SOUND_SPECIAL 8895 +#define SOUND_SLAY 8894 +#define SOUND_DEATH 8893 + +#define SPIRIT_OF_BLAUMEUX 16776 + +struct MANGOS_DLL_DECL boss_lady_blaumeuxAI : public ScriptedAI +{ + boss_lady_blaumeuxAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Mark_Timer; + uint32 VoidZone_Timer; + bool ShieldWall1; + bool ShieldWall2; + + void Reset() + { + Mark_Timer = 20000; // First Horsemen Mark is applied at 20 sec. + VoidZone_Timer = 12000; // right + ShieldWall1 = true; + ShieldWall2 = true; + } + + void InitialYell() + { + if(!InCombat) + { + DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO); + } + } + + void KilledUnit() + { + DoYell(SAY_SLAY,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY); + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DEATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_DEATH); + } + + void Aggro(Unit *who) + { + InitialYell(); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + // Mark of Blaumeux + if(Mark_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_MARK_OF_BLAUMEUX); + Mark_Timer = 12000; + }else Mark_Timer -= diff; + + // Shield Wall - All 4 horsemen will shield wall at 50% hp and 20% hp for 20 seconds + if(ShieldWall1 && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 50) + { + if(ShieldWall1) + { + DoCast(m_creature,SPELL_SHIELDWALL); + ShieldWall1 = false; + } + } + if(ShieldWall2 && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 20) + { + if(ShieldWall2) + { + DoCast(m_creature,SPELL_SHIELDWALL); + ShieldWall2 = false; + } + } + + // Void Zone + if(VoidZone_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_VOIDZONE); + VoidZone_Timer = 12000; + }else VoidZone_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_lady_blaumeux(Creature *_Creature) +{ + return new boss_lady_blaumeuxAI (_Creature); +} + +void AddSC_boss_lady_blaumeux() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_lady_blaumeux"; + newscript->GetAI = GetAI_boss_lady_blaumeux; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_loatheb.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_loatheb.cpp new file mode 100644 index 00000000000..cc4390ceb8e --- /dev/null +++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_loatheb.cpp @@ -0,0 +1,216 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Loatheb +SD%Complete: 100 +SDComment: +SDCategory: Naxxramas +EndScriptData */ + +#include "precompiled.h" + +#define SAY_AGGRO1 "You are mine now!" +#define SAY_AGGRO2 "I see you!" +#define SAY_AGGRO3 "You...are next!" +#define SAY_SLAY1 "Close your eyes... sleep!" +#define SAY_SLAY2 "The races of the world will perish. It is only a matter of time." +#define SAY_SLAY3 "I see endless suffering, I see torment, I see rage. I see... everything!" +#define SAY_SLAY4 "Soon... the world will tremble!" +#define SAY_SLAY5 "The end is upon you." +#define SAY_SLAY6 "Hungry worms will feast on your rotten flesh!" +#define SAY_DEATH "" + +#define SOUND_AGGRO1 8825 +#define SOUND_AGGRO2 8826 +#define SOUND_AGGRO3 8827 +#define SOUND_SLAY1 8829 +#define SOUND_SLAY2 8830 +#define SOUND_SLAY3 8831 +#define SOUND_SLAY4 8832 +#define SOUND_SLAY5 8833 +#define SOUND_SLAY6 8834 +#define SOUND_DEATH 8828 + +#define SPELL_CORRUPTED_MIND 29198 +#define SPELL_POISON_AURA 29865 +#define SPELL_INEVITABLE_DOOM 29204 +#define SPELL_REMOVE_CURSE 30281 + +#define ADD_1X 2957.040 +#define ADD_1Y -3997.590 +#define ADD_1Z 274.280 + +#define ADD_2X 2909.130 +#define ADD_2Y -4042.970 +#define ADD_2Z 274.280 + +#define ADD_3X 2861.102 +#define ADD_3Y -3997.901 +#define ADD_3Z 274.280 + +struct MANGOS_DLL_DECL boss_loathebAI : public ScriptedAI +{ + boss_loathebAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 CorruptedMind_Timer; + uint32 PoisonAura_Timer; + uint32 InevitableDoom_Timer; + uint32 InevitableDoom5mins_Timer; + uint32 RemoveCurse_Timer; + uint32 Summon_Timer; + + void Reset() + { + CorruptedMind_Timer = 4000; + PoisonAura_Timer = 2500; + InevitableDoom_Timer = 120000; + InevitableDoom5mins_Timer = 300000; + RemoveCurse_Timer = 30000; + Summon_Timer = 8000; + } + + void Aggro(Unit *who) + { + switch (rand()%3) + { + case 0: + DoYell(SAY_AGGRO1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO1); + break; + case 1: + DoYell(SAY_AGGRO2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO2); + break; + case 2: + DoYell(SAY_AGGRO3,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO3); + break; + } + } + + void KilledUnit(Unit* victim) + { + switch (rand()%6) + { + case 0: + DoYell(SAY_SLAY1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY1); + break; + case 1: + DoYell(SAY_SLAY2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY2); + break; + case 2: + DoYell(SAY_SLAY3,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY3); + break; + case 3: + DoYell(SAY_SLAY4,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY4); + break; + case 4: + DoYell(SAY_SLAY5,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY5); + break; + case 5: + DoYell(SAY_SLAY6,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY6); + break; + } + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DEATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_DEATH); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //CorruptedMind_Timer + if (CorruptedMind_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CORRUPTED_MIND); + CorruptedMind_Timer = 62000; + }else CorruptedMind_Timer -= diff; + + //PoisonAura_Timer + if (PoisonAura_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_POISON_AURA); + PoisonAura_Timer = 60000; + }else PoisonAura_Timer -= diff; + + //InevitableDoom_Timer + if (InevitableDoom_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_INEVITABLE_DOOM); + InevitableDoom_Timer = 120000; + }else InevitableDoom_Timer -= diff; + + //InevitableDoom5mins_Timer + if (InevitableDoom5mins_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_INEVITABLE_DOOM); + InevitableDoom5mins_Timer = 15000; + }else InevitableDoom5mins_Timer -= diff; + + //RemoveCurse_Timer + if (RemoveCurse_Timer < diff) + { + DoCast(m_creature,SPELL_REMOVE_CURSE); + RemoveCurse_Timer = 30000; + }else RemoveCurse_Timer -= diff; + + //Summon_Timer + if (Summon_Timer < diff) + { + Unit* target = NULL; + Unit* SummonedSpores = NULL; + + SummonedSpores = m_creature->SummonCreature(16286,ADD_1X,ADD_1Y,ADD_1Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000); + SummonedSpores = m_creature->SummonCreature(16286,ADD_2X,ADD_2Y,ADD_2Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000); + SummonedSpores = m_creature->SummonCreature(16286,ADD_3X,ADD_3Y,ADD_3Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000); + if (SummonedSpores) + { + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) + SummonedSpores->AddThreat(target,1.0f); + } + + Summon_Timer = 28000; + } else Summon_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_loatheb(Creature *_Creature) +{ + return new boss_loathebAI (_Creature); +} + +void AddSC_boss_loatheb() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_loatheb"; + newscript->GetAI = GetAI_boss_loatheb; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_maexxna.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_maexxna.cpp new file mode 100644 index 00000000000..bd10cff23a0 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_maexxna.cpp @@ -0,0 +1,246 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Maexxna +SD%Complete: 80 +SDComment: +SDCategory: Naxxramas +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_WEBTRAP 28622 //Spell is normally used by the webtrap on the wall NOT by Maexxna +#define SPELL_WEBSPRAY 29484 +#define SPELL_POISONSHOCK 28741 +#define SPELL_NECROTICPOISON 28776 +#define SPELL_ENRAGE 28747 +#define SPELL_SUMMON_SPIDERLING 29434 + +#define LOC_X1 3546.796 +#define LOC_Y1 -3869.082 +#define LOC_Z1 296.450 + +#define LOC_X2 3531.271 +#define LOC_Y2 -3847.424 +#define LOC_Z2 299.450 + +#define LOC_X3 3497.067 +#define LOC_Y3 -3843.384 +#define LOC_Z3 302.384 + +struct MANGOS_DLL_DECL mob_webwrapAI : public ScriptedAI +{ + mob_webwrapAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint64 victimGUID; + + void Reset() + { + victimGUID = 0; + } + + void SetVictim(Unit* victim) + { + if(victim) + { + victimGUID = victim->GetGUID(); + victim->CastSpell(victim, SPELL_WEBTRAP, true); + } + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if(damage > m_creature->GetHealth()) + { + if(victimGUID) + { + Unit* victim = NULL; + victim = Unit::GetUnit((*m_creature), victimGUID); + victim->RemoveAurasDueToSpell(SPELL_WEBTRAP); + } + } + } + + void Aggro(Unit *who) + { + } + + void MoveInLineOfSight(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + } +}; + +struct MANGOS_DLL_DECL boss_maexxnaAI : public ScriptedAI +{ + boss_maexxnaAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 WebTrap_Timer; + uint32 WebSpray_Timer; + uint32 PoisonShock_Timer; + uint32 NecroticPoison_Timer; + uint32 SummonSpiderling_Timer; + bool Enraged; + + void Reset() + { + WebTrap_Timer = 20000; //20 sec init, 40 sec normal + WebSpray_Timer = 40000; //40 seconds + PoisonShock_Timer = 20000; //20 seconds + NecroticPoison_Timer = 30000; //30 seconds + SummonSpiderling_Timer = 30000; //30 sec init, 40 sec normal + Enraged = false; + } + + void Aggro(Unit *who) + { + } + + void DoCastWebWrap() + { + std::list t_list = m_creature->getThreatManager().getThreatList(); + std::vector targets; + + //This spell doesn't work if we only have 1 player on threat list + if(t_list.size() < 2) + return; + + //begin + 1 , so we don't target the one with the highest threat + std::list::iterator itr = t_list.begin(); + std::advance(itr, 1); + for( ; itr!= t_list.end(); ++itr) //store the threat list in a different container + { + Unit *target = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid()); + //only on alive players + if(target && target->isAlive() && target->GetTypeId() == TYPEID_PLAYER ) + targets.push_back( target); + } + + while(targets.size() > 3) + //cut down to size if we have more than 3 targets + targets.erase(targets.begin()+rand()%targets.size()); + + int i = 0; + for(std::vector::iterator itr = targets.begin(); itr!= targets.end(); ++itr, ++i) + { + // Teleport the 3 targets to a location on the wall and summon a Web Wrap on them + Unit *target = *itr; + Creature* Wrap = NULL; + if(target) + { + switch(i) + { + case 0: + DoTeleportPlayer(target, LOC_X1, LOC_Y1, LOC_Z1, target->GetOrientation()); + Wrap = m_creature->SummonCreature(16486, LOC_X1, LOC_Y1, LOC_Z1, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); + break; + case 1: + DoTeleportPlayer(target, LOC_X2, LOC_Y2, LOC_Z2, target->GetOrientation()); + Wrap = m_creature->SummonCreature(16486, LOC_X2, LOC_Y2, LOC_Z2, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); + break; + case 2: + DoTeleportPlayer(target, LOC_X3, LOC_Y3, LOC_Z3, target->GetOrientation()); + Wrap = m_creature->SummonCreature(16486, LOC_X3, LOC_Y3, LOC_Z3, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); + break; + } + if(Wrap) + { + Wrap->setFaction(m_creature->getFaction()); + ((mob_webwrapAI*)Wrap->AI())->SetVictim(target); + } + } + } + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //WebTrap_Timer + if (WebTrap_Timer < diff) + { + DoCastWebWrap(); + WebTrap_Timer = 40000; + }else WebTrap_Timer -= diff; + + //WebSpray_Timer + if (WebSpray_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_WEBSPRAY); + WebSpray_Timer = 40000; + }else WebSpray_Timer -= diff; + + //PoisonShock_Timer + if (PoisonShock_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_POISONSHOCK); + PoisonShock_Timer = 20000; + }else PoisonShock_Timer -= diff; + + //NecroticPoison_Timer + if (NecroticPoison_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_NECROTICPOISON); + NecroticPoison_Timer = 30000; + }else NecroticPoison_Timer -= diff; + + //SummonSpiderling_Timer + if (SummonSpiderling_Timer < diff) + { + DoCast(m_creature, SPELL_SUMMON_SPIDERLING); + SummonSpiderling_Timer = 40000; + }else SummonSpiderling_Timer -= diff; + + //Enrage if not already enraged and below 30% + if (!Enraged && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 30) + { + DoCast(m_creature,SPELL_ENRAGE); + Enraged = true; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_webwrap(Creature* _Creature) +{ + return new mob_webwrapAI (_Creature); +} + +CreatureAI* GetAI_boss_maexxna(Creature *_Creature) +{ + return new boss_maexxnaAI (_Creature); +} + +void AddSC_boss_maexxna() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_maexxna"; + newscript->GetAI = GetAI_boss_maexxna; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_webwrap"; + newscript->GetAI = GetAI_mob_webwrap; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_noth.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_noth.cpp new file mode 100644 index 00000000000..1682344bf91 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_noth.cpp @@ -0,0 +1,180 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Noth +SD%Complete: 40 +SDComment: Missing Balcony stage +SDCategory: Naxxramas +EndScriptData */ + +#include "precompiled.h" + +#define SAY_AGGRO1 "Glory to the master!" +#define SAY_AGGRO2 "Your life is forfeit!" +#define SAY_AGGRO3 "Die, trespasser!" +#define SAY_SUMMON "Rise, my soldiers! Rise and fight once more!" +#define SAY_SLAY1 "My task is done!" +#define SAY_SLAY2 "Breathe no more!" +#define SAY_DEATH "I will serve the master... in... death!" +#define SOUND_AGGRO1 8845 +#define SOUND_AGGRO2 8846 +#define SOUND_AGGRO3 8847 +#define SOUND_SUMMON 8851 +#define SOUND_SLAY1 8849 +#define SOUND_SLAY2 8850 +#define SOUND_DEATH 8848 + +// Teleport position of Noth on his balcony +#define TELE_X 2631.370 +#define TELE_Y -3529.680 +#define TELE_Z 274.040 +#define TELE_O 6.277 + +#define SPELL_BLINK 29211 +#define SPELL_CRIPPLE 29212 +#define SPELL_CURSEPLAGUEBRINGER 28213 +#define SPELL_WRATHPLAGUEBRINGER 28214 + +// IMPORTANT: BALCONY TELEPORT NOT ADDED YET! WILL BE ADDED SOON! + +struct MANGOS_DLL_DECL boss_nothAI : public ScriptedAI +{ + boss_nothAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Blink_Timer; + uint32 Curse_Timer; + uint32 Wrath_Timer; + uint32 Summon_Timer; + + void Reset() + { + Blink_Timer = 25000; + Curse_Timer = 4000; + Wrath_Timer = 9000; + Summon_Timer = 12000; + } + + void Aggro(Unit *who) + { + switch (rand()%3) + { + case 0: + DoYell(SAY_AGGRO1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO1); + break; + case 1: + DoYell(SAY_AGGRO2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO2); + break; + case 2: + DoYell(SAY_AGGRO3,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO3); + break; + } + } + + void KilledUnit(Unit* victim) + { + switch (rand()%2) + { + case 0: + DoYell(SAY_SLAY1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY1); + break; + case 1: + DoYell(SAY_SLAY2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY2); + break; + } + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DEATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_DEATH); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //Blink_Timer + if (Blink_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CRIPPLE); + DoCast(m_creature,SPELL_BLINK); + + Blink_Timer = 25000; + }else Blink_Timer -= diff; + + //Curse_Timer + if (Curse_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CURSEPLAGUEBRINGER); + Curse_Timer = 28000; + }else Curse_Timer -= diff; + + //Wrath_Timer + if (Wrath_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_WRATHPLAGUEBRINGER); + Wrath_Timer = 18000; + }else Wrath_Timer -= diff; + + //Summon_Timer + if (Summon_Timer < diff) + { + DoYell(SAY_SUMMON,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_SUMMON); + + Unit* target = NULL; + Unit* SummonedSkeletons = NULL; + + SummonedSkeletons = m_creature->SummonCreature(16984,2684.804,-3502.517,261.313,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000); + SummonedSkeletons = m_creature->SummonCreature(16984,2684.804,-3502.517,261.313,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000); + SummonedSkeletons = m_creature->SummonCreature(16984,2684.804,-3502.517,261.313,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000); + SummonedSkeletons = m_creature->SummonCreature(16984,2684.804,-3502.517,261.313,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000); + SummonedSkeletons = m_creature->SummonCreature(16984,2684.804,-3502.517,261.313,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000); + SummonedSkeletons = m_creature->SummonCreature(16984,2684.804,-3502.517,261.313,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000); + + if (SummonedSkeletons) + { + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) + SummonedSkeletons->AddThreat(target,1.0f); + } + + Summon_Timer = 30500; + } else Summon_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_noth(Creature *_Creature) +{ + return new boss_nothAI (_Creature); +} + +void AddSC_boss_noth() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_noth"; + newscript->GetAI = GetAI_boss_noth; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_patchwerk.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_patchwerk.cpp new file mode 100644 index 00000000000..d8a8f73fd69 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_patchwerk.cpp @@ -0,0 +1,160 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Patchwerk +SD%Complete: 100 +SDComment: Some issues with hateful strike inturrupting the melee swing timer. Probably core issue. +SDCategory: Naxxramas +EndScriptData */ + +#include "precompiled.h" + +#define SAY_AGGRO1 "Patchwerk want to play!" +#define SAY_AGGRO2 "Kel'Thuzad make Patchwerk his Avatar of War!" +#define SAY_SLAY "No more play?" +#define SAY_DEATH "What happened to... Patch..." + +#define SOUND_AGGRO1 8909 +#define SOUND_AGGRO2 8910 +#define SOUND_SLAY 8912 +#define SOUND_DEATH 8911 + +#define EMOTE_BERSERK "Patchwerk goes into a berserker rage!" +#define EMOTE_ENRAGE "Patchwerk becomes enraged!" + +#define SPELL_HATEFULSTRIKE 28308 +#define SPELL_ENRAGE 29691 +#define SPELL_BERSERK 27680 +#define SPELL_SLIMEBOLT 32309 + +struct MANGOS_DLL_DECL boss_patchwerkAI : public ScriptedAI +{ + boss_patchwerkAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 HatefullStrike_Timer; + uint32 Enrage_Timer; + uint32 Slimebolt_Timer; + bool Enraged; + + void Reset() + { + HatefullStrike_Timer = 1200; //1.2 seconds + Enrage_Timer = 420000; //7 minutes 420,000 + Slimebolt_Timer = 450000; //7.5 minutes 450,000 + Enraged = false; + } + + void KilledUnit(Unit* Victim) + { + if (rand()%5) + return; + + DoYell(SAY_SLAY, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY); + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_DEATH); + } + + void Aggro(Unit *who) + { + if (rand()%2) + { + DoYell(SAY_AGGRO1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO1); + } + else + { + DoYell(SAY_AGGRO2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO2); + } + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //HatefullStrike_Timer + if (HatefullStrike_Timer < diff) + { + //Cast Hateful strike on the player with the highest + //amount of HP within melee distance + uint32 MostHP = 0; + Unit* pMostHPTarget = NULL; + Unit* pTemp = NULL; + std::list::iterator i = m_creature->getThreatManager().getThreatList().begin(); + + for (i = m_creature->getThreatManager().getThreatList().begin(); i!=m_creature->getThreatManager().getThreatList().end(); ++i) + { + pTemp = Unit::GetUnit((*m_creature),(*i)->getUnitGuid()); + if (pTemp && pTemp->isAlive() && pTemp->GetHealth() > MostHP && m_creature->GetDistance2d(pTemp) < 5) + { + MostHP = pTemp->GetHealth(); + pMostHPTarget = pTemp; + } + } + + if (pMostHPTarget) + DoCast(pMostHPTarget, SPELL_HATEFULSTRIKE); + + HatefullStrike_Timer = 1200; + }else HatefullStrike_Timer -= diff; + + //Enrage_Timer + if (Enrage_Timer < diff) + { + DoCast(m_creature, SPELL_BERSERK); + DoTextEmote(EMOTE_BERSERK, m_creature->getVictim()); + + Enrage_Timer = 300000; + }else Enrage_Timer -= diff; + + //Slimebolt_Timer + if (Slimebolt_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SLIMEBOLT); + Slimebolt_Timer = 5000; + }else Slimebolt_Timer -= diff; + + //Enrage if not already enraged and below 5% + if (!Enraged && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 5) + { + DoCast(m_creature,SPELL_ENRAGE); + DoTextEmote(EMOTE_ENRAGE,NULL); + Enraged = true; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_patchwerk(Creature *_Creature) +{ + return new boss_patchwerkAI (_Creature); +} + +void AddSC_boss_patchwerk() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_patchwerk"; + newscript->GetAI = GetAI_boss_patchwerk; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_razuvious.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_razuvious.cpp new file mode 100644 index 00000000000..707ec574076 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_razuvious.cpp @@ -0,0 +1,167 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Razuvious +SD%Complete: 50 +SDComment: Missing adds and event is impossible without Mind Control +SDCategory: Naxxramas +EndScriptData */ + +#include "precompiled.h" + +//Razuvious - NO TEXT sound only +//8852 aggro01 - Hah hah, I'm just getting warmed up! +//8853 aggro02 Stand and fight! +//8854 aggro03 Show me what you've got! +//8861 slay1 - You should've stayed home! +//8863 slay2- +//8858 cmmnd3 - You disappoint me, students! +//8855 cmmnd1 - Do as I taught you! +//8856 cmmnd2 - Show them no mercy! +//8859 cmmnd4 - The time for practice is over! Show me what you've learned! +//8861 Sweep the leg! Do you have a problem with that? +//8860 death - An honorable... death... +//8947 - Aggro Mixed? - ? + +#define SOUND_AGGRO1 8852 +#define SOUND_AGGRO2 8853 +#define SOUND_AGGRO3 8854 +#define SOUND_SLAY1 8861 +#define SOUND_SLAY2 8863 +#define SOUND_COMMND1 8855 +#define SOUND_COMMND2 8856 +#define SOUND_COMMND3 8858 +#define SOUND_COMMND4 8859 +#define SOUND_COMMND5 8861 +#define SOUND_DEATH 8860 +#define SOUND_AGGROMIX 8847 + +#define SPELL_UNBALANCINGSTRIKE 26613 +#define SPELL_DISRUPTINGSHOUT 29107 + +struct MANGOS_DLL_DECL boss_razuviousAI : public ScriptedAI +{ + boss_razuviousAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 UnbalancingStrike_Timer; + uint32 DisruptingShout_Timer; + uint32 CommandSound_Timer; + + void Reset() + { + UnbalancingStrike_Timer = 30000; //30 seconds + DisruptingShout_Timer = 25000; //25 seconds + CommandSound_Timer = 40000; //40 seconds + } + + void KilledUnit(Unit* Victim) + { + if (rand()%3) + return; + + switch (rand()%2) + { + case 0: + DoPlaySoundToSet(m_creature, SOUND_SLAY1); + break; + case 1: + DoPlaySoundToSet(m_creature, SOUND_SLAY2); + break; + } + } + + void JustDied(Unit* Killer) + { + DoPlaySoundToSet(m_creature, SOUND_DEATH); + } + + void Aggro(Unit *who) + { + switch (rand()%3) + { + case 0: + DoPlaySoundToSet(m_creature, SOUND_AGGRO1); + break; + case 1: + DoPlaySoundToSet(m_creature, SOUND_AGGRO2); + break; + case 2: + DoPlaySoundToSet(m_creature, SOUND_AGGRO3); + break; + } + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //UnbalancingStrike_Timer + if (UnbalancingStrike_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_UNBALANCINGSTRIKE); + UnbalancingStrike_Timer = 30000; + }else UnbalancingStrike_Timer -= diff; + + //DisruptingShout_Timer + if (DisruptingShout_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_DISRUPTINGSHOUT); + DisruptingShout_Timer = 25000; + }else DisruptingShout_Timer -= diff; + + //CommandSound_Timer + if (CommandSound_Timer < diff) + { + switch (rand()%5) + { + case 0: + DoPlaySoundToSet(m_creature, SOUND_COMMND1); + break; + case 1: + DoPlaySoundToSet(m_creature, SOUND_COMMND2); + break; + case 2: + DoPlaySoundToSet(m_creature, SOUND_COMMND3); + break; + case 3: + DoPlaySoundToSet(m_creature, SOUND_COMMND4); + break; + case 4: + DoPlaySoundToSet(m_creature, SOUND_COMMND5); + break; + } + + CommandSound_Timer = 40000; + }else CommandSound_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_razuvious(Creature *_Creature) +{ + return new boss_razuviousAI (_Creature); +} + +void AddSC_boss_razuvious() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_razuvious"; + newscript->GetAI = GetAI_boss_razuvious; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_sapphiron.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_sapphiron.cpp new file mode 100644 index 00000000000..f27375f2835 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_sapphiron.cpp @@ -0,0 +1,199 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Sapphiron +SD%Complete: 0 +SDComment: Place Holder +SDCategory: Naxxramas +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_ICEBOLT 28522 +#define SPELL_FROST_BREATH 29318 +#define SPELL_FROST_AURA 28531 +#define SPELL_LIFE_DRAIN 28542 +#define SPELL_BLIZZARD 28547 +#define SPELL_BESERK 26662 + +struct MANGOS_DLL_DECL boss_sapphironAI : public ScriptedAI +{ + boss_sapphironAI(Creature* c) : ScriptedAI(c) + { + Reset(); + } + + uint32 Icebolt_Count; + uint32 Icebolt_Timer; + uint32 FrostBreath_Timer; + uint32 FrostAura_Timer; + uint32 LifeDrain_Timer; + uint32 Blizzard_Timer; + uint32 Fly_Timer; + uint32 Fly2_Timer; + uint32 Beserk_Timer; + uint32 phase; + bool landoff; + uint32 land_Timer; + + void Reset() + { + FrostAura_Timer = 2000; + LifeDrain_Timer = 24000; + Blizzard_Timer = 20000; + Fly_Timer = 45000; + Icebolt_Timer = 4000; + land_Timer = 2000; + Beserk_Timer = 0; + phase = 1; + Icebolt_Count = 0; + landoff = false; + + //m_creature->ApplySpellMod(SPELL_FROST_AURA, SPELLMOD_DURATION, -1); + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget()) + return; + + if(m_creature->getVictim() && m_creature->isAlive()) + { + if(phase == 1) + { + if(FrostAura_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FROST_AURA); + FrostAura_Timer = 5000; + }else FrostAura_Timer -= diff; + + if(LifeDrain_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + + DoCast(target,SPELL_LIFE_DRAIN); + LifeDrain_Timer = 24000; + }else LifeDrain_Timer -= diff; + + if(Blizzard_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + + DoCast(target,SPELL_BLIZZARD); + Blizzard_Timer = 20000; + }else Blizzard_Timer -= diff; + + if (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() > 10) + { + if(Fly_Timer < diff) + { + phase = 2; + m_creature->InterruptNonMeleeSpells(false); + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); + (*m_creature).GetMotionMaster()->Clear(false); + (*m_creature).GetMotionMaster()->MoveIdle(); + DoCast(m_creature,11010); + m_creature->SetHover(true); + DoCast(m_creature,18430); + Icebolt_Timer = 4000; + Icebolt_Count = 0; + landoff = false; + }else Fly_Timer -= diff; + } + + if (phase == 2) + { + if(Icebolt_Timer < diff && Icebolt_Count < 5) + { + Unit* target = NULL; + + target = SelectUnit(SELECT_TARGET_RANDOM,0); + + DoCast(target,SPELL_ICEBOLT); + Icebolt_Count ++; + Icebolt_Timer = 4000; + }else Icebolt_Timer -= diff; + + if(Icebolt_Count == 5 && !landoff) + { + if(FrostBreath_Timer < diff ) + { + DoTextEmote("takes a deep breath...",NULL); + DoCast(m_creature->getVictim(),SPELL_FROST_BREATH); + land_Timer = 2000; + landoff = true; + FrostBreath_Timer = 6000; + }else FrostBreath_Timer -= diff; + } + + if(landoff) + { + if(land_Timer < diff) + { + phase = 1; + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LAND); + m_creature->SetHover(false); + (*m_creature).GetMotionMaster()->Clear(false); + (*m_creature).GetMotionMaster()->MoveChase(m_creature->getVictim()); + Fly_Timer = 67000; + }else land_Timer -= diff; + } + + } + + if ((m_creature->GetHealth()*100) / m_creature->GetMaxHealth() < 11) + { + if (Beserk_Timer < diff) + { + DoTextEmote("enrages!",NULL); + DoCast(m_creature,SPELL_BESERK); + Beserk_Timer = 300000; + }else Beserk_Timer -= diff; + } + + if( phase!=2 && m_creature->getVictim() && m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE)) + { + if( m_creature->isAttackReady() ) + { + m_creature->AttackerStateUpdate(m_creature->getVictim()); + m_creature->resetAttackTimer(); + } + } + } + } + } +}; + +CreatureAI* GetAI_boss_sapphiron(Creature *_Creature) +{ + return new boss_sapphironAI (_Creature); +} + +void AddSC_boss_sapphiron() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_sapphiron"; + newscript->GetAI = GetAI_boss_sapphiron; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_sir_zeliek.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_sir_zeliek.cpp new file mode 100644 index 00000000000..717e84ca984 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_sir_zeliek.cpp @@ -0,0 +1,146 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Sir_Zeliek +SD%Complete: 100 +SDComment: +SDCategory: Naxxramas +EndScriptData */ + +#include "precompiled.h" + +//All horsemen +#define SPELL_SHIELDWALL 29061 +#define SPELL_BESERK 26662 + +// sir zeliek +#define SPELL_MARK_OF_ZELIEK 28835 +#define SPELL_HOLY_WRATH 28883 + +#define SAY_AGGRO "Flee, before it's too late!" +#define SAY_TAUNT1 "Invaders, cease this foolish venture at once! Turn away while you still can!" +#define SAY_TAUNT2 "Perhaps they will come to their senses, and run away as fast as they can!" +#define SAY_TAUNT3 "Do not continue! Turn back while there's still time!" +#define SAY_SPECIAL "I- I have no choice but to obey!" +#define SAY_SLAY "Forgive me!" +#define SAY_DEATH "It is... as it should be." + +#define SOUND_AGGRO 8913 +#define SOUND_TAUNT1 8917 +#define SOUND_TAUNT2 8918 +#define SOUND_TAUNT3 8919 +#define SOUND_SPECIAl 8916 +#define SOUND_SLAY 8915 +#define SOUND_DEATH 8914 + +struct MANGOS_DLL_DECL boss_sir_zeliekAI : public ScriptedAI +{ + boss_sir_zeliekAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Mark_Timer; + uint32 HolyWrath_Timer; + bool ShieldWall1; + bool ShieldWall2; + + void Reset() + { + Mark_Timer = 20000; // First Horsemen Mark is applied at 20 sec. + HolyWrath_Timer = 12000; // right + ShieldWall1 = true; + ShieldWall2 = true; + } + + void InitialYell() + { + if(!InCombat) + { + DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO); + } + } + + void KilledUnit() + { + DoYell(SAY_SLAY,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY); + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DEATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_DEATH); + } + + void Aggro(Unit *who) + { + InitialYell(); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + // Mark of Zeliek + if(Mark_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_MARK_OF_ZELIEK); + Mark_Timer = 12000; + }else Mark_Timer -= diff; + + // Shield Wall - All 4 horsemen will shield wall at 50% hp and 20% hp for 20 seconds + if(ShieldWall1 && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 50) + { + if(ShieldWall1) + { + DoCast(m_creature,SPELL_SHIELDWALL); + ShieldWall1 = false; + } + } + if(ShieldWall2 && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 20) + { + if(ShieldWall2) + { + DoCast(m_creature,SPELL_SHIELDWALL); + ShieldWall2 = false; + } + } + + // Holy Wrath + if(HolyWrath_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_HOLY_WRATH); + HolyWrath_Timer = 12000; + }else HolyWrath_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_sir_zeliek(Creature *_Creature) +{ + return new boss_sir_zeliekAI (_Creature); +} + +void AddSC_boss_sir_zeliek() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_sir_zeliek"; + newscript->GetAI = GetAI_boss_sir_zeliek; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_stalagg.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_stalagg.cpp new file mode 100644 index 00000000000..53b46122f24 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_stalagg.cpp @@ -0,0 +1,35 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Stalagg +SD%Complete: 0 +SDComment: Merge with Thaddius +SDCategory: Naxxramas +EndScriptData */ + +#include "precompiled.h" + +//Stalagg +//8864 aggro - Stalagg crush you! +//8866 slay - Stalagg Kill! +//8865 death - Master save me... + +#define SPELL_WARSTOMP 28125 +#define SPELL_POWERSURGE 28134 +#define SPELL_CHAIN_LIGHTNING 28900 + +//Not sure how to "force" crushing blows or to knock tank to the opposite platform diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_thaddius.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_thaddius.cpp new file mode 100644 index 00000000000..0bd59cfa0e2 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_thaddius.cpp @@ -0,0 +1,49 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Thaddius +SD%Complete: 0 +SDComment: Merge Feugen & Stalagg with this script +SDCategory: Naxxramas +EndScriptData */ + +#include "precompiled.h" + +//Thaddus +//8873 Lamnt01 - Pleeease! +//8874 Lamnt02 - Stop, make it stop! +//8875 Lamnt03 - Help me! Save me! +//8876 Lamnt04 - Please, nooo! +//8872 greet - You are too late... I... must... OBEY! +//8867 aggro1 - KILL! +//8868 aggro2 - EAT YOUR BONES! +//8869 aggro3 - BREAK YOU! +//8871 elect - Now YOU feel pain! +//8877 slay - You die now! +//8870 die - Thank... you... + +#define SPELL_BALL_LIGHTNING 28299 + +#define SPELL_CHARGE_POSITIVE_DMGBUFF 29659 +#define SPELL_CHARGE_POSITIVE_NEARDMG 28059 + +#define SPELL_CHARGE_NEGATIVE_DMGBUFF 29660 +#define SPELL_CHARGE_NEGATIVE_NEARDMG 28084 + +#define SPELL_CHAIN_LIGHTNING 28900 + +#define SPELL_BESERK 26662 diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_thane_korthazz.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_thane_korthazz.cpp new file mode 100644 index 00000000000..af2010fb3d9 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_thane_korthazz.cpp @@ -0,0 +1,147 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Thane_Korthazz +SD%Complete: 100 +SDComment: +SDCategory: Naxxramas +EndScriptData */ + +#include "precompiled.h" + +//All horsemen +#define SPELL_SHIELDWALL 29061 +#define SPELL_BESERK 26662 + +// thane korthazz +#define SPELL_MARK_OF_KORTHAZZ 28832 +#define SPELL_METEOR 26558 // m_creature->getVictim() auto-area spell but with a core problem + +#define SAY_AGGRO "Come out and fight, ye wee ninny!" +#define SAY_TAUNT1 "To arms, ye roustabouts! We've got company!" +#define SAY_TAUNT2 "I heard about enough of yer sniveling. Shut yer fly trap 'afore I shut it for ye!" +#define SAY_TAUNT3 "I'm gonna enjoy killin' these slack-jawed daffodils!" +#define SAY_SLAY "Next time, bring more friends!" +#define SAY_SPECIAl "I like my meat extra crispy!" +#define SAY_DEATH "What a bloody waste this is!" + +#define SOUND_AGGRO 8899 +#define SOUND_TAUNT1 8903 +#define SOUND_TAUNT2 8904 +#define SOUND_TAUNT3 8905 +#define SOUND_SLAY 8901 +#define SOUND_SPECIAL 8902 +#define SOUND_DEATH 8900 + +#define SPIRIT_OF_KORTHAZZ 16778 + +struct MANGOS_DLL_DECL boss_thane_korthazzAI : public ScriptedAI +{ + boss_thane_korthazzAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Mark_Timer; + uint32 Meteor_Timer; + bool ShieldWall1; + bool ShieldWall2; + + void Reset() + { + Mark_Timer = 20000; // First Horsemen Mark is applied at 20 sec. + Meteor_Timer = 30000; // wrong + ShieldWall1 = true; + ShieldWall2 = true; + } + + void InitialYell() + { + if(!InCombat) + { + DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO); + } + } + + void KilledUnit() + { + DoYell(SAY_SLAY,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY); + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DEATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_DEATH); + } + + void Aggro(Unit *who) + { + InitialYell(); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + // Mark of Korthazz + if(Mark_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_MARK_OF_KORTHAZZ); + Mark_Timer = 12000; + }else Mark_Timer -= diff; + + // Shield Wall - All 4 horsemen will shield wall at 50% hp and 20% hp for 20 seconds + if(ShieldWall1 && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 50) + { + if(ShieldWall1) + { + DoCast(m_creature,SPELL_SHIELDWALL); + ShieldWall1 = false; + } + } + if(ShieldWall2 && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 20) + { + if(ShieldWall2) + { + DoCast(m_creature,SPELL_SHIELDWALL); + ShieldWall2 = false; + } + } + + // Meteor + if(Meteor_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_METEOR); + Meteor_Timer = 20000; // wrong + }else Meteor_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_thane_korthazz(Creature *_Creature) +{ + return new boss_thane_korthazzAI (_Creature); +} + +void AddSC_boss_thane_korthazz() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_thane_korthazz"; + newscript->GetAI = GetAI_boss_thane_korthazz; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/naxxramas/instance_naxxramas.cpp b/src/bindings/scripts/scripts/zone/naxxramas/instance_naxxramas.cpp new file mode 100644 index 00000000000..655d1e07a88 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/naxxramas/instance_naxxramas.cpp @@ -0,0 +1,24 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Naxxramas +SD%Complete: 0 +SDComment: Place holder +SDCategory: Naxxramas +EndScriptData */ + +#include "precompiled.h" diff --git a/src/bindings/scripts/scripts/zone/netherstorm/netherstorm.cpp b/src/bindings/scripts/scripts/zone/netherstorm/netherstorm.cpp new file mode 100644 index 00000000000..4b41574908f --- /dev/null +++ b/src/bindings/scripts/scripts/zone/netherstorm/netherstorm.cpp @@ -0,0 +1,423 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Netherstorm +SD%Complete: 75 +SDComment: Quest support: 10438, 10652 (special flight paths), 10299,10321,10322,10323,10329,10330,10338,10365(Shutting Down Manaforge) +SDCategory: Netherstorm +EndScriptData */ + +/* ContentData +npc_manaforge_control_console +go_manaforge_control_console +npc_protectorate_nether_drake +npc_veronia +EndContentData */ + +#include "precompiled.h" + +/*###### +## npc_manaforge_control_console +######*/ + +#define EMOTE_START "Warning! Emergency shutdown process initiated by $N. Shutdown will complete in two minutes." +#define EMOTE_60 "Emergency shutdown will complete in one minute." +#define EMOTE_30 "Emergency shutdown will complete in thirty seconds." +#define EMOTE_10 "Emergency shutdown will complete in ten seconds." +#define EMOTE_COMPLETE "Emergency shutdown complete." +#define EMOTE_ABORT "Emergency shutdown aborted." + +#define ENTRY_BNAAR_C_CONSOLE 20209 +#define ENTRY_CORUU_C_CONSOLE 20417 +#define ENTRY_DURO_C_CONSOLE 20418 +#define ENTRY_ARA_C_CONSOLE 20440 + +#define ENTRY_SUNFURY_TECH 20218 +#define ENTRY_SUNFURY_PROT 20436 + +#define ENTRY_ARA_TECH 20438 +#define ENTRY_ARA_ENGI 20439 +#define ENTRY_ARA_GORKLONN 20460 + +#define SPELL_DISABLE_VISUAL 35031 +#define SPELL_INTERRUPT_1 35016 //ACID mobs should cast this +#define SPELL_INTERRUPT_2 35176 //ACID mobs should cast this (Manaforge Ara-version) + +struct MANGOS_DLL_DECL npc_manaforge_control_consoleAI : public ScriptedAI +{ + npc_manaforge_control_consoleAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Event_Timer; + uint32 Wave_Timer; + uint32 Phase; + bool Wave; + uint64 someplayer; + uint64 goConsole; + Creature* add; + + void Reset() + { + Event_Timer = 3000; + Wave_Timer = 0; + Phase = 1; + Wave = false; + someplayer = 0; + goConsole = 0; + Creature* add = NULL; + } + + void Aggro(Unit *who) { return; } + + /*void SpellHit(Unit *caster, const SpellEntry *spell) + { + //we have no way of telling the creature was hit by spell -> got aura applied after 10-12 seconds + //then no way for the mobs to actually stop the shutdown as intended. + if( spell->Id == SPELL_INTERRUPT_1 ) + DoSay("Silence! I kill you!",LANG_UNIVERSAL, NULL); + }*/ + + void JustDied(Unit* killer) + { + DoTextEmote(EMOTE_ABORT, NULL); + + if( someplayer ) + { + Unit* p = Unit::GetUnit((*m_creature),someplayer); + if( p && p->GetTypeId() == TYPEID_PLAYER ) + { + switch( m_creature->GetEntry() ) + { + case ENTRY_BNAAR_C_CONSOLE: + ((Player*)p)->FailQuest(10299); + ((Player*)p)->FailQuest(10329); + break; + case ENTRY_CORUU_C_CONSOLE: + ((Player*)p)->FailQuest(10321); + ((Player*)p)->FailQuest(10330); + break; + case ENTRY_DURO_C_CONSOLE: + ((Player*)p)->FailQuest(10322); + ((Player*)p)->FailQuest(10338); + break; + case ENTRY_ARA_C_CONSOLE: + ((Player*)p)->FailQuest(10323); + ((Player*)p)->FailQuest(10365); + break; + } + } + } + + if( goConsole ) + { + if( GameObject* go = GameObject::GetGameObject((*m_creature),goConsole) ) + go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE); + } + } + + void DoWaveSpawnForCreature(Creature *creature) + { + switch( creature->GetEntry() ) + { + case ENTRY_BNAAR_C_CONSOLE: + if( rand()%2 ) + { + add = m_creature->SummonCreature(ENTRY_SUNFURY_TECH,2933.68,4162.55,164.00,1.60,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if( add ) add->GetMotionMaster()->MovePoint(0,2927.36,4212.97,164.00); + } + else + { + add = m_creature->SummonCreature(ENTRY_SUNFURY_TECH,2927.36,4212.97,164.00,4.94,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if( add ) add->GetMotionMaster()->MovePoint(0,2933.68,4162.55,164.00); + } + Wave_Timer = 30000; + break; + case ENTRY_CORUU_C_CONSOLE: + add = m_creature->SummonCreature(ENTRY_SUNFURY_TECH,2445.21,2765.26,134.49,3.93,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if( add ) add->GetMotionMaster()->MovePoint(0,2424.21,2740.15,133.81); + add = m_creature->SummonCreature(ENTRY_SUNFURY_TECH,2429.86,2731.85,134.53,1.31,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if( add ) add->GetMotionMaster()->MovePoint(0,2435.37,2766.04,133.81); + Wave_Timer = 20000; + break; + case ENTRY_DURO_C_CONSOLE: + add = m_creature->SummonCreature(ENTRY_SUNFURY_TECH,2986.80,2205.36,165.37,3.74,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if( add ) add->GetMotionMaster()->MovePoint(0,2985.15,2197.32,164.79); + add = m_creature->SummonCreature(ENTRY_SUNFURY_TECH,2952.91,2191.20,165.32,0.22,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if( add ) add->GetMotionMaster()->MovePoint(0,2060.01,2185.27,164.67); + Wave_Timer = 15000; + break; + case ENTRY_ARA_C_CONSOLE: + if( rand()%2 ) + { + add = m_creature->SummonCreature(ENTRY_ARA_TECH,4035.11,4038.97,194.27,2.57,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if( add ) add->GetMotionMaster()->MovePoint(0,4003.42,4040.19,193.49); + add = m_creature->SummonCreature(ENTRY_ARA_TECH,4033.66,4036.79,194.28,2.57,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if( add ) add->GetMotionMaster()->MovePoint(0,4003.42,4040.19,193.49); + add = m_creature->SummonCreature(ENTRY_ARA_TECH,4037.13,4037.30,194.23,2.57,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if( add ) add->GetMotionMaster()->MovePoint(0,4003.42,4040.19,193.49); + } + else + { + add = m_creature->SummonCreature(ENTRY_ARA_TECH,3099.59,4049.30,194.22,0.05,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if( add ) add->GetMotionMaster()->MovePoint(0,4028.01,4035.17,193.59); + add = m_creature->SummonCreature(ENTRY_ARA_TECH,3999.72,4046.75,194.22,0.05,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if( add ) add->GetMotionMaster()->MovePoint(0,4028.01,4035.17,193.59); + add = m_creature->SummonCreature(ENTRY_ARA_TECH,3996.81,4048.26,194.22,0.05,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if( add ) add->GetMotionMaster()->MovePoint(0,4028.01,4035.17,193.59); + } + Wave_Timer = 15000; + break; + } + } + void DoFinalSpawnForCreature(Creature *creature) + { + switch( creature->GetEntry() ) + { + case ENTRY_BNAAR_C_CONSOLE: + add = m_creature->SummonCreature(ENTRY_SUNFURY_TECH,2946.52,4201.42,163.47,3.54,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if( add ) add->GetMotionMaster()->MovePoint(0,2927.49,4192.81,163.00); + break; + case ENTRY_CORUU_C_CONSOLE: + add = m_creature->SummonCreature(ENTRY_SUNFURY_TECH,2453.88,2737.85,133.27,2.59,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if( add ) add->GetMotionMaster()->MovePoint(0,2433.96,2751.53,133.85); + add = m_creature->SummonCreature(ENTRY_SUNFURY_TECH,2441.62,2735.32,134.49,1.97,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if( add ) add->GetMotionMaster()->MovePoint(0,2433.96,2751.53,133.85); + add = m_creature->SummonCreature(ENTRY_SUNFURY_TECH,2450.73,2754.50,134.49,3.29,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if( add ) add->GetMotionMaster()->MovePoint(0,2433.96,2751.53,133.85); + break; + case ENTRY_DURO_C_CONSOLE: + add = m_creature->SummonCreature(ENTRY_SUNFURY_TECH,2956.18,2202.85,165.32,5.45,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if( add ) add->GetMotionMaster()->MovePoint(0,2972.27,2193.22,164.48); + add = m_creature->SummonCreature(ENTRY_SUNFURY_TECH,2975.30,2211.50,165.32,4.55,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if( add ) add->GetMotionMaster()->MovePoint(0,2972.27,2193.22,164.48); + add = m_creature->SummonCreature(ENTRY_SUNFURY_PROT,2965.02,2217.45,164.16,4.96,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if( add ) add->GetMotionMaster()->MovePoint(0,2972.27,2193.22,164.48); + break; + case ENTRY_ARA_C_CONSOLE: + add = m_creature->SummonCreature(ENTRY_ARA_ENGI,3994.51,4020.46,192.18,0.91,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if( add ) add->GetMotionMaster()->MovePoint(0,4008.35,4035.04,192.70); + add = m_creature->SummonCreature(ENTRY_ARA_GORKLONN,4021.56,4059.35,193.59,4.44,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if( add ) add->GetMotionMaster()->MovePoint(0,4016.62,4039.89,193.46); + break; + } + } + + void UpdateAI(const uint32 diff) + { + if( Event_Timer < diff ) + { + switch(Phase) + { + case 1: + if( someplayer ) + { + Unit* u = Unit::GetUnit((*m_creature),someplayer); + if( u && u->GetTypeId() == TYPEID_PLAYER ) DoTextEmote(EMOTE_START, u); + } + Event_Timer = 60000; + Wave = true; + ++Phase; + break; + case 2: + DoTextEmote(EMOTE_60, NULL); + Event_Timer = 30000; + ++Phase; + break; + case 3: + DoTextEmote(EMOTE_30, NULL); + Event_Timer = 20000; + DoFinalSpawnForCreature(m_creature); + ++Phase; + break; + case 4: + DoTextEmote(EMOTE_10, NULL); + Event_Timer = 10000; + Wave = false; + ++Phase; + break; + case 5: + DoTextEmote(EMOTE_COMPLETE, NULL); + if( someplayer ) + { + Unit* u = Unit::GetUnit((*m_creature),someplayer); + if( u && u->GetTypeId() == TYPEID_PLAYER ) + ((Player*)u)->KilledMonster(m_creature->GetEntry(),m_creature->GetGUID()); + DoCast(m_creature,SPELL_DISABLE_VISUAL); + } + if( goConsole ) + { + if( GameObject* go = GameObject::GetGameObject((*m_creature),goConsole) ) + go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE); + } + ++Phase; + break; + default: + break; + } + } else Event_Timer -= diff; + + if( Wave ) + { + if( Wave_Timer < diff ) + { + DoWaveSpawnForCreature(m_creature); + } else Wave_Timer -= diff; + } + } +}; +CreatureAI* GetAI_npc_manaforge_control_console(Creature *_Creature) +{ + return new npc_manaforge_control_consoleAI (_Creature); +} + +/*###### +## go_manaforge_control_console +######*/ + +//TODO: clean up this workaround when mangos adds support to do it properly (with gossip selections instead of instant summon) +bool GOHello_go_manaforge_control_console(Player *player, GameObject* _GO) +{ + if (_GO->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER) + { + player->PrepareQuestMenu(_GO->GetGUID()); + player->SendPreparedQuest(_GO->GetGUID()); + } + + Creature* manaforge; + manaforge = NULL; + + switch( _GO->GetAreaId() ) + { + case 3726: //b'naar + if( (player->GetQuestStatus(10299) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(10329) == QUEST_STATUS_INCOMPLETE) && + player->HasItemCount(29366,1)) + manaforge = player->SummonCreature(ENTRY_BNAAR_C_CONSOLE,2918.95,4189.98,161.88,0.34,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,125000); + break; + case 3730: //coruu + if( (player->GetQuestStatus(10321) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(10330) == QUEST_STATUS_INCOMPLETE) && + player->HasItemCount(29396,1)) + manaforge = player->SummonCreature(ENTRY_CORUU_C_CONSOLE,2426.77,2750.38,133.24,2.14,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,125000); + break; + case 3734: //duro + if( (player->GetQuestStatus(10322) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(10338) == QUEST_STATUS_INCOMPLETE) && + player->HasItemCount(29397,1)) + manaforge = player->SummonCreature(ENTRY_DURO_C_CONSOLE,2976.48,2183.29,163.20,1.85,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,125000); + break; + case 3722: //ara + if( (player->GetQuestStatus(10323) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(10365) == QUEST_STATUS_INCOMPLETE) && + player->HasItemCount(29411,1)) + manaforge = player->SummonCreature(ENTRY_ARA_C_CONSOLE,4013.71,4028.76,192.10,1.25,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,125000); + break; + } + + if( manaforge ) + { + ((npc_manaforge_control_consoleAI*)manaforge->AI())->someplayer = player->GetGUID(); + ((npc_manaforge_control_consoleAI*)manaforge->AI())->goConsole = _GO->GetGUID(); + _GO->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE); + } + return true; +} + +/*###### +## npc_protectorate_nether_drake +######*/ + +bool GossipHello_npc_protectorate_nether_drake(Player *player, Creature *_Creature) +{ + //On Nethery Wings + if (player->GetQuestStatus(10438) == QUEST_STATUS_INCOMPLETE && player->HasItemCount(29778,1) ) + player->ADD_GOSSIP_ITEM(0, "Fly me to Ultris", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_protectorate_nether_drake(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if (action == GOSSIP_ACTION_INFO_DEF+1) + { + player->CLOSE_GOSSIP_MENU(); + + std::vector nodes; + + nodes.resize(2); + nodes[0] = 152; //from drake + nodes[1] = 153; //end at drake + player->ActivateTaxiPathTo(nodes); //TaxiPath 627 (possibly 627+628(152->153->154->155) ) + } + return true; +} + +/*###### +## npc_veronia +######*/ + +bool GossipHello_npc_veronia(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + //Behind Enemy Lines + if (player->GetQuestStatus(10652) && !player->GetQuestRewardStatus(10652)) + player->ADD_GOSSIP_ITEM(0, "Fly me to Manaforge Coruu please", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_veronia(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if (action == GOSSIP_ACTION_INFO_DEF) + { + player->CLOSE_GOSSIP_MENU(); + player->CastSpell(player,34905,true); //TaxiPath 606 + } + return true; +} + +/*###### +## +######*/ + +void AddSC_netherstorm() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="go_manaforge_control_console"; + newscript->pGOHello = &GOHello_go_manaforge_control_console; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_manaforge_control_console"; + newscript->GetAI = GetAI_npc_manaforge_control_console; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_protectorate_nether_drake"; + newscript->pGossipHello = &GossipHello_npc_protectorate_nether_drake; + newscript->pGossipSelect = &GossipSelect_npc_protectorate_nether_drake; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_veronia"; + newscript->pGossipHello = &GossipHello_npc_veronia; + newscript->pGossipSelect = &GossipSelect_npc_veronia; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/onyxias_lair/boss_onyxia.cpp b/src/bindings/scripts/scripts/zone/onyxias_lair/boss_onyxia.cpp new file mode 100644 index 00000000000..87ee5b8b0cc --- /dev/null +++ b/src/bindings/scripts/scripts/zone/onyxias_lair/boss_onyxia.cpp @@ -0,0 +1,229 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Onyxia +SD%Complete: 50 +SDComment: Phase 2 has many errors. Recommend Rewrite of entire script. +SDCategory: Onyxia's Lair +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_WINGBUFFET 18500 +#define SPELL_FLAMEBREATH 18435 +#define SPELL_CLEAVE 19983 +#define SPELL_TAILSWEEP 15847 +#define SPELL_KNOCK_AWAY 19633 + +#define SPELL_ENGULFINGFLAMES 20019 +#define SPELL_DEEPBREATH 23461 +#define SPELL_FIREBALL 18392 + +#define SPELL_BELLOWINGROAR 18431 +#define SPELL_HEATED_GROUND 22191 + +#define SPELL_SUMMONWHELP 17646 + +#define SAY_AGGRO "How fortuitous. Usually, I must leave my lair to feed." +#define SAY_KILL "Learn your place mortal!" +#define SAY_PHASE_2_TRANS "This meaningless exertion bores me. I'll incinerate you from above!" +#define SAY_PHASE_3_TRANS "It seems you'll need another lesson!" +#define EMOTE_BREATH "takes a deep breath..." + +static float MovementLocations[7][3]= +{ + {-65.8444, -213.809, -60.2985}, + {22.87639, -217.152, -60.0548}, + {-33.5561, -182.682, -60.9457}, + {-31.4963, -250.123, -60.1278}, + {-2.78999, -181.431, -60.8962}, + {-54.9415, -232.242, -60.5555}, + {10.56655, -241.478, -60.9426}, +}; + +static float SpawnLocations[4][3]= +{ + {-30.127, -254.463, -89.440}, + {-30.817, -177.106, -89.258}, + {14.480, -241.560, -85.6300}, + {17.372, -190.840, -85.2810}, +}; + +#define CREATURE_WHELP 11262 + +struct MANGOS_DLL_DECL boss_onyxiaAI : public ScriptedAI +{ + boss_onyxiaAI(Creature* c) : ScriptedAI(c) {Reset();} + + uint32 Phase; + + uint32 FlameBreathTimer; + uint32 CleaveTimer; + uint32 TailSweepTimer; + uint32 MovementTimer; + uint32 EngulfingFlamesTimer; + uint32 SummonWhelpsTimer; + uint32 BellowingRoarTimer; + uint32 WingBuffetTimer; + + void Reset() + { + Phase = 1; + + FlameBreathTimer = 20000; + TailSweepTimer = 2000; + CleaveTimer = 15000; + MovementTimer = 5000; + EngulfingFlamesTimer = 15000; + SummonWhelpsTimer = 45000; + BellowingRoarTimer = 30000; + WingBuffetTimer = 17000; + } + + void Aggro(Unit* who) + { + DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL); + } + + void KilledUnit(Unit *victim) + { + DoYell(SAY_KILL, LANG_UNIVERSAL, NULL); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 60) && (Phase == 1)) + { + Phase = 2; + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); + m_creature->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT + MOVEMENTFLAG_LEVITATING); + m_creature->GetMotionMaster()->Clear(false); + m_creature->GetMotionMaster()->MoveIdle(); + DoYell(SAY_PHASE_2_TRANS, LANG_UNIVERSAL, NULL); + } + + if(((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 40) && (Phase == 2)) + { + Phase = 3; + m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT + MOVEMENTFLAG_LEVITATING); + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LAND); + DoYell(SAY_PHASE_3_TRANS, LANG_UNIVERSAL, NULL); + } + + if(Phase == 1 || Phase == 3) + { + if(FlameBreathTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_FLAMEBREATH); + FlameBreathTimer = 15000; + }else FlameBreathTimer -= diff; + + if(TailSweepTimer < diff) + { + Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1); + if(target && !m_creature->HasInArc(M_PI, target)) + DoCast(target, SPELL_TAILSWEEP); + + TailSweepTimer = 10000; + }else TailSweepTimer -= diff; + + if(CleaveTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_CLEAVE); + CleaveTimer = 10000; + }else CleaveTimer -= diff; + + if(WingBuffetTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_WINGBUFFET); + WingBuffetTimer = 7000 + ((rand()%8)*1000); + }else WingBuffetTimer -= diff; + + DoMeleeAttackIfReady(); + } + + if(Phase == 2) + { + if(!m_creature->isHover()) + { + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); + m_creature->SetHover(true); + } + + if(!m_creature->GetMotionMaster()->empty() && (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() != POINT_MOTION_TYPE)) + m_creature->GetMotionMaster()->Clear(false); + + if(MovementTimer < diff) + { + uint32 random = rand()%8; + if(random < 7) + m_creature->GetMotionMaster()->MovePoint(0, MovementLocations[random][0], MovementLocations[random][1], MovementLocations[random][2]); + else + { + DoTextEmote(EMOTE_BREATH, NULL); + DoCast(m_creature->getVictim(), SPELL_DEEPBREATH); + } + MovementTimer = 25000; + }else MovementTimer -= diff; + + if(EngulfingFlamesTimer < diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_ENGULFINGFLAMES); + EngulfingFlamesTimer = 10000; + }else EngulfingFlamesTimer -= diff; + + if(SummonWhelpsTimer < diff) + { + uint32 max = rand()%20; + for(uint8 i = 0; i < max; ++i) + { + uint8 random = rand()%4; + Creature* Whelp = m_creature->SummonCreature(CREATURE_WHELP, SpawnLocations[random][0], SpawnLocations[random][1], SpawnLocations[random][2], 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000); + if(Whelp) + Whelp->AI()->AttackStart(SelectUnit(SELECT_TARGET_RANDOM, 0)); + } + SummonWhelpsTimer = 45000; + }else SummonWhelpsTimer -= diff; + } + + if(Phase == 3) + { + if(BellowingRoarTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_BELLOWINGROAR); + BellowingRoarTimer = 30000; + }else BellowingRoarTimer -= diff; + } + } +}; + +CreatureAI* GetAI_boss_onyxiaAI(Creature *_Creature) +{ + return new boss_onyxiaAI (_Creature); +} + +void AddSC_boss_onyxia() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_onyxia"; + newscript->GetAI = GetAI_boss_onyxiaAI; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/orgrimmar/orgrimmar.cpp b/src/bindings/scripts/scripts/zone/orgrimmar/orgrimmar.cpp new file mode 100644 index 00000000000..9840f7711dc --- /dev/null +++ b/src/bindings/scripts/scripts/zone/orgrimmar/orgrimmar.cpp @@ -0,0 +1,265 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Orgrimmar +SD%Complete: 100 +SDComment: Quest support: 2460, 5727, 6566 +SDCategory: Orgrimmar +EndScriptData */ + +/* ContentData +npc_neeru_fireblade npc_text + gossip options text missing +npc_shenthul +npc_thrall_warchief +EndContentData */ + +#include "precompiled.h" + +/*###### +## npc_neeru_fireblade +######*/ + +#define QUEST_5727 5727 + +bool GossipHello_npc_neeru_fireblade(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if (player->GetQuestStatus(QUEST_5727) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM(0, "You may speak frankly, Neeru...", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + player->SEND_GOSSIP_MENU(4513, _Creature->GetGUID()); + return true; +} + +bool GossipSelect_npc_neeru_fireblade(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF+1: + player->ADD_GOSSIP_ITEM(0, "[PH] ...", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + player->SEND_GOSSIP_MENU(4513, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + player->CLOSE_GOSSIP_MENU(); + player->AreaExploredOrEventHappens(QUEST_5727); + break; + } + return true; +} + +/*###### +## npc_shenthul +######*/ + +#define QUEST_2460 2460 + +struct MANGOS_DLL_DECL npc_shenthulAI : public ScriptedAI +{ + npc_shenthulAI(Creature* c) : ScriptedAI(c) { Reset(); } + + bool CanTalk; + bool CanEmote; + uint32 Salute_Timer; + uint32 Reset_Timer; + uint64 playerGUID; + + void Reset() + { + CanTalk = false; + CanEmote = false; + Salute_Timer = 6000; + Reset_Timer = 0; + playerGUID = 0; + } + + void Aggro(Unit* who) { } + + void UpdateAI(const uint32 diff) + { + if( CanEmote ) + if( Reset_Timer < diff ) + { + if( Unit* temp = Unit::GetUnit((*m_creature),playerGUID) ) + if( temp->GetTypeId() == TYPEID_PLAYER ) + ((Player*)temp)->FailQuest(QUEST_2460); + Reset(); + } else Reset_Timer -= diff; + + if( CanTalk && !CanEmote ) + if( Salute_Timer < diff ) + { + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE); + CanEmote = true; + Reset_Timer = 60000; + } else Salute_Timer -= diff; + + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_npc_shenthul(Creature *_Creature) +{ + return new npc_shenthulAI (_Creature); +} + +bool QuestAccept_npc_shenthul(Player* player, Creature* creature, Quest const* quest) +{ + if( quest->GetQuestId() == QUEST_2460 ) + { + ((npc_shenthulAI*)creature->AI())->CanTalk = true; + ((npc_shenthulAI*)creature->AI())->playerGUID = player->GetGUID(); + } + return true; +} + +bool ReciveEmote_npc_shenthul(Player *player, Creature *_Creature, uint32 emote) +{ + if( emote == TEXTEMOTE_SALUTE && player->GetQuestStatus(QUEST_2460) == QUEST_STATUS_INCOMPLETE ) + if( ((npc_shenthulAI*)_Creature->AI())->CanEmote ) + { + player->AreaExploredOrEventHappens(QUEST_2460); + ((npc_shenthulAI*)_Creature->AI())->Reset(); + } + return true; +} + +/*###### +## npc_thrall_warchief +######*/ + +#define QUEST_6566 6566 + +#define SPELL_CHAIN_LIGHTNING 16033 +#define SPELL_SHOCK 16034 + +//TODO: verify abilities/timers +struct MANGOS_DLL_DECL npc_thrall_warchiefAI : public ScriptedAI +{ + npc_thrall_warchiefAI(Creature* c) : ScriptedAI(c) { Reset(); } + + uint32 ChainLightning_Timer; + uint32 Shock_Timer; + + void Reset() + { + ChainLightning_Timer = 2000; + Shock_Timer = 8000; + } + + void Aggro(Unit *who) {} + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if( ChainLightning_Timer < diff ) + { + DoCast(m_creature->getVictim(),SPELL_CHAIN_LIGHTNING); + ChainLightning_Timer = 9000; + }else ChainLightning_Timer -= diff; + + if( Shock_Timer < diff ) + { + DoCast(m_creature->getVictim(),SPELL_SHOCK); + Shock_Timer = 15000; + }else Shock_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_npc_thrall_warchief(Creature *_Creature) +{ + return new npc_thrall_warchiefAI (_Creature); +} + +bool GossipHello_npc_thrall_warchief(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if (player->GetQuestStatus(QUEST_6566) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM(0, "Please share your wisdom with me, Warchief.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + return true; +} + +bool GossipSelect_npc_thrall_warchief(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF+1: + player->ADD_GOSSIP_ITEM(0, "What discoveries?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + player->SEND_GOSSIP_MENU(5733, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + player->ADD_GOSSIP_ITEM(0, "Usurper?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + player->SEND_GOSSIP_MENU(5734, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + player->ADD_GOSSIP_ITEM(0, "With all due respect, Warchief - why not allow them to be destroyed? Does this not strengthen our position?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + player->SEND_GOSSIP_MENU(5735, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + player->ADD_GOSSIP_ITEM(0, "I... I did not think of it that way, Warchief.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + player->SEND_GOSSIP_MENU(5736, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + player->ADD_GOSSIP_ITEM(0, "I live only to serve, Warchief! My life is empty and meaningless without your guidance.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); + player->SEND_GOSSIP_MENU(5737, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+6: + player->ADD_GOSSIP_ITEM(0, "Of course, Warchief!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+7); + player->SEND_GOSSIP_MENU(5738, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+7: + player->CLOSE_GOSSIP_MENU(); + player->AreaExploredOrEventHappens(QUEST_6566); + break; + } + return true; +} + +void AddSC_orgrimmar() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npc_neeru_fireblade"; + newscript->pGossipHello = &GossipHello_npc_neeru_fireblade; + newscript->pGossipSelect = &GossipSelect_npc_neeru_fireblade; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_shenthul"; + newscript->GetAI = GetAI_npc_shenthul; + newscript->pQuestAccept = &QuestAccept_npc_shenthul; + newscript->pReceiveEmote = &ReciveEmote_npc_shenthul; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_thrall_warchief"; + newscript->GetAI = GetAI_npc_thrall_warchief; + newscript->pGossipHello = &GossipHello_npc_thrall_warchief; + newscript->pGossipSelect = &GossipSelect_npc_thrall_warchief; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/razorfen_downs/boss_amnennar_the_coldbringer.cpp b/src/bindings/scripts/scripts/zone/razorfen_downs/boss_amnennar_the_coldbringer.cpp new file mode 100644 index 00000000000..d25781c0ca6 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/razorfen_downs/boss_amnennar_the_coldbringer.cpp @@ -0,0 +1,140 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Amnennar_the_coldbringer +SD%Complete: 100 +SDComment: +SDCategory: Razorfen Downs +EndScriptData */ + +#include "precompiled.h" + +#define SAY_0 "You'll never leave this place... alive." +#define SAY_1 "Come, spirits, attend your master." +#define SAY_SLAY "Too...easy!" +#define SOUND_AGGRO 5825 +#define SOUND_SLAY 5826 +#define SOUND_SUMMON 5829 + +#define SPELL_AMNENNARSWRATH 13009 +#define SPELL_FROSTBOLT 10179 + +struct MANGOS_DLL_DECL boss_amnennar_the_coldbringerAI : public ScriptedAI +{ + boss_amnennar_the_coldbringerAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 AmnenarsWrath_Timer; + uint32 FrostBolt_Timer; + bool Spectrals; + int Rand; + int RandX; + int RandY; + Creature* Summoned; + + void Reset() + { + AmnenarsWrath_Timer = 8000; + FrostBolt_Timer = 1000; + Spectrals = false; + } + + void Aggro(Unit *who) + { + DoYell(SAY_0,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO); + } + + void KilledUnit() + { + DoYell(SAY_SLAY, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY); + } + + void SummonSpectrals(Unit* victim) + { + Rand = rand()%5; + switch (rand()%2) + { + case 0: RandX = 0 - Rand; break; + case 1: RandX = 0 + Rand; break; + } + Rand = 0; + Rand = rand()%5; + switch (rand()%2) + { + case 0: RandY = 0 - Rand; break; + case 1: RandY = 0 + Rand; break; + } + Rand = 0; + Summoned = DoSpawnCreature(8585, RandX, RandY, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); + if(Summoned) + ((CreatureAI*)Summoned->AI())->AttackStart(victim); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //AmnenarsWrath_Timer + if (AmnenarsWrath_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_AMNENNARSWRATH); + AmnenarsWrath_Timer = 12000; + } else AmnenarsWrath_Timer -= diff; + + //FrostBolt_Timer + if (FrostBolt_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) DoCast(target,SPELL_FROSTBOLT); + + FrostBolt_Timer = 8000; + } else FrostBolt_Timer -= diff; + + if ( !Spectrals && m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 50 ) + { + DoYell(SAY_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SUMMON); + + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + + SummonSpectrals(target); + SummonSpectrals(target); + SummonSpectrals(target); + Spectrals = true; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_amnennar_the_coldbringer(Creature *_Creature) +{ + return new boss_amnennar_the_coldbringerAI (_Creature); +} + +void AddSC_boss_amnennar_the_coldbringer() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_amnennar_the_coldbringer"; + newscript->GetAI = GetAI_boss_amnennar_the_coldbringer; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/ruins_of_ahnqiraj/boss_ayamiss.cpp b/src/bindings/scripts/scripts/zone/ruins_of_ahnqiraj/boss_ayamiss.cpp new file mode 100644 index 00000000000..f448351d255 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/ruins_of_ahnqiraj/boss_ayamiss.cpp @@ -0,0 +1,107 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Ayamiss +SD%Complete: 50 +SDComment: VERIFY SCRIPT +SDCategory: Ruins of Ahn'Qiraj +EndScriptData */ + +#include "precompiled.h" + +/* +To do: +make him fly from 70-100% +*/ + +#define SPELL_STINGERSPRAY 25749 +#define SPELL_POISONSTINGER 25748 //only used in phase1 +#define SPELL_SUMMONSWARMER 25844 //might be 25708 +// #define SPELL_PARALYZE 23414 doesnt work correct (core) + +struct MANGOS_DLL_DECL boss_ayamissAI : public ScriptedAI +{ + boss_ayamissAI(Creature *c) : ScriptedAI(c) {Reset();} + + Unit *pTarget; + uint32 STINGERSPRAY_Timer; + uint32 POISONSTINGER_Timer; + uint32 SUMMONSWARMER_Timer; + uint32 phase; + + void Reset() + { + pTarget = NULL; + STINGERSPRAY_Timer = 30000; + POISONSTINGER_Timer = 30000; + SUMMONSWARMER_Timer = 60000; + phase=1; + } + + void Aggro(Unit *who) + { + pTarget = who; + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //If he is 70% start phase 2 + if (phase==1 && m_creature->GetHealth()*100 / m_creature->GetMaxHealth() <= 70 && !m_creature->IsNonMeleeSpellCasted(false)) + { + phase=2; + } + + //STINGERSPRAY_Timer (only in phase2) + if (phase==2 && STINGERSPRAY_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_STINGERSPRAY); + STINGERSPRAY_Timer = 30000; + }else STINGERSPRAY_Timer -= diff; + + //POISONSTINGER_Timer (only in phase1) + if (phase==1 && POISONSTINGER_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_POISONSTINGER); + POISONSTINGER_Timer = 30000; + }else POISONSTINGER_Timer -= diff; + + //SUMMONSWARMER_Timer (only in phase1) + if (SUMMONSWARMER_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SUMMONSWARMER); + SUMMONSWARMER_Timer = 60000; + }else SUMMONSWARMER_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_ayamiss(Creature *_Creature) +{ + return new boss_ayamissAI (_Creature); +} + +void AddSC_boss_ayamiss() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_ayamiss"; + newscript->GetAI = GetAI_boss_ayamiss; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/ruins_of_ahnqiraj/boss_buru.cpp b/src/bindings/scripts/scripts/zone/ruins_of_ahnqiraj/boss_buru.cpp new file mode 100644 index 00000000000..65bec030fe9 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/ruins_of_ahnqiraj/boss_buru.cpp @@ -0,0 +1,24 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Buru +SD%Complete: 0 +SDComment: Place Holder +SDCategory: Ruins of Ahn'Qiraj +EndScriptData */ + +#include "precompiled.h" diff --git a/src/bindings/scripts/scripts/zone/ruins_of_ahnqiraj/boss_kurinnaxx.cpp b/src/bindings/scripts/scripts/zone/ruins_of_ahnqiraj/boss_kurinnaxx.cpp new file mode 100644 index 00000000000..8b7411dbaa3 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/ruins_of_ahnqiraj/boss_kurinnaxx.cpp @@ -0,0 +1,93 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Kurinnaxx +SD%Complete: 100 +SDComment: VERIFY SCRIPT AND SQL +SDCategory: Ruins of Ahn'Qiraj +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_MORTALWOUND 25646 +#define SPELL_SANDTRAP 25656 +#define SPELL_ENRAGE 28798 + +struct MANGOS_DLL_DECL boss_kurinnaxxAI : public ScriptedAI +{ + boss_kurinnaxxAI(Creature *c) : ScriptedAI(c) {Reset();} + + Unit *pTarget; + uint32 MORTALWOUND_Timer; + uint32 SANDTRAP_Timer; + uint32 i; + + void Reset() + { + i=0; + pTarget = NULL; + MORTALWOUND_Timer = 30000; + SANDTRAP_Timer = 30000; + } + + void Aggro(Unit *who) + { + pTarget = who; + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //If we are <30% cast enrage + if (i==0 && m_creature->GetHealth()*100 / m_creature->GetMaxHealth() <= 30 && !m_creature->IsNonMeleeSpellCasted(false)) + { + i=1; + DoCast(m_creature->getVictim(),SPELL_ENRAGE); + } + + //MORTALWOUND_Timer + if (MORTALWOUND_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_MORTALWOUND); + MORTALWOUND_Timer = 30000; + }else MORTALWOUND_Timer -= diff; + + //SANDTRAP_Timer + if (SANDTRAP_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SANDTRAP); + SANDTRAP_Timer = 30000; + }else SANDTRAP_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_kurinnaxx(Creature *_Creature) +{ + return new boss_kurinnaxxAI (_Creature); +} + +void AddSC_boss_kurinnaxx() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_kurinnaxx"; + newscript->GetAI = GetAI_boss_kurinnaxx; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/ruins_of_ahnqiraj/boss_moam.cpp b/src/bindings/scripts/scripts/zone/ruins_of_ahnqiraj/boss_moam.cpp new file mode 100644 index 00000000000..42d30bb4eca --- /dev/null +++ b/src/bindings/scripts/scripts/zone/ruins_of_ahnqiraj/boss_moam.cpp @@ -0,0 +1,117 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Moam +SD%Complete: 100 +SDComment: VERIFY SCRIPT AND SQL +SDCategory: Ruins of Ahn'Qiraj +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_TRAMPLE 15550 +#define SPELL_DRAINMANA 27256 +#define SPELL_ARCANEERUPTION 25672 +#define SPELL_SUMMONMANA 25681 +#define SPELL_GRDRSLEEP 24360 //Greater Dreamless Sleep + +#define SAY_MANA "moam bristles with energy!" + +struct MANGOS_DLL_DECL boss_moamAI : public ScriptedAI +{ + boss_moamAI(Creature *c) : ScriptedAI(c) {Reset();} + + Unit *pTarget; + uint32 TRAMPLE_Timer; + uint32 DRAINMANA_Timer; + uint32 SUMMONMANA_Timer; + uint32 i; + uint32 j; + + void Reset() + { + i=0; + j=0; + pTarget = NULL; + TRAMPLE_Timer = 30000; + DRAINMANA_Timer = 30000; + } + + void Aggro(Unit *who) + { + pTarget = who; + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //If we are 100%MANA cast Arcane Erruption + //if (j==1 && m_creature->GetMana()*100 / m_creature->GetMaxMana() == 100 && !m_creature->IsNonMeleeSpellCasted(false)) + { + DoCast(m_creature->getVictim(),SPELL_ARCANEERUPTION); + DoYell(SAY_MANA,LANG_UNIVERSAL,NULL); + } + + //If we are <50%HP cast MANA FIEND (Summon Mana) and Sleep + //if (i==0 && m_creature->GetHealth()*100 / m_creature->GetMaxHealth() <= 50 && !m_creature->IsNonMeleeSpellCasted(false)) + { + i=1; + DoCast(m_creature->getVictim(),SPELL_SUMMONMANA); + DoCast(m_creature->getVictim(),SPELL_GRDRSLEEP); + } + + //SUMMONMANA_Timer + if (i==1 && SUMMONMANA_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SUMMONMANA); + SUMMONMANA_Timer = 90000; + }else SUMMONMANA_Timer -= diff; + + //TRAMPLE_Timer + if (TRAMPLE_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_TRAMPLE); + j=1; + + TRAMPLE_Timer = 30000; + }else TRAMPLE_Timer -= diff; + + //DRAINMANA_Timer + if (DRAINMANA_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_DRAINMANA); + DRAINMANA_Timer = 30000; + }else DRAINMANA_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_moam(Creature *_Creature) +{ + return new boss_moamAI (_Creature); +} + +void AddSC_boss_moam() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_moam"; + newscript->GetAI = GetAI_boss_moam; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/ruins_of_ahnqiraj/boss_ossirian.cpp b/src/bindings/scripts/scripts/zone/ruins_of_ahnqiraj/boss_ossirian.cpp new file mode 100644 index 00000000000..a2a04673925 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/ruins_of_ahnqiraj/boss_ossirian.cpp @@ -0,0 +1,36 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Ossirian +SD%Complete: 0 +SDComment: Place holder +SDCategory: Ruins of Ahn'Qiraj +EndScriptData */ + +#include "precompiled.h" + +//Ossirian +//8593 I am rejuvinated! +//8594 I have... failed +//8595 My powers are renewed! +//8596 My powers return! +//8597 Protect the city at all costs! +//8598 Sands of the desert rise and block out the sun! +//8599 The walls have been breached! +//8600 To your posts. Defend the city. +//8601 Tresspassers will be terminated. +//8602 You are terminated. diff --git a/src/bindings/scripts/scripts/zone/ruins_of_ahnqiraj/boss_rajaxx.cpp b/src/bindings/scripts/scripts/zone/ruins_of_ahnqiraj/boss_rajaxx.cpp new file mode 100644 index 00000000000..3daff71f58a --- /dev/null +++ b/src/bindings/scripts/scripts/zone/ruins_of_ahnqiraj/boss_rajaxx.cpp @@ -0,0 +1,42 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Rajaxx +SD%Complete: 0 +SDComment: Place Holder +SDCategory: Ruins of Ahn'Qiraj +EndScriptData */ + +#include "precompiled.h" + +//Rajaxx +//8603 Attack and make them pay dearly! +//8604 Breath your last! +//8605 Crush them! Drive them out! +//8606 Do not hesitate! Destroy them! +//8613 Warriors! Captians! Continue the fight... +//8614 You are not worth my time $N! +//8612 The time of our retribution is at hand! Let darkness reign in the hearts of our enemies! +//8610 No longer will we wait behind barred doors and walls of stone! No longer will our vengeance be denied! The dragons themselves will tremble before our wrath! +//8608 Fear is for the enemy! Fear and death! +//8611 Staghelm will whimper and beg for his life, just as his whelp of a son did! One thousand years of injustice will end this day! +//8607 Fandral! Your time has come! Go and hide in the Emerald Dream and pray we never find you! +//8609 Impudent fool! I will kill you myself! + +//Andorov - no sound +//"Remember, Rajaxx, when I said I'd kill you last? I lied..." +//"They come now. Try not to get yourself killed, young blood." diff --git a/src/bindings/scripts/scripts/zone/ruins_of_ahnqiraj/instance_ruins_of_ahnqiraj.cpp b/src/bindings/scripts/scripts/zone/ruins_of_ahnqiraj/instance_ruins_of_ahnqiraj.cpp new file mode 100644 index 00000000000..a2bddd52efe --- /dev/null +++ b/src/bindings/scripts/scripts/zone/ruins_of_ahnqiraj/instance_ruins_of_ahnqiraj.cpp @@ -0,0 +1,24 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Ruins_of_Ahnqiraj +SD%Complete: 0 +SDComment: Place holder +SDCategory: Ruins of Ahn'Qiraj +EndScriptData */ + +#include "precompiled.h" diff --git a/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_arcanist_doan.cpp b/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_arcanist_doan.cpp new file mode 100644 index 00000000000..3a6a3526269 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_arcanist_doan.cpp @@ -0,0 +1,171 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Arcanist_Doan +SD%Complete: 100 +SDComment: +SDCategory: Scarlet Monastery +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_POLYMORPH 12826 +#define SPELL_AOESILENCE 8988 +#define SPELL_ARCANEEXPLOSION3 8438 +#define SPELL_ARCANEEXPLOSION4 8439 +#define SPELL_FIREAOE 9435 +#define SPELL_BLINK 1953 +#define SPELL_FIREBALL 21162 +#define SPELL_MANASHIELD4 10191 +#define SPELL_ARCANEBUBBLE 9438 + +#define SAY_AGGRO "You will not defile these mysteries!" +#define SAY_SPECIALAE "Burn in righteous fire!" + +#define SOUND_AGGRO 5842 +#define SOUND_SPECIALAE 5843 + +struct MANGOS_DLL_DECL boss_arcanist_doanAI : public ScriptedAI +{ + boss_arcanist_doanAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 FullAOE_Timer; + uint32 Polymorph_Timer; + uint32 Yell_Timer; + uint32 ArcaneBubble_Timer; + uint32 AoESilence_Timer; + uint32 ArcaneExplosion3_Timer; + uint32 ArcaneExplosion4_Timer; + uint32 Blink_Timer; + uint32 Fireball_Timer; + uint32 ManaShield4_Timer; + + void Reset() + { + FullAOE_Timer = 5000; + Polymorph_Timer = 1; + Yell_Timer = 2000; + ArcaneBubble_Timer = 3000; + AoESilence_Timer = 20000; + ArcaneExplosion3_Timer = 10000; + ArcaneExplosion4_Timer = 10000; + Blink_Timer = 40000; + Fireball_Timer = 6000; + ManaShield4_Timer = 70000; + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //If we are <50% hp cast Arcane Bubble and start casting SPECIAL FIRE AOE + if (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() <= 50 && !m_creature->IsNonMeleeSpellCasted(false)) + { + if (Polymorph_Timer < diff) + { + Unit* target = NULL; + + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target)DoCast(target,SPELL_POLYMORPH); + Polymorph_Timer = 40000; + }else Polymorph_Timer -= diff; + + if (Yell_Timer < diff) + { + DoYell(SAY_SPECIALAE,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_SPECIALAE); + Yell_Timer = 40000; + }else Yell_Timer -= diff; + + if (ArcaneBubble_Timer < diff) + { + DoCast(m_creature,SPELL_ARCANEBUBBLE); + ArcaneBubble_Timer = 40000; + }else ArcaneBubble_Timer -= diff; + + if (FullAOE_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FIREAOE); + FullAOE_Timer = 40000; + }else FullAOE_Timer -= diff; + } + + //AoESilence_Timer + if (AoESilence_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_AOESILENCE); + AoESilence_Timer = 30000; + }else AoESilence_Timer -= diff; + + //ArcaneExplosion3_Timer + if (ArcaneExplosion3_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_ARCANEEXPLOSION3); + ArcaneExplosion3_Timer = 8000; + }else ArcaneExplosion3_Timer -= diff; + + //ArcaneExplosion4_Timer + if (ArcaneExplosion4_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_ARCANEEXPLOSION4); + ArcaneExplosion4_Timer = 10000; + }else ArcaneExplosion4_Timer -= diff; + + //Blink_Timer + if (Blink_Timer < diff) + { + DoCast(m_creature,SPELL_BLINK); + Blink_Timer = 30000; + }else Blink_Timer -= diff; + + //Fireball_Timer + if (Fireball_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FIREBALL); + Fireball_Timer = 12000; + }else Fireball_Timer -= diff; + + //ManaShiled4_Timer + if (ManaShield4_Timer < diff) + { + DoCast(m_creature,SPELL_MANASHIELD4); + ManaShield4_Timer = 70000; + }else ManaShield4_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_arcanist_doan(Creature *_Creature) +{ + return new boss_arcanist_doanAI (_Creature); +} + +void AddSC_boss_arcanist_doan() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_arcanist_doan"; + newscript->GetAI = GetAI_boss_arcanist_doan; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_azshir_the_sleepless.cpp b/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_azshir_the_sleepless.cpp new file mode 100644 index 00000000000..d975cb3d192 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_azshir_the_sleepless.cpp @@ -0,0 +1,97 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Azshir_the_Sleepless +SD%Complete: 80 +SDComment: +SDCategory: Scarlet Monastery +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_CALLOFTHEGRAVE 17831 +#define SPELL_TERRIFY 7399 +#define SPELL_SOULSIPHON 7290 + +struct MANGOS_DLL_DECL boss_azshir_the_sleeplessAI : public ScriptedAI +{ + boss_azshir_the_sleeplessAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 SoulSiphon_Timer; + uint32 CallOftheGrave_Timer; + uint32 Terrify_Timer; + + void Reset() + { + SoulSiphon_Timer = 1; + CallOftheGrave_Timer = 30000; + Terrify_Timer = 20000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //If we are <50% hp cast Soul Siphon rank 1 + if ( m_creature->GetHealth()*100 / m_creature->GetMaxHealth() <= 50 && !m_creature->IsNonMeleeSpellCasted(false)) + { + //SoulSiphon_Timer + if (SoulSiphon_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SOULSIPHON); + return; + + SoulSiphon_Timer = 20000; + }else SoulSiphon_Timer -= diff; + } + + //CallOfTheGrave_Timer + if (CallOftheGrave_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CALLOFTHEGRAVE); + CallOftheGrave_Timer = 30000; + }else CallOftheGrave_Timer -= diff; + + //Terrify_Timer + if (Terrify_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_TERRIFY); + Terrify_Timer = 20000; + }else Terrify_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_azshir_the_sleepless(Creature *_Creature) +{ + return new boss_azshir_the_sleeplessAI (_Creature); +} + +void AddSC_boss_azshir_the_sleepless() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_azshir_the_sleepless"; + newscript->GetAI = GetAI_boss_azshir_the_sleepless; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_bloodmage_thalnos.cpp b/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_bloodmage_thalnos.cpp new file mode 100644 index 00000000000..a130df0fa56 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_bloodmage_thalnos.cpp @@ -0,0 +1,136 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Bloodmage_Thalnos +SD%Complete: 100 +SDComment: +SDCategory: Scarlet Monastery +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_FROSTNOVA2 865 +#define SPELL_FLAMESHOCK3 8053 +#define SPELL_SHADOWBOLT5 1106 +#define SPELL_FLAMESPIKE 8814 +#define SPELL_FIRENOVA 16079 + +#define SAY_AGGRO "We hunger for vengeance." +#define SAY_HEALTH "No rest... for the angry dead!" +#define SAY_DEATH "More... More souls!" + +#define SOUND_AGGRO 5844 +#define SOUND_HEALTH 5846 +#define SOUND_DEATH 5845 + +struct MANGOS_DLL_DECL boss_bloodmage_thalnosAI : public ScriptedAI +{ + boss_bloodmage_thalnosAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 FrostNova2_Timer; + uint32 FlameShock3_Timer; + uint32 ShadowBolt5_Timer; + uint32 FlameSpike_Timer; + uint32 FireNova_Timer; + uint32 Yell_Timer; + + void Reset() + { + Yell_Timer = 1; + FrostNova2_Timer = 10000; + FlameShock3_Timer = 15000; + ShadowBolt5_Timer = 20000; + FlameSpike_Timer = 20000; + FireNova_Timer = 10000; + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //If we are <35% hp + if ( m_creature->GetHealth()*100 / m_creature->GetMaxHealth() <= 35) + { + Yell_Timer -= diff; + + if (Yell_Timer < diff) + { + DoYell(SAY_HEALTH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_HEALTH); + Yell_Timer = 900000; + } + } + + //FrostNova2_Timer + if (FrostNova2_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FROSTNOVA2); + FrostNova2_Timer = 10000; + }else FrostNova2_Timer -= diff; + + //FlameShock3_Timer + if (FlameShock3_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FLAMESHOCK3); + FlameShock3_Timer = 15000; + }else FlameShock3_Timer -= diff; + + //ShadowBolt5_Timer + if (ShadowBolt5_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SHADOWBOLT5); + ShadowBolt5_Timer = 20000; + }else ShadowBolt5_Timer -= diff; + + //FlameSpike_Timer + if (FlameSpike_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FLAMESPIKE); + FlameSpike_Timer = 30000; + }else FlameSpike_Timer -= diff; + + //FireNova_Timer + if (FireNova_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FIRENOVA); + FireNova_Timer = 20000; + }else FireNova_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_bloodmage_thalnos(Creature *_Creature) +{ + return new boss_bloodmage_thalnosAI (_Creature); +} + +void AddSC_boss_bloodmage_thalnos() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_bloodmage_thalnos"; + newscript->GetAI = GetAI_boss_bloodmage_thalnos; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_herod.cpp b/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_herod.cpp new file mode 100644 index 00000000000..ea4cdc52e03 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_herod.cpp @@ -0,0 +1,197 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Herod +SD%Complete: 90 +SDComment: Missing adds spawn at death +SDCategory: Scarlet Monastery +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_RUSHINGCHARGE 32021 +#define SPELL_RUSHINGCHARGE1 6268 + +#define SPELL_CLEAVE 11608 +#define SPELL_WHIRLWIND 8989 +#define SPELL_SUNDERARMOR 16145 +#define SPELL_REND 21949 +#define SPELL_THUNDERCLAP 15588 +#define SPELL_SLAM 11430 +#define SPELL_BERSERKERSTANCE 2458 +#define SPELL_ENRAGE 28747 +#define SPELL_FIREBALL11 10151 +#define SPELL_CONEOFCOLD5 10161 + +#define SAY_AGGRO "Ah, I have been waiting for a real challenge!" +#define SAY_WHIRLWIND "Blades of Light!" +#define SAY_ENRAGE "Light, give me strength!" +#define SAY_DEATH "Hah, is that all?" + +#define SOUND_AGGRO 5830 +#define SOUND_WHIRLWIND 5832 +#define SOUND_ENRAGE 5833 +#define SOUND_DEATH 5831 + +struct MANGOS_DLL_DECL boss_herodAI : public ScriptedAI +{ + boss_herodAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Yell_Timer; + uint32 Enrage_Timer; + uint32 Cleave_Timer; + uint32 Whirlwind_Timer; + uint32 SunderArmor_Timer; + uint32 Rend_Timer; + uint32 ThunderClap_Timer; + uint32 Slam_Timer; + uint32 Fireball11_Timer; + uint32 ConeOfCold5_Timer; + + void Reset() + { + Yell_Timer = 58000; + Whirlwind_Timer = 60000; + Enrage_Timer = 0; + Cleave_Timer = 15000; + SunderArmor_Timer = 40000; + Rend_Timer = 25000; + ThunderClap_Timer = 25000; + Slam_Timer = 20000; + Fireball11_Timer = 30000; + ConeOfCold5_Timer = 40000; + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO); + + //Activate Berserker Stance + DoCast(m_creature,SPELL_BERSERKERSTANCE); + + //Switch between 2 different charge methods + switch (rand()%2) + { + case 0: + DoCast(m_creature,SPELL_RUSHINGCHARGE); + break; + case 1: + DoCast(m_creature,SPELL_RUSHINGCHARGE1); + break; + } + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //If we are <10% hp goes Enraged + if ( m_creature->GetHealth()*100 / m_creature->GetMaxHealth() <= 10 && !m_creature->IsNonMeleeSpellCasted(false) && Enrage_Timer < diff) + { + DoYell(SAY_ENRAGE,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_ENRAGE); + + DoCast(m_creature,SPELL_ENRAGE); + + //Shouldn't cast this agian + Enrage_Timer = diff; + } + + //Cleave_Timer + if (Cleave_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CLEAVE); + Cleave_Timer = 15000; + }else Cleave_Timer -= diff; + + //Yelling and Whirlwind casting + if (Yell_Timer < diff) + { + //Say Whirlwind monologe + DoYell(SAY_WHIRLWIND,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_WHIRLWIND); + + Yell_Timer = 30000; + }else Yell_Timer -= diff; + + if (Whirlwind_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_WHIRLWIND); + Whirlwind_Timer = 30000; + }else Whirlwind_Timer -= diff; + + //SunderArmor_Timer + if (SunderArmor_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SUNDERARMOR); + SunderArmor_Timer = 40000; + }else SunderArmor_Timer -= diff; + + //Rend_Timer + if (Rend_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_REND); + Rend_Timer = 25000; + }else Rend_Timer -= diff; + + //ThunderClap_Timer + if (ThunderClap_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_THUNDERCLAP); + ThunderClap_Timer = 20000; + }else ThunderClap_Timer -= diff; + + //Slam_Timer + if (Slam_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SLAM); + Slam_Timer = 20000; + }else Slam_Timer -= diff; + + //Fireball11_Timer + if (Fireball11_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FIREBALL11); + Fireball11_Timer = 30000; + }else Fireball11_Timer -= diff; + + //ConeOfCold5_Timer + if (ConeOfCold5_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CONEOFCOLD5); + ConeOfCold5_Timer = 40000; + }else ConeOfCold5_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_herod(Creature *_Creature) +{ + return new boss_herodAI (_Creature); +} + +void AddSC_boss_herod() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_herod"; + newscript->GetAI = GetAI_boss_herod; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_high_inquisitor_fairbanks.cpp b/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_high_inquisitor_fairbanks.cpp new file mode 100644 index 00000000000..2817b50eb4c --- /dev/null +++ b/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_high_inquisitor_fairbanks.cpp @@ -0,0 +1,132 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_High_Inquisitor_Faribanks +SD%Complete: 100 +SDComment: +SDCategory: Scarlet Monastery +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_SLEEP2 1090 +#define SPELL_CURSEOFBLOOD 16098 +#define SPELL_SMITE 6060 +#define SPELL_SHADOWWORDPAIN 2767 +#define SPELL_FLASHHEAL4 9474 +#define SPELL_RENEW6 6078 +#define SPELL_DEVOURINGPLAGUE3 19277 +#define SPELL_MINDBLAST5 8105 + +struct MANGOS_DLL_DECL boss_high_inquisitor_fairbanksAI : public ScriptedAI +{ + boss_high_inquisitor_fairbanksAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Healing_Timer; + uint32 Sleep2_Timer; + uint32 Smite_Timer; + uint32 ShadowWordPain_Timer; + uint32 CurseOfBlood_Timer; + uint32 DevouringPlague3_Timer; + uint32 MindBlast5_Timer; + + void Reset() + { + Healing_Timer = 300; + Sleep2_Timer = 45000; + Smite_Timer = 30000; + ShadowWordPain_Timer = 30000; + CurseOfBlood_Timer = 45000; + DevouringPlague3_Timer = 60000; + MindBlast5_Timer = 20000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //If we are <45% hp cast Renew rank 6 or Flash heal rank 4 + if ( m_creature->GetHealth()*100 / m_creature->GetMaxHealth() <= 45 && !m_creature->IsNonMeleeSpellCasted(false) && Healing_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_RENEW6 || SPELL_FLASHHEAL4); + Healing_Timer = 30000; + }else Healing_Timer -= diff; + + //Sleep2_Timer + if (Sleep2_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SLEEP2); + Sleep2_Timer = 45000; + }else Sleep2_Timer -= diff; + + //Smite_Timer + if (Smite_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SMITE); + Smite_Timer = 20000; + }else Smite_Timer -= diff; + + //ShadowWordPain_Timer + if (ShadowWordPain_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SHADOWWORDPAIN); + ShadowWordPain_Timer = 30000; + }else ShadowWordPain_Timer -= diff; + + //CurseOfBlood_Timer + if (CurseOfBlood_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CURSEOFBLOOD); + CurseOfBlood_Timer = 25000; + }else CurseOfBlood_Timer -= diff; + + //DevouringPlague3_Timer + if (DevouringPlague3_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_DEVOURINGPLAGUE3); + DevouringPlague3_Timer = 35000; + }else DevouringPlague3_Timer -= diff; + + //MindBlast5_Timer + if (MindBlast5_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_MINDBLAST5); + MindBlast5_Timer = 30000; + }else MindBlast5_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_high_inquisitor_fairbanks(Creature *_Creature) +{ + return new boss_high_inquisitor_fairbanksAI (_Creature); +} + +void AddSC_boss_high_inquisitor_fairbanks() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_high_inquisitor_fairbanks"; + newscript->GetAI = GetAI_boss_high_inquisitor_fairbanks; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_high_inquisitor_whitemane.cpp b/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_high_inquisitor_whitemane.cpp new file mode 100644 index 00000000000..3a7c03a03b4 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_high_inquisitor_whitemane.cpp @@ -0,0 +1,177 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_High_Inquistor_Whitmane +SD%Complete: 50 +SDComment: Missing connection with commander mograine +SDCategory: Scarlet Monastery +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_DEEPSLEEP 9256 +#define SPELL_SCARLETRESURRECTION 9232 + +#define SPELL_CRUSADERSTRIKE 17281 +#define SPELL_HAMMEROFJUSTICE 13005 +#define SPELL_HOLYSMITE6 9481 +#define SPELL_HOLYFIRE5 15265 +#define SPELL_MINDBLAST6 8106 + +#define SPELL_POWERWORDSHIELD 6065 + +#define SPELL_RENEW 6078 +#define SPELL_FLASHHEAL6 10916 + +#define SAY_AGGRO "There is no escape for you. The Crusade shall destroy all who carry the Scourge's taint." +#define SAY_SPAWN "What, Mograine has fallen? You shall pay for this treachery! " +#define SAY_RES "Arise, my champion!" +#define SAY_DEATH "The Light has spoken!" + +//#define SOUND_AGGRO +#define SOUND_RES 5840 +#define SOUND_SPAWN 5838 +#define SOUND_DEATH 5839 + +struct MANGOS_DLL_DECL boss_high_inquisitor_whitemaneAI : public ScriptedAI +{ + boss_high_inquisitor_whitemaneAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Healing_Timer; + uint32 Renew_Timer; + uint32 PowerWordShield_Timer; + uint32 CrusaderStrike_Timer; + uint32 HammerOfJustice_Timer; + uint32 HolySmite6_Timer; + uint32 HolyFire5_Timer; + uint32 MindBlast6_Timer; + + void Reset() + { + Healing_Timer = 0; + Renew_Timer= 0; + PowerWordShield_Timer = 2000; + CrusaderStrike_Timer = 12000; + HammerOfJustice_Timer = 18000; + HolySmite6_Timer = 10000; + HolyFire5_Timer = 20000; + MindBlast6_Timer = 6000; + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + /* + //This is going to be a routine to make the resurrection event... + if (m_creature->isAlive && m_creature->isAlive) + { + m_creature->Relocate(1163.113370,1398.856812,32.527786,3.171014); + + DoYell(SAY_SPAWN,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_SPAWN); + DoCast(m_creature->getVictim(),SPELL_DEEPSLEEP); + DoCast(m-creature->GetGUID(51117),SPELL_SCARLETRESURRECTION) + } + */ + + //If we are <75% hp cast healing spells at self and Mograine + if ( m_creature->GetHealth()*100 / m_creature->GetMaxHealth() <= 75 ) + { + if (Healing_Timer < diff) + { + DoCast(m_creature,SPELL_FLASHHEAL6); + return; + + //22-32 seconds until we should cast this agian + Healing_Timer = 22000 + rand()%10000; + }else Healing_Timer -= diff; + } + + if ( m_creature->GetHealth()*100 / m_creature->GetMaxHealth() <= 30) + { + if (Renew_Timer < diff) + { + DoCast(m_creature,SPELL_RENEW); + Renew_Timer = 30000; + }else Renew_Timer -= diff; + } + + //PowerWordShield_Timer + if (PowerWordShield_Timer < diff) + { + DoCast(m_creature,SPELL_POWERWORDSHIELD); + PowerWordShield_Timer = 25000; + }else PowerWordShield_Timer -= diff; + + //CrusaderStrike_Timer + if (CrusaderStrike_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CRUSADERSTRIKE); + CrusaderStrike_Timer = 15000; + }else CrusaderStrike_Timer -= diff; + + //HammerOfJustice_Timer + if (HammerOfJustice_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_HAMMEROFJUSTICE); + HammerOfJustice_Timer = 12000; + }else HammerOfJustice_Timer -= diff; + + //HolySmite6_Timer + if (HolySmite6_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_HOLYSMITE6); + HolySmite6_Timer = 10000; + }else HolySmite6_Timer -= diff; + + //HolyFire5_Timer + if (HolyFire5_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_HOLYFIRE5); + HolyFire5_Timer = 15000; + }else HolyFire5_Timer -= diff; + + //MindBlast6_Timer + if (MindBlast6_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_MINDBLAST6); + MindBlast6_Timer = 8000; + }else MindBlast6_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_high_inquisitor_whitemane(Creature *_Creature) +{ + return new boss_high_inquisitor_whitemaneAI (_Creature); +} + +void AddSC_boss_high_inquisitor_whitemane() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_high_inquisitor_whitemane"; + newscript->GetAI = GetAI_boss_high_inquisitor_whitemane; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_houndmaster_loksey.cpp b/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_houndmaster_loksey.cpp new file mode 100644 index 00000000000..342424eed2f --- /dev/null +++ b/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_houndmaster_loksey.cpp @@ -0,0 +1,78 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Houndmaster_Loksey +SD%Complete: 100 +SDComment: +SDCategory: Scarlet Monastery +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_SUMMONSCARLETHOUND 17164 +#define SPELL_ENRAGE 28747 + +#define SAY_AGGRO "Release the hounds!" +#define SOUND_AGGRO 5841 + +struct MANGOS_DLL_DECL boss_houndmaster_lokseyAI : public ScriptedAI +{ + boss_houndmaster_lokseyAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Enrage_Timer; + + void Reset() + { + Enrage_Timer = 6000000; + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO); + + DoCast(m_creature,SPELL_SUMMONSCARLETHOUND); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //If we are <10% hp cast healing spells at self and Mograine + if ( m_creature->GetHealth()*100 / m_creature->GetMaxHealth() <= 10 && !m_creature->IsNonMeleeSpellCasted(false) && Enrage_Timer < diff) + { + DoCast(m_creature,SPELL_ENRAGE); + Enrage_Timer = 900000; + }else Enrage_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_houndmaster_loksey(Creature *_Creature) +{ + return new boss_houndmaster_lokseyAI (_Creature); +} + +void AddSC_boss_houndmaster_loksey() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_houndmaster_loksey"; + newscript->GetAI = GetAI_boss_houndmaster_loksey; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_interrogator_vishas.cpp b/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_interrogator_vishas.cpp new file mode 100644 index 00000000000..c21eef4b458 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_interrogator_vishas.cpp @@ -0,0 +1,113 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Interrogator_Vishas +SD%Complete: 100 +SDComment: +SDCategory: Scarlet Monastery +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_POWERWORDSHIELD 6065 + +#define SAY_AGGRO "Tell me... tell me everything!" +#define SAY_HEALTH1 "Naughty secrets" +#define SAY_HEALTH2 "I'll rip the secrets from your flesh!" +#define SAY_DEATH "Purged by pain!" + +#define SOUND_AGGRO 5847 +#define SOUND_HEALTH1 5849 +#define SOUND_HEALTH2 5850 +#define SOUND_DEATH 5848 + +struct MANGOS_DLL_DECL boss_interrogator_vishasAI : public ScriptedAI +{ + boss_interrogator_vishasAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Yell_Timer; + uint32 PowerWordShield_Timer; + + void Reset() + { + Yell_Timer = 6000000; + PowerWordShield_Timer = 60000; + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //If we are low on hp Do sayings + if ( m_creature->GetHealth()*100 / m_creature->GetMaxHealth() <= 60 && !m_creature->IsNonMeleeSpellCasted(false)) + { + //Yell_Timer + if (Yell_Timer < diff) + { + DoYell(SAY_HEALTH1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_HEALTH1); + return; + + //60 seconds until we should cast this agian + Yell_Timer = 60000; + }else Yell_Timer -= diff; + } + + if ( m_creature->GetHealth()*100 / m_creature->GetMaxHealth() <= 30 && !m_creature->IsNonMeleeSpellCasted(false)) + { + //Yell_Timer + if (Yell_Timer < diff) + { + DoYell(SAY_HEALTH2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_HEALTH2); + return; + + //60 seconds until we should cast this agian + Yell_Timer = 6000000; + }else Yell_Timer -= diff; + } + + //PowerWordShield_Timer + if (PowerWordShield_Timer < diff) + { + DoCast(m_creature,SPELL_POWERWORDSHIELD); + PowerWordShield_Timer = 60000; + }else PowerWordShield_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_interrogator_vishas(Creature *_Creature) +{ + return new boss_interrogator_vishasAI (_Creature); +} + +void AddSC_boss_interrogator_vishas() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_interrogator_vishas"; + newscript->GetAI = GetAI_boss_interrogator_vishas; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_scarlet_commander_mograine.cpp b/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_scarlet_commander_mograine.cpp new file mode 100644 index 00000000000..6bdcda14913 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_scarlet_commander_mograine.cpp @@ -0,0 +1,160 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Scarlet_Commander_Mograine +SD%Complete: 100 +SDComment: Missing revive +SDCategory: Scarlet Monastery +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_DIVINESHIELD2 1020 +#define SPELL_CRUSADERSTRIKE5 35395 +#define SPELL_HAMMEROFJUSTICE3 5589 +#define SPELL_HOLYLIGHT6 3472 +#define SPELL_CONSECRATION3 20922 +#define SPELL_BLESSINGOFWISDOM 1044 +#define SPELL_RETRIBUTIONAURA3 10299 +#define SPELL_BLESSINGOFPROTECTION3 10278 +#define SPELL_FLASHHEAL6 10916 + +#define SAY_AGGRO "Infidels! They must be purified!" +#define SAY_RES "At your side, milady!" +#define SAY_DEATH "Unworthy!" + +#define SOUND_AGGRO 5835 +#define SOUND_RES 5837 +#define SOUND_DEATH 5836 + +struct MANGOS_DLL_DECL boss_scarlet_commander_mograineAI : public ScriptedAI +{ + boss_scarlet_commander_mograineAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Heal_Timer; + uint32 DivineShield2_Timer; + uint32 CrusaderStrike5_Timer; + uint32 HammerOfJustice3_Timer; + uint32 Consecration3_Timer; + uint32 BlessingOfWisdom_Timer; + uint32 BlessingOfProtection3_Timer; + + void Reset() + { + Heal_Timer = 80000; + DivineShield2_Timer = 60000; + CrusaderStrike5_Timer = 20000; + HammerOfJustice3_Timer = 80000; + Consecration3_Timer = 30000; + BlessingOfWisdom_Timer = 45000; + BlessingOfProtection3_Timer = 45000; + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO); + DoCast(m_creature,SPELL_RETRIBUTIONAURA3); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //If we are <50% hp cast Arcane Bubble and start casting SPECIAL Arcane Explosion + if ( m_creature->GetHealth()*100 / m_creature->GetMaxHealth() <= 50 && !m_creature->IsNonMeleeSpellCasted(false)) + { + //heal_Timer + if (Heal_Timer < diff) + { + //Switch between 2 different charge methods + switch (rand()%2) + { + case 0: + DoCast(m_creature,SPELL_HOLYLIGHT6); + break; + case 1: + DoCast(m_creature,SPELL_FLASHHEAL6); + break; + } + return; + + //60 seconds until we should cast this agian + Heal_Timer = 60000; + }else Heal_Timer -= diff; + } + + //DivineShield2_Timer + if (DivineShield2_Timer < diff) + { + DoCast(m_creature,SPELL_DIVINESHIELD2); + DivineShield2_Timer = 60000; + }else DivineShield2_Timer -= diff; + + //CrusaderStrike5_Timer + if (CrusaderStrike5_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CRUSADERSTRIKE5); + CrusaderStrike5_Timer = 20000; + }else CrusaderStrike5_Timer -= diff; + + //HammerOfJustice3_Timer + if (HammerOfJustice3_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_HAMMEROFJUSTICE3); + HammerOfJustice3_Timer = 30000; + }else HammerOfJustice3_Timer -= diff; + + //Consecration3_Timer + if (Consecration3_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CONSECRATION3); + Consecration3_Timer = 20000; + }else Consecration3_Timer -= diff; + + //BlessingOfWisdom_Timer + if (BlessingOfWisdom_Timer < diff) + { + DoCast(m_creature,SPELL_BLESSINGOFWISDOM); + BlessingOfWisdom_Timer = 45000; + }else BlessingOfWisdom_Timer -= diff; + + //BlessingOfProtection3_Timer + if (BlessingOfProtection3_Timer < diff) + { + DoCast(m_creature,SPELL_BLESSINGOFPROTECTION3); + BlessingOfProtection3_Timer = 50000; + }else BlessingOfProtection3_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_scarlet_commander_mograine(Creature *_Creature) +{ + return new boss_scarlet_commander_mograineAI (_Creature); +} + +void AddSC_boss_scarlet_commander_mograine() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_scarlet_commander_mograine"; + newscript->GetAI = GetAI_boss_scarlet_commander_mograine; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_scorn.cpp b/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_scorn.cpp new file mode 100644 index 00000000000..abfda1462ca --- /dev/null +++ b/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_scorn.cpp @@ -0,0 +1,100 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Scorn +SD%Complete: 100 +SDComment: +SDCategory: Scarlet Monastery +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_LICHSLAP 28873 +#define SPELL_FROSTBOLTVOLLEY 8398 +#define SPELL_MINDFLAY 17313 +#define SPELL_FROSTNOVA 15531 + +struct MANGOS_DLL_DECL boss_scornAI : public ScriptedAI +{ + boss_scornAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 LichSlap_Timer; + uint32 FrostboltVolley_Timer; + uint32 MindFlay_Timer; + uint32 FrostNova_Timer; + + void Reset() + { + LichSlap_Timer = 45000; + FrostboltVolley_Timer = 30000; + MindFlay_Timer = 30000; + FrostNova_Timer = 30000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //LichSlap_Timer + if (LichSlap_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_LICHSLAP); + LichSlap_Timer = 45000; + }else LichSlap_Timer -= diff; + + //FrostboltVolley_Timer + if (FrostboltVolley_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FROSTBOLTVOLLEY); + FrostboltVolley_Timer = 20000; + }else FrostboltVolley_Timer -= diff; + + //MindFlay_Timer + if (MindFlay_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_MINDFLAY); + MindFlay_Timer = 20000; + }else MindFlay_Timer -= diff; + + //FrostNova_Timer + if (FrostNova_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FROSTNOVA); + FrostNova_Timer = 15000; + }else FrostNova_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_scorn(Creature *_Creature) +{ + return new boss_scornAI (_Creature); +} + +void AddSC_boss_scorn() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_scorn"; + newscript->GetAI = GetAI_boss_scorn; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/scholomance/boss_darkmaster_gandling.cpp b/src/bindings/scripts/scripts/zone/scholomance/boss_darkmaster_gandling.cpp new file mode 100644 index 00000000000..bb4c17f3425 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/scholomance/boss_darkmaster_gandling.cpp @@ -0,0 +1,192 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Darkmaster_Gandling +SD%Complete: 99 +SDComment: Doors missing in instance script. +SDCategory: Scholomance +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_ARCANEMISSILES 22272 +#define SPELL_SHADOWSHIELD 22417 //Not right ID. But 12040 is wrong either. +#define SPELL_CURSE 18702 + +#define ADD_1X 170.205 +#define ADD_1Y 99.413 +#define ADD_1Z 104.733 +#define ADD_1O 3.16 + +#define ADD_2X 170.813 +#define ADD_2Y 97.857 +#define ADD_2Z 104.713 +#define ADD_2O 3.16 + +#define ADD_3X 170.720 +#define ADD_3Y 100.900 +#define ADD_3Z 104.739 +#define ADD_3O 3.16 + +#define ADD_4X 171.866 +#define ADD_4Y 99.373 +#define ADD_4Z 104.732 +#define ADD_4O 3.16 + +struct MANGOS_DLL_DECL boss_darkmaster_gandlingAI : public ScriptedAI +{ + boss_darkmaster_gandlingAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 ArcaneMissiles_Timer; + uint32 ShadowShield_Timer; + uint32 Curse_Timer; + uint32 Teleport_Timer; + Creature *Summoned; + + void Reset() + { + ArcaneMissiles_Timer = 4500; + ShadowShield_Timer = 12000; + Curse_Timer = 2000; + Teleport_Timer = 16000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //ArcaneMissiles_Timer + if (ArcaneMissiles_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_ARCANEMISSILES); + ArcaneMissiles_Timer = 8000; + }else ArcaneMissiles_Timer -= diff; + + //ShadowShield_Timer + if (ShadowShield_Timer < diff) + { + DoCast(m_creature,SPELL_SHADOWSHIELD); + ShadowShield_Timer = 14000 + rand()%14000; + }else ShadowShield_Timer -= diff; + + //Curse_Timer + if (Curse_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CURSE); + Curse_Timer = 15000 + rand()%12000; + }else Curse_Timer -= diff; + + //Teleporting Random Target to one of the six pre boss rooms and spawn 3-4 skeletons near the gamer. + //We will only telport if gandling has more than 3% of hp so teleported gamers can always loot. + if ( m_creature->GetHealth()*100 / m_creature->GetMaxHealth() > 3 ) + { + if(Teleport_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target && target->GetTypeId() == TYPEID_PLAYER) + { + if(m_creature->getThreatManager().getThreat(target)) + m_creature->getThreatManager().modifyThreatPercent(target, -100); + + switch(rand()%6) + { + case 0: + DoTeleportPlayer(target, 250.0696,0.3921,84.8408,3.149); + Summoned = m_creature->SummonCreature(16119,254.2325,0.3417,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + ((CreatureAI*)Summoned->AI())->AttackStart(target); + Summoned = m_creature->SummonCreature(16119,257.7133,4.0226,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + ((CreatureAI*)Summoned->AI())->AttackStart(target); + Summoned = m_creature->SummonCreature(16119,258.6702,-2.60656,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + ((CreatureAI*)Summoned->AI())->AttackStart(target); + break; + case 1: + DoTeleportPlayer(target, 181.4220,-91.9481,84.8410,1.608); + Summoned = m_creature->SummonCreature(16119,184.0519,-73.5649,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + ((CreatureAI*)Summoned->AI())->AttackStart(target); + Summoned = m_creature->SummonCreature(16119,179.5951,-73.7045,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + ((CreatureAI*)Summoned->AI())->AttackStart(target); + Summoned = m_creature->SummonCreature(16119,180.6452,-78.2143,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + ((CreatureAI*)Summoned->AI())->AttackStart(target); + Summoned = m_creature->SummonCreature(16119,283.2274,-78.1518,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + ((CreatureAI*)Summoned->AI())->AttackStart(target); + break; + case 2: + DoTeleportPlayer(target, 95.1547,-1.8173,85.2289,0.043); + Summoned = m_creature->SummonCreature(16119,100.9404,-1.8016,85.2289,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + ((CreatureAI*)Summoned->AI())->AttackStart(target); + Summoned = m_creature->SummonCreature(16119,101.3729,0.4882,85.2289,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + ((CreatureAI*)Summoned->AI())->AttackStart(target); + Summoned = m_creature->SummonCreature(16119,101.4596,-4.4740,85.2289,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + ((CreatureAI*)Summoned->AI())->AttackStart(target); + break; + case 3: + DoTeleportPlayer(target, 250.0696,0.3921,72.6722,3.149); + Summoned = m_creature->SummonCreature(16119,240.34481,0.7368,72.6722,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + ((CreatureAI*)Summoned->AI())->AttackStart(target); + Summoned = m_creature->SummonCreature(16119,240.3633,-2.9520,72.6722,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + ((CreatureAI*)Summoned->AI())->AttackStart(target); + Summoned = m_creature->SummonCreature(16119,240.6702,3.34949,72.6722,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + ((CreatureAI*)Summoned->AI())->AttackStart(target); + break; + case 4: + DoTeleportPlayer(target, 181.4220,-91.9481,70.7734,1.608); + Summoned = m_creature->SummonCreature(16119,184.0519,-73.5649,70.7734,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + ((CreatureAI*)Summoned->AI())->AttackStart(target); + Summoned = m_creature->SummonCreature(16119,179.5951,-73.7045,70.7734,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + ((CreatureAI*)Summoned->AI())->AttackStart(target); + Summoned = m_creature->SummonCreature(16119,180.6452,-78.2143,70.7734,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + ((CreatureAI*)Summoned->AI())->AttackStart(target); + Summoned = m_creature->SummonCreature(16119,283.2274,-78.1518,70.7734,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + ((CreatureAI*)Summoned->AI())->AttackStart(target); + break; + case 5: + DoTeleportPlayer(target, 106.1541,-1.8994,75.3663,0.043); + Summoned = m_creature->SummonCreature(16119,115.3945,-1.5555,75.3663,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + ((CreatureAI*)Summoned->AI())->AttackStart(target); + Summoned = m_creature->SummonCreature(16119,257.7133,1.8066,75.3663,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + ((CreatureAI*)Summoned->AI())->AttackStart(target); + Summoned = m_creature->SummonCreature(16119,258.6702,-5.1001,75.3663,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + ((CreatureAI*)Summoned->AI())->AttackStart(target); + break; + } + } + Teleport_Timer = 20000 + rand()%15000; + }else Teleport_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_darkmaster_gandling(Creature *_Creature) +{ + return new boss_darkmaster_gandlingAI (_Creature); +} + +void AddSC_boss_darkmaster_gandling() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_darkmaster_gandling"; + newscript->GetAI = GetAI_boss_darkmaster_gandling; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/scholomance/boss_death_knight_darkreaver.cpp b/src/bindings/scripts/scripts/zone/scholomance/boss_death_knight_darkreaver.cpp new file mode 100644 index 00000000000..344ab9840d9 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/scholomance/boss_death_knight_darkreaver.cpp @@ -0,0 +1,59 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Death_knight_darkreaver +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "precompiled.h" + +struct MANGOS_DLL_DECL boss_death_knight_darkreaverAI : public ScriptedAI +{ + boss_death_knight_darkreaverAI(Creature *c) : ScriptedAI(c) {Reset();} + + void Reset() + { + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (m_creature->GetHealth() <= damage) + { + m_creature->CastSpell(m_creature,23261,true); //Summon Darkreaver's Fallen Charger + } + } + + void Aggro(Unit *who) + { + } +}; +CreatureAI* GetAI_boss_death_knight_darkreaver(Creature *_Creature) +{ + return new boss_death_knight_darkreaverAI (_Creature); +} + +void AddSC_boss_death_knight_darkreaver() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_death_knight_darkreaver"; + newscript->GetAI = GetAI_boss_death_knight_darkreaver; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/scholomance/boss_doctor_theolen_krastinov.cpp b/src/bindings/scripts/scripts/zone/scholomance/boss_doctor_theolen_krastinov.cpp new file mode 100644 index 00000000000..4dd663fbc5f --- /dev/null +++ b/src/bindings/scripts/scripts/zone/scholomance/boss_doctor_theolen_krastinov.cpp @@ -0,0 +1,108 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Doctor_Theolen_Krastinov +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "precompiled.h" +#include "def_scholomance.h" + +#define SPELL_REND 18106 +#define SPELL_CLEAVE 15584 +#define SPELL_FRENZY 28371 + +struct MANGOS_DLL_DECL boss_theolenkrastinovAI : public ScriptedAI +{ + boss_theolenkrastinovAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Rend_Timer; + uint32 Cleave_Timer; + uint32 Frenzy_Timer; + + void Reset() + { + Rend_Timer = 8000; + Cleave_Timer = 9000; + Frenzy_Timer =0; + } + + void JustDied(Unit *killer) + { + ScriptedInstance *pInstance = (m_creature->GetInstanceData()) ? ((ScriptedInstance*)m_creature->GetInstanceData()) : NULL; + if(pInstance) + { + pInstance->SetData(DATA_DOCTORTHEOLENKRASTINOV_DEATH, 0); + + if(pInstance->GetData(DATA_CANSPAWNGANDLING)) + m_creature->SummonCreature(1853, 180.73, -9.43856, 75.507, 1.61399, TEMPSUMMON_DEAD_DESPAWN, 0); + } + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //Rend_Timer + if (Rend_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_REND); + Rend_Timer = 10000; + }else Rend_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CLEAVE); + Cleave_Timer = 10000; + }else Cleave_Timer -= diff; + + //Frenzy_Timer + if ( m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 26 ) + { + if (Frenzy_Timer < diff) + { + DoCast(m_creature,SPELL_FRENZY); + DoTextEmote("goes into a killing frenzy!",NULL); + + Frenzy_Timer = 8000; + }else Frenzy_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_theolenkrastinov(Creature *_Creature) +{ + return new boss_theolenkrastinovAI (_Creature); +} + +void AddSC_boss_theolenkrastinov() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_doctor_theolen_krastinov"; + newscript->GetAI = GetAI_boss_theolenkrastinov; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/scholomance/boss_illucia_barov.cpp b/src/bindings/scripts/scripts/zone/scholomance/boss_illucia_barov.cpp new file mode 100644 index 00000000000..1a45b7e2697 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/scholomance/boss_illucia_barov.cpp @@ -0,0 +1,116 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Illucia_Barov +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "precompiled.h" +#include "def_scholomance.h" + +#define SPELL_CURSEOFAGONY 18671 +#define SPELL_SHADOWSHOCK 20603 +#define SPELL_SILENCE 15487 +#define SPELL_FEAR 6215 + +struct MANGOS_DLL_DECL boss_illuciabarovAI : public ScriptedAI +{ + boss_illuciabarovAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 CurseOfAgony_Timer; + uint32 ShadowShock_Timer; + uint32 Silence_Timer; + uint32 Fear_Timer; + + void Reset() + { + CurseOfAgony_Timer = 18000; + ShadowShock_Timer = 9000; + Silence_Timer = 5000; + Fear_Timer = 30000; + } + + void JustDied(Unit *killer) + { + ScriptedInstance *pInstance = (m_creature->GetInstanceData()) ? ((ScriptedInstance*)m_creature->GetInstanceData()) : NULL; + if(pInstance) + { + pInstance->SetData(DATA_LADYILLUCIABAROV_DEATH, 0); + + if(pInstance->GetData(DATA_CANSPAWNGANDLING)) + m_creature->SummonCreature(1853, 180.73, -9.43856, 75.507, 1.61399, TEMPSUMMON_DEAD_DESPAWN, 0); + } + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //CurseOfAgony_Timer + if (CurseOfAgony_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CURSEOFAGONY); + CurseOfAgony_Timer = 30000; + }else CurseOfAgony_Timer -= diff; + + //ShadowShock_Timer + if (ShadowShock_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) DoCast(target,SPELL_SHADOWSHOCK); + + ShadowShock_Timer = 12000; + }else ShadowShock_Timer -= diff; + + //Silence_Timer + if (Silence_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SILENCE); + Silence_Timer = 14000; + }else Silence_Timer -= diff; + + //Fear_Timer + if (Fear_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FEAR); + Fear_Timer = 30000; + }else Fear_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_illuciabarov(Creature *_Creature) +{ + return new boss_illuciabarovAI (_Creature); +} + +void AddSC_boss_illuciabarov() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_illucia_barov"; + newscript->GetAI = GetAI_boss_illuciabarov; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/scholomance/boss_instructor_malicia.cpp b/src/bindings/scripts/scripts/zone/scholomance/boss_instructor_malicia.cpp new file mode 100644 index 00000000000..9d2dbc174d5 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/scholomance/boss_instructor_malicia.cpp @@ -0,0 +1,152 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_instructormalicia +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "precompiled.h" +#include "def_scholomance.h" + +#define SPELL_CALLOFGRAVES 17831 +#define SPELL_CORRUPTION 11672 +#define SPELL_FLASHHEAL 10917 +#define SPELL_RENEW 10929 +#define SPELL_HEALINGTOUCH 9889 + +struct MANGOS_DLL_DECL boss_instructormaliciaAI : public ScriptedAI +{ + boss_instructormaliciaAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 CallOfGraves_Timer; + uint32 Corruption_Timer; + uint32 FlashHeal_Timer; + uint32 Renew_Timer; + uint32 HealingTouch_Timer; + uint32 FlashCounter; + uint32 TouchCounter; + + void Reset() + { + CallOfGraves_Timer = 4000; + Corruption_Timer = 8000; + FlashHeal_Timer = 38000; + Renew_Timer = 32000; + HealingTouch_Timer = 45000; + FlashCounter = 0; + TouchCounter = 0; + } + + void JustDied(Unit *killer) + { + ScriptedInstance *pInstance = (m_creature->GetInstanceData()) ? ((ScriptedInstance*)m_creature->GetInstanceData()) : NULL; + if(pInstance) + { + pInstance->SetData(DATA_INSTRUCTORMALICIA_DEATH, 0); + + if(pInstance->GetData(DATA_CANSPAWNGANDLING)) + m_creature->SummonCreature(1853, 180.73, -9.43856, 75.507, 1.61399, TEMPSUMMON_DEAD_DESPAWN, 0); + } + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //CallOfGraves_Timer + if (CallOfGraves_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CALLOFGRAVES); + CallOfGraves_Timer = 65000; + }else CallOfGraves_Timer -= diff; + + //Corruption_Timer + if (Corruption_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) DoCast(target,SPELL_CORRUPTION); + + Corruption_Timer = 24000; + }else Corruption_Timer -= diff; + + //Renew_Timer + if (Renew_Timer < diff) + { + DoCast(m_creature, SPELL_RENEW); + Renew_Timer = 10000; + }else Renew_Timer -= diff; + + //FlashHeal_Timer + if (FlashHeal_Timer < diff) + { + DoCast(m_creature,SPELL_FLASHHEAL); + + //5 Flashheals will be casted + if (FlashCounter < 2) + { + FlashHeal_Timer = 5000; + FlashCounter++; + } + else + { + FlashCounter=0; + FlashHeal_Timer = 30000; + } + }else FlashHeal_Timer -= diff; + + //HealingTouch_Timer + if (HealingTouch_Timer < diff) + { + DoCast(m_creature,SPELL_HEALINGTOUCH); + + //3 Healingtouchs will be casted + if (HealingTouch_Timer < 2) + { + HealingTouch_Timer = 5500; + TouchCounter++; + } + else + { + TouchCounter=0; + HealingTouch_Timer = 30000; + } + }else HealingTouch_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_instructormalicia(Creature *_Creature) +{ + return new boss_instructormaliciaAI (_Creature); +} + +void AddSC_boss_instructormalicia() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_instructor_malicia"; + newscript->GetAI = GetAI_boss_instructormalicia; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/scholomance/boss_jandice_barov.cpp b/src/bindings/scripts/scripts/zone/scholomance/boss_jandice_barov.cpp new file mode 100644 index 00000000000..05eaba72a3f --- /dev/null +++ b/src/bindings/scripts/scripts/zone/scholomance/boss_jandice_barov.cpp @@ -0,0 +1,226 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_jandicebarov +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_CURSEOFBLOOD 24673 +//#define SPELL_ILLUSION 17773 + +//Spells of Illusion of Jandice Barov +#define SPELL_CLEAVE 15584 + +struct MANGOS_DLL_DECL boss_jandicebarovAI : public ScriptedAI +{ + boss_jandicebarovAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 CurseOfBlood_Timer; + uint32 Illusion_Timer; + //uint32 Illusioncounter; + uint32 Invisible_Timer; + bool Invisible; + int Rand; + int RandX; + int RandY; + Creature* Summoned; + + void Reset() + { + CurseOfBlood_Timer = 15000; + Illusion_Timer = 30000; + Invisible_Timer = 3000; //Too much too low? + Invisible = false; + } + + void Aggro(Unit *who) + { + } + + void SummonIllusions(Unit* victim) + { + Rand = rand()%10; + switch (rand()%2) + { + case 0: RandX = 0 - Rand; break; + case 1: RandX = 0 + Rand; break; + } + Rand = 0; + Rand = rand()%10; + switch (rand()%2) + { + case 0: RandY = 0 - Rand; break; + case 1: RandY = 0 + Rand; break; + } + Rand = 0; + Summoned = DoSpawnCreature(11439, RandX, RandY, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); + if(Summoned) + ((CreatureAI*)Summoned->AI())->AttackStart(victim); + } + + void UpdateAI(const uint32 diff) + { + if (Invisible && Invisible_Timer < diff) + { + //Become visible again + m_creature->setFaction(14); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + //Jandice Model + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID,11073); + Invisible = false; + } else if (Invisible) + { + Invisible_Timer -= diff; + //Do nothing while invisible + return; + } + + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //CurseOfBlood_Timer + if (CurseOfBlood_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CURSEOFBLOOD); + CurseOfBlood_Timer = 30000; + }else CurseOfBlood_Timer -= diff; + + //Illusion_Timer + if (!Invisible && Illusion_Timer < diff) + { + //Inturrupt any spell casting + m_creature->InterruptNonMeleeSpells(false); + m_creature->setFaction(35); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + // Invisible Model + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID,11686); + + //Summon 10 Illusions attacking random gamers + Unit* target = NULL; + for(int i = 0; i < 10;i++) + { + target = SelectUnit(SELECT_TARGET_RANDOM,0); + SummonIllusions(target); + } + Invisible = true; + Invisible_Timer = 3000; + + Illusion_Timer = 25000; + }else Illusion_Timer -= diff; + + // //Illusion_Timer + // if (Illusion_Timer < diff) + // { + // //Cast + // DoCast(m_creature->getVictim(),SPELL_ILLUSION); + // + // //3 Illusion will be summoned + // if (Illusioncounter < 3) + // { + // Illusion_Timer = 500; + // Illusioncounter++; + // } + // else { + // Illusion_Timer = 15000; + // Illusioncounter=0; + // } + // + // }else Illusion_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +// Illusion of Jandice Barov Script + +struct MANGOS_DLL_DECL mob_illusionofjandicebarovAI : public ScriptedAI +{ + mob_illusionofjandicebarovAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Cleave_Timer; + + void Reset() + { + Cleave_Timer = 4000; + } + + void Aggro(Unit *who) + { + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || m_creature->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + float attackRadius = m_creature->GetAttackDistance(who); + if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) + { + if(who->HasStealthAura()) + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + DoStartAttackAndMovement(who); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //Cleave_Timer + if (Cleave_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CLEAVE); + Cleave_Timer = 5000 + rand()%3000; + }else Cleave_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_jandicebarov(Creature *_Creature) +{ + return new boss_jandicebarovAI (_Creature); +} + +CreatureAI* GetAI_mob_illusionofjandicebarov(Creature *_Creature) +{ + return new mob_illusionofjandicebarovAI (_Creature); +} + +void AddSC_boss_jandicebarov() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_jandice_barov"; + newscript->GetAI = GetAI_boss_jandicebarov; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_illusionofjandicebarov"; + newscript->GetAI = GetAI_mob_illusionofjandicebarov; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/scholomance/boss_kormok.cpp b/src/bindings/scripts/scripts/zone/scholomance/boss_kormok.cpp new file mode 100644 index 00000000000..c9fb3c3a260 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/scholomance/boss_kormok.cpp @@ -0,0 +1,155 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Kormok +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_SHADOWBOLTVOLLEY 20741 +#define SPELL_BONESHIELD 27688 + +struct MANGOS_DLL_DECL boss_kormokAI : public ScriptedAI +{ + boss_kormokAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 ShadowVolley_Timer; + uint32 BoneShield_Timer; + uint32 Minion_Timer; + uint32 Mage_Timer; + bool Mages; + int Rand1; + int Rand1X; + int Rand1Y; + int Rand2; + int Rand2X; + int Rand2Y; + Creature* SummonedMinions; + Creature* SummonedMages; + + void Reset() + { + ShadowVolley_Timer = 10000; + BoneShield_Timer = 2000; + Minion_Timer = 15000; + Mage_Timer = 0; + Mages = false; + } + + void Aggro(Unit *who) + { + } + + void SummonMinion(Unit* victim) + { + Rand1 = rand()%8; + switch (rand()%2) + { + case 0: Rand1X = 0 - Rand1; break; + case 1: Rand1X = 0 + Rand1; break; + } + Rand1 = 0; + Rand1 = rand()%8; + switch (rand()%2) + { + case 0: Rand1Y = 0 - Rand1; break; + case 1: Rand1Y = 0 + Rand1; break; + } + Rand1 = 0; + SummonedMinions = DoSpawnCreature(16119, Rand1X, Rand1Y, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000); + ((CreatureAI*)SummonedMinions->AI())->AttackStart(victim); + } + + void SummonMages(Unit* victim) + { + Rand2 = rand()%10; + switch (rand()%2) + { + case 0: Rand2X = 0 - Rand2; break; + case 1: Rand2X = 0 + Rand2; break; + } + Rand2 = 0; + Rand2 = rand()%10; + switch (rand()%2) + { + case 0: Rand2Y = 0 - Rand2; break; + case 1: Rand2Y = 0 + Rand2; break; + } + Rand2 = 0; + SummonedMages = DoSpawnCreature(16120, Rand2X, Rand2Y, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000); + ((CreatureAI*)SummonedMages->AI())->AttackStart(victim); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //ShadowVolley_Timer + if (ShadowVolley_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SHADOWBOLTVOLLEY); + ShadowVolley_Timer = 15000; + }else ShadowVolley_Timer -= diff; + + //BoneShield_Timer + if (BoneShield_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_BONESHIELD); + BoneShield_Timer = 45000; + }else BoneShield_Timer -= diff; + + //Minion_Timer + if (Minion_Timer < diff) + { + //Cast + SummonMinion(m_creature->getVictim()); + SummonMinion(m_creature->getVictim()); + SummonMinion(m_creature->getVictim()); + SummonMinion(m_creature->getVictim()); + + Minion_Timer = 12000; + }else Minion_Timer -= diff; + + //Summon 2 Bone Mages + if ( !Mages && m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 26 ) + { + //Cast + SummonMages(m_creature->getVictim()); + SummonMages(m_creature->getVictim()); + Mages = true; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_kormok(Creature *_Creature) +{ + return new boss_kormokAI (_Creature); +} + +void AddSC_boss_kormok() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_kormok"; + newscript->GetAI = GetAI_boss_kormok; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/scholomance/boss_lord_alexei_barov.cpp b/src/bindings/scripts/scripts/zone/scholomance/boss_lord_alexei_barov.cpp new file mode 100644 index 00000000000..65601ff3ee3 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/scholomance/boss_lord_alexei_barov.cpp @@ -0,0 +1,98 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Lord_Alexei_Barov +SD%Complete: 100 +SDComment: aura applied/defined in database +SDCategory: Scholomance +EndScriptData */ + +#include "precompiled.h" +#include "def_scholomance.h" + +#define SPELL_IMMOLATE 20294 // Old ID was 15570 +#define SPELL_VEILOFSHADOW 17820 + +struct MANGOS_DLL_DECL boss_lordalexeibarovAI : public ScriptedAI +{ + boss_lordalexeibarovAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Immolate_Timer; + uint32 VeilofShadow_Timer; + + void Reset() + { + Immolate_Timer = 7000; + VeilofShadow_Timer = 15000; + + m_creature->LoadCreaturesAddon(); + } + + void JustDied(Unit *killer) + { + ScriptedInstance *pInstance = (m_creature->GetInstanceData()) ? ((ScriptedInstance*)m_creature->GetInstanceData()) : NULL; + if(pInstance) + { + pInstance->SetData(DATA_LORDALEXEIBAROV_DEATH, 0); + + if(pInstance->GetData(DATA_CANSPAWNGANDLING)) + m_creature->SummonCreature(1853, 180.73, -9.43856, 75.507, 1.61399, TEMPSUMMON_DEAD_DESPAWN, 0); + } + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //Immolate_Timer + if (Immolate_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) DoCast(target,SPELL_IMMOLATE); + + Immolate_Timer = 12000; + }else Immolate_Timer -= diff; + + //VeilofShadow_Timer + if (VeilofShadow_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_VEILOFSHADOW); + VeilofShadow_Timer = 20000; + }else VeilofShadow_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_lordalexeibarov(Creature *_Creature) +{ + return new boss_lordalexeibarovAI (_Creature); +} + +void AddSC_boss_lordalexeibarov() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_lord_alexei_barov"; + newscript->GetAI = GetAI_boss_lordalexeibarov; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/scholomance/boss_lorekeeper_polkelt.cpp b/src/bindings/scripts/scripts/zone/scholomance/boss_lorekeeper_polkelt.cpp new file mode 100644 index 00000000000..c1d6929ddfa --- /dev/null +++ b/src/bindings/scripts/scripts/zone/scholomance/boss_lorekeeper_polkelt.cpp @@ -0,0 +1,113 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Lorekeeper_Polkelt +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "precompiled.h" +#include "def_scholomance.h" + +#define SPELL_VOLATILEINFECTION 24928 +#define SPELL_DARKPLAGUE 18270 +#define SPELL_CORROSIVEACID 23313 +#define SPELL_NOXIOUSCATALYST 18151 + +struct MANGOS_DLL_DECL boss_lorekeeperpolkeltAI : public ScriptedAI +{ + boss_lorekeeperpolkeltAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 VolatileInfection_Timer; + uint32 Darkplague_Timer; + uint32 CorrosiveAcid_Timer; + uint32 NoxiousCatalyst_Timer; + + void Reset() + { + VolatileInfection_Timer = 38000; + Darkplague_Timer = 8000; + CorrosiveAcid_Timer = 45000; + NoxiousCatalyst_Timer = 35000; + } + + void JustDied(Unit *killer) + { + ScriptedInstance *pInstance = (m_creature->GetInstanceData()) ? ((ScriptedInstance*)m_creature->GetInstanceData()) : NULL; + if(pInstance) + { + pInstance->SetData(DATA_LOREKEEPERPOLKELT_DEATH, 0); + + if(pInstance->GetData(DATA_CANSPAWNGANDLING)) + m_creature->SummonCreature(1853, 180.73, -9.43856, 75.507, 1.61399, TEMPSUMMON_DEAD_DESPAWN, 0); + } + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //VolatileInfection_Timer + if (VolatileInfection_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_VOLATILEINFECTION); + VolatileInfection_Timer = 32000; + }else VolatileInfection_Timer -= diff; + + //Darkplague_Timer + if (Darkplague_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_DARKPLAGUE); + Darkplague_Timer = 8000; + }else Darkplague_Timer -= diff; + + //CorrosiveAcid_Timer + if (CorrosiveAcid_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CORROSIVEACID); + CorrosiveAcid_Timer = 25000; + }else CorrosiveAcid_Timer -= diff; + + //NoxiousCatalyst_Timer + if (NoxiousCatalyst_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_NOXIOUSCATALYST); + NoxiousCatalyst_Timer = 38000; + }else NoxiousCatalyst_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_lorekeeperpolkelt(Creature *_Creature) +{ + return new boss_lorekeeperpolkeltAI (_Creature); +} + +void AddSC_boss_lorekeeperpolkelt() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_lorekeeper_polkelt"; + newscript->GetAI = GetAI_boss_lorekeeperpolkelt; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/scholomance/boss_ras_frostwhisper.cpp b/src/bindings/scripts/scripts/zone/scholomance/boss_ras_frostwhisper.cpp new file mode 100644 index 00000000000..f8d9e6a66b8 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/scholomance/boss_ras_frostwhisper.cpp @@ -0,0 +1,125 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Ras_Frostwhisper +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_FROSTBOLT 21369 +#define SPELL_ICEARMOR 18100 //This is actually a buff he gives himself +#define SPELL_FREEZE 18763 +#define SPELL_FEAR 26070 +#define SPELL_CHILLNOVA 18099 +#define SPELL_FROSTVOLLEY 8398 + +struct MANGOS_DLL_DECL boss_rasfrostAI : public ScriptedAI +{ + boss_rasfrostAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 IceArmor_Timer; + uint32 Frostbolt_Timer; + uint32 Freeze_Timer; + uint32 Fear_Timer; + uint32 ChillNova_Timer; + uint32 FrostVolley_Timer; + + void Reset() + { + IceArmor_Timer = 2000; + Frostbolt_Timer = 8000; + ChillNova_Timer = 12000; + Freeze_Timer = 18000; + FrostVolley_Timer = 24000; + Fear_Timer = 45000; + + m_creature->CastSpell(m_creature,SPELL_ICEARMOR,true); + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //IceArmor_Timer + if (IceArmor_Timer < diff) + { + DoCast(m_creature, SPELL_ICEARMOR); + IceArmor_Timer = 180000; + }else IceArmor_Timer -= diff; + + //Frostbolt_Timer + if (Frostbolt_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) DoCast(target,SPELL_FROSTBOLT); + + Frostbolt_Timer = 8000; + }else Frostbolt_Timer -= diff; + + //Freeze_Timer + if (Freeze_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FREEZE); + Freeze_Timer = 24000; + }else Freeze_Timer -= diff; + + //Fear_Timer + if (Fear_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FEAR); + Fear_Timer = 30000; + }else Fear_Timer -= diff; + + //ChillNova_Timer + if (ChillNova_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CHILLNOVA); + ChillNova_Timer = 14000; + }else ChillNova_Timer -= diff; + + //FrostVolley_Timer + if (FrostVolley_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FROSTVOLLEY); + FrostVolley_Timer = 15000; + }else FrostVolley_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_rasfrost(Creature *_Creature) +{ + return new boss_rasfrostAI (_Creature); +} + +void AddSC_boss_rasfrost() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_boss_ras_frostwhisper"; + newscript->GetAI = GetAI_boss_rasfrost; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/scholomance/boss_the_ravenian.cpp b/src/bindings/scripts/scripts/zone/scholomance/boss_the_ravenian.cpp new file mode 100644 index 00000000000..ae833b8cc1c --- /dev/null +++ b/src/bindings/scripts/scripts/zone/scholomance/boss_the_ravenian.cpp @@ -0,0 +1,118 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_the_ravenian +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "precompiled.h" +#include "def_scholomance.h" + +#define SPELL_TRAMPLE 15550 +#define SPELL_CLEAVE 20691 +#define SPELL_SUNDERINCLEAVE 25174 +#define SPELL_KNOCKAWAY 10101 + +#define SAY_AGGRO1 "Mine! Mine! Mine! Gizlock is the ruler of this domain! You shall never reveal my presence!" + +struct MANGOS_DLL_DECL boss_theravenianAI : public ScriptedAI +{ + boss_theravenianAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Trample_Timer; + uint32 Cleave_Timer; + uint32 SunderingCleave_Timer; + uint32 KnockAway_Timer; + bool HasYelled; + + void Reset() + { + Trample_Timer = 24000; + Cleave_Timer = 15000; + SunderingCleave_Timer = 40000; + KnockAway_Timer = 32000; + HasYelled = false; + } + + void JustDied(Unit *killer) + { + ScriptedInstance *pInstance = (m_creature->GetInstanceData()) ? ((ScriptedInstance*)m_creature->GetInstanceData()) : NULL; + if(pInstance) + { + pInstance->SetData(DATA_THERAVENIAN_DEATH, 0); + + if(pInstance->GetData(DATA_CANSPAWNGANDLING)) + m_creature->SummonCreature(1853, 180.73, -9.43856, 75.507, 1.61399, TEMPSUMMON_DEAD_DESPAWN, 0); + } + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO1, LANG_UNIVERSAL, NULL); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //Trample_Timer + if (Trample_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_TRAMPLE); + Trample_Timer = 10000; + }else Trample_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CLEAVE); + Cleave_Timer = 7000; + }else Cleave_Timer -= diff; + + //SunderingCleave_Timer + if (SunderingCleave_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SUNDERINCLEAVE); + SunderingCleave_Timer = 20000; + }else SunderingCleave_Timer -= diff; + + //KnockAway_Timer + if (KnockAway_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_KNOCKAWAY); + KnockAway_Timer = 12000; + }else KnockAway_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_theravenian(Creature *_Creature) +{ + return new boss_theravenianAI (_Creature); +} + +void AddSC_boss_theravenian() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_the_ravenian"; + newscript->GetAI = GetAI_boss_theravenian; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/scholomance/boss_vectus.cpp b/src/bindings/scripts/scripts/zone/scholomance/boss_vectus.cpp new file mode 100644 index 00000000000..d6808efaf8a --- /dev/null +++ b/src/bindings/scripts/scripts/zone/scholomance/boss_vectus.cpp @@ -0,0 +1,95 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Vectus +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_FIRESHIELD 19626 +#define SPELL_BLASTWAVE 13021 +#define SPELL_FRENZY 28371 + +struct MANGOS_DLL_DECL boss_vectusAI : public ScriptedAI +{ + boss_vectusAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 FireShield_Timer; + uint32 BlastWave_Timer; + uint32 Frenzy_Timer; + + void Reset() + { + FireShield_Timer = 2000; + BlastWave_Timer = 14000; + Frenzy_Timer = 0; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //FireShield_Timer + if (FireShield_Timer < diff) + { + DoCast(m_creature, SPELL_FIRESHIELD); + FireShield_Timer = 90000; + }else FireShield_Timer -= diff; + + //BlastWave_Timer + if (BlastWave_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_BLASTWAVE); + BlastWave_Timer = 12000; + }else BlastWave_Timer -= diff; + + //Frenzy_Timer + if ( m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 25 ) + { + if (Frenzy_Timer < diff) + { + DoCast(m_creature,SPELL_FRENZY); + DoTextEmote("goes into a killing frenzy!",NULL); + + Frenzy_Timer = 24000; + }else Frenzy_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_vectus(Creature *_Creature) +{ + return new boss_vectusAI (_Creature); +} + +void AddSC_boss_vectus() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_vectus"; + newscript->GetAI = GetAI_boss_vectus; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/scholomance/def_scholomance.h b/src/bindings/scripts/scripts/zone/scholomance/def_scholomance.h new file mode 100644 index 00000000000..a4023315e01 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/scholomance/def_scholomance.h @@ -0,0 +1,15 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_SCHOLOMANCE_H +#define DEF_SCHOLOMANCE_H + +#define DATA_CANSPAWNGANDLING 1 +#define DATA_DOCTORTHEOLENKRASTINOV_DEATH 2 +#define DATA_INSTRUCTORMALICIA_DEATH 3 +#define DATA_LADYILLUCIABAROV_DEATH 4 +#define DATA_LORDALEXEIBAROV_DEATH 5 +#define DATA_LOREKEEPERPOLKELT_DEATH 6 +#define DATA_THERAVENIAN_DEATH 7 +#endif diff --git a/src/bindings/scripts/scripts/zone/scholomance/instance_scholomance.cpp b/src/bindings/scripts/scripts/zone/scholomance/instance_scholomance.cpp new file mode 100644 index 00000000000..7084635493c --- /dev/null +++ b/src/bindings/scripts/scripts/zone/scholomance/instance_scholomance.cpp @@ -0,0 +1,102 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Scholomance +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "precompiled.h" +#include "def_scholomance.h" + +struct MANGOS_DLL_DECL instance_scholomance : public ScriptedInstance +{ + instance_scholomance(Map *Map) : ScriptedInstance(Map) {Initialize();}; + + //Lord Alexei Barov, Doctor Theolen Krastinov, The Ravenian, Lorekeeper Polkelt, Instructor Malicia and the Lady Illucia Barov. + bool IsBossDied[6]; + + void Initialize() + { + IsBossDied[0] = false; + IsBossDied[1] = false; + IsBossDied[2] = false; + IsBossDied[3] = false; + IsBossDied[4] = false; + IsBossDied[5] = false; + } + + bool IsEncounterInProgress() const + { + //not active in scholomance + return false; + } + + uint32 GetData(uint32 type) + { + if(type == DATA_CANSPAWNGANDLING) + if(IsBossDied[0] && IsBossDied[1] && IsBossDied[2] && IsBossDied[3] && IsBossDied[4] && IsBossDied[5]) + return 1; + + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_LORDALEXEIBAROV_DEATH: + IsBossDied[0] = true; + break; + + case DATA_DOCTORTHEOLENKRASTINOV_DEATH: + IsBossDied[1] = true; + break; + + case DATA_THERAVENIAN_DEATH: + IsBossDied[2] = true; + break; + + case DATA_LOREKEEPERPOLKELT_DEATH: + IsBossDied[3] = true; + break; + + case DATA_INSTRUCTORMALICIA_DEATH: + IsBossDied[4] = true; + break; + + case DATA_LADYILLUCIABAROV_DEATH: + IsBossDied[5] = true; + break; + } + } +}; + +InstanceData* GetInstanceData_instance_scholomance(Map* map) +{ + return new instance_scholomance(map); +} + +void AddSC_instance_scholomance() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_scholomance"; + newscript->GetInstanceData = GetInstanceData_instance_scholomance; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/searing_gorge/searing_gorge.cpp b/src/bindings/scripts/scripts/zone/searing_gorge/searing_gorge.cpp new file mode 100644 index 00000000000..6834cd8a078 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/searing_gorge/searing_gorge.cpp @@ -0,0 +1,159 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Searing_Gorge +SD%Complete: 80 +SDComment: Quest support: 3377, 3441 (More accurate info on Kalaran needed). Lothos Riftwaker teleport to Molten Core. +SDCategory: Searing Gorge +EndScriptData */ + +/* ContentData +npc_kalaran_windblade +npc_lothos_riftwaker +npc_zamael_lunthistle +EndContentData */ + +#include "precompiled.h" + +/*###### +## npc_kalaran_windblade +######*/ + +bool GossipHello_npc_kalaran_windblade(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if (player->GetQuestStatus(3441) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM( 0, "Tell me what drives this vengance?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_kalaran_windblade(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF: + player->ADD_GOSSIP_ITEM( 0, "Continue please", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->SEND_GOSSIP_MENU(1954, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+1: + player->ADD_GOSSIP_ITEM( 0, "Let me confer with my colleagues", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->SEND_GOSSIP_MENU(1955, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + player->CLOSE_GOSSIP_MENU(); + player->AreaExploredOrEventHappens(3441); + break; + } + return true; +} + +/*###### +## npc_lothos_riftwaker +######*/ + +bool GossipHello_npc_lothos_riftwaker(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if (player->GetQuestRewardStatus(7487) || player->GetQuestRewardStatus(7848)) + player->ADD_GOSSIP_ITEM(0, "Teleport me to the Molten Core", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_lothos_riftwaker(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if (action == GOSSIP_ACTION_INFO_DEF + 1) + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(409, 1096, -467, -104.6, 3.64); + } + + return true; +} + +/*###### +## npc_zamael_lunthistle +######*/ + +bool GossipHello_npc_zamael_lunthistle(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if (player->GetQuestStatus(3377) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM( 0, "Tell me your story", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + player->SEND_GOSSIP_MENU(1920, _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_zamael_lunthistle(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF: + player->ADD_GOSSIP_ITEM( 0, "Please continue...", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->SEND_GOSSIP_MENU(1921, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+1: + player->ADD_GOSSIP_ITEM( 0, "Goodbye", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->SEND_GOSSIP_MENU(1922, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + player->CLOSE_GOSSIP_MENU(); + player->AreaExploredOrEventHappens(3377); + break; + } + return true; +} + +/*###### +## +######*/ + +void AddSC_searing_gorge() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npc_kalaran_windblade"; + newscript->pGossipHello = &GossipHello_npc_kalaran_windblade; + newscript->pGossipSelect = &GossipSelect_npc_kalaran_windblade; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_lothos_riftwaker"; + newscript->pGossipHello = &GossipHello_npc_lothos_riftwaker; + newscript->pGossipSelect = &GossipSelect_npc_lothos_riftwaker; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_zamael_lunthistle"; + newscript->pGossipHello = &GossipHello_npc_zamael_lunthistle; + newscript->pGossipSelect = &GossipSelect_npc_zamael_lunthistle; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/shadowfang_keep/def_shadowfang_keep.h b/src/bindings/scripts/scripts/zone/shadowfang_keep/def_shadowfang_keep.h new file mode 100644 index 00000000000..7ece07f0231 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/shadowfang_keep/def_shadowfang_keep.h @@ -0,0 +1,12 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_SHADOWFANG_H +#define DEF_SHADOWFANG_H + +#define TYPE_FREE_NPC 1 +#define TYPE_RETHILGORE 2 +#define TYPE_FENRUS 3 +#define TYPE_NANDOS 4 +#endif diff --git a/src/bindings/scripts/scripts/zone/shadowfang_keep/instance_shadowfang_keep.cpp b/src/bindings/scripts/scripts/zone/shadowfang_keep/instance_shadowfang_keep.cpp new file mode 100644 index 00000000000..5e4ce0b3267 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/shadowfang_keep/instance_shadowfang_keep.cpp @@ -0,0 +1,152 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Shadowfang_Keep +SD%Complete: 75 +SDComment: TODO: check what other parts would require additional code (ex: make sure door are in open state if boss dead) +SDCategory: Shadowfang Keep +EndScriptData */ + +#include "precompiled.h" +#include "def_shadowfang_keep.h" + +#define ENCOUNTERS 4 + +//#define ENTRY_BOSS_RETHILGORE 3914 +//#define ENTRY_BOSS_FENRUS 4274 +//#define ENTRY_BOSS_NANDOS 3927 + +#define ENTRY_COURTYARD_DOOR 18895 //door to open when talking to NPC's +#define ENTRY_SORCERER_DOOR 18972 //door to open when Fenrus the Devourer +#define ENTRY_ARUGAL_DOOR 18971 //door to open when Wolf Master Nandos + +struct MANGOS_DLL_DECL instance_shadowfang_keep : public ScriptedInstance +{ + instance_shadowfang_keep(Map *Map) : ScriptedInstance(Map) {Initialize();}; + + uint32 Encounter[ENCOUNTERS]; + + /*uint64 RethilgoreGUID; + uint64 FenrusGUID; + uint64 NandosGUID;*/ + + GameObject *DoorCourtyard; + GameObject *DoorSorcerer; + GameObject *DoorArugal; + + void Initialize() + { + /*RethilgoreGUID = 0; + FenrusGUID = 0; + NandosGUID = 0;*/ + + DoorCourtyard = NULL; + DoorSorcerer = NULL; + DoorArugal = NULL; + } + + void OnObjectCreate(GameObject *go) + { + switch(go->GetEntry()) + { + case ENTRY_COURTYARD_DOOR: DoorCourtyard = go; break; + case ENTRY_SORCERER_DOOR: DoorSorcerer = go; break; + case ENTRY_ARUGAL_DOOR: DoorArugal = go; break; + } + } + + /*void OnCreatureCreate(Creature *creature, uint32 creature_entry) + { + switch(creature_entry) + { + case ENTRY_BOSS_RETHILGORE: + RethilgoreGUID = creature->GetGUID(); + break; + case ENTRY_BOSS_FENRUS: + FenrusGUID = creature->GetGUID(); + break; + case ENTRY_BOSS_NANDOS: + NandosGUID = creature->GetGUID(); + break; + } + }*/ + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case TYPE_FREE_NPC: + if(data == DONE) + { + if(DoorCourtyard) + DoorCourtyard->UseDoorOrButton(); + } + Encounter[0] = data; + break; + case TYPE_RETHILGORE: + Encounter[1] = data; + break; + case TYPE_FENRUS: + if(data == DONE) + { + if(DoorSorcerer) + DoorSorcerer->UseDoorOrButton(); + } + Encounter[2] = data; + break; + case TYPE_NANDOS: + if(data == DONE) + { + if(DoorArugal) + DoorArugal->UseDoorOrButton(); + } + Encounter[3] = data; + break; + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case TYPE_FREE_NPC: + return Encounter[0]; + case TYPE_RETHILGORE: + return Encounter[1]; + case TYPE_FENRUS: + return Encounter[2]; + case TYPE_NANDOS: + return Encounter[3]; + } + return 0; + } + +}; + +InstanceData* GetInstanceData_instance_shadowfang_keep(Map* map) +{ + return new instance_shadowfang_keep(map); +} + +void AddSC_instance_shadowfang_keep() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_shadowfang_keep"; + newscript->GetInstanceData = GetInstanceData_instance_shadowfang_keep; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/shadowfang_keep/shadowfang_keep.cpp b/src/bindings/scripts/scripts/zone/shadowfang_keep/shadowfang_keep.cpp new file mode 100644 index 00000000000..172a0907a79 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/shadowfang_keep/shadowfang_keep.cpp @@ -0,0 +1,117 @@ +/* Copyright (C) 2006,2007 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Shadowfang_Keep +SD%Complete: 75 +SDComment: npc_shadowfang_prisoner using escortAI for movement to door. Might need additional code in case being attacked. Add proper texts/say(). +SDCategory: Shadowfang Keep +EndScriptData */ + +/* ContentData +npc_shadowfang_prisoner +EndContentData */ + +#include "precompiled.h" +#include "../../npc/npc_escortAI.h" +#include "def_shadowfang_keep.h" + +/*###### +## npc_shadowfang_prisoner +######*/ + +struct MANGOS_DLL_DECL npc_shadowfang_prisonerAI : public npc_escortAI +{ + npc_shadowfang_prisonerAI(Creature *c) : npc_escortAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance *pInstance; + + void WaypointReached(uint32 i) + { + if( pInstance && i == 6) + { + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_TALK); + m_creature->Say("Thanks for freeing me, I'll open this door for you, then I will get out of here.", LANG_UNIVERSAL, 0); + pInstance->SetData(TYPE_FREE_NPC, DONE); + } + } + + void Reset() {} + void Aggro(Unit* who) {} +}; + +CreatureAI* GetAI_npc_shadowfang_prisoner(Creature *_Creature) +{ + npc_shadowfang_prisonerAI* prisonerAI = new npc_shadowfang_prisonerAI(_Creature); + + uint32 eCreature = _Creature->GetEntry(); + + if( eCreature==3849) //adamant + prisonerAI->AddWaypoint(0, -254.47, 2117.48, 81.17); + if( eCreature==3850) //ashcrombe + prisonerAI->AddWaypoint(0, -252.35, 2126.71, 81.17); + + prisonerAI->AddWaypoint(1, -253.63, 2131.27, 81.28); + prisonerAI->AddWaypoint(2, -249.66, 2142.45, 87.01); + prisonerAI->AddWaypoint(3, -248.08, 2143.68, 87.01); + prisonerAI->AddWaypoint(4, -238.87, 2139.93, 87.01); + prisonerAI->AddWaypoint(5, -235.47, 2149.18, 90.59); + prisonerAI->AddWaypoint(6, -239.89, 2156.06, 90.62, 20000); + + return (CreatureAI*)prisonerAI; +} + +bool GossipHello_npc_shadowfang_prisoner(Player *player, Creature *_Creature) +{ + ScriptedInstance* pInstance = ((ScriptedInstance*)_Creature->GetInstanceData()); + + if( pInstance && !pInstance->GetData(TYPE_FREE_NPC) && pInstance->GetData(TYPE_RETHILGORE) == DONE ) + player->ADD_GOSSIP_ITEM( 0, "Thanks, I'll follow you to the door.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_shadowfang_prisoner(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + if (action == GOSSIP_ACTION_INFO_DEF+1) + { + player->CLOSE_GOSSIP_MENU(); + ((npc_escortAI*)(_Creature->AI()))->Start(false, false, false, player->GetGUID()); + } + return true; +} + +/*###### +## AddSC +######*/ + +void AddSC_shadowfang_keep() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npc_shadowfang_prisoner"; + newscript->pGossipHello = &GossipHello_npc_shadowfang_prisoner; + newscript->pGossipSelect = &GossipSelect_npc_shadowfang_prisoner; + newscript->GetAI = GetAI_npc_shadowfang_prisoner; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/shadowmoon_valley/boss_doomwalker.cpp b/src/bindings/scripts/scripts/zone/shadowmoon_valley/boss_doomwalker.cpp new file mode 100644 index 00000000000..1960d9f9cc1 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/shadowmoon_valley/boss_doomwalker.cpp @@ -0,0 +1,211 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Doomwalker +SD%Complete: 100 +SDComment: +SDCategory: Shadowmoon Valley +EndScriptData */ + +#include "precompiled.h" + +//-------------------------------------- +//Spells +#define SPELL_SUNDER_ARMOR 30901 + +#define SPELL_CHAIN_LIGHTNING 33665 + +#define SPELL_OVERRUN 32636 +#define SAY_OVERRUN_1 "Trajectory locked." +#define SOUND_OVERRUN_1 11347 +#define SAY_OVERRUN_2 "Engage maximum speed." +#define SOUND_OVERRUN_2 11348 + +#define SPELL_ENRAGE 34624 + +#define SPELL_MARK_DEATH 37128 + +#define SPELL_EARTHQUAKE 32686 +#define SAY_EARTHQUAKE_1 "Tectonic disruption commencing." +#define SOUND_EARTHQUAKE_1 11345 +#define SAY_EARTHQUAKE_2 "Magnitude set. Release." +#define SOUND_EARTHQUAKE_2 11346 + +#define SAY_AGGRO "Do not proceed. You will be eliminated!" +#define SOUND_AGGRO 11344 + +#define SAY_SLAY_1 "Threat level zero." +#define SOUND_SLAY_1 11349 +#define SAY_SLAY_2 "Directive accomplished." +#define SOUND_SLAY_2 11350 +#define SAY_SLAY_3 "Target exterminated." +#define SOUND_SLAY_3 11351 + +#define SAY_DEATH "System failure in five... four..." +#define SOUND_DEATH 11352 + +struct MANGOS_DLL_DECL boss_doomwalkerAI : public ScriptedAI +{ + boss_doomwalkerAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Chain_Timer; + uint32 Enrage_Timer; + uint32 Overrun_Timer; + uint32 Quake_Timer; + uint32 Armor_Timer; + + bool InEnrage; + + void Reset() + { + Enrage_Timer = 0; + Armor_Timer = 10000; + Chain_Timer = 20000; + Quake_Timer = 60000; + Overrun_Timer = 120000; + + InEnrage = false; + } + + void KilledUnit(Unit* Victim) + { + if(rand()%5) + return; + + switch(rand()%3) + { + case 0: + DoYell(SAY_SLAY_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY_1); + break; + case 1: + DoYell(SAY_SLAY_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY_2); + break; + case 2: + DoYell(SAY_SLAY_3, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY_3); + break; + } + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_DEATH); + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if (m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE)) + { + //when hp <= 20% gain enrage + if (((m_creature->GetHealth()*100)/ m_creature->GetMaxHealth()) <= 20) + { + if(Enrage_Timer < diff) + { + DoCast(m_creature,SPELL_ENRAGE); + Enrage_Timer = 6000; + InEnrage = true; + }else Enrage_Timer -= diff; + } + + //Spell Overrun + if (Overrun_Timer < diff) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_OVERRUN_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_OVERRUN_1); + break; + case 1: + DoYell(SAY_OVERRUN_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_OVERRUN_2); + break; + } + DoCast(m_creature->getVictim(),SPELL_OVERRUN); + Overrun_Timer = (30 + rand()% 40) * 1000; //30-70sec cooldown + + }else Overrun_Timer -= diff; + + //Spell Earthquake + if (Quake_Timer < diff) + { + if (rand()%2) + return; + + switch(rand()%2) + { + case 0: + DoYell(SAY_EARTHQUAKE_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_EARTHQUAKE_1); + break; + case 1: + DoYell(SAY_EARTHQUAKE_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_EARTHQUAKE_2); + break; + } + if(InEnrage) + { + m_creature->RemoveAura(SPELL_ENRAGE, 0);//remove enrage before casting earthquake because enrage + earthquake = 16000dmg over 8sec and all dead + } + DoCast(m_creature,SPELL_EARTHQUAKE); + Quake_Timer = (70 + rand()% 30) * 1000; //70-100sec cooldown + }else Quake_Timer -= diff; + + //Spell Chain Lightning + if (Chain_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CHAIN_LIGHTNING); + Chain_Timer = (50 + rand()% 50) * 1000; //50-100sec cooldown + }else Chain_Timer -= diff; + + //Spell Sunder Armor + if (Armor_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SUNDER_ARMOR); + Armor_Timer = (15 + rand()% 7) * 1000; //15-23sec cooldown about 70 proc to stack + }else Armor_Timer -= diff; + + DoMeleeAttackIfReady(); + } + } +}; + +CreatureAI* GetAI_boss_doomwalker(Creature *_Creature) +{ + return new boss_doomwalkerAI (_Creature); +} + +void AddSC_boss_doomwalker() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_doomwalker"; + newscript->GetAI = GetAI_boss_doomwalker; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/shadowmoon_valley/shadowmoon_valley.cpp b/src/bindings/scripts/scripts/zone/shadowmoon_valley/shadowmoon_valley.cpp new file mode 100644 index 00000000000..d75d50c666b --- /dev/null +++ b/src/bindings/scripts/scripts/zone/shadowmoon_valley/shadowmoon_valley.cpp @@ -0,0 +1,748 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Shadowmoon_Valley +SD%Complete: 100 +SDComment: Quest support: 10519, 10583, 10601, 10814, 10804, 10854, 11082. Vendor Drake Dealer Hurlunk. Teleporter TO Invasion Point: Cataclysm +SDCategory: Shadowmoon Valley +EndScriptData */ + +/* ContentData +mob_mature_netherwing_drake +mob_enslaved_netherwing_drake +npc_drake_dealer_hurlunk +npc_invis_legion_teleporter +npcs_flanis_swiftwing_and_kagrosh +npc_murkblood_overseer +npc_neltharaku +npc_karynaku +npc_oronok_tornheart +EndContentData */ + +#include "precompiled.h" + +/*##### +# mob_mature_netherwing_drake +#####*/ + +#define SPELL_PLACE_CARCASS 38439 +#define SPELL_JUST_EATEN 38502 +#define SPELL_NETHER_BREATH 38467 + +#define SAY_JUST_EATEN "Thank you, mortal." + +struct MANGOS_DLL_DECL mob_mature_netherwing_drakeAI : public ScriptedAI +{ + mob_mature_netherwing_drakeAI(Creature* c) : ScriptedAI(c) + { + Reset(); + PlayerGUID = 0; + } + + uint64 PlayerGUID; + + bool IsEating; + bool Evade; + + uint32 ResetTimer; + uint32 CastTimer; + uint32 EatTimer; + + void Reset() + { + IsEating = false; + Evade = false; + + ResetTimer = 120000; + EatTimer = 5000; + CastTimer = 5000; + } + + void Aggro(Unit* who) { } + + void MoveInLineOfSight(Unit* who) + { + if(m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE) + return; + + ScriptedAI::MoveInLineOfSight(who); + } + + void SpellHit(Unit* caster, const SpellEntry* spell) + { + if(!caster) + return; + + if(caster->GetTypeId() == TYPEID_PLAYER && spell->Id == SPELL_PLACE_CARCASS && !m_creature->HasAura(SPELL_JUST_EATEN, 0) && !PlayerGUID) + { + float PlayerX, PlayerY, PlayerZ; + caster->GetClosePoint(PlayerX, PlayerY, PlayerZ, m_creature->GetObjectSize()); + m_creature->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT + MOVEMENTFLAG_LEVITATING); + m_creature->GetMotionMaster()->MovePoint(1, PlayerX, PlayerY, PlayerZ); + PlayerGUID = caster->GetGUID(); + } + } + + void MovementInform(uint32 type, uint32 id) + { + if(type != POINT_MOTION_TYPE) + return; + + if(id == 1) + { + IsEating = true; + EatTimer = 5000; + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_ATTACKUNARMED); + m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT + MOVEMENTFLAG_LEVITATING); + } + } + + void UpdateAI(const uint32 diff) + { + if(IsEating) + if(EatTimer < diff) + { + IsEating = false; + DoCast(m_creature, SPELL_JUST_EATEN); + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); + DoSay(SAY_JUST_EATEN, LANG_DRACONIC, NULL); + if(PlayerGUID) + { + Player* plr = ((Player*)Unit::GetUnit((*m_creature), PlayerGUID)); + if(plr && plr->GetQuestStatus(10804) == QUEST_STATUS_INCOMPLETE) + { + plr->KilledMonster(22131, m_creature->GetGUID()); + Evade = true; + PlayerGUID = 0; + } + } + }else EatTimer -= diff; + + if(Evade) + if(ResetTimer < diff) + EnterEvadeMode(); + else ResetTimer -= diff; + + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(CastTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_NETHER_BREATH); + CastTimer = 5000; + }else CastTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_mature_netherwing_drake(Creature *_creature) +{ + return new mob_mature_netherwing_drakeAI(_creature); +} + +/*### +# mob_enslaved_netherwing_drake +####*/ + +#define FACTION_DEFAULT 62 +#define FACTION_FRIENDLY 1840 // Not sure if this is correct, it was taken off of Mordenai. + +#define SPELL_HIT_FORCE_OF_NELTHARAKU 38762 +#define SPELL_FORCE_OF_NELTHARAKU 38775 + +#define CREATURE_DRAGONMAW_SUBJUGATOR 21718 +#define CREATURE_ESCAPE_DUMMY 22317 + +struct MANGOS_DLL_DECL mob_enslaved_netherwing_drakeAI : public ScriptedAI +{ + mob_enslaved_netherwing_drakeAI(Creature* c) : ScriptedAI(c) + { + Reset(); + PlayerGUID = 0; + Tapped = false; + } + + uint64 PlayerGUID; + uint32 FlyTimer; + bool Tapped; + + void Reset() + { + if(!Tapped) + m_creature->setFaction(FACTION_DEFAULT); + + FlyTimer = 10000; + m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT + MOVEMENTFLAG_LEVITATING); + m_creature->SetVisibility(VISIBILITY_ON); + } + + void Aggro(Unit* who) { } + + Creature* SelectCreatureInGrid(uint32 entry, float range) + { + Creature* pCreature = NULL; + + // Time for some omg mind blowing code to search for creature + CellPair pair(MaNGOS::ComputeCellPair(m_creature->GetPositionX(), m_creature->GetPositionY())); + Cell cell(pair); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck creature_check(*m_creature, entry, true, range); + MaNGOS::CreatureLastSearcher searcher(pCreature, creature_check); + + TypeContainerVisitor, GridTypeMapContainer> creature_searcher(searcher); + + CellLock cell_lock(cell, pair); + cell_lock->Visit(cell_lock, creature_searcher,*(m_creature->GetMap())); + + return pCreature; + } + + void SpellHit(Unit* caster, const SpellEntry* spell) + { + if(!caster) + return; + + if(caster->GetTypeId() == TYPEID_PLAYER && spell->Id == SPELL_HIT_FORCE_OF_NELTHARAKU && !Tapped) + { + Tapped = true; + PlayerGUID = caster->GetGUID(); + + m_creature->setFaction(FACTION_FRIENDLY); + DoCast(caster, SPELL_FORCE_OF_NELTHARAKU, true); + + Creature* Dragonmaw = SelectCreatureInGrid(CREATURE_DRAGONMAW_SUBJUGATOR, 50); + + if(Dragonmaw) + { + m_creature->AddThreat(Dragonmaw, 100000.0f); + AttackStart(Dragonmaw); + } + + HostilReference* ref = m_creature->getThreatManager().getOnlineContainer().getReferenceByTarget(caster); + if(ref) + ref->removeReference(); + } + } + + void MovementInform(uint32 type, uint32 id) + { + if(type != POINT_MOTION_TYPE) + return; + + if(id == 1) + { + if(PlayerGUID) + { + Unit* plr = Unit::GetUnit((*m_creature), PlayerGUID); + if(plr) + DoCast(plr, SPELL_FORCE_OF_NELTHARAKU, true); + + PlayerGUID = 0; + } + m_creature->SetVisibility(VISIBILITY_OFF); + m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT + MOVEMENTFLAG_LEVITATING); + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + m_creature->RemoveCorpse(); + } + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + { + if(Tapped) + if(FlyTimer < diff) + { + Tapped = false; + if(PlayerGUID) + { + Player* plr = ((Player*)Unit::GetUnit((*m_creature), PlayerGUID)); + if(plr && plr->GetQuestStatus(10854) == QUEST_STATUS_INCOMPLETE) + { + plr->KilledMonster(22316, m_creature->GetGUID()); + /* + float x,y,z; + m_creature->GetPosition(x,y,z); + + float dx,dy,dz; + m_creature->GetRandomPoint(x, y, z, 20, dx, dy, dz); + dz += 20; // so it's in the air, not ground*/ + + float dx, dy, dz; + + Creature* EscapeDummy = SelectCreatureInGrid(CREATURE_ESCAPE_DUMMY, 30); + if(EscapeDummy) + EscapeDummy->GetPosition(dx, dy, dz); + else + { + m_creature->GetRandomPoint(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 20, dx, dy, dz); + dz += 25; + } + + m_creature->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT + MOVEMENTFLAG_LEVITATING); + m_creature->GetMotionMaster()->MovePoint(1, dx, dy, dz); + } + } + }else FlyTimer -= diff; + return; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_enslaved_netherwing_drake(Creature* _Creature) +{ + return new mob_enslaved_netherwing_drakeAI(_Creature); +} + +/*##### +# mob_dragonmaw_peon +#####*/ + +struct MANGOS_DLL_DECL mob_dragonmaw_peonAI : public ScriptedAI +{ + mob_dragonmaw_peonAI(Creature* c) : ScriptedAI(c) + { + Reset(); + } + + uint64 PlayerGUID; + bool Tapped; + uint32 PoisonTimer; + + void Reset() + { + PlayerGUID = 0; + Tapped = false; + PoisonTimer = 0; + } + + void Aggro(Unit* who) { } + + void SpellHit(Unit* caster, const SpellEntry* spell) + { + if(!caster) + return; + + if(caster->GetTypeId() == TYPEID_PLAYER && spell->Id == 40468 && !Tapped) + { + PlayerGUID = caster->GetGUID(); + + Tapped = true; + float x, y, z; + caster->GetClosePoint(x, y, z, m_creature->GetObjectSize()); + + m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + m_creature->GetMotionMaster()->MovePoint(1, x, y, z); + } + } + + void MovementInform(uint32 type, uint32 id) + { + if(type != POINT_MOTION_TYPE) + return; + + if(id) + { + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_EAT); + PoisonTimer = 15000; + } + } + + void UpdateAI(const uint32 diff) + { + if(PoisonTimer) + if(PoisonTimer <= diff) + { + if(PlayerGUID) + { + Player* plr = ((Player*)Unit::GetUnit((*m_creature), PlayerGUID)); + if(plr && plr->GetQuestStatus(11020) == QUEST_STATUS_INCOMPLETE) + plr->KilledMonster(23209, m_creature->GetGUID()); + } + PoisonTimer = 0; + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + }else PoisonTimer -= diff; + } +}; + +/*###### +## npc_drake_dealer_hurlunk +######*/ + +bool GossipHello_npc_drake_dealer_hurlunk(Player *player, Creature *_Creature) +{ + if (_Creature->isVendor() && player->GetReputationRank(1015) == REP_EXALTED) + player->ADD_GOSSIP_ITEM(1, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_drake_dealer_hurlunk(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + if (action == GOSSIP_ACTION_TRADE) + player->SEND_VENDORLIST( _Creature->GetGUID() ); + + return true; +} + +/*###### +## npc_invis_legion_teleporter +######*/ + +#define SPELL_TELE_A_TO 37387 +#define SPELL_TELE_H_TO 37389 + +struct MANGOS_DLL_DECL npc_invis_legion_teleporterAI : public ScriptedAI +{ + npc_invis_legion_teleporterAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint64 PlayerGuid; + uint32 TeleTimer; + + void Reset() + { + PlayerGuid=0; + TeleTimer = 5000; + } + + void Aggro(Unit* who) + { + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || who->GetTypeId() != TYPEID_PLAYER) + return; + + if(who->GetTypeId() == TYPEID_PLAYER && m_creature->GetDistance(who)<4) + { + if (who->isAlive() || !who->isInCombat()) + PlayerGuid = who->GetGUID(); + } + } + + void UpdateAI(const uint32 diff) + { + if(TeleTimer < diff) + { + if(PlayerGuid) + { + Player* player = ((Player*)Unit::GetUnit((*m_creature), PlayerGuid)); + + if(m_creature->GetDistance(player)<3) + { + if(player->GetTeam()== ALLIANCE && player->GetQuestRewardStatus(10589)) + player->CastSpell(player,SPELL_TELE_A_TO,false); + if(player->GetTeam()== HORDE && player->GetQuestRewardStatus(10604)) + player->CastSpell(player,SPELL_TELE_H_TO,false); + } + PlayerGuid=0; + } + TeleTimer = 5000; + }else TeleTimer -= diff; + } +}; +CreatureAI* GetAI_npc_invis_legion_teleporter(Creature *_Creature) +{ + return new npc_invis_legion_teleporterAI (_Creature); +} + +/*###### +## npc_flanis_swiftwing_and_kagrosh +######*/ + +bool GossipHello_npcs_flanis_swiftwing_and_kagrosh(Player *player, Creature *_Creature) +{ + if (player->GetQuestStatus(10583) == QUEST_STATUS_INCOMPLETE && !player->HasItemCount(30658,1,true)) + player->ADD_GOSSIP_ITEM( 0, "Take Flanis's Pack", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + if (player->GetQuestStatus(10601) == QUEST_STATUS_INCOMPLETE && !player->HasItemCount(30659,1,true)) + player->ADD_GOSSIP_ITEM( 0, "Take Kagrosh's Pack", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npcs_flanis_swiftwing_and_kagrosh(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + if (action == GOSSIP_ACTION_INFO_DEF+1) + { + ItemPosCountVec dest; + uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, 30658, 1, false); + if( msg == EQUIP_ERR_OK ) + { + player->StoreNewItem( dest, 30658, 1, true); + player->PlayerTalkClass->ClearMenus(); + } + } + if (action == GOSSIP_ACTION_INFO_DEF+2) + { + ItemPosCountVec dest; + uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, 30659, 1, false); + if( msg == EQUIP_ERR_OK ) + { + player->StoreNewItem( dest, 30659, 1, true); + player->PlayerTalkClass->ClearMenus(); + } + } + return true; +} + +/*###### +## npc_murkblood_overseer +######*/ + +#define QUEST_11082 11082 + +bool GossipHello_npc_murkblood_overseer(Player *player, Creature *_Creature) +{ + if (player->GetQuestStatus(QUEST_11082) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM( 0, "I am here for you, overseer.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + player->SEND_GOSSIP_MENU(10940, _Creature->GetGUID()); + return true; +} + +bool GossipSelect_npc_murkblood_overseer(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF+1: + player->ADD_GOSSIP_ITEM(0, "How dare you question an overseer of the Dragonmaw!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + //correct id not known + player->SEND_GOSSIP_MENU(10940, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + player->ADD_GOSSIP_ITEM(0, "Who speaks of me? What are you talking about, broken?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + //correct id not known + player->SEND_GOSSIP_MENU(10940, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + player->ADD_GOSSIP_ITEM(0, "Continue please.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + //correct id not known + player->SEND_GOSSIP_MENU(10940, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + player->ADD_GOSSIP_ITEM(0, "Who are these bidders?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + //correct id not known + player->SEND_GOSSIP_MENU(10940, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + player->ADD_GOSSIP_ITEM(0, "Well... yes.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); + //correct id not known + player->SEND_GOSSIP_MENU(10940, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+6: + //correct id not known + player->SEND_GOSSIP_MENU(10940, _Creature->GetGUID()); + _Creature->CastSpell(player,41121,false); + player->AreaExploredOrEventHappens(QUEST_11082); + break; + } + return true; +} + +/*###### +## npc_neltharaku +######*/ + +bool GossipHello_npc_neltharaku(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if (player->GetQuestStatus(10814) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM( 0, "I am listening, dragon", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + player->SEND_GOSSIP_MENU(10613, _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_neltharaku(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF+1: + player->ADD_GOSSIP_ITEM( 0, "But you are dragons! How could orcs do this to you?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + player->SEND_GOSSIP_MENU(10614, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + player->ADD_GOSSIP_ITEM( 0, "Your mate?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + player->SEND_GOSSIP_MENU(10615, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + player->ADD_GOSSIP_ITEM( 0, "I have battled many beasts, dragon. I will help you.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + player->SEND_GOSSIP_MENU(10616, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + player->CLOSE_GOSSIP_MENU(); + player->AreaExploredOrEventHappens(10814); + break; + } + return true; +} + +/*###### +## npc_oronok +######*/ + +#define GOSSIP_ORONOK1 "I am ready to hear your story, Oronok." +#define GOSSIP_ORONOK2 "How do I find the cipher?" +#define GOSSIP_ORONOK3 "How do you know all of this?" +#define GOSSIP_ORONOK4 "Yet what? What is it, Oronok?" +#define GOSSIP_ORONOK5 "Continue, please." +#define GOSSIP_ORONOK6 "So what of the cipher now? And your boys?" +#define GOSSIP_ORONOK7 "I will find your boys and the cipher, Oronok." + +bool GossipHello_npc_oronok_tornheart(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + if (_Creature->isVendor()) + player->ADD_GOSSIP_ITEM(1, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + + if (player->GetQuestStatus(10519) == QUEST_STATUS_INCOMPLETE) + { + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ORONOK1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + player->SEND_GOSSIP_MENU(10312, _Creature->GetGUID()); + }else + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_oronok_tornheart(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_TRADE: + player->SEND_VENDORLIST( _Creature->GetGUID() ); + break; + case GOSSIP_ACTION_INFO_DEF: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ORONOK2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + player->SEND_GOSSIP_MENU(10313, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+1: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ORONOK3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + player->SEND_GOSSIP_MENU(10314, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ORONOK4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + player->SEND_GOSSIP_MENU(10315, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ORONOK5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + player->SEND_GOSSIP_MENU(10316, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ORONOK6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + player->SEND_GOSSIP_MENU(10317, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ORONOK7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); + player->SEND_GOSSIP_MENU(10318, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+6: + player->CLOSE_GOSSIP_MENU(); + player->AreaExploredOrEventHappens(10519); + break; + } + return true; +} + +/*#### +# npc_karynaku +####*/ + +bool QuestAccept_npc_karynaku(Player* player, Creature* creature, Quest const* quest) +{ + if(quest->GetQuestId() == 10870) // Ally of the Netherwing + { + std::vector nodes; + + nodes.resize(2); + nodes[0] = 161; // From Karynaku + nodes[1] = 162; // To Mordenai + error_log("SD2: Player %s started quest 10870 which has disabled taxi node, need to be fixed in core", player->GetName()); + //player->ActivateTaxiPathTo(nodes, 20811); + } + + return true; +} + +void AddSC_shadowmoon_valley() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "mob_mature_netherwing_drake"; + newscript->GetAI = GetAI_mob_mature_netherwing_drake; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name = "mob_enslaved_netherwing_drake"; + newscript->GetAI = GetAI_mob_enslaved_netherwing_drake; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_drake_dealer_hurlunk"; + newscript->pGossipHello = &GossipHello_npc_drake_dealer_hurlunk; + newscript->pGossipSelect = &GossipSelect_npc_drake_dealer_hurlunk; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_invis_legion_teleporter"; + newscript->GetAI = GetAI_npc_invis_legion_teleporter; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npcs_flanis_swiftwing_and_kagrosh"; + newscript->pGossipHello = &GossipHello_npcs_flanis_swiftwing_and_kagrosh; + newscript->pGossipSelect = &GossipSelect_npcs_flanis_swiftwing_and_kagrosh; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_murkblood_overseer"; + newscript->pGossipHello = &GossipHello_npc_murkblood_overseer; + newscript->pGossipSelect = &GossipSelect_npc_murkblood_overseer; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_neltharaku"; + newscript->pGossipHello = &GossipHello_npc_neltharaku; + newscript->pGossipSelect = &GossipSelect_npc_neltharaku; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name = "npc_karynaku"; + newscript->pQuestAccept = &QuestAccept_npc_karynaku; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_oronok_tornheart"; + newscript->pGossipHello = &GossipHello_npc_oronok_tornheart; + newscript->pGossipSelect = &GossipSelect_npc_oronok_tornheart; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/shattrath/shattrath_city.cpp b/src/bindings/scripts/scripts/zone/shattrath/shattrath_city.cpp new file mode 100644 index 00000000000..8ad5a6e6321 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/shattrath/shattrath_city.cpp @@ -0,0 +1,268 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Shattrath_City +SD%Complete: 100 +SDComment: Quest support: 10004, 10009. Flask vendors, Teleport to Caverns of Time +SDCategory: Shattrath City +EndScriptData */ + +/* ContentData +npc_raliq_the_drunk +npc_salsalabim +npc_shattrathflaskvendors +npc_zephyr +EndContentData */ + +#include "precompiled.h" + +/*###### +## npc_raliq_the_drunk +######*/ + +#define GOSSIP_RALIQ "You owe Sim'salabim money. Hand them over or die!" + +#define FACTION_HOSTILE_RD 45 +#define FACTION_FRIENDLY_RD 35 + +#define SPELL_UPPERCUT 10966 + +struct MANGOS_DLL_DECL npc_raliq_the_drunkAI : public ScriptedAI +{ + npc_raliq_the_drunkAI(Creature* c) : ScriptedAI(c) { Reset(); } + + uint32 Uppercut_Timer; + + void Reset() + { + Uppercut_Timer = 5000; + m_creature->setFaction(FACTION_FRIENDLY_RD); + } + + void Aggro(Unit *who) {} + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if( Uppercut_Timer < diff ) + { + DoCast(m_creature->getVictim(),SPELL_UPPERCUT); + Uppercut_Timer = 15000; + }else Uppercut_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_npc_raliq_the_drunk(Creature *_Creature) +{ + return new npc_raliq_the_drunkAI (_Creature); +} + +bool GossipHello_npc_raliq_the_drunk(Player *player, Creature *_Creature ) +{ + if( player->GetQuestStatus(10009) == QUEST_STATUS_INCOMPLETE ) + player->ADD_GOSSIP_ITEM(1, GOSSIP_RALIQ, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + player->SEND_GOSSIP_MENU(9440, _Creature->GetGUID()); + return true; +} + +bool GossipSelect_npc_raliq_the_drunk(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if( action == GOSSIP_ACTION_INFO_DEF+1 ) + { + player->CLOSE_GOSSIP_MENU(); + _Creature->setFaction(FACTION_HOSTILE_RD); + ((npc_raliq_the_drunkAI*)_Creature->AI())->AttackStart(player); + } + return true; +} + +/*###### +# npc_salsalabim +######*/ + +#define FACTION_HOSTILE_SA 90 +#define FACTION_FRIENDLY_SA 35 +#define QUEST_10004 10004 + +#define SPELL_MAGNETIC_PULL 31705 + +struct MANGOS_DLL_DECL npc_salsalabimAI : public ScriptedAI +{ + npc_salsalabimAI(Creature* c) : ScriptedAI(c) { Reset(); } + + uint32 MagneticPull_Timer; + + void Reset() + { + MagneticPull_Timer = 15000; + m_creature->setFaction(FACTION_FRIENDLY_SA); + } + + void Aggro(Unit *who) {} + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if( done_by->GetTypeId() == TYPEID_PLAYER ) + if( (m_creature->GetHealth()-damage)*100 / m_creature->GetMaxHealth() < 20 ) + { + ((Player*)done_by)->GroupEventHappens(QUEST_10004,m_creature); + damage = 0; + EnterEvadeMode(); + } + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if( MagneticPull_Timer < diff ) + { + DoCast(m_creature->getVictim(),SPELL_MAGNETIC_PULL); + MagneticPull_Timer = 15000; + }else MagneticPull_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_npc_salsalabim(Creature *_Creature) +{ + return new npc_salsalabimAI (_Creature); +} + +bool GossipHello_npc_salsalabim(Player *player, Creature *_Creature) +{ + if( player->GetQuestStatus(QUEST_10004) == QUEST_STATUS_INCOMPLETE ) + { + _Creature->setFaction(FACTION_HOSTILE_SA); + ((npc_salsalabimAI*)_Creature->AI())->AttackStart(player); + } + else + { + if( _Creature->isQuestGiver() ) + player->PrepareQuestMenu( _Creature->GetGUID() ); + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + } + return true; +} + +/* +################################################## +Shattrath City Flask Vendors provides flasks to people exalted with 3 factions: +Haldor the Compulsive +Arcanist Xorith +Both sell special flasks for use in Outlands 25man raids only, +purchasable for one Mark of Illidari each +Purchase requires exalted reputation with Scryers/Aldor, Cenarion Expedition and The Sha'tar +################################################## +*/ + +bool GossipHello_npc_shattrathflaskvendors(Player *player, Creature *_Creature) +{ + if(_Creature->GetEntry() == 23484) + { + // Aldor vendor + if( _Creature->isVendor() && (player->GetReputationRank(932) == REP_EXALTED) && (player->GetReputationRank(935) == REP_EXALTED) && (player->GetReputationRank(942) == REP_EXALTED) ) + { + player->ADD_GOSSIP_ITEM(1, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + player->SEND_GOSSIP_MENU(11085, _Creature->GetGUID()); + } + else + { + player->SEND_GOSSIP_MENU(11083, _Creature->GetGUID()); + } + } + + if(_Creature->GetEntry() == 23483) + { + // Scryers vendor + if( _Creature->isVendor() && (player->GetReputationRank(934) == REP_EXALTED) && (player->GetReputationRank(935) == REP_EXALTED) && (player->GetReputationRank(942) == REP_EXALTED) ) + { + player->ADD_GOSSIP_ITEM(1, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + player->SEND_GOSSIP_MENU(11085, _Creature->GetGUID()); + } + else + { + player->SEND_GOSSIP_MENU(11084, _Creature->GetGUID()); + } + } + + return true; +} + +bool GossipSelect_npc_shattrathflaskvendors(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + if( action == GOSSIP_ACTION_TRADE ) + player->SEND_VENDORLIST( _Creature->GetGUID() ); + + return true; +} + +/*###### +# npc_zephyr +######*/ + +bool GossipHello_npc_zephyr(Player *player, Creature *_Creature) +{ + if( player->GetReputationRank(989) >= REP_REVERED ) + player->ADD_GOSSIP_ITEM(0, "Take me to the Caverns of Time.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_zephyr(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + if( action == GOSSIP_ACTION_INFO_DEF+1 ) + player->CastSpell(player,37778,false); + + return true; +} + +void AddSC_shattrath_city() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npc_raliq_the_drunk"; + newscript->pGossipHello = &GossipHello_npc_raliq_the_drunk; + newscript->pGossipSelect = &GossipSelect_npc_raliq_the_drunk; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_salsalabim"; + newscript->GetAI = GetAI_npc_salsalabim; + newscript->pGossipHello = &GossipHello_npc_salsalabim; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_shattrathflaskvendors"; + newscript->pGossipHello = &GossipHello_npc_shattrathflaskvendors; + newscript->pGossipSelect = &GossipSelect_npc_shattrathflaskvendors; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_zephyr"; + newscript->pGossipHello = &GossipHello_npc_zephyr; + newscript->pGossipSelect = &GossipSelect_npc_zephyr; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/silithus/silithus.cpp b/src/bindings/scripts/scripts/zone/silithus/silithus.cpp new file mode 100644 index 00000000000..8b7681d0557 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/silithus/silithus.cpp @@ -0,0 +1,149 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Silithus +SD%Complete: 100 +SDComment: Quest support: 8304. +SDCategory: Silithus +EndScriptData */ + +/* ContentData +npcs_rutgar_and_frankal +EndContentData */ + +#include "precompiled.h" + +/*### +## npcs_rutgar_and_frankal +###*/ + +//gossip item text best guess +#define GOSSIP_ITEM1 "I seek information about Natalia" + +#define GOSSIP_ITEM2 "That sounds dangerous!" +#define GOSSIP_ITEM3 "What did you do?" +#define GOSSIP_ITEM4 "Who?" +#define GOSSIP_ITEM5 "Women do that. What did she demand?" +#define GOSSIP_ITEM6 "What do you mean?" +#define GOSSIP_ITEM7 "What happened next?" + +#define GOSSIP_ITEM11 "Yes, please continue" +#define GOSSIP_ITEM12 "What language?" +#define GOSSIP_ITEM13 "The Priestess attacked you?!" +#define GOSSIP_ITEM14 "I should ask the monkey about this" +#define GOSSIP_ITEM15 "Then what..." + +//trigger creatures to kill +#define TRIGGER_RUTGAR 15222 +#define TRIGGER_FRANKAL 15221 + +bool GossipHello_npcs_rutgar_and_frankal(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if (player->GetQuestStatus(8304) == QUEST_STATUS_INCOMPLETE && + _Creature->GetEntry() == 15170 && + !player->GetReqKillOrCastCurrentCount(8304, TRIGGER_RUTGAR )) + player->ADD_GOSSIP_ITEM(0, GOSSIP_ITEM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + if (player->GetQuestStatus(8304) == QUEST_STATUS_INCOMPLETE && + _Creature->GetEntry() == 15171 && + player->GetReqKillOrCastCurrentCount(8304, TRIGGER_RUTGAR )) + player->ADD_GOSSIP_ITEM(0, GOSSIP_ITEM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+9); + + player->SEND_GOSSIP_MENU(7754, _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npcs_rutgar_and_frankal(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->SEND_GOSSIP_MENU(7755, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 1: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->SEND_GOSSIP_MENU(7756, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->SEND_GOSSIP_MENU(7757, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->SEND_GOSSIP_MENU(7758, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->SEND_GOSSIP_MENU(7759, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->SEND_GOSSIP_MENU(7760, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: + player->SEND_GOSSIP_MENU(7761, _Creature->GetGUID()); + //'kill' our trigger to update quest status + player->KilledMonster( TRIGGER_RUTGAR, _Creature->GetGUID() ); + break; + + case GOSSIP_ACTION_INFO_DEF + 9: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM11, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->SEND_GOSSIP_MENU(7762, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 10: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM12, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->SEND_GOSSIP_MENU(7763, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 11: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM13, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 12); + player->SEND_GOSSIP_MENU(7764, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 12: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM14, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 13); + player->SEND_GOSSIP_MENU(7765, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 13: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM15, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 14); + player->SEND_GOSSIP_MENU(7766, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 14: + player->SEND_GOSSIP_MENU(7767, _Creature->GetGUID()); + //'kill' our trigger to update quest status + player->KilledMonster( TRIGGER_FRANKAL, _Creature->GetGUID() ); + break; + } + return true; +} + +/*### +## +####*/ + +void AddSC_silithus() +{ + Script *newscript; + newscript = new Script; + newscript->Name="npcs_rutgar_and_frankal"; + newscript->pGossipHello = &GossipHello_npcs_rutgar_and_frankal; + newscript->pGossipSelect = &GossipSelect_npcs_rutgar_and_frankal; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/silvermoon/silvermoon_city.cpp b/src/bindings/scripts/scripts/zone/silvermoon/silvermoon_city.cpp new file mode 100644 index 00000000000..1a237eefde0 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/silvermoon/silvermoon_city.cpp @@ -0,0 +1,103 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Silvermoon_City +SD%Complete: 100 +SDComment: Quest support: 9685 +SDCategory: Silvermoon City +EndScriptData */ + +/* ContentData +npc_blood_knight_stillblade +EndContentData */ + +#include "precompiled.h" + +/*####### +# npc_blood_knight_stillblade +#######*/ + +#define SAY_HEAL "Thank you, dear Paladin, you just saved my life." + +#define QUEST_REDEEMING_THE_DEAD 9685 +#define SPELL_SHIMMERING_VESSEL 31225 +#define SPELL_REVIVE_SELF 32343 + +struct MANGOS_DLL_DECL npc_blood_knight_stillbladeAI : public ScriptedAI +{ + npc_blood_knight_stillbladeAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 lifeTimer; + bool spellHit; + + void Reset() + { + lifeTimer = 120000; + m_creature->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 32); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1,7); // lay down + spellHit = false; + } + + void Aggro(Unit *who) + { + } + + void MoveInLineOfSight(Unit *who) + { + return; + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->GetUInt32Value(UNIT_FIELD_BYTES_1)) + { + if(lifeTimer < diff) + m_creature->AI()->EnterEvadeMode(); + else + lifeTimer -= diff; + } + } + + void SpellHit(Unit *Hitter, const SpellEntry *Spellkind) + { + if((Spellkind->Id == SPELL_SHIMMERING_VESSEL) && !spellHit && + (Hitter->GetTypeId() == TYPEID_PLAYER) && (((Player*)Hitter)->IsActiveQuest(QUEST_REDEEMING_THE_DEAD))) + { + ((Player*)Hitter)->AreaExploredOrEventHappens(QUEST_REDEEMING_THE_DEAD); + DoCast(m_creature,SPELL_REVIVE_SELF); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1,0); + m_creature->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0); + //m_creature->RemoveAllAuras(); + DoSay(SAY_HEAL,LANG_COMMON,NULL); + spellHit = true; + } + } +}; + +CreatureAI* GetAI_npc_blood_knight_stillblade(Creature *_Creature) +{ + return new npc_blood_knight_stillbladeAI (_Creature); +} + +void AddSC_silvermoon_city() +{ + Script *newscript; + newscript = new Script; + newscript->Name="npc_blood_knight_stillblade"; + newscript->GetAI = GetAI_npc_blood_knight_stillblade; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/silverpine_forest/silverpine_forest.cpp b/src/bindings/scripts/scripts/zone/silverpine_forest/silverpine_forest.cpp new file mode 100644 index 00000000000..87c346d58b4 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/silverpine_forest/silverpine_forest.cpp @@ -0,0 +1,100 @@ +/* Copyright (C) 2006,2007 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Silverpine_Forest +SD%Complete: 100 +SDComment: Quest support: 1886 +SDCategory: Silverpine Forest +EndScriptData */ + +/* ContentData +npc_astor_hadren +EndContentData */ + +#include "precompiled.h" + +/*###### +## npc_astor_hadren +######*/ + +struct MANGOS_DLL_DECL npc_astor_hadrenAI : public ScriptedAI +{ + npc_astor_hadrenAI(Creature *c) : ScriptedAI(c) {Reset();} + + void Reset() + { + m_creature->setFaction(68); + } + + void Aggro(Unit* who) + { + } + + void JustDied(Unit *who) + { + m_creature->setFaction(68); + } +}; + +CreatureAI* GetAI_npc_astor_hadren(Creature *_creature) +{ + return new npc_astor_hadrenAI(_creature); +} + +bool GossipHello_npc_astor_hadren(Player *player, Creature *_Creature) +{ + if (player->GetQuestStatus(1886) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM( 0, "You're Astor Hadren, right?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + + player->SEND_GOSSIP_MENU(623, _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_astor_hadren(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF + 1: + player->ADD_GOSSIP_ITEM( 0, "You've got something I need, Astor. And I'll be taking it now.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->SEND_GOSSIP_MENU(624, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + player->CLOSE_GOSSIP_MENU(); + _Creature->setFaction(21); + if(player) + ((npc_astor_hadrenAI*)_Creature->AI())->AttackStart(player); + break; + } + return true; +} + +/*###### +## AddSC +######*/ + +void AddSC_silverpine_forest() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npc_astor_hadren"; + newscript->pGossipHello = &GossipHello_npc_astor_hadren; + newscript->pGossipSelect = &GossipSelect_npc_astor_hadren; + newscript->GetAI = GetAI_npc_astor_hadren; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/stonetalon_mountains/stonetalon_mountains.cpp b/src/bindings/scripts/scripts/zone/stonetalon_mountains/stonetalon_mountains.cpp new file mode 100644 index 00000000000..652af2fe802 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/stonetalon_mountains/stonetalon_mountains.cpp @@ -0,0 +1,80 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Stonetalon_Mountains +SD%Complete: 95 +SDComment: Quest support: 6627 (Braug Dimspirits questions/'answers' might have more to it, need more info) +SDCategory: Stonetalon Mountains +EndScriptData */ + +#include "precompiled.h" + +/*###### +## npc_braug_dimspirit +######*/ + +bool GossipHello_npc_braug_dimspirit(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if (player->GetQuestStatus(6627) == QUEST_STATUS_INCOMPLETE) + { + player->ADD_GOSSIP_ITEM( 0, "Ysera", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + player->ADD_GOSSIP_ITEM( 0, "Neltharion", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + player->ADD_GOSSIP_ITEM( 0, "Nozdormu", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + player->ADD_GOSSIP_ITEM( 0, "Alexstrasza", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + player->ADD_GOSSIP_ITEM( 0, "Malygos", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + player->SEND_GOSSIP_MENU(5820, _Creature->GetGUID()); + } + else + player->SEND_GOSSIP_MENU(5819, _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_braug_dimspirit(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + if (action == GOSSIP_ACTION_INFO_DEF+1) + { + player->CLOSE_GOSSIP_MENU(); + _Creature->CastSpell(player,6766,false); + + } + if (action == GOSSIP_ACTION_INFO_DEF+2) + { + player->CLOSE_GOSSIP_MENU(); + player->AreaExploredOrEventHappens(6627); + } + return true; +} + +/*###### +## AddSC +######*/ + +void AddSC_stonetalon_mountains() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npc_braug_dimspirit"; + newscript->pGossipHello = &GossipHello_npc_braug_dimspirit; + newscript->pGossipSelect = &GossipSelect_npc_braug_dimspirit; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/stormwind/stormwind_city.cpp b/src/bindings/scripts/scripts/zone/stormwind/stormwind_city.cpp new file mode 100644 index 00000000000..0821a424cc4 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/stormwind/stormwind_city.cpp @@ -0,0 +1,272 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Stormwind_City +SD%Complete: 100 +SDComment: Quest support: 1640, 1447, 4185, 11223 (DB support required for spell 42711). Receive emote General Marcus +SDCategory: Stormwind City +EndScriptData */ + +/* ContentData +npc_archmage_malin +npc_bartleby +npc_dashel_stonefist +npc_general_marcus_jonathan +npc_lady_katrana_prestor +EndContentData */ + +#include "precompiled.h" + +/*###### +## npc_archmage_malin +######*/ + +#define GOSSIP_ITEM_MALIN "Can you send me to Theramore? I have an urgent message for Lady Jaina from Highlord Bolvar." + +bool GossipHello_npc_archmage_malin(Player *player, Creature *_Creature) +{ + if(_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if(player->GetQuestStatus(11223) == QUEST_STATUS_COMPLETE && !player->GetQuestRewardStatus(11223)) + player->ADD_GOSSIP_ITEM(0, GOSSIP_ITEM_MALIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_archmage_malin(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + if(action = GOSSIP_ACTION_INFO_DEF) + { + player->CLOSE_GOSSIP_MENU(); + _Creature->CastSpell(player, 42711, true); + } + + return true; +} + +/*###### +## npc_bartleby +######*/ + +struct MANGOS_DLL_DECL npc_bartlebyAI : public ScriptedAI +{ + npc_bartlebyAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint64 PlayerGUID; + + void Reset() + { + m_creature->setFaction(11); + m_creature->setEmoteState(7); + + PlayerGUID = 0; + } + + void JustDied(Unit *who) + { + m_creature->setFaction(11); + } + + void DamageTaken(Unit *done_by, uint32 & damage) + { + if(damage > m_creature->GetHealth() || ((m_creature->GetHealth() - damage)*100 / m_creature->GetMaxHealth() < 15)) + { + //Take 0 damage + damage = 0; + + if (done_by->GetTypeId() == TYPEID_PLAYER && done_by->GetGUID() == PlayerGUID) + { + ((Player*)done_by)->AttackStop(); + ((Player*)done_by)->AreaExploredOrEventHappens(1640); + } + m_creature->CombatStop(); + EnterEvadeMode(); + } + } + + void Aggro(Unit *who) {} +}; + +bool QuestAccept_npc_bartleby(Player *player, Creature *_Creature, Quest const *_Quest) +{ + if(_Quest->GetQuestId() == 1640) + { + _Creature->setFaction(168); + ((npc_bartlebyAI*)_Creature->AI())->PlayerGUID = player->GetGUID(); + ((npc_bartlebyAI*)_Creature->AI())->AttackStart(player); + } + return true; +} + +CreatureAI* GetAI_npc_bartleby(Creature *_creature) +{ + return new npc_bartlebyAI(_creature); +} + +/*###### +## npc_dashel_stonefist +######*/ + +struct MANGOS_DLL_DECL npc_dashel_stonefistAI : public ScriptedAI +{ + npc_dashel_stonefistAI(Creature *c) : ScriptedAI(c) {Reset();} + + void Reset() + { + m_creature->setFaction(11); + m_creature->setEmoteState(7); + } + + void DamageTaken(Unit *done_by, uint32 & damage) + { + if((damage > m_creature->GetHealth()) || (m_creature->GetHealth() - damage)*100 / m_creature->GetMaxHealth() < 15) + { + //Take 0 damage + damage = 0; + + if (done_by->GetTypeId() == TYPEID_PLAYER) + { + ((Player*)done_by)->AttackStop(); + ((Player*)done_by)->AreaExploredOrEventHappens(1447); + } + //m_creature->CombatStop(); + EnterEvadeMode(); + } + AttackedBy(done_by); + } + + void Aggro(Unit *who) {} +}; + +bool QuestAccept_npc_dashel_stonefist(Player *player, Creature *_Creature, Quest const *_Quest) +{ + if(_Quest->GetQuestId() == 1447) + { + _Creature->setFaction(168); + ((npc_dashel_stonefistAI*)_Creature->AI())->AttackStart(player); + } + return true; +} + +CreatureAI* GetAI_npc_dashel_stonefist(Creature *_creature) +{ + return new npc_dashel_stonefistAI(_creature); +} + +/*###### +## npc_general_marcus_jonathan +######*/ + +bool ReceiveEmote_npc_general_marcus_jonathan(Player *player, Creature *_Creature, uint32 emote) +{ + if(player->GetTeam() == ALLIANCE) + { + if (emote == TEXTEMOTE_SALUTE) + { + _Creature->SetOrientation(_Creature->GetAngle(player)); + _Creature->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE); + } + if (emote == TEXTEMOTE_WAVE) + { + _Creature->MonsterSay("Greetings citizen",LANG_COMMON,0); + } + } + return true; +} + +/*###### +## npc_lady_katrana_prestor +######*/ + +#define GOSSIP_ITEM_KAT_1 "Pardon the intrusion, Lady Prestor, but Highlord Bolvar suggested that I seek your advice." +#define GOSSIP_ITEM_KAT_2 "My apologies, Lady Prestor." +#define GOSSIP_ITEM_KAT_3 "Begging your pardon, Lady Prestor. That was not my intent." +#define GOSSIP_ITEM_KAT_4 "Thank you for your time, Lady Prestor." + +bool GossipHello_npc_lady_katrana_prestor(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if (player->GetQuestStatus(4185) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_KAT_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + player->SEND_GOSSIP_MENU(2693, _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_lady_katrana_prestor(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_KAT_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->SEND_GOSSIP_MENU(2694, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+1: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_KAT_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->SEND_GOSSIP_MENU(2695, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_KAT_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->SEND_GOSSIP_MENU(2696, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + player->CLOSE_GOSSIP_MENU(); + player->AreaExploredOrEventHappens(4185); + break; + } + return true; +} + +void AddSC_stormwind_city() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npc_archmage_malin"; + newscript->pGossipHello = &GossipHello_npc_archmage_malin; + newscript->pGossipSelect = &GossipSelect_npc_archmage_malin; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name = "npc_bartleby"; + newscript->GetAI = GetAI_npc_bartleby; + newscript->pQuestAccept = &QuestAccept_npc_bartleby; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name = "npc_dashel_stonefist"; + newscript->GetAI = GetAI_npc_dashel_stonefist; + newscript->pQuestAccept = &QuestAccept_npc_dashel_stonefist; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name = "npc_general_marcus_jonathan"; + newscript->pReceiveEmote = &ReceiveEmote_npc_general_marcus_jonathan; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_lady_katrana_prestor"; + newscript->pGossipHello = &GossipHello_npc_lady_katrana_prestor; + newscript->pGossipSelect = &GossipSelect_npc_lady_katrana_prestor; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/stranglethorn_vale/stranglethorn_vale.cpp b/src/bindings/scripts/scripts/zone/stranglethorn_vale/stranglethorn_vale.cpp new file mode 100644 index 00000000000..35fda2c6f1c --- /dev/null +++ b/src/bindings/scripts/scripts/zone/stranglethorn_vale/stranglethorn_vale.cpp @@ -0,0 +1,107 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Stranglethorn_Vale +SD%Complete: 100 +SDComment: Quest support: 592 +SDCategory: Stranglethorn Vale +EndScriptData */ + +/* ContentData +mob_yenniku +EndContentData */ + +#include "precompiled.h" + +/*###### +## mob_yenniku +######*/ + +struct MANGOS_DLL_DECL mob_yennikuAI : public ScriptedAI +{ + mob_yennikuAI(Creature *c) : ScriptedAI(c) + { + bReset = false; + Reset(); + } + + uint32 Reset_Timer; + bool bReset; + + void Reset() + { + Reset_Timer = 0; + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); + } + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if (caster->GetTypeId() == TYPEID_PLAYER) + { + //Yenniku's Release + if(!bReset && ((Player*)caster)->GetQuestStatus(592) == QUEST_STATUS_INCOMPLETE && spell->Id == 3607) + { + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_STUN); + m_creature->CombatStop(); //stop combat + m_creature->DeleteThreatList(); //unsure of this + m_creature->setFaction(83); //horde generic + + bReset = true; + Reset_Timer = 60000; + } + } + return; + } + + void Aggro(Unit *who) {} + + void UpdateAI(const uint32 diff) + { + if (bReset) + if(Reset_Timer < diff) + { + EnterEvadeMode(); + bReset = false; + m_creature->setFaction(28); //troll, bloodscalp + } + else Reset_Timer -= diff; + + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_mob_yenniku(Creature *_Creature) +{ + return new mob_yennikuAI (_Creature); +} + +/*###### +## +######*/ + +void AddSC_stranglethorn_vale() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "mob_yenniku"; + newscript->GetAI = GetAI_mob_yenniku; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/stratholme/boss_baron_rivendare.cpp b/src/bindings/scripts/scripts/zone/stratholme/boss_baron_rivendare.cpp new file mode 100644 index 00000000000..6355588e7b8 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/stratholme/boss_baron_rivendare.cpp @@ -0,0 +1,215 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: boss_baron_rivendare +SD%Complete: 100 +SDComment: aura applied/defined in database +SDCategory: Stratholme +EndScriptData */ + +#include "precompiled.h" + +#define SAY_0 "Intruders! More pawns of the Argent Dawn, no doubt. I already count one of their number among my prisoners. Withdraw from my domain before she is executed!" +#define SAY_1 "You're still here? Your foolishness is amusing! The Argent Dawn wench needn't suffer in vain. Leave at once and she shall be spared!" +#define SAY_2 "I shall take great pleasure in taking this poor wretch's life! It's not too late, she needn't suffer in vain. Turn back and her death shall be merciful!" +#define SAY_3 "May this prisoner's death serve as a warning. None shall defy the Scourge and live!" +#define SAY_4 "So you see fit to toy with the Lich King's creations? Ramstein, be sure to give the intruders a proper greeting." +#define SAY_5 "Time to take matters into my own hands. Come. Enter my domain and challenge the might of the Scourge!" + +#define ADD_1X 4017.403809 +#define ADD_1Y -3339.703369 +#define ADD_1Z 115.057655 +#define ADD_1O 5.487860 + +#define ADD_2X 4013.189209 +#define ADD_2Y -3351.808350 +#define ADD_2Z 115.052254 +#define ADD_2O 0.134280 + +#define ADD_3X 4017.738037 +#define ADD_3Y -3363.478016 +#define ADD_3Z 115.057274 +#define ADD_3O 0.723313 + +#define ADD_4X 4048.877197 +#define ADD_4Y -3363.223633 +#define ADD_4Z 115.054253 +#define ADD_4O 3.627735 + +#define ADD_5X 4051.777588 +#define ADD_5Y -3350.893311 +#define ADD_5Z 115.055351 +#define ADD_5O 3.066176 + +#define ADD_6X 4048.375977 +#define ADD_6Y -3339.966309 +#define ADD_6Z 115.055222 +#define ADD_6O 2.457497 + +#define SPELL_SHADOWBOLT 18164 +#define SPELL_CLEAVE 15584 +#define SPELL_MORTALSTRIKE 13737 + +// spell 17473 should trigger -> 17471 + +//#define SPELL_RAISEDEAD 17475 +//#define SPELL_DEATHPACT 17698 +//#define SPELL_SUMMONSKELETONS 17274 + +struct MANGOS_DLL_DECL boss_baron_rivendareAI : public ScriptedAI +{ + boss_baron_rivendareAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 ShadowBolt_Timer; + uint32 Cleave_Timer; + uint32 MortalStrike_Timer; + // uint32 RaiseDead_Timer; + uint32 SummonSkeletons_Timer; + Creature *Summoned; + + void Reset() + { + ShadowBolt_Timer = 5000; + Cleave_Timer = 8000; + MortalStrike_Timer = 12000; + // RaiseDead_Timer = 30000; + SummonSkeletons_Timer = 34000; + + m_creature->LoadCreaturesAddon(); + } + + void Aggro(Unit *who) + { + switch (rand()%6) + { + case 0: + DoYell(SAY_0,LANG_UNIVERSAL,NULL); + break; + case 1: + DoYell(SAY_1,LANG_UNIVERSAL,NULL); + break; + case 2: + DoYell(SAY_2,LANG_UNIVERSAL,NULL); + break; + case 3: + DoYell(SAY_3,LANG_UNIVERSAL,NULL); + break; + case 4: + DoYell(SAY_4,LANG_UNIVERSAL,NULL); + break; + case 5: + DoYell(SAY_5,LANG_UNIVERSAL,NULL); + break; + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //ShadowBolt + if (ShadowBolt_Timer < diff) + { + //Cast + if (rand()%100 < 70) //70% chance to cast + { + DoCast(m_creature->getVictim(),SPELL_SHADOWBOLT); + } + //10 seconds until we should cast this again + ShadowBolt_Timer = 10000; + }else ShadowBolt_Timer -= diff; + + //Cleave + if (Cleave_Timer < diff) + { + //Cast + if (rand()%100 < 55) //55% chance to cast + { + DoCast(m_creature->getVictim(),SPELL_CLEAVE); + } + //13 seconds until we should cast this again + Cleave_Timer = 12000; + }else Cleave_Timer -= diff; + + //MortalStrike + if (MortalStrike_Timer < diff) + { + //Cast + if (rand()%100 < 30) //30% chance to cast + { + DoCast(m_creature->getVictim(),SPELL_MORTALSTRIKE); + } + //16 seconds until we should cast this again + MortalStrike_Timer = 16000; + }else MortalStrike_Timer -= diff; + + //RaiseDead + // if (RaiseDead_Timer < diff) + // { + //Cast + // DoCast(m_creature,SPELL_RAISEDEAD); + // DoSay("summon triggered",LANG_UNIVERSAL,NULL); //just a checkpoint + //45 seconds until we should cast this again + // RaiseDead_Timer = 45000; + // }else RaiseDead_Timer -= diff; + + //SummonSkeletons + //Creature* Unit::SummonCreature(uint32 id, float x, float y, float z, float ang,TempSummonType spwtype,uint32 despwtime); + + if (SummonSkeletons_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + + //Cast + Summoned = m_creature->SummonCreature(11197,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,29000); + ((CreatureAI*)Summoned->AI())->AttackStart(target); + Summoned = m_creature->SummonCreature(11197,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,29000); + ((CreatureAI*)Summoned->AI())->AttackStart(target); + Summoned = m_creature->SummonCreature(11197,ADD_3X,ADD_3Y,ADD_3Z,ADD_3O,TEMPSUMMON_TIMED_DESPAWN,29000); + ((CreatureAI*)Summoned->AI())->AttackStart(target); + Summoned = m_creature->SummonCreature(11197,ADD_4X,ADD_4Y,ADD_4Z,ADD_4O,TEMPSUMMON_TIMED_DESPAWN,29000); + ((CreatureAI*)Summoned->AI())->AttackStart(target); + Summoned = m_creature->SummonCreature(11197,ADD_5X,ADD_5Y,ADD_5Z,ADD_5O,TEMPSUMMON_TIMED_DESPAWN,29000); + ((CreatureAI*)Summoned->AI())->AttackStart(target); + Summoned = m_creature->SummonCreature(11197,ADD_6X,ADD_6Y,ADD_6Z,ADD_6O,TEMPSUMMON_TIMED_DESPAWN,29000); + ((CreatureAI*)Summoned->AI())->AttackStart(target); + + //34 seconds until we should cast this again + SummonSkeletons_Timer = 40000; + }else SummonSkeletons_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_baron_rivendare(Creature *_Creature) +{ + return new boss_baron_rivendareAI (_Creature); +} + + +void AddSC_boss_baron_rivendare() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_baron_rivendare"; + newscript->GetAI = GetAI_boss_baron_rivendare; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/stratholme/boss_baroness_anastari.cpp b/src/bindings/scripts/scripts/zone/stratholme/boss_baroness_anastari.cpp new file mode 100644 index 00000000000..79284eb5a26 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/stratholme/boss_baroness_anastari.cpp @@ -0,0 +1,124 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: boss_baroness_anastari +SD%Complete: 90 +SDComment: MC disabled +SDCategory: Stratholme +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_BANSHEEWAIL 16565 +#define SPELL_BANSHEECURSE 16867 +#define SPELL_SILENCE 18327 +//#define SPELL_POSSESS 17244 + +struct MANGOS_DLL_DECL boss_baroness_anastariAI : public ScriptedAI +{ + boss_baroness_anastariAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 BansheeWail_Timer; + uint32 BansheeCurse_Timer; + uint32 Silence_Timer; + //uint32 Possess_Timer; + + void Reset() + { + BansheeWail_Timer = 1000; + BansheeCurse_Timer = 11000; + Silence_Timer = 13000; + //Possess_Timer = 35000; + } + + void Aggro(Unit *who) + { + } + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //BansheeWail + if (BansheeWail_Timer < diff) + { + //Cast + if (rand()%100 < 95) //95% chance to cast + { + DoCast(m_creature->getVictim(),SPELL_BANSHEEWAIL); + } + //4 seconds until we should cast this again + BansheeWail_Timer = 4000; + }else BansheeWail_Timer -= diff; + + //BansheeCurse + if (BansheeCurse_Timer < diff) + { + //Cast + if (rand()%100 < 75) //75% chance to cast + { + DoCast(m_creature->getVictim(),SPELL_BANSHEECURSE); + } + //18 seconds until we should cast this again + BansheeCurse_Timer = 18000; + }else BansheeCurse_Timer -= diff; + + //Silence + if (Silence_Timer < diff) + { + //Cast + if (rand()%100 < 80) //80% chance to cast + { + DoCast(m_creature->getVictim(),SPELL_SILENCE); + } + //13 seconds until we should cast this again + Silence_Timer = 13000; + }else Silence_Timer -= diff; + + //Possess + /* if (Possess_Timer < diff) + { + //Cast + if (rand()%100 < 65) //65% chance to cast + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target)DoCast(target,SPELL_POSSESS); + } + //50 seconds until we should cast this again + Possess_Timer = 50000; + }else Possess_Timer -= diff; + */ + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_baroness_anastari(Creature *_Creature) +{ + return new boss_baroness_anastariAI (_Creature); +} + + +void AddSC_boss_baroness_anastari() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_baroness_anastari"; + newscript->GetAI = GetAI_boss_baroness_anastari; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/stratholme/boss_cannon_master_willey.cpp b/src/bindings/scripts/scripts/zone/stratholme/boss_cannon_master_willey.cpp new file mode 100644 index 00000000000..91d4b4fd397 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/stratholme/boss_cannon_master_willey.cpp @@ -0,0 +1,221 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: boss_cannon_master_willey +SD%Complete: 100 +SDComment: +SDCategory: Stratholme +EndScriptData */ + +#include "precompiled.h" + +//front, left +#define ADD_1X 3553.851807 +#define ADD_1Y -2945.885986 +#define ADD_1Z 125.001015 +#define ADD_1O 0.592007 +//front, right +#define ADD_2X 3559.206299 +#define ADD_2Y -2952.929932 +#define ADD_2Z 125.001015 +#define ADD_2O 0.592007 +//mid, left +#define ADD_3X 3552.417480 +#define ADD_3Y -2948.667236 +#define ADD_3Z 125.001015 +#define ADD_3O 0.592007 +//mid, right +#define ADD_4X 3555.651855 +#define ADD_4Y -2953.519043 +#define ADD_4Z 125.001015 +#define ADD_4O 0.592007 +//back, left +#define ADD_5X 3547.927246 +#define ADD_5Y -2950.977295 +#define ADD_5Z 125.001015 +#define ADD_5O 0.592007 +//back, mid +#define ADD_6X 3553.094697 +#define ADD_6Y -2952.123291 +#define ADD_6Z 125.001015 +#define ADD_6O 0.592007 +//back, right +#define ADD_7X 3552.727539 +#define ADD_7Y -2957.776123 +#define ADD_7Z 125.001015 +#define ADD_7O 0.592007 +//behind, left +#define ADD_8X 3547.156250 +#define ADD_8Y -2953.162354 +#define ADD_8Z 125.001015 +#define ADD_8O 0.592007 +//behind, right +#define ADD_9X 3550.202148 +#define ADD_9Y -2957.437744 +#define ADD_9Z 125.001015 +#define ADD_9O 0.592007 + +#define SPELL_KNOCKAWAY 10101 +#define SPELL_PUMMEL 15615 +#define SPELL_SHOOT 20463 +//#define SPELL_SUMMONCRIMSONRIFLEMAN 17279 + +struct MANGOS_DLL_DECL boss_cannon_master_willeyAI : public ScriptedAI +{ + boss_cannon_master_willeyAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 KnockAway_Timer; + uint32 Pummel_Timer; + uint32 Shoot_Timer; + uint32 SummonRifleman_Timer; + + void Reset() + { + Shoot_Timer = 1000; + Pummel_Timer = 7000; + KnockAway_Timer = 11000; + SummonRifleman_Timer = 15000; + } + + void JustDied(Unit* Victim) + { + m_creature->SummonCreature(11054,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,240000); + m_creature->SummonCreature(11054,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,240000); + m_creature->SummonCreature(11054,ADD_3X,ADD_3Y,ADD_3Z,ADD_3O,TEMPSUMMON_TIMED_DESPAWN,240000); + m_creature->SummonCreature(11054,ADD_4X,ADD_4Y,ADD_4Z,ADD_4O,TEMPSUMMON_TIMED_DESPAWN,240000); + m_creature->SummonCreature(11054,ADD_5X,ADD_5Y,ADD_5Z,ADD_5O,TEMPSUMMON_TIMED_DESPAWN,240000); + m_creature->SummonCreature(11054,ADD_7X,ADD_7Y,ADD_7Z,ADD_7O,TEMPSUMMON_TIMED_DESPAWN,240000); + m_creature->SummonCreature(11054,ADD_9X,ADD_9Y,ADD_9Z,ADD_9O,TEMPSUMMON_TIMED_DESPAWN,240000); + } + + void Aggro(Unit *who) + { + } + + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //Pummel + if (Pummel_Timer < diff) + { + //Cast + if (rand()%100 < 90) //90% chance to cast + { + DoCast(m_creature->getVictim(),SPELL_PUMMEL); + } + //12 seconds until we should cast this again + Pummel_Timer = 12000; + }else Pummel_Timer -= diff; + + //KnockAway + if (KnockAway_Timer < diff) + { + //Cast + if (rand()%100 < 80) //80% chance to cast + { + DoCast(m_creature->getVictim(),SPELL_KNOCKAWAY); + } + //14 seconds until we should cast this again + KnockAway_Timer = 14000; + }else KnockAway_Timer -= diff; + + //Shoot + if (Shoot_Timer < diff) + { + //Cast + DoCast(m_creature->getVictim(),SPELL_SHOOT); + //1 seconds until we should cast this again + Shoot_Timer = 1000; + }else Shoot_Timer -= diff; + + //SummonRifleman + if (SummonRifleman_Timer < diff) + { + //Cast + switch (rand()%9) + { + case 0: + m_creature->SummonCreature(11054,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,240000); + m_creature->SummonCreature(11054,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,240000); + m_creature->SummonCreature(11054,ADD_4X,ADD_4Y,ADD_4Z,ADD_4O,TEMPSUMMON_TIMED_DESPAWN,240000); + break; + case 1: + m_creature->SummonCreature(11054,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,240000); + m_creature->SummonCreature(11054,ADD_3X,ADD_3Y,ADD_3Z,ADD_3O,TEMPSUMMON_TIMED_DESPAWN,240000); + m_creature->SummonCreature(11054,ADD_5X,ADD_5Y,ADD_5Z,ADD_5O,TEMPSUMMON_TIMED_DESPAWN,240000); + break; + case 2: + m_creature->SummonCreature(11054,ADD_3X,ADD_3Y,ADD_3Z,ADD_3O,TEMPSUMMON_TIMED_DESPAWN,240000); + m_creature->SummonCreature(11054,ADD_4X,ADD_4Y,ADD_4Z,ADD_4O,TEMPSUMMON_TIMED_DESPAWN,240000); + m_creature->SummonCreature(11054,ADD_6X,ADD_6Y,ADD_6Z,ADD_6O,TEMPSUMMON_TIMED_DESPAWN,240000); + break; + case 3: + m_creature->SummonCreature(11054,ADD_4X,ADD_4Y,ADD_4Z,ADD_4O,TEMPSUMMON_TIMED_DESPAWN,240000); + m_creature->SummonCreature(11054,ADD_5X,ADD_5Y,ADD_5Z,ADD_5O,TEMPSUMMON_TIMED_DESPAWN,240000); + m_creature->SummonCreature(11054,ADD_7X,ADD_7Y,ADD_7Z,ADD_7O,TEMPSUMMON_TIMED_DESPAWN,240000); + break; + case 4: + m_creature->SummonCreature(11054,ADD_5X,ADD_5Y,ADD_5Z,ADD_5O,TEMPSUMMON_TIMED_DESPAWN,240000); + m_creature->SummonCreature(11054,ADD_6X,ADD_6Y,ADD_6Z,ADD_6O,TEMPSUMMON_TIMED_DESPAWN,240000); + m_creature->SummonCreature(11054,ADD_8X,ADD_8Y,ADD_8Z,ADD_8O,TEMPSUMMON_TIMED_DESPAWN,240000); + break; + case 5: + m_creature->SummonCreature(11054,ADD_6X,ADD_6Y,ADD_6Z,ADD_6O,TEMPSUMMON_TIMED_DESPAWN,240000); + m_creature->SummonCreature(11054,ADD_7X,ADD_7Y,ADD_7Z,ADD_7O,TEMPSUMMON_TIMED_DESPAWN,240000); + m_creature->SummonCreature(11054,ADD_9X,ADD_9Y,ADD_9Z,ADD_9O,TEMPSUMMON_TIMED_DESPAWN,240000); + break; + case 6: + m_creature->SummonCreature(11054,ADD_7X,ADD_7Y,ADD_7Z,ADD_7O,TEMPSUMMON_TIMED_DESPAWN,240000); + m_creature->SummonCreature(11054,ADD_8X,ADD_8Y,ADD_8Z,ADD_8O,TEMPSUMMON_TIMED_DESPAWN,240000); + m_creature->SummonCreature(11054,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,240000); + break; + case 7: + m_creature->SummonCreature(11054,ADD_8X,ADD_8Y,ADD_8Z,ADD_8O,TEMPSUMMON_TIMED_DESPAWN,240000); + m_creature->SummonCreature(11054,ADD_9X,ADD_9Y,ADD_9Z,ADD_9O,TEMPSUMMON_TIMED_DESPAWN,240000); + m_creature->SummonCreature(11054,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,240000); + break; + case 8: + m_creature->SummonCreature(11054,ADD_9X,ADD_9Y,ADD_9Z,ADD_9O,TEMPSUMMON_TIMED_DESPAWN,240000); + m_creature->SummonCreature(11054,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,240000); + m_creature->SummonCreature(11054,ADD_3X,ADD_3Y,ADD_3Z,ADD_3O,TEMPSUMMON_TIMED_DESPAWN,240000); + break; + } + //30 seconds until we should cast this again + SummonRifleman_Timer = 30000; + }else SummonRifleman_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_cannon_master_willey(Creature *_Creature) +{ + return new boss_cannon_master_willeyAI (_Creature); +} + + +void AddSC_boss_cannon_master_willey() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_cannon_master_willey"; + newscript->GetAI = GetAI_boss_cannon_master_willey; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/stratholme/boss_dathrohan_balnazzar.cpp b/src/bindings/scripts/scripts/zone/stratholme/boss_dathrohan_balnazzar.cpp new file mode 100644 index 00000000000..0db8cff8141 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/stratholme/boss_dathrohan_balnazzar.cpp @@ -0,0 +1,316 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: boss_darhrohan_balnazzar +SD%Complete: 100 +SDComment: CHECK SQL +SDCategory: Stratholme +EndScriptData */ + +#include "precompiled.h" + +//Dathrohan spells +#define SPELL_CRUSADERSHAMMER 17286 //AOE stun +#define SPELL_CRUSADERSTRIKE 17281 +#define SPELL_MINDBLAST 17287 +#define SPELL_HOLYSTRIKE 17284 //weapon dmg +3 +#define SPELL_DAZED 1604 + +//Transform +#define SPELL_BALNAZZARTRANSFORM 17288 //restore full HP/mana, trigger spell Balnazzar Transform Stun + +//Balnazzar spells +#define SPELL_SHADOWSHOCK 20603 //AOE 740-860dmg +#define SPELL_PSYCHICSCREAM 15398 //One target, might want to make a code selecting random target +#define SPELL_DEEPSLEEP 24777 //AOE, ten sec +#define SPELL_SHADOWBOLTVOLLEY 20741 //AOE, 255-345dmg +//#define SPELL_MINDCONTROL 15690 //core support needed + +//Summon +//G1 front, left +#define ADD_1X 3444.156250 +#define ADD_1Y -3090.626709 +#define ADD_1Z 135.002319 +#define ADD_1O 2.240888 +//G1 front, right +#define ADD_2X 3449.123535 +#define ADD_2Y -3087.009766 +#define ADD_2Z 135.002319 +#define ADD_2O 2.240888 +//G1 back left +#define ADD_3X 3446.246826 +#define ADD_3Y -3093.466309 +#define ADD_3Z 135.002319 +#define ADD_3O 2.240888 +//G1 back, right +#define ADD_4X 3451.160889 +#define ADD_4Y -3089.904785 +#define ADD_4Z 135.002136 +#define ADD_4O 2.240888 +//G2 front, left +#define ADD_5X 3457.995117 +#define ADD_5Y -3080.916504 +#define ADD_5Z 135.002319 +#define ADD_5O 3.784981 +//G2 front, right +#define ADD_6X 3454.302490 +#define ADD_6Y -3076.330566 +#define ADD_6Z 135.002319 +#define ADD_6O 3.784981 +//G2 back left +#define ADD_7X 3460.975098 +#define ADD_7Y -3078.901367 +#define ADD_7Z 135.002319 +#define ADD_7O 3.784981 +//G2 back, right +#define ADD_8X 3457.338867 +#define ADD_8Y -3073.979004 +#define ADD_8Z 135.002319 +#define ADD_8O 3.784981 + +struct MANGOS_DLL_DECL boss_dathrohan_balnazzarAI : public ScriptedAI +{ + boss_dathrohan_balnazzarAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 CrusadersHammer_Timer; + uint32 CrusaderStrike_Timer; + uint32 MindBlast_Timer; + uint32 HolyStrike_Timer; + uint32 Dazed_Timer; + uint32 ShadowShock_Timer; + uint32 PsychicScream_Timer; + uint32 DeepSleep_Timer; + uint32 ShadowBoltVolley_Timer; + // uint32 MindControl_Timer; + bool Transformed; + + void Reset() + { + CrusadersHammer_Timer = 8000; + CrusaderStrike_Timer = 14000; + MindBlast_Timer = 17000; + HolyStrike_Timer = 18000; + Dazed_Timer = 23000; + ShadowShock_Timer = 4000; + PsychicScream_Timer = 16000; + DeepSleep_Timer = 20000; + ShadowBoltVolley_Timer = 9000; + // MindControl_Timer = 10000; + Transformed = false; + + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID,10545); + m_creature->SetFloatValue(OBJECT_FIELD_SCALE_X, 1.00f); + + } + + void JustDied(Unit* Victim) + { + m_creature->SummonCreature(10698,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,240000); + m_creature->SummonCreature(10698,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,240000); + m_creature->SummonCreature(10698,ADD_3X,ADD_3Y,ADD_3Z,ADD_3O,TEMPSUMMON_TIMED_DESPAWN,240000); + m_creature->SummonCreature(10698,ADD_4X,ADD_4Y,ADD_4Z,ADD_4O,TEMPSUMMON_TIMED_DESPAWN,240000); + m_creature->SummonCreature(10698,ADD_5X,ADD_5Y,ADD_5Z,ADD_5O,TEMPSUMMON_TIMED_DESPAWN,240000); + m_creature->SummonCreature(10698,ADD_6X,ADD_6Y,ADD_6Z,ADD_6O,TEMPSUMMON_TIMED_DESPAWN,240000); + m_creature->SummonCreature(10698,ADD_7X,ADD_7Y,ADD_7Z,ADD_7O,TEMPSUMMON_TIMED_DESPAWN,240000); + m_creature->SummonCreature(10698,ADD_8X,ADD_8Y,ADD_8Z,ADD_8O,TEMPSUMMON_TIMED_DESPAWN,240000); + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //START NOT TRANSFORMED + if (!Transformed) + { + //CrusadersHammer + if (CrusadersHammer_Timer < diff && !m_creature->IsNonMeleeSpellCasted(false)) + { + //Cast + if (rand()%100 < 75) //50% chance to cast + { + DoCast(m_creature->getVictim(),SPELL_CRUSADERSHAMMER); + } + //15 seconds until we should cast this again + CrusadersHammer_Timer = 12000; + }else CrusadersHammer_Timer -= diff; + + //CrusaderStrike + if (CrusaderStrike_Timer < diff && !m_creature->IsNonMeleeSpellCasted(false)) + { + //Cast + if (rand()%100 < 60) //50% chance to cast + { + DoCast(m_creature->getVictim(),SPELL_CRUSADERSTRIKE); + } + //15 seconds until we should cast this again + CrusaderStrike_Timer = 15000; + }else CrusaderStrike_Timer -= diff; + + //MindBlast + if (MindBlast_Timer < diff && !m_creature->IsNonMeleeSpellCasted(false)) + { + //Cast + if (rand()%100 < 70) //70% chance to cast + { + DoCast(m_creature->getVictim(),SPELL_MINDBLAST); + } + //15 seconds until we should cast this again + MindBlast_Timer = 10000; + }else MindBlast_Timer -= diff; + + //HolyStrike + if (HolyStrike_Timer < diff && !m_creature->IsNonMeleeSpellCasted(false)) + { + //Cast + if (rand()%100 < 50) //50% chance to cast + { + DoCast(m_creature->getVictim(),SPELL_HOLYSTRIKE); + } + //15 seconds until we should cast this again + HolyStrike_Timer = 15000; + }else HolyStrike_Timer -= diff; + + //Dazed + if (Dazed_Timer < diff && !m_creature->IsNonMeleeSpellCasted(false)) + { + //Cast + if (rand()%100 < 50) //50% chance to cast + { + DoCast(m_creature->getVictim(),SPELL_DAZED); + } + //15 seconds until we should cast this again + Dazed_Timer = 15000; + }else Dazed_Timer -= diff; + + //BalnazzarTransform + if (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 40) + { + //Cast + DoCast(m_creature,SPELL_BALNAZZARTRANSFORM); //restore hp, mana and stun + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID,10691); //then change disaply id + m_creature->SetFloatValue(OBJECT_FIELD_SCALE_X, 3.00f); //then, change size + Transformed = true; + } + + //START ELSE TRANSFORMED + } else { + + + //MindBlast + if (MindBlast_Timer < diff && !m_creature->IsNonMeleeSpellCasted(false)) + { + //Cast + if (rand()%100 < 60) //70% chance to cast + { + DoCast(m_creature->getVictim(),SPELL_MINDBLAST); + } + //15 seconds until we should cast this again + MindBlast_Timer = 10000; + }else MindBlast_Timer -= diff; + + //ShadowShock + if (ShadowShock_Timer < diff) + { + //Cast + if (rand()%100 < 80) //80% chance to cast + { + DoCast(m_creature->getVictim(),SPELL_SHADOWSHOCK); + } + //15 seconds until we should cast this again + ShadowShock_Timer = 11000; + }else ShadowShock_Timer -= diff; + + //PsychicScream + if (PsychicScream_Timer < diff) + { + //Cast + if (rand()%100 < 60) //60% chance to cast + { + DoCast(m_creature->getVictim(),SPELL_PSYCHICSCREAM); + if(m_creature->getThreatManager().getThreat(m_creature->getVictim())) + m_creature->getThreatManager().modifyThreatPercent(m_creature->getVictim(),-50); + } + //15 seconds until we should cast this again + PsychicScream_Timer = 20000; + }else PsychicScream_Timer -= diff; + + //DeepSleep + if (DeepSleep_Timer < diff) + { + //Cast + if (rand()%100 < 55) //55% chance to cast + { + //Cast + Unit* target = NULL; + + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) + DoCast(target,SPELL_DEEPSLEEP); + } + //15 seconds until we should cast this again + DeepSleep_Timer = 15000; + }else DeepSleep_Timer -= diff; + + //ShadowBoltVolley + if (ShadowBoltVolley_Timer < diff) + { + //Cast + if (rand()%100 < 75) //75% chance to cast + { + DoCast(m_creature->getVictim(),SPELL_SHADOWBOLTVOLLEY); + } + //15 seconds until we should cast this again + ShadowBoltVolley_Timer = 13000; + }else ShadowBoltVolley_Timer -= diff; + + //MindControl + // if (MindControl_Timer < diff) + // { + //Cast + // if (rand()%100 < 50) //50% chance to cast + // { + // DoCast(m_creature->getVictim(),SPELL_MINDCONTROL); + // } + //15 seconds until we should cast this again + // MindControl_Timer = 15000; + // }else MindControl_Timer -= diff; + + //END ELSE TRANSFORMED + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_dathrohan_balnazzar(Creature *_Creature) +{ + return new boss_dathrohan_balnazzarAI (_Creature); +} + +void AddSC_boss_dathrohan_balnazzar() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_dathrohan_balnazzar"; + newscript->GetAI = GetAI_boss_dathrohan_balnazzar; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/stratholme/boss_magistrate_barthilas.cpp b/src/bindings/scripts/scripts/zone/stratholme/boss_magistrate_barthilas.cpp new file mode 100644 index 00000000000..aceb05b1614 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/stratholme/boss_magistrate_barthilas.cpp @@ -0,0 +1,114 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: boss_magistrate_barthilas +SD%Complete: 100 +SDComment: +SDCategory: Stratholme +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_DRAININGBLOW 16793 +#define SPELL_CROWDPUMMEL 10887 +#define SPELL_MIGHTYBLOW 14099 +#define SPELL_DAZED 1604 + +struct MANGOS_DLL_DECL boss_magistrate_barthilasAI : public ScriptedAI +{ + boss_magistrate_barthilasAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 DrainingBlow_Timer; + uint32 CrowdPummel_Timer; + uint32 MightyBlow_Timer; + uint32 Dazed_Timer; + + void Reset() + { + DrainingBlow_Timer = 4000; + CrowdPummel_Timer = 13000; + MightyBlow_Timer = 11000; + Dazed_Timer = 7000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //DrainingBlow + if (DrainingBlow_Timer < diff) + { + //Cast + DoCast(m_creature->getVictim(),SPELL_DRAININGBLOW); + + //4 seconds until we should cast this again + DrainingBlow_Timer = 4000; + }else DrainingBlow_Timer -= diff; + + //CrowdPummel + if (CrowdPummel_Timer < diff) + { + //Cast + DoCast(m_creature->getVictim(),SPELL_CROWDPUMMEL); + + //13 seconds until we should cast this agian + CrowdPummel_Timer = 13000; + }else CrowdPummel_Timer -= diff; + + //MightyBlow + if (MightyBlow_Timer < diff) + { + //Cast + DoCast(m_creature->getVictim(),SPELL_MIGHTYBLOW); + + //11 seconds until we should cast this again + MightyBlow_Timer = 11000; + }else MightyBlow_Timer -= diff; + + //Dazed + if (Dazed_Timer < diff) + { + //Cast + DoCast(m_creature->getVictim(),SPELL_DAZED); + + //20 seconds until we should cast this again + Dazed_Timer = 20000; + }else Dazed_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_magistrate_barthilas(Creature *_Creature) +{ + return new boss_magistrate_barthilasAI (_Creature); +} + + +void AddSC_boss_magistrate_barthilas() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_magistrate_barthilas"; + newscript->GetAI = GetAI_boss_magistrate_barthilas; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/stratholme/boss_maleki_the_pallid.cpp b/src/bindings/scripts/scripts/zone/stratholme/boss_maleki_the_pallid.cpp new file mode 100644 index 00000000000..6c3c75e9bc6 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/stratholme/boss_maleki_the_pallid.cpp @@ -0,0 +1,119 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: boss_maleki_the_pallid +SD%Complete: 100 +SDComment: +SDCategory: Stratholme +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_FROSTNOVA 22645 +#define SPELL_FROSTBOLT 17503 +#define SPELL_DRAINLIFE 20743 +#define SPELL_ICETOMB 16869 + +struct MANGOS_DLL_DECL boss_maleki_the_pallidAI : public ScriptedAI +{ + boss_maleki_the_pallidAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 FrostNova_Timer; + uint32 Frostbolt_Timer; + uint32 IceTomb_Timer; + uint32 DrainLife_Timer; + + void Reset() + { + FrostNova_Timer = 11000; + Frostbolt_Timer = 1000; + IceTomb_Timer = 16000; + DrainLife_Timer = 31000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //FrostNova + if (FrostNova_Timer < diff) + { + //Cast + DoCast(m_creature->getVictim(),SPELL_FROSTNOVA); + //23 seconds until we should cast this again + FrostNova_Timer = 23000; + }else FrostNova_Timer -= diff; + + //Frostbolt + if (Frostbolt_Timer < diff) + { + //Cast + if (rand()%100 < 90) //90% chance to cast + { + DoCast(m_creature->getVictim(),SPELL_FROSTBOLT); + } + //3.5 seconds until we should cast this again + Frostbolt_Timer = 3500; + }else Frostbolt_Timer -= diff; + + //IceTomb + if (IceTomb_Timer < diff) + { + //Cast + if (rand()%100 < 65) //65% chance to cast + { + DoCast(m_creature->getVictim(),SPELL_ICETOMB); + } + //28 seconds until we should cast this again + IceTomb_Timer = 28000; + }else IceTomb_Timer -= diff; + + //DrainLife + if (DrainLife_Timer < diff) + { + //Cast + if (rand()%100 < 55) //55% chance to cast + { + DoCast(m_creature->getVictim(),SPELL_DRAINLIFE); + } + //31 seconds until we should cast this again + DrainLife_Timer = 31000; + }else DrainLife_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_maleki_the_pallid(Creature *_Creature) +{ + return new boss_maleki_the_pallidAI (_Creature); +} + + +void AddSC_boss_maleki_the_pallid() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_maleki_the_pallid"; + newscript->GetAI = GetAI_boss_maleki_the_pallid; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/stratholme/boss_nerubenkan.cpp b/src/bindings/scripts/scripts/zone/stratholme/boss_nerubenkan.cpp new file mode 100644 index 00000000000..59bd632836c --- /dev/null +++ b/src/bindings/scripts/scripts/zone/stratholme/boss_nerubenkan.cpp @@ -0,0 +1,138 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: boss_nerubenkan +SD%Complete: 100 +SDComment: +SDCategory: Stratholme +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_ENCASINGWEBS 4962 +#define SPELL_PIERCEARMOR 6016 +#define SPELL_VIRULENTPOISON 16427 +//#define SPELL_RAISEUNDEADSCARAB 17235 + +struct MANGOS_DLL_DECL boss_nerubenkanAI : public ScriptedAI +{ + boss_nerubenkanAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 EncasingWebs_Timer; + uint32 PierceArmor_Timer; + uint32 VirulentPoison_Timer; + uint32 RaiseUndeadScarab_Timer; + int Rand; + int RandX; + int RandY; + Creature* Summoned; + + void Reset() + { + VirulentPoison_Timer = 3000; + EncasingWebs_Timer = 7000; + PierceArmor_Timer = 19000; + RaiseUndeadScarab_Timer = 11000; + } + + void Aggro(Unit *who) + { + } + + void RaiseUndeadScarab(Unit* victim) + { + Rand = rand()%10; + switch (rand()%2) + { + case 0: RandX = 0 - Rand; break; + case 1: RandX = 0 + Rand; break; + } + Rand = 0; + Rand = rand()%10; + switch (rand()%2) + { + case 0: RandY = 0 - Rand; break; + case 1: RandY = 0 + Rand; break; + } + Rand = 0; + Summoned = DoSpawnCreature(10876, RandX, RandY, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 180000); + if(Summoned) + ((CreatureAI*)Summoned->AI())->AttackStart(victim); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //EncasingWebs + if (EncasingWebs_Timer < diff) + { + //Cast + DoCast(m_creature->getVictim(),SPELL_ENCASINGWEBS); + //30 seconds until we should cast this again + EncasingWebs_Timer = 30000; + }else EncasingWebs_Timer -= diff; + + //PierceArmor + if (PierceArmor_Timer < diff) + { + //Cast + if (rand()%100 < 75) //75% chance to cast + { + DoCast(m_creature->getVictim(),SPELL_PIERCEARMOR); + } + //35 seconds until we should cast this again + PierceArmor_Timer = 35000; + }else PierceArmor_Timer -= diff; + + //VirulentPoison + if (VirulentPoison_Timer < diff) + { + //Cast + DoCast(m_creature->getVictim(),SPELL_VIRULENTPOISON); + //20 seconds until we should cast this again + VirulentPoison_Timer = 20000; + }else VirulentPoison_Timer -= diff; + + //RaiseUndeadScarab + if (RaiseUndeadScarab_Timer < diff) + { + //Cast + RaiseUndeadScarab(m_creature->getVictim()); + //16 seconds until we should cast this again + RaiseUndeadScarab_Timer = 16000; + }else RaiseUndeadScarab_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_nerubenkan(Creature *_Creature) +{ + return new boss_nerubenkanAI (_Creature); +} + + +void AddSC_boss_nerubenkan() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_nerubenkan"; + newscript->GetAI = GetAI_boss_nerubenkan; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/stratholme/boss_order_of_silver_hand.cpp b/src/bindings/scripts/scripts/zone/stratholme/boss_order_of_silver_hand.cpp new file mode 100644 index 00000000000..9da5b48e55c --- /dev/null +++ b/src/bindings/scripts/scripts/zone/stratholme/boss_order_of_silver_hand.cpp @@ -0,0 +1,161 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Silver_Hand_Bosses +SD%Complete: 40 +SDComment: Basic script to have support for Horde paladin epic mount (quest 9737). All 5 members of Order of the Silver Hand running this script (least for now) +SDCategory: Stratholme +EndScriptData */ + +#include "precompiled.h" +#include "def_stratholme.h" + +/*##### +# Additional: +# Although this is a working solution, the correct would be in addition to check if Aurius is dead. +# Once player extinguish the eternal flame (cast spell 31497->start event 11206) Aurius should become hostile. +# Once Aurius is defeated, he should be the one summoning the ghosts. +#####*/ + +#define SH_GREGOR 17910 +#define SH_CATHELA 17911 +#define SH_NEMAS 17912 +#define SH_AELMAR 17913 +#define SH_VICAR 17914 +#define SH_QUEST_CREDIT 17915 + +#define SPELL_HOLY_LIGHT 25263 +#define SPELL_DIVINE_SHIELD 13874 + +struct MANGOS_DLL_DECL boss_silver_hand_bossesAI : public ScriptedAI +{ + boss_silver_hand_bossesAI(Creature* c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance *pInstance; + + uint32 HolyLight_Timer; + uint32 DivineShield_Timer; + + void Reset() + { + HolyLight_Timer = 20000; + DivineShield_Timer = 20000; + + if(pInstance) + { + switch(m_creature->GetEntry()) + { + case SH_AELMAR: + pInstance->SetData(TYPE_SH_AELMAR, 0); + break; + case SH_CATHELA: + pInstance->SetData(TYPE_SH_CATHELA, 0); + break; + case SH_GREGOR: + pInstance->SetData(TYPE_SH_GREGOR, 0); + break; + case SH_NEMAS: + pInstance->SetData(TYPE_SH_NEMAS, 0); + break; + case SH_VICAR: + pInstance->SetData(TYPE_SH_VICAR, 0); + break; + } + } + } + + void Aggro(Unit* who) + { + } + + void JustDied(Unit* Killer) + { + if(pInstance) + { + switch(m_creature->GetEntry()) + { + case SH_AELMAR: + pInstance->SetData(TYPE_SH_AELMAR, 2); + break; + case SH_CATHELA: + pInstance->SetData(TYPE_SH_CATHELA, 2); + break; + case SH_GREGOR: + pInstance->SetData(TYPE_SH_GREGOR, 2); + break; + case SH_NEMAS: + pInstance->SetData(TYPE_SH_NEMAS, 2); + break; + case SH_VICAR: + pInstance->SetData(TYPE_SH_VICAR, 2); + break; + } + if(pInstance->GetData(TYPE_SH_QUEST) && Killer->GetTypeId() == TYPEID_PLAYER) + ((Player*)Killer)->KilledMonster(SH_QUEST_CREDIT,m_creature->GetGUID()); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if (HolyLight_Timer < diff) + { + if (m_creature->GetHealth()*5 < m_creature->GetMaxHealth()) + { + DoCast(m_creature, SPELL_HOLY_LIGHT); + HolyLight_Timer = 20000; + } + }else HolyLight_Timer -= diff; + + if (DivineShield_Timer < diff) + { + if (m_creature->GetHealth()*20 < m_creature->GetMaxHealth()) + { + DoCast(m_creature, SPELL_DIVINE_SHIELD); + DivineShield_Timer = 40000; + } + }else DivineShield_Timer -= diff; + + DoMeleeAttackIfReady(); + } + +}; +CreatureAI* GetAI_boss_silver_hand_bossesAI(Creature *_Creature) +{ + return new boss_silver_hand_bossesAI (_Creature); +} + +/*##### +# +#####*/ + +void AddSC_boss_order_of_silver_hand() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_silver_hand_bosses"; + newscript->GetAI = GetAI_boss_silver_hand_bossesAI; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/stratholme/boss_postmaster_malown.cpp b/src/bindings/scripts/scripts/zone/stratholme/boss_postmaster_malown.cpp new file mode 100644 index 00000000000..c303207101d --- /dev/null +++ b/src/bindings/scripts/scripts/zone/stratholme/boss_postmaster_malown.cpp @@ -0,0 +1,144 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: boss_postmaster_malown +SD%Complete: 50 +SDComment: +SDCategory: Stratholme +EndScriptData */ + +#include "precompiled.h" + +//Spell ID to summon this guy is 24627 "Summon Postmaster Malown" +//He should be spawned along with three other elites once the third postbox has been opened + +#define SAY_MALOWNED "You just got MALOWNED!" + +#define SPELL_WAILINGDEAD 7713 +#define SPELL_BACKHAND 6253 +#define SPELL_CURSEOFWEAKNESS 8552 +#define SPELL_CURSEOFTONGUES 12889 +#define SPELL_CALLOFTHEGRAVE 17831 + +struct MANGOS_DLL_DECL boss_postmaster_malownAI : public ScriptedAI +{ + boss_postmaster_malownAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 WailingDead_Timer; + uint32 Backhand_Timer; + uint32 CurseOfWeakness_Timer; + uint32 CurseOfTongues_Timer; + uint32 CallOfTheGrave_Timer; + bool HasYelled; + + void Reset() + { + WailingDead_Timer = 19000; //lasts 6 sec + Backhand_Timer = 8000; //2 sec stun + CurseOfWeakness_Timer = 20000; //lasts 2 mins + CurseOfTongues_Timer = 22000; + CallOfTheGrave_Timer = 25000; + HasYelled = false; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //WailingDead + if (WailingDead_Timer < diff) + { + //Cast + if (rand()%100 < 65) //65% chance to cast + { + DoCast(m_creature->getVictim(),SPELL_WAILINGDEAD); + } + //19 seconds until we should cast this again + WailingDead_Timer = 19000; + }else WailingDead_Timer -= diff; + + //Backhand + if (Backhand_Timer < diff) + { + //Cast + if (rand()%100 < 45) //45% chance to cast + { + DoCast(m_creature->getVictim(),SPELL_BACKHAND); + } + //8 seconds until we should cast this again + Backhand_Timer = 8000; + }else Backhand_Timer -= diff; + + //CurseOfWeakness + if (CurseOfWeakness_Timer < diff) + { + //Cast + if (rand()%100 < 3) //3% chance to cast + { + DoCast(m_creature->getVictim(),SPELL_CURSEOFWEAKNESS); + } + //20 seconds until we should cast this again + CurseOfWeakness_Timer = 20000; + }else CurseOfWeakness_Timer -= diff; + + //CurseOfTongues + if (CurseOfTongues_Timer < diff) + { + //Cast + if (rand()%100 < 3) //3% chance to cast + { + DoCast(m_creature->getVictim(),SPELL_CURSEOFTONGUES); + } + //22 seconds until we should cast this again + CurseOfTongues_Timer = 22000; + }else CurseOfTongues_Timer -= diff; + + //CallOfTheGrave + if (CallOfTheGrave_Timer < diff) + { + //Cast + if (rand()%100 < 5) //5% chance to cast + { + DoCast(m_creature->getVictim(),SPELL_CALLOFTHEGRAVE); + } + //25 seconds until we should cast this again + CallOfTheGrave_Timer = 25000; + }else CallOfTheGrave_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_postmaster_malown(Creature *_Creature) +{ + return new boss_postmaster_malownAI (_Creature); +} + + +void AddSC_boss_postmaster_malown() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_postmaster_malown"; + newscript->GetAI = GetAI_boss_postmaster_malown; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/stratholme/boss_ramstein_the_gorger.cpp b/src/bindings/scripts/scripts/zone/stratholme/boss_ramstein_the_gorger.cpp new file mode 100644 index 00000000000..7b175f5b9ff --- /dev/null +++ b/src/bindings/scripts/scripts/zone/stratholme/boss_ramstein_the_gorger.cpp @@ -0,0 +1,92 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: boss_ramstein_the_gorger +SD%Complete: 100 +SDComment: +SDCategory: Stratholme +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_TRAMPLE 15550 +#define SPELL_KNOCKOUT 17307 + +struct MANGOS_DLL_DECL boss_ramstein_the_gorgerAI : public ScriptedAI +{ + boss_ramstein_the_gorgerAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Trample_Timer; + uint32 Knockout_Timer; + + void Reset() + { + Trample_Timer = 3000; + Knockout_Timer = 12000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //Trample + if (Trample_Timer < diff) + { + //Cast + if (rand()%100 < 75) //75% chance to cast + { + DoCast(m_creature->getVictim(),SPELL_TRAMPLE); + } + //7 seconds until we should cast this again + Trample_Timer = 7000; + }else Trample_Timer -= diff; + + //Knockout + if (Knockout_Timer < diff) + { + //Cast + if (rand()%100 < 70) //70% chance to cast + { + DoCast(m_creature->getVictim(),SPELL_KNOCKOUT); + } + //10 seconds until we should cast this again + Knockout_Timer = 10000; + }else Knockout_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_ramstein_the_gorger(Creature *_Creature) +{ + return new boss_ramstein_the_gorgerAI (_Creature); +} + + +void AddSC_boss_ramstein_the_gorger() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_ramstein_the_gorger"; + newscript->GetAI = GetAI_boss_ramstein_the_gorger; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/stratholme/boss_timmy_the_cruel.cpp b/src/bindings/scripts/scripts/zone/stratholme/boss_timmy_the_cruel.cpp new file mode 100644 index 00000000000..1fc4eedc5f5 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/stratholme/boss_timmy_the_cruel.cpp @@ -0,0 +1,103 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: boss_timmy_the_cruel +SD%Complete: 100 +SDComment: +SDCategory: Stratholme +EndScriptData */ + +#include "precompiled.h" + +#define SAY_SPAWN "TIMMY!" + +#define SPELL_RAVENOUSCLAW 17470 + +struct MANGOS_DLL_DECL boss_timmy_the_cruelAI : public ScriptedAI +{ + boss_timmy_the_cruelAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 RavenousClaw_Timer; + bool HasYelled; + + void Reset() + { + RavenousClaw_Timer = 10000; + HasYelled = false; + } + + void Aggro(Unit *who) + { + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || m_creature->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + float attackRadius = m_creature->GetAttackDistance(who); + if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) + { + if(who->HasStealthAura()) + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + if (!HasYelled) + { + DoYell(SAY_SPAWN,LANG_UNIVERSAL,NULL); + HasYelled = true; + } + + //Begin melee attack if we are within range + DoStartAttackAndMovement(who); + } + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //RavenousClaw + if (RavenousClaw_Timer < diff) + { + //Cast + DoCast(m_creature->getVictim(),SPELL_RAVENOUSCLAW); + //15 seconds until we should cast this again + RavenousClaw_Timer = 15000; + }else RavenousClaw_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_timmy_the_cruel(Creature *_Creature) +{ + return new boss_timmy_the_cruelAI (_Creature); +} + + +void AddSC_boss_timmy_the_cruel() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_timmy_the_cruel"; + newscript->GetAI = GetAI_boss_timmy_the_cruel; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/stratholme/def_stratholme.h b/src/bindings/scripts/scripts/zone/stratholme/def_stratholme.h new file mode 100644 index 00000000000..27c181a77f5 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/stratholme/def_stratholme.h @@ -0,0 +1,14 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 +* This program is free software licensed under GPL version 2 +* Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_STRATHOLME_H +#define DEF_STRATHOLME_H + +#define TYPE_SH_AELMAR 1 +#define TYPE_SH_CATHELA 2 +#define TYPE_SH_GREGOR 3 +#define TYPE_SH_NEMAS 4 +#define TYPE_SH_VICAR 5 +#define TYPE_SH_QUEST 6 +#endif diff --git a/src/bindings/scripts/scripts/zone/stratholme/instance_stratholme.cpp b/src/bindings/scripts/scripts/zone/stratholme/instance_stratholme.cpp new file mode 100644 index 00000000000..8277d6e043a --- /dev/null +++ b/src/bindings/scripts/scripts/zone/stratholme/instance_stratholme.cpp @@ -0,0 +1,77 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: instance_stratholme +SD%Complete: 100 +SDComment: +SDCategory: Stratholme +EndScriptData */ + +#include "precompiled.h" +#include "def_stratholme.h" + +struct MANGOS_DLL_DECL instance_stratholme : public ScriptedInstance +{ + instance_stratholme(Map *Map) : ScriptedInstance(Map) {Initialize();}; + + bool IsSilverHandDead[5]; + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case TYPE_SH_AELMAR: + IsSilverHandDead[0] = (data) ? true : false; + break; + case TYPE_SH_CATHELA: + IsSilverHandDead[1] = (data) ? true : false; + break; + case TYPE_SH_GREGOR: + IsSilverHandDead[2] = (data) ? true : false; + break; + case TYPE_SH_NEMAS: + IsSilverHandDead[3] = (data) ? true : false; + break; + case TYPE_SH_VICAR: + IsSilverHandDead[4] = (data) ? true : false; + break; + } + } + + uint32 GetData(uint32 type) + { + if(type == TYPE_SH_QUEST) + if(IsSilverHandDead[0] && IsSilverHandDead[1] && IsSilverHandDead[2] && IsSilverHandDead[3] && IsSilverHandDead[4]) + return true; + + return false; + } +}; + +InstanceData* GetInstanceData_instance_stratholme(Map* map) +{ + return new instance_stratholme(map); +} + +void AddSC_instance_stratholme() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_stratholme"; + newscript->GetInstanceData = GetInstanceData_instance_stratholme; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/stratholme/stratholme.cpp b/src/bindings/scripts/scripts/zone/stratholme/stratholme.cpp new file mode 100644 index 00000000000..33e88bc04be --- /dev/null +++ b/src/bindings/scripts/scripts/zone/stratholme/stratholme.cpp @@ -0,0 +1,335 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Stratholme +SD%Complete: 100 +SDComment: trash mobs for strat. Simple AI mobs converted to EAI (except Mindless Skeleton and Thuzadin Acolyte) +SDCategory: Stratholme +EndScriptData */ + +#include "precompiled.h" +#include "../../creature/simple_ai.h" + +/*###### +## mob_freed_soul +######*/ + +//Possibly more of these quotes around. +#define SAY_ZAPPED0 "Thanks to Egan" +#define SAY_ZAPPED1 "Rivendare must die" +#define SAY_ZAPPED2 "Who you gonna call?" +#define SAY_ZAPPED3 "Don't cross those beams!" + +struct MANGOS_DLL_DECL mob_freed_soulAI : public ScriptedAI +{ + mob_freed_soulAI(Creature *c) : ScriptedAI(c) {Reset();} + + void Reset() + { + + switch (rand()%4) + { + case 0: + DoSay(SAY_ZAPPED0,LANG_UNIVERSAL,NULL); + break; + case 1: + DoSay(SAY_ZAPPED1,LANG_UNIVERSAL,NULL); + break; + case 2: + DoSay(SAY_ZAPPED2,LANG_UNIVERSAL,NULL); + break; + case 3: + DoSay(SAY_ZAPPED3,LANG_UNIVERSAL,NULL); + break; + } + } + + void Aggro(Unit* who) + { + } +}; +CreatureAI* GetAI_mob_freed_soul(Creature *_Creature) +{ + return new mob_freed_soulAI (_Creature); +} +/*###### +## mob_restless_soul +######*/ + +struct MANGOS_DLL_DECL mob_restless_soulAI : public ScriptedAI +{ + mob_restless_soulAI(Creature *c) : ScriptedAI(c) {Reset();} + + Unit* PlayerHolder; + uint32 Die_Timer; + bool OkToDie; + + void Reset() + { + Die_Timer = 10000; + OkToDie = false; + + PlayerHolder = NULL; + } + + void Aggro(Unit* who) + { + } + + void SummonFreedSoul(Unit* victim) + { + int Rand; + int RandX; + int RandY; + + Rand = rand()%1; + switch (rand()%2) + { + case 0: RandX = 0 - Rand; break; + case 1: RandX = 0 + Rand; break; + } + Rand = 0; + Rand = rand()%1; + switch (rand()%2) + { + case 0: RandY = 0 - Rand; break; + case 1: RandY = 0 + Rand; break; + } + Rand = 0; + DoSpawnCreature(11136, RandX, RandY, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 300000); + } + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if (caster->GetTypeId() == TYPEID_PLAYER) + { + if(!PlayerHolder && !OkToDie && spell->Id == 17368 && ((Player*)caster)->GetQuestStatus(5282) == QUEST_STATUS_INCOMPLETE) + { + PlayerHolder = caster; + OkToDie = true; + Die_Timer = 5000; + } + } + return; + } + + void JustDied(Unit* Killer) + { + if (Killer->GetTypeId() == TYPEID_PLAYER) + { + //check quest status + if(PlayerHolder == ((Player*)Killer) && ((Player*)Killer)->GetQuestStatus(5282) == QUEST_STATUS_INCOMPLETE) + { + SummonFreedSoul(m_creature->getVictim()); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (PlayerHolder && OkToDie && Die_Timer < diff) + { + PlayerHolder->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + else Die_Timer -= diff; + + return; + } +}; +CreatureAI* GetAI_mob_restless_soul(Creature *_Creature) +{ + return new mob_restless_soulAI (_Creature); +} + +/*###### +## mobs_spectral_ghostly_citizen +######*/ + +struct MANGOS_DLL_DECL mobs_spectral_ghostly_citizenAI : public ScriptedAI +{ + mobs_spectral_ghostly_citizenAI(Creature *c) : ScriptedAI(c) {Reset();} + + Unit* PlayerHolder; + uint32 Die_Timer; + bool OkToDie; + + void Reset() + { + Die_Timer = 5000; + OkToDie = false; + PlayerHolder = NULL; + } + + void Aggro(Unit* who) + { + } + + void SummonRestlessSoul(Unit* victim) + { + int Rand; + int RandX; + int RandY; + + Rand = rand()%7; + switch (rand()%2) + { + case 0: RandX = 0 - Rand; break; + case 1: RandX = 0 + Rand; break; + } + Rand = 0; + Rand = rand()%7; + switch (rand()%2) + { + case 0: RandY = 0 - Rand; break; + case 1: RandY = 0 + Rand; break; + } + Rand = 0; + DoSpawnCreature(11122, RandX, RandY, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 600000); + } + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if (caster->GetTypeId() == TYPEID_PLAYER) + { + if(!PlayerHolder && !OkToDie && spell->Id == 17368 && ((Player*)caster)->GetQuestStatus(5282) == QUEST_STATUS_INCOMPLETE) + { + PlayerHolder = caster; + OkToDie = true; + Die_Timer = 5000; + } + } + return; + } + + void JustDied(Unit* Killer) + { + if (Killer->GetTypeId() == TYPEID_PLAYER) + { + //check quest status + if(PlayerHolder == ((Player*)Killer) && ((Player*)Killer)->GetQuestStatus(5282) == QUEST_STATUS_INCOMPLETE) + { + SummonRestlessSoul(m_creature->getVictim()); //always one + if (rand()%100 < 90) SummonRestlessSoul(m_creature->getVictim()); //90% a second + if (rand()%100 < 50) SummonRestlessSoul(m_creature->getVictim()); //50% a third + if (rand()%100 < 30) SummonRestlessSoul(m_creature->getVictim()); //30% a fourth + } + } + } + + void UpdateAI(const uint32 diff) + { + if (PlayerHolder && OkToDie && Die_Timer < diff) + { + PlayerHolder->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + else Die_Timer -= diff; + + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_mobs_spectral_ghostly_citizen(Creature *_Creature) +{ + return new mobs_spectral_ghostly_citizenAI (_Creature); +} +bool ReciveEmote_mobs_spectral_ghostly_citizen(Player *player, Creature *_Creature, uint32 emote) +{ + _Creature->HandleEmoteCommand(emote); + + if (emote == TEXTEMOTE_DANCE) + ((mobs_spectral_ghostly_citizenAI*)_Creature->AI())->EnterEvadeMode(); + + return true; +} + +/*###### +## mob_mindless_skeleton +######*/ + +CreatureAI* GetAI_mob_mindless_skeleton(Creature *_Creature) +{ + SimpleAI* ai = new SimpleAI (_Creature); + + //dazed + ai->Spell[0].Enabled = true; + ai->Spell[0].Spell_Id = 13496; + ai->Spell[0].Cooldown = 15000; + ai->Spell[0].First_Cast = 3000; + ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_TARGET; + + ai->EnterEvadeMode(); + + return ai; +} + +/*###### +## mob_thuzadin_acolyte +######*/ + +CreatureAI* GetAI_mob_thuzadin_acolyte(Creature *_Creature) +{ + SimpleAI* ai = new SimpleAI (_Creature); + + //dazed + ai->Spell[0].Enabled = true; + ai->Spell[0].Spell_Id = 13496; + ai->Spell[0].Cooldown = 15000; + ai->Spell[0].First_Cast = 1000; + ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_TARGET; + + ai->EnterEvadeMode(); + + return ai; +} + +/*###### +## +######*/ + +void AddSC_stratholme() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="mob_freed_soul"; + newscript->GetAI = GetAI_mob_freed_soul; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_restless_soul"; + newscript->GetAI = GetAI_mob_restless_soul; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mobs_spectral_ghostly_citizen"; + newscript->GetAI = GetAI_mobs_spectral_ghostly_citizen; + newscript->pReceiveEmote = &ReciveEmote_mobs_spectral_ghostly_citizen; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_mindless_skeleton"; + newscript->GetAI = GetAI_mob_mindless_skeleton; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_thuzadin_acolyte"; + newscript->GetAI = GetAI_mob_thuzadin_acolyte; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_brutallus.cpp b/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_brutallus.cpp new file mode 100644 index 00000000000..36a8238cf45 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_brutallus.cpp @@ -0,0 +1,188 @@ +/* Copyright © 2006,2007 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Brutallus +SD%Complete: 80 +SDComment: Needs intro. Talk to the dragon. +EndScriptData */ + +#include "precompiled.h" +#include "def_sunwell_plateau.h" + +// Yells and Sounds used by boss. +#define YELL_AGGRO "Ahh! More lambs to the slaughter!" +#define SOUND_AGGRO 12463 + +#define YELL_BERSERK "So much for a real challenge... Die!" +#define SOUND_BERSERK 12470 + +#define YELL_KILL1 "Perish, insect!" +#define SOUND_KILL1 12464 + +#define YELL_KILL2 "You are meat!" +#define SOUND_KILL2 12465 + +#define YELL_KILL3 "Too easy!" +#define SOUND_KILL3 12466 + +#define YELL_CHARGE "I will crush you!" //I think it use this for stomp. No? +#define SOUND_CHARGE 12460 + +#define YELL_DEATH "Gah! Well done... Now... this gets... interesting..." +#define SOUND_DEATH 12471 + +#define YELL_LOVE1 "Bring the fight to me!" +#define SOUND_LOVE1 12467 + +#define YELL_LOVE2 "Another day, another glorious battle!" +#define SOUND_LOVE2 12468 + +#define YELL_LOVE3 "I live for this!" +#define SOUND_LOVE3 12469 + +// Boss spells. +#define METEOR_SLASH 45150 +#define BURN 46394 +#define STOMP 45185 +#define BERSERK 26662 + +struct MANGOS_DLL_DECL boss_brutallusAI : public ScriptedAI +{ + boss_brutallusAI(Creature *c) : ScriptedAI(c) { Reset(); } + + uint32 SlashTimer; + uint32 BurnTimer; + uint32 StompTimer; + uint32 BerserkTimer; + uint32 LoveTimer; + + void Reset() + { + SlashTimer = 11000; + StompTimer = 30000; + BurnTimer = 60000; + BerserkTimer = 360000; + LoveTimer = 10000 + rand()%7000; + } + + void Aggro(Unit *who) + { + DoYell(YELL_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO); + } + + void KilledUnit(Unit* victim) + { + switch(rand()%3) + { + case 0: + DoYell(YELL_KILL1,LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_KILL1); + break; + case 1: + DoYell(YELL_KILL2,LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_KILL2); + break; + case 2: + DoYell(YELL_KILL3,LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_KILL3); + break; + } + } + + void JustDied(Unit* Killer) + { + DoYell(YELL_DEATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_DEATH); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if(LoveTimer < diff) + { + switch(rand()%3) + { + case 0: + DoYell(YELL_LOVE1,LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_LOVE1); + break; + case 1: + DoYell(YELL_LOVE2,LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_LOVE2); + break; + case 2: + DoYell(YELL_LOVE3,LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_LOVE3); + break; + } + LoveTimer = 15000 + rand()%8000; + }else LoveTimer -= diff; + + if(SlashTimer < diff) + { + DoCast(m_creature->getVictim(),METEOR_SLASH); + SlashTimer = 11000; + }else SlashTimer -= diff; + + if(StompTimer < diff) + { + DoYell(YELL_CHARGE,LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_CHARGE); + Unit *Target = m_creature->getVictim(); + DoCast(Target,STOMP); + if(Target->HasAura(45151,0)) Target->RemoveAura(45151,0); + StompTimer = 30000; + }else StompTimer -= diff; + + if(BurnTimer < diff) + { + Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 0); + DoCast(target,BURN); + BurnTimer = 60000; + } + else BurnTimer -= diff; + + DoMeleeAttackIfReady(); + + if(BerserkTimer < diff) + { + DoYell(YELL_BERSERK,LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_BERSERK); + DoCast(m_creature,BERSERK); + BerserkTimer = 20000; + } + else BerserkTimer -= diff; + } + +}; + +CreatureAI* GetAI_boss_brutallus(Creature *_Creature) +{ + return new boss_brutallusAI (_Creature); +} + +void AddSC_boss_brutallus() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_brutallus"; + newscript->GetAI = GetAI_boss_brutallus; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_kalecgos.cpp b/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_kalecgos.cpp new file mode 100644 index 00000000000..6b35c91ac58 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_kalecgos.cpp @@ -0,0 +1,657 @@ +/* Copyright ? 2006,2007 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Kalecgos +SD%Complete: 0 +SDComment: VERIFY SCRIPT +SDCategory: Sunwell Plateau +EndScriptData */ + +#include "precompiled.h" +#include "WorldPacket.h" +#include "def_sunwell_plateau.h" + +#define SAY_KALECGOS_AGGRO "Aggh! No longer will I be a slave to Malygos! Challenge me and you will be destroyed!" +#define SOUND_KALECGOS_AGGRO 12422 +#define SAY_KALECGOS_SPELL1 "I will purge you!" +#define SOUND_KALECGOS_SPELL1 12423 +#define SAY_KALECGOS_SPELL2 "Your pain has only begun!" +#define SOUND_KALECGOS_SPELL2 12424 +#define SAY_KALECGOS_SLAY1 "In the name of Kil'jaeden!" +#define SOUND_KALECGOS_SLAY1 12425 +#define SAY_KALECGOS_SLAY2 "You were warned!" +#define SOUND_KALECGOS_SLAY2 12426 +#define SAY_KALECGOS_ENRAGE "My awakening is complete! You shall all perish!" +#define SOUND_KALECGOS_ENRAGE 12427 + +#define SAY_SATH_AGGRO "There will be no reprieve. My work here is nearly finished." +#define SOUND_SATH_AGGRO 12451 +#define SAY_SATH_DEATH "I'm... never on... the losing... side..." +#define SOUND_SATH_DEATH 12452 +#define SAY_SATH_SPELL1 "Your misery is my delight!" +#define SOUND_SATH_SPELL1 12453 +#define SAY_SATH_SPELL2 "I will watch you bleed!" +#define SOUND_SATH_SPELL2 12454 +#define SAY_SATH_SLAY1 "Pitious mortal!" +#define SOUND_SATH_SLAY1 12455 +#define SAY_SATH_SLAY2 "Haven't you heard? I always win!" +#define SOUND_SATH_SLAY2 12456 +#define SAY_SATH_ENRAGE "I have toyed with you long enough!" +#define SOUND_SATH_ENRAGE 12457 + +#define SAY_KALEC_AGGRO "I need... your help... Cannot... resist him... much longer..." +#define SOUND_KALEC_AGGRO 12428 +#define SAY_KALEC_NEAR_DEATH "Aaahhh! Help me, before I lose my mind!" +#define SOUND_KALEC_NEAR_DEATH 12429 + //??? +#define SAY_KALEC_NEAR_DEATH2 "Hurry! There is not much of me left!" +#define SOUND_KALEC_NEAR_DEATH2 12430 +#define SAY_KALEC_PLRWIN "I am forever in your debt. Once we have triumphed over Kil'jaeden, this entire world will be in your debt as well." +#define SOUND_KALEC_PLRWIN 12431 + +#define SPELL_SPECTRAL_EXHAUSTION 44867 +#define SPELL_TELEPORT_SPECTRAL_REALM 46019 +#define SPELL_SPECTRAL_REALM 46021 + +#define NOTIFY_SPECTRALLY_EXHAUSTED "Your body is too exhausted to travel to the Spectral Realm." +#define ERROR_INST_DATA "SD2: Instance Data not set properly for Sunwell Plateau. Kalecgos Encounter will be buggy." +#define ERROR_INST_DATA_PLR "SD2 ERROR: Instance Data not set properly for Sunwell Plateau. Please report this to your administrator." +#define ERROR_UNABLE_TO_TELEPORT "SD2: Unable to select target for Spectral Blast. Threatlist has too few players." +#define ERROR_MISSING_TELEPORT_GUID "SD2: [Kalecgos] Invalid TeleportTargetGUID. Unable to teleport player." +#define ERROR_KALECGOS_NOT_FOUND "SD2: Unable to create pointer to Kalecgos from Sathrovarr." + +#define KALECGOS_ARENA_X 1704.34 +#define KALECGOS_ARENA_Y 928.17 +#define KALECGOS_ARENA_Z 53.08 + +/*** Kalecgos ****/ +#define SPELL_SPECTRAL_BLAST 44866 +#define SPELL_ARCANE_BUFFET 45018 +#define SPELL_FROST_BREATH 44799 +#define SPELL_HEROIC_STRIKE 45026 +#define SPELL_REVITALIZE 45027 +#define SPELL_TAIL_LASH 45122 +#define SPELL_TRANSFORM_KALEC 45027 +#define SPELL_CRAZED_RAGE 44806 +uint32 WildMagic[]= { 44978, 45001, 45002, 45004, 45006, 45010 }; + +/*** Sathrovarr ***/ +#define SPELL_CORRUPTING_STRIKE 45029 +#define SPELL_CURSE_OF_BOUNDLESS_AGONY 45032 +#define SPELL_SHADOW_BOLT_VOLLEY 45031 + +/*** Misc ***/ +#define SPELL_BANISH 44836 + +void TeleportToInnerVeil(Player* plr) +{ + if(plr->HasAura(SPELL_SPECTRAL_EXHAUSTION, 0)) + { + plr->GetSession()->SendNotification(NOTIFY_SPECTRALLY_EXHAUSTED); + return; + } + + ScriptedInstance* pInstance = ((ScriptedInstance*)plr->GetInstanceData()); + if(!pInstance) + { + error_log(ERROR_INST_DATA); + plr->GetSession()->SendNotification(ERROR_INST_DATA_PLR); + return; + } + + pInstance->SetData64(DATA_PLAYER_SPECTRAL_REALM, plr->GetGUID()); + // Remove the player from Kalecgos' Threat List + Creature* Kalecgos = ((Creature*)Unit::GetUnit(*plr, pInstance->GetData64(DATA_KALECGOS_DRAGON))); + if(Kalecgos) + { + HostilReference* ref = Kalecgos->getThreatManager().getOnlineContainer().getReferenceByTarget(plr); + if(ref) + ref->removeReference(); + } + + // Add the player to Sathrovarr's Threat List + Creature* Sathrovarr = ((Creature*)Unit::GetUnit(*plr, pInstance->GetData64(DATA_SATHROVARR))); + if(Sathrovarr) + Sathrovarr->AddThreat(plr, 1.0f); + + // Make them able to see Sathrovarr (he's invisible for some reason). Also, when this buff wears off, they get teleported back to Normal Realm (this is handled by Instance Script) + plr->CastSpell(plr, SPELL_SPECTRAL_REALM, true); + plr->CastSpell(plr, SPELL_TELEPORT_SPECTRAL_REALM, true); +} + +bool GOHello_GO_Spectral_Portal(Player* plr, GameObject* go) +{ + TeleportToInnerVeil(plr); + + return true; +} + +struct MANGOS_DLL_DECL boss_kalecgosAI : public ScriptedAI +{ + boss_kalecgosAI(Creature* c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + + uint64 TeleportTargetGUID; + + uint32 ArcaneBuffetTimer; + uint32 FrostBreathTimer; + uint32 WildMagicTimer; + uint32 SpectralBlastTimer; + uint32 SpectralTeleportTimer; + uint32 ForceFieldTimer; + uint32 ExitTimer; + + bool LockedArena; + bool Uncorrupted; + bool Banished; + bool Checked; + bool Enraged; + + void Reset() + { + TeleportTargetGUID = 0; + + // TODO: Fix timers + ArcaneBuffetTimer = 8000; + FrostBreathTimer = 24000; + WildMagicTimer = 18000; + SpectralBlastTimer = 30000; + SpectralTeleportTimer = SpectralBlastTimer + 2000; + + ForceFieldTimer = 20000; + ExitTimer = 0; + + LockedArena = false; + Uncorrupted = false; + Banished = false; + Checked = false; + Enraged = false; + + // Reset Sathrovarr too + if(pInstance) + if(Creature* Sath = ((Creature*)Unit::GetUnit(*m_creature, pInstance->GetData64(DATA_SATHROVARR)))) + Sath->AI()->EnterEvadeMode(); + } + + void Aggro(Unit* who) + { + DoYell(SAY_KALECGOS_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_KALECGOS_AGGRO); + + if(pInstance) + pInstance->SetData(DATA_KALECGOS_EVENT, IN_PROGRESS); + } + + void DamageTaken(Unit* done_by, uint32 &damage) + { + if(damage > m_creature->GetHealth() && done_by != m_creature) + { + if(!Uncorrupted) + { + damage = 0; + Banished = true; + DoCast(m_creature, SPELL_BANISH, true); + m_creature->GetMotionMaster()->MoveIdle(); + } + else + { + damage = 0; + BeginOutro(); + } + } + } + + void KilledUnit(Unit* victim) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_KALECGOS_SLAY1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_KALECGOS_SLAY1); + break; + case 1: + DoYell(SAY_KALECGOS_SLAY2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_KALECGOS_SLAY2); + break; + } + } + + void BeginOutro() + { + debug_log("SD2: KALEC: Beginning Outro"); + + if(!pInstance) + { + error_log(ERROR_INST_DATA); + return; + } + + Unit* Sathrovarr = Unit::GetUnit(*m_creature, pInstance->GetData64(DATA_SATHROVARR)); + if(Sathrovarr) + { + Sathrovarr->DealDamage(Sathrovarr, Sathrovarr->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + + Sathrovarr->Relocate(KALECGOS_ARENA_X, KALECGOS_ARENA_Y, KALECGOS_ARENA_Z); + Sathrovarr->SendMonsterMove(KALECGOS_ARENA_X, KALECGOS_ARENA_Y, KALECGOS_ARENA_Z, 0, 0, 0); + } + + Creature* Kalec = ((Creature*)Unit::GetUnit(*m_creature, pInstance->GetData64(DATA_KALECGOS_HUMAN))); + if(Kalec) + { + Kalec->DeleteThreatList(); + Kalec->SetVisibility(VISIBILITY_OFF); + } + + m_creature->GetMotionMaster()->MoveIdle(); + m_creature->setFaction(35); + } + + void MovementInform(uint32 type, uint32 id) + { + if(type != POINT_MOTION_TYPE) + return; + + if(id) + { + if(pInstance) + { + GameObject* ForceField = GameObject::GetGameObject(*m_creature, pInstance->GetData64(DATA_GO_FORCEFIELD)); + if(ForceField) + ForceField->SetGoState(1); + + pInstance->SetData(DATA_KALECGOS_EVENT, DONE); + } + else error_log(ERROR_INST_DATA); + + m_creature->SetVisibility(VISIBILITY_OFF); + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->getVictim() || !m_creature->SelectHostilTarget() || Banished) + return; + + if(((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 10) && !Enraged) + { + Unit* Sathrovarr = Unit::GetUnit(*m_creature, pInstance->GetData64(DATA_SATHROVARR)); + if(Sathrovarr) + Sathrovarr->CastSpell(Sathrovarr, SPELL_CRAZED_RAGE, true); + DoCast(m_creature, SPELL_CRAZED_RAGE, true); + Enraged = true; + } + + if(((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 1) && !Checked) + { + Checked = true; + + if(!Uncorrupted) + { + Banished = true; + DoCast(m_creature, SPELL_BANISH, true); + m_creature->GetMotionMaster()->MoveIdle(); + } + else + BeginOutro(); + } + + if(ExitTimer) + if(ExitTimer <= diff) + { + debug_log("SD2: KALEC: Exiting the arena"); + DoYell(SAY_KALEC_PLRWIN, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_KALEC_PLRWIN); + m_creature->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT + MOVEMENTFLAG_LEVITATING); + float x, y, z; + float iniX, iniY, iniZ; + m_creature->GetPosition(iniX, iniY, iniZ); + m_creature->GetRandomPoint(iniX, iniY, iniZ, 30, x, y, z); + z = 70; + m_creature->GetMotionMaster()->MovePoint(1, x, y, z); + }else ExitTimer -= diff; + + if(!LockedArena) + if(ForceFieldTimer < diff) + { + if(pInstance) + { + GameObject* ForceField = GameObject::GetGameObject((*m_creature), pInstance->GetData64(DATA_GO_FORCEFIELD)); + if(ForceField) + ForceField->SetUInt32Value(GAMEOBJECT_STATE, 0); + + LockedArena = true; + }else error_log(ERROR_INST_DATA); + }else ForceFieldTimer -= diff; + + if(ArcaneBuffetTimer < diff) + { + if(rand()%3 == 0) + { + DoYell(SAY_KALECGOS_SPELL1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_KALECGOS_SPELL1); + } + DoCast(m_creature->getVictim(), SPELL_ARCANE_BUFFET); + ArcaneBuffetTimer = 20000; + }else ArcaneBuffetTimer -= diff; + + if(FrostBreathTimer < diff) + { + if(rand()%2 == 0) + { + DoYell(SAY_KALECGOS_SPELL2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_KALECGOS_SPELL2); + } + DoCast(m_creature->getVictim(), SPELL_FROST_BREATH); + FrostBreathTimer = 25000; + }else FrostBreathTimer -= diff; + + if(WildMagicTimer < diff) + { + DoCast(m_creature->getVictim(), WildMagic[rand()%6]); + WildMagicTimer = 19000; + }else WildMagicTimer -= diff; + + if(SpectralBlastTimer < diff) + { + if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1)) + { + TeleportTargetGUID = target->GetGUID(); + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, TeleportTargetGUID); + SpectralBlastTimer = 30000; + SpectralTeleportTimer = 2000; + } + }else SpectralBlastTimer -= diff; + + if(SpectralTeleportTimer < diff) + { + if(TeleportTargetGUID) + { + Unit* pUnit = Unit::GetUnit((*m_creature), TeleportTargetGUID); + if(pUnit) + { + pUnit->CastSpell(pUnit, SPELL_SPECTRAL_BLAST, true); + TeleportToInnerVeil((Player*)pUnit); + } + else error_log(ERROR_MISSING_TELEPORT_GUID); + } + else error_log(ERROR_MISSING_TELEPORT_GUID); + + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, m_creature->getVictim()->GetGUID()); + TeleportTargetGUID = 0; + SpectralTeleportTimer = SpectralBlastTimer + 2000; + + }else SpectralTeleportTimer -= diff; + + if(!Banished) DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL boss_sathrovarrAI : public ScriptedAI +{ + boss_sathrovarrAI(Creature* c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + + uint32 CorruptingStrikeTimer; + uint32 CurseOfBoundlessAgonyTimer; + uint32 ShadowBoltVolleyTimer; + bool Banished; + bool Enraged; + + void Reset() + { + // FIXME: Timers + CorruptingStrikeTimer = 5000; + CurseOfBoundlessAgonyTimer = 15000; + ShadowBoltVolleyTimer = 10000; + + Banished = false; + Enraged = false; + + DoCast(m_creature, SPELL_SPECTRAL_REALM, true); + } + + void Aggro(Unit* who) + { + DoYell(SAY_SATH_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SATH_AGGRO); + + Creature* Kalec = ((Creature*)Unit::GetUnit(*m_creature, pInstance->GetData64(DATA_KALECGOS_HUMAN))); + if(Kalec) + { + m_creature->AddThreat(Kalec, 10000000.0f); + Kalec->AddThreat(m_creature, 10000000.0f); + } + } + + void DamageTaken(Unit* done_by, uint32 &damage) + { + if(damage > m_creature->GetHealth()) + { + damage = 0; + DoCast(m_creature, SPELL_BANISH, true); + Banished = true; + + DoYell(SAY_SATH_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SATH_DEATH); + + if(!pInstance) + { + error_log(ERROR_INST_DATA); + return; + } + + pInstance->SetData(DATA_SET_SPECTRAL_CHECK, 5000); + + Creature* Kalecgos = ((Creature*)Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_KALECGOS_DRAGON))); + if(Kalecgos) + { + ((boss_kalecgosAI*)Kalecgos->AI())->Checked = false; + ((boss_kalecgosAI*)Kalecgos->AI())->Uncorrupted = true; + } + else error_log(ERROR_KALECGOS_NOT_FOUND); + } + } + + void KilledUnit(Unit* victim) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_SATH_SLAY1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_SATH_SLAY1); + break; + case 1: + DoYell(SAY_SATH_SLAY2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_SATH_SLAY2); + break; + } + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->getVictim() || !m_creature->SelectHostilTarget() || Banished) + return; + + if(((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 10) && !Enraged) + { + Unit* Kalecgos = Unit::GetUnit(*m_creature, pInstance->GetData64(DATA_KALECGOS_DRAGON)); + if(Kalecgos) + Kalecgos->CastSpell(Kalecgos, SPELL_CRAZED_RAGE, true); + DoCast(m_creature, SPELL_CRAZED_RAGE, true); + Enraged = true; + } + + if(CorruptingStrikeTimer < diff) + { + if(rand()%2 == 0) + { + DoYell(SAY_SATH_SPELL2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SATH_SPELL2); + } + DoCast(m_creature->getVictim(), SPELL_CORRUPTING_STRIKE); + CorruptingStrikeTimer = 13000; + }else CorruptingStrikeTimer -= diff; + + if(CurseOfBoundlessAgonyTimer < diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_CURSE_OF_BOUNDLESS_AGONY); + CurseOfBoundlessAgonyTimer = 35000; + DoCast(m_creature, SPELL_SPECTRAL_REALM, true); + }else CurseOfBoundlessAgonyTimer -= diff; + + if(ShadowBoltVolleyTimer < diff) + { + if(rand()%2 == 0) + { + DoYell(SAY_SATH_SPELL1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SATH_SPELL1); + } + DoCast(m_creature->getVictim(), SPELL_SHADOW_BOLT_VOLLEY); + ShadowBoltVolleyTimer = 15000; + }else ShadowBoltVolleyTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL boss_kalecAI : public ScriptedAI +{ + boss_kalecAI(Creature* c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance *pInstance; + + uint32 RevitalizeTimer; + uint32 HeroicStrikeTimer; + + bool HasYelled10Percent; + bool HasYelled20Percent; + + void Reset() + { + //TODO: Times! + RevitalizeTimer = 30000; + HeroicStrikeTimer = 8000; + + HasYelled10Percent = false; + HasYelled20Percent = false; + + DoCast(m_creature, SPELL_SPECTRAL_REALM, true); + } + + void Aggro(Unit* who) + { + DoYell(SAY_KALEC_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_KALEC_AGGRO); + } + + void JustDied(Unit* killer) + { + // Whatever happens when Kalec (Half-elf) dies + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->getVictim() || !m_creature->SelectHostilTarget()) + return; + + if(RevitalizeTimer < diff) + { + if(pInstance) + { + Unit* pUnit = Unit::GetUnit(*m_creature, pInstance->GetData64(DATA_RANDOM_SPECTRAL_PLAYER)); + if(pUnit) + DoCast(pUnit, SPELL_REVITALIZE); + RevitalizeTimer = 30000; + } + }else RevitalizeTimer -= diff; + + if(HeroicStrikeTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_HEROIC_STRIKE); + HeroicStrikeTimer = 30000; + }else HeroicStrikeTimer -= diff; + + if(((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 20) && !HasYelled20Percent) + { + DoYell(SAY_KALEC_NEAR_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_KALEC_NEAR_DEATH); + HasYelled20Percent = true; + } + + if(((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 10) && !HasYelled10Percent) + { + DoYell(SAY_KALEC_NEAR_DEATH2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_KALEC_NEAR_DEATH2); + HasYelled10Percent = true; + } + } +}; + +CreatureAI* GetAI_boss_kalecgos(Creature* c) +{ + return new boss_kalecgosAI(c); +} + +CreatureAI* GetAI_boss_sathrovarr(Creature* c) +{ + return new boss_sathrovarrAI(c); +} + +CreatureAI* GetAI_boss_kalec(Creature* c) +{ + return new boss_kalecAI(c); +} + +void AddSC_boss_kalecgos() +{ + Script* newscript; + + newscript = new Script; + newscript->GetAI = GetAI_boss_kalecgos; + newscript->Name = "boss_kalecgos"; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->GetAI = GetAI_boss_sathrovarr; + newscript->Name = "boss_sathrovarr"; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->GetAI = GetAI_boss_kalec; + newscript->Name = "boss_kalec"; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->pGOHello = GOHello_GO_Spectral_Portal; + newscript->Name = "go_spectral_portal"; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/sunwell_plateau/def_sunwell_plateau.h b/src/bindings/scripts/scripts/zone/sunwell_plateau/def_sunwell_plateau.h new file mode 100644 index 00000000000..316b13062f0 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/sunwell_plateau/def_sunwell_plateau.h @@ -0,0 +1,43 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_SUNWELLPLATEAU_H +#define DEF_SUNWELLPLATEAU_H + +/*** Encounters ***/ +#define DATA_KALECGOS_EVENT 0 +#define DATA_BRUTALLUS_EVENT 1 +#define DATA_FELMYST_EVENT 2 +#define DATA_EREDAR_TWINS_EVENT 3 +#define DATA_MURU_EVENT 4 +#define DATA_KILJAEDEN_EVENT 5 + +/*** Creatures ***/ +#define DATA_KALECGOS_DRAGON 6 +#define DATA_KALECGOS_HUMAN 7 +#define DATA_SATHROVARR 8 +#define DATA_BRUTALLUS 9 +#define DATA_FELMYST 10 +#define DATA_ALYTHESS 11 +#define DATA_SACROLASH 12 +#define DATA_MURU 13 +#define DATA_KILJAEDEN 14 +#define DATA_KILJAEDEN_CONTROLLER 15 +#define DATA_ANVEENA 16 + +/*** GameObjects ***/ +#define DATA_GO_FORCEFIELD 17 +#define DATA_GO_FIRE_BARRIER 18 +#define DATA_GATE_1 19 +#define DATA_GATE_2 20 +#define DATA_GATE_3 21 +#define DATA_GATE_4 22 +#define DATA_GATE_5 23 + +/*** Misc ***/ +#define DATA_PLAYER_SPECTRAL_REALM 24 +#define DATA_SET_SPECTRAL_CHECK 25 +#define DATA_RANDOM_SPECTRAL_PLAYER 26 +#define DATA_INST_EJECT_PLAYERS 27 +#endif diff --git a/src/bindings/scripts/scripts/zone/sunwell_plateau/instance_sunwell_plateau.cpp b/src/bindings/scripts/scripts/zone/sunwell_plateau/instance_sunwell_plateau.cpp new file mode 100644 index 00000000000..d5c419520ec --- /dev/null +++ b/src/bindings/scripts/scripts/zone/sunwell_plateau/instance_sunwell_plateau.cpp @@ -0,0 +1,275 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +/* ScriptData +SDName: instance_sunwell_plateau +SD%Complete: 0 +SDComment: VERIFY SCRIPT +SDCategory: Sunwell_Plateau +EndScriptData */ + +#include "precompiled.h" +#include "def_sunwell_plateau.h" + +#define ENCOUNTERS 6 + +#define SPELL_SPECTRAL_REALM 46021 +#define SPELL_TELEPORT_NORMAL_REALM 46020 +#define SPELL_SPECTRAL_EXHAUSTION 44867 + +/* Sunwell Plateau: +0 - Kalecgos and Sathrovarr +1 - Brutallus +2 - Felmyst +3 - Eredar Twins (Alythess and Sacrolash) +4 - M'uru +5 - Kil'Jaeden +*/ + +struct MANGOS_DLL_DECL instance_sunwell_plateau : public ScriptedInstance +{ + instance_sunwell_plateau(Map *Map) : ScriptedInstance(Map) {Initialize();}; + + uint32 Encounters[ENCOUNTERS]; + + /** Creatures **/ + uint64 Kalecgos_Dragon; + uint64 Kalecgos_Human; + uint64 Sathrovarr; + uint64 Brutallus; + uint64 Felmyst; + uint64 Alythess; + uint64 Sacrolash; + uint64 Muru; + uint64 KilJaeden; + uint64 KilJaedenController; + uint64 Anveena; + + /** GameObjects **/ + uint64 ForceField; // Kalecgos Encounter + uint64 FireBarrier; // Brutallus Encounter + uint64 Gate[5]; // Rename this to be more specific after door placement is verified. + + /*** Misc ***/ + uint32 SpectralRealmTimer; + std::vector SpectralRealmList; + + void Initialize() + { + /*** Creatures ***/ + Kalecgos_Dragon = 0; + Kalecgos_Human = 0; + Sathrovarr = 0; + Brutallus = 0; + Felmyst = 0; + Alythess = 0; + Sacrolash = 0; + Muru = 0; + KilJaeden = 0; + KilJaedenController = 0; + Anveena = 0; + + /*** GameObjects ***/ + ForceField = 0; + FireBarrier = 0; + Gate[0] = 0; // TODO: Rename Gate[n] with gate_ for better specificity + Gate[1] = 0; + Gate[2] = 0; + Gate[3] = 0; + Gate[4] = 0; + + /*** Encounters ***/ + for(uint8 i = 0; i < ENCOUNTERS; ++i) + Encounters[i] = NOT_STARTED; + + /*** Misc ***/ + SpectralRealmTimer = 5000; + } + + bool IsEncounterInProgress() const + { + for(uint8 i = 0; i < ENCOUNTERS; ++i) + if(Encounters[i] == IN_PROGRESS) + return true; + + return false; + } + + void OnCreatureCreate(Creature* creature, uint32 entry) + { + switch(entry) + { + case 24850: Kalecgos_Dragon = creature->GetGUID(); break; + case 24891: Kalecgos_Human = creature->GetGUID(); break; + case 24892: Sathrovarr = creature->GetGUID(); break; + case 24882: Brutallus = creature->GetGUID(); break; + case 25038: Felmyst = creature->GetGUID(); break; + case 25166: Alythess = creature->GetGUID(); break; + case 25165: Sacrolash = creature->GetGUID(); break; + case 25741: Muru = creature->GetGUID(); break; + case 25315: KilJaeden = creature->GetGUID(); break; + case 25608: KilJaedenController = creature->GetGUID(); break; + case 26046: Anveena = creature->GetGUID(); break; + } + } + + void OnObjectCreate(GameObject* gobj) + { + switch(gobj->GetEntry()) + { + case 188421: ForceField = gobj->GetGUID(); break; + case 188075: FireBarrier = gobj->GetGUID(); break; + case 187979: Gate[0] = gobj->GetGUID(); break; + case 187770: Gate[1] = gobj->GetGUID(); break; + case 187896: Gate[2] = gobj->GetGUID(); break; + case 187990: Gate[3] = gobj->GetGUID(); break; + case 188118: Gate[4] = gobj->GetGUID(); break; + } + } + + uint32 GetData(uint32 id) + { + switch(id) + { + case DATA_KALECGOS_EVENT: return Encounters[0]; break; + case DATA_BRUTALLUS_EVENT: return Encounters[1]; break; + case DATA_FELMYST_EVENT: return Encounters[2]; break; + case DATA_EREDAR_TWINS_EVENT: return Encounters[3]; break; + case DATA_MURU_EVENT: return Encounters[4]; break; + case DATA_KILJAEDEN_EVENT: return Encounters[5]; break; + } + + return 0; + } + + uint64 GetData64(uint32 id) + { + switch(id) + { + case DATA_KALECGOS_DRAGON: return Kalecgos_Dragon; break; + case DATA_KALECGOS_HUMAN: return Kalecgos_Human; break; + case DATA_SATHROVARR: return Sathrovarr; break; + case DATA_BRUTALLUS: return Brutallus; break; + case DATA_FELMYST: return Felmyst; break; + case DATA_ALYTHESS: return Alythess; break; + case DATA_SACROLASH: return Sacrolash; break; + case DATA_MURU: return Muru; break; + case DATA_KILJAEDEN: return KilJaeden; break; + case DATA_KILJAEDEN_CONTROLLER: return KilJaedenController; break; + case DATA_ANVEENA: return Anveena; break; + + case DATA_RANDOM_SPECTRAL_PLAYER: + return *(SpectralRealmList.begin() + rand()%SpectralRealmList.size()); + break; + } + return 0; + } + + void SetData(uint32 id, uint32 data) + { + switch(id) + { + case DATA_KALECGOS_EVENT: Encounters[0] = data; break; + case DATA_BRUTALLUS_EVENT: Encounters[1] = data; break; + case DATA_FELMYST_EVENT: Encounters[2] = data; break; + case DATA_EREDAR_TWINS_EVENT: Encounters[3] = data; break; + case DATA_MURU_EVENT: Encounters[4] = data; break; + case DATA_KILJAEDEN_EVENT: Encounters[5] = data; break; + + case DATA_SET_SPECTRAL_CHECK: SpectralRealmTimer = data; break; + case DATA_INST_EJECT_PLAYERS: EjectPlayers(); break; + } + } + + void SetData64(uint32 id, uint64 guid) + { + switch(id) + { + case DATA_PLAYER_SPECTRAL_REALM: + SpectralRealmList.push_back(guid); + break; + } + } + + // Dirty Hack as we can't use Unit::GetUnit in instance scripts due to lack of a WorldObject. + Player* DirtyHackToGetPlayerFromSpectralList(uint64 guid) + { + Player* first = ((InstanceMap*)instance)->GetPlayers().front(); + if(!first) + return NULL; + + Player* plr = ((Player*)Unit::GetUnit(*first, guid)); + if(plr) + return plr; + + return NULL; + } + + void EjectPlayer(Player* plr) + { + debug_log("SD2: INST: Ejecting Player %s from Spectral Realm", plr->GetName()); + // Remove player from Sathrovarr's threat list + Creature* Sath = ((Creature*)Unit::GetUnit(*plr, Sathrovarr)); + if(Sath && Sath->isAlive()) + { + HostilReference* ref = Sath->getThreatManager().getOnlineContainer().getReferenceByTarget(plr); + if(ref) + { + ref->removeReference(); + debug_log("SD2: INST: Deleting %s from Sathrovarr's threatlist", plr->GetName()); + } + } + + // Put player back in Kalecgos(Dragon)'s threat list + Creature* Kalecgos = ((Creature*)Unit::GetUnit(*plr, Kalecgos_Dragon)); + if(Kalecgos && Kalecgos->isAlive()) + { + debug_log("SD2: INST: Putting %s in Kalecgos' threatlist", plr->GetName()); + Kalecgos->AddThreat(plr, 1.0f); + } + + plr->CastSpell(plr, SPELL_TELEPORT_NORMAL_REALM, true); + plr->CastSpell(plr, SPELL_SPECTRAL_EXHAUSTION, true); + } + + void EjectPlayers() + { + for(uint8 i = 0; i < SpectralRealmList.size(); ++i) + { + Player* plr = DirtyHackToGetPlayerFromSpectralList(SpectralRealmList[i]); + if(plr && !plr->HasAura(SPELL_SPECTRAL_REALM, 0)) + { + EjectPlayer(plr); + SpectralRealmList.erase(SpectralRealmList.begin() + i); + } + } + + SpectralRealmList.clear(); + } + + void Update(uint32 diff) + { + // Only check for Spectral Realm if Kalecgos Encounter is running + if(Encounters[0] == IN_PROGRESS) + if(SpectralRealmTimer < diff) + { + EjectPlayers(); + SpectralRealmTimer = 5000; + }else SpectralRealmTimer -= diff; + } +}; + +InstanceData* GetInstanceData_instance_sunwell_plateau(Map* map) +{ + return new instance_sunwell_plateau(map); +} + +void AddSC_instance_sunwell_plateau() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_sunwell_plateau"; + newscript->GetInstanceData = GetInstanceData_instance_sunwell_plateau; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/tanaris/tanaris.cpp b/src/bindings/scripts/scripts/zone/tanaris/tanaris.cpp new file mode 100644 index 00000000000..a5e74587a51 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/tanaris/tanaris.cpp @@ -0,0 +1,402 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Tanaris +SD%Complete: 80 +SDComment: Quest support: 2954, 4005, 10277, 10279(Special flight path). Noggenfogger vendor +SDCategory: Tanaris +EndScriptData */ + +/* ContentData +mob_aquementas +npc_custodian_of_time +npc_marin_noggenfogger +npc_steward_of_time +npc_stone_watcher_of_norgannon +EndContentData */ + +#include "precompiled.h" +#include "../../npc/npc_escortAI.h" + +/*###### +## mob_aquementas +######*/ + +#define AGGRO_YELL_AQUE "Who dares awaken Aquementas?" + +#define SPELL_AQUA_JET 13586 +#define SPELL_FROST_SHOCK 15089 + +struct MANGOS_DLL_DECL mob_aquementasAI : public ScriptedAI +{ + mob_aquementasAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 SendItem_Timer; + uint32 SwitchFaction_Timer; + bool isFriendly; + + uint32 FrostShock_Timer; + uint32 AquaJet_Timer; + + void Reset() + { + SendItem_Timer = 0; + SwitchFaction_Timer = 10000; + m_creature->setFaction(35); + isFriendly = true; + + AquaJet_Timer = 5000; + FrostShock_Timer = 1000; + } + + void SendItem(Unit* receiver) + { + if (((Player*)receiver)->HasItemCount(11169,1,false) && + ((Player*)receiver)->HasItemCount(11172,11,false) && + ((Player*)receiver)->HasItemCount(11173,1,false) && + !((Player*)receiver)->HasItemCount(11522,1,true)) + { + ItemPosCountVec dest; + uint8 msg = ((Player*)receiver)->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, 11522, 1, false); + if( msg == EQUIP_ERR_OK ) + ((Player*)receiver)->StoreNewItem( dest, 11522, 1, true); + } + } + + void Aggro(Unit* who) + { + DoYell(AGGRO_YELL_AQUE,LANG_UNIVERSAL,who); + } + + void UpdateAI(const uint32 diff) + { + if( isFriendly ) + { + if( SwitchFaction_Timer < diff ) + { + m_creature->setFaction(91); + isFriendly = false; + }else SwitchFaction_Timer -= diff; + } + + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if( !isFriendly ) + { + if( SendItem_Timer < diff ) + { + if( m_creature->getVictim()->GetTypeId() == TYPEID_PLAYER ) + SendItem(m_creature->getVictim()); + SendItem_Timer = 5000; + }else SendItem_Timer -= diff; + } + + if( FrostShock_Timer < diff ) + { + DoCast(m_creature->getVictim(),SPELL_FROST_SHOCK); + FrostShock_Timer = 15000; + }else FrostShock_Timer -= diff; + + if( AquaJet_Timer < diff ) + { + DoCast(m_creature,SPELL_AQUA_JET); + AquaJet_Timer = 15000; + }else AquaJet_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_mob_aquementas(Creature *_Creature) +{ + return new mob_aquementasAI (_Creature); +} + +/*###### +## npc_custodian_of_time +######*/ + +#define WHISPER_CUSTODIAN_1 "Greetings, $N. I will guide you through the cavern. Please try and keep up." +#define WHISPER_CUSTODIAN_2 "We do not know if the Caverns of Time have always been accessible to mortals. Truly, it is impossible to tell as the Timeless One is in perpetual motion, changing our timeways as he sees fit. What you see now may very well not exist tomorrow. You may wake up and have no memory of this place." +#define WHISPER_CUSTODIAN_3 "It is strange, I know... Most mortals cannot actually comprehend what they see here, as often, what they see is not anchored within their own perception of reality." +#define WHISPER_CUSTODIAN_4 "Follow me, please." +#define WHISPER_CUSTODIAN_5 "There are only two truths to be found here: First, that time is chaotic, always in flux, and completely malleable and second, perception does not dictate reality." +#define WHISPER_CUSTODIAN_6 "As custodians of time, we watch over and care for Nozdormu's realm. The master is away at the moment, which means that attempts are being made to dramatically alter time. The master never meddles in the affairs of mortals but instead corrects the alterations made to time by others. He is reactionary in this regard." +#define WHISPER_CUSTODIAN_7 "For normal maintenance of time, the Keepers of Time are sufficient caretakers. We are able to deal with most ordinary disturbances. I speak of little things, such as rogue mages changing something in the past to elevate their status or wealth in the present." +#define WHISPER_CUSTODIAN_8 "These tunnels that you see are called timeways. They are infinite in number. The ones that currently exist in your reality are what the master has deemed as 'trouble spots.' These trouble spots may differ completely in theme but they always share a cause. That is, their existence is a result of the same temporal disturbance. Remember that should you venture inside one..." +#define WHISPER_CUSTODIAN_9 "This timeway is in great disarray! We have agents inside right now attempting to restore order. What information I have indicates that Thrall's freedom is in jeopardy. A malevolent organization known as the Infinite Dragonflight is trying to prevent his escape. I fear without outside assistance, all will be lost." +#define WHISPER_CUSTODIAN_10 "We have very little information on this timeway. Sa'at has been dispatched and is currently inside. The data we have gathered from his correspondence is that the Infinite Dragonflight are once again attempting to alter time. Could it be that the opening of the Dark Portal is being targeted for sabotage? Let us hope not..." +#define WHISPER_CUSTODIAN_11 "This timeway is currently collapsing. What that may hold for the past, present and future is currently unknown..." +#define WHISPER_CUSTODIAN_12 "The timeways are currently ranked in order from least catastrophic to most catastrophic. Note that they are all classified as catastrophic, meaning that any single one of these timeways collapsing would mean that your world would end. We only classify them in such a way so that the heroes and adventurers that are sent here know which timeway best suits their abilities." +#define WHISPER_CUSTODIAN_13 "All we know of this timeway is that it leads to Mount Hyjal. The Infinite Dragonflight have gone to great lengths to prevent our involvement. We know next to nothing, mortal. Soridormi is currently attempting to break through the timeway's defenses but has thus far been unsuccessful. You might be our only hope of breaking through and resolving the conflict." +#define WHISPER_CUSTODIAN_14 "Our time is at an end $N. I would wish you luck, if such a thing existed." + +struct MANGOS_DLL_DECL npc_custodian_of_timeAI : public npc_escortAI +{ + npc_custodian_of_timeAI(Creature *c) : npc_escortAI(c) { Reset(); } + + void WaypointReached(uint32 i) + { + Unit *pTemp = Unit::GetUnit(*m_creature,PlayerGUID); + if( !pTemp ) + return; + + switch( i ) + { + case 0: DoWhisper(WHISPER_CUSTODIAN_1, pTemp); break; + case 1: DoWhisper(WHISPER_CUSTODIAN_2, pTemp); break; + case 2: DoWhisper(WHISPER_CUSTODIAN_3, pTemp); break; + case 3: DoWhisper(WHISPER_CUSTODIAN_4, pTemp); break; + case 5: DoWhisper(WHISPER_CUSTODIAN_5, pTemp); break; + case 6: DoWhisper(WHISPER_CUSTODIAN_6, pTemp); break; + case 7: DoWhisper(WHISPER_CUSTODIAN_7, pTemp); break; + case 8: DoWhisper(WHISPER_CUSTODIAN_8, pTemp); break; + case 9: DoWhisper(WHISPER_CUSTODIAN_9, pTemp); break; + case 10: DoWhisper(WHISPER_CUSTODIAN_4, pTemp); break; + case 13: DoWhisper(WHISPER_CUSTODIAN_10, pTemp); break; + case 14: DoWhisper(WHISPER_CUSTODIAN_4, pTemp); break; + case 16: DoWhisper(WHISPER_CUSTODIAN_11, pTemp); break; + case 17: DoWhisper(WHISPER_CUSTODIAN_12, pTemp); break; + case 18: DoWhisper(WHISPER_CUSTODIAN_4, pTemp); break; + case 22: DoWhisper(WHISPER_CUSTODIAN_13, pTemp); break; + case 23: DoWhisper(WHISPER_CUSTODIAN_4, pTemp); break; + case 24: + DoWhisper(WHISPER_CUSTODIAN_14, pTemp); + DoCast(pTemp,34883); + //below here is temporary workaround, to be removed when spell works properly + ((Player*)pTemp)->AreaExploredOrEventHappens(10277); + break; + } + } + + void MoveInLineOfSight(Unit *who) + { + if( IsBeingEscorted ) + return; + + if( who->GetTypeId() == TYPEID_PLAYER ) + { + if( ((Player*)who)->HasAura(34877,1) && ((Player*)who)->GetQuestStatus(10277) == QUEST_STATUS_INCOMPLETE ) + { + float Radius = 10.0; + if( m_creature->IsWithinDistInMap(who, Radius) ) + { + ((npc_escortAI*)(m_creature->AI()))->Start(false, false, false, who->GetGUID()); + } + } + } + } + + void Aggro(Unit* who) { } + void Reset() { } + + void UpdateAI(const uint32 diff) + { + npc_escortAI::UpdateAI(diff); + } +}; + +CreatureAI* GetAI_npc_custodian_of_time(Creature *_Creature) +{ + npc_custodian_of_timeAI* custodian_of_timeAI = new npc_custodian_of_timeAI(_Creature); + + custodian_of_timeAI->AddWaypoint(0, -8374.93,-4250.21, -204.38,5000); + custodian_of_timeAI->AddWaypoint(1, -8374.93,-4250.21, -204.38,16000); + custodian_of_timeAI->AddWaypoint(2, -8374.93,-4250.21, -204.38,10000); + custodian_of_timeAI->AddWaypoint(3, -8374.93,-4250.21, -204.38,2000); + custodian_of_timeAI->AddWaypoint(4, -8439.40,-4180.05, -209.25); + custodian_of_timeAI->AddWaypoint(5, -8437.82,-4120.84, -208.59,10000); + custodian_of_timeAI->AddWaypoint(6, -8437.82,-4120.84, -208.59,16000); + custodian_of_timeAI->AddWaypoint(7, -8437.82,-4120.84, -208.59,13000); + custodian_of_timeAI->AddWaypoint(8, -8437.82,-4120.84, -208.59,18000); + custodian_of_timeAI->AddWaypoint(9, -8437.82,-4120.84, -208.59,15000); + custodian_of_timeAI->AddWaypoint(10, -8437.82,-4120.84, -208.59,2000); + custodian_of_timeAI->AddWaypoint(11, -8467.26,-4198.63, -214.21); + custodian_of_timeAI->AddWaypoint(12, -8667.76,-4252.13, -209.56); + custodian_of_timeAI->AddWaypoint(13, -8703.71,-4234.58, -209.5,14000); + custodian_of_timeAI->AddWaypoint(14, -8703.71,-4234.58, -209.5,2000); + custodian_of_timeAI->AddWaypoint(15, -8642.81,-4304.37, -209.57); + custodian_of_timeAI->AddWaypoint(16, -8649.06,-4394.36, -208.46,6000); + custodian_of_timeAI->AddWaypoint(17, -8649.06,-4394.36, -208.46,18000); + custodian_of_timeAI->AddWaypoint(18, -8649.06,-4394.36, -208.46,2000); + custodian_of_timeAI->AddWaypoint(19, -8468.72,-4437.67, -215.45); + custodian_of_timeAI->AddWaypoint(20, -8427.54,-4426, -211.13); + custodian_of_timeAI->AddWaypoint(21, -8364.83,-4393.32, -205.91); + custodian_of_timeAI->AddWaypoint(22, -8304.54,-4357.2, -208.2,18000); + custodian_of_timeAI->AddWaypoint(23, -8304.54,-4357.2, -208.2,2000); + custodian_of_timeAI->AddWaypoint(24, -8375.42,-4250.41, -205.14,5000); + custodian_of_timeAI->AddWaypoint(25, -8375.42,-4250.41, -205.14,5000); + + return (CreatureAI*)custodian_of_timeAI; +} + +/*###### +## npc_marin_noggenfogger +######*/ + +bool GossipHello_npc_marin_noggenfogger(Player *player, Creature *_Creature) +{ + if( _Creature->isQuestGiver() ) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if( _Creature->isVendor() && player->GetQuestRewardStatus(2662) ) + player->ADD_GOSSIP_ITEM(1, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_marin_noggenfogger(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + if( action == GOSSIP_ACTION_TRADE ) + player->SEND_VENDORLIST( _Creature->GetGUID() ); + + return true; +} + +/*###### +## npc_steward_of_time +######*/ + +#define GOSSIP_ITEM_FLIGHT "Please take me to the master's lair." + +bool GossipHello_npc_steward_of_time(Player *player, Creature *_Creature) +{ + if( _Creature->isQuestGiver() ) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if( player->GetQuestStatus(10279) == QUEST_STATUS_INCOMPLETE || player->GetQuestRewardStatus(10279) ) + { + player->ADD_GOSSIP_ITEM(0, GOSSIP_ITEM_FLIGHT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->SEND_GOSSIP_MENU(9978,_Creature->GetGUID()); + } + else + player->SEND_GOSSIP_MENU(9977,_Creature->GetGUID()); + + return true; +} + +bool QuestAccept_npc_steward_of_time(Player *player, Creature *creature, Quest const *quest ) +{ + if( quest->GetQuestId() == 10279 ) //Quest: To The Master's Lair + player->CastSpell(player,34891,true); //(Flight through Caverns) + + return false; +} + +bool GossipSelect_npc_steward_of_time(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if( action == GOSSIP_ACTION_INFO_DEF + 1 ) + player->CastSpell(player,34891,true); //(Flight through Caverns) + + return true; +} + +/*###### +## npc_stone_watcher_of_norgannon +######*/ + +#define GOSSIP_ITEM_NORGANNON_1 "What function do you serve?" +#define GOSSIP_ITEM_NORGANNON_2 "What are the Plates of Uldum?" +#define GOSSIP_ITEM_NORGANNON_3 "Where are the Plates of Uldum?" +#define GOSSIP_ITEM_NORGANNON_4 "Excuse me? We've been \"reschedueled for visitations\"? What does that mean?!" +#define GOSSIP_ITEM_NORGANNON_5 "So, what's inside Uldum?" +#define GOSSIP_ITEM_NORGANNON_6 "I will return when i have the Plates of Uldum." + +bool GossipHello_npc_stone_watcher_of_norgannon(Player *player, Creature *_Creature) +{ + if( _Creature->isQuestGiver() ) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if( player->GetQuestStatus(2954) == QUEST_STATUS_INCOMPLETE ) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_NORGANNON_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + player->SEND_GOSSIP_MENU(1674, _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_stone_watcher_of_norgannon(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_NORGANNON_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + player->SEND_GOSSIP_MENU(1675, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+1: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_NORGANNON_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + player->SEND_GOSSIP_MENU(1676, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_NORGANNON_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + player->SEND_GOSSIP_MENU(1677, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_NORGANNON_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + player->SEND_GOSSIP_MENU(1678, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_NORGANNON_6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + player->SEND_GOSSIP_MENU(1679, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + player->CLOSE_GOSSIP_MENU(); + player->AreaExploredOrEventHappens(2954); + break; + } + return true; +} + +/*###### +## AddSC +######*/ + +void AddSC_tanaris() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="mob_aquementas"; + newscript->GetAI = GetAI_mob_aquementas; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_custodian_of_time"; + newscript->GetAI = GetAI_npc_custodian_of_time; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_marin_noggenfogger"; + newscript->pGossipHello = &GossipHello_npc_marin_noggenfogger; + newscript->pGossipSelect = &GossipSelect_npc_marin_noggenfogger; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_steward_of_time"; + newscript->pGossipHello = &GossipHello_npc_steward_of_time; + newscript->pGossipSelect = &GossipSelect_npc_steward_of_time; + newscript->pQuestAccept = &QuestAccept_npc_steward_of_time; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_stone_watcher_of_norgannon"; + newscript->pGossipHello = &GossipHello_npc_stone_watcher_of_norgannon; + newscript->pGossipSelect = &GossipSelect_npc_stone_watcher_of_norgannon; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/tempest_keep/arcatraz/arcatraz.cpp b/src/bindings/scripts/scripts/zone/tempest_keep/arcatraz/arcatraz.cpp new file mode 100644 index 00000000000..abff86b24dd --- /dev/null +++ b/src/bindings/scripts/scripts/zone/tempest_keep/arcatraz/arcatraz.cpp @@ -0,0 +1,612 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Arcatraz +SD%Complete: 60 +SDComment: Warden Mellichar, event controller for Skyriss event. Millhouse Manastorm. TODO: make better combatAI for Millhouse. +SDCategory: Tempest Keep, The Arcatraz +EndScriptData */ + +/* ContentData +npc_millhouse_manastorm +npc_warden_mellichar +mob_zerekethvoidzone +EndContentData */ + +#include "precompiled.h" +#include "def_arcatraz.h" + +/*##### +# npc_millhouse_manastorm +#####*/ + +#define SAY_INTRO_1 "Where in Bonzo's brass buttons am I? And who are-- yaaghh, that's one mother of a headache!" +#define SOUND_INTRO_1 11171 +#define SAY_INTRO_2 "\"Lowly\"? I don't care who you are friend, no one refers to the mighty Millhouse Manastorm as \"Lowly\"! I have no idea what goes on here, but I will gladly join your fight against this impudent imbecile! Prepare to defend yourself, cretin!" +#define SOUND_INTRO_2 11172 + +#define SAY_WATER "I just need to get some things ready first. You guys go ahead and get started. I need to summon up some water..." +#define SOUND_WATER 11173 + +#define SAY_BUFFS "Fantastic! Next, some protective spells. Yes! Now we're cookin'" +#define SOUND_BUFFS 11174 + +#define SAY_DRINK "And of course i'll need some mana. You guys are gonna love this, just wait." +#define SOUND_DRINK 11175 + +#define SAY_READY "Aaalllriiiight!! Who ordered up an extra large can of whoop-ass?" +#define SOUND_READY 11176 + +#define SAY_KILL_1 "I didn't even break a sweat on that one." +#define SOUND_KILL_1 11177 +#define SAY_KILL_2 "You guys, feel free to jump in anytime." +#define SOUND_KILL_2 11178 + +#define SAY_PYRO "I'm gonna light you up, sweet cheeks!" +#define SOUND_PYRO 11179 + +#define SAY_ICEBLOCK "Ice, ice, baby!" +#define SOUND_ICEBLOCK 11180 + +#define SAY_LOWHP "Heal me! Oh, for the love of all that is holy, HEAL me! I'm dying!" +#define SOUND_LOWHP 11181 + +#define SAY_DEATH "You'll be hearing from my lawyer..." +#define SOUND_DEATH 11182 + +#define SAY_COMPLETE "Who's bad? Who's bad? That's right: we bad!" +#define SOUND_COMPLETE 11183 + +#define SPELL_CONJURE_WATER 36879 +#define SPELL_ARCANE_INTELLECT 36880 +#define SPELL_ICE_ARMOR 36881 + +#define SPELL_ARCANE_MISSILES 33833 +#define SPELL_CONE_OF_COLD 12611 +#define SPELL_FIRE_BLAST 13341 +#define SPELL_FIREBALL 14034 +#define SPELL_FROSTBOLT 15497 +#define SPELL_PYROBLAST 33975 + +struct MANGOS_DLL_DECL npc_millhouse_manastormAI : public ScriptedAI +{ + npc_millhouse_manastormAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + + uint32 EventProgress_Timer; + uint32 Phase; + bool Init; + bool LowHp; + + uint32 Pyroblast_Timer; + uint32 Fireball_Timer; + + void Reset() + { + EventProgress_Timer = 2000; + LowHp = false; + Init = false; + Phase = 1; + + Pyroblast_Timer = 1000; + Fireball_Timer = 2500; + + if( pInstance ) + { + if( pInstance->GetData(TYPE_WARDEN_2) == DONE ) + Init = true; + + if( pInstance->GetData(TYPE_HARBINGERSKYRISS) == DONE ) + { + DoYell(SAY_COMPLETE,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_COMPLETE); + } + } + } + + void MoveInLineOfSight(Unit *who) + { + if( !m_creature->getVictim() && who->isTargetableForAttack() && ( m_creature->IsHostileTo( who )) && who->isInAccessablePlaceFor(m_creature) ) + { + if (m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = m_creature->GetAttackDistance(who); + if( m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->IsWithinLOSInMap(who) ) + { + DoStartAttackNoMovement(who); + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + if (!InCombat) + { + Aggro(who); + InCombat = true; + } + } + } + } + + void AttackStart(Unit* who) + { + if (who->isTargetableForAttack()) + { + DoStartAttackNoMovement(who); + + if (!InCombat) + { + Aggro(who); + InCombat = true; + } + } + } + + void Aggro(Unit *who) + { + } + + void KilledUnit(Unit *victim) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_KILL_1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_KILL_1); + break; + case 1: + DoYell(SAY_KILL_2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_KILL_2); + break; + } + } + + void JustDied(Unit *victim) + { + DoYell(SAY_DEATH,LANG_UNIVERSAL,0); + DoPlaySoundToSet(m_creature,SOUND_DEATH); + + /*for questId 10886 (heroic mode only) + if( pInstance && pInstance->GetData(TYPE_HARBINGERSKYRISS) != DONE ) + ->FailQuest();*/ + } + + void UpdateAI(const uint32 diff) + { + if( !Init ) + { + if( EventProgress_Timer < diff ) + { + if( Phase < 8 ) + { + switch( Phase ) + { + case 1: + DoYell(SAY_INTRO_1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_INTRO_1); + EventProgress_Timer = 18000; + break; + case 2: + DoYell(SAY_INTRO_2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_INTRO_2); + EventProgress_Timer = 18000; + break; + case 3: + DoYell(SAY_WATER,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_WATER); + DoCast(m_creature,SPELL_CONJURE_WATER); + EventProgress_Timer = 7000; + break; + case 4: + DoYell(SAY_BUFFS,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_BUFFS); + DoCast(m_creature,SPELL_ICE_ARMOR); + EventProgress_Timer = 7000; + break; + case 5: + DoYell(SAY_DRINK,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_DRINK); + DoCast(m_creature,SPELL_ARCANE_INTELLECT); + EventProgress_Timer = 7000; + break; + case 6: + DoYell(SAY_READY,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_READY); + EventProgress_Timer = 6000; + break; + case 7: + if( pInstance ) + pInstance->SetData(TYPE_WARDEN_2,DONE); + Init = true; + break; + } + ++Phase; + } + } else EventProgress_Timer -= diff; + } + + if( !m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if( !LowHp && ((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 20) ) + { + DoYell(SAY_LOWHP,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_LOWHP); + LowHp = true; + } + + if( Pyroblast_Timer < diff ) + { + if( m_creature->IsNonMeleeSpellCasted(false) ) + return; + + DoYell(SAY_PYRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_PYRO); + + DoCast(m_creature->getVictim(),SPELL_PYROBLAST); + Pyroblast_Timer = 40000; + }else Pyroblast_Timer -=diff; + + if( Fireball_Timer < diff ) + { + DoCast(m_creature->getVictim(),SPELL_FIREBALL); + Fireball_Timer = 4000; + }else Fireball_Timer -=diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_millhouse_manastorm(Creature *_Creature) +{ + return new npc_millhouse_manastormAI (_Creature); +} + +/*##### +# npc_warden_mellichar +#####*/ + +#define YELL_INTRO1 "I knew the prince would be angry but, I... I have not been myself. I had to let them out! The great one speaks to me, you see. Wait--outsiders. Kael'thas did not send you! Good... I'll just tell the prince you released the prisoners!" +#define SOUND_INTRO1 11222 + +#define YELL_INTRO2 "The naaru kept some of the most dangerous beings in existence here in these cells. Let me introduce you to another...." +#define SOUND_INTRO2 11223 + +#define YELL_RELEASE1 "Yes, yes... another! Your will is mine!" +#define SOUND_RELEASE1 11224 + +#define YELL_RELEASE2A "Behold another terrifying creature of incomprehensible power!" +#define SOUND_RELEASE2A 11225 +#define YELL_RELEASE2B "What is this? A lowly gnome? I will do better, O'great one." +#define SOUND_RELEASE2B 11226 + +#define YELL_RELEASE3 "Anarchy! Bedlam! Oh, you are so wise! Yes, I see it now, of course!" +#define SOUND_RELEASE3 11227 + +#define YELL_RELEASE4 "One final cell remains. Yes, O'great one, right away!" +#define SOUND_RELEASE4 11228 + +#define YELL_WELCOME "Welcome, O'great one. I am your humble servant." +#define SOUND_WELCOME 11229 + +//phase 2(acid mobs) +#define ENTRY_TRICKSTER 20905 +#define ENTRY_PH_HUNTER 20906 +//phase 3 +#define ENTRY_MILLHOUSE 20977 +//phase 4(acid mobs) +#define ENTRY_AKKIRIS 20908 +#define ENTRY_SULFURON 20909 +//phase 5(acid mobs) +#define ENTRY_TW_DRAK 20910 +#define ENTRY_BL_DRAK 20911 +//phase 6 +#define ENTRY_SKYRISS 20912 + +//TARGET_SCRIPT +#define SPELL_TARGET_ALPHA 36856 +#define SPELL_TARGET_BETA 36854 +#define SPELL_TARGET_DELTA 36857 +#define SPELL_TARGET_GAMMA 36858 +#define SPELL_TARGET_OMEGA 36852 +#define SPELL_BUBBLE_VISUAL 36849 + +struct MANGOS_DLL_DECL npc_warden_mellicharAI : public ScriptedAI +{ + npc_warden_mellicharAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + + bool IsRunning; + bool CanSpawn; + + uint32 EventProgress_Timer; + uint32 Phase; + + void Reset() + { + IsRunning = false; + CanSpawn = false; + + EventProgress_Timer = 22000; + Phase = 1; + + m_creature->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); + DoCast(m_creature,SPELL_TARGET_OMEGA); + + if( pInstance ) + pInstance->SetData(TYPE_HARBINGERSKYRISS,NOT_STARTED); + } + + void AttackStart(Unit* who) { } + + void MoveInLineOfSight(Unit *who) + { + if( IsRunning ) + return; + + if( !m_creature->getVictim() && who->isTargetableForAttack() && ( m_creature->IsHostileTo( who )) && who->isInAccessablePlaceFor(m_creature) ) + { + if (m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + return; + if (who->GetTypeId() != TYPEID_PLAYER) + return; + + float attackRadius = m_creature->GetAttackDistance(who)/10; + if( m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->IsWithinLOSInMap(who) ) + Aggro(who); + } + } + + void Aggro(Unit *who) + { + DoYell(YELL_INTRO1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_INTRO1); + //possibly wrong spell OR should also cast second spell to make bubble appear (visual for this spell appear to be the correct) + DoCast(m_creature,SPELL_BUBBLE_VISUAL); + + if( pInstance ) + { + pInstance->SetData(TYPE_HARBINGERSKYRISS,IN_PROGRESS); + IsRunning = true; + } + } + + uint32 CanProgress() + { + if( pInstance ) + { + if( Phase == 7 && pInstance->GetData(TYPE_WARDEN_4) == DONE ) + return true; + if( Phase == 6 && pInstance->GetData(TYPE_WARDEN_3) == DONE ) + return true; + if( Phase == 5 && pInstance->GetData(TYPE_WARDEN_2) == DONE ) + return true; + if( Phase == 4 ) + return true; + if( Phase == 3 && pInstance->GetData(TYPE_WARDEN_1) == DONE ) + return true; + if( Phase == 2 && pInstance->GetData(TYPE_HARBINGERSKYRISS) == IN_PROGRESS ) + return true; + if( Phase == 1 && pInstance->GetData(TYPE_HARBINGERSKYRISS) == IN_PROGRESS ) + return true; + return false; + } + return false; + } + + void DoPrepareForPhase() + { + if( pInstance ) + { + m_creature->InterruptNonMeleeSpells(true); + m_creature->RemoveSpellsCausingAura(SPELL_AURA_DUMMY); + + switch( Phase ) + { + case 2: + DoCast(m_creature,SPELL_TARGET_ALPHA); + pInstance->SetData(TYPE_WARDEN_1,IN_PROGRESS); + break; + case 3: + DoCast(m_creature,SPELL_TARGET_BETA); + pInstance->SetData(TYPE_WARDEN_2,IN_PROGRESS); + break; + case 5: + DoCast(m_creature,SPELL_TARGET_DELTA); + pInstance->SetData(TYPE_WARDEN_3,IN_PROGRESS); + break; + case 6: + DoCast(m_creature,SPELL_TARGET_GAMMA); + pInstance->SetData(TYPE_WARDEN_4,IN_PROGRESS); + break; + case 7: + pInstance->SetData(TYPE_WARDEN_5,IN_PROGRESS); + break; + default: + break; + } + CanSpawn = true; + } + } + + void UpdateAI(const uint32 diff) + { + if( !IsRunning ) + return; + + if( EventProgress_Timer < diff ) + { + if( pInstance ) + { + if( pInstance->GetData(TYPE_HARBINGERSKYRISS) == FAIL ) + Reset(); + } + + if( CanSpawn ) + { + //continue beam omega pod, unless we are about to summon skyriss + if( Phase != 7 ) + DoCast(m_creature,SPELL_TARGET_OMEGA); + + switch( Phase ) + { + case 2: + switch( rand()%2 ) + { + case 0: m_creature->SummonCreature(ENTRY_TRICKSTER,478.326,-148.505,42.56,3.19,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); break; + case 1: m_creature->SummonCreature(ENTRY_PH_HUNTER,478.326,-148.505,42.56,3.19,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); break; + } + break; + case 3: + m_creature->SummonCreature(ENTRY_MILLHOUSE,413.292,-148.378,42.56,6.27,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); + break; + case 4: + DoYell(YELL_RELEASE2B,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_RELEASE2B); + break; + case 5: + switch( rand()%2 ) + { + case 0: m_creature->SummonCreature(ENTRY_AKKIRIS,420.179,-174.396,42.58,0.02,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); break; + case 1: m_creature->SummonCreature(ENTRY_SULFURON,420.179,-174.396,42.58,0.02,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); break; + } + break; + case 6: + switch( rand()%2 ) + { + case 0: m_creature->SummonCreature(ENTRY_TW_DRAK,471.795,-174.58,42.58,3.06,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); break; + case 1: m_creature->SummonCreature(ENTRY_BL_DRAK,471.795,-174.58,42.58,3.06,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); break; + } + break; + case 7: + m_creature->SummonCreature(ENTRY_SKYRISS,445.763,-191.639,44.64,1.60,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); + DoYell(YELL_WELCOME,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_WELCOME); + break; + default: + break; + } + CanSpawn = false; + ++Phase; + } + if( CanProgress() ) + { + switch( Phase ) + { + case 1: + DoYell(YELL_INTRO2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_INTRO2); + EventProgress_Timer = 10000; + ++Phase; + break; + case 2: + DoYell(YELL_RELEASE1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_RELEASE1); + DoPrepareForPhase(); + EventProgress_Timer = 7000; + break; + case 3: + DoYell(YELL_RELEASE2A,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_RELEASE2A); + DoPrepareForPhase(); + EventProgress_Timer = 10000; + break; + case 4: + DoPrepareForPhase(); + EventProgress_Timer = 15000; + break; + case 5: + DoYell(YELL_RELEASE3,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_RELEASE3); + DoPrepareForPhase(); + EventProgress_Timer = 15000; + break; + case 6: + DoYell(YELL_RELEASE4,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_RELEASE4); + DoPrepareForPhase(); + EventProgress_Timer = 15000; + break; + case 7: + DoPrepareForPhase(); + EventProgress_Timer = 15000; + break; + default: + break; + } + } + } else EventProgress_Timer -= diff; + } +}; +CreatureAI* GetAI_npc_warden_mellichar(Creature *_Creature) +{ + return new npc_warden_mellicharAI (_Creature); +} + +/*##### +# mob_zerekethvoidzone (this script probably not needed in future -> `creature_template_addon`.`auras`='36120 0') +#####*/ + +#define SPELL_VOID_ZONE_DAMAGE 36120 + +struct MANGOS_DLL_DECL mob_zerekethvoidzoneAI : public ScriptedAI +{ + mob_zerekethvoidzoneAI(Creature *c) : ScriptedAI(c) {Reset();} + + void Reset() + { + m_creature->SetUInt32Value(UNIT_NPC_FLAGS,0); + m_creature->setFaction(16); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + DoCast(m_creature,SPELL_VOID_ZONE_DAMAGE); + } + + void Aggro(Unit* who) {} +}; +CreatureAI* GetAI_mob_zerekethvoidzoneAI(Creature *_Creature) +{ + return new mob_zerekethvoidzoneAI (_Creature); +} + +void AddSC_arcatraz() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npc_millhouse_manastorm"; + newscript->GetAI = GetAI_npc_millhouse_manastorm; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_warden_mellichar"; + newscript->GetAI = GetAI_npc_warden_mellichar; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_zerekethvoidzone"; + newscript->GetAI = GetAI_mob_zerekethvoidzoneAI; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/tempest_keep/arcatraz/boss_harbinger_skyriss.cpp b/src/bindings/scripts/scripts/zone/tempest_keep/arcatraz/boss_harbinger_skyriss.cpp new file mode 100644 index 00000000000..650a6a8979e --- /dev/null +++ b/src/bindings/scripts/scripts/zone/tempest_keep/arcatraz/boss_harbinger_skyriss.cpp @@ -0,0 +1,380 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Harbinger_Skyriss +SD%Complete: 45 +SDComment: CombatAI not fully implemented. Timers will need adjustments. Need better method to "kill" the warden. Need more docs on how event fully work. Reset all event and force start over if fail at one point? +SDCategory: Tempest Keep, The Arcatraz +EndScriptData */ + +/* ContentData +boss_harbinger_skyriss +boss_harbinger_skyriss_illusion +EndContentData */ + +#include "precompiled.h" +#include "def_arcatraz.h" + +#define SAY_INTRO "It is a small matter to control the mind of the weak... for I bear allegiance to powers untouched by time, unmoved by fate. No force on this world or beyond harbors the strength to bend our knee... not even the mighty Legion!" +#define SOUND_INTRO 11122 + +#define SAY_AGGRO "Bear witness to the agent of your demise!" +#define SOUND_AGGRO 11123 + +#define SAY_KILL_1 "Your fate is written!" +#define SOUND_KILL_1 11124 +#define SAY_KILL_2 "The chaos I have sown here is but a taste...." +#define SOUND_KILL_2 11125 + +#define SAY_MIND_1 "You will do my bidding, weakling." +#define SOUND_MIND_1 11127 +#define SAY_MIND_2 "Your will is no longer your own." +#define SOUND_MIND_2 11128 + +#define SAY_FEAR_1 "Flee in terror!" +#define SOUND_FEAR_1 11129 +#define SAY_FEAR_2 "I will show you horrors undreamed of!" +#define SOUND_FEAR_2 11130 + +#define SAY_IMAGE "We span the universe, as countless as the stars!" +#define SOUND_IMAGE 11131 + +#define SAY_DEATH "I am merely one of... infinite multitudes." +#define SOUND_DEATH 11126 + +#define SPELL_FEAR 39415 + +#define SPELL_MIND_REND 36924 +#define H_SPELL_MIND_REND 39017 + +#define SPELL_DOMINATION 37162 +#define H_SPELL_DOMINATION 39019 + +#define H_SPELL_MANA_BURN 39020 + +#define SPELL_66_ILLUSION 36931 //entry 21466 +#define SPELL_33_ILLUSION 36932 //entry 21467 + +struct MANGOS_DLL_DECL boss_harbinger_skyrissAI : public ScriptedAI +{ + boss_harbinger_skyrissAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + HeroicMode = m_creature->GetMap()->IsHeroic(); + Reset(); + } + + ScriptedInstance *pInstance; + bool HeroicMode; + + bool Intro; + bool IsImage33; + bool IsImage66; + + uint32 Intro_Phase; + uint32 Intro_Timer; + uint32 MindRend_Timer; + uint32 Fear_Timer; + uint32 Domination_Timer; + uint32 ManaBurn_Timer; + + void Reset() + { + m_creature->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_UNKNOWN2); + + if( Intro ) + Intro = true; + else + Intro = false; + + IsImage33 = false; + IsImage66 = false; + + Intro_Phase = 1; + Intro_Timer = 5000; + MindRend_Timer = 3000; + Fear_Timer = 15000; + Domination_Timer = 30000; + ManaBurn_Timer = 25000; + } + + void MoveInLineOfSight(Unit *who) + { + if( !Intro ) + return; + + if( !m_creature->getVictim() && who->isTargetableForAttack() && ( m_creature->IsHostileTo( who )) && who->isInAccessablePlaceFor(m_creature) ) + { + if (m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = m_creature->GetAttackDistance(who); + if( m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->IsWithinLOSInMap(who) ) + { + DoStartAttackAndMovement(who); + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + if (!InCombat) + { + Aggro(who); + InCombat = true; + } + } + } + } + + void AttackStart(Unit* who) + { + if( !Intro ) + return; + + if( who->isTargetableForAttack() ) + { + DoStartAttackAndMovement(who); + + if( !InCombat ) + { + Aggro(who); + InCombat = true; + } + } + } + + void Aggro(Unit *who) + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_UNKNOWN2); + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_DEATH); + if( pInstance ) + pInstance->SetData(TYPE_HARBINGERSKYRISS,DONE); + } + + void KilledUnit(Unit* victim) + { + /*if( victim->GetEntry() == 21436 ) + return;*/ + + switch(rand()%2) + { + case 0: + DoYell(SAY_KILL_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_KILL_1); + break; + case 1: + DoYell(SAY_KILL_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_KILL_2); + break; + } + } + + void JustSummoned(Creature *summoned) + { + summoned->AI()->AttackStart(m_creature->getVictim()); + } + + void DoSplit(uint32 val) + { + if( m_creature->IsNonMeleeSpellCasted(false) ) + m_creature->InterruptNonMeleeSpells(false); + + DoYell(SAY_IMAGE, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_IMAGE); + + if( val == 66 ) + DoCast(m_creature, SPELL_66_ILLUSION); + else + DoCast(m_creature, SPELL_33_ILLUSION); + } + + void UpdateAI(const uint32 diff) + { + if( !Intro && !InCombat ) + { + if( !pInstance ) + return; + + if( Intro_Timer < diff ) + { + switch( Intro_Phase ) + { + case 1: + DoYell(SAY_INTRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_INTRO); + ++Intro_Phase; + Intro_Timer = 25000; + break; + case 2: + DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO); + if( Unit *mellic = Unit::GetUnit(*m_creature,pInstance->GetData64(DATA_MELLICHAR)) ) + { + //should have a better way to do this. possibly spell exist. + mellic->setDeathState(JUST_DIED); + mellic->SetHealth(0); + } + ++Intro_Phase; + Intro_Timer = 3000; + break; + case 3: + Intro = true; + break; + default: + break; + } + }else Intro_Timer -=diff; + } + + if( !m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if( !IsImage66 && ((m_creature->GetHealth()*100) / m_creature->GetMaxHealth() <= 66) ) + { + DoSplit(66); + IsImage66 = true; + } + if( !IsImage33 && ((m_creature->GetHealth()*100) / m_creature->GetMaxHealth() <= 33) ) + { + DoSplit(33); + IsImage33 = true; + } + + if( MindRend_Timer < diff ) + { + if( Unit* target = SelectUnit(SELECT_TARGET_RANDOM,1) ) + DoCast(target,HeroicMode ? H_SPELL_MIND_REND : SPELL_MIND_REND); + else + DoCast(m_creature->getVictim(),HeroicMode ? H_SPELL_MIND_REND : SPELL_MIND_REND); + + MindRend_Timer = 8000; + }else MindRend_Timer -=diff; + + if( Fear_Timer < diff ) + { + if( m_creature->IsNonMeleeSpellCasted(false) ) + return; + + switch(rand()%2) + { + case 0: + DoYell(SAY_FEAR_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_FEAR_1); + break; + case 1: + DoYell(SAY_FEAR_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_FEAR_2); + break; + } + + if( Unit* target = SelectUnit(SELECT_TARGET_RANDOM,1) ) + DoCast(target,SPELL_FEAR); + else + DoCast(m_creature->getVictim(),SPELL_FEAR); + + Fear_Timer = 25000; + }else Fear_Timer -=diff; + + if( Domination_Timer < diff ) + { + if( m_creature->IsNonMeleeSpellCasted(false) ) + return; + + switch(rand()%2) + { + case 0: + DoYell(SAY_MIND_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_MIND_1); + break; + case 1: + DoYell(SAY_MIND_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_MIND_2); + break; + } + + if( Unit* target = SelectUnit(SELECT_TARGET_RANDOM,1) ) + DoCast(target,HeroicMode ? H_SPELL_DOMINATION : SPELL_DOMINATION); + else + DoCast(m_creature->getVictim(),HeroicMode ? H_SPELL_DOMINATION : SPELL_DOMINATION); + + Domination_Timer = 16000+rand()%16000; + }else Domination_Timer -=diff; + + if( HeroicMode ) + { + if( ManaBurn_Timer < diff ) + { + if( m_creature->IsNonMeleeSpellCasted(false) ) + return; + + if( Unit* target = SelectUnit(SELECT_TARGET_RANDOM,1) ) + DoCast(target,H_SPELL_MANA_BURN); + + ManaBurn_Timer = 16000+rand()%16000; + }else ManaBurn_Timer -=diff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_harbinger_skyriss(Creature *_Creature) +{ + return new boss_harbinger_skyrissAI (_Creature); +} + +#define SPELL_MIND_REND_IMAGE 36929 +#define H_SPELL_MIND_REND_IMAGE 39021 + +struct MANGOS_DLL_DECL boss_harbinger_skyriss_illusionAI : public ScriptedAI +{ + boss_harbinger_skyriss_illusionAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + HeroicMode = m_creature->GetMap()->IsHeroic(); + Reset(); + } + + ScriptedInstance *pInstance; + bool HeroicMode; + + void Reset() { } + + void Aggro(Unit *who) { } +}; + +CreatureAI* GetAI_boss_harbinger_skyriss_illusion(Creature *_Creature) +{ + return new boss_harbinger_skyriss_illusionAI (_Creature); +} + +void AddSC_boss_harbinger_skyriss() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_harbinger_skyriss"; + newscript->GetAI = GetAI_boss_harbinger_skyriss; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_harbinger_skyriss_illusion"; + newscript->GetAI = GetAI_boss_harbinger_skyriss_illusion; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/tempest_keep/arcatraz/def_arcatraz.h b/src/bindings/scripts/scripts/zone/tempest_keep/arcatraz/def_arcatraz.h new file mode 100644 index 00000000000..8868a36d70c --- /dev/null +++ b/src/bindings/scripts/scripts/zone/tempest_keep/arcatraz/def_arcatraz.h @@ -0,0 +1,19 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_ARCATRAZ_H +#define DEF_ARCATRAZ_H + +#define TYPE_ZEREKETH 1 +#define TYPE_DALLIAH 2 +#define TYPE_SOCCOTHRATES 3 +#define TYPE_HARBINGERSKYRISS 4 +#define TYPE_WARDEN_1 5 +#define TYPE_WARDEN_2 6 +#define TYPE_WARDEN_3 7 +#define TYPE_WARDEN_4 8 +#define TYPE_WARDEN_5 9 + +#define DATA_MELLICHAR 10 +#endif diff --git a/src/bindings/scripts/scripts/zone/tempest_keep/arcatraz/instance_arcatraz.cpp b/src/bindings/scripts/scripts/zone/tempest_keep/arcatraz/instance_arcatraz.cpp new file mode 100644 index 00000000000..7fc1c573ab6 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/tempest_keep/arcatraz/instance_arcatraz.cpp @@ -0,0 +1,224 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Arcatraz +SD%Complete: 80 +SDComment: Mainly Harbringer Skyriss event +SDCategory: Tempest Keep, The Arcatraz +EndScriptData */ + +#include "precompiled.h" +#include "def_arcatraz.h" + +#define ENCOUNTERS 9 + +#define CONTAINMENT_CORE_SECURITY_FIELD_ALPHA 184318 //door opened when Wrath-Scryer Soccothrates dies +#define CONTAINMENT_CORE_SECURITY_FIELD_BETA 184319 //door opened when Dalliah the Doomsayer dies +#define POD_ALPHA 183961 //pod first boss wave +#define POD_BETA 183963 //pod second boss wave +#define POD_DELTA 183964 //pod third boss wave +#define POD_GAMMA 183962 //pod fourth boss wave +#define POD_OMEGA 183965 //pod fifth boss wave + +#define MELLICHAR 21436 //skyriss will kill this unit + +/* Arcatraz encounters: +1 - Zereketh the Unbound event +2 - Dalliah the Doomsayer event +3 - Wrath-Scryer Soccothrates event +4 - Harbinger Skyriss event, 5 sub-events +*/ + +struct MANGOS_DLL_DECL instance_arcatraz : public ScriptedInstance +{ + instance_arcatraz(Map *Map) : ScriptedInstance(Map) {Initialize();}; + + uint32 Encounter[ENCOUNTERS]; + + GameObject *Containment_Core_Security_Field_Alpha; + GameObject *Containment_Core_Security_Field_Beta; + GameObject *Pod_Alpha; + GameObject *Pod_Gamma; + GameObject *Pod_Beta; + GameObject *Pod_Delta; + GameObject *Pod_Omega; + + uint64 Mellichar; + + void Initialize() + { + Containment_Core_Security_Field_Alpha = NULL; + Containment_Core_Security_Field_Beta = NULL; + Pod_Alpha = NULL; + Pod_Beta = NULL; + Pod_Delta = NULL; + Pod_Gamma = NULL; + Pod_Omega = NULL; + + Mellichar = 0; + + for(uint8 i = 0; i < ENCOUNTERS; i++) + Encounter[i] = NOT_STARTED; + } + + bool IsEncounterInProgress() const + { + for(uint8 i = 0; i < ENCOUNTERS; i++) + if(Encounter[i]) return true; + + return false; + } + + void OnObjectCreate(GameObject *go) + { + switch(go->GetEntry()) + { + case CONTAINMENT_CORE_SECURITY_FIELD_ALPHA: Containment_Core_Security_Field_Alpha = go; break; + case CONTAINMENT_CORE_SECURITY_FIELD_BETA: Containment_Core_Security_Field_Beta = go; break; + case POD_ALPHA: Pod_Alpha = go; break; + case POD_BETA: Pod_Beta = go; break; + case POD_DELTA: Pod_Delta = go; break; + case POD_GAMMA: Pod_Gamma = go; break; + case POD_OMEGA: Pod_Omega = go; break; + } + } + + void OnCreatureCreate(Creature *creature, uint32 creature_entry) + { + switch(creature_entry) + { + case MELLICHAR: + Mellichar = creature->GetGUID(); + break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case TYPE_ZEREKETH: + Encounter[0] = data; + break; + + case TYPE_DALLIAH: + if( data == DONE ) + if( Containment_Core_Security_Field_Beta ) + Containment_Core_Security_Field_Beta->UseDoorOrButton(); + Encounter[1] = data; + break; + + case TYPE_SOCCOTHRATES: + if( data == DONE ) + if( Containment_Core_Security_Field_Alpha ) + Containment_Core_Security_Field_Alpha->UseDoorOrButton(); + Encounter[2] = data; + break; + + case TYPE_HARBINGERSKYRISS: + if( data == NOT_STARTED || data == FAIL ) + { + Encounter[4] = NOT_STARTED; + Encounter[5] = NOT_STARTED; + Encounter[6] = NOT_STARTED; + Encounter[7] = NOT_STARTED; + Encounter[8] = NOT_STARTED; + } + Encounter[3] = data; + break; + + case TYPE_WARDEN_1: + if( data == IN_PROGRESS ) + if( Pod_Alpha ) + Pod_Alpha->UseDoorOrButton(); + Encounter[4] = data; + break; + + case TYPE_WARDEN_2: + if( data == IN_PROGRESS ) + if( Pod_Beta ) + Pod_Beta->UseDoorOrButton(); + Encounter[5] = data; + break; + + case TYPE_WARDEN_3: + if( data == IN_PROGRESS ) + if( Pod_Delta ) + Pod_Delta->UseDoorOrButton(); + Encounter[6] = data; + break; + + case TYPE_WARDEN_4: + if( data == IN_PROGRESS ) + if( Pod_Gamma ) + Pod_Gamma->UseDoorOrButton(); + Encounter[7] = data; + break; + + case TYPE_WARDEN_5: + if( data == IN_PROGRESS ) + if( Pod_Omega ) + Pod_Omega->UseDoorOrButton(); + Encounter[8] = data; + break; + } + } + + uint32 GetData(uint32 data) + { + switch(data) + { + case TYPE_HARBINGERSKYRISS: + return Encounter[3]; + case TYPE_WARDEN_1: + return Encounter[4]; + case TYPE_WARDEN_2: + return Encounter[5]; + case TYPE_WARDEN_3: + return Encounter[6]; + case TYPE_WARDEN_4: + return Encounter[7]; + case TYPE_WARDEN_5: + return Encounter[8]; + } + return 0; + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_MELLICHAR: + return Mellichar; + } + return 0; + } +}; + +InstanceData* GetInstanceData_instance_arcatraz(Map* map) +{ + return new instance_arcatraz(map); +} + +void AddSC_instance_arcatraz() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_arcatraz"; + newscript->GetInstanceData = GetInstanceData_instance_arcatraz; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/tempest_keep/botanica/boss_high_botanist_freywinn.cpp b/src/bindings/scripts/scripts/zone/tempest_keep/botanica/boss_high_botanist_freywinn.cpp new file mode 100644 index 00000000000..3dfc0782512 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/tempest_keep/botanica/boss_high_botanist_freywinn.cpp @@ -0,0 +1,215 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_High_Botanist_Freywinn +SD%Complete: 90 +SDComment: some strange visual related to tree form(if aura lost before normal duration end). possible make summon&transform -process smoother(transform after delay) +SDCategory: Tempest Keep, The Botanica +EndScriptData */ + +#include "precompiled.h" + +#define SAY_AGGRO "What are you doing? These specimens are very delicate!" +#define SOUND_AGGRO 11144 + +#define SAY_KILL_1 "Your life cycle is now concluded!" +#define SOUND_KILL_1 11145 +#define SAY_KILL_2 "You will feed the worms." +#define SOUND_KILL_2 11146 + +#define SAY_TREE_1 "Endorel aluminor!" +#define SOUND_TREE_1 11147 +#define SAY_TREE_2 "Nature bends to my will!" +#define SOUND_TREE_2 11148 + +#define SAY_DEATH "The specimens...must be preserved." +#define SOUND_DEATH 11149 + +#define SPELL_TRANQUILITY 34550 +#define SPELL_TREE_FORM 34551 + +#define SPELL_SUMMON_FRAYER 34557 +#define ENTRY_FRAYER 19953 + +#define SPELL_PLANT_WHITE 34759 +#define SPELL_PLANT_GREEN 34761 +#define SPELL_PLANT_BLUE 34762 +#define SPELL_PLANT_RED 34763 + +struct MANGOS_DLL_DECL boss_high_botanist_freywinnAI : public ScriptedAI +{ + boss_high_botanist_freywinnAI(Creature *c) : ScriptedAI(c) { Reset(); } + + std::list Adds_List; + + uint32 SummonSeedling_Timer; + uint32 TreeForm_Timer; + uint32 MoveCheck_Timer; + uint32 DeadAddsCount; + bool MoveFree; + + void Reset() + { + Adds_List.clear(); + + SummonSeedling_Timer = 6000; + TreeForm_Timer = 30000; + MoveCheck_Timer = 1000; + DeadAddsCount = 0; + MoveFree = true; + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO); + } + + void JustSummoned(Creature *summoned) + { + if( summoned->GetEntry() == ENTRY_FRAYER ) + Adds_List.push_back(summoned->GetGUID()); + } + + void DoSummonSeedling() + { + switch(rand()%4) + { + case 0: DoCast(m_creature,SPELL_PLANT_WHITE); break; + case 1: DoCast(m_creature,SPELL_PLANT_GREEN); break; + case 2: DoCast(m_creature,SPELL_PLANT_BLUE); break; + case 3: DoCast(m_creature,SPELL_PLANT_RED); break; + } + } + + void KilledUnit(Unit* victim) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_KILL_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_KILL_1); + break; + case 1: + DoYell(SAY_KILL_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_KILL_2); + break; + } + } + + void UpdateAI(const uint32 diff) + { + if( !m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if( TreeForm_Timer < diff ) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_TREE_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_TREE_1); + break; + case 1: + DoYell(SAY_TREE_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_TREE_2); + break; + } + + if( m_creature->IsNonMeleeSpellCasted(false) ) + m_creature->InterruptNonMeleeSpells(true); + + m_creature->RemoveAllAuras(); + + DoCast(m_creature,SPELL_SUMMON_FRAYER,true); + DoCast(m_creature,SPELL_TRANQUILITY,true); + DoCast(m_creature,SPELL_TREE_FORM,true); + + m_creature->GetMotionMaster()->MoveIdle(); + MoveFree = false; + + TreeForm_Timer = 75000; + }else TreeForm_Timer -= diff; + + if( !MoveFree ) + { + if( MoveCheck_Timer < diff ) + { + if( !Adds_List.empty() ) + { + for(std::list::iterator itr = Adds_List.begin(); itr != Adds_List.end(); ++itr) + { + if( Unit *temp = Unit::GetUnit(*m_creature,*itr) ) + { + if( !temp->isAlive() ) + { + Adds_List.erase(itr); + ++DeadAddsCount; + break; + } + } + } + } + + if( DeadAddsCount < 3 && TreeForm_Timer-30000 < diff ) + DeadAddsCount = 3; + + if( DeadAddsCount >= 3 ) + { + Adds_List.clear(); + DeadAddsCount = 0; + + m_creature->InterruptNonMeleeSpells(true); + m_creature->RemoveAllAuras(); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + MoveFree = true; + } + MoveCheck_Timer = 500; + } + else MoveCheck_Timer -= diff; + + return; + } + + /*if( m_creature->HasAura(SPELL_TREE_FORM,0) || m_creature->HasAura(SPELL_TRANQUILITY,0) ) + return;*/ + + //one random seedling every 5 secs, but not in tree form + if( SummonSeedling_Timer < diff ) + { + DoSummonSeedling(); + SummonSeedling_Timer = 6000; + }else SummonSeedling_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_high_botanist_freywinn(Creature *_Creature) +{ + return new boss_high_botanist_freywinnAI (_Creature); +} + +void AddSC_boss_high_botanist_freywinn() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_high_botanist_freywinn"; + newscript->GetAI = GetAI_boss_high_botanist_freywinn; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/tempest_keep/botanica/boss_laj.cpp b/src/bindings/scripts/scripts/zone/tempest_keep/botanica/boss_laj.cpp new file mode 100644 index 00000000000..f0bc53e7264 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/tempest_keep/botanica/boss_laj.cpp @@ -0,0 +1,198 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Laj +SD%Complete: 95 +SDComment: Immunities _may_ be applied by spells, but this has _not_ been confirmed to be proper way. Most spells require database support. +SDCategory: Tempest Keep, The Botanica +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_ALLERGIC_REACTION 34697 +#define SPELL_TELEPORT_SELF 34673 + +#define SPELL_SUMMON_LASHER_1 34681 +#define SPELL_SUMMON_FLAYER_1 34682 +#define SPELL_SUMMON_LASHER_2 34684 +#define SPELL_SUMMON_FLAYER_2 34685 +#define SPELL_SUMMON_LASHER_3 34686 +#define SPELL_SUMMON_FLAYER_4 34687 +#define SPELL_SUMMON_LASHER_4 34688 +#define SPELL_SUMMON_FLAYER_3 34690 + +#define EMOTE_SUMMON "emits a strange noise." + +#define MODEL_DEFAULT 13109 +#define MODEL_ARCANE 14213 +#define MODEL_FIRE 13110 +#define MODEL_FROST 14112 +#define MODEL_NATURE 14214 + +struct MANGOS_DLL_DECL boss_lajAI : public ScriptedAI +{ + boss_lajAI(Creature *c) : ScriptedAI(c) { Reset(); } + + bool CanSummon; + uint32 Teleport_Timer; + uint32 Summon_Timer; + uint32 Transform_Timer; + uint32 Allergic_Timer; + + void Reset() + { + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID,MODEL_DEFAULT); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, true); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, false); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); + + CanSummon = false; + Teleport_Timer = 20000; + Summon_Timer = 2500; + Transform_Timer = 30000; + Allergic_Timer = 5000; + } + + void DoTransform() + { + switch(rand()%5) + { + case 0: + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID,MODEL_DEFAULT); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, true); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, false); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); + break; + case 1: + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID,MODEL_ARCANE); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, false); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, true); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); + break; + case 2: + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID,MODEL_FIRE); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, false); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, false); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); + break; + case 3: + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID,MODEL_FROST); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, false); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, false); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); + break; + case 4: + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID,MODEL_NATURE); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, false); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, false); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); + m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true); + break; + } + } + + void DoSummons() + { + switch(rand()%4) + { + case 0: + DoCast(m_creature,SPELL_SUMMON_LASHER_1,true); + DoCast(m_creature,SPELL_SUMMON_FLAYER_1,true); + break; + case 1: + DoCast(m_creature,SPELL_SUMMON_LASHER_2,true); + DoCast(m_creature,SPELL_SUMMON_FLAYER_2,true); + break; + case 2: + DoCast(m_creature,SPELL_SUMMON_LASHER_3,true); + DoCast(m_creature,SPELL_SUMMON_FLAYER_3,true); + break; + case 3: + DoCast(m_creature,SPELL_SUMMON_LASHER_4,true); + DoCast(m_creature,SPELL_SUMMON_FLAYER_4,true); + break; + } + CanSummon = false; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if( !m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if( CanSummon ) + { + if( Summon_Timer < diff ) + { + DoTextEmote(EMOTE_SUMMON,NULL); + DoSummons(); + Summon_Timer = 2500; + }else Summon_Timer -= diff; + } + + if( Allergic_Timer < diff ) + { + DoCast(m_creature->getVictim(),SPELL_ALLERGIC_REACTION); + Allergic_Timer = 25000+rand()%15000; + }else Allergic_Timer -= diff; + + if( Teleport_Timer < diff ) + { + DoCast(m_creature,SPELL_TELEPORT_SELF); + Teleport_Timer = 30000+rand()%10000; + CanSummon = true; + }else Teleport_Timer -= diff; + + if( Transform_Timer < diff ) + { + DoTransform(); + Transform_Timer = 25000+rand()%15000; + }else Transform_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_laj(Creature *_Creature) +{ + return new boss_lajAI (_Creature); +} + +void AddSC_boss_laj() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_laj"; + newscript->GetAI = GetAI_boss_laj; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/tempest_keep/botanica/boss_warp_splinter.cpp b/src/bindings/scripts/scripts/zone/tempest_keep/botanica/boss_warp_splinter.cpp new file mode 100644 index 00000000000..ed1f6458faa --- /dev/null +++ b/src/bindings/scripts/scripts/zone/tempest_keep/botanica/boss_warp_splinter.cpp @@ -0,0 +1,288 @@ +/* Copyright (C) 2006,2007 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Warp_Splinter +SD%Complete: 80 +SDComment: Includes Sapling (need some better control with these). Spells for boss possibly need some rework. +SDCategory: Tempest Keep, The Botanica +EndScriptData */ + +#include "precompiled.h" + +/*##### +# mob_treant (Sapling) +#####*/ + +struct MANGOS_DLL_DECL mob_treantAI : public ScriptedAI +{ + mob_treantAI (Creature *c) : ScriptedAI(c) + { + WarpGuid = 0; + Reset(); + } + + uint64 WarpGuid; + + void Reset() + { + m_creature->SetSpeed( MOVE_RUN, 0.5f, true); + m_creature->SetUnitMovementFlags(0); + } + + void Aggro(Unit *who) + { + return; + } + + void MoveInLineOfSight(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if (m_creature->getVictim()->GetGUID() != WarpGuid) + DoMeleeAttackIfReady(); + } +}; + +/*##### +# boss_warp_splinter +#####*/ + +#define WAR_STOMP 34716 +#define SUMMON_TREANTS 34727 // DBC: 34727, 34731, 34733, 34734, 34736, 34739, 34741 (with Ancestral Life spell 34742) // won't work (guardian summon) +#define ARCANE_VOLLEY 35059 //37078, 34785 //must additional script them (because Splinter eats them after 20 sec ^) +#define SPELL_HEAL_FATHER 6262 + +#define CREATURE_TREANT 19949 + +#define SAY_COMBAT_START "Who disturbs this sanctuary?" +#define SOUND_COMBAT_START 11230 + +#define SAY_SLAY_1 "You must die! But wait: this does not-- No, no... you must die!" +#define SOUND_SLAY_1 11231 +#define SAY_SLAY_2 "What am I doing? Why do I..." +#define SOUND_SLAY_2 11232 + +#define SAY_SUMMON_1 "Children, come to me!" +#define SOUND_SUMMON_1 11233 +#define SAY_SUMMON_2 "Maybe this is not-- No, we fight! Come to my aid." +#define SOUND_SUMMON_2 11234 + +#define SAY_DEATH "So... confused. Do not... belong here!" +#define SOUND_DEATH 11235 + +#define TREANT_SPAWN_DIST 50 //50 yards from Warp Splinter's spawn point + +float treant_pos[6][3] = +{ + {24.301233, 427.221100, -27.060635}, + {16.795492, 359.678802, -27.355425}, + {53.493484, 345.381470, -26.196192}, + {61.867096, 439.362732, -25.921030}, + {109.861877, 423.201630, -27.356019}, + {106.780159, 355.582581, -27.593357} +}; + +struct MANGOS_DLL_DECL boss_warp_splinterAI : public ScriptedAI +{ + boss_warp_splinterAI(Creature *c) : ScriptedAI(c) + { + Treant_Spawn_Pos_X = c->GetPositionX(); + Treant_Spawn_Pos_Y = c->GetPositionY(); + Reset(); + } + + uint32 War_Stomp_Timer; + uint32 Summon_Treants_Timer; + uint32 Arcane_Volley_Timer; + uint32 CheckTreantLOS_Timer; + uint32 TreantLife_Timer; + uint64 Treant_GUIDs[6]; + + float Treant_Spawn_Pos_X; + float Treant_Spawn_Pos_Y; + + + void Reset() + { + War_Stomp_Timer = 60000; + Summon_Treants_Timer = 45000; + Arcane_Volley_Timer = 140000; + CheckTreantLOS_Timer = 1000; + TreantLife_Timer = 999999; + + for(int i = 0; i < 6; ++i) + Treant_GUIDs[i] = 0; + + m_creature->SetSpeed( MOVE_RUN, 0.7f, true); + } + + void Aggro(Unit *who) + { + DoYell(SAY_COMBAT_START,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_COMBAT_START); + } + + // On Killed Unit + void KilledUnit(Unit* victim) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_SLAY_1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY_1); + break; + case 1: + DoYell(SAY_SLAY_2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY_2); + break; + } + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DEATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_DEATH); + } + + void SummonTreants() + { + for(int i = 0; i < 6; ++i) + { + float angle = (M_PI / 3) * i; + + float X = Treant_Spawn_Pos_X + TREANT_SPAWN_DIST * cos(angle); + float Y = Treant_Spawn_Pos_Y + TREANT_SPAWN_DIST * sin(angle); + //float Z = m_creature->GetMap()->GetHeight(X,Y, m_creature->GetPositionZ()); + //float Z = m_creature->GetPositionZ(); + float O = - m_creature->GetAngle(X,Y); + + Creature* pTreant = m_creature->SummonCreature(CREATURE_TREANT,treant_pos[i][0],treant_pos[i][1],treant_pos[i][2],O,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,40000); + if(pTreant) + { + //pTreant->GetMotionMaster()->Mutate(new TargetedMovementGenerator(*m_creature)); + pTreant->AddThreat(m_creature, 0.1f); + Treant_GUIDs[i] = pTreant->GetGUID(); + ((mob_treantAI*)pTreant->AI())->WarpGuid = m_creature->GetGUID(); + } + } + + switch(rand()%2) + { + case 0: + DoYell(SAY_SUMMON_1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_SUMMON_1); + break; + case 1: + DoYell(SAY_SUMMON_2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_SUMMON_2); + break; + } + } + + // Warp Splinter eat treants if they are near him + void EatTreant() + { + for( int i=0; i<6; ++i ) + { + Unit *pTreant = Unit::GetUnit(*m_creature, Treant_GUIDs[i]); + + if( pTreant ) + { + if( m_creature->IsWithinDistInMap(pTreant, 5)) + { + // 2) Heal Warp Splinter + int32 CurrentHP_Treant = (int32)pTreant->GetHealth(); + m_creature->CastCustomSpell(m_creature,SPELL_HEAL_FATHER,&CurrentHP_Treant, 0, 0, true,0 ,0, m_creature->GetGUID()); + + // 3) Kill Treant + pTreant->DealDamage(pTreant, pTreant->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + } + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //Check for War Stomp + if(War_Stomp_Timer < diff) + { + DoCast(m_creature->getVictim(),WAR_STOMP); + War_Stomp_Timer = 60000; + } + else War_Stomp_Timer -= diff; + + //Check for Arcane Volley + if(Arcane_Volley_Timer < diff) + { + DoCast(m_creature->getVictim(),ARCANE_VOLLEY); + Arcane_Volley_Timer = 40000+((rand()%20)*1000); + } + else Arcane_Volley_Timer -= diff; + + //Check for Summon Treants + if(Summon_Treants_Timer < diff) + { + SummonTreants(); + Summon_Treants_Timer = 45000; + } + else Summon_Treants_Timer -= diff; + + // I check if there is a Treant in Warp Splinter's LOS, so he can eat them + if( CheckTreantLOS_Timer < diff) + { + EatTreant(); + CheckTreantLOS_Timer = 1000; + } + else CheckTreantLOS_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_warp_splinter(Creature *_Creature) +{ + return new boss_warp_splinterAI (_Creature); +} + +CreatureAI* GetAI_mob_treant(Creature *_Creature) +{ + return new mob_treantAI (_Creature); +} + +void AddSC_boss_warp_splinter() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_warp_splinter"; + newscript->GetAI = GetAI_boss_warp_splinter; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_warp_splinter_treant"; + newscript->GetAI = GetAI_mob_treant; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_astromancer.cpp b/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_astromancer.cpp new file mode 100644 index 00000000000..c671343ad2c --- /dev/null +++ b/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_astromancer.cpp @@ -0,0 +1,563 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: boss_astromancer +SD%Complete: 75 +SDComment: +SDCategory: Tempest Keep, The Eye +EndScriptData */ + +#include "precompiled.h" +#include "def_the_eye.h" + +#define SPELL_ARCANE_MISSILES 33031 +#define SPELL_MARK_OF_THE_ASTROMANCER 33045 +#define MARK_OF_SOLARIAN 33023 +#define SPELL_BLINDING_LIGHT 33009 +#define SPELL_FEAR 29321 +#define SPELL_VOID_BOLT 39329 + +#define SAY_PHASE1 "Tal anu'men no Sin'dorei!" +#define SOUND_PHASE1 11134 +#define SAY_PHASE2 "I will crush your delusions of grandeur!" +#define SOUND_PHASE2 11140 +#define SAY_PHASE21 "Ha ha ha! You are hopelessly outmatched!" +#define SOUND_PHASE21 11139 + +#define SAY_VOID "Enough of this! Now I call upon the fury of the cosmos itself." +//#define SOUND_VOID Not found :( +#define SAY_VOID1 "I become ONE... with the VOID!" +//#define SOUND_VOID1 Not found :( + +#define SAY_KILL1 "Your soul belongs to the Abyss!" +#define SOUND_KILL1 11136 +#define SAY_KILL2 "By the blood of the Highborne!" +#define SOUND_KILL2 11137 +#define SAY_KILL3 "For the Sunwell!" +#define SOUND_KILL3 11138 +#define SAY_DEATH "The warmth of the sun... awaits." +#define SOUND_DEATH 11135 + +#define CENTER_X 432.909f +#define CENTER_Y -373.424f +#define CENTER_Z 17.9608f +#define CENTER_O 1.06421f +#define SMALL_PORTAL_RADIUS 12.6f +#define LARGE_PORTAL_RADIUS 26.0f +#define PORTAL_Z 17.005f + +#define SOLARIUM_AGENT 18925 +#define SOLARIUM_PRIEST 18806 +#define ASTROMANCER_SOLARIAN_SPOTLIGHT 18928 +#define SPELL_SPOTLIGHT 25824 +#define MODEL_HUMAN 18239 +#define MODEL_VOIDWALKER 18988 + +#define SOLARIUM_HEAL 41378 +#define SOLARIUM_SMITE 31740 +#define SOLARIUM_SILENCE 37160 + +#define WV_ARMOR 31000 +#define MIN_RANGE_FOR_DOT_JUMP 20.0f + +struct MANGOS_DLL_DECL boss_high_astromancer_solarianAI : public ScriptedAI +{ + boss_high_astromancer_solarianAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + + defaultarmor=m_creature->GetArmor(); + defaultsize=m_creature->GetFloatValue(OBJECT_FIELD_SCALE_X); + Reset(); + } + + ScriptedInstance *pInstance; + + uint32 ArcaneMissiles_Timer; + uint32 MarkOfTheAstromancer_Timer; + uint32 BlindingLight_Timer; + uint32 Fear_Timer; + uint32 VoidBolt_Timer; + uint32 Phase1_Timer; + uint32 Phase2_Timer; + uint32 Phase3_Timer; + uint32 AppearDelay_Timer; + uint32 MarkOfTheSolarian_Timer; + uint32 Jump_Timer; + uint32 defaultarmor; + + float defaultsize; + + bool AppearDelay; + + uint8 Phase; + + uint64 WrathTarget; + + float Portals[3][3]; + + void Reset() + { + WrathTarget=0; + ArcaneMissiles_Timer = 2000; + MarkOfTheAstromancer_Timer = 15000; + BlindingLight_Timer = 41000; + Fear_Timer = 20000; + VoidBolt_Timer = 10000; + Phase1_Timer = 50000; + Phase2_Timer = 10000; + Phase3_Timer = 15000; + AppearDelay_Timer = 2000; + AppearDelay = false; + MarkOfTheSolarian_Timer=45000; + Jump_Timer=8000; + Phase = 1; + + if(pInstance) + pInstance->SetData(DATA_HIGHASTROMANCERSOLARIANEVENT, NOT_STARTED); + + m_creature->SetArmor(defaultarmor); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetVisibility(VISIBILITY_ON); + m_creature->SetFloatValue(OBJECT_FIELD_SCALE_X, defaultsize); + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_HUMAN); + } + + void StartEvent() + { + DoYell(SAY_PHASE1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_PHASE1); + + if(pInstance) + pInstance->SetData(DATA_HIGHASTROMANCERSOLARIANEVENT, IN_PROGRESS); + } + + void KilledUnit(Unit *victim) + { + switch(rand()%3) + { + case 0: + DoYell(SAY_KILL1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_KILL1); + break; + case 1: + DoYell(SAY_KILL2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_KILL2); + break; + case 2: + DoYell(SAY_KILL3, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_KILL3); + break; + } + } + + void JustDied(Unit *victim) + { + m_creature->SetFloatValue(OBJECT_FIELD_SCALE_X, defaultsize); + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_HUMAN); + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_DEATH); + + if(pInstance) + pInstance->SetData(DATA_HIGHASTROMANCERSOLARIANEVENT, NOT_STARTED); + } + + void Aggro(Unit *who) + { + StartEvent(); + } + + void SummonMinion(uint32 entry, float x, float y, float z) + { + Creature* Summoned = m_creature->SummonCreature(entry, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + if(Summoned) + { + Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target) + Summoned->AI()->AttackStart(target); + } + } + + float Portal_X(float radius) + { + if ((rand()%2)==1) radius = -radius; + return (radius * (float)(rand()%100)/100.0f + CENTER_X); + } + + float Portal_Y(float x, float radius) + { + float z; + + switch(rand()%2) + { + case 0: z = 1; break; + case 1: z = -1; break; + } + return (z*sqrt(radius*radius - (x - CENTER_X)*(x - CENTER_X)) + CENTER_Y); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if (AppearDelay) + { + m_creature->StopMoving(); + m_creature->AttackStop(); + if (AppearDelay_Timer < diff) + { + AppearDelay = false; + if (Phase == 2) + { + switch (rand()%2) + { + case 0: + DoYell(SAY_PHASE2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_PHASE2); + break; + case 1: + DoYell(SAY_PHASE21, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_PHASE21); + break; + } + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetVisibility(VISIBILITY_OFF); + } + if (Phase == 3) + Phase = 1; + + AppearDelay_Timer = 2000; + }else AppearDelay_Timer -= diff; + } + + //the jumping of the dot part of the wrath of the astromancer + if(WrathTarget) + { + if(Jump_Timer< diff) + { + std::list& m_threatlist = m_creature->getThreatManager().getThreatList(); + bool hasJumped = false; + + Unit* target = Unit::GetUnit((*m_creature),WrathTarget); + if(target && target->isAlive()) + { + for(std::list::iterator iter = m_threatlist.begin();iter!=m_threatlist.end();++iter) + { + Unit* currentUnit=Unit::GetUnit((*m_creature),(*iter)->getUnitGuid()); + if(currentUnit) + { + if(currentUnit->IsWithinDistInMap(target,MIN_RANGE_FOR_DOT_JUMP)&¤tUnit->isAlive()&¤tUnit!=target) + { + m_creature->CastSpell(currentUnit,SPELL_MARK_OF_THE_ASTROMANCER, false,0,0,m_creature->GetGUID()); + + Jump_Timer=8000; + WrathTarget=currentUnit->GetGUID(); + hasJumped = true; + break; + } + } + } + } + + if(!hasJumped) + WrathTarget = 0; + }else Jump_Timer -= diff; + } + + if (Phase == 1) + { + //ArcaneMissiles_Timer + if (ArcaneMissiles_Timer < diff) + { + //Solarian casts Arcane Missiles on on random targets in the raid. + Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (!m_creature->HasInArc(2.5f, target)) + target = m_creature->getVictim(); + if (target) + DoCast(target, SPELL_ARCANE_MISSILES); + + ArcaneMissiles_Timer = 3000; + }else ArcaneMissiles_Timer -= diff; + + //MarkOfTheSolarian_Timer + if (MarkOfTheSolarian_Timer < diff) + { + DoCast(m_creature->getVictim(), MARK_OF_SOLARIAN); + MarkOfTheSolarian_Timer = 45000; + }else MarkOfTheSolarian_Timer -= diff; + + //MarkOfTheAstromancer_Timer + if (MarkOfTheAstromancer_Timer < diff) + { + //A debuff that lasts for 5 seconds, cast several times each phase on a random raid member, but not the main tank + Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1); + + if(target) + { + DoCast(target, SPELL_MARK_OF_THE_ASTROMANCER); + + WrathTarget=target->GetGUID(); + Jump_Timer=8000; + } + + MarkOfTheAstromancer_Timer = 15000; + }else MarkOfTheAstromancer_Timer -= diff; + + //BlindingLight_Timer + if (BlindingLight_Timer < diff) + { + //She casts this spell every 45 seconds. It is a kind of Moonfire spell, which she strikes down on the whole raid simultaneously. It hits everyone in the raid for 2280 to 2520 arcane damage. + DoCast(m_creature->getVictim(), SPELL_BLINDING_LIGHT); + + BlindingLight_Timer = 45000; + }else BlindingLight_Timer -= diff; + + //Phase1_Timer + if (Phase1_Timer < diff) + { + Phase = 2; + Phase1_Timer = 50000; + //After these 50 seconds she portals to the middle of the room and disappears, leaving 3 light portals behind. + m_creature->GetMotionMaster()->Clear(); + m_creature->Relocate(CENTER_X, CENTER_Y, CENTER_Z, CENTER_O); + for(int i=0; i<=2; i++) + { + if (!i) + { + Portals[i][0] = Portal_X(SMALL_PORTAL_RADIUS); + Portals[i][1] = Portal_Y(Portals[i][0], SMALL_PORTAL_RADIUS); + Portals[i][2] = CENTER_Z; + }else + { + Portals[i][0] = Portal_X(LARGE_PORTAL_RADIUS); + Portals[i][1] = Portal_Y(Portals[i][0], LARGE_PORTAL_RADIUS); + Portals[i][2] = PORTAL_Z; + } + } + if((abs(Portals[2][0] - Portals[1][0]) < 7) + && (abs(Portals[2][1] - Portals[1][1]) < 7)) + { + int i=1; + if(abs(CENTER_X + 26.0f - Portals[2][0]) < 7) + i = -1; + Portals[2][0] = Portals[2][0]+7*i; + Portals[2][1] = Portal_Y(Portals[2][0], LARGE_PORTAL_RADIUS); + } + for (int i=0; i<=2; i++) + { + Creature* Summoned = m_creature->SummonCreature(ASTROMANCER_SOLARIAN_SPOTLIGHT, Portals[i][0], Portals[i][1], Portals[i][2], CENTER_O, TEMPSUMMON_TIMED_DESPAWN, Phase2_Timer+Phase3_Timer+AppearDelay_Timer+1700); + if(Summoned) + { + Summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Summoned->CastSpell(Summoned, SPELL_SPOTLIGHT, false); + } + } + AppearDelay = true; + }else Phase1_Timer-=diff; + } + else if(Phase == 2) + { + //10 seconds after Solarian disappears, 12 mobs spawn out of the three portals. + m_creature->AttackStop(); + m_creature->StopMoving(); + if (Phase2_Timer < diff) + { + Phase = 3; + for (int i=0; i<=2; i++) + for (int j=1; j<=4; j++) + SummonMinion(SOLARIUM_AGENT, Portals[i][0], Portals[i][1], Portals[i][2]); + Phase2_Timer = 10000; + } else Phase2_Timer -= diff; + } + else if(Phase == 3) + { + //Check Phase3_Timer + if(Phase3_Timer < diff) + { + //15 seconds later Solarian reappears out of one of the 3 portals. Simultaneously, 2 healers appear in the two other portals. + m_creature->AttackStop(); + m_creature->StopMoving(); + int i = rand()%3; + m_creature->GetMotionMaster()->Clear(); + m_creature->Relocate(Portals[i][0], Portals[i][1], Portals[i][2], CENTER_O); + + for (int j=0; j<=2; j++) + if (j!=i) + SummonMinion(SOLARIUM_PRIEST, Portals[j][0], Portals[j][1], Portals[j][2]); + + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetVisibility(VISIBILITY_ON); + + DoYell(SAY_PHASE1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_PHASE1); + AppearDelay = true; + Phase3_Timer = 15000; + }else Phase3_Timer -= diff; + } + else if(Phase == 4) + { + //Fear_Timer + if (Fear_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_FEAR); + Fear_Timer = 20000; + }else Fear_Timer -= diff; + + //VoidBolt_Timer + if (VoidBolt_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_VOID_BOLT); + VoidBolt_Timer = 10000; + }else VoidBolt_Timer -= diff; + } + + //When Solarian reaches 20% she will transform into a huge void walker. + if(Phase != 4 && ((m_creature->GetHealth()*100 / m_creature->GetMaxHealth())<20)) + { + Phase = 4; + + //To make sure she wont be invisible or not selecatble + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetVisibility(VISIBILITY_ON); + switch(rand()%2) + { + case 0: + DoYell(SAY_VOID, LANG_UNIVERSAL, NULL); + break; + case 1: + DoYell(SAY_VOID1, LANG_UNIVERSAL, NULL); + break; + } + + m_creature->SetArmor(WV_ARMOR); + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_VOIDWALKER); + m_creature->SetFloatValue(OBJECT_FIELD_SCALE_X, defaultsize*2.5f); + } + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL mob_solarium_priestAI : public ScriptedAI +{ + mob_solarium_priestAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance *pInstance; + + uint32 healTimer; + uint32 holysmiteTimer; + uint32 aoesilenceTimer; + + void Reset() + { + healTimer = 9000; + holysmiteTimer = 1; + aoesilenceTimer = 15000; + } + + void Aggro(Unit *who) + { + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || m_creature->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + float attackRadius = m_creature->GetAttackDistance(who); + if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) + { + if(who->HasStealthAura()) + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + DoStartAttackAndMovement(who); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if (healTimer < diff) + { + Unit* target = NULL; + + switch(rand()%2) + { + case 0: + if(pInstance) + target = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_ASTROMANCER)); + break; + case 1: + target = m_creature; + break; + } + + if(target) + { + DoCast(target,SOLARIUM_HEAL); + healTimer = 9000; + } + } else healTimer -= diff; + + if(holysmiteTimer < diff) + { + DoCast(m_creature->getVictim(), SOLARIUM_SMITE); + holysmiteTimer = 4000; + } else holysmiteTimer -= diff; + + if (aoesilenceTimer < diff) + { + DoCast(m_creature->getVictim(), SOLARIUM_SILENCE); + aoesilenceTimer = 13000; + } else aoesilenceTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_solarium_priest(Creature *_Creature) +{ + return new mob_solarium_priestAI (_Creature); +} + +CreatureAI* GetAI_boss_high_astromancer_solarian(Creature *_Creature) +{ + return new boss_high_astromancer_solarianAI (_Creature); +} + +void AddSC_boss_high_astromancer_solarian() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_high_astromancer_solarian"; + newscript->GetAI = GetAI_boss_high_astromancer_solarian; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_solarium_priest"; + newscript->GetAI = GetAI_mob_solarium_priest; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_kaelthas.cpp b/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_kaelthas.cpp new file mode 100644 index 00000000000..4e88e44f799 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_kaelthas.cpp @@ -0,0 +1,1639 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: boss_Kaelthas +SD%Complete: 60 +SDComment: SQL, phase 2, phase 3, Mind Control, taunt immunity +SDCategory: Tempest Keep, The Eye +EndScriptData */ + +#include "precompiled.h" +#include "def_the_eye.h" +#include "WorldPacket.h" + +//Phase 2 spells (Not used) +#define SPELL_SUMMON_WEAPONS 36976 +#define SPELL_SUMMON_WEAPONA 36958 +#define SPELL_SUMMON_WEAPONB 36959 +#define SPELL_SUMMON_WEAPONC 36960 +#define SPELL_SUMMON_WEAPOND 36961 +#define SPELL_SUMMON_WEAPONE 36962 +#define SPELL_SUMMON_WEAPONF 36963 +#define SPELL_SUMMON_WEAPONG 36964 +#define SPELL_RES_VISUAL 24171 +#define SPELL_WEAPON_SPAWN 41236 +//Phase 4 spells +#define SPELL_FIREBALL 22088 //wrong but works with CastCustomSpell +#define SPELL_PYROBLAST 36819 +#define SPELL_FLAME_STRIKE 36735 +#define SPELL_FLAME_STRIKE_VIS 36730 +#define SPELL_FLAME_STRIKE_DMG 36731 +#define SPELL_ARCANE_DISRUPTION 36834 +#define SPELL_SHOCK_BARRIER 36815 +#define SPELL_PHOENIX_ANIMATION 36723 +#define SPELL_MIND_CONTROL 32830 +//Phase 5 spells +#define SPELL_EXPLODE 36092 +#define SPELL_FULLPOWER 36187 +#define SPELL_KNOCKBACK 11027 +#define SPELL_GRAVITY_LAPSE 34480 +#define SPELL_GRAVITY_LAPSE_AURA 39432 +#define SPELL_NETHER_BEAM 35873 +//Thaladred the Darkener spells +#define SPELL_PSYCHIC_BLOW 10689 +#define SPELL_SILENCE 30225 +//Lord Sanguinar spells +#define SPELL_BELLOWING_ROAR 40636 +//Grand Astromancer Capernian spells +#define CAPERNIAN_DISTANCE 20 //she casts away from the target +#define SPELL_CAPERNIAN_FIREBALL 36971 +#define SPELL_CONFLAGRATION 37018 +#define SPELL_ARCANE_EXPLOSION 36970 +//Master Engineer Telonicus spells +#define SPELL_BOMB 37036 +#define SPELL_REMOTE_TOY 37027 +//Nether Vapor spell +#define SPELL_NETHER_VAPOR 35859 +//Phoenix spell +#define SPELL_BURN 36721 + +//kael'thas Speech +#define SAY_INTRO "Energy. Power. My people are addicted to it... a dependence made manifest after the Sunwell was destroyed. Welcome... to the future. A pity you are too late to stop it. No one can stop me now! Selama ashal'anore!" +#define SOUND_INTRO 11256 + +#define SAY_ASTROMANCER_CAPERNIAN "Capernian will see to it that your stay here is a short one." +#define SOUND_ASTROMANCER_CAPERNIAN 11257 + +#define SAY_ENGINEER_TELONICUS "Well done, you have proven worthy to test your skills against my master engineer, Telonicus." +#define SOUND_ENGINEER_TELONICUS 11258 + +#define SAY_THALADRED_THE_DARKENER "Let us see how your nerves hold up against the Darkener, Thaladred" +#define SOUND_THALADRED_THE_DARKENER 11259 + +#define SAY_LORD_SANGUINAR "You have persevered against some of my best advisors... but none can withstand the might of the Blood Hammer. Behold, Lord Sanguinar!" +#define SOUND_LORD_SANGUINAR 11260 + +#define SAY_PHASE2 "As you see, I have many weapons in my arsenal...." +#define SOUND_PHASE2 11261 + +#define SAY_PHASE3 "Perhaps I underestimated you. It would be unfair to make you fight all four advisors at once, but... fair treatment was never shown to my people. I'm just returning the favor." +#define SOUND_PHASE3 11262 + +#define SAY_PHASE4 "Alas, sometimes one must take matters into one's own hands. Balamore shanal!" +#define SOUND_PHASE4 11263 + +#define SAY_PHASE5 "I have not come this far to be stopped! The future I have planned will not be jeopardized! Now you will taste true power!!" +#define SOUND_PHASE5 11273 + +#define SAY_SLAY1 "You will not prevail." +#define SOUND_SLAY1 11270 + +#define SAY_SLAY2 "You gambled...and lost." +#define SOUND_SLAY2 11271 + +#define SAY_MINDCONTROL1 "Obey me." +#define SOUND_MINDCONTROL1 11268 + +#define SAY_MINDCONTROL2 "Bow to my will." +#define SOUND_MINDCONTROL2 11269 + +#define SAY_GRAVITYLAPSE1 "Let us see how you fare when your world is turned upside down." +#define SOUND_GRAVITYLAPSE1 11264 + +#define SAY_GRAVITYLAPSE2 "Having trouble staying grounded?" +#define SOUND_GRAVITYLAPSE2 11265 + +#define SAY_SUMMON_PHOENIX1 "Anara'nel belore!" +#define SOUND_SUMMON_PHOENIX1 11267 + +#define SAY_SUMMON_PHOENIX2 "By the power of the sun!" +#define SOUND_SUMMON_PHOENIX2 11266 + +#define SAY_DEATH "For...Quel...thalas!" +#define SOUND_DEATH 11274 + +//Thaladred the Darkener speech +#define SAY_THALADRED_AGGRO "Prepare yourselves!" +#define SOUND_THALADRED_AGGRO 11203 +#define SAY_THALADRED_DEATH "Forgive me, my prince! I have... failed." +#define SOUND_THALADRED_DEATH 11204 +#define EMOTE_THALADRED_GAZE "sets his gaze on $N!" + +//Lord Sanguinar speech +#define SAY_SANGUINAR_AGGRO "Blood for blood!" +#define SOUND_SANGUINAR_AGGRO 11152 +#define SAY_SANGUINAR_DEATH "NO! I ...will... not..." +#define SOUND_SANGUINAR_DEATH 11153 + +//Grand Astromancer Capernian speech +#define SAY_CAPERNIAN_AGGRO "The sin'dore reign supreme!" +#define SOUND_CAPERNIAN_AGGRO 11117 +#define SAY_CAPERNIAN_DEATH "This is not over!" +#define SOUND_CAPERNIAN_DEATH 11118 + +//Master Engineer Telonicus speech +#define SAY_TELONICUS_AGGRO "Anar'alah belore!" +#define SOUND_TELONICUS_AGGRO 11157 +#define SAY_TELONICUS_DEATH "More perils... await" +#define SOUND_TELONICUS_DEATH 11158 + +//Creature IDs +#define PHOENIX 21362 +#define PHOENIX_EGG 21364 + +//Phoenix egg and phoenix model +#define PHOENIX_MODEL 19682 +#define PHOENIX_EGG_MODEL 20245 + +//#define PI 3.141592 +#define TEMP_MC_WHISPER "[SD2 Debug] You would be mind controlled here!" + +//weapon id + position +float KaelthasWeapons[7][5] = +{ + {21270, 794.38, 15, 48.72, 2.9}, //[Cosmic Infuser] + {21269, 785.47, 12.12, 48.72, 3.14}, //[Devastation] + {21271, 781.25, 4.39, 48.72, 3.14}, //[Infinity Blade] + {21273, 777.38, -0.81, 48.72, 3.06}, //[Phaseshift Bulwark] + {21274, 781.48, -6.08, 48.72, 3.9}, //[Staff of Disintegration] + {21272, 785.42, -13.59, 48.72, 3.4}, //[Warp Slicer] + {21268, 793.06, -16.61, 48.72, 3.10} //[Netherstrand Longbow] +}; + +#define GRAVITY_X 795.0f +#define GRAVITY_Y 0.0f +#define GRAVITY_Z 70.0f + +#define TIME_PHASE_2_3 120000 +#define TIME_PHASE_3_4 120000 + +#define KAEL_VISIBLE_RANGE 50.0f + +//Base AI for Advisors +struct MANGOS_DLL_DECL advisorbase_ai : public ScriptedAI +{ + ScriptedInstance* pInstance; + bool FakeDeath; + uint32 DelayRes_Timer; + uint64 DelayRes_Target; + + advisorbase_ai(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || FakeDeath || m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if( !m_creature->getVictim() && who->isTargetableForAttack() && ( m_creature->IsHostileTo( who )) && who->isInAccessablePlaceFor(m_creature) ) + { + if (m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = m_creature->GetAttackDistance(who); + if(m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->IsWithinLOSInMap(who) ) + { + DoStartAttackAndMovement(who); + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + if (!InCombat) + { + Aggro(who); + InCombat = true; + } + } + } + } + + void AttackStart(Unit* who) + { + if (!who || FakeDeath || m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (who->isTargetableForAttack()) + { + //Begin attack + DoStartAttackAndMovement(who); + + if (!InCombat) + { + Aggro(who); + InCombat = true; + } + } + } + + void Reset() + { + FakeDeath = false; + DelayRes_Timer = 0; + DelayRes_Target = 0; + + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + //reset encounter + if(pInstance && (pInstance->GetData(DATA_KAELTHASEVENT) == 1 || pInstance->GetData(DATA_KAELTHASEVENT) == 3)) + { + Creature *Kaelthas = NULL; + Kaelthas = (Creature*)(Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_KAELTHAS))); + + if(Kaelthas) + Kaelthas->AI()->EnterEvadeMode(); + } + } + + void Revive(Unit* Target) + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetHealth(m_creature->GetMaxHealth()); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + DoCast(m_creature, SPELL_RES_VISUAL, false); + DelayRes_Timer = 2000; + } + + void DamageTaken(Unit* pKiller, uint32 &damage) + { + if (damage < m_creature->GetHealth()) + return; + + //Prevent glitch if in fake death + if (FakeDeath) + { + damage = 0; + return; + } + //Don't really die in phase 1 & 3, only die after that + if(pInstance && pInstance->GetData(DATA_KAELTHASEVENT) != 0) + { + //prevent death + damage = 0; + FakeDeath = true; + + m_creature->InterruptNonMeleeSpells(false); + m_creature->SetHealth(0); + m_creature->StopMoving(); + m_creature->ClearComboPointHolders(); + m_creature->RemoveAllAurasOnDeath(); + m_creature->ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false); + m_creature->ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->ClearAllReactives(); + m_creature->SetUInt64Value(UNIT_FIELD_TARGET,0); + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MoveIdle(); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1,PLAYER_STATE_DEAD); + + if (pInstance->GetData(DATA_KAELTHASEVENT) == 3) + JustDied(pKiller); + } + } + + void UpdateAI(const uint32 diff) + { + if (DelayRes_Timer) + if (DelayRes_Timer <= diff) + { + DelayRes_Timer = 0; + FakeDeath = false; + + Unit* Target = Unit::GetUnit((*m_creature), DelayRes_Target); + if (!Target)Target = m_creature->getVictim(); + DoResetThreat(); + AttackStart(Target); + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MoveChase(Target); + m_creature->AddThreat(Target, 0.0f); + }else DelayRes_Timer -= diff; + } + +}; + +//Kael'thas AI +struct MANGOS_DLL_DECL boss_kaelthasAI : public ScriptedAI +{ + boss_kaelthasAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + AdvisorGuid[0] = 0; + AdvisorGuid[1] = 0; + AdvisorGuid[2] = 0; + AdvisorGuid[3] = 0; + Reset(); + } + + ScriptedInstance* pInstance; + + uint32 Fireball_Timer; + uint32 ArcaneDisruption_Timer; + uint32 Phoenix_Timer; + uint32 ShockBarrier_Timer; + uint32 GravityLapse_Timer; + uint32 GravityLapse_Phase; + uint32 NetherBeam_Timer; + uint32 NetherVapor_Timer; + uint32 FlameStrike_Timer; + uint32 MindControl_Timer; + uint32 Phase; + uint32 PhaseSubphase; //generic + uint32 Phase_Timer; //generic timer + uint32 PyrosCasted; + + bool InGravityLapse; + bool IsCastingFireball; + bool ChainPyros; + + uint64 AdvisorGuid[4]; + + void Reset() + { + Fireball_Timer = 5000+rand()%10000; + ArcaneDisruption_Timer = 45000; + MindControl_Timer = 40000; + Phoenix_Timer = 50000; + ShockBarrier_Timer = 60000; + FlameStrike_Timer = 30000; + GravityLapse_Timer = 20000; + GravityLapse_Phase = 0; + NetherBeam_Timer = 8000; + NetherVapor_Timer = 10000; + PyrosCasted = 0; + Phase = 0; + InGravityLapse = false; + IsCastingFireball = false; + ChainPyros = false; + + if(InCombat) + PrepareAdvisors(); + + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if(pInstance) + pInstance->SetData(DATA_KAELTHASEVENT, 0); + } + + void PrepareAdvisors() + { + Creature *pCreature; + for(uint8 i = 0; i < 4; i++) + { + pCreature = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[i])); + if(pCreature) + { + pCreature->Respawn(); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pCreature->setFaction(m_creature->getFaction()); + pCreature->AI()->EnterEvadeMode(); + } + } + } + + void StartEvent() + { + if(!pInstance) + return; + + AdvisorGuid[0] = pInstance->GetData64(DATA_THALADREDTHEDARKENER); + AdvisorGuid[1] = pInstance->GetData64(DATA_LORDSANGUINAR); + AdvisorGuid[2] = pInstance->GetData64(DATA_GRANDASTROMANCERCAPERNIAN); + AdvisorGuid[3] = pInstance->GetData64(DATA_MASTERENGINEERTELONICUS); + + if(!AdvisorGuid[0] || !AdvisorGuid[1] || !AdvisorGuid[2] || !AdvisorGuid[3]) + { + error_log("SD2: Kael'Thas One or more advisors missing, Skipping Phases 1-3"); + DoYell("SD2: Kael'Thas One or more advisors missing, Skipping Phases 1-3", LANG_UNIVERSAL, NULL); + + DoYell(SAY_PHASE4, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_PHASE4); + Phase = 4; + + pInstance->SetData(DATA_KAELTHASEVENT, 4); + + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + Unit *target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target) + { + DoStartAttackAndMovement(target); + } + }else + { + PrepareAdvisors(); + + DoYell(SAY_INTRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_INTRO); + + pInstance->SetData(DATA_KAELTHASEVENT, 1); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + PhaseSubphase = 0; + Phase_Timer = 23000; + Phase = 1; + } + } + + void KilledUnit() + { + switch(rand()%2) + { + case 0: + DoYell(SAY_SLAY1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY1); + break; + case 1: + DoYell(SAY_SLAY2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY2); + break; + } + } + + void JustDied(Unit* Killer) + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + DoYell(SAY_DEATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_DEATH); + + if(pInstance) + pInstance->SetData(DATA_KAELTHASEVENT, 0); + + Creature *pCreature; + for(uint8 i = 0; i < 4; i++) + { + pCreature = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[i])); + if(pCreature) + { + pCreature->DealDamage(pCreature, pCreature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + } + + void Aggro(Unit *who) + { + if (pInstance && !pInstance->GetData(DATA_KAELTHASEVENT) && !Phase) + StartEvent(); + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || m_creature->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + float attackRadius = m_creature->GetAttackDistance(who); + if (Phase >= 4 && m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) + { + if(who->HasStealthAura()) + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + DoStartAttackAndMovement(who); + } + else if(who->isAlive()) + { + if (pInstance && !pInstance->GetData(DATA_KAELTHASEVENT) && !Phase && m_creature->IsWithinDistInMap(who, 60.0f)) + StartEvent(); + + //add to the threat list, so we can use SelectTarget + m_creature->AddThreat(who,0.0f); + } + } + } + + void UpdateAI(const uint32 diff) + { + //Phase 1 + switch (Phase) + { + case 1: + { + Unit *target; + Creature* Advisor; + + //Subphase switch + switch(PhaseSubphase) + { + //Subphase 1 - Start + case 0: + if(Phase_Timer < diff) + { + DoYell(SAY_THALADRED_THE_DARKENER, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_THALADRED_THE_DARKENER); + + //start advisor within 7 seconds + Phase_Timer = 7000; + + PhaseSubphase++; + }else Phase_Timer -= diff; + break; + + //Subphase 1 - Unlock advisor + case 1: + if(Phase_Timer < diff) + { + Advisor = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[0])); + + if(Advisor) + { + Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Advisor->setFaction(m_creature->getFaction()); + + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target) + Advisor->AI()->AttackStart(target); + } + + PhaseSubphase++; + }else Phase_Timer -= diff; + break; + + //Subphase 2 - Start + case 2: + Advisor = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[0])); + if(Advisor && (Advisor->GetUInt32Value(UNIT_FIELD_BYTES_1) == PLAYER_STATE_DEAD)) + { + DoYell(SAY_LORD_SANGUINAR, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_LORD_SANGUINAR); + + //start advisor within 12.5 seconds + Phase_Timer = 12500; + + PhaseSubphase++; + } + break; + + //Subphase 2 - Unlock advisor + case 3: + if(Phase_Timer < diff) + { + Advisor = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[1])); + + if(Advisor) + { + Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Advisor->setFaction(m_creature->getFaction()); + + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target) + Advisor->AI()->AttackStart(target); + } + + PhaseSubphase++; + }else Phase_Timer -= diff; + break; + + //Subphase 3 - Start + case 4: + Advisor = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[1])); + if(Advisor && (Advisor->GetUInt32Value(UNIT_FIELD_BYTES_1) == PLAYER_STATE_DEAD)) + { + DoYell(SAY_ASTROMANCER_CAPERNIAN, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_ASTROMANCER_CAPERNIAN); + + //start advisor within 7 seconds + Phase_Timer = 7000; + + PhaseSubphase++; + } + break; + + //Subphase 3 - Unlock advisor + case 5: + if(Phase_Timer < diff) + { + Advisor = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[2])); + + if(Advisor) + { + Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Advisor->setFaction(m_creature->getFaction()); + + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target) + Advisor->AI()->AttackStart(target); + } + + PhaseSubphase++; + }else Phase_Timer -= diff; + break; + + //Subphase 4 - Start + case 6: + Advisor = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[2])); + if(Advisor && (Advisor->GetUInt32Value(UNIT_FIELD_BYTES_1) == PLAYER_STATE_DEAD)) + { + DoYell(SAY_ENGINEER_TELONICUS, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_ENGINEER_TELONICUS); + + //start advisor within 8.4 seconds + Phase_Timer = 8400; + + PhaseSubphase++; + } + break; + + //Subphase 4 - Unlock advisor + case 7: + if(Phase_Timer < diff) + { + Advisor = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[3])); + + if(Advisor) + { + Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Advisor->setFaction(m_creature->getFaction()); + + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target) + Advisor->AI()->AttackStart(target); + } + + Phase_Timer = 3000; + + PhaseSubphase++; + }else Phase_Timer -= diff; + break; + + //End of phase 1 + case 8: + Advisor = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[3])); + if(Advisor && (Advisor->GetUInt32Value(UNIT_FIELD_BYTES_1) == PLAYER_STATE_DEAD)) + { + Phase = 2; + pInstance->SetData(DATA_KAELTHASEVENT, 2); + + DoYell(SAY_PHASE2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_PHASE2); + PhaseSubphase = 0; + Phase_Timer = 3500; + DoCast(m_creature, SPELL_SUMMON_WEAPONS); + } + break; + } + }break; + + case 2: + { + if (PhaseSubphase == 0) + { + if (Phase_Timer < diff) + { + PhaseSubphase = 1; + }else Phase_Timer -= diff; + } + + //Spawn weapons + if (PhaseSubphase == 1) + { + Unit* Target = SelectUnit(SELECT_TARGET_RANDOM, 0); + + Creature* Weapon; + for (uint32 i = 0; i < 7; i++) + { + Weapon = m_creature->SummonCreature(((uint32)KaelthasWeapons[i][0]),KaelthasWeapons[i][1],KaelthasWeapons[i][2],KaelthasWeapons[i][3],0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000); + + if (!Weapon) + error_log("SD2: Kael'thas weapon %i could not be spawned", i); + else + { + Weapon->setFaction(m_creature->getFaction()); + Weapon->AI()->AttackStart(Target); + Weapon->CastSpell(Weapon, SPELL_WEAPON_SPAWN, false); + } + } + + PhaseSubphase = 2; + Phase_Timer = TIME_PHASE_2_3; + } + + if (PhaseSubphase == 2) + if (Phase_Timer < diff) + { + DoYell(SAY_PHASE3, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_PHASE3); + pInstance->SetData(DATA_KAELTHASEVENT, 3); + Phase = 3; + PhaseSubphase = 0; + }else Phase_Timer -= diff; + }break; + + case 3: + { + if (PhaseSubphase == 0) + { + //Respawn advisors + Unit* Target = SelectUnit(SELECT_TARGET_RANDOM, 0); + + Creature* Advisor; + for (uint32 i = 0; i < 4; i++) + { + Advisor = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[i])); + if (!Advisor) + error_log("SD2: Kael'Thas Advisor %u does not exist. Possibly despawned? Incorrectly Killed?", i); + else ((advisorbase_ai*)Advisor->AI())->Revive(Target); + } + + PhaseSubphase = 1; + Phase_Timer = TIME_PHASE_3_4; + } + + if(Phase_Timer < diff) + { + DoYell(SAY_PHASE4, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_PHASE4); + Phase = 4; + + pInstance->SetData(DATA_KAELTHASEVENT, 4); + + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + Unit *target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target) + { + DoStartAttackAndMovement(target); + } + Phase_Timer = 30000; + }else Phase_Timer -= diff; + } + break; + + case 4: + case 5: + case 6: + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //Fireball_Timer + if(!InGravityLapse && !ChainPyros && Phase != 5) + { + if(Fireball_Timer < diff) + { + if(!IsCastingFireball) + { + if(!m_creature->IsNonMeleeSpellCasted(false)) + { + //interruptable + m_creature->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, false); + int32 dmg = 20000+rand()%5000; + m_creature->CastCustomSpell(m_creature->getVictim(), SPELL_FIREBALL, &dmg, 0, 0, false); + IsCastingFireball = true; + Fireball_Timer = 2500; + } + } + else + { + //apply resistance + m_creature->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, true); + IsCastingFireball = false; + Fireball_Timer = 5000+rand()%10000; + } + }else Fireball_Timer -= diff; + + //ArcaneDisruption_Timer + if(ArcaneDisruption_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_ARCANE_DISRUPTION, true); + + ArcaneDisruption_Timer = 60000; + }else ArcaneDisruption_Timer -= diff; + + if (FlameStrike_Timer < diff) + { + Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0); + DoCast(pUnit, SPELL_FLAME_STRIKE); + + FlameStrike_Timer = 30000; + }FlameStrike_Timer -= diff; + + if (MindControl_Timer < diff) + { + if (m_creature->getThreatManager().getThreatList().size() >= 2) + for (uint32 i = 0; i < 3; i++) + { + debug_log("SD2: Kael'Thas mind control not supported."); + //DoCast(pUnit, SPELL_MIND_CONTROL); + } + + MindControl_Timer = 60000; + }MindControl_Timer -= diff; + } + + //Phoenix_Timer + if(Phoenix_Timer < diff) + { + DoCast(m_creature, SPELL_PHOENIX_ANIMATION); + Creature *Phoenix = DoSpawnCreature(PHOENIX, 0, 0, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 45000); + + if(Phoenix) + { + Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (target) + Phoenix->AI()->AttackStart(target); + }else error_log("SD2: Kael'Thas Phoenix could not be spawned"); + + switch(rand()%2) + { + case 0: + DoYell(SAY_SUMMON_PHOENIX1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SUMMON_PHOENIX1); + break; + + case 1: + DoYell(SAY_SUMMON_PHOENIX2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SUMMON_PHOENIX2); + break; + + default: + break; + } + + Phoenix_Timer = 60000; + }else Phoenix_Timer -= diff; + + //Phase 4 specific spells + if(Phase == 4) + { + if (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 50) + { + pInstance->SetData(DATA_KAELTHASEVENT, 4); + Phase = 5; + Phase_Timer = 10000; + + DoYell(SAY_PHASE5, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_PHASE5); + + m_creature->StopMoving(); + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MoveIdle(); + m_creature->Relocate(GRAVITY_X, GRAVITY_Y, GRAVITY_Z, 0); + m_creature->SendMonsterMove(GRAVITY_X, GRAVITY_Y,GRAVITY_Z, 0, 0, 0); + + m_creature->InterruptNonMeleeSpells(false); + DoCast(m_creature, SPELL_FULLPOWER); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + //ShockBarrier_Timer + if(ShockBarrier_Timer < diff) + { + DoCast(m_creature, SPELL_SHOCK_BARRIER); + ChainPyros = true; + PyrosCasted = 0; + + ShockBarrier_Timer = 60000; + }else ShockBarrier_Timer -= diff; + + //Chain Pyros (3 of them max) + if (ChainPyros && !m_creature->IsNonMeleeSpellCasted(false)) + { + if (PyrosCasted < 3) + { + DoCast(m_creature->getVictim(), SPELL_PYROBLAST); + PyrosCasted++; + + }else + { + ChainPyros = false; + Fireball_Timer = 2500; + ArcaneDisruption_Timer = 60000; + } + } + } + + if (Phase == 5) + { + if(Phase_Timer < diff) + { + m_creature->InterruptNonMeleeSpells(false); + m_creature->RemoveAurasDueToSpell(SPELL_FULLPOWER); + DoCast(m_creature, SPELL_EXPLODE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Phase = 6; + DoStartAttackAndMovement(m_creature->getVictim()); + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + + }else Phase_Timer -= diff; + } + + //Phase 5 + if(Phase == 6) + { + + //GravityLapse_Timer + if(GravityLapse_Timer < diff) + { + std::list::iterator i = m_creature->getThreatManager().getThreatList().begin(); + switch(GravityLapse_Phase) + { + case 0: + m_creature->StopMoving(); + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MoveIdle(); + m_creature->Relocate(GRAVITY_X, GRAVITY_Y, GRAVITY_Z, 0); + m_creature->SendMonsterMove(GRAVITY_X, GRAVITY_Y, GRAVITY_Z, 0, 0, 0); + // 1) Kael'thas will portal the whole raid right into his body + for (i = m_creature->getThreatManager().getThreatList().begin(); i!= m_creature->getThreatManager().getThreatList().end();++i) + { + Unit* pUnit = Unit::GetUnit((*m_creature), (*i)->getUnitGuid()); + if(pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER)) + { + //Use work around packet to prevent player from being dropped from combat + DoTeleportPlayer(pUnit, GRAVITY_X, GRAVITY_Y, GRAVITY_Z, pUnit->GetOrientation()); + } + } + GravityLapse_Timer = 500; + ++GravityLapse_Phase; + InGravityLapse = true; + ShockBarrier_Timer = 1000; + NetherBeam_Timer = 5000; + break; + + case 1: + switch(rand()%2) + { + case 0: + DoYell(SAY_GRAVITYLAPSE1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_GRAVITYLAPSE1); + break; + + case 1: + DoYell(SAY_GRAVITYLAPSE2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_GRAVITYLAPSE2); + break; + } + + // 2) At that point he will put a Gravity Lapse debuff on everyone + for (i = m_creature->getThreatManager().getThreatList().begin(); i!= m_creature->getThreatManager().getThreatList().end();i++) + { + Unit* pUnit = Unit::GetUnit((*m_creature), (*i)->getUnitGuid()); + if(pUnit) + { + m_creature->CastSpell(pUnit, SPELL_KNOCKBACK, true); + //Gravity lapse - needs an exception in Spell system to work + + pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE, true, 0, 0, m_creature->GetGUID()); + pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE_AURA, true, 0, 0, m_creature->GetGUID()); + + //Using packet workaround + WorldPacket data(12); + data.SetOpcode(SMSG_MOVE_SET_CAN_FLY); + data.append(pUnit->GetPackGUID()); + data << uint32(0); + pUnit->SendMessageToSet(&data, true); + } + } + GravityLapse_Timer = 10000; + GravityLapse_Phase++; + break; + + case 2: + //Cast nether vapor aura on self + m_creature->InterruptNonMeleeSpells(false); + DoCast(m_creature, SPELL_NETHER_VAPOR); + + GravityLapse_Timer = 20000; + GravityLapse_Phase++; + break; + + case 3: + //Remove flight + for (i = m_creature->getThreatManager().getThreatList().begin(); i!= m_creature->getThreatManager().getThreatList().end();i++) + { + Unit* pUnit = Unit::GetUnit((*m_creature), (*i)->getUnitGuid()); + if(pUnit) + { + //Using packet workaround + WorldPacket data(12); + data.SetOpcode(SMSG_MOVE_UNSET_CAN_FLY); + data.append(pUnit->GetPackGUID()); + data << uint32(0); + pUnit->SendMessageToSet(&data, true); + } + } + m_creature->RemoveAurasDueToSpell(SPELL_NETHER_VAPOR); + InGravityLapse = false; + GravityLapse_Timer = 60000; + GravityLapse_Phase = 0; + DoStartAttackAndMovement(m_creature->getVictim()); + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + DoResetThreat(); + break; + } + }else GravityLapse_Timer -= diff; + + if(InGravityLapse) + { + //ShockBarrier_Timer + if(ShockBarrier_Timer < diff) + { + DoCast(m_creature, SPELL_SHOCK_BARRIER); + + ShockBarrier_Timer = 20000; + }else ShockBarrier_Timer -= diff; + + //NetherBeam_Timer + if(NetherBeam_Timer < diff) + { + Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0); + DoCast(pUnit, SPELL_NETHER_BEAM); + + NetherBeam_Timer = 4000; + }else NetherBeam_Timer -= diff; + } + } + + if (!InGravityLapse) + DoMeleeAttackIfReady(); + } + } + } +}; + +//Thaladred the Darkener AI +struct MANGOS_DLL_DECL boss_thaladred_the_darkenerAI : public advisorbase_ai +{ + boss_thaladred_the_darkenerAI(Creature *c) : advisorbase_ai(c) {} + + uint32 Gaze_Timer; + uint32 Silence_Timer; + uint32 PsychicBlow_Timer; + + void Reset() + { + Gaze_Timer = 100; + Silence_Timer = 20000; + PsychicBlow_Timer = 10000; + + advisorbase_ai::Reset(); + } + + void JustDied(Unit* pKiller) + { + DoPlaySoundToSet(m_creature, SOUND_THALADRED_DEATH); + DoYell(SAY_THALADRED_DEATH, LANG_UNIVERSAL, NULL); + } + + void Aggro(Unit *who) + { + if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (!who || FakeDeath) + return; + + DoYell(SAY_THALADRED_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_THALADRED_AGGRO); + m_creature->AddThreat(who, 5000000.0f); + } + + void UpdateAI(const uint32 diff) + { + advisorbase_ai::UpdateAI(diff); + + //Faking death, don't do anything + if (FakeDeath) + return; + + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //Gaze_Timer + if(Gaze_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target) + { + DoResetThreat(); + m_creature->AddThreat(target, 5000000.0f); + DoTextEmote(EMOTE_THALADRED_GAZE, target); + Gaze_Timer = 8500; + } + }else Gaze_Timer -= diff; + + //Silence_Timer + if(Silence_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_SILENCE); + Silence_Timer = 20000; + }else Silence_Timer -= diff; + + //PsychicBlow_Timer + if(PsychicBlow_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_PSYCHIC_BLOW); + PsychicBlow_Timer = 20000+rand()%5000; + }else PsychicBlow_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Lord Sanguinar AI +struct MANGOS_DLL_DECL boss_lord_sanguinarAI : public advisorbase_ai +{ + boss_lord_sanguinarAI(Creature *c) : advisorbase_ai(c){} + + uint32 Fear_Timer; + + void Reset() + { + Fear_Timer = 20000; + advisorbase_ai::Reset(); + } + + void JustDied(Unit* Killer) + { + DoPlaySoundToSet(m_creature, SOUND_SANGUINAR_DEATH); + DoYell(SAY_SANGUINAR_DEATH, LANG_UNIVERSAL, NULL); + } + + void Aggro(Unit *who) + { + if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (!who || FakeDeath) + return; + + DoYell(SAY_SANGUINAR_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SANGUINAR_AGGRO); + } + + void UpdateAI(const uint32 diff) + { + advisorbase_ai::UpdateAI(diff); + + //Faking death, don't do anything + if (FakeDeath) + return; + + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //Fear_Timer + if(Fear_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_BELLOWING_ROAR); + Fear_Timer = 25000+rand()%10000; //approximately every 30 seconds + }else Fear_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Grand Astromancer Capernian AI +struct MANGOS_DLL_DECL boss_grand_astromancer_capernianAI : public advisorbase_ai +{ + boss_grand_astromancer_capernianAI(Creature *c) : advisorbase_ai(c){} + + uint32 Fireball_Timer; + uint32 Conflagration_Timer; + uint32 ArcaneExplosion_Timer; + uint32 Yell_Timer; + bool Yell; + + void Reset() + { + Fireball_Timer = 2000; + Conflagration_Timer = 20000; + ArcaneExplosion_Timer = 5000; + Yell_Timer = 2000; + Yell = false; + + advisorbase_ai::Reset(); + } + + void JustDied(Unit* pKiller) + { + DoPlaySoundToSet(m_creature, SOUND_CAPERNIAN_DEATH); + DoYell(SAY_CAPERNIAN_DEATH, LANG_UNIVERSAL, NULL); + } + + void AttackStart(Unit* who) + { + if (!who || FakeDeath || m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (who->isTargetableForAttack()) + { + //Begin attack + DoStartAttackAndMovement(who, CAPERNIAN_DISTANCE, M_PI/2); + + if (!InCombat) + { + Aggro(who); + InCombat = true; + } + } + } + + void Aggro(Unit *who) + { + if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (!who || FakeDeath) + return; + } + + void UpdateAI(const uint32 diff) + { + advisorbase_ai::UpdateAI(diff); + + //Faking Death, don't do anything + if (FakeDeath) + return; + + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //Yell_Timer + if(!Yell) + if(Yell_Timer < diff) + { + DoYell(SAY_CAPERNIAN_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_CAPERNIAN_AGGRO); + + Yell = true; + }else Yell_Timer -= diff; + + //Fireball_Timer + if(Fireball_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_CAPERNIAN_FIREBALL); + Fireball_Timer = 4000; + }else Fireball_Timer -= diff; + + //Conflagration_Timer + if(Conflagration_Timer < diff) + { + Unit *target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + + if(target && m_creature->IsWithinDistInMap(target, 30)) + DoCast(target, SPELL_CONFLAGRATION); + else + DoCast(m_creature->getVictim(), SPELL_CONFLAGRATION); + + Conflagration_Timer = 10000+rand()%5000; + }else Conflagration_Timer -= diff; + + //ArcaneExplosion_Timer + if(ArcaneExplosion_Timer < diff) + { + bool InMeleeRange = false; + Unit *target = NULL; + std::list& m_threatlist = m_creature->getThreatManager().getThreatList(); + for (std::list::iterator i = m_threatlist.begin(); i!= m_threatlist.end();++i) + { + Unit* pUnit = Unit::GetUnit((*m_creature), (*i)->getUnitGuid()); + //if in melee range + if(pUnit && pUnit->IsWithinDistInMap(m_creature, 5)) + { + InMeleeRange = true; + target = pUnit; + break; + } + } + + if(InMeleeRange) + DoCast(target, SPELL_ARCANE_EXPLOSION); + + ArcaneExplosion_Timer = 4000+rand()%2000; + }else ArcaneExplosion_Timer -= diff; + + //Do NOT deal any melee damage. + } +}; + +//Master Engineer Telonicus AI +struct MANGOS_DLL_DECL boss_master_engineer_telonicusAI : public advisorbase_ai +{ + boss_master_engineer_telonicusAI(Creature *c) : advisorbase_ai(c){} + + uint32 Bomb_Timer; + uint32 RemoteToy_Timer; + + void Reset() + { + Bomb_Timer = 10000; + RemoteToy_Timer = 5000; + + advisorbase_ai::Reset(); + } + + void JustDied(Unit* pKiller) + { + DoPlaySoundToSet(m_creature, SOUND_TELONICUS_DEATH); + DoYell(SAY_TELONICUS_DEATH, LANG_UNIVERSAL, NULL); + } + + void Aggro(Unit *who) + { + if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (!who || FakeDeath) + return; + + DoYell(SAY_TELONICUS_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_TELONICUS_AGGRO); + } + + void UpdateAI(const uint32 diff) + { + advisorbase_ai::UpdateAI(diff); + + //Faking Death, do nothing + if (FakeDeath) + return; + + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //Bomb_Timer + if(Bomb_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_BOMB); + Bomb_Timer = 25000; + }else Bomb_Timer -= diff; + + //RemoteToy_Timer + if(RemoteToy_Timer < diff) + { + Unit *target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + + if(target) + DoCast(target, SPELL_REMOTE_TOY); + + RemoteToy_Timer = 10000+rand()%5000; + }else RemoteToy_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Flame Strike AI +struct MANGOS_DLL_DECL mob_kael_flamestrikeAI : public ScriptedAI +{ + mob_kael_flamestrikeAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Timer; + bool Casting; + bool KillSelf; + + void Reset() + { + Timer = 5000; + Casting = false; + KillSelf = false; + + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->setFaction(14); + } + + void Aggro(Unit *who) + { + } + + void MoveInLineOfSight(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if (!Casting) + { + DoCast(m_creature, SPELL_FLAME_STRIKE_VIS); + Casting = true; + } + + //Timer + if(Timer < diff) + { + if (!KillSelf) + { + m_creature->InterruptNonMeleeSpells(false); + DoCast(m_creature, SPELL_FLAME_STRIKE_DMG); + }else m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + + KillSelf = true; + Timer = 1000; + }else Timer -= diff; + } +}; + +//Phoenix AI +struct MANGOS_DLL_DECL mob_phoenixAI : public ScriptedAI +{ + mob_phoenixAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Burn_Timer; + uint32 Hatch_Timer; + uint32 EggVis_Timer; + bool IsEgg; + + void Reset() + { + Burn_Timer = 1000; + Hatch_Timer = 15000; + EggVis_Timer = 0; + IsEgg = false; + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, PHOENIX_MODEL); + } + + void Hatch() + { + IsEgg = false; + m_creature->SetHealth(m_creature->GetMaxHealth()); + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, PHOENIX_MODEL); + Burn_Timer = 1000; + Hatch_Timer = 15000; + EggVis_Timer = 0; + AttackStart(m_creature->getVictim()); + } + + void DamageTaken(Unit* pKiller, uint32 &damage) + { + if (damage < m_creature->GetHealth()) + return; + + //Bird cannot die, only egg + if (!IsEgg) + { + //prevent death + damage = 0; + IsEgg = true; + + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MoveIdle(); + m_creature->SetHealth(m_creature->GetMaxHealth()); + EggVis_Timer = 1000; + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1,PLAYER_STATE_DEAD); + } + } + + void Aggro(Unit *who) + { + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || m_creature->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + float attackRadius = m_creature->GetAttackDistance(who); + if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) + { + if(who->HasStealthAura()) + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + AttackStart(who); + } + } + } + + void UpdateAI(const uint32 diff) + { + //Check if we have a current target + if (!IsEgg) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if (Burn_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_BURN); + Burn_Timer = 1000; + }else Burn_Timer -= diff; + + DoMeleeAttackIfReady(); + } + else + { + if (EggVis_Timer) + if (EggVis_Timer <= diff) + { + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, PHOENIX_EGG_MODEL); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + EggVis_Timer = 0; + }else EggVis_Timer -= diff; + + if (Hatch_Timer < diff) + { + Hatch(); + }else Hatch_Timer -= diff; + } + } +}; + +CreatureAI* GetAI_boss_kaelthas(Creature *_Creature) +{ + return new boss_kaelthasAI (_Creature); +} + +CreatureAI* GetAI_boss_thaladred_the_darkener(Creature *_Creature) +{ + return new boss_thaladred_the_darkenerAI (_Creature); +} + +CreatureAI* GetAI_boss_lord_sanguinar(Creature *_Creature) +{ + return new boss_lord_sanguinarAI (_Creature); +} + +CreatureAI* GetAI_boss_grand_astromancer_capernian(Creature *_Creature) +{ + return new boss_grand_astromancer_capernianAI (_Creature); +} + +CreatureAI* GetAI_boss_master_engineer_telonicus(Creature *_Creature) +{ + return new boss_master_engineer_telonicusAI (_Creature); +} + +CreatureAI* GetAI_mob_kael_flamestrike(Creature *_Creature) +{ + return new mob_kael_flamestrikeAI (_Creature); +} + +CreatureAI* GetAI_mob_phoenix(Creature *_Creature) +{ + return new mob_phoenixAI (_Creature); +} + +void AddSC_boss_kaelthas() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_kaelthas"; + newscript->GetAI = GetAI_boss_kaelthas; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_thaladred_the_darkener"; + newscript->GetAI = GetAI_boss_thaladred_the_darkener; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_lord_sanguinar"; + newscript->GetAI = GetAI_boss_lord_sanguinar; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_grand_astromancer_capernian"; + newscript->GetAI = GetAI_boss_grand_astromancer_capernian; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_master_engineer_telonicus"; + newscript->GetAI = GetAI_boss_master_engineer_telonicus; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name= "mob_kael_flamestrike"; + newscript->GetAI = GetAI_mob_kael_flamestrike; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_phoenix"; + newscript->GetAI = GetAI_mob_phoenix; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_void_reaver.cpp b/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_void_reaver.cpp new file mode 100644 index 00000000000..43072b1947d --- /dev/null +++ b/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_void_reaver.cpp @@ -0,0 +1,203 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Void_Reaver +SD%Complete: 100 +SDComment: +SDCategory: Tempest Keep, The Eye +EndScriptData */ + +#include "precompiled.h" +#include "def_the_eye.h" + +#define SPELL_POUNDING 34162 +#define SPELL_ARCANE_ORB_TRIGGER 34172 +#define SPELL_KNOCK_AWAY 11130 +#define SPELL_BERSERK 27680 + +#define SAY_AGGRO "Alert, you are marked for extermination!" +#define SAY_SLAY1 "Extermination, successful." +#define SAY_SLAY2 "Imbecile life form, no longer functional." +#define SAY_SLAY3 "Threat neutralized." +#define SAY_DEATH "Systems... shutting... down..." +#define SAY_POUNDING1 "Alternative measure commencing..." +#define SAY_POUNDING2 "Calculating force parameters..." + +#define SOUND_AGGRO 11213 +#define SOUND_SLAY1 11215 +#define SOUND_SLAY2 11216 +#define SOUND_SLAY3 11217 +#define SOUND_DEATH 11214 +#define SOUND_POUNDING1 11218 +#define SOUND_POUNDING2 11219 + +#define CREATURE_ORB_TARGET 19577 + +struct MANGOS_DLL_DECL boss_void_reaverAI : public ScriptedAI +{ + boss_void_reaverAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + + uint32 Pounding_Timer; + uint32 ArcaneOrb_Timer; + uint32 KnockAway_Timer; + uint32 Berserk_Timer; + + void Reset() + { + Pounding_Timer = 12000; + ArcaneOrb_Timer = 3000; + KnockAway_Timer = 30000; + Berserk_Timer = 600000; + + if(pInstance) + pInstance->SetData(DATA_VOIDREAVEREVENT, NOT_STARTED); + } + + void KilledUnit(Unit *victim) + { + switch(rand()%3) + { + case 0: + DoYell(SAY_SLAY1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY1); + break; + case 1: + DoYell(SAY_SLAY2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY2); + break; + case 2: + DoYell(SAY_SLAY3, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_SLAY3); + break; + } + } + + void JustDied(Unit *victim) + { + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_DEATH); + + if(pInstance) + pInstance->SetData(DATA_VOIDREAVEREVENT, NOT_STARTED); + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_AGGRO); + + if(pInstance) + pInstance->SetData(DATA_VOIDREAVEREVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + // Pounding + if(Pounding_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_POUNDING); + + switch(rand()%2) + { + case 0: + DoPlaySoundToSet(m_creature, SOUND_POUNDING1); + DoYell(SAY_POUNDING1, LANG_UNIVERSAL, NULL); + break; + case 1: + DoPlaySoundToSet(m_creature, SOUND_POUNDING2); + DoYell(SAY_POUNDING2, LANG_UNIVERSAL, NULL); + break; + } + Pounding_Timer = 12000; + }else Pounding_Timer -= diff; + + // Arcane Orb + if(ArcaneOrb_Timer < diff) + { + Unit *target; + std::list t_list = m_creature->getThreatManager().getThreatList(); + std::vector target_list; + for(std::list::iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + target = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid()); + //15 yard radius minimum + if(target && target->GetDistance2d(m_creature) > 15) + target_list.push_back(target); + target = NULL; + } + if(target_list.size()) + target = *(target_list.begin()+rand()%target_list.size()); + + if (target) + { + Unit* Spawn = NULL; + Spawn = m_creature->SummonCreature(CREATURE_ORB_TARGET, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 10000); + if (Spawn) + m_creature->CastSpell(Spawn, SPELL_ARCANE_ORB_TRIGGER, true); + } + + ArcaneOrb_Timer = 3000; + }else ArcaneOrb_Timer -= diff; + + // Single Target knock back, reduces aggro + if(KnockAway_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_KNOCK_AWAY); + + //Drop 25% aggro + if(m_creature->getThreatManager().getThreat(m_creature->getVictim())) + m_creature->getThreatManager().modifyThreatPercent(m_creature->getVictim(),-25); + + KnockAway_Timer = 30000; + }else KnockAway_Timer -= diff; + + //Berserk + if(Berserk_Timer < diff) + { + if (m_creature->IsNonMeleeSpellCasted(false)) + m_creature->InterruptNonMeleeSpells(false); + + DoCast(m_creature,SPELL_BERSERK); + Berserk_Timer = 600000; + }else Berserk_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_void_reaver(Creature *_Creature) +{ + return new boss_void_reaverAI (_Creature); +} + +void AddSC_boss_void_reaver() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_void_reaver"; + newscript->GetAI = GetAI_boss_void_reaver; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/def_the_eye.h b/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/def_the_eye.h new file mode 100644 index 00000000000..eb7a9ecedf1 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/def_the_eye.h @@ -0,0 +1,20 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_THE_EYE_H +#define DEF_THE_EYE_H + +#define DATA_ALAREVENT 1 +#define DATA_ASTROMANCER 2 +#define DATA_GRANDASTROMANCERCAPERNIAN 3 +#define DATA_HIGHASTROMANCERSOLARIANEVENT 4 +#define DATA_FATHOMLORDKARATHRESSEVENT 5 +#define DATA_KAELTHAS 6 +#define DATA_KAELTHASEVENT 7 +#define DATA_LORDSANGUINAR 8 +#define DATA_MASTERENGINEERTELONICUS 9 +#define DATA_SOLARIANEVENT 10 +#define DATA_THALADREDTHEDARKENER 11 +#define DATA_VOIDREAVEREVENT 12 +#endif diff --git a/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/instance_the_eye.cpp b/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/instance_the_eye.cpp new file mode 100644 index 00000000000..b2bd2920a82 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/instance_the_eye.cpp @@ -0,0 +1,178 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_The_Eye +SD%Complete: 100 +SDComment: +SDCategory: Tempest Keep, The Eye +EndScriptData */ + +#include "precompiled.h" +#include "def_the_eye.h" + +#define ENCOUNTERS 5 + +/* The Eye encounters: +0 - Kael'thas event +1 - Al' ar event +2 - Solarian Event +3 - Void Reaver event +*/ + +struct MANGOS_DLL_DECL instance_the_eye : public ScriptedInstance +{ + instance_the_eye(Map *Map) : ScriptedInstance(Map) {Initialize();}; + + uint64 ThaladredTheDarkener; + uint64 LordSanguinar; + uint64 GrandAstromancerCapernian; + uint64 MasterEngineerTelonicus; + uint64 Kaelthas; + uint64 Astromancer; + + uint8 KaelthasEventPhase; + + bool Encounters[ENCOUNTERS]; + + void Initialize() + { + ThaladredTheDarkener = 0; + LordSanguinar = 0; + GrandAstromancerCapernian = 0; + MasterEngineerTelonicus = 0; + Kaelthas = 0; + Astromancer = 0; + + KaelthasEventPhase = 0; + + for(uint8 i = 0; i < ENCOUNTERS; i++) + Encounters[i] = false; + } + + bool IsEncounterInProgress() const + { + for(uint8 i = 0; i < ENCOUNTERS; i++) + if(Encounters[i]) return true; + + return false; + } + + void OnCreatureCreate(Creature *creature, uint32 creature_entry) + { + switch(creature_entry) + { + case 20064: ThaladredTheDarkener = creature->GetGUID(); break; + case 20063: MasterEngineerTelonicus = creature->GetGUID(); break; + case 20062: GrandAstromancerCapernian = creature->GetGUID(); break; + case 20060: LordSanguinar = creature->GetGUID(); break; + case 19622: Kaelthas = creature->GetGUID(); break; + case 18805: Astromancer = creature->GetGUID(); break; + } + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_THALADREDTHEDARKENER: + return ThaladredTheDarkener; + + case DATA_LORDSANGUINAR: + return LordSanguinar; + + case DATA_GRANDASTROMANCERCAPERNIAN: + return GrandAstromancerCapernian; + + case DATA_MASTERENGINEERTELONICUS: + return MasterEngineerTelonicus; + + case DATA_KAELTHAS: + return Kaelthas; + + case DATA_ASTROMANCER: + return Astromancer; + } + + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_ALAREVENT: + Encounters[0] = (data) ? true : false; + break; + + case DATA_SOLARIANEVENT: + Encounters[1] = (data) ? true : false; + break; + + case DATA_VOIDREAVEREVENT: + Encounters[2] = (data) ? true : false; + break; + + //Kael'thas + case DATA_KAELTHASEVENT: + KaelthasEventPhase = data; + Encounters[3] = (data) ? true : false; + break; + + case DATA_HIGHASTROMANCERSOLARIANEVENT: + Encounters[4] = (data) ? true : false; + break; + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_ALAREVENT: + return Encounters[0]; + + case DATA_SOLARIANEVENT: + return Encounters[1]; + + case DATA_VOIDREAVEREVENT: + return Encounters[2]; + + case DATA_HIGHASTROMANCERSOLARIANEVENT: + return Encounters[4]; + + //Kael'thas + case DATA_KAELTHASEVENT: + return KaelthasEventPhase; + } + + return 0; + } +}; + +InstanceData* GetInstanceData_instance_the_eye(Map* map) +{ + return new instance_the_eye(map); +} + +void AddSC_instance_the_eye() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_the_eye"; + newscript->GetInstanceData = GetInstanceData_instance_the_eye; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/the_eye.cpp b/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/the_eye.cpp new file mode 100644 index 00000000000..055a7ad3095 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/the_eye.cpp @@ -0,0 +1,98 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: The_Eye +SD%Complete: 100 +SDComment: +SDCategory: Tempest Keep, The Eye +EndScriptData */ + +/* ContentData +mob_crystalcore_devastator +EndContentData */ + +#include "precompiled.h" +#include "def_the_eye.h" + +#define SPELL_COUNTERCHARGE 35035 +#define SPELL_KNOCKAWAY 22893 + +struct MANGOS_DLL_DECL mob_crystalcore_devastatorAI : public ScriptedAI +{ + mob_crystalcore_devastatorAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Knockaway_Timer; + uint32 Countercharge_Timer; + + void Reset() + { + Countercharge_Timer = 9000; + Knockaway_Timer = 25000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //Check if we have a current target + //Knockaway_Timer + if (Knockaway_Timer < diff) + { + m_creature->CastSpell(m_creature->getVictim(),SPELL_KNOCKAWAY, true); + + // current aggro target is knocked away pick new target + Unit* Target = SelectUnit(SELECT_TARGET_TOPAGGRO, 0); + + if (!Target || Target == m_creature->getVictim()) + Target = SelectUnit(SELECT_TARGET_TOPAGGRO, 1); + + if (Target) + m_creature->TauntApply(Target); + + Knockaway_Timer = 23000; + } + else Knockaway_Timer -= diff; + + //Countercharge_Timer + if (Countercharge_Timer < diff) + { + DoCast(this->m_creature,SPELL_COUNTERCHARGE); + Countercharge_Timer = 45000; + }else Countercharge_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_crystalcore_devastator(Creature *_Creature) +{ + return new mob_crystalcore_devastatorAI (_Creature); +} + +void AddSC_the_eye() +{ + Script *newscript; + newscript = new Script; + newscript->Name="mob_crystalcore_devastator"; + newscript->GetAI = GetAI_mob_crystalcore_devastator; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/tempest_keep/the_mechanar/boss_gatewatcher_gyrokill.cpp b/src/bindings/scripts/scripts/zone/tempest_keep/the_mechanar/boss_gatewatcher_gyrokill.cpp new file mode 100644 index 00000000000..f7aab61b6bb --- /dev/null +++ b/src/bindings/scripts/scripts/zone/tempest_keep/the_mechanar/boss_gatewatcher_gyrokill.cpp @@ -0,0 +1,24 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss Gatewatcher Gyrokill +SD%Complete: 0 +SDComment: Place Holder +SDCategory: Tempest Keep, The Mechanar +EndScriptData */ + +#include "precompiled.h" diff --git a/src/bindings/scripts/scripts/zone/tempest_keep/the_mechanar/boss_gatewatcher_ironhand.cpp b/src/bindings/scripts/scripts/zone/tempest_keep/the_mechanar/boss_gatewatcher_ironhand.cpp new file mode 100644 index 00000000000..77d57ff9b4c --- /dev/null +++ b/src/bindings/scripts/scripts/zone/tempest_keep/the_mechanar/boss_gatewatcher_ironhand.cpp @@ -0,0 +1,147 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss Gatewatcher Ironhand +SD%Complete: 100 +SDComment: +SDCategory: Tempest Keep, The Mechanar +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_SHADOW_POWER 35322 +#define SPELL_JACKHAMMER 35326 +#define SPELL_STREAM_OF_MACHINE_FLUID 35311 + +#define SAY_SPELL_JACKHAMMER_1 "With the precise angle and velocity... " +#define SOUND_SPELL_JACKHAMMER_1 11112 +#define SAY_SPELL_JACKHAMMER_2 "Low tech yet quiet effective!" +#define SOUND_SPELL_JACKHAMMER_2 11113 + +#define SAY_AGGRO_1 "You have approximately five seconds to live." +#define SOUND_SAY_AGGRO_1 11109 + +#define SAY_SLAY_1 "A foregone conclusion." +#define SOUND_SLAY_1 11110 +#define SAY_SLAY_2 "The processing will continue a schedule!" +#define SOUND_SLAY_2 11111 + +#define SAY_DEATH_1 "My calculations did not... " +#define SOUND_DEATH_1 11114 + + +struct MANGOS_DLL_DECL boss_gatewatcher_iron_handAI : public ScriptedAI +{ + boss_gatewatcher_iron_handAI(Creature *c) : ScriptedAI(c) { Reset(); } + + uint32 Shadow_Power_Timer; + uint32 Jackhammer_Timer; + uint32 Stream_of_Machine_Fluid_Timer; + + void Reset() + { + Shadow_Power_Timer = 25000; + Jackhammer_Timer = 45000; + Stream_of_Machine_Fluid_Timer = 55000; + } + + void Aggro(Unit *who) + { + } + + void KilledUnit(Unit* victim) + { + if (rand()%2) + return; + + switch(rand()%2) + { + case 0: + DoYell(SAY_SLAY_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY_1); + break; + case 1: + DoYell(SAY_SLAY_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY_2); + break; + } + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DEATH_1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_DEATH_1); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //Shadow Power + if(Shadow_Power_Timer < diff) + { + DoCast(m_creature,SPELL_SHADOW_POWER); + Shadow_Power_Timer = 25000; + }else Shadow_Power_Timer -= diff; + + //Jack Hammer + if(Jackhammer_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_JACKHAMMER); + + if (rand()%2) + return; + + switch(rand()%2) + { + case 0: + DoYell(SAY_SPELL_JACKHAMMER_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_SPELL_JACKHAMMER_1); + break; + case 1: + DoYell(SAY_SPELL_JACKHAMMER_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_SPELL_JACKHAMMER_2); + break; + } + + Jackhammer_Timer = 45000; + }else Jackhammer_Timer -= diff; + + //Stream of Machine Fluid + if(Stream_of_Machine_Fluid_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_STREAM_OF_MACHINE_FLUID); + Stream_of_Machine_Fluid_Timer = 55000; + }else Stream_of_Machine_Fluid_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_gatewatcher_iron_hand(Creature *_Creature) +{ + return new boss_gatewatcher_iron_handAI (_Creature); +} + +void AddSC_boss_gatewatcher_iron_hand() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_gatewatcher_iron_hand"; + newscript->GetAI = GetAI_boss_gatewatcher_iron_hand; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/tempest_keep/the_mechanar/boss_nethermancer_sepethrea.cpp b/src/bindings/scripts/scripts/zone/tempest_keep/the_mechanar/boss_nethermancer_sepethrea.cpp new file mode 100644 index 00000000000..e5012885d93 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/tempest_keep/the_mechanar/boss_nethermancer_sepethrea.cpp @@ -0,0 +1,223 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss Nethermancer Sepethrea +SD%Complete: 100 +SDComment: +SDCategory: Tempest Keep, The Mechanar +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_SUMMON_RAGIN_FLAMES 35275 +#define SPELL_INFERNO 19695 +#define SPELL_FIRE_TAIL 35278 + +#define SPELL_FROST_ATTACK 35263 +#define SPELL_ARCANE_BLAST 35314 +#define SPELL_DRAGONS_BREATH 35250 +#define SPELL_KNOCKBACK 37317 +#define SPELL_SOLARBURN 35267 + +#define SAY_SPELL_DRAGONS_BREATH_1 "Think you can take the heat?" +#define SOUND_SPELL_DRAGONS_BREATH_1 11189 +#define SAY_SPELL_DRAGONS_BREATH_2 "Anar'endal dracon!" +#define SOUND_SPELL_DRAGONS_BREATH_2 11190 + +#define SAY_AGGRO "Don't value your life very much, do you?" +#define SOUND_SAY_AGGRO 11186 + +#define SAY_SLAY "And don't come back!" +#define SOUND_SLAY 11187 + +#define SAY_DEATH "Anu... bala belore...alon." +#define SOUND_DEATH 11192 + +struct MANGOS_DLL_DECL boss_nethermancer_sepethreaAI : public ScriptedAI +{ + boss_nethermancer_sepethreaAI(Creature *c) : ScriptedAI(c) { Reset(); } + + uint32 frost_attack_Timer; + uint32 arcane_blast_Timer; + uint32 dragons_breath_Timer; + uint32 knockback_Timer; + uint32 solarburn_Timer; + + void Reset() + { + frost_attack_Timer = 10000; + arcane_blast_Timer = 15000; + dragons_breath_Timer = 20000; + knockback_Timer = 25000; + solarburn_Timer = 30000; + } + + void Aggro(Unit *who) + { + } + + void KilledUnit(Unit* victim) + { + DoYell(SAY_SLAY, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY); + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_DEATH); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //Frost Attack + if(frost_attack_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FROST_ATTACK); + frost_attack_Timer = 10000; + }else frost_attack_Timer -= diff; + + //Arcane Blast + if(arcane_blast_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_ARCANE_BLAST); + arcane_blast_Timer = 15000; + }else arcane_blast_Timer -= diff; + + //Dragons Breath + if(dragons_breath_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_DRAGONS_BREATH); + dragons_breath_Timer = 20000; + + if (rand()%2) + return; + + switch(rand()%2) + { + case 0: + DoYell(SAY_SPELL_DRAGONS_BREATH_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_SPELL_DRAGONS_BREATH_1); + break; + case 1: + DoYell(SAY_SPELL_DRAGONS_BREATH_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_SPELL_DRAGONS_BREATH_2); + break; + } + }else dragons_breath_Timer -= diff; + + //Knockback + if(knockback_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_KNOCKBACK); + knockback_Timer = 25000; + }else knockback_Timer -= diff; + + //Solarburn + if(solarburn_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SOLARBURN); + solarburn_Timer = 30000; + }else solarburn_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_nethermancer_sepethrea(Creature *_Creature) +{ + return new boss_nethermancer_sepethreaAI (_Creature); +} + +struct MANGOS_DLL_DECL mob_ragin_flamesAI : public ScriptedAI +{ + mob_ragin_flamesAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 inferno_Timer; + uint32 flame_timer; + + bool onlyonce; + + void Reset() + { + inferno_Timer = 10000; + flame_timer = 200; + onlyonce = false; + } + + void Aggro(Unit* who) + { + } + + void UpdateAI(const uint32 diff) + { + Unit* target = NULL; + + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if (!onlyonce) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + + m_creature->GetMotionMaster()->MoveChase(target); + onlyonce = true; + } + + if(inferno_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_INFERNO); + inferno_Timer = 10000; + + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + + m_creature->GetMotionMaster()->MoveChase(target); + }else inferno_Timer -= diff; + + if(flame_timer < diff) + { + DoCast(m_creature,SPELL_FIRE_TAIL); + flame_timer = 200; + }else flame_timer -=diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_mob_ragin_flames(Creature *_Creature) +{ + return new mob_ragin_flamesAI (_Creature); +} + +void AddSC_boss_nethermancer_sepethrea() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_nethermancer_sepethrea"; + newscript->GetAI = GetAI_boss_nethermancer_sepethrea; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_ragin_flames"; + newscript->GetAI = GetAI_mob_ragin_flames; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_bug_trio.cpp b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_bug_trio.cpp new file mode 100644 index 00000000000..2592d8e8297 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_bug_trio.cpp @@ -0,0 +1,384 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: boss_kri, boss_yauj, boss_vem : The Bug Trio +SD%Complete: 100 +SDComment: +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "precompiled.h" +#include "def_temple_of_ahnqiraj.h" + +#define SPELL_CLEAVE 26350 +#define SPELL_TOXIC_VOLLEY 25812 +#define SPELL_POISON_CLOUD 38718 //Only Spell with right dmg. +#define SPELL_ENRAGE 34624 //Changed cause 25790 is casted on gamers too. Same prob with old explosion of twin emperors. + +#define SPELL_CHARGE 26561 +#define SPELL_KNOCKBACK 26027 + +#define SPELL_HEAL 25807 +#define SPELL_FEAR 19408 + +struct MANGOS_DLL_DECL boss_kriAI : public ScriptedAI +{ + boss_kriAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance *pInstance; + + uint32 Cleave_Timer; + uint32 ToxicVolley_Timer; + uint32 Check_Timer; + + bool VemDead; + bool Death; + + void Reset() + { + Cleave_Timer = 4000 + rand()%4000; + ToxicVolley_Timer = 6000 + rand()%6000; + Check_Timer = 2000; + + VemDead = false; + Death = false; + } + + void Aggro(Unit *who) + { + } + + void JustDied(Unit* killer) + { + if(pInstance) + { + if(pInstance->GetData(DATA_BUG_TRIO_DEATH) < 2) + // Unlootable if death + m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + + pInstance->SetData(DATA_BUG_TRIO_DEATH, 1); + } + } + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //Cleave_Timer + if (Cleave_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CLEAVE); + Cleave_Timer = 5000 + rand()%7000; + }else Cleave_Timer -= diff; + + //ToxicVolley_Timer + if (ToxicVolley_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_TOXIC_VOLLEY); + ToxicVolley_Timer = 10000 + rand()%5000; + }else ToxicVolley_Timer -= diff; + + if (m_creature->GetHealth() <= m_creature->GetMaxHealth() * 0.05 && !Death) + { + DoCast(m_creature->getVictim(),SPELL_POISON_CLOUD); + Death = true; + } + + if(!VemDead) + { + //Checking if Vem is dead. If yes we will enrage. + if(Check_Timer < diff) + { + if(pInstance && pInstance->GetData(DATA_VEMISDEAD)) + { + DoCast(m_creature, SPELL_ENRAGE); + VemDead = true; + } + Check_Timer = 2000; + }else Check_Timer -=diff; + } + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL boss_vemAI : public ScriptedAI +{ + boss_vemAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance *pInstance; + + uint32 Charge_Timer; + uint32 KnockBack_Timer; + uint32 Enrage_Timer; + + bool Enraged; + + void Reset() + { + Charge_Timer = 15000 + rand()%12000; + KnockBack_Timer = 8000 + rand()%12000; + Enrage_Timer = 120000; + + Enraged = false; + } + + void JustDied(Unit* Killer) + { + if(pInstance) + { + pInstance->SetData(DATA_VEM_DEATH, 0); + if(pInstance->GetData(DATA_BUG_TRIO_DEATH) < 2) + // Unlootable if death + m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + pInstance->SetData(DATA_BUG_TRIO_DEATH, 1); + } + } + + void Aggro(Unit *who) + { + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || m_creature->getVictim()) + return; + + if (who->isTargetableForAttack() && IsVisible(who) && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + float attackRadius = m_creature->GetAttackDistance(who); + if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) + { + if(who->HasStealthAura()) + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + //Begin melee attack if we are within range + DoStartAttackAndMovement(who); + } + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //Charge_Timer + if (Charge_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if(target) + { + DoCast(target, SPELL_CHARGE); + m_creature->SendMonsterMove(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, true,1); + DoStartAttackAndMovement(target); + } + + Charge_Timer = 8000 + rand()%8000; + }else Charge_Timer -= diff; + + //KnockBack_Timer + if (KnockBack_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_KNOCKBACK); + if(m_creature->getThreatManager().getThreat(m_creature->getVictim())) + m_creature->getThreatManager().modifyThreatPercent(m_creature->getVictim(),-80); + KnockBack_Timer = 15000 + rand()%10000; + }else KnockBack_Timer -= diff; + + //Enrage_Timer + if (!Enraged && Enrage_Timer < diff) + { + DoCast(m_creature,SPELL_ENRAGE); + Enraged = true; + }else Charge_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL boss_yaujAI : public ScriptedAI +{ + boss_yaujAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance *pInstance; + + uint32 Heal_Timer; + uint32 Fear_Timer; + uint32 Check_Timer; + + bool VemDead; + + void Reset() + { + Heal_Timer = 25000 + rand()%15000; + Fear_Timer = 12000 + rand()%12000; + Check_Timer = 2000; + + VemDead = false; + } + + void JustDied(Unit* Killer) + { + if(pInstance) + { + if(pInstance->GetData(DATA_BUG_TRIO_DEATH) < 2) + // Unlootable if death + m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + pInstance->SetData(DATA_BUG_TRIO_DEATH, 1); + } + + for(int i = 0; i < 10;i++) + { + Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0); + Creature* Summoned = m_creature->SummonCreature(15621,m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(),0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,90000); + if(Summoned) + ((CreatureAI*)Summoned->AI())->AttackStart(target); + } + } + + void Aggro(Unit *who) + { + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || m_creature->getVictim()) + return; + + if (who->isTargetableForAttack() && IsVisible(who) && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + float attackRadius = m_creature->GetAttackDistance(who); + if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) + { + if(who->HasStealthAura()) + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + //Begin melee attack if we are within range + DoStartAttackAndMovement(who); + } + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //Fear_Timer + if (Fear_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FEAR); + DoResetThreat(); + Fear_Timer = 20000; + }else Fear_Timer -= diff; + + //Casting Heal to other twins or herself. + if(Heal_Timer < diff) + { + if(pInstance) + { + Unit *pKri = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_KRI)); + Unit *pVem = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_VEM)); + + switch(rand()%3) + { + case 0: + if(pKri) + DoCast(pKri, SPELL_HEAL); + break; + case 1: + if(pVem) + DoCast(pVem, SPELL_HEAL); + break; + case 2: + DoCast(m_creature, SPELL_HEAL); + break; + } + } + + Heal_Timer = 15000+rand()%15000; + }else Heal_Timer -= diff; + + //Checking if Vem is dead. If yes we will enrage. + if(Check_Timer < diff) + { + if (!VemDead) + { + if(pInstance) + { + if(pInstance->GetData(DATA_VEMISDEAD)) + { + DoCast(m_creature, SPELL_ENRAGE); + VemDead = true; + } + } + } + Check_Timer = 2000; + }else Check_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_yauj(Creature *_Creature) +{ + return new boss_yaujAI (_Creature); +} + +CreatureAI* GetAI_boss_vem(Creature *_Creature) +{ + return new boss_vemAI (_Creature); +} + +CreatureAI* GetAI_boss_kri(Creature *_Creature) +{ + return new boss_kriAI (_Creature); +} + +void AddSC_bug_trio() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_kri"; + newscript->GetAI = GetAI_boss_kri; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_vem"; + newscript->GetAI = GetAI_boss_vem; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_yauj"; + newscript->GetAI = GetAI_boss_yauj; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_cthun.cpp b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_cthun.cpp new file mode 100644 index 00000000000..a01de84604b --- /dev/null +++ b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_cthun.cpp @@ -0,0 +1,1360 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Cthun +SD%Complete: 95 +SDComment: Darkglare tracking issue +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "precompiled.h" +#include "def_temple_of_ahnqiraj.h" + +#define PI 3.14 + +//****** Out of Combat ****** +//Random Wispers - No txt only sound +#define RND_WISPER_1 8580 //Death is close +#define RND_WISPER_2 8581 //You are already dead +#define RND_WISPER_3 8582 //Your courage will fail +#define RND_WISPER_4 8583 //Your friends will abandon you +#define RND_WISPER_5 8584 //You will betray your friends +#define RND_WISPER_6 8585 //You will die +#define RND_WISPER_7 8586 //You are weak +#define RND_WISPER_8 8587 //Your heart will explode + +//***** Phase 1 ******** + +//Mobs +#define BOSS_EYE_OF_CTHUN 15589 +#define MOB_CLAW_TENTACLE 15725 +#define MOB_EYE_TENTACLE 15726 +#define MOB_SMALL_PORTAL 15904 + +//Eye Spells +#define SPELL_GREEN_BEAM 26134 +#define SPELL_DARK_GLARE 26029 +#define SPELL_RED_COLORATION 22518 //Probably not the right spell but looks similar + +//Eye Tentacles Spells +#define SPELL_MIND_FLAY 26143 + +//Claw Tentacles Spells +#define SPELL_GROUND_RUPTURE 26139 +#define SPELL_HAMSTRING 26141 + +#define MOB_ + +//*****Phase 2****** +//Body spells +//#define SPELL_CARAPACE_CTHUN 26156 //Was removed from client dbcs +#define SPELL_TRANSFORM 26232 + +//Eye Tentacles Spells +//SAME AS PHASE1 + +//Giant Claw Tentacles +#define SPELL_MASSIVE_GROUND_RUPTURE 26100 + +//Also casts Hamstring +#define SPELL_THRASH 3391 + +//Giant Eye Tentacles +//CHAIN CASTS "SPELL_GREEN_BEAM" + +//Stomach Spells +#define SPELL_MOUTH_TENTACLE 26332 +#define SPELL_EXIT_STOMACH_KNOCKBACK 25383 +#define SPELL_DIGESTIVE_ACID 26476 + +//Mobs +#define MOB_BODY_OF_CTHUN 15809 +#define MOB_GIANT_CLAW_TENTACLE 15728 +#define MOB_GIANT_EYE_TENTACLE 15334 +#define MOB_FLESH_TENTACLE 15802 +#define MOB_GIANT_PORTAL 15910 + +//Text emote +#define EMOTE_WEAKENED "is weakened!" + +//Stomach Teleport positions +#define STOMACH_X -8562.0f +#define STOMACH_Y 2037.0f +#define STOMACH_Z -70.0f +#define STOMACH_O 5.05f + +//Flesh tentacle positions +#define TENTACLE_POS1_X -8571.0f +#define TENTACLE_POS1_Y 1990.0f +#define TENTACLE_POS1_Z -98.0f +#define TENTACLE_POS1_O 1.22f + +#define TENTACLE_POS2_X -8525.0f +#define TENTACLE_POS2_Y 1994.0f +#define TENTACLE_POS2_Z -98.0f +#define TENTACLE_POS2_O 2.12f + +//Kick out position +#define KICK_X -8545.0f +#define KICK_Y 1984.0f +#define KICK_Z -96.0f + +struct MANGOS_DLL_DECL flesh_tentacleAI : public Scripted_NoMovementAI +{ + flesh_tentacleAI(Creature *c) : Scripted_NoMovementAI(c), Parent(0) {Reset();} + + uint64 Parent; + uint32 CheckTimer; + + void SpawnedByCthun(uint64 p) + { + Parent = p; + } + + void Reset() + { + CheckTimer = 1000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff); + + void JustDied(Unit* killer); +}; + +struct MANGOS_DLL_DECL eye_of_cthunAI : public Scripted_NoMovementAI +{ + eye_of_cthunAI(Creature *c) : Scripted_NoMovementAI(c) + { + pInst = (ScriptedInstance*)c->GetInstanceData(); + if (!pInst) + error_log("SD2: No Instance eye_of_cthunAI"); + + Reset(); + } + + ScriptedInstance* pInst; + + //Global variables + uint32 PhaseTimer; + + //Eye beam phase + uint32 BeamTimer; + uint32 EyeTentacleTimer; + uint32 ClawTentacleTimer; + + //Dark Glare phase + uint32 DarkGlareTick; + uint32 DarkGlareTickTimer; + float DarkGlareAngle; + bool ClockWise; + + void Reset() + { + //Phase information + PhaseTimer = 50000; //First dark glare in 50 seconds + + //Eye beam phase 50 seconds + BeamTimer = 3000; + EyeTentacleTimer = 45000; //Always spawns 5 seconds before Dark Beam + ClawTentacleTimer = 12500; //4 per Eye beam phase (unsure if they spawn durring Dark beam) + + //Dark Beam phase 35 seconds (each tick = 1 second, 35 ticks) + DarkGlareTick = 0; + DarkGlareTickTimer = 1000; + DarkGlareAngle = 0; + ClockWise = false; + + //Reset flags + m_creature->RemoveAurasDueToSpell(SPELL_RED_COLORATION); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + + //Reset Phase + if (pInst) + pInst->SetData(DATA_CTHUN_PHASE, 0); + } + + void Aggro(Unit *who) + { + DoZoneInCombat(); + } + + void SpawnEyeTentacle(float x, float y) + { + Creature* Spawned; + Spawned = (Creature*)m_creature->SummonCreature(MOB_EYE_TENTACLE,m_creature->GetPositionX()+x,m_creature->GetPositionY()+y,m_creature->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,500); + if (Spawned) + { + Unit* target; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + + if (target) + Spawned->AI()->AttackStart(target); + } + } + + void UpdateAI(const uint32 diff) + { + //Check if we have a target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //No instance + if (!pInst) + return; + + switch (pInst->GetData(DATA_CTHUN_PHASE)) + { + case 0: + { + //BeamTimer + if (BeamTimer < diff) + { + //SPELL_GREEN_BEAM + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) + { + m_creature->InterruptNonMeleeSpells(false); + DoCast(target,SPELL_GREEN_BEAM); + + //Correctly update our target + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, target->GetGUID()); + } + + //Beam every 3 seconds + BeamTimer = 3000; + }else BeamTimer -= diff; + + //ClawTentacleTimer + if (ClawTentacleTimer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) + { + Creature* Spawned = NULL; + + //Spawn claw tentacle on the random target + Spawned = (Creature*)m_creature->SummonCreature(MOB_CLAW_TENTACLE,target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,500); + + if (Spawned) + Spawned->AI()->AttackStart(target); + } + + //One claw tentacle every 12.5 seconds + ClawTentacleTimer = 12500; + }else ClawTentacleTimer -= diff; + + //EyeTentacleTimer + if (EyeTentacleTimer < diff) + { + //Spawn the 8 Eye Tentacles in the corret spots + SpawnEyeTentacle(0, 20); //south + SpawnEyeTentacle(10, 10); //south west + SpawnEyeTentacle(20, 0); //west + SpawnEyeTentacle(10, -10); //north west + + SpawnEyeTentacle(0, -20); //north + SpawnEyeTentacle(-10, -10); //north east + SpawnEyeTentacle(-20, 0); // east + SpawnEyeTentacle(-10, 10); // south east + + //No point actually putting a timer here since + //These shouldn't trigger agian until after phase shifts + EyeTentacleTimer = 45000; + }else EyeTentacleTimer -= diff; + + //PhaseTimer + if (PhaseTimer < diff) + { + //Switch to Dark Beam + pInst->SetData(DATA_CTHUN_PHASE, 1); + + m_creature->InterruptNonMeleeSpells(false); + + //Select random target for dark beam to start on + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + + if (target) + { + //Correctly update our target + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, target->GetGUID()); + + //Face our target + DarkGlareAngle = m_creature->GetAngle(target); + DarkGlareTickTimer = 1000; + DarkGlareTick = 0; + ClockWise = rand()%2; + } + + //Add red coloration to C'thun + DoCast(m_creature,SPELL_RED_COLORATION); + + //Freeze animation + m_creature->setEmoteState(53); + + //Darkbeam for 35 seconds + PhaseTimer = 35000; + }else PhaseTimer -= diff; + + } + break; + case 1: + { + //EyeTentacleTimer + if (DarkGlareTick < 35) + if (DarkGlareTickTimer < diff) + { + //Remove any target + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0); + + //Set angle and cast + if (ClockWise) + m_creature->SetOrientation(DarkGlareAngle + ((float)DarkGlareTick*PI/35)); + else m_creature->SetOrientation(DarkGlareAngle - ((float)DarkGlareTick*PI/35)); + + m_creature->StopMoving(); + + //Actual dark glare cast, maybe something missing here? + m_creature->CastSpell(NULL, SPELL_DARK_GLARE, false); + + //Increase tick + DarkGlareTick++; + + //1 second per tick + DarkGlareTickTimer = 1000; + }else DarkGlareTickTimer -= diff; + + //PhaseTimer + if (PhaseTimer < diff) + { + //Switch to Eye Beam + pInst->SetData(DATA_CTHUN_PHASE, 0); + + BeamTimer = 3000; + EyeTentacleTimer = 45000; //Always spawns 5 seconds before Dark Beam + ClawTentacleTimer = 12500; //4 per Eye beam phase (unsure if they spawn durring Dark beam) + + m_creature->InterruptNonMeleeSpells(false); + + //Remove Red coloration from c'thun + m_creature->RemoveAurasDueToSpell(SPELL_RED_COLORATION); + + //Freeze animation + m_creature->setEmoteState(0); + m_creature->SetUInt32Value(UNIT_FIELD_FLAGS, 0); + + //Eye Beam for 50 seconds + PhaseTimer = 50000; + }else PhaseTimer -= diff; + }break; + + //Transition phase + case 2: + { + //Remove any target + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0); + m_creature->SetHealth(0); + } + + //Dead phase + case 5: + { + m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false); + } + } + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + //No instance + if (!pInst) + return; + + switch (pInst->GetData(DATA_CTHUN_PHASE)) + { + case 0: + case 1: + { + //Only if it will kill + if (damage < m_creature->GetHealth()) + return; + + //Fake death in phase 0 or 1 (green beam or dark glare phase) + m_creature->InterruptNonMeleeSpells(false); + + //Remove Red coloration from c'thun + m_creature->RemoveAurasDueToSpell(SPELL_RED_COLORATION); + + //Reset to normal emote state and prevent select and attack + m_creature->setEmoteState(0); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + + //Remove Target field + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0); + + //Death animation/respawning; + pInst->SetData(DATA_CTHUN_PHASE, 2); + + m_creature->SetHealth(0); + damage = 0; + + m_creature->InterruptNonMeleeSpells(true); + m_creature->RemoveAllAuras(); + } + break; + + case 5: + { + //Allow death here + return; + } + + default: + { + //Prevent death in this phase + damage = 0; + return; + } + break; + } + } +}; + +struct MANGOS_DLL_DECL cthunAI : public Scripted_NoMovementAI +{ + cthunAI(Creature *c) : Scripted_NoMovementAI(c) + { + pInst = (ScriptedInstance*)c->GetInstanceData(); + if (!pInst) + error_log("SD2: No Instance eye_of_cthunAI"); + + Reset(); + } + + ScriptedInstance* pInst; + + //Out of combat whisper timer + uint32 WisperTimer; + + //Global variables + uint32 PhaseTimer; + + //------------------- + + //Phase transition + uint64 HoldPlayer; + + //Body Phase + uint32 EyeTentacleTimer; + uint8 FleshTentaclesKilled; + uint32 GiantClawTentacleTimer; + uint32 GiantEyeTentacleTimer; + uint32 StomachAcidTimer; + uint32 StomachEnterTimer; + uint32 StomachEnterVisTimer; + uint64 StomachEnterTarget; + + //Stomach map, bool = true then in stomach + HM_NAMESPACE::hash_map Stomach_Map; + + void Reset() + { + //One random wisper every 90 - 300 seconds + WisperTimer = 90000; + + //Phase information + PhaseTimer = 10000; //Emerge in 10 seconds + + //No hold player for transition + HoldPlayer = 0; + + //Body Phase + EyeTentacleTimer = 30000; + FleshTentaclesKilled = 0; + GiantClawTentacleTimer = 15000; //15 seconds into body phase (1 min repeat) + GiantEyeTentacleTimer = 45000; //15 seconds into body phase (1 min repeat) + StomachAcidTimer = 4000; //Every 4 seconds + StomachEnterTimer = 10000; //Every 10 seconds + StomachEnterVisTimer = 0; //Always 3.5 seconds after Stomach Enter Timer + StomachEnterTarget = 0; //Target to be teleported to stomach + + //Clear players in stomach and outside + Stomach_Map.clear(); + + //Reset flags + m_creature->RemoveAurasDueToSpell(SPELL_TRANSFORM); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + + if (pInst) + pInst->SetData(DATA_CTHUN_PHASE, 0); + } + + void Aggro(Unit *who) + { + DoZoneInCombat(); + } + + void SpawnEyeTentacle(float x, float y) + { + Creature* Spawned; + Spawned = (Creature*)m_creature->SummonCreature(MOB_EYE_TENTACLE,m_creature->GetPositionX()+x,m_creature->GetPositionY()+y,m_creature->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,500); + if (Spawned) + { + Unit* target; + + target = SelectRandomNotStomach(); + + if (target) + Spawned->AI()->AttackStart(target); + } + } + + Unit* SelectRandomNotStomach() + { + if (Stomach_Map.empty()) + return NULL; + + HM_NAMESPACE::hash_map::iterator i = Stomach_Map.begin(); + + std::list temp; + std::list::iterator j; + + //Get all players in map + while (i != Stomach_Map.end()) + { + //Check for valid player + Unit* pUnit = Unit::GetUnit(*m_creature, i->first); + + //Only units out of stomach + if (pUnit && i->second == false) + { + temp.push_back(pUnit); + } + ++i; + } + + if (temp.empty()) + return NULL; + + j = temp.begin(); + + //Get random but only if we have more than one unit on threat list + if (temp.size() > 1) + advance ( i , rand() % (temp.size() - 1) ); + + return (*j); + } + + void UpdateAI(const uint32 diff) + { + //Check if we have a target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + { + //No target so we'll use this section to do our random wispers instance wide + //WisperTimer + if (WisperTimer < diff) + { + Map *map = m_creature->GetMap(); + if(!map->IsDungeon()) return; + + InstanceMap::PlayerList const &PlayerList = ((InstanceMap*)map)->GetPlayers(); + for (InstanceMap::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + //Play random sound to the zone + switch (rand()%8) + { + case 0: (*i)->PlaySound(RND_WISPER_1, true); break; + case 1: (*i)->PlaySound(RND_WISPER_2, true); break; + case 2: (*i)->PlaySound(RND_WISPER_3, true); break; + case 3: (*i)->PlaySound(RND_WISPER_4, true); break; + case 4: (*i)->PlaySound(RND_WISPER_5, true); break; + case 5: (*i)->PlaySound(RND_WISPER_6, true); break; + case 6: (*i)->PlaySound(RND_WISPER_7, true); break; + case 7: (*i)->PlaySound(RND_WISPER_8, true); break; + } + } + + //One random wisper every 90 - 300 seconds + WisperTimer = 90000 + (rand()% 210000); + }else WisperTimer -= diff; + + return; + } + + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0); + + //No instance + if (!pInst) + return; + + switch (pInst->GetData(DATA_CTHUN_PHASE)) + { + //Transition phase + case 2: + { + //PhaseTimer + if (PhaseTimer < diff) + { + //Switch + pInst->SetData(DATA_CTHUN_PHASE, 3); + + //Switch to c'thun model + m_creature->InterruptNonMeleeSpells(false); + DoCast(m_creature, SPELL_TRANSFORM, false); + m_creature->SetHealth(m_creature->GetMaxHealth()); + + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + + //Emerging phase + //AttackStart(Unit::GetUnit(*m_creature, HoldPlayer)); + DoZoneInCombat(); + + //Place all units in threat list on outside of stomach + Stomach_Map.clear(); + + std::list::iterator i = m_creature->getThreatManager().getThreatList().begin(); + for (; i != m_creature->getThreatManager().getThreatList().end(); ++i) + { + //Outside stomach + Stomach_Map[(*i)->getUnitGuid()] = false; + } + + //Spawn 2 flesh tentacles + FleshTentaclesKilled = 0; + + Creature* Spawned; + + //Spawn flesh tentacle + Spawned = (Creature*)m_creature->SummonCreature(MOB_FLESH_TENTACLE, TENTACLE_POS1_X, TENTACLE_POS1_Y, TENTACLE_POS1_Z, TENTACLE_POS1_O, TEMPSUMMON_CORPSE_DESPAWN, 0); + + if (!Spawned) + FleshTentaclesKilled++; + else + ((flesh_tentacleAI*)(Spawned->AI()))->SpawnedByCthun(m_creature->GetGUID()); + + //Spawn flesh tentacle + Spawned = (Creature*)m_creature->SummonCreature(MOB_FLESH_TENTACLE, TENTACLE_POS2_X, TENTACLE_POS2_Y, TENTACLE_POS2_Z, TENTACLE_POS2_O, TEMPSUMMON_CORPSE_DESPAWN, 0); + + if (!Spawned) + FleshTentaclesKilled++; + else + ((flesh_tentacleAI*)(Spawned->AI()))->SpawnedByCthun(m_creature->GetGUID()); + + PhaseTimer = 0; + }else PhaseTimer -= diff; + + }break; + + //Body Phase + case 3: + { + //Remove Target field + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0); + + //Weaken + if (FleshTentaclesKilled > 1) + { + pInst->SetData(DATA_CTHUN_PHASE, 4); + + DoTextEmote(EMOTE_WEAKENED, NULL); + PhaseTimer = 45000; + + DoCast(m_creature, SPELL_RED_COLORATION, true); + + HM_NAMESPACE::hash_map::iterator i = Stomach_Map.begin(); + + //Kick all players out of stomach + while (i != Stomach_Map.end()) + { + //Check for valid player + Unit* pUnit = Unit::GetUnit(*m_creature, i->first); + + //Only move units in stomach + if (pUnit && i->second == true) + { + //Teleport each player out + DoTeleportPlayer(pUnit, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ()+10, rand()%6); + + //Cast knockback on them + DoCast(pUnit, SPELL_EXIT_STOMACH_KNOCKBACK, true); + + //Remove the acid debuff + pUnit->RemoveAurasDueToSpell(SPELL_DIGESTIVE_ACID); + + i->second = false; + } + ++i; + } + + return; + } + + //Stomach acid + if (StomachAcidTimer < diff) + { + //Apply aura to all players in stomach + HM_NAMESPACE::hash_map::iterator i = Stomach_Map.begin(); + + while (i != Stomach_Map.end()) + { + //Check for valid player + Unit* pUnit = Unit::GetUnit(*m_creature, i->first); + + //Only apply to units in stomach + if (pUnit && i->second == true) + { + //Cast digestive acid on them + DoCast(pUnit, SPELL_DIGESTIVE_ACID, true); + + //Check if player should be kicked from stomach + if (pUnit->GetDistance(KICK_X, KICK_Y, KICK_Z) < 15) + { + //Teleport each player out + DoTeleportPlayer(pUnit, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ()+10, rand()%6); + + //Cast knockback on them + DoCast(pUnit, SPELL_EXIT_STOMACH_KNOCKBACK, true); + + //Remove the acid debuff + pUnit->RemoveAurasDueToSpell(SPELL_DIGESTIVE_ACID); + + i->second = false; + } + } + ++i; + } + + StomachAcidTimer = 4000; + }else StomachAcidTimer -= diff; + + //Stomach Enter Timer + if (StomachEnterTimer < diff) + { + Unit* target = NULL; + target = SelectRandomNotStomach(); + + if (target) + { + //Set target in stomach + Stomach_Map[target->GetGUID()] = true; + target->InterruptNonMeleeSpells(false); + target->CastSpell(target, SPELL_MOUTH_TENTACLE, true, NULL, NULL, m_creature->GetGUID()); + StomachEnterTarget = target->GetGUID(); + StomachEnterVisTimer = 3800; + } + + StomachEnterTimer = 13800; + }else StomachEnterTimer -= diff; + + if (StomachEnterVisTimer && StomachEnterTarget) + if (StomachEnterVisTimer <= diff) + { + //Check for valid player + Unit* pUnit = Unit::GetUnit(*m_creature, StomachEnterTarget); + + if (pUnit) + { + DoTeleportPlayer(pUnit, STOMACH_X, STOMACH_Y, STOMACH_Z, STOMACH_O); + } + + StomachEnterTarget = 0; + StomachEnterVisTimer = 0; + }else StomachEnterVisTimer -= diff; + + //GientClawTentacleTimer + if (GiantClawTentacleTimer < diff) + { + Unit* target = NULL; + target = SelectRandomNotStomach(); + if (target) + { + Creature* Spawned = NULL; + + //Spawn claw tentacle on the random target + Spawned = (Creature*)m_creature->SummonCreature(MOB_GIANT_CLAW_TENTACLE,target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,500); + + if (Spawned) + Spawned->AI()->AttackStart(target); + } + + //One giant claw tentacle every minute + GiantClawTentacleTimer = 60000; + }else GiantClawTentacleTimer -= diff; + + //GiantEyeTentacleTimer + if (GiantEyeTentacleTimer < diff) + { + Unit* target = NULL; + target = SelectRandomNotStomach(); + if (target) + { + + Creature* Spawned = NULL; + + //Spawn claw tentacle on the random target + Spawned = (Creature*)m_creature->SummonCreature(MOB_GIANT_EYE_TENTACLE,target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,500); + + if (Spawned) + Spawned->AI()->AttackStart(target); + } + + //One giant eye tentacle every minute + GiantEyeTentacleTimer = 60000; + }else GiantEyeTentacleTimer -= diff; + + //EyeTentacleTimer + if (EyeTentacleTimer < diff) + { + //Spawn the 8 Eye Tentacles in the corret spots + SpawnEyeTentacle(0, 25); //south + SpawnEyeTentacle(12, 12); //south west + SpawnEyeTentacle(25, 0); //west + SpawnEyeTentacle(12, -12); //north west + + SpawnEyeTentacle(0, -25); //north + SpawnEyeTentacle(-12, -12); //north east + SpawnEyeTentacle(-25, 0); // east + SpawnEyeTentacle(-12, 12); // south east + + //These spawn at every 30 seconds + EyeTentacleTimer = 30000; + }else EyeTentacleTimer -= diff; + + }break; + + //Weakened state + case 4: + { + //PhaseTimer + if (PhaseTimer < diff) + { + //Switch + pInst->SetData(DATA_CTHUN_PHASE, 3); + + //Remove red coloration + m_creature->RemoveAurasDueToSpell(SPELL_RED_COLORATION); + + //Spawn 2 flesh tentacles + FleshTentaclesKilled = 0; + + Creature* Spawned; + + //Spawn flesh tentacle + Spawned = (Creature*)m_creature->SummonCreature(MOB_FLESH_TENTACLE, TENTACLE_POS1_X, TENTACLE_POS1_Y, TENTACLE_POS1_Z, TENTACLE_POS1_O, TEMPSUMMON_CORPSE_DESPAWN, 0); + + if (!Spawned) + FleshTentaclesKilled++; + else + ((flesh_tentacleAI*)(Spawned->AI()))->SpawnedByCthun(m_creature->GetGUID()); + + //Spawn flesh tentacle + Spawned = (Creature*)m_creature->SummonCreature(MOB_FLESH_TENTACLE, TENTACLE_POS2_X, TENTACLE_POS2_Y, TENTACLE_POS2_Z, TENTACLE_POS2_O, TEMPSUMMON_CORPSE_DESPAWN, 0); + + if (!Spawned) + FleshTentaclesKilled++; + else + ((flesh_tentacleAI*)(Spawned->AI()))->SpawnedByCthun(m_creature->GetGUID()); + + PhaseTimer = 0; + }else PhaseTimer -= diff; + } + } + } + + void JustDied(Unit* pKiller) + { + //Switch + if( pInst ) + pInst->SetData(DATA_CTHUN_PHASE, 5); + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + //No instance + if (!pInst) + return; + + switch (pInst->GetData(DATA_CTHUN_PHASE)) + { + case 3: + { + //Not weakened so reduce damage by 99% + if (damage / 99 > 0) damage/= 99; + else damage = 1; + + //Prevent death in non-weakened state + if (damage >= m_creature->GetHealth()) + damage = 0; + + return; + } + break; + + case 4: + { + //Weakened - takes normal damage + return; + } + + default: + damage = 0; + break; + } + } + + void FleshTentcleKilled() + { + FleshTentaclesKilled++; + } +}; + +struct MANGOS_DLL_DECL eye_tentacleAI : public Scripted_NoMovementAI +{ + eye_tentacleAI(Creature *c) : Scripted_NoMovementAI(c) + { + Reset(); + Unit* p = DoSpawnCreature(MOB_SMALL_PORTAL,0,0,0,0,TEMPSUMMON_CORPSE_DESPAWN, 0); + if (p) + Portal = p->GetGUID(); + } + + uint32 MindflayTimer; + uint32 KillSelfTimer; + uint64 Portal; + + void JustDied(Unit*) + { + Unit* p = Unit::GetUnit(*m_creature, Portal); + if (p) + p->DealDamage(p, p->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false); + } + + void Reset() + { + //Mind flay half a second after we spawn + MindflayTimer = 500; + + //This prevents eyes from overlapping + KillSelfTimer = 35000; + } + + void Aggro(Unit *who) + { + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + //Check if we have a target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //KillSelfTimer + if (KillSelfTimer < diff) + { + m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false); + + return; + }else KillSelfTimer -= diff; + + //MindflayTimer + if (MindflayTimer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target && !target->HasAura(SPELL_DIGESTIVE_ACID, 0)) + DoCast(target,SPELL_MIND_FLAY); + + //Mindflay every 10 seconds + MindflayTimer = 10100; + }else MindflayTimer -= diff; + } +}; + +struct MANGOS_DLL_DECL claw_tentacleAI : public Scripted_NoMovementAI +{ + claw_tentacleAI(Creature *c) : Scripted_NoMovementAI(c) + { + Reset(); + Unit* p = DoSpawnCreature(MOB_SMALL_PORTAL,0,0,0,0,TEMPSUMMON_CORPSE_DESPAWN, 0); + if (p) + Portal = p->GetGUID(); + } + + uint32 GroundRuptureTimer; + uint32 HamstringTimer; + uint32 EvadeTimer; + uint64 Portal; + + void JustDied(Unit*) + { + Unit* p = Unit::GetUnit(*m_creature, Portal); + if (p) + p->DealDamage(p, p->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false); + } + + void Reset() + { + //First rupture should happen half a second after we spawn + GroundRuptureTimer = 500; + HamstringTimer = 2000; + EvadeTimer = 5000; + } + + void Aggro(Unit *who) + { + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + //Check if we have a target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //EvadeTimer + if (m_creature->GetDistance(m_creature->getVictim()) > ATTACK_DISTANCE) + if (EvadeTimer < diff) + { + Unit* p = Unit::GetUnit(*m_creature, Portal); + if (p) + p->DealDamage(p, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false); + + //Dissapear and reappear at new position + m_creature->SetVisibility(VISIBILITY_OFF); + + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (!target) + { + m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false); + return; + } + + if (!target->HasAura(SPELL_DIGESTIVE_ACID, 0)) + { + m_creature->GetMap()->CreatureRelocation(m_creature, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0); + Unit* p = DoSpawnCreature(MOB_SMALL_PORTAL,0,0,0,0,TEMPSUMMON_CORPSE_DESPAWN, 0); + if (p) + Portal = p->GetGUID(); + + GroundRuptureTimer = 500; + HamstringTimer = 2000; + EvadeTimer = 5000; + AttackStart(target); + } + + m_creature->SetVisibility(VISIBILITY_ON); + + }else EvadeTimer -= diff; + + //GroundRuptureTimer + if (GroundRuptureTimer < diff) + { + DoCast(m_creature->getVictim(),SPELL_GROUND_RUPTURE); + GroundRuptureTimer = 30000; + }else GroundRuptureTimer -= diff; + + //HamstringTimer + if (HamstringTimer < diff) + { + DoCast(m_creature->getVictim(),SPELL_HAMSTRING); + HamstringTimer = 5000; + }else HamstringTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL giant_claw_tentacleAI : public Scripted_NoMovementAI +{ + giant_claw_tentacleAI(Creature *c) : Scripted_NoMovementAI(c) + { + Reset(); + Unit* p = DoSpawnCreature(MOB_GIANT_PORTAL,0,0,0,0,TEMPSUMMON_CORPSE_DESPAWN, 0); + if (p) + Portal = p->GetGUID(); + } + + uint32 GroundRuptureTimer; + uint32 ThrashTimer; + uint32 HamstringTimer; + uint32 EvadeTimer; + uint64 Portal; + + void JustDied(Unit*) + { + Unit* p = Unit::GetUnit(*m_creature, Portal); + if (p) + p->DealDamage(p, p->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false); + } + + void Reset() + { + //First rupture should happen half a second after we spawn + GroundRuptureTimer = 500; + HamstringTimer = 2000; + ThrashTimer = 5000; + EvadeTimer = 5000; + } + + void Aggro(Unit *who) + { + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + //Check if we have a target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //EvadeTimer + if (m_creature->GetDistance(m_creature->getVictim()) > ATTACK_DISTANCE) + if (EvadeTimer < diff) + { + Unit* p = Unit::GetUnit(*m_creature, Portal); + if (p) + p->DealDamage(p, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false); + + //Dissapear and reappear at new position + m_creature->SetVisibility(VISIBILITY_OFF); + + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (!target) + { + m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false); + return; + } + + if (!target->HasAura(SPELL_DIGESTIVE_ACID, 0)) + { + m_creature->GetMap()->CreatureRelocation(m_creature, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0); + Unit* p = DoSpawnCreature(MOB_GIANT_PORTAL,0,0,0,0,TEMPSUMMON_CORPSE_DESPAWN, 0); + if (p) + Portal = p->GetGUID(); + + GroundRuptureTimer = 500; + HamstringTimer = 2000; + ThrashTimer = 5000; + EvadeTimer = 5000; + AttackStart(target); + } + + m_creature->SetVisibility(VISIBILITY_ON); + + }else EvadeTimer -= diff; + + //GroundRuptureTimer + if (GroundRuptureTimer < diff) + { + DoCast(m_creature->getVictim(),SPELL_GROUND_RUPTURE); + GroundRuptureTimer = 30000; + }else GroundRuptureTimer -= diff; + + //ThrashTimer + if (ThrashTimer < diff) + { + DoCast(m_creature->getVictim(),SPELL_THRASH); + ThrashTimer = 10000; + }else ThrashTimer -= diff; + + //HamstringTimer + if (HamstringTimer < diff) + { + DoCast(m_creature->getVictim(),SPELL_HAMSTRING); + HamstringTimer = 10000; + }else HamstringTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL giant_eye_tentacleAI : public Scripted_NoMovementAI +{ + giant_eye_tentacleAI(Creature *c) : Scripted_NoMovementAI(c) + { + Reset(); + Unit* p = DoSpawnCreature(MOB_GIANT_PORTAL,0,0,0,0,TEMPSUMMON_CORPSE_DESPAWN, 0); + if (p) + Portal = p->GetGUID(); + } + + uint32 BeamTimer; + uint64 Portal; + + void JustDied(Unit*) + { + Unit* p = Unit::GetUnit(*m_creature, Portal); + if (p) + p->DealDamage(p, p->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false); + } + + void Reset() + { + //Green Beam half a second after we spawn + BeamTimer = 500; + } + + void Aggro(Unit *who) + { + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + //Check if we have a target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //BeamTimer + if (BeamTimer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target && !target->HasAura(SPELL_DIGESTIVE_ACID, 0)) + DoCast(target,SPELL_GREEN_BEAM); + + //Beam every 2 seconds + BeamTimer = 2100; + }else BeamTimer -= diff; + } +}; + +//Flesh tentacle functions +void flesh_tentacleAI::UpdateAI(const uint32 diff) +{ + //Check if we have a target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if (Parent) + if (CheckTimer < diff) + { + Unit* pUnit = Unit::GetUnit(*m_creature, Parent); + + if (!pUnit || !pUnit->isAlive() || !pUnit->isInCombat()) + { + Parent = 0; + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false); + return; + } + + CheckTimer = 1000; + }else CheckTimer -= diff; + + DoMeleeAttackIfReady(); +} + +void flesh_tentacleAI::JustDied(Unit* killer) +{ + if (!Parent) + { + DoYell("Error: No Parent variable", LANG_UNIVERSAL, NULL); + return; + } + + Creature* Cthun = (Creature*)Unit::GetUnit(*m_creature, Parent); + + if (Cthun) + ((cthunAI*)(Cthun->AI()))->FleshTentcleKilled(); + else DoYell("Error: No Cthun", LANG_UNIVERSAL, NULL); +} + +//GetAIs +CreatureAI* GetAI_eye_of_cthun(Creature *_Creature) +{ + return new eye_of_cthunAI (_Creature); +} + +CreatureAI* GetAI_cthun(Creature *_Creature) +{ + return new cthunAI (_Creature); +} + +CreatureAI* GetAI_eye_tentacle(Creature *_Creature) +{ + return new eye_tentacleAI (_Creature); +} + +CreatureAI* GetAI_claw_tentacle(Creature *_Creature) +{ + return new claw_tentacleAI (_Creature); +} + +CreatureAI* GetAI_giant_claw_tentacle(Creature *_Creature) +{ + return new giant_claw_tentacleAI (_Creature); +} + +CreatureAI* GetAI_giant_eye_tentacle(Creature *_Creature) +{ + return new giant_eye_tentacleAI (_Creature); +} + +CreatureAI* GetAI_flesh_tentacle(Creature *_Creature) +{ + return new flesh_tentacleAI (_Creature); +} + +void AddSC_boss_cthun() +{ + Script *newscript; + + //Eye + newscript = new Script; + newscript->Name="boss_eye_of_cthun"; + newscript->GetAI = GetAI_eye_of_cthun; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_cthun"; + newscript->GetAI = GetAI_cthun; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_eye_tentacle"; + newscript->GetAI = GetAI_eye_tentacle; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_claw_tentacle"; + newscript->GetAI = GetAI_claw_tentacle; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_giant_claw_tentacle"; + newscript->GetAI = GetAI_giant_claw_tentacle; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_giant_eye_tentacle"; + newscript->GetAI = GetAI_giant_eye_tentacle; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_giant_flesh_tentacle"; + newscript->GetAI = GetAI_flesh_tentacle; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_fankriss.cpp b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_fankriss.cpp new file mode 100644 index 00000000000..da03cc2aad5 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_fankriss.cpp @@ -0,0 +1,190 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Fankriss +SD%Complete: 100 +SDComment: sound not implemented +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "precompiled.h" + +#define SOUND_SENTENCE_YOU 8588 +#define SOUND_SERVE_TO 8589 +#define SOUND_LAWS 8590 +#define SOUND_TRESPASS 8591 +#define SOUND_WILL_BE 8592 + +#define SPELL_MORTAL_WOUND 28467 +#define SPELL_ROOT 28858 + +// Enrage for his spawns +#define SPELL_ENRAGE 28798 + +struct MANGOS_DLL_DECL boss_fankrissAI : public ScriptedAI +{ + boss_fankrissAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 MortalWound_Timer; + uint32 SpawnHatchlings_Timer; + uint32 SpawnSpawns_Timer; + int Rand; + int RandX; + int RandY; + + Creature* Hatchling; + Creature* Spawn; + + void Reset() + { + MortalWound_Timer = 10000 + rand()%5000; + SpawnHatchlings_Timer = 6000 + rand()%6000; + SpawnSpawns_Timer = 15000 + rand()%30000; + } + + void SummonSpawn(Unit* victim) + { + Rand = 10 + (rand()%10); + switch (rand()%2) + { + case 0: RandX = 0 - Rand; break; + case 1: RandX = 0 + Rand; break; + } + Rand = 0; + Rand = 10 + (rand()%10); + switch (rand()%2) + { + case 0: RandY = 0 - Rand; break; + case 1: RandY = 0 + Rand; break; + } + Rand = 0; + Spawn = DoSpawnCreature(15630, RandX, RandY, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + if(Spawn) + ((CreatureAI*)Spawn->AI())->AttackStart(victim); + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //MortalWound_Timer + if (MortalWound_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_MORTAL_WOUND); + MortalWound_Timer = 10000 + rand()%10000; + }else MortalWound_Timer -= diff; + + //Summon 1-3 Spawns of Fankriss at random time. + if (SpawnSpawns_Timer < diff) + { + switch(rand()%3) + { + case 0: + SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM,0)); + break; + case 1: + SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM,0)); + SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM,0)); + break; + case 2: + SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM,0)); + SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM,0)); + SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM,0)); + break; + } + SpawnSpawns_Timer = 30000 + rand()%30000; + }else SpawnSpawns_Timer -= diff; + + // Teleporting Random Target to one of the three tunnels and spawn 4 hatchlings near the gamer. + //We will only telport if fankriss has more than 3% of hp so teleported gamers can always loot. + if ( m_creature->GetHealth()*100 / m_creature->GetMaxHealth() > 3 ) + { + if(SpawnHatchlings_Timer< diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target && target->GetTypeId() == TYPEID_PLAYER) + { + DoCast(target, SPELL_ROOT); + + if(m_creature->getThreatManager().getThreat(target)) + m_creature->getThreatManager().modifyThreatPercent(target, -100); + + switch(rand()%3) + { + case 0: + DoTeleportPlayer(target, -8106.0142,1289.2900,-74.419533,5.112); + Hatchling = m_creature->SummonCreature(15962, target->GetPositionX()-3, target->GetPositionY()-3, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + ((CreatureAI*)Hatchling->AI())->AttackStart(target); + Hatchling = m_creature->SummonCreature(15962, target->GetPositionX()-3, target->GetPositionY()+3, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + ((CreatureAI*)Hatchling->AI())->AttackStart(target); + Hatchling = m_creature->SummonCreature(15962, target->GetPositionX()-5, target->GetPositionY()-5, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + ((CreatureAI*)Hatchling->AI())->AttackStart(target); + Hatchling = m_creature->SummonCreature(15962, target->GetPositionX()-5, target->GetPositionY()+5, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + ((CreatureAI*)Hatchling->AI())->AttackStart(target); + break; + case 1: + DoTeleportPlayer(target, -7990.135354,1155.1907,-78.849319,2.608); + Hatchling = m_creature->SummonCreature(15962, target->GetPositionX()-3, target->GetPositionY()-3, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + ((CreatureAI*)Hatchling->AI())->AttackStart(target); + Hatchling = m_creature->SummonCreature(15962, target->GetPositionX()-3, target->GetPositionY()+3, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + ((CreatureAI*)Hatchling->AI())->AttackStart(target); + Hatchling = m_creature->SummonCreature(15962, target->GetPositionX()-5, target->GetPositionY()-5, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + ((CreatureAI*)Hatchling->AI())->AttackStart(target); + Hatchling = m_creature->SummonCreature(15962, target->GetPositionX()-5, target->GetPositionY()+5, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + ((CreatureAI*)Hatchling->AI())->AttackStart(target); + break; + case 2: + DoTeleportPlayer(target,-8159.7753,1127.9064,-76.868660,0.675); + Hatchling = m_creature->SummonCreature(15962, target->GetPositionX()-3, target->GetPositionY()-3, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + ((CreatureAI*)Hatchling->AI())->AttackStart(target); + Hatchling = m_creature->SummonCreature(15962, target->GetPositionX()-3, target->GetPositionY()+3, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + ((CreatureAI*)Hatchling->AI())->AttackStart(target); + Hatchling = m_creature->SummonCreature(15962, target->GetPositionX()-5, target->GetPositionY()-5, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + ((CreatureAI*)Hatchling->AI())->AttackStart(target); + Hatchling = m_creature->SummonCreature(15962, target->GetPositionX()-5, target->GetPositionY()+5, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + ((CreatureAI*)Hatchling->AI())->AttackStart(target); + break; + } + } + SpawnHatchlings_Timer = 45000 + rand()%15000; + }else SpawnHatchlings_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_fankriss(Creature *_Creature) +{ + return new boss_fankrissAI (_Creature); +} + +void AddSC_boss_fankriss() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_fankriss"; + newscript->GetAI = GetAI_boss_fankriss; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_huhuran.cpp b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_huhuran.cpp new file mode 100644 index 00000000000..65e1da14955 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_huhuran.cpp @@ -0,0 +1,143 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Huhuran +SD%Complete: 100 +SDComment: +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_FRENZY 26051 +#define SPELL_BERSERK 26068 +#define SPELL_POISONBOLT 26052 +#define SPELL_NOXIOUSPOISON 26053 +#define SPELL_WYVERNSTING 26180 +#define SPELL_ACIDSPIT 26050 + +struct MANGOS_DLL_DECL boss_huhuranAI : public ScriptedAI +{ + boss_huhuranAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Frenzy_Timer; + uint32 Wyvern_Timer; + uint32 Spit_Timer; + uint32 PoisonBolt_Timer; + uint32 NoxiousPoison_Timer; + uint32 FrenzyBack_Timer; + + bool Frenzy; + bool Berserk; + + void Reset() + { + Frenzy_Timer = 25000 + rand()%10000; + Wyvern_Timer = 18000 + rand()%10000; + Spit_Timer = 8000; + PoisonBolt_Timer = 4000; + NoxiousPoison_Timer = 10000 + rand()%10000; + FrenzyBack_Timer = 15000; + + Frenzy = false; + Berserk = false; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //Frenzy_Timer + if (!Frenzy && Frenzy_Timer < diff) + { + DoCast(m_creature, SPELL_FRENZY); + Frenzy = true; + PoisonBolt_Timer = 3000; + Frenzy_Timer = 25000 + rand()%10000; + }else Frenzy_Timer -= diff; + + // Wyvern Timer + if (Wyvern_Timer < diff) + { + if( Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0) ) + DoCast(target,SPELL_WYVERNSTING); + Wyvern_Timer = 15000 + rand()%17000; + }else Wyvern_Timer -= diff; + + //Spit Timer + if (Spit_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_ACIDSPIT); + Spit_Timer = 5000 + rand()%5000; + }else Spit_Timer -= diff; + + //NoxiousPoison_Timer + if (NoxiousPoison_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_NOXIOUSPOISON); + NoxiousPoison_Timer = 12000 + rand()%12000; + }else NoxiousPoison_Timer -= diff; + + //PoisonBolt only if frenzy or berserk + if (Frenzy || Berserk) + { + if (PoisonBolt_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_POISONBOLT); + PoisonBolt_Timer = 3000; + }else PoisonBolt_Timer -= diff; + } + + //FrenzyBack_Timer + if (Frenzy && FrenzyBack_Timer < diff) + { + m_creature->InterruptNonMeleeSpells(false); + Frenzy = false; + FrenzyBack_Timer = 15000; + }else FrenzyBack_Timer -= diff; + + if ( !Berserk && m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 31 ) + { + m_creature->InterruptNonMeleeSpells(false); + DoTextEmote("is going berserk", NULL); + DoCast(m_creature, SPELL_BERSERK); + Berserk = true; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_huhuran(Creature *_Creature) +{ + return new boss_huhuranAI (_Creature); +} + +void AddSC_boss_huhuran() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_huhuran"; + newscript->GetAI = GetAI_boss_huhuran; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_ouro.cpp b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_ouro.cpp new file mode 100644 index 00000000000..97853c6cf87 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_ouro.cpp @@ -0,0 +1,140 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Ouro +SD%Complete: 85 +SDComment: No model for submerging. Currently just invisible. +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "precompiled.h" +#include "def_temple_of_ahnqiraj.h" + +#define SPELL_SWEEP 26103 +#define SPELL_SANDBLAST 26102 +#define SPELL_GROUND_RUPTURE 26100 +#define SPELL_BIRTH 26262 //The Birth Animation + +#define SPELL_DIRTMOUND_PASSIVE 26092 + +struct MANGOS_DLL_DECL boss_ouroAI : public ScriptedAI +{ + boss_ouroAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Sweep_Timer; + uint32 SandBlast_Timer; + uint32 Submerge_Timer; + uint32 Back_Timer; + uint32 ChangeTarget_Timer; + uint32 Spawn_Timer; + + bool Enrage; + bool Submerged; + bool InCombat; + + void Reset() + { + Sweep_Timer = 5000 + rand()%5000; + SandBlast_Timer = 20000 + rand()%15000; + Submerge_Timer = 90000 + rand()%60000; + Back_Timer = 30000 + rand()%15000; + ChangeTarget_Timer = 5000 + rand()%3000; + Spawn_Timer = 10000 + rand()%10000; + + Enrage = false; + Submerged = false; + } + + void Aggro(Unit *who) + { + DoCast(m_creature->getVictim(), SPELL_BIRTH); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //Sweep_Timer + if (!Submerged && Sweep_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_SWEEP); + Sweep_Timer = 15000 + rand()%15000; + }else Sweep_Timer -= diff; + + //SandBlast_Timer + if (!Submerged && SandBlast_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_SANDBLAST); + SandBlast_Timer = 20000 + rand()%15000; + }else SandBlast_Timer -= diff; + + //Submerge_Timer + if (!Submerged && Submerge_Timer < diff) + { + //Cast + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_SUBMERGE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->setFaction(35); + DoCast(m_creature, SPELL_DIRTMOUND_PASSIVE); + + Submerged = true; + Back_Timer = 30000 + rand()%15000; + }else Submerge_Timer -= diff; + + //ChangeTarget_Timer + if (Submerged && ChangeTarget_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + + m_creature->Relocate(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0); + m_creature->SendMonsterMove(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, true,1); + + ChangeTarget_Timer = 10000 + rand()%10000; + }else ChangeTarget_Timer -= diff; + + //Back_Timer + if (Submerged && Back_Timer < diff) + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->setFaction(14); + + DoCast(m_creature->getVictim(), SPELL_GROUND_RUPTURE); + + Submerged = false; + Submerge_Timer = 60000 + rand()%60000; + }else Back_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_ouro(Creature *_Creature) +{ + return new boss_ouroAI (_Creature); +} + +void AddSC_boss_ouro() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_ouro"; + newscript->GetAI = GetAI_boss_ouro; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_sartura.cpp b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_sartura.cpp new file mode 100644 index 00000000000..d9a9d27dffc --- /dev/null +++ b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_sartura.cpp @@ -0,0 +1,271 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Sartura +SD%Complete: 99 +SDComment: +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_WHIRLWIND 26083 +#define SPELL_ENRAGE 28747 //Not sure if right ID. +#define SPELL_ENRAGEHARD 28798 + +//Guard Spell +#define SPELL_WHIRLWINDADD 26038 +#define SPELL_KNOCKBACK 26027 + +struct MANGOS_DLL_DECL boss_sarturaAI : public ScriptedAI +{ + boss_sarturaAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 WhirlWind_Timer; + uint32 WhirlWindRandom_Timer; + uint32 WhirlWindEnd_Timer; + uint32 AggroReset_Timer; + uint32 AggroResetEnd_Timer; + uint32 EnrageHard_Timer; + + bool Enraged; + bool EnragedHard; + bool WhirlWind; + bool AggroReset; + + void Reset() + { + WhirlWind_Timer = 30000; + WhirlWindRandom_Timer = 3000 + rand()%4000; + WhirlWindEnd_Timer = 15000; + AggroReset_Timer = 45000 + rand()%10000; + AggroResetEnd_Timer = 5000; + EnrageHard_Timer = 10*60000; + + WhirlWind = false; + AggroReset = false; + Enraged = false; + EnragedHard = false; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if (WhirlWind) + { + if (WhirlWindRandom_Timer < diff) + { + //Attack random Gamers + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,1); + if (target) + DoStartAttackAndMovement(target); + + WhirlWindRandom_Timer = 3000 + rand()%4000; + }else WhirlWindRandom_Timer -= diff; + + if (WhirlWindEnd_Timer < diff) + { + WhirlWind = false; + WhirlWind_Timer = 25000 + rand()%15000; + }else WhirlWindEnd_Timer -= diff; + } + + if (!WhirlWind) + { + if (WhirlWind_Timer < diff) + { + DoCast(m_creature, SPELL_WHIRLWIND); + WhirlWind = true; + WhirlWindEnd_Timer = 15000; + }else WhirlWind_Timer -= diff; + + if (AggroReset_Timer < diff) + { + //Attack random Gamers + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,1); + if (target) + m_creature->TauntApply(target); + + AggroReset = true; + AggroReset_Timer = 2000 + rand()%3000; + }else AggroReset_Timer -= diff; + + if (AggroReset) + { + if (AggroResetEnd_Timer GetHealth()*100 / m_creature->GetMaxHealth() <= 20 && !m_creature->IsNonMeleeSpellCasted(false)) + { + DoCast(m_creature, SPELL_ENRAGE); + Enraged = true; + } + } + + //After 10 minutes hard enrage + if (!EnragedHard) + { + if (EnrageHard_Timer < diff) + { + DoCast(m_creature, SPELL_ENRAGEHARD); + EnragedHard = true; + }EnrageHard_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } + } +}; + +struct MANGOS_DLL_DECL mob_sartura_royal_guardAI : public ScriptedAI +{ + mob_sartura_royal_guardAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 WhirlWind_Timer; + uint32 WhirlWindRandom_Timer; + uint32 WhirlWindEnd_Timer; + uint32 AggroReset_Timer; + uint32 AggroResetEnd_Timer; + uint32 KnockBack_Timer; + + bool WhirlWind; + bool AggroReset; + + void Reset() + { + WhirlWind_Timer = 30000; + WhirlWindRandom_Timer = 3000 + rand()%4000; + WhirlWindEnd_Timer = 15000; + AggroReset_Timer = 45000 + rand()%10000; + AggroResetEnd_Timer = 5000; + KnockBack_Timer = 10000; + + WhirlWind = false; + AggroReset = false; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if (!WhirlWind && WhirlWind_Timer < diff) + { + DoCast(m_creature, SPELL_WHIRLWINDADD); + WhirlWind = true; + WhirlWind_Timer = 25000 + rand()%15000; + WhirlWindEnd_Timer = 15000; + }else WhirlWind_Timer -= diff; + + if (WhirlWind) + { + if (WhirlWindRandom_Timer < diff) + { + //Attack random Gamers + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,1); + if (target) + m_creature->TauntApply(target); + + WhirlWindRandom_Timer = 3000 + rand()%4000; + }else WhirlWindRandom_Timer -= diff; + + if (WhirlWindEnd_Timer < diff) + { + WhirlWind = false; + }else WhirlWindEnd_Timer -= diff; + } + + if (!WhirlWind) + { + if(AggroReset_Timer < diff) + { + //Attack random Gamers + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,1); + if (target) + DoStartAttackAndMovement(target); + + AggroReset = true; + AggroReset_Timer = 2000 + rand()%3000; + }else AggroReset_Timer -= diff; + + if (KnockBack_Timer < diff) + { + DoCast(m_creature, SPELL_WHIRLWINDADD); + KnockBack_Timer = 10000 + rand()%10000; + }else KnockBack_Timer -= diff; + } + + if (AggroReset) + { + if (AggroResetEnd_Timer Name="boss_sartura"; + newscript->GetAI = GetAI_boss_sartura; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_sartura_royal_guard"; + newscript->GetAI = GetAI_mob_sartura_royal_guard; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_skeram.cpp b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_skeram.cpp new file mode 100644 index 00000000000..a2123c21da0 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_skeram.cpp @@ -0,0 +1,314 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Skeram +SD%Complete: 75 +SDComment: Mind Control buggy. +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "precompiled.h" +#include "def_temple_of_ahnqiraj.h" +#include "Group.h" + +#define SPELL_ARCANE_EXPLOSION 25679 +#define SPELL_EARTH_SHOCK 26194 +#define SPELL_TRUE_FULFILLMENT4 26526 +#define SPELL_BLINK 28391 + +#define SOUND_AGGRO1 8615 //8615 Are you so eager to die? I would be happy to accomodate you. +#define SOUND_AGGRO2 8616 //8616 Cower mortals! The age of darkness is at hand. +#define SOUND_AGGRO3 8621 //8621 Tremble! The end is upon you. +#define SOUND_SLAY1 8617 //8617 Let your death serve as an example! +#define SOUND_SLAY2 8619 //8619 Spineless wretchers you will drown in rivers of blood! +#define SOUND_SLAY3 8620 //8620 The screams of the dying will fill the air. A symphony of terror is about to begin! +#define SOUND_SPLIT 8618 //8618 Prepare for the return of the ancient ones! +#define SOUND_DEATH 8622 //8622 You only delay... the inevetable + +class ov_mycoordinates +{ + public: + float x,y,z,r; + ov_mycoordinates(float cx, float cy, float cz, float cr) + { + x = cx; y = cy; z = cz; r = cr; + } +}; + +struct MANGOS_DLL_DECL boss_skeramAI : public ScriptedAI +{ + boss_skeramAI(Creature *c) : ScriptedAI(c) + { + pInstance = (c->GetInstanceData()) ? ((ScriptedInstance*)c->GetInstanceData()) : NULL; + IsImage = false; + Reset(); + } + + ScriptedInstance *pInstance; + + uint32 ArcaneExplosion_Timer; + uint32 EarthShock_Timer; + uint32 FullFillment_Timer; + uint32 Blink_Timer; + uint32 Invisible_Timer; + + Creature *Image1, *Image2; + + bool Images75; + bool Images50; + bool Images25; + bool IsImage; + bool Invisible; + + void Reset() + { + ArcaneExplosion_Timer = 6000 + rand()%6000; + EarthShock_Timer = 2000; + FullFillment_Timer = 15000; + Blink_Timer = 8000 + rand()%12000; + Invisible_Timer = 500; + + Images75 = false; + Images50 = false; + Images25 = false; + Invisible = false; + + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetVisibility(VISIBILITY_ON); + + if (IsImage) + m_creature->setDeathState(JUST_DIED); + } + + void KilledUnit(Unit* victim) + { + switch(rand()%3) + { + case 0: + DoPlaySoundToSet(m_creature,SOUND_SLAY1); + break; + case 1: + DoPlaySoundToSet(m_creature,SOUND_SLAY2); + break; + case 2: + DoPlaySoundToSet(m_creature,SOUND_SLAY3); + break; + } + } + + void JustDied(Unit* Killer) + { + if (!IsImage) + DoPlaySoundToSet(m_creature,SOUND_DEATH); + } + + void Aggro(Unit *who) + { + if (IsImage || Images75) + return; + switch(rand()%3) + { + case 0: + DoPlaySoundToSet(m_creature,SOUND_AGGRO1); + break; + case 1: + DoPlaySoundToSet(m_creature,SOUND_AGGRO2); + break; + case 2: + DoPlaySoundToSet(m_creature,SOUND_AGGRO3); + break; + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //ArcaneExplosion_Timer + if (ArcaneExplosion_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_ARCANE_EXPLOSION); + ArcaneExplosion_Timer = 8000 + rand()%10000; + }else ArcaneExplosion_Timer -= diff; + + //If we are within range melee the target + if( m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE)) + { + //Make sure our attack is ready and we arn't currently casting + if( m_creature->isAttackReady() && !m_creature->IsNonMeleeSpellCasted(false)) + { + m_creature->AttackerStateUpdate(m_creature->getVictim()); + m_creature->resetAttackTimer(); + } + }else + { + //EarthShock_Timer + if (EarthShock_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_EARTH_SHOCK); + EarthShock_Timer = 1000; + }else EarthShock_Timer -= diff; + } + + //Blink_Timer + if (Blink_Timer < diff) + { + //DoCast(m_creature, SPELL_BLINK); + switch(rand()%3) + { + case 0: + m_creature->Relocate(-8340.782227,2083.814453,125.648788,0); + DoResetThreat(); + break; + case 1: + m_creature->Relocate(-8341.546875,2118.504639,133.058151,0); + DoResetThreat(); + break; + case 2: + m_creature->Relocate(-8318.822266,2058.231201,133.058151,0); + DoResetThreat(); + break; + } + DoStopAttack(); + + Blink_Timer= 20000 + rand()%20000; + }else Blink_Timer -= diff; + + int procent = (int) (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() +0.5); + + //Summoning 2 Images and teleporting to a random position on 75% health + if ( (!Images75 && !IsImage) && + (procent <= 75 && procent > 70) ) + DoSplit(75); + + //Summoning 2 Images and teleporting to a random position on 50% health + if ( (!Images50 && !IsImage) && + (procent <= 50 && procent > 45) ) + DoSplit(50); + + //Summoning 2 Images and teleporting to a random position on 25% health + if ( (!Images25 && !IsImage) && + (procent <= 25 && procent > 20) ) + DoSplit(25); + + //Invisible_Timer + if (Invisible) + { + if (Invisible_Timer < diff) + { + //Making Skeram visible after telporting + m_creature->SetVisibility(VISIBILITY_ON); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + Invisible_Timer = 2500; + Invisible = false; + }else Invisible_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } + + void DoSplit(int atPercent /* 75 50 25 */) + { + DoPlaySoundToSet(m_creature,SOUND_SPLIT); + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + + ov_mycoordinates *place1 = new ov_mycoordinates(-8340.782227,2083.814453,125.648788,0); + ov_mycoordinates *place2 = new ov_mycoordinates(-8341.546875,2118.504639,133.058151,0); + ov_mycoordinates *place3 = new ov_mycoordinates(-8318.822266,2058.231201,133.058151,0); + + ov_mycoordinates *bossc=place1, *i1=place2, *i2=place3; + + switch(rand()%3) + { + case 0: + bossc=place1;i1=place2;i2=place3; + break; + case 1: + bossc=place2;i1=place1;i2=place3; + break; + case 2: + bossc=place3;i1=place1;i2=place2; + break; + } + + for (int tryi = 0; tryi < 41; tryi ++) + { + Unit *targetpl = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (targetpl->isType(TYPEMASK_PLAYER)) + { + Group *grp = ((Player *)targetpl)->GetGroup(); + if (grp) + { + for (int ici = 0; ici < TARGETICONCOUNT; ici++) + { + //if (grp ->m_targetIcons[ici] == m_creature->GetGUID()) -- private member:( + grp->SetTargetIcon(ici, 0); + } + } + break; + } + } + + m_creature->RemoveAllAuras(); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetVisibility(VISIBILITY_OFF); + m_creature->Relocate(bossc->x, bossc->y, bossc->z, bossc->r); + Invisible = true; + DoResetThreat(); + DoStopAttack(); + + switch (atPercent) + { + case 75: Images75 = true; break; + case 50: Images50 = true; break; + case 25: Images25 = true; break; + } + + Image1 = m_creature->SummonCreature(15263, i1->x, i1->y, i1->z, i1->r, TEMPSUMMON_CORPSE_DESPAWN, 30000); + Image1->SetMaxHealth(m_creature->GetMaxHealth() / 5); + Image1->SetHealth(m_creature->GetHealth() / 5); + Image1->AI()->AttackStart(target); + + Image2 = m_creature->SummonCreature(15263,i2->x, i2->y, i2->z, i2->r, TEMPSUMMON_CORPSE_DESPAWN, 30000); + Image2->SetMaxHealth(m_creature->GetMaxHealth() / 5); + Image2->SetHealth(m_creature->GetHealth() / 5); + Image2->AI()->AttackStart(target); + + ((boss_skeramAI*)Image1->AI())->IsImage = true; + ((boss_skeramAI*)Image2->AI())->IsImage = true; + + Invisible = true; + } +}; + +CreatureAI* GetAI_boss_skeram(Creature *_Creature) +{ + return new boss_skeramAI (_Creature); +} + +void AddSC_boss_skeram() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_skeram"; + newscript->GetAI = GetAI_boss_skeram; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_twinemperors.cpp b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_twinemperors.cpp new file mode 100644 index 00000000000..dacb55c4055 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_twinemperors.cpp @@ -0,0 +1,698 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Twinemperors +SD%Complete: 95 +SDComment: +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "precompiled.h" +#include "def_temple_of_ahnqiraj.h" +#include "WorldPacket.h" + +#include "Item.h" +#include "Spell.h" + +#define SPELL_HEAL_BROTHER 7393 +#define SPELL_TWIN_TELEPORT 800 // CTRA watches for this spell to start its teleport timer +#define SPELL_TWIN_TELEPORT_VISUAL 26638 // visual + +#define SPELL_EXPLODEBUG 804 +#define SPELL_MUTATE_BUG 802 + +#define SOUND_VN_DEATH 8660 //8660 - Death - Feel +#define SOUND_VN_AGGRO 8661 //8661 - Aggro - Let none +#define SOUND_VN_KILL 8662 //8661 - Kill - your fate + +#define SOUND_VL_AGGRO 8657 //8657 - Aggro - To Late +#define SOUND_VL_KILL 8658 //8658 - Kill - You will not +#define SOUND_VL_DEATH 8659 //8659 - Death + +#define PULL_RANGE 50 +#define ABUSE_BUG_RANGE 20 +#define SPELL_BERSERK 26662 +#define TELEPORTTIME 30000 + +#define SPELL_UPPERCUT 26007 +#define SPELL_UNBALANCING_STRIKE 26613 + +#define VEKLOR_DIST 20 // VL will not come to melee when attacking + +#define SPELL_SHADOWBOLT 26006 +#define SPELL_BLIZZARD 26607 +#define SPELL_ARCANEBURST 568 + +struct MANGOS_DLL_DECL boss_twinemperorsAI : public ScriptedAI +{ + ScriptedInstance *pInstance; + uint32 Heal_Timer; + uint32 Teleport_Timer; + bool AfterTeleport; + uint32 AfterTeleportTimer; + bool DontYellWhenDead; + uint32 Abuse_Bug_Timer, BugsTimer; + bool tspellcasted; + uint32 EnrageTimer; + + virtual bool IAmVeklor() = 0; + virtual void Reset() = 0; + virtual void CastSpellOnBug(Creature *target) = 0; + + boss_twinemperorsAI(Creature *c): ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + } + + void TwinReset() + { + Heal_Timer = 0; // first heal immediately when they get close together + Teleport_Timer = TELEPORTTIME; + AfterTeleport = false; + tspellcasted = false; + AfterTeleportTimer = 0; + Abuse_Bug_Timer = 10000 + rand()%7000; + BugsTimer = 2000; + m_creature->clearUnitState(UNIT_STAT_STUNDED); + DontYellWhenDead = false; + EnrageTimer = 15*60000; + } + + Creature *GetOtherBoss() + { + if(pInstance) + { + return (Creature *)Unit::GetUnit((*m_creature), pInstance->GetData64(IAmVeklor() ? DATA_VEKNILASH : DATA_VEKLOR)); + } + else + { + return (Creature *)0; + } + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + Unit *pOtherBoss = GetOtherBoss(); + if (pOtherBoss) + { + float dPercent = ((float)damage) / ((float)m_creature->GetMaxHealth()); + int odmg = (int)(dPercent * ((float)pOtherBoss->GetMaxHealth())); + int ohealth = pOtherBoss->GetHealth()-odmg; + pOtherBoss->SetHealth(ohealth > 0 ? ohealth : 0); + if (ohealth <= 0) + { + pOtherBoss->setDeathState(JUST_DIED); + pOtherBoss->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + } + } + + void JustDied(Unit* Killer) + { + Creature *pOtherBoss = GetOtherBoss(); + if (pOtherBoss) + { + pOtherBoss->SetHealth(0); + pOtherBoss->setDeathState(JUST_DIED); + pOtherBoss->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + ((boss_twinemperorsAI *)pOtherBoss->AI())->DontYellWhenDead = true; + } + if (!DontYellWhenDead) // I hope AI is not threaded + DoPlaySoundToSet(m_creature, IAmVeklor() ? SOUND_VL_DEATH : SOUND_VN_DEATH); + } + + void KilledUnit(Unit* victim) + { + DoPlaySoundToSet(m_creature, IAmVeklor() ? SOUND_VL_KILL : SOUND_VN_KILL); + } + + void Aggro(Unit *who) + { + DoZoneInCombat(); + InCombat = true; + Creature *pOtherBoss = GetOtherBoss(); + if (pOtherBoss) + { + // TODO: we should activate the other boss location so he can start attackning even if nobody + // is near I dont know how to do that + ScriptedAI *otherAI = (ScriptedAI*)pOtherBoss->AI(); + if (!otherAI->InCombat) + { + DoPlaySoundToSet(m_creature, IAmVeklor() ? SOUND_VL_AGGRO : SOUND_VN_AGGRO); + otherAI->AttackStart(who); + otherAI->DoZoneInCombat(); + } + } + } + + void SpellHit(Unit *caster, const SpellEntry *entry) + { + if (caster == m_creature) + return; + + Creature *pOtherBoss = GetOtherBoss(); + if (entry->Id != SPELL_HEAL_BROTHER || !pOtherBoss) + return; + + // add health so we keep same percentage for both brothers + uint32 mytotal = m_creature->GetMaxHealth(), histotal = pOtherBoss->GetMaxHealth(); + float mult = ((float)mytotal) / ((float)histotal); + if (mult < 1) + mult = 1.0f/mult; + #define HEAL_BROTHER_AMOUNT 30000.0f + uint32 largerAmount = (uint32)((HEAL_BROTHER_AMOUNT * mult) - HEAL_BROTHER_AMOUNT); + + uint32 myh = m_creature->GetHealth(); + uint32 hish = pOtherBoss->GetHealth(); + if (mytotal > histotal) + { + uint32 h = m_creature->GetHealth()+largerAmount; + m_creature->SetHealth(std::min(mytotal, h)); + } + else + { + uint32 h = pOtherBoss->GetHealth()+largerAmount; + pOtherBoss->SetHealth(std::min(histotal, h)); + } + } + + void TryHealBrother(uint32 diff) + { + if (IAmVeklor()) // this spell heals caster and the other brother so let VN cast it + return; + + if (Heal_Timer < diff) + { + Unit *pOtherBoss = GetOtherBoss(); + if (pOtherBoss && (pOtherBoss->GetDistance((const Creature *)m_creature) <= 60)) + { + DoCast(pOtherBoss, SPELL_HEAL_BROTHER); + Heal_Timer = 1000; + } + } else Heal_Timer -= diff; + } + + Unit *GetAnyoneCloseEnough(float dist, bool totallyRandom) + { + int cnt = 0; + std::list::iterator i; + std::list candidates; + + for (i = m_creature->getThreatManager().getThreatList().begin();i != m_creature->getThreatManager().getThreatList().end(); ++i) + { + Unit* pUnit = Unit::GetUnit((*m_creature), (*i)->getUnitGuid()); + if (m_creature->IsWithinDistInMap(pUnit, dist)) + { + if (!totallyRandom) + return pUnit; + candidates.push_back((*i)); + cnt ++; + } + } + if (!cnt) + return NULL; + for (int randomi = rand() % cnt; randomi > 0; randomi --) + candidates.pop_front(); + + i = candidates.begin(); + Unit *ret = Unit::GetUnit((*m_creature), (*i)->getUnitGuid()); + candidates.clear(); + return ret; + } + + Unit *PickNearestPlayer() + { + Unit *nearp = NULL; + float neardist = 0.0f; + std::list::iterator i; + for (i = m_creature->getThreatManager().getThreatList().begin();i != m_creature->getThreatManager().getThreatList().end(); ++i) + { + Unit* pUnit = NULL; + pUnit = Unit::GetUnit((*m_creature), (*i)->getUnitGuid()); + if (!pUnit) + continue; + float pudist = pUnit->GetDistance((const Creature *)m_creature); + if (!nearp || (neardist > pudist)) + { + nearp = pUnit; + neardist = pudist; + } + } + return nearp; + } + + void TeleportToMyBrother() + { + if (!pInstance) + return; + + Teleport_Timer = TELEPORTTIME; + + if(IAmVeklor()) + return; // mechanics handled by veknilash so they teleport exactly at the same time and to correct coordinates + + Creature *pOtherBoss = GetOtherBoss(); + if (pOtherBoss) + { + //m_creature->MonsterYell("Teleporting ...", LANG_UNIVERSAL, 0); + float other_x = pOtherBoss->GetPositionX(); + float other_y = pOtherBoss->GetPositionY(); + float other_z = pOtherBoss->GetPositionZ(); + float other_o = pOtherBoss->GetOrientation(); + + Map *thismap = m_creature->GetMap(); + thismap->CreatureRelocation(pOtherBoss, m_creature->GetPositionX(), + m_creature->GetPositionY(), m_creature->GetPositionZ(), m_creature->GetOrientation()); + thismap->CreatureRelocation(m_creature, other_x, other_y, other_z, other_o); + + SetAfterTeleport(); + ((boss_twinemperorsAI*) pOtherBoss->AI())->SetAfterTeleport(); + } + } + + void SetAfterTeleport() + { + m_creature->InterruptNonMeleeSpells(false); + DoStopAttack(); + DoResetThreat(); + DoCast(m_creature, SPELL_TWIN_TELEPORT_VISUAL); + m_creature->addUnitState(UNIT_STAT_STUNDED); + AfterTeleport = true; + AfterTeleportTimer = 2000; + tspellcasted = false; + } + + bool TryActivateAfterTTelep(uint32 diff) + { + if (AfterTeleport) + { + if (!tspellcasted) + { + m_creature->clearUnitState(UNIT_STAT_STUNDED); + DoCast(m_creature, SPELL_TWIN_TELEPORT); + m_creature->addUnitState(UNIT_STAT_STUNDED); + } + + tspellcasted = true; + + if (AfterTeleportTimer < diff) + { + AfterTeleport = false; + m_creature->clearUnitState(UNIT_STAT_STUNDED); + Unit *nearu = PickNearestPlayer(); + //DoYell(nearu->GetName(), LANG_UNIVERSAL, 0); + AttackStart(nearu); + m_creature->getThreatManager().addThreat(nearu, 10000); + return true; + } + else + { + AfterTeleportTimer -= diff; + // update important timers which would otherwise get skipped + if (EnrageTimer > diff) + EnrageTimer -= diff; + else + EnrageTimer = 0; + if (Teleport_Timer > diff) + Teleport_Timer -= diff; + else + Teleport_Timer = 0; + return false; + } + } + else + { + return true; + } + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || m_creature->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + float attackRadius = m_creature->GetAttackDistance(who); + if (attackRadius < PULL_RANGE) + attackRadius = PULL_RANGE; + if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= /*CREATURE_Z_ATTACK_RANGE*/7 /*there are stairs*/) + { + if(who->HasStealthAura()) + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + AttackStart(who); + } + } + } + + class AnyBugCheck + { + public: + AnyBugCheck(WorldObject const* obj, float range) : i_obj(obj), i_range(range) {} + bool operator()(Unit* u) + { + Creature *c = (Creature *)u; + if (!i_obj->IsWithinDistInMap(c, i_range)) + return false; + return (c->GetEntry() == 15316 || c->GetEntry() == 15317); + } + private: + WorldObject const* i_obj; + float i_range; + }; + + Creature *RespawnNearbyBugsAndGetOne() + { + CellPair p(MaNGOS::ComputeCellPair(m_creature->GetPositionX(), m_creature->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + std::list unitList; + + AnyBugCheck u_check(m_creature, 150); + MaNGOS::CreatureListSearcher searcher(unitList, u_check); + TypeContainerVisitor, GridTypeMapContainer > grid_creature_searcher(searcher); + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, grid_creature_searcher, *(m_creature->GetMap())); + + Creature *nearb = NULL; + + for(std::list::iterator iter = unitList.begin(); iter != unitList.end(); ++iter) + { + Creature *c = (Creature *)(*iter); + if (c->isDead()) + { + c->Respawn(); + c->setFaction(7); + c->RemoveAllAuras(); + } + if (c->IsWithinDistInMap(m_creature, ABUSE_BUG_RANGE)) + { + if (!nearb || (rand()%4)==0) + nearb = c; + } + } + return nearb; + } + + void HandleBugs(uint32 diff) + { + if (BugsTimer < diff || Abuse_Bug_Timer < diff) + { + Creature *c = RespawnNearbyBugsAndGetOne(); + if (Abuse_Bug_Timer < diff) + { + if (c) + { + CastSpellOnBug(c); + Abuse_Bug_Timer = 10000 + rand()%7000; + } + else + { + Abuse_Bug_Timer = 1000; + } + } + else + { + Abuse_Bug_Timer -= diff; + } + BugsTimer = 2000; + } + else + { + BugsTimer -= diff; + Abuse_Bug_Timer -= diff; + } + } + + void CheckEnrage(uint32 diff) + { + if (EnrageTimer < diff) + { + if (!m_creature->IsNonMeleeSpellCasted(true)) + { + DoCast(m_creature, SPELL_BERSERK); + EnrageTimer = 60*60000; + } else EnrageTimer = 0; + } else EnrageTimer-=diff; + } +}; + +class MANGOS_DLL_DECL BugAura : public Aura +{ + public: + BugAura(SpellEntry *spell, uint32 eff, int32 *bp, Unit *target, Unit *caster) : Aura(spell, eff, bp, target, caster, NULL) + {} +}; + +struct MANGOS_DLL_DECL boss_veknilashAI : public boss_twinemperorsAI +{ + bool IAmVeklor() {return false;} + boss_veknilashAI(Creature *c) : boss_twinemperorsAI(c) + { + Reset(); + } + + uint32 UpperCut_Timer; + uint32 UnbalancingStrike_Timer; + uint32 Scarabs_Timer; + int Rand; + int RandX; + int RandY; + + Creature* Summoned; + + void Reset() + { + TwinReset(); + UpperCut_Timer = 14000 + rand()%15000; + UnbalancingStrike_Timer = 8000 + rand()%10000; + Scarabs_Timer = 7000 + rand()%7000; + + //Added. Can be removed if its included in DB. + m_creature->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); + } + + void CastSpellOnBug(Creature *target) + { + target->setFaction(14); + ((CreatureAI*)target->AI())->AttackStart(m_creature->getThreatManager().getHostilTarget()); + SpellEntry *spell = (SpellEntry *)GetSpellStore()->LookupEntry(SPELL_MUTATE_BUG); + for (int i=0; i<3; i++) + { + if (!spell->Effect[i]) + continue; + target->AddAura(new BugAura(spell, i, NULL, target, target)); + } + target->SetHealth(target->GetMaxHealth()); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if (!TryActivateAfterTTelep(diff)) + return; + + //UnbalancingStrike_Timer + if (UnbalancingStrike_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_UNBALANCING_STRIKE); + UnbalancingStrike_Timer = 8000+rand()%12000; + }else UnbalancingStrike_Timer -= diff; + + if (UpperCut_Timer < diff) + { + Unit* randomMelee = GetAnyoneCloseEnough(ATTACK_DISTANCE, true); + if (randomMelee) + DoCast(randomMelee,SPELL_UPPERCUT); + UpperCut_Timer = 15000+rand()%15000; + }else UpperCut_Timer -= diff; + + HandleBugs(diff); + + //Heal brother when 60yrds close + TryHealBrother(diff); + + //Teleporting to brother + if(Teleport_Timer < diff) + { + TeleportToMyBrother(); + }else Teleport_Timer -= diff; + + CheckEnrage(diff); + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL boss_veklorAI : public boss_twinemperorsAI +{ + bool IAmVeklor() {return true;} + boss_veklorAI(Creature *c) : boss_twinemperorsAI(c) + { + Reset(); + } + + uint32 ShadowBolt_Timer; + uint32 Blizzard_Timer; + uint32 ArcaneBurst_Timer; + uint32 Scorpions_Timer; + int Rand; + int RandX; + int RandY; + + Creature* Summoned; + + void Reset() + { + TwinReset(); + ShadowBolt_Timer = 0; + Blizzard_Timer = 15000 + rand()%5000;; + ArcaneBurst_Timer = 1000; + Scorpions_Timer = 7000 + rand()%7000; + + //Added. Can be removed if its included in DB. + m_creature->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true); + m_creature->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, 0); + m_creature->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, 0); + } + + void CastSpellOnBug(Creature *target) + { + target->setFaction(14); + SpellEntry *spell = (SpellEntry *)GetSpellStore()->LookupEntry(SPELL_EXPLODEBUG); + for (int i=0; i<3; i++) + { + if (!spell->Effect[i]) + continue; + target->AddAura(new BugAura(spell, i, NULL, target, target)); + } + target->SetHealth(target->GetMaxHealth()); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + // reset arcane burst after teleport - we need to do this because + // when VL jumps to VN's location there will be a warrior who will get only 2s to run away + // which is almost impossible + if (AfterTeleport) + ArcaneBurst_Timer = 5000; + if (!TryActivateAfterTTelep(diff)) + return; + + //ShadowBolt_Timer + if (ShadowBolt_Timer < diff) + { + if (m_creature->GetDistance(m_creature->getVictim()) > 45) + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim(), VEKLOR_DIST, 0); + else + DoCast(m_creature->getVictim(),SPELL_SHADOWBOLT); + ShadowBolt_Timer = 2000; + }else ShadowBolt_Timer -= diff; + + //Blizzard_Timer + if (Blizzard_Timer < diff) + { + Unit* target = NULL; + target = GetAnyoneCloseEnough(45, true); + if (target) + DoCast(target,SPELL_BLIZZARD); + Blizzard_Timer = 15000+rand()%15000; + }else Blizzard_Timer -= diff; + + if (ArcaneBurst_Timer < diff) + { + Unit *mvic; + if ((mvic=GetAnyoneCloseEnough(ATTACK_DISTANCE, false))!=NULL) + { + DoCast(mvic,SPELL_ARCANEBURST); + ArcaneBurst_Timer = 5000; + } + }else ArcaneBurst_Timer -= diff; + + HandleBugs(diff); + + //Heal brother when 60yrds close + TryHealBrother(diff); + + //Teleporting to brother + if(Teleport_Timer < diff) + { + TeleportToMyBrother(); + }else Teleport_Timer -= diff; + + CheckEnrage(diff); + + //VL doesn't melee + //DoMeleeAttackIfReady(); + } + + void AttackStart(Unit* who) + { + if (!who) + return; + + if (who->isTargetableForAttack()) + { + // VL doesn't melee + if ( m_creature->Attack(who, false) ) + { + m_creature->GetMotionMaster()->MoveChase(who, VEKLOR_DIST, 0); + m_creature->AddThreat(who, 0.0f); + } + + if (!InCombat) + { + Aggro(who); + InCombat = true; + } + } + } +}; + +CreatureAI* GetAI_boss_veknilash(Creature *_Creature) +{ + return new boss_veknilashAI (_Creature); +} + +CreatureAI* GetAI_boss_veklor(Creature *_Creature) +{ + return new boss_veklorAI (_Creature); +} + +void AddSC_boss_twinemperors() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_veknilash"; + newscript->GetAI = GetAI_boss_veknilash; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="boss_veklor"; + newscript->GetAI = GetAI_boss_veklor; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_viscidus.cpp b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_viscidus.cpp new file mode 100644 index 00000000000..36a8bfea1c1 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_viscidus.cpp @@ -0,0 +1,29 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Viscidus +SD%Complete: 0 +SDComment: place holder +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_POISON_SHOCK 25993 +#define SPELL_POISONBOLT_VOLLEY 25991 + +#define SPELL_TOXIN_CLOUD 25989 diff --git a/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/def_temple_of_ahnqiraj.h b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/def_temple_of_ahnqiraj.h new file mode 100644 index 00000000000..fdc6d30a0cb --- /dev/null +++ b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/def_temple_of_ahnqiraj.h @@ -0,0 +1,22 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_TEMPLE_OF_AHNQIRAJ_H +#define DEF_TEMPLE_OF_AHNQIRAJ_H + +#define DATA_SKERAM 1 +#define DATA_KRI 2 +#define DATA_VEM 3 +#define DATA_VEMISDEAD 4 +#define DATA_VEM_DEATH 5 +#define DATA_VEKLOR 6 +#define DATA_VEKLORISDEAD 7 +#define DATA_VEKLOR_DEATH 8 +#define DATA_VEKNILASH 9 +#define DATA_VEKNILASHISDEAD 10 +#define DATA_VEKNILASH_DEATH 11 +#define DATA_BUG_TRIO_DEATH 14 + +#define DATA_CTHUN_PHASE 20 +#endif diff --git a/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/instance_temple_of_ahnqiraj.cpp b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/instance_temple_of_ahnqiraj.cpp new file mode 100644 index 00000000000..724a64e2baa --- /dev/null +++ b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/instance_temple_of_ahnqiraj.cpp @@ -0,0 +1,165 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Temple_of_Ahnqiraj +SD%Complete: 80 +SDComment: +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "precompiled.h" +#include "def_temple_of_ahnqiraj.h" + +struct MANGOS_DLL_DECL instance_temple_of_ahnqiraj : public ScriptedInstance +{ + instance_temple_of_ahnqiraj(Map *Map) : ScriptedInstance(Map) {Initialize();}; + + //If Vem is dead... + bool IsBossDied[3]; + + //Storing Skeram, Vem and Kri. + uint64 SkeramGUID; + uint64 VemGUID; + uint64 KriGUID; + uint64 VeklorGUID; + uint64 VeknilashGUID; + + uint32 BugTrioDeathCount; + + uint32 CthunPhase; + + void Initialize() + { + IsBossDied[0] = false; + IsBossDied[1] = false; + IsBossDied[2] = false; + + SkeramGUID = 0; + VemGUID = 0; + KriGUID = 0; + VeklorGUID = 0; + VeknilashGUID = 0; + + BugTrioDeathCount = 0; + + CthunPhase = 0; + } + + void OnCreatureCreate (Creature *creature, uint32 creature_entry) + { + switch (creature_entry) + { + case 15263: SkeramGUID = creature->GetGUID(); break; + case 15544: VemGUID = creature->GetGUID(); break; + case 15511: KriGUID = creature->GetGUID(); break; + case 15276: VeklorGUID = creature->GetGUID(); break; + case 15275: VeknilashGUID = creature->GetGUID(); break; + } + } + + bool IsEncounterInProgress() const + { + //not active in AQ40 + return false; + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_VEMISDEAD: + if(IsBossDied[0]) + return 1; + break; + + case DATA_VEKLORISDEAD: + if(IsBossDied[1]) + return 1; + break; + + case DATA_VEKNILASHISDEAD: + if(IsBossDied[2]) + return 1; + break; + + case DATA_BUG_TRIO_DEATH: + return BugTrioDeathCount; + + case DATA_CTHUN_PHASE: + return CthunPhase; + } + return 0; + } + + uint64 GetData64 (uint32 identifier) + { + switch(identifier) + { + case DATA_SKERAM: + return SkeramGUID; + case DATA_VEM: + return VemGUID; + case DATA_KRI: + return KriGUID; + case DATA_VEKLOR: + return VeklorGUID; + case DATA_VEKNILASH: + return VeknilashGUID; + } + return 0; + } // end GetData64 + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_VEM_DEATH: + IsBossDied[0] = true; + break; + + case DATA_BUG_TRIO_DEATH: + BugTrioDeathCount++; + break; + + case DATA_VEKLOR_DEATH: + IsBossDied[1] = true; + break; + + case DATA_VEKNILASH_DEATH: + IsBossDied[2] = true; + break; + + case DATA_CTHUN_PHASE: + CthunPhase = data; + break; + } + } +}; + +InstanceData* GetInstanceData_instance_temple_of_ahnqiraj(Map* map) +{ + return new instance_temple_of_ahnqiraj(map); +} + +void AddSC_instance_temple_of_ahnqiraj() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_temple_of_ahnqiraj"; + newscript->GetInstanceData = GetInstanceData_instance_temple_of_ahnqiraj; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp new file mode 100644 index 00000000000..62c21978adf --- /dev/null +++ b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp @@ -0,0 +1,344 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: mob_anubisath_sentinel +SD%Complete: 95 +SDComment: Shadow storm is not properly implemented in core it should only target ppl outside of melee range. +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "precompiled.h" +#include "WorldPacket.h" + +#include "Item.h" +#include "Player.h" +#include "Spell.h" + +#include "Cell.h" +#include "CellImpl.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" + +#define SPELL_MENDING_BUFF 2147 + +#define SPELL_KNOCK_BUFF 21737 +#define SPELL_KNOCK 25778 +#define SPELL_MANAB_BUFF 812 +#define SPELL_MANAB 25779 + +#define SPELL_REFLECTAF_BUFF 13022 +#define SPELL_REFLECTSFr_BUFF 19595 +#define SPELL_THORNS_BUFF 25777 + +#define SPELL_THUNDER_BUFF 2834 +#define SPELL_THUNDER 8732 + +#define SPELL_MSTRIKE_BUFF 9347 +#define SPELL_MSTRIKE 24573 + +#define SPELL_STORM_BUFF 2148 +#define SPELL_STORM 26546 + +class NearbyAQSentinel +{ + public: + NearbyAQSentinel(Unit const* obj) : i_obj(obj) {} + bool operator()(Unit* u) + { + if (u->GetEntry() == 15264 && i_obj->IsWithinDistInMap(u, 70) && !u->isDead()) + return true; + else + return false; + } + private: + Unit const* i_obj; +}; + +struct MANGOS_DLL_DECL aqsentinelAI; +class MANGOS_DLL_DECL SentinelAbilityAura : public Aura +{ + public: + ~SentinelAbilityAura(); + Unit* GetTriggerTarget() const; + SentinelAbilityAura(aqsentinelAI *abilityOwner, SpellEntry *spell, uint32 ability, uint32 eff); + protected: + aqsentinelAI *aOwner; + int32 currentBasePoints; + uint32 abilityId; +}; + +struct MANGOS_DLL_DECL aqsentinelAI : public ScriptedAI +{ + uint32 ability; + int abselected; + + void selectAbility(int asel) + { + switch (asel) + { + case 0: ability = SPELL_MENDING_BUFF;break; + case 1: ability = SPELL_KNOCK_BUFF;break; + case 2: ability = SPELL_MANAB_BUFF;break; + case 3: ability = SPELL_REFLECTAF_BUFF;break; + case 4: ability = SPELL_REFLECTSFr_BUFF;break; + case 5: ability = SPELL_THORNS_BUFF;break; + case 6: ability = SPELL_THUNDER_BUFF;break; + case 7: ability = SPELL_MSTRIKE_BUFF;break; + case 8: ability = SPELL_STORM_BUFF;break; + } + } + + aqsentinelAI(Creature *c) : ScriptedAI(c) + { + ClearBudyList(); + abselected = 0; // just initialization of variable + Reset(); + } + + Creature *nearby[3]; + + void ClearBudyList() + { + nearby[0] = nearby[1] = nearby[2] = NULL; + } + + void AddBuddyToList(Creature *c) + { + if (c==m_creature) + return; + for (int i=0; i<3; i++) + { + if (nearby[i] == c) + return; + if (!nearby[i]) + { + nearby[i] = c; + return; + } + } + } + + void GiveBuddyMyList(Creature *c) + { + aqsentinelAI *cai = (aqsentinelAI *)(c->AI()); + for (int i=0; i<3; i++) + if (nearby[i] && nearby[i]!=c) + cai->AddBuddyToList(nearby[i]); + cai->AddBuddyToList(m_creature); + } + + void SendMyListToBuddies() + { + for (int i=0; i<3; i++) + if (nearby[i]) + GiveBuddyMyList(nearby[i]); + } + + void CallBuddiesToAttack(Unit *who) + { + for (int i=0; i<3; i++) + { + Creature *c = nearby[i]; + if (c) + { + if (!c->isInCombat()) + { + c->SetNoCallAssistence(true); + if(c->AI()) + c->AI()->AttackStart(who); + } + } + } + } + + void AddSentinelsNear(Unit *nears) + { + CellPair p(MaNGOS::ComputeCellPair(nears->GetPositionX(), nears->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + std::list assistList; + + NearbyAQSentinel u_check(nears); + MaNGOS::CreatureListSearcher searcher(assistList, u_check); + TypeContainerVisitor, GridTypeMapContainer > grid_creature_searcher(searcher); + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, grid_creature_searcher, *(nears->GetMap())); + + for(std::list::iterator iter = assistList.begin(); iter != assistList.end(); ++iter) + AddBuddyToList((*iter)); + } + + int pickAbilityRandom(bool *chosenAbilities) + { + for (int t = 0; t < 2; t++) + { + for (int i = !t ? (rand()%9) : 0; i < 9; i++) + { + if (!chosenAbilities[i]) + { + chosenAbilities[i] = true; + return i; + } + } + } + return 0; // should never happen + } + + void GetOtherSentinels(Unit *who) + { + bool *chosenAbilities = new bool[9]; + memset(chosenAbilities, 0, 9*sizeof(bool)); + selectAbility(pickAbilityRandom(chosenAbilities)); + + ClearBudyList(); + AddSentinelsNear(m_creature); + int bli; + for (bli = 0; bli < 3;bli++) + { + if (!nearby[bli]) + break; + AddSentinelsNear(nearby[bli]); + ((aqsentinelAI *)nearby[bli]->AI())->gatherOthersWhenAggro = false; + ((aqsentinelAI *)nearby[bli]->AI())->selectAbility(pickAbilityRandom(chosenAbilities)); + } + /*if (bli < 3) + DoYell("I dont have enough buddies.", LANG_NEUTRAL, 0);*/ + SendMyListToBuddies(); + CallBuddiesToAttack(who); + } + + bool gatherOthersWhenAggro; + + void Reset() + { + if (!m_creature->isDead()) + { + for (int i=0; i<3; i++) + { + if (!nearby[i]) + continue; + if (nearby[i]->isDead()) + nearby[i]->Respawn(); + } + } + ClearBudyList(); + gatherOthersWhenAggro = true; + m_creature->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false); + m_creature->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, false); + } + + void GainSentinelAbility(uint32 id) + { + const SpellEntry *spell = GetSpellStore()->LookupEntry(id); + for (int i=0; i<3; i++) + { + if (!spell->Effect[i]) + continue; + SentinelAbilityAura *a = new SentinelAbilityAura(this, (SpellEntry *)spell, id, i); + m_creature->AddAura(a); + } + if (id == SPELL_KNOCK_BUFF) + { + m_creature->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); + m_creature->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true); + } + } + + void Aggro(Unit *who) + { + if (gatherOthersWhenAggro) + GetOtherSentinels(who); + + GainSentinelAbility(ability); + DoZoneInCombat(); + } + + void JustDied(Unit*) + { + for (int ni=0; ni<3; ni++) + { + Creature *sent = nearby[ni]; + if (!sent) + continue; + if (sent->isDead()) + continue; + int h = sent->GetHealth() + (sent->GetMaxHealth() / 2); + if (h > sent->GetMaxHealth()) + h = sent->GetMaxHealth(); + sent->SetHealth(h); + ((aqsentinelAI *)sent->AI())->GainSentinelAbility(ability); + } + } + + Unit *GetHatedManaUser() + { + std::list::iterator i; + for (i = m_creature->getThreatManager().getThreatList().begin();i != m_creature->getThreatManager().getThreatList().end(); ++i) + { + Unit* pUnit = Unit::GetUnit((*m_creature), (*i)->getUnitGuid()); + if (pUnit->getPowerType()==POWER_MANA) + return pUnit; + } + return NULL; + } +}; +CreatureAI* GetAI_mob_anubisath_sentinelAI(Creature *_Creature) +{ + return new aqsentinelAI (_Creature); +} + +void AddSC_mob_anubisath_sentinel() +{ + Script *newscript; + newscript = new Script; + newscript->Name="mob_anubisath_sentinel"; + newscript->GetAI = GetAI_mob_anubisath_sentinelAI; + m_scripts[nrscripts++] = newscript; +} + +SentinelAbilityAura::~SentinelAbilityAura() {} +Unit* SentinelAbilityAura::GetTriggerTarget() const +{ + switch (abilityId) + { + case SPELL_KNOCK_BUFF: + case SPELL_THUNDER_BUFF: + case SPELL_MSTRIKE_BUFF: + case SPELL_STORM_BUFF: + return aOwner->m_creature->getVictim(); + + case SPELL_MANAB_BUFF: + return aOwner->GetHatedManaUser(); + + case SPELL_MENDING_BUFF: + case SPELL_REFLECTAF_BUFF: + case SPELL_REFLECTSFr_BUFF: + case SPELL_THORNS_BUFF: + default: + return aOwner->m_creature; + } +} + +SentinelAbilityAura::SentinelAbilityAura(aqsentinelAI *abilityOwner, SpellEntry *spell, uint32 ability, uint32 eff) +: Aura(spell, eff, NULL, abilityOwner->m_creature, abilityOwner->m_creature, NULL) +{ + aOwner = abilityOwner; + abilityId = ability; + currentBasePoints = 0; +} diff --git a/src/bindings/scripts/scripts/zone/terokkar_forest/terokkar_forest.cpp b/src/bindings/scripts/scripts/zone/terokkar_forest/terokkar_forest.cpp new file mode 100644 index 00000000000..2dc7e54297b --- /dev/null +++ b/src/bindings/scripts/scripts/zone/terokkar_forest/terokkar_forest.cpp @@ -0,0 +1,399 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Terokkar_Forest +SD%Complete: 80 +SDComment: Quest support: 9889(test script only, sql inside script), 10009, 10873, 10896, 11096. Skettis->Ogri'la Flight +SDCategory: Terokkar Forest +EndScriptData */ + +/* ContentData +mob_unkor_the_ruthless +mob_infested_root_walker +mob_rotting_forest_rager +mob_netherweb_victim +npc_floon +npc_skyguard_handler_deesak +EndContentData */ + +#include "precompiled.h" + +/*###### +## mob_unkor_the_ruthless +######*/ + +/* +UPDATE `creature_template` SET `ScriptName`='mob_unkor_the_ruthless' WHERE `entry`=18262; +*/ + +#define SAY_SUBMIT "I give up! Please don't kill me!" + +#define FACTION_HOSTILE 45 +#define FACTION_FRIENDLY 35 +#define QUEST_DONTKILLTHEFATONE 9889 + +#define SPELL_PULVERIZE 2676 +//#define SPELL_QUID9889 32174 + +struct MANGOS_DLL_DECL mob_unkor_the_ruthlessAI : public ScriptedAI +{ + mob_unkor_the_ruthlessAI(Creature* c) : ScriptedAI(c) { Reset(); } + + bool CanDoQuest; + uint32 UnkorUnfriendly_Timer; + uint32 Pulverize_Timer; + + void Reset() + { + CanDoQuest = false; + UnkorUnfriendly_Timer = 0; + Pulverize_Timer = 3000; + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, PLAYER_STATE_NONE); + m_creature->setFaction(FACTION_HOSTILE); + } + + void Aggro(Unit *who) {} + + void DoNice() + { + DoSay(SAY_SUBMIT,LANG_UNIVERSAL,NULL); + m_creature->setFaction(FACTION_FRIENDLY); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, PLAYER_STATE_SIT); + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); + m_creature->CombatStop(); + UnkorUnfriendly_Timer = 60000; + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if( done_by->GetTypeId() == TYPEID_PLAYER ) + if( (m_creature->GetHealth()-damage)*100 / m_creature->GetMaxHealth() < 30 ) + { + if( Group* pGroup = ((Player*)done_by)->GetGroup() ) + { + for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *pGroupie = itr->getSource(); + if( pGroupie && + pGroupie->GetQuestStatus(QUEST_DONTKILLTHEFATONE) == QUEST_STATUS_INCOMPLETE && + pGroupie->GetReqKillOrCastCurrentCount(QUEST_DONTKILLTHEFATONE, 18260) == 10 ) + { + pGroupie->AreaExploredOrEventHappens(QUEST_DONTKILLTHEFATONE); + if( !CanDoQuest ) + CanDoQuest = true; + } + } + } else + if( ((Player*)done_by)->GetQuestStatus(QUEST_DONTKILLTHEFATONE) == QUEST_STATUS_INCOMPLETE && + ((Player*)done_by)->GetReqKillOrCastCurrentCount(QUEST_DONTKILLTHEFATONE, 18260) == 10 ) + { + ((Player*)done_by)->AreaExploredOrEventHappens(QUEST_DONTKILLTHEFATONE); + CanDoQuest = true; + } + } + } + + void UpdateAI(const uint32 diff) + { + if( CanDoQuest ) + { + if( !UnkorUnfriendly_Timer ) + { + //DoCast(m_creature,SPELL_QUID9889); //not using spell for now + DoNice(); + } + else + { + if( UnkorUnfriendly_Timer < diff ) + { + EnterEvadeMode(); + }else UnkorUnfriendly_Timer -= diff; + } + } + + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if( Pulverize_Timer < diff ) + { + DoCast(m_creature,SPELL_PULVERIZE); + Pulverize_Timer = 9000; + }else Pulverize_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_unkor_the_ruthless(Creature *_Creature) +{ + return new mob_unkor_the_ruthlessAI (_Creature); +} + +/*###### +## mob_infested_root_walker +######*/ + +struct MANGOS_DLL_DECL mob_infested_root_walkerAI : public ScriptedAI +{ + mob_infested_root_walkerAI(Creature *c) : ScriptedAI(c) {Reset();} + + void Reset() { } + void Aggro(Unit *who) { } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (done_by && done_by->GetTypeId() == TYPEID_PLAYER) + if (m_creature->GetHealth() <= damage) + if (rand()%100 < 75) + //Summon Wood Mites + m_creature->CastSpell(m_creature,39130,true); + } +}; +CreatureAI* GetAI_mob_infested_root_walker(Creature *_Creature) +{ + return new mob_infested_root_walkerAI (_Creature); +} + +/*###### +## mob_rotting_forest_rager +######*/ + +struct MANGOS_DLL_DECL mob_rotting_forest_ragerAI : public ScriptedAI +{ + mob_rotting_forest_ragerAI(Creature *c) : ScriptedAI(c) {Reset();} + + void Reset() { } + void Aggro(Unit *who) { } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (done_by->GetTypeId() == TYPEID_PLAYER) + if (m_creature->GetHealth() <= damage) + if (rand()%100 < 75) + //Summon Lots of Wood Mights + m_creature->CastSpell(m_creature,39134,true); + } +}; +CreatureAI* GetAI_mob_rotting_forest_rager(Creature *_Creature) +{ + return new mob_rotting_forest_ragerAI (_Creature); +} + +/*###### +## mob_netherweb_victim +######*/ + +#define QUEST_TARGET 22459 +//#define SPELL_FREE_WEBBED 38950 + +const uint32 netherwebVictims[6] = +{ + 18470, 16805, 21242, 18452, 22482, 21285 +}; +struct MANGOS_DLL_DECL mob_netherweb_victimAI : public ScriptedAI +{ + mob_netherweb_victimAI(Creature *c) : ScriptedAI(c) {Reset();} + + void Reset() { } + void Aggro(Unit *who) { } + void MoveInLineOfSight(Unit *who) { } + + void JustDied(Unit* Killer) + { + if( Killer->GetTypeId() == TYPEID_PLAYER ) + { + if( ((Player*)Killer)->GetQuestStatus(10873) == QUEST_STATUS_INCOMPLETE ) + { + if( rand()%100 < 25 ) + { + DoSpawnCreature(QUEST_TARGET,0,0,0,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,60000); + ((Player*)Killer)->KilledMonster(QUEST_TARGET, m_creature->GetGUID()); + }else + DoSpawnCreature(netherwebVictims[rand()%6],0,0,0,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,60000); + + if( rand()%100 < 75 ) + DoSpawnCreature(netherwebVictims[rand()%6],0,0,0,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,60000); + DoSpawnCreature(netherwebVictims[rand()%6],0,0,0,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,60000); + } + } + } +}; +CreatureAI* GetAI_mob_netherweb_victim(Creature *_Creature) +{ + return new mob_netherweb_victimAI (_Creature); +} + +/*###### +## npc_floon +######*/ + +#define GOSSIP_FLOON1 "You owe Sim'salabim money. Hand them over or die!" +#define GOSSIP_FLOON2 "Hand over the money or die...again!" +#define SAY_FLOON_ATTACK "I choose the third option: KILLING YOU!" + +#define FACTION_HOSTILE_FL 1738 +#define FACTION_FRIENDLY_FL 35 + +#define SPELL_SILENCE 6726 +#define SPELL_FROSTBOLT 9672 +#define SPELL_FROST_NOVA 11831 + +struct MANGOS_DLL_DECL npc_floonAI : public ScriptedAI +{ + npc_floonAI(Creature* c) : ScriptedAI(c) { Reset(); } + + uint32 Silence_Timer; + uint32 Frostbolt_Timer; + uint32 FrostNova_Timer; + + void Reset() + { + Silence_Timer = 2000; + Frostbolt_Timer = 4000; + FrostNova_Timer = 9000; + m_creature->setFaction(FACTION_FRIENDLY_FL); + } + + void Aggro(Unit *who) {} + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if( Silence_Timer < diff ) + { + DoCast(m_creature->getVictim(),SPELL_SILENCE); + Silence_Timer = 30000; + }else Silence_Timer -= diff; + + if( FrostNova_Timer < diff ) + { + DoCast(m_creature,SPELL_FROST_NOVA); + FrostNova_Timer = 20000; + }else FrostNova_Timer -= diff; + + if( Frostbolt_Timer < diff ) + { + DoCast(m_creature->getVictim(),SPELL_FROSTBOLT); + Frostbolt_Timer = 5000; + }else Frostbolt_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_npc_floon(Creature *_Creature) +{ + return new npc_floonAI (_Creature); +} + +bool GossipHello_npc_floon(Player *player, Creature *_Creature ) +{ + if( player->GetQuestStatus(10009) == QUEST_STATUS_INCOMPLETE ) + player->ADD_GOSSIP_ITEM(1, GOSSIP_FLOON1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + player->SEND_GOSSIP_MENU(9442, _Creature->GetGUID()); + return true; +} + +bool GossipSelect_npc_floon(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if( action == GOSSIP_ACTION_INFO_DEF ) + { + player->ADD_GOSSIP_ITEM(1, GOSSIP_FLOON2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + player->SEND_GOSSIP_MENU(9443, _Creature->GetGUID()); + } + if( action == GOSSIP_ACTION_INFO_DEF+1 ) + { + player->CLOSE_GOSSIP_MENU(); + _Creature->setFaction(FACTION_HOSTILE_FL); + ((npc_floonAI*)_Creature->AI())->DoSay(SAY_FLOON_ATTACK,LANG_UNIVERSAL,player); + ((npc_floonAI*)_Creature->AI())->AttackStart(player); + } + return true; +} + +/*###### +## npc_skyguard_handler_deesak +######*/ + +#define GOSSIP_SKYGUARD "Fly me to Ogri'la please" + +bool GossipHello_npc_skyguard_handler_deesak(Player *player, Creature *_Creature ) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if (player->GetReputationRank(1031) >= REP_HONORED) + player->ADD_GOSSIP_ITEM( 2, GOSSIP_SKYGUARD, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_skyguard_handler_deesak(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if (action == GOSSIP_ACTION_INFO_DEF+1) + { + player->CLOSE_GOSSIP_MENU(); + player->CastSpell(player,41279,true); //TaxiPath 705 (Taxi - Skettis to Skyguard Outpost) + } + return true; +} + +/*###### +## AddSC +######*/ + +void AddSC_terokkar_forest() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="mob_unkor_the_ruthless"; + newscript->GetAI = GetAI_mob_unkor_the_ruthless; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_infested_root_walker"; + newscript->GetAI = GetAI_mob_infested_root_walker; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_rotting_forest_rager"; + newscript->GetAI = GetAI_mob_rotting_forest_rager; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_netherweb_victim"; + newscript->GetAI = GetAI_mob_netherweb_victim; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_floon"; + newscript->pGossipHello = &GossipHello_npc_floon; + newscript->pGossipSelect = &GossipSelect_npc_floon; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_skyguard_handler_deesak"; + newscript->pGossipHello = &GossipHello_npc_skyguard_handler_deesak; + newscript->pGossipSelect = &GossipSelect_npc_skyguard_handler_deesak; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/thunder_bluff/thunder_bluff.cpp b/src/bindings/scripts/scripts/zone/thunder_bluff/thunder_bluff.cpp new file mode 100644 index 00000000000..b526325f5c9 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/thunder_bluff/thunder_bluff.cpp @@ -0,0 +1,136 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Thunder_Bluff +SD%Complete: 100 +SDComment: Quest support: 925 +SDCategory: Thunder Bluff +EndScriptData */ + +#include "precompiled.h" + +/*##### +# npc_cairne_bloodhoof +######*/ + +#define SPELL_BERSERKER_CHARGE 16636 +#define SPELL_CLEAVE 16044 +#define SPELL_MORTAL_STRIKE 16856 +#define SPELL_THUNDERCLAP 23931 +#define SPELL_UPPERCUT 22916 + +//TODO: verify abilities/timers +struct MANGOS_DLL_DECL npc_cairne_bloodhoofAI : public ScriptedAI +{ + npc_cairne_bloodhoofAI(Creature* c) : ScriptedAI(c) { Reset(); } + + uint32 BerserkerCharge_Timer; + uint32 Cleave_Timer; + uint32 MortalStrike_Timer; + uint32 Thunderclap_Timer; + uint32 Uppercut_Timer; + + void Reset() + { + BerserkerCharge_Timer = 30000; + Cleave_Timer = 5000; + MortalStrike_Timer = 10000; + Thunderclap_Timer = 15000; + Uppercut_Timer = 10000; + } + + void Aggro(Unit *who) {} + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if( BerserkerCharge_Timer < diff ) + { + Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0); + if( target ) + DoCast(target,SPELL_BERSERKER_CHARGE); + BerserkerCharge_Timer = 25000; + }else BerserkerCharge_Timer -= diff; + + if( Uppercut_Timer < diff ) + { + DoCast(m_creature->getVictim(),SPELL_UPPERCUT); + Uppercut_Timer = 20000; + }else Uppercut_Timer -= diff; + + if( Thunderclap_Timer < diff ) + { + DoCast(m_creature->getVictim(),SPELL_THUNDERCLAP); + Thunderclap_Timer = 15000; + }else Thunderclap_Timer -= diff; + + if( MortalStrike_Timer < diff ) + { + DoCast(m_creature->getVictim(),SPELL_MORTAL_STRIKE); + MortalStrike_Timer = 15000; + }else MortalStrike_Timer -= diff; + + if( Cleave_Timer < diff ) + { + DoCast(m_creature->getVictim(),SPELL_CLEAVE); + Cleave_Timer = 7000; + }else Cleave_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_npc_cairne_bloodhoof(Creature *_Creature) +{ + return new npc_cairne_bloodhoofAI (_Creature); +} + +bool GossipHello_npc_cairne_bloodhoof(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if( player->GetQuestStatus(925) == QUEST_STATUS_INCOMPLETE ) + player->ADD_GOSSIP_ITEM( 0, "I know this is rather silly but a young ward who is a bit shy would like your hoofprint.", GOSSIP_SENDER_MAIN, GOSSIP_SENDER_INFO ); + + player->SEND_GOSSIP_MENU(7013, _Creature->GetGUID() ); + + return true; +} + +bool GossipSelect_npc_cairne_bloodhoof(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if( action == GOSSIP_SENDER_INFO ) + { + player->CastSpell(player, 23123, false); + player->SEND_GOSSIP_MENU(7014, _Creature->GetGUID() ); + } + return true; +} + +void AddSC_thunder_bluff() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npc_cairne_bloodhoof"; + newscript->GetAI = GetAI_npc_cairne_bloodhoof; + newscript->pGossipHello = &GossipHello_npc_cairne_bloodhoof; + newscript->pGossipSelect = &GossipSelect_npc_cairne_bloodhoof; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/tirisfal_glades/tirisfal_glades.cpp b/src/bindings/scripts/scripts/zone/tirisfal_glades/tirisfal_glades.cpp new file mode 100644 index 00000000000..8a02147eb41 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/tirisfal_glades/tirisfal_glades.cpp @@ -0,0 +1,88 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Tirisfal_Glades +SD%Complete: 100 +SDComment: Quest support: 590 +SDCategory: Tirisfal Glades +EndScriptData */ + +/* ContentData +npc_calvin_montague +EndContentData */ + +#include "precompiled.h" + +/*###### +## npc_calvin_montague +######*/ + +#define QUEST_590 590 +#define FACTION_FRIENDLY 68 +#define FACTION_HOSTILE 16 + +struct MANGOS_DLL_DECL npc_calvin_montagueAI : public ScriptedAI +{ + npc_calvin_montagueAI(Creature* c) : ScriptedAI(c) { Reset(); } + + void Reset() + { + m_creature->setFaction(FACTION_FRIENDLY); + } + + void Aggro(Unit* who) { } + + void JustDied(Unit* Killer) + { + if( Killer->GetTypeId() == TYPEID_PLAYER ) + if( ((Player*)Killer)->GetQuestStatus(QUEST_590) == QUEST_STATUS_INCOMPLETE ) + ((Player*)Killer)->AreaExploredOrEventHappens(QUEST_590); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_npc_calvin_montague(Creature *_Creature) +{ + return new npc_calvin_montagueAI (_Creature); +} + +bool QuestAccept_npc_calvin_montague(Player* player, Creature* creature, Quest const* quest) +{ + if( quest->GetQuestId() == QUEST_590 ) + { + creature->setFaction(FACTION_HOSTILE); + ((npc_calvin_montagueAI*)creature->AI())->AttackStart(player); + } + return true; +} + +void AddSC_tirisfal_glades() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npc_calvin_montague"; + newscript->GetAI = GetAI_npc_calvin_montague; + newscript->pQuestAccept = &QuestAccept_npc_calvin_montague; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/uldaman/boss_ironaya.cpp b/src/bindings/scripts/scripts/zone/uldaman/boss_ironaya.cpp new file mode 100644 index 00000000000..57871381f9d --- /dev/null +++ b/src/bindings/scripts/scripts/zone/uldaman/boss_ironaya.cpp @@ -0,0 +1,107 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Ironaya +SD%Complete: 100 +SDComment: +SDCategory: Uldaman +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_ARCINGSMASH 39144 +#define SPELL_KNOCKAWAY 22893 +#define SPELL_WSTOMP 16727 + +#define SAY_AGGRO "None may steal the secrets of the makers!" +#define SOUND_AGGRO 5851 + +struct MANGOS_DLL_DECL boss_ironayaAI : public ScriptedAI +{ + boss_ironayaAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Arcing_Timer; + bool hasCastedWstomp; + bool hasCastedKnockaway; + + void Reset() + { + Arcing_Timer = 3000; + hasCastedKnockaway = false; + hasCastedWstomp = false; + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //If we are <50% hp do knockaway ONCE + if (!hasCastedKnockaway && m_creature->GetHealth()*2 < m_creature->GetMaxHealth()) + { + m_creature->CastSpell(m_creature->getVictim(),SPELL_KNOCKAWAY, true); + + // current aggro target is knocked away pick new target + Unit* Target = SelectUnit(SELECT_TARGET_TOPAGGRO, 0); + + if (!Target || Target == m_creature->getVictim()) + Target = SelectUnit(SELECT_TARGET_TOPAGGRO, 1); + + if (Target) + m_creature->TauntApply(Target); + + //Shouldn't cast this agian + hasCastedKnockaway = true; + } + + //Arcing_Timer + if (Arcing_Timer < diff) + { + DoCast(m_creature,SPELL_ARCINGSMASH); + Arcing_Timer = 13000; + }else Arcing_Timer -= diff; + + if (!hasCastedWstomp && m_creature->GetHealth()*4 < m_creature->GetMaxHealth()) + { + DoCast(m_creature,SPELL_WSTOMP); + hasCastedWstomp = true; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_ironaya(Creature *_Creature) +{ + return new boss_ironayaAI (_Creature); +} + +void AddSC_boss_ironaya() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_ironaya"; + newscript->GetAI = GetAI_boss_ironaya; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/uldaman/uldaman.cpp b/src/bindings/scripts/scripts/zone/uldaman/uldaman.cpp new file mode 100644 index 00000000000..59bad6854fb --- /dev/null +++ b/src/bindings/scripts/scripts/zone/uldaman/uldaman.cpp @@ -0,0 +1,187 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Uldaman +SD%Complete: 100 +SDComment: Quest support: 2278 + 1 trash mob. +SDCategory: Uldaman +EndScriptData */ + +/* ContentData +mob_jadespine_basilisk +npc_lore_keeper_of_norgannon +EndContentData */ + +#include "precompiled.h" + +/*###### +## mob_jadespine_basilisk +######*/ + +#define SPELL_CSLUMBER 3636 + +struct MANGOS_DLL_DECL mob_jadespine_basiliskAI : public ScriptedAI +{ + mob_jadespine_basiliskAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Cslumber_Timer; + + void Reset() + { + Cslumber_Timer = 2000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //Cslumber_Timer + if (Cslumber_Timer < diff) + { + //Cast + // DoCast(m_creature->getVictim(),SPELL_CSLUMBER); + m_creature->CastSpell(m_creature->getVictim(),SPELL_CSLUMBER, true); + + //Stop attacking target thast asleep and pick new target + Cslumber_Timer = 28000; + + Unit* Target = SelectUnit(SELECT_TARGET_TOPAGGRO, 0); + + if (!Target || Target == m_creature->getVictim()) + Target = SelectUnit(SELECT_TARGET_RANDOM, 0); + + if (Target) + m_creature->TauntApply(Target); + + }else Cslumber_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_jadespine_basilisk(Creature *_Creature) +{ + return new mob_jadespine_basiliskAI (_Creature); +} + +/*###### +## npc_lore_keeper_of_norgannon +######*/ + +bool GossipHello_npc_lore_keeper_of_norgannon(Player *player, Creature *_Creature) +{ + if (player->GetQuestStatus(2278) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM( 0, "Who are the Earthen?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + player->SEND_GOSSIP_MENU(1079, _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_lore_keeper_of_norgannon(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF+1: + player->ADD_GOSSIP_ITEM( 0, "What is a \"subterranean being matrix\"?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + player->SEND_GOSSIP_MENU(1080, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + player->ADD_GOSSIP_ITEM( 0, "What are the anomalies you speak of?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + player->SEND_GOSSIP_MENU(1081, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + player->ADD_GOSSIP_ITEM( 0, "What is a resilient foundation of construction?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + player->SEND_GOSSIP_MENU(1082, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + player->ADD_GOSSIP_ITEM( 0, "So... the Earthen were made out of stone?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + player->SEND_GOSSIP_MENU(1083, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + player->ADD_GOSSIP_ITEM( 0, "Anything else I should know about the Earthen?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); + player->SEND_GOSSIP_MENU(1084, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+6: + player->ADD_GOSSIP_ITEM( 0, "I think I understand the Creators' design intent for the Earthen now. What are the Earthen's anomalies that you spoke of earlier?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+7); + player->SEND_GOSSIP_MENU(1085, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+7: + player->ADD_GOSSIP_ITEM( 0, "What high-stress environments would cause the Earthen to destabilize?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+8); + player->SEND_GOSSIP_MENU(1086, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+8: + player->ADD_GOSSIP_ITEM( 0, "What happens when the Earthen destabilize?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+9); + player->SEND_GOSSIP_MENU(1087, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+9: + player->ADD_GOSSIP_ITEM( 0, "Troggs?! Are the troggs you mention the same as the ones in the world today?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+10); + player->SEND_GOSSIP_MENU(1088, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+10: + player->ADD_GOSSIP_ITEM( 0, "You mentioned two results when the Earthen destabilize. What is the second?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+11); + player->SEND_GOSSIP_MENU(1089, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+11: + player->ADD_GOSSIP_ITEM( 0, "Dwarves!!! Now you're telling me that dwarves originally came from the Earthen?!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+12); + player->SEND_GOSSIP_MENU(1090, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+12: + player->ADD_GOSSIP_ITEM( 0, "These dwarves are the same ones today, yes? Do the dwarves maintain any other links to the Earthen?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+13); + player->SEND_GOSSIP_MENU(1091, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+13: + player->ADD_GOSSIP_ITEM( 0, "Who are the Creators?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+14); + player->SEND_GOSSIP_MENU(1092, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+14: + player->ADD_GOSSIP_ITEM( 0, "This is a lot to think about.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+15); + player->SEND_GOSSIP_MENU(1093, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+15: + player->ADD_GOSSIP_ITEM( 0, "I will access the discs now.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+16); + player->SEND_GOSSIP_MENU(1094, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+16: + player->CLOSE_GOSSIP_MENU(); + player->AreaExploredOrEventHappens(2278); + break; + } + return true; +} + +void AddSC_uldaman() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="mob_jadespine_basilisk"; + newscript->GetAI = GetAI_mob_jadespine_basilisk; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_lore_keeper_of_norgannon"; + newscript->pGossipHello = &GossipHello_npc_lore_keeper_of_norgannon; + newscript->pGossipSelect = &GossipSelect_npc_lore_keeper_of_norgannon; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/undercity/undercity.cpp b/src/bindings/scripts/scripts/zone/undercity/undercity.cpp new file mode 100644 index 00000000000..b4845317612 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/undercity/undercity.cpp @@ -0,0 +1,260 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Undercity +SD%Complete: 95 +SDComment: Quest support: 6628(Parqual Fintallas questions/'answers' might have more to it, need more info), 9180(post-event). +SDCategory: Undercity +EndScriptData */ + +/* ContentData +npc_lady_sylvanas_windrunner +npc_highborne_lamenter +npc_parqual_fintallas +EndContentData */ + +#include "precompiled.h" + +/*###### +## npc_lady_sylvanas_windrunner +######*/ + +#define SAY_LAMENT_END "Belore..." +#define EMOTE_LAMENT_END "kneels down and pick up the amulet." + +#define SOUND_CREDIT 10896 +#define ENTRY_HIGHBORNE_LAMENTER 21628 +#define ENTRY_HIGHBORNE_BUNNY 21641 + +#define SPELL_HIGHBORNE_AURA 37090 +#define SPELL_SYLVANAS_CAST 36568 +#define SPELL_RIBBON_OF_SOULS 34432 //the real one to use might be 37099 + +float HighborneLoc[4][3]= +{ + {1285.41, 312.47, 0.51}, + {1286.96, 310.40, 1.00}, + {1289.66, 309.66, 1.52}, + {1292.51, 310.50, 1.99}, +}; +#define HIGHBORNE_LOC_Y -61.00 +#define HIGHBORNE_LOC_Y_NEW -55.50 + +struct MANGOS_DLL_DECL npc_lady_sylvanas_windrunnerAI : public ScriptedAI +{ + npc_lady_sylvanas_windrunnerAI(Creature *c) : ScriptedAI(c) { Reset(); } + + uint32 LamentEvent_Timer; + bool LamentEvent; + uint64 targetGUID; + + float myX; + float myY; + float myZ; + + void Reset() + { + myX = m_creature->GetPositionX(); + myY = m_creature->GetPositionY(); + myZ = m_creature->GetPositionZ(); + + LamentEvent_Timer = 5000; + LamentEvent = false; + targetGUID = 0; + } + + void Aggro(Unit *who) {} + + void JustSummoned(Creature *summoned) + { + if( summoned->GetEntry() == ENTRY_HIGHBORNE_BUNNY ) + { + if( Unit* target = Unit::GetUnit(*summoned,targetGUID) ) + { + target->SendMonsterMove(target->GetPositionX(),target->GetPositionY(),myZ+15.0,0,0,0); + target->Relocate(target->GetPositionX(),target->GetPositionY(),myZ+15.0); + summoned->CastSpell(target,SPELL_RIBBON_OF_SOULS,false); + } + + summoned->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT); + targetGUID = summoned->GetGUID(); + } + } + + void UpdateAI(const uint32 diff) + { + if( LamentEvent ) + { + if( LamentEvent_Timer < diff ) + { + float raX = myX; + float raY = myY; + float raZ = myZ; + + m_creature->GetRandomPoint(myX,myY,myZ,20.0,raX,raY,raZ); + m_creature->SummonCreature(ENTRY_HIGHBORNE_BUNNY,raX,raY,myZ,0,TEMPSUMMON_TIMED_DESPAWN,3000); + + LamentEvent_Timer = 2000; + if( !m_creature->HasAura(SPELL_SYLVANAS_CAST,0) ) + { + DoSay(SAY_LAMENT_END,LANG_UNIVERSAL,NULL); + DoTextEmote(EMOTE_LAMENT_END,NULL); + LamentEvent = false; + } + }else LamentEvent_Timer -= diff; + } + + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_npc_lady_sylvanas_windrunner(Creature *_Creature) +{ + return new npc_lady_sylvanas_windrunnerAI (_Creature); +} + +bool ChooseReward_npc_lady_sylvanas_windrunner(Player *player, Creature *_Creature, const Quest *_Quest, uint32 slot) +{ + if( _Quest->GetQuestId() == 9180 ) + { + ((npc_lady_sylvanas_windrunnerAI*)_Creature->AI())->LamentEvent = true; + ((npc_lady_sylvanas_windrunnerAI*)_Creature->AI())->DoPlaySoundToSet(_Creature,SOUND_CREDIT); + _Creature->CastSpell(_Creature,SPELL_SYLVANAS_CAST,false); + + for( uint8 i = 0; i < 4; i++ ) + _Creature->SummonCreature(ENTRY_HIGHBORNE_LAMENTER, HighborneLoc[i][0], HighborneLoc[i][1], HIGHBORNE_LOC_Y, HighborneLoc[i][2], TEMPSUMMON_TIMED_DESPAWN, 160000); + } + + return true; +} + +/*###### +## npc_highborne_lamenter +######*/ + +struct MANGOS_DLL_DECL npc_highborne_lamenterAI : public ScriptedAI +{ + npc_highborne_lamenterAI(Creature *c) : ScriptedAI(c) { Reset(); } + + uint32 EventMove_Timer; + uint32 EventCast_Timer; + bool EventMove; + bool EventCast; + + void Reset() + { + EventMove_Timer = 10000; + EventCast_Timer = 17500; + EventMove = true; + EventCast = true; + } + + void Aggro(Unit *who) {} + + void UpdateAI(const uint32 diff) + { + if( EventMove ) + { + if( EventMove_Timer < diff ) + { + m_creature->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT | MOVEMENTFLAG_LEVITATING); + m_creature->SendMonsterMoveWithSpeed(m_creature->GetPositionX(),m_creature->GetPositionY(),HIGHBORNE_LOC_Y_NEW,MOVEMENTFLAG_ONTRANSPORT,5000); + m_creature->GetMap()->CreatureRelocation(m_creature,m_creature->GetPositionX(),m_creature->GetPositionY(),HIGHBORNE_LOC_Y_NEW,m_creature->GetOrientation()); + EventMove = false; + }else EventMove_Timer -= diff; + } + if( EventCast ) + { + if( EventCast_Timer < diff ) + { + DoCast(m_creature,SPELL_HIGHBORNE_AURA); + EventCast = false; + }else EventCast_Timer -= diff; + } + } +}; +CreatureAI* GetAI_npc_highborne_lamenter(Creature *_Creature) +{ + return new npc_highborne_lamenterAI (_Creature); +} + +/*###### +## npc_parqual_fintallas +######*/ + +#define SPELL_MARK_OF_SHAME 6767 + +bool GossipHello_npc_parqual_fintallas(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if (player->GetQuestStatus(6628) == QUEST_STATUS_INCOMPLETE && !player->HasAura(SPELL_MARK_OF_SHAME,0) ) + { + player->ADD_GOSSIP_ITEM( 0, "Gul'dan", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + player->ADD_GOSSIP_ITEM( 0, "Kel'Thuzad", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + player->ADD_GOSSIP_ITEM( 0, "Ner'zhul", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + player->SEND_GOSSIP_MENU(5822, _Creature->GetGUID()); + } + else + player->SEND_GOSSIP_MENU(5821, _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_parqual_fintallas(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + if (action == GOSSIP_ACTION_INFO_DEF+1) + { + player->CLOSE_GOSSIP_MENU(); + _Creature->CastSpell(player,SPELL_MARK_OF_SHAME,false); + } + if (action == GOSSIP_ACTION_INFO_DEF+2) + { + player->CLOSE_GOSSIP_MENU(); + player->AreaExploredOrEventHappens(6628); + } + return true; +} + +/*###### +## AddSC +######*/ + +void AddSC_undercity() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npc_lady_sylvanas_windrunner"; + newscript->GetAI = GetAI_npc_lady_sylvanas_windrunner; + newscript->pChooseReward = &ChooseReward_npc_lady_sylvanas_windrunner; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_highborne_lamenter"; + newscript->GetAI = GetAI_npc_highborne_lamenter; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_parqual_fintallas"; + newscript->pGossipHello = &GossipHello_npc_parqual_fintallas; + newscript->pGossipSelect = &GossipSelect_npc_parqual_fintallas; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/wailing_caverns/instance_wailing_caverns.cpp b/src/bindings/scripts/scripts/zone/wailing_caverns/instance_wailing_caverns.cpp new file mode 100644 index 00000000000..a67db38d4ed --- /dev/null +++ b/src/bindings/scripts/scripts/zone/wailing_caverns/instance_wailing_caverns.cpp @@ -0,0 +1,24 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Wailing_Caverns +SD%Complete: 0 +SDComment: Placeholder +SDCategory: Wailing Caverns +EndScriptData */ + +#include "precompiled.h" diff --git a/src/bindings/scripts/scripts/zone/western_plaguelands/western_plaguelands.cpp b/src/bindings/scripts/scripts/zone/western_plaguelands/western_plaguelands.cpp new file mode 100644 index 00000000000..d6a20fb5cca --- /dev/null +++ b/src/bindings/scripts/scripts/zone/western_plaguelands/western_plaguelands.cpp @@ -0,0 +1,176 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Western_Plaguelands +SD%Complete: 90 +SDComment: Quest support: 5216,5219,5222,5225,5229,5231,5233,5235. To obtain Vitreous Focuser (could use more spesifics about gossip items) +SDCategory: Western Plaguelands +EndScriptData */ + +/* ContentData +npcs_dithers_and_arbington +npc_the_scourge_cauldron +EndContentData */ + +#include "precompiled.h" + +/*###### +## npcs_dithers_and_arbington +######*/ + +bool GossipHello_npcs_dithers_and_arbington(Player *player, Creature *_Creature) +{ + if(_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + if (_Creature->isVendor()) + player->ADD_GOSSIP_ITEM(1, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + + if(player->GetQuestRewardStatus(5237) || player->GetQuestRewardStatus(5238)) + { + player->ADD_GOSSIP_ITEM(0, "What does the Felstone Field Cauldron need?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + player->ADD_GOSSIP_ITEM(0, "What does the Dalson's Tears Cauldron need?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + player->ADD_GOSSIP_ITEM(0, "What does the Writhing Haunt Cauldron need?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + player->ADD_GOSSIP_ITEM(0, "What does the Gahrron's Withering Cauldron need?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + player->SEND_GOSSIP_MENU(3985, _Creature->GetGUID()); + }else + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npcs_dithers_and_arbington(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + switch(action) + { + case GOSSIP_ACTION_TRADE: + player->SEND_VENDORLIST( _Creature->GetGUID() ); + break; + case GOSSIP_ACTION_INFO_DEF+1: + player->ADD_GOSSIP_ITEM(0, "Thanks, i need a Vitreous Focuser", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + player->SEND_GOSSIP_MENU(3980, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + player->ADD_GOSSIP_ITEM(0, "Thanks, i need a Vitreous Focuser", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + player->SEND_GOSSIP_MENU(3981, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + player->ADD_GOSSIP_ITEM(0, "Thanks, i need a Vitreous Focuser", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + player->SEND_GOSSIP_MENU(3982, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + player->ADD_GOSSIP_ITEM(0, "Thanks, i need a Vitreous Focuser", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + player->SEND_GOSSIP_MENU(3983, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + player->CLOSE_GOSSIP_MENU(); + _Creature->CastSpell(player, 17529, false); + break; + } + return true; +} + +/*###### +## npc_the_scourge_cauldron +######*/ + +struct MANGOS_DLL_DECL npc_the_scourge_cauldronAI : public ScriptedAI +{ + npc_the_scourge_cauldronAI(Creature *c) : ScriptedAI(c) {Reset();} + + void Reset() {} + + void Aggro(Unit* who) {} + + void DoDie() + { + //summoner dies here + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + //override any database `spawntimesecs` to prevent duplicated summons + uint32 rTime = m_creature->GetRespawnDelay(); + if( rTime<600 ) + m_creature->SetRespawnDelay(600); + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || who->GetTypeId() != TYPEID_PLAYER) + return; + + if(who->GetTypeId() == TYPEID_PLAYER) + { + switch(m_creature->GetAreaId()) + { + case 199: //felstone + if( ((Player*)who)->GetQuestStatus(5216) == QUEST_STATUS_INCOMPLETE || + ((Player*)who)->GetQuestStatus(5229) == QUEST_STATUS_INCOMPLETE ) + { + DoSpawnCreature(11075,0,0,0,m_creature->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); + DoDie(); + } + break; + case 200: //dalson + if( ((Player*)who)->GetQuestStatus(5219) == QUEST_STATUS_INCOMPLETE || + ((Player*)who)->GetQuestStatus(5231) == QUEST_STATUS_INCOMPLETE ) + { + DoSpawnCreature(11077,0,0,0,m_creature->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); + DoDie(); + } + break; + case 201: //gahrron + if( ((Player*)who)->GetQuestStatus(5225) == QUEST_STATUS_INCOMPLETE || + ((Player*)who)->GetQuestStatus(5235) == QUEST_STATUS_INCOMPLETE ) + { + DoSpawnCreature(11078,0,0,0,m_creature->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); + DoDie(); + } + break; + case 202: //writhing + if( ((Player*)who)->GetQuestStatus(5222) == QUEST_STATUS_INCOMPLETE || + ((Player*)who)->GetQuestStatus(5233) == QUEST_STATUS_INCOMPLETE ) + { + DoSpawnCreature(11076,0,0,0,m_creature->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); + DoDie(); + } + break; + } + } + } +}; +CreatureAI* GetAI_npc_the_scourge_cauldron(Creature *_Creature) +{ + return new npc_the_scourge_cauldronAI (_Creature); +} + +/*###### +## +######*/ + +void AddSC_western_plaguelands() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npcs_dithers_and_arbington"; + newscript->pGossipHello = &GossipHello_npcs_dithers_and_arbington; + newscript->pGossipSelect = &GossipSelect_npcs_dithers_and_arbington; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_the_scourge_cauldron"; + newscript->GetAI = GetAI_npc_the_scourge_cauldron; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/winterspring/winterspring.cpp b/src/bindings/scripts/scripts/zone/winterspring/winterspring.cpp new file mode 100644 index 00000000000..fa3ef8dd027 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/winterspring/winterspring.cpp @@ -0,0 +1,157 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Winterspring +SD%Complete: 90 +SDComment: Quest support: 5126 (Loraxs' tale missing proper gossip items text). Vendor Rivern Frostwind. Obtain Cache of Mau'ari +SDCategory: Winterspring +EndScriptData */ + +/* ContentData +npc_lorax +npc_rivern_frostwind +npc_witch_doctor_mauari +EndContentData */ + +#include "precompiled.h" + +/*###### +## npc_lorax +######*/ + +bool GossipHello_npc_lorax(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if (player->GetQuestStatus(5126) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM( 0, "Talk to me", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_lorax(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF: + player->ADD_GOSSIP_ITEM( 0, "What do you do here?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->SEND_GOSSIP_MENU(3759, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+1: + player->ADD_GOSSIP_ITEM( 0, "I can help you", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->SEND_GOSSIP_MENU(3760, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + player->ADD_GOSSIP_ITEM( 0, "What deal?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->SEND_GOSSIP_MENU(3761, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + player->ADD_GOSSIP_ITEM( 0, "Then what happened?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->SEND_GOSSIP_MENU(3762, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + player->ADD_GOSSIP_ITEM( 0, "He is not safe, i'll make sure of that.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->SEND_GOSSIP_MENU(3763, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + player->CLOSE_GOSSIP_MENU(); + player->AreaExploredOrEventHappens(5126); + break; + } + return true; +} + +/*###### +## npc_rivern_frostwind +######*/ + +bool GossipHello_npc_rivern_frostwind(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if (_Creature->isVendor() && player->GetReputationRank(589) == REP_EXALTED) + player->ADD_GOSSIP_ITEM(1, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_rivern_frostwind(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + if (action == GOSSIP_ACTION_TRADE) + player->SEND_VENDORLIST( _Creature->GetGUID() ); + + return true; +} + +/*###### +## npc_witch_doctor_mauari +######*/ + +bool GossipHello_npc_witch_doctor_mauari(Player *player, Creature *_Creature) +{ + if(_Creature->isQuestGiver()) + player->PrepareQuestMenu( _Creature->GetGUID() ); + + if(player->GetQuestRewardStatus(975)) + { + player->ADD_GOSSIP_ITEM(0, "I'd like you to make me a new Cache of Mau'ari please.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + player->SEND_GOSSIP_MENU(3377, _Creature->GetGUID()); + }else + player->SEND_GOSSIP_MENU(3375, _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_witch_doctor_mauari(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + if (action==GOSSIP_ACTION_INFO_DEF+1) + { + player->CLOSE_GOSSIP_MENU(); + _Creature->CastSpell(player, 16351, false); + } + + return true; +} + +void AddSC_winterspring() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npc_lorax"; + newscript->pGossipHello = &GossipHello_npc_lorax; + newscript->pGossipSelect = &GossipSelect_npc_lorax; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_rivern_frostwind"; + newscript->pGossipHello = &GossipHello_npc_rivern_frostwind; + newscript->pGossipSelect = &GossipSelect_npc_rivern_frostwind; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_witch_doctor_mauari"; + newscript->pGossipHello = &GossipHello_npc_witch_doctor_mauari; + newscript->pGossipSelect = &GossipSelect_npc_witch_doctor_mauari; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/zangarmarsh/zangarmarsh.cpp b/src/bindings/scripts/scripts/zone/zangarmarsh/zangarmarsh.cpp new file mode 100644 index 00000000000..e5917dd25ee --- /dev/null +++ b/src/bindings/scripts/scripts/zone/zangarmarsh/zangarmarsh.cpp @@ -0,0 +1,283 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Zangarmarsh +SD%Complete: 100 +SDComment: Quest support: 9785, 9803, 10009. Mark Of ... buffs. +SDCategory: Zangarmarsh +EndScriptData */ + +/* ContentData +npcs_ashyen_and_keleth +npc_cooshcoosh +npc_elder_kuruti +npc_mortog_steamhead +EndContentData */ + +#include "precompiled.h" + +/*###### +## npcs_ashyen_and_keleth +######*/ + +#define GOSSIP_ITEM_BLESS_ASH "Grant me your mark, wise ancient." +#define GOSSIP_ITEM_BLESS_KEL "Grant me your mark, mighty ancient." +#define GOSSIP_REWARD_BLESS "You have my blessing" +//#define TEXT_BLESSINGS "" + +bool GossipHello_npcs_ashyen_and_keleth(Player *player, Creature *_Creature ) +{ + if (player->GetReputationRank(942) > REP_NEUTRAL) + { + if ( _Creature->GetEntry() == 17900) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_BLESS_ASH, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + if ( _Creature->GetEntry() == 17901) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_BLESS_KEL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + } + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npcs_ashyen_and_keleth(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + if (action == GOSSIP_ACTION_INFO_DEF+1) + { + _Creature->setPowerType(POWER_MANA); + _Creature->SetMaxPower(POWER_MANA,200); //set a "fake" mana value, we can't depend on database doing it in this case + _Creature->SetPower(POWER_MANA,200); + + if ( _Creature->GetEntry() == 17900) //check which creature we are dealing with + { + switch (player->GetReputationRank(942)) + { //mark of lore + case REP_FRIENDLY: + _Creature->CastSpell(player, 31808, true); + _Creature->Say(GOSSIP_REWARD_BLESS, LANG_UNIVERSAL, 0); + break; + case REP_HONORED: + _Creature->CastSpell(player, 31810, true); + _Creature->Say(GOSSIP_REWARD_BLESS, LANG_UNIVERSAL, 0); + break; + case REP_REVERED: + _Creature->CastSpell(player, 31811, true); + _Creature->Say(GOSSIP_REWARD_BLESS, LANG_UNIVERSAL, 0); + break; + case REP_EXALTED: + _Creature->CastSpell(player, 31815, true); + _Creature->Say(GOSSIP_REWARD_BLESS, LANG_UNIVERSAL, 0); + break; + } + } + + if ( _Creature->GetEntry() == 17901) + { + switch (player->GetReputationRank(942)) //mark of war + { + case REP_FRIENDLY: + _Creature->CastSpell(player, 31807, true); + _Creature->Say(GOSSIP_REWARD_BLESS, LANG_UNIVERSAL, 0); + break; + case REP_HONORED: + _Creature->CastSpell(player, 31812, true); + _Creature->Say(GOSSIP_REWARD_BLESS, LANG_UNIVERSAL, 0); + break; + case REP_REVERED: + _Creature->CastSpell(player, 31813, true); + _Creature->Say(GOSSIP_REWARD_BLESS, LANG_UNIVERSAL, 0); + break; + case REP_EXALTED: + _Creature->CastSpell(player, 31814, true); + _Creature->Say(GOSSIP_REWARD_BLESS, LANG_UNIVERSAL, 0); + break; + } + } + player->CLOSE_GOSSIP_MENU(); + player->TalkedToCreature(_Creature->GetEntry(), _Creature->GetGUID()); + } + return true; +} + +/*###### +## npc_cooshcoosh +######*/ + +#define GOSSIP_COOSH "You owe Sim'salabim money. Hand them over or die!" + +#define FACTION_HOSTILE_CO 45 +#define FACTION_FRIENDLY_CO 35 + +#define SPELL_LIGHTNING_BOLT 9532 + +struct MANGOS_DLL_DECL npc_cooshcooshAI : public ScriptedAI +{ + npc_cooshcooshAI(Creature* c) : ScriptedAI(c) { Reset(); } + + uint32 LightningBolt_Timer; + + void Reset() + { + LightningBolt_Timer = 2000; + m_creature->setFaction(FACTION_FRIENDLY_CO); + } + + void Aggro(Unit *who) {} + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if( LightningBolt_Timer < diff ) + { + DoCast(m_creature->getVictim(),SPELL_LIGHTNING_BOLT); + LightningBolt_Timer = 5000; + }else LightningBolt_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_npc_cooshcoosh(Creature *_Creature) +{ + return new npc_cooshcooshAI (_Creature); +} + +bool GossipHello_npc_cooshcoosh(Player *player, Creature *_Creature ) +{ + if( player->GetQuestStatus(10009) == QUEST_STATUS_INCOMPLETE ) + player->ADD_GOSSIP_ITEM(1, GOSSIP_COOSH, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + player->SEND_GOSSIP_MENU(9441, _Creature->GetGUID()); + return true; +} + +bool GossipSelect_npc_cooshcoosh(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if( action == GOSSIP_ACTION_INFO_DEF ) + { + player->CLOSE_GOSSIP_MENU(); + _Creature->setFaction(FACTION_HOSTILE_CO); + ((npc_cooshcooshAI*)_Creature->AI())->AttackStart(player); + } + return true; +} + +/*###### +## npc_elder_kuruti +######*/ + +#define GOSSIP_ITEM_KUR1 "Offer treat" +#define GOSSIP_ITEM_KUR2 "Im a messenger for Draenei" +#define GOSSIP_ITEM_KUR3 "Get message" + +bool GossipHello_npc_elder_kuruti(Player *player, Creature *_Creature ) +{ + if( player->GetQuestStatus(9803) == QUEST_STATUS_INCOMPLETE ) + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_KUR1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + player->SEND_GOSSIP_MENU(9226,_Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_elder_kuruti(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + switch (action) + { + case GOSSIP_ACTION_INFO_DEF: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_KUR2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->SEND_GOSSIP_MENU(9227, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 1: + player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_KUR3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->SEND_GOSSIP_MENU(9229, _Creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + { + if( !player->HasItemCount(24573,1) ) + { + ItemPosCountVec dest; + uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, 24573, 1, false); + if( msg == EQUIP_ERR_OK ) + { + player->StoreNewItem( dest, 24573, true); + } + else + player->SendEquipError( msg,NULL,NULL ); + } + player->SEND_GOSSIP_MENU(9231, _Creature->GetGUID()); + break; + } + } + return true; +} + +/*###### +## npc_mortog_steamhead +######*/ + +bool GossipHello_npc_mortog_steamhead(Player *player, Creature *_Creature) +{ + if (_Creature->isVendor() && player->GetReputationRank(942) == REP_EXALTED) + player->ADD_GOSSIP_ITEM(1, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_mortog_steamhead(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + if (action == GOSSIP_ACTION_TRADE) + { + player->SEND_VENDORLIST( _Creature->GetGUID() ); + } + return true; +} + +/*###### +## AddSC +######*/ + +void AddSC_zangarmarsh() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npcs_ashyen_and_keleth"; + newscript->pGossipHello = &GossipHello_npcs_ashyen_and_keleth; + newscript->pGossipSelect = &GossipSelect_npcs_ashyen_and_keleth; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_cooshcoosh"; + newscript->pGossipHello = &GossipHello_npc_cooshcoosh; + newscript->pGossipSelect = &GossipSelect_npc_cooshcoosh; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_elder_kuruti"; + newscript->pGossipHello = &GossipHello_npc_elder_kuruti; + newscript->pGossipSelect = &GossipSelect_npc_elder_kuruti; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_mortog_steamhead"; + newscript->pGossipHello = &GossipHello_npc_mortog_steamhead; + newscript->pGossipSelect = &GossipSelect_npc_mortog_steamhead; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/zulaman/boss_janalai.cpp b/src/bindings/scripts/scripts/zone/zulaman/boss_janalai.cpp new file mode 100644 index 00000000000..0f3de44cd10 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/zulaman/boss_janalai.cpp @@ -0,0 +1,777 @@ +/* Copyright (C) 2006,2007 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Janalai +SD%Complete: 100 +SDComment: +SDCategory: Zul'Aman +EndScriptData */ + +#include "precompiled.h" +#include "def_zulaman.h" + +// Jan'alai +// --Spell +#define SPELL_FLAME_BREATH 43140 +#define SPELL_FIRE_WALL 43113 +#define SPELL_ENRAGE 44779 +#define SPELL_TELETOCENTER 43098 +#define SPELL_SUMMONALL 43097 +#define SPELL_BERSERK 47008 +// -- Fire Bob Spells +#define MOB_FIRE_BOMB 23920 +#define SPELL_FIRE_BOMB_CHANNEL 42621 +#define SPELL_FIRE_BOMB_THROW 42628 +#define SPELL_FIRE_BOMB_DUMMY 42629 +#define SPELL_FIRE_BOMB_DAMAGE 42630 + +// -- SAYs +#define SOUND_AGGRO 12031 +#define SAY_AGGRO "Spirits of da wind be your doom!" +#define SOUND_FIRE_BOMBS 12032 +#define SAY_FIRE_BOMBS "I burn ya now!" +#define SOUND_SUMMON_HATCHER 12033 +#define SAY_SUMMON_HATCHER "Where ma hatcha? Get to work on dem eggs!" +#define SOUND_ALL_EGGS 12034 +#define SAY_ALL_EGGS "I show you strength... in numbers." +#define SOUND_BERSERK 12035 +#define SAY_BERSERK "You done run outta time!" + +#define SOUND_SLAY_1 12036 +#define SAY_SLAY_1 "It all be over now, mon!" +#define SOUND_SLAY_2 12037 +#define SAY_SLAY_2 "Tazaga-choo!" + +#define SOUND_DEATH 12038 +#define SAY_DEATH "Zul'jin... got a surprise for you..." + +#define SOUND_AGGRO_1 12039 //NOT USED need more information + //NOT USED need more information (random say before aggro?) +#define SAY_AGGRO_1 "Come, strangers. The spirit of the dragonhawk hot be hungry for worthy souls." +#define SOUND_AGGRO_2 12040 //NOT USED need more information + //NOT USED need more information (random say before aggro?) +#define SAY_AGGRO_2 "Come, friends. Your bodies gonna feed ma hatchlings, and your souls are going to feed me with power!" + +// --Summons +#define MOB_AMANI_HATCHER 23818 +#define MOB_HATCHLING 23598 + +// -- Hatcher Spells +#define SPELL_HATCH_EGG 43734 + +// -- Hatchling Spells +#define SPELL_FLAMEBUFFED 43299 + +const int area_dx = 44; +const int area_dy = 51; + +float JanalainPos[1][3] = +{ + {-33.93, 1149.27, 19} +}; + +float FireWallCoords[4][4] = +{ + {-10.13, 1149.27, 19, 3.1415}, + {-33.93, 1123.90, 19, 0.5*3.1415}, + {-54.80, 1150.08, 19, 0}, + {-33.93, 1175.68, 19, 1.5*3.1415} +}; + +float hatcherway_l[5][3] = +{ + {-87.46,1170.09,6}, + {-74.41,1154.75,6}, + {-52.74,1153.32,19}, + {-33.37,1172.46,19}, + {-33.09,1203.87,19} +}; + +float hatcherway_r[5][3] = +{ + {-86.57,1132.85,6}, + {-73.94,1146.00,6}, + {-52.29,1146.51,19}, + {-33.57,1125.72,19}, + {-34.29,1095.22,19} +}; + +struct MANGOS_DLL_DECL boss_janalaiAI : public ScriptedAI +{ + boss_janalaiAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance *pInstance; + + uint32 fire_breath_timer; + uint32 bomb_timer; + uint32 throw_timer; + uint32 enrage_timer; + uint32 finishedbomb_timer; + uint32 bombcounter; + uint32 hatchertime; + uint32 eggs; + uint32 wipetimer; + uint32 reset_timer; + bool noeggs; + bool enraged; + bool enragetime; + + uint64 FireBombGUIDs[40]; + uint64 ThrowControllerGUID; + + bool bombing; + + void Reset() + { + if(pInstance) + pInstance->SetData(DATA_JANALAIEVENT, NOT_STARTED); + + fire_breath_timer = 8000; + bomb_timer = 30000; + enrage_timer = 300000; // 5 minutes + finishedbomb_timer = 6000; + throw_timer = 1000; + bombcounter = 0; + noeggs = false; + hatchertime = 10000; + wipetimer = 600000; // 10 mins + bombing =false; + reset_timer = 5000; + enraged = false; + enragetime = false; + + ThrowControllerGUID = 0; + + for(uint8 i = 0; i < 40; i++) + FireBombGUIDs[i] = 0; + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_DEATH); + + if(pInstance) + pInstance->SetData(DATA_JANALAIEVENT, DONE); + } + + void KilledUnit(Unit* victim) + { + switch(rand()%2) + { + case 0: + DoYell(SAY_SLAY_1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY_1); + break; + case 1: + DoYell(SAY_SLAY_2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_SLAY_1); + break; + } + } + + void Aggro(Unit *who) + { + if(pInstance) + pInstance->SetData(DATA_JANALAIEVENT, IN_PROGRESS); + + DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO); + } + + void FireWall() // Create Firewall + { + Creature* wall = NULL; + wall = m_creature->SummonCreature(MOB_FIRE_BOMB,FireWallCoords[0][0],FireWallCoords[0][1],FireWallCoords[0][2],FireWallCoords[0][3],TEMPSUMMON_TIMED_DESPAWN,11500); + if(wall) + wall->CastSpell(wall,SPELL_FIRE_WALL,false); + + wall = m_creature->SummonCreature(MOB_FIRE_BOMB,FireWallCoords[0][0],FireWallCoords[0][1]+5,FireWallCoords[0][2],FireWallCoords[0][3],TEMPSUMMON_TIMED_DESPAWN,11500); + if(wall) + wall->CastSpell(wall,SPELL_FIRE_WALL,false); + + wall = m_creature->SummonCreature(MOB_FIRE_BOMB,FireWallCoords[0][0],FireWallCoords[0][1]-5,FireWallCoords[0][2],FireWallCoords[0][3],TEMPSUMMON_TIMED_DESPAWN,11500); + if(wall) + wall->CastSpell(wall,SPELL_FIRE_WALL,false); + + wall = m_creature->SummonCreature(MOB_FIRE_BOMB,FireWallCoords[1][0]-2,FireWallCoords[1][1]-2,FireWallCoords[1][2],FireWallCoords[1][3],TEMPSUMMON_TIMED_DESPAWN,11500); + if(wall) + wall->CastSpell(wall,SPELL_FIRE_WALL,false); + + wall = m_creature->SummonCreature(MOB_FIRE_BOMB,FireWallCoords[1][0]+2,FireWallCoords[1][1]+2,FireWallCoords[1][2],FireWallCoords[1][3],TEMPSUMMON_TIMED_DESPAWN,11500); + if(wall) + wall->CastSpell(wall,SPELL_FIRE_WALL,false); + + wall = m_creature->SummonCreature(MOB_FIRE_BOMB,FireWallCoords[2][0],FireWallCoords[2][1],FireWallCoords[2][2],FireWallCoords[2][3],TEMPSUMMON_TIMED_DESPAWN,11500); + if(wall) + wall->CastSpell(wall,SPELL_FIRE_WALL,false); + + wall = m_creature->SummonCreature(MOB_FIRE_BOMB,FireWallCoords[2][0],FireWallCoords[2][1]-5,FireWallCoords[2][2],FireWallCoords[2][3],TEMPSUMMON_TIMED_DESPAWN,11500); + if(wall) + wall->CastSpell(wall,SPELL_FIRE_WALL,false); + + wall = m_creature->SummonCreature(MOB_FIRE_BOMB,FireWallCoords[2][0],FireWallCoords[2][1]+5,FireWallCoords[2][2],FireWallCoords[2][3],TEMPSUMMON_TIMED_DESPAWN,11500); + if(wall) + wall->CastSpell(wall,SPELL_FIRE_WALL,false); + + wall = m_creature->SummonCreature(MOB_FIRE_BOMB,FireWallCoords[3][0]-2,FireWallCoords[3][1],FireWallCoords[3][2],FireWallCoords[3][3],TEMPSUMMON_TIMED_DESPAWN,11500); + if(wall) + wall->CastSpell(wall,SPELL_FIRE_WALL,false); + + wall = m_creature->SummonCreature(MOB_FIRE_BOMB,FireWallCoords[3][0]+2,FireWallCoords[3][1],FireWallCoords[3][2],FireWallCoords[3][3],TEMPSUMMON_TIMED_DESPAWN,11500); + if(wall) + wall->CastSpell(wall,SPELL_FIRE_WALL,false); + } + + void throwBombs() // create Bombs + { + float dx; + float dy; + for ( int i(0); i < 40; i++) + { + dx = (rand()%(area_dx))-(area_dx/2); + dy = (rand()%(area_dy))-(area_dy/2); + + Creature* bomb = DoSpawnCreature(MOB_FIRE_BOMB, dx, dy, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 13000); + if(bomb) + FireBombGUIDs[i] = bomb->GetGUID(); + } + + Creature* ThrowController = DoSpawnCreature(MOB_FIRE_BOMB,0,0,1,0,TEMPSUMMON_TIMED_DESPAWN,10000); + if(ThrowController) + ThrowControllerGUID = ThrowController->GetGUID(); + + bombcounter = 0; + } + + void throw5Bombs() //throwanimation + { + for ( int i(0); i < 5; i++) + { + Unit* ThrowController = NULL; + Unit* FireBomb = NULL; + if(ThrowControllerGUID) + ThrowController = Unit::GetUnit((*m_creature), ThrowControllerGUID); + + if(FireBombGUIDs[bombcounter]) + FireBomb = Unit::GetUnit((*m_creature), FireBombGUIDs[bombcounter]); + + if(ThrowController && FireBomb) + { + ThrowController->CastSpell(FireBomb,SPELL_FIRE_BOMB_THROW,true); + FireBomb->CastSpell(FireBomb,SPELL_FIRE_BOMB_DUMMY,false); + bombcounter ++; + } + } + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if(!bombing) // every Spell if NOT Bombing + { + //FIRE BREATH several videos says every 8Secounds + if(fire_breath_timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if(target) + DoCast(target,SPELL_FLAME_BREATH); + fire_breath_timer = 8000; + }else fire_breath_timer -=diff; + + if(bomb_timer < diff) + { + FireWall(); + bomb_timer = 20000+rand()%20000; + m_creature->Relocate(JanalainPos[0][0],JanalainPos[0][1],JanalainPos[0][2],0); + m_creature->SendMonsterMove(JanalainPos[0][0], JanalainPos[0][1],JanalainPos[0][2],0,0,100); + DoYell(SAY_FIRE_BOMBS, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_FIRE_BOMBS); + throwBombs(); + bombing = true; + + //Teleport every Player into the middle + Unit* Temp = NULL; + std::list::iterator i = m_creature->getThreatManager().getThreatList().begin(); + for (; i != m_creature->getThreatManager().getThreatList().end(); ++i) + { + Temp = Unit::GetUnit((*m_creature),(*i)->getUnitGuid()); + if (Temp && m_creature->GetDistance(Temp) > 30.0) + DoTeleportPlayer(Temp, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 0); + } + DoCast(m_creature,SPELL_TELETOCENTER,true); // only Effect Spell + DoCast(m_creature,SPELL_FIRE_BOMB_CHANNEL,false); + finishedbomb_timer = 11000; + }else bomb_timer -=diff; + + //enrage if under 25% hp before 5 min. + if (((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 25) && !enraged) + { + enragetime = true; + enrage_timer = 600000; + } + + //Enrage but only if not bombing + if(enragetime && !enraged) + { + DoYell(SAY_BERSERK, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_BERSERK); + m_creature->InterruptNonMeleeSpells(false); + DoCast(m_creature,SPELL_ENRAGE); + enraged = true; + } + } + + //Enrage after 5 minutes + if(enrage_timer < diff) + { + enragetime = true; + enrage_timer = 600000; + }else enrage_timer -=diff; + + if(bombing) // every Spell if Bombing + { + if(bombcounter < 40) + { + if(throw_timer < diff) + { + throw5Bombs(); + throw_timer = 1000; + }else throw_timer -=diff; + } + + if(finishedbomb_timer < diff) + { + bombing = false; + finishedbomb_timer = 6000; + m_creature->RemoveAura(SPELL_FIRE_BOMB_CHANNEL,0); + m_creature->RemoveAura(SPELL_FIRE_BOMB_CHANNEL,1); + }else finishedbomb_timer -=diff; + } + + //Call Hatcher + if(!noeggs) + { + if(hatchertime < diff) + { + if(pInstance->GetData(DATA_J_EGGSLEFT)>0 || pInstance->GetData(DATA_J_EGGSRIGHT) > 0) + { + Unit* hatcher = NULL; + DoYell(SAY_SUMMON_HATCHER, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_SUMMON_HATCHER); + hatcher = m_creature->SummonCreature(MOB_AMANI_HATCHER,hatcherway_l[0][0],hatcherway_l[0][1],hatcherway_l[0][2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,10000); + if(hatcher) + hatcher->GetMotionMaster()->MovePoint(0, hatcherway_l[0][0], hatcherway_l[0][1], hatcherway_l[0][2]); + + hatcher = m_creature->SummonCreature(MOB_AMANI_HATCHER,hatcherway_r[0][0],hatcherway_r[0][1],hatcherway_r[0][2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,10000); + if(hatcher) + hatcher->GetMotionMaster()->MovePoint(0, hatcherway_r[0][0],hatcherway_r[0][1],hatcherway_r[0][2]); + hatchertime = 45000; + } + else + { + noeggs = true; + } + }else hatchertime -=diff; + } + + //WIPE after 10 minutes + if(wipetimer < diff) + { + DoYell(SAY_BERSERK, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_BERSERK); + DoCast(m_creature,SPELL_ENRAGE); + + wipetimer = 30000; + }else wipetimer -=diff; + + //Hatch All + if(!noeggs && (m_creature->GetHealth()*100) / m_creature->GetMaxHealth() < 35) + { + DoYell(SAY_ALL_EGGS , LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature,SOUND_BERSERK); + + if(pInstance) + eggs = pInstance->GetData(DATA_J_EGGSLEFT); + + int i; + for(i=1;i<=eggs;i=i+1) + { + int r = (rand()%20 - 10); + int s = (rand()%20 - 10); + m_creature->SummonCreature(MOB_HATCHLING,JanalainPos[0][0]+s,JanalainPos[0][1]+r,JanalainPos[0][2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,15000); + + if(pInstance) + pInstance->SetData(DATA_J_HATCHLEFT,1); + } + + if(pInstance) + eggs = pInstance->GetData(DATA_J_EGGSRIGHT); + + for(i=1;i<=eggs;i=i+1) + { + int r = (rand()%20 - 10); + int s = (rand()%20 - 10); + m_creature->SummonCreature(MOB_HATCHLING,JanalainPos[0][0]+s,JanalainPos[0][1]+r,JanalainPos[0][2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,15000); + if(pInstance) + pInstance->SetData(DATA_J_HATCHRIGHT,1); + } + + noeggs = true; + } + + //check for reset ... exploit preventing ... pulled from his podest + if(reset_timer < diff) + { + if(m_creature->GetPositionX() < -70 || m_creature->GetPositionX() > 0) + { + EnterEvadeMode(); + reset_timer = 5000; //every 5 Seca + } + }else reset_timer -=diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_janalaiAI(Creature *_Creature) +{ + return new boss_janalaiAI (_Creature); +} + +struct MANGOS_DLL_DECL mob_jandalai_firebombAI : public ScriptedAI +{ + mob_jandalai_firebombAI(Creature *c) : ScriptedAI(c){Reset();} + + uint32 bomb_timer; + + void Reset() + { + bomb_timer = 12000; + } + + void Aggro(Unit* who) {} + + void AttackStart(Unit* who) {} + + void MoveInLineOfSight(Unit* who) {} + + void UpdateAI(const uint32 diff) + { + if(bomb_timer < diff) //Boom + { + m_creature->CastSpell(m_creature,SPELL_FIRE_BOMB_DAMAGE,false); + bomb_timer = 1800000; + }else bomb_timer -=diff; + } +}; + +CreatureAI* GetAI_mob_jandalai_firebombAI(Creature *_Creature) +{ + return new mob_jandalai_firebombAI (_Creature); +} + +struct MANGOS_DLL_DECL mob_amanishi_hatcherAI : public ScriptedAI +{ + mob_amanishi_hatcherAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance *pInstance; + + uint32 waypoint; + bool waytype; + bool start; + bool hatch; + bool wait; + uint32 hatchlings; + uint32 waittimer; + uint32 eggs; + uint32 delete_timer; + + void Reset() + { + waypoint = 0; + waytype = 0; + hatch = false; + start = false; + wait = false; + waittimer = 4000; + hatchlings = 0; + eggs = 0; + delete_timer = 10000; + + //m_creature->RemoveAllAuras(); + //m_creature->DeleteThreatList(); + //m_creature->CombatStop(); + //DoGoHome(); + } + + void Aggro(Unit* who) + { + } + + void UpdateAI(const uint32 diff) + { + if(pInstance && (pInstance->GetData(DATA_JANALAIEVENT) == 1)) + { + if(!start && !hatch) + { + waytype = ( m_creature->GetPositionY() > 1150); + waypoint = 1; + start = true; + } + + if(start && !hatch) + { + if(wait) + { + if(waittimer < diff) + { + wait = false; + waittimer = 4000; + waypoint++; + + if (waypoint == 5) + { + hatch = true; + waittimer = 0; + hatchlings = 1; + } + } + else + { + waittimer -=diff; + } + } + else + { + m_creature->GetMotionMaster()->Clear(); + if(waytype) + m_creature->GetMotionMaster()->MovePoint(0,hatcherway_l[waypoint][0],hatcherway_l[waypoint][1],hatcherway_l[waypoint][2]); + else + m_creature->GetMotionMaster()->MovePoint(0,hatcherway_r[waypoint][0],hatcherway_r[waypoint][1],hatcherway_r[waypoint][2]); + wait= true; + } + } + + if(start && hatch) + { + if(waittimer < diff) + { + if(!pInstance) + return; + + waittimer = 4000; + Unit* hatchling; + + if(waytype) + { + eggs = pInstance->GetData(DATA_J_EGGSLEFT); + + if(eggs > 0) + DoCast(m_creature,SPELL_HATCH_EGG); + + int i; + for(i=1;i<=hatchlings;i=i+1) + { + eggs = pInstance->GetData(DATA_J_EGGSLEFT); + if(eggs <= 0) + { + if (waytype) waytype = false; else waytype = true; + waittimer = 15000; + hatch = false; + waypoint = 4; + wait = true; + i = hatchlings; + } + else + { + hatchling = DoSpawnCreature(MOB_HATCHLING,rand()%4-2,rand()%4-2,0,0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,15000); + pInstance->SetData(DATA_J_HATCHLEFT,1); + } + } + + DoCast(m_creature,SPELL_HATCH_EGG); + + if(hatchlings < 5) + hatchlings++; + } + else + { + eggs = pInstance->GetData(DATA_J_EGGSRIGHT); + + if(eggs > 0) + DoCast(m_creature,SPELL_HATCH_EGG); + + int i; + for(i=1;i<=hatchlings;i=i+1) + { + eggs = pInstance->GetData(DATA_J_EGGSRIGHT); + if(eggs <= 0) + { + if (waytype) waytype = false; else waytype = true; + waittimer = 15000; + hatch = false; + waypoint = 4; + wait = true; + i = hatchlings; + } + else + { + hatchling = DoSpawnCreature(MOB_HATCHLING,rand()%4-2,rand()%4-2,0,0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,15000); + pInstance->SetData(DATA_J_HATCHRIGHT,1); + } + } + + DoCast(m_creature,SPELL_HATCH_EGG); + hatchlings++; + } + }else waittimer -=diff; + } + } + else + { + if(delete_timer < diff) + { + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + delete_timer = 10000; + }else delete_timer -=diff; + } + } +}; + +CreatureAI* GetAI_mob_amanishi_hatcherAI(Creature *_Creature) +{ + return new mob_amanishi_hatcherAI (_Creature); +} + +struct MANGOS_DLL_DECL mob_hatchlingAI : public ScriptedAI +{ + mob_hatchlingAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance *pInstance; + + uint32 buffer_timer; + uint32 delete_timer; + bool start; + + void Reset() + { + buffer_timer = 7000; + delete_timer = 10000; + start = false; + } + + void Aggro(Unit *who) + { + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || m_creature->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + float attackRadius = m_creature->GetAttackDistance(who); + if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) + { + if(who->HasStealthAura()) + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + DoStartAttackAndMovement(who); + } + } + } + + void UpdateAI(const uint32 diff) + { + if(!start) + { + if(m_creature->GetPositionY() > 1150) + m_creature->GetMotionMaster()->MovePoint(0, hatcherway_l[3][0]+rand()%4-2,hatcherway_l[3][1]+rand()%4-2,hatcherway_l[3][2]); + else + m_creature->GetMotionMaster()->MovePoint(0,hatcherway_r[3][0]+rand()%4-2,hatcherway_r[3][1]+rand()%4-2,hatcherway_r[3][2]); + start = true; + } + + if(delete_timer < diff && (pInstance && !(pInstance->GetData(DATA_JANALAIEVENT) == 1))) + { + if(!(m_creature->getVictim())) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + delete_timer = 10000; + }else delete_timer -=diff; + + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + if (buffer_timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if(target) + DoCast(target,SPELL_FLAMEBUFFED); + + buffer_timer = 7000; + }else buffer_timer -=diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_hatchlingAI(Creature *_Creature) +{ + return new mob_hatchlingAI (_Creature); +} + +void AddSC_boss_janalai() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_janalai"; + newscript->GetAI = GetAI_boss_janalaiAI; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_jandalai_firebomb"; + newscript->GetAI = GetAI_mob_jandalai_firebombAI; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_amanishi_hatcher"; + newscript->GetAI = GetAI_mob_amanishi_hatcherAI; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_hatchling"; + newscript->GetAI = GetAI_mob_hatchlingAI; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/zulaman/boss_nalorakk.cpp b/src/bindings/scripts/scripts/zone/zulaman/boss_nalorakk.cpp new file mode 100644 index 00000000000..01dae191217 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/zulaman/boss_nalorakk.cpp @@ -0,0 +1,272 @@ +/* Copyright (C) 2006,2007 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Nalorakk +SD%Complete: 80 +SDComment: Todo: Trash Waves +SDCategory: Zul'Aman +EndScriptData */ + +#include "precompiled.h" + +//TODO: Trash Waves + +//Unimplemented SoundIDs +/* +#define SOUND_NALORAKK_WAVE1 12066 +#define SOUND_NALORAKK_WAVE2 12067 +#define SOUND_NALORAKK_WAVE3 12068 +#define SOUND_NALORAKK_WAVE4 12069 + +#define SOUND_NALORAKK_EVENT1 12078 +#define SOUND_NALORAKK_EVENT2 12079 +*/ + +//General defines +#define YELL_AGGRO "You be dead soon enough!" +#define SOUND_YELL_AGGRO 12070 +#define YELL_KILL_ONE "Mua-ha-ha! Now whatchoo got to say?" +#define SOUND_YELL_KILL_ONE 12075 +#define YELL_KILL_TWO "Da Amani gonna rule again!" +#define SOUND_YELL_KILL_TWO 12076 +#define YELL_DEATH "I... be waitin' on da udda side...." +#define SOUND_YELL_DEATH 12077 + //Never seen this being used, so just guessing from what I hear. +#define YELL_BERSERK "You had your chance, now it be too late!" +#define SOUND_YELL_BERSERK 12074 + +#define SPELL_BERSERK 45078 //unsure, this increases damage, size and speed + +//Defines for Troll form +#define SPELL_BRUTALSWIPE 42384 +//#define SPELL_MANGLE 42389 This doesn't seem to apply the mangle debuff after all +#define SPELL_MANGLEEFFECT 44955 +#define SPELL_SURGE 42402 +#define SPELL_BEARFORM 42377 + +#define YELL_SURGE "I bring da pain!" +#define SOUND_YELL_SURGE 12071 + +#define YELL_SHIFTEDTOTROLL "Make way for Nalorakk!" +#define SOUND_YELL_TOTROLL 12073 + +//Defines for Bear form +#define SPELL_LACERATINGSLASH 42395 +#define SPELL_RENDFLESH 42397 +#define SPELL_DEAFENINGROAR 42398 + +#define YELL_SHIFTEDTOBEAR "You call on da beast, you gonna get more dan you bargain for!" +#define SOUND_YELL_TOBEAR 12072 + +struct MANGOS_DLL_DECL boss_nalorakkAI : public ScriptedAI +{ + boss_nalorakkAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 ChangeForm_Timer; + uint32 BrutalSwipe_Timer; + uint32 Mangle_Timer; + uint32 Surge_Timer; + uint32 LaceratingSlash_Timer; + uint32 RendFlesh_Timer; + uint32 DeafeningRoar_Timer; + uint32 ShapeShiftCheck_Timer; + uint32 Berserk_Timer; + bool inBearForm; + bool Berserking; + bool ChangedToBear; + bool ChangedToTroll; + + void Reset() + { + ChangeForm_Timer = 45000; + BrutalSwipe_Timer = 12000; + Mangle_Timer = 15000; + Surge_Timer = 20000; + LaceratingSlash_Timer = 6000; + RendFlesh_Timer = 6000; + DeafeningRoar_Timer = 20000; + ShapeShiftCheck_Timer = 40000; + Berserk_Timer = 600000; + inBearForm = false; + Berserking = false; + ChangedToBear = false; + ChangedToTroll = true; + } + + void Aggro(Unit *who) + { + DoYell(YELL_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_YELL_AGGRO); + } + + void KilledUnit(Unit* victim) + { + switch(rand()%2) + { + case 0: + DoYell(YELL_KILL_ONE, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_YELL_KILL_ONE); + break; + case 1: + DoYell(YELL_KILL_TWO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_YELL_KILL_TWO); + break; + } + } + + void JustDied(Unit* Killer) + { + DoYell(YELL_DEATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature, SOUND_YELL_DEATH); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //Berserking + if ((Berserk_Timer < diff) && (!Berserking)) + { + DoCast(m_creature, SPELL_BERSERK); + DoYell(YELL_BERSERK, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_YELL_BERSERK); + Berserking = true; + }else Berserk_Timer -= diff; + + //Don't check if we're shapeshifted every UpdateAI + if (ShapeShiftCheck_Timer < diff) + { + //This will return true if we have bearform aura + inBearForm = m_creature->HasAura(SPELL_BEARFORM, 0); + ShapeShiftCheck_Timer = 1000; + }else ShapeShiftCheck_Timer -= diff; + + //Spells for Troll Form (only to be casted if we NOT have bear phase aura) + if (!inBearForm) + { + //We just changed to troll form! + if (!ChangedToTroll) + { + DoYell(YELL_SHIFTEDTOTROLL, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_YELL_TOTROLL); + ChangedToTroll = true; + ChangedToBear = false; + //Reset spell timers + LaceratingSlash_Timer = 6000 + rand()%19000; + RendFlesh_Timer = 6000 + rand()%19000; + DeafeningRoar_Timer = 15000 + rand()%10000; + ShapeShiftCheck_Timer = 40000; + } + + //Brutal Swipe (some sources may say otherwise, but I've never seen this in Bear form) + if (BrutalSwipe_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_BRUTALSWIPE); + BrutalSwipe_Timer = 7000 + rand()%13000; + }else BrutalSwipe_Timer -= diff; + + //Mangle + if (Mangle_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_MANGLEEFFECT); + Mangle_Timer = 3000 + rand()%17000; + }else Mangle_Timer -= diff; + + //Surge + if (Surge_Timer < diff) + { + //select a random unit other than the main tank + Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 1); + + //if there aren't other units, cast on the tank + if(!target) + target = m_creature->getVictim(); + + DoCast(target, SPELL_SURGE); + + DoYell(YELL_SURGE, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_YELL_SURGE); + + Surge_Timer = 15000 + rand()%17500; + }else Surge_Timer -= diff; + + //Change to Bear Form if we're in Troll Form for 45sec + if (ChangeForm_Timer < diff) + { + DoCast(m_creature, SPELL_BEARFORM); + //And 30sec (bear form) + 45sec (troll form) before we should cast this again + ChangeForm_Timer = 75000; + }else ChangeForm_Timer -= diff; + } + //Spells for Bear Form (only to be casted if we have bear phase aura) + else + { + //We just changed to bear form! + if (!ChangedToBear) + { + DoYell(YELL_SHIFTEDTOBEAR, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_YELL_TOBEAR); + ChangedToBear = true; + ChangedToTroll = false; + //Reset spell timers + Surge_Timer = 15000 + rand()%17500; + BrutalSwipe_Timer = 7000 + rand()%13000; + Mangle_Timer = 3000 + rand()%17000; + ShapeShiftCheck_Timer = 25000; + } + + //Lacerating Slash + if (LaceratingSlash_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_LACERATINGSLASH); + LaceratingSlash_Timer = 6000 + rand()%19000; + }else LaceratingSlash_Timer -= diff; + + //Rend Flesh + if (RendFlesh_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_RENDFLESH); + RendFlesh_Timer = 6000 + rand()%19000; + }else RendFlesh_Timer -= diff; + + //Deafening Roar + if (DeafeningRoar_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_DEAFENINGROAR); + DeafeningRoar_Timer = 15000 + rand()%10000; + }else DeafeningRoar_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_nalorakk(Creature *_Creature) +{ + return new boss_nalorakkAI (_Creature); +} + +void AddSC_boss_nalorakk() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_nalorakk"; + newscript->GetAI = GetAI_boss_nalorakk; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/zulaman/def_zulaman.h b/src/bindings/scripts/scripts/zone/zulaman/def_zulaman.h new file mode 100644 index 00000000000..7a57eba2f51 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/zulaman/def_zulaman.h @@ -0,0 +1,17 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_ZULAMAN_H +#define DEF_ZULAMAN_H + +#define DATA_JANALAI 1 +#define DATA_JANALAIEVENT 2 +#define DATA_J_EGGSLEFT 3 +#define DATA_J_EGGSRIGHT 4 +#define DATA_J_HATCHLEFT 5 +#define DATA_J_HATCHRIGHT 6 + +#define TYPE_RAND_VENDOR_1 7 +#define TYPE_RAND_VENDOR_2 8 +#endif diff --git a/src/bindings/scripts/scripts/zone/zulaman/instance_zulaman.cpp b/src/bindings/scripts/scripts/zone/zulaman/instance_zulaman.cpp new file mode 100644 index 00000000000..7283a27d3a8 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/zulaman/instance_zulaman.cpp @@ -0,0 +1,137 @@ +/* Copyright (C) 2006,2007 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Zulaman +SD%Complete: 80 +SDComment: +SDCategory: Zul'Aman +EndScriptData */ + +#include "precompiled.h" +#include "def_zulaman.h" + +#define ENCOUNTERS 1 +#define RAND_VENDOR 2 + +struct MANGOS_DLL_DECL instance_zulaman : public ScriptedInstance +{ + instance_zulaman(Map *Map) : ScriptedInstance(Map) {Initialize();}; + + uint64 janalai; + uint32 janalai_eggs_l; + uint32 janalai_eggs_r; + + uint32 Encounters[ENCOUNTERS]; + uint32 RandVendor[RAND_VENDOR]; + + void Initialize() + { + janalai = 0; + janalai_eggs_l = 20; + janalai_eggs_r = 20; + + for(uint8 i = 0; i < ENCOUNTERS; i++) + Encounters[i] = NOT_STARTED; + for(uint8 i = 0; i < RAND_VENDOR; i++) + RandVendor[i] = NOT_STARTED; + } + + bool IsEncounterInProgress() const + { + for(uint8 i = 0; i < ENCOUNTERS; i++) + if(Encounters[i] == IN_PROGRESS) return true; + + return false; + } + + void OnCreatureCreate(Creature *creature, uint32 creature_entry) + { + switch(creature_entry) + { + case 23578: + janalai = creature->GetGUID(); + break; + } + } + + uint64 GetData64(uint32 identifier) + { + if(identifier == DATA_JANALAI && janalai) + return janalai; + + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_JANALAIEVENT: + if(data == 0) + { + janalai_eggs_l = 20; + janalai_eggs_r = 20; + } + Encounters[0] = data; + break; + case DATA_J_HATCHLEFT: + janalai_eggs_l -= data; + break; + case DATA_J_HATCHRIGHT: + janalai_eggs_r -= data; + break; + case TYPE_RAND_VENDOR_1: + RandVendor[0] = data; + break; + case TYPE_RAND_VENDOR_2: + RandVendor[1] = data; + break; + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_JANALAIEVENT: + return Encounters[0]; + case DATA_J_EGGSLEFT: + return janalai_eggs_l; + case DATA_J_EGGSRIGHT: + return janalai_eggs_r; + case TYPE_RAND_VENDOR_1: + return RandVendor[0]; + case TYPE_RAND_VENDOR_2: + return RandVendor[1]; + } + return 0; + } +}; + +InstanceData* GetInstanceData_instance_zulaman(Map* map) +{ + return new instance_zulaman(map); +} + +void AddSC_instance_zulaman() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_zulaman"; + newscript->GetInstanceData = GetInstanceData_instance_zulaman; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/zulaman/zulaman.cpp b/src/bindings/scripts/scripts/zone/zulaman/zulaman.cpp new file mode 100644 index 00000000000..965fc6cb11b --- /dev/null +++ b/src/bindings/scripts/scripts/zone/zulaman/zulaman.cpp @@ -0,0 +1,108 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Zulaman +SD%Complete: 90 +SDComment: Forest Frog will turn into different NPC's. Workaround to prevent new entry from running this script +SDCategory: Zul'Aman +EndScriptData */ + +/* ContentData +npc_forest_frog +EndContentData */ + +#include "precompiled.h" +#include "def_zulaman.h" + +/*###### +## npc_forest_frog +######*/ + +#define SPELL_REMOVE_AMANI_CURSE 43732 +#define SPELL_PUSH_MOJO 43923 +#define ENTRY_FOREST_FROG 24396 + +struct MANGOS_DLL_DECL npc_forest_frogAI : public ScriptedAI +{ + npc_forest_frogAI(Creature* c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance *pInstance; + + void Reset() { } + + void Aggro(Unit *who) { } + + void DoSpawnRandom() + { + if( pInstance ) + { + uint32 cEntry = 0; + switch(rand()%11) + { + case 0: cEntry = 24024; break; //Kraz + case 1: cEntry = 24397; break; //Mannuth + case 2: cEntry = 24403; break; //Deez + case 3: cEntry = 24404; break; //Galathryn + case 4: cEntry = 24405; break; //Adarrah + case 5: cEntry = 24406; break; //Fudgerick + case 6: cEntry = 24407; break; //Darwen + case 7: cEntry = 24445; break; //Mitzi + case 8: cEntry = 24448; break; //Christian + case 9: cEntry = 24453; break; //Brennan + case 10: cEntry = 24455; break; //Hollee + } + + if( !pInstance->GetData(TYPE_RAND_VENDOR_1) ) + if(rand()%10 == 1) cEntry = 24408; //Gunter + if( !pInstance->GetData(TYPE_RAND_VENDOR_2) ) + if(rand()%10 == 1) cEntry = 24409; //Kyren + + if( cEntry ) m_creature->UpdateEntry(cEntry); + + if( cEntry == 24408) pInstance->SetData(TYPE_RAND_VENDOR_1,DONE); + if( cEntry == 24409) pInstance->SetData(TYPE_RAND_VENDOR_2,DONE); + } + } + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if( spell->Id == SPELL_REMOVE_AMANI_CURSE && caster->GetTypeId() == TYPEID_PLAYER && m_creature->GetEntry() == ENTRY_FOREST_FROG ) + { + //increase or decrease chance of mojo? + if( rand()%99 == 50 ) DoCast(caster,SPELL_PUSH_MOJO,true); + else DoSpawnRandom(); + } + } +}; +CreatureAI* GetAI_npc_forest_frog(Creature *_Creature) +{ + return new npc_forest_frogAI (_Creature); +} + +void AddSC_zulaman() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npc_forest_frog"; + newscript->GetAI = GetAI_npc_forest_frog; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/zulfarrak/zulfarrak.cpp b/src/bindings/scripts/scripts/zone/zulfarrak/zulfarrak.cpp new file mode 100644 index 00000000000..c526a83ad7e --- /dev/null +++ b/src/bindings/scripts/scripts/zone/zulfarrak/zulfarrak.cpp @@ -0,0 +1,224 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Zulfarrak +SD%Complete: 50 +SDComment: Consider it temporary, no instance script made for this instance yet. +SDCategory: Zul'Farrak +EndScriptData */ + +/* ContentData +npc_sergeant_bly +npc_weegli_blastfuse +EndContentData */ + +#include "precompiled.h" + +/*###### +## npc_sergeant_bly +######*/ + +#define FACTION_HOSTILE 14 +#define FACTION_FRIENDLY 35 + +#define SPELL_SHIELD_BASH 11972 +#define SPELL_REVENGE 12170 + +#define GOSSIP_BLY "[PH] In that case, i will take my reward!" + +struct MANGOS_DLL_DECL npc_sergeant_blyAI : public ScriptedAI +{ + npc_sergeant_blyAI(Creature *c) : ScriptedAI(c) + { + //pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + //ScriptedInstance* pInstance; + + uint32 ShieldBash_Timer; + uint32 Revenge_Timer; //this is wrong, spell should never be used unless m_creature->getVictim() dodge, parry or block attack. Mangos support required. + + void Reset() + { + ShieldBash_Timer = 5000; + Revenge_Timer = 8000; + + m_creature->setFaction(FACTION_FRIENDLY); + + /*if( pInstance ) + pInstance->SetData(0, NOT_STARTED);*/ + } + + void Aggro(Unit *who) + { + /*if( pInstance ) + pInstance->SetData(0, IN_PROGRESS);*/ + } + + void JustDied(Unit *victim) + { + /*if( pInstance ) + pInstance->SetData(0, DONE);*/ + } + + void UpdateAI(const uint32 diff) + { + if( !m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + if( ShieldBash_Timer < diff ) + { + DoCast(m_creature->getVictim(),SPELL_SHIELD_BASH); + ShieldBash_Timer = 15000; + }else ShieldBash_Timer -= diff; + + if( Revenge_Timer < diff ) + { + DoCast(m_creature->getVictim(),SPELL_REVENGE); + Revenge_Timer = 10000; + }else Revenge_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_npc_sergeant_bly(Creature *_Creature) +{ + return new npc_sergeant_blyAI (_Creature); +} + +bool GossipHello_npc_sergeant_bly(Player *player, Creature *_Creature ) +{ + /*if( pInstance->GetData(0) == DONE ) + {*/ + player->ADD_GOSSIP_ITEM(1, GOSSIP_BLY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + player->SEND_GOSSIP_MENU(1517, _Creature->GetGUID()); + /*} + else if( pInstance->GetData(0) == IN_PROGRESS ) + player->SEND_GOSSIP_MENU(1516, _Creature->GetGUID()); + else + player->SEND_GOSSIP_MENU(1515, _Creature->GetGUID());*/ + + return true; +} + +bool GossipSelect_npc_sergeant_bly(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if( action == GOSSIP_ACTION_INFO_DEF+1 ) + { + player->CLOSE_GOSSIP_MENU(); + _Creature->setFaction(FACTION_HOSTILE); + ((npc_sergeant_blyAI*)_Creature->AI())->AttackStart(player); + } + return true; +} + +/*###### +## npc_weegli_blastfuse +######*/ + +#define SPELL_BOMB 8858 +#define SPELL_GOBLIN_LAND_MINE 21688 +#define SPELL_SHOOT 6660 +#define SPELL_WEEGLIS_BARREL 10772 + +#define GOSSIP_WEEGLI "[PH] Please blow up the door." + +struct MANGOS_DLL_DECL npc_weegli_blastfuseAI : public ScriptedAI +{ + npc_weegli_blastfuseAI(Creature *c) : ScriptedAI(c) + { + //pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + //ScriptedInstance* pInstance; + + void Reset() + { + /*if( pInstance ) + pInstance->SetData(0, NOT_STARTED);*/ + } + + void Aggro(Unit *who) + { + /*if( pInstance ) + pInstance->SetData(0, IN_PROGRESS);*/ + } + + void JustDied(Unit *victim) + { + /*if( pInstance ) + pInstance->SetData(0, DONE);*/ + } + + void UpdateAI(const uint32 diff) + { + if( !m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_npc_weegli_blastfuse(Creature *_Creature) +{ + return new npc_weegli_blastfuseAI (_Creature); +} + +bool GossipHello_npc_weegli_blastfuse(Player *player, Creature *_Creature ) +{ + //event not implemented yet, this is only placeholder for future developement + /*if( pInstance->GetData(0) == DONE ) + { + player->ADD_GOSSIP_ITEM(1, GOSSIP_WEEGLI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + player->SEND_GOSSIP_MENU(1514, _Creature->GetGUID());//if event can proceed to end + } + else if( pInstance->GetData(0) == IN_PROGRESS ) + player->SEND_GOSSIP_MENU(1513, _Creature->GetGUID());//if event are in progress + else*/ + player->SEND_GOSSIP_MENU(1511, _Creature->GetGUID()); //if event not started + return true; +} + +bool GossipSelect_npc_weegli_blastfuse(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if( action == GOSSIP_ACTION_INFO_DEF+1 ) + { + player->CLOSE_GOSSIP_MENU(); + //here we make him run to door, set the charge and run away off to nowhere + } + return true; +} + +void AddSC_zulfarrak() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="npc_sergeant_bly"; + newscript->GetAI = GetAI_npc_sergeant_bly; + newscript->pGossipHello = &GossipHello_npc_sergeant_bly; + newscript->pGossipSelect = &GossipSelect_npc_sergeant_bly; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="npc_weegli_blastfuse"; + newscript->GetAI = GetAI_npc_weegli_blastfuse; + newscript->pGossipHello = &GossipHello_npc_weegli_blastfuse; + newscript->pGossipSelect = &GossipSelect_npc_weegli_blastfuse; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/zulgurub/boss_arlokk.cpp b/src/bindings/scripts/scripts/zone/zulgurub/boss_arlokk.cpp new file mode 100644 index 00000000000..7be65ad73f0 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/zulgurub/boss_arlokk.cpp @@ -0,0 +1,211 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Arlokk +SD%Complete: 95 +SDComment: Wrong cleave and red aura is missing. +SDCategory: Zul'Gurub +EndScriptData */ + +#include "precompiled.h" +#include "def_zulgurub.h" + +#define SPELL_SHADOWWORDPAIN 23952 +#define SPELL_GOUGE 24698 +#define SPELL_MARK 24210 +#define SPELL_CLEAVE 26350 //Perhaps not right. Not a red aura... +#define SPELL_PANTHER_TRANSFORM 24190 + +#define SAY_TRANSFORM "Bethekk, your priestess calls upon your might!" +#define SAY_DEATH "At last I am free of the soul flayer..." + +#define SOUND_TRANSFORM 8416 +#define SOUND_DEATH 8412 + +struct MANGOS_DLL_DECL boss_arlokkAI : public ScriptedAI +{ + boss_arlokkAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 ShadowWordPain_Timer; + uint32 Gouge_Timer; + uint32 Mark_Timer; + uint32 Cleave_Timer; + uint32 Vanish_Timer; + uint32 Summon_Timer; + uint32 Visible_Timer; + + Unit* markedTarget; + Creature *Panther; + uint32 Counter; + + bool PhaseTwo; + bool VanishedOnce; + + void Reset() + { + ShadowWordPain_Timer = 8000; + Gouge_Timer = 14000; + Mark_Timer = 35000; + Cleave_Timer = 4000; + Vanish_Timer = 60000; + Summon_Timer = 5000; + Visible_Timer = 6000; + + Counter = 0; + + markedTarget = NULL; + PhaseTwo = false; + VanishedOnce = false; + + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID,15218); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void Aggro(Unit *who) + { + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DEATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_DEATH); + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID,15218); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + ScriptedInstance *pInstance = (m_creature->GetInstanceData()) ? ((ScriptedInstance*)m_creature->GetInstanceData()) : NULL; + + if(pInstance) + pInstance->SetData(DATA_ARLOKK_DEATH, 0); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget()) + return; + + if( m_creature->getVictim() && m_creature->isAlive()) + { + if (!PhaseTwo && ShadowWordPain_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SHADOWWORDPAIN); + ShadowWordPain_Timer = 15000; + }else ShadowWordPain_Timer -= diff; + + if (!PhaseTwo && Mark_Timer < diff) + { + markedTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + + DoCast(markedTarget,SPELL_MARK); + Mark_Timer = 15000; + }else Mark_Timer -= diff; + + if (Summon_Timer < diff && Counter < 31) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + + Panther = m_creature->SummonCreature(15101,-11532.79980,-1649.6734,41.4800,0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + + if(markedTarget && Panther ) + { Panther ->AI()->AttackStart(markedTarget); } + else + { Panther ->AI()->AttackStart(target); } + + Panther = m_creature->SummonCreature(15101,-11532.9970,-1606.4840,41.2979,0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + + if(markedTarget && Panther ) + { Panther ->AI()->AttackStart(markedTarget); } + else + { Panther ->AI()->AttackStart(target); } + + Counter++; + Summon_Timer = 5000; + }else Summon_Timer -= diff; + + if (Vanish_Timer < diff) + { + //Invisble Model + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID,11686); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + //m_creature->CombatStop(); + DoResetThreat(); + VanishedOnce = true; + Vanish_Timer = 45000; + Visible_Timer = 6000; + }else Vanish_Timer -= diff; + + if (VanishedOnce) + { + if(Visible_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + //The Panther Model + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID,15215); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + if (!PhaseTwo) + { + DoYell(SAY_TRANSFORM,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_TRANSFORM); + } + + const CreatureInfo *cinfo = m_creature->GetCreatureInfo(); + m_creature->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 35))); + m_creature->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 35))); + m_creature->UpdateDamagePhysical(BASE_ATTACK); + DoStartAttackAndMovement(target); + //The Panther Model + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID,15215); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + PhaseTwo = true; + }else Visible_Timer -= diff; + } + + //Cleave_Timer + if(PhaseTwo && Cleave_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 16000; + }Cleave_Timer -=diff; + + //Gouge_Timer + if(PhaseTwo && Gouge_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_GOUGE); + if(m_creature->getThreatManager().getThreat(m_creature->getVictim())) + m_creature->getThreatManager().modifyThreatPercent(m_creature->getVictim(),-80); + + Gouge_Timer = 17000+rand()%10000; + }else Gouge_Timer -= diff; + + DoMeleeAttackIfReady(); + } + } +}; +CreatureAI* GetAI_boss_arlokk(Creature *_Creature) +{ + return new boss_arlokkAI (_Creature); +} + +void AddSC_boss_arlokk() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_arlokk"; + newscript->GetAI = GetAI_boss_arlokk; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/zulgurub/boss_gahzranka.cpp b/src/bindings/scripts/scripts/zone/zulgurub/boss_gahzranka.cpp new file mode 100644 index 00000000000..6fd39159cb5 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/zulgurub/boss_gahzranka.cpp @@ -0,0 +1,92 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Gahz'ranka +SD%Complete: 85 +SDComment: Massive Geyser with knockback not working. Spell buggy. +SDCategory: Zul'Gurub +EndScriptData */ + +#include "precompiled.h" + +#define SPELL_FROSTBREATH 21099 +#define SPELL_MASSIVEGEYSER 22421 //Not working. Cause its a summon... +#define SPELL_SLAM 24326 + +struct MANGOS_DLL_DECL boss_gahzrankaAI : public ScriptedAI +{ + boss_gahzrankaAI(Creature *c) : ScriptedAI(c) {Reset();} + uint32 Frostbreath_Timer; + uint32 MassiveGeyser_Timer; + uint32 Slam_Timer; + + void Reset() + { + Frostbreath_Timer = 8000; + MassiveGeyser_Timer = 25000; + Slam_Timer = 17000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //Frostbreath_Timer + if (Frostbreath_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_FROSTBREATH); + Frostbreath_Timer = 7000 + rand()%4000; + }else Frostbreath_Timer -= diff; + + //MassiveGeyser_Timer + if (MassiveGeyser_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_MASSIVEGEYSER); + DoResetThreat(); + + MassiveGeyser_Timer = 22000 + rand()%10000; + }else MassiveGeyser_Timer -= diff; + + //Slam_Timer + if (Slam_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SLAM); + Slam_Timer = 12000 + rand()%8000; + }else Slam_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_gahzranka(Creature *_Creature) +{ + return new boss_gahzrankaAI (_Creature); +} + +void AddSC_boss_gahzranka() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_gahzranka"; + newscript->GetAI = GetAI_boss_gahzranka; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/zulgurub/boss_grilek.cpp b/src/bindings/scripts/scripts/zone/zulgurub/boss_grilek.cpp new file mode 100644 index 00000000000..b25843dbb24 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/zulgurub/boss_grilek.cpp @@ -0,0 +1,92 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Grilek +SD%Complete: 100 +SDComment: +SDCategory: Zul'Gurub +EndScriptData */ + +#include "precompiled.h" +#include "def_zulgurub.h" + +#define SPELL_AVARTAR 24646 //The Enrage Spell +#define SPELL_GROUNDTREMOR 6524 + +struct MANGOS_DLL_DECL boss_grilekAI : public ScriptedAI +{ + boss_grilekAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Avartar_Timer; + uint32 GroundTremor_Timer; + + void Reset() + { + Avartar_Timer = 15000 + rand()%10000; + GroundTremor_Timer = 8000 + rand()%8000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //Avartar_Timer + if (Avartar_Timer < diff) + { + + DoCast(m_creature, SPELL_AVARTAR); + Unit* target = NULL; + + target = SelectUnit(SELECT_TARGET_RANDOM,1); + + if(m_creature->getThreatManager().getThreat(m_creature->getVictim())) + m_creature->getThreatManager().modifyThreatPercent(m_creature->getVictim(),-50); + if (target) + DoStartAttackAndMovement(target); + + Avartar_Timer = 25000 + rand()%10000; + }else Avartar_Timer -= diff; + + //GroundTremor_Timer + if (GroundTremor_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_GROUNDTREMOR); + GroundTremor_Timer = 12000 + rand()%4000; + }else GroundTremor_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_grilek(Creature *_Creature) +{ + return new boss_grilekAI (_Creature); +} + +void AddSC_boss_grilek() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_grilek"; + newscript->GetAI = GetAI_boss_grilek; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/zulgurub/boss_hakkar.cpp b/src/bindings/scripts/scripts/zone/zulgurub/boss_hakkar.cpp new file mode 100644 index 00000000000..719f2d77b87 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/zulgurub/boss_hakkar.cpp @@ -0,0 +1,256 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Hakkar +SD%Complete: 95 +SDComment: Blood siphon spell buggy cause of Core Issue. +SDCategory: Zul'Gurub +EndScriptData */ + +#include "precompiled.h" +#include "def_zulgurub.h" + +#define SPELL_BLOODSIPHON 24322 +#define SPELL_CORRUPTEDBLOOD 24328 +#define SPELL_CAUSEINSANITY 24327 //Not working disabled. +#define SPELL_WILLOFHAKKAR 24178 +#define SPELL_ENRAGE 24318 + +// The Aspects of all High Priests +#define SPELL_ASPECT_OF_JEKLIK 24687 +#define SPELL_ASPECT_OF_VENOXIS 24688 +#define SPELL_ASPECT_OF_MARLI 24686 +#define SPELL_ASPECT_OF_THEKAL 24689 +#define SPELL_ASPECT_OF_ARLOKK 24690 + +#define SAY_AGGRO "PRIDE HERALDS THE END OF YOUR WORLD. COME, MORTALS! FACE THE WRATH OF THE SOULFLAYER!" +#define SOUND_AGGRO 8414 + +#define SAY_SLAY "Fleeing will do you no good, mortals!" + +struct MANGOS_DLL_DECL boss_hakkarAI : public ScriptedAI +{ + boss_hakkarAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + uint32 BloodSiphon_Timer; + uint32 CorruptedBlood_Timer; + uint32 CauseInsanity_Timer; + uint32 WillOfHakkar_Timer; + uint32 Enrage_Timer; + + uint32 CheckJeklik_Timer; + uint32 CheckVenoxis_Timer; + uint32 CheckMarli_Timer; + uint32 CheckThekal_Timer; + uint32 CheckArlokk_Timer; + + uint32 AspectOfJeklik_Timer; + uint32 AspectOfVenoxis_Timer; + uint32 AspectOfMarli_Timer; + uint32 AspectOfThekal_Timer; + uint32 AspectOfArlokk_Timer; + + ScriptedInstance *pInstance; + + bool Enraged; + + void Reset() + { + BloodSiphon_Timer = 90000; + CorruptedBlood_Timer = 25000; + CauseInsanity_Timer = 17000; + WillOfHakkar_Timer = 17000; + Enrage_Timer = 600000; + + CheckJeklik_Timer = 1000; + CheckVenoxis_Timer = 2000; + CheckMarli_Timer = 3000; + CheckThekal_Timer = 4000; + CheckArlokk_Timer = 5000; + + AspectOfJeklik_Timer = 4000; + AspectOfVenoxis_Timer = 7000; + AspectOfMarli_Timer = 12000; + AspectOfThekal_Timer = 8000; + AspectOfArlokk_Timer = 18000; + + Enraged = false; + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //BloodSiphon_Timer + if (BloodSiphon_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_BLOODSIPHON); + BloodSiphon_Timer = 90000; + }else BloodSiphon_Timer -= diff; + + //CorruptedBlood_Timer + if (CorruptedBlood_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CORRUPTEDBLOOD); + CorruptedBlood_Timer = 30000 + rand()%15000; + }else CorruptedBlood_Timer -= diff; + + //CauseInsanity_Timer + // if (CauseInsanity_Timer < diff) + // { + // + // Unit* target = NULL; + // target = SelectUnit(SELECT_TARGET_RANDOM,0); + + // DoCast(target,SPELL_CAUSEINSANITY); + + // CauseInsanity_Timer = 35000 + rand()%8000; + // }else CauseInsanity_Timer -= diff; + + //WillOfHakkar_Timer + if (WillOfHakkar_Timer < diff) + { + + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + + DoCast(target,SPELL_WILLOFHAKKAR); + WillOfHakkar_Timer = 25000 + rand()%10000; + }else WillOfHakkar_Timer -= diff; + + if (!Enraged && Enrage_Timer < diff) + { + DoCast(m_creature, SPELL_ENRAGE); + Enraged = true; + }else Enrage_Timer -= diff; + + //Checking if Jeklik is dead. If not we cast her Aspect + if(CheckJeklik_Timer < diff) + { + if(pInstance) + { + if(!pInstance->GetData(DATA_JEKLIKISDEAD)) + { + if (AspectOfJeklik_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_ASPECT_OF_JEKLIK); + AspectOfJeklik_Timer = 10000 + rand()%4000; + }else AspectOfJeklik_Timer -= diff; + } + } + CheckJeklik_Timer = 1000; + }else CheckJeklik_Timer -= diff; + + //Checking if Venoxis is dead. If not we cast his Aspect + if(CheckVenoxis_Timer < diff) + { + if(pInstance) + { + if(!pInstance->GetData(DATA_VENOXISISDEAD)) + { + if (AspectOfVenoxis_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_ASPECT_OF_VENOXIS); + AspectOfVenoxis_Timer = 8000; + }else AspectOfVenoxis_Timer -= diff; + } + } + CheckVenoxis_Timer = 1000; + }else CheckVenoxis_Timer -= diff; + + //Checking if Marli is dead. If not we cast her Aspect + if(CheckMarli_Timer < diff) + { + if(pInstance) + { + if(!pInstance->GetData(DATA_MARLIISDEAD)) + { + if (AspectOfMarli_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_ASPECT_OF_MARLI); + AspectOfMarli_Timer = 10000; + }else AspectOfMarli_Timer -= diff; + + } + } + CheckMarli_Timer = 1000; + }else CheckMarli_Timer -= diff; + + //Checking if Thekal is dead. If not we cast his Aspect + if(CheckThekal_Timer < diff) + { + if(pInstance) + { + if(!pInstance->GetData(DATA_THEKALISDEAD)) + { + if (AspectOfThekal_Timer < diff) + { + DoCast(m_creature,SPELL_ASPECT_OF_THEKAL); + AspectOfThekal_Timer = 15000; + }else AspectOfThekal_Timer -= diff; + } + } + CheckThekal_Timer = 1000; + }else CheckThekal_Timer -= diff; + + //Checking if Arlokk is dead. If yes we cast her Aspect + if(CheckArlokk_Timer < diff) + { + if(pInstance) + { + if(!pInstance->GetData(DATA_ARLOKKISDEAD)) + { + if (AspectOfArlokk_Timer < diff) + { + DoCast(m_creature,SPELL_ASPECT_OF_ARLOKK); + DoResetThreat(); + + AspectOfArlokk_Timer = 10000 + rand()%5000; + }else AspectOfArlokk_Timer -= diff; + } + } + CheckArlokk_Timer = 1000; + }else CheckArlokk_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_hakkar(Creature *_Creature) +{ + return new boss_hakkarAI (_Creature); +} + +void AddSC_boss_hakkar() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_hakkar"; + newscript->GetAI = GetAI_boss_hakkar; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/zulgurub/boss_hazzarah.cpp b/src/bindings/scripts/scripts/zone/zulgurub/boss_hazzarah.cpp new file mode 100644 index 00000000000..adf5a44ec95 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/zulgurub/boss_hazzarah.cpp @@ -0,0 +1,100 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Hazzarah +SD%Complete: 100 +SDComment: +SDCategory: Zul'Gurub +EndScriptData */ + +#include "precompiled.h" +#include "def_zulgurub.h" + +#define SPELL_MANABURN 26046 +#define SPELL_SLEEP 24664 + +struct MANGOS_DLL_DECL boss_hazzarahAI : public ScriptedAI +{ + boss_hazzarahAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 ManaBurn_Timer; + uint32 Sleep_Timer; + uint32 Illusions_Timer; + Creature* Illusion; + + void Reset() + { + ManaBurn_Timer = 4000 + rand()%6000; + Sleep_Timer = 10000 + rand()%8000; + Illusions_Timer = 10000 + rand()%8000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //ManaBurn_Timer + if (ManaBurn_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_MANABURN); + ManaBurn_Timer = 8000 + rand()%8000; + }else ManaBurn_Timer -= diff; + + //Sleep_Timer + if (Sleep_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SLEEP); + Sleep_Timer = 12000 + rand()%8000; + }else Sleep_Timer -= diff; + + //Illusions_Timer + if (Illusions_Timer < diff) + { + //We will summon 3 illusions that will spawn on a random gamer and attack this gamer + //We will just use one model for the beginning + Unit* target = NULL; + for(int i = 0; i < 3;i++) + { + target = SelectUnit(SELECT_TARGET_RANDOM,0); + Illusion = m_creature->SummonCreature(15163,target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(),0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,30000); + ((CreatureAI*)Illusion->AI())->AttackStart(target); + } + + Illusions_Timer = 15000 + rand()%10000; + }else Illusions_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_hazzarah(Creature *_Creature) +{ + return new boss_hazzarahAI (_Creature); +} + +void AddSC_boss_hazzarah() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_hazzarah"; + newscript->GetAI = GetAI_boss_hazzarah; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/zulgurub/boss_jeklik.cpp b/src/bindings/scripts/scripts/zone/zulgurub/boss_jeklik.cpp new file mode 100644 index 00000000000..efe76bbe5ec --- /dev/null +++ b/src/bindings/scripts/scripts/zone/zulgurub/boss_jeklik.cpp @@ -0,0 +1,297 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Jeklik +SD%Complete: 85 +SDComment: Problem in finding the right flying batriders for spawning and making them fly. +SDCategory: Zul'Gurub +EndScriptData */ + +#include "precompiled.h" +#include "def_zulgurub.h" + +#define SPELL_CHARGE 22911 +#define SPELL_SONICBURST 23918 +#define SPELL_SCREECH 6605 +#define SPELL_SHADOW_WORD_PAIN 23952 +#define SPELL_MIND_FLAY 23953 +#define SPELL_CHAIN_MIND_FLAY 26044 //Right ID unknown. So disabled +#define SPELL_GREATERHEAL 23954 +#define SPELL_BAT_FORM 23966 + +// Batriders Spell + +#define SPELL_BOMB 40332 //Wrong ID but Magmadars bomb is not working... + +#define SAY_AGGRO "Lord Hireek grant me wings of vengance!" +#define SAY_DEATH "Hireek - Finnaly death. Curse you Hakkar! Curse you!" + +#define SOUND_AGGRO 8417 +#define SOUND_DEATH 8422 + +struct MANGOS_DLL_DECL boss_jeklikAI : public ScriptedAI +{ + boss_jeklikAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Charge_Timer; + uint32 SonicBurst_Timer; + uint32 Screech_Timer; + uint32 SpawnBats_Timer; + uint32 ShadowWordPain_Timer; + uint32 MindFlay_Timer; + uint32 ChainMindFlay_Timer; + uint32 GreaterHeal_Timer; + uint32 SpawnFlyingBats_Timer; + + bool PhaseTwo; + + void Reset() + { + Charge_Timer = 20000; + SonicBurst_Timer = 8000; + Screech_Timer = 13000; + SpawnBats_Timer = 60000; + ShadowWordPain_Timer = 6000; + MindFlay_Timer = 11000; + ChainMindFlay_Timer = 26000; + GreaterHeal_Timer = 50000; + SpawnFlyingBats_Timer = 10000; + + PhaseTwo = false; + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO); + DoCast(m_creature,SPELL_BAT_FORM); + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DEATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_DEATH); + + ScriptedInstance *pInstance = ((ScriptedInstance*)m_creature->GetInstanceData()); + if(pInstance) + pInstance->SetData(DATA_JEKLIK_DEATH, 0); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget()) + return; + + if( m_creature->getVictim() && m_creature->isAlive()) + { + if ((m_creature->GetHealth()*100 / m_creature->GetMaxHealth() > 50)) + { + if (Charge_Timer < diff) + { + Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0); + if(target) + { + DoCast(target,SPELL_CHARGE); + + m_creature->Relocate(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0); + m_creature->SendMonsterMove(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, true,1); + DoStartAttackAndMovement(target); + } + + Charge_Timer = 15000 + rand()%15000; + }else Charge_Timer -= diff; + + if (SonicBurst_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SONICBURST); + SonicBurst_Timer = 8000 + rand()%5000; + }else SonicBurst_Timer -= diff; + + if (Screech_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SCREECH); + Screech_Timer = 18000 + rand()%8000; + }else Screech_Timer -= diff; + + if (SpawnBats_Timer < diff) + { + Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0); + + Creature* Bat = NULL; + Bat = m_creature->SummonCreature(11368,-12291.6220,-1380.2640,144.8304,5.483, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if(target && Bat ) { Bat ->AI()->AttackStart(target); } + + Bat = m_creature->SummonCreature(11368,-12289.6220,-1380.2640,144.8304,5.483, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if(target && Bat ) { Bat ->AI()->AttackStart(target); } + + Bat = m_creature->SummonCreature(11368,-12293.6220,-1380.2640,144.8304,5.483, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if(target && Bat ) { Bat ->AI()->AttackStart(target); } + + Bat = m_creature->SummonCreature(11368,-12291.6220,-1380.2640,144.8304,5.483, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if(target && Bat ) { Bat ->AI()->AttackStart(target); } + + Bat = m_creature->SummonCreature(11368,-12289.6220,-1380.2640,144.8304,5.483, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if(target && Bat ) { Bat ->AI()->AttackStart(target); } + Bat = m_creature->SummonCreature(11368,-12293.6220,-1380.2640,144.8304,5.483, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if(target && Bat ) { Bat ->AI()->AttackStart(target); } + + SpawnBats_Timer = 60000; + }else SpawnBats_Timer -= diff; + } + else + { + if(PhaseTwo) + { + if(PhaseTwo && ShadowWordPain_Timer < diff) + { + Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0); + if(target) + { + DoCast(target, SPELL_SHADOW_WORD_PAIN); + ShadowWordPain_Timer = 12000 + rand()%6000; + } + }ShadowWordPain_Timer -=diff; + + if(MindFlay_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_MIND_FLAY); + MindFlay_Timer = 16000; + }MindFlay_Timer -=diff; + + if(ChainMindFlay_Timer < diff) + { + m_creature->InterruptNonMeleeSpells(false); + DoCast(m_creature->getVictim(), SPELL_CHAIN_MIND_FLAY); + ChainMindFlay_Timer = 15000 + rand()%15000; + }ChainMindFlay_Timer -=diff; + + if(GreaterHeal_Timer < diff) + { + m_creature->InterruptNonMeleeSpells(false); + DoCast(m_creature,SPELL_GREATERHEAL); + GreaterHeal_Timer = 25000 + rand()%10000; + }GreaterHeal_Timer -=diff; + + if(SpawnFlyingBats_Timer < diff) + { + Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 0); + + Creature* FlyingBat = m_creature->SummonCreature(14965, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ()+15, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if(FlyingBat) + { + if(target) + FlyingBat->AI()->AttackStart(target); + } + + SpawnFlyingBats_Timer = 10000 + rand()%5000; + }SpawnFlyingBats_Timer -=diff; + } + else + { + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID,15219); + DoResetThreat(); + PhaseTwo = true; + } + } + + DoMeleeAttackIfReady(); + } + } +}; + +//Flying Bat +struct MANGOS_DLL_DECL mob_batriderAI : public ScriptedAI +{ + mob_batriderAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + ScriptedInstance *pInstance; + + uint32 Bomb_Timer; + uint32 Check_Timer; + + void Reset() + { + Bomb_Timer = 2000; + Check_Timer = 1000; + + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void Aggro(Unit *who) {} + + void UpdateAI (const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //Bomb_Timer + if(Bomb_Timer < diff) + { + Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target) + { + DoCast(target, SPELL_BOMB); + Bomb_Timer = 5000; + } + }else Bomb_Timer -= diff; + + //Check_Timer + if(Check_Timer < diff) + { + if(pInstance) + { + if(pInstance->GetData(DATA_JEKLIKISDEAD)) + { + m_creature->setDeathState(JUST_DIED); + m_creature->RemoveCorpse(); + } + } + + Check_Timer = 1000; + }else Check_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_jeklik(Creature *_Creature) +{ + return new boss_jeklikAI (_Creature); +} + +CreatureAI* GetAI_mob_batrider(Creature *_Creature) +{ + return new mob_batriderAI (_Creature); +} + +void AddSC_boss_jeklik() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_jeklik"; + newscript->GetAI = GetAI_boss_jeklik; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_batrider"; + newscript->GetAI = GetAI_mob_batrider; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/zulgurub/boss_jindo.cpp b/src/bindings/scripts/scripts/zone/zulgurub/boss_jindo.cpp new file mode 100644 index 00000000000..8a9a5cb2cc8 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/zulgurub/boss_jindo.cpp @@ -0,0 +1,308 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Jin'do the Hexxer +SD%Complete: 85 +SDComment: Mind Control not working because of core bug. Shades visible for all. +SDCategory: Zul'Gurub +EndScriptData */ + +#include "precompiled.h" +#include "def_zulgurub.h" + +#define SPELL_BRAINWASHTOTEM 24262 +#define SPELL_POWERFULLHEALINGWARD 24309 //We will not use this spell. We will summon a totem by script cause the spell totems will not cast. +#define SPELL_HEX 24053 +#define SPELL_DELUSIONSOFJINDO 24306 +#define SPELL_SHADEOFJINDO 24308 //We will not use this spell. We will summon a shade by script. + +//Healing Ward Spell +#define SPELL_HEAL 38588 //Totems are not working right. Right heal spell ID is 24311 but this spell is not casting... + +//Shade of Jindo Spell +#define SPELL_SHADOWSHOCK 19460 +#define SPELL_INVISIBLE 24699 + +#define SAY_AGGRO "Welcome to da great show friends! Step right up to die!" + +#define SOUND_AGGRO 8425 + +struct MANGOS_DLL_DECL boss_jindoAI : public ScriptedAI +{ + boss_jindoAI(Creature *c) : ScriptedAI(c) + { + pInstance = (c->GetInstanceData()) ? ((ScriptedInstance*)c->GetInstanceData()) : NULL; + Reset(); + } + + uint32 BrainWashTotem_Timer; + uint32 HealingWard_Timer; + uint32 Hex_Timer; + uint32 Delusions_Timer; + uint32 Teleport_Timer; + + Creature *Shade; + Creature *Skeletons; + Creature *HealingWard; + + ScriptedInstance *pInstance; + + void Reset() + { + BrainWashTotem_Timer = 20000; + HealingWard_Timer = 16000; + Hex_Timer = 8000; + Delusions_Timer = 10000; + Teleport_Timer = 5000; + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //BrainWashTotem_Timer + if (BrainWashTotem_Timer < diff) + { + DoCast(m_creature, SPELL_BRAINWASHTOTEM); + BrainWashTotem_Timer = 18000 + rand()%8000; + }else BrainWashTotem_Timer -= diff; + + //HealingWard_Timer + if (HealingWard_Timer < diff) + { + //DoCast(m_creature, SPELL_POWERFULLHEALINGWARD); + HealingWard = m_creature->SummonCreature(14987, m_creature->GetPositionX()+3, m_creature->GetPositionY()-2, m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,30000); + HealingWard_Timer = 14000 + rand()%6000; + }else HealingWard_Timer -= diff; + + //Hex_Timer + if (Hex_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_HEX); + + if(m_creature->getThreatManager().getThreat(m_creature->getVictim())) + m_creature->getThreatManager().modifyThreatPercent(m_creature->getVictim(),-80); + + Hex_Timer = 12000 + rand()%8000; + }else Hex_Timer -= diff; + + //Casting the delusion curse with a shade. So shade will attack the same target with the curse. + if (Delusions_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + + DoCast(target, SPELL_DELUSIONSOFJINDO); + + Shade = m_creature->SummonCreature(14986, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + Shade->AI()->AttackStart(target); + + Delusions_Timer = 4000 + rand()%8000; + }else Delusions_Timer -= diff; + + //Teleporting a random gamer and spawning 9 skeletons that will attack this gamer + if (Teleport_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target && target->GetTypeId() == TYPEID_PLAYER) + { + DoTeleportPlayer(target, -11583.7783,-1249.4278,77.5471,4.745); + + if(m_creature->getThreatManager().getThreat(m_creature->getVictim())) + m_creature->getThreatManager().modifyThreatPercent(target,-100); + + Skeletons = m_creature->SummonCreature(14826, target->GetPositionX()+2, target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + Skeletons->AI()->AttackStart(target); + Skeletons = m_creature->SummonCreature(14826, target->GetPositionX()-2, target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + Skeletons->AI()->AttackStart(target); + Skeletons = m_creature->SummonCreature(14826, target->GetPositionX()+4, target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + Skeletons->AI()->AttackStart(target); + Skeletons = m_creature->SummonCreature(14826, target->GetPositionX()-4, target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + Skeletons->AI()->AttackStart(target); + Skeletons = m_creature->SummonCreature(14826, target->GetPositionX(), target->GetPositionY()+2, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + Skeletons->AI()->AttackStart(target); + Skeletons = m_creature->SummonCreature(14826, target->GetPositionX(), target->GetPositionY()-2, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + Skeletons->AI()->AttackStart(target); + Skeletons = m_creature->SummonCreature(14826, target->GetPositionX(), target->GetPositionY()+4, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + Skeletons->AI()->AttackStart(target); + Skeletons = m_creature->SummonCreature(14826, target->GetPositionX(), target->GetPositionY()-4, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + Skeletons->AI()->AttackStart(target); + Skeletons = m_creature->SummonCreature(14826, target->GetPositionX()+3, target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + Skeletons->AI()->AttackStart(target); + } + + Teleport_Timer = 15000 + rand()%8000; + }else Teleport_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Healing Ward +struct MANGOS_DLL_DECL mob_healing_wardAI : public ScriptedAI +{ + mob_healing_wardAI(Creature *c) : ScriptedAI(c) + { + pInstance = (c->GetInstanceData()) ? ((ScriptedInstance*)c->GetInstanceData()) : NULL; + Reset(); + } + + uint32 Heal_Timer; + + ScriptedInstance *pInstance; + + void Reset() + { + Heal_Timer = 2000; + } + + void Aggro(Unit *who) + { + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || m_creature->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + float attackRadius = m_creature->GetAttackDistance(who); + if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) + { + if(who->HasStealthAura()) + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + DoStartAttackAndMovement(who); + } + } + } + + void UpdateAI (const uint32 diff) + { + //Heal_Timer + if(Heal_Timer < diff) + { + if(pInstance) + { + Unit *pJindo = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_JINDO)); + DoCast(pJindo, SPELL_HEAL); + } + Heal_Timer = 3000; + }else Heal_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Shade of Jindo +struct MANGOS_DLL_DECL mob_shade_of_jindoAI : public ScriptedAI +{ + mob_shade_of_jindoAI(Creature *c) : ScriptedAI(c) + { + pInstance = (c->GetInstanceData()) ? ((ScriptedInstance*)c->GetInstanceData()) : NULL; + Reset(); + } + + uint32 ShadowShock_Timer; + + ScriptedInstance *pInstance; + + void Reset() + { + ShadowShock_Timer = 1000; + m_creature->CastSpell(m_creature, SPELL_INVISIBLE,true); + } + + void Aggro(Unit *who) + { + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || m_creature->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + float attackRadius = m_creature->GetAttackDistance(who); + if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) + { + if(who->HasStealthAura()) + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + DoStartAttackAndMovement(who); + } + } + } + + void UpdateAI (const uint32 diff) + { + + //ShadowShock_Timer + if(ShadowShock_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_SHADOWSHOCK); + ShadowShock_Timer = 2000; + }else ShadowShock_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_jindo(Creature *_Creature) +{ + return new boss_jindoAI (_Creature); +} + +CreatureAI* GetAI_mob_healing_ward(Creature *_Creature) +{ + return new mob_healing_wardAI (_Creature); +} + +CreatureAI* GetAI_mob_shade_of_jindo(Creature *_Creature) +{ + return new mob_shade_of_jindoAI (_Creature); +} + +void AddSC_boss_jindo() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_jindo"; + newscript->GetAI = GetAI_boss_jindo; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_healing_ward"; + newscript->GetAI = GetAI_mob_healing_ward; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_shade_of_jindo"; + newscript->GetAI = GetAI_mob_shade_of_jindo; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/zulgurub/boss_mandokir.cpp b/src/bindings/scripts/scripts/zone/zulgurub/boss_mandokir.cpp new file mode 100644 index 00000000000..7d8465b2780 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/zulgurub/boss_mandokir.cpp @@ -0,0 +1,311 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Mandokir +SD%Complete: 90 +SDComment: Ohgan function needs improvements. +SDCategory: Zul'Gurub +EndScriptData */ + +#include "precompiled.h" +#include "def_zulgurub.h" + +#define SPELL_CHARGE 24315 +#define SPELL_CLEAVE 20691 +#define SPELL_FEAR 29321 +#define SPELL_WHIRLWIND 24236 +#define SPELL_MORTAL_STRIKE 24573 +#define SPELL_ENRAGE 23537 +#define SPELL_WATCH 24314 +#define SPELL_LEVEL_UP 24312 + +//Ohgans Spells +#define SPELL_SUNDERARMOR 24317 + +#define SAY_AGGRO "I'll feed your souls to Hakkar himself!" +#define SOUND_AGGRO 8413 + +#define SAY_WATCH "I'm keeping my eye on you, $N!" +#define SAY_KILL "DING!" + +struct MANGOS_DLL_DECL boss_mandokirAI : public ScriptedAI +{ + boss_mandokirAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + uint32 Watch_Timer; + uint32 TargetInRange; + uint32 Cleave_Timer; + uint32 Whirlwind_Timer; + uint32 Fear_Timer; + uint32 MortalStrike_Timer; + uint32 Check_Timer; + float targetX; + float targetY; + float targetZ; + + ScriptedInstance *pInstance; + + bool endWatch; + bool someWatched; + bool RaptorDead; + bool CombatStart; + + uint64 WatchTarget; + + void Reset() + { + Watch_Timer = 33000; + Cleave_Timer = 7000; + Whirlwind_Timer = 20000; + Fear_Timer = 1000; + MortalStrike_Timer = 1000; + Check_Timer = 1000; + + targetX = 0.0; + targetY = 0.0; + targetZ = 0.0; + TargetInRange = 0; + + WatchTarget = 0; + + someWatched = false; + endWatch = false; + RaptorDead = false; + CombatStart = false; + + DoCast(m_creature, 23243); + } + + void KilledUnit(Unit* victim) + { + if(victim->GetTypeId() == TYPEID_PLAYER) + { + DoYell(SAY_KILL, LANG_UNIVERSAL, NULL); + DoCast(m_creature, SPELL_LEVEL_UP, true); + } + } + + void Aggro(Unit *who) {} + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget()) + return; + + if( m_creature->getVictim() && m_creature->isAlive()) + { + if(!CombatStart) + { + //At combat Start Mandokir is mounted so we must unmount it first + m_creature->Unmount(); + + //And summon his raptor + m_creature->SummonCreature(14988, m_creature->getVictim()->GetPositionX(), m_creature->getVictim()->GetPositionY(), m_creature->getVictim()->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 35000); + CombatStart = true; + } + + if (Watch_Timer < diff) //Every 20 Sec Mandokir will check this + { + if(WatchTarget) //If someone is watched and If the Position of the watched target is different from the one stored, or are attacking, mandokir will charge him + { + Unit* pUnit = Unit::GetUnit(*m_creature, WatchTarget); + + if( pUnit && ( + targetX != pUnit->GetPositionX() || + targetY != pUnit->GetPositionY() || + targetZ != pUnit->GetPositionZ() || + pUnit->isInCombat())) + { + if(m_creature->IsWithinDistInMap(pUnit, ATTACK_DISTANCE)) + { + DoCast(pUnit,24316); + } + else + { + DoCast(pUnit,SPELL_CHARGE); + m_creature->SendMonsterMove(pUnit->GetPositionX(), pUnit->GetPositionY(), pUnit->GetPositionZ(), 0, true,1); + DoStartAttackAndMovement(pUnit); + } + } + } + someWatched = false; + Watch_Timer = 20000; + }else Watch_Timer -= diff; + + if ((Watch_Timer < 8000) && !someWatched) //8 sec(cast time + expire time) before the check for the watch effect mandokir will cast watch debuff on a random target + { + Unit* p = SelectUnit(SELECT_TARGET_RANDOM,0); + if(p) + { + DoYell(SAY_WATCH, LANG_UNIVERSAL, p); + DoCast(p, SPELL_WATCH); + WatchTarget = p->GetGUID(); + someWatched = true; + endWatch = true; + } + } + + if ((Watch_Timer < 1000) && endWatch) //1 sec before the debuf expire, store the target position + { + Unit* pUnit = Unit::GetUnit(*m_creature, WatchTarget); + if (pUnit) + { + targetX = pUnit->GetPositionX(); + targetY = pUnit->GetPositionY(); + targetZ = pUnit->GetPositionZ(); + } + endWatch = false; + } + + if(!someWatched) + { + //Cleave + if (Cleave_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_CLEAVE); + Cleave_Timer = 7000; + }else Cleave_Timer -= diff; + + //Whirlwind + if (Whirlwind_Timer < diff) + { + DoCast(m_creature,SPELL_WHIRLWIND); + Whirlwind_Timer = 18000; + }else Whirlwind_Timer -= diff; + + //If more then 3 targets in melee range mandokir will cast fear + if (Fear_Timer < diff) + { + TargetInRange = 0; + + std::list::iterator i = m_creature->getThreatManager().getThreatList().begin(); + for(; i != m_creature->getThreatManager().getThreatList().end(); ++i) + { + Unit* pUnit = Unit::GetUnit(*m_creature, (*i)->getUnitGuid()); + if(pUnit && m_creature->IsWithinDistInMap(pUnit, ATTACK_DISTANCE)) + TargetInRange++; + } + + if(TargetInRange > 3) + DoCast(m_creature->getVictim(),SPELL_FEAR); + + Fear_Timer = 4000; + }else Fear_Timer -=diff; + + //Mortal Strike if target below 50% hp + if (m_creature->getVictim()->GetHealth() < m_creature->getVictim()->GetMaxHealth()*0.5) + { + if (MortalStrike_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_MORTAL_STRIKE); + MortalStrike_Timer = 15000; + }else MortalStrike_Timer -= diff; + } + } + //Checking if Ohgan is dead. If yes Mandokir will enrage. + if(Check_Timer < diff) + { + if(pInstance) + { + if(pInstance->GetData(DATA_OHGANISDEAD)) + { + if (!RaptorDead) + { + DoCast(m_creature, SPELL_ENRAGE); + RaptorDead = true; + } + } + } + + Check_Timer = 1000; + }else Check_Timer -= diff; + + DoMeleeAttackIfReady(); + } + } +}; + +//Ohgan +struct MANGOS_DLL_DECL mob_ohganAI : public ScriptedAI +{ + mob_ohganAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + uint32 SunderArmor_Timer; + ScriptedInstance *pInstance; + + void Reset() + { + SunderArmor_Timer = 5000; + } + + void Aggro(Unit *who) {} + + void JustDied(Unit* Killer) + { + if(pInstance) + pInstance->SetData(DATA_OHGAN_DEATH, 0); + } + + void UpdateAI (const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //SunderArmor_Timer + if(SunderArmor_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_SUNDERARMOR); + SunderArmor_Timer = 10000 + rand()%5000; + }else SunderArmor_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_mandokir(Creature *_Creature) +{ + return new boss_mandokirAI (_Creature); +} + +CreatureAI* GetAI_mob_ohgan(Creature *_Creature) +{ + return new mob_ohganAI (_Creature); +} + +void AddSC_boss_mandokir() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_mandokir"; + newscript->GetAI = GetAI_boss_mandokir; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_ohgan"; + newscript->GetAI = GetAI_mob_ohgan; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/zulgurub/boss_marli.cpp b/src/bindings/scripts/scripts/zone/zulgurub/boss_marli.cpp new file mode 100644 index 00000000000..44bfc0973e8 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/zulgurub/boss_marli.cpp @@ -0,0 +1,269 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Marli +SD%Complete: 80 +SDComment: Charging healers and casters not working. Perhaps wrong Spell Timers. +SDCategory: Zul'Gurub +EndScriptData */ + +#include "precompiled.h" +#include "def_zulgurub.h" + +#define SPELL_CHARGE 22911 +#define SPELL_ASPECT_OF_MARLI 24686 // A stun spell +#define SPELL_ENVOLWINGWEB 24110 +#define SPELL_POISONVOLLEY 24099 +#define SPELL_SPIDER_FORM 24084 + +//The Spider Spells +#define SPELL_LEVELUP 24312 //Not right Spell. + +#define SAY_AGGRO "Draw me to your web mistress Shadra. Unleash your venom!" +#define SOUND_AGGRO 8418 + +#define SAY_DEATH "ShadraDeath - Bless you mortal for this release. Hakkar controls me no longer..." +#define SOUND_DEATH 8423 + +struct MANGOS_DLL_DECL boss_marliAI : public ScriptedAI +{ + boss_marliAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 SpawnStartSpiders_Timer; + uint32 PoisonVolley_Timer; + uint32 SpawnSpider_Timer; + uint32 Charge_Timer; + uint32 Aspect_Timer; + uint32 Transform_Timer; + uint32 TransformBack_Timer; + + Creature *Spider; + bool Spawned; + bool PhaseTwo; + + void Reset() + { + SpawnStartSpiders_Timer = 1000; + PoisonVolley_Timer = 15000; + SpawnSpider_Timer = 30000; + Charge_Timer = 1500; + Aspect_Timer = 12000; + Transform_Timer = 45000; + TransformBack_Timer = 25000; + + Spawned = false; + PhaseTwo = false; + + m_creature->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); + m_creature->ApplySpellImmune(1, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true); + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO); + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DEATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_DEATH); + ScriptedInstance *pInstance = (m_creature->GetInstanceData()) ? ((ScriptedInstance*)m_creature->GetInstanceData()) : NULL; + if(pInstance) + pInstance->SetData(DATA_MARLI_DEATH, 0); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget()) + return; + + if( m_creature->getVictim() && m_creature->isAlive()) + { + if (PoisonVolley_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_POISONVOLLEY); + PoisonVolley_Timer = 10000 + rand()%10000; + }else PoisonVolley_Timer -= diff; + + if (!PhaseTwo && Aspect_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_ASPECT_OF_MARLI); + Aspect_Timer = 13000 + rand()%5000; + }else Aspect_Timer -= diff; + + if (!Spawned && SpawnStartSpiders_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + + Spider = m_creature->SummonCreature(15041,target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if(target && Spider ) { Spider ->AI()->AttackStart(target); } + Spider = m_creature->SummonCreature(15041,target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if(target && Spider ) { Spider ->AI()->AttackStart(target); } + Spider = m_creature->SummonCreature(15041,target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if(target && Spider ) { Spider ->AI()->AttackStart(target); } + Spider = m_creature->SummonCreature(15041,target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if(target && Spider ) { Spider ->AI()->AttackStart(target); } + + Spawned = true; + }else SpawnStartSpiders_Timer -= diff; + + if (SpawnSpider_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + + Spider = m_creature->SummonCreature(15041,target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if(target && Spider ) { Spider ->AI()->AttackStart(target); } + + SpawnSpider_Timer = 12000 + rand()%5000; + }else SpawnSpider_Timer -= diff; + + if(!PhaseTwo && Transform_Timer < diff) + { + DoCast(m_creature,SPELL_SPIDER_FORM); + const CreatureInfo *cinfo = m_creature->GetCreatureInfo(); + m_creature->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 35))); + m_creature->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 35))); + m_creature->UpdateDamagePhysical(BASE_ATTACK); + DoCast(m_creature->getVictim(),SPELL_ENVOLWINGWEB); + + if(m_creature->getThreatManager().getThreat(m_creature->getVictim())) + m_creature->getThreatManager().modifyThreatPercent(m_creature->getVictim(),-100); + + PhaseTwo = true; + Transform_Timer = 35000 + rand()%25000; + }else Transform_Timer -= diff; + + if (PhaseTwo) + { + if (Charge_Timer < diff) + { + Unit* target = NULL; + int i = 0 ; + while (i < 3) // max 3 tries to get a random target with power_mana + { + ++i; //not aggro leader + target = SelectUnit(SELECT_TARGET_RANDOM,1); + if (target) + if (target->getPowerType() == POWER_MANA) + i=3; + } + if (target) + DoCast(target, SPELL_CHARGE); + // m_creature->Relocate(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0); + // m_creature->SendMonsterMove(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, true,1); + DoStartAttackAndMovement(target); + + Charge_Timer = 8000; + }else Charge_Timer -= diff; + + if (TransformBack_Timer < diff) + { + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID,15220); + const CreatureInfo *cinfo = m_creature->GetCreatureInfo(); + m_creature->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 1))); + m_creature->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 1))); + m_creature->UpdateDamagePhysical(BASE_ATTACK); + + PhaseTwo = false; + TransformBack_Timer = 25000 + rand()%15000; + }else TransformBack_Timer -= diff; + + } + + DoMeleeAttackIfReady(); + } + } +}; + +//Spawn of Marli +struct MANGOS_DLL_DECL mob_spawn_of_marliAI : public ScriptedAI +{ + mob_spawn_of_marliAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 LevelUp_Timer; + + void Reset() + { + LevelUp_Timer = 3000; + } + + void Aggro(Unit *who) + { + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || m_creature->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + float attackRadius = m_creature->GetAttackDistance(who); + if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) + { + if(who->HasStealthAura()) + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + DoStartAttackAndMovement(who); + } + } + } + + void UpdateAI (const uint32 diff) + { + //Return since we have no target + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //LevelUp_Timer + if(LevelUp_Timer < diff) + { + DoCast(m_creature,SPELL_LEVELUP); + LevelUp_Timer = 3000; + }else LevelUp_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_marli(Creature *_Creature) +{ + return new boss_marliAI (_Creature); +} + +CreatureAI* GetAI_mob_spawn_of_marli(Creature *_Creature) +{ + return new mob_spawn_of_marliAI (_Creature); +} + +void AddSC_boss_marli() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_marli"; + newscript->GetAI = GetAI_boss_marli; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_spawn_of_marli"; + newscript->GetAI = GetAI_mob_spawn_of_marli; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/zulgurub/boss_renataki.cpp b/src/bindings/scripts/scripts/zone/zulgurub/boss_renataki.cpp new file mode 100644 index 00000000000..f7e31309b59 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/zulgurub/boss_renataki.cpp @@ -0,0 +1,151 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Renataki +SD%Complete: 100 +SDComment: +SDCategory: Zul'Gurub +EndScriptData */ + +#include "precompiled.h" +#include "def_zulgurub.h" + +#define SPELL_AMBUSH 24337 +#define SPELL_THOUSANDBLADES 24649 + +struct MANGOS_DLL_DECL boss_renatakiAI : public ScriptedAI +{ + boss_renatakiAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Invisible_Timer; + uint32 Ambush_Timer; + uint32 Visible_Timer; + uint32 Aggro_Timer; + uint32 ThousandBlades_Timer; + + bool Invisible; + bool Ambushed; + + void Reset() + { + Invisible_Timer = 8000 + rand()%10000; + Ambush_Timer = 3000; + Visible_Timer = 4000; + Aggro_Timer = 15000 + rand()%10000; + ThousandBlades_Timer = 4000 + rand()%4000; + + Invisible = false; + Ambushed = false; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //Invisible_Timer + if (Invisible_Timer < diff) + { + m_creature->InterruptSpell(CURRENT_GENERIC_SPELL); + m_creature->SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 0); + m_creature->SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO , 218171138); + m_creature->SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + 1, 3); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID,11686); + Invisible = true; + + Invisible_Timer = 15000 + rand()%15000; + }else Invisible_Timer -= diff; + + if (Invisible) + { + if (Ambush_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) + { + m_creature->Relocate(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0); + m_creature->SendMonsterMove(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, true,1); + DoCast(target,SPELL_AMBUSH); + } + + Ambushed = true; + Ambush_Timer = 3000; + }else Ambush_Timer -= diff; + } + + if (Ambushed) + { + if (Visible_Timer < diff) + { + m_creature->InterruptSpell(CURRENT_GENERIC_SPELL); + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID,15268); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 31818); + m_creature->SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO , 218171138); + m_creature->SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + 1, 3); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Invisible = false; + + Visible_Timer = 4000; + }else Visible_Timer -= diff; + } + + //Resetting some aggro so he attacks other gamers + if(!Invisible) + if (Aggro_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,1); + + if(m_creature->getThreatManager().getThreat(m_creature->getVictim())) + m_creature->getThreatManager().modifyThreatPercent(m_creature->getVictim(),-50); + + if (target) + DoStartAttackAndMovement(target); + + Aggro_Timer = 7000 + rand()%13000; + }else Aggro_Timer -= diff; + + if (!Invisible) + if(ThousandBlades_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_THOUSANDBLADES); + ThousandBlades_Timer = 7000 + rand()%5000; + }else ThousandBlades_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_renataki(Creature *_Creature) +{ + return new boss_renatakiAI (_Creature); +} + +void AddSC_boss_renataki() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_renataki"; + newscript->GetAI = GetAI_boss_renataki; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/zulgurub/boss_thekal.cpp b/src/bindings/scripts/scripts/zone/zulgurub/boss_thekal.cpp new file mode 100644 index 00000000000..91d0d6a290c --- /dev/null +++ b/src/bindings/scripts/scripts/zone/zulgurub/boss_thekal.cpp @@ -0,0 +1,545 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Thekal +SD%Complete: 95 +SDComment: Almost finished. +SDCategory: Zul'Gurub +EndScriptData */ + +#include "precompiled.h" +#include "def_zulgurub.h" + +#define SPELL_MORTALCLEAVE 22859 +#define SPELL_SILENCE 23207 +#define SPELL_FRENZY 23342 +#define SPELL_FORCEPUNCH 24189 +#define SPELL_CHARGE 24408 +#define SPELL_ENRAGE 23537 +#define SPELL_SUMMONTIGERS 24183 +#define SPELL_TIGER_FORM 24169 +#define SPELL_RESURRECT 24173 //We will not use this spell. + +//Zealot Lor'Khan Spells +#define SPELL_SHIELD 25020 +#define SPELL_BLOODLUST 24185 +#define SPELL_GREATERHEAL 24208 +#define SPELL_DISARM 22691 + +//Zealot Lor'Khan Spells +#define SPELL_SWEEPINGSTRIKES 18765 +#define SPELL_SINISTERSTRIKE 15667 +#define SPELL_GOUGE 24698 +#define SPELL_KICK 15614 +#define SPELL_BLIND 21060 + +#define SAY_AGGRO "Shirvallah fill me with your rage!" +#define SOUND_AGGRO 8419 + +#define SAY_DEATH "Hakkar binds me no more. Peace at last." +#define SOUND_DEATH 8424 + +struct MANGOS_DLL_DECL boss_thekalAI : public ScriptedAI +{ + boss_thekalAI(Creature *c) : ScriptedAI(c) + { + pInstance = (c->GetInstanceData()) ? ((ScriptedInstance*)c->GetInstanceData()) : NULL; + Reset(); + } + + uint32 MortalCleave_Timer; + uint32 Silence_Timer; + uint32 Frenzy_Timer; + uint32 ForcePunch_Timer; + uint32 Charge_Timer; + uint32 Enrage_Timer; + uint32 SummonTigers_Timer; + uint32 Check_Timer; + uint32 Resurrect_Timer; + + ScriptedInstance *pInstance; + bool Enraged; + bool PhaseTwo; + bool WasDead; + + void Reset() + { + MortalCleave_Timer = 4000; + Silence_Timer = 9000; + Frenzy_Timer = 30000; + ForcePunch_Timer = 4000; + Charge_Timer = 12000; + Enrage_Timer = 32000; + SummonTigers_Timer = 25000; + Check_Timer = 10000; + Resurrect_Timer = 10000; + + Enraged = false; + PhaseTwo = false; + WasDead = false; + + if(pInstance) + pInstance->SetData(DATA_THEKAL_ALIVE, 0); + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO); + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DEATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_DEATH); + ScriptedInstance *pInstance = (m_creature->GetInstanceData()) ? ((ScriptedInstance*)m_creature->GetInstanceData()) : NULL; + if(pInstance) + pInstance->SetData(DATA_THEKAL_DEATH, 0); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget()) + return; + + if( m_creature->getVictim() && m_creature->isAlive()) + { + + //Check_Timer for the death of LorKhan and Zath. + if(!WasDead && Check_Timer < diff) + { + if(pInstance) + { + if(pInstance->GetData(DATA_LORKHANISDEAD)) + { + //Resurrect LorKhan + Unit *pLorKhan = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_LORKHAN)); + pLorKhan->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + pLorKhan->setFaction(14); + pLorKhan->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pLorKhan->SetHealth(int(pLorKhan->GetMaxHealth()*1.0)); + } + + if(pInstance->GetData(DATA_ZATHISDEAD)) + { + //Resurrect Zath + Unit *pZath = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_ZATH)); + pZath->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + pZath->setFaction(14); + pZath->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pZath->SetHealth(int(pZath->GetMaxHealth()*1.0)); + } + } + + Check_Timer = 5000; + }else Check_Timer -= diff; + + if (!PhaseTwo && MortalCleave_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_MORTALCLEAVE); + MortalCleave_Timer = 15000 + rand()%5000; + }else MortalCleave_Timer -= diff; + + if (!PhaseTwo && Silence_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SILENCE); + Silence_Timer = 20000 + rand()%5000; + }else Silence_Timer -= diff; + + if (!PhaseTwo && !WasDead && m_creature->GetHealth() <= m_creature->GetMaxHealth() * 0.05) + { + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 3); + m_creature->AttackStop(); + + if(pInstance) + pInstance->SetData(DATA_THEKALFAKE_DEATH, 0); + + WasDead=true; + } + + //Thekal will transform to Tiger if he died and was not resurrected after 10 seconds. + if(!PhaseTwo && WasDead) + { + if (Resurrect_Timer < diff) + { + DoCast(m_creature,SPELL_TIGER_FORM); + m_creature->SetFloatValue(OBJECT_FIELD_SCALE_X, 2.00f); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetHealth(int(m_creature->GetMaxHealth()*1.0)); + const CreatureInfo *cinfo = m_creature->GetCreatureInfo(); + m_creature->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 40))); + m_creature->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 40))); + m_creature->UpdateDamagePhysical(BASE_ATTACK); + DoResetThreat(); + PhaseTwo = true; + }else Resurrect_Timer -= diff; + } + + if ((m_creature->GetHealth()*100 / m_creature->GetMaxHealth() == 100) && WasDead) + { + WasDead = false; + } + + if (PhaseTwo) + { + if (Charge_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + + DoCast(target,SPELL_CHARGE); + m_creature->SendMonsterMove(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, true,1); + DoStartAttackAndMovement(target); + DoResetThreat(); + + Charge_Timer = 15000 + rand()%7000; + }else Charge_Timer -= diff; + + if (Frenzy_Timer < diff) + { + DoCast(m_creature,SPELL_FRENZY); + Frenzy_Timer = 30000; + }else Frenzy_Timer -= diff; + + if (ForcePunch_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SILENCE); + ForcePunch_Timer = 16000 + rand()%5000; + }else ForcePunch_Timer -= diff; + + if (SummonTigers_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SUMMONTIGERS); + SummonTigers_Timer = 10000 + rand()%4000; + }else SummonTigers_Timer -= diff; + + if ((m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 11) && !Enraged) + { + DoCast(m_creature, SPELL_ENRAGE); + Enraged = true; + } + } + + DoMeleeAttackIfReady(); + } + } +}; + +//Zealot Lor'Khan +struct MANGOS_DLL_DECL mob_zealot_lorkhanAI : public ScriptedAI +{ + mob_zealot_lorkhanAI(Creature *c) : ScriptedAI(c) + { + pInstance = (c->GetInstanceData()) ? ((ScriptedInstance*)c->GetInstanceData()) : NULL; + Reset(); + } + + uint32 Shield_Timer; + uint32 BloodLust_Timer; + uint32 GreaterHeal_Timer; + uint32 Disarm_Timer; + uint32 Check_Timer; + + bool FakeDeath; + + ScriptedInstance *pInstance; + + void Reset() + { + Shield_Timer = 1000; + BloodLust_Timer = 16000; + GreaterHeal_Timer = 32000; + Disarm_Timer = 6000; + Check_Timer = 10000; + + FakeDeath = false; + + if(pInstance) + pInstance->SetData(DATA_LORKHAN_ALIVE, 0); + + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void Aggro(Unit *who) + { + } + + void UpdateAI (const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //Shield_Timer + if(Shield_Timer < diff) + { + DoCast(m_creature,SPELL_SHIELD); + Shield_Timer = 61000; + }else Shield_Timer -= diff; + + //BloodLust_Timer + if(BloodLust_Timer < diff) + { + DoCast(m_creature,SPELL_BLOODLUST); + BloodLust_Timer = 20000+rand()%8000; + }else BloodLust_Timer -= diff; + + //Casting Greaterheal to Thekal or Zath if they are in meele range. + if(GreaterHeal_Timer < diff) + { + if(pInstance) + { + Unit *pThekal = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_THEKAL)); + Unit *pZath = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_ZATH)); + + switch(rand()%2) + { + case 0: + if(m_creature->IsWithinDistInMap(pThekal, ATTACK_DISTANCE)) + DoCast(pThekal, SPELL_GREATERHEAL); + break; + case 1: + if(m_creature->IsWithinDistInMap(pZath, ATTACK_DISTANCE)) + DoCast(pZath, SPELL_GREATERHEAL); + break; + } + } + + GreaterHeal_Timer = 15000+rand()%5000; + }else GreaterHeal_Timer -= diff; + + //Disarm_Timer + if(Disarm_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_DISARM); + Disarm_Timer = 15000+rand()%10000; + }else Disarm_Timer -= diff; + + //Check_Timer for the death of LorKhan and Zath. + if(!FakeDeath && Check_Timer < diff) + { + if(pInstance) + { + if(pInstance->GetData(DATA_THEKALISFAKEDEAD)) + { + //Resurrect Thekal + Unit *pThekal = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_THEKAL)); + pThekal->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + pThekal->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pThekal->setFaction(14); + pThekal->SetHealth(int(pThekal->GetMaxHealth()*1.0)); + } + + if(pInstance->GetData(DATA_ZATHISDEAD)) + { + //Resurrect Zath + Unit *pZath = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_ZATH)); + pZath->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + pZath->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pZath->setFaction(14); + pZath->SetHealth(int(pZath->GetMaxHealth()*1.0)); + } + } + + Check_Timer = 5000; + }else Check_Timer -= diff; + + if (m_creature->GetHealth() <= m_creature->GetMaxHealth() * 0.05) + { + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 3); + m_creature->setFaction(35); + m_creature->AttackStop(); + + if(pInstance) + pInstance->SetData(DATA_LORKHAN_DEATH, 0); + + FakeDeath = true; + } + + DoMeleeAttackIfReady(); + } +}; + +//Zealot Zath +struct MANGOS_DLL_DECL mob_zealot_zathAI : public ScriptedAI +{ + mob_zealot_zathAI(Creature *c) : ScriptedAI(c) + { + pInstance = (c->GetInstanceData()) ? ((ScriptedInstance*)c->GetInstanceData()) : NULL; + Reset(); + } + + uint32 SweepingStrikes_Timer; + uint32 SinisterStrike_Timer; + uint32 Gouge_Timer; + uint32 Kick_Timer; + uint32 Blind_Timer; + uint32 Check_Timer; + + bool FakeDeath; + + ScriptedInstance *pInstance; + + void Reset() + { + SweepingStrikes_Timer = 13000; + SinisterStrike_Timer = 8000; + Gouge_Timer = 25000; + Kick_Timer = 18000; + Blind_Timer = 5000; + Check_Timer = 10000; + + FakeDeath = false; + + if(pInstance) + pInstance->SetData(DATA_ZATH_ALIVE, 0); + + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void Aggro(Unit *who) + { + } + + void UpdateAI (const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; + + //SweepingStrikes_Timer + if(SweepingStrikes_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SWEEPINGSTRIKES); + SweepingStrikes_Timer = 22000+rand()%4000; + }else SweepingStrikes_Timer -= diff; + + //SinisterStrike_Timer + if(SinisterStrike_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_SINISTERSTRIKE); + SinisterStrike_Timer = 8000+rand()%8000; + }else SinisterStrike_Timer -= diff; + + //Gouge_Timer + if(Gouge_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_GOUGE); + + if(m_creature->getThreatManager().getThreat(m_creature->getVictim())) + m_creature->getThreatManager().modifyThreatPercent(m_creature->getVictim(),-100); + + Gouge_Timer = 17000+rand()%10000; + }else Gouge_Timer -= diff; + + //Kick_Timer + if(Kick_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_KICK); + Kick_Timer = 15000+rand()%10000; + }else Kick_Timer -= diff; + + //Blind_Timer + if(Blind_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_BLIND); + Blind_Timer = 10000+rand()%10000; + }else Blind_Timer -= diff; + + //Check_Timer for the death of LorKhan and Zath. + if(!FakeDeath && Check_Timer < diff) + { + if(pInstance) + { + if(pInstance->GetData(DATA_LORKHANISDEAD)) + { + //Resurrect LorKhan + Unit *pLorKhan = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_LORKHAN)); + pLorKhan->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + pLorKhan->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pLorKhan->setFaction(14); + pLorKhan->SetHealth(int(pLorKhan->GetMaxHealth()*1.0)); + } + + if(pInstance->GetData(DATA_THEKALISFAKEDEAD)) + { + //Resurrect Thekal + Unit *pThekal = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_THEKAL)); + pThekal->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + pThekal->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pThekal->setFaction(14); + pThekal->SetHealth(int(pThekal->GetMaxHealth()*1.0)); + } + } + + Check_Timer = 5000; + }else Check_Timer -= diff; + + if (m_creature->GetHealth() <= m_creature->GetMaxHealth() * 0.05) + { + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 3); + m_creature->setFaction(35); + m_creature->AttackStop(); + + if(pInstance) + pInstance->SetData(DATA_ZATH_DEATH, 0); + + FakeDeath = true; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_thekal(Creature *_Creature) +{ + return new boss_thekalAI (_Creature); +} + +CreatureAI* GetAI_mob_zealot_lorkhan(Creature *_Creature) +{ + return new mob_zealot_lorkhanAI (_Creature); +} + +CreatureAI* GetAI_mob_zealot_zath(Creature *_Creature) +{ + return new mob_zealot_zathAI (_Creature); +} + +void AddSC_boss_thekal() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_thekal"; + newscript->GetAI = GetAI_boss_thekal; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_zealot_lorkhan"; + newscript->GetAI = GetAI_mob_zealot_lorkhan; + m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name="mob_zealot_zath"; + newscript->GetAI = GetAI_mob_zealot_zath; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/zulgurub/boss_venoxis.cpp b/src/bindings/scripts/scripts/zone/zulgurub/boss_venoxis.cpp new file mode 100644 index 00000000000..a2405ec9c6f --- /dev/null +++ b/src/bindings/scripts/scripts/zone/zulgurub/boss_venoxis.cpp @@ -0,0 +1,200 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Venoxis +SD%Complete: 100 +SDComment: +SDCategory: Zul'Gurub +EndScriptData */ + +#include "precompiled.h" +#include "def_zulgurub.h" + +#define SPELL_HOLY_FIRE 23860 +#define SPELL_HOLY_WRATH 28883 //Not sure if this or 23979 +#define SPELL_VENOMSPIT 23862 +#define SPELL_HOLY_NOVA 23858 +#define SPELL_POISON_CLOUD 23861 +#define SPELL_SNAKE_FORM 23849 +#define SPELL_RENEW 23895 +#define SPELL_BERSERK 23537 +#define SPELL_DISPELL 23859 + +#define SAY_AGGRO "Let the coils of hate unfurl!" +#define SOUND_AGGRO 8421 + +struct MANGOS_DLL_DECL boss_venoxisAI : public ScriptedAI +{ + boss_venoxisAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 HolyFire_Timer; + uint32 HolyWrath_Timer; + uint32 VenomSpit_Timer; + uint32 Renew_Timer; + uint32 PoisonCloud_Timer; + uint32 HolyNova_Timer; + uint32 Dispell_Timer; + uint32 TargetInRange; + + bool PhaseTwo; + bool InBerserk; + + void Reset() + { + HolyFire_Timer = 10000; + HolyWrath_Timer = 60500; + VenomSpit_Timer = 5500; + Renew_Timer = 30500; + PoisonCloud_Timer = 2000; + HolyNova_Timer = 5000; + Dispell_Timer = 35000; + TargetInRange = 0; + + PhaseTwo = false; + InBerserk= false; + } + + void Aggro(Unit *who) + { + DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(m_creature,SOUND_AGGRO); + } + + void JustDied(Unit* Killer) + { + ScriptedInstance *pInstance = (m_creature->GetInstanceData()) ? ((ScriptedInstance*)m_creature->GetInstanceData()) : NULL; + if(pInstance) + pInstance->SetData(DATA_VENOXIS_DEATH, 0); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget()) + return; + + if( m_creature->getVictim() && m_creature->isAlive()) + { + if ((m_creature->GetHealth()*100 / m_creature->GetMaxHealth() > 50)) + { + if (Dispell_Timer < diff) + { + DoCast(m_creature, SPELL_DISPELL); + Dispell_Timer = 15000 + rand()%15000; + }else Dispell_Timer -= diff; + + if (Renew_Timer < diff) + { + DoCast(m_creature, SPELL_RENEW); + Renew_Timer = 20000 + rand()%10000; + }else Renew_Timer -= diff; + + if (HolyWrath_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_HOLY_WRATH); + HolyWrath_Timer = 15000 + rand()%10000; + }else HolyWrath_Timer -= diff; + + if (HolyNova_Timer < diff) + { + Unit* target = NULL; + TargetInRange = 0; + for(int i=0; i<10; i++) + { + target = SelectUnit(SELECT_TARGET_TOPAGGRO,i); + if(target) + if(m_creature->IsWithinDistInMap(target, ATTACK_DISTANCE)) + TargetInRange++; + } + + if(TargetInRange > 1) + { + DoCast(m_creature->getVictim(),SPELL_HOLY_NOVA); + HolyNova_Timer = 1000; + } + else + { + HolyNova_Timer = 2000; + } + + }else HolyNova_Timer -= diff; + + if (HolyFire_Timer < diff && TargetInRange < 3) + { + Unit* targetrandom = NULL; + targetrandom = SelectUnit(SELECT_TARGET_RANDOM,0); + + DoCast(targetrandom, SPELL_HOLY_FIRE); + HolyFire_Timer = 8000; + }else HolyFire_Timer -= diff; + } + else + { + if(!PhaseTwo) + { + m_creature->InterruptNonMeleeSpells(false); + DoCast(m_creature,SPELL_SNAKE_FORM); + m_creature->SetFloatValue(OBJECT_FIELD_SCALE_X, 2.00f); + const CreatureInfo *cinfo = m_creature->GetCreatureInfo(); + m_creature->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 25))); + m_creature->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 25))); + m_creature->UpdateDamagePhysical(BASE_ATTACK); + DoResetThreat(); + PhaseTwo = true; + } + + if(PhaseTwo && PoisonCloud_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_POISON_CLOUD); + PoisonCloud_Timer = 15000; + }PoisonCloud_Timer -=diff; + + if (PhaseTwo && VenomSpit_Timer < diff) + { + Unit* targetrandom = NULL; + targetrandom = SelectUnit(SELECT_TARGET_RANDOM,0); + + DoCast(targetrandom, SPELL_VENOMSPIT); + VenomSpit_Timer = 15000 + rand()%5000; + }else VenomSpit_Timer -= diff; + + if (PhaseTwo && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 11)) + { + if (!InBerserk) + { + m_creature->InterruptNonMeleeSpells(false); + DoCast(m_creature, SPELL_BERSERK); + InBerserk = true; + } + } + } + DoMeleeAttackIfReady(); + } + } +}; +CreatureAI* GetAI_boss_venoxis(Creature *_Creature) +{ + return new boss_venoxisAI (_Creature); +} + +void AddSC_boss_venoxis() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_venoxis"; + newscript->GetAI = GetAI_boss_venoxis; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/zulgurub/boss_wushoolay.cpp b/src/bindings/scripts/scripts/zone/zulgurub/boss_wushoolay.cpp new file mode 100644 index 00000000000..c94c665c1cb --- /dev/null +++ b/src/bindings/scripts/scripts/zone/zulgurub/boss_wushoolay.cpp @@ -0,0 +1,84 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Wushoolay +SD%Complete: 100 +SDComment: +SDCategory: Zul'Gurub +EndScriptData */ + +#include "precompiled.h" +#include "def_zulgurub.h" + +#define SPELL_LIGHTNINGCLOUD 25033 +#define SPELL_LIGHTNINGWAVE 24819 + +struct MANGOS_DLL_DECL boss_wushoolayAI : public ScriptedAI +{ + boss_wushoolayAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 LightningCloud_Timer; + uint32 LightningWave_Timer; + + void Reset() + { + LightningCloud_Timer = 5000 + rand()%5000; + LightningWave_Timer = 8000 + rand()%8000; + } + + void Aggro(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + //LightningCloud_Timer + if (LightningCloud_Timer < diff) + { + DoCast(m_creature->getVictim(),SPELL_LIGHTNINGCLOUD); + LightningCloud_Timer = 15000 + rand()%5000; + }else LightningCloud_Timer -= diff; + + //LightningWave_Timer + if (LightningWave_Timer < diff) + { + Unit* target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (target) DoCast(target,SPELL_LIGHTNINGWAVE); + + LightningWave_Timer = 12000 + rand()%4000; + }else LightningWave_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_wushoolay(Creature *_Creature) +{ + return new boss_wushoolayAI (_Creature); +} + +void AddSC_boss_wushoolay() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_wushoolay"; + newscript->GetAI = GetAI_boss_wushoolay; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/scripts/zone/zulgurub/def_zulgurub.h b/src/bindings/scripts/scripts/zone/zulgurub/def_zulgurub.h new file mode 100644 index 00000000000..0dcbb83c4df --- /dev/null +++ b/src/bindings/scripts/scripts/zone/zulgurub/def_zulgurub.h @@ -0,0 +1,36 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_ZULGURUB_H +#define DEF_ZULGURUB_H + +#define DATA_ARLOKKISDEAD 1 +#define DATA_ARLOKK_DEATH 2 +#define DATA_JEKLIKISDEAD 3 +#define DATA_JEKLIK_DEATH 4 +#define DATA_JINDO 5 +#define DATA_LORKHAN 6 +#define DATA_LORKHANISALIVE 7 +#define DATA_LORKHANISDEAD 8 +#define DATA_LORKHAN_ALIVE 9 +#define DATA_LORKHAN_DEATH 10 +#define DATA_MARLIISDEAD 11 +#define DATA_MARLI_DEATH 12 +#define DATA_OHGANISDEAD 13 +#define DATA_OHGAN_DEATH 14 +#define DATA_THEKAL 15 +#define DATA_THEKALFAKE_DEATH 16 +#define DATA_THEKALISALIVE 17 +#define DATA_THEKALISDEAD 18 +#define DATA_THEKALISFAKEDEAD 19 +#define DATA_THEKAL_ALIVE 20 +#define DATA_THEKAL_DEATH 21 +#define DATA_VENOXISISDEAD 22 +#define DATA_VENOXIS_DEATH 23 +#define DATA_ZATH 24 +#define DATA_ZATHISALIVE 25 +#define DATA_ZATHISDEAD 26 +#define DATA_ZATH_ALIVE 27 +#define DATA_ZATH_DEATH 28 +#endif diff --git a/src/bindings/scripts/scripts/zone/zulgurub/instance_zulgurub.cpp b/src/bindings/scripts/scripts/zone/zulgurub/instance_zulgurub.cpp new file mode 100644 index 00000000000..d0573414143 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/zulgurub/instance_zulgurub.cpp @@ -0,0 +1,238 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_ZulGurub +SD%Complete: 80 +SDComment: Missing reset function after killing a boss for Ohgan, Thekal. +SDCategory: Zul'Gurub +EndScriptData */ + +#include "precompiled.h" +#include "def_zulgurub.h" + +struct MANGOS_DLL_DECL instance_zulgurub : public ScriptedInstance +{ + instance_zulgurub(Map *Map) : ScriptedInstance(Map) {Initialize();}; + + //If all High Priest bosses were killed. Lorkhan, Zath and Ohgan are added too. + bool IsBossDied[9]; + + //Storing Lorkhan, Zath and Thekal because we need to cast on them later. Jindo is needed for healfunction too. + uint64 LorKhanGUID; + uint64 ZathGUID; + uint64 ThekalGUID; + uint64 JindoGUID; + + void OnCreatureCreate (Creature *creature, uint32 creature_entry) + { + switch (creature_entry) + { + case 11347: + LorKhanGUID = creature->GetGUID(); + break; + + case 11348: + ZathGUID = creature->GetGUID(); + break; + + case 14509: + ThekalGUID = creature->GetGUID(); + break; + + case 11380: + JindoGUID = creature->GetGUID(); + break; + } + } + + void Initialize() + { + IsBossDied[0] = false; + IsBossDied[1] = false; + IsBossDied[2] = false; + IsBossDied[3] = false; + IsBossDied[4] = false; + IsBossDied[5] = false; + IsBossDied[6] = false; + + IsBossDied[7] = false; + IsBossDied[8] = false; + } + + bool IsEncounterInProgress() const + { + //not active in Zul'Gurub + return false; + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_JEKLIKISDEAD: + if(IsBossDied[0]) + return 1; + break; + + case DATA_VENOXISISDEAD: + if(IsBossDied[1]) + return 1; + break; + + case DATA_MARLIISDEAD: + if(IsBossDied[2]) + return 1; + break; + + case DATA_THEKALISDEAD: + if(IsBossDied[3]) + return 1; + break; + + case DATA_ARLOKKISDEAD: + if(IsBossDied[4]) + return 1; + break; + + case DATA_LORKHANISDEAD: + if(IsBossDied[5]) + return 1; + break; + + case DATA_ZATHISDEAD: + if(IsBossDied[6]) + return 1; + break; + + case DATA_THEKALISFAKEDEAD: + if(IsBossDied[7]) + return 1; + break; + + case DATA_OHGANISDEAD: + if(IsBossDied[8]) + return 1; + break; + + //Boss is not dead. Resetting function for some bosses after killing them but whiping at the complete encounter. + + case DATA_THEKALISALIVE: + if(IsBossDied[3]) + return 0; + break; + + case DATA_LORKHANISALIVE: + if(IsBossDied[5]) + return 0; + break; + + case DATA_ZATHISALIVE: + if(IsBossDied[6]) + return 0; + break; + } + + return 0; + } + + uint64 GetData64 (uint32 identifier) + { + switch(identifier) + { + case DATA_LORKHAN: + return LorKhanGUID; + + case DATA_ZATH: + return ZathGUID; + + case DATA_THEKAL: + return ThekalGUID; + + case DATA_JINDO: + return JindoGUID; + } + return 0; + } // end GetData64 + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_JEKLIK_DEATH: + IsBossDied[0] = true; + break; + + case DATA_VENOXIS_DEATH: + IsBossDied[1] = true; + break; + + case DATA_MARLI_DEATH: + IsBossDied[2] = true; + break; + + case DATA_THEKAL_DEATH: + IsBossDied[3] = true; + break; + + case DATA_ARLOKK_DEATH: + IsBossDied[4] = true; + break; + + case DATA_LORKHAN_DEATH: + IsBossDied[5] = true; + break; + + case DATA_ZATH_DEATH: + IsBossDied[6] = true; + break; + + case DATA_THEKALFAKE_DEATH: + IsBossDied[7] = true; + break; + + case DATA_OHGAN_DEATH: + IsBossDied[8] = true; + break; + + case DATA_LORKHAN_ALIVE: + IsBossDied[5] = false; + break; + + case DATA_ZATH_ALIVE: + IsBossDied[6] = false; + break; + + case DATA_THEKAL_ALIVE: + IsBossDied[7] = false; + break; + } + } +}; + +InstanceData* GetInstanceData_instance_zulgurub(Map* map) +{ + return new instance_zulgurub(map); +} + +void AddSC_instance_zulgurub() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_zulgurub"; + newscript->GetInstanceData = GetInstanceData_instance_zulgurub; + m_scripts[nrscripts++] = newscript; +} diff --git a/src/bindings/scripts/sql/Makefile.am b/src/bindings/scripts/sql/Makefile.am new file mode 100644 index 00000000000..27d64eb6f6e --- /dev/null +++ b/src/bindings/scripts/sql/Makefile.am @@ -0,0 +1,31 @@ +# Copyright (C) 2005,2006,2007 MaNGOS +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## Process this file with automake to produce Makefile.in + +## Sub-directories to parse +SUBDIRS = Updates + +## Change installation location +# datadir = scriptdev2/sql +pkgdatadir = $(datadir)/scriptdev2/sql + +## Files to be installed +# Install basic SQL files to datadir +pkgdata_DATA = \ + create_database.sql \ + mangos_full_scripts.sql \ + scriptdev2_structure.sql diff --git a/src/bindings/scripts/sql/Makefile.in b/src/bindings/scripts/sql/Makefile.in new file mode 100644 index 00000000000..a07a30e0826 --- /dev/null +++ b/src/bindings/scripts/sql/Makefile.in @@ -0,0 +1,540 @@ +# Makefile.in generated by automake 1.9.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Copyright (C) 2005,2006,2007 MaNGOS +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../../../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/bindings/ScriptDev2/sql +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-exec-recursive install-info-recursive \ + install-recursive installcheck-recursive installdirs-recursive \ + pdf-recursive ps-recursive uninstall-info-recursive \ + uninstall-recursive +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(pkgdatadir)" +pkgdataDATA_INSTALL = $(INSTALL_DATA) +DATA = $(pkgdata_DATA) +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +# datadir = scriptdev2/sql +pkgdatadir = $(datadir)/scriptdev2/sql +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COMPATLIB = @COMPATLIB@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DOXYGENPATH = @DOXYGENPATH@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ +MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ +MAKEINFO = @MAKEINFO@ +MANGOSD_DEBUG_INFO = @MANGOSD_DEBUG_INFO@ +MANGOSD_ENABLE_CLI = @MANGOSD_ENABLE_CLI@ +MANGOSD_ENABLE_RA = @MANGOSD_ENABLE_RA@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_INCLUDES = @MYSQL_INCLUDES@ +MYSQL_LIBS = @MYSQL_LIBS@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSLLIB = @SSLLIB@ +STRIP = @STRIP@ +USE_DOXYGEN_FALSE = @USE_DOXYGEN_FALSE@ +USE_DOXYGEN_TRUE = @USE_DOXYGEN_TRUE@ +VERSION = @VERSION@ +ZLIB = @ZLIB@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +SUBDIRS = Updates + +# Install basic SQL files to datadir +pkgdata_DATA = \ + scripts.sql + +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/bindings/ScriptDev2/sql/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/bindings/ScriptDev2/sql/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: +install-pkgdataDATA: $(pkgdata_DATA) + @$(NORMAL_INSTALL) + test -z "$(pkgdatadir)" || $(mkdir_p) "$(DESTDIR)$(pkgdatadir)" + @list='$(pkgdata_DATA)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(pkgdataDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgdatadir)/$$f'"; \ + $(pkgdataDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgdatadir)/$$f"; \ + done + +uninstall-pkgdataDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgdata_DATA)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(pkgdatadir)/$$f'"; \ + rm -f "$(DESTDIR)$(pkgdatadir)/$$f"; \ + done + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || $(mkdir_p) "$(distdir)/$$subdir" \ + || exit 1; \ + distdir=`$(am__cd) $(distdir) && pwd`; \ + top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$top_distdir" \ + distdir="$$distdir/$$subdir" \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(DATA) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(pkgdatadir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-libtool \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +info: info-recursive + +info-am: + +install-data-am: install-pkgdataDATA + +install-exec-am: + +install-info: install-info-recursive + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-info-am uninstall-pkgdataDATA + +uninstall-info: uninstall-info-recursive + +.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am \ + clean clean-generic clean-libtool clean-recursive ctags \ + ctags-recursive distclean distclean-generic distclean-libtool \ + distclean-recursive distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-pkgdataDATA install-strip \ + installcheck installcheck-am installdirs installdirs-am \ + maintainer-clean maintainer-clean-generic \ + maintainer-clean-recursive mostlyclean mostlyclean-generic \ + mostlyclean-libtool mostlyclean-recursive pdf pdf-am ps ps-am \ + tags tags-recursive uninstall uninstall-am uninstall-info-am \ + uninstall-pkgdataDATA + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/bindings/scripts/sql/Updates/09_BraveWindfeather.sql b/src/bindings/scripts/sql/Updates/09_BraveWindfeather.sql new file mode 100644 index 00000000000..ae78c707323 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/09_BraveWindfeather.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET`ScriptName` = '' WHERE `entry` = 3209; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/11_SilvaFilnaveth.sql b/src/bindings/scripts/sql/Updates/11_SilvaFilnaveth.sql new file mode 100644 index 00000000000..9900466b717 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/11_SilvaFilnaveth.sql @@ -0,0 +1 @@ +UPDATE `creature` SET `id` = 11798, `curhealth` = 3857 WHERE `guid` = 46833; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/27_Vaelastraz.sql b/src/bindings/scripts/sql/Updates/27_Vaelastraz.sql new file mode 100644 index 00000000000..e57ed2107d9 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/27_Vaelastraz.sql @@ -0,0 +1,2 @@ +UPDATE creature_template SET faction=35 WHERE entry=13020; +UPDATE creature_template SET npcflag=65 WHERE entry=13020; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/Makefile.am b/src/bindings/scripts/sql/Updates/Makefile.am new file mode 100644 index 00000000000..e8389337a6a --- /dev/null +++ b/src/bindings/scripts/sql/Updates/Makefile.am @@ -0,0 +1,215 @@ +# Copyright (C) 2005,2006,2007 MaNGOS +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## Process this file with automake to produce Makefile.in + +## Sub-directories to parse + +## Change installation location +# datadir = scriptdev2/sql/updates +pkgdatadir = $(datadir)/scriptdev2/sql/updates + +## Files to be installed +# Install basic SQL files to datadir +pkgdata_DATA = \ + 09_BraveWindfeather.sql \ + 11_SilvaFilnaveth.sql \ + 27_Vaelastraz.sql \ + r56.sql \ + r59.sql \ + r63.sql \ + r65.sql \ + r72.sql \ + r78.sql \ + r81.sql \ + r91.sql \ + r92.sql \ + r97.sql \ + r108.sql \ + r110.sql \ + r121.sql \ + r123.sql \ + r124.sql \ + r125.sql \ + r128.sql \ + r131.sql \ + r134.sql \ + r136.sql \ + r139.sql \ + r142.sql \ + r144.sql \ + r145.sql \ + r149.sql \ + r150.sql \ + r152.sql \ + r153.sql \ + r157.sql \ + r161.sql \ + r163.sql \ + r169.sql \ + r170.sql \ + r171.sql \ + r172.sql \ + r174.sql \ + r176.sql \ + r177.sql \ + r178.sql \ + r181.sql \ + r182.sql \ + r183.sql \ + r184.sql \ + r186.sql \ + r187.sql \ + r189.sql \ + r191.sql \ + r192.sql \ + r197.sql \ + r204.sql \ + r206.sql \ + r211.sql \ + r213.sql \ + r214.sql \ + r215.sql \ + r218.sql \ + r219.sql \ + r221_scriptdev2.sql \ + r227_scriptdev2.sql \ + r230_mangos.sql \ + r234_mangos.sql \ + r237_mangos.sql \ + r238_mangos.sql \ + r239_mangos.sql \ + r240_scriptdev2.sql \ + r241_mangos.sql \ + r242_mangos.sql \ + r243_mangos.sql \ + r249_mangos.sql \ + r250_mangos.sql \ + r253_mangos.sql \ + r255_mangos.sql \ + r256_mangos.sql \ + r257_mangos.sql \ + r258_mangos.sql \ + r260_mangos.sql \ + r261_mangos.sql \ + r262_mangos.sql \ + r263_mangos.sql \ + r264_mangos.sql \ + r265_mangos.sql \ + r269_mangos.sql \ + r270_mangos.sql \ + r271_mangos.sql \ + r272_mangos.sql \ + r273_mangos.sql \ + r274_mangos.sql \ + r275_mangos.sql \ + r281_scriptdev2.sql \ + r282_mangos.sql \ + r286_mangos.sql \ + r289_mangos.sql \ + r291_mangos.sql \ + r295_mangos.sql \ + r297_mangos.sql \ + r298_scriptdev2.sql \ + r299_scriptdev2.sql \ + r304_mangos.sql \ + r306_scriptdev2.sql \ + r307_mangos.sql \ + r308_mangos.sql \ + r309_mangos.sql \ + r311_mangos.sql \ + r312_mangos.sql \ + r318_mangos.sql \ + r324_mangos.sql \ + r327_mangos.sql \ + r332_scriptdev2.sql \ + r333_mangos.sql \ + r334_mangos.sql \ + r336_mangos.sql \ + r352_mangos.sql \ + r355_mangos.sql \ + r358_mangos.sql \ + r364_mangos.sql \ + r367_mangos.sql \ + r368_mangos.sql \ + r369_mangos.sql \ + r374_mangos.sql \ + r386_mangos.sql \ + r417_mangos.sql \ + r428_mangos.sql \ + r431_mangos.sql \ + r444_mangos.sql \ + r445_mangos.sql \ + r446_mangos.sql \ + r448_scriptdev2.sql \ + r462_mangos.sql \ + r465_mangos.sql \ + r467_mangos.sql \ + r473_mangos.sql \ + r476_mangos.sql \ + r477_mangos.sql \ + r479_mangos.sql \ + r482_mangos.sql \ + r484_mangos.sql \ + r486_mangos.sql \ + r487_mangos.sql \ + r494_mangos.sql \ + r501_mangos.sql \ + r513_mangos.sql \ + r514_mangos.sql \ + r515_mangos.sql \ + r516_mangos.sql \ + r517_mangos.sql \ + r518_mangos.sql \ + r519_mangos.sql \ + r520_mangos.sql \ + r521_mangos.sql \ + r522_mangos.sql \ + r526_mangos.sql \ + r528_mangos.sql \ + r533_mangos.sql \ + r538_scriptdev2.sql \ + r547_mangos.sql \ + r554_mangos.sql \ + r555_mangos.sql \ + r575_mangos.sql \ + r576_mangos.sql \ + r578_mangos.sql \ + r584_mangos.sql \ + r590_mangos.sql \ + r591_mangos.sql \ + r593_mangos.sql \ + r594_mangos.sql \ + r596_mangos.sql \ + r610_mangos.sql \ + r615_scriptdev2.sql \ + r617_mangos.sql \ + r621_mangos.sql \ + r628_mangos.sql \ + r632_mangos.sql \ + r633_mangos.sql \ + r634_scriptdev2.sql \ + r636_mangos.sql \ + r637_mangos.sql \ + r638_mangos.sql \ + r639_mangos.sql \ + r642_mangos.sql \ + r643_mangos.sql \ + r646_mangos.sql \ + r647_scriptdev2.sql \ + r656_scriptdev2.sql \ + r658_mangos.sql \ + r659_mangos.sql diff --git a/src/bindings/scripts/sql/Updates/Makefile.in b/src/bindings/scripts/sql/Updates/Makefile.in new file mode 100644 index 00000000000..9b43048f032 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/Makefile.in @@ -0,0 +1,383 @@ +# Makefile.in generated by automake 1.9.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Copyright (C) 2005,2006,2007 MaNGOS +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../../../../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/bindings/ScriptDev2/sql/Updates +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +SOURCES = +DIST_SOURCES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(pkgdatadir)" +pkgdataDATA_INSTALL = $(INSTALL_DATA) +DATA = $(pkgdata_DATA) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +# datadir = scriptdev2/sql/updates +pkgdatadir = $(datadir)/scriptdev2/sql/updates +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COMPATLIB = @COMPATLIB@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DOXYGENPATH = @DOXYGENPATH@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ +MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ +MAKEINFO = @MAKEINFO@ +MANGOSD_DEBUG_INFO = @MANGOSD_DEBUG_INFO@ +MANGOSD_ENABLE_CLI = @MANGOSD_ENABLE_CLI@ +MANGOSD_ENABLE_RA = @MANGOSD_ENABLE_RA@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_INCLUDES = @MYSQL_INCLUDES@ +MYSQL_LIBS = @MYSQL_LIBS@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSLLIB = @SSLLIB@ +STRIP = @STRIP@ +USE_DOXYGEN_FALSE = @USE_DOXYGEN_FALSE@ +USE_DOXYGEN_TRUE = @USE_DOXYGEN_TRUE@ +VERSION = @VERSION@ +ZLIB = @ZLIB@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ + +# Install basic SQL files to datadir +pkgdata_DATA = \ + 09_BraveWindfeather.sql \ + 11_SilvaFilnaveth.sql \ + 27_Vaelastraz.sql + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/bindings/ScriptDev2/sql/Updates/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/bindings/ScriptDev2/sql/Updates/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: +install-pkgdataDATA: $(pkgdata_DATA) + @$(NORMAL_INSTALL) + test -z "$(pkgdatadir)" || $(mkdir_p) "$(DESTDIR)$(pkgdatadir)" + @list='$(pkgdata_DATA)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(pkgdataDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgdatadir)/$$f'"; \ + $(pkgdataDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgdatadir)/$$f"; \ + done + +uninstall-pkgdataDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgdata_DATA)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(pkgdatadir)/$$f'"; \ + rm -f "$(DESTDIR)$(pkgdatadir)/$$f"; \ + done +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) +installdirs: + for dir in "$(DESTDIR)$(pkgdatadir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-libtool + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-pkgdataDATA + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am uninstall-pkgdataDATA + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + distclean distclean-generic distclean-libtool distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-exec install-exec-am \ + install-info install-info-am install-man install-pkgdataDATA \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + uninstall uninstall-am uninstall-info-am uninstall-pkgdataDATA + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/bindings/scripts/sql/Updates/r104.sql b/src/bindings/scripts/sql/Updates/r104.sql new file mode 100644 index 00000000000..29372b726b7 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r104.sql @@ -0,0 +1 @@ +UPDATE `gameobject_template` SET `ScriptName`='go_orb_of_command' WHERE `entry`='179879'; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r108.sql b/src/bindings/scripts/sql/Updates/r108.sql new file mode 100644 index 00000000000..7c50fe13d77 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r108.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName` = 'mob_dementeddruids' WHERE `entry` = 15260; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r110.sql b/src/bindings/scripts/sql/Updates/r110.sql new file mode 100644 index 00000000000..d5bd73a2fa2 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r110.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName` = 'mob_illusionofjandicebarov' WHERE `entry` = 11439; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r121.sql b/src/bindings/scripts/sql/Updates/r121.sql new file mode 100644 index 00000000000..597bf532508 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r121.sql @@ -0,0 +1,2 @@ +UPDATE `creature_template` SET `ScriptName` = 'mobs_spectral_ghostly_citizen' WHERE `entry` IN (10384, 10385); + diff --git a/src/bindings/scripts/sql/Updates/r123.sql b/src/bindings/scripts/sql/Updates/r123.sql new file mode 100644 index 00000000000..14f73d1e2d3 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r123.sql @@ -0,0 +1,4 @@ +UPDATE creature_template SET ScriptName = 'dashel_stonefist' WHERE entry = '4961'; +UPDATE creature_template SET ScriptName = 'blood_knight_stillblade' WHERE entry = '17768'; +UPDATE creature_template SET ScriptName = 'shattered_rumbler' WHERE entry = '17157'; +UPDATE `creature_template` SET `ScriptName`='neltharaku' WHERE `entry`='21657'; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r124.sql b/src/bindings/scripts/sql/Updates/r124.sql new file mode 100644 index 00000000000..4b5f5cb5794 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r124.sql @@ -0,0 +1,13 @@ +-- BT Trash Mobs +UPDATE `creature_template` SET `scriptname`='mob_blacktemple' WHERE `entry` IN (22844,22845,22846,22849,22853,22855,22869,22873,22875,22876,22877,22878,22880,22881,22882,22883,22884,22945,22953,22954,23337,23339); + +-- The Eye Trash Mobs +UPDATE `creature_template` SET `scriptname`='mob_the_eye' WHERE `entry` IN (20031,20032,20033,20034,20035,20039,20041,20043,20046,20052); +UPDATE `creature_template` SET `scriptname`='mob_crystalcore_devastator' WHERE `entry`='20040'; + +-- Uldaman Trash Mobs +UPDATE `creature_template` SET `scriptname`='mob_uldaman' WHERE `entry` IN (4847,4852,4853,4854,4860,4861,6910,7011,7012,7022,7030,7078,7291); +UPDATE `creature_template` SET `scriptname`='mob_jadespine_basilisk' WHERE `entry`='4863'; + +-- Uldaman Boss Ironaya +UPDATE `creature_template` SET `scriptname`='boss_ironaya' WHERE `entry`='7228'; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r125.sql b/src/bindings/scripts/sql/Updates/r125.sql new file mode 100644 index 00000000000..85477c24e08 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r125.sql @@ -0,0 +1,24 @@ +UPDATE `creature_template` SET `ScriptName` = 'mob_infested_root_walker' WHERE `entry` = 22095; +UPDATE `creature_template` SET `ScriptName` = 'mob_rotting_forest_rager' WHERE `entry` = 22307; +UPDATE `creature_template` SET `ScriptName` = 'mob_netherweb_victim' WHERE `entry` = 22355; + +UPDATE `creature_template` SET `ScriptName` = 'mobs_shadow_council_covert' WHERE `entry` IN (18716, 18717, 18719); +UPDATE `creature_template` SET `npcflag` = 1 WHERE `entry` IN (18716, 18717, 18719); + +UPDATE `creature_template` SET `ScriptName` = 'mob_gurok_the_usurper' WHERE `entry` = 18182; +UPDATE `creature_template` SET `ScriptName` = 'mob_shattered_rumbler' WHERE `entry` = '17157'; +UPDATE `creature_template` SET `ScriptName` = 'mobs_kilsorrow_agent' WHERE `entry` IN (17146, 17147, 17148, 18397, 18658); +UPDATE `creature_template` SET `ScriptName` = 'npc_altruis_the_sufferer' WHERE `entry` = 18417; + +UPDATE `creature_template` SET `ScriptName` = 'npcs_ashyen_and_keleth' WHERE `entry` IN (17900, 17901); +UPDATE `creature_template` SET `npcflag` = 1 WHERE `entry` IN (17900,17901); +UPDATE `creature_template` SET `ScriptName` = 'npc_elder_kuruti' WHERE `entry` = 18197; +UPDATE `creature_template` SET `npcflag` = 1 WHERE `entry` = 18197; + +UPDATE `creature_template` SET `ScriptName` = 'mob_lunaclaw' WHERE `entry` = 12138; + +UPDATE `creature_template` SET `ScriptName` = 'npc_steward_of_time' WHERE `entry` = 20142; + +UPDATE `creature_template` SET `ScriptName` = 'boss_death_knight_darkreaver' WHERE `entry` = 14516; + +UPDATE `creature_template` SET `ScriptName` = 'mob_yenniku' WHERE `entry` = 2530; diff --git a/src/bindings/scripts/sql/Updates/r128.sql b/src/bindings/scripts/sql/Updates/r128.sql new file mode 100644 index 00000000000..f652fa16f10 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r128.sql @@ -0,0 +1 @@ +update `creature_template` SET `scriptname`='npc_guardian' WHERE `entry`='5764'; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r131.sql b/src/bindings/scripts/sql/Updates/r131.sql new file mode 100644 index 00000000000..0899dae38bc --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r131.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName` = 'npc_henze_faulk' WHERE `entry`= 6172; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r134.sql b/src/bindings/scripts/sql/Updates/r134.sql new file mode 100644 index 00000000000..eac5bb78415 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r134.sql @@ -0,0 +1,15 @@ + +UPDATE `instance_template` SET `script` = 'instance_molten_core' WHERE `map`= 409; +UPDATE `instance_template` SET `script` = 'instance_blackwing_lair' WHERE `map`= 469; +UPDATE `instance_template` SET `script` = 'instance_zulgurub' WHERE `map`= 309; +UPDATE `instance_template` SET `script` = 'instance_ruins_of_ahnqiraj' WHERE `map`= 509; +UPDATE `instance_template` SET `script` = 'instance_temple_of_ahnqiraj' WHERE `map`= 531; +UPDATE `instance_template` SET `script` = 'instance_naxxramas' WHERE `map`= 533; + +UPDATE `instance_template` SET `script` = 'instance_karazhan' WHERE `map`= 532; +UPDATE `instance_template` SET `script` = 'instance_hyjal' WHERE `map`= 534; +UPDATE `instance_template` SET `script` = 'instance_gruuls_lair' WHERE `map`= 565; +UPDATE `instance_template` SET `script` = 'instance_magtheridons_lair' WHERE `map`= 544; +UPDATE `instance_template` SET `script` = 'instance_serpent_shrine' WHERE `map`= 548; +UPDATE `instance_template` SET `script` = 'instance_the_eye' WHERE `map`= 550; +UPDATE `instance_template` SET `script` = 'instance_black_temple' WHERE `map`= 564; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r136.sql b/src/bindings/scripts/sql/Updates/r136.sql new file mode 100644 index 00000000000..52a9d87d6de --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r136.sql @@ -0,0 +1,55 @@ + +-- AQ40 bosses -- + +-- Skeram 15263 +UPDATE `creature_template` SET `ScriptName` = 'boss_skeram' WHERE `entry` = 15263; + +-- Vem, Yauj, Kri +-- Vem 15544 +UPDATE `creature_template` SET `ScriptName` = 'boss_vem' WHERE `entry` = 15544; +-- Yauj 15543 +UPDATE `creature_template` SET `ScriptName` = 'boss_yauj' WHERE `entry` = 15543; +-- Yauj Brood 15621 +UPDATE `creature_template` SET `ScriptName` = 'mob_yauj_brood' WHERE `entry` = 15621; +-- Kri 15511 +UPDATE `creature_template` SET `ScriptName` = 'boss_kri' WHERE `entry` = 15511; + +-- Sartura 15516 +UPDATE `creature_template` SET `ScriptName` = 'boss_sartura' WHERE `entry` = 15516; +-- Sartura's Royal Guard 15984 +UPDATE `creature_template` SET `ScriptName` = 'mob_sartura_royal_guard' WHERE `entry` = 15984; + +-- Fankriss 15510 +UPDATE `creature_template` SET `ScriptName` = 'boss_fankriss' WHERE `entry` = 15510; +-- Spawn of Fankriss 15630 +UPDATE `creature_template` SET `ScriptName` = 'mob_spawn_of_fankriss' WHERE `entry` = 15630; + +-- Viscidus 15299 +UPDATE `creature_template` SET `ScriptName` = 'boss_viscidus' WHERE `entry` = 15299; +-- Glob of Viscidus 15667 +UPDATE `creature_template` SET `ScriptName` = 'boss_glob_of_viscidus' WHERE `entry` = 15667; + +-- Huhuran 15509 +UPDATE `creature_template` SET `ScriptName` = 'boss_huhuran' WHERE `entry` = 15509; + +-- Veklor & Veknilash +-- Veklor 15276 +UPDATE `creature_template` SET `ScriptName` = 'boss_veklor' WHERE `entry` = 15276; +-- Veknilash 15275 +UPDATE `creature_template` SET `ScriptName` = 'boss_veknilash' WHERE `entry` = 15275; + +-- Ouro 15517 +UPDATE `creature_template` SET `ScriptName` = 'boss_ouro' WHERE `entry` = 15517; + +-- C'thun +-- Eye 15589 +-- Body 15727 + +UPDATE creature_template SET ScriptName='boss_eye_of_cthun' WHERE entry=15589; +UPDATE creature_template SET ScriptName='mob_claw_tentacle' WHERE entry=15725; +UPDATE creature_template SET ScriptName='mob_eye_tentacle' WHERE entry=15726; + +UPDATE creature_template SET ScriptName='boss_cthun' WHERE entry=15727; +UPDATE creature_template SET ScriptName='mob_giant_claw_tentacle' WHERE entry=15728; +UPDATE creature_template SET ScriptName='mob_giant_eye_tentacle' WHERE entry=15334; +UPDATE creature_template SET ScriptName='mob_giant_flesh_tentacle' WHERE entry=15802; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r139.sql b/src/bindings/scripts/sql/Updates/r139.sql new file mode 100644 index 00000000000..73c013f1a1f --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r139.sql @@ -0,0 +1,35 @@ +UPDATE `creature_template` SET `ScriptName` = 'npc_lokhtos_darkbargainer' WHERE `entry` = 12944; + +UPDATE creature_template SET ScriptName='npc_lady_jaina_proudmoore' WHERE entry=4968; + +UPDATE `creature_template` SET `ScriptName` = 'mobs_spitelashes' WHERE entry IN (6190,6193,6194,6195,6196,7885,7886,12204,12205); + +UPDATE creature_template SET npcflag=1, ScriptName='npc_beaten_corpse' WHERE entry=10668; +UPDATE quest_template SET SpecialFlags=8, ReqCreatureOrGOId1=10668, ReqCreatureOrGOCount1=1 WHERE entry=4921; + +UPDATE creature_template SET ScriptName='boss_rokmar_the_crackler' WHERE entry=17991; +UPDATE creature_template SET ScriptName='boss_warlord_kalithresh' WHERE entry=17798; + +UPDATE `creature_template` SET `ScriptName` = 'boss_midnight' WHERE `entry` = 16151; +UPDATE `creature_template` SET `ScriptName` = 'boss_attumen' WHERE `entry` = 15550; +UPDATE `creature_template` SET `ScriptName` = 'boss_moroes' WHERE `entry` = 15687; +UPDATE `creature_template` SET `ScriptName` = 'boss_maiden_of_virtue' WHERE `entry` = 16457; +UPDATE `creature_template` SET `ScriptName` = 'boss_curator' WHERE `entry` = 15691; +UPDATE `creature_template` SET `ScriptName` = 'boss_big_bad_wolf' WHERE `entry` = 17521; +UPDATE `creature_template` SET `ScriptName` = 'boss_julianne' WHERE `entry` = 17534; +UPDATE `creature_template` SET `ScriptName` = 'boss_romulo' WHERE `entry` = 17533; +UPDATE `creature_template` SET `ScriptName` = 'boss_dorothee' WHERE `entry` = 17535; +UPDATE `creature_template` SET `ScriptName` = 'boss_strawman' WHERE `entry` = 17543; +UPDATE `creature_template` SET `ScriptName` = 'boss_tinhead' WHERE `entry` = 17547; +UPDATE `creature_template` SET `ScriptName` = 'boss_tito' WHERE `entry` = 17548; +UPDATE `creature_template` SET `ScriptName` = 'boss_roar' WHERE `entry` = 17546; +UPDATE `creature_template` SET `ScriptName` = 'boss_crone' WHERE `entry` = 18168; +UPDATE `creature_template` SET `ScriptName` = 'boss_terestian_illhoof' WHERE `entry` = 15688; +UPDATE `creature_template` SET `ScriptName` = 'boss_shade_of_aran' WHERE `entry` = 16524; +UPDATE `creature_template` SET `ScriptName` = 'boss_netherspite' WHERE `entry` = 15689; +UPDATE `creature_template` SET `ScriptName` = 'boss_malchezaar' WHERE `entry` = 15690; +UPDATE `creature_template` SET `ScriptName` = 'boss_nightbane' WHERE `entry` = 17225; + +UPDATE `creature_template` SET `ScriptName` = 'mob_homunculus' WHERE `entry` = 16539; +UPDATE `creature_template` SET `ScriptName` = 'mob_kilrek' WHERE `entry` = 17229; +UPDATE `creature_template` SET `ScriptName` = 'netherspite_infernal' WHERE `entry` = 17646; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r142.sql b/src/bindings/scripts/sql/Updates/r142.sql new file mode 100644 index 00000000000..2cd9b29e6ec --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r142.sql @@ -0,0 +1,11 @@ +-- VoidReaver 19516 +UPDATE `creature_template` SET `ScriptName` = 'boss_void_reaver' WHERE `entry` = 19516; + +-- Arcane Orb Target +REPLACE INTO `creature_template` (`entry`, `modelid_A`, `modelid_H`, `name`, `subname`, `minlevel`, `maxlevel`, `minhealth`, `maxhealth`, `minmana`, `maxmana`, `armor`, `faction_A`, `faction_H`, `npcflag`, `speed`, `rank`, `mindmg`, `maxdmg`, `dmgschool`, `attackpower`, `baseattacktime`, `rangeattacktime`, `flags`, `dynamicflags`, `family`, `trainer_type`, `trainer_spell`, `class`, `race`, `minrangedmg`, `maxrangedmg`, `rangedattackpower`, `type`, `civilian`, `flag1`, `lootid`, `pickpocketloot`, `skinloot`, `resistance1`, `resistance2`, `resistance3`, `resistance4`, `resistance5`, `resistance6`, `spell1`, `spell2`, `spell3`, `spell4`, `mingold`, `maxgold`, `AIName`, `MovementType`, `InhabitType`, `RacialLeader`, `RegenHealth`, `equipment_id`, `ScriptName`) VALUES (19577, 16946, 16946, 'Arcane Orb Target', '', 70, 70, 1, 1, 0, 0, 0, 35, 35, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 3, 0, 1, 0, 'mob_arcane_orb_target'); + +UPDATE `creature_template` SET `ScriptName` = 'boss_omor_the_unscarred' WHERE `entry` = 17308; +UPDATE `creature_template` SET `ScriptName` = 'boss_watchkeeper_gargolmar' WHERE `entry` = 17306; + +UPDATE `creature_template` SET `ScriptName` = 'boss_hungarfen' WHERE `entry` = 17770; +UPDATE `creature_template` SET `ScriptName` = 'mob_underbog_mushroom' WHERE `entry` = 17990; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r144.sql b/src/bindings/scripts/sql/Updates/r144.sql new file mode 100644 index 00000000000..ddf354b9ea1 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r144.sql @@ -0,0 +1,5 @@ +UPDATE `creature_template` SET `ScriptName` = 'boss_the_maker' WHERE `entry` = 17381; +UPDATE `creature_template` SET `ScriptName` = 'boss_broggok' WHERE `entry` = 17380; +UPDATE `creature_template` SET `ScriptName` = 'boss_kelidan_the_breaker' WHERE `entry` = 17377; +UPDATE `creature_template` SET `ScriptName` = 'mob_broggok_poisoncloud' WHERE `entry` = 17662; +UPDATE `creature_template` SET minlevel = 63, maxlevel = 63 WHERE `entry` = 17662; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r145.sql b/src/bindings/scripts/sql/Updates/r145.sql new file mode 100644 index 00000000000..d2d79974048 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r145.sql @@ -0,0 +1,4 @@ + +UPDATE `creature_template` SET `ScriptName` = 'mob_shadow_of_aran' WHERE `entry` = 18254; +UPDATE `creature_template` SET `ScriptName` = 'mob_aran_elemental' WHERE `entry` = 17167; +UPDATE `creature_template` SET `ScriptName` = 'mob_aran_blizzard' WHERE `entry` = 17161; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r149.sql b/src/bindings/scripts/sql/Updates/r149.sql new file mode 100644 index 00000000000..a6311a14e9c --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r149.sql @@ -0,0 +1 @@ +INSERT INTO `spell_script_target` VALUES (30834, 1, 17646); diff --git a/src/bindings/scripts/sql/Updates/r150.sql b/src/bindings/scripts/sql/Updates/r150.sql new file mode 100644 index 00000000000..eb1eb180622 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r150.sql @@ -0,0 +1,19 @@ +UPDATE `creature_template` SET `ScriptName` = 'boss_grand_warlock_nethekurse' WHERE `entry` = 16807; +UPDATE `creature_template` SET `ScriptName` = 'mob_nethe_shadowfissure' WHERE `entry` = 17471; + +UPDATE `creature_template` SET `scriptname`='mob_phoenix' WHERE `entry`='21362'; +UPDATE `creature_template` SET `scriptname`='mob_phoenix_egg' WHERE `entry`='21364'; + +UPDATE `item_template` SET `ScriptName` = 'vorenthals_presence' WHERE `entry`= 30259; + +UPDATE `creature_template` SET `ScriptName` = 'boss_hydromancer_thespia' WHERE `entry` = 17797; +UPDATE `creature_template` SET `ScriptName` = 'mob_coilfang_waterelemental' WHERE `entry` = 17917; + +UPDATE `creature_template` SET `ScriptName` = 'mob_ethereal_beacon' WHERE `entry` = 18431; +UPDATE `creature_template` SET `ScriptName` = 'mob_ethereal_apprentice' WHERE `entry` = 18430; + +UPDATE `creature_template` SET `ScriptName` = 'boss_tavarok' WHERE `entry` = 18343; +UPDATE `creature_template` SET `ScriptName` = 'boss_pandemonius' WHERE `entry` = 18341; +UPDATE `creature_template` SET `ScriptName` = 'boss_nexusprince_shaffar' WHERE `entry` = 18344; + +UPDATE `creature_template` SET `ScriptName` = 'boss_ghazan' WHERE `entry` = 18105; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r152.sql b/src/bindings/scripts/sql/Updates/r152.sql new file mode 100644 index 00000000000..9efdb9f53c4 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r152.sql @@ -0,0 +1,12 @@ +UPDATE `creature_template` SET `ScriptName` = 'mob_syth_fire' WHERE `entry` = 19203; +UPDATE `creature_template` SET `ScriptName` = 'mob_syth_arcane' WHERE `entry` = 19205; +UPDATE `creature_template` SET `ScriptName` = 'mob_syth_frost' WHERE `entry` = 19204; +UPDATE `creature_template` SET `ScriptName` = 'mob_syth_shadow' WHERE `entry` = 19206; + +UPDATE `creature_template` SET `ScriptName` = 'boss_tailonking_ikiss' WHERE `entry` = 18473; +UPDATE `creature_template` SET `ScriptName` = 'boss_darkweaver_syth' WHERE `entry` = 18472; + +UPDATE creature_template SET ScriptName = 'npc_shattrathflaskvendors' WHERE entry = '23483'; +UPDATE creature_template SET ScriptName = 'npc_shattrathflaskvendors' WHERE entry = '23484'; + +UPDATE `creature_template` SET ScriptName='innkeeper' WHERE `npcflag` & 128<>0; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r153.sql b/src/bindings/scripts/sql/Updates/r153.sql new file mode 100644 index 00000000000..fb59c996edf --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r153.sql @@ -0,0 +1,33 @@ +-- Fishing net +UPDATE item_template SET ScriptName = 'draenei_fishing_net' WHERE entry = 23654; + +-- Auchenai Crypts +UPDATE `creature_template` set `scriptname` = 'boss_shirrak_the_dead_watcher' where `entry` = '18371'; +UPDATE `creature_template` set `scriptname` = 'boss_shirrak_the_dead_watcher' where `entry` = '20318'; + +-- Old Hillsbrad +UPDATE `creature_template` set `scriptname` = 'mob_lieutenant_drake' where `entry` = '17848'; +UPDATE `creature_template` set `scriptname` = 'mob_epoch_hunter' where `entry` = '18096'; +UPDATE `creature_template` SET `ScriptName` = 'boss_captain_skarloc' WHERE `entry`=17862; + +-- The Black Morass +UPDATE `creature_template` set `ScriptName` = 'boss_chrono_lord_deja' where `entry` = '17879'; +UPDATE `creature_template` SET `ScriptName` = 'boss_aeonus' WHERE `entry`=17881; +UPDATE `creature_template` set `ScriptName` = 'boss_temporus' where `entry` = '17880'; + +-- Deadmines +UPDATE `creature_template` SET `ScriptName` = 'boss_deadmines' WHERE `entry`=645; +UPDATE `creature_template` SET `ScriptName` = 'boss_deadmines' WHERE `entry`=1763; +UPDATE `creature_template` SET `ScriptName` = 'boss_deadmines' WHERE `entry`=599; +UPDATE `creature_template` SET `ScriptName` = 'boss_deadmines' WHERE `entry`=3586; + +-- Wailing Caverns +UPDATE `creature_template` SET `ScriptName` = 'boss_wailing_caverns' WHERE `entry`=3654; + +-- Gruul's Lair +UPDATE `creature_template` SET `ScriptName` = 'boss_high_king_maulgar' WHERE `entry`=18831; +UPDATE `creature_template` SET `ScriptName` = 'boss_kiggler_the_crazed' WHERE `entry`=18835; +UPDATE `creature_template` SET `ScriptName` = 'boss_blindeye_the_seer' WHERE `entry`=18836; +UPDATE `creature_template` SET `ScriptName` = 'boss_olm_the_summoner' WHERE `entry`=18834; +UPDATE `creature_template` SET `ScriptName` = 'boss_krosh_firehand' WHERE `entry`=18832; +UPDATE `instance_template` SET `script`="instance_gruuls_lair" WHERE `map`=565; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r157.sql b/src/bindings/scripts/sql/Updates/r157.sql new file mode 100644 index 00000000000..05c8299529c --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r157.sql @@ -0,0 +1,7 @@ +UPDATE `creature_template` SET `ScriptName` = 'boss_hydross_the_unstable' WHERE `entry`=21216; +UPDATE `creature_template` SET `ScriptName` = 'boss_leotheras_the_blind' WHERE `entry`=21215; + +-- Magtheridon's Lair +UPDATE `gameobject_template` SET `ScriptName`='go_manticron_cube' WHERE `entry`='181713'; +UPDATE `creature_template` SET `ScriptName` = 'boss_magtheridon' WHERE `entry`=17257; +UPDATE `creature_template` SET `ScriptName` = 'mob_hellfire_channeler' WHERE `entry`=17256; diff --git a/src/bindings/scripts/sql/Updates/r161.sql b/src/bindings/scripts/sql/Updates/r161.sql new file mode 100644 index 00000000000..0bb31ee2ba0 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r161.sql @@ -0,0 +1,12 @@ +-- shadow labyrinth +UPDATE `instance_template` SET `script` = 'instance_shadow_labyrinth' WHERE `map`= 555; +UPDATE `creature_template` SET `ScriptName` = 'boss_murmur' WHERE `entry` = 18708; +UPDATE `creature_template` SET `ScriptName` = 'boss_ambassador_hellmaw' WHERE `entry` = 18731; +UPDATE `creature_template` SET `ScriptName` = 'boss_grandmaster_vorpil' WHERE `entry` = 18732; +UPDATE `creature_template` SET `ScriptName` = 'boss_blackheart_the_inciter' WHERE `entry` = 18667; + +-- fathomlord karathress +UPDATE `creature_template` SET `ScriptName` = 'boss_fathomlord_karathress' WHERE `entry`=21214; +UPDATE `creature_template` SET `ScriptName` = 'boss_fathomguard_sharkkis' WHERE `entry`=21966; +UPDATE `creature_template` SET `ScriptName` = 'boss_fathomguard_tidalvess' WHERE `entry`=21965; +UPDATE `creature_template` SET `ScriptName` = 'boss_fathomguard_caribdis' WHERE `entry`=21964; diff --git a/src/bindings/scripts/sql/Updates/r163.sql b/src/bindings/scripts/sql/Updates/r163.sql new file mode 100644 index 00000000000..9f8253e3cd3 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r163.sql @@ -0,0 +1,2 @@ +UPDATE creature_template SET npcflag=npcflag|1, ScriptName='npc_cairne_bloodhoof' WHERE entry=3057; +UPDATE `gameobject_template` SET `ScriptName`='go_barov_journal' WHERE `entry`=180794; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r164.sql b/src/bindings/scripts/sql/Updates/r164.sql new file mode 100644 index 00000000000..30b7a6a05a6 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r164.sql @@ -0,0 +1,10 @@ +-- gruuls lair trash mobs +UPDATE `creature_template` SET `ScriptName` = 'mob_gruuls_lair' WHERE `entry` IN (19389, 21350); + +-- morogrim tidewalker +UPDATE `creature_template` SET `ScriptName` = 'boss_morogrim_tidewalker' WHERE `entry`=21213; +-- Water Globule +UPDATE `creature_template` SET `ScriptName` = 'mob_water_globule' WHERE `entry`=21913; + +-- Serpentshrine Cavern Trash Mobs +UPDATE `creature_template` SET `ScriptName` = 'mob_serpentshrine_cavern' WHERE `entry` IN (21246, 21339, 21221, 21224, 21227, 21228, 21226, 21225, 21298, 21299); \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r165.sql b/src/bindings/scripts/sql/Updates/r165.sql new file mode 100644 index 00000000000..69401cdb8f4 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r165.sql @@ -0,0 +1,8 @@ + +-- the steam vault +UPDATE `instance_template` SET `script` = 'instance_steam_vault' WHERE `map` = 545; + +-- right old hillsbrad foothills bosses script name +UPDATE `creature_template` SET `ScriptName` = 'boss_lieutenant_drake' WHERE `entry` = 17848; +UPDATE `creature_template` SET `ScriptName` = 'boss_epoch_hunter' WHERE `entry` = 18096; + diff --git a/src/bindings/scripts/sql/Updates/r169.sql b/src/bindings/scripts/sql/Updates/r169.sql new file mode 100644 index 00000000000..d5511e82106 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r169.sql @@ -0,0 +1,4 @@ +-- hellfire peninsula special taxi path +UPDATE `creature_template` SET `ScriptName` = 'npc_wing_commander_brack' WHERE `entry` = 19401; +UPDATE `creature_template` SET `ScriptName` = 'npc_wing_commander_dabiree' WHERE `entry` = 19409; +UPDATE `creature_template` SET `ScriptName` = 'npc_gryphoneer_windbellow' WHERE `entry` = 20235; diff --git a/src/bindings/scripts/sql/Updates/r170.sql b/src/bindings/scripts/sql/Updates/r170.sql new file mode 100644 index 00000000000..c397c160065 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r170.sql @@ -0,0 +1,2 @@ +-- special taxi path netherstorm +UPDATE `creature_template` SET `ScriptName` = 'npc_protectorate_nether_drake' WHERE `entry` = 20903; diff --git a/src/bindings/scripts/sql/Updates/r171.sql b/src/bindings/scripts/sql/Updates/r171.sql new file mode 100644 index 00000000000..5a7adb61514 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r171.sql @@ -0,0 +1,2 @@ +-- multi kill quest mobs hfp +UPDATE `creature_template` SET `ScriptName` = 'mobs_shattered_hand_orc' WHERE `entry` IN (19411, 19410, 19413, 19414, 16867, 19295, 16870, 16878, 19415); diff --git a/src/bindings/scripts/sql/Updates/r172.sql b/src/bindings/scripts/sql/Updates/r172.sql new file mode 100644 index 00000000000..4cac983026d --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r172.sql @@ -0,0 +1,3 @@ +-- support multikill bladespire and bloodmaul ogres +UPDATE `creature_template` SET `ScriptName` = 'mobs_bladespire_ogre' WHERE `entry` IN (19998, 20334, 21296, 21975); +UPDATE `creature_template` SET `ScriptName` = 'mobs_bloodmaul_ogre' WHERE `entry` IN (19948, 19952, 19957); diff --git a/src/bindings/scripts/sql/Updates/r174.sql b/src/bindings/scripts/sql/Updates/r174.sql new file mode 100644 index 00000000000..57dde5a0fd2 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r174.sql @@ -0,0 +1,8 @@ +-- multikill creatures +UPDATE `creature_template` SET `ScriptName` = 'mobs_dragonmaw_orc' WHERE `entry` IN (21717, 21718, 21719, 21720, 22331); +UPDATE `creature_template` SET `ScriptName` = 'mobs_shadowmoon_valley_wildlife' WHERE `entry` IN (21878, 21879); +UPDATE `creature_template` SET `ScriptName` = 'mobs_gordunni_ogre' WHERE `entry` IN (22143, 22144, 22148, 23022); +-- vendor +UPDATE `creature_template` SET `ScriptName` = 'npc_drake_dealer_hurlunk' WHERE `entry` = 23489; +UPDATE `creature_template` SET `ScriptName` = 'npc_rivern_frostwind' WHERE `entry` = 10618; + diff --git a/src/bindings/scripts/sql/Updates/r176.sql b/src/bindings/scripts/sql/Updates/r176.sql new file mode 100644 index 00000000000..58e75375c12 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r176.sql @@ -0,0 +1,5 @@ +-- tales and stories +UPDATE `creature_template` SET `ScriptName` = 'npc_tirion_fordring' WHERE `entry` = 1855; +UPDATE `creature_template` SET `ScriptName` = 'npc_loramus_thalipedes' WHERE `entry` = 7783; +UPDATE `creature_template` SET `ScriptName` = 'npc_fallen_hero_of_horde' WHERE `entry` = 7572; +UPDATE `creature_template` SET `ScriptName` = 'npc_lorax' WHERE `entry` = 10918; diff --git a/src/bindings/scripts/sql/Updates/r177.sql b/src/bindings/scripts/sql/Updates/r177.sql new file mode 100644 index 00000000000..3914679aa3b --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r177.sql @@ -0,0 +1,2 @@ +-- kalaran windblade +UPDATE `creature_template` SET `ScriptName` = 'npc_kalaran_windblade' WHERE `entry` = 8479; diff --git a/src/bindings/scripts/sql/Updates/r178.sql b/src/bindings/scripts/sql/Updates/r178.sql new file mode 100644 index 00000000000..f20a4366885 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r178.sql @@ -0,0 +1,2 @@ +-- kharan mighthammer +UPDATE `creature_template` SET `ScriptName` = 'npc_kharan_mighthammer' WHERE `entry` = 9021; diff --git a/src/bindings/scripts/sql/Updates/r181.sql b/src/bindings/scripts/sql/Updates/r181.sql new file mode 100644 index 00000000000..4807582d1a4 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r181.sql @@ -0,0 +1,2 @@ +-- npc_lantresor_of_the_blade +UPDATE `creature_template` SET `ScriptName` = 'npc_lantresor_of_the_blade' WHERE `entry` = 18261; diff --git a/src/bindings/scripts/sql/Updates/r182.sql b/src/bindings/scripts/sql/Updates/r182.sql new file mode 100644 index 00000000000..5d0a3c68fd2 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r182.sql @@ -0,0 +1,2 @@ +-- npc_ragged_john +UPDATE `creature_template` SET `ScriptName` = 'npc_ragged_john' WHERE `entry` = 9563; diff --git a/src/bindings/scripts/sql/Updates/r183.sql b/src/bindings/scripts/sql/Updates/r183.sql new file mode 100644 index 00000000000..79c175d0996 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r183.sql @@ -0,0 +1,5 @@ +-- revert to original specialflags + flag 4 for mangos support, script no longer needed for quest +UPDATE `quest_template` SET `SpecialFlags`= 140 WHERE `entry` IN (10040, 10041); +UPDATE `creature_template` SET `ScriptName` = '' WHERE `entry` IN (18716, 18717, 18719); +-- gossip only, key to searing gorge discussion +UPDATE `creature_template` SET `ScriptName` = 'npc_mountaineer_pebblebitty' WHERE `entry` = 3836; diff --git a/src/bindings/scripts/sql/Updates/r184.sql b/src/bindings/scripts/sql/Updates/r184.sql new file mode 100644 index 00000000000..599fd9f3c0e --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r184.sql @@ -0,0 +1,2 @@ +-- revert to default database values +UPDATE `quest_template` SET `SpecialFlags`= 10, `ReqCreatureOrGOId1` = 0, `ReqCreatureOrGOId2` = 0, `ReqCreatureOrGOId3`= 0, `ReqCreatureOrGOId4`= 0, `ReqCreatureOrGOCount1` = 0, `ReqCreatureOrGOCount2` = 0, `ReqCreatureOrGOCount3` = 0, `ReqCreatureOrGOCount4`= 0, `ReqSpellCast1` = 0, `ReqSpellCast2` = 0, `ReqSpellCast3` = 0, `ReqSpellCast4` = 0 WHERE `entry` IN (5929, 5930); diff --git a/src/bindings/scripts/sql/Updates/r186.sql b/src/bindings/scripts/sql/Updates/r186.sql new file mode 100644 index 00000000000..a225e6850fc --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r186.sql @@ -0,0 +1,2 @@ +-- leotheras the blind demonform +UPDATE `creature_template` SET `ScriptName` = 'boss_leotheras_the_blind_demonform' WHERE `entry` = 21845; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r187.sql b/src/bindings/scripts/sql/Updates/r187.sql new file mode 100644 index 00000000000..2b34b1c84bf --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r187.sql @@ -0,0 +1,12 @@ +-- test of lore quest npcs +UPDATE `creature_template` SET `ScriptName` = 'npc_parqual_fintallas' WHERE `entry` = 4488; +UPDATE `creature_template` SET `ScriptName` = 'npc_braug_dimspirit' WHERE `entry` = 4489; +-- quest Scratches +UPDATE `creature_template` SET `ScriptName` = 'npc_daranelle' WHERE `entry` = 21469; + +-- no comments of malfuntion, implementing mount vendors script +UPDATE `creature_template` SET `ScriptName` = 'npc_mount_vendor' WHERE `entry` IN (384, 1261, 1460, 2357, 3362, 3685, 4730, 4731, 4885, 7952, 7955, 16264, 17584); + +-- one time update, this is database related sql and should be included in any database +UPDATE `creature_template` SET `npcflag` = `npcflag`|1 WHERE `entry` IN (4488, 4489, 21469); +INSERT IGNORE `spell_teleport` VALUES (6766, 1,-2354.03,-1902.07,95.78,4.6); diff --git a/src/bindings/scripts/sql/Updates/r189.sql b/src/bindings/scripts/sql/Updates/r189.sql new file mode 100644 index 00000000000..51fc09abcd2 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r189.sql @@ -0,0 +1,3 @@ +UPDATE `gameobject_template` SET `ScriptName` = 'go_field_repair_bot' where `entry`=179552; +UPDATE `creature_template` SET `ScriptName` = 'boss_doomwalker' WHERE `entry` = 17711; +UPDATE `creature_template` SET `ScriptName` = 'boss_exarch_maladaar' WHERE `entry` = 18373; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r191.sql b/src/bindings/scripts/sql/Updates/r191.sql new file mode 100644 index 00000000000..f5d563bc272 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r191.sql @@ -0,0 +1,5 @@ + +/* THE MECHANAR */ +UPDATE `creature_template` SET `ScriptName` = 'boss_gatewatcher_iron_hand' WHERE `entry` = 19710; +UPDATE `creature_template` SET `ScriptName` = 'boss_nethermancer_sepethrea' WHERE `entry` = 19221; +UPDATE `creature_template` SET `ScriptName` = 'mob_ragin_flames' WHERE `entry` = 20481; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r192.sql b/src/bindings/scripts/sql/Updates/r192.sql new file mode 100644 index 00000000000..beb8aa31eb8 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r192.sql @@ -0,0 +1,9 @@ +-- lady vashj event +UPDATE `creature_template` SET `ScriptName` = 'boss_lady_vashj' WHERE `entry` = 21212; +UPDATE `creature_template` SET `ScriptName` = 'mob_enchanted_elemental' WHERE `entry` = 21958; +UPDATE `creature_template` SET `ScriptName` = 'mob_tainted_elemental' WHERE `entry` = 22009; +UPDATE `creature_template` SET `ScriptName` = 'mob_coilfang_elite' WHERE `entry` = 22055; +UPDATE `creature_template` SET `ScriptName` = 'mob_coilfang_strider' WHERE `entry` = 22056; +UPDATE `creature_template` SET `ScriptName` = 'mob_fathom_sporebat' WHERE `entry` = 22120; + +UPDATE `gameobject_template` SET `ScriptName` = 'go_shield_generator' WHERE `entry` IN (185052, 185053, 185051, 185054); diff --git a/src/bindings/scripts/sql/Updates/r197.sql b/src/bindings/scripts/sql/Updates/r197.sql new file mode 100644 index 00000000000..800595abd59 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r197.sql @@ -0,0 +1,5 @@ +-- scholomance script +UPDATE `instance_template` SET `script` = 'instance_scholomance' WHERE `map` = 289; + +-- arcatraz script +UPDATE `instance_template` SET `script` = 'instance_arcatraz' WHERE `map` = 552; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r204.sql b/src/bindings/scripts/sql/Updates/r204.sql new file mode 100644 index 00000000000..960ba366f18 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r204.sql @@ -0,0 +1,7 @@ +-- lady vashj event +UPDATE `gameobject_template` SET `type`=0,`ScriptName`='' WHERE `entry` IN (185052, 185053, 185051, 185054); +UPDATE `item_template` SET `ScriptName` = 'item_tainted_core' WHERE `entry` = 31088; +UPDATE `creature_template` SET `ScriptName` = 'mob_shield_generator_channel' WHERE `entry` = 19870; + +-- BWL trash mobs +UPDATE `creature_template` SET `ScriptName` = 'mob_blackwing_lair' WHERE `entry` IN (14265, 12457, 13996, 12459, 14261, 14263, 12467, 12463, 12461, 12464, 12460, 12465, 14262, 14264); diff --git a/src/bindings/scripts/sql/Updates/r206.sql b/src/bindings/scripts/sql/Updates/r206.sql new file mode 100644 index 00000000000..9adcb76a6a3 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r206.sql @@ -0,0 +1,16 @@ +-- Zul'Gurub Bosses Part 1 + Trash Mobs +UPDATE `creature_template` SET `ScriptName` = 'boss_jeklik' WHERE `entry` = 14517; +UPDATE `creature_template` SET `ScriptName` = 'boss_venoxis' WHERE `entry` = 14607; +UPDATE `creature_template` SET `ScriptName` = 'boss_marli' WHERE `entry` = 14510; +UPDATE `creature_template` SET `ScriptName` = 'boss_mandokir' WHERE `entry` = 11382; +UPDATE `creature_template` SET `ScriptName` = 'boss_gahzranka' WHERE `entry` = 15114; +UPDATE `creature_template` SET `ScriptName` = 'boss_jindo' WHERE `entry` = 11380; + +/* Spawn of Marli */ +UPDATE `creature_template` SET `ScriptName` = 'mob_spawn_of_marli' WHERE `entry` = 15041; +/* Jeklik Batrider */ +UPDATE `creature_template` SET `ScriptName` = 'mob_batrider' WHERE `entry` = 14965; + + +-- Darkmaster Ganling +UPDATE `creature_template` SET `ScriptName` = 'boss_darkmaster_gandling' WHERE `entry` = 1853; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r211.sql b/src/bindings/scripts/sql/Updates/r211.sql new file mode 100644 index 00000000000..ceb91171b9a --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r211.sql @@ -0,0 +1,6 @@ +-- kael'thas event +UPDATE `creature_template` SET `ScriptName` = 'boss_kaelthas' WHERE `entry` = 19622; +UPDATE `creature_template` SET `ScriptName` = 'boss_thaladred_the_darkener' WHERE `entry` = 20064; +UPDATE `creature_template` SET `ScriptName` = 'boss_lord_sanguinar' WHERE `entry` = 20060; +UPDATE `creature_template` SET `ScriptName` = 'boss_grand_astromancer_capernian' WHERE `entry` = 20062; +UPDATE `creature_template` SET `ScriptName` = 'boss_master_engineer_telonicus' WHERE `entry` = 20063; diff --git a/src/bindings/scripts/sql/Updates/r213.sql b/src/bindings/scripts/sql/Updates/r213.sql new file mode 100644 index 00000000000..b512cfd5044 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r213.sql @@ -0,0 +1,11 @@ +-- Zul'Gurub Part II +UPDATE `creature_template` SET `ScriptName` = "boss_hakkar" WHERE `creature_template`.`entry` = 15295; +UPDATE `creature_template` SET `ScriptName` = "boss_thekal" WHERE `creature_template`.`entry` = 14509; +UPDATE `creature_template` SET `ScriptName` = "boss_arlokk" WHERE `creature_template`.`entry` = 14515; +UPDATE `creature_template` SET `ScriptName` = "mob_zealot_lorkhan" WHERE `creature_template`.`entry` = 11347; +UPDATE `creature_template` SET `ScriptName` = "mob_zealot_zath" WHERE `creature_template`.`entry` = 11348; +UPDATE `creature_template` SET `ScriptName` = "mob_healing_ward" WHERE `creature_template`.`entry` = 14987; +UPDATE `creature_template` SET `Scriptname` = "mobs_zulgurub" WHERE `creature_template`.`entry` IN (11340 ,11352 , 11350, 11830, 11372, 11351, 14750); + + + diff --git a/src/bindings/scripts/sql/Updates/r214.sql b/src/bindings/scripts/sql/Updates/r214.sql new file mode 100644 index 00000000000..24b5aa393d3 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r214.sql @@ -0,0 +1,2 @@ +UPDATE `creature_template` SET `ScriptName` = "boss_hakkar" WHERE `creature_template`.`entry` = 14834; + diff --git a/src/bindings/scripts/sql/Updates/r215.sql b/src/bindings/scripts/sql/Updates/r215.sql new file mode 100644 index 00000000000..90bfbf0e86b --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r215.sql @@ -0,0 +1 @@ +UPDATE `item_template` SET `ScriptName` = 'item_skin_of_purest_water' WHERE `entry` = 23751; diff --git a/src/bindings/scripts/sql/Updates/r218.sql b/src/bindings/scripts/sql/Updates/r218.sql new file mode 100644 index 00000000000..e6eeb7782aa --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r218.sql @@ -0,0 +1,5 @@ +-- misc quest related +UPDATE `creature_template` SET `ScriptName` = 'npc_restless_apparition' WHERE `entry` = 23861; +UPDATE `creature_template` SET `ScriptName` = 'mobs_direhorn_grimtotem' WHERE `entry` = 23595; +UPDATE `creature_template` SET `ScriptName` = 'mobs_risen_husk_spirit' WHERE `entry` IN (23554, 23555); + diff --git a/src/bindings/scripts/sql/Updates/r219.sql b/src/bindings/scripts/sql/Updates/r219.sql new file mode 100644 index 00000000000..8b01dd43784 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r219.sql @@ -0,0 +1,3 @@ +/* Fix for Wrong ZG Update */ +UPDATE `creature_template` SET `ScriptName` = ' ' WHERE `entry` = 14607; +UPDATE `creature_template` SET `ScriptName` = ' ' WHERE `entry` = 15295; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r221_scriptdev2.sql b/src/bindings/scripts/sql/Updates/r221_scriptdev2.sql new file mode 100644 index 00000000000..06cd4334508 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r221_scriptdev2.sql @@ -0,0 +1 @@ +ALTER TABLE `eventai_Scripts` RENAME TO `eventai_scripts`; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r227_scriptdev2.sql b/src/bindings/scripts/sql/Updates/r227_scriptdev2.sql new file mode 100644 index 00000000000..4e600fc3df8 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r227_scriptdev2.sql @@ -0,0 +1,29 @@ +ALTER TABLE `eventai_scripts` + DROP PRIMARY KEY, + DROP `id`, + ADD `id` int(11) unsigned NOT NULL COMMENT 'Identifier' PRIMARY KEY AUTO_INCREMENT FIRST, + + MODIFY `event_param1` int(11) signed NOT NULL default '0', + MODIFY `event_param2` int(11) signed NOT NULL default '0', + MODIFY `event_param3` int(11) signed NOT NULL default '0', + + MODIFY `action1_param1` int(11) signed NOT NULL default '0', + MODIFY `action1_param2` int(11) signed NOT NULL default '0', + MODIFY `action1_param3` int(11) signed NOT NULL default '0', + + MODIFY `action2_param1` int(11) signed NOT NULL default '0', + MODIFY `action2_param2` int(11) signed NOT NULL default '0', + MODIFY `action2_param3` int(11) signed NOT NULL default '0', + + MODIFY `action3_param1` int(11) signed NOT NULL default '0', + MODIFY `action3_param2` int(11) signed NOT NULL default '0', + MODIFY `action3_param3` int(11) signed NOT NULL default '0', + + ADD `comment` varchar(255) NOT NULL default '' COMMENT 'Event Comment'; + +ALTER TABLE `localized_texts` + DROP PRIMARY KEY, + DROP `id`, + ADD `id` int(11) unsigned NOT NULL COMMENT 'Identifier' PRIMARY KEY AUTO_INCREMENT FIRST, + ADD `comment` varchar(255) NOT NULL default '' COMMENT 'Text Comment'; + \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r230_mangos.sql b/src/bindings/scripts/sql/Updates/r230_mangos.sql new file mode 100644 index 00000000000..4db44512536 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r230_mangos.sql @@ -0,0 +1,2 @@ +UPDATE `creature_template` SET `ScriptName` = 'npc_deserter_agitator' WHERE `entry` = 23602; +UPDATE `gameobject_template` SET `ScriptName` = 'go_field_repair_bot_74A' where `entry`= 179552; diff --git a/src/bindings/scripts/sql/Updates/r234_mangos.sql b/src/bindings/scripts/sql/Updates/r234_mangos.sql new file mode 100644 index 00000000000..8a72910adbe --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r234_mangos.sql @@ -0,0 +1,2 @@ +UPDATE `creature_template` SET `ScriptName` = 'npc_screecher_spirit' WHERE `entry` = 8612; +UPDATE `item_template` SET `ScriptName` = 'item_yehkinyas_bramble' WHERE `entry`= 10699; diff --git a/src/bindings/scripts/sql/Updates/r237_mangos.sql b/src/bindings/scripts/sql/Updates/r237_mangos.sql new file mode 100644 index 00000000000..265bde22802 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r237_mangos.sql @@ -0,0 +1,6 @@ +-- new +UPDATE `creature_template` SET `ScriptName` = 'guard_azuremyst' WHERE `entry` = 18038; +UPDATE `creature_template` SET `ScriptName` = 'guard_eversong' WHERE `entry` = 16221; +-- update +UPDATE `creature_template` SET `ScriptName` = 'guard_durotar' WHERE `entry` = 5953; +UPDATE `creature_template` SET `ScriptName` = '' WHERE `entry` IN (3210, 3211, 3213, 3214, 1736, 1739, 1737); diff --git a/src/bindings/scripts/sql/Updates/r238_mangos.sql b/src/bindings/scripts/sql/Updates/r238_mangos.sql new file mode 100644 index 00000000000..d148e11f863 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r238_mangos.sql @@ -0,0 +1,2 @@ +-- revert previously bad sql +UPDATE `creature_template` SET `ScriptName` = '' WHERE `ScriptName` LIKE '%innkeeper%' AND `npcflag` & 128<>0; diff --git a/src/bindings/scripts/sql/Updates/r239_mangos.sql b/src/bindings/scripts/sql/Updates/r239_mangos.sql new file mode 100644 index 00000000000..8936e4d8f6c --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r239_mangos.sql @@ -0,0 +1 @@ +UPDATE `item_template` SET `ScriptName` = '' WHERE `entry` = 23268; diff --git a/src/bindings/scripts/sql/Updates/r240_scriptdev2.sql b/src/bindings/scripts/sql/Updates/r240_scriptdev2.sql new file mode 100644 index 00000000000..635ee46b18e --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r240_scriptdev2.sql @@ -0,0 +1,2 @@ +ALTER TABLE `eventai_scripts` +ADD `event_inverse_phase_mask` int(11) signed NOT NULL default '0', COMMENT 'Mask which phases this event will not trigger in'; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r241_mangos.sql b/src/bindings/scripts/sql/Updates/r241_mangos.sql new file mode 100644 index 00000000000..ffc99c200d5 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r241_mangos.sql @@ -0,0 +1,2 @@ +UPDATE `creature_template` SET `ScriptName` = 'npc_skyguard_handler_irena' WHERE `entry` = 23413; +UPDATE `creature_template` SET `ScriptName` = 'npc_skyguard_handler_deesak' WHERE `entry` = 23415; diff --git a/src/bindings/scripts/sql/Updates/r242_mangos.sql b/src/bindings/scripts/sql/Updates/r242_mangos.sql new file mode 100644 index 00000000000..49465a656e9 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r242_mangos.sql @@ -0,0 +1,2 @@ +UPDATE `creature_template` SET `ScriptName` = 'npc_zamael_lunthistle' WHERE `entry` = 8436; +UPDATE `creature_template` SET `ScriptName` = 'npc_lothos_riftwaker' WHERE `entry` = 14387; diff --git a/src/bindings/scripts/sql/Updates/r243_mangos.sql b/src/bindings/scripts/sql/Updates/r243_mangos.sql new file mode 100644 index 00000000000..6b1ad08d0a0 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r243_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName` = 'npc_marin_noggenfogger' WHERE `entry` = 7564; diff --git a/src/bindings/scripts/sql/Updates/r249_mangos.sql b/src/bindings/scripts/sql/Updates/r249_mangos.sql new file mode 100644 index 00000000000..cf0c36ef468 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r249_mangos.sql @@ -0,0 +1,3 @@ +UPDATE `creature_template` SET `ScriptName` = 'mob_flamewaker_priest' WHERE `entry` = 11662; +UPDATE `creature_template` SET `ScriptName` = 'boss_datrohan_balnazzar' WHERE `entry` = 10812; + diff --git a/src/bindings/scripts/sql/Updates/r250_mangos.sql b/src/bindings/scripts/sql/Updates/r250_mangos.sql new file mode 100644 index 00000000000..841e39d71b3 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r250_mangos.sql @@ -0,0 +1,2 @@ +UPDATE `creature_template` SET `ScriptName` = 'boss_dathrohan_balnazzar' WHERE `entry` = 10812; + \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r253_mangos.sql b/src/bindings/scripts/sql/Updates/r253_mangos.sql new file mode 100644 index 00000000000..424237be238 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r253_mangos.sql @@ -0,0 +1 @@ +UPDATE `item_template` SET `ScriptName` = 'item_zezzaks_shard' WHERE `entry` = 31463; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r255_mangos.sql b/src/bindings/scripts/sql/Updates/r255_mangos.sql new file mode 100644 index 00000000000..7019586eb96 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r255_mangos.sql @@ -0,0 +1,5 @@ +UPDATE instance_template SET script = 'instance_zulaman' WHERE map = 568; +UPDATE creature_template SET scriptname='boss_janalai' WHERE entry=23578; +UPDATE creature_template SET scriptname='mob_jandalai_firebomb' WHERE entry=23920; +UPDATE creature_template SET scriptname='mob_amanishi_hatcher' WHERE entry=23818; +UPDATE creature_template SET scriptname='mob_hatchling' WHERE entry=23598; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r256_mangos.sql b/src/bindings/scripts/sql/Updates/r256_mangos.sql new file mode 100644 index 00000000000..4207454117e --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r256_mangos.sql @@ -0,0 +1,35 @@ +UPDATE creature_template SET ScriptName = 'npc_tyrande_whisperwind' WHERE entry = 17948; +UPDATE creature_template SET ScriptName = 'npc_thrall' WHERE entry = 17852; +UPDATE creature_template SET ScriptName = 'npc_jaina_proudmoore' WHERE entry = 17772; + +UPDATE creature_template SET ScriptName = 'npc_akama_shade' WHERE entry = 23089; -- Akama at Shade of Akama +UPDATE creature_template SET ScriptName = 'npc_akama_illidan' WHERE entry = 22990; -- Akama at Illidan +UPDATE creature_template SET ScriptName = 'illidari_council' WHERE entry = 23426; -- Illidari Council controller mob +UPDATE creature_template SET ScriptName = 'boss_veras_darkshadow' WHERE entry = 22952; -- Rogue of Illidari Council +UPDATE creature_template SET ScriptName = 'boss_teron_gorefiend' WHERE entry = 22871; -- Teron Gorefiend +UPDATE creature_template SET ScriptName = 'boss_supremus' WHERE entry = 22898; -- Supremus +UPDATE creature_template SET ScriptName = 'boss_shade_of_akama' WHERE entry = 22841; -- Shade of Akama +UPDATE creature_template SET ScriptName = 'boss_reliquary_of_souls' WHERE entry = 22856; -- Reliquary Controller Mob +UPDATE creature_template SET ScriptName = 'boss_essence_of_suffering' WHERE entry = 23418; -- Essence Of Suffering +UPDATE creature_template SET ScriptName = 'boss_essence_of_desire' WHERE entry = 23419; -- Essence of Desire +UPDATE creature_template SET ScriptName = 'boss_essence_of_anger' WHERE entry = 23420; -- Essence of Anger +UPDATE creature_template SET ScriptName = 'boss_najentus' WHERE entry = 22887; -- High Warlord Naj'entus +UPDATE creature_template SET ScriptName = 'boss_gurtogg_bloodboil' WHERE entry = 22948; -- Gurtogg Bloodboil +UPDATE creature_template SET ScriptName = 'boss_mother_shahraz' WHERE entry = 22947; -- Mother Shahraz +UPDATE creature_template SET ScriptName = 'boss_lady_malande' WHERE entry = 22951; -- Priest <3 at Illidari Council +UPDATE creature_template SET ScriptName = 'boss_illidan_stormrage' WHERE entry = 22917; -- Illidan The Betrayer! +UPDATE creature_template SET ScriptName = 'boss_high_nethermancer_zerevor' WHERE entry = 22950; -- Mage at Illidari Council +UPDATE creature_template SET ScriptName = 'boss_gathios_the_shatterer' WHERE entry = 22949; -- Paladin at Illidari Council +UPDATE creature_template SET ScriptName = 'boss_maiev_shadowsong' WHERE entry = 23197; -- Maiev Shadowsong +UPDATE creature_template SET ScriptName = 'mob_blaze' WHERE entry = 23259; -- Blaze mob in Illidan Phase 2 +UPDATE creature_template SET ScriptName = 'mob_flame_of_azzinoth' WHERE entry = 22997; -- Flame of Azzinoth (Illidan Phase 2) +UPDATE creature_template SET ScriptName = 'mob_demon_fire' WHERE entry = 23069; -- Demon Fire in Illidan Phase 2 +UPDATE creature_template SET ScriptName = 'mob_flame_crash' WHERE entry = 23336; -- Flame Crash in Illidan Normal Form +UPDATE creature_template SET ScriptName = 'mob_cage_trap_trigger' WHERE entry = 23304; -- Cage Trap mob in Illidan Phase 3/4 Normal +UPDATE creature_template SET ScriptName = 'mob_shadow_demon' WHERE entry = 23375; -- Shadow Demon in Illidan Demon Form +UPDATE creature_template SET ScriptName = 'npc_volcano' WHERE entry = 23085; -- Supremus Volcano +UPDATE creature_template SET ScriptName = 'molten_flame' WHERE entry = 23095; -- Molten Flame in SUpremus +UPDATE creature_template SET ScriptName = 'mob_ashtongue_channeler' WHERE entry = 23421; -- Ashtongue CHanneler in Shade of AKama +UPDATE creature_template SET ScriptName = 'mob_ashtongue_sorcerer' WHERE entry = 23215; -- Ashtongue Sorcerer in Shade of Akama +UPDATE creature_template SET ScriptName = 'npc_enslaved_soul' WHERE entry = 23469; -- Enslaved Soul in Reliquary Event +-- UPDATE creature_template SET ScriptName = 'mob_najentus_spine' WHERE entry = 500000; -- Workaround creature for spine in Najentus event \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r257_mangos.sql b/src/bindings/scripts/sql/Updates/r257_mangos.sql new file mode 100644 index 00000000000..1bed2c9f098 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r257_mangos.sql @@ -0,0 +1,4 @@ +UPDATE `creature_template` SET `ScriptName` = 'npc_archmage_malin' WHERE `entry` = 2708; +UPDATE `creature_template` SET `ScriptName` = 'npc_dashel_stonefist' WHERE `entry` = 4961; +UPDATE `creature_template` SET `ScriptName` = 'npc_doctor' WHERE `entry` IN (12939, 12920); +UPDATE `creature_template` SET `ScriptName` = 'npc_injured_patient' WHERE `entry` IN (12936, 12937, 12938, 12923, 12924, 12925); diff --git a/src/bindings/scripts/sql/Updates/r258_mangos.sql b/src/bindings/scripts/sql/Updates/r258_mangos.sql new file mode 100644 index 00000000000..18970d669da --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r258_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName` = 'npc_deathly_usher' WHERE `entry` = 8816; diff --git a/src/bindings/scripts/sql/Updates/r260_mangos.sql b/src/bindings/scripts/sql/Updates/r260_mangos.sql new file mode 100644 index 00000000000..e96598d09e1 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r260_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName` = 'npc_lady_katrana_prestor' WHERE `entry` = 1749; diff --git a/src/bindings/scripts/sql/Updates/r261_mangos.sql b/src/bindings/scripts/sql/Updates/r261_mangos.sql new file mode 100644 index 00000000000..b1c8e6312a9 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r261_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName` = 'npc_general_marcus_jonathan' WHERE `entry` = 466; diff --git a/src/bindings/scripts/sql/Updates/r262_mangos.sql b/src/bindings/scripts/sql/Updates/r262_mangos.sql new file mode 100644 index 00000000000..225b7c38437 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r262_mangos.sql @@ -0,0 +1,3 @@ +UPDATE `creature_template` SET `ScriptName` = 'npc_royal_historian_archesonus' WHERE `entry` = 8879; +UPDATE `creature_template` SET `ScriptName` = 'npc_bunthen_plainswind' WHERE `entry` = 11798; +UPDATE `creature_template` SET `ScriptName` = 'npc_silva_filnaveth' WHERE `entry` = 11800; diff --git a/src/bindings/scripts/sql/Updates/r263_mangos.sql b/src/bindings/scripts/sql/Updates/r263_mangos.sql new file mode 100644 index 00000000000..a3ff56a0bd7 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r263_mangos.sql @@ -0,0 +1,3 @@ +UPDATE `gameobject_template` SET `ScriptName` = 'go_northern_crystal_pylon' WHERE `entry` = 164955; +UPDATE `gameobject_template` SET `ScriptName` = 'go_western_crystal_pylon' WHERE `entry` = 164956; +UPDATE `gameobject_template` SET `ScriptName` = 'go_eastern_crystal_pylon' WHERE `entry` = 164957; diff --git a/src/bindings/scripts/sql/Updates/r264_mangos.sql b/src/bindings/scripts/sql/Updates/r264_mangos.sql new file mode 100644 index 00000000000..410f1de42d5 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r264_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName` = 'npc_astor_hadren' WHERE `entry` = 6497; diff --git a/src/bindings/scripts/sql/Updates/r265_mangos.sql b/src/bindings/scripts/sql/Updates/r265_mangos.sql new file mode 100644 index 00000000000..4eaed94ee10 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r265_mangos.sql @@ -0,0 +1,9 @@ +UPDATE `item_template` SET `ScriptName` = 'item_nether_wraith_beacon' WHERE `entry` = 31742; +UPDATE `item_template` SET `ScriptName` = 'item_area_52_special' WHERE `entry` = 28132; +UPDATE `item_template` SET `ScriptName` = 'item_vorenthals_presence' WHERE `entry` = 30259; +UPDATE `item_template` SET `ScriptName` = 'item_draenei_fishing_net' WHERE `entry` = 23654; +UPDATE `item_template` SET `ScriptName` = 'item_skin_of_purest_water' WHERE `entry` = 23751; +UPDATE `item_template` SET `ScriptName` = 'item_yehkinyas_bramble' WHERE `entry` = 10699; +UPDATE `item_template` SET `ScriptName` = 'item_zezzaks_shard' WHERE `entry` = 31463; +UPDATE `creature_template` SET `ScriptName` = '' WHERE `entry` IN (40100,40101,40102,40103,40104,40105,40106,40107,40108,40109,40110,40111,40112,40113); +UPDATE `creature_template` SET `ScriptName` = '' WHERE `entry` IN (40200,40201,40202,40203,40204,40205,40206,40207,40208,40209,40210,40211,40212,40213); diff --git a/src/bindings/scripts/sql/Updates/r269_mangos.sql b/src/bindings/scripts/sql/Updates/r269_mangos.sql new file mode 100644 index 00000000000..95ed715301a --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r269_mangos.sql @@ -0,0 +1,6 @@ +-- removing old script names that does no longer exist +UPDATE `creature_template` SET `ScriptName` = '' WHERE `entry` IN (12198,14982,857,12197,7427,347,15007,2804); +UPDATE `creature_template` SET `ScriptName` = '' WHERE `entry` IN (9564,12136,3149,12137,9566,3150,9559,9558); +UPDATE `creature_template` SET `ScriptName` = '' WHERE `entry` = 197; +UPDATE `creature_template` SET `ScriptName` = '' WHERE `entry` IN (11328, 11260); +UPDATE `creature_template` SET `ScriptName` = '' WHERE `entry` IN (80, 1236, 3578, 40, 1358, 1360, 5996, 1426, 1094, 674); diff --git a/src/bindings/scripts/sql/Updates/r270_mangos.sql b/src/bindings/scripts/sql/Updates/r270_mangos.sql new file mode 100644 index 00000000000..2d7ffe0c432 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r270_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName` = 'npc_overseer_nuaar' WHERE `entry` = 21981; diff --git a/src/bindings/scripts/sql/Updates/r271_mangos.sql b/src/bindings/scripts/sql/Updates/r271_mangos.sql new file mode 100644 index 00000000000..74fcb02284d --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r271_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName` = 'npc_greatmother_geyah' WHERE `entry` = 18141; diff --git a/src/bindings/scripts/sql/Updates/r272_mangos.sql b/src/bindings/scripts/sql/Updates/r272_mangos.sql new file mode 100644 index 00000000000..3e5313f20e0 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r272_mangos.sql @@ -0,0 +1,8 @@ +UPDATE `creature_template` SET `ScriptName` = 'boss_kaelthas' WHERE `entry` = 23054; +UPDATE `creature_template` SET `ScriptName` = 'boss_thaladred_the_darkener' WHERE `entry` = 20064; +UPDATE `creature_template` SET `ScriptName` = 'boss_lord_sanguinar' WHERE `entry` = 20060; +UPDATE `creature_template` SET `ScriptName` = 'boss_grand_astromancer_capernian' WHERE `entry` = 20062; +UPDATE `creature_template` SET `ScriptName` = 'boss_master_engineer_telonicus' WHERE `entry` = 20063; +UPDATE `creature_template` SET `ScriptName` = 'mob_phoenix' WHERE `entry` = 21362; +UPDATE `creature_template` SET `ScriptName` = 'mob_nether_vapor' WHERE `entry` = 21002; +UPDATE `creature_template` SET `ScriptName` = 'mob_kael_flamestrike' WHERE `entry` = 21369; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r273_mangos.sql b/src/bindings/scripts/sql/Updates/r273_mangos.sql new file mode 100644 index 00000000000..db98e282f09 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r273_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName` = 'npc_saikkal_the_elder' WHERE `entry` = 22932; diff --git a/src/bindings/scripts/sql/Updates/r274_mangos.sql b/src/bindings/scripts/sql/Updates/r274_mangos.sql new file mode 100644 index 00000000000..fef98f84e11 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r274_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName` = 'mob_blackwing_lair' WHERE `entry` = 12557; diff --git a/src/bindings/scripts/sql/Updates/r275_mangos.sql b/src/bindings/scripts/sql/Updates/r275_mangos.sql new file mode 100644 index 00000000000..618666b80e1 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r275_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName` = 'mob_shade_of_jindo' WHERE `entry` = 14986; diff --git a/src/bindings/scripts/sql/Updates/r281_scriptdev2.sql b/src/bindings/scripts/sql/Updates/r281_scriptdev2.sql new file mode 100644 index 00000000000..719d1ee7852 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r281_scriptdev2.sql @@ -0,0 +1,35 @@ +ALTER TABLE eventai_scripts +ADD event_chance tinyint(3) unsigned NOT NULL default 100 AFTER event_inverse_phase_mask; + +-- EVENT_T_TIMER_REPEAT +UPDATE eventai_scripts SET event_chance = -event_param3 WHERE event_type = 0 AND event_param3 < 0; + +-- EVENT_T_TIMER_SINGLE +UPDATE eventai_scripts SET event_chance = event_param2 WHERE event_type = 1; + +-- EVENT_T_TIMER_OOC_REPEAT +UPDATE eventai_scripts SET event_chance = -event_param3 WHERE event_type = 2 AND event_param3 < 0; + +-- EVENT_T_TIMER_OOC_SINGLE +UPDATE eventai_scripts SET event_chance = event_param2 WHERE event_type = 3; + +-- EVENT_T_HP_SINGLE +UPDATE eventai_scripts SET event_chance = -event_param3 WHERE event_type = 4 AND event_param3 < 0; + +-- EVENT_T_MANA_SINGLE +UPDATE eventai_scripts SET event_chance = -event_param3 WHERE event_type = 5 AND event_param3 < 0; + +-- EVENT_T_AGGRO +UPDATE eventai_scripts SET event_chance = event_param1 WHERE event_type = 6; + +-- EVENT_T_KILL +UPDATE eventai_scripts SET event_chance = event_param2 WHERE event_type = 7; + +-- EVENT_T_DEATH +UPDATE eventai_scripts SET event_chance = event_param1 WHERE event_type = 8; + +-- EVENT_T_EVADE +UPDATE eventai_scripts SET event_chance = event_param1 WHERE event_type = 9; + +-- EVENT_T_SPELLHIT +UPDATE eventai_scripts SET event_chance = event_param3 WHERE event_type = 10; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r282_mangos.sql b/src/bindings/scripts/sql/Updates/r282_mangos.sql new file mode 100644 index 00000000000..93ea058523a --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r282_mangos.sql @@ -0,0 +1,38 @@ +UPDATE creature_template SET ScriptName = 'npc_tyrande_whisperwind' WHERE entry = 17948; +UPDATE creature_template SET ScriptName = 'npc_thrall' WHERE entry = 17852; +UPDATE creature_template SET ScriptName = 'npc_jaina_proudmoore' WHERE entry = 17772; + +UPDATE creature_template SET ScriptName = 'npc_akama_shade' WHERE entry = 23089; -- Akama at Shade of Akama +UPDATE creature_template SET ScriptName = 'npc_akama_illidan' WHERE entry = 22990; -- Akama at Illidan +UPDATE creature_template SET ScriptName = 'illidari_council' WHERE entry = 23426; -- Illidari Council controller mob +UPDATE creature_template SET ScriptName = 'boss_veras_darkshadow' WHERE entry = 22952; -- Rogue of Illidari Council +UPDATE creature_template SET ScriptName = 'boss_teron_gorefiend' WHERE entry = 22871; -- Teron Gorefiend +UPDATE creature_template SET ScriptName = 'boss_supremus' WHERE entry = 22898; -- Supremus +UPDATE creature_template SET ScriptName = 'boss_shade_of_akama' WHERE entry = 22841; -- Shade of Akama +UPDATE creature_template SET ScriptName = 'boss_reliquary_of_souls' WHERE entry = 22856; -- Reliquary Controller Mob +UPDATE creature_template SET ScriptName = 'boss_essence_of_suffering' WHERE entry = 23418; -- Essence Of Suffering +UPDATE creature_template SET ScriptName = 'boss_essence_of_desire' WHERE entry = 23419; -- Essence of Desire +UPDATE creature_template SET ScriptName = 'boss_essence_of_anger' WHERE entry = 23420; -- Essence of Anger +UPDATE creature_template SET ScriptName = 'boss_najentus' WHERE entry = 22887; -- High Warlord Naj'entus +UPDATE creature_template SET ScriptName = 'boss_gurtogg_bloodboil' WHERE entry = 22948; -- Gurtogg Bloodboil +UPDATE creature_template SET ScriptName = 'boss_mother_shahraz' WHERE entry = 22947; -- Mother Shahraz +UPDATE creature_template SET ScriptName = 'boss_lady_malande' WHERE entry = 22951; -- Priest <3 at Illidari Council +UPDATE creature_template SET ScriptName = 'boss_illidan_stormrage' WHERE entry = 22917; -- Illidan The Betrayer! +UPDATE creature_template SET ScriptName = 'boss_high_nethermancer_zerevor' WHERE entry = 22950; -- Mage at Illidari Council +UPDATE creature_template SET ScriptName = 'boss_gathios_the_shatterer' WHERE entry = 22949; -- Paladin at Illidari Council +UPDATE creature_template SET ScriptName = 'boss_maiev_shadowsong' WHERE entry = 23197; -- Maiev Shadowsong +UPDATE creature_template SET ScriptName = 'mob_blaze' WHERE entry = 23259; -- Blaze mob in Illidan Phase 2 +UPDATE creature_template SET ScriptName = 'mob_flame_of_azzinoth' WHERE entry = 22997; -- Flame of Azzinoth (Illidan Phase 2) +UPDATE creature_template SET ScriptName = 'mob_blade_of_azzinoth' WHERE entry = 22996; -- Blade of Azzinoth (Illidan Phase 2) +UPDATE creature_template SET ScriptName = 'mob_demon_fire' WHERE entry = 23069; -- Demon Fire in Illidan Phase 2 +UPDATE creature_template SET ScriptName = 'mob_flame_crash' WHERE entry = 23336; -- Flame Crash in Illidan Normal Form +UPDATE creature_template SET ScriptName = 'mob_cage_trap_trigger' WHERE entry = 23304; -- Cage Trap mob in Illidan Phase 3/4 Normal +UPDATE creature_template SET ScriptName = 'mob_shadow_demon' WHERE entry = 23375; -- Shadow Demon in Illidan Demon Form +UPDATE creature_template SET ScriptName = 'npc_volcano' WHERE entry = 23085; -- Supremus Volcano +UPDATE creature_template SET ScriptName = 'molten_flame' WHERE entry = 23095; -- Molten Flame in SUpremus +UPDATE creature_template SET ScriptName = 'mob_ashtongue_channeler' WHERE entry = 23421; -- Ashtongue CHanneler in Shade of AKama +UPDATE creature_template SET ScriptName = 'mob_ashtongue_sorcerer' WHERE entry = 23215; -- Ashtongue Sorcerer in Shade of Akama +UPDATE creature_template SET ScriptName = 'npc_enslaved_soul' WHERE entry = 23469; -- Enslaved Soul in Reliquary Event +UPDATE creature_template SET ScriptName = 'mob_doom_blossom' WHERE entry = 23123; -- Doom Blossoms in Teron Gorefiend's encounter +-- UPDATE creature_template sET ScriptName = 'mob_shadowy_construct' WHERE entry = 23111; -- Shadowy Construct in Teron Gorefiend's encounter. Commented until Mind Control is implemented. +-- UPDATE creature_template SET ScriptName = 'mob_najentus_spine' WHERE entry = 500000; -- Workaround creature for spine in Najentus event diff --git a/src/bindings/scripts/sql/Updates/r286_mangos.sql b/src/bindings/scripts/sql/Updates/r286_mangos.sql new file mode 100644 index 00000000000..d1d0a14dfa5 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r286_mangos.sql @@ -0,0 +1,2 @@ +-- Items +UPDATE `item_template` SET `ScriptName` = '' WHERE `entry` = 23751; -- Remove script for Skin of Purest Water \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r289_mangos.sql b/src/bindings/scripts/sql/Updates/r289_mangos.sql new file mode 100644 index 00000000000..48e08ebb878 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r289_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `scriptname` = 'npc_creditmarker_visit_with_ancestors' WHERE `entry` IN (18840,18841,18842,18843); \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r291_mangos.sql b/src/bindings/scripts/sql/Updates/r291_mangos.sql new file mode 100644 index 00000000000..a85fb7bf34c --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r291_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName` = 'mob_spawn_of_fankriss' WHERE `entry` = 15630; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r295_mangos.sql b/src/bindings/scripts/sql/Updates/r295_mangos.sql new file mode 100644 index 00000000000..b992e0ee630 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r295_mangos.sql @@ -0,0 +1,2 @@ +UPDATE `instance_template` SET `script` = 'instance_stratholme' WHERE `map` = 329; +UPDATE `creature_template` SET `ScriptName` = 'boss_silver_hand_bosses' WHERE `entry` IN (17910, 17911, 17912, 17913, 17914); diff --git a/src/bindings/scripts/sql/Updates/r297_mangos.sql b/src/bindings/scripts/sql/Updates/r297_mangos.sql new file mode 100644 index 00000000000..702013c465b --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r297_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName` = 'npc_berthold' WHERE `entry` = 16153; diff --git a/src/bindings/scripts/sql/Updates/r298_scriptdev2.sql b/src/bindings/scripts/sql/Updates/r298_scriptdev2.sql new file mode 100644 index 00000000000..953baee559b --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r298_scriptdev2.sql @@ -0,0 +1,2 @@ +-- EVENT_T_SPELLHIT +UPDATE eventai_scripts SET event_param3 = event_param2, event_param2 = -1 WHERE event_type = 10; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r299_scriptdev2.sql b/src/bindings/scripts/sql/Updates/r299_scriptdev2.sql new file mode 100644 index 00000000000..8b835b0ed7c --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r299_scriptdev2.sql @@ -0,0 +1,9 @@ +CREATE TABLE `eventai_summons` ( +`id` int(11) unsigned NOT NULL COMMENT 'Location Identifier' AUTO_INCREMENT, +`position_x` float NOT NULL default '0', +`position_y` float NOT NULL default '0', +`position_z` float NOT NULL default '0', +`orientation` float NOT NULL default '0', +`spawntimesecs` int(11) unsigned NOT NULL default '120', +PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='EventAI Summoning Locations'; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r304_mangos.sql b/src/bindings/scripts/sql/Updates/r304_mangos.sql new file mode 100644 index 00000000000..2a6ed9c0f60 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r304_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName` = '' WHERE `entry` IN (15440, 15612); diff --git a/src/bindings/scripts/sql/Updates/r306_scriptdev2.sql b/src/bindings/scripts/sql/Updates/r306_scriptdev2.sql new file mode 100644 index 00000000000..60eac88d01e --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r306_scriptdev2.sql @@ -0,0 +1,4 @@ +DROP TABLE IF EXISTS `db_version`; +CREATE TABLE `db_version` ( +`version` varchar(255) NOT NULL default '' COMMENT 'Database version string' +) ENGINE=MyISAM DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r307_mangos.sql b/src/bindings/scripts/sql/Updates/r307_mangos.sql new file mode 100644 index 00000000000..e239d40700d --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r307_mangos.sql @@ -0,0 +1,4 @@ +UPDATE `creature_template` SET `ScriptName` = 'npcs_dithers_and_arbington' WHERE `entry` IN (11056, 11057); +UPDATE `creature_template` SET `ScriptName` = 'npc_witch_doctor_mauari' WHERE `entry` = 10307; +UPDATE `creature_template` SET `ScriptName` = 'npcs_riverbreeze_and_silversky' WHERE `entry` IN (9528, 9529); +UPDATE `creature_template` SET `ScriptName` = 'npc_sayge' WHERE `entry` = 14822; diff --git a/src/bindings/scripts/sql/Updates/r308_mangos.sql b/src/bindings/scripts/sql/Updates/r308_mangos.sql new file mode 100644 index 00000000000..b3c16a91402 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r308_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName` = 'npc_nat_pagle' WHERE `entry` = 12919; diff --git a/src/bindings/scripts/sql/Updates/r309_mangos.sql b/src/bindings/scripts/sql/Updates/r309_mangos.sql new file mode 100644 index 00000000000..03bd078c7ab --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r309_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName` = 'mob_webbed_creature' WHERE `entry` = 17680; diff --git a/src/bindings/scripts/sql/Updates/r311_mangos.sql b/src/bindings/scripts/sql/Updates/r311_mangos.sql new file mode 100644 index 00000000000..22cb325623b --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r311_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName` = 'npc_invis_legion_teleporter' WHERE `entry` = 21807; diff --git a/src/bindings/scripts/sql/Updates/r312_mangos.sql b/src/bindings/scripts/sql/Updates/r312_mangos.sql new file mode 100644 index 00000000000..978152764bd --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r312_mangos.sql @@ -0,0 +1,2 @@ +UPDATE `creature_template` SET `ScriptName` = 'npc_captured_sunhawk_agent' WHERE `entry` = 17824; +UPDATE `creature_template` SET `ScriptName` = 'npc_neltharaku' WHERE `entry` = 21657; diff --git a/src/bindings/scripts/sql/Updates/r318_mangos.sql b/src/bindings/scripts/sql/Updates/r318_mangos.sql new file mode 100644 index 00000000000..5ce2afca20f --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r318_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName` = 'npcs_flanis_swiftwing_and_kagrosh' WHERE `entry` IN (21725, 21727); diff --git a/src/bindings/scripts/sql/Updates/r324_mangos.sql b/src/bindings/scripts/sql/Updates/r324_mangos.sql new file mode 100644 index 00000000000..4b9fb91dc2d --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r324_mangos.sql @@ -0,0 +1,3 @@ +UPDATE `creature_template` SET `ScriptName` = 'npc_mortog_steamhead' WHERE `entry` = 23373; +UPDATE `creature_template` SET `ScriptName` = 'npc_veronia' WHERE `entry` = 20162; +UPDATE `creature_template` SET `ScriptName` = 'npc_susurrus' WHERE `entry` = 17435; diff --git a/src/bindings/scripts/sql/Updates/r327_mangos.sql b/src/bindings/scripts/sql/Updates/r327_mangos.sql new file mode 100644 index 00000000000..d2d56fdfc3c --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r327_mangos.sql @@ -0,0 +1,5 @@ +-- Sunspring Villagers. +UPDATE `creature_template` SET `ScriptName` = 'mob_sunspring_villager' WHERE `entry` = 18240; + +-- Terestian Illhoof +UPDATE `creature_template` SET `ScriptName` = 'mob_demon_chain' WHERE `entry` = 17248; diff --git a/src/bindings/scripts/sql/Updates/r332_scriptdev2.sql b/src/bindings/scripts/sql/Updates/r332_scriptdev2.sql new file mode 100644 index 00000000000..ea67d3e7392 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r332_scriptdev2.sql @@ -0,0 +1,2 @@ +ALTER TABLE eventai_summons +ADD `comment` varchar(255) NOT NULL default '' COMMENT 'Summon Comment' AFTER spawntimesecs; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r333_mangos.sql b/src/bindings/scripts/sql/Updates/r333_mangos.sql new file mode 100644 index 00000000000..48a7f673fad --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r333_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName` = 'npc_oronok_tornheart' WHERE `entry` = 21183; diff --git a/src/bindings/scripts/sql/Updates/r334_mangos.sql b/src/bindings/scripts/sql/Updates/r334_mangos.sql new file mode 100644 index 00000000000..5d010c62209 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r334_mangos.sql @@ -0,0 +1 @@ +UPDATE `instance_template` SET `script` = 'instance_sethekk_halls' WHERE `map` = 556; diff --git a/src/bindings/scripts/sql/Updates/r336_mangos.sql b/src/bindings/scripts/sql/Updates/r336_mangos.sql new file mode 100644 index 00000000000..993b954bb4b --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r336_mangos.sql @@ -0,0 +1,9 @@ +UPDATE `gameobject_template` SET `ScriptName` = 'go_tablet_of_madness' WHERE `entry` = 180368; +UPDATE `creature_template` SET `ScriptName` = 'boss_grilek' WHERE `entry` = 15082; +UPDATE `creature_template` SET `ScriptName` = 'boss_hazzarah' WHERE `entry` = 15083; +UPDATE `creature_template` SET `ScriptName` = 'boss_renataki' WHERE `entry` = 15084; +UPDATE `creature_template` SET `ScriptName` = 'boss_wushoolay' WHERE `entry` = 15085; +UPDATE `creature_template` SET `ScriptName` = 'mobs_zulgurub' WHERE `entry` = 14883; +UPDATE `creature_template` SET `ScriptName` = 'mob_blackwing_lair' WHERE `entry` = 12468; + + diff --git a/src/bindings/scripts/sql/Updates/r352_mangos.sql b/src/bindings/scripts/sql/Updates/r352_mangos.sql new file mode 100644 index 00000000000..a40281bcd33 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r352_mangos.sql @@ -0,0 +1,23 @@ +-- Moroes +update creature_template set scriptname = "boss_moroes" where entry = 15687; +update creature_template set scriptname = "boss_baroness_dorothea_millstipe" where entry = 19875; +update creature_template set scriptname = "boss_baron_rafe_dreuger" where entry = 19874; +update creature_template set scriptname = "boss_lady_catriona_von_indi" where entry = 19872; +update creature_template set scriptname = "boss_lady_keira_berrybuck" where entry = 17007; +update creature_template set scriptname = "boss_lord_robin_daris" where entry = 19876; +update creature_template set scriptname = "boss_lord_crispin_ference" where entry = 19873; + +-- Barnes +update creature_template set scriptname = "npc_barnes" where entry = 16812; +-- Oz Event +update creature_template set scriptname = "boss_dorothee" where entry = 17535; +update creature_template set scriptname = "boss_strawman" where entry = 17543; +update creature_template set scriptname = "boss_tinhead" where entry = 17547; +update creature_template set scriptname = "boss_roar" where entry = 17546; +update creature_template set scriptname = "boss_crone" where entry = 18168; +-- Hood Event +update creature_template set scriptname = "npc_grandmother" where entry = 17603; +update creature_template set scriptname = "boss_bigbadwolf" where entry = 17521; +-- Romeo and Juliet disabled for now +-- update creature_template set scriptname = "boss_julianne" where entry = 17543; +-- update creature_template set scriptname = "boss_romulo" where entry = 17533; diff --git a/src/bindings/scripts/sql/Updates/r355_mangos.sql b/src/bindings/scripts/sql/Updates/r355_mangos.sql new file mode 100644 index 00000000000..a40281bcd33 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r355_mangos.sql @@ -0,0 +1,23 @@ +-- Moroes +update creature_template set scriptname = "boss_moroes" where entry = 15687; +update creature_template set scriptname = "boss_baroness_dorothea_millstipe" where entry = 19875; +update creature_template set scriptname = "boss_baron_rafe_dreuger" where entry = 19874; +update creature_template set scriptname = "boss_lady_catriona_von_indi" where entry = 19872; +update creature_template set scriptname = "boss_lady_keira_berrybuck" where entry = 17007; +update creature_template set scriptname = "boss_lord_robin_daris" where entry = 19876; +update creature_template set scriptname = "boss_lord_crispin_ference" where entry = 19873; + +-- Barnes +update creature_template set scriptname = "npc_barnes" where entry = 16812; +-- Oz Event +update creature_template set scriptname = "boss_dorothee" where entry = 17535; +update creature_template set scriptname = "boss_strawman" where entry = 17543; +update creature_template set scriptname = "boss_tinhead" where entry = 17547; +update creature_template set scriptname = "boss_roar" where entry = 17546; +update creature_template set scriptname = "boss_crone" where entry = 18168; +-- Hood Event +update creature_template set scriptname = "npc_grandmother" where entry = 17603; +update creature_template set scriptname = "boss_bigbadwolf" where entry = 17521; +-- Romeo and Juliet disabled for now +-- update creature_template set scriptname = "boss_julianne" where entry = 17543; +-- update creature_template set scriptname = "boss_romulo" where entry = 17533; diff --git a/src/bindings/scripts/sql/Updates/r358_mangos.sql b/src/bindings/scripts/sql/Updates/r358_mangos.sql new file mode 100644 index 00000000000..01db3736d2e --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r358_mangos.sql @@ -0,0 +1 @@ +update creature_template set scriptname = "mob_cyclone" where entry = 18412; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r364_mangos.sql b/src/bindings/scripts/sql/Updates/r364_mangos.sql new file mode 100644 index 00000000000..d893f4d923c --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r364_mangos.sql @@ -0,0 +1,7 @@ +UPDATE `creature_template` SET `ScriptName` = 'npc_ayren_cloudbreaker' WHERE `entry` = 25059; +UPDATE `creature_template` SET `ScriptName` = 'npc_unrestrained_dragonhawk' WHERE `entry` = 25236; +UPDATE `creature_template` SET `ScriptName` = 'npc_sputtervalve' WHERE `entry` = 3442; +UPDATE `creature_template` SET `ScriptName` = 'npc_budd_nedreck' WHERE `entry` = 23559; +UPDATE `creature_template` SET `ScriptName` = 'npc_blood_knight_dawnstar' WHERE `entry` = 17832; +UPDATE `creature_template` SET `ScriptName` = 'npc_stone_watcher_of_norgannon' WHERE `entry` = 7918; +UPDATE `creature_template` SET `ScriptName` = 'npc_lore_keeper_of_norgannon' WHERE `entry` = 7172; diff --git a/src/bindings/scripts/sql/Updates/r367_mangos.sql b/src/bindings/scripts/sql/Updates/r367_mangos.sql new file mode 100644 index 00000000000..29a27c7d745 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r367_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName` = 'mob_aquementas' WHERE `entry` = 9453; diff --git a/src/bindings/scripts/sql/Updates/r368_mangos.sql b/src/bindings/scripts/sql/Updates/r368_mangos.sql new file mode 100644 index 00000000000..b4cf82da064 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r368_mangos.sql @@ -0,0 +1,5 @@ +UPDATE `instance_template` SET `script` = 'instance_shadowfang_keep' WHERE `map` = 33; +UPDATE `creature_template` SET `ScriptName` = 'boss_fenrus' WHERE `entry` = 4274; +UPDATE `creature_template` SET `ScriptName` = 'boss_nandos' WHERE `entry` = 3927; +UPDATE `creature_template` SET `ScriptName` = 'boss_rethilgore' WHERE `entry` = 3914; +UPDATE `creature_template` SET `ScriptName` = 'npc_shadowfang_prisoner' WHERE `entry` IN (3849, 3850); diff --git a/src/bindings/scripts/sql/Updates/r369_mangos.sql b/src/bindings/scripts/sql/Updates/r369_mangos.sql new file mode 100644 index 00000000000..1d053e5f583 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r369_mangos.sql @@ -0,0 +1,5 @@ +UPDATE `creature_template` SET `ScriptName` = 'boss_rage_winterchill' WHERE `entry` = 17767; +UPDATE `creature_template` SET `ScriptName` = 'boss_anetheron' WHERE `entry` = 17808; +UPDATE `creature_template` SET `ScriptName` = 'boss_kazrogal' WHERE `entry` = 17888; +UPDATE `creature_template` SET `ScriptName` = 'boss_azgalor' WHERE `entry` = 17842; +UPDATE `creature_template` SET `ScriptName` = 'mob_echo_of_archimonde' WHERE `entry` = 13083; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r374_mangos.sql b/src/bindings/scripts/sql/Updates/r374_mangos.sql new file mode 100644 index 00000000000..f430c086f00 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r374_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName` = 'npc_the_scourge_cauldron' WHERE `entry` = 11152; diff --git a/src/bindings/scripts/sql/Updates/r386_mangos.sql b/src/bindings/scripts/sql/Updates/r386_mangos.sql new file mode 100644 index 00000000000..7913666b5ce --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r386_mangos.sql @@ -0,0 +1,7 @@ +UPDATE `item_template` SET `ScriptName` = 'item_Sparrowhawk_Net' WHERE `entry` = 32321; +UPDATE `item_template` SET `ScriptName` = 'item_Blackwhelp_Net' WHERE `entry` = 31129; + +UPDATE `creature_template` SET `ScriptName` = 'npc_spirit_of_olum' WHERE `entry` = 23411; + +UPDATE creature_template SET ScriptName='boss_warp_splinter' WHERE entry='17977'; +UPDATE creature_template SET ScriptName='mob_warp_splinter_treant' WHERE entry='19949'; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r417_mangos.sql b/src/bindings/scripts/sql/Updates/r417_mangos.sql new file mode 100644 index 00000000000..c9c08fe598b --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r417_mangos.sql @@ -0,0 +1 @@ +UPDATE `item_template` SET `ScriptName` = 'item_tame_beast_rods' WHERE `entry` IN (15908,15911,15913,15914,15915,15916,15917,15919,15920,15921,15922,15923,23697,23702,23703,23896,23897,23898); diff --git a/src/bindings/scripts/sql/Updates/r428_mangos.sql b/src/bindings/scripts/sql/Updates/r428_mangos.sql new file mode 100644 index 00000000000..997c636332d --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r428_mangos.sql @@ -0,0 +1,4 @@ +-- Quest Support 10804 (Kindness) +UPDATE creature_template SET scriptname = 'mob_mature_netherwing_drake' WHERE entry = 21648; +-- Quest Support 10854 (The Force of Neltharaku) +UPDATE creature_template SET scriptname = 'mob_enslaved_netherwing_drake' WHERE entry = 21722; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r431_mangos.sql b/src/bindings/scripts/sql/Updates/r431_mangos.sql new file mode 100644 index 00000000000..bd8481815eb --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r431_mangos.sql @@ -0,0 +1,4 @@ +UPDATE `creature_template` SET `ScriptName`='npc_zephyr' WHERE `entry`=25967; +UPDATE `instance_template` SET `script`='instance_old_hillsbrad' WHERE `map`=560; +UPDATE `creature_template` SET `ScriptName`='npc_brazen' WHERE `entry`=18725; +UPDATE `creature_template` SET `ScriptName`='npc_erozion' WHERE `entry`=18723; diff --git a/src/bindings/scripts/sql/Updates/r444_mangos.sql b/src/bindings/scripts/sql/Updates/r444_mangos.sql new file mode 100644 index 00000000000..c45fa7b9620 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r444_mangos.sql @@ -0,0 +1,5 @@ +UPDATE `creature_template` SET `ScriptName`='' WHERE `entry`=22120; +UPDATE `creature_template` SET `ScriptName`='mob_fathom_sporebat' WHERE `entry`=22140; +UPDATE `creature_template` SET `ScriptName`='' WHERE `entry`=20318; +UPDATE `creature_template` SET `ScriptName`='mob_eventai' WHERE `entry` IN (3927,3914,4274); +UPDATE `creature_template` SET `ScriptName`='mob_eventai' WHERE `entry` IN (21717,21718,21719,21720,22331,21878,21879,18371,18343,13083,17808); diff --git a/src/bindings/scripts/sql/Updates/r445_mangos.sql b/src/bindings/scripts/sql/Updates/r445_mangos.sql new file mode 100644 index 00000000000..5ca5011dd4e --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r445_mangos.sql @@ -0,0 +1,2 @@ +UPDATE `creature_template` SET `ScriptName`='boss_high_astromancer_solarian' WHERE `entry`=18805; +UPDATE `creature_template` SET `ScriptName`='mob_solarium_priest' WHERE `entry`=18806; diff --git a/src/bindings/scripts/sql/Updates/r446_mangos.sql b/src/bindings/scripts/sql/Updates/r446_mangos.sql new file mode 100644 index 00000000000..a8a819e3b67 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r446_mangos.sql @@ -0,0 +1,2 @@ +-- Set ACID (mob_eventai) ScriptName for 4 Hyjal-wave bosses +UPDATE `creature_template` SET `ScriptName` = 'mob_eventai' WHERE `entry` IN (17767, 17808, 17888, 17842); diff --git a/src/bindings/scripts/sql/Updates/r448_scriptdev2.sql b/src/bindings/scripts/sql/Updates/r448_scriptdev2.sql new file mode 100644 index 00000000000..66d78082aa0 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r448_scriptdev2.sql @@ -0,0 +1,5 @@ +DROP TABLE IF EXISTS `db_version`; +DROP TABLE IF EXISTS `sd2_db_version`; +CREATE TABLE `sd2_db_version` ( +`version` varchar(255) NOT NULL default '' COMMENT 'Database version string' +) ENGINE=MyISAM DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r462_mangos.sql b/src/bindings/scripts/sql/Updates/r462_mangos.sql new file mode 100644 index 00000000000..6d8ac269de3 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r462_mangos.sql @@ -0,0 +1,2 @@ +UPDATE `creature_template` SET `ScriptName`='npc_taretha' WHERE `entry`=18887; +UPDATE `creature_template` SET `ScriptName`='npc_thrall_old_hillsbrad' WHERE `entry`=17876; diff --git a/src/bindings/scripts/sql/Updates/r465_mangos.sql b/src/bindings/scripts/sql/Updates/r465_mangos.sql new file mode 100644 index 00000000000..35d7d3834f1 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r465_mangos.sql @@ -0,0 +1,3 @@ +UPDATE `creature_template` SET `ScriptName`='boss_harbinger_skyriss' WHERE `entry`=20912; +UPDATE `creature_template` SET `ScriptName`='npc_warden_mellichar' WHERE `entry`=20904; +UPDATE `creature_template` SET `ScriptName`='npc_millhouse_manastorm' WHERE `entry`=20977; diff --git a/src/bindings/scripts/sql/Updates/r467_mangos.sql b/src/bindings/scripts/sql/Updates/r467_mangos.sql new file mode 100644 index 00000000000..711bba7cc94 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r467_mangos.sql @@ -0,0 +1 @@ +UPDATE `item_template` SET `ScriptName`='item_flying_machine' WHERE `entry` IN (34060,34061); diff --git a/src/bindings/scripts/sql/Updates/r473_mangos.sql b/src/bindings/scripts/sql/Updates/r473_mangos.sql new file mode 100644 index 00000000000..f9918bc1b71 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r473_mangos.sql @@ -0,0 +1,3 @@ +UPDATE `item_template` SET `ScriptName`='item_soul_cannon' WHERE `entry`=32825; +UPDATE `item_template` SET `ScriptName`='item_sparrowhawk_net' WHERE `entry`=32321; +UPDATE `item_template` SET `ScriptName`='item_blackwhelp_net' WHERE `entry`=31129; diff --git a/src/bindings/scripts/sql/Updates/r476_mangos.sql b/src/bindings/scripts/sql/Updates/r476_mangos.sql new file mode 100644 index 00000000000..998045f2193 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r476_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName`='npc_engineer_spark_overgrind' WHERE `entry`=17243; diff --git a/src/bindings/scripts/sql/Updates/r477_mangos.sql b/src/bindings/scripts/sql/Updates/r477_mangos.sql new file mode 100644 index 00000000000..0f9c76c5336 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r477_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName`='' WHERE `entry`=19577; diff --git a/src/bindings/scripts/sql/Updates/r479_mangos.sql b/src/bindings/scripts/sql/Updates/r479_mangos.sql new file mode 100644 index 00000000000..216fe068317 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r479_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName`='npc_chicken_cluck' WHERE `entry`=620; diff --git a/src/bindings/scripts/sql/Updates/r482_mangos.sql b/src/bindings/scripts/sql/Updates/r482_mangos.sql new file mode 100644 index 00000000000..b431b85c90e --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r482_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName`='npc_dancing_flames' WHERE `entry`=25305; diff --git a/src/bindings/scripts/sql/Updates/r484_mangos.sql b/src/bindings/scripts/sql/Updates/r484_mangos.sql new file mode 100644 index 00000000000..1f4fefd7fa1 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r484_mangos.sql @@ -0,0 +1,8 @@ +-- Quest support 9678 +UPDATE `gameobject_template` SET `ScriptName`='go_gilded_brazier' WHERE `entry` = '181956'; + +-- Archimonde with related creatures. +UPDATE `creature_template` SET `Scriptname` = "boss_archimonde" WHERE `entry` = 17968; +UPDATE `creature_template` SET `ScriptName` = "mob_doomfire" WHERE `entry` = 18095; +UPDATE `creature_template` SET `Scriptname` = "mob_doomfire_targetting" WHERE `entry` = 18104; +UPDATE `creature_template` SET `ScriptName` = "mob_ancient_wisp" WHERE `entry` = 17946; diff --git a/src/bindings/scripts/sql/Updates/r486_mangos.sql b/src/bindings/scripts/sql/Updates/r486_mangos.sql new file mode 100644 index 00000000000..28920abf0db --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r486_mangos.sql @@ -0,0 +1 @@ +UPDATE `gameobject_template` SET `ScriptName`='' WHERE `entry`=181956; diff --git a/src/bindings/scripts/sql/Updates/r487_mangos.sql b/src/bindings/scripts/sql/Updates/r487_mangos.sql new file mode 100644 index 00000000000..229be423977 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r487_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName`='npc_prospector_anvilward' WHERE `entry`=15420; diff --git a/src/bindings/scripts/sql/Updates/r494_mangos.sql b/src/bindings/scripts/sql/Updates/r494_mangos.sql new file mode 100644 index 00000000000..c8f5aef5d9a --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r494_mangos.sql @@ -0,0 +1 @@ +UPDATE `gameobject_template` SET `ScriptName` = 'gameobject_cage_trap' WHERE `entry` = 185916; diff --git a/src/bindings/scripts/sql/Updates/r501_mangos.sql b/src/bindings/scripts/sql/Updates/r501_mangos.sql new file mode 100644 index 00000000000..7242f3b8a7b --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r501_mangos.sql @@ -0,0 +1,4 @@ +UPDATE `creature_template` SET `ScriptName`='npc_prof_alchemy' WHERE `entry` IN (17909,19052,22427); +UPDATE `creature_template` SET `ScriptName`='npc_prof_blacksmith' WHERE `entry` IN (5164,11145,11146,11176,11177,11178,11191,11192,11193); +UPDATE `creature_template` SET `ScriptName`='npc_prof_leather' WHERE `entry` IN (7866,7867,7868,7869,7870,7871); +UPDATE `creature_template` SET `ScriptName`='npc_prof_tailor' WHERE `entry` IN (22208,22212,22213); diff --git a/src/bindings/scripts/sql/Updates/r513_mangos.sql b/src/bindings/scripts/sql/Updates/r513_mangos.sql new file mode 100644 index 00000000000..fcc3433fa59 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r513_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName`='npc_salsalabim' WHERE `entry`=18584; diff --git a/src/bindings/scripts/sql/Updates/r514_mangos.sql b/src/bindings/scripts/sql/Updates/r514_mangos.sql new file mode 100644 index 00000000000..108948250d9 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r514_mangos.sql @@ -0,0 +1,3 @@ +UPDATE `creature_template` SET `ScriptName`='npc_raliq_the_drunk' WHERE `entry`=18585; +UPDATE `creature_template` SET `ScriptName`='npc_cooshcoosh' WHERE `entry`=18586; +UPDATE `creature_template` SET `ScriptName`='npc_floon' WHERE `entry`=18588; diff --git a/src/bindings/scripts/sql/Updates/r515_mangos.sql b/src/bindings/scripts/sql/Updates/r515_mangos.sql new file mode 100644 index 00000000000..8860641d493 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r515_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName`='npc_murkblood_overseer' WHERE `entry`=23309; diff --git a/src/bindings/scripts/sql/Updates/r516_mangos.sql b/src/bindings/scripts/sql/Updates/r516_mangos.sql new file mode 100644 index 00000000000..76bd7b83780 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r516_mangos.sql @@ -0,0 +1,3 @@ +UPDATE `creature_template` SET `ScriptName`='npc_neeru_fireblade' WHERE `entry`=3216; +UPDATE `creature_template` SET `ScriptName`='npc_shenthul' WHERE `entry`=3401; +UPDATE `creature_template` SET `ScriptName`='npc_thrall_warchief' WHERE `entry`=4949; diff --git a/src/bindings/scripts/sql/Updates/r517_mangos.sql b/src/bindings/scripts/sql/Updates/r517_mangos.sql new file mode 100644 index 00000000000..2077e416c81 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r517_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName`='npc_taskmaster_fizzule' WHERE `entry`=7233; diff --git a/src/bindings/scripts/sql/Updates/r518_mangos.sql b/src/bindings/scripts/sql/Updates/r518_mangos.sql new file mode 100644 index 00000000000..5930aba9256 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r518_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName`='npc_rathis_tomber' WHERE `entry`=16224; diff --git a/src/bindings/scripts/sql/Updates/r519_mangos.sql b/src/bindings/scripts/sql/Updates/r519_mangos.sql new file mode 100644 index 00000000000..fa408a043ec --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r519_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName`='npc_calvin_montague' WHERE `entry`=6784; diff --git a/src/bindings/scripts/sql/Updates/r520_mangos.sql b/src/bindings/scripts/sql/Updates/r520_mangos.sql new file mode 100644 index 00000000000..959ac79be55 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r520_mangos.sql @@ -0,0 +1,2 @@ +UPDATE `item_template` SET `ScriptName`='item_disciplinary_rod' WHERE `entry`=22473; +UPDATE `item_template` SET `ScriptName`='item_protovoltaic_magneto_collector' WHERE `entry`=30656; diff --git a/src/bindings/scripts/sql/Updates/r521_mangos.sql b/src/bindings/scripts/sql/Updates/r521_mangos.sql new file mode 100644 index 00000000000..37d09546b0a --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r521_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName`='npc_gregan_brewspewer' WHERE `entry`=7775; diff --git a/src/bindings/scripts/sql/Updates/r522_mangos.sql b/src/bindings/scripts/sql/Updates/r522_mangos.sql new file mode 100644 index 00000000000..159e6e83826 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r522_mangos.sql @@ -0,0 +1,2 @@ +UPDATE `creature_template` SET `ScriptName`='guard_shattrath_aldor' WHERE `entry`=18549; +UPDATE `creature_template` SET `ScriptName`='guard_shattrath_scryer' WHERE `entry`=18568; diff --git a/src/bindings/scripts/sql/Updates/r526_mangos.sql b/src/bindings/scripts/sql/Updates/r526_mangos.sql new file mode 100644 index 00000000000..2171bed6570 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r526_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName`='npc_injured_draenei' WHERE `entry`=16971; diff --git a/src/bindings/scripts/sql/Updates/r528_mangos.sql b/src/bindings/scripts/sql/Updates/r528_mangos.sql new file mode 100644 index 00000000000..90b63aabe40 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r528_mangos.sql @@ -0,0 +1,2 @@ +UPDATE `creature_template` SET `ScriptName`='npc_skorn_whitecloud' WHERE `entry`=3052; +UPDATE `creature_template` SET `ScriptName`='npc_blood_knight_stillblade' WHERE `entry`=17768; diff --git a/src/bindings/scripts/sql/Updates/r533_mangos.sql b/src/bindings/scripts/sql/Updates/r533_mangos.sql new file mode 100644 index 00000000000..a05d4bfb732 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r533_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName`='npc_augustus_the_touched' WHERE `entry`=12384; diff --git a/src/bindings/scripts/sql/Updates/r538_scriptdev2.sql b/src/bindings/scripts/sql/Updates/r538_scriptdev2.sql new file mode 100644 index 00000000000..92ef9ea24ff --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r538_scriptdev2.sql @@ -0,0 +1,60 @@ +-- Structure updates + +ALTER TABLE eventai_scripts +ADD event_flags tinyint(3) unsigned NOT NULL default '0' AFTER event_chance; + +ALTER TABLE eventai_scripts +ADD event_param4 int(11) signed NOT NULL default '0' AFTER event_param3; + +-- Event updates + +-- EVENT_T_TIMER_REPEAT +UPDATE eventai_scripts SET event_param4 = event_param3+event_param1, event_param3 = event_param1, event_param1 = event_param2, event_flags = 1 WHERE event_type = 0; + +-- EVENT_T_TIMER_SINGLE +UPDATE eventai_scripts SET event_param4 = event_param3+event_param1, event_param3 = event_param1, event_param1 = event_param2, event_type = 0 WHERE event_type = 1; + +-- EVENT_T_TIMER_OOC_REPEAT +UPDATE eventai_scripts SET event_param4 = event_param3+event_param1, event_param3 = event_param1, event_param1 = event_param2, event_flags = 1, event_type = 1 WHERE event_type = 2; + +-- EVENT_T_TIMER_OOC_SINGLE +UPDATE eventai_scripts SET event_param4 = event_param3+event_param1, event_param3 = event_param1, event_param1 = event_param2, event_type = 1 WHERE event_type = 3; + +-- EVENT_T_HP_SINGLE +UPDATE eventai_scripts SET event_param4 = event_param3, event_flags = 0, event_type = 2 WHERE event_type = 4; + +-- EVENT_T_MANA_SINGLE +UPDATE eventai_scripts SET event_param4 = event_param3, event_flags = 0, event_type = 3 WHERE event_type = 5; + +-- EVENT_T_AGGRO +UPDATE eventai_scripts SET event_type = 4 WHERE event_type = 6; + +-- EVENT_T_KILL +UPDATE eventai_scripts SET event_param2 = event_param1, event_flags = 1, event_type = 5 WHERE event_type = 7; + +-- EVENT_T_DEATH +UPDATE eventai_scripts SET event_type = 6 WHERE event_type = 8; + +-- EVENT_T_EVADE +UPDATE eventai_scripts SET event_type = 7 WHERE event_type = 9; + +-- EVENT_T_SPELLHIT +UPDATE eventai_scripts SET event_param4 = event_param3, event_flags = 1, event_type = 8 WHERE event_type = 10; + +-- EVENT_T_RANGE +UPDATE eventai_scripts SET event_param4 = event_param3, event_flags = 1, event_type = 9 WHERE event_type = 11; + +-- EVENT_T_OOC_LOS +UPDATE eventai_scripts SET event_param4 = event_param3, event_flags = 1, event_type = 10 WHERE event_type = 12; + +-- EVENT_T_SPAWNED +UPDATE eventai_scripts SET event_type = 11 WHERE event_type = 13; + +-- EVENT_T_TARGET_HP +UPDATE eventai_scripts SET event_param4 = event_param3, event_flags = 1, event_type = 12 WHERE event_type = 14; + +-- EVENT_T_TARGET_CASTING +UPDATE eventai_scripts SET event_param2 = event_param1, event_flags = 1, event_type = 13 WHERE event_type = 15; + +-- EVENT_T_FRIENDLY_HP +UPDATE eventai_scripts SET event_param4 = event_param3, event_flags = 1, event_type = 14 WHERE event_type = 16; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r547_mangos.sql b/src/bindings/scripts/sql/Updates/r547_mangos.sql new file mode 100644 index 00000000000..cc98862022e --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r547_mangos.sql @@ -0,0 +1,22 @@ +/* Magister's Terrace */ +UPDATE `instance_template` SET `script` = 'instance_magisters_terrace' WHERE `map` = 585; +UPDATE `creature_template` SET `ScriptName` = 'boss_selin_fireheart' WHERE `entry` = 24723; +UPDATE `creature_template` SET `ScriptName` = 'mob_fel_crystal' WHERE `entry` = 24722; +UPDATE `creature_template` SET `ScriptName` = 'boss_vexallus' WHERE `entry` = 24744; +UPDATE `creature_template` SET `ScriptName` = 'mob_pure_energy' WHERE `entry` = 24745; +UPDATE `creature_template` SET `ScriptName` = 'boss_priestess_delrissa' WHERE `entry` = 24560; +UPDATE `creature_template` SET `ScriptName` = 'boss_kagani_nightstrike' WHERE `entry` = 24557; +UPDATE `creature_template` SET `ScriptName` = 'boss_ellris_duskhallow' WHERE `entry` = 24558; +UPDATE `creature_template` SET `ScriptName` = 'mob_imp' WHERE `entry` = 24656; +UPDATE `creature_template` SET `ScriptName` = 'boss_eramas_brightblaze' WHERE `entry` = 24554; +UPDATE `creature_template` SET `ScriptName` = 'boss_yazzai' WHERE `entry` = 24561; +UPDATE `creature_template` SET `ScriptName` = 'boss_warlord_salaris' WHERE `entry` = 24559; +UPDATE `creature_template` SET `ScriptName` = 'boss_garaxxas' WHERE `entry` = 24555; +UPDATE `creature_template` SET `ScriptName` = 'mob_sliver' WHERE `entry` = 24552; +UPDATE `creature_template` SET `ScriptName` = 'boss_apoko' WHERE `entry` = 24553; +UPDATE `creature_template` SET `ScriptName` = 'boss_zelfan' WHERE `entry` = 24556; +UPDATE `creature_template` SET `ScriptName` = 'boss_felblood_kaelthas' WHERE `entry` = 24664; +UPDATE `creature_template` SET `ScriptName` = 'mob_arcane_sphere' WHERE `entry` = 24708; +UPDATE `creature_template` SET `ScriptName` = 'mob_felkael_phoenix' WHERE `entry` = 24674; +UPDATE `creature_template` SET `ScriptName` = 'mob_felkael_phoenix_egg' WHERE `entry` = 24675; +UPDATE `creature_template` SET `ScriptName` = 'mob_felkael_flamestrike' WHERE `entry` = 24666; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r554_mangos.sql b/src/bindings/scripts/sql/Updates/r554_mangos.sql new file mode 100644 index 00000000000..b6beac3adce --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r554_mangos.sql @@ -0,0 +1,3 @@ +UPDATE `creature_template` SET `ScriptName`='boss_mekgineer_steamrigger' WHERE `entry`=17796; +UPDATE `creature_template` SET `ScriptName`='mob_steamrigger_mechanic' WHERE `entry`=17951; +UPDATE `creature_template` SET `ScriptName`='mob_naga_distiller' WHERE `entry`=17954; diff --git a/src/bindings/scripts/sql/Updates/r555_mangos.sql b/src/bindings/scripts/sql/Updates/r555_mangos.sql new file mode 100644 index 00000000000..f0284ddd037 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r555_mangos.sql @@ -0,0 +1,2 @@ +UPDATE `gameobject_template` SET `ScriptName`='go_manaforge_control_console' WHERE `entry` IN (183770,183956,184311,184312); +UPDATE `creature_template` SET `ScriptName`='npc_manaforge_control_console' WHERE `entry` IN (20209,20417,20418,20440); diff --git a/src/bindings/scripts/sql/Updates/r56.sql b/src/bindings/scripts/sql/Updates/r56.sql new file mode 100644 index 00000000000..69e31e9e21c --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r56.sql @@ -0,0 +1,2 @@ +/* Remove guildmaster script from npc's. Core has full support */ +UPDATE `creature_template` SET `ScriptName` = '' WHERE `entry` IN (4974,5054,4613); diff --git a/src/bindings/scripts/sql/Updates/r575_mangos.sql b/src/bindings/scripts/sql/Updates/r575_mangos.sql new file mode 100644 index 00000000000..bbf52bd5c96 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r575_mangos.sql @@ -0,0 +1 @@ +UPDATE `item_template` SET `ScriptName`='item_gor_dreks_ointment' WHERE `entry`=30175; diff --git a/src/bindings/scripts/sql/Updates/r576_mangos.sql b/src/bindings/scripts/sql/Updates/r576_mangos.sql new file mode 100644 index 00000000000..0df34443309 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r576_mangos.sql @@ -0,0 +1 @@ +UPDATE `item_template` SET `ScriptName`='item_muiseks_vessel' WHERE `entry` IN (9606,9618,9619,9620,9621); diff --git a/src/bindings/scripts/sql/Updates/r578_mangos.sql b/src/bindings/scripts/sql/Updates/r578_mangos.sql new file mode 100644 index 00000000000..f82ea62c26e --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r578_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName`='npc_forest_frog' WHERE `entry`=24396; diff --git a/src/bindings/scripts/sql/Updates/r584_mangos.sql b/src/bindings/scripts/sql/Updates/r584_mangos.sql new file mode 100644 index 00000000000..0980b86cc4e --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r584_mangos.sql @@ -0,0 +1 @@ +UPDATE `item_template` SET `ScriptName`='item_voodoo_charm' WHERE `entry`=8149; diff --git a/src/bindings/scripts/sql/Updates/r59.sql b/src/bindings/scripts/sql/Updates/r59.sql new file mode 100644 index 00000000000..219f96220b1 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r59.sql @@ -0,0 +1,3 @@ +UPDATE `creature_template` SET `ScriptName` = 'npc_narm_faulk' WHERE `entry`= 6177; +UPDATE `creature_template` SET `ScriptName` = 'npc_q8304' WHERE `entry` IN (15170, 15171); +UPDATE `creature_template` SET `ScriptName` = 'npc_q8507_q8731' WHERE `entry` IN (15440, 15612); \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r590_mangos.sql b/src/bindings/scripts/sql/Updates/r590_mangos.sql new file mode 100644 index 00000000000..72348756d91 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r590_mangos.sql @@ -0,0 +1,2 @@ +UPDATE `creature_template` SET `ScriptName`='npc_sergeant_bly' WHERE `entry`=7604; +UPDATE `creature_template` SET `ScriptName`='npc_weegli_blastfuse' WHERE `entry`=7607; diff --git a/src/bindings/scripts/sql/Updates/r591_mangos.sql b/src/bindings/scripts/sql/Updates/r591_mangos.sql new file mode 100644 index 00000000000..253fe3ed53b --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r591_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName`='mobs_nether_drake' WHERE `entry` IN (20021,21817,21820,21821,21823); diff --git a/src/bindings/scripts/sql/Updates/r593_mangos.sql b/src/bindings/scripts/sql/Updates/r593_mangos.sql new file mode 100644 index 00000000000..ec6730e3d4e --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r593_mangos.sql @@ -0,0 +1 @@ +UPDATE `gameobject_template` SET `ScriptName`='go_tablet_of_the_seven' WHERE `entry`=169294; diff --git a/src/bindings/scripts/sql/Updates/r594_mangos.sql b/src/bindings/scripts/sql/Updates/r594_mangos.sql new file mode 100644 index 00000000000..3315fd47241 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r594_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName`='mob_anubisath_sentinel' WHERE `entry`=15264; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r596_mangos.sql b/src/bindings/scripts/sql/Updates/r596_mangos.sql new file mode 100644 index 00000000000..2f0e4587883 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r596_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName`='boss_ambassador_hellmaw' WHERE `entry`=18731; diff --git a/src/bindings/scripts/sql/Updates/r610_mangos.sql b/src/bindings/scripts/sql/Updates/r610_mangos.sql new file mode 100644 index 00000000000..1aa9f4b50b4 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r610_mangos.sql @@ -0,0 +1,2 @@ +UPDATE `creature_template` SET `ScriptName`='npc_lady_sylvanas_windrunner' WHERE `entry`=10181; +UPDATE `creature_template` SET `ScriptName`='npc_highborne_lamenter' WHERE `entry`=21628; diff --git a/src/bindings/scripts/sql/Updates/r615_scriptdev2.sql b/src/bindings/scripts/sql/Updates/r615_scriptdev2.sql new file mode 100644 index 00000000000..5c5625860f8 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r615_scriptdev2.sql @@ -0,0 +1,4 @@ +-- Structure updates + +ALTER TABLE localized_texts +ADD `locale_8` varchar(255) NOT NULL default '' AFTER locale_7; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r617_mangos.sql b/src/bindings/scripts/sql/Updates/r617_mangos.sql new file mode 100644 index 00000000000..7a30f9c553d --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r617_mangos.sql @@ -0,0 +1 @@ +UPDATE `item_template` SET `ScriptName`='item_razorthorn_flayer_gland' WHERE `entry`=34255; diff --git a/src/bindings/scripts/sql/Updates/r621_mangos.sql b/src/bindings/scripts/sql/Updates/r621_mangos.sql new file mode 100644 index 00000000000..822de701ebb --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r621_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName`='boss_talon_king_ikiss' WHERE `entry`=18473; diff --git a/src/bindings/scripts/sql/Updates/r628_mangos.sql b/src/bindings/scripts/sql/Updates/r628_mangos.sql new file mode 100644 index 00000000000..47d286d2718 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r628_mangos.sql @@ -0,0 +1,3 @@ +UPDATE `instance_template` SET `script`='instance_shattered_halls' WHERE `map`=540; +UPDATE `creature_template` SET `ScriptName`='mob_fel_orc_convert' WHERE `entry`=17083; +UPDATE `creature_template` SET `ScriptName`='mob_lesser_shadow_fissure' WHERE `entry`=17471; diff --git a/src/bindings/scripts/sql/Updates/r63.sql b/src/bindings/scripts/sql/Updates/r63.sql new file mode 100644 index 00000000000..4627d40067b --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r63.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName` = 'npc_bartleby' WHERE `entry` IN (6090); \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r632_mangos.sql b/src/bindings/scripts/sql/Updates/r632_mangos.sql new file mode 100644 index 00000000000..4ea0c35e6ea --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r632_mangos.sql @@ -0,0 +1,2 @@ +UPDATE `creature_template` SET `ScriptName`='boss_warbringer_omrogg' WHERE `entry`=16809; +UPDATE `creature_template` SET `ScriptName`='mob_omrogg_heads' WHERE `entry` IN (19523,19524); diff --git a/src/bindings/scripts/sql/Updates/r633_mangos.sql b/src/bindings/scripts/sql/Updates/r633_mangos.sql new file mode 100644 index 00000000000..bbf75d1f961 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r633_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName`='npc_rogue_trainer' WHERE `entry` IN (918,4163,3328,4583,5165,5167,13283,16684); diff --git a/src/bindings/scripts/sql/Updates/r634_scriptdev2.sql b/src/bindings/scripts/sql/Updates/r634_scriptdev2.sql new file mode 100644 index 00000000000..31791a57084 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r634_scriptdev2.sql @@ -0,0 +1,35 @@ +DROP TABLE IF EXISTS `script_texts`; +CREATE TABLE `script_texts` ( +`ScriptName` varchar(255) NOT NULL default '', +`Id` int(11) unsigned NOT NULL default '0', +`Sound` int(11) unsigned NOT NULL default '0', +`Type` int(11) unsigned NOT NULL default '0', +`Language` int(11) unsigned NOT NULL default '0', +`Text` varchar(255) NOT NULL default '', +`Comment` varchar(255) NOT NULL default '', +PRIMARY KEY (`ScriptName`,`Id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Script Texts'; + + +DROP TABLE IF EXISTS `script_localized_texts`; +CREATE TABLE `script_localized_texts` ( +`id` int(11) unsigned NOT NULL auto_increment COMMENT 'Identifier', +`locale_1` varchar(255) NOT NULL default '', +`locale_2` varchar(255) NOT NULL default '', +`locale_3` varchar(255) NOT NULL default '', +`locale_4` varchar(255) NOT NULL default '', +`locale_5` varchar(255) NOT NULL default '', +`locale_6` varchar(255) NOT NULL default '', +`locale_7` varchar(255) NOT NULL default '', +`locale_8` varchar(255) NOT NULL default '', +`comment` varchar(255) NOT NULL default '' COMMENT 'Text Comment', +PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Localized Script Text'; + + +DROP TABLE IF EXISTS `eventai_texts`; +CREATE TABLE `eventai_texts` AS SELECT `id`, `locale_0` AS `text`, `comment` FROM `localized_texts`; +TRUNCATE TABLE `localized_texts`; +DROP TABLE IF EXISTS `eventai_localized_texts`; +ALTER TABLE `localized_texts` RENAME TO `eventai_localized_texts`; +ALTER TABLE `eventai_localized_texts` DROP COLUMN `locale_0`; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r636_mangos.sql b/src/bindings/scripts/sql/Updates/r636_mangos.sql new file mode 100644 index 00000000000..55eea42bf2a --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r636_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName`='boss_laj' WHERE `entry`=17980; diff --git a/src/bindings/scripts/sql/Updates/r637_mangos.sql b/src/bindings/scripts/sql/Updates/r637_mangos.sql new file mode 100644 index 00000000000..03a53749cab --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r637_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName`='boss_high_botanist_freywinn' WHERE `entry`=17975; diff --git a/src/bindings/scripts/sql/Updates/r638_mangos.sql b/src/bindings/scripts/sql/Updates/r638_mangos.sql new file mode 100644 index 00000000000..cf20d33e957 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r638_mangos.sql @@ -0,0 +1,2 @@ +UPDATE `item_template` SET `ScriptName`='item_attuned_crystal_cores' WHERE `entry`=34368; +UPDATE `creature_template` SET `ScriptName`='npc_converted_sentry' WHERE `entry`=24981; diff --git a/src/bindings/scripts/sql/Updates/r639_mangos.sql b/src/bindings/scripts/sql/Updates/r639_mangos.sql new file mode 100644 index 00000000000..7946ac237ed --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r639_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName`='npc_ravenholdt' WHERE `entry`=13936; diff --git a/src/bindings/scripts/sql/Updates/r642_mangos.sql b/src/bindings/scripts/sql/Updates/r642_mangos.sql new file mode 100644 index 00000000000..b9963728279 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r642_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName`='mob_shadowmoon_channeler' WHERE `entry`=17653; diff --git a/src/bindings/scripts/sql/Updates/r643_mangos.sql b/src/bindings/scripts/sql/Updates/r643_mangos.sql new file mode 100644 index 00000000000..8659ebcb850 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r643_mangos.sql @@ -0,0 +1,2 @@ +UPDATE `creature_template` SET `ScriptName`='mob_stolen_soul' WHERE `entry`=18441; +UPDATE `creature_template` SET `ScriptName`='mob_avatar_of_martyred' WHERE `entry`=18478; diff --git a/src/bindings/scripts/sql/Updates/r646_mangos.sql b/src/bindings/scripts/sql/Updates/r646_mangos.sql new file mode 100644 index 00000000000..3f43d49bc32 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r646_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName`='boss_harbinger_skyriss_illusion' WHERE `entry` IN (21466,21467); diff --git a/src/bindings/scripts/sql/Updates/r647_scriptdev2.sql b/src/bindings/scripts/sql/Updates/r647_scriptdev2.sql new file mode 100644 index 00000000000..bd259718b81 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r647_scriptdev2.sql @@ -0,0 +1,10 @@ +DROP TABLE IF EXISTS `script_texts`; +CREATE TABLE `script_texts` ( +`id` int(11) unsigned NOT NULL auto_increment COMMENT 'Identifier', +`sound` int(11) unsigned NOT NULL default '0', +`type` int(11) unsigned NOT NULL default '0', +`language` int(11) unsigned NOT NULL default '0', +`text` varchar(255) NOT NULL default '', +`comment` varchar(255) NOT NULL default '', +PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Script Texts'; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r65.sql b/src/bindings/scripts/sql/Updates/r65.sql new file mode 100644 index 00000000000..2c878bfed56 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r65.sql @@ -0,0 +1,2 @@ +UPDATE `creature_template` SET `npcflag`='3', `ScriptName`='npc_lothos_riftwalker' WHERE `entry`='14387'; +UPDATE creature_template SET ScriptName="boss_gruul" WHERE entry=19044; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r656_scriptdev2.sql b/src/bindings/scripts/sql/Updates/r656_scriptdev2.sql new file mode 100644 index 00000000000..96fcd146d76 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r656_scriptdev2.sql @@ -0,0 +1,5 @@ +ALTER TABLE +`eventai_localized_texts` ADD COLUMN `locale_8` varchar(255) NOT NULL default '' AFTER locale_7; + +ALTER TABLE +`script_localized_texts` ADD COLUMN `locale_8` varchar(255) NOT NULL default '' AFTER locale_7; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r658_mangos.sql b/src/bindings/scripts/sql/Updates/r658_mangos.sql new file mode 100644 index 00000000000..50ae5fcbd4c --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r658_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName`='npc_custodian_of_time' WHERE `entry`=20129; diff --git a/src/bindings/scripts/sql/Updates/r659_mangos.sql b/src/bindings/scripts/sql/Updates/r659_mangos.sql new file mode 100644 index 00000000000..feb9379b8af --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r659_mangos.sql @@ -0,0 +1,4 @@ +UPDATE `creature_template` SET `ScriptName`='npc_akama_shade' WHERE `entry`=22990; -- Akama at Shade of Akama +UPDATE `creature_template` SET `ScriptName`='npc_akama_illidan' WHERE `entry`=23089; -- Akama at Illidan +UPDATE `creature_template` SET `ScriptName`='mob_illidari_council' WHERE `entry`=23426; -- Illidari Council controller mob +UPDATE `creature_template` SET `ScriptName`='mob_blood_elf_council_voice_trigger' WHERE `entry` = 23499; -- Voice Trigger Mob (Controls Aggro + Enrage yells) diff --git a/src/bindings/scripts/sql/Updates/r72.sql b/src/bindings/scripts/sql/Updates/r72.sql new file mode 100644 index 00000000000..fd79e95cd66 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r72.sql @@ -0,0 +1,4 @@ +UPDATE `creature_template` SET `ScriptName` = 'mobs_mana_tapped' WHERE `entry` IN (15273,15274,15294,15298,15367); +UPDATE `creature_template` SET `ScriptName` = 'mobs_ghoul_flayer' WHERE `entry` IN (8530, 8531, 8532); +UPDATE `creature_template` SET `ScriptName` = 'mobs_bonechewer_orc' WHERE `entry` IN (16876, 16925, 18952, 19701); +UPDATE `item_template` SET `ScriptName` = 'purification_mixture' WHERE `entry`= 23268; \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r78.sql b/src/bindings/scripts/sql/Updates/r78.sql new file mode 100644 index 00000000000..783482aed8e --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r78.sql @@ -0,0 +1,3 @@ +UPDATE `item_template` SET `ScriptName` = 'nether_wraith_beacon' WHERE `entry` = 31742; +UPDATE `item_template` SET `ScriptName` = 'area_52_special' WHERE `entry` = 28132; +UPDATE `creature_template` SET `ScriptName` = 'guard_shattrath' WHERE `entry` = 19687; diff --git a/src/bindings/scripts/sql/Updates/r81.sql b/src/bindings/scripts/sql/Updates/r81.sql new file mode 100644 index 00000000000..c1785f088d8 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r81.sql @@ -0,0 +1,35 @@ +UPDATE `creature_template` SET `ScriptName` = 'boss_gyth' WHERE `entry` = 10339; +UPDATE `creature_template` SET `ScriptName` = 'boss_rend_blackhand' WHERE `entry` = 10429; +UPDATE `creature_template` SET `ScriptName` = 'boss_pyroguard_emberseer' WHERE `entry` = 9816; +UPDATE `creature_template` SET `ScriptName` = 'mob_chromatic_elite_guard' WHERE `entry` = 10814; +UPDATE `creature_template` SET `ScriptName` = 'mob_ancient_core_hound' WHERE `entry` = 11673; +UPDATE `creature_template` SET `ScriptName` = 'mob_core_rager' WHERE `entry` = 11672; +UPDATE `creature_template` SET `ScriptName` = 'mob_firesworn' WHERE `entry` = 12099; +UPDATE `creature_template` SET `ScriptName` = 'mob_firewalker' WHERE `entry` = 11666; +UPDATE `creature_template` SET `ScriptName` = 'mob_flame_guard' WHERE `entry` = 11667; +UPDATE `creature_template` SET `ScriptName` = 'mob_flamewaker' WHERE `entry` = 11661; +UPDATE `creature_template` SET `ScriptName` = 'mob_flamewaker_elite' WHERE `entry` = 11664; +UPDATE `creature_template` SET `ScriptName` = 'mob_flamewaker_healer' WHERE `entry` = 11663; +UPDATE `creature_template` SET `ScriptName` = 'mob_flamewaker_protector' WHERE `entry` = 12119; +UPDATE `creature_template` SET `ScriptName` = 'mob_lavaspawn' WHERE `entry` = 12265; +UPDATE `creature_template` SET `ScriptName` = 'mob_molten_destroyer' WHERE `entry` = 11659; +UPDATE `creature_template` SET `ScriptName` = 'mob_molten_giant' WHERE `entry` = 11658; +UPDATE `creature_template` SET `ScriptName` = 'boss_azuregos' WHERE `entry` = 6109; + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r91.sql b/src/bindings/scripts/sql/Updates/r91.sql new file mode 100644 index 00000000000..bd7fc1131ac --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r91.sql @@ -0,0 +1,2 @@ +UPDATE `creature_template` SET `ScriptName` = 'npc_great_bear_spirit' WHERE `entry` = 11956; +UPDATE `creature_template` SET `ScriptName` = 'npcs_rutgar_and_frankal.cpp' WHERE `entry` IN (15170, 15171); \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r92.sql b/src/bindings/scripts/sql/Updates/r92.sql new file mode 100644 index 00000000000..b149b69c19c --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r92.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName` = 'npcs_rutgar_and_frankal' WHERE `entry` IN (15170, 15171); \ No newline at end of file diff --git a/src/bindings/scripts/sql/Updates/r97.sql b/src/bindings/scripts/sql/Updates/r97.sql new file mode 100644 index 00000000000..95934d6ce15 --- /dev/null +++ b/src/bindings/scripts/sql/Updates/r97.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName` = 'npcs_captains_blackanvil_and_skullsplit' WHERE `entry` IN (15440, 15612); diff --git a/src/bindings/scripts/sql/create_database.sql b/src/bindings/scripts/sql/create_database.sql new file mode 100644 index 00000000000..747dab2acb1 --- /dev/null +++ b/src/bindings/scripts/sql/create_database.sql @@ -0,0 +1,4 @@ +CREATE DATABASE `scriptdev2` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; + +GRANT ALL PRIVILEGES ON `scriptdev2` . * TO 'mangos'@'localhost' WITH GRANT OPTION; + diff --git a/src/bindings/scripts/sql/mangos_full_scripts.sql b/src/bindings/scripts/sql/mangos_full_scripts.sql new file mode 100644 index 00000000000..d63662a5866 --- /dev/null +++ b/src/bindings/scripts/sql/mangos_full_scripts.sql @@ -0,0 +1,871 @@ +/* */ + +/* WORLD BOSS */ +UPDATE `creature_template` SET `ScriptName`='boss_ysondre' WHERE `entry`=14887; +UPDATE `creature_template` SET `ScriptName`='boss_emeriss' WHERE `entry`=14889; +UPDATE `creature_template` SET `ScriptName`='boss_taerar' WHERE `entry`=14890; +UPDATE `creature_template` SET `ScriptName`='boss_shade_of_taerar' WHERE `entry`=15302; +UPDATE `creature_template` SET `ScriptName`='boss_kruul' WHERE `entry`=18338; +UPDATE `creature_template` SET `ScriptName`='boss_azuregos' WHERE `entry`=6109; +UPDATE `creature_template` SET `ScriptName`='mob_dementeddruids' WHERE `entry`=15260; + +/* GO */ +UPDATE `gameobject_template` SET `ScriptName`='go_northern_crystal_pylon' WHERE `entry`=164955; +UPDATE `gameobject_template` SET `ScriptName`='go_western_crystal_pylon' WHERE `entry`=164956; +UPDATE `gameobject_template` SET `ScriptName`='go_eastern_crystal_pylon' WHERE `entry`=164957; +UPDATE `gameobject_template` SET `ScriptName`='go_barov_journal' WHERE `entry`=180794; +UPDATE `gameobject_template` SET `ScriptName`='go_field_repair_bot_74A' where `entry`= 179552; +UPDATE `gameobject_template` SET `ScriptName`='go_orb_of_command' WHERE `entry`=179879; +UPDATE `gameobject_template` SET `ScriptName`='go_tablet_of_madness' WHERE `entry`=180368; +UPDATE `gameobject_template` SET `ScriptName`='go_tablet_of_the_seven' WHERE `entry`=169294; + +/* GUARD */ +UPDATE `creature_template` SET `ScriptName`='guard_azuremyst' WHERE `entry`=18038; +UPDATE `creature_template` SET `ScriptName`='guard_orgrimmar' WHERE `entry`=3296; +UPDATE `creature_template` SET `ScriptName`='guard_stormwind' WHERE `entry` IN (68,1976); +UPDATE `creature_template` SET `ScriptName`='guard_contested' WHERE `entry` IN (9460,4624,3502,11190,15184); +UPDATE `creature_template` SET `ScriptName`='guard_elwynnforest' WHERE `entry`=1423; +UPDATE `creature_template` SET `ScriptName`='guard_eversong' WHERE `entry`=16221; +UPDATE `creature_template` SET `ScriptName`='guard_darnassus' WHERE `entry`=4262; +UPDATE `creature_template` SET `ScriptName`='guard_teldrassil' WHERE `entry`=3571; +UPDATE `creature_template` SET `ScriptName`='guard_ironforge' WHERE `entry`=5595; +UPDATE `creature_template` SET `ScriptName`='guard_dunmorogh' WHERE `entry` IN (727,13076); +UPDATE `creature_template` SET `ScriptName`='guard_undercity' WHERE `entry`=5624; +UPDATE `creature_template` SET `ScriptName`='guard_bluffwatcher' WHERE `entry`=3084; +UPDATE `creature_template` SET `ScriptName`='guard_durotar' WHERE `entry`=5953; +UPDATE `creature_template` SET `ScriptName`='guard_mulgore' WHERE `entry` IN (3212,3215,3217,3218,3219,3220,3221,3222,3223,3224); +UPDATE `creature_template` SET `ScriptName`='guard_dunmorogh' WHERE `entry` IN (727,13076); +UPDATE `creature_template` SET `ScriptName`='guard_tirisfal' WHERE `entry` IN (1735,1738,2210,1744,1745,5725,1743,2209,1746,1742); +UPDATE `creature_template` SET `ScriptName`='guard_silvermoon' WHERE `entry`=16222; +UPDATE `creature_template` SET `ScriptName`='guard_exodar' WHERE `entry`=16733; +UPDATE `creature_template` SET `ScriptName`='guard_shattrath' WHERE `entry`=19687; +UPDATE `creature_template` SET `ScriptName`='guard_shattrath_aldor' WHERE `entry`=18549; +UPDATE `creature_template` SET `ScriptName`='guard_shattrath_scryer' WHERE `entry`=18568; + +/* ITEM */ +UPDATE `item_template` SET `ScriptName`='item_area_52_special' WHERE `entry`=28132; +UPDATE `item_template` SET `ScriptName`='item_attuned_crystal_cores' WHERE `entry`=34368; +UPDATE `item_template` SET `ScriptName`='item_blackwhelp_net' WHERE `entry`=31129; +UPDATE `item_template` SET `ScriptName`='item_disciplinary_rod' WHERE `entry`=22473; +UPDATE `item_template` SET `ScriptName`='item_draenei_fishing_net' WHERE `entry`=23654; +UPDATE `item_template` SET `ScriptName`='item_flying_machine' WHERE `entry` IN (34060,34061); +UPDATE `item_template` SET `ScriptName`='item_gor_dreks_ointment' WHERE `entry`=30175; +UPDATE `item_template` SET `ScriptName`='item_muiseks_vessel' WHERE `entry` IN (9606,9618,9619,9620,9621); +UPDATE `item_template` SET `ScriptName`='item_nether_wraith_beacon' WHERE `entry`=31742; +UPDATE `item_template` SET `ScriptName`='item_protovoltaic_magneto_collector' WHERE `entry`=30656; +UPDATE `item_template` SET `ScriptName`='item_razorthorn_flayer_gland' WHERE `entry`=34255; +UPDATE `item_template` SET `ScriptName`='item_soul_cannon' WHERE `entry`=32825; +UPDATE `item_template` SET `ScriptName`='item_sparrowhawk_net' WHERE `entry`=32321; +UPDATE `item_template` SET `ScriptName`='item_tainted_core' WHERE `entry`=31088; +UPDATE `item_template` SET `ScriptName`='item_tame_beast_rods' WHERE `entry` IN (15908,15911,15913,15914,15915,15916,15917,15919,15920,15921,15922,15923,23697,23702,23703,23896,23897,23898); +UPDATE `item_template` SET `ScriptName`='item_voodoo_charm' WHERE `entry`=8149; +UPDATE `item_template` SET `ScriptName`='item_vorenthals_presence' WHERE `entry`=30259; +UPDATE `item_template` SET `ScriptName`='item_yehkinyas_bramble' WHERE `entry`=10699; +UPDATE `item_template` SET `ScriptName`='item_zezzaks_shard' WHERE `entry`=31463; + +/* NPC (usually creatures to be found in more than one specific zone) */ +UPDATE `creature_template` SET `ScriptName`='npc_chicken_cluck' WHERE `entry`=620; +UPDATE `creature_template` SET `ScriptName`='npc_dancing_flames' WHERE `entry`=25305; +UPDATE `creature_template` SET `ScriptName`='npc_guardian' WHERE `entry`=5764; +UPDATE `creature_template` SET `ScriptName`='npc_mount_vendor' WHERE `entry` IN (384,1261,1460,2357,3362,3685,4730,4731,4885,7952,7955,16264,17584); +UPDATE `creature_template` SET `ScriptName`='npc_doctor' WHERE `entry` IN (12939,12920); +UPDATE `creature_template` SET `ScriptName`='npc_injured_patient' WHERE `entry` IN (12936,12937,12938,12923,12924,12925); +UPDATE `creature_template` SET `ScriptName`='npc_prof_alchemy' WHERE `entry` IN (17909,19052,22427); +UPDATE `creature_template` SET `ScriptName`='npc_prof_blacksmith' WHERE `entry` IN (5164,11145,11146,11176,11177,11178,11191,11192,11193); +UPDATE `creature_template` SET `ScriptName`='npc_prof_leather' WHERE `entry` IN (7866,7867,7868,7869,7870,7871); +UPDATE `creature_template` SET `ScriptName`='npc_prof_tailor' WHERE `entry` IN (22208,22212,22213); +UPDATE `creature_template` SET `ScriptName`='npc_rogue_trainer' WHERE `entry` IN (918,4163,3328,4583,5165,5167,13283,16684); +UPDATE `creature_template` SET `ScriptName`='npc_sayge' WHERE `entry`=14822; + + +/* */ +/* ZONE */ +/* */ + +/* ALTERAC MOUNTAINS */ +UPDATE `creature_template` SET `ScriptName`='npc_ravenholdt' WHERE `entry`=13936; + +/* ALTERAC VALLEY */ + + +/* ARATHI HIGHLANDS */ + + +/* ASHENVALE */ + + +/* */ +/* AUCHINDOUN */ +/* */ + +/* MANA TOMBS */ +UPDATE `creature_template` SET `ScriptName`='boss_pandemonius' WHERE `entry`=18341; +UPDATE `creature_template` SET `ScriptName`='boss_nexusprince_shaffar' WHERE `entry`=18344; +UPDATE `creature_template` SET `ScriptName`='mob_ethereal_beacon' WHERE `entry`=18431; + +/* AUCHENAI CRYPTS */ +UPDATE `creature_template` SET `ScriptName`='boss_exarch_maladaar' WHERE `entry`=18373; +UPDATE `creature_template` SET `ScriptName`='mob_avatar_of_martyred' WHERE `entry`=18478; +UPDATE `creature_template` SET `ScriptName`='mob_stolen_soul' WHERE `entry`=18441; + +/* SETHEKK HALLS */ +UPDATE `instance_template` SET `script`='instance_sethekk_halls' WHERE `map`=556; +UPDATE `creature_template` SET `ScriptName`='mob_syth_fire' WHERE `entry`=19203; +UPDATE `creature_template` SET `ScriptName`='mob_syth_arcane' WHERE `entry`=19205; +UPDATE `creature_template` SET `ScriptName`='mob_syth_frost' WHERE `entry`=19204; +UPDATE `creature_template` SET `ScriptName`='mob_syth_shadow' WHERE `entry`=19206; +UPDATE `creature_template` SET `ScriptName`='boss_talon_king_ikiss' WHERE `entry`=18473; +UPDATE `creature_template` SET `ScriptName`='boss_darkweaver_syth' WHERE `entry`=18472; + +/* SHADOW LABYRINTH */ +UPDATE `instance_template` SET `script`='instance_shadow_labyrinth' WHERE `map`=555; +UPDATE `creature_template` SET `ScriptName`='boss_murmur' WHERE `entry`=18708; +UPDATE `creature_template` SET `ScriptName`='boss_grandmaster_vorpil' WHERE `entry`=18732; +UPDATE `creature_template` SET `ScriptName`='boss_blackheart_the_inciter' WHERE `entry`=18667; +UPDATE `creature_template` SET `ScriptName`='boss_ambassador_hellmaw' WHERE `entry`=18731; + +/* AZSHARA */ +UPDATE `creature_template` SET `ScriptName`='mobs_spitelashes' WHERE `entry` IN (6190,6193,6194,6195,6196,7885,7886,12204,12205); +UPDATE `creature_template` SET `ScriptName`='npc_loramus_thalipedes' WHERE `entry`=7783; + +/* AZUREMYST ISLE */ +UPDATE `creature_template` SET `ScriptName`='npc_engineer_spark_overgrind' WHERE `entry`=17243; +UPDATE `creature_template` SET `ScriptName`='npc_injured_draenei' WHERE `entry`=16971; +UPDATE `creature_template` SET `ScriptName`='npc_susurrus' WHERE `entry`=17435; + +/* BADLANDS */ + + +/* BARRENS */ +UPDATE `creature_template` SET `ScriptName`='npc_beaten_corpse' WHERE `entry`=10668; +UPDATE `creature_template` SET `ScriptName`='npc_sputtervalve' WHERE `entry`=3442; +UPDATE `creature_template` SET `ScriptName`='npc_taskmaster_fizzule' WHERE `entry`=7233; + +/* BLACK TEMPLE */ +UPDATE `instance_template` SET `script`='instance_black_temple' WHERE `map`=564; +UPDATE `creature_template` SET `ScriptName`='npc_akama_shade' WHERE `entry`=22990; -- Akama at Shade of Akama +UPDATE `creature_template` SET `ScriptName`='npc_akama_illidan' WHERE `entry`=23089; -- Akama at Illidan +UPDATE `creature_template` SET `ScriptName`='mob_illidari_council' WHERE `entry`=23426; -- Illidari Council controller mob +UPDATE `creature_template` SET `ScriptName`='mob_blood_elf_council_voice_trigger' WHERE `entry` = 23499; -- Voice Trigger Mob (Controls Aggro + Enrage yells) +UPDATE `creature_template` SET `ScriptName`='boss_veras_darkshadow' WHERE `entry`=22952; -- Rogue of Illidari Council +UPDATE `creature_template` SET `ScriptName`='boss_teron_gorefiend' WHERE `entry`=22871; -- Teron Gorefiend +UPDATE `creature_template` SET `ScriptName`='boss_supremus' WHERE `entry`=22898; -- Supremus +UPDATE `creature_template` SET `ScriptName`='boss_shade_of_akama' WHERE `entry`=22841; -- Shade of Akama +UPDATE `creature_template` SET `ScriptName`='boss_reliquary_of_souls' WHERE `entry`=22856; -- Reliquary Controller Mob +UPDATE `creature_template` SET `ScriptName`='boss_essence_of_suffering' WHERE `entry`=23418; -- Essence Of Suffering +UPDATE `creature_template` SET `ScriptName`='boss_essence_of_desire' WHERE `entry`=23419; -- Essence of Desire +UPDATE `creature_template` SET `ScriptName`='boss_essence_of_anger' WHERE `entry`=23420; -- Essence of Anger +UPDATE `creature_template` SET `ScriptName`='boss_najentus' WHERE `entry`=22887; -- High Warlord Naj'entus +UPDATE `creature_template` SET `ScriptName`='boss_gurtogg_bloodboil' WHERE `entry`=22948; -- Gurtogg Bloodboil +UPDATE `creature_template` SET `ScriptName`='boss_mother_shahraz' WHERE `entry`=22947; -- Mother Shahraz +UPDATE `creature_template` SET `ScriptName`='boss_lady_malande' WHERE `entry`=22951; -- Priest <3 at Illidari Council +UPDATE `creature_template` SET `ScriptName`='boss_illidan_stormrage' WHERE `entry`=22917; -- Illidan The Betrayer! +UPDATE `creature_template` SET `ScriptName`='boss_high_nethermancer_zerevor' WHERE `entry`=22950; -- Mage at Illidari Council +UPDATE `creature_template` SET `ScriptName`='boss_gathios_the_shatterer' WHERE `entry`=22949; -- Paladin at Illidari Council +UPDATE `creature_template` SET `ScriptName`='boss_maiev_shadowsong' WHERE `entry`=23197; -- Maiev Shadowsong +UPDATE `gameobject_template` SET `ScriptName`='gameobject_cage_trap' WHERE `entry`=185916; -- Cage Trap GO in Illidan Encounter +UPDATE `creature_template` SET `ScriptName`='mob_blaze' WHERE `entry`=23259; -- Blaze mob in Illidan Phase 2 +UPDATE `creature_template` SET `ScriptName`='mob_flame_of_azzinoth' WHERE `entry`=22997; -- Flame of Azzinoth (Illidan Phase 2) +UPDATE `creature_template` SET `ScriptName`='mob_blade_of_azzinoth' WHERE `entry`=22996; -- Blade of Azzinoth (Illidan Phase 2) +UPDATE `creature_template` SET `ScriptName`='mob_demon_fire' WHERE `entry`=23069; -- Demon Fire in Illidan Phase 2 +UPDATE `creature_template` SET `ScriptName`='mob_flame_crash' WHERE `entry`=23336; -- Flame Crash in Illidan Normal Form +UPDATE `creature_template` SET `ScriptName`='mob_cage_trap_trigger' WHERE `entry`=23304; -- Cage Trap mob in Illidan Phase 3/4 Normal +UPDATE `creature_template` SET `ScriptName`='mob_shadow_demon' WHERE `entry`=23375; -- Shadow Demon in Illidan Demon Form +UPDATE `creature_template` SET `ScriptName`='npc_volcano' WHERE `entry`=23085; -- Supremus Volcano +UPDATE `creature_template` SET `ScriptName`='molten_flame' WHERE `entry`=23095; -- Molten Flame in SUpremus +UPDATE `creature_template` SET `ScriptName`='mob_ashtongue_channeler' WHERE `entry`=23421; -- Ashtongue CHanneler in Shade of AKama +UPDATE `creature_template` SET `ScriptName`='mob_ashtongue_sorcerer' WHERE `entry`=23215; -- Ashtongue Sorcerer in Shade of Akama +UPDATE `creature_template` SET `ScriptName`='npc_enslaved_soul' WHERE `entry`=23469; -- Enslaved Soul in Reliquary Event +UPDATE `creature_template` SET `ScriptName`='mob_doom_blossom' WHERE `entry`=23123; -- Doom Blossoms in Teron Gorefiend's encounter +UPDATE `creature_template` SET `ScriptName`='npc_spirit_of_olum' WHERE `entry`=23411; +-- UPDATE `creature_template` SET `ScriptName`='mob_shadowy_construct' WHERE `entry`=23111; -- Shadowy Construct in Teron Gorefiend's encounter. Commented until Mind Control is implemented. + +/* BLACKFATHOM DEPTHS */ + + +/* BLACKROCK DEPTHS */ +UPDATE `creature_template` SET `ScriptName`='boss_emperor_dagran_thaurissan' WHERE `entry`=9019; +UPDATE `creature_template` SET `ScriptName`='boss_moira_bronzebeard' WHERE `entry`=8929; +UPDATE `creature_template` SET `ScriptName`='boss_ambassador_flamelash' WHERE `entry`=9156; +UPDATE `creature_template` SET `ScriptName`='boss_angerrel' WHERE `entry`=9035; +UPDATE `creature_template` SET `ScriptName`='boss_anubshiah' WHERE `entry`=9031; +UPDATE `creature_template` SET `ScriptName`='boss_doomrel' WHERE `entry`=9039; +UPDATE `creature_template` SET `ScriptName`='boss_doperel' WHERE `entry`=9040; +UPDATE `creature_template` SET `ScriptName`='boss_general_angerforge' WHERE `entry`=9033; +UPDATE `creature_template` SET `ScriptName`='boss_gloomrel' WHERE `entry`=9037; +UPDATE `creature_template` SET `ScriptName`='boss_gorosh_the_dervish' WHERE `entry`=9027; +UPDATE `creature_template` SET `ScriptName`='boss_grizzle' WHERE `entry`=9028; +UPDATE `creature_template` SET `ScriptName`='boss_haterel' WHERE `entry`=9034; +UPDATE `creature_template` SET `ScriptName`='boss_high_interrogator_gerstahn' WHERE `entry`=9018; +UPDATE `creature_template` SET `ScriptName`='boss_magmus' WHERE `entry`=9938; +UPDATE `creature_template` SET `ScriptName`='boss_seethrel' WHERE `entry`=9038; +UPDATE `creature_template` SET `ScriptName`='boss_vilerel' WHERE `entry`=9036; +UPDATE `creature_template` SET `ScriptName`='phalanx' WHERE `entry`=9502; +UPDATE `creature_template` SET `ScriptName`='npc_lokhtos_darkbargainer' WHERE `entry`=12944; +UPDATE `creature_template` SET `ScriptName`='npc_kharan_mighthammer' WHERE `entry`=9021; + +/* BLACKROCK SPIRE */ +/* BLACKROCK SPIRE Lower bosses */ +UPDATE `creature_template` SET `ScriptName`='boss_highlord_omokk' WHERE `entry`=9196; +UPDATE `creature_template` SET `ScriptName`='boss_shadow_hunter_voshgajin' WHERE `entry`=9236; +UPDATE `creature_template` SET `ScriptName`='boss_warmaster_voone' WHERE `entry`=9237; +UPDATE `creature_template` SET `ScriptName`='boss_mother_smolderweb' WHERE `entry`=10596; +UPDATE `creature_template` SET `ScriptName`='quartermaster_zigris' WHERE `entry`=9736; +UPDATE `creature_template` SET `ScriptName`='boss_halycon' WHERE `entry`=10220; +UPDATE `creature_template` SET `ScriptName`='boss_overlord_wyrmthalak' WHERE `entry`=9568; +/* BLACKROCK SPIRE Upper bosses */ +UPDATE `creature_template` SET `ScriptName`='boss_the_beast' WHERE `entry`=10430; +UPDATE `creature_template` SET `ScriptName`='boss_drakkisath' WHERE `entry`=10363; +UPDATE `creature_template` SET `ScriptName`='boss_gyth' WHERE `entry`=10339; +UPDATE `creature_template` SET `ScriptName`='boss_rend_blackhand' WHERE `entry`=10429; +UPDATE `creature_template` SET `ScriptName`='boss_pyroguard_emberseer' WHERE `entry`=9816; + +/* BLACKWING LAIR */ +UPDATE `instance_template` SET `script`='instance_blackwing_lair' WHERE `map`=469; +UPDATE `creature_template` SET `ScriptName`='boss_razorgore' WHERE `entry`=12435; +UPDATE `creature_template` SET `ScriptName`='boss_vaelastrasz' WHERE `entry`=13020; +UPDATE `creature_template` SET `ScriptName`='boss_broodlord' WHERE `entry`=12017; +UPDATE `creature_template` SET `ScriptName`='boss_firemaw' WHERE `entry`=11983; +UPDATE `creature_template` SET `ScriptName`='boss_ebonroc' WHERE `entry`=14601; +UPDATE `creature_template` SET `ScriptName`='boss_flamegor' WHERE `entry`=11981; +UPDATE `creature_template` SET `ScriptName`='boss_chromaggus' WHERE `entry`=14020; +UPDATE `creature_template` SET `ScriptName`='boss_victor_nefarius' WHERE `entry`=10162; +UPDATE `creature_template` SET `ScriptName`='boss_nefarian' WHERE `entry`=11583; + +/* BLADE'S EDGE MOUNTAINS */ +UPDATE `creature_template` SET `ScriptName`='mobs_bladespire_ogre' WHERE `entry` IN (19998,20334,21296,21975); +UPDATE `creature_template` SET `ScriptName`='mobs_nether_drake' WHERE `entry` IN (20021,21817,21820,21821,21823); +UPDATE `creature_template` SET `ScriptName`='npc_daranelle' WHERE `entry`=21469; +UPDATE `creature_template` SET `ScriptName`='npc_overseer_nuaar' WHERE `entry`=21981; +UPDATE `creature_template` SET `ScriptName`='npc_saikkal_the_elder' WHERE `entry`=22932; +UPDATE `creature_template` SET `ScriptName`='npc_skyguard_handler_deesak' WHERE `entry`=23415; + +/* BLASTED LANDS */ +UPDATE `creature_template` SET `ScriptName`='npc_deathly_usher' WHERE `entry`=8816; +UPDATE `creature_template` SET `ScriptName`='npc_fallen_hero_of_horde' WHERE `entry`=7572; + +/* BLOODMYST ISLE */ +UPDATE `creature_template` SET `ScriptName`='mob_webbed_creature' WHERE `entry`=17680; +UPDATE `creature_template` SET `ScriptName`='npc_captured_sunhawk_agent' WHERE `entry`=17824; + +/* BURNING STEPPES */ +UPDATE `creature_template` SET `ScriptName`='npc_ragged_john' WHERE `entry`=9563; + +/* */ +/* CAVERNS OF TIME */ +/* */ + +/* MT. HYJAL */ +UPDATE `instance_template` SET `script`='instance_hyjal' WHERE `map`=534; +UPDATE `creature_template` SET `ScriptName`='npc_tyrande_whisperwind' WHERE `entry`=17948; +UPDATE `creature_template` SET `ScriptName`='npc_thrall' WHERE `entry` =17852; +UPDATE `creature_template` SET `ScriptName`='npc_jaina_proudmoore' WHERE `entry`=17772; +UPDATE `creature_template` SET `ScriptName`='boss_archimonde' WHERE `entry`=17968; +UPDATE `creature_template` SET `ScriptName`='mob_doomfire' WHERE `entry`=18095; +UPDATE `creature_template` SET `ScriptName`='mob_doomfire_targetting' WHERE `entry`=18104; +UPDATE `creature_template` SET `ScriptName`='mob_ancient_wisp' WHERE `entry`=17946; + +/* OLD HILLSBRAD */ +UPDATE `instance_template` SET `script`='instance_old_hillsbrad' WHERE `map`=560; +UPDATE `creature_template` SET `ScriptName`='boss_lieutenant_drake' WHERE `entry`=17848; +UPDATE `creature_template` SET `ScriptName`='boss_epoch_hunter' WHERE `entry`=18096; +UPDATE `creature_template` SET `ScriptName`='boss_captain_skarloc' WHERE `entry`=17862; +UPDATE `creature_template` SET `ScriptName`='npc_brazen' WHERE `entry`=18725; +UPDATE `creature_template` SET `ScriptName`='npc_erozion' WHERE `entry`=18723; +UPDATE `creature_template` SET `ScriptName`='npc_taretha' WHERE `entry`=18887; +UPDATE `creature_template` SET `ScriptName`='npc_thrall_old_hillsbrad' WHERE `entry`=17876; + +/* THE DARK PORTAL */ +UPDATE `creature_template` SET `ScriptName`='boss_chrono_lord_deja' WHERE `entry`=17879; +UPDATE `creature_template` SET `ScriptName`='boss_aeonus' WHERE `entry`=17881; +UPDATE `creature_template` SET `ScriptName`='boss_temporus' WHERE `entry`=17880; + + +/* */ +/* COILFANG RESERVOIR */ +/* */ + +/* THE SLAVE PENS */ + +/* THE UNDERBOG */ +UPDATE `creature_template` SET `ScriptName`='mob_underbog_mushroom' WHERE `entry`=17990; +UPDATE `creature_template` SET `ScriptName`='boss_hungarfen' WHERE `entry`=17770; + +/* THE STEAMVAULT */ +UPDATE `instance_template` SET `script`='instance_steam_vault' WHERE `map`=545; +UPDATE `creature_template` SET `ScriptName`='boss_hydromancer_thespia' WHERE `entry`=17797; +UPDATE `creature_template` SET `ScriptName`='boss_mekgineer_steamrigger' WHERE `entry`=17796; +UPDATE `creature_template` SET `ScriptName`='boss_warlord_kalithresh' WHERE `entry`=17798; +UPDATE `creature_template` SET `ScriptName`='mob_coilfang_waterelemental' WHERE `entry`=17917; +UPDATE `creature_template` SET `ScriptName`='mob_naga_distiller' WHERE `entry`=17954; +UPDATE `creature_template` SET `ScriptName`='mob_steamrigger_mechanic' WHERE `entry`=17951; + +/* SERPENTSHRINE CAVERN */ +UPDATE `instance_template` SET `script`='instance_serpent_shrine' WHERE `map`=548; +UPDATE `creature_template` SET `ScriptName`='boss_hydross_the_unstable' WHERE `entry`=21216; +/* Leotheras the Blind event */ +UPDATE `creature_template` SET `ScriptName`='boss_leotheras_the_blind' WHERE `entry`=21215; +UPDATE `creature_template` SET `ScriptName`='boss_leotheras_the_blind_demonform' WHERE `entry`=21845; +/* Fathom-lord Karathress event */ +UPDATE `creature_template` SET `ScriptName`='boss_fathomlord_karathress' WHERE `entry`=21214; +UPDATE `creature_template` SET `ScriptName`='boss_fathomguard_sharkkis' WHERE `entry`=21966; +UPDATE `creature_template` SET `ScriptName`='boss_fathomguard_tidalvess' WHERE `entry`=21965; +UPDATE `creature_template` SET `ScriptName`='boss_fathomguard_caribdis' WHERE `entry`=21964; +/* Morogrim Tidewalker event */ +UPDATE `creature_template` SET `ScriptName`='boss_morogrim_tidewalker' WHERE `entry`=21213; +UPDATE `creature_template` SET `ScriptName`='mob_water_globule' WHERE `entry`=21913; +/* Lady Vashj event */ +UPDATE `creature_template` SET `ScriptName`='boss_lady_vashj' WHERE `entry`=21212; +UPDATE `creature_template` SET `ScriptName`='mob_enchanted_elemental' WHERE `entry`=21958; +UPDATE `creature_template` SET `ScriptName`='mob_tainted_elemental' WHERE `entry`=22009; +UPDATE `creature_template` SET `ScriptName`='mob_coilfang_elite' WHERE `entry`=22055; +UPDATE `creature_template` SET `ScriptName`='mob_coilfang_strider' WHERE `entry`=22056; +UPDATE `creature_template` SET `ScriptName`='mob_fathom_sporebat' WHERE `entry`=22140; +UPDATE `creature_template` SET `ScriptName`='mob_shield_generator_channel' WHERE `entry`=19870; + + +/* DARKSHORE */ + + +/* DEADMINES */ + + +/* DEADWIND PASS */ + + +/* DESOLACE */ + + +/* DIRE MAUL */ + + +/* DUN MOROGH */ +UPDATE `creature_template` SET `ScriptName`='npc_narm_faulk' WHERE `entry`=6177; + + +/* DUROTAR */ + + +/* DUSKWOOD */ + + +/* DUSTWALLOW MARSH */ +UPDATE `creature_template` SET `ScriptName`='mobs_risen_husk_spirit' WHERE `entry` IN (23554,23555); +UPDATE `creature_template` SET `ScriptName`='npc_deserter_agitator' WHERE `entry`=23602; +UPDATE `creature_template` SET `ScriptName`='npc_lady_jaina_proudmoore' WHERE `entry`=4968; +UPDATE `creature_template` SET `ScriptName`='npc_nat_pagle' WHERE `entry`=12919; +UPDATE `creature_template` SET `ScriptName`='npc_restless_apparition' WHERE `entry`=23861; + +/* EASTERN PLAGUELANDS */ +UPDATE `creature_template` SET `ScriptName`='mobs_ghoul_flayer' WHERE `entry` IN (8530,8531,8532); +UPDATE `creature_template` SET `ScriptName`='npc_augustus_the_touched' WHERE `entry`=12384; +UPDATE `creature_template` SET `ScriptName`='npc_darrowshire_spirit' WHERE `entry`=11064; +UPDATE `creature_template` SET `ScriptName`='npc_tirion_fordring' WHERE `entry`=1855; + +/* ELWYNN FOREST */ +UPDATE `creature_template` SET `ScriptName`='npc_henze_faulk' WHERE `entry`=6172; + +/* EVERSONG WOODS */ +UPDATE `creature_template` SET `ScriptName`='mobs_mana_tapped' WHERE `entry` IN (15273,15274,15294,15298,15367); +UPDATE `creature_template` SET `ScriptName`='npc_prospector_anvilward' WHERE `entry`=15420; + +/* FELWOOD */ +UPDATE `creature_template` SET `ScriptName`='npcs_riverbreeze_and_silversky' WHERE `entry` IN (9528,9529); + +/* FERALAS */ +UPDATE `creature_template` SET `ScriptName`='npc_gregan_brewspewer' WHERE `entry`=7775; +UPDATE `creature_template` SET `ScriptName`='npc_screecher_spirit' WHERE `entry`=8612; + +/* GHOSTLANDS */ +UPDATE `creature_template` SET `ScriptName`='npc_blood_knight_dawnstar' WHERE `entry`=17832; +UPDATE `creature_template` SET `ScriptName`='npc_budd_nedreck' WHERE `entry`=23559; +UPDATE `creature_template` SET `ScriptName`='npc_rathis_tomber' WHERE `entry`=16224; + +/* GNOMEREGAN */ + + +/* GRUUL'S LAIR */ +UPDATE `instance_template` SET `script`='instance_gruuls_lair' WHERE `map` =565; +UPDATE `creature_template` SET `ScriptName`='boss_gruul' WHERE `entry`=19044; +/* Maulgar and Event */ +UPDATE `creature_template` SET `ScriptName`='boss_high_king_maulgar' WHERE `entry`=18831; +UPDATE `creature_template` SET `ScriptName`='boss_kiggler_the_crazed' WHERE `entry`=18835; +UPDATE `creature_template` SET `ScriptName`='boss_blindeye_the_seer' WHERE `entry`=18836; +UPDATE `creature_template` SET `ScriptName`='boss_olm_the_summoner' WHERE `entry`=18834; +UPDATE `creature_template` SET `ScriptName`='boss_krosh_firehand' WHERE `entry`=18832; + +/* */ +/* HELLFIRE CITADEL */ +/* */ + +/* BLOOD FURNACE */ +/* The Maker,Broggok,Kelidan,Broggok's cloud */ +UPDATE `creature_template` SET `ScriptName`='boss_the_maker' WHERE `entry`=17381; +UPDATE `creature_template` SET `ScriptName`='boss_broggok' WHERE `entry`=17380; +UPDATE `creature_template` SET `ScriptName`='boss_kelidan_the_breaker' WHERE `entry`=17377; +UPDATE `creature_template` SET `ScriptName`='mob_broggok_poisoncloud' WHERE `entry`=17662; +UPDATE `creature_template` SET `ScriptName`='mob_shadowmoon_channeler' WHERE `entry`=17653; + +/* HELLFIRE RAMPARTS */ +/* Vazruden,Omor the Unscarred,Watchkeeper Gargolmar */ +UPDATE `creature_template` SET `ScriptName`='boss_omor_the_unscarred' WHERE `entry`=17308; +UPDATE `creature_template` SET `ScriptName`='boss_watchkeeper_gargolmar' WHERE `entry`=17306; + +/* SHATTERED HALLS */ +/* Nethekurse and his spawned shadowfissure */ +UPDATE `creature_template` SET `ScriptName`='boss_grand_warlock_nethekurse' WHERE `entry`=16807; +UPDATE `creature_template` SET `ScriptName`='boss_warbringer_omrogg' WHERE `entry`=16809; +UPDATE `creature_template` SET `ScriptName`='mob_fel_orc_convert' WHERE `entry`=17083; +UPDATE `creature_template` SET `ScriptName`='mob_lesser_shadow_fissure' WHERE `entry`=17471; +UPDATE `creature_template` SET `ScriptName`='mob_omrogg_heads' WHERE `entry` IN (19523,19524); +UPDATE `instance_template` SET `script`='instance_shattered_halls' WHERE `map`=540; + +/* MAGTHERIDON'S LAIR */ +UPDATE `instance_template` SET `script`='instance_magtheridons_lair' WHERE `map`=544; +UPDATE `gameobject_template` SET `ScriptName`='go_manticron_cube' WHERE `entry`=181713; +UPDATE `creature_template` SET `ScriptName`='boss_magtheridon' WHERE `entry` =17257; +UPDATE `creature_template` SET `ScriptName`='mob_hellfire_channeler' WHERE `entry`=17256; + +/* HELLFIRE PENINSULA */ +UPDATE `creature_template` SET `ScriptName`='boss_doomlord_kazzak' WHERE `entry`=18728; +UPDATE `creature_template` SET `ScriptName`='npc_wing_commander_brack' WHERE `entry`=19401; +UPDATE `creature_template` SET `ScriptName`='npc_wing_commander_dabiree' WHERE `entry`=19409; +UPDATE `creature_template` SET `ScriptName`='npc_gryphoneer_windbellow' WHERE `entry`=20235; + +/* HILLSBRAD FOOTHILLS */ + + +/* HINTERLANDS */ + + +/* IRONFORGE */ +UPDATE `creature_template` SET `ScriptName`='npc_royal_historian_archesonus' WHERE `entry`=8879; + +/* ISLE OF QUEL'DANAS */ +UPDATE `creature_template` SET `ScriptName`='npc_ayren_cloudbreaker' WHERE `entry`=25059; +UPDATE `creature_template` SET `ScriptName`='npc_converted_sentry' WHERE `entry`=24981; +UPDATE `creature_template` SET `ScriptName`='npc_unrestrained_dragonhawk' WHERE `entry`=25236; + +/* KARAZHAN */ +UPDATE `instance_template` SET `script`='instance_karazhan' WHERE `map`=532; +UPDATE `creature_template` SET `ScriptName`='boss_midnight' WHERE `entry`=16151; +UPDATE `creature_template` SET `ScriptName`='boss_attumen' WHERE `entry`=15550; +UPDATE `creature_template` SET `ScriptName`='boss_moroes' WHERE `entry`=15687; +UPDATE `creature_template` SET `ScriptName`='boss_maiden_of_virtue' WHERE `entry`=16457; +UPDATE `creature_template` SET `ScriptName`='boss_curator' WHERE `entry`=15691; +UPDATE `creature_template` SET `ScriptName`='boss_julianne' WHERE `entry`=17534; +UPDATE `creature_template` SET `ScriptName`='boss_romulo' WHERE `entry`=17533; +UPDATE `creature_template` SET `ScriptName`='boss_dorothee' WHERE `entry`=17535; +UPDATE `creature_template` SET `ScriptName`='boss_strawman' WHERE `entry`=17543; +UPDATE `creature_template` SET `ScriptName`='boss_tinhead' WHERE `entry`=17547; +UPDATE `creature_template` SET `ScriptName`='boss_tito' WHERE `entry`=17548; +UPDATE `creature_template` SET `ScriptName`='boss_roar' WHERE `entry`=17546; +UPDATE `creature_template` SET `ScriptName`='boss_crone' WHERE `entry`=18168; +UPDATE `creature_template` SET `ScriptName`='boss_terestian_illhoof' WHERE `entry`=15688; +UPDATE `creature_template` SET `ScriptName`='boss_shade_of_aran' WHERE `entry`=16524; +UPDATE `creature_template` SET `ScriptName`='boss_netherspite' WHERE `entry`=15689; +UPDATE `creature_template` SET `ScriptName`='boss_malchezaar' WHERE `entry`=15690; +UPDATE `creature_template` SET `ScriptName`='boss_nightbane' WHERE `entry`=17225; +UPDATE `creature_template` SET `ScriptName`='boss_baroness_dorothea_millstipe' WHERE `entry`=19875; +UPDATE `creature_template` SET `ScriptName`='boss_baron_rafe_dreuger' WHERE `entry`=19874; +UPDATE `creature_template` SET `ScriptName`='boss_lady_catriona_von_indi' WHERE `entry`=19872; +UPDATE `creature_template` SET `ScriptName`='boss_lady_keira_berrybuck' WHERE `entry`=17007; +UPDATE `creature_template` SET `ScriptName`='boss_lord_robin_daris' WHERE `entry`=19876; +UPDATE `creature_template` SET `ScriptName`='boss_lord_crispin_ference' WHERE `entry`=19873; +UPDATE `creature_template` SET `ScriptName`='boss_bigbadwolf' WHERE `entry`=17521; +UPDATE `creature_template` SET `ScriptName`='mob_shadow_of_aran' WHERE `entry`=18254; +UPDATE `creature_template` SET `ScriptName`='mob_aran_elemental' WHERE `entry`=17167; +UPDATE `creature_template` SET `ScriptName`='mob_aran_blizzard' WHERE `entry`=17161; +UPDATE `creature_template` SET `ScriptName`='mob_homunculus' WHERE `entry`=16539; +UPDATE `creature_template` SET `ScriptName`='mob_kilrek' WHERE `entry`=17229; +UPDATE `creature_template` SET `ScriptName`='mob_demon_chain' WHERE `entry`=17248; +UPDATE `creature_template` SET `ScriptName`='mob_cyclone' WHERE `entry`=18412; +UPDATE `creature_template` SET `ScriptName`='netherspite_infernal' WHERE `entry`=17646; +UPDATE `creature_template` SET `ScriptName`='npc_berthold' WHERE `entry`=16153; +UPDATE `creature_template` SET `ScriptName`='npc_barnes' WHERE `entry`=16812; +UPDATE `creature_template` SET `ScriptName`='npc_grandmother' WHERE `entry`=17603; + + +/* LOCH MODAN */ +UPDATE `creature_template` SET `ScriptName`='npc_mountaineer_pebblebitty' WHERE `entry`=3836; + +/* Magister's Terrace */ +UPDATE `instance_template` SET `script`='instance_magisters_terrace' WHERE `map`=585; +UPDATE `creature_template` SET `ScriptName`='boss_selin_fireheart' WHERE `entry`=24723; +UPDATE `creature_template` SET `ScriptName`='mob_fel_crystal' WHERE `entry`=24722; +UPDATE `creature_template` SET `ScriptName`='boss_vexallus' WHERE `entry`=24744; +UPDATE `creature_template` SET `ScriptName`='mob_pure_energy' WHERE `entry`=24745; +UPDATE `creature_template` SET `ScriptName`='boss_priestess_delrissa' WHERE `entry`=24560; +UPDATE `creature_template` SET `ScriptName`='boss_kagani_nightstrike' WHERE `entry`=24557; +UPDATE `creature_template` SET `ScriptName`='boss_ellris_duskhallow' WHERE `entry`=24558; +UPDATE `creature_template` SET `ScriptName`='boss_eramas_brightblaze' WHERE `entry`=24554; +UPDATE `creature_template` SET `ScriptName`='boss_yazzai' WHERE `entry`=24561; +UPDATE `creature_template` SET `ScriptName`='boss_warlord_salaris' WHERE `entry`=24559; +UPDATE `creature_template` SET `ScriptName`='boss_garaxxas' WHERE `entry`=24555; +UPDATE `creature_template` SET `ScriptName`='mob_sliver' WHERE `entry`=24552; +UPDATE `creature_template` SET `ScriptName`='boss_apoko' WHERE `entry`=24553; +UPDATE `creature_template` SET `ScriptName`='boss_zelfan' WHERE `entry`=24556; +UPDATE `creature_template` SET `ScriptName`='boss_felblood_kaelthas' WHERE `entry`=24664; +UPDATE `creature_template` SET `ScriptName`='mob_arcane_sphere' WHERE `entry`=24708; +UPDATE `creature_template` SET `ScriptName`='mob_felkael_phoenix' WHERE `entry`=24674; +UPDATE `creature_template` SET `ScriptName`='mob_felkael_phoenix_egg' WHERE `entry`=24675; +UPDATE `creature_template` SET `ScriptName`='mob_felkael_flamestrike' WHERE `entry`=24666; + +/* MARAUDON */ +UPDATE `creature_template` SET `ScriptName`='boss_princess_theradras' WHERE `entry`=12201; +UPDATE `creature_template` SET `ScriptName`='boss_noxxion' WHERE `entry`=13282; +UPDATE `creature_template` SET `ScriptName`='boss_landslide' WHERE `entry`=12203; +UPDATE `creature_template` SET `ScriptName`='celebras_the_cursed' WHERE `entry`=12225; + +/* MOLTEN CORE */ +UPDATE `instance_template` SET `script`='instance_molten_core' WHERE `map`=409; +UPDATE `creature_template` SET `ScriptName`='boss_lucifron' WHERE `entry`=12118; +UPDATE `creature_template` SET `ScriptName`='boss_magmadar' WHERE `entry`=11982; +UPDATE `creature_template` SET `ScriptName`='boss_gehennas' WHERE `entry`=12259; +UPDATE `creature_template` SET `ScriptName`='boss_garr' WHERE `entry`=12057; +UPDATE `creature_template` SET `ScriptName`='boss_baron_geddon' WHERE `entry`=12056; +UPDATE `creature_template` SET `ScriptName`='boss_shazzrah' WHERE `entry`=12264; +UPDATE `creature_template` SET `ScriptName`='boss_golemagg' WHERE `entry`=11988; +UPDATE `creature_template` SET `ScriptName`='boss_sulfuron' WHERE `entry`=12098; +UPDATE `creature_template` SET `ScriptName`='boss_majordomo' WHERE `entry`=12018; +UPDATE `creature_template` SET `ScriptName`='boss_ragnaros' WHERE `entry`=11502; +UPDATE `creature_template` SET `ScriptName`='mob_ancient_core_hound' WHERE `entry`=11673; +UPDATE `creature_template` SET `ScriptName`='mob_firesworn' WHERE `entry`=12099; +UPDATE `creature_template` SET `ScriptName`='mob_core_rager' WHERE `entry`=11672; +UPDATE `creature_template` SET `ScriptName`='mob_flamewaker_priest' WHERE `entry`=11662; + +/* MOONGLADE */ +UPDATE `creature_template` SET `ScriptName`='npc_bunthen_plainswind' WHERE `entry`=11798; +UPDATE `creature_template` SET `ScriptName`='npc_great_bear_spirit' WHERE `entry`=11956; +UPDATE `creature_template` SET `ScriptName`='npc_silva_filnaveth' WHERE `entry`=11800; + +/* MULGORE */ +UPDATE `creature_template` SET `ScriptName`='npc_skorn_whitecloud' WHERE `entry`=3052; + +/* NAGRAND */ +UPDATE `creature_template` SET `ScriptName`='mob_lump' WHERE `entry`=18351; +UPDATE `creature_template` SET `ScriptName`='mob_shattered_rumbler' WHERE `entry`=17157; +UPDATE `creature_template` SET `ScriptName`='mob_sunspring_villager' WHERE `entry`=18240; +UPDATE `creature_template` SET `ScriptName`='npc_altruis_the_sufferer' WHERE `entry`=18417; +UPDATE `creature_template` SET `ScriptName`='npc_greatmother_geyah' WHERE `entry`=18141; +UPDATE `creature_template` SET `ScriptName`='npc_lantresor_of_the_blade' WHERE `entry`=18261; +UPDATE `creature_template` SET `ScriptName`='npc_creditmarker_visit_with_ancestors' WHERE `entry` IN (18840,18841,18842,18843); + +/* NAXXRAMAS */ +UPDATE `instance_template` SET `script`='instance_naxxramas' WHERE `map`=533; +UPDATE `creature_template` SET `ScriptName`='boss_anubrekhan' WHERE `entry`=15956; +UPDATE `creature_template` SET `ScriptName`='boss_faerlina' WHERE `entry`=15953; +UPDATE `creature_template` SET `ScriptName`='boss_maexxna' WHERE `entry`=15952; +UPDATE `creature_template` SET `ScriptName`='boss_noth' WHERE `entry`=15954; +UPDATE `creature_template` SET `ScriptName`='boss_heigan' WHERE `entry`=15936; +UPDATE `creature_template` SET `ScriptName`='boss_loatheb' WHERE `entry`=16011; +UPDATE `creature_template` SET `ScriptName`='boss_razuvious' WHERE `entry`=16061; +UPDATE `creature_template` SET `ScriptName`='boss_gothik' WHERE `entry`=16060; +UPDATE `creature_template` SET `ScriptName`='boss_highlord_mograine' WHERE `entry`=16062; +UPDATE `creature_template` SET `ScriptName`='boss_thane_korthazz' WHERE `entry`=16064; +UPDATE `creature_template` SET `ScriptName`='boss_sir_zeliek' WHERE `entry`=16063; +UPDATE `creature_template` SET `ScriptName`='boss_lady_blaumeux' WHERE `entry`=16065; +UPDATE `creature_template` SET `ScriptName`='boss_patchwerk' WHERE `entry`=16028; +UPDATE `creature_template` SET `ScriptName`='boss_grobbulus' WHERE `entry`=15931; +UPDATE `creature_template` SET `ScriptName`='boss_gluth' WHERE `entry`=15932; +UPDATE `creature_template` SET `ScriptName`='boss_thaddius' WHERE `entry`=15928; +UPDATE `creature_template` SET `ScriptName`='boss_stalagg' WHERE `entry`=15929; +UPDATE `creature_template` SET `ScriptName`='boss_fugen' WHERE `entry`=15930; +UPDATE `creature_template` SET `ScriptName`='boss_sapphiron' WHERE `entry`=15989; +UPDATE `creature_template` SET `ScriptName`='boss_kelthuzad' WHERE `entry`=15990; + +/* NETHERSTORM */ +UPDATE `gameobject_template` SET `ScriptName`='go_manaforge_control_console' WHERE `entry` IN (183770,183956,184311,184312); +UPDATE `creature_template` SET `ScriptName`='npc_manaforge_control_console' WHERE `entry` IN (20209,20417,20418,20440); +UPDATE `creature_template` SET `ScriptName`='npc_protectorate_nether_drake' WHERE `entry`=20903; +UPDATE `creature_template` SET `ScriptName`='npc_veronia' WHERE `entry`=20162; + +/* ONYXIA'S LAIR */ +UPDATE `creature_template` SET `ScriptName`='boss_onyxia' WHERE `entry`=10184; + +/* ORGRIMMAR */ +UPDATE `creature_template` SET `ScriptName`='npc_neeru_fireblade' WHERE `entry`=3216; +UPDATE `creature_template` SET `ScriptName`='npc_shenthul' WHERE `entry`=3401; +UPDATE `creature_template` SET `ScriptName`='npc_thrall_warchief' WHERE `entry`=4949; + +/* RAGEFIRE CHASM */ + + +/* RAZORFEN DOWNS */ +UPDATE `creature_template` SET `ScriptName`='boss_amnennar_the_coldbringer' WHERE `entry`=7358; + +/* REDRIDGE MOUNTAINS */ + + +/* RUINS OF AHN'QIRAJ */ +UPDATE `instance_template` SET `script`='instance_ruins_of_ahnqiraj' WHERE `map`=509; + +/* SCARLET MONASTERY */ +UPDATE `creature_template` SET `ScriptName`='boss_arcanist_doan' WHERE `entry`=6487; +UPDATE `creature_template` SET `ScriptName`='boss_azshir_the_sleepless' WHERE `entry`=6490; +UPDATE `creature_template` SET `ScriptName`='boss_bloodmage_thalnos' WHERE `entry`=4543; +UPDATE `creature_template` SET `ScriptName`='boss_herod' WHERE `entry`=3975; +UPDATE `creature_template` SET `ScriptName`='boss_high_inquisitor_fairbanks' WHERE `entry`=4542; +UPDATE `creature_template` SET `ScriptName`='boss_high_inquisitor_whitemane' WHERE `entry`=3977; +UPDATE `creature_template` SET `ScriptName`='boss_houndmaster_loksey' WHERE `entry`=3974; +UPDATE `creature_template` SET `ScriptName`='boss_interrogator_vishas' WHERE `entry`=3983; +UPDATE `creature_template` SET `ScriptName`='boss_scarlet_commander_mograine' WHERE `entry`=3976; +UPDATE `creature_template` SET `ScriptName`='boss_scorn' WHERE `entry`=14693; + +/* SCHOLOMANCE */ +UPDATE `instance_template` SET `script`='instance_scholomance' WHERE `map`=289; +UPDATE `creature_template` SET `ScriptName`='boss_darkmaster_gandling' WHERE `entry`=1853; +UPDATE `creature_template` SET `ScriptName`='boss_death_knight_darkreaver' WHERE `entry`=14516; +UPDATE `creature_template` SET `ScriptName`='boss_lord_alexei_barov' WHERE `entry`=10504; +UPDATE `creature_template` SET `ScriptName`='boss_instructor_malicia' WHERE `entry`=10505; +UPDATE `creature_template` SET `ScriptName`='boss_boss_ras_frostwhisper' WHERE `entry`=10508; +UPDATE `creature_template` SET `ScriptName`='boss_the_ravenian' WHERE `entry`=10507; +UPDATE `creature_template` SET `ScriptName`='boss_vectus' WHERE `entry`=10432; +UPDATE `creature_template` SET `ScriptName`='boss_illucia_barov' WHERE `entry`=10502; +UPDATE `creature_template` SET `ScriptName`='boss_doctor_theolen_krastinov' WHERE `entry`=11261; +UPDATE `creature_template` SET `ScriptName`='boss_jandice_barov' WHERE `entry`=10503; +UPDATE `creature_template` SET `ScriptName`='boss_lorekeeper_polkelt' WHERE `entry`=10901; +UPDATE `creature_template` SET `ScriptName`='boss_kormok' WHERE `entry`=16118; +UPDATE `creature_template` SET `ScriptName`='mob_illusionofjandicebarov' WHERE `entry`=11439; + +/* SEARING GORGE */ +UPDATE `creature_template` SET `ScriptName`='npc_kalaran_windblade' WHERE `entry`=8479; +UPDATE `creature_template` SET `ScriptName`='npc_lothos_riftwaker' WHERE `entry`=14387; +UPDATE `creature_template` SET `ScriptName`='npc_zamael_lunthistle' WHERE `entry`=8436; + +/* SHADOWFANG KEEP */ +UPDATE `instance_template` SET `script`='instance_shadowfang_keep' WHERE `map`=33; +UPDATE `creature_template` SET `ScriptName`='npc_shadowfang_prisoner' WHERE `entry` IN (3849,3850); + +/* SHADOWMOON VALLEY */ +UPDATE `creature_template` SET `ScriptName`='boss_doomwalker' WHERE `entry`=17711; +UPDATE `creature_template` SET `ScriptName`='npc_drake_dealer_hurlunk' WHERE `entry`=23489; +UPDATE `creature_template` SET `ScriptName`='npc_invis_legion_teleporter' WHERE `entry`=21807; +UPDATE `creature_template` SET `ScriptName`='npcs_flanis_swiftwing_and_kagrosh' WHERE `entry` IN (21725,21727); +UPDATE `creature_template` SET `ScriptName`='npc_murkblood_overseer' WHERE `entry`=23309; +UPDATE `creature_template` SET `ScriptName`='npc_neltharaku' WHERE `entry`=21657; +UPDATE `creature_template` SET `ScriptName`='npc_oronok_tornheart' WHERE `entry`=21183; +UPDATE `creature_template` SET `ScriptName`='mob_mature_netherwing_drake' WHERE `entry`=21648; +UPDATE `creature_template` SET `ScriptName`='mob_enslaved_netherwing_drake' WHERE `entry`=21722; + +/* SHATTRATH */ +UPDATE `creature_template` SET `ScriptName`='npc_raliq_the_drunk' WHERE `entry`=18585; +UPDATE `creature_template` SET `ScriptName`='npc_salsalabim' WHERE `entry`=18584; +UPDATE `creature_template` SET `ScriptName`='npc_shattrathflaskvendors' WHERE `entry` IN (23483,23484); +UPDATE `creature_template` SET `ScriptName`='npc_zephyr' WHERE `entry`=25967; + +/* SILITHUS */ +UPDATE `creature_template` SET `ScriptName`='npcs_rutgar_and_frankal' WHERE `entry` IN (15170,15171); + +/* SILVERMOON */ +UPDATE `creature_template` SET `ScriptName`='npc_blood_knight_stillblade' WHERE `entry`=17768; + +/* SILVERPINE FOREST */ +UPDATE `creature_template` SET `ScriptName`='npc_astor_hadren' WHERE `entry`=6497; + +/* STOCKADES */ + +/* STONETALON MOUNTAINS */ +UPDATE `creature_template` SET `ScriptName`='npc_braug_dimspirit' WHERE `entry`=4489; + +/* STORMWIND CITY */ +UPDATE `creature_template` SET `ScriptName`='npc_archmage_malin' WHERE `entry`=2708; +UPDATE `creature_template` SET `ScriptName`='npc_bartleby' WHERE `entry`=6090; +UPDATE `creature_template` SET `ScriptName`='npc_dashel_stonefist' WHERE `entry`=4961; +UPDATE `creature_template` SET `ScriptName`='npc_general_marcus_jonathan' WHERE `entry`=466; +UPDATE `creature_template` SET `ScriptName`='npc_lady_katrana_prestor' WHERE `entry`=1749; + +/* STRANGLETHORN VALE */ +UPDATE `creature_template` SET `ScriptName`='mob_yenniku' WHERE `entry`=2530; + +/* STRATHOLME */ +UPDATE `instance_template` SET `script`='instance_stratholme' WHERE `map`=329; +UPDATE `creature_template` SET `ScriptName`='boss_dathrohan_balnazzar' WHERE `entry`=10812; +UPDATE `creature_template` SET `ScriptName`='boss_magistrate_barthilas' WHERE `entry`=10435; +UPDATE `creature_template` SET `ScriptName`='boss_maleki_the_pallid' WHERE `entry`=10438; +UPDATE `creature_template` SET `ScriptName`='boss_nerubenkan' WHERE `entry`=10437; +UPDATE `creature_template` SET `ScriptName`='boss_cannon_master_willey' WHERE `entry`=10997; +UPDATE `creature_template` SET `ScriptName`='boss_baroness_anastari' WHERE `entry`=10436; +UPDATE `creature_template` SET `ScriptName`='boss_ramstein_the_gorger' WHERE `entry`=10439; +UPDATE `creature_template` SET `ScriptName`='boss_timmy_the_cruel' WHERE `entry`=10808; +UPDATE `creature_template` SET `ScriptName`='boss_silver_hand_bosses' WHERE `entry` IN (17910,17911,17912,17913,17914); +UPDATE `creature_template` SET `ScriptName`='boss_postmaster_malown' WHERE `entry`=11143; +UPDATE `creature_template` SET `ScriptName`='boss_baron_rivendare' WHERE `entry`=10440; +UPDATE `creature_template` SET `ScriptName`='mob_mindless_skeleton' WHERE `entry`=11197; +UPDATE `creature_template` SET `ScriptName`='mob_thuzadin_acolyte' WHERE `entry`=10399; +UPDATE `creature_template` SET `ScriptName`='mobs_spectral_ghostly_citizen' WHERE `entry` IN (10384,10385); +UPDATE `creature_template` SET `ScriptName`='mob_restless_soul' WHERE `entry`=11122; +UPDATE `creature_template` SET `ScriptName`='mob_freed_soul' WHERE `entry`=11136; + +/* SUNKEN TEMPLE */ + + +/* SWAMP OF SORROWS */ + + +/* TANARIS */ +UPDATE `creature_template` SET `ScriptName`='mob_aquementas' WHERE `entry`=9453; +UPDATE `creature_template` SET `ScriptName`='npc_custodian_of_time' WHERE `entry`=20129; +UPDATE `creature_template` SET `ScriptName`='npc_marin_noggenfogger' WHERE `entry`=7564; +UPDATE `creature_template` SET `ScriptName`='npc_steward_of_time' WHERE `entry`=20142; +UPDATE `creature_template` SET `ScriptName`='npc_stone_watcher_of_norgannon' WHERE `entry`=7918; + +/* TELDRASSIL */ + + +/* */ +/* TEMPEST KEEP */ +/* */ + +/* THE MECHANAR */ +UPDATE `creature_template` SET `ScriptName`='boss_gatewatcher_iron_hand' WHERE `entry`=19710; +UPDATE `creature_template` SET `ScriptName`='boss_nethermancer_sepethrea' WHERE `entry`=19221; +UPDATE `creature_template` SET `ScriptName`='mob_ragin_flames' WHERE `entry`=20481; + +/* THE BOTANICA */ +UPDATE `creature_template` SET `ScriptName`='boss_high_botanist_freywinn' WHERE `entry`=17975; +UPDATE `creature_template` SET `ScriptName`='boss_laj' WHERE `entry`=17980; +UPDATE `creature_template` SET `ScriptName`='boss_warp_splinter' WHERE `entry`=17977; +UPDATE `creature_template` SET `ScriptName`='mob_warp_splinter_treant' WHERE `entry`=19949; + +/* THE ARCATRAZ */ +UPDATE `instance_template` SET `script`='instance_arcatraz' WHERE `map`=552; +UPDATE `creature_template` SET `ScriptName`='mob_zerekethvoidzone' WHERE `entry`=21101; +UPDATE `creature_template` SET `ScriptName`='boss_harbinger_skyriss' WHERE `entry`=20912; +UPDATE `creature_template` SET `ScriptName`='boss_harbinger_skyriss_illusion' WHERE `entry` IN (21466,21467); +UPDATE `creature_template` SET `ScriptName`='npc_warden_mellichar' WHERE `entry`=20904; +UPDATE `creature_template` SET `ScriptName`='npc_millhouse_manastorm' WHERE `entry`=20977; + +/* THE EYE */ +UPDATE `instance_template` SET `script`='instance_the_eye' WHERE `map`=550; +/* The Eye Trash Mobs */ +UPDATE `creature_template` SET `ScriptName`='mob_crystalcore_devastator' WHERE `entry`=20040; +/* Void Reaver event */ +UPDATE `creature_template` SET `ScriptName`='boss_void_reaver' WHERE `entry`=19516; +/* Astromancer event */ +UPDATE `creature_template` SET `ScriptName`='boss_high_astromancer_solarian' WHERE `entry`=18805; +UPDATE `creature_template` SET `ScriptName`='mob_solarium_priest' WHERE `entry`=18806; +/* Kael'thas event */ +UPDATE `creature_template` SET `ScriptName`='boss_kaelthas' WHERE `entry`=19622; +UPDATE `creature_template` SET `ScriptName`='boss_thaladred_the_darkener' WHERE `entry`=20064; +UPDATE `creature_template` SET `ScriptName`='boss_lord_sanguinar' WHERE `entry`=20060; +UPDATE `creature_template` SET `ScriptName`='boss_grand_astromancer_capernian' WHERE `entry`=20062; +UPDATE `creature_template` SET `ScriptName`='boss_master_engineer_telonicus' WHERE `entry`=20063; +UPDATE `creature_template` SET `ScriptName`='mob_phoenix' WHERE `entry`=21362; +UPDATE `creature_template` SET `ScriptName`='mob_nether_vapor' WHERE `entry`=21002; +UPDATE `creature_template` SET `ScriptName`='mob_kael_flamestrike' WHERE `entry`=21369; + +/* TEMPLE OF AHN'QIRAJ */ +UPDATE `instance_template` SET `script`='instance_temple_of_ahnqiraj' WHERE `map`=531; +UPDATE `creature_template` SET `ScriptName`='boss_cthun' WHERE `entry`=15727; +UPDATE `creature_template` SET `ScriptName`='boss_skeram' WHERE `entry`=15263; +UPDATE `creature_template` SET `ScriptName`='boss_vem' WHERE `entry`=15544; +UPDATE `creature_template` SET `ScriptName`='boss_yauj' WHERE `entry`=15543; +UPDATE `creature_template` SET `ScriptName`='boss_kri' WHERE `entry`=15511; +UPDATE `creature_template` SET `ScriptName`='boss_sartura' WHERE `entry`=15516; +UPDATE `creature_template` SET `ScriptName`='boss_fankriss' WHERE `entry`=15510; +UPDATE `creature_template` SET `ScriptName`='boss_viscidus' WHERE `entry`=15299; +UPDATE `creature_template` SET `ScriptName`='boss_glob_of_viscidus' WHERE `entry`=15667; +UPDATE `creature_template` SET `ScriptName`='boss_huhuran' WHERE `entry`=15509; +UPDATE `creature_template` SET `ScriptName`='boss_veklor' WHERE `entry`=15276; +UPDATE `creature_template` SET `ScriptName`='boss_veknilash' WHERE `entry`=15275; +UPDATE `creature_template` SET `ScriptName`='boss_ouro' WHERE `entry`=15517; +UPDATE `creature_template` SET `ScriptName`='boss_eye_of_cthun' WHERE `entry`=15589; +UPDATE `creature_template` SET `ScriptName`='mob_sartura_royal_guard' WHERE `entry`=15984; +UPDATE `creature_template` SET `ScriptName`='mob_yauj_brood' WHERE `entry`=15621; +UPDATE `creature_template` SET `ScriptName`='mob_claw_tentacle' WHERE `entry`=15725; +UPDATE `creature_template` SET `ScriptName`='mob_eye_tentacle' WHERE `entry`=15726; +UPDATE `creature_template` SET `ScriptName`='mob_giant_claw_tentacle' WHERE `entry`=15728; +UPDATE `creature_template` SET `ScriptName`='mob_giant_eye_tentacle' WHERE `entry`=15334; +UPDATE `creature_template` SET `ScriptName`='mob_giant_flesh_tentacle' WHERE `entry`=15802; +UPDATE `creature_template` SET `ScriptName`='mob_anubisath_sentinel' WHERE `entry`=15264; + +/* TEROKKAR FOREST */ +UPDATE `creature_template` SET `ScriptName`='mob_infested_root_walker' WHERE `entry`=22095; +UPDATE `creature_template` SET `ScriptName`='mob_netherweb_victim' WHERE `entry`=22355; +UPDATE `creature_template` SET `ScriptName`='mob_rotting_forest_rager' WHERE `entry`=22307; +UPDATE `creature_template` SET `ScriptName`='npc_floon' WHERE `entry`=18588; +UPDATE `creature_template` SET `ScriptName`='npc_skyguard_handler_irena' WHERE `entry`=23413; + +/* THOUSAND NEEDLES */ + + +/* THUNDER BLUFF */ +UPDATE `creature_template` SET `ScriptName`='npc_cairne_bloodhoof' WHERE `entry`=3057; + +/* TIRISFAL GLADES */ +UPDATE `creature_template` SET `ScriptName`='npc_calvin_montague' WHERE `entry`=6784; + +/* ULDAMAN */ +UPDATE `creature_template` SET `ScriptName`='boss_ironaya' WHERE `entry`=7228; +UPDATE `creature_template` SET `ScriptName`='mob_jadespine_basilisk' WHERE `entry`=4863; +UPDATE `creature_template` SET `ScriptName`='npc_lore_keeper_of_norgannon' WHERE `entry`=7172; + +/* UN'GORO CRATER */ + + +/* UNDERCITY */ +UPDATE `creature_template` SET `ScriptName`='npc_lady_sylvanas_windrunner' WHERE `entry`=10181; +UPDATE `creature_template` SET `ScriptName`='npc_highborne_lamenter' WHERE `entry`=21628; +UPDATE `creature_template` SET `ScriptName`='npc_parqual_fintallas' WHERE `entry`=4488; + +/* WAILING CAVERNS */ + + +/* WESTERN PLAGUELANDS */ +UPDATE `creature_template` SET `ScriptName`='npcs_dithers_and_arbington' WHERE `entry` IN (11056,11057); +UPDATE `creature_template` SET `ScriptName`='npc_the_scourge_cauldron' WHERE `entry`=11152; + +/* WESTFALL */ + + +/* WETLANDS */ + + +/* WINTERSPRING */ +UPDATE `creature_template` SET `ScriptName`='npc_lorax' WHERE `entry`=10918; +UPDATE `creature_template` SET `ScriptName`='npc_rivern_frostwind' WHERE `entry`=10618; +UPDATE `creature_template` SET `ScriptName`='npc_witch_doctor_mauari' WHERE `entry`=10307; + +/* ZANGARMARSH */ +UPDATE `creature_template` SET `ScriptName`='npcs_ashyen_and_keleth' WHERE `entry` IN (17900,17901); +UPDATE `creature_template` SET `ScriptName`='npc_cooshcoosh' WHERE `entry`=18586; +UPDATE `creature_template` SET `ScriptName`='npc_elder_kuruti' WHERE `entry`=18197; +UPDATE `creature_template` SET `ScriptName`='npc_mortog_steamhead' WHERE `entry`=23373; + +/* ZUL'AMAN */ +UPDATE `instance_template` SET `script`='instance_zulaman' WHERE `map`=568; +UPDATE `creature_template` SET `ScriptName`='boss_janalai' WHERE `entry`=23578; +UPDATE `creature_template` SET `ScriptName`='boss_nalorakk' WHERE `entry`=23576; +UPDATE `creature_template` SET `ScriptName`='mob_jandalai_firebomb' WHERE `entry`=23920; +UPDATE `creature_template` SET `ScriptName`='mob_amanishi_hatcher' WHERE `entry`=23818; +UPDATE `creature_template` SET `ScriptName`='mob_hatchling' WHERE `entry`=23598; +UPDATE `creature_template` SET `ScriptName`='npc_forest_frog' WHERE `entry`=24396; + +/* ZUL'FARRAK */ +UPDATE `creature_template` SET `ScriptName`='npc_sergeant_bly' WHERE `entry`=7604; +UPDATE `creature_template` SET `ScriptName`='npc_weegli_blastfuse' WHERE `entry`=7607; + +/* ZUL'GURUB */ +UPDATE `instance_template` SET `script`='instance_zulgurub' WHERE `map`=309; +UPDATE `creature_template` SET `ScriptName`='boss_jeklik' WHERE `entry`=14517; +UPDATE `creature_template` SET `ScriptName`='boss_venoxis' WHERE `entry`=14507; +UPDATE `creature_template` SET `ScriptName`='boss_marli' WHERE `entry`=14510; +UPDATE `creature_template` SET `ScriptName`='boss_mandokir' WHERE `entry`=11382; +UPDATE `creature_template` SET `ScriptName`='boss_gahzranka' WHERE `entry`=15114; +UPDATE `creature_template` SET `ScriptName`='boss_jindo' WHERE `entry`=11380; +UPDATE `creature_template` SET `ScriptName`='boss_hakkar' WHERE `entry`=14834; +UPDATE `creature_template` SET `ScriptName`='boss_thekal' WHERE `entry`=14509; +UPDATE `creature_template` SET `ScriptName`='boss_arlokk' WHERE `entry`=14515; +UPDATE `creature_template` SET `ScriptName`='boss_grilek' WHERE `entry`=15082; +UPDATE `creature_template` SET `ScriptName`='boss_hazzarah' WHERE `entry`=15083; +UPDATE `creature_template` SET `ScriptName`='boss_renataki' WHERE `entry`=15084; +UPDATE `creature_template` SET `ScriptName`='boss_wushoolay' WHERE `entry`=15085; +UPDATE `creature_template` SET `ScriptName`='mob_zealot_lorkhan' WHERE `entry`=11347; +UPDATE `creature_template` SET `ScriptName`='mob_zealot_zath' WHERE `entry`=11348; +UPDATE `creature_template` SET `ScriptName`='mob_healing_ward' WHERE `entry`=14987; +UPDATE `creature_template` SET `ScriptName`='mob_spawn_of_marli' WHERE `entry`=15041; +UPDATE `creature_template` SET `ScriptName`='mob_batrider' WHERE `entry`=14965; +UPDATE `creature_template` SET `ScriptName`='mob_shade_of_jindo' WHERE `entry`=14986; + +/* EOF */ diff --git a/src/bindings/scripts/sql/old/mangos_old_spells.sql b/src/bindings/scripts/sql/old/mangos_old_spells.sql new file mode 100644 index 00000000000..8419cacd226 --- /dev/null +++ b/src/bindings/scripts/sql/old/mangos_old_spells.sql @@ -0,0 +1,374 @@ +/* Old spell queries from Scriptdev revision 55. Not supported by scriptdev anylonger */ +/* To be used in ordinary database developement. Can be added in any changeset/revision as database developers sees fit */ + +UPDATE `creature_template` SET `spell1` = 116 WHERE `entry` = 946; +UPDATE `creature_template` SET `spell1` = 16415 WHERE `entry` = 4063; +UPDATE `creature_template` SET `spell1` = 205 WHERE `entry` = 1867; +UPDATE `creature_template` SET `spell1` = 705 WHERE `entry` = 1915; +UPDATE `creature_template` SET `spell1` = 145, `spell2` = 134 WHERE `entry` = 1914; +UPDATE `creature_template` SET `spell1` = 837, `spell2` = 122 WHERE `entry` = 1889; +UPDATE `creature_template` SET `spell1` = 8406, `spell2` = 865 WHERE `entry` = 314; +UPDATE `creature_template` SET `spell1` = 6041, `spell2` = 6364 WHERE `entry` = 2570; +UPDATE `creature_template` SET `spell1` = 8407, `spell2` = 12486 WHERE `entry` = 2567; +UPDATE `creature_template` SET `spell1` = 6041 WHERE `entry` = 697; +UPDATE `creature_template` SET `spell1` = 8402, `spell2` = 8423 WHERE `entry` = 1653; +UPDATE `creature_template` SET `spell1` = 8402 WHERE `entry` = 1562; +UPDATE `creature_template` SET `spell1` = 7641, `spell2` = 11707 WHERE `entry` = 1564; +UPDATE `creature_template` SET `spell1` = 1106 WHERE `entry` = 3218; +UPDATE `creature_template` SET `spell1` = 837 WHERE `entry` = 2591; +UPDATE `creature_template` SET `spell1` = 837 WHERE `entry` = 2255; +UPDATE `creature_template` SET `spell1` = 205 WHERE `entry` = 1539; +UPDATE `creature_template` SET `spell1` = 15264, `spell2` = 6060, `spell3` = 988 WHERE `entry` = 4299; +UPDATE `creature_template` SET `spell1` = 984, `spell2` = 1026 WHERE `entry` = 4296; +UPDATE `creature_template` SET `spell1` = 8438, `spell2` = 2601 WHERE `entry` = 4300; +UPDATE `creature_template` SET `spell1` = 1088, `spell2` = 992 WHERE `entry` = 533; +UPDATE `creature_template` SET `spell1` = 7322 WHERE `entry` = 203; +UPDATE `creature_template` SET `spell1` = 1106, `spell2` = 2941 WHERE `entry` = 2577; +UPDATE `creature_template` SET `spell1` = 548, `spell2` = 6535 WHERE `entry` = 3273; +UPDATE `creature_template` SET `spell1` = 529 WHERE `entry` = 1183; +UPDATE `creature_template` SET `spell1` = 992, `spell2` = 705 WHERE `entry` = 436; +UPDATE `creature_template` SET `spell1` = 5177 WHERE `entry` = 7235; +UPDATE `creature_template` SET `spell1` = 5177 WHERE `entry` = 2012; +UPDATE `creature_template` SET `spell1` = 403, `spell2` = 770 WHERE `entry` = 1397; +UPDATE `creature_template` SET `spell1` = 2136 WHERE `entry` = 1174; +UPDATE `creature_template` SET `spell1` = 143 WHERE `entry` = 2018; +UPDATE `creature_template` SET `spell1` = 915, `spell2` = 2606 WHERE `entry` = 1399; +UPDATE `creature_template` SET `spell1` = 915, `spell2` = 8293 WHERE `entry` = 3783; +UPDATE `creature_template` SET `spell1` = 984 WHERE `entry` = 3732; +UPDATE `creature_template` SET `spell1` = 13480 WHERE `entry` = 3725; +UPDATE `creature_template` SET `spell1` = 13480 WHERE `entry` = 3728; +UPDATE `creature_template` SET `spell1` = 9672, `spell2` = 7101 WHERE `entry` = 3662; +UPDATE `creature_template` SET `spell1` = 18089 WHERE `entry` = 2207; +UPDATE `creature_template` SET `spell1` = 8402, `spell2` = 10215 WHERE `entry` = 7026; +UPDATE `creature_template` SET `spell1` = 11659, `spell2` = 8402 WHERE `entry` = 7028; +UPDATE `creature_template` SET `spell1` = 7918, `spell2` = 6685 WHERE `entry` = 7038; +UPDATE `creature_template` SET `spell1` = 676, `spell2` = 53, `spell3` = 0 WHERE `entry` = 6866; +UPDATE `creature_template` SET `spell1` = 53, `spell2` = 0, `spell3` = 0 WHERE `entry` = 122; +UPDATE `creature_template` SET `spell1` = 71, `spell2` = 1671 WHERE `entry` = 449; +UPDATE `creature_template` SET `spell1` = 6554 WHERE `entry` = 121; +UPDATE `creature_template` SET `spell1` = 53 WHERE `entry` = 590; +UPDATE `creature_template` SET `spell1` = 12166 WHERE `entry` = 3232; +UPDATE `creature_template` SET `spell1` = 403 WHERE `entry` = 2953; +UPDATE `creature_template` SET `spell1` = 3385 WHERE `entry` = 2954; +UPDATE `creature_template` SET `spell1` = 15657, `spell2` = 17230, `spell3` = 16509, `spell4` = 0 WHERE `entry` = 1707; +UPDATE `creature_template` SET `spell1` = 6253, `spell2` = 16244, `spell3` = 8242, `spell4` = 16509 WHERE `entry` = 1711; +UPDATE `creature_template` SET `spell1` = 6547, `spell2` = 2590, `spell3` = 6253 WHERE `entry` = 1708; +UPDATE `creature_template` SET `spell1` = 11554, `spell2` = 8242, `spell3` = 6253 WHERE `entry` = 1715; +UPDATE `creature_template` SET `spell1` = 1768, `spell2` = 17230, `spell3` = 16509 WHERE `entry` = 1706; +UPDATE `creature_template` SET `spell1` = 5115 WHERE `entry` = 1729; +UPDATE `creature_template` SET `spell1` = 9915 WHERE `entry` = 1732; +UPDATE `creature_template` SET `spell1` = 143 WHERE `entry` = 1726; +UPDATE `creature_template` SET `spell1` = 143 WHERE `entry` = 619; +UPDATE `creature_template` SET `spell1` = 6660 WHERE `entry` = 657; +UPDATE `creature_template` SET `spell1` = 6660, `spell2` = 6685 WHERE `entry` = 4417; +UPDATE `creature_template` SET `spell1` = 6685 WHERE `entry` = 598; +UPDATE `creature_template` SET `spell1` = 6016 WHERE `entry` = 4416; +UPDATE `creature_template` SET `spell1` = 5115, `spell2` = 6435 WHERE `entry` = 594; +UPDATE `creature_template` SET `spell1` = 9915 WHERE `entry` = 634; +UPDATE `creature_template` SET `spell1` = 205 WHERE `entry` = 1725; +UPDATE `creature_template` SET `spell1` = 133, `spell2` = 205, `spell3` = 113 WHERE `entry` = 4418; +UPDATE `creature_template` SET `spell1` = 6136, `spell2` = 116 WHERE `entry` = 474; +UPDATE `creature_template` SET `spell1` = 3140, `spell2` = 12486, `spell3` = 3443 WHERE `entry` = 910; +UPDATE `creature_template` SET `spell1` = 744, `spell2` = 7992, `spell3` = 2590 WHERE `entry` = 909; +UPDATE `creature_template` SET `spell1` = 8646 WHERE `entry` = 116; +UPDATE `creature_template` SET `spell1` = 53 WHERE `entry` = 504; +UPDATE `creature_template` SET `spell1` = 2764 WHERE `entry` = 95; +UPDATE `creature_template` SET `spell1` = 53, `spell2` = 133 WHERE `entry` = 94; +UPDATE `creature_template` SET `spell1` = 168 WHERE `entry` = 589; +UPDATE `creature_template` SET `spell1` = 8382, `spell2` = 8733 WHERE `entry` = 4819; +UPDATE `creature_template` SET `spell1` = 6145, `spell2` = 71, `spell3` = 22691 WHERE `entry` = 4818; +UPDATE `creature_template` SET `spell1` = 14109, `spell2` = 3358, `spell3` = 8733, `spell4` = 12024 WHERE `entry` = 4820; +UPDATE `creature_template` SET `spell1` = 7357 WHERE `entry` = 4359; +UPDATE `creature_template` SET `spell1` = 7357 WHERE `entry` = 1024; +UPDATE `creature_template` SET `spell1` = 1777, `spell2` = 6533 WHERE `entry` = 1028; +UPDATE `creature_template` SET `spell1` = 10177 WHERE `entry` = 1418; +UPDATE `creature_template` SET `spell1` = 744, `spell2` = 1707 WHERE `entry` = 1026; +UPDATE `creature_template` SET `spell1` = 7372, `spell2` = 2457 WHERE `entry` = 1027; +UPDATE `creature_template` SET `spell1` = 15869 WHERE `entry` = 1029; +UPDATE `creature_template` SET `spell1` = 7357 WHERE `entry` = 747; +UPDATE `creature_template` SET `spell1` = 7357 WHERE `entry` = 171; +UPDATE `creature_template` SET `spell1` = 7357 WHERE `entry` = 544; +UPDATE `creature_template` SET `spell1` = 7357 WHERE `entry` = 545; +UPDATE `creature_template` SET `spell1` = 7357 WHERE `entry` = 578; +UPDATE `creature_template` SET `spell1` = 744, `spell2` = 865 WHERE `entry` = 127; +UPDATE `creature_template` SET `spell1` = 13519, `spell2` = 6074 WHERE `entry` = 517; +UPDATE `creature_template` SET `spell1` = 10277 WHERE `entry` = 458; +UPDATE `creature_template` SET `spell1` = 7357 WHERE `entry` = 126; +UPDATE `creature_template` SET `spell1` = 205, `spell2` = 331 WHERE `entry` = 548; +UPDATE `creature_template` SET `spell1` = 2589 WHERE `entry` = 732; +UPDATE `creature_template` SET `spell1` = 3368 WHERE `entry` = 46; +UPDATE `creature_template` SET `spell1` = 6268 WHERE `entry` = 1083; +UPDATE `creature_template` SET `spell1` = 3393 WHERE `entry` = 422; +UPDATE `creature_template` SET `spell1` = 3288 WHERE `entry` = 1011; +UPDATE `creature_template` SET `spell1` = 8016 WHERE `entry` = 1008; +UPDATE `creature_template` SET `spell1` = 8016 WHERE `entry` = 1007; +UPDATE `creature_template` SET `spell1` = 205 WHERE `entry` = 1009; +UPDATE `creature_template` SET `spell1` = 547, `spell2` = 548 WHERE `entry` = 1013; +UPDATE `creature_template` SET `spell1` = 744 WHERE `entry` = 434; +UPDATE `creature_template` SET `spell1` = 3150 WHERE `entry` = 433; +UPDATE `creature_template` SET `spell1` = 6205 WHERE `entry` = 432; +UPDATE `creature_template` SET `spell1` = 705 WHERE `entry` = 429; +UPDATE `creature_template` SET `spell1` = 71, `spell2` = 8380, `spell3` = 8629 WHERE `entry` = 568; +UPDATE `creature_template` SET `spell1` = 744 WHERE `entry` = 579; +UPDATE `creature_template` SET `spell1` = 6730, `spell2` = 6016 WHERE `entry` = 448; +UPDATE `creature_template` SET `spell1` = 6730, `spell2` = 6016 WHERE `entry` = 500; +UPDATE `creature_template` SET `spell1` = 8016, `spell2` = 0 WHERE `entry` = 123; +UPDATE `creature_template` SET `spell1` = 1160 WHERE `entry` = 124; +UPDATE `creature_template` SET `spell1` = 3368 WHERE `entry` = 501; +UPDATE `creature_template` SET `spell1` = 3237 WHERE `entry` = 1674; +UPDATE `creature_template` SET `spell1` = 3237 WHERE `entry` = 1772; +UPDATE `creature_template` SET `spell1` = 3237, `spell2` = 695 WHERE `entry` = 1773; +UPDATE `creature_template` SET `spell1` = 3237 WHERE `entry` = 1939; +UPDATE `creature_template` SET `spell1` = 3237 WHERE `entry` = 1940; +UPDATE `creature_template` SET `spell1` = 3237 WHERE `entry` = 1942; +UPDATE `creature_template` SET `spell1` = 3237 WHERE `entry` = 1944; +UPDATE `creature_template` SET `spell1` = 2480 WHERE `entry` = 3112; +UPDATE `creature_template` SET `spell1` = 5280 WHERE `entry` = 3111; +UPDATE `creature_template` SET `spell1` = 3248 WHERE `entry` = 3114; +UPDATE `creature_template` SET `spell1` = 6950, `spell2` = 774 WHERE `entry` = 3113; +UPDATE `creature_template` SET `spell1` = 548, `spell2` = 8045, `spell3` = 8052 WHERE `entry` = 3269; +UPDATE `creature_template` SET `spell1` = 594, `spell2` = 8092, `spell3` = 2052 WHERE `entry` = 3458; +UPDATE `creature_template` SET `spell1` = 594, `spell2` = 598, `spell3` = 8102, `spell4` = 6074 WHERE `entry` = 3271; +UPDATE `creature_template` SET `spell1` = 1978, `spell2` = 3044 WHERE `entry` = 3265; +UPDATE `creature_template` SET `spell1` = 13446, `spell2` = 12323, `spell3` = 13443 WHERE `entry` = 3459; +UPDATE `creature_template` SET `spell1` = 22356 WHERE `entry` = 3267; +UPDATE `creature_template` SET `spell1` = 3427 WHERE `entry` = 712; +UPDATE `creature_template` SET `spell1` = 5164 WHERE `entry` = 446; +UPDATE `creature_template` SET `spell1` = 331, `spell2` = 548 WHERE `entry` = 430; +UPDATE `creature_template` SET `spell1` = 7919 WHERE `entry` = 424; +UPDATE `creature_template` SET `spell1` = 3148 WHERE `entry` = 1115; +UPDATE `creature_template` SET `spell1` = 5164 WHERE `entry` = 1117; +UPDATE `creature_template` SET `spell1` = 53 WHERE `entry` = 1116; +UPDATE `creature_template` SET `spell1` = 5164 WHERE `entry` = 1118; +UPDATE `creature_template` SET `spell1` = 10277 WHERE `entry` = 1162; +UPDATE `creature_template` SET `spell1` = 529 WHERE `entry` = 1166; +UPDATE `creature_template` SET `spell1` = 1776 WHERE `entry` = 1163; +UPDATE `creature_template` SET `spell1` = 11976 WHERE `entry` = 1164; +UPDATE `creature_template` SET `spell1` = 331 WHERE `entry` = 1197; +UPDATE `creature_template` SET `spell1` = 2121 WHERE `entry` = 1165; +UPDATE `creature_template` SET `spell1` = 7405, `spell2` = 71 WHERE `entry` = 1167; +UPDATE `creature_template` SET `spell1` = 11660, `spell2` = 17926, `spell3` = 6215, `spell4` = 11672 WHERE `entry` = 1789; +UPDATE `creature_template` SET `spell1` = 348, `spell2` = 686 WHERE `entry` = 4473; +UPDATE `creature_template` SET `spell1` = 15580, `spell2` = 15613, `spell3` = 23600, `spell4` = 16406 WHERE `entry` = 10391; +UPDATE `creature_template` SET `spell1` = 3416 WHERE `entry` = 531; +UPDATE `creature_template` SET `spell1` = 7369 WHERE `entry` = 1783; +UPDATE `creature_template` SET `spell1` = 838 WHERE `entry` = 7341; +UPDATE `creature_template` SET `spell1` = 15580, `spell2` = 15613, `spell3` = 16406 WHERE `entry` = 10390; +UPDATE `creature_template` SET `spell1` = 9734, `spell2` = 6074 WHERE `entry` = 787; +UPDATE `creature_template` SET `spell1` = 7322, `spell2` = 12486 WHERE `entry` = 203; +UPDATE `creature_template` SET `spell1` = 7992 WHERE `entry` = 1110; +UPDATE `creature_template` SET `spell1` = 17312, `spell2` = 992, `spell3` = 984 WHERE `entry` = 7340; +UPDATE `creature_template` SET `spell1` = 22940, `spell2` = 1411 WHERE `entry` = 1784; +UPDATE `creature_template` SET `spell1` = 705, `spell2` = 1014 WHERE `entry` = 7342; +UPDATE `creature_template` SET `spell1` = 8699 WHERE `entry` = 785; +UPDATE `creature_template` SET `spell1` = 7373 WHERE `entry` = 48; +UPDATE `creature_template` SET `spell1` = 19644, `spell2` = 21949, `spell3` = 19642 WHERE `entry` = 6488; +UPDATE `creature_template` SET `spell1` = 10179, `spell2` = 22645, `spell3` = 13009, `spell4` = 12556 WHERE `entry` = 7358; +UPDATE `creature_template` SET `spell1` = 10148, `spell2` = 12470 WHERE `entry` = 7357; +UPDATE `creature_template` SET `spell1` = 12947, `spell2` = 12946 WHERE `entry` = 7356; +UPDATE `creature_template` SET `spell1` = 12255, `spell2` = 12252, `spell3` = 12254 WHERE `entry` = 7355; +UPDATE `creature_template` SET `spell1` = 10892, `spell2` = 11659 WHERE `entry` = 7354; +UPDATE `creature_template` SET `spell1` = 21667, `spell2` = 21331, `spell3` = 21793 WHERE `entry` = 12225; +UPDATE `creature_template` SET `spell1` = 21080, `spell2` = 8817 WHERE `entry` = 12236; +UPDATE `creature_template` SET `spell1` = 24375, `spell2` = 15580 WHERE `entry` = 12237; +UPDATE `creature_template` SET `spell1` = 21909, `spell2` = 21832, `spell3` = 19128, `spell4` = 21869 WHERE `entry` = 12201; +UPDATE `creature_template` SET `spell1` = 21911, `spell2` = 15584, `spell3` = 21749 WHERE `entry` = 12258; +UPDATE `creature_template` SET `spell1` = 21833, `spell2` = 22334 WHERE `entry` = 13601; +UPDATE `creature_template` SET `spell1` = 21687, `spell2` = 21547, `spell3` = 21707 WHERE `entry` = 13282; +UPDATE `creature_template` SET `spell1` = 9770, `spell2` = 16145, `spell3` = 1604, `spell4` = 9776 WHERE `entry` = 6206; +UPDATE `creature_template` SET `spell1` = 9770, `spell2` = 1604, `spell3` = 12540 WHERE `entry` = 6208; +UPDATE `creature_template` SET `spell1` = 10851 WHERE `entry` = 6209; +UPDATE `creature_template` SET `spell1` = 1604, `spell2` = 6409, `spell3` = 3420 WHERE `entry` = 6215; +UPDATE `creature_template` SET `spell1` = 9459, `spell2` = 1604, `spell3` = 10341, `spell4` = 11638 WHERE `entry` = 6219; +UPDATE `creature_template` SET `spell1` = 16169, `spell2` = 5568, `spell3` = 10887 WHERE `entry` = 6229; +UPDATE `creature_template` SET `spell1` = 3053, `spell2` = 16412 WHERE `entry` = 6228; +UPDATE `creature_template` SET `spell1` = 11082, `spell2` = 11085, `spell3` = 11084 WHERE `entry` = 6235; +UPDATE `creature_template` SET `spell1` = 1604 WHERE `entry` = 7361; +UPDATE `creature_template` SET `spell1` = 6660, `spell2` = 8858 WHERE `entry` = 6407; +UPDATE `creature_template` SET `spell1` = 8211, `spell2` = 10341, `spell3` = 1604, `spell4` = 9459 WHERE `entry` = 6220; +UPDATE `creature_template` SET `spell1` = 10341, `spell2` = 1604, `spell3` = 9459 WHERE `entry` = 6218; +UPDATE `creature_template` SET `spell1` = 1604, `spell2` = 11264, `spell3` = 12024 WHERE `entry` = 7603; +UPDATE `creature_template` SET `spell1` = 6660, `spell2` = 2643, `spell3` = 5116 WHERE `entry` = 6223; +UPDATE `creature_template` SET `spell1` = 13398, `spell2` = 1604, `spell3` = 12024 WHERE `entry` = 6222; +UPDATE `creature_template` SET `spell1` = 11820, `spell2` = 1604 WHERE `entry` = 6234; +UPDATE `creature_template` SET `spell1` = 1604 WHERE `entry` = 6233; +UPDATE `creature_template` SET `spell1` = 11306, `spell2` = 10733 WHERE `entry` = 6226; +UPDATE `creature_template` SET `spell1` = 22519, `spell2` = 11264 WHERE `entry` = 6227; +UPDATE `creature_template` SET `spell1` = 10346, `spell2` = 1604, `spell3` = 17174 WHERE `entry` = 6225; +UPDATE `creature_template` SET `spell1` = 6533, `spell2` = 1604, `spell3` = 11820, `spell4` = 11084 WHERE `entry` = 6230; +UPDATE `creature_template` SET `spell1` = 10341, `spell2` = 9459 WHERE `entry` = 7079; +UPDATE `creature_template` SET `spell1` = 22689, `spell2` = 22662, `spell3` = 19319 WHERE `entry` = 11492; +UPDATE `creature_template` SET `spell1` = 15708, `spell2` = 23511 WHERE `entry` = 14325; +UPDATE `creature_template` SET `spell1` = 10947, `spell2` = 10151 WHERE `entry` = 14324; +UPDATE `creature_template` SET `spell1` = 15580, `spell2` = 15655, `spell3` = 22572, `spell4` = 20691 WHERE `entry` = 14321; +UPDATE `creature_template` SET `spell1` = 15580, `spell2` = 15655, `spell3` = 20691 WHERE `entry` = 14326; +UPDATE `creature_template` SET `spell1` = 15580, `spell2` = 17307, `spell3` = 20691 WHERE `entry` = 14323; +UPDATE `creature_template` SET `spell1` = 22419, `spell2` = 22420, `spell3` = 22421 WHERE `entry` = 13280; +UPDATE `creature_template` SET `spell1` = 22422 WHERE `entry` = 14122; +UPDATE `creature_template` SET `spell1` = 5116, `spell2` = 20904, `spell3` = 14290, `spell4` = 14295 WHERE `entry` = 11488; +UPDATE `creature_template` SET `spell1` = 16128, `spell2` = 15550, `spell3` = 22899 WHERE `entry` = 11496; +UPDATE `creature_template` SET `spell1` = 22909 WHERE `entry` = 14396; +UPDATE `creature_template` SET `spell1` = 15708, `spell2` = 24375 WHERE `entry` = 11501; +UPDATE `creature_template` SET `spell1` = 11668, `spell2` = 14887 WHERE `entry` = 14327; +UPDATE `creature_template` SET `spell1` = 10984 WHERE `entry` = 14506; +UPDATE `creature_template` SET `spell1` = 10894, `spell2` = 10947, `spell3` = 18807 WHERE `entry` = 11487; +UPDATE `creature_template` SET `spell1` = 20691, `spell2` = 22920 WHERE `entry` = 11486; +UPDATE `creature_template` SET `spell1` = 22424, `spell2` = 10151, `spell3` = 16144 WHERE `entry` = 14354; +UPDATE `creature_template` SET `spell1` = 20691, `spell2` = 24375 WHERE `entry` = 11498; +UPDATE `creature_template` SET `spell1` = 15550, `spell2` = 22924, `spell3` = 22994 WHERE `entry` = 11489; +UPDATE `creature_template` SET `spell1` = 22478, `spell2` = 22651 WHERE `entry` = 11490; +UPDATE `creature_template` SET `spell1` = 20832, `spell2` = 16102, `spell3` = 15530, `spell4` = 16170 WHERE `entry` = 11444; +UPDATE `creature_template` SET `spell1` = 22572, `spell2` = 22916 WHERE `entry` = 11450; +UPDATE `creature_template` SET `spell1` = 13737, `spell2` = 20677, `spell3` = 24317 WHERE `entry` = 11441; +UPDATE `creature_template` SET `spell1` = 19474 WHERE `entry` = 11457; +UPDATE `creature_template` SET `spell1` = 22460, `spell2` = 22272 WHERE `entry` = 13197; +UPDATE `creature_template` SET `spell1`=512, `spell2`=1010, `spell3`=0, `spell4`=0 WHERE `entry`=10415; +UPDATE `creature_template` SET `spell1`=1096, `spell2`=0, `spell3`=0, `spell4`=0 WHERE `entry`=10917; +UPDATE `creature_template` SET `spell1`=20603, `spell2`=15398, `spell3`=9256, `spell4`=20741 WHERE `entry`=10813; +UPDATE `creature_template` SET `spell1`=16565, `spell2`=16867, `spell3`=18327, `spell4`=0 WHERE `entry`=10436; +UPDATE `creature_template` SET `spell1`=16866, `spell2`=1604, `spell3`=0, `spell4`=0 WHERE `entry`=10697; +UPDATE `creature_template` SET `spell1`=1604, `spell2`=16866, `spell3`=0, `spell4`=0 WHERE `entry`=10416; +UPDATE `creature_template` SET `spell1`=17439, `spell2`=15584, `spell3`=1604, `spell4`=0 WHERE `entry`=10394; +UPDATE `creature_template` SET `spell1`=1604, `spell2`=5884, `spell3`=0, `spell4`=0 WHERE `entry`=11121; +UPDATE `creature_template` SET `spell1`=16140, `spell2`=1604, `spell3`=0, `spell4`=0 WHERE `entry`=10383; +UPDATE `creature_template` SET `spell1`=1604, `spell2`=3589, `spell3`=0, `spell4`=0 WHERE `entry`=8530; +UPDATE `creature_template` SET `spell1`=23382, `spell2`=15615, `spell3`=16496, `spell4`=0 WHERE `entry`=10997; +UPDATE `creature_template` SET `spell1`=13020, `spell2`=23413, `spell3`=0, `spell4`=0 WHERE `entry`=10425; +UPDATE `creature_template` SET `spell1`=17293, `spell2`=23462, `spell3`=17274, `spell4`=0 WHERE `entry`=10811; +UPDATE `creature_template` SET `spell1`=1604, `spell2`=15749, `spell3`=11972, `spell4`=13534 WHERE `entry`=13118; +UPDATE `creature_template` SET `spell1`=11831, `spell2`=23412, `spell3`=1604, `spell4`=0 WHERE `entry`=10419; +UPDATE `creature_template` SET `spell1`=5101, `spell2`=17143, `spell3`=13005, `spell4`=0 WHERE `entry`=12337; +UPDATE `creature_template` SET `spell1`=13005, `spell2`=1604, `spell3`=20005, `spell4`=0 WHERE `entry`=10421; +UPDATE `creature_template` SET `spell1`=36647, `spell2`=17143, `spell3`=1604, `spell4`=0 WHERE `entry`=10424; +UPDATE `creature_template` SET `spell1`=15749, `spell2`=33871, `spell3`=1604, `spell4`=0 WHERE `entry`=10418; +UPDATE `creature_template` SET `spell1`=17445, `spell2`=1604, `spell3`=39077, `spell4`=0 WHERE `entry`=11120; +UPDATE `creature_template` SET `spell1`=17287, `spell2`=1604, `spell3`=22645, `spell4`=0 WHERE `entry`=10420; +UPDATE `creature_template` SET `spell1`=22645, `spell2`=17165, `spell3`=22947, `spell4`=0 WHERE `entry`=10426; +UPDATE `creature_template` SET `spell1`=36033, `spell2`=17145, `spell3`=1604, `spell4`=0 WHERE `entry`=11043; +UPDATE `creature_template` SET `spell1`=36176, `spell2`=36947, `spell3`=1604, `spell4`=0 WHERE `entry`=10423; +UPDATE `creature_template` SET `spell1`=38094, `spell2`=1604, `spell3`=6788, `spell4`=0 WHERE `entry`=11054; +UPDATE `creature_template` SET `spell1`=15451, `spell2`=16927, `spell3`=16144, `spell4`=15534 WHERE `entry`=10422; +UPDATE `creature_template` SET `spell1`=22412, `spell2`=4962, `spell3`=1604, `spell4`=3589 WHERE `entry`=10413; +UPDATE `creature_template` SET `spell1`=15471, `spell2`=1604, `spell3`=3589, `spell4`=16430 WHERE `entry`=10412; +UPDATE `creature_template` SET `spell1`=16401, `spell2`=12023, `spell3`=1604, `spell4`=20812 WHERE `entry`=8556; +UPDATE `creature_template` SET `spell1`=4629, `spell2`=20549, `spell3`=20812, `spell4`=21949 WHERE `entry`=11859; +UPDATE `creature_template` SET `spell1`=1604, `spell2`=15530, `spell3`=15531, `spell4`=16458 WHERE `entry`=15607; +UPDATE `creature_template` SET `spell1`=16388, `spell2`=0, `spell3`=0, `spell4`=0 WHERE `entry`=10557; +UPDATE `creature_template` SET `spell1`=18200, `spell2`=1604, `spell3`=9791, `spell4`=16458 WHERE `entry`=10407; +UPDATE `creature_template` SET `spell1`=7964, `spell2`=20712, `spell3`=1604, `spell4`=23511 WHERE `entry`=11058; +UPDATE `creature_template` SET `spell1`=16249, `spell2`=16143, `spell3`=16449, `spell4`=0 WHERE `entry`=11136; +UPDATE `creature_template` SET `spell1`=22687, `spell2`=1604, `spell3`=0, `spell4`=0 WHERE `entry`=10385; +UPDATE `creature_template` SET `spell1`=12538, `spell2`=15608, `spell3`=16172, `spell4`=1604 WHERE `entry`=10406; +UPDATE `creature_template` SET `spell1`=17286, `spell2`=1604, `spell3`=20830, `spell4`=0 WHERE `entry`=10812; +UPDATE `creature_template` SET `spell1`=3589, `spell2`=16867, `spell3`=1604, `spell4`=0 WHERE `entry`=8541; +UPDATE `creature_template` SET `spell1`=17685, `spell2`=18663, `spell3`=19643, `spell4`=20812 WHERE `entry`=16101; +UPDATE `creature_template` SET `spell1`=16793, `spell2`=10887, `spell3`=14099, `spell4`=1604 WHERE `entry`=10435; +UPDATE `creature_template` SET `spell1`=15850, `spell2`=16249, `spell3`=20743, `spell4`=16869 WHERE `entry`=10438; +UPDATE `creature_template` SET `spell1`=12734, `spell2`=16172, `spell3`=1604, `spell4`=6788 WHERE `entry`=11032; +UPDATE `creature_template` SET `spell1`=16143, `spell2`=1604, `spell3`=15043, `spell4`=0 WHERE `entry`=10382; +UPDATE `creature_template` SET `spell1`=1604, `spell2`=6788, `spell3`=0, `spell4`=0 WHERE `entry`=11197; +UPDATE `creature_template` SET `spell1`=1604, `spell2`=6788, `spell3`=0, `spell4`=0 WHERE `entry`=11030; +UPDATE `creature_template` SET `spell1`=5568, `spell2`=17307, `spell3`=1604, `spell4`=6788 WHERE `entry`=10439; +UPDATE `creature_template` SET `spell1`=19813, `spell2`=4283, `spell3`=0, `spell4`=0 WHERE `entry`=11658; +UPDATE `creature_template` SET `spell1`=19393, `spell2`=0, `spell3`=0, `spell4`=0 WHERE `entry`=11668; +UPDATE `creature_template` SET `spell1`=25787, `spell2`=0, `spell3`=0, `spell4`=0 WHERE `entry`=12101; +UPDATE `creature_template` SET `spell1`=19364, `spell2`=19365, `spell3`=19369, `spell4`=19367 WHERE `entry`=11673; +UPDATE `creature_template` SET `spell1`=4283, `spell2`=19813, `spell3`=0, `spell4`=0 WHERE `entry`=11659; +UPDATE `creature_template` SET `spell1`=20228, `spell2`=0, `spell3`=0, `spell4`=0 WHERE `entry`=12143; +UPDATE `creature_template` SET `spell1`=20203, `spell2`=0, `spell3`=0, `spell4`=0 WHERE `entry`=11669; +UPDATE `creature_template` SET `spell1`=24668, `spell2`=23952, `spell3`=10960, `spell4`=0 WHERE `entry`=11663; +UPDATE `creature_template` SET `spell1`=23952, `spell2`=20294, `spell3`=0, `spell4`=0 WHERE `entry`=11662; +UPDATE `creature_template` SET `spell1`=20677, `spell2`=20740, `spell3`=0, `spell4`=0 WHERE `entry`=12119; +UPDATE `creature_template` SET `spell1`=20623, `spell2`=0, `spell3`=0, `spell4`=0 WHERE `entry`=11664; +UPDATE `creature_template` SET `spell1`=19778, `spell2`=19771, `spell3`=0, `spell4`=0 WHERE `entry`=11671; +UPDATE `creature_template` SET `spell1`=21081, `spell2`=19730, `spell3`=0, `spell4`=0 WHERE `entry`=11661; +UPDATE `creature_template` SET `spell1`=19626, `spell2`=19630, `spell3`=19631, `spell4`=0 WHERE `entry`=11667; +UPDATE `creature_template` SET `spell1`=19798, `spell2`=19496, `spell3`=0, `spell4`=0 WHERE `entry`=12806; +UPDATE `creature_template` SET `spell1`=19635, `spell2`=0, `spell3`=0, `spell4`=0 WHERE `entry`=11666; +UPDATE `creature_template` SET `spell1`=19642, `spell2`=19644, `spell3`=0, `spell4`=0 WHERE `entry`=12100; +UPDATE `creature_template` SET `spell1`=19641, `spell2`=0, `spell3`=0, `spell4`=0 WHERE `entry`=12076; +UPDATE `creature_template` SET `spell1`=20294, `spell2`=0, `spell3`=0, `spell4`=0 WHERE `entry`=12099; +UPDATE `creature_template` SET `spell1`=18108, `spell2`=0, `spell3`=0, `spell4`=0 WHERE `entry`=12265; +UPDATE `creature_template` SET `spell1`=22689, `spell2`=19319, `spell3`=0, `spell4`=0 WHERE `entry`=11672; +UPDATE `creature_template` SET `spell1`=35178, `spell2`=15749, `spell3`=0, `spell4`=0 WHERE `entry`=10509; +UPDATE `creature_template` SET `spell1`=35178, `spell2`=0, `spell3`=0, `spell4`=0 WHERE `entry`=9819; +UPDATE `creature_template` SET `spell1`=30688, `spell2`=0, `spell3`=0, `spell4`=0 WHERE `entry`=10319; +UPDATE `creature_template` SET `spell1`=20816, `spell2`=0, `spell3`=0, `spell4`=0 WHERE `entry`=9817; +UPDATE `creature_template` SET `spell1`=32192, `spell2`=18108, `spell3`=0, `spell4`=0 WHERE `entry`=9818; +UPDATE `creature_template` SET `spell1`=23462, `spell2`=23341, `spell3`=17274, `spell4`=0 WHERE `entry`=9816; +UPDATE `creature_template` SET `spell1`=24317, `spell2`=0, `spell3`=0, `spell4`=0 WHERE `entry`=10258; +UPDATE `creature_template` SET `spell1`=145, `spell2`=0, `spell3`=0, `spell4`=0 WHERE `entry`=10161; +UPDATE `creature_template` SET `spell1`=0, `spell2`=0, `spell3`=0, `spell4`=0 WHERE `entry`=10683; +UPDATE `creature_template` SET `spell1`=28725, `spell2`=0, `spell3`=0, `spell4`=0 WHERE `entry`=10264; +UPDATE `creature_template` SET `spell1`=12461, `spell2`=22591, `spell3`=16172, `spell4`=24317 WHERE `entry`=10899; +UPDATE `creature_template` SET `spell1`=12461, `spell2`=0, `spell3`=0, `spell4`=0 WHERE `entry`=10317; +UPDATE `creature_template` SET `spell1`=0, `spell2`=0, `spell3`=0, `spell4`=0 WHERE `entry`=10762; +UPDATE `creature_template` SET `spell1`=0, `spell2`=0, `spell3`=0, `spell4`=0 WHERE `entry`=10742; +UPDATE `creature_template` SET `spell1`=30014, `spell2`=32370, `spell3`=0, `spell4`=0 WHERE `entry`=10447; +UPDATE `creature_template` SET `spell1`=22414, `spell2`=23512, `spell3`=0, `spell4`=0 WHERE `entry`=10442; +UPDATE `creature_template` SET `spell1`=20691, `spell2`=15589, `spell3`=23931, `spell4`=0 WHERE `entry`=10429; +UPDATE `creature_template` SET `spell1`=20667, `spell2`=20712, `spell3`=18763, `spell4`=0 WHERE `entry`=10339; +UPDATE `creature_template` SET `spell1`=11286, `spell2`=0, `spell3`=0, `spell4`=0 WHERE `entry`=10318; +UPDATE `creature_template` SET `spell1`=23462, `spell2`=25668, `spell3`=0, `spell4`=0 WHERE `entry`=10372; +UPDATE `creature_template` SET `spell1`=28168, `spell2`=27580, `spell3`=0, `spell4`=0 WHERE `entry`=10371; +UPDATE `creature_template` SET `spell1`=23462, `spell2`=0, `spell3`=0, `spell4`=0 WHERE `entry`=10083; +UPDATE `creature_template` SET `spell1`=20741, `spell2`=24668, `spell3`=0, `spell4`=0 WHERE `entry`=10162; +UPDATE `creature_template` SET `spell1`=17883, `spell2`=16785, `spell3`=0, `spell4`=0 WHERE `entry`=10430; +UPDATE `creature_template` SET `spell1`=23462, `spell2`=20691, `spell3`=23023, `spell4`=23931 WHERE `entry`=10363; +UPDATE `creature_template` SET `spell1`=20276, `spell2`=0, `spell3`=0, `spell4`=0 WHERE `entry`=10814; +UPDATE `creature_template` SET `spell1`=13496, `spell2`=0, `spell3`=0, `spell4`=0 WHERE `entry`=11598; +UPDATE `creature_template` SET `spell1`=27559, `spell2`=20691, `spell3`=12020, `spell4`=30138 WHERE `entry`=10487; +UPDATE `creature_template` SET `spell1`=17715, `spell2`=27559, `spell3`=20276, `spell4`=0 WHERE `entry`=10491; +UPDATE `creature_template` SET `spell1`=11660, `spell2`=18807, `spell3`=0, `spell4`=0 WHERE `entry`=10470; +UPDATE `creature_template` SET `spell1`=18270, `spell2`=0, `spell3`=0, `spell4`=0 WHERE `entry`=10481; +UPDATE `creature_template` SET `spell1`=18116, `spell2`=17695, `spell3`=20741, `spell4`=15584 WHERE `entry`=10433; +UPDATE `creature_template` SET `spell1`=17472, `spell2`=15584, `spell3`=0, `spell4`=0 WHERE `entry`=10482; +UPDATE `creature_template` SET `spell1`=18106, `spell2`=18116, `spell3`=15584, `spell4`=0 WHERE `entry`=11261; +UPDATE `creature_template` SET `spell1`=18116, `spell2`=20741, `spell3`=18144, `spell4`=0 WHERE `entry`=10506; +UPDATE `creature_template` SET `spell1`=11672, `spell2`=12020, `spell3`=18116, `spell4`=0 WHERE `entry`=10505; +UPDATE `creature_template` SET `spell1`=16359, `spell2`=3584, `spell3`=18116, `spell4`=0 WHERE `entry`=10901; +UPDATE `creature_template` SET `spell1`=24375, `spell2`=18813, `spell3`=18116, `spell4`=0 WHERE `entry`=11622; +UPDATE `creature_template` SET `spell1`=15550, `spell2`=20691, `spell3`=18116, `spell4`=0 WHERE `entry`=10507; +UPDATE `creature_template` SET `spell1`=11668, `spell2`=11700, `spell3`=18116, `spell4`=0 WHERE `entry`=10504; +UPDATE `creature_template` SET `spell1`=24673, `spell2`=18270, `spell3`=18116, `spell4`=0 WHERE `entry`=10503; +UPDATE `creature_template` SET `spell1`=15584, `spell2`=17472, `spell3`=0, `spell4`=0 WHERE `entry`=11439; +UPDATE `creature_template` SET `spell1`=18116, `spell2`=19460, `spell3`=6215, `spell4`=15487 WHERE `entry`=10502; +UPDATE `creature_template` SET `spell1`=18702, `spell2`=10212, `spell3`=18116, `spell4`=0 WHERE `entry`=1853; +UPDATE `creature_template` SET `spell1`=16350, `spell2`=21369, `spell3`=8398, `spell4`=18033 WHERE `entry`=10508; +UPDATE `creature_template` SET `spell1`=27224, `spell2`=30900, `spell3`=3609, `spell4`=0 WHERE `entry`=14861; +UPDATE `creature_template` SET `spell1`=18278, `spell2`=29405, `spell3`=12020, `spell4`=0 WHERE `entry`=10498; +UPDATE `creature_template` SET `spell1`=24063, `spell2`=18270, `spell3`=0, `spell4`=0 WHERE `entry`=10495; +UPDATE `creature_template` SET `spell1`=12020, `spell2`=18278, `spell3`=25304, `spell4`=0 WHERE `entry`=11263; +UPDATE `creature_template` SET `spell1`=16469, `spell2`=25349, `spell3`=0, `spell4`=0 WHERE `entry`=11551; +UPDATE `creature_template` SET `spell1`=25304, `spell2`=11660, `spell3`=12020, `spell4`=0 WHERE `entry`=10477; +UPDATE `creature_template` SET `spell1`=25304, `spell2`=12020, `spell3`=10161, `spell4`=0 WHERE `entry`=10472; +UPDATE `creature_template` SET `spell1`=15571, `spell2`=0, `spell3`=0, `spell4`=0 WHERE `entry`=10475; +UPDATE `creature_template` SET `spell1`=25304, `spell2`=10161, `spell3`=10473, `spell4`=0 WHERE `entry`=10469; +UPDATE `creature_template` SET `spell1`=11660, `spell2`=15571, `spell3`=10161, `spell4`=0 WHERE `entry`=11284; +UPDATE `creature_template` SET `spell1`=17689, `spell2`=15571, `spell3`=18270, `spell4`=0 WHERE `entry`=10480; +UPDATE `creature_template` SET `spell1`=15571, `spell2`=30138, `spell3`=0, `spell4`=0 WHERE `entry`=10497; +UPDATE `creature_template` SET `spell1`=15571, `spell2`=30138, `spell3`=0, `spell4`=0 WHERE `entry`=10479; +UPDATE `creature_template` SET `spell1`=17504, `spell2`=12867, `spell3`=0, `spell4`=0 WHERE `entry`=14513; +UPDATE `creature_template` SET `spell1`=17504, `spell2`=12867, `spell3`=24673, `spell4`=0 WHERE `entry`=14520; +UPDATE `creature_template` SET `spell1`=30138, `spell2`=11660, `spell3`=0, `spell4`=0 WHERE `entry`=14521; +UPDATE `creature_template` SET `spell1`=11556, `spell2`=8140, `spell3`=23262, `spell4`=0 WHERE `entry`=14518; +UPDATE `creature_template` SET `spell1`=10894, `spell2`=23244, `spell3`=0, `spell4`=0 WHERE `entry`=14519; +UPDATE `creature_template` SET `spell1`=11556, `spell2`=8140, `spell3`=15571, `spell4`=0 WHERE `entry`=14514; +UPDATE `creature_template` SET `spell1`=15571, `spell2`=23244, `spell3`=0, `spell4`=0 WHERE `entry`=14512; +UPDATE `creature_template` SET `spell1`=12292, `spell2`=15571, `spell3`=28168, `spell4`=0 WHERE `entry`=10488; +UPDATE `creature_template` SET `spell1`=15571, `spell2`=24063, `spell3`=18270, `spell4`=12021 WHERE `entry`=10485; +UPDATE `creature_template` SET `spell1`=10161, `spell2`=13021, `spell3`=20883, `spell4`=0 WHERE `entry`=11257; +UPDATE `creature_template` SET `spell1`=15571, `spell2`=0, `spell3`=0, `spell4`=0 WHERE `entry`=10478; +UPDATE `creature_template` SET `spell1`=17504, `spell2`=26554, `spell3`=35011, `spell4`=0 WHERE `entry`=10486; +UPDATE `creature_template` SET `spell1`=19627, `spell2`=18816, `spell3`=13021, `spell4`=0 WHERE `entry`=10432; +UPDATE `creature_template` SET `spell1`=18807, `spell2`=10876, `spell3`=0, `spell4`=0 WHERE `entry`=10471; +UPDATE `creature_template` SET `spell1`=10876, `spell2`=25304, `spell3`=18647, `spell4`=0 WHERE `entry`=10500; +UPDATE `creature_template` SET `spell1`=29684, `spell2`=25051, `spell3`=0, `spell4`=0 WHERE `entry`=10489; + +UPDATE `creature_template` SET `spell1` = 24317, `spell2` = 19644 WHERE `entry` = 8890; +UPDATE `creature_template` SET `spell1` = 30901, `spell2` = 27581, `spell3` = 34510 WHERE `entry` = 8891; +UPDATE `creature_template` SET `spell1` = 29560, `spell2` = 19644 WHERE `entry` = 8892; +UPDATE `creature_template` SET `spell1` = 40082, `spell2` = 30901 WHERE `entry` = 8893; +UPDATE `creature_template` SET `spell1` = 8812, `spell2` = 10961, `spell3` = 10947 WHERE `entry` = 8894; +UPDATE `creature_template` SET `spell1` = 25292, `spell2` = 1020 WHERE `entry` = 8895; +UPDATE `creature_template` SET `spell1` = 17143, `spell2` = 10293, `spell3` = 25292 WHERE `entry` = 8898; diff --git a/src/bindings/scripts/sql/optional/mangos_optional_generic_creature.sql b/src/bindings/scripts/sql/optional/mangos_optional_generic_creature.sql new file mode 100644 index 00000000000..a787b584e66 --- /dev/null +++ b/src/bindings/scripts/sql/optional/mangos_optional_generic_creature.sql @@ -0,0 +1,283 @@ +/* */ + +/* WORLD CREATURE These are creatures to be found in more than one specific zone */ +/* Spider */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (14881); + +/* */ +/* ZONE */ +/* */ + +/* ALTERAC MOUNTAINS */ +/* Crushridge Mage, Argus Shadow Mage, Dalaran Summoner, Archmage Ansirem Runeweaver */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (2255, 2318, 2358, 2543); + +/* ALTERAC VALLEY */ +/* Wildpaw Mystic */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (11838); + +/* ARATHI HIGHLANDS */ +/* Feeboz, Boulderfist Shaman, Boulderfist Magus, Syndicate Magus, Dark Iron Shadowcaster, Witherbark Axe Thrower, Plains Creeper, Giant Plains Creeper */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (4063, 2570, 2567, 2591, 2577, 2554, 2563, 2565); + +/* ASHENVALE */ +/* Shadethicket Raincaller, Forsaken Seeker, Dark Strand Cultist, Dark Strand Adept */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (3783, 3732, 3725, 3728); + + +/* */ +/* AUCHINDOUN */ +/* */ + + + +/* AZSHARA */ +/* Draconic Magelord, Draconic Mageweaver, Archmage Xylem */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (6129, 6131, 8379); + +/* BADLANDS */ +/* Dustbelcher Ogre Mage, Dustbelcher Mystic, Shadowmage Vivian Lagrave */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (2720, 2907, 9078); + +/* BARRENS */ +/* Kolkar Stormer, Razormane Geomancer, Razormane Seer, Razormane Mystic, Razormane Hunter, Razormane Warfrenzy, Razormane Water Seeker, Silithid Creeper, Elder Mystic Razorsnout, Horde Axe Thrower */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (3273, 3269, 3458, 3271, 3265, 3459, 3267, 3250, 3270, 9458); + +/* BLACKFATHOM DEPTHS */ +/* Blindlight Oracle, Blindlight Muckdweller, Blindlight Murloc, Twilight Shadowmage */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (4820, 4819, 4818, 4813); + + +/* Hedrum the Creeper, Dark Keeper Zimrel */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (9032, 9441); +/* Anvilrage military */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (8890, 8891, 8892, 8893, 8894, 8895, 8898); +/* Cave Creeper */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (8933); + +/* BLACKROCK SPIRE */ +/* Blackhand Dreadweaver,Blackhand Summoner,Blackhand Veteran,Blackhand Elite,Blackhand Assassin,Blackhand Iron Guard,Chromatic Whelp,Chromatic Dragonspawn,Rookery Whelp,Rookery Guardian,Rage Talon Captain,Rage Talon Fire Tongue,Rage Talon Flamescale */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (9817, 9818, 9819, 10317, 10318, 10319, 10442, 10447, 10161, 10258, 10371, 10372, 10083); +/* Spirestone Battle Mage, Spirestone Mystic, Smolderthorn Mystic, Smolderthorn Axe Thrower, Bloodaxe Summoner , Spire Spider, Spire Spiderling */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (9197, 9198, 9239, 9267, 9717, 10374, 10375); + + +/* BLACKROCK SPIRE Upper */ +/* Jed Runewatcher,Solakar Flamewreath,Goraluk Anvilcrack */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry`IN (10509,10264,10899); + +/* BLACKWING LAIR */ +/* Trash Mobs */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (12420); + + +/* BLASTED LANDS */ +/* Dreadmaul Ogre Mage, Bloodmage Drazial, Bloodmage Lynnore, Archmage Allistarj */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (5975, 7505, 7506, 7666); + +/* BURNING STEPPES */ +/* Blackrock Sorcerer, Blackrock Warlock, Scalding Broodling, Thaurissan Agent, Firegut Ogre Mage */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (7026, 7028, 7048, 7038, 7034); + + +/* DARKSHORE */ +/* Delmanis the Hated, Greymist Oracle, */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (3662, 2207); + +/* DEADMINES */ +/* Defias Squallshaper, Defias Magician, Defias Conjurer, Defias Overseer, Defias Watchman, Defias Wizard, Defias Evoker, Defias Pirate, Defias Taskmaster, Defias Miner, Defias Strip Miner, Defias Henchman, */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (1732, 1726, 619, 634, 1725, 4418, 1729, 657, 4417, 598, 4416, 594); + +/* DEADWIND PASS */ +/* Deadwind Ogre Mage */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (7379); + +/* DESOLACE */ +/* Burning Blade Shadowmage, Burning Blade Summoner, Mage Hunter */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (4667, 4668, 4681); + +/* DIRE MAUL */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (11492, 14325, 14324, 14321, 14326, 14323, 13280, 14122, 11488, 11496, 14396, 11501, 14327, 14506, 11487, 11486, 14354, 11498, 11489, 11490, 11444, 11450, 11441, 11457, 13197); +/* Gordok Mage-Lord, Highborne Summoner */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (11444, 11466); + +/* DUN MOROGH */ +/* Frostmane Novice, Frostmane Seer, Rockjaw Skullthumper, Rockjaw Bonesnapper, Rockjaw Ambusher, Rockjaw Backbreaker, */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (946, 1397, 1115, 1117, 1116, 1118); + +/* DUROTAR */ +/* Razormane Scout, Razormane Dustrunner, Razormane Quilboar, Razormane Battleguard, Vile Familiar */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (3112, 3113, 3111, 3114, 3101); + +/* DUSKWOOD */ +/* Eliza, Nightbane Shadow Weaver, Skeletal Mage, Defias Night Runner, Defias Night Blade, Skeletal Fiend, Skeletal Healer, Skeletal Mage, Skeletal Raider, Skeletal Warder, Skeletal Warrior, Venom Web Spider, Pygmy Venom Web Spider */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (314, 533, 203, 215, 909, 531, 787, 203, 1110, 785, 48, 217, 539); + +/* DUSTWALLOW MARSH */ +/* Mirefin Murloc, Darkmist Spider, Withervine Creeper, Darkfang Creeper, Darkfang Spider, Giant Darkfang Spider, Archmage Tervosh */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (4359, 4376, 4382, 4412, 4413, 4415, 4967); + +/* EASTERN PLAGUELANDS */ +/* Crimson Bodyguard, Crimson Courier, Crypt Walker, Hate Shrieker, Cursed Mage, Shadowmage, Dark Summoner, Scarlet Archmage, Archmage Angela Dosantos */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (13118, 12337, 8556, 8541, 8524, 8550, 8551, 9451, 16116); + +/* ELWYNN FOREST */ +/* Hogger, Defias Rogue Wizard, Defias Enchanter, Defias Bodyguard, Defias Bandit, Defias Cutpurse, Murloc Lurker, Murloc Forager, Forest Spider, Mine Spider */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (448, 474, 910, 6866, 116, 94, 732, 46, 30, 43); + +/* FELWOOD */ +/* Timbermaw Mystic */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (11552); + +/* FERALAS */ +/* Gordunni Ogre Mage, Gordunni Mage-Lord, Woodpaw Mystic, Gordok Ogre-Mage */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (5237, 5239, 5254, 11443); + +/* GNOMEREGAN */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (6206, 6208, 6209, 6215, 6219, 6229, 6228, 6235, 7361, 6407, 6220, 6218, 7603, 6223, 6222, 6234, 6233, 6226, 6227, 6225, 6230, 7079); + +/* */ +/* HELLFIRE CITADEL */ +/* */ + +/* Laughing Skull Legionnaire, Laughing Skull Warden, Laughing Skull Rogue, Hellfire Imp, Shadowmoon Channeler, Fel Orc Neophyte, Shadowmoon Technician, Shadowmoon Adept, Hellfire Familiar, Felguard Brute, Shadowmoon Summoner, Shadowmoon Warlock */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (17626, 17624, 17491, 17477, 17653, 17429, 17414, 17397, 19016, 18894, 17395, 17371); + +/* HELLFIRE RAMPARTS */ +/* Vazruden, Omor the Unscarred, Watchkeeper Gargolmar */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (17537, 17308, 17306); +/* Hellfire Watcher , Bonechewer Hungerer, Bonechewer Beastmaster, Bonechewer Ravener, Bonechewer Ripper, Bonechewer Destroyer, Bleeding Hollow Archer, Bleeding Hollow Darkcaster, Hellfire Sentry , Bleeding Hollow Scryer */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (17309, 17259, 17455, 17264, 17281, 17271, 17270, 17269, 17517, 17478); + +/* SHATTERED HALLS */ +/* Warchief Kargath Bladefist */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (16808); +/* Shattered Hand Centurion, Shadowmoon Darkcaster, Shattered Hand Champion, Sharpshooter Guard, Shattered Hand Assassin, Warbringer O'mrogg, Grand Warlock Nethekurse, Shattered Hand Sharpshooter, Shattered Hand Legionnaire, Shattered Hand Reaver, Shattered Hand Brawler */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (17465, 17694, 17671, 17622, 17695, 16809, 16807, 16704, 16700, 16699, 16593); + + +/* HILLSBRAD FOOTHILLS */ +/* Syndicate Shadow Mage, Elder Moss Creeper, Giant Moss Creeper(also AM), Forest Moss Creeper, Writhing Mage */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (2244, 2348, 2349, 2350, 7075); + +/* HINTERLANDS */ +/* Vilebranch Axe Thrower, Mystic Yayo'jin */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (2639, 14739); + +/* LOCH MODAN */ +/* Mo'grosh Mystic, Tunnel Rat Geomancer, Magosh , Stonesplinter Scout, Stonesplinter Seer, Stonesplinter Geomancer, Stonesplinter Skullthumper, Stonesplinter Bonesnapper, Stonesplinter Shaman, Stonesplinter Digger, */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (1183, 1174, 1399, 1162, 1166, 1165, 1163, 1164, 1197, 1167); + +/* MULGORE */ +/* Bristleback Shaman, Bristleback Interloper, Bristleback Quilboar, Bristleback Battleboar, Bristleback Interloper, */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (2953, 3232, 2952, 2954, 3232); + +/* NAXXRAMAS */ +/* Dread Creeper, Archmage Tarsis Kir-Moldir */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (15974, 16381); + +/* ONYXIA'S LAIR */ +/* Onyxian Whelp */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (11262); + +/* RAZORFEN DOWNS */ +/* Mordresh Fire Eye, Plaguemaw the Rotting, Tuten\'kash, Ragglesnout, Glutton */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (7357, 7356, 7355, 7354, 8567); +/* Skeletal Frostweaver, Skeletal Shadowcaster, Skeletal Summoner, */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (7341, 7340, 7342); + +/* REDRIDGE MOUNTAINS */ +/* Blackrock Shadowcaster, Murloc Minor Tidecaller, Murloc Nightcrawler, Murloc Tidecaller, Murloc Scout, Murloc Shorestriker, Shadowhide Darkweaver, Rabid Shadowhide Gnoll, Shadowhide Gnoll, Shadowhide Brute, Shadowhide Warrior, Shadowhide Assassin, Redridge Mystic, Redridge Poacher, Redridge Thrasher, Redridge Basher, Black Dragon Whelp, Tarantula, Greater Tarantula, Blackrock Summoner */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (436, 548, 544, 545, 578, 1083, 422, 429, 434, 433, 432, 568, 579, 430, 424, 712, 446, 441, 442, 505, 4463); + +/* SCARLET MONASTERY */ +/* Fallen Champion, Scarlet Chaplain, Scarlet Adept, Scarlet Wizard, */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (6488, 4299, 4296, 4300); + +/* SCHOLOMANCE */ +/* Kirtonos the Herald, Rattlegore, Marduk Blackpool, Risen Guard, Risen Bonewarder, Risen Lackey, Risen Aberration, Risen Warrior, Risen Protector, Risen Construct, Risen Guardian, Diseased Ghoul, Ragged Ghoul, Spectral Projection, Spectral Teacher, Necrofiend, Scholomance Neophyte, Scholomance Acolyte, Scholomance Occultist */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (10506, 11622, 10433, 10489, 10491, 10482, 10485, 10486, 10487, 10488, 11598, 10495, 10497, 11263, 10500, 11551, 10470, 10471, 10472); +/* Scholomance Student, Scholomance Necromancer, Scholomance Adept, Scholomance Handler, Splintered Skeleton, Skulking Corpse, Unstable Corpse, Reanimated Corpse, Aspect of Banality, Aspect of Corruption, Aspect of Malice, Aspect of Shadow, Blood Steward of Kirtonos, Spectral Tutor, Dark Shade, Corrupted Spirit, Malicious Spirit, Banal Spirit, Scholomance Dark Summoner */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (10475, 10477, 10469, 11257, 10478, 10479, 10480, 10481, 14518, 14519, 14520, 14521, 14861, 10498, 11284, 14512, 14513, 14514, 11582); + +/* SEARING GORGE */ +/* Glassweb Spider, Searing Lava Spider, Greater Lava Spider */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (5856, 5857, 5858); + +/* SHADOWFANG KEEP */ +/* Archmage Arugal */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (4275); + + +/* SILITHUS */ +/* Orgrimmar Legion Axe Thrower, Stormwind Archmage */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (15617, 15859); + +/* SILVERPINE FOREST */ +/* Dalaran Apprentice, Dalaran Conjuror, Dalaran Mage, Dalaran Wizard, Rot Hide Mystic, Rot Hide Gladerunner, Rot Hide Brute, Rot Hide Plague Weaver, Rot Hide Savage, Rot Hide Bruiser, Mist Creeper, Dalaran Apprentice, Dalaran Wizard, Dalaran Protector, Dalaran Warder, Dalaran Mage, Dalaran Conjuror, Lake Creeper, Elder Lake Creeper, Vile Fin Shorecreeper, Nightlash, Archmage Ataeric */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (1867, 1915, 1914, 1889, 1773, 1772, 1939, 1940, 1942, 1944, 1781, 1867, 1889, 1912, 1913, 1914, 1915, 1955, 1956, 1957, 1983, 2120); + +/* STOCKADES */ +/* Defias Captive, Defias Convict, Defias Inmate, Defias Insurgent, Defias Prisoner, */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (1707, 1711, 1708, 1715, 1706); + +/* STONETALON MOUNTAINS */ +/* Deepmoss Creeper */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (4005); + +/* STRANGLETHORN VALE */ +/* Bloodscalp Shaman, Bloodsail Elder Magus, Bloodsail Mage, Bloodsail Warlock, Bloodscalp Axe Thrower, Skullsplitter Axe Thrower, Bloodscalp Mystic, Skullsplitter Mystic */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (697, 1653, 1562, 1564, 694, 696, 701, 780); + +/* STRATHOLME */ +/* Jarien, Aurius, Ash'ari Crystal, Elder Farwhisper, Mindless Undead */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (16101, 10917, 10415, 15607, 11030); + +/* SUNKEN TEMPLE */ +/* Zekkis, Kazkaz the Unholy, Spawn of Hakkar, Shade of Eranikus, Jammal'an the Prophet, Ogom the Wretched, Zolo, Gasher, Loro, Hukku, Zul'Lor, Mijan, Morphaz, Weaver, Dreamscythe, Hazzas, Avatar of Hakkar, Atal'alarion */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (5400, 5401, 5708, 5709, 5710, 5711, 5712, 5713, 5714, 5715, 5716, 5717, 5719, 5720, 5721, 5722, 8443, 8580); +/* Jade, Murk Slitherer, Murk Spitter, Murk Worm, Saturated Ooze, Fungal Ooze, Cursed Atal'ai, Atal'ai Witch Doctor, Enthralled Atal'ai, Mummified Atal'ai, Unliving Atal'ai, Atal'ai Priest, Atal'ai Corpse Eater, Atal'ai Deathwalker, Atal'ai High Priest, Nightmare Scalebane, Nightmare Wyrmkin, Nightmare Wanderer, Hakkari Frostwing, Nightmare Whelp, Atal'ai Skeleton, Hakkari Sapper, Hakkari Minion, Hakkari Bloodkeeper, Nightmare Suppressor */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (1063, 5224, 5225, 5226, 5228, 5235, 5243, 5259, 5261, 5263, 5267, 5269, 5270, 5271, 5273, 5277, 5280, 5283, 5291, 8319, 8324, 8336, 8437, 8438, 8497); + +/* SWAMP OF SORROWS */ +/* Marsh Murloc, Adolescent Whelp, Dreaming Whelp, Wyrmkin Dreamwalker, Scalebane Captain, Deathstrike Tarantula */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (747, 740, 741, 743, 745, 769); + +/* TANARIS */ +/* Dunemaul Ogre Mage, Wastewander Shadow Mage, Sandfury Axe Thrower */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (5473, 5617, 5646); + +/* TELDRASSIL */ +/* Gnarlpine Mystic, Gnarlpine Pathfinder, Bloodfeather Sorceress, Webwood Spider, Giant Webwood Spider */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (7235, 2012, 2018, 1986, 2001); + +/* TIRISFAL GLADES */ +/* Scarlet Neophyte, Rot Hide Gnoll, Young Night Web Spider, Night Web Spider, Vicious Night Web Spider */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (1539, 1674, 1504, 1505, 1555); + +/* UN'GORO CRATER */ +/* Tar Creeper */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (6527); + +/* WAILING CAVERNS */ +/* Deviate Creeper */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (3632); + +/* WESTERN PLAGUELANDS */ +/* Skeletal Acolyte, Skeletal Flayer, Skeletal Sorcerer, Scarlet Mage, Araj the Summoner */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (1789, 1783, 1784, 1826, 1852); + +/* WESTFALL */ +/* Defias Pillager, Defias Smuggler, Defias Trapper, Defias Highwayman, Defias Knuckleduster, Defias Pathstalker, Defias Looter, Murloc Oracle, Murloc Hunter, Murloc Warrior, Murloc Tidehunter, Murloc Coastrunner, Riverpaw Scout, Riverpaw Mongrel, Riverpaw Brute, Riverpaw Herbalist, Defias Renegade Mage, Riverpaw Mystic */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (589, 95, 504, 122, 449, 121, 590, 517, 458, 171, 127, 126, 500, 123, 124, 501, 450, 453); + +/* WETLANDS */ +/* Bluegill Forager, Bluegill Murloc, Bluegill Muckdweller, Bluegill Raider, Bluegill Warrior, Bluegill Oracle, Mosshide Mistweaver, Mosshide Mystic, Mosshide Trapper, Mosshide Mongrel, Mosshide Gnoll, Fen Creeper, Red Whelp, Lost Whelp, Flamesnorting Whelp, Crimson Whelp */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (1026, 1024, 1028, 1418, 1027, 1029, 1009, 1013, 1011, 1008, 1007, 1040, 1042, 1043, 1044, 1069); + +/* WINTERSPRING */ +/* Cobalt Mageweaver, Chillwind Chimaera */ +UPDATE `creature_template` SET `ScriptName` = 'generic_creature' WHERE `entry` IN (7437, 7448); + + +/* EOF */ diff --git a/src/bindings/scripts/sql/scriptdev2_structure.sql b/src/bindings/scripts/sql/scriptdev2_structure.sql new file mode 100644 index 00000000000..7c20c216b6e --- /dev/null +++ b/src/bindings/scripts/sql/scriptdev2_structure.sql @@ -0,0 +1,105 @@ +DROP TABLE IF EXISTS `eventai_scripts`; +CREATE TABLE `eventai_scripts` ( +`id` int(11) unsigned NOT NULL COMMENT 'Identifier' AUTO_INCREMENT, +`creature_id` int(11) unsigned NOT NULL default '0' COMMENT 'Creature Template Identifier', + +`event_type` tinyint(5) unsigned NOT NULL default '0' COMMENT 'Event Type', +`event_inverse_phase_mask` int(11) signed NOT NULL default '0' COMMENT 'Mask which phases this event will not trigger in', +`event_chance` int(3) unsigned NOT NULL default '100', +`event_flags` int(3) unsigned NOT NULL default '0', +`event_param1` int(11) signed NOT NULL default '0', +`event_param2` int(11) signed NOT NULL default '0', +`event_param3` int(11) signed NOT NULL default '0', +`event_param4` int(11) signed NOT NULL default '0', + +`action1_type` tinyint(5) unsigned NOT NULL default '0' COMMENT 'Action Type', +`action1_param1` int(11) signed NOT NULL default '0', +`action1_param2` int(11) signed NOT NULL default '0', +`action1_param3` int(11) signed NOT NULL default '0', + +`action2_type` tinyint(5) unsigned NOT NULL default '0' COMMENT 'Action Type', +`action2_param1` int(11) signed NOT NULL default '0', +`action2_param2` int(11) signed NOT NULL default '0', +`action2_param3` int(11) signed NOT NULL default '0', + +`action3_type` tinyint(5) unsigned NOT NULL default '0' COMMENT 'Action Type', +`action3_param1` int(11) signed NOT NULL default '0', +`action3_param2` int(11) signed NOT NULL default '0', +`action3_param3` int(11) signed NOT NULL default '0', + +`comment` varchar(255) NOT NULL default '' COMMENT 'Event Comment', + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='EventAI Scripts'; + +DROP TABLE IF EXISTS `eventai_texts`; +CREATE TABLE `eventai_texts` ( + +`id` int(11) unsigned NOT NULL default '0' COMMENT 'Identifier', +`text` varchar(255) character set utf8 NOT NULL default '', +`comment` varchar(255) character set utf8 NOT NULL default '' COMMENT 'Text Comment', + +PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Texts used in EventAI'; + +DROP TABLE IF EXISTS `eventai_localized_texts`; +CREATE TABLE `eventai_localized_texts` ( + +`id` int(11) unsigned NOT NULL COMMENT 'Identifier' AUTO_INCREMENT, +`locale_1` varchar(255) NOT NULL default '', +`locale_2` varchar(255) NOT NULL default '', +`locale_3` varchar(255) NOT NULL default '', +`locale_4` varchar(255) NOT NULL default '', +`locale_5` varchar(255) NOT NULL default '', +`locale_6` varchar(255) NOT NULL default '', +`locale_7` varchar(255) NOT NULL default '', +`locale_8` varchar(255) NOT NULL default '', +`comment` varchar(255) NOT NULL default '' COMMENT 'Text Comment', + +PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='EventAI Localized Text'; + +DROP TABLE IF EXISTS `eventai_summons`; +CREATE TABLE `eventai_summons` ( +`id` int(11) unsigned NOT NULL COMMENT 'Location Identifier' AUTO_INCREMENT, +`position_x` float NOT NULL default '0', +`position_y` float NOT NULL default '0', +`position_z` float NOT NULL default '0', +`orientation` float NOT NULL default '0', +`spawntimesecs` int(11) unsigned NOT NULL default '120', +`comment` varchar(255) NOT NULL default '' COMMENT 'Summon Comment', +PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='EventAI Summoning Locations'; + +DROP TABLE IF EXISTS `script_texts`; +CREATE TABLE `script_texts` ( +`id` int(11) unsigned NOT NULL auto_increment COMMENT 'Identifier', +`sound` int(11) unsigned NOT NULL default '0', +`type` int(11) unsigned NOT NULL default '0', +`language` int(11) unsigned NOT NULL default '0', +`text` varchar(255) NOT NULL default '', +`comment` varchar(255) NOT NULL default '', +PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Script Texts'; + + +DROP TABLE IF EXISTS `script_localized_texts`; +CREATE TABLE `script_localized_texts` ( +`id` int(11) unsigned NOT NULL auto_increment COMMENT 'Identifier', +`locale_1` varchar(255) NOT NULL default '', +`locale_2` varchar(255) NOT NULL default '', +`locale_3` varchar(255) NOT NULL default '', +`locale_4` varchar(255) NOT NULL default '', +`locale_5` varchar(255) NOT NULL default '', +`locale_6` varchar(255) NOT NULL default '', +`locale_7` varchar(255) NOT NULL default '', +`locale_8` varchar(255) NOT NULL default '', +`comment` varchar(255) NOT NULL default '' COMMENT 'Text Comment', +PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Localized Script Text'; + + +DROP TABLE IF EXISTS `sd2_db_version`; +CREATE TABLE `sd2_db_version` ( +`version` varchar(255) NOT NULL default '' COMMENT 'Database version string' +) ENGINE=MyISAM DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/src/bindings/scripts/system.cpp b/src/bindings/scripts/system.cpp new file mode 100644 index 00000000000..5133963daa3 --- /dev/null +++ b/src/bindings/scripts/system.cpp @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "precompiled.h" diff --git a/src/bindings/scripts/trinityscript.conf.dist b/src/bindings/scripts/trinityscript.conf.dist new file mode 100644 index 00000000000..97a59270f09 --- /dev/null +++ b/src/bindings/scripts/trinityscript.conf.dist @@ -0,0 +1,20 @@ +# ScriptDev2 Configuration file +# This file must be placed within the directory which holds mangosd.conf and realmd.conf +ConfVersion=2008100201 + +# Database connection settings for the world server. +# Default: hostname;port;username;password;database +# .;somenumber;username;password;database - use named pipes at Windows +# Named pipes: mySQL required adding "enable-named-pipe" to [mysqld] section my.ini +# .;/path/to/unix_socket;username;password;database - use Unix sockets at Unix/Linux +# Unix sockets: experimental, not tested +ScriptDev2DatabaseInfo = "127.0.0.1;3306;mangos;mangos;scriptdev2" + +# Setting for current locale to use +Locale = 0 + +# EventAI Error reporting +# 0 - Only startup (Default) +# 1 - Startup errors and Runtime event errors +# 2 - Startup errors, Runtime event errors, and Creation errors +EAIErrorLevel = 1 \ No newline at end of file diff --git a/src/framework/Dynamic/FactoryHolder.h b/src/framework/Dynamic/FactoryHolder.h new file mode 100644 index 00000000000..7041c4ecbfa --- /dev/null +++ b/src/framework/Dynamic/FactoryHolder.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_FACTORY_HOLDER +#define MANGOS_FACTORY_HOLDER + +#include "Platform/Define.h" +#include "Utilities/TypeList.h" +#include "ObjectRegistry.h" +#include "Policies/SingletonImp.h" + +/** FactoryHolder holds a factory object of a specific type + */ +template +class MANGOS_DLL_DECL FactoryHolder +{ + public: + typedef ObjectRegistry, Key > FactoryHolderRegistry; + typedef MaNGOS::Singleton FactoryHolderRepository; + + FactoryHolder(Key k) : i_key(k) {} + virtual ~FactoryHolder() {} + inline Key key() const { return i_key; } + + void RegisterSelf(void) { FactoryHolderRepository::Instance().InsertItem(this, i_key); } + void DeregisterSelf(void) { FactoryHolderRepository::Instance().RemoveItem(this, false); } + + /// Abstract Factory create method + virtual T* Create(void *data = NULL) const = 0; + private: + Key i_key; +}; + +/** Permissible is a classic way of letting the object decide + * whether how good they handle things. This is not retricted + * to factory selectors. + */ +template +class Permissible +{ + public: + virtual ~Permissible() {} + virtual int Permit(const T *) const = 0; +}; +#endif diff --git a/src/framework/Dynamic/ObjectRegistry.h b/src/framework/Dynamic/ObjectRegistry.h new file mode 100644 index 00000000000..e0d885d2b9b --- /dev/null +++ b/src/framework/Dynamic/ObjectRegistry.h @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_OBJECTREGISTRY_H +#define MANGOS_OBJECTREGISTRY_H + +#include "Platform/Define.h" +#include "Utilities/HashMap.h" +#include "Policies/Singleton.h" + +#include +#include + +/** ObjectRegistry holds all registry item of the same type + */ +template +class MANGOS_DLL_DECL ObjectRegistry +{ + public: + typedef std::map RegistryMapType; + + /// Returns a registry item + const T* GetRegistryItem(Key key) const + { + typename RegistryMapType::const_iterator iter = i_registeredObjects.find(key); + return( iter == i_registeredObjects.end() ? NULL : iter->second ); + } + + /// Inserts a registry item + bool InsertItem(T *obj, Key key, bool override = false) + { + typename RegistryMapType::iterator iter = i_registeredObjects.find(key); + if( iter != i_registeredObjects.end() ) + { + if( !override ) + return false; + delete iter->second; + i_registeredObjects.erase(iter); + } + + i_registeredObjects[key] = obj; + return true; + } + + /// Removes a registry item + void RemoveItem(Key key, bool delete_object = true) + { + typename RegistryMapType::iterator iter = i_registeredObjects.find(key); + if( iter != i_registeredObjects.end() ) + { + if( delete_object ) + delete iter->second; + i_registeredObjects.erase(iter); + } + } + + /// Returns true if registry contains an item + bool HasItem(Key key) const + { + return (i_registeredObjects.find(key) != i_registeredObjects.end()); + } + + /// Inefficiently return a vector of registered items + unsigned int GetRegisteredItems(std::vector &l) const + { + unsigned int sz = l.size(); + l.resize(sz + i_registeredObjects.size()); + for(typename RegistryMapType::const_iterator iter = i_registeredObjects.begin(); iter != i_registeredObjects.end(); ++iter) + l[sz++] = iter->first; + return i_registeredObjects.size(); + } + + /// Return the map of registered items + RegistryMapType const &GetRegisteredItems() const + { + return i_registeredObjects; + } + + private: + RegistryMapType i_registeredObjects; + friend class MaNGOS::OperatorNew >; + + // protected for friend use since it should be a singleton + ObjectRegistry() {} + ~ObjectRegistry() + { + for(typename RegistryMapType::iterator iter=i_registeredObjects.begin(); iter != i_registeredObjects.end(); ++iter) + delete iter->second; + i_registeredObjects.clear(); + } +}; +#endif diff --git a/src/framework/GameSystem/Grid.h b/src/framework/GameSystem/Grid.h new file mode 100644 index 00000000000..f4a274a51a6 --- /dev/null +++ b/src/framework/GameSystem/Grid.h @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_GRID_H +#define MANGOS_GRID_H + +/* + @class Grid + Grid is a logical segment of the game world represented inside MaNGOS. + Grid is bind at compile time to a particular type of object which + we call it the object of interested. There are many types of loader, + specially, dynamic loader, static loader, or on-demand loader. There's + a subtle difference between dynamic loader and on-demand loader but + this is implementation specific to the loader class. From the + Grid's perspective, the loader meets its API requirement is suffice. +*/ + +#include "Platform/Define.h" +#include "Policies/ThreadingModel.h" +#include "TypeContainer.h" +#include "TypeContainerVisitor.h" + +// forward declaration +template class GridLoader; + +template +< +class ACTIVE_OBJECT, +class WORLD_OBJECT_TYPES, +class GRID_OBJECT_TYPES, +class ThreadModel = MaNGOS::SingleThreaded +> +class MANGOS_DLL_DECL Grid +{ + // allows the GridLoader to access its internals + template friend class GridLoader; + public: + + /** destructor to clean up its resources. This includes unloading the + grid if it has not been unload. + */ + ~Grid() {} + + /** an object of interested enters the grid + */ + template bool AddWorldObject(SPECIFIC_OBJECT *obj, OBJECT_HANDLE hdl) + { + return i_objects.template insert(hdl, obj); + } + + /** an object of interested exits the grid + */ + template bool RemoveWorldObject(SPECIFIC_OBJECT *obj, OBJECT_HANDLE hdl) + { + return i_objects.template remove(obj, hdl); + } + + /** Accessors: Returns a specific type of object in the WORDL_OBJECT_TYPES + */ + template const SPECIFIC_OBJECT* GetWorldObject(OBJECT_HANDLE hdl, SPECIFIC_OBJECT* fake) const { return i_objects.template find(hdl); } + template SPECIFIC_OBJECT* GetWorldObject(OBJECT_HANDLE hdl, SPECIFIC_OBJECT *fake) { return i_objects.template find(hdl, fake); } + + /** Refreshes/update the grid. This required for remote grids. + */ + void RefreshGrid(void) { /* TBI */} + + /** Locks a grid. Any object enters must wait until the grid is unlock. + */ + void LockGrid(void) { /* TBI */ } + + /** Unlocks the grid. + */ + void UnlockGrid(void) { /* TBI */ } + + /** Grid visitor for grid objects + */ + template void Visit(TypeContainerVisitor > &visitor) + { + visitor.Visit(i_container); + } + + /** Grid visitor for world objects + */ + template void Visit(TypeContainerVisitor > &visitor) + { + visitor.Visit(i_objects); + } + + /** Returns the number of object within the grid. + */ + unsigned int ActiveObjectsInGrid(void) const { return i_objects.template Count(); } + + /** Accessors: Returns a specific type of object in the GRID_OBJECT_TYPES + */ + template const SPECIFIC_OBJECT* GetGridObject(OBJECT_HANDLE hdl, SPECIFIC_OBJECT *fake) const { return i_container.template find(hdl, fake); } + template SPECIFIC_OBJECT* GetGridObject(OBJECT_HANDLE hdl, SPECIFIC_OBJECT *fake) { return i_container.template find(hdl, fake); } + + /** Inserts a container type object into the grid. + */ + template bool AddGridObject(SPECIFIC_OBJECT *obj, OBJECT_HANDLE hdl) { return i_container.template insert(hdl, obj); } + + /** Removes a containter type object from the grid + */ + template bool RemoveGridObject(SPECIFIC_OBJECT *obj, OBJECT_HANDLE hdl) { return i_container.template remove(obj, hdl); } + + private: + + typedef typename ThreadModel::Lock Guard; + typedef typename ThreadModel::VolatileType VolatileType; + + TypeMapContainer i_container; + TypeMapContainer i_objects; +}; +#endif diff --git a/src/framework/GameSystem/GridLoader.h b/src/framework/GameSystem/GridLoader.h new file mode 100644 index 00000000000..07982a613f5 --- /dev/null +++ b/src/framework/GameSystem/GridLoader.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_GRIDLOADER_H +#define MANGOS_GRIDLOADER_H + +/** + @class GridLoader + The GridLoader is working in conjuction with the Grid and responsible + for loading and unloading object-types (one or more) when objects + enters a grid. Unloading is scheduled and might be canceled if + an interested object re-enters. GridLoader does not do the actuall + loading and unloading but implements as a template pattern that + delicate its loading and unloading for the actualy loader and unloader. + GridLoader manages the grid (both local and remote). + */ + +#include "Platform/Define.h" +#include "Grid.h" +#include "TypeContainerVisitor.h" + +template +< +class ACTIVE_OBJECT, +class WORLD_OBJECT_TYPES, +class GRID_OBJECT_TYPES +> +class MANGOS_DLL_DECL GridLoader +{ + public: + + /** Loads the grid + */ + template + void Load(Grid &grid, LOADER &loader) + { + grid.LockGrid(); + loader.Load(grid); + grid.UnlockGrid(); + } + + /** Stop the grid + */ + template + void Stop(Grid &grid, STOPER &stoper) + { + grid.LockGrid(); + stoper.Stop(grid); + grid.UnlockGrid(); + } + /** Unloads the grid + */ + template + void Unload(Grid &grid, UNLOADER &unloader) + { + grid.LockGrid(); + unloader.Unload(grid); + grid.UnlockGrid(); + } +}; +#endif diff --git a/src/framework/GameSystem/GridRefManager.h b/src/framework/GameSystem/GridRefManager.h new file mode 100644 index 00000000000..fb402a1c6d3 --- /dev/null +++ b/src/framework/GameSystem/GridRefManager.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _GRIDREFMANAGER +#define _GRIDREFMANAGER + +#include "Utilities/LinkedReference/RefManager.h" + +template +class GridReference; + +template +class GridRefManager : public RefManager, OBJECT> +{ + public: + typedef LinkedListHead::Iterator< GridReference > iterator; + + GridReference* getFirst() { return (GridReference*)RefManager, OBJECT>::getFirst(); } + GridReference* getLast() { return (GridReference*)RefManager, OBJECT>::getLast(); } + + iterator begin() { return iterator(getFirst()); } + iterator end() { return iterator(NULL); } + iterator rbegin() { return iterator(getLast()); } + iterator rend() { return iterator(NULL); } +}; +#endif diff --git a/src/framework/GameSystem/GridReference.h b/src/framework/GameSystem/GridReference.h new file mode 100644 index 00000000000..92d30e54ae1 --- /dev/null +++ b/src/framework/GameSystem/GridReference.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _GRIDREFERENCE_H +#define _GRIDREFERENCE_H + +#include "Utilities/LinkedReference/Reference.h" + +template +class GridRefManager; + +template +class MANGOS_DLL_SPEC GridReference : public Reference, OBJECT> +{ + protected: + void targetObjectBuildLink() + { + // called from link() + this->getTarget()->insertFirst(this); + this->getTarget()->incSize(); + } + void targetObjectDestroyLink() + { + // called from unlink() + if(this->isValid()) this->getTarget()->decSize(); + } + void sourceObjectDestroyLink() + { + // called from invalidate() + this->getTarget()->decSize(); + } + public: + GridReference() : Reference, OBJECT>() {} + ~GridReference() { this->unlink(); } + GridReference *next() { return (GridReference*)Reference, OBJECT>::next(); } +}; +#endif diff --git a/src/framework/GameSystem/NGrid.h b/src/framework/GameSystem/NGrid.h new file mode 100644 index 00000000000..941a90282e2 --- /dev/null +++ b/src/framework/GameSystem/NGrid.h @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_NGRID_H +#define MANGOS_NGRID_H + +/** NGrid is nothing more than a wrapper of the Grid with an NxN cells + */ + +#include "GameSystem/Grid.h" +#include "GameSystem/GridReference.h" +#include "Timer.h" + +class GridInfo +{ +public: + GridInfo() : i_timer(0) {} + GridInfo(time_t expiry, bool unload = true ) : i_timer(expiry), i_unloadflag(unload) {} + const TimeTracker& getTimeTracker() const { return i_timer; } + bool getUnloadFlag() const { return i_unloadflag; } + void setUnloadFlag( bool pFlag) { i_unloadflag = pFlag; } + void setTimer(const TimeTracker& pTimer) { i_timer = pTimer; } + void ResetTimeTracker(time_t interval) { i_timer.Reset(interval); } + void UpdateTimeTracker(time_t diff) { i_timer.Update(diff); } + +private: + TimeTracker i_timer; + bool i_unloadflag; +}; + +typedef enum +{ + GRID_STATE_INVALID = 0, + GRID_STATE_ACTIVE = 1, + GRID_STATE_IDLE = 2, + GRID_STATE_REMOVAL= 3, + MAX_GRID_STATE = 4 +} grid_state_t; + +template +< +unsigned int N, +class ACTIVE_OBJECT, +class WORLD_OBJECT_TYPES, +class GRID_OBJECT_TYPES, +class ThreadModel = MaNGOS::SingleThreaded +> +class MANGOS_DLL_DECL NGrid +{ + public: + + typedef Grid GridType; + NGrid(uint32 id, int32 x, int32 y, time_t expiry, bool unload = true) : + i_gridId(id), i_cellstate(GRID_STATE_INVALID), i_x(x), i_y(y), i_GridObjectDataLoaded(false) + { + i_GridInfo = GridInfo(expiry, unload); + } + + const GridType& operator()(unsigned short x, unsigned short y) const { return i_cells[x][y]; } + GridType& operator()(unsigned short x, unsigned short y) { return i_cells[x][y]; } + + inline const uint32& GetGridId(void) const { return i_gridId; } + inline void SetGridId(const uint32 id) const { i_gridId = id; } + inline grid_state_t GetGridState(void) const { return i_cellstate; } + inline void SetGridState(grid_state_t s) { i_cellstate = s; } + inline int32 getX() const { return i_x; } + inline int32 getY() const { return i_y; } + + void link(GridRefManager >* pTo) + { + i_Reference.link(pTo, this); + } + bool isGridObjectDataLoaded() const { return i_GridObjectDataLoaded; } + void setGridObjectDataLoaded(bool pLoaded) { i_GridObjectDataLoaded = pLoaded; } + + GridInfo* getGridInfoRef() { return &i_GridInfo; } + const TimeTracker& getTimeTracker() const { return i_GridInfo.getTimeTracker(); } + bool getUnloadFlag() const { return i_GridInfo.getUnloadFlag(); } + void setUnloadFlag( bool pFlag) { i_GridInfo.setUnloadFlag(pFlag); } + void ResetTimeTracker(time_t interval) { i_GridInfo.ResetTimeTracker(interval); } + void UpdateTimeTracker(time_t diff) { i_GridInfo.UpdateTimeTracker(diff); } + + template void AddWorldObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj, OBJECT_HANDLE hdl) + { + i_cells[x][y].AddWorldObject(obj, hdl); + } + + template void RemoveWorldObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj, OBJECT_HANDLE hdl) + { + i_cells[x][y].RemoveWorldObject(obj, hdl); + } + + template void Visit(TypeContainerVisitor > &visitor) + { + for(unsigned int x=0; x < N; ++x) + for(unsigned int y=0; y < N; ++y) + i_cells[x][y].Visit(visitor); + } + + template void Visit(const uint32 &x, const uint32 &y, TypeContainerVisitor > &visitor) + { + i_cells[x][y].Visit(visitor); + } + + unsigned int ActiveObjectsInGrid(void) const + { + unsigned int count=0; + for(unsigned int x=0; x < N; ++x) + for(unsigned int y=0; y < N; ++y) + count += i_cells[x][y].ActiveObjectsInGrid(); + return count; + } + + template const SPECIFIC_OBJECT* GetGridObject(const uint32 x, const uint32 y, OBJECT_HANDLE hdl) const + { + return i_cells[x][y].template GetGridObject(hdl); + } + + template SPECIFIC_OBJECT* GetGridObject(const uint32 x, const uint32 y, OBJECT_HANDLE hdl) + { + return i_cells[x][y].template GetGridObject(hdl); + } + + template bool AddGridObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj, OBJECT_HANDLE hdl) + { + return i_cells[x][y].AddGridObject(hdl, obj); + } + + template bool RemoveGridObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj, OBJECT_HANDLE hdl) + { + return i_cells[x][y].RemoveGridObject(obj, hdl); + } + + private: + + uint32 i_gridId; + GridInfo i_GridInfo; + GridReference > i_Reference; + int32 i_x; + int32 i_y; + grid_state_t i_cellstate; + GridType i_cells[N][N]; + bool i_GridObjectDataLoaded; +}; +#endif diff --git a/src/framework/GameSystem/TypeContainer.h b/src/framework/GameSystem/TypeContainer.h new file mode 100644 index 00000000000..c07d8229a99 --- /dev/null +++ b/src/framework/GameSystem/TypeContainer.h @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_TYPECONTAINER_H +#define MANGOS_TYPECONTAINER_H + +/* + * Here, you'll find a series of containers that allow you to hold multiple + * types of object at the same time. + */ + +#include +#include +#include "Platform/Define.h" +#include "Utilities/TypeList.h" +#include "GameSystem/GridRefManager.h" + +/* + * @class ContainerMapList is a mulit-type container for map elements + * By itself its meaningless but collaborate along with TypeContainers, + * it become the most powerfully container in the whole system. + */ +template struct ContainerMapList +{ + //std::map _element; + GridRefManager _element; +}; + +template<> struct ContainerMapList /* nothing is in type null */ +{ +}; +template struct ContainerMapList > +{ + ContainerMapList _elements; + ContainerMapList _TailElements; +}; + +/* + * @class ContaierArrayList is a multi-type container for + * array of elements. + */ +template struct ContainerArrayList +{ + std::vector _element; +}; + +// termination condition +template<> struct ContainerArrayList {}; +// recursion +template struct ContainerArrayList > +{ + ContainerArrayList _elements; + ContainerArrayList _TailElements; +}; + +/* + * @class ContainerList is a simple list of different types of elements + * + */ +template struct ContainerList +{ + OBJECT _element; +}; + +/* TypeNull is underfined */ +template<> struct ContainerList {}; +template struct ContainerList > +{ + ContainerList _elements; + ContainerMapList _TailElements; +}; + +#include "TypeContainerFunctions.h" + +/* + * @class TypeMapContainer contains a fixed number of types and is + * determined at compile time. This is probably the most complicated + * class and do its simplest thing, that is, holds objects + * of different types. + */ + +template +class MANGOS_DLL_DECL TypeMapContainer +{ + public: + template size_t Count() const { return MaNGOS::Count(i_elements, (SPECIFIC_TYPE*)NULL); } + + template SPECIFIC_TYPE* find(OBJECT_HANDLE hdl, SPECIFIC_TYPE *fake) { return MaNGOS::Find(i_elements, hdl,fake); } + + /// find a specific type of object in the container + template const SPECIFIC_TYPE* find(OBJECT_HANDLE hdl, SPECIFIC_TYPE *fake) const { return MaNGOS::Find(i_elements, hdl,fake); } + + /// inserts a specific object into the container + template bool insert(OBJECT_HANDLE hdl, SPECIFIC_TYPE *obj) + { + SPECIFIC_TYPE* t = MaNGOS::Insert(i_elements, obj, hdl); + return (t != NULL); + } + + /// Removes the object from the container, and returns the removed object + template bool remove(SPECIFIC_TYPE* obj, OBJECT_HANDLE hdl) + { + SPECIFIC_TYPE* t = MaNGOS::Remove(i_elements, obj, hdl); + return (t != NULL); + } + + ContainerMapList & GetElements(void) { return i_elements; } + const ContainerMapList & GetElements(void) const { return i_elements;} + + private: + ContainerMapList i_elements; +}; +#endif diff --git a/src/framework/GameSystem/TypeContainerFunctions.h b/src/framework/GameSystem/TypeContainerFunctions.h new file mode 100644 index 00000000000..81a6a5f876b --- /dev/null +++ b/src/framework/GameSystem/TypeContainerFunctions.h @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TYPECONTAINER_FUNCTIONS_H +#define TYPECONTAINER_FUNCTIONS_H + +/* + * Here you'll find a list of helper functions to make + * the TypeContainer usefull. Without it, its hard + * to access or mutate the container. + */ + +#include "Platform/Define.h" +#include "Utilities/TypeList.h" +#include + +namespace MaNGOS +{ + /* ContainerMapList Helpers */ + // count functions + template size_t Count(const ContainerMapList &elements, SPECIFIC_TYPE* /*fake*/) + { + return elements._element.getSize(); + }; + + template size_t Count(const ContainerMapList &/*elements*/, SPECIFIC_TYPE* /*fake*/) + { + return 0; + } + + template size_t Count(const ContainerMapList &/*elements*/, SPECIFIC_TYPE* /*fake*/) + { + return 0; + } + + template size_t Count(const ContainerMapList >&elements, SPECIFIC_TYPE* fake) + { + return Count(elements._elements,fake); + } + + template size_t Count(const ContainerMapList >&elements, SPECIFIC_TYPE* fake) + { + return Count(elements._TailElements, fake); + } + + // non-const find functions + template SPECIFIC_TYPE* Find(ContainerMapList &/*elements*/, OBJECT_HANDLE /*hdl*/, SPECIFIC_TYPE* /*fake*/) + { + //typename std::map::iterator iter = elements._element.find(hdl); + //return (iter == elements._element.end() ? NULL : iter->second); + return NULL; + }; + + template SPECIFIC_TYPE* Find(ContainerMapList &/*elements*/, OBJECT_HANDLE /*hdl*/, SPECIFIC_TYPE* /*fake*/) + { + return NULL; // terminate recursion + } + + template SPECIFIC_TYPE* Find(ContainerMapList &/*elements*/, OBJECT_HANDLE /*hdl*/, SPECIFIC_TYPE* /*fake*/) + { + return NULL; // this is a missed + } + + template SPECIFIC_TYPE* Find(ContainerMapList >&/*elements*/, OBJECT_HANDLE /*hdl*/, SPECIFIC_TYPE* /*fake*/) + { + //SPECIFIC_TYPE* t = Find(elements._elements, hdl,fake); + //return (t != NULL ? t :Find(elements._TailElements, hdl,fake)); + return NULL; + } + + // const find functions + template const SPECIFIC_TYPE* Find(const ContainerMapList &/*elements*/, OBJECT_HANDLE /*hdl*/, SPECIFIC_TYPE* /*fake*/) + { + //typename SPECIFIC_TYPE::iterator iter = elements._element.find(hdl); + //return (iter == elements._element.end() ? NULL : iter->second); + return NULL; + }; + + template const SPECIFIC_TYPE* Find(const ContainerMapList &/*elements*/, OBJECT_HANDLE /*hdl*/, SPECIFIC_TYPE* /*fake*/) + { + return NULL; + } + + template const SPECIFIC_TYPE* Find(const ContainerMapList &/*elements*/, OBJECT_HANDLE /*hdl*/, SPECIFIC_TYPE* /*fake*/) + { + return NULL; + } + + template SPECIFIC_TYPE* Find(const ContainerMapList >&elements, OBJECT_HANDLE hdl, SPECIFIC_TYPE* fake) + { + SPECIFIC_TYPE* t = Find(elements._elements, hdl,fake); + if( t) + return t; + + return Find(elements._TailElement, hdl,fake); + } + + // non-const insert functions + template SPECIFIC_TYPE* Insert(ContainerMapList &elements, SPECIFIC_TYPE *obj, OBJECT_HANDLE /*hdl*/) + { + //elements._element[hdl] = obj; + obj->GetGridRef().link(&elements._element, obj); + return obj; + }; + + template SPECIFIC_TYPE* Insert(ContainerMapList &/*elements*/, SPECIFIC_TYPE * /*obj*/, OBJECT_HANDLE /*hdl*/) + { + return NULL; + } + + // this is a missed + template SPECIFIC_TYPE* Insert(ContainerMapList &/*elements*/, SPECIFIC_TYPE * /*obj*/, OBJECT_HANDLE /*hdl*/) + { + return NULL; // a missed + } + + // Recursion + template SPECIFIC_TYPE* Insert(ContainerMapList >&elements, SPECIFIC_TYPE *obj, OBJECT_HANDLE hdl) + { + SPECIFIC_TYPE* t= Insert(elements._elements, obj, hdl); + return (t != NULL ? t : Insert(elements._TailElements, obj, hdl)); + } + + // non-const remove method + template SPECIFIC_TYPE* Remove(ContainerMapList & /*elements*/, SPECIFIC_TYPE *obj, OBJECT_HANDLE /*hdl*/) + { + /*typename std::map::iterator iter = elements._element.find(hdl); + if( iter != elements._element.end() ) + { + SPECIFIC_TYPE* t = iter->second; + elements._element.erase(iter); + return t; + }*/ + obj->GetGridRef().unlink(); + return obj; + } + + template SPECIFIC_TYPE* Remove(ContainerMapList &/*elements*/, SPECIFIC_TYPE * /*obj*/, OBJECT_HANDLE /*hdl*/) + { + return NULL; + } + + // this is a missed + template SPECIFIC_TYPE* Remove(ContainerMapList &/*elements*/, SPECIFIC_TYPE * /*obj*/, OBJECT_HANDLE /*hdl*/) + { + return NULL; // a missed + } + + template SPECIFIC_TYPE* Remove(ContainerMapList > &elements, SPECIFIC_TYPE *obj, OBJECT_HANDLE hdl) + { + // The head element is bad + SPECIFIC_TYPE* t = Remove(elements._elements, obj, hdl); + return ( t != NULL ? t : Remove(elements._TailElements, obj, hdl) ); + } + +} +#endif diff --git a/src/framework/GameSystem/TypeContainerFunctionsPtr.h b/src/framework/GameSystem/TypeContainerFunctionsPtr.h new file mode 100644 index 00000000000..37ede0f6411 --- /dev/null +++ b/src/framework/GameSystem/TypeContainerFunctionsPtr.h @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TYPECONTAINER_FUNCTIONS_PTR_H +#define TYPECONTAINER_FUNCTIONS_PTR_H + +/* + * Here you'll find a list of helper functions to make + * the TypeContainer usefull. Without it, its hard + * to access or mutate the container. + */ + +#include "Platform/Define.h" +#include "Utilities/TypeList.h" +#include + +namespace MaNGOS +{ + /* ContainerMapList Helpers */ + // count functions + // template size_t Count(const ContainerMapList &elements, CountedPtr* /*fake*/) + // { + // return elements._element.size(); + // }; + // + // template size_t Count(const ContainerMapList &elements, CountedPtr* /*fake*/) + // { + // return 0; + // } + // + // template size_t Count(const ContainerMapList &elements, CountedPtr* /*fake*/) + // { + // return 0; + // } + // + // template size_t Count(const ContainerMapList >&elements, SPECIFIC_TYPE* fake) + // { + // return Count(elements._elements,fake); + // } + // + // template size_t Count(const ContainerMapList >&elements, SPECIFIC_TYPE* fake) + // { + // return Count(elements._TailElements, fake); + // } + + // non-const find functions + template CountedPtr& Find(ContainerMapList &elements, OBJECT_HANDLE hdl, CountedPtr* /*fake*/) + { + typename std::map >::iterator iter = elements._element.find(hdl); + return (iter == elements._element.end() ? NullPtr((SPECIFIC_TYPE*)NULL) : iter->second); + }; + + template CountedPtr& Find(ContainerMapList &elements, OBJECT_HANDLE hdl, CountedPtr* /*fake*/) + { + return NullPtr((SPECIFIC_TYPE*)NULL);// terminate recursion + } + + template CountedPtr& Find(ContainerMapList &elements, OBJECT_HANDLE hdl, CountedPtr* /*fake*/) + { + return NullPtr((SPECIFIC_TYPE*)NULL);// this is a missed + } + + template CountedPtr& Find(ContainerMapList >&elements, OBJECT_HANDLE hdl, CountedPtr* fake) + { + CountedPtr &t = Find(elements._elements, hdl,fake); + return (!t ? Find(elements._TailElements, hdl,fake) : t); + } + + // const find functions + template const CountedPtr& Find(const ContainerMapList &elements, OBJECT_HANDLE hdl, CountedPtr* /*fake*/) + { + typename CountedPtr::iterator iter = elements._element.find(hdl); + return (iter == elements._element.end() ? NullPtr((SPECIFIC_TYPE*)NULL) : iter->second); + }; + + template const CountedPtr& Find(const ContainerMapList &elements, OBJECT_HANDLE hdl, CountedPtr* /*fake*/) + { + return NullPtr((SPECIFIC_TYPE*)NULL); + } + + template const CountedPtr& Find(const ContainerMapList &elements, OBJECT_HANDLE hdl, CountedPtr* /*fake*/) + { + return NullPtr((SPECIFIC_TYPE*)NULL); + } + + template CountedPtr& Find(const ContainerMapList >&elements, OBJECT_HANDLE hdl, CountedPtr* fake) + { + CountedPtr &t = Find(elements._elements, hdl,fake); + if(!t) + t = Find(elements._TailElement, hdl,fake); + + return t; + } + + // non-const insert functions + template CountedPtr& Insert(ContainerMapList &elements, CountedPtr &obj, OBJECT_HANDLE hdl) + { + elements._element[hdl] = obj; + return obj; + }; + + template CountedPtr& Insert(ContainerMapList &elements, CountedPtr &obj, OBJECT_HANDLE hdl) + { + return NullPtr((SPECIFIC_TYPE*)NULL); + } + + // this is a missed + template CountedPtr& Insert(ContainerMapList &elements, CountedPtr &obj, OBJECT_HANDLE hdl) + { + return NullPtr((SPECIFIC_TYPE*)NULL);// a missed + } + + // Recursion + template CountedPtr& Insert(ContainerMapList >&elements, CountedPtr &obj, OBJECT_HANDLE hdl) + { + CountedPtr &t= Insert(elements._elements, obj, hdl); + return (!t ? Insert(elements._TailElements, obj, hdl) : t); + } + + // non-const remove method + template bool Remove(ContainerMapList &elements, CountedPtr &obj, OBJECT_HANDLE hdl) + { + typename std::map >::iterator iter = elements._element.find(hdl); + if( iter != elements._element.end() ) + { + elements._element.erase(iter); + return true; + } + + return false; // found... terminate the search + } + + template bool Remove(ContainerMapList &elements, CountedPtr &obj, OBJECT_HANDLE hdl) + { + return false; + } + + // this is a missed + template bool Remove(ContainerMapList &elements, CountedPtr &obj, OBJECT_HANDLE hdl) + { + return false; + } + + template bool Remove(ContainerMapList > &elements, CountedPtr &obj, OBJECT_HANDLE hdl) + { + // The head element is bad + bool t = Remove(elements._elements, obj, hdl); + return ( !t ? Remove(elements._TailElements, obj, hdl) : t ); + } + +} +#endif diff --git a/src/framework/GameSystem/TypeContainerVisitor.h b/src/framework/GameSystem/TypeContainerVisitor.h new file mode 100644 index 00000000000..8920b6d14d9 --- /dev/null +++ b/src/framework/GameSystem/TypeContainerVisitor.h @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_TYPECONTAINERVISITOR_H +#define MANGOS_TYPECONTAINERVISITOR_H + +/* + * @class TypeContainerVisitor is implemented as a visitor pattern. It is + * a visitor to the TypeContainerList or TypeContainerMapList. The visitor has + * to overload its types as a visit method is called. + */ + +#include "Platform/Define.h" +#include "TypeContainer.h" + +// forward declaration +template class TypeContainerVisitor; + +// visitor helper +template void VisitorHelper(VISITOR &v, TYPE_CONTAINER &c) +{ + v.Visit(c); +}; + +// terminate condition for container list +template void VisitorHelper(VISITOR &v, ContainerList &c) +{ +} + +template void VisitorHelper(VISITOR &v, ContainerList &c) +{ + v.Visit(c._element); +} + +// recursion for container list +template void VisitorHelper(VISITOR &v, ContainerList > &c) +{ + VisitorHelper(v, c._elements); + VisitorHelper(v, c._TailElements); +} + +// terminate condition container map list +template void VisitorHelper(VISITOR &/*v*/, ContainerMapList &/*c*/) +{ +} + +template void VisitorHelper(VISITOR &v, ContainerMapList &c) +{ + v.Visit(c._element); +} + +// recursion container map list +template void VisitorHelper(VISITOR &v, ContainerMapList > &c) +{ + VisitorHelper(v, c._elements); + VisitorHelper(v, c._TailElements); +} + +// array list +template void VisitorHelper(VISITOR &v, ContainerArrayList &c) +{ + v.Visit(c._element); +} + +template void VisitorHelper(VISITOR &/*v*/, ContainerArrayList &/*c*/) +{ +} + +// recursion +template void VisitorHelper(VISITOR &v, ContainerArrayList > &c) +{ + VisitorHelper(v, c._elements); + VisitorHelper(v, c._TailElements); +} + +// for TypeMapContainer +template void VisitorHelper(VISITOR &v, TypeMapContainer &c) +{ + VisitorHelper(v, c.GetElements()); +} + +template +class MANGOS_DLL_DECL TypeContainerVisitor +{ + public: + TypeContainerVisitor(VISITOR &v) : i_visitor(v) {} + + void Visit(TYPE_CONTAINER &c) + { + VisitorHelper(i_visitor, c); + } + + void Visit(const TYPE_CONTAINER &c) const + { + VisitorHelper(i_visitor, c); + } + + private: + VISITOR &i_visitor; +}; +#endif diff --git a/src/framework/Makefile.am b/src/framework/Makefile.am new file mode 100644 index 00000000000..aab4f653c41 --- /dev/null +++ b/src/framework/Makefile.am @@ -0,0 +1,64 @@ +# Copyright (C) 2005-2008 MaNGOS +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## Process this file with automake to produce Makefile.in + +## Sub-directories to parse + +## CPP flags for includes, defines, etc. +AM_CPPFLAGS = -I$(srcdir) + +## Build MaNGOS framework library as convenience library. +# libMaNGOSScript shared library will later be reused by world server daemon. +noinst_LIBRARIES = libmangosframework.a +libmangosframework_a_SOURCES = \ + Policies/ObjectLifeTime.cpp \ + Utilities/EventProcessor.cpp + +## Additional files to include when running 'make dist' +# Source and header files for the Framework. +EXTRA_DIST = \ + Dynamic/FactoryHolder.h \ + Dynamic/ObjectRegistry.h \ + GameSystem/Grid.h \ + GameSystem/GridLoader.h \ + GameSystem/GridRefManager.h \ + GameSystem/GridReference.h \ + GameSystem/NGrid.h \ + GameSystem/TypeContainer.h \ + GameSystem/TypeContainerFunctions.h \ + GameSystem/TypeContainerFunctionsPtr.h \ + GameSystem/TypeContainerVisitor.h \ + Network/SocketDefines.h \ + Platform/CompilerDefs.h \ + Platform/Define.h \ + Policies/CreationPolicy.h \ + Policies/ObjectLifeTime.h \ + Policies/Singleton.h \ + Policies/SingletonImp.h \ + Policies/ThreadingModel.h \ + Utilities/CountedReference/Reference.h \ + Utilities/CountedReference/ReferenceHolder.h \ + Utilities/CountedReference/ReferenceImpl.h \ + Utilities/LinkedReference/RefManager.h \ + Utilities/LinkedReference/Reference.h \ + Utilities/ByteConverter.h \ + Utilities/Callback.h \ + Utilities/EventProcessor.h \ + Utilities/HashMap.h \ + Utilities/LinkedList.h \ + Utilities/TypeList.h + diff --git a/src/framework/Network/SocketDefines.h b/src/framework/Network/SocketDefines.h new file mode 100644 index 00000000000..5b03758815b --- /dev/null +++ b/src/framework/Network/SocketDefines.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_SOCKETDEFINES_H +#define MANGOS_SOCKETDEFINES_H + +#ifdef WIN32 + +/* Windows socket definitions + */ +#define FD_SETSIZE 1024 +#include +#include + +typedef SOCKET SocketHandle; +typedef fd_set SelectSet; + +#else + +/* The unix socket definitions + */ +#include +#include +#ifdef __APPLE_CC__ +#include +#endif + +typedef int SocketHandle; +typedef fd_set SelectSet; +#endif +#endif diff --git a/src/framework/Platform/CompilerDefs.h b/src/framework/Platform/CompilerDefs.h new file mode 100644 index 00000000000..c0f659d55c4 --- /dev/null +++ b/src/framework/Platform/CompilerDefs.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_COMPILERDEFS_H +#define MANGOS_COMPILERDEFS_H + +#define PLATFORM_WINDOWS 0 +#define PLATFORM_UNIX 1 +#define PLATFORM_APPLE 2 +#define PLATFORM_INTEL 3 + +// must be first (win 64 also define WIN32) +#if defined( _WIN64 ) +# define PLATFORM PLATFORM_WINDOWS +#elif defined( __WIN32__ ) || defined( WIN32 ) || defined( _WIN32 ) +# define PLATFORM PLATFORM_WINDOWS +#elif defined( __APPLE_CC__ ) +# define PLATFORM PLATFORM_APPLE +#elif defined( __INTEL_COMPILER ) +# define PLATFORM PLATFORM_INTEL +#else +# define PLATFORM PLATFORM_UNIX +#endif + +#define COMPILER_MICROSOFT 0 +#define COMPILER_GNU 1 +#define COMPILER_BORLAND 2 +#define COMPILER_INTEL 3 + +#ifdef _MSC_VER +# define COMPILER COMPILER_MICROSOFT +#elif defined( __BORLANDC__ ) +# define COMPILER COMPILER_BORLAND +#elif defined( __INTEL_COMPILER ) +# define COMPILER COMPILER_INTEL +#elif defined( __GNUC__ ) +# define COMPILER COMPILER_GNU +#else +# pragma error "FATAL ERROR: Unknown compiler." +#endif + +#if COMPILER == COMPILER_MICROSOFT +# pragma warning( disable : 4267 ) // conversion from 'size_t' to 'int', possible loss of data +# pragma warning( disable : 4786 ) // identifier was truncated to '255' characters in the debug information +#endif +#endif diff --git a/src/framework/Platform/Define.h b/src/framework/Platform/Define.h new file mode 100644 index 00000000000..268cc4aab1b --- /dev/null +++ b/src/framework/Platform/Define.h @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_DEFINE_H +#define MANGOS_DEFINE_H + +#include "Platform/CompilerDefs.h" +#include + +/* Endian detection code from sha2.c: +------------------------------------------------------------------------- +Copyright (c) 2001, Dr Brian Gladman , Worcester, UK. +All rights reserved. + +TERMS + +Redistribution and use in source and binary forms, with or without +modification, are permitted subject to the following conditions: + +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +3. The copyright holder's name must not be used to endorse or promote +any products derived from this software without his specific prior +written permission. + +This software is provided 'as is' with no express or implied warranties +of correctness or fitness for purpose. +------------------------------------------------------------------------- +*/ + +/* 1. PLATFORM SPECIFIC INCLUDES */ + +#if defined(__GNU_LIBRARY__) +# include +# include +#elif defined(__CRYPTLIB__) +# if defined( INC_ALL ) +# include "crypt.h" +# elif defined( INC_CHILD ) +# include "../crypt.h" +# else +# include "crypt.h" +# endif +# if defined(DATA_LITTLEENDIAN) +# define PLATFORM_BYTE_ORDER SHA_LITTLE_ENDIAN +# else +# define PLATFORM_BYTE_ORDER SHA_BIG_ENDIAN +# endif +#elif defined(_MSC_VER) +# include +#elif !defined(WIN32) +# include +# if !defined (_ENDIAN_H) +# include +# else +# include _ENDIAN_H +# endif +#endif + +/* 2. BYTE ORDER IN 32-BIT WORDS + +To obtain the highest speed on processors with 32-bit words, this code +needs to determine the order in which bytes are packed into such words. +The following block of code is an attempt to capture the most obvious +ways in which various environemnts specify their endian definitions. +It may well fail, in which case the definitions will need to be set by +editing at the points marked **** EDIT HERE IF NECESSARY **** below. +*/ + +#define MANGOS_LITTLEENDIAN 0 +#define MANGOS_BIGENDIAN 1 + +#if !defined(MANGOS_ENDIAN) +# if defined(LITTLE_ENDIAN) || defined(BIG_ENDIAN) +# if defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN) +# if defined(BYTE_ORDER) +# if (BYTE_ORDER == LITTLE_ENDIAN) +# define MANGOS_ENDIAN MANGOS_LITTLEENDIAN +# elif (BYTE_ORDER == BIG_ENDIAN) +# define MANGOS_ENDIAN MANGOS_BIGENDIAN +# endif +# endif +# elif defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN) +# define MANGOS_ENDIAN MANGOS_LITTLEENDIAN +# elif !defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN) +# define MANGOS_ENDIAN MANGOS_BIGENDIAN +# endif +# elif defined(_LITTLE_ENDIAN) || defined(_BIG_ENDIAN) +# if defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN) +# if defined(_BYTE_ORDER) +# if (_BYTE_ORDER == _LITTLE_ENDIAN) +# define MANGOS_ENDIAN MANGOS_LITTLEENDIAN +# elif (_BYTE_ORDER == _BIG_ENDIAN) +# define MANGOS_ENDIAN MANGOS_BIGENDIAN +# endif +# endif +# elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) +# define MANGOS_ENDIAN MANGOS_LITTLE_ENDIAN +# elif !defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN) +# define MANGOS_ENDIAN MANGOS_BIGENDIAN +# endif +# elif 0 /* **** EDIT HERE IF NECESSARY **** */ +# define MANGOS_ENDIAN MANGOS_LITTLEENDIAN +# elif 0 /* **** EDIT HERE IF NECESSARY **** */ +# define MANGOS_ENDIAN MANGOS_BIGENDIAN +# elif (('1234' >> 24) == '1') +# define MANGOS_ENDIAN MANGOS_LITTLEENDIAN +# elif (('4321' >> 24) == '1') +# define MANGOS_ENDIAN MANGOS_BIGENDIAN +# else +# define MANGOS_ENDIAN MANGOS_LITTLEENDIAN +# endif +#endif + +/* End of Endian detection code from sha2.c: */ + +#if PLATFORM == PLATFORM_WINDOWS +#define MANGOS_EXPORT __declspec(dllexport) +#define MANGOS_LIBRARY_HANDLE HMODULE +#define MANGOS_LOAD_LIBRARY(a) LoadLibrary(a) +#define MANGOS_CLOSE_LIBRARY FreeLibrary +#define MANGOS_GET_PROC_ADDR GetProcAddress +#define MANGOS_IMPORT __cdecl +#define MANGOS_SCRIPT_EXT ".dll" +#define MANGOS_SCRIPT_NAME "TrinityScript" +#else +#define MANGOS_LIBRARY_HANDLE void* +#define MANGOS_EXPORT export +#define MANGOS_LOAD_LIBRARY(a) dlopen(a,RTLD_NOW) +#define MANGOS_CLOSE_LIBRARY dlclose +#define MANGOS_GET_PROC_ADDR dlsym + +#if defined(__APPLE_CC__) && defined(BIG_ENDIAN) +#define MANGOS_IMPORT __attribute__ ((longcall)) +#else +#define MANGOS_IMPORT __attribute__ ((cdecl)) +#endif + +#define MANGOS_SCRIPT_EXT ".so" +#define MANGOS_SCRIPT_NAME "libtrinityscript" +#endif + +#ifdef WIN32 +#ifdef MANGOS_WIN32_DLL_IMPORT + +#define MANGOS_DLL_DECL __declspec(dllimport) +#else +#ifdef MANGOS_WIND_DLL_EXPORT +#define MANGOS_DLL_DECL __declspec(dllexport) +#else +#define MANGOS_DLL_DECL +#endif +#endif + +#else +#define MANGOS_DLL_DECL +#endif + +#ifndef DEBUG +#define MANGOS_INLINE inline +#else +#ifndef MANGOS_DEBUG +#define MANGOS_DEBUG +#endif +#define MANGOS_INLINE +#endif + +#if COMPILER == COMPILER_MICROSOFT +typedef __int64 int64; +typedef __int32 int32; +typedef __int16 int16; +typedef __int8 int8; +typedef unsigned __int64 uint64; +typedef unsigned __int32 uint32; +typedef unsigned __int16 uint16; +typedef unsigned __int8 uint8; +#else +typedef __int64_t int64; +typedef __int32_t int32; +typedef __int16_t int16; +typedef __int8_t int8; +typedef __uint64_t uint64; +typedef __uint32_t uint32; +typedef __uint16_t uint16; +typedef __uint8_t uint8; +typedef uint16 WORD; +typedef uint32 DWORD; +#endif +typedef uint64 OBJECT_HANDLE; + +#if PLATFORM == PLATFORM_WINDOWS +# define MANGOS_DLL_SPEC __declspec(dllexport) +# ifndef DECLSPEC_NORETURN +# define DECLSPEC_NORETURN __declspec(noreturn) +# endif +#else +# define MANGOS_DLL_SPEC +# define DECLSPEC_NORETURN +#endif + +#if COMPILER == COMPILER_GNU +# define ATTR_NORETURN __attribute__((noreturn)) +# define ATTR_PRINTF(F,V) __attribute__ ((format (printf, F, V))) +#else +# define ATTR_NORETURN +# define ATTR_PRINTF(F,V) +#endif + +#endif diff --git a/src/framework/Policies/CreationPolicy.h b/src/framework/Policies/CreationPolicy.h new file mode 100644 index 00000000000..20419982965 --- /dev/null +++ b/src/framework/Policies/CreationPolicy.h @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_CREATIONPOLICY_H +#define MANGOS_CREATIONPOLICY_H + +#include +#include "Platform/Define.h" + +namespace MaNGOS +{ + /** + * OperatorNew policy creates an object on the heap using new. + */ + template + class MANGOS_DLL_DECL OperatorNew + { + public: + static T* Create(void) { return (new T); } + static void Destroy(T *obj) { delete obj; } + }; + + /** + * LocalStaticCreation policy creates an object on the stack + * the first time call Create. + */ + template + class MANGOS_DLL_DECL LocalStaticCreation + { + union MaxAlign + { + char t_[sizeof(T)]; + short int shortInt_; + int int_; + long int longInt_; + float float_; + double double_; + long double longDouble_; + struct Test; + int Test::* pMember_; + int (Test::*pMemberFn_)(int); + }; + public: + static T* Create(void) + { + static MaxAlign si_localStatic; + return new(&si_localStatic) T; + } + + static void Destroy(T *obj) { obj->~T(); } + }; + + /** + * CreateUsingMalloc by pass the memory manger. + */ + template + class MANGOS_DLL_DECL CreateUsingMalloc + { + public: + static T* Create() + { + void* p = ::malloc(sizeof(T)); + if (!p) return 0; + return new(p) T; + } + + static void Destroy(T* p) + { + p->~T(); + ::free(p); + } + }; + + /** + * CreateOnCallBack creates the object base on the call back. + */ + template + class MANGOS_DLL_DECL CreateOnCallBack + { + public: + static T* Create() + { + return CALL_BACK::createCallBack(); + } + + static void Destroy(T *p) + { + CALL_BACK::destroyCallBack(p); + } + }; +} +#endif diff --git a/src/framework/Policies/ObjectLifeTime.cpp b/src/framework/Policies/ObjectLifeTime.cpp new file mode 100644 index 00000000000..af40edc1274 --- /dev/null +++ b/src/framework/Policies/ObjectLifeTime.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include "ObjectLifeTime.h" + +namespace MaNGOS +{ + extern "C" void external_wrapper(void *p) + { + std::atexit( (void (*)())p ); + } + + void MANGOS_DLL_SPEC at_exit( void (*func)() ) + { + external_wrapper((void*)func); + } +} diff --git a/src/framework/Policies/ObjectLifeTime.h b/src/framework/Policies/ObjectLifeTime.h new file mode 100644 index 00000000000..c47daaca339 --- /dev/null +++ b/src/framework/Policies/ObjectLifeTime.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_OBJECTLIFETIME_H +#define MANGOS_OBJECTLIFETIME_H + +#include +#include "Platform/Define.h" + +typedef void (* Destroyer)(void); + +namespace MaNGOS +{ + void MANGOS_DLL_SPEC at_exit( void (*func)() ); + + template + class MANGOS_DLL_DECL ObjectLifeTime + { + public: + inline static void ScheduleCall(void (*destroyer)() ) + { + at_exit( destroyer ); + } + + DECLSPEC_NORETURN static void OnDeadReference(void) ATTR_NORETURN; + + }; + + template + inline void ObjectLifeTime::OnDeadReference(void)// We don't handle Dead Reference for now + { + throw std::runtime_error("Dead Reference"); + } +} +#endif diff --git a/src/framework/Policies/Singleton.h b/src/framework/Policies/Singleton.h new file mode 100644 index 00000000000..b70c5486dff --- /dev/null +++ b/src/framework/Policies/Singleton.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_SINGLETON_H +#define MANGOS_SINGLETON_H + +/** + * @brief class Singleton + */ + +#include "CreationPolicy.h" +#include "ThreadingModel.h" +#include "ObjectLifeTime.h" + +namespace MaNGOS +{ + template + < + typename T, + class ThreadingModel = MaNGOS::SingleThreaded, + class CreatePolicy = MaNGOS::OperatorNew, + class LifeTimePolicy = MaNGOS::ObjectLifeTime + > + class MANGOS_DLL_DECL Singleton + { + public: + static T& Instance(); + + protected: + Singleton() {}; + + private: + + // Prohibited actions...this does not prevent hijacking. + Singleton(const Singleton &); + Singleton& operator=(const Singleton &); + + // Singleton Helpers + static void DestroySingleton(); + + // data structure + typedef typename ThreadingModel::Lock Guard; + static T *si_instance; + static bool si_destroyed; + }; +} +#endif diff --git a/src/framework/Policies/SingletonImp.h b/src/framework/Policies/SingletonImp.h new file mode 100644 index 00000000000..ce0a4403472 --- /dev/null +++ b/src/framework/Policies/SingletonImp.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_SINGLETONIMPL_H +#define MANGOS_SINGLETONIMPL_H + +#include "Singleton.h" + +// avoid the using namespace here cuz +// its a .h file afterall + +template +< +typename T, +class ThreadingModel, +class CreatePolicy, +class LifeTimePolicy +> +T& +MaNGOS::Singleton::Instance() +{ + if( !si_instance ) + { + // double-checked Locking pattern + Guard(); + if( !si_instance ) + { + if( si_destroyed ) + { + si_destroyed = false; + LifeTimePolicy::OnDeadReference(); + } + si_instance = CreatePolicy::Create(); + LifeTimePolicy::ScheduleCall(&DestroySingleton); + } + } + + return *si_instance; +} + +template +< +typename T, +class ThreadingModel, +class CreatePolicy, +class LifeTimePolicy +> +void +MaNGOS::Singleton::DestroySingleton() +{ + CreatePolicy::Destroy(si_instance); + si_instance = NULL; + si_destroyed = true; +} + +#define INSTANTIATE_SINGLETON_1(TYPE) \ + template class MANGOS_DLL_DECL MaNGOS::Singleton, MaNGOS::OperatorNew, MaNGOS::ObjectLifeTime >; \ + template<> TYPE* MaNGOS::Singleton, MaNGOS::OperatorNew, MaNGOS::ObjectLifeTime >::si_instance = 0; \ + template<> bool MaNGOS::Singleton, MaNGOS::OperatorNew, MaNGOS::ObjectLifeTime >::si_destroyed = false + +#define INSTANTIATE_SINGLETON_2(TYPE, THREADINGMODEL) \ + template class MANGOS_DLL_DECL MaNGOS::Singleton, MaNGOS::ObjectLifeTime >; \ + template<> TYPE* MaNGOS::Singleton, MaNGOS::ObjectLifeTime >::si_instance = 0; \ + template<> bool MaNGOS::Singleton, MaNGOS::ObjectLifeTime >::si_destroyed = false + +#define INSTANTIATE_SINGLETON_3(TYPE, THREADINGMODEL, CREATIONPOLICY ) \ + template class MANGOS_DLL_DECL MaNGOS::Singleton >; \ + template<> TYPE* MaNGOS::Singleton >::si_instance = 0; \ + template<> bool MaNGOS::Singleton >::si_destroyed = false + +#define INSTANTIATE_SINGLETON_4(TYPE, THREADINGMODEL, CREATIONPOLICY, OBJECTLIFETIME) \ + template class MANGOS_DLL_DECL MaNGOS::Singleton; \ + template<> TYPE* MaNGOS::Singleton::si_instance = 0; \ + template<> bool MaNGOS::Singleton::si_destroyed = false +#endif diff --git a/src/framework/Policies/ThreadingModel.h b/src/framework/Policies/ThreadingModel.h new file mode 100644 index 00000000000..8175b3f82af --- /dev/null +++ b/src/framework/Policies/ThreadingModel.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_THREADINGMODEL_H +#define MANGOS_THREADINGMODEL_H + +/** + * @class ThreadingModel + * + */ + +#include "Platform/Define.h" + +namespace MaNGOS +{ + inline void Guard(void *) {} + + template class MANGOS_DLL_DECL GeneralLock + { + public: + GeneralLock(MUTEX &m) : i_mutex(m) + { + i_mutex.acquire(); + } + + ~GeneralLock() + { + i_mutex.release(); + } + private: + GeneralLock(const GeneralLock &); + GeneralLock& operator=(const GeneralLock &); + MUTEX &i_mutex; + }; + + template + class MANGOS_DLL_DECL SingleThreaded + { + public: + + struct Lock // empty object + { + Lock() {} + Lock(const T &) {} + Lock(const SingleThreaded &) // for single threaded we ignore this + { + } + }; + + typedef T VolatileType; + }; + + // object level lockable + template + class MANGOS_DLL_DECL ObjectLevelLockable + { + public: + ObjectLevelLockable() : i_mtx() {} + + friend class Lock; + + class Lock + { + public: + Lock(ObjectLevelLockable &host) : i_lock(host.i_mtx) + { + } + + private: + GeneralLock i_lock; + }; + + typedef volatile T VolatileType; + + private: + // prevent the compiler creating a copy construct + ObjectLevelLockable(const ObjectLevelLockable &); + ObjectLevelLockable& operator=(const ObjectLevelLockable &); + + MUTEX i_mtx; + }; + + template + class MANGOS_DLL_DECL ClassLevelLockable + { + public: + class Lock; + friend class Lock; + typedef volatile T VolatileType; + + ClassLevelLockable() {} + + class Lock + { + public: + Lock(T& /*host*/) { ClassLevelLockable::si_mtx.acquire(); } + Lock(ClassLevelLockable &) { ClassLevelLockable::si_mtx.acquire(); } + Lock() { ClassLevelLockable::si_mtx.acquire(); } + ~Lock() { ClassLevelLockable::si_mtx.release(); } + }; + + private: + static MUTEX si_mtx; + }; + +} + +template MUTEX MaNGOS::ClassLevelLockable::si_mtx; + +#define INSTANTIATE_CLASS_MUTEX(CTYPE,MUTEX) \ + template class MANGOS_DLL_DECL MaNGOS::ClassLevelLockable +#endif diff --git a/src/framework/Utilities/ByteConverter.h b/src/framework/Utilities/ByteConverter.h new file mode 100644 index 00000000000..fade287ed0a --- /dev/null +++ b/src/framework/Utilities/ByteConverter.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_BYTECONVERTER_H +#define MANGOS_BYTECONVERTER_H + +/** ByteConverter reverse your byte order. This is use + for cross platform where they have different endians. + */ + +#include +#include + +namespace ByteConverter +{ + template + inline void convert(char *val) + { + std::swap(*val, *(val + T - 1)); + convert(val + 1); + } + + template<> inline void convert<0>(char *) {} + template<> inline void convert<1>(char *) {} // ignore central byte + + template inline void apply(T *val) + { + convert((char *)(val)); + } +} + +#if MANGOS_ENDIAN == MANGOS_BIGENDIAN +template inline void EndianConvert(T& val) { ByteConverter::apply(&val); } +#else +template inline void EndianConvert(T&) { } +#endif + +template inline void EndianConvert(T*) { } +inline void EndianConvert(uint8&) { } +inline void EndianConvert( int8&) { } + +#endif diff --git a/src/framework/Utilities/Callback.h b/src/framework/Utilities/Callback.h new file mode 100644 index 00000000000..d794821a892 --- /dev/null +++ b/src/framework/Utilities/Callback.h @@ -0,0 +1,382 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_CALLBACK_H +#define MANGOS_CALLBACK_H + +/// ------------ BASE CLASSES ------------ + +namespace MaNGOS +{ + template < class Class, typename ParamType1 = void, typename ParamType2 = void, typename ParamType3 = void, typename ParamType4 = void > + class _Callback + { + protected: + typedef void (Class::*Method)(ParamType1, ParamType2, ParamType3, ParamType4); + Class *m_object; + Method m_method; + ParamType1 m_param1; + ParamType2 m_param2; + ParamType3 m_param3; + ParamType4 m_param4; + void _Execute() { (m_object->*m_method)(m_param1, m_param2, m_param3, m_param4); } + public: + _Callback(Class *object, Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3, ParamType4 param4) + : m_object(object), m_method(method), m_param1(param1), m_param2(param2), m_param3(param3), m_param4(param4) {} + _Callback(_Callback < Class, ParamType1, ParamType2, ParamType3, ParamType4> const& cb) + : m_object(cb.object), m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2), m_param3(cb.m_param3), m_param4(cb.m_param4) {} + }; + + template < class Class, typename ParamType1, typename ParamType2, typename ParamType3 > + class _Callback < Class, ParamType1, ParamType2, ParamType3 > + { + protected: + typedef void (Class::*Method)(ParamType1, ParamType2, ParamType3); + Class *m_object; + Method m_method; + ParamType1 m_param1; + ParamType2 m_param2; + ParamType3 m_param3; + void _Execute() { (m_object->*m_method)(m_param1, m_param2, m_param3); } + public: + _Callback(Class *object, Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3) + : m_object(object), m_method(method), m_param1(param1), m_param2(param2) {} + _Callback(_Callback < Class, ParamType1, ParamType2, ParamType3 > const& cb) + : m_object(cb.object), m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2), m_param3(cb.m_param3) {} + }; + + template < class Class, typename ParamType1, typename ParamType2 > + class _Callback < Class, ParamType1, ParamType2 > + { + protected: + typedef void (Class::*Method)(ParamType1, ParamType2); + Class *m_object; + Method m_method; + ParamType1 m_param1; + ParamType2 m_param2; + void _Execute() { (m_object->*m_method)(m_param1, m_param2); } + public: + _Callback(Class *object, Method method, ParamType1 param1, ParamType2 param2) + : m_object(object), m_method(method), m_param1(param1), m_param2(param2) {} + _Callback(_Callback < Class, ParamType1, ParamType2 > const& cb) + : m_object(cb.m_object), m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2) {} + }; + + template < class Class, typename ParamType1 > + class _Callback < Class, ParamType1 > + { + protected: + typedef void (Class::*Method)(ParamType1); + Class *m_object; + Method m_method; + ParamType1 m_param1; + void _Execute() { (m_object->*m_method)(m_param1); } + public: + _Callback(Class *object, Method method, ParamType1 param1) + : m_object(object), m_method(method), m_param1(param1) {} + _Callback(_Callback < Class, ParamType1 > const& cb) + : m_object(cb.m_object), m_method(cb.m_method), m_param1(cb.m_param1) {} + }; + + template < class Class > + class _Callback < Class > + { + protected: + typedef void (Class::*Method)(); + Class *m_object; + Method m_method; + void _Execute() { (m_object->*m_method)(); } + public: + _Callback(Class *object, Method method) + : m_object(object), m_method(method) {} + _Callback(_Callback < Class > const& cb) + : m_object(cb.m_object), m_method(cb.m_method) {} + }; + + /// ---- Statics ---- + + template < typename ParamType1 = void, typename ParamType2 = void, typename ParamType3 = void, typename ParamType4 = void > + class _SCallback + { + protected: + typedef void (*Method)(ParamType1, ParamType2, ParamType3, ParamType4); + Method m_method; + ParamType1 m_param1; + ParamType2 m_param2; + ParamType3 m_param3; + ParamType4 m_param4; + void _Execute() { (*m_method)(m_param1, m_param2, m_param3, m_param4); } + public: + _SCallback(Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3, ParamType4 param4) + : m_method(method), m_param1(param1), m_param2(param2), m_param3(param3), m_param4(param4) {} + _SCallback(_SCallback < ParamType1, ParamType2, ParamType3, ParamType4> const& cb) + : m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2), m_param3(cb.m_param3), m_param4(cb.m_param4) {} + }; + + template < typename ParamType1, typename ParamType2, typename ParamType3 > + class _SCallback < ParamType1, ParamType2, ParamType3 > + { + protected: + typedef void (*Method)(ParamType1, ParamType2, ParamType3); + Method m_method; + ParamType1 m_param1; + ParamType2 m_param2; + ParamType3 m_param3; + void _Execute() { (*m_method)(m_param1, m_param2, m_param3); } + public: + _SCallback(Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3) + : m_method(method), m_param1(param1), m_param2(param2) {} + _SCallback(_SCallback < ParamType1, ParamType2, ParamType3 > const& cb) + : m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2), m_param3(cb.m_param3) {} + }; + + template < typename ParamType1, typename ParamType2 > + class _SCallback < ParamType1, ParamType2 > + { + protected: + typedef void (*Method)(ParamType1, ParamType2); + Method m_method; + ParamType1 m_param1; + ParamType2 m_param2; + void _Execute() { (*m_method)(m_param1, m_param2); } + public: + _SCallback(Method method, ParamType1 param1, ParamType2 param2) + : m_method(method), m_param1(param1), m_param2(param2) {} + _SCallback(_SCallback < ParamType1, ParamType2 > const& cb) + : m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2) {} + }; + + template < typename ParamType1 > + class _SCallback < ParamType1 > + { + protected: + typedef void (*Method)(ParamType1); + Method m_method; + ParamType1 m_param1; + void _Execute() { (*m_method)(m_param1); } + public: + _SCallback(Method method, ParamType1 param1) + : m_method(method), m_param1(param1) {} + _SCallback(_SCallback < ParamType1 > const& cb) + : m_method(cb.m_method), m_param1(cb.m_param1) {} + }; + + template < > + class _SCallback < > + { + protected: + typedef void (*Method)(); + Method m_method; + void _Execute() { (*m_method)(); } + public: + _SCallback(Method method) + : m_method(method) {} + _SCallback(_SCallback <> const& cb) + : m_method(cb.m_method) {} + }; +} + +/// --------- GENERIC CALLBACKS ---------- + +namespace MaNGOS +{ + class ICallback + { + public: + virtual void Execute() = 0; + virtual ~ICallback() {} + }; + + template < class CB > + class _ICallback : public CB, public ICallback + { + public: + _ICallback(CB const& cb) : CB(cb) {} + void Execute() { CB::_Execute(); } + }; + + template < class Class, typename ParamType1 = void, typename ParamType2 = void, typename ParamType3 = void, typename ParamType4 = void > + class Callback : + public _ICallback< _Callback < Class, ParamType1, ParamType2, ParamType3, ParamType4 > > + { + private: + typedef _Callback < Class, ParamType1, ParamType2, ParamType3, ParamType4 > C4; + public: + Callback(Class *object, typename C4::Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3, ParamType4 param4) + : _ICallback< C4 >(C4(object, method, param1, param2, param3, param4)) {} + }; + + template < class Class, typename ParamType1, typename ParamType2, typename ParamType3 > + class Callback < Class, ParamType1, ParamType2, ParamType3 > : + public _ICallback< _Callback < Class, ParamType1, ParamType2, ParamType3 > > + { + private: + typedef _Callback < Class, ParamType1, ParamType2, ParamType3 > C3; + public: + Callback(Class *object, typename C3::Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3) + : _ICallback< C3 >(C3(object, method, param1, param2, param3)) {} + }; + + template < class Class, typename ParamType1, typename ParamType2 > + class Callback < Class, ParamType1, ParamType2 > : + public _ICallback< _Callback < Class, ParamType1, ParamType2 > > + { + private: + typedef _Callback < Class, ParamType1, ParamType2 > C2; + public: + Callback(Class *object, typename C2::Method method, ParamType1 param1, ParamType2 param2) + : _ICallback< C2 >(C2(object, method, param1, param2)) {} + }; + + template < class Class, typename ParamType1 > + class Callback < Class, ParamType1 > : + public _ICallback< _Callback < Class, ParamType1 > > + { + private: + typedef _Callback < Class, ParamType1 > C1; + public: + Callback(Class *object, typename C1::Method method, ParamType1 param1) + : _ICallback< C1 >(C1(object, method, param1)) {} + }; + + template < class Class > + class Callback < Class > : public _ICallback< _Callback < Class > > + { + private: + typedef _Callback < Class > C0; + public: + Callback(Class *object, typename C0::Method method) + : _ICallback< C0 >(C0(object, method)) {} + }; +} + +/// ---------- QUERY CALLBACKS ----------- + +class QueryResult; + +namespace MaNGOS +{ + class IQueryCallback + { + public: + virtual void Execute() = 0; + virtual ~IQueryCallback() {} + virtual void SetResult(QueryResult* result) = 0; + virtual QueryResult* GetResult() = 0; + }; + + template < class CB > + class _IQueryCallback : public CB, public IQueryCallback + { + public: + _IQueryCallback(CB const& cb) : CB(cb) {} + void Execute() { CB::_Execute(); } + void SetResult(QueryResult* result) { CB::m_param1 = result; } + QueryResult* GetResult() { return CB::m_param1; } + }; + + template < class Class, typename ParamType1 = void, typename ParamType2 = void, typename ParamType3 = void > + class QueryCallback : + public _IQueryCallback< _Callback < Class, QueryResult*, ParamType1, ParamType2, ParamType3 > > + { + private: + typedef _Callback < Class, QueryResult*, ParamType1, ParamType2, ParamType3 > QC3; + public: + QueryCallback(Class *object, typename QC3::Method method, QueryResult* result, ParamType1 param1, ParamType2 param2, ParamType3 param3) + : _IQueryCallback< QC3 >(QC3(object, method, result, param1, param2, param3)) {} + }; + + template < class Class, typename ParamType1, typename ParamType2 > + class QueryCallback < Class, ParamType1, ParamType2 > : + public _IQueryCallback< _Callback < Class, QueryResult*, ParamType1, ParamType2 > > + { + private: + typedef _Callback < Class, QueryResult*, ParamType1, ParamType2 > QC2; + public: + QueryCallback(Class *object, typename QC2::Method method, QueryResult* result, ParamType1 param1, ParamType2 param2) + : _IQueryCallback< QC2 >(QC2(object, method, result, param1, param2)) {} + }; + + template < class Class, typename ParamType1 > + class QueryCallback < Class, ParamType1 > : + public _IQueryCallback< _Callback < Class, QueryResult*, ParamType1 > > + { + private: + typedef _Callback < Class, QueryResult*, ParamType1 > QC1; + public: + QueryCallback(Class *object, typename QC1::Method method, QueryResult* result, ParamType1 param1) + : _IQueryCallback< QC1 >(QC1(object, method, result, param1)) {} + }; + + template < class Class > + class QueryCallback < Class > : public _IQueryCallback< _Callback < Class, QueryResult* > > + { + private: + typedef _Callback < Class, QueryResult* > QC0; + public: + QueryCallback(Class *object, typename QC0::Method method, QueryResult* result) + : _IQueryCallback< QC0 >(QC0(object, method, result)) {} + }; + + /// ---- Statics ---- + + template < typename ParamType1 = void, typename ParamType2 = void, typename ParamType3 = void > + class SQueryCallback : + public _IQueryCallback< _SCallback < QueryResult*, ParamType1, ParamType2, ParamType3 > > + { + private: + typedef _SCallback < QueryResult*, ParamType1, ParamType2, ParamType3 > QC3; + public: + SQueryCallback(typename QC3::Method method, QueryResult* result, ParamType1 param1, ParamType2 param2, ParamType3 param3) + : _IQueryCallback< QC3 >(QC3(method, result, param1, param2, param3)) {} + }; + + template < typename ParamType1, typename ParamType2 > + class SQueryCallback < ParamType1, ParamType2 > : + public _IQueryCallback< _SCallback < QueryResult*, ParamType1, ParamType2 > > + { + private: + typedef _SCallback < QueryResult*, ParamType1, ParamType2 > QC2; + public: + SQueryCallback(typename QC2::Method method, QueryResult* result, ParamType1 param1, ParamType2 param2) + : _IQueryCallback< QC2 >(QC2(method, result, param1, param2)) {} + }; + + template < typename ParamType1 > + class SQueryCallback < ParamType1 > : + public _IQueryCallback< _SCallback < QueryResult*, ParamType1 > > + { + private: + typedef _SCallback < QueryResult*, ParamType1 > QC1; + public: + SQueryCallback(typename QC1::Method method, QueryResult* result, ParamType1 param1) + : _IQueryCallback< QC1 >(QC1(method, result, param1)) {} + }; + + template < > + class SQueryCallback < > : public _IQueryCallback< _SCallback < QueryResult* > > + { + private: + typedef _SCallback < QueryResult* > QC0; + public: + SQueryCallback(QC0::Method method, QueryResult* result) + : _IQueryCallback< QC0 >(QC0(method, result)) {} + }; +} + +#endif diff --git a/src/framework/Utilities/CountedReference/Reference.h b/src/framework/Utilities/CountedReference/Reference.h new file mode 100644 index 00000000000..581c6399a1b --- /dev/null +++ b/src/framework/Utilities/CountedReference/Reference.h @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_REFERENCE_H +#define MANGOS_REFERENCE_H + +/** + * Referencer + * Referencer is an object that holds a reference holder that hold a reference + * counted object. When an object's reference count drop to zero, it removes + * the object. This is a non intrusive mechanism and any object at any point + * in time can be referenced. When and object is reference counted, do not + * pass the object directly to other methods but rather, pass its + * reference around. Objects can be reference counted in both single threaded + * model and multi-threaded model + */ + +#include +#include "Platform/Define.h" +#include "Policies/ThreadingModel.h" +#include "ReferenceHolder.h" + +template +< +typename T, +class THREADING_MODEL = MaNGOS::SingleThreaded +> +class MANGOS_DLL_DECL Referencer +{ + typedef typename THREADING_MODEL::Lock Lock; + typedef ReferenceHolder ReferenceeHolder; + public: + + /// Constructs a referencer. + Referencer(T *ref = NULL); + + /// Copy constructor + Referencer(const Referencer &obj) : i_holder(NULL) { *this = obj; } + + /// Destructor + ~Referencer(); + + /// Referencee accessor + T* referencee(void) { return (i_holder == NULL ? NULL : i_holder->i_referencee); } + const T* referencee(void) const { return (i_holder == NULL ? NULL : i_holder->i_referencee); } + + //T& referencee(void){ return _referencee(); } + //const T& referencee(void) const { return const_cast(this)->_referencee(); } + operator T&(void) { return _referencee(); } + operator const T&(void) const { return *const_cast(this)->_referencee(); } + + /// cast operators + T* operator*() { return (i_holder == NULL ? NULL : i_holder->i_referencee); } + T const * operator*() const { return (i_holder == NULL ? NULL : i_holder->i_referencee); } + + /// overload operators + T* operator->() { return (i_holder == NULL ? NULL : i_holder->i_referencee); } + const T * operator->() const { return (i_holder == NULL ? NULL : i_holder->i_referencee); } + + /// operator = + Referencer& operator=(const Referencer &obj); + Referencer& operator=(T *); + + /// returns true if i_referencee is null + bool isNull(void) const { return i_holder == NULL; } + + private: + + T& _referencee(void) + { + if( i_holder == NULL ) + throw std::runtime_error("Invalid access to null pointer"); + return *i_holder->i_referencee; + } + + void deReference(ReferenceeHolder *); + void addReference(ReferenceeHolder *); + + // private data + ReferenceeHolder *i_holder; +}; +#endif diff --git a/src/framework/Utilities/CountedReference/ReferenceHolder.h b/src/framework/Utilities/CountedReference/ReferenceHolder.h new file mode 100644 index 00000000000..5387b14107a --- /dev/null +++ b/src/framework/Utilities/CountedReference/ReferenceHolder.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_REFERENCEHOLDER_H +#define MANGOS_REFERENCEHOLDER_H + +/** ReferenceHolder holds the actualy referenced obejct as well the refence + count. The ReferenecHolder implements as a policy base object and + will decided by the Reference class to be consnsitent. + */ + +template +< +typename T, +class THREADING_MODEL +> +struct ReferenceHolder : public THREADING_MODEL +{ + explicit ReferenceHolder(T *ref) : i_referencee(ref), i_referenceCount(0) {} + T *i_referencee; + unsigned int i_referenceCount; + typedef typename THREADING_MODEL::Lock Lock; +}; +#endif diff --git a/src/framework/Utilities/CountedReference/ReferenceImpl.h b/src/framework/Utilities/CountedReference/ReferenceImpl.h new file mode 100644 index 00000000000..dffd05c52c4 --- /dev/null +++ b/src/framework/Utilities/CountedReference/ReferenceImpl.h @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_REFERENCEIMPL_H +#define MANGOS_REFERENCEIMPL_H + +#include "Reference.h" + +template +< +typename T, +class THREADING_MODEL +> +Referencer::Referencer(T *ref) +: i_holder(NULL) +{ + if( ref != NULL ) + { + i_holder = new ReferenceeHolder(ref); + ++i_holder->i_referenceCount; + } +} + +template +< +typename T, +class THREADING_MODEL +> +Referencer::~Referencer() +{ + if( i_holder != NULL ) + deReference(i_holder); + i_holder = NULL; +} + +template +< +typename T, +class THREADING_MODEL +> +Referencer& +Referencer::operator=(const Referencer &obj) +{ + if( i_holder != NULL ) + deReference(i_holder); + if( obj.i_holder != NULL ) + addReference(obj.i_holder); + i_holder = obj.i_holder; + return *this; +} + +template +< +typename T, +class THREADING_MODEL +> +Referencer& +Referencer::operator=(T *ref) +{ + if( i_holder != NULL ) + deReference(i_holder); + i_holder = NULL; + if( ref != NULL ) + { + i_holder = new ReferenceeHolder(ref); + ++i_holder->i_referenceCount; + } + + return *this; +} + +template +< +typename T, +class THREADING_MODEL +> +void +Referencer::deReference(ReferenceHolder *holder) +{ + assert( holder != NULL && holder->i_referenceCount > 0); + bool delete_object = false; + + { + // The guard is within the scope due to the guard + // must release earlier than expected. + Lock guard(*holder); + Guard(&guard); + + --holder->i_referenceCount; + if( holder->i_referenceCount == 0 ) + delete_object = true; + } + + if( delete_object ) + { + delete holder->i_referencee; + delete holder; + } +} + +template +< +typename T, +class THREADING_MODEL +> +void +Referencer::addReference(ReferenceHolder *holder) +{ + assert( i_holder != NULL ); + Lock guard(*holder); + Guard(&guard); + + ++holder->i_referenceCount; +} +#endif diff --git a/src/framework/Utilities/EventProcessor.cpp b/src/framework/Utilities/EventProcessor.cpp new file mode 100644 index 00000000000..55581ff7f8c --- /dev/null +++ b/src/framework/Utilities/EventProcessor.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "EventProcessor.h" + +EventProcessor::EventProcessor() +{ + m_time = 0; + m_aborting = false; +} + +EventProcessor::~EventProcessor() +{ + KillAllEvents(); +} + +void EventProcessor::Update(uint32 p_time) +{ + // update time + m_time += p_time; + + // main event loop + EventList::iterator i; + while (((i = m_events.begin()) != m_events.end()) && i->first <= m_time) + { + // get and remove event from queue + BasicEvent* Event = i->second; + m_events.erase(i); + + if (!Event->to_Abort) + { + if (Event->Execute(m_time, p_time)) + { + // completely destroy event if it is not re-added + delete Event; + } + } + else + { + Event->Abort(m_time); + delete Event; + } + } +} + +void EventProcessor::KillAllEvents() +{ + // prevent event insertions + m_aborting = true; + + // first, abort all existing events + for (EventList::iterator i = m_events.begin(); i != m_events.end(); ++i) + { + i->second->to_Abort = true; + i->second->Abort(m_time); + delete i->second; + } + + // clear event list + m_events.clear(); +} + +void EventProcessor::AddEvent(BasicEvent* Event, uint64 e_time, bool set_addtime) +{ + if (set_addtime) Event->m_addTime = m_time; + Event->m_execTime = e_time; + m_events.insert(std::pair(e_time, Event)); +} + +uint64 EventProcessor::CalculateTime(uint64 t_offset) +{ + return(m_time + t_offset); +} diff --git a/src/framework/Utilities/EventProcessor.h b/src/framework/Utilities/EventProcessor.h new file mode 100644 index 00000000000..d0a94ce08ae --- /dev/null +++ b/src/framework/Utilities/EventProcessor.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __EVENTPROCESSOR_H +#define __EVENTPROCESSOR_H + +#include "Platform/Define.h" + +#include + +// Note. All times are in milliseconds here. + +class BasicEvent +{ + public: + BasicEvent() { to_Abort = false; } + virtual ~BasicEvent() // override destructor to perform some actions on event removal + { + }; + + // this method executes when the event is triggered + // return false if event does not want to be deleted + // e_time is execution time, p_time is update interval + virtual bool Execute(uint64 /*e_time*/, uint32 /*p_time*/) { return true; } + + virtual void Abort(uint64 /*e_time*/) {} // this method executes when the event is aborted + + bool to_Abort; // set by externals when the event is aborted, aborted events don't execute + // and get Abort call when deleted + + // these can be used for time offset control + uint64 m_addTime; // time when the event was added to queue, filled by event handler + uint64 m_execTime; // planned time of next execution, filled by event handler +}; + +typedef std::multimap EventList; + +class EventProcessor +{ + public: + EventProcessor(); + ~EventProcessor(); + + void Update(uint32 p_time); + void KillAllEvents(); + void AddEvent(BasicEvent* Event, uint64 e_time, bool set_addtime = true); + uint64 CalculateTime(uint64 t_offset); + protected: + uint64 m_time; + EventList m_events; + bool m_aborting; +}; +#endif diff --git a/src/framework/Utilities/HashMap.h b/src/framework/Utilities/HashMap.h new file mode 100644 index 00000000000..2f887bd1943 --- /dev/null +++ b/src/framework/Utilities/HashMap.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_HASHMAP_H +#define MANGOS_HASHMAP_H + +#include "Platform/CompilerDefs.h" +#include "Platform/Define.h" + +#if COMPILER == COMPILER_INTEL +#include +#elif COMPILER == COMPILER_GNU && __GNUC__ >= 3 +#include +#else +#include +#endif + +#ifdef _STLPORT_VERSION +#define HM_NAMESPACE std +using std::hash_map; +#elif COMPILER == COMPILER_MICROSOFT && _MSC_VER >= 1300 +#define HM_NAMESPACE stdext +using stdext::hash_map; +#elif COMPILER == COMPILER_INTEL +#define HM_NAMESPACE std +using std::hash_map; +#elif COMPILER == COMPILER_GNU && __GNUC__ >= 3 +#define HM_NAMESPACE __gnu_cxx +using __gnu_cxx::hash_map; + +namespace __gnu_cxx +{ + template<> struct hash + { + size_t operator()(const unsigned long long &__x) const { return (size_t)__x; } + }; + template struct hash + { + size_t operator()(T * const &__x) const { return (size_t)__x; } + }; + +}; + +#else +#define HM_NAMESPACE std +using std::hash_map; +#endif +#endif diff --git a/src/framework/Utilities/LinkedList.h b/src/framework/Utilities/LinkedList.h new file mode 100644 index 00000000000..3686c12c34c --- /dev/null +++ b/src/framework/Utilities/LinkedList.h @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _LINKEDLIST +#define _LINKEDLIST + +#include "Common.h" + +//============================================ +class LinkedListHead; + +class LinkedListElement +{ + private: + friend class LinkedListHead; + + LinkedListElement* iNext; + LinkedListElement* iPrev; + public: + LinkedListElement() { iNext = NULL; iPrev = NULL; } + ~LinkedListElement() { delink(); } + + bool hasNext() const { return(iNext->iNext != NULL); } + bool hasPrev() const { return(iPrev->iPrev != NULL); } + bool isInList() const { return(iNext != NULL && iPrev != NULL); } + + LinkedListElement * next() { return hasNext() ? iNext : NULL; } + LinkedListElement const* next() const { return hasNext() ? iNext : NULL; } + LinkedListElement * prev() { return hasPrev() ? iPrev : NULL; } + LinkedListElement const* prev() const { return hasPrev() ? iPrev : NULL; } + + void delink() + { + if(isInList()) + { + iNext->iPrev = iPrev; iPrev->iNext = iNext; iNext = NULL; iPrev = NULL; + } + } + + void insertBefore(LinkedListElement* pElem) + { + pElem->iNext = this; + pElem->iPrev = iPrev; + iPrev->iNext = pElem; + iPrev = pElem; + } + + void insertAfter(LinkedListElement* pElem) + { + pElem->iPrev = this; + pElem->iNext = iNext; + iNext->iPrev = pElem; + iNext = pElem; + } +}; + +//============================================ + +class LinkedListHead +{ + private: + LinkedListElement iFirst; + LinkedListElement iLast; + uint32 iSize; + public: + LinkedListHead() + { + // create empty list + + iFirst.iNext = &iLast; + iLast.iPrev = &iFirst; + iSize = 0; + } + + bool isEmpty() const { return(!iFirst.iNext->isInList()); } + + LinkedListElement * getFirst() { return(isEmpty() ? NULL : iFirst.iNext); } + LinkedListElement const* getFirst() const { return(isEmpty() ? NULL : iFirst.iNext); } + + LinkedListElement * getLast() { return(isEmpty() ? NULL : iLast.iPrev); } + LinkedListElement const* getLast() const { return(isEmpty() ? NULL : iLast.iPrev); } + + void insertFirst(LinkedListElement* pElem) + { + iFirst.insertAfter(pElem); + } + + void insertLast(LinkedListElement* pElem) + { + iLast.insertBefore(pElem); + } + + uint32 getSize() const + { + if(!iSize) + { + uint32 result = 0; + LinkedListElement const* e = getFirst(); + while(e) + { + ++result; + e = e->next(); + } + return result; + } + else + return iSize; + } + + void incSize() { ++iSize; } + void decSize() { --iSize; } + + template + class Iterator + { + public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef _Ty value_type; + typedef ptrdiff_t difference_type; + typedef ptrdiff_t distance_type; + typedef _Ty* pointer; + typedef _Ty& reference; + + Iterator() : _Ptr(0) + { // construct with null node pointer + } + + Iterator(pointer _Pnode) : _Ptr(_Pnode) + { // construct with node pointer _Pnode + } + + reference operator*() + { // return designated value + return *_Ptr; + } + + pointer operator->() + { // return pointer to class object + return _Ptr; + } + + Iterator& operator++() + { // preincrement + _Ptr = _Ptr->next(); + return (*this); + } + + Iterator operator++(int) + { // postincrement + iterator _Tmp = *this; + ++*this; + return (_Tmp); + } + + Iterator& operator--() + { // predecrement + _Ptr = _Ptr->prev(); + return (*this); + } + + Iterator operator--(int) + { // postdecrement + iterator _Tmp = *this; + --*this; + return (_Tmp); + } + + bool operator==(Iterator const &_Right) const + { // test for iterator equality + return (_Ptr == _Right._Ptr); + } + + bool operator!=(Iterator const &_Right) const + { // test for iterator inequality + return (!(*this == _Right)); + } + + bool operator==(pointer const &_Right) const + { // test for pointer equality + return (_Ptr != _Right); + } + + bool operator!=(pointer const &_Right) const + { // test for pointer equality + return (!(*this == _Right)); + } + + pointer _Mynode() + { // return node pointer + return (_Ptr); + } + + protected: + pointer _Ptr; // pointer to node + }; + + typedef Iterator iterator; +}; + +//============================================ +#endif diff --git a/src/framework/Utilities/LinkedReference/RefManager.h b/src/framework/Utilities/LinkedReference/RefManager.h new file mode 100644 index 00000000000..4e71ec7f2ed --- /dev/null +++ b/src/framework/Utilities/LinkedReference/RefManager.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _REFMANAGER_H +#define _REFMANAGER_H +//===================================================== + +#include "Utilities/LinkedList.h" +#include "Utilities/LinkedReference/Reference.h" + +template class RefManager : public LinkedListHead +{ + public: + typedef LinkedListHead::Iterator< Reference > iterator; + RefManager() { } + virtual ~RefManager() { clearReferences(); } + + Reference* getFirst() { return ((Reference*) LinkedListHead::getFirst()); } + Reference* getLast() { return ((Reference*) LinkedListHead::getLast()); } + + iterator begin() { return iterator(getFirst()); } + iterator end() { return iterator(NULL); } + iterator rbegin() { return iterator(getLast()); } + iterator rend() { return iterator(NULL); } + + void clearReferences() + { + LinkedListElement* ref; + while((ref = getFirst()) != NULL) + { + ((Reference*) ref)->invalidate(); + ref->delink(); // the delink might be already done by invalidate(), but doing it here again does not hurt and insures an empty list + } + } +}; + +//===================================================== +#endif diff --git a/src/framework/Utilities/LinkedReference/Reference.h b/src/framework/Utilities/LinkedReference/Reference.h new file mode 100644 index 00000000000..682bfd82162 --- /dev/null +++ b/src/framework/Utilities/LinkedReference/Reference.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _REFERENCE_H +#define _REFERENCE_H + +#include "Utilities/LinkedList.h" + +//===================================================== + +template class Reference : public LinkedListElement +{ + private: + TO* iRefTo; + FROM* iRefFrom; + protected: + // Tell our refTo (target) object that we have a link + virtual void targetObjectBuildLink() = 0; + + // Tell our refTo (taget) object, that the link is cut + virtual void targetObjectDestroyLink() = 0; + + // Tell our refFrom (source) object, that the link is cut (Target destroyed) + virtual void sourceObjectDestroyLink() = 0; + public: + Reference() { iRefTo = NULL; iRefFrom = NULL; } + virtual ~Reference() {} + + // Create new link + inline void link(TO* toObj, FROM* fromObj) + { + assert(fromObj); // fromObj MUST not be NULL + if(isValid()) + unlink(); + if(toObj != NULL) + { + iRefTo = toObj; + iRefFrom = fromObj; + targetObjectBuildLink(); + } + } + + // We don't need the reference anymore. Call comes from the refFrom object + // Tell our refTo object, that the link is cut + inline void unlink() { targetObjectDestroyLink(); delink(); iRefTo = NULL; iRefFrom = NULL; } + + // Link is invalid due to destruction of referenced target object. Call comes from the refTo object + // Tell our refFrom object, that the link is cut + inline void invalidate() // the iRefFrom MUST remain!! + { + sourceObjectDestroyLink(); delink(); iRefTo = NULL; + } + + inline bool isValid() const // Only check the iRefTo + { + return iRefTo != NULL; + } + + Reference* next() { return((Reference*)LinkedListElement::next()); } + Reference* prev() { return((Reference*)LinkedListElement::prev()); } + + inline TO* operator ->() const { return iRefTo; } + inline TO* getTarget() const { return iRefTo; } + + inline FROM* getSource() const { return iRefFrom; } +}; + +//===================================================== +#endif diff --git a/src/framework/Utilities/TypeList.h b/src/framework/Utilities/TypeList.h new file mode 100644 index 00000000000..074f5eb2483 --- /dev/null +++ b/src/framework/Utilities/TypeList.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_TYPELIST_H +#define MANGOS_TYPELIST_H + +/* + @struct TypeList + TypeList is the most simple but yet the most powerfull class of all. It holds + at compile time the different type of objects in a linked list. + */ + +class TypeNull; + +template +struct TypeList +{ + typedef HEAD Head; + typedef TAIL Tail; +}; + +// enough for now.. can be expand at any point in time as needed +#define TYPELIST_1(T1) TypeList +#define TYPELIST_2(T1, T2) TypeList +#define TYPELIST_3(T1, T2, T3) TypeList +#define TYPELIST_4(T1, T2, T3, T4) TypeList +#define TYPELIST_5(T1, T2, T3, T4, T5) TypeList +#endif diff --git a/src/game/AccountMgr.cpp b/src/game/AccountMgr.cpp new file mode 100644 index 00000000000..3b14db46dba --- /dev/null +++ b/src/game/AccountMgr.cpp @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "AccountMgr.h" +#include "Database/DatabaseEnv.h" +#include "ObjectMgr.h" +#include "Player.h" +#include "Policies/SingletonImp.h" +#include "Util.h" + +#ifdef DO_POSTGRESQL +extern DatabasePostgre loginDatabase; +#else +extern DatabaseMysql loginDatabase; +#endif + +INSTANTIATE_SINGLETON_1(AccountMgr); + +AccountMgr::AccountMgr() +{} + +AccountMgr::~AccountMgr() +{} + +AccountOpResult AccountMgr::CreateAccount(std::string username, std::string password) +{ + if(utf8length(username) > MAX_ACCOUNT_STR) + return AOR_NAME_TOO_LONG; // username's too long + + normilizeString(username); + normilizeString(password); + + loginDatabase.escape_string(username); + loginDatabase.escape_string(password); + + QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE username = '%s'", username.c_str()); + if(result) + { + delete result; + return AOR_NAME_ALREDY_EXIST; // username does already exist + } + + if(!loginDatabase.PExecute("INSERT INTO account(username,sha_pass_hash,joindate) VALUES('%s',SHA1(CONCAT('%s',':','%s')),NOW())", username.c_str(), username.c_str(), password.c_str())) + return AOR_DB_INTERNAL_ERROR; // unexpected error + loginDatabase.Execute("INSERT INTO realmcharacters (realmid, acctid, numchars) SELECT realmlist.id, account.id, 0 FROM account, realmlist WHERE account.id NOT IN (SELECT acctid FROM realmcharacters)"); + + return AOR_OK; // everything's fine +} + +AccountOpResult AccountMgr::DeleteAccount(uint32 accid) +{ + QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d'", accid); + if(!result) + return AOR_NAME_NOT_EXIST; // account doesn't exist + delete result; + + result = CharacterDatabase.PQuery("SELECT guid FROM characters WHERE account='%d'",accid); + if (result) + { + do + { + Field *fields = result->Fetch(); + uint32 guidlo = fields[0].GetUInt32(); + uint64 guid = MAKE_NEW_GUID(guidlo, 0, HIGHGUID_PLAYER); + + // kick if player currently + if(Player* p = objmgr.GetPlayer(guid)) + { + WorldSession* s = p->GetSession(); + s->KickPlayer(); // mark session to remove at next session list update + s->LogoutPlayer(false); // logout player without waiting next session list update + } + + Player::DeleteFromDB(guid, accid, false); // no need to update realm characters + } while (result->NextRow()); + + delete result; + } + + // table realm specific but common for all characters of account for realm + CharacterDatabase.PExecute("DELETE FROM character_tutorial WHERE account = '%u'",accid); + + loginDatabase.BeginTransaction(); + + bool res = + loginDatabase.PExecute("DELETE FROM account WHERE id='%d'", accid) && + loginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid='%d'", accid); + + loginDatabase.CommitTransaction(); + + if(!res) + return AOR_DB_INTERNAL_ERROR; // unexpected error; + + return AOR_OK; +} + +AccountOpResult AccountMgr::ChangeUsername(uint32 accid, std::string new_uname, std::string new_passwd) +{ + QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d'", accid); + if(!result) + return AOR_NAME_NOT_EXIST; // account doesn't exist + delete result; + + if(utf8length(new_uname) > MAX_ACCOUNT_STR) + return AOR_NAME_TOO_LONG; + + if(utf8length(new_passwd) > MAX_ACCOUNT_STR) + return AOR_PASS_TOO_LONG; + + normilizeString(new_uname); + normilizeString(new_passwd); + + loginDatabase.escape_string(new_uname); + loginDatabase.escape_string(new_passwd); + if(!loginDatabase.PExecute("UPDATE account SET username='%s',sha_pass_hash=SHA1(CONCAT('%s',':','%s')) WHERE id='%d'", new_uname.c_str(), new_uname.c_str(), new_passwd.c_str(), accid)) + return AOR_DB_INTERNAL_ERROR; // unexpected error + + return AOR_OK; +} + +AccountOpResult AccountMgr::ChangePassword(uint32 accid, std::string new_passwd) +{ + QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d'", accid); + if(!result) + return AOR_NAME_NOT_EXIST; // account doesn't exist + delete result; + + if (utf8length(new_passwd) > MAX_ACCOUNT_STR) + return AOR_PASS_TOO_LONG; + + normilizeString(new_passwd); + + loginDatabase.escape_string(new_passwd); + if(!loginDatabase.PExecute("UPDATE account SET sha_pass_hash=SHA1(CONCAT(username,':','%s')) WHERE id='%d'", new_passwd.c_str(), accid)) + return AOR_DB_INTERNAL_ERROR; // unexpected error + + return AOR_OK; +} + +uint32 AccountMgr::GetId(std::string username) +{ + loginDatabase.escape_string(username); + QueryResult *result = loginDatabase.PQuery("SELECT id FROM account WHERE username = '%s'", username.c_str()); + if(!result) + return 0; + else + { + uint32 id = (*result)[0].GetUInt32(); + delete result; + return id; + } +} + +bool AccountMgr::CheckPassword(uint32 accid, std::string passwd) +{ + normilizeString(passwd); + loginDatabase.escape_string(passwd); + + QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d' AND sha_pass_hash=SHA1(CONCAT(username,':','%s'))", accid, passwd.c_str()); + if (result) + { + delete result; + return true; + } + + return false; +} + +bool AccountMgr::normilizeString(std::string& utf8str) +{ + wchar_t wstr_buf[MAX_ACCOUNT_STR+1]; + + size_t wstr_len = MAX_ACCOUNT_STR; + if(!Utf8toWStr(utf8str,wstr_buf,wstr_len)) + return false; + + std::transform( &wstr_buf[0], wstr_buf+wstr_len, &wstr_buf[0], wcharToUpperOnlyLatin ); + + return WStrToUtf8(wstr_buf,wstr_len,utf8str); +} diff --git a/src/game/AccountMgr.h b/src/game/AccountMgr.h new file mode 100644 index 00000000000..ed04773a8d3 --- /dev/null +++ b/src/game/AccountMgr.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _ACCMGR_H +#define _ACCMGR_H + +#include "Common.h" +#include "Policies/Singleton.h" +#include + +enum AccountOpResult +{ + AOR_OK, + AOR_NAME_TOO_LONG, + AOR_PASS_TOO_LONG, + AOR_NAME_ALREDY_EXIST, + AOR_NAME_NOT_EXIST, + AOR_DB_INTERNAL_ERROR +}; + +#define MAX_ACCOUNT_STR 16 + +class AccountMgr +{ + public: + AccountMgr(); + ~AccountMgr(); + + AccountOpResult CreateAccount(std::string username, std::string password); + AccountOpResult DeleteAccount(uint32 accid); + AccountOpResult ChangeUsername(uint32 accid, std::string new_uname, std::string new_passwd); + AccountOpResult ChangePassword(uint32 accid, std::string new_passwd); + bool CheckPassword(uint32 accid, std::string passwd); + + uint32 GetId(std::string username); + + static bool normilizeString(std::string& utf8str); +}; + +#define accmgr MaNGOS::Singleton::Instance() +#endif diff --git a/src/game/AddonHandler.cpp b/src/game/AddonHandler.cpp new file mode 100644 index 00000000000..a03ea0359ad --- /dev/null +++ b/src/game/AddonHandler.cpp @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "AddonHandler.h" +#include "Database/DatabaseEnv.h" +#include "Opcodes.h" +#include "Log.h" +#include "Policies/SingletonImp.h" +#include "zlib/zlib.h" + +INSTANTIATE_SINGLETON_1( AddonHandler ); + +AddonHandler::AddonHandler() +{ +} + +AddonHandler::~AddonHandler() +{ +} + +bool AddonHandler::BuildAddonPacket(WorldPacket *Source, WorldPacket *Target) +{ + ByteBuffer AddOnPacked; + uLongf AddonRealSize; + uint32 CurrentPosition; + uint32 TempValue; + + unsigned char tdata[256] = + { + 0xC3, 0x5B, 0x50, 0x84, 0xB9, 0x3E, 0x32, 0x42, 0x8C, 0xD0, 0xC7, 0x48, 0xFA, 0x0E, 0x5D, 0x54, + 0x5A, 0xA3, 0x0E, 0x14, 0xBA, 0x9E, 0x0D, 0xB9, 0x5D, 0x8B, 0xEE, 0xB6, 0x84, 0x93, 0x45, 0x75, + 0xFF, 0x31, 0xFE, 0x2F, 0x64, 0x3F, 0x3D, 0x6D, 0x07, 0xD9, 0x44, 0x9B, 0x40, 0x85, 0x59, 0x34, + 0x4E, 0x10, 0xE1, 0xE7, 0x43, 0x69, 0xEF, 0x7C, 0x16, 0xFC, 0xB4, 0xED, 0x1B, 0x95, 0x28, 0xA8, + 0x23, 0x76, 0x51, 0x31, 0x57, 0x30, 0x2B, 0x79, 0x08, 0x50, 0x10, 0x1C, 0x4A, 0x1A, 0x2C, 0xC8, + 0x8B, 0x8F, 0x05, 0x2D, 0x22, 0x3D, 0xDB, 0x5A, 0x24, 0x7A, 0x0F, 0x13, 0x50, 0x37, 0x8F, 0x5A, + 0xCC, 0x9E, 0x04, 0x44, 0x0E, 0x87, 0x01, 0xD4, 0xA3, 0x15, 0x94, 0x16, 0x34, 0xC6, 0xC2, 0xC3, + 0xFB, 0x49, 0xFE, 0xE1, 0xF9, 0xDA, 0x8C, 0x50, 0x3C, 0xBE, 0x2C, 0xBB, 0x57, 0xED, 0x46, 0xB9, + 0xAD, 0x8B, 0xC6, 0xDF, 0x0E, 0xD6, 0x0F, 0xBE, 0x80, 0xB3, 0x8B, 0x1E, 0x77, 0xCF, 0xAD, 0x22, + 0xCF, 0xB7, 0x4B, 0xCF, 0xFB, 0xF0, 0x6B, 0x11, 0x45, 0x2D, 0x7A, 0x81, 0x18, 0xF2, 0x92, 0x7E, + 0x98, 0x56, 0x5D, 0x5E, 0x69, 0x72, 0x0A, 0x0D, 0x03, 0x0A, 0x85, 0xA2, 0x85, 0x9C, 0xCB, 0xFB, + 0x56, 0x6E, 0x8F, 0x44, 0xBB, 0x8F, 0x02, 0x22, 0x68, 0x63, 0x97, 0xBC, 0x85, 0xBA, 0xA8, 0xF7, + 0xB5, 0x40, 0x68, 0x3C, 0x77, 0x86, 0x6F, 0x4B, 0xD7, 0x88, 0xCA, 0x8A, 0xD7, 0xCE, 0x36, 0xF0, + 0x45, 0x6E, 0xD5, 0x64, 0x79, 0x0F, 0x17, 0xFC, 0x64, 0xDD, 0x10, 0x6F, 0xF3, 0xF5, 0xE0, 0xA6, + 0xC3, 0xFB, 0x1B, 0x8C, 0x29, 0xEF, 0x8E, 0xE5, 0x34, 0xCB, 0xD1, 0x2A, 0xCE, 0x79, 0xC3, 0x9A, + 0x0D, 0x36, 0xEA, 0x01, 0xE0, 0xAA, 0x91, 0x20, 0x54, 0xF0, 0x72, 0xD8, 0x1E, 0xC7, 0x89, 0xD2 + }; + + // broken addon packet, can't be received from real client + if (Source->rpos() + 4 > Source->size()) + return false; + + *Source >> TempValue; //get real size of the packed structure + + // empty addon packet, nothing process, can't be received from real client + if(!TempValue) + return false; + + AddonRealSize = TempValue; //temp value because ZLIB only excepts uLongf + + CurrentPosition = Source->rpos(); //get the position of the pointer in the structure + + AddOnPacked.resize(AddonRealSize); //resize target for zlib action + + if (!uncompress(const_cast(AddOnPacked.contents()), &AddonRealSize, const_cast((*Source).contents() + CurrentPosition), (*Source).size() - CurrentPosition)!= Z_OK) + { + Target->Initialize(SMSG_ADDON_INFO); + + while(AddOnPacked.rpos() < AddOnPacked.size()) + { + std::string AddonNames; + uint8 unk6; + uint32 crc, unk7; + + // check next addon data format correctness + if(AddOnPacked.rpos()+1+4+4+1 > AddOnPacked.size()) + return false; + + AddOnPacked >> AddonNames; + + // recheck next addon data format correctness + if(AddOnPacked.rpos()+4+4+1 > AddOnPacked.size()) + return false; + + AddOnPacked >> crc >> unk7 >> unk6; + + //sLog.outDebug("ADDON: Name:%s CRC:%x Unknown1 :%x Unknown2 :%x", AddonNames.c_str(), crc, unk7, unk6); + + *Target << (uint8)2; + + uint8 unk1 = 1; + *Target << (uint8)unk1; + if (unk1) + { + uint8 unk2 = crc != 0x1c776d01LL; //If addon is Standard addon CRC + *Target << (uint8)unk2; + if (unk2) + Target->append(tdata, sizeof(tdata)); + + *Target << (uint32)0; + } + + uint8 unk3 = 0; + *Target << (uint8)unk3; + if (unk3) + { + // String, 256 + } + } + } + else + { + sLog.outError("Addon packet uncompress error :("); + return false; + } + return true; +} + +/* Code use in 1.10.2 when client not ignore ban state sended for addons. Saved for reference if client switch to use server ban state information +void AddonHandler::BuildAddonPacket(WorldPacket* Source, WorldPacket* Target, uint32 Packetoffset) +{ + ByteBuffer AddOnPacked; + uLongf AddonRealSize; + uint32 CurrentPosition; + uint32 TempValue; + + *Source >> TempValue; //get real size of the packed structure + + AddonRealSize = TempValue; //temp value becouse ZLIB only excepts uLongf + + CurrentPosition = Source->rpos(); //get the position of the pointer in the structure + + AddOnPacked.resize(AddonRealSize); //resize target for zlib action + + if (!uncompress((uint8*)AddOnPacked.contents(), &AddonRealSize, (uint8*)(*Source).contents() + CurrentPosition, (*Source).size() - CurrentPosition)!= Z_OK) + { + bool* AddonAllowed = new bool; //handle addon check and enable-ing + + uint32 Unknown1; + uint8 Unknown0; + + AddOnPacked >> Unknown0; + AddOnPacked >> Unknown1; + + Target->Initialize(SMSG_ADDON_INFO); + + uint32 i = 5; //offset for addon extraction + while(i != AddOnPacked.size()) + { + std::string AddonNames; + AddOns* Addonstr = new AddOns; + uint8 unk6; + uint64 CRCCHECK; + AddOnPacked >> AddonNames >> CRCCHECK >> unk6; + + //sLog.outDebug("ADDON: Name:%s CRC:%x Unknown:%x",AddonNames.c_str(), CRCCHECK,unk6); + + Addonstr->Name = AddonNames; + Addonstr->CRC = CRCCHECK; + + //if not allowed but unknown added to list + if (GetAddonStatus(Addonstr, AddonAllowed)) // If addon is new + { + Addonstr->Enabled = m_Addon_Default; // by default new addons are set from Config file + *AddonAllowed = m_Addon_Default; // Set addon allowed on default value + _AddAddon(Addonstr); + sLog.outDetail("Found new Addon, Name:%s CRC:%x Unknown:%x",AddonNames.c_str(), CRCCHECK, unk6); + } + + if (CRCCHECK == 0x4C1C776D01LL) //If addon is Standard addon CRC + { + //value's standard Addons + *Target << uint8(0) << uint8(2) << uint8(1) << uint8(0) << uint32(0); + } + else if (*AddonAllowed) //if addon is Custom addons + //value's enable addon + *Target << uint8(0x00) << uint8(0x01) << uint8(0x00) << uint8(0x01); + else + //value's disable addom + *Target << uint8(0x00) << uint8(0x0) << uint8(0x00) << uint8(0x0); + + i += AddonNames.size() + 10; + } + *Target << uint8(0x0); + + //delete mem allocation + delete AddonAllowed; + } + else + { + //handle uncompress error + } +} +*/ diff --git a/src/game/AddonHandler.h b/src/game/AddonHandler.h new file mode 100644 index 00000000000..2e2db5011b2 --- /dev/null +++ b/src/game/AddonHandler.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ADDONHANDLER_H +#define __ADDONHANDLER_H + +#include "Common.h" +#include "Policies/Singleton.h" +#include "WorldPacket.h" +#include "Config/ConfigEnv.h" + +class AddonHandler +{ + public: + /* Construction */ + AddonHandler(); + ~AddonHandler(); + //built addon packet + bool BuildAddonPacket(WorldPacket* Source, WorldPacket* Target); +}; +#define sAddOnHandler MaNGOS::Singleton::Instance() +#endif diff --git a/src/game/AggressorAI.cpp b/src/game/AggressorAI.cpp new file mode 100644 index 00000000000..494acbb9a51 --- /dev/null +++ b/src/game/AggressorAI.cpp @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "AggressorAI.h" +#include "Errors.h" +#include "Creature.h" +#include "Player.h" +#include "ObjectAccessor.h" +#include "VMapFactory.h" +#include "World.h" + +#include + +int +AggressorAI::Permissible(const Creature *creature) +{ + // have some hostile factions, it will be selected by IsHostileTo check at MoveInLineOfSight + if( !creature->isCivilian() && !creature->IsNeutralToAll() ) + return PERMIT_BASE_PROACTIVE; + + return PERMIT_BASE_NO; +} + +AggressorAI::AggressorAI(Creature &c) : i_creature(c), i_victimGuid(0), i_state(STATE_NORMAL), i_tracker(TIME_INTERVAL_LOOK) +{ +} + +void +AggressorAI::MoveInLineOfSight(Unit *u) +{ + if( i_creature.GetDistanceZ(u) > CREATURE_Z_ATTACK_RANGE ) + return; + if( !i_creature.getVictim() && !i_creature.hasUnitState(UNIT_STAT_STUNDED) && u->isTargetableForAttack() && + ( i_creature.IsHostileTo( u ) /*|| u->getVictim() && i_creature.IsFriendlyTo( u->getVictim() )*/ ) && + u->isInAccessablePlaceFor(&i_creature) ) + { + float attackRadius = i_creature.GetAttackDistance(u); + if(i_creature.IsWithinDistInMap(u, attackRadius) && i_creature.IsWithinLOSInMap(u) ) + { + AttackStart(u); + u->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + } + } +} + +void AggressorAI::EnterEvadeMode() +{ + if( !i_creature.isAlive() ) + { + DEBUG_LOG("Creature stopped attacking cuz his dead [guid=%u]", i_creature.GetGUIDLow()); + i_victimGuid = 0; + i_creature.CombatStop(); + i_creature.DeleteThreatList(); + return; + } + + Unit* victim = ObjectAccessor::GetUnit(i_creature, i_victimGuid ); + + if( !victim ) + { + DEBUG_LOG("Creature stopped attacking because victim is non exist [guid=%u]", i_creature.GetGUIDLow()); + } + else if( !victim->isAlive() ) + { + DEBUG_LOG("Creature stopped attacking cuz his victim is dead [guid=%u]", i_creature.GetGUIDLow()); + } + else if( victim->HasStealthAura() ) + { + DEBUG_LOG("Creature stopped attacking cuz his victim is stealth [guid=%u]", i_creature.GetGUIDLow()); + } + else if( victim->isInFlight() ) + { + DEBUG_LOG("Creature stopped attacking cuz his victim is fly away [guid=%u]", i_creature.GetGUIDLow()); + } + else + { + DEBUG_LOG("Creature stopped attacking due to target out run him [guid=%u]", i_creature.GetGUIDLow()); + //i_state = STATE_LOOK_AT_VICTIM; + //i_tracker.Reset(TIME_INTERVAL_LOOK); + } + + if(!i_creature.isCharmed()) + { + i_creature.RemoveAllAuras(); + + // Remove TargetedMovementGenerator from MotionMaster stack list, and add HomeMovementGenerator instead + if( i_creature.GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE ) + i_creature.GetMotionMaster()->MoveTargetedHome(); + } + + i_creature.DeleteThreatList(); + i_victimGuid = 0; + i_creature.CombatStop(); + i_creature.SetLootRecipient(NULL); +} + +void +AggressorAI::UpdateAI(const uint32 /*diff*/) +{ + // update i_victimGuid if i_creature.getVictim() !=0 and changed + if(!i_creature.SelectHostilTarget() || !i_creature.getVictim()) + return; + + i_victimGuid = i_creature.getVictim()->GetGUID(); + + if( i_creature.isAttackReady() ) + { + if( i_creature.IsWithinDistInMap(i_creature.getVictim(), ATTACK_DISTANCE)) + { + i_creature.AttackerStateUpdate(i_creature.getVictim()); + i_creature.resetAttackTimer(); + } + } +} + +bool +AggressorAI::IsVisible(Unit *pl) const +{ + return i_creature.GetDistance(pl) < sWorld.getConfig(CONFIG_SIGHT_MONSTER) + && pl->isVisibleForOrDetect(&i_creature,true); +} + +void +AggressorAI::AttackStart(Unit *u) +{ + if( !u ) + return; + + if(i_creature.Attack(u,true)) + { + i_creature.SetInCombatWith(u); + u->SetInCombatWith(&i_creature); + + i_creature.AddThreat(u, 0.0f); + // DEBUG_LOG("Creature %s tagged a victim to kill [guid=%u]", i_creature.GetName(), u->GetGUIDLow()); + i_victimGuid = u->GetGUID(); + + i_creature.GetMotionMaster()->MoveChase(u); + } +} diff --git a/src/game/AggressorAI.h b/src/game/AggressorAI.h new file mode 100644 index 00000000000..b90b12182b2 --- /dev/null +++ b/src/game/AggressorAI.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_AGGRESSORAI_H +#define MANGOS_AGGRESSORAI_H + +#include "CreatureAI.h" +#include "Timer.h" + +class Creature; + +class MANGOS_DLL_DECL AggressorAI : public CreatureAI +{ + enum AggressorState + { + STATE_NORMAL = 1, + STATE_LOOK_AT_VICTIM = 2 + }; + + public: + + AggressorAI(Creature &c); + + void MoveInLineOfSight(Unit *); + void AttackStart(Unit *); + void EnterEvadeMode(); + bool IsVisible(Unit *) const; + + void UpdateAI(const uint32); + static int Permissible(const Creature *); + + private: + Creature &i_creature; + uint64 i_victimGuid; + AggressorState i_state; + TimeTracker i_tracker; +}; +#endif diff --git a/src/game/AnimalRandomMovementGenerator.h b/src/game/AnimalRandomMovementGenerator.h new file mode 100644 index 00000000000..a40eb65eb07 --- /dev/null +++ b/src/game/AnimalRandomMovementGenerator.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_ANIMAL_RANDOMMOVEMENTGENERATOR_H +#define MANGOS_ANIMAL_RANDOMMOVEMENTGENERATOR_H + +/** AnimalRandomMovementGenerator follows the research on + * quantifying scale-dependant effects of animal movement + * with simple per-location models (R.H. Gardner, R.V. O'Neil, + * M.G: Turner and V.H. Dale). It is specifically used on + * animal creatures. + */ +#endif diff --git a/src/game/ArenaTeam.cpp b/src/game/ArenaTeam.cpp new file mode 100644 index 00000000000..578340a4a8d --- /dev/null +++ b/src/game/ArenaTeam.cpp @@ -0,0 +1,517 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "WorldPacket.h" +#include "ObjectMgr.h" +#include "ArenaTeam.h" + +ArenaTeam::ArenaTeam() +{ + Id = 0; + Type = 0; + Name = ""; + CaptainGuid = 0; + BackgroundColor = 0; // background + EmblemStyle = 0; // icon + EmblemColor = 0; // icon color + BorderStyle = 0; // border + BorderColor = 0; // border color + stats.games = 0; + stats.played = 0; + stats.rank = 0; + stats.rating = 1500; + stats.wins = 0; + stats.wins2 = 0; +} + +ArenaTeam::~ArenaTeam() +{ + +} + +bool ArenaTeam::create(uint64 captainGuid, uint32 type, std::string ArenaTeamName) +{ + if(!objmgr.GetPlayer(captainGuid)) // player not exist + return false; + if(objmgr.GetArenaTeamByName(ArenaTeamName)) // arena team with this name already exist + return false; + + sLog.outDebug("GUILD: creating arena team %s to leader: %u", ArenaTeamName.c_str(), GUID_LOPART(CaptainGuid)); + + CaptainGuid = captainGuid; + Name = ArenaTeamName; + Type = type; + + QueryResult *result = CharacterDatabase.Query("SELECT MAX(arenateamid) FROM arena_team"); + if( result ) + { + Id = (*result)[0].GetUInt32()+1; + delete result; + } + else Id = 1; + + // ArenaTeamName already assigned to ArenaTeam::name, use it to encode string for DB + CharacterDatabase.escape_string(ArenaTeamName); + + CharacterDatabase.BeginTransaction(); + // CharacterDatabase.PExecute("DELETE FROM arena_team WHERE arenateamid='%u'", Id); - MAX(arenateam)+1 not exist + CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid='%u'", Id); + CharacterDatabase.PExecute("INSERT INTO arena_team (arenateamid,name,captainguid,type,BackgroundColor,EmblemStyle,EmblemColor,BorderStyle,BorderColor) " + "VALUES('%u','%s','%u','%u','%u','%u','%u','%u','%u')", + Id, ArenaTeamName.c_str(), GUID_LOPART(CaptainGuid), Type, BackgroundColor,EmblemStyle,EmblemColor,BorderStyle,BorderColor); + CharacterDatabase.PExecute("INSERT INTO arena_team_stats (arenateamid, rating, games, wins, played, wins2, rank) VALUES " + "('%u', '%u', '%u', '%u', '%u', '%u', '%u')", Id,stats.rating,stats.games,stats.wins,stats.played,stats.wins2,stats.rank); + + CharacterDatabase.CommitTransaction(); + + AddMember(CaptainGuid); + return true; +} + +bool ArenaTeam::AddMember(uint64 PlayerGuid) +{ + std::string plName; + uint8 plClass; + + if(GetMembersSize() >= GetType() * 2) + { + // arena team is full (can't have more than type * 2 players!) + // return false + return false; + } + + if(!objmgr.GetPlayerNameByGUID(PlayerGuid, plName)) // player doesnt exist + return false; + // player already in arenateam of that size + if(Player::GetArenaTeamIdFromDB(PlayerGuid, GetType()) != 0) + { + sLog.outError("Arena::AddMember() : player already in this sized team"); + return false; + } + + // remove all player signs from another petitions + // this will be prevent attempt joining player to many arenateams and corrupt arena team data integrity + Player::RemovePetitionsAndSigns(PlayerGuid, GetType()); + + Player *pl = objmgr.GetPlayer(PlayerGuid); + if(pl) + { + plClass = (uint8)pl->getClass(); + } + else + { + QueryResult *result = CharacterDatabase.PQuery("SELECT class FROM characters WHERE guid='%u'", GUID_LOPART(PlayerGuid)); + if(!result) + return false; + plClass = (*result)[0].GetUInt8(); + delete result; + } + + ArenaTeamMember newmember; + newmember.name = plName; + newmember.guid = PlayerGuid; + newmember.Class = plClass; + newmember.played_season = 0; + newmember.played_week = 0; + newmember.wons_season = 0; + newmember.wons_week = 0; + members.push_back(newmember); + + CharacterDatabase.PExecute("INSERT INTO arena_team_member (arenateamid,guid) VALUES ('%u', '%u')", Id, GUID_LOPART(newmember.guid)); + + if(pl) + { + pl->SetInArenaTeam(Id, GetSlot()); + pl->SetArenaTeamIdInvited(0); + } + else + { + Player::SetUInt32ValueInDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6), Id, PlayerGuid); + } + + // hide promote/remove buttons + if(CaptainGuid != PlayerGuid) + { + if(pl) + pl->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1); + else + Player::SetUInt32ValueInDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1, PlayerGuid); + } + return true; +} + +bool ArenaTeam::LoadArenaTeamFromDB(uint32 ArenaTeamId) +{ + LoadStatsFromDB(ArenaTeamId); + LoadMembersFromDB(ArenaTeamId); + + // 0 1 2 3 4 5 6 7 8 + QueryResult *result = CharacterDatabase.PQuery("SELECT arenateamid,name,captainguid,type,BackgroundColor,EmblemStyle,EmblemColor,BorderStyle,BorderColor FROM arena_team WHERE arenateamid = '%u'", ArenaTeamId); + + if(!result) + return false; + + Field *fields = result->Fetch(); + + Id = fields[0].GetUInt32(); + Name = fields[1].GetCppString(); + CaptainGuid = MAKE_NEW_GUID(fields[2].GetUInt32(), 0, HIGHGUID_PLAYER); + Type = fields[3].GetUInt32(); + BackgroundColor = fields[4].GetUInt32(); + EmblemStyle = fields[5].GetUInt32(); + EmblemColor = fields[6].GetUInt32(); + BorderStyle = fields[7].GetUInt32(); + BorderColor = fields[8].GetUInt32(); + + delete result; + + return true; +} + +void ArenaTeam::LoadStatsFromDB(uint32 ArenaTeamId) +{ + // 0 1 2 3 4 5 + QueryResult *result = CharacterDatabase.PQuery("SELECT rating,games,wins,played,wins2,rank FROM arena_team_stats WHERE arenateamid = '%u'", ArenaTeamId); + + if(!result) + return; + + Field *fields = result->Fetch(); + + stats.rating = fields[0].GetUInt32(); + stats.games = fields[1].GetUInt32(); + stats.wins = fields[2].GetUInt32(); + stats.played = fields[3].GetUInt32(); + stats.wins2 = fields[4].GetUInt32(); + stats.rank = fields[5].GetUInt32(); + + delete result; +} + +void ArenaTeam::LoadMembersFromDB(uint32 ArenaTeamId) +{ + Field *fields; + + QueryResult *result = CharacterDatabase.PQuery("SELECT guid,played_week,wons_week,played_season,wons_season FROM arena_team_member WHERE arenateamid = '%u'", ArenaTeamId); + if(!result) + return; + + do + { + fields = result->Fetch(); + ArenaTeamMember newmember; + newmember.guid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); + LoadPlayerStats(&newmember); + newmember.played_week = fields[1].GetUInt32(); + newmember.wons_week = fields[2].GetUInt32(); + newmember.played_season = fields[3].GetUInt32(); + newmember.wons_season = fields[4].GetUInt32(); + members.push_back(newmember); + }while( result->NextRow() ); + delete result; +} + +void ArenaTeam::LoadPlayerStats(ArenaTeamMember *member) +{ + Field *fields; + + QueryResult *result = CharacterDatabase.PQuery("SELECT name,class FROM characters WHERE guid = '%u'", GUID_LOPART(member->guid)); + if(!result) + return; + fields = result->Fetch(); + member->name = fields[0].GetCppString(); + member->Class = fields[1].GetUInt8(); + + delete result; +} + +void ArenaTeam::SetCaptain(uint64 guid) +{ + // disable remove/promote buttons + Player *oldcaptain = objmgr.GetPlayer(GetCaptain()); + if(oldcaptain) + oldcaptain->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1); + else + Player::SetUInt32ValueInDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1, GetCaptain()); + + // set new captain + CaptainGuid = guid; + + // update database + CharacterDatabase.PExecute("UPDATE arena_team SET captainguid = '%u' WHERE arenateamid = '%u'", GUID_LOPART(guid), Id); + + // enable remove/promote buttons + Player *newcaptain = objmgr.GetPlayer(guid); + if(newcaptain) + newcaptain->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 0); + else + Player::SetUInt32ValueInDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 0, guid); +} + +void ArenaTeam::DelMember(uint64 guid) +{ + MemberList::iterator itr; + for (itr = members.begin(); itr != members.end(); itr++) + { + if (itr->guid == guid) + { + members.erase(itr); + break; + } + } + + Player *player = objmgr.GetPlayer(guid); + if(player) + { + player->SetInArenaTeam(0, GetSlot()); + player->GetSession()->SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, GetName(), "", 0); + } + else + { + Player::SetUInt32ValueInDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6), 0, guid); + } + + CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE guid = '%u'", GUID_LOPART(guid)); +} + +void ArenaTeam::Disband(WorldSession *session) +{ + // event + WorldPacket data; + session->BuildArenaTeamEventPacket(&data, ERR_ARENA_TEAM_DISBANDED_S, 2, session->GetPlayerName(), GetName(), ""); + BroadcastPacket(&data); + + uint32 count = members.size(); + uint64 *memberGuids = new uint64[count]; + + MemberList::iterator itr; + uint32 i=0; + for(itr = members.begin(); itr != members.end(); itr++) + { + memberGuids[i] = itr->guid; + ++i; + } + + for(uint32 j = 0; j < count; j++) + DelMember(memberGuids[j]); + delete[] memberGuids; + + CharacterDatabase.BeginTransaction(); + CharacterDatabase.PExecute("DELETE FROM arena_team WHERE arenateamid = '%u'", Id); + CharacterDatabase.PExecute("DELETE FROM arena_team_stats WHERE arenateamid = '%u'", Id); + CharacterDatabase.CommitTransaction(); + objmgr.RemoveArenaTeam(this); +} + +void ArenaTeam::Roster(WorldSession *session) +{ + Player *pl = NULL; + + WorldPacket data(SMSG_ARENA_TEAM_ROSTER, 100); + data << uint32(GetId()); // arena team id + data << uint32(GetMembersSize()); // members count + data << uint32(GetType()); // arena team type? + + for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) + { + pl = objmgr.GetPlayer(itr->guid); + if(pl) + { + data << uint64(pl->GetGUID()); // guid + data << uint8(1); // online flag + data << pl->GetName(); // member name + data << uint32(itr->guid == GetCaptain() ? 0 : 1);// unknown + data << uint8(pl->getLevel()); // unknown, probably level + data << uint8(pl->getClass()); // class + data << uint32(itr->played_week); // played this week + data << uint32(itr->wons_week); // wins this week + data << uint32(itr->played_season); // played this season + data << uint32(itr->wons_season); // wins this season + data << uint32(0); // personal rating? + } + else + { + data << uint64(itr->guid); // guid + data << uint8(0); // online flag + data << itr->name; // member name + data << uint32(itr->guid == GetCaptain() ? 0 : 1);// unknown + data << uint8(0); // unknown, level? + data << uint8(itr->Class); // class + data << uint32(itr->played_week); // played this week + data << uint32(itr->wons_week); // wins this week + data << uint32(itr->played_season); // played this season + data << uint32(itr->wons_season); // wins this season + data << uint32(0); // personal rating? + } + } + session->SendPacket(&data); + sLog.outDebug("WORLD: Sent SMSG_ARENA_TEAM_ROSTER"); +} + +void ArenaTeam::Query(WorldSession *session) +{ + WorldPacket data(SMSG_ARENA_TEAM_QUERY_RESPONSE, 4*7+GetName().size()+1); + data << uint32(GetId()); // team id + data << GetName(); // team name + data << uint32(GetType()); // arena team type (2=2x2, 3=3x3 or 5=5x5) + data << uint32(BackgroundColor); // background color + data << uint32(EmblemStyle); // emblem style + data << uint32(EmblemColor); // emblem color + data << uint32(BorderStyle); // border style + data << uint32(BorderColor); // border color + session->SendPacket(&data); + sLog.outDebug("WORLD: Sent SMSG_ARENA_TEAM_QUERY_RESPONSE"); +} + +void ArenaTeam::Stats(WorldSession *session) +{ + WorldPacket data(SMSG_ARENA_TEAM_STATS, 4*7); + data << uint32(GetId()); // arena team id + data << uint32(stats.rating); // rating + data << uint32(stats.games); // games + data << uint32(stats.wins); // wins + data << uint32(stats.played); // played + data << uint32(stats.wins2); // wins(again o_O) + data << uint32(stats.rank); // rank + session->SendPacket(&data); +} + +void ArenaTeam::InspectStats(WorldSession *session, uint64 guid) +{ + WorldPacket data(MSG_INSPECT_ARENA_TEAMS, 8+1+4*6); + data << uint64(guid); // player guid + data << uint8(GetSlot()); // slot (0...2) + data << uint32(GetId()); // arena team id + data << uint32(stats.rating); // rating + data << uint32(stats.games); // games + data << uint32(stats.wins); // wins + data << uint32(stats.played); // played (count of all games, that played...) + data << uint32(0); // 2.3.3 personal rating? + session->SendPacket(&data); +} + +void ArenaTeam::SetEmblem(uint32 backgroundColor, uint32 emblemStyle, uint32 emblemColor, uint32 borderStyle, uint32 borderColor) +{ + BackgroundColor = backgroundColor; + EmblemStyle = emblemStyle; + EmblemColor = emblemColor; + BorderStyle = borderStyle; + BorderColor = borderColor; + + CharacterDatabase.PExecute("UPDATE arena_team SET BackgroundColor='%u', EmblemStyle='%u', EmblemColor='%u', BorderStyle='%u', BorderColor='%u' WHERE arenateamid='%u'", BackgroundColor, EmblemStyle, EmblemColor, BorderStyle, BorderColor, Id); +} + +void ArenaTeam::SetStats(uint32 stat_type, uint32 value) +{ + switch(stat_type) + { + case STAT_TYPE_RATING: + stats.rating = value; + CharacterDatabase.PExecute("UPDATE arena_team_stats SET rating = '%u' WHERE arenateamid = '%u'", value, GetId()); + break; + case STAT_TYPE_GAMES: + stats.games = value; + CharacterDatabase.PExecute("UPDATE arena_team_stats SET games = '%u' WHERE arenateamid = '%u'", value, GetId()); + break; + case STAT_TYPE_WINS: + stats.wins = value; + CharacterDatabase.PExecute("UPDATE arena_team_stats SET wins = '%u' WHERE arenateamid = '%u'", value, GetId()); + break; + case STAT_TYPE_PLAYED: + stats.played = value; + CharacterDatabase.PExecute("UPDATE arena_team_stats SET played = '%u' WHERE arenateamid = '%u'", value, GetId()); + break; + case STAT_TYPE_WINS2: + stats.wins2 = value; + CharacterDatabase.PExecute("UPDATE arena_team_stats SET wins2 = '%u' WHERE arenateamid = '%u'", value, GetId()); + break; + case STAT_TYPE_RANK: + stats.rank = value; + CharacterDatabase.PExecute("UPDATE arena_team_stats SET rank = '%u' WHERE arenateamid = '%u'", value, GetId()); + break; + default: + sLog.outDebug("unknown stat type in ArenaTeam::SetStats() %u", stat_type); + break; + } +} + +uint8 ArenaTeam::GetSlot() const +{ + uint8 slot = GetSlotByType(GetType()); + if(slot >= MAX_ARENA_SLOT) + { + sLog.outError("Unknown arena team type %u for arena team %u", uint32(GetType()), GetId()); + return 0; // better return existed slot to prevent untelated data curruption + } + + return slot; +} + +void ArenaTeam::BroadcastPacket(WorldPacket *packet) +{ + for (MemberList::iterator itr = members.begin(); itr != members.end(); itr++) + { + Player *player = objmgr.GetPlayer(itr->guid); + if(player) + player->GetSession()->SendPacket(packet); + } +} + +uint8 ArenaTeam::GetSlotByType( uint32 type ) +{ + switch(type) + { + case ARENA_TEAM_2v2: return 0; + case ARENA_TEAM_3v3: return 1; + case ARENA_TEAM_5v5: return 2; + default: + break; + } + return 0xFF; +} + +bool ArenaTeam::HaveMember( uint64 guid ) const +{ + for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr) + if(itr->guid==guid) + return true; + + return false; +} + +/* +arenateam fields (id from 2.3.3 client): +1414 - arena team id 2v2 +1415 - 0=captain, 1=member +1416 - played this season +1417 - played this week +1418 - unk +1419 - unk +1420 - arena team id 3v3 +1421 - 0=captain, 1=member +1422 - played this season +1423 - played this week +1424 - unk +1425 - unk +1426 - arena team id 5v5 +1427 - 0=captain, 1=member +1428 - played this season +1429 - played this week +1430 - unk +1431 - unk +*/ diff --git a/src/game/ArenaTeam.h b/src/game/ArenaTeam.h new file mode 100644 index 00000000000..9b4ef67ead1 --- /dev/null +++ b/src/game/ArenaTeam.h @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOSSERVER_ARENATEAM_H +#define MANGOSSERVER_ARENATEAM_H + +enum ArenaTeamCommandTypes +{ + ERR_ARENA_TEAM_CREATE_S = 0x00, + ERR_ARENA_TEAM_INVITE_SS = 0x01, + //ERR_ARENA_TEAM_QUIT_S = 0x02, + ERR_ARENA_TEAM_QUIT_S = 0x03, + ERR_ARENA_TEAM_FOUNDER_S = 0x0C // need check, probably wrong... +}; + +enum ArenaTeamCommandErrors +{ + //ARENA_TEAM_PLAYER_NO_MORE_IN_ARENA_TEAM = 0x00, + ERR_ARENA_TEAM_INTERNAL = 0x01, + ERR_ALREADY_IN_ARENA_TEAM = 0x02, + ERR_ALREADY_IN_ARENA_TEAM_S = 0x03, + ERR_INVITED_TO_ARENA_TEAM = 0x04, + ERR_ALREADY_INVITED_TO_ARENA_TEAM_S = 0x05, + ERR_ARENA_TEAM_NAME_INVALID = 0x06, + ERR_ARENA_TEAM_NAME_EXISTS_S = 0x07, + ERR_ARENA_TEAM_LEADER_LEAVE_S = 0x08, + ERR_ARENA_TEAM_PERMISSIONS = 0x08, + ERR_ARENA_TEAM_PLAYER_NOT_IN_TEAM = 0x09, + ERR_ARENA_TEAM_PLAYER_NOT_IN_TEAM_SS = 0x0A, + ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S = 0x0B, + ERR_ARENA_TEAM_NOT_ALLIED = 0x0C +}; + +enum ArenaTeamEvents +{ + ERR_ARENA_TEAM_JOIN_SS = 3, // player name + arena team name + ERR_ARENA_TEAM_LEAVE_SS = 4, // player name + arena team name + ERR_ARENA_TEAM_REMOVE_SSS = 5, // player name + arena team name + captain name + ERR_ARENA_TEAM_LEADER_IS_SS = 6, // player name + arena team name + ERR_ARENA_TEAM_LEADER_CHANGED_SSS = 7, // old captain + new captain + arena team name + ERR_ARENA_TEAM_DISBANDED_S = 8 // captain name + arena team name +}; + +/* +need info how to send these ones: +ERR_ARENA_TEAM_YOU_JOIN_S - client show it automatically when accept invite +ERR_ARENA_TEAM_TARGET_TOO_LOW_S +ERR_ARENA_TEAM_TOO_MANY_MEMBERS_S +ERR_ARENA_TEAM_LEVEL_TOO_LOW_I +*/ + +enum ArenaTeamStatTypes +{ + STAT_TYPE_RATING = 0, + STAT_TYPE_GAMES = 1, + STAT_TYPE_WINS = 2, + STAT_TYPE_PLAYED = 3, + STAT_TYPE_WINS2 = 4, + STAT_TYPE_RANK = 5 +}; + +enum ArenaTeamTypes +{ + ARENA_TEAM_2v2 = 2, + ARENA_TEAM_3v3 = 3, + ARENA_TEAM_5v5 = 5 +}; + +struct ArenaTeamMember +{ + uint64 guid; + std::string name; + //uint32 unk2; + //uint8 unk1; + uint8 Class; + uint32 played_week; + uint32 wons_week; + uint32 played_season; + uint32 wons_season; +}; + +struct ArenaTeamStats +{ + uint32 rating; + uint32 games; + uint32 wins; + uint32 played; + uint32 wins2; + uint32 rank; +}; + +#define MAX_ARENA_SLOT 3 // 0..2 slots + +class ArenaTeam +{ + public: + ArenaTeam(); + ~ArenaTeam(); + + bool create(uint64 CaptainGuid, uint32 type, std::string ArenaTeamName); + void Disband(WorldSession *session); + + typedef std::list MemberList; + + uint32 GetId() const { return Id; } + uint32 GetType() const { return Type; } + uint8 GetSlot() const; + static uint8 GetSlotByType(uint32 type); + const uint64& GetCaptain() const { return CaptainGuid; } + std::string GetName() const { return Name; } + ArenaTeamStats GetStats() const { return stats; } + void SetStats(uint32 stat_type, uint32 value); + uint32 GetRating() const { return stats.rating; } + + uint32 GetEmblemStyle() const { return EmblemStyle; } + uint32 GetEmblemColor() const { return EmblemColor; } + uint32 GetBorderStyle() const { return BorderStyle; } + uint32 GetBorderColor() const { return BorderColor; } + uint32 GetBackgroundColor() const { return BackgroundColor; } + + void SetCaptain(uint64 guid); + bool AddMember(uint64 PlayerGuid); + void DelMember(uint64 guid); + + void SetEmblem(uint32 backgroundColor, uint32 emblemStyle, uint32 emblemColor, uint32 borderStyle, uint32 borderColor); + + uint32 GetMembersSize() const { return members.size(); } + MemberList::iterator membersbegin(){ return members.begin(); } + MemberList::iterator membersEnd(){ return members.end(); } + bool HaveMember(uint64 guid) const; + + bool LoadArenaTeamFromDB(uint32 ArenaTeamId); + void LoadMembersFromDB(uint32 ArenaTeamId); + void LoadStatsFromDB(uint32 ArenaTeamId); + void LoadPlayerStats(ArenaTeamMember* member); + + void BroadcastPacket(WorldPacket *packet); + + void Roster(WorldSession *session); + void Query(WorldSession *session); + void Stats(WorldSession *session); + void InspectStats(WorldSession *session, uint64 guid); + + protected: + + uint32 Id; + uint32 Type; + std::string Name; + uint64 CaptainGuid; + + uint32 BackgroundColor; // ARGB format + uint32 EmblemStyle; // icon id + uint32 EmblemColor; // ARGB format + uint32 BorderStyle; // border image id + uint32 BorderColor; // ARGB format + + MemberList members; + ArenaTeamStats stats; +}; +#endif diff --git a/src/game/ArenaTeamHandler.cpp b/src/game/ArenaTeamHandler.cpp new file mode 100644 index 00000000000..33786e93532 --- /dev/null +++ b/src/game/ArenaTeamHandler.cpp @@ -0,0 +1,462 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "WorldSession.h" +#include "WorldPacket.h" +#include "Log.h" +#include "Database/DatabaseEnv.h" +#include "Player.h" +#include "ObjectMgr.h" +#include "ArenaTeam.h" +#include "World.h" +#include "SocialMgr.h" + +void WorldSession::HandleInspectArenaStatsOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("MSG_INSPECT_ARENA_TEAMS"); + //recv_data.hexlike(); + + CHECK_PACKET_SIZE(recv_data, 8); + + uint64 guid; + recv_data >> guid; + sLog.outDebug("Inspect Arena stats " I64FMTD, guid); + + if(Player *plr = objmgr.GetPlayer(guid)) + { + for (uint8 i = 0; i < MAX_ARENA_SLOT; i++) + { + if(uint32 a_id = plr->GetArenaTeamId(i)) + { + if(ArenaTeam *at = objmgr.GetArenaTeamById(a_id)) + at->InspectStats(this, plr->GetGUID()); + } + } + } +} + +void WorldSession::HandleArenaTeamQueryOpcode(WorldPacket & recv_data) +{ + sLog.outDebug( "WORLD: Received CMSG_ARENA_TEAM_QUERY" ); + //recv_data.hexlike(); + + CHECK_PACKET_SIZE(recv_data, 4); + + uint32 ArenaTeamId; + recv_data >> ArenaTeamId; + + ArenaTeam *arenateam = objmgr.GetArenaTeamById(ArenaTeamId); + if(!arenateam) // arena team not found + return; + + arenateam->Query(this); + arenateam->Stats(this); +} + +void WorldSession::HandleArenaTeamRosterOpcode(WorldPacket & recv_data) +{ + sLog.outDebug( "WORLD: Received CMSG_ARENA_TEAM_ROSTER" ); + //recv_data.hexlike(); + + CHECK_PACKET_SIZE(recv_data, 4); + + uint32 ArenaTeamId; // arena team id + recv_data >> ArenaTeamId; + + ArenaTeam *arenateam = objmgr.GetArenaTeamById(ArenaTeamId); + if(!arenateam) + return; + + arenateam->Roster(this); +} + +void WorldSession::HandleArenaTeamAddMemberOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("CMSG_ARENA_TEAM_ADD_MEMBER"); + //recv_data.hexlike(); + + CHECK_PACKET_SIZE(recv_data, 4+1); + + uint32 ArenaTeamId; // arena team id + std::string Invitedname; + + Player * player = NULL; + + recv_data >> ArenaTeamId >> Invitedname; + + if(!Invitedname.empty()) + { + if(!normalizePlayerName(Invitedname)) + return; + + player = ObjectAccessor::Instance().FindPlayerByName(Invitedname.c_str()); + } + + if(!player) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", Invitedname, ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S); + return; + } + + if(player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + { + //SendArenaTeamCommandResult(ARENA_TEAM_INVITE_SS,"",Invitedname,ARENA_TEAM_PLAYER_NOT_FOUND_S); + // can't find related opcode + SendNotification("%s is not high enough level to join your team", player->GetName()); + return; + } + + ArenaTeam *arenateam = objmgr.GetArenaTeamById(ArenaTeamId); + if(!arenateam) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PLAYER_NOT_IN_TEAM); + return; + } + + // OK result but not send invite + if(player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow())) + return; + + if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && player->GetTeam() != GetPlayer()->GetTeam()) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED); + return; + } + + if(player->GetArenaTeamId(arenateam->GetSlot())) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, player->GetName(), "", ERR_ALREADY_IN_ARENA_TEAM_S); + return; + } + + if(player->GetArenaTeamIdInvited()) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, player->GetName(), "", ERR_ALREADY_INVITED_TO_ARENA_TEAM_S); + return; + } + + if(arenateam->GetMembersSize() >= arenateam->GetType() * 2) + { + // should send an "arena team is full" or the likes message, I just don't know the proper values so... ERR_INTERNAL +// SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_INTERNAL); + SendNotification("Your arena team is full, %s cannot join it.", player->GetName()); + return; + } + + sLog.outDebug("Player %s Invited %s to Join his ArenaTeam", GetPlayer()->GetName(), Invitedname.c_str()); + + player->SetArenaTeamIdInvited(arenateam->GetId()); + + WorldPacket data(SMSG_ARENA_TEAM_INVITE, (8+10)); + data << GetPlayer()->GetName(); + data << arenateam->GetName(); + player->GetSession()->SendPacket(&data); + + sLog.outDebug("WORLD: Sent SMSG_ARENA_TEAM_INVITE"); +} + +void WorldSession::HandleArenaTeamInviteAcceptOpcode(WorldPacket & /*recv_data*/) +{ + sLog.outDebug("CMSG_ARENA_TEAM_INVITE_ACCEPT"); // empty opcode + + ArenaTeam *at = objmgr.GetArenaTeamById(_player->GetArenaTeamIdInvited()); + if(!at) + { + // arena team not exist + return; + } + + if(_player->GetArenaTeamId(at->GetSlot())) + { + // already in arena team that size + return; + } + + // not let enemies sign petition + if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && _player->GetTeam() != objmgr.GetPlayerTeamByGUID(at->GetCaptain())) + return; + + if(!at->AddMember(_player->GetGUID())) + return; + + // event + WorldPacket data; + BuildArenaTeamEventPacket(&data, ERR_ARENA_TEAM_JOIN_SS, 2, _player->GetName(), at->GetName(), ""); + at->BroadcastPacket(&data); +} + +void WorldSession::HandleArenaTeamInviteDeclineOpcode(WorldPacket & /*recv_data*/) +{ + sLog.outDebug("CMSG_ARENA_TEAM_INVITE_DECLINE"); // empty opcode + + _player->SetArenaTeamIdInvited(0); // no more invited +} + +void WorldSession::HandleArenaTeamLeaveOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("CMSG_ARENA_TEAM_LEAVE"); + //recv_data.hexlike(); + + CHECK_PACKET_SIZE(recv_data, 4); + + uint32 ArenaTeamId; // arena team id + recv_data >> ArenaTeamId; + + ArenaTeam *at = objmgr.GetArenaTeamById(ArenaTeamId); + if(!at) + { + // send command result + return; + } + if(_player->GetGUID() == at->GetCaptain() && at->GetMembersSize() > 1) + { + // check for correctness + SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, "", "", ERR_ARENA_TEAM_LEADER_LEAVE_S); + return; + } + // arena team has only one member (=captain) + if(_player->GetGUID() == at->GetCaptain()) + { + at->Disband(this); + delete at; + return; + } + + at->DelMember(_player->GetGUID()); + + // event + WorldPacket data; + BuildArenaTeamEventPacket(&data, ERR_ARENA_TEAM_LEAVE_SS, 2, _player->GetName(), at->GetName(), ""); + at->BroadcastPacket(&data); + + //SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, at->GetName(), "", 0); +} + +void WorldSession::HandleArenaTeamDisbandOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("CMSG_ARENA_TEAM_DISBAND"); + //recv_data.hexlike(); + + CHECK_PACKET_SIZE(recv_data, 4); + + uint32 ArenaTeamId; // arena team id + recv_data >> ArenaTeamId; + + ArenaTeam *at = objmgr.GetArenaTeamById(ArenaTeamId); + if(!at) + { + // arena team not found + return; + } + + if(at->GetCaptain() != _player->GetGUID()) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PERMISSIONS); + return; + } + + at->Disband(this); + delete at; +} + +void WorldSession::HandleArenaTeamRemoveFromTeamOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("CMSG_ARENA_TEAM_REMOVE_FROM_TEAM"); + //recv_data.hexlike(); + + CHECK_PACKET_SIZE(recv_data, 4+1); + + uint32 ArenaTeamId; + std::string name; + + recv_data >> ArenaTeamId; + recv_data >> name; + + ArenaTeam *at = objmgr.GetArenaTeamById(ArenaTeamId); + if(!at) + { + // arena team not found + return; + } + + uint64 guid = objmgr.GetPlayerGUIDByName(name); + if(!guid) + { + // player guid not found + return; + } + + if(at->GetCaptain() == guid) + { + // unsure + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PERMISSIONS); + return; + } + + if(at->GetCaptain() != _player->GetGUID()) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PERMISSIONS); + return; + } + + if(at->GetCaptain() == guid) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_LEADER_LEAVE_S); + return; + } + + at->DelMember(guid); + + // event + WorldPacket data; + BuildArenaTeamEventPacket(&data, ERR_ARENA_TEAM_REMOVE_SSS, 3, name, at->GetName(), _player->GetName()); + at->BroadcastPacket(&data); +} + +void WorldSession::HandleArenaTeamPromoteToCaptainOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("CMSG_ARENA_TEAM_PROMOTE_TO_CAPTAIN"); + //recv_data.hexlike(); + + CHECK_PACKET_SIZE(recv_data, 4+1); + + uint32 ArenaTeamId; + std::string name; + + recv_data >> ArenaTeamId; + recv_data >> name; + + ArenaTeam *at = objmgr.GetArenaTeamById(ArenaTeamId); + if(!at) + { + // arena team not found + return; + } + + uint64 guid = objmgr.GetPlayerGUIDByName(name); + if(!guid) + { + // player guid not found + return; + } + + if(at->GetCaptain() == guid) + { + // target player already captain + return; + } + + if(at->GetCaptain() != _player->GetGUID()) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PERMISSIONS); + return; + } + + at->SetCaptain(guid); + + // event + WorldPacket data; + BuildArenaTeamEventPacket(&data, ERR_ARENA_TEAM_LEADER_CHANGED_SSS, 3, _player->GetName(), name, at->GetName()); + at->BroadcastPacket(&data); +} + +void WorldSession::SendArenaTeamCommandResult(uint32 unk1, std::string str1, std::string str2, uint32 unk3) +{ + WorldPacket data(SMSG_ARENA_TEAM_COMMAND_RESULT, 4+str1.length()+1+str2.length()+1+4); + data << unk1; + data << str1; + data << str2; + data << unk3; + SendPacket(&data); +} + +void WorldSession::BuildArenaTeamEventPacket(WorldPacket *data, uint8 eventid, uint8 str_count, std::string str1, std::string str2, std::string str3) +{ + data->Initialize(SMSG_ARENA_TEAM_EVENT, 1+1+1); + *data << eventid; + *data << str_count; + switch(str_count) + { + case 1: + *data << str1; + break; + case 2: + *data << str1; + *data << str2; + break; + case 3: + *data << str1; + *data << str2; + *data << str3; + break; + default: + sLog.outError("Unhandled str_count %u in SendArenaTeamEvent()", str_count); + return; + } +} + +void WorldSession::SendNotInArenaTeamPacket(uint8 type) +{ + WorldPacket data(SMSG_ARENA_ERROR, 4+1); // 886 - You are not in a %uv%u arena team + uint32 unk = 0; + data << uint32(unk); // unk(0) + if(!unk) + data << uint8(type); // team type (2=2v2,3=3v3,5=5v5), can be used for custom types... + SendPacket(&data); +} + +/* ++ERR_ARENA_NO_TEAM_II "You are not in a %dv%d arena team" + ++ERR_ARENA_TEAM_CREATE_S "%s created. To disband, use /teamdisband [2v2, 3v3, 5v5]." ++ERR_ARENA_TEAM_INVITE_SS "You have invited %s to join %s" ++ERR_ARENA_TEAM_QUIT_S "You are no longer a member of %s" +ERR_ARENA_TEAM_FOUNDER_S "Congratulations, you are a founding member of %s! To leave, use /teamquit [2v2, 3v3, 5v5]." + ++ERR_ARENA_TEAM_INTERNAL "Internal arena team error" ++ERR_ALREADY_IN_ARENA_TEAM "You are already in an arena team of that size" ++ERR_ALREADY_IN_ARENA_TEAM_S "%s is already in an arena team of that size" ++ERR_INVITED_TO_ARENA_TEAM "You have already been invited into an arena team" ++ERR_ALREADY_INVITED_TO_ARENA_TEAM_S "%s has already been invited to an arena team" ++ERR_ARENA_TEAM_NAME_INVALID "That name contains invalid characters, please enter a new name" ++ERR_ARENA_TEAM_NAME_EXISTS_S "There is already an arena team named \"%s\"" ++ERR_ARENA_TEAM_LEADER_LEAVE_S "You must promote a new team captain using /teamcaptain before leaving the team" ++ERR_ARENA_TEAM_PERMISSIONS "You don't have permission to do that" ++ERR_ARENA_TEAM_PLAYER_NOT_IN_TEAM "You are not in an arena team of that size" ++ERR_ARENA_TEAM_PLAYER_NOT_IN_TEAM_SS "%s is not in %s" ++ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S "\"%s\" not found" ++ERR_ARENA_TEAM_NOT_ALLIED "You cannot invite players from the opposing alliance" + ++ERR_ARENA_TEAM_JOIN_SS "%s has joined %s" ++ERR_ARENA_TEAM_YOU_JOIN_S "You have joined %s. To leave, use /teamquit [2v2, 3v3, 5v5]." + ++ERR_ARENA_TEAM_LEAVE_SS "%s has left %s" + ++ERR_ARENA_TEAM_LEADER_IS_SS "%s is the captain of %s" ++ERR_ARENA_TEAM_LEADER_CHANGED_SSS "%s has made %s the new captain of %s" + ++ERR_ARENA_TEAM_REMOVE_SSS "%s has been kicked out of %s by %s" + ++ERR_ARENA_TEAM_DISBANDED_S "%s has disbanded %s" + +ERR_ARENA_TEAM_TARGET_TOO_LOW_S "%s is not high enough level to join your team" + +ERR_ARENA_TEAM_TOO_MANY_MEMBERS_S "%s is full" + +ERR_ARENA_TEAM_LEVEL_TOO_LOW_I "You must be level %d to form an arena team" +*/ diff --git a/src/game/AuctionHouse.cpp b/src/game/AuctionHouse.cpp new file mode 100644 index 00000000000..9b527400b04 --- /dev/null +++ b/src/game/AuctionHouse.cpp @@ -0,0 +1,747 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Opcodes.h" +#include "Log.h" +#include "World.h" +#include "ObjectMgr.h" +#include "Player.h" +#include "UpdateMask.h" +#include "AuctionHouseObject.h" +#include "Util.h" + +//please DO NOT use iterator++, because it is slower than ++iterator!!! +//post-incrementation is always slower than pre-incrementation ! + +//void called when player click on auctioneer npc +void WorldSession::HandleAuctionHelloOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8); + + uint64 guid; //NPC guid + recv_data >> guid; + + Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_AUCTIONEER); + if (!unit) + { + sLog.outDebug( "WORLD: HandleAuctionHelloOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); + return; + } + + // remove fake death + if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + SendAuctionHello(guid, unit); +} + +static uint8 AuctioneerFactionToLocation(uint32 faction) +{ + if(sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION)) + return 7; // neutral + + FactionTemplateEntry const* u_entry = sFactionTemplateStore.LookupEntry(faction); + if(!u_entry) + return 7; // neutral + + if(u_entry->ourMask & FACTION_MASK_ALLIANCE) + return 2; + else if(u_entry->ourMask & FACTION_MASK_HORDE) + return 6; + else + return 7; +} + +//this void causes that auction window is opened +void WorldSession::SendAuctionHello( uint64 guid, Creature* unit ) +{ + WorldPacket data( MSG_AUCTION_HELLO, 12 ); + data << (uint64) guid; + data << (uint32) AuctioneerFactionToLocation(unit->getFaction()); + SendPacket( &data ); +} + +//this function inserts to WorldPacket auction's data +bool WorldSession::SendAuctionInfo(WorldPacket & data, AuctionEntry* auction) +{ + Item *pItem = objmgr.GetAItem(auction->item_guidlow); + if (!pItem) + { + sLog.outError("auction to item, that doesn't exist !!!!"); + return false; + } + data << auction->Id; + data << pItem->GetUInt32Value(OBJECT_FIELD_ENTRY); + + for (uint8 i = 0; i < MAX_INSPECTED_ENCHANTMENT_SLOT; i++) + { + data << (uint32) pItem->GetEnchantmentId(EnchantmentSlot(i)); + data << (uint32) pItem->GetEnchantmentDuration(EnchantmentSlot(i)); + data << (uint32) pItem->GetEnchantmentCharges(EnchantmentSlot(i)); + } + + data << (uint32) pItem->GetItemRandomPropertyId(); //random item property id + data << (uint32) pItem->GetItemSuffixFactor(); //SuffixFactor + data << (uint32) pItem->GetCount(); //item->count + data << (uint32) pItem->GetSpellCharges(); //item->charge FFFFFFF + data << (uint32) 0; //Unknown + data << (uint64) auction->owner; //Auction->owner + data << (uint32) auction->startbid; //Auction->startbid (not sure if useful) + data << (uint32) ((auction->bid)? objmgr.GetAuctionOutBid(auction->bid) : 0); + //minimal outbid + data << (uint32) auction->buyout; //auction->buyout + data << (uint32) (auction->time - time(NULL)) * 1000; //time left + data << (uint64) auction->bidder; //auction->bidder current + data << (uint32) auction->bid; //current bid + return true; +} + +//call this method when player bids, creates, or deletes auction +void WorldSession::SendAuctionCommandResult(uint32 auctionId, uint32 Action, uint32 ErrorCode, uint32 bidError ) +{ + WorldPacket data( SMSG_AUCTION_COMMAND_RESULT, 16 ); + data << auctionId; + data << Action; + data << ErrorCode; + if ( !ErrorCode && Action ) + data << bidError; //when bid, then send 0, once... + SendPacket(&data); +} + +//this function sends notification, if bidder is online +void WorldSession::SendAuctionBidderNotification( uint32 location, uint32 auctionId, uint64 bidder, uint32 bidSum, uint32 diff, uint32 item_template) +{ + WorldPacket data(SMSG_AUCTION_BIDDER_NOTIFICATION, (8*4)); + data << location; + data << auctionId; + data << (uint64) bidder; + data << bidSum; + data << (uint32) diff; + data << item_template; + data << (uint32) 0; + SendPacket(&data); +} + +//this void causes on client to display: "Your auction sold" +void WorldSession::SendAuctionOwnerNotification( AuctionEntry* auction) +{ + WorldPacket data(SMSG_AUCTION_OWNER_NOTIFICATION, (7*4)); + data << auction->Id; + data << auction->bid; + data << (uint32) 0; //unk + data << (uint32) 0; //unk + data << (uint32) 0; //unk + data << auction->item_template; + data << (uint32) 0; //unk + SendPacket(&data); +} + +//this function sends mail to old bidder +void WorldSession::SendAuctionOutbiddedMail(AuctionEntry *auction, uint32 newPrice) +{ + uint64 oldBidder_guid = MAKE_NEW_GUID(auction->bidder,0, HIGHGUID_PLAYER); + Player *oldBidder = objmgr.GetPlayer(oldBidder_guid); + + uint32 oldBidder_accId = 0; + if(!oldBidder) + oldBidder_accId = objmgr.GetPlayerAccountIdByGUID(oldBidder_guid); + + // old bidder exist + if(oldBidder || oldBidder_accId) + { + std::ostringstream msgAuctionOutbiddedSubject; + msgAuctionOutbiddedSubject << auction->item_template << ":0:" << AUCTION_OUTBIDDED; + + if (oldBidder) + oldBidder->GetSession()->SendAuctionBidderNotification( auction->location, auction->Id, _player->GetGUID(), newPrice, objmgr.GetAuctionOutBid(auction->bid), auction->item_template); + + WorldSession::SendMailTo(oldBidder, MAIL_AUCTION, MAIL_STATIONERY_AUCTION, auction->location, auction->bidder, msgAuctionOutbiddedSubject.str(), 0, NULL, auction->bid, 0, MAIL_CHECK_MASK_NONE); + } +} + +//this function sends mail, when auction is cancelled to old bidder +void WorldSession::SendAuctionCancelledToBidderMail( AuctionEntry* auction ) +{ + uint64 bidder_guid = MAKE_NEW_GUID(auction->bidder, 0, HIGHGUID_PLAYER); + Player *bidder = objmgr.GetPlayer(bidder_guid); + + uint32 bidder_accId = 0; + if(!bidder) + bidder_accId = objmgr.GetPlayerAccountIdByGUID(bidder_guid); + + // bidder exist + if(bidder || bidder_accId) + { + std::ostringstream msgAuctionCancelledSubject; + msgAuctionCancelledSubject << auction->item_template << ":0:" << AUCTION_CANCELLED_TO_BIDDER; + + WorldSession::SendMailTo(bidder, MAIL_AUCTION, MAIL_STATIONERY_AUCTION, auction->location, auction->bidder, msgAuctionCancelledSubject.str(), 0, NULL, auction->bid, 0, MAIL_CHECK_MASK_NONE); + } +} + +//this void creates new auction and adds auction to some auctionhouse +void WorldSession::HandleAuctionSellItem( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+8+4+4+4); + + uint64 auctioneer, item; + uint32 etime, bid, buyout; + recv_data >> auctioneer >> item; + recv_data >> bid >> buyout >> etime; + Player *pl = GetPlayer(); + + if (!item || !bid || !etime) + return; //check for cheaters + + Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, auctioneer,UNIT_NPC_FLAG_AUCTIONEER); + if (!pCreature) + { + sLog.outDebug( "WORLD: HandleAuctionSellItem - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(auctioneer)) ); + return; + } + + // client send time in minutes, convert to common used sec time + etime *= MINUTE; + + // client understand only 3 auction time + switch(etime) + { + case 1*MIN_AUCTION_TIME: + case 2*MIN_AUCTION_TIME: + case 4*MIN_AUCTION_TIME: + break; + default: + return; + } + + // remove fake death + if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + Item *it = pl->GetItemByGuid( item ); + //do not allow to sell already auctioned items + if(objmgr.GetAItem(GUID_LOPART(item))) + { + sLog.outError("AuctionError, player %s is sending item id: %u, but item is already in another auction", pl->GetName(), GUID_LOPART(item)); + SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); + return; + } + // prevent sending bag with items (cheat: can be placed in bag after adding equiped empty bag to auction) + if(!it) + { + SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_ITEM_NOT_FOUND); + return; + } + + if(!it->CanBeTraded()) + { + SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); + return; + } + + if (it->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_CONJURED) || it->GetUInt32Value(ITEM_FIELD_DURATION)) + { + SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); + return; + } + + uint32 location = AuctioneerFactionToLocation(pCreature->getFaction()); + AuctionHouseObject * mAuctions; + mAuctions = objmgr.GetAuctionsMap( location ); + + //we have to take deposit : + uint32 deposit = objmgr.GetAuctionDeposit( location, etime, it ); + if ( pl->GetMoney() < deposit ) + { + SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_NOT_ENOUGHT_MONEY); + return; + } + + if( GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) ) + { + sLog.outCommand("GM %s (Account: %u) create auction: %s (Entry: %u Count: %u)", + GetPlayerName(),GetAccountId(),it->GetProto()->Name1,it->GetEntry(),it->GetCount()); + } + + pl->ModifyMoney( -int32(deposit) ); + + uint32 auction_time = uint32(etime * sWorld.getRate(RATE_AUCTION_TIME)); + + AuctionEntry *AH = new AuctionEntry; + AH->Id = objmgr.GenerateAuctionID(); + AH->auctioneer = GUID_LOPART(auctioneer); + AH->item_guidlow = GUID_LOPART(item); + AH->item_template = it->GetEntry(); + AH->owner = pl->GetGUIDLow(); + AH->startbid = bid; + AH->bidder = 0; + AH->bid = 0; + AH->buyout = buyout; + AH->time = time(NULL) + auction_time; + AH->deposit = deposit; + AH->location = location; + + sLog.outDetail("selling item %u to auctioneer %u with initial bid %u with buyout %u and with time %u (in sec) in location: %u", GUID_LOPART(item), GUID_LOPART(auctioneer), bid, buyout, auction_time, location); + mAuctions->AddAuction(AH); + + objmgr.AddAItem(it); + pl->MoveItemFromInventory( it->GetBagSlot(), it->GetSlot(), true); + + CharacterDatabase.BeginTransaction(); + it->DeleteFromInventoryDB(); + it->SaveToDB(); // recursive and not have transaction guard into self, not in inventiory and can be save standalone + CharacterDatabase.PExecute("INSERT INTO auctionhouse (id,auctioneerguid,itemguid,item_template,itemowner,buyoutprice,time,buyguid,lastbid,startbid,deposit,location) " + "VALUES ('%u', '%u', '%u', '%u', '%u', '%u', '" I64FMTD "', '%u', '%u', '%u', '%u', '%u')", + AH->Id, AH->auctioneer, AH->item_guidlow, AH->item_template, AH->owner, AH->buyout, (uint64)AH->time, AH->bidder, AH->bid, AH->startbid, AH->deposit, AH->location); + pl->SaveInventoryAndGoldToDB(); + CharacterDatabase.CommitTransaction(); + + SendAuctionCommandResult(AH->Id, AUCTION_SELL_ITEM, AUCTION_OK); +} + +//this function is called when client bids or buys out auction +void WorldSession::HandleAuctionPlaceBid( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+4+4); + + uint64 auctioneer; + uint32 auctionId; + uint32 price; + recv_data >> auctioneer; + recv_data >> auctionId >> price; + + if (!auctionId || !price) + return; //check for cheaters + + Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, auctioneer,UNIT_NPC_FLAG_AUCTIONEER); + if (!pCreature) + { + sLog.outDebug( "WORLD: HandleAuctionPlaceBid - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(auctioneer)) ); + return; + } + + // remove fake death + if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + uint32 location = AuctioneerFactionToLocation(pCreature->getFaction()); + + AuctionHouseObject * mAuctions; + mAuctions = objmgr.GetAuctionsMap( location ); + + AuctionEntry *auction = mAuctions->GetAuction(auctionId); + Player *pl = GetPlayer(); + + if( !auction || auction->owner == pl->GetGUIDLow() ) + { + //you cannot bid your own auction: + SendAuctionCommandResult( 0, AUCTION_PLACE_BID, CANNOT_BID_YOUR_AUCTION_ERROR ); + return; + } + + // impossible have online own another character (use this for speedup check in case online owner) + Player* auction_owner = objmgr.GetPlayer(MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER)); + if( !auction_owner && objmgr.GetPlayerAccountIdByGUID(MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER)) == pl->GetSession()->GetAccountId()) + { + //you cannot bid your another character auction: + SendAuctionCommandResult( 0, AUCTION_PLACE_BID, CANNOT_BID_YOUR_AUCTION_ERROR ); + return; + } + + if (price < (auction->bid + objmgr.GetAuctionOutBid(auction->bid))) + { + //auction has already higher bid, client tests it! + //SendAuctionCommandResult(auction->auctionId, AUCTION_PLACE_BID, ???); + return; + } + + if (price > pl->GetMoney()) + { + //you don't have enought money!, client tests! + //SendAuctionCommandResult(auction->auctionId, AUCTION_PLACE_BID, ???); + return; + } + + if ((price < auction->buyout) || (auction->buyout == 0)) + { + if (auction->bidder > 0) + { + if ( auction->bidder == pl->GetGUIDLow() ) + { + pl->ModifyMoney( -int32(price - auction->bid)); + } + else + { + // mail to last bidder and return money + SendAuctionOutbiddedMail( auction , price ); + pl->ModifyMoney( -int32(price) ); + } + } + else + { + pl->ModifyMoney( -int32(price) ); + } + auction->bidder = pl->GetGUIDLow(); + auction->bid = price; + + // after this update we should save player's money ... + CharacterDatabase.PExecute("UPDATE auctionhouse SET buyguid = '%u',lastbid = '%u' WHERE id = '%u'", auction->bidder, auction->bid, auction->Id); + + SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, AUCTION_OK, 0 ); + } + else + { + //buyout: + if (pl->GetGUIDLow() == auction->bidder ) + { + pl->ModifyMoney(-int32(auction->buyout - auction->bid)); + } + else + { + pl->ModifyMoney(-int32(auction->buyout)); + if ( auction->bidder ) //buyout for bidded auction .. + { + SendAuctionOutbiddedMail( auction, auction->buyout ); + } + } + auction->bidder = pl->GetGUIDLow(); + auction->bid = auction->buyout; + + objmgr.SendAuctionSalePendingMail( auction ); + objmgr.SendAuctionSuccessfulMail( auction ); + objmgr.SendAuctionWonMail( auction ); + + SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, AUCTION_OK); + + objmgr.RemoveAItem(auction->item_guidlow); + mAuctions->RemoveAuction(auction->Id); + CharacterDatabase.PExecute("DELETE FROM auctionhouse WHERE id = '%u'",auction->Id); + + delete auction; + } + CharacterDatabase.BeginTransaction(); + pl->SaveInventoryAndGoldToDB(); + CharacterDatabase.CommitTransaction(); +} + +//this void is called when auction_owner cancels his auction +void WorldSession::HandleAuctionRemoveItem( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+4); + + uint64 auctioneer; + uint32 auctionId; + recv_data >> auctioneer; + recv_data >> auctionId; + //sLog.outDebug( "Cancel AUCTION AuctionID: %u", auctionId); + + Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, auctioneer,UNIT_NPC_FLAG_AUCTIONEER); + if (!pCreature) + { + sLog.outDebug( "WORLD: HandleAuctionRemoveItem - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(auctioneer)) ); + return; + } + + // remove fake death + if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + uint32 location = AuctioneerFactionToLocation(pCreature->getFaction()); + + AuctionHouseObject * mAuctions; + mAuctions = objmgr.GetAuctionsMap( location ); + + AuctionEntry *auction = mAuctions->GetAuction(auctionId); + Player *pl = GetPlayer(); + + if (auction && auction->owner == pl->GetGUIDLow()) + { + Item *pItem = objmgr.GetAItem(auction->item_guidlow); + if (pItem) + { + if (auction->bidder > 0) // If we have a bidder, we have to send him the money he paid + { + uint32 auctionCut = objmgr.GetAuctionCut( auction->location, auction->bid); + if ( pl->GetMoney() < auctionCut ) //player doesn't have enough money, maybe message needed + return; + //some auctionBidderNotification would be needed, but don't know that parts.. + SendAuctionCancelledToBidderMail( auction ); + pl->ModifyMoney( -int32(auctionCut) ); + } + // Return the item by mail + std::ostringstream msgAuctionCanceledOwner; + msgAuctionCanceledOwner << auction->item_template << ":0:" << AUCTION_CANCELED; + + MailItemsInfo mi; + mi.AddItem(auction->item_guidlow, auction->item_template, pItem); + + // item will deleted or added to received mail list + WorldSession::SendMailTo(pl, MAIL_AUCTION, MAIL_STATIONERY_AUCTION, auction->location, pl->GetGUIDLow(), msgAuctionCanceledOwner.str(), 0, &mi, 0, 0, MAIL_CHECK_MASK_NONE); + } + else + { + sLog.outError("Auction id: %u has non-existed item (item guid : %u)!!!", auction->Id, auction->item_guidlow); + SendAuctionCommandResult( 0, AUCTION_CANCEL, AUCTION_INTERNAL_ERROR ); + return; + } + } + else + { + SendAuctionCommandResult( 0, AUCTION_CANCEL, AUCTION_INTERNAL_ERROR ); + //this code isn't possible ... maybe there should be assert + sLog.outError("CHEATER : %u, he tried to cancel auction (id: %u) of another player, or auction is NULL", pl->GetGUIDLow(), auctionId ); + return; + } + + //inform player, that auction is removed + SendAuctionCommandResult( auction->Id, AUCTION_CANCEL, AUCTION_OK ); + // Now remove the auction + CharacterDatabase.BeginTransaction(); + CharacterDatabase.PExecute("DELETE FROM auctionhouse WHERE id = '%u'",auction->Id); + pl->SaveInventoryAndGoldToDB(); + CharacterDatabase.CommitTransaction(); + objmgr.RemoveAItem( auction->item_guidlow ); + mAuctions->RemoveAuction( auction->Id ); + delete auction; +} + +//called when player lists his bids +void WorldSession::HandleAuctionListBidderItems( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+4+4); + + uint64 guid; //NPC guid + uint32 listfrom; //page of auctions + uint32 outbiddedCount; //count of outbidded auctions + + recv_data >> guid; + recv_data >> listfrom; // not used in fact (this list not have page control in client) + recv_data >> outbiddedCount; + if (recv_data.size() != (16 + outbiddedCount * 4 )) + { + sLog.outError("Client sent bad opcode!!! with count: %u and size : %d (mustbe: %d", outbiddedCount, recv_data.size(),(16 + outbiddedCount * 4 )); + outbiddedCount = 0; + } + + Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_AUCTIONEER); + if (!pCreature) + { + sLog.outDebug( "WORLD: HandleAuctionListBidderItems - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); + return; + } + + // remove fake death + if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + uint32 location = AuctioneerFactionToLocation(pCreature->getFaction()); + AuctionHouseObject* mAuctions = objmgr.GetAuctionsMap( location ); + + WorldPacket data( SMSG_AUCTION_BIDDER_LIST_RESULT, (4+4+4) ); + Player *pl = GetPlayer(); + data << (uint32) 0; //add 0 as count + uint32 count = 0; + uint32 totalcount = 0; + while ( outbiddedCount > 0) //add all data, which client requires + { + --outbiddedCount; + uint32 outbiddedAuctionId; + recv_data >> outbiddedAuctionId; + AuctionEntry * auction = mAuctions->GetAuction( outbiddedAuctionId ); + if ( auction && SendAuctionInfo(data, auction)) + { + ++totalcount; + ++count; + } + } + for (AuctionHouseObject::AuctionEntryMap::iterator itr = mAuctions->GetAuctionsBegin();itr != mAuctions->GetAuctionsEnd();++itr) + { + AuctionEntry *Aentry = itr->second; + if( Aentry && Aentry->bidder == pl->GetGUIDLow() ) + { + if (SendAuctionInfo(data, itr->second)) + ++count; + ++totalcount; + } + } + data.put( 0, count ); // add count to placeholder + data << totalcount; + data << (uint32)300; //unk 2.3.0 + SendPacket(&data); +} + +//this void sends player info about his auctions +void WorldSession::HandleAuctionListOwnerItems( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+4); + + uint32 listfrom; + uint64 guid; + + recv_data >> guid; + recv_data >> listfrom; // not used in fact (this list not have page control in client) + + Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_AUCTIONEER); + if (!pCreature) + { + sLog.outDebug( "WORLD: HandleAuctionListOwnerItems - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); + return; + } + + // remove fake death + if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + uint32 location = AuctioneerFactionToLocation(pCreature->getFaction()); + + AuctionHouseObject* mAuctions = objmgr.GetAuctionsMap( location ); + + WorldPacket data( SMSG_AUCTION_OWNER_LIST_RESULT, (4+4+4) ); + data << (uint32) 0; // amount place holder + + uint32 count = 0; + uint32 totalcount = 0; + for (AuctionHouseObject::AuctionEntryMap::iterator itr = mAuctions->GetAuctionsBegin();itr != mAuctions->GetAuctionsEnd();++itr) + { + AuctionEntry *Aentry = itr->second; + if( Aentry && Aentry->owner == _player->GetGUIDLow() ) + { + if(SendAuctionInfo(data, itr->second)) + ++count; + ++totalcount; + } + } + data.put(0, count); + data << (uint32) totalcount; + data << (uint32) 0; + SendPacket(&data); +} + +//this void is called when player clicks on search button +void WorldSession::HandleAuctionListItems( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+4+1+1+1+4+4+4+4+1); + + std::string searchedname, name; + uint8 levelmin, levelmax, usable, location; + uint32 count, totalcount, listfrom, auctionSlotID, auctionMainCategory, auctionSubCategory, quality; + uint64 guid; + + recv_data >> guid; + recv_data >> listfrom; // start, used for page control listing by 50 elements + recv_data >> searchedname; + + // recheck with known string size + CHECK_PACKET_SIZE(recv_data,8+4+(searchedname.size()+1)+1+1+4+4+4+4+1); + + recv_data >> levelmin >> levelmax; + recv_data >> auctionSlotID >> auctionMainCategory >> auctionSubCategory; + recv_data >> quality >> usable; + + Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_AUCTIONEER); + if (!pCreature) + { + sLog.outDebug( "WORLD: HandleAuctionListItems - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); + return; + } + + // remove fake death + if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + location = AuctioneerFactionToLocation(pCreature->getFaction()); + AuctionHouseObject * mAuctions; + mAuctions = objmgr.GetAuctionsMap( location ); + + //sLog.outDebug("Auctionhouse search guid: " I64FMTD ", list from: %u, searchedname: %s, levelmin: %u, levelmax: %u, auctionSlotID: %u, auctionMainCategory: %u, auctionSubCategory: %u, quality: %u, usable: %u", guid, listfrom, searchedname.c_str(), levelmin, levelmax, auctionSlotID, auctionMainCategory, auctionSubCategory, quality, usable); + + WorldPacket data( SMSG_AUCTION_LIST_RESULT, (4+4+4) ); + count = 0; + totalcount = 0; + data << (uint32) 0; + + // converting string that we try to find to lower case + std::wstring wsearchedname; + if(!Utf8toWStr(searchedname,wsearchedname)) + return; + + wstrToLower(wsearchedname); + + for (AuctionHouseObject::AuctionEntryMap::iterator itr = mAuctions->GetAuctionsBegin();itr != mAuctions->GetAuctionsEnd();++itr) + { + AuctionEntry *Aentry = itr->second; + Item *item = objmgr.GetAItem(Aentry->item_guidlow); + if( item ) + { + ItemPrototype const *proto = item->GetProto(); + if( proto ) + { + if( auctionMainCategory == (0xffffffff) || proto->Class == auctionMainCategory ) + { + if( auctionSubCategory == (0xffffffff) || proto->SubClass == auctionSubCategory ) + { + if( auctionSlotID == (0xffffffff) || proto->InventoryType == auctionSlotID ) + { + if( quality == (0xffffffff) || proto->Quality == quality ) + { + if( usable == (0x00) || _player->CanUseItem( item ) == EQUIP_ERR_OK ) + { + if( ( levelmin == (0x00) || proto->RequiredLevel >= levelmin ) && ( levelmax == (0x00) || proto->RequiredLevel <= levelmax ) ) + { + name = proto->Name1; + + // local name + int loc_idx = GetSessionDbLocaleIndex(); + if ( loc_idx >= 0 ) + { + ItemLocale const *il = objmgr.GetItemLocale(proto->ItemId); + if (il) + { + if (il->Name.size() > loc_idx && !il->Name[loc_idx].empty()) + name = il->Name[loc_idx]; + } + } + + if(name.empty()) + continue; + + if( wsearchedname.empty() || Utf8FitTo(name, wsearchedname) ) + { + if ((count < 50) && (totalcount >= listfrom)) + { + ++count; + SendAuctionInfo( data, Aentry); + } + ++totalcount; + } + } + } + } + } + } + } + } + } + } + data.put(0, count); + data << (uint32) totalcount; + data << (uint32) 300; // unk 2.3.0 const? + SendPacket(&data); +} diff --git a/src/game/AuctionHouseObject.h b/src/game/AuctionHouseObject.h new file mode 100644 index 00000000000..504c41c62e5 --- /dev/null +++ b/src/game/AuctionHouseObject.h @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _AUCTION_HOUSE_H +#define _AUCTION_HOUSE_H + +#include "SharedDefines.h" + +#define MIN_AUCTION_TIME (12*HOUR) + +enum AuctionError +{ + AUCTION_OK = 0, + AUCTION_INTERNAL_ERROR = 2, + AUCTION_NOT_ENOUGHT_MONEY = 3, + AUCTION_ITEM_NOT_FOUND = 4, + CANNOT_BID_YOUR_AUCTION_ERROR = 10 +}; + +enum AuctionAction +{ + AUCTION_SELL_ITEM = 0, + AUCTION_CANCEL = 1, + AUCTION_PLACE_BID = 2 +}; + +struct AuctionEntry +{ + uint32 Id; + uint32 auctioneer; + uint32 item_guidlow; + uint32 item_template; + uint32 owner; + uint32 startbid; //maybe useless + uint32 bid; + uint32 buyout; + time_t time; + uint32 bidder; + uint32 deposit; //deposit can be calculated only when creating auction + uint32 location; +}; + +//this class is used as auctionhouse instance +class AuctionHouseObject +{ + public: + AuctionHouseObject() {} + ~AuctionHouseObject() + { + for (AuctionEntryMap::iterator itr = AuctionsMap.begin(); itr != AuctionsMap.end(); ++itr) + delete itr->second; + } + + typedef std::map AuctionEntryMap; + + uint32 Getcount() { return AuctionsMap.size(); } + + AuctionEntryMap::iterator GetAuctionsBegin() {return AuctionsMap.begin();} + AuctionEntryMap::iterator GetAuctionsEnd() {return AuctionsMap.end();} + + void AddAuction(AuctionEntry *ah) + { + ASSERT( ah ); + AuctionsMap[ah->Id] = ah; + } + + AuctionEntry* GetAuction(uint32 id) const + { + AuctionEntryMap::const_iterator itr = AuctionsMap.find( id ); + if( itr != AuctionsMap.end() ) + return itr->second; + return NULL; + } + + bool RemoveAuction(uint32 id) + { + AuctionEntryMap::iterator i = AuctionsMap.find(id); + if (i == AuctionsMap.end()) + { + return false; + } + AuctionsMap.erase(i); + return true; + } + + private: + AuctionEntryMap AuctionsMap; +}; +#endif diff --git a/src/game/Bag.cpp b/src/game/Bag.cpp new file mode 100644 index 00000000000..a529d075dcf --- /dev/null +++ b/src/game/Bag.cpp @@ -0,0 +1,249 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Bag.h" +#include "ObjectMgr.h" +#include "Database/DatabaseEnv.h" +#include "Log.h" +#include "WorldPacket.h" +#include "UpdateData.h" +#include "WorldSession.h" + +Bag::Bag( ): Item() +{ + m_objectType |= TYPEMASK_CONTAINER; + m_objectTypeId = TYPEID_CONTAINER; + + m_valuesCount = CONTAINER_END; + + memset(m_bagslot, 0, sizeof(Item *) * MAX_BAG_SIZE); // Maximum 20 Slots +} + +Bag::~Bag() +{ + for(int i = 0; iAddToWorld(); + } +} + +void Bag::RemoveFromWorld() +{ + for(int i = 0; iRemoveFromWorld(); + } + + Item::RemoveFromWorld(); +} + +bool Bag::Create(uint32 guidlow, uint32 itemid, Player const* owner) +{ + ItemPrototype const * itemProto = objmgr.GetItemPrototype(itemid); + + if(!itemProto || itemProto->ContainerSlots > MAX_BAG_SIZE) + return false; + + Object::_Create( guidlow, 0, HIGHGUID_CONTAINER ); + + SetUInt32Value(OBJECT_FIELD_ENTRY, itemid); + SetFloatValue(OBJECT_FIELD_SCALE_X, 1.0f); + + SetUInt64Value(ITEM_FIELD_OWNER, owner ? owner->GetGUID() : 0); + SetUInt64Value(ITEM_FIELD_CONTAINED, owner ? owner->GetGUID() : 0); + + SetUInt32Value(ITEM_FIELD_MAXDURABILITY, itemProto->MaxDurability); + SetUInt32Value(ITEM_FIELD_DURABILITY, itemProto->MaxDurability); + SetUInt32Value(ITEM_FIELD_FLAGS, itemProto->Flags); + SetUInt32Value(ITEM_FIELD_STACK_COUNT, 1); + + // Setting the number of Slots the Container has + SetUInt32Value(CONTAINER_FIELD_NUM_SLOTS, itemProto->ContainerSlots); + + // Cleanning 20 slots + for (uint8 i = 0; i < MAX_BAG_SIZE; i++) + { + SetUInt64Value(CONTAINER_FIELD_SLOT_1 + (i*2), 0); + m_bagslot[i] = NULL; + } + + return true; +} + +void Bag::SaveToDB() +{ + Item::SaveToDB(); +} + +bool Bag::LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult *result) +{ + if(!Item::LoadFromDB(guid, owner_guid, result)) + return false; + + // cleanup bag content related item value fields (its will be filled correctly from `character_inventory`) + for (uint32 i = 0; i < GetProto()->ContainerSlots; i++) + { + SetUInt64Value(CONTAINER_FIELD_SLOT_1 + (i*2), 0); + if (m_bagslot[i]) + { + delete m_bagslot[i]; + m_bagslot[i] = NULL; + } + } + + return true; +} + +void Bag::DeleteFromDB() +{ + for (int i = 0; i < MAX_BAG_SIZE; i++) + { + if (m_bagslot[i]) + { + m_bagslot[i]->DeleteFromDB(); + } + } + + Item::DeleteFromDB(); +} + +uint32 Bag::GetFreeSlots() const +{ + uint32 ContainerSlots=GetProto()->ContainerSlots; + uint32 slots = 0; + for (uint8 i=0; i SetContainer(NULL); + + m_bagslot[slot] = NULL; + SetUInt64Value( CONTAINER_FIELD_SLOT_1 + (slot * 2), 0 ); +} + +void Bag::StoreItem( uint8 slot, Item *pItem, bool /*update*/ ) +{ + assert(slot < MAX_BAG_SIZE); + + if( pItem ) + { + m_bagslot[slot] = pItem; + SetUInt64Value(CONTAINER_FIELD_SLOT_1 + (slot * 2), pItem->GetGUID()); + pItem->SetUInt64Value(ITEM_FIELD_CONTAINED, GetGUID()); + pItem->SetUInt64Value( ITEM_FIELD_OWNER, GetOwnerGUID() ); + pItem->SetContainer(this); + pItem->SetSlot(slot); + } +} + +void Bag::BuildCreateUpdateBlockForPlayer( UpdateData *data, Player *target ) const +{ + Item::BuildCreateUpdateBlockForPlayer( data, target ); + + for (int i = 0; i < MAX_BAG_SIZE; i++) + { + if(m_bagslot[i]) + m_bagslot[i]->BuildCreateUpdateBlockForPlayer( data, target ); + } +} + +// If the bag is empty returns true +bool Bag::IsEmpty() const +{ + uint32 ContainerSlots=GetProto()->ContainerSlots; + for(uint32 i=0; i < ContainerSlots; i++) + if (m_bagslot[i]) return false; + + return true; +} + +uint32 Bag::GetItemCount( uint32 item, Item* eItem ) const +{ + uint32 ContainerSlots=GetProto()->ContainerSlots; + + Item *pItem; + uint32 count = 0; + for(uint32 i=0; i < ContainerSlots; i++) + { + pItem = m_bagslot[i]; + if( pItem && pItem != eItem && pItem->GetEntry() == item ) + count += pItem->GetCount(); + } + + if(eItem && eItem->GetProto()->GemProperties) + { + for(uint32 i=0; i < ContainerSlots; i++) + { + pItem = m_bagslot[i]; + if( pItem && pItem != eItem && pItem->GetProto()->Socket[0].Color ) + count += pItem->GetGemCountWithID(item); + } + } + + return count; +} + +uint8 Bag::GetSlotByItemGUID(uint64 guid) const +{ + uint32 ContainerSlots=GetProto()->ContainerSlots; + + for(uint32 i=0;iGetGUID() == guid) + return i; + } + return NULL_SLOT; +} + +// Adds an item to a bag slot +// - slot can be NULL_SLOT, in that case function searchs for a free slot +// - Return values: 0 - item not added +// 1 - item added to a free slot (and perhaps to a stack) +// 2 - item added to a stack (item should be deleted) +Item* Bag::GetItemByPos( uint8 slot ) const +{ + ItemPrototype const *pBagProto = GetProto(); + if( pBagProto ) + { + if( slot < pBagProto->ContainerSlots ) + return m_bagslot[slot]; + } + return NULL; +} diff --git a/src/game/Bag.h b/src/game/Bag.h new file mode 100644 index 00000000000..cc7ca52b338 --- /dev/null +++ b/src/game/Bag.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_BAG_H +#define MANGOS_BAG_H + +// Maximum 36 Slots ( (CONTAINER_END - CONTAINER_FIELD_SLOT_1)/2 +#define MAX_BAG_SIZE 36 // 2.0.12 + +#include "Object.h" +#include "ItemPrototype.h" +#include "Unit.h" +#include "Creature.h" +#include "Item.h" + +class Bag : public Item +{ + public: + + Bag(); + ~Bag(); + + void AddToWorld(); + void RemoveFromWorld(); + + bool Create(uint32 guidlow, uint32 itemid, Player const* owner); + + void Clear(); + void StoreItem( uint8 slot, Item *pItem, bool update ); + void RemoveItem( uint8 slot, bool update ); + + Item* GetItemByPos( uint8 slot ) const; + uint32 GetItemCount( uint32 item, Item* eItem = NULL ) const; + + uint8 GetSlotByItemGUID(uint64 guid) const; + bool IsEmpty() const; + uint32 GetFreeSlots() const; + + // DB operations + // overwrite virtual Item::SaveToDB + void SaveToDB(); + // overwrite virtual Item::LoadFromDB + bool LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult *result = NULL); + // overwrite virtual Item::DeleteFromDB + void DeleteFromDB(); + + void BuildCreateUpdateBlockForPlayer(UpdateData *data, Player *target) const; + + protected: + + // Bag Storage space + Item* m_bagslot[MAX_BAG_SIZE]; +}; + +inline Item* NewItemOrBag(ItemPrototype const * proto) +{ + return (proto->InventoryType == INVTYPE_BAG) ? new Bag : new Item; +} +#endif diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp new file mode 100644 index 00000000000..589b4175049 --- /dev/null +++ b/src/game/BattleGround.cpp @@ -0,0 +1,1153 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Object.h" +#include "Player.h" +#include "BattleGround.h" +#include "Creature.h" +#include "MapManager.h" +#include "Language.h" +#include "Chat.h" +#include "SpellAuras.h" +#include "World.h" +#include "Util.h" + +BattleGround::BattleGround() +{ + m_TypeID = 0; + m_InstanceID = 0; + m_Status = 0; + m_EndTime = 0; + m_LastResurrectTime = 0; + m_Queue_type = MAX_BATTLEGROUND_QUEUES; + m_InvitedAlliance = 0; + m_InvitedHorde = 0; + m_ArenaType = 0; + m_IsArena = false; + m_Winner = 2; + m_StartTime = 0; + m_Events = 0; + m_IsRated = false; + m_BuffChange = false; + m_Name = ""; + m_LevelMin = 0; + m_LevelMax = 0; + + m_MaxPlayersPerTeam = 0; + m_MaxPlayers = 0; + m_MinPlayersPerTeam = 0; + m_MinPlayers = 0; + + m_MapId = 0; + + m_TeamStartLocX[BG_TEAM_ALLIANCE] = 0; + m_TeamStartLocX[BG_TEAM_HORDE] = 0; + + m_TeamStartLocY[BG_TEAM_ALLIANCE] = 0; + m_TeamStartLocY[BG_TEAM_HORDE] = 0; + + m_TeamStartLocZ[BG_TEAM_ALLIANCE] = 0; + m_TeamStartLocZ[BG_TEAM_HORDE] = 0; + + m_TeamStartLocO[BG_TEAM_ALLIANCE] = 0; + m_TeamStartLocO[BG_TEAM_HORDE] = 0; + + m_BgRaids[BG_TEAM_ALLIANCE] = NULL; + m_BgRaids[BG_TEAM_HORDE] = NULL; + + m_PlayersCount[BG_TEAM_ALLIANCE] = 0; + m_PlayersCount[BG_TEAM_HORDE] = 0; +} + +BattleGround::~BattleGround() +{ + +} + +void BattleGround::Update(time_t diff) +{ + + if(!GetPlayersSize() && !GetRemovedPlayersSize() && !GetReviveQueueSize()) + //BG is empty + return; + + WorldPacket data; + + if(GetRemovedPlayersSize()) + { + for(std::map::iterator itr = m_RemovedPlayers.begin(); itr != m_RemovedPlayers.end(); ++itr) + { + Player *plr = objmgr.GetPlayer(itr->first); + switch(itr->second) + { + //following code is handled by event: + /*case 0: + sBattleGroundMgr.m_BattleGroundQueues[GetTypeID()].RemovePlayer(itr->first); + //RemovePlayerFromQueue(itr->first); + if(plr) + { + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(m_TypeID), STATUS_NONE, 0, 0); + plr->GetSession()->SendPacket(&data); + } + break;*/ + case 1: // currently in bg and was removed from bg + if(plr) + RemovePlayerAtLeave(itr->first, true, true); + else + RemovePlayerAtLeave(itr->first, false, false); + break; + case 2: // revive queue + RemovePlayerFromResurrectQueue(itr->first); + break; + default: + sLog.outError("BattleGround: Unknown remove player case!"); + } + } + m_RemovedPlayers.clear(); + } + + // this code isn't efficient and its idea isn't implemented yet + /* offline players are removed from battleground in worldsession::LogoutPlayer() + // remove offline players from bg after ~5 minutes + if(GetPlayersSize()) + { + for(std::map::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + { + Player *plr = objmgr.GetPlayer(itr->first); + itr->second.LastOnlineTime += diff; + + if(plr) + itr->second.LastOnlineTime = 0; // update last online time + else + if(itr->second.LastOnlineTime >= MAX_OFFLINE_TIME) // 5 minutes + m_RemovedPlayers[itr->first] = 1; // add to remove list (BG) + } + }*/ + + m_LastResurrectTime += diff; + if (m_LastResurrectTime >= RESURRECTION_INTERVAL) + { + if(GetReviveQueueSize()) + { + for(std::map >::iterator itr = m_ReviveQueue.begin(); itr != m_ReviveQueue.end(); ++itr) + { + Creature *sh = NULL; + for(std::vector::iterator itr2 = (itr->second).begin(); itr2 != (itr->second).end(); ++itr2) + { + Player *plr = objmgr.GetPlayer(*itr2); + if(!plr) + continue; + + if (!sh) + { + sh = ObjectAccessor::GetCreature(*plr, itr->first); + // only for visual effect + if (sh) + sh->CastSpell(sh, SPELL_SPIRIT_HEAL, true); // Spirit Heal, effect 117 + } + + plr->CastSpell(plr, SPELL_RESURRECTION_VISUAL, true); // Resurrection visual + m_ResurrectQueue.push_back(*itr2); + } + (itr->second).clear(); + } + + m_ReviveQueue.clear(); + m_LastResurrectTime = 0; + } + else + // queue is clear and time passed, just update last resurrection time + m_LastResurrectTime = 0; + } + else if (m_LastResurrectTime > 500) // Resurrect players only half a second later, to see spirit heal effect on NPC + { + for(std::vector::iterator itr = m_ResurrectQueue.begin(); itr != m_ResurrectQueue.end(); ++itr) + { + Player *plr = objmgr.GetPlayer(*itr); + if(!plr) + continue; + plr->ResurrectPlayer(1.0f); + plr->CastSpell(plr, SPELL_SPIRIT_HEAL_MANA, true); + ObjectAccessor::Instance().ConvertCorpseForPlayer(*itr); + } + m_ResurrectQueue.clear(); + } + + if(GetStatus() == STATUS_WAIT_LEAVE) + { + // remove all players from battleground after 2 minutes + m_EndTime += diff; + if(m_EndTime >= TIME_TO_AUTOREMOVE) // 2 minutes + { + for(std::map::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + { + m_RemovedPlayers[itr->first] = 1; // add to remove list (BG) + } + // do not change any battleground's private variables + } + } +} + +void BattleGround::SetTeamStartLoc(uint32 TeamID, float X, float Y, float Z, float O) +{ + uint8 idx = GetTeamIndexByTeamId(TeamID); + m_TeamStartLocX[idx] = X; + m_TeamStartLocY[idx] = Y; + m_TeamStartLocZ[idx] = Z; + m_TeamStartLocO[idx] = O; +} + +void BattleGround::SendPacketToAll(WorldPacket *packet) +{ + for(std::map::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + { + Player *plr = objmgr.GetPlayer(itr->first); + if(plr) + plr->GetSession()->SendPacket(packet); + else + sLog.outError("BattleGround: Player " I64FMTD " not found!", itr->first); + } +} + +void BattleGround::SendPacketToTeam(uint32 TeamID, WorldPacket *packet, Player *sender, bool self) +{ + for(std::map::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + { + Player *plr = objmgr.GetPlayer(itr->first); + + if(!plr) + { + sLog.outError("BattleGround: Player " I64FMTD " not found!", itr->first); + continue; + } + + if(!self && sender == plr) + continue; + + if(plr->GetTeam() == TeamID) + plr->GetSession()->SendPacket(packet); + } +} + +void BattleGround::PlaySoundToAll(uint32 SoundID) +{ + WorldPacket data; + sBattleGroundMgr.BuildPlaySoundPacket(&data, SoundID); + SendPacketToAll(&data); +} + +void BattleGround::PlaySoundToTeam(uint32 SoundID, uint32 TeamID) +{ + WorldPacket data; + + for(std::map::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + { + Player *plr = objmgr.GetPlayer(itr->first); + + if(!plr) + { + sLog.outError("BattleGround: Player " I64FMTD " not found!", itr->first); + continue; + } + + if(plr->GetTeam() == TeamID) + { + sBattleGroundMgr.BuildPlaySoundPacket(&data, SoundID); + plr->GetSession()->SendPacket(&data); + } + } +} + +void BattleGround::CastSpellOnTeam(uint32 SpellID, uint32 TeamID) +{ + for(std::map::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + { + Player *plr = objmgr.GetPlayer(itr->first); + + if(!plr) + { + sLog.outError("BattleGround: Player " I64FMTD " not found!", itr->first); + continue; + } + + if(plr->GetTeam() == TeamID) + plr->CastSpell(plr, SpellID, true); + } +} + +void BattleGround::RewardHonorToTeam(uint32 Honor, uint32 TeamID) +{ + for(std::map::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + { + Player *plr = objmgr.GetPlayer(itr->first); + + if(!plr) + { + sLog.outError("BattleGround: Player " I64FMTD " not found!", itr->first); + continue; + } + + if(plr->GetTeam() == TeamID) + UpdatePlayerScore(plr, SCORE_BONUS_HONOR, Honor); + } +} + +void BattleGround::RewardReputationToTeam(uint32 faction_id, uint32 Reputation, uint32 TeamID) +{ + FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id); + + if(!factionEntry) + return; + + for(std::map::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + { + Player *plr = objmgr.GetPlayer(itr->first); + + if(!plr) + { + sLog.outError("BattleGround: Player " I64FMTD " not found!", itr->first); + continue; + } + + if(plr->GetTeam() == TeamID) + plr->ModifyFactionReputation(factionEntry, Reputation); + } +} + +void BattleGround::UpdateWorldState(uint32 Field, uint32 Value) +{ + WorldPacket data; + sBattleGroundMgr.BuildUpdateWorldStatePacket(&data, Field, Value); + SendPacketToAll(&data); +} + +void BattleGround::UpdateWorldStateForPlayer(uint32 Field, uint32 Value, Player *Source) +{ + WorldPacket data; + sBattleGroundMgr.BuildUpdateWorldStatePacket(&data, Field, Value); + Source->GetSession()->SendPacket(&data); +} + +void BattleGround::EndBattleGround(uint32 winner) +{ + WorldPacket data; + Player *Source = NULL; + const char *winmsg = ""; + + if(winner == ALLIANCE) + { + winmsg = GetMangosString(LANG_BG_A_WINS); + + PlaySoundToAll(SOUND_ALLIANCE_WINS); // alliance wins sound + + SetWinner(WINNER_ALLIANCE); + } + else + { + winmsg = GetMangosString(LANG_BG_H_WINS); + + PlaySoundToAll(SOUND_HORDE_WINS); // horde wins sound + + SetWinner(WINNER_HORDE); + } + + SetStatus(STATUS_WAIT_LEAVE); + m_EndTime = 0; + + for(std::map::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + { + Player *plr = objmgr.GetPlayer(itr->first); + if(!plr) + { + sLog.outError("BattleGround: Player " I64FMTD " not found!", itr->first); + continue; + } + + if(!plr->isAlive()) + { + plr->ResurrectPlayer(1.0f); + plr->SpawnCorpseBones(); + } + + if(plr->GetTeam() == winner) + { + if(!Source) + Source = plr; + RewardMark(plr,ITEM_WINNER_COUNT); + UpdatePlayerScore(plr, SCORE_BONUS_HONOR, 20); + RewardQuest(plr); + } + else + { + RewardMark(plr,ITEM_LOSER_COUNT); + } + + plr->CombatStopWithPets(true); + + BlockMovement(plr); + + sBattleGroundMgr.BuildPvpLogDataPacket(&data, this); + plr->GetSession()->SendPacket(&data); + + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(m_TypeID), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime()); + plr->GetSession()->SendPacket(&data); + } + + if(Source) + { + ChatHandler(Source).FillMessageData(&data, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, Source->GetGUID(), winmsg); + SendPacketToAll(&data); + } +} + +uint32 BattleGround::GetBattlemasterEntry() const +{ + switch(GetTypeID()) + { + case BATTLEGROUND_AV: return 15972; + case BATTLEGROUND_WS: return 14623; + case BATTLEGROUND_AB: return 14879; + case BATTLEGROUND_EY: return 22516; + case BATTLEGROUND_NA: return 20200; + default: return 0; + } +} + +void BattleGround::RewardMark(Player *plr,uint32 count) +{ + // 'Inactive' this aura prevents the player from gaining honor points and battleground tokens + if(plr->GetDummyAura(SPELL_AURA_PLAYER_INACTIVE)) + return; + + BattleGroundMarks mark; + bool IsSpell; + switch(GetTypeID()) + { + case BATTLEGROUND_AV: + IsSpell = true; + if(count == ITEM_WINNER_COUNT) + mark = SPELL_AV_MARK_WINNER; + else + mark = SPELL_AV_MARK_LOSER; + break; + case BATTLEGROUND_WS: + IsSpell = true; + if(count == ITEM_WINNER_COUNT) + mark = SPELL_WS_MARK_WINNER; + else + mark = SPELL_WS_MARK_LOSER; + break; + case BATTLEGROUND_AB: + IsSpell = true; + if(count == ITEM_WINNER_COUNT) + mark = SPELL_AB_MARK_WINNER; + else + mark = SPELL_AB_MARK_LOSER; + break; + case BATTLEGROUND_EY: + IsSpell = false; + mark = ITEM_EY_MARK_OF_HONOR; + break; + default: + return; + } + + if(IsSpell) + plr->CastSpell(plr, mark, true); + else if ( objmgr.GetItemPrototype( mark ) ) + { + ItemPosCountVec dest; + uint32 no_space_count = 0; + uint8 msg = plr->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, mark, count, &no_space_count ); + if( msg != EQUIP_ERR_OK ) // convert to possible store amount + count -= no_space_count; + + if( count != 0 && !dest.empty()) // can add some + if(Item* item = plr->StoreNewItem( dest, mark, true, 0)) + plr->SendNewItem(item,count,false,true); + + if(no_space_count > 0) + SendRewardMarkByMail(plr,mark,no_space_count); + } +} + +void BattleGround::SendRewardMarkByMail(Player *plr,uint32 mark, uint32 count) +{ + uint32 bmEntry = GetBattlemasterEntry(); + if(!bmEntry) + return; + + ItemPrototype const* markProto = objmgr.GetItemPrototype(mark); + if(!markProto) + return; + + if(Item* markItem = Item::CreateItem(mark,count,plr)) + { + // save new item before send + markItem->SaveToDB(); // save for prevent lost at next mail load, if send fail then item will deleted + + // item + MailItemsInfo mi; + mi.AddItem(markItem->GetGUIDLow(), markItem->GetEntry(), markItem); + + // subject: item name + std::string subject = markProto->Name1; + int loc_idx = plr->GetSession()->GetSessionDbLocaleIndex(); + if ( loc_idx >= 0 ) + if(ItemLocale const *il = objmgr.GetItemLocale(markProto->ItemId)) + if (il->Name.size() > loc_idx && !il->Name[loc_idx].empty()) + subject = il->Name[loc_idx]; + + // text + std::string textFormat = plr->GetSession()->GetMangosString(LANG_BG_MARK_BY_MAIL); + char textBuf[300]; + snprintf(textBuf,300,textFormat.c_str(),GetName(),GetName()); + uint32 itemTextId = objmgr.CreateItemText( textBuf ); + + WorldSession::SendMailTo(plr, MAIL_CREATURE, MAIL_STATIONERY_NORMAL, bmEntry, plr->GetGUIDLow(), subject, itemTextId , &mi, 0, 0, MAIL_CHECK_MASK_NONE); + } +} + +void BattleGround::RewardQuest(Player *plr) +{ + // 'Inactive' this aura prevents the player from gaining honor points and battleground tokens + if(plr->GetDummyAura(SPELL_AURA_PLAYER_INACTIVE)) + return; + + uint32 quest; + switch(GetTypeID()) + { + case BATTLEGROUND_AV: + quest = SPELL_AV_QUEST_REWARD; + break; + case BATTLEGROUND_WS: + quest = SPELL_WS_QUEST_REWARD; + break; + case BATTLEGROUND_AB: + quest = SPELL_AB_QUEST_REWARD; + break; + case BATTLEGROUND_EY: + quest = SPELL_EY_QUEST_REWARD; + break; + default: + return; + } + + plr->CastSpell(plr, quest, true); +} + +void BattleGround::BlockMovement(Player *plr) +{ + plr->SetClientControl(plr, 0); // movement disabled NOTE: the effect will be automatically removed by client when the player is teleported from the battleground, so no need to send with uint8(1) in RemovePlayerAtLeave() +} + +void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPacket) +{ + // Remove from lists/maps + std::map::iterator itr = m_Players.find(guid); + if(itr != m_Players.end()) + { + UpdatePlayersCountByTeam(itr->second.Team, true); // -1 player + m_Players.erase(itr); + } + + std::map::iterator itr2 = m_PlayerScores.find(guid); + if(itr2 != m_PlayerScores.end()) + { + delete itr2->second; // delete player's score + m_PlayerScores.erase(itr2); + } + + RemovePlayerFromResurrectQueue(guid); + + Player *plr = objmgr.GetPlayer(guid); + + if(plr && !plr->isAlive()) // resurrect on exit + { + plr->ResurrectPlayer(1.0f); + plr->SpawnCorpseBones(); + } + + RemovePlayer(plr, guid); // BG subclass specific code + + if(plr) + { + plr->ClearAfkReports(); + + if(isArena()) + { + if(!sWorld.IsFFAPvPRealm()) + plr->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP); + } + + WorldPacket data; + if(SendPacket) + { + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(m_TypeID), STATUS_NONE, 0, 0); + plr->GetSession()->SendPacket(&data); + } + + // this call is important, because player, when joins to battleground, this method is not called, so it must be called when leaving bg + plr->RemoveBattleGroundQueueId(m_TypeID); + + DecreaseInvitedCount(plr->GetTeam()); + //we should update battleground queue, but only if bg isn't ending + if (GetQueueType() < MAX_BATTLEGROUND_QUEUES) + sBattleGroundMgr.m_BattleGroundQueues[GetTypeID()].Update(GetTypeID(), GetQueueType()); + + if(!plr->GetBattleGroundId()) + return; + + Group * group = plr->GetGroup(); + + // remove from raid group if exist + if(group && group == GetBgRaid(plr->GetTeam())) + { + if(!group->RemoveMember(guid, 0)) // group was disbanded + { + SetBgRaid(plr->GetTeam(), NULL); + delete group; + } + } + + // Do next only if found in battleground + plr->SetBattleGroundId(0); // We're not in BG. + + // Let others know + sBattleGroundMgr.BuildPlayerLeftBattleGroundPacket(&data, plr); + SendPacketToTeam(plr->GetTeam(), &data, plr, false); + + if(Transport) + { + plr->TeleportTo(plr->GetBattleGroundEntryPointMap(), plr->GetBattleGroundEntryPointX(), plr->GetBattleGroundEntryPointY(), plr->GetBattleGroundEntryPointZ(), plr->GetBattleGroundEntryPointO()); + //sLog.outDetail("BATTLEGROUND: Sending %s to %f,%f,%f,%f", pl->GetName(), x,y,z,O); + } + + // Log + sLog.outDetail("BATTLEGROUND: Removed player %s from BattleGround.", plr->GetName()); + } + + /// there will be code which will add battleground to BGFreeSlotQueue , when battleground instance will exist + // we always should check if BG is in that queue before adding.. + + if(!GetPlayersSize()) + { + Reset(); + } +} + +// this method is called when no players remains in battleground +void BattleGround::Reset() +{ + SetQueueType(MAX_BATTLEGROUND_QUEUES); + SetWinner(WINNER_NONE); + SetStatus(STATUS_WAIT_QUEUE); + SetStartTime(0); + SetEndTime(0); + SetLastResurrectTime(0); + + m_Events = 0; + + if (m_InvitedAlliance > 0 || m_InvitedHorde > 0) + sLog.outError("BattleGround system ERROR: bad counter, m_InvitedAlliance: %d, m_InvitedHorde: %d", m_InvitedAlliance, m_InvitedHorde); + + m_InvitedAlliance = 0; + m_InvitedHorde = 0; + + m_Players.clear(); + m_PlayerScores.clear(); + + // reset BGSubclass + this->ResetBGSubclass(); +} + +void BattleGround::StartBattleGround() +{ + ///this method should spawn spirit guides and so on + SetStartTime(0); + + SetLastResurrectTime(0); +} + +void BattleGround::AddPlayer(Player *plr) +{ + // score struct must be created in inherited class + + uint64 guid = plr->GetGUID(); + uint32 team = plr->GetBGTeam(); + + BattleGroundPlayer bp; + bp.LastOnlineTime = 0; + bp.Team = team; + + // Add to list/maps + m_Players[guid] = bp; + + UpdatePlayersCountByTeam(team, false); // +1 player + + WorldPacket data; + sBattleGroundMgr.BuildPlayerJoinedBattleGroundPacket(&data, plr); + SendPacketToTeam(team, &data, plr, false); + + if(isArena()) + { + plr->RemoveArenaSpellCooldowns(); + //plr->RemoveArenaAuras(); + plr->RemoveAllEnchantments(TEMP_ENCHANTMENT_SLOT); + if(team == ALLIANCE && plr->GetTeam() == ALLIANCE) + plr->CastSpell(plr,SPELL_ALLIANCE_GOLD_FLAG,true); + else if(team == HORDE && plr->GetTeam() == ALLIANCE) + plr->CastSpell(plr,SPELL_ALLIANCE_GREEN_FLAG,true); + else if(team == ALLIANCE && plr->GetTeam() == HORDE) + plr->CastSpell(plr,SPELL_HORDE_GOLD_FLAG,true); + else + plr->CastSpell(plr,SPELL_HORDE_GREEN_FLAG,true); + plr->DestroyConjuredItems(true); + + if(GetStatus() == STATUS_WAIT_JOIN) // not started yet + { + plr->CastSpell(plr, SPELL_ARENA_PREPARATION, true); + + plr->SetHealth(plr->GetMaxHealth()); + plr->SetPower(POWER_MANA, plr->GetMaxPower(POWER_MANA)); + } + } + else + { + if(GetStatus() == STATUS_WAIT_JOIN) // not started yet + plr->CastSpell(plr, SPELL_PREPARATION, true); // reduces all mana cost of spells. + } + + if(isArena()) + plr->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP); + + // Log + sLog.outDetail("BATTLEGROUND: Player %s joined the battle.", plr->GetName()); +} + +/* This method should be called only once ... it adds pointer to queue */ +void BattleGround::AddToBGFreeSlotQueue() +{ + sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].push_front(this); +} + +/* This method removes this battleground from free queue - it must be called when deleting battleground - not used now*/ +void BattleGround::RemoveFromBGFreeSlotQueue() +{ + /* uncomment this code when battlegrounds will work like instances + for (std::deque::iterator itr = sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].begin(); itr != sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].end(); ++itr) + { + if ((*itr)->GetInstanceID() == m_InstanceID) + { + sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].erase(itr); + return; + } + }*/ +} + +/* +this method should decide, if we can invite new player of certain team to BG, it is based on BATTLEGROUND_STATUS +*/ +bool BattleGround::HasFreeSlotsForTeam(uint32 Team) const +{ + //if BG is starting ... invite anyone: + if (GetStatus() == STATUS_WAIT_JOIN) + return GetInvitedCount(Team) < GetMaxPlayersPerTeam(); + //if BG is already started .. do not allow to join too much players of one faction + uint32 otherTeam; + if (Team == ALLIANCE) + otherTeam = GetInvitedCount(HORDE); + else + otherTeam = GetInvitedCount(ALLIANCE); + if (GetStatus() == STATUS_IN_PROGRESS) + return (GetInvitedCount(Team) <= otherTeam && GetInvitedCount(Team) < GetMaxPlayersPerTeam()); + + return false; +} + +/* this method isn't called already, it will be useful when more battlegrounds of one type will be available */ +bool BattleGround::HasFreeSlots() const +{ + return GetPlayersSize() < GetMaxPlayers(); +} + +void BattleGround::UpdatePlayerScore(Player *Source, uint32 type, uint32 value) +{ + //this procedure is called from virtual function implemented in bg subclass + std::map::iterator itr = m_PlayerScores.find(Source->GetGUID()); + + if(itr == m_PlayerScores.end()) // player not found... + return; + + switch(type) + { + case SCORE_KILLING_BLOWS: // Killing blows + itr->second->KillingBlows += value; + break; + case SCORE_DEATHS: // Deaths + itr->second->Deaths += value; + break; + case SCORE_HONORABLE_KILLS: // Honorable kills + itr->second->HonorableKills += value; + break; + case SCORE_BONUS_HONOR: // Honor bonus + // reward honor instantly + if(Source->RewardHonor(NULL, 1, value)) + itr->second->BonusHonor += value; + break; + //used only in EY, but in MSG_PVP_LOG_DATA opcode + case SCORE_DAMAGE_DONE: // Damage Done + itr->second->DamageDone += value; + break; + case SCORE_HEALING_DONE: // Healing Done + itr->second->HealingDone += value; + break; + default: + sLog.outError("BattleGround: Unknown player score type %u", type); + break; + } +} + +void BattleGround::AddPlayerToResurrectQueue(uint64 npc_guid, uint64 player_guid) +{ + m_ReviveQueue[npc_guid].push_back(player_guid); + + Player *plr = objmgr.GetPlayer(player_guid); + if(!plr) + return; + + plr->CastSpell(plr, SPELL_WAITING_FOR_RESURRECT, true); + SpellEntry const *spellInfo = sSpellStore.LookupEntry( SPELL_WAITING_FOR_RESURRECT ); + if(spellInfo) + { + Aura *Aur = CreateAura(spellInfo, 0, NULL, plr); + plr->AddAura(Aur); + } +} + +void BattleGround::RemovePlayerFromResurrectQueue(uint64 player_guid) +{ + for(std::map >::iterator itr = m_ReviveQueue.begin(); itr != m_ReviveQueue.end(); ++itr) + { + for(std::vector::iterator itr2 =(itr->second).begin(); itr2 != (itr->second).end(); ++itr2) + { + if(*itr2 == player_guid) + { + (itr->second).erase(itr2); + + Player *plr = objmgr.GetPlayer(player_guid); + if(!plr) + return; + + plr->RemoveAurasDueToSpell(SPELL_WAITING_FOR_RESURRECT); + + return; + } + } + } +} + +bool BattleGround::AddObject(uint32 type, uint32 entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime) +{ + GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(entry); + if(!goinfo) + { + sLog.outErrorDb("Gameobject template %u not found in database! BattleGround not created!", entry); + return false; + } + + uint32 guid = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT); + + GameObjectData& data = objmgr.NewGOData(guid); + + data.id = entry; + data.mapid = GetMapId(); + data.posX = x; + data.posY = y; + data.posZ = z; + data.orientation = o; + data.rotation0 = rotation0; + data.rotation1 = rotation1; + data.rotation2 = rotation2; + data.rotation3 = rotation3; + data.spawntimesecs = respawnTime; + data.animprogress = 100; + data.go_state = 1; + data.spawnMask = 1; + objmgr.AddGameobjectToGrid(guid, &data); + + m_BgObjects[type] = MAKE_NEW_GUID(guid, entry, HIGHGUID_GAMEOBJECT); + + return true; +} + +//some doors aren't despawned so we cannot handle their closing in gameobject::update() +//it would be nice to correctly implement GO_ACTIVATED state and open/close doors in gameobject code +void BattleGround::DoorClose(uint32 type) +{ + GameObject *obj = HashMapHolder::Find(m_BgObjects[type]); + if(obj) + { + //if doors are open, close it + if( obj->getLootState() == GO_ACTIVATED && !obj->GetGoState() ) + { + //change state to allow door to be closed + obj->SetLootState(GO_READY); + obj->UseDoorOrButton(RESPAWN_ONE_DAY); + } + } + else + { + sLog.outError("BattleGround: Door object not found (cannot close doors)"); + } +} + +void BattleGround::DoorOpen(uint32 type) +{ + GameObject *obj = HashMapHolder::Find(m_BgObjects[type]); + if(obj) + { + //change state to be sure they will be opened + obj->SetLootState(GO_READY); + obj->UseDoorOrButton(RESPAWN_ONE_DAY); + } + else + { + sLog.outError("BattleGround: Door object not found! - doors will be closed."); + } +} + +void BattleGround::SpawnBGObject(uint32 type, uint32 respawntime) +{ + if( respawntime == 0 ) + { + GameObject *obj = HashMapHolder::Find(m_BgObjects[type]); + if(obj) + { + //we need to change state from GO_JUST_DEACTIVATED to GO_READY in case battleground is starting again + if( obj->getLootState() == GO_JUST_DEACTIVATED ) + obj->SetLootState(GO_READY); + obj->Respawn(); + } + else + objmgr.SaveGORespawnTime(GUID_LOPART(m_BgObjects[type]), 0, 0); + } + else + { + GameObject *obj = HashMapHolder::Find(m_BgObjects[type]); + if(obj) + { + obj->SetRespawnTime(respawntime); + obj->SetLootState(GO_JUST_DEACTIVATED); + } + else + objmgr.SaveGORespawnTime(GUID_LOPART(m_BgObjects[type]), 0, time(NULL) + respawntime); + } +} + +Creature* BattleGround::AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o) +{ + // note: this should normally be FindMap + // but it's a hack to allow the battlegrounds to initialize at server startup + Map * map = MapManager::Instance().GetMap(GetMapId(), 0); + if(!map) return NULL; + + Creature* pCreature = new Creature; + if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, entry, teamval)) + { + sLog.outError("Can't create creature entry: %u",entry); + delete pCreature; + return NULL; + } + + pCreature->Relocate(x, y, z, o); + + if(!pCreature->IsPositionValid()) + { + sLog.outError("ERROR: Creature (guidlow %d, entry %d) not added to battleground. Suggested coordinates isn't valid (X: %f Y: %f)",pCreature->GetGUIDLow(),pCreature->GetEntry(),pCreature->GetPositionX(),pCreature->GetPositionY()); + return NULL; + } + + pCreature->AIM_Initialize(); + + //pCreature->SetDungeonDifficulty(0); + + map->Add(pCreature); + m_BgCreatures[type] = pCreature->GetGUID(); + return pCreature; +} + +bool BattleGround::DelCreature(uint32 type) +{ + Creature *cr = HashMapHolder::Find(m_BgCreatures[type]); + if(!cr) + { + sLog.outError("Can't find creature guid: %u",m_BgCreatures[type]); + return false; + } + cr->CleanupsBeforeDelete(); + cr->AddObjectToRemoveList(); + m_BgCreatures[type] = 0; + return true; +} + +bool BattleGround::DelObject(uint32 type) +{ + GameObject *obj = HashMapHolder::Find(m_BgObjects[type]); + if(!obj) + { + sLog.outError("Can't find gobject guid: %u",m_BgObjects[type]); + return false; + } + obj->SetRespawnTime(0); // not save respawn time + obj->Delete(); + m_BgObjects[type] = 0; + return true; +} + +bool BattleGround::AddSpiritGuide(uint32 type, float x, float y, float z, float o, uint32 team) +{ + uint32 entry = 0; + + if(team == ALLIANCE) + entry = 13116; + else + entry = 13117; + + Creature* pCreature = AddCreature(entry,type,team,x,y,z,o); + if(!pCreature) + { + sLog.outError("Can't create Spirit guide. BattleGround not created!"); + this->EndNow(); + return false; + } + + pCreature->setDeathState(DEAD); + + pCreature->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, pCreature->GetGUID()); + // aura + pCreature->SetUInt32Value(UNIT_FIELD_AURA, SPELL_SPIRIT_HEAL_CHANNEL); + pCreature->SetUInt32Value(UNIT_FIELD_AURAFLAGS, 0x00000009); + pCreature->SetUInt32Value(UNIT_FIELD_AURALEVELS, 0x0000003C); + pCreature->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS, 0x000000FF); + // casting visual effect + pCreature->SetUInt32Value(UNIT_CHANNEL_SPELL, SPELL_SPIRIT_HEAL_CHANNEL); + // correct cast speed + pCreature->SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0f); + + //pCreature->CastSpell(pCreature, SPELL_SPIRIT_HEAL_CHANNEL, true); + + return true; +} + +void BattleGround::SendMessageToAll(char const* text) +{ + WorldPacket data; + ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, text, NULL); + SendPacketToAll(&data); +} + +void BattleGround::SendMessageToAll(int32 entry) +{ + char const* text = GetMangosString(entry); + WorldPacket data; + ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, text, NULL); + SendPacketToAll(&data); +} + +void BattleGround::EndNow() +{ + SetStatus(STATUS_WAIT_LEAVE); + SetEndTime(TIME_TO_AUTOREMOVE); +} + +// Battleground messages are localized using the dbc lang, they are not client language dependent +const char *BattleGround::GetMangosString(int32 entry) +{ + // FIXME: now we have different DBC locales and need localized message for each target client + return objmgr.GetMangosStringForDBCLocale(entry); +} + +/* +important notice: +buffs aren't spawned/despawned when players captures anything +buffs are in their positions when battleground starts +*/ +void BattleGround::HandleTriggerBuff(uint64 const& go_guid) +{ + GameObject *obj = HashMapHolder::Find(go_guid); + if(!obj || obj->GetGoType() != GAMEOBJECT_TYPE_TRAP || !obj->isSpawned()) + return; + + //change buff type, when buff is used: + int32 index = m_BgObjects.size() - 1; + while (index >= 0 && m_BgObjects[index] != go_guid) + index--; + if (index < 0) + { + sLog.outError("BattleGround (Type: %u) has buff gameobject (Guid: %u Entry: %u Type:%u) but it hasn't that object in its internal data",GetTypeID(),GUID_LOPART(go_guid),obj->GetEntry(),obj->GetGoType()); + return; + } + + //randomly select new buff + uint8 buff = urand(0, 2); + uint32 entry = obj->GetEntry(); + if( m_BuffChange && entry != Buff_Entries[buff] ) + { + //despawn current buff + SpawnBGObject(index, RESPAWN_ONE_DAY); + //set index for new one + for (uint8 currBuffTypeIndex = 0; currBuffTypeIndex < 3; ++currBuffTypeIndex) + if( entry == Buff_Entries[currBuffTypeIndex] ) + { + index -= currBuffTypeIndex; + index += buff; + } + } + + SpawnBGObject(index, BUFF_RESPAWN_TIME); +} + +void BattleGround::HandleKillPlayer( Player *player, Player *killer ) +{ + //keep in mind that for arena this will have to be changed a bit + + // add +1 deaths + UpdatePlayerScore(player, SCORE_DEATHS, 1); + + // add +1 kills to group and +1 killing_blows to killer + if( killer ) + { + UpdatePlayerScore(killer, SCORE_HONORABLE_KILLS, 1); + UpdatePlayerScore(killer, SCORE_KILLING_BLOWS, 1); + + for(std::map::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + { + Player *plr = objmgr.GetPlayer(itr->first); + + if(!plr || plr == killer) + continue; + + if( plr->GetTeam() == killer->GetTeam() && plr->IsAtGroupRewardDistance(player) ) + UpdatePlayerScore(plr, SCORE_HONORABLE_KILLS, 1); + } + } + + // to be able to remove insignia + player->SetFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE ); +} diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h new file mode 100644 index 00000000000..154e5b02416 --- /dev/null +++ b/src/game/BattleGround.h @@ -0,0 +1,486 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __BATTLEGROUND_H +#define __BATTLEGROUND_H + +#include "Common.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Opcodes.h" +#include "ObjectMgr.h" +#include "BattleGroundMgr.h" +#include "SharedDefines.h" + +enum BattleGroundSounds +{ + SOUND_HORDE_WINS = 8454, + SOUND_ALLIANCE_WINS = 8455, + SOUND_BG_START = 3439 +}; + +enum BattleGroundQuests +{ + SPELL_WS_QUEST_REWARD = 43483, + SPELL_AB_QUEST_REWARD = 43484, + SPELL_AV_QUEST_REWARD = 43475, + SPELL_AV_QUEST_KILLED_BOSS = 23658, + SPELL_EY_QUEST_REWARD = 43477, + SPELL_AB_QUEST_REWARD_4_BASES = 24061, + SPELL_AB_QUEST_REWARD_5_BASES = 24064 +}; + +enum BattleGroundMarks +{ + SPELL_WS_MARK_LOSER = 24950, + SPELL_WS_MARK_WINNER = 24951, + SPELL_AB_MARK_LOSER = 24952, + SPELL_AB_MARK_WINNER = 24953, + SPELL_AV_MARK_LOSER = 24954, + SPELL_AV_MARK_WINNER = 24955, + ITEM_EY_MARK_OF_HONOR = 29024 +}; + +enum BattleGroundMarksCount +{ + ITEM_WINNER_COUNT = 3, + ITEM_LOSER_COUNT = 1 +}; + +enum BattleGroundSpells +{ + SPELL_WAITING_FOR_RESURRECT = 2584, // Waiting to Resurrect + SPELL_SPIRIT_HEAL_CHANNEL = 22011, // Spirit Heal Channel + SPELL_SPIRIT_HEAL = 22012, // Spirit Heal + SPELL_RESURRECTION_VISUAL = 24171, // Resurrection Impact Visual + SPELL_ARENA_PREPARATION = 32727, // use this one, 32728 not correct + SPELL_ALLIANCE_GOLD_FLAG = 32724, + SPELL_ALLIANCE_GREEN_FLAG = 32725, + SPELL_HORDE_GOLD_FLAG = 35774, + SPELL_HORDE_GREEN_FLAG = 35775, + SPELL_PREPARATION = 44521, // Preparation + SPELL_SPIRIT_HEAL_MANA = 44535, // Spirit Heal + SPELL_RECENTLY_DROPPED_FLAG = 42792, // Recently Dropped Flag + SPELL_AURA_PLAYER_INACTIVE = 43681 // Inactive +}; + +enum BattleGroundTimeIntervals +{ + RESURRECTION_INTERVAL = 30000, // ms + REMIND_INTERVAL = 30000, // ms + INVITE_ACCEPT_WAIT_TIME = 120000, // ms + TIME_TO_AUTOREMOVE = 120000, // ms + MAX_OFFLINE_TIME = 300000, // ms + START_DELAY0 = 120000, // ms + START_DELAY1 = 60000, // ms + START_DELAY2 = 30000, // ms + START_DELAY3 = 15000, // ms used only in arena + RESPAWN_ONE_DAY = 86400, // secs + RESPAWN_IMMEDIATELY = 0, // secs + BUFF_RESPAWN_TIME = 180, // secs + BG_HONOR_SCORE_TICKS = 330 // points +}; + +enum BattleGroundBuffObjects +{ + BG_OBJECTID_SPEEDBUFF_ENTRY = 179871, + BG_OBJECTID_REGENBUFF_ENTRY = 179904, + BG_OBJECTID_BERSERKERBUFF_ENTRY = 179905 +}; + +const uint32 Buff_Entries[3] = { BG_OBJECTID_SPEEDBUFF_ENTRY, BG_OBJECTID_REGENBUFF_ENTRY, BG_OBJECTID_BERSERKERBUFF_ENTRY }; + +enum BattleGroundStatus +{ + STATUS_NONE = 0, + STATUS_WAIT_QUEUE = 1, + STATUS_WAIT_JOIN = 2, + STATUS_IN_PROGRESS = 3, + STATUS_WAIT_LEAVE = 4 // custom +}; + +struct BattleGroundPlayer +{ + uint32 LastOnlineTime; // for tracking and removing offline players from queue after 5 minutes + uint32 Team; // Player's team +}; + +struct BattleGroundObjectInfo +{ + BattleGroundObjectInfo() : object(NULL), timer(0), spellid(0) {} + + GameObject *object; + int32 timer; + uint32 spellid; +}; + +#define MAX_QUEUED_PLAYERS_MAP 7 + +enum BattleGroundTypeId +{ + BATTLEGROUND_AV = 1, + BATTLEGROUND_WS = 2, + BATTLEGROUND_AB = 3, + BATTLEGROUND_NA = 4, + BATTLEGROUND_BE = 5, + BATTLEGROUND_AA = 6, + BATTLEGROUND_EY = 7, + BATTLEGROUND_RL = 8 +}; + +enum ScoreType +{ + SCORE_KILLING_BLOWS = 1, + SCORE_DEATHS = 2, + SCORE_HONORABLE_KILLS = 3, + SCORE_BONUS_HONOR = 4, + //EY, but in MSG_PVP_LOG_DATA opcode! + SCORE_DAMAGE_DONE = 5, + SCORE_HEALING_DONE = 6, + //WS + SCORE_FLAG_CAPTURES = 7, + SCORE_FLAG_RETURNS = 8, + //AB + SCORE_BASES_ASSAULTED = 9, + SCORE_BASES_DEFENDED = 10, + //AV + SCORE_GRAVEYARDS_ASSAULTED = 11, + SCORE_GRAVEYARDS_DEFENDED = 12, + SCORE_TOWERS_ASSAULTED = 13, + SCORE_TOWERS_DEFENDED = 14, + SCORE_MINES_CAPTURED = 15, + SCORE_LEADERS_KILLED = 16, + SCORE_SECONDARY_OBJECTIVES = 17 + // TODO : implement them +}; + +enum ArenaType +{ + ARENA_TYPE_2v2 = 2, + ARENA_TYPE_3v3 = 3, + ARENA_TYPE_5v5 = 5 +}; + +enum BattleGroundType +{ + TYPE_BATTLEGROUND = 3, + TYPE_ARENA = 4 +}; + +enum BattleGroundWinner +{ + WINNER_HORDE = 0, + WINNER_ALLIANCE = 1, + WINNER_NONE = 2 +}; + +enum BattleGroundTeamId +{ + BG_TEAM_ALLIANCE = 0, + BG_TEAM_HORDE = 1 +}; + +class BattleGroundScore +{ + public: + BattleGroundScore() : KillingBlows(0), HonorableKills(0), Deaths(0), DamageDone(0), HealingDone(0), BonusHonor(0) {}; + virtual ~BattleGroundScore() //virtual destructor is used when deleting score from scores map + { + }; + uint32 KillingBlows; + uint32 Deaths; + uint32 HonorableKills; + uint32 BonusHonor; + uint32 DamageDone; + uint32 HealingDone; +}; + +/* +This class is used to: +1. Add player to battleground +2. Remove player from battleground +3. some certain cases, same for all battlegrounds +4. It has properties same for all battlegrounds +*/ +class BattleGround +{ + friend class BattleGroundMgr; + + public: + /* Construction */ + BattleGround(); + virtual ~BattleGround(); + virtual void Update(time_t diff); // must be implemented in BG subclass of BG specific update code, but must in begginning call parent version + virtual bool SetupBattleGround() // must be implemented in BG subclass + { + return true; + } + void Reset(); // resets all common properties for battlegrounds + virtual void ResetBGSubclass() // must be implemented in BG subclass + { + } + + /* Battleground */ + // Get methods: + char const* GetName() const { return m_Name; } + uint32 GetTypeID() const { return m_TypeID; } + uint32 GetQueueType() const { return m_Queue_type; } + uint32 GetInstanceID() const { return m_InstanceID; } + uint32 GetStatus() const { return m_Status; } + uint32 GetStartTime() const { return m_StartTime; } + uint32 GetEndTime() const { return m_EndTime; } + uint32 GetLastResurrectTime() const { return m_LastResurrectTime; } + uint32 GetMaxPlayers() const { return m_MaxPlayers; } + uint32 GetMinPlayers() const { return m_MinPlayers; } + + uint32 GetMinLevel() const { return m_LevelMin; } + uint32 GetMaxLevel() const { return m_LevelMax; } + + uint32 GetMaxPlayersPerTeam() const { return m_MaxPlayersPerTeam; } + uint32 GetMinPlayersPerTeam() const { return m_MinPlayersPerTeam; } + + int GetStartDelayTime() const { return m_StartDelayTime; } + uint8 GetArenaType() const { return m_ArenaType; } + uint8 GetWinner() const { return m_Winner; } + uint32 GetBattlemasterEntry() const; + + // Set methods: + void SetName(char const* Name) { m_Name = Name; } + void SetTypeID(uint32 TypeID) { m_TypeID = TypeID; } + void SetQueueType(uint32 ID) { m_Queue_type = ID; } + void SetInstanceID(uint32 InstanceID) { m_InstanceID = InstanceID; } + void SetStatus(uint32 Status) { m_Status = Status; } + void SetStartTime(uint32 Time) { m_StartTime = Time; } + void SetEndTime(uint32 Time) { m_EndTime = Time; } + void SetLastResurrectTime(uint32 Time) { m_LastResurrectTime = Time; } + void SetMaxPlayers(uint32 MaxPlayers) { m_MaxPlayers = MaxPlayers; } + void SetMinPlayers(uint32 MinPlayers) { m_MinPlayers = MinPlayers; } + void SetLevelRange(uint32 min, uint32 max) { m_LevelMin = min; m_LevelMax = max; } + void SetRated(bool state) { m_IsRated = state; } + void SetArenaType(uint8 type) { m_ArenaType = type; } + void SetArenaorBGType(bool _isArena) { m_IsArena = _isArena; } + void SetWinner(uint8 winner) { m_Winner = winner; } + + void ModifyStartDelayTime(int diff) { m_StartDelayTime -= diff; } + void SetStartDelayTime(int Time) { m_StartDelayTime = Time; } + + void SetMaxPlayersPerTeam(uint32 MaxPlayers) { m_MaxPlayersPerTeam = MaxPlayers; } + void SetMinPlayersPerTeam(uint32 MinPlayers) { m_MinPlayersPerTeam = MinPlayers; } + + void AddToBGFreeSlotQueue(); //this queue will be useful when more battlegrounds instances will be available + void RemoveFromBGFreeSlotQueue(); //this method could delete whole BG instance, if another free is available + + void DecreaseInvitedCount(uint32 team) { (team == ALLIANCE) ? --m_InvitedAlliance : --m_InvitedHorde; } + void IncreaseInvitedCount(uint32 team) { (team == ALLIANCE) ? ++m_InvitedAlliance : ++m_InvitedHorde; } + uint32 GetInvitedCount(uint32 team) const + { + if( team == ALLIANCE ) + return m_InvitedAlliance; + else + return m_InvitedHorde; + } + bool HasFreeSlotsForTeam(uint32 Team) const; + bool HasFreeSlots() const; + + bool isArena() const { return m_IsArena; } + bool isBattleGround() const { return !m_IsArena; } + bool isRated() const { return m_IsRated; } + + typedef std::map BattleGroundPlayerMap; + BattleGroundPlayerMap const& GetPlayers() const { return m_Players; } + uint32 GetPlayersSize() const { return m_Players.size(); } + uint32 GetRemovedPlayersSize() const { return m_RemovedPlayers.size(); } + + std::map::const_iterator GetPlayerScoresBegin() const { return m_PlayerScores.begin(); } + std::map::const_iterator GetPlayerScoresEnd() const { return m_PlayerScores.end(); } + uint32 GetPlayerScoresSize() const { return m_PlayerScores.size(); } + + uint32 GetReviveQueueSize() const { return m_ReviveQueue.size(); } + + void AddPlayerToResurrectQueue(uint64 npc_guid, uint64 player_guid); + void RemovePlayerFromResurrectQueue(uint64 player_guid); + + void StartBattleGround(); + + /* Location */ + void SetMapId(uint32 MapID) { m_MapId = MapID; } + uint32 GetMapId() const { return m_MapId; } + + void SetTeamStartLoc(uint32 TeamID, float X, float Y, float Z, float O); + void GetTeamStartLoc(uint32 TeamID, float &X, float &Y, float &Z, float &O) const + { + uint8 idx = GetTeamIndexByTeamId(TeamID); + X = m_TeamStartLocX[idx]; + Y = m_TeamStartLocY[idx]; + Z = m_TeamStartLocZ[idx]; + O = m_TeamStartLocO[idx]; + } + + /* Packet Transfer */ + // method that should fill worldpacket with actual world states (not yet implemented for all battlegrounds!) + virtual void FillInitialWorldStates(WorldPacket& /*data*/) {} + void SendPacketToTeam(uint32 TeamID, WorldPacket *packet, Player *sender = NULL, bool self = true); + void SendPacketToAll(WorldPacket *packet); + void PlaySoundToTeam(uint32 SoundID, uint32 TeamID); + void PlaySoundToAll(uint32 SoundID); + void CastSpellOnTeam(uint32 SpellID, uint32 TeamID); + void RewardHonorToTeam(uint32 Honor, uint32 TeamID); + void RewardReputationToTeam(uint32 faction_id, uint32 Reputation, uint32 TeamID); + void RewardMark(Player *plr,uint32 count); + void SendRewardMarkByMail(Player *plr,uint32 mark, uint32 count); + void RewardQuest(Player *plr); + void UpdateWorldState(uint32 Field, uint32 Value); + void UpdateWorldStateForPlayer(uint32 Field, uint32 Value, Player *Source); + void EndBattleGround(uint32 winner); + void BlockMovement(Player *plr); + + void SendMessageToAll(char const* text); + void SendMessageToAll(int32 entry); + + /* Raid Group */ + Group *GetBgRaid(uint32 TeamID) const { return TeamID == ALLIANCE ? m_BgRaids[BG_TEAM_ALLIANCE] : m_BgRaids[BG_TEAM_HORDE]; } + void SetBgRaid(uint32 TeamID, Group *bg_raid) + { + Group* &old_raid = TeamID == ALLIANCE ? m_BgRaids[BG_TEAM_ALLIANCE] : m_BgRaids[BG_TEAM_HORDE]; + if(old_raid) old_raid->SetBattlegroundGroup(NULL); + if(bg_raid) bg_raid->SetBattlegroundGroup(this); + old_raid = bg_raid; + } + + virtual void UpdatePlayerScore(Player *Source, uint32 type, uint32 value); + + uint8 GetTeamIndexByTeamId(uint32 Team) const { return Team == ALLIANCE ? BG_TEAM_ALLIANCE : BG_TEAM_HORDE; } + uint32 GetPlayersCountByTeam(uint32 Team) const { return m_PlayersCount[GetTeamIndexByTeamId(Team)]; } + void UpdatePlayersCountByTeam(uint32 Team, bool remove) + { + if(remove) + --m_PlayersCount[GetTeamIndexByTeamId(Team)]; + else + ++m_PlayersCount[GetTeamIndexByTeamId(Team)]; + } + + /* Triggers handle */ + // must be implemented in BG subclass + virtual void HandleAreaTrigger(Player* /*Source*/, uint32 /*Trigger*/) {} + // must be implemented in BG subclass if need AND call base class generic code + virtual void HandleKillPlayer(Player *player, Player *killer); + + /* Battleground events */ + /* these functions will return true event is possible, but false if player is bugger */ + virtual void EventPlayerDroppedFlag(Player* /*player*/) {} + virtual void EventPlayerClickedOnFlag(Player* /*player*/, GameObject* /*target_obj*/) {} + virtual void EventPlayerCapturedFlag(Player* /*player*/) {} + + /* Death related */ + virtual WorldSafeLocsEntry const* GetClosestGraveYard(float /*x*/, float /*y*/, float /*z*/, uint32 /*team*/) { return NULL; } + + virtual void AddPlayer(Player *plr); // must be implemented in BG subclass + virtual void RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPacket); + // can be extended in in BG subclass + + void HandleTriggerBuff(uint64 const& go_guid); + + // TODO: make this protected: + typedef std::vector BGObjects; + typedef std::vector BGCreatures; + BGObjects m_BgObjects; + BGCreatures m_BgCreatures; + void SpawnBGObject(uint32 type, uint32 respawntime); + bool AddObject(uint32 type, uint32 entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime = 0); + Creature* AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o); + bool DelCreature(uint32 type); + bool DelObject(uint32 type); + bool AddSpiritGuide(uint32 type, float x, float y, float z, float o, uint32 team); + + void DoorOpen(uint32 type); + void DoorClose(uint32 type); + const char *GetMangosString(int32 entry); + + protected: + //this method is called, when BG cannot spawn its own spirit guide, or something is wrong, It correctly ends BattleGround + void EndNow(); + + /* Scorekeeping */ + // Player scores + std::map m_PlayerScores; + // must be implemented in BG subclass + virtual void RemovePlayer(Player * /*player*/, uint64 /*guid*/) {} + + /* Player lists, those need to be accessible by inherited classes */ + BattleGroundPlayerMap m_Players; + // Spirit Guide guid + Player list GUIDS + std::map > m_ReviveQueue; + + /* + this is important variable used for invitation messages + */ + uint8 m_Events; + + bool m_BuffChange; + + private: + /* Battleground */ + uint32 m_TypeID; //Battleground type, defined in enum BattleGroundTypeId + uint32 m_InstanceID; //BattleGround Instance's GUID! + uint32 m_Status; + uint32 m_StartTime; + uint32 m_EndTime; + uint32 m_LastResurrectTime; + uint32 m_Queue_type; + uint8 m_ArenaType; // 2=2v2, 3=3v3, 5=5v5 + // this variable is not used .... it can be found in many other ways... but to store it in BG object instance is useless + //uint8 m_BattleGroundType; // 3=BG, 4=arena + //instead of uint8 (in previous line) is bool used + bool m_IsArena; + uint8 m_Winner; // 0=alliance, 1=horde, 2=none + int32 m_StartDelayTime; + bool m_IsRated; // is this battle rated? + char const *m_Name; + + /* Player lists */ + std::vector m_ResurrectQueue; // Player GUID + std::map m_RemovedPlayers; // uint8 is remove type (0 - bgqueue, 1 - bg, 2 - resurrect queue) + + /* Invited counters are useful for player invitation to BG - do not allow, if BG is started to one faction to have 2 more players than another faction */ + /* Invited counters will be changed only when removing already invited player from queue, removing player from battleground and inviting player to BG */ + /* Invited players counters*/ + uint32 m_InvitedAlliance; + uint32 m_InvitedHorde; + + /* Raid Group */ + Group *m_BgRaids[2]; // 0 - alliance, 1 - horde + + /* Players count by team */ + uint32 m_PlayersCount[2]; + + /* Limits */ + uint32 m_LevelMin; + uint32 m_LevelMax; + uint32 m_MaxPlayersPerTeam; + uint32 m_MaxPlayers; + uint32 m_MinPlayersPerTeam; + uint32 m_MinPlayers; + + /* Location */ + uint32 m_MapId; + float m_TeamStartLocX[2]; + float m_TeamStartLocY[2]; + float m_TeamStartLocZ[2]; + float m_TeamStartLocO[2]; +}; +#endif diff --git a/src/game/BattleGroundAA.cpp b/src/game/BattleGroundAA.cpp new file mode 100644 index 00000000000..6929ef29681 --- /dev/null +++ b/src/game/BattleGroundAA.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Player.h" +#include "BattleGround.h" +#include "BattleGroundAA.h" + +BattleGroundAA::BattleGroundAA() +{ + +} + +BattleGroundAA::~BattleGroundAA() +{ + +} + +void BattleGroundAA::Update(time_t diff) +{ + BattleGround::Update(diff); +} + +void BattleGroundAA::AddPlayer(Player *plr) +{ + BattleGround::AddPlayer(plr); + //create score and add it to map, default values are set in constructor + BattleGroundAAScore* sc = new BattleGroundAAScore; + + m_PlayerScores[plr->GetGUID()] = sc; +} + +void BattleGroundAA::RemovePlayer(Player * /*plr*/, uint64 /*guid*/) +{ +} + +void BattleGroundAA::HandleKillPlayer(Player* player, Player* killer) +{ + BattleGround::HandleKillPlayer(player, killer); +} + +void BattleGroundAA::HandleAreaTrigger(Player * /*Source*/, uint32 /*Trigger*/) +{ +} + +bool BattleGroundAA::SetupBattleGround() +{ + return true; +} diff --git a/src/game/BattleGroundAA.h b/src/game/BattleGroundAA.h new file mode 100644 index 00000000000..3db494430ee --- /dev/null +++ b/src/game/BattleGroundAA.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __BATTLEGROUNDAA_H +#define __BATTLEGROUNDAA_H + +class BattleGround; + +class BattleGroundAAScore : public BattleGroundScore +{ + public: + BattleGroundAAScore() {}; + virtual ~BattleGroundAAScore() {}; + //TODO fix me +}; + +class BattleGroundAA : public BattleGround +{ + friend class BattleGroundMgr; + + public: + BattleGroundAA(); + ~BattleGroundAA(); + void Update(time_t diff); + + /* inherited from BattlegroundClass */ + virtual void AddPlayer(Player *plr); + void RemovePlayer(Player *plr, uint64 guid); + void HandleAreaTrigger(Player *Source, uint32 Trigger); + bool SetupBattleGround(); + void HandleKillPlayer(Player* player, Player *killer); +}; +#endif diff --git a/src/game/BattleGroundAB.cpp b/src/game/BattleGroundAB.cpp new file mode 100644 index 00000000000..feb305e546a --- /dev/null +++ b/src/game/BattleGroundAB.cpp @@ -0,0 +1,649 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Object.h" +#include "Player.h" +#include "BattleGround.h" +#include "BattleGroundAB.h" +#include "Creature.h" +#include "Chat.h" +#include "ObjectMgr.h" +#include "MapManager.h" +#include "Language.h" +#include "Util.h" + +BattleGroundAB::BattleGroundAB() +{ + m_BuffChange = true; + m_BgObjects.resize(BG_AB_OBJECT_MAX); + m_BgCreatures.resize(BG_AB_ALL_NODES_COUNT); +} + +BattleGroundAB::~BattleGroundAB() +{ +} + +void BattleGroundAB::Update(time_t diff) +{ + BattleGround::Update(diff); + + if( GetStatus() == STATUS_WAIT_JOIN && GetPlayersSize() ) + { + ModifyStartDelayTime(diff); + + if( !(m_Events & 0x01) ) + { + m_Events |= 0x01; + + sLog.outDebug("Arathi Basin: entering state STATUS_WAIT_JOIN ..."); + + // despawn banners, auras and buffs + for (int obj = BG_AB_OBJECT_BANNER_NEUTRAL; obj < BG_AB_DYNAMIC_NODES_COUNT * 8; ++obj) + SpawnBGObject(obj, RESPAWN_ONE_DAY); + for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT * 3; ++i) + SpawnBGObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + i, RESPAWN_ONE_DAY); + + // Starting doors + SpawnBGObject(BG_AB_OBJECT_GATE_A, RESPAWN_IMMEDIATELY); + SpawnBGObject(BG_AB_OBJECT_GATE_H, RESPAWN_IMMEDIATELY); + DoorClose(BG_AB_OBJECT_GATE_A); + DoorClose(BG_AB_OBJECT_GATE_H); + + // Starting base spirit guides + _NodeOccupied(BG_AB_SPIRIT_ALIANCE,ALLIANCE); + _NodeOccupied(BG_AB_SPIRIT_HORDE,HORDE); + + SetStartDelayTime(START_DELAY0); + } + // After 1 minute, warning is signalled + else if( GetStartDelayTime() <= START_DELAY1 && !(m_Events & 0x04) ) + { + m_Events |= 0x04; + SendMessageToAll(GetMangosString(LANG_BG_AB_ONEMINTOSTART)); + } + // After 1,5 minute, warning is signalled + else if( GetStartDelayTime() <= START_DELAY2 && !(m_Events & 0x08) ) + { + m_Events |= 0x08; + SendMessageToAll(GetMangosString(LANG_BG_AB_HALFMINTOSTART)); + } + // After 2 minutes, gates OPEN ! x) + else if( GetStartDelayTime() < 0 && !(m_Events & 0x10) ) + { + m_Events |= 0x10; + SendMessageToAll(GetMangosString(LANG_BG_AB_STARTED)); + + // spawn neutral banners + for (int banner = BG_AB_OBJECT_BANNER_NEUTRAL, i = 0; i < 5; banner += 8, ++i) + SpawnBGObject(banner, RESPAWN_IMMEDIATELY); + for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) + { + //randomly select buff to spawn + uint8 buff = urand(0, 2); + SpawnBGObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + buff + i * 3, RESPAWN_IMMEDIATELY); + } + DoorOpen(BG_AB_OBJECT_GATE_A); + DoorOpen(BG_AB_OBJECT_GATE_H); + + PlaySoundToAll(SOUND_BG_START); + SetStatus(STATUS_IN_PROGRESS); + + for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) + if(Player* plr = objmgr.GetPlayer(itr->first)) + plr->RemoveAurasDueToSpell(SPELL_PREPARATION); + } + + } + else if( GetStatus() == STATUS_IN_PROGRESS ) + { + int team_points[2] = { 0, 0 }; + + for (int node = 0; node < BG_AB_DYNAMIC_NODES_COUNT; ++node) + { + // 3 sec delay to spawn new banner instead previous despawned one + if( m_BannerTimers[node].timer ) + { + if( m_BannerTimers[node].timer > diff ) + m_BannerTimers[node].timer -= diff; + else + { + m_BannerTimers[node].timer = 0; + _CreateBanner(node, m_BannerTimers[node].type, m_BannerTimers[node].teamIndex, false); + } + } + + // 1-minute to occupy a node from contested state + if( m_NodeTimers[node] ) + { + if( m_NodeTimers[node] > diff ) + m_NodeTimers[node] -= diff; + else + { + m_NodeTimers[node] = 0; + // Change from contested to occupied ! + uint8 teamIndex = m_Nodes[node]-1; + m_prevNodes[node] = m_Nodes[node]; + m_Nodes[node] += 2; + // burn current contested banner + _DelBanner(node, BG_AB_NODE_TYPE_CONTESTED, teamIndex); + // create new occupied banner + _CreateBanner(node, BG_AB_NODE_TYPE_OCCUPIED, teamIndex, true); + _SendNodeUpdate(node); + _NodeOccupied(node,(teamIndex == 0) ? ALLIANCE:HORDE); + // Message to chatlog + char buf[256]; + uint8 type = (teamIndex == 0) ? CHAT_MSG_BG_SYSTEM_ALLIANCE : CHAT_MSG_BG_SYSTEM_HORDE; + sprintf(buf, GetMangosString(LANG_BG_AB_NODE_TAKEN), (teamIndex == 0) ? GetMangosString(LANG_BG_AB_ALLY) : GetMangosString(LANG_BG_AB_HORDE), _GetNodeName(node)); + WorldPacket data; + ChatHandler::FillMessageData(&data, NULL, type, LANG_UNIVERSAL, NULL, 0, buf, NULL); + SendPacketToAll(&data); + PlaySoundToAll((teamIndex == 0) ? SOUND_NODE_CAPTURED_ALLIANCE : SOUND_NODE_CAPTURED_HORDE); + } + } + + for (int team = 0; team < 2; ++team) + if( m_Nodes[node] == team + BG_AB_NODE_TYPE_OCCUPIED ) + ++team_points[team]; + } + + // Accumulate points + for (int team = 0; team < 2; ++team) + { + int points = team_points[team]; + if( !points ) + continue; + m_lastTick[team] += diff; + if( m_lastTick[team] > BG_AB_TickIntervals[points] ) + { + m_lastTick[team] -= BG_AB_TickIntervals[points]; + m_TeamScores[team] += BG_AB_TickPoints[points]; + m_HonorScoreTics[team] += BG_AB_TickPoints[points]; + m_ReputationScoreTics[team] += BG_AB_TickPoints[points]; + if( m_ReputationScoreTics[team] >= 200 ) + { + (team == BG_TEAM_ALLIANCE) ? RewardReputationToTeam(509, 10, ALLIANCE) : RewardReputationToTeam(510, 10, HORDE); + m_ReputationScoreTics[team] -= 200; + } + if( m_HonorScoreTics[team] >= BG_HONOR_SCORE_TICKS ) + { + (team == BG_TEAM_ALLIANCE) ? RewardHonorToTeam(20, ALLIANCE) : RewardHonorToTeam(20, HORDE); + m_HonorScoreTics[team] -= BG_HONOR_SCORE_TICKS; + } + if( !m_IsInformedNearVictory && m_TeamScores[team] > 1800 ) + { + if( team == BG_TEAM_ALLIANCE ) + SendMessageToAll(GetMangosString(LANG_BG_AB_A_NEAR_VICTORY)); + else + SendMessageToAll(GetMangosString(LANG_BG_AB_H_NEAR_VICTORY)); + PlaySoundToAll(SOUND_NEAR_VICTORY); + m_IsInformedNearVictory = true; + } + + if( m_TeamScores[team] > 2000 ) + m_TeamScores[team] = 2000; + if( team == BG_TEAM_ALLIANCE ) + UpdateWorldState(BG_AB_OP_RESOURCES_ALLY, m_TeamScores[team]); + if( team == BG_TEAM_HORDE ) + UpdateWorldState(BG_AB_OP_RESOURCES_HORDE, m_TeamScores[team]); + } + } + + // Test win condition + if( m_TeamScores[BG_TEAM_ALLIANCE] >= 2000 ) + EndBattleGround(ALLIANCE); + if( m_TeamScores[BG_TEAM_HORDE] >= 2000 ) + EndBattleGround(HORDE); + } +} + +void BattleGroundAB::AddPlayer(Player *plr) +{ + BattleGround::AddPlayer(plr); + //create score and add it to map, default values are set in the constructor + BattleGroundABScore* sc = new BattleGroundABScore; + + m_PlayerScores[plr->GetGUID()] = sc; +} + +void BattleGroundAB::RemovePlayer(Player * /*plr*/, uint64 /*guid*/) +{ + +} + +void BattleGroundAB::HandleAreaTrigger(Player *Source, uint32 Trigger) +{ + if( GetStatus() != STATUS_IN_PROGRESS ) + return; + + switch(Trigger) + { + case 3948: // Arathi Basin Alliance Exit. + if( Source->GetTeam() != ALLIANCE ) + Source->GetSession()->SendAreaTriggerMessage("Only The Alliance can use that portal"); + else + Source->LeaveBattleground(); + break; + case 3949: // Arathi Basin Horde Exit. + if( Source->GetTeam() != HORDE ) + Source->GetSession()->SendAreaTriggerMessage("Only The Horde can use that portal"); + else + Source->LeaveBattleground(); + break; + case 3866: // Stables + case 3869: // Gold Mine + case 3867: // Farm + case 3868: // Lumber Mill + case 3870: // Black Smith + case 4020: // Unk1 + case 4021: // Unk2 + //break; + default: + //sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger); + //Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger); + break; + } +} + +/* type: 0-neutral, 1-contested, 3-occupied + teamIndex: 0-ally, 1-horde */ +void BattleGroundAB::_CreateBanner(uint8 node, uint8 type, uint8 teamIndex, bool delay) +{ + // Just put it into the queue + if( delay ) + { + m_BannerTimers[node].timer = 2000; + m_BannerTimers[node].type = type; + m_BannerTimers[node].teamIndex = teamIndex; + return; + } + + uint8 obj = node*8 + type + teamIndex; + + SpawnBGObject(obj, RESPAWN_IMMEDIATELY); + + // handle aura with banner + if( !type ) + return; + obj = node * 8 + ((type == BG_AB_NODE_TYPE_OCCUPIED) ? (5 + teamIndex) : 7); + SpawnBGObject(obj, RESPAWN_IMMEDIATELY); +} + +void BattleGroundAB::_DelBanner(uint8 node, uint8 type, uint8 teamIndex) +{ + uint8 obj = node*8 + type + teamIndex; + SpawnBGObject(obj, RESPAWN_ONE_DAY); + + // handle aura with banner + if( !type ) + return; + obj = node * 8 + ((type == BG_AB_NODE_TYPE_OCCUPIED) ? (5 + teamIndex) : 7); + SpawnBGObject(obj, RESPAWN_ONE_DAY); +} + +const char* BattleGroundAB::_GetNodeName(uint8 node) +{ + switch (node) + { + case BG_AB_NODE_STABLES: + return GetMangosString(LANG_BG_AB_NODE_STABLES); + case BG_AB_NODE_BLACKSMITH: + return GetMangosString(LANG_BG_AB_NODE_BLACKSMITH); + case BG_AB_NODE_FARM: + return GetMangosString(LANG_BG_AB_NODE_FARM); + case BG_AB_NODE_LUMBER_MILL: + return GetMangosString(LANG_BG_AB_NODE_LUMBER_MILL); + case BG_AB_NODE_GOLD_MINE: + return GetMangosString(LANG_BG_AB_NODE_GOLD_MINE); + default: + ASSERT(0); + } + return ""; +} + +void BattleGroundAB::FillInitialWorldStates(WorldPacket& data) +{ + const uint8 plusArray[] = {0, 2, 3, 0, 1}; + + // Node icons + for (uint8 node = 0; node < BG_AB_DYNAMIC_NODES_COUNT; ++node) + data << uint32(BG_AB_OP_NODEICONS[node]) << uint32((m_Nodes[node]==0)?1:0); + + // Node occupied states + for (uint8 node = 0; node < BG_AB_DYNAMIC_NODES_COUNT; ++node) + for (uint8 i = 1; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) + data << uint32(BG_AB_OP_NODESTATES[node] + plusArray[i]) << uint32((m_Nodes[node]==i)?1:0); + + // How many bases each team owns + uint8 ally = 0, horde = 0; + for (uint8 node = 0; node < BG_AB_DYNAMIC_NODES_COUNT; ++node) + if( m_Nodes[node] == BG_AB_NODE_STATUS_ALLY_OCCUPIED ) + ++ally; + else if( m_Nodes[node] == BG_AB_NODE_STATUS_HORDE_OCCUPIED ) + ++horde; + + data << uint32(BG_AB_OP_OCCUPIED_BASES_ALLY) << uint32(ally); + data << uint32(BG_AB_OP_OCCUPIED_BASES_HORDE) << uint32(horde); + + // Team scores + data << uint32(BG_AB_OP_RESOURCES_MAX) << uint32(BG_AB_MAX_TEAM_SCORE); + data << uint32(BG_AB_OP_RESOURCES_WARNING) << uint32(BG_AB_WARNING_SCORE); + data << uint32(BG_AB_OP_RESOURCES_ALLY) << uint32(m_TeamScores[BG_TEAM_ALLIANCE]); + data << uint32(BG_AB_OP_RESOURCES_HORDE) << uint32(m_TeamScores[BG_TEAM_HORDE]); + + // other unknown + data << uint32(0x745) << uint32(0x2); // 37 1861 unk +} + +void BattleGroundAB::_SendNodeUpdate(uint8 node) +{ + // Send node owner state update to refresh map icons on client + const uint8 plusArray[] = {0, 2, 3, 0, 1}; + + if( m_prevNodes[node] ) + UpdateWorldState(BG_AB_OP_NODESTATES[node] + plusArray[m_prevNodes[node]], 0); + else + UpdateWorldState(BG_AB_OP_NODEICONS[node], 0); + + UpdateWorldState(BG_AB_OP_NODESTATES[node] + plusArray[m_Nodes[node]], 1); + + // How many bases each team owns + uint8 ally = 0, horde = 0; + for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) + if( m_Nodes[i] == BG_AB_NODE_STATUS_ALLY_OCCUPIED ) + ++ally; + else if( m_Nodes[i] == BG_AB_NODE_STATUS_HORDE_OCCUPIED ) + ++horde; + + UpdateWorldState(BG_AB_OP_OCCUPIED_BASES_ALLY, ally); + UpdateWorldState(BG_AB_OP_OCCUPIED_BASES_HORDE, horde); +} + +void BattleGroundAB::_NodeOccupied(uint8 node,Team team) +{ + if( !AddSpiritGuide(node, BG_AB_SpiritGuidePos[node][0], BG_AB_SpiritGuidePos[node][1], BG_AB_SpiritGuidePos[node][2], BG_AB_SpiritGuidePos[node][3], team) ) + sLog.outError("Failed to spawn spirit guide! point: %u, team: %u,", node, team); + + uint8 capturedNodes = 0; + for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) + { + if( m_Nodes[node] == GetTeamIndexByTeamId(team) + BG_AB_NODE_TYPE_OCCUPIED && !m_NodeTimers[i]) + ++capturedNodes; + } + if(capturedNodes >= 5) + CastSpellOnTeam(SPELL_AB_QUEST_REWARD_5_BASES, team); + if(capturedNodes >= 4) + CastSpellOnTeam(SPELL_AB_QUEST_REWARD_4_BASES, team); +} + +void BattleGroundAB::_NodeDeOccupied(uint8 node) +{ + if( node >= BG_AB_DYNAMIC_NODES_COUNT) + return; + + // Those who are waiting to resurrect at this node are taken to the closest own node's graveyard + std::vector ghost_list = m_ReviveQueue[m_BgCreatures[node]]; + if( !ghost_list.empty() ) + { + WorldSafeLocsEntry const *ClosestGrave = NULL; + Player *plr; + for (std::vector::iterator itr = ghost_list.begin(); itr != ghost_list.end(); ++itr) + { + plr = objmgr.GetPlayer(*ghost_list.begin()); + if( !plr ) + continue; + if( !ClosestGrave ) + ClosestGrave = GetClosestGraveYard(plr->GetPositionX(), plr->GetPositionY(), plr->GetPositionZ(), plr->GetTeam()); + + plr->TeleportTo(GetMapId(), ClosestGrave->x, ClosestGrave->y, ClosestGrave->z, plr->GetOrientation()); + } + } + + if( m_BgCreatures[node] ) + DelCreature(node); + + // buff object isn't despawned +} + +/* Invoked if a player used a banner as a gameobject */ +void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*target_obj*/) +{ + if( GetStatus() != STATUS_IN_PROGRESS ) + return; + + uint8 node = BG_AB_NODE_STABLES; + GameObject* obj=HashMapHolder::Find(m_BgObjects[node*8+7]); + while ( (node < BG_AB_DYNAMIC_NODES_COUNT) && ((!obj) || (!source->IsWithinDistInMap(obj,10)))) + { + ++node; + obj=HashMapHolder::Find(m_BgObjects[node*8+BG_AB_OBJECT_AURA_CONTESTED]); + } + + if( node == BG_AB_DYNAMIC_NODES_COUNT) + { + // this means our player isn't close to any of banners - maybe cheater ?? + return; + } + + uint8 teamIndex = GetTeamIndexByTeamId(source->GetTeam()); + + // Message to chatlog + char buf[256]; + uint8 type = (teamIndex == 0) ? CHAT_MSG_BG_SYSTEM_ALLIANCE : CHAT_MSG_BG_SYSTEM_HORDE; + + // Check if player really could use this banner, not cheated + if( !(m_Nodes[node] == 0 || teamIndex == m_Nodes[node]%2) ) + return; + + source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); + uint32 sound = 0; + // If node is neutral, change to contested + if( m_Nodes[node] == BG_AB_NODE_TYPE_NEUTRAL ) + { + UpdatePlayerScore(source, SCORE_BASES_ASSAULTED, 1); + m_prevNodes[node] = m_Nodes[node]; + m_Nodes[node] = teamIndex + 1; + // burn current neutral banner + _DelBanner(node, BG_AB_NODE_TYPE_NEUTRAL, 0); + // create new contested banner + _CreateBanner(node, BG_AB_NODE_TYPE_CONTESTED, teamIndex, true); + _SendNodeUpdate(node); + m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME; + sprintf(buf, GetMangosString(LANG_BG_AB_NODE_CLAIMED), _GetNodeName(node), (teamIndex == 0) ? GetMangosString(LANG_BG_AB_ALLY) : GetMangosString(LANG_BG_AB_HORDE)); + sound = SOUND_NODE_CLAIMED; + } + // If node is contested + else if( (m_Nodes[node] == BG_AB_NODE_STATUS_ALLY_CONTESTED) || (m_Nodes[node] == BG_AB_NODE_STATUS_HORDE_CONTESTED) ) + { + // If last state is NOT occupied, change node to enemy-contested + if( m_prevNodes[node] < BG_AB_NODE_TYPE_OCCUPIED ) + { + UpdatePlayerScore(source, SCORE_BASES_ASSAULTED, 1); + m_prevNodes[node] = m_Nodes[node]; + m_Nodes[node] = teamIndex + BG_AB_NODE_TYPE_CONTESTED; + // burn current contested banner + _DelBanner(node, BG_AB_NODE_TYPE_CONTESTED, !teamIndex); + // create new contested banner + _CreateBanner(node, BG_AB_NODE_TYPE_CONTESTED, teamIndex, true); + _SendNodeUpdate(node); + m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME; + sprintf(buf, GetMangosString(LANG_BG_AB_NODE_ASSAULTED), _GetNodeName(node)); + } + // If contested, change back to occupied + else + { + UpdatePlayerScore(source, SCORE_BASES_DEFENDED, 1); + m_prevNodes[node] = m_Nodes[node]; + m_Nodes[node] = teamIndex + BG_AB_NODE_TYPE_OCCUPIED; + // burn current contested banner + _DelBanner(node, BG_AB_NODE_TYPE_CONTESTED, !teamIndex); + // create new occupied banner + _CreateBanner(node, BG_AB_NODE_TYPE_OCCUPIED, teamIndex, true); + _SendNodeUpdate(node); + m_NodeTimers[node] = 0; + _NodeOccupied(node,(teamIndex == 0) ? ALLIANCE:HORDE); + sprintf(buf, GetMangosString(LANG_BG_AB_NODE_DEFENDED), _GetNodeName(node)); + } + sound = (teamIndex == 0) ? SOUND_NODE_ASSAULTED_ALLIANCE : SOUND_NODE_ASSAULTED_HORDE; + } + // If node is occupied, change to enemy-contested + else + { + UpdatePlayerScore(source, SCORE_BASES_ASSAULTED, 1); + m_prevNodes[node] = m_Nodes[node]; + m_Nodes[node] = teamIndex + BG_AB_NODE_TYPE_CONTESTED; + // burn current occupied banner + _DelBanner(node, BG_AB_NODE_TYPE_OCCUPIED, !teamIndex); + // create new contested banner + _CreateBanner(node, BG_AB_NODE_TYPE_CONTESTED, teamIndex, true); + _SendNodeUpdate(node); + _NodeDeOccupied(node); + m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME; + sprintf(buf, GetMangosString(LANG_BG_AB_NODE_ASSAULTED), _GetNodeName(node)); + sound = (teamIndex == 0) ? SOUND_NODE_ASSAULTED_ALLIANCE : SOUND_NODE_ASSAULTED_HORDE; + } + WorldPacket data; + ChatHandler::FillMessageData(&data, source->GetSession(), type, LANG_UNIVERSAL, NULL, source->GetGUID(), buf, NULL); + SendPacketToAll(&data); + // If node is occupied again, send "X has taken the Y" msg. + if( m_Nodes[node] >= BG_AB_NODE_TYPE_OCCUPIED ) + { + sprintf(buf, GetMangosString(LANG_BG_AB_NODE_TAKEN), (teamIndex == 0) ? GetMangosString(LANG_BG_AB_ALLY) : GetMangosString(LANG_BG_AB_HORDE), _GetNodeName(node)); + ChatHandler::FillMessageData(&data, NULL, type, LANG_UNIVERSAL, NULL, 0, buf, NULL); + SendPacketToAll(&data); + } + PlaySoundToAll(sound); +} + +bool BattleGroundAB::SetupBattleGround() +{ + for (int i = 0 ; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) + { + if( !AddObject(BG_AB_OBJECT_BANNER_NEUTRAL + 8*i,BG_AB_OBJECTID_NODE_BANNER_0 + i,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY) + || !AddObject(BG_AB_OBJECT_BANNER_CONT_A + 8*i,BG_AB_OBJECTID_BANNER_CONT_A,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY) + || !AddObject(BG_AB_OBJECT_BANNER_CONT_H + 8*i,BG_AB_OBJECTID_BANNER_CONT_H,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY) + || !AddObject(BG_AB_OBJECT_BANNER_ALLY + 8*i,BG_AB_OBJECTID_BANNER_A,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY) + || !AddObject(BG_AB_OBJECT_BANNER_HORDE + 8*i,BG_AB_OBJECTID_BANNER_H,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY) + || !AddObject(BG_AB_OBJECT_AURA_ALLY + 8*i,BG_AB_OBJECTID_AURA_A,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY) + || !AddObject(BG_AB_OBJECT_AURA_HORDE + 8*i,BG_AB_OBJECTID_AURA_H,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY) + || !AddObject(BG_AB_OBJECT_AURA_CONTESTED + 8*i,BG_AB_OBJECTID_AURA_C,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY) + ) + { + sLog.outErrorDb("BatteGroundAB: Failed to spawn some object BattleGround not created!"); + return false; + } + } + if( !AddObject(BG_AB_OBJECT_GATE_A,BG_AB_OBJECTID_GATE_A,BG_AB_DoorPositions[0][0],BG_AB_DoorPositions[0][1],BG_AB_DoorPositions[0][2],BG_AB_DoorPositions[0][3],BG_AB_DoorPositions[0][4],BG_AB_DoorPositions[0][5],BG_AB_DoorPositions[0][6],BG_AB_DoorPositions[0][7],RESPAWN_IMMEDIATELY) + || !AddObject(BG_AB_OBJECT_GATE_H,BG_AB_OBJECTID_GATE_H,BG_AB_DoorPositions[1][0],BG_AB_DoorPositions[1][1],BG_AB_DoorPositions[1][2],BG_AB_DoorPositions[1][3],BG_AB_DoorPositions[1][4],BG_AB_DoorPositions[1][5],BG_AB_DoorPositions[1][6],BG_AB_DoorPositions[1][7],RESPAWN_IMMEDIATELY) + ) + { + sLog.outErrorDb("BatteGroundAB: Failed to spawn door object BattleGround not created!"); + return false; + } + //buffs + for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) + { + if( !AddObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + 3 * i, Buff_Entries[0], BG_AB_BuffPositions[i][0], BG_AB_BuffPositions[i][1], BG_AB_BuffPositions[i][2], BG_AB_BuffPositions[i][3], 0, 0, sin(BG_AB_BuffPositions[i][3]/2), cos(BG_AB_BuffPositions[i][3]/2), RESPAWN_ONE_DAY) + || !AddObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + 3 * i + 1, Buff_Entries[1], BG_AB_BuffPositions[i][0], BG_AB_BuffPositions[i][1], BG_AB_BuffPositions[i][2], BG_AB_BuffPositions[i][3], 0, 0, sin(BG_AB_BuffPositions[i][3]/2), cos(BG_AB_BuffPositions[i][3]/2), RESPAWN_ONE_DAY) + || !AddObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + 3 * i + 2, Buff_Entries[2], BG_AB_BuffPositions[i][0], BG_AB_BuffPositions[i][1], BG_AB_BuffPositions[i][2], BG_AB_BuffPositions[i][3], 0, 0, sin(BG_AB_BuffPositions[i][3]/2), cos(BG_AB_BuffPositions[i][3]/2), RESPAWN_ONE_DAY) + ) + sLog.outErrorDb("BatteGroundAB: Failed to spawn buff object!"); + } + + return true; +} + +void BattleGroundAB::ResetBGSubclass() +{ + m_TeamScores[BG_TEAM_ALLIANCE] = 0; + m_TeamScores[BG_TEAM_HORDE] = 0; + m_lastTick[BG_TEAM_ALLIANCE] = 0; + m_lastTick[BG_TEAM_HORDE] = 0; + m_HonorScoreTics[BG_TEAM_ALLIANCE] = 0; + m_HonorScoreTics[BG_TEAM_HORDE] = 0; + m_ReputationScoreTics[BG_TEAM_ALLIANCE] = 0; + m_ReputationScoreTics[BG_TEAM_HORDE] = 0; + m_IsInformedNearVictory = false; + for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) + { + m_Nodes[i] = 0; + m_prevNodes[i] = 0; + m_NodeTimers[i] = 0; + m_BannerTimers[i].timer = 0; + } + + for (uint8 i = 0; i < BG_AB_ALL_NODES_COUNT; ++i) + if(m_BgCreatures[i]) + DelCreature(i); +} + +WorldSafeLocsEntry const* BattleGroundAB::GetClosestGraveYard(float x, float y, float /*z*/, uint32 team) +{ + uint8 teamIndex = GetTeamIndexByTeamId(team); + + // Is there any occupied node for this team? + std::vector nodes; + for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) + if( m_Nodes[i] == teamIndex + 3 ) + nodes.push_back(i); + + WorldSafeLocsEntry const* good_entry = NULL; + // If so, select the closest node to place ghost on + if( !nodes.empty() ) + { + float mindist = 999999.0f; + for (uint8 i = 0; i < nodes.size(); ++i) + { + WorldSafeLocsEntry const*entry = sWorldSafeLocsStore.LookupEntry( BG_AB_GraveyardIds[nodes[i]] ); + if( !entry ) + continue; + float dist = (entry->x - x)*(entry->x - x)+(entry->y - y)*(entry->y - y); + if( mindist > dist ) + { + mindist = dist; + good_entry = entry; + } + } + nodes.clear(); + } + // If not, place ghost on starting location + if( !good_entry ) + good_entry = sWorldSafeLocsStore.LookupEntry( BG_AB_GraveyardIds[teamIndex+5] ); + + return good_entry; +} + +void BattleGroundAB::UpdatePlayerScore(Player *Source, uint32 type, uint32 value) +{ + std::map::iterator itr = m_PlayerScores.find(Source->GetGUID()); + + if( itr == m_PlayerScores.end() ) // player not found... + return; + + switch(type) + { + case SCORE_BASES_ASSAULTED: + ((BattleGroundABScore*)itr->second)->BasesAssaulted += value; + break; + case SCORE_BASES_DEFENDED: + ((BattleGroundABScore*)itr->second)->BasesDefended += value; + break; + default: + BattleGround::UpdatePlayerScore(Source,type,value); + break; + } +} diff --git a/src/game/BattleGroundAB.h b/src/game/BattleGroundAB.h new file mode 100644 index 00000000000..289d26f98fd --- /dev/null +++ b/src/game/BattleGroundAB.h @@ -0,0 +1,284 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __BATTLEGROUNDAB_H +#define __BATTLEGROUNDAB_H + +class BattleGround; + +enum BG_AB_WorldStates +{ + BG_AB_OP_OCCUPIED_BASES_HORDE = 1778, + BG_AB_OP_OCCUPIED_BASES_ALLY = 1779, + BG_AB_OP_RESOURCES_ALLY = 1776, + BG_AB_OP_RESOURCES_HORDE = 1777, + BG_AB_OP_RESOURCES_MAX = 1780, + BG_AB_OP_RESOURCES_WARNING = 1955 +/* + BG_AB_OP_STABLE_ICON = 1842, //Stable map icon (NONE) + BG_AB_OP_STABLE_STATE_ALIENCE = 1767, //Stable map state (ALIENCE) + BG_AB_OP_STABLE_STATE_HORDE = 1768, //Stable map state (HORDE) + BG_AB_OP_STABLE_STATE_CON_ALI = 1769, //Stable map state (CON ALIENCE) + BG_AB_OP_STABLE_STATE_CON_HOR = 1770, //Stable map state (CON HORDE) + BG_AB_OP_FARM_ICON = 1845, //Farm map icon (NONE) + BG_AB_OP_FARM_STATE_ALIENCE = 1772, //Farm state (ALIENCE) + BG_AB_OP_FARM_STATE_HORDE = 1773, //Farm state (HORDE) + BG_AB_OP_FARM_STATE_CON_ALI = 1774, //Farm state (CON ALIENCE) + BG_AB_OP_FARM_STATE_CON_HOR = 1775, //Farm state (CON HORDE) + + BG_AB_OP_BLACKSMITH_ICON = 1846, //Blacksmith map icon (NONE) + BG_AB_OP_BLACKSMITH_STATE_ALIENCE = 1782, //Blacksmith map state (ALIENCE) + BG_AB_OP_BLACKSMITH_STATE_HORDE = 1783, //Blacksmith map state (HORDE) + BG_AB_OP_BLACKSMITH_STATE_CON_ALI = 1784, //Blacksmith map state (CON ALIENCE) + BG_AB_OP_BLACKSMITH_STATE_CON_HOR = 1785, //Blacksmith map state (CON HORDE) + BG_AB_OP_LUMBERMILL_ICON = 1844, //Lumber Mill map icon (NONE) + BG_AB_OP_LUMBERMILL_STATE_ALIENCE = 1792, //Lumber Mill map state (ALIENCE) + BG_AB_OP_LUMBERMILL_STATE_HORDE = 1793, //Lumber Mill map state (HORDE) + BG_AB_OP_LUMBERMILL_STATE_CON_ALI = 1794, //Lumber Mill map state (CON ALIENCE) + BG_AB_OP_LUMBERMILL_STATE_CON_HOR = 1795, //Lumber Mill map state (CON HORDE) + BG_AB_OP_GOLDMINE_ICON = 1843, //Gold Mine map icon (NONE) + BG_AB_OP_GOLDMINE_STATE_ALIENCE = 1787, //Gold Mine map state (ALIENCE) + BG_AB_OP_GOLDMINE_STATE_HORDE = 1788, //Gold Mine map state (HORDE) + BG_AB_OP_GOLDMINE_STATE_CON_ALI = 1789, //Gold Mine map state (CON ALIENCE + BG_AB_OP_GOLDMINE_STATE_CON_HOR = 1790, //Gold Mine map state (CON HORDE) +*/ +}; + +const uint32 BG_AB_OP_NODESTATES[5] = {1767, 1782, 1772, 1792, 1787}; + +const uint32 BG_AB_OP_NODEICONS[5] = {1842, 1846, 1845, 1844, 1843}; + +/* Note: code uses that these IDs follow each other */ +enum BG_AB_NodeObjectId +{ + BG_AB_OBJECTID_NODE_BANNER_0 = 180087, // Stables banner + BG_AB_OBJECTID_NODE_BANNER_1 = 180088, // Blacksmith banner + BG_AB_OBJECTID_NODE_BANNER_2 = 180089, // Farm banner + BG_AB_OBJECTID_NODE_BANNER_3 = 180090, // Lumber mill banner + BG_AB_OBJECTID_NODE_BANNER_4 = 180091 // Gold mine banner +}; + +enum BG_AB_ObjectType +{ + // for all 5 node points 8*5=40 objects + BG_AB_OBJECT_BANNER_NEUTRAL = 0, + BG_AB_OBJECT_BANNER_CONT_A = 1, + BG_AB_OBJECT_BANNER_CONT_H = 2, + BG_AB_OBJECT_BANNER_ALLY = 3, + BG_AB_OBJECT_BANNER_HORDE = 4, + BG_AB_OBJECT_AURA_ALLY = 5, + BG_AB_OBJECT_AURA_HORDE = 6, + BG_AB_OBJECT_AURA_CONTESTED = 7, + //gates + BG_AB_OBJECT_GATE_A = 40, + BG_AB_OBJECT_GATE_H = 41, + //buffs + BG_AB_OBJECT_SPEEDBUFF_STABLES = 42, + BG_AB_OBJECT_REGENBUFF_STABLES = 43, + BG_AB_OBJECT_BERSERKBUFF_STABLES = 44, + BG_AB_OBJECT_SPEEDBUFF_BLACKSMITH = 45, + BG_AB_OBJECT_REGENBUFF_BLACKSMITH = 46, + BG_AB_OBJECT_BERSERKBUFF_BLACKSMITH = 47, + BG_AB_OBJECT_SPEEDBUFF_FARM = 48, + BG_AB_OBJECT_REGENBUFF_FARM = 49, + BG_AB_OBJECT_BERSERKBUFF_FARM = 50, + BG_AB_OBJECT_SPEEDBUFF_LUMBER_MILL = 51, + BG_AB_OBJECT_REGENBUFF_LUMBER_MILL = 52, + BG_AB_OBJECT_BERSERKBUFF_LUMBER_MILL = 53, + BG_AB_OBJECT_SPEEDBUFF_GOLD_MINE = 54, + BG_AB_OBJECT_REGENBUFF_GOLD_MINE = 55, + BG_AB_OBJECT_BERSERKBUFF_GOLD_MINE = 56, + BG_AB_OBJECT_MAX = 57, +}; + +/* Object id templates from DB */ +enum BG_AB_ObjectTypes +{ + BG_AB_OBJECTID_BANNER_A = 180058, + BG_AB_OBJECTID_BANNER_CONT_A = 180059, + BG_AB_OBJECTID_BANNER_H = 180060, + BG_AB_OBJECTID_BANNER_CONT_H = 180061, + + BG_AB_OBJECTID_AURA_A = 180100, + BG_AB_OBJECTID_AURA_H = 180101, + BG_AB_OBJECTID_AURA_C = 180102, + + BG_AB_OBJECTID_GATE_A = 180255, + BG_AB_OBJECTID_GATE_H = 180256 +}; + +enum BG_AB_Timers +{ + BG_AB_FLAG_CAPTURING_TIME = 60000, +}; + +enum BG_AB_Score +{ + BG_AB_MAX_TEAM_SCORE = 2000, + BG_AB_WARNING_SCORE = 1800 +}; + +/* do NOT change the order, else wrong behaviour */ +enum BG_AB_BattleGroundNodes +{ + BG_AB_NODE_STABLES = 0, + BG_AB_NODE_BLACKSMITH = 1, + BG_AB_NODE_FARM = 2, + BG_AB_NODE_LUMBER_MILL = 3, + BG_AB_NODE_GOLD_MINE = 4, + + BG_AB_DYNAMIC_NODES_COUNT = 5, // dynamic nodes that can be captured + + BG_AB_SPIRIT_ALIANCE = 5, + BG_AB_SPIRIT_HORDE = 6, + + BG_AB_ALL_NODES_COUNT = 7, // all nodes (dynamic and static) +}; + +enum BG_AB_NodeStatus +{ + BG_AB_NODE_TYPE_NEUTRAL = 0, + BG_AB_NODE_TYPE_CONTESTED = 1, + BG_AB_NODE_STATUS_ALLY_CONTESTED = 1, + BG_AB_NODE_STATUS_HORDE_CONTESTED = 2, + BG_AB_NODE_TYPE_OCCUPIED = 3, + BG_AB_NODE_STATUS_ALLY_OCCUPIED = 3, + BG_AB_NODE_STATUS_HORDE_OCCUPIED = 4 +}; + +enum BG_AB_Sounds +{ + SOUND_NODE_CLAIMED = 8192, + SOUND_NODE_CAPTURED_ALLIANCE = 8173, + SOUND_NODE_CAPTURED_HORDE = 8213, + SOUND_NODE_ASSAULTED_ALLIANCE = 8174, + SOUND_NODE_ASSAULTED_HORDE = 8212, + SOUND_NEAR_VICTORY = 8456 +}; + +// x, y, z, o +const float BG_AB_NodePositions[BG_AB_DYNAMIC_NODES_COUNT][4] = { + {1166.785f, 1200.132f, -56.70859f, 0.9075713f}, // stables + {977.0156f, 1046.616f, -44.80923f, -2.600541f}, // blacksmith + {806.1821f, 874.2723f, -55.99371f, -2.303835f}, // farm + {856.1419f, 1148.902f, 11.18469f, -2.303835f}, // lumber mill + {1146.923f, 848.1782f, -110.917f, -0.7330382f} // gold mine +}; + +// x, y, z, o, rot0, rot1, rot2, rot3 +const float BG_AB_DoorPositions[2][8] = { + {1284.597f, 1281.167f, -15.97792f, 0.7068594f, 0.012957f, -0.060288f, 0.344959f, 0.93659f}, + {708.0903f, 708.4479f, -17.8342f, -2.391099f, 0.050291f, 0.015127f, 0.929217f, -0.365784f} +}; + +// Tick intervals and given points: case 0,1,2,3,4,5 captured nodes +const uint32 BG_AB_TickIntervals[6] = {0, 12000, 9000, 6000, 3000, 1000}; +const uint32 BG_AB_TickPoints[6] = {0, 10, 10, 10, 10, 30}; + +// WorldSafeLocs ids for 5 nodes, and for ally, and horde starting location +const uint32 BG_AB_GraveyardIds[BG_AB_ALL_NODES_COUNT] = {895, 894, 893, 897, 896, 898, 899}; + +// x, y, z, o +const float BG_AB_BuffPositions[BG_AB_DYNAMIC_NODES_COUNT][4] = { + {1185.71f, 1185.24f, -56.36f, 2.56f}, // stables + {990.75f, 1008.18f, -42.60f, 2.43f}, // blacksmith + {817.66f, 843.34f, -56.54f, 3.01f}, // farm + {807.46f, 1189.16f, 11.92f, 5.44f}, // lumber mill + {1146.62f, 816.94f, -98.49f, 6.14f} // gold mine +}; + +// x, y, z, o +const float BG_AB_SpiritGuidePos[BG_AB_ALL_NODES_COUNT][4] = { + {1200.03f, 1171.09f, -56.47f, 5.15f}, // stables + {1017.43f, 960.61f, -42.95f, 4.88f}, // blacksmith + {833.00f, 793.00f, -57.25f, 5.27f}, // farm + {775.17f, 1206.40f, 15.79f, 1.90f}, // lumber mill + {1207.48f, 787.00f, -83.36f, 5.51f}, // gold mine + {1354.05f, 1275.48f, -11.30f, 4.77f}, // alliance starting base + {714.61f, 646.15f, -10.87f, 4.34f} // horde starting base +}; + +struct BG_AB_BannerTimer +{ + uint32 timer; + uint8 type; + uint8 teamIndex; +}; + +class BattleGroundABScore : public BattleGroundScore +{ + public: + BattleGroundABScore(): BasesAssaulted(0), BasesDefended(0) {}; + virtual ~BattleGroundABScore() {}; + uint32 BasesAssaulted; + uint32 BasesDefended; +}; + +class BattleGroundAB : public BattleGround +{ + friend class BattleGroundMgr; + + public: + BattleGroundAB(); + ~BattleGroundAB(); + + void Update(time_t diff); + void AddPlayer(Player *plr); + void RemovePlayer(Player *plr,uint64 guid); + void HandleAreaTrigger(Player *Source, uint32 Trigger); + virtual bool SetupBattleGround(); + virtual void ResetBGSubclass(); + virtual WorldSafeLocsEntry const* GetClosestGraveYard(float x, float y, float z, uint32 team); + + /* Scorekeeping */ + virtual void UpdatePlayerScore(Player *Source, uint32 type, uint32 value); + + virtual void FillInitialWorldStates(WorldPacket& data); + + /* Nodes occupying */ + virtual void EventPlayerClickedOnFlag(Player *source, GameObject* target_obj); + + private: + /* Gameobject spawning/despawning */ + void _CreateBanner(uint8 node, uint8 type, uint8 teamIndex, bool delay); + void _DelBanner(uint8 node, uint8 type, uint8 teamIndex); + void _SendNodeUpdate(uint8 node); + + /* Creature spawning/despawning */ + // TODO: working, scripted peons spawning + void _NodeOccupied(uint8 node,Team team); + void _NodeDeOccupied(uint8 node); + + const char* _GetNodeName(uint8 node); + + /* Nodes info: + 0: neutral + 1: ally contested + 2: horde contested + 3: ally occupied + 4: horde occupied */ + uint8 m_Nodes[BG_AB_DYNAMIC_NODES_COUNT]; + uint8 m_prevNodes[BG_AB_DYNAMIC_NODES_COUNT]; + BG_AB_BannerTimer m_BannerTimers[BG_AB_DYNAMIC_NODES_COUNT]; + int32 m_NodeTimers[BG_AB_DYNAMIC_NODES_COUNT]; + uint32 m_TeamScores[2]; + uint32 m_lastTick[2]; + uint32 m_HonorScoreTics[2]; + uint32 m_ReputationScoreTics[2]; + bool m_IsInformedNearVictory; +}; +#endif diff --git a/src/game/BattleGroundAV.cpp b/src/game/BattleGroundAV.cpp new file mode 100644 index 00000000000..78b585be190 --- /dev/null +++ b/src/game/BattleGroundAV.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Object.h" +#include "Player.h" +#include "BattleGround.h" +#include "BattleGroundAV.h" +#include "Creature.h" +#include "MapManager.h" +#include "Language.h" + +BattleGroundAV::BattleGroundAV() +{ + +} + +BattleGroundAV::~BattleGroundAV() +{ + +} + +void BattleGroundAV::Update(time_t diff) +{ + BattleGround::Update(diff); +} + +void BattleGroundAV::AddPlayer(Player *plr) +{ + BattleGround::AddPlayer(plr); + //create score and add it to map, default values are set in constructor + BattleGroundAVScore* sc = new BattleGroundAVScore; + + m_PlayerScores[plr->GetGUID()] = sc; +} + +void BattleGroundAV::RemovePlayer(Player* /*plr*/,uint64 /*guid*/) +{ + +} + +void BattleGroundAV::HandleAreaTrigger(Player *Source, uint32 Trigger) +{ + // this is wrong way to implement these things. On official it done by gameobject spell cast. + if(GetStatus() != STATUS_IN_PROGRESS) + return; + + uint32 SpellId = 0; + switch(Trigger) + { + case 95: + case 2606: + case 2608: + case 3326: + case 3327: + case 3328: + case 3329: + case 3330: + case 3331: + break; + default: + sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger); + Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger); + break; + } + + if(SpellId) + Source->CastSpell(Source, SpellId, true); +} + +void BattleGroundAV::UpdatePlayerScore(Player* Source, uint32 type, uint32 value) +{ + + std::map::iterator itr = m_PlayerScores.find(Source->GetGUID()); + + if(itr == m_PlayerScores.end()) // player not found... + return; + + switch(type) + { + case SCORE_GRAVEYARDS_ASSAULTED: + ((BattleGroundAVScore*)itr->second)->GraveyardsAssaulted += value; + break; + case SCORE_GRAVEYARDS_DEFENDED: + ((BattleGroundAVScore*)itr->second)->GraveyardsDefended += value; + break; + case SCORE_TOWERS_ASSAULTED: + ((BattleGroundAVScore*)itr->second)->TowersAssaulted += value; + break; + case SCORE_TOWERS_DEFENDED: + ((BattleGroundAVScore*)itr->second)->TowersDefended += value; + break; + case SCORE_MINES_CAPTURED: + ((BattleGroundAVScore*)itr->second)->MinesCaptured += value; + break; + case SCORE_LEADERS_KILLED: + ((BattleGroundAVScore*)itr->second)->LeadersKilled += value; + break; + case SCORE_SECONDARY_OBJECTIVES: + ((BattleGroundAVScore*)itr->second)->SecondaryObjectives += value; + break; + default: + BattleGround::UpdatePlayerScore(Source,type,value); + break; + } +} diff --git a/src/game/BattleGroundAV.h b/src/game/BattleGroundAV.h new file mode 100644 index 00000000000..441c310fda9 --- /dev/null +++ b/src/game/BattleGroundAV.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __BATTLEGROUNDAV_H +#define __BATTLEGROUNDAV_H + +class BattleGround; + +class BattleGroundAVScore : public BattleGroundScore +{ + public: + BattleGroundAVScore() : GraveyardsAssaulted(0), GraveyardsDefended(0), TowersAssaulted(0), TowersDefended(0), MinesCaptured(0), LeadersKilled(0), SecondaryObjectives(0) {}; + virtual ~BattleGroundAVScore() {}; + uint32 GraveyardsAssaulted; + uint32 GraveyardsDefended; + uint32 TowersAssaulted; + uint32 TowersDefended; + uint32 MinesCaptured; + uint32 LeadersKilled; + uint32 SecondaryObjectives; +}; + +class BattleGroundAV : public BattleGround +{ + friend class BattleGroundMgr; + + public: + BattleGroundAV(); + ~BattleGroundAV(); + void Update(time_t diff); + + /* inherited from BattlegroundClass */ + virtual void AddPlayer(Player *plr); + + void RemovePlayer(Player *plr,uint64 guid); + void HandleAreaTrigger(Player *Source, uint32 Trigger); + //bool SetupBattleGround(); + + /* Scorekeeping */ + void UpdatePlayerScore(Player *Source, uint32 type, uint32 value); + + private: +}; +#endif diff --git a/src/game/BattleGroundBE.cpp b/src/game/BattleGroundBE.cpp new file mode 100644 index 00000000000..a85286ce6d5 --- /dev/null +++ b/src/game/BattleGroundBE.cpp @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Object.h" +#include "Player.h" +#include "BattleGround.h" +#include "BattleGroundBE.h" +#include "Creature.h" +#include "ObjectMgr.h" +#include "MapManager.h" +#include "Language.h" + +BattleGroundBE::BattleGroundBE() +{ + m_BgObjects.resize(BG_BE_OBJECT_MAX); +} + +BattleGroundBE::~BattleGroundBE() +{ + +} + +void BattleGroundBE::Update(time_t diff) +{ + BattleGround::Update(diff); + + // after bg start we get there + if (GetStatus() == STATUS_WAIT_JOIN && GetPlayersSize()) + { + ModifyStartDelayTime(diff); + + if (!(m_Events & 0x01)) + { + m_Events |= 0x01; + for(uint32 i = BG_BE_OBJECT_DOOR_1; i <= BG_BE_OBJECT_DOOR_4; i++) + SpawnBGObject(i, RESPAWN_IMMEDIATELY); + + for(uint32 i = BG_BE_OBJECT_BUFF_1; i <= BG_BE_OBJECT_BUFF_2; i++) + SpawnBGObject(i, RESPAWN_ONE_DAY); + + SetStartDelayTime(START_DELAY1); + SendMessageToAll(LANG_ARENA_ONE_MINUTE); + } + // After 30 seconds, warning is signalled + else if (GetStartDelayTime() <= START_DELAY2 && !(m_Events & 0x04)) + { + m_Events |= 0x04; + SendMessageToAll(LANG_ARENA_THIRTY_SECONDS); + } + // After 15 seconds, warning is signalled + else if (GetStartDelayTime() <= START_DELAY3 && !(m_Events & 0x08)) + { + m_Events |= 0x08; + SendMessageToAll(LANG_ARENA_FIFTEEN_SECONDS); + } + // delay expired (1 minute) + else if (GetStartDelayTime() <= 0 && !(m_Events & 0x10)) + { + m_Events |= 0x10; + + for(uint32 i = BG_BE_OBJECT_DOOR_1; i <= BG_BE_OBJECT_DOOR_2; i++) + DoorOpen(i); + + for(uint32 i = BG_BE_OBJECT_BUFF_1; i <= BG_BE_OBJECT_BUFF_2; i++) + SpawnBGObject(i, 60); + + SendMessageToAll(LANG_ARENA_BEGUN); + SetStatus(STATUS_IN_PROGRESS); + SetStartDelayTime(0); + + for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) + if(Player *plr = objmgr.GetPlayer(itr->first)) + plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION); + } + } + + /*if(GetStatus() == STATUS_IN_PROGRESS) + { + // update something + }*/ +} + +void BattleGroundBE::AddPlayer(Player *plr) +{ + BattleGround::AddPlayer(plr); + //create score and add it to map, default values are set in constructor + BattleGroundBEScore* sc = new BattleGroundBEScore; + + m_PlayerScores[plr->GetGUID()] = sc; +} + +void BattleGroundBE::RemovePlayer(Player *plr, uint64 guid) +{ + +} + +void BattleGroundBE::HandleKillPlayer(Player *player, Player *killer) +{ + if(GetStatus() != STATUS_IN_PROGRESS) + return; + + if(!killer) + { + sLog.outError("Killer player not found"); + return; + } + + BattleGround::HandleKillPlayer(player, killer); + + uint32 killer_team_index = GetTeamIndexByTeamId(killer->GetTeam()); + + ++m_TeamKills[killer_team_index]; // add kills to killer's team + + if(m_TeamKills[killer_team_index] >= GetPlayersCountByTeam(player->GetTeam())) + { + // all opponents killed + EndBattleGround(killer->GetTeam()); + } +} + +void BattleGroundBE::HandleAreaTrigger(Player *Source, uint32 Trigger) +{ + // this is wrong way to implement these things. On official it done by gameobject spell cast. + if(GetStatus() != STATUS_IN_PROGRESS) + return; + + //uint32 SpellId = 0; + //uint64 buff_guid = 0; + switch(Trigger) + { + case 4538: // buff trigger? + //buff_guid = m_BgObjects[BG_BE_OBJECT_BUFF_1]; + break; + case 4539: // buff trigger? + //buff_guid = m_BgObjects[BG_BE_OBJECT_BUFF_2]; + break; + default: + sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger); + Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger); + break; + } + + //if(buff_guid) + // HandleTriggerBuff(buff_guid,Source); +} + +void BattleGroundBE::ResetBGSubclass() +{ + m_TeamKills[BG_TEAM_ALLIANCE] = 0; + m_TeamKills[BG_TEAM_HORDE] = 0; +} + +bool BattleGroundBE::SetupBattleGround() +{ + // gates + if( !AddObject(BG_BE_OBJECT_DOOR_1, BG_BE_OBJECT_TYPE_DOOR_1, 6287.277f, 282.1877f, 3.810925f, -2.260201f, 0, 0, 0.9044551f, -0.4265689f, RESPAWN_IMMEDIATELY) + || !AddObject(BG_BE_OBJECT_DOOR_2, BG_BE_OBJECT_TYPE_DOOR_2, 6189.546f, 241.7099f, 3.101481f, 0.8813917f, 0, 0, 0.4265689f, 0.9044551f, RESPAWN_IMMEDIATELY) + || !AddObject(BG_BE_OBJECT_DOOR_3, BG_BE_OBJECT_TYPE_DOOR_3, 6299.116f, 296.5494f, 3.308032f, 0.8813917f, 0, 0, 0.4265689f, 0.9044551f, RESPAWN_IMMEDIATELY) + || !AddObject(BG_BE_OBJECT_DOOR_4, BG_BE_OBJECT_TYPE_DOOR_4, 6177.708f, 227.3481f, 3.604374f, -2.260201f, 0, 0, 0.9044551f, -0.4265689f, RESPAWN_IMMEDIATELY) + // buffs + || !AddObject(BG_BE_OBJECT_BUFF_1, BG_BE_OBJECT_TYPE_BUFF_1, 6249.042f, 275.3239f, 11.22033f, -1.448624f, 0, 0, 0.6626201f, -0.7489557f, 120) + || !AddObject(BG_BE_OBJECT_BUFF_2, BG_BE_OBJECT_TYPE_BUFF_2, 6228.26f, 249.566f, 11.21812f, -0.06981307f, 0, 0, 0.03489945f, -0.9993908f, 120)) + { + sLog.outErrorDb("BatteGroundBE: Failed to spawn some object!"); + return false; + } + + return true; +} + +void BattleGroundBE::UpdatePlayerScore(Player* Source, uint32 type, uint32 value) +{ + + std::map::iterator itr = m_PlayerScores.find(Source->GetGUID()); + + if(itr == m_PlayerScores.end()) // player not found... + return; + + //there is nothing special in this score + BattleGround::UpdatePlayerScore(Source,type,value); + +} + +/* +21:45:46 id:231310 [S2C] SMSG_INIT_WORLD_STATES (706 = 0x02C2) len: 86 +0000: 32 02 00 00 76 0e 00 00 00 00 00 00 09 00 f3 09 | 2...v........... +0010: 00 00 01 00 00 00 f1 09 00 00 01 00 00 00 f0 09 | ................ +0020: 00 00 02 00 00 00 d4 08 00 00 00 00 00 00 d8 08 | ................ +0030: 00 00 00 00 00 00 d7 08 00 00 00 00 00 00 d6 08 | ................ +0040: 00 00 00 00 00 00 d5 08 00 00 00 00 00 00 d3 08 | ................ +0050: 00 00 00 00 00 00 | ...... + +spell 32724 - Gold Team +spell 32725 - Green Team +35774 Gold Team +35775 Green Team +*/ diff --git a/src/game/BattleGroundBE.h b/src/game/BattleGroundBE.h new file mode 100644 index 00000000000..1b92faab9fc --- /dev/null +++ b/src/game/BattleGroundBE.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __BATTLEGROUNDBE_H +#define __BATTLEGROUNDBE_H + +class BattleGround; + +enum BattleGroundBEObjectTypes +{ + BG_BE_OBJECT_DOOR_1 = 0, + BG_BE_OBJECT_DOOR_2 = 1, + BG_BE_OBJECT_DOOR_3 = 2, + BG_BE_OBJECT_DOOR_4 = 3, + BG_BE_OBJECT_BUFF_1 = 4, + BG_BE_OBJECT_BUFF_2 = 5, + BG_BE_OBJECT_MAX = 6 +}; + +enum BattleGroundBEObjects +{ + BG_BE_OBJECT_TYPE_DOOR_1 = 183971, + BG_BE_OBJECT_TYPE_DOOR_2 = 183973, + BG_BE_OBJECT_TYPE_DOOR_3 = 183970, + BG_BE_OBJECT_TYPE_DOOR_4 = 183972, + BG_BE_OBJECT_TYPE_BUFF_1 = 184663, + BG_BE_OBJECT_TYPE_BUFF_2 = 184664 +}; + +class BattleGroundBEScore : public BattleGroundScore +{ + public: + BattleGroundBEScore() {}; + virtual ~BattleGroundBEScore() {}; +}; + +class BattleGroundBE : public BattleGround +{ + friend class BattleGroundMgr; + + public: + BattleGroundBE(); + ~BattleGroundBE(); + void Update(time_t diff); + + /* inherited from BattlegroundClass */ + virtual void AddPlayer(Player *plr); + + void RemovePlayer(Player *plr, uint64 guid); + void HandleAreaTrigger(Player *Source, uint32 Trigger); + bool SetupBattleGround(); + void ResetBGSubclass(); + void HandleKillPlayer(Player* player, Player *killer); + + /* Scorekeeping */ + void UpdatePlayerScore(Player *Source, uint32 type, uint32 value); + + private: + uint32 m_TeamKills[2]; // count of kills for each team +}; +#endif diff --git a/src/game/BattleGroundEY.cpp b/src/game/BattleGroundEY.cpp new file mode 100644 index 00000000000..dbde3295f4d --- /dev/null +++ b/src/game/BattleGroundEY.cpp @@ -0,0 +1,909 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Object.h" +#include "Player.h" +#include "BattleGround.h" +#include "BattleGroundEY.h" +#include "Creature.h" +#include "Chat.h" +#include "ObjectMgr.h" +#include "MapManager.h" +#include "Language.h" +#include "Util.h" + +BattleGroundEY::BattleGroundEY() +{ + m_BuffChange = true; + m_BgObjects.resize(BG_EY_OBJECT_MAX); + m_BgCreatures.resize(BG_EY_CREATURES_MAX); + m_Points_Trigger[FEL_REALVER] = TR_FEL_REALVER_BUFF; + m_Points_Trigger[BLOOD_ELF] = TR_BLOOD_ELF_BUFF; + m_Points_Trigger[DRAENEI_RUINS] = TR_DRAENEI_RUINS_BUFF; + m_Points_Trigger[MAGE_TOWER] = TR_MAGE_TOWER_BUFF; +} + +BattleGroundEY::~BattleGroundEY() +{ +} + +void BattleGroundEY::Update(time_t diff) +{ + BattleGround::Update(diff); + // after bg start we get there (once) + if (GetStatus() == STATUS_WAIT_JOIN && GetPlayersSize()) + { + ModifyStartDelayTime(diff); + + if(!(m_Events & 0x01)) + { + m_Events |= 0x01; + + SpawnBGObject(BG_EY_OBJECT_DOOR_A, RESPAWN_IMMEDIATELY); + SpawnBGObject(BG_EY_OBJECT_DOOR_H, RESPAWN_IMMEDIATELY); + + for(uint32 i = BG_EY_OBJECT_A_BANNER_FEL_REALVER_CENTER; i < BG_EY_OBJECT_MAX; ++i) + SpawnBGObject(i, RESPAWN_ONE_DAY); + + SetStartDelayTime(START_DELAY0); + } + // After 1 minute, warning is signalled + else if(GetStartDelayTime() <= START_DELAY1 && !(m_Events & 0x04)) + { + m_Events |= 0x04; + SendMessageToAll(GetMangosString(LANG_BG_EY_ONE_MINUTE)); + } + // After 1,5 minute, warning is signalled + else if(GetStartDelayTime() <= START_DELAY2 && !(m_Events & 0x08)) + { + m_Events |= 0x08; + SendMessageToAll(GetMangosString(LANG_BG_EY_HALF_MINUTE)); + } + // After 2 minutes, gates OPEN ! x) + else if(GetStartDelayTime() < 0 && !(m_Events & 0x10)) + { + m_Events |= 0x10; + SpawnBGObject(BG_EY_OBJECT_DOOR_A, RESPAWN_ONE_DAY); + SpawnBGObject(BG_EY_OBJECT_DOOR_H, RESPAWN_ONE_DAY); + + for(uint32 i = BG_EY_OBJECT_N_BANNER_FEL_REALVER_CENTER; i <= BG_EY_OBJECT_FLAG_NETHERSTORM; ++i) + SpawnBGObject(i, RESPAWN_IMMEDIATELY); + for(uint32 i = 0; i < EY_POINTS_MAX; ++i) + { + //randomly spawn buff + uint8 buff = urand(0, 2); + SpawnBGObject(BG_EY_OBJECT_SPEEDBUFF_FEL_REALVER + buff + i * 3, RESPAWN_IMMEDIATELY); + } + + SendMessageToAll(GetMangosString(LANG_BG_EY_BEGIN)); + + PlaySoundToAll(SOUND_BG_START); + SetStatus(STATUS_IN_PROGRESS); + + for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) + if(Player *plr = objmgr.GetPlayer(itr->first)) + plr->RemoveAurasDueToSpell(SPELL_PREPARATION); + } + } + else if(GetStatus() == STATUS_IN_PROGRESS) + { + m_PointAddingTimer -= diff; + if(m_PointAddingTimer <= 0) + { + m_PointAddingTimer = BG_EY_FPOINTS_TICK_TIME; + if (m_TeamPointsCount[BG_TEAM_ALLIANCE] > 0) + AddPoints(ALLIANCE, BG_EY_TickPoints[m_TeamPointsCount[BG_TEAM_ALLIANCE] - 1]); + if (m_TeamPointsCount[BG_TEAM_HORDE] > 0) + AddPoints(HORDE, BG_EY_TickPoints[m_TeamPointsCount[BG_TEAM_HORDE] - 1]); + } + + if(m_FlagState == BG_EY_FLAG_STATE_WAIT_RESPAWN || m_FlagState == BG_EY_FLAG_STATE_ON_GROUND) + { + m_FlagsTimer -= diff; + + if(m_FlagsTimer < 0) + { + m_FlagsTimer = 0; + if (m_FlagState == BG_EY_FLAG_STATE_WAIT_RESPAWN) + RespawnFlag(true); + else + RespawnFlagAfterDrop(); + } + } + + m_TowerCapCheckTimer -= diff; + if(m_TowerCapCheckTimer <= 0) + { + //check if player joined point + /*I used this order of calls, because although we will check if one player is in gameobject's distance 2 times + but we can count of players on current point in CheckSomeoneLeftPoint + */ + this->CheckSomeoneJoinedPoint(); + //check if player left point + this->CheckSomeoneLeftPoint(); + this->UpdatePointStatuses(); + m_TowerCapCheckTimer = BG_EY_FPOINTS_TICK_TIME; + } + } +} + +void BattleGroundEY::AddPoints(uint32 Team, uint32 Points) +{ + uint8 team_index = GetTeamIndexByTeamId(Team); + m_TeamScores[team_index] += Points; + m_HonorScoreTics[team_index] += Points; + if (m_HonorScoreTics[team_index] >= BG_HONOR_SCORE_TICKS) + { + RewardHonorToTeam(20, Team); + m_HonorScoreTics[team_index] -= BG_HONOR_SCORE_TICKS; + } + UpdateTeamScore(Team); +} + +void BattleGroundEY::CheckSomeoneJoinedPoint() +{ + GameObject *obj = NULL; + for (uint8 i = 0; i < EY_POINTS_MAX; ++i) + { + obj = HashMapHolder::Find(m_BgObjects[BG_EY_OBJECT_TOWER_CAP_FEL_REALVER + i]); + if (obj) + { + uint8 j = 0; + while (j < m_PlayersNearPoint[EY_POINTS_MAX].size()) + { + Player *plr = objmgr.GetPlayer(m_PlayersNearPoint[EY_POINTS_MAX][j]); + if(!plr) + { + sLog.outError("BattleGroundEY: Player " I64FMTD " not found!", m_PlayersNearPoint[EY_POINTS_MAX][j]); + ++j; + continue; + } + if (plr->isAlive() && plr->IsWithinDistInMap(obj, BG_EY_POINT_RADIUS)) + { + //player joined point! + //show progress bar + UpdateWorldStateForPlayer(PROGRESS_BAR_PERCENT_GREY, BG_EY_PROGRESS_BAR_PERCENT_GREY, plr); + UpdateWorldStateForPlayer(PROGRESS_BAR_STATUS, m_PointBarStatus[i], plr); + UpdateWorldStateForPlayer(PROGRESS_BAR_SHOW, BG_EY_PROGRESS_BAR_SHOW, plr); + //add player to point + m_PlayersNearPoint[i].push_back(m_PlayersNearPoint[EY_POINTS_MAX][j]); + //remove player from "free space" + m_PlayersNearPoint[EY_POINTS_MAX].erase(m_PlayersNearPoint[EY_POINTS_MAX].begin() + j); + } + else + ++j; + } + } + } +} + +void BattleGroundEY::CheckSomeoneLeftPoint() +{ + //reset current point counts + for (uint8 i = 0; i < 2*EY_POINTS_MAX; ++i) + m_CurrentPointPlayersCount[i] = 0; + GameObject *obj = NULL; + for(uint8 i = 0; i < EY_POINTS_MAX; ++i) + { + obj = HashMapHolder::Find(m_BgObjects[BG_EY_OBJECT_TOWER_CAP_FEL_REALVER + i]); + if(obj) + { + uint8 j = 0; + while (j < m_PlayersNearPoint[i].size()) + { + Player *plr = objmgr.GetPlayer(m_PlayersNearPoint[i][j]); + if (!plr) + { + sLog.outError("BattleGroundEY: Player " I64FMTD " not found!", m_PlayersNearPoint[i][j]); + //move not existed player to "free space" - this will cause many error showing in log, but it is a very important bug + m_PlayersNearPoint[EY_POINTS_MAX].push_back(m_PlayersNearPoint[i][j]); + m_PlayersNearPoint[i].erase(m_PlayersNearPoint[i].begin() + j); + ++j; + continue; + } + if (!plr->isAlive() || !plr->IsWithinDistInMap(obj, BG_EY_POINT_RADIUS)) + //move player out of point (add him to players that are out of points + { + m_PlayersNearPoint[EY_POINTS_MAX].push_back(m_PlayersNearPoint[i][j]); + m_PlayersNearPoint[i].erase(m_PlayersNearPoint[i].begin() + j); + this->UpdateWorldStateForPlayer(PROGRESS_BAR_SHOW, BG_EY_PROGRESS_BAR_DONT_SHOW, plr); + } + else + { + //player is neat flag, so update count: + m_CurrentPointPlayersCount[2 * i + GetTeamIndexByTeamId(plr->GetTeam())]++; + ++j; + } + } + } + } +} + +void BattleGroundEY::UpdatePointStatuses() +{ + for(uint8 point = 0; point < EY_POINTS_MAX; ++point) + { + if (m_PlayersNearPoint[point].empty()) + continue; + //count new point bar status: + m_PointBarStatus[point] += (m_CurrentPointPlayersCount[2 * point] - m_CurrentPointPlayersCount[2 * point + 1] < BG_EY_POINT_MAX_CAPTURERS_COUNT) ? m_CurrentPointPlayersCount[2 * point] - m_CurrentPointPlayersCount[2 * point + 1] : BG_EY_POINT_MAX_CAPTURERS_COUNT; + + if (m_PointBarStatus[point] > BG_EY_PROGRESS_BAR_ALI_CONTROLLED) + //point is fully alliance's + m_PointBarStatus[point] = BG_EY_PROGRESS_BAR_ALI_CONTROLLED; + if (m_PointBarStatus[point] < BG_EY_PROGRESS_BAR_HORDE_CONTROLLED) + //point is fully horde's + m_PointBarStatus[point] = BG_EY_PROGRESS_BAR_HORDE_CONTROLLED; + + uint32 pointOwnerTeamId = 0; + //find which team should own this point + if (m_PointBarStatus[point] <= BG_EY_PROGRESS_BAR_NEUTRAL_LOW) + pointOwnerTeamId = HORDE; + else if (m_PointBarStatus[point] >= BG_EY_PROGRESS_BAR_NEUTRAL_HIGH) + pointOwnerTeamId = ALLIANCE; + else + pointOwnerTeamId = EY_POINT_NO_OWNER; + + for (uint8 i = 0; i < m_PlayersNearPoint[point].size(); ++i) + { + Player *plr = objmgr.GetPlayer(m_PlayersNearPoint[point][i]); + if (plr) + { + this->UpdateWorldStateForPlayer(PROGRESS_BAR_STATUS, m_PointBarStatus[point], plr); + //if point owner changed we must evoke event! + if (pointOwnerTeamId != m_PointOwnedByTeam[point]) + { + //point was uncontrolled and player is from team which captured point + if (m_PointState[point] == EY_POINT_STATE_UNCONTROLLED && plr->GetTeam() == pointOwnerTeamId) + this->EventTeamCapturedPoint(plr, point); + + //point was under control and player isn't from team which controlled it + if (m_PointState[point] == EY_POINT_UNDER_CONTROL && plr->GetTeam() != m_PointOwnedByTeam[point]) + this->EventTeamLostPoint(plr, point); + } + } + } + } +} + +void BattleGroundEY::UpdateTeamScore(uint32 Team) +{ + uint32 score = GetTeamScore(Team); + if(score >= EY_MAX_TEAM_SCORE) + { + score = EY_MAX_TEAM_SCORE; + EndBattleGround(Team); + } + + if(Team == ALLIANCE) + UpdateWorldState(EY_ALLIANCE_RESOURCES, score); + else + UpdateWorldState(EY_HORDE_RESOURCES, score); +} + +void BattleGroundEY::UpdatePointsCount(uint32 Team) +{ + if(Team == ALLIANCE) + UpdateWorldState(EY_ALLIANCE_BASE, m_TeamPointsCount[BG_TEAM_ALLIANCE]); + else + UpdateWorldState(EY_HORDE_BASE, m_TeamPointsCount[BG_TEAM_HORDE]); +} + +void BattleGroundEY::UpdatePointsIcons(uint32 Team, uint32 Point) +{ + //we MUST firstly send 0, after that we can send 1!!! + if (m_PointState[Point] == EY_POINT_UNDER_CONTROL) + { + UpdateWorldState(m_PointsIconStruct[Point].WorldStateControlIndex, 0); + if(Team == ALLIANCE) + UpdateWorldState(m_PointsIconStruct[Point].WorldStateAllianceControlledIndex, 1); + else + UpdateWorldState(m_PointsIconStruct[Point].WorldStateHordeControlledIndex, 1); + } + else + { + if(Team == ALLIANCE) + UpdateWorldState(m_PointsIconStruct[Point].WorldStateAllianceControlledIndex, 0); + else + UpdateWorldState(m_PointsIconStruct[Point].WorldStateHordeControlledIndex, 0); + UpdateWorldState(m_PointsIconStruct[Point].WorldStateControlIndex, 1); + } +} + +void BattleGroundEY::AddPlayer(Player *plr) +{ + BattleGround::AddPlayer(plr); + //create score and add it to map + BattleGroundEYScore* sc = new BattleGroundEYScore; + + m_PlayersNearPoint[EY_POINTS_MAX].push_back(plr->GetGUID()); + + m_PlayerScores[plr->GetGUID()] = sc; +} + +void BattleGroundEY::RemovePlayer(Player *plr, uint64 guid) +{ + // sometimes flag aura not removed :( + for (int j = EY_POINTS_MAX; j >= 0; --j) + { + for(int i = 0; i < m_PlayersNearPoint[j].size(); ++i) + if(m_PlayersNearPoint[j][i] == guid) + m_PlayersNearPoint[j].erase(m_PlayersNearPoint[j].begin() + i); + } + if(IsFlagPickedup()) + { + if(m_FlagKeeper == guid) + { + if(plr) + this->EventPlayerDroppedFlag(plr); + else + { + SetFlagPicker(0); + RespawnFlag(true); + } + } + } +} + +void BattleGroundEY::HandleAreaTrigger(Player *Source, uint32 Trigger) +{ + if(GetStatus() != STATUS_IN_PROGRESS) + return; + + if(!Source->isAlive()) //hack code, must be removed later + return; + + switch(Trigger) + { + case TR_BLOOD_ELF_POINT: + if(m_PointState[BLOOD_ELF] == EY_POINT_UNDER_CONTROL && m_PointOwnedByTeam[BLOOD_ELF] == Source->GetTeam()) + if(m_FlagState && GetFlagPickerGUID() == Source->GetGUID()) + EventPlayerCapturedFlag(Source, BG_EY_OBJECT_FLAG_BLOOD_ELF); + break; + case TR_FEL_REALVER_POINT: + if(m_PointState[FEL_REALVER] == EY_POINT_UNDER_CONTROL && m_PointOwnedByTeam[FEL_REALVER] == Source->GetTeam()) + if(m_FlagState && GetFlagPickerGUID() == Source->GetGUID()) + EventPlayerCapturedFlag(Source, BG_EY_OBJECT_FLAG_FEL_REALVER); + break; + case TR_MAGE_TOWER_POINT: + if(m_PointState[MAGE_TOWER] == EY_POINT_UNDER_CONTROL && m_PointOwnedByTeam[MAGE_TOWER] == Source->GetTeam()) + if(m_FlagState && GetFlagPickerGUID() == Source->GetGUID()) + EventPlayerCapturedFlag(Source, BG_EY_OBJECT_FLAG_MAGE_TOWER); + break; + case TR_DRAENEI_RUINS_POINT: + if(m_PointState[DRAENEI_RUINS] == EY_POINT_UNDER_CONTROL && m_PointOwnedByTeam[DRAENEI_RUINS] == Source->GetTeam()) + if(m_FlagState && GetFlagPickerGUID() == Source->GetGUID()) + EventPlayerCapturedFlag(Source, BG_EY_OBJECT_FLAG_DRAENEI_RUINS); + break; + case 4512: + case 4515: + case 4517: + case 4519: + case 4530: + case 4531: + case 4568: + case 4569: + case 4570: + case 4571: + break; + default: + sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger); + Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger); + break; + } +} + +bool BattleGroundEY::SetupBattleGround() +{ + // doors + if( !AddObject(BG_EY_OBJECT_DOOR_A, BG_OBJECT_A_DOOR_EY_ENTRY, 2527.6f, 1596.91f, 1262.13f, -3.12414f, -0.173642f, -0.001515f, 0.98477f, -0.008594f, RESPAWN_IMMEDIATELY) + || !AddObject(BG_EY_OBJECT_DOOR_H, BG_OBJECT_H_DOOR_EY_ENTRY, 1803.21f, 1539.49f, 1261.09f, 3.14159f, 0.173648f, 0, 0.984808f, 0, RESPAWN_IMMEDIATELY) + // banners (alliance) + || !AddObject(BG_EY_OBJECT_A_BANNER_FEL_REALVER_CENTER, BG_OBJECT_A_BANNER_EY_ENTRY, 2057.46f, 1735.07f, 1187.91f, -0.925024f, 0, 0, 0.446198f, -0.894934f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_A_BANNER_FEL_REALVER_LEFT, BG_OBJECT_A_BANNER_EY_ENTRY, 2032.25f, 1729.53f, 1190.33f, 1.8675f, 0, 0, 0.803857f, 0.594823f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_A_BANNER_FEL_REALVER_RIGHT, BG_OBJECT_A_BANNER_EY_ENTRY, 2092.35f, 1775.46f, 1187.08f, -0.401426f, 0, 0, 0.199368f, -0.979925f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_A_BANNER_BLOOD_ELF_CENTER, BG_OBJECT_A_BANNER_EY_ENTRY, 2047.19f, 1349.19f, 1189.0f, -1.62316f, 0, 0, 0.725374f, -0.688354f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_A_BANNER_BLOOD_ELF_LEFT, BG_OBJECT_A_BANNER_EY_ENTRY, 2074.32f, 1385.78f, 1194.72f, 0.488692f, 0, 0, 0.241922f, 0.970296f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_A_BANNER_BLOOD_ELF_RIGHT, BG_OBJECT_A_BANNER_EY_ENTRY, 2025.13f, 1386.12f, 1192.74f, 2.3911f, 0, 0, 0.930418f, 0.366501f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_CENTER, BG_OBJECT_A_BANNER_EY_ENTRY, 2276.8f, 1400.41f, 1196.33f, 2.44346f, 0, 0, 0.939693f, 0.34202f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_LEFT, BG_OBJECT_A_BANNER_EY_ENTRY, 2305.78f, 1404.56f, 1199.38f, 1.74533f, 0, 0, 0.766044f, 0.642788f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_RIGHT, BG_OBJECT_A_BANNER_EY_ENTRY, 2245.4f, 1366.41f, 1195.28f, 2.21657f, 0, 0, 0.894934f, 0.446198f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_A_BANNER_MAGE_TOWER_CENTER, BG_OBJECT_A_BANNER_EY_ENTRY, 2270.84f, 1784.08f, 1186.76f, 2.42601f, 0, 0, 0.936672f, 0.350207f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_A_BANNER_MAGE_TOWER_LEFT, BG_OBJECT_A_BANNER_EY_ENTRY, 2269.13f, 1737.7f, 1186.66f, 0.994838f, 0, 0, 0.477159f, 0.878817f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_A_BANNER_MAGE_TOWER_RIGHT, BG_OBJECT_A_BANNER_EY_ENTRY, 2300.86f, 1741.25f, 1187.7f, -0.785398f, 0, 0, 0.382683f, -0.92388f, RESPAWN_ONE_DAY) + // banners (horde) + || !AddObject(BG_EY_OBJECT_H_BANNER_FEL_REALVER_CENTER, BG_OBJECT_H_BANNER_EY_ENTRY, 2057.46f, 1735.07f, 1187.91f, -0.925024f, 0, 0, 0.446198f, -0.894934f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_H_BANNER_FEL_REALVER_LEFT, BG_OBJECT_H_BANNER_EY_ENTRY, 2032.25f, 1729.53f, 1190.33f, 1.8675f, 0, 0, 0.803857f, 0.594823f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_H_BANNER_FEL_REALVER_RIGHT, BG_OBJECT_H_BANNER_EY_ENTRY, 2092.35f, 1775.46f, 1187.08f, -0.401426f, 0, 0, 0.199368f, -0.979925f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_H_BANNER_BLOOD_ELF_CENTER, BG_OBJECT_H_BANNER_EY_ENTRY, 2047.19f, 1349.19f, 1189.0f, -1.62316f, 0, 0, 0.725374f, -0.688354f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_H_BANNER_BLOOD_ELF_LEFT, BG_OBJECT_H_BANNER_EY_ENTRY, 2074.32f, 1385.78f, 1194.72f, 0.488692f, 0, 0, 0.241922f, 0.970296f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_H_BANNER_BLOOD_ELF_RIGHT, BG_OBJECT_H_BANNER_EY_ENTRY, 2025.13f, 1386.12f, 1192.74f, 2.3911f, 0, 0, 0.930418f, 0.366501f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_CENTER, BG_OBJECT_H_BANNER_EY_ENTRY, 2276.8f, 1400.41f, 1196.33f, 2.44346f, 0, 0, 0.939693f, 0.34202f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_LEFT, BG_OBJECT_H_BANNER_EY_ENTRY, 2305.78f, 1404.56f, 1199.38f, 1.74533f, 0, 0, 0.766044f, 0.642788f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_RIGHT, BG_OBJECT_H_BANNER_EY_ENTRY, 2245.4f, 1366.41f, 1195.28f, 2.21657f, 0, 0, 0.894934f, 0.446198f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_H_BANNER_MAGE_TOWER_CENTER, BG_OBJECT_H_BANNER_EY_ENTRY, 2270.84f, 1784.08f, 1186.76f, 2.42601f, 0, 0, 0.936672f, 0.350207f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_H_BANNER_MAGE_TOWER_LEFT, BG_OBJECT_H_BANNER_EY_ENTRY, 2269.13f, 1737.7f, 1186.66f, 0.994838f, 0, 0, 0.477159f, 0.878817f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_H_BANNER_MAGE_TOWER_RIGHT, BG_OBJECT_H_BANNER_EY_ENTRY, 2300.86f, 1741.25f, 1187.7f, -0.785398f, 0, 0, 0.382683f, -0.92388f, RESPAWN_ONE_DAY) + // banners (natural) + || !AddObject(BG_EY_OBJECT_N_BANNER_FEL_REALVER_CENTER, BG_OBJECT_N_BANNER_EY_ENTRY, 2057.46f, 1735.07f, 1187.91f, -0.925024f, 0, 0, 0.446198f, -0.894934f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_N_BANNER_FEL_REALVER_LEFT, BG_OBJECT_N_BANNER_EY_ENTRY, 2032.25f, 1729.53f, 1190.33f, 1.8675f, 0, 0, 0.803857f, 0.594823f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_N_BANNER_FEL_REALVER_RIGHT, BG_OBJECT_N_BANNER_EY_ENTRY, 2092.35f, 1775.46f, 1187.08f, -0.401426f, 0, 0, 0.199368f, -0.979925f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_CENTER, BG_OBJECT_N_BANNER_EY_ENTRY, 2047.19f, 1349.19f, 1189.0f, -1.62316f, 0, 0, 0.725374f, -0.688354f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_LEFT, BG_OBJECT_N_BANNER_EY_ENTRY, 2074.32f, 1385.78f, 1194.72f, 0.488692f, 0, 0, 0.241922f, 0.970296f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_RIGHT, BG_OBJECT_N_BANNER_EY_ENTRY, 2025.13f, 1386.12f, 1192.74f, 2.3911f, 0, 0, 0.930418f, 0.366501f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_CENTER, BG_OBJECT_N_BANNER_EY_ENTRY, 2276.8f, 1400.41f, 1196.33f, 2.44346f, 0, 0, 0.939693f, 0.34202f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_LEFT, BG_OBJECT_N_BANNER_EY_ENTRY, 2305.78f, 1404.56f, 1199.38f, 1.74533f, 0, 0, 0.766044f, 0.642788f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_RIGHT, BG_OBJECT_N_BANNER_EY_ENTRY, 2245.4f, 1366.41f, 1195.28f, 2.21657f, 0, 0, 0.894934f, 0.446198f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_CENTER, BG_OBJECT_N_BANNER_EY_ENTRY, 2270.84f, 1784.08f, 1186.76f, 2.42601f, 0, 0, 0.936672f, 0.350207f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_LEFT, BG_OBJECT_N_BANNER_EY_ENTRY, 2269.13f, 1737.7f, 1186.66f, 0.994838f, 0, 0, 0.477159f, 0.878817f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_RIGHT, BG_OBJECT_N_BANNER_EY_ENTRY, 2300.86f, 1741.25f, 1187.7f, -0.785398f, 0, 0, 0.382683f, -0.92388f, RESPAWN_ONE_DAY) + // flags + || !AddObject(BG_EY_OBJECT_FLAG_NETHERSTORM, BG_OBJECT_FLAG2_EY_ENTRY, 2174.782227f, 1569.054688f, 1160.361938f, -1.448624f, 0, 0, 0.662620f, -0.748956f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_FLAG_FEL_REALVER, BG_OBJECT_FLAG1_EY_ENTRY, 2044.28f, 1729.68f, 1189.96f, -0.017453f, 0, 0, 0.008727f, -0.999962f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_FLAG_BLOOD_ELF, BG_OBJECT_FLAG1_EY_ENTRY, 2048.83f, 1393.65f, 1194.49f, 0.20944f, 0, 0, 0.104528f, 0.994522f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_FLAG_DRAENEI_RUINS, BG_OBJECT_FLAG1_EY_ENTRY, 2286.56f, 1402.36f, 1197.11f, 3.72381f, 0, 0, 0.957926f, -0.287016f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_FLAG_MAGE_TOWER, BG_OBJECT_FLAG1_EY_ENTRY, 2284.48f, 1731.23f, 1189.99f, 2.89725f, 0, 0, 0.992546f, 0.121869f, RESPAWN_ONE_DAY) + // tower cap + || !AddObject(BG_EY_OBJECT_TOWER_CAP_FEL_REALVER, BG_OBJECT_FR_TOWER_CAP_EY_ENTRY, 2024.600708f, 1742.819580f, 1195.157715f, 2.443461f, 0, 0, 0.939693f, 0.342020f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_TOWER_CAP_BLOOD_ELF, BG_OBJECT_BE_TOWER_CAP_EY_ENTRY, 2050.493164f, 1372.235962f, 1194.563477f, 1.710423f, 0, 0, 0.754710f, 0.656059f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_TOWER_CAP_DRAENEI_RUINS, BG_OBJECT_DR_TOWER_CAP_EY_ENTRY, 2301.010498f, 1386.931641f, 1197.183472f, 1.570796f, 0, 0, 0.707107f, 0.707107f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_TOWER_CAP_MAGE_TOWER, BG_OBJECT_HU_TOWER_CAP_EY_ENTRY, 2282.121582f, 1760.006958f, 1189.707153f, 1.919862f, 0, 0, 0.819152f, 0.573576f, RESPAWN_ONE_DAY) + ) + { + sLog.outErrorDb("BatteGroundEY: Failed to spawn some object BattleGround not created!"); + return false; + } + + //buffs + for (int i = 0; i < EY_POINTS_MAX; ++i) + { + AreaTriggerEntry const* at = sAreaTriggerStore.LookupEntry(m_Points_Trigger[i]); + if( !at ) + { + sLog.outError("BattleGroundEY: Unknown trigger: %u", m_Points_Trigger[i]); + continue; + } + if ( !AddObject(BG_EY_OBJECT_SPEEDBUFF_FEL_REALVER + i * 3, Buff_Entries[0], at->x, at->y, at->z, 0.907571f, 0, 0, 0.438371f, 0.898794f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_SPEEDBUFF_FEL_REALVER + i * 3 + 1, Buff_Entries[1], at->x, at->y, at->z, 0.907571f, 0, 0, 0.438371f, 0.898794f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_SPEEDBUFF_FEL_REALVER + i * 3 + 2, Buff_Entries[2], at->x, at->y, at->z, 0.907571f, 0, 0, 0.438371f, 0.898794f, RESPAWN_ONE_DAY) + ) + sLog.outError("BattleGroundEY: Cannot spawn buff"); + } + + WorldSafeLocsEntry const *sg = NULL; + sg = sWorldSafeLocsStore.LookupEntry(EY_GRAVEYARD_MAIN_ALLIANCE); + if( !sg || !AddSpiritGuide(EY_SPIRIT_MAIN_ALLIANCE, sg->x, sg->y, sg->z, 3.124139f, ALLIANCE) ) + { + sLog.outErrorDb("BatteGroundEY: Failed to spawn spirit guide! BattleGround not created!"); + return false; + } + + sg = sWorldSafeLocsStore.LookupEntry(EY_GRAVEYARD_MAIN_HORDE); + if( !sg || !AddSpiritGuide(EY_SPIRIT_MAIN_HORDE, sg->x, sg->y, sg->z, 3.193953f, HORDE) ) + { + sLog.outErrorDb("BatteGroundEY: Failed to spawn spirit guide! BattleGround not created!"); + return false; + } + + return true; +} + +void BattleGroundEY::ResetBGSubclass() +{ + m_TeamScores[BG_TEAM_ALLIANCE] = 0; + m_TeamScores[BG_TEAM_HORDE] = 0; + m_TeamPointsCount[BG_TEAM_ALLIANCE] = 0; + m_TeamPointsCount[BG_TEAM_HORDE] = 0; + m_HonorScoreTics[BG_TEAM_ALLIANCE] = 0; + m_HonorScoreTics[BG_TEAM_HORDE] = 0; + m_FlagState = BG_EY_FLAG_STATE_ON_BASE; + m_FlagCapturedBgObjectType = 0; + m_FlagKeeper = 0; + m_DroppedFlagGUID = 0; + m_PointAddingTimer = 0; + m_TowerCapCheckTimer = 0; + + for(uint8 i = 0; i < EY_POINTS_MAX; ++i) + { + m_PointOwnedByTeam[i] = EY_POINT_NO_OWNER; + m_PointState[i] = EY_POINT_STATE_UNCONTROLLED; + m_PointBarStatus[i] = BG_EY_PROGRESS_BAR_STATE_MIDDLE; + m_PlayersNearPoint[i].clear(); + m_PlayersNearPoint[i].reserve(15); //tip size + } + m_PlayersNearPoint[EY_PLAYERS_OUT_OF_POINTS].clear(); + m_PlayersNearPoint[EY_PLAYERS_OUT_OF_POINTS].reserve(30); +} + +void BattleGroundEY::RespawnFlag(bool send_message) +{ + if (m_FlagCapturedBgObjectType > 0) + SpawnBGObject(m_FlagCapturedBgObjectType, RESPAWN_ONE_DAY); + + m_FlagCapturedBgObjectType = 0; + m_FlagState = BG_EY_FLAG_STATE_ON_BASE; + SpawnBGObject(BG_EY_OBJECT_FLAG_NETHERSTORM, RESPAWN_IMMEDIATELY); + + if(send_message) + { + SendMessageToAll(GetMangosString(LANG_BG_EY_RESETED_FLAG)); + PlaySoundToAll(BG_EY_SOUND_FLAG_RESET); // flags respawned sound... + } + + UpdateWorldState(NETHERSTORM_FLAG, 1); +} + +void BattleGroundEY::RespawnFlagAfterDrop() +{ + RespawnFlag(true); + + GameObject *obj = HashMapHolder::Find(GetDroppedFlagGUID()); + if(obj) + obj->Delete(); + else + sLog.outError("BattleGroundEY: Unknown dropped flag guid: %u",GetDroppedFlagGUID()); + + SetDroppedFlagGUID(0); +} + +void BattleGroundEY::HandleKillPlayer(Player *player, Player *killer) +{ + if(GetStatus() != STATUS_IN_PROGRESS) + return; + + BattleGround::HandleKillPlayer(player, killer); + EventPlayerDroppedFlag(player); +} + +void BattleGroundEY::EventPlayerDroppedFlag(Player *Source) +{ + // Drop allowed in any BG state + + if(!IsFlagPickedup()) + return; + + if(GetFlagPickerGUID() != Source->GetGUID()) + return; + + const char *message = ""; + uint8 type = 0; + + SetFlagPicker(0); + Source->RemoveAurasDueToSpell(BG_EY_NETHERSTORM_FLAG_SPELL); + m_FlagState = BG_EY_FLAG_STATE_ON_GROUND; + m_FlagsTimer = BG_EY_FLAG_RESPAWN_TIME; + Source->CastSpell(Source, SPELL_RECENTLY_DROPPED_FLAG, true); + Source->CastSpell(Source, BG_EY_PLAYER_DROPPED_FLAG_SPELL, true); + if(Source->GetTeam() == ALLIANCE) + { + message = GetMangosString(LANG_BG_EY_DROPPED_FLAG); + type = CHAT_MSG_BG_SYSTEM_ALLIANCE; + } + else + { + message = GetMangosString(LANG_BG_EY_DROPPED_FLAG); + type = CHAT_MSG_BG_SYSTEM_HORDE; + } + //this does not work correctly :( (it should remove flag carrier name) + UpdateWorldState(NETHERSTORM_FLAG_STATE_HORDE, BG_EY_FLAG_STATE_WAIT_RESPAWN); + UpdateWorldState(NETHERSTORM_FLAG_STATE_ALLIANCE, BG_EY_FLAG_STATE_WAIT_RESPAWN); + + WorldPacket data; + ChatHandler::FillMessageData(&data, Source->GetSession(), type, LANG_UNIVERSAL, NULL, Source->GetGUID(), message, NULL); + SendPacketToAll(&data); +} + +void BattleGroundEY::EventPlayerClickedOnFlag(Player *Source, GameObject* target_obj) +{ + if(GetStatus() != STATUS_IN_PROGRESS || this->IsFlagPickedup() || !Source->IsWithinDistInMap(target_obj, 10)) + return; + + const char *message; + uint8 type = 0; + message = GetMangosString(LANG_BG_EY_HAS_TAKEN_FLAG); + + if(Source->GetTeam() == ALLIANCE) + { + UpdateWorldState(NETHERSTORM_FLAG_STATE_ALLIANCE, BG_EY_FLAG_STATE_ON_PLAYER); + type = CHAT_MSG_BG_SYSTEM_ALLIANCE; + PlaySoundToAll(BG_EY_SOUND_FLAG_PICKED_UP_ALLIANCE); + } + else + { + UpdateWorldState(NETHERSTORM_FLAG_STATE_HORDE, BG_EY_FLAG_STATE_ON_PLAYER); + type = CHAT_MSG_BG_SYSTEM_HORDE; + PlaySoundToAll(BG_EY_SOUND_FLAG_PICKED_UP_HORDE); + } + + if (m_FlagState == BG_EY_FLAG_STATE_ON_BASE) + UpdateWorldState(NETHERSTORM_FLAG, 0); + m_FlagState = BG_EY_FLAG_STATE_ON_PLAYER; + + SpawnBGObject(BG_EY_OBJECT_FLAG_NETHERSTORM, RESPAWN_ONE_DAY); + SetFlagPicker(Source->GetGUID()); + //get flag aura on player + Source->CastSpell(Source, BG_EY_NETHERSTORM_FLAG_SPELL, true); + Source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); + + WorldPacket data; + ChatHandler::FillMessageData(&data, Source->GetSession(), type, LANG_UNIVERSAL, NULL, Source->GetGUID(), message, NULL); + SendPacketToAll(&data); +} + +void BattleGroundEY::EventTeamLostPoint(Player *Source, uint32 Point) +{ + if(GetStatus() != STATUS_IN_PROGRESS) + return; + + //Natural point + uint8 message_type = 0; + const char *message = ""; + uint32 Team = m_PointOwnedByTeam[Point]; + + if(!Team) + return; + + if (Team == ALLIANCE) + { + m_TeamPointsCount[BG_TEAM_ALLIANCE]--; + message_type = CHAT_MSG_BG_SYSTEM_ALLIANCE; + message = GetMangosString(m_LoosingPointTypes[Point].MessageIdAlliance); + SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeAlliance, RESPAWN_ONE_DAY); + SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeAlliance + 1, RESPAWN_ONE_DAY); + SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeAlliance + 2, RESPAWN_ONE_DAY); + } + else + { + m_TeamPointsCount[BG_TEAM_HORDE]--; + message_type = CHAT_MSG_BG_SYSTEM_HORDE; + message = GetMangosString(m_LoosingPointTypes[Point].MessageIdHorde); + SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeHorde, RESPAWN_ONE_DAY); + SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeHorde + 1, RESPAWN_ONE_DAY); + SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeHorde + 2, RESPAWN_ONE_DAY); + } + + SpawnBGObject(m_LoosingPointTypes[Point].SpawnNeutralObjectType, RESPAWN_IMMEDIATELY); + SpawnBGObject(m_LoosingPointTypes[Point].SpawnNeutralObjectType + 1, RESPAWN_IMMEDIATELY); + SpawnBGObject(m_LoosingPointTypes[Point].SpawnNeutralObjectType + 2, RESPAWN_IMMEDIATELY); + + //buff isn't despawned + + m_PointOwnedByTeam[Point] = EY_POINT_NO_OWNER; + m_PointState[Point] = EY_POINT_NO_OWNER; + + WorldPacket data; + ChatHandler::FillMessageData(&data, Source->GetSession(), message_type, LANG_UNIVERSAL, NULL, Source->GetGUID(), message, NULL); + SendPacketToAll(&data); + + UpdatePointsIcons(Team, Point); + UpdatePointsCount(Team); +} + +void BattleGroundEY::EventTeamCapturedPoint(Player *Source, uint32 Point) +{ + if(GetStatus() != STATUS_IN_PROGRESS) + return; + + uint8 type = 0; + const char *message = ""; + uint32 Team = Source->GetTeam(); + + SpawnBGObject(m_CapturingPointTypes[Point].DespawnNeutralObjectType, RESPAWN_ONE_DAY); + SpawnBGObject(m_CapturingPointTypes[Point].DespawnNeutralObjectType + 1, RESPAWN_ONE_DAY); + SpawnBGObject(m_CapturingPointTypes[Point].DespawnNeutralObjectType + 2, RESPAWN_ONE_DAY); + + if (Team == ALLIANCE) + { + m_TeamPointsCount[BG_TEAM_ALLIANCE]++; + type = CHAT_MSG_BG_SYSTEM_ALLIANCE; + message = GetMangosString(m_CapturingPointTypes[Point].MessageIdAlliance); + SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeAlliance, RESPAWN_IMMEDIATELY); + SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeAlliance + 1, RESPAWN_IMMEDIATELY); + SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeAlliance + 2, RESPAWN_IMMEDIATELY); + } + else + { + m_TeamPointsCount[BG_TEAM_HORDE]++; + type = CHAT_MSG_BG_SYSTEM_HORDE; + message = GetMangosString(m_CapturingPointTypes[Point].MessageIdHorde); + SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeHorde, RESPAWN_IMMEDIATELY); + SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeHorde + 1, RESPAWN_IMMEDIATELY); + SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeHorde + 2, RESPAWN_IMMEDIATELY); + } + + //buff isn't respawned + + m_PointOwnedByTeam[Point] = Team; + m_PointState[Point] = EY_POINT_UNDER_CONTROL; + + WorldPacket data; + ChatHandler::FillMessageData(&data, Source->GetSession(), type, LANG_UNIVERSAL, NULL, Source->GetGUID(), message, NULL); + SendPacketToAll(&data); + + if(m_BgCreatures[Point]) + DelCreature(Point); + + WorldSafeLocsEntry const *sg = NULL; + sg = sWorldSafeLocsStore.LookupEntry(m_CapturingPointTypes[Point].GraveYardId); + if(!sg || !AddSpiritGuide(Point, sg->x, sg->y, sg->z, 3.124139f, Team)) + sLog.outError("BatteGroundEY: Failed to spawn spirit guide! point: %u, team: u, graveyard_id: %u", Point, Team, m_CapturingPointTypes[Point].GraveYardId); + + UpdatePointsIcons(Team, Point); + UpdatePointsCount(Team); +} + +void BattleGroundEY::EventPlayerCapturedFlag(Player *Source, uint32 BgObjectType) +{ + if(GetStatus() != STATUS_IN_PROGRESS || this->GetFlagPickerGUID() != Source->GetGUID()) + return; + + uint8 type = 0; + uint8 team_id = 0; + const char *message = ""; + + SetFlagPicker(0); + m_FlagState = BG_EY_FLAG_STATE_WAIT_RESPAWN; + Source->RemoveAurasDueToSpell(BG_EY_NETHERSTORM_FLAG_SPELL); + + Source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); + if(Source->GetTeam() == ALLIANCE) + { + PlaySoundToAll(BG_EY_SOUND_FLAG_CAPTURED_ALLIANCE); + team_id = BG_TEAM_ALLIANCE; + message = GetMangosString(LANG_BG_EY_CAPTURED_FLAG_A); + type = CHAT_MSG_BG_SYSTEM_ALLIANCE; + } + else + { + PlaySoundToAll(BG_EY_SOUND_FLAG_CAPTURED_HORDE); + team_id = BG_TEAM_HORDE; + message = GetMangosString(LANG_BG_EY_CAPTURED_FLAG_H); + type = CHAT_MSG_BG_SYSTEM_HORDE; + } + + SpawnBGObject(BgObjectType, RESPAWN_IMMEDIATELY); + + m_FlagsTimer = BG_EY_FLAG_RESPAWN_TIME; + m_FlagCapturedBgObjectType = BgObjectType; + + WorldPacket data; + ChatHandler::FillMessageData(&data, Source->GetSession(), type, LANG_UNIVERSAL, NULL, Source->GetGUID(), message, NULL); + SendPacketToAll(&data); + + if(m_TeamPointsCount[team_id] > 0) + AddPoints(Source->GetTeam(), BG_EY_FlagPoints[m_TeamPointsCount[team_id] - 1]); + + UpdatePlayerScore(Source, SCORE_FLAG_CAPTURES, 1); +} + +void BattleGroundEY::UpdatePlayerScore(Player *Source, uint32 type, uint32 value) +{ + std::map::iterator itr = m_PlayerScores.find(Source->GetGUID()); + + if(itr == m_PlayerScores.end()) // player not found + return; + + switch(type) + { + case SCORE_FLAG_CAPTURES: // flags captured + ((BattleGroundEYScore*)itr->second)->FlagCaptures += value; + break; + default: + BattleGround::UpdatePlayerScore(Source, type, value); + break; + } +} + +void BattleGroundEY::FillInitialWorldStates(WorldPacket& data) +{ + data << uint32(EY_HORDE_BASE) << uint32(m_TeamPointsCount[BG_TEAM_HORDE]); + data << uint32(EY_ALLIANCE_BASE) << uint32(m_TeamPointsCount[BG_TEAM_ALLIANCE]); + data << uint32(0xab6) << uint32(0x0); + data << uint32(0xab5) << uint32(0x0); + data << uint32(0xab4) << uint32(0x0); + data << uint32(0xab3) << uint32(0x0); + data << uint32(0xab2) << uint32(0x0); + data << uint32(0xab1) << uint32(0x0); + data << uint32(0xab0) << uint32(0x0); + data << uint32(0xaaf) << uint32(0x0); + + data << uint32(DRAENEI_RUINS_HORDE_CONTROL) << uint32(m_PointOwnedByTeam[DRAENEI_RUINS] == HORDE && m_PointState[DRAENEI_RUINS] == EY_POINT_UNDER_CONTROL); + + data << uint32(DRAENEI_RUINS_ALLIANCE_CONTROL) << uint32(m_PointOwnedByTeam[DRAENEI_RUINS] == ALLIANCE && m_PointState[DRAENEI_RUINS] == EY_POINT_UNDER_CONTROL); + + data << uint32(DRAENEI_RUINS_UNCONTROL) << uint32(m_PointState[DRAENEI_RUINS] != EY_POINT_UNDER_CONTROL); + + data << uint32(MAGE_TOWER_ALLIANCE_CONTROL) << uint32(m_PointOwnedByTeam[MAGE_TOWER] == ALLIANCE && m_PointState[MAGE_TOWER] == EY_POINT_UNDER_CONTROL); + + data << uint32(MAGE_TOWER_HORDE_CONTROL) << uint32(m_PointOwnedByTeam[MAGE_TOWER] == HORDE && m_PointState[MAGE_TOWER] == EY_POINT_UNDER_CONTROL); + + data << uint32(MAGE_TOWER_UNCONTROL) << uint32(m_PointState[MAGE_TOWER] != EY_POINT_UNDER_CONTROL); + + data << uint32(FEL_REAVER_HORDE_CONTROL) << uint32(m_PointOwnedByTeam[FEL_REALVER] == HORDE && m_PointState[FEL_REALVER] == EY_POINT_UNDER_CONTROL); + + data << uint32(FEL_REAVER_ALLIANCE_CONTROL) << uint32(m_PointOwnedByTeam[FEL_REALVER] == ALLIANCE && m_PointState[FEL_REALVER] == EY_POINT_UNDER_CONTROL); + + data << uint32(FEL_REAVER_UNCONTROL) << uint32(m_PointState[FEL_REALVER] != EY_POINT_UNDER_CONTROL); + + data << uint32(BLOOD_ELF_HORDE_CONTROL) << uint32(m_PointOwnedByTeam[BLOOD_ELF] == HORDE && m_PointState[BLOOD_ELF] == EY_POINT_UNDER_CONTROL); + + data << uint32(BLOOD_ELF_ALLIANCE_CONTROL) << uint32(m_PointOwnedByTeam[BLOOD_ELF] == ALLIANCE && m_PointState[BLOOD_ELF] == EY_POINT_UNDER_CONTROL); + + data << uint32(BLOOD_ELF_UNCONTROL) << uint32(m_PointState[BLOOD_ELF] != EY_POINT_UNDER_CONTROL); + + data << uint32(NETHERSTORM_FLAG) << uint32(m_FlagState == BG_EY_FLAG_STATE_ON_BASE); + + data << uint32(0xad2) << uint32(0x1); + data << uint32(0xad1) << uint32(0x1); + data << uint32(0xabe) << uint32(GetTeamScore(HORDE)); + data << uint32(0xabd) << uint32(GetTeamScore(ALLIANCE)); + data << uint32(0xa05) << uint32(0x8e); + data << uint32(0xaa0) << uint32(0x0); + data << uint32(0xa9f) << uint32(0x0); + data << uint32(0xa9e) << uint32(0x0); + data << uint32(0xc0d) << uint32(0x17b); +} + +WorldSafeLocsEntry const *BattleGroundEY::GetClosestGraveYard(float x, float y, float z, uint32 team) +{ + uint32 g_id = 0; + + if(team == ALLIANCE) + g_id = EY_GRAVEYARD_MAIN_ALLIANCE; + else if(team == HORDE) + g_id = EY_GRAVEYARD_MAIN_HORDE; + else + return NULL; + + float distance, nearestDistance; + + WorldSafeLocsEntry const* entry = NULL; + WorldSafeLocsEntry const* nearestEntry = NULL; + entry = sWorldSafeLocsStore.LookupEntry(g_id); + nearestEntry = entry; + + if(!entry) + { + sLog.outError("BattleGroundEY: Not found the main team graveyard. Graveyard system isn't working!"); + return NULL; + } + + distance = (entry->x - x)*(entry->x - x) + (entry->y - y)*(entry->y - y) + (entry->z - z)*(entry->z - z); + nearestDistance = distance; + + for(uint8 i = 0; i < EY_POINTS_MAX; ++i) + { + if(m_PointOwnedByTeam[i]==team && m_PointState[i]==EY_POINT_UNDER_CONTROL) + { + entry = sWorldSafeLocsStore.LookupEntry(m_CapturingPointTypes[i].GraveYardId); + if(!entry) + sLog.outError("BattleGroundEY: Not found graveyard: %u",m_CapturingPointTypes[i].GraveYardId); + else + { + distance = (entry->x - x)*(entry->x - x) + (entry->y - y)*(entry->y - y) + (entry->z - z)*(entry->z - z); + if(distance < nearestDistance) + { + nearestDistance = distance; + nearestEntry = entry; + } + } + } + } + + return nearestEntry; +} diff --git a/src/game/BattleGroundEY.h b/src/game/BattleGroundEY.h new file mode 100644 index 00000000000..661f107682d --- /dev/null +++ b/src/game/BattleGroundEY.h @@ -0,0 +1,372 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __BATTLEGROUNDEY_H +#define __BATTLEGROUNDEY_H + +#include "Language.h" + +class BattleGround; + +#define EY_MAX_TEAM_SCORE 2000 +#define BG_EY_FLAG_RESPAWN_TIME 10000 //10 seconds +#define BG_EY_FPOINTS_TICK_TIME 2000 //2 seconds + +enum BG_EY_WorldStates +{ + EY_ALLIANCE_RESOURCES = 2749, + EY_HORDE_RESOURCES = 2750, + EY_ALLIANCE_BASE = 2752, + EY_HORDE_BASE = 2753, + DRAENEI_RUINS_HORDE_CONTROL = 2733, + DRAENEI_RUINS_ALLIANCE_CONTROL = 2732, + DRAENEI_RUINS_UNCONTROL = 2731, + MAGE_TOWER_ALLIANCE_CONTROL = 2730, + MAGE_TOWER_HORDE_CONTROL = 2729, + MAGE_TOWER_UNCONTROL = 2728, + FEL_REAVER_HORDE_CONTROL = 2727, + FEL_REAVER_ALLIANCE_CONTROL = 2726, + FEL_REAVER_UNCONTROL = 2725, + BLOOD_ELF_HORDE_CONTROL = 2724, + BLOOD_ELF_ALLIANCE_CONTROL = 2723, + BLOOD_ELF_UNCONTROL = 2722, + PROGRESS_BAR_PERCENT_GREY = 2720, //100 = empty (only grey), 0 = blue|red (no grey) + PROGRESS_BAR_STATUS = 2719, //50 init!, 48 ... hordak bere .. 33 .. 0 = full 100% hordacky , 100 = full alliance + PROGRESS_BAR_SHOW = 2718, //1 init, 0 druhy send - bez messagu, 1 = controlled aliance + NETHERSTORM_FLAG = 2757, + //set to 2 when flag is picked up, and to 1 if it is dropped + NETHERSTORM_FLAG_STATE_ALLIANCE = 2769, + NETHERSTORM_FLAG_STATE_HORDE = 2770 +}; + +enum BG_EY_ProgressBarConsts +{ + BG_EY_POINT_MAX_CAPTURERS_COUNT = 5, + BG_EY_POINT_RADIUS = 70, + BG_EY_PROGRESS_BAR_DONT_SHOW = 0, + BG_EY_PROGRESS_BAR_SHOW = 1, + BG_EY_PROGRESS_BAR_PERCENT_GREY = 40, + BG_EY_PROGRESS_BAR_STATE_MIDDLE = 50, + BG_EY_PROGRESS_BAR_HORDE_CONTROLLED = 0, + BG_EY_PROGRESS_BAR_NEUTRAL_LOW = 30, + BG_EY_PROGRESS_BAR_NEUTRAL_HIGH = 70, + BG_EY_PROGRESS_BAR_ALI_CONTROLLED = 100 +}; + +enum BG_EY_Sounds +{ + //strange ids, but sure about them + BG_EY_SOUND_FLAG_PICKED_UP_ALLIANCE = 8212, + BG_EY_SOUND_FLAG_CAPTURED_HORDE = 8213, + BG_EY_SOUND_FLAG_PICKED_UP_HORDE = 8174, + BG_EY_SOUND_FLAG_CAPTURED_ALLIANCE = 8173, + BG_EY_SOUND_FLAG_RESET = 8192 +}; + +enum BG_EY_Spells +{ + BG_EY_NETHERSTORM_FLAG_SPELL = 34976, + BG_EY_PLAYER_DROPPED_FLAG_SPELL = 34991 +}; + +enum EYBattleGroundObjectEntry +{ + BG_OBJECT_A_DOOR_EY_ENTRY = 184719, //Alliance door + BG_OBJECT_H_DOOR_EY_ENTRY = 184720, //Horde door + BG_OBJECT_FLAG1_EY_ENTRY = 184493, //Netherstorm flag (generic) + BG_OBJECT_FLAG2_EY_ENTRY = 184141, //Netherstorm flag (flagstand) + BG_OBJECT_FLAG3_EY_ENTRY = 184142, //Netherstorm flag (flagdrop) + BG_OBJECT_A_BANNER_EY_ENTRY = 184381, //Visual Banner (Alliance) + BG_OBJECT_H_BANNER_EY_ENTRY = 184380, //Visual Banner (Horde) + BG_OBJECT_N_BANNER_EY_ENTRY = 184382, //Visual Banner (Neutral) + BG_OBJECT_BE_TOWER_CAP_EY_ENTRY = 184080, //BE Tower Cap Pt + BG_OBJECT_FR_TOWER_CAP_EY_ENTRY = 184081, //Fel Reaver Cap Pt + BG_OBJECT_HU_TOWER_CAP_EY_ENTRY = 184082, //Human Tower Cap Pt + BG_OBJECT_DR_TOWER_CAP_EY_ENTRY = 184083 //Draenei Tower Cap Pt +}; + +enum EYBattleGroundPointsTrigger +{ + TR_BLOOD_ELF_POINT = 4476, + TR_FEL_REALVER_POINT = 4514, + TR_MAGE_TOWER_POINT = 4516, + TR_DRAENEI_RUINS_POINT = 4518, + TR_BLOOD_ELF_BUFF = 4568, + TR_FEL_REALVER_BUFF = 4569, + TR_MAGE_TOWER_BUFF = 4570, + TR_DRAENEI_RUINS_BUFF = 4571 +}; + +enum EYBattleGroundGaveyards +{ + EY_GRAVEYARD_MAIN_ALLIANCE = 1103, + EY_GRAVEYARD_MAIN_HORDE = 1104, + EY_GRAVEYARD_FEL_REALVER = 1105, + EY_GRAVEYARD_BLOOD_ELF = 1106, + EY_GRAVEYARD_DRAENEI_RUINS = 1107, + EY_GRAVEYARD_MAGE_TOWER = 1108 +}; + +enum EYBattleGroundPoints +{ + FEL_REALVER = 0, + BLOOD_ELF = 1, + DRAENEI_RUINS = 2, + MAGE_TOWER = 3, + + EY_PLAYERS_OUT_OF_POINTS = 4, + EY_POINTS_MAX = 4 +}; + +enum EYBattleGroundCreaturesTypes +{ + EY_SPIRIT_FEL_REALVER = 0, + EY_SPIRIT_BLOOD_ELF = 1, + EY_SPIRIT_DRAENEI_RUINS = 2, + EY_SPIRIT_MAGE_TOWER = 3, + EY_SPIRIT_MAIN_ALLIANCE = 4, + EY_SPIRIT_MAIN_HORDE = 5, + + BG_EY_CREATURES_MAX = 6 +}; + +enum EYBattleGroundObjectTypes +{ + BG_EY_OBJECT_DOOR_A = 0, + BG_EY_OBJECT_DOOR_H = 1, + BG_EY_OBJECT_A_BANNER_FEL_REALVER_CENTER = 2, + BG_EY_OBJECT_A_BANNER_FEL_REALVER_LEFT = 3, + BG_EY_OBJECT_A_BANNER_FEL_REALVER_RIGHT = 4, + BG_EY_OBJECT_A_BANNER_BLOOD_ELF_CENTER = 5, + BG_EY_OBJECT_A_BANNER_BLOOD_ELF_LEFT = 6, + BG_EY_OBJECT_A_BANNER_BLOOD_ELF_RIGHT = 7, + BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_CENTER = 8, + BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_LEFT = 9, + BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_RIGHT = 10, + BG_EY_OBJECT_A_BANNER_MAGE_TOWER_CENTER = 11, + BG_EY_OBJECT_A_BANNER_MAGE_TOWER_LEFT = 12, + BG_EY_OBJECT_A_BANNER_MAGE_TOWER_RIGHT = 13, + BG_EY_OBJECT_H_BANNER_FEL_REALVER_CENTER = 14, + BG_EY_OBJECT_H_BANNER_FEL_REALVER_LEFT = 15, + BG_EY_OBJECT_H_BANNER_FEL_REALVER_RIGHT = 16, + BG_EY_OBJECT_H_BANNER_BLOOD_ELF_CENTER = 17, + BG_EY_OBJECT_H_BANNER_BLOOD_ELF_LEFT = 18, + BG_EY_OBJECT_H_BANNER_BLOOD_ELF_RIGHT = 19, + BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_CENTER = 20, + BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_LEFT = 21, + BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_RIGHT = 22, + BG_EY_OBJECT_H_BANNER_MAGE_TOWER_CENTER = 23, + BG_EY_OBJECT_H_BANNER_MAGE_TOWER_LEFT = 24, + BG_EY_OBJECT_H_BANNER_MAGE_TOWER_RIGHT = 25, + BG_EY_OBJECT_N_BANNER_FEL_REALVER_CENTER = 26, + BG_EY_OBJECT_N_BANNER_FEL_REALVER_LEFT = 27, + BG_EY_OBJECT_N_BANNER_FEL_REALVER_RIGHT = 28, + BG_EY_OBJECT_N_BANNER_BLOOD_ELF_CENTER = 29, + BG_EY_OBJECT_N_BANNER_BLOOD_ELF_LEFT = 30, + BG_EY_OBJECT_N_BANNER_BLOOD_ELF_RIGHT = 31, + BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_CENTER = 32, + BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_LEFT = 33, + BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_RIGHT = 34, + BG_EY_OBJECT_N_BANNER_MAGE_TOWER_CENTER = 35, + BG_EY_OBJECT_N_BANNER_MAGE_TOWER_LEFT = 36, + BG_EY_OBJECT_N_BANNER_MAGE_TOWER_RIGHT = 37, + BG_EY_OBJECT_TOWER_CAP_FEL_REALVER = 38, + BG_EY_OBJECT_TOWER_CAP_BLOOD_ELF = 39, + BG_EY_OBJECT_TOWER_CAP_DRAENEI_RUINS = 40, + BG_EY_OBJECT_TOWER_CAP_MAGE_TOWER = 41, + BG_EY_OBJECT_FLAG_NETHERSTORM = 42, + BG_EY_OBJECT_FLAG_FEL_REALVER = 43, + BG_EY_OBJECT_FLAG_BLOOD_ELF = 44, + BG_EY_OBJECT_FLAG_DRAENEI_RUINS = 45, + BG_EY_OBJECT_FLAG_MAGE_TOWER = 46, + //buffs + BG_EY_OBJECT_SPEEDBUFF_FEL_REALVER = 47, + BG_EY_OBJECT_REGENBUFF_FEL_REALVER = 48, + BG_EY_OBJECT_BERSERKBUFF_FEL_REALVER = 49, + BG_EY_OBJECT_SPEEDBUFF_BLOOD_ELF = 50, + BG_EY_OBJECT_REGENBUFF_BLOOD_ELF = 51, + BG_EY_OBJECT_BERSERKBUFF_BLOOD_ELF = 52, + BG_EY_OBJECT_SPEEDBUFF_DRAENEI_RUINS = 53, + BG_EY_OBJECT_REGENBUFF_DRAENEI_RUINS = 54, + BG_EY_OBJECT_BERSERKBUFF_DRAENEI_RUINS = 55, + BG_EY_OBJECT_SPEEDBUFF_MAGE_TOWER = 56, + BG_EY_OBJECT_REGENBUFF_MAGE_TOWER = 57, + BG_EY_OBJECT_BERSERKBUFF_MAGE_TOWER = 58, + BG_EY_OBJECT_MAX = 59 +}; + +enum BG_EY_FlagState +{ + BG_EY_FLAG_STATE_ON_BASE = 0, + BG_EY_FLAG_STATE_WAIT_RESPAWN = 1, + BG_EY_FLAG_STATE_ON_PLAYER = 2, + BG_EY_FLAG_STATE_ON_GROUND = 3 +}; + +enum EYBattleGroundPointState +{ + EY_POINT_NO_OWNER = 0, + EY_POINT_STATE_UNCONTROLLED = 0, + EY_POINT_UNDER_CONTROL = 3 +}; + +struct BattleGroundEYPointIconsStruct +{ + BattleGroundEYPointIconsStruct(uint32 _WorldStateControlIndex, uint32 _WorldStateAllianceControlledIndex, uint32 _WorldStateHordeControlledIndex) + : WorldStateControlIndex(_WorldStateControlIndex), WorldStateAllianceControlledIndex(_WorldStateAllianceControlledIndex), WorldStateHordeControlledIndex(_WorldStateHordeControlledIndex) {} + uint32 WorldStateControlIndex; + uint32 WorldStateAllianceControlledIndex; + uint32 WorldStateHordeControlledIndex; +}; + +struct BattleGroundEYLoosingPointStruct +{ + BattleGroundEYLoosingPointStruct(uint32 _SpawnNeutralObjectType, uint32 _DespawnObjectTypeAlliance, uint32 _MessageIdAlliance, uint32 _DespawnObjectTypeHorde, uint32 _MessageIdHorde) + : SpawnNeutralObjectType(_SpawnNeutralObjectType), DespawnObjectTypeAlliance(_DespawnObjectTypeAlliance), MessageIdAlliance(_MessageIdAlliance), DespawnObjectTypeHorde(_DespawnObjectTypeHorde), MessageIdHorde(_MessageIdHorde) {} + uint32 SpawnNeutralObjectType; + uint32 DespawnObjectTypeAlliance; + uint32 DespawnObjectTypeHorde; + uint32 MessageIdHorde; + uint32 MessageIdAlliance; +}; + +struct BattleGroundEYCapturingPointStruct +{ + BattleGroundEYCapturingPointStruct(uint32 _DespawnNeutralObjectType, uint32 _SpawnObjectTypeAlliance, uint32 _MessageIdAlliance, uint32 _SpawnObjectTypeHorde, uint32 _MessageIdHorde, uint32 _GraveYardId) + : DespawnNeutralObjectType(_DespawnNeutralObjectType), SpawnObjectTypeAlliance(_SpawnObjectTypeAlliance), MessageIdAlliance(_MessageIdAlliance), SpawnObjectTypeHorde(_SpawnObjectTypeHorde), MessageIdHorde(_MessageIdHorde), GraveYardId(_GraveYardId) {} + uint32 DespawnNeutralObjectType; + uint32 SpawnObjectTypeAlliance; + uint32 SpawnObjectTypeHorde; + uint32 MessageIdHorde; + uint32 MessageIdAlliance; + uint32 GraveYardId; +}; + +const uint8 BG_EY_TickPoints[EY_POINTS_MAX] = {1, 2, 5, 10}; +const uint32 BG_EY_FlagPoints[EY_POINTS_MAX] = {75, 85, 100, 500}; + +//constant arrays: +const BattleGroundEYPointIconsStruct m_PointsIconStruct[EY_POINTS_MAX] = +{ + BattleGroundEYPointIconsStruct(FEL_REAVER_UNCONTROL, FEL_REAVER_ALLIANCE_CONTROL, FEL_REAVER_HORDE_CONTROL), + BattleGroundEYPointIconsStruct(BLOOD_ELF_UNCONTROL, BLOOD_ELF_ALLIANCE_CONTROL, BLOOD_ELF_HORDE_CONTROL), + BattleGroundEYPointIconsStruct(DRAENEI_RUINS_UNCONTROL, DRAENEI_RUINS_ALLIANCE_CONTROL, DRAENEI_RUINS_HORDE_CONTROL), + BattleGroundEYPointIconsStruct(MAGE_TOWER_UNCONTROL, MAGE_TOWER_ALLIANCE_CONTROL, MAGE_TOWER_HORDE_CONTROL) +}; +const BattleGroundEYLoosingPointStruct m_LoosingPointTypes[EY_POINTS_MAX] = +{ + BattleGroundEYLoosingPointStruct(BG_EY_OBJECT_N_BANNER_FEL_REALVER_CENTER, BG_EY_OBJECT_A_BANNER_FEL_REALVER_CENTER, LANG_BG_EY_HAS_LOST_A_F_RUINS, BG_EY_OBJECT_H_BANNER_FEL_REALVER_CENTER, LANG_BG_EY_HAS_LOST_H_F_RUINS), + BattleGroundEYLoosingPointStruct(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_CENTER, BG_EY_OBJECT_A_BANNER_BLOOD_ELF_CENTER, LANG_BG_EY_HAS_LOST_A_B_TOWER, BG_EY_OBJECT_H_BANNER_BLOOD_ELF_CENTER, LANG_BG_EY_HAS_LOST_H_B_TOWER), + BattleGroundEYLoosingPointStruct(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_CENTER, BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_CENTER, LANG_BG_EY_HAS_LOST_A_D_RUINS, BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_CENTER, LANG_BG_EY_HAS_LOST_H_D_RUINS), + BattleGroundEYLoosingPointStruct(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_CENTER, BG_EY_OBJECT_A_BANNER_MAGE_TOWER_CENTER, LANG_BG_EY_HAS_LOST_A_M_TOWER, BG_EY_OBJECT_H_BANNER_MAGE_TOWER_CENTER, LANG_BG_EY_HAS_LOST_H_M_TOWER) +}; +const BattleGroundEYCapturingPointStruct m_CapturingPointTypes[EY_POINTS_MAX] = +{ + BattleGroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_FEL_REALVER_CENTER, BG_EY_OBJECT_A_BANNER_FEL_REALVER_CENTER, LANG_BG_EY_HAS_TAKEN_A_F_RUINS, BG_EY_OBJECT_H_BANNER_FEL_REALVER_CENTER, LANG_BG_EY_HAS_TAKEN_H_F_RUINS, EY_GRAVEYARD_FEL_REALVER), + BattleGroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_CENTER, BG_EY_OBJECT_A_BANNER_BLOOD_ELF_CENTER, LANG_BG_EY_HAS_TAKEN_A_B_TOWER, BG_EY_OBJECT_H_BANNER_BLOOD_ELF_CENTER, LANG_BG_EY_HAS_TAKEN_H_B_TOWER, EY_GRAVEYARD_BLOOD_ELF), + BattleGroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_CENTER, BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_CENTER, LANG_BG_EY_HAS_TAKEN_A_D_RUINS, BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_CENTER, LANG_BG_EY_HAS_TAKEN_H_D_RUINS, EY_GRAVEYARD_DRAENEI_RUINS), + BattleGroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_CENTER, BG_EY_OBJECT_A_BANNER_MAGE_TOWER_CENTER, LANG_BG_EY_HAS_TAKEN_A_M_TOWER, BG_EY_OBJECT_H_BANNER_MAGE_TOWER_CENTER, LANG_BG_EY_HAS_TAKEN_H_M_TOWER, EY_GRAVEYARD_MAGE_TOWER) +}; + +class BattleGroundEYScore : public BattleGroundScore +{ + public: + BattleGroundEYScore () : FlagCaptures(0) {}; + virtual ~BattleGroundEYScore() {}; + uint32 FlagCaptures; +}; + +class BattleGroundEY : public BattleGround +{ + friend class BattleGroundMgr; + + public: + BattleGroundEY(); + ~BattleGroundEY(); + void Update(time_t diff); + + /* inherited from BattlegroundClass */ + virtual void AddPlayer(Player *plr); + + /* BG Flags */ + uint64 GetFlagPickerGUID() const { return m_FlagKeeper; } + void SetFlagPicker(uint64 guid) { m_FlagKeeper = guid; } + bool IsFlagPickedup() const { return m_FlagKeeper != 0; } + uint8 GetFlagState() const { return m_FlagState; } + void RespawnFlag(bool send_message); + void RespawnFlagAfterDrop(); + + void RemovePlayer(Player *plr,uint64 guid); + void HandleBuffUse(uint64 const& buff_guid); + void HandleAreaTrigger(Player *Source, uint32 Trigger); + void HandleKillPlayer(Player *player, Player *killer); + virtual WorldSafeLocsEntry const* GetClosestGraveYard(float x, float y, float z, uint32 team); + virtual bool SetupBattleGround(); + virtual void ResetBGSubclass(); + void UpdateTeamScore(uint32 Team); + void UpdatePlayerScore(Player *Source, uint32 type, uint32 value); + virtual void FillInitialWorldStates(WorldPacket& data); + void SetDroppedFlagGUID(uint64 guid) { m_DroppedFlagGUID = guid;} + uint64 GetDroppedFlagGUID() const { return m_DroppedFlagGUID;} + + /* Battleground Events */ + virtual void EventPlayerClickedOnFlag(Player *Source, GameObject* target_obj); + virtual void EventPlayerDroppedFlag(Player *Source); + + private: + void EventPlayerCapturedFlag(Player *Source, uint32 BgObjectType); + void EventTeamCapturedPoint(Player *Source, uint32 Point); + void EventTeamLostPoint(Player *Source, uint32 Point); + void UpdatePointsCount(uint32 Team); + void UpdatePointsIcons(uint32 Team, uint32 Point); + + /* Point status updating procedures */ + void CheckSomeoneLeftPoint(); + void CheckSomeoneJoinedPoint(); + void UpdatePointStatuses(); + + /* Scorekeeping */ + uint32 GetTeamScore(uint32 Team) const { return m_TeamScores[GetTeamIndexByTeamId(Team)]; } + void AddPoints(uint32 Team, uint32 Points); + + void RemovePoint(uint32 TeamID, uint32 Points = 1) { m_TeamScores[GetTeamIndexByTeamId(TeamID)] -= Points; } + void SetTeamPoint(uint32 TeamID, uint32 Points = 0) { m_TeamScores[GetTeamIndexByTeamId(TeamID)] = Points; } + + uint32 m_TeamScores[2]; + uint32 m_HonorScoreTics[2]; + uint32 m_TeamPointsCount[2]; + + uint32 m_Points_Trigger[EY_POINTS_MAX]; + + uint64 m_FlagKeeper; // keepers guid + uint64 m_DroppedFlagGUID; + uint32 m_FlagCapturedBgObjectType; // type that should be despawned when flag is captured + uint8 m_FlagState; // for checking flag state + int32 m_FlagsTimer; + int32 m_TowerCapCheckTimer; + + uint32 m_PointOwnedByTeam[EY_POINTS_MAX]; + uint8 m_PointState[EY_POINTS_MAX]; + int32 m_PointBarStatus[EY_POINTS_MAX]; + typedef std::vector PlayersNearPointType; + PlayersNearPointType m_PlayersNearPoint[EY_POINTS_MAX + 1]; + uint8 m_CurrentPointPlayersCount[2*EY_POINTS_MAX]; + + int32 m_PointAddingTimer; +}; +#endif diff --git a/src/game/BattleGroundHandler.cpp b/src/game/BattleGroundHandler.cpp new file mode 100644 index 00000000000..85de6855563 --- /dev/null +++ b/src/game/BattleGroundHandler.cpp @@ -0,0 +1,621 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "WorldPacket.h" +#include "Opcodes.h" +#include "Log.h" +#include "Player.h" +#include "ObjectMgr.h" +#include "WorldSession.h" +#include "MapManager.h" +#include "ObjectAccessor.h" +#include "Object.h" +#include "BattleGroundMgr.h" +#include "BattleGroundWS.h" +#include "BattleGround.h" + +void WorldSession::HandleBattleGroundHelloOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data, 8); + + uint64 guid; + recv_data >> guid; + sLog.outDebug( "WORLD: Recvd CMSG_BATTLEMASTER_HELLO Message from: " I64FMT, guid); + + Creature *unit = ObjectAccessor::GetCreature(*_player, guid); + if(!unit) + return; + + if(!unit->isBattleMaster()) // it's not battlemaster + return; + + // Stop the npc if moving + unit->StopMoving(); + + uint32 bgTypeId = objmgr.GetBattleMasterBG(unit->GetEntry()); + + if(!_player->GetBGAccessByLevel(bgTypeId)) + { + // temp, must be gossip message... + SendNotification("You don't meet Battleground level requirements"); + return; + } + + SendBattlegGroundList(guid, bgTypeId); +} + +void WorldSession::SendBattlegGroundList( uint64 guid, uint32 bgTypeId ) +{ + WorldPacket data; + sBattleGroundMgr.BuildBattleGroundListPacket(&data, guid, _player, bgTypeId); + SendPacket( &data ); +} + +void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data, 8+4+4+1); + + uint64 guid; + uint32 bgTypeId; + uint32 instanceId; + uint8 joinAsGroup; + + recv_data >> guid; // battlemaster guid + recv_data >> bgTypeId; // battleground type id (DBC id) + recv_data >> instanceId; // instance id, 0 if First Available selected + recv_data >> joinAsGroup; // join as group + + sLog.outDebug( "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from: " I64FMT " for BG (Type: %u)", guid, bgTypeId); + + if(bgTypeId >= MAX_BATTLEGROUND_TYPES) // cheating? + return; + + // ignore if we already in BG or BG queue + if(_player->InBattleGround()) + return; + + Creature *unit = ObjectAccessor::GetCreature(*_player, guid); + if(!unit) + return; + + if(!unit->isBattleMaster()) // it's not battlemaster + return; + + // check Deserter debuff + if( !_player->CanJoinToBattleground() ) + { + WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4); + data << (uint32) 0xFFFFFFFE; + _player->GetSession()->SendPacket(&data); + return; + } + + // check existence + BattleGround *bg = sBattleGroundMgr.GetBattleGround(bgTypeId); + if(!bg) + return; + + if(joinAsGroup && _player->GetGroup()) + { + Group *grp = _player->GetGroup(); + for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *member = itr->getSource(); + if(!member) continue; + + if( !member->CanJoinToBattleground() ) + { + WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4); + data << (uint32) 0xFFFFFFFE; + _player->GetSession()->SendPacket(&data); + continue; + } + if (member->InBattleGroundQueueForBattleGroundType(bgTypeId)) + //player is already in this queue + continue; + + WorldPacket data; + // add to queue + uint32 queueSlot = member->AddBattleGroundQueueId(bgTypeId); + if (queueSlot == PLAYER_MAX_BATTLEGROUND_QUEUES) + { + // fill data packet + //member->GetSession()->SendPacket(data); + continue; + } + + // store entry point coords (same as leader entry point) + member->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation()); + + // send status packet (in queue) + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0); + member->GetSession()->SendPacket(&data); + sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId); + member->GetSession()->SendPacket(&data); + sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].AddPlayer(member, bgTypeId); + } + } + else + { + if (_player->InBattleGroundQueueForBattleGroundType(bgTypeId)) + //player is already in this queue + return; + uint32 queueSlot = _player->AddBattleGroundQueueId(bgTypeId); + if (queueSlot == PLAYER_MAX_BATTLEGROUND_QUEUES) + { + WorldPacket data; + // fill data packet + //SendPacket(data); + return; + } + + // store entry point coords + _player->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation()); + + WorldPacket data; + // send status packet (in queue) + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0); + SendPacket(&data); + sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].AddPlayer(_player, bgTypeId); + } +} + +void WorldSession::HandleBattleGroundPlayerPositionsOpcode( WorldPacket & /*recv_data*/ ) +{ + // empty opcode + sLog.outDebug("WORLD: Recvd MSG_BATTLEGROUND_PLAYER_POSITIONS Message"); + + BattleGround *bg = _player->GetBattleGround(); + if(!bg) // can't be received if player not in battleground + return; + + if(bg->GetTypeID() == BATTLEGROUND_WS) + { + uint32 count1 = 0; + uint32 count2 = 0; + + Player *ap = objmgr.GetPlayer(((BattleGroundWS*)bg)->GetAllianceFlagPickerGUID()); + if(ap) ++count2; + + Player *hp = objmgr.GetPlayer(((BattleGroundWS*)bg)->GetHordeFlagPickerGUID()); + if(hp) ++count2; + + WorldPacket data(MSG_BATTLEGROUND_PLAYER_POSITIONS, (4+4+16*count1+16*count2)); + data << count1; // alliance flag holders count + /*for(uint8 i = 0; i < count1; i++) + { + data << uint64(0); // guid + data << (float)0; // x + data << (float)0; // y + }*/ + data << count2; // horde flag holders count + if(ap) + { + data << (uint64)ap->GetGUID(); + data << (float)ap->GetPositionX(); + data << (float)ap->GetPositionY(); + } + if(hp) + { + data << (uint64)hp->GetGUID(); + data << (float)hp->GetPositionX(); + data << (float)hp->GetPositionY(); + } + + SendPacket(&data); + } +} + +void WorldSession::HandleBattleGroundPVPlogdataOpcode( WorldPacket & /*recv_data*/ ) +{ + sLog.outDebug( "WORLD: Recvd MSG_PVP_LOG_DATA Message"); + + BattleGround *bg = _player->GetBattleGround(); + if(!bg) + return; + + WorldPacket data; + sBattleGroundMgr.BuildPvpLogDataPacket(&data, bg); + SendPacket(&data); + + sLog.outDebug( "WORLD: Sent MSG_PVP_LOG_DATA Message"); +} + +void WorldSession::HandleBattleGroundListOpcode( WorldPacket &recv_data ) +{ + CHECK_PACKET_SIZE(recv_data, 4); + + sLog.outDebug( "WORLD: Recvd CMSG_BATTLEFIELD_LIST Message"); + + uint32 bgTypeId; + recv_data >> bgTypeId; // id from DBC + + if(bgTypeId >= MAX_BATTLEGROUND_TYPES) // cheating? + return; + + // can't be received if player not in BG queue + if(!_player->InBattleGroundQueueForBattleGroundType(bgTypeId)) + return; + + BattlemasterListEntry const* bl = sBattlemasterListStore.LookupEntry(bgTypeId); + + if(!bl) + return; + + WorldPacket data; + sBattleGroundMgr.BuildBattleGroundListPacket(&data, _player->GetGUID(), _player, bgTypeId); + SendPacket( &data ); +} + +void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data ) +{ + CHECK_PACKET_SIZE(recv_data, 1+1+4+2+1); + + sLog.outDebug( "WORLD: Recvd CMSG_BATTLEFIELD_PORT Message"); + + uint8 unk1; + uint8 unk2; // unk, can be 0x0 (may be if was invited?) and 0x1 + uint32 bgTypeId; // type id from dbc + uint16 unk; // 0x1F90 constant? + uint8 action; // enter battle 0x1, leave queue 0x0 + + recv_data >> unk1 >> unk2 >> bgTypeId >> unk >> action; + + if(bgTypeId >= MAX_BATTLEGROUND_TYPES) // cheating? + return; + + if(!_player->InBattleGroundQueueForBattleGroundType(bgTypeId)) + return; + + BattleGround *bg = sBattleGroundMgr.GetBattleGround(bgTypeId); + if(!bg) + return; + + uint32 queueSlot = 0; + WorldPacket data; + switch(action) + { + case 1: // port to battleground + // cheating? + if(!_player->IsInvitedForBattleGroundType(bgTypeId)) + return; + + // check if player is not deserter + if( !_player->CanJoinToBattleground() ) + { + WorldPacket data2; + data2.Initialize(SMSG_GROUP_JOINED_BATTLEGROUND, 4); + data2 << (uint32) 0xFFFFFFFE; + SendPacket(&data2); + return; + } + + // if the player is dead, resurrect him before teleport + if(!_player->isAlive()) + { + _player->ResurrectPlayer(1.0f,false); + _player->SpawnCorpseBones(); + } + + // leave current group + _player->RemoveFromGroup(); + + // packet to player about BG status + queueSlot = _player->GetBattleGroundQueueIndex(bgTypeId); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime()); + _player->GetSession()->SendPacket(&data); + + // remove battleground queue status from BGmgr + sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].RemovePlayer(_player->GetGUID(), false); + + // this is still needed here if battleground "jumping" shouldn't add deserter debuff + // also this required to prevent stuck at old battleground after SetBattleGroundId set to new + if (BattleGround *currentBg = _player->GetBattleGround()) + currentBg->RemovePlayerAtLeave(_player->GetGUID(), false, true); + + _player->SetBattleGroundId(bg->GetTypeID()); + sBattleGroundMgr.SendToBattleGround(_player, bgTypeId); + bg->AddPlayer(_player); + break; + case 0: // leave queue + queueSlot = _player->GetBattleGroundQueueIndex(bgTypeId); + _player->RemoveBattleGroundQueueId(bgTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_NONE, 0, 0); + sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].RemovePlayer(_player->GetGUID(), true); + SendPacket(&data); + break; + default: + sLog.outError("Battleground port: unknown action %u", action); + break; + } +} + +void WorldSession::HandleBattleGroundLeaveOpcode( WorldPacket & /*recv_data*/ ) +{ + //CHECK_PACKET_SIZE(recv_data, 1+1+4+2); + + sLog.outDebug( "WORLD: Recvd CMSG_LEAVE_BATTLEFIELD Message"); + + //uint8 unk1, unk2; + //uint32 bgTypeId; // id from DBC + //uint16 unk3; + + //recv_data >> unk1 >> unk2 >> bgTypeId >> unk3; - no used currently + + //if(bgTypeId >= MAX_BATTLEGROUND_TYPES) // cheating? but not important in this case + // return; + + // not allow leave battleground in combat + if(_player->isInCombat()) + if(BattleGround* bg = _player->GetBattleGround()) + if(bg->GetStatus() != STATUS_WAIT_LEAVE) + return; + + _player->LeaveBattleground(); +} + +void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ ) +{ + // empty opcode + sLog.outDebug( "WORLD: Battleground status" ); + + WorldPacket data; + + // TODO: we must put player back to battleground in case disconnect (< 5 minutes offline time) or teleport player on login(!) from battleground map to entry point + if(_player->InBattleGround()) + { + BattleGround *bg = _player->GetBattleGround(); + if(bg) + { + uint32 queueSlot = _player->GetBattleGroundQueueIndex(bg->GetTypeID()); + if((bg->GetStatus() <= STATUS_IN_PROGRESS)) + { + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime()); + SendPacket(&data); + } + for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) + { + uint32 queue_id = _player->GetBattleGroundQueueId(i); + if (i == queueSlot || !queue_id) + continue; + BattleGround *bg2 = sBattleGroundMgr.GetBattleGround(queue_id); + if(bg2) + { + //in this call is small bug, this call should be filled by player's waiting time in queue + //this call nulls all timers for client : + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg2, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0); + SendPacket(&data); + } + } + } + } + else + { + // we should update all queues? .. i'm not sure if this code is correct + for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) + { + if(uint32 queue_id = _player->GetBattleGroundQueueId(i)) + { + if(BattleGround *bg = sBattleGroundMgr.GetBattleGround(queue_id)) + { + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0); + SendPacket(&data); + } + } + } + } +} + +void WorldSession::HandleAreaSpiritHealerQueryOpcode( WorldPacket & recv_data ) +{ + sLog.outDebug("WORLD: CMSG_AREA_SPIRIT_HEALER_QUERY"); + + CHECK_PACKET_SIZE(recv_data, 8); + + BattleGround *bg = _player->GetBattleGround(); + if(!bg) + return; + + uint64 guid; + recv_data >> guid; + + Creature *unit = ObjectAccessor::GetCreature(*_player, guid); + if(!unit) + return; + + if(!unit->isSpiritService()) // it's not spirit service + return; + + sBattleGroundMgr.SendAreaSpiritHealerQueryOpcode(_player, bg, guid); +} + +void WorldSession::HandleAreaSpiritHealerQueueOpcode( WorldPacket & recv_data ) +{ + sLog.outDebug("WORLD: CMSG_AREA_SPIRIT_HEALER_QUEUE"); + + CHECK_PACKET_SIZE(recv_data, 8); + + BattleGround *bg = _player->GetBattleGround(); + if(!bg) + return; + + uint64 guid; + recv_data >> guid; + + Creature *unit = ObjectAccessor::GetCreature(*_player, guid); + if(!unit) + return; + + if(!unit->isSpiritService()) // it's not spirit service + return; + + bg->AddPlayerToResurrectQueue(guid, _player->GetGUID()); +} + +void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data, 8+1+1+1); + + sLog.outDebug("WORLD: CMSG_BATTLEMASTER_JOIN_ARENA"); + recv_data.hexlike(); + + // ignore if we already in BG or BG queue + if(_player->InBattleGround()) + return; + + for(int qId = 0; qId < PLAYER_MAX_BATTLEGROUND_QUEUES; ++qId) + { + if(_player->GetBattleGroundQueueId(qId) != 0) + return; + } + + uint64 guid; // arena Battlemaster guid + uint8 type; // 2v2, 3v3 or 5v5 + uint8 asGroup; // asGroup + uint8 isRated; // isRated + recv_data >> guid >> type >> asGroup >> isRated; + + Creature *unit = ObjectAccessor::GetCreature(*_player, guid); + if(!unit) + return; + + if(!unit->isBattleMaster()) // it's not battle master + return; + + uint8 arenatype = 0; + + switch(type) + { + case 0: + arenatype = ARENA_TYPE_2v2; + break; + case 1: + arenatype = ARENA_TYPE_3v3; + break; + case 2: + arenatype = ARENA_TYPE_5v5; + break; + default: + sLog.outError("Unknown arena type %u at HandleBattleGroundArenaJoin()", type); + return; + } + + if(isRated && !_player->GetArenaTeamId(type)) // player not in arena team of that size + { + _player->GetSession()->SendNotInArenaTeamPacket(arenatype); + return; + } + + if(asGroup && !_player->GetGroup()) // player not in group + return; + + // check existence + BattleGround *bg = sBattleGroundMgr.GetBattleGround(BATTLEGROUND_AA); + if(!bg) + return; + + bg->SetArenaType(arenatype); + bg->SetRated(isRated); + + if(asGroup && _player->GetGroup()) + { + Group *grp = _player->GetGroup(); + for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *member = itr->getSource(); + if(!member) continue; + + /*if (!member->CanJoinToBattleground()) + //player has deserter aura .. do nothing + */ + + if (member->InBattleGroundQueueForBattleGroundType(BATTLEGROUND_AA)) + //player is already in this queue + continue; + + // add to queue + uint32 queueSlot = member->AddBattleGroundQueueId(BATTLEGROUND_AA); + if (queueSlot == PLAYER_MAX_BATTLEGROUND_QUEUES) + { + WorldPacket data; + //fill data + //member->GetSession()->SendPacket(data); + continue; + } + + // store entry point coords (same as leader entry point) + member->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation()); + + WorldPacket data; + // send status packet (in queue) + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0); + member->GetSession()->SendPacket(&data); + sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, BATTLEGROUND_AA); + member->GetSession()->SendPacket(&data); + sBattleGroundMgr.m_BattleGroundQueues[BATTLEGROUND_AA].AddPlayer(member, BATTLEGROUND_AA); + } + } + else + { + /*if (!member->CanJoinToBattleground()) + //player has deserter aura .. do nothing + */ + + if (_player->InBattleGroundQueueForBattleGroundType(BATTLEGROUND_AA)) + //player is already in this queue + return; + + uint32 queueSlot = _player->AddBattleGroundQueueId(BATTLEGROUND_AA); + if (queueSlot == PLAYER_MAX_BATTLEGROUND_QUEUES) + { + WorldPacket data; + //fill data (player is in 3 queues already) + //SendPacket(data); + return; + } + + // store entry point coords + _player->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation()); + + WorldPacket data; + // send status packet (in queue) + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0); + SendPacket(&data); + sBattleGroundMgr.m_BattleGroundQueues[BATTLEGROUND_AA].AddPlayer(_player, BATTLEGROUND_AA); + } +} + +void WorldSession::HandleBattleGroundReportAFK( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data, 8); + + uint64 playerGuid; + recv_data >> playerGuid; + Player *reportedPlayer = objmgr.GetPlayer(playerGuid); + + if(!reportedPlayer) + { + sLog.outDebug("WorldSession::HandleBattleGroundReportAFK: player not found"); + return; + } + + sLog.outDebug("WorldSession::HandleBattleGroundReportAFK: %s reported %s", _player->GetName(), reportedPlayer->GetName()); + + reportedPlayer->ReportedAfkBy(_player); +} diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp new file mode 100644 index 00000000000..52dad08345b --- /dev/null +++ b/src/game/BattleGroundMgr.cpp @@ -0,0 +1,867 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Player.h" +#include "BattleGroundMgr.h" +#include "BattleGroundAV.h" +#include "BattleGroundAB.h" +#include "BattleGroundEY.h" +#include "BattleGroundWS.h" +#include "BattleGroundNA.h" +#include "BattleGroundBE.h" +#include "BattleGroundAA.h" +#include "BattleGroundRL.h" +#include "SharedDefines.h" +#include "Policies/SingletonImp.h" +#include "MapManager.h" +#include "ObjectMgr.h" +#include "ProgressBar.h" +#include "World.h" +#include "Chat.h" + +INSTANTIATE_SINGLETON_1( BattleGroundMgr ); + +/*********************************************************/ +/*** BATTLEGROUND QUEUE SYSTEM ***/ +/*********************************************************/ + +BattleGroundQueue::BattleGroundQueue() +{ + //queues are empty, we don't have to call clear() + for (int i = 0; i < MAX_BATTLEGROUND_QUEUES; i++) + { + m_QueuedPlayers[i].Horde = 0; + m_QueuedPlayers[i].Alliance = 0; + //m_QueuedPlayers[i].AverageTime = 0; + } +} + +BattleGroundQueue::~BattleGroundQueue() +{ + for (int i = 0; i < MAX_BATTLEGROUND_QUEUES; i++) + { + m_QueuedPlayers[i].clear(); + } +} + +void BattleGroundQueue::AddPlayer(Player *plr, uint32 bgTypeId) +{ + uint32 queue_id = plr->GetBattleGroundQueueIdFromLevel(); + + //if player isn't in queue, he is added, if already is, then values are overwritten, no memory leak + PlayerQueueInfo& info = m_QueuedPlayers[queue_id][plr->GetGUID()]; + info.InviteTime = 0; + info.IsInvitedToBGInstanceGUID = 0; + info.LastInviteTime = 0; + info.LastOnlineTime = getMSTime(); + info.Team = plr->GetTeam(); + + //add player to waiting order queue + m_PlayersSortedByWaitTime[queue_id].push_back(plr->GetGUID()); + + if(plr->GetTeam() == ALLIANCE) + ++m_QueuedPlayers[queue_id].Alliance; + else + ++m_QueuedPlayers[queue_id].Horde; + + this->Update(bgTypeId, queue_id); + + if( sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE) ) + { + BattleGround* bg = sBattleGroundMgr.GetBattleGround(bgTypeId); + char const* bgName = bg->GetName(); + + uint32 q_min_level = Player::GetMinLevelForBattleGroundQueueId(queue_id); + uint32 q_max_level = Player::GetMaxLevelForBattleGroundQueueId(queue_id); + + // replace hardcoded max level by player max level for nice output + if(q_max_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + q_max_level = sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); + + int8 MinPlayers = bg->GetMinPlayersPerTeam(); + + uint8 qHorde = m_QueuedPlayers[queue_id].Horde; + uint8 qAlliance = m_QueuedPlayers[queue_id].Alliance; + + // Show queue status to player only (when joining queue) + if(sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY)) + { + ChatHandler(plr).PSendSysMessage(LANG_BG_QUEUE_ANNOUNCE_SELF, + bgName, q_min_level, q_max_level, qAlliance, MinPlayers - qAlliance, qHorde, MinPlayers - qHorde); + } + // System message + else + { + sWorld.SendWorldText(LANG_BG_QUEUE_ANNOUNCE_WORLD, + bgName, q_min_level, q_max_level, qAlliance, MinPlayers - qAlliance, qHorde, MinPlayers - qHorde); + } + } +} + +void BattleGroundQueue::RemovePlayer(uint64 guid, bool decreaseInvitedCount) +{ + Player *plr = objmgr.GetPlayer(guid); + + uint32 queue_id = 0; + QueuedPlayersMap::iterator itr; + bool IsSet = false; + if(!plr) + { //player is offline, we need to find him somewhere in queues + /// there is something wrong if this code is run, because we have in queue only online players! + sLog.outError("Battleground: removing offline player from BG queue - this might not happen, but it should not cause crash"); + for (uint32 i = 0; i < MAX_BATTLEGROUND_QUEUES; i++) + { + itr = m_QueuedPlayers[i].find(guid); + if(itr != m_QueuedPlayers[i].end()) + { + queue_id = i; + IsSet = true; + break; + } + } + } + else + { //player is online, we have his level, so we can find exact queue from his level + queue_id = plr->GetBattleGroundQueueIdFromLevel(); + itr = m_QueuedPlayers[queue_id].find(guid); + IsSet = true; + } + + //all variables are set, so remove player + //remove player from time queue + m_PlayersSortedByWaitTime[queue_id].remove(guid); + + if (IsSet && itr != m_QueuedPlayers[queue_id].end()) + { + if (!itr->second.IsInvitedToBGInstanceGUID) + { + if(itr->second.Team == ALLIANCE) + --m_QueuedPlayers[queue_id].Alliance; + else + --m_QueuedPlayers[queue_id].Horde; + } + else + { + if (decreaseInvitedCount) + { + BattleGround* bg = sBattleGroundMgr.GetBattleGround(itr->second.IsInvitedToBGInstanceGUID); + if (bg) + bg->DecreaseInvitedCount(itr->second.Team); + } + } + m_QueuedPlayers[queue_id].erase(itr); + } +} + +/* +this method is called when player is inserted, or removed from BG Queue - there is only one player's status changed, so we don't use while(true) cycles to invite whole queue +add method calls this by itself, the remove method could works in other way, so you have to call this method from other code after calling remove method +*/ +void BattleGroundQueue::Update(uint32 bgTypeId, uint32 queue_id) +{ + if (queue_id >= MAX_BATTLEGROUND_QUEUES) + { + //this is error, that caused crashes (not in , but now it shouldn't) + sLog.outError("BattleGroundQueue::Update() called for non existing queue type - this can cause crash, pls report problem, if this is the last line of error log before crash"); + return; + } + + //if no players in queue ... do nothing + if (this->m_QueuedPlayers[queue_id].Alliance == 0 && this->m_QueuedPlayers[queue_id].Horde == 0) + return; + + //battleground with free slot for player should be always the last in this queue + for (BGFreeSlotQueueType::iterator itr = sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].begin(); itr != sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].end(); ++itr) + { + // battleground is running, so if: + // DO NOT allow queue manager to invite new player to running arena + if ((*itr)->isBattleGround() && (*itr)->GetQueueType() == queue_id && (*itr)->GetStatus() > STATUS_WAIT_QUEUE && (*itr)->GetStatus() < STATUS_WAIT_LEAVE) + { + //we must check both teams + BattleGround* bg = *itr; //we have to store battleground pointer here, because when battleground is full, it is removed from free queue (not yet implemented!!) + // and iterator is invalid + + //check if there are some players in queue + if (m_QueuedPlayers[queue_id].Alliance > 0 || m_QueuedPlayers[queue_id].Horde > 0) + { + for (PlayerGuidsSortedByTimeQueue::iterator itr2 = m_PlayersSortedByWaitTime[queue_id].begin(); itr2 != m_PlayersSortedByWaitTime[queue_id].end();) + { + Player* plr = objmgr.GetPlayer(*itr2); + if (!plr) + { + //something is wrong!, kick player from queue + sLog.outError("BATTLEGROUND: problem with inviting offline player to Battleground queue .... pls report bug"); + uint64 oldval = *itr2; + itr2 = m_PlayersSortedByWaitTime[queue_id].erase(itr2); + RemovePlayer(oldval, true); + continue; + } + + // player will be invited, if in bg there is a free slot for him + if (bg->HasFreeSlotsForTeam(plr->GetTeam())) + { + // iterator to player's queue status + QueuedPlayersMap::iterator itrPlayerStatus = m_QueuedPlayers[queue_id].find(*itr2); + + // remove him from time queue + itr2 = m_PlayersSortedByWaitTime[queue_id].erase(itr2); + + // only check to be sure ... but this condition shouldn't be true (if it is true, then there is a bug somewhere and pls report it) + if (itrPlayerStatus == m_QueuedPlayers[queue_id].end()) + continue; + + // check if player is not already invited + if (!itrPlayerStatus->second.IsInvitedToBGInstanceGUID) + { + itrPlayerStatus->second.IsInvitedToBGInstanceGUID = bg->GetInstanceID(); + itrPlayerStatus->second.InviteTime = getMSTime(); + itrPlayerStatus->second.LastInviteTime = getMSTime(); + if(itrPlayerStatus->second.Team == ALLIANCE) + --m_QueuedPlayers[queue_id].Alliance; + else + --m_QueuedPlayers[queue_id].Horde; + sBattleGroundMgr.InvitePlayer(plr, bg->GetInstanceID()); + + WorldPacket data; + uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgTypeId); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr->GetTeam(), queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0); + plr->GetSession()->SendPacket(&data); + } + } + else + ++itr2; + + //if battleground is FULL, then it is removed from free slot queue - not yet implemented! + if (!bg->HasFreeSlots()) + { + //if bg is full, there is no need to invite other players, so break + break; + //remove BG from BGFreeSlotQueue - not used now, in this system we don't remove BGs from free queue + //bg->RemoveFromBGFreeSlotQueue() --- do not uncomment this - not yet implemented + } + } + } + } + } + + /* THIS IS A CASE THAT IN QUEUE THERE IS ENOUGHT PLAYERS TO START NEW BG */ + //itr->end is the last BG - template, which is not already started! + + /* here will be a most of change, when we create battlegrounds instantiated */ + /* if (there is enough players to start new BG) + Battleground* newbg = sBattleGroundMgr.CreateNewBattleGround(bgTypeId) + - that function will use the COPY constructor on BattleGround class ( in bg manager we should have one battleground as a template + (battleground template will be used only to create new BGs, it will be an instance of BG class, but it won't ever start) */ + + /* following code is working with current Battleground system and it should be removed, when BGs will work like instances */ + BattleGround* bg2 = sBattleGroundMgr.GetBattleGround(bgTypeId); + if (bg2->GetQueueType() != MAX_BATTLEGROUND_QUEUES || bg2->GetStatus() != STATUS_WAIT_QUEUE) + return; + if (m_QueuedPlayers[queue_id].Alliance >= bg2->GetMinPlayersPerTeam() && m_QueuedPlayers[queue_id].Horde >= bg2->GetMinPlayersPerTeam()) + { + bg2->SetStatus(STATUS_WAIT_JOIN); + bg2->SetQueueType(queue_id); + + for (PlayerGuidsSortedByTimeQueue::iterator itr2 = m_PlayersSortedByWaitTime[queue_id].begin(); itr2 != m_PlayersSortedByWaitTime[queue_id].end();) + { + Player* plr = objmgr.GetPlayer(*itr2); + if (!plr) + { + //something is wrong!, kick player from queue + sLog.outError("BATTLEGROUND: problem with inviting offline player to Battleground queue .... pls report bug"); + uint64 oldval = *itr2; + itr2 = m_PlayersSortedByWaitTime[queue_id].erase(itr2); + RemovePlayer(oldval, true); + continue; + } + + /* TODO: (i'm not sure this code will be useful: + here should be some condition like if (bg2->isArena() && bg2->isRated()) + { + invite players from 1 certain group on each faction to play arena match + } else if ....and existing code + */ + // player will be invited, if in bg there is a free slot for him + if (bg2->HasFreeSlotsForTeam(plr->GetTeam())) + { + // iterator to player's queue status + QueuedPlayersMap::iterator itrPlayerStatus = m_QueuedPlayers[queue_id].find(*itr2); + + // remove him from time queue + itr2 = m_PlayersSortedByWaitTime[queue_id].erase(itr2); + + // only check to be sure ... but this condition shouldn't be true (if it is true, then there is a bug somewhere and report it) + if (itrPlayerStatus == m_QueuedPlayers[queue_id].end()) + continue; + + //check if player is not already invited + if (!itrPlayerStatus->second.IsInvitedToBGInstanceGUID) + { + itrPlayerStatus->second.IsInvitedToBGInstanceGUID = bg2->GetInstanceID(); + itrPlayerStatus->second.InviteTime = getMSTime(); + itrPlayerStatus->second.LastInviteTime = getMSTime(); + + if(itrPlayerStatus->second.Team == ALLIANCE) + --m_QueuedPlayers[queue_id].Alliance; + else + --m_QueuedPlayers[queue_id].Horde; + + sBattleGroundMgr.InvitePlayer(plr, bg2->GetInstanceID()); + + WorldPacket data; + uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgTypeId); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg2, plr->GetTeam(), queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0); + plr->GetSession()->SendPacket(&data); + } + } + else + ++itr2; + } + bg2->StartBattleGround(); + } +} + +/*********************************************************/ +/*** BATTLEGROUND QUEUE EVENTS ***/ +/*********************************************************/ + +bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 p_time) +{ + Player* plr = objmgr.GetPlayer( m_PlayerGuid ); + + // player logged off (we should do nothing, he is correctly removed from queue in another procedure) + if (!plr) + return true; + + // Player can be in another BG queue and must be removed in normal way in any case + // // player is already in battleground ... do nothing (battleground queue status is deleted when player is teleported to BG) + // if (plr->GetBattleGroundId() > 0) + // return true; + + BattleGround* bg = sBattleGroundMgr.GetBattleGround(m_BgInstanceGUID); + if (!bg) + return true; + + uint32 queueSlot = plr->GetBattleGroundQueueIndex(bg->GetTypeID()); + if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue + { + // check if player is invited to this bg ... this check must be here, because when player leaves queue and joins another, it would cause a problems + BattleGroundQueue::QueuedPlayersMap const& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bg->GetTypeID()].m_QueuedPlayers[plr->GetBattleGroundQueueIdFromLevel()]; + BattleGroundQueue::QueuedPlayersMap::const_iterator qItr = qpMap.find(m_PlayerGuid); + if (qItr != qpMap.end() && qItr->second.IsInvitedToBGInstanceGUID == m_BgInstanceGUID) + { + WorldPacket data; + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr->GetTeam(), queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME/2, 0); + plr->GetSession()->SendPacket(&data); + } + } + return true; //event will be deleted +} + +void BGQueueInviteEvent::Abort(uint64 /*e_time*/) +{ + //this should not be called + sLog.outError("Battleground invite event ABORTED!"); +} + +bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) +{ + Player* plr = objmgr.GetPlayer( m_PlayerGuid ); + if (!plr) + // player logged off (we should do nothing, he is correctly removed from queue in another procedure) + return true; + + // Player can be in another BG queue and must be removed in normal way in any case + //if (plr->InBattleGround()) + // // player is already in battleground ... do nothing (battleground queue status is deleted when player is teleported to BG) + // return true; + + BattleGround* bg = sBattleGroundMgr.GetBattleGround(m_BgInstanceGUID); + if (!bg) + return true; + + uint32 queueSlot = plr->GetBattleGroundQueueIndex(bg->GetTypeID()); + if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue (base at player data + { + // check if player is invited to this bg ... this check must be here, because when player leaves queue and joins another, it would cause a problems + BattleGroundQueue::QueuedPlayersMap const& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bg->GetTypeID()].m_QueuedPlayers[plr->GetBattleGroundQueueIdFromLevel()]; + BattleGroundQueue::QueuedPlayersMap::const_iterator qItr = qpMap.find(m_PlayerGuid); + if (qItr!=qpMap.end() && qItr->second.IsInvitedToBGInstanceGUID == m_BgInstanceGUID) + { + plr->RemoveBattleGroundQueueId(bg->GetTypeID()); + sBattleGroundMgr.m_BattleGroundQueues[bg->GetTypeID()].RemovePlayer(m_PlayerGuid, true); + sBattleGroundMgr.m_BattleGroundQueues[bg->GetTypeID()].Update(bg->GetTypeID(), bg->GetQueueType()); + + WorldPacket data; + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr->GetTeam(), queueSlot, STATUS_NONE, 0, 0); + plr->GetSession()->SendPacket(&data); + } + } + + //event will be deleted + return true; +} + +void BGQueueRemoveEvent::Abort(uint64 /*e_time*/) +{ + //this should not be called + sLog.outError("Battleground remove event ABORTED!"); +} + +/*********************************************************/ +/*** BATTLEGROUND MANAGER ***/ +/*********************************************************/ + +BattleGroundMgr::BattleGroundMgr() +{ + m_BattleGrounds.clear(); +} + +BattleGroundMgr::~BattleGroundMgr() +{ + for(std::map::iterator itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); ++itr) + delete itr->second; + m_BattleGrounds.clear(); +} + +void BattleGroundMgr::Update(time_t diff) +{ + for(BattleGroundSet::iterator itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); ++itr) + itr->second->Update(diff); +} + +void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2) +{ + // we can be in 3 queues in same time... + if(StatusID == 0) + { + data->Initialize(SMSG_BATTLEFIELD_STATUS, 4*3); + *data << uint32(QueueSlot); // queue id (0...2) + *data << uint64(0); + return; + } + + data->Initialize(SMSG_BATTLEFIELD_STATUS, (4+1+1+4+2+4+1+4+4+4)); + *data << uint32(QueueSlot); // queue id (0...2) - player can be in 3 queues in time + // uint64 in client + *data << uint64( uint64(bg->GetArenaType()) | (uint64(0x0D) << 8) | (uint64(bg->GetTypeID()) << 16) | (uint64(0x1F90) << 48) ); + *data << uint32(0); // unknown + // alliance/horde for BG and skirmish/rated for Arenas + *data << uint8(bg->isArena() ? (bg->isRated() ? 1 : 0) : bg->GetTeamIndexByTeamId(team)); + *data << uint32(StatusID); // status + switch(StatusID) + { + case STATUS_WAIT_QUEUE: // status_in_queue + *data << uint32(Time1); // average wait time, milliseconds + *data << uint32(Time2); // time in queue, updated every minute? + break; + case STATUS_WAIT_JOIN: // status_invite + *data << uint32(bg->GetMapId()); // map id + *data << uint32(Time1); // time to remove from queue, milliseconds + break; + case STATUS_IN_PROGRESS: // status_in_progress + *data << uint32(bg->GetMapId()); // map id + *data << uint32(Time1); // 0 at bg start, 120000 after bg end, time to bg auto leave, milliseconds + *data << uint32(Time2); // time from bg start, milliseconds + *data << uint8(0x1); // unk sometimes 0x0! + break; + default: + sLog.outError("Unknown BG status!"); + break; + } +} + +void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg) +{ + uint8 type = (bg->isArena() ? 1 : 0); + // last check on 2.4.1 + data->Initialize(MSG_PVP_LOG_DATA, (1+1+4+40*bg->GetPlayerScoresSize())); + *data << uint8(type); // seems to be type (battleground=0/arena=1) + if(type) // arena + { + for(uint8 i = 0; i < 2; i++) + { + *data << uint32(3000+1+i); // rating change: showed value - 3000 + *data << uint32(0); // 2.4.0, has some to do with rating change... + *data << uint8(0); // some unknown string + } + } + + if(bg->GetWinner() == 2) + { + *data << uint8(0); // bg in progress + } + else + { + *data << uint8(1); // bg ended + *data << uint8(bg->GetWinner()); // who win + } + + *data << (int32)(bg->GetPlayerScoresSize()); + + for(std::map::const_iterator itr = bg->GetPlayerScoresBegin(); itr != bg->GetPlayerScoresEnd(); ++itr) + { + *data << (uint64)itr->first; + *data << (int32)itr->second->KillingBlows; + if(type) + { + // this value is team (green/gold)? + // that part probably wrong + Player *plr = objmgr.GetPlayer(itr->first); + if(plr) + { + if(plr->GetTeam() == HORDE) + *data << uint8(0); + else if(plr->GetTeam() == ALLIANCE) + *data << uint8(1); + else + *data << uint8(0); + } + else + *data << uint8(0); + } + else + { + *data << (int32)itr->second->HonorableKills; + *data << (int32)itr->second->Deaths; + *data << (int32)itr->second->BonusHonor; // bonus honor + } + *data << (int32)itr->second->DamageDone; // damage done + *data << (int32)itr->second->HealingDone; // healing done + switch(bg->GetTypeID()) // battleground specific things + { + case BATTLEGROUND_AV: + *data << (uint32)0x00000005; // count of next fields + *data << (uint32)((BattleGroundAVScore*)itr->second)->GraveyardsAssaulted; // GraveyardsAssaulted + *data << (uint32)((BattleGroundAVScore*)itr->second)->GraveyardsDefended; // GraveyardsDefended + *data << (uint32)((BattleGroundAVScore*)itr->second)->TowersAssaulted; // TowersAssaulted + *data << (uint32)((BattleGroundAVScore*)itr->second)->TowersDefended; // TowersDefended + *data << (uint32)((BattleGroundAVScore*)itr->second)->MinesCaptured; // MinesCaptured + break; + case BATTLEGROUND_WS: + *data << (uint32)0x00000002; // count of next fields + *data << (uint32)((BattleGroundWGScore*)itr->second)->FlagCaptures; // flag captures + *data << (uint32)((BattleGroundWGScore*)itr->second)->FlagReturns; // flag returns + break; + case BATTLEGROUND_AB: + *data << (uint32)0x00000002; // count of next fields + *data << (uint32)((BattleGroundABScore*)itr->second)->BasesAssaulted; // bases asssulted + *data << (uint32)((BattleGroundABScore*)itr->second)->BasesDefended; // bases defended + break; + case BATTLEGROUND_EY: + *data << (uint32)0x00000001; // count of next fields + *data << (uint32)((BattleGroundEYScore*)itr->second)->FlagCaptures; // flag captures + break; + case BATTLEGROUND_NA: + case BATTLEGROUND_BE: + case BATTLEGROUND_AA: + case BATTLEGROUND_RL: + *data << (int32)0; // 0 + break; + default: + sLog.outDebug("Unhandled MSG_PVP_LOG_DATA for BG id %u", bg->GetTypeID()); + *data << (int32)0; + break; + } + } +} + +void BattleGroundMgr::BuildGroupJoinedBattlegroundPacket(WorldPacket *data, uint32 bgTypeId) +{ + /*bgTypeId is: + 0 - Your group has joined a battleground queue, but you are not eligible + 1 - Your group has joined the queue for AV + 2 - Your group has joined the queue for WS + 3 - Your group has joined the queue for AB + 4 - Your group has joined the queue for NA + 5 - Your group has joined the queue for BE Arena + 6 - Your group has joined the queue for All Arenas + 7 - Your group has joined the queue for EotS*/ + data->Initialize(SMSG_GROUP_JOINED_BATTLEGROUND, 4); + *data << uint32(bgTypeId); +} + +void BattleGroundMgr::BuildUpdateWorldStatePacket(WorldPacket *data, uint32 field, uint32 value) +{ + data->Initialize(SMSG_UPDATE_WORLD_STATE, 4+4); + *data << uint32(field); + *data << uint32(value); +} + +void BattleGroundMgr::BuildPlaySoundPacket(WorldPacket *data, uint32 soundid) +{ + data->Initialize(SMSG_PLAY_SOUND, 4); + *data << uint32(soundid); +} + +void BattleGroundMgr::BuildPlayerLeftBattleGroundPacket(WorldPacket *data, Player *plr) +{ + data->Initialize(SMSG_BATTLEGROUND_PLAYER_LEFT, 8); + *data << uint64(plr->GetGUID()); +} + +void BattleGroundMgr::BuildPlayerJoinedBattleGroundPacket(WorldPacket *data, Player *plr) +{ + data->Initialize(SMSG_BATTLEGROUND_PLAYER_JOINED, 8); + *data << uint64(plr->GetGUID()); +} + +void BattleGroundMgr::InvitePlayer(Player* plr, uint32 bgInstanceGUID) +{ + // set invited player counters: + BattleGround* bg = this->GetBattleGround(bgInstanceGUID); + if(!bg) + return; + + bg->IncreaseInvitedCount(plr->GetTeam()); + plr->SetInviteForBattleGroundType(bg->GetTypeID()); + // create invite events: + //add events to player's counters ---- this is not good way - there should be something like global event processor, where we should add those events + BGQueueInviteEvent* inviteEvent = new BGQueueInviteEvent(plr->GetGUID(), bgInstanceGUID); + plr->m_Events.AddEvent(inviteEvent, plr->m_Events.CalculateTime(INVITE_ACCEPT_WAIT_TIME/2)); + BGQueueRemoveEvent* removeEvent = new BGQueueRemoveEvent(plr->GetGUID(), bgInstanceGUID, plr->GetTeam()); + plr->m_Events.AddEvent(removeEvent, plr->m_Events.CalculateTime(INVITE_ACCEPT_WAIT_TIME)); +} + +uint32 BattleGroundMgr::CreateBattleGround(uint32 bgTypeId, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam, uint32 LevelMin, uint32 LevelMax, char* BattleGroundName, uint32 MapID, float Team1StartLocX, float Team1StartLocY, float Team1StartLocZ, float Team1StartLocO, float Team2StartLocX, float Team2StartLocY, float Team2StartLocZ, float Team2StartLocO) +{ + // Create the BG + BattleGround *bg = NULL; + + switch(bgTypeId) + { + case BATTLEGROUND_AV: bg = new BattleGroundAV; break; + case BATTLEGROUND_WS: bg = new BattleGroundWS; break; + case BATTLEGROUND_AB: bg = new BattleGroundAB; break; + case BATTLEGROUND_NA: bg = new BattleGroundNA; break; + case BATTLEGROUND_BE: bg = new BattleGroundBE; break; + case BATTLEGROUND_AA: bg = new BattleGroundAA; break; + case BATTLEGROUND_EY: bg = new BattleGroundEY; break; + case BATTLEGROUND_RL: bg = new BattleGroundRL; break; + default:bg = new BattleGround; break; // placeholder for non implemented BG + } + + bg->SetMapId(MapID); + bg->Reset(); + if(!bg->SetupBattleGround()) + { + delete bg; + return 0; + } + + BattlemasterListEntry const *bl = sBattlemasterListStore.LookupEntry(bgTypeId); + //in previous method is checked if exists entry in sBattlemasterListStore, so no check needed + if (bl) + { + bg->SetArenaorBGType(bl->type == TYPE_ARENA); + } + + bg->SetTypeID(bgTypeId); + bg->SetInstanceID(bgTypeId); // temporary + bg->SetMinPlayersPerTeam(MinPlayersPerTeam); + bg->SetMaxPlayersPerTeam(MaxPlayersPerTeam); + bg->SetMinPlayers(MinPlayersPerTeam*2); + bg->SetMaxPlayers(MaxPlayersPerTeam*2); + bg->SetName(BattleGroundName); + bg->SetTeamStartLoc(ALLIANCE, Team1StartLocX, Team1StartLocY, Team1StartLocZ, Team1StartLocO); + bg->SetTeamStartLoc(HORDE, Team2StartLocX, Team2StartLocY, Team2StartLocZ, Team2StartLocO); + bg->SetLevelRange(LevelMin, LevelMax); + //add BaggleGround instance to FreeSlotQueue + bg->AddToBGFreeSlotQueue(); + + AddBattleGround(bg->GetInstanceID(), bg); + //sLog.outDetail("BattleGroundMgr: Created new battleground: %u %s (Map %u, %u players per team, Levels %u-%u)", bg_TypeID, bg->m_Name, bg->m_MapId, bg->m_MaxPlayersPerTeam, bg->m_LevelMin, bg->m_LevelMax); + return bg->GetInstanceID(); +} + +void BattleGroundMgr::CreateInitialBattleGrounds() +{ + float AStartLoc[4]; + float HStartLoc[4]; + uint32 MaxPlayersPerTeam, MinPlayersPerTeam, MinLvl, MaxLvl, start1, start2; + BattlemasterListEntry const *bl; + WorldSafeLocsEntry const *start; + + uint32 count = 0; + + // 0 1 2 3 4 5 6 7 8 + QueryResult *result = WorldDatabase.Query("SELECT id, MinPlayersPerTeam,MaxPlayersPerTeam,MinLvl,MaxLvl,AllianceStartLoc,AllianceStartO,HordeStartLoc,HordeStartO FROM battleground_template"); + + if(!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outErrorDb(">> Loaded 0 battlegrounds. DB table `battleground_template` is empty."); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 bgTypeID = fields[0].GetUInt32(); + + // can be overwrited by values from DB + bl = sBattlemasterListStore.LookupEntry(bgTypeID); + if(!bl) + { + sLog.outError("Battleground ID %u not found in BattlemasterList.dbc. Battleground not created.",bgTypeID); + continue; + } + + MaxPlayersPerTeam = bl->maxplayersperteam; + MinPlayersPerTeam = bl->maxplayersperteam/2; + MinLvl = bl->minlvl; + MaxLvl = bl->maxlvl; + + if(fields[1].GetUInt32()) + MinPlayersPerTeam = fields[1].GetUInt32(); + + if(fields[2].GetUInt32()) + MaxPlayersPerTeam = fields[2].GetUInt32(); + + if(fields[3].GetUInt32()) + MinLvl = fields[3].GetUInt32(); + + if(fields[4].GetUInt32()) + MaxLvl = fields[4].GetUInt32(); + + start1 = fields[5].GetUInt32(); + + start = sWorldSafeLocsStore.LookupEntry(start1); + if(start) + { + AStartLoc[0] = start->x; + AStartLoc[1] = start->y; + AStartLoc[2] = start->z; + AStartLoc[3] = fields[6].GetFloat(); + } + else if(bgTypeID == BATTLEGROUND_AA) + { + AStartLoc[0] = 0; + AStartLoc[1] = 0; + AStartLoc[2] = 0; + AStartLoc[3] = fields[6].GetFloat(); + } + else + { + sLog.outErrorDb("Table `battleground_template` for id %u have non-existed WorldSafeLocs.dbc id %u in field `AllianceStartLoc`. BG not created.",bgTypeID,start1); + continue; + } + + start2 = fields[7].GetUInt32(); + + start = sWorldSafeLocsStore.LookupEntry(start2); + if(start) + { + HStartLoc[0] = start->x; + HStartLoc[1] = start->y; + HStartLoc[2] = start->z; + HStartLoc[3] = fields[8].GetFloat(); + } + else if(bgTypeID == BATTLEGROUND_AA) + { + HStartLoc[0] = 0; + HStartLoc[1] = 0; + HStartLoc[2] = 0; + HStartLoc[3] = fields[8].GetFloat(); + } + else + { + sLog.outErrorDb("Table `battleground_template` for id %u have non-existed WorldSafeLocs.dbc id %u in field `HordeStartLoc`. BG not created.",bgTypeID,start2); + continue; + } + + //sLog.outDetail("Creating battleground %s, %u-%u", bl->name[sWorld.GetDBClang()], MinLvl, MaxLvl); + if(!CreateBattleGround(bgTypeID, MinPlayersPerTeam, MaxPlayersPerTeam, MinLvl, MaxLvl, bl->name[sWorld.GetDefaultDbcLocale()], bl->mapid[0], AStartLoc[0], AStartLoc[1], AStartLoc[2], AStartLoc[3], HStartLoc[0], HStartLoc[1], HStartLoc[2], HStartLoc[3])) + continue; + + ++count; + } while (result->NextRow()); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u battlegrounds", count ); +} + +void BattleGroundMgr::BuildBattleGroundListPacket(WorldPacket *data, uint64 guid, Player* plr, uint32 bgTypeId) +{ + uint32 PlayerLevel = 10; + + if(plr) + PlayerLevel = plr->getLevel(); + + data->Initialize(SMSG_BATTLEFIELD_LIST); + *data << uint64(guid); // battlemaster guid + *data << uint32(bgTypeId); // battleground id + if(bgTypeId == BATTLEGROUND_AA) // arena + { + *data << uint8(5); // unk + *data << uint32(0); // unk + } + else // battleground + { + *data << uint8(0x00); // unk + + size_t count_pos = data->wpos(); + uint32 count = 0; + *data << uint32(0x00); // number of bg instances + + for(std::map::iterator itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); ++itr) + { + if(itr->second->GetTypeID() == bgTypeId && (PlayerLevel >= itr->second->GetMinLevel()) && (PlayerLevel <= itr->second->GetMaxLevel())) + { + *data << uint32(itr->second->GetInstanceID()); + ++count; + } + } + data->put( count_pos , count); + } +} + +void BattleGroundMgr::SendToBattleGround(Player *pl, uint32 bgTypeId) +{ + BattleGround *bg = GetBattleGround(bgTypeId); + if(bg) + { + uint32 mapid = bg->GetMapId(); + float x, y, z, O; + bg->GetTeamStartLoc(pl->GetTeam(), x, y, z, O); + + sLog.outDetail("BATTLEGROUND: Sending %s to map %u, X %f, Y %f, Z %f, O %f", pl->GetName(), mapid, x, y, z, O); + pl->TeleportTo(mapid, x, y, z, O); + } +} + +void BattleGroundMgr::SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, uint64 guid) +{ + WorldPacket data(SMSG_AREA_SPIRIT_HEALER_TIME, 12); + uint32 time_ = 30000 - bg->GetLastResurrectTime(); // resurrect every 30 seconds + if(time_ == uint32(-1)) + time_ = 0; + data << guid << time_; + pl->GetSession()->SendPacket(&data); +} diff --git a/src/game/BattleGroundMgr.h b/src/game/BattleGroundMgr.h new file mode 100644 index 00000000000..90eb4d2f775 --- /dev/null +++ b/src/game/BattleGroundMgr.h @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __BATTLEGROUNDMGR_H +#define __BATTLEGROUNDMGR_H + +#include "BattleGround.h" +#include "Policies/Singleton.h" + +class BattleGround; + +//TODO it is not possible to have this structure, because we should have BattlegroundSet for each queue +//so i propose to change this type to array 1..MAX_BATTLEGROUND_TYPES of sets or maps.. +typedef std::map BattleGroundSet; +//typedef std::map BattleGroundQueueSet; +typedef std::deque BGFreeSlotQueueType; + +#define MAX_BATTLEGROUND_QUEUES 7 // for level ranges 10-19, 20-29, 30-39, 40-49, 50-59, 60-69, 70+ + +#define MAX_BATTLEGROUND_TYPES 9 // each BG type will be in array + +struct PlayerQueueInfo +{ + uint32 InviteTime; // first invite time + uint32 LastInviteTime; // last invite time + uint32 IsInvitedToBGInstanceGUID; // was invited to certain BG + uint32 LastOnlineTime; // for tracking and removing offline players from queue after 5 minutes + uint32 Team; // Player team (ALLIANCE/HORDE) + bool IsRated; + bool AsGroup; // uint32 GroupId; + uint8 ArenaType; +}; + +struct PlayersCount +{ + uint32 Alliance; + uint32 Horde; +}; + +template class bgqueue: public std::map<_Kty, _Ty> +{ + public: + uint32 Alliance; + uint32 Horde; + //bool Ready; // not used now + //uint32 AverageTime; //not already implemented (it should be average time in queue for last 10 players) +}; + +class BattleGroundQueue +{ + public: + BattleGroundQueue(); + ~BattleGroundQueue(); +/* + uint32 GetType(); + void SetType(uint32 type);*/ + + void Update(uint32 bgTypeId, uint32 queue_id); + + void AddPlayer(Player *plr, uint32 bgTypeId); + void RemovePlayer(uint64 guid, bool decreaseInvitedCount); + + typedef bgqueue QueuedPlayersMap; + QueuedPlayersMap m_QueuedPlayers[MAX_BATTLEGROUND_QUEUES]; + typedef std::list PlayerGuidsSortedByTimeQueue; + PlayerGuidsSortedByTimeQueue m_PlayersSortedByWaitTime[MAX_BATTLEGROUND_QUEUES]; +}; + +/* + This class is used to invite player to BG again, when minute lasts from his first invitation + it is capable to solve all possibilities +*/ +class BGQueueInviteEvent : public BasicEvent +{ + public: + BGQueueInviteEvent(uint64 pl_guid, uint32 BgInstanceGUID) : m_PlayerGuid(pl_guid), m_BgInstanceGUID(BgInstanceGUID) {}; + virtual ~BGQueueInviteEvent() {}; + + virtual bool Execute(uint64 e_time, uint32 p_time); + virtual void Abort(uint64 e_time); + private: + uint64 m_PlayerGuid; + uint32 m_BgInstanceGUID; + +}; + +/* + This class is used to remove player from BG queue after 2 minutes from first invitation +*/ +class BGQueueRemoveEvent : public BasicEvent +{ + public: + BGQueueRemoveEvent(uint64 pl_guid, uint32 bgInstanceGUID, uint32 playersTeam) : m_PlayerGuid(pl_guid), m_BgInstanceGUID(bgInstanceGUID), m_PlayersTeam(playersTeam) {}; + virtual ~BGQueueRemoveEvent() {}; + + virtual bool Execute(uint64 e_time, uint32 p_time); + virtual void Abort(uint64 e_time); + private: + uint64 m_PlayerGuid; + uint32 m_BgInstanceGUID; + uint32 m_PlayersTeam; +}; + + +class BattleGroundMgr +{ + public: + /* Construction */ + BattleGroundMgr(); + ~BattleGroundMgr(); + void Update(time_t diff); + + /* Packet Building */ + void BuildPlayerJoinedBattleGroundPacket(WorldPacket *data, Player *plr); + void BuildPlayerLeftBattleGroundPacket(WorldPacket *data, Player *plr); + void BuildBattleGroundListPacket(WorldPacket *data, uint64 guid, Player *plr, uint32 bgTypeId); + void BuildGroupJoinedBattlegroundPacket(WorldPacket *data, uint32 bgTypeId); + void BuildUpdateWorldStatePacket(WorldPacket *data, uint32 field, uint32 value); + void BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg); + void BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2); + void BuildPlaySoundPacket(WorldPacket *data, uint32 soundid); + + /* Player invitation */ + // called from Queue update, or from Addplayer to queue + void InvitePlayer(Player* plr, uint32 bgInstanceGUID); + + /* Battlegrounds */ + BattleGroundSet::iterator GetBattleGroundsBegin() { return m_BattleGrounds.begin(); }; + BattleGroundSet::iterator GetBattleGroundsEnd() { return m_BattleGrounds.end(); }; + + BattleGround* GetBattleGround(uint8 ID) + { + BattleGroundSet::iterator i = m_BattleGrounds.find(ID); + if(i != m_BattleGrounds.end()) + return i->second; + else + return NULL; + }; + + uint32 CreateBattleGround(uint32 bgTypeId, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam, uint32 LevelMin, uint32 LevelMax, char* BattleGroundName, uint32 MapID, float Team1StartLocX, float Team1StartLocY, float Team1StartLocZ, float Team1StartLocO, float Team2StartLocX, float Team2StartLocY, float Team2StartLocZ, float Team2StartLocO); + + inline void AddBattleGround(uint32 ID, BattleGround* BG) { m_BattleGrounds[ID] = BG; }; + + void CreateInitialBattleGrounds(); + + void SendToBattleGround(Player *pl, uint32 bgTypeId); + + /* Battleground queues */ + //these queues are instantiated when creating BattlegroundMrg + BattleGroundQueue m_BattleGroundQueues[MAX_BATTLEGROUND_TYPES]; // public, because we need to access them in BG handler code + + BGFreeSlotQueueType BGFreeSlotQueue[MAX_BATTLEGROUND_TYPES]; + + void SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, uint64 guid); + + private: + + /* Battlegrounds */ + BattleGroundSet m_BattleGrounds; +}; + +#define sBattleGroundMgr MaNGOS::Singleton::Instance() +#endif diff --git a/src/game/BattleGroundNA.cpp b/src/game/BattleGroundNA.cpp new file mode 100644 index 00000000000..636efe7e586 --- /dev/null +++ b/src/game/BattleGroundNA.cpp @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Object.h" +#include "Player.h" +#include "BattleGround.h" +#include "BattleGroundNA.h" +#include "Creature.h" +#include "ObjectMgr.h" +#include "MapManager.h" +#include "Language.h" + +BattleGroundNA::BattleGroundNA() +{ + m_BgObjects.resize(BG_NA_OBJECT_MAX); +} + +BattleGroundNA::~BattleGroundNA() +{ + +} + +void BattleGroundNA::Update(time_t diff) +{ + BattleGround::Update(diff); + + // after bg start we get there + if (GetStatus() == STATUS_WAIT_JOIN && GetPlayersSize()) + { + ModifyStartDelayTime(diff); + + if (!(m_Events & 0x01)) + { + m_Events |= 0x01; + for(uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_4; i++) + SpawnBGObject(i, RESPAWN_IMMEDIATELY); + + SetStartDelayTime(START_DELAY1); + SendMessageToAll(LANG_ARENA_ONE_MINUTE); + } + // After 30 seconds, warning is signalled + else if (GetStartDelayTime() <= START_DELAY2 && !(m_Events & 0x04)) + { + m_Events |= 0x04; + SendMessageToAll(LANG_ARENA_THIRTY_SECONDS); + } + // After 15 seconds, warning is signalled + else if (GetStartDelayTime() <= START_DELAY3 && !(m_Events & 0x08)) + { + m_Events |= 0x08; + SendMessageToAll(LANG_ARENA_FIFTEEN_SECONDS); + } + // delay expired (1 minute) + else if (GetStartDelayTime() <= 0 && !(m_Events & 0x10)) + { + m_Events |= 0x10; + + for(uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_2; i++) + DoorOpen(i); + + SendMessageToAll(LANG_ARENA_BEGUN); + SetStatus(STATUS_IN_PROGRESS); + SetStartDelayTime(0); + + for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) + if(Player *plr = objmgr.GetPlayer(itr->first)) + plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION); + } + } + + /*if(GetStatus() == STATUS_IN_PROGRESS) + { + // update something + }*/ +} + +void BattleGroundNA::AddPlayer(Player *plr) +{ + BattleGround::AddPlayer(plr); + //create score and add it to map, default values are set in constructor + BattleGroundNAScore* sc = new BattleGroundNAScore; + + m_PlayerScores[plr->GetGUID()] = sc; +} + +void BattleGroundNA::RemovePlayer(Player* /*plr*/, uint64 /*guid*/) +{ + +} + +void BattleGroundNA::HandleKillPlayer(Player *player, Player *killer) +{ + if(GetStatus() != STATUS_IN_PROGRESS) + return; + + if(!killer) + { + sLog.outError("BattleGroundNA: Killer player not found"); + return; + } + + BattleGround::HandleKillPlayer(player, killer); + + uint32 killer_team_index = GetTeamIndexByTeamId(killer->GetTeam()); + + ++m_TeamKills[killer_team_index]; // add kills to killer's team + + if(m_TeamKills[killer_team_index] >= GetPlayersCountByTeam(player->GetTeam())) + { + // all opponents killed + EndBattleGround(killer->GetTeam()); + } +} + +void BattleGroundNA::HandleAreaTrigger(Player *Source, uint32 Trigger) +{ + if(GetStatus() != STATUS_IN_PROGRESS) + return; + + //uint32 SpellId = 0; + //uint64 buff_guid = 0; + switch(Trigger) + { + case 4536: // buff trigger? + case 4537: // buff trigger? + break; + default: + sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger); + Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger); + break; + } + + //if(buff_guid) + // HandleTriggerBuff(buff_guid,Source); +} + +void BattleGroundNA::ResetBGSubclass() +{ + m_TeamKills[BG_TEAM_ALLIANCE] = 0; + m_TeamKills[BG_TEAM_HORDE] = 0; +} + +bool BattleGroundNA::SetupBattleGround() +{ + // gates + if( !AddObject(BG_NA_OBJECT_DOOR_1, BG_NA_OBJECT_TYPE_DOOR_1, 4031.854f, 2966.833f, 12.6462f, -2.648788f, 0, 0, 0.9697962f, -0.2439165f, RESPAWN_IMMEDIATELY) + || !AddObject(BG_NA_OBJECT_DOOR_2, BG_NA_OBJECT_TYPE_DOOR_2, 4081.179f, 2874.97f, 12.39171f, 0.4928045f, 0, 0, 0.2439165f, 0.9697962f, RESPAWN_IMMEDIATELY) + || !AddObject(BG_NA_OBJECT_DOOR_3, BG_NA_OBJECT_TYPE_DOOR_3, 4023.709f, 2981.777f, 10.70117f, -2.648788f, 0, 0, 0.9697962f, -0.2439165f, RESPAWN_IMMEDIATELY) + || !AddObject(BG_NA_OBJECT_DOOR_4, BG_NA_OBJECT_TYPE_DOOR_4, 4090.064f, 2858.438f, 10.23631f, 0.4928045f, 0, 0, 0.2439165f, 0.9697962f, RESPAWN_IMMEDIATELY)) + { + sLog.outErrorDb("BatteGroundNA: Failed to spawn some object!"); + return false; + } + + return true; +} + +/* +20:12:14 id:036668 [S2C] SMSG_INIT_WORLD_STATES (706 = 0x02C2) len: 86 +0000: 2f 02 00 00 72 0e 00 00 00 00 00 00 09 00 11 0a | /...r........... +0010: 00 00 01 00 00 00 0f 0a 00 00 00 00 00 00 10 0a | ................ +0020: 00 00 00 00 00 00 d4 08 00 00 00 00 00 00 d8 08 | ................ +0030: 00 00 00 00 00 00 d7 08 00 00 00 00 00 00 d6 08 | ................ +0040: 00 00 00 00 00 00 d5 08 00 00 00 00 00 00 d3 08 | ................ +0050: 00 00 00 00 00 00 | ...... +*/ diff --git a/src/game/BattleGroundNA.h b/src/game/BattleGroundNA.h new file mode 100644 index 00000000000..1ca04e8ba2f --- /dev/null +++ b/src/game/BattleGroundNA.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __BATTLEGROUNDNA_H +#define __BATTLEGROUNDNA_H + +class BattleGround; + +enum BattleGroundNAObjectTypes +{ + BG_NA_OBJECT_DOOR_1 = 0, + BG_NA_OBJECT_DOOR_2 = 1, + BG_NA_OBJECT_DOOR_3 = 2, + BG_NA_OBJECT_DOOR_4 = 3, + BG_NA_OBJECT_MAX = 4 +}; + +enum BattleGroundNAObjects +{ + BG_NA_OBJECT_TYPE_DOOR_1 = 183978, + BG_NA_OBJECT_TYPE_DOOR_2 = 183980, + BG_NA_OBJECT_TYPE_DOOR_3 = 183977, + BG_NA_OBJECT_TYPE_DOOR_4 = 183979 +}; + +class BattleGroundNAScore : public BattleGroundScore +{ + public: + BattleGroundNAScore() {}; + virtual ~BattleGroundNAScore() {}; + //TODO fix me +}; + +class BattleGroundNA : public BattleGround +{ + friend class BattleGroundMgr; + + public: + BattleGroundNA(); + ~BattleGroundNA(); + void Update(time_t diff); + + /* inherited from BattlegroundClass */ + virtual void AddPlayer(Player *plr); + + void RemovePlayer(Player *plr, uint64 guid); + void HandleAreaTrigger(Player *Source, uint32 Trigger); + bool SetupBattleGround(); + virtual void ResetBGSubclass(); + void HandleKillPlayer(Player* player, Player *killer); + + private: + uint32 m_TeamKills[2]; // count of kills for each team +}; +#endif diff --git a/src/game/BattleGroundRL.cpp b/src/game/BattleGroundRL.cpp new file mode 100644 index 00000000000..68ba34e06ed --- /dev/null +++ b/src/game/BattleGroundRL.cpp @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Object.h" +#include "Player.h" +#include "BattleGround.h" +#include "BattleGroundRL.h" +#include "Creature.h" +#include "ObjectMgr.h" +#include "MapManager.h" +#include "Language.h" + +BattleGroundRL::BattleGroundRL() +{ + m_BgObjects.resize(BG_RL_OBJECT_MAX); +} + +BattleGroundRL::~BattleGroundRL() +{ + +} + +void BattleGroundRL::Update(time_t diff) +{ + BattleGround::Update(diff); + + if (GetStatus() == STATUS_WAIT_JOIN && GetPlayersSize()) + { + ModifyStartDelayTime(diff); + + if (!(m_Events & 0x01)) + { + m_Events |= 0x01; + + for(uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; i++) + SpawnBGObject(i, RESPAWN_IMMEDIATELY); + + SetStartDelayTime(START_DELAY1); + SendMessageToAll(LANG_ARENA_ONE_MINUTE); + } + // After 30 seconds, warning is signalled + else if (GetStartDelayTime() <= START_DELAY2 && !(m_Events & 0x04)) + { + m_Events |= 0x04; + SendMessageToAll(LANG_ARENA_THIRTY_SECONDS); + } + // After 15 seconds, warning is signalled + else if (GetStartDelayTime() <= START_DELAY3 && !(m_Events & 0x08)) + { + m_Events |= 0x08; + SendMessageToAll(LANG_ARENA_FIFTEEN_SECONDS); + } + // delay expired (1 minute) + else if (GetStartDelayTime() <= 0 && !(m_Events & 0x10)) + { + m_Events |= 0x10; + + for(uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; i++) + DoorOpen(i); + + SendMessageToAll(LANG_ARENA_BEGUN); + SetStatus(STATUS_IN_PROGRESS); + SetStartDelayTime(0); + + for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) + if(Player *plr = objmgr.GetPlayer(itr->first)) + plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION); + } + } + + /*if(GetStatus() == STATUS_IN_PROGRESS) + { + // update something + }*/ +} + +void BattleGroundRL::AddPlayer(Player *plr) +{ + BattleGround::AddPlayer(plr); + //create score and add it to map, default values are set in constructor + BattleGroundRLScore* sc = new BattleGroundRLScore; + + m_PlayerScores[plr->GetGUID()] = sc; +} + +void BattleGroundRL::RemovePlayer(Player *plr, uint64 guid) +{ + +} + +void BattleGroundRL::HandleKillPlayer(Player *player, Player *killer) +{ + if(GetStatus() != STATUS_IN_PROGRESS) + return; + + if(!killer) + { + sLog.outError("Killer player not found"); + return; + } + + BattleGround::HandleKillPlayer(player, killer); + + uint32 killer_team_index = GetTeamIndexByTeamId(killer->GetTeam()); + + ++m_TeamKills[killer_team_index]; // add kills to killer's team + + if(m_TeamKills[killer_team_index] >= GetPlayersCountByTeam(player->GetTeam())) + { + // all opponents killed + EndBattleGround(killer->GetTeam()); + } +} + +void BattleGroundRL::HandleAreaTrigger(Player *Source, uint32 Trigger) +{ + // this is wrong way to implement these things. On official it done by gameobject spell cast. + if(GetStatus() != STATUS_IN_PROGRESS) + return; + + //uint32 SpellId = 0; + //uint64 buff_guid = 0; + switch(Trigger) + { + case 4696: // buff trigger? + case 4697: // buff trigger? + break; + default: + sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger); + Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger); + break; + } + + //if(buff_guid) + // HandleTriggerBuff(buff_guid,Source); +} + +void BattleGroundRL::ResetBGSubclass() +{ + m_TeamKills[BG_TEAM_ALLIANCE] = 0; + m_TeamKills[BG_TEAM_HORDE] = 0; +} + +bool BattleGroundRL::SetupBattleGround() +{ + // gates + if( !AddObject(BG_RL_OBJECT_DOOR_1, BG_RL_OBJECT_TYPE_DOOR_1, 1293.561f, 1601.938f, 31.60557f, -1.457349f, 0, 0, -0.6658813f, 0.7460576f, RESPAWN_IMMEDIATELY) + || !AddObject(BG_RL_OBJECT_DOOR_2, BG_RL_OBJECT_TYPE_DOOR_2, 1278.648f, 1730.557f, 31.60557f, 1.684245f, 0, 0, 0.7460582f, 0.6658807f, RESPAWN_IMMEDIATELY)) + { + sLog.outErrorDb("BatteGroundRL: Failed to spawn some object!"); + return false; + } + + return true; +} + +/* +Packet S->C, id 600, SMSG_INIT_WORLD_STATES (706), len 86 +0000: 3C 02 00 00 80 0F 00 00 00 00 00 00 09 00 BA 0B | <............... +0010: 00 00 01 00 00 00 B9 0B 00 00 02 00 00 00 B8 0B | ................ +0020: 00 00 00 00 00 00 D8 08 00 00 00 00 00 00 D7 08 | ................ +0030: 00 00 00 00 00 00 D6 08 00 00 00 00 00 00 D5 08 | ................ +0040: 00 00 00 00 00 00 D3 08 00 00 00 00 00 00 D4 08 | ................ +0050: 00 00 00 00 00 00 | ...... +*/ diff --git a/src/game/BattleGroundRL.h b/src/game/BattleGroundRL.h new file mode 100644 index 00000000000..2fdbfc4c83c --- /dev/null +++ b/src/game/BattleGroundRL.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __BATTLEGROUNDRL_H +#define __BATTLEGROUNDRL_H + +class BattleGround; + +enum BattleGroundRLObjectTypes +{ + BG_RL_OBJECT_DOOR_1 = 0, + BG_RL_OBJECT_DOOR_2 = 1, + BG_RL_OBJECT_MAX = 2 +}; + +enum BattleGroundRLObjects +{ + BG_RL_OBJECT_TYPE_DOOR_1 = 185918, + BG_RL_OBJECT_TYPE_DOOR_2 = 185917 +}; + +class BattleGroundRLScore : public BattleGroundScore +{ + public: + BattleGroundRLScore() {}; + virtual ~BattleGroundRLScore() {}; + //TODO fix me +}; + +class BattleGroundRL : public BattleGround +{ + friend class BattleGroundMgr; + + public: + BattleGroundRL(); + ~BattleGroundRL(); + void Update(time_t diff); + + /* inherited from BattlegroundClass */ + virtual void AddPlayer(Player *plr); + + void RemovePlayer(Player *plr, uint64 guid); + void HandleAreaTrigger(Player *Source, uint32 Trigger); + bool SetupBattleGround(); + virtual void ResetBGSubclass(); + void HandleKillPlayer(Player* player, Player *killer); + + private: + uint32 m_TeamKills[2]; // count of kills for each team +}; +#endif diff --git a/src/game/BattleGroundWS.cpp b/src/game/BattleGroundWS.cpp new file mode 100644 index 00000000000..d907b6e3bcb --- /dev/null +++ b/src/game/BattleGroundWS.cpp @@ -0,0 +1,678 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Object.h" +#include "Player.h" +#include "BattleGround.h" +#include "BattleGroundWS.h" +#include "Creature.h" +#include "GameObject.h" +#include "Chat.h" +#include "MapManager.h" +#include "Language.h" + +BattleGroundWS::BattleGroundWS() +{ + m_BgObjects.resize(BG_WS_OBJECT_MAX); + m_BgCreatures.resize(BG_CREATURES_MAX_WS); +} + +BattleGroundWS::~BattleGroundWS() +{ +} + +void BattleGroundWS::Update(time_t diff) +{ + BattleGround::Update(diff); + + // after bg start we get there (once) + if (GetStatus() == STATUS_WAIT_JOIN && GetPlayersSize()) + { + ModifyStartDelayTime(diff); + + if(!(m_Events & 0x01)) + { + m_Events |= 0x01; + + for(uint32 i = BG_WS_OBJECT_DOOR_A_1; i <= BG_WS_OBJECT_DOOR_H_4; i++) + { + SpawnBGObject(i, RESPAWN_IMMEDIATELY); + DoorClose(i); + } + for(uint32 i = BG_WS_OBJECT_A_FLAG; i <= BG_WS_OBJECT_BERSERKBUFF_2; i++) + SpawnBGObject(i, RESPAWN_ONE_DAY); + + SetStartDelayTime(START_DELAY0); + } + // After 1 minute, warning is signalled + else if(GetStartDelayTime() <= START_DELAY1 && !(m_Events & 0x04)) + { + m_Events |= 0x04; + SendMessageToAll(GetMangosString(LANG_BG_WS_ONE_MINUTE)); + } + // After 1,5 minute, warning is signalled + else if(GetStartDelayTime() <= START_DELAY2 && !(m_Events & 0x08)) + { + m_Events |= 0x08; + SendMessageToAll(GetMangosString(LANG_BG_WS_HALF_MINUTE)); + } + // After 2 minutes, gates OPEN ! x) + else if(GetStartDelayTime() < 0 && !(m_Events & 0x10)) + { + m_Events |= 0x10; + for(uint32 i = BG_WS_OBJECT_DOOR_A_1; i <= BG_WS_OBJECT_DOOR_A_4; i++) + DoorOpen(i); + for(uint32 i = BG_WS_OBJECT_DOOR_H_1; i <= BG_WS_OBJECT_DOOR_H_2; i++) + DoorOpen(i); + + SpawnBGObject(BG_WS_OBJECT_DOOR_A_5, RESPAWN_ONE_DAY); + SpawnBGObject(BG_WS_OBJECT_DOOR_A_6, RESPAWN_ONE_DAY); + SpawnBGObject(BG_WS_OBJECT_DOOR_H_3, RESPAWN_ONE_DAY); + SpawnBGObject(BG_WS_OBJECT_DOOR_H_4, RESPAWN_ONE_DAY); + + for(uint32 i = BG_WS_OBJECT_A_FLAG; i <= BG_WS_OBJECT_BERSERKBUFF_2; i++) + SpawnBGObject(i, RESPAWN_IMMEDIATELY); + + SendMessageToAll(GetMangosString(LANG_BG_WS_BEGIN)); + + PlaySoundToAll(SOUND_BG_START); + SetStatus(STATUS_IN_PROGRESS); + + for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) + if(Player* plr = objmgr.GetPlayer(itr->first)) + plr->RemoveAurasDueToSpell(SPELL_PREPARATION); + } + } + else if(GetStatus() == STATUS_IN_PROGRESS) + { + if(m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_WAIT_RESPAWN) + { + m_FlagsTimer[BG_TEAM_ALLIANCE] -= diff; + + if(m_FlagsTimer[BG_TEAM_ALLIANCE] < 0) + { + m_FlagsTimer[BG_TEAM_ALLIANCE] = 0; + RespawnFlag(ALLIANCE, true); + } + } + if(m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_ON_GROUND) + { + m_FlagsDropTimer[BG_TEAM_ALLIANCE] -= diff; + + if(m_FlagsDropTimer[BG_TEAM_ALLIANCE] < 0) + { + m_FlagsDropTimer[BG_TEAM_ALLIANCE] = 0; + RespawnFlagAfterDrop(ALLIANCE); + } + } + if(m_FlagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_WAIT_RESPAWN) + { + m_FlagsTimer[BG_TEAM_HORDE] -= diff; + + if(m_FlagsTimer[BG_TEAM_HORDE] < 0) + { + m_FlagsTimer[BG_TEAM_HORDE] = 0; + RespawnFlag(HORDE, true); + } + } + if(m_FlagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_ON_GROUND) + { + m_FlagsDropTimer[BG_TEAM_HORDE] -= diff; + + if(m_FlagsDropTimer[BG_TEAM_HORDE] < 0) + { + m_FlagsDropTimer[BG_TEAM_HORDE] = 0; + RespawnFlagAfterDrop(HORDE); + } + } + } +} + +void BattleGroundWS::AddPlayer(Player *plr) +{ + BattleGround::AddPlayer(plr); + //create score and add it to map, default values are set in constructor + BattleGroundWGScore* sc = new BattleGroundWGScore; + + m_PlayerScores[plr->GetGUID()] = sc; +} + +void BattleGroundWS::RespawnFlag(uint32 Team, bool captured) +{ + if(Team == ALLIANCE) + { + sLog.outDebug("Respawn Alliance flag"); + m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_BASE; + } + else + { + sLog.outDebug("Respawn Horde flag"); + m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_BASE; + } + + if(captured) + { + //when map_update will be allowed for battlegrounds this code will be useless + SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_IMMEDIATELY); + SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_IMMEDIATELY); + SendMessageToAll(GetMangosString(LANG_BG_WS_F_PLACED)); + PlaySoundToAll(BG_WS_SOUND_FLAGS_RESPAWNED); // flag respawned sound... + } +} + +void BattleGroundWS::RespawnFlagAfterDrop(uint32 team) +{ + if(GetStatus() != STATUS_IN_PROGRESS) + return; + + RespawnFlag(team,false); + if(team == ALLIANCE) + { + SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_IMMEDIATELY); + SendMessageToAll(GetMangosString(LANG_BG_WS_ALLIANCE_FLAG_RESPAWNED)); + } + else + { + SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_IMMEDIATELY); + SendMessageToAll(GetMangosString(LANG_BG_WS_HORDE_FLAG_RESPAWNED)); + } + + PlaySoundToAll(BG_WS_SOUND_FLAGS_RESPAWNED); + + GameObject *obj = HashMapHolder::Find(GetDroppedFlagGUID(team)); + if(obj) + obj->Delete(); + else + sLog.outError("unknown droped flag bg, guid: %u",GetDroppedFlagGUID(team)); + + SetDroppedFlagGUID(0,team); +} + +void BattleGroundWS::EventPlayerCapturedFlag(Player *Source) +{ + if(GetStatus() != STATUS_IN_PROGRESS) + return; + + uint8 type = 0; + uint32 winner = 0; + const char *message = ""; + + //TODO FIX reputation and honor gains for low level players! + + Source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); + if(Source->GetTeam() == ALLIANCE) + { + if (!this->IsHordeFlagPickedup()) + return; + SetHordeFlagPicker(0); // must be before aura remove to prevent 2 events (drop+capture) at the same time + // horde flag in base (but not respawned yet) + m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_WAIT_RESPAWN; + // Drop Horde Flag from Player + Source->RemoveAurasDueToSpell(BG_WS_SPELL_WARSONG_FLAG); + message = GetMangosString(LANG_BG_WS_CAPTURED_HF); + type = CHAT_MSG_BG_SYSTEM_ALLIANCE; + if(GetTeamScore(ALLIANCE) < BG_WS_MAX_TEAM_SCORE) + AddPoint(ALLIANCE, 1); + PlaySoundToAll(BG_WS_SOUND_FLAG_CAPTURED_ALLIANCE); + RewardReputationToTeam(890, 35, ALLIANCE); // +35 reputation + RewardHonorToTeam(40, ALLIANCE); // +40 bonushonor + } + else + { + if (!this->IsAllianceFlagPickedup()) + return; + SetAllianceFlagPicker(0); // must be before aura remove to prevent 2 events (drop+capture) at the same time + // alliance flag in base (but not respawned yet) + m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_WAIT_RESPAWN; + // Drop Alliance Flag from Player + Source->RemoveAurasDueToSpell(BG_WS_SPELL_SILVERWING_FLAG); + message = GetMangosString(LANG_BG_WS_CAPTURED_AF); + type = CHAT_MSG_BG_SYSTEM_HORDE; + if(GetTeamScore(HORDE) < BG_WS_MAX_TEAM_SCORE) + AddPoint(HORDE, 1); + PlaySoundToAll(BG_WS_SOUND_FLAG_CAPTURED_HORDE); + RewardReputationToTeam(889, 35, HORDE); // +35 reputation + RewardHonorToTeam(40, HORDE); // +40 bonushonor + } + + SpawnBGObject(BG_WS_OBJECT_H_FLAG, BG_WS_FLAG_RESPAWN_TIME); + SpawnBGObject(BG_WS_OBJECT_A_FLAG, BG_WS_FLAG_RESPAWN_TIME); + + WorldPacket data; + ChatHandler::FillMessageData(&data, Source->GetSession(), type, LANG_UNIVERSAL, NULL, Source->GetGUID(), message, NULL); + SendPacketToAll(&data); + + UpdateFlagState(Source->GetTeam(), 1); // flag state none + UpdateTeamScore(Source->GetTeam()); + // only flag capture should be updated + UpdatePlayerScore(Source, SCORE_FLAG_CAPTURES, 1); // +1 flag captures... + + if(GetTeamScore(ALLIANCE) == BG_WS_MAX_TEAM_SCORE) + winner = ALLIANCE; + + if(GetTeamScore(HORDE) == BG_WS_MAX_TEAM_SCORE) + winner = HORDE; + + if(winner) + { + UpdateWorldState(BG_WS_FLAG_UNK_ALLIANCE, 0); + UpdateWorldState(BG_WS_FLAG_UNK_HORDE, 0); + UpdateWorldState(BG_WS_FLAG_STATE_ALLIANCE, 1); + UpdateWorldState(BG_WS_FLAG_STATE_HORDE, 1); + + EndBattleGround(winner); + } + else + { + m_FlagsTimer[GetTeamIndexByTeamId(Source->GetTeam()) ? 0 : 1] = BG_WS_FLAG_RESPAWN_TIME; + } +} + +void BattleGroundWS::EventPlayerDroppedFlag(Player *Source) +{ + // Drop allowed in any BG state + + const char *message = ""; + uint8 type = 0; + bool set = false; + + if(Source->GetTeam() == ALLIANCE) + { + if(!this->IsHordeFlagPickedup()) + return; + if(GetHordeFlagPickerGUID() == Source->GetGUID()) + { + SetHordeFlagPicker(0); + Source->RemoveAurasDueToSpell(BG_WS_SPELL_WARSONG_FLAG); + m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_GROUND; + message = GetMangosString(LANG_BG_WS_DROPPED_HF); + type = CHAT_MSG_BG_SYSTEM_HORDE; + Source->CastSpell(Source, BG_WS_SPELL_WARSONG_FLAG_DROPPED, true); + set = true; + } + } + else + { + if(!this->IsAllianceFlagPickedup()) + return; + if(GetAllianceFlagPickerGUID() == Source->GetGUID()) + { + SetAllianceFlagPicker(0); + Source->RemoveAurasDueToSpell(BG_WS_SPELL_SILVERWING_FLAG); + m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_GROUND; + message = GetMangosString(LANG_BG_WS_DROPPED_AF); + type = CHAT_MSG_BG_SYSTEM_ALLIANCE; + Source->CastSpell(Source, BG_WS_SPELL_SILVERWING_FLAG_DROPPED, true); + set = true; + } + } + + if (set) + { + Source->CastSpell(Source, SPELL_RECENTLY_DROPPED_FLAG, true); + UpdateFlagState(Source->GetTeam(), 1); + + WorldPacket data; + ChatHandler::FillMessageData(&data, Source->GetSession(), type, LANG_UNIVERSAL, NULL, Source->GetGUID(), message, NULL); + SendPacketToAll(&data); + + if(Source->GetTeam() == ALLIANCE) + UpdateWorldState(BG_WS_FLAG_UNK_HORDE, uint32(-1)); + else + UpdateWorldState(BG_WS_FLAG_UNK_ALLIANCE, uint32(-1)); + + m_FlagsDropTimer[GetTeamIndexByTeamId(Source->GetTeam()) ? 0 : 1] = BG_WS_FLAG_DROP_TIME; + } +} + +void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target_obj) +{ + if(GetStatus() != STATUS_IN_PROGRESS) + return; + + const char *message; + uint8 type = 0; + + //alliance flag picked up from base + if(Source->GetTeam() == HORDE && this->GetFlagState(ALLIANCE) == BG_WS_FLAG_STATE_ON_BASE + && this->m_BgObjects[BG_WS_OBJECT_A_FLAG] == target_obj->GetGUID()) + { + message = GetMangosString(LANG_BG_WS_PICKEDUP_AF); + type = CHAT_MSG_BG_SYSTEM_HORDE; + PlaySoundToAll(BG_WS_SOUND_ALLIANCE_FLAG_PICKED_UP); + SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_ONE_DAY); + SetAllianceFlagPicker(Source->GetGUID()); + m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_PLAYER; + //update world state to show correct flag carrier + UpdateFlagState(HORDE, BG_WS_FLAG_STATE_ON_PLAYER); + UpdateWorldState(BG_WS_FLAG_UNK_ALLIANCE, 1); + Source->CastSpell(Source, BG_WS_SPELL_SILVERWING_FLAG, true); + } + + //horde flag picked up from base + if (Source->GetTeam() == ALLIANCE && this->GetFlagState(HORDE) == BG_WS_FLAG_STATE_ON_BASE + && this->m_BgObjects[BG_WS_OBJECT_H_FLAG] == target_obj->GetGUID()) + { + message = GetMangosString(LANG_BG_WS_PICKEDUP_HF); + type = CHAT_MSG_BG_SYSTEM_ALLIANCE; + PlaySoundToAll(BG_WS_SOUND_HORDE_FLAG_PICKED_UP); + SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_ONE_DAY); + SetHordeFlagPicker(Source->GetGUID()); + m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_PLAYER; + //update world state to show correct flag carrier + UpdateFlagState(ALLIANCE, BG_WS_FLAG_STATE_ON_PLAYER); + UpdateWorldState(BG_WS_FLAG_UNK_HORDE, 1); + Source->CastSpell(Source, BG_WS_SPELL_WARSONG_FLAG, true); + } + + //Alliance flag on ground(not in base) (returned or picked up again from ground!) + if(this->GetFlagState(ALLIANCE) == BG_WS_FLAG_STATE_ON_GROUND && Source->IsWithinDistInMap(target_obj, 10)) + { + if(Source->GetTeam() == ALLIANCE) + { + message = GetMangosString(LANG_BG_WS_RETURNED_AF); + type = CHAT_MSG_BG_SYSTEM_ALLIANCE; + UpdateFlagState(HORDE, BG_WS_FLAG_STATE_WAIT_RESPAWN); + RespawnFlag(ALLIANCE, false); + SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_IMMEDIATELY); + PlaySoundToAll(BG_WS_SOUND_FLAG_RETURNED); + UpdatePlayerScore(Source, SCORE_FLAG_RETURNS, 1); + } + else + { + message = GetMangosString(LANG_BG_WS_PICKEDUP_AF); + type = CHAT_MSG_BG_SYSTEM_HORDE; + PlaySoundToAll(BG_WS_SOUND_ALLIANCE_FLAG_PICKED_UP); + SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_ONE_DAY); + SetAllianceFlagPicker(Source->GetGUID()); + Source->CastSpell(Source, BG_WS_SPELL_SILVERWING_FLAG, true); + m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_PLAYER; + UpdateFlagState(HORDE, BG_WS_FLAG_STATE_ON_PLAYER); + UpdateWorldState(BG_WS_FLAG_UNK_ALLIANCE, 1); + } + //called in HandleGameObjectUseOpcode: + //target_obj->Delete(); + } + + //Horde flag on ground(not in base) (returned or picked up again) + if(this->GetFlagState(HORDE) == BG_WS_FLAG_STATE_ON_GROUND && Source->IsWithinDistInMap(target_obj, 10)) + { + if(Source->GetTeam() == HORDE) + { + message = GetMangosString(LANG_BG_WS_RETURNED_HF); + type = CHAT_MSG_BG_SYSTEM_HORDE; + UpdateFlagState(ALLIANCE, BG_WS_FLAG_STATE_WAIT_RESPAWN); + RespawnFlag(HORDE, false); + SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_IMMEDIATELY); + PlaySoundToAll(BG_WS_SOUND_FLAG_RETURNED); + UpdatePlayerScore(Source, SCORE_FLAG_RETURNS, 1); + } + else + { + message = GetMangosString(LANG_BG_WS_PICKEDUP_HF); + type = CHAT_MSG_BG_SYSTEM_ALLIANCE; + PlaySoundToAll(BG_WS_SOUND_HORDE_FLAG_PICKED_UP); + SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_ONE_DAY); + SetHordeFlagPicker(Source->GetGUID()); + Source->CastSpell(Source, BG_WS_SPELL_WARSONG_FLAG, true); + m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_PLAYER; + UpdateFlagState(ALLIANCE, BG_WS_FLAG_STATE_ON_PLAYER); + UpdateWorldState(BG_WS_FLAG_UNK_HORDE, 1); + } + //called in HandleGameObjectUseOpcode: + //target_obj->Delete(); + } + + if (!type) + return; + + WorldPacket data; + ChatHandler::FillMessageData(&data, Source->GetSession(), type, LANG_UNIVERSAL, NULL, Source->GetGUID(), message, NULL); + SendPacketToAll(&data); + Source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); +} + +void BattleGroundWS::RemovePlayer(Player *plr, uint64 guid) +{ + // sometimes flag aura not removed :( + if(IsAllianceFlagPickedup() && m_FlagKeepers[BG_TEAM_ALLIANCE] == guid) + { + if(!plr) + { + sLog.outError("BattleGroundWS: Removing offline player who has the FLAG!!"); + this->SetAllianceFlagPicker(0); + this->RespawnFlag(ALLIANCE, false); + } + else + this->EventPlayerDroppedFlag(plr); + } + if(IsHordeFlagPickedup() && m_FlagKeepers[BG_TEAM_HORDE] == guid) + { + if(!plr) + { + sLog.outError("BattleGroundWS: Removing offline player who has the FLAG!!"); + this->SetHordeFlagPicker(0); + this->RespawnFlag(HORDE, false); + } + else + this->EventPlayerDroppedFlag(plr); + } +} + +void BattleGroundWS::UpdateFlagState(uint32 team, uint32 value) +{ + if(team == ALLIANCE) + UpdateWorldState(BG_WS_FLAG_STATE_ALLIANCE, value); + else + UpdateWorldState(BG_WS_FLAG_STATE_HORDE, value); +} + +void BattleGroundWS::UpdateTeamScore(uint32 team) +{ + if(team == ALLIANCE) + UpdateWorldState(BG_WS_FLAG_CAPTURES_ALLIANCE, GetTeamScore(team)); + else + UpdateWorldState(BG_WS_FLAG_CAPTURES_HORDE, GetTeamScore(team)); +} + +void BattleGroundWS::HandleAreaTrigger(Player *Source, uint32 Trigger) +{ + // this is wrong way to implement these things. On official it done by gameobject spell cast. + if(GetStatus() != STATUS_IN_PROGRESS) + return; + + //uint32 SpellId = 0; + //uint64 buff_guid = 0; + switch(Trigger) + { + case 3686: // Alliance elixir of speed spawn. Trigger not working, because located inside other areatrigger, can be replaced by IsWithinDist(object, dist) in BattleGround::Update(). + //buff_guid = m_BgObjects[BG_WS_OBJECT_SPEEDBUFF_1]; + break; + case 3687: // Horde elixir of speed spawn. Trigger not working, because located inside other areatrigger, can be replaced by IsWithinDist(object, dist) in BattleGround::Update(). + //buff_guid = m_BgObjects[BG_WS_OBJECT_SPEEDBUFF_2]; + break; + case 3706: // Alliance elixir of regeneration spawn + //buff_guid = m_BgObjects[BG_WS_OBJECT_REGENBUFF_1]; + break; + case 3708: // Horde elixir of regeneration spawn + //buff_guid = m_BgObjects[BG_WS_OBJECT_REGENBUFF_2]; + break; + case 3707: // Alliance elixir of berserk spawn + //buff_guid = m_BgObjects[BG_WS_OBJECT_BERSERKBUFF_1]; + break; + case 3709: // Horde elixir of berserk spawn + //buff_guid = m_BgObjects[BG_WS_OBJECT_BERSERKBUFF_2]; + break; + case 3646: // Alliance Flag spawn + if(m_FlagState[BG_TEAM_HORDE] && !m_FlagState[BG_TEAM_ALLIANCE]) + if(GetHordeFlagPickerGUID() == Source->GetGUID()) + EventPlayerCapturedFlag(Source); + break; + case 3647: // Horde Flag spawn + if(m_FlagState[BG_TEAM_ALLIANCE] && !m_FlagState[BG_TEAM_HORDE]) + if(GetAllianceFlagPickerGUID() == Source->GetGUID()) + EventPlayerCapturedFlag(Source); + break; + case 3649: // unk1 + case 3688: // unk2 + case 4628: // unk3 + case 4629: // unk4 + break; + default: + sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger); + Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger); + break; + } + + //if(buff_guid) + // HandleTriggerBuff(buff_guid,Source); +} + +bool BattleGroundWS::SetupBattleGround() +{ + // flags + if( !AddObject(BG_WS_OBJECT_A_FLAG, BG_OBJECT_A_FLAG_WS_ENTRY, 1540.423f, 1481.325f, 351.8284f, 3.089233f, 0, 0, 0.9996573f, 0.02617699f, BG_WS_FLAG_RESPAWN_TIME/1000) + || !AddObject(BG_WS_OBJECT_H_FLAG, BG_OBJECT_H_FLAG_WS_ENTRY, 916.0226f, 1434.405f, 345.413f, 0.01745329f, 0, 0, 0.008726535f, 0.9999619f, BG_WS_FLAG_RESPAWN_TIME/1000) + // buffs + || !AddObject(BG_WS_OBJECT_SPEEDBUFF_1, BG_OBJECTID_SPEEDBUFF_ENTRY, 1449.93f, 1470.71f, 342.6346f, -1.64061f, 0, 0, 0.7313537f, -0.6819983f, BUFF_RESPAWN_TIME) + || !AddObject(BG_WS_OBJECT_SPEEDBUFF_2, BG_OBJECTID_SPEEDBUFF_ENTRY, 1005.171f, 1447.946f, 335.9032f, 1.64061f, 0, 0, 0.7313537f, 0.6819984f, BUFF_RESPAWN_TIME) + || !AddObject(BG_WS_OBJECT_REGENBUFF_1, BG_OBJECTID_REGENBUFF_ENTRY, 1317.506f, 1550.851f, 313.2344f, -0.2617996f, 0, 0, 0.1305263f, -0.9914448f, BUFF_RESPAWN_TIME) + || !AddObject(BG_WS_OBJECT_REGENBUFF_2, BG_OBJECTID_REGENBUFF_ENTRY, 1110.451f, 1353.656f, 316.5181f, -0.6806787f, 0, 0, 0.333807f, -0.9426414f, BUFF_RESPAWN_TIME) + || !AddObject(BG_WS_OBJECT_BERSERKBUFF_1, BG_OBJECTID_BERSERKERBUFF_ENTRY, 1320.09f, 1378.79f, 314.7532f, 1.186824f, 0, 0, 0.5591929f, 0.8290376f, BUFF_RESPAWN_TIME) + || !AddObject(BG_WS_OBJECT_BERSERKBUFF_2, BG_OBJECTID_BERSERKERBUFF_ENTRY, 1139.688f, 1560.288f, 306.8432f, -2.443461f, 0, 0, 0.9396926f, -0.3420201f, BUFF_RESPAWN_TIME) + // alliance gates + || !AddObject(BG_WS_OBJECT_DOOR_A_1, BG_OBJECT_DOOR_A_1_WS_ENTRY, 1503.335f, 1493.466f, 352.1888f, 3.115414f, 0, 0, 0.9999143f, 0.01308903f, RESPAWN_IMMEDIATELY) + || !AddObject(BG_WS_OBJECT_DOOR_A_2, BG_OBJECT_DOOR_A_2_WS_ENTRY, 1492.478f, 1457.912f, 342.9689f, 3.115414f, 0, 0, 0.9999143f, 0.01308903f, RESPAWN_IMMEDIATELY) + || !AddObject(BG_WS_OBJECT_DOOR_A_3, BG_OBJECT_DOOR_A_3_WS_ENTRY, 1468.503f, 1494.357f, 351.8618f, 3.115414f, 0, 0, 0.9999143f, 0.01308903f, RESPAWN_IMMEDIATELY) + || !AddObject(BG_WS_OBJECT_DOOR_A_4, BG_OBJECT_DOOR_A_4_WS_ENTRY, 1471.555f, 1458.778f, 362.6332f, 3.115414f, 0, 0, 0.9999143f, 0.01308903f, RESPAWN_IMMEDIATELY) + || !AddObject(BG_WS_OBJECT_DOOR_A_5, BG_OBJECT_DOOR_A_5_WS_ENTRY, 1492.347f, 1458.34f, 342.3712f, -0.03490669f, 0, 0, 0.01745246f, -0.9998477f, RESPAWN_IMMEDIATELY) + || !AddObject(BG_WS_OBJECT_DOOR_A_6, BG_OBJECT_DOOR_A_6_WS_ENTRY, 1503.466f, 1493.367f, 351.7352f, -0.03490669f, 0, 0, 0.01745246f, -0.9998477f, RESPAWN_IMMEDIATELY) + // horde gates + || !AddObject(BG_WS_OBJECT_DOOR_H_1, BG_OBJECT_DOOR_H_1_WS_ENTRY, 949.1663f, 1423.772f, 345.6241f, -0.5756807f, -0.01673368f, -0.004956111f, -0.2839723f, 0.9586737f, RESPAWN_IMMEDIATELY) + || !AddObject(BG_WS_OBJECT_DOOR_H_2, BG_OBJECT_DOOR_H_2_WS_ENTRY, 953.0507f, 1459.842f, 340.6526f, -1.99662f, -0.1971825f, 0.1575096f, -0.8239487f, 0.5073641f, RESPAWN_IMMEDIATELY) + || !AddObject(BG_WS_OBJECT_DOOR_H_3, BG_OBJECT_DOOR_H_3_WS_ENTRY, 949.9523f, 1422.751f, 344.9273f, 0.0f, 0, 0, 0, 1, RESPAWN_IMMEDIATELY) + || !AddObject(BG_WS_OBJECT_DOOR_H_4, BG_OBJECT_DOOR_H_4_WS_ENTRY, 950.7952f, 1459.583f, 342.1523f, 0.05235988f, 0, 0, 0.02617695f, 0.9996573f, RESPAWN_IMMEDIATELY) + ) + { + sLog.outErrorDb("BatteGroundWS: Failed to spawn some object BattleGround not created!"); + return false; + } + + WorldSafeLocsEntry const *sg = sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_MAIN_ALLIANCE); + if(!sg || !AddSpiritGuide(WS_SPIRIT_MAIN_ALLIANCE, sg->x, sg->y, sg->z, 3.124139f, ALLIANCE)) + { + sLog.outErrorDb("BatteGroundWS: Failed to spawn Alliance spirit guide! BattleGround not created!"); + return false; + } + + sg = sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_MAIN_HORDE); + if(!sg || !AddSpiritGuide(WS_SPIRIT_MAIN_HORDE, sg->x, sg->y, sg->z, 3.193953f, HORDE)) + { + sLog.outErrorDb("BatteGroundWS: Failed to spawn Horde spirit guide! BattleGround not created!"); + return false; + } + + sLog.outDebug("BatteGroundWS: BG objects and spirit guides spawned"); + + return true; +} + +void BattleGroundWS::ResetBGSubclass() +{ + m_FlagKeepers[BG_TEAM_ALLIANCE] = 0; + m_FlagKeepers[BG_TEAM_HORDE] = 0; + m_DroppedFlagGUID[BG_TEAM_ALLIANCE] = 0; + m_DroppedFlagGUID[BG_TEAM_HORDE] = 0; + m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_BASE; + m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_BASE; + m_TeamScores[BG_TEAM_ALLIANCE] = 0; + m_TeamScores[BG_TEAM_HORDE] = 0; + + /* Spirit nodes is static at this BG and then not required deleting at BG reset. + if(m_BgCreatures[WS_SPIRIT_MAIN_ALLIANCE]) + DelCreature(WS_SPIRIT_MAIN_ALLIANCE); + + if(m_BgCreatures[WS_SPIRIT_MAIN_HORDE]) + DelCreature(WS_SPIRIT_MAIN_HORDE); + */ +} + +void BattleGroundWS::HandleKillPlayer(Player *player, Player *killer) +{ + if(GetStatus() != STATUS_IN_PROGRESS) + return; + + EventPlayerDroppedFlag(player); + + BattleGround::HandleKillPlayer(player, killer); +} + +void BattleGroundWS::UpdatePlayerScore(Player *Source, uint32 type, uint32 value) +{ + + std::map::iterator itr = m_PlayerScores.find(Source->GetGUID()); + + if(itr == m_PlayerScores.end()) // player not found + return; + + switch(type) + { + case SCORE_FLAG_CAPTURES: // flags captured + ((BattleGroundWGScore*)itr->second)->FlagCaptures += value; + break; + case SCORE_FLAG_RETURNS: // flags returned + ((BattleGroundWGScore*)itr->second)->FlagReturns += value; + break; + default: + BattleGround::UpdatePlayerScore(Source, type, value); + break; + } +} + +void BattleGroundWS::FillInitialWorldStates(WorldPacket& data) +{ + data << uint32(BG_WS_FLAG_CAPTURES_ALLIANCE) << uint32(GetTeamScore(ALLIANCE)); + data << uint32(BG_WS_FLAG_CAPTURES_HORDE) << uint32(GetTeamScore(HORDE)); + + if(m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_ON_GROUND) + data << uint32(BG_WS_FLAG_UNK_ALLIANCE) << uint32(-1); + else if (m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_ON_PLAYER) + data << uint32(BG_WS_FLAG_UNK_ALLIANCE) << uint32(1); + else + data << uint32(BG_WS_FLAG_UNK_ALLIANCE) << uint32(0); + + if(m_FlagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_ON_GROUND) + data << uint32(BG_WS_FLAG_UNK_HORDE) << uint32(-1); + else if (m_FlagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_ON_PLAYER) + data << uint32(BG_WS_FLAG_UNK_HORDE) << uint32(1); + else + data << uint32(BG_WS_FLAG_UNK_HORDE) << uint32(0); + + data << uint32(BG_WS_FLAG_CAPTURES_MAX) << uint32(BG_WS_MAX_TEAM_SCORE); + + if (m_FlagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_ON_PLAYER) + data << uint32(BG_WS_FLAG_STATE_HORDE) << uint32(2); + else + data << uint32(BG_WS_FLAG_STATE_HORDE) << uint32(1); + + if (m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_ON_PLAYER) + data << uint32(BG_WS_FLAG_STATE_ALLIANCE) << uint32(2); + else + data << uint32(BG_WS_FLAG_STATE_ALLIANCE) << uint32(1); + +} diff --git a/src/game/BattleGroundWS.h b/src/game/BattleGroundWS.h new file mode 100644 index 00000000000..d9f2b7f6142 --- /dev/null +++ b/src/game/BattleGroundWS.h @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __BATTLEGROUNDWS_H +#define __BATTLEGROUNDWS_H + +#include "BattleGround.h" + +#define BG_WS_MAX_TEAM_SCORE 3 +#define BG_WS_FLAG_RESPAWN_TIME 23000 +#define BG_WS_FLAG_DROP_TIME 10000 + +enum BG_WS_Sound +{ + BG_WS_SOUND_FLAG_CAPTURED_ALLIANCE = 8173, + BG_WS_SOUND_FLAG_CAPTURED_HORDE = 8213, + BG_WS_SOUND_FLAG_PLACED = 8232, + BG_WS_SOUND_FLAG_RETURNED = 8192, + BG_WS_SOUND_HORDE_FLAG_PICKED_UP = 8212, + BG_WS_SOUND_ALLIANCE_FLAG_PICKED_UP = 8174, + BG_WS_SOUND_FLAGS_RESPAWNED = 8232 +}; + +enum BG_WS_SpellId +{ + BG_WS_SPELL_WARSONG_FLAG = 23333, + BG_WS_SPELL_WARSONG_FLAG_DROPPED = 23334, + BG_WS_SPELL_SILVERWING_FLAG = 23335, + BG_WS_SPELL_SILVERWING_FLAG_DROPPED = 23336 +}; + +enum BG_WS_WorldStates +{ + BG_WS_FLAG_UNK_ALLIANCE = 1545, + BG_WS_FLAG_UNK_HORDE = 1546, +// FLAG_UNK = 1547, + BG_WS_FLAG_CAPTURES_ALLIANCE = 1581, + BG_WS_FLAG_CAPTURES_HORDE = 1582, + BG_WS_FLAG_CAPTURES_MAX = 1601, + BG_WS_FLAG_STATE_HORDE = 2338, + BG_WS_FLAG_STATE_ALLIANCE = 2339 +}; + +enum BG_WS_ObjectTypes +{ + BG_WS_OBJECT_DOOR_A_1 = 0, + BG_WS_OBJECT_DOOR_A_2 = 1, + BG_WS_OBJECT_DOOR_A_3 = 2, + BG_WS_OBJECT_DOOR_A_4 = 3, + BG_WS_OBJECT_DOOR_A_5 = 4, + BG_WS_OBJECT_DOOR_A_6 = 5, + BG_WS_OBJECT_DOOR_H_1 = 6, + BG_WS_OBJECT_DOOR_H_2 = 7, + BG_WS_OBJECT_DOOR_H_3 = 8, + BG_WS_OBJECT_DOOR_H_4 = 9, + BG_WS_OBJECT_A_FLAG = 10, + BG_WS_OBJECT_H_FLAG = 11, + BG_WS_OBJECT_SPEEDBUFF_1 = 12, + BG_WS_OBJECT_SPEEDBUFF_2 = 13, + BG_WS_OBJECT_REGENBUFF_1 = 14, + BG_WS_OBJECT_REGENBUFF_2 = 15, + BG_WS_OBJECT_BERSERKBUFF_1 = 16, + BG_WS_OBJECT_BERSERKBUFF_2 = 17, + BG_WS_OBJECT_MAX = 18 +}; + +enum BG_WS_ObjectEntry +{ + BG_OBJECT_DOOR_A_1_WS_ENTRY = 179918, + BG_OBJECT_DOOR_A_2_WS_ENTRY = 179919, + BG_OBJECT_DOOR_A_3_WS_ENTRY = 179920, + BG_OBJECT_DOOR_A_4_WS_ENTRY = 179921, + BG_OBJECT_DOOR_A_5_WS_ENTRY = 180322, + BG_OBJECT_DOOR_A_6_WS_ENTRY = 180322, + BG_OBJECT_DOOR_H_1_WS_ENTRY = 179916, + BG_OBJECT_DOOR_H_2_WS_ENTRY = 179917, + BG_OBJECT_DOOR_H_3_WS_ENTRY = 180322, + BG_OBJECT_DOOR_H_4_WS_ENTRY = 180322, + BG_OBJECT_A_FLAG_WS_ENTRY = 179830, + BG_OBJECT_H_FLAG_WS_ENTRY = 179831 +}; + +enum BG_WS_FlagState +{ + BG_WS_FLAG_STATE_ON_BASE = 0, + BG_WS_FLAG_STATE_WAIT_RESPAWN = 1, + BG_WS_FLAG_STATE_ON_PLAYER = 2, + BG_WS_FLAG_STATE_ON_GROUND = 3 +}; + +enum BG_WS_Graveyards +{ + WS_GRAVEYARD_MAIN_ALLIANCE = 771, + WS_GRAVEYARD_MAIN_HORDE = 772 +}; + +enum BG_WS_CreatureTypes +{ + WS_SPIRIT_MAIN_ALLIANCE = 0, + WS_SPIRIT_MAIN_HORDE = 1, + + BG_CREATURES_MAX_WS = 2 +}; + +class BattleGroundWGScore : public BattleGroundScore +{ + public: + BattleGroundWGScore() : FlagCaptures(0), FlagReturns(0) {}; + virtual ~BattleGroundWGScore() {}; + uint32 FlagCaptures; + uint32 FlagReturns; +}; + +class BattleGroundWS : public BattleGround +{ + friend class BattleGroundMgr; + + public: + /* Construction */ + BattleGroundWS(); + ~BattleGroundWS(); + void Update(time_t diff); + + /* inherited from BattlegroundClass */ + virtual void AddPlayer(Player *plr); + + /* BG Flags */ + uint64 GetAllianceFlagPickerGUID() const { return m_FlagKeepers[BG_TEAM_ALLIANCE]; } + uint64 GetHordeFlagPickerGUID() const { return m_FlagKeepers[BG_TEAM_HORDE]; } + void SetAllianceFlagPicker(uint64 guid) { m_FlagKeepers[BG_TEAM_ALLIANCE] = guid; } + void SetHordeFlagPicker(uint64 guid) { m_FlagKeepers[BG_TEAM_HORDE] = guid; } + bool IsAllianceFlagPickedup() const { return m_FlagKeepers[BG_TEAM_ALLIANCE] != 0; } + bool IsHordeFlagPickedup() const { return m_FlagKeepers[BG_TEAM_HORDE] != 0; } + void RespawnFlag(uint32 Team, bool captured); + void RespawnFlagAfterDrop(uint32 Team); + uint8 GetFlagState(uint32 team) { return m_FlagState[GetTeamIndexByTeamId(team)]; } + + /* Battleground Events */ + virtual void EventPlayerDroppedFlag(Player *Source); + virtual void EventPlayerClickedOnFlag(Player *Source, GameObject* target_obj); + virtual void EventPlayerCapturedFlag(Player *Source); + + void RemovePlayer(Player *plr, uint64 guid); + void HandleAreaTrigger(Player *Source, uint32 Trigger); + void HandleKillPlayer(Player *player, Player *killer); + bool SetupBattleGround(); + virtual void ResetBGSubclass(); + + void UpdateFlagState(uint32 team, uint32 value); + void UpdateTeamScore(uint32 team); + void UpdatePlayerScore(Player *Source, uint32 type, uint32 value); + void SetDroppedFlagGUID(uint64 guid, uint32 TeamID) { m_DroppedFlagGUID[GetTeamIndexByTeamId(TeamID)] = guid;} + uint64 GetDroppedFlagGUID(uint32 TeamID) { return m_DroppedFlagGUID[GetTeamIndexByTeamId(TeamID)];} + virtual void FillInitialWorldStates(WorldPacket& data); + + /* Scorekeeping */ + uint32 GetTeamScore(uint32 TeamID) const { return m_TeamScores[GetTeamIndexByTeamId(TeamID)]; } + void AddPoint(uint32 TeamID, uint32 Points = 1) { m_TeamScores[GetTeamIndexByTeamId(TeamID)] += Points; } + void SetTeamPoint(uint32 TeamID, uint32 Points = 0) { m_TeamScores[GetTeamIndexByTeamId(TeamID)] = Points; } + void RemovePoint(uint32 TeamID, uint32 Points = 1) { m_TeamScores[GetTeamIndexByTeamId(TeamID)] -= Points; } + + private: + uint64 m_FlagKeepers[2]; // 0 - alliance, 1 - horde + uint64 m_DroppedFlagGUID[2]; + uint8 m_FlagState[2]; // for checking flag state + uint32 m_TeamScores[2]; + int32 m_FlagsTimer[2]; + int32 m_FlagsDropTimer[2]; +}; +#endif diff --git a/src/game/Cell.h b/src/game/Cell.h new file mode 100644 index 00000000000..873debabb14 --- /dev/null +++ b/src/game/Cell.h @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_CELL_H +#define MANGOS_CELL_H + +#include "GameSystem/TypeContainer.h" +#include "GameSystem/TypeContainerVisitor.h" +#include "GridDefines.h" +#include + +class Map; + +enum District +{ + UPPER_DISTRICT = 1, + LOWER_DISTRICT = 1 << 1, + LEFT_DISTRICT = 1 << 2, + RIGHT_DISTRICT = 1 << 3, + CENTER_DISTRICT = 1 << 4, + UPPER_LEFT_DISTRICT = (UPPER_DISTRICT | LEFT_DISTRICT), + UPPER_RIGHT_DISTRICT = (UPPER_DISTRICT | RIGHT_DISTRICT), + LOWER_LEFT_DISTRICT = (LOWER_DISTRICT | LEFT_DISTRICT), + LOWER_RIGHT_DISTRICT = (LOWER_DISTRICT | RIGHT_DISTRICT), + ALL_DISTRICT = (UPPER_DISTRICT | LOWER_DISTRICT | LEFT_DISTRICT | RIGHT_DISTRICT | CENTER_DISTRICT) +}; + +template struct CellLock; + +struct MANGOS_DLL_DECL Cell +{ + Cell() { data.All = 0; } + Cell(const Cell &cell) { data.All = cell.data.All; } + explicit Cell(CellPair const& p); + + void operator|=(Cell &cell) + { + data.Part.reserved = 0; + cell.data.Part.reserved = 0; + uint32 x, y, old_x, old_y; + Compute(x, y); + cell.Compute(old_x, old_y); + + if( std::abs(int(x-old_x)) > 1 || std::abs(int(y-old_y)) > 1) + { + data.Part.reserved = ALL_DISTRICT; + cell.data.Part.reserved = ALL_DISTRICT; + return; + } + + if( x < old_x ) + { + data.Part.reserved |= LEFT_DISTRICT; + cell.data.Part.reserved |= RIGHT_DISTRICT; + } + else if( old_x < x ) + { + data.Part.reserved |= RIGHT_DISTRICT; + cell.data.Part.reserved |= LEFT_DISTRICT; + } + if( y < old_y ) + { + data.Part.reserved |= UPPER_DISTRICT; + cell.data.Part.reserved |= LOWER_DISTRICT; + } + else if( old_y < y ) + { + data.Part.reserved |= LOWER_DISTRICT; + cell.data.Part.reserved |= UPPER_DISTRICT; + } + } + + void Compute(uint32 &x, uint32 &y) const + { + x = data.Part.grid_x*MAX_NUMBER_OF_CELLS + data.Part.cell_x; + y = data.Part.grid_y*MAX_NUMBER_OF_CELLS + data.Part.cell_y; + } + + inline bool DiffCell(const Cell &cell) const + { + return( data.Part.cell_x != cell.data.Part.cell_x || + data.Part.cell_y != cell.data.Part.cell_y ); + } + + inline bool DiffGrid(const Cell &cell) const + { + return( data.Part.grid_x != cell.data.Part.grid_x || + data.Part.grid_y != cell.data.Part.grid_y ); + } + + uint32 CellX() const { return data.Part.cell_x; } + uint32 CellY() const { return data.Part.cell_y; } + uint32 GridX() const { return data.Part.grid_x; } + uint32 GridY() const { return data.Part.grid_y; } + bool NoCreate() const { return data.Part.nocreate; } + void SetNoCreate() { data.Part.nocreate = 1; } + + CellPair cellPair() const + { + return CellPair( + data.Part.grid_x*MAX_NUMBER_OF_CELLS+data.Part.cell_x, + data.Part.grid_y*MAX_NUMBER_OF_CELLS+data.Part.cell_y); + } + + Cell& operator=(const Cell &cell) + { + this->data.All = cell.data.All; + return *this; + } + + bool operator==(const Cell &cell) const { return (data.All == cell.data.All); } + bool operator!=(const Cell &cell) const { return !operator==(cell); } + union + { + struct + { + unsigned grid_x : 6; + unsigned grid_y : 6; + unsigned cell_x : 4; + unsigned cell_y : 4; + unsigned nocreate : 1; + unsigned reserved : 11; + } Part; + uint32 All; + } data; + + template void Visit(const CellLock &, TypeContainerVisitor &visitor, Map &) const; +}; + +template +struct MANGOS_DLL_DECL CellLock +{ + const Cell& i_cell; + const CellPair &i_cellPair; + CellLock(const Cell &c, const CellPair &p) : i_cell(c), i_cellPair(p) {} + CellLock(const CellLock &cell) : i_cell(cell.i_cell), i_cellPair(cell.i_cellPair) {} + const Cell* operator->(void) const { return &i_cell; } + const Cell* operator->(void) { return &i_cell; } + operator const Cell &(void) const { return i_cell; } + CellLock& operator=(const CellLock &cell) + { + this->~CellLock(); + new (this) CellLock(cell); + return *this; + } +}; +#endif diff --git a/src/game/CellImpl.h b/src/game/CellImpl.h new file mode 100644 index 00000000000..72c41e4b3c4 --- /dev/null +++ b/src/game/CellImpl.h @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_CELLIMPL_H +#define MANGOS_CELLIMPL_H + +#include "Cell.h" +#include "Map.h" +#include + +inline Cell::Cell(CellPair const& p) +{ + data.Part.grid_x = p.x_coord / MAX_NUMBER_OF_CELLS; + data.Part.grid_y = p.y_coord / MAX_NUMBER_OF_CELLS; + data.Part.cell_x = p.x_coord % MAX_NUMBER_OF_CELLS; + data.Part.cell_y = p.y_coord % MAX_NUMBER_OF_CELLS; + data.Part.nocreate = 0; + data.Part.reserved = 0; +} + +template +inline void +Cell::Visit(const CellLock &l, TypeContainerVisitor &visitor, Map &m) const +{ + const CellPair &standing_cell = l.i_cellPair; + if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) + return; + + uint16 district = (District)this->data.Part.reserved; + if(district == CENTER_DISTRICT) + { + m.Visit(l, visitor); + return; + } + + // set up the cell range based on the district + // the overloaded operators handle range checking + CellPair begin_cell = standing_cell; + CellPair end_cell = standing_cell; + + switch( district ) + { + case ALL_DISTRICT: + { + begin_cell << 1; begin_cell -= 1; // upper left + end_cell >> 1; end_cell += 1; // lower right + break; + } + case UPPER_LEFT_DISTRICT: + { + begin_cell << 1; begin_cell -= 1; // upper left + break; + } + case UPPER_RIGHT_DISTRICT: + { + begin_cell -= 1; // up + end_cell >> 1; // right + break; + } + case LOWER_LEFT_DISTRICT: + { + begin_cell << 1; // left + end_cell += 1; // down + break; + } + case LOWER_RIGHT_DISTRICT: + { + end_cell >> 1; end_cell += 1; // lower right + break; + } + case LEFT_DISTRICT: + { + begin_cell -= 1; // up + end_cell >> 1; end_cell += 1; // lower right + break; + } + case RIGHT_DISTRICT: + { + begin_cell << 1; begin_cell -= 1; // upper left + end_cell += 1; // down + break; + } + case UPPER_DISTRICT: + { + begin_cell << 1; begin_cell -= 1; // upper left + end_cell >> 1; // right + break; + } + case LOWER_DISTRICT: + { + begin_cell << 1; // left + end_cell >> 1; end_cell += 1; // lower right + break; + } + default: + { + assert( false ); + break; + } + } + + // loop the cell range + for(uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; x++) + { + for(uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; y++) + { + CellPair cell_pair(x,y); + Cell r_zone(cell_pair); + r_zone.data.Part.nocreate = l->data.Part.nocreate; + CellLock lock(r_zone, cell_pair); + m.Visit(lock, visitor); + } + } +} +#endif diff --git a/src/game/Channel.cpp b/src/game/Channel.cpp new file mode 100644 index 00000000000..0fff8c7854b --- /dev/null +++ b/src/game/Channel.cpp @@ -0,0 +1,994 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Channel.h" +#include "ObjectMgr.h" +#include "World.h" +#include "SocialMgr.h" + +Channel::Channel(std::string name, uint32 channel_id) +: m_name(name), m_announce(true), m_moderate(false), m_channelId(channel_id), m_ownerGUID(0), m_password(""), m_flags(0) +{ + // set special flags if built-in channel + ChatChannelsEntry const* ch = GetChannelEntryFor(channel_id); + if(ch) // it's built-in channel + { + channel_id = ch->ChannelID; // built-in channel + m_announce = false; // no join/leave announces + + m_flags |= CHANNEL_FLAG_GENERAL; // for all built-in channels + + if(ch->flags & CHANNEL_DBC_FLAG_TRADE) // for trade channel + m_flags |= CHANNEL_FLAG_TRADE; + + if(ch->flags & CHANNEL_DBC_FLAG_CITY_ONLY2) // for city only channels + m_flags |= CHANNEL_FLAG_CITY; + + if(ch->flags & CHANNEL_DBC_FLAG_LFG) // for LFG channel + m_flags |= CHANNEL_FLAG_LFG; + else // for all other channels + m_flags |= CHANNEL_FLAG_NOT_LFG; + } + else // it's custom channel + { + m_flags |= CHANNEL_FLAG_CUSTOM; + } +} + +void Channel::Join(uint64 p, const char *pass) +{ + WorldPacket data; + if(IsOn(p)) + { + if(!IsConstant()) // non send error message for built-in channels + { + MakePlayerAlreadyMember(&data, p); + SendToOne(&data, p); + } + return; + } + + if(IsBanned(p)) + { + MakeBanned(&data); + SendToOne(&data, p); + return; + } + + if(m_password.length() > 0 && strcmp(pass, m_password.c_str())) + { + MakeWrongPassword(&data); + SendToOne(&data, p); + return; + } + + Player *plr = objmgr.GetPlayer(p); + + if(plr) + { + if(HasFlag(CHANNEL_FLAG_LFG) && + sWorld.getConfig(CONFIG_RESTRICTED_LFG_CHANNEL) && plr->GetSession()->GetSecurity() == SEC_PLAYER && + (plr->GetGroup() || plr->m_lookingForGroup.Empty()) ) + { + MakeNotInLfg(&data); + SendToOne(&data, p); + return; + } + + if(plr->GetGuildId() && (GetFlags() == 0x38)) + return; + + plr->JoinedChannel(this); + } + + if(m_announce && (!plr || plr->GetSession()->GetSecurity() < SEC_GAMEMASTER || !sWorld.getConfig(CONFIG_SILENTLY_GM_JOIN_TO_CHANNEL) )) + { + MakeJoined(&data, p); + SendToAll(&data); + } + + data.clear(); + + PlayerInfo pinfo; + pinfo.player = p; + pinfo.flags = 0; + players[p] = pinfo; + + MakeYouJoined(&data); + SendToOne(&data, p); + + JoinNotify(p); + + // if no owner first logged will become + if(!IsConstant() && !m_ownerGUID) + { + SetOwner(p, (players.size() > 1 ? true : false)); + players[p].SetModerator(true); + } +} + +void Channel::Leave(uint64 p, bool send) +{ + if(!IsOn(p)) + { + if(send) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, p); + } + } + else + { + Player *plr = objmgr.GetPlayer(p); + + if(send) + { + WorldPacket data; + MakeYouLeft(&data); + SendToOne(&data, p); + if(plr) + plr->LeftChannel(this); + data.clear(); + } + + bool changeowner = players[p].IsOwner(); + + players.erase(p); + if(m_announce && (!plr || plr->GetSession()->GetSecurity() < SEC_GAMEMASTER || !sWorld.getConfig(CONFIG_SILENTLY_GM_JOIN_TO_CHANNEL) )) + { + WorldPacket data; + MakeLeft(&data, p); + SendToAll(&data); + } + + LeaveNotify(p); + + if(changeowner) + { + uint64 newowner = !players.empty() ? players.begin()->second.player : 0; + SetOwner(newowner); + } + } +} + +void Channel::KickOrBan(uint64 good, const char *badname, bool ban) +{ + uint32 sec = 0; + Player *gplr = objmgr.GetPlayer(good); + if(gplr) + sec = gplr->GetSession()->GetSecurity(); + + if(!IsOn(good)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, good); + } + else if(!players[good].IsModerator() && sec < SEC_GAMEMASTER) + { + WorldPacket data; + MakeNotModerator(&data); + SendToOne(&data, good); + } + else + { + Player *bad = objmgr.GetPlayer(badname); + if(bad == NULL || !IsOn(bad->GetGUID())) + { + WorldPacket data; + MakePlayerNotFound(&data, badname); + SendToOne(&data, good); + } + else if(sec < SEC_GAMEMASTER && bad->GetGUID() == m_ownerGUID && good != m_ownerGUID) + { + WorldPacket data; + MakeNotOwner(&data); + SendToOne(&data, good); + } + else + { + bool changeowner = (m_ownerGUID == bad->GetGUID()); + + WorldPacket data; + + if(ban && !IsBanned(bad->GetGUID())) + { + banned.push_back(bad->GetGUID()); + MakePlayerBanned(&data, bad->GetGUID(), good); + } + else + MakePlayerKicked(&data, bad->GetGUID(), good); + + SendToAll(&data); + players.erase(bad->GetGUID()); + bad->LeftChannel(this); + + if(changeowner) + { + uint64 newowner = !players.empty() ? good : false; + SetOwner(newowner); + } + } + } +} + +void Channel::UnBan(uint64 good, const char *badname) +{ + uint32 sec = 0; + Player *gplr = objmgr.GetPlayer(good); + if(gplr) + sec = gplr->GetSession()->GetSecurity(); + + if(!IsOn(good)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, good); + } + else if(!players[good].IsModerator() && sec < SEC_GAMEMASTER) + { + WorldPacket data; + MakeNotModerator(&data); + SendToOne(&data, good); + } + else + { + Player *bad = objmgr.GetPlayer(badname); + if(bad == NULL || !IsBanned(bad->GetGUID())) + { + WorldPacket data; + MakePlayerNotFound(&data, badname); + SendToOne(&data, good); + } + else + { + banned.remove(bad->GetGUID()); + + WorldPacket data; + MakePlayerUnbanned(&data, bad->GetGUID(), good); + SendToAll(&data); + } + } +} + +void Channel::Password(uint64 p, const char *pass) +{ + uint32 sec = 0; + Player *plr = objmgr.GetPlayer(p); + if(plr) + sec = plr->GetSession()->GetSecurity(); + + if(!IsOn(p)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, p); + } + else if(!players[p].IsModerator() && sec < SEC_GAMEMASTER) + { + WorldPacket data; + MakeNotModerator(&data); + SendToOne(&data, p); + } + else + { + m_password = pass; + + WorldPacket data; + MakePasswordChanged(&data, p); + SendToAll(&data); + } +} + +void Channel::SetMode(uint64 p, const char *p2n, bool mod, bool set) +{ + uint32 sec = 0; + Player *plr = objmgr.GetPlayer(p); + if(plr) + sec = plr->GetSession()->GetSecurity(); + + if(!IsOn(p)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, p); + } + else if(!players[p].IsModerator() && sec < SEC_GAMEMASTER) + { + WorldPacket data; + MakeNotModerator(&data); + SendToOne(&data, p); + } + else + { + Player *newp = objmgr.GetPlayer(p2n); + if(!newp) + { + WorldPacket data; + MakePlayerNotFound(&data, p2n); + SendToOne(&data, p); + return; + } + + PlayerInfo inf = players[newp->GetGUID()]; + if(p == m_ownerGUID && newp->GetGUID() == m_ownerGUID && mod) + return; + + if(!IsOn(newp->GetGUID())) + { + WorldPacket data; + MakePlayerNotFound(&data, p2n); + SendToOne(&data, p); + return; + } + + // allow make moderator from another team only if both is GMs + // at this moment this only way to show channel post for GM from another team + if( (plr->GetSession()->GetSecurity() < SEC_GAMEMASTER || newp->GetSession()->GetSecurity() < SEC_GAMEMASTER) && + plr->GetTeam() != newp->GetTeam() && !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL) ) + { + WorldPacket data; + MakePlayerNotFound(&data, p2n); + SendToOne(&data, p); + return; + } + + if(m_ownerGUID == newp->GetGUID() && m_ownerGUID != p) + { + WorldPacket data; + MakeNotOwner(&data); + SendToOne(&data, p); + return; + } + + if(mod) + SetModerator(newp->GetGUID(), set); + else + SetMute(newp->GetGUID(), set); + } +} + +void Channel::SetOwner(uint64 p, const char *newname) +{ + uint32 sec = 0; + Player *plr = objmgr.GetPlayer(p); + if(plr) + sec = plr->GetSession()->GetSecurity(); + + if(!IsOn(p)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, p); + return; + } + + if(sec < SEC_GAMEMASTER && p != m_ownerGUID) + { + WorldPacket data; + MakeNotOwner(&data); + SendToOne(&data, p); + return; + } + + Player *newp = objmgr.GetPlayer(newname); + if(newp == NULL || !IsOn(newp->GetGUID())) + { + WorldPacket data; + MakePlayerNotFound(&data, newname); + SendToOne(&data, p); + return; + } + + if(newp->GetTeam() != plr->GetTeam() && !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL)) + { + WorldPacket data; + MakePlayerNotFound(&data, newname); + SendToOne(&data, p); + return; + } + + players[newp->GetGUID()].SetModerator(true); + SetOwner(newp->GetGUID()); +} + +void Channel::SendWhoOwner(uint64 p) +{ + if(!IsOn(p)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, p); + } + else + { + WorldPacket data; + MakeChannelOwner(&data); + SendToOne(&data, p); + } +} + +void Channel::List(Player* player) +{ + uint64 p = player->GetGUID(); + + if(!IsOn(p)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, p); + } + else + { + WorldPacket data(SMSG_CHANNEL_LIST, 1+(GetName().size()+1)+1+4+players.size()*(8+1)); + data << uint8(1); // channel type? + data << GetName(); // channel name + data << uint8(GetFlags()); // channel flags? + + size_t pos = data.wpos(); + data << uint32(0); // size of list, placeholder + + bool gmInWhoList = sWorld.getConfig(CONFIG_GM_IN_WHO_LIST) || player->GetSession()->GetSecurity() > SEC_PLAYER; + + uint32 count = 0; + for(PlayerList::iterator i = players.begin(); i != players.end(); ++i) + { + Player *plr = objmgr.GetPlayer(i->first); + + // PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters + // MODERATOR, GAME MASTER, ADMINISTRATOR can see all + if( plr && ( plr->GetSession()->GetSecurity() == SEC_PLAYER || gmInWhoList && plr->IsVisibleGloballyFor(player) ) ) + { + data << uint64(i->first); + data << uint8(i->second.flags); // flags seems to be changed... + ++count; + } + } + + data.put(pos,count); + + SendToOne(&data, p); + } +} + +void Channel::Announce(uint64 p) +{ + uint32 sec = 0; + Player *plr = objmgr.GetPlayer(p); + if(plr) + sec = plr->GetSession()->GetSecurity(); + + if(!IsOn(p)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, p); + } + else if(!players[p].IsModerator() && sec < SEC_GAMEMASTER) + { + WorldPacket data; + MakeNotModerator(&data); + SendToOne(&data, p); + } + else + { + m_announce = !m_announce; + + WorldPacket data; + if(m_announce) + MakeAnnouncementsOn(&data, p); + else + MakeAnnouncementsOff(&data, p); + SendToAll(&data); + } +} + +void Channel::Moderate(uint64 p) +{ + uint32 sec = 0; + Player *plr = objmgr.GetPlayer(p); + if(plr) + sec = plr->GetSession()->GetSecurity(); + + if(!IsOn(p)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, p); + } + else if(!players[p].IsModerator() && sec < SEC_GAMEMASTER) + { + WorldPacket data; + MakeNotModerator(&data); + SendToOne(&data, p); + } + else + { + m_moderate = !m_moderate; + + WorldPacket data; + if(m_moderate) + MakeModerationOn(&data, p); + else + MakeModerationOff(&data, p); + SendToAll(&data); + } +} + +void Channel::Say(uint64 p, const char *what, uint32 lang) +{ + if(!what) + return; + if (sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL)) + lang = LANG_UNIVERSAL; + + uint32 sec = 0; + Player *plr = objmgr.GetPlayer(p); + if(plr) + sec = plr->GetSession()->GetSecurity(); + + if(!IsOn(p)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, p); + } + else if(players[p].IsMuted()) + { + WorldPacket data; + MakeMuted(&data); + SendToOne(&data, p); + } + else if(m_moderate && !players[p].IsModerator() && sec < SEC_GAMEMASTER) + { + WorldPacket data; + MakeNotModerator(&data); + SendToOne(&data, p); + } + else + { + uint32 messageLength = strlen(what) + 1; + + WorldPacket data(SMSG_MESSAGECHAT, 1+4+8+4+m_name.size()+1+8+4+messageLength+1); + data << (uint8)CHAT_MSG_CHANNEL; + data << (uint32)lang; + data << p; // 2.1.0 + data << uint32(0); // 2.1.0 + data << m_name; + data << p; + data << messageLength; + data << what; + data << uint8(plr ? plr->chatTag() : 0); + + SendToAll(&data, !players[p].IsModerator() ? p : false); + } +} + +void Channel::Invite(uint64 p, const char *newname) +{ + if(!IsOn(p)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, p); + return; + } + + Player *newp = objmgr.GetPlayer(newname); + if(!newp) + { + WorldPacket data; + MakePlayerNotFound(&data, newname); + SendToOne(&data, p); + return; + } + + Player *plr = objmgr.GetPlayer(p); + if (!plr) + return; + + if (newp->GetTeam() != plr->GetTeam() && !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL)) + { + WorldPacket data; + MakeInviteWrongFaction(&data); + SendToOne(&data, p); + return; + } + + if(IsOn(newp->GetGUID())) + { + WorldPacket data; + MakePlayerAlreadyMember(&data, newp->GetGUID()); + SendToOne(&data, p); + return; + } + + WorldPacket data; + if(!newp->GetSocial()->HasIgnore(GUID_LOPART(p))) + { + MakeInvite(&data, p); + SendToOne(&data, newp->GetGUID()); + data.clear(); + } + MakePlayerInvited(&data, newp->GetGUID()); + SendToOne(&data, p); +} + +void Channel::SetOwner(uint64 guid, bool exclaim) +{ + if(m_ownerGUID) + { + // [] will re-add player after it possible removed + PlayerList::iterator p_itr = players.find(m_ownerGUID); + if(p_itr != players.end()) + p_itr->second.SetOwner(false); + } + + m_ownerGUID = guid; + if(m_ownerGUID) + { + uint8 oldFlag = GetPlayerFlags(m_ownerGUID); + players[m_ownerGUID].SetOwner(true); + + WorldPacket data; + MakeModeChange(&data, m_ownerGUID, oldFlag); + SendToAll(&data); + + if(exclaim) + { + MakeOwnerChanged(&data, m_ownerGUID); + SendToAll(&data); + } + } +} + +void Channel::SendToAll(WorldPacket *data, uint64 p) +{ + for(PlayerList::iterator i = players.begin(); i != players.end(); ++i) + { + Player *plr = objmgr.GetPlayer(i->first); + if(plr) + { + if(!p || !plr->GetSocial()->HasIgnore(GUID_LOPART(p))) + plr->GetSession()->SendPacket(data); + } + } +} + +void Channel::SendToAllButOne(WorldPacket *data, uint64 who) +{ + for(PlayerList::iterator i = players.begin(); i != players.end(); ++i) + { + if(i->first != who) + { + Player *plr = objmgr.GetPlayer(i->first); + if(plr) + plr->GetSession()->SendPacket(data); + } + } +} + +void Channel::SendToOne(WorldPacket *data, uint64 who) +{ + Player *plr = objmgr.GetPlayer(who); + if(plr) + plr->GetSession()->SendPacket(data); +} + +void Channel::Voice(uint64 guid1, uint64 guid2) +{ + +} + +void Channel::DeVoice(uint64 guid1, uint64 guid2) +{ + +} + +// done +void Channel::MakeNotifyPacket(WorldPacket *data, uint8 notify_type) +{ + data->Initialize(SMSG_CHANNEL_NOTIFY, 1+m_name.size()+1); + *data << uint8(notify_type); + *data << m_name; +} + +// done 0x00 +void Channel::MakeJoined(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_JOINED_NOTICE); + *data << uint64(guid); +} + +// done 0x01 +void Channel::MakeLeft(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_LEFT_NOTICE); + *data << uint64(guid); +} + +// done 0x02 +void Channel::MakeYouJoined(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_YOU_JOINED_NOTICE); + *data << uint8(GetFlags()); + *data << uint32(GetChannelId()); + *data << uint32(0); +} + +// done 0x03 +void Channel::MakeYouLeft(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_YOU_LEFT_NOTICE); + *data << uint32(GetChannelId()); + *data << uint8(0); // can be 0x00 and 0x01 +} + +// done 0x04 +void Channel::MakeWrongPassword(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_WRONG_PASSWORD_NOTICE); +} + +// done 0x05 +void Channel::MakeNotMember(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_NOT_MEMBER_NOTICE); +} + +// done 0x06 +void Channel::MakeNotModerator(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_NOT_MODERATOR_NOTICE); +} + +// done 0x07 +void Channel::MakePasswordChanged(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_PASSWORD_CHANGED_NOTICE); + *data << uint64(guid); +} + +// done 0x08 +void Channel::MakeOwnerChanged(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_OWNER_CHANGED_NOTICE); + *data << uint64(guid); +} + +// done 0x09 +void Channel::MakePlayerNotFound(WorldPacket *data, std::string name) +{ + MakeNotifyPacket(data, CHAT_PLAYER_NOT_FOUND_NOTICE); + *data << name; +} + +// done 0x0A +void Channel::MakeNotOwner(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_NOT_OWNER_NOTICE); +} + +// done 0x0B +void Channel::MakeChannelOwner(WorldPacket *data) +{ + std::string name = ""; + + if(!objmgr.GetPlayerNameByGUID(m_ownerGUID, name) || name.empty()) + name = "PLAYER_NOT_FOUND"; + + MakeNotifyPacket(data, CHAT_CHANNEL_OWNER_NOTICE); + *data << ((IsConstant() || !m_ownerGUID) ? "Nobody" : name); +} + +// done 0x0C +void Channel::MakeModeChange(WorldPacket *data, uint64 guid, uint8 oldflags) +{ + MakeNotifyPacket(data, CHAT_MODE_CHANGE_NOTICE); + *data << uint64(guid); + *data << uint8(oldflags); + *data << uint8(GetPlayerFlags(guid)); +} + +// done 0x0D +void Channel::MakeAnnouncementsOn(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_ANNOUNCEMENTS_ON_NOTICE); + *data << uint64(guid); +} + +// done 0x0E +void Channel::MakeAnnouncementsOff(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_ANNOUNCEMENTS_OFF_NOTICE); + *data << uint64(guid); +} + +// done 0x0F +void Channel::MakeModerationOn(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_MODERATION_ON_NOTICE); + *data << uint64(guid); +} + +// done 0x10 +void Channel::MakeModerationOff(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_MODERATION_OFF_NOTICE); + *data << uint64(guid); +} + +// done 0x11 +void Channel::MakeMuted(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_MUTED_NOTICE); +} + +// done 0x12 +void Channel::MakePlayerKicked(WorldPacket *data, uint64 bad, uint64 good) +{ + MakeNotifyPacket(data, CHAT_PLAYER_KICKED_NOTICE); + *data << uint64(bad); + *data << uint64(good); +} + +// done 0x13 +void Channel::MakeBanned(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_BANNED_NOTICE); +} + +// done 0x14 +void Channel::MakePlayerBanned(WorldPacket *data, uint64 bad, uint64 good) +{ + MakeNotifyPacket(data, CHAT_PLAYER_BANNED_NOTICE); + *data << uint64(bad); + *data << uint64(good); +} + +// done 0x15 +void Channel::MakePlayerUnbanned(WorldPacket *data, uint64 bad, uint64 good) +{ + MakeNotifyPacket(data, CHAT_PLAYER_UNBANNED_NOTICE); + *data << uint64(bad); + *data << uint64(good); +} + +// done 0x16 +void Channel::MakePlayerNotBanned(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_PLAYER_NOT_BANNED_NOTICE); + *data << uint64(guid); +} + +// done 0x17 +void Channel::MakePlayerAlreadyMember(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_PLAYER_ALREADY_MEMBER_NOTICE); + *data << uint64(guid); +} + +// done 0x18 +void Channel::MakeInvite(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_INVITE_NOTICE); + *data << uint64(guid); +} + +// done 0x19 +void Channel::MakeInviteWrongFaction(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_INVITE_WRONG_FACTION_NOTICE); +} + +// done 0x1A +void Channel::MakeWrongFaction(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_WRONG_FACTION_NOTICE); +} + +// done 0x1B +void Channel::MakeInvalidName(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_INVALID_NAME_NOTICE); +} + +// done 0x1C +void Channel::MakeNotModerated(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_NOT_MODERATED_NOTICE); +} + +// done 0x1D +void Channel::MakePlayerInvited(WorldPacket *data, uint64 guid) +{ + std::string name; + + if(!objmgr.GetPlayerNameByGUID(guid, name) || name.empty()) + return; // player name not found + + MakeNotifyPacket(data, CHAT_PLAYER_INVITED_NOTICE); + *data << name; +} + +// done 0x1E +void Channel::MakePlayerInviteBanned(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_PLAYER_INVITE_BANNED_NOTICE); + *data << uint64(guid); +} + +// done 0x1F +void Channel::MakeThrottled(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_THROTTLED_NOTICE); +} + +// done 0x20 +void Channel::MakeNotInArea(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_NOT_IN_AREA_NOTICE); +} + +// done 0x21 +void Channel::MakeNotInLfg(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_NOT_IN_LFG_NOTICE); +} + +// done 0x22 +void Channel::MakeVoiceOn(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_VOICE_ON_NOTICE); + *data << uint64(guid); +} + +// done 0x23 +void Channel::MakeVoiceOff(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_VOICE_OFF_NOTICE); + *data << uint64(guid); +} + +void Channel::JoinNotify(uint64 guid) +{ + WorldPacket data; + + if(IsConstant()) + data.Initialize(SMSG_USERLIST_ADD, 8+1+1+4+GetName().size()+1); + else + data.Initialize(SMSG_USERLIST_UPDATE, 8+1+1+4+GetName().size()+1); + + data << uint64(guid); + data << uint8(GetPlayerFlags(guid)); + data << uint8(GetFlags()); + data << uint32(GetNumPlayers()); + data << GetName(); + SendToAll(&data); +} + +void Channel::LeaveNotify(uint64 guid) +{ + WorldPacket data(SMSG_USERLIST_REMOVE, 8+1+4+GetName().size()+1); + data << uint64(guid); + data << uint8(GetFlags()); + data << uint32(GetNumPlayers()); + data << GetName(); + SendToAll(&data); +} diff --git a/src/game/Channel.h b/src/game/Channel.h new file mode 100644 index 00000000000..342992411b6 --- /dev/null +++ b/src/game/Channel.h @@ -0,0 +1,291 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _CHANNEL_H +#define _CHANNEL_H + +#include "Common.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Opcodes.h" +#include "Player.h" + +#include +#include +#include + +class Channel +{ + enum ChatNotify + { + CHAT_JOINED_NOTICE = 0x00, //+ "%s joined channel."; + CHAT_LEFT_NOTICE = 0x01, //+ "%s left channel."; + //CHAT_SUSPENDED_NOTICE = 0x01, // "%s left channel."; + CHAT_YOU_JOINED_NOTICE = 0x02, //+ "Joined Channel: [%s]"; -- You joined + //CHAT_YOU_CHANGED_NOTICE = 0x02, // "Changed Channel: [%s]"; + CHAT_YOU_LEFT_NOTICE = 0x03, //+ "Left Channel: [%s]"; -- You left + CHAT_WRONG_PASSWORD_NOTICE = 0x04, //+ "Wrong password for %s."; + CHAT_NOT_MEMBER_NOTICE = 0x05, //+ "Not on channel %s."; + CHAT_NOT_MODERATOR_NOTICE = 0x06, //+ "Not a moderator of %s."; + CHAT_PASSWORD_CHANGED_NOTICE = 0x07, //+ "[%s] Password changed by %s."; + CHAT_OWNER_CHANGED_NOTICE = 0x08, //+ "[%s] Owner changed to %s."; + CHAT_PLAYER_NOT_FOUND_NOTICE = 0x09, //+ "[%s] Player %s was not found."; + CHAT_NOT_OWNER_NOTICE = 0x0A, //+ "[%s] You are not the channel owner."; + CHAT_CHANNEL_OWNER_NOTICE = 0x0B, //+ "[%s] Channel owner is %s."; + CHAT_MODE_CHANGE_NOTICE = 0x0C, //? + CHAT_ANNOUNCEMENTS_ON_NOTICE = 0x0D, //+ "[%s] Channel announcements enabled by %s."; + CHAT_ANNOUNCEMENTS_OFF_NOTICE = 0x0E, //+ "[%s] Channel announcements disabled by %s."; + CHAT_MODERATION_ON_NOTICE = 0x0F, //+ "[%s] Channel moderation enabled by %s."; + CHAT_MODERATION_OFF_NOTICE = 0x10, //+ "[%s] Channel moderation disabled by %s."; + CHAT_MUTED_NOTICE = 0x11, //+ "[%s] You do not have permission to speak."; + CHAT_PLAYER_KICKED_NOTICE = 0x12, //? "[%s] Player %s kicked by %s."; + CHAT_BANNED_NOTICE = 0x13, //+ "[%s] You are banned from that channel."; + CHAT_PLAYER_BANNED_NOTICE = 0x14, //? "[%s] Player %s banned by %s."; + CHAT_PLAYER_UNBANNED_NOTICE = 0x15, //? "[%s] Player %s unbanned by %s."; + CHAT_PLAYER_NOT_BANNED_NOTICE = 0x16, //+ "[%s] Player %s is not banned."; + CHAT_PLAYER_ALREADY_MEMBER_NOTICE = 0x17, //+ "[%s] Player %s is already on the channel."; + CHAT_INVITE_NOTICE = 0x18, //+ "%2$s has invited you to join the channel '%1$s'."; + CHAT_INVITE_WRONG_FACTION_NOTICE = 0x19, //+ "Target is in the wrong alliance for %s."; + CHAT_WRONG_FACTION_NOTICE = 0x1A, //+ "Wrong alliance for %s."; + CHAT_INVALID_NAME_NOTICE = 0x1B, //+ "Invalid channel name"; + CHAT_NOT_MODERATED_NOTICE = 0x1C, //+ "%s is not moderated"; + CHAT_PLAYER_INVITED_NOTICE = 0x1D, //+ "[%s] You invited %s to join the channel"; + CHAT_PLAYER_INVITE_BANNED_NOTICE = 0x1E, //+ "[%s] %s has been banned."; + CHAT_THROTTLED_NOTICE = 0x1F, //+ "[%s] The number of messages that can be sent to this channel is limited, please wait to send another message."; + CHAT_NOT_IN_AREA_NOTICE = 0x20, //+ "[%s] You are not in the correct area for this channel."; -- The user is trying to send a chat to a zone specific channel, and they're not physically in that zone. + CHAT_NOT_IN_LFG_NOTICE = 0x21, //+ "[%s] You must be queued in looking for group before joining this channel."; -- The user must be in the looking for group system to join LFG chat channels. + CHAT_VOICE_ON_NOTICE = 0x22, //+ "[%s] Channel voice enabled by %s."; + CHAT_VOICE_OFF_NOTICE = 0x23, //+ "[%s] Channel voice disabled by %s."; + }; + + enum ChannelFlags + { + CHANNEL_FLAG_NONE = 0x00, + CHANNEL_FLAG_CUSTOM = 0x01, + // 0x02 + CHANNEL_FLAG_TRADE = 0x04, + CHANNEL_FLAG_NOT_LFG = 0x08, + CHANNEL_FLAG_GENERAL = 0x10, + CHANNEL_FLAG_CITY = 0x20, + CHANNEL_FLAG_LFG = 0x40, + CHANNEL_FLAG_VOICE = 0x80 + // General 0x18 = 0x10 | 0x08 + // Trade 0x3C = 0x20 | 0x10 | 0x08 | 0x04 + // LocalDefence 0x18 = 0x10 | 0x08 + // GuildRecruitment 0x38 = 0x20 | 0x10 | 0x08 + // LookingForGroup 0x50 = 0x40 | 0x10 + }; + + enum ChannelDBCFlags + { + CHANNEL_DBC_FLAG_NONE = 0x00000, + CHANNEL_DBC_FLAG_INITIAL = 0x00001, // General, Trade, LocalDefense, LFG + CHANNEL_DBC_FLAG_ZONE_DEP = 0x00002, // General, Trade, LocalDefense, GuildRecruitment + CHANNEL_DBC_FLAG_GLOBAL = 0x00004, // WorldDefense + CHANNEL_DBC_FLAG_TRADE = 0x00008, // Trade + CHANNEL_DBC_FLAG_CITY_ONLY = 0x00010, // Trade, GuildRecruitment + CHANNEL_DBC_FLAG_CITY_ONLY2 = 0x00020, // Trade, GuildRecruitment + CHANNEL_DBC_FLAG_DEFENSE = 0x10000, // LocalDefense, WorldDefense + CHANNEL_DBC_FLAG_GUILD_REQ = 0x20000, // GuildRecruitment + CHANNEL_DBC_FLAG_LFG = 0x40000 // LookingForGroup + }; + + enum ChannelMemberFlags + { + MEMBER_FLAG_NONE = 0x00, + MEMBER_FLAG_OWNER = 0x01, + MEMBER_FLAG_MODERATOR = 0x02, + MEMBER_FLAG_VOICED = 0x04, + MEMBER_FLAG_MUTED = 0x08, + MEMBER_FLAG_CUSTOM = 0x10, + MEMBER_FLAG_MIC_MUTED = 0x20, + // 0x40 + // 0x80 + }; + + struct PlayerInfo + { + uint64 player; + uint8 flags; + + bool HasFlag(uint8 flag) { return flags & flag; } + void SetFlag(uint8 flag) { if(!HasFlag(flag)) flags |= flag; } + bool IsOwner() { return flags & MEMBER_FLAG_OWNER; } + void SetOwner(bool state) + { + if(state) flags |= MEMBER_FLAG_OWNER; + else flags &= ~MEMBER_FLAG_OWNER; + } + bool IsModerator() { return flags & MEMBER_FLAG_MODERATOR; } + void SetModerator(bool state) + { + if(state) flags |= MEMBER_FLAG_MODERATOR; + else flags &= ~MEMBER_FLAG_MODERATOR; + } + bool IsMuted() { return flags & MEMBER_FLAG_MUTED; } + void SetMuted(bool state) + { + if(state) flags |= MEMBER_FLAG_MUTED; + else flags &= ~MEMBER_FLAG_MUTED; + } + }; + + typedef std::map PlayerList; + PlayerList players; + typedef std::list BannedList; + BannedList banned; + bool m_announce; + bool m_moderate; + std::string m_name; + std::string m_password; + uint8 m_flags; + uint32 m_channelId; + uint64 m_ownerGUID; + + private: + // initial packet data (notify type and channel name) + void MakeNotifyPacket(WorldPacket *data, uint8 notify_type); + // type specific packet data + void MakeJoined(WorldPacket *data, uint64 guid); //+ 0x00 + void MakeLeft(WorldPacket *data, uint64 guid); //+ 0x01 + void MakeYouJoined(WorldPacket *data); //+ 0x02 + void MakeYouLeft(WorldPacket *data); //+ 0x03 + void MakeWrongPassword(WorldPacket *data); //? 0x04 + void MakeNotMember(WorldPacket *data); //? 0x05 + void MakeNotModerator(WorldPacket *data); //? 0x06 + void MakePasswordChanged(WorldPacket *data, uint64 guid); //+ 0x07 + void MakeOwnerChanged(WorldPacket *data, uint64 guid); //? 0x08 + void MakePlayerNotFound(WorldPacket *data, std::string name); //+ 0x09 + void MakeNotOwner(WorldPacket *data); //? 0x0A + void MakeChannelOwner(WorldPacket *data); //? 0x0B + void MakeModeChange(WorldPacket *data, uint64 guid, uint8 oldflags); //+ 0x0C + void MakeAnnouncementsOn(WorldPacket *data, uint64 guid); //+ 0x0D + void MakeAnnouncementsOff(WorldPacket *data, uint64 guid); //+ 0x0E + void MakeModerationOn(WorldPacket *data, uint64 guid); //+ 0x0F + void MakeModerationOff(WorldPacket *data, uint64 guid); //+ 0x10 + void MakeMuted(WorldPacket *data); //? 0x11 + void MakePlayerKicked(WorldPacket *data, uint64 bad, uint64 good); //? 0x12 + void MakeBanned(WorldPacket *data); //? 0x13 + void MakePlayerBanned(WorldPacket *data, uint64 bad, uint64 good); //? 0x14 + void MakePlayerUnbanned(WorldPacket *data, uint64 bad, uint64 good); //? 0x15 + void MakePlayerNotBanned(WorldPacket *data, uint64 guid); //? 0x16 + void MakePlayerAlreadyMember(WorldPacket *data, uint64 guid); //+ 0x17 + void MakeInvite(WorldPacket *data, uint64 guid); //? 0x18 + void MakeInviteWrongFaction(WorldPacket *data); //? 0x19 + void MakeWrongFaction(WorldPacket *data); //? 0x1A + void MakeInvalidName(WorldPacket *data); //? 0x1B + void MakeNotModerated(WorldPacket *data); //? 0x1C + void MakePlayerInvited(WorldPacket *data, uint64 guid); //+ 0x1D + void MakePlayerInviteBanned(WorldPacket *data, uint64 guid); //? 0x1E + void MakeThrottled(WorldPacket *data); //? 0x1F + void MakeNotInArea(WorldPacket *data); //? 0x20 + void MakeNotInLfg(WorldPacket *data); //? 0x21 + void MakeVoiceOn(WorldPacket *data, uint64 guid); //+ 0x22 + void MakeVoiceOff(WorldPacket *data, uint64 guid); //+ 0x23 + + void SendToAll(WorldPacket *data, uint64 p = 0); + void SendToAllButOne(WorldPacket *data, uint64 who); + void SendToOne(WorldPacket *data, uint64 who); + + bool IsOn(uint64 who) const { return players.count(who) > 0; } + + bool IsBanned(const uint64 guid) const + { + for(BannedList::const_iterator i = banned.begin(); i != banned.end(); ++i) + if(*i == guid) + return true; + return false; + } + + bool IsFirst() const { return !(players.size() > 1); } + + uint8 GetPlayerFlags(uint64 p) const + { + PlayerList::const_iterator p_itr = players.find(p); + if(p_itr == players.end()) + return 0; + + return p_itr->second.flags; + } + + void SetModerator(uint64 p, bool set) + { + if(players[p].IsModerator() != set) + { + uint8 oldFlag = GetPlayerFlags(p); + players[p].SetModerator(set); + + WorldPacket data; + MakeModeChange(&data, p, oldFlag); + SendToAll(&data); + } + } + + void SetMute(uint64 p, bool set) + { + if(players[p].IsMuted() != set) + { + uint8 oldFlag = GetPlayerFlags(p); + players[p].SetMuted(set); + + WorldPacket data; + MakeModeChange(&data, p, oldFlag); + SendToAll(&data); + } + } + + public: + Channel(std::string name, uint32 channel_id); + std::string GetName() const { return m_name; } + uint32 GetChannelId() const { return m_channelId; } + bool IsConstant() const { return m_channelId != 0; } + bool IsAnnounce() const { return m_announce; } + bool IsLFG() const { return GetFlags() & CHANNEL_FLAG_LFG; } + std::string GetPassword() const { return m_password; } + void SetPassword(std::string npassword) { m_password = npassword; } + void SetAnnounce(bool nannounce) { m_announce = nannounce; } + uint32 GetNumPlayers() const { return players.size(); } + uint8 GetFlags() const { return m_flags; } + bool HasFlag(uint8 flag) { return m_flags & flag; } + + void Join(uint64 p, const char *pass); + void Leave(uint64 p, bool send = true); + void KickOrBan(uint64 good, const char *badname, bool ban); + void Kick(uint64 good, const char *badname) { KickOrBan(good, badname, false); } + void Ban(uint64 good, const char *badname) { KickOrBan(good, badname, true); } + void UnBan(uint64 good, const char *badname); + void Password(uint64 p, const char *pass); + void SetMode(uint64 p, const char *p2n, bool mod, bool set); + void SetOwner(uint64 p, bool exclaim = true); + void SetOwner(uint64 p, const char *newname); + void SendWhoOwner(uint64 p); + void SetModerator(uint64 p, const char *newname) { SetMode(p, newname, true, true); } + void UnsetModerator(uint64 p, const char *newname) { SetMode(p, newname, true, false); } + void SetMute(uint64 p, const char *newname) { SetMode(p, newname, false, true); } + void UnsetMute(uint64 p, const char *newname) { SetMode(p, newname, false, false); } + void List(Player* p); + void Announce(uint64 p); + void Moderate(uint64 p); + void Say(uint64 p, const char *what, uint32 lang); + void Invite(uint64 p, const char *newp); + void Voice(uint64 guid1, uint64 guid2); + void DeVoice(uint64 guid1, uint64 guid2); + void JoinNotify(uint64 guid); // invisible notify + void LeaveNotify(uint64 guid); // invisible notify +}; +#endif diff --git a/src/game/ChannelHandler.cpp b/src/game/ChannelHandler.cpp new file mode 100644 index 00000000000..4c8bdd1c516 --- /dev/null +++ b/src/game/ChannelHandler.cpp @@ -0,0 +1,387 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ObjectMgr.h" // for normalizePlayerName +#include "ChannelMgr.h" +#include "Policies/SingletonImp.h" + +INSTANTIATE_SINGLETON_1( AllianceChannelMgr ); +INSTANTIATE_SINGLETON_1( HordeChannelMgr ); + +void WorldSession::HandleChannelJoin(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + CHECK_PACKET_SIZE(recvPacket, 4+1+1+1); + + uint32 channel_id; + uint8 unknown1, unknown2; + std::string channelname, pass; + + recvPacket >> channel_id >> unknown1 >> unknown2; + recvPacket >> channelname; + + if(channelname.empty()) + return; + + // recheck + CHECK_PACKET_SIZE(recvPacket, 4+1+1+(channelname.size()+1)+1); + + recvPacket >> pass; + if(ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if(Channel *chn = cMgr->GetJoinChannel(channelname, channel_id)) + chn->Join(_player->GetGUID(), pass.c_str()); +} + +void WorldSession::HandleChannelLeave(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + CHECK_PACKET_SIZE(recvPacket, 4+1); + + uint32 unk; + std::string channelname; + recvPacket >> unk; // channel id? + recvPacket >> channelname; + + if(channelname.empty()) + return; + + if(ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + { + if(Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->Leave(_player->GetGUID(), true); + cMgr->LeftChannel(channelname); + } +} + +void WorldSession::HandleChannelList(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + CHECK_PACKET_SIZE(recvPacket, 1); + + std::string channelname; + recvPacket >> channelname; + + if(ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if(Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->List(_player); +} + +void WorldSession::HandleChannelPassword(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + CHECK_PACKET_SIZE(recvPacket, 1+1); + + std::string channelname, pass; + recvPacket >> channelname; + + // recheck + CHECK_PACKET_SIZE(recvPacket, (channelname.size()+1)+1); + + recvPacket >> pass; + + if(ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if(Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->Password(_player->GetGUID(), pass.c_str()); +} + +void WorldSession::HandleChannelSetOwner(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + CHECK_PACKET_SIZE(recvPacket, 1+1); + + std::string channelname, newp; + recvPacket >> channelname; + + // recheck + CHECK_PACKET_SIZE(recvPacket, (channelname.size()+1)+1); + + recvPacket >> newp; + + if(!normalizePlayerName(newp)) + return; + + if(ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if(Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->SetOwner(_player->GetGUID(), newp.c_str()); +} + +void WorldSession::HandleChannelOwner(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + CHECK_PACKET_SIZE(recvPacket, 1); + + std::string channelname; + recvPacket >> channelname; + if(ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if(Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->SendWhoOwner(_player->GetGUID()); +} + +void WorldSession::HandleChannelModerator(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + CHECK_PACKET_SIZE(recvPacket, 1+1); + + std::string channelname, otp; + recvPacket >> channelname; + + // recheck + CHECK_PACKET_SIZE(recvPacket, (channelname.size()+1)+1); + + recvPacket >> otp; + + if(!normalizePlayerName(otp)) + return; + + if(ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if(Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->SetModerator(_player->GetGUID(), otp.c_str()); +} + +void WorldSession::HandleChannelUnmoderator(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + CHECK_PACKET_SIZE(recvPacket, 1+1); + + std::string channelname, otp; + recvPacket >> channelname; + + // recheck + CHECK_PACKET_SIZE(recvPacket, (channelname.size()+1)+1); + + recvPacket >> otp; + + if(!normalizePlayerName(otp)) + return; + + if(ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if(Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->UnsetModerator(_player->GetGUID(), otp.c_str()); +} + +void WorldSession::HandleChannelMute(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + CHECK_PACKET_SIZE(recvPacket, 1+1); + + std::string channelname, otp; + recvPacket >> channelname; + + // recheck + CHECK_PACKET_SIZE(recvPacket, (channelname.size()+1)+1); + + recvPacket >> otp; + + if(!normalizePlayerName(otp)) + return; + + if(ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if(Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->SetMute(_player->GetGUID(), otp.c_str()); +} + +void WorldSession::HandleChannelUnmute(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + CHECK_PACKET_SIZE(recvPacket, 1+1); + + std::string channelname, otp; + recvPacket >> channelname; + + // recheck + CHECK_PACKET_SIZE(recvPacket, (channelname.size()+1)+1); + + recvPacket >> otp; + + if(!normalizePlayerName(otp)) + return; + + if(ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if(Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->UnsetMute(_player->GetGUID(), otp.c_str()); +} + +void WorldSession::HandleChannelInvite(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + CHECK_PACKET_SIZE(recvPacket, 1+1); + + std::string channelname, otp; + recvPacket >> channelname; + + // recheck + CHECK_PACKET_SIZE(recvPacket, (channelname.size()+1)+1); + + recvPacket >> otp; + + if(!normalizePlayerName(otp)) + return; + + if(ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if(Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->Invite(_player->GetGUID(), otp.c_str()); +} + +void WorldSession::HandleChannelKick(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + CHECK_PACKET_SIZE(recvPacket, 1+1); + + std::string channelname, otp; + recvPacket >> channelname; + + // recheck + CHECK_PACKET_SIZE(recvPacket, (channelname.size()+1)+1); + + recvPacket >> otp; + if(!normalizePlayerName(otp)) + return; + + if(ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if(Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->Kick(_player->GetGUID(), otp.c_str()); +} + +void WorldSession::HandleChannelBan(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + CHECK_PACKET_SIZE(recvPacket, 1+1); + + std::string channelname, otp; + recvPacket >> channelname; + + // recheck + CHECK_PACKET_SIZE(recvPacket, (channelname.size()+1)+1); + + recvPacket >> otp; + + if(!normalizePlayerName(otp)) + return; + + if(ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if(Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->Ban(_player->GetGUID(), otp.c_str()); +} + +void WorldSession::HandleChannelUnban(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + CHECK_PACKET_SIZE(recvPacket, 1+1); + + std::string channelname, otp; + recvPacket >> channelname; + + // recheck + CHECK_PACKET_SIZE(recvPacket, (channelname.size()+1)+1); + + recvPacket >> otp; + + if(!normalizePlayerName(otp)) + return; + + if(ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if(Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->UnBan(_player->GetGUID(), otp.c_str()); +} + +void WorldSession::HandleChannelAnnounce(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + CHECK_PACKET_SIZE(recvPacket, 1); + + std::string channelname; + recvPacket >> channelname; + if(ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if(Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->Announce(_player->GetGUID()); +} + +void WorldSession::HandleChannelModerate(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + CHECK_PACKET_SIZE(recvPacket, 1); + + std::string channelname; + recvPacket >> channelname; + if(ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if(Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->Moderate(_player->GetGUID()); +} + +void WorldSession::HandleChannelRosterQuery(WorldPacket &recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + CHECK_PACKET_SIZE(recvPacket, 1); + + std::string channelname; + recvPacket >> channelname; + if(ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if(Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->List(_player); +} + +void WorldSession::HandleChannelInfoQuery(WorldPacket &recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + CHECK_PACKET_SIZE(recvPacket, 1); + + std::string channelname; + recvPacket >> channelname; + if(ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + { + if(Channel *chn = cMgr->GetChannel(channelname, _player)) + { + WorldPacket data(SMSG_CHANNEL_MEMBER_COUNT, chn->GetName().size()+1+1+4); + data << chn->GetName(); + data << uint8(chn->GetFlags()); + data << uint32(chn->GetNumPlayers()); + SendPacket(&data); + } + } +} + +void WorldSession::HandleChannelJoinNotify(WorldPacket &recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + CHECK_PACKET_SIZE(recvPacket, 1); + + std::string channelname; + recvPacket >> channelname; + /*if(ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if(Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->JoinNotify(_player->GetGUID());*/ +} diff --git a/src/game/ChannelMgr.h b/src/game/ChannelMgr.h new file mode 100644 index 00000000000..eb15f08a39e --- /dev/null +++ b/src/game/ChannelMgr.h @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef MANGOSSERVER_CHANNELMGR_H +#define MANGOSSERVER_CHANNELMGR_H + +#include "Channel.h" +#include "Policies/Singleton.h" +#include "World.h" + +#include +#include + +class ChannelMgr +{ + public: + typedef std::map ChannelMap; + ChannelMgr() {} + ~ChannelMgr() + { + for(ChannelMap::iterator itr = channels.begin();itr!=channels.end(); ++itr) + delete itr->second; + channels.clear(); + } + Channel *GetJoinChannel(std::string name, uint32 channel_id) + { + if(channels.count(name) == 0) + { + Channel *nchan = new Channel(name,channel_id); + channels[name] = nchan; + } + return channels[name]; + } + Channel *GetChannel(std::string name, Player *p) + { + ChannelMap::const_iterator i = channels.find(name); + + if(i == channels.end()) + { + WorldPacket data; + MakeNotOnPacket(&data,name); + p->GetSession()->SendPacket(&data); + return NULL; + } + else + return i->second; + } + void LeftChannel(std::string name) + { + ChannelMap::const_iterator i = channels.find(name); + + if(i == channels.end()) + return; + + Channel* channel = i->second; + + if(channel->GetNumPlayers() == 0 && !channel->IsConstant()) + { + channels.erase(name); + delete channel; + } + } + private: + ChannelMap channels; + void MakeNotOnPacket(WorldPacket *data, std::string name) + { + data->Initialize(SMSG_CHANNEL_NOTIFY, (1+10)); // we guess size + (*data) << (uint8)0x05 << name; + } +}; + +class AllianceChannelMgr : public ChannelMgr {}; +class HordeChannelMgr : public ChannelMgr {}; + +inline ChannelMgr* channelMgr(uint32 team) +{ + if (sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL)) + //For Test,No Seprate Faction + return &MaNGOS::Singleton::Instance(); + + if(team==ALLIANCE) + return &MaNGOS::Singleton::Instance(); + if(team==HORDE) + return &MaNGOS::Singleton::Instance(); + return NULL; +} +#endif diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp new file mode 100644 index 00000000000..f63af7d7f81 --- /dev/null +++ b/src/game/CharacterHandler.cpp @@ -0,0 +1,1065 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "WorldPacket.h" +#include "WorldSocket.h" +#include "WorldSession.h" +#include "Opcodes.h" +#include "Log.h" +#include "World.h" +#include "ObjectMgr.h" +#include "Player.h" +#include "Guild.h" +#include "UpdateMask.h" +#include "Auth/md5.h" +#include "MapManager.h" +#include "ObjectAccessor.h" +#include "Group.h" +#include "Database/DatabaseImpl.h" +#include "PlayerDump.h" +#include "SocialMgr.h" +#include "Util.h" + +class LoginQueryHolder : public SqlQueryHolder +{ + private: + uint32 m_accountId; + uint64 m_guid; + public: + LoginQueryHolder(uint32 accountId, uint64 guid) + : m_accountId(accountId), m_guid(guid) { } + uint64 GetGuid() const { return m_guid; } + uint32 GetAccountId() const { return m_accountId; } + bool Initialize(); +}; + +bool LoginQueryHolder::Initialize() +{ + SetSize(MAX_PLAYER_LOGIN_QUERY); + + bool res = true; + + // NOTE: all fields in `characters` must be read to prevent lost character data at next save in case wrong DB structure. + // !!! NOTE: including unused `zone`,`online` + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADFROM, "SELECT guid, account, data, name, race, class, position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, gmstate, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeon_difficulty FROM characters WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADGROUP, "SELECT leaderGuid FROM group_member WHERE memberGuid ='%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADBOUNDINSTANCES, "SELECT id, permanent, map, difficulty, resettime FROM character_instance LEFT JOIN instance ON instance = id WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADAURAS, "SELECT caster_guid,spell,effect_index,amount,maxduration,remaintime,remaincharges FROM character_aura WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADSPELLS, "SELECT spell,slot,active,disabled FROM character_spell WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADQUESTSTATUS, "SELECT quest,status,rewarded,explored,timer,mobcount1,mobcount2,mobcount3,mobcount4,itemcount1,itemcount2,itemcount3,itemcount4 FROM character_queststatus WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADDAILYQUESTSTATUS,"SELECT quest,time FROM character_queststatus_daily WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADTUTORIALS, "SELECT tut0,tut1,tut2,tut3,tut4,tut5,tut6,tut7 FROM character_tutorial WHERE account = '%u' AND realmid = '%u'", GetAccountId(), realmID); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADREPUTATION, "SELECT faction,standing,flags FROM character_reputation WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADINVENTORY, "SELECT data,bag,slot,item,item_template FROM character_inventory JOIN item_instance ON character_inventory.item = item_instance.guid WHERE character_inventory.guid = '%u' ORDER BY bag,slot", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADACTIONS, "SELECT button,action,type,misc FROM character_action WHERE guid = '%u' ORDER BY button", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADMAILCOUNT, "SELECT COUNT(id) FROM mail WHERE receiver = '%u' AND (checked & 1)=0 AND deliver_time <= '" I64FMTD "'", GUID_LOPART(m_guid),(uint64)time(NULL)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADMAILDATE, "SELECT MIN(deliver_time) FROM mail WHERE receiver = '%u' AND (checked & 1)=0", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADSOCIALLIST, "SELECT friend,flags,note FROM character_social WHERE guid = '%u' LIMIT 255", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADHOMEBIND, "SELECT map,zone,position_x,position_y,position_z FROM character_homebind WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADSPELLCOOLDOWNS, "SELECT spell,item,time FROM character_spell_cooldown WHERE guid = '%u'", GUID_LOPART(m_guid)); + if(sWorld.getConfig(CONFIG_DECLINED_NAMES_USED)) + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES, "SELECT genitive, dative, accusative, instrumental, prepositional FROM character_declinedname WHERE guid = '%u'",GUID_LOPART(m_guid)); + // in other case still be dummy query + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADGUILD, "SELECT guildid,rank FROM guild_member WHERE guid = '%u'", GUID_LOPART(m_guid)); + + return res; +} + +// don't call WorldSession directly +// it may get deleted before the query callbacks get executed +// instead pass an account id to this handler +class CharacterHandler +{ + public: + void HandleCharEnumCallback(QueryResult * result, uint32 account) + { + WorldSession * session = sWorld.FindSession(account); + if(!session) + { + delete result; + return; + } + session->HandleCharEnum(result); + } + void HandlePlayerLoginCallback(QueryResult * /*dummy*/, SqlQueryHolder * holder) + { + if (!holder) return; + WorldSession *session = sWorld.FindSession(((LoginQueryHolder*)holder)->GetAccountId()); + if(!session) + { + delete holder; + return; + } + session->HandlePlayerLogin((LoginQueryHolder*)holder); + } +} chrHandler; + +void WorldSession::HandleCharEnum(QueryResult * result) +{ + // keys can be non cleared if player open realm list and close it by 'cancel' + loginDatabase.PExecute("UPDATE account SET v = '0', s = '0' WHERE id = '%u'", GetAccountId()); + + WorldPacket data(SMSG_CHAR_ENUM, 100); // we guess size + + uint8 num = 0; + + data << num; + + if( result ) + { + Player *plr = new Player(this); + do + { + sLog.outDetail("Loading char guid %u from account %u.",(*result)[0].GetUInt32(),GetAccountId()); + + if(plr->MinimalLoadFromDB( result, (*result)[0].GetUInt32() )) + { + plr->BuildEnumData( result, &data ); + ++num; + } + } + while( result->NextRow() ); + + delete plr; + delete result; + } + + data.put(0, num); + + SendPacket( &data ); +} + +void WorldSession::HandleCharEnumOpcode( WorldPacket & /*recv_data*/ ) +{ + /// get all the data necessary for loading all characters (along with their pets) on the account + CharacterDatabase.AsyncPQuery(&chrHandler, &CharacterHandler::HandleCharEnumCallback, GetAccountId(), + !sWorld.getConfig(CONFIG_DECLINED_NAMES_USED) ? + // ------- Query Without Declined Names -------- + // 0 1 2 3 4 5 6 7 8 + "SELECT characters.data, characters.name, characters.position_x, characters.position_y, characters.position_z, characters.map, characters.totaltime, characters.leveltime, characters.at_login, " + // 9 10 11 + "character_pet.entry, character_pet.modelid, character_pet.level " + "FROM characters LEFT JOIN character_pet ON characters.guid=character_pet.owner AND character_pet.slot='0' " + "WHERE characters.account = '%u' ORDER BY characters.guid" + : + // --------- Query With Declined Names --------- + // 0 1 2 3 4 5 6 7 8 + "SELECT characters.data, characters.name, characters.position_x, characters.position_y, characters.position_z, characters.map, characters.totaltime, characters.leveltime, characters.at_login, " + // 9 10 11 12 + "character_pet.entry, character_pet.modelid, character_pet.level, genitive " + "FROM characters LEFT JOIN character_pet ON characters.guid = character_pet.owner AND character_pet.slot='0' " + "LEFT JOIN character_declinedname ON characters.guid = character_declinedname.guid " + "WHERE characters.account = '%u' ORDER BY characters.guid", + GetAccountId()); +} + +void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,1+1+1+1+1+1+1+1+1+1); + + std::string name; + uint8 race_,class_; + bool pTbc = this->IsTBC() && sWorld.getConfig(CONFIG_EXPANSION) > 0; + recv_data >> name; + + // recheck with known string size + CHECK_PACKET_SIZE(recv_data,(name.size()+1)+1+1+1+1+1+1+1+1+1); + + recv_data >> race_; + recv_data >> class_; + + WorldPacket data(SMSG_CHAR_CREATE, 1); // returned with diff.values in all cases + + if(GetSecurity() == SEC_PLAYER) + { + if(uint32 mask = sWorld.getConfig(CONFIG_CHARACTERS_CREATING_DISABLED)) + { + bool disabled = false; + + uint32 team = Player::TeamForRace(race_); + switch(team) + { + case ALLIANCE: disabled = mask & (1<<0); break; + case HORDE: disabled = mask & (1<<1); break; + } + + if(disabled) + { + data << (uint8)CHAR_CREATE_DISABLED; + SendPacket( &data ); + return; + } + } + } + + if (!sChrClassesStore.LookupEntry(class_)|| + !sChrRacesStore.LookupEntry(race_)) + { + data << (uint8)CHAR_CREATE_FAILED; + SendPacket( &data ); + sLog.outError("Class: %u or Race %u not found in DBC (Wrong DBC files?) or Cheater?", class_, race_); + return; + } + + // prevent character creating Expansion race without Expansion account + if (!pTbc&&(race_>RACE_TROLL)) + { + data << (uint8)CHAR_CREATE_EXPANSION; + sLog.outError("No Expansion Account:[%d] but tried to Create TBC character",GetAccountId()); + SendPacket( &data ); + return; + } + + // prevent character creating with invalid name + if(!normalizePlayerName(name)) + { + data << (uint8)CHAR_NAME_INVALID_CHARACTER; + SendPacket( &data ); + sLog.outError("Account:[%d] but tried to Create character with empty [name] ",GetAccountId()); + return; + } + + // check name limitations + if(!ObjectMgr::IsValidName(name,true)) + { + data << (uint8)CHAR_NAME_INVALID_CHARACTER; + SendPacket( &data ); + return; + } + + if(GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(name)) + { + data << (uint8)CHAR_NAME_RESERVED; + SendPacket( &data ); + return; + } + + if(objmgr.GetPlayerGUIDByName(name)) + { + data << (uint8)CHAR_CREATE_NAME_IN_USE; + SendPacket( &data ); + return; + } + + QueryResult *resultacct = loginDatabase.PQuery("SELECT SUM(numchars) FROM realmcharacters WHERE acctid = '%d'", GetAccountId()); + if ( resultacct ) + { + Field *fields=resultacct->Fetch(); + uint32 acctcharcount = fields[0].GetUInt32(); + delete resultacct; + + if (acctcharcount >= sWorld.getConfig(CONFIG_CHARACTERS_PER_ACCOUNT)) + { + data << (uint8)CHAR_CREATE_ACCOUNT_LIMIT; + SendPacket( &data ); + return; + } + } + + QueryResult *result = CharacterDatabase.PQuery("SELECT COUNT(guid) FROM characters WHERE account = '%d'", GetAccountId()); + uint8 charcount = 0; + if ( result ) + { + Field *fields=result->Fetch(); + charcount = fields[0].GetUInt8(); + delete result; + + if (charcount >= sWorld.getConfig(CONFIG_CHARACTERS_PER_REALM)) + { + data << (uint8)CHAR_CREATE_SERVER_LIMIT; + SendPacket( &data ); + return; + } + } + + bool AllowTwoSideAccounts = !sWorld.IsPvPRealm() || sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_ACCOUNTS) || GetSecurity() > SEC_PLAYER; + uint32 skipCinematics = sWorld.getConfig(CONFIG_SKIP_CINEMATICS); + + bool have_same_race = false; + if(!AllowTwoSideAccounts || skipCinematics == 1) + { + QueryResult *result2 = CharacterDatabase.PQuery("SELECT DISTINCT race FROM characters WHERE account = '%u' %s", GetAccountId(),skipCinematics == 1 ? "" : "LIMIT 1"); + if(result2) + { + uint32 team_= Player::TeamForRace(race_); + + Field* field = result2->Fetch(); + uint8 race = field[0].GetUInt32(); + + // need to check team only for first character + // TODO: what to if account already has characters of both races? + if (!AllowTwoSideAccounts) + { + uint32 team=0; + if(race > 0) + team = Player::TeamForRace(race); + + if(team != team_) + { + data << (uint8)CHAR_CREATE_PVP_TEAMS_VIOLATION; + SendPacket( &data ); + delete result2; + return; + } + } + + if (skipCinematics == 1) + { + // TODO: check if cinematic already shown? (already logged in?; cinematic field) + while (race_ != race && result2->NextRow()) + { + field = result2->Fetch(); + race = field[0].GetUInt32(); + } + have_same_race = race_ == race; + } + delete result2; + } + } + + // extract other data required for player creating + uint8 gender, skin, face, hairStyle, hairColor, facialHair, outfitId; + recv_data >> gender >> skin >> face; + recv_data >> hairStyle >> hairColor >> facialHair >> outfitId; + + Player * pNewChar = new Player(this); + if(!pNewChar->Create( objmgr.GenerateLowGuid(HIGHGUID_PLAYER), name, race_, class_, gender, skin, face, hairStyle, hairColor, facialHair, outfitId )) + { + // Player not create (race/class problem?) + delete pNewChar; + + data << (uint8)CHAR_CREATE_ERROR; + SendPacket( &data ); + + return; + } + + if(have_same_race && skipCinematics == 1 || skipCinematics == 2) + pNewChar->setCinematic(1); // not show intro + + // Player created, save it now + pNewChar->SaveToDB(); + charcount+=1; + + loginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid= '%d' AND realmid = '%d'", GetAccountId(), realmID); + loginDatabase.PExecute("INSERT INTO realmcharacters (numchars, acctid, realmid) VALUES (%u, %u, %u)", charcount, GetAccountId(), realmID); + + delete pNewChar; // created only to call SaveToDB() + + data << (uint8)CHAR_CREATE_SUCCESS; + SendPacket( &data ); + + std::string IP_str = _socket ? _socket->GetRemoteAddress().c_str() : "-"; + sLog.outBasic("Account: %d (IP: %s) Create Character:[%s]",GetAccountId(),IP_str.c_str(),name.c_str()); + sLog.outChar("Account: %d (IP: %s) Create Character:[%s]",GetAccountId(),IP_str.c_str(),name.c_str()); +} + +void WorldSession::HandleCharDeleteOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8); + + uint64 guid; + recv_data >> guid; + + // can't delete loaded character + if(objmgr.GetPlayer(guid)) + return; + + uint32 accountId = 0; + std::string name; + + // is guild leader + if(objmgr.GetGuildByLeader(guid)) + { + WorldPacket data(SMSG_CHAR_DELETE, 1); + data << (uint8)CHAR_DELETE_FAILED_GUILD_LEADER; + SendPacket( &data ); + return; + } + + // is arena team captain + if(objmgr.GetArenaTeamByCapitan(guid)) + { + WorldPacket data(SMSG_CHAR_DELETE, 1); + data << (uint8)CHAR_DELETE_FAILED_ARENA_CAPTAIN; + SendPacket( &data ); + return; + } + + QueryResult *result = CharacterDatabase.PQuery("SELECT account,name FROM characters WHERE guid='%u'", GUID_LOPART(guid)); + if(result) + { + Field *fields = result->Fetch(); + accountId = fields[0].GetUInt32(); + name = fields[1].GetCppString(); + delete result; + } + + // prevent deleting other players' characters using cheating tools + if(accountId != GetAccountId()) + return; + + std::string IP_str = _socket ? _socket->GetRemoteAddress().c_str() : "-"; + sLog.outBasic("Account: %d (IP: %s) Delete Character:[%s] (guid:%u)",GetAccountId(),IP_str.c_str(),name.c_str(),GUID_LOPART(guid)); + sLog.outChar("Account: %d (IP: %s) Delete Character:[%s] (guid: %u)",GetAccountId(),IP_str.c_str(),name.c_str(),GUID_LOPART(guid)); + + if(sLog.IsOutCharDump()) // optimize GetPlayerDump call + { + std::string dump = PlayerDumpWriter().GetDump(GUID_LOPART(guid)); + sLog.outCharDump(dump.c_str(),GetAccountId(),GUID_LOPART(guid),name.c_str()); + } + + Player::DeleteFromDB(guid, GetAccountId()); + + WorldPacket data(SMSG_CHAR_DELETE, 1); + data << (uint8)CHAR_DELETE_SUCCESS; + SendPacket( &data ); +} + +void WorldSession::HandlePlayerLoginOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8); + + m_playerLoading = true; + uint64 playerGuid = 0; + + DEBUG_LOG( "WORLD: Recvd Player Logon Message" ); + + recv_data >> playerGuid; + + LoginQueryHolder *holder = new LoginQueryHolder(GetAccountId(), playerGuid); + if(!holder->Initialize()) + { + delete holder; // delete all unprocessed queries + m_playerLoading = false; + return; + } + + CharacterDatabase.DelayQueryHolder(&chrHandler, &CharacterHandler::HandlePlayerLoginCallback, holder); +} + +void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder) +{ + uint64 playerGuid = holder->GetGuid(); + + Player* pCurrChar = new Player(this); + pCurrChar->GetMotionMaster()->Initialize(); + + // "GetAccountId()==db stored account id" checked in LoadFromDB (prevent login not own character using cheating tools) + if(!pCurrChar->LoadFromDB(GUID_LOPART(playerGuid), holder)) + { + KickPlayer(); // disconnect client, player no set to session and it will not deleted or saved at kick + delete pCurrChar; // delete it manually + delete holder; // delete all unprocessed queries + m_playerLoading = false; + return; + } + + SetPlayer(pCurrChar); + + pCurrChar->SendDungeonDifficulty(false); + + WorldPacket data( SMSG_LOGIN_VERIFY_WORLD, 20 ); + data << pCurrChar->GetMapId(); + data << pCurrChar->GetPositionX(); + data << pCurrChar->GetPositionY(); + data << pCurrChar->GetPositionZ(); + data << pCurrChar->GetOrientation(); + SendPacket(&data); + + data.Initialize( SMSG_ACCOUNT_DATA_TIMES, 128 ); + for(int i = 0; i < 32; i++) + data << uint32(0); + SendPacket(&data); + + data.Initialize(SMSG_FEATURE_SYSTEM_STATUS, 2); // added in 2.2.0 + data << uint8(2); // unknown value + data << uint8(0); // enable(1)/disable(0) voice chat interface in client + SendPacket(&data); + + // Send MOTD + { + data.Initialize(SMSG_MOTD, 50); // new in 2.0.1 + data << (uint32)0; + + uint32 linecount=0; + std::string str_motd = sWorld.GetMotd(); + std::string::size_type pos, nextpos; + + pos = 0; + while ( (nextpos= str_motd.find('@',pos)) != std::string::npos ) + { + if (nextpos != pos) + { + data << str_motd.substr(pos,nextpos-pos); + ++linecount; + } + pos = nextpos+1; + } + + if (posGetGuildId() != 0) + { + Guild* guild = objmgr.GetGuildById(pCurrChar->GetGuildId()); + if(guild) + { + data.Initialize(SMSG_GUILD_EVENT, (2+guild->GetMOTD().size()+1)); + data << (uint8)GE_MOTD; + data << (uint8)1; + data << guild->GetMOTD(); + SendPacket(&data); + DEBUG_LOG( "WORLD: Sent guild-motd (SMSG_GUILD_EVENT)" ); + + data.Initialize(SMSG_GUILD_EVENT, (5+10)); // we guess size + data<<(uint8)GE_SIGNED_ON; + data<<(uint8)1; + data<GetName(); + data<GetGUID(); + guild->BroadcastPacket(&data); + DEBUG_LOG( "WORLD: Sent guild-signed-on (SMSG_GUILD_EVENT)" ); + + // Increment online members of the guild + guild->IncOnlineMemberCount(); + } + else + { + // remove wrong guild data + sLog.outError("Player %s (GUID: %u) marked as member not existed guild (id: %u), removing guild membership for player.",pCurrChar->GetName(),pCurrChar->GetGUIDLow(),pCurrChar->GetGuildId()); + pCurrChar->SetUInt32Value(PLAYER_GUILDID,0); + pCurrChar->SetUInt32ValueInDB(PLAYER_GUILDID,0,pCurrChar->GetGUID()); + } + } + + if(!pCurrChar->isAlive()) + pCurrChar->SendCorpseReclaimDelay(true); + + pCurrChar->SendInitialPacketsBeforeAddToMap(); + + //Show cinematic at the first time that player login + if( !pCurrChar->getCinematic() ) + { + pCurrChar->setCinematic(1); + + ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(pCurrChar->getRace()); + if(rEntry) + { + data.Initialize( SMSG_TRIGGER_CINEMATIC,4 ); + data << uint32(rEntry->startmovie); + SendPacket( &data ); + } + } + + //QueryResult *result = CharacterDatabase.PQuery("SELECT guildid,rank FROM guild_member WHERE guid = '%u'",pCurrChar->GetGUIDLow()); + QueryResult *resultGuild = holder->GetResult(PLAYER_LOGIN_QUERY_LOADGUILD); + + if(resultGuild) + { + Field *fields = resultGuild->Fetch(); + pCurrChar->SetInGuild(fields[0].GetUInt32()); + pCurrChar->SetRank(fields[1].GetUInt32()); + delete resultGuild; + } + else if(pCurrChar->GetGuildId()) // clear guild related fields in case wrong data about non existed membership + { + pCurrChar->SetInGuild(0); + pCurrChar->SetRank(0); + } + + if (!MapManager::Instance().GetMap(pCurrChar->GetMapId(), pCurrChar)->Add(pCurrChar)) + { + AreaTrigger const* at = objmgr.GetGoBackTrigger(pCurrChar->GetMapId()); + if(at) + pCurrChar->TeleportTo(at->target_mapId, at->target_X, at->target_Y, at->target_Z, pCurrChar->GetOrientation()); + else + pCurrChar->TeleportTo(pCurrChar->m_homebindMapId, pCurrChar->m_homebindX, pCurrChar->m_homebindY, pCurrChar->m_homebindZ, pCurrChar->GetOrientation()); + } + + ObjectAccessor::Instance().AddObject(pCurrChar); + //sLog.outDebug("Player %s added to Map.",pCurrChar->GetName()); + pCurrChar->GetSocial()->SendSocialList(); + + pCurrChar->SendInitialPacketsAfterAddToMap(); + + CharacterDatabase.PExecute("UPDATE characters SET online = 1 WHERE guid = '%u'", pCurrChar->GetGUIDLow()); + loginDatabase.PExecute("UPDATE account SET online = 1 WHERE id = '%u'", GetAccountId()); + pCurrChar->SetInGameTime( getMSTime() ); + + // announce group about member online (must be after add to player list to receive announce to self) + if(Group *group = pCurrChar->GetGroup()) + { + //pCurrChar->groupInfo.group->SendInit(this); // useless + group->SendUpdate(); + } + + // friend status + sSocialMgr.SendFriendStatus(pCurrChar, FRIEND_ONLINE, pCurrChar->GetGUIDLow(), "", true); + + // Place character in world (and load zone) before some object loading + pCurrChar->LoadCorpse(); + + // setting Ghost+speed if dead + //if ( pCurrChar->m_deathState == DEAD ) + if (pCurrChar->m_deathState != ALIVE) + { + // not blizz like, we must correctly save and load player instead... + if(pCurrChar->getRace() == RACE_NIGHTELF) + pCurrChar->CastSpell(pCurrChar, 20584, true, 0);// auras SPELL_AURA_INCREASE_SPEED(+speed in wisp form), SPELL_AURA_INCREASE_SWIM_SPEED(+swim speed in wisp form), SPELL_AURA_TRANSFORM (to wisp form) + pCurrChar->CastSpell(pCurrChar, 8326, true, 0); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?) + + //pCurrChar->SetUInt32Value(UNIT_FIELD_AURA+41, 8326); + //pCurrChar->SetUInt32Value(UNIT_FIELD_AURA+42, 20584); + //pCurrChar->SetUInt32Value(UNIT_FIELD_AURAFLAGS+6, 238); + //pCurrChar->SetUInt32Value(UNIT_FIELD_AURALEVELS+11, 514); + //pCurrChar->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS+11, 65535); + //pCurrChar->SetUInt32Value(UNIT_FIELD_DISPLAYID, 1825); + //if (pCurrChar->getRace() == RACE_NIGHTELF) + //{ + // pCurrChar->SetSpeed(MOVE_RUN, 1.5f*1.2f, true); + // pCurrChar->SetSpeed(MOVE_SWIM, 1.5f*1.2f, true); + //} + //else + //{ + // pCurrChar->SetSpeed(MOVE_RUN, 1.5f, true); + // pCurrChar->SetSpeed(MOVE_SWIM, 1.5f, true); + //} + pCurrChar->SetMovement(MOVE_WATER_WALK); + } + + if(uint32 sourceNode = pCurrChar->m_taxi.GetTaxiSource()) + { + + sLog.outDebug( "WORLD: Restart character %u taxi flight", pCurrChar->GetGUIDLow() ); + + uint32 MountId = objmgr.GetTaxiMount(sourceNode, pCurrChar->GetTeam()); + uint32 path = pCurrChar->m_taxi.GetCurrentTaxiPath(); + + // search appropriate start path node + uint32 startNode = 0; + + TaxiPathNodeList const& nodeList = sTaxiPathNodesByPath[path]; + + float distPrev = MAP_SIZE*MAP_SIZE; + float distNext = + (nodeList[0].x-pCurrChar->GetPositionX())*(nodeList[0].x-pCurrChar->GetPositionX())+ + (nodeList[0].y-pCurrChar->GetPositionY())*(nodeList[0].y-pCurrChar->GetPositionY())+ + (nodeList[0].z-pCurrChar->GetPositionZ())*(nodeList[0].z-pCurrChar->GetPositionZ()); + + for(uint32 i = 1; i < nodeList.size(); ++i) + { + TaxiPathNode const& node = nodeList[i]; + TaxiPathNode const& prevNode = nodeList[i-1]; + + // skip nodes at another map + if(node.mapid != pCurrChar->GetMapId()) + continue; + + distPrev = distNext; + + distNext = + (node.x-pCurrChar->GetPositionX())*(node.x-pCurrChar->GetPositionX())+ + (node.y-pCurrChar->GetPositionY())*(node.y-pCurrChar->GetPositionY())+ + (node.z-pCurrChar->GetPositionZ())*(node.z-pCurrChar->GetPositionZ()); + + float distNodes = + (node.x-prevNode.x)*(node.x-prevNode.x)+ + (node.y-prevNode.y)*(node.y-prevNode.y)+ + (node.z-prevNode.z)*(node.z-prevNode.z); + + if(distNext + distPrev < distNodes) + { + startNode = i; + break; + } + } + + SendDoFlight( MountId, path, startNode ); + } + + // Load pet if any and player is alive and not in taxi flight + if(pCurrChar->isAlive() && pCurrChar->m_taxi.GetTaxiSource()==0) + pCurrChar->LoadPet(); + + // Set FFA PvP for non GM in non-rest mode + if(sWorld.IsFFAPvPRealm() && !pCurrChar->isGameMaster() && !pCurrChar->HasFlag(PLAYER_FLAGS,PLAYER_FLAGS_RESTING) ) + pCurrChar->SetFlag(PLAYER_FLAGS,PLAYER_FLAGS_FFA_PVP); + + if(pCurrChar->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP)) + pCurrChar->SetContestedPvP(); + + // Apply at_login requests + if(pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_SPELLS)) + { + pCurrChar->resetSpells(); + SendNotification("Spells has been reset."); + } + + if(pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_TALENTS)) + { + pCurrChar->resetTalents(true); + SendNotification("Talents has been reset."); + } + + // show time before shutdown if shutdown planned. + if(sWorld.IsShutdowning()) + sWorld.ShutdownMsg(true,pCurrChar); + + if(pCurrChar->isGameMaster()) + SendNotification("GM mode is ON"); + + std::string IP_str = _socket ? _socket->GetRemoteAddress().c_str() : "-"; + sLog.outChar("Account: %d (IP: %s) Login Character:[%s] (guid:%u)",GetAccountId(),IP_str.c_str(),pCurrChar->GetName() ,pCurrChar->GetGUID()); + + m_playerLoading = false; + delete holder; +} + +void WorldSession::HandleSetFactionAtWar( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,4+1); + + DEBUG_LOG( "WORLD: Received CMSG_SET_FACTION_ATWAR" ); + + uint32 repListID; + uint8 flag; + + recv_data >> repListID; + recv_data >> flag; + + FactionStateList::iterator itr = GetPlayer()->m_factions.find(repListID); + if (itr == GetPlayer()->m_factions.end()) + return; + + // always invisible or hidden faction can't change war state + if(itr->second.Flags & (FACTION_FLAG_INVISIBLE_FORCED|FACTION_FLAG_HIDDEN) ) + return; + + GetPlayer()->SetFactionAtWar(&itr->second,flag); +} + +//I think this function is never used :/ I dunno, but i guess this opcode not exists +void WorldSession::HandleSetFactionCheat( WorldPacket & /*recv_data*/ ) +{ + //CHECK_PACKET_SIZE(recv_data,4+4); + + //sLog.outDebug("WORLD SESSION: HandleSetFactionCheat"); + /* + uint32 FactionID; + uint32 Standing; + + recv_data >> FactionID; + recv_data >> Standing; + + std::list::iterator itr; + + for(itr = GetPlayer()->factions.begin(); itr != GetPlayer()->factions.end(); ++itr) + { + if(itr->ReputationListID == FactionID) + { + itr->Standing += Standing; + itr->Flags = (itr->Flags | 1); + break; + } + } + */ + GetPlayer()->UpdateReputation(); +} + +void WorldSession::HandleMeetingStoneInfo( WorldPacket & /*recv_data*/ ) +{ + DEBUG_LOG( "WORLD: Received CMSG_MEETING_STONE_INFO" ); + + WorldPacket data(SMSG_MEETINGSTONE_SETQUEUE, 5); + data << uint32(0) << uint8(6); + SendPacket(&data); +} + +void WorldSession::HandleTutorialFlag( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,4); + + uint32 iFlag; + recv_data >> iFlag; + + uint32 wInt = (iFlag / 32); + if (wInt >= 8) + { + //sLog.outError("CHEATER? Account:[%d] Guid[%u] tried to send wrong CMSG_TUTORIAL_FLAG", GetAccountId(),GetGUID()); + return; + } + uint32 rInt = (iFlag % 32); + + uint32 tutflag = GetPlayer()->GetTutorialInt( wInt ); + tutflag |= (1 << rInt); + GetPlayer()->SetTutorialInt( wInt, tutflag ); + + //sLog.outDebug("Received Tutorial Flag Set {%u}.", iFlag); +} + +void WorldSession::HandleTutorialClear( WorldPacket & /*recv_data*/ ) +{ + for ( uint32 iI = 0; iI < 8; iI++) + GetPlayer()->SetTutorialInt( iI, 0xFFFFFFFF ); +} + +void WorldSession::HandleTutorialReset( WorldPacket & /*recv_data*/ ) +{ + for ( uint32 iI = 0; iI < 8; iI++) + GetPlayer()->SetTutorialInt( iI, 0x00000000 ); +} + +void WorldSession::HandleSetWatchedFactionIndexOpcode(WorldPacket & recv_data) +{ + CHECK_PACKET_SIZE(recv_data,4); + + DEBUG_LOG("WORLD: Received CMSG_SET_WATCHED_FACTION"); + uint32 fact; + recv_data >> fact; + GetPlayer()->SetUInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, fact); +} + +void WorldSession::HandleSetWatchedFactionInactiveOpcode(WorldPacket & recv_data) +{ + CHECK_PACKET_SIZE(recv_data,4+1); + + DEBUG_LOG("WORLD: Received CMSG_SET_FACTION_INACTIVE"); + uint32 replistid; + uint8 inactive; + recv_data >> replistid >> inactive; + + FactionStateList::iterator itr = _player->m_factions.find(replistid); + if (itr == _player->m_factions.end()) + return; + + _player->SetFactionInactive(&itr->second, inactive); +} + +void WorldSession::HandleToggleHelmOpcode( WorldPacket & /*recv_data*/ ) +{ + DEBUG_LOG("CMSG_TOGGLE_HELM for %s", _player->GetName()); + _player->ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_HELM); +} + +void WorldSession::HandleToggleCloakOpcode( WorldPacket & /*recv_data*/ ) +{ + DEBUG_LOG("CMSG_TOGGLE_CLOAK for %s", _player->GetName()); + _player->ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_CLOAK); +} + +void WorldSession::HandleChangePlayerNameOpcode(WorldPacket& recv_data) +{ + CHECK_PACKET_SIZE(recv_data,8+1); + + uint64 guid; + std::string newname; + std::string oldname; + + CHECK_PACKET_SIZE(recv_data, 8+1); + + recv_data >> guid; + recv_data >> newname; + + QueryResult *result = CharacterDatabase.PQuery("SELECT at_login FROM characters WHERE guid ='%u'", GUID_LOPART(guid)); + if (result) + { + uint32 at_loginFlags; + Field *fields = result->Fetch(); + at_loginFlags = fields[0].GetUInt32(); + delete result; + + if (!(at_loginFlags & AT_LOGIN_RENAME)) + { + WorldPacket data(SMSG_CHAR_RENAME, 1); + data << (uint8)CHAR_CREATE_ERROR; + SendPacket( &data ); + return; + } + } + else + { + WorldPacket data(SMSG_CHAR_RENAME, 1); + data << (uint8)CHAR_CREATE_ERROR; + SendPacket( &data ); + return; + } + + if(!objmgr.GetPlayerNameByGUID(guid, oldname)) // character not exist, because we have no name for this guid + { + WorldPacket data(SMSG_CHAR_RENAME, 1); + data << (uint8)CHAR_LOGIN_NO_CHARACTER; + SendPacket( &data ); + return; + } + + // prevent character rename to invalid name + if(!normalizePlayerName(newname)) + { + WorldPacket data(SMSG_CHAR_RENAME, 1); + data << (uint8)CHAR_NAME_NO_NAME; + SendPacket( &data ); + return; + } + + if(!ObjectMgr::IsValidName(newname,true)) + { + WorldPacket data(SMSG_CHAR_RENAME, 1); + data << (uint8)CHAR_NAME_INVALID_CHARACTER; + SendPacket( &data ); + return; + } + + // check name limitations + if(GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(newname)) + { + WorldPacket data(SMSG_CHAR_RENAME, 1); + data << (uint8)CHAR_NAME_RESERVED; + SendPacket( &data ); + return; + } + + if(objmgr.GetPlayerGUIDByName(newname)) // character with this name already exist + { + WorldPacket data(SMSG_CHAR_RENAME, 1); + data << (uint8)CHAR_CREATE_ERROR; + SendPacket( &data ); + return; + } + + if(newname == oldname) // checked by client + { + WorldPacket data(SMSG_CHAR_RENAME, 1); + data << (uint8)CHAR_NAME_FAILURE; + SendPacket( &data ); + return; + } + + // we have to check character at_login_flag & AT_LOGIN_RENAME also (fake packets hehe) + + CharacterDatabase.escape_string(newname); + CharacterDatabase.PExecute("UPDATE characters set name = '%s', at_login = at_login & ~ %u WHERE guid ='%u'", newname.c_str(), uint32(AT_LOGIN_RENAME),GUID_LOPART(guid)); + CharacterDatabase.PExecute("DELETE FROM character_declinedname WHERE guid ='%u'", GUID_LOPART(guid)); + + std::string IP_str = _socket ? _socket->GetRemoteAddress().c_str() : "-"; + sLog.outChar("Account: %d (IP: %s) Character:[%s] (guid:%u) Changed name to: %s",GetAccountId(),IP_str.c_str(),oldname.c_str(),GUID_LOPART(guid),newname.c_str()); + + WorldPacket data(SMSG_CHAR_RENAME,1+8+(newname.size()+1)); + data << (uint8)RESPONSE_SUCCESS; + data << guid; + data << newname; + SendPacket(&data); +} + +void WorldSession::HandleDeclinedPlayerNameOpcode(WorldPacket& recv_data) +{ + uint64 guid; + + CHECK_PACKET_SIZE(recv_data, 8+6); + recv_data >> guid; + + // not accept declined names for unsupported languages + std::string name; + if(!objmgr.GetPlayerNameByGUID(guid,name)) + { + WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT,4+8); + data << (uint32)1; + data << guid; + SendPacket(&data); + return; + } + + std::wstring wname; + if(!Utf8toWStr(name,wname)) + { + WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT,4+8); + data << (uint32)1; + data << guid; + SendPacket(&data); + return; + } + + if(!isCyrillicCharacter(wname[0])) // name already stored as only single alphabet using + { + WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT,4+8); + data << (uint32)1; + data << guid; + SendPacket(&data); + return; + } + + std::string name2; + DeclinedName declinedname; + + recv_data >> name2; + + if(name2!=name) // character have different name + { + WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT,4+8); + data << (uint32)1; + data << guid; + SendPacket(&data); + return; + } + + for(int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) + { + recv_data >> declinedname.name[i]; + if(!normalizePlayerName(declinedname.name[i])) + { + WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT,4+8); + data << (uint32)1; + data << guid; + SendPacket(&data); + return; + } + } + + if(!ObjectMgr::CheckDeclinedNames(GetMainPartOfName(wname,0),declinedname)) + { + WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT,4+8); + data << (uint32)1; + data << guid; + SendPacket(&data); + return; + } + + for(int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) + CharacterDatabase.escape_string(declinedname.name[i]); + + CharacterDatabase.BeginTransaction(); + CharacterDatabase.PExecute("DELETE FROM character_declinedname WHERE guid = '%u'", GUID_LOPART(guid)); + CharacterDatabase.PExecute("INSERT INTO character_declinedname (guid, genitive, dative, accusative, instrumental, prepositional) VALUES ('%u','%s','%s','%s','%s','%s')", + GUID_LOPART(guid), declinedname.name[0].c_str(),declinedname.name[1].c_str(),declinedname.name[2].c_str(),declinedname.name[3].c_str(),declinedname.name[4].c_str()); + CharacterDatabase.CommitTransaction(); + + WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT,4+8); + data << (uint32)0; // OK + data << guid; + SendPacket(&data); +} diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp new file mode 100644 index 00000000000..9635542cf4f --- /dev/null +++ b/src/game/Chat.cpp @@ -0,0 +1,1103 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Language.h" +#include "Database/DatabaseEnv.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Opcodes.h" +#include "Log.h" +#include "World.h" +#include "ObjectMgr.h" +#include "Player.h" +#include "UpdateMask.h" +#include "Chat.h" +#include "MapManager.h" +#include "GridNotifiersImpl.h" +#include "CellImpl.h" + +bool ChatHandler::load_command_table = true; + +LanguageDesc lang_description[LANGUAGES_COUNT] = +{ + { LANG_ADDON, 0, 0 }, + { LANG_UNIVERSAL, 0, 0 }, + { LANG_ORCISH, 669, SKILL_LANG_ORCISH }, + { LANG_DARNASSIAN, 671, SKILL_LANG_DARNASSIAN }, + { LANG_TAURAHE, 670, SKILL_LANG_TAURAHE }, + { LANG_DWARVISH, 672, SKILL_LANG_DWARVEN }, + { LANG_COMMON, 668, SKILL_LANG_COMMON }, + { LANG_DEMONIC, 815, SKILL_LANG_DEMON_TONGUE }, + { LANG_TITAN, 816, SKILL_LANG_TITAN }, + { LANG_THALASSIAN, 813, SKILL_LANG_THALASSIAN }, + { LANG_DRACONIC, 814, SKILL_LANG_DRACONIC }, + { LANG_KALIMAG, 817, SKILL_LANG_OLD_TONGUE }, + { LANG_GNOMISH, 7340, SKILL_LANG_GNOMISH }, + { LANG_TROLL, 7341, SKILL_LANG_TROLL }, + { LANG_GUTTERSPEAK, 17737, SKILL_LANG_GUTTERSPEAK }, + { LANG_DRAENEI, 29932, SKILL_LANG_DRAENEI }, + { LANG_ZOMBIE, 0, 0 }, + { LANG_GNOMISH_BINARY, 0, 0 }, + { LANG_GOBLIN_BINARY, 0, 0 } +}; + +LanguageDesc const* GetLanguageDescByID(uint32 lang) +{ + for(int i = 0; i < LANGUAGES_COUNT; ++i) + { + if(uint32(lang_description[i].lang_id) == lang) + return &lang_description[i]; + } + + return NULL; +} + +LanguageDesc const* GetLanguageDescBySpell(uint32 spell_id) +{ + for(int i = 0; i < LANGUAGES_COUNT; ++i) + { + if(lang_description[i].spell_id == spell_id) + return &lang_description[i]; + } + + return NULL; +} + +LanguageDesc const* GetLanguageDescBySkill(uint32 skill_id) +{ + for(int i = 0; i < LANGUAGES_COUNT; ++i) + { + if(lang_description[i].skill_id == skill_id) + return &lang_description[i]; + } + + return NULL; +} + +ChatCommand * ChatHandler::getCommandTable() +{ + static ChatCommand serverCommandTable[] = + { + { "idlerestart", SEC_ADMINISTRATOR, &ChatHandler::HandleIdleRestartCommand, "", NULL }, + { "idleshutdown", SEC_ADMINISTRATOR, &ChatHandler::HandleIdleShutDownCommand, "", NULL }, + { "info", SEC_PLAYER, &ChatHandler::HandleInfoCommand, "", NULL }, + { "restart", SEC_ADMINISTRATOR, &ChatHandler::HandleRestartCommand, "", NULL }, + { "shutdown", SEC_ADMINISTRATOR, &ChatHandler::HandleShutDownCommand, "", NULL }, + { NULL, 0, NULL, "", NULL } + }; + + static ChatCommand modifyCommandTable[] = + { + { "hp", SEC_MODERATOR, &ChatHandler::HandleModifyHPCommand, "", NULL }, + { "mana", SEC_MODERATOR, &ChatHandler::HandleModifyManaCommand, "", NULL }, + { "rage", SEC_MODERATOR, &ChatHandler::HandleModifyRageCommand, "", NULL }, + { "energy", SEC_MODERATOR, &ChatHandler::HandleModifyEnergyCommand, "", NULL }, + { "money", SEC_MODERATOR, &ChatHandler::HandleModifyMoneyCommand, "", NULL }, + { "speed", SEC_MODERATOR, &ChatHandler::HandleModifySpeedCommand, "", NULL }, + { "swim", SEC_MODERATOR, &ChatHandler::HandleModifySwimCommand, "", NULL }, + { "scale", SEC_MODERATOR, &ChatHandler::HandleModifyScaleCommand, "", NULL }, + { "bit", SEC_MODERATOR, &ChatHandler::HandleModifyBitCommand, "", NULL }, + { "bwalk", SEC_MODERATOR, &ChatHandler::HandleModifyBWalkCommand, "", NULL }, + { "fly", SEC_MODERATOR, &ChatHandler::HandleModifyFlyCommand, "", NULL }, + { "aspeed", SEC_MODERATOR, &ChatHandler::HandleModifyASpeedCommand, "", NULL }, + { "faction", SEC_MODERATOR, &ChatHandler::HandleModifyFactionCommand, "", NULL }, + { "spell", SEC_MODERATOR, &ChatHandler::HandleModifySpellCommand, "", NULL }, + { "tp", SEC_MODERATOR, &ChatHandler::HandleModifyTalentCommand, "", NULL }, + { "titles", SEC_MODERATOR, &ChatHandler::HandleModifyKnownTitlesCommand, "", NULL }, + { "mount", SEC_MODERATOR, &ChatHandler::HandleModifyMountCommand, "", NULL }, + { "honor", SEC_MODERATOR, &ChatHandler::HandleModifyHonorCommand, "", NULL }, + { "rep", SEC_MODERATOR, &ChatHandler::HandleModifyRepCommand, "", NULL }, + { "arena", SEC_MODERATOR, &ChatHandler::HandleModifyArenaCommand, "", NULL }, + { "drunk", SEC_MODERATOR, &ChatHandler::HandleDrunkCommand, "", NULL }, + { "standstate", SEC_GAMEMASTER, &ChatHandler::HandleStandStateCommand, "", NULL }, + { "morph", SEC_GAMEMASTER, &ChatHandler::HandleMorphCommand, "", NULL }, + { NULL, 0, NULL, "", NULL } + }; + + static ChatCommand wpCommandTable[] = + { + { "show", SEC_GAMEMASTER, &ChatHandler::HandleWpShowCommand, "", NULL }, + { "add", SEC_GAMEMASTER, &ChatHandler::HandleWpAddCommand, "", NULL }, + { "modify", SEC_GAMEMASTER, &ChatHandler::HandleWpModifyCommand, "", NULL }, + { "export", SEC_ADMINISTRATOR, &ChatHandler::HandleWpExportCommand, "", NULL }, + { "import", SEC_ADMINISTRATOR, &ChatHandler::HandleWpImportCommand, "", NULL }, + { NULL, 0, NULL, "", NULL } + }; + + static ChatCommand debugCommandTable[] = + { + { "inarc", SEC_ADMINISTRATOR, &ChatHandler::HandleDebugInArcCommand, "", NULL }, + { "spellfail", SEC_ADMINISTRATOR, &ChatHandler::HandleDebugSpellFailCommand, "", NULL }, + { "setpoi", SEC_ADMINISTRATOR, &ChatHandler::HandleSetPoiCommand, "", NULL }, + { "qpartymsg", SEC_ADMINISTRATOR, &ChatHandler::HandleSendQuestPartyMsgCommand, "", NULL }, + { "qinvalidmsg", SEC_ADMINISTRATOR, &ChatHandler::HandleSendQuestInvalidMsgCommand, "", NULL }, + { "equiperr", SEC_ADMINISTRATOR, &ChatHandler::HandleEquipErrorCommand, "", NULL }, + { "sellerr", SEC_ADMINISTRATOR, &ChatHandler::HandleSellErrorCommand, "", NULL }, + { "buyerr", SEC_ADMINISTRATOR, &ChatHandler::HandleBuyErrorCommand, "", NULL }, + { "sendopcode", SEC_ADMINISTRATOR, &ChatHandler::HandleSendOpcodeCommand, "", NULL }, + { "uws", SEC_ADMINISTRATOR, &ChatHandler::HandleUpdateWorldStateCommand, "", NULL }, + { "ps", SEC_ADMINISTRATOR, &ChatHandler::HandlePlaySound2Command, "", NULL }, + { "scn", SEC_ADMINISTRATOR, &ChatHandler::HandleSendChannelNotifyCommand, "", NULL }, + { "scm", SEC_ADMINISTRATOR, &ChatHandler::HandleSendChatMsgCommand, "", NULL }, + { "getitemstate", SEC_ADMINISTRATOR, &ChatHandler::HandleGetItemState, "", NULL }, + { "playsound", SEC_MODERATOR, &ChatHandler::HandlePlaySoundCommand, "", NULL }, + { "update", SEC_ADMINISTRATOR, &ChatHandler::HandleUpdate, "", NULL }, + { "setvalue", SEC_ADMINISTRATOR, &ChatHandler::HandleSetValue, "", NULL }, + { "getvalue", SEC_ADMINISTRATOR, &ChatHandler::HandleGetValue, "", NULL }, + { "Mod32Value", SEC_ADMINISTRATOR, &ChatHandler::HandleMod32Value, "", NULL }, + { "anim", SEC_GAMEMASTER, &ChatHandler::HandleAnimCommand, "", NULL }, + { "lootrecipient", SEC_GAMEMASTER, &ChatHandler::HandleGetLootRecipient, "", NULL }, + { NULL, 0, NULL, "", NULL } + }; + + static ChatCommand eventCommandTable[] = + { + { "activelist", SEC_GAMEMASTER, &ChatHandler::HandleEventActiveListCommand, "", NULL }, + { "start", SEC_GAMEMASTER, &ChatHandler::HandleEventStartCommand, "", NULL }, + { "stop", SEC_GAMEMASTER, &ChatHandler::HandleEventStopCommand, "", NULL }, + { "", SEC_GAMEMASTER, &ChatHandler::HandleEventInfoCommand, "", NULL }, + { NULL, 0, NULL, "", NULL } + }; + + static ChatCommand learnCommandTable[] = + { + { "all", SEC_ADMINISTRATOR, &ChatHandler::HandleLearnAllCommand, "", NULL }, + { "all_gm", SEC_GAMEMASTER, &ChatHandler::HandleLearnAllGMCommand, "", NULL }, + { "all_crafts", SEC_GAMEMASTER, &ChatHandler::HandleLearnAllCraftsCommand, "", NULL }, + { "all_default", SEC_MODERATOR, &ChatHandler::HandleLearnAllDefaultCommand, "", NULL }, + { "all_lang", SEC_MODERATOR, &ChatHandler::HandleLearnAllLangCommand, "", NULL }, + { "all_myclass", SEC_ADMINISTRATOR, &ChatHandler::HandleLearnAllMyClassCommand, "", NULL }, + { "all_myspells", SEC_ADMINISTRATOR, &ChatHandler::HandleLearnAllMySpellsCommand, "", NULL }, + { "all_mytalents", SEC_ADMINISTRATOR, &ChatHandler::HandleLearnAllMyTalentsCommand, "", NULL }, + { "all_recipes", SEC_GAMEMASTER, &ChatHandler::HandleLearnAllRecipesCommand, "", NULL }, + { "", SEC_ADMINISTRATOR, &ChatHandler::HandleLearnCommand, "", NULL }, + { NULL, 0, NULL, "", NULL } + }; + + static ChatCommand reloadCommandTable[] = + { + { "all", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadAllCommand, "", NULL }, + { "all_quest", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadAllQuestCommand, "", NULL }, + { "all_loot", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadAllLootCommand, "", NULL }, + { "all_scripts", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadAllScriptsCommand, "", NULL }, + { "all_spell", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadAllSpellCommand, "", NULL }, + { "all_item", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadAllItemCommand, "", NULL }, + + { "config", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadConfigCommand, "", NULL }, + + { "areatrigger_tavern", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadAreaTriggerTavernCommand, "", NULL }, + { "areatrigger_teleport", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadAreaTriggerTeleportCommand, "", NULL }, + { "areatrigger_involvedrelation",SEC_ADMINISTRATOR, &ChatHandler::HandleReloadQuestAreaTriggersCommand, "", NULL }, + { "event_scripts", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadEventScriptsCommand, "", NULL }, + { "command", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadCommandCommand, "", NULL }, + { "creature_involvedrelation", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadCreatureQuestInvRelationsCommand,"",NULL }, + { "creature_loot_template", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadLootTemplatesCreatureCommand, "", NULL }, + { "creature_questrelation", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadCreatureQuestRelationsCommand, "", NULL }, + { "disenchant_loot_template", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadLootTemplatesDisenchantCommand, "", NULL }, + { "fishing_loot_template", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadLootTemplatesFishingCommand, "", NULL }, + { "game_graveyard_zone", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadGameGraveyardZoneCommand, "", NULL }, + { "gameobject_involvedrelation", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadGOQuestInvRelationsCommand, "", NULL }, + { "gameobject_loot_template", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadLootTemplatesGameobjectCommand, "", NULL }, + { "gameobject_questrelation", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadGOQuestRelationsCommand, "", NULL }, + { "gameobject_scripts", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadGameObjectScriptsCommand, "", NULL }, + { "item_enchantment_template", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadItemEnchantementsCommand, "", NULL }, + { "item_loot_template", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadLootTemplatesItemCommand, "", NULL }, + { "mangos_string", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadMangosStringCommand, "", NULL }, + { "page_text", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadPageTextsCommand, "", NULL }, + { "pickpocketing_loot_template", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadLootTemplatesPickpocketingCommand,"",NULL}, + { "prospecting_loot_template", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadLootTemplatesProspectingCommand,"", NULL }, + { "quest_mail_loot_template", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadLootTemplatesQuestMailCommand, "", NULL }, + { "quest_end_scripts", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadQuestEndScriptsCommand, "", NULL }, + { "quest_start_scripts", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadQuestStartScriptsCommand, "", NULL }, + { "quest_template", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadQuestTemplateCommand, "", NULL }, + { "reference_loot_template", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadLootTemplatesReferenceCommand, "", NULL }, + { "reserved_name", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadReservedNameCommand, "", NULL }, + { "skill_discovery_template", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadSkillDiscoveryTemplateCommand, "", NULL }, + { "skill_extra_item_template", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadSkillExtraItemTemplateCommand, "", NULL }, + { "skill_fishing_base_level", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadSkillFishingBaseLevelCommand, "", NULL }, + { "skinning_loot_template", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadLootTemplatesSkinningCommand, "", NULL }, + { "spell_affect", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadSpellAffectCommand, "", NULL }, + { "spell_chain", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadSpellChainCommand, "", NULL }, + { "spell_elixir", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadSpellElixirCommand, "", NULL }, + { "spell_learn_spell", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadSpellLearnSpellCommand, "", NULL }, + { "spell_pet_auras", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadSpellPetAurasCommand, "", NULL }, + { "spell_proc_event", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadSpellProcEventCommand, "", NULL }, + { "spell_script_target", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadSpellScriptTargetCommand, "", NULL }, + { "spell_scripts", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadSpellScriptsCommand, "", NULL }, + { "spell_target_position", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadSpellTargetPositionCommand, "", NULL }, + { "spell_threats", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadSpellThreatsCommand, "", NULL }, + { "", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadCommand, "", NULL }, + { NULL, 0, NULL, "", NULL } + }; + + static ChatCommand honorCommandTable[] = + { + { "add", SEC_GAMEMASTER, &ChatHandler::HandleAddHonorCommand, "", NULL }, + { "addkill", SEC_GAMEMASTER, &ChatHandler::HandleHonorAddKillCommand, "", NULL }, + { "update", SEC_GAMEMASTER, &ChatHandler::HandleUpdateHonorFieldsCommand, "", NULL }, + { NULL, 0, NULL, "", NULL } + }; + + static ChatCommand guildCommandTable[] = + { + { "create", SEC_GAMEMASTER, &ChatHandler::HandleGuildCreateCommand, "", NULL }, + { "delete", SEC_GAMEMASTER, &ChatHandler::HandleGuildDeleteCommand, "", NULL }, + { "invite", SEC_GAMEMASTER, &ChatHandler::HandleGuildInviteCommand, "", NULL }, + { "uninvite", SEC_GAMEMASTER, &ChatHandler::HandleGuildUninviteCommand, "", NULL }, + { "rank", SEC_GAMEMASTER, &ChatHandler::HandleGuildRankCommand, "", NULL }, + { NULL, 0, NULL, "", NULL } + }; + + static ChatCommand lookupCommandTable[] = + { + { "area", SEC_MODERATOR, &ChatHandler::HandleLookupAreaCommand, "", NULL }, + { "creature", SEC_ADMINISTRATOR, &ChatHandler::HandleLookupCreatureCommand, "", NULL }, + { "event", SEC_GAMEMASTER, &ChatHandler::HandleLookupEventCommand, "", NULL }, + { "faction", SEC_ADMINISTRATOR, &ChatHandler::HandleLookupFactionCommand, "", NULL }, + { "item", SEC_ADMINISTRATOR, &ChatHandler::HandleLookupItemCommand, "", NULL }, + { "itemset", SEC_ADMINISTRATOR, &ChatHandler::HandleLookupItemSetCommand, "", NULL }, + { "object", SEC_ADMINISTRATOR, &ChatHandler::HandleLookupObjectCommand, "", NULL }, + { "quest", SEC_ADMINISTRATOR, &ChatHandler::HandleLookupQuestCommand, "", NULL }, + { "skill", SEC_ADMINISTRATOR, &ChatHandler::HandleLookupSkillCommand, "", NULL }, + { "spell", SEC_ADMINISTRATOR, &ChatHandler::HandleLookupSpellCommand, "", NULL }, + { "tele", SEC_MODERATOR, &ChatHandler::HandleLookupTeleCommand, "", NULL }, + { NULL, 0, NULL, "", NULL } + }; + + static ChatCommand resetCommandTable[] = + { + { "honor", SEC_ADMINISTRATOR, &ChatHandler::HandleResetHonorCommand, "", NULL }, + { "level", SEC_ADMINISTRATOR, &ChatHandler::HandleResetLevelCommand, "", NULL }, + { "spells", SEC_ADMINISTRATOR, &ChatHandler::HandleResetSpellsCommand, "", NULL }, + { "stats", SEC_ADMINISTRATOR, &ChatHandler::HandleResetStatsCommand, "", NULL }, + { "talents", SEC_ADMINISTRATOR, &ChatHandler::HandleResetTalentsCommand, "", NULL }, + { "all", SEC_ADMINISTRATOR, &ChatHandler::HandleResetAllCommand, "", NULL }, + { NULL, 0, NULL, "", NULL } + }; + + static ChatCommand castCommandTable[] = + { + { "back", SEC_ADMINISTRATOR, &ChatHandler::HandleCastBackCommand, "", NULL }, + { "dist", SEC_ADMINISTRATOR, &ChatHandler::HandleCastDistCommand, "", NULL }, + { "self", SEC_ADMINISTRATOR, &ChatHandler::HandleCastSelfCommand, "", NULL }, + { "target", SEC_ADMINISTRATOR, &ChatHandler::HandleCastTargetCommand, "", NULL }, + { "", SEC_ADMINISTRATOR, &ChatHandler::HandleCastCommand, "", NULL }, + { NULL, 0, NULL, "", NULL } + }; + + static ChatCommand pdumpCommandTable[] = + { + { "load", SEC_ADMINISTRATOR, &ChatHandler::HandleLoadPDumpCommand, "", NULL }, + { "write", SEC_ADMINISTRATOR, &ChatHandler::HandleWritePDumpCommand, "", NULL }, + { NULL, 0, NULL, "", NULL } + }; + + static ChatCommand listCommandTable[] = + { + { "creature", SEC_ADMINISTRATOR, &ChatHandler::HandleListCreatureCommand, "", NULL }, + { "item", SEC_ADMINISTRATOR, &ChatHandler::HandleListItemCommand, "", NULL }, + { "object", SEC_ADMINISTRATOR, &ChatHandler::HandleListObjectCommand, "", NULL }, + { "auras", SEC_ADMINISTRATOR, &ChatHandler::HandleListAurasCommand, "", NULL }, + { NULL, 0, NULL, "", NULL } + }; + + static ChatCommand teleCommandTable[] = + { + { "add", SEC_ADMINISTRATOR, &ChatHandler::HandleAddTeleCommand, "", NULL }, + { "del", SEC_ADMINISTRATOR, &ChatHandler::HandleDelTeleCommand, "", NULL }, + { "name", SEC_MODERATOR, &ChatHandler::HandleNameTeleCommand, "", NULL }, + { "group", SEC_MODERATOR, &ChatHandler::HandleGroupTeleCommand, "", NULL }, + { "", SEC_MODERATOR, &ChatHandler::HandleTeleCommand, "", NULL }, + { NULL, 0, NULL, "", NULL } + }; + + static ChatCommand npcCommandTable[] = + { + { "say", SEC_MODERATOR, &ChatHandler::HandleSayCommand, "", NULL }, + { "whisper", SEC_MODERATOR, &ChatHandler::HandleNpcWhisperCommand, "", NULL }, + { "yell", SEC_MODERATOR, &ChatHandler::HandleYellCommand, "", NULL }, + { "textemote", SEC_MODERATOR, &ChatHandler::HandleTextEmoteCommand, "", NULL }, + { "add", SEC_GAMEMASTER, &ChatHandler::HandleAddSpwCommand, "", NULL }, + { "delete", SEC_GAMEMASTER, &ChatHandler::HandleDelCreatureCommand, "", NULL }, + { "spawndist", SEC_GAMEMASTER, &ChatHandler::HandleSpawnDistCommand, "", NULL }, + { "spawntime", SEC_GAMEMASTER, &ChatHandler::HandleSpawnTimeCommand, "", NULL }, + { "factionid", SEC_GAMEMASTER, &ChatHandler::HandleFactionIdCommand, "", NULL }, + { "addmove", SEC_GAMEMASTER, &ChatHandler::HandleAddMoveCommand, "", NULL }, + { "setmovetype", SEC_GAMEMASTER, &ChatHandler::HandleSetMoveTypeCommand, "", NULL }, + { "move", SEC_GAMEMASTER, &ChatHandler::HandleMoveCreatureCommand, "", NULL }, + { "changelevel", SEC_GAMEMASTER, &ChatHandler::HandleChangeLevelCommand, "", NULL }, + { "setmodel", SEC_GAMEMASTER, &ChatHandler::HandleSetModelCommand, "", NULL }, + { "additem", SEC_GAMEMASTER, &ChatHandler::HandleAddVendorItemCommand, "", NULL }, + { "delitem", SEC_GAMEMASTER, &ChatHandler::HandleDelVendorItemCommand, "", NULL }, + { "flag", SEC_GAMEMASTER, &ChatHandler::HandleNPCFlagCommand, "", NULL }, + { "changeentry", SEC_ADMINISTRATOR, &ChatHandler::HandleChangeEntryCommand, "", NULL }, + { "info", SEC_ADMINISTRATOR, &ChatHandler::HandleNpcInfoCommand, "", NULL }, + { "playemote", SEC_ADMINISTRATOR, &ChatHandler::HandlePlayEmoteCommand, "", NULL }, + + //{ TODO: fix or remove this commands + { "name", SEC_GAMEMASTER, &ChatHandler::HandleNameCommand, "", NULL }, + { "subname", SEC_GAMEMASTER, &ChatHandler::HandleSubNameCommand, "", NULL }, + { "addweapon", SEC_ADMINISTRATOR, &ChatHandler::HandleAddWeaponCommand, "", NULL }, + //} + + { NULL, 0, NULL, "", NULL } + }; + + static ChatCommand goCommandTable[] = + { + { "grid", SEC_MODERATOR, &ChatHandler::HandleGoGridCommand, "", NULL }, + { "creature", SEC_GAMEMASTER, &ChatHandler::HandleGoCreatureCommand, "", NULL }, + { "object", SEC_GAMEMASTER, &ChatHandler::HandleGoObjectCommand, "", NULL }, + { "trigger", SEC_GAMEMASTER, &ChatHandler::HandleGoTriggerCommand, "", NULL }, + { "graveyard", SEC_GAMEMASTER, &ChatHandler::HandleGoGraveyardCommand, "", NULL }, + { "zonexy", SEC_MODERATOR, &ChatHandler::HandleGoZoneXYCommand, "", NULL }, + { "xy", SEC_MODERATOR, &ChatHandler::HandleGoXYCommand, "", NULL }, + { "xyz", SEC_MODERATOR, &ChatHandler::HandleGoXYZCommand, "", NULL }, + { "", SEC_MODERATOR, &ChatHandler::HandleGoXYZCommand, "", NULL }, + { NULL, 0, NULL, "", NULL } + }; + + static ChatCommand gobjectCommandTable[] = + { + { "add", SEC_GAMEMASTER, &ChatHandler::HandleGameObjectCommand, "", NULL }, + { "delete", SEC_GAMEMASTER, &ChatHandler::HandleDelObjectCommand, "", NULL }, + { "target", SEC_GAMEMASTER, &ChatHandler::HandleTargetObjectCommand, "", NULL }, + { "turn", SEC_GAMEMASTER, &ChatHandler::HandleTurnObjectCommand, "", NULL }, + { "move", SEC_GAMEMASTER, &ChatHandler::HandleMoveObjectCommand, "", NULL }, + { "near", SEC_ADMINISTRATOR, &ChatHandler::HandleNearObjectCommand, "", NULL }, + { NULL, 0, NULL, "", NULL } + }; + + static ChatCommand questCommandTable[] = + { + { "add", SEC_ADMINISTRATOR, &ChatHandler::HandleAddQuest, "", NULL }, + { "complete", SEC_ADMINISTRATOR, &ChatHandler::HandleCompleteQuest, "", NULL }, + { "remove", SEC_ADMINISTRATOR, &ChatHandler::HandleRemoveQuest, "", NULL }, + { NULL, 0, NULL, "", NULL } + }; + + static ChatCommand gmCommandTable[] = + { + { "list", SEC_PLAYER, &ChatHandler::HandleGMListCommand, "", NULL }, + { "visible", SEC_MODERATOR, &ChatHandler::HandleVisibleCommand, "", NULL }, + { "fly", SEC_ADMINISTRATOR, &ChatHandler::HandleFlyModeCommand, "", NULL }, + { "", SEC_MODERATOR, &ChatHandler::HandleGMmodeCommand, "", NULL }, + { NULL, 0, NULL, "", NULL } + }; + + static ChatCommand instanceCommandTable[] = + { + { "listbinds", SEC_MODERATOR, &ChatHandler::HandleInstanceListBindsCommand, "", NULL }, + { "unbind", SEC_MODERATOR, &ChatHandler::HandleInstanceUnbindCommand, "", NULL }, + { "stats", SEC_MODERATOR, &ChatHandler::HandleInstanceStatsCommand, "", NULL }, + { "savedata", SEC_MODERATOR, &ChatHandler::HandleInstanceSaveDataCommand, "", NULL }, + { NULL, 0, NULL, "", NULL } + }; + + static ChatCommand commandTable[] = + { + { "gm", SEC_MODERATOR, NULL, "", gmCommandTable }, + { "npc", SEC_MODERATOR, NULL, "", npcCommandTable }, + { "go", SEC_MODERATOR, NULL, "", goCommandTable }, + { "learn", SEC_MODERATOR, NULL, "", learnCommandTable }, + { "modify", SEC_MODERATOR, NULL, "", modifyCommandTable }, + { "debug", SEC_MODERATOR, NULL, "", debugCommandTable }, + { "tele", SEC_MODERATOR, NULL, "", teleCommandTable }, + { "event", SEC_GAMEMASTER, NULL, "", eventCommandTable }, + { "gobject", SEC_GAMEMASTER, NULL, "", gobjectCommandTable }, + { "honor", SEC_GAMEMASTER, NULL, "", honorCommandTable }, + { "wp", SEC_GAMEMASTER, NULL, "", wpCommandTable }, + { "quest", SEC_ADMINISTRATOR, NULL, "", questCommandTable }, + { "reload", SEC_ADMINISTRATOR, NULL, "", reloadCommandTable }, + { "list", SEC_ADMINISTRATOR, NULL, "", listCommandTable }, + { "lookup", SEC_ADMINISTRATOR, NULL, "", lookupCommandTable }, + { "pdump", SEC_ADMINISTRATOR, NULL, "", pdumpCommandTable }, + { "guild", SEC_ADMINISTRATOR, NULL, "", guildCommandTable }, + { "cast", SEC_ADMINISTRATOR, NULL, "", castCommandTable }, + { "reset", SEC_ADMINISTRATOR, NULL, "", resetCommandTable }, + { "instance", SEC_ADMINISTRATOR, NULL, "", instanceCommandTable }, + { "server", SEC_ADMINISTRATOR, NULL, "", serverCommandTable }, + + { "aura", SEC_ADMINISTRATOR, &ChatHandler::HandleAuraCommand, "", NULL }, + { "unaura", SEC_ADMINISTRATOR, &ChatHandler::HandleUnAuraCommand, "", NULL }, + { "acct", SEC_PLAYER, &ChatHandler::HandleAcctCommand, "", NULL }, + { "announce", SEC_MODERATOR, &ChatHandler::HandleAnnounceCommand, "", NULL }, + { "notify", SEC_MODERATOR, &ChatHandler::HandleNotifyCommand, "", NULL }, + { "goname", SEC_MODERATOR, &ChatHandler::HandleGonameCommand, "", NULL }, + { "namego", SEC_MODERATOR, &ChatHandler::HandleNamegoCommand, "", NULL }, + { "groupgo", SEC_MODERATOR, &ChatHandler::HandleGroupgoCommand, "", NULL }, + { "commands", SEC_PLAYER, &ChatHandler::HandleCommandsCommand, "", NULL }, + { "demorph", SEC_GAMEMASTER, &ChatHandler::HandleDeMorphCommand, "", NULL }, + { "die", SEC_ADMINISTRATOR, &ChatHandler::HandleDieCommand, "", NULL }, + { "revive", SEC_ADMINISTRATOR, &ChatHandler::HandleReviveCommand, "", NULL }, + { "dismount", SEC_PLAYER, &ChatHandler::HandleDismountCommand, "", NULL }, + { "gps", SEC_MODERATOR, &ChatHandler::HandleGPSCommand, "", NULL }, + { "guid", SEC_GAMEMASTER, &ChatHandler::HandleGUIDCommand, "", NULL }, + { "help", SEC_PLAYER, &ChatHandler::HandleHelpCommand, "", NULL }, + { "itemmove", SEC_GAMEMASTER, &ChatHandler::HandleItemMoveCommand, "", NULL }, + { "cooldown", SEC_ADMINISTRATOR, &ChatHandler::HandleCooldownCommand, "", NULL }, + { "unlearn", SEC_ADMINISTRATOR, &ChatHandler::HandleUnLearnCommand, "", NULL }, + { "distance", SEC_ADMINISTRATOR, &ChatHandler::HandleGetDistanceCommand, "", NULL }, + { "recall", SEC_MODERATOR, &ChatHandler::HandleRecallCommand, "", NULL }, + { "save", SEC_PLAYER, &ChatHandler::HandleSaveCommand, "", NULL }, + { "saveall", SEC_MODERATOR, &ChatHandler::HandleSaveAllCommand, "", NULL }, + { "kick", SEC_GAMEMASTER, &ChatHandler::HandleKickPlayerCommand, "", NULL }, + { "security", SEC_ADMINISTRATOR, &ChatHandler::HandleSecurityCommand, "", NULL }, + { "ban", SEC_ADMINISTRATOR, &ChatHandler::HandleBanCommand, "", NULL }, + { "unban", SEC_ADMINISTRATOR, &ChatHandler::HandleUnBanCommand, "", NULL }, + { "baninfo", SEC_ADMINISTRATOR, &ChatHandler::HandleBanInfoCommand, "", NULL }, + { "banlist", SEC_ADMINISTRATOR, &ChatHandler::HandleBanListCommand, "", NULL }, + { "plimit", SEC_ADMINISTRATOR, &ChatHandler::HandlePLimitCommand, "", NULL }, + { "start", SEC_PLAYER, &ChatHandler::HandleStartCommand, "", NULL }, + { "taxicheat", SEC_MODERATOR, &ChatHandler::HandleTaxiCheatCommand, "", NULL }, + { "allowmove", SEC_ADMINISTRATOR, &ChatHandler::HandleAllowMovementCommand, "", NULL }, + { "linkgrave", SEC_ADMINISTRATOR, &ChatHandler::HandleLinkGraveCommand, "", NULL }, + { "neargrave", SEC_ADMINISTRATOR, &ChatHandler::HandleNearGraveCommand, "", NULL }, + { "transport", SEC_ADMINISTRATOR, &ChatHandler::HandleSpawnTransportCommand, "", NULL }, + { "explorecheat", SEC_ADMINISTRATOR, &ChatHandler::HandleExploreCheatCommand, "", NULL }, + { "hover", SEC_ADMINISTRATOR, &ChatHandler::HandleHoverCommand, "", NULL }, + { "levelup", SEC_ADMINISTRATOR, &ChatHandler::HandleLevelUpCommand, "", NULL }, + { "showarea", SEC_ADMINISTRATOR, &ChatHandler::HandleShowAreaCommand, "", NULL }, + { "hidearea", SEC_ADMINISTRATOR, &ChatHandler::HandleHideAreaCommand, "", NULL }, + { "additem", SEC_ADMINISTRATOR, &ChatHandler::HandleAddItemCommand, "", NULL }, + { "additemset", SEC_ADMINISTRATOR, &ChatHandler::HandleAddItemSetCommand, "", NULL }, + { "bank", SEC_ADMINISTRATOR, &ChatHandler::HandleBankCommand, "", NULL }, + { "wchange", SEC_ADMINISTRATOR, &ChatHandler::HandleChangeWeather, "", NULL }, + { "ticket", SEC_GAMEMASTER, &ChatHandler::HandleTicketCommand, "", NULL }, + { "delticket", SEC_GAMEMASTER, &ChatHandler::HandleDelTicketCommand, "", NULL }, + { "maxskill", SEC_ADMINISTRATOR, &ChatHandler::HandleMaxSkillCommand, "", NULL }, + { "setskill", SEC_ADMINISTRATOR, &ChatHandler::HandleSetSkillCommand, "", NULL }, + { "whispers", SEC_MODERATOR, &ChatHandler::HandleWhispersCommand, "", NULL }, + { "pinfo", SEC_GAMEMASTER, &ChatHandler::HandlePInfoCommand, "", NULL }, + { "password", SEC_PLAYER, &ChatHandler::HandlePasswordCommand, "", NULL }, + { "lockaccount", SEC_PLAYER, &ChatHandler::HandleLockAccountCommand, "", NULL }, + { "respawn", SEC_ADMINISTRATOR, &ChatHandler::HandleRespawnCommand, "", NULL }, + { "sendmail", SEC_MODERATOR, &ChatHandler::HandleSendMailCommand, "", NULL }, + { "rename", SEC_GAMEMASTER, &ChatHandler::HandleRenameCommand, "", NULL }, + { "loadscripts", SEC_ADMINISTRATOR, &ChatHandler::HandleLoadScriptsCommand, "", NULL }, + { "mute", SEC_GAMEMASTER, &ChatHandler::HandleMuteCommand, "", NULL }, + { "unmute", SEC_GAMEMASTER, &ChatHandler::HandleUnmuteCommand, "", NULL }, + { "movegens", SEC_ADMINISTRATOR, &ChatHandler::HandleMovegensCommand, "", NULL }, + { "cometome", SEC_ADMINISTRATOR, &ChatHandler::HandleComeToMeCommand, "", NULL }, + { "damage", SEC_ADMINISTRATOR, &ChatHandler::HandleDamageCommand, "", NULL }, + { "combatstop", SEC_GAMEMASTER, &ChatHandler::HandleCombatStopCommand, "", NULL }, + + { NULL, 0, NULL, "", NULL } + }; + + if(load_command_table) + { + load_command_table = false; + + QueryResult *result = WorldDatabase.Query("SELECT name,security,help FROM command"); + if (result) + { + do + { + Field *fields = result->Fetch(); + std::string name = fields[0].GetCppString(); + for(uint32 i = 0; commandTable[i].Name != NULL; i++) + { + if (name == commandTable[i].Name) + { + commandTable[i].SecurityLevel = (uint16)fields[1].GetUInt16(); + commandTable[i].Help = fields[2].GetCppString(); + } + if(commandTable[i].ChildCommands != NULL) + { + ChatCommand *ptable = commandTable[i].ChildCommands; + for(uint32 j = 0; ptable[j].Name != NULL; j++) + { + // first case for "" named subcommand + if (ptable[j].Name[0]=='\0' && name == commandTable[i].Name || + name == fmtstring("%s %s", commandTable[i].Name, ptable[j].Name) ) + { + ptable[j].SecurityLevel = (uint16)fields[1].GetUInt16(); + ptable[j].Help = fields[2].GetCppString(); + } + } + } + } + } while(result->NextRow()); + delete result; + } + } + + return commandTable; +} + +const char *ChatHandler::GetMangosString(int32 entry) +{ + return m_session->GetMangosString(entry); +} + +bool ChatHandler::hasStringAbbr(const char* s1, const char* s2) +{ + for(;;) + { + if( !*s2 ) + return true; + else if( !*s1 ) + return false; + else if( tolower( *s1 ) != tolower( *s2 ) ) + return false; + ++s1; ++s2; + } +} + +void ChatHandler::SendSysMessage(const char *str) +{ + WorldPacket data; + + // need copy to prevent corruption by strtok call in LineFromMessage original string + char* buf = strdup(str); + char* pos = buf; + + while(char* line = LineFromMessage(pos)) + { + FillSystemMessageData(&data, line); + m_session->SendPacket(&data); + } + + free(buf); +} + +void ChatHandler::SendGlobalSysMessage(const char *str) +{ + WorldPacket data; + + // need copy to prevent corruption by strtok call in LineFromMessage original string + char* buf = strdup(str); + char* pos = buf; + + while(char* line = LineFromMessage(pos)) + { + FillSystemMessageData(&data, line); + sWorld.SendGlobalMessage(&data); + } + + free(buf); +} + +void ChatHandler::SendSysMessage(int32 entry) +{ + SendSysMessage(GetMangosString(entry)); +} + +void ChatHandler::PSendSysMessage(int32 entry, ...) +{ + const char *format = GetMangosString(entry); + va_list ap; + char str [1024]; + va_start(ap, entry); + vsnprintf(str,1024,format, ap ); + va_end(ap); + SendSysMessage(str); +} + +void ChatHandler::PSendSysMessage(const char *format, ...) +{ + va_list ap; + char str [1024]; + va_start(ap, format); + vsnprintf(str,1024,format, ap ); + va_end(ap); + SendSysMessage(str); +} + +bool ChatHandler::ExecuteCommandInTable(ChatCommand *table, const char* text, std::string fullcmd) +{ + char const* oldtext = text; + std::string cmd = ""; + + while (*text != ' ' && *text != '\0') + { + cmd += *text; + ++text; + } + + while (*text == ' ') ++text; + + if(!cmd.length()) + return false; + + for(uint32 i = 0; table[i].Name != NULL; i++) + { + // allow pass "" command name in table + if(strlen(table[i].Name) && !hasStringAbbr(table[i].Name, cmd.c_str())) + continue; + + // select subcommand from child commands list + if(table[i].ChildCommands != NULL) + { + if(!ExecuteCommandInTable(table[i].ChildCommands, text, fullcmd)) + { + if(text && text[0] != '\0') + SendSysMessage(LANG_NO_SUBCMD); + else + SendSysMessage(LANG_CMD_SYNTAX); + + ShowHelpForCommand(table[i].ChildCommands,text); + } + + return true; + } + + // check security level only for simple command (without child commands) + if(m_session->GetSecurity() < table[i].SecurityLevel) + continue; + + SetSentErrorMessage(false); + // table[i].Name == "" is special case: send original command to handler + if((this->*(table[i].Handler))(strlen(table[i].Name)!=0 ? text : oldtext)) + { + if(table[i].SecurityLevel > SEC_PLAYER) + { + Player* p = m_session->GetPlayer(); + uint64 sel_guid = p->GetSelection(); + sLog.outCommand("Command: %s [Player: %s (Account: %u) X: %f Y: %f Z: %f Map: %u Selected: %s (GUID: %u)]", + fullcmd.c_str(),p->GetName(),m_session->GetAccountId(),p->GetPositionX(),p->GetPositionY(),p->GetPositionZ(),p->GetMapId(), + GetLogNameForGuid(sel_guid),GUID_LOPART(sel_guid)); + } + } + // some commands have custom error messages. Don't send the default one in these cases. + else if(!sentErrorMessage) + { + if(!table[i].Help.empty()) + SendSysMessage(table[i].Help.c_str()); + else + SendSysMessage(LANG_CMD_SYNTAX); + } + + return true; + } + + return false; +} + +int ChatHandler::ParseCommands(const char* text) +{ + ASSERT(text); + ASSERT(*text); + + //if(m_session->GetSecurity() == 0) + // return 0; + + if(text[0] != '!' && text[0] != '.') + return 0; + + // ignore single . and ! in line + if(strlen(text) < 2) + return 0; + + // ignore messages staring from many dots. + if(text[0] == '.' && text[1] == '.' || text[0] == '!' && text[1] == '!') + return 0; + + ++text; + + std::string fullcmd = text; // original `text` can't be used. It content destroyed in command code processing. + + if(!ExecuteCommandInTable(getCommandTable(), text, fullcmd)) + SendSysMessage(LANG_NO_CMD); + + return 1; +} + +bool ChatHandler::ShowHelpForSubCommands(ChatCommand *table, char const* cmd, char const* subcmd) +{ + std::string list; + for(uint32 i = 0; table[i].Name != NULL; ++i) + { + if(m_session->GetSecurity() < table[i].SecurityLevel) + continue; + + if(strlen(table[i].Name) && !hasStringAbbr(table[i].Name, subcmd)) + continue; + + (list += "\n ") += table[i].Name; + } + + if(list.empty()) + return false; + + if(table==getCommandTable()) + { + SendSysMessage(LANG_AVIABLE_CMD); + PSendSysMessage("%s",list.c_str()); + } + else + PSendSysMessage(LANG_SUBCMDS_LIST,cmd,list.c_str()); + + return true; +} + +bool ChatHandler::ShowHelpForCommand(ChatCommand *table, const char* cmd) +{ + if(*cmd) + { + for(uint32 i = 0; table[i].Name != NULL; ++i) + { + if(m_session->GetSecurity() < table[i].SecurityLevel) + continue; + + if(strlen(table[i].Name) && !hasStringAbbr(table[i].Name, cmd)) + continue; + + // have subcommand + char const* subcmd = (*cmd) ? strtok(NULL, " ") : ""; + + if(table[i].ChildCommands && subcmd && *subcmd) + { + if(ShowHelpForCommand(table[i].ChildCommands, subcmd)) + return true; + } + + if(!table[i].Help.empty()) + SendSysMessage(table[i].Help.c_str()); + + if(table[i].ChildCommands) + if(ShowHelpForSubCommands(table[i].ChildCommands,table[i].Name,subcmd ? subcmd : "")) + return true; + + return !table[i].Help.empty(); + } + } + else + { + for(uint32 i = 0; table[i].Name != NULL; ++i) + { + if(m_session->GetSecurity() < table[i].SecurityLevel) + continue; + + if(strlen(table[i].Name)) + continue; + + if(!table[i].Help.empty()) + SendSysMessage(table[i].Help.c_str()); + + if(table[i].ChildCommands) + if(ShowHelpForSubCommands(table[i].ChildCommands,"","")) + return true; + + return !table[i].Help.empty(); + } + } + + return ShowHelpForSubCommands(table,"",cmd); +} + +//Note: target_guid used only in CHAT_MSG_WHISPER_INFORM mode (in this case channelName ignored) +void ChatHandler::FillMessageData( WorldPacket *data, WorldSession* session, uint8 type, uint32 language, const char *channelName, uint64 target_guid, const char *message, Unit *speaker) +{ + uint32 messageLength = (message ? strlen(message) : 0) + 1; + + data->Initialize(SMSG_MESSAGECHAT, 100); // guess size + *data << uint8(type); + if ((type != CHAT_MSG_CHANNEL && type != CHAT_MSG_WHISPER) || language == LANG_ADDON) + *data << uint32(language); + else + *data << uint32(LANG_UNIVERSAL); + + switch(type) + { + case CHAT_MSG_SAY: + case CHAT_MSG_PARTY: + case CHAT_MSG_RAID: + case CHAT_MSG_GUILD: + case CHAT_MSG_OFFICER: + case CHAT_MSG_YELL: + case CHAT_MSG_WHISPER: + case CHAT_MSG_CHANNEL: + case CHAT_MSG_RAID_LEADER: + case CHAT_MSG_RAID_WARNING: + case CHAT_MSG_BG_SYSTEM_NEUTRAL: + case CHAT_MSG_BG_SYSTEM_ALLIANCE: + case CHAT_MSG_BG_SYSTEM_HORDE: + case CHAT_MSG_BATTLEGROUND: + case CHAT_MSG_BATTLEGROUND_LEADER: + target_guid = session ? session->GetPlayer()->GetGUID() : 0; + break; + case CHAT_MSG_MONSTER_SAY: + case CHAT_MSG_MONSTER_PARTY: + case CHAT_MSG_MONSTER_YELL: + case CHAT_MSG_MONSTER_WHISPER: + case CHAT_MSG_MONSTER_EMOTE: + case CHAT_MSG_RAID_BOSS_WHISPER: + case CHAT_MSG_RAID_BOSS_EMOTE: + { + *data << uint64(speaker->GetGUID()); + *data << uint32(0); // 2.1.0 + *data << uint32(strlen(speaker->GetName()) + 1); + *data << speaker->GetName(); + uint64 listener_guid = 0; + *data << uint64(listener_guid); + if(listener_guid && !IS_PLAYER_GUID(listener_guid)) + { + *data << uint32(1); // string listener_name_length + *data << uint8(0); // string listener_name + } + *data << uint32(messageLength); + *data << message; + *data << uint8(0); + return; + } + default: + if (type != CHAT_MSG_REPLY && type != CHAT_MSG_IGNORED && type != CHAT_MSG_DND && type != CHAT_MSG_AFK) + target_guid = 0; // only for CHAT_MSG_WHISPER_INFORM used original value target_guid + break; + } + + *data << uint64(target_guid); // there 0 for BG messages + *data << uint32(0); // can be chat msg group or something + + if (type == CHAT_MSG_CHANNEL) + { + ASSERT(channelName); + *data << channelName; + } + + *data << uint64(target_guid); + *data << uint32(messageLength); + *data << message; + if(session != 0 && type != CHAT_MSG_REPLY && type != CHAT_MSG_DND && type != CHAT_MSG_AFK) + *data << uint8(session->GetPlayer()->chatTag()); + else + *data << uint8(0); +} + +Player * ChatHandler::getSelectedPlayer() +{ + uint64 guid = m_session->GetPlayer()->GetSelection(); + + if (guid == 0) + return m_session->GetPlayer(); + + return objmgr.GetPlayer(guid); +} + +Unit* ChatHandler::getSelectedUnit() +{ + uint64 guid = m_session->GetPlayer()->GetSelection(); + + if (guid == 0) + return m_session->GetPlayer(); + + return ObjectAccessor::GetUnit(*m_session->GetPlayer(),guid); +} + +Creature* ChatHandler::getSelectedCreature() +{ + return ObjectAccessor::GetCreatureOrPet(*m_session->GetPlayer(),m_session->GetPlayer()->GetSelection()); +} + +char* ChatHandler::extractKeyFromLink(char* text, char const* linkType, char** something1) +{ + // skip empty + if(!text) + return NULL; + + // skip speces + while(*text==' '||*text=='\t'||*text=='\b') + ++text; + + if(!*text) + return NULL; + + // return non link case + if(text[0]!='|') + return strtok(text, " "); + + // [name] Shift-click form |color|linkType:key|h[name]|h|r + // or + // [name] Shift-click form |color|linkType:key:something1:...:somethingN|h[name]|h|r + + char* check = strtok(text, "|"); // skip color + if(!check) + return NULL; // end of data + + char* cLinkType = strtok(NULL, ":"); // linktype + if(!cLinkType) + return NULL; // end of data + + if(strcmp(cLinkType,linkType) != 0) + { + strtok(NULL, " "); // skip link tail (to allow continue strtok(NULL,s) use after retturn from function + SendSysMessage(LANG_WRONG_LINK_TYPE); + return NULL; + } + + char* cKeys = strtok(NULL, "|"); // extract keys and values + char* cKeysTail = strtok(NULL, ""); + + char* cKey = strtok(cKeys, ":|"); // extract key + if(something1) + *something1 = strtok(NULL, ":|"); // extract something + + strtok(cKeysTail, "]"); // restart scan tail and skip name with possible spaces + strtok(NULL, " "); // skip link tail (to allow continue strtok(NULL,s) use after retturn from function + return cKey; +} + +char* ChatHandler::extractKeyFromLink(char* text, char const* const* linkTypes, int* found_idx, char** something1) +{ + // skip empty + if(!text) + return NULL; + + // skip speces + while(*text==' '||*text=='\t'||*text=='\b') + ++text; + + if(!*text) + return NULL; + + // return non link case + if(text[0]!='|') + return strtok(text, " "); + + // [name] Shift-click form |color|linkType:key|h[name]|h|r + // or + // [name] Shift-click form |color|linkType:key:something1:...:somethingN|h[name]|h|r + + char* check = strtok(text, "|"); // skip color + if(!check) + return NULL; // end of data + + char* cLinkType = strtok(NULL, ":"); // linktype + if(!cLinkType) + return NULL; // end of data + + for(int i = 0; linkTypes[i]; ++i) + { + if(strcmp(cLinkType,linkTypes[i]) == 0) + { + char* cKeys = strtok(NULL, "|"); // extract keys and values + char* cKeysTail = strtok(NULL, ""); + + char* cKey = strtok(cKeys, ":|"); // extract key + if(something1) + *something1 = strtok(NULL, ":|"); // extract something + + strtok(cKeysTail, "]"); // restart scan tail and skip name with possible spaces + strtok(NULL, " "); // skip link tail (to allow continue strtok(NULL,s) use after return from function + if(found_idx) + *found_idx = i; + return cKey; + } + } + + strtok(NULL, " "); // skip link tail (to allow continue strtok(NULL,s) use after return from function + SendSysMessage(LANG_WRONG_LINK_TYPE); + return NULL; +} + +char const *fmtstring( char const *format, ... ) +{ + va_list argptr; + #define MAX_FMT_STRING 32000 + static char temp_buffer[MAX_FMT_STRING]; + static char string[MAX_FMT_STRING]; + static int index = 0; + char *buf; + int len; + + va_start(argptr, format); + vsnprintf(temp_buffer,MAX_FMT_STRING, format, argptr); + va_end(argptr); + + len = strlen(temp_buffer); + + if( len >= MAX_FMT_STRING ) + return "ERROR"; + + if (len + index >= MAX_FMT_STRING-1) + { + index = 0; + } + + buf = &string[index]; + memcpy( buf, temp_buffer, len+1 ); + + index += len + 1; + + return buf; +} + +GameObject* ChatHandler::GetObjectGlobalyWithGuidOrNearWithDbGuid(uint32 lowguid,uint32 entry) +{ + Player* pl = m_session->GetPlayer(); + + GameObject* obj = ObjectAccessor::GetGameObject(*pl, MAKE_NEW_GUID(lowguid, entry, HIGHGUID_GAMEOBJECT)); + + if(!obj && objmgr.GetGOData(lowguid)) // guid is DB guid of object + { + // search near player then + CellPair p(MaNGOS::ComputeCellPair(pl->GetPositionX(), pl->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + + MaNGOS::GameObjectWithDbGUIDCheck go_check(*pl,lowguid); + MaNGOS::GameObjectSearcher checker(obj,go_check); + + TypeContainerVisitor, GridTypeMapContainer > object_checker(checker); + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, object_checker, *MapManager::Instance().GetMap(pl->GetMapId(), pl)); + } + + return obj; +} + +static char const* const spellTalentKeys[] = { + "Hspell", + "Htalent", + 0 +}; + +uint32 ChatHandler::extractSpellIdFromLink(char* text) +{ + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r + // number or [name] Shift-click form |color|Htalent:telen_id,rank|h[name]|h|r + int type = 0; + char* rankS = NULL; + char* idS = extractKeyFromLink(text,spellTalentKeys,&type,&rankS); + if(!idS) + return 0; + + uint32 id = (uint32)atol(idS); + + // spell + if(type==0) + return id; + + // talent + TalentEntry const* talentEntry = sTalentStore.LookupEntry(id); + if(!talentEntry) + return 0; + + int32 rank = rankS ? (uint32)atol(rankS) : 0; + if(rank >= 5) + return 0; + + if(rank < 0) + rank = 0; + + return talentEntry->RankID[rank]; +} + diff --git a/src/game/Chat.h b/src/game/Chat.h new file mode 100644 index 00000000000..49b219e875e --- /dev/null +++ b/src/game/Chat.h @@ -0,0 +1,406 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOSSERVER_CHAT_H +#define MANGOSSERVER_CHAT_H + +#include "SharedDefines.h" + +class ChatHandler; +class WorldSession; +class Creature; +class Player; +class Unit; + +struct LanguageDesc +{ + Language lang_id; + uint32 spell_id; + uint32 skill_id; +}; + +extern LanguageDesc lang_description[LANGUAGES_COUNT]; + +LanguageDesc const* GetLanguageDescByID(uint32 lang); +LanguageDesc const* GetLanguageDescBySpell(uint32 spell_id); +LanguageDesc const* GetLanguageDescBySkill(uint32 skill_id); + +class ChatCommand +{ + public: + const char * Name; + uint32 SecurityLevel; // function pointer required correct align (use uint32) + bool (ChatHandler::*Handler)(const char* args); + std::string Help; + ChatCommand * ChildCommands; +}; + +class ChatHandler +{ + public: + explicit ChatHandler(WorldSession* session) : m_session(session) {} + explicit ChatHandler(Player* player) : m_session(player->GetSession()) {} + ~ChatHandler() {} + + static void FillMessageData( WorldPacket *data, WorldSession* session, uint8 type, uint32 language, const char *channelName, uint64 target_guid, const char *message, Unit *speaker); + + void FillMessageData( WorldPacket *data, uint8 type, uint32 language, uint64 target_guid, const char* message) + { + FillMessageData( data, m_session, type, language, NULL, target_guid, message, NULL); + } + + void FillSystemMessageData( WorldPacket *data, const char* message ) + { + FillMessageData( data, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, 0, message ); + } + + static char* LineFromMessage(char*& pos) { char* start = strtok(pos,"\n"); pos = NULL; return start; } + + const char *GetMangosString(int32 entry); + + void SendSysMessage( const char *str); + void SendSysMessage( int32 entry); + void PSendSysMessage( const char *format, ...) ATTR_PRINTF(2,3); + void PSendSysMessage( int32 entry, ... ); + + int ParseCommands(const char* text); + + protected: + bool hasStringAbbr(const char* s1, const char* s2); + void SendGlobalSysMessage(const char *str); + + bool ExecuteCommandInTable(ChatCommand *table, const char* text, std::string fullcommand); + bool ShowHelpForCommand(ChatCommand *table, const char* cmd); + bool ShowHelpForSubCommands(ChatCommand *table, char const* cmd, char const* subcmd); + + ChatCommand* getCommandTable(); + + bool HandleHelpCommand(const char* args); + bool HandleCommandsCommand(const char* args); + bool HandleAcctCommand(const char* args); + bool HandleStartCommand(const char* args); + bool HandleInfoCommand(const char* args); + bool HandleDismountCommand(const char* args); + bool HandleSaveCommand(const char* args); + bool HandleGMListCommand(const char* args); + + bool HandleNamegoCommand(const char* args); + bool HandleGonameCommand(const char* args); + bool HandleGroupgoCommand(const char* args); + bool HandleRecallCommand(const char* args); + bool HandleAnnounceCommand(const char* args); + bool HandleNotifyCommand(const char* args); + bool HandleGMmodeCommand(const char* args); + bool HandleVisibleCommand(const char* args); + bool HandleGPSCommand(const char* args); + bool HandleTaxiCheatCommand(const char* args); + bool HandleWhispersCommand(const char* args); + bool HandleSayCommand(const char* args); + bool HandleNpcWhisperCommand(const char* args); + bool HandleYellCommand(const char* args); + bool HandlePlayEmoteCommand(const char* args); + bool HandleSendMailCommand(const char* args); + bool HandleNameTeleCommand(const char* args); + bool HandleGroupTeleCommand(const char* args); + bool HandleDrunkCommand(const char* args); + + bool HandleEventActiveListCommand(const char* args); + bool HandleEventStartCommand(const char* args); + bool HandleEventStopCommand(const char* args); + bool HandleEventInfoCommand(const char* args); + + bool HandleModifyKnownTitlesCommand(const char* args); + bool HandleModifyHPCommand(const char* args); + bool HandleModifyManaCommand(const char* args); + bool HandleModifyRageCommand(const char* args); + bool HandleModifyEnergyCommand(const char* args); + bool HandleModifyMoneyCommand(const char* args); + bool HandleModifyASpeedCommand(const char* args); + bool HandleModifySpeedCommand(const char* args); + bool HandleModifyBWalkCommand(const char* args); + bool HandleModifyFlyCommand(const char* args); + bool HandleModifySwimCommand(const char* args); + bool HandleModifyScaleCommand(const char* args); + bool HandleModifyMountCommand(const char* args); + bool HandleModifyBitCommand(const char* args); + bool HandleModifyFactionCommand(const char* args); + bool HandleModifySpellCommand(const char* args); + bool HandleModifyTalentCommand (const char* args); + bool HandleModifyHonorCommand (const char* args); + bool HandleModifyRepCommand(const char* args); + bool HandleModifyArenaCommand(const char* args); + + bool HandleReloadCommand(const char* args); + bool HandleReloadAllCommand(const char* args); + bool HandleReloadAllAreaCommand(const char* args); + bool HandleReloadAllItemCommand(const char* args); + bool HandleReloadAllLootCommand(const char* args); + bool HandleReloadAllQuestCommand(const char* args); + bool HandleReloadAllScriptsCommand(const char* args); + bool HandleReloadAllSpellCommand(const char* args); + + bool HandleReloadConfigCommand(const char* args); + + bool HandleReloadAreaTriggerTavernCommand(const char* args); + bool HandleReloadAreaTriggerTeleportCommand(const char* args); + bool HandleReloadEventScriptsCommand(const char* args); + bool HandleReloadCommandCommand(const char* args); + bool HandleReloadCreatureQuestRelationsCommand(const char* args); + bool HandleReloadCreatureQuestInvRelationsCommand(const char* args); + bool HandleReloadGameGraveyardZoneCommand(const char* args); + bool HandleReloadGameObjectScriptsCommand(const char* args); + bool HandleReloadGOQuestRelationsCommand(const char* args); + bool HandleReloadGOQuestInvRelationsCommand(const char* args); + bool HandleReloadLootTemplatesCreatureCommand(const char* args); + bool HandleReloadLootTemplatesDisenchantCommand(const char* args); + bool HandleReloadLootTemplatesFishingCommand(const char* args); + bool HandleReloadLootTemplatesGameobjectCommand(const char* args); + bool HandleReloadLootTemplatesItemCommand(const char* args); + bool HandleReloadLootTemplatesPickpocketingCommand(const char* args); + bool HandleReloadLootTemplatesProspectingCommand(const char* args); + bool HandleReloadLootTemplatesReferenceCommand(const char* args); + bool HandleReloadLootTemplatesQuestMailCommand(const char* args); + bool HandleReloadLootTemplatesSkinningCommand(const char* args); + bool HandleReloadMangosStringCommand(const char* args); + bool HandleReloadQuestAreaTriggersCommand(const char* args); + bool HandleReloadQuestEndScriptsCommand(const char* args); + bool HandleReloadQuestStartScriptsCommand(const char* args); + bool HandleReloadQuestTemplateCommand(const char* args); + bool HandleReloadReservedNameCommand(const char*); + bool HandleReloadSkillDiscoveryTemplateCommand(const char* args); + bool HandleReloadSkillExtraItemTemplateCommand(const char* args); + bool HandleReloadSkillFishingBaseLevelCommand(const char* args); + bool HandleReloadSpellAffectCommand(const char* args); + bool HandleReloadSpellChainCommand(const char* args); + bool HandleReloadSpellElixirCommand(const char* args); + bool HandleReloadSpellLearnSpellCommand(const char* args); + bool HandleReloadSpellProcEventCommand(const char* args); + bool HandleReloadSpellScriptTargetCommand(const char* args); + bool HandleReloadSpellScriptsCommand(const char* args); + bool HandleReloadSpellTargetPositionCommand(const char* args); + bool HandleReloadSpellThreatsCommand(const char* args); + bool HandleReloadSpellPetAurasCommand(const char* args); + bool HandleReloadPageTextsCommand(const char* args); + bool HandleReloadItemEnchantementsCommand(const char* args); + + bool HandleInstanceListBindsCommand(const char* args); + bool HandleInstanceUnbindCommand(const char* args); + bool HandleInstanceStatsCommand(const char* args); + bool HandleInstanceSaveDataCommand(const char * args); + + bool HandleAddHonorCommand(const char* args); + bool HandleHonorAddKillCommand(const char* args); + bool HandleUpdateHonorFieldsCommand(const char* args); + + bool HandleLoadScriptsCommand(const char* args); + bool HandleSendQuestPartyMsgCommand(const char* args); + bool HandleSendQuestInvalidMsgCommand(const char* args); + + bool HandleDebugInArcCommand(const char* args); + bool HandleDebugSpellFailCommand(const char* args); + + bool HandleGUIDCommand(const char* args); + bool HandleNameCommand(const char* args); + bool HandleSubNameCommand(const char* args); + bool HandleItemMoveCommand(const char* args); + bool HandleDelCreatureCommand(const char* args); + bool HandleDeMorphCommand(const char* args); + bool HandleAddVendorItemCommand(const char* args); + bool HandleDelVendorItemCommand(const char* args); + bool HandleAddMoveCommand(const char* args); + bool HandleSetMoveTypeCommand(const char* args); + bool HandleChangeLevelCommand(const char* args); + bool HandleSetPoiCommand(const char* args); + bool HandleEquipErrorCommand(const char* args); + bool HandleNPCFlagCommand(const char* args); + bool HandleSetModelCommand(const char* args); + bool HandleFactionIdCommand(const char* args); + bool HandleAddSpwCommand(const char* args); + bool HandleSpawnDistCommand(const char* args); + bool HandleSpawnTimeCommand(const char* args); + bool HandleGoCreatureCommand(const char* args); + bool HandleGoObjectCommand(const char* args); + bool HandleGoTriggerCommand(const char* args); + bool HandleGoGraveyardCommand(const char* args); + bool HandleTargetObjectCommand(const char* args); + bool HandleDelObjectCommand(const char* args); + bool HandleMoveCreatureCommand(const char* args); + bool HandleMoveObjectCommand(const char* args); + bool HandleTurnObjectCommand(const char* args); + bool HandlePInfoCommand(const char* args); + bool HandlePLimitCommand(const char* args); + bool HandleMuteCommand(const char* args); + bool HandleUnmuteCommand(const char* args); + bool HandleMovegensCommand(const char* args); + + bool HandleBanCommand(const char* args); + bool HandleUnBanCommand(const char* args); + bool HandleBanInfoCommand(const char* args); + bool HandleBanListCommand(const char* args); + bool HandleIdleRestartCommand(const char* args); + bool HandleIdleShutDownCommand(const char* args); + bool HandleShutDownCommand(const char* args); + bool HandleRestartCommand(const char* args); + bool HandleSecurityCommand(const char* args); + bool HandleGoXYCommand(const char* args); + bool HandleGoXYZCommand(const char* args); + bool HandleGoZoneXYCommand(const char* args); + bool HandleGoGridCommand(const char* args); + bool HandleAddWeaponCommand(const char* args); + bool HandleAllowMovementCommand(const char* args); + bool HandleGoCommand(const char* args); + bool HandleLearnCommand(const char* args); + bool HandleLearnAllCommand(const char* args); + bool HandleLearnAllGMCommand(const char* args); + bool HandleLearnAllCraftsCommand(const char* args); + bool HandleLearnAllRecipesCommand(const char* args); + bool HandleLearnAllDefaultCommand(const char* args); + bool HandleLearnAllLangCommand(const char* args); + bool HandleLearnAllMyClassCommand(const char* args); + bool HandleLearnAllMySpellsCommand(const char* args); + bool HandleLearnAllMyTalentsCommand(const char* args); + bool HandleCooldownCommand(const char* args); + bool HandleUnLearnCommand(const char* args); + bool HandleGetDistanceCommand(const char* args); + bool HandleGameObjectCommand(const char* args); + bool HandleAnimCommand(const char* args); + bool HandlePlaySoundCommand(const char* args); + bool HandleStandStateCommand(const char* args); + bool HandleDieCommand(const char* args); + bool HandleDamageCommand(const char *args); + bool HandleReviveCommand(const char* args); + bool HandleMorphCommand(const char* args); + bool HandleAuraCommand(const char* args); + bool HandleUnAuraCommand(const char* args); + bool HandleLinkGraveCommand(const char* args); + bool HandleNearGraveCommand(const char* args); + bool HandleSpawnTransportCommand(const char* args); + bool HandleExploreCheatCommand(const char* args); + bool HandleTextEmoteCommand(const char* args); + bool HandleNpcInfoCommand(const char* args); + bool HandleHoverCommand(const char* args); + bool HandleLevelUpCommand(const char* args); + bool HandleShowAreaCommand(const char* args); + bool HandleHideAreaCommand(const char* args); + bool HandleAddItemCommand(const char* args); + bool HandleAddItemSetCommand(const char* args); + bool HandleLookupItemCommand(const char * args); + bool HandleLookupItemSetCommand(const char * args); + bool HandleGuildCreateCommand(const char* args); + bool HandleGuildInviteCommand(const char* args); + bool HandleGuildUninviteCommand(const char* args); + bool HandleGuildRankCommand(const char* args); + bool HandleGuildDeleteCommand(const char* args); + bool HandleUpdate(const char* args); + bool HandleBankCommand(const char* args); + bool HandleChangeWeather(const char* args); + bool HandleKickPlayerCommand(const char * args); + bool HandleTeleCommand(const char * args); + bool HandleAddTeleCommand(const char * args); + bool HandleDelTeleCommand(const char * args); + bool HandleListAurasCommand(const char * args); + bool HandleLookupTeleCommand(const char * args); + + bool HandleResetHonorCommand(const char * args); + bool HandleResetLevelCommand(const char * args); + bool HandleResetSpellsCommand(const char * args); + + bool HandleResetStatsCommand(const char * args); + bool HandleResetTalentsCommand(const char * args); + + bool HandleResetAllCommand(const char * args); + bool HandleTicketCommand(const char* args); + bool HandleDelTicketCommand(const char* args); + bool HandleMaxSkillCommand(const char* args); + bool HandleSetSkillCommand(const char* args); + bool HandleListCreatureCommand(const char* args); + bool HandleListItemCommand(const char* args); + bool HandleListObjectCommand(const char* args); + bool HandleNearObjectCommand(const char* args); + bool HandleLookupAreaCommand(const char* args); + bool HandleLookupCreatureCommand(const char* args); + bool HandleLookupEventCommand(const char* args); + bool HandleLookupFactionCommand(const char * args); + bool HandleLookupObjectCommand(const char* args); + bool HandleLookupQuestCommand(const char* args); + bool HandleLookupSkillCommand(const char* args); + bool HandleLookupSpellCommand(const char* args); + bool HandlePasswordCommand(const char* args); + bool HandleLockAccountCommand(const char* args); + bool HandleRespawnCommand(const char* args); + bool HandleWpAddCommand(const char* args); + bool HandleWpModifyCommand(const char* args); + bool HandleWpShowCommand(const char* args); + bool HandleWpExportCommand(const char* args); + bool HandleWpImportCommand(const char* args); + bool HandleFlyModeCommand(const char* args); + bool HandleSendOpcodeCommand(const char* args); + bool HandleSellErrorCommand(const char* args); + bool HandleBuyErrorCommand(const char* args); + bool HandleUpdateWorldStateCommand(const char* args); + bool HandlePlaySound2Command(const char* args); + bool HandleSendChannelNotifyCommand(const char* args); + bool HandleSendChatMsgCommand(const char* args); + bool HandleRenameCommand(const char * args); + bool HandleLoadPDumpCommand(const char *args); + bool HandleWritePDumpCommand(const char *args); + bool HandleChangeEntryCommand(const char *args); + bool HandleCastCommand(const char *args); + bool HandleCastBackCommand(const char *args); + bool HandleCastDistCommand(const char *args); + bool HandleCastSelfCommand(const char *args); + bool HandleCastTargetCommand(const char *args); + bool HandleComeToMeCommand(const char *args); + bool HandleCombatStopCommand(const char *args); + + //! Development Commands + bool HandleSetValue(const char* args); + bool HandleGetValue(const char* args); + bool HandleSet32Bit(const char* args); + bool HandleMod32Value(const char* args); + bool HandleAddQuest(const char * args); + bool HandleRemoveQuest(const char * args); + bool HandleCompleteQuest(const char * args); + bool HandleSaveAllCommand(const char* args); + bool HandleGetItemState(const char * args); + bool HandleGetLootRecipient(const char * args); + + Player* getSelectedPlayer(); + Creature* getSelectedCreature(); + Unit* getSelectedUnit(); + char* extractKeyFromLink(char* text, char const* linkType, char** something1 = NULL); + char* extractKeyFromLink(char* text, char const* const* linkTypes, int* found_idx, char** something1 = NULL); + uint32 extractSpellIdFromLink(char* text); + + GameObject* GetObjectGlobalyWithGuidOrNearWithDbGuid(uint32 lowguid,uint32 entry); + + WorldSession * m_session; + + // Utility methods for commands + void ShowTicket(uint64 guid, char const* text, char const* time); + uint32 GetTicketIDByNum(uint32 num); + + void SetSentErrorMessage(bool val){ sentErrorMessage = val;}; + private: + // common global flag + static bool load_command_table; + bool sentErrorMessage; +}; +#endif + +char const *fmtstring( char const *format, ... ); diff --git a/src/game/ChatHandler.cpp b/src/game/ChatHandler.cpp new file mode 100644 index 00000000000..dd3a711858d --- /dev/null +++ b/src/game/ChatHandler.cpp @@ -0,0 +1,583 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Log.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "World.h" +#include "Opcodes.h" +#include "ObjectMgr.h" +#include "Chat.h" +#include "Database/DatabaseEnv.h" +#include "ChannelMgr.h" +#include "Group.h" +#include "Guild.h" +#include "MapManager.h" +#include "ObjectAccessor.h" +#include "ScriptCalls.h" +#include "Player.h" +#include "SpellAuras.h" +#include "Language.h" +#include "Util.h" + +void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,4+4+1); + + uint32 type; + uint32 lang; + + recv_data >> type; + recv_data >> lang; + + if(type >= MAX_CHAT_MSG_TYPE) + { + sLog.outError("CHAT: Wrong message type received: %u", type); + return; + } + + //sLog.outDebug("CHAT: packet received. type %u, lang %u", type, lang ); + + // prevent talking at unknown language (cheating) + LanguageDesc const* langDesc = GetLanguageDescByID(lang); + if(!langDesc) + { + SendNotification("Unknown language"); + return; + } + if(langDesc->skill_id != 0 && !_player->HasSkill(langDesc->skill_id)) + { + // also check SPELL_AURA_COMPREHEND_LANGUAGE (client offers option to speak in that language) + Unit::AuraList const& langAuras = _player->GetAurasByType(SPELL_AURA_COMPREHEND_LANGUAGE); + bool foundAura = false; + for(Unit::AuraList::const_iterator i = langAuras.begin();i != langAuras.end(); ++i) + { + if((*i)->GetModifier()->m_miscvalue == lang) + { + foundAura = true; + break; + } + } + if(!foundAura) + { + SendNotification("You don't know that language"); + return; + } + } + + if(lang == LANG_ADDON) + { + // Disabled addon channel? + if(!sWorld.getConfig(CONFIG_ADDON_CHANNEL)) + return; + } + // LANG_ADDON should not be changed nor be affected by flood control + else + { + // send in universal language if player in .gmon mode (ignore spell effects) + if (_player->isGameMaster()) + lang = LANG_UNIVERSAL; + else + { + // send in universal language in two side iteration allowed mode + if (sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT)) + lang = LANG_UNIVERSAL; + else + { + switch(type) + { + case CHAT_MSG_PARTY: + case CHAT_MSG_RAID: + case CHAT_MSG_RAID_LEADER: + case CHAT_MSG_RAID_WARNING: + // allow two side chat at group channel if two side group allowed + if(sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP)) + lang = LANG_UNIVERSAL; + break; + case CHAT_MSG_GUILD: + case CHAT_MSG_OFFICER: + // allow two side chat at guild channel if two side guild allowed + if(sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD)) + lang = LANG_UNIVERSAL; + break; + } + } + + // but overwrite it by SPELL_AURA_MOD_LANGUAGE auras (only single case used) + Unit::AuraList const& ModLangAuras = _player->GetAurasByType(SPELL_AURA_MOD_LANGUAGE); + if(!ModLangAuras.empty()) + lang = ModLangAuras.front()->GetModifier()->m_miscvalue; + } + + if (!_player->CanSpeak()) + { + std::string timeStr = secsToTimeString(m_muteTime - time(NULL)); + SendNotification(GetMangosString(LANG_WAIT_BEFORE_SPEAKING),timeStr.c_str()); + return; + } + + if (type != CHAT_MSG_AFK && type != CHAT_MSG_DND) + GetPlayer()->UpdateSpeakTime(); + } + + switch(type) + { + case CHAT_MSG_SAY: + case CHAT_MSG_EMOTE: + case CHAT_MSG_YELL: + { + std::string msg = ""; + recv_data >> msg; + + if(msg.empty()) + break; + + if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) + break; + + // strip invisible characters for non-addon messages + if (lang != LANG_ADDON && sWorld.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING)) + stripLineInvisibleChars(msg); + + if(msg.empty()) + break; + + if(type == CHAT_MSG_SAY) + GetPlayer()->Say(msg, lang); + else if(type == CHAT_MSG_EMOTE) + GetPlayer()->TextEmote(msg); + else if(type == CHAT_MSG_YELL) + GetPlayer()->Yell(msg, lang); + } break; + + case CHAT_MSG_WHISPER: + { + std::string to, msg; + recv_data >> to; + CHECK_PACKET_SIZE(recv_data,4+4+(to.size()+1)+1); + recv_data >> msg; + + // strip invisible characters for non-addon messages + if (lang != LANG_ADDON && sWorld.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING)) + stripLineInvisibleChars(msg); + + if(msg.empty()) + break; + + if(!normalizePlayerName(to)) + { + WorldPacket data(SMSG_CHAT_PLAYER_NOT_FOUND, (to.size()+1)); + data<GetSession()->GetSecurity() : 0; + if(!player || tSecurity == SEC_PLAYER && pSecurity > SEC_PLAYER && !player->isAcceptWhispers()) + { + WorldPacket data(SMSG_CHAT_PLAYER_NOT_FOUND, (to.size()+1)); + data<GetTeam(); + uint32 sideb = player->GetTeam(); + if( sidea != sideb ) + { + WorldPacket data(SMSG_CHAT_PLAYER_NOT_FOUND, (to.size()+1)); + data<Whisper(msg, lang,player->GetGUID()); + } break; + + case CHAT_MSG_PARTY: + { + std::string msg = ""; + recv_data >> msg; + + if(msg.empty()) + break; + + if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) + break; + + // strip invisible characters for non-addon messages + if (lang != LANG_ADDON && sWorld.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING)) + stripLineInvisibleChars(msg); + + if(msg.empty()) + break; + + Group *group = GetPlayer()->GetGroup(); + if(!group) + return; + + WorldPacket data; + ChatHandler::FillMessageData(&data, this, CHAT_MSG_PARTY, lang, NULL, 0, msg.c_str(),NULL); + group->BroadcastPacket(&data, group->GetMemberGroup(GetPlayer()->GetGUID())); + } + break; + case CHAT_MSG_GUILD: + { + std::string msg = ""; + recv_data >> msg; + + if(msg.empty()) + break; + + if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) + break; + + // strip invisible characters for non-addon messages + if (lang != LANG_ADDON && sWorld.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING)) + stripLineInvisibleChars(msg); + + if(msg.empty()) + break; + + if (GetPlayer()->GetGuildId()) + { + Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + if (guild) + guild->BroadcastToGuild(this, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL); + } + + break; + } + case CHAT_MSG_OFFICER: + { + std::string msg = ""; + recv_data >> msg; + + if(msg.empty()) + break; + + if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) + break; + + // strip invisible characters for non-addon messages + if (lang != LANG_ADDON && sWorld.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING)) + stripLineInvisibleChars(msg); + + if(msg.empty()) + break; + + if (GetPlayer()->GetGuildId()) + { + Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + if (guild) + guild->BroadcastToOfficers(this, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL); + } + break; + } + case CHAT_MSG_RAID: + { + std::string msg=""; + recv_data >> msg; + + if(msg.empty()) + break; + + if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) + break; + + // strip invisible characters for non-addon messages + if (lang != LANG_ADDON && sWorld.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING)) + stripLineInvisibleChars(msg); + + if(msg.empty()) + break; + + Group *group = GetPlayer()->GetGroup(); + if(!group || !group->isRaidGroup()) + return; + + WorldPacket data; + ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID, lang, "", 0, msg.c_str(),NULL); + group->BroadcastPacket(&data); + } break; + case CHAT_MSG_RAID_LEADER: + { + std::string msg=""; + recv_data >> msg; + + if(msg.empty()) + break; + + if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) + break; + + // strip invisible characters for non-addon messages + if (lang != LANG_ADDON && sWorld.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING)) + stripLineInvisibleChars(msg); + + if(msg.empty()) + break; + + Group *group = GetPlayer()->GetGroup(); + if(!group || !group->isRaidGroup() || !group->IsLeader(GetPlayer()->GetGUID())) + return; + + WorldPacket data; + ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_LEADER, lang, "", 0, msg.c_str(),NULL); + group->BroadcastPacket(&data); + } break; + case CHAT_MSG_RAID_WARNING: + { + std::string msg=""; + recv_data >> msg; + + // strip invisible characters for non-addon messages + if (lang != LANG_ADDON && sWorld.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING)) + stripLineInvisibleChars(msg); + + if(msg.empty()) + break; + + Group *group = GetPlayer()->GetGroup(); + if(!group || !group->isRaidGroup() || !(group->IsLeader(GetPlayer()->GetGUID()) || group->IsAssistant(GetPlayer()->GetGUID()))) + return; + + WorldPacket data; + ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_WARNING, lang, "", 0, msg.c_str(),NULL); + group->BroadcastPacket(&data); + } break; + + case CHAT_MSG_BATTLEGROUND: + { + std::string msg=""; + recv_data >> msg; + + // strip invisible characters for non-addon messages + if (lang != LANG_ADDON && sWorld.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING)) + stripLineInvisibleChars(msg); + + if(msg.empty()) + break; + + Group *group = GetPlayer()->GetGroup(); + if(!group || !group->isRaidGroup()) + return; + + WorldPacket data; + ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND, lang, "", 0, msg.c_str(),NULL); + group->BroadcastPacket(&data); + } break; + + case CHAT_MSG_BATTLEGROUND_LEADER: + { + std::string msg=""; + recv_data >> msg; + + // strip invisible characters for non-addon messages + if (lang != LANG_ADDON && sWorld.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING)) + stripLineInvisibleChars(msg); + + if(msg.empty()) + break; + + Group *group = GetPlayer()->GetGroup(); + if(!group || !group->isRaidGroup() || !group->IsLeader(GetPlayer()->GetGUID())) + return; + + WorldPacket data; + ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND_LEADER, lang, "", 0, msg.c_str(),NULL); + group->BroadcastPacket(&data); + } break; + + case CHAT_MSG_CHANNEL: + { + std::string channel = "", msg = ""; + recv_data >> channel; + + // recheck + CHECK_PACKET_SIZE(recv_data,4+4+(channel.size()+1)+1); + + recv_data >> msg; + + // strip invisible characters for non-addon messages + if (lang != LANG_ADDON && sWorld.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING)) + stripLineInvisibleChars(msg); + + if(msg.empty()) + break; + + if(ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + { + if(Channel *chn = cMgr->GetChannel(channel,_player)) + chn->Say(_player->GetGUID(),msg.c_str(),lang); + } + } break; + + case CHAT_MSG_AFK: + { + std::string msg; + recv_data >> msg; + + if((msg.empty() || !_player->isAFK()) && !_player->isInCombat() ) + { + if(!_player->isAFK()) + { + if(msg.empty()) + msg = GetMangosString(LANG_PLAYER_AFK_DEFAULT); + _player->afkMsg = msg; + } + _player->ToggleAFK(); + if(_player->isAFK() && _player->isDND()) + _player->ToggleDND(); + } + } break; + + case CHAT_MSG_DND: + { + std::string msg; + recv_data >> msg; + + if(msg.empty() || !_player->isDND()) + { + if(!_player->isDND()) + { + if(msg.empty()) + msg = GetMangosString(LANG_PLAYER_DND_DEFAULT); + _player->dndMsg = msg; + } + _player->ToggleDND(); + if(_player->isDND() && _player->isAFK()) + _player->ToggleAFK(); + } + } break; + + default: + sLog.outError("CHAT: unknown message type %u, lang: %u", type, lang); + break; + } +} + +void WorldSession::HandleEmoteOpcode( WorldPacket & recv_data ) +{ + if(!GetPlayer()->isAlive()) + return; + CHECK_PACKET_SIZE(recv_data,4); + + uint32 emote; + recv_data >> emote; + GetPlayer()->HandleEmoteCommand(emote); +} + +void WorldSession::HandleTextEmoteOpcode( WorldPacket & recv_data ) +{ + if(!GetPlayer()->isAlive()) + return; + + if (!GetPlayer()->CanSpeak()) + { + std::string timeStr = secsToTimeString(m_muteTime - time(NULL)); + SendNotification(GetMangosString(LANG_WAIT_BEFORE_SPEAKING),timeStr.c_str()); + return; + } + + CHECK_PACKET_SIZE(recv_data,4+4+8); + + uint32 text_emote, emoteNum; + uint64 guid; + + recv_data >> text_emote; + recv_data >> emoteNum; + recv_data >> guid; + + const char *nam = 0; + uint32 namlen = 1; + + Unit* unit = ObjectAccessor::GetUnit(*_player, guid); + Creature *pCreature = dynamic_cast(unit); + if(unit) + { + nam = unit->GetName(); + namlen = (nam ? strlen(nam) : 0) + 1; + } + + EmotesTextEntry const *em = sEmotesTextStore.LookupEntry(text_emote); + if (em) + { + uint32 emote_anim = em->textid; + + WorldPacket data; + + switch(emote_anim) + { + case EMOTE_STATE_SLEEP: + case EMOTE_STATE_SIT: + case EMOTE_STATE_KNEEL: + case EMOTE_ONESHOT_NONE: + break; + default: + GetPlayer()->HandleEmoteCommand(emote_anim); + break; + } + + data.Initialize(SMSG_TEXT_EMOTE, (20+namlen)); + data << GetPlayer()->GetGUID(); + data << (uint32)text_emote; + data << emoteNum; + data << (uint32)namlen; + if( namlen > 1 ) + { + data.append(nam, namlen); + } + else + { + data << (uint8)0x00; + } + + GetPlayer()->SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),true); + + //Send scripted event call + if (pCreature && Script) + Script->ReceiveEmote(GetPlayer(),pCreature,text_emote); + } +} + +void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recv_data ) +{ + CHECK_PACKET_SIZE(recv_data, 8+1); + + uint64 iguid; + uint8 unk; + //sLog.outDebug("WORLD: Received CMSG_CHAT_IGNORED"); + + recv_data >> iguid; + recv_data >> unk; // probably related to spam reporting + + Player *player = objmgr.GetPlayer(iguid); + if(!player || !player->GetSession()) + return; + + WorldPacket data; + ChatHandler::FillMessageData(&data, this, CHAT_MSG_IGNORED, LANG_UNIVERSAL, NULL, GetPlayer()->GetGUID(), GetPlayer()->GetName(),NULL); + player->GetSession()->SendPacket(&data); +} diff --git a/src/game/CombatHandler.cpp b/src/game/CombatHandler.cpp new file mode 100644 index 00000000000..047c639e44e --- /dev/null +++ b/src/game/CombatHandler.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Log.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "World.h" +#include "ObjectAccessor.h" +#include "CreatureAI.h" +#include "ObjectDefines.h" + +void WorldSession::HandleAttackSwingOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8); + + uint64 guid; + recv_data >> guid; + + DEBUG_LOG( "WORLD: Recvd CMSG_ATTACKSWING Message guidlow:%u guidhigh:%u", GUID_LOPART(guid), GUID_HIPART(guid) ); + + Unit *pEnemy = ObjectAccessor::GetUnit(*_player, guid); + + if(!pEnemy) + { + if(!IS_UNIT_GUID(guid)) + sLog.outError("WORLD: Object %u (TypeID: %u) isn't player, pet or creature",GUID_LOPART(guid),GuidHigh2TypeId(GUID_HIPART(guid))); + else + sLog.outError( "WORLD: Enemy %s %u not found",GetLogNameForGuid(guid),GUID_LOPART(guid)); + + // stop attack state at client + SendAttackStop(NULL); + return; + } + + if(_player->IsFriendlyTo(pEnemy) || pEnemy->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE)) + { + sLog.outError( "WORLD: Enemy %s %u is friendly",(IS_PLAYER_GUID(guid) ? "player" : "creature"),GUID_LOPART(guid)); + + // stop attack state at client + SendAttackStop(pEnemy); + return; + } + + if(!pEnemy->isAlive()) + { + // client can generate swing to known dead target if autoswitch between autoshot and autohit is enabled in client options + // stop attack state at client + SendAttackStop(pEnemy); + return; + } + + _player->Attack(pEnemy,true); +} + +void WorldSession::HandleAttackStopOpcode( WorldPacket & /*recv_data*/ ) +{ + GetPlayer()->AttackStop(); +} + +void WorldSession::HandleSetSheathedOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,4); + + uint32 sheathed; + recv_data >> sheathed; + + //sLog.outDebug( "WORLD: Recvd CMSG_SETSHEATHED Message guidlow:%u value1:%u", GetPlayer()->GetGUIDLow(), sheathed ); + + GetPlayer()->SetSheath(sheathed); +} + +void WorldSession::SendAttackStop(Unit const* enemy) +{ + WorldPacket data( SMSG_ATTACKSTOP, (4+20) ); // we guess size + data.append(GetPlayer()->GetPackGUID()); + data.append(enemy ? enemy->GetPackGUID() : 0); // must be packed guid + data << uint32(0); // unk, can be 1 also + SendPacket(&data); +} diff --git a/src/game/ConfusedMovementGenerator.cpp b/src/game/ConfusedMovementGenerator.cpp new file mode 100644 index 00000000000..f1e7c2c1548 --- /dev/null +++ b/src/game/ConfusedMovementGenerator.cpp @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Creature.h" +#include "MapManager.h" +#include "Opcodes.h" +#include "ConfusedMovementGenerator.h" +#include "DestinationHolderImp.h" + +template +void +ConfusedMovementGenerator::Initialize(T &unit) +{ + const float wander_distance=11; + float x,y,z; + x = unit.GetPositionX(); + y = unit.GetPositionY(); + z = unit.GetPositionZ(); + uint32 mapid=unit.GetMapId(); + + Map const* map = MapManager::Instance().GetBaseMap(mapid); + + i_nextMove = 1; + + bool is_water_ok, is_land_ok; + _InitSpecific(unit, is_water_ok, is_land_ok); + + for(unsigned int idx=0; idx < MAX_CONF_WAYPOINTS+1; ++idx) + { + const float wanderX=wander_distance*rand_norm() - wander_distance/2; + const float wanderY=wander_distance*rand_norm() - wander_distance/2; + + i_waypoints[idx][0] = x + wanderX; + i_waypoints[idx][1] = y + wanderY; + + // prevent invalid coordinates generation + MaNGOS::NormalizeMapCoord(i_waypoints[idx][0]); + MaNGOS::NormalizeMapCoord(i_waypoints[idx][1]); + + bool is_water = map->IsInWater(i_waypoints[idx][0],i_waypoints[idx][1],z); + // if generated wrong path just ignore + if( is_water && !is_water_ok || !is_water && !is_land_ok ) + { + i_waypoints[idx][0] = idx > 0 ? i_waypoints[idx-1][0] : x; + i_waypoints[idx][1] = idx > 0 ? i_waypoints[idx-1][1] : y; + } + unit.UpdateGroundPositionZ(i_waypoints[idx][0],i_waypoints[idx][1],z); + i_waypoints[idx][2] = z; + } + + unit.StopMoving(); + unit.RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + unit.addUnitState(UNIT_STAT_CONFUSED); +} + +template<> +void +ConfusedMovementGenerator::_InitSpecific(Creature &creature, bool &is_water_ok, bool &is_land_ok) +{ + is_water_ok = creature.canSwim(); + is_land_ok = creature.canWalk(); +} + +template<> +void +ConfusedMovementGenerator::_InitSpecific(Player &, bool &is_water_ok, bool &is_land_ok) +{ + is_water_ok = true; + is_land_ok = true; +} + +template +void +ConfusedMovementGenerator::Reset(T &unit) +{ + i_nextMove = 1; + i_nextMoveTime.Reset(0); + i_destinationHolder.ResetUpdate(); + unit.StopMoving(); +} + +template +bool +ConfusedMovementGenerator::Update(T &unit, const uint32 &diff) +{ + if(!&unit) + return true; + + if(unit.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED | UNIT_STAT_DISTRACTED)) + return true; + + if( i_nextMoveTime.Passed() ) + { + // currently moving, update location + Traveller traveller(unit); + if( i_destinationHolder.UpdateTraveller(traveller, diff, false)) + { + if( i_destinationHolder.HasArrived()) + { + // arrived, stop and wait a bit + unit.StopMoving(); + + i_nextMove = urand(1,MAX_CONF_WAYPOINTS); + i_nextMoveTime.Reset(urand(0, 1500-1)); // TODO: check the minimum reset time, should be probably higher + } + } + } + else + { + // waiting for next move + i_nextMoveTime.Update(diff); + if( i_nextMoveTime.Passed() ) + { + // start moving + assert( i_nextMove <= MAX_CONF_WAYPOINTS ); + const float x = i_waypoints[i_nextMove][0]; + const float y = i_waypoints[i_nextMove][1]; + const float z = i_waypoints[i_nextMove][2]; + Traveller traveller(unit); + i_destinationHolder.SetDestination(traveller, x, y, z); + } + } + return true; +} + +template +void +ConfusedMovementGenerator::Finalize(T &unit) +{ + unit.clearUnitState(UNIT_STAT_CONFUSED); +} + +template void ConfusedMovementGenerator::Initialize(Player &player); +template void ConfusedMovementGenerator::Initialize(Creature &creature); +template void ConfusedMovementGenerator::Finalize(Player &player); +template void ConfusedMovementGenerator::Finalize(Creature &creature); +template void ConfusedMovementGenerator::Reset(Player &player); +template void ConfusedMovementGenerator::Reset(Creature &creature); +template bool ConfusedMovementGenerator::Update(Player &player, const uint32 &diff); +template bool ConfusedMovementGenerator::Update(Creature &creature, const uint32 &diff); diff --git a/src/game/ConfusedMovementGenerator.h b/src/game/ConfusedMovementGenerator.h new file mode 100644 index 00000000000..78955297395 --- /dev/null +++ b/src/game/ConfusedMovementGenerator.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_RANDOMMOTIONGENERATOR_H +#define MANGOS_RANDOMMOTIONGENERATOR_H + +#include "MovementGenerator.h" +#include "DestinationHolder.h" +#include "Traveller.h" + +#define MAX_CONF_WAYPOINTS 24 + +template +class MANGOS_DLL_SPEC ConfusedMovementGenerator +: public MovementGeneratorMedium< T, ConfusedMovementGenerator > +{ + public: + explicit ConfusedMovementGenerator() : i_nextMoveTime(0) {} + + void Initialize(T &); + void Finalize(T &); + void Reset(T &); + bool Update(T &, const uint32 &); + + MovementGeneratorType GetMovementGeneratorType() { return CONFUSED_MOTION_TYPE; } + private: + void _InitSpecific(T &, bool &, bool &); + TimeTracker i_nextMoveTime; + float i_waypoints[MAX_CONF_WAYPOINTS+1][3]; + DestinationHolder< Traveller > i_destinationHolder; + uint32 i_nextMove; +}; +#endif diff --git a/src/game/Corpse.cpp b/src/game/Corpse.cpp new file mode 100644 index 00000000000..785c6b4f784 --- /dev/null +++ b/src/game/Corpse.cpp @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Corpse.h" +#include "Player.h" +#include "UpdateMask.h" +#include "MapManager.h" +#include "ObjectAccessor.h" +#include "Database/DatabaseEnv.h" +#include "Opcodes.h" +#include "WorldSession.h" +#include "WorldPacket.h" +#include "GossipDef.h" +#include "World.h" + +Corpse::Corpse(CorpseType type) : WorldObject() +{ + m_objectType |= TYPEMASK_CORPSE; + m_objectTypeId = TYPEID_CORPSE; + // 2.3.2 - 0x58 + m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HASPOSITION); + + m_valuesCount = CORPSE_END; + + m_type = type; + + m_time = time(NULL); + + lootForBody = false; +} + +Corpse::~Corpse() +{ +} + +void Corpse::AddToWorld() +{ + ///- Register the corpse for guid lookup + if(!IsInWorld()) ObjectAccessor::Instance().AddObject(this); + Object::AddToWorld(); +} + +void Corpse::RemoveFromWorld() +{ + ///- Remove the corpse from the accessor + if(IsInWorld()) ObjectAccessor::Instance().RemoveObject(this); + Object::RemoveFromWorld(); +} + +bool Corpse::Create( uint32 guidlow ) +{ + Object::_Create(guidlow, 0, HIGHGUID_CORPSE); + return true; +} + +bool Corpse::Create( uint32 guidlow, Player *owner, uint32 mapid, float x, float y, float z, float ang ) +{ + SetInstanceId(owner->GetInstanceId()); + + WorldObject::_Create(guidlow, HIGHGUID_CORPSE, mapid); + + Relocate(x,y,z,ang); + + if(!IsPositionValid()) + { + sLog.outError("ERROR: Corpse (guidlow %d, owner %s) not created. Suggested coordinates isn't valid (X: %d Y: ^%d)",guidlow,owner->GetName(),x,y); + return false; + } + + SetFloatValue( OBJECT_FIELD_SCALE_X, 1 ); + SetFloatValue( CORPSE_FIELD_POS_X, x ); + SetFloatValue( CORPSE_FIELD_POS_Y, y ); + SetFloatValue( CORPSE_FIELD_POS_Z, z ); + SetFloatValue( CORPSE_FIELD_FACING, ang ); + SetUInt64Value( CORPSE_FIELD_OWNER, owner->GetGUID() ); + + m_grid = MaNGOS::ComputeGridPair(GetPositionX(), GetPositionY()); + + return true; +} + +void Corpse::SaveToDB() +{ + // prevent DB data inconsistance problems and duplicates + CharacterDatabase.BeginTransaction(); + DeleteFromDB(); + + std::ostringstream ss; + ss << "INSERT INTO corpse (guid,player,position_x,position_y,position_z,orientation,zone,map,data,time,corpse_type,instance) VALUES (" + << GetGUIDLow() << ", " << GUID_LOPART(GetOwnerGUID()) << ", " << GetPositionX() << ", " << GetPositionY() << ", " << GetPositionZ() << ", " + << GetOrientation() << ", " << GetZoneId() << ", " << GetMapId() << ", '"; + for(uint16 i = 0; i < m_valuesCount; i++ ) + ss << GetUInt32Value(i) << " "; + ss << "'," << uint64(m_time) <<", " << uint32(GetType()) << ", " << int(GetInstanceId()) << ")"; + CharacterDatabase.Execute( ss.str().c_str() ); + CharacterDatabase.CommitTransaction(); +} + +void Corpse::DeleteBonesFromWorld() +{ + assert(GetType()==CORPSE_BONES); + Corpse* corpse = ObjectAccessor::GetCorpse(*this, GetGUID()); + + if (!corpse) + { + sLog.outError("Bones %u not found in world.", GetGUIDLow()); + return; + } + + AddObjectToRemoveList(); +} + +void Corpse::DeleteFromDB() +{ + if(GetType() == CORPSE_BONES) + // only specific bones + CharacterDatabase.PExecute("DELETE FROM corpse WHERE guid = '%d'", GetGUIDLow()); + else + // all corpses (not bones) + CharacterDatabase.PExecute("DELETE FROM corpse WHERE player = '%d' AND corpse_type <> '0'", GUID_LOPART(GetOwnerGUID())); +} + +bool Corpse::LoadFromDB(uint32 guid, QueryResult *result, uint32 InstanceId) +{ + bool external = (result != NULL); + if (!external) + // 0 1 2 3 4 5 6 7 8 + result = CharacterDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map,data,time,corpse_type,instance FROM corpse WHERE guid = '%u'",guid); + + if( ! result ) + { + sLog.outError("ERROR: Corpse (GUID: %u) not found in table `corpse`, can't load. ",guid); + return false; + } + + Field *fields = result->Fetch(); + + if(!LoadFromDB(guid,fields)) + { + if (!external) delete result; + return false; + } + + if (!external) delete result; + return true; +} + +bool Corpse::LoadFromDB(uint32 guid, Field *fields) +{ + // 0 1 2 3 4 5 6 7 8 + //result = CharacterDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map,data,time,corpse_type,instance FROM corpse WHERE guid = '%u'",guid); + float positionX = fields[0].GetFloat(); + float positionY = fields[1].GetFloat(); + float positionZ = fields[2].GetFloat(); + float ort = fields[3].GetFloat(); + uint32 mapid = fields[4].GetUInt32(); + + if(!LoadValues( fields[5].GetString() )) + { + sLog.outError("ERROR: Corpse #%d have broken data in `data` field. Can't be loaded.",guid); + return false; + } + + m_time = time_t(fields[6].GetUInt64()); + m_type = CorpseType(fields[7].GetUInt32()); + if(m_type >= MAX_CORPSE_TYPE) + { + sLog.outError("ERROR: Corpse (guidlow %d, owner %d) have wrong corpse type, not load.",GetGUIDLow(),GUID_LOPART(GetOwnerGUID())); + return false; + } + uint32 instanceid = fields[8].GetUInt32(); + + // overwrite possible wrong/corrupted guid + SetUInt64Value(OBJECT_FIELD_GUID, MAKE_NEW_GUID(guid, 0, HIGHGUID_CORPSE)); + + // place + SetInstanceId(instanceid); + SetMapId(mapid); + Relocate(positionX,positionY,positionZ,ort); + + if(!IsPositionValid()) + { + sLog.outError("ERROR: Corpse (guidlow %d, owner %d) not created. Suggested coordinates isn't valid (X: %d Y: ^%d)",GetGUIDLow(),GUID_LOPART(GetOwnerGUID()),GetPositionX(),GetPositionY()); + return false; + } + + m_grid = MaNGOS::ComputeGridPair(GetPositionX(), GetPositionY()); + + return true; +} + +bool Corpse::isVisibleForInState(Player const* u, bool inVisibleList) const +{ + return IsInWorld() && u->IsInWorld() && IsWithinDistInMap(u,World::GetMaxVisibleDistanceForObject()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f)); +} diff --git a/src/game/Corpse.h b/src/game/Corpse.h new file mode 100644 index 00000000000..f99523779a7 --- /dev/null +++ b/src/game/Corpse.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOSSERVER_CORPSE_H +#define MANGOSSERVER_CORPSE_H + +#include "Object.h" +#include "Database/DatabaseEnv.h" +#include "GridDefines.h" +#include "LootMgr.h" + +enum CorpseType +{ + CORPSE_BONES = 0, + CORPSE_RESURRECTABLE_PVE = 1, + CORPSE_RESURRECTABLE_PVP = 2 +}; +#define MAX_CORPSE_TYPE 3 + +// Value equal client resurrection dialog show radius. +#define CORPSE_RECLAIM_RADIUS 39 + +enum CorpseFlags +{ + CORPSE_FLAG_NONE = 0x00, + CORPSE_FLAG_BONES = 0x01, + CORPSE_FLAG_UNK1 = 0x02, + CORPSE_FLAG_UNK2 = 0x04, + CORPSE_FLAG_HIDE_HELM = 0x08, + CORPSE_FLAG_HIDE_CLOAK = 0x10, + CORPSE_FLAG_LOOTABLE = 0x20 +}; + +class Corpse : public WorldObject +{ + public: + explicit Corpse( CorpseType type = CORPSE_BONES ); + ~Corpse( ); + + void AddToWorld(); + void RemoveFromWorld(); + + bool Create( uint32 guidlow ); + bool Create( uint32 guidlow, Player *owner, uint32 mapid, float x, float y, float z, float ang ); + + void SaveToDB(); + bool LoadFromDB(uint32 guid, QueryResult *result, uint32 InstanceId); + bool LoadFromDB(uint32 guid, Field *fields); + + void DeleteBonesFromWorld(); + void DeleteFromDB(); + + uint64 const& GetOwnerGUID() const { return GetUInt64Value(CORPSE_FIELD_OWNER); } + + time_t const& GetGhostTime() const { return m_time; } + void ResetGhostTime() { m_time = time(NULL); } + CorpseType GetType() const { return m_type; } + + GridPair const& GetGrid() const { return m_grid; } + void SetGrid(GridPair const& grid) { m_grid = grid; } + + bool isVisibleForInState(Player const* u, bool inVisibleList) const; + + Loot loot; // remove insignia ONLY at BG + Player* lootRecipient; + bool lootForBody; + + void Say(const char* text, uint32 language, uint64 TargetGuid) { MonsterSay(text,language,TargetGuid); } + void Yell(const char* text, uint32 language, uint64 TargetGuid) { MonsterYell(text,language,TargetGuid); } + void TextEmote(const char* text, uint64 TargetGuid) { MonsterTextEmote(text,TargetGuid); } + void Whisper(const char* text, uint64 receiver) { MonsterWhisper(text,receiver); } + void Say(int32 textId, uint32 language, uint64 TargetGuid) { MonsterSay(textId,language,TargetGuid); } + void Yell(int32 textId, uint32 language, uint64 TargetGuid) { MonsterYell(textId,language,TargetGuid); } + void TextEmote(int32 textId, uint64 TargetGuid) { MonsterTextEmote(textId,TargetGuid); } + void Whisper(int32 textId,uint64 receiver) { MonsterWhisper(textId,receiver); } + + GridReference &GetGridRef() { return m_gridRef; } + private: + GridReference m_gridRef; + + CorpseType m_type; + time_t m_time; + GridPair m_grid; // gride for corpse position for fast search +}; +#endif diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp new file mode 100644 index 00000000000..bab0c16b4e9 --- /dev/null +++ b/src/game/Creature.cpp @@ -0,0 +1,1993 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "World.h" +#include "ObjectMgr.h" +#include "SpellMgr.h" +#include "Creature.h" +#include "QuestDef.h" +#include "GossipDef.h" +#include "Player.h" +#include "Opcodes.h" +#include "Log.h" +#include "LootMgr.h" +#include "MapManager.h" +#include "CreatureAI.h" +#include "CreatureAISelector.h" +#include "Formulas.h" +#include "SpellAuras.h" +#include "WaypointMovementGenerator.h" +#include "InstanceData.h" +#include "BattleGround.h" +#include "Util.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" +#include "CellImpl.h" + +// apply implementation of the singletons +#include "Policies/SingletonImp.h" + +Creature::Creature() : +Unit(), i_AI(NULL), +lootForPickPocketed(false), lootForBody(false), m_groupLootTimer(0), lootingGroupLeaderGUID(0), +m_itemsLoaded(false), m_trainerSpellsLoaded(false), m_trainer_type(0), m_lootMoney(0), m_lootRecipient(0), +m_deathTimer(0), m_respawnTime(0), m_respawnDelay(25), m_corpseDelay(60), m_respawnradius(0.0f), +m_gossipOptionLoaded(false),m_NPCTextId(0), m_emoteState(0), m_isPet(false), m_isTotem(false), +m_regenTimer(2000), m_defaultMovementType(IDLE_MOTION_TYPE), m_equipmentId(0), +m_AlreadyCallAssistence(false), m_regenHealth(true), m_AI_locked(false), m_isDeadByDefault(false), +m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL),m_creatureInfo(NULL) +{ + m_valuesCount = UNIT_END; + + for(int i =0; i<4; ++i) + m_spells[i] = 0; + + m_CreatureSpellCooldowns.clear(); + m_CreatureCategoryCooldowns.clear(); + m_GlobalCooldown = 0; + m_unit_movement_flags = MOVEMENTFLAG_WALK_MODE; +} + +Creature::~Creature() +{ + CleanupsBeforeDelete(); + + m_trainer_spells.clear(); + m_vendor_items.clear(); + + delete i_AI; + i_AI = NULL; +} + +void Creature::AddToWorld() +{ + ///- Register the creature for guid lookup + if(!IsInWorld()) ObjectAccessor::Instance().AddObject(this); + Unit::AddToWorld(); +} + +void Creature::RemoveFromWorld() +{ + ///- Remove the creature from the accessor + if(IsInWorld()) ObjectAccessor::Instance().RemoveObject(this); + Unit::RemoveFromWorld(); +} + +void Creature::LoadTrainerSpells() +{ + if(m_trainerSpellsLoaded) + return; + + m_trainer_spells.clear(); + m_trainer_type = 0; + + Field *fields; + QueryResult *result = WorldDatabase.PQuery("SELECT spell,spellcost,reqskill,reqskillvalue,reqlevel FROM npc_trainer WHERE entry = '%u'", GetEntry()); + + if(!result) + return; + + do + { + fields = result->Fetch(); + + uint32 spellid = fields[0].GetUInt32(); + SpellEntry const *spellinfo = sSpellStore.LookupEntry(spellid); + + if(!spellinfo) + { + sLog.outErrorDb("Trainer (Entry: %u ) has non existing spell %u",GetEntry(),spellid); + continue; + } + + if(!SpellMgr::IsSpellValid(spellinfo)) + { + sLog.outErrorDb("LoadTrainerSpells: Trainer (Entry: %u) has broken learning spell %u.", GetEntry(), spellid); + continue; + } + + if(SpellMgr::IsProfessionSpell(spellinfo->Id)) + m_trainer_type = 2; + + TrainerSpell tspell; + tspell.spell = spellinfo; + tspell.spellcost = fields[1].GetUInt32(); + tspell.reqskill = fields[2].GetUInt32(); + tspell.reqskillvalue= fields[3].GetUInt32(); + tspell.reqlevel = fields[4].GetUInt32(); + + m_trainer_spells.push_back(tspell); + + } while( result->NextRow() ); + + delete result; + + m_trainerSpellsLoaded = true; +} + +void Creature::RemoveCorpse() +{ + if( getDeathState()!=CORPSE && !m_isDeadByDefault || getDeathState()!=ALIVE && m_isDeadByDefault ) + return; + + m_deathTimer = 0; + setDeathState(DEAD); + ObjectAccessor::UpdateObjectVisibility(this); + loot.clear(); + m_respawnTime = time(NULL) + m_respawnDelay; + + float x,y,z,o; + GetRespawnCoord(x, y, z, &o); + MapManager::Instance().GetMap(GetMapId(), this)->CreatureRelocation(this,x,y,z,o); +} + +/** + * change the entry of creature until respawn + */ +bool Creature::InitEntry(uint32 Entry, uint32 team, const CreatureData *data ) +{ + CreatureInfo const *normalInfo = objmgr.GetCreatureTemplate(Entry); + if(!normalInfo) + { + sLog.outErrorDb("Creature::UpdateEntry creature entry %u does not exist.", Entry); + return false; + } + + // get heroic mode entry + uint32 actualEntry = Entry; + CreatureInfo const *cinfo = normalInfo; + if(normalInfo->HeroicEntry) + { + Map *map = MapManager::Instance().FindMap(GetMapId(), GetInstanceId()); + if(map && map->IsHeroic()) + { + cinfo = objmgr.GetCreatureTemplate(normalInfo->HeroicEntry); + if(!cinfo) + { + sLog.outErrorDb("Creature::UpdateEntry creature heroic entry %u does not exist.", actualEntry); + return false; + } + } + } + + SetUInt32Value(OBJECT_FIELD_ENTRY, Entry); // normal entry always + m_creatureInfo = cinfo; // map mode related always + + if (cinfo->DisplayID_A == 0 || cinfo->DisplayID_H == 0) // Cancel load if no model defined + { + sLog.outErrorDb("Creature (Entry: %u) has no model defined for Horde or Alliance in table `creature_template`, can't load. ",Entry); + return false; + } + + uint32 display_id = objmgr.ChooseDisplayId(team, GetCreatureInfo(), data); + CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id); + if (!minfo) + { + sLog.outErrorDb("Creature (Entry: %u) has model %u not found in table `creature_model_info`, can't load. ", Entry, display_id); + return false; + } + else + display_id = minfo->modelid; // it can be different (for another gender) + + SetDisplayId(display_id); + SetNativeDisplayId(display_id); + SetByteValue(UNIT_FIELD_BYTES_0, 2, minfo->gender); + + // Load creature equipment + if(!data || data->equipmentId == 0) + { // use default from the template + LoadEquipment(cinfo->equipmentId); + } + else if(data && data->equipmentId != -1) + { // override, -1 means no equipment + LoadEquipment(data->equipmentId); + } + + SetName(normalInfo->Name); // at normal entry always + + SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS,minfo->bounding_radius); + SetFloatValue(UNIT_FIELD_COMBATREACH,minfo->combat_reach ); + + SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0f); + + SetSpeed(MOVE_WALK, cinfo->speed ); + SetSpeed(MOVE_RUN, cinfo->speed ); + SetSpeed(MOVE_SWIM, cinfo->speed ); + + SetFloatValue(OBJECT_FIELD_SCALE_X, cinfo->scale); + + // checked at loading + m_defaultMovementType = MovementGeneratorType(cinfo->MovementType); + if(!m_respawnradius && m_defaultMovementType==RANDOM_MOTION_TYPE) + m_defaultMovementType = IDLE_MOTION_TYPE; + + return true; +} + +bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData *data ) +{ + if(!InitEntry(Entry,team,data)) + return false; + + m_regenHealth = GetCreatureInfo()->RegenHealth; + + // creatures always have melee weapon ready if any + SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE ); + SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_AURAS ); + + SelectLevel(GetCreatureInfo()); + if (team == HORDE) + SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, GetCreatureInfo()->faction_H); + else + SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, GetCreatureInfo()->faction_A); + + SetUInt32Value(UNIT_NPC_FLAGS,GetCreatureInfo()->npcflag); + + SetAttackTime(BASE_ATTACK, GetCreatureInfo()->baseattacktime); + SetAttackTime(OFF_ATTACK, GetCreatureInfo()->baseattacktime); + SetAttackTime(RANGED_ATTACK,GetCreatureInfo()->rangeattacktime); + + SetUInt32Value(UNIT_FIELD_FLAGS,GetCreatureInfo()->Flags); + SetUInt32Value(UNIT_DYNAMIC_FLAGS,GetCreatureInfo()->dynamicflags); + + SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(GetCreatureInfo()->armor)); + SetModifierValue(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(GetCreatureInfo()->resistance1)); + SetModifierValue(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(GetCreatureInfo()->resistance2)); + SetModifierValue(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(GetCreatureInfo()->resistance3)); + SetModifierValue(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(GetCreatureInfo()->resistance4)); + SetModifierValue(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(GetCreatureInfo()->resistance5)); + SetModifierValue(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(GetCreatureInfo()->resistance6)); + + SetCanModifyStats(true); + UpdateAllStats(); + + FactionTemplateEntry const* factionTemplate = sFactionTemplateStore.LookupEntry(GetCreatureInfo()->faction_A); + if (factionTemplate) // check and error show at loading templates + { + FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionTemplate->faction); + if (factionEntry) + if( !(GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_CIVILIAN) && + (factionEntry->team == ALLIANCE || factionEntry->team == HORDE) ) + SetPvP(true); + } + + m_spells[0] = GetCreatureInfo()->spell1; + m_spells[1] = GetCreatureInfo()->spell2; + m_spells[2] = GetCreatureInfo()->spell3; + m_spells[3] = GetCreatureInfo()->spell4; + + return true; +} + +void Creature::Update(uint32 diff) +{ + if(m_GlobalCooldown <= diff) + m_GlobalCooldown = 0; + else + m_GlobalCooldown -= diff; + + switch( m_deathState ) + { + case JUST_ALIVED: + // Dont must be called, see Creature::setDeathState JUST_ALIVED -> ALIVE promoting. + sLog.outError("Creature (GUIDLow: %u Entry: %u ) in wrong state: JUST_ALIVED (4)",GetGUIDLow(),GetEntry()); + break; + case JUST_DIED: + // Dont must be called, see Creature::setDeathState JUST_DIED -> CORPSE promoting. + sLog.outError("Creature (GUIDLow: %u Entry: %u ) in wrong state: JUST_DEAD (1)",GetGUIDLow(),GetEntry()); + break; + case DEAD: + { + if( m_respawnTime <= time(NULL) ) + { + DEBUG_LOG("Respawning..."); + m_respawnTime = 0; + lootForPickPocketed = false; + lootForBody = false; + + if(m_originalEntry != GetUInt32Value(OBJECT_FIELD_ENTRY)) + UpdateEntry(m_originalEntry); + + CreatureInfo const *cinfo = GetCreatureInfo(); + + SelectLevel(cinfo); + SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0); + if (m_isDeadByDefault) + { + setDeathState(JUST_DIED); + SetHealth(0); + i_motionMaster.Clear(); + clearUnitState(UNIT_STAT_ALL_STATE); + LoadCreaturesAddon(true); + } + else + setDeathState( JUST_ALIVED ); + + //Call AI respawn virtual function + i_AI->JustRespawned(); + + MapManager::Instance().GetMap(GetMapId(), this)->Add(this); + } + break; + } + case CORPSE: + { + if (m_isDeadByDefault) + break; + + if( m_deathTimer <= diff ) + { + RemoveCorpse(); + DEBUG_LOG("Removing corpse... %u ", GetUInt32Value(OBJECT_FIELD_ENTRY)); + } + else + { + m_deathTimer -= diff; + if (m_groupLootTimer && lootingGroupLeaderGUID) + { + if(diff <= m_groupLootTimer) + { + m_groupLootTimer -= diff; + } + else + { + Group* group = objmgr.GetGroupByLeader(lootingGroupLeaderGUID); + if (group) + group->EndRoll(); + m_groupLootTimer = 0; + lootingGroupLeaderGUID = 0; + } + } + } + + break; + } + case ALIVE: + { + if (m_isDeadByDefault) + { + if( m_deathTimer <= diff ) + { + RemoveCorpse(); + DEBUG_LOG("Removing alive corpse... %u ", GetUInt32Value(OBJECT_FIELD_ENTRY)); + } + else + { + m_deathTimer -= diff; + } + } + + Unit::Update( diff ); + + // creature can be dead after Unit::Update call + // CORPSE/DEAD state will processed at next tick (in other case death timer will be updated unexpectedly) + if(!isAlive()) + break; + + if(!IsInEvadeMode()) + { + // do not allow the AI to be changed during update + m_AI_locked = true; + i_AI->UpdateAI(diff); + m_AI_locked = false; + } + + // creature can be dead after UpdateAI call + // CORPSE/DEAD state will processed at next tick (in other case death timer will be updated unexpectedly) + if(!isAlive()) + break; + if(m_regenTimer > 0) + { + if(diff >= m_regenTimer) + m_regenTimer = 0; + else + m_regenTimer -= diff; + } + if (m_regenTimer != 0) + break; + + if (!isInCombat() || IsPolymorphed()) + RegenerateHealth(); + + RegenerateMana(); + + m_regenTimer = 2000; + break; + } + default: + break; + } +} + +void Creature::RegenerateMana() +{ + uint32 curValue = GetPower(POWER_MANA); + uint32 maxValue = GetMaxPower(POWER_MANA); + + if (curValue >= maxValue) + return; + + uint32 addvalue = 0; + + // Combat and any controlled creature + if (isInCombat() || GetCharmerOrOwnerGUID()) + { + if(!IsUnderLastManaUseEffect()) + { + float ManaIncreaseRate = sWorld.getRate(RATE_POWER_MANA); + float Spirit = GetStat(STAT_SPIRIT); + + addvalue = uint32((Spirit/5.0f + 17.0f) * ManaIncreaseRate); + } + } + else + addvalue = maxValue/3; + + ModifyPower(POWER_MANA, addvalue); +} + +void Creature::RegenerateHealth() +{ + if (!isRegeneratingHealth()) + return; + + uint32 curValue = GetHealth(); + uint32 maxValue = GetMaxHealth(); + + if (curValue >= maxValue) + return; + + uint32 addvalue = 0; + + // Not only pet, but any controelled creature + if(GetCharmerOrOwnerGUID()) + { + float HealthIncreaseRate = sWorld.getRate(RATE_HEALTH); + float Spirit = GetStat(STAT_SPIRIT); + + if( GetPower(POWER_MANA) > 0 ) + addvalue = uint32(Spirit * 0.25 * HealthIncreaseRate); + else + addvalue = uint32(Spirit * 0.80 * HealthIncreaseRate); + } + else + addvalue = maxValue/3; + + ModifyHealth(addvalue); +} + +bool Creature::AIM_Initialize() +{ + // make sure nothing can change the AI during AI update + if(m_AI_locked) + { + sLog.outDebug("AIM_Initialize: failed to init, locked."); + return false; + } + + CreatureAI * oldAI = i_AI; + i_motionMaster.Initialize(); + i_AI = FactorySelector::selectAI(this); + if (oldAI) + delete oldAI; + return true; +} + +bool Creature::Create (uint32 guidlow, Map *map, uint32 Entry, uint32 team, const CreatureData *data) +{ + SetMapId(map->GetId()); + SetInstanceId(map->GetInstanceId()); + + //oX = x; oY = y; dX = x; dY = y; m_moveTime = 0; m_startMove = 0; + const bool bResult = CreateFromProto(guidlow, Entry, team, data); + + if (bResult) + { + switch (GetCreatureInfo()->rank) + { + case CREATURE_ELITE_RARE: + m_corpseDelay = sWorld.getConfig(CONFIG_CORPSE_DECAY_RARE); + break; + case CREATURE_ELITE_ELITE: + m_corpseDelay = sWorld.getConfig(CONFIG_CORPSE_DECAY_ELITE); + break; + case CREATURE_ELITE_RAREELITE: + m_corpseDelay = sWorld.getConfig(CONFIG_CORPSE_DECAY_RAREELITE); + break; + case CREATURE_ELITE_WORLDBOSS: + m_corpseDelay = sWorld.getConfig(CONFIG_CORPSE_DECAY_WORLDBOSS); + break; + default: + m_corpseDelay = sWorld.getConfig(CONFIG_CORPSE_DECAY_NORMAL); + break; + } + } + + return bResult; +} + +bool Creature::isCanTrainingOf(Player* pPlayer, bool msg) const +{ + if(!isTrainer()) + return false; + + if(m_trainer_spells.empty()) + { + sLog.outErrorDb("Creature %u (Entry: %u) have UNIT_NPC_FLAG_TRAINER but have empty trainer spell list.", + GetGUIDLow(),GetEntry()); + return false; + } + + switch(GetCreatureInfo()->trainer_type) + { + case TRAINER_TYPE_CLASS: + if(pPlayer->getClass()!=GetCreatureInfo()->classNum) + { + if(msg) + { + pPlayer->PlayerTalkClass->ClearMenus(); + switch(GetCreatureInfo()->classNum) + { + case CLASS_DRUID: pPlayer->PlayerTalkClass->SendGossipMenu( 4913,GetGUID()); break; + case CLASS_HUNTER: pPlayer->PlayerTalkClass->SendGossipMenu(10090,GetGUID()); break; + case CLASS_MAGE: pPlayer->PlayerTalkClass->SendGossipMenu( 328,GetGUID()); break; + case CLASS_PALADIN:pPlayer->PlayerTalkClass->SendGossipMenu( 1635,GetGUID()); break; + case CLASS_PRIEST: pPlayer->PlayerTalkClass->SendGossipMenu( 4436,GetGUID()); break; + case CLASS_ROGUE: pPlayer->PlayerTalkClass->SendGossipMenu( 4797,GetGUID()); break; + case CLASS_SHAMAN: pPlayer->PlayerTalkClass->SendGossipMenu( 5003,GetGUID()); break; + case CLASS_WARLOCK:pPlayer->PlayerTalkClass->SendGossipMenu( 5836,GetGUID()); break; + case CLASS_WARRIOR:pPlayer->PlayerTalkClass->SendGossipMenu( 4985,GetGUID()); break; + } + } + return false; + } + break; + case TRAINER_TYPE_PETS: + if(pPlayer->getClass()!=CLASS_HUNTER) + { + pPlayer->PlayerTalkClass->ClearMenus(); + pPlayer->PlayerTalkClass->SendGossipMenu(3620,GetGUID()); + return false; + } + break; + case TRAINER_TYPE_MOUNTS: + if(GetCreatureInfo()->race && pPlayer->getRace() != GetCreatureInfo()->race) + { + if(msg) + { + pPlayer->PlayerTalkClass->ClearMenus(); + switch(GetCreatureInfo()->classNum) + { + case RACE_DWARF: pPlayer->PlayerTalkClass->SendGossipMenu(5865,GetGUID()); break; + case RACE_GNOME: pPlayer->PlayerTalkClass->SendGossipMenu(4881,GetGUID()); break; + case RACE_HUMAN: pPlayer->PlayerTalkClass->SendGossipMenu(5861,GetGUID()); break; + case RACE_NIGHTELF: pPlayer->PlayerTalkClass->SendGossipMenu(5862,GetGUID()); break; + case RACE_ORC: pPlayer->PlayerTalkClass->SendGossipMenu(5863,GetGUID()); break; + case RACE_TAUREN: pPlayer->PlayerTalkClass->SendGossipMenu(5864,GetGUID()); break; + case RACE_TROLL: pPlayer->PlayerTalkClass->SendGossipMenu(5816,GetGUID()); break; + case RACE_UNDEAD_PLAYER:pPlayer->PlayerTalkClass->SendGossipMenu( 624,GetGUID()); break; + case RACE_BLOODELF: pPlayer->PlayerTalkClass->SendGossipMenu(5862,GetGUID()); break; + case RACE_DRAENEI: pPlayer->PlayerTalkClass->SendGossipMenu(5864,GetGUID()); break; + } + } + return false; + } + break; + case TRAINER_TYPE_TRADESKILLS: + if(GetCreatureInfo()->trainer_spell && !pPlayer->HasSpell(GetCreatureInfo()->trainer_spell)) + { + if(msg) + { + pPlayer->PlayerTalkClass->ClearMenus(); + pPlayer->PlayerTalkClass->SendGossipMenu(11031,GetGUID()); + } + return false; + } + break; + default: + return false; // checked and error output at creature_template loading + } + return true; +} + +bool Creature::isCanIneractWithBattleMaster(Player* pPlayer, bool msg) const +{ + if(!isBattleMaster()) + return false; + + uint32 bgTypeId = objmgr.GetBattleMasterBG(GetEntry()); + if(!msg) + return pPlayer->GetBGAccessByLevel(bgTypeId); + + if(!pPlayer->GetBGAccessByLevel(bgTypeId)) + { + pPlayer->PlayerTalkClass->ClearMenus(); + switch(bgTypeId) + { + case BATTLEGROUND_AV: pPlayer->PlayerTalkClass->SendGossipMenu(7616,GetGUID()); break; + case BATTLEGROUND_WS: pPlayer->PlayerTalkClass->SendGossipMenu(7599,GetGUID()); break; + case BATTLEGROUND_AB: pPlayer->PlayerTalkClass->SendGossipMenu(7642,GetGUID()); break; + case BATTLEGROUND_EY: + case BATTLEGROUND_NA: + case BATTLEGROUND_BE: + case BATTLEGROUND_AA: + case BATTLEGROUND_RL: pPlayer->PlayerTalkClass->SendGossipMenu(10024,GetGUID()); break; + break; + } + return false; + } + return true; +} + +bool Creature::isCanTrainingAndResetTalentsOf(Player* pPlayer) const +{ + return pPlayer->getLevel() >= 10 + && GetCreatureInfo()->trainer_type == TRAINER_TYPE_CLASS + && pPlayer->getClass() == GetCreatureInfo()->classNum; +} + +void Creature::prepareGossipMenu( Player *pPlayer,uint32 gossipid ) +{ + PlayerMenu* pm=pPlayer->PlayerTalkClass; + pm->ClearMenus(); + + // lazy loading single time at use + LoadGossipOptions(); + + GossipOption* gso; + GossipOption* ingso; + + for( GossipOptionList::iterator i = m_goptions.begin( ); i != m_goptions.end( ); i++ ) + { + gso=&*i; + if(gso->GossipId == gossipid) + { + bool cantalking=true; + if(gso->Id==1) + { + uint32 textid=GetNpcTextId(); + GossipText * gossiptext=objmgr.GetGossipText(textid); + if(!gossiptext) + cantalking=false; + } + else + { + switch (gso->Action) + { + case GOSSIP_OPTION_QUESTGIVER: + pPlayer->PrepareQuestMenu(GetGUID()); + //if (pm->GetQuestMenu()->MenuItemCount() == 0) + cantalking=false; + //pm->GetQuestMenu()->ClearMenu(); + break; + case GOSSIP_OPTION_ARMORER: + cantalking=false; // added in special mode + break; + case GOSSIP_OPTION_SPIRITHEALER: + if( !pPlayer->isDead() ) + cantalking=false; + break; + case GOSSIP_OPTION_VENDOR: + // load vendor items if not yet + LoadGoods(); + + if(!GetItemCount()) + { + sLog.outErrorDb("Creature %u (Entry: %u) have UNIT_NPC_FLAG_VENDOR but have empty trading item list.", + GetGUIDLow(),GetEntry()); + cantalking=false; + } + break; + case GOSSIP_OPTION_TRAINER: + // Lazy loading at first access + LoadTrainerSpells(); + + if(!isCanTrainingOf(pPlayer,false)) + cantalking=false; + break; + case GOSSIP_OPTION_UNLEARNTALENTS: + if(!isCanTrainingAndResetTalentsOf(pPlayer)) + cantalking=false; + break; + case GOSSIP_OPTION_UNLEARNPETSKILLS: + if(!pPlayer->GetPet() || pPlayer->GetPet()->getPetType() != HUNTER_PET || pPlayer->GetPet()->m_spells.size() <= 1 || GetCreatureInfo()->trainer_type != TRAINER_TYPE_PETS || GetCreatureInfo()->classNum != CLASS_HUNTER) + cantalking=false; + break; + case GOSSIP_OPTION_TAXIVENDOR: + if ( pPlayer->GetSession()->SendLearnNewTaxiNode(this) ) + return; + break; + case GOSSIP_OPTION_BATTLEFIELD: + if(!isCanIneractWithBattleMaster(pPlayer,false)) + cantalking=false; + break; + case GOSSIP_OPTION_SPIRITGUIDE: + case GOSSIP_OPTION_INNKEEPER: + case GOSSIP_OPTION_BANKER: + case GOSSIP_OPTION_PETITIONER: + case GOSSIP_OPTION_STABLEPET: + case GOSSIP_OPTION_TABARDDESIGNER: + case GOSSIP_OPTION_AUCTIONEER: + break; // no checks + default: + sLog.outErrorDb("Creature %u (entry: %u) have unknown gossip option %u",GetGUIDLow(),GetEntry(),gso->Action); + break; + } + } + + if(!gso->Option.empty() && cantalking ) + { //note for future dev: should have database fields for BoxMessage & BoxMoney + pm->GetGossipMenu()->AddMenuItem((uint8)gso->Icon,gso->Option, gossipid,gso->Action,"",0,false); + ingso=gso; + } + } + } + + ///some gossips aren't handled in normal way ... so we need to do it this way .. TODO: handle it in normal way ;-) + if(pm->GetGossipMenu()->MenuItemCount()==0 && !pm->GetQuestMenu()->MenuItemCount()) + { + if(HasFlag(UNIT_NPC_FLAGS,UNIT_NPC_FLAG_TRAINER)) + { + LoadTrainerSpells(); // Lazy loading at first access + isCanTrainingOf(pPlayer,true); // output error message if need + } + if(HasFlag(UNIT_NPC_FLAGS,UNIT_NPC_FLAG_BATTLEMASTER)) + { + isCanIneractWithBattleMaster(pPlayer,true); // output error message if need + } + } +} + +void Creature::sendPreparedGossip(Player* player) +{ + if(!player) + return; + + GossipMenu* gossipmenu = player->PlayerTalkClass->GetGossipMenu(); + + // in case empty gossip menu open quest menu if any + if (gossipmenu->MenuItemCount() == 0 && GetNpcTextId() == 0) + { + player->SendPreparedQuest(GetGUID()); + return; + } + + // in case non empty gossip menu (that not included quests list size) show it + // (quest entries from quest menu wiill be included in list) + player->PlayerTalkClass->SendGossipMenu(GetNpcTextId(), GetGUID()); +} + +void Creature::OnGossipSelect(Player* player, uint32 option) +{ + GossipMenu* gossipmenu = player->PlayerTalkClass->GetGossipMenu(); + uint32 action=gossipmenu->GetItem(option).m_gAction; + uint32 zoneid=GetZoneId(); + uint64 guid=GetGUID(); + GossipOption const *gossip=GetGossipOption( action ); + uint32 textid; + if(!gossip) + { + zoneid=0; + gossip=GetGossipOption( action ); + if(!gossip) + return; + } + textid=GetGossipTextId( action, zoneid); + if(textid==0) + textid=GetNpcTextId(); + + switch (gossip->Action) + { + case GOSSIP_OPTION_GOSSIP: + player->PlayerTalkClass->CloseGossip(); + player->PlayerTalkClass->SendTalking( textid ); + break; + case GOSSIP_OPTION_SPIRITHEALER: + if( player->isDead() ) + CastSpell(this,17251,true,NULL,NULL,player->GetGUID()); + break; + case GOSSIP_OPTION_QUESTGIVER: + player->PrepareQuestMenu( guid ); + player->SendPreparedQuest( guid ); + break; + case GOSSIP_OPTION_VENDOR: + case GOSSIP_OPTION_ARMORER: + player->GetSession()->SendListInventory(guid); + break; + case GOSSIP_OPTION_STABLEPET: + player->GetSession()->SendStablePet(guid); + break; + case GOSSIP_OPTION_TRAINER: + player->GetSession()->SendTrainerList(guid); + break; + case GOSSIP_OPTION_UNLEARNTALENTS: + player->PlayerTalkClass->CloseGossip(); + player->SendTalentWipeConfirm(guid); + break; + case GOSSIP_OPTION_UNLEARNPETSKILLS: + player->PlayerTalkClass->CloseGossip(); + player->SendPetSkillWipeConfirm(); + break; + case GOSSIP_OPTION_TAXIVENDOR: + player->GetSession()->SendTaxiMenu(this); + break; + case GOSSIP_OPTION_INNKEEPER: + player->PlayerTalkClass->CloseGossip(); + player->SetBindPoint( guid ); + break; + case GOSSIP_OPTION_BANKER: + player->GetSession()->SendShowBank( guid ); + break; + case GOSSIP_OPTION_PETITIONER: + player->PlayerTalkClass->CloseGossip(); + player->GetSession()->SendPetitionShowList( guid ); + break; + case GOSSIP_OPTION_TABARDDESIGNER: + player->PlayerTalkClass->CloseGossip(); + player->GetSession()->SendTabardVendorActivate( guid ); + break; + case GOSSIP_OPTION_AUCTIONEER: + player->GetSession()->SendAuctionHello( guid, this ); + break; + case GOSSIP_OPTION_SPIRITGUIDE: + case GOSSIP_GUARD_SPELLTRAINER: + case GOSSIP_GUARD_SKILLTRAINER: + prepareGossipMenu( player,gossip->Id ); + sendPreparedGossip( player ); + break; + case GOSSIP_OPTION_BATTLEFIELD: + { + uint32 bgTypeId = objmgr.GetBattleMasterBG(GetEntry()); + player->GetSession()->SendBattlegGroundList( GetGUID(), bgTypeId ); + break; + } + default: + OnPoiSelect( player, gossip ); + break; + } + +} + +void Creature::OnPoiSelect(Player* player, GossipOption const *gossip) +{ + if(gossip->GossipId==GOSSIP_GUARD_SPELLTRAINER || gossip->GossipId==GOSSIP_GUARD_SKILLTRAINER) + { + //float x,y; + //bool findnpc=false; + Poi_Icon icon = ICON_POI_0; + //QueryResult *result; + //Field *fields; + uint32 mapid=GetMapId(); + Map const* map=MapManager::Instance().GetBaseMap( mapid ); + uint16 areaflag=map->GetAreaFlag(GetPositionX(),GetPositionY()); + uint32 zoneid=Map::GetZoneId(areaflag,mapid); + std::string areaname= gossip->Option; + /* + uint16 pflag; + + // use the action relate to creaturetemplate.trainer_type ? + result= WorldDatabase.PQuery("SELECT creature.position_x,creature.position_y FROM creature,creature_template WHERE creature.map = '%u' AND creature.id = creature_template.entry AND creature_template.trainer_type = '%u'", mapid, gossip->Action ); + if(!result) + return; + do + { + fields = result->Fetch(); + x=fields[0].GetFloat(); + y=fields[1].GetFloat(); + pflag=map->GetAreaFlag(GetPositionX(),GetPositionY()); + if(pflag==areaflag) + { + findnpc=true; + break; + } + }while(result->NextRow()); + + delete result; + + if(!findnpc) + { + player->PlayerTalkClass->SendTalking( "$NSorry", "Here no this person."); + return; + }*/ + + //need add more case. + switch(gossip->Action) + { + case GOSSIP_GUARD_BANK: + icon=ICON_POI_HOUSE; + break; + case GOSSIP_GUARD_RIDE: + icon=ICON_POI_RWHORSE; + break; + case GOSSIP_GUARD_GUILD: + icon=ICON_POI_BLUETOWER; + break; + default: + icon=ICON_POI_TOWER; + break; + } + uint32 textid=GetGossipTextId( gossip->Action, zoneid ); + player->PlayerTalkClass->SendTalking( textid ); + // how this could worked player->PlayerTalkClass->SendPointOfInterest( x, y, icon, 2, 15, areaname.c_str() ); + } +} + +uint32 Creature::GetGossipTextId(uint32 action, uint32 zoneid) +{ + QueryResult *result= WorldDatabase.PQuery("SELECT textid FROM npc_gossip_textid WHERE action = '%u' AND zoneid ='%u'", action, zoneid ); + + if(!result) + return 0; + + Field *fields = result->Fetch(); + uint32 id = fields[0].GetUInt32(); + + delete result; + + return id; +} + +uint32 Creature::GetNpcTextId() +{ + // already loaded and cached + if(m_NPCTextId) + return m_NPCTextId; + + QueryResult* result = WorldDatabase.PQuery("SELECT textid FROM npc_gossip WHERE npc_guid= '%u'", m_DBTableGuid); + if(result) + { + Field *fields = result->Fetch(); + m_NPCTextId = fields[0].GetUInt32(); + delete result; + } + else + m_NPCTextId = DEFAULT_GOSSIP_MESSAGE; + + return m_NPCTextId; +} + +GossipOption const* Creature::GetGossipOption( uint32 id ) const +{ + for( GossipOptionList::const_iterator i = m_goptions.begin( ); i != m_goptions.end( ); i++ ) + { + if(i->Action==id ) + return &*i; + } + return NULL; +} + +void Creature::LoadGossipOptions() +{ + if(m_gossipOptionLoaded) + return; + + uint32 npcflags=GetUInt32Value(UNIT_NPC_FLAGS); + + QueryResult *result = WorldDatabase.PQuery( "SELECT id,gossip_id,npcflag,icon,action,option_text FROM npc_option WHERE (npcflag & %u)<>0", npcflags ); + + if(!result) + return; + + GossipOption go; + do + { + Field *fields = result->Fetch(); + go.Id= fields[0].GetUInt32(); + go.GossipId = fields[1].GetUInt32(); + go.NpcFlag=fields[2].GetUInt32(); + go.Icon=fields[3].GetUInt32(); + go.Action=fields[4].GetUInt32(); + go.Option=fields[5].GetCppString(); + addGossipOption(go); + }while( result->NextRow() ); + delete result; + + m_gossipOptionLoaded = true; +} + +void Creature::AI_SendMoveToPacket(float x, float y, float z, uint32 time, uint32 MovementFlags, uint8 type) +{ + /* uint32 timeElap = getMSTime(); + if ((timeElap - m_startMove) < m_moveTime) + { + oX = (dX - oX) * ( (timeElap - m_startMove) / m_moveTime ); + oY = (dY - oY) * ( (timeElap - m_startMove) / m_moveTime ); + } + else + { + oX = dX; + oY = dY; + } + + dX = x; + dY = y; + m_orientation = atan2((oY - dY), (oX - dX)); + + m_startMove = getMSTime(); + m_moveTime = time;*/ + SendMonsterMove(x, y, z, type, MovementFlags, time); +} + +Player *Creature::GetLootRecipient() const +{ + if (!m_lootRecipient) return NULL; + else return ObjectAccessor::FindPlayer(m_lootRecipient); +} + +void Creature::SetLootRecipient(Unit *unit) +{ + // set the player whose group should receive the right + // to loot the creature after it dies + // should be set to NULL after the loot disappears + + if (!unit) + { + m_lootRecipient = 0; + RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_OTHER_TAGGER); + return; + } + + Player* player = unit->GetCharmerOrOwnerPlayerOrPlayerItself(); + if(!player) // normal creature, no player involved + return; + + m_lootRecipient = player->GetGUID(); + SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_OTHER_TAGGER); +} + +void Creature::SaveToDB() +{ + // this should only be used when the creature has already been loaded + // perferably after adding to map, because mapid may not be valid otherwise + CreatureData const *data = objmgr.GetCreatureData(m_DBTableGuid); + if(!data) + { + sLog.outError("Creature::SaveToDB failed, cannot get creature data!"); + return; + } + + SaveToDB(GetMapId(), data->spawnMask); +} + +void Creature::SaveToDB(uint32 mapid, uint8 spawnMask) +{ + // update in loaded data + CreatureData& data = objmgr.NewOrExistCreatureData(m_DBTableGuid); + + uint32 displayId = GetNativeDisplayId(); + + // check if it's a custom model and if not, use 0 for displayId + CreatureInfo const *cinfo = GetCreatureInfo(); + if(cinfo) + { + if(displayId != cinfo->DisplayID_A && displayId != cinfo->DisplayID_H) + { + CreatureModelInfo const *minfo = objmgr.GetCreatureModelInfo(cinfo->DisplayID_A); + if(!minfo || displayId != minfo->modelid_other_gender) + { + minfo = objmgr.GetCreatureModelInfo(cinfo->DisplayID_H); + if(minfo && displayId == minfo->modelid_other_gender) + displayId = 0; + } + else + displayId = 0; + } + else + displayId = 0; + } + + // data->guid = guid don't must be update at save + data.id = GetEntry(); + data.mapid = mapid; + data.displayid = displayId; + data.equipmentId = GetEquipmentId(); + data.posX = GetPositionX(); + data.posY = GetPositionY(); + data.posZ = GetPositionZ(); + data.orientation = GetOrientation(); + data.spawntimesecs = m_respawnDelay; + // prevent add data integrity problems + data.spawndist = GetDefaultMovementType()==IDLE_MOTION_TYPE ? 0 : m_respawnradius; + data.currentwaypoint = 0; + data.curhealth = GetHealth(); + data.curmana = GetPower(POWER_MANA); + data.is_dead = m_isDeadByDefault; + // prevent add data integrity problems + data.movementType = !m_respawnradius && GetDefaultMovementType()==RANDOM_MOTION_TYPE + ? IDLE_MOTION_TYPE : GetDefaultMovementType(); + data.spawnMask = spawnMask; + + // updated in DB + WorldDatabase.BeginTransaction(); + + WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid = '%u'", m_DBTableGuid); + + std::ostringstream ss; + ss << "INSERT INTO creature VALUES (" + << m_DBTableGuid << "," + << GetEntry() << "," + << mapid <<"," + << (uint32)spawnMask << "," + << displayId <<"," + << GetEquipmentId() <<"," + << GetPositionX() << "," + << GetPositionY() << "," + << GetPositionZ() << "," + << GetOrientation() << "," + << m_respawnDelay << "," //respawn time + << (float) m_respawnradius << "," //spawn distance (float) + << (uint32) (0) << "," //currentwaypoint + << GetHealth() << "," //curhealth + << GetPower(POWER_MANA) << "," //curmana + << (m_isDeadByDefault ? 1 : 0) << "," //is_dead + << GetDefaultMovementType() << ")"; //default movement generator type + + WorldDatabase.PExecuteLog( ss.str( ).c_str( ) ); + + WorldDatabase.CommitTransaction(); +} + +void Creature::SelectLevel(const CreatureInfo *cinfo) +{ + uint32 rank = isPet()? 0 : cinfo->rank; + + // level + uint32 minlevel = std::min(cinfo->maxlevel, cinfo->minlevel); + uint32 maxlevel = std::max(cinfo->maxlevel, cinfo->minlevel); + uint32 level = minlevel == maxlevel ? minlevel : urand(minlevel, maxlevel); + SetLevel(level); + + float rellevel = maxlevel == minlevel ? 0 : (float(level - minlevel))/(maxlevel - minlevel); + + // health + float healthmod = _GetHealthMod(rank); + + uint32 minhealth = std::min(cinfo->maxhealth, cinfo->minhealth); + uint32 maxhealth = std::max(cinfo->maxhealth, cinfo->minhealth); + uint32 health = uint32(healthmod * (minhealth + uint32(rellevel*(maxhealth - minhealth)))); + + SetCreateHealth(health); + SetMaxHealth(health); + SetHealth(health); + + // mana + uint32 minmana = std::min(cinfo->maxmana, cinfo->minmana); + uint32 maxmana = std::max(cinfo->maxmana, cinfo->minmana); + uint32 mana = minmana + uint32(rellevel*(maxmana - minmana)); + + SetCreateMana(mana); + SetMaxPower(POWER_MANA, mana); //MAX Mana + SetPower(POWER_MANA, mana); + + SetModifierValue(UNIT_MOD_HEALTH, BASE_VALUE, health); + SetModifierValue(UNIT_MOD_MANA, BASE_VALUE, mana); + + // damage + float damagemod = _GetDamageMod(rank); + + SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, cinfo->mindmg * damagemod); + SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, cinfo->maxdmg * damagemod); + + SetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE,cinfo->minrangedmg * damagemod); + SetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE,cinfo->maxrangedmg * damagemod); + + SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, cinfo->attackpower * damagemod); +} + +float Creature::_GetHealthMod(int32 Rank) +{ + switch (Rank) // define rates for each elite rank + { + case CREATURE_ELITE_NORMAL: + return sWorld.getRate(RATE_CREATURE_NORMAL_HP); + case CREATURE_ELITE_ELITE: + return sWorld.getRate(RATE_CREATURE_ELITE_ELITE_HP); + case CREATURE_ELITE_RAREELITE: + return sWorld.getRate(RATE_CREATURE_ELITE_RAREELITE_HP); + case CREATURE_ELITE_WORLDBOSS: + return sWorld.getRate(RATE_CREATURE_ELITE_WORLDBOSS_HP); + case CREATURE_ELITE_RARE: + return sWorld.getRate(RATE_CREATURE_ELITE_RARE_HP); + default: + return sWorld.getRate(RATE_CREATURE_ELITE_ELITE_HP); + } +} + +float Creature::_GetDamageMod(int32 Rank) +{ + switch (Rank) // define rates for each elite rank + { + case CREATURE_ELITE_NORMAL: + return sWorld.getRate(RATE_CREATURE_NORMAL_DAMAGE); + case CREATURE_ELITE_ELITE: + return sWorld.getRate(RATE_CREATURE_ELITE_ELITE_DAMAGE); + case CREATURE_ELITE_RAREELITE: + return sWorld.getRate(RATE_CREATURE_ELITE_RAREELITE_DAMAGE); + case CREATURE_ELITE_WORLDBOSS: + return sWorld.getRate(RATE_CREATURE_ELITE_WORLDBOSS_DAMAGE); + case CREATURE_ELITE_RARE: + return sWorld.getRate(RATE_CREATURE_ELITE_RARE_DAMAGE); + default: + return sWorld.getRate(RATE_CREATURE_ELITE_ELITE_DAMAGE); + } +} + +float Creature::GetSpellDamageMod(int32 Rank) +{ + switch (Rank) // define rates for each elite rank + { + case CREATURE_ELITE_NORMAL: + return sWorld.getRate(RATE_CREATURE_NORMAL_SPELLDAMAGE); + case CREATURE_ELITE_ELITE: + return sWorld.getRate(RATE_CREATURE_ELITE_ELITE_SPELLDAMAGE); + case CREATURE_ELITE_RAREELITE: + return sWorld.getRate(RATE_CREATURE_ELITE_RAREELITE_SPELLDAMAGE); + case CREATURE_ELITE_WORLDBOSS: + return sWorld.getRate(RATE_CREATURE_ELITE_WORLDBOSS_SPELLDAMAGE); + case CREATURE_ELITE_RARE: + return sWorld.getRate(RATE_CREATURE_ELITE_RARE_SPELLDAMAGE); + default: + return sWorld.getRate(RATE_CREATURE_ELITE_ELITE_SPELLDAMAGE); + } +} + +bool Creature::CreateFromProto(uint32 guidlow, uint32 Entry, uint32 team, const CreatureData *data) +{ + CreatureInfo const *cinfo = objmgr.GetCreatureTemplate(Entry); + if(!cinfo) + { + sLog.outErrorDb("Error: creature entry %u does not exist.", Entry); + return false; + } + m_originalEntry = Entry; + + Object::_Create(guidlow, Entry, HIGHGUID_UNIT); + + m_DBTableGuid = guidlow; + if(!UpdateEntry(Entry, team, data)) + return false; + + //Notify the map's instance data. + //Only works if you create the object in it, not if it is moves to that map. + //Normally non-players do not teleport to other maps. + Map *map = MapManager::Instance().FindMap(GetMapId(), GetInstanceId()); + if(map && map->IsDungeon() && ((InstanceMap*)map)->GetInstanceData()) + { + ((InstanceMap*)map)->GetInstanceData()->OnCreatureCreate(this, Entry); + } + + return true; +} + +bool Creature::LoadFromDB(uint32 guid, Map *map) +{ + CreatureData const* data = objmgr.GetCreatureData(guid); + + if(!data) + { + sLog.outErrorDb("Creature (GUID: %u) not found in table `creature`, can't load. ",guid); + return false; + } + + uint32 stored_guid = guid; + if (map->GetInstanceId() != 0) guid = objmgr.GenerateLowGuid(HIGHGUID_UNIT); + + uint16 team = 0; + if(!Create(guid,map,data->id,team,data)) + return false; + + Relocate(data->posX,data->posY,data->posZ,data->orientation); + + if(!IsPositionValid()) + { + sLog.outError("ERROR: Creature (guidlow %d, entry %d) not loaded. Suggested coordinates isn't valid (X: %f Y: %f)",GetGUIDLow(),GetEntry(),GetPositionX(),GetPositionY()); + return false; + } + + m_DBTableGuid = stored_guid; + LoadCreaturesAddon(); + + m_respawnradius = data->spawndist; + + m_respawnDelay = data->spawntimesecs; + m_isDeadByDefault = data->is_dead; + m_deathState = m_isDeadByDefault ? DEAD : ALIVE; + + m_respawnTime = objmgr.GetCreatureRespawnTime(m_DBTableGuid,GetInstanceId()); + if(m_respawnTime > time(NULL)) // not ready to respawn + m_deathState = DEAD; + else if(m_respawnTime) // respawn time set but expired + { + m_respawnTime = 0; + objmgr.SaveCreatureRespawnTime(m_DBTableGuid,GetInstanceId(),0); + } + + uint32 curhealth = data->curhealth; + if(curhealth) + { + curhealth = uint32(curhealth*_GetHealthMod(GetCreatureInfo()->rank)); + if(curhealth < 1) + curhealth = 1; + } + + SetHealth(m_deathState == ALIVE ? curhealth : 0); + SetPower(POWER_MANA,data->curmana); + + SetMeleeDamageSchool(SpellSchools(GetCreatureInfo()->dmgschool)); + + // checked at creature_template loading + m_defaultMovementType = MovementGeneratorType(data->movementType); + + AIM_Initialize(); + return true; +} + +void Creature::LoadEquipment(uint32 equip_entry, bool force) +{ + if(equip_entry == 0) + { + if (force) + { + for (uint8 i=0;i<3;i++) + { + SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_DISPLAY + i, 0); + SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + (i * 2), 0); + SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + (i * 2) + 1, 0); + } + m_equipmentId = 0; + } + return; + } + + EquipmentInfo const *einfo = objmgr.GetEquipmentInfo(equip_entry); + if (!einfo) + return; + + m_equipmentId = equip_entry; + for (uint8 i=0;i<3;i++) + { + SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_DISPLAY + i, einfo->equipmodel[i]); + SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + (i * 2), einfo->equipinfo[i]); + SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + (i * 2) + 1, einfo->equipslot[i]); + } +} + +void Creature::LoadGoods() +{ + // already loaded; + if(m_itemsLoaded) + return; + + m_vendor_items.clear(); + + QueryResult *result = WorldDatabase.PQuery("SELECT item, maxcount, incrtime, ExtendedCost FROM npc_vendor WHERE entry = '%u'", GetEntry()); + + if(!result) + return; + + do + { + Field *fields = result->Fetch(); + + if (GetItemCount() >= MAX_VENDOR_ITEMS) + { + sLog.outErrorDb( "Vendor %u has too many items (%u >= %i). Check the DB!", GetEntry(), GetItemCount(), MAX_VENDOR_ITEMS ); + break; + } + + uint32 item_id = fields[0].GetUInt32(); + if(!sItemStorage.LookupEntry(item_id)) + { + sLog.outErrorDb("Vendor %u have in item list non-existed item %u",GetEntry(),item_id); + continue; + } + + uint32 ExtendedCost = fields[3].GetUInt32(); + if(ExtendedCost && !sItemExtendedCostStore.LookupEntry(ExtendedCost)) + sLog.outErrorDb("Item (Entry: %u) has wrong ExtendedCost (%u) for vendor (%u)",item_id,ExtendedCost,GetEntry()); + + AddItem( item_id, fields[1].GetUInt32(), fields[2].GetUInt32(), ExtendedCost); + } + while( result->NextRow() ); + + delete result; + + m_itemsLoaded = true; +} + +bool Creature::hasQuest(uint32 quest_id) const +{ + QuestRelations const& qr = objmgr.mCreatureQuestRelations; + for(QuestRelations::const_iterator itr = qr.lower_bound(GetEntry()); itr != qr.upper_bound(GetEntry()); ++itr) + { + if(itr->second==quest_id) + return true; + } + return false; +} + +bool Creature::hasInvolvedQuest(uint32 quest_id) const +{ + QuestRelations const& qr = objmgr.mCreatureQuestInvolvedRelations; + for(QuestRelations::const_iterator itr = qr.lower_bound(GetEntry()); itr != qr.upper_bound(GetEntry()); ++itr) + { + if(itr->second==quest_id) + return true; + } + return false; +} + +void Creature::DeleteFromDB() +{ + objmgr.SaveCreatureRespawnTime(m_DBTableGuid,GetInstanceId(),0); + objmgr.DeleteCreatureData(m_DBTableGuid); + + WorldDatabase.BeginTransaction(); + WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid = '%u'", m_DBTableGuid); + WorldDatabase.PExecuteLog("DELETE FROM creature_addon WHERE guid = '%u'", m_DBTableGuid); + WorldDatabase.PExecuteLog("DELETE FROM creature_movement WHERE id = '%u'", m_DBTableGuid); + WorldDatabase.PExecuteLog("DELETE FROM game_event_creature WHERE guid = '%u'", m_DBTableGuid); + WorldDatabase.PExecuteLog("DELETE FROM game_event_model_equip WHERE guid = '%u'", m_DBTableGuid); + WorldDatabase.CommitTransaction(); +} + +float Creature::GetAttackDistance(Unit const* pl) const +{ + float aggroRate = sWorld.getRate(RATE_CREATURE_AGGRO); + if(aggroRate==0) + return 0.0f; + + int32 playerlevel = pl->getLevelForTarget(this); + int32 creaturelevel = getLevelForTarget(pl); + + int32 leveldif = playerlevel - creaturelevel; + + // "The maximum Aggro Radius has a cap of 25 levels under. Example: A level 30 char has the same Aggro Radius of a level 5 char on a level 60 mob." + if ( leveldif < - 25) + leveldif = -25; + + // "The aggro radius of a mob having the same level as the player is roughly 20 yards" + float RetDistance = 20; + + // "Aggro Radius varries with level difference at a rate of roughly 1 yard/level" + // radius grow if playlevel < creaturelevel + RetDistance -= (float)leveldif; + + if(creaturelevel+5 <= sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + { + // detect range auras + RetDistance += GetTotalAuraModifier(SPELL_AURA_MOD_DETECT_RANGE); + + // detected range auras + RetDistance += pl->GetTotalAuraModifier(SPELL_AURA_MOD_DETECTED_RANGE); + } + + // "Minimum Aggro Radius for a mob seems to be combat range (5 yards)" + if(RetDistance < 5) + RetDistance = 5; + + return (RetDistance*aggroRate); +} + +void Creature::setDeathState(DeathState s) +{ + if((s == JUST_DIED && !m_isDeadByDefault)||(s == JUST_ALIVED && m_isDeadByDefault)) + { + m_deathTimer = m_corpseDelay*1000; + + // always save boss respawn time at death to prevent crash cheating + if(sWorld.getConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATLY) || isWorldBoss()) + SaveRespawnTime(); + + if(!IsStopped()) + StopMoving(); + } + Unit::setDeathState(s); + + if(s == JUST_DIED) + { + SetUInt64Value (UNIT_FIELD_TARGET,0); // remove target selection in any cases (can be set at aura remove in Unit::setDeathState) + SetUInt32Value(UNIT_NPC_FLAGS, 0); + + if(!isPet() && GetCreatureInfo()->SkinLootId) + if ( LootTemplates_Skinning.HaveLootFor(GetCreatureInfo()->SkinLootId) ) + SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); + + Unit::setDeathState(CORPSE); + } + if(s == JUST_ALIVED) + { + SetHealth(GetMaxHealth()); + SetLootRecipient(NULL); + Unit::setDeathState(ALIVE); + CreatureInfo const *cinfo = GetCreatureInfo(); + SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0); + RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); + AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + SetUInt32Value(UNIT_NPC_FLAGS, cinfo->npcflag); + clearUnitState(UNIT_STAT_ALL_STATE); + i_motionMaster.Clear(); + SetMeleeDamageSchool(SpellSchools(cinfo->dmgschool)); + LoadCreaturesAddon(true); + } +} + +void Creature::Respawn() +{ + RemoveCorpse(); + + // forced recreate creature object at clients + UnitVisibility currentVis = GetVisibility(); + SetVisibility(VISIBILITY_RESPAWN); + ObjectAccessor::UpdateObjectVisibility(this); + SetVisibility(currentVis); // restore visibility state + ObjectAccessor::UpdateObjectVisibility(this); + + if(getDeathState()==DEAD) + { + objmgr.SaveCreatureRespawnTime(m_DBTableGuid,GetInstanceId(),0); + m_respawnTime = time(NULL); // respawn at next tick + } +} + +bool Creature::IsImmunedToSpell(SpellEntry const* spellInfo, bool useCharges) +{ + if (!spellInfo) + return false; + + if (GetCreatureInfo()->MechanicImmuneMask & (1 << (spellInfo->Mechanic - 1))) + return true; + + return Unit::IsImmunedToSpell(spellInfo, useCharges); +} + +bool Creature::IsImmunedToSpellEffect(uint32 effect, uint32 mechanic) const +{ + if (GetCreatureInfo()->MechanicImmuneMask & (1 << (mechanic-1))) + return true; + + return Unit::IsImmunedToSpellEffect(effect, mechanic); +} + +SpellEntry const *Creature::reachWithSpellAttack(Unit *pVictim) +{ + if(!pVictim) + return NULL; + + for(uint32 i=0; i < CREATURE_MAX_SPELLS; i++) + { + if(!m_spells[i]) + continue; + SpellEntry const *spellInfo = sSpellStore.LookupEntry(m_spells[i] ); + if(!spellInfo) + { + sLog.outError("WORLD: unknown spell id %i\n", m_spells[i]); + continue; + } + + bool bcontinue = true; + for(uint32 j=0;j<3;j++) + { + if( (spellInfo->Effect[j] == SPELL_EFFECT_SCHOOL_DAMAGE ) || + (spellInfo->Effect[j] == SPELL_EFFECT_INSTAKILL) || + (spellInfo->Effect[j] == SPELL_EFFECT_ENVIRONMENTAL_DAMAGE) || + (spellInfo->Effect[j] == SPELL_EFFECT_HEALTH_LEECH ) + ) + { + bcontinue = false; + break; + } + } + if(bcontinue) continue; + + if(spellInfo->manaCost > GetPower(POWER_MANA)) + continue; + SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(spellInfo->rangeIndex); + float range = GetSpellMaxRange(srange); + float minrange = GetSpellMinRange(srange); + float dist = GetDistance(pVictim); + //if(!isInFront( pVictim, range ) && spellInfo->AttributesEx ) + // continue; + if( dist > range || dist < minrange ) + continue; + if(HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED)) + continue; + return spellInfo; + } + return NULL; +} + +SpellEntry const *Creature::reachWithSpellCure(Unit *pVictim) +{ + if(!pVictim) + return NULL; + + for(uint32 i=0; i < CREATURE_MAX_SPELLS; i++) + { + if(!m_spells[i]) + continue; + SpellEntry const *spellInfo = sSpellStore.LookupEntry(m_spells[i] ); + if(!spellInfo) + { + sLog.outError("WORLD: unknown spell id %i\n", m_spells[i]); + continue; + } + + bool bcontinue = true; + for(uint32 j=0;j<3;j++) + { + if( (spellInfo->Effect[j] == SPELL_EFFECT_HEAL ) ) + { + bcontinue = false; + break; + } + } + if(bcontinue) continue; + + if(spellInfo->manaCost > GetPower(POWER_MANA)) + continue; + SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(spellInfo->rangeIndex); + float range = GetSpellMaxRange(srange); + float minrange = GetSpellMinRange(srange); + float dist = GetDistance(pVictim); + //if(!isInFront( pVictim, range ) && spellInfo->AttributesEx ) + // continue; + if( dist > range || dist < minrange ) + continue; + if(HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED)) + continue; + return spellInfo; + } + return NULL; +} + +bool Creature::IsVisibleInGridForPlayer(Player* pl) const +{ + // gamemaster in GM mode see all, including ghosts + if(pl->isGameMaster()) + return true; + + // Live player (or with not release body see live creatures or death creatures with corpse disappearing time > 0 + if(pl->isAlive() || pl->GetDeathTimer() > 0) + { + if( GetEntry() == VISUAL_WAYPOINT && !pl->isGameMaster() ) + return false; + return isAlive() || m_deathTimer > 0 || m_isDeadByDefault && m_deathState==CORPSE; + } + + // Dead player see live creatures near own corpse + if(isAlive()) + { + Corpse *corpse = pl->GetCorpse(); + if(corpse) + { + // 20 - aggro distance for same level, 25 - max additional distance if player level less that creature level + if(corpse->IsWithinDistInMap(this,(20+25)*sWorld.getRate(RATE_CREATURE_AGGRO))) + return true; + } + } + + // Dead player see Spirit Healer or Spirit Guide + if(isSpiritService()) + return true; + + // and not see any other + return false; +} + +void Creature::CallAssistence() +{ + if( !m_AlreadyCallAssistence && getVictim() && !isPet() && !isCharmed()) + { + SetNoCallAssistence(true); + + float radius = sWorld.getConfig(CONFIG_CREATURE_FAMILY_ASSISTEMCE_RADIUS); + if(radius > 0) + { + std::list assistList; + + { + CellPair p(MaNGOS::ComputeCellPair(GetPositionX(), GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + MaNGOS::AnyAssistCreatureInRangeCheck u_check(this, getVictim(), radius); + MaNGOS::CreatureListSearcher searcher(assistList, u_check); + + TypeContainerVisitor, GridTypeMapContainer > grid_creature_searcher(searcher); + + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, grid_creature_searcher, *MapManager::Instance().GetMap(GetMapId(), this)); + } + + for(std::list::iterator iter = assistList.begin(); iter != assistList.end(); ++iter) + { + (*iter)->SetNoCallAssistence(true); + if((*iter)->AI()) + (*iter)->AI()->AttackStart(getVictim()); + } + } + } +} + +void Creature::SaveRespawnTime() +{ + if(isPet()) + return; + + if(m_respawnTime > time(NULL)) // dead (no corpse) + objmgr.SaveCreatureRespawnTime(m_DBTableGuid,GetInstanceId(),m_respawnTime); + else if(m_deathTimer > 0) // dead (corpse) + objmgr.SaveCreatureRespawnTime(m_DBTableGuid,GetInstanceId(),time(NULL)+m_respawnDelay+m_deathTimer/1000); +} + +bool Creature::IsOutOfThreatArea(Unit* pVictim) const +{ + if(!pVictim) + return true; + + if(!pVictim->IsInMap(this)) + return true; + + if(!pVictim->isTargetableForAttack()) + return true; + + if(!pVictim->isInAccessablePlaceFor(this)) + return true; + + if(sMapStore.LookupEntry(GetMapId())->Instanceable()) + return false; + + float length = pVictim->GetDistance(CombatStartX,CombatStartY,CombatStartZ); + float AttackDist = GetAttackDistance(pVictim); + uint32 ThreatRadius = sWorld.getConfig(CONFIG_THREAT_RADIUS); + + //Use AttackDistance in distance check if threat radius is lower. This prevents creature bounce in and ouf of combat every update tick. + return ( length > (ThreatRadius > AttackDist ? ThreatRadius : AttackDist)); +} + +CreatureDataAddon const* Creature::GetCreatureAddon() const +{ + if(CreatureDataAddon const* addon = ObjectMgr::GetCreatureAddon(m_DBTableGuid)) + return addon; + + // dependent from heroic mode entry + return ObjectMgr::GetCreatureTemplateAddon(GetCreatureInfo()->Entry); +} + +//creature_addon table +bool Creature::LoadCreaturesAddon(bool reload) +{ + CreatureDataAddon const *cainfo = GetCreatureAddon(); + if(!cainfo) + return false; + + if (cainfo->mount != 0) + Mount(cainfo->mount); + + if (cainfo->bytes0 != 0) + SetUInt32Value(UNIT_FIELD_BYTES_0, cainfo->bytes0); + + if (cainfo->bytes1 != 0) + SetUInt32Value(UNIT_FIELD_BYTES_1, cainfo->bytes1); + + if (cainfo->bytes2 != 0) + SetUInt32Value(UNIT_FIELD_BYTES_2, cainfo->bytes2); + + if (cainfo->emote != 0) + SetUInt32Value(UNIT_NPC_EMOTESTATE, cainfo->emote); + + if (cainfo->move_flags != 0) + SetUnitMovementFlags(cainfo->move_flags); + + if(cainfo->auras) + { + for (CreatureDataAddonAura const* cAura = cainfo->auras; cAura->spell_id; ++cAura) + { + SpellEntry const *AdditionalSpellInfo = sSpellStore.LookupEntry(cAura->spell_id); + if (!AdditionalSpellInfo) + { + sLog.outErrorDb("Creature (GUIDLow: %u Entry: %u ) has wrong spell %u defined in `auras` field.",GetGUIDLow(),GetEntry(),cAura->spell_id); + continue; + } + + // skip already applied aura + if(HasAura(cAura->spell_id,cAura->effect_idx)) + { + if(!reload) + sLog.outErrorDb("Creature (GUIDLow: %u Entry: %u ) has duplicate aura (spell %u effect %u) in `auras` field.",GetGUIDLow(),GetEntry(),cAura->spell_id,cAura->effect_idx); + + continue; + } + + Aura* AdditionalAura = CreateAura(AdditionalSpellInfo, cAura->effect_idx, NULL, this, this, 0); + AddAura(AdditionalAura); + sLog.outDebug("Spell: %u with Aura %u added to creature (GUIDLow: %u Entry: %u )", cAura->spell_id, AdditionalSpellInfo->EffectApplyAuraName[0],GetGUIDLow(),GetEntry()); + } + } + return true; +} + +/// Send a message to LocalDefense channel for players oposition team in the zone +void Creature::SendZoneUnderAttackMessage(Player* attacker) +{ + uint32 enemy_team = attacker->GetTeam(); + + WorldPacket data(SMSG_ZONE_UNDER_ATTACK,4); + data << (uint32)GetZoneId(); + sWorld.SendGlobalMessage(&data,NULL,(enemy_team==ALLIANCE ? HORDE : ALLIANCE)); +} + +void Creature::_AddCreatureSpellCooldown(uint32 spell_id, time_t end_time) +{ + m_CreatureSpellCooldowns[spell_id] = end_time; +} + +void Creature::_AddCreatureCategoryCooldown(uint32 category, time_t apply_time) +{ + m_CreatureCategoryCooldowns[category] = apply_time; +} + +void Creature::AddCreatureSpellCooldown(uint32 spellid) +{ + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellid); + if(!spellInfo) + return; + + uint32 cooldown = GetSpellRecoveryTime(spellInfo); + if(cooldown) + _AddCreatureSpellCooldown(spellid, time(NULL) + cooldown/1000); + + if(spellInfo->Category) + _AddCreatureCategoryCooldown(spellInfo->Category, time(NULL)); + + m_GlobalCooldown = spellInfo->StartRecoveryTime; +} + +bool Creature::HasCategoryCooldown(uint32 spell_id) const +{ + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id); + if(!spellInfo) + return false; + + // check global cooldown if spell affected by it + if (spellInfo->StartRecoveryCategory > 0 && m_GlobalCooldown > 0) + return true; + + CreatureSpellCooldowns::const_iterator itr = m_CreatureCategoryCooldowns.find(spellInfo->Category); + return(itr != m_CreatureCategoryCooldowns.end() && time_t(itr->second + (spellInfo->CategoryRecoveryTime / 1000)) > time(NULL)); +} + +bool Creature::HasSpellCooldown(uint32 spell_id) const +{ + CreatureSpellCooldowns::const_iterator itr = m_CreatureSpellCooldowns.find(spell_id); + return (itr != m_CreatureSpellCooldowns.end() && itr->second > time(NULL)) || HasCategoryCooldown(spell_id); +} + +bool Creature::IsInEvadeMode() const +{ + return !i_motionMaster.empty() && i_motionMaster.GetCurrentMovementGeneratorType() == HOME_MOTION_TYPE; +} + +bool Creature::HasSpell(uint32 spellID) const +{ + uint8 i; + for(i = 0; i < CREATURE_MAX_SPELLS; ++i) + if(spellID == m_spells[i]) + break; + return i < CREATURE_MAX_SPELLS; //broke before end of iteration of known spells +} + +time_t Creature::GetRespawnTimeEx() const +{ + time_t now = time(NULL); + if(m_respawnTime > now) // dead (no corpse) + return m_respawnTime; + else if(m_deathTimer > 0) // dead (corpse) + return now+m_respawnDelay+m_deathTimer/1000; + else + return now; +} + +void Creature::GetRespawnCoord( float &x, float &y, float &z, float* ori, float* dist ) const +{ + if(CreatureData const* data = objmgr.GetCreatureData(GetDBTableGUIDLow())) + { + x = data->posX; + y = data->posY; + z = data->posZ; + if(ori) + *ori = data->orientation; + if(dist) + *dist = data->spawndist; + } + else + { + x = GetPositionX(); + y = GetPositionY(); + z = GetPositionZ(); + if(ori) + *ori = GetOrientation(); + if(dist) + *dist = 0; + } +} + +void Creature::AllLootRemovedFromCorpse() +{ + if (!HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE)) + { + uint32 nDeathTimer; + + CreatureInfo const *cinfo = GetCreatureInfo(); + + // corpse was not skinnable -> apply corpse looted timer + if (!cinfo || !cinfo->SkinLootId) + nDeathTimer = (uint32)((m_corpseDelay * 1000) * sWorld.getRate(RATE_CORPSE_DECAY_LOOTED)); + // corpse skinnable, but without skinning flag, and then skinned, corpse will despawn next update + else + nDeathTimer = 0; + + // update death timer only if looted timer is shorter + if (m_deathTimer > nDeathTimer) + m_deathTimer = nDeathTimer; + } +} + +uint32 Creature::getLevelForTarget( Unit const* target ) const +{ + if(!isWorldBoss()) + return Unit::getLevelForTarget(target); + + uint32 level = target->getLevel()+sWorld.getConfig(CONFIG_WORLD_BOSS_LEVEL_DIFF); + if(level < 1) + return 1; + if(level > 255) + return 255; + return level; +} + +char const* Creature::GetScriptName() const +{ + return ObjectMgr::GetCreatureTemplate(GetEntry())->ScriptName; +} diff --git a/src/game/Creature.h b/src/game/Creature.h new file mode 100644 index 00000000000..d70954acefe --- /dev/null +++ b/src/game/Creature.h @@ -0,0 +1,611 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOSSERVER_CREATURE_H +#define MANGOSSERVER_CREATURE_H + +#include "Common.h" +#include "Unit.h" +#include "UpdateMask.h" +#include "ItemPrototype.h" +#include "LootMgr.h" +#include "Database/DatabaseEnv.h" +#include "Cell.h" + +struct SpellEntry; + +class CreatureAI; +class Quest; +class Player; +class WorldSession; + +enum Gossip_Option +{ + GOSSIP_OPTION_NONE = 0, //UNIT_NPC_FLAG_NONE = 0, + GOSSIP_OPTION_GOSSIP = 1, //UNIT_NPC_FLAG_GOSSIP = 1, + GOSSIP_OPTION_QUESTGIVER = 2, //UNIT_NPC_FLAG_QUESTGIVER = 2, + GOSSIP_OPTION_VENDOR = 3, //UNIT_NPC_FLAG_VENDOR = 4, + GOSSIP_OPTION_TAXIVENDOR = 4, //UNIT_NPC_FLAG_TAXIVENDOR = 8, + GOSSIP_OPTION_TRAINER = 5, //UNIT_NPC_FLAG_TRAINER = 16, + GOSSIP_OPTION_SPIRITHEALER = 6, //UNIT_NPC_FLAG_SPIRITHEALER = 32, + GOSSIP_OPTION_SPIRITGUIDE = 7, //UNIT_NPC_FLAG_SPIRITGUIDE = 64, + GOSSIP_OPTION_INNKEEPER = 8, //UNIT_NPC_FLAG_INNKEEPER = 128, + GOSSIP_OPTION_BANKER = 9, //UNIT_NPC_FLAG_BANKER = 256, + GOSSIP_OPTION_PETITIONER = 10, //UNIT_NPC_FLAG_PETITIONER = 512, + GOSSIP_OPTION_TABARDDESIGNER = 11, //UNIT_NPC_FLAG_TABARDDESIGNER = 1024, + GOSSIP_OPTION_BATTLEFIELD = 12, //UNIT_NPC_FLAG_BATTLEFIELDPERSON = 2048, + GOSSIP_OPTION_AUCTIONEER = 13, //UNIT_NPC_FLAG_AUCTIONEER = 4096, + GOSSIP_OPTION_STABLEPET = 14, //UNIT_NPC_FLAG_STABLE = 8192, + GOSSIP_OPTION_ARMORER = 15, //UNIT_NPC_FLAG_ARMORER = 16384, + GOSSIP_OPTION_UNLEARNTALENTS = 16, //UNIT_NPC_FLAG_TRAINER (bonus option for GOSSIP_OPTION_TRAINER) + GOSSIP_OPTION_UNLEARNPETSKILLS = 17 //UNIT_NPC_FLAG_TRAINER (bonus option for GOSSIP_OPTION_TRAINER) +}; + +enum Gossip_Guard +{ + GOSSIP_GUARD_BANK = 32, + GOSSIP_GUARD_RIDE = 33, + GOSSIP_GUARD_GUILD = 34, + GOSSIP_GUARD_INN = 35, + GOSSIP_GUARD_MAIL = 36, + GOSSIP_GUARD_AUCTION = 37, + GOSSIP_GUARD_WEAPON = 38, + GOSSIP_GUARD_STABLE = 39, + GOSSIP_GUARD_BATTLE = 40, + GOSSIP_GUARD_SPELLTRAINER = 41, + GOSSIP_GUARD_SKILLTRAINER = 42 +}; + +enum Gossip_Guard_Spell +{ + GOSSIP_GUARD_SPELL_WARRIOR = 64, + GOSSIP_GUARD_SPELL_PALADIN = 65, + GOSSIP_GUARD_SPELL_HUNTER = 66, + GOSSIP_GUARD_SPELL_ROGUE = 67, + GOSSIP_GUARD_SPELL_PRIEST = 68, + GOSSIP_GUARD_SPELL_UNKNOWN1 = 69, + GOSSIP_GUARD_SPELL_SHAMAN = 70, + GOSSIP_GUARD_SPELL_MAGE = 71, + GOSSIP_GUARD_SPELL_WARLOCK = 72, + GOSSIP_GUARD_SPELL_UNKNOWN2 = 73, + GOSSIP_GUARD_SPELL_DRUID = 74 +}; + +enum Gossip_Guard_Skill +{ + GOSSIP_GUARD_SKILL_ALCHEMY = 80, + GOSSIP_GUARD_SKILL_BLACKSMITH = 81, + GOSSIP_GUARD_SKILL_COOKING = 82, + GOSSIP_GUARD_SKILL_ENCHANT = 83, + GOSSIP_GUARD_SKILL_FIRSTAID = 84, + GOSSIP_GUARD_SKILL_FISHING = 85, + GOSSIP_GUARD_SKILL_HERBALISM = 86, + GOSSIP_GUARD_SKILL_LEATHER = 87, + GOSSIP_GUARD_SKILL_MINING = 88, + GOSSIP_GUARD_SKILL_SKINNING = 89, + GOSSIP_GUARD_SKILL_TAILORING = 90, + GOSSIP_GUARD_SKILL_ENGINERING = 91 +}; + +struct GossipOption +{ + uint32 Id; + uint32 GossipId; + uint32 NpcFlag; + uint32 Icon; + uint32 Action; + std::string Option; +}; + +struct CreatureItem +{ + CreatureItem(uint32 _item, uint32 _maxcount, uint32 _incrtime, uint32 _ExtendedCost) + : id(_item), count(_maxcount), maxcount(_maxcount), incrtime(_incrtime), ExtendedCost(_ExtendedCost), lastincr((uint32)time(NULL)) {} + + uint32 id; + uint32 count; + uint32 maxcount; + uint32 incrtime; + uint32 lastincr; + uint32 ExtendedCost; +}; + +struct TrainerSpell +{ + SpellEntry const* spell; + uint32 spellcost; + uint32 reqskill; + uint32 reqskillvalue; + uint32 reqlevel; +}; + +enum CreatureFlagsExtra +{ + CREATURE_FLAG_EXTRA_INSTANCE_BIND = 0x00000001, // creature kill bind instance with killer and killer's group + CREATURE_FLAG_EXTRA_CIVILIAN = 0x00000002, // not aggro (ignore faction/reputation hostility) + CREATURE_FLAG_EXTRA_NO_PARRY = 0x00000004, // creature can't parry + CREATURE_FLAG_EXTRA_NO_PARRY_HASTEN = 0x00000008, // creature can't counter-attack at parry + CREATURE_FLAG_EXTRA_NO_BLOCK = 0x00000010, // creature can't block + CREATURE_FLAG_EXTRA_NO_CRUSH = 0x00000020, // creature can't do crush attacks + CREATURE_FLAG_EXTRA_NO_XP_AT_KILL = 0x00000040, // creature kill not provide XP +}; + +// GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push,N), also any gcc version not support it at some platform +#if defined( __GNUC__ ) +#pragma pack(1) +#else +#pragma pack(push,1) +#endif + +// from `creature_template` table +struct CreatureInfo +{ + uint32 Entry; + uint32 HeroicEntry; + uint32 DisplayID_A; + uint32 DisplayID_A2; + uint32 DisplayID_H; + uint32 DisplayID_H2; + char* Name; + char* SubName; + char* IconName; + uint32 minlevel; + uint32 maxlevel; + uint32 minhealth; + uint32 maxhealth; + uint32 minmana; + uint32 maxmana; + uint32 armor; + uint32 faction_A; + uint32 faction_H; + uint32 npcflag; + float speed; + float scale; + uint32 rank; + float mindmg; + float maxdmg; + uint32 dmgschool; + uint32 attackpower; + uint32 baseattacktime; + uint32 rangeattacktime; + uint32 Flags; + uint32 dynamicflags; + uint32 family; + uint32 trainer_type; + uint32 trainer_spell; + uint32 classNum; + uint32 race; + float minrangedmg; + float maxrangedmg; + uint32 rangedattackpower; + uint32 type; + uint32 flag1; + uint32 lootid; + uint32 pickpocketLootId; + uint32 SkinLootId; + int32 resistance1; + int32 resistance2; + int32 resistance3; + int32 resistance4; + int32 resistance5; + int32 resistance6; + uint32 spell1; + uint32 spell2; + uint32 spell3; + uint32 spell4; + uint32 PetSpellDataId; + uint32 mingold; + uint32 maxgold; + char const* AIName; + uint32 MovementType; + uint32 InhabitType; + bool RacialLeader; + bool RegenHealth; + uint32 equipmentId; + uint32 MechanicImmuneMask; + uint32 flags_extra; + char const* ScriptName; +}; + +struct CreatureLocale +{ + std::vector Name; + std::vector SubName; +}; + +struct EquipmentInfo +{ + uint32 entry; + uint32 equipmodel[3]; + uint32 equipinfo[3]; + uint32 equipslot[3]; +}; + +// from `creature` table +struct CreatureData +{ + uint32 id; // entry in creature_template + uint16 mapid; + uint32 displayid; + int32 equipmentId; + float posX; + float posY; + float posZ; + float orientation; + uint32 spawntimesecs; + float spawndist; + uint32 currentwaypoint; + uint32 curhealth; + uint32 curmana; + bool is_dead; + uint8 movementType; + uint8 spawnMask; +}; + +struct CreatureDataAddonAura +{ + uint16 spell_id; + uint8 effect_idx; +}; + +// from `creature_addon` table +struct CreatureDataAddon +{ + uint32 guidOrEntry; + uint32 mount; + uint32 bytes0; + uint32 bytes1; + uint32 bytes2; + uint32 emote; + uint32 move_flags; + CreatureDataAddonAura const* auras; // loaded as char* "spell1 eff1 spell2 eff2 ... " +}; + +struct CreatureModelInfo +{ + uint32 modelid; + float bounding_radius; + float combat_reach; + uint8 gender; + uint32 modelid_other_gender; +}; + +enum InhabitTypeValues +{ + INHABIT_GROUND = 1, + INHABIT_WATER = 2, + INHABIT_AIR = 4, + INHABIT_ANYWHERE = INHABIT_GROUND | INHABIT_WATER | INHABIT_AIR +}; + +// GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some platform +#if defined( __GNUC__ ) +#pragma pack() +#else +#pragma pack(pop) +#endif + +typedef std::list GossipOptionList; + +typedef std::map CreatureSpellCooldowns; + +// max different by z coordinate for creature aggro reaction +#define CREATURE_Z_ATTACK_RANGE 3 + +#define MAX_VENDOR_ITEMS 255 // Limitation in item count field size in SMSG_LIST_INVENTORY + +class MANGOS_DLL_SPEC Creature : public Unit +{ + CreatureAI *i_AI; + + public: + + explicit Creature(); + virtual ~Creature(); + + void AddToWorld(); + void RemoveFromWorld(); + + bool Create (uint32 guidlow, Map *map, uint32 Entry, uint32 team, const CreatureData *data = NULL); + bool LoadCreaturesAddon(bool reload = false); + void SelectLevel(const CreatureInfo *cinfo); + void LoadEquipment(uint32 equip_entry, bool force=false); + + uint32 GetDBTableGUIDLow() const { return m_DBTableGuid; } + char const* GetSubName() const { return GetCreatureInfo()->SubName; } + + void Update( uint32 time ); // overwrited Unit::Update + void GetRespawnCoord(float &x, float &y, float &z, float* ori = NULL, float* dist =NULL) const; + uint32 GetEquipmentId() const { return m_equipmentId; } + + bool isPet() const { return m_isPet; } + void SetCorpseDelay(uint32 delay) { m_corpseDelay = delay; } + bool isTotem() const { return m_isTotem; } + bool isRacialLeader() const { return GetCreatureInfo()->RacialLeader; } + bool isCivilian() const { return GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_CIVILIAN; } + bool canWalk() const { return GetCreatureInfo()->InhabitType & INHABIT_GROUND; } + bool canSwim() const { return GetCreatureInfo()->InhabitType & INHABIT_WATER; } + bool canFly() const { return GetCreatureInfo()->InhabitType & INHABIT_AIR; } + ///// TODO RENAME THIS!!!!! + bool isCanTrainingOf(Player* player, bool msg) const; + bool isCanIneractWithBattleMaster(Player* player, bool msg) const; + bool isCanTrainingAndResetTalentsOf(Player* pPlayer) const; + bool IsOutOfThreatArea(Unit* pVictim) const; + bool IsImmunedToSpell(SpellEntry const* spellInfo, bool useCharges = false); + // redefine Unit::IsImmunedToSpell + bool IsImmunedToSpellEffect(uint32 effect, uint32 mechanic) const; + // redefine Unit::IsImmunedToSpellEffect + bool isElite() const + { + if(isPet()) + return false; + + uint32 rank = GetCreatureInfo()->rank; + return rank != CREATURE_ELITE_NORMAL && rank != CREATURE_ELITE_RARE; + } + + bool isWorldBoss() const + { + if(isPet()) + return false; + + return GetCreatureInfo()->rank == CREATURE_ELITE_WORLDBOSS; + } + + uint32 getLevelForTarget(Unit const* target) const; // overwrite Unit::getLevelForTarget for boss level support + + bool IsInEvadeMode() const; + + bool AIM_Initialize(); + + void AI_SendMoveToPacket(float x, float y, float z, uint32 time, uint32 MovementFlags, uint8 type); + CreatureAI* AI() { return i_AI; } + + uint32 GetShieldBlockValue() const //dunno mob block value + { + return (getLevel()/2 + uint32(GetStat(STAT_STRENGTH)/20)); + } + + SpellSchoolMask GetMeleeDamageSchoolMask() const { return m_meleeDamageSchoolMask; } + void SetMeleeDamageSchool(SpellSchools school) { m_meleeDamageSchoolMask = SpellSchoolMask(1 << school); } + + void _AddCreatureSpellCooldown(uint32 spell_id, time_t end_time); + void _AddCreatureCategoryCooldown(uint32 category, time_t apply_time); + void AddCreatureSpellCooldown(uint32 spellid); + bool HasSpellCooldown(uint32 spell_id) const; + bool HasCategoryCooldown(uint32 spell_id) const; + + bool HasSpell(uint32 spellID) const; + + bool UpdateEntry(uint32 entry, uint32 team=ALLIANCE, const CreatureData* data=NULL); + bool UpdateStats(Stats stat); + bool UpdateAllStats(); + void UpdateResistances(uint32 school); + void UpdateArmor(); + void UpdateMaxHealth(); + void UpdateMaxPower(Powers power); + void UpdateAttackPowerAndDamage(bool ranged = false); + void UpdateDamagePhysical(WeaponAttackType attType); + uint32 GetCurrentEquipmentId() { return m_equipmentId; } + float GetSpellDamageMod(int32 Rank); + + /*********************************************************/ + /*** VENDOR SYSTEM ***/ + /*********************************************************/ + void LoadGoods(); // must be called before access to vendor items, lazy loading at first call + void ReloadGoods() { m_itemsLoaded = false; LoadGoods(); } + + CreatureItem* GetItem(uint32 slot) + { + if(slot>=m_vendor_items.size()) return NULL; + return &m_vendor_items[slot]; + } + uint8 GetItemCount() const { return m_vendor_items.size(); } + void AddItem( uint32 item, uint32 maxcount, uint32 ptime, uint32 ExtendedCost) + { + m_vendor_items.push_back(CreatureItem(item, maxcount, ptime, ExtendedCost)); + } + bool RemoveItem( uint32 item_id ) + { + for(CreatureItems::iterator i = m_vendor_items.begin(); i != m_vendor_items.end(); ++i ) + { + if(i->id==item_id) + { + m_vendor_items.erase(i); + return true; + } + } + return false; + } + CreatureItem* FindItem(uint32 item_id) + { + for(CreatureItems::iterator i = m_vendor_items.begin(); i != m_vendor_items.end(); ++i ) + if(i->id==item_id) + return &*i; + return NULL; + } + + /*********************************************************/ + /*** TRAINER SYSTEM ***/ + /*********************************************************/ + typedef std::list SpellsList; + void LoadTrainerSpells(); // must be called before access to trainer spells, lazy loading at first call + void ReloadTrainerSpells() { m_trainerSpellsLoaded = false; LoadTrainerSpells(); } + SpellsList const& GetTrainerSpells() const { return m_trainer_spells; } + uint32 GetTrainerType() const { return m_trainer_type; } + + CreatureInfo const *GetCreatureInfo() const { return m_creatureInfo; } + CreatureDataAddon const* GetCreatureAddon() const; + char const* GetScriptName() const; + + void prepareGossipMenu( Player *pPlayer,uint32 gossipid ); + void sendPreparedGossip( Player* player); + void OnGossipSelect(Player* player, uint32 option); + void OnPoiSelect(Player* player, GossipOption const *gossip); + + uint32 GetGossipTextId(uint32 action, uint32 zoneid); + uint32 GetNpcTextId(); + void LoadGossipOptions(); + GossipOption const* GetGossipOption( uint32 id ) const; + void addGossipOption(GossipOption const& gso) { m_goptions.push_back(gso); } + + void setEmoteState(uint8 emote) { m_emoteState = emote; }; + void Say(const char* text, uint32 language, uint64 TargetGuid) { MonsterSay(text,language,TargetGuid); } + void Yell(const char* text, uint32 language, uint64 TargetGuid) { MonsterYell(text,language,TargetGuid); } + void TextEmote(const char* text, uint64 TargetGuid, bool IsBossEmote = false) { MonsterTextEmote(text,TargetGuid,IsBossEmote); } + void Whisper(const char* text, uint64 receiver, bool IsBossWhisper = false) { MonsterWhisper(text,receiver,IsBossWhisper); } + void Say(int32 textId, uint32 language, uint64 TargetGuid) { MonsterSay(textId,language,TargetGuid); } + void Yell(int32 textId, uint32 language, uint64 TargetGuid) { MonsterYell(textId,language,TargetGuid); } + void TextEmote(int32 textId, uint64 TargetGuid, bool IsBossEmote = false) { MonsterTextEmote(textId,TargetGuid,IsBossEmote); } + void Whisper(int32 textId, uint64 receiver, bool IsBossWhisper = false) { MonsterWhisper(textId,receiver,IsBossWhisper); } + + void setDeathState(DeathState s); // overwrite virtual Unit::setDeathState + + bool LoadFromDB(uint32 guid, Map *map); + void SaveToDB(); + // overwrited in Pet + virtual void SaveToDB(uint32 mapid, uint8 spawnMask); + virtual void DeleteFromDB(); // overwrited in Pet + + Loot loot; + bool lootForPickPocketed; + bool lootForBody; + Player *GetLootRecipient() const; + bool hasLootRecipient() const { return m_lootRecipient!=0; } + + void SetLootRecipient (Unit* unit); + void AllLootRemovedFromCorpse(); + + SpellEntry const *reachWithSpellAttack(Unit *pVictim); + SpellEntry const *reachWithSpellCure(Unit *pVictim); + + uint32 m_spells[CREATURE_MAX_SPELLS]; + CreatureSpellCooldowns m_CreatureSpellCooldowns; + CreatureSpellCooldowns m_CreatureCategoryCooldowns; + uint32 m_GlobalCooldown; + + float GetAttackDistance(Unit const* pl) const; + + void CallAssistence(); + void SetNoCallAssistence(bool val) { m_AlreadyCallAssistence = val; } + + MovementGeneratorType GetDefaultMovementType() const { return m_defaultMovementType; } + void SetDefaultMovementType(MovementGeneratorType mgt) { m_defaultMovementType = mgt; } + + // for use only in LoadHelper, Map::Add Map::CreatureCellRelocation + Cell const& GetCurrentCell() const { return m_currentCell; } + void SetCurrentCell(Cell const& cell) { m_currentCell = cell; } + + bool IsVisibleInGridForPlayer(Player* pl) const; + + void RemoveCorpse(); + + time_t const& GetRespawnTime() const { return m_respawnTime; } + time_t GetRespawnTimeEx() const; + void SetRespawnTime(uint32 respawn) { m_respawnTime = respawn ? time(NULL) + respawn : 0; } + void Respawn(); + void SaveRespawnTime(); + + uint32 GetRespawnDelay() const { return m_respawnDelay; } + void SetRespawnDelay(uint32 delay) { m_respawnDelay = delay; } + + float GetRespawnRadius() const { return m_respawnradius; } + void SetRespawnRadius(float dist) { m_respawnradius = dist; } + + uint32 m_groupLootTimer; // (msecs)timer used for group loot + uint64 lootingGroupLeaderGUID; // used to find group which is looting corpse + + void SendZoneUnderAttackMessage(Player* attacker); + + bool hasQuest(uint32 quest_id) const; + bool hasInvolvedQuest(uint32 quest_id) const; + + GridReference &GetGridRef() { return m_gridRef; } + bool isRegeneratingHealth() { return m_regenHealth; } + virtual uint8 GetPetAutoSpellSize() const { return CREATURE_MAX_SPELLS; } + virtual uint32 GetPetAutoSpellOnPos(uint8 pos) const + { + if (pos >= CREATURE_MAX_SPELLS || m_charmInfo->GetCharmSpell(pos)->active != ACT_ENABLED) + return 0; + else + return m_charmInfo->GetCharmSpell(pos)->spellId; + } + + void SetCombatStartPosition(float x, float y, float z) { CombatStartX = x; CombatStartY = y; CombatStartZ = z; } + void GetCombatStartPosition(float &x, float &y, float &z) { x = CombatStartX; y = CombatStartY; z = CombatStartZ; } + + protected: + bool CreateFromProto(uint32 guidlow,uint32 Entry,uint32 team, const CreatureData *data = NULL); + bool InitEntry(uint32 entry, uint32 team=ALLIANCE, const CreatureData* data=NULL); + + // vendor items + typedef std::vector CreatureItems; + CreatureItems m_vendor_items; + bool m_itemsLoaded; // vendor items loading state + + // trainer spells + bool m_trainerSpellsLoaded; // trainer spells loading state + SpellsList m_trainer_spells; + uint32 m_trainer_type; // trainer type based at trainer spells, can be different from creature_template value. + // req. for correct show non-prof. trainers like weaponmaster. + void _RealtimeSetCreatureInfo(); + + static float _GetHealthMod(int32 Rank); + static float _GetDamageMod(int32 Rank); + + uint32 m_lootMoney; + uint64 m_lootRecipient; + + /// Timers + uint32 m_deathTimer; // (msecs)timer for death or corpse disappearance + time_t m_respawnTime; // (secs) time of next respawn + uint32 m_respawnDelay; // (secs) delay between corpse disappearance and respawning + uint32 m_corpseDelay; // (secs) delay between death and corpse disappearance + float m_respawnradius; + + bool m_gossipOptionLoaded; + GossipOptionList m_goptions; + uint32 m_NPCTextId; // cached value + + uint8 m_emoteState; + bool m_isPet; // set only in Pet::Pet + bool m_isTotem; // set only in Totem::Totem + void RegenerateMana(); + void RegenerateHealth(); + uint32 m_regenTimer; + MovementGeneratorType m_defaultMovementType; + Cell m_currentCell; // store current cell where creature listed + uint32 m_DBTableGuid; + uint32 m_equipmentId; + + bool m_AlreadyCallAssistence; + bool m_regenHealth; + bool m_AI_locked; + bool m_isDeadByDefault; + + SpellSchoolMask m_meleeDamageSchoolMask; + uint32 m_originalEntry; + + float CombatStartX; + float CombatStartY; + float CombatStartZ; + private: + GridReference m_gridRef; + CreatureInfo const* m_creatureInfo; // in heroic mode can different from ObjMgr::GetCreatureTemplate(GetEntry()) +}; +#endif diff --git a/src/game/CreatureAI.cpp b/src/game/CreatureAI.cpp new file mode 100644 index 00000000000..06b3d447327 --- /dev/null +++ b/src/game/CreatureAI.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "CreatureAI.h" +#include "HateMatrix.h" + +CreatureAI::~CreatureAI() +{ +} + +uint32 HateBinder::si_noHateValue=0; diff --git a/src/game/CreatureAI.h b/src/game/CreatureAI.h new file mode 100644 index 00000000000..185fb571bb2 --- /dev/null +++ b/src/game/CreatureAI.h @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_CREATUREAI_H +#define MANGOS_CREATUREAI_H + +#include "Common.h" +#include "Platform/Define.h" +#include "Policies/Singleton.h" +#include "Dynamic/ObjectRegistry.h" +#include "Dynamic/FactoryHolder.h" + +class Unit; +class Creature; +struct SpellEntry; + +#define TIME_INTERVAL_LOOK 5000 +#define VISIBILITY_RANGE 10000 + +class MANGOS_DLL_SPEC CreatureAI +{ + public: + + virtual ~CreatureAI(); + + // Called if IsVisible(Unit *who) is true at each *who move + virtual void MoveInLineOfSight(Unit *) = 0; + + // Called at each attack of m_creature by any victim + virtual void AttackStart(Unit *) = 0; + + // Called at stopping attack by any attacker + virtual void EnterEvadeMode() = 0; + + // Called at any heal cast/item used (call non implemented) + virtual void HealBy(Unit * /*healer*/, uint32 /*amount_healed*/) {} + + // Called at any Damage to any victim (before damage apply) + virtual void DamageDeal(Unit * /*done_to*/, uint32 & /*damage*/) {} + + // Called at any Damage from any attacker (before damage apply) + virtual void DamageTaken(Unit *done_by, uint32 & /*damage*/) { AttackedBy(done_by); } + + // Is unit visible for MoveInLineOfSight + virtual bool IsVisible(Unit *) const = 0; + + // Called at World update tick + virtual void UpdateAI(const uint32 diff ) = 0; + + // Called when the creature is killed + virtual void JustDied(Unit *) {} + + // Called when the creature kills a unit + virtual void KilledUnit(Unit *) {} + + // Called when the creature summon successfully other creature + virtual void JustSummoned(Creature* ) {} + + virtual void SummonedCreatureDespawn(Creature* /*unit*/) {} + + // Called when hit by a spell + virtual void SpellHit(Unit*, const SpellEntry*) {} + + // Called when vitim entered water and creature can not enter water + virtual bool canReachByRangeAttack(Unit*) { return false; } + + // Called when the creature is attacked + virtual void AttackedBy(Unit * /*attacker*/) {} + + // Called when creature is spawned or respawned (for reseting variables) + virtual void JustRespawned() {} + + // Called at waypoint reached or point movement finished + virtual void MovementInform(uint32 /*MovementType*/, uint32 /*Data*/) {} +}; + +struct SelectableAI : public FactoryHolder, public Permissible +{ + + SelectableAI(const char *id) : FactoryHolder(id) {} +}; + +template +struct CreatureAIFactory : public SelectableAI +{ + CreatureAIFactory(const char *name) : SelectableAI(name) {} + + CreatureAI* Create(void *) const; + + int Permit(const Creature *c) const { return REAL_AI::Permissible(c); } +}; + +enum Permitions +{ + PERMIT_BASE_NO = -1, + PERMIT_BASE_IDLE = 1, + PERMIT_BASE_REACTIVE = 100, + PERMIT_BASE_PROACTIVE = 200, + PERMIT_BASE_FACTION_SPECIFIC = 400, + PERMIT_BASE_SPECIAL = 800 +}; + +typedef FactoryHolder CreatureAICreator; +typedef FactoryHolder::FactoryHolderRegistry CreatureAIRegistry; +typedef FactoryHolder::FactoryHolderRepository CreatureAIRepository; +#endif diff --git a/src/game/CreatureAIImpl.h b/src/game/CreatureAIImpl.h new file mode 100644 index 00000000000..65ac4708238 --- /dev/null +++ b/src/game/CreatureAIImpl.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef CREATUREAIIMPL_H +#define CREATUREAIIMPL_H + +#include "CreatureAI.h" + +template +inline CreatureAI* +CreatureAIFactory::Create(void *data) const +{ + Creature* creature = reinterpret_cast(data); + return (new REAL_AI(*creature)); +} +#endif diff --git a/src/game/CreatureAIRegistry.cpp b/src/game/CreatureAIRegistry.cpp new file mode 100644 index 00000000000..3a5e3dcfc91 --- /dev/null +++ b/src/game/CreatureAIRegistry.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "CreatureAIRegistry.h" +#include "NullCreatureAI.h" +#include "ReactorAI.h" +#include "AggressorAI.h" +#include "GuardAI.h" +#include "PetAI.h" +#include "TotemAI.h" +#include "RandomMovementGenerator.h" +#include "CreatureAIImpl.h" +#include "MovementGeneratorImpl.h" +#include "MapManager.h" +#include "CreatureAIRegistry.h" +#include "WaypointMovementGenerator.h" + +namespace AIRegistry +{ + void Initialize() + { + (new CreatureAIFactory("NullAI"))->RegisterSelf(); + (new CreatureAIFactory("AggressorAI"))->RegisterSelf(); + (new CreatureAIFactory("ReactorAI"))->RegisterSelf(); + (new CreatureAIFactory("GuardAI"))->RegisterSelf(); + (new CreatureAIFactory("PetAI"))->RegisterSelf(); + (new CreatureAIFactory("TotemAI"))->RegisterSelf(); + + (new MovementGeneratorFactory >(RANDOM_MOTION_TYPE))->RegisterSelf(); + (new MovementGeneratorFactory >(WAYPOINT_MOTION_TYPE))->RegisterSelf(); + } +} diff --git a/src/game/CreatureAIRegistry.h b/src/game/CreatureAIRegistry.h new file mode 100644 index 00000000000..a254b6718b2 --- /dev/null +++ b/src/game/CreatureAIRegistry.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_CREATUREAIREGISTRY_H +#define MANGOS_CREATUREAIREGISTRY_H + +namespace AIRegistry +{ + void Initialize(void); +} +#endif diff --git a/src/game/CreatureAISelector.cpp b/src/game/CreatureAISelector.cpp new file mode 100644 index 00000000000..2e8b6f1a230 --- /dev/null +++ b/src/game/CreatureAISelector.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Creature.h" +#include "CreatureAIImpl.h" +#include "CreatureAISelector.h" +#include "NullCreatureAI.h" +#include "Policies/SingletonImp.h" +#include "MovementGenerator.h" +#include "ScriptCalls.h" +#include "Pet.h" + +INSTANTIATE_SINGLETON_1(CreatureAIRegistry); +INSTANTIATE_SINGLETON_1(MovementGeneratorRegistry); + +namespace FactorySelector +{ + CreatureAI* selectAI(Creature *creature) + { + // Allow scripting AI for normal creatures and not controlled pets (guardians and mini-pets) + if((!creature->isPet() || !((Pet*)creature)->isControlled()) && !creature->isCharmed()) + if(CreatureAI* scriptedAI = Script->GetAI(creature)) + return scriptedAI; + + CreatureAIRegistry &ai_registry(CreatureAIRepository::Instance()); + assert( creature->GetCreatureInfo() != NULL ); + CreatureInfo const *cinfo=creature->GetCreatureInfo(); + + const CreatureAICreator *ai_factory = NULL; + + std::string ainame=cinfo->AIName; + + // select by script name + if( !ainame.empty()) + ai_factory = ai_registry.GetRegistryItem( ainame.c_str() ); + + // select by NPC flags + if(!ai_factory) + { + if( creature->isGuard() ) + ainame="GuardAI"; + else if(creature->isPet() || creature->isCharmed()) + ainame="PetAI"; + else if(creature->isTotem()) + ainame="TotemAI"; + + ai_factory = ai_registry.GetRegistryItem( ainame.c_str() ); + } + + // select by permit check + if(!ai_factory) + { + int best_val = -1; + typedef CreatureAIRegistry::RegistryMapType RMT; + RMT const &l = ai_registry.GetRegisteredItems(); + for( RMT::const_iterator iter = l.begin(); iter != l.end(); ++iter) + { + const CreatureAICreator *factory = iter->second; + const SelectableAI *p = dynamic_cast(factory); + assert( p != NULL ); + int val = p->Permit(creature); + if( val > best_val ) + { + best_val = val; + ai_factory = p; + } + } + } + + // select NullCreatureAI if not another cases + ainame = (ai_factory == NULL) ? "NullCreatureAI" : ai_factory->key(); + + DEBUG_LOG("Creature %u used AI is %s.", creature->GetGUIDLow(), ainame.c_str() ); + return ( ai_factory == NULL ? new NullCreatureAI : ai_factory->Create(creature) ); + } + + MovementGenerator* selectMovementGenerator(Creature *creature) + { + MovementGeneratorRegistry &mv_registry(MovementGeneratorRepository::Instance()); + assert( creature->GetCreatureInfo() != NULL ); + const MovementGeneratorCreator *mv_factory = mv_registry.GetRegistryItem( creature->GetDefaultMovementType()); + + /* if( mv_factory == NULL ) + { + int best_val = -1; + std::vector l; + mv_registry.GetRegisteredItems(l); + for( std::vector::iterator iter = l.begin(); iter != l.end(); ++iter) + { + const MovementGeneratorCreator *factory = mv_registry.GetRegistryItem((*iter).c_str()); + const SelectableMovement *p = dynamic_cast(factory); + assert( p != NULL ); + int val = p->Permit(creature); + if( val > best_val ) + { + best_val = val; + mv_factory = p; + } + } + }*/ + + return ( mv_factory == NULL ? NULL : mv_factory->Create(creature) ); + + } +} diff --git a/src/game/CreatureAISelector.h b/src/game/CreatureAISelector.h new file mode 100644 index 00000000000..328850dbc3d --- /dev/null +++ b/src/game/CreatureAISelector.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_CREATUREAISELECTOR_H +#define MANGOS_CREATUREAISELECTOR_H + +class CreatureAI; +class Creature; +class MovementGenerator; + +namespace FactorySelector +{ + CreatureAI* selectAI(Creature *); + MovementGenerator* selectMovementGenerator(Creature *); +} +#endif diff --git a/src/game/DestinationHolder.cpp b/src/game/DestinationHolder.cpp new file mode 100644 index 00000000000..2c427ad7702 --- /dev/null +++ b/src/game/DestinationHolder.cpp @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "DestinationHolder.h" diff --git a/src/game/DestinationHolder.h b/src/game/DestinationHolder.h new file mode 100644 index 00000000000..93705bb67cb --- /dev/null +++ b/src/game/DestinationHolder.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_DESTINATION_HOLDER_H +#define MANGOS_DESTINATION_HOLDER_H + +#include "Platform/Define.h" +#include "Timer.h" + +class WorldObject; + +#define TRAVELLER_UPDATE_INTERVAL 300 + +template +class MANGOS_DLL_DECL DestinationHolder +{ + TimeTrackerSmall i_tracker; + uint32 i_totalTravelTime; + uint32 i_timeElapsed; + bool i_destSet; + float i_fromX, i_fromY, i_fromZ; + float i_destX, i_destY, i_destZ; + + public: + DestinationHolder() : i_tracker(TRAVELLER_UPDATE_INTERVAL), i_totalTravelTime(0), i_timeElapsed(0), + i_destSet(false), i_fromX(0), i_fromY(0), i_fromZ(0), i_destX(0), i_destY(0), i_destZ(0) {} + + uint32 SetDestination(TRAVELLER &traveller, float dest_x, float dest_y, float dest_z, bool sendMove = true); + void GetDestination(float &x, float &y, float &z) const { x = i_destX; y = i_destY; z = i_destZ; } + bool UpdateExpired(void) const { return i_tracker.Passed(); } + void ResetUpdate(uint32 t = TRAVELLER_UPDATE_INTERVAL) { i_tracker.Reset(t); } + uint32 GetTotalTravelTime(void) const { return i_totalTravelTime; } + void IncreaseTravelTime(uint32 increment) { i_totalTravelTime += increment; } + bool HasDestination(void) const { return i_destSet; } + float GetDestinationDiff(float x, float y, float z) const; + bool HasArrived(void) const { return (i_totalTravelTime == 0 || i_timeElapsed >= i_totalTravelTime); } + bool UpdateTraveller(TRAVELLER &traveller, uint32 diff, bool force_update=false, bool micro_movement=false); + uint32 StartTravel(TRAVELLER &traveller, bool sendMove = true); + void GetLocationNow(uint32 mapid, float &x, float &y, float &z, bool is3D = false) const; + void GetLocationNowNoMicroMovement(float &x, float &y, float &z) const; // For use without micro movement + float GetDistance2dFromDestSq(const WorldObject &obj) const; + + private: + void _findOffSetPoint(float x1, float y1, float x2, float y2, float offset, float &x, float &y); + +}; +#endif diff --git a/src/game/DestinationHolderImp.h b/src/game/DestinationHolderImp.h new file mode 100644 index 00000000000..8f5efa54b0c --- /dev/null +++ b/src/game/DestinationHolderImp.h @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_DESTINATIONHOLDERIMP_H +#define MANGOS_DESTINATIONHOLDERIMP_H + +#include "Creature.h" +#include "MapManager.h" +#include "DestinationHolder.h" + +#include + +template +void +DestinationHolder::_findOffSetPoint(float x1, float y1, float x2, float y2, float offset, float &x, float &y) +{ + /* given the point (x1, y1) and (x2, y2).. need to find the point (x,y) on the same line + * such that the distance from (x, y) to (x2, y2) is offset. + * Let the distance of p1 to p2 = d.. then the ratio of offset/d = (x2-x)/(x2-x1) + * hence x = x2 - (offset/d)*(x2-x1) + * like wise offset/d = (y2-y)/(y2-y1); + */ + if( offset == 0 ) + { + x = x2; + y = y2; + } + else + { + double x_diff = double(x2 - x1); + double y_diff = double(y2 - y1); + double distance_d = (double)((x_diff*x_diff) + (y_diff * y_diff)); + if(distance_d == 0) + { + x = x2; + y = y2; + } + else + { + distance_d = ::sqrt(distance_d); // starting distance + double distance_ratio = (double)(distance_d - offset)/(double)distance_d; + // line above has revised formula which is more correct, I think + x = (float)(x1 + (distance_ratio*x_diff)); + y = (float)(y1 + (distance_ratio*y_diff)); + } + } +} + +template +uint32 +DestinationHolder::SetDestination(TRAVELLER &traveller, float dest_x, float dest_y, float dest_z, bool sendMove) +{ + i_destSet = true; + i_destX = dest_x; + i_destY = dest_y; + i_destZ = dest_z; + + return StartTravel(traveller, sendMove); +} + +template +uint32 +DestinationHolder::StartTravel(TRAVELLER &traveller, bool sendMove) +{ + if(!i_destSet) return 0; + + i_fromX = traveller.GetPositionX(); + i_fromY = traveller.GetPositionY(); + i_fromZ = traveller.GetPositionZ(); + + float dx = i_destX - i_fromX; + float dy = i_destY - i_fromY; + float dz = i_destZ - i_fromZ; + + float dist; + //Should be for Creature Flying and Swimming. + if(traveller.GetTraveller().hasUnitState(UNIT_STAT_IN_FLIGHT)) + dist = sqrt((dx*dx) + (dy*dy) + (dz*dz)); + else //Walking on the ground + dist = sqrt((dx*dx) + (dy*dy)); + float speed = traveller.Speed(); + + speed *= 0.001f; // speed is in seconds so convert from second to millisecond + i_totalTravelTime = static_cast(dist/speed); + i_timeElapsed = 0; + if(sendMove) + traveller.MoveTo(i_destX, i_destY, i_destZ, i_totalTravelTime); + return i_totalTravelTime; +} + +template +bool +DestinationHolder::UpdateTraveller(TRAVELLER &traveller, uint32 diff, bool force_update, bool micro_movement) +{ + if(!micro_movement) + { + i_tracker.Update(diff); + i_timeElapsed += diff; + if( i_tracker.Passed() || force_update ) + { + ResetUpdate(); + if(!i_destSet) return true; + float x,y,z; + GetLocationNowNoMicroMovement(x, y, z); + if( x == -431602080 ) + return false; + if( traveller.GetTraveller().GetPositionX() != x || traveller.GetTraveller().GetPositionY() != y ) + { + float ori = traveller.GetTraveller().GetAngle(x, y); + traveller.Relocation(x, y, z, ori); + } + return true; + } + return false; + } + i_tracker.Update(diff); + i_timeElapsed += diff; + if( i_tracker.Passed() || force_update ) + { + ResetUpdate(); + if(!i_destSet) return true; + float x,y,z; + + if(!traveller.GetTraveller().hasUnitState(UNIT_STAT_MOVING | UNIT_STAT_IN_FLIGHT)) + return true; + + if(traveller.GetTraveller().hasUnitState(UNIT_STAT_IN_FLIGHT)) + GetLocationNow(traveller.GetTraveller().GetMapId() ,x, y, z, true); // Should repositione Object with right Coord, so I can bypass some Grid Relocation + else + GetLocationNow(traveller.GetTraveller().GetMapId(), x, y, z, false); + + if( x == -431602080 ) + return false; + + if( traveller.GetTraveller().GetPositionX() != x || traveller.GetTraveller().GetPositionY() != y ) + { + float ori = traveller.GetTraveller().GetAngle(x, y); + traveller.Relocation(x, y, z, ori); + } + // Change movement computation to micro movement based on last tick coords, this makes system work + // even on multiple floors zones without hugh vmaps usage ;) + + // Take care of underrun of uint32 + if (i_totalTravelTime >= i_timeElapsed) + i_totalTravelTime -= i_timeElapsed; // Consider only the remaining part + else + i_totalTravelTime = 0; + + i_timeElapsed = 0; + i_fromX = x; // and change origine + i_fromY = y; // then I take into account only micro movement + i_fromZ = z; + return true; + } + return false; +} + +template +void +DestinationHolder::GetLocationNow(uint32 mapid, float &x, float &y, float &z, bool is3D) const +{ + if( HasArrived() ) + { + x = i_destX; + y = i_destY; + z = i_destZ; + } + else if(HasDestination()) + { + double percent_passed = (double)i_timeElapsed / (double)i_totalTravelTime; + const float distanceX = ((i_destX - i_fromX) * percent_passed); + const float distanceY = ((i_destY - i_fromY) * percent_passed); + const float distanceZ = ((i_destZ - i_fromZ) * percent_passed); + x = i_fromX + distanceX; + y = i_fromY + distanceY; + float z2 = i_fromZ + distanceZ; + // All that is not finished but previous code neither... Traveller need be able to swim. + if(is3D) + z = z2; + else + { + //That part is good for mob Walking on the floor. But the floor is not allways what we thought. + z = MapManager::Instance().GetBaseMap(mapid)->GetHeight(x,y,i_fromZ,false); // Disable cave check + const float groundDist = sqrt(distanceX*distanceX + distanceY*distanceY); + const float zDist = fabs(i_fromZ - z) + 0.000001f; + const float slope = groundDist / zDist; + if(slope < 1.0f) // This prevents the ground returned by GetHeight to be used when in cave + z = z2; // a climb or jump of more than 45 is denied + } + } +} + +template +float +DestinationHolder::GetDistance2dFromDestSq(const WorldObject &obj) const +{ + float x,y,z; + obj.GetPosition(x,y,z); + return (i_destX-x)*(i_destX-x)+(i_destY-y)*(i_destY-y); +} + +template +float +DestinationHolder::GetDestinationDiff(float x, float y, float z) const +{ + return sqrt(((x-i_destX)*(x-i_destX)) + ((y-i_destY)*(y-i_destY)) + ((z-i_destZ)*(z-i_destZ))); +} + +template +void +DestinationHolder::GetLocationNowNoMicroMovement(float &x, float &y, float &z) const +{ + if( HasArrived() ) + { + x = i_destX; + y = i_destY; + z = i_destZ; + } + else + { + double percent_passed = (double)i_timeElapsed / (double)i_totalTravelTime; + x = i_fromX + ((i_destX - i_fromX) * percent_passed); + y = i_fromY + ((i_destY - i_fromY) * percent_passed); + z = i_fromZ + ((i_destZ - i_fromZ) * percent_passed); + } +} + +#endif diff --git a/src/game/DuelHandler.cpp b/src/game/DuelHandler.cpp new file mode 100644 index 00000000000..1019c68d908 --- /dev/null +++ b/src/game/DuelHandler.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "World.h" +#include "Log.h" +#include "Opcodes.h" +#include "UpdateData.h" +#include "MapManager.h" +#include "Player.h" + +void WorldSession::HandleDuelAcceptedOpcode(WorldPacket& recvPacket) +{ + CHECK_PACKET_SIZE(recvPacket,8); + + uint64 guid; + Player *pl; + Player *plTarget; + + if(!GetPlayer()->duel) // ignore accept from duel-sender + return; + + recvPacket >> guid; + + pl = GetPlayer(); + plTarget = pl->duel->opponent; + + if(pl == pl->duel->initiator || !plTarget || pl == plTarget || pl->duel->startTime != 0 || plTarget->duel->startTime != 0) + return; + + //sLog.outDebug( "WORLD: received CMSG_DUEL_ACCEPTED" ); + DEBUG_LOG("Player 1 is: %u (%s)", pl->GetGUIDLow(),pl->GetName()); + DEBUG_LOG("Player 2 is: %u (%s)", plTarget->GetGUIDLow(),plTarget->GetName()); + + time_t now = time(NULL); + pl->duel->startTimer = now; + plTarget->duel->startTimer = now; + + WorldPacket data(SMSG_DUEL_COUNTDOWN, 4); + data << (uint32)3000; // 3 seconds + pl->GetSession()->SendPacket(&data); + plTarget->GetSession()->SendPacket(&data); +} + +void WorldSession::HandleDuelCancelledOpcode(WorldPacket& recvPacket) +{ + CHECK_PACKET_SIZE(recvPacket,8); + + //sLog.outDebug( "WORLD: received CMSG_DUEL_CANCELLED" ); + + // no duel requested + if(!GetPlayer()->duel) + return; + + // player surrendered in a duel using /forfeit + if(GetPlayer()->duel->startTime != 0) + { + GetPlayer()->CombatStopWithPets(true); + if(GetPlayer()->duel->opponent) + GetPlayer()->duel->opponent->CombatStopWithPets(true); + + GetPlayer()->CastSpell(GetPlayer(), 7267, true); // beg + GetPlayer()->DuelComplete(DUEL_WON); + return; + } + + // player either discarded the duel using the "discard button" + // or used "/forfeit" before countdown reached 0 + uint64 guid; + recvPacket >> guid; + + GetPlayer()->DuelComplete(DUEL_INTERUPTED); +} diff --git a/src/game/DynamicObject.cpp b/src/game/DynamicObject.cpp new file mode 100644 index 00000000000..d01a6f84a4d --- /dev/null +++ b/src/game/DynamicObject.cpp @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "GameObject.h" +#include "UpdateMask.h" +#include "Opcodes.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "World.h" +#include "ObjectAccessor.h" +#include "Database/DatabaseEnv.h" +#include "SpellAuras.h" +#include "MapManager.h" +#include "GridNotifiers.h" +#include "CellImpl.h" +#include "GridNotifiersImpl.h" + +DynamicObject::DynamicObject() : WorldObject() +{ + m_objectType |= TYPEMASK_DYNAMICOBJECT; + m_objectTypeId = TYPEID_DYNAMICOBJECT; + // 2.3.2 - 0x58 + m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HASPOSITION); + + m_valuesCount = DYNAMICOBJECT_END; +} + +void DynamicObject::AddToWorld() +{ + ///- Register the dynamicObject for guid lookup + if(!IsInWorld()) ObjectAccessor::Instance().AddObject(this); + Object::AddToWorld(); +} + +void DynamicObject::RemoveFromWorld() +{ + ///- Remove the dynamicObject from the accessor + if(IsInWorld()) ObjectAccessor::Instance().RemoveObject(this); + Object::RemoveFromWorld(); +} + +bool DynamicObject::Create( uint32 guidlow, Unit *caster, uint32 spellId, uint32 effIndex, float x, float y, float z, int32 duration, float radius ) +{ + SetInstanceId(caster->GetInstanceId()); + + WorldObject::_Create(guidlow, HIGHGUID_DYNAMICOBJECT, caster->GetMapId()); + Relocate(x,y,z,0); + + if(!IsPositionValid()) + { + sLog.outError("ERROR: DynamicObject (spell %u eff %u) not created. Suggested coordinates isn't valid (X: %f Y: %f)",spellId,effIndex,GetPositionX(),GetPositionY()); + return false; + } + + SetUInt32Value( OBJECT_FIELD_ENTRY, spellId ); + SetFloatValue( OBJECT_FIELD_SCALE_X, 1 ); + SetUInt64Value( DYNAMICOBJECT_CASTER, caster->GetGUID() ); + SetUInt32Value( DYNAMICOBJECT_BYTES, 0x00000001 ); + SetUInt32Value( DYNAMICOBJECT_SPELLID, spellId ); + SetFloatValue( DYNAMICOBJECT_RADIUS, radius); + SetFloatValue( DYNAMICOBJECT_POS_X, x ); + SetFloatValue( DYNAMICOBJECT_POS_Y, y ); + SetFloatValue( DYNAMICOBJECT_POS_Z, z ); + SetUInt32Value( DYNAMICOBJECT_CASTTIME, getMSTime() ); // new 2.4.0 + + m_aliveDuration = duration; + m_radius = radius; + m_effIndex = effIndex; + m_spellId = spellId; + m_casterGuid = caster->GetGUID(); + return true; +} + +Unit* DynamicObject::GetCaster() const +{ + // can be not found in some cases + return ObjectAccessor::GetUnit(*this,m_casterGuid); +} + +void DynamicObject::Update(uint32 p_time) +{ + // caster can be not in world at time dynamic object update, but dynamic object not yet deleted in Unit destructor + Unit* caster = GetCaster(); + if(!caster) + { + Delete(); + return; + } + + bool deleteThis = false; + + if(m_aliveDuration > int32(p_time)) + m_aliveDuration -= p_time; + else + deleteThis = true; + + // TODO: make a timer and update this in larger intervals + CellPair p(MaNGOS::ComputeCellPair(GetPositionX(), GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + MaNGOS::DynamicObjectUpdater notifier(*this,caster); + + TypeContainerVisitor world_object_notifier(notifier); + TypeContainerVisitor grid_object_notifier(notifier); + + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, world_object_notifier, *MapManager::Instance().GetMap(GetMapId(), this)); + cell_lock->Visit(cell_lock, grid_object_notifier, *MapManager::Instance().GetMap(GetMapId(), this)); + + if(deleteThis) + { + caster->RemoveDynObjectWithGUID(GetGUID()); + Delete(); + } +} + +void DynamicObject::Delete() +{ + SendObjectDeSpawnAnim(GetGUID()); + AddObjectToRemoveList(); +} + +void DynamicObject::Delay(int32 delaytime) +{ + m_aliveDuration -= delaytime; + for(AffectedSet::iterator iunit= m_affected.begin();iunit != m_affected.end();++iunit) + if (*iunit) + (*iunit)->DelayAura(m_spellId, m_effIndex, delaytime); +} + +bool DynamicObject::isVisibleForInState(Player const* u, bool inVisibleList) const +{ + return IsInWorld() && u->IsInWorld() && IsWithinDistInMap(u,World::GetMaxVisibleDistanceForObject()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f)); +} diff --git a/src/game/DynamicObject.h b/src/game/DynamicObject.h new file mode 100644 index 00000000000..279a763d4ce --- /dev/null +++ b/src/game/DynamicObject.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOSSERVER_DYNAMICOBJECT_H +#define MANGOSSERVER_DYNAMICOBJECT_H + +#include "Object.h" + +class Unit; +struct SpellEntry; + +class DynamicObject : public WorldObject +{ + public: + typedef std::set AffectedSet; + explicit DynamicObject(); + + void AddToWorld(); + void RemoveFromWorld(); + + bool Create(uint32 guidlow, Unit *caster, uint32 spellId, uint32 effIndex, float x, float y, float z, int32 duration, float radius); + void Update(uint32 p_time); + void Delete(); + uint32 GetSpellId() const { return m_spellId; } + uint32 GetEffIndex() const { return m_effIndex; } + uint32 GetDuration() const { return m_aliveDuration; } + uint64 GetCasterGUID() const { return m_casterGuid; } + Unit* GetCaster() const; + float GetRadius() const { return m_radius; } + bool IsAffecting(Unit *unit) const { return m_affected.find(unit) != m_affected.end(); } + void AddAffected(Unit *unit) { m_affected.insert(unit); } + void RemoveAffected(Unit *unit) { m_affected.erase(unit); } + void Delay(int32 delaytime); + bool isVisibleForInState(Player const* u, bool inVisibleList) const; + + void Say(const char* text, uint32 language, uint64 TargetGuid) { MonsterSay(text,language,TargetGuid); } + void Yell(const char* text, uint32 language, uint64 TargetGuid) { MonsterYell(text,language,TargetGuid); } + void TextEmote(const char* text, uint64 TargetGuid) { MonsterTextEmote(text,TargetGuid); } + void Whisper(const char* text, uint64 receiver) { MonsterWhisper(text,receiver); } + void Say(int32 textId, uint32 language, uint64 TargetGuid) { MonsterSay(textId,language,TargetGuid); } + void Yell(int32 textId, uint32 language, uint64 TargetGuid) { MonsterYell(textId,language,TargetGuid); } + void TextEmote(int32 textId, uint64 TargetGuid) { MonsterTextEmote(textId,TargetGuid); } + void Whisper(int32 textId,uint64 receiver) { MonsterWhisper(textId,receiver); } + + GridReference &GetGridRef() { return m_gridRef; } + protected: + uint64 m_casterGuid; + uint32 m_spellId; + uint32 m_effIndex; + int32 m_aliveDuration; + time_t m_nextThinkTime; + float m_radius; + AffectedSet m_affected; + private: + GridReference m_gridRef; +}; +#endif diff --git a/src/game/FleeingMovementGenerator.cpp b/src/game/FleeingMovementGenerator.cpp new file mode 100644 index 00000000000..80ecf13922f --- /dev/null +++ b/src/game/FleeingMovementGenerator.cpp @@ -0,0 +1,379 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Creature.h" +#include "MapManager.h" +#include "FleeingMovementGenerator.h" +#include "DestinationHolderImp.h" +#include "ObjectAccessor.h" + +#define MIN_QUIET_DISTANCE 28.0f +#define MAX_QUIET_DISTANCE 43.0f + +template +void +FleeingMovementGenerator::_setTargetLocation(T &owner) +{ + if( !&owner ) + return; + + if( owner.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED) ) + return; + + if(!_setMoveData(owner)) + return; + + float x, y, z; + if(!_getPoint(owner, x, y, z)) + return; + + owner.addUnitState(UNIT_STAT_FLEEING); + Traveller traveller(owner); + i_destinationHolder.SetDestination(traveller, x, y, z); +} + +template +bool +FleeingMovementGenerator::_getPoint(T &owner, float &x, float &y, float &z) +{ + if(!&owner) + return false; + + x = owner.GetPositionX(); + y = owner.GetPositionY(); + z = owner.GetPositionZ(); + + float temp_x, temp_y, angle; + const Map * _map = MapManager::Instance().GetBaseMap(owner.GetMapId()); + //primitive path-finding + for(uint8 i = 0; i < 18; i++) + { + if(i_only_forward && i > 2) + break; + + float distance = 5.0f; + + switch(i) + { + case 0: + angle = i_cur_angle; + break; + case 1: + angle = i_cur_angle; + distance /= 2; + break; + case 2: + angle = i_cur_angle; + distance /= 4; + break; + case 3: + angle = i_cur_angle + M_PI/4.0f; + break; + case 4: + angle = i_cur_angle - M_PI/4.0f; + break; + case 5: + angle = i_cur_angle + M_PI/4.0f; + distance /= 2; + break; + case 6: + angle = i_cur_angle - M_PI/4.0f; + distance /= 2; + break; + case 7: + angle = i_cur_angle + M_PI/2.0f; + break; + case 8: + angle = i_cur_angle - M_PI/2.0f; + break; + case 9: + angle = i_cur_angle + M_PI/2.0f; + distance /= 2; + break; + case 10: + angle = i_cur_angle - M_PI/2.0f; + distance /= 2; + break; + case 11: + angle = i_cur_angle + M_PI/4.0f; + distance /= 4; + break; + case 12: + angle = i_cur_angle - M_PI/4.0f; + distance /= 4; + break; + case 13: + angle = i_cur_angle + M_PI/2.0f; + distance /= 4; + break; + case 14: + angle = i_cur_angle - M_PI/2.0f; + distance /= 4; + break; + case 15: + angle = i_cur_angle + M_PI*3/4.0f; + distance /= 2; + break; + case 16: + angle = i_cur_angle - M_PI*3/4.0f; + distance /= 2; + break; + case 17: + angle = i_cur_angle + M_PI; + distance /= 2; + break; + } + temp_x = x + distance * cos(angle); + temp_y = y + distance * sin(angle); + MaNGOS::NormalizeMapCoord(temp_x); + MaNGOS::NormalizeMapCoord(temp_y); + if( owner.IsWithinLOS(temp_x,temp_y,z)) + { + bool is_water_now = _map->IsInWater(x,y,z); + + if(is_water_now && _map->IsInWater(temp_x,temp_y,z)) + { + x = temp_x; + y = temp_y; + return true; + } + float new_z = _map->GetHeight(temp_x,temp_y,z,true); + + if(new_z <= INVALID_HEIGHT) + continue; + + bool is_water_next = _map->IsInWater(temp_x,temp_y,new_z); + + if((is_water_now && !is_water_next && !is_land_ok) || (!is_water_now && is_water_next && !is_water_ok)) + continue; + + if( !(new_z - z) || distance / fabs(new_z - z) > 1.0f) + { + float new_z_left = _map->GetHeight(temp_x + 1.0f*cos(angle+M_PI/2),temp_y + 1.0f*sin(angle+M_PI/2),z,true); + float new_z_right = _map->GetHeight(temp_x + 1.0f*cos(angle-M_PI/2),temp_y + 1.0f*sin(angle-M_PI/2),z,true); + if(fabs(new_z_left - new_z) < 1.2f && fabs(new_z_right - new_z) < 1.2f) + { + x = temp_x; + y = temp_y; + z = new_z; + return true; + } + } + } + } + i_to_distance_from_caster = 0.0f; + i_nextCheckTime.Reset( urand(500,1000) ); + return false; +} + +template +bool +FleeingMovementGenerator::_setMoveData(T &owner) +{ + float cur_dist_xyz = owner.GetDistance(i_caster_x, i_caster_y, i_caster_z); + + if(i_to_distance_from_caster > 0.0f) + { + if((i_last_distance_from_caster > i_to_distance_from_caster && cur_dist_xyz < i_to_distance_from_caster) || + // if we reach lower distance + (i_last_distance_from_caster > i_to_distance_from_caster && cur_dist_xyz > i_last_distance_from_caster) || + // if we can't be close + (i_last_distance_from_caster < i_to_distance_from_caster && cur_dist_xyz > i_to_distance_from_caster) || + // if we reach bigger distance + (cur_dist_xyz > MAX_QUIET_DISTANCE) || // if we are too far + (i_last_distance_from_caster > MIN_QUIET_DISTANCE && cur_dist_xyz < MIN_QUIET_DISTANCE) ) + // if we leave 'quiet zone' + { + // we are very far or too close, stopping + i_to_distance_from_caster = 0.0f; + i_nextCheckTime.Reset( urand(500,1000) ); + return false; + } + else + { + // now we are running, continue + i_last_distance_from_caster = cur_dist_xyz; + return true; + } + } + + float cur_dist; + float angle_to_caster; + + Unit * fright = ObjectAccessor::GetUnit(owner, i_frightGUID); + + if(fright) + { + cur_dist = fright->GetDistance(&owner); + if(cur_dist < cur_dist_xyz) + { + i_caster_x = fright->GetPositionX(); + i_caster_y = fright->GetPositionY(); + i_caster_z = fright->GetPositionZ(); + angle_to_caster = fright->GetAngle(&owner); + } + else + { + cur_dist = cur_dist_xyz; + angle_to_caster = owner.GetAngle(i_caster_x, i_caster_y) + M_PI; + } + } + else + { + cur_dist = cur_dist_xyz; + angle_to_caster = owner.GetAngle(i_caster_x, i_caster_y) + M_PI; + } + + // if we too close may use 'path-finding' else just stop + i_only_forward = cur_dist >= MIN_QUIET_DISTANCE/3; + + //get angle and 'distance from caster' to run + float angle; + + if(i_cur_angle == 0.0f && i_last_distance_from_caster == 0.0f) //just started, first time + { + angle = rand_norm()*(1.0f - cur_dist/MIN_QUIET_DISTANCE) * M_PI/3 + rand_norm()*M_PI*2/3; + i_to_distance_from_caster = MIN_QUIET_DISTANCE; + i_only_forward = true; + } + else if(cur_dist < MIN_QUIET_DISTANCE) + { + angle = M_PI/6 + rand_norm()*M_PI*2/3; + i_to_distance_from_caster = cur_dist*2/3 + rand_norm()*(MIN_QUIET_DISTANCE - cur_dist*2/3); + } + else if(cur_dist > MAX_QUIET_DISTANCE) + { + angle = rand_norm()*M_PI/3 + M_PI*2/3; + i_to_distance_from_caster = MIN_QUIET_DISTANCE + 2.5f + rand_norm()*(MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE - 2.5f); + } + else + { + angle = rand_norm()*M_PI; + i_to_distance_from_caster = MIN_QUIET_DISTANCE + 2.5f + rand_norm()*(MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE - 2.5f); + } + + int8 sign = rand_norm() > 0.5f ? 1 : -1; + i_cur_angle = sign*angle + angle_to_caster; + + // current distance + i_last_distance_from_caster = cur_dist; + + return true; +} + +template +void +FleeingMovementGenerator::Initialize(T &owner) +{ + if(!&owner) + return; + + Unit * fright = ObjectAccessor::GetUnit(owner, i_frightGUID); + if(!fright) + return; + + _Init(owner); + owner.RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + i_caster_x = fright->GetPositionX(); + i_caster_y = fright->GetPositionY(); + i_caster_z = fright->GetPositionZ(); + i_only_forward = true; + i_cur_angle = 0.0f; + i_last_distance_from_caster = 0.0f; + i_to_distance_from_caster = 0.0f; + _setTargetLocation(owner); +} + +template<> +void +FleeingMovementGenerator::_Init(Creature &owner) +{ + if(!&owner) + return; + owner.SetUInt64Value(UNIT_FIELD_TARGET, 0); + is_water_ok = owner.canSwim(); + is_land_ok = owner.canWalk(); +} + +template<> +void +FleeingMovementGenerator::_Init(Player &) +{ + is_water_ok = true; + is_land_ok = true; +} + +template +void +FleeingMovementGenerator::Finalize(T &owner) +{ + owner.clearUnitState(UNIT_STAT_FLEEING); +} + +template +void +FleeingMovementGenerator::Reset(T &owner) +{ + Initialize(owner); +} + +template +bool +FleeingMovementGenerator::Update(T &owner, const uint32 & time_diff) +{ + if( !&owner || !owner.isAlive() ) + return false; + if( owner.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED) ) + return true; + + Traveller traveller(owner); + + i_nextCheckTime.Update(time_diff); + + if( (owner.IsStopped() && !i_destinationHolder.HasArrived()) || !i_destinationHolder.HasDestination() ) + { + _setTargetLocation(owner); + return true; + } + + if (i_destinationHolder.UpdateTraveller(traveller, time_diff, false)) + { + i_destinationHolder.ResetUpdate(50); + if(i_nextCheckTime.Passed() && i_destinationHolder.HasArrived()) + { + _setTargetLocation(owner); + return true; + } + } + return true; +} + +template void FleeingMovementGenerator::Initialize(Player &); +template void FleeingMovementGenerator::Initialize(Creature &); +template bool FleeingMovementGenerator::_setMoveData(Player &); +template bool FleeingMovementGenerator::_setMoveData(Creature &); +template bool FleeingMovementGenerator::_getPoint(Player &, float &, float &, float &); +template bool FleeingMovementGenerator::_getPoint(Creature &, float &, float &, float &); +template void FleeingMovementGenerator::_setTargetLocation(Player &); +template void FleeingMovementGenerator::_setTargetLocation(Creature &); +template void FleeingMovementGenerator::Finalize(Player &); +template void FleeingMovementGenerator::Finalize(Creature &); +template void FleeingMovementGenerator::Reset(Player &); +template void FleeingMovementGenerator::Reset(Creature &); +template bool FleeingMovementGenerator::Update(Player &, const uint32 &); +template bool FleeingMovementGenerator::Update(Creature &, const uint32 &); diff --git a/src/game/FleeingMovementGenerator.h b/src/game/FleeingMovementGenerator.h new file mode 100644 index 00000000000..f0b48e27b23 --- /dev/null +++ b/src/game/FleeingMovementGenerator.h @@ -0,0 +1,62 @@ +/* +* Copyright (C) 2005-2008 MaNGOS +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef MANGOS_FLEEINGMOVEMENTGENERATOR_H +#define MANGOS_FLEEINGMOVEMENTGENERATOR_H + +#include "MovementGenerator.h" +#include "DestinationHolder.h" +#include "Traveller.h" +#include "MapManager.h" + +template +class MANGOS_DLL_SPEC FleeingMovementGenerator +: public MovementGeneratorMedium< T, FleeingMovementGenerator > +{ + public: + FleeingMovementGenerator(uint64 fright) : i_frightGUID(fright), i_nextCheckTime(0) {} + + void Initialize(T &); + void Finalize(T &); + void Reset(T &); + bool Update(T &, const uint32 &); + + MovementGeneratorType GetMovementGeneratorType() { return FLEEING_MOTION_TYPE; } + + private: + void _setTargetLocation(T &owner); + bool _getPoint(T &owner, float &x, float &y, float &z); + bool _setMoveData(T &owner); + void _Init(T &); + + bool is_water_ok :1; + bool is_land_ok :1; + bool i_only_forward:1; + + float i_caster_x; + float i_caster_y; + float i_caster_z; + float i_last_distance_from_caster; + float i_to_distance_from_caster; + float i_cur_angle; + TimeTracker i_nextCheckTime; + uint64 i_frightGUID; + + DestinationHolder< Traveller > i_destinationHolder; +}; +#endif diff --git a/src/game/FollowerRefManager.h b/src/game/FollowerRefManager.h new file mode 100644 index 00000000000..460a3612ded --- /dev/null +++ b/src/game/FollowerRefManager.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _FOLLOWERREFMANAGER +#define _FOLLOWERREFMANAGER + +#include "Utilities/LinkedReference/RefManager.h" + +class Unit; +class TargetedMovementGeneratorBase; + +class FollowerRefManager : public RefManager +{ + +}; +#endif diff --git a/src/game/FollowerReference.cpp b/src/game/FollowerReference.cpp new file mode 100644 index 00000000000..2ebea8187f5 --- /dev/null +++ b/src/game/FollowerReference.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Unit.h" +#include "TargetedMovementGenerator.h" +#include "FollowerReference.h" + +void FollowerReference::targetObjectBuildLink() +{ + getTarget()->addFollower(this); +} + +void FollowerReference::targetObjectDestroyLink() +{ + getTarget()->removeFollower(this); +} + +void FollowerReference::sourceObjectDestroyLink() +{ + getSource()->stopFollowing(); +} diff --git a/src/game/FollowerReference.h b/src/game/FollowerReference.h new file mode 100644 index 00000000000..3a79d8cedb0 --- /dev/null +++ b/src/game/FollowerReference.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _FOLLOWERREFERENCE_H +#define _FOLLOWERREFERENCE_H + +#include "Utilities/LinkedReference/Reference.h" + +class TargetedMovementGeneratorBase; +class Unit; + +class MANGOS_DLL_SPEC FollowerReference : public Reference +{ + protected: + void targetObjectBuildLink(); + void targetObjectDestroyLink(); + void sourceObjectDestroyLink(); +}; +#endif diff --git a/src/game/Formulas.h b/src/game/Formulas.h new file mode 100644 index 00000000000..a7ef3200e73 --- /dev/null +++ b/src/game/Formulas.h @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_FORMULAS_H +#define MANGOS_FORMULAS_H + +#include "World.h" + +namespace MaNGOS +{ + namespace XP + { + typedef enum XPColorChar { RED, ORANGE, YELLOW, GREEN, GRAY }; + + inline uint32 GetGrayLevel(uint32 pl_level) + { + if( pl_level <= 5 ) + return 0; + else if( pl_level <= 39 ) + return pl_level - 5 - pl_level/10; + else if( pl_level <= 59 ) + return pl_level - 1 - pl_level/5; + else + return pl_level - 9; + } + + inline XPColorChar GetColorCode(uint32 pl_level, uint32 mob_level) + { + if( mob_level >= pl_level + 5 ) + return RED; + else if( mob_level >= pl_level + 3 ) + return ORANGE; + else if( mob_level >= pl_level - 2 ) + return YELLOW; + else if( mob_level > GetGrayLevel(pl_level) ) + return GREEN; + else + return GRAY; + } + + inline uint32 GetZeroDifference(uint32 pl_level) + { + if( pl_level < 8 ) return 5; + if( pl_level < 10 ) return 6; + if( pl_level < 12 ) return 7; + if( pl_level < 16 ) return 8; + if( pl_level < 20 ) return 9; + if( pl_level < 30 ) return 11; + if( pl_level < 40 ) return 12; + if( pl_level < 45 ) return 13; + if( pl_level < 50 ) return 14; + if( pl_level < 55 ) return 15; + if( pl_level < 60 ) return 16; + return 17; + } + + inline uint32 BaseGain(uint32 pl_level, uint32 mob_level, ContentLevels content) + { + const uint32 nBaseExp = content == CONTENT_1_60 ? 45 : 235; + if( mob_level >= pl_level ) + { + uint32 nLevelDiff = mob_level - pl_level; + if (nLevelDiff > 4) + nLevelDiff = 4; + return ((pl_level*5 + nBaseExp) * (20 + nLevelDiff)/10 + 1)/2; + } + else + { + uint32 gray_level = GetGrayLevel(pl_level); + if( mob_level > gray_level ) + { + uint32 ZD = GetZeroDifference(pl_level); + return (pl_level*5 + nBaseExp) * (ZD + mob_level - pl_level)/ZD; + } + return 0; + } + } + + inline uint32 Gain(Player *pl, Unit *u) + { + if(u->GetTypeId()==TYPEID_UNIT && ( + ((Creature*)u)->isTotem() || ((Creature*)u)->isPet() || + (((Creature*)u)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_NO_XP_AT_KILL) )) + return 0; + + uint32 xp_gain= BaseGain(pl->getLevel(), u->getLevel(), GetContentLevelsForMapAndZone(pl->GetMapId(),pl->GetZoneId())); + if( xp_gain == 0 ) + return 0; + + if(u->GetTypeId()==TYPEID_UNIT && ((Creature*)u)->isElite()) + xp_gain *= 2; + + return (uint32)(xp_gain*sWorld.getRate(RATE_XP_KILL)); + } + + inline uint32 xp_Diff(uint32 lvl) + { + if( lvl < 29 ) + return 0; + if( lvl == 29 ) + return 1; + if( lvl == 30 ) + return 3; + if( lvl == 31 ) + return 6; + else + return (5*(lvl-30)); + } + + inline uint32 mxp(uint32 lvl) + { + if (lvl < 60) + { + return (45 + (5*lvl)); + } + else + { + return (235 + (5*lvl)); + } + } + + inline uint32 xp_to_level(uint32 lvl) + { + uint32 xp = 0; + if (lvl < 60) + { + xp = (8*lvl + xp_Diff(lvl)) * mxp(lvl); + } + else if (lvl == 60) + { + xp = (155 + mxp(lvl) * (1344 - 70 - ((69 - lvl) * (7 + (69 - lvl) * 8 - 1)/2))); + } + else if (lvl < 70) + { + xp = (155 + mxp(lvl) * (1344 - ((69-lvl) * (7 + (69 - lvl) * 8 - 1)/2))); + }else + { + // level higher than 70 is not supported + xp = (uint32)(779700 * (pow(sWorld.getRate(RATE_XP_PAST_70), (int32)lvl - 69))); + return ((xp < 0x7fffffff) ? xp : 0x7fffffff); + } + + // The XP to Level is always rounded to the nearest 100 points (50 rounded to high). + xp = ((xp + 50) / 100) * 100; // use additional () for prevent free association operations in C++ + + if ((lvl > 10) && (lvl < 60)) // compute discount added in 2.3.x + { + uint32 discount = (lvl < 28) ? (lvl - 10) : 18; + xp = (xp * (100 - discount)) / 100; // apply discount + xp = (xp / 100) * 100; // floor to hundreds + } + + return xp; + } + + inline float xp_in_group_rate(uint32 count, bool isRaid) + { + if(isRaid) + { + // FIX ME: must apply decrease modifiers dependent from raid size + return 1.0f; + } + else + { + switch(count) + { + case 0: + case 1: + case 2: + return 1.0f; + case 3: + return 1.166f; + case 4: + return 1.3f; + case 5: + default: + return 1.4f; + } + } + } + } +} +#endif diff --git a/src/game/GameEvent.cpp b/src/game/GameEvent.cpp new file mode 100644 index 00000000000..e36cb6caae8 --- /dev/null +++ b/src/game/GameEvent.cpp @@ -0,0 +1,659 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "GameEvent.h" +#include "World.h" +#include "ObjectMgr.h" +#include "ProgressBar.h" +#include "Language.h" +#include "Log.h" +#include "MapManager.h" +#include "Policies/SingletonImp.h" + +INSTANTIATE_SINGLETON_1(GameEvent); + +bool GameEvent::CheckOneGameEvent(uint16 entry) const +{ + // Get the event information + time_t currenttime = time(NULL); + if( mGameEvent[entry].start < currenttime && currenttime < mGameEvent[entry].end && + ((currenttime - mGameEvent[entry].start) % (mGameEvent[entry].occurence * MINUTE)) < (mGameEvent[entry].length * MINUTE) ) + return true; + else + return false; +} + +uint32 GameEvent::NextCheck(uint16 entry) const +{ + time_t currenttime = time(NULL); + + // outdated event: we return max + if (currenttime > mGameEvent[entry].end) + return max_ge_check_delay; + + // never started event, we return delay before start + if (mGameEvent[entry].start > currenttime) + return (mGameEvent[entry].start - currenttime); + + uint32 delay; + // in event, we return the end of it + if ((((currenttime - mGameEvent[entry].start) % (mGameEvent[entry].occurence * 60)) < (mGameEvent[entry].length * 60))) + // we return the delay before it ends + delay = (mGameEvent[entry].length * MINUTE) - ((currenttime - mGameEvent[entry].start) % (mGameEvent[entry].occurence * MINUTE)); + else // not in window, we return the delay before next start + delay = (mGameEvent[entry].occurence * MINUTE) - ((currenttime - mGameEvent[entry].start) % (mGameEvent[entry].occurence * MINUTE)); + // In case the end is before next check + if (mGameEvent[entry].end < time_t(currenttime + delay)) + return (mGameEvent[entry].end - currenttime); + else + return delay; +} + +void GameEvent::StartEvent( uint16 event_id, bool overwrite ) +{ + AddActiveEvent(event_id); + ApplyNewEvent(event_id); + if(overwrite) + { + mGameEvent[event_id].start = time(NULL); + if(mGameEvent[event_id].end <= mGameEvent[event_id].start) + mGameEvent[event_id].end = mGameEvent[event_id].start+mGameEvent[event_id].length; + } +} + +void GameEvent::StopEvent( uint16 event_id, bool overwrite ) +{ + RemoveActiveEvent(event_id); + UnApplyEvent(event_id); + if(overwrite) + { + mGameEvent[event_id].start = time(NULL) - mGameEvent[event_id].length * MINUTE; + if(mGameEvent[event_id].end <= mGameEvent[event_id].start) + mGameEvent[event_id].end = mGameEvent[event_id].start+mGameEvent[event_id].length; + } +} + +void GameEvent::LoadFromDB() +{ + { + QueryResult *result = WorldDatabase.Query("SELECT MAX(entry) FROM game_event"); + if( !result ) + { + sLog.outString(">> Table game_event is empty."); + sLog.outString(); + return; + } + + Field *fields = result->Fetch(); + + uint32 max_event_id = fields[0].GetUInt16(); + delete result; + + mGameEvent.resize(max_event_id+1); + } + + QueryResult *result = WorldDatabase.Query("SELECT entry,UNIX_TIMESTAMP(start_time),UNIX_TIMESTAMP(end_time),occurence,length,description FROM game_event"); + if( !result ) + { + mGameEvent.clear(); + sLog.outString(">> Table game_event is empty:"); + sLog.outString(); + return; + } + + uint32 count = 0; + + barGoLink bar( result->GetRowCount() ); + do + { + ++count; + Field *fields = result->Fetch(); + + bar.step(); + + uint16 event_id = fields[0].GetUInt16(); + if(event_id==0) + { + sLog.outErrorDb("`game_event` game event id (%i) is reserved and can't be used.",event_id); + continue; + } + + GameEventData& pGameEvent = mGameEvent[event_id]; + uint64 starttime = fields[1].GetUInt64(); + pGameEvent.start = time_t(starttime); + uint64 endtime = fields[2].GetUInt64(); + pGameEvent.end = time_t(endtime); + pGameEvent.occurence = fields[3].GetUInt32(); + pGameEvent.length = fields[4].GetUInt32(); + + if(pGameEvent.length==0) // length>0 is validity check + { + sLog.outErrorDb("`game_event` game event id (%i) have length 0 and can't be used.",event_id); + continue; + } + + pGameEvent.description = fields[5].GetCppString(); + + } while( result->NextRow() ); + + sLog.outString(); + sLog.outString( ">> Loaded %u game events", count ); + delete result; + + mGameEventCreatureGuids.resize(mGameEvent.size()*2-1); + // 1 2 + result = WorldDatabase.Query("SELECT creature.guid, game_event_creature.event " + "FROM creature JOIN game_event_creature ON creature.guid = game_event_creature.guid"); + + count = 0; + if( !result ) + { + barGoLink bar2(1); + bar2.step(); + + sLog.outString(); + sLog.outString(">> Loaded %u creatures in game events", count ); + } + else + { + + barGoLink bar2( result->GetRowCount() ); + do + { + Field *fields = result->Fetch(); + + bar2.step(); + + uint32 guid = fields[0].GetUInt32(); + int16 event_id = fields[1].GetInt16(); + + int32 internal_event_id = mGameEvent.size() + event_id - 1; + + if(internal_event_id < 0 || internal_event_id >= mGameEventCreatureGuids.size()) + { + sLog.outErrorDb("`game_event_creature` game event id (%i) is out of range compared to max event id in `game_event`",event_id); + continue; + } + + ++count; + GuidList& crelist = mGameEventCreatureGuids[internal_event_id]; + crelist.push_back(guid); + + } while( result->NextRow() ); + sLog.outString(); + sLog.outString( ">> Loaded %u creatures in game events", count ); + delete result; + } + + mGameEventGameobjectGuids.resize(mGameEvent.size()*2-1); + // 1 2 + result = WorldDatabase.Query("SELECT gameobject.guid, game_event_gameobject.event " + "FROM gameobject JOIN game_event_gameobject ON gameobject.guid=game_event_gameobject.guid"); + + count = 0; + if( !result ) + { + barGoLink bar3(1); + bar3.step(); + + sLog.outString(); + sLog.outString(">> Loaded %u gameobjects in game events", count ); + } + else + { + + barGoLink bar3( result->GetRowCount() ); + do + { + Field *fields = result->Fetch(); + + bar3.step(); + + uint32 guid = fields[0].GetUInt32(); + int16 event_id = fields[1].GetInt16(); + + int32 internal_event_id = mGameEvent.size() + event_id - 1; + + if(internal_event_id < 0 || internal_event_id >= mGameEventGameobjectGuids.size()) + { + sLog.outErrorDb("`game_event_gameobject` game event id (%i) is out of range compared to max event id in `game_event`",event_id); + continue; + } + + ++count; + GuidList& golist = mGameEventGameobjectGuids[internal_event_id]; + golist.push_back(guid); + + } while( result->NextRow() ); + sLog.outString(); + sLog.outString( ">> Loaded %u gameobjects in game events", count ); + + delete result; + } + + mGameEventModelEquip.resize(mGameEvent.size()); + // 0 1 2 + result = WorldDatabase.Query("SELECT creature.guid, game_event_model_equip.event, game_event_model_equip.modelid," + // 3 + "game_event_model_equip.equipment_id " + "FROM creature JOIN game_event_model_equip ON creature.guid=game_event_model_equip.guid"); + + count = 0; + if( !result ) + { + barGoLink bar3(1); + bar3.step(); + + sLog.outString(); + sLog.outString(">> Loaded %u model/equipment changes in game events", count ); + } + else + { + + barGoLink bar3( result->GetRowCount() ); + do + { + Field *fields = result->Fetch(); + + bar3.step(); + uint32 guid = fields[0].GetUInt32(); + uint16 event_id = fields[1].GetUInt16(); + + if(event_id >= mGameEventModelEquip.size()) + { + sLog.outErrorDb("`game_event_model_equip` game event id (%u) is out of range compared to max event id in `game_event`",event_id); + continue; + } + + ++count; + ModelEquipList& equiplist = mGameEventModelEquip[event_id]; + ModelEquip newModelEquipSet; + newModelEquipSet.modelid = fields[2].GetUInt32(); + newModelEquipSet.equipment_id = fields[3].GetUInt32(); + newModelEquipSet.equipement_id_prev = 0; + newModelEquipSet.modelid_prev = 0; + + if(newModelEquipSet.equipment_id > 0) + { + if(!objmgr.GetEquipmentInfo(newModelEquipSet.equipment_id)) + { + sLog.outErrorDb("Table `game_event_model_equip` have creature (Guid: %u) with equipment_id %u not found in table `creature_equip_template`, set to no equipment.", guid, newModelEquipSet.equipment_id); + continue; + } + } + + equiplist.push_back(std::pair(guid, newModelEquipSet)); + + } while( result->NextRow() ); + sLog.outString(); + sLog.outString( ">> Loaded %u model/equipment changes in game events", count ); + + delete result; + } + + mGameEventQuests.resize(mGameEvent.size()); + // 0 1 2 + result = WorldDatabase.Query("SELECT id, quest, event FROM game_event_creature_quest"); + + count = 0; + if( !result ) + { + barGoLink bar3(1); + bar3.step(); + + sLog.outString(); + sLog.outString(">> Loaded %u quests additions in game events", count ); + } + else + { + + barGoLink bar3( result->GetRowCount() ); + do + { + Field *fields = result->Fetch(); + + bar3.step(); + uint32 id = fields[0].GetUInt32(); + uint32 quest = fields[1].GetUInt32(); + uint16 event_id = fields[2].GetUInt16(); + + if(event_id >= mGameEventQuests.size()) + { + sLog.outErrorDb("`game_event_creature_quest` game event id (%u) is out of range compared to max event id in `game_event`",event_id); + continue; + } + + ++count; + QuestRelList& questlist = mGameEventQuests[event_id]; + questlist.push_back(QuestRelation(id, quest)); + + } while( result->NextRow() ); + sLog.outString(); + sLog.outString( ">> Loaded %u quests additions in game events", count ); + + delete result; + } +} + +uint32 GameEvent::Initialize() // return the next event delay in ms +{ + m_ActiveEvents.clear(); + uint32 delay = Update(); + sLog.outBasic("Game Event system initialized." ); + isSystemInit = true; + return delay; +} + +uint32 GameEvent::Update() // return the next event delay in ms +{ + uint32 nextEventDelay = max_ge_check_delay; // 1 day + uint32 calcDelay; + for (uint16 itr = 1; itr < mGameEvent.size(); itr++) + { + //sLog.outErrorDb("Checking event %u",itr); + if (CheckOneGameEvent(itr)) + { + //sLog.outDebug("GameEvent %u is active",itr->first); + if (!IsActiveEvent(itr)) + StartEvent(itr); + } + else + { + //sLog.outDebug("GameEvent %u is not active",itr->first); + if (IsActiveEvent(itr)) + StopEvent(itr); + else + { + if (!isSystemInit) + { + int16 event_nid = (-1) * (itr); + // spawn all negative ones for this event + GameEventSpawn(event_nid); + } + } + } + calcDelay = NextCheck(itr); + if (calcDelay < nextEventDelay) + nextEventDelay = calcDelay; + } + sLog.outBasic("Next game event check in %u seconds.", nextEventDelay + 1); + return (nextEventDelay + 1) * 1000; // Add 1 second to be sure event has started/stopped at next call +} + +void GameEvent::UnApplyEvent(uint16 event_id) +{ + sLog.outString("GameEvent %u \"%s\" removed.", event_id, mGameEvent[event_id].description.c_str()); + // un-spawn positive event tagged objects + GameEventUnspawn(event_id); + // spawn negative event tagget objects + int16 event_nid = (-1) * event_id; + GameEventSpawn(event_nid); + // restore equipment or model + ChangeEquipOrModel(event_id, false); + // Remove quests that are events only to non event npc + UpdateEventQuests(event_id, false); +} + +void GameEvent::ApplyNewEvent(uint16 event_id) +{ + switch(sWorld.getConfig(CONFIG_EVENT_ANNOUNCE)) + { + case 0: // disable + break; + case 1: // announce events + sWorld.SendWorldText(LANG_EVENTMESSAGE, mGameEvent[event_id].description.c_str()); + break; + } + + sLog.outString("GameEvent %u \"%s\" started.", event_id, mGameEvent[event_id].description.c_str()); + // spawn positive event tagget objects + GameEventSpawn(event_id); + // un-spawn negative event tagged objects + int16 event_nid = (-1) * event_id; + GameEventUnspawn(event_nid); + // Change equipement or model + ChangeEquipOrModel(event_id, true); + // Add quests that are events only to non event npc + UpdateEventQuests(event_id, true); +} + +void GameEvent::GameEventSpawn(int16 event_id) +{ + int32 internal_event_id = mGameEvent.size() + event_id - 1; + + if(internal_event_id < 0 || internal_event_id >= mGameEventCreatureGuids.size()) + { + sLog.outError("GameEvent::GameEventSpawn attempt access to out of range mGameEventCreatureGuids element %i (size: %u)",internal_event_id,mGameEventCreatureGuids.size()); + return; + } + + for (GuidList::iterator itr = mGameEventCreatureGuids[internal_event_id].begin();itr != mGameEventCreatureGuids[internal_event_id].end();++itr) + { + // Add to correct cell + CreatureData const* data = objmgr.GetCreatureData(*itr); + if (data) + { + objmgr.AddCreatureToGrid(*itr, data); + + // Spawn if necessary (loaded grids only) + Map* map = const_cast(MapManager::Instance().GetBaseMap(data->mapid)); + // We use spawn coords to spawn + if(!map->Instanceable() && !map->IsRemovalGrid(data->posX,data->posY)) + { + Creature* pCreature = new Creature; + //sLog.outDebug("Spawning creature %u",*itr); + if (!pCreature->LoadFromDB(*itr, map)) + { + delete pCreature; + } + else + { + map->Add(pCreature); + } + } + } + } + + if(internal_event_id < 0 || internal_event_id >= mGameEventGameobjectGuids.size()) + { + sLog.outError("GameEvent::GameEventSpawn attempt access to out of range mGameEventGameobjectGuids element %i (size: %u)",internal_event_id,mGameEventGameobjectGuids.size()); + return; + } + + for (GuidList::iterator itr = mGameEventGameobjectGuids[internal_event_id].begin();itr != mGameEventGameobjectGuids[internal_event_id].end();++itr) + { + // Add to correct cell + GameObjectData const* data = objmgr.GetGOData(*itr); + if (data) + { + objmgr.AddGameobjectToGrid(*itr, data); + // Spawn if necessary (loaded grids only) + // this base map checked as non-instanced and then only existed + Map* map = const_cast(MapManager::Instance().GetBaseMap(data->mapid)); + // We use current coords to unspawn, not spawn coords since creature can have changed grid + if(!map->Instanceable() && !map->IsRemovalGrid(data->posX, data->posY)) + { + GameObject* pGameobject = new GameObject; + //sLog.outDebug("Spawning gameobject %u", *itr); + if (!pGameobject->LoadFromDB(*itr, map)) + { + delete pGameobject; + } + else + { + if(pGameobject->isSpawnedByDefault()) + map->Add(pGameobject); + } + } + } + } +} + +void GameEvent::GameEventUnspawn(int16 event_id) +{ + int32 internal_event_id = mGameEvent.size() + event_id - 1; + + if(internal_event_id < 0 || internal_event_id >= mGameEventCreatureGuids.size()) + { + sLog.outError("GameEvent::GameEventUnspawn attempt access to out of range mGameEventCreatureGuids element %i (size: %u)",internal_event_id,mGameEventCreatureGuids.size()); + return; + } + + for (GuidList::iterator itr = mGameEventCreatureGuids[internal_event_id].begin();itr != mGameEventCreatureGuids[internal_event_id].end();++itr) + { + // Remove the creature from grid + if( CreatureData const* data = objmgr.GetCreatureData(*itr) ) + { + objmgr.RemoveCreatureFromGrid(*itr, data); + + if( Creature* pCreature = ObjectAccessor::Instance().GetObjectInWorld(MAKE_NEW_GUID(*itr, data->id, HIGHGUID_UNIT), (Creature*)NULL) ) + { + pCreature->CleanupsBeforeDelete(); + pCreature->AddObjectToRemoveList(); + } + } + } + + if(internal_event_id < 0 || internal_event_id >= mGameEventGameobjectGuids.size()) + { + sLog.outError("GameEvent::GameEventUnspawn attempt access to out of range mGameEventGameobjectGuids element %i (size: %u)",internal_event_id,mGameEventGameobjectGuids.size()); + return; + } + + for (GuidList::iterator itr = mGameEventGameobjectGuids[internal_event_id].begin();itr != mGameEventGameobjectGuids[internal_event_id].end();++itr) + { + // Remove the gameobject from grid + if(GameObjectData const* data = objmgr.GetGOData(*itr)) + { + objmgr.RemoveGameobjectFromGrid(*itr, data); + + if( GameObject* pGameobject = ObjectAccessor::Instance().GetObjectInWorld(MAKE_NEW_GUID(*itr, data->id, HIGHGUID_GAMEOBJECT), (GameObject*)NULL) ) + pGameobject->AddObjectToRemoveList(); + } + } +} + +void GameEvent::ChangeEquipOrModel(int16 event_id, bool activate) +{ + for(ModelEquipList::iterator itr = mGameEventModelEquip[event_id].begin();itr != mGameEventModelEquip[event_id].end();++itr) + { + // Remove the creature from grid + CreatureData const* data = objmgr.GetCreatureData(itr->first); + if(!data) + continue; + + // Update if spawned + Creature* pCreature = ObjectAccessor::Instance().GetObjectInWorld(MAKE_NEW_GUID(itr->first, data->id,HIGHGUID_UNIT), (Creature*)NULL); + if (pCreature) + { + if (activate) + { + itr->second.equipement_id_prev = pCreature->GetCurrentEquipmentId(); + itr->second.modelid_prev = pCreature->GetDisplayId(); + pCreature->LoadEquipment(itr->second.equipment_id, true); + if (itr->second.modelid >0 && itr->second.modelid_prev != itr->second.modelid) + { + CreatureModelInfo const *minfo = objmgr.GetCreatureModelInfo(itr->second.modelid); + if (minfo) + { + pCreature->SetDisplayId(itr->second.modelid); + pCreature->SetNativeDisplayId(itr->second.modelid); + pCreature->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS,minfo->bounding_radius); + pCreature->SetFloatValue(UNIT_FIELD_COMBATREACH,minfo->combat_reach ); + } + } + } + else + { + pCreature->LoadEquipment(itr->second.equipement_id_prev, true); + if (itr->second.modelid_prev >0 && itr->second.modelid_prev != itr->second.modelid) + { + CreatureModelInfo const *minfo = objmgr.GetCreatureModelInfo(itr->second.modelid_prev); + if (minfo) + { + pCreature->SetDisplayId(itr->second.modelid_prev); + pCreature->SetNativeDisplayId(itr->second.modelid_prev); + pCreature->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS,minfo->bounding_radius); + pCreature->SetFloatValue(UNIT_FIELD_COMBATREACH,minfo->combat_reach ); + } + } + } + } + else // If not spawned + { + CreatureData const* data = objmgr.GetCreatureData(itr->first); + if (data && activate) + { + CreatureInfo const *cinfo = objmgr.GetCreatureTemplate(data->id); + uint32 display_id = objmgr.ChooseDisplayId(0,cinfo,data); + CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id); + if (minfo) + display_id = minfo->modelid; + if (data->equipmentId == 0) + itr->second.equipement_id_prev = cinfo->equipmentId; + else if (data->equipmentId != -1) + itr->second.equipement_id_prev = data->equipmentId; + itr->second.modelid_prev = display_id; + } + } + // now last step: put in data + // just to have write access to it + CreatureData& data2 = objmgr.NewOrExistCreatureData(itr->first); + if (activate) + { + data2.displayid = itr->second.modelid; + data2.equipmentId = itr->second.equipment_id; + } + else + { + data2.displayid = itr->second.modelid_prev; + data2.equipmentId = itr->second.equipement_id_prev; + } + } +} + +void GameEvent::UpdateEventQuests(uint16 event_id, bool Activate) +{ + QuestRelList::iterator itr; + for (itr = mGameEventQuests[event_id].begin();itr != mGameEventQuests[event_id].end();++itr) + { + QuestRelations &CreatureQuestMap = objmgr.mCreatureQuestRelations; + if (Activate) // Add the pair(id,quest) to the multimap + CreatureQuestMap.insert(QuestRelations::value_type(itr->first, itr->second)); + else + { // Remove the pair(id,quest) from the multimap + QuestRelations::iterator qitr = CreatureQuestMap.find(itr->first); + if (qitr == CreatureQuestMap.end()) + continue; + QuestRelations::iterator lastElement = CreatureQuestMap.upper_bound(itr->first); + for ( ;qitr != lastElement;++qitr) + { + if (qitr->second == itr->second) + { + CreatureQuestMap.erase(qitr); // iterator is now no more valid + break; // but we can exit loop since the element is found + } + } + } + } +} + +GameEvent::GameEvent() +{ + isSystemInit = false; +} diff --git a/src/game/GameEvent.h b/src/game/GameEvent.h new file mode 100644 index 00000000000..535422eb407 --- /dev/null +++ b/src/game/GameEvent.h @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_GAMEEVENT_H +#define MANGOS_GAMEEVENT_H + +#include "Platform/Define.h" +#include "Creature.h" +#include "GameObject.h" + +#define max_ge_check_delay 86400 // 1 day in seconds + +struct GameEventData +{ + GameEventData() : start(1),end(0),occurence(0),length(0) {} + time_t start; + time_t end; + uint32 occurence; + uint32 length; + std::string description; + + bool isValid() const { return length > 0; } +}; + +struct ModelEquip +{ + uint32 modelid; + uint32 equipment_id; + uint32 modelid_prev; + uint32 equipement_id_prev; +}; + +class GameEvent +{ + public: + GameEvent(); + ~GameEvent() {}; + typedef std::set ActiveEvents; + typedef std::vector GameEventDataMap; + ActiveEvents const& GetActiveEventList() const { return m_ActiveEvents; } + GameEventDataMap const& GetEventMap() const { return mGameEvent; } + bool CheckOneGameEvent(uint16 entry) const; + uint32 NextCheck(uint16 entry) const; + void LoadFromDB(); + uint32 Update(); + bool IsActiveEvent(uint16 event_id) { return ( m_ActiveEvents.find(event_id)!=m_ActiveEvents.end()); } + uint32 Initialize(); + void StartEvent(uint16 event_id, bool overwrite = false); + void StopEvent(uint16 event_id, bool overwrite = false); + private: + void AddActiveEvent(uint16 event_id) { m_ActiveEvents.insert(event_id); } + void RemoveActiveEvent(uint16 event_id) { m_ActiveEvents.erase(event_id); } + void ApplyNewEvent(uint16 event_id); + void UnApplyEvent(uint16 event_id); + void GameEventSpawn(int16 event_id); + void GameEventUnspawn(int16 event_id); + void ChangeEquipOrModel(int16 event_id, bool activate); + void UpdateEventQuests(uint16 event_id, bool Activate); + protected: + typedef std::list GuidList; + typedef std::vector GameEventGuidMap; + typedef std::pair ModelEquipPair; + typedef std::list ModelEquipList; + typedef std::vector GameEventModelEquipMap; + typedef std::pair QuestRelation; + typedef std::list QuestRelList; + typedef std::vector GameEventQuestMap; + GameEventQuestMap mGameEventQuests; + GameEventModelEquipMap mGameEventModelEquip; + GameEventGuidMap mGameEventCreatureGuids; + GameEventGuidMap mGameEventGameobjectGuids; + GameEventDataMap mGameEvent; + ActiveEvents m_ActiveEvents; + bool isSystemInit; +}; + +#define gameeventmgr MaNGOS::Singleton::Instance() +#endif diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp new file mode 100644 index 00000000000..c3b8cf3d6e4 --- /dev/null +++ b/src/game/GameObject.cpp @@ -0,0 +1,1253 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "QuestDef.h" +#include "GameObject.h" +#include "ObjectMgr.h" +#include "SpellMgr.h" +#include "Spell.h" +#include "UpdateMask.h" +#include "Opcodes.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "World.h" +#include "Database/DatabaseEnv.h" +#include "MapManager.h" +#include "LootMgr.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" +#include "CellImpl.h" +#include "InstanceData.h" +#include "BattleGround.h" +#include "Util.h" + +GameObject::GameObject() : WorldObject() +{ + m_objectType |= TYPEMASK_GAMEOBJECT; + m_objectTypeId = TYPEID_GAMEOBJECT; + // 2.3.2 - 0x58 + m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HASPOSITION); + + m_valuesCount = GAMEOBJECT_END; + m_respawnTime = 0; + m_respawnDelayTime = 25; + m_lootState = GO_NOT_READY; + m_spawnedByDefault = true; + m_usetimes = 0; + m_spellId = 0; + m_charges = 5; + m_cooldownTime = 0; + m_goInfo = NULL; +} + +GameObject::~GameObject() +{ + if(m_uint32Values) // field array can be not exist if GameOBject not loaded + { + // crash possable at access to deleted GO in Unit::m_gameobj + uint64 owner_guid = GetOwnerGUID(); + if(owner_guid) + { + Unit* owner = ObjectAccessor::GetUnit(*this,owner_guid); + if(owner) + owner->RemoveGameObject(this,false); + else if(!IS_PLAYER_GUID(owner_guid)) + sLog.outError("Delete GameObject (GUID: %u Entry: %u ) that have references in not found creature %u GO list. Crash possable later.",GetGUIDLow(),GetGOInfo()->id,GUID_LOPART(owner_guid)); + } + } +} + +void GameObject::AddToWorld() +{ + ///- Register the gameobject for guid lookup + if(!IsInWorld()) ObjectAccessor::Instance().AddObject(this); + Object::AddToWorld(); +} + +void GameObject::RemoveFromWorld() +{ + ///- Remove the gameobject from the accessor + if(IsInWorld()) ObjectAccessor::Instance().RemoveObject(this); + Object::RemoveFromWorld(); +} + +bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, uint32 go_state) +{ + Relocate(x,y,z,ang); + SetMapId(map->GetId()); + SetInstanceId(map->GetInstanceId()); + + if(!IsPositionValid()) + { + sLog.outError("ERROR: Gameobject (GUID: %u Entry: %u ) not created. Suggested coordinates isn't valid (X: %f Y: %f)",guidlow,name_id,x,y); + return false; + } + + GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(name_id); + if (!goinfo) + { + sLog.outErrorDb("Gameobject (GUID: %u Entry: %u) not created: it have not exist entry in `gameobject_template`. Map: %u (X: %f Y: %f Z: %f) ang: %f rotation0: %f rotation1: %f rotation2: %f rotation3: %f",guidlow, name_id, map->GetId(), x, y, z, ang, rotation0, rotation1, rotation2, rotation3); + return false; + } + + Object::_Create(guidlow, goinfo->id, HIGHGUID_GAMEOBJECT); + + m_DBTableGuid = guidlow; + m_goInfo = goinfo; + + if (goinfo->type >= MAX_GAMEOBJECT_TYPE) + { + sLog.outErrorDb("Gameobject (GUID: %u Entry: %u) not created: it have not exist GO type '%u' in `gameobject_template`. It's will crash client if created.",guidlow,name_id,goinfo->type); + return false; + } + + SetFloatValue(GAMEOBJECT_POS_X, x); + SetFloatValue(GAMEOBJECT_POS_Y, y); + SetFloatValue(GAMEOBJECT_POS_Z, z); + SetFloatValue(GAMEOBJECT_FACING, ang); //this is not facing angle + + SetFloatValue (GAMEOBJECT_ROTATION, rotation0); + SetFloatValue (GAMEOBJECT_ROTATION+1, rotation1); + SetFloatValue (GAMEOBJECT_ROTATION+2, rotation2); + SetFloatValue (GAMEOBJECT_ROTATION+3, rotation3); + + SetFloatValue(OBJECT_FIELD_SCALE_X, goinfo->size); + + SetUInt32Value(GAMEOBJECT_FACTION, goinfo->faction); + SetUInt32Value(GAMEOBJECT_FLAGS, goinfo->flags); + + SetUInt32Value(OBJECT_FIELD_ENTRY, goinfo->id); + + SetUInt32Value(GAMEOBJECT_DISPLAYID, goinfo->displayId); + + SetGoState(go_state); + SetGoType(GameobjectTypes(goinfo->type)); + + SetGoAnimProgress(animprogress); + + // Spell charges for GAMEOBJECT_TYPE_SPELLCASTER (22) + if (goinfo->type == GAMEOBJECT_TYPE_SPELLCASTER) + m_charges = goinfo->spellcaster.charges; + + //Notify the map's instance data. + //Only works if you create the object in it, not if it is moves to that map. + //Normally non-players do not teleport to other maps. + if(map->IsDungeon() && ((InstanceMap*)map)->GetInstanceData()) + { + ((InstanceMap*)map)->GetInstanceData()->OnObjectCreate(this); + } + + return true; +} + +void GameObject::Update(uint32 /*p_time*/) +{ + if (IS_MO_TRANSPORT(GetGUID())) + { + //((Transport*)this)->Update(p_time); + return; + } + + switch (m_lootState) + { + case GO_NOT_READY: + { + switch(GetGoType()) + { + case GAMEOBJECT_TYPE_TRAP: + { + // Arming Time for GAMEOBJECT_TYPE_TRAP (6) + Unit* owner = GetOwner(); + if (owner && ((Player*)owner)->isInCombat()) + m_cooldownTime = time(NULL) + GetGOInfo()->trap.startDelay; + m_lootState = GO_READY; + break; + } + case GAMEOBJECT_TYPE_FISHINGNODE: + { + // fishing code (bobber ready) + if( time(NULL) > m_respawnTime - FISHING_BOBBER_READY_TIME ) + { + // splash bobber (bobber ready now) + Unit* caster = GetOwner(); + if(caster && caster->GetTypeId()==TYPEID_PLAYER) + { + SetGoState(0); + SetUInt32Value(GAMEOBJECT_FLAGS, 32); + + UpdateData udata; + WorldPacket packet; + BuildValuesUpdateBlockForPlayer(&udata,((Player*)caster)); + udata.BuildPacket(&packet); + ((Player*)caster)->GetSession()->SendPacket(&packet); + + WorldPacket data(SMSG_GAMEOBJECT_CUSTOM_ANIM,8+4); + data << GetGUID(); + data << (uint32)(0); + ((Player*)caster)->SendMessageToSet(&data,true); + } + + m_lootState = GO_READY; // can be succesfully open with some chance + } + return; + } + default: + m_lootState = GO_READY; // for other GOis same switched without delay to GO_READY + break; + } + // NO BREAK for switch (m_lootState) + } + case GO_READY: + { + if (m_respawnTime > 0) // timer on + { + if (m_respawnTime <= time(NULL)) // timer expired + { + m_respawnTime = 0; + m_SkillupList.clear(); + m_usetimes = 0; + + switch (GetGoType()) + { + case GAMEOBJECT_TYPE_FISHINGNODE: // can't fish now + { + Unit* caster = GetOwner(); + if(caster && caster->GetTypeId()==TYPEID_PLAYER) + { + if(caster->m_currentSpells[CURRENT_CHANNELED_SPELL]) + { + caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->SendChannelUpdate(0); + caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->finish(false); + } + + WorldPacket data(SMSG_FISH_NOT_HOOKED,0); + ((Player*)caster)->GetSession()->SendPacket(&data); + } + // can be delete + m_lootState = GO_JUST_DEACTIVATED; + return; + } + case GAMEOBJECT_TYPE_DOOR: + case GAMEOBJECT_TYPE_BUTTON: + //we need to open doors if they are closed (add there another condition if this code breaks some usage, but it need to be here for battlegrounds) + if( !GetGoState() ) + SwitchDoorOrButton(false); + //flags in AB are type_button and we need to add them here so no break! + default: + if(!m_spawnedByDefault) // despawn timer + { + // can be despawned or destroyed + SetLootState(GO_JUST_DEACTIVATED); + return; + } + // respawn timer + MapManager::Instance().GetMap(GetMapId(), this)->Add(this); + break; + } + } + } + + // traps can have time and can not have + GameObjectInfo const* goInfo = GetGOInfo(); + if(goInfo->type == GAMEOBJECT_TYPE_TRAP) + { + // traps + Unit* owner = GetOwner(); + Unit* ok = NULL; // pointer to appropriate target if found any + + if(m_cooldownTime >= time(NULL)) + return; + + bool IsBattleGroundTrap = false; + //FIXME: this is activation radius (in different casting radius that must be selected from spell data) + //TODO: move activated state code (cast itself) to GO_ACTIVATED, in this place only check activating and set state + float radius = goInfo->trap.radius; + if(!radius) + { + if(goInfo->trap.cooldown != 3) // cast in other case (at some triggring/linked go/etc explicit call) + return; + else + { + if(m_respawnTime > 0) + break; + + radius = goInfo->trap.cooldown; // battlegrounds gameobjects has data2 == 0 && data5 == 3 + IsBattleGroundTrap = true; + } + } + + bool NeedDespawn = (goInfo->trap.charges != 0); + + CellPair p(MaNGOS::ComputeCellPair(GetPositionX(),GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + + // Note: this hack with search required until GO casting not implemented + // search unfriendly creature + if(owner && NeedDespawn) // hunter trap + { + MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck u_check(this, owner, radius); + MaNGOS::UnitSearcher checker(ok, u_check); + + CellLock cell_lock(cell, p); + + TypeContainerVisitor, GridTypeMapContainer > grid_object_checker(checker); + cell_lock->Visit(cell_lock, grid_object_checker, *MapManager::Instance().GetMap(GetMapId(), this)); + + // or unfriendly player/pet + if(!ok) + { + TypeContainerVisitor, WorldTypeMapContainer > world_object_checker(checker); + cell_lock->Visit(cell_lock, world_object_checker, *MapManager::Instance().GetMap(GetMapId(), this)); + } + } + else // environmental trap + { + // environmental damage spells already have around enemies targeting but this not help in case not existed GO casting support + + // affect only players + Player* p_ok = NULL; + MaNGOS::AnyPlayerInObjectRangeCheck p_check(this, radius); + MaNGOS::PlayerSearcher checker(p_ok, p_check); + + CellLock cell_lock(cell, p); + + TypeContainerVisitor, WorldTypeMapContainer > world_object_checker(checker); + cell_lock->Visit(cell_lock, world_object_checker, *MapManager::Instance().GetMap(GetMapId(), this)); + ok = p_ok; + } + + if (ok) + { + Unit *caster = owner ? owner : ok; + + caster->CastSpell(ok, goInfo->trap.spellId, true); + m_cooldownTime = time(NULL) + 4; // 4 seconds + + if(NeedDespawn) + SetLootState(GO_JUST_DEACTIVATED); // can be despawned or destroyed + + if(IsBattleGroundTrap && ok->GetTypeId() == TYPEID_PLAYER) + { + //BattleGround gameobjects case + if(((Player*)ok)->InBattleGround()) + if(BattleGround *bg = ((Player*)ok)->GetBattleGround()) + bg->HandleTriggerBuff(GetGUID()); + } + } + } + + if (m_charges && m_usetimes >= m_charges) + SetLootState(GO_JUST_DEACTIVATED); // can be despawned or destroyed + + break; + } + case GO_ACTIVATED: + { + switch(GetGoType()) + { + case GAMEOBJECT_TYPE_DOOR: + case GAMEOBJECT_TYPE_BUTTON: + if(GetAutoCloseTime() && (m_cooldownTime < time(NULL))) + { + SwitchDoorOrButton(false); + SetLootState(GO_JUST_DEACTIVATED); + } + break; + } + break; + } + case GO_JUST_DEACTIVATED: + { + //if Gameobject should cast spell, then this, but some GOs (type = 10) should be destroyed + if (GetGoType() == GAMEOBJECT_TYPE_GOOBER) + { + uint32 spellId = GetGOInfo()->goober.spellId; + + if(spellId) + { + std::set::iterator it = m_unique_users.begin(); + std::set::iterator end = m_unique_users.end(); + for (; it != end; it++) + { + Unit* owner = Unit::GetUnit(*this, uint64(*it)); + if (owner) owner->CastSpell(owner, spellId, false); + } + + m_unique_users.clear(); + m_usetimes = 0; + } + //any return here in case battleground traps + } + + if(GetOwnerGUID()) + { + m_respawnTime = 0; + Delete(); + return; + } + + //burning flags in some battlegrounds, if you find better condition, just add it + if (GetGoAnimProgress() > 0) + { + SendObjectDeSpawnAnim(this->GetGUID()); + //reset flags + SetUInt32Value(GAMEOBJECT_FLAGS, GetGOInfo()->flags); + } + + loot.clear(); + SetLootState(GO_READY); + + if(!m_respawnDelayTime) + return; + + if(!m_spawnedByDefault) + { + m_respawnTime = 0; + return; + } + + m_respawnTime = time(NULL) + m_respawnDelayTime; + + // if option not set then object will be saved at grid unload + if(sWorld.getConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATLY)) + SaveRespawnTime(); + + ObjectAccessor::UpdateObjectVisibility(this); + + break; + } + } +} + +void GameObject::Refresh() +{ + // not refresh despawned not casted GO (despawned casted GO destroyed in all cases anyway) + if(m_respawnTime > 0 && m_spawnedByDefault) + return; + + if(isSpawned()) + MapManager::Instance().GetMap(GetMapId(), this)->Add(this); +} + +void GameObject::AddUniqueUse(Player* player) +{ + AddUse(); + m_unique_users.insert(player->GetGUIDLow()); +} + +void GameObject::Delete() +{ + SendObjectDeSpawnAnim(GetGUID()); + + SetGoState(1); + SetUInt32Value(GAMEOBJECT_FLAGS, GetGOInfo()->flags); + + AddObjectToRemoveList(); +} + +void GameObject::getFishLoot(Loot *fishloot) +{ + fishloot->clear(); + + uint32 subzone = GetAreaId(); + + // if subzone loot exist use it + if(LootTemplates_Fishing.HaveLootFor(subzone)) + fishloot->FillLoot(subzone, LootTemplates_Fishing, NULL); + // else use zone loot + else + fishloot->FillLoot(GetZoneId(), LootTemplates_Fishing, NULL); +} + +void GameObject::SaveToDB() +{ + // this should only be used when the creature has already been loaded + // perferably after adding to map, because mapid may not be valid otherwise + GameObjectData const *data = objmgr.GetGOData(m_DBTableGuid); + if(!data) + { + sLog.outError("GameObject::SaveToDB failed, cannot get gameobject data!"); + return; + } + + SaveToDB(GetMapId(), data->spawnMask); +} + +void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask) +{ + const GameObjectInfo *goI = GetGOInfo(); + + if (!goI) + return; + + // update in loaded data (changing data only in this place) + GameObjectData& data = objmgr.NewGOData(m_DBTableGuid); + + // data->guid = guid don't must be update at save + data.id = GetEntry(); + data.mapid = mapid; + data.posX = GetFloatValue(GAMEOBJECT_POS_X); + data.posY = GetFloatValue(GAMEOBJECT_POS_Y); + data.posZ = GetFloatValue(GAMEOBJECT_POS_Z); + data.orientation = GetFloatValue(GAMEOBJECT_FACING); + data.rotation0 = GetFloatValue(GAMEOBJECT_ROTATION+0); + data.rotation1 = GetFloatValue(GAMEOBJECT_ROTATION+1); + data.rotation2 = GetFloatValue(GAMEOBJECT_ROTATION+2); + data.rotation3 = GetFloatValue(GAMEOBJECT_ROTATION+3); + data.spawntimesecs = m_spawnedByDefault ? m_respawnDelayTime : -(int32)m_respawnDelayTime; + data.animprogress = GetGoAnimProgress(); + data.go_state = GetGoState(); + data.spawnMask = spawnMask; + + // updated in DB + std::ostringstream ss; + ss << "INSERT INTO gameobject VALUES ( " + << m_DBTableGuid << ", " + << GetUInt32Value (OBJECT_FIELD_ENTRY) << ", " + << mapid << ", " + << (uint32)spawnMask << ", " + << GetFloatValue(GAMEOBJECT_POS_X) << ", " + << GetFloatValue(GAMEOBJECT_POS_Y) << ", " + << GetFloatValue(GAMEOBJECT_POS_Z) << ", " + << GetFloatValue(GAMEOBJECT_FACING) << ", " + << GetFloatValue(GAMEOBJECT_ROTATION) << ", " + << GetFloatValue(GAMEOBJECT_ROTATION+1) << ", " + << GetFloatValue(GAMEOBJECT_ROTATION+2) << ", " + << GetFloatValue(GAMEOBJECT_ROTATION+3) << ", " + << m_respawnDelayTime << ", " + << GetGoAnimProgress() << ", " + << GetGoState() << ")"; + + WorldDatabase.BeginTransaction(); + WorldDatabase.PExecuteLog("DELETE FROM gameobject WHERE guid = '%u'", m_DBTableGuid); + WorldDatabase.PExecuteLog( ss.str( ).c_str( ) ); + WorldDatabase.CommitTransaction(); +} + +bool GameObject::LoadFromDB(uint32 guid, Map *map) +{ + GameObjectData const* data = objmgr.GetGOData(guid); + + if( !data ) + { + sLog.outErrorDb("ERROR: Gameobject (GUID: %u) not found in table `gameobject`, can't load. ",guid); + return false; + } + + uint32 entry = data->id; + uint32 map_id = data->mapid; + float x = data->posX; + float y = data->posY; + float z = data->posZ; + float ang = data->orientation; + + float rotation0 = data->rotation0; + float rotation1 = data->rotation1; + float rotation2 = data->rotation2; + float rotation3 = data->rotation3; + + uint32 animprogress = data->animprogress; + uint32 go_state = data->go_state; + + uint32 stored_guid = guid; + if (map->GetInstanceId() != 0) guid = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT); + + if (!Create(guid,entry, map, x, y, z, ang, rotation0, rotation1, rotation2, rotation3, animprogress, go_state) ) + return false; + + m_DBTableGuid = stored_guid; + + switch(GetGOInfo()->type) + { + case GAMEOBJECT_TYPE_DOOR: + case GAMEOBJECT_TYPE_BUTTON: + /* this code (in comment) isn't correct because in battlegrounds we need despawnable doors and buttons, pls remove + SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NODESPAWN); + m_spawnedByDefault = true; + m_respawnDelayTime = 0; + m_respawnTime = 0; + break;*/ + default: + if(data->spawntimesecs >= 0) + { + m_spawnedByDefault = true; + m_respawnDelayTime = data->spawntimesecs; + m_respawnTime = objmgr.GetGORespawnTime(stored_guid, map->GetInstanceId()); + + // ready to respawn + if(m_respawnTime && m_respawnTime <= time(NULL)) + { + m_respawnTime = 0; + objmgr.SaveGORespawnTime(m_DBTableGuid,GetInstanceId(),0); + } + } + else + { + m_spawnedByDefault = false; + m_respawnDelayTime = -data->spawntimesecs; + m_respawnTime = 0; + } + break; + } + + return true; +} + +void GameObject::DeleteFromDB() +{ + objmgr.SaveGORespawnTime(m_DBTableGuid,GetInstanceId(),0); + objmgr.DeleteGOData(m_DBTableGuid); + WorldDatabase.PExecuteLog("DELETE FROM gameobject WHERE guid = '%u'", m_DBTableGuid); + WorldDatabase.PExecuteLog("DELETE FROM game_event_gameobject WHERE guid = '%u'", m_DBTableGuid); +} + +GameObject* GameObject::GetGameObject(WorldObject& object, uint64 guid) +{ + return ObjectAccessor::GetGameObject(object,guid); +} + +GameObjectInfo const *GameObject::GetGOInfo() const +{ + return m_goInfo; +} + +uint32 GameObject::GetLootId(GameObjectInfo const* ginfo) +{ + if (!ginfo) + return 0; + + switch(ginfo->type) + { + case GAMEOBJECT_TYPE_CHEST: + return ginfo->chest.lootId; + case GAMEOBJECT_TYPE_FISHINGHOLE: + return ginfo->fishinghole.lootId; + case GAMEOBJECT_TYPE_FISHINGNODE: + return ginfo->fishnode.lootId; + default: + return 0; + } +} + +/*********************************************************/ +/*** QUEST SYSTEM ***/ +/*********************************************************/ +bool GameObject::hasQuest(uint32 quest_id) const +{ + QuestRelations const& qr = objmgr.mGOQuestRelations; + for(QuestRelations::const_iterator itr = qr.lower_bound(GetEntry()); itr != qr.upper_bound(GetEntry()); ++itr) + { + if(itr->second==quest_id) + return true; + } + return false; +} + +bool GameObject::hasInvolvedQuest(uint32 quest_id) const +{ + QuestRelations const& qr = objmgr.mGOQuestInvolvedRelations; + for(QuestRelations::const_iterator itr = qr.lower_bound(GetEntry()); itr != qr.upper_bound(GetEntry()); ++itr) + { + if(itr->second==quest_id) + return true; + } + return false; +} + +bool GameObject::IsTransport() const +{ + // If something is marked as a transport, don't transmit an out of range packet for it. + GameObjectInfo const * gInfo = GetGOInfo(); + if(!gInfo) return false; + return gInfo->type == GAMEOBJECT_TYPE_TRANSPORT || gInfo->type == GAMEOBJECT_TYPE_MO_TRANSPORT; +} + +Unit* GameObject::GetOwner() const +{ + return ObjectAccessor::GetUnit(*this, GetOwnerGUID()); +} + +void GameObject::SaveRespawnTime() +{ + if(m_respawnTime > time(NULL) && m_spawnedByDefault) + objmgr.SaveGORespawnTime(m_DBTableGuid,GetInstanceId(),m_respawnTime); +} + +bool GameObject::isVisibleForInState(Player const* u, bool inVisibleList) const +{ + // Not in world + if(!IsInWorld() || !u->IsInWorld()) + return false; + + // Transport always visible at this step implementation + if(IsTransport() && IsInMap(u)) + return true; + + // quick check visibility false cases for non-GM-mode + if(!u->isGameMaster()) + { + // despawned and then not visible for non-GM in GM-mode + if(!isSpawned()) + return false; + + // special invisibility cases + /* TODO: implement trap stealth, take look at spell 2836 + if(GetGOInfo()->type == GAMEOBJECT_TYPE_TRAP && GetGOInfo()->trap.stealthed && u->IsHostileTo(GetOwner())) + { + if(check stuff here) + return false; + }*/ + + // Smuggled Mana Cell required 10 invisibility type detection/state + if(GetEntry()==187039 && ((u->m_detectInvisibilityMask | u->m_invisibilityMask) & (1<<10))==0) + return false; + } + + // check distance + return IsWithinDistInMap(u,World::GetMaxVisibleDistanceForObject() + + (inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f) ); +} + +void GameObject::Respawn() +{ + if(m_spawnedByDefault && m_respawnTime > 0) + { + m_respawnTime = time(NULL); + objmgr.SaveGORespawnTime(m_DBTableGuid,GetInstanceId(),0); + } +} + +bool GameObject::ActivateToQuest( Player *pTarget)const +{ + if(!objmgr.IsGameObjectForQuests(GetEntry())) + return false; + + switch(GetGoType()) + { + // scan GO chest with loot including quest items + case GAMEOBJECT_TYPE_CHEST: + { + if(LootTemplates_Gameobject.HaveQuestLootForPlayer(GetLootId(), pTarget)) + return true; + break; + } + case GAMEOBJECT_TYPE_GOOBER: + { + if(pTarget->GetQuestStatus(GetGOInfo()->goober.questId) == QUEST_STATUS_INCOMPLETE) + return true; + break; + } + default: + break; + } + + return false; +} + +void GameObject::TriggeringLinkedGameObject( uint32 trapEntry, Unit* target) +{ + GameObjectInfo const* trapInfo = sGOStorage.LookupEntry(trapEntry); + if(!trapInfo || trapInfo->type!=GAMEOBJECT_TYPE_TRAP) + return; + + SpellEntry const* trapSpell = sSpellStore.LookupEntry(trapInfo->trap.spellId); + if(!trapSpell) // checked at load already + return; + + float range = GetSpellMaxRange(sSpellRangeStore.LookupEntry(trapSpell->rangeIndex)); + + // search nearest linked GO + GameObject* trapGO = NULL; + { + // using original GO distance + CellPair p(MaNGOS::ComputeCellPair(GetPositionX(), GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + + MaNGOS::NearestGameObjectEntryInObjectRangeCheck go_check(*target,trapEntry,range); + MaNGOS::GameObjectLastSearcher checker(trapGO,go_check); + + TypeContainerVisitor, GridTypeMapContainer > object_checker(checker); + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, object_checker, *MapManager::Instance().GetMap(GetMapId(), this)); + } + + // found correct GO + // FIXME: when GO casting will be implemented trap must cast spell to target + if(trapGO) + target->CastSpell(target,trapSpell,true); +} + +GameObject* GameObject::LookupFishingHoleAround(float range) +{ + GameObject* ok = NULL; + + CellPair p(MaNGOS::ComputeCellPair(GetPositionX(),GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + MaNGOS::NearestGameObjectFishingHole u_check(*this, range); + MaNGOS::GameObjectSearcher checker(ok, u_check); + + CellLock cell_lock(cell, p); + + TypeContainerVisitor, GridTypeMapContainer > grid_object_checker(checker); + cell_lock->Visit(cell_lock, grid_object_checker, *MapManager::Instance().GetMap(GetMapId(), this)); + + return ok; +} + +void GameObject::UseDoorOrButton(uint32 time_to_restore) +{ + if(m_lootState != GO_READY) + return; + + if(!time_to_restore) + time_to_restore = GetAutoCloseTime(); + + SwitchDoorOrButton(true); + SetLootState(GO_ACTIVATED); + + m_cooldownTime = time(NULL) + time_to_restore; + +} + +void GameObject::SwitchDoorOrButton(bool activate) +{ + if(activate) + SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE); + else + RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE); + + if(GetGoState()) //if closed -> open + SetGoState(0); + else //if open -> close + SetGoState(1); +} + +void GameObject::Use(Unit* user) +{ + // by default spell caster is user + Unit* spellCaster = user; + uint32 spellId = 0; + + switch(GetGoType()) + { + case GAMEOBJECT_TYPE_DOOR: //0 + case GAMEOBJECT_TYPE_BUTTON: //1 + //doors/buttons never really despawn, only reset to default state/flags + UseDoorOrButton(); + + // activate script + sWorld.ScriptsStart(sGameObjectScripts, GetDBTableGUIDLow(), spellCaster, this); + return; + + case GAMEOBJECT_TYPE_QUESTGIVER: //2 + { + if(user->GetTypeId()!=TYPEID_PLAYER) + return; + + Player* player = (Player*)user; + + player->PrepareQuestMenu( GetGUID() ); + player->SendPreparedQuest( GetGUID() ); + return; + } + //Sitting: Wooden bench, chairs enzz + case GAMEOBJECT_TYPE_CHAIR: //7 + { + GameObjectInfo const* info = GetGOInfo(); + if(!info) + return; + + if(user->GetTypeId()!=TYPEID_PLAYER) + return; + + Player* player = (Player*)user; + + // a chair may have n slots. we have to calculate their positions and teleport the player to the nearest one + + // check if the db is sane + if(info->chair.slots > 0) + { + float lowestDist = DEFAULT_VISIBILITY_DISTANCE; + + float x_lowest = GetPositionX(); + float y_lowest = GetPositionY(); + + // the object orientation + 1/2 pi + // every slot will be on that straight line + float orthogonalOrientation = GetOrientation()+M_PI*0.5f; + // find nearest slot + for(uint32 i=0; ichair.slots; i++) + { + // the distance between this slot and the center of the go - imagine a 1D space + float relativeDistance = (info->size*i)-(info->size*(info->chair.slots-1)/2.0f); + + float x_i = GetPositionX() + relativeDistance * cos(orthogonalOrientation); + float y_i = GetPositionY() + relativeDistance * sin(orthogonalOrientation); + + // calculate the distance between the player and this slot + float thisDistance = player->GetDistance2d(x_i, y_i); + + /* debug code. It will spawn a npc on each slot to visualize them. + Creature* helper = player->SummonCreature(14496, x_i, y_i, GetPositionZ(), GetOrientation(), TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 10000); + std::ostringstream output; + output << i << ": thisDist: " << thisDistance; + helper->MonsterSay(output.str().c_str(), LANG_UNIVERSAL, 0); + */ + + if(thisDistance <= lowestDist) + { + lowestDist = thisDistance; + x_lowest = x_i; + y_lowest = y_i; + } + } + player->TeleportTo(GetMapId(), x_lowest, y_lowest, GetPositionZ(), GetOrientation(),TELE_TO_NOT_LEAVE_TRANSPORT | TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET); + } + else + { + // fallback, will always work + player->TeleportTo(GetMapId(), GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation(),TELE_TO_NOT_LEAVE_TRANSPORT | TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET); + } + player->SetStandState(PLAYER_STATE_SIT_LOW_CHAIR+info->chair.height); + return; + } + //big gun, its a spell/aura + case GAMEOBJECT_TYPE_GOOBER: //10 + { + GameObjectInfo const* info = GetGOInfo(); + + if(user->GetTypeId()==TYPEID_PLAYER) + { + Player* player = (Player*)user; + + // show page + if(info->goober.pageId) + { + WorldPacket data(SMSG_GAMEOBJECT_PAGETEXT, 8); + data << GetGUID(); + player->GetSession()->SendPacket(&data); + } + + // possible quest objective for active quests + player->CastedCreatureOrGO(info->id, GetGUID(), 0); + } + + // cast this spell later if provided + spellId = info->goober.spellId; + + break; + } + case GAMEOBJECT_TYPE_CAMERA: //13 + { + GameObjectInfo const* info = GetGOInfo(); + if(!info) + return; + + if(user->GetTypeId()!=TYPEID_PLAYER) + return; + + Player* player = (Player*)user; + + if(info->camera.cinematicId) + { + WorldPacket data(SMSG_TRIGGER_CINEMATIC, 4); + data << info->camera.cinematicId; + player->GetSession()->SendPacket(&data); + } + return; + } + //fishing bobber + case GAMEOBJECT_TYPE_FISHINGNODE: //17 + { + if(user->GetTypeId()!=TYPEID_PLAYER) + return; + + Player* player = (Player*)user; + + if(player->GetGUID() != GetOwnerGUID()) + return; + + switch(getLootState()) + { + case GO_READY: // ready for loot + { + // 1) skill must be >= base_zone_skill + // 2) if skill == base_zone_skill => 5% chance + // 3) chance is linear dependence from (base_zone_skill-skill) + + uint32 subzone = GetAreaId(); + + int32 zone_skill = objmgr.GetFishingBaseSkillLevel( subzone ); + if(!zone_skill) + zone_skill = objmgr.GetFishingBaseSkillLevel( GetZoneId() ); + + //provide error, no fishable zone or area should be 0 + if(!zone_skill) + sLog.outErrorDb("Fishable areaId %u are not properly defined in `skill_fishing_base_level`.",subzone); + + int32 skill = player->GetSkillValue(SKILL_FISHING); + int32 chance = skill - zone_skill + 5; + int32 roll = irand(1,100); + + DEBUG_LOG("Fishing check (skill: %i zone min skill: %i chance %i roll: %i",skill,zone_skill,chance,roll); + + if(skill >= zone_skill && chance >= roll) + { + // prevent removing GO at spell cancel + player->RemoveGameObject(this,false); + SetOwnerGUID(player->GetGUID()); + + //fish catched + player->UpdateFishingSkill(); + + GameObject* ok = LookupFishingHoleAround(DEFAULT_VISIBILITY_DISTANCE); + if (ok) + { + player->SendLoot(ok->GetGUID(),LOOT_FISHINGHOLE); + SetLootState(GO_JUST_DEACTIVATED); + } + else + player->SendLoot(GetGUID(),LOOT_FISHING); + } + else + { + // fish escaped, can be deleted now + SetLootState(GO_JUST_DEACTIVATED); + + WorldPacket data(SMSG_FISH_ESCAPED, 0); + player->GetSession()->SendPacket(&data); + } + break; + } + case GO_JUST_DEACTIVATED: // nothing to do, will be deleted at next update + break; + default: + { + SetLootState(GO_JUST_DEACTIVATED); + + WorldPacket data(SMSG_FISH_NOT_HOOKED, 0); + player->GetSession()->SendPacket(&data); + break; + } + } + + if(player->m_currentSpells[CURRENT_CHANNELED_SPELL]) + { + player->m_currentSpells[CURRENT_CHANNELED_SPELL]->SendChannelUpdate(0); + player->m_currentSpells[CURRENT_CHANNELED_SPELL]->finish(); + } + return; + } + + case GAMEOBJECT_TYPE_SUMMONING_RITUAL: //18 + { + if(user->GetTypeId()!=TYPEID_PLAYER) + return; + + Player* player = (Player*)user; + + Unit* caster = GetOwner(); + + GameObjectInfo const* info = GetGOInfo(); + + if( !caster || caster->GetTypeId()!=TYPEID_PLAYER ) + return; + + // accept only use by player from same group for caster except caster itself + if(((Player*)caster)==player || !((Player*)caster)->IsInSameRaidWith(player)) + return; + + AddUniqueUse(player); + + // full amount unique participants including original summoner + if(GetUniqueUseCount() < info->summoningRitual.reqParticipants) + return; + + // in case summoning ritual caster is GO creator + spellCaster = caster; + + if(!caster->m_currentSpells[CURRENT_CHANNELED_SPELL]) + return; + + spellId = info->summoningRitual.spellId; + + // finish spell + caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->SendChannelUpdate(0); + caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->finish(); + + // can be deleted now + SetLootState(GO_JUST_DEACTIVATED); + + // go to end function to spell casting + break; + } + case GAMEOBJECT_TYPE_SPELLCASTER: //22 + { + SetUInt32Value(GAMEOBJECT_FLAGS,2); + + GameObjectInfo const* info = GetGOInfo(); + if(!info) + return; + + if(info->spellcaster.partyOnly) + { + Unit* caster = GetOwner(); + if( !caster || caster->GetTypeId()!=TYPEID_PLAYER ) + return; + + if(user->GetTypeId()!=TYPEID_PLAYER || !((Player*)user)->IsInSameRaidWith((Player*)caster)) + return; + } + + spellId = info->spellcaster.spellId; + + AddUse(); + break; + } + case GAMEOBJECT_TYPE_MEETINGSTONE: //23 + { + GameObjectInfo const* info = GetGOInfo(); + + if(user->GetTypeId()!=TYPEID_PLAYER) + return; + + Player* player = (Player*)user; + + Player* targetPlayer = ObjectAccessor::FindPlayer(player->GetSelection()); + + // accept only use by player from same group for caster except caster itself + if(!targetPlayer || targetPlayer == player || !targetPlayer->IsInSameGroupWith(player)) + return; + + //required lvl checks! + uint8 level = player->getLevel(); + if (level < info->meetingstone.minLevel || level > info->meetingstone.maxLevel) + return; + level = targetPlayer->getLevel(); + if (level < info->meetingstone.minLevel || level > info->meetingstone.maxLevel) + return; + + spellId = 23598; + + break; + } + + case GAMEOBJECT_TYPE_FLAGSTAND: // 24 + { + if(user->GetTypeId()!=TYPEID_PLAYER) + return; + + Player* player = (Player*)user; + + if( player->InBattleGround() && // in battleground + !player->IsMounted() && // not mounted + !player->HasStealthAura() && // not stealthed + !player->HasInvisibilityAura() && // not invisible + player->isAlive()) // live player + { + BattleGround *bg = player->GetBattleGround(); + if(!bg) + return; + // BG flag click + // AB: + // 15001 + // 15002 + // 15003 + // 15004 + // 15005 + bg->EventPlayerClickedOnFlag(player, this); + return; //we don;t need to delete flag ... it is despawned! + } + break; + } + case GAMEOBJECT_TYPE_FLAGDROP: // 26 + { + if(user->GetTypeId()!=TYPEID_PLAYER) + return; + + Player* player = (Player*)user; + + if( player->InBattleGround() && // in battleground + !player->IsMounted() && // not mounted + !player->HasStealthAura() && // not stealthed + !player->HasInvisibilityAura() && // not invisible + !player->HasAura(SPELL_RECENTLY_DROPPED_FLAG, 0) && // can't pickup + player->isAlive()) // live player + { + BattleGround *bg = player->GetBattleGround(); + if(!bg) + return; + // BG flag dropped + // WS: + // 179785 - Silverwing Flag + // 179786 - Warsong Flag + // EotS: + // 184142 - Netherstorm Flag + GameObjectInfo const* info = GetGOInfo(); + if(info) + { + switch(info->id) + { + case 179785: // Silverwing Flag + // check if it's correct bg + if(bg->GetTypeID() == BATTLEGROUND_WS) + bg->EventPlayerClickedOnFlag(player, this); + break; + case 179786: // Warsong Flag + if(bg->GetTypeID() == BATTLEGROUND_WS) + bg->EventPlayerClickedOnFlag(player, this); + break; + case 184142: // Netherstorm Flag + if(bg->GetTypeID() == BATTLEGROUND_EY) + bg->EventPlayerClickedOnFlag(player, this); + break; + } + } + //this cause to call return, all flags must be deleted here!! + spellId = 0; + Delete(); + } + break; + } + default: + sLog.outDebug("Unknown Object Type %u", GetGoType()); + break; + } + + if(!spellId) + return; + + SpellEntry const *spellInfo = sSpellStore.LookupEntry( spellId ); + if(!spellInfo) + { + sLog.outError("WORLD: unknown spell id %u at use action for gameobject (Entry: %u GoType: %u )", spellId,GetEntry(),GetGoType()); + return; + } + + Spell *spell = new Spell(spellCaster, spellInfo, false); + + // spell target is user of GO + SpellCastTargets targets; + targets.setUnitTarget( user ); + + spell->prepare(&targets); +} diff --git a/src/game/GameObject.h b/src/game/GameObject.h new file mode 100644 index 00000000000..30f3a815397 --- /dev/null +++ b/src/game/GameObject.h @@ -0,0 +1,592 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOSSERVER_GAMEOBJECT_H +#define MANGOSSERVER_GAMEOBJECT_H + +#include "Common.h" +#include "SharedDefines.h" +#include "Object.h" +#include "LootMgr.h" +#include "Database/DatabaseEnv.h" + +// GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push,N), also any gcc version not support it at some platform +#if defined( __GNUC__ ) +#pragma pack(1) +#else +#pragma pack(push,1) +#endif + +// from `gameobject_template` +struct GameObjectInfo +{ + uint32 id; + uint32 type; + uint32 displayId; + char *name; + char *castBarCaption; + uint32 faction; + uint32 flags; + float size; + union // different GO types have different data field + { + //0 GAMEOBJECT_TYPE_DOOR + struct + { + uint32 startOpen; //0 used client side to determine GO_ACTIVATED means open/closed + uint32 lockId; //1 -> Lock.dbc + uint32 autoCloseTime; //2 secs till autoclose = autoCloseTime / 0x10000 + uint32 noDamageImmune; //3 break opening whenever you recieve damage? + uint32 openTextID; //4 can be used to replace castBarCaption? + uint32 closeTextID; //5 + } door; + //1 GAMEOBJECT_TYPE_BUTTON + struct + { + uint32 startOpen; //0 + uint32 lockId; //1 -> Lock.dbc + uint32 autoCloseTime; //2 secs till autoclose = autoCloseTime / 0x10000 + uint32 linkedTrap; //3 + uint32 noDamageImmune; //4 isBattlegroundObject + uint32 large; //5 + uint32 openTextID; //6 can be used to replace castBarCaption? + uint32 closeTextID; //7 + uint32 losOK; //8 + } button; + //2 GAMEOBJECT_TYPE_QUESTGIVER + struct + { + uint32 lockId; //0 -> Lock.dbc + uint32 questList; //1 + uint32 pageMaterial; //2 + uint32 gossipID; //3 + uint32 customAnim; //4 + uint32 noDamageImmune; //5 + uint32 openTextID; //6 can be used to replace castBarCaption? + uint32 losOK; //7 + uint32 allowMounted; //8 + uint32 large; //9 + } questgiver; + //3 GAMEOBJECT_TYPE_CHEST + struct + { + uint32 lockId; //0 -> Lock.dbc + uint32 lootId; //1 + uint32 chestRestockTime; //2 + uint32 consumable; //3 + uint32 minSuccessOpens; //4 + uint32 maxSuccessOpens; //5 + uint32 eventId; //6 lootedEvent + uint32 linkedTrapId; //7 + uint32 questId; //8 not used currently but store quest required for GO activation for player + uint32 level; //9 + uint32 losOK; //10 + uint32 leaveLoot; //11 + uint32 notInCombat; //12 + uint32 logLoot; //13 + uint32 openTextID; //14 can be used to replace castBarCaption? + uint32 groupLootRules; //15 + } chest; + //5 GAMEOBJECT_TYPE_GENERIC + struct + { + uint32 floatingTooltip; //0 + uint32 highlight; //1 + uint32 serverOnly; //2 + uint32 large; //3 + uint32 floatOnWater; //4 + uint32 questID; //5 + } _generic; + //6 GAMEOBJECT_TYPE_TRAP + struct + { + uint32 lockId; //0 -> Lock.dbc + uint32 level; //1 + uint32 radius; //2 radius for trap activation + uint32 spellId; //3 + uint32 charges; //4 need respawn (if > 0) + uint32 cooldown; //5 time in secs + uint32 autoCloseTime; //6 + uint32 startDelay; //7 + uint32 serverOnly; //8 + uint32 stealthed; //9 + uint32 large; //10 + uint32 stealthAffected; //11 + uint32 openTextID; //12 can be used to replace castBarCaption? + uint32 closeTextID; //13 + } trap; + //7 GAMEOBJECT_TYPE_CHAIR + struct + { + uint32 slots; //0 + uint32 height; //1 + uint32 onlyCreatorUse; //2 + } chair; + //8 GAMEOBJECT_TYPE_SPELL_FOCUS + struct + { + uint32 focusId; //0 + uint32 dist; //1 + uint32 linkedTrapId; //2 + uint32 serverOnly; //3 + uint32 questID; //4 + uint32 large; //5 + } spellFocus; + //9 GAMEOBJECT_TYPE_TEXT + struct + { + uint32 pageID; //0 + uint32 language; //1 + uint32 pageMaterial; //2 + uint32 allowMounted; //3 + } text; + //10 GAMEOBJECT_TYPE_GOOBER + struct + { + uint32 lockId; //0 -> Lock.dbc + uint32 questId; //1 + uint32 eventId; //2 + uint32 autoCloseTime; //3 + uint32 customAnim; //4 + uint32 consumable; //5 + uint32 cooldown; //6 + uint32 pageId; //7 + uint32 language; //8 + uint32 pageMaterial; //9 + uint32 spellId; //10 + uint32 noDamageImmune; //11 + uint32 linkedTrapId; //12 + uint32 large; //13 + uint32 openTextID; //14 can be used to replace castBarCaption? + uint32 closeTextID; //15 + uint32 losOK; //16 isBattlegroundObject + uint32 allowMounted; //17 + } goober; + //11 GAMEOBJECT_TYPE_TRANSPORT + struct + { + uint32 pause; //0 + uint32 startOpen; //1 + uint32 autoCloseTime; //2 secs till autoclose = autoCloseTime / 0x10000 + } transport; + //12 GAMEOBJECT_TYPE_AREADAMAGE + struct + { + uint32 lockId; //0 + uint32 radius; //1 + uint32 damageMin; //2 + uint32 damageMax; //3 + uint32 damageSchool; //4 + uint32 autoCloseTime; //5 secs till autoclose = autoCloseTime / 0x10000 + uint32 openTextID; //6 + uint32 closeTextID; //7 + } areadamage; + //13 GAMEOBJECT_TYPE_CAMERA + struct + { + uint32 lockId; //0 -> Lock.dbc + uint32 cinematicId; //1 + uint32 eventID; //2 + uint32 openTextID; //3 can be used to replace castBarCaption? + } camera; + //15 GAMEOBJECT_TYPE_MO_TRANSPORT + struct + { + uint32 taxiPathId; //0 + uint32 moveSpeed; //1 + uint32 accelRate; //2 + uint32 startEventID; //3 + uint32 stopEventID; //4 + uint32 transportPhysics; //5 + uint32 mapID; //6 + } moTransport; + //17 GAMEOBJECT_TYPE_FISHINGNODE + struct + { + uint32 _data0; //0 + uint32 lootId; //1 + } fishnode; + //18 GAMEOBJECT_TYPE_SUMMONING_RITUAL + struct + { + uint32 reqParticipants; //0 + uint32 spellId; //1 + uint32 animSpell; //2 + uint32 ritualPersistent; //3 + uint32 casterTargetSpell; //4 + uint32 casterTargetSpellTargets; //5 + uint32 castersGrouped; //6 + uint32 ritualNoTargetCheck; //7 + } summoningRitual; + //20 GAMEOBJECT_TYPE_AUCTIONHOUSE + struct + { + uint32 actionHouseID; //0 + } auctionhouse; + //21 GAMEOBJECT_TYPE_GUARDPOST + struct + { + uint32 creatureID; //0 + uint32 charges; //1 + } guardpost; + //22 GAMEOBJECT_TYPE_SPELLCASTER + struct + { + uint32 spellId; //0 + uint32 charges; //1 + uint32 partyOnly; //2 + } spellcaster; + //23 GAMEOBJECT_TYPE_MEETINGSTONE + struct + { + uint32 minLevel; //0 + uint32 maxLevel; //1 + uint32 areaID; //2 + } meetingstone; + //24 GAMEOBJECT_TYPE_FLAGSTAND + struct + { + uint32 lockId; //0 + uint32 pickupSpell; //1 + uint32 radius; //2 + uint32 returnAura; //3 + uint32 returnSpell; //4 + uint32 noDamageImmune; //5 + uint32 openTextID; //6 + uint32 losOK; //7 + } flagstand; + //25 GAMEOBJECT_TYPE_FISHINGHOLE // not implemented yet + struct + { + uint32 radius; //0 how close bobber must land for sending loot + uint32 lootId; //1 + uint32 minSuccessOpens; //2 + uint32 maxSuccessOpens; //3 + uint32 lockId; //4 -> Lock.dbc; possibly 1628 for all? + } fishinghole; + //26 GAMEOBJECT_TYPE_FLAGDROP + struct + { + uint32 lockId; //0 + uint32 eventID; //1 + uint32 pickupSpell; //2 + uint32 noDamageImmune; //3 + uint32 openTextID; //4 + } flagdrop; + //27 GAMEOBJECT_TYPE_MINI_GAME + struct + { + uint32 gameType; //0 + } miniGame; + //29 GAMEOBJECT_TYPE_CAPTURE_POINT + struct + { + uint32 radius; //0 + uint32 spell; //1 + uint32 worldState1; //2 + uint32 worldstate2; //3 + uint32 winEventID1; //4 + uint32 winEventID2; //5 + uint32 contestedEventID1; //6 + uint32 contestedEventID2; //7 + uint32 progressEventID1; //8 + uint32 progressEventID2; //9 + uint32 neutralEventID1; //10 + uint32 neutralEventID2; //11 + uint32 neutralPercent; //12 + uint32 worldstate3; //13 + uint32 minSuperiority; //14 + uint32 maxSuperiority; //15 + uint32 minTime; //16 + uint32 maxTime; //17 + uint32 large; //18 + uint32 highlight; //19 + } capturePoint; + //30 GAMEOBJECT_TYPE_AURA_GENERATOR + struct + { + uint32 startOpen; //0 + uint32 radius; //1 + uint32 auraID1; //2 + uint32 conditionID1; //3 + uint32 auraID2; //4 + uint32 conditionID2; //5 + uint32 serverOnly; //6 + } auraGenerator; + //31 GAMEOBJECT_TYPE_DUNGEON_DIFFICULTY + struct + { + uint32 mapID; //0 + uint32 difficulty; //1 + } dungeonDifficulty; + //32 GAMEOBJECT_TYPE_DO_NOT_USE_YET + struct + { + uint32 mapID; //0 + uint32 difficulty; //1 + } doNotUseYet; + //33 GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING + struct + { + uint32 dmgPctState1; //0 + uint32 dmgPctState2; //1 + uint32 state1Name; //2 + uint32 state2Name; //3 + } destructibleBuilding; + + // not use for specific field access (only for output with loop by all filed), also this determinate max union size + struct // GAMEOBJECT_TYPE_SPELLCASTER + { + uint32 data[24]; + } raw; + }; + char *ScriptName; +}; + +struct GameObjectLocale +{ + std::vector Name; + std::vector CastBarCaption; +}; + +// from `gameobject` +struct GameObjectData +{ + uint32 id; // entry in gamobject_template + uint32 mapid; + float posX; + float posY; + float posZ; + float orientation; + float rotation0; + float rotation1; + float rotation2; + float rotation3; + int32 spawntimesecs; + uint32 animprogress; + uint32 go_state; + uint8 spawnMask; +}; + +// GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some platform +#if defined( __GNUC__ ) +#pragma pack() +#else +#pragma pack(pop) +#endif + +// For containers: [GO_NOT_READY]->GO_READY (close)->GO_ACTIVATED (open) ->GO_JUST_DEACTIVATED->GO_READY -> ... +// For bobber: GO_NOT_READY ->GO_READY (close)->GO_ACTIVATED (open) ->GO_JUST_DEACTIVATED-> +// For door(closed):[GO_NOT_READY]->GO_READY (close)->GO_ACTIVATED (open) ->GO_JUST_DEACTIVATED->GO_READY(close) -> ... +// For door(open): [GO_NOT_READY]->GO_READY (open) ->GO_ACTIVATED (close)->GO_JUST_DEACTIVATED->GO_READY(open) -> ... +enum LootState +{ + GO_NOT_READY = 0, + GO_READY, // can be ready but despawned, and then not possible activate until spawn + GO_ACTIVATED, + GO_JUST_DEACTIVATED +}; + +class Unit; + +// 5 sec for bobber catch +#define FISHING_BOBBER_READY_TIME 5 + +class MANGOS_DLL_SPEC GameObject : public WorldObject +{ + public: + explicit GameObject(); + ~GameObject(); + + void AddToWorld(); + void RemoveFromWorld(); + + bool Create(uint32 guidlow, uint32 name_id, Map *map, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, uint32 go_state); + void Update(uint32 p_time); + static GameObject* GetGameObject(WorldObject& object, uint64 guid); + GameObjectInfo const* GetGOInfo() const; + + bool IsTransport() const; + + void SetOwnerGUID(uint64 owner) + { + m_spawnedByDefault = false; // all object with owner is despawned after delay + SetUInt64Value(OBJECT_FIELD_CREATED_BY, owner); + } + uint64 GetOwnerGUID() const { return GetUInt64Value(OBJECT_FIELD_CREATED_BY); } + Unit* GetOwner() const; + + uint32 GetDBTableGUIDLow() const { return m_DBTableGuid; } + + void Say(const char* text, uint32 language, uint64 TargetGuid) { MonsterSay(text,language,TargetGuid); } + void Yell(const char* text, uint32 language, uint64 TargetGuid) { MonsterYell(text,language,TargetGuid); } + void TextEmote(const char* text, uint64 TargetGuid) { MonsterTextEmote(text,TargetGuid); } + void Whisper(const char* text,uint64 receiver) { MonsterWhisper(text,receiver); } + void Say(int32 textId, uint32 language, uint64 TargetGuid) { MonsterSay(textId,language,TargetGuid); } + void Yell(int32 textId, uint32 language, uint64 TargetGuid) { MonsterYell(textId,language,TargetGuid); } + void TextEmote(int32 textId, uint64 TargetGuid) { MonsterTextEmote(textId,TargetGuid); } + void Whisper(int32 textId, uint64 receiver) { MonsterWhisper(textId,receiver); } + + void SaveToDB(); + void SaveToDB(uint32 mapid, uint8 spawnMask); + bool LoadFromDB(uint32 guid, Map *map); + void DeleteFromDB(); + void SetLootState(LootState s) { m_lootState = s; } + static uint32 GetLootId(GameObjectInfo const* info); + uint32 GetLootId() const { return GetLootId(GetGOInfo()); } + uint32 GetLockId() const + { + switch(GetGoType()) + { + case GAMEOBJECT_TYPE_DOOR: return GetGOInfo()->door.lockId; + case GAMEOBJECT_TYPE_BUTTON: return GetGOInfo()->button.lockId; + case GAMEOBJECT_TYPE_QUESTGIVER: return GetGOInfo()->questgiver.lockId; + case GAMEOBJECT_TYPE_CHEST: return GetGOInfo()->chest.lockId; + case GAMEOBJECT_TYPE_TRAP: return GetGOInfo()->trap.lockId; + case GAMEOBJECT_TYPE_GOOBER: return GetGOInfo()->goober.lockId; + case GAMEOBJECT_TYPE_AREADAMAGE: return GetGOInfo()->areadamage.lockId; + case GAMEOBJECT_TYPE_CAMERA: return GetGOInfo()->camera.lockId; + case GAMEOBJECT_TYPE_FLAGSTAND: return GetGOInfo()->flagstand.lockId; + case GAMEOBJECT_TYPE_FISHINGHOLE:return GetGOInfo()->fishinghole.lockId; + case GAMEOBJECT_TYPE_FLAGDROP: return GetGOInfo()->flagdrop.lockId; + default: return 0; + } + } + + time_t GetRespawnTime() const { return m_respawnTime; } + time_t GetRespawnTimeEx() const + { + time_t now = time(NULL); + if(m_respawnTime > now) + return m_respawnTime; + else + return now; + } + + void SetRespawnTime(int32 respawn) + { + m_respawnTime = respawn > 0 ? time(NULL) + respawn : 0; + m_respawnDelayTime = respawn > 0 ? respawn : 0; + } + void Respawn(); + bool isSpawned() const + { + return m_respawnDelayTime == 0 || + (m_respawnTime > 0 && !m_spawnedByDefault) || + (m_respawnTime == 0 && m_spawnedByDefault); + } + bool isSpawnedByDefault() const { return m_spawnedByDefault; } + uint32 GetRespawnDelay() const { return m_respawnDelayTime; } + void Refresh(); + void Delete(); + void SetSpellId(uint32 id) { m_spellId = id;} + uint32 GetSpellId() const { return m_spellId;} + void getFishLoot(Loot *loot); + GameobjectTypes GetGoType() const { return GameobjectTypes(GetUInt32Value(GAMEOBJECT_TYPE_ID)); } + void SetGoType(GameobjectTypes type) { SetUInt32Value(GAMEOBJECT_TYPE_ID, type); } + uint32 GetGoState() const { return GetUInt32Value(GAMEOBJECT_STATE); } + void SetGoState(uint32 state) { SetUInt32Value(GAMEOBJECT_STATE, state); } + uint32 GetGoArtKit() const { return GetUInt32Value(GAMEOBJECT_ARTKIT); } + void SetGoArtKit(uint32 artkit) { SetUInt32Value(GAMEOBJECT_ARTKIT, artkit); } + uint32 GetGoAnimProgress() const { return GetUInt32Value(GAMEOBJECT_ANIMPROGRESS); } + void SetGoAnimProgress(uint32 animprogress) { SetUInt32Value(GAMEOBJECT_ANIMPROGRESS, animprogress); } + + void Use(Unit* user); + + LootState getLootState() const { return m_lootState; } + + void AddToSkillupList(uint32 PlayerGuidLow) { m_SkillupList.push_back(PlayerGuidLow); } + bool IsInSkillupList(uint32 PlayerGuidLow) const + { + for (std::list::const_iterator i = m_SkillupList.begin(); i != m_SkillupList.end(); ++i) + if (*i == PlayerGuidLow) return true; + return false; + } + void ClearSkillupList() { m_SkillupList.clear(); } + + void AddUniqueUse(Player* player); + void AddUse() { ++m_usetimes; } + + uint32 GetUseCount() const { return m_usetimes; } + uint32 GetUniqueUseCount() const { return m_unique_users.size(); } + + void SaveRespawnTime(); + + Loot loot; + + bool hasQuest(uint32 quest_id) const; + bool hasInvolvedQuest(uint32 quest_id) const; + bool ActivateToQuest(Player *pTarget) const; + void UseDoorOrButton(uint32 time_to_restore = 0); // 0 = use `gameobject`.`spawntimesecs` + + uint32 GetLinkedGameObjectEntry() const + { + switch(GetGoType()) + { + case GAMEOBJECT_TYPE_CHEST: return GetGOInfo()->chest.linkedTrapId; + case GAMEOBJECT_TYPE_SPELL_FOCUS: return GetGOInfo()->spellFocus.linkedTrapId; + case GAMEOBJECT_TYPE_GOOBER: return GetGOInfo()->goober.linkedTrapId; + default: return 0; + } + } + + uint32 GetAutoCloseTime() const + { + uint32 autoCloseTime = 0; + switch(GetGoType()) + { + case GAMEOBJECT_TYPE_DOOR: autoCloseTime = GetGOInfo()->door.autoCloseTime; break; + case GAMEOBJECT_TYPE_BUTTON: autoCloseTime = GetGOInfo()->button.autoCloseTime; break; + case GAMEOBJECT_TYPE_TRAP: autoCloseTime = GetGOInfo()->trap.autoCloseTime; break; + case GAMEOBJECT_TYPE_GOOBER: autoCloseTime = GetGOInfo()->goober.autoCloseTime; break; + case GAMEOBJECT_TYPE_TRANSPORT: autoCloseTime = GetGOInfo()->transport.autoCloseTime; break; + case GAMEOBJECT_TYPE_AREADAMAGE: autoCloseTime = GetGOInfo()->areadamage.autoCloseTime; break; + default: break; + } + return autoCloseTime / 0x10000; + } + + void TriggeringLinkedGameObject( uint32 trapEntry, Unit* target); + + bool isVisibleForInState(Player const* u, bool inVisibleList) const; + + GameObject* LookupFishingHoleAround(float range); + + GridReference &GetGridRef() { return m_gridRef; } + protected: + uint32 m_charges; // Spell charges for GAMEOBJECT_TYPE_SPELLCASTER (22) + uint32 m_spellId; + time_t m_respawnTime; // (secs) time of next respawn (or despawn if GO have owner()), + uint32 m_respawnDelayTime; // (secs) if 0 then current GO state no dependent from timer + LootState m_lootState; + bool m_spawnedByDefault; + time_t m_cooldownTime; // used as internal reaction delay time store (not state change reaction). + // For traps this: spell casting cooldown, for doors/buttons: reset time. + std::list m_SkillupList; + + std::set m_unique_users; + uint32 m_usetimes; + + uint32 m_DBTableGuid; + GameObjectInfo const* m_goInfo; + private: + void SwitchDoorOrButton(bool activate); + + GridReference m_gridRef; +}; +#endif diff --git a/src/game/GlobalEvents.cpp b/src/game/GlobalEvents.cpp new file mode 100644 index 00000000000..5bac79ad102 --- /dev/null +++ b/src/game/GlobalEvents.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** \file + \ingroup world +*/ + +#include "Log.h" +#include "Database/DatabaseEnv.h" +#include "Platform/Define.h" +#include "MapManager.h" +#include "ObjectAccessor.h" +#include "GlobalEvents.h" +#include "ObjectDefines.h" +#include "Corpse.h" + +/// Handle periodic erase of corpses and bones +static void CorpsesErase(bool bones,uint32 delay) +{ + ///- Get the list of eligible corpses/bones to be removed + //No SQL injection (uint32 and enum) + QueryResult *result = CharacterDatabase.PQuery("SELECT guid,position_x,position_y,map,player FROM corpse WHERE UNIX_TIMESTAMP()-time > '%u' AND corpse_type %s '0'", delay, (bones ? "=" : "<>") ); + + if(result) + { + do + { + Field *fields = result->Fetch(); + uint32 guidlow = fields[0].GetUInt32(); + float positionX = fields[1].GetFloat(); + float positionY = fields[2].GetFloat(); + uint32 mapid = fields[3].GetUInt32(); + uint64 player_guid = MAKE_NEW_GUID(fields[4].GetUInt32(), 0, HIGHGUID_PLAYER); + + uint64 guid = MAKE_NEW_GUID(guidlow, 0, HIGHGUID_CORPSE); + + sLog.outDebug("[Global event] Removing %s %u (X:%f Y:%f Map:%u).",(bones?"bones":"corpse"),guidlow,positionX,positionY,mapid); + + /// Resurrectable - convert corpses to bones + if(!bones) + { + if(!ObjectAccessor::Instance().ConvertCorpseForPlayer(player_guid)) + { + sLog.outDebug("Corpse %u not found in world. Delete from DB.",guidlow); + CharacterDatabase.PExecute("DELETE FROM corpse WHERE guid = '%u'",guidlow); + } + } + else + ///- or delete bones + { + MapManager::Instance().RemoveBonesFromMap(mapid, guid, positionX, positionY); + + ///- remove bones from the database + CharacterDatabase.PExecute("DELETE FROM corpse WHERE guid = '%u'",guidlow); + } + } while (result->NextRow()); + + delete result; + } +} + +/// not thread guarded variant for call from other thread +void CorpsesErase() +{ + CorpsesErase(true, 20*MINUTE); + CorpsesErase(false,3*DAY); +} diff --git a/src/game/GlobalEvents.h b/src/game/GlobalEvents.h new file mode 100644 index 00000000000..aacf72d730a --- /dev/null +++ b/src/game/GlobalEvents.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/// \addtogroup world +/// @{ +/// \file + +#ifndef __GLOBALEVENTS_H +#define __GLOBALEVENTS_H + +void CorpsesErase(); +void HandleCorpsesErase(void*); +#endif +/// @} diff --git a/src/game/GossipDef.cpp b/src/game/GossipDef.cpp new file mode 100644 index 00000000000..57c3597a7b8 --- /dev/null +++ b/src/game/GossipDef.cpp @@ -0,0 +1,765 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "QuestDef.h" +#include "GossipDef.h" +#include "ObjectMgr.h" +#include "Opcodes.h" +#include "WorldPacket.h" +#include "WorldSession.h" + +GossipMenu::GossipMenu() +{ + m_gItems.reserve(16); // can be set for max from most often sizes to speedup push_back and less memory use +} + +GossipMenu::~GossipMenu() +{ + ClearMenu(); +} + +void GossipMenu::AddMenuItem(uint8 Icon, std::string Message, uint32 dtSender, uint32 dtAction, std::string BoxMessage, uint32 BoxMoney, bool Coded) +{ + ASSERT( m_gItems.size() <= GOSSIP_MAX_MENU_ITEMS ); + + GossipMenuItem gItem; + + gItem.m_gIcon = Icon; + gItem.m_gMessage = Message; + gItem.m_gCoded = Coded; + gItem.m_gSender = dtSender; + gItem.m_gAction = dtAction; + gItem.m_gBoxMessage = BoxMessage; + gItem.m_gBoxMoney = BoxMoney; + + m_gItems.push_back(gItem); +} + +void GossipMenu::AddMenuItem(uint8 Icon, std::string Message, bool Coded) +{ + AddMenuItem( Icon, Message, 0, 0, "", 0, Coded); +} + +void GossipMenu::AddMenuItem(uint8 Icon, char const* Message, bool Coded) +{ + AddMenuItem(Icon, std::string(Message ? Message : ""),Coded); +} + +void GossipMenu::AddMenuItem(uint8 Icon, char const* Message, uint32 dtSender, uint32 dtAction, char const* BoxMessage, uint32 BoxMoney, bool Coded) +{ + AddMenuItem(Icon, std::string(Message ? Message : ""), dtSender, dtAction, std::string(BoxMessage ? BoxMessage : ""), BoxMoney, Coded); +} + +uint32 GossipMenu::MenuItemSender( unsigned int ItemId ) +{ + if ( ItemId >= m_gItems.size() ) return 0; + + return m_gItems[ ItemId ].m_gSender; +} + +uint32 GossipMenu::MenuItemAction( unsigned int ItemId ) +{ + if ( ItemId >= m_gItems.size() ) return 0; + + return m_gItems[ ItemId ].m_gAction; +} + +bool GossipMenu::MenuItemCoded( unsigned int ItemId ) +{ + if ( ItemId >= m_gItems.size() ) return 0; + + return m_gItems[ ItemId ].m_gCoded; +} + +void GossipMenu::ClearMenu() +{ + m_gItems.clear(); +} + +PlayerMenu::PlayerMenu( WorldSession *Session ) +{ + pGossipMenu = new GossipMenu(); + pQuestMenu = new QuestMenu(); + pSession = Session; +} + +PlayerMenu::~PlayerMenu() +{ + delete pGossipMenu; + delete pQuestMenu; +} + +void PlayerMenu::ClearMenus() +{ + pGossipMenu->ClearMenu(); + pQuestMenu->ClearMenu(); +} + +uint32 PlayerMenu::GossipOptionSender( unsigned int Selection ) +{ + return pGossipMenu->MenuItemSender( Selection ); +} + +uint32 PlayerMenu::GossipOptionAction( unsigned int Selection ) +{ + return pGossipMenu->MenuItemAction( Selection ); +} + +bool PlayerMenu::GossipOptionCoded( unsigned int Selection ) +{ + return pGossipMenu->MenuItemCoded( Selection ); +} + +void PlayerMenu::SendGossipMenu( uint32 TitleTextId, uint64 npcGUID ) +{ + WorldPacket data( SMSG_GOSSIP_MESSAGE, (100) ); // guess size + data << npcGUID; + data << uint32(0); // new 2.4.0 + data << uint32( TitleTextId ); + data << uint32( pGossipMenu->MenuItemCount() ); // max count 0x0F + + for ( unsigned int iI = 0; iI < pGossipMenu->MenuItemCount(); iI++ ) + { + GossipMenuItem const& gItem = pGossipMenu->GetItem(iI); + data << uint32( iI ); + data << uint8( gItem.m_gIcon ); + // icons: + // 0 unlearn talents/misc + // 1 trader + // 2 taxi + // 3 trainer + // 9 BG/arena + data << uint8( gItem.m_gCoded ); // makes pop up box password + data << uint32(gItem.m_gBoxMoney); // money required to open menu, 2.0.3 + data << gItem.m_gMessage; // text for gossip item + data << gItem.m_gBoxMessage; // accept text (related to money) pop up box, 2.0.3 + } + + data << uint32( pQuestMenu->MenuItemCount() ); // max count 0x20 + + for ( uint16 iI = 0; iI < pQuestMenu->MenuItemCount(); iI++ ) + { + QuestMenuItem const& qItem = pQuestMenu->GetItem(iI); + uint32 questID = qItem.m_qId; + Quest const* pQuest = objmgr.GetQuestTemplate(questID); + + data << questID; + data << uint32( qItem.m_qIcon ); + data << uint32( pQuest ? pQuest->GetQuestLevel() : 0 ); + std::string Title = pQuest->GetTitle(); + + int loc_idx = pSession->GetSessionDbLocaleIndex(); + if (loc_idx >= 0) + { + QuestLocale const *ql = objmgr.GetQuestLocale(questID); + if (ql) + { + if (ql->Title.size() > loc_idx && !ql->Title[loc_idx].empty()) + Title=ql->Title[loc_idx]; + } + } + data << Title; + } + + pSession->SendPacket( &data ); + //sLog.outDebug( "WORLD: Sent SMSG_GOSSIP_MESSAGE NPCGuid=%u",GUID_LOPART(npcGUID) ); +} + +void PlayerMenu::CloseGossip() +{ + WorldPacket data( SMSG_GOSSIP_COMPLETE, 0 ); + pSession->SendPacket( &data ); + + //sLog.outDebug( "WORLD: Sent SMSG_GOSSIP_COMPLETE" ); +} + +void PlayerMenu::SendPointOfInterest( float X, float Y, uint32 Icon, uint32 Flags, uint32 Data, char const * locName ) +{ + WorldPacket data( SMSG_GOSSIP_POI, (4+4+4+4+4+10) ); // guess size + data << Flags; + data << X << Y; + data << uint32(Icon); + data << uint32(Data); + data << locName; + + pSession->SendPacket( &data ); + //sLog.outDebug("WORLD: Sent SMSG_GOSSIP_POI"); +} + +void PlayerMenu::SendTalking( uint32 textID ) +{ + GossipText *pGossip; + std::string GossipStr; + + pGossip = objmgr.GetGossipText(textID); + + WorldPacket data( SMSG_NPC_TEXT_UPDATE, 100 ); // guess size + data << textID; // can be < 0 + + if (!pGossip) + { + for(uint32 i = 0; i < 8; ++i) + { + data << float(0); + data << "Greetings $N"; + data << "Greetings $N"; + data << uint32(0); + data << uint32(0); + data << uint32(0); + data << uint32(0); + data << uint32(0); + data << uint32(0); + data << uint32(0); + } + } + else + { + std::string Text_0[8],Text_1[8]; + for (int i=0;i<8;i++) + { + Text_0[i]=pGossip->Options[i].Text_0; + Text_1[i]=pGossip->Options[i].Text_1; + } + int loc_idx = pSession->GetSessionDbLocaleIndex(); + if (loc_idx >= 0) + { + NpcTextLocale const *nl = objmgr.GetNpcTextLocale(textID); + if (nl) + { + for (int i=0;i<8;i++) + { + if (nl->Text_0[i].size() > loc_idx && !nl->Text_0[i][loc_idx].empty()) + Text_0[i]=nl->Text_0[i][loc_idx]; + if (nl->Text_1[i].size() > loc_idx && !nl->Text_1[i][loc_idx].empty()) + Text_1[i]=nl->Text_1[i][loc_idx]; + } + } + } + for (int i=0; i<8; i++) + { + data << pGossip->Options[i].Probability; + + if ( Text_0[i].empty() ) + data << Text_1[i]; + else + data << Text_0[i]; + + if ( Text_1[i].empty() ) + data << Text_0[i]; + else + data << Text_1[i]; + + data << pGossip->Options[i].Language; + + data << pGossip->Options[i].Emotes[0]._Delay; + data << pGossip->Options[i].Emotes[0]._Emote; + + data << pGossip->Options[i].Emotes[1]._Delay; + data << pGossip->Options[i].Emotes[1]._Emote; + + data << pGossip->Options[i].Emotes[2]._Delay; + data << pGossip->Options[i].Emotes[2]._Emote; + } + } + pSession->SendPacket( &data ); + + sLog.outDebug( "WORLD: Sent SMSG_NPC_TEXT_UPDATE " ); +} + +void PlayerMenu::SendTalking( char const * title, char const * text ) +{ + WorldPacket data( SMSG_NPC_TEXT_UPDATE, 50 ); // guess size + data << uint32(0); + for(uint32 i = 0; i < 8; ++i) + { + data << float(0); + data << title; + data << text; + data << uint32(0); + data << uint32(0); + data << uint32(0); + data << uint32(0); + data << uint32(0); + data << uint32(0); + data << uint32(0); + } + + pSession->SendPacket( &data ); + + sLog.outDebug( "WORLD: Sent SMSG_NPC_TEXT_UPDATE " ); +} + +/*********************************************************/ +/*** QUEST SYSTEM ***/ +/*********************************************************/ + +QuestMenu::QuestMenu() +{ + m_qItems.reserve(16); // can be set for max from most often sizes to speedup push_back and less memory use +} + +QuestMenu::~QuestMenu() +{ + ClearMenu(); +} + +void QuestMenu::AddMenuItem( uint32 QuestId, uint8 Icon) +{ + Quest const* qinfo = objmgr.GetQuestTemplate(QuestId); + if (!qinfo) return; + + ASSERT( m_qItems.size() <= GOSSIP_MAX_MENU_ITEMS ); + + QuestMenuItem qItem; + + qItem.m_qId = QuestId; + qItem.m_qIcon = Icon; + + m_qItems.push_back(qItem); +} + +bool QuestMenu::HasItem( uint32 questid ) +{ + for (QuestMenuItemList::iterator i = m_qItems.begin(); i != m_qItems.end(); i++) + { + if(i->m_qId==questid) + { + return true; + } + } + return false; +} + +void QuestMenu::ClearMenu() +{ + m_qItems.clear(); +} + +void PlayerMenu::SendQuestGiverQuestList( QEmote eEmote, std::string Title, uint64 npcGUID ) +{ + WorldPacket data( SMSG_QUESTGIVER_QUEST_LIST, 100 ); // guess size + data << uint64(npcGUID); + data << Title; + data << uint32(eEmote._Delay ); // player emote + data << uint32(eEmote._Emote ); // NPC emote + data << uint8 ( pQuestMenu->MenuItemCount() ); + + for ( uint16 iI = 0; iI < pQuestMenu->MenuItemCount(); iI++ ) + { + QuestMenuItem qmi=pQuestMenu->GetItem(iI); + uint32 questID = qmi.m_qId; + Quest const *pQuest = objmgr.GetQuestTemplate(questID); + + std::string title = pQuest ? pQuest->GetTitle() : ""; + + int loc_idx = pSession->GetSessionDbLocaleIndex(); + if (loc_idx >= 0) + { + if(QuestLocale const *ql = objmgr.GetQuestLocale(questID)) + { + if (ql->Title.size() > loc_idx && !ql->Title[loc_idx].empty()) + title=ql->Title[loc_idx]; + } + } + + data << uint32(questID); + data << uint32(qmi.m_qIcon); + data << uint32(pQuest ? pQuest->GetQuestLevel() : 0); + data << title; + } + pSession->SendPacket( &data ); + //uint32 fqid=pQuestMenu->GetItem(0).m_qId; + //sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_QUEST_LIST NPC Guid=%u, questid-0=%u",npcGUID,fqid); +} + +void PlayerMenu::SendQuestGiverStatus( uint8 questStatus, uint64 npcGUID ) +{ + WorldPacket data( SMSG_QUESTGIVER_STATUS, 9 ); + data << uint64(npcGUID); + data << uint8(questStatus); + + pSession->SendPacket( &data ); + //sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_STATUS NPC Guid=%u, status=%u",GUID_LOPART(npcGUID),questStatus); +} + +void PlayerMenu::SendQuestGiverQuestDetails( Quest const *pQuest, uint64 npcGUID, bool ActivateAccept ) +{ + WorldPacket data(SMSG_QUESTGIVER_QUEST_DETAILS, 100); // guess size + + std::string Title = pQuest->GetTitle(); + std::string Details = pQuest->GetDetails(); + std::string Objectives = pQuest->GetObjectives(); + std::string EndText = pQuest->GetEndText(); + + int loc_idx = pSession->GetSessionDbLocaleIndex(); + if (loc_idx >= 0) + { + QuestLocale const *ql = objmgr.GetQuestLocale(pQuest->GetQuestId()); + if (ql) + { + if (ql->Title.size() > loc_idx && !ql->Title[loc_idx].empty()) + Title=ql->Title[loc_idx]; + if (ql->Details.size() > loc_idx && !ql->Details[loc_idx].empty()) + Details=ql->Details[loc_idx]; + if (ql->Objectives.size() > loc_idx && !ql->Objectives[loc_idx].empty()) + Objectives=ql->Objectives[loc_idx]; + if (ql->EndText.size() > loc_idx && !ql->EndText[loc_idx].empty()) + EndText=ql->EndText[loc_idx]; + } + } + + data << uint64(npcGUID); + data << uint32(pQuest->GetQuestId()); + data << Title << Details << Objectives; + data << uint32(ActivateAccept); + data << uint32(pQuest->GetSuggestedPlayers()); + + if (pQuest->HasFlag(QUEST_FLAGS_HIDDEN_REWARDS)) + { + data << uint32(0); // Rewarded chosen items hidden + data << uint32(0); // Rewarded items hidden + data << uint32(0); // Rewarded money hidden + } + else + { + ItemPrototype const* IProto; + + data << uint32(pQuest->GetRewChoiceItemsCount()); + for (uint32 i=0; i < QUEST_REWARD_CHOICES_COUNT; i++) + { + if ( !pQuest->RewChoiceItemId[i] ) continue; + data << uint32(pQuest->RewChoiceItemId[i]); + data << uint32(pQuest->RewChoiceItemCount[i]); + IProto = objmgr.GetItemPrototype(pQuest->RewChoiceItemId[i]); + if ( IProto ) + data << uint32(IProto->DisplayInfoID); + else + data << uint32( 0x00 ); + } + + data << uint32(pQuest->GetRewItemsCount()); + for (uint32 i=0; i < QUEST_REWARDS_COUNT; i++) + { + if ( !pQuest->RewItemId[i] ) continue; + data << uint32(pQuest->RewItemId[i]); + data << uint32(pQuest->RewItemCount[i]); + IProto = objmgr.GetItemPrototype(pQuest->RewItemId[i]); + if ( IProto ) + data << uint32(IProto->DisplayInfoID); + else + data << uint32(0); + } + data << uint32(pQuest->GetRewOrReqMoney()); + } + + data << uint32(0); // Honor points reward, not implemented + data << uint32(pQuest->GetRewSpell()); // reward spell, this spell will display (icon) (casted if RewSpellCast==0) + data << uint32(pQuest->GetRewSpellCast()); // casted spell + data << uint32(pQuest->GetCharTitleId()); // CharTitleId, new 2.4.0, player gets this title (id from CharTitles) + + data << uint32(QUEST_EMOTE_COUNT); + for (uint32 i=0; i < QUEST_EMOTE_COUNT; i++) + { + data << uint32(pQuest->DetailsEmote[i]); + data << uint32(0); // DetailsEmoteDelay + } + pSession->SendPacket( &data ); + + //sLog.outDebug("WORLD: Sent SMSG_QUESTGIVER_QUEST_DETAILS NPCGuid=%u, questid=%u",GUID_LOPART(npcGUID),pQuest->GetQuestId()); +} + +void PlayerMenu::SendQuestQueryResponse( Quest const *pQuest ) +{ + std::string Title,Details,Objectives,EndText; + std::string ObjectiveText[QUEST_OBJECTIVES_COUNT]; + Title = pQuest->GetTitle(); + Details = pQuest->GetDetails(); + Objectives = pQuest->GetObjectives(); + EndText = pQuest->GetEndText(); + for (int i=0;iObjectiveText[i]; + + int loc_idx = pSession->GetSessionDbLocaleIndex(); + if (loc_idx >= 0) + { + QuestLocale const *ql = objmgr.GetQuestLocale(pQuest->GetQuestId()); + if (ql) + { + if (ql->Title.size() > loc_idx && !ql->Title[loc_idx].empty()) + Title=ql->Title[loc_idx]; + if (ql->Details.size() > loc_idx && !ql->Details[loc_idx].empty()) + Details=ql->Details[loc_idx]; + if (ql->Objectives.size() > loc_idx && !ql->Objectives[loc_idx].empty()) + Objectives=ql->Objectives[loc_idx]; + if (ql->EndText.size() > loc_idx && !ql->EndText[loc_idx].empty()) + EndText=ql->EndText[loc_idx]; + + for (int i=0;iObjectiveText[i].size() > loc_idx && !ql->ObjectiveText[i][loc_idx].empty()) + ObjectiveText[i]=ql->ObjectiveText[i][loc_idx]; + } + } + + WorldPacket data( SMSG_QUEST_QUERY_RESPONSE, 100 ); // guess size + + data << uint32(pQuest->GetQuestId()); + data << uint32(pQuest->GetMinLevel()); // not MinLevel. Accepted values: 0, 1 or 2 Possible theory for future dev: 0==cannot in quest log, 1==can in quest log session only(removed on log out), 2==can in quest log always (save to db) + data << uint32(pQuest->GetQuestLevel()); // may be 0 + data << uint32(pQuest->GetZoneOrSort()); // zone or sort to display in quest log + + data << uint32(pQuest->GetType()); + data << uint32(pQuest->GetSuggestedPlayers()); + + data << uint32(pQuest->GetRepObjectiveFaction()); // shown in quest log as part of quest objective + data << uint32(pQuest->GetRepObjectiveValue()); // shown in quest log as part of quest objective + + data << uint32(0); // RequiredOpositeRepFaction + data << uint32(0); // RequiredOpositeRepValue, required faction value with another (oposite) faction (objective) + + data << uint32(pQuest->GetNextQuestInChain()); // client will request this quest from NPC, if not 0 + + if (pQuest->HasFlag(QUEST_FLAGS_HIDDEN_REWARDS)) + data << uint32(0); // Hide money rewarded + else + data << uint32(pQuest->GetRewOrReqMoney()); + + data << uint32(pQuest->GetRewMoneyMaxLevel()); // used in XP calculation at client + data << uint32(pQuest->GetRewSpell()); // reward spell, this spell will display (icon) (casted if RewSpellCast==0) + data << uint32(pQuest->GetRewSpellCast()); // casted spell + + data << uint32(0); // Honor points reward, not implemented + data << uint32(pQuest->GetSrcItemId()); + data << uint32(pQuest->GetFlags() & 0xFFFF); + data << uint32(pQuest->GetCharTitleId()); // CharTitleId, new 2.4.0, player gets this title (id from CharTitles) + + int iI; + + if (pQuest->HasFlag(QUEST_FLAGS_HIDDEN_REWARDS)) + { + for (iI = 0; iI < QUEST_REWARDS_COUNT; iI++) + data << uint32(0) << uint32(0); + for (iI = 0; iI < QUEST_REWARD_CHOICES_COUNT; iI++) + data << uint32(0) << uint32(0); + } + else + { + for (iI = 0; iI < QUEST_REWARDS_COUNT; iI++) + { + data << uint32(pQuest->RewItemId[iI]); + data << uint32(pQuest->RewItemCount[iI]); + } + for (iI = 0; iI < QUEST_REWARD_CHOICES_COUNT; iI++) + { + data << uint32(pQuest->RewChoiceItemId[iI]); + data << uint32(pQuest->RewChoiceItemCount[iI]); + } + } + + data << pQuest->GetPointMapId(); + data << pQuest->GetPointX(); + data << pQuest->GetPointY(); + data << pQuest->GetPointOpt(); + + data << Title; + data << Objectives; + data << Details; + data << EndText; + + for (iI = 0; iI < QUEST_OBJECTIVES_COUNT; iI++) + { + if (pQuest->ReqCreatureOrGOId[iI] < 0) + { + // client expected gameobject template id in form (id|0x80000000) + data << uint32((pQuest->ReqCreatureOrGOId[iI]*(-1))|0x80000000); + } + else + { + data << uint32(pQuest->ReqCreatureOrGOId[iI]); + } + data << uint32(pQuest->ReqCreatureOrGOCount[iI]); + data << uint32(pQuest->ReqItemId[iI]); + data << uint32(pQuest->ReqItemCount[iI]); + } + + for (iI = 0; iI < QUEST_OBJECTIVES_COUNT; iI++) + data << ObjectiveText[iI]; + + pSession->SendPacket( &data ); + //sLog.outDebug( "WORLD: Sent SMSG_QUEST_QUERY_RESPONSE questid=%u",pQuest->GetQuestId() ); +} + +void PlayerMenu::SendQuestGiverOfferReward( Quest const* pQuest, uint64 npcGUID, bool EnbleNext ) +{ + std::string Title = pQuest->GetTitle(); + std::string OfferRewardText = pQuest->GetOfferRewardText(); + + int loc_idx = pSession->GetSessionDbLocaleIndex(); + if (loc_idx >= 0) + { + QuestLocale const *ql = objmgr.GetQuestLocale(pQuest->GetQuestId()); + if (ql) + { + if (ql->Title.size() > loc_idx && !ql->Title[loc_idx].empty()) + Title=ql->Title[loc_idx]; + if (ql->OfferRewardText.size() > loc_idx && !ql->OfferRewardText[loc_idx].empty()) + OfferRewardText=ql->OfferRewardText[loc_idx]; + } + } + + WorldPacket data( SMSG_QUESTGIVER_OFFER_REWARD, 50 ); // guess size + + data << npcGUID; + data << pQuest->GetQuestId(); + data << Title; + data << OfferRewardText; + + data << uint32( EnbleNext ); + data << uint32(0); // unk + + uint32 EmoteCount = 0; + for (uint32 i = 0; i < QUEST_EMOTE_COUNT; i++) + { + if(pQuest->OfferRewardEmote[i] <= 0) + break; + ++EmoteCount; + } + + data << EmoteCount; // Emote Count + for (uint32 i = 0; i < EmoteCount; i++) + { + data << uint32(0); // Delay Emote + data << pQuest->OfferRewardEmote[i]; + } + + ItemPrototype const *pItem; + + data << uint32(pQuest->GetRewChoiceItemsCount()); + for (uint32 i=0; i < pQuest->GetRewChoiceItemsCount(); i++) + { + pItem = objmgr.GetItemPrototype( pQuest->RewChoiceItemId[i] ); + + data << uint32(pQuest->RewChoiceItemId[i]); + data << uint32(pQuest->RewChoiceItemCount[i]); + + if ( pItem ) + data << uint32(pItem->DisplayInfoID); + else + data << uint32(0); + } + + data << uint32(pQuest->GetRewItemsCount()); + for (uint16 i=0; i < pQuest->GetRewItemsCount(); i++) + { + pItem = objmgr.GetItemPrototype(pQuest->RewItemId[i]); + data << uint32(pQuest->RewItemId[i]); + data << uint32(pQuest->RewItemCount[i]); + + if ( pItem ) + data << uint32(pItem->DisplayInfoID); + else + data << uint32(0); + } + + data << uint32(pQuest->GetRewOrReqMoney()); + data << uint32(0x00); // new 2.3.0. Honor points + data << uint32(0x08); // unused by client? + data << uint32(pQuest->GetRewSpell()); // reward spell, this spell will display (icon) (casted if RewSpellCast==0) + data << uint32(pQuest->GetRewSpellCast()); // casted spell + data << uint32(0); // Honor points reward, not implemented + pSession->SendPacket( &data ); + //sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_OFFER_REWARD NPCGuid=%u, questid=%u",GUID_LOPART(npcGUID),pQuest->GetQuestId() ); +} + +void PlayerMenu::SendQuestGiverRequestItems( Quest const *pQuest, uint64 npcGUID, bool Completable, bool CloseOnCancel ) +{ + // We can always call to RequestItems, but this packet only goes out if there are actually + // items. Otherwise, we'll skip straight to the OfferReward + + // We may wish a better check, perhaps checking the real quest requirements + if (pQuest->GetRequestItemsText().empty()) + { + SendQuestGiverOfferReward(pQuest, npcGUID, true); + return; + } + + std::string Title,RequestItemsText; + Title = pQuest->GetTitle(); + RequestItemsText = pQuest->GetRequestItemsText(); + + int loc_idx = pSession->GetSessionDbLocaleIndex(); + if (loc_idx >= 0) + { + QuestLocale const *ql = objmgr.GetQuestLocale(pQuest->GetQuestId()); + if (ql) + { + if (ql->Title.size() > loc_idx && !ql->Title[loc_idx].empty()) + Title=ql->Title[loc_idx]; + if (ql->RequestItemsText.size() > loc_idx && !ql->RequestItemsText[loc_idx].empty()) + RequestItemsText=ql->RequestItemsText[loc_idx]; + } + } + + WorldPacket data( SMSG_QUESTGIVER_REQUEST_ITEMS, 50 ); // guess size + data << npcGUID; + data << pQuest->GetQuestId(); + data << Title; + data << RequestItemsText; + + data << uint32(0x00); // unknown + + if(Completable) + data << pQuest->GetCompleteEmote(); + else + data << pQuest->GetIncompleteEmote(); + + // Close Window after cancel + if (CloseOnCancel) + data << uint32(0x01); + else + data << uint32(0x00); + + data << uint32(0x00); // unknown + + // Required Money + data << uint32(pQuest->GetRewOrReqMoney() < 0 ? -pQuest->GetRewOrReqMoney() : 0); + + data << uint32( pQuest->GetReqItemsCount() ); + ItemPrototype const *pItem; + for (int i = 0; i < QUEST_OBJECTIVES_COUNT; i++) + { + if ( !pQuest->ReqItemId[i] ) continue; + pItem = objmgr.GetItemPrototype(pQuest->ReqItemId[i]); + data << uint32(pQuest->ReqItemId[i]); + data << uint32(pQuest->ReqItemCount[i]); + + if ( pItem ) + data << uint32(pItem->DisplayInfoID); + else + data << uint32(0); + } + + if ( !Completable ) + data << uint32(0x00); + else + data << uint32(0x03); + + data << uint32(0x04) << uint32(0x08) << uint32(0x10); + + pSession->SendPacket( &data ); + //sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_REQUEST_ITEMS NPCGuid=%u, questid=%u",GUID_LOPART(npcGUID),pQuest->GetQuestId() ); +} diff --git a/src/game/GossipDef.h b/src/game/GossipDef.h new file mode 100644 index 00000000000..aacf7a8fcb8 --- /dev/null +++ b/src/game/GossipDef.h @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOSSERVER_GOSSIP_H +#define MANGOSSERVER_GOSSIP_H + +#include "Common.h" +#include "QuestDef.h" +#include "NPCHandler.h" + +class WorldSession; + +#define GOSSIP_MAX_MENU_ITEMS 64 // client supported items unknown, but provided number must be enough +#define DEFAULT_GOSSIP_MESSAGE 0xffffff + +//POI defines +enum Poi_Icon +{ + ICON_POI_0 = 0, // Grey ? + ICON_POI_1 = 1, // Red ? + ICON_POI_2 = 2, // Blue ? + ICON_POI_BWTOMB = 3, // Blue and White Tomb Stone + ICON_POI_HOUSE = 4, // House + ICON_POI_TOWER = 5, // Tower + ICON_POI_REDFLAG = 6, // Red Flag with Yellow ! + ICON_POI_TOMB = 7, // Tomb Stone + ICON_POI_BWTOWER = 8, // Blue and White Tower + ICON_POI_REDTOWER = 9, // Red Tower + ICON_POI_BLUETOWER = 10, // Blue Tower + ICON_POI_RWTOWER = 11, // Red and White Tower + ICON_POI_REDTOMB = 12, // Red Tomb Stone + ICON_POI_RWTOMB = 13, // Red and White Tomb Stone + ICON_POI_BLUETOMB = 14, // Blue Tomb Stone + ICON_POI_NOTHING = 15, // NOTHING + ICON_POI_16 = 16, // Red ? + ICON_POI_17 = 17, // Grey ? + ICON_POI_18 = 18, // Blue ? + ICON_POI_19 = 19, // Red and White ? + ICON_POI_20 = 20, // Red ? + ICON_POI_GREYLOGS = 21, // Grey Wood Logs + ICON_POI_BWLOGS = 22, // Blue and White Wood Logs + ICON_POI_BLUELOGS = 23, // Blue Wood Logs + ICON_POI_RWLOGS = 24, // Red and White Wood Logs + ICON_POI_REDLOGS = 25, // Red Wood Logs + ICON_POI_26 = 26, // Grey ? + ICON_POI_27 = 27, // Blue and White ? + ICON_POI_28 = 28, // Blue ? + ICON_POI_29 = 29, // Red and White ? + ICON_POI_30 = 30, // Red ? + ICON_POI_GREYHOUSE = 31, // Grey House + ICON_POI_BWHOUSE = 32, // Blue and White House + ICON_POI_BLUEHOUSE = 33, // Blue House + ICON_POI_RWHOUSE = 34, // Red and White House + ICON_POI_REDHOUSE = 35, // Red House + ICON_POI_GREYHORSE = 36, // Grey Horse + ICON_POI_BWHORSE = 37, // Blue and White Horse + ICON_POI_BLUEHORSE = 38, // Blue Horse + ICON_POI_RWHORSE = 39, // Red and White Horse + ICON_POI_REDHORSE = 40 // Red Horse +}; + +struct GossipMenuItem +{ + uint8 m_gIcon; + bool m_gCoded; + std::string m_gMessage; + uint32 m_gSender; + uint32 m_gAction; + std::string m_gBoxMessage; + uint32 m_gBoxMoney; +}; + +typedef std::vector GossipMenuItemList; + +struct QuestMenuItem +{ + uint32 m_qId; + uint8 m_qIcon; +}; + +typedef std::vector QuestMenuItemList; + +class MANGOS_DLL_SPEC GossipMenu +{ + public: + GossipMenu(); + ~GossipMenu(); + + void AddMenuItem(uint8 Icon, std::string Message, bool Coded = false); + void AddMenuItem(uint8 Icon, std::string Message, uint32 dtSender, uint32 dtAction, std::string BoxMessage, uint32 BoxMoney, bool Coded = false); + + // for using from scripts, don't must be inlined + void AddMenuItem(uint8 Icon, char const* Message, bool Coded = false); + void AddMenuItem(uint8 Icon, char const* Message, uint32 dtSender, uint32 dtAction, char const* BoxMessage, uint32 BoxMoney, bool Coded = false); + + unsigned int MenuItemCount() + { + return m_gItems.size(); + } + + GossipMenuItem const& GetItem( unsigned int Id ) + { + return m_gItems[ Id ]; + } + + uint32 MenuItemSender( unsigned int ItemId ); + uint32 MenuItemAction( unsigned int ItemId ); + bool MenuItemCoded( unsigned int ItemId ); + + void ClearMenu(); + + protected: + GossipMenuItemList m_gItems; +}; + +class QuestMenu +{ + public: + QuestMenu(); + ~QuestMenu(); + + void AddMenuItem( uint32 QuestId, uint8 Icon); + void ClearMenu(); + + uint8 MenuItemCount() + { + return m_qItems.size(); + } + bool HasItem( uint32 questid ); + + QuestMenuItem const& GetItem( uint16 Id ) + { + return m_qItems[ Id ]; + } + + protected: + QuestMenuItemList m_qItems; +}; + +class MANGOS_DLL_SPEC PlayerMenu +{ + private: + GossipMenu* pGossipMenu; + QuestMenu* pQuestMenu; + WorldSession* pSession; + + public: + PlayerMenu( WorldSession *Session ); + ~PlayerMenu(); + + GossipMenu* GetGossipMenu() { return pGossipMenu; } + QuestMenu* GetQuestMenu() { return pQuestMenu; } + + void ClearMenus(); + uint32 GossipOptionSender( unsigned int Selection ); + uint32 GossipOptionAction( unsigned int Selection ); + bool GossipOptionCoded( unsigned int Selection ); + + void SendGossipMenu( uint32 TitleTextId, uint64 npcGUID ); + void CloseGossip(); + void SendPointOfInterest( float X, float Y, uint32 Icon, uint32 Flags, uint32 Data, const char * locName ); + void SendTalking( uint32 textID ); + void SendTalking( char const * title, char const * text ); + + /*********************************************************/ + /*** QUEST SYSTEM ***/ + /*********************************************************/ + void SendQuestGiverStatus( uint8 questStatus, uint64 npcGUID ); + + void SendQuestGiverQuestList( QEmote eEmote, std::string Title, uint64 npcGUID ); + + void SendQuestQueryResponse ( Quest const *pQuest ); + void SendQuestGiverQuestDetails( Quest const *pQuest, uint64 npcGUID, bool ActivateAccept); + + void SendQuestGiverOfferReward( Quest const* pQuest, uint64 npcGUID, bool EnbleNext ); + void SendQuestGiverRequestItems( Quest const *pQuest, uint64 npcGUID, bool Completable, bool CloseOnCancel ); +}; +#endif diff --git a/src/game/GridDefines.h b/src/game/GridDefines.h new file mode 100644 index 00000000000..d6287fa495c --- /dev/null +++ b/src/game/GridDefines.h @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_GRIDDEFINES_H +#define MANGOS_GRIDDEFINES_H + +#include "Common.h" +#include "GameSystem/NGrid.h" +#include + +// Forward class definitions +class Corpse; +class Creature; +class DynamicObject; +class GameObject; +class Pet; +class Player; + +#define MAX_NUMBER_OF_GRIDS 64 + +#define SIZE_OF_GRIDS 533.33333f +#define CENTER_GRID_ID (MAX_NUMBER_OF_GRIDS/2) + +#define CENTER_GRID_OFFSET (SIZE_OF_GRIDS/2) + +#define MIN_GRID_DELAY MINUTE*1000 +#define MIN_MAP_UPDATE_DELAY 50 + +#define MAX_NUMBER_OF_CELLS 8 +#define SIZE_OF_GRID_CELL (SIZE_OF_GRIDS/MAX_NUMBER_OF_CELLS) + +#define CENTER_GRID_CELL_ID 256 +#define CENTER_GRID_CELL_OFFSET (SIZE_OF_GRID_CELL/2) + +#define TOTAL_NUMBER_OF_CELLS_PER_MAP (MAX_NUMBER_OF_GRIDS*MAX_NUMBER_OF_CELLS) + +#define MAP_RESOLUTION 256 + +#define MAP_SIZE (SIZE_OF_GRIDS*MAX_NUMBER_OF_GRIDS) +#define MAP_HALFSIZE (MAP_SIZE/2) + +// Creature used instead pet to simplify *::Visit templates (not required duplicate code for Creature->Pet case) +typedef TYPELIST_3(Player, Creature/*pets*/, Corpse/*resurrectable*/) AllWorldObjectTypes; +typedef TYPELIST_4(GameObject, Creature/*except pets*/, DynamicObject, Corpse/*Bones*/) AllGridObjectTypes; + +typedef GridRefManager CorpseMapType; +typedef GridRefManager CreatureMapType; +typedef GridRefManager DynamicObjectMapType; +typedef GridRefManager GameObjectMapType; +typedef GridRefManager PlayerMapType; + +typedef Grid GridType; +typedef NGrid<8, Player, AllWorldObjectTypes, AllGridObjectTypes> NGridType; + +typedef TypeMapContainer GridTypeMapContainer; +typedef TypeMapContainer WorldTypeMapContainer; + +template +struct MANGOS_DLL_DECL CoordPair +{ + CoordPair(uint32 x=0, uint32 y=0) : x_coord(x), y_coord(y) {} + CoordPair(const CoordPair &obj) : x_coord(obj.x_coord), y_coord(obj.y_coord) {} + bool operator==(const CoordPair &obj) const { return (obj.x_coord == x_coord && obj.y_coord == y_coord); } + bool operator!=(const CoordPair &obj) const { return !operator==(obj); } + CoordPair& operator=(const CoordPair &obj) + { + x_coord = obj.x_coord; + y_coord = obj.y_coord; + return *this; + } + + void operator<<(const uint32 val) + { + if( x_coord >= val ) + x_coord -= val; + } + + void operator>>(const uint32 val) + { + if( x_coord+val < LIMIT ) + x_coord += val; + } + + void operator-=(const uint32 val) + { + if( y_coord >= val ) + y_coord -= val; + } + + void operator+=(const uint32 val) + { + if( y_coord+val < LIMIT ) + y_coord += val; + } + + uint32 x_coord; + uint32 y_coord; +}; + +typedef CoordPair GridPair; +typedef CoordPair CellPair; + +namespace MaNGOS +{ + template + inline RET_TYPE Compute(float x, float y, float center_offset, float size) + { + // calculate and store temporary values in double format for having same result as same mySQL calculations + double x_offset = (double(x) - center_offset)/size; + double y_offset = (double(y) - center_offset)/size; + + int x_val = int(x_offset+CENTER_VAL + 0.5); + int y_val = int(y_offset+CENTER_VAL + 0.5); + return RET_TYPE(x_val, y_val); + } + + inline GridPair ComputeGridPair(float x, float y) + { + return Compute(x, y, CENTER_GRID_OFFSET, SIZE_OF_GRIDS); + } + + inline CellPair ComputeCellPair(float x, float y) + { + return Compute(x, y, CENTER_GRID_CELL_OFFSET, SIZE_OF_GRID_CELL); + } + + inline void NormalizeMapCoord(float &c) + { + if(c > MAP_HALFSIZE - 0.5) + c = MAP_HALFSIZE - 0.5; + else if(c < -(MAP_HALFSIZE - 0.5)) + c = -(MAP_HALFSIZE - 0.5); + } + + inline bool IsValidMapCoord(float c) + { + return finite(c) && (std::fabs(c) <= MAP_HALFSIZE - 0.5); + } + + inline bool IsValidMapCoord(float x, float y) + { + return IsValidMapCoord(x) && IsValidMapCoord(y); + } + + inline bool IsValidMapCoord(float x, float y, float z) + { + return IsValidMapCoord(x,y) && finite(z); + } + + inline bool IsValidMapCoord(float x, float y, float z, float o) + { + return IsValidMapCoord(x,y,z) && finite(o); + } +} +#endif diff --git a/src/game/GridNotifiers.cpp b/src/game/GridNotifiers.cpp new file mode 100644 index 00000000000..5348b7f61b0 --- /dev/null +++ b/src/game/GridNotifiers.cpp @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "GridNotifiers.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "UpdateData.h" +#include "Item.h" +#include "Map.h" +#include "MapManager.h" +#include "Transports.h" +#include "ObjectAccessor.h" + +using namespace MaNGOS; + +void +MaNGOS::PlayerNotifier::Visit(PlayerMapType &m) +{ + for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + { + if( iter->getSource() == &i_player ) + continue; + + iter->getSource()->UpdateVisibilityOf(&i_player); + i_player.UpdateVisibilityOf(iter->getSource()); + } +} + +void +VisibleChangesNotifier::Visit(PlayerMapType &m) +{ + for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + { + if(iter->getSource() == &i_object) + continue; + + iter->getSource()->UpdateVisibilityOf(&i_object); + } +} + +void +VisibleNotifier::Visit(PlayerMapType &m) +{ + for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + { + if( iter->getSource() == &i_player ) + continue; + + iter->getSource()->UpdateVisibilityOf(&i_player); + i_player.UpdateVisibilityOf(iter->getSource(),i_data,i_data_updates,i_visibleNow); + i_clientGUIDs.erase(iter->getSource()->GetGUID()); + } +} + +void +VisibleNotifier::Notify() +{ + // at this moment i_clientGUIDs have guids that not iterate at grid level checks + // but exist one case when this possible and object not out of range: transports + if(Transport* transport = i_player.GetTransport()) + { + for(Transport::PlayerSet::const_iterator itr = transport->GetPassengers().begin();itr!=transport->GetPassengers().end();++itr) + { + if(i_clientGUIDs.find((*itr)->GetGUID())!=i_clientGUIDs.end()) + { + (*itr)->UpdateVisibilityOf(&i_player); + i_player.UpdateVisibilityOf((*itr),i_data,i_data_updates,i_visibleNow); + i_clientGUIDs.erase((*itr)->GetGUID()); + } + } + } + + // generate outOfRange for not iterate objects + i_data.AddOutOfRangeGUID(i_clientGUIDs); + for(Player::ClientGUIDs::iterator itr = i_clientGUIDs.begin();itr!=i_clientGUIDs.end();++itr) + { + i_player.m_clientGUIDs.erase(*itr); + + #ifdef MANGOS_DEBUG + if((sLog.getLogFilter() & LOG_FILTER_VISIBILITY_CHANGES)==0) + sLog.outDebug("Object %u (Type: %u) is out of range (no in active cells set) now for player %u",GUID_LOPART(*itr),GuidHigh2TypeId(GUID_HIPART(*itr)),i_player.GetGUIDLow()); + #endif + } + + // send update to other players (except player updates that already sent using SendUpdateToPlayer) + for(UpdateDataMapType::iterator iter = i_data_updates.begin(); iter != i_data_updates.end(); ++iter) + { + if(iter->first==&i_player) + continue; + + WorldPacket packet; + iter->second.BuildPacket(&packet); + iter->first->GetSession()->SendPacket(&packet); + } + + if( i_data.HasData() ) + { + // send create/outofrange packet to player (except player create updates that already sent using SendUpdateToPlayer) + WorldPacket packet; + i_data.BuildPacket(&packet); + i_player.GetSession()->SendPacket(&packet); + + // send out of range to other players if need + std::set const& oor = i_data.GetOutOfRangeGUIDs(); + for(std::set::const_iterator iter = oor.begin(); iter != oor.end(); ++iter) + { + if(!IS_PLAYER_GUID(*iter)) + continue; + + Player* plr = ObjectAccessor::GetPlayer(i_player,*iter); + if(plr) + plr->UpdateVisibilityOf(&i_player); + } + } + + // Now do operations that required done at object visibility change to visible + + // target aura duration for caster show only if target exist at caster client + // send data at target visibility change (adding to client) + for(std::set::const_iterator vItr = i_visibleNow.begin(); vItr != i_visibleNow.end(); ++vItr) + if((*vItr)!=&i_player && (*vItr)->isType(TYPEMASK_UNIT)) + i_player.SendAuraDurationsForTarget((Unit*)(*vItr)); +} + +void +MessageDeliverer::Visit(PlayerMapType &m) +{ + for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + { + if( i_toSelf || iter->getSource() != &i_player) + { + if(WorldSession* session = iter->getSource()->GetSession()) + session->SendPacket(i_message); + } + } +} + +void +ObjectMessageDeliverer::Visit(PlayerMapType &m) +{ + for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + { + if(WorldSession* session = iter->getSource()->GetSession()) + session->SendPacket(i_message); + } +} + +void +MessageDistDeliverer::Visit(PlayerMapType &m) +{ + for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + { + if( (i_toSelf || iter->getSource() != &i_player ) && + (!i_ownTeamOnly || iter->getSource()->GetTeam() == i_player.GetTeam() ) && + (!i_dist || iter->getSource()->GetDistance(&i_player) <= i_dist) ) + { + if(WorldSession* session = iter->getSource()->GetSession()) + session->SendPacket(i_message); + } + } +} + +void +ObjectMessageDistDeliverer::Visit(PlayerMapType &m) +{ + for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + { + if( !i_dist || iter->getSource()->GetDistance(&i_object) <= i_dist ) + { + if(WorldSession* session = iter->getSource()->GetSession()) + session->SendPacket(i_message); + } + } +} + +template void +ObjectUpdater::Visit(GridRefManager &m) +{ + for(typename GridRefManager::iterator iter = m.begin(); iter != m.end(); ++iter) + { + iter->getSource()->Update(i_timeDiff); + } +} + +template void ObjectUpdater::Visit(GameObjectMapType &); +template void ObjectUpdater::Visit(DynamicObjectMapType &); + +bool CannibalizeObjectCheck::operator()(Corpse* u) +{ + // ignore bones + if(u->GetType()==CORPSE_BONES) + return false; + + Player* owner = ObjectAccessor::FindPlayer(u->GetOwnerGUID()); + + if( !owner || i_funit->IsFriendlyTo(owner)) + return false; + + if(i_funit->IsWithinDistInMap(u, i_range) ) + return true; + + return false; +} diff --git a/src/game/GridNotifiers.h b/src/game/GridNotifiers.h new file mode 100644 index 00000000000..215cf9152e6 --- /dev/null +++ b/src/game/GridNotifiers.h @@ -0,0 +1,812 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_GRIDNOTIFIERS_H +#define MANGOS_GRIDNOTIFIERS_H + +#include "ObjectGridLoader.h" +#include "ByteBuffer.h" +#include "UpdateData.h" +#include + +#include "Corpse.h" +#include "Object.h" +#include "DynamicObject.h" +#include "GameObject.h" +#include "Player.h" +#include "Unit.h" + +class Player; +//class Map; + +namespace MaNGOS +{ + + struct MANGOS_DLL_DECL PlayerNotifier + { + explicit PlayerNotifier(Player &pl) : i_player(pl) {} + void Visit(PlayerMapType &); + template void Visit(GridRefManager &) {} + Player &i_player; + }; + + struct MANGOS_DLL_DECL VisibleNotifier + { + Player &i_player; + UpdateData i_data; + UpdateDataMapType i_data_updates; + Player::ClientGUIDs i_clientGUIDs; + std::set i_visibleNow; + + explicit VisibleNotifier(Player &player) : i_player(player),i_clientGUIDs(player.m_clientGUIDs) {} + template void Visit(GridRefManager &m); + void Visit(PlayerMapType &); + void Notify(void); + }; + + struct MANGOS_DLL_DECL VisibleChangesNotifier + { + WorldObject &i_object; + + explicit VisibleChangesNotifier(WorldObject &object) : i_object(object) {} + template void Visit(GridRefManager &) {} + void Visit(PlayerMapType &); + }; + + struct MANGOS_DLL_DECL GridUpdater + { + GridType &i_grid; + uint32 i_timeDiff; + GridUpdater(GridType &grid, uint32 diff) : i_grid(grid), i_timeDiff(diff) {} + + template void updateObjects(GridRefManager &m) + { + for(typename GridRefManager::iterator iter = m.begin(); iter != m.end(); ++iter) + iter->getSource()->Update(i_timeDiff); + } + + void Visit(PlayerMapType &m) { updateObjects(m); } + void Visit(CreatureMapType &m){ updateObjects(m); } + void Visit(GameObjectMapType &m) { updateObjects(m); } + void Visit(DynamicObjectMapType &m) { updateObjects(m); } + void Visit(CorpseMapType &m) { updateObjects(m); } + }; + + struct MANGOS_DLL_DECL MessageDeliverer + { + Player &i_player; + WorldPacket *i_message; + bool i_toSelf; + MessageDeliverer(Player &pl, WorldPacket *msg, bool to_self) : i_player(pl), i_message(msg), i_toSelf(to_self) {} + void Visit(PlayerMapType &m); + template void Visit(GridRefManager &) {} + }; + + struct MANGOS_DLL_DECL ObjectMessageDeliverer + { + WorldPacket *i_message; + explicit ObjectMessageDeliverer(WorldPacket *msg) : i_message(msg) {} + void Visit(PlayerMapType &m); + template void Visit(GridRefManager &) {} + }; + + struct MANGOS_DLL_DECL MessageDistDeliverer + { + Player &i_player; + WorldPacket *i_message; + bool i_toSelf; + bool i_ownTeamOnly; + float i_dist; + MessageDistDeliverer(Player &pl, WorldPacket *msg, bool to_self, bool ownTeamOnly, float dist) : i_player(pl), i_message(msg), i_toSelf(to_self), i_ownTeamOnly(ownTeamOnly), i_dist(dist) {} + void Visit(PlayerMapType &m); + template void Visit(GridRefManager &) {} + }; + + struct MANGOS_DLL_DECL ObjectMessageDistDeliverer + { + WorldObject &i_object; + WorldPacket *i_message; + float i_dist; + ObjectMessageDistDeliverer(WorldObject &obj, WorldPacket *msg, float dist) : i_object(obj), i_message(msg), i_dist(dist) {} + void Visit(PlayerMapType &m); + template void Visit(GridRefManager &) {} + }; + + struct MANGOS_DLL_DECL ObjectUpdater + { + uint32 i_timeDiff; + explicit ObjectUpdater(const uint32 &diff) : i_timeDiff(diff) {} + template void Visit(GridRefManager &m); + void Visit(PlayerMapType &) {} + void Visit(CorpseMapType &) {} + void Visit(CreatureMapType &); + }; + + template + struct MANGOS_DLL_DECL ObjectAccessorNotifier + { + T *& i_object; + + uint64 i_id; + ObjectAccessorNotifier(T * &obj, uint64 id) : i_object(obj), i_id(id) + { + i_object = NULL; + } + + void Visit(GridRefManager &m ) + { + if( i_object == NULL ) + { + GridRefManager *iter = m.find(i_id); + if( iter != m.end() ) + { + assert( iter->second != NULL ); + i_object = iter->second; + } + } + } + + template void Visit(GridRefManager &) {} + }; + + struct MANGOS_DLL_DECL PlayerRelocationNotifier + { + Player &i_player; + PlayerRelocationNotifier(Player &pl) : i_player(pl) {} + template void Visit(GridRefManager &) {} + void Visit(PlayerMapType &); + void Visit(CreatureMapType &); + }; + + struct MANGOS_DLL_DECL CreatureRelocationNotifier + { + Creature &i_creature; + CreatureRelocationNotifier(Creature &c) : i_creature(c) {} + template void Visit(GridRefManager &) {} + #ifdef WIN32 + template<> void Visit(PlayerMapType &); + #endif + }; + + struct MANGOS_DLL_DECL DynamicObjectUpdater + { + DynamicObject &i_dynobject; + Unit* i_check; + DynamicObjectUpdater(DynamicObject &dynobject, Unit* caster) : i_dynobject(dynobject) + { + i_check = caster; + Unit* owner = i_check->GetOwner(); + if(owner) + i_check = owner; + } + + template inline void Visit(GridRefManager &) {} + #ifdef WIN32 + template<> inline void Visit(PlayerMapType &); + template<> inline void Visit(CreatureMapType &); + #endif + + void VisitHelper(Unit* target); + }; + + // SEARCHERS & LIST SEARCHERS & WORKERS + + // WorldObject searchers & workers + + template + struct MANGOS_DLL_DECL WorldObjectSearcher + { + WorldObject* &i_object; + Check &i_check; + + WorldObjectSearcher(WorldObject* & result, Check& check) : i_object(result),i_check(check) {} + + void Visit(GameObjectMapType &m); + void Visit(PlayerMapType &m); + void Visit(CreatureMapType &m); + void Visit(CorpseMapType &m); + void Visit(DynamicObjectMapType &m); + + template void Visit(GridRefManager &) {} + }; + + template + struct MANGOS_DLL_DECL WorldObjectListSearcher + { + std::list &i_objects; + Check& i_check; + + WorldObjectListSearcher(std::list &objects, Check & check) : i_objects(objects),i_check(check) {} + + void Visit(PlayerMapType &m); + void Visit(CreatureMapType &m); + void Visit(CorpseMapType &m); + void Visit(GameObjectMapType &m); + void Visit(DynamicObjectMapType &m); + + template void Visit(GridRefManager &) {} + }; + + template + struct MANGOS_DLL_DECL WorldObjectWorker + { + Do const& i_do; + + explicit WorldObjectWorker(Do const& _do) : i_do(_do) {} + + void Visit(GameObjectMapType &m) + { + for(GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + i_do(itr->getSource()); + } + + void Visit(PlayerMapType &m) + { + for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + i_do(itr->getSource()); + } + void Visit(CreatureMapType &m) + { + for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + i_do(itr->getSource()); + } + + void Visit(CorpseMapType &m) + { + for(CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + i_do(itr->getSource()); + } + + void Visit(DynamicObjectMapType &m) + { + for(DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + i_do(itr->getSource()); + } + + template void Visit(GridRefManager &) {} + }; + + // Gameobject searchers + + template + struct MANGOS_DLL_DECL GameObjectSearcher + { + GameObject* &i_object; + Check &i_check; + + GameObjectSearcher(GameObject* & result, Check& check) : i_object(result),i_check(check) {} + + void Visit(GameObjectMapType &m); + + template void Visit(GridRefManager &) {} + }; + + // Last accepted by Check GO if any (Check can change requirements at each call) + template + struct MANGOS_DLL_DECL GameObjectLastSearcher + { + GameObject* &i_object; + Check& i_check; + + GameObjectLastSearcher(GameObject* & result, Check& check) : i_object(result),i_check(check) {} + + void Visit(GameObjectMapType &m); + + template void Visit(GridRefManager &) {} + }; + + template + struct MANGOS_DLL_DECL GameObjectListSearcher + { + std::list &i_objects; + Check& i_check; + + GameObjectListSearcher(std::list &objects, Check & check) : i_objects(objects),i_check(check) {} + + void Visit(GameObjectMapType &m); + + template void Visit(GridRefManager &) {} + }; + + // Unit searchers + + // First accepted by Check Unit if any + template + struct MANGOS_DLL_DECL UnitSearcher + { + Unit* &i_object; + Check & i_check; + + UnitSearcher(Unit* & result, Check & check) : i_object(result),i_check(check) {} + + void Visit(CreatureMapType &m); + void Visit(PlayerMapType &m); + + template void Visit(GridRefManager &) {} + }; + + // Last accepted by Check Unit if any (Check can change requirements at each call) + template + struct MANGOS_DLL_DECL UnitLastSearcher + { + Unit* &i_object; + Check & i_check; + + UnitLastSearcher(Unit* & result, Check & check) : i_object(result),i_check(check) {} + + void Visit(CreatureMapType &m); + void Visit(PlayerMapType &m); + + template void Visit(GridRefManager &) {} + }; + + // All accepted by Check units if any + template + struct MANGOS_DLL_DECL UnitListSearcher + { + std::list &i_objects; + Check& i_check; + + UnitListSearcher(std::list &objects, Check & check) : i_objects(objects),i_check(check) {} + + void Visit(PlayerMapType &m); + void Visit(CreatureMapType &m); + + template void Visit(GridRefManager &) {} + }; + + // Creature searchers + + template + struct MANGOS_DLL_DECL CreatureSearcher + { + Creature* &i_object; + Check & i_check; + + CreatureSearcher(Creature* & result, Check & check) : i_object(result),i_check(check) {} + + void Visit(CreatureMapType &m); + + template void Visit(GridRefManager &) {} + }; + + // Last accepted by Check Creature if any (Check can change requirements at each call) + template + struct MANGOS_DLL_DECL CreatureLastSearcher + { + Creature* &i_object; + Check & i_check; + + CreatureLastSearcher(Creature* & result, Check & check) : i_object(result),i_check(check) {} + + void Visit(CreatureMapType &m); + + template void Visit(GridRefManager &) {} + }; + + template + struct MANGOS_DLL_DECL CreatureListSearcher + { + std::list &i_objects; + Check& i_check; + + CreatureListSearcher(std::list &objects, Check & check) : i_objects(objects),i_check(check) {} + + void Visit(CreatureMapType &m); + + template void Visit(GridRefManager &) {} + }; + + // Player searchers + + template + struct MANGOS_DLL_DECL PlayerSearcher + { + Player* &i_object; + Check & i_check; + + PlayerSearcher(Player* & result, Check & check) : i_object(result),i_check(check) {} + + void Visit(PlayerMapType &m); + + template void Visit(GridRefManager &) {} + }; + + template + struct MANGOS_DLL_DECL PlayerWorker + { + Do& i_do; + + explicit PlayerWorker(Do& _do) : i_do(_do) {} + + void Visit(PlayerMapType &m) + { + for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + i_do(itr->getSource()); + } + + template void Visit(GridRefManager &) {} + }; + + // CHECKS && DO classes + + // WorldObject check classes + class CannibalizeObjectCheck + { + public: + CannibalizeObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {} + bool operator()(Player* u) + { + if( i_funit->IsFriendlyTo(u) || u->isAlive() || u->isInFlight() ) + return false; + + if(i_funit->IsWithinDistInMap(u, i_range) ) + return true; + + return false; + } + bool operator()(Corpse* u); + bool operator()(Creature* u) + { + if( i_funit->IsFriendlyTo(u) || u->isAlive() || u->isInFlight() || + (u->GetCreatureTypeMask() & CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD)==0) + return false; + + if(i_funit->IsWithinDistInMap(u, i_range) ) + return true; + + return false; + } + template bool operator()(NOT_INTERESTED* u) { return false; } + private: + Unit* const i_funit; + float i_range; + }; + + // WorldObject do classes + + class RespawnDo + { + public: + RespawnDo() {} + void operator()(Creature* u) const { u->Respawn(); } + void operator()(GameObject* u) const { u->Respawn(); } + void operator()(WorldObject*) const {} + void operator()(Corpse*) const {} + }; + + // GameObject checks + + class GameObjectFocusCheck + { + public: + GameObjectFocusCheck(Unit const* unit,uint32 focusId) : i_unit(unit), i_focusId(focusId) {} + bool operator()(GameObject* go) const + { + if(go->GetGOInfo()->type != GAMEOBJECT_TYPE_SPELL_FOCUS) + return false; + + if(go->GetGOInfo()->spellFocus.focusId != i_focusId) + return false; + + float dist = go->GetGOInfo()->spellFocus.dist; + + return go->IsWithinDistInMap(i_unit, dist); + } + private: + Unit const* i_unit; + uint32 i_focusId; + }; + + // Find the nearest Fishing hole and return true only if source object is in range of hole + class NearestGameObjectFishingHole + { + public: + NearestGameObjectFishingHole(WorldObject const& obj, float range) : i_obj(obj), i_range(range) {} + bool operator()(GameObject* go) + { + if(go->GetGOInfo()->type == GAMEOBJECT_TYPE_FISHINGHOLE && go->isSpawned() && i_obj.IsWithinDistInMap(go, i_range) && i_obj.IsWithinDistInMap(go, go->GetGOInfo()->fishinghole.radius)) + { + i_range = i_obj.GetDistance(go); + return true; + } + return false; + } + float GetLastRange() const { return i_range; } + private: + WorldObject const& i_obj; + float i_range; + + // prevent clone + NearestGameObjectFishingHole(NearestGameObjectFishingHole const&); + }; + + // Success at unit in range, range update for next check (this can be use with GameobjectLastSearcher to find nearest GO) + class NearestGameObjectEntryInObjectRangeCheck + { + public: + NearestGameObjectEntryInObjectRangeCheck(WorldObject const& obj,uint32 entry, float range) : i_obj(obj), i_entry(entry), i_range(range) {} + bool operator()(GameObject* go) + { + if(go->GetEntry() == i_entry && i_obj.IsWithinDistInMap(go, i_range)) + { + i_range = i_obj.GetDistance(go); // use found GO range as new range limit for next check + return true; + } + return false; + } + float GetLastRange() const { return i_range; } + private: + WorldObject const& i_obj; + uint32 i_entry; + float i_range; + + // prevent clone this object + NearestGameObjectEntryInObjectRangeCheck(NearestGameObjectEntryInObjectRangeCheck const&); + }; + + class GameObjectWithDbGUIDCheck + { + public: + GameObjectWithDbGUIDCheck(WorldObject const& obj,uint32 db_guid) : i_obj(obj), i_db_guid(db_guid) {} + bool operator()(GameObject const* go) const + { + return go->GetDBTableGUIDLow() == i_db_guid; + } + private: + WorldObject const& i_obj; + uint32 i_db_guid; + }; + + // Unit checks + + class AnyUnfriendlyUnitInObjectRangeCheck + { + public: + AnyUnfriendlyUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {} + bool operator()(Unit* u) + { + if(u->isAlive() && i_obj->IsWithinDistInMap(u, i_range) && !i_funit->IsFriendlyTo(u)) + return true; + else + return false; + } + private: + WorldObject const* i_obj; + Unit const* i_funit; + float i_range; + }; + + class AnyFriendlyUnitInObjectRangeCheck + { + public: + AnyFriendlyUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {} + bool operator()(Unit* u) + { + if(u->isAlive() && i_obj->IsWithinDistInMap(u, i_range) && i_funit->IsFriendlyTo(u)) + return true; + else + return false; + } + private: + WorldObject const* i_obj; + Unit const* i_funit; + float i_range; + }; + + class AnyUnitInObjectRangeCheck + { + public: + AnyUnitInObjectRangeCheck(WorldObject const* obj, float range) : i_obj(obj), i_range(range) {} + bool operator()(Unit* u) + { + if(u->isAlive() && i_obj->IsWithinDistInMap(u, i_range)) + return true; + + return false; + } + private: + WorldObject const* i_obj; + float i_range; + }; + + // Success at unit in range, range update for next check (this can be use with UnitLastSearcher to find nearest unit) + class NearestAttackableUnitInObjectRangeCheck + { + public: + NearestAttackableUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {} + bool operator()(Unit* u) + { + if( u->isTargetableForAttack() && i_obj->IsWithinDistInMap(u, i_range) && + !i_funit->IsFriendlyTo(u) && u->isVisibleForOrDetect(i_funit,false) ) + { + i_range = i_obj->GetDistance(u); // use found unit range as new range limit for next check + return true; + } + + return false; + } + private: + WorldObject const* i_obj; + Unit const* i_funit; + float i_range; + + // prevent clone this object + NearestAttackableUnitInObjectRangeCheck(NearestAttackableUnitInObjectRangeCheck const&); + }; + + class AnyAoETargetUnitInObjectRangeCheck + { + public: + AnyAoETargetUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) + : i_obj(obj), i_funit(funit), i_range(range) + { + Unit const* check = i_funit; + Unit const* owner = i_funit->GetOwner(); + if(owner) + check = owner; + i_targetForPlayer = ( check->GetTypeId()==TYPEID_PLAYER ); + } + bool operator()(Unit* u) + { + // Check contains checks for: live, non-selectable, non-attackable flags, flight check and GM check, ignore totems + if (!u->isTargetableForAttack()) + return false; + if(u->GetTypeId()==TYPEID_UNIT && ((Creature*)u)->isTotem()) + return false; + + if(( i_targetForPlayer ? !i_funit->IsFriendlyTo(u) : i_funit->IsHostileTo(u) )&& i_obj->IsWithinDistInMap(u, i_range)) + return true; + + return false; + } + private: + bool i_targetForPlayer; + WorldObject const* i_obj; + Unit const* i_funit; + float i_range; + }; + + struct AnyDeadUnitCheck + { + bool operator()(Unit* u) { return !u->isAlive(); } + }; + + struct AnyStealthedCheck + { + bool operator()(Unit* u) { return u->GetVisibility()==VISIBILITY_GROUP_STEALTH; } + }; + + // Creature checks + + class InAttackDistanceFromAnyHostileCreatureCheck + { + public: + explicit InAttackDistanceFromAnyHostileCreatureCheck(Unit* funit) : i_funit(funit) {} + bool operator()(Creature* u) + { + if(u->isAlive() && u->IsHostileTo(i_funit) && i_funit->IsWithinDistInMap(u, u->GetAttackDistance(i_funit))) + return true; + + return false; + } + private: + Unit* const i_funit; + }; + + class AnyAssistCreatureInRangeCheck + { + public: + AnyAssistCreatureInRangeCheck(Unit* funit, Unit* enemy, float range) + : i_funit(funit), i_enemy(enemy), i_range(range) + { + } + bool operator()(Creature* u) + { + if(u == i_funit) + return false; + + // we don't need help from zombies :) + if( !u->isAlive() ) + return false; + + // skip fighting creature + if( u->isInCombat() ) + return false; + + // only from same creature faction + if(u->getFaction() != i_funit->getFaction() ) + return false; + + // only free creature + if( u->GetCharmerOrOwnerGUID() ) + return false; + + // too far + if( !i_funit->IsWithinDistInMap(u, i_range) ) + return false; + + // skip non hostile to caster enemy creatures + if( !u->IsHostileTo(i_enemy) ) + return false; + + // only if see assisted creature + if(!u->IsWithinLOSInMap(i_funit) ) + return false; + + return true; + } + private: + Unit* const i_funit; + Unit* const i_enemy; + float i_range; + }; + + // Success at unit in range, range update for next check (this can be use with CreatureLastSearcher to find nearest creature) + class NearestCreatureEntryWithLiveStateInObjectRangeCheck + { + public: + NearestCreatureEntryWithLiveStateInObjectRangeCheck(WorldObject const& obj,uint32 entry, bool alive, float range) + : i_obj(obj), i_entry(entry), i_alive(alive), i_range(range) {} + + bool operator()(Creature* u) + { + if(u->GetEntry() == i_entry && u->isAlive()==i_alive && i_obj.IsWithinDistInMap(u, i_range)) + { + i_range = i_obj.GetDistance(u); // use found unit range as new range limit for next check + return true; + } + return false; + } + float GetLastRange() const { return i_range; } + private: + WorldObject const& i_obj; + uint32 i_entry; + bool i_alive; + float i_range; + + // prevent clone this object + NearestCreatureEntryWithLiveStateInObjectRangeCheck(NearestCreatureEntryWithLiveStateInObjectRangeCheck const&); + }; + + class AnyPlayerInObjectRangeCheck + { + public: + AnyPlayerInObjectRangeCheck(WorldObject const* obj, float range) : i_obj(obj), i_range(range) {} + bool operator()(Player* u) + { + if(u->isAlive() && i_obj->IsWithinDistInMap(u, i_range)) + return true; + + return false; + } + private: + WorldObject const* i_obj; + float i_range; + }; + + #ifndef WIN32 + template<> void PlayerRelocationNotifier::Visit(CreatureMapType &); + template<> void PlayerRelocationNotifier::Visit(PlayerMapType &); + template<> void CreatureRelocationNotifier::Visit(PlayerMapType &); + template<> void CreatureRelocationNotifier::Visit(CreatureMapType &); + template<> inline void DynamicObjectUpdater::Visit(CreatureMapType &); + template<> inline void DynamicObjectUpdater::Visit(PlayerMapType &); + #endif +} +#endif diff --git a/src/game/GridNotifiersImpl.h b/src/game/GridNotifiersImpl.h new file mode 100644 index 00000000000..9dd422a3ad3 --- /dev/null +++ b/src/game/GridNotifiersImpl.h @@ -0,0 +1,489 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_GRIDNOTIFIERSIMPL_H +#define MANGOS_GRIDNOTIFIERSIMPL_H + +#include "GridNotifiers.h" +#include "WorldPacket.h" +#include "Corpse.h" +#include "Player.h" +#include "UpdateData.h" +#include "CreatureAI.h" +#include "SpellAuras.h" + +template +inline void +MaNGOS::VisibleNotifier::Visit(GridRefManager &m) +{ + for(typename GridRefManager::iterator iter = m.begin(); iter != m.end(); ++iter) + { + i_player.UpdateVisibilityOf(iter->getSource(),i_data,i_data_updates,i_visibleNow); + i_clientGUIDs.erase(iter->getSource()->GetGUID()); + } +} + +inline void +MaNGOS::ObjectUpdater::Visit(CreatureMapType &m) +{ + for(CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + if(!iter->getSource()->isSpiritService()) + iter->getSource()->Update(i_timeDiff); +} + +inline void +MaNGOS::PlayerRelocationNotifier::Visit(PlayerMapType &m) +{ + for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + { + if(&i_player==iter->getSource()) + continue; + + // visibility for players updated by ObjectAccessor::UpdateVisibilityFor calls in appropriate places + + // Cancel Trade + if(i_player.GetTrader()==iter->getSource()) + // iteraction distance + if(!i_player.IsWithinDistInMap(iter->getSource(), 5)) + i_player.GetSession()->SendCancelTrade(); // will clode both side trade windows + } +} + +inline void PlayerCreatureRelocationWorker(Player* pl, Creature* c) +{ + // update creature visibility at player/creature move + pl->UpdateVisibilityOf(c); + + // Creature AI reaction + if(!c->hasUnitState(UNIT_STAT_CHASE | UNIT_STAT_SEARCHING | UNIT_STAT_FLEEING)) + { + if( c->AI() && c->AI()->IsVisible(pl) && !c->IsInEvadeMode() ) + c->AI()->MoveInLineOfSight(pl); + } +} + +inline void CreatureCreatureRelocationWorker(Creature* c1, Creature* c2) +{ + if(!c1->hasUnitState(UNIT_STAT_CHASE | UNIT_STAT_SEARCHING | UNIT_STAT_FLEEING)) + { + if( c1->AI() && c1->AI()->IsVisible(c2) && !c1->IsInEvadeMode() ) + c1->AI()->MoveInLineOfSight(c2); + } + + if(!c2->hasUnitState(UNIT_STAT_CHASE | UNIT_STAT_SEARCHING | UNIT_STAT_FLEEING)) + { + if( c2->AI() && c2->AI()->IsVisible(c1) && !c2->IsInEvadeMode() ) + c2->AI()->MoveInLineOfSight(c1); + } +} + +inline void +MaNGOS::PlayerRelocationNotifier::Visit(CreatureMapType &m) +{ + if(!i_player.isAlive() || i_player.isInFlight()) + return; + + for(CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + if( iter->getSource()->isAlive()) + PlayerCreatureRelocationWorker(&i_player,iter->getSource()); +} + +template<> +inline void +MaNGOS::CreatureRelocationNotifier::Visit(PlayerMapType &m) +{ + if(!i_creature.isAlive()) + return; + + for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + if( iter->getSource()->isAlive() && !iter->getSource()->isInFlight()) + PlayerCreatureRelocationWorker(iter->getSource(), &i_creature); +} + +template<> +inline void +MaNGOS::CreatureRelocationNotifier::Visit(CreatureMapType &m) +{ + if(!i_creature.isAlive()) + return; + + for(CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + { + Creature* c = iter->getSource(); + if( c != &i_creature && c->isAlive()) + CreatureCreatureRelocationWorker(c, &i_creature); + } +} + +inline void MaNGOS::DynamicObjectUpdater::VisitHelper(Unit* target) +{ + if(!target->isAlive() || target->isInFlight() ) + return; + + if(target->GetTypeId()==TYPEID_UNIT && ((Creature*)target)->isTotem()) + return; + + if (!i_dynobject.IsWithinDistInMap(target, i_dynobject.GetRadius())) + return; + + //Check targets for not_selectable unit flag and remove + if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE)) + return; + + // Evade target + if( target->GetTypeId()==TYPEID_UNIT && ((Creature*)target)->IsInEvadeMode() ) + return; + + //Check player targets and remove if in GM mode or GM invisibility (for not self casting case) + if( target->GetTypeId()==TYPEID_PLAYER && target != i_check && (((Player*)target)->isGameMaster() || ((Player*)target)->GetVisibility()==VISIBILITY_OFF) ) + return; + + if( i_check->GetTypeId()==TYPEID_PLAYER ) + { + if (i_check->IsFriendlyTo( target )) + return; + } + else + { + if (!i_check->IsHostileTo( target )) + return; + } + + if (i_dynobject.IsAffecting(target)) + return; + + SpellEntry const *spellInfo = sSpellStore.LookupEntry(i_dynobject.GetSpellId()); + uint32 eff_index = i_dynobject.GetEffIndex(); + // Check target immune to spell or aura + if (target->IsImmunedToSpell(spellInfo) || target->IsImmunedToSpellEffect(spellInfo->Effect[eff_index], spellInfo->EffectMechanic[eff_index])) + return; + // Apply PersistentAreaAura on target + PersistentAreaAura* Aur = new PersistentAreaAura(spellInfo, eff_index, NULL, target, i_dynobject.GetCaster()); + target->AddAura(Aur); + i_dynobject.AddAffected(target); +} + +template<> +inline void +MaNGOS::DynamicObjectUpdater::Visit(CreatureMapType &m) +{ + for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + VisitHelper(itr->getSource()); +} + +template<> +inline void +MaNGOS::DynamicObjectUpdater::Visit(PlayerMapType &m) +{ + for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + VisitHelper(itr->getSource()); +} + +// SEARCHERS & LIST SEARCHERS & WORKERS + +// WorldObject searchers & workers + +template +void MaNGOS::WorldObjectSearcher::Visit(GameObjectMapType &m) +{ + // already found + if(i_object) + return; + + for(GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if(i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void MaNGOS::WorldObjectSearcher::Visit(PlayerMapType &m) +{ + // already found + if(i_object) + return; + + for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if(i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void MaNGOS::WorldObjectSearcher::Visit(CreatureMapType &m) +{ + // already found + if(i_object) + return; + + for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if(i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void MaNGOS::WorldObjectSearcher::Visit(CorpseMapType &m) +{ + // already found + if(i_object) + return; + + for(CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if(i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void MaNGOS::WorldObjectSearcher::Visit(DynamicObjectMapType &m) +{ + // already found + if(i_object) + return; + + for(DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if(i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void MaNGOS::WorldObjectListSearcher::Visit(PlayerMapType &m) +{ + for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if(i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +template +void MaNGOS::WorldObjectListSearcher::Visit(CreatureMapType &m) +{ + for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if(i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +template +void MaNGOS::WorldObjectListSearcher::Visit(CorpseMapType &m) +{ + for(CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if(i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +template +void MaNGOS::WorldObjectListSearcher::Visit(GameObjectMapType &m) +{ + for(GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if(i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +template +void MaNGOS::WorldObjectListSearcher::Visit(DynamicObjectMapType &m) +{ + for(DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if(i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +// Gameobject searchers + +template +void MaNGOS::GameObjectSearcher::Visit(GameObjectMapType &m) +{ + // already found + if(i_object) + return; + + for(GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if(i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void MaNGOS::GameObjectLastSearcher::Visit(GameObjectMapType &m) +{ + for(GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if(i_check(itr->getSource())) + i_object = itr->getSource(); + } +} + +template +void MaNGOS::GameObjectListSearcher::Visit(GameObjectMapType &m) +{ + for(GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if(i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +// Unit searchers + +template +void MaNGOS::UnitSearcher::Visit(CreatureMapType &m) +{ + // already found + if(i_object) + return; + + for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if(i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void MaNGOS::UnitSearcher::Visit(PlayerMapType &m) +{ + // already found + if(i_object) + return; + + for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if(i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void MaNGOS::UnitLastSearcher::Visit(CreatureMapType &m) +{ + for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if(i_check(itr->getSource())) + i_object = itr->getSource(); + } +} + +template +void MaNGOS::UnitLastSearcher::Visit(PlayerMapType &m) +{ + for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if(i_check(itr->getSource())) + i_object = itr->getSource(); + } +} + +template +void MaNGOS::UnitListSearcher::Visit(PlayerMapType &m) +{ + for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if(i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +template +void MaNGOS::UnitListSearcher::Visit(CreatureMapType &m) +{ + for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if(i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +// Creature searchers + +template +void MaNGOS::CreatureSearcher::Visit(CreatureMapType &m) +{ + // already found + if(i_object) + return; + + for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if(i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void MaNGOS::CreatureLastSearcher::Visit(CreatureMapType &m) +{ + for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if(i_check(itr->getSource())) + i_object = itr->getSource(); + } +} + +template +void MaNGOS::CreatureListSearcher::Visit(CreatureMapType &m) +{ + for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if(i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +template +void MaNGOS::PlayerSearcher::Visit(PlayerMapType &m) +{ + // already found + if(i_object) + return; + + for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if(i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +#endif // MANGOS_GRIDNOTIFIERSIMPL_H diff --git a/src/game/GridStates.cpp b/src/game/GridStates.cpp new file mode 100644 index 00000000000..0c4557fb131 --- /dev/null +++ b/src/game/GridStates.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "GridStates.h" +#include "GridNotifiers.h" +#include "ObjectAccessor.h" +#include "GameSystem/Grid.h" +#include "Log.h" + +void +InvalidState::Update(Map &, NGridType &, GridInfo &, const uint32 &/*x*/, const uint32 &/*y*/, const uint32 &) const +{ +} + +void +ActiveState::Update(Map &m, NGridType &grid, GridInfo & info, const uint32 &x, const uint32 &y, const uint32 &t_diff) const +{ + // Only check grid activity every (grid_expiry/10) ms, because it's really useless to do it every cycle + info.UpdateTimeTracker(t_diff); + if( info.getTimeTracker().Passed() ) + { + if( grid.ActiveObjectsInGrid() == 0 && !ObjectAccessor::Instance().PlayersNearGrid(x, y, m.GetId(), m.GetInstanceId()) ) + { + ObjectGridStoper stoper(grid); + stoper.StopN(); + grid.SetGridState(GRID_STATE_IDLE); + } + else + { + m.ResetGridExpiry(grid, 0.1f); + } + } +} + +void +IdleState::Update(Map &m, NGridType &grid, GridInfo &info, const uint32 &x, const uint32 &y, const uint32 &) const +{ + m.ResetGridExpiry(grid); + grid.SetGridState(GRID_STATE_REMOVAL); + sLog.outDebug("Grid[%u,%u] on map %u moved to IDLE state", x, y, m.GetId()); +} + +void +RemovalState::Update(Map &m, NGridType &grid, GridInfo &info, const uint32 &x, const uint32 &y, const uint32 &t_diff) const +{ + if(info.getUnloadFlag()) + { + info.UpdateTimeTracker(t_diff); + if( info.getTimeTracker().Passed() ) + { + if( !m.UnloadGrid(x, y, false) ) + { + sLog.outDebug("Grid[%u,%u] for map %u differed unloading due to players nearby", x, y, m.GetId()); + m.ResetGridExpiry(grid); + } + } + } +} diff --git a/src/game/GridStates.h b/src/game/GridStates.h new file mode 100644 index 00000000000..8a4e716ece4 --- /dev/null +++ b/src/game/GridStates.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_GRIDSTATES_H +#define MANGOS_GRIDSTATES_H + +#include "Map.h" + +class MANGOS_DLL_DECL GridState +{ + public: +#ifdef MANGOS_DEBUG +#define MAGIC_TESTVAL 0xFBE823BA + GridState() { i_Magic = MAGIC_TESTVAL; } + bool checkMagic() + { + if(i_Magic != MAGIC_TESTVAL) + { + sLog.outError("!!! GridState: Magic value gone !!!"); + return false; + } + return true; + } + void setMagic() { i_Magic = MAGIC_TESTVAL; } + unsigned int i_Magic; +#endif + virtual void Update(Map &, NGridType&, GridInfo &, const uint32 &x, const uint32 &y, const uint32 &t_diff) const = 0; +}; + +class MANGOS_DLL_DECL InvalidState : public GridState +{ + public: + + void Update(Map &, NGridType &, GridInfo &, const uint32 &x, const uint32 &y, const uint32 &t_diff) const; +}; + +class MANGOS_DLL_DECL ActiveState : public GridState +{ + public: + + void Update(Map &, NGridType &, GridInfo &, const uint32 &x, const uint32 &y, const uint32 &t_diff) const; +}; + +class MANGOS_DLL_DECL IdleState : public GridState +{ + public: + + void Update(Map &, NGridType &, GridInfo &, const uint32 &x, const uint32 &y, const uint32 &t_diff) const; +}; + +class MANGOS_DLL_DECL RemovalState : public GridState +{ + public: + + void Update(Map &, NGridType &, GridInfo &, const uint32 &x, const uint32 &y, const uint32 &t_diff) const; +}; +#endif diff --git a/src/game/Group.cpp b/src/game/Group.cpp new file mode 100644 index 00000000000..e74a3778e87 --- /dev/null +++ b/src/game/Group.cpp @@ -0,0 +1,1406 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Opcodes.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Player.h" +#include "World.h" +#include "ObjectMgr.h" +#include "Group.h" +#include "ObjectAccessor.h" +#include "BattleGround.h" +#include "MapManager.h" +#include "InstanceSaveMgr.h" +#include "MapInstanced.h" +#include "Util.h" + +Group::Group() +{ + m_leaderGuid = 0; + m_mainTank = 0; + m_mainAssistant = 0; + m_groupType = (GroupType)0; + m_bgGroup = NULL; + m_lootMethod = (LootMethod)0; + m_looterGuid = 0; + m_lootThreshold = ITEM_QUALITY_UNCOMMON; + + for(int i=0; iGetBgRaid(ALLIANCE) == this) m_bgGroup->SetBgRaid(ALLIANCE, NULL); + else if(m_bgGroup->GetBgRaid(HORDE) == this) m_bgGroup->SetBgRaid(HORDE, NULL); + else sLog.outError("Group::~Group: battleground group is not linked to the correct battleground."); + } + Rolls::iterator itr; + while(!RollId.empty()) + { + itr = RollId.begin(); + Roll *r = *itr; + RollId.erase(itr); + delete(r); + } + + // it is undefined whether objectmgr (which stores the groups) or instancesavemgr + // will be unloaded first so we must be prepared for both cases + // this may unload some instance saves + for(uint8 i = 0; i < TOTAL_DIFFICULTIES; i++) + for(BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end(); ++itr) + itr->second.save->RemoveGroup(this); +} + +bool Group::Create(const uint64 &guid, const char * name) +{ + m_leaderGuid = guid; + m_leaderName = name; + + m_groupType = isBGGroup() ? GROUPTYPE_RAID : GROUPTYPE_NORMAL; + m_lootMethod = GROUP_LOOT; + m_lootThreshold = ITEM_QUALITY_UNCOMMON; + m_looterGuid = guid; + + m_difficulty = DIFFICULTY_NORMAL; + if(!isBGGroup()) + { + Player *leader = objmgr.GetPlayer(guid); + if(leader) m_difficulty = leader->GetDifficulty(); + + Player::ConvertInstancesToGroup(leader, this, guid); + + // store group in database + CharacterDatabase.BeginTransaction(); + CharacterDatabase.PExecute("DELETE FROM groups WHERE leaderGuid ='%u'", GUID_LOPART(m_leaderGuid)); + CharacterDatabase.PExecute("DELETE FROM group_member WHERE leaderGuid ='%u'", GUID_LOPART(m_leaderGuid)); + CharacterDatabase.PExecute("INSERT INTO groups(leaderGuid,mainTank,mainAssistant,lootMethod,looterGuid,lootThreshold,icon1,icon2,icon3,icon4,icon5,icon6,icon7,icon8,isRaid,difficulty) " + "VALUES('%u','%u','%u','%u','%u','%u','" I64FMTD "','" I64FMTD "','" I64FMTD "','" I64FMTD "','" I64FMTD "','" I64FMTD "','" I64FMTD "','" I64FMTD "','%u','%u')", + GUID_LOPART(m_leaderGuid), GUID_LOPART(m_mainTank), GUID_LOPART(m_mainAssistant), uint32(m_lootMethod), + GUID_LOPART(m_looterGuid), uint32(m_lootThreshold), m_targetIcons[0], m_targetIcons[1], m_targetIcons[2], m_targetIcons[3], m_targetIcons[4], m_targetIcons[5], m_targetIcons[6], m_targetIcons[7], isRaidGroup(), m_difficulty); + } + + if(!AddMember(guid, name)) + return false; + + if(!isBGGroup()) CharacterDatabase.CommitTransaction(); + + return true; +} + +bool Group::LoadGroupFromDB(const uint64 &leaderGuid, QueryResult *result, bool loadMembers) +{ + if(isBGGroup()) + return false; + + bool external = true; + if(!result) + { + external = false; + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 + result = CharacterDatabase.PQuery("SELECT mainTank, mainAssistant, lootMethod, looterGuid, lootThreshold, icon1, icon2, icon3, icon4, icon5, icon6, icon7, icon8, isRaid, difficulty FROM groups WHERE leaderGuid ='%u'", GUID_LOPART(leaderGuid)); + if(!result) + return false; + } + + m_leaderGuid = leaderGuid; + + // group leader not exist + if(!objmgr.GetPlayerNameByGUID(m_leaderGuid, m_leaderName)) + { + if(!external) delete result; + return false; + } + + m_groupType = (*result)[13].GetBool() ? GROUPTYPE_RAID : GROUPTYPE_NORMAL; + m_difficulty = (*result)[14].GetUInt8(); + m_mainTank = (*result)[0].GetUInt64(); + m_mainAssistant = (*result)[1].GetUInt64(); + m_lootMethod = (LootMethod)(*result)[2].GetUInt8(); + m_looterGuid = MAKE_NEW_GUID((*result)[3].GetUInt32(), 0, HIGHGUID_PLAYER); + m_lootThreshold = (ItemQualities)(*result)[4].GetUInt16(); + + for(int i=0; iNextRow() ); + delete result; + // group too small + if(GetMembersCount() < 2) + return false; + } + + return true; +} + +bool Group::LoadMemberFromDB(uint32 guidLow, uint8 subgroup, bool assistant) +{ + MemberSlot member; + member.guid = MAKE_NEW_GUID(guidLow, 0, HIGHGUID_PLAYER); + + // skip non-existed member + if(!objmgr.GetPlayerNameByGUID(member.guid, member.name)) + return false; + + member.group = subgroup; + member.assistant = assistant; + m_memberSlots.push_back(member); + return true; +} + +bool Group::AddInvite(Player *player) +{ + if(!player || player->GetGroupInvite() || player->GetGroup()) + return false; + + RemoveInvite(player); + + m_invitees.insert(player->GetGUID()); + + player->SetGroupInvite(this); + + return true; +} + +bool Group::AddLeaderInvite(Player *player) +{ + if(!AddInvite(player)) + return false; + + m_leaderGuid = player->GetGUID(); + m_leaderName = player->GetName(); + return true; +} + +uint32 Group::RemoveInvite(Player *player) +{ + for(InvitesList::iterator itr=m_invitees.begin(); itr!=m_invitees.end(); ++itr) + { + if((*itr) == player->GetGUID()) + { + m_invitees.erase(itr); + break; + } + } + + player->SetGroupInvite(NULL); + return GetMembersCount(); +} + +void Group::RemoveAllInvites() +{ + for(InvitesList::iterator itr=m_invitees.begin(); itr!=m_invitees.end(); ++itr) + { + Player *invitee = objmgr.GetPlayer(*itr); + if(invitee) + invitee->SetGroupInvite(NULL); + } + m_invitees.clear(); +} + +bool Group::AddMember(const uint64 &guid, const char* name) +{ + if(!_addMember(guid, name)) + return false; + SendUpdate(); + + Player *player = objmgr.GetPlayer(guid); + if(player) + { + if(!IsLeader(player->GetGUID()) && !isBGGroup()) + { + // reset the new member's instances, unless he is currently in one of them + // including raid/heroic instances that they are not permanently bound to! + player->ResetInstances(INSTANCE_RESET_GROUP_JOIN); + + if(player->getLevel() >= LEVELREQUIREMENT_HEROIC && player->GetDifficulty() != GetDifficulty() ) + { + player->SetDifficulty(m_difficulty); + player->SendDungeonDifficulty(true); + } + } + player->SetGroupUpdateFlag(GROUP_UPDATE_FULL); + UpdatePlayerOutOfRange(player); + } + + return true; +} + +uint32 Group::RemoveMember(const uint64 &guid, const uint8 &method) +{ + // remove member and change leader (if need) only if strong more 2 members _before_ member remove + if(GetMembersCount() > (isBGGroup() ? 1 : 2)) // in BG group case allow 1 members group + { + bool leaderChanged = _removeMember(guid); + + Player *player = objmgr.GetPlayer( guid ); + if (player) + { + WorldPacket data; + + if(method == 1) + { + data.Initialize( SMSG_GROUP_UNINVITE, 0 ); + player->GetSession()->SendPacket( &data ); + } + + data.Initialize(SMSG_GROUP_LIST, 24); + data << uint64(0) << uint64(0) << uint64(0); + player->GetSession()->SendPacket(&data); + + _homebindIfInstance(player); + } + + if(leaderChanged) + { + WorldPacket data(SMSG_GROUP_SET_LEADER, (m_memberSlots.front().name.size()+1)); + data << m_memberSlots.front().name; + BroadcastPacket(&data); + } + + SendUpdate(); + } + // if group before remove <= 2 disband it + else + Disband(true); + + return m_memberSlots.size(); +} + +void Group::ChangeLeader(const uint64 &guid) +{ + member_citerator slot = _getMemberCSlot(guid); + + if(slot==m_memberSlots.end()) + return; + + _setLeader(guid); + + WorldPacket data(SMSG_GROUP_SET_LEADER, slot->name.size()+1); + data << slot->name; + BroadcastPacket(&data); + SendUpdate(); +} + +void Group::Disband(bool hideDestroy) +{ + Player *player; + + for(member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr) + { + player = objmgr.GetPlayer(citr->guid); + if(!player) + continue; + + player->SetGroup(NULL); + + if(!player->GetSession()) + continue; + + WorldPacket data; + if(!hideDestroy) + { + data.Initialize(SMSG_GROUP_DESTROYED, 0); + player->GetSession()->SendPacket(&data); + } + + data.Initialize(SMSG_GROUP_LIST, 24); + data << uint64(0) << uint64(0) << uint64(0); + player->GetSession()->SendPacket(&data); + + _homebindIfInstance(player); + } + RollId.clear(); + m_memberSlots.clear(); + + RemoveAllInvites(); + + if(!isBGGroup()) + { + CharacterDatabase.BeginTransaction(); + CharacterDatabase.PExecute("DELETE FROM groups WHERE leaderGuid='%u'", GUID_LOPART(m_leaderGuid)); + CharacterDatabase.PExecute("DELETE FROM group_member WHERE leaderGuid='%u'", GUID_LOPART(m_leaderGuid)); + CharacterDatabase.CommitTransaction(); + ResetInstances(INSTANCE_RESET_GROUP_DISBAND, NULL); + } + + m_leaderGuid = 0; + m_leaderName = ""; +} + +/*********************************************************/ +/*** LOOT SYSTEM ***/ +/*********************************************************/ + +void Group::SendLootStartRoll(uint32 CountDown, const Roll &r) +{ + WorldPacket data(SMSG_LOOT_START_ROLL, (8+4+4+4+4+4)); + data << uint64(r.itemGUID); // guid of rolled item + data << uint32(r.totalPlayersRolling); // maybe the number of players rolling for it??? + data << uint32(r.itemid); // the itemEntryId for the item that shall be rolled for + data << uint32(r.itemRandomSuffix); // randomSuffix + data << uint32(r.itemRandomPropId); // item random property ID + data << uint32(CountDown); // the countdown time to choose "need" or "greed" + + for (Roll::PlayerVote::const_iterator itr=r.playerVote.begin(); itr!=r.playerVote.end(); ++itr) + { + Player *p = objmgr.GetPlayer(itr->first); + if(!p || !p->GetSession()) + continue; + + if(itr->second != NOT_VALID) + p->GetSession()->SendPacket( &data ); + } +} + +void Group::SendLootRoll(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r) +{ + WorldPacket data(SMSG_LOOT_ROLL, (8+4+8+4+4+4+1+1)); + data << uint64(SourceGuid); // guid of the item rolled + data << uint32(0); // unknown, maybe amount of players + data << uint64(TargetGuid); + data << uint32(r.itemid); // the itemEntryId for the item that shall be rolled for + data << uint32(r.itemRandomSuffix); // randomSuffix + data << uint32(r.itemRandomPropId); // Item random property ID + data << uint8(RollNumber); // 0: "Need for: [item name]" > 127: "you passed on: [item name]" Roll number + data << uint8(RollType); // 0: "Need for: [item name]" 0: "You have selected need for [item name] 1: need roll 2: greed roll + data << uint8(0); // 2.4.0 + + for( Roll::PlayerVote::const_iterator itr=r.playerVote.begin(); itr!=r.playerVote.end(); ++itr) + { + Player *p = objmgr.GetPlayer(itr->first); + if(!p || !p->GetSession()) + continue; + + if(itr->second != NOT_VALID) + p->GetSession()->SendPacket( &data ); + } +} + +void Group::SendLootRollWon(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r) +{ + WorldPacket data(SMSG_LOOT_ROLL_WON, (8+4+4+4+4+8+1+1)); + data << uint64(SourceGuid); // guid of the item rolled + data << uint32(0); // unknown, maybe amount of players + data << uint32(r.itemid); // the itemEntryId for the item that shall be rolled for + data << uint32(r.itemRandomSuffix); // randomSuffix + data << uint32(r.itemRandomPropId); // Item random property + data << uint64(TargetGuid); // guid of the player who won. + data << uint8(RollNumber); // rollnumber realted to SMSG_LOOT_ROLL + data << uint8(RollType); // Rolltype related to SMSG_LOOT_ROLL + + for( Roll::PlayerVote::const_iterator itr=r.playerVote.begin(); itr!=r.playerVote.end(); ++itr) + { + Player *p = objmgr.GetPlayer(itr->first); + if(!p || !p->GetSession()) + continue; + + if(itr->second != NOT_VALID) + p->GetSession()->SendPacket( &data ); + } +} + +void Group::SendLootAllPassed(uint32 NumberOfPlayers, const Roll &r) +{ + WorldPacket data(SMSG_LOOT_ALL_PASSED, (8+4+4+4+4)); + data << uint64(r.itemGUID); // Guid of the item rolled + data << uint32(NumberOfPlayers); // The number of players rolling for it??? + data << uint32(r.itemid); // The itemEntryId for the item that shall be rolled for + data << uint32(r.itemRandomPropId); // Item random property ID + data << uint32(r.itemRandomSuffix); // Item random suffix ID + + for( Roll::PlayerVote::const_iterator itr=r.playerVote.begin(); itr!=r.playerVote.end(); ++itr) + { + Player *p = objmgr.GetPlayer(itr->first); + if(!p || !p->GetSession()) + continue; + + if(itr->second != NOT_VALID) + p->GetSession()->SendPacket( &data ); + } +} + +void Group::GroupLoot(uint64 playerGUID, Loot *loot, Creature *creature) +{ + std::vector::iterator i; + ItemPrototype const *item; + uint8 itemSlot = 0; + Player *player = objmgr.GetPlayer(playerGUID); + Group *group = player->GetGroup(); + + for (i=loot->items.begin(); i != loot->items.end(); ++i, ++itemSlot) + { + item = objmgr.GetItemPrototype(i->itemid); + if (!item) + { + //sLog.outDebug("Group::GroupLoot: missing item prototype for item with id: %d", i->itemid); + continue; + } + + //roll for over-threshold item if it's one-player loot + if (item->Quality >= uint32(m_lootThreshold) && !i->freeforall) + { + uint64 newitemGUID = MAKE_NEW_GUID(objmgr.GenerateLowGuid(HIGHGUID_ITEM),0,HIGHGUID_ITEM); + Roll* r=new Roll(newitemGUID,*i); + + //a vector is filled with only near party members + for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *member = itr->getSource(); + if(!member || !member->GetSession()) + continue; + if ( i->AllowedForPlayer(member) ) + { + if (member->GetDistance2d(creature) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE)) + { + r->playerVote[member->GetGUID()] = NOT_EMITED_YET; + ++r->totalPlayersRolling; + } + } + } + + r->setLoot(loot); + r->itemSlot = itemSlot; + + group->SendLootStartRoll(60000, *r); + + loot->items[itemSlot].is_blocked = true; + creature->m_groupLootTimer = 60000; + creature->lootingGroupLeaderGUID = GetLeaderGUID(); + + RollId.push_back(r); + } + else + i->is_underthreshold=1; + + } +} + +void Group::NeedBeforeGreed(uint64 playerGUID, Loot *loot, Creature *creature) +{ + ItemPrototype const *item; + Player *player = objmgr.GetPlayer(playerGUID); + Group *group = player->GetGroup(); + + uint8 itemSlot = 0; + for(std::vector::iterator i=loot->items.begin(); i != loot->items.end(); ++i, ++itemSlot) + { + item = objmgr.GetItemPrototype(i->itemid); + + //only roll for one-player items, not for ones everyone can get + if (item->Quality >= uint32(m_lootThreshold) && !i->freeforall) + { + uint64 newitemGUID = MAKE_NEW_GUID(objmgr.GenerateLowGuid(HIGHGUID_ITEM),0,HIGHGUID_ITEM); + Roll* r=new Roll(newitemGUID,*i); + + for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *playerToRoll = itr->getSource(); + if(!playerToRoll || !playerToRoll->GetSession()) + continue; + + if (playerToRoll->CanUseItem(item) && i->AllowedForPlayer(playerToRoll) ) + { + if (playerToRoll->GetDistance2d(creature) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE)) + { + r->playerVote[playerToRoll->GetGUID()] = NOT_EMITED_YET; + ++r->totalPlayersRolling; + } + } + } + + if (r->totalPlayersRolling > 0) + { + r->setLoot(loot); + r->itemSlot = itemSlot; + + group->SendLootStartRoll(60000, *r); + + loot->items[itemSlot].is_blocked = true; + + RollId.push_back(r); + } + else + { + delete r; + } + } + else + i->is_underthreshold=1; + } +} + +void Group::MasterLoot(uint64 playerGUID, Loot* /*loot*/, Creature *creature) +{ + Player *player = objmgr.GetPlayer(playerGUID); + if(!player) + return; + + sLog.outDebug("Group::MasterLoot (SMSG_LOOT_MASTER_LIST, 330) player = [%s].", player->GetName()); + + uint32 real_count = 0; + + WorldPacket data(SMSG_LOOT_MASTER_LIST, 330); + data << (uint8)GetMembersCount(); + + for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *looter = itr->getSource(); + if (!looter->IsInWorld()) + continue; + + if (looter->GetDistance2d(creature) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE)) + { + data << looter->GetGUID(); + ++real_count; + } + } + + data.put(0,real_count); + + for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *looter = itr->getSource(); + if (looter->GetDistance2d(creature) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE)) + looter->GetSession()->SendPacket(&data); + } +} + +void Group::CountRollVote(uint64 playerGUID, uint64 Guid, uint32 NumberOfPlayers, uint8 Choise) +{ + Rolls::iterator rollI = GetRoll(Guid); + if (rollI == RollId.end()) + return; + Roll* roll = *rollI; + + Roll::PlayerVote::iterator itr = roll->playerVote.find(playerGUID); + // this condition means that player joins to the party after roll begins + if (itr == roll->playerVote.end()) + return; + + if (roll->getLoot()) + if (roll->getLoot()->items.empty()) + return; + + switch (Choise) + { + case 0: //Player choose pass + { + SendLootRoll(0, playerGUID, 128, 128, *roll); + ++roll->totalPass; + itr->second = PASS; + } + break; + case 1: //player choose Need + { + SendLootRoll(0, playerGUID, 1, 1, *roll); + ++roll->totalNeed; + itr->second = NEED; + } + break; + case 2: //player choose Greed + { + SendLootRoll(0, playerGUID, 2, 2, *roll); + ++roll->totalGreed; + itr->second = GREED; + } + break; + } + if (roll->totalPass + roll->totalGreed + roll->totalNeed >= roll->totalPlayersRolling) + { + CountTheRoll(rollI, NumberOfPlayers); + } +} + +//called when roll timer expires +void Group::EndRoll() +{ + Rolls::iterator itr; + while(!RollId.empty()) + { + //need more testing here, if rolls disappear + itr = RollId.begin(); + CountTheRoll(itr, GetMembersCount()); //i don't have to edit player votes, who didn't vote ... he will pass + } +} + +void Group::CountTheRoll(Rolls::iterator rollI, uint32 NumberOfPlayers) +{ + Roll* roll = *rollI; + if(!roll->isValid()) // is loot already deleted ? + { + RollId.erase(rollI); + delete roll; + return; + } + //end of the roll + if (roll->totalNeed > 0) + { + if(!roll->playerVote.empty()) + { + uint8 maxresul = 0; + uint64 maxguid = (*roll->playerVote.begin()).first; + Player *player; + + for( Roll::PlayerVote::const_iterator itr=roll->playerVote.begin(); itr!=roll->playerVote.end(); ++itr) + { + if (itr->second != NEED) + continue; + + uint8 randomN = urand(1, 99); + SendLootRoll(0, itr->first, randomN, 1, *roll); + if (maxresul < randomN) + { + maxguid = itr->first; + maxresul = randomN; + } + } + SendLootRollWon(0, maxguid, maxresul, 1, *roll); + player = objmgr.GetPlayer(maxguid); + + if(player && player->GetSession()) + { + ItemPosCountVec dest; + LootItem *item = &(roll->getLoot()->items[roll->itemSlot]); + uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, roll->itemid, item->count ); + if ( msg == EQUIP_ERR_OK ) + { + item->is_looted = true; + roll->getLoot()->NotifyItemRemoved(roll->itemSlot); + --roll->getLoot()->unlootedCount; + player->StoreNewItem( dest, roll->itemid, true, item->randomPropertyId); + } + else + { + item->is_blocked = false; + player->SendEquipError( msg, NULL, NULL ); + } + } + } + } + else if (roll->totalGreed > 0) + { + if(!roll->playerVote.empty()) + { + uint8 maxresul = 0; + uint64 maxguid = (*roll->playerVote.begin()).first; + Player *player; + + Roll::PlayerVote::iterator itr; + for (itr=roll->playerVote.begin(); itr!=roll->playerVote.end(); ++itr) + { + if (itr->second != GREED) + continue; + + uint8 randomN = urand(1, 99); + SendLootRoll(0, itr->first, randomN, 2, *roll); + if (maxresul < randomN) + { + maxguid = itr->first; + maxresul = randomN; + } + } + SendLootRollWon(0, maxguid, maxresul, 2, *roll); + player = objmgr.GetPlayer(maxguid); + + if(player && player->GetSession()) + { + ItemPosCountVec dest; + LootItem *item = &(roll->getLoot()->items[roll->itemSlot]); + uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, roll->itemid, item->count ); + if ( msg == EQUIP_ERR_OK ) + { + item->is_looted = true; + roll->getLoot()->NotifyItemRemoved(roll->itemSlot); + --roll->getLoot()->unlootedCount; + player->StoreNewItem( dest, roll->itemid, true, item->randomPropertyId); + } + else + { + item->is_blocked = false; + player->SendEquipError( msg, NULL, NULL ); + } + } + } + } + else + { + SendLootAllPassed(NumberOfPlayers, *roll); + LootItem *item = &(roll->getLoot()->items[roll->itemSlot]); + if(item) item->is_blocked = false; + } + RollId.erase(rollI); + delete roll; +} + +void Group::SetTargetIcon(uint8 id, uint64 guid) +{ + if(id >= TARGETICONCOUNT) + return; + + // clean other icons + if( guid != 0 ) + for(int i=0; inext()) + { + Player* member = itr->getSource(); + if(!member || !member->isAlive()) // only for alive + continue; + + if(!member->IsAtGroupRewardDistance(victim)) // at req. distance + continue; + + ++count; + sum_level += member->getLevel(); + if(!member_with_max_level || member_with_max_level->getLevel() < member->getLevel()) + member_with_max_level = member; + } +} + +void Group::SendTargetIconList(WorldSession *session) +{ + if(!session) + return; + + WorldPacket data(MSG_RAID_TARGET_UPDATE, (1+TARGETICONCOUNT*9)); + data << (uint8)1; + + for(int i=0; iSendPacket(&data); +} + +void Group::SendUpdate() +{ + Player *player; + + for(member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr) + { + player = objmgr.GetPlayer(citr->guid); + if(!player || !player->GetSession()) + continue; + // guess size + WorldPacket data(SMSG_GROUP_LIST, (1+1+1+1+8+4+GetMembersCount()*20)); + data << (uint8)m_groupType; // group type + data << (uint8)(isBGGroup() ? 1 : 0); // 2.0.x, isBattleGroundGroup? + data << (uint8)(citr->group); // groupid + data << (uint8)(citr->assistant?0x01:0); // 0x2 main assist, 0x4 main tank + data << uint64(0x50000000FFFFFFFELL); // related to voice chat? + data << uint32(GetMembersCount()-1); + for(member_citerator citr2 = m_memberSlots.begin(); citr2 != m_memberSlots.end(); ++citr2) + { + if(citr->guid == citr2->guid) + continue; + + data << citr2->name; + data << (uint64)citr2->guid; + // online-state + data << (uint8)(objmgr.GetPlayer(citr2->guid) ? 1 : 0); + data << (uint8)(citr2->group); // groupid + data << (uint8)(citr2->assistant?0x01:0); // 0x2 main assist, 0x4 main tank + } + + data << uint64(m_leaderGuid); // leader guid + if(GetMembersCount()-1) + { + data << (uint8)m_lootMethod; // loot method + data << (uint64)m_looterGuid; // looter guid + data << (uint8)m_lootThreshold; // loot threshold + data << (uint8)m_difficulty; // Heroic Mod Group + + } + player->GetSession()->SendPacket( &data ); + } +} + +void Group::UpdatePlayerOutOfRange(Player* pPlayer) +{ + if(!pPlayer) + return; + + Player *player; + WorldPacket data; + pPlayer->GetSession()->BuildPartyMemberStatsChangedPacket(pPlayer, &data); + + for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next()) + { + player = itr->getSource(); + if (player && player != pPlayer && !pPlayer->isVisibleFor(player)) + player->GetSession()->SendPacket(&data); + } +} + +void Group::BroadcastPacket(WorldPacket *packet, int group, uint64 ignore) +{ + for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *pl = itr->getSource(); + if(!pl || (ignore != 0 && pl->GetGUID() == ignore)) + continue; + + if (pl->GetSession() && (group==-1 || itr->getSubGroup()==group)) + pl->GetSession()->SendPacket(packet); + } +} + +void Group::BroadcastReadyCheck(WorldPacket *packet) +{ + for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *pl = itr->getSource(); + if(pl && pl->GetSession()) + if(IsLeader(pl->GetGUID()) || IsAssistant(pl->GetGUID())) + pl->GetSession()->SendPacket(packet); + } +} + +void Group::OfflineReadyCheck() +{ + for(member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr) + { + Player *pl = objmgr.GetPlayer(citr->guid); + if (!pl || !pl->GetSession()) + { + WorldPacket data(MSG_RAID_READY_CHECK_CONFIRM, 9); + data << citr->guid; + data << (uint8)0; + BroadcastReadyCheck(&data); + } + } +} + +bool Group::_addMember(const uint64 &guid, const char* name, bool isAssistant) +{ + // get first not-full group + uint8 groupid = 0; + std::vector temp(MAXRAIDSIZE/MAXGROUPSIZE); + for(member_citerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr) + { + if (itr->group >= temp.size()) continue; + ++temp[itr->group]; + if(temp[groupid] >= MAXGROUPSIZE) + ++groupid; + } + + return _addMember(guid, name, isAssistant, groupid); +} + +bool Group::_addMember(const uint64 &guid, const char* name, bool isAssistant, uint8 group) +{ + if(IsFull()) + return false; + + if(!guid) + return false; + + Player *player = objmgr.GetPlayer(guid); + + MemberSlot member; + member.guid = guid; + member.name = name; + member.group = group; + member.assistant = isAssistant; + m_memberSlots.push_back(member); + + if(player) + { + player->SetGroupInvite(NULL); + player->SetGroup(this, group); + // if the same group invites the player back, cancel the homebind timer + InstanceGroupBind *bind = GetBoundInstance(player->GetMapId(), player->GetDifficulty()); + if(bind && bind->save->GetInstanceId() == player->GetInstanceId()) + player->m_InstanceValid = true; + } + + if(!isRaidGroup()) // reset targetIcons for non-raid-groups + { + for(int i=0; iSetGroup(NULL); + } + + _removeRolls(guid); + + member_witerator slot = _getMemberWSlot(guid); + if (slot != m_memberSlots.end()) + m_memberSlots.erase(slot); + + if(!isBGGroup()) + CharacterDatabase.PExecute("DELETE FROM group_member WHERE memberGuid='%u'", GUID_LOPART(guid)); + + if(m_leaderGuid == guid) // leader was removed + { + if(GetMembersCount() > 0) + _setLeader(m_memberSlots.front().guid); + return true; + } + + return false; +} + +void Group::_setLeader(const uint64 &guid) +{ + member_citerator slot = _getMemberCSlot(guid); + if(slot==m_memberSlots.end()) + return; + + if(!isBGGroup()) + { + // TODO: set a time limit to have this function run rarely cause it can be slow + CharacterDatabase.BeginTransaction(); + + // update the group's bound instances when changing leaders + + // remove all permanent binds from the group + // in the DB also remove solo binds that will be replaced with permbinds + // from the new leader + CharacterDatabase.PExecute( + "DELETE FROM group_instance WHERE leaderguid='%u' AND (permanent = 1 OR " + "instance IN (SELECT instance FROM character_instance WHERE guid = '%u')" + ")", GUID_LOPART(m_leaderGuid), GUID_LOPART(slot->guid) + ); + + Player *player = objmgr.GetPlayer(slot->guid); + if(player) + { + for(uint8 i = 0; i < TOTAL_DIFFICULTIES; i++) + { + for(BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end();) + { + if(itr->second.perm) + { + itr->second.save->RemoveGroup(this); + m_boundInstances[i].erase(itr++); + } + else + ++itr; + } + } + } + + // update the group's solo binds to the new leader + CharacterDatabase.PExecute("UPDATE group_instance SET leaderGuid='%u' WHERE leaderGuid = '%u'", GUID_LOPART(slot->guid), GUID_LOPART(m_leaderGuid)); + + // copy the permanent binds from the new leader to the group + // overwriting the solo binds with permanent ones if necessary + // in the DB those have been deleted already + Player::ConvertInstancesToGroup(player, this, slot->guid); + + // update the group leader + CharacterDatabase.PExecute("UPDATE groups SET leaderGuid='%u' WHERE leaderGuid='%u'", GUID_LOPART(slot->guid), GUID_LOPART(m_leaderGuid)); + CharacterDatabase.PExecute("UPDATE group_member SET leaderGuid='%u' WHERE leaderGuid='%u'", GUID_LOPART(slot->guid), GUID_LOPART(m_leaderGuid)); + CharacterDatabase.CommitTransaction(); + } + + m_leaderGuid = slot->guid; + m_leaderName = slot->name; +} + +void Group::_removeRolls(const uint64 &guid) +{ + for (Rolls::iterator it = RollId.begin(); it < RollId.end(); it++) + { + Roll* roll = *it; + Roll::PlayerVote::iterator itr2 = roll->playerVote.find(guid); + if(itr2 == roll->playerVote.end()) + continue; + + if (itr2->second == GREED) --roll->totalGreed; + if (itr2->second == NEED) --roll->totalNeed; + if (itr2->second == PASS) --roll->totalPass; + if (itr2->second != NOT_VALID) --roll->totalPlayersRolling; + + roll->playerVote.erase(itr2); + + CountRollVote(guid, roll->itemGUID, GetMembersCount()-1, 3); + } +} + +void Group::_convertToRaid() +{ + m_groupType = GROUPTYPE_RAID; + + if(!isBGGroup()) CharacterDatabase.PExecute("UPDATE groups SET isRaid = 1 WHERE leaderGuid='%u'", GUID_LOPART(m_leaderGuid)); +} + +bool Group::_setMembersGroup(const uint64 &guid, const uint8 &group) +{ + member_witerator slot = _getMemberWSlot(guid); + if(slot==m_memberSlots.end()) + return false; + + slot->group = group; + if(!isBGGroup()) CharacterDatabase.PExecute("UPDATE group_member SET subgroup='%u' WHERE memberGuid='%u'", group, GUID_LOPART(guid)); + return true; +} + +bool Group::_setAssistantFlag(const uint64 &guid, const bool &state) +{ + member_witerator slot = _getMemberWSlot(guid); + if(slot==m_memberSlots.end()) + return false; + + slot->assistant = state; + if(!isBGGroup()) CharacterDatabase.PExecute("UPDATE group_member SET assistant='%u' WHERE memberGuid='%u'", (state==true)?1:0, GUID_LOPART(guid)); + return true; +} + +bool Group::_setMainTank(const uint64 &guid) +{ + member_citerator slot = _getMemberCSlot(guid); + if(slot==m_memberSlots.end()) + return false; + + if(m_mainAssistant == guid) + _setMainAssistant(0); + m_mainTank = guid; + if(!isBGGroup()) CharacterDatabase.PExecute("UPDATE groups SET mainTank='%u' WHERE leaderGuid='%u'", GUID_LOPART(m_mainTank), GUID_LOPART(m_leaderGuid)); + return true; +} + +bool Group::_setMainAssistant(const uint64 &guid) +{ + member_witerator slot = _getMemberWSlot(guid); + if(slot==m_memberSlots.end()) + return false; + + if(m_mainTank == guid) + _setMainTank(0); + m_mainAssistant = guid; + if(!isBGGroup()) CharacterDatabase.PExecute("UPDATE groups SET mainAssistant='%u' WHERE leaderGuid='%u'", GUID_LOPART(m_mainAssistant), GUID_LOPART(m_leaderGuid)); + return true; +} + +bool Group::SameSubGroup(Player const* member1, Player const* member2) const +{ + if(!member1 || !member2) return false; + if (member1->GetGroup() != this || member2->GetGroup() != this) return false; + else return member1->GetSubGroup() == member2->GetSubGroup(); +} + +// allows setting subgroup for offline members +void Group::ChangeMembersGroup(const uint64 &guid, const uint8 &group) +{ + if(!isRaidGroup()) + return; + Player *player = objmgr.GetPlayer(guid); + if (!player) + { + if(_setMembersGroup(guid, group)) + SendUpdate(); + } + else ChangeMembersGroup(player, group); +} + +// only for online members +void Group::ChangeMembersGroup(Player *player, const uint8 &group) +{ + if(!player || !isRaidGroup()) + return; + if(_setMembersGroup(player->GetGUID(), group)) + { + player->GetGroupRef().setSubGroup(group); + SendUpdate(); + } +} + +void Group::UpdateLooterGuid( Creature* creature, bool ifneed ) +{ + switch (GetLootMethod()) + { + case MASTER_LOOT: + case FREE_FOR_ALL: + return; + default: + // round robin style looting applies for all low + // quality items in each loot method except free for all and master loot + break; + } + + member_citerator guid_itr = _getMemberCSlot(GetLooterGuid()); + if(guid_itr != m_memberSlots.end()) + { + if(ifneed) + { + // not update if only update if need and ok + Player* looter = ObjectAccessor::FindPlayer(guid_itr->guid); + if(looter && looter->GetDistance2d(creature) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE)) + return; + } + ++guid_itr; + } + + // search next after current + if(guid_itr != m_memberSlots.end()) + { + for(member_citerator itr = guid_itr; itr != m_memberSlots.end(); ++itr) + { + if(Player* pl = ObjectAccessor::FindPlayer(itr->guid)) + { + if (pl->GetDistance2d(creature) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE)) + { + bool refresh = pl->GetLootGUID()==creature->GetGUID(); + + //if(refresh) // update loot for new looter + // pl->GetSession()->DoLootRelease(pl->GetLootGUID()); + SetLooterGuid(pl->GetGUID()); + SendUpdate(); + if(refresh) // update loot for new looter + pl->SendLoot(creature->GetGUID(),LOOT_CORPSE); + return; + } + } + } + } + + // search from start + for(member_citerator itr = m_memberSlots.begin(); itr != guid_itr; ++itr) + { + if(Player* pl = ObjectAccessor::FindPlayer(itr->guid)) + { + if (pl->GetDistance2d(creature) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE)) + { + bool refresh = pl->GetLootGUID()==creature->GetGUID(); + + //if(refresh) // update loot for new looter + // pl->GetSession()->DoLootRelease(pl->GetLootGUID()); + SetLooterGuid(pl->GetGUID()); + SendUpdate(); + if(refresh) // update loot for new looter + pl->SendLoot(creature->GetGUID(),LOOT_CORPSE); + return; + } + } + } + + SetLooterGuid(0); + SendUpdate(); +} + +//=================================================== +//============== Roll =============================== +//=================================================== + +void Roll::targetObjectBuildLink() +{ + // called from link() + this->getTarget()->addLootValidatorRef(this); +} + +void Group::SetDifficulty(uint8 difficulty) +{ + m_difficulty = difficulty; + if(!isBGGroup()) CharacterDatabase.PExecute("UPDATE groups SET difficulty = %u WHERE leaderGuid ='%u'", m_difficulty, GUID_LOPART(m_leaderGuid)); + + for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *player = itr->getSource(); + if(!player->GetSession() || player->getLevel() < LEVELREQUIREMENT_HEROIC) + continue; + player->SetDifficulty(difficulty); + player->SendDungeonDifficulty(true); + } +} + +bool Group::InCombatToInstance(uint32 instanceId) +{ + for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *pPlayer = itr->getSource(); + if(pPlayer->getAttackers().size() && pPlayer->GetInstanceId() == instanceId) + return true; + } + return false; +} + +void Group::ResetInstances(uint8 method, Player* SendMsgTo) +{ + if(isBGGroup()) + return; + + // method can be INSTANCE_RESET_ALL, INSTANCE_RESET_CHANGE_DIFFICULTY, INSTANCE_RESET_GROUP_DISBAND + + // we assume that when the difficulty changes, all instances that can be reset will be + uint8 dif = GetDifficulty(); + + for(BoundInstancesMap::iterator itr = m_boundInstances[dif].begin(); itr != m_boundInstances[dif].end();) + { + InstanceSave *p = itr->second.save; + const MapEntry *entry = sMapStore.LookupEntry(itr->first); + if(!entry || (!p->CanReset() && method != INSTANCE_RESET_GROUP_DISBAND)) + { + ++itr; + continue; + } + + if(method == INSTANCE_RESET_ALL) + { + // the "reset all instances" method can only reset normal maps + if(dif == DIFFICULTY_HEROIC || entry->map_type == MAP_RAID) + { + ++itr; + continue; + } + } + + bool isEmpty = true; + // if the map is loaded, reset it + Map *map = MapManager::Instance().FindMap(p->GetMapId(), p->GetInstanceId()); + if(map && map->IsDungeon()) + isEmpty = ((InstanceMap*)map)->Reset(method); + + if(SendMsgTo) + { + if(isEmpty) SendMsgTo->SendResetInstanceSuccess(p->GetMapId()); + else SendMsgTo->SendResetInstanceFailed(0, p->GetMapId()); + } + + if(isEmpty || method == INSTANCE_RESET_GROUP_DISBAND || method == INSTANCE_RESET_CHANGE_DIFFICULTY) + { + // do not reset the instance, just unbind if others are permanently bound to it + if(p->CanReset()) p->DeleteFromDB(); + else CharacterDatabase.PExecute("DELETE FROM group_instance WHERE instance = '%u'", p->GetInstanceId()); + // i don't know for sure if hash_map iterators + m_boundInstances[dif].erase(itr); + itr = m_boundInstances[dif].begin(); + // this unloads the instance save unless online players are bound to it + // (eg. permanent binds or GM solo binds) + p->RemoveGroup(this); + } + else + ++itr; + } +} + +InstanceGroupBind* Group::GetBoundInstance(uint32 mapid, uint8 difficulty) +{ + // some instances only have one difficulty + const MapEntry* entry = sMapStore.LookupEntry(mapid); + if(!entry || !entry->SupportsHeroicMode()) difficulty = DIFFICULTY_NORMAL; + + BoundInstancesMap::iterator itr = m_boundInstances[difficulty].find(mapid); + if(itr != m_boundInstances[difficulty].end()) + return &itr->second; + else + return NULL; +} + +InstanceGroupBind* Group::BindToInstance(InstanceSave *save, bool permanent, bool load) +{ + if(save && !isBGGroup()) + { + InstanceGroupBind& bind = m_boundInstances[save->GetDifficulty()][save->GetMapId()]; + if(bind.save) + { + // when a boss is killed or when copying the players's binds to the group + if(permanent != bind.perm || save != bind.save) + if(!load) CharacterDatabase.PExecute("UPDATE group_instance SET instance = '%u', permanent = '%u' WHERE leaderGuid = '%u' AND instance = '%u'", save->GetInstanceId(), permanent, GUID_LOPART(GetLeaderGUID()), bind.save->GetInstanceId()); + } + else + if(!load) CharacterDatabase.PExecute("INSERT INTO group_instance (leaderGuid, instance, permanent) VALUES ('%u', '%u', '%u')", GUID_LOPART(GetLeaderGUID()), save->GetInstanceId(), permanent); + + if(bind.save != save) + { + if(bind.save) bind.save->RemoveGroup(this); + save->AddGroup(this); + } + + bind.save = save; + bind.perm = permanent; + if(!load) sLog.outDebug("Group::BindToInstance: %d is now bound to map %d, instance %d, difficulty %d", GUID_LOPART(GetLeaderGUID()), save->GetMapId(), save->GetInstanceId(), save->GetDifficulty()); + return &bind; + } + else + return NULL; +} + +void Group::UnbindInstance(uint32 mapid, uint8 difficulty, bool unload) +{ + BoundInstancesMap::iterator itr = m_boundInstances[difficulty].find(mapid); + if(itr != m_boundInstances[difficulty].end()) + { + if(!unload) CharacterDatabase.PExecute("DELETE FROM group_instance WHERE leaderGuid = '%u' AND instance = '%u'", GUID_LOPART(GetLeaderGUID()), itr->second.save->GetInstanceId()); + itr->second.save->RemoveGroup(this); // save can become invalid + m_boundInstances[difficulty].erase(itr); + } +} + +void Group::_homebindIfInstance(Player *player) +{ + if(player && !player->isGameMaster() && sMapStore.LookupEntry(player->GetMapId())->IsDungeon()) + { + // leaving the group in an instance, the homebind timer is started + // unless the player is permanently saved to the instance + InstanceSave *save = sInstanceSaveManager.GetInstanceSave(player->GetInstanceId()); + InstancePlayerBind *playerBind = save ? player->GetBoundInstance(save->GetMapId(), save->GetDifficulty()) : NULL; + if(!playerBind || !playerBind->perm) + player->m_InstanceValid = false; + } +} diff --git a/src/game/Group.h b/src/game/Group.h new file mode 100644 index 00000000000..14ea3ad7cba --- /dev/null +++ b/src/game/Group.h @@ -0,0 +1,368 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOSSERVER_GROUP_H +#define MANGOSSERVER_GROUP_H + +#include "GroupReference.h" +#include "GroupRefManager.h" +#include "LootMgr.h" + +#include +#include + +#define MAXGROUPSIZE 5 +#define MAXRAIDSIZE 40 +#define TARGETICONCOUNT 8 + +enum RollVote +{ + PASS = 0, + NEED = 1, + GREED = 2, + NOT_EMITED_YET = 3, + NOT_VALID = 4 +}; + +enum GroupMemberOnlineStatus +{ + MEMBER_STATUS_OFFLINE = 0x0000, + MEMBER_STATUS_ONLINE = 0x0001, + MEMBER_STATUS_PVP = 0x0002, + MEMBER_STATUS_UNK0 = 0x0004, // dead? (health=0) + MEMBER_STATUS_UNK1 = 0x0008, // ghost? (health=1) + MEMBER_STATUS_UNK2 = 0x0010, // never seen + MEMBER_STATUS_UNK3 = 0x0020, // never seen + MEMBER_STATUS_UNK4 = 0x0040, // appears with dead and ghost flags + MEMBER_STATUS_UNK5 = 0x0080, // never seen +}; + +enum GroupType +{ + GROUPTYPE_NORMAL = 0, + GROUPTYPE_RAID = 1 +}; + +class BattleGround; + +enum GroupUpdateFlags +{ + GROUP_UPDATE_FLAG_NONE = 0x00000000, // nothing + GROUP_UPDATE_FLAG_STATUS = 0x00000001, // uint16, flags + GROUP_UPDATE_FLAG_CUR_HP = 0x00000002, // uint16 + GROUP_UPDATE_FLAG_MAX_HP = 0x00000004, // uint16 + GROUP_UPDATE_FLAG_POWER_TYPE = 0x00000008, // uint8 + GROUP_UPDATE_FLAG_CUR_POWER = 0x00000010, // uint16 + GROUP_UPDATE_FLAG_MAX_POWER = 0x00000020, // uint16 + GROUP_UPDATE_FLAG_LEVEL = 0x00000040, // uint16 + GROUP_UPDATE_FLAG_ZONE = 0x00000080, // uint16 + GROUP_UPDATE_FLAG_POSITION = 0x00000100, // uint16, uint16 + GROUP_UPDATE_FLAG_AURAS = 0x00000200, // uint64 mask, for each bit set uint16 spellid + uint8 unk + GROUP_UPDATE_FLAG_PET_GUID = 0x00000400, // uint64 pet guid + GROUP_UPDATE_FLAG_PET_NAME = 0x00000800, // pet name, NULL terminated string + GROUP_UPDATE_FLAG_PET_MODEL_ID = 0x00001000, // uint16, model id + GROUP_UPDATE_FLAG_PET_CUR_HP = 0x00002000, // uint16 pet cur health + GROUP_UPDATE_FLAG_PET_MAX_HP = 0x00004000, // uint16 pet max health + GROUP_UPDATE_FLAG_PET_POWER_TYPE = 0x00008000, // uint8 pet power type + GROUP_UPDATE_FLAG_PET_CUR_POWER = 0x00010000, // uint16 pet cur power + GROUP_UPDATE_FLAG_PET_MAX_POWER = 0x00020000, // uint16 pet max power + GROUP_UPDATE_FLAG_PET_AURAS = 0x00040000, // uint64 mask, for each bit set uint16 spellid + uint8 unk, pet auras... + GROUP_UPDATE_PET = 0x0007FC00, // all pet flags + GROUP_UPDATE_FULL = 0x0007FFFF, // all known flags +}; + +#define GROUP_UPDATE_FLAGS_COUNT 20 + // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12,13,14,15,16,17,18,19 +static const uint8 GroupUpdateLength[GROUP_UPDATE_FLAGS_COUNT] = { 0, 2, 2, 2, 1, 2, 2, 2, 2, 4, 8, 8, 1, 2, 2, 2, 1, 2, 2, 8}; + +class InstanceSave; + +class Roll : public LootValidatorRef +{ + public: + Roll(uint64 _guid, LootItem const& li) + : itemGUID(_guid), itemid(li.itemid), itemRandomPropId(li.randomPropertyId), itemRandomSuffix(li.randomSuffix), + totalPlayersRolling(0), totalNeed(0), totalGreed(0), totalPass(0), itemSlot(0) {} + ~Roll() { } + void setLoot(Loot *pLoot) { link(pLoot, this); } + Loot *getLoot() { return getTarget(); } + void targetObjectBuildLink(); + + uint64 itemGUID; + uint32 itemid; + int32 itemRandomPropId; + uint32 itemRandomSuffix; + typedef std::map PlayerVote; + PlayerVote playerVote; //vote position correspond with player position (in group) + uint8 totalPlayersRolling; + uint8 totalNeed; + uint8 totalGreed; + uint8 totalPass; + uint8 itemSlot; +}; + +struct InstanceGroupBind +{ + InstanceSave *save; + bool perm; + /* permanent InstanceGroupBinds exist iff the leader has a permanent + PlayerInstanceBind for the same instance. */ + InstanceGroupBind() : save(NULL), perm(false) {} +}; + +/** request member stats checken **/ +/** todo: uninvite people that not accepted invite **/ +class MANGOS_DLL_SPEC Group +{ + public: + struct MemberSlot + { + uint64 guid; + std::string name; + uint8 group; + bool assistant; + }; + typedef std::list MemberSlotList; + typedef MemberSlotList::const_iterator member_citerator; + + typedef HM_NAMESPACE::hash_map< uint32 /*mapId*/, InstanceGroupBind> BoundInstancesMap; + protected: + typedef MemberSlotList::iterator member_witerator; + typedef std::set InvitesList; + + typedef std::vector Rolls; + + public: + Group(); + ~Group(); + + // group manipulation methods + bool Create(const uint64 &guid, const char * name); + bool LoadGroupFromDB(const uint64 &leaderGuid, QueryResult *result = NULL, bool loadMembers = true); + bool LoadMemberFromDB(uint32 guidLow, uint8 subgroup, bool assistant); + bool AddInvite(Player *player); + uint32 RemoveInvite(Player *player); + void RemoveAllInvites(); + bool AddLeaderInvite(Player *player); + bool AddMember(const uint64 &guid, const char* name); + // method: 0=just remove, 1=kick + uint32 RemoveMember(const uint64 &guid, const uint8 &method); + void ChangeLeader(const uint64 &guid); + void SetLootMethod(LootMethod method) { m_lootMethod = method; } + void SetLooterGuid(const uint64 &guid) { m_looterGuid = guid; } + void UpdateLooterGuid( Creature* creature, bool ifneed = false ); + void SetLootThreshold(ItemQualities threshold) { m_lootThreshold = threshold; } + void Disband(bool hideDestroy=false); + + // properties accessories + bool IsFull() const { return (m_groupType==GROUPTYPE_NORMAL) ? (m_memberSlots.size()>=MAXGROUPSIZE) : (m_memberSlots.size()>=MAXRAIDSIZE); } + bool isRaidGroup() const { return m_groupType==GROUPTYPE_RAID; } + bool isBGGroup() const { return m_bgGroup != NULL; } + bool IsCreated() const { return GetMembersCount() > 0; } + const uint64& GetLeaderGUID() const { return m_leaderGuid; } + const char * GetLeaderName() const { return m_leaderName.c_str(); } + LootMethod GetLootMethod() const { return m_lootMethod; } + const uint64& GetLooterGuid() const { return m_looterGuid; } + ItemQualities GetLootThreshold() const { return m_lootThreshold; } + + // member manipulation methods + bool IsMember(uint64 guid) const { return _getMemberCSlot(guid) != m_memberSlots.end(); } + bool IsLeader(uint64 guid) const { return (GetLeaderGUID() == guid); } + bool IsAssistant(uint64 guid) const + { + member_citerator mslot = _getMemberCSlot(guid); + if(mslot==m_memberSlots.end()) + return false; + + return mslot->assistant; + } + + bool SameSubGroup(uint64 guid1, uint64 guid2) const + { + member_citerator mslot2 = _getMemberCSlot(guid2); + if(mslot2==m_memberSlots.end()) + return false; + + return SameSubGroup(guid1,&*mslot2); + } + + bool SameSubGroup(uint64 guid1, MemberSlot const* slot2) const + { + member_citerator mslot1 = _getMemberCSlot(guid1); + if(mslot1==m_memberSlots.end() || !slot2) + return false; + + return (mslot1->group==slot2->group); + } + + bool SameSubGroup(Player const* member1, Player const* member2) const; + + MemberSlotList const& GetMemberSlots() const { return m_memberSlots; } + GroupReference* GetFirstMember() { return m_memberMgr.getFirst(); } + uint32 GetMembersCount() const { return m_memberSlots.size(); } + void GetDataForXPAtKill(Unit const* victim, uint32& count,uint32& sum_level, Player* & member_with_max_level); + uint8 GetMemberGroup(uint64 guid) const + { + member_citerator mslot = _getMemberCSlot(guid); + if(mslot==m_memberSlots.end()) + return (MAXRAIDSIZE/MAXGROUPSIZE+1); + + return mslot->group; + } + + // some additional raid methods + void ConvertToRaid() + { + _convertToRaid(); + SendUpdate(); + } + void SetBattlegroundGroup(BattleGround *bg) { m_bgGroup = bg; } + + void ChangeMembersGroup(const uint64 &guid, const uint8 &group); + void ChangeMembersGroup(Player *player, const uint8 &group); + + void SetAssistant(const uint64 &guid, const bool &state) + { + if(!isRaidGroup()) + return; + if(_setAssistantFlag(guid, state)) + SendUpdate(); + } + void SetMainTank(const uint64 &guid) + { + if(!isRaidGroup()) + return; + + if(_setMainTank(guid)) + SendUpdate(); + } + void SetMainAssistant(const uint64 &guid) + { + if(!isRaidGroup()) + return; + + if(_setMainAssistant(guid)) + SendUpdate(); + } + + void SetTargetIcon(uint8 id, uint64 guid); + void SetDifficulty(uint8 difficulty); + uint8 GetDifficulty() { return m_difficulty; } + uint16 InInstance(); + bool InCombatToInstance(uint32 instanceId); + void ResetInstances(uint8 method, Player* SendMsgTo); + + // -no description- + //void SendInit(WorldSession *session); + void SendTargetIconList(WorldSession *session); + void SendUpdate(); + void UpdatePlayerOutOfRange(Player* pPlayer); + // ignore: GUID of player that will be ignored + void BroadcastPacket(WorldPacket *packet, int group=-1, uint64 ignore=0); + void BroadcastReadyCheck(WorldPacket *packet); + void OfflineReadyCheck(); + + /*********************************************************/ + /*** LOOT SYSTEM ***/ + /*********************************************************/ + + void SendLootStartRoll(uint32 CountDown, const Roll &r); + void SendLootRoll(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r); + void SendLootRollWon(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r); + void SendLootAllPassed(uint32 NumberOfPlayers, const Roll &r); + void GroupLoot(uint64 playerGUID, Loot *loot, Creature *creature); + void NeedBeforeGreed(uint64 playerGUID, Loot *loot, Creature *creature); + void MasterLoot(uint64 playerGUID, Loot *loot, Creature *creature); + Rolls::iterator GetRoll(uint64 Guid) + { + Rolls::iterator iter; + for (iter=RollId.begin(); iter != RollId.end(); ++iter) + { + if ((*iter)->itemGUID == Guid && (*iter)->isValid()) + { + return iter; + } + } + return RollId.end(); + } + void CountTheRoll(Rolls::iterator roll, uint32 NumberOfPlayers); + void CountRollVote(uint64 playerGUID, uint64 Guid, uint32 NumberOfPlayers, uint8 Choise); + void EndRoll(); + + void LinkMember(GroupReference *pRef) { m_memberMgr.insertFirst(pRef); } + void DelinkMember(GroupReference* /*pRef*/ ) { } + + InstanceGroupBind* BindToInstance(InstanceSave *save, bool permanent, bool load = false); + void UnbindInstance(uint32 mapid, uint8 difficulty, bool unload = false); + InstanceGroupBind* GetBoundInstance(uint32 mapid, uint8 difficulty); + BoundInstancesMap& GetBoundInstances(uint8 difficulty) { return m_boundInstances[difficulty]; } + + protected: + bool _addMember(const uint64 &guid, const char* name, bool isAssistant=false); + bool _addMember(const uint64 &guid, const char* name, bool isAssistant, uint8 group); + bool _removeMember(const uint64 &guid); // returns true if leader has changed + void _setLeader(const uint64 &guid); + + void _removeRolls(const uint64 &guid); + + void _convertToRaid(); + bool _setMembersGroup(const uint64 &guid, const uint8 &group); + bool _setAssistantFlag(const uint64 &guid, const bool &state); + bool _setMainTank(const uint64 &guid); + bool _setMainAssistant(const uint64 &guid); + + void _homebindIfInstance(Player *player); + + member_citerator _getMemberCSlot(uint64 Guid) const + { + for(member_citerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr) + { + if (itr->guid == Guid) + return itr; + } + return m_memberSlots.end(); + } + + member_witerator _getMemberWSlot(uint64 Guid) + { + for(member_witerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr) + { + if (itr->guid == Guid) + return itr; + } + return m_memberSlots.end(); + } + + MemberSlotList m_memberSlots; + GroupRefManager m_memberMgr; + InvitesList m_invitees; + uint64 m_leaderGuid; + std::string m_leaderName; + uint64 m_mainTank; + uint64 m_mainAssistant; + GroupType m_groupType; + uint8 m_difficulty; + BattleGround* m_bgGroup; + uint64 m_targetIcons[TARGETICONCOUNT]; + LootMethod m_lootMethod; + ItemQualities m_lootThreshold; + uint64 m_looterGuid; + Rolls RollId; + BoundInstancesMap m_boundInstances[TOTAL_DIFFICULTIES]; +}; +#endif diff --git a/src/game/GroupHandler.cpp b/src/game/GroupHandler.cpp new file mode 100644 index 00000000000..f2c05e14f5f --- /dev/null +++ b/src/game/GroupHandler.cpp @@ -0,0 +1,934 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "Opcodes.h" +#include "Log.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "World.h" +#include "ObjectMgr.h" +#include "Player.h" +#include "Group.h" +#include "ObjectAccessor.h" +#include "MapManager.h" +#include "SocialMgr.h" +#include "Util.h" + +/* differeces from off: + -you can uninvite yourself - is is useful + -you can accept invitation even if leader went offline +*/ +/* todo: + -group_destroyed msg is sent but not shown + -reduce xp gaining when in raid group + -quest sharing has to be corrected + -FIX sending PartyMemberStats +*/ + +void WorldSession::SendPartyResult(PartyOperation operation, std::string member, PartyResult res) +{ + WorldPacket data(SMSG_PARTY_COMMAND_RESULT, (8+member.size()+1)); + data << (uint32)operation; + data << member; + data << (uint32)res; + + SendPacket( &data ); +} + +void WorldSession::HandleGroupInviteOpcode( WorldPacket & recv_data ) +{ + std::string membername; + recv_data >> membername; + + if(_player->InBattleGround()) + { + SendPartyResult(PARTY_OP_INVITE, membername, PARTY_RESULT_INVITE_RESTRICTED); + return; + } + + // attempt add selected player + + // cheating + if(!normalizePlayerName(membername)) + { + SendPartyResult(PARTY_OP_INVITE, membername, PARTY_RESULT_CANT_FIND_TARGET); + return; + } + + Player *player = objmgr.GetPlayer(membername.c_str()); + + // no player + if(!player) + { + SendPartyResult(PARTY_OP_INVITE, membername, PARTY_RESULT_CANT_FIND_TARGET); + return; + } + + // can't group with + if(!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && GetPlayer()->GetTeam() != player->GetTeam()) + { + SendPartyResult(PARTY_OP_INVITE, membername, PARTY_RESULT_TARGET_UNFRIENDLY); + return; + } + if(GetPlayer()->GetInstanceId() != 0 && player->GetInstanceId() != 0 && GetPlayer()->GetInstanceId() != player->GetInstanceId() && GetPlayer()->GetMapId() == player->GetMapId()) + { + SendPartyResult(PARTY_OP_INVITE, membername, PARTY_RESULT_NOT_IN_YOUR_INSTANCE); + return; + } + // just ignore us + if(player->GetInstanceId() != 0 && player->GetDifficulty() != GetPlayer()->GetDifficulty()) + { + SendPartyResult(PARTY_OP_INVITE, membername, PARTY_RESULT_TARGET_IGNORE_YOU); + return; + } + + if(player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow())) + { + SendPartyResult(PARTY_OP_INVITE, membername, PARTY_RESULT_TARGET_IGNORE_YOU); + return; + } + + // player already in another group or invited + if(player->GetGroup() || player->GetGroupInvite() ) + { + SendPartyResult(PARTY_OP_INVITE, membername, PARTY_RESULT_ALREADY_IN_GROUP); + return; + } + + Group *group = GetPlayer()->GetGroup(); + + if(group) + { + // not have permissions for invite + if(!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID())) + { + SendPartyResult(PARTY_OP_INVITE, "", PARTY_RESULT_YOU_NOT_LEADER); + return; + } + + // not have place + if(group->IsFull()) + { + SendPartyResult(PARTY_OP_INVITE, "", PARTY_RESULT_PARTY_FULL); + return; + } + } + + // ok, but group not exist, start a new group + // but don't create and save the group to the DB until + // at least one person joins + if(!group) + { + group = new Group; + // new group: if can't add then delete + if(!group->AddLeaderInvite(GetPlayer())) + { + delete group; + return; + } + if(!group->AddInvite(player)) + { + delete group; + return; + } + } + else + { + // already existed group: if can't add then just leave + if(!group->AddInvite(player)) + { + return; + } + } + + // ok, we do it + WorldPacket data(SMSG_GROUP_INVITE, 10); // guess size + data << GetPlayer()->GetName(); + player->GetSession()->SendPacket(&data); + + SendPartyResult(PARTY_OP_INVITE, membername, PARTY_RESULT_OK); +} + +void WorldSession::HandleGroupAcceptOpcode( WorldPacket & /*recv_data*/ ) +{ + Group *group = GetPlayer()->GetGroupInvite(); + if (!group) return; + + if(group->GetLeaderGUID() == GetPlayer()->GetGUID()) + { + sLog.outError("HandleGroupAcceptOpcode: player %s(%d) tried to accept an invite to his own group", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow()); + return; + } + + // remove in from ivites in any case + group->RemoveInvite(GetPlayer()); + + /** error handling **/ + /********************/ + + // not have place + if(group->IsFull()) + { + SendPartyResult(PARTY_OP_INVITE, "", PARTY_RESULT_PARTY_FULL); + return; + } + + Player* leader = objmgr.GetPlayer(group->GetLeaderGUID()); + + if(leader && leader->InBattleGround()) + { + SendPartyResult(PARTY_OP_INVITE, "", PARTY_RESULT_INVITE_RESTRICTED); + return; + } + + // forming a new group, create it + if(!group->IsCreated()) + { + if(leader) group->RemoveInvite(leader); + group->Create(group->GetLeaderGUID(), group->GetLeaderName()); + objmgr.AddGroup(group); + } + + // everything's fine, do it + if(!group->AddMember(GetPlayer()->GetGUID(), GetPlayer()->GetName())) + return; + + uint8 subgroup = group->GetMemberGroup(GetPlayer()->GetGUID()); + + GetPlayer()->SetGroup(group, subgroup); +} + +void WorldSession::HandleGroupDeclineOpcode( WorldPacket & /*recv_data*/ ) +{ + Group *group = GetPlayer()->GetGroupInvite(); + if (!group) return; + + Player *leader = objmgr.GetPlayer(group->GetLeaderGUID()); + + /** error handling **/ + if(!leader || !leader->GetSession()) + return; + /********************/ + + // everything's fine, do it + if(!group->IsCreated()) + { + // note: this means that if you invite more than one person + // and one of them declines before the first one accepts + // all invites will be cleared + // fixme: is that ok ? + group->RemoveAllInvites(); + delete group; + } + + GetPlayer()->SetGroupInvite(NULL); + + WorldPacket data( SMSG_GROUP_DECLINE, 10 ); // guess size + data << GetPlayer()->GetName(); + leader->GetSession()->SendPacket( &data ); +} + +void WorldSession::HandleGroupUninviteGuidOpcode(WorldPacket & recv_data) +{ + CHECK_PACKET_SIZE(recv_data,8); + + uint64 guid; + recv_data >> guid; + + if(_player->InBattleGround()) + { + SendPartyResult(PARTY_OP_INVITE, "", PARTY_RESULT_INVITE_RESTRICTED); + return; + } + + std::string membername; + if(!objmgr.GetPlayerNameByGUID(guid, membername)) + return; // not found + + HandleGroupUninvite(guid, membername); +} + +void WorldSession::HandleGroupUninviteNameOpcode(WorldPacket & recv_data) +{ + CHECK_PACKET_SIZE(recv_data,1); + + std::string membername; + recv_data >> membername; + + if(_player->InBattleGround()) + { + SendPartyResult(PARTY_OP_INVITE, membername, PARTY_RESULT_INVITE_RESTRICTED); + return; + } + + // player not found + if(!normalizePlayerName(membername)) + return; + + uint64 guid = objmgr.GetPlayerGUIDByName(membername); + + // player not found + if(!guid) + return; + + HandleGroupUninvite(guid, membername); +} + +void WorldSession::HandleGroupUninvite(uint64 guid, std::string name) +{ + Group *group = GetPlayer()->GetGroup(); + if(!group) + return; + + if(_player->InBattleGround()) + { + SendPartyResult(PARTY_OP_INVITE, "", PARTY_RESULT_INVITE_RESTRICTED); + return; + } + + Player *player = objmgr.GetPlayer(guid); + + /** error handling **/ + if(!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID())) + { + SendPartyResult(PARTY_OP_LEAVE, "", PARTY_RESULT_YOU_NOT_LEADER); + return; + } + + if(!group->IsMember(guid) && (player && player->GetGroupInvite() != group)) + { + SendPartyResult(PARTY_OP_LEAVE, name, PARTY_RESULT_NOT_IN_YOUR_PARTY); + return; + } + + if(guid == GetPlayer()->GetGUID()) + { + sLog.outError("WorldSession::HandleGroupUninvite: leader %s(%d) tried to uninvite himself from the group.", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow()); + return; + } + /********************/ + + // everything's fine, do it + + if(player && player->GetGroupInvite()) // uninvite invitee + player->UninviteFromGroup(); + else // uninvite member + Player::RemoveFromGroup(group,guid); +} + +void WorldSession::HandleGroupSetLeaderOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8); + + Group *group = GetPlayer()->GetGroup(); + if(!group) + return; + + uint64 guid; + recv_data >> guid; + + Player *player = objmgr.GetPlayer(guid); + + /** error handling **/ + if (!player || !group->IsLeader(GetPlayer()->GetGUID()) || player->GetGroup() != group) + return; + /********************/ + + // everything's fine, do it + group->ChangeLeader(guid); +} + +void WorldSession::HandleGroupLeaveOpcode( WorldPacket & /*recv_data*/ ) +{ + if(!GetPlayer()->GetGroup()) + return; + + if(_player->InBattleGround()) + { + SendPartyResult(PARTY_OP_INVITE, "", PARTY_RESULT_INVITE_RESTRICTED); + return; + } + + /** error handling **/ + /********************/ + + // everything's fine, do it + SendPartyResult(PARTY_OP_LEAVE, GetPlayer()->GetName(), PARTY_RESULT_OK); + + GetPlayer()->RemoveFromGroup(); +} + +void WorldSession::HandleLootMethodOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,4+8+4); + + Group *group = GetPlayer()->GetGroup(); + if(!group) + return; + + uint32 lootMethod; + uint64 lootMaster; + uint32 lootThreshold; + recv_data >> lootMethod >> lootMaster >> lootThreshold; + + /** error handling **/ + if(!group->IsLeader(GetPlayer()->GetGUID())) + return; + /********************/ + + // everything's fine, do it + group->SetLootMethod((LootMethod)lootMethod); + group->SetLooterGuid(lootMaster); + group->SetLootThreshold((ItemQualities)lootThreshold); + group->SendUpdate(); +} + +void WorldSession::HandleLootRoll( WorldPacket &recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+4+1); + + if(!GetPlayer()->GetGroup()) + return; + + uint64 Guid; + uint32 NumberOfPlayers; + uint8 Choise; + recv_data >> Guid; //guid of the item rolled + recv_data >> NumberOfPlayers; + recv_data >> Choise; //0: pass, 1: need, 2: greed + + //sLog.outDebug("WORLD RECIEVE CMSG_LOOT_ROLL, From:%u, Numberofplayers:%u, Choise:%u", (uint32)Guid, NumberOfPlayers, Choise); + + Group* group = GetPlayer()->GetGroup(); + if(!group) + return; + + // everything's fine, do it + group->CountRollVote(GetPlayer()->GetGUID(), Guid, NumberOfPlayers, Choise); +} + +void WorldSession::HandleMinimapPingOpcode(WorldPacket& recv_data) +{ + CHECK_PACKET_SIZE(recv_data,4+4); + + if(!GetPlayer()->GetGroup()) + return; + + float x, y; + recv_data >> x; + recv_data >> y; + + //sLog.outDebug("Received opcode MSG_MINIMAP_PING X: %f, Y: %f", x, y); + + /** error handling **/ + /********************/ + + // everything's fine, do it + WorldPacket data(MSG_MINIMAP_PING, (8+4+4)); + data << GetPlayer()->GetGUID(); + data << x; + data << y; + GetPlayer()->GetGroup()->BroadcastPacket(&data, -1, GetPlayer()->GetGUID()); +} + +void WorldSession::HandleRandomRollOpcode(WorldPacket& recv_data) +{ + CHECK_PACKET_SIZE(recv_data,4+4); + + uint32 minimum, maximum, roll; + recv_data >> minimum; + recv_data >> maximum; + + /** error handling **/ + if(minimum > maximum || maximum > 10000) // < 32768 for urand call + return; + /********************/ + + // everything's fine, do it + roll = urand(minimum, maximum); + + //sLog.outDebug("ROLL: MIN: %u, MAX: %u, ROLL: %u", minimum, maximum, roll); + + WorldPacket data(MSG_RANDOM_ROLL, 4+4+4+8); + data << minimum; + data << maximum; + data << roll; + data << GetPlayer()->GetGUID(); + if(GetPlayer()->GetGroup()) + GetPlayer()->GetGroup()->BroadcastPacket(&data); + else + SendPacket(&data); +} + +void WorldSession::HandleRaidIconTargetOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,1); + + Group *group = GetPlayer()->GetGroup(); + if(!group) + return; + + uint8 x; + recv_data >> x; + + /** error handling **/ + /********************/ + + // everything's fine, do it + if(x == 0xFF) // target icon request + { + group->SendTargetIconList(this); + } + else // target icon update + { + // recheck + CHECK_PACKET_SIZE(recv_data,1+8); + + if(!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID())) + return; + + uint64 guid; + recv_data >> guid; + group->SetTargetIcon(x, guid); + } +} + +void WorldSession::HandleRaidConvertOpcode( WorldPacket & /*recv_data*/ ) +{ + Group *group = GetPlayer()->GetGroup(); + if(!group) + return; + + if(_player->InBattleGround()) + return; + + /** error handling **/ + if(!group->IsLeader(GetPlayer()->GetGUID()) || group->GetMembersCount() < 2) + return; + /********************/ + + // everything's fine, do it (is it 0 (PARTY_OP_INVITE) correct code) + SendPartyResult(PARTY_OP_INVITE, "", PARTY_RESULT_OK); + group->ConvertToRaid(); +} + +void WorldSession::HandleGroupChangeSubGroupOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,1+1); + + Group *group = GetPlayer()->GetGroup(); + if(!group) + return; + + std::string name; + uint8 groupNr; + recv_data >> name; + + // recheck + CHECK_PACKET_SIZE(recv_data,(name.size()+1)+1); + + recv_data >> groupNr; + + /** error handling **/ + if(!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID())) + return; + /********************/ + + // everything's fine, do it + group->ChangeMembersGroup(objmgr.GetPlayer(name.c_str()), groupNr); +} + +void WorldSession::HandleGroupAssistantOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+1); + + Group *group = GetPlayer()->GetGroup(); + if(!group) + return; + + uint64 guid; + uint8 flag; + recv_data >> guid; + recv_data >> flag; + + /** error handling **/ + if(!group->IsLeader(GetPlayer()->GetGUID())) + return; + /********************/ + + // everything's fine, do it + group->SetAssistant(guid, (flag==0?false:true)); +} + +void WorldSession::HandleGroupPromoteOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data, 1+1+8); + + Group *group = GetPlayer()->GetGroup(); + if(!group) + return; + + uint8 flag1, flag2; + uint64 guid; + recv_data >> flag1 >> flag2; + recv_data >> guid; + // if(flag1) Main Assist + // 0x4 + // if(flag2) Main Tank + // 0x2 + + /** error handling **/ + if(!group->IsLeader(GetPlayer()->GetGUID())) + return; + /********************/ + + // everything's fine, do it + if(flag1 == 1) + group->SetMainAssistant(guid); + if(flag2 == 1) + group->SetMainTank(guid); +} + +void WorldSession::HandleRaidReadyCheckOpcode( WorldPacket & recv_data ) +{ + Group *group = GetPlayer()->GetGroup(); + if(!group) + return; + + if(recv_data.empty()) // request + { + /** error handling **/ + if(!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID())) + return; + /********************/ + + // everything's fine, do it + WorldPacket data(MSG_RAID_READY_CHECK, 8); + data << GetPlayer()->GetGUID(); + group->BroadcastPacket(&data, -1); + + group->OfflineReadyCheck(); + } + else // answer + { + uint8 state; + recv_data >> state; + + // everything's fine, do it + WorldPacket data(MSG_RAID_READY_CHECK_CONFIRM, 9); + data << GetPlayer()->GetGUID(); + data << state; + group->BroadcastReadyCheck(&data); + } +} + +void WorldSession::HandleRaidReadyCheckFinishOpcode( WorldPacket & recv_data ) +{ + //Group* group = GetPlayer()->GetGroup(); + //if(!group) + // return; + + //if(!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID())) + // return; + + // Is any reaction need? +} + +void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacket *data) +{ + uint32 mask = player->GetGroupUpdateFlag(); + + if (mask == GROUP_UPDATE_FLAG_NONE) + return; + + if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) // if update power type, update current/max power also + mask |= (GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER); + + if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) // same for pets + mask |= (GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER); + + uint32 byteCount = 0; + for (int i = 1; i < GROUP_UPDATE_FLAGS_COUNT; ++i) + if (mask & (1 << i)) + byteCount += GroupUpdateLength[i]; + + data->Initialize(SMSG_PARTY_MEMBER_STATS, 8 + 4 + byteCount); + data->append(player->GetPackGUID()); + *data << (uint32) mask; + + if (mask & GROUP_UPDATE_FLAG_STATUS) + { + if (player) + { + if (player->IsPvP()) + *data << (uint16) (MEMBER_STATUS_ONLINE | MEMBER_STATUS_PVP); + else + *data << (uint16) MEMBER_STATUS_ONLINE; + } + else + *data << (uint16) MEMBER_STATUS_OFFLINE; + } + + if (mask & GROUP_UPDATE_FLAG_CUR_HP) + *data << (uint16) player->GetHealth(); + + if (mask & GROUP_UPDATE_FLAG_MAX_HP) + *data << (uint16) player->GetMaxHealth(); + + Powers powerType = player->getPowerType(); + if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) + *data << (uint8) powerType; + + if (mask & GROUP_UPDATE_FLAG_CUR_POWER) + *data << (uint16) player->GetPower(powerType); + + if (mask & GROUP_UPDATE_FLAG_MAX_POWER) + *data << (uint16) player->GetMaxPower(powerType); + + if (mask & GROUP_UPDATE_FLAG_LEVEL) + *data << (uint16) player->getLevel(); + + if (mask & GROUP_UPDATE_FLAG_ZONE) + *data << (uint16) player->GetZoneId(); + + if (mask & GROUP_UPDATE_FLAG_POSITION) + *data << (uint16) player->GetPositionX() << (uint16) player->GetPositionY(); + + if (mask & GROUP_UPDATE_FLAG_AURAS) + { + uint64 auramask = player->GetAuraUpdateMask(); + *data << uint64(auramask); + for(uint32 i = 0; i < MAX_AURAS; ++i) + { + if(auramask & (uint64(1) << i)) + { + *data << uint16(player->GetUInt32Value(UNIT_FIELD_AURA + i)); + *data << uint8(1); + } + } + } + + Pet *pet = player->GetPet(); + if (mask & GROUP_UPDATE_FLAG_PET_GUID) + { + if(pet) + *data << (uint64) pet->GetGUID(); + else + *data << (uint64) 0; + } + + if (mask & GROUP_UPDATE_FLAG_PET_NAME) + { + if(pet) + *data << pet->GetName(); + else + *data << (uint8) 0; + } + + if (mask & GROUP_UPDATE_FLAG_PET_MODEL_ID) + { + if(pet) + *data << (uint16) pet->GetDisplayId(); + else + *data << (uint16) 0; + } + + if (mask & GROUP_UPDATE_FLAG_PET_CUR_HP) + { + if(pet) + *data << (uint16) pet->GetHealth(); + else + *data << (uint16) 0; + } + + if (mask & GROUP_UPDATE_FLAG_PET_MAX_HP) + { + if(pet) + *data << (uint16) pet->GetMaxHealth(); + else + *data << (uint16) 0; + } + + if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) + { + if(pet) + *data << (uint8) pet->getPowerType(); + else + *data << (uint8) 0; + } + + if (mask & GROUP_UPDATE_FLAG_PET_CUR_POWER) + { + if(pet) + *data << (uint16) pet->GetPower(pet->getPowerType()); + else + *data << (uint16) 0; + } + + if (mask & GROUP_UPDATE_FLAG_PET_MAX_POWER) + { + if(pet) + *data << (uint16) pet->GetMaxPower(pet->getPowerType()); + else + *data << (uint16) 0; + } + + if (mask & GROUP_UPDATE_FLAG_PET_AURAS) + { + if(pet) + { + uint64 auramask = pet->GetAuraUpdateMask(); + *data << uint64(auramask); + for(uint32 i = 0; i < MAX_AURAS; ++i) + { + if(auramask & (uint64(1) << i)) + { + *data << uint16(pet->GetUInt32Value(UNIT_FIELD_AURA + i)); + *data << uint8(1); + } + } + } + else + *data << (uint64) 0; + } +} + +/*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/ +void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data ) +{ + CHECK_PACKET_SIZE(recv_data, 8); + + sLog.outDebug("WORLD: Received CMSG_REQUEST_PARTY_MEMBER_STATS"); + uint64 Guid; + recv_data >> Guid; + + Player *player = objmgr.GetPlayer(Guid); + if(!player) + { + WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 3+4+2); + data.appendPackGUID(Guid); + data << (uint32) GROUP_UPDATE_FLAG_STATUS; + data << (uint16) MEMBER_STATUS_OFFLINE; + SendPacket(&data); + return; + } + + Pet *pet = player->GetPet(); + + WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 4+2+2+2+1+2*6+8+1+8); + data.append(player->GetPackGUID()); + + uint32 mask1 = 0x00040BFF; // common mask, real flags used 0x000040BFF + if(pet) + mask1 = 0x7FFFFFFF; // for hunters and other classes with pets + + Powers powerType = player->getPowerType(); + data << (uint32) mask1; // group update mask + data << (uint16) MEMBER_STATUS_ONLINE; // member's online status + data << (uint16) player->GetHealth(); // GROUP_UPDATE_FLAG_CUR_HP + data << (uint16) player->GetMaxHealth(); // GROUP_UPDATE_FLAG_MAX_HP + data << (uint8) powerType; // GROUP_UPDATE_FLAG_POWER_TYPE + data << (uint16) player->GetPower(powerType); // GROUP_UPDATE_FLAG_CUR_POWER + data << (uint16) player->GetMaxPower(powerType); // GROUP_UPDATE_FLAG_MAX_POWER + data << (uint16) player->getLevel(); // GROUP_UPDATE_FLAG_LEVEL + data << (uint16) player->GetZoneId(); // GROUP_UPDATE_FLAG_ZONE + data << (uint16) player->GetPositionX(); // GROUP_UPDATE_FLAG_POSITION + data << (uint16) player->GetPositionY(); // GROUP_UPDATE_FLAG_POSITION + + uint64 auramask = 0; + size_t maskPos = data.wpos(); + data << (uint64) auramask; // placeholder + for(uint8 i = 0; i < MAX_AURAS; ++i) + { + if(uint32 aura = player->GetUInt32Value(UNIT_FIELD_AURA + i)) + { + auramask |= (uint64(1) << i); + data << uint16(aura); + data << uint8(1); + } + } + data.put(maskPos,auramask); // GROUP_UPDATE_FLAG_AURAS + + if(pet) + { + Powers petpowertype = pet->getPowerType(); + data << (uint64) pet->GetGUID(); // GROUP_UPDATE_FLAG_PET_GUID + data << pet->GetName(); // GROUP_UPDATE_FLAG_PET_NAME + data << (uint16) pet->GetDisplayId(); // GROUP_UPDATE_FLAG_PET_MODEL_ID + data << (uint16) pet->GetHealth(); // GROUP_UPDATE_FLAG_PET_CUR_HP + data << (uint16) pet->GetMaxHealth(); // GROUP_UPDATE_FLAG_PET_MAX_HP + data << (uint8) petpowertype; // GROUP_UPDATE_FLAG_PET_POWER_TYPE + data << (uint16) pet->GetPower(petpowertype); // GROUP_UPDATE_FLAG_PET_CUR_POWER + data << (uint16) pet->GetMaxPower(petpowertype); // GROUP_UPDATE_FLAG_PET_MAX_POWER + + uint64 petauramask = 0; + size_t petMaskPos = data.wpos(); + data << (uint64) petauramask; // placeholder + for(uint8 i = 0; i < MAX_AURAS; ++i) + { + if(uint32 petaura = pet->GetUInt32Value(UNIT_FIELD_AURA + i)) + { + petauramask |= (uint64(1) << i); + data << (uint16) petaura; + data << (uint8) 1; + } + } + data.put(petMaskPos,petauramask); // GROUP_UPDATE_FLAG_PET_AURAS + } + else + { + data << (uint8) 0; // GROUP_UPDATE_FLAG_PET_NAME + data << (uint64) 0; // GROUP_UPDATE_FLAG_PET_AURAS + } + + SendPacket(&data); +} + +/*!*/void WorldSession::HandleRequestRaidInfoOpcode( WorldPacket & /*recv_data*/ ) +{ + // every time the player checks the character screen + _player->SendRaidInfo(); +} + +/*void WorldSession::HandleGroupCancelOpcode( WorldPacket & recv_data ) +{ + sLog.outDebug( "WORLD: got CMSG_GROUP_CANCEL." ); +}*/ + +void WorldSession::HandleGroupPassOnLootOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data, 4); + + sLog.outDebug("WORLD: Received CMSG_GROUP_PASS_ON_LOOT"); + + uint32 unkn; + recv_data >> unkn; + + // ignore if player not loaded + if(!GetPlayer()) // needed because STATUS_AUTHED + { + if(unkn!=0) + sLog.outError("CMSG_GROUP_PASS_ON_LOOT value<>0 for not-loaded character!"); + return; + } + + if(unkn!=0) + sLog.outError("CMSG_GROUP_PASS_ON_LOOT: activation not implemented!"); +} diff --git a/src/game/GroupRefManager.h b/src/game/GroupRefManager.h new file mode 100644 index 00000000000..da849214416 --- /dev/null +++ b/src/game/GroupRefManager.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _GROUPREFMANAGER +#define _GROUPREFMANAGER + +#include "Utilities/LinkedReference/RefManager.h" + +class Group; +class Player; +class GroupReference; + +class GroupRefManager : public RefManager +{ + public: + GroupReference* getFirst() { return ((GroupReference* ) RefManager::getFirst()); } +}; +#endif diff --git a/src/game/GroupReference.cpp b/src/game/GroupReference.cpp new file mode 100644 index 00000000000..33aff764e92 --- /dev/null +++ b/src/game/GroupReference.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Player.h" +#include "Group.h" +#include "GroupReference.h" + +void GroupReference::targetObjectBuildLink() +{ + // called from link() + getTarget()->LinkMember(this); +} + +void GroupReference::targetObjectDestroyLink() +{ + // called from unlink() + getTarget()->DelinkMember(this); +} + +void GroupReference::sourceObjectDestroyLink() +{ + // called from invalidate() + getTarget()->DelinkMember(this); +} diff --git a/src/game/GroupReference.h b/src/game/GroupReference.h new file mode 100644 index 00000000000..1e4453b020a --- /dev/null +++ b/src/game/GroupReference.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _GROUPREFERENCE_H +#define _GROUPREFERENCE_H + +#include "Utilities/LinkedReference/Reference.h" + +class Group; +class Player; + +class MANGOS_DLL_SPEC GroupReference : public Reference +{ + protected: + uint8 iSubGroup; + void targetObjectBuildLink(); + void targetObjectDestroyLink(); + void sourceObjectDestroyLink(); + public: + GroupReference() : Reference(), iSubGroup(0) {} + ~GroupReference() { unlink(); } + GroupReference *next() { return (GroupReference*)Reference::next(); } + uint8 getSubGroup() const { return iSubGroup; } + void setSubGroup(uint8 pSubGroup) { iSubGroup = pSubGroup; } +}; +#endif diff --git a/src/game/GuardAI.cpp b/src/game/GuardAI.cpp new file mode 100644 index 00000000000..fffbb7d4000 --- /dev/null +++ b/src/game/GuardAI.cpp @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "GuardAI.h" +#include "Errors.h" +#include "Creature.h" +#include "Player.h" +#include "ObjectAccessor.h" +#include "World.h" + +int GuardAI::Permissible(const Creature *creature) +{ + if( creature->isGuard()) + return PERMIT_BASE_SPECIAL; + + return PERMIT_BASE_NO; +} + +GuardAI::GuardAI(Creature &c) : i_creature(c), i_victimGuid(0), i_state(STATE_NORMAL), i_tracker(TIME_INTERVAL_LOOK) +{ +} + +void GuardAI::MoveInLineOfSight(Unit *u) +{ + if( !i_creature.getVictim() && u->isTargetableForAttack() && + ( u->IsHostileToPlayers() || i_creature.IsHostileTo(u) /*|| u->getVictim() && i_creature.IsFriendlyTo(u->getVictim())*/ ) && + u->isInAccessablePlaceFor(&i_creature)) + { + float attackRadius = i_creature.GetAttackDistance(u); + if(i_creature.IsWithinDistInMap(u,attackRadius) && i_creature.GetDistanceZ(u) <= CREATURE_Z_ATTACK_RANGE) + { + //Need add code to let guard support player + AttackStart(u); + u->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + } + } +} + +void GuardAI::EnterEvadeMode() +{ + if( !i_creature.isAlive() ) + { + DEBUG_LOG("Creature stopped attacking because he's dead [guid=%u]", i_creature.GetGUIDLow()); + i_creature.StopMoving(); + i_creature.GetMotionMaster()->MoveIdle(); + + i_state = STATE_NORMAL; + + i_victimGuid = 0; + i_creature.CombatStop(); + i_creature.DeleteThreatList(); + return; + } + + Unit* victim = ObjectAccessor::GetUnit(i_creature, i_victimGuid ); + + if( !victim ) + { + DEBUG_LOG("Creature stopped attacking because victim is non exist [guid=%u]", i_creature.GetGUIDLow()); + } + else if( !victim ->isAlive() ) + { + DEBUG_LOG("Creature stopped attacking because victim is dead [guid=%u]", i_creature.GetGUIDLow()); + } + else if( victim ->HasStealthAura() ) + { + DEBUG_LOG("Creature stopped attacking because victim is using stealth [guid=%u]", i_creature.GetGUIDLow()); + } + else if( victim ->isInFlight() ) + { + DEBUG_LOG("Creature stopped attacking because victim is flying away [guid=%u]", i_creature.GetGUIDLow()); + } + else + { + DEBUG_LOG("Creature stopped attacking because victim outran him [guid=%u]", i_creature.GetGUIDLow()); + } + + i_creature.RemoveAllAuras(); + i_creature.DeleteThreatList(); + i_victimGuid = 0; + i_creature.CombatStop(); + i_state = STATE_NORMAL; + + // Remove TargetedMovementGenerator from MotionMaster stack list, and add HomeMovementGenerator instead + if( i_creature.GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE ) + i_creature.GetMotionMaster()->MoveTargetedHome(); +} + +void GuardAI::UpdateAI(const uint32 /*diff*/) +{ + // update i_victimGuid if i_creature.getVictim() !=0 and changed + if(!i_creature.SelectHostilTarget() || !i_creature.getVictim()) + return; + + i_victimGuid = i_creature.getVictim()->GetGUID(); + + if( i_creature.isAttackReady() ) + { + if( i_creature.IsWithinDistInMap(i_creature.getVictim(), ATTACK_DISTANCE)) + { + i_creature.AttackerStateUpdate(i_creature.getVictim()); + i_creature.resetAttackTimer(); + } + } +} + +bool GuardAI::IsVisible(Unit *pl) const +{ + return i_creature.GetDistance(pl) < sWorld.getConfig(CONFIG_SIGHT_GUARDER) + && pl->isVisibleForOrDetect(&i_creature,true); +} + +void GuardAI::AttackStart(Unit *u) +{ + if( !u ) + return; + + // DEBUG_LOG("Creature %s tagged a victim to kill [guid=%u]", i_creature.GetName(), u->GetGUIDLow()); + if(i_creature.Attack(u,true)) + { + i_creature.SetInCombatWith(u); + u->SetInCombatWith(&i_creature); + + i_creature.AddThreat(u, 0.0f); + i_victimGuid = u->GetGUID(); + i_creature.GetMotionMaster()->MoveChase(u); + } +} + +void GuardAI::JustDied(Unit *killer) +{ + if(Player* pkiller = killer->GetCharmerOrOwnerPlayerOrPlayerItself()) + i_creature.SendZoneUnderAttackMessage(pkiller); +} + diff --git a/src/game/GuardAI.h b/src/game/GuardAI.h new file mode 100644 index 00000000000..f11dad6870e --- /dev/null +++ b/src/game/GuardAI.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_GUARDAI_H +#define MANGOS_GUARDAI_H + +#include "CreatureAI.h" +#include "Timer.h" + +class Creature; + +class MANGOS_DLL_DECL GuardAI : public CreatureAI +{ + enum GuardState + { + STATE_NORMAL = 1, + STATE_LOOK_AT_VICTIM = 2 + }; + + public: + + GuardAI(Creature &c); + + void MoveInLineOfSight(Unit *); + void AttackStart(Unit *); + void EnterEvadeMode(); + void JustDied(Unit *); + bool IsVisible(Unit *) const; + + void UpdateAI(const uint32); + static int Permissible(const Creature *); + + private: + Creature &i_creature; + uint64 i_victimGuid; + GuardState i_state; + TimeTracker i_tracker; +}; +#endif diff --git a/src/game/Guild.cpp b/src/game/Guild.cpp new file mode 100644 index 00000000000..bce616be394 --- /dev/null +++ b/src/game/Guild.cpp @@ -0,0 +1,1940 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Database/DatabaseEnv.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "MapManager.h" +#include "Player.h" +#include "Opcodes.h" +#include "ObjectMgr.h" +#include "Guild.h" +#include "Chat.h" +#include "SocialMgr.h" +#include "Util.h" + +Guild::Guild() +{ + Id = 0; + name = ""; + leaderGuid = 0; + GINFO = MOTD = ""; + EmblemStyle = 0; + EmblemColor = 0; + BorderStyle = 0; + BorderColor = 0; + BackgroundColor = 0; + + CreatedYear = 0; + CreatedMonth = 0; + CreatedDay = 0; +} + +Guild::~Guild() +{ + +} + +bool Guild::create(uint64 lGuid, std::string gname) +{ + std::string rname; + std::string lName; + + if(!objmgr.GetPlayerNameByGUID(lGuid, lName)) + return false; + if(objmgr.GetGuildByName(gname)) + return false; + + sLog.outDebug("GUILD: creating guild %s to leader: %u", gname.c_str(), GUID_LOPART(lGuid)); + + leaderGuid = lGuid; + name = gname; + GINFO = ""; + MOTD = "No message set."; + guildbank_money = 0; + purchased_tabs = 0; + + QueryResult *result = CharacterDatabase.Query( "SELECT MAX(guildid) FROM guild" ); + if( result ) + { + Id = (*result)[0].GetUInt32()+1; + delete result; + } + else Id = 1; + + // gname already assigned to Guild::name, use it to encode string for DB + CharacterDatabase.escape_string(gname); + + std::string dbGINFO = GINFO; + std::string dbMOTD = MOTD; + CharacterDatabase.escape_string(dbGINFO); + CharacterDatabase.escape_string(dbMOTD); + + CharacterDatabase.BeginTransaction(); + // CharacterDatabase.PExecute("DELETE FROM guild WHERE guildid='%u'", Id); - MAX(guildid)+1 not exist + CharacterDatabase.PExecute("DELETE FROM guild_rank WHERE guildid='%u'", Id); + CharacterDatabase.PExecute("DELETE FROM guild_member WHERE guildid='%u'", Id); + CharacterDatabase.PExecute("INSERT INTO guild (guildid,name,leaderguid,info,motd,createdate,EmblemStyle,EmblemColor,BorderStyle,BorderColor,BackgroundColor,BankMoney) " + "VALUES('%u','%s','%u', '%s', '%s', NOW(),'%u','%u','%u','%u','%u','" I64FMTD "')", + Id, gname.c_str(), GUID_LOPART(leaderGuid), dbGINFO.c_str(), dbMOTD.c_str(), EmblemStyle, EmblemColor, BorderStyle, BorderColor, BackgroundColor, guildbank_money); + CharacterDatabase.CommitTransaction(); + + rname = "Guild Master"; + CreateRank(rname,GR_RIGHT_ALL); + rname = "Officer"; + CreateRank(rname,GR_RIGHT_ALL); + rname = "Veteran"; + CreateRank(rname,GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK); + rname = "Member"; + CreateRank(rname,GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK); + rname = "Initiate"; + CreateRank(rname,GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK); + + return AddMember(lGuid, (uint32)GR_GUILDMASTER); +} + +bool Guild::AddMember(uint64 plGuid, uint32 plRank) +{ + if(Player::GetGuildIdFromDB(plGuid) != 0) // player already in guild + return false; + + // remove all player signs from another petitions + // this will be prevent attempt joining player to many guilds and corrupt guild data integrity + Player::RemovePetitionsAndSigns(plGuid, 9); + + // fill player data + MemberSlot newmember; + + if(!FillPlayerData(plGuid, &newmember)) // problems with player data collection + return false; + + newmember.RankId = plRank; + newmember.OFFnote = (std::string)""; + newmember.Pnote = (std::string)""; + newmember.logout_time = time(NULL); + newmember.BankResetTimeMoney = 0; // this will force update at first query + for (int i = 0; i < GUILD_BANK_MAX_TABS; ++i) + newmember.BankResetTimeTab[i] = 0; + members[GUID_LOPART(plGuid)] = newmember; + + std::string dbPnote = newmember.Pnote; + std::string dbOFFnote = newmember.OFFnote; + CharacterDatabase.escape_string(dbPnote); + CharacterDatabase.escape_string(dbOFFnote); + + CharacterDatabase.PExecute("INSERT INTO guild_member (guildid,guid,rank,pnote,offnote) VALUES ('%u', '%u', '%u','%s','%s')", + Id, GUID_LOPART(plGuid), newmember.RankId, dbPnote.c_str(), dbOFFnote.c_str()); + + Player* pl = objmgr.GetPlayer(plGuid); + if(pl) + { + pl->SetInGuild(Id); + pl->SetRank(newmember.RankId); + pl->SetGuildIdInvited(0); + } + else + { + Player::SetUInt32ValueInDB(PLAYER_GUILDID, Id, plGuid); + Player::SetUInt32ValueInDB(PLAYER_GUILDRANK, newmember.RankId, plGuid); + } + return true; +} + +void Guild::SetMOTD(std::string motd) +{ + MOTD = motd; + + // motd now can be used for encoding to DB + CharacterDatabase.escape_string(motd); + CharacterDatabase.PExecute("UPDATE guild SET motd='%s' WHERE guildid='%u'", motd.c_str(), Id); +} + +void Guild::SetGINFO(std::string ginfo) +{ + GINFO = ginfo; + + // ginfo now can be used for encoding to DB + CharacterDatabase.escape_string(ginfo); + CharacterDatabase.PExecute("UPDATE guild SET info='%s' WHERE guildid='%u'", ginfo.c_str(), Id); +} + +bool Guild::LoadGuildFromDB(uint32 GuildId) +{ + if(!LoadRanksFromDB(GuildId)) + return false; + + if(!LoadMembersFromDB(GuildId)) + return false; + + QueryResult *result = CharacterDatabase.PQuery("SELECT MAX(TabId) FROM guild_bank_tab WHERE guildid='%u'", GuildId); + if(result) + { + Field *fields = result->Fetch(); + purchased_tabs = fields[0].GetUInt8()+1; // Because TabId begins at 0 + delete result; + } + else + purchased_tabs = 0; + + LoadBankRightsFromDB(GuildId); // Must be after LoadRanksFromDB because it populates rank struct + + // 0 1 2 3 4 5 6 + result = CharacterDatabase.PQuery("SELECT guildid, name, leaderguid, EmblemStyle, EmblemColor, BorderStyle, BorderColor," + // 7 8 9 10 11 + "BackgroundColor, info, motd, createdate, BankMoney FROM guild WHERE guildid = '%u'", GuildId); + + if(!result) + return false; + + Field *fields = result->Fetch(); + + Id = fields[0].GetUInt32(); + name = fields[1].GetCppString(); + leaderGuid = MAKE_NEW_GUID(fields[2].GetUInt32(), 0, HIGHGUID_PLAYER); + + EmblemStyle = fields[3].GetUInt32(); + EmblemColor = fields[4].GetUInt32(); + BorderStyle = fields[5].GetUInt32(); + BorderColor = fields[6].GetUInt32(); + BackgroundColor = fields[7].GetUInt32(); + GINFO = fields[8].GetCppString(); + MOTD = fields[9].GetCppString(); + uint64 time = fields[10].GetUInt64(); //datetime is uint64 type ... YYYYmmdd:hh:mm:ss + guildbank_money = fields[11].GetUInt64(); + + delete result; + + uint64 dTime = time /1000000; + CreatedDay = dTime%100; + CreatedMonth = (dTime/100)%100; + CreatedYear = (dTime/10000)%10000; + + // If the leader does not exist attempt to promote another member + if(!objmgr.GetPlayerAccountIdByGUID(leaderGuid )) + { + DelMember(leaderGuid); + + // check no members case (disbanded) + if(members.empty()) + return false; + } + + sLog.outDebug("Guild %u Creation time Loaded day: %u, month: %u, year: %u", GuildId, CreatedDay, CreatedMonth, CreatedYear); + m_bankloaded = false; + m_eventlogloaded = false; + m_onlinemembers = 0; + RenumBankLogs(); + RenumGuildEventlog(); + return true; +} + +bool Guild::LoadRanksFromDB(uint32 GuildId) +{ + Field *fields; + QueryResult *result = CharacterDatabase.PQuery("SELECT rname,rights,BankMoneyPerDay,rid FROM guild_rank WHERE guildid = '%u' ORDER BY rid ASC", GuildId); + + if(!result) + return false; + + bool broken_ranks = false; + + do + { + fields = result->Fetch(); + + std::string rankName = fields[0].GetCppString(); + uint32 rankRights = fields[1].GetUInt32(); + uint32 rankMoney = fields[2].GetUInt32(); + uint32 rankRID = fields[3].GetUInt32(); + + if(rankRID != m_ranks.size()+1) // guild_rank.rid always store rank+1 + broken_ranks = true; + + if(m_ranks.size()==GR_GUILDMASTER) // prevent loss leader rights + rankRights |= GR_RIGHT_ALL; + + AddRank(rankName,rankRights,rankMoney); + }while( result->NextRow() ); + delete result; + + if(m_ranks.size()==0) // empty rank table? + { + AddRank("Guild Master",GR_RIGHT_ALL,0); + broken_ranks = true; + } + + // guild_rank have wrong numbered ranks, repair + if(broken_ranks) + { + sLog.outError("Guild %u have broken `guild_rank` data, repairing...",GuildId); + CharacterDatabase.BeginTransaction(); + CharacterDatabase.PExecute("DELETE FROM guild_rank WHERE guildid='%u'", GuildId); + for(size_t i =0; i < m_ranks.size(); ++i) + { + // guild_rank.rid always store rank+1 + std::string name = m_ranks[i].name; + uint32 rights = m_ranks[i].rights; + CharacterDatabase.escape_string(name); + CharacterDatabase.PExecute( "INSERT INTO guild_rank (guildid,rid,rname,rights) VALUES ('%u', '%u', '%s', '%u')", GuildId, i+1, name.c_str(), rights); + } + CharacterDatabase.CommitTransaction(); + } + + return true; +} + +bool Guild::LoadMembersFromDB(uint32 GuildId) +{ + // 0 1 2 3 4 5 + QueryResult *result = CharacterDatabase.PQuery("SELECT guild_member.guid,rank, pnote, offnote, BankResetTimeMoney,BankRemMoney," + // 6 7 8 9 10 11 + "BankResetTimeTab0, BankRemSlotsTab0, BankResetTimeTab1, BankRemSlotsTab1, BankResetTimeTab2, BankRemSlotsTab2," + // 12 13 14 15 16 17 + "BankResetTimeTab3, BankRemSlotsTab3, BankResetTimeTab4, BankRemSlotsTab4, BankResetTimeTab5, BankRemSlotsTab5," + // 18 + "logout_time FROM guild_member LEFT JOIN characters ON characters.guid = guild_member.guid WHERE guildid = '%u'", GuildId); + + if(!result) + return false; + + do + { + Field *fields = result->Fetch(); + MemberSlot newmember; + newmember.RankId = fields[1].GetUInt32(); + uint64 guid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); + + // Player does not exist + if(!FillPlayerData(guid, &newmember)) + continue; + + newmember.Pnote = fields[2].GetCppString(); + newmember.OFFnote = fields[3].GetCppString(); + newmember.BankResetTimeMoney = fields[4].GetUInt32(); + newmember.BankRemMoney = fields[5].GetUInt32(); + for (int i = 0; i < GUILD_BANK_MAX_TABS; ++i) + { + newmember.BankResetTimeTab[i] = fields[6+(2*i)].GetUInt32(); + newmember.BankRemSlotsTab[i] = fields[7+(2*i)].GetUInt32(); + } + newmember.logout_time = fields[18].GetUInt64(); + members[GUID_LOPART(guid)] = newmember; + + }while( result->NextRow() ); + delete result; + + if(members.empty()) + return false; + + return true; +} + +bool Guild::FillPlayerData(uint64 guid, MemberSlot* memslot) +{ + std::string plName; + uint32 plLevel; + uint32 plClass; + uint32 plZone; + + Player* pl = objmgr.GetPlayer(guid); + if(pl) + { + plName = pl->GetName(); + plLevel = pl->getLevel(); + plClass = pl->getClass(); + plZone = pl->GetZoneId(); + } + else + { + if(!objmgr.GetPlayerNameByGUID(guid, plName)) // player doesn't exist + return false; + + plLevel = Player::GetUInt32ValueFromDB(UNIT_FIELD_LEVEL, guid); + if(plLevel<1||plLevel>255) // can be at broken `data` field + { + sLog.outError("Player (GUID: %u) has a broken data in field `characters`.`data`.",GUID_LOPART(guid)); + return false; + } + plZone = Player::GetZoneIdFromDB(guid); + + QueryResult *result = CharacterDatabase.PQuery("SELECT class FROM characters WHERE guid='%u'", GUID_LOPART(guid)); + if(!result) + return false; + plClass = (*result)[0].GetUInt32(); + if(plClass=MAX_CLASSES) // can be at broken `class` field + { + sLog.outError("Player (GUID: %u) has a broken data in field `characters`.`class`.",GUID_LOPART(guid)); + return false; + } + + delete result; + } + + memslot->name = plName; + memslot->level = plLevel; + memslot->Class = plClass; + memslot->zoneId = plZone; + + return(true); +} + +void Guild::LoadPlayerStatsByGuid(uint64 guid) +{ + MemberList::iterator itr = members.find(GUID_LOPART(guid)); + if (itr == members.end() ) + return; + + Player *pl = ObjectAccessor::FindPlayer(guid); + if(!pl) + return; + itr->second.name = pl->GetName(); + itr->second.level = pl->getLevel(); + itr->second.Class = pl->getClass(); +} + +void Guild::SetLeader(uint64 guid) +{ + leaderGuid = guid; + this->ChangeRank(guid, GR_GUILDMASTER); + + CharacterDatabase.PExecute("UPDATE guild SET leaderguid='%u' WHERE guildid='%u'", GUID_LOPART(guid), Id); +} + +void Guild::DelMember(uint64 guid, bool isDisbanding) +{ + if(this->leaderGuid == guid && !isDisbanding) + { + std::ostringstream ss; + ss<<"SELECT guid FROM guild_member WHERE guildid='"<SetLeader(newLeaderGUID); + + newLeader = objmgr.GetPlayer(newLeaderGUID); + if(newLeader) + { + newLeader->SetRank(GR_GUILDMASTER); + newLeaderName = newLeader->GetName(); + } + else + { + Player::SetUInt32ValueInDB(PLAYER_GUILDRANK, GR_GUILDMASTER, newLeaderGUID); + objmgr.GetPlayerNameByGUID(newLeaderGUID, newLeaderName); + } + + // when leader non-exist (at guild load with deleted leader only) not send broadcasts + if(objmgr.GetPlayerNameByGUID(guid, oldLeaderName)) + { + WorldPacket data(SMSG_GUILD_EVENT, (1+1+oldLeaderName.size()+1+newLeaderName.size()+1)); + data << (uint8)GE_LEADER_CHANGED; + data << (uint8)2; + data << oldLeaderName; + data << newLeaderName; + this->BroadcastPacket(&data); + + data.Initialize(SMSG_GUILD_EVENT, (1+1+oldLeaderName.size()+1)); + data << (uint8)GE_LEFT; + data << (uint8)1; + data << oldLeaderName; + this->BroadcastPacket(&data); + } + + sLog.outDebug( "WORLD: Sent (SMSG_GUILD_EVENT)" ); + } + else + { + this->Disband(); + return; + } + } + + members.erase(GUID_LOPART(guid)); + + Player *player = objmgr.GetPlayer(guid); + if(player) + { + player->SetInGuild(0); + player->SetRank(0); + } + else + { + Player::SetUInt32ValueInDB(PLAYER_GUILDID, 0, guid); + Player::SetUInt32ValueInDB(PLAYER_GUILDRANK, GR_GUILDMASTER, guid); + } + + CharacterDatabase.PExecute("DELETE FROM guild_member WHERE guid = '%u'", GUID_LOPART(guid)); +} + +void Guild::ChangeRank(uint64 guid, uint32 newRank) +{ + MemberList::iterator itr = members.find(GUID_LOPART(guid)); + if( itr != members.end() ) + itr->second.RankId = newRank; + + Player *player = objmgr.GetPlayer(guid); + if(player) + player->SetRank(newRank); + else + Player::SetUInt32ValueInDB(PLAYER_GUILDRANK, newRank, guid); + + CharacterDatabase.PExecute( "UPDATE guild_member SET rank='%u' WHERE guid='%u'", newRank, GUID_LOPART(guid) ); +} + +void Guild::SetPNOTE(uint64 guid,std::string pnote) +{ + MemberList::iterator itr = members.find(GUID_LOPART(guid)); + if( itr == members.end() ) + return; + + itr->second.Pnote = pnote; + + // pnote now can be used for encoding to DB + CharacterDatabase.escape_string(pnote); + CharacterDatabase.PExecute("UPDATE guild_member SET pnote = '%s' WHERE guid = '%u'", pnote.c_str(), itr->first); +} + +void Guild::SetOFFNOTE(uint64 guid,std::string offnote) +{ + MemberList::iterator itr = members.find(GUID_LOPART(guid)); + if( itr == members.end() ) + return; + itr->second.OFFnote = offnote; + // offnote now can be used for encoding to DB + CharacterDatabase.escape_string(offnote); + CharacterDatabase.PExecute("UPDATE guild_member SET offnote = '%s' WHERE guid = '%u'", offnote.c_str(), itr->first); +} + +void Guild::BroadcastToGuild(WorldSession *session, std::string msg, uint32 language) +{ + if (session && session->GetPlayer() && HasRankRight(session->GetPlayer()->GetRank(),GR_RIGHT_GCHATSPEAK)) + { + WorldPacket data; + ChatHandler(session).FillMessageData(&data, CHAT_MSG_GUILD, language, 0, msg.c_str()); + + for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr) + { + Player *pl = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER)); + + if (pl && pl->GetSession() && HasRankRight(pl->GetRank(),GR_RIGHT_GCHATLISTEN) && !pl->GetSocial()->HasIgnore(session->GetPlayer()->GetGUIDLow()) ) + pl->GetSession()->SendPacket(&data); + } + } +} + +void Guild::BroadcastToOfficers(WorldSession *session, std::string msg, uint32 language) +{ + if (session && session->GetPlayer() && HasRankRight(session->GetPlayer()->GetRank(),GR_RIGHT_OFFCHATSPEAK)) + { + for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) + { + WorldPacket data; + ChatHandler::FillMessageData(&data, session, CHAT_MSG_OFFICER, language, NULL, 0, msg.c_str(),NULL); + + Player *pl = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER)); + + if (pl && pl->GetSession() && HasRankRight(pl->GetRank(),GR_RIGHT_OFFCHATLISTEN) && !pl->GetSocial()->HasIgnore(session->GetPlayer()->GetGUIDLow())) + pl->GetSession()->SendPacket(&data); + } + } +} + +void Guild::BroadcastPacket(WorldPacket *packet) +{ + for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) + { + Player *player = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER)); + if(player) + player->GetSession()->SendPacket(packet); + } +} + +void Guild::BroadcastPacketToRank(WorldPacket *packet, uint32 rankId) +{ + for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) + { + if (itr->second.RankId == rankId) + { + Player *player = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER)); + if(player) + player->GetSession()->SendPacket(packet); + } + } +} + +void Guild::CreateRank(std::string name_,uint32 rights) +{ + if(m_ranks.size() >= GUILD_MAX_RANKS) + return; + + AddRank(name_,rights,0); + + for (int i = 0; i < purchased_tabs; ++i) + { + CreateBankRightForTab(m_ranks.size()-1, uint8(i)); + } + + // guild_rank.rid always store rank+1 value + + // name now can be used for encoding to DB + CharacterDatabase.escape_string(name_); + CharacterDatabase.PExecute( "INSERT INTO guild_rank (guildid,rid,rname,rights) VALUES ('%u', '%u', '%s', '%u')", Id, m_ranks.size(), name_.c_str(), rights ); +} + +void Guild::AddRank(std::string name_,uint32 rights, uint32 money) +{ + m_ranks.push_back(RankInfo(name_,rights,money)); +} + +void Guild::DelRank() +{ + if(m_ranks.empty()) + return; + + // guild_rank.rid always store rank+1 value + uint32 rank = m_ranks.size()-1; + CharacterDatabase.PExecute("DELETE FROM guild_rank WHERE rid>='%u' AND guildid='%u'", (rank+1), Id); + + m_ranks.pop_back(); +} + +std::string Guild::GetRankName(uint32 rankId) +{ + if(rankId >= m_ranks.size()) + return ""; + + return m_ranks[rankId].name; +} + +uint32 Guild::GetRankRights(uint32 rankId) +{ + if(rankId >= m_ranks.size()) + return 0; + + return m_ranks[rankId].rights; +} + +void Guild::SetRankName(uint32 rankId, std::string name_) +{ + if(rankId >= m_ranks.size()) + return; + + m_ranks[rankId].name = name_; + + // name now can be used for encoding to DB + CharacterDatabase.escape_string(name_); + CharacterDatabase.PExecute("UPDATE guild_rank SET rname='%s' WHERE rid='%u' AND guildid='%u'", name_.c_str(), (rankId+1), Id); +} + +void Guild::SetRankRights(uint32 rankId, uint32 rights) +{ + if(rankId >= m_ranks.size()) + return; + + m_ranks[rankId].rights = rights; + + CharacterDatabase.PExecute("UPDATE guild_rank SET rights='%u' WHERE rid='%u' AND guildid='%u'", rights, (rankId+1), Id); +} + +void Guild::Disband() +{ + WorldPacket data(SMSG_GUILD_EVENT, 1); + data << (uint8)GE_DISBANDED; + this->BroadcastPacket(&data); + + while (!members.empty()) + { + MemberList::iterator itr = members.begin(); + DelMember(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER), true); + } + + CharacterDatabase.BeginTransaction(); + CharacterDatabase.PExecute("DELETE FROM guild WHERE guildid = '%u'",Id); + CharacterDatabase.PExecute("DELETE FROM guild_rank WHERE guildid = '%u'",Id); + CharacterDatabase.PExecute("DELETE FROM guild_bank_tab WHERE guildid = '%u'",Id); + CharacterDatabase.PExecute("DELETE FROM guild_bank_item WHERE guildid = '%u'",Id); + CharacterDatabase.PExecute("DELETE FROM guild_bank_right WHERE guildid = '%u'",Id); + CharacterDatabase.PExecute("DELETE FROM guild_bank_eventlog WHERE guildid = '%u'",Id); + CharacterDatabase.PExecute("DELETE FROM guild_eventlog WHERE guildid = '%u'",Id); + CharacterDatabase.CommitTransaction(); + objmgr.RemoveGuild(this); +} + +void Guild::Roster(WorldSession *session) +{ + // we can only guess size + WorldPacket data(SMSG_GUILD_ROSTER, (4+MOTD.length()+1+GINFO.length()+1+4+m_ranks.size()*(4+4+GUILD_BANK_MAX_TABS*(4+4))+members.size()*50)); + data << (uint32)members.size(); + data << MOTD; + data << GINFO; + + data << (uint32)m_ranks.size(); + for (RankList::iterator ritr = m_ranks.begin(); ritr != m_ranks.end();++ritr) + { + data << (uint32)ritr->rights; + data << (uint32)ritr->BankMoneyPerDay; // count of: withdraw gold(gold/day) Note: in game set gold, in packet set bronze. + for (int i = 0; i < GUILD_BANK_MAX_TABS; ++i) + { + data << (uint32)ritr->TabRight[i]; // for TAB_i rights: view tabs = 0x01, deposit items =0x02 + data << (uint32)ritr->TabSlotPerDay[i]; // for TAB_i count of: withdraw items(stack/day) + } + } + for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) + { + if (Player *pl = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER))) + { + data << (uint64)pl->GetGUID(); + data << (uint8)1; + data << (std::string)pl->GetName(); + data << (uint32)itr->second.RankId; + data << (uint8)pl->getLevel(); + data << (uint8)pl->getClass(); + data << (uint8)0; // new 2.4.0 + data << (uint32)pl->GetZoneId(); + data << itr->second.Pnote; + data << itr->second.OFFnote; + } + else + { + data << uint64(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER)); + data << (uint8)0; + data << itr->second.name; + data << (uint32)itr->second.RankId; + data << (uint8)itr->second.level; + data << (uint8)itr->second.Class; + data << (uint8)0; // new 2.4.0 + data << (uint32)itr->second.zoneId; + data << (float(time(NULL)-itr->second.logout_time) / DAY); + data << itr->second.Pnote; + data << itr->second.OFFnote; + } + } + session->SendPacket(&data);; + sLog.outDebug( "WORLD: Sent (SMSG_GUILD_ROSTER)" ); +} + +void Guild::Query(WorldSession *session) +{ + WorldPacket data(SMSG_GUILD_QUERY_RESPONSE, (8*32+200));// we can only guess size + + data << Id; + data << name; + RankList::iterator itr; + for (size_t i = 0 ; i < 10; ++i) // show always 10 ranks + { + if(i < m_ranks.size()) + data << m_ranks[i].name; + else + data << (uint8)0; // null string + } + + data << uint32(EmblemStyle); + data << uint32(EmblemColor); + data << uint32(BorderStyle); + data << uint32(BorderColor); + data << uint32(BackgroundColor); + + session->SendPacket( &data ); + sLog.outDebug( "WORLD: Sent (SMSG_GUILD_QUERY_RESPONSE)" ); +} + +void Guild::SetEmblem(uint32 emblemStyle, uint32 emblemColor, uint32 borderStyle, uint32 borderColor, uint32 backgroundColor) +{ + this->EmblemStyle = emblemStyle; + this->EmblemColor = emblemColor; + this->BorderStyle = borderStyle; + this->BorderColor = borderColor; + this->BackgroundColor = backgroundColor; + + CharacterDatabase.PExecute("UPDATE guild SET EmblemStyle=%u, EmblemColor=%u, BorderStyle=%u, BorderColor=%u, BackgroundColor=%u WHERE guildid = %u", EmblemStyle, EmblemColor, BorderStyle, BorderColor, BackgroundColor, Id); +} + +void Guild::UpdateLogoutTime(uint64 guid) +{ + MemberList::iterator itr = members.find(GUID_LOPART(guid)); + if (itr == members.end() ) + return; + + itr->second.logout_time = time(NULL); + + if (m_onlinemembers > 0) + --m_onlinemembers; + else + { + UnloadGuildBank(); + UnloadGuildEventlog(); + } +} + +// ************************************************* +// Guild Eventlog part +// ************************************************* +// Display guild eventlog +void Guild::DisplayGuildEventlog(WorldSession *session) +{ + // Load guild eventlog, if not already done + if (!m_eventlogloaded) + LoadGuildEventLogFromDB(); + + // Sending result + WorldPacket data(MSG_GUILD_EVENT_LOG_QUERY, 0); + // count, max count == 100 + data << uint8(m_GuildEventlog.size()); + for (GuildEventlog::const_iterator itr = m_GuildEventlog.begin(); itr != m_GuildEventlog.end(); ++itr) + { + // Event type + data << uint8((*itr)->EventType); + // Player 1 + data << uint64((*itr)->PlayerGuid1); + // Player 2 not for left/join guild events + if( (*itr)->EventType != GUILD_EVENT_LOG_JOIN_GUILD && (*itr)->EventType != GUILD_EVENT_LOG_LEAVE_GUILD ) + data << uint64((*itr)->PlayerGuid2); + // New Rank - only for promote/demote guild events + if( (*itr)->EventType == GUILD_EVENT_LOG_PROMOTE_PLAYER || (*itr)->EventType == GUILD_EVENT_LOG_DEMOTE_PLAYER ) + data << uint8((*itr)->NewRank); + // Event timestamp + data << uint32(time(NULL)-(*itr)->TimeStamp); + } + session->SendPacket(&data); + sLog.outDebug("WORLD: Sent (MSG_GUILD_EVENT_LOG_QUERY)"); +} + +// Load guild eventlog from DB +void Guild::LoadGuildEventLogFromDB() +{ + // Return if already loaded + if (m_eventlogloaded) + return; + + QueryResult *result = CharacterDatabase.PQuery("SELECT LogGuid, EventType, PlayerGuid1, PlayerGuid2, NewRank, TimeStamp FROM guild_eventlog WHERE guildid=%u ORDER BY LogGuid DESC LIMIT %u", Id, GUILD_EVENTLOG_MAX_ENTRIES); + if(!result) + return; + do + { + Field *fields = result->Fetch(); + GuildEventlogEntry *NewEvent = new GuildEventlogEntry; + // Fill entry + NewEvent->LogGuid = fields[0].GetUInt32(); + NewEvent->EventType = fields[1].GetUInt8(); + NewEvent->PlayerGuid1 = fields[2].GetUInt32(); + NewEvent->PlayerGuid2 = fields[3].GetUInt32(); + NewEvent->NewRank = fields[4].GetUInt8(); + NewEvent->TimeStamp = fields[5].GetUInt64(); + // Add entry to map + m_GuildEventlog.push_front(NewEvent); + + } while( result->NextRow() ); + delete result; + + // Check lists size in case to many event entries in db + // This cases can happen only if a crash occured somewhere and table has too many log entries + if (!m_GuildEventlog.empty()) + { + CharacterDatabase.PExecute("DELETE FROM guild_eventlog WHERE guildid=%u AND LogGuid < %u", Id, m_GuildEventlog.front()->LogGuid); + } + m_eventlogloaded = true; +} + +// Unload guild eventlog +void Guild::UnloadGuildEventlog() +{ + if (!m_eventlogloaded) + return; + GuildEventlogEntry *EventLogEntry; + if( !m_GuildEventlog.empty() ) + { + do + { + EventLogEntry = *(m_GuildEventlog.begin()); + m_GuildEventlog.pop_front(); + delete EventLogEntry; + }while( !m_GuildEventlog.empty() ); + } + m_eventlogloaded = false; +} + +// This will renum guids used at load to prevent always going up until infinit +void Guild::RenumGuildEventlog() +{ + QueryResult *result = CharacterDatabase.PQuery("SELECT Min(LogGuid), Max(LogGuid) FROM guild_eventlog WHERE guildid = %u", Id); + if(!result) + return; + + Field *fields = result->Fetch(); + CharacterDatabase.PExecute("UPDATE guild_eventlog SET LogGuid=LogGuid-%u+1 WHERE guildid=%u ORDER BY LogGuid %s",fields[0].GetUInt32(), Id, fields[0].GetUInt32()?"ASC":"DESC"); + GuildEventlogMaxGuid = fields[1].GetUInt32()+1; + delete result; +} + +// Add entry to guild eventlog +void Guild::LogGuildEvent(uint8 EventType, uint32 PlayerGuid1, uint32 PlayerGuid2, uint8 NewRank) +{ + GuildEventlogEntry *NewEvent = new GuildEventlogEntry; + // Fill entry + NewEvent->LogGuid = GuildEventlogMaxGuid++; + NewEvent->EventType = EventType; + NewEvent->PlayerGuid1 = PlayerGuid1; + NewEvent->PlayerGuid2 = PlayerGuid2; + NewEvent->NewRank = NewRank; + NewEvent->TimeStamp = uint32(time(NULL)); + // Check max entry limit and delete from db if needed + if (m_GuildEventlog.size() > GUILD_EVENTLOG_MAX_ENTRIES) + { + GuildEventlogEntry *OldEvent = *(m_GuildEventlog.begin()); + m_GuildEventlog.pop_front(); + CharacterDatabase.PExecute("DELETE FROM guild_eventlog WHERE guildid='%u' AND LogGuid='%u'", Id, OldEvent->LogGuid); + delete OldEvent; + } + // Add entry to map + m_GuildEventlog.push_back(NewEvent); + // Add new eventlog entry into DB + CharacterDatabase.PExecute("INSERT INTO guild_eventlog (guildid, LogGuid, EventType, PlayerGuid1, PlayerGuid2, NewRank, TimeStamp) VALUES ('%u','%u','%u','%u','%u','%u','" I64FMTD "')", + Id, NewEvent->LogGuid, uint32(NewEvent->EventType), NewEvent->PlayerGuid1, NewEvent->PlayerGuid2, uint32(NewEvent->NewRank), NewEvent->TimeStamp); +} + +// ************************************************* +// Guild Bank part +// ************************************************* +// Bank content related +void Guild::DisplayGuildBankContent(WorldSession *session, uint8 TabId) +{ + WorldPacket data(SMSG_GUILD_BANK_LIST,1200); + + GuildBankTab const* tab = GetBankTab(TabId); + if (!tab) + return; + + if(!IsMemberHaveRights(session->GetPlayer()->GetGUIDLow(),TabId,GUILD_BANK_RIGHT_VIEW_TAB)) + return; + + data << uint64(GetGuildBankMoney()); + data << uint8(TabId); + // remaining slots for today + data << uint32(GetMemberSlotWithdrawRem(session->GetPlayer()->GetGUIDLow(), TabId)); + data << uint8(0); // Tell client this is a tab content packet + + data << uint8(GUILD_BANK_MAX_SLOTS); + + for (int i=0; iSendPacket(&data); + + sLog.outDebug("WORLD: Sent (SMSG_GUILD_BANK_LIST)"); +} + +void Guild::DisplayGuildBankMoneyUpdate() +{ + WorldPacket data(SMSG_GUILD_BANK_LIST, 8+1+4+1+1); + + data << uint64(GetGuildBankMoney()); + data << uint8(0); + // remaining slots for today + + size_t rempos = data.wpos(); + data << uint32(0); // will be filled later + data << uint8(0); // Tell client this is a tab content packet + + data << uint8(0); // not send items + + BroadcastPacket(&data); + + sLog.outDebug("WORLD: Sent (SMSG_GUILD_BANK_LIST)"); +} + +void Guild::DisplayGuildBankContentUpdate(uint8 TabId, int32 slot1, int32 slot2) +{ + GuildBankTab const* tab = GetBankTab(TabId); + if (!tab) + return; + + WorldPacket data(SMSG_GUILD_BANK_LIST,1200); + + data << uint64(GetGuildBankMoney()); + data << uint8(TabId); + // remaining slots for today + + size_t rempos = data.wpos(); + data << uint32(0); // will be filled later + data << uint8(0); // Tell client this is a tab content packet + + if(slot2==-1) // single item in slot1 + { + data << uint8(1); + + AppendDisplayGuildBankSlot(data, tab, slot1); + } + else // 2 items (in slot1 and slot2) + { + data << uint8(2); + + if(slot1 > slot2) + std::swap(slot1,slot2); + + AppendDisplayGuildBankSlot(data, tab, slot1); + AppendDisplayGuildBankSlot(data, tab, slot2); + } + + for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) + { + Player *player = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER)); + if(!player) + continue; + + if(!IsMemberHaveRights(itr->first,TabId,GUILD_BANK_RIGHT_VIEW_TAB)) + continue; + + data.put(rempos,uint32(GetMemberSlotWithdrawRem(player->GetGUIDLow(), TabId))); + + player->GetSession()->SendPacket(&data); + } + + sLog.outDebug("WORLD: Sent (SMSG_GUILD_BANK_LIST)"); +} + +void Guild::DisplayGuildBankContentUpdate(uint8 TabId, GuildItemPosCountVec const& slots) +{ + GuildBankTab const* tab = GetBankTab(TabId); + if (!tab) + return; + + WorldPacket data(SMSG_GUILD_BANK_LIST,1200); + + data << uint64(GetGuildBankMoney()); + data << uint8(TabId); + // remaining slots for today + + size_t rempos = data.wpos(); + data << uint32(0); // will be filled later + data << uint8(0); // Tell client this is a tab content packet + + data << uint8(slots.size()); // updates count + + for(GuildItemPosCountVec::const_iterator itr = slots.begin(); itr != slots.end(); ++itr) + AppendDisplayGuildBankSlot(data, tab, itr->slot); + + for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) + { + Player *player = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER)); + if(!player) + continue; + + if(!IsMemberHaveRights(itr->first,TabId,GUILD_BANK_RIGHT_VIEW_TAB)) + continue; + + data.put(rempos,uint32(GetMemberSlotWithdrawRem(player->GetGUIDLow(), TabId))); + + player->GetSession()->SendPacket(&data); + } + + sLog.outDebug("WORLD: Sent (SMSG_GUILD_BANK_LIST)"); +} + +Item* Guild::GetItem(uint8 TabId, uint8 SlotId) +{ + if (TabId >= m_TabListMap.size() || SlotId >= GUILD_BANK_MAX_SLOTS) + return NULL; + return m_TabListMap[TabId]->Slots[SlotId]; +} + +// ************************************************* +// Tab related + +void Guild::DisplayGuildBankTabsInfo(WorldSession *session) +{ + // Time to load bank if not already done + if (!m_bankloaded) + LoadGuildBankFromDB(); + + WorldPacket data(SMSG_GUILD_BANK_LIST, 500); + + data << uint64(GetGuildBankMoney()); + data << uint8(0); // TabInfo packet must be for TabId 0 + data << uint32(0xFFFFFFFF); // bit 9 must be set for this packet to work + data << uint8(1); // Tell Client this is a TabInfo packet + + data << uint8(purchased_tabs); // here is the number of tabs + + for(int i = 0; i < purchased_tabs; ++i) + { + data << m_TabListMap[i]->Name.c_str(); + data << m_TabListMap[i]->Icon.c_str(); + } + data << uint8(0); // Do not send tab content + session->SendPacket(&data); + + sLog.outDebug("WORLD: Sent (SMSG_GUILD_BANK_LIST)"); +} + +void Guild::CreateNewBankTab() +{ + if (purchased_tabs >= GUILD_BANK_MAX_TABS) + return; + + ++purchased_tabs; + + GuildBankTab* AnotherTab = new GuildBankTab; + memset(AnotherTab->Slots, 0, GUILD_BANK_MAX_SLOTS * sizeof(Item*)); + m_TabListMap.resize(purchased_tabs); + m_TabListMap[purchased_tabs-1] = AnotherTab; + + CharacterDatabase.BeginTransaction(); + CharacterDatabase.PExecute("DELETE FROM guild_bank_tab WHERE guildid='%u' AND TabId='%u'", Id, uint32(purchased_tabs-1)); + CharacterDatabase.PExecute("INSERT INTO guild_bank_tab (guildid,TabId) VALUES ('%u','%u')", Id, uint32(purchased_tabs-1)); + CharacterDatabase.CommitTransaction(); +} + +void Guild::SetGuildBankTabInfo(uint8 TabId, std::string Name, std::string Icon) +{ + if (TabId >= GUILD_BANK_MAX_TABS) + return; + if (TabId >= m_TabListMap.size()) + return; + + if (!m_TabListMap[TabId]) + return; + + if(m_TabListMap[TabId]->Name == Name && m_TabListMap[TabId]->Icon == Icon) + return; + + m_TabListMap[TabId]->Name = Name; + m_TabListMap[TabId]->Icon = Icon; + + CharacterDatabase.escape_string(Name); + CharacterDatabase.escape_string(Icon); + CharacterDatabase.PExecute("UPDATE guild_bank_tab SET TabName='%s',TabIcon='%s' WHERE guildid='%u' AND TabId='%u'", Name.c_str(), Icon.c_str(), Id, uint32(TabId)); +} + +void Guild::CreateBankRightForTab(uint32 rankId, uint8 TabId) +{ + sLog.outDebug("CreateBankRightForTab. rank: %u, TabId: %u", rankId, uint32(TabId)); + if (rankId >= m_ranks.size() || TabId >= GUILD_BANK_MAX_TABS) + return; + + m_ranks[rankId].TabRight[TabId]=0; + m_ranks[rankId].TabSlotPerDay[TabId]=0; + CharacterDatabase.BeginTransaction(); + CharacterDatabase.PExecute("DELETE FROM guild_bank_right WHERE guildid = '%u' AND TabId = '%u' AND rid = '%u'", Id, uint32(TabId), rankId); + CharacterDatabase.PExecute("INSERT INTO guild_bank_right (guildid,TabId,rid) VALUES ('%u','%u','%u')", Id, uint32(TabId), rankId); + CharacterDatabase.CommitTransaction(); +} + +uint32 Guild::GetBankRights(uint32 rankId, uint8 TabId) const +{ + if(rankId >= m_ranks.size() || TabId >= GUILD_BANK_MAX_TABS) + return 0; + + return m_ranks[rankId].TabRight[TabId]; +} + +// ************************************************* +// Guild bank loading/unloading related + +// This load should be called when the bank is first accessed by a guild member +void Guild::LoadGuildBankFromDB() +{ + if (m_bankloaded) + return; + + m_bankloaded = true; + LoadGuildBankEventLogFromDB(); + + // 0 1 2 3 + QueryResult *result = CharacterDatabase.PQuery("SELECT TabId, TabName, TabIcon, TabText FROM guild_bank_tab WHERE guildid='%u' ORDER BY TabId", Id); + if(!result) + { + purchased_tabs = 0; + return; + } + + m_TabListMap.resize(purchased_tabs); + do + { + Field *fields = result->Fetch(); + uint8 TabId = fields[0].GetUInt8(); + + GuildBankTab *NewTab = new GuildBankTab; + memset(NewTab->Slots, 0, GUILD_BANK_MAX_SLOTS * sizeof(Item*)); + + NewTab->Name = fields[1].GetCppString(); + NewTab->Icon = fields[2].GetCppString(); + NewTab->Text = fields[3].GetCppString(); + + m_TabListMap[TabId] = NewTab; + }while( result->NextRow() ); + + delete result; + + // 0 1 2 3 + result = CharacterDatabase.PQuery("SELECT TabId, SlotId, item_guid, item_entry FROM guild_bank_item WHERE guildid='%u' ORDER BY TabId", Id); + if(!result) + return; + + do + { + Field *fields = result->Fetch(); + uint8 TabId = fields[0].GetUInt8(); + uint8 SlotId = fields[1].GetUInt8(); + uint32 ItemGuid = fields[2].GetUInt32(); + uint32 ItemEntry = fields[3].GetUInt32(); + + if (TabId >= purchased_tabs || TabId >= GUILD_BANK_MAX_TABS) + { + sLog.outError( "Guild::LoadGuildBankFromDB: Invalid tab for item (GUID: %u id: #%u) in guild bank, skipped.", ItemGuid,ItemEntry); + continue; + } + + if (SlotId >= GUILD_BANK_MAX_SLOTS) + { + sLog.outError( "Guild::LoadGuildBankFromDB: Invalid slot for item (GUID: %u id: #%u) in guild bank, skipped.", ItemGuid,ItemEntry); + continue; + } + + ItemPrototype const *proto = objmgr.GetItemPrototype(ItemEntry); + + if(!proto) + { + sLog.outError( "Guild::LoadGuildBankFromDB: Unknown item (GUID: %u id: #%u) in guild bank, skipped.", ItemGuid,ItemEntry); + continue; + } + + Item *pItem = NewItemOrBag(proto); + if(!pItem->LoadFromDB(ItemGuid, 0)) + { + CharacterDatabase.PExecute("DELETE FROM guild_bank_item WHERE guildid='%u' AND TabId='%u' AND SlotId='%u'", Id, uint32(TabId), uint32(SlotId)); + sLog.outError("Item GUID %u not found in item_instance, deleting from Guild Bank!", ItemGuid); + delete pItem; + continue; + } + + pItem->AddToWorld(); + m_TabListMap[TabId]->Slots[SlotId] = pItem; + }while( result->NextRow() ); + + delete result; +} + +// This unload should be called when the last member of the guild gets offline +void Guild::UnloadGuildBank() +{ + if (!m_bankloaded) + return; + for (uint8 i = 0 ; i < purchased_tabs ; ++i ) + { + for (uint8 j = 0 ; j < GUILD_BANK_MAX_SLOTS ; ++j) + { + if (m_TabListMap[i]->Slots[j]) + { + m_TabListMap[i]->Slots[j]->RemoveFromWorld(); + delete m_TabListMap[i]->Slots[j]; + } + } + delete m_TabListMap[i]; + } + m_TabListMap.clear(); + + UnloadGuildBankEventLog(); + m_bankloaded = false; +} + +// ************************************************* +// Money deposit/withdraw related + +void Guild::SendMoneyInfo(WorldSession *session, uint32 LowGuid) +{ + WorldPacket data(MSG_GUILD_BANK_MONEY_WITHDRAWN, 4); + data << uint32(GetMemberMoneyWithdrawRem(LowGuid)); + session->SendPacket(&data); + sLog.outDebug("WORLD: Sent MSG_GUILD_BANK_MONEY_WITHDRAWN"); +} + +bool Guild::MemberMoneyWithdraw(uint32 amount, uint32 LowGuid) +{ + uint32 MoneyWithDrawRight = GetMemberMoneyWithdrawRem(LowGuid); + + if (MoneyWithDrawRight < amount || GetGuildBankMoney() < amount) + return false; + + SetBankMoney(GetGuildBankMoney()-amount); + + if (MoneyWithDrawRight < WITHDRAW_MONEY_UNLIMITED) + { + MemberList::iterator itr = members.find(LowGuid); + if (itr == members.end() ) + return false; + itr->second.BankRemMoney -= amount; + CharacterDatabase.PExecute("UPDATE guild_member SET BankRemMoney='%u' WHERE guildid='%u' AND guid='%u'", + itr->second.BankRemMoney, Id, LowGuid); + } + return true; +} + +void Guild::SetBankMoney(int64 money) +{ + if (money < 0) // I don't know how this happens, it does!! + money = 0; + guildbank_money = money; + + CharacterDatabase.PExecute("UPDATE guild SET BankMoney='" I64FMTD "' WHERE guildid='%u'", money, Id); +} + +// ************************************************* +// Item per day and money per day related + +bool Guild::MemberItemWithdraw(uint8 TabId, uint32 LowGuid) +{ + uint32 SlotsWithDrawRight = GetMemberSlotWithdrawRem(LowGuid, TabId); + + if (SlotsWithDrawRight == 0) + return false; + + if (SlotsWithDrawRight < WITHDRAW_SLOT_UNLIMITED) + { + MemberList::iterator itr = members.find(LowGuid); + if (itr == members.end() ) + return false; + --itr->second.BankRemSlotsTab[TabId]; + CharacterDatabase.PExecute("UPDATE guild_member SET BankRemSlotsTab%u='%u' WHERE guildid='%u' AND guid='%u'", + uint32(TabId), itr->second.BankRemSlotsTab[TabId], Id, LowGuid); + } + return true; +} + +bool Guild::IsMemberHaveRights(uint32 LowGuid, uint8 TabId, uint32 rights) const +{ + MemberList::const_iterator itr = members.find(LowGuid); + if (itr == members.end() ) + return false; + + if (itr->second.RankId == GR_GUILDMASTER) + return true; + + return (GetBankRights(itr->second.RankId,TabId) & rights)==rights; +} + +uint32 Guild::GetMemberSlotWithdrawRem(uint32 LowGuid, uint8 TabId) +{ + MemberList::iterator itr = members.find(LowGuid); + if (itr == members.end() ) + return 0; + + if (itr->second.RankId == GR_GUILDMASTER) + return WITHDRAW_SLOT_UNLIMITED; + + if((GetBankRights(itr->second.RankId,TabId) & GUILD_BANK_RIGHT_VIEW_TAB)!=GUILD_BANK_RIGHT_VIEW_TAB) + return 0; + + uint32 curTime = uint32(time(NULL)/MINUTE); + if (curTime - itr->second.BankResetTimeTab[TabId] >= 24*HOUR/MINUTE) + { + itr->second.BankResetTimeTab[TabId] = curTime; + itr->second.BankRemSlotsTab[TabId] = GetBankSlotPerDay(itr->second.RankId, TabId); + CharacterDatabase.PExecute("UPDATE guild_member SET BankResetTimeTab%u='%u',BankRemSlotsTab%u='%u' WHERE guildid='%u' AND guid='%u'", + uint32(TabId), itr->second.BankResetTimeTab[TabId], uint32(TabId), itr->second.BankRemSlotsTab[TabId], Id, LowGuid); + } + return itr->second.BankRemSlotsTab[TabId]; +} + +uint32 Guild::GetMemberMoneyWithdrawRem(uint32 LowGuid) +{ + MemberList::iterator itr = members.find(LowGuid); + if (itr == members.end() ) + return 0; + + if (itr->second.RankId == GR_GUILDMASTER) + return WITHDRAW_MONEY_UNLIMITED; + + uint32 curTime = uint32(time(NULL)/MINUTE); // minutes + // 24 hours + if (curTime > itr->second.BankResetTimeMoney + 24*HOUR/MINUTE) + { + itr->second.BankResetTimeMoney = curTime; + itr->second.BankRemMoney = GetBankMoneyPerDay(itr->second.RankId); + CharacterDatabase.PExecute("UPDATE guild_member SET BankResetTimeMoney='%u',BankRemMoney='%u' WHERE guildid='%u' AND guid='%u'", + itr->second.BankResetTimeMoney, itr->second.BankRemMoney, Id, LowGuid); + } + return itr->second.BankRemMoney; +} + +void Guild::SetBankMoneyPerDay(uint32 rankId, uint32 money) +{ + if (rankId >= m_ranks.size()) + return; + + if (rankId == GR_GUILDMASTER) + money = WITHDRAW_MONEY_UNLIMITED; + + m_ranks[rankId].BankMoneyPerDay = money; + + for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) + if (itr->second.RankId == rankId) + itr->second.BankResetTimeMoney = 0; + + CharacterDatabase.PExecute("UPDATE guild_rank SET BankMoneyPerDay='%u' WHERE rid='%u' AND guildid='%u'", money, (rankId+1), Id); + CharacterDatabase.PExecute("UPDATE guild_member SET BankResetTimeMoney='0' WHERE guildid='%u' AND rank='%u'", Id, rankId); +} + +void Guild::SetBankRightsAndSlots(uint32 rankId, uint8 TabId, uint32 right, uint32 nbSlots, bool db) +{ + if(rankId >= m_ranks.size() || + TabId >= GUILD_BANK_MAX_TABS || + TabId >= purchased_tabs) + return; + + if (rankId == GR_GUILDMASTER) + { + nbSlots = WITHDRAW_SLOT_UNLIMITED; + right = GUILD_BANK_RIGHT_FULL; + } + + m_ranks[rankId].TabSlotPerDay[TabId]=nbSlots; + m_ranks[rankId].TabRight[TabId]=right; + + if (db) + { + for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) + if (itr->second.RankId == rankId) + for (int i = 0; i < GUILD_BANK_MAX_TABS; ++i) + itr->second.BankResetTimeTab[i] = 0; + + CharacterDatabase.PExecute("DELETE FROM guild_bank_right WHERE guildid='%u' AND TabId='%u' AND rid='%u'", Id, uint32(TabId), rankId); + CharacterDatabase.PExecute("INSERT INTO guild_bank_right (guildid,TabId,rid,gbright,SlotPerDay) VALUES " + "('%u','%u','%u','%u','%u')", Id, uint32(TabId), rankId, m_ranks[rankId].TabRight[TabId], m_ranks[rankId].TabSlotPerDay[TabId]); + CharacterDatabase.PExecute("UPDATE guild_member SET BankResetTimeTab%u='0' WHERE guildid='%u' AND rank='%u'", uint32(TabId), Id, rankId); + } +} + +uint32 Guild::GetBankMoneyPerDay(uint32 rankId) +{ + if(rankId >= m_ranks.size()) + return 0; + + if (rankId == GR_GUILDMASTER) + return WITHDRAW_MONEY_UNLIMITED; + return m_ranks[rankId].BankMoneyPerDay; +} + +uint32 Guild::GetBankSlotPerDay(uint32 rankId, uint8 TabId) +{ + if(rankId >= m_ranks.size() || TabId >= GUILD_BANK_MAX_TABS) + return 0; + + if (rankId == GR_GUILDMASTER) + return WITHDRAW_SLOT_UNLIMITED; + return m_ranks[rankId].TabSlotPerDay[TabId]; +} + +// ************************************************* +// Rights per day related + +void Guild::LoadBankRightsFromDB(uint32 GuildId) +{ + // 0 1 2 3 + QueryResult *result = CharacterDatabase.PQuery("SELECT TabId, rid, gbright, SlotPerDay FROM guild_bank_right WHERE guildid = '%u' ORDER BY TabId", GuildId); + + if(!result) + return; + + do + { + Field *fields = result->Fetch(); + uint8 TabId = fields[0].GetUInt8(); + uint32 rankId = fields[1].GetUInt32(); + uint16 right = fields[2].GetUInt16(); + uint16 SlotPerDay = fields[3].GetUInt16(); + + SetBankRightsAndSlots(rankId, TabId, right, SlotPerDay, false); + + }while( result->NextRow() ); + delete result; + + return; +} + +// ************************************************* +// Bank log related + +void Guild::LoadGuildBankEventLogFromDB() +{ + // We can't add a limit as in Guild::LoadGuildEventLogFromDB since we fetch both money and bank log and know nothing about the composition + // 0 1 2 3 4 5 6 7 + QueryResult *result = CharacterDatabase.PQuery("SELECT LogGuid, LogEntry, TabId, PlayerGuid, ItemOrMoney, ItemStackCount, DestTabId, TimeStamp FROM guild_bank_eventlog WHERE guildid='%u' ORDER BY TimeStamp DESC", Id); + if(!result) + return; + + do + { + Field *fields = result->Fetch(); + GuildBankEvent *NewEvent = new GuildBankEvent; + + NewEvent->LogGuid = fields[0].GetUInt32(); + NewEvent->LogEntry = fields[1].GetUInt8(); + uint8 TabId = fields[2].GetUInt8(); + NewEvent->PlayerGuid = fields[3].GetUInt32(); + NewEvent->ItemOrMoney = fields[4].GetUInt32(); + NewEvent->ItemStackCount = fields[5].GetUInt8(); + NewEvent->DestTabId = fields[6].GetUInt8(); + NewEvent->TimeStamp = fields[7].GetUInt64(); + + if (TabId >= GUILD_BANK_MAX_TABS) + { + sLog.outError( "Guild::LoadGuildBankEventLogFromDB: Invalid tabid '%u' for guild bank log entry (guild: '%s', LogGuid: %u), skipped.", TabId, GetName().c_str(), NewEvent->LogGuid); + delete NewEvent; + continue; + } + if (NewEvent->isMoneyEvent() && m_GuildBankEventLog_Money.size() >= GUILD_BANK_MAX_LOGS + || m_GuildBankEventLog_Item[TabId].size() >= GUILD_BANK_MAX_LOGS) + { + delete NewEvent; + continue; + } + if (NewEvent->isMoneyEvent()) + m_GuildBankEventLog_Money.push_front(NewEvent); + else + m_GuildBankEventLog_Item[TabId].push_front(NewEvent); + + }while( result->NextRow() ); + delete result; + + // Check lists size in case to many event entries in db for a tab or for money + // This cases can happen only if a crash occured somewhere and table has too many log entries + if (!m_GuildBankEventLog_Money.empty()) + { + CharacterDatabase.PExecute("DELETE FROM guild_bank_eventlog WHERE guildid=%u AND LogGuid < %u", + Id, m_GuildBankEventLog_Money.front()->LogGuid); + } + for (int i = 0; i < GUILD_BANK_MAX_TABS; ++i) + { + if (!m_GuildBankEventLog_Item[i].empty()) + { + CharacterDatabase.PExecute("DELETE FROM guild_bank_eventlog WHERE guildid=%u AND LogGuid < %u", + Id, m_GuildBankEventLog_Item[i].front()->LogGuid); + } + } +} + +void Guild::UnloadGuildBankEventLog() +{ + GuildBankEvent *EventLogEntry; + if( !m_GuildBankEventLog_Money.empty() ) + { + do + { + EventLogEntry = *(m_GuildBankEventLog_Money.begin()); + m_GuildBankEventLog_Money.pop_front(); + delete EventLogEntry; + }while( !m_GuildBankEventLog_Money.empty() ); + } + + for (int i = 0; i < GUILD_BANK_MAX_TABS; ++i) + { + if( !m_GuildBankEventLog_Item[i].empty() ) + { + do + { + EventLogEntry = *(m_GuildBankEventLog_Item[i].begin()); + m_GuildBankEventLog_Item[i].pop_front(); + delete EventLogEntry; + }while( !m_GuildBankEventLog_Item[i].empty() ); + } + } +} + +void Guild::DisplayGuildBankLogs(WorldSession *session, uint8 TabId) +{ + if (TabId > GUILD_BANK_MAX_TABS) + return; + + if (TabId == GUILD_BANK_MAX_TABS) + { + // Here we display money logs + WorldPacket data(MSG_GUILD_BANK_LOG_QUERY, m_GuildBankEventLog_Money.size()*(4*4+1)+1+1); + data << uint8(TabId); // Here GUILD_BANK_MAX_TABS + data << uint8(m_GuildBankEventLog_Money.size()); // number of log entries + for (GuildBankEventLog::const_iterator itr = m_GuildBankEventLog_Money.begin(); itr != m_GuildBankEventLog_Money.end(); ++itr) + { + data << uint8((*itr)->LogEntry); + data << uint64(MAKE_NEW_GUID((*itr)->PlayerGuid,0,HIGHGUID_PLAYER)); + data << uint32((*itr)->ItemOrMoney); + data << uint32(time(NULL)-(*itr)->TimeStamp); + } + session->SendPacket(&data); + } + else + { + // here we display current tab logs + WorldPacket data(MSG_GUILD_BANK_LOG_QUERY, m_GuildBankEventLog_Item[TabId].size()*(4*4+1+1)+1+1); + data << uint8(TabId); // Here a real Tab Id + // number of log entries + data << uint8(m_GuildBankEventLog_Item[TabId].size()); + for (GuildBankEventLog::const_iterator itr = m_GuildBankEventLog_Item[TabId].begin(); itr != m_GuildBankEventLog_Item[TabId].end(); ++itr) + { + data << uint8((*itr)->LogEntry); + data << uint64(MAKE_NEW_GUID((*itr)->PlayerGuid,0,HIGHGUID_PLAYER)); + data << uint32((*itr)->ItemOrMoney); + data << uint8((*itr)->ItemStackCount); + if ((*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM || (*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM2) + data << uint8((*itr)->DestTabId); // moved tab + data << uint32(time(NULL)-(*itr)->TimeStamp); + } + session->SendPacket(&data); + } + sLog.outDebug("WORLD: Sent (MSG_GUILD_BANK_LOG_QUERY)"); +} + +void Guild::LogBankEvent(uint8 LogEntry, uint8 TabId, uint32 PlayerGuidLow, uint32 ItemOrMoney, uint8 ItemStackCount, uint8 DestTabId) +{ + GuildBankEvent *NewEvent = new GuildBankEvent; + + NewEvent->LogGuid = LogMaxGuid++; + NewEvent->LogEntry = LogEntry; + NewEvent->PlayerGuid = PlayerGuidLow; + NewEvent->ItemOrMoney = ItemOrMoney; + NewEvent->ItemStackCount = ItemStackCount; + NewEvent->DestTabId = DestTabId; + NewEvent->TimeStamp = uint32(time(NULL)); + + if (NewEvent->isMoneyEvent()) + { + if (m_GuildBankEventLog_Money.size() > GUILD_BANK_MAX_LOGS) + { + GuildBankEvent *OldEvent = *(m_GuildBankEventLog_Money.begin()); + m_GuildBankEventLog_Money.pop_front(); + CharacterDatabase.PExecute("DELETE FROM guild_bank_eventlog WHERE guildid='%u' AND LogGuid='%u'", Id, OldEvent->LogGuid); + delete OldEvent; + } + m_GuildBankEventLog_Money.push_back(NewEvent); + } + else + { + if (m_GuildBankEventLog_Item[TabId].size() > GUILD_BANK_MAX_LOGS) + { + GuildBankEvent *OldEvent = *(m_GuildBankEventLog_Item[TabId].begin()); + m_GuildBankEventLog_Item[TabId].pop_front(); + CharacterDatabase.PExecute("DELETE FROM guild_bank_eventlog WHERE guildid='%u' AND LogGuid='%u'", Id, OldEvent->LogGuid); + delete OldEvent; + } + m_GuildBankEventLog_Item[TabId].push_back(NewEvent); + } + CharacterDatabase.PExecute("INSERT INTO guild_bank_eventlog (guildid,LogGuid,LogEntry,TabId,PlayerGuid,ItemOrMoney,ItemStackCount,DestTabId,TimeStamp) VALUES ('%u','%u','%u','%u','%u','%u','%u','%u','" I64FMTD "')", + Id, NewEvent->LogGuid, uint32(NewEvent->LogEntry), uint32(TabId), NewEvent->PlayerGuid, NewEvent->ItemOrMoney, uint32(NewEvent->ItemStackCount), uint32(NewEvent->DestTabId), NewEvent->TimeStamp); +} + +// This will renum guids used at load to prevent always going up until infinit +void Guild::RenumBankLogs() +{ + QueryResult *result = CharacterDatabase.PQuery("SELECT Min(LogGuid), Max(LogGuid) FROM guild_bank_eventlog WHERE guildid = %u", Id); + if(!result) + return; + + Field *fields = result->Fetch(); + CharacterDatabase.PExecute("UPDATE guild_bank_eventlog SET LogGuid=LogGuid-%u+1 WHERE guildid=%u ORDER BY LogGuid %s",fields[0].GetUInt32(), Id, fields[0].GetUInt32()?"ASC":"DESC"); + LogMaxGuid = fields[1].GetUInt32()+1; + delete result; +} + +bool Guild::AddGBankItemToDB(uint32 GuildId, uint32 BankTab , uint32 BankTabSlot , uint32 GUIDLow, uint32 Entry ) +{ + CharacterDatabase.PExecute("DELETE FROM guild_bank_item WHERE guildid = '%u' AND TabId = '%u'AND SlotId = '%u'", GuildId, BankTab, BankTabSlot); + CharacterDatabase.PExecute("INSERT INTO guild_bank_item (guildid,TabId,SlotId,item_guid,item_entry) " + "VALUES ('%u', '%u', '%u', '%u', '%u')", GuildId, BankTab, BankTabSlot, GUIDLow, Entry); + return true; +} + +void Guild::AppendDisplayGuildBankSlot( WorldPacket& data, GuildBankTab const *tab, int slot ) +{ + Item *pItem = tab->Slots[slot]; + uint32 entry = pItem ? pItem->GetEntry() : 0; + + data << uint8(slot); + data << uint32(entry); + if (entry) + { + // random item property id +8 + data << (uint32) pItem->GetItemRandomPropertyId(); + if (pItem->GetItemRandomPropertyId()) + // SuffixFactor +4 + data << (uint32) pItem->GetItemSuffixFactor(); + // +12 // ITEM_FIELD_STACK_COUNT + data << uint8(pItem->GetCount()); + data << uint32(0); // +16 // Unknown value + data << uint8(0); // unknown 2.4.2 + if (uint32 Enchant0 = pItem->GetEnchantmentId(PERM_ENCHANTMENT_SLOT)) + { + data << uint8(1); // number of enchantments (max 3) why max 3? + data << uint8(PERM_ENCHANTMENT_SLOT); // enchantment slot (range: 0:2) + data << uint32(Enchant0); // enchantment id + } + else + data << uint8(0); // no enchantments (0) + } +} + +Item* Guild::StoreItem(uint8 tabId, GuildItemPosCountVec const& dest, Item* pItem ) +{ + if( !pItem ) + return NULL; + + Item* lastItem = pItem; + + for(GuildItemPosCountVec::const_iterator itr = dest.begin(); itr != dest.end(); ) + { + uint8 slot = itr->slot; + uint32 count = itr->count; + + ++itr; + + if(itr == dest.end()) + { + lastItem = _StoreItem(tabId,slot,pItem,count,false); + break; + } + + lastItem = _StoreItem(tabId,slot,pItem,count,true); + } + + return lastItem; +} + +// Return stored item (if stored to stack, it can diff. from pItem). And pItem ca be deleted in this case. +Item* Guild::_StoreItem( uint8 tab, uint8 slot, Item *pItem, uint32 count, bool clone ) +{ + if( !pItem ) + return NULL; + + sLog.outDebug( "GUILD STORAGE: StoreItem tab = %u, slot = %u, item = %u, count = %u", tab, slot, pItem->GetEntry(), count); + + Item* pItem2 = m_TabListMap[tab]->Slots[slot]; + + if( !pItem2 ) + { + if(clone) + pItem = pItem->CloneItem(count); + else + pItem->SetCount(count); + + if(!pItem) + return NULL; + + m_TabListMap[tab]->Slots[slot] = pItem; + + pItem->SetUInt64Value(ITEM_FIELD_CONTAINED, 0); + pItem->SetUInt64Value(ITEM_FIELD_OWNER, 0); + AddGBankItemToDB(GetId(), tab, slot, pItem->GetGUIDLow(), pItem->GetEntry()); + pItem->FSetState(ITEM_NEW); + pItem->SaveToDB(); // not in onventory and can be save standalone + + return pItem; + } + else + { + pItem2->SetCount( pItem2->GetCount() + count ); + pItem2->FSetState(ITEM_CHANGED); + pItem2->SaveToDB(); // not in onventory and can be save standalone + + if(!clone) + { + pItem->RemoveFromWorld(); + pItem->DeleteFromDB(); + delete pItem; + } + + return pItem2; + } +} + +void Guild::RemoveItem(uint8 tab, uint8 slot ) +{ + m_TabListMap[tab]->Slots[slot] = NULL; + CharacterDatabase.PExecute("DELETE FROM guild_bank_item WHERE guildid='%u' AND TabId='%u' AND SlotId='%u'", + GetId(), uint32(tab), uint32(slot)); +} + +uint8 Guild::_CanStoreItem_InSpecificSlot( uint8 tab, uint8 slot, GuildItemPosCountVec &dest, uint32& count, bool swap, Item* pSrcItem ) const +{ + Item* pItem2 = m_TabListMap[tab]->Slots[slot]; + + // ignore move item (this slot will be empty at move) + if(pItem2==pSrcItem) + pItem2 = NULL; + + uint32 need_space; + + // empty specific slot - check item fit to slot + if( !pItem2 || swap ) + { + // non empty stack with space + need_space = pSrcItem->GetMaxStackCount(); + } + // non empty slot, check item type + else + { + // check item type + if(pItem2->GetEntry() != pSrcItem->GetEntry()) + return EQUIP_ERR_ITEM_CANT_STACK; + + // check free space + if(pItem2->GetCount() >= pSrcItem->GetMaxStackCount()) + return EQUIP_ERR_ITEM_CANT_STACK; + + need_space = pSrcItem->GetMaxStackCount() - pItem2->GetCount(); + } + + if(need_space > count) + need_space = count; + + dest.push_back(GuildItemPosCount(slot,need_space)); + count -= need_space; + return EQUIP_ERR_OK; +} + +uint8 Guild::_CanStoreItem_InTab( uint8 tab, GuildItemPosCountVec &dest, uint32& count, bool merge, Item* pSrcItem, uint8 skip_slot ) const +{ + for(uint32 j = 0; j < GUILD_BANK_MAX_SLOTS; j++) + { + // skip specific slot already processed in first called _CanStoreItem_InSpecificSlot + if(j==skip_slot) + continue; + + Item* pItem2 = m_TabListMap[tab]->Slots[j]; + + // ignore move item (this slot will be empty at move) + if(pItem2==pSrcItem) + pItem2 = NULL; + + // if merge skip empty, if !merge skip non-empty + if((pItem2!=NULL)!=merge) + continue; + + if( pItem2 ) + { + if(pItem2->GetEntry() == pSrcItem->GetEntry() && pItem2->GetCount() < pSrcItem->GetMaxStackCount() ) + { + uint32 need_space = pSrcItem->GetMaxStackCount() - pItem2->GetCount(); + if(need_space > count) + need_space = count; + + dest.push_back(GuildItemPosCount(j,need_space)); + count -= need_space; + + if(count==0) + return EQUIP_ERR_OK; + } + } + else + { + uint32 need_space = pSrcItem->GetMaxStackCount(); + if(need_space > count) + need_space = count; + + dest.push_back(GuildItemPosCount(j,need_space)); + count -= need_space; + + if(count==0) + return EQUIP_ERR_OK; + } + } + return EQUIP_ERR_OK; +} + +uint8 Guild::CanStoreItem( uint8 tab, uint8 slot, GuildItemPosCountVec &dest, uint32 count, Item *pItem, bool swap ) const +{ + sLog.outDebug( "GUILD STORAGE: CanStoreItem tab = %u, slot = %u, item = %u, count = %u", tab, slot, pItem->GetEntry(), count); + + if(count > pItem->GetCount()) + return EQUIP_ERR_COULDNT_SPLIT_ITEMS; + + if(pItem->IsSoulBound()) + return EQUIP_ERR_CANT_DROP_SOULBOUND; + + // in specific slot + if( slot != NULL_SLOT ) + { + uint8 res = _CanStoreItem_InSpecificSlot(tab,slot,dest,count,swap,pItem); + if(res!=EQUIP_ERR_OK) + return res; + + if(count==0) + return EQUIP_ERR_OK; + } + + // not specific slot or have spece for partly store only in specific slot + + // search stack in tab for merge to + if( pItem->GetMaxStackCount() > 1 ) + { + uint8 res = _CanStoreItem_InTab(tab,dest,count,true,pItem,slot); + if(res!=EQUIP_ERR_OK) + return res; + + if(count==0) + return EQUIP_ERR_OK; + } + + // search free slot in bag for place to + uint8 res = _CanStoreItem_InTab(tab,dest,count,false,pItem,slot); + if(res!=EQUIP_ERR_OK) + return res; + + if(count==0) + return EQUIP_ERR_OK; + + return EQUIP_ERR_BANK_FULL; +} + +void Guild::SetGuildBankTabText(uint8 TabId, std::string text) +{ + if (TabId >= GUILD_BANK_MAX_TABS) + return; + if (TabId >= m_TabListMap.size()) + return; + if (!m_TabListMap[TabId]) + return; + + if(m_TabListMap[TabId]->Text==text) + return; + + utf8truncate(text,500); // DB and client size limitation + + m_TabListMap[TabId]->Text = text; + + CharacterDatabase.escape_string(text); + CharacterDatabase.PExecute("UPDATE guild_bank_tab SET TabText='%s' WHERE guildid='%u' AND TabId='%u'", text.c_str(), Id, uint32(TabId)); +} + +void Guild::SendGuildBankTabText(WorldSession *session, uint8 TabId) +{ + if (TabId > GUILD_BANK_MAX_TABS) + return; + + GuildBankTab const *tab = GetBankTab(TabId); + if (!tab) + return; + + WorldPacket data(MSG_QUERY_GUILD_BANK_TEXT, 1+tab->Text.size()+1); + data << uint8(TabId); + data << tab->Text; + session->SendPacket(&data); +} diff --git a/src/game/Guild.h b/src/game/Guild.h new file mode 100644 index 00000000000..3f16d80987d --- /dev/null +++ b/src/game/Guild.h @@ -0,0 +1,435 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOSSERVER_GUILD_H +#define MANGOSSERVER_GUILD_H + +#define WITHDRAW_MONEY_UNLIMITED 0xFFFFFFFF +#define WITHDRAW_SLOT_UNLIMITED 0xFFFFFFFF + +#include "Item.h" + +class Item; + +enum GuildDefaultRanks +{ + GR_GUILDMASTER = 0, + GR_OFFICER = 1, + //GR_VETERAN = 2, -- not used anywhere and possible incorrect in modified rank list + //GR_MEMBER = 3, + //GR_INITIATE = 4, -- use Guild::GetLowestRank() instead for lowest rank +}; + +enum GuildRankRights +{ + GR_RIGHT_EMPTY = 0x00000040, + GR_RIGHT_GCHATLISTEN = 0x00000041, + GR_RIGHT_GCHATSPEAK = 0x00000042, + GR_RIGHT_OFFCHATLISTEN = 0x00000044, + GR_RIGHT_OFFCHATSPEAK = 0x00000048, + GR_RIGHT_PROMOTE = 0x000000C0, + GR_RIGHT_DEMOTE = 0x00000140, + GR_RIGHT_INVITE = 0x00000050, + GR_RIGHT_REMOVE = 0x00000060, + GR_RIGHT_SETMOTD = 0x00001040, + GR_RIGHT_EPNOTE = 0x00002040, + GR_RIGHT_VIEWOFFNOTE = 0x00004040, + GR_RIGHT_EOFFNOTE = 0x00008040, + GR_RIGHT_MODIFY_GUILD_INFO = 0x00010040, + GR_RIGHT_REPAIR_FROM_GUILD = 0x00020000, // unused in 2.4.x?, Remove money withdraw capacity + GR_RIGHT_WITHDRAW_REPAIR = 0x00040000, // withdraw for repair + GR_RIGHT_WITHDRAW_GOLD = 0x00080000, // withdraw gold + GR_RIGHT_ALL = 0x000FF1FF +}; + +enum Typecommand +{ + GUILD_CREATE_S = 0x00, + GUILD_INVITE_S = 0x01, + GUILD_QUIT_S = 0x03, + GUILD_FOUNDER_S = 0x0E, + GUILD_UNK1 = 0x10, + GUILD_BANK_S = 0x15, + GUILD_UNK3 = 0x16 +}; + +enum CommandErrors +{ + GUILD_PLAYER_NO_MORE_IN_GUILD = 0x00, + GUILD_INTERNAL = 0x01, + GUILD_ALREADY_IN_GUILD = 0x02, + ALREADY_IN_GUILD = 0x03, + INVITED_TO_GUILD = 0x04, + ALREADY_INVITED_TO_GUILD = 0x05, + GUILD_NAME_INVALID = 0x06, + GUILD_NAME_EXISTS = 0x07, + GUILD_LEADER_LEAVE = 0x08, + GUILD_PERMISSIONS = 0x08, + GUILD_PLAYER_NOT_IN_GUILD = 0x09, + GUILD_PLAYER_NOT_IN_GUILD_S = 0x0A, + GUILD_PLAYER_NOT_FOUND = 0x0B, + GUILD_NOT_ALLIED = 0x0C, + GUILD_RANK_TOO_HIGH_S = 0x0D, + GUILD_ALREADY_LOWEST_RANK_S = 0x0E, + GUILD_TEMP_ERROR = 0x11, + GUILD_RANK_IN_USE = 0x12, + GUILD_IGNORE = 0x13, + GUILD_ERR_UNK1 = 0x17, + GUILD_WITHDRAW_TOO_MUCH = 0x18, + GUILD_BANK_NO_MONEY = 0x19, + GUILD_BANK_TAB_IS_FULL = 0x1B, + GUILD_BANK_ITEM_NOT_FOUND = 0x1C +}; + +enum GuildEvents +{ + GE_PROMOTION = 0x00, + GE_DEMOTION = 0x01, + GE_MOTD = 0x02, + GE_JOINED = 0x03, + GE_LEFT = 0x04, + GE_REMOVED = 0x05, + GE_LEADER_IS = 0x06, + GE_LEADER_CHANGED = 0x07, + GE_DISBANDED = 0x08, + GE_TABARDCHANGE = 0x09, + GE_UNK1 = 0x0A, // string, string + GE_UNK2 = 0x0B, + GE_SIGNED_ON = 0x0C, + GE_SIGNED_OFF = 0x0D, + GE_UNK3 = 0x0E, + GE_BANKTAB_PURCHASED= 0x0F, + GE_UNK5 = 0x10, + GE_UNK6 = 0x11, // string 0000000000002710 is 1 gold + GE_UNK7 = 0x12 +}; + +enum PetitionTurns +{ + PETITION_TURN_OK = 0, + PETITION_TURN_ALREADY_IN_GUILD = 2, + PETITION_TURN_NEED_MORE_SIGNATURES = 4, +}; + +enum PetitionSigns +{ + PETITION_SIGN_OK = 0, + PETITION_SIGN_ALREADY_SIGNED = 1, + PETITION_SIGN_ALREADY_IN_GUILD = 2, + PETITION_SIGN_CANT_SIGN_OWN = 3, + PETITION_SIGN_NOT_SERVER = 4, +}; + +enum GuildBankRights +{ + GUILD_BANK_RIGHT_VIEW_TAB = 0x01, + GUILD_BANK_RIGHT_PUT_ITEM = 0x02, + GUILD_BANK_RIGHT_UPDATE_TEXT = 0x04, + + GUILD_BANK_RIGHT_DEPOSIT_ITEM = GUILD_BANK_RIGHT_VIEW_TAB | GUILD_BANK_RIGHT_PUT_ITEM, + GUILD_BANK_RIGHT_FULL = 0xFF, +}; + +enum GuildBankLogEntries +{ + GUILD_BANK_LOG_DEPOSIT_ITEM = 1, + GUILD_BANK_LOG_WITHDRAW_ITEM = 2, + GUILD_BANK_LOG_MOVE_ITEM = 3, + GUILD_BANK_LOG_DEPOSIT_MONEY = 4, + GUILD_BANK_LOG_WITHDRAW_MONEY = 5, + GUILD_BANK_LOG_REPAIR_MONEY = 6, + GUILD_BANK_LOG_MOVE_ITEM2 = 7, +}; + +enum GuildEventLogEntryTypes +{ + GUILD_EVENT_LOG_INVITE_PLAYER = 1, + GUILD_EVENT_LOG_JOIN_GUILD = 2, + GUILD_EVENT_LOG_PROMOTE_PLAYER = 3, + GUILD_EVENT_LOG_DEMOTE_PLAYER = 4, + GUILD_EVENT_LOG_UNINVITE_PLAYER = 5, + GUILD_EVENT_LOG_LEAVE_GUILD = 6, +}; + +struct GuildEventlogEntry +{ + uint32 LogGuid; + uint8 EventType; + uint32 PlayerGuid1; + uint32 PlayerGuid2; + uint8 NewRank; + uint64 TimeStamp; +}; + +enum GuildEmblem +{ + ERR_GUILDEMBLEM_SUCCESS = 0, + ERR_GUILDEMBLEM_INVALID_TABARD_COLORS = 1, + ERR_GUILDEMBLEM_NOGUILD = 2, + ERR_GUILDEMBLEM_NOTGUILDMASTER = 3, + ERR_GUILDEMBLEM_NOTENOUGHMONEY = 4, + ERR_GUILDEMBLEM_INVALIDVENDOR = 5 +}; + +struct GuildBankEvent +{ + uint32 LogGuid; + uint8 LogEntry; + uint8 TabId; + uint32 PlayerGuid; + uint32 ItemOrMoney; + uint8 ItemStackCount; + uint8 DestTabId; + uint64 TimeStamp; + + const bool isMoneyEvent() + { + return LogEntry == GUILD_BANK_LOG_DEPOSIT_MONEY || + LogEntry == GUILD_BANK_LOG_WITHDRAW_MONEY || + LogEntry == GUILD_BANK_LOG_REPAIR_MONEY; + } +}; + +struct GuildBankTab +{ + Item* Slots[GUILD_BANK_MAX_SLOTS]; + std::string Name; + std::string Icon; + std::string Text; +}; + +struct GuildItemPosCount +{ + GuildItemPosCount(uint8 _slot, uint8 _count) : slot(_slot), count(_count) {} + + uint8 slot; + uint8 count; +}; +typedef std::vector GuildItemPosCountVec; + +struct MemberSlot +{ + uint64 logout_time; + std::string name; + std::string Pnote; + std::string OFFnote; + uint32 RankId; + uint32 zoneId; + uint8 level; + uint8 Class; + uint32 BankResetTimeMoney; + uint32 BankRemMoney; + uint32 BankResetTimeTab[GUILD_BANK_MAX_TABS]; + uint32 BankRemSlotsTab[GUILD_BANK_MAX_TABS]; +}; + +struct RankInfo +{ + RankInfo(std::string _name, uint32 _rights, uint32 _money) : name(_name), rights(_rights), BankMoneyPerDay(_money) + { + for(uint8 i = 0; i < GUILD_BANK_MAX_TABS; ++i) + { + TabRight[i] = 0; + TabSlotPerDay[i] = 0; + } + } + + std::string name; + uint32 rights; + uint32 BankMoneyPerDay; + uint32 TabRight[GUILD_BANK_MAX_TABS]; + uint32 TabSlotPerDay[GUILD_BANK_MAX_TABS]; +}; + +class Guild +{ + public: + Guild(); + ~Guild(); + + bool create(uint64 lGuid, std::string gname); + void Disband(); + + typedef std::map MemberList; + typedef std::vector RankList; + + uint32 GetId(){ return Id; } + const uint64& GetLeader(){ return leaderGuid; } + std::string GetName(){ return name; } + std::string GetMOTD(){ return MOTD; } + std::string GetGINFO(){ return GINFO; } + + uint32 GetCreatedYear(){ return CreatedYear; } + uint32 GetCreatedMonth(){ return CreatedMonth; } + uint32 GetCreatedDay(){ return CreatedDay; } + + uint32 GetEmblemStyle(){ return EmblemStyle; } + uint32 GetEmblemColor(){ return EmblemColor; } + uint32 GetBorderStyle(){ return BorderStyle; } + uint32 GetBorderColor(){ return BorderColor; } + uint32 GetBackgroundColor(){ return BackgroundColor; } + + void SetLeader(uint64 guid); + bool AddMember(uint64 plGuid, uint32 plRank); + void ChangeRank(uint64 guid, uint32 newRank); + void DelMember(uint64 guid, bool isDisbanding=false); + uint32 GetLowestRank() const { return GetNrRanks()-1; } + + void SetMOTD(std::string motd); + void SetGINFO(std::string ginfo); + void SetPNOTE(uint64 guid,std::string pnote); + void SetOFFNOTE(uint64 guid,std::string offnote); + void SetEmblem(uint32 emblemStyle, uint32 emblemColor, uint32 borderStyle, uint32 borderColor, uint32 backgroundColor); + + uint32 GetMemberSize() const { return members.size(); } + + bool LoadGuildFromDB(uint32 GuildId); + bool LoadRanksFromDB(uint32 GuildId); + bool LoadMembersFromDB(uint32 GuildId); + + bool FillPlayerData(uint64 guid, MemberSlot* memslot); + void LoadPlayerStatsByGuid(uint64 guid); + + void BroadcastToGuild(WorldSession *session, std::string msg, uint32 language = LANG_UNIVERSAL); + void BroadcastToOfficers(WorldSession *session, std::string msg, uint32 language = LANG_UNIVERSAL); + void BroadcastPacketToRank(WorldPacket *packet, uint32 rankId); + void BroadcastPacket(WorldPacket *packet); + + void CreateRank(std::string name,uint32 rights); + void DelRank(); + std::string GetRankName(uint32 rankId); + uint32 GetRankRights(uint32 rankId); + uint32 GetNrRanks() const { return m_ranks.size(); } + + void SetRankName(uint32 rankId, std::string name); + void SetRankRights(uint32 rankId, uint32 rights); + bool HasRankRight(uint32 rankId, uint32 right) + { + return ((GetRankRights(rankId) & right) != GR_RIGHT_EMPTY) ? true : false; + } + + void Roster(WorldSession *session); + void Query(WorldSession *session); + + void UpdateLogoutTime(uint64 guid); + // Guild eventlog + void LoadGuildEventLogFromDB(); + void UnloadGuildEventlog(); + void DisplayGuildEventlog(WorldSession *session); + void LogGuildEvent(uint8 EventType, uint32 PlayerGuid1, uint32 PlayerGuid2, uint8 NewRank); + void RenumGuildEventlog(); + + // ** Guild bank ** + // Content & item deposit/withdraw + void DisplayGuildBankContent(WorldSession *session, uint8 TabId); + void DisplayGuildBankContentUpdate(uint8 TabId, int32 slot1, int32 slot2 = -1); + void DisplayGuildBankContentUpdate(uint8 TabId, GuildItemPosCountVec const& slots); + void DisplayGuildBankMoneyUpdate(); + + Item* GetItem(uint8 TabId, uint8 SlotId); + uint8 CanStoreItem( uint8 tab, uint8 slot, GuildItemPosCountVec& dest, uint32 count, Item *pItem, bool swap = false) const; + Item* StoreItem( uint8 tab, GuildItemPosCountVec const& pos, Item *pItem ); + void RemoveItem(uint8 tab, uint8 slot ); + + // Tabs + void DisplayGuildBankTabsInfo(WorldSession *session); + void CreateNewBankTab(); + void SetGuildBankTabText(uint8 TabId, std::string text); + void SendGuildBankTabText(WorldSession *session, uint8 TabId); + void SetGuildBankTabInfo(uint8 TabId, std::string name, std::string icon); + void CreateBankRightForTab(uint32 rankid, uint8 TabId); + const GuildBankTab *GetBankTab(uint8 index) { if(index >= m_TabListMap.size()) return NULL; return m_TabListMap[index]; } + const uint8 GetPurchasedTabs() const { return purchased_tabs; } + uint32 GetBankRights(uint32 rankId, uint8 TabId) const; + bool IsMemberHaveRights(uint32 LowGuid, uint8 TabId,uint32 rights) const; + bool CanMemberViewTab(uint32 LowGuid, uint8 TabId) const; + // Load/unload + void LoadGuildBankFromDB(); + void UnloadGuildBank(); + void IncOnlineMemberCount() { ++m_onlinemembers; } + // Money deposit/withdraw + void SendMoneyInfo(WorldSession *session, uint32 LowGuid); + bool MemberMoneyWithdraw(uint32 amount, uint32 LowGuid); + uint64 GetGuildBankMoney() { return guildbank_money; } + void SetBankMoney(int64 money); + // per days + bool MemberItemWithdraw(uint8 TabId, uint32 LowGuid); + uint32 GetMemberSlotWithdrawRem(uint32 LowGuid, uint8 TabId); + uint32 GetMemberMoneyWithdrawRem(uint32 LowGuid); + void SetBankMoneyPerDay(uint32 rankId, uint32 money); + void SetBankRightsAndSlots(uint32 rankId, uint8 TabId, uint32 right, uint32 SlotPerDay, bool db); + uint32 GetBankMoneyPerDay(uint32 rankId); + uint32 GetBankSlotPerDay(uint32 rankId, uint8 TabId); + // rights per day + void LoadBankRightsFromDB(uint32 GuildId); + // logs + void LoadGuildBankEventLogFromDB(); + void UnloadGuildBankEventLog(); + void DisplayGuildBankLogs(WorldSession *session, uint8 TabId); + void LogBankEvent(uint8 LogEntry, uint8 TabId, uint32 PlayerGuidLow, uint32 ItemOrMoney, uint8 ItemStackCount=0, uint8 DestTabId=0); + void RenumBankLogs(); + bool AddGBankItemToDB(uint32 GuildId, uint32 BankTab , uint32 BankTabSlot , uint32 GUIDLow, uint32 Entry ); + + protected: + void AddRank(std::string name,uint32 rights,uint32 money); + + uint32 Id; + std::string name; + uint64 leaderGuid; + std::string MOTD; + std::string GINFO; + uint32 CreatedYear; + uint32 CreatedMonth; + uint32 CreatedDay; + + uint32 EmblemStyle; + uint32 EmblemColor; + uint32 BorderStyle; + uint32 BorderColor; + uint32 BackgroundColor; + + RankList m_ranks; + + MemberList members; + + typedef std::vector TabListMap; + TabListMap m_TabListMap; + + /** These are actually ordered lists. The first element is the oldest entry.*/ + typedef std::list GuildEventlog; + typedef std::list GuildBankEventLog; + GuildEventlog m_GuildEventlog; + GuildBankEventLog m_GuildBankEventLog_Money; + GuildBankEventLog m_GuildBankEventLog_Item[GUILD_BANK_MAX_TABS]; + + bool m_bankloaded; + bool m_eventlogloaded; + uint32 m_onlinemembers; + uint64 guildbank_money; + uint8 purchased_tabs; + + uint32 LogMaxGuid; + uint32 GuildEventlogMaxGuid; + private: + // internal common parts for CanStore/StoreItem functions + void AppendDisplayGuildBankSlot( WorldPacket& data, GuildBankTab const *tab, int32 slot ); + uint8 _CanStoreItem_InSpecificSlot( uint8 tab, uint8 slot, GuildItemPosCountVec& dest, uint32& count, bool swap, Item *pSrcItem ) const; + uint8 _CanStoreItem_InTab( uint8 tab, GuildItemPosCountVec& dest, uint32& count, bool merge, Item *pSrcItem, uint8 skip_slot ) const; + Item* _StoreItem( uint8 tab, uint8 slot, Item *pItem, uint32 count, bool clone ); +}; +#endif diff --git a/src/game/GuildHandler.cpp b/src/game/GuildHandler.cpp new file mode 100644 index 00000000000..a82a45fde40 --- /dev/null +++ b/src/game/GuildHandler.cpp @@ -0,0 +1,1815 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "World.h" +#include "ObjectMgr.h" +#include "Log.h" +#include "Opcodes.h" +#include "Guild.h" +#include "MapManager.h" +#include "GossipDef.h" +#include "SocialMgr.h" + +void WorldSession::HandleGuildQueryOpcode(WorldPacket& recvPacket) +{ + CHECK_PACKET_SIZE(recvPacket, 4); + + uint32 guildId; + Guild *guild; + + //sLog.outDebug("WORLD: Received CMSG_GUILD_QUERY"); + + recvPacket >> guildId; + + guild = objmgr.GetGuildById(guildId); + if(!guild) + { + SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD); + return; + } + + guild->Query(this); +} + +void WorldSession::HandleGuildCreateOpcode(WorldPacket& recvPacket) +{ + CHECK_PACKET_SIZE(recvPacket, 1); + + std::string gname; + + //sLog.outDebug("WORLD: Received CMSG_GUILD_CREATE"); + + recvPacket >> gname; + + if(GetPlayer()->GetGuildId()) + return; + + Guild *guild = new Guild; + if(!guild->create(GetPlayer()->GetGUID(),gname)) + { + delete guild; + return; + } + + objmgr.AddGuild(guild); +} + +void WorldSession::HandleGuildInviteOpcode(WorldPacket& recvPacket) +{ + CHECK_PACKET_SIZE(recvPacket, 1); + + std::string Invitedname, plname; + + //sLog.outDebug("WORLD: Received CMSG_GUILD_INVITE"); + + Player * player = NULL; + + recvPacket >> Invitedname; + + if(normalizePlayerName(Invitedname)) + player = ObjectAccessor::Instance().FindPlayerByName(Invitedname.c_str()); + + if(!player) + { + SendGuildCommandResult(GUILD_INVITE_S, Invitedname, GUILD_PLAYER_NOT_FOUND); + return; + } + + Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + if(!guild) + { + SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD); + return; + } + + // OK result but not send invite + if(player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow())) + return; + + // not let enemies sign guild charter + if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && player->GetTeam() != GetPlayer()->GetTeam()) + { + SendGuildCommandResult(GUILD_INVITE_S, Invitedname, GUILD_NOT_ALLIED); + return; + } + + if(player->GetGuildId()) + { + plname = player->GetName(); + SendGuildCommandResult(GUILD_INVITE_S, plname, ALREADY_IN_GUILD); + return; + } + + if(player->GetGuildIdInvited()) + { + plname = player->GetName(); + SendGuildCommandResult(GUILD_INVITE_S, plname, ALREADY_INVITED_TO_GUILD); + return; + } + + if(!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_INVITE)) + { + SendGuildCommandResult(GUILD_INVITE_S, "", GUILD_PERMISSIONS); + return; + } + + sLog.outDebug("Player %s Invited %s to Join his Guild", GetPlayer()->GetName(), Invitedname.c_str()); + + player->SetGuildIdInvited(GetPlayer()->GetGuildId()); + // Put record into guildlog + guild->LogGuildEvent(GUILD_EVENT_LOG_INVITE_PLAYER, GetPlayer()->GetGUIDLow(), player->GetGUIDLow(), 0); + + WorldPacket data(SMSG_GUILD_INVITE, (8+10)); // guess size + data << GetPlayer()->GetName(); + data << guild->GetName(); + player->GetSession()->SendPacket(&data); + + //sLog.outDebug("WORLD: Sent (SMSG_GUILD_INVITE)"); +} + +void WorldSession::HandleGuildRemoveOpcode(WorldPacket& recvPacket) +{ + CHECK_PACKET_SIZE(recvPacket, 1); + + std::string plName; + uint64 plGuid; + uint32 plGuildId; + Guild *guild; + Player *player; + + //sLog.outDebug("WORLD: Received CMSG_GUILD_REMOVE"); + + recvPacket >> plName; + + if(!normalizePlayerName(plName)) + return; + + player = ObjectAccessor::Instance().FindPlayerByName(plName.c_str()); + guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + + if(player) + { + plGuid = player->GetGUID(); + plGuildId = player->GetGuildId(); + } + else + { + plGuid = objmgr.GetPlayerGUIDByName(plName); + plGuildId = Player::GetGuildIdFromDB(plGuid); + } + + if(!guild) + { + SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD); + return; + } + + if(!plGuid) + { + SendGuildCommandResult(GUILD_INVITE_S, plName, GUILD_PLAYER_NOT_FOUND); + return; + } + + if(!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_REMOVE)) + { + SendGuildCommandResult(GUILD_INVITE_S, "", GUILD_PERMISSIONS); + return; + } + + if(plGuid == guild->GetLeader()) + { + SendGuildCommandResult(GUILD_QUIT_S, "", GUILD_LEADER_LEAVE); + return; + } + + if(GetPlayer()->GetGuildId() != plGuildId) + { + SendGuildCommandResult(GUILD_INVITE_S, plName, GUILD_PLAYER_NOT_IN_GUILD_S); + return; + } + + guild->DelMember(plGuid); + // Put record into guildlog + guild->LogGuildEvent(GUILD_EVENT_LOG_UNINVITE_PLAYER, GetPlayer()->GetGUIDLow(), GUID_LOPART(plGuid), 0); + + WorldPacket data(SMSG_GUILD_EVENT, (2+20)); // guess size + data << (uint8)GE_REMOVED; + data << (uint8)2; // strings count + data << plName; + data << GetPlayer()->GetName(); + guild->BroadcastPacket(&data); +} + +void WorldSession::HandleGuildAcceptOpcode(WorldPacket& /*recvPacket*/) +{ + Guild *guild; + Player *player = GetPlayer(); + + //sLog.outDebug("WORLD: Received CMSG_GUILD_ACCEPT"); + + guild = objmgr.GetGuildById(player->GetGuildIdInvited()); + if(!guild || player->GetGuildId()) + return; + + // not let enemies sign guild charter + if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && player->GetTeam() != objmgr.GetPlayerTeamByGUID(guild->GetLeader())) + return; + + if(!guild->AddMember(GetPlayer()->GetGUID(),guild->GetLowestRank())) + return; + // Put record into guildlog + guild->LogGuildEvent(GUILD_EVENT_LOG_JOIN_GUILD, GetPlayer()->GetGUIDLow(), 0, 0); + + WorldPacket data(SMSG_GUILD_EVENT, (2+10)); // guess size + data << (uint8)GE_JOINED; + data << (uint8)1; + data << player->GetName(); + guild->BroadcastPacket(&data); + + //sLog.outDebug("WORLD: Sent (SMSG_GUILD_EVENT)"); +} + +void WorldSession::HandleGuildDeclineOpcode(WorldPacket& /*recvPacket*/) +{ + //sLog.outDebug("WORLD: Received CMSG_GUILD_DECLINE"); + + GetPlayer()->SetGuildIdInvited(0); + GetPlayer()->SetInGuild(0); +} + +void WorldSession::HandleGuildInfoOpcode(WorldPacket& /*recvPacket*/) +{ + Guild *guild; + //sLog.outDebug("WORLD: Received CMSG_GUILD_INFO"); + + guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + if(!guild) + { + SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD); + return; + } + + WorldPacket data(SMSG_GUILD_INFO, (5*4 + guild->GetName().size() + 1)); + data << guild->GetName(); + data << guild->GetCreatedDay(); + data << guild->GetCreatedMonth(); + data << guild->GetCreatedYear(); + data << guild->GetMemberSize(); + data << guild->GetMemberSize(); + + SendPacket(&data); +} + +void WorldSession::HandleGuildRosterOpcode(WorldPacket& /*recvPacket*/) +{ + //sLog.outDebug("WORLD: Received CMSG_GUILD_ROSTER"); + + Guild* guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + if(!guild) + return; + + guild->Roster(this); +} + +void WorldSession::HandleGuildPromoteOpcode(WorldPacket& recvPacket) +{ + CHECK_PACKET_SIZE(recvPacket, 1); + + std::string plName; + uint64 plGuid; + uint32 plGuildId; + uint32 plRankId; + Player *player; + Guild *guild; + + //sLog.outDebug("WORLD: Received CMSG_GUILD_PROMOTE"); + + recvPacket >> plName; + + if(!normalizePlayerName(plName)) + return; + + player = ObjectAccessor::Instance().FindPlayerByName(plName.c_str()); + guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + if(player) + { + plGuid = player->GetGUID(); + plGuildId = player->GetGuildId(); + plRankId = player->GetRank(); + } + else + { + plGuid = objmgr.GetPlayerGUIDByName(plName); + plGuildId = Player::GetGuildIdFromDB(plGuid); + plRankId = Player::GetRankFromDB(plGuid); + } + + if(!guild) + { + SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD); + return; + } + else if(!plGuid) + { + SendGuildCommandResult(GUILD_INVITE_S, plName, GUILD_PLAYER_NOT_FOUND); + return; + } + else if(plGuid == GetPlayer()->GetGUID()) + { + SendGuildCommandResult(GUILD_INVITE_S, "", GUILD_NAME_INVALID); + return; + } + else if(GetPlayer()->GetGuildId() != plGuildId) + { + SendGuildCommandResult(GUILD_INVITE_S, plName, GUILD_PLAYER_NOT_IN_GUILD_S); + return; + } + else if(!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_PROMOTE)) + { + SendGuildCommandResult(GUILD_INVITE_S, "", GUILD_PERMISSIONS); + return; + } + else if((plRankId-1) == 0 || (plRankId-1) < this->GetPlayer()->GetRank()) + return; + + if(plRankId < 1) + { + SendGuildCommandResult(GUILD_INVITE_S, "", GUILD_INTERNAL); + return; + } + + uint32 newRankId = plRankId < guild->GetNrRanks() ? plRankId-1 : guild->GetNrRanks()-1; + + guild->ChangeRank(plGuid, newRankId); + // Put record into guildlog + guild->LogGuildEvent(GUILD_EVENT_LOG_PROMOTE_PLAYER, GetPlayer()->GetGUIDLow(), GUID_LOPART(plGuid), newRankId); + + WorldPacket data(SMSG_GUILD_EVENT, (2+30)); // guess size + data << (uint8)GE_PROMOTION; + data << (uint8)3; + data << GetPlayer()->GetName(); + data << plName; + data << guild->GetRankName(newRankId); + guild->BroadcastPacket(&data); +} + +void WorldSession::HandleGuildDemoteOpcode(WorldPacket& recvPacket) +{ + CHECK_PACKET_SIZE(recvPacket, 1); + + std::string plName; + uint64 plGuid; + uint32 plGuildId; + uint32 plRankId; + Player *player; + Guild *guild; + + //sLog.outDebug("WORLD: Received CMSG_GUILD_DEMOTE"); + + recvPacket >> plName; + + if(!normalizePlayerName(plName)) + return; + + player = ObjectAccessor::Instance().FindPlayerByName(plName.c_str()); + guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + if(player) + { + plGuid = player->GetGUID(); + plGuildId = player->GetGuildId(); + plRankId = player->GetRank(); + } + else + { + plGuid = objmgr.GetPlayerGUIDByName(plName); + plGuildId = Player::GetGuildIdFromDB(plGuid); + plRankId = Player::GetRankFromDB(plGuid); + } + + if(!guild) + { + SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD); + return; + } + + if( !plGuid ) + { + SendGuildCommandResult(GUILD_INVITE_S, plName, GUILD_PLAYER_NOT_FOUND); + return; + } + + if(plGuid == GetPlayer()->GetGUID()) + { + SendGuildCommandResult(GUILD_INVITE_S, "", GUILD_NAME_INVALID); + return; + } + + if(GetPlayer()->GetGuildId() != plGuildId) + { + SendGuildCommandResult(GUILD_INVITE_S, plName, GUILD_PLAYER_NOT_IN_GUILD_S); + return; + } + + if(!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_DEMOTE)) + { + SendGuildCommandResult(GUILD_INVITE_S, "", GUILD_PERMISSIONS); + return; + } + + if((plRankId+1) >= guild->GetNrRanks() || plRankId <= this->GetPlayer()->GetRank()) + return; + + guild->ChangeRank(plGuid, (plRankId+1)); + // Put record into guildlog + guild->LogGuildEvent(GUILD_EVENT_LOG_DEMOTE_PLAYER, GetPlayer()->GetGUIDLow(), GUID_LOPART(plGuid), (plRankId+1)); + + WorldPacket data(SMSG_GUILD_EVENT, (2+30)); // guess size + data << (uint8)GE_DEMOTION; + data << (uint8)3; + data << GetPlayer()->GetName(); + data << plName; + data << guild->GetRankName(plRankId+1); + guild->BroadcastPacket(&data); +} + +void WorldSession::HandleGuildLeaveOpcode(WorldPacket& /*recvPacket*/) +{ + std::string plName; + Guild *guild; + + //sLog.outDebug("WORLD: Received CMSG_GUILD_LEAVE"); + + guild = objmgr.GetGuildById(_player->GetGuildId()); + if(!guild) + { + SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD); + return; + } + if(_player->GetGUID() == guild->GetLeader() && guild->GetMemberSize() > 1) + { + SendGuildCommandResult(GUILD_QUIT_S, "", GUILD_LEADER_LEAVE); + return; + } + + if(_player->GetGUID() == guild->GetLeader()) + { + guild->Disband(); + return; + } + + plName = _player->GetName(); + + guild->DelMember(_player->GetGUID()); + // Put record into guildlog + guild->LogGuildEvent(GUILD_EVENT_LOG_LEAVE_GUILD, _player->GetGUIDLow(), 0, 0); + + WorldPacket data(SMSG_GUILD_EVENT, (2+10)); // guess size + data << (uint8)GE_LEFT; + data << (uint8)1; + data << plName; + guild->BroadcastPacket(&data); + + //sLog.outDebug("WORLD: Sent (SMSG_GUILD_EVENT)"); + + SendGuildCommandResult(GUILD_QUIT_S, guild->GetName(), GUILD_PLAYER_NO_MORE_IN_GUILD); +} + +void WorldSession::HandleGuildDisbandOpcode(WorldPacket& /*recvPacket*/) +{ + std::string name; + Guild *guild; + + //sLog.outDebug("WORLD: Received CMSG_GUILD_DISBAND"); + + guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + if(!guild) + { + SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD); + return; + } + if(GetPlayer()->GetGUID() != guild->GetLeader()) + { + SendGuildCommandResult(GUILD_INVITE_S, "", GUILD_PERMISSIONS); + return; + } + + guild->Disband(); + + //sLog.outDebug("WORLD: Guild Sucefully Disbanded"); +} + +void WorldSession::HandleGuildLeaderOpcode(WorldPacket& recvPacket) +{ + CHECK_PACKET_SIZE(recvPacket, 1); + + std::string name; + Player *newLeader; + uint64 newLeaderGUID; + uint32 newLeaderGuild; + Player *oldLeader = GetPlayer(); + Guild *guild; + + //sLog.outDebug("WORLD: Received CMSG_GUILD_LEADER"); + + recvPacket >> name; + + if(!normalizePlayerName(name)) + return; + + newLeader = ObjectAccessor::Instance().FindPlayerByName(name.c_str()); + if(newLeader) + { + newLeaderGUID = newLeader->GetGUID(); + newLeaderGuild = newLeader->GetGuildId(); + } + else + { + newLeaderGUID = objmgr.GetPlayerGUIDByName(name); + newLeaderGuild = Player::GetGuildIdFromDB(newLeaderGUID); + } + guild = objmgr.GetGuildById(oldLeader->GetGuildId()); + + if(!guild) + { + SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD); + return; + } + else if(!newLeaderGUID) + { + SendGuildCommandResult(GUILD_INVITE_S, name, GUILD_PLAYER_NOT_FOUND); + return; + } + if(oldLeader->GetGuildId() != newLeaderGuild) + { + SendGuildCommandResult(GUILD_INVITE_S, name, GUILD_PLAYER_NOT_IN_GUILD_S); + return; + } + if(oldLeader->GetGUID() != guild->GetLeader()) + { + SendGuildCommandResult(GUILD_INVITE_S, "", GUILD_PERMISSIONS); + return; + } + + guild->SetLeader(newLeaderGUID); + guild->ChangeRank(oldLeader->GetGUID(), GR_OFFICER); + + WorldPacket data(SMSG_GUILD_EVENT, (2+20)); // guess size + data << (uint8)GE_LEADER_CHANGED; + data << (uint8)2; + data << oldLeader->GetName(); + data << name.c_str(); + guild->BroadcastPacket(&data); + + //sLog.outDebug("WORLD: Sent (SMSG_GUILD_EVENT)"); +} + +void WorldSession::HandleGuildMOTDOpcode(WorldPacket& recvPacket) +{ + Guild *guild; + std::string MOTD; + + //sLog.outDebug("WORLD: Received CMSG_GUILD_MOTD"); + + guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + if(!guild) + { + SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD); + return; + } + if(!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_SETMOTD)) + { + SendGuildCommandResult(GUILD_INVITE_S, "", GUILD_PERMISSIONS); + return; + } + + if(!recvPacket.empty()) + recvPacket >> MOTD; + else + MOTD = ""; + + guild->SetMOTD(MOTD); + + WorldPacket data(SMSG_GUILD_EVENT, (2+MOTD.size()+1)); + data << (uint8)GE_MOTD; + data << (uint8)1; + data << MOTD; + guild->BroadcastPacket(&data); + + //sLog.outDebug("WORLD: Sent (SMSG_GUILD_EVENT)"); +} + +void WorldSession::HandleGuildSetPublicNoteOpcode(WorldPacket& recvPacket) +{ + CHECK_PACKET_SIZE(recvPacket, 1); + + Guild *guild; + Player *player; + uint64 plGuid; + uint32 plGuildId; + std::string name,PNOTE; + + //sLog.outDebug("WORLD: Received CMSG_GUILD_SET_PUBLIC_NOTE"); + + recvPacket >> name; + + if(!normalizePlayerName(name)) + return; + + player = ObjectAccessor::Instance().FindPlayerByName(name.c_str()); + guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + if(player) + { + plGuid = player->GetGUID(); + plGuildId = player->GetGuildId(); + } + else + { + plGuid = objmgr.GetPlayerGUIDByName(name); + plGuildId = Player::GetGuildIdFromDB(plGuid); + } + + if(!guild) + { + SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD); + return; + } + else if(!plGuid) + { + SendGuildCommandResult(GUILD_INVITE_S, name, GUILD_PLAYER_NOT_FOUND); + return; + } + else if(GetPlayer()->GetGuildId() != plGuildId) + { + SendGuildCommandResult(GUILD_INVITE_S, name, GUILD_PLAYER_NOT_IN_GUILD_S); + return; + } + if(!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_EPNOTE)) + { + SendGuildCommandResult(GUILD_INVITE_S, "", GUILD_PERMISSIONS); + return; + } + + recvPacket >> PNOTE; + guild->SetPNOTE(plGuid, PNOTE); + + guild->Roster(this); +} + +void WorldSession::HandleGuildSetOfficerNoteOpcode(WorldPacket& recvPacket) +{ + CHECK_PACKET_SIZE(recvPacket, 1); + + Guild *guild; + Player *player; + uint64 plGuid; + uint32 plGuildId; + std::string plName, OFFNOTE; + + //sLog.outDebug("WORLD: Received CMSG_GUILD_SET_OFFICER_NOTE"); + + recvPacket >> plName; + + if(!normalizePlayerName(plName)) + return; + + player = ObjectAccessor::Instance().FindPlayerByName(plName.c_str()); + guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + if(player) + { + plGuid = player->GetGUID(); + plGuildId = player->GetGuildId(); + } + else + { + plGuid = objmgr.GetPlayerGUIDByName(plName); + plGuildId = Player::GetGuildIdFromDB(plGuid); + } + + if(!guild) + { + SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD); + return; + } + else if( !plGuid ) + { + SendGuildCommandResult(GUILD_INVITE_S, plName, GUILD_PLAYER_NOT_FOUND); + return; + } + else if(GetPlayer()->GetGuildId() != plGuildId) + { + SendGuildCommandResult(GUILD_INVITE_S, plName, GUILD_PLAYER_NOT_IN_GUILD_S); + return; + } + if(!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_EOFFNOTE)) + { + SendGuildCommandResult(GUILD_INVITE_S, "", GUILD_PERMISSIONS); + return; + } + + recvPacket >> OFFNOTE; + guild->SetOFFNOTE(plGuid, OFFNOTE); + + guild->Roster(this); +} + +void WorldSession::HandleGuildRankOpcode(WorldPacket& recvPacket) +{ + CHECK_PACKET_SIZE(recvPacket, 4+4+1+4*13); + //recvPacket.hexlike(); + + Guild *guild; + std::string rankname; + uint32 rankId; + uint32 rights, MoneyPerDay; + uint32 BankRights; + uint32 BankSlotPerDay; + + //sLog.outDebug("WORLD: Received CMSG_GUILD_RANK"); + + guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + if(!guild) + { + SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD); + return; + } + + else if(GetPlayer()->GetGUID() != guild->GetLeader()) + { + SendGuildCommandResult(GUILD_INVITE_S, "", GUILD_PERMISSIONS); + return; + } + + recvPacket >> rankId; + recvPacket >> rights; + recvPacket >> rankname; + recvPacket >> MoneyPerDay; + + for (int i = 0; i < GUILD_BANK_MAX_TABS; ++i) + { + recvPacket >> BankRights; + recvPacket >> BankSlotPerDay; + guild->SetBankRightsAndSlots(rankId, uint8(i), uint16(BankRights & 0xFF), uint16(BankSlotPerDay), true); + } + sLog.outDebug("WORLD: Changed RankName to %s , Rights to 0x%.4X", rankname.c_str(), rights); + + guild->SetBankMoneyPerDay(rankId, MoneyPerDay); + guild->SetRankName(rankId, rankname); + + if(rankId==GR_GUILDMASTER) // prevent loss leader rights + rights |= GR_RIGHT_ALL; + + guild->SetRankRights(rankId, rights); + + guild->Query(this); + guild->Roster(this); +} + +void WorldSession::HandleGuildAddRankOpcode(WorldPacket& recvPacket) +{ + CHECK_PACKET_SIZE(recvPacket, 1); + + Guild *guild; + std::string rankname; + + //sLog.outDebug("WORLD: Received CMSG_GUILD_ADD_RANK"); + + guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + if(!guild) + { + SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD); + return; + } + + if(GetPlayer()->GetGUID() != guild->GetLeader()) + { + SendGuildCommandResult(GUILD_INVITE_S, "", GUILD_PERMISSIONS); + return; + } + + if(guild->GetNrRanks() >= GUILD_MAX_RANKS) // client not let create more 10 than ranks + return; + + recvPacket >> rankname; + + guild->CreateRank(rankname, GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK); + + guild->Query(this); + guild->Roster(this); +} + +void WorldSession::HandleGuildDelRankOpcode(WorldPacket& /*recvPacket*/) +{ + Guild *guild; + std::string rankname; + + //sLog.outDebug("WORLD: Received CMSG_GUILD_DEL_RANK"); + + guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + if(!guild) + { + SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD); + return; + } + + else if(GetPlayer()->GetGUID() != guild->GetLeader()) + { + SendGuildCommandResult(GUILD_INVITE_S, "", GUILD_PERMISSIONS); + return; + } + + guild->DelRank(); + + guild->Query(this); + guild->Roster(this); +} + +void WorldSession::SendGuildCommandResult(uint32 typecmd,std::string str,uint32 cmdresult) +{ + WorldPacket data(SMSG_GUILD_COMMAND_RESULT, (8+str.size()+1)); + data << typecmd; + data << str; + data << cmdresult; + SendPacket(&data); + + //sLog.outDebug("WORLD: Sent (SMSG_GUILD_COMMAND_RESULT)"); +} + +void WorldSession::HandleGuildChangeInfoOpcode(WorldPacket& recvPacket) +{ + CHECK_PACKET_SIZE(recvPacket, 1); + + //sLog.outDebug("WORLD: Received CMSG_GUILD_INFO_TEXT"); + + std::string GINFO; + + recvPacket >> GINFO; + + Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + if(!guild) + { + SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD); + return; + } + + if(!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_MODIFY_GUILD_INFO)) + { + SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PERMISSIONS); + return; + } + + guild->SetGINFO(GINFO); +} + +void WorldSession::HandleGuildSaveEmblemOpcode(WorldPacket& recvPacket) +{ + CHECK_PACKET_SIZE(recvPacket, 8+4+4+4+4+4); + + //sLog.outDebug("WORLD: Received MSG_SAVE_GUILD_EMBLEM"); + + uint64 vendorGuid; + + uint32 EmblemStyle; + uint32 EmblemColor; + uint32 BorderStyle; + uint32 BorderColor; + uint32 BackgroundColor; + + recvPacket >> vendorGuid; + + Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, vendorGuid,UNIT_NPC_FLAG_TABARDDESIGNER); + if (!pCreature) + { + //"That's not an emblem vendor!" + SendSaveGuildEmblem(ERR_GUILDEMBLEM_INVALIDVENDOR); + sLog.outDebug("WORLD: HandleGuildSaveEmblemOpcode - Unit (GUID: %u) not found or you can't interact with him.", GUID_LOPART(vendorGuid)); + return; + } + + // remove fake death + if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + recvPacket >> EmblemStyle; + recvPacket >> EmblemColor; + recvPacket >> BorderStyle; + recvPacket >> BorderColor; + recvPacket >> BackgroundColor; + + Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + if(!guild) + { + //"You are not part of a guild!"; + SendSaveGuildEmblem(ERR_GUILDEMBLEM_NOGUILD); + return; + } + + if (guild->GetLeader() != GetPlayer()->GetGUID()) + { + //"Only guild leaders can create emblems." + SendSaveGuildEmblem(ERR_GUILDEMBLEM_NOTGUILDMASTER); + return; + } + + if(GetPlayer()->GetMoney() < 10*GOLD) + { + //"You can't afford to do that." + SendSaveGuildEmblem(ERR_GUILDEMBLEM_NOTENOUGHMONEY); + return; + } + + GetPlayer()->ModifyMoney(-10*GOLD); + guild->SetEmblem(EmblemStyle, EmblemColor, BorderStyle, BorderColor, BackgroundColor); + + //"Guild Emblem saved." + SendSaveGuildEmblem(ERR_GUILDEMBLEM_SUCCESS); + + guild->Query(this); +} + +void WorldSession::HandleGuildEventLogOpcode(WorldPacket& /* recvPacket */) +{ + // empty + sLog.outDebug("WORLD: Received (MSG_GUILD_EVENT_LOG_QUERY)"); + //recvPacket.hexlike(); + + uint32 GuildId = GetPlayer()->GetGuildId(); + if (GuildId == 0) + return; + + Guild *pGuild = objmgr.GetGuildById(GuildId); + if(!pGuild) + return; + + pGuild->DisplayGuildEventlog(this); +} + +/****** GUILD BANK *******/ + +void WorldSession::HandleGuildBankGetMoneyAmount( WorldPacket & /* recv_data */ ) +{ + sLog.outDebug("WORLD: Received (MSG_GUILD_BANK_MONEY_WITHDRAWN)"); + //recv_data.hexlike(); + + uint32 GuildId = GetPlayer()->GetGuildId(); + if (GuildId == 0) + return; + + Guild *pGuild = objmgr.GetGuildById(GuildId); + if(!pGuild) + return; + + pGuild->SendMoneyInfo(this, GetPlayer()->GetGUIDLow()); +} + +void WorldSession::HandleGuildBankGetRights( WorldPacket& /* recv_data */ ) +{ + sLog.outDebug("WORLD: Received (MSG_GUILD_PERMISSIONS)"); + + uint32 GuildId = GetPlayer()->GetGuildId(); + if (GuildId == 0) + return; + + Guild *pGuild = objmgr.GetGuildById(GuildId); + if(!pGuild) + return; + + uint32 rankId = GetPlayer()->GetRank(); + + WorldPacket data(MSG_GUILD_PERMISSIONS, 4*15+1); + data << uint32(rankId); // guild rank id + data << uint32(pGuild->GetRankRights(rankId)); // rank rights + // money per day left + data << uint32(pGuild->GetMemberMoneyWithdrawRem(GetPlayer()->GetGUIDLow())); + data << uint8(pGuild->GetPurchasedTabs()); // tabs count + for(int i = 0; i < GUILD_BANK_MAX_TABS; ++i) + { + data << uint32(pGuild->GetBankRights(rankId, uint8(i))); + data << uint32(pGuild->GetMemberSlotWithdrawRem(GetPlayer()->GetGUIDLow(), uint8(i))); + } + SendPacket(&data); + sLog.outDebug("WORLD: Sent (MSG_GUILD_PERMISSIONS)"); +} + +/* Called when clicking on Guild bank gameobject */ +void WorldSession::HandleGuildBankQuery( WorldPacket & recv_data ) +{ + sLog.outDebug("WORLD: Received (CMSG_GUILD_BANKER_ACTIVATE)"); + CHECK_PACKET_SIZE(recv_data,8+1); + uint64 GoGuid; + uint8 unk; + recv_data >> GoGuid >> unk; + + if (!objmgr.IsGuildVaultGameObject(_player, GoGuid)) + return; + + if (uint32 GuildId = GetPlayer()->GetGuildId()) + { + if(Guild *pGuild = objmgr.GetGuildById(GuildId)) + { + pGuild->DisplayGuildBankTabsInfo(this); + return; + } + } + + SendGuildCommandResult(GUILD_BANK_S, "", GUILD_PLAYER_NOT_IN_GUILD); +} + +/* Called when opening guild bank tab only (first one) */ +void WorldSession::HandleGuildBankTabColon( WorldPacket & recv_data ) +{ + sLog.outDebug("WORLD: Received (CMSG_GUILD_BANK_QUERY_TAB)"); + CHECK_PACKET_SIZE(recv_data,8+1+1); + uint64 GoGuid; + uint8 TabId,unk1; + recv_data >> GoGuid >> TabId >> unk1; + + if (!objmgr.IsGuildVaultGameObject(_player, GoGuid)) + return; + + uint32 GuildId = GetPlayer()->GetGuildId(); + if (GuildId == 0) + return; + + Guild *pGuild = objmgr.GetGuildById(GuildId); + if(!pGuild) + return; + + // Let's update the amount of gold the player can withdraw before displaying the content + // This is usefull if money withdraw right has changed + pGuild->SendMoneyInfo(this, GetPlayer()->GetGUIDLow()); + + pGuild->DisplayGuildBankContent(this, TabId); +} + +void WorldSession::HandleGuildBankDeposit( WorldPacket & recv_data ) +{ + sLog.outDebug("WORLD: Received (CMSG_GUILD_BANK_DEPOSIT_MONEY)"); + CHECK_PACKET_SIZE(recv_data,8+4); + uint64 GoGuid; + uint32 money; + recv_data >> GoGuid >> money; + + if (!money) + return; + + if (!objmgr.IsGuildVaultGameObject(_player, GoGuid)) + return; + + uint32 GuildId = GetPlayer()->GetGuildId(); + if (GuildId == 0) + return; + + Guild *pGuild = objmgr.GetGuildById(GuildId); + if(!pGuild) + return; + + if (GetPlayer()->GetMoney() < money) + return; + + CharacterDatabase.BeginTransaction(); + + pGuild->SetBankMoney(pGuild->GetGuildBankMoney()+money); + GetPlayer()->ModifyMoney(-int(money)); + GetPlayer()->SaveGoldToDB(); + + CharacterDatabase.CommitTransaction(); + + // logging money + if(_player->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE)) + { + sLog.outCommand("GM %s (Account: %u) deposit money (Amount: %u) to guild bank (Guild ID %u)", + _player->GetName(),_player->GetSession()->GetAccountId(),money,GuildId); + } + + // log + pGuild->LogBankEvent(GUILD_BANK_LOG_DEPOSIT_MONEY, uint8(0), GetPlayer()->GetGUIDLow(), money); + + pGuild->DisplayGuildBankTabsInfo(this); + pGuild->DisplayGuildBankContent(this, 0); + pGuild->DisplayGuildBankMoneyUpdate(); +} + +void WorldSession::HandleGuildBankWithdraw( WorldPacket & recv_data ) +{ + sLog.outDebug("WORLD: Received (CMSG_GUILD_BANK_WITHDRAW_MONEY)"); + CHECK_PACKET_SIZE(recv_data,8+4); + uint64 GoGuid; + uint32 money; + recv_data >> GoGuid >> money; + + if (!money) + return; + + if (!objmgr.IsGuildVaultGameObject(_player, GoGuid)) + return; + + uint32 GuildId = GetPlayer()->GetGuildId(); + if (GuildId == 0) + return; + + Guild *pGuild = objmgr.GetGuildById(GuildId); + if(!pGuild) + return; + + if (pGuild->GetGuildBankMoney()HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_WITHDRAW_GOLD)) + return; + + CharacterDatabase.BeginTransaction(); + + if (!pGuild->MemberMoneyWithdraw(money, GetPlayer()->GetGUIDLow())) + { + CharacterDatabase.RollbackTransaction(); + return; + } + + GetPlayer()->ModifyMoney(money); + GetPlayer()->SaveGoldToDB(); + + CharacterDatabase.CommitTransaction(); + + // Log + pGuild->LogBankEvent(GUILD_BANK_LOG_WITHDRAW_MONEY, uint8(0), GetPlayer()->GetGUIDLow(), money); + + pGuild->SendMoneyInfo(this, GetPlayer()->GetGUIDLow()); + pGuild->DisplayGuildBankTabsInfo(this); + pGuild->DisplayGuildBankContent(this, 0); + pGuild->DisplayGuildBankMoneyUpdate(); +} + +void WorldSession::HandleGuildBankDepositItem( WorldPacket & recv_data ) +{ + sLog.outDebug("WORLD: Received (CMSG_GUILD_BANK_SWAP_ITEMS)"); + //recv_data.hexlike(); + + uint64 GoGuid; + uint8 BankToBank; + + uint8 BankTab, BankTabSlot, AutoStore, AutoStoreCount, PlayerSlot, PlayerBag, SplitedAmount = 0; + uint8 BankTabDst, BankTabSlotDst, unk2, ToChar = 1; + uint32 ItemEntry, unk1; + bool BankToChar = false; + + CHECK_PACKET_SIZE(recv_data,8+1); + recv_data >> GoGuid >> BankToBank; + if (BankToBank) + { + // recheck + CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+1+1+4+1+1+4+1+1); + recv_data >> BankTabDst; + recv_data >> BankTabSlotDst; + recv_data >> unk1; // always 0 + recv_data >> BankTab; + recv_data >> BankTabSlot; + recv_data >> ItemEntry; + recv_data >> unk2; // always 0 + recv_data >> SplitedAmount; + + if (BankTabSlotDst >= GUILD_BANK_MAX_SLOTS) + return; + if (BankTabDst == BankTab && BankTabSlotDst == BankTabSlot) + return; + } + else + { + // recheck + CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+1+1+4+1); + recv_data >> BankTab; + recv_data >> BankTabSlot; + recv_data >> ItemEntry; + recv_data >> AutoStore; + if (AutoStore) + { + // recheck + CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+1); + recv_data >> AutoStoreCount; + } + // recheck + CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+1+1); + recv_data >> PlayerBag; + recv_data >> PlayerSlot; + if (!AutoStore) + { + // recheck + CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+1+1); + recv_data >> ToChar; + recv_data >> SplitedAmount; + } + + if (BankTabSlot >= GUILD_BANK_MAX_SLOTS && BankTabSlot != 0xFF) + return; + } + + if (!objmgr.IsGuildVaultGameObject(_player, GoGuid)) + return; + + uint32 GuildId = GetPlayer()->GetGuildId(); + if (GuildId == 0) + return; + + Guild *pGuild = objmgr.GetGuildById(GuildId); + if(!pGuild) + return; + + Player *pl = GetPlayer(); + + // Bank <-> Bank + if (BankToBank) + { + // empty operation + if(BankTab==BankTabDst && BankTabSlot==BankTabSlotDst) + return; + + Item *pItemSrc = pGuild->GetItem(BankTab, BankTabSlot); + if (!pItemSrc) // may prevent crash + return; + + if(SplitedAmount > pItemSrc->GetCount()) + return; // cheating? + else if(SplitedAmount == pItemSrc->GetCount()) + SplitedAmount = 0; // no split + + Item *pItemDst = pGuild->GetItem(BankTabDst, BankTabSlotDst); + + if(BankTab!=BankTabDst) + { + // check dest pos rights (if different tabs) + if(!pGuild->IsMemberHaveRights(pl->GetGUIDLow(), BankTabDst, GUILD_BANK_RIGHT_DEPOSIT_ITEM)) + return; + + // check source pos rights (if different tabs) + uint32 remRight = pGuild->GetMemberSlotWithdrawRem(pl->GetGUIDLow(), BankTab); + if(remRight <= 0) + return; + } + + if (SplitedAmount) + { // Bank -> Bank item split (in empty or non empty slot + GuildItemPosCountVec dest; + uint8 msg = pGuild->CanStoreItem(BankTabDst,BankTabSlotDst,dest,SplitedAmount,pItemSrc,false); + if( msg != EQUIP_ERR_OK ) + { + pl->SendEquipError( msg, pItemSrc, NULL ); + return; + } + + Item *pNewItem = pItemSrc->CloneItem( SplitedAmount ); + if( !pNewItem ) + { + pl->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, pItemSrc, NULL ); + return; + } + + CharacterDatabase.BeginTransaction(); + pGuild->LogBankEvent(GUILD_BANK_LOG_MOVE_ITEM, BankTab, pl->GetGUIDLow(), pItemSrc->GetEntry(), SplitedAmount, BankTabDst); + + pl->ItemRemovedQuestCheck( pItemSrc->GetEntry(), SplitedAmount ); + pItemSrc->SetCount( pItemSrc->GetCount() - SplitedAmount ); + pItemSrc->FSetState(ITEM_CHANGED); + pItemSrc->SaveToDB(); // not in inventory and can be save standalone + pGuild->StoreItem(BankTabDst,dest,pNewItem); + CharacterDatabase.CommitTransaction(); + } + else // non split + { + GuildItemPosCountVec gDest; + uint8 msg = pGuild->CanStoreItem(BankTabDst,BankTabSlotDst,gDest,pItemSrc->GetCount(),pItemSrc,false); + if( msg == EQUIP_ERR_OK ) // merge to + { + CharacterDatabase.BeginTransaction(); + pGuild->LogBankEvent(GUILD_BANK_LOG_MOVE_ITEM, BankTab, pl->GetGUIDLow(), pItemSrc->GetEntry(), pItemSrc->GetCount(), BankTabDst); + + pGuild->RemoveItem(BankTab, BankTabSlot); + pGuild->StoreItem(BankTabDst, gDest, pItemSrc); + CharacterDatabase.CommitTransaction(); + } + else // swap + { + gDest.clear(); + uint8 msg = pGuild->CanStoreItem(BankTabDst,BankTabSlotDst,gDest,pItemSrc->GetCount(),pItemSrc,true); + if( msg != EQUIP_ERR_OK ) + { + pl->SendEquipError( msg, pItemSrc, NULL ); + return; + } + + GuildItemPosCountVec gSrc; + msg = pGuild->CanStoreItem(BankTab,BankTabSlot,gSrc,pItemDst->GetCount(),pItemDst,true); + if( msg != EQUIP_ERR_OK ) + { + pl->SendEquipError( msg, pItemDst, NULL ); + return; + } + + if(BankTab!=BankTabDst) + { + // check source pos rights (item swapped to src) + if(!pGuild->IsMemberHaveRights(pl->GetGUIDLow(), BankTab, GUILD_BANK_RIGHT_DEPOSIT_ITEM)) + return; + + // check dest pos rights (item swapped to src) + uint32 remRightDst = pGuild->GetMemberSlotWithdrawRem(pl->GetGUIDLow(), BankTabDst); + if(remRightDst <= 0) + return; + } + + CharacterDatabase.BeginTransaction(); + pGuild->LogBankEvent(GUILD_BANK_LOG_MOVE_ITEM, BankTab, pl->GetGUIDLow(), pItemSrc->GetEntry(), pItemSrc->GetCount(), BankTabDst); + pGuild->LogBankEvent(GUILD_BANK_LOG_MOVE_ITEM, BankTabDst, pl->GetGUIDLow(), pItemDst->GetEntry(), pItemDst->GetCount(), BankTab); + + pGuild->RemoveItem(BankTab, BankTabSlot); + pGuild->RemoveItem(BankTabDst, BankTabSlotDst); + pGuild->StoreItem(BankTab, gSrc, pItemDst); + pGuild->StoreItem(BankTabDst, gDest, pItemSrc); + CharacterDatabase.CommitTransaction(); + } + } + pGuild->DisplayGuildBankContentUpdate(BankTab,BankTabSlot,BankTab==BankTabDst ? BankTabSlotDst : -1); + if(BankTab!=BankTabDst) + pGuild->DisplayGuildBankContentUpdate(BankTabDst,BankTabSlotDst); + return; + } + + // Player <-> Bank + + // char->bank autostore click return BankTabSlot = 255 = NULL_SLOT + // do similar for bank->char + if(AutoStore && ToChar) + { + PlayerBag = NULL_BAG; + PlayerSlot = NULL_SLOT; + } + + // allow work with inventory only + if(!Player::IsInventoryPos(PlayerBag,PlayerSlot) && !(PlayerBag == NULL_BAG && PlayerSlot == NULL_SLOT) ) + { + _player->SendEquipError( EQUIP_ERR_NONE, NULL, NULL ); + return; + } + + Item *pItemBank = pGuild->GetItem(BankTab, BankTabSlot); + Item *pItemChar = GetPlayer()->GetItemByPos(PlayerBag, PlayerSlot); + if (!pItemChar && !pItemBank) // Nothing to do + return; + + if (!pItemChar && !ToChar) // Problem to get item from player + return; + + if (!pItemBank && ToChar) // Problem to get bank item + return; + + // BankToChar swap or char to bank remaining + + if (ToChar) // Bank -> Char cases + { + if(SplitedAmount > pItemBank->GetCount()) + return; // cheating? + else if(SplitedAmount == pItemBank->GetCount()) + SplitedAmount = 0; // no split + + if (SplitedAmount) + { // Bank -> Char split to slot (patly move) + Item *pNewItem = pItemBank->CloneItem( SplitedAmount ); + if( !pNewItem ) + { + pl->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, pItemBank, NULL ); + return; + } + + ItemPosCountVec dest; + uint8 msg = pl->CanStoreItem(PlayerBag, PlayerSlot, dest, pNewItem, false); + if( msg != EQUIP_ERR_OK ) + { + pl->SendEquipError( msg, pNewItem, NULL ); + delete pNewItem; + return; + } + + // check source pos rights (item moved to inventory) + uint32 remRight = pGuild->GetMemberSlotWithdrawRem(pl->GetGUIDLow(), BankTab); + if(remRight <= 0) + { + delete pNewItem; + return; + } + + CharacterDatabase.BeginTransaction(); + pGuild->LogBankEvent(GUILD_BANK_LOG_WITHDRAW_ITEM, BankTab, pl->GetGUIDLow(), pItemBank->GetEntry(), SplitedAmount); + + pItemBank->SetCount(pItemBank->GetCount()-SplitedAmount); + pItemBank->FSetState(ITEM_CHANGED); + pItemBank->SaveToDB(); // not in inventory and can be save standalone + pl->MoveItemToInventory(dest,pNewItem,true); + pl->SaveInventoryAndGoldToDB(); + + pGuild->MemberItemWithdraw(BankTab, pl->GetGUIDLow()); + CharacterDatabase.CommitTransaction(); + } + else // Bank -> Char swap with slot (move) + { + ItemPosCountVec dest; + uint8 msg = pl->CanStoreItem(PlayerBag, PlayerSlot, dest, pItemBank, false); + if( msg == EQUIP_ERR_OK ) // merge case + { + // check source pos rights (item moved to inventory) + uint32 remRight = pGuild->GetMemberSlotWithdrawRem(pl->GetGUIDLow(), BankTab); + if(remRight <= 0) + return; + + CharacterDatabase.BeginTransaction(); + pGuild->LogBankEvent(GUILD_BANK_LOG_WITHDRAW_ITEM, BankTab, pl->GetGUIDLow(), pItemBank->GetEntry(), pItemBank->GetCount()); + + pGuild->RemoveItem(BankTab, BankTabSlot); + pl->MoveItemToInventory(dest,pItemBank,true); + pl->SaveInventoryAndGoldToDB(); + + pGuild->MemberItemWithdraw(BankTab, pl->GetGUIDLow()); + CharacterDatabase.CommitTransaction(); + } + else // Bank <-> Char swap items + { + // check source pos rights (item swapped to bank) + if(!pGuild->IsMemberHaveRights(pl->GetGUIDLow(), BankTab, GUILD_BANK_RIGHT_DEPOSIT_ITEM)) + return; + + if(pItemChar) + { + if(!pItemChar->CanBeTraded()) + { + _player->SendEquipError( EQUIP_ERR_ITEMS_CANT_BE_SWAPPED, pItemChar, NULL ); + return; + } + } + + ItemPosCountVec iDest; + msg = pl->CanStoreItem(PlayerBag, PlayerSlot, iDest, pItemBank, true); + if( msg != EQUIP_ERR_OK ) + { + pl->SendEquipError( msg, pItemBank, NULL ); + return; + } + + GuildItemPosCountVec gDest; + if(pItemChar) + { + msg = pGuild->CanStoreItem(BankTab,BankTabSlot,gDest,pItemChar->GetCount(),pItemChar,true); + if( msg != EQUIP_ERR_OK ) + { + pl->SendEquipError( msg, pItemChar, NULL ); + return; + } + } + + // check source pos rights (item moved to inventory) + uint32 remRight = pGuild->GetMemberSlotWithdrawRem(pl->GetGUIDLow(), BankTab); + if(remRight <= 0) + return; + + if(pItemChar) + { + // logging item move to bank + if(_player->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE)) + { + sLog.outCommand("GM %s (Account: %u) deposit item: %s (Entry: %d Count: %u) to guild bank (Guild ID: %u )", + _player->GetName(),_player->GetSession()->GetAccountId(), + pItemChar->GetProto()->Name1,pItemChar->GetEntry(),pItemChar->GetCount(), + GuildId); + } + } + + CharacterDatabase.BeginTransaction(); + pGuild->LogBankEvent(GUILD_BANK_LOG_WITHDRAW_ITEM, BankTab, pl->GetGUIDLow(), pItemBank->GetEntry(), pItemBank->GetCount()); + if(pItemChar) + pGuild->LogBankEvent(GUILD_BANK_LOG_DEPOSIT_ITEM, BankTab, pl->GetGUIDLow(), pItemChar->GetEntry(), pItemChar->GetCount()); + + pGuild->RemoveItem(BankTab, BankTabSlot); + if(pItemChar) + { + pl->MoveItemFromInventory(PlayerBag, PlayerSlot, true); + pItemChar->DeleteFromInventoryDB(); + } + + if(pItemChar) + pGuild->StoreItem(BankTab, gDest, pItemChar); + pl->MoveItemToInventory(iDest,pItemBank,true); + pl->SaveInventoryAndGoldToDB(); + + pGuild->MemberItemWithdraw(BankTab, pl->GetGUIDLow()); + CharacterDatabase.CommitTransaction(); + } + } + pGuild->DisplayGuildBankContentUpdate(BankTab,BankTabSlot); + return; + } // End "To char" part + + // Char -> Bank cases + + if(!pItemChar->CanBeTraded()) + { + _player->SendEquipError( EQUIP_ERR_ITEMS_CANT_BE_SWAPPED, pItemChar, NULL ); + return; + } + + // check source pos rights (item moved to bank) + if(!pGuild->IsMemberHaveRights(pl->GetGUIDLow(), BankTab, GUILD_BANK_RIGHT_DEPOSIT_ITEM)) + return; + + if(SplitedAmount > pItemChar->GetCount()) + return; // cheating? + else if(SplitedAmount == pItemChar->GetCount()) + SplitedAmount = 0; // no split + + if (SplitedAmount) + { // Char -> Bank split to empty or non-empty slot (partly move) + GuildItemPosCountVec dest; + uint8 msg = pGuild->CanStoreItem(BankTab,BankTabSlot,dest,SplitedAmount,pItemChar,false); + if( msg != EQUIP_ERR_OK ) + { + pl->SendEquipError( msg, pItemChar, NULL ); + return; + } + + Item *pNewItem = pItemChar->CloneItem( SplitedAmount ); + if( !pNewItem ) + { + pl->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, pItemChar, NULL ); + return; + } + + // logging item move to bank (before items merge + if(_player->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE)) + { + sLog.outCommand("GM %s (Account: %u) deposit item: %s (Entry: %d Count: %u) to guild bank (Guild ID: %u )", + _player->GetName(),_player->GetSession()->GetAccountId(), + pItemChar->GetProto()->Name1,pItemChar->GetEntry(),SplitedAmount,GuildId); + } + + CharacterDatabase.BeginTransaction(); + pGuild->LogBankEvent(GUILD_BANK_LOG_DEPOSIT_ITEM, BankTab, pl->GetGUIDLow(), pItemChar->GetEntry(), SplitedAmount); + + pl->ItemRemovedQuestCheck( pItemChar->GetEntry(), SplitedAmount ); + pItemChar->SetCount(pItemChar->GetCount()-SplitedAmount); + pItemChar->SetState(ITEM_CHANGED); + pl->SaveInventoryAndGoldToDB(); + pGuild->StoreItem(BankTab, dest, pNewItem); + CharacterDatabase.CommitTransaction(); + + pGuild->DisplayGuildBankContentUpdate(BankTab,dest); + } + else // Char -> Bank swap with empty or non-empty (move) + { + GuildItemPosCountVec dest; + uint8 msg = pGuild->CanStoreItem(BankTab,BankTabSlot,dest,pItemChar->GetCount(),pItemChar,false); + if( msg == EQUIP_ERR_OK ) // merge + { + // logging item move to bank + if(_player->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE)) + { + sLog.outCommand("GM %s (Account: %u) deposit item: %s (Entry: %d Count: %u) to guild bank (Guild ID: %u )", + _player->GetName(),_player->GetSession()->GetAccountId(), + pItemChar->GetProto()->Name1,pItemChar->GetEntry(),pItemChar->GetCount(), + GuildId); + } + + CharacterDatabase.BeginTransaction(); + pGuild->LogBankEvent(GUILD_BANK_LOG_DEPOSIT_ITEM, BankTab, pl->GetGUIDLow(), pItemChar->GetEntry(), pItemChar->GetCount()); + + pl->MoveItemFromInventory(PlayerBag, PlayerSlot, true); + pItemChar->DeleteFromInventoryDB(); + + pGuild->StoreItem(BankTab,dest,pItemChar); + pl->SaveInventoryAndGoldToDB(); + CharacterDatabase.CommitTransaction(); + + pGuild->DisplayGuildBankContentUpdate(BankTab,dest); + } + else // Char <-> Bank swap items (posible NULL bank item) + { + ItemPosCountVec iDest; + if(pItemBank) + { + msg = pl->CanStoreItem(PlayerBag, PlayerSlot, iDest, pItemBank, true); + if( msg != EQUIP_ERR_OK ) + { + pl->SendEquipError( msg, pItemBank, NULL ); + return; + } + } + + GuildItemPosCountVec gDest; + msg = pGuild->CanStoreItem(BankTab,BankTabSlot,gDest,pItemChar->GetCount(),pItemChar,true); + if( msg != EQUIP_ERR_OK ) + { + pl->SendEquipError( msg, pItemChar, NULL ); + return; + } + + if(pItemBank) + { + // check bank pos rights (item swapped with inventory) + uint32 remRight = pGuild->GetMemberSlotWithdrawRem(pl->GetGUIDLow(), BankTab); + if(remRight <= 0) + return; + } + + // logging item move to bank + if(_player->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE)) + { + sLog.outCommand("GM %s (Account: %u) deposit item: %s (Entry: %d Count: %u) to guild bank (Guild ID: %u )", + _player->GetName(),_player->GetSession()->GetAccountId(), + pItemChar->GetProto()->Name1,pItemChar->GetEntry(),pItemChar->GetCount(), + GuildId); + } + + CharacterDatabase.BeginTransaction(); + if(pItemBank) + pGuild->LogBankEvent(GUILD_BANK_LOG_WITHDRAW_ITEM, BankTab, pl->GetGUIDLow(), pItemBank->GetEntry(), pItemBank->GetCount()); + pGuild->LogBankEvent(GUILD_BANK_LOG_DEPOSIT_ITEM, BankTab, pl->GetGUIDLow(), pItemChar->GetEntry(), pItemChar->GetCount()); + + pl->MoveItemFromInventory(PlayerBag, PlayerSlot, true); + pItemChar->DeleteFromInventoryDB(); + if(pItemBank) + pGuild->RemoveItem(BankTab, BankTabSlot); + + pGuild->StoreItem(BankTab,gDest,pItemChar); + if(pItemBank) + pl->MoveItemToInventory(iDest,pItemBank,true); + pl->SaveInventoryAndGoldToDB(); + if(pItemBank) + pGuild->MemberItemWithdraw(BankTab, pl->GetGUIDLow()); + CharacterDatabase.CommitTransaction(); + + pGuild->DisplayGuildBankContentUpdate(BankTab,gDest); + } + } +} + +void WorldSession::HandleGuildBankBuyTab( WorldPacket & recv_data ) +{ + sLog.outDebug("WORLD: Received (CMSG_GUILD_BANK_BUY_TAB)"); + CHECK_PACKET_SIZE(recv_data, 8+1); + //recv_data.hexlike(); + uint64 GoGuid; + uint8 TabId; + + recv_data >> GoGuid; + recv_data >> TabId; + + if (!objmgr.IsGuildVaultGameObject(_player, GoGuid)) + return; + + uint32 GuildId = GetPlayer()->GetGuildId(); + if (GuildId==0) + return; + + Guild *pGuild = objmgr.GetGuildById(GuildId); + if(!pGuild) + return; + + uint32 TabCost = objmgr.GetGuildBankTabPrice(TabId) * GOLD; + if (!TabCost) + return; + + if (pGuild->GetPurchasedTabs() >= GUILD_BANK_MAX_TABS) + return; + + if (TabId != pGuild->GetPurchasedTabs()) // purchased_tabs = 0 when buying Tab 0, that is why this check can be made + { + sLog.outError("Error: trying to buy a tab non contigous to owned ones"); + return; + } + + if (GetPlayer()->GetMoney() < TabCost) // Should not happen, this is checked by client + return; + + // Go on with creating tab + pGuild->CreateNewBankTab(); + GetPlayer()->ModifyMoney(-int(TabCost)); + pGuild->SetBankMoneyPerDay(GetPlayer()->GetRank(), WITHDRAW_MONEY_UNLIMITED); + pGuild->SetBankRightsAndSlots(GetPlayer()->GetRank(), TabId, GUILD_BANK_RIGHT_FULL, WITHDRAW_SLOT_UNLIMITED, true); + pGuild->Roster(this); + pGuild->DisplayGuildBankTabsInfo(this); +} + +void WorldSession::HandleGuildBankModifyTab( WorldPacket & recv_data ) +{ + sLog.outDebug("WORLD: Received (CMSG_GUILD_BANK_UPDATE_TAB)"); + //recv_data.hexlike(); + CHECK_PACKET_SIZE(recv_data, 8+1+1+1); + uint64 GoGuid; + uint8 TabId; + std::string Name; + std::string IconIndex; + + recv_data >> GoGuid; + recv_data >> TabId; + recv_data >> Name; + recv_data >> IconIndex; + + if(Name.empty()) + return; + + if(IconIndex.empty()) + return; + + if (!objmgr.IsGuildVaultGameObject(_player, GoGuid)) + return; + + uint32 GuildId = GetPlayer()->GetGuildId(); + if (GuildId==0) + return; + + Guild *pGuild = objmgr.GetGuildById(GuildId); + if(!pGuild) + return; + + pGuild->SetGuildBankTabInfo(TabId, Name, IconIndex); + pGuild->DisplayGuildBankTabsInfo(this); + pGuild->DisplayGuildBankContent(this, TabId); +} + +void WorldSession::HandleGuildBankLog( WorldPacket & recv_data ) +{ + sLog.outDebug("WORLD: Received (MSG_GUILD_BANK_LOG_QUERY)"); + CHECK_PACKET_SIZE(recv_data, 1); + + uint32 GuildId = GetPlayer()->GetGuildId(); + if (GuildId == 0) + return; + + Guild *pGuild = objmgr.GetGuildById(GuildId); + if(!pGuild) + return; + + uint8 TabId; + recv_data >> TabId; + + pGuild->DisplayGuildBankLogs(this, TabId); +} + +void WorldSession::HandleGuildBankTabText(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: Received MSG_QUERY_GUILD_BANK_TEXT"); + CHECK_PACKET_SIZE(recv_data, 1); + + uint32 GuildId = GetPlayer()->GetGuildId(); + if (GuildId == 0) + return; + + Guild *pGuild = objmgr.GetGuildById(GuildId); + if(!pGuild) + return; + + uint8 TabId; + recv_data >> TabId; + + pGuild->SendGuildBankTabText(this, TabId); +} + +void WorldSession::HandleGuildBankSetTabText(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: Received CMSG_SET_GUILD_BANK_TEXT"); + CHECK_PACKET_SIZE(recv_data, 1+1); + + uint32 GuildId = GetPlayer()->GetGuildId(); + if (GuildId == 0) + return; + + Guild *pGuild = objmgr.GetGuildById(GuildId); + if(!pGuild) + return; + + uint8 TabId; + std::string Text; + recv_data >> TabId; + recv_data >> Text; + + pGuild->SetGuildBankTabText(TabId, Text); +} + +void WorldSession::SendSaveGuildEmblem( uint32 msg ) +{ + WorldPacket data(MSG_SAVE_GUILD_EMBLEM, 4); + data << uint32(msg); // not part of guild + SendPacket( &data ); +} diff --git a/src/game/HateMatrix.h b/src/game/HateMatrix.h new file mode 100644 index 00000000000..fc0cbcee625 --- /dev/null +++ b/src/game/HateMatrix.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_HATEMATRIX_H +#define MANGOS_HATEMATRIX_H + +#include "Utilities/HashMap.h" +#include + +class Unit; + +struct MANGOS_DLL_DECL HateMatrix +{ + typedef hash_map HateMatrixMapType; + + inline uint32 operator[](Unit *unit) const + { + HateMatrixMapType::const_iterator iter = i_hateValues.find(unit); + return (iter == i_hateValues.end() ? 0 : iter->second); + } + + inline uint32& operator[](Unit *unit) + { + HateMatrixMapType::iterator iter = i_hateValues.find(unit); + if( iter == i_hateValues.end() ) + { + std::pair p = i_hateValues.insert( HateMatrixMapType::value_type(unit, 0) ); + assert(p.second); + iter = p.first; + } + + return iter->second; + } + + inline void ClearMatrix(void) { i_hateValues.clear(); } + + inline void RemoveValue(Unit *unit) + { + HateMatrixMapType::iterator iter = i_hateValues.find(unit); + if( iter != i_hateValues.end() ) + i_hateValues.erase( iter ); + } + + inline void AddValue(Unit *unit, uint32 val) + { + (*this)[unit] += val; + } + + private: + HateMatrixMapType i_hateValues; +}; + +struct HateBinder +{ + static uint32 si_noHateValue; + uint32 &i_hateValue; + Unit *i_unit; + HateBinder(uint32 &val, Unit *u) : i_hateValue(val), i_unit(u) {} + HateBinder() : i_hateValue(si_noHateValue), i_unit(NULL) {} + HateBinder(const HateBinder &obj) : i_hateValue(obj.i_hateValue), i_unit(obj.i_unit) {} + + HateBinder& operator=(const HateBinder &obj) + { + i_hateValue = obj.i_hateValue; + i_unit = obj.i_unit; + return *this; + } +}; +#endif diff --git a/src/game/HomeMovementGenerator.cpp b/src/game/HomeMovementGenerator.cpp new file mode 100644 index 00000000000..281909b68de --- /dev/null +++ b/src/game/HomeMovementGenerator.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "HomeMovementGenerator.h" +#include "Creature.h" +#include "Traveller.h" +#include "MapManager.h" +#include "ObjectAccessor.h" +#include "DestinationHolderImp.h" +#include "ObjectMgr.h" +#include "WorldPacket.h" + +void +HomeMovementGenerator::Initialize(Creature & owner) +{ + owner.RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + _setTargetLocation(owner); +} + +void +HomeMovementGenerator::Reset(Creature &) +{ +} + +void +HomeMovementGenerator::_setTargetLocation(Creature & owner) +{ + if( !&owner ) + return; + + if( owner.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED | UNIT_STAT_DISTRACTED) ) + return; + + float x, y, z; + owner.GetRespawnCoord(x, y, z); + + CreatureTraveller traveller(owner); + + uint32 travel_time = i_destinationHolder.SetDestination(traveller, x, y, z); + modifyTravelTime(travel_time); + owner.clearUnitState(UNIT_STAT_ALL_STATE); +} + +bool +HomeMovementGenerator::Update(Creature &owner, const uint32& time_diff) +{ + CreatureTraveller traveller( owner); + i_destinationHolder.UpdateTraveller(traveller, time_diff, false); + + if (time_diff > i_travel_timer) + { + owner.AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + + // restore orientation of not moving creature at returning to home + if(owner.GetDefaultMovementType()==IDLE_MOTION_TYPE) + { + if(CreatureData const* data = objmgr.GetCreatureData(owner.GetDBTableGUIDLow())) + { + owner.SetOrientation(data->orientation); + WorldPacket packet; + owner.BuildHeartBeatMsg(&packet); + owner.SendMessageToSet(&packet, false); + } + } + return false; + } + + i_travel_timer -= time_diff; + + return true; +} diff --git a/src/game/HomeMovementGenerator.h b/src/game/HomeMovementGenerator.h new file mode 100644 index 00000000000..aa7dc27a1b1 --- /dev/null +++ b/src/game/HomeMovementGenerator.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_HOMEMOVEMENTGENERATOR_H +#define MANGOS_HOMEMOVEMENTGENERATOR_H + +#include "MovementGenerator.h" +#include "DestinationHolder.h" +#include "Traveller.h" + +class Creature; + +template < class T > +class MANGOS_DLL_SPEC HomeMovementGenerator; + +template <> +class MANGOS_DLL_SPEC HomeMovementGenerator +: public MovementGeneratorMedium< Creature, HomeMovementGenerator > +{ + public: + + HomeMovementGenerator() {} + ~HomeMovementGenerator() {} + + void Initialize(Creature &); + void Finalize(Creature &) {} + void Reset(Creature &); + bool Update(Creature &, const uint32 &); + void modifyTravelTime(uint32 travel_time) { i_travel_timer = travel_time; } + MovementGeneratorType GetMovementGeneratorType() { return HOME_MOTION_TYPE; } + + bool GetDestination(float& x, float& y, float& z) const { i_destinationHolder.GetDestination(x,y,z); return true; } + private: + void _setTargetLocation(Creature &); + DestinationHolder< Traveller > i_destinationHolder; + + uint32 i_travel_timer; +}; +#endif diff --git a/src/game/HostilRefManager.cpp b/src/game/HostilRefManager.cpp new file mode 100644 index 00000000000..5ce8ec4d556 --- /dev/null +++ b/src/game/HostilRefManager.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "HostilRefManager.h" +#include "ThreatManager.h" +#include "Unit.h" +#include "Database/DBCStructure.h" +#include "SpellMgr.h" + +HostilRefManager::~HostilRefManager() +{ + deleteReferences(); +} + +//================================================= +// send threat to all my hateres for the pVictim +// The pVictim is hated than by them as well +// use for buffs and healing threat functionality + +void HostilRefManager::threatAssist(Unit *pVictim, float pThreat, SpellEntry const *pThreatSpell, bool pSingleTarget) +{ + HostilReference* ref; + + uint32 size = pSingleTarget ? 1 : getSize(); // if pSingleTarget do not devide threat + ref = getFirst(); + while(ref != NULL) + { + float threat = ThreatCalcHelper::calcThreat(pVictim, iOwner, pThreat, (pThreatSpell ? GetSpellSchoolMask(pThreatSpell) : SPELL_SCHOOL_MASK_NORMAL), pThreatSpell); + if(pVictim == getOwner()) + ref->addThreat(float (threat) / size); // It is faster to modify the threat durectly if possible + else + ref->getSource()->addThreat(pVictim, float (threat) / size); + ref = ref->next(); + } +} + +//================================================= + +void HostilRefManager::addThreatPercent(int32 pValue) +{ + HostilReference* ref; + + ref = getFirst(); + while(ref != NULL) + { + ref->addThreatPercent(pValue); + ref = ref->next(); + } +} + +//================================================= +// The online / offline status is given to the method. The calculation has to be done before + +void HostilRefManager::setOnlineOfflineState(bool pIsOnline) +{ + HostilReference* ref; + + ref = getFirst(); + while(ref != NULL) + { + ref->setOnlineOfflineState(pIsOnline); + ref = ref->next(); + } +} + +//================================================= +// The online / offline status is calculated and set + +void HostilRefManager::updateThreatTables() +{ + HostilReference* ref = getFirst(); + while(ref) + { + ref->updateOnlineStatus(); + ref = ref->next(); + } +} + +//================================================= +// The references are not needed anymore +// tell the source to remove them from the list and free the mem + +void HostilRefManager::deleteReferences() +{ + HostilReference* ref = getFirst(); + while(ref) + { + HostilReference* nextRef = ref->next(); + ref->removeReference(); + delete ref; + ref = nextRef; + } +} + +//================================================= +// delete one reference, defined by Unit + +void HostilRefManager::deleteReference(Unit *pCreature) +{ + HostilReference* ref = getFirst(); + while(ref) + { + HostilReference* nextRef = ref->next(); + if(ref->getSource()->getOwner() == pCreature) + { + ref->removeReference(); + delete ref; + break; + } + ref = nextRef; + } +} + +//================================================= +// set state for one reference, defined by Unit + +void HostilRefManager::setOnlineOfflineState(Unit *pCreature,bool pIsOnline) +{ + HostilReference* ref = getFirst(); + while(ref) + { + HostilReference* nextRef = ref->next(); + if(ref->getSource()->getOwner() == pCreature) + { + ref->setOnlineOfflineState(pIsOnline); + break; + } + ref = nextRef; + } +} + +//================================================= diff --git a/src/game/HostilRefManager.h b/src/game/HostilRefManager.h new file mode 100644 index 00000000000..b4e4707e9fe --- /dev/null +++ b/src/game/HostilRefManager.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _HOSTILEREFMANAGER +#define _HOSTILEREFMANAGER + +#include "Common.h" +#include "Utilities/LinkedReference/RefManager.h" + +class Unit; +class ThreatManager; +class HostilReference; +struct SpellEntry; + +//================================================= + +class HostilRefManager : public RefManager +{ + private: + Unit *iOwner; + public: + explicit HostilRefManager(Unit *pOwner) { iOwner = pOwner; } + ~HostilRefManager(); + + Unit* getOwner() { return iOwner; } + + // send threat to all my hateres for the pVictim + // The pVictim is hated than by them as well + // use for buffs and healing threat functionality + void threatAssist(Unit *pVictim, float threat, SpellEntry const *threatSpell = 0, bool pSingleTarget=false); + + void addThreatPercent(int32 pValue); + + // The references are not needed anymore + // tell the source to remove them from the list and free the mem + void deleteReferences(); + + HostilReference* getFirst() { return ((HostilReference* ) RefManager::getFirst()); } + + void updateThreatTables(); + + void setOnlineOfflineState(bool pIsOnline); + + // set state for one reference, defined by Unit + void setOnlineOfflineState(Unit *pCreature,bool pIsOnline); + + // delete one reference, defined by Unit + void deleteReference(Unit *pCreature); +}; +//================================================= +#endif diff --git a/src/game/IdleMovementGenerator.cpp b/src/game/IdleMovementGenerator.cpp new file mode 100644 index 00000000000..3932bd63f1f --- /dev/null +++ b/src/game/IdleMovementGenerator.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "IdleMovementGenerator.h" +#include "Creature.h" + +IdleMovementGenerator si_idleMovement; + +void +IdleMovementGenerator::Reset(Unit& /*owner*/) +{ +} + +void +DistractMovementGenerator::Initialize(Unit& owner) +{ + owner.addUnitState(UNIT_STAT_DISTRACTED); +} + +void +DistractMovementGenerator::Finalize(Unit& owner) +{ + owner.clearUnitState(UNIT_STAT_DISTRACTED); +} + +bool +DistractMovementGenerator::Update(Unit& owner, const uint32& time_diff) +{ + if(time_diff > m_timer) + return false; + + m_timer -= time_diff; + return true; +} diff --git a/src/game/IdleMovementGenerator.h b/src/game/IdleMovementGenerator.h new file mode 100644 index 00000000000..cd1c8a20ac7 --- /dev/null +++ b/src/game/IdleMovementGenerator.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_IDLEMOVEMENTGENERATOR_H +#define MANGOS_IDLEMOVEMENTGENERATOR_H + +#include "MovementGenerator.h" + +class MANGOS_DLL_SPEC IdleMovementGenerator : public MovementGenerator +{ + public: + + void Initialize(Unit &) { } + void Finalize(Unit &) { } + void Reset(Unit &); + bool Update(Unit &, const uint32 &) { return true; } + MovementGeneratorType GetMovementGeneratorType() { return IDLE_MOTION_TYPE; } +}; + +extern IdleMovementGenerator si_idleMovement; + +class MANGOS_DLL_SPEC DistractMovementGenerator : public MovementGenerator +{ + public: + explicit DistractMovementGenerator(uint32 timer) : m_timer(timer) {} + + void Initialize(Unit& owner); + void Finalize(Unit& owner); + void Reset(Unit& owner) { Initialize(owner); } + bool Update(Unit& owner, const uint32& time_diff); + MovementGeneratorType GetMovementGeneratorType() { return DISTRACT_MOTION_TYPE; } + + private: + uint32 m_timer; +}; + +#endif diff --git a/src/game/InstanceData.cpp b/src/game/InstanceData.cpp new file mode 100644 index 00000000000..78c7bea2584 --- /dev/null +++ b/src/game/InstanceData.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "InstanceData.h" +#include "Database/DatabaseEnv.h" +#include "Map.h" + +void InstanceData::SaveToDB() +{ + if(!Save()) return; + std::string data = Save(); + CharacterDatabase.escape_string(data); + CharacterDatabase.PExecute("UPDATE instance SET data = '%s' WHERE id = '%d'", data.c_str(), instance->GetInstanceId()); +} diff --git a/src/game/InstanceData.h b/src/game/InstanceData.h new file mode 100644 index 00000000000..518fa8661fd --- /dev/null +++ b/src/game/InstanceData.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_INSTANCE_DATA_H +#define MANGOS_INSTANCE_DATA_H + +#include "Common.h" + +class Map; +class Unit; +class Player; +class GameObject; +class Creature; + +class MANGOS_DLL_SPEC InstanceData +{ + public: + + explicit InstanceData(Map *map) : instance(map) {} + virtual ~InstanceData() {} + + Map *instance; + + //On creation, NOT load. + virtual void Initialize() {} + + //On load + virtual void Load(const char* /*data*/) {} + + //When save is needed, this function generates the data + virtual const char* Save() { return ""; } + + void SaveToDB(); + + //Called every map update + virtual void Update(uint32 /*diff*/) {} + + //Used by the map's CanEnter function. + //This is to prevent players from entering during boss encounters. + virtual bool IsEncounterInProgress() const { return false; }; + + //Called when a player successfully enters the instance. + virtual void OnPlayerEnter(Player *) {} + + //Called when a gameobject is created + virtual void OnObjectCreate(GameObject *) {} + + //called on creature creation + virtual void OnCreatureCreate(Creature * /*creature*/, uint32 /*creature_entry*/) {} +}; +#endif diff --git a/src/game/InstanceSaveMgr.cpp b/src/game/InstanceSaveMgr.cpp new file mode 100644 index 00000000000..aedf7015b3a --- /dev/null +++ b/src/game/InstanceSaveMgr.cpp @@ -0,0 +1,649 @@ +/* + * Copyright (C) 2005,2006,2007 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "InstanceSaveMgr.h" +#include "Common.h" +#include "Database/SQLStorage.h" + +#include "Player.h" +#include "GridNotifiers.h" +#include "WorldSession.h" +#include "Log.h" +#include "GridStates.h" +#include "CellImpl.h" +#include "Map.h" +#include "MapManager.h" +#include "MapInstanced.h" +#include "InstanceSaveMgr.h" +#include "Timer.h" +#include "GridNotifiersImpl.h" +#include "Config/ConfigEnv.h" +#include "Transports.h" +#include "ObjectAccessor.h" +#include "ObjectMgr.h" +#include "World.h" +#include "Group.h" +#include "InstanceData.h" +#include "ProgressBar.h" + +INSTANTIATE_SINGLETON_1( InstanceSaveManager ); + +InstanceSaveManager::InstanceSaveManager() : lock_instLists(false) +{ +} + +InstanceSaveManager::~InstanceSaveManager() +{ + // it is undefined whether this or objectmgr will be unloaded first + // so we must be prepared for both cases + lock_instLists = true; + for (InstanceSaveHashMap::iterator itr = m_instanceSaveById.begin(); itr != m_instanceSaveById.end(); ++itr) + { + InstanceSave *save = itr->second; + for(InstanceSave::PlayerListType::iterator itr = save->m_playerList.begin(), next = itr; itr != save->m_playerList.end(); itr = next) + { + ++next; + (*itr)->UnbindInstance(save->GetMapId(), save->GetDifficulty(), true); + } + save->m_playerList.clear(); + for(InstanceSave::GroupListType::iterator itr = save->m_groupList.begin(), next = itr; itr != save->m_groupList.end(); itr = next) + { + ++next; + (*itr)->UnbindInstance(save->GetMapId(), save->GetDifficulty(), true); + } + save->m_groupList.clear(); + delete save; + } +} + +/* +- adding instance into manager +- called from InstanceMap::Add, _LoadBoundInstances, LoadGroups +*/ +InstanceSave* InstanceSaveManager::AddInstanceSave(uint32 mapId, uint32 instanceId, uint8 difficulty, time_t resetTime, bool canReset, bool load) +{ + InstanceSave *save = GetInstanceSave(instanceId); + if(save) return save; + + const MapEntry* entry = sMapStore.LookupEntry(mapId); + if(!entry || instanceId == 0) + { + sLog.outError("InstanceSaveManager::AddInstanceSave: mapid = %d, instanceid = %d!", mapId, instanceId); + return NULL; + } + + if(!resetTime) + { + // initialize reset time + // for normal instances if no creatures are killed the instance will reset in two hours + if(entry->map_type == MAP_RAID || difficulty == DIFFICULTY_HEROIC) + resetTime = GetResetTimeFor(mapId); + else + { + resetTime = time(NULL) + 2 * HOUR; + // normally this will be removed soon after in InstanceMap::Add, prevent error + ScheduleReset(true, resetTime, InstResetEvent(0, mapId, instanceId)); + } + } + + sLog.outDebug("InstanceSaveManager::AddInstanceSave: mapid = %d, instanceid = %d", mapId, instanceId); + + save = new InstanceSave(mapId, instanceId, difficulty, resetTime, canReset); + if(!load) save->SaveToDB(); + + m_instanceSaveById[instanceId] = save; + return save; +} + +InstanceSave *InstanceSaveManager::GetInstanceSave(uint32 InstanceId) +{ + InstanceSaveHashMap::iterator itr = m_instanceSaveById.find(InstanceId); + return itr != m_instanceSaveById.end() ? itr->second : NULL; +} + +void InstanceSaveManager::DeleteInstanceFromDB(uint32 instanceid) +{ + CharacterDatabase.BeginTransaction(); + CharacterDatabase.PExecute("DELETE FROM instance WHERE id = '%u'", instanceid); + CharacterDatabase.PExecute("DELETE FROM character_instance WHERE instance = '%u'", instanceid); + CharacterDatabase.PExecute("DELETE FROM group_instance WHERE instance = '%u'", instanceid); + CharacterDatabase.CommitTransaction(); + // respawn times should be deleted only when the map gets unloaded +} + +void InstanceSaveManager::RemoveInstanceSave(uint32 InstanceId) +{ + InstanceSaveHashMap::iterator itr = m_instanceSaveById.find( InstanceId ); + if(itr != m_instanceSaveById.end()) + { + // save the resettime for normal instances only when they get unloaded + if(time_t resettime = itr->second->GetResetTimeForDB()) + CharacterDatabase.PExecute("UPDATE instance SET resettime = '"I64FMTD"' WHERE id = '%u'", (uint64)resettime, InstanceId); + delete itr->second; + m_instanceSaveById.erase(itr); + } +} + +InstanceSave::InstanceSave(uint16 MapId, uint32 InstanceId, uint8 difficulty, + time_t resetTime, bool canReset) +: m_mapid(MapId), m_instanceid(InstanceId), m_resetTime(resetTime), + m_difficulty(difficulty), m_canReset(canReset) +{ +} + +InstanceSave::~InstanceSave() +{ + // the players and groups must be unbound before deleting the save + assert(m_playerList.empty() && m_groupList.empty()); +} + +/* + Called from AddInstanceSave +*/ +void InstanceSave::SaveToDB() +{ + // save instance data too + std::string data; + + Map *map = MapManager::Instance().FindMap(m_instanceid, GetMapId()); + if(map) + { + assert(map->IsDungeon()); + InstanceData *iData = ((InstanceMap *)map)->GetInstanceData(); + if(iData && iData->Save()) + { + data = iData->Save(); + CharacterDatabase.escape_string(data); + } + } + + CharacterDatabase.PExecute("INSERT INTO instance VALUES ('%u', '%u', '"I64FMTD"', '%u', '%s')", m_instanceid, GetMapId(), (uint64)GetResetTimeForDB(), GetDifficulty(), data.c_str()); +} + +time_t InstanceSave::GetResetTimeForDB() +{ + // only save the reset time for normal instances + const MapEntry *entry = sMapStore.LookupEntry(GetMapId()); + if(!entry || entry->map_type == MAP_RAID || GetDifficulty() == DIFFICULTY_HEROIC) + return 0; + else + return GetResetTime(); +} + +// to cache or not to cache, that is the question +InstanceTemplate const* InstanceSave::GetTemplate() +{ + return objmgr.GetInstanceTemplate(m_mapid); +} + +MapEntry const* InstanceSave::GetMapEntry() +{ + return sMapStore.LookupEntry(m_mapid); +} + +void InstanceSave::DeleteFromDB() +{ + InstanceSaveManager::DeleteInstanceFromDB(GetInstanceId()); +} + +/* true if the instance save is still valid */ +bool InstanceSave::UnloadIfEmpty() +{ + if(m_playerList.empty() && m_groupList.empty()) + { + if(!sInstanceSaveManager.lock_instLists) + sInstanceSaveManager.RemoveInstanceSave(GetInstanceId()); + return false; + } + else + return true; +} + +void InstanceSaveManager::_DelHelper(DatabaseType &db, const char *fields, const char *table, const char *queryTail,...) +{ + Tokens fieldTokens = StrSplit(fields, ", "); + assert(fieldTokens.size() != 0); + + va_list ap; + char szQueryTail [MAX_QUERY_LEN]; + va_start(ap, queryTail); + int res = vsnprintf( szQueryTail, MAX_QUERY_LEN, queryTail, ap ); + va_end(ap); + + QueryResult *result = db.PQuery("SELECT %s FROM %s %s", fields, table, szQueryTail); + if(result) + { + do + { + Field *fields = result->Fetch(); + std::ostringstream ss; + for(size_t i = 0; i < fieldTokens.size(); i++) + { + std::string fieldValue = fields[i].GetCppString(); + db.escape_string(fieldValue); + ss << (i != 0 ? " AND " : "") << fieldTokens[i] << " = '" << fieldValue << "'"; + } + db.DirectPExecute("DELETE FROM %s WHERE %s", table, ss.str().c_str()); + } while (result->NextRow()); + delete result; + } +} + +void InstanceSaveManager::CleanupInstances() +{ + uint64 now = (uint64)time(NULL); + + barGoLink bar(2); + bar.step(); + + // load reset times and clean expired instances + sInstanceSaveManager.LoadResetTimes(); + + // clean character/group - instance binds with invalid group/characters + _DelHelper(CharacterDatabase, "character_instance.guid, instance", "character_instance", "LEFT JOIN characters ON character_instance.guid = characters.guid WHERE characters.guid IS NULL"); + _DelHelper(CharacterDatabase, "group_instance.leaderGuid, instance", "group_instance", "LEFT JOIN characters ON group_instance.leaderGuid = characters.guid LEFT JOIN groups ON group_instance.leaderGuid = groups.leaderGuid WHERE characters.guid IS NULL OR groups.leaderGuid IS NULL"); + + // clean instances that do not have any players or groups bound to them + _DelHelper(CharacterDatabase, "id, map, difficulty", "instance", "LEFT JOIN character_instance ON character_instance.instance = id LEFT JOIN group_instance ON group_instance.instance = id WHERE character_instance.instance IS NULL AND group_instance.instance IS NULL"); + + // clean invalid instance references in other tables + _DelHelper(CharacterDatabase, "character_instance.guid, instance", "character_instance", "LEFT JOIN instance ON character_instance.instance = instance.id WHERE instance.id IS NULL"); + _DelHelper(CharacterDatabase, "group_instance.leaderGuid, instance", "group_instance", "LEFT JOIN instance ON group_instance.instance = instance.id WHERE instance.id IS NULL"); + + // creature_respawn and gameobject_respawn are in another database + // first, obtain total instance set + std::set< uint32 > InstanceSet; + QueryResult *result = CharacterDatabase.PQuery("SELECT id FROM instance"); + if( result ) + { + do + { + Field *fields = result->Fetch(); + InstanceSet.insert(fields[0].GetUInt32()); + } + while (result->NextRow()); + delete result; + } + + // creature_respawn + result = WorldDatabase.PQuery("SELECT DISTINCT(instance) FROM creature_respawn WHERE instance <> 0"); + if( result ) + { + do + { + Field *fields = result->Fetch(); + if(InstanceSet.find(fields[0].GetUInt32()) == InstanceSet.end()) + WorldDatabase.DirectPExecute("DELETE FROM creature_respawn WHERE instance = '%u'", fields[0].GetUInt32()); + } + while (result->NextRow()); + delete result; + } + + // gameobject_respawn + result = WorldDatabase.PQuery("SELECT DISTINCT(instance) FROM gameobject_respawn WHERE instance <> 0"); + if( result ) + { + do + { + Field *fields = result->Fetch(); + if(InstanceSet.find(fields[0].GetUInt32()) == InstanceSet.end()) + WorldDatabase.DirectPExecute("DELETE FROM gameobject_respawn WHERE instance = '%u'", fields[0].GetUInt32()); + } + while (result->NextRow()); + delete result; + } + + bar.step(); + sLog.outString(); + sLog.outString( ">> Initialized %u instances", (uint32)InstanceSet.size()); +} + +void InstanceSaveManager::PackInstances() +{ + // this routine renumbers player instance associations in such a way so they start from 1 and go up + // TODO: this can be done a LOT more efficiently + + // obtain set of all associations + std::set< uint32 > InstanceSet; + + // all valid ids are in the instance table + // any associations to ids not in this table are assumed to be + // cleaned already in CleanupInstances + QueryResult *result = CharacterDatabase.PQuery("SELECT id FROM instance"); + if( result ) + { + do + { + Field *fields = result->Fetch(); + InstanceSet.insert(fields[0].GetUInt32()); + } + while (result->NextRow()); + delete result; + } + + barGoLink bar( InstanceSet.size() + 1); + bar.step(); + + uint32 InstanceNumber = 1; + // we do assume std::set is sorted properly on integer value + for (std::set< uint32 >::iterator i = InstanceSet.begin(); i != InstanceSet.end(); i++) + { + if (*i != InstanceNumber) + { + // remap instance id + WorldDatabase.PExecute("UPDATE creature_respawn SET instance = '%u' WHERE instance = '%u'", InstanceNumber, *i); + WorldDatabase.PExecute("UPDATE gameobject_respawn SET instance = '%u' WHERE instance = '%u'", InstanceNumber, *i); + CharacterDatabase.PExecute("UPDATE corpse SET instance = '%u' WHERE instance = '%u'", InstanceNumber, *i); + CharacterDatabase.PExecute("UPDATE character_instance SET instance = '%u' WHERE instance = '%u'", InstanceNumber, *i); + CharacterDatabase.PExecute("UPDATE instance SET id = '%u' WHERE id = '%u'", InstanceNumber, *i); + CharacterDatabase.PExecute("UPDATE group_instance SET instance = '%u' WHERE instance = '%u'", InstanceNumber, *i); + } + + ++InstanceNumber; + bar.step(); + } + + sLog.outString(); + sLog.outString( ">> Instance numbers remapped, next instance id is %u", InstanceNumber ); +} + +void InstanceSaveManager::LoadResetTimes() +{ + time_t now = time(NULL); + time_t today = (now / DAY) * DAY; + + // NOTE: Use DirectPExecute for tables that will be queried later + + // get the current reset times for normal instances (these may need to be updated) + // these are only kept in memory for InstanceSaves that are loaded later + // resettime = 0 in the DB for raid/heroic instances so those are skipped + typedef std::map > ResetTimeMapType; + ResetTimeMapType InstResetTime; + QueryResult *result = CharacterDatabase.PQuery("SELECT id, map, resettime FROM instance WHERE resettime > 0"); + if( result ) + { + do + { + if(uint64 resettime = (*result)[2].GetUInt64()) + { + uint32 id = (*result)[0].GetUInt32(); + uint32 mapid = (*result)[1].GetUInt32(); + InstResetTime[id] = std::pair(mapid, resettime); + } + } + while (result->NextRow()); + delete result; + + // update reset time for normal instances with the max creature respawn time + X hours + result = WorldDatabase.PQuery("SELECT MAX(respawntime), instance FROM creature_respawn WHERE instance > 0 GROUP BY instance"); + if( result ) + { + do + { + Field *fields = result->Fetch(); + uint32 instance = fields[1].GetUInt32(); + uint64 resettime = fields[0].GetUInt64() + 2 * HOUR; + ResetTimeMapType::iterator itr = InstResetTime.find(instance); + if(itr != InstResetTime.end() && itr->second.second != resettime) + { + CharacterDatabase.DirectPExecute("UPDATE instance SET resettime = '"I64FMTD"' WHERE id = '%u'", resettime, instance); + itr->second.second = resettime; + } + } + while (result->NextRow()); + delete result; + } + + // schedule the reset times + for(ResetTimeMapType::iterator itr = InstResetTime.begin(); itr != InstResetTime.end(); ++itr) + if(itr->second.second > now) + ScheduleReset(true, itr->second.second, InstResetEvent(0, itr->second.first, itr->first)); + } + + // load the global respawn times for raid/heroic instances + uint32 diff = sWorld.getConfig(CONFIG_INSTANCE_RESET_TIME_HOUR) * HOUR; + m_resetTimeByMapId.resize(sMapStore.GetNumRows()+1); + result = CharacterDatabase.Query("SELECT mapid, resettime FROM instance_reset"); + if(result) + { + do + { + Field *fields = result->Fetch(); + uint32 mapid = fields[0].GetUInt32(); + if(!objmgr.GetInstanceTemplate(mapid)) + { + sLog.outError("InstanceSaveManager::LoadResetTimes: invalid mapid %u in instance_reset!", mapid); + CharacterDatabase.DirectPExecute("DELETE FROM instance_reset WHERE mapid = '%u'", mapid); + continue; + } + + // update the reset time if the hour in the configs changes + uint64 oldresettime = fields[1].GetUInt64(); + uint64 newresettime = (oldresettime / DAY) * DAY + diff; + if(oldresettime != newresettime) + CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '"I64FMTD"' WHERE mapid = '%u'", newresettime, mapid); + + m_resetTimeByMapId[mapid] = newresettime; + } while(result->NextRow()); + delete result; + } + + // clean expired instances, references to them will be deleted in CleanupInstances + // must be done before calculating new reset times + _DelHelper(CharacterDatabase, "id, map, difficulty", "instance", "LEFT JOIN instance_reset ON mapid = map WHERE (instance.resettime < '"I64FMTD"' AND instance.resettime > '0') OR (NOT instance_reset.resettime IS NULL AND instance_reset.resettime < '"I64FMTD"')", (uint64)now, (uint64)now); + + // calculate new global reset times for expired instances and those that have never been reset yet + // add the global reset times to the priority queue + for(uint32 i = 0; i < sInstanceTemplate.MaxEntry; i++) + { + InstanceTemplate* temp = (InstanceTemplate*)objmgr.GetInstanceTemplate(i); + if(!temp) continue; + // only raid/heroic maps have a global reset time + const MapEntry* entry = sMapStore.LookupEntry(temp->map); + if(!entry || !entry->HasResetTime()) + continue; + + uint32 period = temp->reset_delay * DAY; + assert(period != 0); + time_t t = m_resetTimeByMapId[temp->map]; + if(!t) + { + // initialize the reset time + t = today + period + diff; + CharacterDatabase.DirectPExecute("INSERT INTO instance_reset VALUES ('%u','"I64FMTD"')", i, (uint64)t); + } + + if(t < now) + { + // assume that expired instances have already been cleaned + // calculate the next reset time + t = (t / DAY) * DAY; + t += ((today - t) / period + 1) * period + diff; + CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '"I64FMTD"' WHERE mapid = '%u'", (uint64)t, i); + } + + m_resetTimeByMapId[temp->map] = t; + + // schedule the global reset/warning + uint8 type = 1; + static int tim[4] = {3600, 900, 300, 60}; + for(; type < 4; type++) + if(t - tim[type-1] > now) break; + ScheduleReset(true, t - tim[type-1], InstResetEvent(type, i)); + } +} + +void InstanceSaveManager::ScheduleReset(bool add, time_t time, InstResetEvent event) +{ + if(add) m_resetTimeQueue.insert(std::pair(time, event)); + else + { + // find the event in the queue and remove it + ResetTimeQueue::iterator itr; + std::pair range; + range = m_resetTimeQueue.equal_range(time); + for(itr = range.first; itr != range.second; ++itr) + if(itr->second == event) { m_resetTimeQueue.erase(itr); return; } + // in case the reset time changed (should happen very rarely), we search the whole queue + if(itr == range.second) + { + for(itr = m_resetTimeQueue.begin(); itr != m_resetTimeQueue.end(); ++itr) + if(itr->second == event) { m_resetTimeQueue.erase(itr); return; } + if(itr == m_resetTimeQueue.end()) + sLog.outError("InstanceSaveManager::ScheduleReset: cannot cancel the reset, the event(%d,%d,%d) was not found!", event.type, event.mapid, event.instanceId); + } + } +} + +void InstanceSaveManager::Update() +{ + time_t now = time(NULL), t; + while(!m_resetTimeQueue.empty() && (t = m_resetTimeQueue.begin()->first) < now) + { + InstResetEvent &event = m_resetTimeQueue.begin()->second; + if(event.type == 0) + { + // for individual normal instances, max creature respawn + X hours + _ResetInstance(event.mapid, event.instanceId); + m_resetTimeQueue.erase(m_resetTimeQueue.begin()); + } + else + { + // global reset/warning for a certain map + time_t resetTime = GetResetTimeFor(event.mapid); + _ResetOrWarnAll(event.mapid, event.type != 4, resetTime - now); + if(event.type != 4) + { + // schedule the next warning/reset + event.type++; + static int tim[4] = {3600, 900, 300, 60}; + ScheduleReset(true, resetTime - tim[event.type-1], event); + } + m_resetTimeQueue.erase(m_resetTimeQueue.begin()); + } + } +} + +void InstanceSaveManager::_ResetSave(InstanceSaveHashMap::iterator &itr) +{ + // unbind all players bound to the instance + // do not allow UnbindInstance to automatically unload the InstanceSaves + lock_instLists = true; + InstanceSave::PlayerListType &pList = itr->second->m_playerList; + while(!pList.empty()) + { + Player *player = *(pList.begin()); + player->UnbindInstance(itr->second->GetMapId(), itr->second->GetDifficulty(), true); + } + InstanceSave::GroupListType &gList = itr->second->m_groupList; + while(!gList.empty()) + { + Group *group = *(gList.begin()); + group->UnbindInstance(itr->second->GetMapId(), itr->second->GetDifficulty(), true); + } + m_instanceSaveById.erase(itr++); + lock_instLists = false; +} + +void InstanceSaveManager::_ResetInstance(uint32 mapid, uint32 instanceId) +{ + sLog.outDebug("InstanceSaveMgr::_ResetInstance %u, %u", mapid, instanceId); + Map *map = (MapInstanced*)MapManager::Instance().GetBaseMap(mapid); + if(!map->Instanceable()) + return; + + InstanceSaveHashMap::iterator itr = m_instanceSaveById.find(instanceId); + if(itr != m_instanceSaveById.end()) _ResetSave(itr); + DeleteInstanceFromDB(instanceId); // even if save not loaded + + Map* iMap = ((MapInstanced*)map)->FindMap(instanceId); + if(iMap && iMap->IsDungeon()) ((InstanceMap*)iMap)->Reset(INSTANCE_RESET_RESPAWN_DELAY); + else objmgr.DeleteRespawnTimeForInstance(instanceId); // even if map is not loaded +} + +void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, bool warn, uint32 timeLeft) +{ + // global reset for all instances of the given map + // note: this isn't fast but it's meant to be executed very rarely + Map *map = (MapInstanced*)MapManager::Instance().GetBaseMap(mapid); + if(!map->Instanceable()) + return; + uint64 now = (uint64)time(NULL); + + if(!warn) + { + // this is called one minute before the reset time + InstanceTemplate* temp = (InstanceTemplate*)objmgr.GetInstanceTemplate(mapid); + if(!temp || !temp->reset_delay) + { + sLog.outError("InstanceSaveManager::ResetOrWarnAll: no instance template or reset delay for map %d", mapid); + return; + } + + // remove all binds to instances of the given map + for(InstanceSaveHashMap::iterator itr = m_instanceSaveById.begin(); itr != m_instanceSaveById.end();) + { + if(itr->second->GetMapId() == mapid) + _ResetSave(itr); + else + ++itr; + } + + // delete them from the DB, even if not loaded + CharacterDatabase.BeginTransaction(); + CharacterDatabase.PExecute("DELETE FROM character_instance USING character_instance LEFT JOIN instance ON character_instance.instance = id WHERE map = '%u'", mapid); + CharacterDatabase.PExecute("DELETE FROM group_instance USING group_instance LEFT JOIN instance ON group_instance.instance = id WHERE map = '%u'", mapid); + CharacterDatabase.PExecute("DELETE FROM instance WHERE map = '%u'", mapid); + CharacterDatabase.CommitTransaction(); + + // calculate the next reset time + uint32 diff = sWorld.getConfig(CONFIG_INSTANCE_RESET_TIME_HOUR) * HOUR; + uint32 period = temp->reset_delay * DAY; + uint64 next_reset = ((now + timeLeft + MINUTE) / DAY * DAY) + period + diff; + // update it in the DB + CharacterDatabase.PExecute("UPDATE instance_reset SET resettime = '"I64FMTD"' WHERE mapid = '%d'", next_reset, mapid); + } + + MapInstanced::InstancedMaps &instMaps = ((MapInstanced*)map)->GetInstancedMaps(); + MapInstanced::InstancedMaps::iterator mitr; + for(mitr = instMaps.begin(); mitr != instMaps.end(); ++mitr) + { + Map *map = mitr->second; + if(!map->IsDungeon()) continue; + if(warn) ((InstanceMap*)map)->SendResetWarnings(timeLeft); + else ((InstanceMap*)map)->Reset(INSTANCE_RESET_GLOBAL); + } + + // TODO: delete creature/gameobject respawn times even if the maps are not loaded +} + +uint32 InstanceSaveManager::GetNumBoundPlayersTotal() +{ + uint32 ret = 0; + for(InstanceSaveHashMap::iterator itr = m_instanceSaveById.begin(); itr != m_instanceSaveById.end(); ++itr) + ret += itr->second->GetPlayerCount(); + return ret; +} + +uint32 InstanceSaveManager::GetNumBoundGroupsTotal() +{ + uint32 ret = 0; + for(InstanceSaveHashMap::iterator itr = m_instanceSaveById.begin(); itr != m_instanceSaveById.end(); ++itr) + ret += itr->second->GetGroupCount(); + return ret; +} diff --git a/src/game/InstanceSaveMgr.h b/src/game/InstanceSaveMgr.h new file mode 100644 index 00000000000..961e915eb11 --- /dev/null +++ b/src/game/InstanceSaveMgr.h @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2005,2006,2007 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __InstanceSaveMgr_H +#define __InstanceSaveMgr_H + +#include "Platform/Define.h" +#include "Policies/Singleton.h" +#include "zthread/Mutex.h" +#include +#include +#include "Utilities/HashMap.h" +#include "Database/DatabaseEnv.h" + +struct InstanceTemplate; +struct MapEntry; +class Player; +class Group; + +/* + Holds the information necessary for creating a new map for an existing instance + Is referenced in three cases: + - player-instance binds for solo players (not in group) + - player-instance binds for permanent heroic/raid saves + - group-instance binds (both solo and permanent) cache the player binds for the group leader +*/ +class InstanceSave +{ + friend class InstanceSaveManager; + public: + /* Created either when: + - any new instance is being generated + - the first time a player bound to InstanceId logs in + - when a group bound to the instance is loaded */ + InstanceSave(uint16 MapId, uint32 InstanceId, uint8 difficulty, time_t resetTime, bool canReset); + + /* Unloaded when m_playerList and m_groupList become empty + or when the instance is reset */ + ~InstanceSave(); + + uint8 GetPlayerCount() { return m_playerList.size(); } + uint8 GetGroupCount() { return m_groupList.size(); } + + /* A map corresponding to the InstanceId/MapId does not always exist. + InstanceSave objects may be created on player logon but the maps are + created and loaded only when a player actually enters the instance. */ + uint32 GetInstanceId() { return m_instanceid; } + uint32 GetMapId() { return m_mapid; } + + /* Saved when the instance is generated for the first time */ + void SaveToDB(); + /* When the instance is being reset (permanently deleted) */ + void DeleteFromDB(); + + /* for normal instances this corresponds to max(creature respawn time) + X hours + for raid/heroic instances this caches the global respawn time for the map */ + time_t GetResetTime() { return m_resetTime; } + void SetResetTime(time_t resetTime) { m_resetTime = resetTime; } + time_t GetResetTimeForDB(); + + InstanceTemplate const* GetTemplate(); + MapEntry const* GetMapEntry(); + + /* online players bound to the instance (perm/solo) + does not include the members of the group unless they have permanent saves */ + void AddPlayer(Player *player) { m_playerList.push_back(player); } + bool RemovePlayer(Player *player) { m_playerList.remove(player); return UnloadIfEmpty(); } + /* all groups bound to the instance */ + void AddGroup(Group *group) { m_groupList.push_back(group); } + bool RemoveGroup(Group *group) { m_groupList.remove(group); return UnloadIfEmpty(); } + + /* instances cannot be reset (except at the global reset time) + if there are players permanently bound to it + this is cached for the case when those players are offline */ + bool CanReset() { return m_canReset; } + void SetCanReset(bool canReset) { m_canReset = canReset; } + + /* currently it is possible to omit this information from this structure + but that would depend on a lot of things that can easily change in future */ + uint8 GetDifficulty() { return m_difficulty; } + + typedef std::list PlayerListType; + typedef std::list GroupListType; + private: + bool UnloadIfEmpty(); + /* the only reason the instSave-object links are kept is because + the object-instSave links need to be broken at reset time + TODO: maybe it's enough to just store the number of players/groups */ + PlayerListType m_playerList; + GroupListType m_groupList; + time_t m_resetTime; + uint32 m_instanceid; + uint16 m_mapid; + uint8 m_difficulty; + bool m_canReset; +}; + +class MANGOS_DLL_DECL InstanceSaveManager : public MaNGOS::Singleton > +{ + friend class InstanceSave; + public: + InstanceSaveManager(); + ~InstanceSaveManager(); + + typedef std::map InstanceSaveMap; + typedef HM_NAMESPACE::hash_map InstanceSaveHashMap; + typedef std::map InstanceSaveMapMap; + + /* resetTime is a global propery of each (raid/heroic) map + all instances of that map reset at the same time */ + struct InstResetEvent + { + uint8 type; + uint16 mapid; + uint16 instanceId; + InstResetEvent(uint8 t = 0, uint16 m = 0, uint16 i = 0) : type(t), mapid(m), instanceId(i) {} + bool operator == (const InstResetEvent& e) { return e.instanceId == instanceId; } + }; + typedef std::multimap ResetTimeQueue; + typedef std::vector ResetTimeVector; + + void CleanupInstances(); + void PackInstances(); + + void LoadResetTimes(); + time_t GetResetTimeFor(uint32 mapid) { return m_resetTimeByMapId[mapid]; } + void ScheduleReset(bool add, time_t time, InstResetEvent event); + + void Update(); + + InstanceSave* AddInstanceSave(uint32 mapId, uint32 instanceId, uint8 difficulty, time_t resetTime, bool canReset, bool load = false); + void RemoveInstanceSave(uint32 InstanceId); + static void DeleteInstanceFromDB(uint32 instanceid); + + InstanceSave *GetInstanceSave(uint32 InstanceId); + + /* statistics */ + uint32 GetNumInstanceSaves() { return m_instanceSaveById.size(); } + uint32 GetNumBoundPlayersTotal(); + uint32 GetNumBoundGroupsTotal(); + + private: + void _ResetOrWarnAll(uint32 mapid, bool warn, uint32 timeleft); + void _ResetInstance(uint32 mapid, uint32 instanceId); + void _ResetSave(InstanceSaveHashMap::iterator &itr); + void _DelHelper(DatabaseType &db, const char *fields, const char *table, const char *queryTail,...); + // used during global instance resets + bool lock_instLists; + // fast lookup by instance id + InstanceSaveHashMap m_instanceSaveById; + // fast lookup for reset times + ResetTimeVector m_resetTimeByMapId; + ResetTimeQueue m_resetTimeQueue; +}; + +#define sInstanceSaveManager MaNGOS::Singleton::Instance() +#endif diff --git a/src/game/Item.cpp b/src/game/Item.cpp new file mode 100644 index 00000000000..b7e5d010773 --- /dev/null +++ b/src/game/Item.cpp @@ -0,0 +1,915 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Item.h" +#include "ObjectMgr.h" +#include "WorldPacket.h" +#include "Database/DatabaseEnv.h" +#include "ItemEnchantmentMgr.h" + +void AddItemsSetItem(Player*player,Item *item) +{ + ItemPrototype const *proto = item->GetProto(); + uint32 setid = proto->ItemSet; + + ItemSetEntry const *set = sItemSetStore.LookupEntry(setid); + + if(!set) + { + sLog.outErrorDb("Item set %u for item (id %u) not found, mods not applied.",setid,proto->ItemId); + return; + } + + if( set->required_skill_id && player->GetSkillValue(set->required_skill_id) < set->required_skill_value ) + return; + + ItemSetEffect *eff = NULL; + + for(size_t x = 0; x < player->ItemSetEff.size(); ++x) + { + if(player->ItemSetEff[x] && player->ItemSetEff[x]->setid == setid) + { + eff = player->ItemSetEff[x]; + break; + } + } + + if(!eff) + { + eff = new ItemSetEffect; + memset(eff,0,sizeof(ItemSetEffect)); + eff->setid = setid; + + size_t x = 0; + for(; x < player->ItemSetEff.size(); x++) + if(!player->ItemSetEff[x]) + break; + + if(x < player->ItemSetEff.size()) + player->ItemSetEff[x]=eff; + else + player->ItemSetEff.push_back(eff); + } + + ++eff->item_count; + + for(uint32 x=0;x<8;x++) + { + if(!set->spells [x]) + continue; + //not enough for spell + if(set->items_to_triggerspell[x] > eff->item_count) + continue; + + uint32 z=0; + for(;z<8;z++) + if(eff->spells[z] && eff->spells[z]->Id==set->spells[x]) + break; + + if(z < 8) + continue; + + //new spell + for(uint32 y=0;y<8;y++) + { + if(!eff->spells[y]) // free slot + { + SpellEntry const *spellInfo = sSpellStore.LookupEntry(set->spells[x]); + if(!spellInfo) + { + sLog.outError("WORLD: unknown spell id %u in items set %u effects", set->spells[x],setid); + break; + } + + // spell casted only if fit form requirement, in other case will casted at form change + player->ApplyEquipSpell(spellInfo,NULL,true); + eff->spells[y] = spellInfo; + break; + } + } + } +} + +void RemoveItemsSetItem(Player*player,ItemPrototype const *proto) +{ + uint32 setid = proto->ItemSet; + + ItemSetEntry const *set = sItemSetStore.LookupEntry(setid); + + if(!set) + { + sLog.outErrorDb("Item set #%u for item #%u not found, mods not removed.",setid,proto->ItemId); + return; + } + + ItemSetEffect *eff = NULL; + size_t setindex = 0; + for(;setindex < player->ItemSetEff.size(); setindex++) + { + if(player->ItemSetEff[setindex] && player->ItemSetEff[setindex]->setid == setid) + { + eff = player->ItemSetEff[setindex]; + break; + } + } + + // can be in case now enough skill requirement for set appling but set has been appliend when skill requirement not enough + if(!eff) + return; + + --eff->item_count; + + for(uint32 x=0;x<8;x++) + { + if(!set->spells[x]) + continue; + + // enough for spell + if(set->items_to_triggerspell[x] <= eff->item_count) + continue; + + for(uint32 z=0;z<8;z++) + { + if(eff->spells[z] && eff->spells[z]->Id==set->spells[x]) + { + // spell can be not active if not fit form requirement + player->ApplyEquipSpell(eff->spells[z],NULL,false); + eff->spells[z]=NULL; + break; + } + } + } + + if(!eff->item_count) //all items of a set were removed + { + assert(eff == player->ItemSetEff[setindex]); + delete eff; + player->ItemSetEff[setindex] = NULL; + } +} + +bool ItemCanGoIntoBag(ItemPrototype const *pProto, ItemPrototype const *pBagProto) +{ + if(!pProto || !pBagProto) + return false; + + switch(pBagProto->Class) + { + case ITEM_CLASS_CONTAINER: + switch(pBagProto->SubClass) + { + case ITEM_SUBCLASS_CONTAINER: + return true; + case ITEM_SUBCLASS_SOUL_CONTAINER: + if(!(pProto->BagFamily & BAG_FAMILY_MASK_SHARDS)) + return false; + return true; + case ITEM_SUBCLASS_HERB_CONTAINER: + if(!(pProto->BagFamily & BAG_FAMILY_MASK_HERBS)) + return false; + return true; + case ITEM_SUBCLASS_ENCHANTING_CONTAINER: + if(!(pProto->BagFamily & BAG_FAMILY_MASK_ENCHANTING_SUPP)) + return false; + return true; + case ITEM_SUBCLASS_MINING_CONTAINER: + if(!(pProto->BagFamily & BAG_FAMILY_MASK_MINING_SUPP)) + return false; + return true; + case ITEM_SUBCLASS_ENGINEERING_CONTAINER: + if(!(pProto->BagFamily & BAG_FAMILY_MASK_ENGINEERING_SUPP)) + return false; + return true; + case ITEM_SUBCLASS_GEM_CONTAINER: + if(!(pProto->BagFamily & BAG_FAMILY_MASK_GEMS)) + return false; + return true; + case ITEM_SUBCLASS_LEATHERWORKING_CONTAINER: + if(!(pProto->BagFamily & BAG_FAMILY_MASK_LEATHERWORKING_SUPP)) + return false; + return true; + default: + return false; + } + case ITEM_CLASS_QUIVER: + switch(pBagProto->SubClass) + { + case ITEM_SUBCLASS_QUIVER: + if(!(pProto->BagFamily & BAG_FAMILY_MASK_ARROWS)) + return false; + return true; + case ITEM_SUBCLASS_AMMO_POUCH: + if(!(pProto->BagFamily & BAG_FAMILY_MASK_BULLETS)) + return false; + return true; + default: + return false; + } + } + return false; +} + +Item::Item( ) +{ + m_objectType |= TYPEMASK_ITEM; + m_objectTypeId = TYPEID_ITEM; + // 2.3.2 - 0x18 + m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID); + + m_valuesCount = ITEM_END; + m_slot = 0; + uState = ITEM_NEW; + uQueuePos = -1; + m_container = NULL; + m_lootGenerated = false; + mb_in_trade = false; +} + +bool Item::Create( uint32 guidlow, uint32 itemid, Player const* owner) +{ + Object::_Create( guidlow, 0, HIGHGUID_ITEM ); + + SetUInt32Value(OBJECT_FIELD_ENTRY, itemid); + SetFloatValue(OBJECT_FIELD_SCALE_X, 1.0f); + + SetUInt64Value(ITEM_FIELD_OWNER, owner ? owner->GetGUID() : 0); + SetUInt64Value(ITEM_FIELD_CONTAINED, owner ? owner->GetGUID() : 0); + + ItemPrototype const *itemProto = objmgr.GetItemPrototype(itemid); + if(!itemProto) + return false; + + SetUInt32Value(ITEM_FIELD_STACK_COUNT, 1); + SetUInt32Value(ITEM_FIELD_MAXDURABILITY, itemProto->MaxDurability); + SetUInt32Value(ITEM_FIELD_DURABILITY, itemProto->MaxDurability); + + for(int i = 0; i < 5; ++i) + SetSpellCharges(i,itemProto->Spells[i].SpellCharges); + + SetUInt32Value(ITEM_FIELD_FLAGS, itemProto->Flags); + SetUInt32Value(ITEM_FIELD_DURATION, abs(itemProto->Duration)); + + return true; +} + +void Item::UpdateDuration(Player* owner, uint32 diff) +{ + if (!GetUInt32Value(ITEM_FIELD_DURATION)) + return; + + sLog.outDebug("Item::UpdateDuration Item (Entry: %u Duration %u Diff %u)",GetEntry(),GetUInt32Value(ITEM_FIELD_DURATION),diff); + + if (GetUInt32Value(ITEM_FIELD_DURATION)<=diff) + { + owner->DestroyItem(GetBagSlot(), GetSlot(), true); + return; + } + + SetUInt32Value(ITEM_FIELD_DURATION, GetUInt32Value(ITEM_FIELD_DURATION) - diff); + SetState(ITEM_CHANGED); // save new time in database +} + +void Item::SaveToDB() +{ + uint32 guid = GetGUIDLow(); + switch (uState) + { + case ITEM_NEW: + { + CharacterDatabase.PExecute( "DELETE FROM item_instance WHERE guid = '%u'", guid ); + std::ostringstream ss; + ss << "INSERT INTO item_instance (guid,owner_guid,data) VALUES (" << guid << "," << GUID_LOPART(GetOwnerGUID()) << ",'"; + for(uint16 i = 0; i < m_valuesCount; i++ ) + ss << GetUInt32Value(i) << " "; + ss << "' )"; + CharacterDatabase.Execute( ss.str().c_str() ); + } break; + case ITEM_CHANGED: + { + std::ostringstream ss; + ss << "UPDATE item_instance SET data = '"; + for(uint16 i = 0; i < m_valuesCount; i++ ) + ss << GetUInt32Value(i) << " "; + ss << "', owner_guid = '" << GUID_LOPART(GetOwnerGUID()) << "' WHERE guid = '" << guid << "'"; + + CharacterDatabase.Execute( ss.str().c_str() ); + + if(HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED)) + CharacterDatabase.PExecute("UPDATE character_gifts SET guid = '%u' WHERE item_guid = '%u'", GUID_LOPART(GetOwnerGUID()),GetGUIDLow()); + } break; + case ITEM_REMOVED: + { + if (GetUInt32Value(ITEM_FIELD_ITEM_TEXT_ID) > 0 ) + CharacterDatabase.PExecute("DELETE FROM item_text WHERE id = '%u'", GetUInt32Value(ITEM_FIELD_ITEM_TEXT_ID)); + CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid = '%u'", guid); + if(HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED)) + CharacterDatabase.PExecute("DELETE FROM character_gifts WHERE item_guid = '%u'", GetGUIDLow()); + delete this; + return; + } + case ITEM_UNCHANGED: + break; + } + SetState(ITEM_UNCHANGED); +} + +bool Item::LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult *result) +{ + // create item before any checks for store correct guid + // and allow use "FSetState(ITEM_REMOVED); SaveToDB();" for deleting item from DB + Object::_Create(guid, 0, HIGHGUID_ITEM); + + bool delete_result = false; + if(!result) + { + result = CharacterDatabase.PQuery("SELECT data FROM item_instance WHERE guid = '%u'", guid); + delete_result = true; + } + + if (!result) + { + sLog.outError("ERROR: Item (GUID: %u owner: %u) not found in table `item_instance`, can't load. ",guid,GUID_LOPART(owner_guid)); + return false; + } + + Field *fields = result->Fetch(); + + if(!LoadValues(fields[0].GetString())) + { + sLog.outError("ERROR: Item #%d have broken data in `data` field. Can't be loaded.",guid); + if (delete_result) delete result; + return false; + } + + bool need_save = false; // need explicit save data at load fixes + + // overwrite possible wrong/corrupted guid + uint64 new_item_guid = MAKE_NEW_GUID(guid,0, HIGHGUID_ITEM); + if(GetUInt64Value(OBJECT_FIELD_GUID) != new_item_guid) + { + SetUInt64Value(OBJECT_FIELD_GUID, MAKE_NEW_GUID(guid,0, HIGHGUID_ITEM)); + need_save = true; + } + + if (delete_result) delete result; + + ItemPrototype const* proto = GetProto(); + if(!proto) + return false; + + // recalculate suffix factor + if(GetItemRandomPropertyId() < 0) + { + if(UpdateItemSuffixFactor()) + need_save = true; + } + + // Remove bind flag for items vs NO_BIND set + if (IsSoulBound() && proto->Bonding == NO_BIND) + { + ApplyModFlag(ITEM_FIELD_FLAGS,ITEM_FLAGS_BINDED, false); + need_save = true; + } + + // update duration if need, and remove if not need + if((proto->Duration==0) != (GetUInt32Value(ITEM_FIELD_DURATION)==0)) + { + SetUInt32Value(ITEM_FIELD_DURATION,abs(proto->Duration)); + need_save = true; + } + + // set correct owner + if(owner_guid != 0 && GetOwnerGUID() != owner_guid) + { + SetOwnerGUID(owner_guid); + need_save = true; + } + + if(need_save) // normal item changed state set not work at loading + { + std::ostringstream ss; + ss << "UPDATE item_instance SET data = '"; + for(uint16 i = 0; i < m_valuesCount; i++ ) + ss << GetUInt32Value(i) << " "; + ss << "', owner_guid = '" << GUID_LOPART(GetOwnerGUID()) << "' WHERE guid = '" << guid << "'"; + + CharacterDatabase.Execute( ss.str().c_str() ); + } + + return true; +} + +void Item::DeleteFromDB() +{ + CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid = '%u'",GetGUIDLow()); +} + +void Item::DeleteFromInventoryDB() +{ + CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE item = '%u'",GetGUIDLow()); +} + +ItemPrototype const *Item::GetProto() const +{ + return objmgr.GetItemPrototype(GetUInt32Value(OBJECT_FIELD_ENTRY)); +} + +Player* Item::GetOwner()const +{ + return objmgr.GetPlayer(GetOwnerGUID()); +} + +uint32 Item::GetSkill() +{ + const static uint32 item_weapon_skills[MAX_ITEM_SUBCLASS_WEAPON] = + { + SKILL_AXES, SKILL_2H_AXES, SKILL_BOWS, SKILL_GUNS, SKILL_MACES, + SKILL_2H_MACES, SKILL_POLEARMS, SKILL_SWORDS, SKILL_2H_SWORDS, 0, + SKILL_STAVES, 0, 0, SKILL_UNARMED, 0, + SKILL_DAGGERS, SKILL_THROWN, SKILL_ASSASSINATION, SKILL_CROSSBOWS, SKILL_WANDS, + SKILL_FISHING + }; + + const static uint32 item_armor_skills[MAX_ITEM_SUBCLASS_ARMOR] = + { + 0,SKILL_CLOTH,SKILL_LEATHER,SKILL_MAIL,SKILL_PLATE_MAIL,0,SKILL_SHIELD,0,0,0 + }; + + ItemPrototype const* proto = GetProto(); + + switch (proto->Class) + { + case ITEM_CLASS_WEAPON: + if( proto->SubClass >= MAX_ITEM_SUBCLASS_WEAPON ) + return 0; + else + return item_weapon_skills[proto->SubClass]; + + case ITEM_CLASS_ARMOR: + if( proto->SubClass >= MAX_ITEM_SUBCLASS_ARMOR ) + return 0; + else + return item_armor_skills[proto->SubClass]; + + default: + return 0; + } +} + +uint32 Item::GetSpell() +{ + ItemPrototype const* proto = GetProto(); + + switch (proto->Class) + { + case ITEM_CLASS_WEAPON: + switch (proto->SubClass) + { + case ITEM_SUBCLASS_WEAPON_AXE: return 196; + case ITEM_SUBCLASS_WEAPON_AXE2: return 197; + case ITEM_SUBCLASS_WEAPON_BOW: return 264; + case ITEM_SUBCLASS_WEAPON_GUN: return 266; + case ITEM_SUBCLASS_WEAPON_MACE: return 198; + case ITEM_SUBCLASS_WEAPON_MACE2: return 199; + case ITEM_SUBCLASS_WEAPON_POLEARM: return 200; + case ITEM_SUBCLASS_WEAPON_SWORD: return 201; + case ITEM_SUBCLASS_WEAPON_SWORD2: return 202; + case ITEM_SUBCLASS_WEAPON_STAFF: return 227; + case ITEM_SUBCLASS_WEAPON_DAGGER: return 1180; + case ITEM_SUBCLASS_WEAPON_THROWN: return 2567; + case ITEM_SUBCLASS_WEAPON_SPEAR: return 3386; + case ITEM_SUBCLASS_WEAPON_CROSSBOW:return 5011; + case ITEM_SUBCLASS_WEAPON_WAND: return 5009; + default: return 0; + } + case ITEM_CLASS_ARMOR: + switch(proto->SubClass) + { + case ITEM_SUBCLASS_ARMOR_CLOTH: return 9078; + case ITEM_SUBCLASS_ARMOR_LEATHER: return 9077; + case ITEM_SUBCLASS_ARMOR_MAIL: return 8737; + case ITEM_SUBCLASS_ARMOR_PLATE: return 750; + case ITEM_SUBCLASS_ARMOR_SHIELD: return 9116; + default: return 0; + } + } + return 0; +} + +int32 Item::GenerateItemRandomPropertyId(uint32 item_id) +{ + ItemPrototype const *itemProto = sItemStorage.LookupEntry(item_id); + + if(!itemProto) + return 0; + + // item must have one from this field values not null if it can have random enchantments + if((!itemProto->RandomProperty) && (!itemProto->RandomSuffix)) + return 0; + + // item can have not null only one from field values + if((itemProto->RandomProperty) && (itemProto->RandomSuffix)) + { + sLog.outErrorDb("Item template %u have RandomProperty==%u and RandomSuffix==%u, but must have one from field =0",itemProto->ItemId,itemProto->RandomProperty,itemProto->RandomSuffix); + return 0; + } + + // RandomProperty case + if(itemProto->RandomProperty) + { + uint32 randomPropId = GetItemEnchantMod(itemProto->RandomProperty); + ItemRandomPropertiesEntry const *random_id = sItemRandomPropertiesStore.LookupEntry(randomPropId); + if(!random_id) + { + sLog.outErrorDb("Enchantment id #%u used but it doesn't have records in 'ItemRandomProperties.dbc'",randomPropId); + return 0; + } + + return random_id->ID; + } + // RandomSuffix case + else + { + uint32 randomPropId = GetItemEnchantMod(itemProto->RandomSuffix); + ItemRandomSuffixEntry const *random_id = sItemRandomSuffixStore.LookupEntry(randomPropId); + if(!random_id) + { + sLog.outErrorDb("Enchantment id #%u used but it doesn't have records in sItemRandomSuffixStore.",randomPropId); + return 0; + } + + return -int32(random_id->ID); + } +} + +void Item::SetItemRandomProperties(int32 randomPropId) +{ + if(!randomPropId) + return; + + if(randomPropId > 0) + { + ItemRandomPropertiesEntry const *item_rand = sItemRandomPropertiesStore.LookupEntry(randomPropId); + if(item_rand) + { + if(GetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID) != int32(item_rand->ID)) + { + SetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID,item_rand->ID); + SetState(ITEM_CHANGED); + } + for(uint32 i = PROP_ENCHANTMENT_SLOT_2; i < PROP_ENCHANTMENT_SLOT_2 + 3; ++i) + SetEnchantment(EnchantmentSlot(i),item_rand->enchant_id[i - PROP_ENCHANTMENT_SLOT_2],0,0); + } + } + else + { + ItemRandomSuffixEntry const *item_rand = sItemRandomSuffixStore.LookupEntry(-randomPropId); + if(item_rand) + { + if( GetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID) != -int32(item_rand->ID) || + !GetItemSuffixFactor()) + { + SetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID,-int32(item_rand->ID)); + UpdateItemSuffixFactor(); + SetState(ITEM_CHANGED); + } + + for(uint32 i = PROP_ENCHANTMENT_SLOT_0; i < PROP_ENCHANTMENT_SLOT_0 + 3; ++i) + SetEnchantment(EnchantmentSlot(i),item_rand->enchant_id[i - PROP_ENCHANTMENT_SLOT_0],0,0); + } + } +} + +bool Item::UpdateItemSuffixFactor() +{ + uint32 suffixFactor = GenerateEnchSuffixFactor(GetEntry()); + if(GetItemSuffixFactor()==suffixFactor) + return false; + SetUInt32Value(ITEM_FIELD_PROPERTY_SEED,suffixFactor); + return true; +} + +void Item::SetState(ItemUpdateState state, Player *forplayer) +{ + if (uState == ITEM_NEW && state == ITEM_REMOVED) + { + // pretend the item never existed + RemoveFromUpdateQueueOf(forplayer); + delete this; + return; + } + + if (state != ITEM_UNCHANGED) + { + // new items must stay in new state until saved + if (uState != ITEM_NEW) uState = state; + AddToUpdateQueueOf(forplayer); + } + else + { + // unset in queue + // the item must be removed from the queue manually + uQueuePos = -1; + uState = ITEM_UNCHANGED; + } +} + +void Item::AddToUpdateQueueOf(Player *player) +{ + if (IsInUpdateQueue()) return; + + if (!player) + { + player = GetOwner(); + if (!player) + { + sLog.outError("Item::AddToUpdateQueueOf - GetPlayer didn't find a player matching owner's guid (%u)!", GUID_LOPART(GetOwnerGUID())); + return; + } + } + + if (player->GetGUID() != GetOwnerGUID()) + { + sLog.outError("Item::AddToUpdateQueueOf - Owner's guid (%u) and player's guid (%u) don't match!", GUID_LOPART(GetOwnerGUID()), player->GetGUIDLow()); + return; + } + + if (player->m_itemUpdateQueueBlocked) return; + + player->m_itemUpdateQueue.push_back(this); + uQueuePos = player->m_itemUpdateQueue.size()-1; +} + +void Item::RemoveFromUpdateQueueOf(Player *player) +{ + if (!IsInUpdateQueue()) return; + + if (!player) + { + player = GetOwner(); + if (!player) + { + sLog.outError("Item::RemoveFromUpdateQueueOf - GetPlayer didn't find a player matching owner's guid (%u)!", GUID_LOPART(GetOwnerGUID())); + return; + } + } + + if (player->GetGUID() != GetOwnerGUID()) + { + sLog.outError("Item::RemoveFromUpdateQueueOf - Owner's guid (%u) and player's guid (%u) don't match!", GUID_LOPART(GetOwnerGUID()), player->GetGUIDLow()); + return; + } + + if (player->m_itemUpdateQueueBlocked) return; + + player->m_itemUpdateQueue[uQueuePos] = NULL; + uQueuePos = -1; +} + +uint8 Item::GetBagSlot() const +{ + return m_container ? m_container->GetSlot() : uint8(INVENTORY_SLOT_BAG_0); +} + +bool Item::IsEquipped() const +{ + return !IsInBag() && m_slot < EQUIPMENT_SLOT_END; +} + +bool Item::CanBeTraded() const +{ + if(IsSoulBound()) + return false; + if(IsBag() && (Player::IsBagPos(GetPos()) || !((Bag const*)this)->IsEmpty()) ) + return false; + + if(Player* owner = GetOwner()) + { + if(owner->CanUnequipItem(GetPos(),false) != EQUIP_ERR_OK ) + return false; + if(owner->GetLootGUID()==GetGUID()) + return false; + } + + if (IsBoundByEnchant()) + return false; + + return true; +} + +bool Item::IsBoundByEnchant() const +{ + // Check all enchants for soulbound + for(uint32 enchant_slot = PERM_ENCHANTMENT_SLOT; enchant_slot < MAX_ENCHANTMENT_SLOT; ++enchant_slot) + { + uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot)); + if(!enchant_id) + continue; + + SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id); + if(!enchantEntry) + continue; + + if(enchantEntry->slot & ENCHANTMENT_CAN_SOULBOUND) + return true; + } + return false; +} + +bool Item::IsFitToSpellRequirements(SpellEntry const* spellInfo) const +{ + ItemPrototype const* proto = GetProto(); + + if (spellInfo->EquippedItemClass != -1) // -1 == any item class + { + if(spellInfo->EquippedItemClass != int32(proto->Class)) + return false; // wrong item class + + if(spellInfo->EquippedItemSubClassMask != 0) // 0 == any subclass + { + if((spellInfo->EquippedItemSubClassMask & (1 << proto->SubClass)) == 0) + return false; // subclass not present in mask + } + } + + if(spellInfo->EquippedItemInventoryTypeMask != 0) // 0 == any inventory type + { + if((spellInfo->EquippedItemInventoryTypeMask & (1 << proto->InventoryType)) == 0) + return false; // inventory type not present in mask + } + + return true; +} + +void Item::SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint32 charges) +{ + // Better lost small time at check in comparison lost time at item save to DB. + if( GetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_ID_OFFSET)==id && + GetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET)==duration && + GetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET)==charges ) + return; + + SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_ID_OFFSET,id); + SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET,duration); + SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET,charges); + SetState(ITEM_CHANGED); +} + +void Item::SetEnchantmentDuration(EnchantmentSlot slot, uint32 duration) +{ + if(GetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET)==duration) + return; + + SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET,duration); + SetState(ITEM_CHANGED); +} + +void Item::SetEnchantmentCharges(EnchantmentSlot slot, uint32 charges) +{ + SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET,charges); + SetState(ITEM_CHANGED); +} + +void Item::ClearEnchantment(EnchantmentSlot slot) +{ + if(!GetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_ID_OFFSET)) + return; + + for(int x=0;x<3;x++) + SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + x,0); + SetState(ITEM_CHANGED); +} + +bool Item::GemsFitSockets() const +{ + bool fits = true; + for(uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+3; ++enchant_slot) + { + uint8 SocketColor = GetProto()->Socket[enchant_slot-SOCK_ENCHANTMENT_SLOT].Color; + + uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot)); + if(!enchant_id) + { + if(SocketColor) fits &= false; + continue; + } + + SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id); + if(!enchantEntry) + { + if(SocketColor) fits &= false; + continue; + } + + uint8 GemColor = 0; + + uint32 gemid = enchantEntry->GemID; + if(gemid) + { + ItemPrototype const* gemProto = sItemStorage.LookupEntry(gemid); + if(gemProto) + { + GemPropertiesEntry const* gemProperty = sGemPropertiesStore.LookupEntry(gemProto->GemProperties); + if(gemProperty) + GemColor = gemProperty->color; + } + } + + fits &= (GemColor & SocketColor) ? true : false; + } + return fits; +} + +uint8 Item::GetGemCountWithID(uint32 GemID) const +{ + uint8 count = 0; + for(uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+3; ++enchant_slot) + { + uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot)); + if(!enchant_id) + continue; + + SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id); + if(!enchantEntry) + continue; + + if(GemID == enchantEntry->GemID) + ++count; + } + return count; +} + +bool Item::IsLimitedToAnotherMapOrZone( uint32 cur_mapId, uint32 cur_zoneId) const +{ + ItemPrototype const* proto = GetProto(); + return proto && (proto->Map && proto->Map != cur_mapId || proto->Area && proto->Area != cur_zoneId ); +} + +// Though the client has the information in the item's data field, +// we have to send SMSG_ITEM_TIME_UPDATE to display the remaining +// time. +void Item::SendTimeUpdate(Player* owner) +{ + if (!GetUInt32Value(ITEM_FIELD_DURATION)) + return; + + WorldPacket data(SMSG_ITEM_TIME_UPDATE, (8+4)); + data << (uint64)GetGUID(); + data << (uint32)GetUInt32Value(ITEM_FIELD_DURATION); + owner->GetSession()->SendPacket(&data); +} + +Item* Item::CreateItem( uint32 item, uint32 count, Player const* player ) +{ + if ( count < 1 ) + return NULL; //don't create item at zero count + + ItemPrototype const *pProto = objmgr.GetItemPrototype( item ); + if( pProto ) + { + if ( count > pProto->Stackable ) + count = pProto->Stackable; + + assert(count !=0 && "pProto->Stackable==0 but checked at loading already"); + + Item *pItem = NewItemOrBag( pProto ); + if( pItem->Create(objmgr.GenerateLowGuid(HIGHGUID_ITEM), item, player) ) + { + pItem->SetCount( count ); + return pItem; + } + else + delete pItem; + } + return NULL; +} + +Item* Item::CloneItem( uint32 count, Player const* player ) const +{ + Item* newItem = CreateItem( GetEntry(), count, player ); + if(!newItem) + return NULL; + + newItem->SetUInt32Value( ITEM_FIELD_CREATOR, GetUInt32Value( ITEM_FIELD_CREATOR ) ); + newItem->SetUInt32Value( ITEM_FIELD_GIFTCREATOR, GetUInt32Value( ITEM_FIELD_GIFTCREATOR ) ); + newItem->SetUInt32Value( ITEM_FIELD_FLAGS, GetUInt32Value( ITEM_FIELD_FLAGS ) ); + newItem->SetUInt32Value( ITEM_FIELD_DURATION, GetUInt32Value( ITEM_FIELD_DURATION ) ); + newItem->SetItemRandomProperties(GetItemRandomPropertyId()); + return newItem; +} diff --git a/src/game/Item.h b/src/game/Item.h new file mode 100644 index 00000000000..7379edd03f8 --- /dev/null +++ b/src/game/Item.h @@ -0,0 +1,298 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOSSERVER_ITEM_H +#define MANGOSSERVER_ITEM_H + +#include "Common.h" +#include "Object.h" +#include "LootMgr.h" +#include "ItemPrototype.h" + +struct SpellEntry; +class Bag; +class QueryResult; + +struct ItemSetEffect +{ + uint32 setid; + uint32 item_count; + SpellEntry const *spells[8]; +}; + +enum InventoryChangeFailure +{ + EQUIP_ERR_OK = 0, + EQUIP_ERR_CANT_EQUIP_LEVEL_I = 1, + EQUIP_ERR_ERR_CANT_EQUIP_SKILL = 2, + EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT = 3, + EQUIP_ERR_BAG_FULL = 4, + EQUIP_ERR_NONEMPTY_BAG_OVER_OTHER_BAG = 5, + EQUIP_ERR_CANT_TRADE_EQUIP_BAGS = 6, + EQUIP_ERR_ONLY_AMMO_CAN_GO_HERE = 7, + EQUIP_ERR_NO_REQUIRED_PROFICIENCY = 8, + EQUIP_ERR_NO_EQUIPMENT_SLOT_AVAILABLE = 9, + EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM = 10, + EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM2 = 11, + EQUIP_ERR_NO_EQUIPMENT_SLOT_AVAILABLE2 = 12, + EQUIP_ERR_CANT_EQUIP_WITH_TWOHANDED = 13, + EQUIP_ERR_CANT_DUAL_WIELD = 14, + EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG = 15, + EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG2 = 16, + EQUIP_ERR_CANT_CARRY_MORE_OF_THIS = 17, + EQUIP_ERR_NO_EQUIPMENT_SLOT_AVAILABLE3 = 18, + EQUIP_ERR_ITEM_CANT_STACK = 19, + EQUIP_ERR_ITEM_CANT_BE_EQUIPPED = 20, + EQUIP_ERR_ITEMS_CANT_BE_SWAPPED = 21, + EQUIP_ERR_SLOT_IS_EMPTY = 22, + EQUIP_ERR_ITEM_NOT_FOUND = 23, + EQUIP_ERR_CANT_DROP_SOULBOUND = 24, + EQUIP_ERR_OUT_OF_RANGE = 25, + EQUIP_ERR_TRIED_TO_SPLIT_MORE_THAN_COUNT = 26, + EQUIP_ERR_COULDNT_SPLIT_ITEMS = 27, + EQUIP_ERR_MISSING_REAGENT = 28, + EQUIP_ERR_NOT_ENOUGH_MONEY = 29, + EQUIP_ERR_NOT_A_BAG = 30, + EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS = 31, + EQUIP_ERR_DONT_OWN_THAT_ITEM = 32, + EQUIP_ERR_CAN_EQUIP_ONLY1_QUIVER = 33, + EQUIP_ERR_MUST_PURCHASE_THAT_BAG_SLOT = 34, + EQUIP_ERR_TOO_FAR_AWAY_FROM_BANK = 35, + EQUIP_ERR_ITEM_LOCKED = 36, + EQUIP_ERR_YOU_ARE_STUNNED = 37, + EQUIP_ERR_YOU_ARE_DEAD = 38, + EQUIP_ERR_CANT_DO_RIGHT_NOW = 39, + EQUIP_ERR_INT_BAG_ERROR = 40, + EQUIP_ERR_CAN_EQUIP_ONLY1_QUIVER2 = 41, + EQUIP_ERR_CAN_EQUIP_ONLY1_AMMOPOUCH = 42, + EQUIP_ERR_STACKABLE_CANT_BE_WRAPPED = 43, + EQUIP_ERR_EQUIPPED_CANT_BE_WRAPPED = 44, + EQUIP_ERR_WRAPPED_CANT_BE_WRAPPED = 45, + EQUIP_ERR_BOUND_CANT_BE_WRAPPED = 46, + EQUIP_ERR_UNIQUE_CANT_BE_WRAPPED = 47, + EQUIP_ERR_BAGS_CANT_BE_WRAPPED = 48, + EQUIP_ERR_ALREADY_LOOTED = 49, + EQUIP_ERR_INVENTORY_FULL = 50, + EQUIP_ERR_BANK_FULL = 51, + EQUIP_ERR_ITEM_IS_CURRENTLY_SOLD_OUT = 52, + EQUIP_ERR_BAG_FULL3 = 53, + EQUIP_ERR_ITEM_NOT_FOUND2 = 54, + EQUIP_ERR_ITEM_CANT_STACK2 = 55, + EQUIP_ERR_BAG_FULL4 = 56, + EQUIP_ERR_ITEM_SOLD_OUT = 57, + EQUIP_ERR_OBJECT_IS_BUSY = 58, + EQUIP_ERR_NONE = 59, + EQUIP_ERR_NOT_IN_COMBAT = 60, + EQUIP_ERR_NOT_WHILE_DISARMED = 61, + EQUIP_ERR_BAG_FULL6 = 62, + EQUIP_ERR_CANT_EQUIP_RANK = 63, + EQUIP_ERR_CANT_EQUIP_REPUTATION = 64, + EQUIP_ERR_TOO_MANY_SPECIAL_BAGS = 65, + EQUIP_ERR_LOOT_CANT_LOOT_THAT_NOW = 66, + EQUIP_ERR_ITEM_UNIQUE_EQUIPABLE = 67, + EQUIP_ERR_VENDOR_MISSING_TURNINS = 68, + EQUIP_ERR_NOT_ENOUGH_HONOR_POINTS = 69, + EQUIP_ERR_NOT_ENOUGH_ARENA_POINTS = 70, + EQUIP_ERR_ITEM_MAX_COUNT_SOCKETED = 71, + EQUIP_ERR_MAIL_BOUND_ITEM = 72, + EQUIP_ERR_NO_SPLIT_WHILE_PROSPECTING = 73, + EQUIP_ERR_ITEM_MAX_COUNT_EQUIPPED_SOCKETED = 75, + EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED = 76, + EQUIP_ERR_TOO_MUCH_GOLD = 77, + EQUIP_ERR_NOT_DURING_ARENA_MATCH = 78, + EQUIP_ERR_CANNOT_TRADE_THAT = 79, + EQUIP_ERR_PERSONAL_ARENA_RATING_TOO_LOW = 80 + // probably exist more +}; + +enum BuyFailure +{ + BUY_ERR_CANT_FIND_ITEM = 0, + BUY_ERR_ITEM_ALREADY_SOLD = 1, + BUY_ERR_NOT_ENOUGHT_MONEY = 2, + BUY_ERR_SELLER_DONT_LIKE_YOU = 4, + BUY_ERR_DISTANCE_TOO_FAR = 5, + BUY_ERR_ITEM_SOLD_OUT = 7, + BUY_ERR_CANT_CARRY_MORE = 8, + BUY_ERR_RANK_REQUIRE = 11, + BUY_ERR_REPUTATION_REQUIRE = 12 +}; + +enum SellFailure +{ + SELL_ERR_CANT_FIND_ITEM = 1, + SELL_ERR_CANT_SELL_ITEM = 2, // merchant doesn't like that item + SELL_ERR_CANT_FIND_VENDOR = 3, // merchant doesn't like you + SELL_ERR_YOU_DONT_OWN_THAT_ITEM = 4, // you don't own that item + SELL_ERR_UNK = 5, // nothing appears... + SELL_ERR_ONLY_EMPTY_BAG = 6 // can only do with empty bags +}; + +// -1 from client enchantment slot number +enum EnchantmentSlot +{ + PERM_ENCHANTMENT_SLOT = 0, + TEMP_ENCHANTMENT_SLOT = 1, + SOCK_ENCHANTMENT_SLOT = 2, + SOCK_ENCHANTMENT_SLOT_2 = 3, + SOCK_ENCHANTMENT_SLOT_3 = 4, + BONUS_ENCHANTMENT_SLOT = 5, + MAX_INSPECTED_ENCHANTMENT_SLOT = 6, + + PROP_ENCHANTMENT_SLOT_0 = 6, // used with RandomSuffix + PROP_ENCHANTMENT_SLOT_1 = 7, // used with RandomSuffix + PROP_ENCHANTMENT_SLOT_2 = 8, // used with RandomSuffix and RandomProperty + PROP_ENCHANTMENT_SLOT_3 = 9, // used with RandomProperty + PROP_ENCHANTMENT_SLOT_4 = 10, // used with RandomProperty + MAX_ENCHANTMENT_SLOT = 11 +}; + +#define MAX_VISIBLE_ITEM_OFFSET 16 // 16 fields per visible item (creator(2) + enchantments(12) + properties(1) + pad(1)) + +enum EnchantmentOffset +{ + ENCHANTMENT_ID_OFFSET = 0, + ENCHANTMENT_DURATION_OFFSET = 1, + ENCHANTMENT_CHARGES_OFFSET = 2 +}; + +#define MAX_ENCHANTMENT_OFFSET 3 + +enum EnchantmentSlotMask +{ + ENCHANTMENT_CAN_SOULBOUND = 0x01, + ENCHANTMENT_UNK1 = 0x02, + ENCHANTMENT_UNK2 = 0x04, + ENCHANTMENT_UNK3 = 0x08 +}; + +enum ItemUpdateState +{ + ITEM_UNCHANGED = 0, + ITEM_CHANGED = 1, + ITEM_NEW = 2, + ITEM_REMOVED = 3 +}; + +bool ItemCanGoIntoBag(ItemPrototype const *proto, ItemPrototype const *pBagProto); + +class MANGOS_DLL_SPEC Item : public Object +{ + public: + static Item* CreateItem( uint32 item, uint32 count, Player const* player = NULL ); + Item* CloneItem( uint32 count, Player const* player = NULL ) const; + + Item ( ); + + virtual bool Create( uint32 guidlow, uint32 itemid, Player const* owner); + + ItemPrototype const* GetProto() const; + + uint64 const& GetOwnerGUID() const { return GetUInt64Value(ITEM_FIELD_OWNER); } + void SetOwnerGUID(uint64 guid) { SetUInt64Value(ITEM_FIELD_OWNER, guid); } + Player* GetOwner()const; + + void SetBinding(bool val) { ApplyModFlag(ITEM_FIELD_FLAGS,ITEM_FLAGS_BINDED,val); } + bool IsSoulBound() const { return HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_BINDED); } + bool IsBindedNotWith(uint64 guid) const { return IsSoulBound() && GetOwnerGUID()!= guid; } + bool IsBoundByEnchant() const; + virtual void SaveToDB(); + virtual bool LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult *result = NULL); + virtual void DeleteFromDB(); + void DeleteFromInventoryDB(); + + bool IsBag() const { return GetProto()->InventoryType == INVTYPE_BAG; } + bool IsBroken() const { return GetUInt32Value(ITEM_FIELD_MAXDURABILITY) > 0 && GetUInt32Value(ITEM_FIELD_DURABILITY) == 0; } + bool CanBeTraded() const; + void SetInTrade(bool b = true) { mb_in_trade = b; } + bool IsInTrade() const { return mb_in_trade; } + + bool IsFitToSpellRequirements(SpellEntry const* spellInfo) const; + bool IsLimitedToAnotherMapOrZone( uint32 cur_mapId, uint32 cur_zoneId) const; + bool GemsFitSockets() const; + + uint32 GetEntry() const { return GetUInt32Value(OBJECT_FIELD_ENTRY); } + uint32 GetCount() const { return GetUInt32Value (ITEM_FIELD_STACK_COUNT); } + void SetCount(uint32 value) { SetUInt32Value (ITEM_FIELD_STACK_COUNT, value); } + uint32 GetMaxStackCount() const { return GetProto()->Stackable; } + uint8 GetGemCountWithID(uint32 GemID) const; + + uint8 GetSlot() const {return m_slot;} + Bag *GetContainer() { return m_container; } + uint8 GetBagSlot() const; + void SetSlot(uint8 slot) {m_slot = slot;} + uint16 GetPos() const { return uint16(GetBagSlot()) << 8 | GetSlot(); } + void SetContainer(Bag *container) { m_container = container; } + + bool IsInBag() const { return m_container != NULL; } + bool IsEquipped() const; + + uint32 GetSkill(); + uint32 GetSpell(); + + // RandomPropertyId (signed but stored as unsigned) + int32 GetItemRandomPropertyId() const { return GetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID); } + uint32 GetItemSuffixFactor() const { return GetUInt32Value(ITEM_FIELD_PROPERTY_SEED); } + void SetItemRandomProperties(int32 randomPropId); + bool UpdateItemSuffixFactor(); + static int32 GenerateItemRandomPropertyId(uint32 item_id); + void SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint32 charges); + void SetEnchantmentDuration(EnchantmentSlot slot, uint32 duration); + void SetEnchantmentCharges(EnchantmentSlot slot, uint32 charges); + void ClearEnchantment(EnchantmentSlot slot); + uint32 GetEnchantmentId(EnchantmentSlot slot) const { return GetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_ID_OFFSET);} + uint32 GetEnchantmentDuration(EnchantmentSlot slot) const { return GetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET);} + uint32 GetEnchantmentCharges(EnchantmentSlot slot) const { return GetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET);} + + void SendTimeUpdate(Player* owner); + void UpdateDuration(Player* owner, uint32 diff); + + // spell charges (signed but stored as unsigned) + int32 GetSpellCharges(uint8 index/*0..5*/ = 0) const { return GetInt32Value(ITEM_FIELD_SPELL_CHARGES + index); } + void SetSpellCharges(uint8 index/*0..5*/, int32 value) { SetInt32Value(ITEM_FIELD_SPELL_CHARGES + index,value); } + + Loot loot; + bool m_lootGenerated; + + // Update States + ItemUpdateState GetState() const { return uState; } + void SetState(ItemUpdateState state, Player *forplayer = NULL); + void AddToUpdateQueueOf(Player *player); + void RemoveFromUpdateQueueOf(Player *player); + bool IsInUpdateQueue() const { return uQueuePos != -1; } + uint16 GetQueuePos() const { return uQueuePos; } + void FSetState(ItemUpdateState state) // forced + { + uState = state; + } + + bool hasQuest(uint32 quest_id) const + { + ItemPrototype const *itemProto = GetProto(); + return itemProto && itemProto->StartQuest == quest_id; + } + bool hasInvolvedQuest(uint32 /*quest_id*/) const { return false; } + + private: + uint8 m_slot; + Bag *m_container; + ItemUpdateState uState; + int16 uQueuePos; + bool mb_in_trade; // true if item is currently in trade-window +}; +#endif diff --git a/src/game/ItemEnchantmentMgr.cpp b/src/game/ItemEnchantmentMgr.cpp new file mode 100644 index 00000000000..9fd2e961745 --- /dev/null +++ b/src/game/ItemEnchantmentMgr.cpp @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include "ItemEnchantmentMgr.h" +#include "Database/DatabaseEnv.h" +#include "Log.h" +#include "ObjectMgr.h" +#include "ProgressBar.h" +#include +#include +#include "Util.h" + +struct EnchStoreItem +{ + uint32 ench; + float chance; + + EnchStoreItem() + : ench(0), chance(0) {} + + EnchStoreItem(uint32 _ench, float _chance) + : ench(_ench), chance(_chance) {} +}; + +typedef std::vector EnchStoreList; +typedef HM_NAMESPACE::hash_map EnchantmentStore; + +static EnchantmentStore RandomItemEnch; + +void LoadRandomEnchantmentsTable() +{ + RandomItemEnch.clear(); // for reload case + + EnchantmentStore::iterator tab; + uint32 entry, ench; + float chance; + uint32 count = 0; + + QueryResult *result = WorldDatabase.Query("SELECT entry, ench, chance FROM item_enchantment_template"); + + if (result) + { + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + entry = fields[0].GetUInt32(); + ench = fields[1].GetUInt32(); + chance = fields[2].GetFloat(); + + if (chance > 0.000001f && chance <= 100.0f) + RandomItemEnch[entry].push_back( EnchStoreItem(ench, chance) ); + + ++count; + } while (result->NextRow()); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u Item Enchantment definitions", count ); + } + else + { + sLog.outString(); + sLog.outErrorDb( ">> Loaded 0 Item Enchantment definitions. DB table `item_enchantment_template` is empty."); + } +} + +uint32 GetItemEnchantMod(uint32 entry) +{ + if (!entry) return 0; + + EnchantmentStore::iterator tab = RandomItemEnch.find(entry); + + if (tab == RandomItemEnch.end()) + { + sLog.outErrorDb("Item RandomProperty / RandomSuffix id #%u used in `item_template` but it doesn't have records in `item_enchantment_template` table.",entry); + return 0; + } + + double dRoll = rand_chance(); + float fCount = 0; + + for(EnchStoreList::iterator ench_iter = tab->second.begin(); ench_iter != tab->second.end(); ++ench_iter) + { + fCount += ench_iter->chance; + + if (fCount > dRoll) return ench_iter->ench; + } + + //we could get here only if sum of all enchantment chances is lower than 100% + dRoll = (irand(0, (int)floor(fCount * 100) + 1)) / 100; + fCount = 0; + + for(EnchStoreList::iterator ench_iter = tab->second.begin(); ench_iter != tab->second.end(); ++ench_iter) + { + fCount += ench_iter->chance; + + if (fCount > dRoll) return ench_iter->ench; + } + + return 0; +} + +uint32 GenerateEnchSuffixFactor(uint32 item_id) +{ + ItemPrototype const *itemProto = objmgr.GetItemPrototype(item_id); + + if(!itemProto) + return 0; + if(!itemProto->RandomSuffix) + return 0; + + RandomPropertiesPointsEntry const *randomProperty = sRandomPropertiesPointsStore.LookupEntry(itemProto->ItemLevel); + if(!randomProperty) + return 0; + + uint32 suffixFactor; + switch(itemProto->InventoryType) + { + // Items of that type don`t have points + case INVTYPE_NON_EQUIP: + case INVTYPE_BAG: + case INVTYPE_TABARD: + case INVTYPE_AMMO: + case INVTYPE_QUIVER: + case INVTYPE_RELIC: + return 0; + // Select point coefficient + case INVTYPE_HEAD: + case INVTYPE_BODY: + case INVTYPE_CHEST: + case INVTYPE_LEGS: + case INVTYPE_2HWEAPON: + case INVTYPE_ROBE: + suffixFactor = 0; + break; + case INVTYPE_SHOULDERS: + case INVTYPE_WAIST: + case INVTYPE_FEET: + case INVTYPE_HANDS: + case INVTYPE_TRINKET: + suffixFactor = 1; + break; + case INVTYPE_NECK: + case INVTYPE_WRISTS: + case INVTYPE_FINGER: + case INVTYPE_SHIELD: + case INVTYPE_CLOAK: + case INVTYPE_HOLDABLE: + suffixFactor = 2; + break; + case INVTYPE_WEAPON: + case INVTYPE_WEAPONMAINHAND: + case INVTYPE_WEAPONOFFHAND: + suffixFactor = 3; + break; + case INVTYPE_RANGED: + case INVTYPE_THROWN: + case INVTYPE_RANGEDRIGHT: + suffixFactor = 4; + break; + default: + return 0; + } + // Select rare/epic modifier + switch (itemProto->Quality) + { + case ITEM_QUALITY_UNCOMMON: + return randomProperty->UncommonPropertiesPoints[suffixFactor]; + case ITEM_QUALITY_RARE: + return randomProperty->RarePropertiesPoints[suffixFactor]; + case ITEM_QUALITY_EPIC: + return randomProperty->EpicPropertiesPoints[suffixFactor]; + case ITEM_QUALITY_LEGENDARY: + case ITEM_QUALITY_ARTIFACT: + return 0; // not have random properties + default: + break; + } + return 0; +} diff --git a/src/game/ItemEnchantmentMgr.h b/src/game/ItemEnchantmentMgr.h new file mode 100644 index 00000000000..95c93cf39df --- /dev/null +++ b/src/game/ItemEnchantmentMgr.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _ITEM_ENCHANTMENT_MGR_H +#define _ITEM_ENCHANTMENT_MGR_H + +#include "Common.h" + +void LoadRandomEnchantmentsTable(); +uint32 GetItemEnchantMod(uint32 entry); +uint32 GenerateEnchSuffixFactor(uint32 item_id); +#endif diff --git a/src/game/ItemHandler.cpp b/src/game/ItemHandler.cpp new file mode 100644 index 00000000000..de687ad6a09 --- /dev/null +++ b/src/game/ItemHandler.cpp @@ -0,0 +1,1221 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "World.h" +#include "Opcodes.h" +#include "Log.h" +#include "ObjectMgr.h" +#include "Player.h" +#include "Item.h" +#include "UpdateData.h" +#include "ObjectAccessor.h" + +void WorldSession::HandleSplitItemOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,1+1+1+1+1); + + //sLog.outDebug("WORLD: CMSG_SPLIT_ITEM"); + uint8 srcbag, srcslot, dstbag, dstslot, count; + + recv_data >> srcbag >> srcslot >> dstbag >> dstslot >> count; + //sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u, dstslot = %u, count = %u", srcbag, srcslot, dstbag, dstslot, count); + + uint16 src = ( (srcbag << 8) | srcslot ); + uint16 dst = ( (dstbag << 8) | dstslot ); + + if(src==dst) + return; + + if (count==0) + return; //check count - if zero it's fake packet + + _player->SplitItem( src, dst, count ); +} + +void WorldSession::HandleSwapInvItemOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,1+1); + + //sLog.outDebug("WORLD: CMSG_SWAP_INV_ITEM"); + uint8 srcslot, dstslot; + + recv_data >> srcslot >> dstslot; + //sLog.outDebug("STORAGE: receive srcslot = %u, dstslot = %u", srcslot, dstslot); + + // prevent attempt swap same item to current position generated by client at special checting sequence + if(srcslot==dstslot) + return; + + uint16 src = ( (INVENTORY_SLOT_BAG_0 << 8) | srcslot ); + uint16 dst = ( (INVENTORY_SLOT_BAG_0 << 8) | dstslot ); + + _player->SwapItem( src, dst ); +} + +void WorldSession::HandleAutoEquipItemSlotOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+1); + uint64 itemguid; + uint8 dstslot; + recv_data >> itemguid >> dstslot; + + // cheating attempt, client should never send opcode in that case + if(!Player::IsEquipmentPos(INVENTORY_SLOT_BAG_0, dstslot)) + return; + + Item* item = _player->GetItemByGuid(itemguid); + uint16 dstpos = dstslot | (INVENTORY_SLOT_BAG_0 << 8); + + if(!item || item->GetPos() == dstpos) + return; + + _player->SwapItem(item->GetPos(), dstpos); +} + +void WorldSession::HandleSwapItem( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,1+1+1+1); + + //sLog.outDebug("WORLD: CMSG_SWAP_ITEM"); + uint8 dstbag, dstslot, srcbag, srcslot; + + recv_data >> dstbag >> dstslot >> srcbag >> srcslot ; + //sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u, dstslot = %u", srcbag, srcslot, dstbag, dstslot); + + uint16 src = ( (srcbag << 8) | srcslot ); + uint16 dst = ( (dstbag << 8) | dstslot ); + + // prevent attempt swap same item to current position generated by client at special checting sequence + if(src==dst) + return; + + _player->SwapItem( src, dst ); +} + +void WorldSession::HandleAutoEquipItemOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,1+1); + + //sLog.outDebug("WORLD: CMSG_AUTOEQUIP_ITEM"); + uint8 srcbag, srcslot; + + recv_data >> srcbag >> srcslot; + //sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u", srcbag, srcslot); + + Item *pSrcItem = _player->GetItemByPos( srcbag, srcslot ); + if( !pSrcItem ) + return; // only at cheat + + if(pSrcItem->m_lootGenerated) // prevent swap looting item + { + //best error message found for attempting to swap while looting + _player->SendEquipError( EQUIP_ERR_CANT_DO_RIGHT_NOW, pSrcItem, NULL ); + return; + } + + uint16 dest; + uint8 msg = _player->CanEquipItem( NULL_SLOT, dest, pSrcItem, !pSrcItem->IsBag() ); + if( msg != EQUIP_ERR_OK ) + { + _player->SendEquipError( msg, pSrcItem, NULL ); + return; + } + + uint16 src = pSrcItem->GetPos(); + if(dest==src) // prevent equip in same slot, only at cheat + return; + + Item *pDstItem = _player->GetItemByPos( dest ); + if( !pDstItem ) // empty slot, simple case + { + _player->RemoveItem( srcbag, srcslot, true ); + _player->EquipItem( dest, pSrcItem, true ); + _player->AutoUnequipOffhandIfNeed(); + } + else // have currently equipped item, not simple case + { + uint8 dstbag = pDstItem->GetBagSlot(); + uint8 dstslot = pDstItem->GetSlot(); + + msg = _player->CanUnequipItem( dest, !pSrcItem->IsBag() ); + if( msg != EQUIP_ERR_OK ) + { + _player->SendEquipError( msg, pDstItem, NULL ); + return; + } + + // check dest->src move possibility + ItemPosCountVec sSrc; + uint16 eSrc; + if( _player->IsInventoryPos( src ) ) + { + msg = _player->CanStoreItem( srcbag, srcslot, sSrc, pDstItem, true ); + if( msg != EQUIP_ERR_OK ) + msg = _player->CanStoreItem( srcbag, NULL_SLOT, sSrc, pDstItem, true ); + if( msg != EQUIP_ERR_OK ) + msg = _player->CanStoreItem( NULL_BAG, NULL_SLOT, sSrc, pDstItem, true ); + } + else if( _player->IsBankPos( src ) ) + { + msg = _player->CanBankItem( srcbag, srcslot, sSrc, pDstItem, true ); + if( msg != EQUIP_ERR_OK ) + msg = _player->CanBankItem( srcbag, NULL_SLOT, sSrc, pDstItem, true ); + if( msg != EQUIP_ERR_OK ) + msg = _player->CanBankItem( NULL_BAG, NULL_SLOT, sSrc, pDstItem, true ); + } + else if( _player->IsEquipmentPos( src ) ) + { + msg = _player->CanEquipItem( srcslot, eSrc, pDstItem, true); + if( msg == EQUIP_ERR_OK ) + msg = _player->CanUnequipItem( eSrc, true); + } + + if( msg != EQUIP_ERR_OK ) + { + _player->SendEquipError( msg, pDstItem, pSrcItem ); + return; + } + + // now do moves, remove... + _player->RemoveItem(dstbag, dstslot, false); + _player->RemoveItem(srcbag, srcslot, false); + + // add to dest + _player->EquipItem(dest, pSrcItem, true); + + // add to src + if( _player->IsInventoryPos( src ) ) + _player->StoreItem(sSrc, pDstItem, true); + else if( _player->IsBankPos( src ) ) + _player->BankItem(sSrc, pDstItem, true); + else if( _player->IsEquipmentPos( src ) ) + _player->EquipItem(eSrc, pDstItem, true); + + _player->AutoUnequipOffhandIfNeed(); + } +} + +void WorldSession::HandleDestroyItemOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,1+1+1+1+1+1); + + //sLog.outDebug("WORLD: CMSG_DESTROYITEM"); + uint8 bag, slot, count, data1, data2, data3; + + recv_data >> bag >> slot >> count >> data1 >> data2 >> data3; + //sLog.outDebug("STORAGE: receive bag = %u, slot = %u, count = %u", bag, slot, count); + + uint16 pos = (bag << 8) | slot; + + // prevent drop unequipable items (in combat, for example) and non-empty bags + if(_player->IsEquipmentPos(pos) || _player->IsBagPos(pos)) + { + uint8 msg = _player->CanUnequipItem( pos, false ); + if( msg != EQUIP_ERR_OK ) + { + _player->SendEquipError( msg, _player->GetItemByPos(pos), NULL ); + return; + } + } + + Item *pItem = _player->GetItemByPos( bag, slot ); + if(!pItem) + { + _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); + return; + } + + if(count) + { + uint32 i_count = count; + _player->DestroyItemCount( pItem, i_count, true ); + } + else + _player->DestroyItem( bag, slot, true ); +} + +// Only _static_ data send in this packet !!! +void WorldSession::HandleItemQuerySingleOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data, 4); + + //sLog.outDebug("WORLD: CMSG_ITEM_QUERY_SINGLE"); + uint32 item; + recv_data >> item; + + sLog.outDetail("STORAGE: Item Query = %u", item); + + ItemPrototype const *pProto = objmgr.GetItemPrototype( item ); + if( pProto ) + { + std::string Name = pProto->Name1; + std::string Description = pProto->Description; + + int loc_idx = GetSessionDbLocaleIndex(); + if ( loc_idx >= 0 ) + { + ItemLocale const *il = objmgr.GetItemLocale(pProto->ItemId); + if (il) + { + if (il->Name.size() > loc_idx && !il->Name[loc_idx].empty()) + Name = il->Name[loc_idx]; + if (il->Description.size() > loc_idx && !il->Description[loc_idx].empty()) + Description = il->Description[loc_idx]; + } + } + // guess size + WorldPacket data( SMSG_ITEM_QUERY_SINGLE_RESPONSE, 600); + data << pProto->ItemId; + data << pProto->Class; + data << pProto->SubClass; + data << uint32(-1); // new 2.0.3, not exist in wdb cache? + data << Name; + data << uint8(0x00); //pProto->Name2; // blizz not send name there, just uint8(0x00); <-- \0 = empty string = empty name... + data << uint8(0x00); //pProto->Name3; // blizz not send name there, just uint8(0x00); + data << uint8(0x00); //pProto->Name4; // blizz not send name there, just uint8(0x00); + data << pProto->DisplayInfoID; + data << pProto->Quality; + data << pProto->Flags; + data << pProto->BuyPrice; + data << pProto->SellPrice; + data << pProto->InventoryType; + data << pProto->AllowableClass; + data << pProto->AllowableRace; + data << pProto->ItemLevel; + data << pProto->RequiredLevel; + data << pProto->RequiredSkill; + data << pProto->RequiredSkillRank; + data << pProto->RequiredSpell; + data << pProto->RequiredHonorRank; + data << pProto->RequiredCityRank; + data << pProto->RequiredReputationFaction; + data << pProto->RequiredReputationRank; + data << pProto->MaxCount; + data << pProto->Stackable; + data << pProto->ContainerSlots; + for(int i = 0; i < 10; i++) + { + data << pProto->ItemStat[i].ItemStatType; + data << pProto->ItemStat[i].ItemStatValue; + } + for(int i = 0; i < 5; i++) + { + data << pProto->Damage[i].DamageMin; + data << pProto->Damage[i].DamageMax; + data << pProto->Damage[i].DamageType; + } + data << pProto->Armor; + data << pProto->HolyRes; + data << pProto->FireRes; + data << pProto->NatureRes; + data << pProto->FrostRes; + data << pProto->ShadowRes; + data << pProto->ArcaneRes; + data << pProto->Delay; + data << pProto->Ammo_type; + + data << (float)pProto->RangedModRange; + for(int s = 0; s < 5; s++) + { + // send DBC data for cooldowns in same way as it used in Spell::SendSpellCooldown + // use `item_template` or if not set then only use spell cooldowns + SpellEntry const* spell = sSpellStore.LookupEntry(pProto->Spells[s].SpellId); + if(spell) + { + bool db_data = pProto->Spells[s].SpellCooldown >= 0 || pProto->Spells[s].SpellCategoryCooldown >= 0; + + data << pProto->Spells[s].SpellId; + data << pProto->Spells[s].SpellTrigger; + data << uint32(-abs(pProto->Spells[s].SpellCharges)); + + if(db_data) + { + data << uint32(pProto->Spells[s].SpellCooldown); + data << uint32(pProto->Spells[s].SpellCategory); + data << uint32(pProto->Spells[s].SpellCategoryCooldown); + } + else + { + data << uint32(spell->RecoveryTime); + data << uint32(spell->Category); + data << uint32(spell->CategoryRecoveryTime); + } + } + else + { + data << uint32(0); + data << uint32(0); + data << uint32(0); + data << uint32(-1); + data << uint32(0); + data << uint32(-1); + } + } + data << pProto->Bonding; + data << Description; + data << pProto->PageText; + data << pProto->LanguageID; + data << pProto->PageMaterial; + data << pProto->StartQuest; + data << pProto->LockID; + data << pProto->Material; + data << pProto->Sheath; + data << pProto->RandomProperty; + data << pProto->RandomSuffix; + data << pProto->Block; + data << pProto->ItemSet; + data << pProto->MaxDurability; + data << pProto->Area; + data << pProto->Map; // Added in 1.12.x & 2.0.1 client branch + data << pProto->BagFamily; + data << pProto->TotemCategory; + for(int s = 0; s < 3; s++) + { + data << pProto->Socket[s].Color; + data << pProto->Socket[s].Content; + } + data << pProto->socketBonus; + data << pProto->GemProperties; + data << pProto->RequiredDisenchantSkill; + data << pProto->ArmorDamageModifier; + data << uint32(0); // added in 2.4.2.8209, duration (seconds) + SendPacket( &data ); + } + else + { + sLog.outDebug( "WORLD: CMSG_ITEM_QUERY_SINGLE - NO item INFO! (ENTRY: %u)", item ); + WorldPacket data( SMSG_ITEM_QUERY_SINGLE_RESPONSE, 4); + data << uint32(item | 0x80000000); + SendPacket( &data ); + } +} + +void WorldSession::HandleReadItem( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,1+1); + + //sLog.outDebug( "WORLD: CMSG_READ_ITEM"); + + uint8 bag, slot; + recv_data >> bag >> slot; + + //sLog.outDetail("STORAGE: Read bag = %u, slot = %u", bag, slot); + Item *pItem = _player->GetItemByPos( bag, slot ); + + if( pItem && pItem->GetProto()->PageText ) + { + WorldPacket data; + + uint8 msg = _player->CanUseItem( pItem ); + if( msg == EQUIP_ERR_OK ) + { + data.Initialize (SMSG_READ_ITEM_OK, 8); + sLog.outDetail("STORAGE: Item page sent"); + } + else + { + data.Initialize( SMSG_READ_ITEM_FAILED, 8 ); + sLog.outDetail("STORAGE: Unable to read item"); + _player->SendEquipError( msg, pItem, NULL ); + } + data << pItem->GetGUID(); + SendPacket(&data); + } + else + _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); +} + +void WorldSession::HandlePageQuerySkippedOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,4+8); + + sLog.outDebug( "WORLD: Received CMSG_PAGE_TEXT_QUERY" ); + + uint32 itemid; + uint64 guid; + + recv_data >> itemid >> guid; + + sLog.outDetail( "Packet Info: itemid: %u guidlow: %u guidentry: %u guidhigh: %u", + itemid, GUID_LOPART(guid), GUID_ENPART(guid), GUID_HIPART(guid)); +} + +void WorldSession::HandleSellItemOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+8+1); + + sLog.outDebug( "WORLD: Received CMSG_SELL_ITEM" ); + uint64 vendorguid, itemguid; + uint8 _count; + + recv_data >> vendorguid >> itemguid >> _count; + + // prevent possible overflow, as mangos uses uint32 for item count + uint32 count = _count; + + if(!itemguid) + return; + + Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, vendorguid,UNIT_NPC_FLAG_VENDOR); + if (!pCreature) + { + sLog.outDebug( "WORLD: HandleSellItemOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(vendorguid)) ); + _player->SendSellError( SELL_ERR_CANT_FIND_VENDOR, NULL, itemguid, 0); + return; + } + + // remove fake death + if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + Item *pItem = _player->GetItemByGuid( itemguid ); + if( pItem ) + { + // prevent sell not owner item + if(_player->GetGUID()!=pItem->GetOwnerGUID()) + { + _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0); + return; + } + + // prevent sell non empty bag by drag-and-drop at vendor's item list + if(pItem->IsBag() && !((Bag*)pItem)->IsEmpty()) + { + _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0); + return; + } + + // prevent sell currently looted item + if(_player->GetLootGUID()==pItem->GetGUID()) + { + _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0); + return; + } + + // special case at auto sell (sell all) + if(count==0) + { + count = pItem->GetCount(); + } + else + { + // prevent sell more items that exist in stack (possable only not from client) + if(count > pItem->GetCount()) + { + _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0); + return; + } + } + + ItemPrototype const *pProto = pItem->GetProto(); + if( pProto ) + { + if( pProto->SellPrice > 0 ) + { + if(count < pItem->GetCount()) // need split items + { + Item *pNewItem = pItem->CloneItem( count, _player ); + if (!pNewItem) + { + sLog.outError("WORLD: HandleSellItemOpcode - could not create clone of item %u; count = %u", pItem->GetEntry(), count ); + _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0); + return; + } + + pItem->SetCount( pItem->GetCount() - count ); + _player->ItemRemovedQuestCheck( pItem->GetEntry(), count ); + if( _player->IsInWorld() ) + pItem->SendUpdateToPlayer( _player ); + pItem->SetState(ITEM_CHANGED, _player); + + _player->AddItemToBuyBackSlot( pNewItem ); + if( _player->IsInWorld() ) + pNewItem->SendUpdateToPlayer( _player ); + } + else + { + _player->ItemRemovedQuestCheck( pItem->GetEntry(), pItem->GetCount()); + _player->RemoveItem( pItem->GetBagSlot(), pItem->GetSlot(), true); + pItem->RemoveFromUpdateQueueOf(_player); + _player->AddItemToBuyBackSlot( pItem ); + } + + _player->ModifyMoney( pProto->SellPrice * count ); + } + else + _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0); + return; + } + } + _player->SendSellError( SELL_ERR_CANT_FIND_ITEM, pCreature, itemguid, 0); + return; +} + +void WorldSession::HandleBuybackItem(WorldPacket & recv_data) +{ + CHECK_PACKET_SIZE(recv_data,8+4); + + sLog.outDebug( "WORLD: Received CMSG_BUYBACK_ITEM" ); + uint64 vendorguid; + uint32 slot; + + recv_data >> vendorguid >> slot; + + Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, vendorguid,UNIT_NPC_FLAG_VENDOR); + if (!pCreature) + { + sLog.outDebug( "WORLD: HandleBuybackItem - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(vendorguid)) ); + _player->SendSellError( SELL_ERR_CANT_FIND_VENDOR, NULL, 0, 0); + return; + } + + // remove fake death + if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + Item *pItem = _player->GetItemFromBuyBackSlot( slot ); + if( pItem ) + { + uint32 price = _player->GetUInt32Value( PLAYER_FIELD_BUYBACK_PRICE_1 + slot - BUYBACK_SLOT_START ); + if( _player->GetMoney() < price ) + { + _player->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, pItem->GetEntry(), 0); + return; + } + + ItemPosCountVec dest; + uint8 msg = _player->CanStoreItem( NULL_BAG, NULL_SLOT, dest, pItem, false ); + if( msg == EQUIP_ERR_OK ) + { + _player->ModifyMoney( -(int32)price ); + _player->RemoveItemFromBuyBackSlot( slot, false ); + _player->ItemAddedQuestCheck( pItem->GetEntry(), pItem->GetCount()); + _player->StoreItem( dest, pItem, true ); + } + else + _player->SendEquipError( msg, pItem, NULL ); + return; + } + else + _player->SendBuyError( BUY_ERR_CANT_FIND_ITEM, pCreature, 0, 0); +} + +void WorldSession::HandleBuyItemInSlotOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+4+8+1+1); + + sLog.outDebug( "WORLD: Received CMSG_BUY_ITEM_IN_SLOT" ); + uint64 vendorguid, bagguid; + uint32 item; + uint8 slot, count; + + recv_data >> vendorguid >> item >> bagguid >> slot >> count; + + GetPlayer()->BuyItemFromVendor(vendorguid,item,count,bagguid,slot); +} + +void WorldSession::HandleBuyItemOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+4+1+1); + + sLog.outDebug( "WORLD: Received CMSG_BUY_ITEM" ); + uint64 vendorguid; + uint32 item; + uint8 count, unk1; + + recv_data >> vendorguid >> item >> count >> unk1; + + GetPlayer()->BuyItemFromVendor(vendorguid,item,count,NULL_BAG,NULL_SLOT); +} + +void WorldSession::HandleListInventoryOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8); + + uint64 guid; + + recv_data >> guid; + + if(!GetPlayer()->isAlive()) + return; + + sLog.outDebug( "WORLD: Recvd CMSG_LIST_INVENTORY" ); + + SendListInventory( guid ); +} + +void WorldSession::SendListInventory( uint64 vendorguid ) +{ + sLog.outDebug( "WORLD: Sent SMSG_LIST_INVENTORY" ); + + Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, vendorguid,UNIT_NPC_FLAG_VENDOR); + if (!pCreature) + { + sLog.outDebug( "WORLD: SendListInventory - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(vendorguid)) ); + _player->SendSellError( SELL_ERR_CANT_FIND_VENDOR, NULL, 0, 0); + return; + } + + // remove fake death + if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + // Stop the npc if moving + pCreature->StopMoving(); + // load vendor items if not yet + pCreature->LoadGoods(); + + uint8 numitems = pCreature->GetItemCount(); + uint8 count = 0; + uint32 ptime = time(NULL); + uint32 diff; + + WorldPacket data( SMSG_LIST_INVENTORY, (8+1+numitems*8*4) ); + data << uint64(vendorguid); + data << uint8(numitems); + + float discountMod = _player->GetReputationPriceDiscount(pCreature); + + ItemPrototype const *pProto; + for(int i = 0; i < numitems; i++ ) + { + CreatureItem* crItem = pCreature->GetItem(i); + if( crItem ) + { + pProto = objmgr.GetItemPrototype(crItem->id); + if( pProto ) + { + if((pProto->AllowableClass & _player->getClassMask()) == 0 && pProto->Bonding == BIND_WHEN_PICKED_UP && !_player->isGameMaster()) + continue; + ++count; + if( crItem->incrtime != 0 && (crItem->lastincr + crItem->incrtime <= ptime) ) + { + diff = uint32((ptime - crItem->lastincr)/crItem->incrtime); + if( (crItem->count + diff * pProto->BuyCount) <= crItem->maxcount ) + crItem->count += diff * pProto->BuyCount; + else + crItem->count = crItem->maxcount; + crItem->lastincr = ptime; + } + data << uint32(count); + data << uint32(crItem->id); + data << uint32(pProto->DisplayInfoID); + data << uint32(crItem->maxcount <= 0 ? 0xFFFFFFFF : crItem->count); + + uint32 price = pProto->BuyPrice; + + // reputation discount + price = uint32(floor(pProto->BuyPrice * discountMod)); + + data << uint32(price); + data << uint32(pProto->MaxDurability); + data << uint32(pProto->BuyCount); + data << uint32(crItem->ExtendedCost); + } + } + } + + if ( count == 0 || data.size() != 8 + 1 + size_t(count) * 8 * 4 ) + return; + + data.put(8, count); + SendPacket( &data ); +} + +void WorldSession::HandleAutoStoreBagItemOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,1+1+1); + + //sLog.outDebug("WORLD: CMSG_AUTOSTORE_BAG_ITEM"); + uint8 srcbag, srcslot, dstbag; + + recv_data >> srcbag >> srcslot >> dstbag; + //sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u", srcbag, srcslot, dstbag); + + Item *pItem = _player->GetItemByPos( srcbag, srcslot ); + if( !pItem ) + return; + + uint16 src = pItem->GetPos(); + + // check unequip potability for equipped items and bank bags + if(_player->IsEquipmentPos ( src ) || _player->IsBagPos ( src )) + { + uint8 msg = _player->CanUnequipItem( src, !_player->IsBagPos ( src )); + if(msg != EQUIP_ERR_OK) + { + _player->SendEquipError( msg, pItem, NULL ); + return; + } + } + + ItemPosCountVec dest; + uint8 msg = _player->CanStoreItem( dstbag, NULL_SLOT, dest, pItem, false ); + if( msg != EQUIP_ERR_OK ) + { + _player->SendEquipError( msg, pItem, NULL ); + return; + } + + // no-op: placed in same slot + if(dest.size()==1 && dest[0].pos==src) + { + // just remove grey item state + _player->SendEquipError( EQUIP_ERR_NONE, pItem, NULL ); + return; + } + + _player->RemoveItem(srcbag, srcslot, true ); + _player->StoreItem( dest, pItem, true ); +} + +void WorldSession::HandleBuyBankSlotOpcode(WorldPacket& /*recvPacket*/) +{ + sLog.outDebug("WORLD: CMSG_BUY_BANK_SLOT"); + + uint32 slot = _player->GetByteValue(PLAYER_BYTES_2, 2); + + // next slot + ++slot; + + sLog.outDetail("PLAYER: Buy bank bag slot, slot number = %u", slot); + + BankBagSlotPricesEntry const* slotEntry = sBankBagSlotPricesStore.LookupEntry(slot); + + if(!slotEntry) + return; + + uint32 price = slotEntry->price; + + if (_player->GetMoney() < price) + return; + + _player->SetByteValue(PLAYER_BYTES_2, 2, slot); + _player->ModifyMoney(-int32(price)); +} + +void WorldSession::HandleAutoBankItemOpcode(WorldPacket& recvPacket) +{ + CHECK_PACKET_SIZE(recvPacket,1+1); + + sLog.outDebug("WORLD: CMSG_AUTOBANK_ITEM"); + uint8 srcbag, srcslot; + + recvPacket >> srcbag >> srcslot; + sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u", srcbag, srcslot); + + Item *pItem = _player->GetItemByPos( srcbag, srcslot ); + if( !pItem ) + return; + + ItemPosCountVec dest; + uint8 msg = _player->CanBankItem( NULL_BAG, NULL_SLOT, dest, pItem, false ); + if( msg != EQUIP_ERR_OK ) + { + _player->SendEquipError( msg, pItem, NULL ); + return; + } + + _player->RemoveItem(srcbag, srcslot, true); + _player->BankItem( dest, pItem, true ); +} + +void WorldSession::HandleAutoStoreBankItemOpcode(WorldPacket& recvPacket) +{ + CHECK_PACKET_SIZE(recvPacket,1+1); + + sLog.outDebug("WORLD: CMSG_AUTOSTORE_BANK_ITEM"); + uint8 srcbag, srcslot; + + recvPacket >> srcbag >> srcslot; + sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u", srcbag, srcslot); + + Item *pItem = _player->GetItemByPos( srcbag, srcslot ); + if( !pItem ) + return; + + if(_player->IsBankPos(srcbag, srcslot)) // moving from bank to inventory + { + ItemPosCountVec dest; + uint8 msg = _player->CanStoreItem( NULL_BAG, NULL_SLOT, dest, pItem, false ); + if( msg != EQUIP_ERR_OK ) + { + _player->SendEquipError( msg, pItem, NULL ); + return; + } + + _player->RemoveItem(srcbag, srcslot, true); + _player->StoreItem( dest, pItem, true ); + } + else // moving from inventory to bank + { + ItemPosCountVec dest; + uint8 msg = _player->CanBankItem( NULL_BAG, NULL_SLOT, dest, pItem, false ); + if( msg != EQUIP_ERR_OK ) + { + _player->SendEquipError( msg, pItem, NULL ); + return; + } + + _player->RemoveItem(srcbag, srcslot, true); + _player->BankItem( dest, pItem, true ); + } +} + +void WorldSession::HandleSetAmmoOpcode(WorldPacket & recv_data) +{ + CHECK_PACKET_SIZE(recv_data,4); + + if(!GetPlayer()->isAlive()) + { + GetPlayer()->SendEquipError( EQUIP_ERR_YOU_ARE_DEAD, NULL, NULL ); + return; + } + + sLog.outDebug("WORLD: CMSG_SET_AMMO"); + uint32 item; + + recv_data >> item; + + if(!item) + GetPlayer()->RemoveAmmo(); + else + GetPlayer()->SetAmmo(item); +} + +void WorldSession::SendEnchantmentLog(uint64 Target, uint64 Caster,uint32 ItemID,uint32 SpellID) +{ + WorldPacket data(SMSG_ENCHANTMENTLOG, (8+8+4+4+1)); // last check 2.0.10 + data << Target; + data << Caster; + data << ItemID; + data << SpellID; + data << uint8(0); + SendPacket(&data); +} + +void WorldSession::SendItemEnchantTimeUpdate(uint64 Playerguid, uint64 Itemguid,uint32 slot,uint32 Duration) +{ + // last check 2.0.10 + WorldPacket data(SMSG_ITEM_ENCHANT_TIME_UPDATE, (8+4+4+8)); + data << uint64(Itemguid); + data << uint32(slot); + data << uint32(Duration); + data << uint64(Playerguid); + SendPacket(&data); +} + +void WorldSession::HandleItemNameQueryOpcode(WorldPacket & recv_data) +{ + CHECK_PACKET_SIZE(recv_data,4); + + uint32 itemid; + recv_data >> itemid; + sLog.outDebug("WORLD: CMSG_ITEM_NAME_QUERY %u", itemid); + ItemPrototype const *pProto = objmgr.GetItemPrototype( itemid ); + if( pProto ) + { + std::string Name; + Name = pProto->Name1; + + int loc_idx = GetSessionDbLocaleIndex(); + if (loc_idx >= 0) + { + ItemLocale const *il = objmgr.GetItemLocale(pProto->ItemId); + if (il) + { + if (il->Name.size() > loc_idx && !il->Name[loc_idx].empty()) + Name = il->Name[loc_idx]; + } + } + // guess size + WorldPacket data(SMSG_ITEM_NAME_QUERY_RESPONSE, (4+10)); + data << uint32(pProto->ItemId); + data << Name; + data << uint32(pProto->InventoryType); + SendPacket(&data); + return; + } + else + sLog.outDebug("WORLD: CMSG_ITEM_NAME_QUERY for item %u failed (unknown item)", itemid); +} + +void WorldSession::HandleWrapItemOpcode(WorldPacket& recv_data) +{ + CHECK_PACKET_SIZE(recv_data,1+1+1+1); + + sLog.outDebug("Received opcode CMSG_WRAP_ITEM"); + + uint8 gift_bag, gift_slot, item_bag, item_slot; + //recv_data.hexlike(); + + recv_data >> gift_bag >> gift_slot; // paper + recv_data >> item_bag >> item_slot; // item + + sLog.outDebug("WRAP: receive gift_bag = %u, gift_slot = %u, item_bag = %u, item_slot = %u", gift_bag, gift_slot, item_bag, item_slot); + + Item *gift = _player->GetItemByPos( gift_bag, gift_slot ); + if(!gift) + { + _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, gift, NULL ); + return; + } + + if(!gift->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPER))// cheating: non-wrapper wrapper + { + _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, gift, NULL ); + return; + } + + Item *item = _player->GetItemByPos( item_bag, item_slot ); + + if( !item ) + { + _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, item, NULL ); + return; + } + + if(item==gift) // not possable with pacjket from real client + { + _player->SendEquipError( EQUIP_ERR_WRAPPED_CANT_BE_WRAPPED, item, NULL ); + return; + } + + if(item->IsEquipped()) + { + _player->SendEquipError( EQUIP_ERR_EQUIPPED_CANT_BE_WRAPPED, item, NULL ); + return; + } + + if(item->GetUInt64Value(ITEM_FIELD_GIFTCREATOR)) // HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED); + { + _player->SendEquipError( EQUIP_ERR_WRAPPED_CANT_BE_WRAPPED, item, NULL ); + return; + } + + if(item->IsBag()) + { + _player->SendEquipError( EQUIP_ERR_BAGS_CANT_BE_WRAPPED, item, NULL ); + return; + } + + if(item->IsSoulBound()) + { + _player->SendEquipError( EQUIP_ERR_BOUND_CANT_BE_WRAPPED, item, NULL ); + return; + } + + if(item->GetMaxStackCount() != 1) + { + _player->SendEquipError( EQUIP_ERR_STACKABLE_CANT_BE_WRAPPED, item, NULL ); + return; + } + + // maybe not correct check (it is better than nothing) + if(item->GetProto()->MaxCount>0) + { + _player->SendEquipError( EQUIP_ERR_UNIQUE_CANT_BE_WRAPPED, item, NULL ); + return; + } + + CharacterDatabase.BeginTransaction(); + CharacterDatabase.PExecute("INSERT INTO character_gifts VALUES ('%u', '%u', '%u', '%u')", GUID_LOPART(item->GetOwnerGUID()), item->GetGUIDLow(), item->GetEntry(), item->GetUInt32Value(ITEM_FIELD_FLAGS)); + item->SetUInt32Value(OBJECT_FIELD_ENTRY, gift->GetUInt32Value(OBJECT_FIELD_ENTRY)); + + switch (item->GetEntry()) + { + case 5042: item->SetUInt32Value(OBJECT_FIELD_ENTRY, 5043); break; + case 5048: item->SetUInt32Value(OBJECT_FIELD_ENTRY, 5044); break; + case 17303: item->SetUInt32Value(OBJECT_FIELD_ENTRY, 17302); break; + case 17304: item->SetUInt32Value(OBJECT_FIELD_ENTRY, 17305); break; + case 17307: item->SetUInt32Value(OBJECT_FIELD_ENTRY, 17308); break; + case 21830: item->SetUInt32Value(OBJECT_FIELD_ENTRY, 21831); break; + } + item->SetUInt64Value(ITEM_FIELD_GIFTCREATOR, _player->GetGUID()); + item->SetUInt32Value(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED); + item->SetState(ITEM_CHANGED, _player); + + if(item->GetState()==ITEM_NEW) // save new item, to have alway for `character_gifts` record in `item_instance` + { + // after save it will be impossible to remove the item from the queue + item->RemoveFromUpdateQueueOf(_player); + item->SaveToDB(); // item gave inventory record unchanged and can be save standalone + } + CharacterDatabase.CommitTransaction(); + + uint32 count = 1; + _player->DestroyItemCount(gift, count, true); +} + +void WorldSession::HandleSocketOpcode(WorldPacket& recv_data) +{ + sLog.outDebug("WORLD: CMSG_SOCKET_GEMS"); + + CHECK_PACKET_SIZE(recv_data,8*4); + + uint64 guids[4]; + uint32 GemEnchants[3], OldEnchants[3]; + Item *Gems[3]; + bool SocketBonusActivated, SocketBonusToBeActivated; + + for(int i = 0; i < 4; i++) + recv_data >> guids[i]; + + if(!guids[0]) + return; + + //cheat -> tried to socket same gem multiple times + if((guids[1] && (guids[1] == guids[2] || guids[1] == guids[3])) || (guids[2] && (guids[2] == guids[3]))) + return; + + Item *itemTarget = _player->GetItemByGuid(guids[0]); + if(!itemTarget) //missing item to socket + return; + + //this slot is excepted when applying / removing meta gem bonus + uint8 slot = itemTarget->IsEquipped() ? itemTarget->GetSlot() : NULL_SLOT; + + for(int i = 0; i < 3; i++) + Gems[i] = guids[i + 1] ? _player->GetItemByGuid(guids[i + 1]) : NULL; + + GemPropertiesEntry const *GemProps[3]; + for(int i = 0; i < 3; ++i) //get geminfo from dbc storage + { + GemProps[i] = (Gems[i]) ? sGemPropertiesStore.LookupEntry(Gems[i]->GetProto()->GemProperties) : NULL; + } + + for(int i = 0; i < 3; ++i) //check for hack maybe + { + // tried to put gem in socket where no socket exists / tried to put normal gem in meta socket + // tried to put meta gem in normal socket + if( GemProps[i] && ( !itemTarget->GetProto()->Socket[i].Color || + itemTarget->GetProto()->Socket[i].Color == SOCKET_COLOR_META && GemProps[i]->color != SOCKET_COLOR_META || + itemTarget->GetProto()->Socket[i].Color != SOCKET_COLOR_META && GemProps[i]->color == SOCKET_COLOR_META ) ) + return; + } + + for(int i = 0; i < 3; ++i) //get new and old enchantments + { + GemEnchants[i] = (GemProps[i]) ? GemProps[i]->spellitemenchantement : 0; + OldEnchants[i] = itemTarget->GetEnchantmentId(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT+i)); + } + + // check unique-equipped conditions + for(int i = 0; i < 3; ++i) + { + if (Gems[i] && (Gems[i]->GetProto()->Flags & ITEM_FLAGS_UNIQUE_EQUIPPED)) + { + // for equipped item check all equipment for duplicate equipped gems + if(itemTarget->IsEquipped()) + { + if(GetPlayer()->GetItemOrItemWithGemEquipped(Gems[i]->GetEntry())) + { + _player->SendEquipError( EQUIP_ERR_ITEM_UNIQUE_EQUIPABLE, itemTarget, NULL ); + return; + } + } + + // continue check for case when attempt add 2 similar unique equipped gems in one item. + for (int j = 0; j < 3; ++j) + { + if ((i != j) && (Gems[j]) && (Gems[i]->GetProto()->ItemId == Gems[j]->GetProto()->ItemId)) + { + _player->SendEquipError( EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, NULL ); + return; + } + } + for (int j = 0; j < 3; ++j) + { + if (OldEnchants[j]) + { + SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(OldEnchants[j]); + if(!enchantEntry) + continue; + + if ((enchantEntry->GemID == Gems[i]->GetProto()->ItemId) && (i != j)) + { + _player->SendEquipError( EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, NULL ); + return; + } + } + } + } + } + + SocketBonusActivated = itemTarget->GemsFitSockets(); //save state of socketbonus + _player->ToggleMetaGemsActive(slot, false); //turn off all metagems (except for the target item) + + //if a meta gem is being equipped, all information has to be written to the item before testing if the conditions for the gem are met + + //remove ALL enchants + for(uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+3; ++enchant_slot) + _player->ApplyEnchantment(itemTarget,EnchantmentSlot(enchant_slot),false); + + for(int i = 0; i < 3; ++i) + { + if(GemEnchants[i]) + { + itemTarget->SetEnchantment(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT+i), GemEnchants[i],0,0); + if(Item* guidItem = _player->GetItemByGuid(guids[i + 1])) + _player->DestroyItem(guidItem->GetBagSlot(), guidItem->GetSlot(), true ); + } + } + + for(uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+3; ++enchant_slot) + _player->ApplyEnchantment(itemTarget,EnchantmentSlot(enchant_slot),true); + + SocketBonusToBeActivated = itemTarget->GemsFitSockets();//current socketbonus state + if(SocketBonusActivated ^ SocketBonusToBeActivated) //if there was a change... + { + _player->ApplyEnchantment(itemTarget,BONUS_ENCHANTMENT_SLOT,false); + itemTarget->SetEnchantment(BONUS_ENCHANTMENT_SLOT, (SocketBonusToBeActivated ? itemTarget->GetProto()->socketBonus : 0), 0, 0); + _player->ApplyEnchantment(itemTarget,BONUS_ENCHANTMENT_SLOT,true); + //it is not displayed, client has an inbuilt system to determine if the bonus is activated + } + + _player->ToggleMetaGemsActive(slot, true); //turn on all metagems (except for target item) +} + +void WorldSession::HandleCancelTempItemEnchantmentOpcode(WorldPacket& recv_data) +{ + sLog.outDebug("WORLD: CMSG_CANCEL_TEMP_ENCHANTMENT"); + + CHECK_PACKET_SIZE(recv_data,4); + + uint32 eslot; + + recv_data >> eslot; + + // apply only to equipped item + if(!Player::IsEquipmentPos(INVENTORY_SLOT_BAG_0,eslot)) + return; + + Item* item = GetPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, eslot); + + if(!item) + return; + + if(!item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT)) + return; + + GetPlayer()->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,false); + item->ClearEnchantment(TEMP_ENCHANTMENT_SLOT); +} diff --git a/src/game/ItemPrototype.h b/src/game/ItemPrototype.h new file mode 100644 index 00000000000..2325d229859 --- /dev/null +++ b/src/game/ItemPrototype.h @@ -0,0 +1,565 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _ITEMPROTOTYPE_H +#define _ITEMPROTOTYPE_H + +#include "Common.h" + +enum ItemModType +{ + ITEM_MOD_MANA = 0, + ITEM_MOD_HEALTH = 1, + ITEM_MOD_AGILITY = 3, + ITEM_MOD_STRENGTH = 4, + ITEM_MOD_INTELLECT = 5, + ITEM_MOD_SPIRIT = 6, + ITEM_MOD_STAMINA = 7, + ITEM_MOD_DEFENSE_SKILL_RATING = 12, + ITEM_MOD_DODGE_RATING = 13, + ITEM_MOD_PARRY_RATING = 14, + ITEM_MOD_BLOCK_RATING = 15, + ITEM_MOD_HIT_MELEE_RATING = 16, + ITEM_MOD_HIT_RANGED_RATING = 17, + ITEM_MOD_HIT_SPELL_RATING = 18, + ITEM_MOD_CRIT_MELEE_RATING = 19, + ITEM_MOD_CRIT_RANGED_RATING = 20, + ITEM_MOD_CRIT_SPELL_RATING = 21, + ITEM_MOD_HIT_TAKEN_MELEE_RATING = 22, + ITEM_MOD_HIT_TAKEN_RANGED_RATING = 23, + ITEM_MOD_HIT_TAKEN_SPELL_RATING = 24, + ITEM_MOD_CRIT_TAKEN_MELEE_RATING = 25, + ITEM_MOD_CRIT_TAKEN_RANGED_RATING = 26, + ITEM_MOD_CRIT_TAKEN_SPELL_RATING = 27, + ITEM_MOD_HASTE_MELEE_RATING = 28, + ITEM_MOD_HASTE_RANGED_RATING = 29, + ITEM_MOD_HASTE_SPELL_RATING = 30, + ITEM_MOD_HIT_RATING = 31, + ITEM_MOD_CRIT_RATING = 32, + ITEM_MOD_HIT_TAKEN_RATING = 33, + ITEM_MOD_CRIT_TAKEN_RATING = 34, + ITEM_MOD_RESILIENCE_RATING = 35, + ITEM_MOD_HASTE_RATING = 36, + ITEM_MOD_EXPERTISE_RATING = 37 +}; + +#define MAX_ITEM_MOD 38 + +enum ItemSpelltriggerType +{ + ITEM_SPELLTRIGGER_ON_USE = 0, // use after equip cooldown + ITEM_SPELLTRIGGER_ON_EQUIP = 1, + ITEM_SPELLTRIGGER_CHANCE_ON_HIT = 2, + ITEM_SPELLTRIGGER_SOULSTONE = 4, + ITEM_SPELLTRIGGER_ON_NO_DELAY_USE = 5, // no equip cooldown + ITEM_SPELLTRIGGER_LEARN_SPELL_ID = 6 // used in item_template.spell_2 with spell_id with SPELL_GENERIC_LEARN in spell_1 +}; + +#define MAX_ITEM_SPELLTRIGGER 7 + +enum ItemBondingType +{ + NO_BIND = 0, + BIND_WHEN_PICKED_UP = 1, + BIND_WHEN_EQUIPED = 2, + BIND_WHEN_USE = 3, + BIND_QUEST_ITEM = 4, + BIND_QUEST_ITEM1 = 5 // not used in game +}; + +#define MAX_BIND_TYPE 6 + +// masks for ITEM_FIELD_FLAGS field +enum ITEM_FLAGS +{ + ITEM_FLAGS_BINDED = 0x00000001, + ITEM_FLAGS_CONJURED = 0x00000002, + ITEM_FLAGS_OPENABLE = 0x00000004, + ITEM_FLAGS_WRAPPED = 0x00000008, + ITEM_FLAGS_WRAPPER = 0x00000200, // used or not used wrapper + ITEM_FLAGS_PARTY_LOOT = 0x00000800, // determines if item is party loot or not + ITEM_FLAGS_CHARTER = 0x00002000, // arena/guild charter + ITEM_FLAGS_UNIQUE_EQUIPPED = 0x00080000, + ITEM_FLAGS_USEABLE_IN_ARENA = 0x00200000, + ITEM_FLAGS_THROWABLE = 0x00400000, // not used in game for check trow possibility, only for item in game tooltip + ITEM_FLAGS_SPECIALUSE = 0x00800000 // last used flag in 2.3.0 +}; + +enum BAG_FAMILY_MASK +{ + BAG_FAMILY_MASK_ARROWS = 0x00000001, + BAG_FAMILY_MASK_BULLETS = 0x00000002, + BAG_FAMILY_MASK_SHARDS = 0x00000004, + BAG_FAMILY_MASK_LEATHERWORKING_SUPP = 0x00000008, + BAG_FAMILY_MASK_UNUSED = 0x00000010, // not used currently + BAG_FAMILY_MASK_HERBS = 0x00000020, + BAG_FAMILY_MASK_ENCHANTING_SUPP = 0x00000040, + BAG_FAMILY_MASK_ENGINEERING_SUPP = 0x00000080, + BAG_FAMILY_MASK_KEYS = 0x00000100, + BAG_FAMILY_MASK_GEMS = 0x00000200, + BAG_FAMILY_MASK_MINING_SUPP = 0x00000400, + BAG_FAMILY_MASK_SOULBOUND_EQUIPMENT = 0x00000800, + BAG_FAMILY_MASK_VANITY_PETS = 0x00001000 +}; + +/* TODO: Not entirely positive on need for this?? +enum SOCKET_CONTENT (); +*/ + +enum SocketColor +{ + SOCKET_COLOR_META = 1, + SOCKET_COLOR_RED = 2, + SOCKET_COLOR_YELLOW = 4, + SOCKET_COLOR_BLUE = 8 +}; + +#define SOCKET_COLOR_ALL (SOCKET_COLOR_META | SOCKET_COLOR_RED | SOCKET_COLOR_YELLOW | SOCKET_COLOR_BLUE) + +enum InventoryType +{ + INVTYPE_NON_EQUIP = 0, + INVTYPE_HEAD = 1, + INVTYPE_NECK = 2, + INVTYPE_SHOULDERS = 3, + INVTYPE_BODY = 4, + INVTYPE_CHEST = 5, + INVTYPE_WAIST = 6, + INVTYPE_LEGS = 7, + INVTYPE_FEET = 8, + INVTYPE_WRISTS = 9, + INVTYPE_HANDS = 10, + INVTYPE_FINGER = 11, + INVTYPE_TRINKET = 12, + INVTYPE_WEAPON = 13, + INVTYPE_SHIELD = 14, + INVTYPE_RANGED = 15, + INVTYPE_CLOAK = 16, + INVTYPE_2HWEAPON = 17, + INVTYPE_BAG = 18, + INVTYPE_TABARD = 19, + INVTYPE_ROBE = 20, + INVTYPE_WEAPONMAINHAND = 21, + INVTYPE_WEAPONOFFHAND = 22, + INVTYPE_HOLDABLE = 23, + INVTYPE_AMMO = 24, + INVTYPE_THROWN = 25, + INVTYPE_RANGEDRIGHT = 26, + INVTYPE_QUIVER = 27, + INVTYPE_RELIC = 28 +}; + +#define MAX_INVTYPE 29 + +enum ItemClass +{ + ITEM_CLASS_CONSUMABLE = 0, + ITEM_CLASS_CONTAINER = 1, + ITEM_CLASS_WEAPON = 2, + ITEM_CLASS_GEM = 3, + ITEM_CLASS_ARMOR = 4, + ITEM_CLASS_REAGENT = 5, + ITEM_CLASS_PROJECTILE = 6, + ITEM_CLASS_TRADE_GOODS = 7, + ITEM_CLASS_GENERIC = 8, + ITEM_CLASS_RECIPE = 9, + ITEM_CLASS_MONEY = 10, + ITEM_CLASS_QUIVER = 11, + ITEM_CLASS_QUEST = 12, + ITEM_CLASS_KEY = 13, + ITEM_CLASS_PERMANENT = 14, + ITEM_CLASS_JUNK = 15 +}; + +#define MAX_ITEM_CLASS 16 + +enum ItemSubclassConsumable +{ + ITEM_SUBCLASS_CONSUMABLE = 0, + ITEM_SUBCLASS_POTION = 1, + ITEM_SUBCLASS_ELIXIR = 2, + ITEM_SUBCLASS_FLASK = 3, + ITEM_SUBCLASS_SCROLL = 4, + ITEM_SUBCLASS_FOOD = 5, + ITEM_SUBCLASS_ITEM_ENHANCEMENT = 6, + ITEM_SUBCLASS_BANDAGE = 7, + ITEM_SUBCLASS_CONSUMABLE_OTHER = 8 +}; + +#define MAX_ITEM_SUBCLASS_CONSUMABLE 9 + +enum ItemSubclassContainer +{ + ITEM_SUBCLASS_CONTAINER = 0, + ITEM_SUBCLASS_SOUL_CONTAINER = 1, + ITEM_SUBCLASS_HERB_CONTAINER = 2, + ITEM_SUBCLASS_ENCHANTING_CONTAINER = 3, + ITEM_SUBCLASS_ENGINEERING_CONTAINER = 4, + ITEM_SUBCLASS_GEM_CONTAINER = 5, + ITEM_SUBCLASS_MINING_CONTAINER = 6, + ITEM_SUBCLASS_LEATHERWORKING_CONTAINER = 7 +}; + +#define MAX_ITEM_SUBCLASS_CONTAINER 8 + +enum ItemSubclassWeapon +{ + ITEM_SUBCLASS_WEAPON_AXE = 0, + ITEM_SUBCLASS_WEAPON_AXE2 = 1, + ITEM_SUBCLASS_WEAPON_BOW = 2, + ITEM_SUBCLASS_WEAPON_GUN = 3, + ITEM_SUBCLASS_WEAPON_MACE = 4, + ITEM_SUBCLASS_WEAPON_MACE2 = 5, + ITEM_SUBCLASS_WEAPON_POLEARM = 6, + ITEM_SUBCLASS_WEAPON_SWORD = 7, + ITEM_SUBCLASS_WEAPON_SWORD2 = 8, + ITEM_SUBCLASS_WEAPON_obsolete = 9, + ITEM_SUBCLASS_WEAPON_STAFF = 10, + ITEM_SUBCLASS_WEAPON_EXOTIC = 11, + ITEM_SUBCLASS_WEAPON_EXOTIC2 = 12, + ITEM_SUBCLASS_WEAPON_FIST = 13, + ITEM_SUBCLASS_WEAPON_MISC = 14, + ITEM_SUBCLASS_WEAPON_DAGGER = 15, + ITEM_SUBCLASS_WEAPON_THROWN = 16, + ITEM_SUBCLASS_WEAPON_SPEAR = 17, + ITEM_SUBCLASS_WEAPON_CROSSBOW = 18, + ITEM_SUBCLASS_WEAPON_WAND = 19, + ITEM_SUBCLASS_WEAPON_FISHING_POLE = 20 +}; + +#define MAX_ITEM_SUBCLASS_WEAPON 21 + +enum ItemSubclassGem +{ + ITEM_SUBCLASS_GEM_RED = 0, + ITEM_SUBCLASS_GEM_BLUE = 1, + ITEM_SUBCLASS_GEM_YELLOW = 2, + ITEM_SUBCLASS_GEM_PURPLE = 3, + ITEM_SUBCLASS_GEM_GREEN = 4, + ITEM_SUBCLASS_GEM_ORANGE = 5, + ITEM_SUBCLASS_GEM_META = 6, + ITEM_SUBCLASS_GEM_SIMPLE = 7, + ITEM_SUBCLASS_GEM_PRISMATIC = 8 +}; + +#define MAX_ITEM_SUBCLASS_GEM 9 + +enum ItemSubclassArmor +{ + ITEM_SUBCLASS_ARMOR_MISC = 0, + ITEM_SUBCLASS_ARMOR_CLOTH = 1, + ITEM_SUBCLASS_ARMOR_LEATHER = 2, + ITEM_SUBCLASS_ARMOR_MAIL = 3, + ITEM_SUBCLASS_ARMOR_PLATE = 4, + ITEM_SUBCLASS_ARMOR_BUCKLER = 5, + ITEM_SUBCLASS_ARMOR_SHIELD = 6, + ITEM_SUBCLASS_ARMOR_LIBRAM = 7, + ITEM_SUBCLASS_ARMOR_IDOL = 8, + ITEM_SUBCLASS_ARMOR_TOTEM = 9 +}; + +#define MAX_ITEM_SUBCLASS_ARMOR 10 + +enum ItemSubclassReagent +{ + ITEM_SUBCLASS_REAGENT = 0 +}; + +#define MAX_ITEM_SUBCLASS_REAGENT 1 + +enum ItemSubclassProjectile +{ + ITEM_SUBCLASS_WAND = 0, // ABS + ITEM_SUBCLASS_BOLT = 1, // ABS + ITEM_SUBCLASS_ARROW = 2, + ITEM_SUBCLASS_BULLET = 3, + ITEM_SUBCLASS_THROWN = 4 // ABS +}; + +#define MAX_ITEM_SUBCLASS_PROJECTILE 5 + +enum ItemSubclassTradeGoods +{ + ITEM_SUBCLASS_TRADE_GOODS = 0, + ITEM_SUBCLASS_PARTS = 1, + ITEM_SUBCLASS_EXPLOSIVES = 2, + ITEM_SUBCLASS_DEVICES = 3, + ITEM_SUBCLASS_JEWELCRAFTING = 4, + ITEM_SUBCLASS_CLOTH = 5, + ITEM_SUBCLASS_LEATHER = 6, + ITEM_SUBCLASS_METAL_STONE = 7, + ITEM_SUBCLASS_MEAT = 8, + ITEM_SUBCLASS_HERB = 9, + ITEM_SUBCLASS_ELEMENTAL = 10, + ITEM_SUBCLASS_TRADE_GOODS_OTHER = 11, + ITEM_SUBCLASS_ENCHANTING = 12, + ITEM_SUBCLASS_MATERIAL = 13 // Added in 2.4.2 +}; + +#define MAX_ITEM_SUBCLASS_TRADE_GOODS 14 + +enum ItemSubclassGeneric +{ + ITEM_SUBCLASS_GENERIC = 0 +}; + +#define MAX_ITEM_SUBCLASS_GENERIC 1 + +enum ItemSubclassRecipe +{ + ITEM_SUBCLASS_BOOK = 0, + ITEM_SUBCLASS_LEATHERWORKING_PATTERN = 1, + ITEM_SUBCLASS_TAILORING_PATTERN = 2, + ITEM_SUBCLASS_ENGINEERING_SCHEMATIC = 3, + ITEM_SUBCLASS_BLACKSMITHING = 4, + ITEM_SUBCLASS_COOKING_RECIPE = 5, + ITEM_SUBCLASS_ALCHEMY_RECIPE = 6, + ITEM_SUBCLASS_FIRST_AID_MANUAL = 7, + ITEM_SUBCLASS_ENCHANTING_FORMULA = 8, + ITEM_SUBCLASS_FISHING_MANUAL = 9, + ITEM_SUBCLASS_JEWELCRAFTING_RECIPE = 10 +}; + +#define MAX_ITEM_SUBCLASS_RECIPE 11 + +enum ItemSubclassMoney +{ + ITEM_SUBCLASS_MONEY = 0 +}; + +#define MAX_ITEM_SUBCLASS_MONEY 1 + +enum ItemSubclassQuiver +{ + ITEM_SUBCLASS_QUIVER0 = 0, // ABS + ITEM_SUBCLASS_QUIVER1 = 1, // ABS + ITEM_SUBCLASS_QUIVER = 2, + ITEM_SUBCLASS_AMMO_POUCH = 3 +}; + +#define MAX_ITEM_SUBCLASS_QUIVER 4 + +enum ItemSubclassQuest +{ + ITEM_SUBCLASS_QUEST = 0 +}; + +#define MAX_ITEM_SUBCLASS_QUEST 1 + +enum ItemSubclassKey +{ + ITEM_SUBCLASS_KEY = 0, + ITEM_SUBCLASS_LOCKPICK = 1 +}; + +#define MAX_ITEM_SUBCLASS_KEY 2 + +enum ItemSubclassPermanent +{ + ITEM_SUBCLASS_PERMANENT = 0 +}; + +#define MAX_ITEM_SUBCLASS_PERMANENT 1 + +enum ItemSubclassJunk +{ + ITEM_SUBCLASS_JUNK = 0, + ITEM_SUBCLASS_JUNK_REAGENT = 1, + ITEM_SUBCLASS_JUNK_PET = 2, + ITEM_SUBCLASS_JUNK_HOLIDAY = 3, + ITEM_SUBCLASS_JUNK_OTHER = 4, + ITEM_SUBCLASS_JUNK_MOUNT = 5 +}; + +#define MAX_ITEM_SUBCLASS_JUNK 6 + +const uint32 MaxItemSubclassValues[MAX_ITEM_CLASS] = +{ + MAX_ITEM_SUBCLASS_CONSUMABLE, + MAX_ITEM_SUBCLASS_CONTAINER, + MAX_ITEM_SUBCLASS_WEAPON, + MAX_ITEM_SUBCLASS_GEM, + MAX_ITEM_SUBCLASS_ARMOR, + MAX_ITEM_SUBCLASS_REAGENT, + MAX_ITEM_SUBCLASS_PROJECTILE, + MAX_ITEM_SUBCLASS_TRADE_GOODS, + MAX_ITEM_SUBCLASS_GENERIC, + MAX_ITEM_SUBCLASS_RECIPE, + MAX_ITEM_SUBCLASS_MONEY, + MAX_ITEM_SUBCLASS_QUIVER, + MAX_ITEM_SUBCLASS_QUEST, + MAX_ITEM_SUBCLASS_KEY, + MAX_ITEM_SUBCLASS_PERMANENT, + MAX_ITEM_SUBCLASS_JUNK +}; + +inline uint8 ItemSubClassToDurabilityMultiplierId(uint32 ItemClass, uint32 ItemSubClass) +{ + switch(ItemClass) + { + case ITEM_CLASS_WEAPON: return ItemSubClass; + case ITEM_CLASS_ARMOR: return ItemSubClass + 21; + } + return 0; +} + +// GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push,N), also any gcc version not support it at some platform +#if defined( __GNUC__ ) +#pragma pack(1) +#else +#pragma pack(push,1) +#endif + +struct _Damage +{ + float DamageMin; + float DamageMax; + uint32 DamageType; // id from Resistances.dbc + +}; + +struct _ItemStat +{ + uint32 ItemStatType; + int32 ItemStatValue; + +}; +struct _Spell +{ + uint32 SpellId; // id from Spell.dbc + uint32 SpellTrigger; + int32 SpellCharges; + float SpellPPMRate; + int32 SpellCooldown; + uint32 SpellCategory; // id from SpellCategory.dbc + int32 SpellCategoryCooldown; + +}; + +struct _Socket +{ + uint32 Color; + uint32 Content; +}; + +struct ItemPrototype +{ + uint32 ItemId; + uint32 Class; // id from ItemClass.dbc + uint32 SubClass; // id from ItemSubClass.dbc + uint32 Unk0; + char* Name1; + uint32 DisplayInfoID; // id from ItemDisplayInfo.dbc + uint32 Quality; + uint32 Flags; + uint32 BuyCount; + uint32 BuyPrice; + uint32 SellPrice; + uint32 InventoryType; + uint32 AllowableClass; + uint32 AllowableRace; + uint32 ItemLevel; + uint32 RequiredLevel; + uint32 RequiredSkill; // id from SkillLine.dbc + uint32 RequiredSkillRank; + uint32 RequiredSpell; // id from Spell.dbc + uint32 RequiredHonorRank; + uint32 RequiredCityRank; + uint32 RequiredReputationFaction; // id from Faction.dbc + uint32 RequiredReputationRank; + uint32 MaxCount; + uint32 Stackable; + uint32 ContainerSlots; + _ItemStat ItemStat[10]; + _Damage Damage[5]; + uint32 Armor; + uint32 HolyRes; + uint32 FireRes; + uint32 NatureRes; + uint32 FrostRes; + uint32 ShadowRes; + uint32 ArcaneRes; + uint32 Delay; + uint32 Ammo_type; + float RangedModRange; + + _Spell Spells[5]; + uint32 Bonding; + char* Description; + uint32 PageText; + uint32 LanguageID; + uint32 PageMaterial; + uint32 StartQuest; // id from QuestCache.wdb + uint32 LockID; + uint32 Material; // id from Material.dbc + uint32 Sheath; + uint32 RandomProperty; // id from ItemRandomProperties.dbc + uint32 RandomSuffix; // id from ItemRandomSuffix.dbc + uint32 Block; + uint32 ItemSet; // id from ItemSet.dbc + uint32 MaxDurability; + uint32 Area; // id from AreaTable.dbc + uint32 Map; // id from Map.dbc + uint32 BagFamily; // id from ItemBagFamily.dbc + uint32 TotemCategory; // id from TotemCategory.dbc + _Socket Socket[3]; + uint32 socketBonus; // id from SpellItemEnchantment.dbc + uint32 GemProperties; // id from GemProperties.dbc + uint32 RequiredDisenchantSkill; + float ArmorDamageModifier; + char* ScriptName; + uint32 DisenchantID; + uint32 FoodType; + uint32 MinMoneyLoot; + uint32 MaxMoneyLoot; + int32 Duration; // negative = realtime, positive = ingame time + + // helpers + bool CanChangeEquipStateInCombat() const + { + switch(InventoryType) + { + case INVTYPE_RELIC: + case INVTYPE_SHIELD: + return true; + } + + switch(Class) + { + case ITEM_CLASS_WEAPON: + case ITEM_CLASS_PROJECTILE: + return true; + } + + return false; + } +}; + +struct ItemLocale +{ + std::vector Name; + std::vector Description; +}; + +// GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some platform +#if defined( __GNUC__ ) +#pragma pack() +#else +#pragma pack(pop) +#endif +#endif diff --git a/src/game/LFGHandler.cpp b/src/game/LFGHandler.cpp new file mode 100644 index 00000000000..df87b51de89 --- /dev/null +++ b/src/game/LFGHandler.cpp @@ -0,0 +1,337 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "WorldSession.h" +#include "Log.h" +#include "Database/DatabaseEnv.h" +#include "Player.h" +#include "WorldPacket.h" +#include "ObjectMgr.h" +#include "World.h" + +static void AttemptJoin(Player* _player) +{ + // skip not can autojoin cases and player group case + if(!_player->m_lookingForGroup.canAutoJoin() || _player->GetGroup()) + return; + + //TODO: Guard Player Map + HashMapHolder::MapType const& players = ObjectAccessor::Instance().GetPlayers(); + for(HashMapHolder::MapType::const_iterator iter = players.begin(); iter != players.end(); ++iter) + { + Player *plr = iter->second; + + // skip enemies and self + if(!plr || plr==_player || plr->GetTeam() != _player->GetTeam()) + continue; + + // skip not auto add, not group leader cases + if(!plr->GetSession()->LookingForGroup_auto_add || plr->GetGroup() && plr->GetGroup()->GetLeaderGUID()!=plr->GetGUID()) + continue; + + // skip non auto-join or empty slots, or non compatible slots + if(!plr->m_lookingForGroup.more.canAutoJoin() || !_player->m_lookingForGroup.HaveInSlot(plr->m_lookingForGroup.more)) + continue; + + // attempt create group, or skip + if(!plr->GetGroup()) + { + Group* group = new Group; + if(!group->Create(plr->GetGUID(), plr->GetName())) + { + delete group; + continue; + } + + objmgr.AddGroup(group); + } + + // stop at success join + if(plr->GetGroup()->AddMember(_player->GetGUID(), _player->GetName())) + { + if( sWorld.getConfig(CONFIG_RESTRICTED_LFG_CHANNEL) && _player->GetSession()->GetSecurity() == SEC_PLAYER ) + _player->LeaveLFGChannel(); + break; + } + // full + else + { + if( sWorld.getConfig(CONFIG_RESTRICTED_LFG_CHANNEL) && plr->GetSession()->GetSecurity() == SEC_PLAYER ) + plr->LeaveLFGChannel(); + } + } +} + +static void AttemptAddMore(Player* _player) +{ + // skip not group leader case + if(_player->GetGroup() && _player->GetGroup()->GetLeaderGUID()!=_player->GetGUID()) + return; + + if(!_player->m_lookingForGroup.more.canAutoJoin()) + return; + + //TODO: Guard Player map + HashMapHolder::MapType const& players = ObjectAccessor::Instance().GetPlayers(); + for(HashMapHolder::MapType::const_iterator iter = players.begin(); iter != players.end(); ++iter) + { + Player *plr = iter->second; + + // skip enemies and self + if(!plr || plr==_player || plr->GetTeam() != _player->GetTeam()) + continue; + + // skip not auto join or in group + if(!plr->GetSession()->LookingForGroup_auto_join || plr->GetGroup() ) + continue; + + if(!plr->m_lookingForGroup.HaveInSlot(_player->m_lookingForGroup.more)) + continue; + + // attempt create group if need, or stop attempts + if(!_player->GetGroup()) + { + Group* group = new Group; + if(!group->Create(_player->GetGUID(), _player->GetName())) + { + delete group; + return; // cann't create group (??) + } + + objmgr.AddGroup(group); + } + + // stop at join fail (full) + if(!_player->GetGroup()->AddMember(plr->GetGUID(), plr->GetName()) ) + { + if( sWorld.getConfig(CONFIG_RESTRICTED_LFG_CHANNEL) && _player->GetSession()->GetSecurity() == SEC_PLAYER ) + _player->LeaveLFGChannel(); + + break; + } + + // joined + if( sWorld.getConfig(CONFIG_RESTRICTED_LFG_CHANNEL) && plr->GetSession()->GetSecurity() == SEC_PLAYER ) + plr->LeaveLFGChannel(); + + // and group full + if(_player->GetGroup()->IsFull() ) + { + if( sWorld.getConfig(CONFIG_RESTRICTED_LFG_CHANNEL) && _player->GetSession()->GetSecurity() == SEC_PLAYER ) + _player->LeaveLFGChannel(); + + break; + } + } +} + +void WorldSession::HandleLfgAutoJoinOpcode( WorldPacket & /*recv_data*/ ) +{ + sLog.outDebug("CMSG_SET_LFG_AUTO_JOIN"); + LookingForGroup_auto_join = true; + + if(!_player) // needed because STATUS_AUTHED + return; + + AttemptJoin(_player); +} + +void WorldSession::HandleLfgCancelAutoJoinOpcode( WorldPacket & /*recv_data*/ ) +{ + sLog.outDebug("CMSG_UNSET_LFG_AUTO_JOIN"); + LookingForGroup_auto_join = false; +} + +void WorldSession::HandleLfmAutoAddMembersOpcode( WorldPacket & /*recv_data*/ ) +{ + sLog.outDebug("CMSG_SET_LFM_AUTOADD"); + LookingForGroup_auto_add = true; + + if(!_player) // needed because STATUS_AUTHED + return; + + AttemptAddMore(_player); +} + +void WorldSession::HandleLfmCancelAutoAddmembersOpcode( WorldPacket & /*recv_data*/ ) +{ + sLog.outDebug("CMSG_UNSET_LFM_AUTOADD"); + LookingForGroup_auto_add = false; +} + +void WorldSession::HandleLfgClearOpcode( WorldPacket & /*recv_data */ ) +{ + sLog.outDebug("CMSG_LOOKING_FOR_GROUP_CLEAR"); + + for(int i = 0; i < MAX_LOOKING_FOR_GROUP_SLOT; ++i) + _player->m_lookingForGroup.slots[i].Clear(); + + if( sWorld.getConfig(CONFIG_RESTRICTED_LFG_CHANNEL) && _player->GetSession()->GetSecurity() == SEC_PLAYER ) + _player->LeaveLFGChannel(); +} + +void WorldSession::HandleLfmSetNoneOpcode( WorldPacket & /*recv_data */) +{ + sLog.outDebug("CMSG_SET_LOOKING_FOR_NONE"); + + _player->m_lookingForGroup.more.Clear(); +} + +void WorldSession::HandleLfmSetOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,4); + + sLog.outDebug("CMSG_SET_LOOKING_FOR_MORE"); + //recv_data.hexlike(); + uint32 temp, entry, type; + + recv_data >> temp; + + entry = ( temp & 0xFFFF); + type = ( (temp >> 24) & 0xFFFF); + + _player->m_lookingForGroup.more.Set(entry,type); + sLog.outDebug("LFM set: temp %u, zone %u, type %u", temp, entry, type); + + if(LookingForGroup_auto_add) + AttemptAddMore(_player); + + SendLfgResult(type, entry, 1); +} + +void WorldSession::HandleLfgSetCommentOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,1); + + sLog.outDebug("CMSG_SET_COMMENTARY"); + //recv_data.hexlike(); + + std::string comment; + recv_data >> comment; + sLog.outDebug("LFG comment %s", comment.c_str()); + + _player->m_lookingForGroup.comment = comment; +} + +void WorldSession::HandleLookingForGroup(WorldPacket& recv_data) +{ + CHECK_PACKET_SIZE(recv_data,4+4+4); + + sLog.outDebug("MSG_LOOKING_FOR_GROUP"); + //recv_data.hexlike(); + uint32 type, entry, unk; + + recv_data >> type >> entry >> unk; + sLog.outDebug("MSG_LOOKING_FOR_GROUP: type %u, entry %u, unk %u", type, entry, unk); + + if(LookingForGroup_auto_add) + AttemptAddMore(_player); + + if(LookingForGroup_auto_join) + AttemptJoin(_player); + + SendLfgResult(type, entry, 0); +} + +void WorldSession::SendLfgResult(uint32 type, uint32 entry, uint8 lfg_type) +{ + uint32 number = 0; + + // start preper packet; + WorldPacket data(MSG_LOOKING_FOR_GROUP); + data << uint32(type); // type + data << uint32(entry); // entry from LFGDungeons.dbc + data << uint32(0); // count, placeholder + data << uint32(0); // count again, strange, placeholder + + //TODO: Guard Player map + HashMapHolder::MapType const& players = ObjectAccessor::Instance().GetPlayers(); + for(HashMapHolder::MapType::const_iterator iter = players.begin(); iter != players.end(); ++iter) + { + Player *plr = iter->second; + + if(!plr || plr->GetTeam() != _player->GetTeam()) + continue; + + if(!plr->m_lookingForGroup.HaveInSlot(entry,type)) + continue; + + ++number; + + data.append(plr->GetPackGUID()); // packed guid + data << plr->getLevel(); // level + data << plr->GetZoneId(); // current zone + data << lfg_type; // 0x00 - LFG, 0x01 - LFM + + for(uint8 j = 0; j < MAX_LOOKING_FOR_GROUP_SLOT; ++j) + { + data << uint32( plr->m_lookingForGroup.slots[j].entry | (plr->m_lookingForGroup.slots[j].type << 24) ); + } + data << plr->m_lookingForGroup.comment; + + Group *group = plr->GetGroup(); + if(group) + { + data << group->GetMembersCount()-1; // count of group members without group leader + for(GroupReference *itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *member = itr->getSource(); + if(member && member->GetGUID() != plr->GetGUID()) + { + data.append(member->GetPackGUID()); // packed guid + data << member->getLevel(); // player level + } + } + } + else + { + data << uint32(0x00); + } + } + + // fill count placeholders + data.put(4+4, number); + data.put(4+4+4,number); + + SendPacket(&data); +} + +void WorldSession::HandleSetLfgOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,4+4); + + sLog.outDebug("CMSG_SET_LOOKING_FOR_GROUP"); + //recv_data.hexlike(); + uint32 slot, temp, entry, type; + + recv_data >> slot >> temp; + + entry = ( temp & 0xFFFF); + type = ( (temp >> 24) & 0xFFFF); + + if(slot >= MAX_LOOKING_FOR_GROUP_SLOT) + return; + + _player->m_lookingForGroup.slots[slot].Set(entry,type); + sLog.outDebug("LFG set: looknumber %u, temp %X, type %u, entry %u", slot, temp, type, entry); + + if(LookingForGroup_auto_join) + AttemptJoin(_player); + + SendLfgResult(type, entry, 0); +} diff --git a/src/game/Language.h b/src/game/Language.h new file mode 100644 index 00000000000..bb36bffcee6 --- /dev/null +++ b/src/game/Language.h @@ -0,0 +1,665 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __MANGOS_LANGUAGE_H +#define __MANGOS_LANGUAGE_H + +enum MangosStrings +{ + // for chat commands + LANG_SELECT_CHAR_OR_CREATURE = 1, + LANG_SELECT_CREATURE = 2, + + // level 0 chat + LANG_SYSTEMMESSAGE = 3, + LANG_EVENTMESSAGE = 4, + LANG_NO_HELP_CMD = 5, + LANG_NO_CMD = 6, + LANG_NO_SUBCMD = 7, + LANG_SUBCMDS_LIST = 8, + LANG_AVIABLE_CMD = 9, + LANG_CMD_SYNTAX = 10, + LANG_ACCOUNT_LEVEL = 11, + LANG_CONNECTED_USERS = 12, + LANG_UPTIME = 13, + LANG_PLAYER_SAVED = 14, + LANG_PLAYERS_SAVED = 15, + LANG_GMS_ON_SRV = 16, + LANG_GMS_NOT_LOGGED = 17, + LANG_YOU_IN_FLIGHT = 18, + //LANG_YOU_IN_BATTLEGROUND = 19, not used + //LANG_TARGET_IN_FLIGHT = 20, not used + LANG_CHAR_IN_FLIGHT = 21, + LANG_CHAR_NON_MOUNTED = 22, + LANG_YOU_IN_COMBAT = 23, + LANG_YOU_USED_IT_RECENTLY = 24, + LANG_COMMAND_NOTCHANGEPASSWORD = 25, + LANG_COMMAND_PASSWORD = 26, + LANG_COMMAND_WRONGOLDPASSWORD = 27, + LANG_COMMAND_ACCLOCKLOCKED = 28, + LANG_COMMAND_ACCLOCKUNLOCKED = 29, + LANG_SPELL_RANK = 30, + LANG_KNOWN = 31, + LANG_LEARN = 32, + LANG_PASSIVE = 33, + LANG_TALENT = 34, + LANG_ACTIVE = 35, + LANG_COMPLETE = 36, + LANG_OFFLINE = 37, + LANG_ON = 38, + LANG_OFF = 39, + LANG_YOU_ARE = 40, + LANG_VISIBLE = 41, + LANG_INVISIBLE = 42, + LANG_DONE = 43, + LANG_YOU = 44, + LANG_UNKNOWN = 45, + LANG_ERROR = 46, + LANG_NON_EXIST_CHARACTER = 47, + LANG_FRIEND_IGNORE_UNKNOWN = 48, + LANG_LEVEL_MINREQUIRED = 49, + LANG_LEVEL_MINREQUIRED_AND_ITEM = 50, + LANG_NPC_TAINER_HELLO = 51, + // Room for more level 0 + + // level 1 chat + LANG_GLOBAL_NOTIFY = 100, + LANG_MAP_POSITION = 101, + LANG_IS_TELEPORTED = 102, + LANG_CANNOT_SUMMON_TO_INST = 103, + LANG_CANNOT_GO_TO_INST_PARTY = 104, + LANG_CANNOT_GO_TO_INST_GM = 105, + LANG_CANNOT_GO_INST_INST = 106, + LANG_CANNOT_SUMMON_INST_INST = 107, + + LANG_SUMMONING = 108, + LANG_SUMMONED_BY = 109, + LANG_TELEPORTING_TO = 110, + LANG_TELEPORTED_TO_BY = 111, + LANG_NO_PLAYER = 112, + LANG_APPEARING_AT = 113, + LANG_APPEARING_TO = 114, + + LANG_BAD_VALUE = 115, + LANG_NO_CHAR_SELECTED = 116, + LANG_NOT_IN_GROUP = 117, + + LANG_YOU_CHANGE_HP = 118, + LANG_YOURS_HP_CHANGED = 119, + LANG_YOU_CHANGE_MANA = 120, + LANG_YOURS_MANA_CHANGED = 121, + LANG_YOU_CHANGE_ENERGY = 122, + LANG_YOURS_ENERGY_CHANGED = 123, + + LANG_CURRENT_ENERGY = 124, //log + LANG_YOU_CHANGE_RAGE = 125, + LANG_YOURS_RAGE_CHANGED = 126, + LANG_YOU_CHANGE_LVL = 127, + LANG_CURRENT_FACTION = 128, + LANG_WRONG_FACTION = 129, + LANG_YOU_CHANGE_FACTION = 130, + LANG_YOU_CHANGE_SPELLFLATID = 131, + LANG_YOURS_SPELLFLATID_CHANGED = 132, + LANG_YOU_GIVE_TAXIS = 133, + LANG_YOU_REMOVE_TAXIS = 134, + LANG_YOURS_TAXIS_ADDED = 135, + LANG_YOURS_TAXIS_REMOVED = 136, + + LANG_YOU_CHANGE_ASPEED = 137, + LANG_YOURS_ASPEED_CHANGED = 138, + LANG_YOU_CHANGE_SPEED = 139, + LANG_YOURS_SPEED_CHANGED = 140, + LANG_YOU_CHANGE_SWIM_SPEED = 141, + LANG_YOURS_SWIM_SPEED_CHANGED = 142, + LANG_YOU_CHANGE_BACK_SPEED = 143, + LANG_YOURS_BACK_SPEED_CHANGED = 144, + LANG_YOU_CHANGE_FLY_SPEED = 145, + LANG_YOURS_FLY_SPEED_CHANGED = 146, + + LANG_YOU_CHANGE_SIZE = 147, + LANG_YOURS_SIZE_CHANGED = 148, + LANG_NO_MOUNT = 149, + LANG_YOU_GIVE_MOUNT = 150, + LANG_MOUNT_GIVED = 151, + + LANG_CURRENT_MONEY = 152, + LANG_YOU_TAKE_ALL_MONEY = 153, + LANG_YOURS_ALL_MONEY_GONE = 154, + LANG_YOU_TAKE_MONEY = 155, + LANG_YOURS_MONEY_TAKEN = 156, + LANG_YOU_GIVE_MONEY = 157, + LANG_YOURS_MONEY_GIVEN = 158, + LANG_YOU_HEAR_SOUND = 159, + + LANG_NEW_MONEY = 160, // Log + + LANG_REMOVE_BIT = 161, + LANG_SET_BIT = 162, + LANG_COMMAND_TELE_TABLEEMPTY = 163, + LANG_COMMAND_TELE_NOTFOUND = 164, + LANG_COMMAND_TELE_PARAMETER = 165, + LANG_COMMAND_TELE_NOREQUEST = 166, + LANG_COMMAND_TELE_NOLOCATION = 167, + LANG_COMMAND_TELE_LOCATION = 168, + + LANG_MAIL_SENT = 169, + LANG_SOUND_NOT_EXIST = 170, + // Room for more level 1 + + // level 2 chat + LANG_NO_SELECTION = 200, + LANG_OBJECT_GUID = 201, + LANG_TOO_LONG_NAME = 202, + LANG_CHARS_ONLY = 203, + LANG_TOO_LONG_SUBNAME = 204, + LANG_NOT_IMPLEMENTED = 205, + + LANG_ITEM_ADDED_TO_LIST = 206, + LANG_ITEM_NOT_FOUND = 207, + LANG_ITEM_DELETED_FROM_LIST = 208, + LANG_ITEM_NOT_IN_LIST = 209, + LANG_ITEM_ALREADY_IN_LIST = 210, + + LANG_RESET_SPELLS_ONLINE = 211, + LANG_RESET_SPELLS_OFFLINE = 212, + LANG_RESET_TALENTS_ONLINE = 213, + LANG_RESET_TALENTS_OFFLINE = 214, + LANG_RESET_SPELLS = 215, + LANG_RESET_TALENTS = 216, + + LANG_RESETALL_UNKNOWN_CASE = 217, + LANG_RESETALL_SPELLS = 218, + LANG_RESETALL_TALENTS = 219, + + LANG_WAYPOINT_NOTFOUND = 220, + LANG_WAYPOINT_NOTFOUNDLAST = 221, + LANG_WAYPOINT_NOTFOUNDSEARCH = 222, + LANG_WAYPOINT_NOTFOUNDDBPROBLEM = 223, + LANG_WAYPOINT_CREATSELECTED = 224, + LANG_WAYPOINT_CREATNOTFOUND = 225, + LANG_WAYPOINT_VP_SELECT = 226, + LANG_WAYPOINT_VP_NOTFOUND = 227, + LANG_WAYPOINT_VP_NOTCREATED = 228, + LANG_WAYPOINT_VP_ALLREMOVED = 229, + LANG_WAYPOINT_NOTCREATED = 230, + LANG_WAYPOINT_NOGUID = 231, + LANG_WAYPOINT_NOWAYPOINTGIVEN = 232, + LANG_WAYPOINT_ARGUMENTREQ = 233, + LANG_WAYPOINT_ADDED = 234, + LANG_WAYPOINT_ADDED_NO = 235, + LANG_WAYPOINT_CHANGED = 236, + LANG_WAYPOINT_CHANGED_NO = 237, + LANG_WAYPOINT_EXPORTED = 238, + LANG_WAYPOINT_NOTHINGTOEXPORT = 239, + LANG_WAYPOINT_IMPORTED = 240, + LANG_WAYPOINT_REMOVED = 241, + LANG_WAYPOINT_NOTREMOVED = 242, + LANG_WAYPOINT_TOOFAR1 = 243, + LANG_WAYPOINT_TOOFAR2 = 244, + LANG_WAYPOINT_TOOFAR3 = 245, + LANG_WAYPOINT_INFO_TITLE = 246, + LANG_WAYPOINT_INFO_WAITTIME = 247, + LANG_WAYPOINT_INFO_MODEL = 248, + LANG_WAYPOINT_INFO_EMOTE = 249, + LANG_WAYPOINT_INFO_SPELL = 250, + LANG_WAYPOINT_INFO_TEXT = 251, + LANG_WAYPOINT_INFO_AISCRIPT = 252, + + LANG_RENAME_PLAYER = 253, + LANG_RENAME_PLAYER_GUID = 254, + + LANG_WAYPOINT_WPCREATNOTFOUND = 255, + LANG_WAYPOINT_NPCNOTFOUND = 256, + + LANG_MOVE_TYPE_SET = 257, + LANG_MOVE_TYPE_SET_NODEL = 258, + LANG_USE_BOL = 259, + LANG_VALUE_SAVED = 260, + LANG_VALUE_SAVED_REJOIN = 261, + + LANG_COMMAND_GOAREATRNOTFOUND = 262, + LANG_INVALID_TARGET_COORD = 263, + LANG_INVALID_ZONE_COORD = 264, + LANG_INVALID_ZONE_MAP = 265, + LANG_COMMAND_TARGETOBJNOTFOUND = 266, + LANG_COMMAND_GOOBJNOTFOUND = 267, + LANG_COMMAND_GOCREATNOTFOUND = 268, + LANG_COMMAND_GOCREATMULTIPLE = 269, + LANG_COMMAND_DELCREATMESSAGE = 270, + LANG_COMMAND_CREATUREMOVED = 271, + LANG_COMMAND_CREATUREATSAMEMAP = 272, + LANG_COMMAND_OBJNOTFOUND = 273, + LANG_COMMAND_DELOBJREFERCREATURE = 274, + LANG_COMMAND_DELOBJMESSAGE = 275, + LANG_COMMAND_TURNOBJMESSAGE = 276, + LANG_COMMAND_MOVEOBJMESSAGE = 277, + LANG_COMMAND_VENDORSELECTION = 278, + LANG_COMMAND_NEEDITEMSEND = 279, + LANG_COMMAND_ADDVENDORITEMITEMS = 280, + LANG_COMMAND_KICKSELF = 281, + LANG_COMMAND_KICKMESSAGE = 282, + LANG_COMMAND_KICKNOTFOUNDPLAYER = 283, + LANG_COMMAND_WHISPERACCEPTING = 284, + LANG_COMMAND_WHISPERON = 285, + LANG_COMMAND_WHISPEROFF = 286, + LANG_COMMAND_CREATGUIDNOTFOUND = 287, + LANG_COMMAND_TICKETCOUNT = 288, + LANG_COMMAND_TICKETNEW = 289, + LANG_COMMAND_TICKETVIEW = 290, + LANG_COMMAND_TICKETON = 291, + LANG_COMMAND_TICKETOFF = 292, + LANG_COMMAND_TICKENOTEXIST = 293, + LANG_COMMAND_ALLTICKETDELETED = 294, + LANG_COMMAND_TICKETPLAYERDEL = 295, + LANG_COMMAND_TICKETDEL = 296, + LANG_COMMAND_SPAWNDIST = 297, + LANG_COMMAND_SPAWNTIME = 298, + LANG_COMMAND_MODIFY_HONOR = 299, + + LANG_YOUR_CHAT_DISABLED = 300, + LANG_YOU_DISABLE_CHAT = 301, + LANG_CHAT_ALREADY_ENABLED = 302, + LANG_YOUR_CHAT_ENABLED = 303, + LANG_YOU_ENABLE_CHAT = 304, + + LANG_COMMAND_MODIFY_REP = 305, + LANG_COMMAND_MODIFY_ARENA = 306, + LANG_COMMAND_FACTION_NOTFOUND = 307, + LANG_COMMAND_FACTION_UNKNOWN = 308, + LANG_COMMAND_FACTION_INVPARAM = 309, + LANG_COMMAND_FACTION_DELTA = 310, + LANG_FACTION_LIST = 311, + LANG_FACTION_VISIBLE = 312, + LANG_FACTION_ATWAR = 313, + LANG_FACTION_PEACE_FORCED = 314, + LANG_FACTION_HIDDEN = 315, + LANG_FACTION_INVISIBLE_FORCED = 316, + LANG_FACTION_INACTIVE = 317, + LANG_REP_HATED = 318, + LANG_REP_HOSTILE = 319, + LANG_REP_UNFRIENDLY = 320, + LANG_REP_NEUTRAL = 321, + LANG_REP_FRIENDLY = 322, + LANG_REP_HONORED = 323, + LANG_REP_REVERED = 324, + LANG_REP_EXALTED = 325, + LANG_COMMAND_FACTION_NOREP_ERROR = 326, + LANG_FACTION_NOREPUTATION = 327, + + // Room for more level 2 + + // level 3 chat + LANG_SCRIPTS_RELOADED = 400, + LANG_YOU_CHANGE_SECURITY = 401, + LANG_YOURS_SECURITY_CHANGED = 402, + LANG_YOURS_SECURITY_IS_LOW = 403, + LANG_CREATURE_MOVE_DISABLED = 404, + LANG_CREATURE_MOVE_ENABLED = 405, + LANG_NO_WEATHER = 406, + LANG_WEATHER_DISABLED = 407, + + LANG_BAN_YOUBANNED = 408, + LANG_BAN_YOUPERMBANNED = 409, + LANG_BAN_NOTFOUND = 410, + + LANG_UNBAN_UNBANNED = 411, + LANG_UNBAN_ERROR = 412, + + LANG_BANINFO_NOACCOUNT = 413, + LANG_BANINFO_NOCHARACTER = 414, + LANG_BANINFO_NOIP = 415, + LANG_BANINFO_NOACCOUNTBAN = 416, + LANG_BANINFO_BANHISTORY = 417, + LANG_BANINFO_HISTORYENTRY = 418, + LANG_BANINFO_INFINITE = 419, + LANG_BANINFO_NEVER = 420, + LANG_BANINFO_YES = 421, + LANG_BANINFO_NO = 422, + LANG_BANINFO_IPENTRY = 423, + + LANG_BANLIST_NOIP = 424, + LANG_BANLIST_NOACCOUNT = 425, + LANG_BANLIST_NOCHARACTER = 426, + LANG_BANLIST_MATCHINGIP = 427, + LANG_BANLIST_MATCHINGACCOUNT = 428, + + LANG_COMMAND_LEARN_MANY_SPELLS = 429, + LANG_COMMAND_LEARN_CLASS_SPELLS = 430, + LANG_COMMAND_LEARN_CLASS_TALENTS = 431, + LANG_COMMAND_LEARN_ALL_LANG = 432, + LANG_COMMAND_LEARN_ALL_CRAFT = 433, + LANG_COMMAND_COULDNOTFIND = 434, + LANG_COMMAND_ITEMIDINVALID = 435, + LANG_COMMAND_NOITEMFOUND = 436, + LANG_COMMAND_LISTOBJINVALIDID = 437, + LANG_COMMAND_LISTITEMMESSAGE = 438, + LANG_COMMAND_LISTOBJMESSAGE = 439, + LANG_COMMAND_INVALIDCREATUREID = 440, + LANG_COMMAND_LISTCREATUREMESSAGE = 441, + LANG_COMMAND_NOAREAFOUND = 442, + LANG_COMMAND_NOITEMSETFOUND = 443, + LANG_COMMAND_NOSKILLFOUND = 444, + LANG_COMMAND_NOSPELLFOUND = 445, + LANG_COMMAND_NOQUESTFOUND = 446, + LANG_COMMAND_NOCREATUREFOUND = 447, + LANG_COMMAND_NOGAMEOBJECTFOUND = 448, + LANG_COMMAND_GRAVEYARDNOEXIST = 449, + LANG_COMMAND_GRAVEYARDALRLINKED = 450, + LANG_COMMAND_GRAVEYARDLINKED = 451, + LANG_COMMAND_GRAVEYARDWRONGZONE = 452, + LANG_COMMAND_GRAVEYARDWRONGTEAM = 453, + LANG_COMMAND_GRAVEYARDERROR = 454, + LANG_COMMAND_GRAVEYARD_NOTEAM = 455, + LANG_COMMAND_GRAVEYARD_ANY = 456, + LANG_COMMAND_GRAVEYARD_ALLIANCE = 457, + LANG_COMMAND_GRAVEYARD_HORDE = 458, + LANG_COMMAND_GRAVEYARDNEAREST = 459, + LANG_COMMAND_ZONENOGRAVEYARDS = 460, + LANG_COMMAND_ZONENOGRAFACTION = 461, + LANG_COMMAND_TP_ALREADYEXIST = 462, + LANG_COMMAND_TP_ADDED = 463, + LANG_COMMAND_TP_ADDEDERR = 464, + LANG_COMMAND_TP_DELETED = 465, + LANG_COMMAND_TP_DELETEERR = 466, + + LANG_COMMAND_TARGET_LISTAURAS = 467, + LANG_COMMAND_TARGET_AURADETAIL = 468, + LANG_COMMAND_TARGET_LISTAURATYPE = 469, + LANG_COMMAND_TARGET_AURASIMPLE = 470, + + LANG_COMMAND_QUEST_NOTFOUND = 471, + LANG_COMMAND_QUEST_STARTFROMITEM = 472, + LANG_COMMAND_QUEST_REMOVED = 473, + LANG_COMMAND_QUEST_REWARDED = 474, + LANG_COMMAND_QUEST_COMPLETE = 475, + LANG_COMMAND_QUEST_ACTIVE = 476, + + LANG_COMMAND_FLYMODE_STATUS = 477, + + LANG_COMMAND_OPCODESENT = 478, + + LANG_COMMAND_IMPORT_SUCCESS = 479, + LANG_COMMAND_IMPORT_FAILED = 480, + LANG_COMMAND_EXPORT_SUCCESS = 481, + LANG_COMMAND_EXPORT_FAILED = 482, + + LANG_COMMAND_SPELL_BROKEN = 483, + + LANG_SET_SKILL = 484, + LANG_SET_SKILL_ERROR = 485, + + LANG_INVALID_SKILL_ID = 486, + LANG_LEARNING_GM_SKILLS = 487, + LANG_YOU_KNOWN_SPELL = 488, + LANG_TARGET_KNOWN_SPELL = 489, + LANG_UNKNOWN_SPELL = 490, + LANG_FORGET_SPELL = 491, + LANG_REMOVEALL_COOLDOWN = 492, + LANG_REMOVE_COOLDOWN = 493, + + LANG_ADDITEM = 494, //log + LANG_ADDITEMSET = 495, //log + LANG_REMOVEITEM = 496, + LANG_ITEM_CANNOT_CREATE = 497, + LANG_INSERT_GUILD_NAME = 498, + LANG_PLAYER_NOT_FOUND = 499, + LANG_PLAYER_IN_GUILD = 500, + LANG_GUILD_NOT_CREATED = 501, + LANG_NO_ITEMS_FROM_ITEMSET_FOUND = 502, + + LANG_DISTANCE = 503, + + LANG_ITEM_SLOT = 504, + LANG_ITEM_SLOT_NOT_EXIST = 505, + LANG_ITEM_ADDED_TO_SLOT = 506, + LANG_ITEM_SAVE_FAILED = 507, + LANG_ITEMLIST_SLOT = 508, + LANG_ITEMLIST_MAIL = 509, + LANG_ITEMLIST_AUCTION = 510, + + LANG_WRONG_LINK_TYPE = 511, + LANG_ITEM_LIST = 512, + LANG_QUEST_LIST = 513, + LANG_CREATURE_ENTRY_LIST = 514, + LANG_CREATURE_LIST = 515, + LANG_GO_ENTRY_LIST = 516, + LANG_GO_LIST = 517, + LANG_ITEMSET_LIST = 518, + LANG_TELE_LIST = 519, + LANG_SPELL_LIST = 520, + LANG_SKILL_LIST = 521, + + LANG_GAMEOBJECT_NOT_EXIST = 522, + + LANG_GAMEOBJECT_CURRENT = 523, //log + LANG_GAMEOBJECT_DETAIL = 524, + LANG_GAMEOBJECT_ADD = 525, + + LANG_MOVEGENS_LIST = 526, + LANG_MOVEGENS_IDLE = 527, + LANG_MOVEGENS_RANDOM = 528, + LANG_MOVEGENS_WAYPOINT = 529, + LANG_MOVEGENS_ANIMAL_RANDOM = 530, + LANG_MOVEGENS_CONFUSED = 531, + LANG_MOVEGENS_TARGETED_PLAYER = 532, + LANG_MOVEGENS_TARGETED_CREATURE = 533, + LANG_MOVEGENS_TARGETED_NULL = 534, + LANG_MOVEGENS_HOME_CREATURE = 535, + LANG_MOVEGENS_HOME_PLAYER = 536, + LANG_MOVEGENS_FLIGHT = 537, + LANG_MOVEGENS_UNKNOWN = 538, + + LANG_NPCINFO_CHAR = 539, + LANG_NPCINFO_LEVEL = 540, + LANG_NPCINFO_HEALTH = 541, + LANG_NPCINFO_FLAGS = 542, + LANG_NPCINFO_LOOT = 543, + LANG_NPCINFO_POSITION = 544, + LANG_NPCINFO_VENDOR = 545, + LANG_NPCINFO_TRAINER = 546, + LANG_NPCINFO_DUNGEON_ID = 547, + + LANG_PINFO_ACCOUNT = 548, + LANG_PINFO_LEVEL = 549, + LANG_PINFO_NO_REP = 550, + + LANG_YOU_SET_EXPLORE_ALL = 551, + LANG_YOU_SET_EXPLORE_NOTHING = 552, + LANG_YOURS_EXPLORE_SET_ALL = 553, + LANG_YOURS_EXPLORE_SET_NOTHING = 554, + + LANG_HOVER_ENABLED = 555, + LANG_HOVER_DISABLED = 556, + LANG_YOURS_LEVEL_UP = 557, + LANG_YOURS_LEVEL_DOWN = 558, + LANG_YOURS_LEVEL_PROGRESS_RESET = 559, + LANG_EXPLORE_AREA = 560, + LANG_UNEXPLORE_AREA = 561, + + LANG_UPDATE = 562, + LANG_UPDATE_CHANGE = 563, + LANG_TOO_BIG_INDEX = 564, + LANG_SET_UINT = 565, //log + LANG_SET_UINT_FIELD = 566, + LANG_SET_FLOAT = 567, //log + LANG_SET_FLOAT_FIELD = 568, + LANG_GET_UINT = 569, //log + LANG_GET_UINT_FIELD = 570, + LANG_GET_FLOAT = 571, //log + LANG_GET_FLOAT_FIELD = 572, + LANG_SET_32BIT = 573, //log + LANG_SET_32BIT_FIELD = 574, + LANG_CHANGE_32BIT = 575, //log + LANG_CHANGE_32BIT_FIELD = 576, + + LANG_INVISIBLE_INVISIBLE = 577, + LANG_INVISIBLE_VISIBLE = 578, + LANG_SELECTED_TARGET_NOT_HAVE_VICTIM = 579, + + LANG_COMMAND_LEARN_ALL_DEFAULT_AND_QUEST = 580, + LANG_COMMAND_NEAROBJMESSAGE = 581, + LANG_COMMAND_RAWPAWNTIMES = 582, + + LANG_EVENT_ENTRY_LIST = 583, + LANG_NOEVENTFOUND = 584, + LANG_EVENT_NOT_EXIST = 585, + LANG_EVENT_INFO = 586, + LANG_EVENT_ALREADY_ACTIVE = 587, + LANG_EVENT_NOT_ACTIVE = 588, + + LANG_MOVEGENS_POINT = 589, + LANG_MOVEGENS_FEAR = 590, + LANG_MOVEGENS_DISTRACT = 591, + + LANG_COMMAND_LEARN_ALL_RECIPES = 592, + + // Battleground + LANG_BG_A_WINS = 600, + LANG_BG_H_WINS = 601, + LANG_BG_WS_ONE_MINUTE = 602, + LANG_BG_WS_HALF_MINUTE = 603, + LANG_BG_WS_BEGIN = 604, + + LANG_BG_WS_CAPTURED_HF = 605, + LANG_BG_WS_CAPTURED_AF = 606, + LANG_BG_WS_DROPPED_HF = 607, + LANG_BG_WS_DROPPED_AF = 608, + LANG_BG_WS_RETURNED_AF = 609, + LANG_BG_WS_RETURNED_HF = 610, + LANG_BG_WS_PICKEDUP_HF = 611, + LANG_BG_WS_PICKEDUP_AF = 612, + LANG_BG_WS_F_PLACED = 613, + LANG_BG_WS_ALLIANCE_FLAG_RESPAWNED = 614, + LANG_BG_WS_HORDE_FLAG_RESPAWNED = 615, + + LANG_BG_EY_ONE_MINUTE = 636, + LANG_BG_EY_HALF_MINUTE = 637, + LANG_BG_EY_BEGIN = 638, + + LANG_BG_AB_ALLY = 650, + LANG_BG_AB_HORDE = 651, + LANG_BG_AB_NODE_STABLES = 652, + LANG_BG_AB_NODE_BLACKSMITH = 653, + LANG_BG_AB_NODE_FARM = 654, + LANG_BG_AB_NODE_LUMBER_MILL = 655, + LANG_BG_AB_NODE_GOLD_MINE = 656, + LANG_BG_AB_NODE_TAKEN = 657, + LANG_BG_AB_NODE_DEFENDED = 658, + LANG_BG_AB_NODE_ASSAULTED = 659, + LANG_BG_AB_NODE_CLAIMED = 660, + LANG_BG_AB_ONEMINTOSTART = 661, + LANG_BG_AB_HALFMINTOSTART = 662, + LANG_BG_AB_STARTED = 663, + LANG_BG_AB_A_NEAR_VICTORY = 664, + LANG_BG_AB_H_NEAR_VICTORY = 665, + LANG_BG_MARK_BY_MAIL = 666, + + LANG_BG_EY_HAS_TAKEN_A_M_TOWER = 667, + LANG_BG_EY_HAS_TAKEN_H_M_TOWER = 668, + LANG_BG_EY_HAS_TAKEN_A_D_RUINS = 669, + LANG_BG_EY_HAS_TAKEN_H_D_RUINS = 670, + LANG_BG_EY_HAS_TAKEN_A_B_TOWER = 671, + LANG_BG_EY_HAS_TAKEN_H_B_TOWER = 672, + LANG_BG_EY_HAS_TAKEN_A_F_RUINS = 673, + LANG_BG_EY_HAS_TAKEN_H_F_RUINS = 674, + LANG_BG_EY_HAS_LOST_A_M_TOWER = 675, + LANG_BG_EY_HAS_LOST_H_M_TOWER = 676, + LANG_BG_EY_HAS_LOST_A_D_RUINS = 677, + LANG_BG_EY_HAS_LOST_H_D_RUINS = 678, + LANG_BG_EY_HAS_LOST_A_B_TOWER = 679, + LANG_BG_EY_HAS_LOST_H_B_TOWER = 680, + LANG_BG_EY_HAS_LOST_A_F_RUINS = 681, + LANG_BG_EY_HAS_LOST_H_F_RUINS = 682, + LANG_BG_EY_HAS_TAKEN_FLAG = 683, + LANG_BG_EY_CAPTURED_FLAG_A = 684, + LANG_BG_EY_CAPTURED_FLAG_H = 685, + LANG_BG_EY_DROPPED_FLAG = 686, + LANG_BG_EY_RESETED_FLAG = 687, + + LANG_ARENA_ONE_TOOLOW = 700, + LANG_ARENA_ONE_MINUTE = 701, + LANG_ARENA_THIRTY_SECONDS = 702, + LANG_ARENA_FIFTEEN_SECONDS = 703, + LANG_ARENA_BEGUN = 704, + + LANG_WAIT_BEFORE_SPEAKING = 705, + LANG_NOT_EQUIPPED_ITEM = 706, + LANG_PLAYER_DND = 707, + LANG_PLAYER_AFK = 708, + LANG_PLAYER_DND_DEFAULT = 709, + LANG_PLAYER_AFK_DEFAULT = 710, + + LANG_BG_QUEUE_ANNOUNCE_SELF = 711, + LANG_BG_QUEUE_ANNOUNCE_WORLD = 712, +}; +#endif + +/* NOT USED VALUES +// alliance ranks +#define LANG_ALI_PRIVATE "Private " +#define LANG_ALI_CORPORAL "Corporal " +#define LANG_ALI_SERGEANT "Sergeant " +#define LANG_ALI_MASTER_SERGEANT "Master Sergeant " +#define LANG_ALI_SERGEANT_MAJOR "Sergeant Major " +#define LANG_ALI_KNIGHT "Knight " +#define LANG_ALI_KNIGHT_LIEUTENANT "Knight-Lieutenant " +#define LANG_ALI_KNIGHT_CAPTAIN "Knight-Captain " +#define LANG_ALI_KNIGHT_CHAMPION "Knight-Champion " +#define LANG_ALI_LIEUTENANT_COMMANDER "Lieutenant Commander " +#define LANG_ALI_COMMANDER "Commander " +#define LANG_ALI_MARSHAL "Marshal " +#define LANG_ALI_FIELD_MARSHAL "Field Marshal " +#define LANG_ALI_GRAND_MARSHAL "Grand Marshal " +#define LANG_ALI_GAME_MASTER "Game Master " + +// horde ranks +#define LANG_HRD_SCOUT "Scout " +#define LANG_HRD_GRUNT "Grunt " +#define LANG_HRD_SERGEANT "Sergeant " +#define LANG_HRD_SENIOR_SERGEANT "Senior Sergeant " +#define LANG_HRD_FIRST_SERGEANT "First Sergeant " +#define LANG_HRD_STONE_GUARD "Stone Guard " +#define LANG_HRD_BLOOD_GUARD "Blood Guard " +#define LANG_HRD_LEGIONNARE "Legionnaire " +#define LANG_HRD_CENTURION "Centurion " +#define LANG_HRD_CHAMPION "Champion " +#define LANG_HRD_LIEUTENANT_GENERAL "Lieutenant General " +#define LANG_HRD_GENERAL "General " +#define LANG_HRD_WARLORD "Warlord " +#define LANG_HRD_HIGH_WARLORD "High Warlord " +#define LANG_HRD_GAME_MASTER "Game Master " + +#define LANG_NO_RANK "No rank " +#define LANG_RANK "%s (Rank %u)" +#define LANG_HONOR_TODAY "Today: [Honorable kills: |c0000ff00%u|r] [Dishonorable kills: |c00ff0000%u|r]" +#define LANG_HONOR_YESTERDAY "Yesterday: [Kills: |c0000ff00%u|r] [Honor: %u]" +#define LANG_HONOR_THIS_WEEK "This week: [Kills: |c0000ff00%u|r] [Honor: %u]" +#define LANG_HONOR_LAST_WEEK "Last week: [Kills: |c0000ff00%u|r] [Honor: %u] [Standing: %u]" +#define LANG_HONOR_LIFE "Lifetime: [Honorable kills: |c0000ff00%u|r] [Dishonorable kills: |c00ff0000%u|r] [Highest rank %u: %s]" + +// level 2 +#define LANG_ADD_OBJ "AddObject at Chat.cpp" //log +#define LANG_DEMORPHED "Demorphed %s" //log + +// level 3 +#define LANG_SPAWNING_SPIRIT_HEAL "Spawning spirit healers\n" +#define LANG_NO_SPIRIT_HEAL_DB "No spirit healers in database, exiting." + +#define LANG_ADD_OBJ_LV3 "AddObject at Level3.cpp line 1176" + +*/ diff --git a/src/game/Level0.cpp b/src/game/Level0.cpp new file mode 100644 index 00000000000..5130b158360 --- /dev/null +++ b/src/game/Level0.cpp @@ -0,0 +1,233 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "World.h" +#include "Player.h" +#include "Opcodes.h" +#include "Chat.h" +#include "MapManager.h" +#include "ObjectAccessor.h" +#include "Language.h" +#include "AccountMgr.h" +#include "SystemConfig.h" +#include "Util.h" + +bool ChatHandler::HandleHelpCommand(const char* args) +{ + if(!*args) + return false; + + char* cmd = strtok((char*)args, " "); + if(!cmd) + return false; + + if(!ShowHelpForCommand(getCommandTable(), cmd)) + SendSysMessage(LANG_NO_HELP_CMD); + + return true; +} + +bool ChatHandler::HandleCommandsCommand(const char* args) +{ + ShowHelpForCommand(getCommandTable(), ""); + return true; +} + +bool ChatHandler::HandleAcctCommand(const char* /*args*/) +{ + uint32 gmlevel = m_session->GetSecurity(); + PSendSysMessage(LANG_ACCOUNT_LEVEL, gmlevel); + return true; +} + +bool ChatHandler::HandleStartCommand(const char* /*args*/) +{ + Player *chr = m_session->GetPlayer(); + + if(chr->isInFlight()) + { + SendSysMessage(LANG_YOU_IN_FLIGHT); + SetSentErrorMessage(true); + return false; + } + + if(chr->isInCombat()) + { + SendSysMessage(LANG_YOU_IN_COMBAT); + SetSentErrorMessage(true); + return false; + } + + // cast spell Stuck + chr->CastSpell(chr,7355,false); + return true; +} + +bool ChatHandler::HandleInfoCommand(const char* /*args*/) +{ + uint32 activeClientsNum = sWorld.GetActiveSessionCount(); + uint32 queuedClientsNum = sWorld.GetQueuedSessionCount(); + uint32 maxActiveClientsNum = sWorld.GetMaxActiveSessionCount(); + uint32 maxQueuedClientsNum = sWorld.GetMaxQueuedSessionCount(); + std::string str = secsToTimeString(sWorld.GetUptime()); + + PSendSysMessage(_FULLVERSION); + PSendSysMessage(LANG_CONNECTED_USERS, activeClientsNum, maxActiveClientsNum, queuedClientsNum, maxQueuedClientsNum); + PSendSysMessage(LANG_UPTIME, str.c_str()); + + return true; +} + +bool ChatHandler::HandleDismountCommand(const char* /*args*/) +{ + //If player is not mounted, so go out :) + if (!m_session->GetPlayer( )->IsMounted()) + { + SendSysMessage(LANG_CHAR_NON_MOUNTED); + SetSentErrorMessage(true); + return false; + } + + if(m_session->GetPlayer( )->isInFlight()) + { + SendSysMessage(LANG_YOU_IN_FLIGHT); + SetSentErrorMessage(true); + return false; + } + + m_session->GetPlayer()->Unmount(); + m_session->GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); + return true; +} + +bool ChatHandler::HandleSaveCommand(const char* /*args*/) +{ + Player *player=m_session->GetPlayer(); + + // save GM account without delay and output message (testing, etc) + if(m_session->GetSecurity()) + { + player->SaveToDB(); + SendSysMessage(LANG_PLAYER_SAVED); + return true; + } + + // save or plan save after 20 sec (logout delay) if current next save time more this value and _not_ output any messages to prevent cheat planning + uint32 save_interval = sWorld.getConfig(CONFIG_INTERVAL_SAVE); + if(save_interval==0 || save_interval > 20*1000 && player->GetSaveTimer() <= save_interval - 20*1000) + player->SaveToDB(); + + return true; +} + +bool ChatHandler::HandleGMListCommand(const char* /*args*/) +{ + bool first = true; + + HashMapHolder::MapType &m = HashMapHolder::GetContainer(); + HashMapHolder::MapType::iterator itr = m.begin(); + for(; itr != m.end(); ++itr) + { + if( itr->second->GetSession()->GetSecurity() && (itr->second->isGameMaster() || sWorld.getConfig(CONFIG_GM_IN_GM_LIST) ) && + itr->second->IsVisibleGloballyFor(m_session->GetPlayer()) ) + { + if(first) + { + SendSysMessage(LANG_GMS_ON_SRV); + first = false; + } + + SendSysMessage(itr->second->GetName()); + } + } + + if(first) + SendSysMessage(LANG_GMS_NOT_LOGGED); + + return true; +} + +bool ChatHandler::HandlePasswordCommand(const char* args) +{ + if(!*args) + return false; + + char *old_pass = strtok ((char*)args, " "); + char *new_pass = strtok (NULL, " "); + char *new_pass_c = strtok (NULL, " "); + + if( !old_pass || !new_pass || !new_pass_c ) + return false; + + std::string password_old = old_pass; + std::string password_new = new_pass; + std::string password_new_c = new_pass_c; + + if(!accmgr.CheckPassword(m_session->GetAccountId(), password_old) || password_new != password_new_c) + { + SendSysMessage(LANG_COMMAND_WRONGOLDPASSWORD); + SetSentErrorMessage(true); + return false; + } + + AccountOpResult result = accmgr.ChangePassword(m_session->GetAccountId(), password_new); + + switch(result) + { + case AOR_OK: + SendSysMessage(LANG_COMMAND_PASSWORD); + break; + default: + SendSysMessage(LANG_COMMAND_NOTCHANGEPASSWORD); + SetSentErrorMessage(true); + return false; + } + + return true; +} + +bool ChatHandler::HandleLockAccountCommand(const char* args) +{ + if (!*args) + { + SendSysMessage(LANG_USE_BOL); + return true; + } + + std::string argstr = (char*)args; + if (argstr == "on") + { + loginDatabase.PExecute( "UPDATE account SET locked = '1' WHERE id = '%d'",m_session->GetAccountId()); + PSendSysMessage(LANG_COMMAND_ACCLOCKLOCKED); + return true; + } + + if (argstr == "off") + { + loginDatabase.PExecute( "UPDATE account SET locked = '0' WHERE id = '%d'",m_session->GetAccountId()); + PSendSysMessage(LANG_COMMAND_ACCLOCKUNLOCKED); + return true; + } + + SendSysMessage(LANG_USE_BOL); + return true; +} diff --git a/src/game/Level1.cpp b/src/game/Level1.cpp new file mode 100644 index 00000000000..21c1eec9f16 --- /dev/null +++ b/src/game/Level1.cpp @@ -0,0 +1,2351 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "World.h" +#include "ObjectMgr.h" +#include "Player.h" +#include "Opcodes.h" +#include "Chat.h" +#include "Log.h" +#include "MapManager.h" +#include "ObjectAccessor.h" +#include "Language.h" +#include "CellImpl.h" +#include "InstanceSaveMgr.h" +#include "Util.h" +#ifdef _DEBUG_VMAPS +#include "VMapFactory.h" +#endif + +bool ChatHandler::HandleSayCommand(const char* args) +{ + if(!*args) + return false; + + Creature* pCreature = getSelectedCreature(); + if(!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + pCreature->Say(args, LANG_UNIVERSAL, 0); + + return true; +} + +bool ChatHandler::HandleYellCommand(const char* args) +{ + if(!*args) + return false; + + Creature* pCreature = getSelectedCreature(); + if(!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + pCreature->Yell(args, LANG_UNIVERSAL, 0); + + return true; +} + +//show text emote by creature in chat +bool ChatHandler::HandleTextEmoteCommand(const char* args) +{ + if(!*args) + return false; + + Creature* pCreature = getSelectedCreature(); + + if(!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + pCreature->TextEmote(args, 0); + + return true; +} + +// make npc whisper to player +bool ChatHandler::HandleNpcWhisperCommand(const char* args) +{ + if(!*args) + return false; + + char* receiver_str = strtok((char*)args, " "); + char* text = strtok(NULL, ""); + + uint64 guid = m_session->GetPlayer()->GetSelection(); + Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid); + + if(!pCreature || !receiver_str || !text) + { + return false; + } + + uint64 receiver_guid= atol(receiver_str); + + pCreature->Whisper(text,receiver_guid); + + return true; +} + +// global announce +bool ChatHandler::HandleAnnounceCommand(const char* args) +{ + if(!*args) + return false; + + sWorld.SendWorldText(LANG_SYSTEMMESSAGE,args); + return true; +} + +//notification player at the screen +bool ChatHandler::HandleNotifyCommand(const char* args) +{ + if(!*args) + return false; + + std::string str = GetMangosString(LANG_GLOBAL_NOTIFY); + str += args; + + WorldPacket data(SMSG_NOTIFICATION, (str.size()+1)); + data << str; + sWorld.SendGlobalMessage(&data); + + return true; +} + +//Enable\Dissable GM Mode +bool ChatHandler::HandleGMmodeCommand(const char* args) +{ + if(!*args) + { + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; + } + + std::string argstr = (char*)args; + + if (argstr == "on") + { + m_session->GetPlayer()->SetGameMaster(true); + m_session->SendNotification("GM mode is ON"); + #ifdef _DEBUG_VMAPS + VMAP::IVMapManager *vMapManager = VMAP::VMapFactory::createOrGetVMapManager(); + vMapManager->processCommand("stoplog"); + #endif + return true; + } + + if (argstr == "off") + { + m_session->GetPlayer()->SetGameMaster(false); + m_session->SendNotification("GM mode is OFF"); + #ifdef _DEBUG_VMAPS + VMAP::IVMapManager *vMapManager = VMAP::VMapFactory::createOrGetVMapManager(); + vMapManager->processCommand("startlog"); + #endif + return true; + } + + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; +} + +//Enable\Dissable Invisible mode +bool ChatHandler::HandleVisibleCommand(const char* args) +{ + if (!*args) + { + PSendSysMessage(LANG_YOU_ARE, m_session->GetPlayer()->isGMVisible() ? GetMangosString(LANG_VISIBLE) : GetMangosString(LANG_INVISIBLE)); + return true; + } + + std::string argstr = (char*)args; + + if (argstr == "on") + { + m_session->GetPlayer()->SetGMVisible(true); + m_session->SendNotification(GetMangosString(LANG_INVISIBLE_VISIBLE)); + return true; + } + + if (argstr == "off") + { + m_session->SendNotification(GetMangosString(LANG_INVISIBLE_INVISIBLE)); + m_session->GetPlayer()->SetGMVisible(false); + return true; + } + + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; +} + +bool ChatHandler::HandleGPSCommand(const char* args) +{ + WorldObject *obj = NULL; + if (*args) + { + std::string name = args; + if(normalizePlayerName(name)) + obj = objmgr.GetPlayer(name.c_str()); + + if(!obj) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + } + else + { + obj = getSelectedUnit(); + + if(!obj) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + } + CellPair cell_val = MaNGOS::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()); + Cell cell(cell_val); + + uint32 zone_id = obj->GetZoneId(); + uint32 area_id = obj->GetAreaId(); + + MapEntry const* mapEntry = sMapStore.LookupEntry(obj->GetMapId()); + AreaTableEntry const* zoneEntry = GetAreaEntryByAreaID(zone_id); + AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(area_id); + + float zone_x = obj->GetPositionX(); + float zone_y = obj->GetPositionY(); + + Map2ZoneCoordinates(zone_x,zone_y,zone_id); + + Map const *map = MapManager::Instance().GetMap(obj->GetMapId(), obj); + float ground_z = map->GetHeight(obj->GetPositionX(), obj->GetPositionY(), MAX_HEIGHT); + float floor_z = map->GetHeight(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ()); + + GridPair p = MaNGOS::ComputeGridPair(obj->GetPositionX(), obj->GetPositionY()); + + int gx=63-p.x_coord; + int gy=63-p.y_coord; + + uint32 have_map = Map::ExistMap(obj->GetMapId(),gx,gy) ? 1 : 0; + uint32 have_vmap = Map::ExistVMap(obj->GetMapId(),gx,gy) ? 1 : 0; + + PSendSysMessage(LANG_MAP_POSITION, + obj->GetMapId(), (mapEntry ? mapEntry->name[m_session->GetSessionDbcLocale()] : "" ), + zone_id, (zoneEntry ? zoneEntry->area_name[m_session->GetSessionDbcLocale()] : "" ), + area_id, (areaEntry ? areaEntry->area_name[m_session->GetSessionDbcLocale()] : "" ), + obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), obj->GetOrientation(), + cell.GridX(), cell.GridY(), cell.CellX(), cell.CellY(), obj->GetInstanceId(), + zone_x, zone_y, ground_z, floor_z, have_map, have_vmap ); + + sLog.outDebug("Player %s GPS call for %s '%s' (%s: %u):", + m_session->GetPlayer()->GetName(), + (obj->GetTypeId() == TYPEID_PLAYER ? "player" : "creature"), obj->GetName(), + (obj->GetTypeId() == TYPEID_PLAYER ? "GUID" : "Entry"), (obj->GetTypeId() == TYPEID_PLAYER ? obj->GetGUIDLow(): obj->GetEntry()) ); + sLog.outDebug(GetMangosString(LANG_MAP_POSITION), + obj->GetMapId(), (mapEntry ? mapEntry->name[sWorld.GetDefaultDbcLocale()] : "" ), + zone_id, (zoneEntry ? zoneEntry->area_name[sWorld.GetDefaultDbcLocale()] : "" ), + area_id, (areaEntry ? areaEntry->area_name[sWorld.GetDefaultDbcLocale()] : "" ), + obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), obj->GetOrientation(), + cell.GridX(), cell.GridY(), cell.CellX(), cell.CellY(), obj->GetInstanceId(), + zone_x, zone_y, ground_z, floor_z, have_map, have_vmap ); + + return true; +} + +//Summon Player +bool ChatHandler::HandleNamegoCommand(const char* args) +{ + if(!*args) + return false; + + std::string name = args; + + if(!normalizePlayerName(name)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + Player *chr = objmgr.GetPlayer(name.c_str()); + if (chr) + { + if(chr->IsBeingTeleported()==true) + { + PSendSysMessage(LANG_IS_TELEPORTED, chr->GetName()); + SetSentErrorMessage(true); + return false; + } + + Map* pMap = MapManager::Instance().GetMap(m_session->GetPlayer()->GetMapId(),m_session->GetPlayer()); + + if(pMap->Instanceable()) + { + Map* cMap = MapManager::Instance().GetMap(chr->GetMapId(),chr); + if( cMap->Instanceable() && cMap->GetInstanceId() != pMap->GetInstanceId() ) + { + // cannot summon from instance to instance + PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST,chr->GetName()); + SetSentErrorMessage(true); + return false; + } + + // we are in instance, and can summon only player in our group with us as lead + if ( !m_session->GetPlayer()->GetGroup() || !chr->GetGroup() || + (chr->GetGroup()->GetLeaderGUID() != m_session->GetPlayer()->GetGUID()) || + (m_session->GetPlayer()->GetGroup()->GetLeaderGUID() != m_session->GetPlayer()->GetGUID()) ) + // the last check is a bit excessive, but let it be, just in case + { + PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST,chr->GetName()); + SetSentErrorMessage(true); + return false; + } + } + + PSendSysMessage(LANG_SUMMONING, chr->GetName(),""); + + if (m_session->GetPlayer()->IsVisibleGloballyFor(chr)) + ChatHandler(chr).PSendSysMessage(LANG_SUMMONED_BY, m_session->GetPlayer()->GetName()); + + // stop flight if need + if(chr->isInFlight()) + { + chr->GetMotionMaster()->MovementExpired(); + chr->m_taxi.ClearTaxiDestinations(); + } + // save only in non-flight case + else + chr->SaveRecallPosition(); + + // before GM + float x,y,z; + m_session->GetPlayer()->GetClosePoint(x,y,z,chr->GetObjectSize()); + chr->TeleportTo(m_session->GetPlayer()->GetMapId(),x,y,z,chr->GetOrientation()); + } + else if (uint64 guid = objmgr.GetPlayerGUIDByName(name)) + { + PSendSysMessage(LANG_SUMMONING, name.c_str(),GetMangosString(LANG_OFFLINE)); + + // in point where GM stay + Player::SavePositionInDB(m_session->GetPlayer()->GetMapId(), + m_session->GetPlayer()->GetPositionX(), + m_session->GetPlayer()->GetPositionY(), + m_session->GetPlayer()->GetPositionZ(), + m_session->GetPlayer()->GetOrientation(), + m_session->GetPlayer()->GetZoneId(), + guid); + } + else + { + PSendSysMessage(LANG_NO_PLAYER, args); + SetSentErrorMessage(true); + } + + return true; +} + +//Teleport to Player +bool ChatHandler::HandleGonameCommand(const char* args) +{ + if(!*args) + return false; + + Player* _player = m_session->GetPlayer(); + + std::string name = args; + + if(!normalizePlayerName(name)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + Player *chr = objmgr.GetPlayer(name.c_str()); + if (chr) + { + Map* cMap = MapManager::Instance().GetMap(chr->GetMapId(),chr); + if(cMap->Instanceable()) + { + Map* pMap = MapManager::Instance().GetMap(_player->GetMapId(),_player); + + // we have to go to instance, and can go to player only if: + // 1) we are in his group (either as leader or as member) + // 2) we are not bound to any group and have GM mode on + if (_player->GetGroup()) + { + // we are in group, we can go only if we are in the player group + if (_player->GetGroup() != chr->GetGroup()) + { + PSendSysMessage(LANG_CANNOT_GO_TO_INST_PARTY,chr->GetName()); + SetSentErrorMessage(true); + return false; + } + } + else + { + // we are not in group, let's verify our GM mode + if (!_player->isGameMaster()) + { + PSendSysMessage(LANG_CANNOT_GO_TO_INST_GM,chr->GetName()); + SetSentErrorMessage(true); + return false; + } + } + + // if the player or the player's group is bound to another instance + // the player will not be bound to another one + InstancePlayerBind *pBind = _player->GetBoundInstance(chr->GetMapId(), chr->GetDifficulty()); + if(!pBind) + { + Group *group = _player->GetGroup(); + InstanceGroupBind *gBind = group ? group->GetBoundInstance(chr->GetMapId(), chr->GetDifficulty()) : NULL; + if(!gBind) + { + // if no bind exists, create a solo bind + InstanceSave *save = sInstanceSaveManager.GetInstanceSave(chr->GetInstanceId()); + if(save) _player->BindToInstance(save, !save->CanReset()); + } + } + + _player->SetDifficulty(chr->GetDifficulty()); + } + + PSendSysMessage(LANG_APPEARING_AT, chr->GetName()); + + if (_player->IsVisibleGloballyFor(chr)) + ChatHandler(chr).PSendSysMessage(LANG_APPEARING_TO, _player->GetName()); + + // stop flight if need + if(_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->m_taxi.ClearTaxiDestinations(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + // to point to see at target with same orientation + float x,y,z; + chr->GetContactPoint(m_session->GetPlayer(),x,y,z); + + _player->TeleportTo(chr->GetMapId(), x, y, z, _player->GetAngle( chr ), TELE_TO_GM_MODE); + + return true; + } + + if (uint64 guid = objmgr.GetPlayerGUIDByName(name)) + { + PSendSysMessage(LANG_APPEARING_AT, name.c_str()); + + // to point where player stay (if loaded) + float x,y,z,o; + uint32 map; + bool in_flight; + if(Player::LoadPositionFromDB(map,x,y,z,o,in_flight,guid)) + { + // stop flight if need + if(_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->m_taxi.ClearTaxiDestinations(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + _player->TeleportTo(map, x, y, z,_player->GetOrientation()); + return true; + } + } + + PSendSysMessage(LANG_NO_PLAYER, args); + + SetSentErrorMessage(true); + return false; +} + +// Teleport player to last position +bool ChatHandler::HandleRecallCommand(const char* args) +{ + Player* chr = NULL; + + if(!*args) + { + chr = getSelectedPlayer(); + if(!chr) + chr = m_session->GetPlayer(); + } + else + { + std::string name = args; + + if(!normalizePlayerName(name)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + chr = objmgr.GetPlayer(name.c_str()); + + if(!chr) + { + PSendSysMessage(LANG_NO_PLAYER, args); + SetSentErrorMessage(true); + return false; + } + } + + if(chr->IsBeingTeleported()) + { + PSendSysMessage(LANG_IS_TELEPORTED, chr->GetName()); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if(chr->isInFlight()) + { + chr->GetMotionMaster()->MovementExpired(); + chr->m_taxi.ClearTaxiDestinations(); + } + + chr->TeleportTo(chr->m_recallMap, chr->m_recallX, chr->m_recallY, chr->m_recallZ, chr->m_recallO); + return true; +} + +//Edit Player KnownTitles +bool ChatHandler::HandleModifyKnownTitlesCommand(const char* args) +{ + if(!*args) + return false; + + uint64 titles = 0; + + sscanf((char*)args, I64FMTD, &titles); + + Player *chr = getSelectedPlayer(); + if (!chr) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + uint64 titles2 = titles; + + for(int i=1; i < sCharTitlesStore.GetNumRows(); ++i) + if(CharTitlesEntry const* tEntry = sCharTitlesStore.LookupEntry(i)) + titles2 &= ~(uint64(1) << tEntry->bit_index); + + titles &= ~titles2; // remove not existed titles + + chr->SetUInt64Value(PLAYER__FIELD_KNOWN_TITLES, titles); + SendSysMessage(LANG_DONE); + + return true; +} + +//Edit Player HP +bool ChatHandler::HandleModifyHPCommand(const char* args) +{ + if(!*args) + return false; + + // char* pHp = strtok((char*)args, " "); + // if (!pHp) + // return false; + + // char* pHpMax = strtok(NULL, " "); + // if (!pHpMax) + // return false; + + // int32 hpm = atoi(pHpMax); + // int32 hp = atoi(pHp); + + int32 hp = atoi((char*)args); + int32 hpm = atoi((char*)args); + + if (hp <= 0 || hpm <= 0 || hpm < hp) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_YOU_CHANGE_HP, chr->GetName(), hp, hpm); + ChatHandler(chr).PSendSysMessage(LANG_YOURS_HP_CHANGED, m_session->GetPlayer()->GetName(), hp, hpm); + + chr->SetMaxHealth( hpm ); + chr->SetHealth( hp ); + + return true; +} + +//Edit Player Mana +bool ChatHandler::HandleModifyManaCommand(const char* args) +{ + if(!*args) + return false; + + // char* pmana = strtok((char*)args, " "); + // if (!pmana) + // return false; + + // char* pmanaMax = strtok(NULL, " "); + // if (!pmanaMax) + // return false; + + // int32 manam = atoi(pmanaMax); + // int32 mana = atoi(pmana); + int32 mana = atoi((char*)args); + int32 manam = atoi((char*)args); + + if (mana <= 0 || manam <= 0 || manam < mana) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_YOU_CHANGE_MANA, chr->GetName(), mana, manam); + ChatHandler(chr).PSendSysMessage(LANG_YOURS_MANA_CHANGED, m_session->GetPlayer()->GetName(), mana, manam); + + chr->SetMaxPower(POWER_MANA,manam ); + chr->SetPower(POWER_MANA, mana ); + + return true; +} + +//Edit Player Energy +bool ChatHandler::HandleModifyEnergyCommand(const char* args) +{ + if(!*args) + return false; + + // char* pmana = strtok((char*)args, " "); + // if (!pmana) + // return false; + + // char* pmanaMax = strtok(NULL, " "); + // if (!pmanaMax) + // return false; + + // int32 manam = atoi(pmanaMax); + // int32 mana = atoi(pmana); + + int32 energy = atoi((char*)args)*10; + int32 energym = atoi((char*)args)*10; + + if (energy <= 0 || energym <= 0 || energym < energy) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (!chr) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_YOU_CHANGE_ENERGY, chr->GetName(), energy/10, energym/10); + ChatHandler(chr).PSendSysMessage(LANG_YOURS_ENERGY_CHANGED, m_session->GetPlayer()->GetName(), energy/10, energym/10); + + chr->SetMaxPower(POWER_ENERGY,energym ); + chr->SetPower(POWER_ENERGY, energy ); + + sLog.outDetail(GetMangosString(LANG_CURRENT_ENERGY),chr->GetMaxPower(POWER_ENERGY)); + + return true; +} + +//Edit Player Rage +bool ChatHandler::HandleModifyRageCommand(const char* args) +{ + if(!*args) + return false; + + // char* pmana = strtok((char*)args, " "); + // if (!pmana) + // return false; + + // char* pmanaMax = strtok(NULL, " "); + // if (!pmanaMax) + // return false; + + // int32 manam = atoi(pmanaMax); + // int32 mana = atoi(pmana); + + int32 rage = atoi((char*)args)*10; + int32 ragem = atoi((char*)args)*10; + + if (rage <= 0 || ragem <= 0 || ragem < rage) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_YOU_CHANGE_RAGE, chr->GetName(), rage/10, ragem/10); + // Special case: I use GetMangosString here to get local of destination char ;) + ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetMangosString(LANG_YOURS_RAGE_CHANGED), m_session->GetPlayer()->GetName(), rage/10, ragem/10); + + chr->SetMaxPower(POWER_RAGE,ragem ); + chr->SetPower(POWER_RAGE, rage ); + + return true; +} + +//Edit Player Faction +bool ChatHandler::HandleModifyFactionCommand(const char* args) +{ + if(!*args) + return false; + + char* pfactionid = extractKeyFromLink((char*)args,"Hfaction"); + + Creature* chr = getSelectedCreature(); + if(!chr) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if(!pfactionid) + { + if(chr) + { + uint32 factionid = chr->getFaction(); + uint32 flag = chr->GetUInt32Value(UNIT_FIELD_FLAGS); + uint32 npcflag = chr->GetUInt32Value(UNIT_NPC_FLAGS); + uint32 dyflag = chr->GetUInt32Value(UNIT_DYNAMIC_FLAGS); + PSendSysMessage(LANG_CURRENT_FACTION,chr->GetGUIDLow(),factionid,flag,npcflag,dyflag); + } + return true; + } + + if( !chr ) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + uint32 factionid = atoi(pfactionid); + uint32 flag; + + char *pflag = strtok(NULL, " "); + if (!pflag) + flag = chr->GetUInt32Value(UNIT_FIELD_FLAGS); + else + flag = atoi(pflag); + + char* pnpcflag = strtok(NULL, " "); + + uint32 npcflag; + if(!pnpcflag) + npcflag = chr->GetUInt32Value(UNIT_NPC_FLAGS); + else + npcflag = atoi(pnpcflag); + + char* pdyflag = strtok(NULL, " "); + + uint32 dyflag; + if(!pdyflag) + dyflag = chr->GetUInt32Value(UNIT_DYNAMIC_FLAGS); + else + dyflag = atoi(pdyflag); + + if(!sFactionTemplateStore.LookupEntry(factionid)) + { + PSendSysMessage(LANG_WRONG_FACTION, factionid); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_YOU_CHANGE_FACTION, chr->GetGUIDLow(),factionid,flag,npcflag,dyflag); + + //sprintf((char*)buf,"%s changed your Faction to %i.", m_session->GetPlayer()->GetName(), factionid); + //FillSystemMessageData(&data, m_session, buf); + + //chr->GetSession()->SendPacket(&data); + + chr->setFaction(factionid); + chr->SetUInt32Value(UNIT_FIELD_FLAGS,flag); + chr->SetUInt32Value(UNIT_NPC_FLAGS,npcflag); + chr->SetUInt32Value(UNIT_DYNAMIC_FLAGS,dyflag); + + return true; +} + +//Edit Player Spell +bool ChatHandler::HandleModifySpellCommand(const char* args) +{ + if(!*args) return false; + char* pspellflatid = strtok((char*)args, " "); + if (!pspellflatid) + return false; + + char* pop = strtok(NULL, " "); + if (!pop) + return false; + + char* pval = strtok(NULL, " "); + if (!pval) + return false; + + uint16 mark; + + char* pmark = strtok(NULL, " "); + + uint8 spellflatid = atoi(pspellflatid); + uint8 op = atoi(pop); + uint16 val = atoi(pval); + if(!pmark) + mark = 65535; + else + mark = atoi(pmark); + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_YOU_CHANGE_SPELLFLATID, spellflatid, val, mark, chr->GetName()); + if(chr != m_session->GetPlayer()) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_SPELLFLATID_CHANGED, m_session->GetPlayer()->GetName(), spellflatid, val, mark); + + WorldPacket data(SMSG_SET_FLAT_SPELL_MODIFIER, (1+1+2+2)); + data << uint8(spellflatid); + data << uint8(op); + data << uint16(val); + data << uint16(mark); + chr->GetSession()->SendPacket(&data); + + return true; +} + +//Edit Player TP +bool ChatHandler::HandleModifyTalentCommand (const char* args) +{ + if (!*args) + return false; + + int tp = atoi((char*)args); + if (tp>0) + { + Player* player = getSelectedPlayer(); + if(!player) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + player->SetFreeTalentPoints(tp); + return true; + } + return false; +} + +//Enable On\OFF all taxi paths +bool ChatHandler::HandleTaxiCheatCommand(const char* args) +{ + if (!*args) + { + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; + } + + std::string argstr = (char*)args; + + Player *chr = getSelectedPlayer(); + if (!chr) + { + chr=m_session->GetPlayer(); + } + + if (argstr == "on") + { + chr->SetTaxiCheater(true); + PSendSysMessage(LANG_YOU_GIVE_TAXIS, chr->GetName()); + + if(chr != m_session->GetPlayer()) + // to send localized data to target + ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetMangosString(LANG_YOURS_TAXIS_ADDED), m_session->GetPlayer()->GetName()); + return true; + } + + if (argstr == "off") + { + chr->SetTaxiCheater(false); + PSendSysMessage(LANG_YOU_REMOVE_TAXIS, chr->GetName()); + + if(chr != m_session->GetPlayer()) + ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetMangosString(LANG_YOURS_TAXIS_REMOVED), m_session->GetPlayer()->GetName()); + + return true; + } + + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; +} + +//Edit Player Aspeed +bool ChatHandler::HandleModifyASpeedCommand(const char* args) +{ + if (!*args) + return false; + + float ASpeed = (float)atof((char*)args); + + if (ASpeed > 10 || ASpeed < 0.1) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + if(chr->isInFlight()) + { + PSendSysMessage(LANG_CHAR_IN_FLIGHT,chr->GetName()); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_YOU_CHANGE_ASPEED, ASpeed, chr->GetName()); + + if(chr != m_session->GetPlayer()) + ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetMangosString(LANG_YOURS_ASPEED_CHANGED), m_session->GetPlayer()->GetName(), ASpeed); + + chr->SetSpeed(MOVE_WALK, ASpeed,true); + chr->SetSpeed(MOVE_RUN, ASpeed,true); + chr->SetSpeed(MOVE_SWIM, ASpeed,true); + //chr->SetSpeed(MOVE_TURN, ASpeed,true); + chr->SetSpeed(MOVE_FLY, ASpeed,true); + return true; +} + +//Edit Player Speed +bool ChatHandler::HandleModifySpeedCommand(const char* args) +{ + if (!*args) + return false; + + float Speed = (float)atof((char*)args); + + if (Speed > 10 || Speed < 0.1) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + if(chr->isInFlight()) + { + PSendSysMessage(LANG_CHAR_IN_FLIGHT,chr->GetName()); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_YOU_CHANGE_SPEED, Speed, chr->GetName()); + + if(chr != m_session->GetPlayer()) + ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetMangosString(LANG_YOURS_SPEED_CHANGED), m_session->GetPlayer()->GetName(), Speed); + + chr->SetSpeed(MOVE_RUN,Speed,true); + + return true; +} + +//Edit Player Swim Speed +bool ChatHandler::HandleModifySwimCommand(const char* args) +{ + if (!*args) + return false; + + float Swim = (float)atof((char*)args); + + if (Swim > 10.0f || Swim < 0.01f) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + if(chr->isInFlight()) + { + PSendSysMessage(LANG_CHAR_IN_FLIGHT,chr->GetName()); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_YOU_CHANGE_SWIM_SPEED, Swim, chr->GetName()); + + if(chr != m_session->GetPlayer()) + ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetMangosString(LANG_YOURS_SWIM_SPEED_CHANGED), m_session->GetPlayer()->GetName(), Swim); + + chr->SetSpeed(MOVE_SWIM,Swim,true); + + return true; +} + +//Edit Player Walk Speed +bool ChatHandler::HandleModifyBWalkCommand(const char* args) +{ + if (!*args) + return false; + + float BSpeed = (float)atof((char*)args); + + if (BSpeed > 10.0f || BSpeed < 0.1f) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + if(chr->isInFlight()) + { + PSendSysMessage(LANG_CHAR_IN_FLIGHT,chr->GetName()); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_YOU_CHANGE_BACK_SPEED, BSpeed, chr->GetName()); + + if(chr != m_session->GetPlayer()) + ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetMangosString(LANG_YOURS_BACK_SPEED_CHANGED), m_session->GetPlayer()->GetName(), BSpeed); + + chr->SetSpeed(MOVE_WALKBACK,BSpeed,true); + + return true; +} + +//Edit Player Fly +bool ChatHandler::HandleModifyFlyCommand(const char* args) +{ + if (!*args) + return false; + + float FSpeed = (float)atof((char*)args); + + if (FSpeed > 10.0f || FSpeed < 0.1f) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_YOU_CHANGE_FLY_SPEED, FSpeed, chr->GetName()); + + if(chr != m_session->GetPlayer()) + ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetMangosString(LANG_YOURS_FLY_SPEED_CHANGED), m_session->GetPlayer()->GetName(), FSpeed); + + chr->SetSpeed(MOVE_FLY,FSpeed,true); + + return true; +} + +//Edit Player Scale +bool ChatHandler::HandleModifyScaleCommand(const char* args) +{ + if (!*args) + return false; + + float Scale = (float)atof((char*)args); + if (Scale > 3.0f || Scale <= 0.0f) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_YOU_CHANGE_SIZE, Scale, chr->GetName()); + + if(chr != m_session->GetPlayer()) + ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetMangosString(LANG_YOURS_SIZE_CHANGED), m_session->GetPlayer()->GetName(), Scale); + + chr->SetFloatValue(OBJECT_FIELD_SCALE_X, Scale); + + return true; +} + +//Enable Player mount +bool ChatHandler::HandleModifyMountCommand(const char* args) +{ + if(!*args) + return false; + + uint16 mId = 1147; + float speed = (float)15; + uint32 num = 0; + + num = atoi((char*)args); + switch(num) + { + case 1: + mId=14340; + break; + case 2: + mId=4806; + break; + case 3: + mId=6471; + break; + case 4: + mId=12345; + break; + case 5: + mId=6472; + break; + case 6: + mId=6473; + break; + case 7: + mId=10670; + break; + case 8: + mId=10719; + break; + case 9: + mId=10671; + break; + case 10: + mId=10672; + break; + case 11: + mId=10720; + break; + case 12: + mId=14349; + break; + case 13: + mId=11641; + break; + case 14: + mId=12244; + break; + case 15: + mId=12242; + break; + case 16: + mId=14578; + break; + case 17: + mId=14579; + break; + case 18: + mId=14349; + break; + case 19: + mId=12245; + break; + case 20: + mId=14335; + break; + case 21: + mId=207; + break; + case 22: + mId=2328; + break; + case 23: + mId=2327; + break; + case 24: + mId=2326; + break; + case 25: + mId=14573; + break; + case 26: + mId=14574; + break; + case 27: + mId=14575; + break; + case 28: + mId=604; + break; + case 29: + mId=1166; + break; + case 30: + mId=2402; + break; + case 31: + mId=2410; + break; + case 32: + mId=2409; + break; + case 33: + mId=2408; + break; + case 34: + mId=2405; + break; + case 35: + mId=14337; + break; + case 36: + mId=6569; + break; + case 37: + mId=10661; + break; + case 38: + mId=10666; + break; + case 39: + mId=9473; + break; + case 40: + mId=9476; + break; + case 41: + mId=9474; + break; + case 42: + mId=14374; + break; + case 43: + mId=14376; + break; + case 44: + mId=14377; + break; + case 45: + mId=2404; + break; + case 46: + mId=2784; + break; + case 47: + mId=2787; + break; + case 48: + mId=2785; + break; + case 49: + mId=2736; + break; + case 50: + mId=2786; + break; + case 51: + mId=14347; + break; + case 52: + mId=14346; + break; + case 53: + mId=14576; + break; + case 54: + mId=9695; + break; + case 55: + mId=9991; + break; + case 56: + mId=6448; + break; + case 57: + mId=6444; + break; + case 58: + mId=6080; + break; + case 59: + mId=6447; + break; + case 60: + mId=4805; + break; + case 61: + mId=9714; + break; + case 62: + mId=6448; + break; + case 63: + mId=6442; + break; + case 64: + mId=14632; + break; + case 65: + mId=14332; + break; + case 66: + mId=14331; + break; + case 67: + mId=8469; + break; + case 68: + mId=2830; + break; + case 69: + mId=2346; + break; + default: + SendSysMessage(LANG_NO_MOUNT); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_YOU_GIVE_MOUNT, chr->GetName()); + + if(chr != m_session->GetPlayer()) + ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetMangosString(LANG_MOUNT_GIVED), m_session->GetPlayer()->GetName()); + + chr->SetUInt32Value( UNIT_FIELD_FLAGS , 0x001000 ); + chr->Mount(mId); + + WorldPacket data( SMSG_FORCE_RUN_SPEED_CHANGE, (8+4+1+4) ); + data.append(chr->GetPackGUID()); + data << (uint32)0; + data << (uint8)0; //new 2.1.0 + data << float(speed); + chr->SendMessageToSet( &data, true ); + + data.Initialize( SMSG_FORCE_SWIM_SPEED_CHANGE, (8+4+4) ); + data.append(chr->GetPackGUID()); + data << (uint32)0; + data << float(speed); + chr->SendMessageToSet( &data, true ); + + return true; +} + +//Edit Player money +bool ChatHandler::HandleModifyMoneyCommand(const char* args) +{ + if (!*args) + return false; + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + int32 addmoney = atoi((char*)args); + + uint32 moneyuser = chr->GetMoney(); + + if(addmoney < 0) + { + int32 newmoney = moneyuser + addmoney; + + sLog.outDetail(GetMangosString(LANG_CURRENT_MONEY), moneyuser, addmoney, newmoney); + if(newmoney <= 0 ) + { + PSendSysMessage(LANG_YOU_TAKE_ALL_MONEY, chr->GetName()); + + if(chr != m_session->GetPlayer()) + ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetMangosString(LANG_YOURS_ALL_MONEY_GONE), m_session->GetPlayer()->GetName()); + + chr->SetMoney(0); + } + else + { + PSendSysMessage(LANG_YOU_TAKE_MONEY, abs(addmoney), chr->GetName()); + if(chr != m_session->GetPlayer()) + ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetMangosString(LANG_YOURS_MONEY_TAKEN), m_session->GetPlayer()->GetName(), abs(addmoney)); + chr->SetMoney( newmoney ); + } + } + else + { + PSendSysMessage(LANG_YOU_GIVE_MONEY, addmoney, chr->GetName()); + if(chr != m_session->GetPlayer()) + ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetMangosString(LANG_YOURS_MONEY_GIVEN), m_session->GetPlayer()->GetName(), addmoney); + chr->ModifyMoney( addmoney ); + } + + sLog.outDetail(GetMangosString(LANG_NEW_MONEY), moneyuser, addmoney, chr->GetMoney() ); + + return true; +} + +//Edit Player field +bool ChatHandler::HandleModifyBitCommand(const char* args) +{ + if( !*args ) + return false; + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + char* pField = strtok((char*)args, " "); + if (!pField) + return false; + + char* pBit = strtok(NULL, " "); + if (!pBit) + return false; + + uint16 field = atoi(pField); + uint32 bit = atoi(pBit); + + if (field < 1 || field >= PLAYER_END) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + if (bit < 1 || bit > 32) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + if ( chr->HasFlag( field, (1<<(bit-1)) ) ) + { + chr->RemoveFlag( field, (1<<(bit-1)) ); + PSendSysMessage(LANG_REMOVE_BIT, bit, field); + } + else + { + chr->SetFlag( field, (1<<(bit-1)) ); + PSendSysMessage(LANG_SET_BIT, bit, field); + } + + return true; +} + +//Teleport by game_tele entry +bool ChatHandler::HandleModifyHonorCommand (const char* args) +{ + if (!*args) + return false; + + Player *target = getSelectedPlayer(); + if(!target) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + int32 amount = (uint32)atoi(args); + + target->ModifyHonorPoints(amount); + + PSendSysMessage(LANG_COMMAND_MODIFY_HONOR, target->GetName(), target->GetHonorPoints()); + + return true; +} + +bool ChatHandler::HandleTeleCommand(const char * args) +{ + if(!*args) + return false; + + Player* _player = m_session->GetPlayer(); + + char* cId = extractKeyFromLink((char*)args,"Htele"); // string or [name] Shift-click form |color|Htele:name|h[name]|h|r + if(!cId) + return false; + + std::string name = cId; + WorldDatabase.escape_string(name); + + QueryResult *result = WorldDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map FROM game_tele WHERE name = '%s'",name.c_str()); + if (!result) + { + SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); + SetSentErrorMessage(true); + return false; + } + Field *fields = result->Fetch(); + float x = fields[0].GetFloat(); + float y = fields[1].GetFloat(); + float z = fields[2].GetFloat(); + float ort = fields[3].GetFloat(); + int mapid = fields[4].GetUInt16(); + delete result; + + if(!MapManager::IsValidMapCoord(mapid,x,y,x,ort)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if(_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->m_taxi.ClearTaxiDestinations(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + _player->TeleportTo(mapid, x, y, z, ort); + return true; +} + +bool ChatHandler::HandleLookupAreaCommand(const char* args) +{ + if(!*args) + return false; + + std::string namepart = args; + std::wstring wnamepart; + + if(!Utf8toWStr(namepart,wnamepart)) + return false; + + uint32 counter = 0; // Counter for figure out that we found smth. + + // converting string that we try to find to lower case + wstrToLower( wnamepart ); + + // Search in AreaTable.dbc + for (uint32 areaflag = 0; areaflag < sAreaStore.GetNumRows(); ++areaflag) + { + AreaTableEntry const *areaEntry = sAreaStore.LookupEntry(areaflag); + if(areaEntry) + { + int loc = m_session->GetSessionDbcLocale(); + std::string name = areaEntry->area_name[loc]; + if(name.empty()) + continue; + + if(!Utf8FitTo(name, wnamepart)) + { + loc = 0; + for(; loc < MAX_LOCALE; ++loc) + { + if(loc==m_session->GetSessionDbcLocale()) + continue; + + name = areaEntry->area_name[loc]; + if(name.empty()) + continue; + + if (Utf8FitTo(name, wnamepart)) + break; + } + } + + if(loc < MAX_LOCALE) + { + // send area in "id - [name]" format + std::ostringstream ss; + ss << areaEntry->ID << " - |cffffffff|Harea:" << areaEntry->ID << "|h[" << name << " " << localeNames[loc]<< "]|h|r"; + + SendSysMessage(ss.str().c_str()); + + ++counter; + } + } + } + if (counter == 0) // if counter == 0 then we found nth + SendSysMessage(LANG_COMMAND_NOAREAFOUND); + return true; +} + +//Find tele in game_tele order by name +bool ChatHandler::HandleLookupTeleCommand(const char * args) +{ + if(!*args) + { + SendSysMessage(LANG_COMMAND_TELE_PARAMETER); + SetSentErrorMessage(true); + return false; + } + char const* str = strtok((char*)args, " "); + if(!str) + return false; + + std::string namepart = str; + WorldDatabase.escape_string(namepart); + QueryResult *result = WorldDatabase.PQuery("SELECT name FROM game_tele WHERE name "_LIKE_" '""%%%s%%""'",namepart.c_str()); + if (!result) + { + SendSysMessage(LANG_COMMAND_TELE_NOREQUEST); + SetSentErrorMessage(true); + return false; + } + std::string reply; + for (uint64 i=0; i < result->GetRowCount(); i++) + { + Field *fields = result->Fetch(); + reply += " |cffffffff|Htele:"; + reply += fields[0].GetCppString(); + reply += "|h["; + reply += fields[0].GetCppString(); + reply += "]|h|r\n"; + result->NextRow(); + } + delete result; + + if(reply.empty()) + SendSysMessage(LANG_COMMAND_TELE_NOLOCATION); + else + { + reply = GetMangosString(LANG_COMMAND_TELE_LOCATION) + reply; + SendSysMessage(reply.c_str()); + } + return true; +} + +//Enable\Dissable accept whispers (for GM) +bool ChatHandler::HandleWhispersCommand(const char* args) +{ + if(!*args) + { + PSendSysMessage(LANG_COMMAND_WHISPERACCEPTING, m_session->GetPlayer()->isAcceptWhispers() ? GetMangosString(LANG_ON) : GetMangosString(LANG_OFF)); + return true; + } + + std::string argstr = (char*)args; + // whisper on + if (argstr == "on") + { + m_session->GetPlayer()->SetAcceptWhispers(true); + SendSysMessage(LANG_COMMAND_WHISPERON); + return true; + } + + // whisper off + if (argstr == "off") + { + m_session->GetPlayer()->SetAcceptWhispers(false); + SendSysMessage(LANG_COMMAND_WHISPEROFF); + return true; + } + + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; +} + +//Play sound +bool ChatHandler::HandlePlaySoundCommand(const char* args) +{ + // USAGE: .debug playsound #soundid + // #soundid - ID decimal number from SoundEntries.dbc (1st column) + // this file have about 5000 sounds. + // In this realization only caller can hear this sound. + if( *args ) + { + uint32 dwSoundId = atoi((char*)args); + + if( !sSoundEntriesStore.LookupEntry(dwSoundId) ) + { + PSendSysMessage(LANG_SOUND_NOT_EXIST, dwSoundId); + SetSentErrorMessage(true); + return false; + } + + WorldPacket data(SMSG_PLAY_OBJECT_SOUND,4+8); + data << uint32(dwSoundId) << m_session->GetPlayer()->GetGUID(); + m_session->SendPacket(&data); + + PSendSysMessage(LANG_YOU_HEAR_SOUND, dwSoundId); + return true; + } + + return false; +} + +//Save all players in the world +bool ChatHandler::HandleSaveAllCommand(const char* /*args*/) +{ + ObjectAccessor::Instance().SaveAllPlayers(); + SendSysMessage(LANG_PLAYERS_SAVED); + return true; +} + +//Send mail by command +bool ChatHandler::HandleSendMailCommand(const char* args) +{ + if(!*args) + return false; + + char* pName = strtok((char*)args, " "); + char* msgSubject = strtok(NULL, " "); + char* msgText = strtok(NULL, ""); + + if (!msgText) + return false; + + // pName, msgSubject, msgText isn't NUL after prev. check + + std::string name = pName; + std::string subject = msgSubject; + std::string text = msgText; + + if(!normalizePlayerName(name)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + uint64 receiver_guid = objmgr.GetPlayerGUIDByName(name); + + if(!receiver_guid) + return false; + + uint32 mailId = objmgr.GenerateMailID(); + uint32 sender_guidlo = m_session->GetPlayer()->GetGUIDLow(); + uint32 messagetype = MAIL_NORMAL; + uint32 stationery = MAIL_STATIONERY_GM; + uint32 itemTextId = 0; + if (!text.empty()) + { + itemTextId = objmgr.CreateItemText( text ); + } + + Player *receiver = objmgr.GetPlayer(receiver_guid); + + WorldSession::SendMailTo(receiver,messagetype, stationery, sender_guidlo, GUID_LOPART(receiver_guid), subject, itemTextId, NULL, 0, 0, MAIL_CHECK_MASK_NONE); + + PSendSysMessage(LANG_MAIL_SENT, name.c_str()); + return true; +} + +// teleport player to given game_tele.entry +bool ChatHandler::HandleNameTeleCommand(const char * args) +{ + if(!*args) + return false; + + char* pName = strtok((char*)args, " "); + + if(!pName) + return false; + + char* tail = strtok(NULL, ""); + if(!tail) + return false; + + char* cId = extractKeyFromLink((char*)tail,"Htele"); // string or [name] Shift-click form |color|Htele:name|h[name]|h|r + if(!cId) + return false; + + std::string location = cId; + + std::string name = pName; + + if(!normalizePlayerName(name)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + WorldDatabase.escape_string(location); + QueryResult *result = WorldDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map FROM game_tele WHERE name = '%s'",location.c_str()); + if (!result) + { + SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); + SetSentErrorMessage(true); + return false; + } + + Field *fields = result->Fetch(); + float x = fields[0].GetFloat(); + float y = fields[1].GetFloat(); + float z = fields[2].GetFloat(); + float ort = fields[3].GetFloat(); + int mapid = fields[4].GetUInt16(); + delete result; + + if(!MapManager::IsValidMapCoord(mapid,x,y,x,ort)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid); + SetSentErrorMessage(true); + return false; + } + + Player *chr = objmgr.GetPlayer(name.c_str()); + if (chr) + { + + if(chr->IsBeingTeleported()==true) + { + PSendSysMessage(LANG_IS_TELEPORTED, chr->GetName()); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_TELEPORTING_TO, chr->GetName(),"", location.c_str()); + + if (m_session->GetPlayer()->IsVisibleGloballyFor(chr)) + ChatHandler(chr).PSendSysMessage(LANG_TELEPORTED_TO_BY, m_session->GetPlayer()->GetName()); + + // stop flight if need + if(chr->isInFlight()) + { + chr->GetMotionMaster()->MovementExpired(); + chr->m_taxi.ClearTaxiDestinations(); + } + // save only in non-flight case + else + chr->SaveRecallPosition(); + + chr->TeleportTo(mapid,x,y,z,chr->GetOrientation()); + } + else if (uint64 guid = objmgr.GetPlayerGUIDByName(name.c_str())) + { + PSendSysMessage(LANG_TELEPORTING_TO, name.c_str(), GetMangosString(LANG_OFFLINE), location.c_str()); + Player::SavePositionInDB(mapid,x,y,z,ort,MapManager::Instance().GetZoneId(mapid,x,y),guid); + } + else + PSendSysMessage(LANG_NO_PLAYER, name.c_str()); + + return true; +} + +//Teleport group to given game_tele.entry +bool ChatHandler::HandleGroupTeleCommand(const char * args) +{ + if(!*args) + return false; + + Player *player = getSelectedPlayer(); + if (!player) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + char* cId = extractKeyFromLink((char*)args,"Htele"); // string or [name] Shift-click form |color|Htele:name|h[name]|h|r + if(!cId) + return false; + + std::string location = cId; + + WorldDatabase.escape_string(location); + QueryResult *result = WorldDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map FROM game_tele WHERE name = '%s'",location.c_str()); + if (!result) + { + SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); + SetSentErrorMessage(true); + return false; + } + Field *fields = result->Fetch(); + float x = fields[0].GetFloat(); + float y = fields[1].GetFloat(); + float z = fields[2].GetFloat(); + float ort = fields[3].GetFloat(); + int mapid = fields[4].GetUInt16(); + delete result; + + if(!MapManager::IsValidMapCoord(mapid,x,y,z,ort)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid); + SetSentErrorMessage(true); + return false; + } + + Group *grp = player->GetGroup(); + + if(!grp) + { + PSendSysMessage(LANG_NOT_IN_GROUP,player->GetName()); + SetSentErrorMessage(true); + return false; + } + + for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *pl = itr->getSource(); + + if(!pl || !pl->GetSession() ) + continue; + + if(pl->IsBeingTeleported()) + { + PSendSysMessage(LANG_IS_TELEPORTED, pl->GetName()); + continue; + } + + PSendSysMessage(LANG_TELEPORTING_TO, pl->GetName(),"", location.c_str()); + + if (m_session->GetPlayer() != pl && m_session->GetPlayer()->IsVisibleGloballyFor(pl)) + ChatHandler(pl).PSendSysMessage(LANG_TELEPORTED_TO_BY, m_session->GetPlayer()->GetName()); + + // stop flight if need + if(pl->isInFlight()) + { + pl->GetMotionMaster()->MovementExpired(); + pl->m_taxi.ClearTaxiDestinations(); + } + // save only in non-flight case + else + pl->SaveRecallPosition(); + + pl->TeleportTo(mapid, x, y, z, ort); + } + + return true; +} + +//Summon group of player +bool ChatHandler::HandleGroupgoCommand(const char* args) +{ + if(!*args) + return false; + + std::string name = args; + + if(!normalizePlayerName(name)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + Player *player = objmgr.GetPlayer(name.c_str()); + if (!player) + { + PSendSysMessage(LANG_NO_PLAYER, args); + SetSentErrorMessage(true); + return false; + } + + Group *grp = player->GetGroup(); + + if(!grp) + { + PSendSysMessage(LANG_NOT_IN_GROUP,player->GetName()); + SetSentErrorMessage(true); + return false; + } + + Map* gmMap = MapManager::Instance().GetMap(m_session->GetPlayer()->GetMapId(),m_session->GetPlayer()); + bool to_instance = gmMap->Instanceable(); + + // we are in instance, and can summon only player in our group with us as lead + if ( to_instance && ( + !m_session->GetPlayer()->GetGroup() || (grp->GetLeaderGUID() != m_session->GetPlayer()->GetGUID()) || + (m_session->GetPlayer()->GetGroup()->GetLeaderGUID() != m_session->GetPlayer()->GetGUID()) ) ) + // the last check is a bit excessive, but let it be, just in case + { + SendSysMessage(LANG_CANNOT_SUMMON_TO_INST); + SetSentErrorMessage(true); + return false; + } + + for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *pl = itr->getSource(); + + if(!pl || pl==m_session->GetPlayer() || !pl->GetSession() ) + continue; + + if(pl->IsBeingTeleported()==true) + { + PSendSysMessage(LANG_IS_TELEPORTED, pl->GetName()); + SetSentErrorMessage(true); + return false; + } + + if (to_instance) + { + Map* plMap = MapManager::Instance().GetMap(pl->GetMapId(),pl); + + if ( plMap->Instanceable() && plMap->GetInstanceId() != gmMap->GetInstanceId() ) + { + // cannot summon from instance to instance + PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST,pl->GetName()); + SetSentErrorMessage(true); + return false; + } + } + + PSendSysMessage(LANG_SUMMONING, pl->GetName(),""); + + if (m_session->GetPlayer()->IsVisibleGloballyFor(pl)) + ChatHandler(pl).PSendSysMessage(LANG_SUMMONED_BY, m_session->GetPlayer()->GetName()); + + // stop flight if need + if(pl->isInFlight()) + { + pl->GetMotionMaster()->MovementExpired(); + pl->m_taxi.ClearTaxiDestinations(); + } + // save only in non-flight case + else + pl->SaveRecallPosition(); + + // before GM + float x,y,z; + m_session->GetPlayer()->GetClosePoint(x,y,z,pl->GetObjectSize()); + pl->TeleportTo(m_session->GetPlayer()->GetMapId(),x,y,z,pl->GetOrientation()); + } + + return true; +} + +//teleport at coordinates +bool ChatHandler::HandleGoXYCommand(const char* args) +{ + if(!*args) + return false; + + Player* _player = m_session->GetPlayer(); + + char* px = strtok((char*)args, " "); + char* py = strtok(NULL, " "); + char* pmapid = strtok(NULL, " "); + + if (!px || !py) + return false; + + float x = (float)atof(px); + float y = (float)atof(py); + uint32 mapid; + if (pmapid) + mapid = (uint32)atoi(pmapid); + else mapid = _player->GetMapId(); + + if(!MapManager::IsValidMapCoord(mapid,x,y)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if(_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->m_taxi.ClearTaxiDestinations(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + Map const *map = MapManager::Instance().GetBaseMap(mapid); + float z = std::max(map->GetHeight(x, y, MAX_HEIGHT), map->GetWaterLevel(x, y)); + + _player->TeleportTo(mapid, x, y, z, _player->GetOrientation()); + + return true; +} + +//teleport at coordinates, including Z +bool ChatHandler::HandleGoXYZCommand(const char* args) +{ + if(!*args) + return false; + + Player* _player = m_session->GetPlayer(); + + char* px = strtok((char*)args, " "); + char* py = strtok(NULL, " "); + char* pz = strtok(NULL, " "); + char* pmapid = strtok(NULL, " "); + + if (!px || !py || !pz) + return false; + + float x = (float)atof(px); + float y = (float)atof(py); + float z = (float)atof(pz); + uint32 mapid; + if (pmapid) + mapid = (uint32)atoi(pmapid); + else + mapid = _player->GetMapId(); + + if(!MapManager::IsValidMapCoord(mapid,x,y,z)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if(_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->m_taxi.ClearTaxiDestinations(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + _player->TeleportTo(mapid, x, y, z, _player->GetOrientation()); + + return true; +} + +//teleport at coordinates +bool ChatHandler::HandleGoZoneXYCommand(const char* args) +{ + if(!*args) + return false; + + Player* _player = m_session->GetPlayer(); + + char* px = strtok((char*)args, " "); + char* py = strtok(NULL, " "); + char* tail = strtok(NULL,""); + + char* cAreaId = extractKeyFromLink(tail,"Harea"); // string or [name] Shift-click form |color|Harea:area_id|h[name]|h|r + + if (!px || !py) + return false; + + float x = (float)atof(px); + float y = (float)atof(py); + uint32 areaid = cAreaId ? (uint32)atoi(cAreaId) : _player->GetZoneId(); + + AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(areaid); + + if( x<0 || x>100 || y<0 || y>100 || !areaEntry ) + { + PSendSysMessage(LANG_INVALID_ZONE_COORD,x,y,areaid); + SetSentErrorMessage(true); + return false; + } + + // update to parent zone if exist (client map show only zones without parents) + AreaTableEntry const* zoneEntry = areaEntry->zone ? GetAreaEntryByAreaID(areaEntry->zone) : areaEntry; + + Map const *map = MapManager::Instance().GetBaseMap(zoneEntry->mapid); + + if(map->Instanceable()) + { + PSendSysMessage(LANG_INVALID_ZONE_MAP,areaEntry->ID,areaEntry->area_name[m_session->GetSessionDbcLocale()],map->GetId(),map->GetMapName()); + SetSentErrorMessage(true); + return false; + } + + Zone2MapCoordinates(x,y,zoneEntry->ID); + + if(!MapManager::IsValidMapCoord(zoneEntry->mapid,x,y)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,zoneEntry->mapid); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if(_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->m_taxi.ClearTaxiDestinations(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + float z = std::max(map->GetHeight(x, y, MAX_HEIGHT), map->GetWaterLevel(x, y)); + _player->TeleportTo(zoneEntry->mapid, x, y, z, _player->GetOrientation()); + + return true; +} + +//teleport to grid +bool ChatHandler::HandleGoGridCommand(const char* args) +{ + if(!*args) return false; + Player* _player = m_session->GetPlayer(); + + char* px = strtok((char*)args, " "); + char* py = strtok(NULL, " "); + char* pmapid = strtok(NULL, " "); + + if (!px || !py) + return false; + + float grid_x = (float)atof(px); + float grid_y = (float)atof(py); + uint32 mapid; + if (pmapid) + mapid = (uint32)atoi(pmapid); + else mapid = _player->GetMapId(); + + // center of grid + float x = (grid_x-CENTER_GRID_ID+0.5f)*SIZE_OF_GRIDS; + float y = (grid_y-CENTER_GRID_ID+0.5f)*SIZE_OF_GRIDS; + + if(!MapManager::IsValidMapCoord(mapid,x,y)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if(_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->m_taxi.ClearTaxiDestinations(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + Map const *map = MapManager::Instance().GetBaseMap(mapid); + float z = std::max(map->GetHeight(x, y, MAX_HEIGHT), map->GetWaterLevel(x, y)); + _player->TeleportTo(mapid, x, y, z, _player->GetOrientation()); + + return true; +} + +bool ChatHandler::HandleDrunkCommand(const char* args) +{ + if(!*args) return false; + + uint32 drunklevel = (uint32)atoi(args); + if(drunklevel > 100) + drunklevel = 100; + + uint16 drunkMod = drunklevel * 0xFFFF / 100; + + m_session->GetPlayer()->SetDrunkValue(drunkMod); + + return true; +} diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp new file mode 100644 index 00000000000..63ad2a7a0b9 --- /dev/null +++ b/src/game/Level2.cpp @@ -0,0 +1,3948 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "World.h" +#include "ObjectMgr.h" +#include "Player.h" +#include "Item.h" +#include "GameObject.h" +#include "Opcodes.h" +#include "Chat.h" +#include "ObjectAccessor.h" +#include "MapManager.h" +#include "Language.h" +#include "World.h" +#include "GameEvent.h" +#include "SpellMgr.h" +#include "WaypointManager.h" +#include "Util.h" +#include +#include +#include +#include + +static uint32 ReputationRankStrIndex[MAX_REPUTATION_RANK] = +{ + LANG_REP_HATED, LANG_REP_HOSTILE, LANG_REP_UNFRIENDLY, LANG_REP_NEUTRAL, + LANG_REP_FRIENDLY, LANG_REP_HONORED, LANG_REP_REVERED, LANG_REP_EXALTED +}; + +//mute player for some times +bool ChatHandler::HandleMuteCommand(const char* args) +{ + if (!*args) + return false; + + char *charname = strtok((char*)args, " "); + if (!charname) + return false; + + std::string cname = charname; + + char *timetonotspeak = strtok(NULL, " "); + if(!timetonotspeak) + return false; + + uint32 notspeaktime = (uint32) atoi(timetonotspeak); + + if(!normalizePlayerName(cname)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + uint64 guid = objmgr.GetPlayerGUIDByName(cname.c_str()); + if(!guid) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + Player *chr = objmgr.GetPlayer(guid); + + // check security + uint32 account_id = 0; + uint32 security = 0; + + if (chr) + { + account_id = chr->GetSession()->GetAccountId(); + security = chr->GetSession()->GetSecurity(); + } + else + { + account_id = objmgr.GetPlayerAccountIdByGUID(guid); + security = objmgr.GetSecurityByAccount(account_id); + } + + if(security >= m_session->GetSecurity()) + { + SendSysMessage(LANG_YOURS_SECURITY_IS_LOW); + SetSentErrorMessage(true); + return false; + } + + time_t mutetime = time(NULL) + notspeaktime*60; + + if (chr) + chr->GetSession()->m_muteTime = mutetime; + + loginDatabase.PExecute("UPDATE account SET mutetime = " I64FMTD " WHERE id = '%u'",uint64(mutetime), account_id ); + + if(chr) + ChatHandler(chr).PSendSysMessage(LANG_YOUR_CHAT_DISABLED, notspeaktime); + + PSendSysMessage(LANG_YOU_DISABLE_CHAT, cname.c_str(), notspeaktime); + + return true; +} + +//unmute player +bool ChatHandler::HandleUnmuteCommand(const char* args) +{ + if (!*args) + return false; + + char *charname = strtok((char*)args, " "); + if (!charname) + return false; + + std::string cname = charname; + + if(!normalizePlayerName(cname)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + uint64 guid = objmgr.GetPlayerGUIDByName(cname.c_str()); + if(!guid) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + Player *chr = objmgr.GetPlayer(guid); + + // check security + uint32 account_id = 0; + uint32 security = 0; + + if (chr) + { + account_id = chr->GetSession()->GetAccountId(); + security = chr->GetSession()->GetSecurity(); + } + else + { + account_id = objmgr.GetPlayerAccountIdByGUID(guid); + security = objmgr.GetSecurityByAccount(account_id); + } + + if(security >= m_session->GetSecurity()) + { + SendSysMessage(LANG_YOURS_SECURITY_IS_LOW); + SetSentErrorMessage(true); + return false; + } + + if (chr) + { + if(chr->CanSpeak()) + { + SendSysMessage(LANG_CHAT_ALREADY_ENABLED); + SetSentErrorMessage(true); + return false; + } + + chr->GetSession()->m_muteTime = 0; + } + + loginDatabase.PExecute("UPDATE account SET mutetime = '0' WHERE id = '%u'", account_id ); + + if(chr) + ChatHandler(chr).PSendSysMessage(LANG_YOUR_CHAT_ENABLED); + + PSendSysMessage(LANG_YOU_ENABLE_CHAT, cname.c_str()); + return true; +} + +bool ChatHandler::HandleTargetObjectCommand(const char* args) +{ + Player* pl = m_session->GetPlayer(); + QueryResult *result; + GameEvent::ActiveEvents const& activeEventsList = gameeventmgr.GetActiveEventList(); + if(*args) + { + int32 id = atoi((char*)args); + if(id) + result = WorldDatabase.PQuery("SELECT guid, id, position_x, position_y, position_z, orientation, map, (POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) AS order_ FROM gameobject WHERE map = '%i' AND id = '%u' ORDER BY order_ ASC LIMIT 1", + pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), pl->GetMapId(),id); + else + { + std::string name = args; + WorldDatabase.escape_string(name); + result = WorldDatabase.PQuery( + "SELECT guid, id, position_x, position_y, position_z, orientation, map, (POW(position_x - %f, 2) + POW(position_y - %f, 2) + POW(position_z - %f, 2)) AS order_ " + "FROM gameobject,gameobject_template WHERE gameobject_template.entry = gameobject.id AND map = %i AND name "_LIKE_" '""%%%s%%""' ORDER BY order_ ASC LIMIT 1", + pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), pl->GetMapId(),name.c_str()); + } + } + else + { + std::ostringstream eventFilter; + eventFilter << " AND (event IS NULL "; + bool initString = true; + + for (GameEvent::ActiveEvents::const_iterator itr = activeEventsList.begin(); itr != activeEventsList.end(); ++itr) + { + if (initString) + { + eventFilter << "OR event IN (" <<*itr; + initString =false; + } + else + eventFilter << "," << *itr; + } + + if (!initString) + eventFilter << "))"; + else + eventFilter << ")"; + + result = WorldDatabase.PQuery("SELECT gameobject.guid, id, position_x, position_y, position_z, orientation, map, " + "(POW(position_x - %f, 2) + POW(position_y - %f, 2) + POW(position_z - %f, 2)) AS order_ FROM gameobject " + "LEFT OUTER JOIN game_event_gameobject on gameobject.guid=game_event_gameobject.guid WHERE map = '%i' %s ORDER BY order_ ASC LIMIT 1", + m_session->GetPlayer()->GetPositionX(), m_session->GetPlayer()->GetPositionY(), m_session->GetPlayer()->GetPositionZ(), m_session->GetPlayer()->GetMapId(),eventFilter.str().c_str()); + } + + if (!result) + { + SendSysMessage(LANG_COMMAND_TARGETOBJNOTFOUND); + return true; + } + + Field *fields = result->Fetch(); + uint32 lowguid = fields[0].GetUInt32(); + uint32 id = fields[1].GetUInt32(); + float x = fields[2].GetFloat(); + float y = fields[3].GetFloat(); + float z = fields[4].GetFloat(); + float o = fields[5].GetFloat(); + int mapid = fields[6].GetUInt16(); + delete result; + + GameObjectInfo const* goI = objmgr.GetGameObjectInfo(id); + + if (!goI) + { + PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id); + return false; + } + + GameObject* target = ObjectAccessor::GetGameObject(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,id,HIGHGUID_GAMEOBJECT)); + + PSendSysMessage(LANG_GAMEOBJECT_DETAIL, lowguid, goI->name, lowguid, id, x, y, z, mapid, o); + + if(target) + { + int32 curRespawnDelay = target->GetRespawnTimeEx()-time(NULL); + if(curRespawnDelay < 0) + curRespawnDelay = 0; + + std::string curRespawnDelayStr = secsToTimeString(curRespawnDelay,true); + std::string defRespawnDelayStr = secsToTimeString(target->GetRespawnDelay(),true); + + PSendSysMessage(LANG_COMMAND_RAWPAWNTIMES, defRespawnDelayStr.c_str(),curRespawnDelayStr.c_str()); + } + return true; +} + +//teleport to gameobject +bool ChatHandler::HandleGoObjectCommand(const char* args) +{ + if(!*args) + return false; + + Player* _player = m_session->GetPlayer(); + + // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameobject"); + if(!cId) + return false; + + int32 guid = atoi(cId); + if(!guid) + return false; + + float x, y, z, ort; + int mapid; + + // by DB guid + if (GameObjectData const* go_data = objmgr.GetGOData(guid)) + { + x = go_data->posX; + y = go_data->posY; + z = go_data->posZ; + ort = go_data->orientation; + mapid = go_data->mapid; + } + else + { + SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND); + SetSentErrorMessage(true); + return false; + } + + if(!MapManager::IsValidMapCoord(mapid,x,y,z,ort)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if(_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->m_taxi.ClearTaxiDestinations(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + _player->TeleportTo(mapid, x, y, z, ort); + return true; +} + +bool ChatHandler::HandleGoTriggerCommand(const char* args) +{ + Player* _player = m_session->GetPlayer(); + + if (!*args) + return false; + + char *atId = strtok((char*)args, " "); + if (!atId) + return false; + + int32 i_atId = atoi(atId); + + if(!i_atId) + return false; + + AreaTriggerEntry const* at = sAreaTriggerStore.LookupEntry(i_atId); + if (!at) + { + PSendSysMessage(LANG_COMMAND_GOAREATRNOTFOUND,i_atId); + SetSentErrorMessage(true); + return false; + } + + if(!MapManager::IsValidMapCoord(at->mapid,at->x,at->y,at->z)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,at->x,at->y,at->mapid); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if(_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->m_taxi.ClearTaxiDestinations(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + _player->TeleportTo(at->mapid, at->x, at->y, at->z, _player->GetOrientation()); + return true; +} + +bool ChatHandler::HandleGoGraveyardCommand(const char* args) +{ + Player* _player = m_session->GetPlayer(); + + if (!*args) + return false; + + char *gyId = strtok((char*)args, " "); + if (!gyId) + return false; + + int32 i_gyId = atoi(gyId); + + if(!i_gyId) + return false; + + WorldSafeLocsEntry const* gy = sWorldSafeLocsStore.LookupEntry(i_gyId); + if (!gy) + { + PSendSysMessage(LANG_COMMAND_GRAVEYARDNOEXIST,i_gyId); + SetSentErrorMessage(true); + return false; + } + + if(!MapManager::IsValidMapCoord(gy->map_id,gy->x,gy->y,gy->z)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,gy->x,gy->y,gy->map_id); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if(_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->m_taxi.ClearTaxiDestinations(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + _player->TeleportTo(gy->map_id, gy->x, gy->y, gy->z, _player->GetOrientation()); + return true; +} + +/** \brief Teleport the GM to the specified creature + * + * .gocreature --> TP using creature.guid + * .gocreature azuregos --> TP player to the mob with this name + * Warning: If there is more than one mob with this name + * you will be teleported to the first one that is found. + * .gocreature id 6109 --> TP player to the mob, that has this creature_template.entry + * Warning: If there is more than one mob with this "id" + * you will be teleported to the first one that is found. + */ +//teleport to creature +bool ChatHandler::HandleGoCreatureCommand(const char* args) +{ + if(!*args) + return false; + Player* _player = m_session->GetPlayer(); + + // "id" or number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r + char* pParam1 = extractKeyFromLink((char*)args,"Hcreature"); + if (!pParam1) + return false; + + std::ostringstream whereClause; + + // User wants to teleport to the NPC's template entry + if( strcmp(pParam1, "id") == 0 ) + { + //sLog.outError("DEBUG: ID found"); + + // Get the "creature_template.entry" + // number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r + char* tail = strtok(NULL,""); + if(!tail) + return false; + char* cId = extractKeyFromLink(tail,"Hcreature_entry"); + if(!cId) + return false; + + int32 tEntry = atoi(cId); + //sLog.outError("DEBUG: ID value: %d", tEntry); + if(!tEntry) + return false; + + whereClause << "WHERE id = '" << tEntry << "'"; + } + else + { + //sLog.outError("DEBUG: ID *not found*"); + + int32 guid = atoi(pParam1); + + // Number is invalid - maybe the user specified the mob's name + if(!guid) + { + std::string name = pParam1; + WorldDatabase.escape_string(name); + whereClause << ", creature_template WHERE creature.id = creature_template.entry AND creature_template.name "_LIKE_" '" << name << "'"; + } + else + { + whereClause << "WHERE guid = '" << guid << "'"; + } + } + //sLog.outError("DEBUG: %s", whereClause.c_str()); + + QueryResult *result = WorldDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map FROM creature %s", whereClause.str().c_str() ); + if (!result) + { + SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND); + SetSentErrorMessage(true); + return false; + } + if( result->GetRowCount() > 1 ) + { + SendSysMessage(LANG_COMMAND_GOCREATMULTIPLE); + } + + Field *fields = result->Fetch(); + float x = fields[0].GetFloat(); + float y = fields[1].GetFloat(); + float z = fields[2].GetFloat(); + float ort = fields[3].GetFloat(); + int mapid = fields[4].GetUInt16(); + + delete result; + + if(!MapManager::IsValidMapCoord(mapid,x,y,z,ort)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if(_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->m_taxi.ClearTaxiDestinations(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + _player->TeleportTo(mapid, x, y, z, ort); + return true; +} + +bool ChatHandler::HandleGUIDCommand(const char* /*args*/) +{ + uint64 guid = m_session->GetPlayer()->GetSelection(); + + if (guid == 0) + { + SendSysMessage(LANG_NO_SELECTION); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_OBJECT_GUID, GUID_LOPART(guid), GUID_HIPART(guid)); + return true; +} + +bool ChatHandler::HandleLookupFactionCommand(const char* args) +{ + if(!*args) + return false; + + Player *target = getSelectedPlayer(); + if (!target) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + std::string namepart = args; + std::wstring wnamepart; + + if(!Utf8toWStr(namepart,wnamepart)) + return false; + + // converting string that we try to find to lower case + wstrToLower( wnamepart ); + + uint32 counter = 0; // Counter for figure out that we found smth. + + for (uint32 id = 0; id < sFactionStore.GetNumRows(); id++) + //for(FactionStateList::const_iterator itr = target->m_factions.begin(); itr != target->m_factions.end(); ++itr) + { + FactionEntry const *factionEntry = sFactionStore.LookupEntry(id); + //FactionEntry const *factionEntry = sFactionStore.LookupEntry(itr->second.ID); + if (factionEntry) + { + FactionStateList::const_iterator repItr = target->m_factions.find(factionEntry->reputationListID); + + int loc = m_session->GetSessionDbcLocale(); + std::string name = factionEntry->name[loc]; + if(name.empty()) + continue; + + if (!Utf8FitTo(name, wnamepart)) + { + loc = 0; + for(; loc < MAX_LOCALE; ++loc) + { + if(loc==m_session->GetSessionDbcLocale()) + continue; + + name = factionEntry->name[loc]; + if(name.empty()) + continue; + + if (Utf8FitTo(name, wnamepart)) + break; + } + } + + if(loc < MAX_LOCALE) + { + // send faction in "id - [faction] rank reputation [visible] [at war] [own team] [unknown] [invisible] [inactive]" format + // or "id - [faction] [no reputation]" format + std::ostringstream ss; + ss << id << " - |cffffffff|Hfaction:" << id << "|h[" << name << " " << localeNames[loc] << "]|h|r"; + + if (repItr != target->m_factions.end()) + { + ReputationRank rank = target->GetReputationRank(factionEntry); + std::string rankName = GetMangosString(ReputationRankStrIndex[rank]); + + ss << " " << rankName << "|h|r (" << target->GetReputation(factionEntry) << ")"; + + if(repItr->second.Flags & FACTION_FLAG_VISIBLE) + ss << GetMangosString(LANG_FACTION_VISIBLE); + if(repItr->second.Flags & FACTION_FLAG_AT_WAR) + ss << GetMangosString(LANG_FACTION_ATWAR); + if(repItr->second.Flags & FACTION_FLAG_PEACE_FORCED) + ss << GetMangosString(LANG_FACTION_PEACE_FORCED); + if(repItr->second.Flags & FACTION_FLAG_HIDDEN) + ss << GetMangosString(LANG_FACTION_HIDDEN); + if(repItr->second.Flags & FACTION_FLAG_INVISIBLE_FORCED) + ss << GetMangosString(LANG_FACTION_INVISIBLE_FORCED); + if(repItr->second.Flags & FACTION_FLAG_INACTIVE) + ss << GetMangosString(LANG_FACTION_INACTIVE); + } + else + ss << GetMangosString(LANG_FACTION_NOREPUTATION); + + SendSysMessage(ss.str().c_str()); + counter++; + } + } + } + + if (counter == 0) // if counter == 0 then we found nth + SendSysMessage(LANG_COMMAND_FACTION_NOTFOUND); + return true; +} + +bool ChatHandler::HandleModifyRepCommand(const char * args) +{ + if (!*args) return false; + + Player* target = NULL; + target = getSelectedPlayer(); + + if(!target) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + char* factionTxt = extractKeyFromLink((char*)args,"Hfaction"); + if(!factionTxt) + return false; + + uint32 factionId = atoi(factionTxt); + + int32 amount = 0; + char *rankTxt = strtok(NULL, " "); + if (!factionTxt || !rankTxt) + return false; + + amount = atoi(rankTxt); + if ((amount == 0) && (rankTxt[0] != '-') && !isdigit(rankTxt[0])) + { + std::string rankStr = rankTxt; + std::wstring wrankStr; + if(!Utf8toWStr(rankStr,wrankStr)) + return false; + wstrToLower( wrankStr ); + + int r = 0; + amount = -42000; + for (; r < MAX_REPUTATION_RANK; ++r) + { + std::string rank = GetMangosString(ReputationRankStrIndex[r]); + if(rank.empty()) + continue; + + std::wstring wrank; + if(!Utf8toWStr(rank,wrank)) + continue; + + wstrToLower(wrank); + + if(wrank.substr(0,wrankStr.size())==wrankStr) + { + char *deltaTxt = strtok(NULL, " "); + if (deltaTxt) + { + int32 delta = atoi(deltaTxt); + if ((delta < 0) || (delta > Player::ReputationRank_Length[r] -1)) + { + PSendSysMessage(LANG_COMMAND_FACTION_DELTA, (Player::ReputationRank_Length[r]-1)); + SetSentErrorMessage(true); + return false; + } + amount += delta; + } + break; + } + amount += Player::ReputationRank_Length[r]; + } + if (r >= MAX_REPUTATION_RANK) + { + PSendSysMessage(LANG_COMMAND_FACTION_INVPARAM, rankTxt); + SetSentErrorMessage(true); + return false; + } + } + + FactionEntry const *factionEntry = sFactionStore.LookupEntry(factionId); + + if (!factionEntry) + { + PSendSysMessage(LANG_COMMAND_FACTION_UNKNOWN, factionId); + SetSentErrorMessage(true); + return false; + } + + if (factionEntry->reputationListID < 0) + { + PSendSysMessage(LANG_COMMAND_FACTION_NOREP_ERROR, factionEntry->name[m_session->GetSessionDbcLocale()], factionId); + SetSentErrorMessage(true); + return false; + } + + target->SetFactionReputation(factionEntry,amount); + PSendSysMessage(LANG_COMMAND_MODIFY_REP, factionEntry->name[m_session->GetSessionDbcLocale()], factionId, target->GetName(), target->GetReputation(factionId)); + return true; +} + +bool ChatHandler::HandleNameCommand(const char* args) +{ + /* Temp. disabled + if(!*args) + return false; + + if(strlen((char*)args)>75) + { + PSendSysMessage(LANG_TOO_LONG_NAME, strlen((char*)args)-75); + return true; + } + + for (uint8 i = 0; i < strlen(args); i++) + { + if(!isalpha(args[i]) && args[i]!=' ') + { + SendSysMessage(LANG_CHARS_ONLY); + return false; + } + } + + uint64 guid; + guid = m_session->GetPlayer()->GetSelection(); + if (guid == 0) + { + SendSysMessage(LANG_NO_SELECTION); + return true; + } + + Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid); + + if(!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + return true; + } + + pCreature->SetName(args); + uint32 idname = objmgr.AddCreatureTemplate(pCreature->GetName()); + pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname); + + pCreature->SaveToDB(); + */ + + return true; +} + +bool ChatHandler::HandleSubNameCommand(const char* /*args*/) +{ + /* Temp. disabled + + if(!*args) + args = ""; + + if(strlen((char*)args)>75) + { + + PSendSysMessage(LANG_TOO_LONG_SUBNAME, strlen((char*)args)-75); + return true; + } + + for (uint8 i = 0; i < strlen(args); i++) + { + if(!isalpha(args[i]) && args[i]!=' ') + { + SendSysMessage(LANG_CHARS_ONLY); + return false; + } + } + uint64 guid; + guid = m_session->GetPlayer()->GetSelection(); + if (guid == 0) + { + SendSysMessage(LANG_NO_SELECTION); + return true; + } + + Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid); + + if(!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + return true; + } + + uint32 idname = objmgr.AddCreatureSubName(pCreature->GetName(),args,pCreature->GetUInt32Value(UNIT_FIELD_DISPLAYID)); + pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname); + + pCreature->SaveToDB(); + */ + return true; +} + +//move item to other slot +bool ChatHandler::HandleItemMoveCommand(const char* args) +{ + if(!*args) + return false; + uint8 srcslot, dstslot; + + char* pParam1 = strtok((char*)args, " "); + if (!pParam1) + return false; + + char* pParam2 = strtok(NULL, " "); + if (!pParam2) + return false; + + srcslot = (uint8)atoi(pParam1); + dstslot = (uint8)atoi(pParam2); + + uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot); + uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot); + + if(srcslot==dstslot) + return true; + + m_session->GetPlayer()->SwapItem( src, dst ); + + return true; +} + +//add spawn of creature +bool ChatHandler::HandleAddSpwCommand(const char* args) +{ + if(!*args) + return false; + char* charID = strtok((char*)args, " "); + if (!charID) + return false; + + char* team = strtok(NULL, " "); + int32 teamval = 0; + if (team) { teamval = atoi(team); } + if (teamval < 0) { teamval = 0; } + + uint32 id = atoi(charID); + + Player *chr = m_session->GetPlayer(); + float x = chr->GetPositionX(); + float y = chr->GetPositionY(); + float z = chr->GetPositionZ(); + float o = chr->GetOrientation(); + Map *map = chr->GetMap(); + + Creature* pCreature = new Creature; + if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, id, (uint32)teamval)) + { + delete pCreature; + return false; + } + + pCreature->Relocate(x,y,z,o); + + if(!pCreature->IsPositionValid()) + { + sLog.outError("ERROR: Creature (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",pCreature->GetGUIDLow(),pCreature->GetEntry(),pCreature->GetPositionX(),pCreature->GetPositionY()); + delete pCreature; + return false; + } + + pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode())); + + uint32 db_guid = pCreature->GetDBTableGUIDLow(); + + // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); + pCreature->LoadFromDB(db_guid, map); + + map->Add(pCreature); + objmgr.AddCreatureToGrid(db_guid, objmgr.GetCreatureData(db_guid)); + return true; +} + +bool ChatHandler::HandleDelCreatureCommand(const char* args) +{ + Creature* unit = NULL; + + if(*args) + { + // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hcreature"); + if(!cId) + return false; + + uint32 lowguid = atoi(cId); + if(!lowguid) + return false; + + if (CreatureData const* cr_data = objmgr.GetCreatureData(lowguid)) + unit = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, cr_data->id, HIGHGUID_UNIT)); + } + else + unit = getSelectedCreature(); + + if(!unit || unit->isPet() || unit->isTotem()) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + // Delete the creature + unit->CombatStop(); + unit->DeleteFromDB(); + unit->CleanupsBeforeDelete(); + unit->AddObjectToRemoveList(); + + SendSysMessage(LANG_COMMAND_DELCREATMESSAGE); + + return true; +} + +//delete object by selection or guid +bool ChatHandler::HandleDelObjectCommand(const char* args) +{ + // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameobject"); + if(!cId) + return false; + + uint32 lowguid = atoi(cId); + if(!lowguid) + return false; + + GameObject* obj = NULL; + + // by DB guid + if (GameObjectData const* go_data = objmgr.GetGOData(lowguid)) + obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id); + + if(!obj) + { + PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + uint64 owner_guid = obj->GetOwnerGUID(); + if(owner_guid) + { + Unit* owner = ObjectAccessor::GetUnit(*m_session->GetPlayer(),owner_guid); + if(!owner && !IS_PLAYER_GUID(owner_guid)) + { + PSendSysMessage(LANG_COMMAND_DELOBJREFERCREATURE, GUID_LOPART(owner_guid), obj->GetGUIDLow()); + SetSentErrorMessage(true); + return false; + } + + owner->RemoveGameObject(obj,false); + } + + obj->SetRespawnTime(0); // not save respawn time + obj->Delete(); + obj->DeleteFromDB(); + + PSendSysMessage(LANG_COMMAND_DELOBJMESSAGE, obj->GetGUIDLow()); + + return true; +} + +//turn selected object +bool ChatHandler::HandleTurnObjectCommand(const char* args) +{ + // number or [name] Shift-click form |color|Hgameobject:go_id|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameobject"); + if(!cId) + return false; + + uint32 lowguid = atoi(cId); + if(!lowguid) + return false; + + GameObject* obj = NULL; + + // by DB guid + if (GameObjectData const* go_data = objmgr.GetGOData(lowguid)) + obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id); + + if(!obj) + { + PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + char* po = strtok(NULL, " "); + float o; + + if (po) + { + o = (float)atof(po); + } + else + { + Player *chr = m_session->GetPlayer(); + o = chr->GetOrientation(); + } + + float rot2 = sin(o/2); + float rot3 = cos(o/2); + + Map* map = MapManager::Instance().GetMap(obj->GetMapId(),obj); + map->Remove(obj,false); + + obj->Relocate(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), o); + + obj->SetFloatValue(GAMEOBJECT_FACING, o); + obj->SetFloatValue(GAMEOBJECT_ROTATION+2, rot2); + obj->SetFloatValue(GAMEOBJECT_ROTATION+3, rot3); + + map->Add(obj); + + obj->SaveToDB(); + obj->Refresh(); + + PSendSysMessage(LANG_COMMAND_TURNOBJMESSAGE, obj->GetGUIDLow(), o); + + return true; +} + +//move selected creature +bool ChatHandler::HandleMoveCreatureCommand(const char* args) +{ + uint32 lowguid = 0; + + Creature* pCreature = getSelectedCreature(); + + if(!pCreature) + { + // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hcreature"); + if(!cId) + return false; + + uint32 lowguid = atoi(cId); + + /* FIXME: impossibel without entry + if(lowguid) + pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT)); + */ + + // Attempting creature load from DB data + if(!pCreature) + { + CreatureData const* data = objmgr.GetCreatureData(lowguid); + if(!data) + { + PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + uint32 map_id = data->mapid; + + if(m_session->GetPlayer()->GetMapId()!=map_id) + { + PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid); + SetSentErrorMessage(true); + return false; + } + } + else + { + lowguid = pCreature->GetDBTableGUIDLow(); + } + } + else + { + lowguid = pCreature->GetDBTableGUIDLow(); + } + + float x = m_session->GetPlayer()->GetPositionX(); + float y = m_session->GetPlayer()->GetPositionY(); + float z = m_session->GetPlayer()->GetPositionZ(); + float o = m_session->GetPlayer()->GetOrientation(); + + if (pCreature) + { + if(CreatureData const* data = objmgr.GetCreatureData(pCreature->GetDBTableGUIDLow())) + { + const_cast(data)->posX = x; + const_cast(data)->posY = y; + const_cast(data)->posZ = z; + const_cast(data)->orientation = o; + } + MapManager::Instance().GetMap(pCreature->GetMapId(),pCreature)->CreatureRelocation(pCreature,x, y, z,o); + pCreature->GetMotionMaster()->Initialize(); + if(pCreature->isAlive()) // dead creature will reset movement generator at respawn + { + pCreature->setDeathState(JUST_DIED); + pCreature->Respawn(); + } + } + + WorldDatabase.PExecuteLog("UPDATE creature SET position_x = '%f', position_y = '%f', position_z = '%f', orientation = '%f' WHERE guid = '%u'", x, y, z, o, lowguid); + PSendSysMessage(LANG_COMMAND_CREATUREMOVED); + return true; +} + +//move selected object +bool ChatHandler::HandleMoveObjectCommand(const char* args) +{ + // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameobject"); + if(!cId) + return false; + + uint32 lowguid = atoi(cId); + if(!lowguid) + return false; + + GameObject* obj = NULL; + + // by DB guid + if (GameObjectData const* go_data = objmgr.GetGOData(lowguid)) + obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id); + + if(!obj) + { + PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + char* px = strtok(NULL, " "); + char* py = strtok(NULL, " "); + char* pz = strtok(NULL, " "); + + if (!px) + { + Player *chr = m_session->GetPlayer(); + + Map* map = MapManager::Instance().GetMap(obj->GetMapId(),obj); + map->Remove(obj,false); + + obj->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), obj->GetOrientation()); + obj->SetFloatValue(GAMEOBJECT_POS_X, chr->GetPositionX()); + obj->SetFloatValue(GAMEOBJECT_POS_Y, chr->GetPositionY()); + obj->SetFloatValue(GAMEOBJECT_POS_Z, chr->GetPositionZ()); + + map->Add(obj); + } + else + { + if(!py || !pz) + return false; + + float x = (float)atof(px); + float y = (float)atof(py); + float z = (float)atof(pz); + + if(!MapManager::IsValidMapCoord(obj->GetMapId(),x,y,z)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,obj->GetMapId()); + SetSentErrorMessage(true); + return false; + } + + Map* map = MapManager::Instance().GetMap(obj->GetMapId(),obj); + map->Remove(obj,false); + + obj->Relocate(x, y, z, obj->GetOrientation()); + obj->SetFloatValue(GAMEOBJECT_POS_X, x); + obj->SetFloatValue(GAMEOBJECT_POS_Y, y); + obj->SetFloatValue(GAMEOBJECT_POS_Z, z); + + map->Add(obj); + } + + obj->SaveToDB(); + obj->Refresh(); + + PSendSysMessage(LANG_COMMAND_MOVEOBJMESSAGE, obj->GetGUIDLow()); + + return true; +} + +//demorph player or unit +bool ChatHandler::HandleDeMorphCommand(const char* /*args*/) +{ + Unit *target = getSelectedUnit(); + if(!target) + target = m_session->GetPlayer(); + + target->DeMorph(); + + return true; +} + +//add item in vendorlist +bool ChatHandler::HandleAddVendorItemCommand(const char* args) +{ + if (!*args) + return false; + + Creature* vendor = getSelectedCreature(); + if (!vendor || !vendor->isVendor()) + { + SendSysMessage(LANG_COMMAND_VENDORSELECTION); + SetSentErrorMessage(true); + return false; + } + + char* pitem = extractKeyFromLink((char*)args,"Hitem"); + if (!pitem) + { + SendSysMessage(LANG_COMMAND_NEEDITEMSEND); + SetSentErrorMessage(true); + return false; + } + uint32 itemId = atol(pitem); + + char* fmaxcount = strtok(NULL, " "); //add maxcount, default: 0 + uint32 maxcount = 0; + if (fmaxcount) + maxcount = atol(fmaxcount); + + char* fincrtime = strtok(NULL, " "); //add incrtime, default: 0 + uint32 incrtime = 0; + if (fincrtime) + incrtime = atol(fincrtime); + + char* fextendedcost = strtok(NULL, " "); //add ExtendedCost, default: 0 + uint32 extendedcost = fextendedcost ? atol(fextendedcost) : 0; + + ItemPrototype const *pProto = objmgr.GetItemPrototype(itemId); + if(!pProto) + { + PSendSysMessage(LANG_ITEM_NOT_FOUND, itemId); + SetSentErrorMessage(true); + return false; + } + + if(extendedcost && !sItemExtendedCostStore.LookupEntry(extendedcost)) + { + PSendSysMessage(LANG_BAD_VALUE, extendedcost); + SetSentErrorMessage(true); + return false; + } + + // load vendor items if not yet + vendor->LoadGoods(); + + if(vendor->FindItem(itemId)) + { + PSendSysMessage(LANG_ITEM_ALREADY_IN_LIST,itemId); + SetSentErrorMessage(true); + return false; + } + + if (vendor->GetItemCount() >= MAX_VENDOR_ITEMS) + { + SendSysMessage(LANG_COMMAND_ADDVENDORITEMITEMS); + SetSentErrorMessage(true); + return false; + } + + // add to DB and to current ingame vendor + WorldDatabase.PExecuteLog("INSERT INTO npc_vendor (entry,item,maxcount,incrtime,extendedcost) VALUES('%u','%u','%u','%u','%u')",vendor->GetEntry(), itemId, maxcount,incrtime,extendedcost); + vendor->AddItem(itemId,maxcount,incrtime,extendedcost); + PSendSysMessage(LANG_ITEM_ADDED_TO_LIST,itemId,pProto->Name1,maxcount,incrtime,extendedcost); + return true; +} + +//del item from vendor list +bool ChatHandler::HandleDelVendorItemCommand(const char* args) +{ + if (!*args) + return false; + + Creature* vendor = getSelectedCreature(); + if (!vendor || !vendor->isVendor()) + { + SendSysMessage(LANG_COMMAND_VENDORSELECTION); + SetSentErrorMessage(true); + return false; + } + + char* pitem = extractKeyFromLink((char*)args,"Hitem"); + if (!pitem) + { + SendSysMessage(LANG_COMMAND_NEEDITEMSEND); + SetSentErrorMessage(true); + return false; + } + uint32 itemId = atol(pitem); + + ItemPrototype const *pProto = objmgr.GetItemPrototype(itemId); + if(!pProto) + { + PSendSysMessage(LANG_ITEM_NOT_FOUND, itemId); + SetSentErrorMessage(true); + return false; + } + + // load vendor items if not yet + vendor->LoadGoods(); + + if (!vendor->RemoveItem(itemId)) + { + PSendSysMessage(LANG_ITEM_NOT_IN_LIST,itemId); + SetSentErrorMessage(true); + return false; + } + + WorldDatabase.PExecuteLog("DELETE FROM npc_vendor WHERE entry='%u' AND item='%u'",vendor->GetEntry(), itemId); + PSendSysMessage(LANG_ITEM_DELETED_FROM_LIST,itemId,pProto->Name1); + return true; +} + +//add move for creature +bool ChatHandler::HandleAddMoveCommand(const char* args) +{ + if(!*args) + return false; + + char* guid_str = strtok((char*)args, " "); + char* wait_str = strtok((char*)NULL, " "); + + uint32 lowguid = atoi((char*)guid_str); + + Creature* pCreature = NULL; + + /* FIXME: impossible without entry + if(lowguid) + pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT)); + */ + + // attempt check creature existence by DB data + if(!pCreature) + { + CreatureData const* data = objmgr.GetCreatureData(lowguid); + if(!data) + { + PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + } + else + { + // obtain real GUID for DB operations + lowguid = pCreature->GetDBTableGUIDLow(); + } + + int wait = wait_str ? atoi(wait_str) : 0; + + if(wait < 0) + wait = 0; + + Player* player = m_session->GetPlayer(); + + WaypointMgr.AddLastNode(lowguid, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), wait, 0); + + // update movement type + WorldDatabase.PExecuteLog("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid); + if(pCreature) + { + pCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE); + pCreature->GetMotionMaster()->Initialize(); + if(pCreature->isAlive()) // dead creature will reset movement generator at respawn + { + pCreature->setDeathState(JUST_DIED); + pCreature->Respawn(); + } + pCreature->SaveToDB(); + } + + SendSysMessage(LANG_WAYPOINT_ADDED); + + return true; +} + +/** + * Set the movement type for an NPC.
+ *
+ * Valid movement types are: + *
    + *
  • stay - NPC wont move
  • + *
  • random - NPC will move randomly according to the spawndist
  • + *
  • way - NPC will move with given waypoints set
  • + *
+ * additional parameter: NODEL - so no waypoints are deleted, if you + * change the movement type + */ +bool ChatHandler::HandleSetMoveTypeCommand(const char* args) +{ + if(!*args) + return false; + + // 3 arguments: + // GUID (optional - you can also select the creature) + // stay|random|way (determines the kind of movement) + // NODEL (optional - tells the system NOT to delete any waypoints) + // this is very handy if you want to do waypoints, that are + // later switched on/off according to special events (like escort + // quests, etc) + char* guid_str = strtok((char*)args, " "); + char* type_str = strtok((char*)NULL, " "); + char* dontdel_str = strtok((char*)NULL, " "); + + bool doNotDelete = false; + + if(!guid_str) + return false; + + uint32 lowguid = 0; + Creature* pCreature = NULL; + + if( dontdel_str ) + { + //sLog.outError("DEBUG: All 3 params are set"); + + // All 3 params are set + // GUID + // type + // doNotDEL + if( stricmp( dontdel_str, "NODEL" ) == 0 ) + { + //sLog.outError("DEBUG: doNotDelete = true;"); + doNotDelete = true; + } + } + else + { + // Only 2 params - but maybe NODEL is set + if( type_str ) + { + sLog.outError("DEBUG: Only 2 params "); + if( stricmp( type_str, "NODEL" ) == 0 ) + { + //sLog.outError("DEBUG: type_str, NODEL "); + doNotDelete = true; + type_str = NULL; + } + } + } + + if(!type_str) // case .setmovetype $move_type (with selected creature) + { + type_str = guid_str; + pCreature = getSelectedCreature(); + if(!pCreature) + return false; + lowguid = pCreature->GetDBTableGUIDLow(); + } + else // case .setmovetype #creature_guid $move_type (with selected creature) + { + lowguid = atoi((char*)guid_str); + + /* impossible without entry + if(lowguid) + pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT)); + */ + + // attempt check creature existence by DB data + if(!pCreature) + { + CreatureData const* data = objmgr.GetCreatureData(lowguid); + if(!data) + { + PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + } + else + { + lowguid = pCreature->GetDBTableGUIDLow(); + } + } + + // now lowguid is low guid really existed creature + // and pCreature point (maybe) to this creature or NULL + + MovementGeneratorType move_type; + + std::string type = type_str; + + if(type == "stay") + move_type = IDLE_MOTION_TYPE; + else if(type == "random") + move_type = RANDOM_MOTION_TYPE; + else if(type == "way") + move_type = WAYPOINT_MOTION_TYPE; + else + return false; + + // update movement type + if(doNotDelete == false) + WaypointMgr.DeletePath(lowguid); + + if(pCreature) + { + pCreature->SetDefaultMovementType(move_type); + pCreature->GetMotionMaster()->Initialize(); + if(pCreature->isAlive()) // dead creature will reset movement generator at respawn + { + pCreature->setDeathState(JUST_DIED); + pCreature->Respawn(); + } + pCreature->SaveToDB(); + } + if( doNotDelete == false ) + { + PSendSysMessage(LANG_MOVE_TYPE_SET,type_str); + } + else + { + PSendSysMessage(LANG_MOVE_TYPE_SET_NODEL,type_str); + } + + return true; +} // HandleSetMoveTypeCommand + +//change level of creature or pet +bool ChatHandler::HandleChangeLevelCommand(const char* args) +{ + if (!*args) + return false; + + uint8 lvl = (uint8) atoi((char*)args); + if ( lvl < 1 || lvl > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) + 3) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Creature* pCreature = getSelectedCreature(); + if(!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if(pCreature->isPet()) + { + ((Pet*)pCreature)->GivePetLevel(lvl); + } + else + { + pCreature->SetMaxHealth( 100 + 30*lvl); + pCreature->SetHealth( 100 + 30*lvl); + pCreature->SetLevel( lvl); + pCreature->SaveToDB(); + } + + return true; +} + +//set npcflag of creature +bool ChatHandler::HandleNPCFlagCommand(const char* args) +{ + if (!*args) + return false; + + uint32 npcFlags = (uint32) atoi((char*)args); + + Creature* pCreature = getSelectedCreature(); + + if(!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + pCreature->SetUInt32Value(UNIT_NPC_FLAGS, npcFlags); + + WorldDatabase.PExecuteLog("UPDATE creature_template SET npcflag = '%u' WHERE entry = '%u'", npcFlags, pCreature->GetEntry()); + + SendSysMessage(LANG_VALUE_SAVED_REJOIN); + + return true; +} + +//set model of creature +bool ChatHandler::HandleSetModelCommand(const char* args) +{ + if (!*args) + return false; + + uint32 displayId = (uint32) atoi((char*)args); + + Creature *pCreature = getSelectedCreature(); + + if(!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + pCreature->SetDisplayId(displayId); + pCreature->SetNativeDisplayId(displayId); + + pCreature->SaveToDB(); + + return true; +} + +//morph creature or player +bool ChatHandler::HandleMorphCommand(const char* args) +{ + if (!*args) + return false; + + uint16 display_id = (uint16)atoi((char*)args); + + Unit *target = getSelectedUnit(); + if(!target) + target = m_session->GetPlayer(); + + target->SetDisplayId(display_id); + + return true; +} + +//set faction of creature or go +bool ChatHandler::HandleFactionIdCommand(const char* args) +{ + if (!*args) + return false; + + uint32 factionId = (uint32) atoi((char*)args); + + if (!sFactionTemplateStore.LookupEntry(factionId)) + { + PSendSysMessage(LANG_WRONG_FACTION, factionId); + SetSentErrorMessage(true); + return false; + } + + Creature* pCreature = getSelectedCreature(); + + if(!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + pCreature->setFaction(factionId); + + // faction is set in creature_template - not inside creature + + // update in memory + if(CreatureInfo const *cinfo = pCreature->GetCreatureInfo()) + { + const_cast(cinfo)->faction_A = factionId; + const_cast(cinfo)->faction_H = factionId; + } + + // and DB + WorldDatabase.PExecuteLog("UPDATE creature_template SET faction_A = '%u', faction_H = '%u' WHERE entry = '%u'", factionId, factionId, pCreature->GetEntry()); + + return true; +} + +//kick player +bool ChatHandler::HandleKickPlayerCommand(const char *args) +{ + char* kickName = strtok((char*)args, " "); + if (!kickName) + { + Player* player = getSelectedPlayer(); + + if(!player) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + if(player==m_session->GetPlayer()) + { + SendSysMessage(LANG_COMMAND_KICKSELF); + SetSentErrorMessage(true); + return false; + } + + player->GetSession()->KickPlayer(); + } + else + { + std::string name = kickName; + if(!normalizePlayerName(name)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + if(name==m_session->GetPlayer()->GetName()) + { + SendSysMessage(LANG_COMMAND_KICKSELF); + SetSentErrorMessage(true); + return false; + } + + if(sWorld.KickPlayer(name)) + { + PSendSysMessage(LANG_COMMAND_KICKMESSAGE,name.c_str()); + } + else + PSendSysMessage(LANG_COMMAND_KICKNOTFOUNDPLAYER,name.c_str()); + } + + return true; +} + +//show info of player +bool ChatHandler::HandlePInfoCommand(const char* args) +{ + Player* target = NULL; + uint64 targetGUID = 0; + + char* px = strtok((char*)args, " "); + char* py = NULL; + + std::string name; + + if (px) + { + name = px; + + if(name.empty()) + return false; + + if(!normalizePlayerName(name)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + target = objmgr.GetPlayer(name.c_str()); + if (target) + py = strtok(NULL, " "); + else + { + targetGUID = objmgr.GetPlayerGUIDByName(name); + if(targetGUID) + py = strtok(NULL, " "); + else + py = px; + } + } + + if(!target && !targetGUID) + { + target = getSelectedPlayer(); + } + + if(!target && !targetGUID) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + uint32 accId = 0; + uint32 money = 0; + uint32 total_player_time = 0; + uint32 level = 0; + uint32 latency = 0; + + // get additional information from Player object + if(target) + { + targetGUID = target->GetGUID(); + name = target->GetName(); // re-read for case getSelectedPlayer() target + accId = target->GetSession()->GetAccountId(); + money = target->GetMoney(); + total_player_time = target->GetTotalPlayedTime(); + level = target->getLevel(); + latency = target->GetSession()->GetLatency(); + } + // get additional information from DB + else + { + accId = objmgr.GetPlayerAccountIdByGUID(targetGUID); + Player plr(m_session); // use current session for temporary load + plr.MinimalLoadFromDB(NULL, targetGUID); + money = plr.GetMoney(); + total_player_time = plr.GetTotalPlayedTime(); + level = plr.getLevel(); + } + + std::string username = GetMangosString(LANG_ERROR); + std::string last_ip = GetMangosString(LANG_ERROR); + uint32 security = 0; + std::string last_login = GetMangosString(LANG_ERROR); + + QueryResult* result = loginDatabase.PQuery("SELECT username,gmlevel,last_ip,last_login FROM account WHERE id = '%u'",accId); + if(result) + { + Field* fields = result->Fetch(); + username = fields[0].GetCppString(); + security = fields[1].GetUInt32(); + if(m_session->GetSecurity() >= security) + { + last_ip = fields[2].GetCppString(); + last_login = fields[3].GetCppString(); + } + else + { + last_ip = "-"; + last_login = "-"; + } + + delete result; + } + + PSendSysMessage(LANG_PINFO_ACCOUNT, (target?"":GetMangosString(LANG_OFFLINE)), name.c_str(), GUID_LOPART(targetGUID), username.c_str(), accId, security, last_ip.c_str(), last_login.c_str(), latency); + + std::string timeStr = secsToTimeString(total_player_time,true,true); + uint32 gold = money /GOLD; + uint32 silv = (money % GOLD) / SILVER; + uint32 copp = (money % GOLD) % SILVER; + PSendSysMessage(LANG_PINFO_LEVEL, timeStr.c_str(), level, gold,silv,copp ); + + if ( py && strncmp(py, "rep", 3) == 0 ) + { + if(!target) + { + // rep option not implemented for offline case + SendSysMessage(LANG_PINFO_NO_REP); + SetSentErrorMessage(true); + return false; + } + + char* FactionName; + for(FactionStateList::const_iterator itr = target->m_factions.begin(); itr != target->m_factions.end(); ++itr) + { + FactionEntry const *factionEntry = sFactionStore.LookupEntry(itr->second.ID); + if (factionEntry) + FactionName = factionEntry->name[m_session->GetSessionDbcLocale()]; + else + FactionName = "#Not found#"; + ReputationRank rank = target->GetReputationRank(factionEntry); + std::string rankName = GetMangosString(ReputationRankStrIndex[rank]); + std::ostringstream ss; + ss << itr->second.ID << ": |cffffffff|Hfaction:" << itr->second.ID << "|h[" << FactionName << "]|h|r " << rankName << "|h|r (" << target->GetReputation(factionEntry) << ")"; + + if(itr->second.Flags & FACTION_FLAG_VISIBLE) + ss << GetMangosString(LANG_FACTION_VISIBLE); + if(itr->second.Flags & FACTION_FLAG_AT_WAR) + ss << GetMangosString(LANG_FACTION_ATWAR); + if(itr->second.Flags & FACTION_FLAG_PEACE_FORCED) + ss << GetMangosString(LANG_FACTION_PEACE_FORCED); + if(itr->second.Flags & FACTION_FLAG_HIDDEN) + ss << GetMangosString(LANG_FACTION_HIDDEN); + if(itr->second.Flags & FACTION_FLAG_INVISIBLE_FORCED) + ss << GetMangosString(LANG_FACTION_INVISIBLE_FORCED); + if(itr->second.Flags & FACTION_FLAG_INACTIVE) + ss << GetMangosString(LANG_FACTION_INACTIVE); + + SendSysMessage(ss.str().c_str()); + } + } + return true; +} + +//show tickets +void ChatHandler::ShowTicket(uint64 guid, char const* text, char const* time) +{ + std::string name; + if(!objmgr.GetPlayerNameByGUID(guid,name)) + name = GetMangosString(LANG_UNKNOWN); + + PSendSysMessage(LANG_COMMAND_TICKETVIEW, name.c_str(),time,text); +} + +//ticket commands +bool ChatHandler::HandleTicketCommand(const char* args) +{ + char* px = strtok((char*)args, " "); + + // ticket + if (!px) + { + size_t count; + QueryResult *result = CharacterDatabase.Query("SELECT COUNT(ticket_id) FROM character_ticket"); + if(result) + { + count = (*result)[0].GetUInt32(); + delete result; + } + else + count = 0; + + PSendSysMessage(LANG_COMMAND_TICKETCOUNT, count, m_session->GetPlayer()->isAcceptTickets() ? GetMangosString(LANG_ON) : GetMangosString(LANG_OFF)); + return true; + } + + // ticket on + if(strncmp(px,"on",3) == 0) + { + m_session->GetPlayer()->SetAcceptTicket(true); + SendSysMessage(LANG_COMMAND_TICKETON); + return true; + } + + // ticket off + if(strncmp(px,"off",4) == 0) + { + m_session->GetPlayer()->SetAcceptTicket(false); + SendSysMessage(LANG_COMMAND_TICKETOFF); + return true; + } + + // ticket #num + int num = atoi(px); + if(num > 0) + { + QueryResult *result = CharacterDatabase.PQuery("SELECT guid,ticket_text,ticket_lastchange FROM character_ticket ORDER BY ticket_id ASC LIMIT %d,1",num-1); + + if(!result) + { + PSendSysMessage(LANG_COMMAND_TICKENOTEXIST, num); + delete result; + SetSentErrorMessage(true); + return false; + } + + Field* fields = result->Fetch(); + + uint64 guid = fields[0].GetUInt64(); + char const* text = fields[1].GetString(); + char const* time = fields[2].GetString(); + + ShowTicket(guid,text,time); + delete result; + return true; + } + + std::string name = px; + + if(!normalizePlayerName(name)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + uint64 guid = objmgr.GetPlayerGUIDByName(name); + + if(!guid) + return false; + + // ticket $char_name + QueryResult *result = CharacterDatabase.PQuery("SELECT ticket_text,ticket_lastchange FROM character_ticket WHERE guid = '%u' ORDER BY ticket_id ASC",GUID_LOPART(guid)); + + if(!result) + return false; + + Field* fields = result->Fetch(); + + char const* text = fields[0].GetString(); + char const* time = fields[1].GetString(); + + ShowTicket(guid,text,time); + delete result; + + return true; +} + +uint32 ChatHandler::GetTicketIDByNum(uint32 num) +{ + QueryResult *result = CharacterDatabase.Query("SELECT ticket_id FROM character_ticket"); + + if(!result || num > result->GetRowCount()) + { + PSendSysMessage(LANG_COMMAND_TICKENOTEXIST, num); + delete result; + return 0; + } + + for(uint32 i = 1; i < num; ++i) + result->NextRow(); + + Field* fields = result->Fetch(); + + uint32 id = fields[0].GetUInt32(); + delete result; + return id; +} + +//dell all tickets +bool ChatHandler::HandleDelTicketCommand(const char *args) +{ + char* px = strtok((char*)args, " "); + if (!px) + return false; + + // delticket all + if(strncmp(px,"all",4) == 0) + { + QueryResult *result = CharacterDatabase.Query("SELECT guid FROM character_ticket"); + + if(!result) + return true; + + // notify players about ticket deleting + do + { + Field* fields = result->Fetch(); + + uint64 guid = fields[0].GetUInt64(); + + if(Player* sender = objmgr.GetPlayer(guid)) + sender->GetSession()->SendGMTicketGetTicket(0x0A,0); + + }while(result->NextRow()); + + delete result; + + CharacterDatabase.PExecute("DELETE FROM character_ticket"); + SendSysMessage(LANG_COMMAND_ALLTICKETDELETED); + return true; + } + + int num = (uint32)atoi(px); + + // delticket #num + if(num > 0) + { + QueryResult *result = CharacterDatabase.PQuery("SELECT ticket_id,guid FROM character_ticket LIMIT %i",num); + + if(!result || uint64(num) > result->GetRowCount()) + { + PSendSysMessage(LANG_COMMAND_TICKENOTEXIST, num); + delete result; + SetSentErrorMessage(true); + return false; + } + + for(int i = 1; i < num; ++i) + result->NextRow(); + + Field* fields = result->Fetch(); + + uint32 id = fields[0].GetUInt32(); + uint64 guid = fields[1].GetUInt64(); + delete result; + + CharacterDatabase.PExecute("DELETE FROM character_ticket WHERE ticket_id = '%u'", id); + + // notify players about ticket deleting + if(Player* sender = objmgr.GetPlayer(guid)) + { + sender->GetSession()->SendGMTicketGetTicket(0x0A,0); + PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL,sender->GetName()); + } + else + SendSysMessage(LANG_COMMAND_TICKETDEL); + + return true; + } + + std::string name = px; + + if(!normalizePlayerName(name)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + uint64 guid = objmgr.GetPlayerGUIDByName(name); + + if(!guid) + return false; + + // delticket $char_name + CharacterDatabase.PExecute("DELETE FROM character_ticket WHERE guid = '%u'",GUID_LOPART(guid)); + + // notify players about ticket deleting + if(Player* sender = objmgr.GetPlayer(guid)) + sender->GetSession()->SendGMTicketGetTicket(0x0A,0); + + PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL,px); + return true; +} + +//set spawn dist of creature +bool ChatHandler::HandleSpawnDistCommand(const char* args) +{ + if(!*args) + return false; + + float option = atof((char*)args); + if (option < 0.0f) + { + SendSysMessage(LANG_BAD_VALUE); + return false; + } + + MovementGeneratorType mtype = IDLE_MOTION_TYPE; + if (option >0.0f) + mtype = RANDOM_MOTION_TYPE; + + Creature *pCreature = getSelectedCreature(); + uint32 u_guidlow = 0; + + if (pCreature) + u_guidlow = pCreature->GetDBTableGUIDLow(); + else + return false; + + pCreature->SetRespawnRadius((float)option); + pCreature->SetDefaultMovementType(mtype); + pCreature->GetMotionMaster()->Initialize(); + if(pCreature->isAlive()) // dead creature will reset movement generator at respawn + { + pCreature->setDeathState(JUST_DIED); + pCreature->Respawn(); + } + + WorldDatabase.PExecuteLog("UPDATE creature SET spawndist=%f, MovementType=%i WHERE guid=%u",option,mtype,u_guidlow); + PSendSysMessage(LANG_COMMAND_SPAWNDIST,option); + return true; +} + +bool ChatHandler::HandleSpawnTimeCommand(const char* args) +{ + if(!*args) + return false; + + char* stime = strtok((char*)args, " "); + + if (!stime) + return false; + + int i_stime = atoi((char*)stime); + + if (i_stime < 0) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Creature *pCreature = getSelectedCreature(); + uint32 u_guidlow = 0; + + if (pCreature) + u_guidlow = pCreature->GetDBTableGUIDLow(); + else + return false; + + WorldDatabase.PExecuteLog("UPDATE creature SET spawntimesecs=%i WHERE guid=%u",i_stime,u_guidlow); + pCreature->SetRespawnDelay((uint32)i_stime); + PSendSysMessage(LANG_COMMAND_SPAWNTIME,i_stime); + + return true; +} + +/** + * Add a waypoint to a creature. + * + * The user can either select an npc or provide its GUID. + * + * The user can even select a visual waypoint - then the new waypoint + * is placed *after* the selected one - this makes insertion of new + * waypoints possible. + * + * eg: + * .wp add 12345 + * -> adds a waypoint to the npc with the GUID 12345 + * + * .wp add + * -> adds a waypoint to the currently selected creature + * + * + * @param args if the user did not provide a GUID, it is NULL + * + * @return true - command did succeed, false - something went wrong + */ +bool ChatHandler::HandleWpAddCommand(const char* args) +{ + sLog.outDebug("DEBUG: HandleWpAddCommand"); + + // optional + char* guid_str = NULL; + + if(*args) + { + guid_str = strtok((char*)args, " "); + } + + uint32 lowguid = 0; + uint32 point = 0; + Creature* target = getSelectedCreature(); + // Did player provide a GUID? + if (!guid_str) + { + sLog.outDebug("DEBUG: HandleWpAddCommand - No GUID provided"); + + // No GUID provided + // -> Player must have selected a creature + + if(!target) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + if (target->GetEntry() == VISUAL_WAYPOINT ) + { + sLog.outDebug("DEBUG: HandleWpAddCommand - target->GetEntry() == VISUAL_WAYPOINT (1) "); + + QueryResult *result = + WorldDatabase.PQuery( "SELECT id, point FROM creature_movement WHERE wpguid = %u", + target->GetGUIDLow() ); + if(!result) + { + PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUIDLow()); + // User selected a visual spawnpoint -> get the NPC + // Select NPC GUID + // Since we compare float values, we have to deal with + // some difficulties. + // Here we search for all waypoints that only differ in one from 1 thousand + // (0.001) - There is no other way to compare C++ floats with mySQL floats + // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html + const char* maxDIFF = "0.01"; + result = WorldDatabase.PQuery( "SELECT id, point FROM creature_movement WHERE (abs(position_x - %f) <= %s ) and (abs(position_y - %f) <= %s ) and (abs(position_z - %f) <= %s )", + target->GetPositionX(), maxDIFF, target->GetPositionY(), maxDIFF, target->GetPositionZ(), maxDIFF); + if(!result) + { + PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, target->GetGUIDLow()); + SetSentErrorMessage(true); + return false; + } + } + do + { + Field *fields = result->Fetch(); + lowguid = fields[0].GetUInt32(); + point = fields[1].GetUInt32(); + }while( result->NextRow() ); + delete result; + + CreatureData const* data = objmgr.GetCreatureData(lowguid); + if(!data) + { + PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + target = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT)); + if(!target) + { + PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, lowguid); + SetSentErrorMessage(true); + return false; + } + } + else + { + lowguid = target->GetDBTableGUIDLow(); + } + } + else + { + sLog.outDebug("DEBUG: HandleWpAddCommand - GUID provided"); + + // GUID provided + // Warn if player also selected a creature + // -> Creature selection is ignored <- + if(target) + { + SendSysMessage(LANG_WAYPOINT_CREATSELECTED); + } + lowguid = atoi((char*)guid_str); + + CreatureData const* data = objmgr.GetCreatureData(lowguid); + if(!data) + { + PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + target = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT)); + if(!target) + { + PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + } + // lowguid -> GUID of the NPC + // point -> number of the waypoint (if not 0) + sLog.outDebug("DEBUG: HandleWpAddCommand - danach"); + + sLog.outDebug("DEBUG: HandleWpAddCommand - point == 0"); + + Player* player = m_session->GetPlayer(); + WaypointMgr.AddLastNode(lowguid, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), 0, 0); + + // update movement type + if(target) + { + target->SetDefaultMovementType(WAYPOINT_MOTION_TYPE); + target->GetMotionMaster()->Initialize(); + if(target->isAlive()) // dead creature will reset movement generator at respawn + { + target->setDeathState(JUST_DIED); + target->Respawn(); + } + target->SaveToDB(); + } + else + WorldDatabase.PExecuteLog("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid); + + PSendSysMessage(LANG_WAYPOINT_ADDED, point, lowguid); + + return true; +} // HandleWpAddCommand + +/** + * .wp modify emote | spell | text | del | move | add + * + * add -> add a WP after the selected visual waypoint + * User must select a visual waypoint and then issue ".wp modify add" + * + * emote + * User has selected a visual waypoint before. + * is added to this waypoint. Everytime the + * NPC comes to this waypoint, the emote is called. + * + * emote + * User has not selected visual waypoint before. + * For the waypoint for the NPC with + * an emote is added. + * Everytime the NPC comes to this waypoint, the emote is called. + * + * + * info -> User did not select a visual waypoint and + */ +bool ChatHandler::HandleWpModifyCommand(const char* args) +{ + sLog.outDebug("DEBUG: HandleWpModifyCommand"); + + if(!*args) + return false; + + // first arg: add del text emote spell waittime move + char* show_str = strtok((char*)args, " "); + if (!show_str) + { + return false; + } + + std::string show = show_str; + // Check + // Remember: "show" must also be the name of a column! + if( (show != "emote") && (show != "spell") && (show != "text1") && (show != "text2") + && (show != "text3") && (show != "text4") && (show != "text5") + && (show != "waittime") && (show != "del") && (show != "move") && (show != "add") + && (show != "model1") && (show != "model2") && (show != "orientation")) + { + return false; + } + + // Next arg is: + + // Did user provide a GUID + // or did the user select a creature? + // -> variable lowguid is filled with the GUID of the NPC + uint32 lowguid = 0; + uint32 point = 0; + uint32 wpGuid = 0; + Creature* target = getSelectedCreature(); + + if(target) + { + sLog.outDebug("DEBUG: HandleWpModifyCommand - User did select an NPC"); + + // Did the user select a visual spawnpoint? + if (target->GetEntry() != VISUAL_WAYPOINT ) + { + PSendSysMessage(LANG_WAYPOINT_VP_SELECT); + SetSentErrorMessage(true); + return false; + } + + wpGuid = target->GetGUIDLow(); + + // The visual waypoint + QueryResult *result = + WorldDatabase.PQuery( "SELECT id, point FROM creature_movement WHERE wpguid = %u LIMIT 1", + target->GetGUIDLow() ); + if(!result) + { + PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, wpGuid); + SetSentErrorMessage(true); + return false; + } + sLog.outDebug("DEBUG: HandleWpModifyCommand - After getting wpGuid"); + + Field *fields = result->Fetch(); + lowguid = fields[0].GetUInt32(); + point = fields[1].GetUInt32(); + + // Cleanup memory + sLog.outDebug("DEBUG: HandleWpModifyCommand - Cleanup memory"); + delete result; + } + else + { + // User did provide + + char* guid_str = strtok((char*)NULL, " "); + if( !guid_str ) + { + SendSysMessage(LANG_WAYPOINT_NOGUID); + return false; + } + lowguid = atoi((char*)guid_str); + + CreatureData const* data = objmgr.GetCreatureData(lowguid); + if(!data) + { + PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage("DEBUG: GUID provided: %d", lowguid); + + char* point_str = strtok((char*)NULL, " "); + if( !point_str ) + { + SendSysMessage(LANG_WAYPOINT_NOWAYPOINTGIVEN); + return false; + } + point = atoi((char*)point_str); + + PSendSysMessage("DEBUG: wpNumber provided: %d", point); + + // Now we need the GUID of the visual waypoint + // -> "del", "move", "add" command + + QueryResult *result = WorldDatabase.PQuery( "SELECT wpguid FROM creature_movement WHERE id = '%u' AND point = '%u' LIMIT 1", lowguid, point); + if (!result) + { + PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, lowguid, point); + SetSentErrorMessage(true); + return false; + } + + Field *fields = result->Fetch(); + wpGuid = fields[0].GetUInt32(); + + // Free memory + delete result; + } + + char* arg_str = NULL; + // Check for argument + if( (show.find("text") == std::string::npos ) && (show != "del") && (show != "move") && (show != "add")) + { + // Text is enclosed in "<>", all other arguments not + if( show.find("text") != std::string::npos ) + arg_str = strtok((char*)NULL, "<>"); + else + arg_str = strtok((char*)NULL, " "); + + if( !arg_str) + { + PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, show_str); + return false; + } + } + + sLog.outDebug("DEBUG: HandleWpModifyCommand - Parameters parsed - now execute the command"); + + // wpGuid -> GUID of the waypoint creature + // lowguid -> GUID of the NPC + // point -> waypoint number + + // Special functions: + // add - move - del -> no args commands + // Add a waypoint after the selected visual + if(show == "add" && target) + { + PSendSysMessage("DEBUG: wp modify add, GUID: %u", lowguid); + + // Get the creature for which we read the waypoint + CreatureData const* data = objmgr.GetCreatureData(lowguid); + if(!data) + { + PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT)); + + if( !npcCreature ) + { + PSendSysMessage(LANG_WAYPOINT_NPCNOTFOUND); + SetSentErrorMessage(true); + return false; + } + + sLog.outDebug("DEBUG: HandleWpModifyCommand - add -- npcCreature"); + + // What to do: + // Add the visual spawnpoint (DB only) + // Adjust the waypoints + // Respawn the owner of the waypoints + sLog.outDebug("DEBUG: HandleWpModifyCommand - add"); + + Player* chr = m_session->GetPlayer(); + Map *map = chr->GetMap(); + + if(npcCreature) + { + npcCreature->GetMotionMaster()->Initialize(); + if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn + { + npcCreature->setDeathState(JUST_DIED); + npcCreature->Respawn(); + } + } + + // create the waypoint creature + wpGuid = 0; + Creature* wpCreature = new Creature; + if (!wpCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map,VISUAL_WAYPOINT,0)) + { + PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); + delete wpCreature; + } + else + { + wpCreature->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation()); + + if(!wpCreature->IsPositionValid()) + { + sLog.outError("ERROR: Creature (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",wpCreature->GetGUIDLow(),wpCreature->GetEntry(),wpCreature->GetPositionX(),wpCreature->GetPositionY()); + delete wpCreature; + } + else + { + wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode())); + // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); + wpCreature->LoadFromDB(wpCreature->GetDBTableGUIDLow(), map); + map->Add(wpCreature); + wpGuid = wpCreature->GetGUIDLow(); + } + } + + WaypointMgr.AddAfterNode(lowguid, point, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), 0, 0, wpGuid); + + if(!wpGuid) + return false; + + PSendSysMessage(LANG_WAYPOINT_ADDED_NO, point+1); + return true; + } // add + + if(show == "del" && target) + { + PSendSysMessage("DEBUG: wp modify del, GUID: %u", lowguid); + + // Get the creature for which we read the waypoint + CreatureData const* data = objmgr.GetCreatureData(lowguid); + if(!data) + { + PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT)); + + // wpCreature + Creature* wpCreature = NULL; + if( wpGuid != 0 ) + { + wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT)); + wpCreature->DeleteFromDB(); + wpCreature->CleanupsBeforeDelete(); + wpCreature->AddObjectToRemoveList(); + } + + // What to do: + // Remove the visual spawnpoint + // Adjust the waypoints + // Respawn the owner of the waypoints + + WaypointMgr.DeleteNode(lowguid, point); + + if(npcCreature) + { + // Any waypoints left? + QueryResult *result2 = WorldDatabase.PQuery( "SELECT point FROM creature_movement WHERE id = '%u'",lowguid); + if(!result2) + { + npcCreature->SetDefaultMovementType(RANDOM_MOTION_TYPE); + } + else + { + npcCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE); + delete result2; + } + npcCreature->GetMotionMaster()->Initialize(); + if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn + { + npcCreature->setDeathState(JUST_DIED); + npcCreature->Respawn(); + } + npcCreature->SaveToDB(); + } + + PSendSysMessage(LANG_WAYPOINT_REMOVED); + return true; + } // del + + if(show == "move" && target) + { + PSendSysMessage("DEBUG: wp move, GUID: %u", lowguid); + + Player *chr = m_session->GetPlayer(); + Map *map = chr->GetMap(); + { + // Get the creature for which we read the waypoint + CreatureData const* data = objmgr.GetCreatureData(lowguid); + if(!data) + { + PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT)); + + // wpCreature + Creature* wpCreature = NULL; + // What to do: + // Move the visual spawnpoint + // Respawn the owner of the waypoints + if( wpGuid != 0 ) + { + wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT)); + wpCreature->DeleteFromDB(); + wpCreature->CleanupsBeforeDelete(); + wpCreature->AddObjectToRemoveList(); + // re-create + Creature* wpCreature2 = new Creature; + if (!wpCreature2->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, VISUAL_WAYPOINT, 0)) + { + PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); + delete wpCreature2; + return false; + } + + wpCreature2->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation()); + + if(!wpCreature2->IsPositionValid()) + { + sLog.outError("ERROR: Creature (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",wpCreature2->GetGUIDLow(),wpCreature2->GetEntry(),wpCreature2->GetPositionX(),wpCreature2->GetPositionY()); + delete wpCreature2; + return false; + } + + wpCreature2->SaveToDB(map->GetId(), (1 << map->GetSpawnMode())); + // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); + wpCreature2->LoadFromDB(wpCreature2->GetDBTableGUIDLow(), map); + map->Add(wpCreature2); + //MapManager::Instance().GetMap(npcCreature->GetMapId())->Add(wpCreature2); + } + + WaypointMgr.SetNodePosition(lowguid, point, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ()); + + if(npcCreature) + { + npcCreature->GetMotionMaster()->Initialize(); + if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn + { + npcCreature->setDeathState(JUST_DIED); + npcCreature->Respawn(); + } + } + PSendSysMessage(LANG_WAYPOINT_CHANGED); + } + return true; + } // move + + // Create creature - npc that has the waypoint + CreatureData const* data = objmgr.GetCreatureData(lowguid); + if(!data) + { + PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + WaypointMgr.SetNodeText(lowguid, point, show_str, arg_str); + + Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT)); + if(npcCreature) + { + npcCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE); + npcCreature->GetMotionMaster()->Initialize(); + if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn + { + npcCreature->setDeathState(JUST_DIED); + npcCreature->Respawn(); + } + } + PSendSysMessage(LANG_WAYPOINT_CHANGED_NO, show_str); + + return true; +} + +/** + * .wp show info | on | off + * + * info -> User has selected a visual waypoint before + * + * info -> User did not select a visual waypoint and + * provided the GUID of the NPC and the number of + * the waypoint. + * + * on -> User has selected an NPC; all visual waypoints for this + * NPC are added to the world + * + * on -> User did not select an NPC - instead the GUID of the + * NPC is provided. All visual waypoints for this NPC + * are added from the world. + * + * off -> User has selected an NPC; all visual waypoints for this + * NPC are removed from the world. + * + * on -> User did not select an NPC - instead the GUID of the + * NPC is provided. All visual waypoints for this NPC + * are removed from the world. + * + * + */ +bool ChatHandler::HandleWpShowCommand(const char* args) +{ + sLog.outDebug("DEBUG: HandleWpShowCommand"); + + if(!*args) + return false; + + // first arg: on, off, first, last + char* show_str = strtok((char*)args, " "); + if (!show_str) + { + return false; + } + // second arg: GUID (optional, if a creature is selected) + char* guid_str = strtok((char*)NULL, " "); + sLog.outDebug("DEBUG: HandleWpShowCommand: show_str: %s guid_str: %s", show_str, guid_str); + //if (!guid_str) { + // return false; + //} + + // Did user provide a GUID + // or did the user select a creature? + // -> variable lowguid is filled with the GUID + Creature* target = getSelectedCreature(); + // Did player provide a GUID? + if (!guid_str) + { + sLog.outDebug("DEBUG: HandleWpShowCommand: !guid_str"); + // No GUID provided + // -> Player must have selected a creature + + if(!target) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + } + else + { + sLog.outDebug("DEBUG: HandleWpShowCommand: GUID provided"); + // GUID provided + // Warn if player also selected a creature + // -> Creature selection is ignored <- + if(target) + { + SendSysMessage(LANG_WAYPOINT_CREATSELECTED); + } + + uint32 lowguid = atoi((char*)guid_str); + + CreatureData const* data = objmgr.GetCreatureData(lowguid); + if(!data) + { + PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + target = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT)); + + if(!target) + { + PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + } + + uint32 lowguid = target->GetDBTableGUIDLow(); + + std::string show = show_str; + uint32 Maxpoint; + + sLog.outDebug("DEBUG: HandleWpShowCommand: lowguid: %u", lowguid); + + sLog.outDebug("DEBUG: HandleWpShowCommand: Habe creature: %ld", target ); + + sLog.outDebug("DEBUG: HandleWpShowCommand: wpshow - show: %s", show_str); + //PSendSysMessage("wpshow - show: %s", show); + + // Show info for the selected waypoint + if(show == "info") + { + PSendSysMessage("DEBUG: wp info, GUID: %u", lowguid); + + // Check if the user did specify a visual waypoint + if( target->GetEntry() != VISUAL_WAYPOINT ) + { + PSendSysMessage(LANG_WAYPOINT_VP_SELECT); + SetSentErrorMessage(true); + return false; + } + + //PSendSysMessage("wp on, GUID: %u", lowguid); + + //pCreature->GetPositionX(); + + QueryResult *result = + WorldDatabase.PQuery( "SELECT id, point, waittime, emote, spell, text1, text2, text3, text4, text5, model1, model2 FROM creature_movement WHERE wpguid = %u", + target->GetGUID() ); + if(!result) + { + // Since we compare float values, we have to deal with + // some difficulties. + // Here we search for all waypoints that only differ in one from 1 thousand + // (0.001) - There is no other way to compare C++ floats with mySQL floats + // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html + const char* maxDIFF = "0.01"; + PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUID()); + + result = WorldDatabase.PQuery( "SELECT id, point, waittime, emote, spell, text1, text2, text3, text4, text5, model1, model2 FROM creature_movement WHERE (abs(position_x - %f) <= %s ) and (abs(position_y - %f) <= %s ) and (abs(position_z - %f) <= %s )", + target->GetPositionX(), maxDIFF, target->GetPositionY(), maxDIFF, target->GetPositionZ(), maxDIFF); + if(!result) + { + PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, lowguid); + SetSentErrorMessage(true); + return false; + } + } + do + { + Field *fields = result->Fetch(); + uint32 creGUID = fields[0].GetUInt32(); + uint32 point = fields[1].GetUInt32(); + int waittime = fields[2].GetUInt32(); + uint32 emote = fields[3].GetUInt32(); + uint32 spell = fields[4].GetUInt32(); + const char * text1 = fields[5].GetString(); + const char * text2 = fields[6].GetString(); + const char * text3 = fields[7].GetString(); + const char * text4 = fields[8].GetString(); + const char * text5 = fields[9].GetString(); + uint32 model1 = fields[10].GetUInt32(); + uint32 model2 = fields[11].GetUInt32(); + + // Get the creature for which we read the waypoint + Creature* wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(creGUID,VISUAL_WAYPOINT,HIGHGUID_UNIT)); + + PSendSysMessage(LANG_WAYPOINT_INFO_TITLE, point, (wpCreature ? wpCreature->GetName() : ""), creGUID); + PSendSysMessage(LANG_WAYPOINT_INFO_WAITTIME, waittime); + PSendSysMessage(LANG_WAYPOINT_INFO_MODEL, 1, model1); + PSendSysMessage(LANG_WAYPOINT_INFO_MODEL, 2, model2); + PSendSysMessage(LANG_WAYPOINT_INFO_EMOTE, emote); + PSendSysMessage(LANG_WAYPOINT_INFO_SPELL, spell); + PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 1, text1); + PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 2, text2); + PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 3, text3); + PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 4, text4); + PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 5, text5); + + }while( result->NextRow() ); + // Cleanup memory + delete result; + return true; + } + + if(show == "on") + { + PSendSysMessage("DEBUG: wp on, GUID: %u", lowguid); + + QueryResult *result = WorldDatabase.PQuery( "SELECT point, position_x,position_y,position_z FROM creature_movement WHERE id = '%u'",lowguid); + if(!result) + { + PSendSysMessage(LANG_WAYPOINT_NOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + // Delete all visuals for this NPC + QueryResult *result2 = WorldDatabase.PQuery( "SELECT wpguid FROM creature_movement WHERE id = '%u' and wpguid <> 0", lowguid); + if(result2) + { + bool hasError = false; + do + { + Field *fields = result2->Fetch(); + uint32 wpguid = fields[0].GetUInt32(); + Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(wpguid,VISUAL_WAYPOINT,HIGHGUID_UNIT)); + + if(!pCreature) + { + PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, wpguid); + hasError = true; + WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid = '%u'", wpguid); + } + else + { + pCreature->DeleteFromDB(); + pCreature->CleanupsBeforeDelete(); + pCreature->AddObjectToRemoveList(); + } + + }while( result2->NextRow() ); + delete result2; + if( hasError ) + { + PSendSysMessage(LANG_WAYPOINT_TOOFAR1); + PSendSysMessage(LANG_WAYPOINT_TOOFAR2); + PSendSysMessage(LANG_WAYPOINT_TOOFAR3); + } + } + + do + { + Field *fields = result->Fetch(); + uint32 point = fields[0].GetUInt32(); + float x = fields[1].GetFloat(); + float y = fields[2].GetFloat(); + float z = fields[3].GetFloat(); + + uint32 id = VISUAL_WAYPOINT; + + Player *chr = m_session->GetPlayer(); + Map *map = chr->GetMap(); + float o = chr->GetOrientation(); + + Creature* wpCreature = new Creature; + if (!wpCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, id, 0)) + { + PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id); + delete wpCreature; + delete result; + return false; + } + + wpCreature->Relocate(x, y, z, o); + + if(!wpCreature->IsPositionValid()) + { + sLog.outError("ERROR: Creature (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",wpCreature->GetGUIDLow(),wpCreature->GetEntry(),wpCreature->GetPositionX(),wpCreature->GetPositionY()); + delete wpCreature; + delete result; + return false; + } + + wpCreature->SetVisibility(VISIBILITY_OFF); + sLog.outDebug("DEBUG: UPDATE creature_movement SET wpguid = '%u"); + // set "wpguid" column to the visual waypoint + WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '%u' WHERE id = '%u' and point = '%u'", wpCreature->GetGUIDLow(), lowguid, point); + + wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode())); + // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); + wpCreature->LoadFromDB(wpCreature->GetDBTableGUIDLow(),map); + map->Add(wpCreature); + //MapManager::Instance().GetMap(wpCreature->GetMapId())->Add(wpCreature); + }while( result->NextRow() ); + + // Cleanup memory + delete result; + return true; + } + + if(show == "first") + { + PSendSysMessage("DEBUG: wp first, GUID: %u", lowguid); + + QueryResult *result = WorldDatabase.PQuery( "SELECT position_x,position_y,position_z FROM creature_movement WHERE point='1' AND id = '%u'",lowguid); + if(!result) + { + PSendSysMessage(LANG_WAYPOINT_NOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + Field *fields = result->Fetch(); + float x = fields[0].GetFloat(); + float y = fields[1].GetFloat(); + float z = fields[2].GetFloat(); + uint32 id = VISUAL_WAYPOINT; + + Player *chr = m_session->GetPlayer(); + float o = chr->GetOrientation(); + Map *map = chr->GetMap(); + + Creature* pCreature = new Creature; + if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT),map, id, 0)) + { + PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id); + delete pCreature; + delete result; + return false; + } + + pCreature->Relocate(x, y, z, o); + + if(!pCreature->IsPositionValid()) + { + sLog.outError("ERROR: Creature (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",pCreature->GetGUIDLow(),pCreature->GetEntry(),pCreature->GetPositionX(),pCreature->GetPositionY()); + delete pCreature; + delete result; + return false; + } + + pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode())); + pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), map); + map->Add(pCreature); + //player->PlayerTalkClass->SendPointOfInterest(x, y, 6, 6, 0, "First Waypoint"); + + // Cleanup memory + delete result; + return true; + } + + if(show == "last") + { + PSendSysMessage("DEBUG: wp last, GUID: %u", lowguid); + + QueryResult *result = WorldDatabase.PQuery( "SELECT MAX(point) FROM creature_movement WHERE id = '%u'",lowguid); + if( result ) + { + Maxpoint = (*result)[0].GetUInt32(); + + delete result; + } + else + Maxpoint = 0; + + result = WorldDatabase.PQuery( "SELECT position_x,position_y,position_z FROM creature_movement WHERE point ='%u' AND id = '%u'",Maxpoint, lowguid); + if(!result) + { + PSendSysMessage(LANG_WAYPOINT_NOTFOUNDLAST, lowguid); + SetSentErrorMessage(true); + return false; + } + Field *fields = result->Fetch(); + float x = fields[0].GetFloat(); + float y = fields[1].GetFloat(); + float z = fields[2].GetFloat(); + uint32 id = VISUAL_WAYPOINT; + + Player *chr = m_session->GetPlayer(); + float o = chr->GetOrientation(); + Map *map = chr->GetMap(); + + Creature* pCreature = new Creature; + if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, id, 0)) + { + PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id); + delete pCreature; + delete result; + return false; + } + + pCreature->Relocate(x, y, z, o); + + if(!pCreature->IsPositionValid()) + { + sLog.outError("ERROR: Creature (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",pCreature->GetGUIDLow(),pCreature->GetEntry(),pCreature->GetPositionX(),pCreature->GetPositionY()); + delete pCreature; + delete result; + return false; + } + + pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode())); + pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), map); + map->Add(pCreature); + //player->PlayerTalkClass->SendPointOfInterest(x, y, 6, 6, 0, "Last Waypoint"); + // Cleanup memory + delete result; + return true; + } + + if(show == "off") + { + QueryResult *result = WorldDatabase.PQuery("SELECT guid FROM creature WHERE id = '%d'", VISUAL_WAYPOINT); + if(!result) + { + SendSysMessage(LANG_WAYPOINT_VP_NOTFOUND); + SetSentErrorMessage(true); + return false; + } + bool hasError = false; + do + { + Field *fields = result->Fetch(); + uint32 guid = fields[0].GetUInt32(); + Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(guid,VISUAL_WAYPOINT,HIGHGUID_UNIT)); + + //Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid); + + if(!pCreature) + { + PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, guid); + hasError = true; + WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid = '%u'", guid); + } + else + { + pCreature->DeleteFromDB(); + pCreature->CleanupsBeforeDelete(); + pCreature->AddObjectToRemoveList(); + } + }while(result->NextRow()); + // set "wpguid" column to "empty" - no visual waypoint spawned + WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '0'"); + + if( hasError ) + { + PSendSysMessage(LANG_WAYPOINT_TOOFAR1); + PSendSysMessage(LANG_WAYPOINT_TOOFAR2); + PSendSysMessage(LANG_WAYPOINT_TOOFAR3); + } + + SendSysMessage(LANG_WAYPOINT_VP_ALLREMOVED); + // Cleanup memory + delete result; + + return true; + } + + PSendSysMessage("DEBUG: wpshow - no valid command found"); + + return true; +} // HandleWpShowCommand + +bool ChatHandler::HandleWpExportCommand(const char *args) +{ + if(!*args) + return false; + + // Next arg is: + + // Did user provide a GUID + // or did the user select a creature? + // -> variable lowguid is filled with the GUID of the NPC + uint32 lowguid = 0; + Creature* target = getSelectedCreature(); + char* arg_str = NULL; + if (target) + { + if (target->GetEntry() != VISUAL_WAYPOINT) + lowguid = target->GetGUIDLow(); + else + { + QueryResult *result = WorldDatabase.PQuery( "SELECT id FROM creature_movement WHERE wpguid = %u LIMIT 1", target->GetGUIDLow() ); + if (!result) + { + PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, target->GetGUIDLow()); + return true; + } + Field *fields = result->Fetch(); + lowguid = fields[0].GetUInt32();; + delete result; + } + + arg_str = strtok((char*)args, " "); + } + else + { + // user provided + char* guid_str = strtok((char*)args, " "); + if( !guid_str ) + { + SendSysMessage(LANG_WAYPOINT_NOGUID); + return false; + } + lowguid = atoi((char*)guid_str); + + arg_str = strtok((char*)NULL, " "); + } + + if( !arg_str) + { + PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, "export"); + return false; + } + + PSendSysMessage("DEBUG: wp export, GUID: %u", lowguid); + + QueryResult *result = WorldDatabase.PQuery( + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + "SELECT point, position_x, position_y, position_z, orientation, model1, model2, waittime, emote, spell, text1, text2, text3, text4, text5, id FROM creature_movement WHERE id = '%u' ORDER BY point", lowguid ); + + if (!result) + { + PSendSysMessage(LANG_WAYPOINT_NOTHINGTOEXPORT); + SetSentErrorMessage(true); + return false; + } + + std::ofstream outfile; + outfile.open (arg_str); + + do + { + Field *fields = result->Fetch(); + + outfile << "INSERT INTO creature_movement "; + outfile << "( id, point, position_x, position_y, position_z, orientation, model1, model2, waittime, emote, spell, text1, text2, text3, text4, text5 ) VALUES "; + + outfile << "( "; + outfile << fields[15].GetUInt32(); // id + outfile << ", "; + outfile << fields[0].GetUInt32(); // point + outfile << ", "; + outfile << fields[1].GetFloat(); // position_x + outfile << ", "; + outfile << fields[2].GetFloat(); // position_y + outfile << ", "; + outfile << fields[3].GetUInt32(); // position_z + outfile << ", "; + outfile << fields[4].GetUInt32(); // orientation + outfile << ", "; + outfile << fields[5].GetUInt32(); // model1 + outfile << ", "; + outfile << fields[6].GetUInt32(); // model2 + outfile << ", "; + outfile << fields[7].GetUInt16(); // waittime + outfile << ", "; + outfile << fields[8].GetUInt32(); // emote + outfile << ", "; + outfile << fields[9].GetUInt32(); // spell + outfile << ", "; + const char *tmpChar = fields[10].GetString(); + if( !tmpChar ) + { + outfile << "NULL"; // text1 + } + else + { + outfile << "'"; + outfile << tmpChar; // text1 + outfile << "'"; + } + outfile << ", "; + tmpChar = fields[11].GetString(); + if( !tmpChar ) + { + outfile << "NULL"; // text2 + } + else + { + outfile << "'"; + outfile << tmpChar; // text2 + outfile << "'"; + } + outfile << ", "; + tmpChar = fields[12].GetString(); + if( !tmpChar ) + { + outfile << "NULL"; // text3 + } + else + { + outfile << "'"; + outfile << tmpChar; // text3 + outfile << "'"; + } + outfile << ", "; + tmpChar = fields[13].GetString(); + if( !tmpChar ) + { + outfile << "NULL"; // text4 + } + else + { + outfile << "'"; + outfile << tmpChar; // text4 + outfile << "'"; + } + outfile << ", "; + tmpChar = fields[14].GetString(); + if( !tmpChar ) + { + outfile << "NULL"; // text5 + } + else + { + outfile << "'"; + outfile << tmpChar; // text5 + outfile << "'"; + } + outfile << ");\n "; + + } while( result->NextRow() ); + delete result; + + PSendSysMessage(LANG_WAYPOINT_EXPORTED); + outfile.close(); + + return true; +} + +bool ChatHandler::HandleWpImportCommand(const char *args) +{ + if(!*args) + return false; + + char* arg_str = strtok((char*)args, " "); + if (!arg_str) + return false; + + std::string line; + std::ifstream infile (arg_str); + if (infile.is_open()) + { + while (! infile.eof() ) + { + getline (infile,line); + //cout << line << endl; + QueryResult *result = WorldDatabase.PQuery(line.c_str()); + delete result; + } + infile.close(); + } + PSendSysMessage(LANG_WAYPOINT_IMPORTED); + + return true; +} + +//rename characters +bool ChatHandler::HandleRenameCommand(const char* args) +{ + Player* target = NULL; + uint64 targetGUID = 0; + std::string oldname; + + char* px = strtok((char*)args, " "); + + if(px) + { + oldname = px; + + if(!normalizePlayerName(oldname)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + target = objmgr.GetPlayer(oldname.c_str()); + + if (!target) + targetGUID = objmgr.GetPlayerGUIDByName(oldname); + } + + if(!target && !targetGUID) + { + target = getSelectedPlayer(); + } + + if(!target && !targetGUID) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + if(target) + { + PSendSysMessage(LANG_RENAME_PLAYER, target->GetName()); + target->SetAtLoginFlag(AT_LOGIN_RENAME); + CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '1' WHERE guid = '%u'", target->GetGUIDLow()); + } + else + { + PSendSysMessage(LANG_RENAME_PLAYER_GUID, oldname.c_str(), GUID_LOPART(targetGUID)); + CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '1' WHERE guid = '%u'", GUID_LOPART(targetGUID)); + } + + return true; +} + +//spawn go +bool ChatHandler::HandleGameObjectCommand(const char* args) +{ + if (!*args) + return false; + + char* pParam1 = strtok((char*)args, " "); + if (!pParam1) + return false; + + uint32 id = atoi((char*)pParam1); + if(!id) + return false; + + char* spawntimeSecs = strtok(NULL, " "); + + const GameObjectInfo *goI = objmgr.GetGameObjectInfo(id); + + if (!goI) + { + PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id); + SetSentErrorMessage(true); + return false; + } + + Player *chr = m_session->GetPlayer(); + float x = float(chr->GetPositionX()); + float y = float(chr->GetPositionY()); + float z = float(chr->GetPositionZ()); + float o = float(chr->GetOrientation()); + Map *map = chr->GetMap(); + + float rot2 = sin(o/2); + float rot3 = cos(o/2); + + GameObject* pGameObj = new GameObject; + uint32 db_lowGUID = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT); + + if(!pGameObj->Create(db_lowGUID, goI->id, map, x, y, z, o, 0, 0, rot2, rot3, 0, 1)) + { + delete pGameObj; + return false; + } + + if( spawntimeSecs ) + { + uint32 value = atoi((char*)spawntimeSecs); + pGameObj->SetRespawnTime(value); + //sLog.outDebug("*** spawntimeSecs: %d", value); + } + + // fill the gameobject data and save to the db + pGameObj->SaveToDB(map->GetId(), (1 << map->GetSpawnMode())); + + // this will generate a new guid if the object is in an instance + if(!pGameObj->LoadFromDB(db_lowGUID, map)) + { + delete pGameObj; + return false; + } + + sLog.outDebug(GetMangosString(LANG_GAMEOBJECT_CURRENT), goI->name, db_lowGUID, x, y, z, o); + + map->Add(pGameObj); + + // TODO: is it really necessary to add both the real and DB table guid here ? + objmgr.AddGameobjectToGrid(db_lowGUID, objmgr.GetGOData(db_lowGUID)); + + PSendSysMessage(LANG_GAMEOBJECT_ADD,id,goI->name,db_lowGUID,x,y,z); + return true; +} + +//show animation +bool ChatHandler::HandleAnimCommand(const char* args) +{ + if (!*args) + return false; + + uint32 anim_id = atoi((char*)args); + m_session->GetPlayer()->HandleEmoteCommand(anim_id); + return true; +} + +//change standstate +bool ChatHandler::HandleStandStateCommand(const char* args) +{ + if (!*args) + return false; + + uint32 anim_id = atoi((char*)args); + m_session->GetPlayer( )->SetUInt32Value( UNIT_NPC_EMOTESTATE , anim_id ); + + return true; +} + +bool ChatHandler::HandleAddHonorCommand(const char* args) +{ + if (!*args) + return false; + + Player *target = getSelectedPlayer(); + if(!target) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + uint32 amount = (uint32)atoi(args); + target->RewardHonor(NULL, 1, amount); + return true; +} + +bool ChatHandler::HandleHonorAddKillCommand(const char* /*args*/) +{ + Unit *target = getSelectedUnit(); + if(!target) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + m_session->GetPlayer()->RewardHonor(target, 1); + return true; +} + +bool ChatHandler::HandleUpdateHonorFieldsCommand(const char* /*args*/) +{ + Player *target = getSelectedPlayer(); + if(!target) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + target->UpdateHonorFields(); + return true; +} + +bool ChatHandler::HandleLookupEventCommand(const char* args) +{ + if(!*args) + return false; + + std::string namepart = args; + std::wstring wnamepart; + + // converting string that we try to find to lower case + if(!Utf8toWStr(namepart,wnamepart)) + return false; + + wstrToLower(wnamepart); + + uint32 counter = 0; + + GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap(); + GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList(); + + for(uint32 id = 0; id < events.size(); ++id ) + { + GameEventData const& eventData = events[id]; + + std::string descr = eventData.description; + if(descr.empty()) + continue; + + if (Utf8FitTo(descr, wnamepart)) + { + char const* active = activeEvents.find(id) != activeEvents.end() ? GetMangosString(LANG_ACTIVE) : ""; + PSendSysMessage(LANG_EVENT_ENTRY_LIST,id,id,descr.c_str(),active ); + ++counter; + } + } + + if (counter==0) + SendSysMessage(LANG_NOEVENTFOUND); + + return true; +} + +bool ChatHandler::HandleEventActiveListCommand(const char* args) +{ + uint32 counter = 0; + + GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap(); + GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList(); + + char const* active = GetMangosString(LANG_ACTIVE); + + for(GameEvent::ActiveEvents::const_iterator itr = activeEvents.begin(); itr != activeEvents.end(); ++itr ) + { + uint32 event_id = *itr; + GameEventData const& eventData = events[event_id]; + + PSendSysMessage(LANG_EVENT_ENTRY_LIST,event_id,event_id,eventData.description.c_str(),active ); + ++counter; + } + + if (counter==0) + SendSysMessage(LANG_NOEVENTFOUND); + + return true; +} + +bool ChatHandler::HandleEventInfoCommand(const char* args) +{ + if(!*args) + return false; + + // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameevent"); + if(!cId) + return false; + + uint32 event_id = atoi(cId); + + GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap(); + + if(event_id >=events.size()) + { + SendSysMessage(LANG_EVENT_NOT_EXIST); + SetSentErrorMessage(true); + return false; + } + + GameEventData const& eventData = events[event_id]; + if(!eventData.isValid()) + { + SendSysMessage(LANG_EVENT_NOT_EXIST); + SetSentErrorMessage(true); + return false; + } + + GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList(); + bool active = activeEvents.find(event_id) != activeEvents.end(); + char const* activeStr = active ? GetMangosString(LANG_ACTIVE) : ""; + + std::string startTimeStr = TimeToTimestampStr(eventData.start); + std::string endTimeStr = TimeToTimestampStr(eventData.end); + + uint32 delay = gameeventmgr.NextCheck(event_id); + time_t nextTime = time(NULL)+delay; + std::string nextStr = nextTime >= eventData.start && nextTime < eventData.end ? TimeToTimestampStr(time(NULL)+delay) : "-"; + + std::string occurenceStr = secsToTimeString(eventData.occurence * MINUTE); + std::string lengthStr = secsToTimeString(eventData.length * MINUTE); + + PSendSysMessage(LANG_EVENT_INFO,event_id,eventData.description.c_str(),activeStr, + startTimeStr.c_str(),endTimeStr.c_str(),occurenceStr.c_str(),lengthStr.c_str(), + nextStr.c_str()); + return true; +} + +bool ChatHandler::HandleEventStartCommand(const char* args) +{ + if(!*args) + return false; + + // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameevent"); + if(!cId) + return false; + + int32 event_id = atoi(cId); + + GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap(); + + if(event_id < 1 || event_id >=events.size()) + { + SendSysMessage(LANG_EVENT_NOT_EXIST); + SetSentErrorMessage(true); + return false; + } + + GameEventData const& eventData = events[event_id]; + if(!eventData.isValid()) + { + SendSysMessage(LANG_EVENT_NOT_EXIST); + SetSentErrorMessage(true); + return false; + } + + GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList(); + if(activeEvents.find(event_id) != activeEvents.end()) + { + PSendSysMessage(LANG_EVENT_ALREADY_ACTIVE,event_id); + SetSentErrorMessage(true); + return false; + } + + gameeventmgr.StartEvent(event_id,true); + return true; +} + +bool ChatHandler::HandleEventStopCommand(const char* args) +{ + if(!*args) + return false; + + // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameevent"); + if(!cId) + return false; + + int32 event_id = atoi(cId); + + GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap(); + + if(event_id < 1 || event_id >=events.size()) + { + SendSysMessage(LANG_EVENT_NOT_EXIST); + SetSentErrorMessage(true); + return false; + } + + GameEventData const& eventData = events[event_id]; + if(!eventData.isValid()) + { + SendSysMessage(LANG_EVENT_NOT_EXIST); + SetSentErrorMessage(true); + return false; + } + + GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList(); + + if(activeEvents.find(event_id) == activeEvents.end()) + { + PSendSysMessage(LANG_EVENT_NOT_ACTIVE,event_id); + SetSentErrorMessage(true); + return false; + } + + gameeventmgr.StopEvent(event_id,true); + return true; +} + +bool ChatHandler::HandleCombatStopCommand(const char* args) +{ + Player *player; + + if(*args) + { + std::string playername = args; + + if(!normalizePlayerName(playername)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + player = objmgr.GetPlayer(playername.c_str()); + + if(!player) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + } + else + { + player = getSelectedPlayer(); + + if (!player) + player = m_session->GetPlayer(); + } + + player->CombatStop(); + player->getHostilRefManager().deleteReferences(); + return true; +} + +bool ChatHandler::HandleLearnAllCraftsCommand(const char* /*args*/) +{ + uint32 classmask = m_session->GetPlayer()->getClassMask(); + + for (uint32 i = 0; i < sSkillLineStore.GetNumRows(); ++i) + { + SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(i); + if( !skillInfo ) + continue; + + if( skillInfo->categoryId == SKILL_CATEGORY_PROFESSION || skillInfo->categoryId == SKILL_CATEGORY_SECONDARY ) + { + for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j) + { + SkillLineAbilityEntry const *skillLine = sSkillLineAbilityStore.LookupEntry(j); + if( !skillLine ) + continue; + + // skip racial skills + if( skillLine->racemask != 0 ) + continue; + + // skip wrong class skills + if( skillLine->classmask && (skillLine->classmask & classmask) == 0) + continue; + + if( skillLine->skillId != i || skillLine->forward_spellid ) + continue; + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId); + if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false)) + continue; + + m_session->GetPlayer()->learnSpell(skillLine->spellId); + } + } + } + + SendSysMessage(LANG_COMMAND_LEARN_ALL_CRAFT); + return true; +} + +bool ChatHandler::HandleLearnAllRecipesCommand(const char* args) +{ + // Learns all recipes of specified profession and sets skill to max + // Example: .learn all_recipes enchanting + + Player* target = getSelectedPlayer(); + if( !target ) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + return false; + } + + if(!*args) + return false; + + std::wstring wnamepart; + + if(!Utf8toWStr(args,wnamepart)) + return false; + + uint32 counter = 0; // Counter for figure out that we found smth. + + // converting string that we try to find to lower case + wstrToLower( wnamepart ); + + uint32 classmask = m_session->GetPlayer()->getClassMask(); + + for (uint32 i = 0; i < sSkillLineStore.GetNumRows(); ++i) + { + SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(i); + if( !skillInfo ) + continue; + + if( skillInfo->categoryId != SKILL_CATEGORY_PROFESSION && + skillInfo->categoryId != SKILL_CATEGORY_SECONDARY ) + continue; + + int loc = m_session->GetSessionDbcLocale(); + std::string name = skillInfo->name[loc]; + + if(Utf8FitTo(name, wnamepart)) + { + for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j) + { + SkillLineAbilityEntry const *skillLine = sSkillLineAbilityStore.LookupEntry(j); + if( !skillLine ) + continue; + + if( skillLine->skillId != i || skillLine->forward_spellid ) + continue; + + // skip racial skills + if( skillLine->racemask != 0 ) + continue; + + // skip wrong class skills + if( skillLine->classmask && (skillLine->classmask & classmask) == 0) + continue; + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId); + if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false)) + continue; + + if( !target->HasSpell(spellInfo->Id) ) + m_session->GetPlayer()->learnSpell(skillLine->spellId); + } + + uint16 maxLevel = target->GetPureMaxSkillValue(skillInfo->id); + target->SetSkill(skillInfo->id, maxLevel, maxLevel); + PSendSysMessage(LANG_COMMAND_LEARN_ALL_RECIPES, name.c_str()); + return true; + } + } + + return false; +} diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp new file mode 100644 index 00000000000..93f39229b7d --- /dev/null +++ b/src/game/Level3.cpp @@ -0,0 +1,5424 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "World.h" +#include "ObjectMgr.h" +#include "PlayerDump.h" +#include "SpellMgr.h" +#include "Player.h" +#include "Opcodes.h" +#include "GameObject.h" +#include "Chat.h" +#include "Log.h" +#include "Guild.h" +#include "ObjectAccessor.h" +#include "MapManager.h" +#include "SpellAuras.h" +#include "ScriptCalls.h" +#include "Language.h" +#include "GridNotifiersImpl.h" +#include "CellImpl.h" +#include "Weather.h" +#include "PointMovementGenerator.h" +#include "TargetedMovementGenerator.h" +#include "SkillDiscovery.h" +#include "SkillExtraItems.h" +#include "SystemConfig.h" +#include "Config/ConfigEnv.h" +#include "Util.h" +#include "ItemEnchantmentMgr.h" +#include "InstanceSaveMgr.h" +#include "InstanceData.h" + +//reload commands +bool ChatHandler::HandleReloadCommand(const char* arg) +{ + // this is error catcher for wrong table name in .reload commands + PSendSysMessage("Db table with name starting from '%s' not found and can't be reloaded.",arg); + SetSentErrorMessage(true); + return false; +} + +bool ChatHandler::HandleReloadAllCommand(const char*) +{ + HandleReloadAreaTriggerTeleportCommand(""); + //HandleReloadAreaTriggerTavernCommand(""); -- reloaded in HandleReloadAreaTriggerTavernCommand + //HandleReloadQuestAreaTriggersCommand(""); -- reloaded in HandleReloadAllQuestCommand + HandleReloadSkillFishingBaseLevelCommand(""); + + HandleReloadAllLootCommand(""); + HandleReloadAllQuestCommand(""); + HandleReloadAllSpellCommand(""); + HandleReloadAllItemCommand(""); + + HandleReloadCommandCommand(""); + HandleReloadReservedNameCommand(""); + HandleReloadMangosStringCommand(""); + return true; +} + +bool ChatHandler::HandleReloadAllAreaCommand(const char*) +{ + HandleReloadAreaTriggerTeleportCommand(""); + //HandleReloadAreaTriggerTavernCommand(""); -- reloaded in HandleReloadAreaTriggerTavernCommand + return true; +} + +bool ChatHandler::HandleReloadAllQuestCommand(const char* /*args*/) +{ + HandleReloadQuestAreaTriggersCommand("a"); + HandleReloadQuestTemplateCommand("a"); + + sLog.outString( "Re-Loading Quests Relations..." ); + objmgr.LoadQuestRelations(); + SendGlobalSysMessage("DB tables `*_questrelation` and `*_involvedrelation` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadAllLootCommand(const char*) +{ + sLog.outString( "Re-Loading Loot Tables..." ); + LoadLootTables(); + SendGlobalSysMessage("DB tables `*_loot_template` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadAllScriptsCommand(const char*) +{ + if(sWorld.IsScriptScheduled()) + { + PSendSysMessage("DB scripts used currently, please attempt reload later."); + SetSentErrorMessage(true); + return false; + } + + sLog.outString( "Re-Loading Scripts..." ); + HandleReloadGameObjectScriptsCommand("a"); + HandleReloadEventScriptsCommand("a"); + HandleReloadQuestEndScriptsCommand("a"); + HandleReloadQuestStartScriptsCommand("a"); + HandleReloadSpellScriptsCommand("a"); + SendGlobalSysMessage("DB tables `*_scripts` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadAllSpellCommand(const char*) +{ + HandleReloadSkillDiscoveryTemplateCommand("a"); + HandleReloadSkillExtraItemTemplateCommand("a"); + HandleReloadSpellAffectCommand("a"); + HandleReloadSpellChainCommand("a"); + HandleReloadSpellElixirCommand("a"); + HandleReloadSpellLearnSpellCommand("a"); + HandleReloadSpellProcEventCommand("a"); + HandleReloadSpellScriptTargetCommand("a"); + HandleReloadSpellTargetPositionCommand("a"); + HandleReloadSpellThreatsCommand("a"); + HandleReloadSpellPetAurasCommand("a"); + return true; +} + +bool ChatHandler::HandleReloadAllItemCommand(const char*) +{ + HandleReloadPageTextsCommand("a"); + HandleReloadItemEnchantementsCommand("a"); + return true; +} + +bool ChatHandler::HandleReloadConfigCommand(const char* arg) +{ + sLog.outString( "Re-Loading config settings..." ); + sWorld.LoadConfigSettings(true); + SendGlobalSysMessage("World config settings reloaded."); + return true; +} + +bool ChatHandler::HandleReloadAreaTriggerTavernCommand(const char*) +{ + sLog.outString( "Re-Loading Tavern Area Triggers..." ); + objmgr.LoadTavernAreaTriggers(); + SendGlobalSysMessage("DB table `areatrigger_tavern` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadAreaTriggerTeleportCommand(const char*) +{ + sLog.outString( "Re-Loading AreaTrigger teleport definitions..." ); + objmgr.LoadAreaTriggerTeleports(); + SendGlobalSysMessage("DB table `areatrigger_teleport` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadCommandCommand(const char*) +{ + load_command_table = true; + SendGlobalSysMessage("DB table `command` will be reloaded at next chat command use."); + return true; +} + +bool ChatHandler::HandleReloadCreatureQuestRelationsCommand(const char*) +{ + sLog.outString( "Loading Quests Relations... (`creature_questrelation`)" ); + objmgr.LoadCreatureQuestRelations(); + SendGlobalSysMessage("DB table `creature_questrelation` (creature quest givers) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadCreatureQuestInvRelationsCommand(const char*) +{ + sLog.outString( "Loading Quests Relations... (`creature_involvedrelation`)" ); + objmgr.LoadCreatureInvolvedRelations(); + SendGlobalSysMessage("DB table `creature_involvedrelation` (creature quest takers) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadGOQuestRelationsCommand(const char*) +{ + sLog.outString( "Loading Quests Relations... (`gameobject_questrelation`)" ); + objmgr.LoadGameobjectQuestRelations(); + SendGlobalSysMessage("DB table `gameobject_questrelation` (gameobject quest givers) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadGOQuestInvRelationsCommand(const char*) +{ + sLog.outString( "Loading Quests Relations... (`gameobject_involvedrelation`)" ); + objmgr.LoadGameobjectInvolvedRelations(); + SendGlobalSysMessage("DB table `gameobject_involvedrelation` (gameobject quest takers) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadQuestAreaTriggersCommand(const char*) +{ + sLog.outString( "Re-Loading Quest Area Triggers..." ); + objmgr.LoadQuestAreaTriggers(); + SendGlobalSysMessage("DB table `areatrigger_involvedrelation` (quest area triggers) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadQuestTemplateCommand(const char*) +{ + sLog.outString( "Re-Loading Quest Templates..." ); + objmgr.LoadQuests(); + SendGlobalSysMessage("DB table `quest_template` (quest definitions) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesCreatureCommand(const char*) +{ + sLog.outString( "Re-Loading Loot Tables... (`creature_loot_template`)" ); + LoadLootTemplates_Creature(); + LootTemplates_Creature.CheckLootRefs(); + SendGlobalSysMessage("DB table `creature_loot_template` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesDisenchantCommand(const char*) +{ + sLog.outString( "Re-Loading Loot Tables... (`disenchant_loot_template`)" ); + LoadLootTemplates_Disenchant(); + LootTemplates_Disenchant.CheckLootRefs(); + SendGlobalSysMessage("DB table `disenchant_loot_template` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesFishingCommand(const char*) +{ + sLog.outString( "Re-Loading Loot Tables... (`fishing_loot_template`)" ); + LoadLootTemplates_Fishing(); + LootTemplates_Fishing.CheckLootRefs(); + SendGlobalSysMessage("DB table `fishing_loot_template` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesGameobjectCommand(const char*) +{ + sLog.outString( "Re-Loading Loot Tables... (`gameobject_loot_template`)" ); + LoadLootTemplates_Gameobject(); + LootTemplates_Gameobject.CheckLootRefs(); + SendGlobalSysMessage("DB table `gameobject_loot_template` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesItemCommand(const char*) +{ + sLog.outString( "Re-Loading Loot Tables... (`item_loot_template`)" ); + LoadLootTemplates_Item(); + LootTemplates_Item.CheckLootRefs(); + SendGlobalSysMessage("DB table `item_loot_template` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesPickpocketingCommand(const char*) +{ + sLog.outString( "Re-Loading Loot Tables... (`pickpocketing_loot_template`)" ); + LoadLootTemplates_Pickpocketing(); + LootTemplates_Pickpocketing.CheckLootRefs(); + SendGlobalSysMessage("DB table `pickpocketing_loot_template` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesProspectingCommand(const char*) +{ + sLog.outString( "Re-Loading Loot Tables... (`prospecting_loot_template`)" ); + LoadLootTemplates_Prospecting(); + LootTemplates_Prospecting.CheckLootRefs(); + SendGlobalSysMessage("DB table `prospecting_loot_template` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesQuestMailCommand(const char*) +{ + sLog.outString( "Re-Loading Loot Tables... (`quest_mail_loot_template`)" ); + LoadLootTemplates_QuestMail(); + LootTemplates_QuestMail.CheckLootRefs(); + SendGlobalSysMessage("DB table `quest_mail_loot_template` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesReferenceCommand(const char*) +{ + sLog.outString( "Re-Loading Loot Tables... (`reference_loot_template`)" ); + LoadLootTemplates_Reference(); + SendGlobalSysMessage("DB table `reference_loot_template` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesSkinningCommand(const char*) +{ + sLog.outString( "Re-Loading Loot Tables... (`skinning_loot_template`)" ); + LoadLootTemplates_Skinning(); + LootTemplates_Skinning.CheckLootRefs(); + SendGlobalSysMessage("DB table `skinning_loot_template` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadMangosStringCommand(const char*) +{ + sLog.outString( "Re-Loading mangos_string Table!" ); + objmgr.LoadMangosStrings(); + SendGlobalSysMessage("DB table `mangos_string` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadReservedNameCommand(const char*) +{ + sLog.outString( "Loading ReservedNames... (`reserved_name`)" ); + objmgr.LoadReservedPlayersNames(); + SendGlobalSysMessage("DB table `reserved_name` (player reserved names) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSkillDiscoveryTemplateCommand(const char* /*args*/) +{ + sLog.outString( "Re-Loading Skill Discovery Table..." ); + LoadSkillDiscoveryTable(); + SendGlobalSysMessage("DB table `skill_discovery_template` (recipes discovered at crafting) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSkillExtraItemTemplateCommand(const char* /*args*/) +{ + sLog.outString( "Re-Loading Skill Extra Item Table..." ); + LoadSkillExtraItemTable(); + SendGlobalSysMessage("DB table `skill_extra_item_template` (extra item creation when crafting) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSkillFishingBaseLevelCommand(const char* /*args*/) +{ + sLog.outString( "Re-Loading Skill Fishing base level requirements..." ); + objmgr.LoadFishingBaseSkillLevel(); + SendGlobalSysMessage("DB table `skill_fishing_base_level` (fishing base level for zone/subzone) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellAffectCommand(const char*) +{ + sLog.outString( "Re-Loading SpellAffect definitions..." ); + spellmgr.LoadSpellAffects(); + SendGlobalSysMessage("DB table `spell_affect` (spell mods apply requirements) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellChainCommand(const char*) +{ + sLog.outString( "Re-Loading Spell Chain Data... " ); + spellmgr.LoadSpellChains(); + SendGlobalSysMessage("DB table `spell_chain` (spell ranks) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellElixirCommand(const char*) +{ + sLog.outString( "Re-Loading Spell Elixir types..." ); + spellmgr.LoadSpellElixirs(); + SendGlobalSysMessage("DB table `spell_elixir` (spell exlixir types) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellLearnSpellCommand(const char*) +{ + sLog.outString( "Re-Loading Spell Learn Spells..." ); + spellmgr.LoadSpellLearnSpells(); + SendGlobalSysMessage("DB table `spell_learn_spell` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellProcEventCommand(const char*) +{ + sLog.outString( "Re-Loading Spell Proc Event conditions..." ); + spellmgr.LoadSpellProcEvents(); + SendGlobalSysMessage("DB table `spell_proc_event` (spell proc trigger requirements) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellScriptTargetCommand(const char*) +{ + sLog.outString( "Re-Loading SpellsScriptTarget..." ); + spellmgr.LoadSpellScriptTarget(); + SendGlobalSysMessage("DB table `spell_script_target` (spell targets selection in case specific creature/GO requirements) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellTargetPositionCommand(const char*) +{ + sLog.outString( "Re-Loading Spell target coordinates..." ); + spellmgr.LoadSpellTargetPositions(); + SendGlobalSysMessage("DB table `spell_target_position` (destination coordinates for spell targets) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellThreatsCommand(const char*) +{ + sLog.outString( "Re-Loading Aggro Spells Definitions..."); + spellmgr.LoadSpellThreats(); + SendGlobalSysMessage("DB table `spell_threat` (spell aggro definitions) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellPetAurasCommand(const char*) +{ + sLog.outString( "Re-Loading Spell pet auras..."); + spellmgr.LoadSpellPetAuras(); + SendGlobalSysMessage("DB table `spell_pet_auras` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadPageTextsCommand(const char*) +{ + sLog.outString( "Re-Loading Page Texts..." ); + objmgr.LoadPageTexts(); + SendGlobalSysMessage("DB table `page_texts` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadItemEnchantementsCommand(const char*) +{ + sLog.outString( "Re-Loading Item Random Enchantments Table..." ); + LoadRandomEnchantmentsTable(); + SendGlobalSysMessage("DB table `item_enchantment_template` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadGameObjectScriptsCommand(const char* arg) +{ + if(sWorld.IsScriptScheduled()) + { + SendSysMessage("DB scripts used currently, please attempt reload later."); + SetSentErrorMessage(true); + return false; + } + + if(*arg!='a') + sLog.outString( "Re-Loading Scripts from `gameobject_scripts`..."); + + objmgr.LoadGameObjectScripts(); + + if(*arg!='a') + SendGlobalSysMessage("DB table `gameobject_scripts` reloaded."); + + return true; +} + +bool ChatHandler::HandleReloadEventScriptsCommand(const char* arg) +{ + if(sWorld.IsScriptScheduled()) + { + SendSysMessage("DB scripts used currently, please attempt reload later."); + SetSentErrorMessage(true); + return false; + } + + if(*arg!='a') + sLog.outString( "Re-Loading Scripts from `event_scripts`..."); + + objmgr.LoadEventScripts(); + + if(*arg!='a') + SendGlobalSysMessage("DB table `event_scripts` reloaded."); + + return true; +} + +bool ChatHandler::HandleReloadQuestEndScriptsCommand(const char* arg) +{ + if(sWorld.IsScriptScheduled()) + { + SendSysMessage("DB scripts used currently, please attempt reload later."); + SetSentErrorMessage(true); + return false; + } + + if(*arg!='a') + sLog.outString( "Re-Loading Scripts from `quest_end_scripts`..."); + + objmgr.LoadQuestEndScripts(); + + if(*arg!='a') + SendGlobalSysMessage("DB table `quest_end_scripts` reloaded."); + + return true; +} + +bool ChatHandler::HandleReloadQuestStartScriptsCommand(const char* arg) +{ + if(sWorld.IsScriptScheduled()) + { + SendSysMessage("DB scripts used currently, please attempt reload later."); + SetSentErrorMessage(true); + return false; + } + + if(*arg!='a') + sLog.outString( "Re-Loading Scripts from `quest_start_scripts`..."); + + objmgr.LoadQuestStartScripts(); + + if(*arg!='a') + SendGlobalSysMessage("DB table `quest_start_scripts` reloaded."); + + return true; +} + +bool ChatHandler::HandleReloadSpellScriptsCommand(const char* arg) +{ + if(sWorld.IsScriptScheduled()) + { + SendSysMessage("DB scripts used currently, please attempt reload later."); + SetSentErrorMessage(true); + return false; + } + + if(*arg!='a') + sLog.outString( "Re-Loading Scripts from `spell_scripts`..."); + + objmgr.LoadSpellScripts(); + + if(*arg!='a') + SendGlobalSysMessage("DB table `spell_scripts` reloaded."); + + return true; +} + +bool ChatHandler::HandleReloadGameGraveyardZoneCommand(const char* /*arg*/) +{ + sLog.outString( "Re-Loading Graveyard-zone links..."); + + objmgr.LoadGraveyardZones(); + + SendGlobalSysMessage("DB table `game_graveyard_zone` reloaded."); + + return true; +} + +bool ChatHandler::HandleLoadScriptsCommand(const char* args) +{ + if(!LoadScriptingModule(args)) return true; + + sWorld.SendWorldText(LANG_SCRIPTS_RELOADED); + return true; +} + +bool ChatHandler::HandleSecurityCommand(const char* args) +{ + char* arg1 = strtok((char*)args, " "); + if( !arg1 ) + return false; + + char* arg2 = 0; + + std::string targetName; + uint32 targetAccountId = 0; + uint32 targetSecurity = 0; + + Player* targetPlayer = getSelectedPlayer(); + if(targetPlayer) + { + targetName = targetPlayer->GetName(); + targetAccountId = targetPlayer->GetSession()->GetAccountId(); + targetSecurity = targetPlayer->GetSession()->GetSecurity(); + arg2 = arg1; + } + else + { + targetName = arg1; + if(!normalizePlayerName(targetName)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + targetPlayer = ObjectAccessor::Instance().FindPlayerByName(targetName.c_str()); + if(targetPlayer) + { + targetAccountId = targetPlayer->GetSession()->GetAccountId(); + targetSecurity = targetPlayer->GetSession()->GetSecurity(); + } + else + { + uint64 targetGUID = objmgr.GetPlayerGUIDByName(targetName.c_str()); + if(!targetGUID) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + targetAccountId = objmgr.GetPlayerAccountIdByGUID(targetGUID); + targetSecurity = objmgr.GetSecurityByAccount(targetAccountId); + } + + arg2 = strtok(NULL, " "); + } + + int32 gm = (int32)atoi(arg2); + if ( gm < SEC_PLAYER || gm > SEC_ADMINISTRATOR ) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + // can set security level only for target with less security and to less security that we have + if(targetSecurity >= m_session->GetSecurity() || uint32(gm) >= m_session->GetSecurity() ) + { + SendSysMessage(LANG_YOURS_SECURITY_IS_LOW); + SetSentErrorMessage(true); + return false; + } + + if(targetPlayer) + { + if( targetPlayer != m_session->GetPlayer() ) + ChatHandler(targetPlayer).PSendSysMessage(LANG_YOURS_SECURITY_CHANGED,m_session->GetPlayer()->GetName(), gm); + + targetPlayer->GetSession()->SetSecurity(gm); + } + + PSendSysMessage(LANG_YOU_CHANGE_SECURITY, targetName.c_str(), gm); + loginDatabase.PExecute("UPDATE account SET gmlevel = '%i' WHERE id = '%u'", gm, targetAccountId); + + return true; +} + +bool ChatHandler::HandleAllowMovementCommand(const char* /*args*/) +{ + if(sWorld.getAllowMovement()) + { + sWorld.SetAllowMovement(false); + SendSysMessage(LANG_CREATURE_MOVE_DISABLED); + } + else + { + sWorld.SetAllowMovement(true); + SendSysMessage(LANG_CREATURE_MOVE_ENABLED); + } + return true; +} + +bool ChatHandler::HandleMaxSkillCommand(const char* /*args*/) +{ + Player* SelectedPlayer = getSelectedPlayer(); + if(!SelectedPlayer) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // each skills that have max skill value dependent from level seted to current level max skill value + SelectedPlayer->UpdateSkillsToMaxSkillsForLevel(); + return true; +} + +bool ChatHandler::HandleSetSkillCommand(const char* args) +{ + // number or [name] Shift-click form |color|Hskill:skill_id|h[name]|h|r + char* skill_p = extractKeyFromLink((char*)args,"Hskill"); + if(!skill_p) + return false; + + char *level_p = strtok (NULL, " "); + + if( !level_p) + return false; + + char *max_p = strtok (NULL, " "); + + int32 skill = atoi(skill_p); + + if (skill <= 0) + { + PSendSysMessage(LANG_INVALID_SKILL_ID, skill); + SetSentErrorMessage(true); + return false; + } + + int32 level = atol (level_p); + + Player * target = getSelectedPlayer(); + if(!target) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + SkillLineEntry const* sl = sSkillLineStore.LookupEntry(skill); + if(!sl) + { + PSendSysMessage(LANG_INVALID_SKILL_ID, skill); + SetSentErrorMessage(true); + return false; + } + + if(!target->GetSkillValue(skill)) + { + PSendSysMessage(LANG_SET_SKILL_ERROR, target->GetName(), skill, sl->name[0]); + SetSentErrorMessage(true); + return false; + } + + int32 max = max_p ? atol (max_p) : target->GetPureMaxSkillValue(skill); + + if( level <= 0 || level > max || max <= 0 ) + return false; + + target->SetSkill(skill, level, max); + PSendSysMessage(LANG_SET_SKILL, skill, sl->name[0], target->GetName(), level, max); + + return true; +} + +bool ChatHandler::HandleUnLearnCommand(const char* args) +{ + if (!*args) + return false; + + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r + uint32 min_id = extractSpellIdFromLink((char*)args); + if(!min_id) + return false; + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r + char* tail = strtok(NULL,""); + + uint32 max_id = extractSpellIdFromLink(tail); + + if (!max_id) + { + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r + max_id = min_id+1; + } + else + { + if (max_id < min_id) + std::swap(min_id,max_id); + + max_id=max_id+1; + } + + Player* target = getSelectedPlayer(); + if(!target) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + for(uint32 spell=min_id;spellHasSpell(spell)) + target->removeSpell(spell); + else + SendSysMessage(LANG_FORGET_SPELL); + } + + return true; +} + +bool ChatHandler::HandleCooldownCommand(const char* args) +{ + Player* target = getSelectedPlayer(); + if(!target) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + if (!*args) + { + target->RemoveAllSpellCooldown(); + PSendSysMessage(LANG_REMOVEALL_COOLDOWN, target->GetName()); + } + else + { + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spell_id = extractSpellIdFromLink((char*)args); + if(!spell_id) + return false; + + if(!sSpellStore.LookupEntry(spell_id)) + { + PSendSysMessage(LANG_UNKNOWN_SPELL, target==m_session->GetPlayer() ? GetMangosString(LANG_YOU) : target->GetName()); + SetSentErrorMessage(true); + return false; + } + + WorldPacket data( SMSG_CLEAR_COOLDOWN, (4+8) ); + data << uint32(spell_id); + data << uint64(target->GetGUID()); + target->GetSession()->SendPacket(&data); + target->RemoveSpellCooldown(spell_id); + PSendSysMessage(LANG_REMOVE_COOLDOWN, spell_id, target==m_session->GetPlayer() ? GetMangosString(LANG_YOU) : target->GetName()); + } + return true; +} + +bool ChatHandler::HandleLearnAllCommand(const char* /*args*/) +{ + static const char *allSpellList[] = + { + "3365", + "6233", + "6247", + "6246", + "6477", + "6478", + "22810", + "8386", + "21651", + "21652", + "522", + "7266", + "8597", + "2479", + "22027", + "6603", + "5019", + "133", + "168", + "227", + "5009", + "9078", + "668", + "203", + "20599", + "20600", + "81", + "20597", + "20598", + "20864", + "1459", + "5504", + "587", + "5143", + "118", + "5505", + "597", + "604", + "1449", + "1460", + "2855", + "1008", + "475", + "5506", + "1463", + "12824", + "8437", + "990", + "5145", + "8450", + "1461", + "759", + "8494", + "8455", + "8438", + "6127", + "8416", + "6129", + "8451", + "8495", + "8439", + "3552", + "8417", + "10138", + "12825", + "10169", + "10156", + "10144", + "10191", + "10201", + "10211", + "10053", + "10173", + "10139", + "10145", + "10192", + "10170", + "10202", + "10054", + "10174", + "10193", + "12826", + "2136", + "143", + "145", + "2137", + "2120", + "3140", + "543", + "2138", + "2948", + "8400", + "2121", + "8444", + "8412", + "8457", + "8401", + "8422", + "8445", + "8402", + "8413", + "8458", + "8423", + "8446", + "10148", + "10197", + "10205", + "10149", + "10215", + "10223", + "10206", + "10199", + "10150", + "10216", + "10207", + "10225", + "10151", + "116", + "205", + "7300", + "122", + "837", + "10", + "7301", + "7322", + "6143", + "120", + "865", + "8406", + "6141", + "7302", + "8461", + "8407", + "8492", + "8427", + "8408", + "6131", + "7320", + "10159", + "8462", + "10185", + "10179", + "10160", + "10180", + "10219", + "10186", + "10177", + "10230", + "10181", + "10161", + "10187", + "10220", + "2018", + "2663", + "12260", + "2660", + "3115", + "3326", + "2665", + "3116", + "2738", + "3293", + "2661", + "3319", + "2662", + "9983", + "8880", + "2737", + "2739", + "7408", + "3320", + "2666", + "3323", + "3324", + "3294", + "22723", + "23219", + "23220", + "23221", + "23228", + "23338", + "10788", + "10790", + "5611", + "5016", + "5609", + "2060", + "10963", + "10964", + "10965", + "22593", + "22594", + "596", + "996", + "499", + "768", + "17002", + "1448", + "1082", + "16979", + "1079", + "5215", + "20484", + "5221", + "15590", + "17007", + "6795", + "6807", + "5487", + "1446", + "1066", + "5421", + "3139", + "779", + "6811", + "6808", + "1445", + "5216", + "1737", + "5222", + "5217", + "1432", + "6812", + "9492", + "5210", + "3030", + "1441", + "783", + "6801", + "20739", + "8944", + "9491", + "22569", + "5226", + "6786", + "1433", + "8973", + "1828", + "9495", + "9006", + "6794", + "8993", + "5203", + "16914", + "6784", + "9635", + "22830", + "20722", + "9748", + "6790", + "9753", + "9493", + "9752", + "9831", + "9825", + "9822", + "5204", + "5401", + "22831", + "6793", + "9845", + "17401", + "9882", + "9868", + "20749", + "9893", + "9899", + "9895", + "9832", + "9902", + "9909", + "22832", + "9828", + "9851", + "9883", + "9869", + "17406", + "17402", + "9914", + "20750", + "9897", + "9848", + "3127", + "107", + "204", + "9116", + "2457", + "78", + "18848", + "331", + "403", + "2098", + "1752", + "11278", + "11288", + "11284", + "6461", + "2344", + "2345", + "6463", + "2346", + "2352", + "775", + "1434", + "1612", + "71", + "2468", + "2458", + "2467", + "7164", + "7178", + "7367", + "7376", + "7381", + "21156", + "5209", + "3029", + "5201", + "9849", + "9850", + "20719", + "22568", + "22827", + "22828", + "22829", + "6809", + "8972", + "9005", + "9823", + "9827", + "6783", + "9913", + "6785", + "6787", + "9866", + "9867", + "9894", + "9896", + "6800", + "8992", + "9829", + "9830", + "780", + "769", + "6749", + "6750", + "9755", + "9754", + "9908", + "20745", + "20742", + "20747", + "20748", + "9746", + "9745", + "9880", + "9881", + "5391", + "842", + "3025", + "3031", + "3287", + "3329", + "1945", + "3559", + "4933", + "4934", + "4935", + "4936", + "5142", + "5390", + "5392", + "5404", + "5420", + "6405", + "7293", + "7965", + "8041", + "8153", + "9033", + "9034", + //"9036", problems with ghost state + "16421", + "21653", + "22660", + "5225", + "9846", + "2426", + "5916", + "6634", + //"6718", phasing stealth, annoing for learn all case. + "6719", + "8822", + "9591", + "9590", + "10032", + "17746", + "17747", + "8203", + "11392", + "12495", + "16380", + "23452", + "4079", + "4996", + "4997", + "4998", + "4999", + "5000", + "6348", + "6349", + "6481", + "6482", + "6483", + "6484", + "11362", + "11410", + "11409", + "12510", + "12509", + "12885", + "13142", + "21463", + "23460", + "11421", + "11416", + "11418", + "1851", + "10059", + "11423", + "11417", + "11422", + "11419", + "11424", + "11420", + "27", + "31", + "33", + "34", + "35", + "15125", + "21127", + "22950", + "1180", + "201", + "12593", + "12842", + "16770", + "6057", + "12051", + "18468", + "12606", + "12605", + "18466", + "12502", + "12043", + "15060", + "12042", + "12341", + "12848", + "12344", + "12353", + "18460", + "11366", + "12350", + "12352", + "13043", + "11368", + "11113", + "12400", + "11129", + "16766", + "12573", + "15053", + "12580", + "12475", + "12472", + "12953", + "12488", + "11189", + "12985", + "12519", + "16758", + "11958", + "12490", + "11426", + "3565", + "3562", + "18960", + "3567", + "3561", + "3566", + "3563", + "1953", + "2139", + "12505", + "13018", + "12522", + "12523", + "5146", + "5144", + "5148", + "8419", + "8418", + "10213", + "10212", + "10157", + "12524", + "13019", + "12525", + "13020", + "12526", + "13021", + "18809", + "13031", + "13032", + "13033", + "4036", + "3920", + "3919", + "3918", + "7430", + "3922", + "3923", + "7411", + "7418", + "7421", + "13262", + "7412", + "7415", + "7413", + "7416", + "13920", + "13921", + "7745", + "7779", + "7428", + "7457", + "7857", + "7748", + "7426", + "13421", + "7454", + "13378", + "7788", + "14807", + "14293", + "7795", + "6296", + "20608", + "755", + "444", + "427", + "428", + "442", + "447", + "3578", + "3581", + "19027", + "3580", + "665", + "3579", + "3577", + "6755", + "3576", + "2575", + "2577", + "2578", + "2579", + "2580", + "2656", + "2657", + "2576", + "3564", + "10248", + "8388", + "2659", + "14891", + "3308", + "3307", + "10097", + "2658", + "3569", + "16153", + "3304", + "10098", + "4037", + "3929", + "3931", + "3926", + "3924", + "3930", + "3977", + "3925", + "136", + "228", + "5487", + "43", + "202", + "0" + }; + + int loop = 0; + while(strcmp(allSpellList[loop], "0")) + { + uint32 spell = atol((char*)allSpellList[loop++]); + + if (m_session->GetPlayer()->HasSpell(spell)) + continue; + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell); + if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer())) + { + PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spell); + continue; + } + + m_session->GetPlayer()->learnSpell(spell); + } + + SendSysMessage(LANG_COMMAND_LEARN_MANY_SPELLS); + + return true; +} + +bool ChatHandler::HandleLearnAllGMCommand(const char* /*args*/) +{ + static const char *gmSpellList[] = + { + "24347", // Become A Fish, No Breath Bar + "35132", // Visual Boom + "38488", // Attack 4000-8000 AOE + "38795", // Attack 2000 AOE + Slow Down 90% + "15712", // Attack 200 + "1852", // GM Spell Silence + "31899", // Kill + "31924", // Kill + "29878", // Kill My Self + "26644", // More Kill + + "28550", //Invisible 24 + "23452", //Invisible + Target + "0" + }; + + uint16 gmSpellIter = 0; + while( strcmp(gmSpellList[gmSpellIter], "0") ) + { + uint32 spell = atol((char*)gmSpellList[gmSpellIter++]); + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell); + if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer())) + { + PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spell); + continue; + } + + m_session->GetPlayer()->learnSpell(spell); + } + + SendSysMessage(LANG_LEARNING_GM_SKILLS); + return true; +} + +bool ChatHandler::HandleLearnAllMyClassCommand(const char* /*args*/) +{ + HandleLearnAllMySpellsCommand(""); + HandleLearnAllMyTalentsCommand(""); + return true; +} + +bool ChatHandler::HandleLearnAllMySpellsCommand(const char* /*args*/) +{ + ChrClassesEntry const* clsEntry = sChrClassesStore.LookupEntry(m_session->GetPlayer()->getClass()); + if(!clsEntry) + return true; + uint32 family = clsEntry->spellfamily; + + for (uint32 i = 0; i < sSpellStore.GetNumRows(); i++) + { + SpellEntry const *spellInfo = sSpellStore.LookupEntry(i); + if(!spellInfo) + continue; + + // skip wrong class/race skills + if(!m_session->GetPlayer()->IsSpellFitByClassAndRace(spellInfo->Id)) + continue; + + // skip other spell families + if( spellInfo->SpellFamilyName != family) + continue; + + //TODO: skip triggered spells + + // skip spells with first rank learned as talent (and all talents then also) + uint32 first_rank = spellmgr.GetFirstSpellInChain(spellInfo->Id); + if(GetTalentSpellCost(first_rank) > 0 ) + continue; + + // skip broken spells + if(!SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false)) + continue; + + m_session->GetPlayer()->learnSpell(i); + } + + SendSysMessage(LANG_COMMAND_LEARN_CLASS_SPELLS); + return true; +} + +static void learnAllHighRanks(Player* player, uint32 spellid) +{ + SpellChainMapNext const& nextMap = spellmgr.GetSpellChainNext(); + for(SpellChainMapNext::const_iterator itr = nextMap.lower_bound(spellid); itr != nextMap.upper_bound(spellid); ++itr) + { + player->learnSpell(itr->second); + learnAllHighRanks(player,itr->second); + } +} + +bool ChatHandler::HandleLearnAllMyTalentsCommand(const char* /*args*/) +{ + Player* player = m_session->GetPlayer(); + uint32 classMask = player->getClassMask(); + + for (uint32 i = 0; i < sTalentStore.GetNumRows(); i++) + { + TalentEntry const *talentInfo = sTalentStore.LookupEntry(i); + if(!talentInfo) + continue; + + TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry( talentInfo->TalentTab ); + if(!talentTabInfo) + continue; + + if( (classMask & talentTabInfo->ClassMask) == 0 ) + continue; + + // search highest talent rank + uint32 spellid = 0; + int rank = 4; + for(; rank >= 0; --rank) + { + if(talentInfo->RankID[rank]!=0) + { + spellid = talentInfo->RankID[rank]; + break; + } + } + + if(!spellid) // ??? none spells in telent + continue; + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellid); + if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false)) + continue; + + // learn highest rank of talent + player->learnSpell(spellid); + + // and learn all non-talent spell ranks (recursive by tree) + learnAllHighRanks(player,spellid); + } + + SendSysMessage(LANG_COMMAND_LEARN_CLASS_TALENTS); + return true; +} + +bool ChatHandler::HandleLearnAllLangCommand(const char* /*args*/) +{ + // skipping UNIVERSAL language (0) + for(int i = 1; i < LANGUAGES_COUNT; ++i) + m_session->GetPlayer()->learnSpell(lang_description[i].spell_id); + + SendSysMessage(LANG_COMMAND_LEARN_ALL_LANG); + return true; +} + +bool ChatHandler::HandleLearnAllDefaultCommand(const char* args) +{ + char* pName = strtok((char*)args, ""); + Player *player = NULL; + if (pName) + { + std::string name = pName; + + if(!normalizePlayerName(name)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + player = objmgr.GetPlayer(name.c_str()); + } + else + player = getSelectedPlayer(); + + if(!player) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + player->learnDefaultSpells(); + player->learnQuestRewardedSpells(); + + PSendSysMessage(LANG_COMMAND_LEARN_ALL_DEFAULT_AND_QUEST,player->GetName()); + return true; +} + +bool ChatHandler::HandleLearnCommand(const char* args) +{ + Player* targetPlayer = getSelectedPlayer(); + + if(!targetPlayer) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spell = extractSpellIdFromLink((char*)args); + if(!spell || !sSpellStore.LookupEntry(spell)) + return false; + + if (targetPlayer->HasSpell(spell)) + { + if(targetPlayer == m_session->GetPlayer()) + SendSysMessage(LANG_YOU_KNOWN_SPELL); + else + PSendSysMessage(LANG_TARGET_KNOWN_SPELL,targetPlayer->GetName()); + SetSentErrorMessage(true); + return false; + } + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell); + if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer())) + { + PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spell); + SetSentErrorMessage(true); + return false; + } + + targetPlayer->learnSpell(spell); + + return true; +} + +bool ChatHandler::HandleAddItemCommand(const char* args) +{ + if (!*args) + return false; + + uint32 itemId = 0; + + if(args[0]=='[') // [name] manual form + { + char* citemName = citemName = strtok((char*)args, "]"); + + if(citemName && citemName[0]) + { + std::string itemName = citemName+1; + WorldDatabase.escape_string(itemName); + QueryResult *result = WorldDatabase.PQuery("SELECT entry FROM item_template WHERE name = '%s'", itemName.c_str()); + if (!result) + { + PSendSysMessage(LANG_COMMAND_COULDNOTFIND, citemName+1); + SetSentErrorMessage(true); + return false; + } + itemId = result->Fetch()->GetUInt16(); + delete result; + } + else + return false; + } + else // item_id or [name] Shift-click form |color|Hitem:item_id:0:0:0|h[name]|h|r + { + char* cId = extractKeyFromLink((char*)args,"Hitem"); + if(!cId) + return false; + itemId = atol(cId); + } + + char* ccount = strtok(NULL, " "); + + int32 count = 1; + + if (ccount) + count = strtol(ccount, NULL, 10); + + if (count == 0) + count = 1; + + Player* pl = m_session->GetPlayer(); + Player* plTarget = getSelectedPlayer(); + if(!plTarget) + plTarget = pl; + + sLog.outDetail(GetMangosString(LANG_ADDITEM), itemId, count); + + ItemPrototype const *pProto = objmgr.GetItemPrototype(itemId); + if(!pProto) + { + PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, itemId); + SetSentErrorMessage(true); + return false; + } + + //Subtract + if (count < 0) + { + plTarget->DestroyItemCount(itemId, -count, true, false); + PSendSysMessage(LANG_REMOVEITEM, itemId, -count, plTarget->GetName()); + return true; + } + + //Adding items + uint32 noSpaceForCount = 0; + + // check space and find places + ItemPosCountVec dest; + uint8 msg = plTarget->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, itemId, count, &noSpaceForCount ); + if( msg != EQUIP_ERR_OK ) // convert to possible store amount + count -= noSpaceForCount; + + if( count == 0 || dest.empty()) // can't add any + { + PSendSysMessage(LANG_ITEM_CANNOT_CREATE, itemId, noSpaceForCount ); + SetSentErrorMessage(true); + return false; + } + + Item* item = plTarget->StoreNewItem( dest, itemId, true, Item::GenerateItemRandomPropertyId(itemId)); + + // remove binding (let GM give it to another player later) + if(pl==plTarget) + for(ItemPosCountVec::const_iterator itr = dest.begin(); itr != dest.end(); ++itr) + if(Item* item1 = pl->GetItemByPos(itr->pos)) + item1->SetBinding( false ); + + if(count > 0 && item) + { + pl->SendNewItem(item,count,false,true); + if(pl!=plTarget) + plTarget->SendNewItem(item,count,true,false); + } + + if(noSpaceForCount > 0) + PSendSysMessage(LANG_ITEM_CANNOT_CREATE, itemId, noSpaceForCount); + + return true; +} + +bool ChatHandler::HandleAddItemSetCommand(const char* args) +{ + if (!*args) + return false; + + char* cId = extractKeyFromLink((char*)args,"Hitemset"); // number or [name] Shift-click form |color|Hitemset:itemset_id|h[name]|h|r + if (!cId) + return false; + + uint32 itemsetId = atol(cId); + + // prevent generation all items with itemset field value '0' + if (itemsetId == 0) + { + PSendSysMessage(LANG_NO_ITEMS_FROM_ITEMSET_FOUND,itemsetId); + SetSentErrorMessage(true); + return false; + } + + Player* pl = m_session->GetPlayer(); + Player* plTarget = getSelectedPlayer(); + if(!plTarget) + plTarget = pl; + + sLog.outDetail(GetMangosString(LANG_ADDITEMSET), itemsetId); + + QueryResult *result = WorldDatabase.PQuery("SELECT entry FROM item_template WHERE itemset = %u",itemsetId); + + if(!result) + { + PSendSysMessage(LANG_NO_ITEMS_FROM_ITEMSET_FOUND,itemsetId); + + SetSentErrorMessage(true); + return false; + } + + do + { + Field *fields = result->Fetch(); + uint32 itemId = fields[0].GetUInt32(); + + ItemPosCountVec dest; + uint8 msg = plTarget->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, itemId, 1 ); + if( msg == EQUIP_ERR_OK ) + { + Item* item = plTarget->StoreNewItem( dest, itemId, true); + + // remove binding (let GM give it to another player later) + if(pl==plTarget) + item->SetBinding( false ); + + pl->SendNewItem(item,1,false,true); + if(pl!=plTarget) + plTarget->SendNewItem(item,1,true,false); + } + else + { + pl->SendEquipError( msg, NULL, NULL ); + PSendSysMessage(LANG_ITEM_CANNOT_CREATE, itemId, 1); + } + + }while( result->NextRow() ); + + delete result; + + return true; +} + +bool ChatHandler::HandleListItemCommand(const char* args) +{ + if(!*args) + return false; + + char* cId = extractKeyFromLink((char*)args,"Hitem"); + if(!cId) + return false; + uint32 item_id = atol(cId); + + ItemPrototype const* itemProto = item_id ? itemProto = objmgr.GetItemPrototype(item_id) : NULL; + + if(!itemProto) + { + PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, item_id); + SetSentErrorMessage(true); + return false; + } + + char* c_count = strtok(NULL, " "); + int count = c_count ? atol(c_count) : 10; + + if(count < 0) + return false; + + QueryResult *result; + + // inventory case + uint32 inv_count = 0; + result=CharacterDatabase.PQuery("SELECT COUNT(item_template) FROM character_inventory WHERE item_template='%u'",item_id); + if(result) + { + inv_count = (*result)[0].GetUInt32(); + delete result; + } + + result=CharacterDatabase.PQuery( + // 0 1 2 3 4 5 + "SELECT ci.item, cibag.slot AS bag, ci.slot, ci.guid, characters.account,characters.name " + "FROM character_inventory AS ci LEFT JOIN character_inventory AS cibag ON (cibag.item=ci.bag),characters " + "WHERE ci.item_template='%u' AND ci.guid = characters.guid LIMIT %u ", + item_id,uint32(count)); + + if(result) + { + do + { + Field *fields = result->Fetch(); + uint32 item_guid = fields[0].GetUInt32(); + uint32 item_bag = fields[1].GetUInt32(); + uint32 item_slot = fields[2].GetUInt32(); + uint32 owner_guid = fields[3].GetUInt32(); + uint32 owner_acc = fields[4].GetUInt32(); + std::string owner_name = fields[5].GetCppString(); + + char const* item_pos = 0; + if(Player::IsEquipmentPos(item_bag,item_slot)) + item_pos = "[equipped]"; + else if(Player::IsInventoryPos(item_bag,item_slot)) + item_pos = "[in inventory]"; + else if(Player::IsBankPos(item_bag,item_slot)) + item_pos = "[in bank]"; + else + item_pos = ""; + + PSendSysMessage(LANG_ITEMLIST_SLOT, + item_guid,owner_name.c_str(),owner_guid,owner_acc,item_pos); + } while (result->NextRow()); + + int64 res_count = result->GetRowCount(); + + delete result; + + if(count > res_count) + count-=res_count; + else if(count) + count = 0; + } + + // mail case + uint32 mail_count = 0; + result=CharacterDatabase.PQuery("SELECT COUNT(item_template) FROM mail_items WHERE item_template='%u'", item_id); + if(result) + { + mail_count = (*result)[0].GetUInt32(); + delete result; + } + + if(count > 0) + { + result=CharacterDatabase.PQuery( + // 0 1 2 3 4 5 6 + "SELECT mail_items.item_guid, mail.sender, mail.receiver, char_s.account, char_s.name, char_r.account, char_r.name " + "FROM mail,mail_items,characters as char_s,characters as char_r " + "WHERE mail_items.item_template='%u' AND char_s.guid = mail.sender AND char_r.guid = mail.receiver AND mail.id=mail_items.mail_id LIMIT %u", + item_id,uint32(count)); + } + else + result = NULL; + + if(result) + { + do + { + Field *fields = result->Fetch(); + uint32 item_guid = fields[0].GetUInt32(); + uint32 item_s = fields[1].GetUInt32(); + uint32 item_r = fields[2].GetUInt32(); + uint32 item_s_acc = fields[3].GetUInt32(); + std::string item_s_name = fields[4].GetCppString(); + uint32 item_r_acc = fields[5].GetUInt32(); + std::string item_r_name = fields[6].GetCppString(); + + char const* item_pos = "[in mail]"; + + PSendSysMessage(LANG_ITEMLIST_MAIL, + item_guid,item_s_name.c_str(),item_s,item_s_acc,item_r_name.c_str(),item_r,item_r_acc,item_pos); + } while (result->NextRow()); + + int64 res_count = result->GetRowCount(); + + delete result; + + if(count > res_count) + count-=res_count; + else if(count) + count = 0; + } + + // auction case + uint32 auc_count = 0; + result=CharacterDatabase.PQuery("SELECT COUNT(item_template) FROM auctionhouse WHERE item_template='%u'",item_id); + if(result) + { + auc_count = (*result)[0].GetUInt32(); + delete result; + } + + if(count > 0) + { + result=CharacterDatabase.PQuery( + // 0 1 2 3 + "SELECT auctionhouse.itemguid, auctionhouse.itemowner, characters.account, characters.name " + "FROM auctionhouse,characters WHERE auctionhouse.item_template='%u' AND characters.guid = auctionhouse.itemowner LIMIT %u", + item_id,uint32(count)); + } + else + result = NULL; + + if(result) + { + do + { + Field *fields = result->Fetch(); + uint32 item_guid = fields[0].GetUInt32(); + uint32 owner = fields[1].GetUInt32(); + uint32 owner_acc = fields[2].GetUInt32(); + std::string owner_name = fields[3].GetCppString(); + + char const* item_pos = "[in auction]"; + + PSendSysMessage(LANG_ITEMLIST_AUCTION, item_guid, owner_name.c_str(), owner, owner_acc,item_pos); + } while (result->NextRow()); + + delete result; + } + + if(inv_count+mail_count+auc_count == 0) + { + SendSysMessage(LANG_COMMAND_NOITEMFOUND); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_COMMAND_LISTITEMMESSAGE,item_id,inv_count+mail_count+auc_count,inv_count,mail_count,auc_count); + + return true; +} + +bool ChatHandler::HandleListObjectCommand(const char* args) +{ + if(!*args) + return false; + + // number or [name] Shift-click form |color|Hgameobject_entry:go_id|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameobject_entry"); + if(!cId) + return false; + + uint32 go_id = atol(cId); + + GameObjectInfo const * gInfo = objmgr.GetGameObjectInfo(go_id); + + if(!go_id || !gInfo) + { + PSendSysMessage(LANG_COMMAND_LISTOBJINVALIDID, go_id); + SetSentErrorMessage(true); + return false; + } + + char* c_count = strtok(NULL, " "); + int count = c_count ? atol(c_count) : 10; + + if(count < 0) + return false; + + Player* pl = m_session->GetPlayer(); + QueryResult *result; + + uint32 obj_count = 0; + result=WorldDatabase.PQuery("SELECT COUNT(guid) FROM gameobject WHERE id='%u'",go_id); + if(result) + { + obj_count = (*result)[0].GetUInt32(); + delete result; + } + + result = WorldDatabase.PQuery("SELECT guid, position_x, position_y, position_z, map, (POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) AS order_ FROM gameobject WHERE id = '%u' ORDER BY order_ ASC LIMIT %u", + pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(),go_id,uint32(count)); + + if (result) + { + do + { + Field *fields = result->Fetch(); + uint32 guid = fields[0].GetUInt32(); + float x = fields[1].GetFloat(); + float y = fields[2].GetFloat(); + float z = fields[3].GetFloat(); + int mapid = fields[4].GetUInt16(); + + PSendSysMessage(LANG_GO_LIST, guid, guid, gInfo->name, x, y, z, mapid); + } while (result->NextRow()); + + delete result; + } + + PSendSysMessage(LANG_COMMAND_LISTOBJMESSAGE,go_id,obj_count); + return true; +} + +bool ChatHandler::HandleNearObjectCommand(const char* args) +{ + float distance = (!*args) ? 10 : atol(args); + uint32 count = 0; + + Player* pl = m_session->GetPlayer(); + QueryResult *result = WorldDatabase.PQuery("SELECT guid, id, position_x, position_y, position_z, map, " + "(POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) AS order_ " + "FROM gameobject WHERE map='%u' AND (POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) <= '%f' ORDER BY order_", + pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), + pl->GetMapId(),pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(),distance*distance); + + if (result) + { + do + { + Field *fields = result->Fetch(); + uint32 guid = fields[0].GetUInt32(); + uint32 entry = fields[1].GetUInt32(); + float x = fields[2].GetFloat(); + float y = fields[3].GetFloat(); + float z = fields[4].GetFloat(); + int mapid = fields[5].GetUInt16(); + + GameObjectInfo const * gInfo = objmgr.GetGameObjectInfo(entry); + + if(!gInfo) + continue; + + PSendSysMessage(LANG_GO_LIST, guid, guid, gInfo->name, x, y, z, mapid); + + ++count; + } while (result->NextRow()); + + delete result; + } + + PSendSysMessage(LANG_COMMAND_NEAROBJMESSAGE,distance,count); + return true; +} + +bool ChatHandler::HandleListCreatureCommand(const char* args) +{ + if(!*args) + return false; + + // number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hcreature_entry"); + if(!cId) + return false; + + uint32 cr_id = atol(cId); + + CreatureInfo const* cInfo = objmgr.GetCreatureTemplate(cr_id); + + if(!cr_id || !cInfo) + { + PSendSysMessage(LANG_COMMAND_INVALIDCREATUREID, cr_id); + SetSentErrorMessage(true); + return false; + } + + char* c_count = strtok(NULL, " "); + int count = c_count ? atol(c_count) : 10; + + if(count < 0) + return false; + + Player* pl = m_session->GetPlayer(); + QueryResult *result; + + uint32 cr_count = 0; + result=WorldDatabase.PQuery("SELECT COUNT(guid) FROM creature WHERE id='%u'",cr_id); + if(result) + { + cr_count = (*result)[0].GetUInt32(); + delete result; + } + + result = WorldDatabase.PQuery("SELECT guid, position_x, position_y, position_z, map, (POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) AS order_ FROM creature WHERE id = '%u' ORDER BY order_ ASC LIMIT %u", + pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), cr_id,uint32(count)); + + if (result) + { + do + { + Field *fields = result->Fetch(); + uint32 guid = fields[0].GetUInt32(); + float x = fields[1].GetFloat(); + float y = fields[2].GetFloat(); + float z = fields[3].GetFloat(); + int mapid = fields[4].GetUInt16(); + + PSendSysMessage(LANG_CREATURE_LIST, guid, guid, cInfo->Name, x, y, z, mapid); + } while (result->NextRow()); + + delete result; + } + + PSendSysMessage(LANG_COMMAND_LISTCREATUREMESSAGE,cr_id,cr_count); + return true; +} + +bool ChatHandler::HandleLookupItemCommand(const char* args) +{ + if(!*args) + return false; + + std::string namepart = args; + std::wstring wnamepart; + + // converting string that we try to find to lower case + if(!Utf8toWStr(namepart,wnamepart)) + return false; + + wstrToLower(wnamepart); + + uint32 counter = 0; + + // Search in `item_template` + for (uint32 id = 0; id < sItemStorage.MaxEntry; id++) + { + ItemPrototype const *pProto = sItemStorage.LookupEntry(id); + if(!pProto) + continue; + + int loc_idx = m_session->GetSessionDbLocaleIndex(); + if ( loc_idx >= 0 ) + { + ItemLocale const *il = objmgr.GetItemLocale(pProto->ItemId); + if (il) + { + if (il->Name.size() > loc_idx && !il->Name[loc_idx].empty()) + { + std::string name = il->Name[loc_idx]; + + if (Utf8FitTo(name, wnamepart)) + { + PSendSysMessage(LANG_ITEM_LIST, id, id, name.c_str()); + ++counter; + continue; + } + } + } + } + + std::string name = pProto->Name1; + if(name.empty()) + continue; + + if (Utf8FitTo(name, wnamepart)) + { + PSendSysMessage(LANG_ITEM_LIST, id, id, name.c_str()); + ++counter; + } + } + + if (counter==0) + SendSysMessage(LANG_COMMAND_NOITEMFOUND); + + return true; +} + +bool ChatHandler::HandleLookupItemSetCommand(const char* args) +{ + if(!*args) + return false; + + std::string namepart = args; + std::wstring wnamepart; + + if(!Utf8toWStr(namepart,wnamepart)) + return false; + + // converting string that we try to find to lower case + wstrToLower( wnamepart ); + + uint32 counter = 0; // Counter for figure out that we found smth. + + // Search in ItemSet.dbc + for (uint32 id = 0; id < sItemSetStore.GetNumRows(); id++) + { + ItemSetEntry const *set = sItemSetStore.LookupEntry(id); + if(set) + { + int loc = m_session->GetSessionDbcLocale(); + std::string name = set->name[m_session->GetSessionDbcLocale()]; + if(name.empty()) + continue; + + if (!Utf8FitTo(name, wnamepart)) + { + loc = 0; + for(; loc < MAX_LOCALE; ++loc) + { + if(loc==m_session->GetSessionDbcLocale()) + continue; + + name = set->name[m_session->GetSessionDbcLocale()]; + if(name.empty()) + continue; + + if (Utf8FitTo(name, wnamepart)) + break; + } + } + + if(loc < MAX_LOCALE) + { + // send item set in "id - [namedlink locale]" format + PSendSysMessage(LANG_ITEMSET_LIST,id,id,name.c_str(),localeNames[loc]); + ++counter; + } + } + } + if (counter == 0) // if counter == 0 then we found nth + SendSysMessage(LANG_COMMAND_NOITEMSETFOUND); + return true; +} + +bool ChatHandler::HandleLookupSkillCommand(const char* args) +{ + Player* target = getSelectedPlayer(); + if(!target) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + if(!*args) + return false; + + std::string namepart = args; + std::wstring wnamepart; + + if(!Utf8toWStr(namepart,wnamepart)) + return false; + + // converting string that we try to find to lower case + wstrToLower( wnamepart ); + + uint32 counter = 0; // Counter for figure out that we found smth. + + // Search in SkillLine.dbc + for (uint32 id = 0; id < sSkillLineStore.GetNumRows(); id++) + { + SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(id); + if(skillInfo) + { + int loc = m_session->GetSessionDbcLocale(); + std::string name = skillInfo->name[loc]; + if(name.empty()) + continue; + + if (!Utf8FitTo(name, wnamepart)) + { + loc = 0; + for(; loc < MAX_LOCALE; ++loc) + { + if(loc==m_session->GetSessionDbcLocale()) + continue; + + name = skillInfo->name[loc]; + if(name.empty()) + continue; + + if (Utf8FitTo(name, wnamepart)) + break; + } + } + + if(loc < MAX_LOCALE) + { + // send skill in "id - [namedlink locale]" format + PSendSysMessage(LANG_SKILL_LIST,id,id,name.c_str(),localeNames[loc],(target->HasSkill(id) ? m_session->GetMangosString(LANG_KNOWN) : "")); + + ++counter; + } + } + } + if (counter == 0) // if counter == 0 then we found nth + SendSysMessage(LANG_COMMAND_NOSKILLFOUND); + return true; +} + +bool ChatHandler::HandleLookupSpellCommand(const char* args) +{ + Player* target = getSelectedPlayer(); + if( !target ) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + if(!*args) + return false; + + std::string namepart = args; + std::wstring wnamepart; + + if(!Utf8toWStr(namepart,wnamepart)) + return false; + + // converting string that we try to find to lower case + wstrToLower( wnamepart ); + + uint32 counter = 0; // Counter for figure out that we found smth. + + // Search in Spell.dbc + for (uint32 id = 0; id < sSpellStore.GetNumRows(); id++) + { + SpellEntry const *spellInfo = sSpellStore.LookupEntry(id); + if(spellInfo) + { + int loc = m_session->GetSessionDbcLocale(); + std::string name = spellInfo->SpellName[loc]; + if(name.empty()) + continue; + + if (!Utf8FitTo(name, wnamepart)) + { + loc = 0; + for(; loc < MAX_LOCALE; ++loc) + { + if(loc==m_session->GetSessionDbcLocale()) + continue; + + name = spellInfo->SpellName[loc]; + if(name.empty()) + continue; + + if (Utf8FitTo(name, wnamepart)) + break; + } + } + + if(loc < MAX_LOCALE) + { + bool known = target->HasSpell(id); + bool learn = (spellInfo->Effect[0] == SPELL_EFFECT_LEARN_SPELL); + + uint32 telentCost = GetTalentSpellCost(id); + + bool talent = (telentCost > 0); + bool passive = IsPassiveSpell(id); + bool active = target->HasAura(id,0) || target->HasAura(id,1) || target->HasAura(id,2); + + // unit32 used to prevent interpreting uint8 as char at output + // find rank of learned spell for learning spell, or talent rank + uint32 rank = telentCost ? telentCost : spellmgr.GetSpellRank(learn ? spellInfo->EffectTriggerSpell[0] : id); + + // send spell in "id - [name, rank N] [talent] [passive] [learn] [known]" format + std::ostringstream ss; + ss << id << " - |cffffffff|Hspell:" << id << "|h[" << name; + + // include rank in link name + if(rank) + ss << GetMangosString(LANG_SPELL_RANK) << rank; + + ss << " " << localeNames[loc] << "]|h|r"; + + if(talent) + ss << GetMangosString(LANG_TALENT); + if(passive) + ss << GetMangosString(LANG_PASSIVE); + if(learn) + ss << GetMangosString(LANG_LEARN); + if(known) + ss << GetMangosString(LANG_KNOWN); + if(active) + ss << GetMangosString(LANG_ACTIVE); + + SendSysMessage(ss.str().c_str()); + + ++counter; + } + } + } + if (counter == 0) // if counter == 0 then we found nth + SendSysMessage(LANG_COMMAND_NOSPELLFOUND); + return true; +} + +bool ChatHandler::HandleLookupQuestCommand(const char* args) +{ + Player* target = getSelectedPlayer(); + if( !target ) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + if(!*args) + return false; + + std::string namepart = args; + std::wstring wnamepart; + + // converting string that we try to find to lower case + if(!Utf8toWStr(namepart,wnamepart)) + return false; + + wstrToLower(wnamepart); + + uint32 counter = 0 ; + + ObjectMgr::QuestMap const& qTemplates = objmgr.GetQuestTemplates(); + for (ObjectMgr::QuestMap::const_iterator iter = qTemplates.begin(); iter != qTemplates.end(); ++iter) + { + Quest * qinfo = iter->second; + + int loc_idx = m_session->GetSessionDbLocaleIndex(); + if ( loc_idx >= 0 ) + { + QuestLocale const *il = objmgr.GetQuestLocale(qinfo->GetQuestId()); + if (il) + { + if (il->Title.size() > loc_idx && !il->Title[loc_idx].empty()) + { + std::string title = il->Title[loc_idx]; + + if (Utf8FitTo(title, wnamepart)) + { + QuestStatus status = target->GetQuestStatus(qinfo->GetQuestId()); + + char const* statusStr = ""; + if(status == QUEST_STATUS_COMPLETE) + { + if(target->GetQuestRewardStatus(qinfo->GetQuestId())) + statusStr = GetMangosString(LANG_COMMAND_QUEST_REWARDED); + else + statusStr = GetMangosString(LANG_COMMAND_QUEST_COMPLETE); + } + else if(status == QUEST_STATUS_INCOMPLETE) + statusStr = GetMangosString(LANG_COMMAND_QUEST_ACTIVE); + + PSendSysMessage(LANG_QUEST_LIST,qinfo->GetQuestId(),qinfo->GetQuestId(),title.c_str(),(status == QUEST_STATUS_COMPLETE ? GetMangosString(LANG_COMPLETE) : (status == QUEST_STATUS_INCOMPLETE ? GetMangosString(LANG_ACTIVE) : "") )); + ++counter; + continue; + } + } + } + } + + std::string title = qinfo->GetTitle(); + if(title.empty()) + continue; + + if (Utf8FitTo(title, wnamepart)) + { + QuestStatus status = target->GetQuestStatus(qinfo->GetQuestId()); + + char const* statusStr = ""; + if(status == QUEST_STATUS_COMPLETE) + { + if(target->GetQuestRewardStatus(qinfo->GetQuestId())) + statusStr = GetMangosString(LANG_COMMAND_QUEST_REWARDED); + else + statusStr = GetMangosString(LANG_COMMAND_QUEST_COMPLETE); + } + else if(status == QUEST_STATUS_INCOMPLETE) + statusStr = GetMangosString(LANG_COMMAND_QUEST_ACTIVE); + + PSendSysMessage(LANG_QUEST_LIST,qinfo->GetQuestId(),qinfo->GetQuestId(), title.c_str(),(status == QUEST_STATUS_COMPLETE ? GetMangosString(LANG_COMPLETE) : (status == QUEST_STATUS_INCOMPLETE ? GetMangosString(LANG_ACTIVE) : "") )); + ++counter; + } + } + + if (counter==0) + SendSysMessage(LANG_COMMAND_NOQUESTFOUND); + + return true; +} + +bool ChatHandler::HandleLookupCreatureCommand(const char* args) +{ + if(!*args) + return false; + + std::string namepart = args; + std::wstring wnamepart; + + // converting string that we try to find to lower case + if(!Utf8toWStr(namepart,wnamepart)) + return false; + + wstrToLower(wnamepart); + + uint32 counter = 0; + + for (uint32 id = 0; id< sCreatureStorage.MaxEntry; id++ ) + { + CreatureInfo const* cInfo = sCreatureStorage.LookupEntry(id); + if(!cInfo) + continue; + + int loc_idx = m_session->GetSessionDbLocaleIndex(); + if ( loc_idx >= 0 ) + { + CreatureLocale const *cl = objmgr.GetCreatureLocale(id); + if (cl) + { + if (cl->Name.size() > loc_idx && !cl->Name[loc_idx].empty()) + { + std::string name = cl->Name[loc_idx]; + + if (Utf8FitTo(name, wnamepart)) + { + PSendSysMessage(LANG_CREATURE_ENTRY_LIST, id, id, name.c_str()); + ++counter; + continue; + } + } + } + } + + std::string name = cInfo->Name; + if(name.empty()) + continue; + + if (Utf8FitTo(name, wnamepart)) + { + PSendSysMessage(LANG_CREATURE_ENTRY_LIST,id,id,name.c_str()); + ++counter; + } + } + + if (counter==0) + SendSysMessage(LANG_COMMAND_NOCREATUREFOUND); + + return true; +} + +bool ChatHandler::HandleLookupObjectCommand(const char* args) +{ + if(!*args) + return false; + + std::string namepart = args; + std::wstring wnamepart; + + // converting string that we try to find to lower case + if(!Utf8toWStr(namepart,wnamepart)) + return false; + + wstrToLower(wnamepart); + + uint32 counter = 0; + + for (uint32 id = 0; id< sGOStorage.MaxEntry; id++ ) + { + GameObjectInfo const* gInfo = sGOStorage.LookupEntry(id); + if(!gInfo) + continue; + + int loc_idx = m_session->GetSessionDbLocaleIndex(); + if ( loc_idx >= 0 ) + { + GameObjectLocale const *gl = objmgr.GetGameObjectLocale(id); + if (gl) + { + if (gl->Name.size() > loc_idx && !gl->Name[loc_idx].empty()) + { + std::string name = gl->Name[loc_idx]; + + if (Utf8FitTo(name, wnamepart)) + { + PSendSysMessage(LANG_GO_ENTRY_LIST, id, id, name.c_str()); + ++counter; + continue; + } + } + } + } + + std::string name = gInfo->name; + if(name.empty()) + continue; + + if(Utf8FitTo(name, wnamepart)) + { + PSendSysMessage(LANG_GO_ENTRY_LIST, id, id, name.c_str()); + ++counter; + } + } + + if(counter==0) + SendSysMessage(LANG_COMMAND_NOGAMEOBJECTFOUND); + + return true; +} + +/** \brief GM command level 3 - Create a guild. + * + * This command allows a GM (level 3) to create a guild. + * + * The "args" parameter contains the name of the guild leader + * and then the name of the guild. + * + */ +bool ChatHandler::HandleGuildCreateCommand(const char* args) +{ + + if (!*args) + return false; + + Guild *guild; + Player * player; + char *lname,*gname; + std::string guildname; + + lname = strtok((char*)args, " "); + gname = strtok(NULL, ""); + + if(!lname) + return false; + else if(!gname) + { + SendSysMessage(LANG_INSERT_GUILD_NAME); + SetSentErrorMessage(true); + return false; + } + + guildname = gname; + player = ObjectAccessor::Instance().FindPlayerByName(lname); + + if(!player) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + if(!player->GetGuildId()) + { + guild = new Guild; + if(!guild->create(player->GetGUID(),guildname)) + { + delete guild; + SendSysMessage(LANG_GUILD_NOT_CREATED); + SetSentErrorMessage(true); + return false; + } + + objmgr.AddGuild(guild); + } + else + SendSysMessage(LANG_PLAYER_IN_GUILD); + + return true; +} + +bool ChatHandler::HandleGuildInviteCommand(const char *args) +{ + if(!*args) + return false; + + char* par1 = strtok((char*)args, " "); + char* par2 = strtok (NULL, ""); + if(!par1 || !par2) + return false; + + std::string glName = par2; + Guild* targetGuild = objmgr.GetGuildByName(glName); + if(!targetGuild) + return false; + + std::string plName = par1; + if(!normalizePlayerName(plName)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + uint64 plGuid = 0; + if(Player* targetPlayer = ObjectAccessor::Instance().FindPlayerByName(plName.c_str())) + plGuid = targetPlayer->GetGUID(); + else + plGuid = objmgr.GetPlayerGUIDByName(plName.c_str()); + + if(!plGuid) + false; + + // players's guild membership checked in AddMember before add + if(!targetGuild->AddMember(plGuid,targetGuild->GetLowestRank())) + return false; + + return true; +} + +bool ChatHandler::HandleGuildUninviteCommand(const char *args) +{ + if(!*args) + return false; + + char* par1 = strtok((char*)args, " "); + if(!par1) + return false; + std::string plName = par1; + if(!normalizePlayerName(plName)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + uint64 plGuid = 0; + uint32 glId = 0; + if(Player* targetPlayer = ObjectAccessor::Instance().FindPlayerByName(plName.c_str())) + { + plGuid = targetPlayer->GetGUID(); + glId = targetPlayer->GetGuildId(); + } + else + { + plGuid = objmgr.GetPlayerGUIDByName(plName.c_str()); + glId = Player::GetGuildIdFromDB(plGuid); + } + + if(!plGuid || !glId) + return false; + + Guild* targetGuild = objmgr.GetGuildById(glId); + if(!targetGuild) + return false; + + targetGuild->DelMember(plGuid); + + return true; +} + +bool ChatHandler::HandleGuildRankCommand(const char *args) +{ + if(!*args) + return false; + + char* par1 = strtok((char*)args, " "); + char* par2 = strtok(NULL, " "); + if(!par1 || !par2) + return false; + std::string plName = par1; + if(!normalizePlayerName(plName)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + uint64 plGuid = 0; + uint32 glId = 0; + if(Player* targetPlayer = ObjectAccessor::Instance().FindPlayerByName(plName.c_str())) + { + plGuid = targetPlayer->GetGUID(); + glId = targetPlayer->GetGuildId(); + } + else + { + plGuid = objmgr.GetPlayerGUIDByName(plName.c_str()); + glId = Player::GetGuildIdFromDB(plGuid); + } + + if(!plGuid || !glId) + return false; + + Guild* targetGuild = objmgr.GetGuildById(glId); + if(!targetGuild) + return false; + + uint32 newrank = uint32(atoi(par2)); + if(newrank > targetGuild->GetLowestRank()) + return false; + + targetGuild->ChangeRank(plGuid,newrank); + + return true; +} + +bool ChatHandler::HandleGuildDeleteCommand(const char* args) +{ + if(!*args) + return false; + + char* par1 = strtok((char*)args, " "); + if(!par1) + return false; + + std::string gld = par1; + + Guild* targetGuild = objmgr.GetGuildByName(gld); + if(!targetGuild) + return false; + + targetGuild->Disband(); + + return true; +} + +bool ChatHandler::HandleGetDistanceCommand(const char* /*args*/) +{ + Unit* pUnit = getSelectedUnit(); + + if(!pUnit) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_DISTANCE, m_session->GetPlayer()->GetDistance(pUnit),m_session->GetPlayer()->GetDistance2d(pUnit)); + + return true; +} + +// FIX-ME!!! + +bool ChatHandler::HandleAddWeaponCommand(const char* /*args*/) +{ + /*if (!*args) + return false; + + uint64 guid = m_session->GetPlayer()->GetSelection(); + if (guid == 0) + { + SendSysMessage(LANG_NO_SELECTION); + return true; + } + + Creature *pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid); + + if(!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + return true; + } + + char* pSlotID = strtok((char*)args, " "); + if (!pSlotID) + return false; + + char* pItemID = strtok(NULL, " "); + if (!pItemID) + return false; + + uint32 ItemID = atoi(pItemID); + uint32 SlotID = atoi(pSlotID); + + ItemPrototype* tmpItem = objmgr.GetItemPrototype(ItemID); + + bool added = false; + if(tmpItem) + { + switch(SlotID) + { + case 1: + pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, ItemID); + added = true; + break; + case 2: + pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY_01, ItemID); + added = true; + break; + case 3: + pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY_02, ItemID); + added = true; + break; + default: + PSendSysMessage(LANG_ITEM_SLOT_NOT_EXIST,SlotID); + added = false; + break; + } + if(added) + { + PSendSysMessage(LANG_ITEM_ADDED_TO_SLOT,ItemID,tmpItem->Name1,SlotID); + } + } + else + { + PSendSysMessage(LANG_ITEM_NOT_FOUND,ItemID); + return true; + } + */ + return true; +} + +bool ChatHandler::HandleDieCommand(const char* /*args*/) +{ + Unit* target = getSelectedUnit(); + + if(!target || !m_session->GetPlayer()->GetSelection()) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if( target->isAlive() ) + { + m_session->GetPlayer()->DealDamage(target, target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + return true; +} + +bool ChatHandler::HandleDamageCommand(const char * args) +{ + if (!*args) + return false; + + Unit* target = getSelectedUnit(); + + if(!target || !m_session->GetPlayer()->GetSelection()) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if( !target->isAlive() ) + return true; + + char* damageStr = strtok((char*)args, " "); + if(!damageStr) + return false; + + int32 damage = atoi((char*)damageStr); + if(damage <=0) + return true; + + char* schoolStr = strtok((char*)NULL, " "); + + // flat melee damage without resistence/etc reduction + if(!schoolStr) + { + m_session->GetPlayer()->DealDamage(target, damage, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + m_session->GetPlayer()->SendAttackStateUpdate (HITINFO_NORMALSWING2, target, 1, SPELL_SCHOOL_MASK_NORMAL, damage, 0, 0, VICTIMSTATE_NORMAL, 0); + return true; + } + + uint32 school = schoolStr ? atoi((char*)schoolStr) : SPELL_SCHOOL_NORMAL; + if(school >= MAX_SPELL_SCHOOL) + return false; + + SpellSchoolMask schoolmask = SpellSchoolMask(1 << school); + + if ( schoolmask & SPELL_SCHOOL_MASK_NORMAL ) + damage = m_session->GetPlayer()->CalcArmorReducedDamage(target, damage); + + char* spellStr = strtok((char*)NULL, " "); + + // melee damage by specific school + if(!spellStr) + { + uint32 absorb = 0; + uint32 resist = 0; + + m_session->GetPlayer()->CalcAbsorbResist(target,schoolmask, SPELL_DIRECT_DAMAGE, damage, &absorb, &resist); + + if (damage <= absorb + resist) + return true; + + damage -= absorb + resist; + + m_session->GetPlayer()->DealDamage(target, damage, NULL, DIRECT_DAMAGE, schoolmask, NULL, false); + m_session->GetPlayer()->SendAttackStateUpdate (HITINFO_NORMALSWING2, target, 1, schoolmask, damage, absorb, resist, VICTIMSTATE_NORMAL, 0); + return true; + } + + // non-melee damage + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spellid = extractSpellIdFromLink((char*)args); + if(!spellid || !sSpellStore.LookupEntry(spellid)) + return false; + + m_session->GetPlayer()->SpellNonMeleeDamageLog(target, spellid, damage, false); + return true; +} + +bool ChatHandler::HandleModifyArenaCommand(const char * args) +{ + if (!*args) + return false; + + Player *target = getSelectedPlayer(); + if(!target) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + int32 amount = (uint32)atoi(args); + + target->ModifyArenaPoints(amount); + + PSendSysMessage(LANG_COMMAND_MODIFY_ARENA, target->GetName(), target->GetArenaPoints()); + + return true; +} + +bool ChatHandler::HandleReviveCommand(const char* args) +{ + Player* SelectedPlayer = NULL; + + if (*args) + { + std::string name = args; + if(!normalizePlayerName(name)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + SelectedPlayer = objmgr.GetPlayer(name.c_str()); + } + else + SelectedPlayer = getSelectedPlayer(); + + if(!SelectedPlayer) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + SelectedPlayer->ResurrectPlayer(0.5f); + SelectedPlayer->SpawnCorpseBones(); + SelectedPlayer->SaveToDB(); + return true; +} + +bool ChatHandler::HandleAuraCommand(const char* args) +{ + char* px = strtok((char*)args, " "); + if (!px) + return false; + + Unit *target = getSelectedUnit(); + if(!target) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + uint32 spellID = (uint32)atoi(px); + SpellEntry const *spellInfo = sSpellStore.LookupEntry( spellID ); + if(spellInfo) + { + for(uint32 i = 0;i<3;i++) + { + uint8 eff = spellInfo->Effect[i]; + if (eff>=TOTAL_SPELL_EFFECTS) + continue; + if( IsAreaAuraEffect(eff) || + eff == SPELL_EFFECT_APPLY_AURA || + eff == SPELL_EFFECT_PERSISTENT_AREA_AURA ) + { + Aura *Aur = CreateAura(spellInfo, i, NULL, target); + target->AddAura(Aur); + } + } + } + + return true; +} + +bool ChatHandler::HandleUnAuraCommand(const char* args) +{ + char* px = strtok((char*)args, " "); + if (!px) + return false; + + Unit *target = getSelectedUnit(); + if(!target) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + std::string argstr = args; + if (argstr == "all") + { + target->RemoveAllAuras(); + return true; + } + + uint32 spellID = (uint32)atoi(px); + target->RemoveAurasDueToSpell(spellID); + + return true; +} + +bool ChatHandler::HandleLinkGraveCommand(const char* args) +{ + if(!*args) + return false; + + char* px = strtok((char*)args, " "); + if (!px) + return false; + + uint32 g_id = (uint32)atoi(px); + + uint32 g_team; + + char* px2 = strtok(NULL, " "); + + if (!px2) + g_team = 0; + else if (strncmp(px2,"horde",6)==0) + g_team = HORDE; + else if (strncmp(px2,"alliance",9)==0) + g_team = ALLIANCE; + else + return false; + + WorldSafeLocsEntry const* graveyard = sWorldSafeLocsStore.LookupEntry(g_id); + + if(!graveyard ) + { + PSendSysMessage(LANG_COMMAND_GRAVEYARDNOEXIST, g_id); + SetSentErrorMessage(true); + return false; + } + + Player* player = m_session->GetPlayer(); + + uint32 zoneId = player->GetZoneId(); + + AreaTableEntry const *areaEntry = GetAreaEntryByAreaID(zoneId); + if(!areaEntry || areaEntry->zone !=0 ) + { + PSendSysMessage(LANG_COMMAND_GRAVEYARDWRONGZONE, g_id,zoneId); + SetSentErrorMessage(true); + return false; + } + + if(graveyard->map_id != areaEntry->mapid && g_team != 0) + { + SendSysMessage(LANG_COMMAND_GRAVEYARDWRONGTEAM); + SetSentErrorMessage(true); + return false; + } + + if(objmgr.AddGraveYardLink(g_id,player->GetZoneId(),g_team)) + PSendSysMessage(LANG_COMMAND_GRAVEYARDLINKED, g_id,zoneId); + else + PSendSysMessage(LANG_COMMAND_GRAVEYARDALRLINKED, g_id,zoneId); + + return true; +} + +bool ChatHandler::HandleNearGraveCommand(const char* args) +{ + uint32 g_team; + + size_t argslen = strlen(args); + + if(!*args) + g_team = 0; + else if (strncmp((char*)args,"horde",argslen)==0) + g_team = HORDE; + else if (strncmp((char*)args,"alliance",argslen)==0) + g_team = ALLIANCE; + else + return false; + + Player* player = m_session->GetPlayer(); + + WorldSafeLocsEntry const* graveyard = objmgr.GetClosestGraveYard( + player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(),player->GetMapId(),g_team); + + if(graveyard) + { + uint32 g_id = graveyard->ID; + + GraveYardData const* data = objmgr.FindGraveYardData(g_id,player->GetZoneId()); + if (!data) + { + PSendSysMessage(LANG_COMMAND_GRAVEYARDERROR,g_id); + SetSentErrorMessage(true); + return false; + } + + g_team = data->team; + + std::string team_name = GetMangosString(LANG_COMMAND_GRAVEYARD_NOTEAM); + + if(g_team == 0) + team_name = GetMangosString(LANG_COMMAND_GRAVEYARD_ANY); + else if(g_team == HORDE) + team_name = GetMangosString(LANG_COMMAND_GRAVEYARD_HORDE); + else if(g_team == ALLIANCE) + team_name = GetMangosString(LANG_COMMAND_GRAVEYARD_ALLIANCE); + + PSendSysMessage(LANG_COMMAND_GRAVEYARDNEAREST, g_id,team_name.c_str(),player->GetZoneId()); + } + else + { + std::string team_name; + + if(g_team == 0) + team_name = GetMangosString(LANG_COMMAND_GRAVEYARD_ANY); + else if(g_team == HORDE) + team_name = GetMangosString(LANG_COMMAND_GRAVEYARD_HORDE); + else if(g_team == ALLIANCE) + team_name = GetMangosString(LANG_COMMAND_GRAVEYARD_ALLIANCE); + + if(g_team == ~uint32(0)) + PSendSysMessage(LANG_COMMAND_ZONENOGRAVEYARDS, player->GetZoneId()); + else + PSendSysMessage(LANG_COMMAND_ZONENOGRAFACTION, player->GetZoneId(),team_name.c_str()); + } + + return true; +} + +bool ChatHandler::HandleSpawnTransportCommand(const char* /*args*/) +{ + return true; +} + +//play npc emote +bool ChatHandler::HandlePlayEmoteCommand(const char* args) +{ + uint32 emote = atoi((char*)args); + + Creature* target = getSelectedCreature(); + if(!target) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + target->SetUInt32Value(UNIT_NPC_EMOTESTATE,emote); + + return true; +} + +bool ChatHandler::HandleNpcInfoCommand(const char* /*args*/) +{ + Creature* target = getSelectedCreature(); + + if(!target) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + uint32 faction = target->getFaction(); + uint32 npcflags = target->GetUInt32Value(UNIT_NPC_FLAGS); + uint32 displayid = target->GetDisplayId(); + uint32 nativeid = target->GetNativeDisplayId(); + uint32 Entry = target->GetEntry(); + CreatureInfo const* cInfo = target->GetCreatureInfo(); + + int32 curRespawnDelay = target->GetRespawnTimeEx()-time(NULL); + if(curRespawnDelay < 0) + curRespawnDelay = 0; + std::string curRespawnDelayStr = secsToTimeString(curRespawnDelay,true); + std::string defRespawnDelayStr = secsToTimeString(target->GetRespawnDelay(),true); + + PSendSysMessage(LANG_NPCINFO_CHAR, target->GetDBTableGUIDLow(), faction, npcflags, Entry, displayid, nativeid); + PSendSysMessage(LANG_NPCINFO_LEVEL, target->getLevel()); + PSendSysMessage(LANG_NPCINFO_HEALTH,target->GetCreateHealth(), target->GetMaxHealth(), target->GetHealth()); + PSendSysMessage(LANG_NPCINFO_FLAGS, target->GetUInt32Value(UNIT_FIELD_FLAGS), target->GetUInt32Value(UNIT_DYNAMIC_FLAGS), target->getFaction()); + PSendSysMessage(LANG_COMMAND_RAWPAWNTIMES, defRespawnDelayStr.c_str(),curRespawnDelayStr.c_str()); + PSendSysMessage(LANG_NPCINFO_LOOT, cInfo->lootid,cInfo->pickpocketLootId,cInfo->SkinLootId); + PSendSysMessage(LANG_NPCINFO_DUNGEON_ID, target->GetInstanceId()); + PSendSysMessage(LANG_NPCINFO_POSITION,float(target->GetPositionX()), float(target->GetPositionY()), float(target->GetPositionZ())); + + if ((npcflags & UNIT_NPC_FLAG_VENDOR) ) + { + SendSysMessage(LANG_NPCINFO_VENDOR); + } + if ((npcflags & UNIT_NPC_FLAG_TRAINER) ) + { + SendSysMessage(LANG_NPCINFO_TRAINER); + } + + return true; +} + +bool ChatHandler::HandleExploreCheatCommand(const char* args) +{ + if (!*args) + return false; + + int flag = atoi((char*)args); + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + if (flag != 0) + { + PSendSysMessage(LANG_YOU_SET_EXPLORE_ALL, chr->GetName()); + if(chr!=m_session->GetPlayer()) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_EXPLORE_SET_ALL,m_session->GetPlayer()->GetName()); + } + else + { + PSendSysMessage(LANG_YOU_SET_EXPLORE_NOTHING, chr->GetName()); + if(chr!=m_session->GetPlayer()) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_EXPLORE_SET_NOTHING,m_session->GetPlayer()->GetName()); + } + + for (uint8 i=0; i<128; i++) + { + if (flag != 0) + { + m_session->GetPlayer()->SetFlag(PLAYER_EXPLORED_ZONES_1+i,0xFFFFFFFF); + } + else + { + m_session->GetPlayer()->SetFlag(PLAYER_EXPLORED_ZONES_1+i,0); + } + } + + return true; +} + +bool ChatHandler::HandleHoverCommand(const char* args) +{ + char* px = strtok((char*)args, " "); + uint32 flag; + if (!px) + flag = 1; + else + flag = atoi(px); + + m_session->GetPlayer()->SetHover(flag); + + if (flag) + SendSysMessage(LANG_HOVER_ENABLED); + else + SendSysMessage(LANG_HOVER_DISABLED); + + return true; +} + +bool ChatHandler::HandleLevelUpCommand(const char* args) +{ + char* px = strtok((char*)args, " "); + char* py = strtok((char*)NULL, " "); + + // command format parsing + char* pname = (char*)NULL; + int addlevel = 1; + + if(px && py) // .levelup name level + { + addlevel = atoi(py); + pname = px; + } + else if(px && !py) // .levelup name OR .levelup level + { + if(isalpha(px[0])) // .levelup name + pname = px; + else // .levelup level + addlevel = atoi(px); + } + // else .levelup - nothing do for prepering + + // player + Player *chr = NULL; + uint64 chr_guid = 0; + + std::string name; + + if(pname) // player by name + { + name = pname; + if(!normalizePlayerName(name)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + chr = objmgr.GetPlayer(name.c_str()); + if(!chr) // not in game + { + chr_guid = objmgr.GetPlayerGUIDByName(name); + if (chr_guid == 0) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + } + } + else // player by selection + { + chr = getSelectedPlayer(); + + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + name = chr->GetName(); + } + + assert(chr || chr_guid); + + int32 oldlevel = chr ? chr->getLevel() : Player::GetUInt32ValueFromDB(UNIT_FIELD_LEVEL,chr_guid); + int32 newlevel = oldlevel + addlevel; + if(newlevel < 1) + newlevel = 1; + if(newlevel > 255) // hardcoded maximum level + newlevel = 255; + + if(chr) + { + chr->GiveLevel(newlevel); + chr->InitTalentForLevel(); + chr->SetUInt32Value(PLAYER_XP,0); + + if(oldlevel == newlevel) + ChatHandler(chr).SendSysMessage(LANG_YOURS_LEVEL_PROGRESS_RESET); + else + if(oldlevel < newlevel) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_LEVEL_UP,newlevel-oldlevel); + else + if(oldlevel > newlevel) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_LEVEL_DOWN,newlevel-oldlevel); + } + else + { + // update levle and XP at level, all other will be updated at loading + Tokens values; + Player::LoadValuesArrayFromDB(values,chr_guid); + Player::SetUInt32ValueInArray(values,UNIT_FIELD_LEVEL,newlevel); + Player::SetUInt32ValueInArray(values,PLAYER_XP,0); + Player::SaveValuesArrayInDB(values,chr_guid); + } + + if(m_session->GetPlayer() != chr) // including chr==NULL + PSendSysMessage(LANG_YOU_CHANGE_LVL,name.c_str(),newlevel); + return true; +} + +bool ChatHandler::HandleShowAreaCommand(const char* args) +{ + if (!*args) + return false; + + int area = atoi((char*)args); + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + int offset = area / 32; + uint32 val = (uint32)(1 << (area % 32)); + + if(offset >= 128) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + uint32 currFields = chr->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset); + chr->SetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset, (uint32)(currFields | val)); + + SendSysMessage(LANG_EXPLORE_AREA); + return true; +} + +bool ChatHandler::HandleHideAreaCommand(const char* args) +{ + if (!*args) + return false; + + int area = atoi((char*)args); + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + int offset = area / 32; + uint32 val = (uint32)(1 << (area % 32)); + + if(offset >= 128) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + uint32 currFields = chr->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset); + chr->SetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset, (uint32)(currFields ^ val)); + + SendSysMessage(LANG_UNEXPLORE_AREA); + return true; +} + +bool ChatHandler::HandleUpdate(const char* args) +{ + if(!*args) + return false; + + uint32 updateIndex; + uint32 value; + + char* pUpdateIndex = strtok((char*)args, " "); + + Unit* chr = getSelectedUnit(); + if (chr == NULL) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if(!pUpdateIndex) + { + return true; + } + updateIndex = atoi(pUpdateIndex); + //check updateIndex + if(chr->GetTypeId() == TYPEID_PLAYER) + { + if (updateIndex>=PLAYER_END) return true; + } + else + { + if (updateIndex>=UNIT_END) return true; + } + + char* pvalue = strtok(NULL, " "); + if (!pvalue) + { + value=chr->GetUInt32Value(updateIndex); + + PSendSysMessage(LANG_UPDATE, chr->GetGUIDLow(),updateIndex,value); + return true; + } + + value=atoi(pvalue); + + PSendSysMessage(LANG_UPDATE_CHANGE, chr->GetGUIDLow(),updateIndex,value); + + chr->SetUInt32Value(updateIndex,value); + + return true; +} + +bool ChatHandler::HandleBankCommand(const char* /*args*/) +{ + m_session->SendShowBank( m_session->GetPlayer()->GetGUID() ); + + return true; +} + +bool ChatHandler::HandleChangeWeather(const char* args) +{ + if(!*args) + return false; + + //Weather is OFF + if (!sWorld.getConfig(CONFIG_WEATHER)) + { + SendSysMessage(LANG_WEATHER_DISABLED); + SetSentErrorMessage(true); + return false; + } + + //*Change the weather of a cell + char* px = strtok((char*)args, " "); + char* py = strtok(NULL, " "); + + if (!px || !py) + return false; + + uint32 type = (uint32)atoi(px); //0 to 3, 0: fine, 1: rain, 2: snow, 3: sand + float grade = (float)atof(py); //0 to 1, sending -1 is instand good weather + + Player *player = m_session->GetPlayer(); + uint32 zoneid = player->GetZoneId(); + + Weather* wth = sWorld.FindWeather(zoneid); + + if(!wth) + wth = sWorld.AddWeather(zoneid); + if(!wth) + { + SendSysMessage(LANG_NO_WEATHER); + SetSentErrorMessage(true); + return false; + } + + wth->SetWeather(WeatherType(type), grade); + + return true; +} + +bool ChatHandler::HandleSetValue(const char* args) +{ + if(!*args) + return false; + + char* px = strtok((char*)args, " "); + char* py = strtok(NULL, " "); + char* pz = strtok(NULL, " "); + + if (!px || !py) + return false; + + Unit* target = getSelectedUnit(); + if(!target) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + uint64 guid = target->GetGUID(); + + uint32 Opcode = (uint32)atoi(px); + if(Opcode >= target->GetValuesCount()) + { + PSendSysMessage(LANG_TOO_BIG_INDEX, Opcode, GUID_LOPART(guid), target->GetValuesCount()); + return false; + } + uint32 iValue; + float fValue; + bool isint32 = true; + if(pz) + isint32 = (bool)atoi(pz); + if(isint32) + { + iValue = (uint32)atoi(py); + sLog.outDebug(GetMangosString(LANG_SET_UINT), GUID_LOPART(guid), Opcode, iValue); + target->SetUInt32Value( Opcode , iValue ); + PSendSysMessage(LANG_SET_UINT_FIELD, GUID_LOPART(guid), Opcode,iValue); + } + else + { + fValue = (float)atof(py); + sLog.outDebug(GetMangosString(LANG_SET_FLOAT), GUID_LOPART(guid), Opcode, fValue); + target->SetFloatValue( Opcode , fValue ); + PSendSysMessage(LANG_SET_FLOAT_FIELD, GUID_LOPART(guid), Opcode,fValue); + } + + return true; +} + +bool ChatHandler::HandleGetValue(const char* args) +{ + if(!*args) + return false; + + char* px = strtok((char*)args, " "); + char* pz = strtok(NULL, " "); + + if (!px) + return false; + + Unit* target = getSelectedUnit(); + if(!target) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + uint64 guid = target->GetGUID(); + + uint32 Opcode = (uint32)atoi(px); + if(Opcode >= target->GetValuesCount()) + { + PSendSysMessage(LANG_TOO_BIG_INDEX, Opcode, GUID_LOPART(guid), target->GetValuesCount()); + return false; + } + uint32 iValue; + float fValue; + bool isint32 = true; + if(pz) + isint32 = (bool)atoi(pz); + + if(isint32) + { + iValue = target->GetUInt32Value( Opcode ); + sLog.outDebug(GetMangosString(LANG_GET_UINT), GUID_LOPART(guid), Opcode, iValue); + PSendSysMessage(LANG_GET_UINT_FIELD, GUID_LOPART(guid), Opcode, iValue); + } + else + { + fValue = target->GetFloatValue( Opcode ); + sLog.outDebug(GetMangosString(LANG_GET_FLOAT), GUID_LOPART(guid), Opcode, fValue); + PSendSysMessage(LANG_GET_FLOAT_FIELD, GUID_LOPART(guid), Opcode, fValue); + } + + return true; +} + +bool ChatHandler::HandleSet32Bit(const char* args) +{ + if(!*args) + return false; + + char* px = strtok((char*)args, " "); + char* py = strtok(NULL, " "); + + if (!px || !py) + return false; + + uint32 Opcode = (uint32)atoi(px); + uint32 Value = (uint32)atoi(py); + if (Value > 32) //uint32 = 32 bits + return false; + + sLog.outDebug(GetMangosString(LANG_SET_32BIT), Opcode, Value); + + m_session->GetPlayer( )->SetUInt32Value( Opcode , 2^Value ); + + PSendSysMessage(LANG_SET_32BIT_FIELD, Opcode,1); + return true; +} + +bool ChatHandler::HandleMod32Value(const char* args) +{ + if(!*args) + return false; + + char* px = strtok((char*)args, " "); + char* py = strtok(NULL, " "); + + if (!px || !py) + return false; + + uint32 Opcode = (uint32)atoi(px); + int Value = atoi(py); + + if(Opcode >= m_session->GetPlayer()->GetValuesCount()) + { + PSendSysMessage(LANG_TOO_BIG_INDEX, Opcode, m_session->GetPlayer()->GetGUIDLow(), m_session->GetPlayer( )->GetValuesCount()); + return false; + } + + sLog.outDebug(GetMangosString(LANG_CHANGE_32BIT), Opcode, Value); + + int CurrentValue = (int)m_session->GetPlayer( )->GetUInt32Value( Opcode ); + + CurrentValue += Value; + m_session->GetPlayer( )->SetUInt32Value( Opcode , (uint32)CurrentValue ); + + PSendSysMessage(LANG_CHANGE_32BIT_FIELD, Opcode,CurrentValue); + + return true; +} + +bool ChatHandler::HandleAddTeleCommand(const char * args) +{ + if(!*args) + return false; + QueryResult *result; + Player *player=m_session->GetPlayer(); + if (!player) return false; + + std::string name = args; + WorldDatabase.escape_string(name); + result = WorldDatabase.PQuery("SELECT id FROM game_tele WHERE name = '%s'",name.c_str()); + if (result) + { + SendSysMessage(LANG_COMMAND_TP_ALREADYEXIST); + delete result; + SetSentErrorMessage(true); + return false; + } + + float x = player->GetPositionX(); + float y = player->GetPositionY(); + float z = player->GetPositionZ(); + float ort = player->GetOrientation(); + int mapid = player->GetMapId(); + + if(WorldDatabase.PExecuteLog("INSERT INTO game_tele (position_x,position_y,position_z,orientation,map,name) VALUES (%f,%f,%f,%f,%d,'%s')",x,y,z,ort,mapid,name.c_str())) + { + SendSysMessage(LANG_COMMAND_TP_ADDED); + } + else + { + SendSysMessage(LANG_COMMAND_TP_ADDEDERR); + SetSentErrorMessage(true); + return false; + } + + return true; +} + +bool ChatHandler::HandleDelTeleCommand(const char * args) +{ + if(!*args) + return false; + + std::string name = args; + WorldDatabase.escape_string(name); + + QueryResult *result=WorldDatabase.PQuery("SELECT id FROM game_tele WHERE name = '%s'",name.c_str()); + if (!result) + { + SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); + SetSentErrorMessage(true); + return false; + } + delete result; + + if(WorldDatabase.PExecuteLog("DELETE FROM game_tele WHERE name = '%s'",name.c_str())) + { + SendSysMessage(LANG_COMMAND_TP_DELETED); + } + else + { + SendSysMessage(LANG_COMMAND_TP_DELETEERR); + SetSentErrorMessage(true); + return false; + } + return true; +} + +bool ChatHandler::HandleListAurasCommand (const char * /*args*/) +{ + Unit *unit = getSelectedUnit(); + if(!unit) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + char const* talentStr = GetMangosString(LANG_TALENT); + char const* passiveStr = GetMangosString(LANG_PASSIVE); + + Unit::AuraMap const& uAuras = unit->GetAuras(); + PSendSysMessage(LANG_COMMAND_TARGET_LISTAURAS, uAuras.size()); + for (Unit::AuraMap::const_iterator itr = uAuras.begin(); itr != uAuras.end(); ++itr) + { + bool talent = GetTalentSpellCost(itr->second->GetId()) > 0; + PSendSysMessage(LANG_COMMAND_TARGET_AURADETAIL, itr->second->GetId(), itr->second->GetEffIndex(), + itr->second->GetModifier()->m_auraname, itr->second->GetAuraDuration(), itr->second->GetAuraMaxDuration(), + itr->second->GetSpellProto()->SpellName[m_session->GetSessionDbcLocale()], + (itr->second->IsPassive() ? passiveStr : ""),(talent ? talentStr : ""), + IS_PLAYER_GUID(itr->second->GetCasterGUID()) ? "player" : "creature",GUID_LOPART(itr->second->GetCasterGUID())); + } + for (int i = 0; i < TOTAL_AURAS; i++) + { + Unit::AuraList const& uAuraList = unit->GetAurasByType(AuraType(i)); + if (uAuraList.empty()) continue; + PSendSysMessage(LANG_COMMAND_TARGET_LISTAURATYPE, uAuraList.size(), i); + for (Unit::AuraList::const_iterator itr = uAuraList.begin(); itr != uAuraList.end(); ++itr) + { + bool talent = GetTalentSpellCost((*itr)->GetId()) > 0; + PSendSysMessage(LANG_COMMAND_TARGET_AURASIMPLE, (*itr)->GetId(), (*itr)->GetEffIndex(), + (*itr)->GetSpellProto()->SpellName[m_session->GetSessionDbcLocale()],((*itr)->IsPassive() ? passiveStr : ""),(talent ? talentStr : ""), + IS_PLAYER_GUID((*itr)->GetCasterGUID()) ? "player" : "creature",GUID_LOPART((*itr)->GetCasterGUID())); + } + } + return true; +} + +bool ChatHandler::HandleResetHonorCommand (const char * args) +{ + char* pName = strtok((char*)args, ""); + Player *player = NULL; + if (pName) + { + std::string name = pName; + if(!normalizePlayerName(name)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + uint64 guid = objmgr.GetPlayerGUIDByName(name.c_str()); + player = objmgr.GetPlayer(guid); + } + else + player = getSelectedPlayer(); + + if(!player) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + return true; + } + + player->SetUInt32Value(PLAYER_FIELD_KILLS, 0); + player->SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORBALE_KILLS, 0); + player->SetUInt32Value(PLAYER_FIELD_HONOR_CURRENCY, 0); + player->SetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, 0); + player->SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, 0); + + return true; +} + +static bool HandleResetStatsOrLevelHelper(Player* player) +{ + PlayerInfo const *info = objmgr.GetPlayerInfo(player->getRace(), player->getClass()); + if(!info) return false; + + ChrClassesEntry const* cEntry = sChrClassesStore.LookupEntry(player->getClass()); + if(!cEntry) + { + sLog.outError("Class %u not found in DBC (Wrong DBC files?)",player->getClass()); + return false; + } + + uint8 powertype = cEntry->powerType; + + uint32 unitfield; + if(powertype == POWER_RAGE) + unitfield = 0x1100EE00; + else if(powertype == POWER_ENERGY) + unitfield = 0x00000000; + else if(powertype == POWER_MANA) + unitfield = 0x0000EE00; + else + { + sLog.outError("Invalid default powertype %u for player (class %u)",powertype,player->getClass()); + return false; + } + + // reset m_form if no aura + if(!player->HasAuraType(SPELL_AURA_MOD_SHAPESHIFT)) + player->m_form = FORM_NONE; + + player->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, DEFAULT_WORLD_OBJECT_SIZE ); + player->SetFloatValue(UNIT_FIELD_COMBATREACH, 1.5f ); + + player->setFactionForRace(player->getRace()); + + player->SetUInt32Value(UNIT_FIELD_BYTES_0, ( ( player->getRace() ) | ( player->getClass() << 8 ) | ( player->getGender() << 16 ) | ( powertype << 24 ) ) ); + + // reset only if player not in some form; + if(player->m_form==FORM_NONE) + { + switch(player->getGender()) + { + case GENDER_FEMALE: + player->SetDisplayId(info->displayId_f); + player->SetNativeDisplayId(info->displayId_f); + break; + case GENDER_MALE: + player->SetDisplayId(info->displayId_m); + player->SetNativeDisplayId(info->displayId_m); + break; + default: + break; + } + } + + // set UNIT_FIELD_BYTES_1 to init state but preserve m_form value + player->SetUInt32Value(UNIT_FIELD_BYTES_1, unitfield); + player->SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_UNK3 | UNIT_BYTE2_FLAG_UNK5 ); + player->SetByteValue(UNIT_FIELD_BYTES_2, 3, player->m_form); + + player->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); + + //-1 is default value + player->SetUInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, uint32(-1)); + + //player->SetUInt32Value(PLAYER_FIELD_BYTES, 0xEEE00000 ); + return true; +} + +bool ChatHandler::HandleResetLevelCommand(const char * args) +{ + char* pName = strtok((char*)args, ""); + Player *player = NULL; + if (pName) + { + std::string name = pName; + if(!normalizePlayerName(name)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + uint64 guid = objmgr.GetPlayerGUIDByName(name.c_str()); + player = objmgr.GetPlayer(guid); + } + else + player = getSelectedPlayer(); + + if(!player) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + if(!HandleResetStatsOrLevelHelper(player)) + return false; + + player->SetLevel(1); + player->InitStatsForLevel(true); + player->InitTaxiNodesForLevel(); + player->InitTalentForLevel(); + player->SetUInt32Value(PLAYER_XP,0); + + // reset level to summoned pet + Pet* pet = player->GetPet(); + if(pet && pet->getPetType()==SUMMON_PET) + pet->InitStatsForLevel(1); + + return true; +} + +bool ChatHandler::HandleResetStatsCommand(const char * args) +{ + char* pName = strtok((char*)args, ""); + Player *player = NULL; + if (pName) + { + std::string name = pName; + if(!normalizePlayerName(name)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + uint64 guid = objmgr.GetPlayerGUIDByName(name.c_str()); + player = objmgr.GetPlayer(guid); + } + else + player = getSelectedPlayer(); + + if(!player) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + if(!HandleResetStatsOrLevelHelper(player)) + return false; + + player->InitStatsForLevel(true); + player->InitTaxiNodesForLevel(); + player->InitTalentForLevel(); + + return true; +} + +bool ChatHandler::HandleResetSpellsCommand(const char * args) +{ + char* pName = strtok((char*)args, ""); + Player *player = NULL; + uint64 playerGUID = 0; + if (pName) + { + std::string name = pName; + + if(!normalizePlayerName(name)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + player = objmgr.GetPlayer(name.c_str()); + if(!player) + playerGUID = objmgr.GetPlayerGUIDByName(name.c_str()); + } + else + player = getSelectedPlayer(); + + if(!player && !playerGUID) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + if(player) + { + player->resetSpells(); + + ChatHandler(player).SendSysMessage(LANG_RESET_SPELLS); + + if(m_session->GetPlayer()!=player) + PSendSysMessage(LANG_RESET_SPELLS_ONLINE,player->GetName()); + } + else + { + CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '%u' WHERE guid = '%u'",uint32(AT_LOGIN_RESET_SPELLS), GUID_LOPART(playerGUID)); + PSendSysMessage(LANG_RESET_SPELLS_OFFLINE,pName); + } + + return true; +} + +bool ChatHandler::HandleResetTalentsCommand(const char * args) +{ + char* pName = strtok((char*)args, ""); + Player *player = NULL; + uint64 playerGUID = 0; + if (pName) + { + std::string name = pName; + if(!normalizePlayerName(name)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + player = objmgr.GetPlayer(name.c_str()); + if(!player) + playerGUID = objmgr.GetPlayerGUIDByName(name.c_str()); + } + else + player = getSelectedPlayer(); + + if(!player && !playerGUID) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + if(player) + { + player->resetTalents(true); + + ChatHandler(player).SendSysMessage(LANG_RESET_TALENTS); + + if(m_session->GetPlayer()!=player) + PSendSysMessage(LANG_RESET_TALENTS_ONLINE,player->GetName()); + } + else + { + CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '%u' WHERE guid = '%u'",uint32(AT_LOGIN_RESET_TALENTS), GUID_LOPART(playerGUID) ); + PSendSysMessage(LANG_RESET_TALENTS_OFFLINE,pName); + } + + return true; +} + +bool ChatHandler::HandleResetAllCommand(const char * args) +{ + if(!*args) + return false; + + std::string casename = args; + + AtLoginFlags atLogin; + + // Command specially created as single command to prevent using short case names + if(casename=="spells") + { + atLogin = AT_LOGIN_RESET_SPELLS; + sWorld.SendWorldText(LANG_RESETALL_SPELLS); + } + else if(casename=="talents") + { + atLogin = AT_LOGIN_RESET_TALENTS; + sWorld.SendWorldText(LANG_RESETALL_TALENTS); + } + else + { + PSendSysMessage(LANG_RESETALL_UNKNOWN_CASE,args); + SetSentErrorMessage(true); + return false; + } + + CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '%u'",atLogin); + HashMapHolder::MapType const& plist = ObjectAccessor::Instance().GetPlayers(); + for(HashMapHolder::MapType::const_iterator itr = plist.begin(); itr != plist.end(); ++itr) + itr->second->SetAtLoginFlag(atLogin); + + return true; +} + +bool ChatHandler::HandleShutDownCommand(const char* args) +{ + if(!*args) + return false; + + if(std::string(args)=="cancel") + { + sWorld.ShutdownCancel(); + } + else + { + int32 time = atoi(args); + + ///- Prevent interpret wrong arg value as 0 secs shutdown time + if(time == 0 && (args[0]!='0' || args[1]!='\0') || time < 0) + return false; + + sWorld.ShutdownServ(time); + } + return true; +} + +bool ChatHandler::HandleRestartCommand(const char* args) +{ + if(!*args) + return false; + + if(std::string(args)=="cancel") + { + sWorld.ShutdownCancel(); + } + else + { + int32 time = atoi(args); + + ///- Prevent interpret wrong arg value as 0 secs shutdown time + if(time == 0 && (args[0]!='0' || args[1]!='\0') || time < 0) + return false; + + sWorld.ShutdownServ(time, SHUTDOWN_MASK_RESTART); + } + return true; +} + +bool ChatHandler::HandleIdleRestartCommand(const char* args) +{ + if(!*args) + return false; + + if(std::string(args)=="cancel") + { + sWorld.ShutdownCancel(); + } + else + { + int32 time = atoi(args); + + ///- Prevent interpret wrong arg value as 0 secs shutdown time + if(time == 0 && (args[0]!='0' || args[1]!='\0') || time < 0) + return false; + + sWorld.ShutdownServ(time,SHUTDOWN_MASK_RESTART+SHUTDOWN_MASK_IDLE); + } + return true; +} + +bool ChatHandler::HandleIdleShutDownCommand(const char* args) +{ + if(!*args) + return false; + + if(std::string(args)=="cancel") + { + sWorld.ShutdownCancel(); + } + else + { + int32 time = atoi(args); + + ///- Prevent interpret wrong arg value as 0 secs shutdown time + if(time == 0 && (args[0]!='0' || args[1]!='\0') || time < 0) + return false; + + sWorld.ShutdownServ(time,SHUTDOWN_MASK_IDLE); + } + return true; +} + +bool ChatHandler::HandleAddQuest(const char* args) +{ + Player* player = getSelectedPlayer(); + if(!player) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // .addquest #entry' + // number or [name] Shift-click form |color|Hquest:quest_id|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hquest"); + if(!cId) + return false; + + uint32 entry = atol(cId); + + Quest const* pQuest = objmgr.GetQuestTemplate(entry); + + if(!pQuest) + { + PSendSysMessage(LANG_COMMAND_QUEST_NOTFOUND,entry); + SetSentErrorMessage(true); + return false; + } + + // check item starting quest (it can work incorrectly if added without item in inventory) + QueryResult *result = WorldDatabase.PQuery("SELECT entry FROM item_template WHERE startquest = '%u' LIMIT 1",entry); + if(result) + { + Field* fields = result->Fetch(); + uint32 item_id = fields[0].GetUInt32(); + delete result; + + PSendSysMessage(LANG_COMMAND_QUEST_STARTFROMITEM, entry,item_id); + SetSentErrorMessage(true); + return false; + } + + // ok, normal (creature/GO starting) quest + if( player->CanAddQuest( pQuest, true ) ) + { + player->AddQuest( pQuest, NULL ); + + if ( player->CanCompleteQuest( entry ) ) + player->CompleteQuest( entry ); + } + + return true; +} + +bool ChatHandler::HandleRemoveQuest(const char* args) +{ + Player* player = getSelectedPlayer(); + if(!player) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // .removequest #entry' + // number or [name] Shift-click form |color|Hquest:quest_id|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hquest"); + if(!cId) + return false; + + uint32 entry = atol(cId); + + Quest const* pQuest = objmgr.GetQuestTemplate(entry); + + if(!pQuest) + { + PSendSysMessage(LANG_COMMAND_QUEST_NOTFOUND, entry); + SetSentErrorMessage(true); + return false; + } + + // remove all quest entries for 'entry' from quest log + for(uint8 slot = 0; slot < MAX_QUEST_LOG_SIZE; ++slot ) + { + uint32 quest = player->GetQuestSlotQuestId(slot); + if(quest==entry) + { + player->SetQuestSlot(slot,0); + + // we ignore unequippable quest items in this case, its' still be equipped + player->TakeQuestSourceItem( quest, false ); + } + } + + // set quest status to not started (will updated in DB at next save) + player->SetQuestStatus( entry, QUEST_STATUS_NONE); + + // reset rewarded for restart repeatable quest + player->getQuestStatusMap()[entry].m_rewarded = false; + + SendSysMessage(LANG_COMMAND_QUEST_REMOVED); + return true; +} + +bool ChatHandler::HandleCompleteQuest(const char* args) +{ + Player* player = getSelectedPlayer(); + if(!player) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // .quest complete #entry + // number or [name] Shift-click form |color|Hquest:quest_id|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hquest"); + if(!cId) + return false; + + uint32 entry = atol(cId); + + Quest const* pQuest = objmgr.GetQuestTemplate(entry); + + // If player doesn't have the quest + if(!pQuest || player->GetQuestStatus(entry) == QUEST_STATUS_NONE) + { + PSendSysMessage(LANG_COMMAND_QUEST_NOTFOUND, entry); + SetSentErrorMessage(true); + return false; + } + + // Add quest items for quests that require items + for(uint8 x = 0; x < QUEST_OBJECTIVES_COUNT; ++x) + { + uint32 id = pQuest->ReqItemId[x]; + uint32 count = pQuest->ReqItemCount[x]; + if(!id || !count) + continue; + + uint32 curItemCount = player->GetItemCount(id,true); + + ItemPosCountVec dest; + uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, id, count-curItemCount ); + if( msg == EQUIP_ERR_OK ) + { + Item* item = player->StoreNewItem( dest, id, true); + player->SendNewItem(item,count-curItemCount,true,false); + } + } + + // All creature/GO slain/casted (not required, but otherwise it will display "Creature slain 0/10") + for(uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; i++) + { + uint32 creature = pQuest->ReqCreatureOrGOId[i]; + uint32 creaturecount = pQuest->ReqCreatureOrGOCount[i]; + + if(uint32 spell_id = pQuest->ReqSpell[i]) + { + for(uint16 z = 0; z < creaturecount; ++z) + player->CastedCreatureOrGO(creature,0,spell_id); + } + else if(creature > 0) + { + for(uint16 z = 0; z < creaturecount; ++z) + player->KilledMonster(creature,0); + } + else if(creature < 0) + { + for(uint16 z = 0; z < creaturecount; ++z) + player->CastedCreatureOrGO(creature,0,0); + } + } + + // If the quest requires reputation to complete + if(uint32 repFaction = pQuest->GetRepObjectiveFaction()) + { + uint32 repValue = pQuest->GetRepObjectiveValue(); + uint32 curRep = player->GetReputation(repFaction); + if(curRep < repValue) + { + FactionEntry const *factionEntry = sFactionStore.LookupEntry(repFaction); + player->SetFactionReputation(factionEntry,repValue); + } + } + + // If the quest requires money + int32 ReqOrRewMoney = pQuest->GetRewOrReqMoney(); + if(ReqOrRewMoney < 0) + player->ModifyMoney(-ReqOrRewMoney); + + player->CompleteQuest(entry); + return true; +} + +bool ChatHandler::HandleBanCommand(const char* args) +{ + if(!args) + return false; + + char* type = strtok((char*)args, " "); + + if(!type) + return false; + char* nameOrIP = strtok(NULL, " "); + + if(!nameOrIP) + return false; + + char* duration = strtok(NULL," "); + if(!duration || !atoi(duration)) + return false; + + char* reason = strtok(NULL,""); + if(!reason) + return false; + + switch(sWorld.BanAccount(type, nameOrIP, duration, reason,m_session->GetPlayerName())) + { + case BAN_SUCCESS: + if(atoi(duration)>0) + PSendSysMessage(LANG_BAN_YOUBANNED,nameOrIP,secsToTimeString(TimeStringToSecs(duration),true).c_str(),reason); + else + PSendSysMessage(LANG_BAN_YOUPERMBANNED,nameOrIP,reason); + break; + case BAN_SYNTAX_ERROR: + return false; + case BAN_NOTFOUND: + PSendSysMessage(LANG_BAN_NOTFOUND,type,nameOrIP); + break; + } + + return true; +} + +bool ChatHandler::HandleUnBanCommand(const char* args) +{ + if(!args) + return false; + char* type = strtok((char*)args, " "); + if(!type) + return false; + char* nameOrIP = strtok(NULL, " "); + + if(!nameOrIP) + return false; + + if(sWorld.RemoveBanAccount(type,nameOrIP)) + PSendSysMessage(LANG_UNBAN_UNBANNED,nameOrIP); + else + PSendSysMessage(LANG_UNBAN_ERROR,nameOrIP); + + return true; +} + +bool ChatHandler::HandleBanInfoCommand(const char* args) +{ + if(!args) + return false; + + char* cType = strtok((char*)args, " "); + char* cnameOrIP = strtok(NULL, ""); + if(!cType || !cnameOrIP) + return false; + + std::string nameOrIP = cnameOrIP; + std::string type = cType; + if (!IsIPAddress(cnameOrIP) && type=="ip") + return false; + + Field *fields; + if(type != "ip") + { + //look the accountid up + uint32 accountid; + std::string accountname; + if(type == "account") + { + loginDatabase.escape_string(nameOrIP); + QueryResult *result = loginDatabase.PQuery("SELECT id, username FROM account WHERE username = '%s'",nameOrIP.c_str()); + if (!result) + { + PSendSysMessage(LANG_BANINFO_NOACCOUNT); + return true; + } + fields = result->Fetch(); + accountid = fields[0].GetUInt32(); + accountname = fields[1].GetCppString(); + delete result; + } + else if(type == "character") + { + if(!normalizePlayerName(nameOrIP)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + loginDatabase.escape_string(nameOrIP); + QueryResult *result = CharacterDatabase.PQuery("SELECT account FROM characters WHERE name = '%s'", nameOrIP.c_str()); + if (!result) + { + PSendSysMessage(LANG_BANINFO_NOCHARACTER); + return true; + } + fields = result->Fetch(); + accountid = fields[0].GetUInt32(); + delete result; + result = loginDatabase.PQuery("SELECT username FROM account WHERE id = '%u'", accountid); + if (!result) + { + PSendSysMessage(LANG_BANINFO_NOCHARACTER); + return true; + } + fields = result->Fetch(); + accountname = fields[0].GetCppString(); + delete result; + } + else + return false; + + QueryResult *result = loginDatabase.PQuery("SELECT FROM_UNIXTIME(bandate), unbandate-bandate, active, unbandate,banreason,bannedby FROM account_banned WHERE id = '%u' ORDER BY bandate ASC",accountid); + if(!result) + { + PSendSysMessage(LANG_BANINFO_NOACCOUNTBAN, accountname.c_str()); + return true; + } + + PSendSysMessage(LANG_BANINFO_BANHISTORY,accountname.c_str()); + do + { + fields = result->Fetch(); + + time_t unbandate = time_t(fields[3].GetUInt64()); + bool active = false; + if(fields[2].GetBool() && (fields[1].GetUInt64() == (uint64)0 ||unbandate >= time(NULL)) ) + active = true; + bool permanent = (fields[1].GetUInt64() == (uint64)0); + std::string bantime = permanent?GetMangosString(LANG_BANINFO_INFINITE):secsToTimeString(fields[1].GetUInt64(), true); + PSendSysMessage(LANG_BANINFO_HISTORYENTRY, + fields[0].GetString(), bantime.c_str(), active ? GetMangosString(LANG_BANINFO_YES):GetMangosString(LANG_BANINFO_NO), fields[4].GetString(), fields[5].GetString()); + }while (result->NextRow()); + + delete result; + } + else + { + loginDatabase.escape_string(nameOrIP); + QueryResult *result = loginDatabase.PQuery("SELECT ip, FROM_UNIXTIME(bandate), FROM_UNIXTIME(unbandate), unbandate-UNIX_TIMESTAMP(), banreason,bannedby,unbandate-bandate FROM ip_banned WHERE ip = '%s'",nameOrIP.c_str()); + if(!result) + { + PSendSysMessage(LANG_BANINFO_NOIP); + return true; + } + fields = result->Fetch(); + bool permanent = (fields[6].GetUInt64()==(uint64)0); + PSendSysMessage(LANG_BANINFO_IPENTRY, + fields[0].GetString(), fields[1].GetString(), permanent ? GetMangosString(LANG_BANINFO_NEVER):fields[2].GetString(), + permanent ? GetMangosString(LANG_BANINFO_INFINITE):secsToTimeString(fields[3].GetUInt64(), true).c_str(), fields[4].GetString(), fields[5].GetString()); + delete result; + } + return true; +} + +bool ChatHandler::HandleBanListCommand(const char* args) +{ + loginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); + if(!*args) + return false; + char* cType = strtok((char*)args, " "); + char* cFilter = strtok(NULL, ""); + if(!cType || !cFilter) + return false; + std::string Filter = cFilter; + std::string Type = cType; + loginDatabase.escape_string(Filter); + + QueryResult* result = NULL; + Field *fields = NULL; + if(Type == "ip") + { + result = loginDatabase.PQuery("SELECT ip FROM ip_banned WHERE ip "_LIKE_" '""%%%s%%""'",Filter.c_str()); + if(!result) + { + PSendSysMessage(LANG_BANLIST_NOIP); + return true; + } + PSendSysMessage(LANG_BANLIST_MATCHINGIP); + do + { + fields = result->Fetch(); + PSendSysMessage("%s",fields[0].GetString()); + } while (result->NextRow()); + + delete result; + return true; + } + //lookup accountid + if(Type == "account") + { + result = loginDatabase.PQuery("SELECT id FROM account WHERE username "_LIKE_" '""%%%s%%""' ",Filter.c_str()); + if (!result) + { + PSendSysMessage(LANG_BANLIST_NOACCOUNT); + return true; + } + //do not delete result + } + else if(Type == "characters") + { + result = CharacterDatabase.PQuery("SELECT account FROM characters, WHERE name "_LIKE_" '""%%%s%%""' ",Filter.c_str()); + if (!result) + { + PSendSysMessage(LANG_BANLIST_NOCHARACTER); + return true; + } + } + else + return false; + + PSendSysMessage(LANG_BANLIST_MATCHINGACCOUNT); + do + { + fields = result->Fetch(); + uint32 accountid = fields[0].GetUInt32(); + QueryResult* banresult = loginDatabase.PQuery("SELECT account.username FROM account,account_banned WHERE account_banned.id='%u' AND account_banned.active = '1' AND account_banned.id=account.id",accountid); + if(banresult) + { + Field* fields2 = banresult->Fetch(); + PSendSysMessage("%s",fields2[0].GetString()); + delete banresult; + } + } while (result->NextRow()); + + delete result; + return true; +} + +bool ChatHandler::HandleRespawnCommand(const char* /*args*/) +{ + Player* pl = m_session->GetPlayer(); + + CellPair p(MaNGOS::ComputeCellPair(pl->GetPositionX(), pl->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + MaNGOS::RespawnDo u_do; + MaNGOS::WorldObjectWorker worker(u_do); + + TypeContainerVisitor, GridTypeMapContainer > obj_worker(worker); + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, obj_worker, *MapManager::Instance().GetMap(pl->GetMapId(), pl)); + + return true; +} + +bool ChatHandler::HandleFlyModeCommand(const char* args) +{ + if(!args) + return false; + + Unit *unit = getSelectedUnit(); + if (!unit || (unit->GetTypeId() != TYPEID_PLAYER)) + unit = m_session->GetPlayer(); + + WorldPacket data(12); + if (strncmp(args, "on", 3) == 0) + data.SetOpcode(SMSG_MOVE_SET_CAN_FLY); + else if (strncmp(args, "off", 4) == 0) + data.SetOpcode(SMSG_MOVE_UNSET_CAN_FLY); + else + { + SendSysMessage(LANG_USE_BOL); + return false; + } + data.append(unit->GetPackGUID()); + data << uint32(0); // unknown + unit->SendMessageToSet(&data, true); + PSendSysMessage(LANG_COMMAND_FLYMODE_STATUS, unit->GetName(), args); + return true; +} + +bool ChatHandler::HandleLoadPDumpCommand(const char *args) +{ + if(!args) + return false; + + char * file = strtok((char*)args, " "); if(!file) return false; + char * acc = strtok(NULL, " "); if(!acc) return false; + if(!file || !acc) + return false; + + uint32 account_id = objmgr.GetAccountByAccountName(acc); + if(!account_id) + { + account_id = atoi(acc); + if(account_id) + { + std::string acc_name; + if(!objmgr.GetAccountNameByAccount(account_id,acc_name)) + return false; + } + else + return false; + } + + char * name = strtok(NULL, " "); + char * guid_str = name ? strtok(NULL, " ") : NULL; + + uint32 guid = guid_str ? atoi(guid_str) : 0; + + if(PlayerDumpReader().LoadDump(file, account_id, name ? name : "", guid)) + PSendSysMessage(LANG_COMMAND_IMPORT_SUCCESS); + else + PSendSysMessage(LANG_COMMAND_IMPORT_FAILED); + + return true; +} + +bool ChatHandler::HandleChangeEntryCommand(const char *args) +{ + if(!args) + return false; + + uint32 newEntryNum = atoi(args); + if(!newEntryNum) + return false; + + Unit* unit = getSelectedUnit(); + if(!unit || unit->GetTypeId() != TYPEID_UNIT) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + Creature* creature = (Creature*)unit; + if(creature->UpdateEntry(newEntryNum)) + SendSysMessage(LANG_DONE); + else + SendSysMessage(LANG_ERROR); + return true; +} + +bool ChatHandler::HandleWritePDumpCommand(const char *args) +{ + if(!args) + return false; + + char* file = strtok((char*)args, " "); + char* p2 = strtok(NULL, " "); + + if(!file || !p2) + return false; + + uint32 guid = objmgr.GetPlayerGUIDByName(p2); + if(!guid) + guid = atoi(p2); + + if (PlayerDumpWriter().WriteDump(file, guid)) + PSendSysMessage(LANG_COMMAND_EXPORT_SUCCESS); + else + PSendSysMessage(LANG_COMMAND_EXPORT_FAILED); + + return true; +} + +bool ChatHandler::HandleMovegensCommand(const char* /*args*/) +{ + Unit* unit = getSelectedUnit(); + if(!unit) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_MOVEGENS_LIST,(unit->GetTypeId()==TYPEID_PLAYER ? "Player" : "Creature" ),unit->GetGUIDLow()); + + MotionMaster* mm = unit->GetMotionMaster(); + for(MotionMaster::const_iterator itr = mm->begin(); itr != mm->end(); ++itr) + { + switch((*itr)->GetMovementGeneratorType()) + { + case IDLE_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_IDLE); break; + case RANDOM_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_RANDOM); break; + case WAYPOINT_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_WAYPOINT); break; + case ANIMAL_RANDOM_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_ANIMAL_RANDOM); break; + case CONFUSED_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_CONFUSED); break; + case TARGETED_MOTION_TYPE: + { + if(unit->GetTypeId()==TYPEID_PLAYER) + { + TargetedMovementGenerator const* mgen = static_cast const*>(*itr); + Unit* target = mgen->GetTarget(); + if(target) + PSendSysMessage(LANG_MOVEGENS_TARGETED_PLAYER,target->GetName(),target->GetGUIDLow()); + else + SendSysMessage(LANG_MOVEGENS_TARGETED_NULL); + } + else + { + TargetedMovementGenerator const* mgen = static_cast const*>(*itr); + Unit* target = mgen->GetTarget(); + if(target) + PSendSysMessage(LANG_MOVEGENS_TARGETED_CREATURE,target->GetName(),target->GetGUIDLow()); + else + SendSysMessage(LANG_MOVEGENS_TARGETED_NULL); + } + break; + } + case HOME_MOTION_TYPE: + if(unit->GetTypeId()==TYPEID_UNIT) + { + float x,y,z; + (*itr)->GetDestination(x,y,z); + PSendSysMessage(LANG_MOVEGENS_HOME_CREATURE,x,y,z); + } + else + SendSysMessage(LANG_MOVEGENS_HOME_PLAYER); + break; + case FLIGHT_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_FLIGHT); break; + case POINT_MOTION_TYPE: + { + float x,y,z; + (*itr)->GetDestination(x,y,z); + PSendSysMessage(LANG_MOVEGENS_POINT,x,y,z); + break; + } + case FLEEING_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_FEAR); break; + case DISTRACT_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_DISTRACT); break; + default: + PSendSysMessage(LANG_MOVEGENS_UNKNOWN,(*itr)->GetMovementGeneratorType()); + break; + } + } + return true; +} + +bool ChatHandler::HandlePLimitCommand(const char *args) +{ + if(*args) + { + char* param = strtok((char*)args, " "); + if(!param) + return false; + + int l = strlen(param); + + if( strncmp(param,"player",l) == 0 ) + sWorld.SetPlayerLimit(-SEC_PLAYER); + else if(strncmp(param,"moderator",l) == 0 ) + sWorld.SetPlayerLimit(-SEC_MODERATOR); + else if(strncmp(param,"gamemaster",l) == 0 ) + sWorld.SetPlayerLimit(-SEC_GAMEMASTER); + else if(strncmp(param,"administrator",l) == 0 ) + sWorld.SetPlayerLimit(-SEC_ADMINISTRATOR); + else if(strncmp(param,"reset",l) == 0 ) + sWorld.SetPlayerLimit( sConfig.GetIntDefault("PlayerLimit", DEFAULT_PLAYER_LIMIT) ); + else + { + int val = atoi(param); + if(val < -SEC_ADMINISTRATOR) val = -SEC_ADMINISTRATOR; + + sWorld.SetPlayerLimit(val); + } + + // kick all low security level players + if(sWorld.GetPlayerAmountLimit() > SEC_PLAYER) + sWorld.KickAllLess(sWorld.GetPlayerSecurityLimit()); + } + + uint32 pLimit = sWorld.GetPlayerAmountLimit(); + AccountTypes allowedAccountType = sWorld.GetPlayerSecurityLimit(); + char const* secName = ""; + switch(allowedAccountType) + { + case SEC_PLAYER: secName = "Player"; break; + case SEC_MODERATOR: secName = "Moderator"; break; + case SEC_GAMEMASTER: secName = "Gamemaster"; break; + case SEC_ADMINISTRATOR: secName = "Administrator"; break; + default: secName = ""; break; + } + + PSendSysMessage("Player limits: amount %u, min. security level %s.",pLimit,secName); + + return true; +} + +bool ChatHandler::HandleCastCommand(const char* args) +{ + if(!*args) + return false; + + Unit* target = getSelectedUnit(); + + if(!target) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spell = extractSpellIdFromLink((char*)args); + if(!spell) + return false; + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell); + if(!spellInfo) + return false; + + if(!SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer())) + { + PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spell); + SetSentErrorMessage(true); + return false; + } + + char* trig_str = strtok(NULL, " "); + if(trig_str) + { + int l = strlen(trig_str); + if(strncmp(trig_str,"triggered",l) != 0 ) + return false; + } + + bool triggered = (trig_str != NULL); + + m_session->GetPlayer()->CastSpell(target,spell,triggered); + + return true; +} + +bool ChatHandler::HandleCastBackCommand(const char* args) +{ + Creature* caster = getSelectedCreature(); + + if(!caster) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spell = extractSpellIdFromLink((char*)args); + if(!spell || !sSpellStore.LookupEntry(spell)) + return false; + + char* trig_str = strtok(NULL, " "); + if(trig_str) + { + int l = strlen(trig_str); + if(strncmp(trig_str,"triggered",l) != 0 ) + return false; + } + + bool triggered = (trig_str != NULL); + + // update orientation at server + caster->SetOrientation(caster->GetAngle(m_session->GetPlayer())); + + // and client + WorldPacket data; + caster->BuildHeartBeatMsg(&data); + caster->SendMessageToSet(&data,true); + + caster->CastSpell(m_session->GetPlayer(),spell,false); + + return true; +} + +bool ChatHandler::HandleCastDistCommand(const char* args) +{ + if(!*args) + return false; + + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spell = extractSpellIdFromLink((char*)args); + if(!spell) + return false; + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell); + if(!spellInfo) + return false; + + if(!SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer())) + { + PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spell); + SetSentErrorMessage(true); + return false; + } + + char *distStr = strtok(NULL, " "); + + float dist = 0; + + if(distStr) + sscanf(distStr, "%f", &dist); + + char* trig_str = strtok(NULL, " "); + if(trig_str) + { + int l = strlen(trig_str); + if(strncmp(trig_str,"triggered",l) != 0 ) + return false; + } + + bool triggered = (trig_str != NULL); + + float x,y,z; + m_session->GetPlayer()->GetClosePoint(x,y,z,dist); + + m_session->GetPlayer()->CastSpell(x,y,z,spell,triggered); + return true; +} + +bool ChatHandler::HandleCastTargetCommand(const char* args) +{ + Creature* caster = getSelectedCreature(); + + if(!caster) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if(!caster->getVictim()) + { + SendSysMessage(LANG_SELECTED_TARGET_NOT_HAVE_VICTIM); + SetSentErrorMessage(true); + return false; + } + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spell = extractSpellIdFromLink((char*)args); + if(!spell || !sSpellStore.LookupEntry(spell)) + return false; + + char* trig_str = strtok(NULL, " "); + if(trig_str) + { + int l = strlen(trig_str); + if(strncmp(trig_str,"triggered",l) != 0 ) + return false; + } + + bool triggered = (trig_str != NULL); + + // update orientation at server + caster->SetOrientation(caster->GetAngle(m_session->GetPlayer())); + + // and client + WorldPacket data; + caster->BuildHeartBeatMsg(&data); + caster->SendMessageToSet(&data,true); + + caster->CastSpell(caster->getVictim(),spell,false); + + return true; +} + +/* +ComeToMe command REQUIRED for 3rd party scripting library to have access to PointMovementGenerator +Without this function 3rd party scripting library will get linking errors (unresolved external) +when attempting to use the PointMovementGenerator +*/ +bool ChatHandler::HandleComeToMeCommand(const char *args) +{ + Creature* caster = getSelectedCreature(); + + if(!caster) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + char* newFlagStr = strtok((char*)args, " "); + + if(!newFlagStr) + return false; + + uint32 newFlags = atoi(newFlagStr); + + caster->SetUnitMovementFlags(newFlags); + + Player* pl = m_session->GetPlayer(); + + caster->GetMotionMaster()->MovePoint(0, pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ()); + return true; +} + +bool ChatHandler::HandleCastSelfCommand(const char* args) +{ + if(!*args) + return false; + + Unit* target = getSelectedUnit(); + + if(!target) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spell = extractSpellIdFromLink((char*)args); + if(!spell) + return false; + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell); + if(!spellInfo) + return false; + + if(!SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer())) + { + PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spell); + SetSentErrorMessage(true); + return false; + } + + target->CastSpell(target,spell,false); + + return true; +} + +std::string GetTimeString(uint32 time) +{ + uint16 days = time / DAY, hours = (time % DAY) / HOUR, minute = (time % HOUR) / MINUTE; + std::ostringstream ss; + if(days) ss << days << "d "; + if(hours) ss << hours << "h "; + ss << minute << "m"; + return ss.str(); +} + +bool ChatHandler::HandleInstanceListBindsCommand(const char* /*args*/) +{ + Player* player = getSelectedPlayer(); + if (!player) player = m_session->GetPlayer(); + uint32 counter = 0; + for(uint8 i = 0; i < TOTAL_DIFFICULTIES; i++) + { + Player::BoundInstancesMap &binds = player->GetBoundInstances(i); + for(Player::BoundInstancesMap::iterator itr = binds.begin(); itr != binds.end(); ++itr) + { + InstanceSave *save = itr->second.save; + std::string timeleft = GetTimeString(save->GetResetTime() - time(NULL)); + PSendSysMessage("map: %d inst: %d perm: %s diff: %s canReset: %s TTR: %s", itr->first, save->GetInstanceId(), itr->second.perm ? "yes" : "no", save->GetDifficulty() == DIFFICULTY_NORMAL ? "normal" : "heroic", save->CanReset() ? "yes" : "no", timeleft.c_str()); + counter++; + } + } + PSendSysMessage("player binds: %d", counter); + counter = 0; + Group *group = player->GetGroup(); + if(group) + { + for(uint8 i = 0; i < TOTAL_DIFFICULTIES; i++) + { + Group::BoundInstancesMap &binds = group->GetBoundInstances(i); + for(Group::BoundInstancesMap::iterator itr = binds.begin(); itr != binds.end(); ++itr) + { + InstanceSave *save = itr->second.save; + std::string timeleft = GetTimeString(save->GetResetTime() - time(NULL)); + PSendSysMessage("map: %d inst: %d perm: %s diff: %s canReset: %s TTR: %s", itr->first, save->GetInstanceId(), itr->second.perm ? "yes" : "no", save->GetDifficulty() == DIFFICULTY_NORMAL ? "normal" : "heroic", save->CanReset() ? "yes" : "no", timeleft.c_str()); + counter++; + } + } + } + PSendSysMessage("group binds: %d", counter); + + return true; +} + +bool ChatHandler::HandleInstanceUnbindCommand(const char* args) +{ + if(!*args) + return false; + + std::string cmd = args; + if(cmd == "all") + { + Player* player = getSelectedPlayer(); + if (!player) player = m_session->GetPlayer(); + uint32 counter = 0; + for(uint8 i = 0; i < TOTAL_DIFFICULTIES; i++) + { + Player::BoundInstancesMap &binds = player->GetBoundInstances(i); + for(Player::BoundInstancesMap::iterator itr = binds.begin(); itr != binds.end();) + { + if(itr->first != player->GetMapId()) + { + InstanceSave *save = itr->second.save; + std::string timeleft = GetTimeString(save->GetResetTime() - time(NULL)); + PSendSysMessage("unbinding map: %d inst: %d perm: %s diff: %s canReset: %s TTR: %s", itr->first, save->GetInstanceId(), itr->second.perm ? "yes" : "no", save->GetDifficulty() == DIFFICULTY_NORMAL ? "normal" : "heroic", save->CanReset() ? "yes" : "no", timeleft.c_str()); + player->UnbindInstance(itr, i); + counter++; + } + else + ++itr; + } + } + PSendSysMessage("instances unbound: %d", counter); + } + return true; +} + +bool ChatHandler::HandleInstanceStatsCommand(const char* /*args*/) +{ + PSendSysMessage("instances loaded: %d", MapManager::Instance().GetNumInstances()); + PSendSysMessage("players in instances: %d", MapManager::Instance().GetNumPlayersInInstances()); + PSendSysMessage("instance saves: %d", sInstanceSaveManager.GetNumInstanceSaves()); + PSendSysMessage("players bound: %d", sInstanceSaveManager.GetNumBoundPlayersTotal()); + PSendSysMessage("groups bound: %d", sInstanceSaveManager.GetNumBoundGroupsTotal()); + return true; +} + +bool ChatHandler::HandleInstanceSaveDataCommand(const char * /*args*/) +{ + Player* pl = m_session->GetPlayer(); + + Map* map = pl->GetMap(); + if (!map->IsDungeon()) + { + PSendSysMessage("Map is not a dungeon."); + SetSentErrorMessage(true); + return false; + } + + if (!((InstanceMap*)map)->GetInstanceData()) + { + PSendSysMessage("Map has no instance data."); + SetSentErrorMessage(true); + return false; + } + + ((InstanceMap*)map)->GetInstanceData()->SaveToDB(); + return true; +} diff --git a/src/game/LootHandler.cpp b/src/game/LootHandler.cpp new file mode 100644 index 00000000000..05c0ac8a997 --- /dev/null +++ b/src/game/LootHandler.cpp @@ -0,0 +1,494 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "WorldPacket.h" +#include "Log.h" +#include "Corpse.h" +#include "GameObject.h" +#include "Player.h" +#include "ObjectAccessor.h" +#include "WorldSession.h" +#include "LootMgr.h" +#include "Object.h" +#include "Group.h" +#include "World.h" +#include "Util.h" + +void WorldSession::HandleAutostoreLootItemOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,1); + + sLog.outDebug("WORLD: CMSG_AUTOSTORE_LOOT_ITEM"); + Player *player = GetPlayer(); + uint64 lguid = player->GetLootGUID(); + Loot *loot; + uint8 lootSlot; + + recv_data >> lootSlot; + + if (IS_GAMEOBJECT_GUID(lguid)) + { + GameObject *go = + ObjectAccessor::GetGameObject(*player, lguid); + + // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO + if (!go || (go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player,INTERACTION_DISTANCE)) + { + player->SendLootRelease(lguid); + return; + } + + loot = &go->loot; + } + else if (IS_ITEM_GUID(lguid)) + { + Item *pItem = player->GetItemByGuid( lguid ); + + if (!pItem) + { + player->SendLootRelease(lguid); + return; + } + + loot = &pItem->loot; + } + else + { + Creature* pCreature = + ObjectAccessor::GetCreature(*player, lguid); + + bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass()==CLASS_ROGUE && pCreature->lootForPickPocketed); + + if( !ok_loot || !pCreature->IsWithinDistInMap(_player,INTERACTION_DISTANCE) ) + { + player->SendLootRelease(lguid); + return; + } + + loot = &pCreature->loot; + } + + QuestItem *qitem = NULL; + QuestItem *ffaitem = NULL; + QuestItem *conditem = NULL; + + LootItem *item = loot->LootItemInSlot(lootSlot,player,&qitem,&ffaitem,&conditem); + + if(!item) + { + player->SendEquipError( EQUIP_ERR_ALREADY_LOOTED, NULL, NULL ); + return; + } + + // questitems use the blocked field for other purposes + if (!qitem && item->is_blocked) + { + player->SendLootRelease(lguid); + return; + } + + ItemPosCountVec dest; + uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, item->itemid, item->count ); + if ( msg == EQUIP_ERR_OK ) + { + Item * newitem = player->StoreNewItem( dest, item->itemid, true, item->randomPropertyId); + + if (qitem) + { + qitem->is_looted = true; + //freeforall is 1 if everyone's supposed to get the quest item. + if (item->freeforall || loot->GetPlayerQuestItems().size() == 1) + player->SendNotifyLootItemRemoved(lootSlot); + else + loot->NotifyQuestItemRemoved(qitem->index); + } + else + { + if (ffaitem) + { + //freeforall case, notify only one player of the removal + ffaitem->is_looted=true; + player->SendNotifyLootItemRemoved(lootSlot); + } + else + { + //not freeforall, notify everyone + if(conditem) + conditem->is_looted=true; + loot->NotifyItemRemoved(lootSlot); + } + } + + //if only one person is supposed to loot the item, then set it to looted + if (!item->freeforall) + item->is_looted = true; + + --loot->unlootedCount; + + player->SendNewItem(newitem, uint32(item->count), false, false, true); + } + else + player->SendEquipError( msg, NULL, NULL ); +} + +void WorldSession::HandleLootMoneyOpcode( WorldPacket & /*recv_data*/ ) +{ + sLog.outDebug("WORLD: CMSG_LOOT_MONEY"); + + Player *player = GetPlayer(); + uint64 guid = player->GetLootGUID(); + if(!guid) + return; + + Loot *pLoot = NULL; + + switch(GUID_HIPART(guid)) + { + case HIGHGUID_GAMEOBJECT: + { + GameObject *pGameObject = ObjectAccessor::GetGameObject(*GetPlayer(), guid); + + // not check distance for GO in case owned GO (fishing bobber case, for example) + if( pGameObject && (pGameObject->GetOwnerGUID()==_player->GetGUID() || pGameObject->IsWithinDistInMap(_player,INTERACTION_DISTANCE)) ) + pLoot = &pGameObject->loot; + + break; + } + case HIGHGUID_CORPSE: // remove insignia ONLY in BG + { + Corpse *bones = ObjectAccessor::GetCorpse(*GetPlayer(), guid); + + if (bones && bones->IsWithinDistInMap(_player,INTERACTION_DISTANCE) ) + pLoot = &bones->loot; + + break; + } + case HIGHGUID_ITEM: + { + if(Item *item = GetPlayer()->GetItemByGuid(guid)) + pLoot = &item->loot; + break; + } + case HIGHGUID_UNIT: + { + Creature* pCreature = ObjectAccessor::GetCreature(*GetPlayer(), guid); + + bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass()==CLASS_ROGUE && pCreature->lootForPickPocketed); + + if ( ok_loot && pCreature->IsWithinDistInMap(_player,INTERACTION_DISTANCE) ) + pLoot = &pCreature->loot ; + + break; + } + default: + return; // unlootable type + } + + if( pLoot ) + { + if (!IS_ITEM_GUID(guid) && player->GetGroup()) //item can be looted only single player + { + Group *group = player->GetGroup(); + + std::vector playersNear; + for(GroupReference *itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player* playerGroup = itr->getSource(); + if(!playerGroup) + continue; + if (player->GetDistance2d(playerGroup) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE)) + playersNear.push_back(playerGroup); + } + + uint32 money_per_player = uint32((pLoot->gold)/(playersNear.size())); + + for (std::vector::iterator i = playersNear.begin(); i != playersNear.end(); ++i) + { + (*i)->ModifyMoney( money_per_player ); + //Offset surely incorrect, but works + WorldPacket data( SMSG_LOOT_MONEY_NOTIFY, 4 ); + data << uint32(money_per_player); + (*i)->GetSession()->SendPacket( &data ); + } + } + else + player->ModifyMoney( pLoot->gold ); + pLoot->gold = 0; + pLoot->NotifyMoneyRemoved(); + } +} + +void WorldSession::HandleLootOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8); + + sLog.outDebug("WORLD: CMSG_LOOT"); + + uint64 guid; + recv_data >> guid; + + GetPlayer()->SendLoot(guid, LOOT_CORPSE); +} + +void WorldSession::HandleLootReleaseOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8); + + sLog.outDebug("WORLD: CMSG_LOOT_RELEASE"); + + // cheaters can modify lguid to prevent correct apply loot release code and re-loot + // use internal stored guid + //uint64 lguid; + //recv_data >> lguid; + + if(uint64 lguid = GetPlayer()->GetLootGUID()) + DoLootRelease(lguid); +} + +void WorldSession::DoLootRelease( uint64 lguid ) +{ + Player *player = GetPlayer(); + Loot *loot; + + player->SetLootGUID(0); + player->SendLootRelease(lguid); + + player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_LOOTING); + + if (IS_GAMEOBJECT_GUID(lguid)) + { + GameObject *go = + ObjectAccessor::GetGameObject(*player, lguid); + + // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO + if (!go || (go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player,INTERACTION_DISTANCE)) + return; + + loot = &go->loot; + + if (go->GetGoType() == GAMEOBJECT_TYPE_DOOR) + { + // locked doors are opened with spelleffect openlock, prevent remove its as looted + go->UseDoorOrButton(); + } + else if (loot->isLooted() || go->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE) + { + // GO is mineral vein? so it is not removed after its looted + if(go->GetGoType() == GAMEOBJECT_TYPE_CHEST) + { + uint32 go_min = go->GetGOInfo()->chest.minSuccessOpens; + uint32 go_max = go->GetGOInfo()->chest.maxSuccessOpens; + + // only vein pass this check + if(go_min != 0 && go_max > go_min) + { + float amount_rate = sWorld.getRate(RATE_MINING_AMOUNT); + float min_amount = go_min*amount_rate; + float max_amount = go_max*amount_rate; + + go->AddUse(); + float uses = float(go->GetUseCount()); + + if(uses < max_amount) + { + if(uses >= min_amount) + { + float chance_rate = sWorld.getRate(RATE_MINING_NEXT); + + int32 ReqValue = 175; + LockEntry const *lockInfo = sLockStore.LookupEntry(go->GetGOInfo()->chest.lockId); + if(lockInfo) + ReqValue = lockInfo->requiredminingskill; + float skill = float(player->GetSkillValue(SKILL_MINING))/(ReqValue+25); + double chance = pow(0.8*chance_rate,4*(1/double(max_amount))*double(uses)); + if(roll_chance_f(100*chance+skill)) + { + go->SetLootState(GO_READY); + } + else // not have more uses + go->SetLootState(GO_JUST_DEACTIVATED); + } + else // 100% chance until min uses + go->SetLootState(GO_READY); + } + else // max uses already + go->SetLootState(GO_JUST_DEACTIVATED); + } + else // not vein + go->SetLootState(GO_JUST_DEACTIVATED); + } + else if (go->GetGoType() == GAMEOBJECT_TYPE_FISHINGHOLE) + { // The fishing hole used once more + go->AddUse(); // if the max usage is reached, will be despawned in next tick + if (go->GetUseCount()>=irand(go->GetGOInfo()->fishinghole.minSuccessOpens,go->GetGOInfo()->fishinghole.maxSuccessOpens)) + { + go->SetLootState(GO_JUST_DEACTIVATED); + } + else + go->SetLootState(GO_READY); + } + else // not chest (or vein/herb/etc) + go->SetLootState(GO_JUST_DEACTIVATED); + + loot->clear(); + } + else + // not fully looted object + go->SetLootState(GO_ACTIVATED); + } + else if (IS_CORPSE_GUID(lguid)) // ONLY remove insignia at BG + { + Corpse *corpse = ObjectAccessor::GetCorpse(*player, lguid); + if (!corpse || !corpse->IsWithinDistInMap(_player,INTERACTION_DISTANCE) ) + return; + + loot = &corpse->loot; + + if (loot->isLooted()) + { + loot->clear(); + corpse->RemoveFlag(CORPSE_FIELD_DYNAMIC_FLAGS, CORPSE_DYNFLAG_LOOTABLE); + } + } + else if (IS_ITEM_GUID(lguid)) + { + Item *pItem = player->GetItemByGuid(lguid ); + if(!pItem) + return; + if( (pItem->GetProto()->BagFamily & BAG_FAMILY_MASK_MINING_SUPP) && + pItem->GetProto()->Class == ITEM_CLASS_TRADE_GOODS && + pItem->GetCount() >= 5) + { + pItem->m_lootGenerated = false; + pItem->loot.clear(); + + uint32 count = 5; + player->DestroyItemCount(pItem, count, true); + } + else + // FIXME: item don't must be deleted in case not fully looted state. But this pre-request implement loot saving in DB at item save. Or checting possible. + player->DestroyItem( pItem->GetBagSlot(),pItem->GetSlot(), true); + return; // item can be looted only single player + } + else + { + Creature* pCreature = ObjectAccessor::GetCreature(*player, lguid); + + bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass()==CLASS_ROGUE && pCreature->lootForPickPocketed); + if ( !ok_loot || !pCreature->IsWithinDistInMap(_player,INTERACTION_DISTANCE) ) + return; + + loot = &pCreature->loot; + + // update next looter + if(Player *recipient = pCreature->GetLootRecipient()) + if(Group* group = recipient->GetGroup()) + if (group->GetLooterGuid() == player->GetGUID()) + group->UpdateLooterGuid(pCreature); + + if (loot->isLooted()) + { + // skip pickpocketing loot for speed, skinning timer redunction is no-op in fact + if(!pCreature->isAlive()) + pCreature->AllLootRemovedFromCorpse(); + + pCreature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + loot->clear(); + } + } + + //Player is not looking at loot list, he doesn't need to see updates on the loot list + loot->RemoveLooter(player->GetGUID()); +} + +void WorldSession::HandleLootMasterGiveOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+1+8); + + uint8 slotid; + uint64 lootguid, target_playerguid; + + recv_data >> lootguid >> slotid >> target_playerguid; + + if(!_player->GetGroup() || _player->GetGroup()->GetLooterGuid() != _player->GetGUID()) + { + _player->SendLootRelease(GetPlayer()->GetLootGUID()); + return; + } + + Player *target = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(target_playerguid, 0, HIGHGUID_PLAYER)); + if(!target) + return; + + sLog.outDebug("WorldSession::HandleLootMasterGiveOpcode (CMSG_LOOT_MASTER_GIVE, 0x02A3) Target = [%s].", target->GetName()); + + if(_player->GetLootGUID() != lootguid) + return; + + Loot *pLoot = NULL; + + if(IS_CREATURE_GUID(GetPlayer()->GetLootGUID())) + { + Creature *pCreature = ObjectAccessor::GetCreature(*GetPlayer(), lootguid); + if(!pCreature) + return; + + pLoot = &pCreature->loot; + } + else if(IS_GAMEOBJECT_GUID(GetPlayer()->GetLootGUID())) + { + GameObject *pGO = ObjectAccessor::GetGameObject(*GetPlayer(), lootguid); + if(!pGO) + return; + + pLoot = &pGO->loot; + } + + if(!pLoot) + return; + + if (slotid > pLoot->items.size()) + { + sLog.outDebug("AutoLootItem: Player %s might be using a hack! (slot %d, size %d)",GetPlayer()->GetName(), slotid, pLoot->items.size()); + return; + } + + LootItem& item = pLoot->items[slotid]; + + ItemPosCountVec dest; + uint8 msg = target->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, item.itemid, item.count ); + if ( msg != EQUIP_ERR_OK ) + { + target->SendEquipError( msg, NULL, NULL ); + _player->SendEquipError( msg, NULL, NULL ); // send duplicate of error massage to master looter + return; + } + + // not move item from loot to target inventory + Item * newitem = target->StoreNewItem( dest, item.itemid, true, item.randomPropertyId ); + target->SendNewItem(newitem, uint32(item.count), false, false, true ); + + // mark as looted + item.count=0; + item.is_looted=true; + + + pLoot->NotifyItemRemoved(slotid); + --pLoot->unlootedCount; +} diff --git a/src/game/LootMgr.cpp b/src/game/LootMgr.cpp new file mode 100644 index 00000000000..e7848ff4094 --- /dev/null +++ b/src/game/LootMgr.cpp @@ -0,0 +1,1239 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "LootMgr.h" +#include "Log.h" +#include "ObjectMgr.h" +#include "ProgressBar.h" +#include "World.h" +#include "Util.h" +#include "SharedDefines.h" + +static Rates const qualityToRate[MAX_ITEM_QUALITY] = { + RATE_DROP_ITEM_POOR, // ITEM_QUALITY_POOR + RATE_DROP_ITEM_NORMAL, // ITEM_QUALITY_NORMAL + RATE_DROP_ITEM_UNCOMMON, // ITEM_QUALITY_UNCOMMON + RATE_DROP_ITEM_RARE, // ITEM_QUALITY_RARE + RATE_DROP_ITEM_EPIC, // ITEM_QUALITY_EPIC + RATE_DROP_ITEM_LEGENDARY, // ITEM_QUALITY_LEGENDARY + RATE_DROP_ITEM_ARTIFACT, // ITEM_QUALITY_ARTIFACT +}; + +LootStore LootTemplates_Creature( "creature_loot_template", "creature entry"); +LootStore LootTemplates_Disenchant( "disenchant_loot_template", "item disenchant id"); +LootStore LootTemplates_Fishing( "fishing_loot_template", "area id"); +LootStore LootTemplates_Gameobject( "gameobject_loot_template", "gameobject entry"); +LootStore LootTemplates_Item( "item_loot_template", "item entry"); +LootStore LootTemplates_Pickpocketing("pickpocketing_loot_template","creature pickpocket lootid"); +LootStore LootTemplates_Prospecting( "prospecting_loot_template", "item entry"); +LootStore LootTemplates_QuestMail( "quest_mail_loot_template", "quest id"); +LootStore LootTemplates_Reference( "reference_loot_template", "reference id"); +LootStore LootTemplates_Skinning( "skinning_loot_template", "creature skinning id"); + + +class LootTemplate::LootGroup // A set of loot definitions for items (refs are not allowed) +{ + public: + void AddEntry(LootStoreItem& item); // Adds an entry to the group (at loading stage) + bool HasQuestDrop() const; // True if group includes at least 1 quest drop entry + bool HasQuestDropForPlayer(Player const * player) const; + // The same for active quests of the player + void Process(Loot& loot) const; // Rolls an item from the group (if any) and adds the item to the loot + float RawTotalChance() const; // Overall chance for the group (without equal chanced items) + float TotalChance() const; // Overall chance for the group + + void Verify(LootStore const& lootstore, uint32 id, uint32 group_id) const; + void CollectLootIds(LootIdSet& set) const; + void CheckLootRefs(LootTemplateMap const& store, LootIdSet* ref_set) const; + private: + LootStoreItemList ExplicitlyChanced; // Entries with chances defined in DB + LootStoreItemList EqualChanced; // Zero chances - every entry takes the same chance + + LootStoreItem const * Roll() const; // Rolls an item from the group, returns NULL if all miss their chances +}; + +//Remove all data and free all memory +void LootStore::Clear() +{ + for (LootTemplateMap::const_iterator itr=m_LootTemplates.begin(); itr != m_LootTemplates.end(); ++itr) + delete itr->second; + m_LootTemplates.clear(); +} + +// Checks validity of the loot store +// Actual checks are done within LootTemplate::Verify() which is called for every template +void LootStore::Verify() const +{ + for (LootTemplateMap::const_iterator i = m_LootTemplates.begin(); i != m_LootTemplates.end(); ++i ) + i->second->Verify(*this, i->first); +} + +// Loads a *_loot_template DB table into loot store +// All checks of the loaded template are called from here, no error reports at loot generation required +void LootStore::LoadLootTable() +{ + LootTemplateMap::iterator tab; + uint32 count = 0; + + // Clearing store (for reloading case) + Clear(); + + sLog.outString( "%s :", GetName()); + + // 0 1 2 3 4 5 6 7 8 + QueryResult *result = WorldDatabase.PQuery("SELECT entry, item, ChanceOrQuestChance, groupid, mincountOrRef, maxcount, lootcondition, condition_value1, condition_value2 FROM %s",GetName()); + + if (result) + { + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 entry = fields[0].GetUInt32(); + uint32 item = fields[1].GetUInt32(); + float chanceOrQuestChance = fields[2].GetFloat(); + uint8 group = fields[3].GetUInt8(); + int32 mincountOrRef = fields[4].GetInt32(); + uint8 maxcount = fields[5].GetUInt8(); + ConditionType condition = (ConditionType)fields[6].GetUInt8(); + uint32 cond_value1 = fields[7].GetUInt32(); + uint32 cond_value2 = fields[8].GetUInt32(); + + if(!PlayerCondition::IsValid(condition,cond_value1, cond_value2)) + { + sLog.outErrorDb("... in table '%s' entry %u item %u", GetName(), entry, item); + continue; // error already printed to log/console. + } + + // (condition + cond_value1/2) are converted into single conditionId + uint16 conditionId = objmgr.GetConditionId(condition, cond_value1, cond_value2); + + LootStoreItem storeitem = LootStoreItem(item, chanceOrQuestChance, group, conditionId, mincountOrRef, maxcount); + + if (!storeitem.IsValid(*this,entry)) // Validity checks + continue; + + // Looking for the template of the entry + // often entries are put together + if (m_LootTemplates.empty() || tab->first != entry) + { + // Searching the template (in case template Id changed) + tab = m_LootTemplates.find(entry); + if ( tab == m_LootTemplates.end() ) + { + std::pair< LootTemplateMap::iterator, bool > pr = m_LootTemplates.insert(LootTemplateMap::value_type(entry, new LootTemplate)); + tab = pr.first; + } + } + // else is empty - template Id and iter are the same + // finally iter refers to already existed or just created + + // Adds current row to the template + tab->second->AddEntry(storeitem); + ++count; + + } while (result->NextRow()); + + delete result; + + Verify(); // Checks validity of the loot store + + sLog.outString(); + sLog.outString( ">> Loaded %u loot definitions (%d templates)", count, m_LootTemplates.size()); + } + else + { + sLog.outString(); + sLog.outErrorDb( ">> Loaded 0 loot definitions. DB table `%s` is empty.",GetName() ); + } +} + +bool LootStore::HaveQuestLootFor(uint32 loot_id) const +{ + LootTemplateMap::const_iterator itr = m_LootTemplates.find(loot_id); + if(itr == m_LootTemplates.end()) + return false; + + // scan loot for quest items + return itr->second->HasQuestDrop(m_LootTemplates); +} + +bool LootStore::HaveQuestLootForPlayer(uint32 loot_id,Player* player) const +{ + LootTemplateMap::const_iterator tab = m_LootTemplates.find(loot_id); + if (tab != m_LootTemplates.end()) + if (tab->second->HasQuestDropForPlayer(m_LootTemplates, player)) + return true; + + return false; +} + +LootTemplate const* LootStore::GetLootFor(uint32 loot_id) const +{ + LootTemplateMap::const_iterator tab = m_LootTemplates.find(loot_id); + + if (tab == m_LootTemplates.end()) + return NULL; + + return tab->second; +} + +void LootStore::LoadAndCollectLootIds(LootIdSet& ids_set) +{ + LoadLootTable(); + + for(LootTemplateMap::const_iterator tab = m_LootTemplates.begin(); tab != m_LootTemplates.end(); ++tab) + ids_set.insert(tab->first); +} + +void LootStore::CheckLootRefs(LootIdSet* ref_set) const +{ + for(LootTemplateMap::const_iterator ltItr = m_LootTemplates.begin(); ltItr != m_LootTemplates.end(); ++ltItr) + ltItr->second->CheckLootRefs(m_LootTemplates,ref_set); +} + +void LootStore::ReportUnusedIds(LootIdSet const& ids_set) const +{ + // all still listed ids isn't referenced + for(LootIdSet::const_iterator itr = ids_set.begin(); itr != ids_set.end(); ++itr) + sLog.outErrorDb("Table '%s' entry %d isn't %s and not referenced from loot, and then useless.", GetName(), *itr,GetEntryName()); +} + +void LootStore::ReportNotExistedId(uint32 id) const +{ + sLog.outErrorDb("Table '%s' entry %d (%s) not exist but used as loot id in DB.", GetName(), id,GetEntryName()); +} + +// +// --------- LootStoreItem --------- +// + +// Checks if the entry (quest, non-quest, reference) takes it's chance (at loot generation) +// RATE_DROP_ITEMS is no longer used for all types of entries +bool LootStoreItem::Roll() const +{ + if(chance>=100.f) + return true; + + if(mincountOrRef < 0) // reference case + return roll_chance_f(chance*sWorld.getRate(RATE_DROP_ITEM_REFERENCED)); + + ItemPrototype const *pProto = objmgr.GetItemPrototype(itemid); + + float qualityModifier = pProto ? sWorld.getRate(qualityToRate[pProto->Quality]) : 1.0f; + + return roll_chance_f(chance*qualityModifier); +} + +// Checks correctness of values +bool LootStoreItem::IsValid(LootStore const& store, uint32 entry) const +{ + if (mincountOrRef == 0) + { + sLog.outErrorDb("Table '%s' entry %d item %d: wrong mincountOrRef (%d) - skipped", store.GetName(), entry, itemid, mincountOrRef); + return false; + } + + if( mincountOrRef > 0 ) // item (quest or non-quest) entry, maybe grouped + { + ItemPrototype const *proto = objmgr.GetItemPrototype(itemid); + if(!proto) + { + sLog.outErrorDb("Table '%s' entry %d item %d: item entry not listed in `item_template` - skipped", store.GetName(), entry, itemid); + return false; + } + + if( chance == 0 && group == 0) // Zero chance is allowed for grouped entries only + { + sLog.outErrorDb("Table '%s' entry %d item %d: equal-chanced grouped entry, but group not defined - skipped", store.GetName(), entry, itemid); + return false; + } + + if( chance != 0 && chance < 0.000001f ) // loot with low chance + { + sLog.outErrorDb("Table '%s' entry %d item %d: low chance (%d) - skipped", store.GetName(), entry, itemid, chance); + return false; + } + } + else // mincountOrRef < 0 + { + if (needs_quest) + sLog.outErrorDb("Table '%s' entry %d item %d: quest chance will be treated as non-quest chance", store.GetName(), entry, itemid); + else if( chance == 0 ) // no chance for the reference + { + sLog.outErrorDb("Table '%s' entry %d item %d: zero chance is specified for a reference, skipped", store.GetName(), entry, itemid); + return false; + } + } + return true; // Referenced template existence is checked at whole store level +} + +// +// --------- LootItem --------- +// + +// Constructor, copies most fields from LootStoreItem and generates random count +LootItem::LootItem(LootStoreItem const& li) +{ + itemid = li.itemid; + conditionId = li.conditionId; + + ItemPrototype const* proto = objmgr.GetItemPrototype(itemid); + freeforall = proto && (proto->Flags & ITEM_FLAGS_PARTY_LOOT); + + needs_quest = li.needs_quest; + + count = urand(li.mincountOrRef, li.maxcount); // constructor called for mincountOrRef > 0 only + randomSuffix = GenerateEnchSuffixFactor(itemid); + randomPropertyId = Item::GenerateItemRandomPropertyId(itemid); + is_looted = 0; + is_blocked = 0; + is_underthreshold = 0; + is_counted = 0; +} + +// Basic checks for player/item compatibility - if false no chance to see the item in the loot +bool LootItem::AllowedForPlayer(Player const * player) const +{ + // DB conditions check + if ( !objmgr.IsPlayerMeetToCondition(player,conditionId) ) + return false; + + if ( needs_quest ) + { + // Checking quests for quest-only drop (check only quests requirements in this case) + if( !player->HasQuestForItem(itemid) ) + return false; + } + else + { + // Not quest only drop (check quest starting items for already accepted non-repeatable quests) + ItemPrototype const *pProto = objmgr.GetItemPrototype(itemid); + if (pProto && pProto->StartQuest && player->GetQuestStatus(pProto->StartQuest) != QUEST_STATUS_NONE && !player->HasQuestForItem(itemid)) + return false; + } + + return true; +} + +// +// --------- Loot --------- +// + +// Inserts the item into the loot (called by LootTemplate processors) +void Loot::AddItem(LootStoreItem const & item) +{ + if (item.needs_quest) // Quest drop + { + if (quest_items.size() < MAX_NR_QUEST_ITEMS) + quest_items.push_back(LootItem(item)); + } + else if (items.size() < MAX_NR_LOOT_ITEMS) // Non-quest drop + { + items.push_back(LootItem(item)); + + // non-conditional one-player only items are counted here, + // free for all items are counted in FillFFALoot(), + // non-ffa conditionals are counted in FillNonQuestNonFFAConditionalLoot() + if( !item.conditionId ) + { + ItemPrototype const* proto = objmgr.GetItemPrototype(item.itemid); + if( !proto || (proto->Flags & ITEM_FLAGS_PARTY_LOOT)==0 ) + ++unlootedCount; + } + } +} + +// Calls processor of corresponding LootTemplate (which handles everything including references) +void Loot::FillLoot(uint32 loot_id, LootStore const& store, Player* loot_owner) +{ + LootTemplate const* tab = store.GetLootFor(loot_id); + + if (!tab) + { + sLog.outErrorDb("Table '%s' loot id #%u used but it doesn't have records.",store.GetName(),loot_id); + return; + } + + items.reserve(MAX_NR_LOOT_ITEMS); + quest_items.reserve(MAX_NR_QUEST_ITEMS); + + tab->Process(*this, store); // Processing is done there, callback via Loot::AddItem() + + // Setting access rights fow group-looting case + if(!loot_owner) + return; + Group * pGroup=loot_owner->GetGroup(); + if(!pGroup) + return; + for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + { + //fill the quest item map for every player in the recipient's group + Player* pl = itr->getSource(); + if(!pl) + continue; + uint32 plguid = pl->GetGUIDLow(); + QuestItemMap::iterator qmapitr = PlayerQuestItems.find(plguid); + if (qmapitr == PlayerQuestItems.end()) + { + FillQuestLoot(pl); + } + qmapitr = PlayerFFAItems.find(plguid); + if (qmapitr == PlayerFFAItems.end()) + { + FillFFALoot(pl); + } + qmapitr = PlayerNonQuestNonFFAConditionalItems.find(plguid); + if (qmapitr == PlayerNonQuestNonFFAConditionalItems.end()) + { + FillNonQuestNonFFAConditionalLoot(pl); + } + } +} + +QuestItemList* Loot::FillFFALoot(Player* player) +{ + QuestItemList *ql = new QuestItemList(); + + for(uint8 i = 0; i < items.size(); i++) + { + LootItem &item = items[i]; + if(!item.is_looted && item.freeforall && item.AllowedForPlayer(player) ) + { + ql->push_back(QuestItem(i)); + ++unlootedCount; + } + } + if (ql->empty()) + { + delete ql; + return NULL; + } + + PlayerFFAItems[player->GetGUIDLow()] = ql; + return ql; +} + +QuestItemList* Loot::FillQuestLoot(Player* player) +{ + if (items.size() == MAX_NR_LOOT_ITEMS) return NULL; + QuestItemList *ql = new QuestItemList(); + + for(uint8 i = 0; i < quest_items.size(); i++) + { + LootItem &item = quest_items[i]; + if(!item.is_looted && item.AllowedForPlayer(player) ) + { + ql->push_back(QuestItem(i)); + + // questitems get blocked when they first apper in a + // player's quest vector + // + // increase once if one looter only, looter-times if free for all + if (item.freeforall || !item.is_blocked) + ++unlootedCount; + + item.is_blocked = true; + + if (items.size() + ql->size() == MAX_NR_LOOT_ITEMS) + break; + } + } + if (ql->empty()) + { + delete ql; + return NULL; + } + + PlayerQuestItems[player->GetGUIDLow()] = ql; + return ql; +} + +QuestItemList* Loot::FillNonQuestNonFFAConditionalLoot(Player* player) +{ + QuestItemList *ql = new QuestItemList(); + + for(uint8 i = 0; i < items.size(); ++i) + { + LootItem &item = items[i]; + if(!item.is_looted && !item.freeforall && item.conditionId && item.AllowedForPlayer(player)) + { + ql->push_back(QuestItem(i)); + if(!item.is_counted) + { + ++unlootedCount; + item.is_counted=true; + } + } + } + if (ql->empty()) + { + delete ql; + return NULL; + } + + PlayerNonQuestNonFFAConditionalItems[player->GetGUIDLow()] = ql; + return ql; +} + +//=================================================== + +void Loot::NotifyItemRemoved(uint8 lootIndex) +{ + // notify all players that are looting this that the item was removed + // convert the index to the slot the player sees + std::set::iterator i_next; + for(std::set::iterator i = PlayersLooting.begin(); i != PlayersLooting.end(); i = i_next) + { + i_next = i; + ++i_next; + if(Player* pl = ObjectAccessor::FindPlayer(*i)) + pl->SendNotifyLootItemRemoved(lootIndex); + else + PlayersLooting.erase(i); + } +} + +void Loot::NotifyMoneyRemoved() +{ + // notify all players that are looting this that the money was removed + std::set::iterator i_next; + for(std::set::iterator i = PlayersLooting.begin(); i != PlayersLooting.end(); i = i_next) + { + i_next = i; + ++i_next; + if(Player* pl = ObjectAccessor::FindPlayer(*i)) + pl->SendNotifyLootMoneyRemoved(); + else + PlayersLooting.erase(i); + } +} + +void Loot::NotifyQuestItemRemoved(uint8 questIndex) +{ + // when a free for all questitem is looted + // all players will get notified of it being removed + // (other questitems can be looted by each group member) + // bit inefficient but isnt called often + + std::set::iterator i_next; + for(std::set::iterator i = PlayersLooting.begin(); i != PlayersLooting.end(); i = i_next) + { + i_next = i; + ++i_next; + if(Player* pl = ObjectAccessor::FindPlayer(*i)) + { + QuestItemMap::iterator pq = PlayerQuestItems.find(pl->GetGUIDLow()); + if (pq != PlayerQuestItems.end() && pq->second) + { + // find where/if the player has the given item in it's vector + QuestItemList& pql = *pq->second; + + uint8 j; + for (j = 0; j < pql.size(); ++j) + if (pql[j].index == questIndex) + break; + + if (j < pql.size()) + pl->SendNotifyLootItemRemoved(items.size()+j); + } + } + else + PlayersLooting.erase(i); + } +} + +void Loot::generateMoneyLoot( uint32 minAmount, uint32 maxAmount ) +{ + if (maxAmount > 0) + { + if (maxAmount <= minAmount) + gold = uint32(maxAmount * sWorld.getRate(RATE_DROP_MONEY)); + else if ((maxAmount - minAmount) < 32700) + gold = uint32(urand(minAmount, maxAmount) * sWorld.getRate(RATE_DROP_MONEY)); + else + gold = uint32(urand(minAmount >> 8, maxAmount >> 8) * sWorld.getRate(RATE_DROP_MONEY)) << 8; + } +} + +LootItem* Loot::LootItemInSlot(uint32 lootSlot, Player* player, QuestItem **qitem, QuestItem **ffaitem, QuestItem **conditem) +{ + LootItem* item = NULL; + bool is_looted = true; + if (lootSlot >= items.size()) + { + uint32 questSlot = lootSlot - items.size(); + QuestItemMap::const_iterator itr = PlayerQuestItems.find(player->GetGUIDLow()); + if (itr != PlayerQuestItems.end() && questSlot < itr->second->size()) + { + QuestItem *qitem2 = &itr->second->at(questSlot); + if(qitem) + *qitem = qitem2; + item = &quest_items[qitem2->index]; + is_looted = qitem2->is_looted; + } + } + else + { + item = &items[lootSlot]; + is_looted = item->is_looted; + if(item->freeforall) + { + QuestItemMap::const_iterator itr = PlayerFFAItems.find(player->GetGUIDLow()); + if (itr != PlayerFFAItems.end()) + { + for(QuestItemList::iterator iter=itr->second->begin(); iter!= itr->second->end(); ++iter) + if(iter->index==lootSlot) + { + QuestItem *ffaitem2 = (QuestItem*)&(*iter); + if(ffaitem) + *ffaitem = ffaitem2; + is_looted = ffaitem2->is_looted; + break; + } + } + } + else if(item->conditionId) + { + QuestItemMap::const_iterator itr = PlayerNonQuestNonFFAConditionalItems.find(player->GetGUIDLow()); + if (itr != PlayerNonQuestNonFFAConditionalItems.end()) + { + for(QuestItemList::iterator iter=itr->second->begin(); iter!= itr->second->end(); ++iter) + { + if(iter->index==lootSlot) + { + QuestItem *conditem2 = (QuestItem*)&(*iter); + if(conditem) + *conditem = conditem2; + is_looted = conditem2->is_looted; + break; + } + } + } + } + } + + if(is_looted) + return NULL; + + return item; +} + +ByteBuffer& operator<<(ByteBuffer& b, LootItem const& li) +{ + b << uint32(li.itemid); + b << uint32(li.count); // nr of items of this type + b << uint32(objmgr.GetItemPrototype(li.itemid)->DisplayInfoID); + b << uint32(li.randomSuffix); + b << uint32(li.randomPropertyId); + //b << uint8(0); // slot type - will send after this function call + return b; +} + +ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv) +{ + Loot &l = lv.loot; + + uint8 itemsShown = 0; + + //gold + b << uint32(lv.permission!=NONE_PERMISSION ? l.gold : 0); + + size_t count_pos = b.wpos(); // pos of item count byte + b << uint8(0); // item count placeholder + + switch (lv.permission) + { + case GROUP_PERMISSION: + { + // You are not the items proprietary, so you can only see + // blocked rolled items and quest items, and !ffa items + for (uint8 i = 0; i < l.items.size(); ++i) + { + if (!l.items[i].is_looted && !l.items[i].freeforall && !l.items[i].conditionId && l.items[i].AllowedForPlayer(lv.viewer)) + { + uint8 slot_type = (l.items[i].is_blocked || l.items[i].is_underthreshold) ? 0 : 1; + + b << uint8(i) << l.items[i]; //send the index and the item if it's not looted, and blocked or under threshold, free for all items will be sent later, only one-player loots here + b << uint8(slot_type); // 0 - get 1 - look only + ++itemsShown; + } + } + break; + } + case ALL_PERMISSION: + case MASTER_PERMISSION: + { + uint8 slot_type = (lv.permission==MASTER_PERMISSION) ? 2 : 0; + for (uint8 i = 0; i < l.items.size(); ++i) + { + if (!l.items[i].is_looted && !l.items[i].freeforall && !l.items[i].conditionId && l.items[i].AllowedForPlayer(lv.viewer)) + { + b << uint8(i) << l.items[i]; //only send one-player loot items now, free for all will be sent later + b << uint8(slot_type); // 0 - get 2 - master selection + ++itemsShown; + } + } + break; + } + case NONE_PERMISSION: + default: + return b; // nothing output more + } + + if (lv.qlist) + { + for (QuestItemList::iterator qi = lv.qlist->begin() ; qi != lv.qlist->end(); ++qi) + { + LootItem &item = l.quest_items[qi->index]; + if (!qi->is_looted && !item.is_looted) + { + b << uint8(l.items.size() + (qi - lv.qlist->begin())); + b << item; + b << uint8(0); // allow loot + ++itemsShown; + } + } + } + + if (lv.ffalist) + { + for (QuestItemList::iterator fi = lv.ffalist->begin() ; fi != lv.ffalist->end(); ++fi) + { + LootItem &item = l.items[fi->index]; + if (!fi->is_looted && !item.is_looted) + { + b << uint8(fi->index) << item; + b << uint8(0); // allow loot + ++itemsShown; + } + } + } + + if (lv.conditionallist) + { + for (QuestItemList::iterator ci = lv.conditionallist->begin() ; ci != lv.conditionallist->end(); ++ci) + { + LootItem &item = l.items[ci->index]; + if (!ci->is_looted && !item.is_looted) + { + b << uint8(ci->index) << item; + b << uint8(0); // allow loot + ++itemsShown; + } + } + } + + //update number of items shown + b.put(count_pos,itemsShown); + + return b; +} + +// +// --------- LootTemplate::LootGroup --------- +// + +// Adds an entry to the group (at loading stage) +void LootTemplate::LootGroup::AddEntry(LootStoreItem& item) +{ + if (item.chance != 0) + ExplicitlyChanced.push_back(item); + else + EqualChanced.push_back(item); +} + +// Rolls an item from the group, returns NULL if all miss their chances +LootStoreItem const * LootTemplate::LootGroup::Roll() const +{ + if (!ExplicitlyChanced.empty()) // First explicitly chanced entries are checked + { + float Roll = rand_chance(); + + for (uint32 i=0; i=100.f) + return &ExplicitlyChanced[i]; + + ItemPrototype const *pProto = objmgr.GetItemPrototype(ExplicitlyChanced[i].itemid); + float qualityMultiplier = pProto ? sWorld.getRate(qualityToRate[pProto->Quality]) : 1.0f; + Roll -= ExplicitlyChanced[i].chance * qualityMultiplier; + if (Roll < 0) + return &ExplicitlyChanced[i]; + } + } + if (!EqualChanced.empty()) // If nothing selected yet - an item is taken from equal-chanced part + return &EqualChanced[irand(0, EqualChanced.size()-1)]; + + return NULL; // Empty drop from the group +} + +// True if group includes at least 1 quest drop entry +bool LootTemplate::LootGroup::HasQuestDrop() const +{ + for (LootStoreItemList::const_iterator i=ExplicitlyChanced.begin(); i != ExplicitlyChanced.end(); ++i) + if (i->needs_quest) + return true; + for (LootStoreItemList::const_iterator i=EqualChanced.begin(); i != EqualChanced.end(); ++i) + if (i->needs_quest) + return true; + return false; +} + +// True if group includes at least 1 quest drop entry for active quests of the player +bool LootTemplate::LootGroup::HasQuestDropForPlayer(Player const * player) const +{ + for (LootStoreItemList::const_iterator i=ExplicitlyChanced.begin(); i != ExplicitlyChanced.end(); ++i) + if (player->HasQuestForItem(i->itemid)) + return true; + for (LootStoreItemList::const_iterator i=EqualChanced.begin(); i != EqualChanced.end(); ++i) + if (player->HasQuestForItem(i->itemid)) + return true; + return false; +} + +// Rolls an item from the group (if any takes its chance) and adds the item to the loot +void LootTemplate::LootGroup::Process(Loot& loot) const +{ + LootStoreItem const * item = Roll(); + if (item != NULL) + loot.AddItem(*item); +} + +// Overall chance for the group without equal chanced items +float LootTemplate::LootGroup::RawTotalChance() const +{ + float result = 0; + + for (LootStoreItemList::const_iterator i=ExplicitlyChanced.begin(); i != ExplicitlyChanced.end(); ++i) + if ( !i->needs_quest ) + result += i->chance; + + return result; +} + +// Overall chance for the group +float LootTemplate::LootGroup::TotalChance() const +{ + float result = RawTotalChance(); + + if (!EqualChanced.empty() && result < 100.0f) + return 100.0f; + + return result; +} + +void LootTemplate::LootGroup::Verify(LootStore const& lootstore, uint32 id, uint32 group_id) const +{ + float chance = RawTotalChance(); + if (chance > 101.0f) // TODO: replace with 100% when DBs will be ready + { + sLog.outErrorDb("Table '%s' entry %u group %d has total chance > 100%% (%f)", lootstore.GetName(), id, group_id, chance); + } + + if(chance >= 100.0f && !EqualChanced.empty()) + { + sLog.outErrorDb("Table '%s' entry %u group %d has items with chance=0%% but group total chance >= 100%% (%f)", lootstore.GetName(), id, group_id, chance); + } +} + +void LootTemplate::LootGroup::CheckLootRefs(LootTemplateMap const& store, LootIdSet* ref_set) const +{ + for (LootStoreItemList::const_iterator ieItr=ExplicitlyChanced.begin(); ieItr != ExplicitlyChanced.end(); ++ieItr) + { + if(ieItr->mincountOrRef < 0) + { + if(!LootTemplates_Reference.GetLootFor(-ieItr->mincountOrRef)) + LootTemplates_Reference.ReportNotExistedId(-ieItr->mincountOrRef); + else if(ref_set) + ref_set->erase(-ieItr->mincountOrRef); + } + } + + for (LootStoreItemList::const_iterator ieItr=EqualChanced.begin(); ieItr != EqualChanced.end(); ++ieItr) + { + if(ieItr->mincountOrRef < 0) + { + if(!LootTemplates_Reference.GetLootFor(-ieItr->mincountOrRef)) + LootTemplates_Reference.ReportNotExistedId(-ieItr->mincountOrRef); + else if(ref_set) + ref_set->erase(-ieItr->mincountOrRef); + } + } +} + +// +// --------- LootTemplate --------- +// + +// Adds an entry to the group (at loading stage) +void LootTemplate::AddEntry(LootStoreItem& item) +{ + if (item.group > 0 && item.mincountOrRef > 0) // Group + { + if (item.group >= Groups.size()) + Groups.resize(item.group); // Adds new group the the loot template if needed + Groups[item.group-1].AddEntry(item); // Adds new entry to the group + } + else // Non-grouped entries and references are stored together + Entries.push_back(item); +} + +// Rolls for every item in the template and adds the rolled items the the loot +void LootTemplate::Process(Loot& loot, LootStore const& store, uint8 groupId) const +{ + if (groupId) // Group reference uses own processing of the group + { + if (groupId > Groups.size()) + return; // Error message already printed at loading stage + + Groups[groupId-1].Process(loot); + return; + } + + // Rolling non-grouped items + for (LootStoreItemList::const_iterator i = Entries.begin() ; i != Entries.end() ; i++ ) + { + if ( !i->Roll() ) + continue; // Bad luck for the entry + + if (i->mincountOrRef < 0) // References processing + { + LootTemplate const* Referenced = LootTemplates_Reference.GetLootFor(-i->mincountOrRef); + + if(!Referenced) + continue; // Error message already printed at loading stage + + for (uint32 loop=0; loop < i->maxcount; ++loop )// Ref multiplicator + Referenced->Process(loot, store, i->group); // Ref processing + } + else // Plain entries (not a reference, not grouped) + loot.AddItem(*i); // Chance is already checked, just add + } + + // Now processing groups + for (LootGroups::const_iterator i = Groups.begin( ) ; i != Groups.end( ) ; i++ ) + i->Process(loot); +} + +// True if template includes at least 1 quest drop entry +bool LootTemplate::HasQuestDrop(LootTemplateMap const& store, uint8 groupId) const +{ + if (groupId) // Group reference + { + if (groupId > Groups.size()) + return false; // Error message [should be] already printed at loading stage + return Groups[groupId-1].HasQuestDrop(); + } + + for (LootStoreItemList::const_iterator i = Entries.begin(); i != Entries.end(); ++i ) + { + if (i->mincountOrRef < 0) // References + { + LootTemplateMap::const_iterator Referenced = store.find(-i->mincountOrRef); + if( Referenced ==store.end() ) + continue; // Error message [should be] already printed at loading stage + if (Referenced->second->HasQuestDrop(store, i->group) ) + return true; + } + else if ( i->needs_quest ) + return true; // quest drop found + } + + // Now processing groups + for (LootGroups::const_iterator i = Groups.begin() ; i != Groups.end() ; i++ ) + if (i->HasQuestDrop()) + return true; + + return false; +} + +// True if template includes at least 1 quest drop for an active quest of the player +bool LootTemplate::HasQuestDropForPlayer(LootTemplateMap const& store, Player const* player, uint8 groupId) const +{ + if (groupId) // Group reference + { + if (groupId > Groups.size()) + return false; // Error message already printed at loading stage + return Groups[groupId-1].HasQuestDropForPlayer(player); + } + + // Checking non-grouped entries + for (LootStoreItemList::const_iterator i = Entries.begin() ; i != Entries.end() ; i++ ) + { + if (i->mincountOrRef < 0) // References processing + { + LootTemplateMap::const_iterator Referenced = store.find(-i->mincountOrRef); + if (Referenced == store.end() ) + continue; // Error message already printed at loading stage + if (Referenced->second->HasQuestDropForPlayer(store, player, i->group) ) + return true; + } + else if ( player->HasQuestForItem(i->itemid) ) + return true; // active quest drop found + } + + // Now checking groups + for (LootGroups::const_iterator i = Groups.begin(); i != Groups.end(); ++i ) + if (i->HasQuestDrop()) + return true; + + return false; +} + +// Checks integrity of the template +void LootTemplate::Verify(LootStore const& lootstore, uint32 id) const +{ + // Checking group chances + for (uint32 i=0; i < Groups.size(); ++i) + Groups[i].Verify(lootstore,id,i+1); + + // TODO: References validity checks +} + +void LootTemplate::CheckLootRefs(LootTemplateMap const& store, LootIdSet* ref_set) const +{ + for(LootStoreItemList::const_iterator ieItr = Entries.begin(); ieItr != Entries.end(); ++ieItr) + { + if(ieItr->mincountOrRef < 0) + { + if(!LootTemplates_Reference.GetLootFor(-ieItr->mincountOrRef)) + LootTemplates_Reference.ReportNotExistedId(-ieItr->mincountOrRef); + else if(ref_set) + ref_set->erase(-ieItr->mincountOrRef); + } + } + + for(LootGroups::const_iterator grItr = Groups.begin(); grItr != Groups.end(); ++grItr) + grItr->CheckLootRefs(store,ref_set); +} + +void LoadLootTemplates_Creature() +{ + LootIdSet ids_set, ids_setUsed; + LootTemplates_Creature.LoadAndCollectLootIds(ids_set); + + // remove real entries and check existence loot + for(uint32 i = 1; i < sCreatureStorage.MaxEntry; ++i ) + { + if(CreatureInfo const* cInfo = sCreatureStorage.LookupEntry(i)) + { + if(uint32 lootid = cInfo->lootid) + { + if(!ids_set.count(lootid)) + LootTemplates_Creature.ReportNotExistedId(lootid); + else + ids_setUsed.insert(lootid); + } + } + } + for(LootIdSet::const_iterator itr = ids_setUsed.begin(); itr != ids_setUsed.end(); ++itr) + ids_set.erase(*itr); + + // output error for any still listed (not referenced from appropriate table) ids + LootTemplates_Creature.ReportUnusedIds(ids_set); +} + +void LoadLootTemplates_Disenchant() +{ + LootIdSet ids_set, ids_setUsed; + LootTemplates_Disenchant.LoadAndCollectLootIds(ids_set); + + // remove real entries and check existence loot + for(uint32 i = 1; i < sItemStorage.MaxEntry; ++i ) + { + if(ItemPrototype const* proto = sItemStorage.LookupEntry(i)) + { + if(uint32 lootid = proto->DisenchantID) + { + if(!ids_set.count(lootid)) + LootTemplates_Disenchant.ReportNotExistedId(lootid); + else + ids_setUsed.insert(lootid); + } + } + } + for(LootIdSet::const_iterator itr = ids_setUsed.begin(); itr != ids_setUsed.end(); ++itr) + ids_set.erase(*itr); + // output error for any still listed (not referenced from appropriate table) ids + LootTemplates_Disenchant.ReportUnusedIds(ids_set); +} + +void LoadLootTemplates_Fishing() +{ + LootIdSet ids_set; + LootTemplates_Fishing.LoadAndCollectLootIds(ids_set); + + // remove real entries and check existence loot + for(uint32 i = 1; i < sAreaStore.GetNumRows(); ++i ) + { + if(AreaTableEntry const* areaEntry = sAreaStore.LookupEntry(i)) + if(ids_set.count(areaEntry->ID)) + ids_set.erase(areaEntry->ID); + } + + // output error for any still listed (not referenced from appropriate table) ids + LootTemplates_Fishing.ReportUnusedIds(ids_set); +} + +void LoadLootTemplates_Gameobject() +{ + LootIdSet ids_set, ids_setUsed; + LootTemplates_Gameobject.LoadAndCollectLootIds(ids_set); + + // remove real entries and check existence loot + for(uint32 i = 1; i < sGOStorage.MaxEntry; ++i ) + { + if(GameObjectInfo const* gInfo = sGOStorage.LookupEntry(i)) + { + if(uint32 lootid = GameObject::GetLootId(gInfo)) + { + if(!ids_set.count(lootid)) + LootTemplates_Gameobject.ReportNotExistedId(lootid); + else + ids_setUsed.insert(lootid); + } + } + } + for(LootIdSet::const_iterator itr = ids_setUsed.begin(); itr != ids_setUsed.end(); ++itr) + ids_set.erase(*itr); + + // output error for any still listed (not referenced from appropriate table) ids + LootTemplates_Gameobject.ReportUnusedIds(ids_set); +} + +void LoadLootTemplates_Item() +{ + LootIdSet ids_set; + LootTemplates_Item.LoadAndCollectLootIds(ids_set); + + // remove real entries and check existence loot + for(uint32 i = 1; i < sItemStorage.MaxEntry; ++i ) + if(ItemPrototype const* proto = sItemStorage.LookupEntry(i)) + if(ids_set.count(proto->ItemId)) + ids_set.erase(proto->ItemId); + + // output error for any still listed (not referenced from appropriate table) ids + LootTemplates_Item.ReportUnusedIds(ids_set); +} + +void LoadLootTemplates_Pickpocketing() +{ + LootIdSet ids_set, ids_setUsed; + LootTemplates_Pickpocketing.LoadAndCollectLootIds(ids_set); + + // remove real entries and check existence loot + for(uint32 i = 1; i < sCreatureStorage.MaxEntry; ++i ) + { + if(CreatureInfo const* cInfo = sCreatureStorage.LookupEntry(i)) + { + if(uint32 lootid = cInfo->pickpocketLootId) + { + if(!ids_set.count(lootid)) + LootTemplates_Pickpocketing.ReportNotExistedId(lootid); + else + ids_setUsed.insert(lootid); + } + } + } + for(LootIdSet::const_iterator itr = ids_setUsed.begin(); itr != ids_setUsed.end(); ++itr) + ids_set.erase(*itr); + + // output error for any still listed (not referenced from appropriate table) ids + LootTemplates_Pickpocketing.ReportUnusedIds(ids_set); +} + +void LoadLootTemplates_Prospecting() +{ + LootIdSet ids_set; + LootTemplates_Prospecting.LoadAndCollectLootIds(ids_set); + + // remove real entries and check existence loot + for(uint32 i = 1; i < sItemStorage.MaxEntry; ++i ) + if(ItemPrototype const* proto = sItemStorage.LookupEntry(i)) + if(ids_set.count(proto->ItemId)) + ids_set.erase(proto->ItemId); + + // output error for any still listed (not referenced from appropriate table) ids + LootTemplates_Prospecting.ReportUnusedIds(ids_set); +} + +void LoadLootTemplates_QuestMail() +{ + LootIdSet ids_set; + LootTemplates_QuestMail.LoadAndCollectLootIds(ids_set); + + // remove real entries and check existence loot + ObjectMgr::QuestMap const& questMap = objmgr.GetQuestTemplates(); + for(ObjectMgr::QuestMap::const_iterator itr = questMap.begin(); itr != questMap.end(); ++itr ) + if(ids_set.count(itr->first)) + ids_set.erase(itr->first); + + // output error for any still listed (not referenced from appropriate table) ids + LootTemplates_QuestMail.ReportUnusedIds(ids_set); +} + +void LoadLootTemplates_Skinning() +{ + LootIdSet ids_set, ids_setUsed; + LootTemplates_Skinning.LoadAndCollectLootIds(ids_set); + + // remove real entries and check existence loot + for(uint32 i = 1; i < sCreatureStorage.MaxEntry; ++i ) + { + if(CreatureInfo const* cInfo = sCreatureStorage.LookupEntry(i)) + { + if(uint32 lootid = cInfo->SkinLootId) + { + if(!ids_set.count(lootid)) + LootTemplates_Skinning.ReportNotExistedId(lootid); + else + ids_setUsed.insert(lootid); + } + } + } + for(LootIdSet::const_iterator itr = ids_setUsed.begin(); itr != ids_setUsed.end(); ++itr) + ids_set.erase(*itr); + + // output error for any still listed (not referenced from appropriate table) ids + LootTemplates_Skinning.ReportUnusedIds(ids_set); +} + +void LoadLootTemplates_Reference() +{ + LootIdSet ids_set; + LootTemplates_Reference.LoadAndCollectLootIds(ids_set); + + // check references and remove used + LootTemplates_Creature.CheckLootRefs(&ids_set); + LootTemplates_Fishing.CheckLootRefs(&ids_set); + LootTemplates_Gameobject.CheckLootRefs(&ids_set); + LootTemplates_Item.CheckLootRefs(&ids_set); + LootTemplates_Pickpocketing.CheckLootRefs(&ids_set); + LootTemplates_Skinning.CheckLootRefs(&ids_set); + LootTemplates_Disenchant.CheckLootRefs(&ids_set); + LootTemplates_Prospecting.CheckLootRefs(&ids_set); + LootTemplates_QuestMail.CheckLootRefs(&ids_set); + LootTemplates_Reference.CheckLootRefs(&ids_set); + + // output error for any still listed ids (not referenced from any loot table) + LootTemplates_Reference.ReportUnusedIds(ids_set); +} diff --git a/src/game/LootMgr.h b/src/game/LootMgr.h new file mode 100644 index 00000000000..fe063a447fc --- /dev/null +++ b/src/game/LootMgr.h @@ -0,0 +1,331 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_LOOTMGR_H +#define MANGOS_LOOTMGR_H + +#include "ItemEnchantmentMgr.h" +#include "ByteBuffer.h" +#include "Utilities/LinkedReference/RefManager.h" + +#include +#include + +enum RollType +{ + ROLL_PASS = 0, + ROLL_NEED = 1, + ROLL_GREED = 2 +}; + +#define MAX_NR_LOOT_ITEMS 16 +// note: the client cannot show more than 16 items total +#define MAX_NR_QUEST_ITEMS 32 +// unrelated to the number of quest items shown, just for reserve + +enum LootMethod +{ + FREE_FOR_ALL = 0, + ROUND_ROBIN = 1, + MASTER_LOOT = 2, + GROUP_LOOT = 3, + NEED_BEFORE_GREED = 4 +}; + +enum PermissionTypes +{ + ALL_PERMISSION = 0, + GROUP_PERMISSION = 1, + MASTER_PERMISSION = 2, + NONE_PERMISSION = 3 +}; + +class Player; +class LootStore; + +struct LootStoreItem +{ + uint32 itemid; // id of the item + float chance; // always positive, chance to drop for both quest and non-quest items, chance to be used for refs + int32 mincountOrRef; // mincount for drop items (positive) or minus referenced TemplateleId (negative) + uint8 group :8; + uint8 maxcount :8; // max drop count for the item (mincountOrRef positive) or Ref multiplicator (mincountOrRef negative) + uint16 conditionId :16; // additional loot condition Id + bool needs_quest :1; // quest drop (negative ChanceOrQuestChance in DB) + + // Constructor, converting ChanceOrQuestChance -> (chance, needs_quest) + // displayid is filled in IsValid() which must be called after + LootStoreItem(uint32 _itemid, float _chanceOrQuestChance, int8 _group, uint8 _conditionId, int32 _mincountOrRef, uint8 _maxcount) + : itemid(_itemid), chance(fabs(_chanceOrQuestChance)), mincountOrRef(_mincountOrRef), + group(_group), maxcount(_maxcount), conditionId(_conditionId), + needs_quest(_chanceOrQuestChance < 0) {} + + bool Roll() const; // Checks if the entry takes it's chance (at loot generation) + bool IsValid(LootStore const& store, uint32 entry) const; + // Checks correctness of values +}; + +struct LootItem +{ + uint32 itemid; + uint32 randomSuffix; + int32 randomPropertyId; + uint16 conditionId :16; // allow compiler pack structure + uint8 count : 8; + bool is_looted : 1; + bool is_blocked : 1; + bool freeforall : 1; // free for all + bool is_underthreshold : 1; + bool is_counted : 1; + bool needs_quest : 1; // quest drop + + // Constructor, copies most fields from LootStoreItem, generates random count and random suffixes/properties + // Should be called for non-reference LootStoreItem entries only (mincountOrRef > 0) + explicit LootItem(LootStoreItem const& li); + + // Basic checks for player/item compatibility - if false no chance to see the item in the loot + bool AllowedForPlayer(Player const * player) const; +}; + +struct QuestItem +{ + uint8 index; // position in quest_items; + bool is_looted; + + QuestItem() + : index(0), is_looted(false) {} + + QuestItem(uint8 _index, bool _islooted = false) + : index(_index), is_looted(_islooted) {} +}; + +struct Loot; +class LootTemplate; + +typedef std::vector QuestItemList; +typedef std::map QuestItemMap; +typedef std::vector LootStoreItemList; +typedef HM_NAMESPACE::hash_map LootTemplateMap; + +typedef std::set LootIdSet; + +class LootStore +{ + public: + explicit LootStore(char const* name, char const* entryName) : m_name(name), m_entryName(entryName) {} + virtual ~LootStore() { Clear(); } + + void Verify() const; + + void LoadAndCollectLootIds(LootIdSet& ids_set); + void CheckLootRefs(LootIdSet* ref_set = NULL) const;// check existence reference and remove it from ref_set + void ReportUnusedIds(LootIdSet const& ids_set) const; + void ReportNotExistedId(uint32 id) const; + + bool HaveLootFor(uint32 loot_id) const { return m_LootTemplates.find(loot_id) != m_LootTemplates.end(); } + bool HaveQuestLootFor(uint32 loot_id) const; + bool HaveQuestLootForPlayer(uint32 loot_id,Player* player) const; + + LootTemplate const* GetLootFor(uint32 loot_id) const; + + char const* GetName() const { return m_name; } + char const* GetEntryName() const { return m_entryName; } + protected: + void LoadLootTable(); + void Clear(); + private: + LootTemplateMap m_LootTemplates; + char const* m_name; + char const* m_entryName; +}; + +class LootTemplate +{ + class LootGroup; // A set of loot definitions for items (refs are not allowed inside) + typedef std::vector LootGroups; + + public: + // Adds an entry to the group (at loading stage) + void AddEntry(LootStoreItem& item); + // Rolls for every item in the template and adds the rolled items the the loot + void Process(Loot& loot, LootStore const& store, uint8 GroupId = 0) const; + + // True if template includes at least 1 quest drop entry + bool HasQuestDrop(LootTemplateMap const& store, uint8 GroupId = 0) const; + // True if template includes at least 1 quest drop for an active quest of the player + bool HasQuestDropForPlayer(LootTemplateMap const& store, Player const * player, uint8 GroupId = 0) const; + + // Checks integrity of the template + void Verify(LootStore const& store, uint32 Id) const; + void CheckLootRefs(LootTemplateMap const& store, LootIdSet* ref_set) const; + private: + LootStoreItemList Entries; // not grouped only + LootGroups Groups; // groups have own (optimised) processing, grouped entries go there +}; + +//===================================================== + +class LootValidatorRef : public Reference +{ + public: + LootValidatorRef() {} + void targetObjectDestroyLink() {} + void sourceObjectDestroyLink() {} +}; + +//===================================================== + +class LootValidatorRefManager : public RefManager +{ + public: + typedef LinkedListHead::Iterator< LootValidatorRef > iterator; + + LootValidatorRef* getFirst() { return (LootValidatorRef*)RefManager::getFirst(); } + LootValidatorRef* getLast() { return (LootValidatorRef*)RefManager::getLast(); } + + iterator begin() { return iterator(getFirst()); } + iterator end() { return iterator(NULL); } + iterator rbegin() { return iterator(getLast()); } + iterator rend() { return iterator(NULL); } +}; + +//===================================================== + +struct Loot +{ + QuestItemMap const& GetPlayerQuestItems() const { return PlayerQuestItems; } + QuestItemMap const& GetPlayerFFAItems() const { return PlayerFFAItems; } + QuestItemMap const& GetPlayerNonQuestNonFFAConditionalItems() const { return PlayerNonQuestNonFFAConditionalItems; } + + QuestItemList* FillFFALoot(Player* player); + QuestItemList* FillQuestLoot(Player* player); + QuestItemList* FillNonQuestNonFFAConditionalLoot(Player* player); + + std::vector items; + std::vector quest_items; + uint32 gold; + uint8 unlootedCount; + + Loot(uint32 _gold = 0) : gold(_gold), unlootedCount(0) {} + ~Loot() { clear(); } + + // if loot becomes invalid this reference is used to inform the listener + void addLootValidatorRef(LootValidatorRef* pLootValidatorRef) + { + i_LootValidatorRefManager.insertFirst(pLootValidatorRef); + } + + // void clear(); + void clear() + { + items.clear(); gold = 0; PlayersLooting.clear(); + for (QuestItemMap::iterator itr = PlayerQuestItems.begin(); itr != PlayerQuestItems.end(); ++itr) + delete itr->second; + for (QuestItemMap::iterator itr = PlayerFFAItems.begin(); itr != PlayerFFAItems.end(); ++itr) + delete itr->second; + for (QuestItemMap::iterator itr = PlayerNonQuestNonFFAConditionalItems.begin(); itr != PlayerNonQuestNonFFAConditionalItems.end(); ++itr) + delete itr->second; + + PlayerQuestItems.clear(); + PlayerFFAItems.clear(); + PlayerNonQuestNonFFAConditionalItems.clear(); + + items.clear(); + quest_items.clear(); + gold = 0; + unlootedCount = 0; + i_LootValidatorRefManager.clearReferences(); + } + + bool empty() const { return items.empty() && gold == 0; } + bool isLooted() const { return gold == 0 && unlootedCount == 0; } + + void NotifyItemRemoved(uint8 lootIndex); + void NotifyQuestItemRemoved(uint8 questIndex); + void NotifyMoneyRemoved(); + void AddLooter(uint64 GUID) { PlayersLooting.insert(GUID); } + void RemoveLooter(uint64 GUID) { PlayersLooting.erase(GUID); } + + void generateMoneyLoot(uint32 minAmount, uint32 maxAmount); + void FillLoot(uint32 loot_id, LootStore const& store, Player* loot_owner); + + // Inserts the item into the loot (called by LootTemplate processors) + void AddItem(LootStoreItem const & item); + + LootItem* LootItemInSlot(uint32 lootslot, Player* player, QuestItem** qitem = NULL, QuestItem** ffaitem = NULL, QuestItem** conditem = NULL); + private: + std::set PlayersLooting; + QuestItemMap PlayerQuestItems; + QuestItemMap PlayerFFAItems; + QuestItemMap PlayerNonQuestNonFFAConditionalItems; + + // All rolls are registered here. They need to know, when the loot is not valid anymore + LootValidatorRefManager i_LootValidatorRefManager; + +}; + +struct LootView +{ + Loot &loot; + QuestItemList *qlist; + QuestItemList *ffalist; + QuestItemList *conditionallist; + Player *viewer; + PermissionTypes permission; + LootView(Loot &_loot, QuestItemList *_qlist, QuestItemList *_ffalist, QuestItemList *_conditionallist, Player *_viewer,PermissionTypes _permission = ALL_PERMISSION) + : loot(_loot), qlist(_qlist), ffalist(_ffalist), conditionallist(_conditionallist), viewer(_viewer), permission(_permission) {} +}; + +extern LootStore LootTemplates_Creature; +extern LootStore LootTemplates_Fishing; +extern LootStore LootTemplates_Gameobject; +extern LootStore LootTemplates_Item; +extern LootStore LootTemplates_Pickpocketing; +extern LootStore LootTemplates_Skinning; +extern LootStore LootTemplates_Disenchant; +extern LootStore LootTemplates_Prospecting; +extern LootStore LootTemplates_QuestMail; + +void LoadLootTemplates_Creature(); +void LoadLootTemplates_Fishing(); +void LoadLootTemplates_Gameobject(); +void LoadLootTemplates_Item(); +void LoadLootTemplates_Pickpocketing(); +void LoadLootTemplates_Skinning(); +void LoadLootTemplates_Disenchant(); +void LoadLootTemplates_Prospecting(); +void LoadLootTemplates_QuestMail(); +void LoadLootTemplates_Reference(); + +inline void LoadLootTables() +{ + LoadLootTemplates_Creature(); + LoadLootTemplates_Fishing(); + LoadLootTemplates_Gameobject(); + LoadLootTemplates_Item(); + LoadLootTemplates_Pickpocketing(); + LoadLootTemplates_Skinning(); + LoadLootTemplates_Disenchant(); + LoadLootTemplates_Prospecting(); + LoadLootTemplates_QuestMail(); + LoadLootTemplates_Reference(); +} + +ByteBuffer& operator<<(ByteBuffer& b, LootItem const& li); +ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv); +#endif diff --git a/src/game/Mail.cpp b/src/game/Mail.cpp new file mode 100644 index 00000000000..a97ed9470a7 --- /dev/null +++ b/src/game/Mail.cpp @@ -0,0 +1,838 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Mail.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Opcodes.h" +#include "Log.h" +#include "World.h" +#include "ObjectMgr.h" +#include "Player.h" +#include "UpdateMask.h" +#include "Unit.h" +#include "Language.h" +#include "Database/DBCStores.h" + +void MailItem::deleteItem( bool inDB ) +{ + if(item) + { + if(inDB) + CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid='%u'", item->GetGUIDLow()); + + delete item; + item=NULL; + } +} + +void WorldSession::HandleSendMail(WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+1+1+1+4+4+1+4+4+8+1); + + uint64 mailbox, unk3; + std::string receiver, subject, body; + uint32 unk1, unk2, money, COD; + uint8 unk4; + recv_data >> mailbox; + recv_data >> receiver; + + // recheck + CHECK_PACKET_SIZE(recv_data, 8+(receiver.size()+1)+1+1+4+4+1+4+4+8+1); + + recv_data >> subject; + + // recheck + CHECK_PACKET_SIZE(recv_data, 8+(receiver.size()+1)+(subject.size()+1)+1+4+4+1+4+4+8+1); + + recv_data >> body; + + // recheck + CHECK_PACKET_SIZE(recv_data, 8+(receiver.size()+1)+(subject.size()+1)+(body.size()+1)+4+4+1+4+4+8+1); + + recv_data >> unk1; // stationery? + recv_data >> unk2; // 0x00000000 + + MailItemsInfo mi; + + uint8 items_count; + recv_data >> items_count; // attached items count + + if(items_count > 12) // client limit + return; + + // recheck + CHECK_PACKET_SIZE(recv_data, 8+(receiver.size()+1)+(subject.size()+1)+(body.size()+1)+4+4+1+items_count*(1+8)+4+4+8+1); + + if(items_count) + { + for(uint8 i = 0; i < items_count; ++i) + { + uint8 item_slot; + uint64 item_guid; + recv_data >> item_slot; + recv_data >> item_guid; + mi.AddItem(GUID_LOPART(item_guid), item_slot); + } + } + + recv_data >> money >> COD; // money and cod + recv_data >> unk3; // const 0 + recv_data >> unk4; // const 0 + + items_count = mi.size(); // this is the real size after the duplicates have been removed + + if (receiver.empty()) + return; + + Player* pl = _player; + + uint64 rc = 0; + if(normalizePlayerName(receiver)) + rc = objmgr.GetPlayerGUIDByName(receiver); + + if (!rc) + { + sLog.outDetail("Player %u is sending mail to %s (GUID: not existed!) with subject %s and body %s includes %u items, %u copper and %u COD copper with unk1 = %u, unk2 = %u", + pl->GetGUIDLow(), receiver.c_str(), subject.c_str(), body.c_str(), items_count, money, COD, unk1, unk2); + pl->SendMailResult(0, 0, MAIL_ERR_RECIPIENT_NOT_FOUND); + return; + } + + sLog.outDetail("Player %u is sending mail to %s (GUID: %u) with subject %s and body %s includes %u items, %u copper and %u COD copper with unk1 = %u, unk2 = %u", pl->GetGUIDLow(), receiver.c_str(), GUID_LOPART(rc), subject.c_str(), body.c_str(), items_count, money, COD, unk1, unk2); + + if(pl->GetGUID() == rc) + { + pl->SendMailResult(0, 0, MAIL_ERR_CANNOT_SEND_TO_SELF); + return; + } + + uint32 reqmoney = money + 30; + if (items_count) + reqmoney = money + (30 * items_count); + + if (pl->GetMoney() < reqmoney) + { + pl->SendMailResult(0, 0, MAIL_ERR_NOT_ENOUGH_MONEY); + return; + } + + Player *receive = objmgr.GetPlayer(rc); + + uint32 rc_team = 0; + uint8 mails_count = 0; //do not allow to send to one player more than 100 mails + + if(receive) + { + rc_team = receive->GetTeam(); + mails_count = receive->GetMailSize(); + } + else + { + rc_team = objmgr.GetPlayerTeamByGUID(rc); + QueryResult* result = CharacterDatabase.PQuery("SELECT COUNT(*) FROM mail WHERE receiver = '%u'", GUID_LOPART(rc)); + if(result) + { + Field *fields = result->Fetch(); + mails_count = fields[0].GetUInt32(); + delete result; + } + } + //do not allow to have more than 100 mails in mailbox.. mails count is in opcode uint8!!! - so max can be 255.. + if (mails_count > 100) + { + pl->SendMailResult(0, 0, MAIL_ERR_INTERNAL_ERROR); + return; + } + // test the receiver's Faction... + if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL) && pl->GetTeam() != rc_team && GetSecurity() == SEC_PLAYER) + { + pl->SendMailResult(0, 0, MAIL_ERR_NOT_YOUR_TEAM); + return; + } + + if (items_count) + { + for(MailItemMap::iterator mailItemIter = mi.begin(); mailItemIter != mi.end(); ++mailItemIter) + { + MailItem& mailItem = mailItemIter->second; + + if(!mailItem.item_guidlow) + { + pl->SendMailResult(0, 0, MAIL_ERR_INTERNAL_ERROR); + return; + } + + mailItem.item = pl->GetItemByGuid(MAKE_NEW_GUID(mailItem.item_guidlow, 0, HIGHGUID_ITEM)); + // prevent sending bag with items (cheat: can be placed in bag after adding equipped empty bag to mail) + if(!mailItem.item || !mailItem.item->CanBeTraded()) + { + pl->SendMailResult(0, 0, MAIL_ERR_INTERNAL_ERROR); + return; + } + if (mailItem.item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_CONJURED) || mailItem.item->GetUInt32Value(ITEM_FIELD_DURATION)) + { + pl->SendMailResult(0, 0, MAIL_ERR_INTERNAL_ERROR); + return; + } + } + } + pl->SendMailResult(0, 0, MAIL_OK); + + uint32 itemTextId = 0; + if (!body.empty()) + { + itemTextId = objmgr.CreateItemText( body ); + } + + pl->ModifyMoney( -int32(reqmoney) ); + + bool needItemDelay = false; + + if(items_count > 0 || money > 0) + { + uint32 rc_account = 0; + if(receive) + rc_account = receive->GetSession()->GetAccountId(); + else + rc_account = objmgr.GetPlayerAccountIdByGUID(rc); + + if (items_count > 0) + { + for(MailItemMap::iterator mailItemIter = mi.begin(); mailItemIter != mi.end(); ++mailItemIter) + { + MailItem& mailItem = mailItemIter->second; + if(!mailItem.item) + continue; + + mailItem.item_template = mailItem.item ? mailItem.item->GetEntry() : 0; + + if( GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) ) + { + sLog.outCommand("GM %s (Account: %u) mail item: %s (Entry: %u Count: %u) to player: %s (Account: %u)", + GetPlayerName(), GetAccountId(), mailItem.item->GetProto()->Name1, mailItem.item->GetEntry(), mailItem.item->GetCount(), receiver.c_str(), rc_account); + } + + pl->MoveItemFromInventory(mailItem.item->GetBagSlot(), mailItem.item->GetSlot(), true); + CharacterDatabase.BeginTransaction(); + mailItem.item->DeleteFromInventoryDB(); //deletes item from character's inventory + mailItem.item->SaveToDB(); // recursive and not have transaction guard into self, item not in inventory and can be save standalone + // owner in data will set at mail receive and item extracting + CharacterDatabase.PExecute("UPDATE item_instance SET owner_guid = '%u' WHERE guid='%u'", GUID_LOPART(rc), mailItem.item->GetGUIDLow()); + CharacterDatabase.CommitTransaction(); + } + + // if item send to character at another account, then apply item delivery delay + needItemDelay = pl->GetSession()->GetAccountId() != rc_account; + } + + if(money > 0 && GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE)) + { + sLog.outCommand("GM %s (Account: %u) mail money: %u to player: %s (Account: %u)", + GetPlayerName(), GetAccountId(), money, receiver.c_str(), rc_account); + } + } + + // If theres is an item, there is a one hour delivery delay if sent to another account's character. + uint32 deliver_delay = needItemDelay ? sWorld.getConfig(CONFIG_MAIL_DELIVERY_DELAY) : 0; + + // will delete item or place to receiver mail list + WorldSession::SendMailTo(receive, MAIL_NORMAL, MAIL_STATIONERY_NORMAL, pl->GetGUIDLow(), GUID_LOPART(rc), subject, itemTextId, &mi, money, COD, MAIL_CHECK_MASK_NONE, deliver_delay); + + CharacterDatabase.BeginTransaction(); + pl->SaveInventoryAndGoldToDB(); + CharacterDatabase.CommitTransaction(); +} + +//called when mail is read +void WorldSession::HandleMarkAsRead(WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+4); + + uint64 mailbox; + uint32 mailId; + recv_data >> mailbox; + recv_data >> mailId; + Player *pl = _player; + Mail *m = pl->GetMail(mailId); + if (m) + { + if (pl->unReadMails) + --pl->unReadMails; + m->checked = m->checked | MAIL_CHECK_MASK_READ; + // m->expire_time = time(NULL) + (30 * DAY); // Expire time do not change at reading mail + pl->m_mailsUpdated = true; + m->state = MAIL_STATE_CHANGED; + } +} + +//called when client deletes mail +void WorldSession::HandleMailDelete(WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+4); + + uint64 mailbox; + uint32 mailId; + recv_data >> mailbox; + recv_data >> mailId; + Player* pl = _player; + pl->m_mailsUpdated = true; + Mail *m = pl->GetMail(mailId); + if(m) + m->state = MAIL_STATE_DELETED; + pl->SendMailResult(mailId, MAIL_DELETED, 0); +} + +void WorldSession::HandleReturnToSender(WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+4); + + uint64 mailbox; + uint32 mailId; + recv_data >> mailbox; + recv_data >> mailId; + Player *pl = _player; + Mail *m = pl->GetMail(mailId); + if(!m || m->state == MAIL_STATE_DELETED || m->deliver_time > time(NULL)) + { + pl->SendMailResult(mailId, MAIL_RETURNED_TO_SENDER, MAIL_ERR_INTERNAL_ERROR); + return; + } + //we can return mail now + //so firstly delete the old one + CharacterDatabase.BeginTransaction(); + CharacterDatabase.PExecute("DELETE FROM mail WHERE id = '%u'", mailId); + // needed? + CharacterDatabase.PExecute("DELETE FROM mail_items WHERE mail_id = '%u'", mailId); + CharacterDatabase.CommitTransaction(); + pl->RemoveMail(mailId); + + MailItemsInfo mi; + + if(m->HasItems()) + { + for(std::vector::iterator itr2 = m->items.begin(); itr2 != m->items.end(); ++itr2) + { + Item *item = pl->GetMItem(itr2->item_guid); + if(item) + mi.AddItem(item->GetGUIDLow(), item->GetEntry(), item); + else + { + //WTF? + } + + pl->RemoveMItem(itr2->item_guid); + } + } + + SendReturnToSender(MAIL_NORMAL, GetAccountId(), m->receiver, m->sender, m->subject, m->itemTextId, &mi, m->money, 0, m->mailTemplateId); + + delete m; //we can deallocate old mail + pl->SendMailResult(mailId, MAIL_RETURNED_TO_SENDER, 0); +} + +void WorldSession::SendReturnToSender(uint8 messageType, uint32 sender_acc, uint32 sender_guid, uint32 receiver_guid, std::string subject, uint32 itemTextId, MailItemsInfo *mi, uint32 money, uint32 COD, uint16 mailTemplateId ) +{ + if(messageType != MAIL_NORMAL) // return only to players + { + mi->deleteIncludedItems(true); + return; + } + + Player *receiver = objmgr.GetPlayer(MAKE_NEW_GUID(receiver_guid, 0, HIGHGUID_PLAYER)); + + uint32 rc_account = 0; + if(!receiver) + rc_account = objmgr.GetPlayerAccountIdByGUID(MAKE_NEW_GUID(receiver_guid, 0, HIGHGUID_PLAYER)); + + if(!receiver && !rc_account) // sender not exist + { + mi->deleteIncludedItems(true); + return; + } + + // preper mail and send in other case + bool needItemDelay = false; + + if(mi && !mi->empty()) + { + // if item send to character at another account, then apply item delivery delay + needItemDelay = sender_acc != rc_account; + + // set owner to new receiver (to prevent delete item with sender char deleting) + CharacterDatabase.BeginTransaction(); + for(MailItemMap::iterator mailItemIter = mi->begin(); mailItemIter != mi->end(); ++mailItemIter) + { + MailItem& mailItem = mailItemIter->second; + mailItem.item->SaveToDB(); // item not in inventory and can be save standalone + // owner in data will set at mail receive and item extracting + CharacterDatabase.PExecute("UPDATE item_instance SET owner_guid = '%u' WHERE guid='%u'", receiver_guid, mailItem.item->GetGUIDLow()); + } + CharacterDatabase.CommitTransaction(); + } + + // If theres is an item, there is a one hour delivery delay. + uint32 deliver_delay = needItemDelay ? sWorld.getConfig(CONFIG_MAIL_DELIVERY_DELAY) : 0; + + // will delete item or place to receiver mail list + WorldSession::SendMailTo(receiver, MAIL_NORMAL, MAIL_STATIONERY_NORMAL, sender_guid, receiver_guid, subject, itemTextId, mi, money, 0, MAIL_CHECK_MASK_RETURNED,deliver_delay,mailTemplateId); +} + +//called when player takes item attached in mail +void WorldSession::HandleTakeItem(WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+4+4); + + uint64 mailbox; + uint32 mailId; + uint32 itemId; + recv_data >> mailbox; + recv_data >> mailId; + recv_data >> itemId; // item guid low? + Player* pl = _player; + + Mail* m = pl->GetMail(mailId); + if(!m || m->state == MAIL_STATE_DELETED || m->deliver_time > time(NULL)) + { + pl->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_ERR_INTERNAL_ERROR); + return; + } + + // prevent cheating with skip client money check + if(pl->GetMoney() < m->COD) + { + pl->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_ERR_NOT_ENOUGH_MONEY); + return; + } + + Item *it = pl->GetMItem(itemId); + + ItemPosCountVec dest; + uint8 msg = _player->CanStoreItem( NULL_BAG, NULL_SLOT, dest, it, false ); + if( msg == EQUIP_ERR_OK ) + { + m->RemoveItem(itemId); + m->removedItems.push_back(itemId); + + if (m->COD > 0) //if there is COD, take COD money from player and send them to sender by mail + { + uint64 sender_guid = MAKE_NEW_GUID(m->sender, 0, HIGHGUID_PLAYER); + Player *receive = objmgr.GetPlayer(sender_guid); + + uint32 sender_accId = 0; + + if( GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) ) + { + std::string sender_name; + if(receive) + { + sender_accId = receive->GetSession()->GetAccountId(); + sender_name = receive->GetName(); + } + else + { + // can be calculated early + sender_accId = objmgr.GetPlayerAccountIdByGUID(sender_guid); + + if(!objmgr.GetPlayerNameByGUID(sender_guid,sender_name)) + sender_name = objmgr.GetMangosStringForDBCLocale(LANG_UNKNOWN); + } + sLog.outCommand("GM %s (Account: %u) receive mail item: %s (Entry: %u Count: %u) and send COD money: %u to player: %s (Account: %u)", + GetPlayerName(),GetAccountId(),it->GetProto()->Name1,it->GetEntry(),it->GetCount(),m->COD,sender_name.c_str(),sender_accId); + } + else if(!receive) + sender_accId = objmgr.GetPlayerAccountIdByGUID(sender_guid); + + // check player existanse + if(receive || sender_accId) + { + WorldSession::SendMailTo(receive, MAIL_NORMAL, MAIL_STATIONERY_NORMAL, m->receiver, m->sender, m->subject, 0, NULL, m->COD, 0, MAIL_CHECK_MASK_COD_PAYMENT); + } + + pl->ModifyMoney( -int32(m->COD) ); + } + m->COD = 0; + m->state = MAIL_STATE_CHANGED; + pl->m_mailsUpdated = true; + pl->RemoveMItem(it->GetGUIDLow()); + + uint32 count = it->GetCount(); // save counts before store and possible merge with deleting + pl->MoveItemToInventory(dest,it,true); + + CharacterDatabase.BeginTransaction(); + pl->SaveInventoryAndGoldToDB(); + pl->_SaveMail(); + CharacterDatabase.CommitTransaction(); + + pl->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_OK, 0, itemId, count); + } + else + pl->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_ERR_BAG_FULL, msg); +} + +void WorldSession::HandleTakeMoney(WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+4); + + uint64 mailbox; + uint32 mailId; + recv_data >> mailbox; + recv_data >> mailId; + Player *pl = _player; + + Mail* m = pl->GetMail(mailId); + if(!m || m->state == MAIL_STATE_DELETED || m->deliver_time > time(NULL)) + { + pl->SendMailResult(mailId, MAIL_MONEY_TAKEN, MAIL_ERR_INTERNAL_ERROR); + return; + } + + pl->SendMailResult(mailId, MAIL_MONEY_TAKEN, 0); + + pl->ModifyMoney(m->money); + m->money = 0; + m->state = MAIL_STATE_CHANGED; + pl->m_mailsUpdated = true; + + // save money and mail to prevent cheating + CharacterDatabase.BeginTransaction(); + pl->SetUInt32ValueInDB(PLAYER_FIELD_COINAGE,pl->GetMoney(),pl->GetGUID()); + pl->_SaveMail(); + CharacterDatabase.CommitTransaction(); +} + +//called when player lists his received mails +void WorldSession::HandleGetMail(WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8); + + uint64 mailbox; + recv_data >> mailbox; + + //GameObject* obj = ObjectAccessor::GetGameObject(_player, mailbox); + //if(!obj || !obj->IsMailBox()) + // return; + + Player* pl = _player; + + //load players mails, and mailed items + if(!pl->m_mailsLoaded) + pl ->_LoadMail(); + + // client can't work with packets > max int16 value + const uint32 maxPacketSize = 32767; + + uint32 mails_count = 0; // real send to client mails amount + + WorldPacket data(SMSG_MAIL_LIST_RESULT, (200)); // guess size + data << uint8(0); // mail's count + time_t cur_time = time(NULL); + + for(PlayerMails::iterator itr = pl->GetmailBegin(); itr != pl->GetmailEnd(); ++itr) + { + // skip deleted or not delivered (deliver delay not expired) mails + if ((*itr)->state == MAIL_STATE_DELETED || cur_time < (*itr)->deliver_time) + continue; + + uint8 item_count = (*itr)->items.size(); // max count is MAX_MAIL_ITEMS (12) + + size_t next_mail_size = 2+4+1+8+4*8+((*itr)->subject.size()+1)+1+item_count*(1+4+4+6*3*4+4+4+1+4+4+4); + + if(data.wpos()+next_mail_size > maxPacketSize) + break; + + data << (uint16) 0x0040; // unknown 2.3.0, different values + data << (uint32) (*itr)->messageID; // Message ID + data << (uint8) (*itr)->messageType; // Message Type + + switch((*itr)->messageType) + { + case MAIL_NORMAL: // sender guid + data << uint64(MAKE_NEW_GUID((*itr)->sender, 0, HIGHGUID_PLAYER)); + break; + case MAIL_CREATURE: + case MAIL_GAMEOBJECT: + case MAIL_AUCTION: + data << (uint32) (*itr)->sender; // creature/gameobject entry, auction id + break; + case MAIL_ITEM: // item entry (?) sender = "Unknown", NYI + break; + } + + data << (uint32) (*itr)->COD; // COD + data << (uint32) (*itr)->itemTextId; // sure about this + data << (uint32) 0; // unknown + data << (uint32) (*itr)->stationery; // stationery (Stationery.dbc) + data << (uint32) (*itr)->money; // Gold + data << (uint32) 0x04; // unknown, 0x4 - auction, 0x10 - normal + // Time + data << (float) ((*itr)->expire_time-time(NULL))/DAY; + data << (uint32) (*itr)->mailTemplateId; // mail template (MailTemplate.dbc) + data << (*itr)->subject; // Subject string - once 00, when mail type = 3 + + data << (uint8) item_count; + + for(uint8 i = 0; i < item_count; ++i) + { + Item *item = pl->GetMItem((*itr)->items[i].item_guid); + // item index (0-6?) + data << (uint8) i; + // item guid low? + data << (uint32) (item ? item->GetGUIDLow() : 0); + // entry + data << (uint32) (item ? item->GetEntry() : 0); + for(uint8 j = 0; j < 6; ++j) + { + // unsure + data << (uint32) (item ? item->GetEnchantmentCharges((EnchantmentSlot)j) : 0); + // unsure + data << (uint32) (item ? item->GetEnchantmentDuration((EnchantmentSlot)j) : 0); + // unsure + data << (uint32) (item ? item->GetEnchantmentId((EnchantmentSlot)j) : 0); + } + // can be negative + data << (uint32) (item ? item->GetItemRandomPropertyId() : 0); + // unk + data << (uint32) (item ? item->GetItemSuffixFactor() : 0); + // stack count + data << (uint8) (item ? item->GetCount() : 0); + // charges + data << (uint32) (item ? item->GetSpellCharges() : 0); + // durability + data << (uint32) (item ? item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY) : 0); + // durability + data << (uint32) (item ? item->GetUInt32Value(ITEM_FIELD_DURABILITY) : 0); + } + + mails_count += 1; + } + + data.put(0, mails_count); // set real send mails to client + SendPacket(&data); + + // recalculate m_nextMailDelivereTime and unReadMails + _player->UpdateNextMailTimeAndUnreads(); +} + +///this function is called when client needs mail message body, or when player clicks on item which has ITEM_FIELD_ITEM_TEXT_ID > 0 +void WorldSession::HandleItemTextQuery(WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,4+4+4); + + uint32 itemTextId; + uint32 mailId; //this value can be item id in bag, but it is also mail id + uint32 unk; //maybe something like state - 0x70000000 + + recv_data >> itemTextId >> mailId >> unk; + + //some check needed, if player has item with guid mailId, or has mail with id mailId + + sLog.outDebug("CMSG_ITEM_TEXT_QUERY itemguid: %u, mailId: %u, unk: %u", itemTextId, mailId, unk); + + WorldPacket data(SMSG_ITEM_TEXT_QUERY_RESPONSE, (4+10));// guess size + data << itemTextId; + data << objmgr.GetItemText( itemTextId ); + SendPacket(&data); +} + +//used when player copies mail body to his inventory +void WorldSession::HandleMailCreateTextItem(WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+4); + + uint64 mailbox; + uint32 mailId; + + recv_data >> mailbox >> mailId; + + Player *pl = _player; + + Mail* m = pl->GetMail(mailId); + if(!m || !m->itemTextId || m->state == MAIL_STATE_DELETED || m->deliver_time > time(NULL)) + { + pl->SendMailResult(mailId, MAIL_MADE_PERMANENT, MAIL_ERR_INTERNAL_ERROR); + return; + } + + Item *bodyItem = new Item; // This is not bag and then can be used new Item. + if(!bodyItem->Create(objmgr.GenerateLowGuid(HIGHGUID_ITEM), MAIL_BODY_ITEM_TEMPLATE, pl)) + { + delete bodyItem; + return; + } + + bodyItem->SetUInt32Value( ITEM_FIELD_ITEM_TEXT_ID , m->itemTextId ); + bodyItem->SetUInt32Value( ITEM_FIELD_CREATOR, m->sender); + + sLog.outDetail("HandleMailCreateTextItem mailid=%u",mailId); + + ItemPosCountVec dest; + uint8 msg = _player->CanStoreItem( NULL_BAG, NULL_SLOT, dest, bodyItem, false ); + if( msg == EQUIP_ERR_OK ) + { + m->itemTextId = 0; + m->state = MAIL_STATE_CHANGED; + pl->m_mailsUpdated = true; + + pl->StoreItem(dest, bodyItem, true); + //bodyItem->SetState(ITEM_NEW, pl); is set automatically + pl->SendMailResult(mailId, MAIL_MADE_PERMANENT, 0); + } + else + { + pl->SendMailResult(mailId, MAIL_MADE_PERMANENT, MAIL_ERR_BAG_FULL, msg); + delete bodyItem; + } +} + +//TODO Fix me! ... this void has probably bad condition, but good data are sent +void WorldSession::HandleMsgQueryNextMailtime(WorldPacket & /*recv_data*/ ) +{ + WorldPacket data(MSG_QUERY_NEXT_MAIL_TIME, 8); + + if(!_player->m_mailsLoaded) + _player->_LoadMail(); + + if( _player->unReadMails > 0 ) + { + data << (uint32) 0; // float + data << (uint32) 0; // count + uint32 count = 0; + for(PlayerMails::iterator itr = _player->GetmailBegin(); itr != _player->GetmailEnd(); ++itr) + { + Mail *m = (*itr); + // not checked yet, already must be delivered + if((m->checked & MAIL_CHECK_MASK_READ)==0 && (m->deliver_time <= time(NULL))) + { + ++count; + + if(count > 2) + { + count = 2; + break; + } + + data << (uint64) m->sender; // sender guid + + switch(m->messageType) + { + case MAIL_AUCTION: + data << (uint32) 2; + data << (uint32) 2; + data << (uint32) m->stationery; + break; + default: + data << (uint32) 0; + data << (uint32) 0; + data << (uint32) m->stationery; + break; + } + data << (uint32) 0xC6000000; // float unk, time or something + } + } + data.put(4, count); + } + else + { + data << (uint32) 0xC7A8C000; + data << (uint32) 0x00000000; + } + SendPacket(&data); +} + +void WorldSession::SendMailTo(Player* receiver, uint8 messageType, uint8 stationery, uint32 sender_guidlow_or_entry, uint32 receiver_guidlow, std::string subject, uint32 itemTextId, MailItemsInfo* mi, uint32 money, uint32 COD, uint32 checked, uint32 deliver_delay, uint16 mailTemplateId) +{ + uint32 mailId = objmgr.GenerateMailID(); + + time_t deliver_time = time(NULL) + deliver_delay; + + //expire time if COD 3 days, if no COD 30 days, if auction sale pending 1 hour + uint32 expire_delay; + if(messageType == MAIL_AUCTION && !mi && !money) // auction mail without any items and money + expire_delay = HOUR; + else + expire_delay = (COD > 0) ? 3*DAY : 30*DAY; + + time_t expire_time = deliver_time + expire_delay; + + if(mailTemplateId && !sMailTemplateStore.LookupEntry(mailTemplateId)) + { + sLog.outError( "WorldSession::SendMailTo - Mail have not existed MailTemplateId (%u), remove at send", mailTemplateId); + mailTemplateId = 0; + } + + if(receiver) + { + receiver->AddNewMailDeliverTime(deliver_time); + + if ( receiver->IsMailsLoaded() ) + { + Mail * m = new Mail; + m->messageID = mailId; + m->messageType = messageType; + m->stationery = stationery; + m->mailTemplateId = mailTemplateId; + m->sender = sender_guidlow_or_entry; + m->receiver = receiver->GetGUIDLow(); + m->subject = subject; + m->itemTextId = itemTextId; + + if(mi) + m->AddAllItems(*mi); + + m->expire_time = expire_time; + m->deliver_time = deliver_time; + m->money = money; + m->COD = COD; + m->checked = checked; + m->state = MAIL_STATE_UNCHANGED; + + receiver->AddMail(m); //to insert new mail to beginning of maillist + + if(mi) + { + for(MailItemMap::iterator mailItemIter = mi->begin(); mailItemIter != mi->end(); ++mailItemIter) + { + MailItem& mailItem = mailItemIter->second; + if(mailItem.item) + receiver->AddMItem(mailItem.item); + } + } + } + else if(mi) + mi->deleteIncludedItems(); + } + else if(mi) + mi->deleteIncludedItems(); + + CharacterDatabase.BeginTransaction(); + CharacterDatabase.escape_string(subject); + CharacterDatabase.PExecute("INSERT INTO mail (id,messageType,stationery,mailTemplateId,sender,receiver,subject,itemTextId,has_items,expire_time,deliver_time,money,cod,checked) " + "VALUES ('%u', '%u', '%u', '%u', '%u', '%u', '%s', '%u', '%u', '" I64FMTD "','" I64FMTD "', '%u', '%u', '%d')", + mailId, messageType, stationery, mailTemplateId, sender_guidlow_or_entry, receiver_guidlow, subject.c_str(), itemTextId, (mi && !mi->empty() ? 1 : 0), (uint64)expire_time, (uint64)deliver_time, money, COD, checked); + + if(mi) + { + for(MailItemMap::const_iterator mailItemIter = mi->begin(); mailItemIter != mi->end(); ++mailItemIter) + { + MailItem const& mailItem = mailItemIter->second; + CharacterDatabase.PExecute("INSERT INTO mail_items (mail_id,item_guid,item_template,receiver) VALUES ('%u', '%u', '%u','%u')", mailId, mailItem.item_guidlow, mailItem.item_template,receiver_guidlow); + } + } + CharacterDatabase.CommitTransaction(); +} diff --git a/src/game/Mail.h b/src/game/Mail.h new file mode 100644 index 00000000000..bec54eb41f7 --- /dev/null +++ b/src/game/Mail.h @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef MANGOS_MAIL_H +#define MANGOS_MAIL_H + +#include "Common.h" +#include + +class Item; + +#define MAIL_BODY_ITEM_TEMPLATE 8383 // - plain letter, A Dusty Unsent Letter: 889 +#define MAX_MAIL_ITEMS 12 + +enum MAIL_RESPONSE +{ + MAIL_OK = 0, + MAIL_MONEY_TAKEN = 1, + MAIL_ITEM_TAKEN = 2, + MAIL_RETURNED_TO_SENDER = 3, + MAIL_DELETED = 4, + MAIL_MADE_PERMANENT = 5 +}; + +enum MAIL_ERRORS +{ + MAIL_ERR_BAG_FULL = 1, + MAIL_ERR_CANNOT_SEND_TO_SELF = 2, + MAIL_ERR_NOT_ENOUGH_MONEY = 3, + MAIL_ERR_RECIPIENT_NOT_FOUND = 4, + MAIL_ERR_NOT_YOUR_TEAM = 5, + MAIL_ERR_INTERNAL_ERROR = 6, + MAIL_ERR_DISABLED_FOR_TRIAL_ACC = 14, + MAIL_ERR_RECIPIENT_CAP_REACHED = 15, + MAIL_ERR_CANT_SEND_WRAPPED_COD = 16, + MAIL_ERR_MAIL_AND_CHAT_SUSPENDED = 17 +}; + +enum MailCheckMask +{ + MAIL_CHECK_MASK_NONE = 0, + MAIL_CHECK_MASK_READ = 1, + MAIL_CHECK_MASK_AUCTION = 4, + MAIL_CHECK_MASK_COD_PAYMENT = 8, + MAIL_CHECK_MASK_RETURNED = 16 +}; + +enum MailMessageType +{ + MAIL_NORMAL = 0, + MAIL_AUCTION = 2, + MAIL_CREATURE = 3, // client send CMSG_CREATURE_QUERY on this mailmessagetype + MAIL_GAMEOBJECT = 4, // client send CMSG_GAMEOBJECT_QUERY on this mailmessagetype + MAIL_ITEM = 5, // client send CMSG_ITEM_QUERY on this mailmessagetype +}; + +enum MailState +{ + MAIL_STATE_UNCHANGED = 1, + MAIL_STATE_CHANGED = 2, + MAIL_STATE_DELETED = 3 +}; + +enum MailAuctionAnswers +{ + AUCTION_OUTBIDDED = 0, + AUCTION_WON = 1, + AUCTION_SUCCESSFUL = 2, + AUCTION_EXPIRED = 3, + AUCTION_CANCELLED_TO_BIDDER = 4, + AUCTION_CANCELED = 5, + AUCTION_SALE_PENDING = 6 +}; + +// gathered from Stationery.dbc +enum MailStationery +{ + MAIL_STATIONERY_UNKNOWN = 0x01, + MAIL_STATIONERY_NORMAL = 0x29, + MAIL_STATIONERY_GM = 0x3D, + MAIL_STATIONERY_AUCTION = 0x3E, + MAIL_STATIONERY_VAL = 0x40, + MAIL_STATIONERY_CHR = 0x41 +}; + +struct MailItemInfo +{ + uint32 item_guid; + uint32 item_template; +}; + +struct MailItem +{ + MailItem() : item_slot(0), item_guidlow(0), item_template(0), item(NULL) {} + + uint8 item_slot; // slot in mail + uint32 item_guidlow; // item guid (low part) + uint32 item_template; // item entry + Item *item; // item pointer + + void deleteItem(bool inDB = false); +}; + +typedef std::map MailItemMap; + +class MailItemsInfo +{ + public: + MailItemMap::const_iterator begin() const { return i_MailItemMap.begin(); } + MailItemMap::const_iterator end() const { return i_MailItemMap.end(); } + MailItemMap::iterator begin() { return i_MailItemMap.begin(); } + MailItemMap::iterator end() { return i_MailItemMap.end(); } + + void AddItem(uint32 guidlow, uint32 _template, Item *item, uint8 slot = 0) + { + MailItem mailItem; + mailItem.item_slot = slot; + mailItem.item_guidlow = guidlow; + mailItem.item_template = _template; + mailItem.item = item; + i_MailItemMap[guidlow] = mailItem; + } + + void AddItem(uint32 guidlow, uint8 slot = 0) + { + MailItem mailItem; + mailItem.item_guidlow = guidlow; + mailItem.item_slot = slot; + i_MailItemMap[guidlow] = mailItem; + } + + uint8 size() const { return i_MailItemMap.size(); } + bool empty() const { return i_MailItemMap.empty(); } + + void deleteIncludedItems(bool inDB = false) + { + for(MailItemMap::iterator mailItemIter = begin(); mailItemIter != end(); ++mailItemIter) + { + MailItem& mailItem = mailItemIter->second; + mailItem.deleteItem(inDB); + } + } + private: + MailItemMap i_MailItemMap; // Keep the items in a map to avoid duplicate guids (which can happen), store only low part of guid +}; + +struct Mail +{ + uint32 messageID; + uint8 messageType; + uint8 stationery; + uint16 mailTemplateId; + uint32 sender; + uint32 receiver; + std::string subject; + uint32 itemTextId; + std::vector items; + std::vector removedItems; + time_t expire_time; + time_t deliver_time; + uint32 money; + uint32 COD; + uint32 checked; + MailState state; + + void AddItem(uint32 itemGuidLow, uint32 item_template) + { + MailItemInfo mii; + mii.item_guid = itemGuidLow; + mii.item_template = item_template; + items.push_back(mii); + } + + void AddAllItems(MailItemsInfo& pMailItemsInfo) + { + for(MailItemMap::iterator mailItemIter = pMailItemsInfo.begin(); mailItemIter != pMailItemsInfo.end(); ++mailItemIter) + { + MailItem& mailItem = mailItemIter->second; + AddItem(mailItem.item_guidlow, mailItem.item_template); + } + } + + bool RemoveItem(uint32 itemId) + { + for(std::vector::iterator itr = items.begin(); itr != items.end(); ++itr) + { + if(itr->item_guid == itemId) + { + items.erase(itr); + return true; + } + } + return false; + } + + bool HasItems() const { return !items.empty(); } +}; +#endif diff --git a/src/game/Makefile.am b/src/game/Makefile.am new file mode 100644 index 00000000000..cffd1f7b093 --- /dev/null +++ b/src/game/Makefile.am @@ -0,0 +1,278 @@ +# Copyright (C) 2005-2008 MaNGOS +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## Process this file with automake to produce Makefile.in + +## Sub-directories to parse + +## CPP flags for includes, defines, etc. +AM_CPPFLAGS = + +## Build MaNGOS game library as convenience library. +# All libraries will be convenience libraries. Might be changed to shared +# later. +noinst_LIBRARIES = libgame.a + +libgame_a_CPPFLAGS = \ +$(MYSQL_INCLUDES) \ +$(POSTGRE_INCLUDES) \ +-I$(top_srcdir)/dep/include \ +-I$(top_srcdir)/src/framework \ +-I$(top_srcdir)/src/shared \ +-I$(top_srcdir)/src/shared/vmap + +# libmangossgame library will later be reused by ... +libgame_a_SOURCES = \ +$(srcdir)/AccountMgr.cpp \ +$(srcdir)/AccountMgr.h \ +$(srcdir)/AddonHandler.cpp \ +$(srcdir)/AddonHandler.h \ +$(srcdir)/AggressorAI.cpp \ +$(srcdir)/AggressorAI.h \ +$(srcdir)/AnimalRandomMovementGenerator.h \ +$(srcdir)/ArenaTeam.cpp \ +$(srcdir)/ArenaTeam.h \ +$(srcdir)/ArenaTeamHandler.cpp \ +$(srcdir)/AuctionHouse.cpp \ +$(srcdir)/AuctionHouseObject.h \ +$(srcdir)/Bag.cpp \ +$(srcdir)/Bag.h \ +$(srcdir)/BattleGround.cpp \ +$(srcdir)/BattleGroundAA.cpp \ +$(srcdir)/BattleGroundAB.cpp \ +$(srcdir)/BattleGroundAV.cpp \ +$(srcdir)/BattleGroundBE.cpp \ +$(srcdir)/BattleGroundEY.cpp \ +$(srcdir)/BattleGroundNA.cpp \ +$(srcdir)/BattleGroundRL.cpp \ +$(srcdir)/BattleGroundWS.cpp \ +$(srcdir)/BattleGround.h \ +$(srcdir)/BattleGroundAA.h \ +$(srcdir)/BattleGroundAB.h \ +$(srcdir)/BattleGroundAV.h \ +$(srcdir)/BattleGroundBE.h \ +$(srcdir)/BattleGroundEY.h \ +$(srcdir)/BattleGroundNA.h \ +$(srcdir)/BattleGroundRL.h \ +$(srcdir)/BattleGroundWS.h \ +$(srcdir)/BattleGroundHandler.cpp \ +$(srcdir)/BattleGroundMgr.cpp \ +$(srcdir)/BattleGroundMgr.h \ +$(srcdir)/Cell.h \ +$(srcdir)/CellImpl.h \ +$(srcdir)/Channel.cpp \ +$(srcdir)/Channel.h \ +$(srcdir)/ChannelHandler.cpp \ +$(srcdir)/ChannelMgr.h \ +$(srcdir)/CharacterHandler.cpp \ +$(srcdir)/Chat.cpp \ +$(srcdir)/Chat.h \ +$(srcdir)/ChatHandler.cpp \ +$(srcdir)/CombatHandler.cpp \ +$(srcdir)/ConfusedMovementGenerator.cpp \ +$(srcdir)/ConfusedMovementGenerator.h \ +$(srcdir)/Corpse.cpp \ +$(srcdir)/Corpse.h \ +$(srcdir)/CreatureAI.cpp \ +$(srcdir)/CreatureAI.h \ +$(srcdir)/CreatureAIImpl.h \ +$(srcdir)/CreatureAIRegistry.cpp \ +$(srcdir)/CreatureAIRegistry.h \ +$(srcdir)/CreatureAISelector.cpp \ +$(srcdir)/CreatureAISelector.h \ +$(srcdir)/Creature.cpp \ +$(srcdir)/Creature.h \ +$(srcdir)/debugcmds.cpp \ +$(srcdir)/DestinationHolder.cpp \ +$(srcdir)/DestinationHolder.h \ +$(srcdir)/DestinationHolderImp.h \ +$(srcdir)/DuelHandler.cpp \ +$(srcdir)/DynamicObject.cpp \ +$(srcdir)/DynamicObject.h \ +$(srcdir)/FleeingMovementGenerator.cpp \ +$(srcdir)/FleeingMovementGenerator.h \ +$(srcdir)/Formulas.h \ +$(srcdir)/GameEvent.cpp \ +$(srcdir)/GameEvent.h \ +$(srcdir)/GameObject.cpp \ +$(srcdir)/GameObject.h \ +$(srcdir)/GlobalEvents.cpp \ +$(srcdir)/GlobalEvents.h \ +$(srcdir)/GossipDef.cpp \ +$(srcdir)/GossipDef.h \ +$(srcdir)/GridDefines.h \ +$(srcdir)/GridNotifiers.cpp \ +$(srcdir)/GridNotifiers.h \ +$(srcdir)/GridNotifiersImpl.h \ +$(srcdir)/GridStates.cpp \ +$(srcdir)/GridStates.h \ +$(srcdir)/Group.cpp \ +$(srcdir)/Group.h \ +$(srcdir)/GroupHandler.cpp \ +$(srcdir)/GuardAI.cpp \ +$(srcdir)/GuardAI.h \ +$(srcdir)/Guild.cpp \ +$(srcdir)/Guild.h \ +$(srcdir)/GuildHandler.cpp \ +$(srcdir)/HateMatrix.h \ +$(srcdir)/HomeMovementGenerator.cpp \ +$(srcdir)/HomeMovementGenerator.h \ +$(srcdir)/HostilRefManager.cpp \ +$(srcdir)/HostilRefManager.h \ +$(srcdir)/IdleMovementGenerator.cpp \ +$(srcdir)/IdleMovementGenerator.h \ +$(srcdir)/InstanceData.cpp \ +$(srcdir)/InstanceData.h \ +$(srcdir)/InstanceSaveMgr.cpp \ +$(srcdir)/InstanceSaveMgr.h \ +$(srcdir)/Item.cpp \ +$(srcdir)/Item.h \ +$(srcdir)/ItemEnchantmentMgr.cpp \ +$(srcdir)/ItemEnchantmentMgr.h \ +$(srcdir)/ItemHandler.cpp \ +$(srcdir)/ItemPrototype.h \ +$(srcdir)/Language.h \ +$(srcdir)/Level0.cpp \ +$(srcdir)/Level1.cpp \ +$(srcdir)/Level2.cpp \ +$(srcdir)/Level3.cpp \ +$(srcdir)/LFGHandler.cpp \ +$(srcdir)/LootHandler.cpp \ +$(srcdir)/LootMgr.cpp \ +$(srcdir)/LootMgr.h \ +$(srcdir)/Mail.cpp \ +$(srcdir)/Mail.h \ +$(srcdir)/Map.cpp \ +$(srcdir)/Map.h \ +$(srcdir)/MapInstanced.cpp \ +$(srcdir)/MapInstanced.h \ +$(srcdir)/MapManager.cpp \ +$(srcdir)/MapManager.h \ +$(srcdir)/MiscHandler.cpp \ +$(srcdir)/MotionMaster.cpp \ +$(srcdir)/MotionMaster.h \ +$(srcdir)/MovementGenerator.cpp \ +$(srcdir)/MovementGenerator.h \ +$(srcdir)/MovementGeneratorImpl.h \ +$(srcdir)/MovementHandler.cpp \ +$(srcdir)/NPCHandler.cpp \ +$(srcdir)/NPCHandler.h \ +$(srcdir)/NullCreatureAI.cpp \ +$(srcdir)/NullCreatureAI.h \ +$(srcdir)/ObjectAccessor.cpp \ +$(srcdir)/ObjectAccessor.h \ +$(srcdir)/Object.cpp \ +$(srcdir)/ObjectDefines.h \ +$(srcdir)/ObjectGridLoader.cpp \ +$(srcdir)/ObjectGridLoader.h \ +$(srcdir)/Object.h \ +$(srcdir)/ObjectMgr.cpp \ +$(srcdir)/ObjectMgr.h \ +$(srcdir)/ObjectPosSelector.cpp \ +$(srcdir)/ObjectPosSelector.h \ +$(srcdir)/Opcodes.cpp \ +$(srcdir)/Opcodes.h \ +$(srcdir)/Path.h \ +$(srcdir)/PetAI.cpp \ +$(srcdir)/PetAI.h \ +$(srcdir)/Pet.cpp \ +$(srcdir)/Pet.h \ +$(srcdir)/PetHandler.cpp \ +$(srcdir)/PetitionsHandler.cpp \ +$(srcdir)/Player.cpp \ +$(srcdir)/Player.h \ +$(srcdir)/PlayerDump.cpp \ +$(srcdir)/PlayerDump.h \ +$(srcdir)/PointMovementGenerator.cpp \ +$(srcdir)/PointMovementGenerator.h \ +$(srcdir)/QueryHandler.cpp \ +$(srcdir)/QuestDef.cpp \ +$(srcdir)/QuestDef.h \ +$(srcdir)/QuestHandler.cpp \ +$(srcdir)/RandomMovementGenerator.cpp \ +$(srcdir)/RandomMovementGenerator.h \ +$(srcdir)/ReactorAI.cpp \ +$(srcdir)/ReactorAI.h \ +$(srcdir)/ScriptCalls.cpp \ +$(srcdir)/ScriptCalls.h \ +$(srcdir)/SharedDefines.h \ +$(srcdir)/SkillHandler.cpp \ +$(srcdir)/SpellAuraDefines.h \ +$(srcdir)/SpellAuras.cpp \ +$(srcdir)/SpellAuras.h \ +$(srcdir)/Spell.cpp \ +$(srcdir)/SpellEffects.cpp \ +$(srcdir)/Spell.h \ +$(srcdir)/SkillDiscovery.cpp \ +$(srcdir)/SkillDiscovery.h \ +$(srcdir)/SkillExtraItems.cpp \ +$(srcdir)/SkillExtraItems.h \ +$(srcdir)/SpellHandler.cpp \ +$(srcdir)/SocialMgr.cpp \ +$(srcdir)/SocialMgr.h \ +$(srcdir)/SpellMgr.cpp \ +$(srcdir)/SpellMgr.h \ +$(srcdir)/StatSystem.cpp \ +$(srcdir)/TargetedMovementGenerator.cpp \ +$(srcdir)/TargetedMovementGenerator.h \ +$(srcdir)/TaxiHandler.cpp \ +$(srcdir)/TemporarySummon.cpp \ +$(srcdir)/TemporarySummon.h \ +$(srcdir)/tools.cpp \ +$(srcdir)/Tools.h \ +$(srcdir)/TotemAI.cpp \ +$(srcdir)/TotemAI.h \ +$(srcdir)/Totem.cpp \ +$(srcdir)/Totem.h \ +$(srcdir)/TradeHandler.cpp \ +$(srcdir)/Transports.cpp \ +$(srcdir)/Transports.h \ +$(srcdir)/ThreatManager.cpp \ +$(srcdir)/ThreatManager.h \ +$(srcdir)/Traveller.h \ +$(srcdir)/Unit.cpp \ +$(srcdir)/Unit.h \ +$(srcdir)/UnitEvents.h \ +$(srcdir)/UpdateData.cpp \ +$(srcdir)/UpdateData.h \ +$(srcdir)/UpdateFields.h \ +$(srcdir)/UpdateMask.h \ +$(srcdir)/VoiceChatHandler.cpp \ +$(srcdir)/WaypointManager.cpp \ +$(srcdir)/WaypointManager.h \ +$(srcdir)/WaypointMovementGenerator.cpp \ +$(srcdir)/WaypointMovementGenerator.h \ +$(srcdir)/Weather.cpp \ +$(srcdir)/Weather.h \ +$(srcdir)/World.cpp \ +$(srcdir)/World.h \ +$(srcdir)/WorldLog.cpp \ +$(srcdir)/WorldLog.h \ +$(srcdir)/WorldSession.cpp \ +$(srcdir)/WorldSession.h \ +$(srcdir)/WorldSocket.cpp \ +$(srcdir)/WorldSocket.h \ +$(srcdir)/WorldSocketMgr.cpp \ +$(srcdir)/WorldSocketMgr.h \ +$(srcdir)/FollowerReference.cpp \ +$(srcdir)/FollowerReference.h \ +$(srcdir)/FollowerRefManager.h \ +$(srcdir)/GroupReference.cpp \ +$(srcdir)/GroupReference.h \ +$(srcdir)/GroupRefManager.h + +## Additional files to include when running 'make dist' +# Nothing yet. diff --git a/src/game/Map.cpp b/src/game/Map.cpp new file mode 100644 index 00000000000..df03bb96842 --- /dev/null +++ b/src/game/Map.cpp @@ -0,0 +1,1795 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Player.h" +#include "GridNotifiers.h" +#include "WorldSession.h" +#include "Log.h" +#include "GridStates.h" +#include "CellImpl.h" +#include "InstanceData.h" +#include "Map.h" +#include "GridNotifiersImpl.h" +#include "Config/ConfigEnv.h" +#include "Transports.h" +#include "ObjectAccessor.h" +#include "ObjectMgr.h" +#include "World.h" +#include "ScriptCalls.h" +#include "Group.h" + +#include "MapManager.h" +#include "MapInstanced.h" +#include "InstanceSaveMgr.h" +#include "VMapFactory.h" + +#define DEFAULT_GRID_EXPIRY 300 +#define MAX_GRID_LOAD_TIME 50 + +// magic *.map header +const char MAP_MAGIC[] = "MAP_2.00"; + +GridState* si_GridStates[MAX_GRID_STATE]; + +Map::~Map() +{ + UnloadAll(true); +} + +bool Map::ExistMap(uint32 mapid,int x,int y) +{ + int len = sWorld.GetDataPath().length()+strlen("maps/%03u%02u%02u.map")+1; + char* tmp = new char[len]; + snprintf(tmp, len, (char *)(sWorld.GetDataPath()+"maps/%03u%02u%02u.map").c_str(),mapid,x,y); + + FILE *pf=fopen(tmp,"rb"); + + if(!pf) + { + sLog.outError("Check existing of map file '%s': not exist!",tmp); + delete[] tmp; + return false; + } + + char magic[8]; + fread(magic,1,8,pf); + if(strncmp(MAP_MAGIC,magic,8)) + { + sLog.outError("Map file '%s' is non-compatible version (outdated?). Please, create new using ad.exe program.",tmp); + delete [] tmp; + fclose(pf); //close file before return + return false; + } + + delete [] tmp; + fclose(pf); + + return true; +} + +bool Map::ExistVMap(uint32 mapid,int x,int y) +{ + if(VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager()) + { + if(vmgr->isMapLoadingEnabled()) + { + // x and y are swaped !! => fixed now + bool exists = vmgr->existsMap((sWorld.GetDataPath()+ "vmaps").c_str(), mapid, x,y); + if(!exists) + { + std::string name = vmgr->getDirFileName(mapid,x,y); + sLog.outError("VMap file '%s' is missing or point to wrong version vmap file, redo vmaps with latest vmap_assembler.exe program", (sWorld.GetDataPath()+"vmaps/"+name).c_str()); + return false; + } + } + } + + return true; +} + +void Map::LoadVMap(int x,int y) +{ + // x and y are swaped !! + int vmapLoadResult = VMAP::VMapFactory::createOrGetVMapManager()->loadMap((sWorld.GetDataPath()+ "vmaps").c_str(), GetId(), x,y); + switch(vmapLoadResult) + { + case VMAP::VMAP_LOAD_RESULT_OK: + sLog.outDetail("VMAP loaded name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", GetMapName(), GetId(), x,y, x,y); + break; + case VMAP::VMAP_LOAD_RESULT_ERROR: + sLog.outDetail("Could not load VMAP name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", GetMapName(), GetId(), x,y, x,y); + break; + case VMAP::VMAP_LOAD_RESULT_IGNORED: + DEBUG_LOG("Ignored VMAP name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", GetMapName(), GetId(), x,y, x,y); + break; + } +} + +void Map::LoadMap(uint32 mapid, uint32 instanceid, int x,int y) +{ + if( instanceid != 0 ) + { + if(GridMaps[x][y]) + return; + + Map* baseMap = const_cast(MapManager::Instance().GetBaseMap(mapid)); + + // load gridmap for base map + if (!baseMap->GridMaps[x][y]) + baseMap->EnsureGridCreated(GridPair(63-x,63-y)); + +//+++ if (!baseMap->GridMaps[x][y]) don't check for GridMaps[gx][gy], we need the management for vmaps +// return; + + ((MapInstanced*)(baseMap))->AddGridMapReference(GridPair(x,y)); + baseMap->SetUnloadFlag(GridPair(63-x,63-y), false); + GridMaps[x][y] = baseMap->GridMaps[x][y]; + return; + } + + //map already load, delete it before reloading (Is it neccessary? Do we really need the abilty the reload maps during runtime?) + if(GridMaps[x][y]) + { + sLog.outDetail("Unloading already loaded map %u before reloading.",mapid); + delete (GridMaps[x][y]); + GridMaps[x][y]=NULL; + } + + // map file name + char *tmp=NULL; + // Pihhan: dataPath length + "maps/" + 3+2+2+ ".map" length may be > 32 ! + int len = sWorld.GetDataPath().length()+strlen("maps/%03u%02u%02u.map")+1; + tmp = new char[len]; + snprintf(tmp, len, (char *)(sWorld.GetDataPath()+"maps/%03u%02u%02u.map").c_str(),mapid,x,y); + sLog.outDetail("Loading map %s",tmp); + // loading data + FILE *pf=fopen(tmp,"rb"); + if(!pf) + { + delete [] tmp; + return; + } + + char magic[8]; + fread(magic,1,8,pf); + if(strncmp(MAP_MAGIC,magic,8)) + { + sLog.outError("Map file '%s' is non-compatible version (outdated?). Please, create new using ad.exe program.",tmp); + delete [] tmp; + fclose(pf); //close file before return + return; + } + delete [] tmp; + + GridMap * buf= new GridMap; + fread(buf,1,sizeof(GridMap),pf); + fclose(pf); + + GridMaps[x][y] = buf; +} + +void Map::LoadMapAndVMap(uint32 mapid, uint32 instanceid, int x,int y) +{ + LoadMap(mapid,instanceid,x,y); + if(instanceid == 0) + LoadVMap(x, y); // Only load the data for the base map +} + +void Map::InitStateMachine() +{ + si_GridStates[GRID_STATE_INVALID] = new InvalidState; + si_GridStates[GRID_STATE_ACTIVE] = new ActiveState; + si_GridStates[GRID_STATE_IDLE] = new IdleState; + si_GridStates[GRID_STATE_REMOVAL] = new RemovalState; +} + +void Map::DeleteStateMachine() +{ + delete si_GridStates[GRID_STATE_INVALID]; + delete si_GridStates[GRID_STATE_ACTIVE]; + delete si_GridStates[GRID_STATE_IDLE]; + delete si_GridStates[GRID_STATE_REMOVAL]; +} + +Map::Map(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode) + : i_id(id), i_gridExpiry(expiry), i_mapEntry (sMapStore.LookupEntry(id)), + i_InstanceId(InstanceId), i_spawnMode(SpawnMode), m_unloadTimer(0) +{ + for(unsigned int idx=0; idx < MAX_NUMBER_OF_GRIDS; ++idx) + { + for(unsigned int j=0; j < MAX_NUMBER_OF_GRIDS; ++j) + { + //z code + GridMaps[idx][j] =NULL; + setNGrid(NULL, idx, j); + } + } +} + +// Template specialization of utility methods +template +void Map::AddToGrid(T* obj, NGridType *grid, Cell const& cell) +{ + (*grid)(cell.CellX(), cell.CellY()).template AddGridObject(obj, obj->GetGUID()); +} + +template<> +void Map::AddToGrid(Player* obj, NGridType *grid, Cell const& cell) +{ + (*grid)(cell.CellX(), cell.CellY()).AddWorldObject(obj, obj->GetGUID()); +} + +template<> +void Map::AddToGrid(Corpse *obj, NGridType *grid, Cell const& cell) +{ + // add to world object registry in grid + if(obj->GetType()!=CORPSE_BONES) + { + (*grid)(cell.CellX(), cell.CellY()).AddWorldObject(obj, obj->GetGUID()); + } + // add to grid object store + else + { + (*grid)(cell.CellX(), cell.CellY()).AddGridObject(obj, obj->GetGUID()); + } +} + +template<> +void Map::AddToGrid(Creature* obj, NGridType *grid, Cell const& cell) +{ + // add to world object registry in grid + if(obj->isPet()) + { + (*grid)(cell.CellX(), cell.CellY()).AddWorldObject(obj, obj->GetGUID()); + obj->SetCurrentCell(cell); + } + // add to grid object store + else + { + (*grid)(cell.CellX(), cell.CellY()).AddGridObject(obj, obj->GetGUID()); + obj->SetCurrentCell(cell); + } +} + +template +void Map::RemoveFromGrid(T* obj, NGridType *grid, Cell const& cell) +{ + (*grid)(cell.CellX(), cell.CellY()).template RemoveGridObject(obj, obj->GetGUID()); +} + +template<> +void Map::RemoveFromGrid(Player* obj, NGridType *grid, Cell const& cell) +{ + (*grid)(cell.CellX(), cell.CellY()).RemoveWorldObject(obj, obj->GetGUID()); +} + +template<> +void Map::RemoveFromGrid(Corpse *obj, NGridType *grid, Cell const& cell) +{ + // remove from world object registry in grid + if(obj->GetType()!=CORPSE_BONES) + { + (*grid)(cell.CellX(), cell.CellY()).RemoveWorldObject(obj, obj->GetGUID()); + } + // remove from grid object store + else + { + (*grid)(cell.CellX(), cell.CellY()).RemoveGridObject(obj, obj->GetGUID()); + } +} + +template<> +void Map::RemoveFromGrid(Creature* obj, NGridType *grid, Cell const& cell) +{ + // remove from world object registry in grid + if(obj->isPet()) + { + (*grid)(cell.CellX(), cell.CellY()).RemoveWorldObject(obj, obj->GetGUID()); + } + // remove from grid object store + else + { + (*grid)(cell.CellX(), cell.CellY()).RemoveGridObject(obj, obj->GetGUID()); + } +} + +template +void Map::DeleteFromWorld(T* obj) +{ + // Note: In case resurrectable corpse and pet its removed from gloabal lists in own destructors + delete obj; +} + +template +void Map::AddNotifier(T* , Cell const& , CellPair const& ) +{ +} + +template<> +void Map::AddNotifier(Player* obj, Cell const& cell, CellPair const& cellpair) +{ + PlayerRelocationNotify(obj,cell,cellpair); +} + +template<> +void Map::AddNotifier(Creature* obj, Cell const& cell, CellPair const& cellpair) +{ + CreatureRelocationNotify(obj,cell,cellpair); +} + +void +Map::EnsureGridCreated(const GridPair &p) +{ + if(!getNGrid(p.x_coord, p.y_coord)) + { + Guard guard(*this); + if(!getNGrid(p.x_coord, p.y_coord)) + { + setNGrid(new NGridType(p.x_coord*MAX_NUMBER_OF_GRIDS + p.y_coord, p.x_coord, p.y_coord, i_gridExpiry, sWorld.getConfig(CONFIG_GRID_UNLOAD)), + p.x_coord, p.y_coord); + + // build a linkage between this map and NGridType + buildNGridLinkage(getNGrid(p.x_coord, p.y_coord)); + + getNGrid(p.x_coord, p.y_coord)->SetGridState(GRID_STATE_IDLE); + + //z coord + int gx=63-p.x_coord; + int gy=63-p.y_coord; + + if(!GridMaps[gx][gy]) + Map::LoadMapAndVMap(i_id,i_InstanceId,gx,gy); + } + } +} + +void +Map::EnsureGridLoadedForPlayer(const Cell &cell, Player *player, bool add_player) +{ + EnsureGridCreated(GridPair(cell.GridX(), cell.GridY())); + NGridType *grid = getNGrid(cell.GridX(), cell.GridY()); + + assert(grid != NULL); + if( !isGridObjectDataLoaded(cell.GridX(), cell.GridY()) ) + { + if( player != NULL ) + { + player->SendDelayResponse(MAX_GRID_LOAD_TIME); + DEBUG_LOG("Player %s enter cell[%u,%u] triggers of loading grid[%u,%u] on map %u", player->GetName(), cell.CellX(), cell.CellY(), cell.GridX(), cell.GridY(), i_id); + } + else + { + DEBUG_LOG("Player nearby triggers of loading grid [%u,%u] on map %u", cell.GridX(), cell.GridY(), i_id); + } + + ObjectGridLoader loader(*grid, this, cell); + loader.LoadN(); + setGridObjectDataLoaded(true, cell.GridX(), cell.GridY()); + + // Add resurrectable corpses to world object list in grid + ObjectAccessor::Instance().AddCorpsesToGrid(GridPair(cell.GridX(),cell.GridY()),(*grid)(cell.CellX(), cell.CellY()), this); + + ResetGridExpiry(*getNGrid(cell.GridX(), cell.GridY()), 0.1f); + grid->SetGridState(GRID_STATE_ACTIVE); + + if( add_player && player != NULL ) + (*grid)(cell.CellX(), cell.CellY()).AddWorldObject(player, player->GetGUID()); + } + else if( player && add_player ) + AddToGrid(player,grid,cell); +} + +void +Map::LoadGrid(const Cell& cell, bool no_unload) +{ + EnsureGridCreated(GridPair(cell.GridX(), cell.GridY())); + NGridType *grid = getNGrid(cell.GridX(), cell.GridY()); + + assert(grid != NULL); + if( !isGridObjectDataLoaded(cell.GridX(), cell.GridY()) ) + { + ObjectGridLoader loader(*grid, this, cell); + loader.LoadN(); + + // Add resurrectable corpses to world object list in grid + ObjectAccessor::Instance().AddCorpsesToGrid(GridPair(cell.GridX(),cell.GridY()),(*grid)(cell.CellX(), cell.CellY()), this); + + setGridObjectDataLoaded(true,cell.GridX(), cell.GridY()); + if(no_unload) + getNGrid(cell.GridX(), cell.GridY())->setUnloadFlag(false); + } + LoadVMap(63-cell.GridX(),63-cell.GridY()); +} + +bool Map::Add(Player *player) +{ + player->SetInstanceId(this->GetInstanceId()); + + // update player state for other player and visa-versa + CellPair p = MaNGOS::ComputeCellPair(player->GetPositionX(), player->GetPositionY()); + Cell cell(p); + EnsureGridLoadedForPlayer(cell, player, true); + player->AddToWorld(); + + SendInitSelf(player); + SendInitTransports(player); + + UpdatePlayerVisibility(player,cell,p); + UpdateObjectsVisibilityFor(player,cell,p); + + AddNotifier(player,cell,p); + return true; +} + +template +void +Map::Add(T *obj) +{ + CellPair p = MaNGOS::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()); + + assert(obj); + + if(p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP ) + { + sLog.outError("Map::Add: Object " I64FMTD " have invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUID(), obj->GetPositionX(), obj->GetPositionY(), p.x_coord, p.y_coord); + return; + } + + Cell cell(p); + EnsureGridCreated(GridPair(cell.GridX(), cell.GridY())); + NGridType *grid = getNGrid(cell.GridX(), cell.GridY()); + assert( grid != NULL ); + + AddToGrid(obj,grid,cell); + obj->AddToWorld(); + + DEBUG_LOG("Object %u enters grid[%u,%u]", GUID_LOPART(obj->GetGUID()), cell.GridX(), cell.GridY()); + + UpdateObjectVisibility(obj,cell,p); + + AddNotifier(obj,cell,p); +} + +void Map::MessageBroadcast(Player *player, WorldPacket *msg, bool to_self) +{ + CellPair p = MaNGOS::ComputeCellPair(player->GetPositionX(), player->GetPositionY()); + + if(p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP ) + { + sLog.outError("Map::MessageBroadcast: Player (GUID: %u) have invalid coordinates X:%f Y:%f grid cell [%u:%u]", player->GetGUIDLow(), player->GetPositionX(), player->GetPositionY(), p.x_coord, p.y_coord); + return; + } + + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + + if( !loaded(GridPair(cell.data.Part.grid_x, cell.data.Part.grid_y)) ) + return; + + MaNGOS::MessageDeliverer post_man(*player, msg, to_self); + TypeContainerVisitor message(post_man); + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, message, *this); +} + +void Map::MessageBroadcast(WorldObject *obj, WorldPacket *msg) +{ + CellPair p = MaNGOS::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()); + + if(p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP ) + { + sLog.outError("Map::MessageBroadcast: Object " I64FMTD " have invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUID(), obj->GetPositionX(), obj->GetPositionY(), p.x_coord, p.y_coord); + return; + } + + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + if( !loaded(GridPair(cell.data.Part.grid_x, cell.data.Part.grid_y)) ) + return; + + MaNGOS::ObjectMessageDeliverer post_man(msg); + TypeContainerVisitor message(post_man); + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, message, *this); +} + +void Map::MessageDistBroadcast(Player *player, WorldPacket *msg, float dist, bool to_self, bool own_team_only) +{ + CellPair p = MaNGOS::ComputeCellPair(player->GetPositionX(), player->GetPositionY()); + + if(p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP ) + { + sLog.outError("Map::MessageBroadcast: Player (GUID: %u) have invalid coordinates X:%f Y:%f grid cell [%u:%u]", player->GetGUIDLow(), player->GetPositionX(), player->GetPositionY(), p.x_coord, p.y_coord); + return; + } + + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + + if( !loaded(GridPair(cell.data.Part.grid_x, cell.data.Part.grid_y)) ) + return; + + MaNGOS::MessageDistDeliverer post_man(*player, msg, dist, to_self, own_team_only); + TypeContainerVisitor message(post_man); + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, message, *this); +} + +void Map::MessageDistBroadcast(WorldObject *obj, WorldPacket *msg, float dist) +{ + CellPair p = MaNGOS::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()); + + if(p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP ) + { + sLog.outError("Map::MessageBroadcast: Object " I64FMTD " have invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUID(), obj->GetPositionX(), obj->GetPositionY(), p.x_coord, p.y_coord); + return; + } + + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + if( !loaded(GridPair(cell.data.Part.grid_x, cell.data.Part.grid_y)) ) + return; + + MaNGOS::ObjectMessageDistDeliverer post_man(*obj, msg,dist); + TypeContainerVisitor message(post_man); + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, message, *this); +} + +bool Map::loaded(const GridPair &p) const +{ + return ( getNGrid(p.x_coord, p.y_coord) && isGridObjectDataLoaded(p.x_coord, p.y_coord) ); +} + +void Map::Update(const uint32 &t_diff) +{ + // Don't unload grids if it's battleground, since we may have manually added GOs,creatures, those doesn't load from DB at grid re-load ! + // This isn't really bother us, since as soon as we have instanced BG-s, the whole map unloads as the BG gets ended + if (IsBattleGroundOrArena()) + return; + + for (GridRefManager::iterator i = GridRefManager::begin(); i != GridRefManager::end(); ) + { + NGridType *grid = i->getSource(); + GridInfo *info = i->getSource()->getGridInfoRef(); + ++i; // The update might delete the map and we need the next map before the iterator gets invalid + assert(grid->GetGridState() >= 0 && grid->GetGridState() < MAX_GRID_STATE); + si_GridStates[grid->GetGridState()]->Update(*this, *grid, *info, grid->getX(), grid->getY(), t_diff); + } +} + +void InstanceMap::Update(const uint32& t_diff) +{ + Map::Update(t_diff); + + if(i_data) + i_data->Update(t_diff); +} + + +void Map::Remove(Player *player, bool remove) +{ + CellPair p = MaNGOS::ComputeCellPair(player->GetPositionX(), player->GetPositionY()); + if(p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) + { + // invalid coordinates + player->RemoveFromWorld(); + + if( remove ) + DeleteFromWorld(player); + + return; + } + + Cell cell(p); + + if( !getNGrid(cell.data.Part.grid_x, cell.data.Part.grid_y) ) + { + sLog.outError("Map::Remove() i_grids was NULL x:%d, y:%d",cell.data.Part.grid_x,cell.data.Part.grid_y); + return; + } + + DEBUG_LOG("Remove player %s from grid[%u,%u]", player->GetName(), cell.GridX(), cell.GridY()); + NGridType *grid = getNGrid(cell.GridX(), cell.GridY()); + assert(grid != NULL); + + player->RemoveFromWorld(); + RemoveFromGrid(player,grid,cell); + + SendRemoveTransports(player); + + UpdateObjectsVisibilityFor(player,cell,p); + + if( remove ) + DeleteFromWorld(player); +} + +bool Map::RemoveBones(uint64 guid, float x, float y) +{ + if (IsRemovalGrid(x, y)) + { + Corpse * corpse = ObjectAccessor::Instance().GetObjectInWorld(GetId(), x, y, guid, (Corpse*)NULL); + if(corpse && corpse->GetTypeId() == TYPEID_CORPSE && corpse->GetType() == CORPSE_BONES) + corpse->DeleteBonesFromWorld(); + else + return false; + } + return true; +} + +template +void +Map::Remove(T *obj, bool remove) +{ + CellPair p = MaNGOS::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()); + if(p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP ) + { + sLog.outError("Map::Remove: Object " I64FMTD " have invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUID(), obj->GetPositionX(), obj->GetPositionY(), p.x_coord, p.y_coord); + return; + } + + Cell cell(p); + if( !loaded(GridPair(cell.data.Part.grid_x, cell.data.Part.grid_y)) ) + return; + + DEBUG_LOG("Remove object " I64FMTD " from grid[%u,%u]", obj->GetGUID(), cell.data.Part.grid_x, cell.data.Part.grid_y); + NGridType *grid = getNGrid(cell.GridX(), cell.GridY()); + assert( grid != NULL ); + + obj->RemoveFromWorld(); + RemoveFromGrid(obj,grid,cell); + + UpdateObjectVisibility(obj,cell,p); + + if( remove ) + { + // if option set then object already saved at this moment + if(!sWorld.getConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATLY)) + obj->SaveRespawnTime(); + DeleteFromWorld(obj); + } +} + +void +Map::PlayerRelocation(Player *player, float x, float y, float z, float orientation) +{ + assert(player); + + CellPair old_val = MaNGOS::ComputeCellPair(player->GetPositionX(), player->GetPositionY()); + CellPair new_val = MaNGOS::ComputeCellPair(x, y); + + Cell old_cell(old_val); + Cell new_cell(new_val); + new_cell |= old_cell; + bool same_cell = (new_cell == old_cell); + + player->Relocate(x, y, z, orientation); + + if( old_cell.DiffGrid(new_cell) || old_cell.DiffCell(new_cell) ) + { + DEBUG_LOG("Player %s relocation grid[%u,%u]cell[%u,%u]->grid[%u,%u]cell[%u,%u]", player->GetName(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY()); + + // update player position for group at taxi flight + if(player->GetGroup() && player->isInFlight()) + player->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_POSITION); + + NGridType* oldGrid = getNGrid(old_cell.GridX(), old_cell.GridY()); + RemoveFromGrid(player, oldGrid,old_cell); + if( !old_cell.DiffGrid(new_cell) ) + AddToGrid(player, oldGrid,new_cell); + + if( old_cell.DiffGrid(new_cell) ) + EnsureGridLoadedForPlayer(new_cell, player, true); + } + + // if move then update what player see and who seen + UpdatePlayerVisibility(player,new_cell,new_val); + UpdateObjectsVisibilityFor(player,new_cell,new_val); + PlayerRelocationNotify(player,new_cell,new_val); + NGridType* newGrid = getNGrid(new_cell.GridX(), new_cell.GridY()); + if( !same_cell && newGrid->GetGridState()!= GRID_STATE_ACTIVE ) + { + ResetGridExpiry(*newGrid, 0.1f); + newGrid->SetGridState(GRID_STATE_ACTIVE); + } +} + +void +Map::CreatureRelocation(Creature *creature, float x, float y, float z, float ang) +{ + assert(CheckGridIntegrity(creature,false)); + + Cell old_cell = creature->GetCurrentCell(); + + CellPair new_val = MaNGOS::ComputeCellPair(x, y); + Cell new_cell(new_val); + + // delay creature move for grid/cell to grid/cell moves + if( old_cell.DiffCell(new_cell) || old_cell.DiffGrid(new_cell) ) + { + #ifdef MANGOS_DEBUG + if((sLog.getLogFilter() & LOG_FILTER_CREATURE_MOVES)==0) + sLog.outDebug("Creature (GUID: %u Entry: %u) added to moving list from grid[%u,%u]cell[%u,%u] to grid[%u,%u]cell[%u,%u].", creature->GetGUIDLow(), creature->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY()); + #endif + AddCreatureToMoveList(creature,x,y,z,ang); + // in diffcell/diffgrid case notifiers called at finishing move creature in Map::MoveAllCreaturesInMoveList + } + else + { + creature->Relocate(x, y, z, ang); + CreatureRelocationNotify(creature,new_cell,new_val); + } + assert(CheckGridIntegrity(creature,true)); +} + +void Map::AddCreatureToMoveList(Creature *c, float x, float y, float z, float ang) +{ + if(!c) + return; + + i_creaturesToMove[c] = CreatureMover(x,y,z,ang); +} + +void Map::MoveAllCreaturesInMoveList() +{ + while(!i_creaturesToMove.empty()) + { + // get data and remove element; + CreatureMoveList::iterator iter = i_creaturesToMove.begin(); + Creature* c = iter->first; + CreatureMover cm = iter->second; + i_creaturesToMove.erase(iter); + + // calculate cells + CellPair new_val = MaNGOS::ComputeCellPair(cm.x, cm.y); + Cell new_cell(new_val); + + // do move or do move to respawn or remove creature if previous all fail + if(CreatureCellRelocation(c,new_cell)) + { + // update pos + c->Relocate(cm.x, cm.y, cm.z, cm.ang); + CreatureRelocationNotify(c,new_cell,new_cell.cellPair()); + } + else + { + // if creature can't be move in new cell/grid (not loaded) move it to repawn cell/grid + // creature coordinates will be updated and notifiers send + if(!CreatureRespawnRelocation(c)) + { + // ... or unload (if respawn grid also not loaded) + #ifdef MANGOS_DEBUG + if((sLog.getLogFilter() & LOG_FILTER_CREATURE_MOVES)==0) + sLog.outDebug("Creature (GUID: %u Entry: %u ) can't be move to unloaded respawn grid.",c->GetGUIDLow(),c->GetEntry()); + #endif + c->CleanupsBeforeDelete(); + AddObjectToRemoveList(c); + } + } + } +} + +bool Map::CreatureCellRelocation(Creature *c, Cell new_cell) +{ + Cell const& old_cell = c->GetCurrentCell(); + if(!old_cell.DiffGrid(new_cell) ) // in same grid + { + // if in same cell then none do + if(old_cell.DiffCell(new_cell)) + { + #ifdef MANGOS_DEBUG + if((sLog.getLogFilter() & LOG_FILTER_CREATURE_MOVES)==0) + sLog.outDebug("Creature (GUID: %u Entry: %u) moved in grid[%u,%u] from cell[%u,%u] to cell[%u,%u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.CellX(), new_cell.CellY()); + #endif + + if( !old_cell.DiffGrid(new_cell) ) + { + RemoveFromGrid(c,getNGrid(old_cell.GridX(), old_cell.GridY()),old_cell); + AddToGrid(c,getNGrid(new_cell.GridX(), new_cell.GridY()),new_cell); + c->SetCurrentCell(new_cell); + } + } + else + { + #ifdef MANGOS_DEBUG + if((sLog.getLogFilter() & LOG_FILTER_CREATURE_MOVES)==0) + sLog.outDebug("Creature (GUID: %u Entry: %u) move in same grid[%u,%u]cell[%u,%u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY()); + #endif + } + } + else // in diff. grids + if(loaded(GridPair(new_cell.GridX(), new_cell.GridY()))) + { + #ifdef MANGOS_DEBUG + if((sLog.getLogFilter() & LOG_FILTER_CREATURE_MOVES)==0) + sLog.outDebug("Creature (GUID: %u Entry: %u) moved from grid[%u,%u]cell[%u,%u] to grid[%u,%u]cell[%u,%u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY()); + #endif + + RemoveFromGrid(c,getNGrid(old_cell.GridX(), old_cell.GridY()),old_cell); + { + EnsureGridCreated(GridPair(new_cell.GridX(), new_cell.GridY())); + AddToGrid(c,getNGrid(new_cell.GridX(), new_cell.GridY()),new_cell); + } + } + else + { + #ifdef MANGOS_DEBUG + if((sLog.getLogFilter() & LOG_FILTER_CREATURE_MOVES)==0) + sLog.outDebug("Creature (GUID: %u Entry: %u) attempt move from grid[%u,%u]cell[%u,%u] to unloaded grid[%u,%u]cell[%u,%u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY()); + #endif + return false; + } + + return true; +} + +bool Map::CreatureRespawnRelocation(Creature *c) +{ + float resp_x, resp_y, resp_z, resp_o; + c->GetRespawnCoord(resp_x, resp_y, resp_z, &resp_o); + + CellPair resp_val = MaNGOS::ComputeCellPair(resp_x, resp_y); + Cell resp_cell(resp_val); + + c->CombatStop(); + c->GetMotionMaster()->Clear(); + + #ifdef MANGOS_DEBUG + if((sLog.getLogFilter() & LOG_FILTER_CREATURE_MOVES)==0) + sLog.outDebug("Creature (GUID: %u Entry: %u) will moved from grid[%u,%u]cell[%u,%u] to respawn grid[%u,%u]cell[%u,%u].", c->GetGUIDLow(), c->GetEntry(), c->GetCurrentCell().GridX(), c->GetCurrentCell().GridY(), c->GetCurrentCell().CellX(), c->GetCurrentCell().CellY(), resp_cell.GridX(), resp_cell.GridY(), resp_cell.CellX(), resp_cell.CellY()); + #endif + + // teleport it to respawn point (like normal respawn if player see) + if(CreatureCellRelocation(c,resp_cell)) + { + c->Relocate(resp_x, resp_y, resp_z, resp_o); + c->GetMotionMaster()->Initialize(); // prevent possible problems with default move generators + CreatureRelocationNotify(c,resp_cell,resp_cell.cellPair()); + return true; + } + else + return false; +} + +bool Map::UnloadGrid(const uint32 &x, const uint32 &y, bool pForce) +{ + NGridType *grid = getNGrid(x, y); + assert( grid != NULL); + + { + if(!pForce && ObjectAccessor::Instance().PlayersNearGrid(x, y, i_id, i_InstanceId) ) + return false; + + DEBUG_LOG("Unloading grid[%u,%u] for map %u", x,y, i_id); + ObjectGridUnloader unloader(*grid); + + // Finish creature moves, remove and delete all creatures with delayed remove before moving to respawn grids + // Must know real mob position before move + DoDelayedMovesAndRemoves(); + + // move creatures to respawn grids if this is diff.grid or to remove list + unloader.MoveToRespawnN(); + + // Finish creature moves, remove and delete all creatures with delayed remove before unload + DoDelayedMovesAndRemoves(); + + unloader.UnloadN(); + delete getNGrid(x, y); + setNGrid(NULL, x, y); + } + int gx=63-x; + int gy=63-y; + + // delete grid map, but don't delete if it is from parent map (and thus only reference) + //+++if (GridMaps[gx][gy]) don't check for GridMaps[gx][gy], we might have to unload vmaps + { + if (i_InstanceId == 0) + { + if(GridMaps[gx][gy]) delete (GridMaps[gx][gy]); + // x and y are swaped + VMAP::VMapFactory::createOrGetVMapManager()->unloadMap(GetId(), gy, gx); + } + else + ((MapInstanced*)(MapManager::Instance().GetBaseMap(i_id)))->RemoveGridMapReference(GridPair(gx, gy)); + GridMaps[gx][gy] = NULL; + } + DEBUG_LOG("Unloading grid[%u,%u] for map %u finished", x,y, i_id); + return true; +} + +void Map::UnloadAll(bool pForce) +{ + // clear all delayed moves, useless anyway do this moves before map unload. + i_creaturesToMove.clear(); + + for (GridRefManager::iterator i = GridRefManager::begin(); i != GridRefManager::end(); ) + { + NGridType &grid(*i->getSource()); + ++i; + UnloadGrid(grid.getX(), grid.getY(), pForce); // deletes the grid and removes it from the GridRefManager + } +} + +float Map::GetHeight(float x, float y, float z, bool pUseVmaps) const +{ + GridPair p = MaNGOS::ComputeGridPair(x, y); + + // half opt method + int gx=(int)(32-x/SIZE_OF_GRIDS); //grid x + int gy=(int)(32-y/SIZE_OF_GRIDS); //grid y + + float lx=MAP_RESOLUTION*(32 -x/SIZE_OF_GRIDS - gx); + float ly=MAP_RESOLUTION*(32 -y/SIZE_OF_GRIDS - gy); + + // ensure GridMap is loaded + const_cast(this)->EnsureGridCreated(GridPair(63-gx,63-gy)); + + // find raw .map surface under Z coordinates + float mapHeight; + if(GridMap* gmap = GridMaps[gx][gy]) + { + int lx_int = (int)lx; + int ly_int = (int)ly; + + float zi[4]; + // Probe 4 nearest points (except border cases) + zi[0] = gmap->Z[lx_int][ly_int]; + zi[1] = lx < MAP_RESOLUTION-1 ? gmap->Z[lx_int+1][ly_int] : zi[0]; + zi[2] = ly < MAP_RESOLUTION-1 ? gmap->Z[lx_int][ly_int+1] : zi[0]; + zi[3] = lx < MAP_RESOLUTION-1 && ly < MAP_RESOLUTION-1 ? gmap->Z[lx_int+1][ly_int+1] : zi[0]; + // Recalculate them like if their x,y positions were in the range 0,1 + float b[4]; + b[0] = zi[0]; + b[1] = zi[1]-zi[0]; + b[2] = zi[2]-zi[0]; + b[3] = zi[0]-zi[1]-zi[2]+zi[3]; + // Normalize the dx and dy to be in range 0..1 + float fact_x = lx - lx_int; + float fact_y = ly - ly_int; + // Use the simplified bilinear equation, as described in [url="http://en.wikipedia.org/wiki/Bilinear_interpolation"]http://en.wikipedia.org/wiki/Bilinear_interpolation[/url] + float _mapheight = b[0] + (b[1]*fact_x) + (b[2]*fact_y) + (b[3]*fact_x*fact_y); + + // look from a bit higher pos to find the floor, ignore under surface case + if(z + 2.0f > _mapheight) + mapHeight = _mapheight; + else + mapHeight = VMAP_INVALID_HEIGHT_VALUE; + } + else + mapHeight = VMAP_INVALID_HEIGHT_VALUE; + + float vmapHeight; + if(pUseVmaps) + { + VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager(); + if(vmgr->isHeightCalcEnabled()) + { + // look from a bit higher pos to find the floor + vmapHeight = vmgr->getHeight(GetId(), x, y, z + 2.0f); + } + else + vmapHeight = VMAP_INVALID_HEIGHT_VALUE; + } + else + vmapHeight = VMAP_INVALID_HEIGHT_VALUE; + + // mapHeight set for any above raw ground Z or <= INVALID_HEIGHT + // vmapheight set for any under Z value or <= INVALID_HEIGHT + + if( vmapHeight > INVALID_HEIGHT ) + { + if( mapHeight > INVALID_HEIGHT ) + { + // we have mapheight and vmapheight and must select more appropriate + + // we are already under the surface or vmap height above map heigt + // or if the distance of the vmap height is less the land height distance + if( z < mapHeight || vmapHeight > mapHeight || fabs(mapHeight-z) > fabs(vmapHeight-z) ) + return vmapHeight; + else + return mapHeight; // better use .map surface height + + } + else + return vmapHeight; // we have only vmapHeight (if have) + } + else + { + if(!pUseVmaps) + return mapHeight; // explicitly use map data (if have) + else if(mapHeight > INVALID_HEIGHT && (z < mapHeight + 2 || z == MAX_HEIGHT)) + return mapHeight; // explicitly use map data if original z < mapHeight but map found (z+2 > mapHeight) + else + return VMAP_INVALID_HEIGHT_VALUE; // we not have any height + } +} + +uint16 Map::GetAreaFlag(float x, float y ) const +{ + //local x,y coords + float lx,ly; + int gx,gy; + GridPair p = MaNGOS::ComputeGridPair(x, y); + + // half opt method + gx=(int)(32-x/SIZE_OF_GRIDS) ; //grid x + gy=(int)(32-y/SIZE_OF_GRIDS); //grid y + + lx=16*(32 -x/SIZE_OF_GRIDS - gx); + ly=16*(32 -y/SIZE_OF_GRIDS - gy); + //DEBUG_LOG("my %d %d si %d %d",gx,gy,p.x_coord,p.y_coord); + + // ensure GridMap is loaded + const_cast(this)->EnsureGridCreated(GridPair(63-gx,63-gy)); + + if(GridMaps[gx][gy]) + return GridMaps[gx][gy]->area_flag[(int)(lx)][(int)(ly)]; + // this used while not all *.map files generated (instances) + else + return GetAreaFlagByMapId(i_id); +} + +uint8 Map::GetTerrainType(float x, float y ) const +{ + //local x,y coords + float lx,ly; + int gx,gy; + + // half opt method + gx=(int)(32-x/SIZE_OF_GRIDS) ; //grid x + gy=(int)(32-y/SIZE_OF_GRIDS); //grid y + + lx=16*(32 -x/SIZE_OF_GRIDS - gx); + ly=16*(32 -y/SIZE_OF_GRIDS - gy); + + // ensure GridMap is loaded + const_cast(this)->EnsureGridCreated(GridPair(63-gx,63-gy)); + + if(GridMaps[gx][gy]) + return GridMaps[gx][gy]->terrain_type[(int)(lx)][(int)(ly)]; + else + return 0; + +} + +float Map::GetWaterLevel(float x, float y ) const +{ + //local x,y coords + float lx,ly; + int gx,gy; + + // half opt method + gx=(int)(32-x/SIZE_OF_GRIDS) ; //grid x + gy=(int)(32-y/SIZE_OF_GRIDS); //grid y + + lx=128*(32 -x/SIZE_OF_GRIDS - gx); + ly=128*(32 -y/SIZE_OF_GRIDS - gy); + + // ensure GridMap is loaded + const_cast(this)->EnsureGridCreated(GridPair(63-gx,63-gy)); + + if(GridMaps[gx][gy]) + return GridMaps[gx][gy]->liquid_level[(int)(lx)][(int)(ly)]; + else + return 0; +} + +uint32 Map::GetAreaId(uint16 areaflag,uint32 map_id) +{ + AreaTableEntry const *entry = GetAreaEntryByAreaFlagAndMap(areaflag,map_id); + + if (entry) + return entry->ID; + else + return 0; +} + +uint32 Map::GetZoneId(uint16 areaflag,uint32 map_id) +{ + AreaTableEntry const *entry = GetAreaEntryByAreaFlagAndMap(areaflag,map_id); + + if( entry ) + return ( entry->zone != 0 ) ? entry->zone : entry->ID; + else + return 0; +} + +bool Map::IsInWater(float x, float y, float pZ) const +{ + // This method is called too often to use vamps for that (4. parameter = false). + // The pZ pos is taken anyway for future use + float z = GetHeight(x,y,pZ,false); // use .map base surface height + + // underground or instance without vmap + if(z <= INVALID_HEIGHT) + return false; + + float water_z = GetWaterLevel(x,y); + uint8 flag = GetTerrainType(x,y); + return (z < (water_z-2)) && (flag & 0x01); +} + +bool Map::IsUnderWater(float x, float y, float z) const +{ + float water_z = GetWaterLevel(x,y); + uint8 flag = GetTerrainType(x,y); + return (z < (water_z-2)) && (flag & 0x01); +} + +bool Map::CheckGridIntegrity(Creature* c, bool moved) const +{ + Cell const& cur_cell = c->GetCurrentCell(); + + CellPair xy_val = MaNGOS::ComputeCellPair(c->GetPositionX(), c->GetPositionY()); + Cell xy_cell(xy_val); + if(xy_cell != cur_cell) + { + sLog.outError("ERROR: %s (GUID: %u) X: %f Y: %f (%s) in grid[%u,%u]cell[%u,%u] instead grid[%u,%u]cell[%u,%u]", + (c->GetTypeId()==TYPEID_PLAYER ? "Player" : "Creature"),c->GetGUIDLow(), + c->GetPositionX(),c->GetPositionY(),(moved ? "final" : "original"), + cur_cell.GridX(), cur_cell.GridY(), cur_cell.CellX(), cur_cell.CellY(), + xy_cell.GridX(), xy_cell.GridY(), xy_cell.CellX(), xy_cell.CellY()); + return true; // not crash at error, just output error in debug mode + } + + return true; +} + +const char* Map::GetMapName() const +{ + return i_mapEntry ? i_mapEntry->name[sWorld.GetDefaultDbcLocale()] : "UNNAMEDMAP\x0"; +} + +void Map::UpdateObjectVisibility( WorldObject* obj, Cell cell, CellPair cellpair) +{ + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + MaNGOS::VisibleChangesNotifier notifier(*obj); + TypeContainerVisitor player_notifier(notifier); + CellLock cell_lock(cell, cellpair); + cell_lock->Visit(cell_lock, player_notifier, *this); +} + +void Map::UpdatePlayerVisibility( Player* player, Cell cell, CellPair cellpair ) +{ + cell.data.Part.reserved = ALL_DISTRICT; + + MaNGOS::PlayerNotifier pl_notifier(*player); + TypeContainerVisitor player_notifier(pl_notifier); + + CellLock cell_lock(cell, cellpair); + cell_lock->Visit(cell_lock, player_notifier, *this); +} + +void Map::UpdateObjectsVisibilityFor( Player* player, Cell cell, CellPair cellpair ) +{ + MaNGOS::VisibleNotifier notifier(*player); + + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + TypeContainerVisitor world_notifier(notifier); + TypeContainerVisitor grid_notifier(notifier); + CellLock cell_lock(cell, cellpair); + cell_lock->Visit(cell_lock, world_notifier, *this); + cell_lock->Visit(cell_lock, grid_notifier, *this); + + // send data + notifier.Notify(); +} + +void Map::PlayerRelocationNotify( Player* player, Cell cell, CellPair cellpair ) +{ + CellLock cell_lock(cell, cellpair); + MaNGOS::PlayerRelocationNotifier relocationNotifier(*player); + cell.data.Part.reserved = ALL_DISTRICT; + + TypeContainerVisitor p2grid_relocation(relocationNotifier); + TypeContainerVisitor p2world_relocation(relocationNotifier); + + cell_lock->Visit(cell_lock, p2grid_relocation, *this); + cell_lock->Visit(cell_lock, p2world_relocation, *this); +} + +void Map::CreatureRelocationNotify(Creature *creature, Cell cell, CellPair cellpair) +{ + CellLock cell_lock(cell, cellpair); + MaNGOS::CreatureRelocationNotifier relocationNotifier(*creature); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); // not trigger load unloaded grids at notifier call + + TypeContainerVisitor c2world_relocation(relocationNotifier); + TypeContainerVisitor c2grid_relocation(relocationNotifier); + + cell_lock->Visit(cell_lock, c2world_relocation, *this); + cell_lock->Visit(cell_lock, c2grid_relocation, *this); +} + +void Map::SendInitSelf( Player * player ) +{ + sLog.outDetail("Creating player data for himself %u", player->GetGUIDLow()); + + UpdateData data; + + bool hasTransport = false; + + // attach to player data current transport data + if(Transport* transport = player->GetTransport()) + { + hasTransport = true; + transport->BuildCreateUpdateBlockForPlayer(&data, player); + } + + // build data for self presence in world at own client (one time for map) + player->BuildCreateUpdateBlockForPlayer(&data, player); + + // build other passengers at transport also (they always visible and marked as visible and will not send at visibility update at add to map + if(Transport* transport = player->GetTransport()) + { + for(Transport::PlayerSet::const_iterator itr = transport->GetPassengers().begin();itr!=transport->GetPassengers().end();++itr) + { + if(player!=(*itr) && player->HaveAtClient(*itr)) + { + hasTransport = true; + (*itr)->BuildCreateUpdateBlockForPlayer(&data, player); + } + } + } + + WorldPacket packet; + data.BuildPacket(&packet, hasTransport); + player->GetSession()->SendPacket(&packet); +} + +void Map::SendInitTransports( Player * player ) +{ + // Hack to send out transports + MapManager::TransportMap& tmap = MapManager::Instance().m_TransportsByMap; + + // no transports at map + if (tmap.find(player->GetMapId()) == tmap.end()) + return; + + UpdateData transData; + + MapManager::TransportSet& tset = tmap[player->GetMapId()]; + + bool hasTransport = false; + + for (MapManager::TransportSet::iterator i = tset.begin(); i != tset.end(); ++i) + { + if((*i) != player->GetTransport()) // send data for current transport in other place + { + hasTransport = true; + (*i)->BuildCreateUpdateBlockForPlayer(&transData, player); + } + } + + WorldPacket packet; + transData.BuildPacket(&packet, hasTransport); + player->GetSession()->SendPacket(&packet); +} + +void Map::SendRemoveTransports( Player * player ) +{ + // Hack to send out transports + MapManager::TransportMap& tmap = MapManager::Instance().m_TransportsByMap; + + // no transports at map + if (tmap.find(player->GetMapId()) == tmap.end()) + return; + + UpdateData transData; + + MapManager::TransportSet& tset = tmap[player->GetMapId()]; + + // except used transport + for (MapManager::TransportSet::iterator i = tset.begin(); i != tset.end(); ++i) + if(player->GetTransport() != (*i)) + (*i)->BuildOutOfRangeUpdateBlock(&transData); + + WorldPacket packet; + transData.BuildPacket(&packet); + player->GetSession()->SendPacket(&packet); +} + +inline void Map::setNGrid(NGridType *grid, uint32 x, uint32 y) +{ + if(x >= MAX_NUMBER_OF_GRIDS || y >= MAX_NUMBER_OF_GRIDS) + { + sLog.outError("map::setNGrid() Invalid grid coordinates found: %d, %d!",x,y); + assert(false); + } + i_grids[x][y] = grid; +} + +void Map::DoDelayedMovesAndRemoves() +{ + MoveAllCreaturesInMoveList(); + RemoveAllObjectsInRemoveList(); +} + +void Map::AddObjectToRemoveList(WorldObject *obj) +{ + assert(obj->GetMapId()==GetId() && obj->GetInstanceId()==GetInstanceId()); + + i_objectsToRemove.insert(obj); + //sLog.outDebug("Object (GUID: %u TypeId: %u ) added to removing list.",obj->GetGUIDLow(),obj->GetTypeId()); +} + +void Map::RemoveAllObjectsInRemoveList() +{ + if(i_objectsToRemove.empty()) + return; + + //sLog.outDebug("Object remover 1 check."); + while(!i_objectsToRemove.empty()) + { + WorldObject* obj = *i_objectsToRemove.begin(); + i_objectsToRemove.erase(i_objectsToRemove.begin()); + + switch(obj->GetTypeId()) + { + case TYPEID_CORPSE: + { + Corpse* corpse = ObjectAccessor::Instance().GetCorpse(*obj, obj->GetGUID()); + if (!corpse) + sLog.outError("ERROR: Try delete corpse/bones %u that not in map", obj->GetGUIDLow()); + else + Remove(corpse,true); + break; + } + case TYPEID_DYNAMICOBJECT: + Remove((DynamicObject*)obj,true); + break; + case TYPEID_GAMEOBJECT: + Remove((GameObject*)obj,true); + break; + case TYPEID_UNIT: + Remove((Creature*)obj,true); + break; + default: + sLog.outError("Non-grid object (TypeId: %u) in grid object removing list, ignored.",obj->GetTypeId()); + break; + } + } + //sLog.outDebug("Object remover 2 check."); +} + +bool Map::CanUnload(const uint32 &diff) +{ + if(!m_unloadTimer) return false; + if(m_unloadTimer < diff) return true; + m_unloadTimer -= diff; + return false; +} + +template void Map::Add(Corpse *); +template void Map::Add(Creature *); +template void Map::Add(GameObject *); +template void Map::Add(DynamicObject *); + +template void Map::Remove(Corpse *,bool); +template void Map::Remove(Creature *,bool); +template void Map::Remove(GameObject *, bool); +template void Map::Remove(DynamicObject *, bool); + +/* ******* Dungeon Instance Maps ******* */ + +InstanceMap::InstanceMap(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode) + : Map(id, expiry, InstanceId, SpawnMode), i_data(NULL), + m_resetAfterUnload(false), m_unloadWhenEmpty(false) +{ + // the timer is started by default, and stopped when the first player joins + // this make sure it gets unloaded if for some reason no player joins + m_unloadTimer = std::max(sWorld.getConfig(CONFIG_INSTANCE_UNLOAD_DELAY), (uint32)MIN_UNLOAD_DELAY); +} + +InstanceMap::~InstanceMap() +{ + if(i_data) + { + delete i_data; + i_data = NULL; + } +} + +/* + Do map specific checks to see if the player can enter +*/ +bool InstanceMap::CanEnter(Player *player) +{ + if(std::find(i_Players.begin(),i_Players.end(),player)!=i_Players.end()) + { + sLog.outError("InstanceMap::CanEnter - player %s(%u) already in map %d,%d,%d!", player->GetName(), player->GetGUIDLow(), GetId(), GetInstanceId(), GetSpawnMode()); + assert(false); + return false; + } + + // cannot enter if the instance is full (player cap), GMs don't count + InstanceTemplate const* iTemplate = objmgr.GetInstanceTemplate(GetId()); + if (!player->isGameMaster() && GetPlayersCountExceptGMs() >= iTemplate->maxPlayers) + { + sLog.outDetail("MAP: Instance '%u' of map '%s' cannot have more than '%u' players. Player '%s' rejected", GetInstanceId(), GetMapName(), iTemplate->maxPlayers, player->GetName()); + player->SendTransferAborted(GetId(), TRANSFER_ABORT_MAX_PLAYERS); + return false; + } + + // cannot enter while players in the instance are in combat + Group *pGroup = player->GetGroup(); + if(pGroup && pGroup->InCombatToInstance(GetInstanceId()) && player->isAlive() && player->GetMapId() != GetId()) + { + player->SendTransferAborted(GetId(), TRANSFER_ABORT_ZONE_IN_COMBAT); + return false; + } + + return Map::CanEnter(player); +} + +/* + Do map specific checks and add the player to the map if successful. +*/ +bool InstanceMap::Add(Player *player) +{ + // TODO: Not sure about checking player level: already done in HandleAreaTriggerOpcode + // GMs still can teleport player in instance. + // Is it needed? + + { + Guard guard(*this); + if(!CanEnter(player)) + return false; + + // get or create an instance save for the map + InstanceSave *mapSave = sInstanceSaveManager.GetInstanceSave(GetInstanceId()); + if(!mapSave) + { + sLog.outDetail("InstanceMap::Add: creating instance save for map %d spawnmode %d with instance id %d", GetId(), GetSpawnMode(), GetInstanceId()); + mapSave = sInstanceSaveManager.AddInstanceSave(GetId(), GetInstanceId(), GetSpawnMode(), 0, true); + } + + // check for existing instance binds + InstancePlayerBind *playerBind = player->GetBoundInstance(GetId(), GetSpawnMode()); + if(playerBind && playerBind->perm) + { + // cannot enter other instances if bound permanently + if(playerBind->save != mapSave) + { + sLog.outError("InstanceMap::Add: player %s(%d) is permanently bound to instance %d,%d,%d,%d,%d,%d but he is being put in instance %d,%d,%d,%d,%d,%d", player->GetName(), player->GetGUIDLow(), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset()); + assert(false); + } + } + else + { + Group *pGroup = player->GetGroup(); + if(pGroup) + { + // solo saves should be reset when entering a group + InstanceGroupBind *groupBind = pGroup->GetBoundInstance(GetId(), GetSpawnMode()); + if(playerBind) + { + sLog.outError("InstanceMap::Add: player %s(%d) is being put in instance %d,%d,%d,%d,%d,%d but he is in group %d and is bound to instance %d,%d,%d,%d,%d,%d!", player->GetName(), player->GetGUIDLow(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset(), GUID_LOPART(pGroup->GetLeaderGUID()), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset()); + if(groupBind) sLog.outError("InstanceMap::Add: the group is bound to instance %d,%d,%d,%d,%d,%d", groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty(), groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount(), groupBind->save->CanReset()); + assert(false); + } + // bind to the group or keep using the group save + if(!groupBind) + pGroup->BindToInstance(mapSave, false); + else + { + // cannot jump to a different instance without resetting it + if(groupBind->save != mapSave) + { + sLog.outError("InstanceMap::Add: player %s(%d) is being put in instance %d,%d,%d but he is in group %d which is bound to instance %d,%d,%d!", player->GetName(), player->GetGUIDLow(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), GUID_LOPART(pGroup->GetLeaderGUID()), groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty()); + if(mapSave) + sLog.outError("MapSave players: %d, group count: %d", mapSave->GetPlayerCount(), mapSave->GetGroupCount()); + else + sLog.outError("MapSave NULL"); + if(groupBind->save) + sLog.outError("GroupBind save players: %d, group count: %d", groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount()); + else + sLog.outError("GroupBind save NULL"); + assert(false); + } + // if the group/leader is permanently bound to the instance + // players also become permanently bound when they enter + if(groupBind->perm) + { + WorldPacket data(SMSG_INSTANCE_SAVE_CREATED, 4); + data << uint32(0); + player->GetSession()->SendPacket(&data); + player->BindToInstance(mapSave, true); + } + } + } + else + { + // set up a solo bind or continue using it + if(!playerBind) + player->BindToInstance(mapSave, false); + else + // cannot jump to a different instance without resetting it + assert(playerBind->save == mapSave); + } + } + + if(i_data) i_data->OnPlayerEnter(player); + SetResetSchedule(false); + + i_Players.push_back(player); + player->SendInitWorldStates(); + sLog.outDetail("MAP: Player '%s' entered the instance '%u' of map '%s'", player->GetName(), GetInstanceId(), GetMapName()); + // initialize unload state + m_unloadTimer = 0; + m_resetAfterUnload = false; + m_unloadWhenEmpty = false; + } + + // this will acquire the same mutex so it cannot be in the previous block + Map::Add(player); + return true; +} + +void InstanceMap::Remove(Player *player, bool remove) +{ + sLog.outDetail("MAP: Removing player '%s' from instance '%u' of map '%s' before relocating to other map", player->GetName(), GetInstanceId(), GetMapName()); + i_Players.remove(player); + SetResetSchedule(true); + if(!m_unloadTimer && i_Players.empty()) + m_unloadTimer = m_unloadWhenEmpty ? MIN_UNLOAD_DELAY : std::max(sWorld.getConfig(CONFIG_INSTANCE_UNLOAD_DELAY), (uint32)MIN_UNLOAD_DELAY); + Map::Remove(player, remove); +} + +void InstanceMap::CreateInstanceData(bool load) +{ + if(i_data != NULL) + return; + + InstanceTemplate const* mInstance = objmgr.GetInstanceTemplate(GetId()); + if (mInstance) + { + i_script = mInstance->script; + i_data = Script->CreateInstanceData(this); + } + + if(!i_data) + return; + + if(load) + { + // TODO: make a global storage for this + QueryResult* result = CharacterDatabase.PQuery("SELECT data FROM instance WHERE map = '%u' AND id = '%u'", GetId(), i_InstanceId); + if (result) + { + Field* fields = result->Fetch(); + const char* data = fields[0].GetString(); + if(data) + { + sLog.outDebug("Loading instance data for `%s` with id %u", i_script.c_str(), i_InstanceId); + i_data->Load(data); + } + delete result; + } + } + else + { + sLog.outDebug("New instance data, \"%s\" ,initialized!",i_script.c_str()); + i_data->Initialize(); + } +} + +/* + Returns true if there are no players in the instance +*/ +bool InstanceMap::Reset(uint8 method) +{ + // note: since the map may not be loaded when the instance needs to be reset + // the instance must be deleted from the DB by InstanceSaveManager + + if(!i_Players.empty()) + { + if(method == INSTANCE_RESET_ALL) + { + // notify the players to leave the instance so it can be reset + for(PlayerList::iterator itr = i_Players.begin(); itr != i_Players.end(); ++itr) + (*itr)->SendResetFailedNotify(GetId()); + } + else + { + if(method == INSTANCE_RESET_GLOBAL) + { + // set the homebind timer for players inside (1 minute) + for(PlayerList::iterator itr = i_Players.begin(); itr != i_Players.end(); ++itr) + (*itr)->m_InstanceValid = false; + } + + // the unload timer is not started + // instead the map will unload immediately after the players have left + m_unloadWhenEmpty = true; + m_resetAfterUnload = true; + } + } + else + { + // unloaded at next update + m_unloadTimer = MIN_UNLOAD_DELAY; + m_resetAfterUnload = true; + } + + return i_Players.empty(); +} + +uint32 InstanceMap::GetPlayersCountExceptGMs() const +{ + uint32 count = 0; + for(PlayerList::const_iterator itr = i_Players.begin(); itr != i_Players.end(); ++itr) + if(!(*itr)->isGameMaster()) + ++count; + return count; +} + +void InstanceMap::PermBindAllPlayers(Player *player) +{ + InstanceSave *save = sInstanceSaveManager.GetInstanceSave(GetInstanceId()); + if(!save) + { + sLog.outError("Cannot bind players, no instance save available for map!\n"); + return; + } + + Group *group = player->GetGroup(); + // group members outside the instance group don't get bound + for(PlayerList::iterator itr = i_Players.begin(); itr != i_Players.end(); ++itr) + { + if(*itr) + { + // players inside an instance cannot be bound to other instances + // some players may already be permanently bound, in this case nothing happens + InstancePlayerBind *bind = (*itr)->GetBoundInstance(save->GetMapId(), save->GetDifficulty()); + if(!bind || !bind->perm) + { + (*itr)->BindToInstance(save, true); + WorldPacket data(SMSG_INSTANCE_SAVE_CREATED, 4); + data << uint32(0); + (*itr)->GetSession()->SendPacket(&data); + } + + // if the leader is not in the instance the group will not get a perm bind + if(group && group->GetLeaderGUID() == (*itr)->GetGUID()) + group->BindToInstance(save, true); + } + } +} + +time_t InstanceMap::GetResetTime() +{ + InstanceSave *save = sInstanceSaveManager.GetInstanceSave(GetInstanceId()); + return save ? save->GetDifficulty() : DIFFICULTY_NORMAL; +} + +void InstanceMap::UnloadAll(bool pForce) +{ + if(!i_Players.empty()) + { + sLog.outError("InstanceMap::UnloadAll: there are still players in the instance at unload, should not happen!"); + for(PlayerList::iterator itr = i_Players.begin(); itr != i_Players.end(); ++itr) + if(*itr) (*itr)->TeleportTo((*itr)->m_homebindMapId, (*itr)->m_homebindX, (*itr)->m_homebindY, (*itr)->m_homebindZ, (*itr)->GetOrientation()); + } + + if(m_resetAfterUnload == true) + objmgr.DeleteRespawnTimeForInstance(GetInstanceId()); + + Map::UnloadAll(pForce); +} + +void InstanceMap::SendResetWarnings(uint32 timeLeft) +{ + for(PlayerList::iterator itr = i_Players.begin(); itr != i_Players.end(); ++itr) + (*itr)->SendInstanceResetWarning(GetId(), timeLeft); +} + +void InstanceMap::SetResetSchedule(bool on) +{ + // only for normal instances + // the reset time is only scheduled when there are no payers inside + // it is assumed that the reset time will rarely (if ever) change while the reset is scheduled + if(i_Players.empty() && !IsRaid() && !IsHeroic()) + { + InstanceSave *save = sInstanceSaveManager.GetInstanceSave(GetInstanceId()); + if(!save) sLog.outError("InstanceMap::SetResetSchedule: cannot turn schedule %s, no save available for instance %d of %d", on ? "on" : "off", GetInstanceId(), GetId()); + else sInstanceSaveManager.ScheduleReset(on, save->GetResetTime(), InstanceSaveManager::InstResetEvent(0, GetId(), GetInstanceId())); + } +} + +void InstanceMap::SendToPlayers(WorldPacket const* data) const +{ + for(PlayerList::const_iterator itr = i_Players.begin(); itr != i_Players.end(); ++itr) + (*itr)->GetSession()->SendPacket(data); +} + +/* ******* Battleground Instance Maps ******* */ + +BattleGroundMap::BattleGroundMap(uint32 id, time_t expiry, uint32 InstanceId) + : Map(id, expiry, InstanceId, DIFFICULTY_NORMAL) +{ +} + +BattleGroundMap::~BattleGroundMap() +{ +} + +bool BattleGroundMap::CanEnter(Player * player) +{ + if(std::find(i_Players.begin(),i_Players.end(),player)!=i_Players.end()) + { + sLog.outError("BGMap::CanEnter - player %u already in map!", player->GetGUIDLow()); + assert(false); + return false; + } + + if(player->GetBattleGroundId() != GetInstanceId()) + return false; + + // player number limit is checked in bgmgr, no need to do it here + + return Map::CanEnter(player); +} + +bool BattleGroundMap::Add(Player * player) +{ + { + Guard guard(*this); + if(!CanEnter(player)) + return false; + i_Players.push_back(player); + // reset instance validity, battleground maps do not homebind + player->m_InstanceValid = true; + } + return Map::Add(player); +} + +void BattleGroundMap::Remove(Player *player, bool remove) +{ + sLog.outDetail("MAP: Removing player '%s' from bg '%u' of map '%s' before relocating to other map", player->GetName(), GetInstanceId(), GetMapName()); + i_Players.remove(player); + Map::Remove(player, remove); +} + +void BattleGroundMap::SetUnload() +{ + m_unloadTimer = MIN_UNLOAD_DELAY; +} + +void BattleGroundMap::UnloadAll(bool pForce) +{ + while(!i_Players.empty()) + { + PlayerList::iterator itr = i_Players.begin(); + Player * plr = *itr; + if(plr) (plr)->TeleportTo((*itr)->m_homebindMapId, (*itr)->m_homebindX, (*itr)->m_homebindY, (*itr)->m_homebindZ, (*itr)->GetOrientation()); + // TeleportTo removes the player from this map (if the map exists) -> calls BattleGroundMap::Remove -> invalidates the iterator. + // just in case, remove the player from the list explicitly here as well to prevent a possible infinite loop + // note that this remove is not needed if the code works well in other places + i_Players.remove(plr); + } + + Map::UnloadAll(pForce); +} diff --git a/src/game/Map.h b/src/game/Map.h new file mode 100644 index 00000000000..bc723e4bca5 --- /dev/null +++ b/src/game/Map.h @@ -0,0 +1,396 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_MAP_H +#define MANGOS_MAP_H + +#include "Platform/Define.h" +#include "Policies/ThreadingModel.h" +#include "zthread/Lockable.h" +#include "zthread/Mutex.h" +#include "zthread/FairReadWriteLock.h" +#include "Database/DBCStructure.h" +#include "GridDefines.h" +#include "Cell.h" +#include "Object.h" +#include "Timer.h" +#include "SharedDefines.h" +#include "GameSystem/GridRefManager.h" + +#include +#include + +class Unit; +class WorldPacket; +class InstanceData; +class Group; +class InstanceSave; + +namespace ZThread +{ + class Lockable; + class ReadWriteLock; +} + +typedef ZThread::FairReadWriteLock GridRWLock; + +template +struct RGuard +{ + RGuard(MUTEX &l) : i_lock(l.getReadLock()) {} + MaNGOS::GeneralLock i_lock; +}; + +template +struct WGuard +{ + WGuard(MUTEX &l) : i_lock(l.getWriteLock()) {} + MaNGOS::GeneralLock i_lock; +}; + +typedef RGuard GridReadGuard; +typedef WGuard GridWriteGuard; +typedef MaNGOS::SingleThreaded::Lock NullGuard; + +typedef struct +{ + uint16 area_flag[16][16]; + uint8 terrain_type[16][16]; + float liquid_level[128][128]; + float Z[MAP_RESOLUTION][MAP_RESOLUTION]; +}GridMap; + +struct CreatureMover +{ + CreatureMover() : x(0), y(0), z(0), ang(0) {} + CreatureMover(float _x, float _y, float _z, float _ang) : x(_x), y(_y), z(_z), ang(_ang) {} + + float x, y, z, ang; +}; + +// GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push,N), also any gcc version not support it at some platform +#if defined( __GNUC__ ) +#pragma pack(1) +#else +#pragma pack(push,1) +#endif + +struct InstanceTemplate +{ + uint32 map; + uint32 parent; + uint32 levelMin; + uint32 levelMax; + uint32 maxPlayers; + uint32 reset_delay; + float startLocX; + float startLocY; + float startLocZ; + float startLocO; + char const* script; +}; + +enum LevelRequirementVsMode +{ + LEVELREQUIREMENT_HEROIC = 70 +}; + +#if defined( __GNUC__ ) +#pragma pack() +#else +#pragma pack(pop) +#endif + +typedef HM_NAMESPACE::hash_map CreatureMoveList; + +#define MAX_HEIGHT 100000.0f // can be use for find ground height at surface +#define INVALID_HEIGHT -100000.0f // for check, must be equal to VMAP_INVALID_HEIGHT, real value for unknown height is VMAP_INVALID_HEIGHT_VALUE +#define MIN_UNLOAD_DELAY 1 // immediate unload + +class MANGOS_DLL_SPEC Map : public GridRefManager, public MaNGOS::ObjectLevelLockable +{ + public: + Map(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode); + virtual ~Map(); + + // currently unused for normal maps + virtual bool CanUnload(const uint32& diff); + + virtual bool Add(Player *); + virtual void Remove(Player *, bool); + template void Add(T *); + template void Remove(T *, bool); + + virtual void Update(const uint32&); + + void MessageBroadcast(Player *, WorldPacket *, bool to_self); + void MessageBroadcast(WorldObject *, WorldPacket *); + void MessageDistBroadcast(Player *, WorldPacket *, float dist, bool to_self, bool own_team_only = false); + void MessageDistBroadcast(WorldObject *, WorldPacket *, float dist); + + void PlayerRelocation(Player *, float x, float y, float z, float angl); + void CreatureRelocation(Creature *creature, float x, float y, float, float); + + template void Visit(const CellLock &cell, TypeContainerVisitor &visitor); + + inline bool IsRemovalGrid(float x, float y) const + { + GridPair p = MaNGOS::ComputeGridPair(x, y); + return( !getNGrid(p.x_coord, p.y_coord) || getNGrid(p.x_coord, p.y_coord)->GetGridState() == GRID_STATE_REMOVAL ); + } + + bool GetUnloadFlag(const GridPair &p) const { return getNGrid(p.x_coord, p.y_coord)->getUnloadFlag(); } + void SetUnloadFlag(const GridPair &p, bool unload) { getNGrid(p.x_coord, p.y_coord)->setUnloadFlag(unload); } + void LoadGrid(const Cell& cell, bool no_unload = false); + bool UnloadGrid(const uint32 &x, const uint32 &y, bool pForce); + virtual void UnloadAll(bool pForce); + + void ResetGridExpiry(NGridType &grid, float factor = 1) const + { + grid.ResetTimeTracker((time_t)((float)i_gridExpiry*factor)); + } + + time_t GetGridExpiry(void) const { return i_gridExpiry; } + uint32 GetId(void) const { return i_id; } + + static bool ExistMap(uint32 mapid, int x, int y); + static bool ExistVMap(uint32 mapid, int x, int y); + void LoadMapAndVMap(uint32 mapid, uint32 instanceid, int x, int y); + + static void InitStateMachine(); + static void DeleteStateMachine(); + + // some calls like isInWater should not use vmaps due to processor power + // can return INVALID_HEIGHT if under z+2 z coord not found height + float GetHeight(float x, float y, float z, bool pCheckVMap=true) const; + bool IsInWater(float x, float y, float z) const; // does not use z pos. This is for future use + + uint16 GetAreaFlag(float x, float y ) const; + uint8 GetTerrainType(float x, float y ) const; + float GetWaterLevel(float x, float y ) const; + bool IsUnderWater(float x, float y, float z) const; + + static uint32 GetAreaId(uint16 areaflag,uint32 map_id); + static uint32 GetZoneId(uint16 areaflag,uint32 map_id); + + uint32 GetAreaId(float x, float y) const + { + return GetAreaId(GetAreaFlag(x,y),i_id); + } + + uint32 GetZoneId(float x, float y) const + { + return GetZoneId(GetAreaFlag(x,y),i_id); + } + + virtual void MoveAllCreaturesInMoveList(); + virtual void RemoveAllObjectsInRemoveList(); + + bool CreatureRespawnRelocation(Creature *c); // used only in MoveAllCreaturesInMoveList and ObjectGridUnloader + + // assert print helper + bool CheckGridIntegrity(Creature* c, bool moved) const; + + uint32 GetInstanceId() { return i_InstanceId; } + uint8 GetSpawnMode() { return (i_spawnMode); } + virtual bool CanEnter(Player* /*player*/) { return true; } + const char* GetMapName() const; + + bool Instanceable() const { return i_mapEntry && i_mapEntry->Instanceable(); } + // NOTE: this duplicate of Instanceable(), but Instanceable() can be changed when BG also will be instanceable + bool IsDungeon() const { return i_mapEntry && i_mapEntry->IsDungeon(); } + bool IsRaid() const { return i_mapEntry && i_mapEntry->IsRaid(); } + bool IsHeroic() const { return i_spawnMode == DIFFICULTY_HEROIC; } + bool IsBattleGround() const { return i_mapEntry && i_mapEntry->IsBattleGround(); } + bool IsBattleArena() const { return i_mapEntry && i_mapEntry->IsBattleArena(); } + bool IsBattleGroundOrArena() const { return i_mapEntry && i_mapEntry->IsBattleGroundOrArena(); } + + void AddObjectToRemoveList(WorldObject *obj); + void DoDelayedMovesAndRemoves(); + + virtual bool RemoveBones(uint64 guid, float x, float y); + + void UpdateObjectVisibility(WorldObject* obj, Cell cell, CellPair cellpair); + void UpdatePlayerVisibility(Player* player, Cell cell, CellPair cellpair); + void UpdateObjectsVisibilityFor(Player* player, Cell cell, CellPair cellpair); + + void resetMarkedCells() { marked_cells.reset(); } + bool isCellMarked(uint32 pCellId) { return marked_cells.test(pCellId); } + void markCell(uint32 pCellId) { marked_cells.set(pCellId); } + private: + void LoadVMap(int pX, int pY); + void LoadMap(uint32 mapid, uint32 instanceid, int x,int y); + + void SetTimer(uint32 t) { i_gridExpiry = t < MIN_GRID_DELAY ? MIN_GRID_DELAY : t; } + //uint64 CalculateGridMask(const uint32 &y) const; + + void SendInitSelf( Player * player ); + + void SendInitTransports( Player * player ); + void SendRemoveTransports( Player * player ); + + void PlayerRelocationNotify(Player* player, Cell cell, CellPair cellpair); + void CreatureRelocationNotify(Creature *creature, Cell newcell, CellPair newval); + + bool CreatureCellRelocation(Creature *creature, Cell new_cell); + + void AddCreatureToMoveList(Creature *c, float x, float y, float z, float ang); + CreatureMoveList i_creaturesToMove; + + bool loaded(const GridPair &) const; + void EnsureGridLoadedForPlayer(const Cell&, Player*, bool add_player); + void EnsureGridCreated(const GridPair &); + + void buildNGridLinkage(NGridType* pNGridType) { pNGridType->link(this); } + + template void AddType(T *obj); + template void RemoveType(T *obj, bool); + + NGridType* getNGrid(uint32 x, uint32 y) const + { + return i_grids[x][y]; + } + + bool isGridObjectDataLoaded(uint32 x, uint32 y) const { return getNGrid(x,y)->isGridObjectDataLoaded(); } + void setGridObjectDataLoaded(bool pLoaded, uint32 x, uint32 y) { getNGrid(x,y)->setGridObjectDataLoaded(pLoaded); } + + inline void setNGrid(NGridType* grid, uint32 x, uint32 y); + + protected: + typedef MaNGOS::ObjectLevelLockable::Lock Guard; + + MapEntry const* i_mapEntry; + uint8 i_spawnMode; + uint32 i_id; + uint32 i_InstanceId; + uint32 m_unloadTimer; + + private: + typedef GridReadGuard ReadGuard; + typedef GridWriteGuard WriteGuard; + + NGridType* i_grids[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]; + GridMap *GridMaps[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]; + std::bitset marked_cells; + + time_t i_gridExpiry; + + std::set i_objectsToRemove; + + // Type specific code for add/remove to/from grid + template + void AddToGrid(T*, NGridType *, Cell const&); + + template + void AddNotifier(T*, Cell const&, CellPair const&); + + template + void RemoveFromGrid(T*, NGridType *, Cell const&); + + template + void DeleteFromWorld(T*); +}; + +enum InstanceResetMethod +{ + INSTANCE_RESET_ALL, + INSTANCE_RESET_CHANGE_DIFFICULTY, + INSTANCE_RESET_GLOBAL, + INSTANCE_RESET_GROUP_DISBAND, + INSTANCE_RESET_GROUP_JOIN, + INSTANCE_RESET_RESPAWN_DELAY +}; + +class MANGOS_DLL_SPEC InstanceMap : public Map +{ + public: + typedef std::list PlayerList; // online players only + + InstanceMap(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode); + ~InstanceMap(); + bool Add(Player *); + void Remove(Player *, bool); + void Update(const uint32&); + void CreateInstanceData(bool load); + bool Reset(uint8 method); + std::string GetScript() { return i_script; } + InstanceData* GetInstanceData() { return i_data; } + void PermBindAllPlayers(Player *player); + PlayerList const& GetPlayers() const { return i_Players;} + void SendToPlayers(WorldPacket const* data) const; + time_t GetResetTime(); + void UnloadAll(bool pForce); + bool CanEnter(Player* player); + uint32 GetPlayersCountExceptGMs() const; + uint32 HavePlayers() const { return !i_Players.empty(); } + void SendResetWarnings(uint32 timeLeft); + void SetResetSchedule(bool on); + private: + bool m_resetAfterUnload; + bool m_unloadWhenEmpty; + InstanceData* i_data; + std::string i_script; + // only online players that are inside the instance currently + // TODO ? - use the grid instead to access the players + PlayerList i_Players; +}; + +class MANGOS_DLL_SPEC BattleGroundMap : public Map +{ + public: + typedef std::list PlayerList; // online players only + + BattleGroundMap(uint32 id, time_t, uint32 InstanceId); + ~BattleGroundMap(); + + bool Add(Player *); + void Remove(Player *, bool); + bool CanEnter(Player* player); + void SetUnload(); + void UnloadAll(bool pForce); + private: + PlayerList i_Players; +}; + +/*inline +uint64 +Map::CalculateGridMask(const uint32 &y) const +{ + uint64 mask = 1; + mask <<= y; + return mask; +} +*/ + +template +inline void +Map::Visit(const CellLock &cell, TypeContainerVisitor &visitor) +{ + const uint32 x = cell->GridX(); + const uint32 y = cell->GridY(); + const uint32 cell_x = cell->CellX(); + const uint32 cell_y = cell->CellY(); + + if( !cell->NoCreate() || loaded(GridPair(x,y)) ) + { + EnsureGridLoadedForPlayer(cell, NULL, false); + //LOCK_TYPE guard(i_info[x][y]->i_lock); + getNGrid(x, y)->Visit(cell_x, cell_y, visitor); + } +} +#endif diff --git a/src/game/MapInstanced.cpp b/src/game/MapInstanced.cpp new file mode 100644 index 00000000000..2ff105c2f9d --- /dev/null +++ b/src/game/MapInstanced.cpp @@ -0,0 +1,252 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "MapInstanced.h" +#include "ObjectMgr.h" +#include "MapManager.h" +#include "BattleGround.h" +#include "VMapFactory.h" +#include "InstanceSaveMgr.h" +#include "World.h" + +MapInstanced::MapInstanced(uint32 id, time_t expiry, uint32 aInstanceId) : Map(id, expiry, 0, 0) +{ + // initialize instanced maps list + m_InstancedMaps.clear(); + // fill with zero + memset(&GridMapReference, 0, MAX_NUMBER_OF_GRIDS*MAX_NUMBER_OF_GRIDS*sizeof(uint16)); +} + +void MapInstanced::Update(const uint32& t) +{ + // take care of loaded GridMaps (when unused, unload it!) + Map::Update(t); + + // update the instanced maps + InstancedMaps::iterator i = m_InstancedMaps.begin(); + + while (i != m_InstancedMaps.end()) + { + if(i->second->CanUnload(t)) + { + DestroyInstance(i); // iterator incremented + } + else + { + // update only here, because it may schedule some bad things before delete + i->second->Update(t); + ++i; + } + } +} + +void MapInstanced::MoveAllCreaturesInMoveList() +{ + for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); i++) + { + i->second->MoveAllCreaturesInMoveList(); + } + + Map::MoveAllCreaturesInMoveList(); +} + +void MapInstanced::RemoveAllObjectsInRemoveList() +{ + for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); i++) + { + i->second->RemoveAllObjectsInRemoveList(); + } + + Map::RemoveAllObjectsInRemoveList(); +} + +bool MapInstanced::RemoveBones(uint64 guid, float x, float y) +{ + bool remove_result = false; + + for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); i++) + { + remove_result = remove_result || i->second->RemoveBones(guid, x, y); + } + + return remove_result || Map::RemoveBones(guid,x,y); +} + +void MapInstanced::UnloadAll(bool pForce) +{ + // Unload instanced maps + for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); i++) + i->second->UnloadAll(pForce); + + // Delete the maps only after everything is unloaded to prevent crashes + for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); i++) + delete i->second; + + m_InstancedMaps.clear(); + + // Unload own grids (just dummy(placeholder) grids, neccesary to unload GridMaps!) + Map::UnloadAll(pForce); +} + +/* +- return the right instance for the object, based on its InstanceId +- create the instance if it's not created already +- the player is not actually added to the instance (only in InstanceMap::Add) +*/ +Map* MapInstanced::GetInstance(const WorldObject* obj) +{ + uint32 CurInstanceId = obj->GetInstanceId(); + Map* map = NULL; + + if (obj->GetMapId() == GetId() && CurInstanceId != 0) + { + // the object wants to be put in a certain instance of this map + map = _FindMap(CurInstanceId); + if(!map) + { + // For players if the instanceId is set, it's assumed they are already in a map, + // hence the map must be loaded. For Creatures, GameObjects etc the map must exist + // prior to calling GetMap, they are not allowed to create maps for themselves. + sLog.outError("GetInstance: object %s(%d), typeId %d, in world %d, should be in map %d,%d but that's not loaded yet.", obj->GetName(), obj->GetGUIDLow(), obj->GetTypeId(), obj->IsInWorld(), obj->GetMapId(), obj->GetInstanceId()); + assert(false); + } + return(map); + } + else + { + // instance not specified, find an existing or create a new one + if(obj->GetTypeId() != TYPEID_PLAYER) + { + sLog.outError("MAPINSTANCED: WorldObject '%u' (Entry: %u TypeID: %u) is in map %d,%d and requested base map instance of map %d, this must not happen", obj->GetGUIDLow(), obj->GetEntry(), obj->GetTypeId(), obj->GetMapId(), obj->GetInstanceId(), GetId()); + assert(false); + return NULL; + } + else + { + uint32 NewInstanceId = 0; // instanceId of the resulting map + Player* player = (Player*)obj; + + // TODO: battlegrounds and arenas + + InstancePlayerBind *pBind = player->GetBoundInstance(GetId(), player->GetDifficulty()); + InstanceSave *pSave = pBind ? pBind->save : NULL; + + // the player's permanet player bind is taken into consideration first + // then the player's group bind and finally the solo bind. + if(!pBind || !pBind->perm) + { + InstanceGroupBind *groupBind = NULL; + Group *group = player->GetGroup(); + // use the player's difficulty setting (it may not be the same as the group's) + if(group && (groupBind = group->GetBoundInstance(GetId(), player->GetDifficulty()))) + pSave = groupBind->save; + } + + if(pSave) + { + // solo/perm/group + NewInstanceId = pSave->GetInstanceId(); + map = _FindMap(NewInstanceId); + // it is possible that the save exists but the map doesn't + if(!map) + map = CreateInstance(NewInstanceId, pSave, pSave->GetDifficulty()); + return map; + } + else + { + // if no instanceId via group members or instance saves is found + // the instance will be created for the first time + NewInstanceId = MapManager::Instance().GenerateInstanceId(); + return CreateInstance(NewInstanceId, NULL, player->GetDifficulty()); + } + } + } +} + +InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave *save, uint8 difficulty) +{ + // load/create a map + Guard guard(*this); + + // make sure we have a valid map id + const MapEntry* entry = sMapStore.LookupEntry(GetId()); + if(!entry) + { + sLog.outError("CreateInstance: no entry for map %d", GetId()); + assert(false); + } + const InstanceTemplate * iTemplate = objmgr.GetInstanceTemplate(GetId()); + if(!iTemplate) + { + sLog.outError("CreateInstance: no instance template for map %d", GetId()); + assert(false); + } + + // some instances only have one difficulty + if(!entry->SupportsHeroicMode()) difficulty = DIFFICULTY_NORMAL; + + sLog.outDebug("MapInstanced::CreateInstance: %smap instance %d for %d created with difficulty %s", save?"":"new ", InstanceId, GetId(), difficulty?"heroic":"normal"); + + InstanceMap *map = new InstanceMap(GetId(), GetGridExpiry(), InstanceId, difficulty); + assert(map->IsDungeon()); + + bool load_data = save != NULL; + map->CreateInstanceData(load_data); + + m_InstancedMaps[InstanceId] = map; + return map; +} + +BattleGroundMap* MapInstanced::CreateBattleGround(uint32 InstanceId) +{ + // load/create a map + Guard guard(*this); + + sLog.outDebug("MapInstanced::CreateBattleGround: map bg %d for %d created.", InstanceId, GetId()); + + BattleGroundMap *map = new BattleGroundMap(GetId(), GetGridExpiry(), InstanceId); + assert(map->IsBattleGroundOrArena()); + + m_InstancedMaps[InstanceId] = map; + return map; +} + +void MapInstanced::DestroyInstance(uint32 InstanceId) +{ + InstancedMaps::iterator itr = m_InstancedMaps.find(InstanceId); + if(itr != m_InstancedMaps.end()) + DestroyInstance(itr); +} + +// increments the iterator after erase +void MapInstanced::DestroyInstance(InstancedMaps::iterator &itr) +{ + itr->second->UnloadAll(true); + // should only unload VMaps if this is the last instance and grid unloading is enabled + if(m_InstancedMaps.size() <= 1 && sWorld.getConfig(CONFIG_GRID_UNLOAD)) + { + VMAP::VMapFactory::createOrGetVMapManager()->unloadMap(itr->second->GetId()); + // in that case, unload grids of the base map, too + // so in the next map creation, (EnsureGridCreated actually) VMaps will be reloaded + Map::UnloadAll(true); + } + // erase map + delete itr->second; + m_InstancedMaps.erase(itr++); +} + diff --git a/src/game/MapInstanced.h b/src/game/MapInstanced.h new file mode 100644 index 00000000000..58ee6b7a9bc --- /dev/null +++ b/src/game/MapInstanced.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_MAP_INSTANCED_H +#define MANGOS_MAP_INSTANCED_H + +#include "Map.h" +#include "InstanceSaveMgr.h" + +class MANGOS_DLL_DECL MapInstanced : public Map +{ + friend class MapManager; + public: + typedef HM_NAMESPACE::hash_map< uint32, Map* > InstancedMaps; + + MapInstanced(uint32 id, time_t, uint32 aInstanceId); + ~MapInstanced() {} + + // functions overwrite Map versions + void Update(const uint32&); + void MoveAllCreaturesInMoveList(); + void RemoveAllObjectsInRemoveList(); + bool RemoveBones(uint64 guid, float x, float y); + void UnloadAll(bool pForce); + + Map* GetInstance(const WorldObject* obj); + Map* FindMap(uint32 InstanceId) { return _FindMap(InstanceId); } + void DestroyInstance(uint32 InstanceId); + void DestroyInstance(InstancedMaps::iterator &itr); + void AddGridMapReference(const GridPair &p) { ++GridMapReference[p.x_coord][p.y_coord]; } + void RemoveGridMapReference(const GridPair &p) + { + --GridMapReference[p.x_coord][p.y_coord]; + if (!GridMapReference[p.x_coord][p.y_coord]) { SetUnloadFlag(GridPair(63-p.x_coord,63-p.y_coord), true); } + } + + InstancedMaps &GetInstancedMaps() { return m_InstancedMaps; } + + private: + + InstanceMap* CreateInstance(uint32 InstanceId, InstanceSave *save, uint8 difficulty); + BattleGroundMap* CreateBattleGround(uint32 InstanceId); + + InstancedMaps m_InstancedMaps; + + Map* _FindMap(uint32 InstanceId) + { + InstancedMaps::iterator i = m_InstancedMaps.find(InstanceId); + + return(i == m_InstancedMaps.end() ? NULL : i->second); + } + + uint16 GridMapReference[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]; +}; +#endif diff --git a/src/game/MapManager.cpp b/src/game/MapManager.cpp new file mode 100644 index 00000000000..84c13333ddf --- /dev/null +++ b/src/game/MapManager.cpp @@ -0,0 +1,340 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "MapManager.h" +#include "InstanceSaveMgr.h" +#include "Policies/SingletonImp.h" +#include "Database/DatabaseEnv.h" +#include "Log.h" +#include "ObjectAccessor.h" +#include "Transports.h" +#include "GridDefines.h" +#include "MapInstanced.h" +#include "DestinationHolderImp.h" +#include "World.h" +#include "CellImpl.h" +#include "Corpse.h" +#include "ObjectMgr.h" + +#define CLASS_LOCK MaNGOS::ClassLevelLockable +INSTANTIATE_SINGLETON_2(MapManager, CLASS_LOCK); +INSTANTIATE_CLASS_MUTEX(MapManager, ZThread::Mutex); + +extern GridState* si_GridStates[]; // debugging code, should be deleted some day + +MapManager::MapManager() : i_gridCleanUpDelay(sWorld.getConfig(CONFIG_INTERVAL_GRIDCLEAN)) +{ + i_timer.SetInterval(sWorld.getConfig(CONFIG_INTERVAL_MAPUPDATE)); +} + +MapManager::~MapManager() +{ + for(MapMapType::iterator iter=i_maps.begin(); iter != i_maps.end(); ++iter) + delete iter->second; + + for(TransportSet::iterator i = m_Transports.begin(); i != m_Transports.end(); ++i) + delete *i; + + Map::DeleteStateMachine(); +} + +void +MapManager::Initialize() +{ + Map::InitStateMachine(); + + // debugging code, should be deleted some day + { + for(int i=0;icheckMagic()) + { + ok = false; + si_GridStates[i]->setMagic(); + } + #endif + } + if(!ok) + ++i_GridStateErrorCount; + if(i_GridStateErrorCount > 2) + assert(false); // force a crash. Too many errors +} + +Map* +MapManager::_GetBaseMap(uint32 id) +{ + Map *m = _findMap(id); + + if( m == NULL ) + { + Guard guard(*this); + + const MapEntry* entry = sMapStore.LookupEntry(id); + if (entry && entry->IsDungeon()) + { + m = new MapInstanced(id, i_gridCleanUpDelay, 0); + } + else + { + m = new Map(id, i_gridCleanUpDelay, 0, 0); + } + i_maps[id] = m; + } + + assert(m != NULL); + return m; +} + +Map* MapManager::GetMap(uint32 id, const WorldObject* obj) +{ + //if(!obj->IsInWorld()) sLog.outError("GetMap: called for map %d with object (typeid %d, guid %d, mapid %d, instanceid %d) who is not in world!", id, obj->GetTypeId(), obj->GetGUIDLow(), obj->GetMapId(), obj->GetInstanceId()); + Map *m = _GetBaseMap(id); + + if (m && obj && m->Instanceable()) m = ((MapInstanced*)m)->GetInstance(obj); + + return m; +} + +Map* MapManager::FindMap(uint32 mapid, uint32 instanceId) +{ + Map *map = FindMap(mapid); + if(!map) return NULL; + if(!map->Instanceable()) return instanceId == 0 ? map : NULL; + return ((MapInstanced*)map)->FindMap(instanceId); +} + +/* + checks that do not require a map to be created + will send transfer error messages on fail +*/ +bool MapManager::CanPlayerEnter(uint32 mapid, Player* player) +{ + const MapEntry *entry = sMapStore.LookupEntry(mapid); + if(!entry) return false; + const char *mapName = entry->name[player->GetSession()->GetSessionDbcLocale()]; + + if(entry->map_type == MAP_INSTANCE || entry->map_type == MAP_RAID) + { + if (entry->map_type == MAP_RAID) + { + // GMs can avoid raid limitations + if(!player->isGameMaster() && !sWorld.getConfig(CONFIG_INSTANCE_IGNORE_RAID)) + { + // can only enter in a raid group + Group* group = player->GetGroup(); + if (!group || !group->isRaidGroup()) + { + // probably there must be special opcode, because client has this string constant in GlobalStrings.lua + // TODO: this is not a good place to send the message + player->GetSession()->SendAreaTriggerMessage("You must be in a raid group to enter %s instance", mapName); + sLog.outDebug("MAP: Player '%s' must be in a raid group to enter instance of '%s'", player->GetName(), mapName); + return false; + } + } + } + + //The player has a heroic mode and tries to enter into instance which has no a heroic mode + if (!entry->SupportsHeroicMode() && player->GetDifficulty() == DIFFICULTY_HEROIC) + { + player->SendTransferAborted(mapid, TRANSFER_ABORT_DIFFICULTY2); //Send aborted message + return false; + } + + if (!player->isAlive()) + { + if(Corpse *corpse = player->GetCorpse()) + { + // let enter in ghost mode in instance that connected to inner instance with corpse + uint32 instance_map = corpse->GetMapId(); + do + { + if(instance_map==mapid) + break; + + InstanceTemplate const* instance = objmgr.GetInstanceTemplate(instance_map); + instance_map = instance ? instance->parent : 0; + } + while (instance_map); + + if (!instance_map) + { + player->GetSession()->SendAreaTriggerMessage("You cannot enter %s while in a ghost mode", mapName); + sLog.outDebug("MAP: Player '%s' doesn't has a corpse in instance '%s' and can't enter", player->GetName(), mapName); + return false; + } + sLog.outDebug("MAP: Player '%s' has corpse in instance '%s' and can enter", player->GetName(), mapName); + } + else + { + sLog.outDebug("Map::CanEnter - player '%s' is dead but doesn't have a corpse!", player->GetName()); + } + } + + // TODO: move this to a map dependent location + /*if(i_data && i_data->IsEncounterInProgress()) + { + sLog.outDebug("MAP: Player '%s' can't enter instance '%s' while an encounter is in progress.", player->GetName(), GetMapName()); + player->SendTransferAborted(GetId(), TRANSFER_ABORT_ZONE_IN_COMBAT); + return(false); + }*/ + return true; + } + else + return true; +} + +void MapManager::DeleteInstance(uint32 mapid, uint32 instanceId, uint8 mode) +{ + Map *m = _GetBaseMap(mapid); + if (m && m->Instanceable()) + ((MapInstanced*)m)->DestroyInstance(instanceId); +} + +void MapManager::RemoveBonesFromMap(uint32 mapid, uint64 guid, float x, float y) +{ + bool remove_result = _GetBaseMap(mapid)->RemoveBones(guid, x, y); + + if (!remove_result) + { + sLog.outDebug("Bones %u not found in world. Delete from DB also.", GUID_LOPART(guid)); + } +} + +void +MapManager::Update(time_t diff) +{ + i_timer.Update(diff); + if( !i_timer.Passed() ) + return; + + for(MapMapType::iterator iter=i_maps.begin(); iter != i_maps.end(); ++iter) + { + checkAndCorrectGridStatesArray(); // debugging code, should be deleted some day + iter->second->Update(i_timer.GetCurrent()); + } + + ObjectAccessor::Instance().Update(i_timer.GetCurrent()); + for (TransportSet::iterator iter = m_Transports.begin(); iter != m_Transports.end(); ++iter) + (*iter)->Update(i_timer.GetCurrent()); + + i_timer.SetCurrent(0); +} + +void MapManager::DoDelayedMovesAndRemoves() +{ + for(MapMapType::iterator iter=i_maps.begin(); iter != i_maps.end(); ++iter) + iter->second->DoDelayedMovesAndRemoves(); +} + +bool MapManager::ExistMapAndVMap(uint32 mapid, float x,float y) +{ + GridPair p = MaNGOS::ComputeGridPair(x,y); + + int gx=63-p.x_coord; + int gy=63-p.y_coord; + + return Map::ExistMap(mapid,gx,gy) && Map::ExistVMap(mapid,gx,gy); +} + +bool MapManager::IsValidMAP(uint32 mapid) +{ + MapEntry const* mEntry = sMapStore.LookupEntry(mapid); + return mEntry && (!mEntry->Instanceable() || objmgr.GetInstanceTemplate(mapid)); +} + +void MapManager::LoadGrid(int mapid, float x, float y, const WorldObject* obj, bool no_unload) +{ + CellPair p = MaNGOS::ComputeCellPair(x,y); + Cell cell(p); + GetMap(mapid, obj)->LoadGrid(cell,no_unload); +} + +void MapManager::UnloadAll() +{ + for(MapMapType::iterator iter=i_maps.begin(); iter != i_maps.end(); ++iter) + iter->second->UnloadAll(true); + + while(!i_maps.empty()) + { + delete i_maps.begin()->second; + i_maps.erase(i_maps.begin()); + } +} + +void MapManager::InitMaxInstanceId() +{ + i_MaxInstanceId = 0; + + QueryResult *result = CharacterDatabase.Query( "SELECT MAX(id) FROM instance" ); + if( result ) + { + i_MaxInstanceId = result->Fetch()[0].GetUInt32(); + delete result; + } +} + +uint32 MapManager::GetNumInstances() +{ + uint32 ret = 0; + for(MapMapType::iterator itr = i_maps.begin(); itr != i_maps.end(); ++itr) + { + Map *map = itr->second; + if(!map->Instanceable()) continue; + MapInstanced::InstancedMaps &maps = ((MapInstanced *)map)->GetInstancedMaps(); + for(MapInstanced::InstancedMaps::iterator mitr = maps.begin(); mitr != maps.end(); ++mitr) + if(mitr->second->IsDungeon()) ret++; + } + return ret; +} + +uint32 MapManager::GetNumPlayersInInstances() +{ + uint32 ret = 0; + for(MapMapType::iterator itr = i_maps.begin(); itr != i_maps.end(); ++itr) + { + Map *map = itr->second; + if(!map->Instanceable()) continue; + MapInstanced::InstancedMaps &maps = ((MapInstanced *)map)->GetInstancedMaps(); + for(MapInstanced::InstancedMaps::iterator mitr = maps.begin(); mitr != maps.end(); ++mitr) + if(mitr->second->IsDungeon()) + ret += ((InstanceMap*)mitr->second)->GetPlayers().size(); + } + return ret; +} diff --git a/src/game/MapManager.h b/src/game/MapManager.h new file mode 100644 index 00000000000..833f14dfc62 --- /dev/null +++ b/src/game/MapManager.h @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_MAPMANAGER_H +#define MANGOS_MAPMANAGER_H + +#include "Platform/Define.h" +#include "Policies/Singleton.h" +#include "zthread/Mutex.h" +#include "Common.h" +#include "Map.h" +#include "GridStates.h" +class Transport; + +class MANGOS_DLL_DECL MapManager : public MaNGOS::Singleton > +{ + + friend class MaNGOS::OperatorNew; + typedef HM_NAMESPACE::hash_map MapMapType; + typedef std::pair::iterator, bool> MapMapPair; + + public: + + Map* GetMap(uint32, const WorldObject* obj); + Map* FindMap(uint32 mapid) { return _findMap(mapid); } + Map* FindMap(uint32 mapid, uint32 instanceId); + + // only const version for outer users + Map const* GetBaseMap(uint32 id) const { return const_cast(this)->_GetBaseMap(id); } + void DeleteInstance(uint32 mapid, uint32 instanceId, uint8 mode); + + inline uint16 GetAreaFlag(uint32 mapid, float x, float y) const + { + Map const* m = GetBaseMap(mapid); + return m->GetAreaFlag(x, y); + } + inline uint32 GetAreaId(uint32 mapid, float x, float y) { return Map::GetAreaId(GetAreaFlag(mapid, x, y),mapid); } + inline uint32 GetZoneId(uint32 mapid, float x, float y) { return Map::GetZoneId(GetAreaFlag(mapid, x, y),mapid); } + + void Initialize(void); + void Update(time_t); + + inline void SetGridCleanUpDelay(uint32 t) + { + if( t < MIN_GRID_DELAY ) + i_gridCleanUpDelay = MIN_GRID_DELAY; + else + i_gridCleanUpDelay = t; + } + + inline void SetMapUpdateInterval(uint32 t) + { + if( t > MIN_MAP_UPDATE_DELAY ) + t = MIN_MAP_UPDATE_DELAY; + + i_timer.SetInterval(t); + i_timer.Reset(); + } + + void LoadGrid(int mapid, float x, float y, const WorldObject* obj, bool no_unload = false); + void UnloadAll(); + + static bool ExistMapAndVMap(uint32 mapid, float x, float y); + static bool IsValidMAP(uint32 mapid); + + static bool IsValidMapCoord(uint32 mapid, float x,float y) + { + return IsValidMAP(mapid) && MaNGOS::IsValidMapCoord(x,y); + } + + static bool IsValidMapCoord(uint32 mapid, float x,float y,float z) + { + return IsValidMAP(mapid) && MaNGOS::IsValidMapCoord(x,y,z); + } + + static bool IsValidMapCoord(uint32 mapid, float x,float y,float z,float o) + { + return IsValidMAP(mapid) && MaNGOS::IsValidMapCoord(x,y,z,o); + } + + void DoDelayedMovesAndRemoves(); + + void LoadTransports(); + + typedef std::set TransportSet; + TransportSet m_Transports; + + typedef std::map TransportMap; + TransportMap m_TransportsByMap; + + bool CanPlayerEnter(uint32 mapid, Player* player); + void RemoveBonesFromMap(uint32 mapid, uint64 guid, float x, float y); + inline uint32 GenerateInstanceId() { return ++i_MaxInstanceId; } + void InitMaxInstanceId(); + + /* statistics */ + uint32 GetNumInstances(); + uint32 GetNumPlayersInInstances(); + + private: + // debugging code, should be deleted some day + void checkAndCorrectGridStatesArray(); // just for debugging to find some memory overwrites + GridState* i_GridStates[MAX_GRID_STATE]; // shadow entries to the global array in Map.cpp + int i_GridStateErrorCount; + private: + MapManager(); + ~MapManager(); + + MapManager(const MapManager &); + MapManager& operator=(const MapManager &); + + Map* _GetBaseMap(uint32 id); + Map* _findMap(uint32 id) const + { + MapMapType::const_iterator iter = i_maps.find(id); + return (iter == i_maps.end() ? NULL : iter->second); + } + + typedef MaNGOS::ClassLevelLockable::Lock Guard; + uint32 i_gridCleanUpDelay; + MapMapType i_maps; + IntervalTimer i_timer; + + uint32 i_MaxInstanceId; +}; +#endif diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp new file mode 100644 index 00000000000..092795c6fbe --- /dev/null +++ b/src/game/MiscHandler.cpp @@ -0,0 +1,1761 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Language.h" +#include "Database/DatabaseEnv.h" +#include "WorldPacket.h" +#include "Opcodes.h" +#include "Log.h" +#include "Player.h" +#include "World.h" +#include "ObjectMgr.h" +#include "WorldSession.h" +#include "Auth/BigNumber.h" +#include "Auth/Sha1.h" +#include "UpdateData.h" +#include "LootMgr.h" +#include "Chat.h" +#include "ScriptCalls.h" +#include +#include "MapManager.h" +#include "ObjectAccessor.h" +#include "Object.h" +#include "BattleGround.h" +#include "SpellAuras.h" +#include "Pet.h" +#include "SocialMgr.h" + +void WorldSession::HandleRepopRequestOpcode( WorldPacket & /*recv_data*/ ) +{ + sLog.outDebug( "WORLD: Recvd CMSG_REPOP_REQUEST Message" ); + + if(GetPlayer()->isAlive()||GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) + return; + + // the world update order is sessions, players, creatures + // the netcode runs in parallel with all of these + // creatures can kill players + // so if the server is lagging enough the player can + // release spirit after he's killed but before he is updated + if(GetPlayer()->getDeathState() == JUST_DIED) + { + sLog.outDebug("HandleRepopRequestOpcode: got request after player %s(%d) was killed and before he was updated", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow()); + GetPlayer()->KillPlayer(); + } + + //this is spirit release confirm? + GetPlayer()->RemovePet(NULL,PET_SAVE_NOT_IN_SLOT, true); + GetPlayer()->BuildPlayerRepop(); + GetPlayer()->RepopAtGraveyard(); +} + +void WorldSession::HandleWhoOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,4+4+1+1+4+4+4+4); + + sLog.outDebug( "WORLD: Recvd CMSG_WHO Message" ); + //recv_data.hexlike(); + + uint32 clientcount = 0; + + uint32 level_min, level_max, racemask, classmask, zones_count, str_count; + uint32 zoneids[10]; // 10 is client limit + std::string player_name, guild_name; + + recv_data >> level_min; // maximal player level, default 0 + recv_data >> level_max; // minimal player level, default 100 + recv_data >> player_name; // player name, case sensitive... + + // recheck + CHECK_PACKET_SIZE(recv_data,4+4+(player_name.size()+1)+1+4+4+4+4); + + recv_data >> guild_name; // guild name, case sensitive... + + // recheck + CHECK_PACKET_SIZE(recv_data,4+4+(player_name.size()+1)+(guild_name.size()+1)+4+4+4+4); + + recv_data >> racemask; // race mask + recv_data >> classmask; // class mask + recv_data >> zones_count; // zones count, client limit=10 (2.0.10) + + if(zones_count > 10) + return; // can't be received from real client or broken packet + + // recheck + CHECK_PACKET_SIZE(recv_data,4+4+(player_name.size()+1)+(guild_name.size()+1)+4+4+4+(4*zones_count)+4); + + for(uint32 i = 0; i < zones_count; i++) + { + uint32 temp; + recv_data >> temp; // zone id, 0 if zone is unknown... + zoneids[i] = temp; + sLog.outDebug("Zone %u: %u", i, zoneids[i]); + } + + recv_data >> str_count; // user entered strings count, client limit=4 (checked on 2.0.10) + + if(str_count > 4) + return; // can't be received from real client or broken packet + + // recheck + CHECK_PACKET_SIZE(recv_data,4+4+(player_name.size()+1)+(guild_name.size()+1)+4+4+4+(4*zones_count)+4+(1*str_count)); + + sLog.outDebug("Minlvl %u, maxlvl %u, name %s, guild %s, racemask %u, classmask %u, zones %u, strings %u", level_min, level_max, player_name.c_str(), guild_name.c_str(), racemask, classmask, zones_count, str_count); + + std::wstring str[4]; // 4 is client limit + for(uint32 i = 0; i < str_count; i++) + { + // recheck (have one more byte) + CHECK_PACKET_SIZE(recv_data,recv_data.rpos()); + + std::string temp; + recv_data >> temp; // user entered string, it used as universal search pattern(guild+player name)? + + if(!Utf8toWStr(temp,str[i])) + continue; + + wstrToLower(str[i]); + + sLog.outDebug("String %u: %s", i, str[i].c_str()); + } + + std::wstring wplayer_name; + std::wstring wguild_name; + if(!(Utf8toWStr(player_name, wplayer_name) && Utf8toWStr(guild_name, wguild_name))) + return; + wstrToLower(wplayer_name); + wstrToLower(wguild_name); + + // client send in case not set max level value 100 but mangos support 255 max level, + // update it to show GMs with characters after 100 level + if(level_max >= 100) + level_max = 255; + + uint32 team = _player->GetTeam(); + uint32 security = GetSecurity(); + bool allowTwoSideWhoList = sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_WHO_LIST); + bool gmInWhoList = sWorld.getConfig(CONFIG_GM_IN_WHO_LIST); + + WorldPacket data( SMSG_WHO, 50 ); // guess size + data << clientcount; // clientcount place holder + data << clientcount; // clientcount place holder + + //TODO: Guard Player map + HashMapHolder::MapType& m = ObjectAccessor::Instance().GetPlayers(); + for(HashMapHolder::MapType::iterator itr = m.begin(); itr != m.end(); ++itr) + { + if (security == SEC_PLAYER) + { + // player can see member of other team only if CONFIG_ALLOW_TWO_SIDE_WHO_LIST + if (itr->second->GetTeam() != team && !allowTwoSideWhoList ) + continue; + + // player can see MODERATOR, GAME MASTER, ADMINISTRATOR only if CONFIG_GM_IN_WHO_LIST + if ((itr->second->GetSession()->GetSecurity() > SEC_PLAYER && !gmInWhoList)) + continue; + } + + // check if target is globally visible for player + if (!(itr->second->IsVisibleGloballyFor(_player))) + continue; + + // check if target's level is in level range + uint32 lvl = itr->second->getLevel(); + if (lvl < level_min || lvl > level_max) + continue; + + // check if class matches classmask + uint32 class_ = itr->second->getClass(); + if (!(classmask & (1 << class_))) + continue; + + // check if race matches racemask + uint32 race = itr->second->getRace(); + if (!(racemask & (1 << race))) + continue; + + uint32 pzoneid = itr->second->GetZoneId(); + + bool z_show = true; + for(uint32 i = 0; i < zones_count; i++) + { + if(zoneids[i] == pzoneid) + { + z_show = true; + break; + } + + z_show = false; + } + if (!z_show) + continue; + + std::string pname = itr->second->GetName(); + std::wstring wpname; + if(!Utf8toWStr(pname,wpname)) + continue; + wstrToLower(wpname); + + if (!(wplayer_name.empty() || wpname.find(wplayer_name) != std::wstring::npos)) + continue; + + std::string gname = objmgr.GetGuildNameById(itr->second->GetGuildId()); + std::wstring wgname; + if(!Utf8toWStr(gname,wgname)) + continue; + wstrToLower(wgname); + + if (!(wguild_name.empty() || wgname.find(wguild_name) != std::wstring::npos)) + continue; + + std::string aname; + if(AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(itr->second->GetZoneId())) + aname = areaEntry->area_name[GetSessionDbcLocale()]; + + bool s_show = true; + for(uint32 i = 0; i < str_count; i++) + { + if (!str[i].empty()) + { + if (wgname.find(str[i]) != std::wstring::npos || + wpname.find(str[i]) != std::wstring::npos || + Utf8FitTo(aname, str[i]) ) + { + s_show = true; + break; + } + s_show = false; + } + } + if (!s_show) + continue; + + data << pname; // player name + data << gname; // guild name + data << uint32( lvl ); // player level + data << uint32( class_ ); // player class + data << uint32( race ); // player race + data << uint8(0); // new 2.4.0 + data << uint32( pzoneid ); // player zone id + + // 49 is maximum player count sent to client + if ((++clientcount) == 49) + break; + } + + data.put( 0, clientcount ); //insert right count + data.put( sizeof(uint32), clientcount ); //insert right count + + SendPacket(&data); + sLog.outDebug( "WORLD: Send SMSG_WHO Message" ); +} + +void WorldSession::HandleLogoutRequestOpcode( WorldPacket & /*recv_data*/ ) +{ + sLog.outDebug( "WORLD: Recvd CMSG_LOGOUT_REQUEST Message, security - %u", GetSecurity() ); + + if (uint64 lguid = GetPlayer()->GetLootGUID()) + DoLootRelease(lguid); + + //instant logout for admins, gm's, mod's + if( GetSecurity() > SEC_PLAYER ) + { + LogoutPlayer(true); + return; + } + + //Can not logout if... + if( GetPlayer()->isInCombat() || //...is in combat + GetPlayer()->duel || //...is in Duel + //...is jumping ...is falling + GetPlayer()->HasUnitMovementFlag(MOVEMENTFLAG_JUMPING | MOVEMENTFLAG_FALLING)) + { + WorldPacket data( SMSG_LOGOUT_RESPONSE, (2+4) ) ; + data << (uint8)0xC; + data << uint32(0); + data << uint8(0); + SendPacket( &data ); + LogoutRequest(0); + return; + } + + //instant logout in taverns/cities or on taxi + if(GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) || GetPlayer()->isInFlight()) + { + LogoutPlayer(true); + return; + } + + // not set flags if player can't free move to prevent lost state at logout cancel + if(GetPlayer()->CanFreeMove()) + { + GetPlayer()->SetStandState(PLAYER_STATE_SIT); + + WorldPacket data( SMSG_FORCE_MOVE_ROOT, (8+4) ); // guess size + data.append(GetPlayer()->GetPackGUID()); + data << (uint32)2; + SendPacket( &data ); + GetPlayer()->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE); + } + + WorldPacket data( SMSG_LOGOUT_RESPONSE, 5 ); + data << uint32(0); + data << uint8(0); + SendPacket( &data ); + LogoutRequest(time(NULL)); +} + +void WorldSession::HandlePlayerLogoutOpcode( WorldPacket & /*recv_data*/ ) +{ + sLog.outDebug( "WORLD: Recvd CMSG_PLAYER_LOGOUT Message" ); +} + +void WorldSession::HandleLogoutCancelOpcode( WorldPacket & /*recv_data*/ ) +{ + sLog.outDebug( "WORLD: Recvd CMSG_LOGOUT_CANCEL Message" ); + + LogoutRequest(0); + + WorldPacket data( SMSG_LOGOUT_CANCEL_ACK, 0 ); + SendPacket( &data ); + + // not remove flags if can't free move - its not set in Logout request code. + if(GetPlayer()->CanFreeMove()) + { + //!we can move again + data.Initialize( SMSG_FORCE_MOVE_UNROOT, 8 ); // guess size + data.append(GetPlayer()->GetPackGUID()); + data << uint32(0); + SendPacket( &data ); + + //! Stand Up + GetPlayer()->SetStandState(PLAYER_STATE_NONE); + + //! DISABLE_ROTATE + GetPlayer()->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE); + } + + sLog.outDebug( "WORLD: sent SMSG_LOGOUT_CANCEL_ACK Message" ); +} + +void WorldSession::SendGMTicketGetTicket(uint32 status, char const* text) +{ + int len = text ? strlen(text) : 0; + WorldPacket data( SMSG_GMTICKET_GETTICKET, (4+len+1+4+2+4+4) ); + data << uint32(status); // standard 0x0A, 0x06 if text present + if(status == 6) + { + data << text; // ticket text + data << uint8(0x7); // ticket category + data << float(0); // time from ticket creation? + data << float(0); // const + data << float(0); // const + data << uint8(0); // const + data << uint8(0); // const + } + SendPacket( &data ); +} + +void WorldSession::HandleGMTicketGetTicketOpcode( WorldPacket & /*recv_data*/ ) +{ + WorldPacket data( SMSG_QUERY_TIME_RESPONSE, 4+4 ); + data << (uint32)time(NULL); + data << (uint32)0; + SendPacket( &data ); + + uint64 guid; + Field *fields; + guid = GetPlayer()->GetGUID(); + + QueryResult *result = CharacterDatabase.PQuery("SELECT COUNT(ticket_id) FROM character_ticket WHERE guid = '%u'", GUID_LOPART(guid)); + + if (result) + { + int cnt; + fields = result->Fetch(); + cnt = fields[0].GetUInt32(); + delete result; + + if ( cnt > 0 ) + { + QueryResult *result2 = CharacterDatabase.PQuery("SELECT ticket_text FROM character_ticket WHERE guid = '%u'", GUID_LOPART(guid)); + if(result2) + { + Field *fields2 = result2->Fetch(); + SendGMTicketGetTicket(0x06,fields2[0].GetString()); + delete result2; + } + } + else + SendGMTicketGetTicket(0x0A,0); + } +} + +void WorldSession::HandleGMTicketUpdateTextOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,1); + + std::string ticketText; + recv_data >> ticketText; + + CharacterDatabase.escape_string(ticketText); + CharacterDatabase.PExecute("UPDATE character_ticket SET ticket_text = '%s' WHERE guid = '%u'", ticketText.c_str(), _player->GetGUIDLow()); +} + +void WorldSession::HandleGMTicketDeleteOpcode( WorldPacket & /*recv_data*/ ) +{ + uint32 guid = GetPlayer()->GetGUIDLow(); + + CharacterDatabase.PExecute("DELETE FROM character_ticket WHERE guid = '%u' LIMIT 1",guid); + + WorldPacket data( SMSG_GMTICKET_DELETETICKET, 4 ); + data << uint32(9); + SendPacket( &data ); + + SendGMTicketGetTicket(0x0A, 0); +} + +void WorldSession::HandleGMTicketCreateOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data, 4*4+1+2*4); + + uint32 map; + float x, y, z; + std::string ticketText = ""; + uint32 unk1, unk2; + + recv_data >> map >> x >> y >> z; // last check 2.4.3 + recv_data >> ticketText; + + // recheck + CHECK_PACKET_SIZE(recv_data,4*4+(ticketText.size()+1)+2*4); + + recv_data >> unk1 >> unk2; + // note: the packet might contain more data, but the exact structure of that is unknown + + sLog.outDebug("TicketCreate: map %u, x %f, y %f, z %f, text %s, unk1 %u, unk2 %u", map, x, y, z, ticketText.c_str(), unk1, unk2); + + CharacterDatabase.escape_string(ticketText); + + QueryResult *result = CharacterDatabase.PQuery("SELECT COUNT(*) FROM character_ticket WHERE guid = '%u'", _player->GetGUIDLow()); + + if (result) + { + int cnt; + Field *fields = result->Fetch(); + cnt = fields[0].GetUInt32(); + delete result; + + if ( cnt > 0 ) + { + WorldPacket data( SMSG_GMTICKET_CREATE, 4 ); + data << uint32(1); + SendPacket( &data ); + } + else + { + CharacterDatabase.PExecute("INSERT INTO character_ticket (guid,ticket_text) VALUES ('%u', '%s')", _player->GetGUIDLow(), ticketText.c_str()); + + WorldPacket data( SMSG_QUERY_TIME_RESPONSE, 4+4 ); + data << (uint32)time(NULL); + data << (uint32)0; + SendPacket( &data ); + + data.Initialize( SMSG_GMTICKET_CREATE, 4 ); + data << uint32(2); + SendPacket( &data ); + DEBUG_LOG("update the ticket\n"); + + //TODO: Guard player map + HashMapHolder::MapType &m = ObjectAccessor::Instance().GetPlayers(); + for(HashMapHolder::MapType::iterator itr = m.begin(); itr != m.end(); ++itr) + { + if(itr->second->GetSession()->GetSecurity() >= SEC_GAMEMASTER && itr->second->isAcceptTickets()) + ChatHandler(itr->second).PSendSysMessage(LANG_COMMAND_TICKETNEW,GetPlayer()->GetName()); + } + } + } +} + +void WorldSession::HandleGMTicketSystemStatusOpcode( WorldPacket & /*recv_data*/ ) +{ + WorldPacket data( SMSG_GMTICKET_SYSTEMSTATUS,4 ); + data << uint32(1); // we can also disable ticket system by sending 0 value + + SendPacket( &data ); +} + +void WorldSession::HandleGMSurveySubmit( WorldPacket & recv_data) +{ + // GM survey is shown after SMSG_GM_TICKET_STATUS_UPDATE with status = 3 + CHECK_PACKET_SIZE(recv_data,4+4); + uint32 x; + recv_data >> x; // answer range? (6 = 0-5?) + sLog.outDebug("SURVEY: X = %u", x); + + uint8 result[10]; + memset(result, 0, sizeof(result)); + for( int i = 0; i < 10; ++i) + { + CHECK_PACKET_SIZE(recv_data,recv_data.rpos()+4); + uint32 questionID; + recv_data >> questionID; // GMSurveyQuestions.dbc + if (!questionID) + break; + + CHECK_PACKET_SIZE(recv_data,recv_data.rpos()+1+1); + uint8 value; + std::string unk_text; + recv_data >> value; // answer + recv_data >> unk_text; // always empty? + + result[i] = value; + sLog.outDebug("SURVEY: ID %u, value %u, text %s", questionID, value, unk_text.c_str()); + } + + CHECK_PACKET_SIZE(recv_data,recv_data.rpos()+1); + std::string comment; + recv_data >> comment; // addional comment + sLog.outDebug("SURVEY: comment %s", comment.c_str()); + + // TODO: chart this data in some way +} + +void WorldSession::HandleTogglePvP( WorldPacket & recv_data ) +{ + // this opcode can be used in two ways: Either set explicit new status or toggle old status + if(recv_data.size() == 1) + { + bool newPvPStatus; + recv_data >> newPvPStatus; + GetPlayer()->ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP, newPvPStatus); + } + else + { + GetPlayer()->ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP); + } + + if(GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP)) + { + if(!GetPlayer()->IsPvP() || GetPlayer()->pvpInfo.endTimer != 0) + GetPlayer()->UpdatePvP(true, true); + } + else + { + if(!GetPlayer()->pvpInfo.inHostileArea && GetPlayer()->IsPvP()) + GetPlayer()->pvpInfo.endTimer = time(NULL); // start toggle-off + } +} + +void WorldSession::HandleZoneUpdateOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,4); + + uint32 newZone; + recv_data >> newZone; + + sLog.outDetail("WORLD: Recvd ZONE_UPDATE: %u", newZone); + + if(newZone != _player->GetZoneId()) + GetPlayer()->SendInitWorldStates(); // only if really enters to new zone, not just area change, works strange... + + GetPlayer()->UpdateZone(newZone); +} + +void WorldSession::HandleSetTargetOpcode( WorldPacket & recv_data ) +{ + // When this packet send? + CHECK_PACKET_SIZE(recv_data,8); + + uint64 guid ; + recv_data >> guid; + + _player->SetUInt32Value(UNIT_FIELD_TARGET,guid); + + // update reputation list if need + Unit* unit = ObjectAccessor::GetUnit(*_player, guid ); + if(!unit) + return; + + _player->SetFactionVisibleForFactionTemplateId(unit->getFaction()); +} + +void WorldSession::HandleSetSelectionOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8); + + uint64 guid; + recv_data >> guid; + + _player->SetSelection(guid); + + // update reputation list if need + Unit* unit = ObjectAccessor::GetUnit(*_player, guid ); + if(!unit) + return; + + _player->SetFactionVisibleForFactionTemplateId(unit->getFaction()); +} + +void WorldSession::HandleStandStateChangeOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,1); + + sLog.outDebug( "WORLD: Received CMSG_STAND_STATE_CHANGE" ); + uint8 animstate; + recv_data >> animstate; + + _player->SetStandState(animstate); +} + +void WorldSession::HandleFriendListOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data, 4); + sLog.outDebug( "WORLD: Received CMSG_CONTACT_LIST" ); + uint32 unk; + recv_data >> unk; + sLog.outDebug("unk value is %u", unk); + _player->GetSocial()->SendSocialList(); +} + +void WorldSession::HandleAddFriendOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data, 1+1); + + sLog.outDebug( "WORLD: Received CMSG_ADD_FRIEND" ); + + std::string friendName = GetMangosString(LANG_FRIEND_IGNORE_UNKNOWN); + std::string friendNote; + FriendsResult friendResult = FRIEND_NOT_FOUND; + Player *pFriend = NULL; + uint64 friendGuid = 0; + + recv_data >> friendName; + + // recheck + CHECK_PACKET_SIZE(recv_data, (friendName.size()+1)+1); + + recv_data >> friendNote; + + if(!normalizePlayerName(friendName)) + return; + + CharacterDatabase.escape_string(friendName); // prevent SQL injection - normal name don't must changed by this call + + sLog.outDebug( "WORLD: %s asked to add friend : '%s'", + GetPlayer()->GetName(), friendName.c_str() ); + + friendGuid = objmgr.GetPlayerGUIDByName(friendName); + + if(friendGuid) + { + pFriend = ObjectAccessor::FindPlayer(friendGuid); + if(pFriend==GetPlayer()) + friendResult = FRIEND_SELF; + else if(GetPlayer()->GetTeam()!=objmgr.GetPlayerTeamByGUID(friendGuid) && !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND) && GetSecurity() < SEC_MODERATOR) + friendResult = FRIEND_ENEMY; + else if(GetPlayer()->GetSocial()->HasFriend(GUID_LOPART(friendGuid))) + friendResult = FRIEND_ALREADY; + } + + if (friendGuid && friendResult==FRIEND_NOT_FOUND) + { + if( pFriend && pFriend->IsInWorld() && pFriend->IsVisibleGloballyFor(GetPlayer())) + friendResult = FRIEND_ADDED_ONLINE; + else + friendResult = FRIEND_ADDED_OFFLINE; + + if(!_player->GetSocial()->AddToSocialList(GUID_LOPART(friendGuid), false)) + { + friendResult = FRIEND_LIST_FULL; + sLog.outDebug( "WORLD: %s's friend list is full.", GetPlayer()->GetName()); + } + + _player->GetSocial()->SetFriendNote(GUID_LOPART(friendGuid), friendNote); + + sLog.outDebug( "WORLD: %s Guid found '%u'.", friendName.c_str(), GUID_LOPART(friendGuid)); + } + else if(friendResult==FRIEND_ALREADY) + { + sLog.outDebug( "WORLD: %s Guid Already a Friend.", friendName.c_str() ); + } + else if(friendResult==FRIEND_SELF) + { + sLog.outDebug( "WORLD: %s Guid can't add himself.", friendName.c_str() ); + } + else + { + sLog.outDebug( "WORLD: %s Guid not found.", friendName.c_str() ); + } + + sSocialMgr.SendFriendStatus(GetPlayer(), friendResult, GUID_LOPART(friendGuid), friendName, false); + + sLog.outDebug( "WORLD: Sent (SMSG_FRIEND_STATUS)" ); +} + +void WorldSession::HandleDelFriendOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data, 8); + + uint64 FriendGUID; + + sLog.outDebug( "WORLD: Received CMSG_DEL_FRIEND" ); + + recv_data >> FriendGUID; + + _player->GetSocial()->RemoveFromSocialList(GUID_LOPART(FriendGUID), false); + + sSocialMgr.SendFriendStatus(GetPlayer(), FRIEND_REMOVED, GUID_LOPART(FriendGUID), "", false); + + sLog.outDebug( "WORLD: Sent motd (SMSG_FRIEND_STATUS)" ); +} + +void WorldSession::HandleAddIgnoreOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,1); + + sLog.outDebug( "WORLD: Received CMSG_ADD_IGNORE" ); + + std::string IgnoreName = GetMangosString(LANG_FRIEND_IGNORE_UNKNOWN); + FriendsResult ignoreResult = FRIEND_IGNORE_NOT_FOUND; + uint64 IgnoreGuid = 0; + + recv_data >> IgnoreName; + + if(!normalizePlayerName(IgnoreName)) + return; + + CharacterDatabase.escape_string(IgnoreName); // prevent SQL injection - normal name don't must changed by this call + + sLog.outDebug( "WORLD: %s asked to Ignore: '%s'", + GetPlayer()->GetName(), IgnoreName.c_str() ); + + IgnoreGuid = objmgr.GetPlayerGUIDByName(IgnoreName); + + if(IgnoreGuid) + { + if(IgnoreGuid==GetPlayer()->GetGUID()) + ignoreResult = FRIEND_IGNORE_SELF; + else + { + if( GetPlayer()->GetSocial()->HasIgnore(GUID_LOPART(IgnoreGuid)) ) + ignoreResult = FRIEND_IGNORE_ALREADY; + } + } + + if (IgnoreGuid && ignoreResult == FRIEND_IGNORE_NOT_FOUND) + { + ignoreResult = FRIEND_IGNORE_ADDED; + + _player->GetSocial()->AddToSocialList(GUID_LOPART(IgnoreGuid), true); + } + else if(ignoreResult==FRIEND_IGNORE_ALREADY) + { + sLog.outDebug( "WORLD: %s Guid Already Ignored.", IgnoreName.c_str() ); + } + else if(ignoreResult==FRIEND_IGNORE_SELF) + { + sLog.outDebug( "WORLD: %s Guid can't add himself.", IgnoreName.c_str() ); + } + else + { + sLog.outDebug( "WORLD: %s Guid not found.", IgnoreName.c_str() ); + } + + sSocialMgr.SendFriendStatus(GetPlayer(), ignoreResult, GUID_LOPART(IgnoreGuid), "", false); + + sLog.outDebug( "WORLD: Sent (SMSG_FRIEND_STATUS)" ); +} + +void WorldSession::HandleDelIgnoreOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data, 8); + + uint64 IgnoreGUID; + + sLog.outDebug( "WORLD: Received CMSG_DEL_IGNORE" ); + + recv_data >> IgnoreGUID; + + _player->GetSocial()->RemoveFromSocialList(GUID_LOPART(IgnoreGUID), true); + + sSocialMgr.SendFriendStatus(GetPlayer(), FRIEND_IGNORE_REMOVED, GUID_LOPART(IgnoreGUID), "", false); + + sLog.outDebug( "WORLD: Sent motd (SMSG_FRIEND_STATUS)" ); +} + +void WorldSession::HandleSetFriendNoteOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data, 8+1); + uint64 guid; + std::string note; + recv_data >> guid >> note; + _player->GetSocial()->SetFriendNote(guid, note); +} + +void WorldSession::HandleBugOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,4+4+1+4+1); + + uint32 suggestion, contentlen; + std::string content; + uint32 typelen; + std::string type; + + recv_data >> suggestion >> contentlen >> content; + + //recheck + CHECK_PACKET_SIZE(recv_data,4+4+(content.size()+1)+4+1); + + recv_data >> typelen >> type; + + if( suggestion == 0 ) + sLog.outDebug( "WORLD: Received CMSG_BUG [Bug Report]" ); + else + sLog.outDebug( "WORLD: Received CMSG_BUG [Suggestion]" ); + + sLog.outDebug( type.c_str( ) ); + sLog.outDebug( content.c_str( ) ); + + CharacterDatabase.escape_string(type); + CharacterDatabase.escape_string(content); + CharacterDatabase.PExecute ("INSERT INTO bugreport (type,content) VALUES('%s', '%s')", type.c_str( ), content.c_str( )); +} + +void WorldSession::HandleCorpseReclaimOpcode(WorldPacket &recv_data) +{ + CHECK_PACKET_SIZE(recv_data,8); + + sLog.outDetail("WORLD: Received CMSG_RECLAIM_CORPSE"); + if (GetPlayer()->isAlive()) + return; + + // body not released yet + if(!GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) + return; + + Corpse *corpse = GetPlayer()->GetCorpse(); + + if (!corpse ) + return; + + // prevent resurrect before 30-sec delay after body release not finished + if(corpse->GetGhostTime() + GetPlayer()->GetCorpseReclaimDelay(corpse->GetType()==CORPSE_RESURRECTABLE_PVP) > time(NULL)) + return; + + float dist = corpse->GetDistance2d(GetPlayer()); + sLog.outDebug("Corpse 2D Distance: \t%f",dist); + if (dist > CORPSE_RECLAIM_RADIUS) + return; + + uint64 guid; + recv_data >> guid; + + // resurrect + GetPlayer()->ResurrectPlayer(GetPlayer()->InBattleGround() ? 1.0f : 0.5f); + + // spawn bones + GetPlayer()->SpawnCorpseBones(); + + GetPlayer()->SaveToDB(); +} + +void WorldSession::HandleResurrectResponseOpcode(WorldPacket & recv_data) +{ + CHECK_PACKET_SIZE(recv_data,8+1); + + sLog.outDetail("WORLD: Received CMSG_RESURRECT_RESPONSE"); + + if(GetPlayer()->isAlive()) + return; + + uint64 guid; + uint8 status; + recv_data >> guid; + recv_data >> status; + + if(status == 0) + { + GetPlayer()->clearResurrectRequestData(); // reject + return; + } + + if(!GetPlayer()->isRessurectRequestedBy(guid)) + return; + + GetPlayer()->ResurectUsingRequestData(); + GetPlayer()->SaveToDB(); +} + +void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data) +{ + CHECK_PACKET_SIZE(recv_data,4); + + sLog.outDebug("WORLD: Received CMSG_AREATRIGGER"); + + uint32 Trigger_ID; + + recv_data >> Trigger_ID; + sLog.outDebug("Trigger ID:%u",Trigger_ID); + + if(GetPlayer()->isInFlight()) + { + sLog.outDebug("Player '%s' (GUID: %u) in flight, ignore Area Trigger ID:%u",GetPlayer()->GetName(),GetPlayer()->GetGUIDLow(), Trigger_ID); + return; + } + + AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(Trigger_ID); + if(!atEntry) + { + sLog.outDebug("Player '%s' (GUID: %u) send unknown (by DBC) Area Trigger ID:%u",GetPlayer()->GetName(),GetPlayer()->GetGUIDLow(), Trigger_ID); + return; + } + + if (GetPlayer()->GetMapId()!=atEntry->mapid) + { + sLog.outDebug("Player '%s' (GUID: %u) too far (trigger map: %u player map: %u), ignore Area Trigger ID: %u", GetPlayer()->GetName(), atEntry->mapid, GetPlayer()->GetMapId(), GetPlayer()->GetGUIDLow(), Trigger_ID); + return; + } + + // delta is safe radius + const float delta = 5.0f; + // check if player in the range of areatrigger + Player* pl = GetPlayer(); + + if (atEntry->radius > 0) + { + // if we have radius check it + float dist = pl->GetDistance(atEntry->x,atEntry->y,atEntry->z); + if(dist > atEntry->radius + delta) + { + sLog.outDebug("Player '%s' (GUID: %u) too far (radius: %f distance: %f), ignore Area Trigger ID: %u", + pl->GetName(), pl->GetGUIDLow(), atEntry->radius, dist, Trigger_ID); + return; + } + } + else + { + // we have only extent + float dx = pl->GetPositionX() - atEntry->x; + float dy = pl->GetPositionY() - atEntry->y; + float dz = pl->GetPositionZ() - atEntry->z; + double es = sin(atEntry->box_orientation); + double ec = cos(atEntry->box_orientation); + // calc rotated vector based on extent axis + double rotateDx = dx*ec - dy*es; + double rotateDy = dx*es + dy*ec; + + if( (fabs(rotateDx) > atEntry->box_x/2 + delta) || + (fabs(rotateDy) > atEntry->box_y/2 + delta) || + (fabs(dz) > atEntry->box_z/2 + delta) ) + { + sLog.outDebug("Player '%s' (GUID: %u) too far (1/2 box X: %f 1/2 box Y: %u 1/2 box Z: %u rotate dX: %f rotate dY: %f dZ:%f), ignore Area Trigger ID: %u", + pl->GetName(), pl->GetGUIDLow(), atEntry->box_x/2, atEntry->box_y/2, atEntry->box_z/2, rotateDx, rotateDy, dz, Trigger_ID); + return; + } + } + + if(Script->scriptAreaTrigger(GetPlayer(), atEntry)) + return; + + uint32 quest_id = objmgr.GetQuestForAreaTrigger( Trigger_ID ); + if( quest_id && GetPlayer()->isAlive() && GetPlayer()->IsActiveQuest(quest_id) ) + { + Quest const* pQuest = objmgr.GetQuestTemplate(quest_id); + if( pQuest ) + { + if(GetPlayer()->GetQuestStatus(quest_id) == QUEST_STATUS_INCOMPLETE) + GetPlayer()->AreaExploredOrEventHappens( quest_id ); + } + } + + if(objmgr.IsTavernAreaTrigger(Trigger_ID)) + { + // set resting flag we are in the inn + GetPlayer()->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING); + GetPlayer()->InnEnter(time(NULL), atEntry->mapid, atEntry->x, atEntry->y, atEntry->z); + GetPlayer()->SetRestType(REST_TYPE_IN_TAVERN); + + if(sWorld.IsFFAPvPRealm()) + GetPlayer()->RemoveFlag(PLAYER_FLAGS,PLAYER_FLAGS_FFA_PVP); + + return; + } + + if(GetPlayer()->InBattleGround()) + { + BattleGround* bg = GetPlayer()->GetBattleGround(); + if(bg) + if(bg->GetStatus() == STATUS_IN_PROGRESS) + bg->HandleAreaTrigger(GetPlayer(), Trigger_ID); + + return; + } + + // NULL if all values default (non teleport trigger) + AreaTrigger const* at = objmgr.GetAreaTrigger(Trigger_ID); + if(!at) + return; + + if(!GetPlayer()->isGameMaster()) + { + uint32 missingLevel = 0; + if(GetPlayer()->getLevel() < at->requiredLevel && !sWorld.getConfig(CONFIG_INSTANCE_IGNORE_LEVEL)) + missingLevel = at->requiredLevel; + + // must have one or the other, report the first one that's missing + uint32 missingItem = 0; + if(at->requiredItem) + { + if(!GetPlayer()->HasItemCount(at->requiredItem, 1) && + (!at->requiredItem2 || !GetPlayer()->HasItemCount(at->requiredItem2, 1))) + missingItem = at->requiredItem; + } + else if(at->requiredItem2 && !GetPlayer()->HasItemCount(at->requiredItem2, 1)) + missingItem = at->requiredItem2; + + uint32 missingKey = 0; + if(GetPlayer()->GetDifficulty() == DIFFICULTY_HEROIC) + { + if(at->heroicKey) + { + if(!GetPlayer()->HasItemCount(at->heroicKey, 1) && + (!at->heroicKey2 || !GetPlayer()->HasItemCount(at->heroicKey2, 1))) + missingKey = at->heroicKey; + } + else if(at->heroicKey2 && !GetPlayer()->HasItemCount(at->heroicKey2, 1)) + missingKey = at->heroicKey2; + } + + uint32 missingQuest = 0; + if(at->requiredQuest && !GetPlayer()->GetQuestRewardStatus(at->requiredQuest)) + missingQuest = at->requiredQuest; + + if(missingLevel || missingItem || missingKey || missingQuest) + { + // TODO: all this is probably wrong + if(missingItem) + SendAreaTriggerMessage(GetMangosString(LANG_LEVEL_MINREQUIRED_AND_ITEM), at->requiredLevel, objmgr.GetItemPrototype(missingItem)->Name1); + else if(missingKey) + GetPlayer()->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_DIFFICULTY2); + else if(missingQuest) + SendAreaTriggerMessage(at->requiredFailedText.c_str()); + else if(missingLevel) + SendAreaTriggerMessage(GetMangosString(LANG_LEVEL_MINREQUIRED), missingLevel); + return; + } + } + + GetPlayer()->TeleportTo(at->target_mapId,at->target_X,at->target_Y,at->target_Z,at->target_Orientation,TELE_TO_NOT_LEAVE_TRANSPORT); +} + +void WorldSession::HandleUpdateAccountData(WorldPacket &/*recv_data*/) +{ + sLog.outDetail("WORLD: Received CMSG_UPDATE_ACCOUNT_DATA"); + //recv_data.hexlike(); +} + +void WorldSession::HandleRequestAccountData(WorldPacket& /*recv_data*/) +{ + sLog.outDetail("WORLD: Received CMSG_REQUEST_ACCOUNT_DATA"); + //recv_data.hexlike(); +} + +void WorldSession::HandleSetActionButtonOpcode(WorldPacket& recv_data) +{ + CHECK_PACKET_SIZE(recv_data,1+2+1+1); + + sLog.outDebug( "WORLD: Received CMSG_SET_ACTION_BUTTON" ); + uint8 button, misc, type; + uint16 action; + recv_data >> button >> action >> misc >> type; + sLog.outDetail( "BUTTON: %u ACTION: %u TYPE: %u MISC: %u", button, action, type, misc ); + if(action==0) + { + sLog.outDetail( "MISC: Remove action from button %u", button ); + + GetPlayer()->removeActionButton(button); + } + else + { + if(type==ACTION_BUTTON_MACRO || type==ACTION_BUTTON_CMACRO) + { + sLog.outDetail( "MISC: Added Macro %u into button %u", action, button ); + GetPlayer()->addActionButton(button,action,type,misc); + } + else if(type==ACTION_BUTTON_SPELL) + { + sLog.outDetail( "MISC: Added Action %u into button %u", action, button ); + GetPlayer()->addActionButton(button,action,type,misc); + } + else if(type==ACTION_BUTTON_ITEM) + { + sLog.outDetail( "MISC: Added Item %u into button %u", action, button ); + GetPlayer()->addActionButton(button,action,type,misc); + } + else + sLog.outError( "MISC: Unknown action button type %u for action %u into button %u", type, action, button ); + } +} + +void WorldSession::HandleCompleteCinema( WorldPacket & /*recv_data*/ ) +{ + DEBUG_LOG( "WORLD: Player is watching cinema" ); +} + +void WorldSession::HandleNextCinematicCamera( WorldPacket & /*recv_data*/ ) +{ + DEBUG_LOG( "WORLD: Which movie to play" ); +} + +void WorldSession::HandleMoveTimeSkippedOpcode( WorldPacket & /*recv_data*/ ) +{ + /* WorldSession::Update( getMSTime() );*/ + DEBUG_LOG( "WORLD: Time Lag/Synchronization Resent/Update" ); + + /* + CHECK_PACKET_SIZE(recv_data,8+4); + uint64 guid; + uint32 time_skipped; + recv_data >> guid; + recv_data >> time_skipped; + sLog.outDebug( "WORLD: CMSG_MOVE_TIME_SKIPPED" ); + + /// TODO + must be need use in mangos + We substract server Lags to move time ( AntiLags ) + for exmaple + GetPlayer()->ModifyLastMoveTime( -int32(time_skipped) ); + */ +} + +void WorldSession::HandleFeatherFallAck(WorldPacket &/*recv_data*/) +{ + DEBUG_LOG("WORLD: CMSG_MOVE_FEATHER_FALL_ACK"); +} + +void WorldSession::HandleMoveUnRootAck(WorldPacket&/* recv_data*/) +{ + /* + CHECK_PACKET_SIZE(recv_data,8+8+4+4+4+4+4); + + sLog.outDebug( "WORLD: CMSG_FORCE_MOVE_UNROOT_ACK" ); + recv_data.hexlike(); + uint64 guid; + uint64 unknown1; + uint32 unknown2; + float PositionX; + float PositionY; + float PositionZ; + float Orientation; + + recv_data >> guid; + recv_data >> unknown1; + recv_data >> unknown2; + recv_data >> PositionX; + recv_data >> PositionY; + recv_data >> PositionZ; + recv_data >> Orientation; + + // TODO for later may be we can use for anticheat + DEBUG_LOG("Guid " I64FMTD,guid); + DEBUG_LOG("unknown1 " I64FMTD,unknown1); + DEBUG_LOG("unknown2 %u",unknown2); + DEBUG_LOG("X %f",PositionX); + DEBUG_LOG("Y %f",PositionY); + DEBUG_LOG("Z %f",PositionZ); + DEBUG_LOG("O %f",Orientation); + */ +} + +void WorldSession::HandleMoveRootAck(WorldPacket&/* recv_data*/) +{ + /* + CHECK_PACKET_SIZE(recv_data,8+8+4+4+4+4+4); + + sLog.outDebug( "WORLD: CMSG_FORCE_MOVE_ROOT_ACK" ); + recv_data.hexlike(); + uint64 guid; + uint64 unknown1; + uint32 unknown2; + float PositionX; + float PositionY; + float PositionZ; + float Orientation; + + recv_data >> guid; + recv_data >> unknown1; + recv_data >> unknown2; + recv_data >> PositionX; + recv_data >> PositionY; + recv_data >> PositionZ; + recv_data >> Orientation; + + // for later may be we can use for anticheat + DEBUG_LOG("Guid " I64FMTD,guid); + DEBUG_LOG("unknown1 " I64FMTD,unknown1); + DEBUG_LOG("unknown1 %u",unknown2); + DEBUG_LOG("X %f",PositionX); + DEBUG_LOG("Y %f",PositionY); + DEBUG_LOG("Z %f",PositionZ); + DEBUG_LOG("O %f",Orientation); + */ +} + +void WorldSession::HandleMoveTeleportAck(WorldPacket&/* recv_data*/) +{ + /* + CHECK_PACKET_SIZE(recv_data,8+4); + + sLog.outDebug("MSG_MOVE_TELEPORT_ACK"); + uint64 guid; + uint32 flags, time; + + recv_data >> guid; + recv_data >> flags >> time; + DEBUG_LOG("Guid " I64FMTD,guid); + DEBUG_LOG("Flags %u, time %u",flags, time/1000); + */ +} + +void WorldSession::HandleSetActionBar(WorldPacket& recv_data) +{ + CHECK_PACKET_SIZE(recv_data,1); + + uint8 ActionBar; + + recv_data >> ActionBar; + + if(!GetPlayer()) // ignore until not logged (check needed because STATUS_AUTHED) + { + if(ActionBar!=0) + sLog.outError("WorldSession::HandleSetActionBar in not logged state with value: %u, ignored",uint32(ActionBar)); + return; + } + + GetPlayer()->SetByteValue(PLAYER_FIELD_BYTES, 2, ActionBar); +} + +void WorldSession::HandleWardenDataOpcode(WorldPacket& /*recv_data*/) +{ + /* + CHECK_PACKET_SIZE(recv_data,1); + + uint8 tmp; + recv_data >> tmp; + sLog.outDebug("Received opcode CMSG_WARDEN_DATA, not resolve.uint8 = %u",tmp); + */ +} + +void WorldSession::HandlePlayedTime(WorldPacket& /*recv_data*/) +{ + uint32 TotalTimePlayed = GetPlayer()->GetTotalPlayedTime(); + uint32 LevelPlayedTime = GetPlayer()->GetLevelPlayedTime(); + + WorldPacket data(SMSG_PLAYED_TIME, 8); + data << TotalTimePlayed; + data << LevelPlayedTime; + SendPacket(&data); +} + +void WorldSession::HandleInspectOpcode(WorldPacket& recv_data) +{ + CHECK_PACKET_SIZE(recv_data, 8); + + uint64 guid; + recv_data >> guid; + DEBUG_LOG("Inspected guid is " I64FMTD, guid); + + _player->SetSelection(guid); + + Player *plr = objmgr.GetPlayer(guid); + if(!plr) // wrong player + return; + + uint32 talent_points = 0x3D; + uint32 guid_size = plr->GetPackGUID().size(); + WorldPacket data(SMSG_INSPECT_TALENT, 4+talent_points); + data.append(plr->GetPackGUID()); + data << uint32(talent_points); + + // fill by 0 talents array + for(uint32 i = 0; i < talent_points; ++i) + data << uint8(0); + + if(sWorld.getConfig(CONFIG_TALENTS_INSPECTING) || _player->isGameMaster()) + { + // find class talent tabs (all players have 3 talent tabs) + uint32 const* talentTabIds = GetTalentTabPages(plr->getClass()); + + uint32 talentTabPos = 0; // pos of first talent rank in tab including all prev tabs + for(uint32 i = 0; i < 3; ++i) + { + uint32 talentTabId = talentTabIds[i]; + + // fill by real data + for(uint32 talentId = 0; talentId < sTalentStore.GetNumRows(); ++talentId) + { + TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentId); + if(!talentInfo) + continue; + + // skip another tab talents + if(talentInfo->TalentTab != talentTabId) + continue; + + // find talent rank + uint32 curtalent_maxrank = 0; + for(uint32 k = 5; k > 0; --k) + { + if(talentInfo->RankID[k-1] && plr->HasSpell(talentInfo->RankID[k-1])) + { + curtalent_maxrank = k; + break; + } + } + + // not learned talent + if(!curtalent_maxrank) + continue; + + // 1 rank talent bit index + uint32 curtalent_index = talentTabPos + GetTalentInspectBitPosInTab(talentId); + + uint32 curtalent_rank_index = curtalent_index+curtalent_maxrank-1; + + // slot/offset in 7-bit bytes + uint32 curtalent_rank_slot7 = curtalent_rank_index / 7; + uint32 curtalent_rank_offset7 = curtalent_rank_index % 7; + + // rank pos with skipped 8 bit + uint32 curtalent_rank_index2 = curtalent_rank_slot7 * 8 + curtalent_rank_offset7; + + // slot/offset in 8-bit bytes with skipped high bit + uint32 curtalent_rank_slot = curtalent_rank_index2 / 8; + uint32 curtalent_rank_offset = curtalent_rank_index2 % 8; + + // apply mask + uint32 val = data.read(guid_size + 4 + curtalent_rank_slot); + val |= (1 << curtalent_rank_offset); + data.put(guid_size + 4 + curtalent_rank_slot, val & 0xFF); + } + + talentTabPos += GetTalentTabInspectBitSize(talentTabId); + } + } + + SendPacket(&data); +} + +void WorldSession::HandleInspectHonorStatsOpcode(WorldPacket& recv_data) +{ + CHECK_PACKET_SIZE(recv_data, 8); + + uint64 guid; + recv_data >> guid; + + Player *player = objmgr.GetPlayer(guid); + + if(!player) + { + sLog.outError("InspectHonorStats: WTF, player not found..."); + return; + } + + WorldPacket data(MSG_INSPECT_HONOR_STATS, 8+1+4*4); + data << uint64(player->GetGUID()); + data << uint8(player->GetUInt32Value(PLAYER_FIELD_HONOR_CURRENCY)); + data << uint32(player->GetUInt32Value(PLAYER_FIELD_KILLS)); + data << uint32(player->GetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION)); + data << uint32(player->GetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION)); + data << uint32(player->GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORBALE_KILLS)); + SendPacket(&data); +} + +void WorldSession::HandleWorldTeleportOpcode(WorldPacket& recv_data) +{ + CHECK_PACKET_SIZE(recv_data,4+4+4+4+4+4); + + // write in client console: worldport 469 452 6454 2536 180 or /console worldport 469 452 6454 2536 180 + // Received opcode CMSG_WORLD_TELEPORT + // Time is ***, map=469, x=452.000000, y=6454.000000, z=2536.000000, orient=3.141593 + + //sLog.outDebug("Received opcode CMSG_WORLD_TELEPORT"); + + if(GetPlayer()->isInFlight()) + { + sLog.outDebug("Player '%s' (GUID: %u) in flight, ignore worldport command.",GetPlayer()->GetName(),GetPlayer()->GetGUIDLow()); + return; + } + + uint32 time; + uint32 mapid; + float PositionX; + float PositionY; + float PositionZ; + float Orientation; + + recv_data >> time; // time in m.sec. + recv_data >> mapid; + recv_data >> PositionX; + recv_data >> PositionY; + recv_data >> PositionZ; + recv_data >> Orientation; // o (3.141593 = 180 degrees) + DEBUG_LOG("Time %u sec, map=%u, x=%f, y=%f, z=%f, orient=%f", time/1000, mapid, PositionX, PositionY, PositionZ, Orientation); + + if (GetSecurity() >= SEC_ADMINISTRATOR) + GetPlayer()->TeleportTo(mapid,PositionX,PositionY,PositionZ,Orientation); + else + SendNotification("You do not have permission to perform that function"); + sLog.outDebug("Received worldport command from player %s", GetPlayer()->GetName()); +} + +void WorldSession::HandleWhoisOpcode(WorldPacket& recv_data) +{ + CHECK_PACKET_SIZE(recv_data, 1); + + sLog.outDebug("Received opcode CMSG_WHOIS"); + std::string charname, acc, email, lastip, msg; + recv_data >> charname; + + if (GetSecurity() < SEC_ADMINISTRATOR) + { + SendNotification("You do not have permission to perform that function"); + return; + } + + if(charname.empty()) + { + SendNotification("Please provide character name"); + return; + } + + uint32 accid; + Field *fields; + + Player *plr = objmgr.GetPlayer(charname.c_str()); + + if(plr) + accid = plr->GetSession()->GetAccountId(); + else + { + SendNotification("Player %s not found or offline", charname.c_str()); + return; + } + + if(!accid) + { + SendNotification("Account for character %s not found", charname.c_str()); + return; + } + + QueryResult *result = loginDatabase.PQuery("SELECT username,email,last_ip FROM account WHERE id=%u", accid); + if(result) + { + fields = result->Fetch(); + acc = fields[0].GetCppString(); + if(acc.empty()) + acc = "Unknown"; + email = fields[1].GetCppString(); + if(email.empty()) + email = "Unknown"; + lastip = fields[2].GetCppString(); + if(lastip.empty()) + lastip = "Unknown"; + msg = charname + "'s " + "account is " + acc + ", e-mail: " + email + ", last ip: " + lastip; + + WorldPacket data(SMSG_WHOIS, msg.size()+1); + data << msg; + _player->GetSession()->SendPacket(&data); + } + else + SendNotification("Account for character %s not found", charname.c_str()); + + delete result; + sLog.outDebug("Received whois command from player %s for character %s", GetPlayer()->GetName(), charname.c_str()); +} + +void WorldSession::HandleReportSpamOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data, 1+8); + sLog.outDebug("WORLD: CMSG_REPORT_SPAM"); + recv_data.hexlike(); + + uint8 spam_type; // 0 - mail, 1 - chat + uint64 spammer_guid; + uint32 unk1, unk2, unk3, unk4 = 0; + std::string description = ""; + recv_data >> spam_type; // unk 0x01 const, may be spam type (mail/chat) + recv_data >> spammer_guid; // player guid + switch(spam_type) + { + case 0: + CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4+4+4); + recv_data >> unk1; // const 0 + recv_data >> unk2; // probably mail id + recv_data >> unk3; // const 0 + break; + case 1: + CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4+4+4+4+1); + recv_data >> unk1; // probably language + recv_data >> unk2; // message type? + recv_data >> unk3; // probably channel id + recv_data >> unk4; // unk random value + recv_data >> description; // spam description string (messagetype, channel name, player name, message) + break; + } + + // NOTE: all chat messages from this spammer automatically ignored by spam reporter until logout in case chat spam. + // if it's mail spam - ALL mails from this spammer automatically removed by client + + // Complaint Received message + WorldPacket data(SMSG_COMPLAIN_RESULT, 1); + data << uint8(0); + SendPacket(&data); + + sLog.outDebug("REPORT SPAM: type %u, guid %u, unk1 %u, unk2 %u, unk3 %u, unk4 %u, message %s", spam_type, GUID_LOPART(spammer_guid), unk1, unk2, unk3, unk4, description.c_str()); +} + +void WorldSession::HandleRealmStateRequestOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data, 4); + + sLog.outDebug("CMSG_REALM_SPLIT"); + + uint32 unk; + std::string split_date = "01/01/01"; + recv_data >> unk; + + WorldPacket data(SMSG_REALM_SPLIT, 4+4+split_date.size()+1); + data << unk; + data << uint32(0x00000000); // realm split state + // split states: + // 0x0 realm normal + // 0x1 realm split + // 0x2 realm split pending + data << split_date; + SendPacket(&data); + //sLog.outDebug("response sent %u", unk); +} + +void WorldSession::HandleFarSightOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data, 1); + + sLog.outDebug("WORLD: CMSG_FAR_SIGHT"); + //recv_data.hexlike(); + + uint8 unk; + recv_data >> unk; + + switch(unk) + { + case 0: + //WorldPacket data(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, 0) + //SendPacket(&data); + //_player->SetUInt64Value(PLAYER_FARSIGHT, 0); + sLog.outDebug("Removed FarSight from player %u", _player->GetGUIDLow()); + break; + case 1: + sLog.outDebug("Added FarSight " I64FMTD " to player %u", _player->GetUInt64Value(PLAYER_FARSIGHT), _player->GetGUIDLow()); + break; + } +} + +void WorldSession::HandleChooseTitleOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data, 4); + + sLog.outDebug("CMSG_SET_TITLE"); + + int32 title; + recv_data >> title; + + // -1 at none + if(title > 0 && title < 64) + { + if(!GetPlayer()->HasFlag64(PLAYER__FIELD_KNOWN_TITLES,uint64(1) << title)) + return; + } + else + title = 0; + + GetPlayer()->SetUInt32Value(PLAYER_CHOSEN_TITLE, title); +} + +void WorldSession::HandleAllowMoveAckOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data, 4+4); + + sLog.outDebug("CMSG_ALLOW_MOVE_ACK"); + + uint32 counter, time_; + recv_data >> counter >> time_; + + // time_ seems always more than getMSTime() + uint32 diff = getMSTimeDiff(getMSTime(),time_); + + sLog.outDebug("response sent: counter %u, time %u (HEX: %X), ms. time %u, diff %u", counter, time_, time_, getMSTime(), diff); +} + +void WorldSession::HandleResetInstancesOpcode( WorldPacket & /*recv_data*/ ) +{ + sLog.outDebug("WORLD: CMSG_RESET_INSTANCES"); + Group *pGroup = _player->GetGroup(); + if(pGroup) + { + if(pGroup->IsLeader(_player->GetGUID())) + pGroup->ResetInstances(INSTANCE_RESET_ALL, _player); + } + else + _player->ResetInstances(INSTANCE_RESET_ALL); +} + +void WorldSession::HandleDungeonDifficultyOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data, 4); + + sLog.outDebug("MSG_SET_DUNGEON_DIFFICULTY"); + + uint32 mode; + recv_data >> mode; + + if(mode == _player->GetDifficulty()) + return; + + if(mode > DIFFICULTY_HEROIC) + { + sLog.outError("WorldSession::HandleDungeonDifficultyOpcode: player %d sent an invalid instance mode %d!", _player->GetGUIDLow(), mode); + return; + } + + // cannot reset while in an instance + Map *map = _player->GetMap(); + if(map && map->IsDungeon()) + { + sLog.outError("WorldSession::HandleDungeonDifficultyOpcode: player %d tried to reset the instance while inside!", _player->GetGUIDLow()); + return; + } + + if(_player->getLevel() < LEVELREQUIREMENT_HEROIC) + return; + Group *pGroup = _player->GetGroup(); + if(pGroup) + { + if(pGroup->IsLeader(_player->GetGUID())) + { + // the difficulty is set even if the instances can't be reset + //_player->SendDungeonDifficulty(true); + pGroup->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, _player); + pGroup->SetDifficulty(mode); + } + } + else + { + _player->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY); + _player->SetDifficulty(mode); + } +} + +void WorldSession::HandleNewUnknownOpcode( WorldPacket & recv_data ) +{ + sLog.outDebug("New Unknown Opcode %u", recv_data.GetOpcode()); + recv_data.hexlike(); + /* + New Unknown Opcode 837 + STORAGE_SIZE: 60 + 02 00 00 00 00 00 00 00 | 00 00 00 00 01 20 00 00 + 89 EB 33 01 71 5C 24 C4 | 15 03 35 45 74 47 8B 42 + BA B8 1B 40 00 00 00 00 | 00 00 00 00 77 66 42 BF + 23 91 26 3F 00 00 60 41 | 00 00 00 00 + + New Unknown Opcode 837 + STORAGE_SIZE: 44 + 02 00 00 00 00 00 00 00 | 00 00 00 00 00 00 80 00 + 7B 80 34 01 84 EA 2B C4 | 5F A1 36 45 C9 39 1C 42 + BA B8 1B 40 CE 06 00 00 | 00 00 80 3F + */ +} + +void WorldSession::HandleDismountOpcode( WorldPacket & /*recv_data*/ ) +{ + sLog.outDebug("WORLD: CMSG_CANCEL_MOUNT_AURA"); + //recv_data.hexlike(); + + //If player is not mounted, so go out :) + if (!_player->IsMounted()) // not blizz like; no any messages on blizz + { + ChatHandler(this).SendSysMessage(LANG_CHAR_NON_MOUNTED); + return; + } + + if(_player->isInFlight()) // not blizz like; no any messages on blizz + { + ChatHandler(this).SendSysMessage(LANG_YOU_IN_FLIGHT); + return; + } + + _player->Unmount(); + _player->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); +} + +void WorldSession::HandleMoveFlyModeChangeAckOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data, 8+4+4); + + // fly mode on/off + sLog.outDebug("WORLD: CMSG_MOVE_SET_CAN_FLY_ACK"); + //recv_data.hexlike(); + + uint64 guid; + uint32 unk; + uint32 flags; + + recv_data >> guid >> unk >> flags; + + _player->SetUnitMovementFlags(flags); + /* + on: + 25 00 00 00 00 00 00 00 | 00 00 00 00 00 00 80 00 + 85 4E A9 01 19 BA 7A C3 | 42 0D 70 44 44 B0 A8 42 + 78 15 94 40 39 03 00 00 | 00 00 80 3F + off: + 25 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00 + 10 FD A9 01 19 BA 7A C3 | 42 0D 70 44 44 B0 A8 42 + 78 15 94 40 39 03 00 00 | 00 00 00 00 + */ +} + +void WorldSession::HandleRequestPetInfoOpcode( WorldPacket & /*recv_data */) +{ + /* + sLog.outDebug("WORLD: CMSG_REQUEST_PET_INFO"); + recv_data.hexlike(); + */ +} + +void WorldSession::HandleSetTaxiBenchmarkOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data, 1); + + uint8 mode; + recv_data >> mode; + + sLog.outDebug("Client used \"/timetest %d\" command", mode); +} diff --git a/src/game/MotionMaster.cpp b/src/game/MotionMaster.cpp new file mode 100644 index 00000000000..cf910bf50b2 --- /dev/null +++ b/src/game/MotionMaster.cpp @@ -0,0 +1,342 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "MotionMaster.h" +#include "CreatureAISelector.h" +#include "Creature.h" +#include "Traveller.h" + +#include "ConfusedMovementGenerator.h" +#include "FleeingMovementGenerator.h" +#include "HomeMovementGenerator.h" +#include "IdleMovementGenerator.h" +#include "PointMovementGenerator.h" +#include "TargetedMovementGenerator.h" +#include "WaypointMovementGenerator.h" + +#include + +inline bool isStatic(MovementGenerator *mv) +{ + return (mv == &si_idleMovement); +} + +void +MotionMaster::Initialize() +{ + // clear ALL movement generators (including default) + while(!empty()) + { + MovementGenerator *curr = top(); + curr->Finalize(*i_owner); + pop(); + if( !isStatic( curr ) ) + delete curr; + } + + // set new default movement generator + if(i_owner->GetTypeId() == TYPEID_UNIT) + { + MovementGenerator* movement = FactorySelector::selectMovementGenerator((Creature*)i_owner); + push( movement == NULL ? &si_idleMovement : movement ); + top()->Initialize(*i_owner); + } + else + push(&si_idleMovement); +} + +MotionMaster::~MotionMaster() +{ + // clear ALL movement generators (including default) + while(!empty()) + { + MovementGenerator *curr = top(); + curr->Finalize(*i_owner); + pop(); + if( !isStatic( curr ) ) + delete curr; + } +} + +void +MotionMaster::UpdateMotion(const uint32 &diff) +{ + if( i_owner->hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED) ) + return; + assert( !empty() ); + if (!top()->Update(*i_owner, diff)) + MovementExpired(); +} + +void +MotionMaster::Clear(bool reset) +{ + while( !empty() && size() > 1 ) + { + MovementGenerator *curr = top(); + curr->Finalize(*i_owner); + pop(); + if( !isStatic( curr ) ) + delete curr; + } + + if (reset) + { + assert( !empty() ); + top()->Reset(*i_owner); + } +} + +void +MotionMaster::MovementExpired(bool reset) +{ + if( empty() || size() == 1 ) + return; + + MovementGenerator *curr = top(); + curr->Finalize(*i_owner); + pop(); + + if( !isStatic(curr) ) + delete curr; + + assert( !empty() ); + while( !empty() && top()->GetMovementGeneratorType() == TARGETED_MOTION_TYPE ) + { + // Should check if target is still valid? If not valid it will crash. + curr = top(); + curr->Finalize(*i_owner); + pop(); + delete curr; + } + if( empty() ) + Initialize(); + if (reset) top()->Reset(*i_owner); +} + +void MotionMaster::MoveIdle() +{ + if( empty() || !isStatic( top() ) ) + push( &si_idleMovement ); +} + +void +MotionMaster::MoveTargetedHome() +{ + if(i_owner->hasUnitState(UNIT_STAT_FLEEING)) + return; + + Clear(false); + + if(i_owner->GetTypeId()==TYPEID_UNIT && !((Creature*)i_owner)->GetCharmerOrOwnerGUID()) + { + DEBUG_LOG("Creature (Entry: %u GUID: %u) targeted home", i_owner->GetEntry(), i_owner->GetGUIDLow()); + Mutate(new HomeMovementGenerator()); + } + else if(i_owner->GetTypeId()==TYPEID_UNIT && ((Creature*)i_owner)->GetCharmerOrOwnerGUID()) + { + sLog.outError("Pet or controlled creature (Entry: %u GUID: %u) attempt targeted home", + i_owner->GetEntry(), i_owner->GetGUIDLow() ); + } + else + { + sLog.outError("Player (GUID: %u) attempt targeted home", i_owner->GetGUIDLow() ); + } +} + +void +MotionMaster::MoveConfused() +{ + if(i_owner->GetTypeId()==TYPEID_PLAYER) + { + DEBUG_LOG("Player (GUID: %u) move confused", i_owner->GetGUIDLow() ); + Mutate(new ConfusedMovementGenerator()); + } + else + { + DEBUG_LOG("Creature (Entry: %u GUID: %u) move confused", + i_owner->GetEntry(), i_owner->GetGUIDLow() ); + Mutate(new ConfusedMovementGenerator()); + } +} + +void +MotionMaster::MoveChase(Unit* target, float dist, float angle) +{ + // ignore movement request if target not exist + if(!target) + return; + + i_owner->clearUnitState(UNIT_STAT_FOLLOW); + if(i_owner->GetTypeId()==TYPEID_PLAYER) + { + DEBUG_LOG("Player (GUID: %u) chase to %s (GUID: %u)", + target->GetTypeId()==TYPEID_PLAYER ? "player" : "creature", + target->GetTypeId()==TYPEID_PLAYER ? i_owner->GetGUIDLow() : ((Creature*)i_owner)->GetDBTableGUIDLow() ); + Mutate(new TargetedMovementGenerator(*target,dist,angle)); + } + else + { + DEBUG_LOG("Creature (Entry: %u GUID: %u) chase to %s (GUID: %u)", + i_owner->GetEntry(), i_owner->GetGUIDLow(), + target->GetTypeId()==TYPEID_PLAYER ? "player" : "creature", + target->GetTypeId()==TYPEID_PLAYER ? target->GetGUIDLow() : ((Creature*)target)->GetDBTableGUIDLow() ); + Mutate(new TargetedMovementGenerator(*target,dist,angle)); + } +} + +void +MotionMaster::MoveFollow(Unit* target, float dist, float angle) +{ + Clear(); + + // ignore movement request if target not exist + if(!target) + return; + + i_owner->addUnitState(UNIT_STAT_FOLLOW); + if(i_owner->GetTypeId()==TYPEID_PLAYER) + { + DEBUG_LOG("Player (GUID: %u) follow to %s (GUID: %u)", i_owner->GetGUIDLow(), + target->GetTypeId()==TYPEID_PLAYER ? "player" : "creature", + target->GetTypeId()==TYPEID_PLAYER ? i_owner->GetGUIDLow() : ((Creature*)i_owner)->GetDBTableGUIDLow() ); + Mutate(new TargetedMovementGenerator(*target,dist,angle)); + } + else + { + DEBUG_LOG("Creature (Entry: %u GUID: %u) follow to %s (GUID: %u)", + i_owner->GetEntry(), i_owner->GetGUIDLow(), + target->GetTypeId()==TYPEID_PLAYER ? "player" : "creature", + target->GetTypeId()==TYPEID_PLAYER ? target->GetGUIDLow() : ((Creature*)target)->GetDBTableGUIDLow() ); + Mutate(new TargetedMovementGenerator(*target,dist,angle)); + } +} + +void +MotionMaster::MovePoint(uint32 id, float x, float y, float z) +{ + if(i_owner->GetTypeId()==TYPEID_PLAYER) + { + DEBUG_LOG("Player (GUID: %u) targeted point (Id: %u X: %f Y: %f Z: %f)", i_owner->GetGUIDLow(), id, x, y, z ); + Mutate(new PointMovementGenerator(id,x,y,z)); + } + else + { + DEBUG_LOG("Creature (Entry: %u GUID: %u) targeted point (ID: %u X: %f Y: %f Z: %f)", + i_owner->GetEntry(), i_owner->GetGUIDLow(), id, x, y, z ); + Mutate(new PointMovementGenerator(id,x,y,z)); + } +} + +void +MotionMaster::MoveFleeing(Unit* enemy) +{ + if(!enemy) + return; + + if(i_owner->GetTypeId()==TYPEID_PLAYER) + { + DEBUG_LOG("Player (GUID: %u) flee from %s (GUID: %u)", i_owner->GetGUIDLow(), + enemy->GetTypeId()==TYPEID_PLAYER ? "player" : "creature", + enemy->GetTypeId()==TYPEID_PLAYER ? enemy->GetGUIDLow() : ((Creature*)enemy)->GetDBTableGUIDLow() ); + Mutate(new FleeingMovementGenerator(enemy->GetGUID())); + } + else + { + DEBUG_LOG("Creature (Entry: %u GUID: %u) flee from %s (GUID: %u)", + i_owner->GetEntry(), i_owner->GetGUIDLow(), + enemy->GetTypeId()==TYPEID_PLAYER ? "player" : "creature", + enemy->GetTypeId()==TYPEID_PLAYER ? enemy->GetGUIDLow() : ((Creature*)enemy)->GetDBTableGUIDLow() ); + Mutate(new FleeingMovementGenerator(enemy->GetGUID())); + } +} + +void +MotionMaster::MoveTaxiFlight(uint32 path, uint32 pathnode) +{ + if(i_owner->GetTypeId()==TYPEID_PLAYER) + { + DEBUG_LOG("Player (GUID: %u) taxi to (Path %u node %u)", i_owner->GetGUIDLow(), path, pathnode); + FlightPathMovementGenerator* mgen = new FlightPathMovementGenerator(path,pathnode); + Mutate(mgen); + } + else + { + sLog.outError("Creature (Entry: %u GUID: %u) attempt taxi to (Path %u node %u)", + i_owner->GetEntry(), i_owner->GetGUIDLow(), path, pathnode ); + } +} + +void +MotionMaster::MoveDistract(uint32 timer) +{ + if(i_owner->GetTypeId()==TYPEID_PLAYER) + { + DEBUG_LOG("Player (GUID: %u) distracted (timer: %u)", i_owner->GetGUIDLow(), timer); + } + else + { + DEBUG_LOG("Creature (Entry: %u GUID: %u) (timer: %u)", + i_owner->GetEntry(), i_owner->GetGUIDLow(), timer); + } + + DistractMovementGenerator* mgen = new DistractMovementGenerator(timer); + Mutate(mgen); +} + +void MotionMaster::Mutate(MovementGenerator *m) +{ + if (!empty()) + { + switch(top()->GetMovementGeneratorType()) + { + // HomeMovement is not that important, delete it if meanwhile a new comes + case HOME_MOTION_TYPE: + // DistractMovement interrupted by any other movement + case DISTRACT_MOTION_TYPE: + MovementExpired(false); + } + } + m->Initialize(*i_owner); + push(m); +} + +void MotionMaster::propagateSpeedChange() +{ + Impl::container_type::iterator it = Impl::c.begin(); + for ( ;it != end(); ++it) + { + (*it)->unitSpeedChanged(); + } +} + +MovementGeneratorType MotionMaster::GetCurrentMovementGeneratorType() const +{ + if(empty()) + return IDLE_MOTION_TYPE; + + return top()->GetMovementGeneratorType(); +} + +bool MotionMaster::GetDestination(float &x, float &y, float &z) +{ + if(empty()) + return false; + + return top()->GetDestination(x,y,z); +} diff --git a/src/game/MotionMaster.h b/src/game/MotionMaster.h new file mode 100644 index 00000000000..f7a38e47618 --- /dev/null +++ b/src/game/MotionMaster.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_MOTIONMASTER_H +#define MANGOS_MOTIONMASTER_H + +#include "Common.h" +#include + +class MovementGenerator; +class Unit; + +// Creature Entry ID used for waypoints show, visible only for GMs +#define VISUAL_WAYPOINT 1 + +// values 0 ... MAX_DB_MOTION_TYPE-1 used in DB +enum MovementGeneratorType +{ + IDLE_MOTION_TYPE = 0, // IdleMovementGenerator.h + RANDOM_MOTION_TYPE = 1, // RandomMovementGenerator.h + WAYPOINT_MOTION_TYPE = 2, // WaypointMovementGenerator.h + MAX_DB_MOTION_TYPE = 3, // *** this and below motion types can't be set in DB. + ANIMAL_RANDOM_MOTION_TYPE = MAX_DB_MOTION_TYPE, // AnimalRandomMovementGenerator.h + CONFUSED_MOTION_TYPE = 4, // ConfusedMovementGenerator.h + TARGETED_MOTION_TYPE = 5, // TargetedMovementGenerator.h + HOME_MOTION_TYPE = 6, // HomeMovementGenerator.h + FLIGHT_MOTION_TYPE = 7, // WaypointMovementGenerator.h + POINT_MOTION_TYPE = 8, // PointMovementGenerator.h + FLEEING_MOTION_TYPE = 9, // FleeingMovementGenerator.h + DISTRACT_MOTION_TYPE = 10, // IdleMovementGenerator.h +}; + +class MANGOS_DLL_SPEC MotionMaster : private std::stack +{ + private: + typedef std::stack Impl; + public: + + explicit MotionMaster(Unit *unit) : i_owner(unit) {} + ~MotionMaster(); + + void Initialize(); + + MovementGenerator* operator->(void) { return top(); } + + using Impl::top; + using Impl::empty; + + typedef Impl::container_type::const_iterator const_iterator; + const_iterator begin() const { return Impl::c.begin(); } + const_iterator end() const { return Impl::c.end(); } + + void UpdateMotion(const uint32 &diff); + void Clear(bool reset = true); + void MovementExpired(bool reset = true); + + void MoveIdle(); + void MoveTargetedHome(); + void MoveFollow(Unit* target, float dist, float angle); + void MoveChase(Unit* target, float dist = 0.0f, float angle = 0.0f); + void MoveConfused(); + void MoveFleeing(Unit* enemy); + void MovePoint(uint32 id, float x,float y,float z); + void MoveTaxiFlight(uint32 path, uint32 pathnode); + void MoveDistract(uint32 time); + + MovementGeneratorType GetCurrentMovementGeneratorType() const; + + void propagateSpeedChange(); + + bool GetDestination(float &x, float &y, float &z); + private: + void Mutate(MovementGenerator *m); // use Move* functions instead + + Unit *i_owner; +}; +#endif diff --git a/src/game/MovementGenerator.cpp b/src/game/MovementGenerator.cpp new file mode 100644 index 00000000000..b717f6cf443 --- /dev/null +++ b/src/game/MovementGenerator.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "MovementGenerator.h" + +MovementGenerator::~MovementGenerator() +{ +} diff --git a/src/game/MovementGenerator.h b/src/game/MovementGenerator.h new file mode 100644 index 00000000000..982de574c19 --- /dev/null +++ b/src/game/MovementGenerator.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_MOVEMENTGENERATOR_H +#define MANGOS_MOVEMENTGENERATOR_H + +#include "Platform/Define.h" +#include "Policies/Singleton.h" +#include "Dynamic/ObjectRegistry.h" +#include "Dynamic/FactoryHolder.h" +#include "Common.h" +#include "MotionMaster.h" + +class Unit; + +class MANGOS_DLL_SPEC MovementGenerator +{ + public: + virtual ~MovementGenerator(); + + virtual void Initialize(Unit &) = 0; + virtual void Finalize(Unit &) = 0; + + virtual void Reset(Unit &) = 0; + + virtual bool Update(Unit &, const uint32 &time_diff) = 0; + + virtual MovementGeneratorType GetMovementGeneratorType() = 0; + + virtual void unitSpeedChanged() { } + + virtual bool GetDestination(float& /*x*/, float& /*y*/, float& /*z*/) const { return false; } +}; + +template +class MANGOS_DLL_SPEC MovementGeneratorMedium : public MovementGenerator +{ + public: + void Initialize(Unit &u) + { + //u->AssertIsType(); + (static_cast(this))->Initialize(*((T*)&u)); + } + void Finalize(Unit &u) + { + //u->AssertIsType(); + (static_cast(this))->Finalize(*((T*)&u)); + } + void Reset(Unit &u) + { + //u->AssertIsType(); + (static_cast(this))->Reset(*((T*)&u)); + } + bool Update(Unit &u, const uint32 &time_diff) + { + //u->AssertIsType(); + return (static_cast(this))->Update(*((T*)&u), time_diff); + } + public: + // will not link if not overridden in the generators + void Initialize(T &u); + void Finalize(T &u); + void Reset(T &u); + bool Update(T &u, const uint32 &time_diff); +}; + +struct SelectableMovement : public FactoryHolder +{ + SelectableMovement(MovementGeneratorType mgt) : FactoryHolder(mgt) {} +}; + +template +struct MovementGeneratorFactory : public SelectableMovement +{ + MovementGeneratorFactory(MovementGeneratorType mgt) : SelectableMovement(mgt) {} + + MovementGenerator* Create(void *) const; +}; + +typedef FactoryHolder MovementGeneratorCreator; +typedef FactoryHolder::FactoryHolderRegistry MovementGeneratorRegistry; +typedef FactoryHolder::FactoryHolderRepository MovementGeneratorRepository; +#endif diff --git a/src/game/MovementGeneratorImpl.h b/src/game/MovementGeneratorImpl.h new file mode 100644 index 00000000000..c3859a548f5 --- /dev/null +++ b/src/game/MovementGeneratorImpl.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_MOVEMENTGENERATOR_IMPL_H +#define MANGOS_MOVEMENTGENERATOR_IMPL_H + +#include "MovementGenerator.h" + +template +inline MovementGenerator* +MovementGeneratorFactory::Create(void *data) const +{ + Creature* creature = reinterpret_cast(data); + return (new MOVEMENT_GEN(*creature)); +} +#endif diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp new file mode 100644 index 00000000000..1efd4e3c3e7 --- /dev/null +++ b/src/game/MovementHandler.cpp @@ -0,0 +1,585 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Opcodes.h" +#include "Log.h" +#include "World.h" +#include "Corpse.h" +#include "Player.h" +#include "MapManager.h" +#include "Transports.h" +#include "BattleGround.h" +#include "WaypointMovementGenerator.h" +#include "InstanceSaveMgr.h" + +void WorldSession::HandleMoveWorldportAckOpcode( WorldPacket & /*recv_data*/ ) +{ + sLog.outDebug( "WORLD: got MSG_MOVE_WORLDPORT_ACK." ); + HandleMoveWorldportAckOpcode(); +} + +void WorldSession::HandleMoveWorldportAckOpcode() +{ + // get the teleport destination + WorldLocation &loc = GetPlayer()->GetTeleportDest(); + + // possible errors in the coordinate validity check + if(!MapManager::IsValidMapCoord(loc.mapid,loc.x,loc.y,loc.z,loc.o)) + { + LogoutPlayer(false); + return; + } + + // get the destination map entry, not the current one, this will fix homebind and reset greeting + MapEntry const* mEntry = sMapStore.LookupEntry(loc.mapid); + InstanceTemplate const* mInstance = objmgr.GetInstanceTemplate(loc.mapid); + + // reset instance validity, except if going to an instance inside an instance + if(GetPlayer()->m_InstanceValid == false && !mInstance) + GetPlayer()->m_InstanceValid = true; + + GetPlayer()->SetSemaphoreTeleport(false); + + // relocate the player to the teleport destination + GetPlayer()->SetMapId(loc.mapid); + GetPlayer()->Relocate(loc.x, loc.y, loc.z, loc.o); + + // since the MapId is set before the GetInstance call, the InstanceId must be set to 0 + // to let GetInstance() determine the proper InstanceId based on the player's binds + GetPlayer()->SetInstanceId(0); + + // check this before Map::Add(player), because that will create the instance save! + bool reset_notify = (GetPlayer()->GetBoundInstance(GetPlayer()->GetMapId(), GetPlayer()->GetDifficulty()) == NULL); + + GetPlayer()->SendInitialPacketsBeforeAddToMap(); + // the CanEnter checks are done in TeleporTo but conditions may change + // while the player is in transit, for example the map may get full + if(!MapManager::Instance().GetMap(GetPlayer()->GetMapId(), GetPlayer())->Add(GetPlayer())) + { + sLog.outDebug("WORLD: teleport of player %s (%d) to location %d,%f,%f,%f,%f failed", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), loc.mapid, loc.x, loc.y, loc.z, loc.o); + // teleport the player home + GetPlayer()->SetDontMove(false); + if(!GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation())) + { + // the player must always be able to teleport home + sLog.outError("WORLD: failed to teleport player %s (%d) to homebind location %d,%f,%f,%f,%f!", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation()); + assert(false); + } + return; + } + GetPlayer()->SendInitialPacketsAfterAddToMap(); + + // flight fast teleport case + if(GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType()==FLIGHT_MOTION_TYPE) + { + if(!_player->InBattleGround()) + { + // short preparations to continue flight + GetPlayer()->SetDontMove(false); + FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top()); + flight->Initialize(*GetPlayer()); + return; + } + + // battleground state prepare, stop flight + GetPlayer()->GetMotionMaster()->MovementExpired(); + GetPlayer()->m_taxi.ClearTaxiDestinations(); + } + + // resurrect character at enter into instance where his corpse exist after add to map + Corpse *corpse = GetPlayer()->GetCorpse(); + if (corpse && corpse->GetType() != CORPSE_BONES && corpse->GetMapId() == GetPlayer()->GetMapId()) + { + if( mEntry->IsDungeon() ) + { + GetPlayer()->ResurrectPlayer(0.5f,false); + GetPlayer()->SpawnCorpseBones(); + GetPlayer()->SaveToDB(); + } + } + + if(mEntry->IsRaid() && mInstance) + { + if(reset_notify) + { + uint32 timeleft = sInstanceSaveManager.GetResetTimeFor(GetPlayer()->GetMapId()) - time(NULL); + GetPlayer()->SendInstanceResetWarning(GetPlayer()->GetMapId(), timeleft); // greeting at the entrance of the resort raid instance + } + } + + // mount allow check + if(!mEntry->IsMountAllowed()) + _player->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); + + // battleground state preper + if(_player->InBattleGround()) + { + BattleGround *bg = _player->GetBattleGround(); + if(bg) + { + if(bg->GetMapId() == _player->GetMapId()) // we teleported to bg + { + if(!bg->GetBgRaid(_player->GetTeam())) // first player joined + { + Group *group = new Group; + bg->SetBgRaid(_player->GetTeam(), group); + group->Create(_player->GetGUIDLow(), _player->GetName()); + } + else // raid already exist + { + bg->GetBgRaid(_player->GetTeam())->AddMember(_player->GetGUID(), _player->GetName()); + } + } + } + } + + // honorless target + if(GetPlayer()->pvpInfo.inHostileArea) + GetPlayer()->CastSpell(GetPlayer(), 2479, true); + + // resummon pet + if(GetPlayer()->m_temporaryUnsummonedPetNumber) + { + Pet* NewPet = new Pet; + if(!NewPet->LoadPetFromDB(GetPlayer(), 0, GetPlayer()->m_temporaryUnsummonedPetNumber, true)) + delete NewPet; + + GetPlayer()->m_temporaryUnsummonedPetNumber = 0; + } + + GetPlayer()->SetDontMove(false); +} + +void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data, 4+1+4+4+4+4+4); + + if(GetPlayer()->GetDontMove()) + return; + + /* extract packet */ + MovementInfo movementInfo; + uint32 MovementFlags; + + recv_data >> MovementFlags; + recv_data >> movementInfo.unk1; + recv_data >> movementInfo.time; + recv_data >> movementInfo.x; + recv_data >> movementInfo.y; + recv_data >> movementInfo.z; + recv_data >> movementInfo.o; + + //Save movement flags + _player->SetUnitMovementFlags(MovementFlags); + + if(MovementFlags & MOVEMENTFLAG_ONTRANSPORT) + { + // recheck + CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+8+4+4+4+4+4); + + recv_data >> movementInfo.t_guid; + recv_data >> movementInfo.t_x; + recv_data >> movementInfo.t_y; + recv_data >> movementInfo.t_z; + recv_data >> movementInfo.t_o; + recv_data >> movementInfo.t_time; + } + + if(MovementFlags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2)) + { + // recheck + CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4); + + recv_data >> movementInfo.s_pitch; // pitch, -1.55=looking down, 0=looking straight forward, +1.55=looking up + } + + // recheck + CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4); + + recv_data >> movementInfo.fallTime; // duration of last jump (when in jump duration from jump begin to now) + + if(MovementFlags & MOVEMENTFLAG_JUMPING) + { + // recheck + CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4+4+4+4); + + recv_data >> movementInfo.j_unk; // constant, but different when jumping in water and on land? + recv_data >> movementInfo.j_sinAngle; // sin of angle between orientation0 and players orientation + recv_data >> movementInfo.j_cosAngle; // cos of angle between orientation0 and players orientation + recv_data >> movementInfo.j_xyspeed; // speed of xy movement + } + + if(MovementFlags & MOVEMENTFLAG_SPLINE) + { + // recheck + CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4); + + recv_data >> movementInfo.u_unk1; // unknown + } + /*----------------*/ + + if(recv_data.size() != recv_data.rpos()) + { + sLog.outError("MovementHandler: player %s (guid %d, account %u) sent a packet (opcode %u) that is %u bytes larger than it should be. Kicked as cheater.", _player->GetName(), _player->GetGUIDLow(), _player->GetSession()->GetAccountId(), recv_data.GetOpcode(), recv_data.size() - recv_data.rpos()); + KickPlayer(); + return; + } + + if (!MaNGOS::IsValidMapCoord(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o)) + return; + + /* handle special cases */ + if (MovementFlags & MOVEMENTFLAG_ONTRANSPORT) + { + // transports size limited + // (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped) + if( movementInfo.t_x > 50 || movementInfo.t_y > 50 || movementInfo.t_z > 50 ) + return; + + if( !MaNGOS::IsValidMapCoord(movementInfo.x+movementInfo.t_x, movementInfo.y+movementInfo.t_y, + movementInfo.z+movementInfo.t_z, movementInfo.o+movementInfo.t_o) ) + return; + + // if we boarded a transport, add us to it + if (!GetPlayer()->m_transport) + { + // elevators also cause the client to send MOVEMENTFLAG_ONTRANSPORT - just unmount if the guid can be found in the transport list + for (MapManager::TransportSet::iterator iter = MapManager::Instance().m_Transports.begin(); iter != MapManager::Instance().m_Transports.end(); ++iter) + { + if ((*iter)->GetGUID() == movementInfo.t_guid) + { + // unmount before boarding + _player->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); + + GetPlayer()->m_transport = (*iter); + (*iter)->AddPassenger(GetPlayer()); + break; + } + } + } + } + else if (GetPlayer()->m_transport) // if we were on a transport, leave + { + GetPlayer()->m_transport->RemovePassenger(GetPlayer()); + GetPlayer()->m_transport = NULL; + movementInfo.t_x = 0.0f; + movementInfo.t_y = 0.0f; + movementInfo.t_z = 0.0f; + movementInfo.t_o = 0.0f; + movementInfo.t_time = 0; + } + + // fall damage generation (ignore in flight case that can be triggred also at lags in moment teleportation to another map). + if (recv_data.GetOpcode() == MSG_MOVE_FALL_LAND && !GetPlayer()->isInFlight()) + { + Player *target = GetPlayer(); + + //Players with Feather Fall or low fall time, or physical immunity (charges used) are ignored + if (movementInfo.fallTime > 1100 && !target->isDead() && !target->isGameMaster() && + !target->HasAuraType(SPELL_AURA_HOVER) && !target->HasAuraType(SPELL_AURA_FEATHER_FALL) && + !target->HasAuraType(SPELL_AURA_FLY) && !target->IsImmunedToDamage(SPELL_SCHOOL_MASK_NORMAL,true) ) + { + //Safe fall, fall time reduction + int32 safe_fall = target->GetTotalAuraModifier(SPELL_AURA_SAFE_FALL); + uint32 fall_time = (movementInfo.fallTime > (safe_fall*10)) ? movementInfo.fallTime - (safe_fall*10) : 0; + + if(fall_time > 1100) //Prevent damage if fall time < 1100 + { + //Fall Damage calculation + float fallperc = float(fall_time)/1100; + uint32 damage = (uint32)(((fallperc*fallperc -1) / 9 * target->GetMaxHealth())*sWorld.getRate(RATE_DAMAGE_FALL)); + + float height = movementInfo.z; + target->UpdateGroundPositionZ(movementInfo.x,movementInfo.y,height); + + if (damage > 0) + { + //Prevent fall damage from being more than the player maximum health + if (damage > target->GetMaxHealth()) + damage = target->GetMaxHealth(); + + // Gust of Wind + if (target->GetDummyAura(43621)) + damage = target->GetMaxHealth()/2; + + target->EnvironmentalDamage(target->GetGUID(), DAMAGE_FALL, damage); + } + + //Z given by moveinfo, LastZ, FallTime, WaterZ, MapZ, Damage, Safefall reduction + DEBUG_LOG("FALLDAMAGE z=%f sz=%f pZ=%f FallTime=%d mZ=%f damage=%d SF=%d" , movementInfo.z, height, target->GetPositionZ(), movementInfo.fallTime, height, damage, safe_fall); + } + } + + //handle fall and logout at the same time (logout started before fall finished) + /* outdated and create problems with sit at stun sometime + if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE)) + { + target->SetStandState(PLAYER_STATE_SIT); + // Can't move + WorldPacket data( SMSG_FORCE_MOVE_ROOT, 12 ); + data.append(target->GetPackGUID()); + data << (uint32)2; + SendPacket( &data ); + } + */ + } + + if(((MovementFlags & MOVEMENTFLAG_SWIMMING) != 0) != GetPlayer()->IsInWater()) + { + // now client not include swimming flag in case jumping under water + GetPlayer()->SetInWater( !GetPlayer()->IsInWater() || GetPlayer()->GetBaseMap()->IsUnderWater(movementInfo.x, movementInfo.y, movementInfo.z) ); + } + + /*----------------------*/ + + /* process position-change */ + recv_data.put(5, getMSTime()); // offset flags(4) + unk(1) + WorldPacket data(recv_data.GetOpcode(), (GetPlayer()->GetPackGUID().size()+recv_data.size())); + data.append(GetPlayer()->GetPackGUID()); + data.append(recv_data.contents(), recv_data.size()); + GetPlayer()->SendMessageToSet(&data, false); + + GetPlayer()->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); + GetPlayer()->m_movementInfo = movementInfo; + + if(GetPlayer()->isMovingOrTurning()) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + if(movementInfo.z < -500.0f) + { + // NOTE: this is actually called many times while falling + // even after the player has been teleported away + // TODO: discard movement packets after the player is rooted + if(GetPlayer()->isAlive()) + { + GetPlayer()->EnvironmentalDamage(GetPlayer()->GetGUID(),DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth()); + // change the death state to CORPSE to prevent the death timer from + // starting in the next player update + GetPlayer()->KillPlayer(); + GetPlayer()->BuildPlayerRepop(); + } + + // cancel the death timer here if started + GetPlayer()->RepopAtGraveyard(); + } +} + +void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data) +{ + CHECK_PACKET_SIZE(recv_data, 8+4+4+1+4+4+4+4+4); + + /* extract packet */ + uint64 guid; + uint8 unkB; + uint32 unk1, flags, time, fallTime; + float x, y, z, orientation; + + uint64 t_GUID; + float t_x, t_y, t_z, t_o; + uint32 t_time; + float s_pitch; + float j_unk1, j_sinAngle, j_cosAngle, j_xyspeed; + float u_unk1; + float newspeed; + + recv_data >> guid; + + // now can skip not our packet + if(_player->GetGUID() != guid) + return; + + // continue parse packet + + recv_data >> unk1; + recv_data >> flags >> unkB >> time; + recv_data >> x >> y >> z >> orientation; + if (flags & MOVEMENTFLAG_ONTRANSPORT) + { + // recheck + CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+8+4+4+4+4+4); + + recv_data >> t_GUID; + recv_data >> t_x >> t_y >> t_z >> t_o >> t_time; + } + if (flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2)) + { + // recheck + CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4); + + recv_data >> s_pitch; // pitch, -1.55=looking down, 0=looking straight forward, +1.55=looking up + } + + // recheck + CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4); + + recv_data >> fallTime; // duration of last jump (when in jump duration from jump begin to now) + + if ((flags & MOVEMENTFLAG_JUMPING) || (flags & MOVEMENTFLAG_FALLING)) + { + // recheck + CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4+4+4+4); + + recv_data >> j_unk1; // ?constant, but different when jumping in water and on land? + recv_data >> j_sinAngle >> j_cosAngle; // sin + cos of angle between orientation0 and players orientation + recv_data >> j_xyspeed; // speed of xy movement + } + + if(flags & MOVEMENTFLAG_SPLINE) + { + // recheck + CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4); + + recv_data >> u_unk1; // unknown + } + + // recheck + CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4); + + recv_data >> newspeed; + /*----------------*/ + + // client ACK send one packet for mounted/run case and need skip all except last from its + // in other cases anti-cheat check can be fail in false case + UnitMoveType move_type; + UnitMoveType force_move_type; + + static char const* move_type_name[MAX_MOVE_TYPE] = { "Walk", "Run", "Walkback", "Swim", "Swimback", "Turn", "Fly", "Flyback" }; + + uint16 opcode = recv_data.GetOpcode(); + switch(opcode) + { + case CMSG_FORCE_WALK_SPEED_CHANGE_ACK: move_type = MOVE_WALK; force_move_type = MOVE_WALK; break; + case CMSG_FORCE_RUN_SPEED_CHANGE_ACK: move_type = MOVE_RUN; force_move_type = MOVE_RUN; break; + case CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK: move_type = MOVE_WALKBACK; force_move_type = MOVE_WALKBACK; break; + case CMSG_FORCE_SWIM_SPEED_CHANGE_ACK: move_type = MOVE_SWIM; force_move_type = MOVE_SWIM; break; + case CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK: move_type = MOVE_SWIMBACK; force_move_type = MOVE_SWIMBACK; break; + case CMSG_FORCE_TURN_RATE_CHANGE_ACK: move_type = MOVE_TURN; force_move_type = MOVE_TURN; break; + case CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK: move_type = MOVE_FLY; force_move_type = MOVE_FLY; break; + case CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK: move_type = MOVE_FLYBACK; force_move_type = MOVE_FLYBACK; break; + default: + sLog.outError("WorldSession::HandleForceSpeedChangeAck: Unknown move type opcode: %u", opcode); + return; + } + + // skip all forced speed changes except last and unexpected + // in run/mounted case used one ACK and it must be skipped.m_forced_speed_changes[MOVE_RUN} store both. + if(_player->m_forced_speed_changes[force_move_type] > 0) + { + --_player->m_forced_speed_changes[force_move_type]; + if(_player->m_forced_speed_changes[force_move_type] > 0) + return; + } + + if (!_player->GetTransport() && fabs(_player->GetSpeed(move_type) - newspeed) > 0.01f) + { + if(_player->GetSpeed(move_type) > newspeed) // must be greater - just correct + { + sLog.outError("%sSpeedChange player %s is NOT correct (must be %f instead %f), force set to correct value", + move_type_name[move_type], _player->GetName(), _player->GetSpeed(move_type), newspeed); + _player->SetSpeed(move_type,_player->GetSpeedRate(move_type),true); + } + else // must be lesser - cheating + { + sLog.outBasic("Player %s from account id %u kicked for incorrect speed (must be %f instead %f)", + _player->GetName(),_player->GetSession()->GetAccountId(),_player->GetSpeed(move_type), newspeed); + _player->GetSession()->KickPlayer(); + } + } +} + +void WorldSession::HandleSetActiveMoverOpcode(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: Recvd CMSG_SET_ACTIVE_MOVER"); + + CHECK_PACKET_SIZE(recv_data,8); + + uint64 guid; + recv_data >> guid; + + WorldPacket data(SMSG_TIME_SYNC_REQ, 4); // new 2.0.x, enable movement + data << uint32(0x00000000); // on blizz it increments periodically + SendPacket(&data); +} + +void WorldSession::HandleMountSpecialAnimOpcode(WorldPacket& /*recvdata*/) +{ + //sLog.outDebug("WORLD: Recvd CMSG_MOUNTSPECIAL_ANIM"); + + WorldPacket data(SMSG_MOUNTSPECIAL_ANIM, 8); + data << uint64(GetPlayer()->GetGUID()); + + GetPlayer()->SendMessageToSet(&data, false); +} + +void WorldSession::HandleMoveKnockBackAck( WorldPacket & /*recv_data*/ ) +{ + // CHECK_PACKET_SIZE(recv_data,?); + sLog.outDebug("CMSG_MOVE_KNOCK_BACK_ACK"); + // Currently not used but maybe use later for recheck final player position + // (must be at call same as into "recv_data >> x >> y >> z >> orientation;" + + /* + uint32 flags, time; + float x, y, z, orientation; + uint64 guid; + uint32 sequence; + uint32 ukn1; + float xdirection,ydirection,hspeed,vspeed; + + recv_data >> guid; + recv_data >> sequence; + recv_data >> flags >> time; + recv_data >> x >> y >> z >> orientation; + recv_data >> ukn1; //unknown + recv_data >> vspeed >> xdirection >> ydirection >> hspeed; + + // skip not personal message; + if(GetPlayer()->GetGUID()!=guid) + return; + + // check code + */ +} + +void WorldSession::HandleMoveHoverAck( WorldPacket& /*recv_data*/ ) +{ + sLog.outDebug("CMSG_MOVE_HOVER_ACK"); +} + +void WorldSession::HandleMoveWaterWalkAck(WorldPacket& /*recv_data*/) +{ + sLog.outDebug("CMSG_MOVE_WATER_WALK_ACK"); +} + +void WorldSession::HandleSummonResponseOpcode(WorldPacket& recv_data) +{ + CHECK_PACKET_SIZE(recv_data,8+1); + + if(!_player->isAlive() || _player->isInCombat() ) + return; + + uint64 summoner_guid; + bool agree; + recv_data >> summoner_guid; + recv_data >> agree; + + _player->SummonIfPossible(agree); +} diff --git a/src/game/NPCHandler.cpp b/src/game/NPCHandler.cpp new file mode 100644 index 00000000000..5739f56e328 --- /dev/null +++ b/src/game/NPCHandler.cpp @@ -0,0 +1,832 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Language.h" +#include "Database/DatabaseEnv.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Opcodes.h" +#include "Log.h" +#include "World.h" +#include "ObjectMgr.h" +#include "SpellMgr.h" +#include "Player.h" +#include "GossipDef.h" +#include "SpellAuras.h" +#include "UpdateMask.h" +#include "ScriptCalls.h" +#include "ObjectAccessor.h" +#include "Creature.h" +#include "MapManager.h" +#include "Pet.h" +#include "BattleGroundMgr.h" +#include "BattleGround.h" +#include "Guild.h" + +void WorldSession::HandleTabardVendorActivateOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8); + + uint64 guid; + recv_data >> guid; + + Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_TABARDDESIGNER); + if (!unit) + { + sLog.outDebug( "WORLD: HandleTabardVendorActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); + return; + } + + // remove fake death + if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + SendTabardVendorActivate(guid); +} + +void WorldSession::SendTabardVendorActivate( uint64 guid ) +{ + WorldPacket data( MSG_TABARDVENDOR_ACTIVATE, 8 ); + data << guid; + SendPacket( &data ); +} + +void WorldSession::HandleBankerActivateOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8); + + uint64 guid; + + sLog.outDebug( "WORLD: Received CMSG_BANKER_ACTIVATE" ); + + recv_data >> guid; + + Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_BANKER); + if (!unit) + { + sLog.outDebug( "WORLD: HandleBankerActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); + return; + } + + // remove fake death + if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + SendShowBank(guid); +} + +void WorldSession::SendShowBank( uint64 guid ) +{ + WorldPacket data( SMSG_SHOW_BANK, 8 ); + data << guid; + SendPacket( &data ); +} + +void WorldSession::HandleTrainerListOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8); + + uint64 guid; + + recv_data >> guid; + SendTrainerList( guid ); +} + +void WorldSession::SendTrainerList( uint64 guid ) +{ + std::string str = GetMangosString(LANG_NPC_TAINER_HELLO); + SendTrainerList( guid, str ); +} + +void WorldSession::SendTrainerList( uint64 guid,std::string strTitle ) +{ + sLog.outDebug( "WORLD: SendTrainerList" ); + + Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_TRAINER); + if (!unit) + { + sLog.outDebug( "WORLD: SendTrainerList - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); + return; + } + + // remove fake death + if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + // Lazy loading at first access + unit->LoadTrainerSpells(); + + // trainer list loaded at check; + if(!unit->isCanTrainingOf(_player,true)) + return; + + CreatureInfo const *ci = unit->GetCreatureInfo(); + + if (!ci) + { + sLog.outDebug( "WORLD: SendTrainerList - (%u) NO CREATUREINFO! (GUID: %u)", uint32(GUID_LOPART(guid)), guid ); + return; + } + + Creature::SpellsList const& trainer_spells = unit->GetTrainerSpells(); + + WorldPacket data( SMSG_TRAINER_LIST, 8+4+4+trainer_spells.size()*38 + strTitle.size()+1); + data << guid; + data << uint32(unit->GetTrainerType()); + + size_t count_pos = data.wpos(); + data << uint32(trainer_spells.size()); + + // reputation discount + float fDiscountMod = _player->GetReputationPriceDiscount(unit); + + uint32 count = 0; + for(Creature::SpellsList::const_iterator itr = trainer_spells.begin(); itr != trainer_spells.end(); ++itr) + { + if(!_player->IsSpellFitByClassAndRace(itr->spell->Id)) + continue; + + ++count; + + bool primary_prof_first_rank = spellmgr.IsPrimaryProfessionFirstRankSpell(itr->spell->Id); + + SpellChainNode const* chain_node = spellmgr.GetSpellChainNode(itr->spell->Id); + + data << uint32(itr->spell->Id); + data << uint8(_player->GetTrainerSpellState(&*itr)); + data << uint32(floor(itr->spellcost * fDiscountMod)); + + data << uint32(primary_prof_first_rank ? 1 : 0); // primary prof. learn confirmation dialog + data << uint32(primary_prof_first_rank ? 1 : 0); // must be equal prev. field to have learn button in enabled state + data << uint8(itr->reqlevel ? itr->reqlevel : itr->spell->spellLevel); + data << uint32(itr->reqskill); + data << uint32(itr->reqskillvalue); + data << uint32(chain_node ? (chain_node->prev ? chain_node->prev : chain_node->req) : 0); + data << uint32(chain_node && chain_node->prev ? chain_node->req : 0); + data << uint32(0); + } + + data << strTitle; + + data.put(count_pos,count); + SendPacket( &data ); +} + +void WorldSession::HandleTrainerBuySpellOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+4); + + uint64 guid; + uint32 spellId = 0; + + recv_data >> guid >> spellId; + sLog.outDebug( "WORLD: Received CMSG_TRAINER_BUY_SPELL NpcGUID=%u, learn spell id is: %u",uint32(GUID_LOPART(guid)), spellId ); + + Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_TRAINER); + if (!unit) + { + sLog.outDebug( "WORLD: HandleTrainerBuySpellOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); + return; + } + + // remove fake death + if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + // Lazy loading at first access + unit->LoadTrainerSpells(); + + if(!unit->isCanTrainingOf(_player,true)) + return; + + TrainerSpell const* trainer_spell = NULL; + + // check present spell in trainer spell list + Creature::SpellsList const& trainer_spells = unit->GetTrainerSpells(); + for(Creature::SpellsList::const_iterator itr = trainer_spells.begin(); itr != trainer_spells.end(); ++itr) + { + if(itr->spell->Id == spellId) + { + trainer_spell = &*itr; + break; + } + } + + // not found, cheat? + if(!trainer_spell) + return; + + // can't be learn, cheat? Or double learn with lags... + if(_player->GetTrainerSpellState(trainer_spell) != TRAINER_SPELL_GREEN) + return; + + // apply reputation discount + uint32 nSpellCost = uint32(floor(trainer_spell->spellcost * _player->GetReputationPriceDiscount(unit))); + + // check money requirement + if(_player->GetMoney() < nSpellCost ) + return; + + WorldPacket data(SMSG_PLAY_SPELL_VISUAL, 12); // visual effect on trainer + data << uint64(guid) << uint32(0xB3); + SendPacket(&data); + + data.Initialize(SMSG_PLAY_SPELL_IMPACT, 12); // visual effect on player + data << uint64(_player->GetGUID()) << uint32(0x016A); + SendPacket(&data); + + _player->ModifyMoney( -int32(nSpellCost) ); + + // learn explicitly to prevent lost money at lags, learning spell will be only show spell animation + _player->learnSpell(trainer_spell->spell->Id); + + data.Initialize(SMSG_TRAINER_BUY_SUCCEEDED, 12); + data << uint64(guid) << uint32(spellId); + SendPacket(&data); +} + +void WorldSession::HandleGossipHelloOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8); + + sLog.outDebug( "WORLD: Received CMSG_GOSSIP_HELLO" ); + + uint64 guid; + recv_data >> guid; + + Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_NONE); + if (!unit) + { + sLog.outDebug( "WORLD: HandleGossipHelloOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); + return; + } + + // remove fake death + if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + if( unit->isArmorer() || unit->isCivilian() || unit->isQuestGiver() || unit->isServiceProvider()) + { + unit->StopMoving(); + } + + // If spiritguide, no need for gossip menu, just put player into resurrect queue + if (unit->isSpiritGuide()) + { + BattleGround *bg = _player->GetBattleGround(); + if(bg) + { + bg->AddPlayerToResurrectQueue(unit->GetGUID(), _player->GetGUID()); + sBattleGroundMgr.SendAreaSpiritHealerQueryOpcode(_player, bg, unit->GetGUID()); + return; + } + } + + if(!Script->GossipHello( _player, unit )) + { + _player->TalkedToCreature(unit->GetEntry(),unit->GetGUID()); + unit->prepareGossipMenu(_player,0); + unit->sendPreparedGossip( _player ); + } +} + +void WorldSession::HandleGossipSelectOptionOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+4+4); + + sLog.outDebug("WORLD: CMSG_GOSSIP_SELECT_OPTION"); + + uint32 option; + uint32 unk; + uint64 guid; + std::string code = ""; + + recv_data >> guid >> unk >> option; + + if(_player->PlayerTalkClass->GossipOptionCoded( option )) + { + // recheck + CHECK_PACKET_SIZE(recv_data,8+4+1); + sLog.outBasic("reading string"); + recv_data >> code; + sLog.outBasic("string read: %s", code.c_str()); + } + + Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_NONE); + if (!unit) + { + sLog.outDebug( "WORLD: HandleGossipSelectOptionOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); + return; + } + + // remove fake death + if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + if(!code.empty()) + { + + if(!Script->GossipSelectWithCode( _player, unit, _player->PlayerTalkClass->GossipOptionSender( option ), _player->PlayerTalkClass->GossipOptionAction( option ), code.c_str()) ) + unit->OnGossipSelect( _player, option ); + } + else + + if(!Script->GossipSelect( _player, unit, _player->PlayerTalkClass->GossipOptionSender( option ), _player->PlayerTalkClass->GossipOptionAction( option )) ) + unit->OnGossipSelect( _player, option ); +} + +void WorldSession::HandleSpiritHealerActivateOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8); + + sLog.outDebug("WORLD: CMSG_SPIRIT_HEALER_ACTIVATE"); + + uint64 guid; + + recv_data >> guid; + + Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_SPIRITHEALER); + if (!unit) + { + sLog.outDebug( "WORLD: HandleSpiritHealerActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); + return; + } + + // remove fake death + if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + SendSpiritResurrect(); +} + +void WorldSession::SendSpiritResurrect() +{ + _player->ResurrectPlayer(0.5f,false, true); + + _player->DurabilityLossAll(0.25f,true); + + // get corpse nearest graveyard + WorldSafeLocsEntry const *corpseGrave = NULL; + Corpse *corpse = _player->GetCorpse(); + if(corpse) + corpseGrave = objmgr.GetClosestGraveYard( + corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetMapId(), _player->GetTeam() ); + + // now can spawn bones + _player->SpawnCorpseBones(); + + // teleport to nearest from corpse graveyard, if different from nearest to player ghost + if(corpseGrave) + { + WorldSafeLocsEntry const *ghostGrave = objmgr.GetClosestGraveYard( + _player->GetPositionX(), _player->GetPositionY(), _player->GetPositionZ(), _player->GetMapId(), _player->GetTeam() ); + + if(corpseGrave != ghostGrave) + _player->TeleportTo(corpseGrave->map_id, corpseGrave->x, corpseGrave->y, corpseGrave->z, _player->GetOrientation()); + // or update at original position + else + ObjectAccessor::UpdateVisibilityForPlayer(_player); + } + // or update at original position + else + ObjectAccessor::UpdateVisibilityForPlayer(_player); + + _player->SaveToDB(); +} + +void WorldSession::HandleBinderActivateOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8); + + uint64 npcGUID; + recv_data >> npcGUID; + + if(!GetPlayer()->isAlive()) + return; + + Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID,UNIT_NPC_FLAG_INNKEEPER); + if (!unit) + { + sLog.outDebug( "WORLD: HandleBinderActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) ); + return; + } + + // remove fake death + if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + SendBindPoint(unit); +} + +void WorldSession::SendBindPoint(Creature *npc) +{ + uint32 bindspell = 3286; + + // update sql homebind + CharacterDatabase.PExecute("UPDATE character_homebind SET map = '%u', zone = '%u', position_x = '%f', position_y = '%f', position_z = '%f' WHERE guid = '%u'", _player->GetMapId(), _player->GetZoneId(), _player->GetPositionX(), _player->GetPositionY(), _player->GetPositionZ(), _player->GetGUIDLow()); + _player->m_homebindMapId = _player->GetMapId(); + _player->m_homebindZoneId = _player->GetZoneId(); + _player->m_homebindX = _player->GetPositionX(); + _player->m_homebindY = _player->GetPositionY(); + _player->m_homebindZ = _player->GetPositionZ(); + + // send spell for bind 3286 bind magic + npc->CastSpell(_player, bindspell, true); + + WorldPacket data( SMSG_TRAINER_BUY_SUCCEEDED, (8+4)); + data << npc->GetGUID(); + data << bindspell; + SendPacket( &data ); + + // binding + data.Initialize( SMSG_BINDPOINTUPDATE, (4+4+4+4+4) ); + data << float(_player->GetPositionX()); + data << float(_player->GetPositionY()); + data << float(_player->GetPositionZ()); + data << uint32(_player->GetMapId()); + data << uint32(_player->GetZoneId()); + SendPacket( &data ); + + DEBUG_LOG("New Home Position X is %f",_player->GetPositionX()); + DEBUG_LOG("New Home Position Y is %f",_player->GetPositionY()); + DEBUG_LOG("New Home Position Z is %f",_player->GetPositionZ()); + DEBUG_LOG("New Home MapId is %u",_player->GetMapId()); + DEBUG_LOG("New Home ZoneId is %u",_player->GetZoneId()); + + // zone update + data.Initialize( SMSG_PLAYERBOUND, 8+4 ); + data << uint64(_player->GetGUID()); + data << uint32(_player->GetZoneId()); + SendPacket( &data ); + + _player->PlayerTalkClass->CloseGossip(); +} + +//Need fix +void WorldSession::HandleListStabledPetsOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8); + + sLog.outDebug("WORLD: Recv MSG_LIST_STABLED_PETS"); + uint64 npcGUID; + + recv_data >> npcGUID; + + Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER); + if (!unit) + { + sLog.outDebug( "WORLD: HandleListStabledPetsOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) ); + return; + } + + // remove fake death + if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + SendStablePet(npcGUID); +} + +void WorldSession::SendStablePet(uint64 guid ) +{ + sLog.outDebug("WORLD: Recv MSG_LIST_STABLED_PETS Send."); + + WorldPacket data(MSG_LIST_STABLED_PETS, 200); // guess size + data << uint64 ( guid ); + + Pet *pet = _player->GetPet(); + + data << uint8(0); // place holder for slot show number + data << uint8(GetPlayer()->m_stableSlots); + + uint8 num = 0; // counter for place holder + + // not let move dead pet in slot + if(pet && pet->isAlive() && pet->getPetType()==HUNTER_PET) + { + data << uint32(pet->GetCharmInfo()->GetPetNumber()); + data << uint32(pet->GetEntry()); + data << uint32(pet->getLevel()); + data << pet->GetName(); // petname + data << uint32(pet->GetLoyaltyLevel()); // loyalty + data << uint8(0x01); // client slot 1 == current pet (0) + ++num; + } + + // 0 1 2 3 4 5 6 + QueryResult* result = CharacterDatabase.PQuery("SELECT owner, slot, id, entry, level, loyalty, name FROM character_pet WHERE owner = '%u' AND slot > 0 AND slot < 3",_player->GetGUIDLow()); + + if(result) + { + do + { + Field *fields = result->Fetch(); + + data << uint32(fields[2].GetUInt32()); // petnumber + data << uint32(fields[3].GetUInt32()); // creature entry + data << uint32(fields[4].GetUInt32()); // level + data << fields[6].GetString(); // name + data << uint32(fields[5].GetUInt32()); // loyalty + data << uint8(fields[1].GetUInt32()+1); // slot + + ++num; + }while( result->NextRow() ); + + delete result; + } + + data.put(8, num); // set real data to placeholder + SendPacket(&data); +} + +void WorldSession::HandleStablePet( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8); + + sLog.outDebug("WORLD: Recv CMSG_STABLE_PET not dispose."); + uint64 npcGUID; + + recv_data >> npcGUID; + + if(!GetPlayer()->isAlive()) + return; + + Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER); + if (!unit) + { + sLog.outDebug( "WORLD: HandleStablePet - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) ); + return; + } + + // remove fake death + if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + Pet *pet = _player->GetPet(); + + WorldPacket data(SMSG_STABLE_RESULT, 200); // guess size + + // can't place in stable dead pet + if(!pet||!pet->isAlive()||pet->getPetType()!=HUNTER_PET) + { + data << uint8(0x06); + SendPacket(&data); + return; + } + + uint32 free_slot = 1; + + QueryResult *result = CharacterDatabase.PQuery("SELECT owner,slot,id FROM character_pet WHERE owner = '%u' AND slot > 0 AND slot < 3 ORDER BY slot ",_player->GetGUIDLow()); + if(result) + { + do + { + Field *fields = result->Fetch(); + + uint32 slot = fields[1].GetUInt32(); + + if(slot==free_slot) // this slot not free + ++free_slot; + }while( result->NextRow() ); + } + delete result; + + if( free_slot > 0 && free_slot <= GetPlayer()->m_stableSlots) + { + _player->RemovePet(pet,PetSaveMode(free_slot)); + data << uint8(0x08); + } + else + data << uint8(0x06); + + SendPacket(&data); +} + +void WorldSession::HandleUnstablePet( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+4); + + sLog.outDebug("WORLD: Recv CMSG_UNSTABLE_PET."); + uint64 npcGUID; + uint32 petnumber; + + recv_data >> npcGUID >> petnumber; + + Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER); + if (!unit) + { + sLog.outDebug( "WORLD: HandleUnstablePet - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) ); + return; + } + + // remove fake death + if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + WorldPacket data(SMSG_STABLE_RESULT, 200); // guess size + + Pet* pet = _player->GetPet(); + if(pet && pet->isAlive()) + { + uint8 i = 0x06; + data << uint8(i); + SendPacket(&data); + return; + } + + // delete dead pet + if(pet) + _player->RemovePet(pet,PET_SAVE_AS_DELETED); + + Pet *newpet = NULL; + + QueryResult *result = CharacterDatabase.PQuery("SELECT entry FROM character_pet WHERE owner = '%u' AND id = '%u' AND slot > 0 AND slot < 3",_player->GetGUIDLow(),petnumber); + if(result) + { + Field *fields = result->Fetch(); + uint32 petentry = fields[0].GetUInt32(); + + newpet = new Pet(HUNTER_PET); + if(!newpet->LoadPetFromDB(_player,petentry,petnumber)) + { + delete newpet; + newpet = NULL; + } + delete result; + } + + if(newpet) + data << uint8(0x09); + else + data << uint8(0x06); + SendPacket(&data); +} + +void WorldSession::HandleBuyStableSlot( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8); + + sLog.outDebug("WORLD: Recv CMSG_BUY_STABLE_SLOT."); + uint64 npcGUID; + + recv_data >> npcGUID; + + Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER); + if (!unit) + { + sLog.outDebug( "WORLD: HandleBuyStableSlot - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) ); + return; + } + + // remove fake death + if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + WorldPacket data(SMSG_STABLE_RESULT, 200); + + if(GetPlayer()->m_stableSlots < 2) // max slots amount = 2 + { + StableSlotPricesEntry const *SlotPrice = sStableSlotPricesStore.LookupEntry(GetPlayer()->m_stableSlots+1); + if(_player->GetMoney() >= SlotPrice->Price) + { + ++GetPlayer()->m_stableSlots; + _player->ModifyMoney(-int32(SlotPrice->Price)); + data << uint8(0x0A); // success buy + } + else + data << uint8(0x06); + } + else + data << uint8(0x06); + + SendPacket(&data); +} + +void WorldSession::HandleStableRevivePet( WorldPacket &/* recv_data */) +{ + sLog.outDebug("HandleStableRevivePet: Not implemented"); +} + +void WorldSession::HandleStableSwapPet( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+4); + + sLog.outDebug("WORLD: Recv CMSG_STABLE_SWAP_PET."); + uint64 npcGUID; + uint32 pet_number; + + recv_data >> npcGUID >> pet_number; + + Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER); + if (!unit) + { + sLog.outDebug( "WORLD: HandleStableSwapPet - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) ); + return; + } + + // remove fake death + if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + WorldPacket data(SMSG_STABLE_RESULT, 200); // guess size + + Pet* pet = _player->GetPet(); + + if(!pet || pet->getPetType()!=HUNTER_PET) + return; + + // find swapped pet slot in stable + QueryResult *result = CharacterDatabase.PQuery("SELECT slot,entry FROM character_pet WHERE owner = '%u' AND id = '%u'",_player->GetGUIDLow(),pet_number); + if(!result) + return; + + Field *fields = result->Fetch(); + + uint32 slot = fields[0].GetUInt32(); + uint32 petentry = fields[1].GetUInt32(); + delete result; + + // move alive pet to slot or delele dead pet + _player->RemovePet(pet,pet->isAlive() ? PetSaveMode(slot) : PET_SAVE_AS_DELETED); + + // summon unstabled pet + Pet *newpet = new Pet; + if(!newpet->LoadPetFromDB(_player,petentry,pet_number)) + { + delete newpet; + data << uint8(0x06); + } + else + data << uint8(0x09); + + SendPacket(&data); +} + +void WorldSession::HandleRepairItemOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+8+1); + + sLog.outDebug("WORLD: CMSG_REPAIR_ITEM"); + + uint64 npcGUID, itemGUID; + uint8 guildBank; // new in 2.3.2, bool that means from guild bank money + + recv_data >> npcGUID >> itemGUID >> guildBank; + + Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_REPAIR); + if (!unit) + { + sLog.outDebug( "WORLD: HandleRepairItemOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) ); + return; + } + + // remove fake death + if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + // reputation discount + float discountMod = _player->GetReputationPriceDiscount(unit); + + uint32 TotalCost = 0; + if (itemGUID) + { + sLog.outDebug("ITEM: Repair item, itemGUID = %u, npcGUID = %u", GUID_LOPART(itemGUID), GUID_LOPART(npcGUID)); + + Item* item = _player->GetItemByGuid(itemGUID); + + if(item) + TotalCost= _player->DurabilityRepair(item->GetPos(),true,discountMod,guildBank>0?true:false); + } + else + { + sLog.outDebug("ITEM: Repair all items, npcGUID = %u", GUID_LOPART(npcGUID)); + + TotalCost = _player->DurabilityRepairAll(true,discountMod,guildBank>0?true:false); + } + if (guildBank) + { + uint32 GuildId = _player->GetGuildId(); + if (!GuildId) + return; + Guild *pGuild = objmgr.GetGuildById(GuildId); + if (!pGuild) + return; + pGuild->LogBankEvent(GUILD_BANK_LOG_REPAIR_MONEY, 0, _player->GetGUIDLow(), TotalCost); + pGuild->SendMoneyInfo(this, _player->GetGUIDLow()); + } +} diff --git a/src/game/NPCHandler.h b/src/game/NPCHandler.h new file mode 100644 index 00000000000..1f42be22969 --- /dev/null +++ b/src/game/NPCHandler.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __NPCHANDLER_H +#define __NPCHANDLER_H + +// GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push,N), also any gcc version not support it at some platform +#if defined( __GNUC__ ) +#pragma pack(1) +#else +#pragma pack(push,1) +#endif + +struct PageText +{ + uint32 Page_ID; + char * Text; + + uint32 Next_Page; +}; + +// GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some platform +#if defined( __GNUC__ ) +#pragma pack() +#else +#pragma pack(pop) +#endif + +struct QEmote +{ + uint32 _Emote; + uint32 _Delay; +}; + +struct GossipTextOption +{ + std::string Text_0; + std::string Text_1; + uint32 Language; + float Probability; + QEmote Emotes[3]; +}; + +struct GossipText +{ + uint32 Text_ID; + GossipTextOption Options[8]; +}; + +struct PageTextLocale +{ + std::vector Text; +}; + +struct NpcTextLocale +{ + NpcTextLocale() { Text_0.resize(8); Text_1.resize(8); } + + std::vector > Text_0; + std::vector > Text_1; +}; +#endif diff --git a/src/game/NullCreatureAI.cpp b/src/game/NullCreatureAI.cpp new file mode 100644 index 00000000000..81f72c17da9 --- /dev/null +++ b/src/game/NullCreatureAI.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "NullCreatureAI.h" + +NullCreatureAI::~NullCreatureAI() +{ +} diff --git a/src/game/NullCreatureAI.h b/src/game/NullCreatureAI.h new file mode 100644 index 00000000000..7404e0a40f8 --- /dev/null +++ b/src/game/NullCreatureAI.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_NULLCREATUREAI_H +#define MANGOS_NULLCREATUREAI_H + +#include "CreatureAI.h" + +class MANGOS_DLL_DECL NullCreatureAI : public CreatureAI +{ + public: + + NullCreatureAI(Creature &) {} + NullCreatureAI() {} + + ~NullCreatureAI(); + + void MoveInLineOfSight(Unit *) {} + void AttackStart(Unit *) {} + void EnterEvadeMode() {} + + bool IsVisible(Unit *) const { return false; } + + void UpdateAI(const uint32) {} + static int Permissible(const Creature *) { return PERMIT_BASE_IDLE; } +}; +#endif diff --git a/src/game/Object.cpp b/src/game/Object.cpp new file mode 100644 index 00000000000..b3e61e102d3 --- /dev/null +++ b/src/game/Object.cpp @@ -0,0 +1,1631 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "SharedDefines.h" +#include "WorldPacket.h" +#include "Opcodes.h" +#include "Log.h" +#include "World.h" +#include "Object.h" +#include "Creature.h" +#include "Player.h" +#include "ObjectMgr.h" +#include "WorldSession.h" +#include "UpdateData.h" +#include "UpdateMask.h" +#include "Util.h" +#include "MapManager.h" +#include "ObjectAccessor.h" +#include "Log.h" +#include "Transports.h" +#include "TargetedMovementGenerator.h" +#include "WaypointMovementGenerator.h" +#include "VMapFactory.h" +#include "CellImpl.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" + +#include "ObjectPosSelector.h" + +#include "TemporarySummon.h" + +uint32 GuidHigh2TypeId(uint32 guid_hi) +{ + switch(guid_hi) + { + case HIGHGUID_ITEM: return TYPEID_ITEM; + //case HIGHGUID_CONTAINER: return TYPEID_CONTAINER; HIGHGUID_CONTAINER==HIGHGUID_ITEM currently + case HIGHGUID_UNIT: return TYPEID_UNIT; + case HIGHGUID_PET: return TYPEID_UNIT; + case HIGHGUID_PLAYER: return TYPEID_PLAYER; + case HIGHGUID_GAMEOBJECT: return TYPEID_GAMEOBJECT; + case HIGHGUID_DYNAMICOBJECT:return TYPEID_DYNAMICOBJECT; + case HIGHGUID_CORPSE: return TYPEID_CORPSE; + case HIGHGUID_MO_TRANSPORT: return TYPEID_GAMEOBJECT; + } + return 10; // unknown +} + +Object::Object( ) +{ + m_objectTypeId = TYPEID_OBJECT; + m_objectType = TYPEMASK_OBJECT; + + m_uint32Values = 0; + m_uint32Values_mirror = 0; + m_valuesCount = 0; + + m_inWorld = false; + m_objectUpdated = false; + + m_PackGUID.clear(); + m_PackGUID.appendPackGUID(0); +} + +Object::~Object( ) +{ + if(m_objectUpdated) + ObjectAccessor::Instance().RemoveUpdateObject(this); + + if(m_uint32Values) + { + if(IsInWorld()) + { + ///- Do NOT call RemoveFromWorld here, if the object is a player it will crash + sLog.outError("Object::~Object - guid="I64FMTD", typeid=%d deleted but still in world!!", GetGUID(), GetTypeId()); + //assert(0); + } + + //DEBUG_LOG("Object desctr 1 check (%p)",(void*)this); + delete [] m_uint32Values; + delete [] m_uint32Values_mirror; + //DEBUG_LOG("Object desctr 2 check (%p)",(void*)this); + } +} + +void Object::_InitValues() +{ + m_uint32Values = new uint32[ m_valuesCount ]; + memset(m_uint32Values, 0, m_valuesCount*sizeof(uint32)); + + m_uint32Values_mirror = new uint32[ m_valuesCount ]; + memset(m_uint32Values_mirror, 0, m_valuesCount*sizeof(uint32)); + + m_objectUpdated = false; +} + +void Object::_Create( uint32 guidlow, uint32 entry, HighGuid guidhigh ) +{ + if(!m_uint32Values) _InitValues(); + + uint64 guid = MAKE_NEW_GUID(guidlow, entry, guidhigh); // required more changes to make it working + SetUInt64Value( OBJECT_FIELD_GUID, guid ); + SetUInt32Value( OBJECT_FIELD_TYPE, m_objectType ); + m_PackGUID.clear(); + m_PackGUID.appendPackGUID(GetGUID()); +} + +void Object::BuildMovementUpdateBlock(UpdateData * data, uint32 flags ) const +{ + ByteBuffer buf(500); + + buf << uint8( UPDATETYPE_MOVEMENT ); + buf << GetGUID(); + + _BuildMovementUpdate(&buf, flags, 0x00000000); + + data->AddUpdateBlock(buf); +} + +void Object::BuildCreateUpdateBlockForPlayer(UpdateData *data, Player *target) const +{ + if(!target) + { + return; + } + + uint8 updatetype = UPDATETYPE_CREATE_OBJECT; + uint8 flags = m_updateFlag; + uint32 flags2 = 0; + + /** lower flag1 **/ + if(target == this) // building packet for oneself + { + flags |= UPDATEFLAG_SELF; + + /*** temporary reverted - until real source of stack corruption will not found + updatetype = UPDATETYPE_CREATE_OBJECT2; + ****/ + } + + if(flags & UPDATEFLAG_HASPOSITION) + { + // UPDATETYPE_CREATE_OBJECT2 dynamic objects, corpses... + if(isType(TYPEMASK_DYNAMICOBJECT) || isType(TYPEMASK_CORPSE) || isType(TYPEMASK_PLAYER)) + updatetype = UPDATETYPE_CREATE_OBJECT2; + + // UPDATETYPE_CREATE_OBJECT2 for pets... + if(target->GetPetGUID() == GetGUID()) + updatetype = UPDATETYPE_CREATE_OBJECT2; + + // UPDATETYPE_CREATE_OBJECT2 for some gameobject types... + if(isType(TYPEMASK_GAMEOBJECT)) + { + switch(((GameObject*)this)->GetGoType()) + { + case GAMEOBJECT_TYPE_TRAP: + case GAMEOBJECT_TYPE_DUEL_ARBITER: + case GAMEOBJECT_TYPE_FLAGSTAND: + case GAMEOBJECT_TYPE_FLAGDROP: + updatetype = UPDATETYPE_CREATE_OBJECT2; + break; + case GAMEOBJECT_TYPE_TRANSPORT: + flags |= UPDATEFLAG_TRANSPORT; + break; + } + } + } + + //sLog.outDebug("BuildCreateUpdate: update-type: %u, object-type: %u got flags: %X, flags2: %X", updatetype, m_objectTypeId, flags, flags2); + + ByteBuffer buf(500); + buf << (uint8)updatetype; + //buf.append(GetPackGUID()); //client crashes when using this + buf << (uint8)0xFF << GetGUID(); + buf << (uint8)m_objectTypeId; + + _BuildMovementUpdate(&buf, flags, flags2); + + UpdateMask updateMask; + updateMask.SetCount( m_valuesCount ); + _SetCreateBits( &updateMask, target ); + _BuildValuesUpdate(updatetype, &buf, &updateMask, target ); + data->AddUpdateBlock(buf); +} + +void Object::BuildUpdate(UpdateDataMapType &update_players) +{ + ObjectAccessor::_buildUpdateObject(this,update_players); + ClearUpdateMask(true); +} + +void Object::SendUpdateToPlayer(Player* player) +{ + // send update to another players + SendUpdateObjectToAllExcept(player); + + // send create update to player + UpdateData upd; + WorldPacket packet; + + upd.Clear(); + BuildCreateUpdateBlockForPlayer(&upd, player); + upd.BuildPacket(&packet); + player->GetSession()->SendPacket(&packet); + + // now object updated/(create updated) +} + +void Object::BuildValuesUpdateBlockForPlayer(UpdateData *data, Player *target) const +{ + ByteBuffer buf(500); + + buf << (uint8) UPDATETYPE_VALUES; + //buf.append(GetPackGUID()); //client crashes when using this. but not have crash in debug mode + buf << (uint8)0xFF; + buf << GetGUID(); + + UpdateMask updateMask; + updateMask.SetCount( m_valuesCount ); + + _SetUpdateBits( &updateMask, target ); + _BuildValuesUpdate(UPDATETYPE_VALUES, &buf, &updateMask, target ); + + data->AddUpdateBlock(buf); +} + +void Object::BuildOutOfRangeUpdateBlock(UpdateData * data) const +{ + data->AddOutOfRangeGUID(GetGUID()); +} + +void Object::DestroyForPlayer(Player *target) const +{ + ASSERT(target); + + WorldPacket data(SMSG_DESTROY_OBJECT, 8); + data << GetGUID(); + target->GetSession()->SendPacket( &data ); +} + +void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2 ) const +{ + *data << (uint8)flags; // update flags + + // 0x20 + if (flags & UPDATEFLAG_LIVING) + { + switch(GetTypeId()) + { + case TYPEID_UNIT: + { + flags2 = ((Unit*)this)->GetUnitMovementFlags(); + } + break; + case TYPEID_PLAYER: + { + flags2 = ((Player*)this)->GetUnitMovementFlags(); + + if(((Player*)this)->GetTransport()) + flags2 |= MOVEMENTFLAG_ONTRANSPORT; + else + flags2 &= ~MOVEMENTFLAG_ONTRANSPORT; + + // remove unknown, unused etc flags for now + flags2 &= ~MOVEMENTFLAG_SPLINE2; // will be set manually + + if(((Player*)this)->isInFlight()) + { + WPAssert(((Player*)this)->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE); + flags2 = (MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_SPLINE2); + } + } + break; + } + + *data << uint32(flags2); // movement flags + *data << uint8(0); // unk 2.3.0 + *data << uint32(getMSTime()); // time (in milliseconds) + } + + // 0x40 + if (flags & UPDATEFLAG_HASPOSITION) + { + // 0x02 + if(flags & UPDATEFLAG_TRANSPORT && ((GameObject*)this)->GetGoType() == GAMEOBJECT_TYPE_MO_TRANSPORT) + { + *data << (float)0; + *data << (float)0; + *data << (float)0; + *data << ((WorldObject *)this)->GetOrientation(); + } + else + { + *data << ((WorldObject *)this)->GetPositionX(); + *data << ((WorldObject *)this)->GetPositionY(); + *data << ((WorldObject *)this)->GetPositionZ(); + *data << ((WorldObject *)this)->GetOrientation(); + } + } + + // 0x20 + if(flags & UPDATEFLAG_LIVING) + { + // 0x00000200 + if(flags2 & MOVEMENTFLAG_ONTRANSPORT) + { + if(GetTypeId() == TYPEID_PLAYER) + { + *data << (uint64)((Player*)this)->GetTransport()->GetGUID(); + *data << (float)((Player*)this)->GetTransOffsetX(); + *data << (float)((Player*)this)->GetTransOffsetY(); + *data << (float)((Player*)this)->GetTransOffsetZ(); + *data << (float)((Player*)this)->GetTransOffsetO(); + *data << (uint32)((Player*)this)->GetTransTime(); + } + //MaNGOS currently not have support for other than player on transport + } + + // 0x02200000 + if(flags2 & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2)) + { + if(GetTypeId() == TYPEID_PLAYER) + *data << (float)((Player*)this)->m_movementInfo.s_pitch; + else + *data << (float)0; // is't part of movement packet, we must store and send it... + } + + if(GetTypeId() == TYPEID_PLAYER) + *data << (uint32)((Player*)this)->m_movementInfo.fallTime; + else + *data << (uint32)0; // last fall time + + // 0x00001000 + if(flags2 & MOVEMENTFLAG_JUMPING) + { + if(GetTypeId() == TYPEID_PLAYER) + { + *data << (float)((Player*)this)->m_movementInfo.j_unk; + *data << (float)((Player*)this)->m_movementInfo.j_sinAngle; + *data << (float)((Player*)this)->m_movementInfo.j_cosAngle; + *data << (float)((Player*)this)->m_movementInfo.j_xyspeed; + } + else + { + *data << (float)0; + *data << (float)0; + *data << (float)0; + *data << (float)0; + } + } + + // 0x04000000 + if(flags2 & MOVEMENTFLAG_SPLINE) + { + if(GetTypeId() == TYPEID_PLAYER) + *data << (float)((Player*)this)->m_movementInfo.u_unk1; + else + *data << (float)0; + } + + *data << ((Unit*)this)->GetSpeed( MOVE_WALK ); + *data << ((Unit*)this)->GetSpeed( MOVE_RUN ); + *data << ((Unit*)this)->GetSpeed( MOVE_SWIMBACK ); + *data << ((Unit*)this)->GetSpeed( MOVE_SWIM ); + *data << ((Unit*)this)->GetSpeed( MOVE_WALKBACK ); + *data << ((Unit*)this)->GetSpeed( MOVE_FLY ); + *data << ((Unit*)this)->GetSpeed( MOVE_FLYBACK ); + *data << ((Unit*)this)->GetSpeed( MOVE_TURN ); + + // 0x08000000 + if(flags2 & MOVEMENTFLAG_SPLINE2) + { + if(GetTypeId() != TYPEID_PLAYER) + { + sLog.outDebug("_BuildMovementUpdate: MOVEMENTFLAG_SPLINE2 for non-player"); + return; + } + + if(!((Player*)this)->isInFlight()) + { + sLog.outDebug("_BuildMovementUpdate: MOVEMENTFLAG_SPLINE2 but not in flight"); + return; + } + + WPAssert(((Player*)this)->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE); + + FlightPathMovementGenerator *fmg = (FlightPathMovementGenerator*)(((Player*)this)->GetMotionMaster()->top()); + + uint32 flags3 = 0x00000300; + + *data << uint32(flags3); // splines flag? + + if(flags3 & 0x10000) // probably x,y,z coords there + { + *data << (float)0; + *data << (float)0; + *data << (float)0; + } + + if(flags3 & 0x20000) // probably guid there + { + *data << uint64(0); + } + + if(flags3 & 0x40000) // may be orientation + { + *data << (float)0; + } + + Path &path = fmg->GetPath(); + + float x, y, z; + ((Player*)this)->GetPosition(x, y, z); + + uint32 inflighttime = uint32(path.GetPassedLength(fmg->GetCurrentNode(), x, y, z) * 32); + uint32 traveltime = uint32(path.GetTotalLength() * 32); + + *data << uint32(inflighttime); // passed move time? + *data << uint32(traveltime); // full move time? + *data << uint32(0); // ticks count? + + uint32 poscount = uint32(path.Size()); + + *data << uint32(poscount); // points count + + for(uint32 i = 0; i < poscount; ++i) + { + *data << path.GetNodes()[i].x; + *data << path.GetNodes()[i].y; + *data << path.GetNodes()[i].z; + } + + /*for(uint32 i = 0; i < poscount; i++) + { + // path points + *data << (float)0; + *data << (float)0; + *data << (float)0; + }*/ + + *data << path.GetNodes()[poscount-1].x; + *data << path.GetNodes()[poscount-1].y; + *data << path.GetNodes()[poscount-1].z; + + // target position (path end) + /**data << ((Unit*)this)->GetPositionX(); + *data << ((Unit*)this)->GetPositionY(); + *data << ((Unit*)this)->GetPositionZ();*/ + } + } + + // 0x8 + if(flags & UPDATEFLAG_LOWGUID) + { + switch(GetTypeId()) + { + case TYPEID_OBJECT: + case TYPEID_ITEM: + case TYPEID_CONTAINER: + case TYPEID_GAMEOBJECT: + case TYPEID_DYNAMICOBJECT: + case TYPEID_CORPSE: + *data << uint32(GetGUIDLow()); // GetGUIDLow() + break; + case TYPEID_UNIT: + *data << uint32(0x0000000B); // unk, can be 0xB or 0xC + break; + case TYPEID_PLAYER: + if(flags & UPDATEFLAG_SELF) + *data << uint32(0x00000015); // unk, can be 0x15 or 0x22 + else + *data << uint32(0x00000008); // unk, can be 0x7 or 0x8 + break; + default: + *data << uint32(0x00000000); // unk + break; + } + } + + // 0x10 + if(flags & UPDATEFLAG_HIGHGUID) + { + switch(GetTypeId()) + { + case TYPEID_OBJECT: + case TYPEID_ITEM: + case TYPEID_CONTAINER: + case TYPEID_GAMEOBJECT: + case TYPEID_DYNAMICOBJECT: + case TYPEID_CORPSE: + *data << uint32(GetGUIDHigh()); // GetGUIDHigh() + break; + default: + *data << uint32(0x00000000); // unk + break; + } + } + + // 0x4 + if(flags & UPDATEFLAG_FULLGUID) + { + *data << uint8(0); // packed guid (probably target guid) + } + + // 0x2 + if(flags & UPDATEFLAG_TRANSPORT) + { + *data << uint32(getMSTime()); // ms time + } +} + +void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask *updateMask, Player *target) const +{ + if(!target) + return; + + bool IsActivateToQuest = false; + if (updatetype == UPDATETYPE_CREATE_OBJECT || updatetype == UPDATETYPE_CREATE_OBJECT2) + { + if (isType(TYPEMASK_GAMEOBJECT) && !((GameObject*)this)->IsTransport()) + { + if ( ((GameObject*)this)->ActivateToQuest(target) || target->isGameMaster()) + { + IsActivateToQuest = true; + updateMask->SetBit(GAMEOBJECT_DYN_FLAGS); + } + } + } + else //case UPDATETYPE_VALUES + { + if (isType(TYPEMASK_GAMEOBJECT) && !((GameObject*)this)->IsTransport()) + { + if ( ((GameObject*)this)->ActivateToQuest(target) || target->isGameMaster()) + { + IsActivateToQuest = true; + } + updateMask->SetBit(GAMEOBJECT_DYN_FLAGS); + updateMask->SetBit(GAMEOBJECT_ANIMPROGRESS); + } + } + + WPAssert(updateMask && updateMask->GetCount() == m_valuesCount); + + *data << (uint8)updateMask->GetBlockCount(); + data->append( updateMask->GetMask(), updateMask->GetLength() ); + + // 2 specialized loops for speed optimization in non-unit case + if(isType(TYPEMASK_UNIT)) // unit (creature/player) case + { + for( uint16 index = 0; index < m_valuesCount; index ++ ) + { + if( updateMask->GetBit( index ) ) + { + // remove custom flag before send + if( index == UNIT_NPC_FLAGS ) + *data << uint32(m_uint32Values[ index ] & ~UNIT_NPC_FLAG_GUARD); + // FIXME: Some values at server stored in float format but must be sent to client in uint32 format + else if(index >= UNIT_FIELD_BASEATTACKTIME && index <= UNIT_FIELD_RANGEDATTACKTIME) + { + // convert from float to uint32 and send + *data << uint32(m_floatValues[ index ] < 0 ? 0 : m_floatValues[ index ]); + } + // there are some float values which may be negative or can't get negative due to other checks + else if(index >= UNIT_FIELD_NEGSTAT0 && index <= UNIT_FIELD_NEGSTAT4 || + index >= UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE && index <= (UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE + 6) || + index >= UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE && index <= (UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE + 6) || + index >= UNIT_FIELD_POSSTAT0 && index <= UNIT_FIELD_POSSTAT4) + { + *data << uint32(m_floatValues[ index ]); + } + // Gamemasters should be always able to select units - remove not selectable flag + else if(index == UNIT_FIELD_FLAGS && target->isGameMaster()) + { + *data << (m_uint32Values[ index ] & ~UNIT_FLAG_NOT_SELECTABLE); + } + // hide lootable animation for unallowed players + else if(index == UNIT_DYNAMIC_FLAGS && GetTypeId() == TYPEID_UNIT) + { + if(!target->isAllowedToLoot((Creature*)this)) + *data << (m_uint32Values[ index ] & ~UNIT_DYNFLAG_LOOTABLE); + else + *data << (m_uint32Values[ index ] & ~UNIT_DYNFLAG_OTHER_TAGGER); + } + else + { + // send in current format (float as float, uint32 as uint32) + *data << m_uint32Values[ index ]; + } + } + } + } + else if(isType(TYPEMASK_GAMEOBJECT)) // gameobject case + { + for( uint16 index = 0; index < m_valuesCount; index ++ ) + { + if( updateMask->GetBit( index ) ) + { + // send in current format (float as float, uint32 as uint32) + if ( index == GAMEOBJECT_DYN_FLAGS ) + { + if(IsActivateToQuest ) + { + switch(((GameObject*)this)->GetGoType()) + { + case GAMEOBJECT_TYPE_CHEST: + *data << uint32(9); // enable quest object. Represent 9, but 1 for client before 2.3.0 + break; + case GAMEOBJECT_TYPE_GOOBER: + *data << uint32(1); + break; + default: + *data << uint32(0); //unknown. not happen. + break; + } + } + else + *data << uint32(0); // disable quest object + } + else + *data << m_uint32Values[ index ]; // other cases + } + } + } + else // other objects case (no special index checks) + { + for( uint16 index = 0; index < m_valuesCount; index ++ ) + { + if( updateMask->GetBit( index ) ) + { + // send in current format (float as float, uint32 as uint32) + *data << m_uint32Values[ index ]; + } + } + } +} + +void Object::ClearUpdateMask(bool remove) +{ + for( uint16 index = 0; index < m_valuesCount; index ++ ) + { + if(m_uint32Values_mirror[index]!= m_uint32Values[index]) + m_uint32Values_mirror[index] = m_uint32Values[index]; + } + if(m_objectUpdated) + { + if(remove) + ObjectAccessor::Instance().RemoveUpdateObject(this); + m_objectUpdated = false; + } +} + +// Send current value fields changes to all viewers +void Object::SendUpdateObjectToAllExcept(Player* exceptPlayer) +{ + // changes will be send in create packet + if(!IsInWorld()) + return; + + // nothing do + if(!m_objectUpdated) + return; + + ObjectAccessor::UpdateObject(this,exceptPlayer); +} + +bool Object::LoadValues(const char* data) +{ + if(!m_uint32Values) _InitValues(); + + Tokens tokens = StrSplit(data, " "); + + if(tokens.size() != m_valuesCount) + return false; + + Tokens::iterator iter; + int index; + for (iter = tokens.begin(), index = 0; index < m_valuesCount; ++iter, ++index) + { + m_uint32Values[index] = atol((*iter).c_str()); + } + + return true; +} + +void Object::_SetUpdateBits(UpdateMask *updateMask, Player* /*target*/) const +{ + for( uint16 index = 0; index < m_valuesCount; index ++ ) + { + if(m_uint32Values_mirror[index]!= m_uint32Values[index]) + updateMask->SetBit(index); + } +} + +void Object::_SetCreateBits(UpdateMask *updateMask, Player* /*target*/) const +{ + for( uint16 index = 0; index < m_valuesCount; index++ ) + { + if(GetUInt32Value(index) != 0) + updateMask->SetBit(index); + } +} + +void Object::SetInt32Value( uint16 index, int32 value ) +{ + ASSERT( index < m_valuesCount || PrintIndexError( index , true ) ); + + if(m_int32Values[ index ] != value) + { + m_int32Values[ index ] = value; + + if(m_inWorld) + { + if(!m_objectUpdated) + { + ObjectAccessor::Instance().AddUpdateObject(this); + m_objectUpdated = true; + } + } + } +} + +void Object::SetUInt32Value( uint16 index, uint32 value ) +{ + ASSERT( index < m_valuesCount || PrintIndexError( index , true ) ); + + if(m_uint32Values[ index ] != value) + { + m_uint32Values[ index ] = value; + + if(m_inWorld) + { + if(!m_objectUpdated) + { + ObjectAccessor::Instance().AddUpdateObject(this); + m_objectUpdated = true; + } + } + } +} + +void Object::SetUInt64Value( uint16 index, const uint64 &value ) +{ + ASSERT( index + 1 < m_valuesCount || PrintIndexError( index , true ) ); + if(*((uint64*)&(m_uint32Values[ index ])) != value) + { + m_uint32Values[ index ] = *((uint32*)&value); + m_uint32Values[ index + 1 ] = *(((uint32*)&value) + 1); + + if(m_inWorld) + { + if(!m_objectUpdated) + { + ObjectAccessor::Instance().AddUpdateObject(this); + m_objectUpdated = true; + } + } + } +} + +void Object::SetFloatValue( uint16 index, float value ) +{ + ASSERT( index < m_valuesCount || PrintIndexError( index , true ) ); + + if(m_floatValues[ index ] != value) + { + m_floatValues[ index ] = value; + + if(m_inWorld) + { + if(!m_objectUpdated) + { + ObjectAccessor::Instance().AddUpdateObject(this); + m_objectUpdated = true; + } + } + } +} + +void Object::SetByteValue( uint16 index, uint8 offset, uint8 value ) +{ + ASSERT( index < m_valuesCount || PrintIndexError( index , true ) ); + + if(offset > 4) + { + sLog.outError("Object::SetByteValue: wrong offset %u", offset); + return; + } + + if(uint8(m_uint32Values[ index ] >> (offset * 8)) != value) + { + m_uint32Values[ index ] &= ~uint32(uint32(0xFF) << (offset * 8)); + m_uint32Values[ index ] |= uint32(uint32(value) << (offset * 8)); + + if(m_inWorld) + { + if(!m_objectUpdated) + { + ObjectAccessor::Instance().AddUpdateObject(this); + m_objectUpdated = true; + } + } + } +} + +void Object::SetUInt16Value( uint16 index, uint8 offset, uint16 value ) +{ + ASSERT( index < m_valuesCount || PrintIndexError( index , true ) ); + + if(offset > 2) + { + sLog.outError("Object::SetUInt16Value: wrong offset %u", offset); + return; + } + + if(uint8(m_uint32Values[ index ] >> (offset * 16)) != value) + { + m_uint32Values[ index ] &= ~uint32(uint32(0xFFFF) << (offset * 16)); + m_uint32Values[ index ] |= uint32(uint32(value) << (offset * 16)); + + if(m_inWorld) + { + if(!m_objectUpdated) + { + ObjectAccessor::Instance().AddUpdateObject(this); + m_objectUpdated = true; + } + } + } +} + +void Object::SetStatFloatValue( uint16 index, float value) +{ + if(value < 0) + value = 0.0f; + + SetFloatValue(index, value); +} + +void Object::SetStatInt32Value( uint16 index, int32 value) +{ + if(value < 0) + value = 0; + + SetUInt32Value(index, uint32(value)); +} + +void Object::ApplyModUInt32Value(uint16 index, int32 val, bool apply) +{ + int32 cur = GetUInt32Value(index); + cur += (apply ? val : -val); + if(cur < 0) + cur = 0; + SetUInt32Value(index,cur); +} + +void Object::ApplyModInt32Value(uint16 index, int32 val, bool apply) +{ + int32 cur = GetInt32Value(index); + cur += (apply ? val : -val); + SetInt32Value(index,cur); +} + +void Object::ApplyModSignedFloatValue(uint16 index, float val, bool apply) +{ + float cur = GetFloatValue(index); + cur += (apply ? val : -val); + SetFloatValue(index,cur); +} + +void Object::ApplyModPositiveFloatValue(uint16 index, float val, bool apply) +{ + float cur = GetFloatValue(index); + cur += (apply ? val : -val); + if(cur < 0) + cur = 0; + SetFloatValue(index,cur); +} + +void Object::SetFlag( uint16 index, uint32 newFlag ) +{ + ASSERT( index < m_valuesCount || PrintIndexError( index , true ) ); + uint32 oldval = m_uint32Values[ index ]; + uint32 newval = oldval | newFlag; + + if(oldval != newval) + { + m_uint32Values[ index ] = newval; + + if(m_inWorld) + { + if(!m_objectUpdated) + { + ObjectAccessor::Instance().AddUpdateObject(this); + m_objectUpdated = true; + } + } + } +} + +void Object::RemoveFlag( uint16 index, uint32 oldFlag ) +{ + ASSERT( index < m_valuesCount || PrintIndexError( index , true ) ); + uint32 oldval = m_uint32Values[ index ]; + uint32 newval = oldval & ~oldFlag; + + if(oldval != newval) + { + m_uint32Values[ index ] = newval; + + if(m_inWorld) + { + if(!m_objectUpdated) + { + ObjectAccessor::Instance().AddUpdateObject(this); + m_objectUpdated = true; + } + } + } +} + +bool Object::PrintIndexError(uint32 index, bool set) const +{ + sLog.outError("ERROR: Attempt %s non-existed value field: %u (count: %u) for object typeid: %u type mask: %u",(set ? "set value to" : "get value from"),index,m_valuesCount,GetTypeId(),m_objectType); + + // assert must fail after function call + return false; +} + +WorldObject::WorldObject() +{ + m_positionX = 0.0f; + m_positionY = 0.0f; + m_positionZ = 0.0f; + m_orientation = 0.0f; + + m_mapId = 0; + m_InstanceId = 0; + + m_name = ""; + + mSemaphoreTeleport = false; +} + +void WorldObject::_Create( uint32 guidlow, HighGuid guidhigh, uint32 mapid ) +{ + Object::_Create(guidlow, 0, guidhigh); + + m_mapId = mapid; +} + +uint32 WorldObject::GetZoneId() const +{ + return MapManager::Instance().GetBaseMap(m_mapId)->GetZoneId(m_positionX,m_positionY); +} + +uint32 WorldObject::GetAreaId() const +{ + return MapManager::Instance().GetBaseMap(m_mapId)->GetAreaId(m_positionX,m_positionY); +} + +InstanceData* WorldObject::GetInstanceData() +{ + Map *map = MapManager::Instance().GetMap(m_mapId, this); + return map->IsDungeon() ? ((InstanceMap*)map)->GetInstanceData() : NULL; +} + + //slow +float WorldObject::GetDistance(const WorldObject* obj) const +{ + float dx = GetPositionX() - obj->GetPositionX(); + float dy = GetPositionY() - obj->GetPositionY(); + float dz = GetPositionZ() - obj->GetPositionZ(); + float sizefactor = GetObjectSize() + obj->GetObjectSize(); + float dist = sqrt((dx*dx) + (dy*dy) + (dz*dz)) - sizefactor; + return ( dist > 0 ? dist : 0); +} + +float WorldObject::GetDistance2d(float x, float y) const +{ + float dx = GetPositionX() - x; + float dy = GetPositionY() - y; + float sizefactor = GetObjectSize(); + float dist = sqrt((dx*dx) + (dy*dy)) - sizefactor; + return ( dist > 0 ? dist : 0); +} + +float WorldObject::GetDistance(const float x, const float y, const float z) const +{ + float dx = GetPositionX() - x; + float dy = GetPositionY() - y; + float dz = GetPositionZ() - z; + float sizefactor = GetObjectSize(); + float dist = sqrt((dx*dx) + (dy*dy) + (dz*dz)) - sizefactor; + return ( dist > 0 ? dist : 0); +} + +float WorldObject::GetDistance2d(const WorldObject* obj) const +{ + float dx = GetPositionX() - obj->GetPositionX(); + float dy = GetPositionY() - obj->GetPositionY(); + float sizefactor = GetObjectSize() + obj->GetObjectSize(); + float dist = sqrt((dx*dx) + (dy*dy)) - sizefactor; + return ( dist > 0 ? dist : 0); +} + +float WorldObject::GetDistanceZ(const WorldObject* obj) const +{ + float dz = fabs(GetPositionZ() - obj->GetPositionZ()); + float sizefactor = GetObjectSize() + obj->GetObjectSize(); + float dist = dz - sizefactor; + return ( dist > 0 ? dist : 0); +} + +bool WorldObject::IsWithinDistInMap(const WorldObject* obj, const float dist2compare) const +{ + if (!obj || !IsInMap(obj)) return false; + + float dx = GetPositionX() - obj->GetPositionX(); + float dy = GetPositionY() - obj->GetPositionY(); + float dz = GetPositionZ() - obj->GetPositionZ(); + float distsq = dx*dx + dy*dy + dz*dz; + float sizefactor = GetObjectSize() + obj->GetObjectSize(); + float maxdist = dist2compare + sizefactor; + + return distsq < maxdist * maxdist; +} + +bool WorldObject::IsWithinLOSInMap(const WorldObject* obj) const +{ + if (!IsInMap(obj)) return false; + float ox,oy,oz; + obj->GetPosition(ox,oy,oz); + return(IsWithinLOS(ox, oy, oz )); +} + +bool WorldObject::IsWithinLOS(const float ox, const float oy, const float oz ) const +{ + float x,y,z; + GetPosition(x,y,z); + VMAP::IVMapManager *vMapManager = VMAP::VMapFactory::createOrGetVMapManager(); + return vMapManager->isInLineOfSight(GetMapId(), x, y, z+2.0f, ox, oy, oz+2.0f); +} + +float WorldObject::GetAngle(const WorldObject* obj) const +{ + if(!obj) return 0; + return GetAngle( obj->GetPositionX(), obj->GetPositionY() ); +} + +// Return angle in range 0..2*pi +float WorldObject::GetAngle( const float x, const float y ) const +{ + float dx = x - GetPositionX(); + float dy = y - GetPositionY(); + + float ang = atan2(dy, dx); + ang = (ang >= 0) ? ang : 2 * M_PI + ang; + return ang; +} + +bool WorldObject::HasInArc(const float arcangle, const WorldObject* obj) const +{ + float arc = arcangle; + + // move arc to range 0.. 2*pi + while( arc >= 2.0f * M_PI ) + arc -= 2.0f * M_PI; + while( arc < 0 ) + arc += 2.0f * M_PI; + + float angle = GetAngle( obj ); + angle -= m_orientation; + + // move angle to range -pi ... +pi + while( angle > M_PI) + angle -= 2.0f * M_PI; + while(angle < -M_PI) + angle += 2.0f * M_PI; + + float lborder = -1 * (arc/2.0f); // in range -pi..0 + float rborder = (arc/2.0f); // in range 0..pi + return (( angle >= lborder ) && ( angle <= rborder )); +} + +void WorldObject::GetRandomPoint( float x, float y, float z, float distance, float &rand_x, float &rand_y, float &rand_z) const +{ + if(distance==0) + { + rand_x = x; + rand_y = y; + rand_z = z; + return; + } + + // angle to face `obj` to `this` + float angle = rand_norm()*2*M_PI; + float new_dist = rand_norm()*distance; + + rand_x = x + new_dist * cos(angle); + rand_y = y + new_dist * sin(angle); + rand_z = z; + + MaNGOS::NormalizeMapCoord(rand_x); + MaNGOS::NormalizeMapCoord(rand_y); + UpdateGroundPositionZ(rand_x,rand_y,rand_z); // update to LOS height if available +} + +void WorldObject::UpdateGroundPositionZ(float x, float y, float &z) const +{ + float new_z = MapManager::Instance().GetBaseMap(GetMapId())->GetHeight(x,y,z,true); + if(new_z > INVALID_HEIGHT) + z = new_z+ 0.05f; // just to be sure that we are not a few pixel under the surface +} + +bool WorldObject::IsPositionValid() const +{ + return MaNGOS::IsValidMapCoord(m_positionX,m_positionY,m_positionZ,m_orientation); +} + +void WorldObject::MonsterSay(const char* text, uint32 language, uint64 TargetGuid) +{ + WorldPacket data(SMSG_MESSAGECHAT, 200); + BuildMonsterChat(&data,CHAT_MSG_MONSTER_SAY,text,language,GetName(),TargetGuid); + SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_SAY),true); +} + +void WorldObject::MonsterYell(const char* text, uint32 language, uint64 TargetGuid) +{ + WorldPacket data(SMSG_MESSAGECHAT, 200); + BuildMonsterChat(&data,CHAT_MSG_MONSTER_YELL,text,language,GetName(),TargetGuid); + SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_YELL),true); +} + +void WorldObject::MonsterTextEmote(const char* text, uint64 TargetGuid, bool IsBossEmote) +{ + WorldPacket data(SMSG_MESSAGECHAT, 200); + BuildMonsterChat(&data,IsBossEmote ? CHAT_MSG_RAID_BOSS_EMOTE : CHAT_MSG_MONSTER_EMOTE,text,LANG_UNIVERSAL,GetName(),TargetGuid); + SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),true); +} + +void WorldObject::MonsterWhisper(const char* text, uint64 receiver, bool IsBossWhisper) +{ + Player *player = objmgr.GetPlayer(receiver); + if(!player || !player->GetSession()) + return; + + WorldPacket data(SMSG_MESSAGECHAT, 200); + BuildMonsterChat(&data,IsBossWhisper ? CHAT_MSG_RAID_BOSS_WHISPER : CHAT_MSG_MONSTER_WHISPER,text,LANG_UNIVERSAL,GetName(),receiver); + + player->GetSession()->SendPacket(&data); +} + +namespace MaNGOS +{ + class MessageChatLocaleCacheDo + { + public: + MessageChatLocaleCacheDo(WorldObject const& obj, ChatMsg msgtype, int32 textId, uint32 language, uint64 targetGUID, float dist) + : i_object(obj), i_msgtype(msgtype), i_textId(textId), i_language(language), + i_targetGUID(targetGUID), i_dist(dist) + { + } + + ~MessageChatLocaleCacheDo() + { + for(int i = 0; i < i_data_cache.size(); ++i) + delete i_data_cache[i]; + } + + void operator()(Player* p) + { + // skip far away players + if(p->GetDistance(&i_object) > i_dist) + return; + + uint32 loc_idx = p->GetSession()->GetSessionDbLocaleIndex(); + uint32 cache_idx = loc_idx+1; + WorldPacket* data; + + // create if not cached yet + if(i_data_cache.size() < cache_idx+1 || !i_data_cache[cache_idx]) + { + if(i_data_cache.size() < cache_idx+1) + i_data_cache.resize(cache_idx+1); + + char const* text = objmgr.GetMangosString(i_textId,loc_idx); + + data = new WorldPacket(SMSG_MESSAGECHAT, 200); + + // TODO: i_object.GetName() also must be localized? + i_object.BuildMonsterChat(data,i_msgtype,text,i_language,i_object.GetName(),i_targetGUID); + + i_data_cache[cache_idx] = data; + } + else + data = i_data_cache[cache_idx]; + + p->SendDirectMessage(data); + } + + private: + WorldObject const& i_object; + ChatMsg i_msgtype; + int32 i_textId; + uint32 i_language; + uint64 i_targetGUID; + float i_dist; + std::vector i_data_cache; // 0 = default, i => i-1 locale index + }; +} // namespace MaNGOS + +void WorldObject::MonsterSay(int32 textId, uint32 language, uint64 TargetGuid) +{ + CellPair p = MaNGOS::ComputeCellPair(GetPositionX(), GetPositionY()); + + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + MaNGOS::MessageChatLocaleCacheDo say_do(*this, CHAT_MSG_MONSTER_SAY, textId,language,TargetGuid,sWorld.getConfig(CONFIG_LISTEN_RANGE_SAY)); + MaNGOS::PlayerWorker say_worker(say_do); + TypeContainerVisitor, WorldTypeMapContainer > message(say_worker); + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, message, *GetMap()); +} + +void WorldObject::MonsterYell(int32 textId, uint32 language, uint64 TargetGuid) +{ + CellPair p = MaNGOS::ComputeCellPair(GetPositionX(), GetPositionY()); + + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + MaNGOS::MessageChatLocaleCacheDo say_do(*this, CHAT_MSG_MONSTER_YELL, textId,language,TargetGuid,sWorld.getConfig(CONFIG_LISTEN_RANGE_YELL)); + MaNGOS::PlayerWorker say_worker(say_do); + TypeContainerVisitor, WorldTypeMapContainer > message(say_worker); + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, message, *GetMap()); +} + +void WorldObject::MonsterTextEmote(int32 textId, uint64 TargetGuid, bool IsBossEmote) +{ + CellPair p = MaNGOS::ComputeCellPair(GetPositionX(), GetPositionY()); + + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + MaNGOS::MessageChatLocaleCacheDo say_do(*this, IsBossEmote ? CHAT_MSG_RAID_BOSS_EMOTE : CHAT_MSG_MONSTER_EMOTE, textId,LANG_UNIVERSAL,TargetGuid,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE)); + MaNGOS::PlayerWorker say_worker(say_do); + TypeContainerVisitor, WorldTypeMapContainer > message(say_worker); + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, message, *GetMap()); +} + +void WorldObject::MonsterWhisper(int32 textId, uint64 receiver, bool IsBossWhisper) +{ + Player *player = objmgr.GetPlayer(receiver); + if(!player || !player->GetSession()) + return; + + uint32 loc_idx = player->GetSession()->GetSessionDbLocaleIndex(); + char const* text = objmgr.GetMangosString(textId,loc_idx); + + WorldPacket data(SMSG_MESSAGECHAT, 200); + BuildMonsterChat(&data,IsBossWhisper ? CHAT_MSG_RAID_BOSS_WHISPER : CHAT_MSG_MONSTER_WHISPER,text,LANG_UNIVERSAL,GetName(),receiver); + + player->GetSession()->SendPacket(&data); +} + +void WorldObject::BuildMonsterChat(WorldPacket *data, uint8 msgtype, char const* text, uint32 language, char const* name, uint64 targetGuid) const +{ + bool pre = (msgtype==CHAT_MSG_MONSTER_EMOTE || msgtype==CHAT_MSG_RAID_BOSS_EMOTE); + + *data << (uint8)msgtype; + *data << (uint32)language; + *data << (uint64)GetGUID(); + *data << (uint32)0; //2.1.0 + *data << (uint32)(strlen(name)+1); + *data << name; + *data << (uint64)targetGuid; //Unit Target + if( targetGuid && !IS_PLAYER_GUID(targetGuid) ) + { + *data << (uint32)1; // target name length + *data << (uint8)0; // target name + } + *data << (uint32)(strlen(text)+1+(pre?3:0)); + if(pre) + data->append("%s ",3); + *data << text; + *data << (uint8)0; // ChatTag +} + +void WorldObject::BuildHeartBeatMsg(WorldPacket *data) const +{ + //Heartbeat message cannot be used for non-units + if (!isType(TYPEMASK_UNIT)) + return; + + data->Initialize(MSG_MOVE_HEARTBEAT, 32); + data->append(GetPackGUID()); + *data << uint32(((Unit*)this)->GetUnitMovementFlags()); // movement flags + *data << uint8(0); // 2.3.0 + *data << getMSTime(); // time + *data << m_positionX; + *data << m_positionY; + *data << m_positionZ; + *data << m_orientation; + *data << uint32(0); +} + +void WorldObject::BuildTeleportAckMsg(WorldPacket *data, float x, float y, float z, float ang) const +{ + //TeleportAck message cannot be used for non-units + if (!isType(TYPEMASK_UNIT)) + return; + + data->Initialize(MSG_MOVE_TELEPORT_ACK, 41); + data->append(GetPackGUID()); + *data << uint32(0); // this value increments every time + *data << uint32(((Unit*)this)->GetUnitMovementFlags()); // movement flags + *data << uint8(0); // 2.3.0 + *data << getMSTime(); // time + *data << x; + *data << y; + *data << z; + *data << ang; + *data << uint32(0); +} + +void WorldObject::SendMessageToSet(WorldPacket *data, bool /*bToSelf*/) +{ + MapManager::Instance().GetMap(m_mapId, this)->MessageBroadcast(this, data); +} + +void WorldObject::SendMessageToSetInRange(WorldPacket *data, float dist, bool /*bToSelf*/) +{ + MapManager::Instance().GetMap(m_mapId, this)->MessageDistBroadcast(this, data, dist); +} + +void WorldObject::SendObjectDeSpawnAnim(uint64 guid) +{ + WorldPacket data(SMSG_GAMEOBJECT_DESPAWN_ANIM, 8); + data << guid; + SendMessageToSet(&data, true); +} + +Map* WorldObject::GetMap() const +{ + return MapManager::Instance().GetMap(GetMapId(), this); +} + +Map const* WorldObject::GetBaseMap() const +{ + return MapManager::Instance().GetBaseMap(GetMapId()); +} + +void WorldObject::AddObjectToRemoveList() +{ + Map* map = GetMap(); + if(!map) + { + sLog.outError("Object (TypeId: %u Entry: %u GUID: %u) at attempt add to move list not have valid map (Id: %u).",GetTypeId(),GetEntry(),GetGUIDLow(),GetMapId()); + return; + } + + map->AddObjectToRemoveList(this); +} + +Creature* WorldObject::SummonCreature(uint32 id, float x, float y, float z, float ang,TempSummonType spwtype,uint32 despwtime) +{ + TemporarySummon* pCreature = new TemporarySummon(GetGUID()); + + pCreature->SetInstanceId(GetInstanceId()); + uint32 team = 0; + if (GetTypeId()==TYPEID_PLAYER) + team = ((Player*)this)->GetTeam(); + + if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), GetMap(), id, team)) + { + delete pCreature; + return NULL; + } + + if (x == 0.0f && y == 0.0f && z == 0.0f) + GetClosePoint(x, y, z, pCreature->GetObjectSize()); + + pCreature->Relocate(x, y, z, ang); + + if(!pCreature->IsPositionValid()) + { + sLog.outError("ERROR: Creature (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",pCreature->GetGUIDLow(),pCreature->GetEntry(),pCreature->GetPositionX(),pCreature->GetPositionY()); + delete pCreature; + return NULL; + } + + pCreature->Summon(spwtype, despwtime); + + if(GetTypeId()==TYPEID_UNIT && ((Creature*)this)->AI()) + ((Creature*)this)->AI()->JustSummoned(pCreature); + + //return the creature therewith the summoner has access to it + return pCreature; +} + +namespace MaNGOS +{ + class NearUsedPosDo + { + public: + NearUsedPosDo(WorldObject const& obj, WorldObject const* searcher, float angle, ObjectPosSelector& selector) + : i_object(obj), i_searcher(searcher), i_angle(angle), i_selector(selector) {} + + void operator()(Corpse*) const {} + void operator()(DynamicObject*) const {} + + void operator()(Creature* c) const + { + // skip self or target + if(c==i_searcher || c==&i_object) + return; + + float x,y,z; + + if( !c->isAlive() || c->hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED | UNIT_STAT_DISTRACTED) || + !c->GetMotionMaster()->GetDestination(x,y,z) ) + { + x = c->GetPositionX(); + y = c->GetPositionY(); + } + + add(c,x,y); + } + + template + void operator()(T* u) const + { + // skip self or target + if(u==i_searcher || u==&i_object) + return; + + float x,y; + + x = u->GetPositionX(); + y = u->GetPositionY(); + + add(u,x,y); + } + + // we must add used pos that can fill places around center + void add(WorldObject* u, float x, float y) const + { + // dist include size of u + float dist2d = i_object.GetDistance2d(x,y); + + // u is too nearest to i_object + if(dist2d + i_object.GetObjectSize() + u->GetObjectSize() < i_selector.m_dist - i_selector.m_size) + return; + + // u is too far away from i_object + if(dist2d + i_object.GetObjectSize() - u->GetObjectSize() > i_selector.m_dist + i_selector.m_size) + return; + + float angle = i_object.GetAngle(u)-i_angle; + + // move angle to range -pi ... +pi + while( angle > M_PI) + angle -= 2.0f * M_PI; + while(angle < -M_PI) + angle += 2.0f * M_PI; + + i_selector.AddUsedPos(u->GetObjectSize(),angle,dist2d + i_object.GetObjectSize()); + } + private: + WorldObject const& i_object; + WorldObject const* i_searcher; + float i_angle; + ObjectPosSelector& i_selector; + }; +} // namespace MaNGOS + +//=================================================================================================== + +void WorldObject::GetNearPoint2D(float &x, float &y, float distance2d, float absAngle ) const +{ + x = GetPositionX() + (GetObjectSize() + distance2d) * cos(absAngle); + y = GetPositionY() + (GetObjectSize() + distance2d) * sin(absAngle); + + MaNGOS::NormalizeMapCoord(x); + MaNGOS::NormalizeMapCoord(y); +} + +void WorldObject::GetNearPoint(WorldObject const* searcher, float &x, float &y, float &z, float searcher_size, float distance2d, float absAngle ) const +{ + GetNearPoint2D(x,y,distance2d+searcher_size,absAngle); + z = GetPositionZ(); + + // if detection disabled, return first point + if(!sWorld.getConfig(CONFIG_DETECT_POS_COLLISION)) + { + UpdateGroundPositionZ(x,y,z); // update to LOS height if available + return; + } + + // or remember first point + float first_x = x; + float first_y = y; + bool first_los_conflict = false; // first point LOS problems + + // prepare selector for work + ObjectPosSelector selector(GetPositionX(),GetPositionY(),GetObjectSize(),distance2d+searcher_size); + + // adding used positions around object + { + CellPair p(MaNGOS::ComputeCellPair(GetPositionX(), GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + MaNGOS::NearUsedPosDo u_do(*this,searcher,absAngle,selector); + MaNGOS::WorldObjectWorker worker(u_do); + + TypeContainerVisitor, GridTypeMapContainer > grid_obj_worker(worker); + TypeContainerVisitor, WorldTypeMapContainer > world_obj_worker(worker); + + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, grid_obj_worker, *MapManager::Instance().GetMap(GetMapId(), this)); + cell_lock->Visit(cell_lock, world_obj_worker, *MapManager::Instance().GetMap(GetMapId(), this)); + } + + // maybe can just place in primary position + if( selector.CheckOriginal() ) + { + UpdateGroundPositionZ(x,y,z); // update to LOS height if available + + if(IsWithinLOS(x,y,z)) + return; + + first_los_conflict = true; // first point have LOS problems + } + + float angle; // candidate of angle for free pos + + // special case when one from list empty and then empty side preferred + if(selector.FirstAngle(angle)) + { + GetNearPoint2D(x,y,distance2d,absAngle+angle); + z = GetPositionZ(); + UpdateGroundPositionZ(x,y,z); // update to LOS height if available + + if(IsWithinLOS(x,y,z)) + return; + } + + // set first used pos in lists + selector.InitializeAngle(); + + // select in positions after current nodes (selection one by one) + while(selector.NextAngle(angle)) // angle for free pos + { + GetNearPoint2D(x,y,distance2d,absAngle+angle); + z = GetPositionZ(); + UpdateGroundPositionZ(x,y,z); // update to LOS height if available + + if(IsWithinLOS(x,y,z)) + return; + } + + // BAD NEWS: not free pos (or used or have LOS problems) + // Attempt find _used_ pos without LOS problem + + if(!first_los_conflict) + { + x = first_x; + y = first_y; + + UpdateGroundPositionZ(x,y,z); // update to LOS height if available + return; + } + + // special case when one from list empty and then empty side preferred + if( selector.IsNonBalanced() ) + { + if(!selector.FirstAngle(angle)) // _used_ pos + { + GetNearPoint2D(x,y,distance2d,absAngle+angle); + z = GetPositionZ(); + UpdateGroundPositionZ(x,y,z); // update to LOS height if available + + if(IsWithinLOS(x,y,z)) + return; + } + } + + // set first used pos in lists + selector.InitializeAngle(); + + // select in positions after current nodes (selection one by one) + while(selector.NextUsedAngle(angle)) // angle for used pos but maybe without LOS problem + { + GetNearPoint2D(x,y,distance2d,absAngle+angle); + z = GetPositionZ(); + UpdateGroundPositionZ(x,y,z); // update to LOS height if available + + if(IsWithinLOS(x,y,z)) + return; + } + + // BAD BAD NEWS: all found pos (free and used) have LOS problem :( + x = first_x; + y = first_y; + + UpdateGroundPositionZ(x,y,z); // update to LOS height if available +} diff --git a/src/game/Object.h b/src/game/Object.h new file mode 100644 index 00000000000..c870e9452c9 --- /dev/null +++ b/src/game/Object.h @@ -0,0 +1,460 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _OBJECT_H +#define _OBJECT_H + +#include "Common.h" +#include "ByteBuffer.h" +#include "UpdateFields.h" +#include "UpdateData.h" +#include "GameSystem/GridReference.h" +#include "ObjectDefines.h" + +#include +#include + +#define CONTACT_DISTANCE 0.5f +#define INTERACTION_DISTANCE 5 +#define ATTACK_DISTANCE 5 +#define DETECT_DISTANCE 20 // max distance to successful detect stealthed unit +#define MAX_VISIBILITY_DISTANCE (5*SIZE_OF_GRID_CELL/2.0f) // max distance for visible object show, limited by active zone for player based at cell size (active zone = 5x5 cells) +#define DEFAULT_VISIBILITY_DISTANCE (SIZE_OF_GRID_CELL) // default visible distance + +#define DEFAULT_WORLD_OBJECT_SIZE 0.388999998569489f // player size, also currently used (correctly?) for any non Unit world objects + +enum TypeMask +{ + TYPEMASK_OBJECT = 0x0001, + TYPEMASK_ITEM = 0x0002, + TYPEMASK_CONTAINER = 0x0006, // TYPEMASK_ITEM | 0x0004 + TYPEMASK_UNIT = 0x0008, + TYPEMASK_PLAYER = 0x0010, + TYPEMASK_GAMEOBJECT = 0x0020, + TYPEMASK_DYNAMICOBJECT = 0x0040, + TYPEMASK_CORPSE = 0x0080, + TYPEMASK_AIGROUP = 0x0100, + TYPEMASK_AREATRIGGER = 0x0200 +}; + +enum TypeID +{ + TYPEID_OBJECT = 0, + TYPEID_ITEM = 1, + TYPEID_CONTAINER = 2, + TYPEID_UNIT = 3, + TYPEID_PLAYER = 4, + TYPEID_GAMEOBJECT = 5, + TYPEID_DYNAMICOBJECT = 6, + TYPEID_CORPSE = 7, + TYPEID_AIGROUP = 8, + TYPEID_AREATRIGGER = 9 +}; + +uint32 GuidHigh2TypeId(uint32 guid_hi); + +enum TempSummonType +{ + TEMPSUMMON_TIMED_OR_DEAD_DESPAWN = 1, // despawns after a specified time OR when the creature disappears + TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN = 2, // despawns after a specified time OR when the creature dies + TEMPSUMMON_TIMED_DESPAWN = 3, // despawns after a specified time + TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT = 4, // despawns after a specified time after the creature is out of combat + TEMPSUMMON_CORPSE_DESPAWN = 5, // despawns instantly after death + TEMPSUMMON_CORPSE_TIMED_DESPAWN = 6, // despawns after a specified time after death + TEMPSUMMON_DEAD_DESPAWN = 7, // despawns when the creature disappears + TEMPSUMMON_MANUAL_DESPAWN = 8 // despawns when UnSummon() is called +}; + +class WorldPacket; +class UpdateData; +class ByteBuffer; +class WorldSession; +class Creature; +class Player; +class Map; +class UpdateMask; +class InstanceData; + +typedef HM_NAMESPACE::hash_map UpdateDataMapType; + +struct WorldLocation +{ + uint32 mapid; + float x; + float y; + float z; + float o; + explicit WorldLocation(uint32 mapid = 0, float x = 0, float y = 0, float z = 0, float o = 0) + : mapid(mapid), x(x), y(y), z(z), o(o) {} + WorldLocation(WorldLocation const &loc) + : mapid(loc.mapid), x(loc.x), y(loc.y), z(loc.z), o(loc.o) {} +}; + +class MANGOS_DLL_SPEC Object +{ + public: + virtual ~Object ( ); + + const bool& IsInWorld() const { return m_inWorld; } + virtual void AddToWorld() + { + if(m_inWorld) + return; + + m_inWorld = true; + + // synchronize values mirror with values array (changes will send in updatecreate opcode any way + ClearUpdateMask(true); + } + virtual void RemoveFromWorld() + { + // if we remove from world then sending changes not required + if(m_uint32Values) + ClearUpdateMask(true); + m_inWorld = false; + } + + const uint64& GetGUID() const { return GetUInt64Value(0); } + uint32 GetGUIDLow() const { return GUID_LOPART(GetUInt64Value(0)); } + uint32 GetGUIDMid() const { return GUID_ENPART(GetUInt64Value(0)); } + uint32 GetGUIDHigh() const { return GUID_HIPART(GetUInt64Value(0)); } + const ByteBuffer& GetPackGUID() const { return m_PackGUID; } + uint32 GetEntry() const { return GetUInt32Value(OBJECT_FIELD_ENTRY); } + + uint8 GetTypeId() const { return m_objectTypeId; } + bool isType(uint16 mask) const { return (mask & m_objectType); } + + virtual void BuildCreateUpdateBlockForPlayer( UpdateData *data, Player *target ) const; + void SendUpdateToPlayer(Player* player); + + void BuildValuesUpdateBlockForPlayer( UpdateData *data, Player *target ) const; + void BuildOutOfRangeUpdateBlock( UpdateData *data ) const; + void BuildMovementUpdateBlock( UpdateData * data, uint32 flags = 0 ) const; + void BuildUpdate(UpdateDataMapType &); + + virtual void DestroyForPlayer( Player *target ) const; + + const int32& GetInt32Value( uint16 index ) const + { + ASSERT( index < m_valuesCount || PrintIndexError( index , false) ); + return m_int32Values[ index ]; + } + + const uint32& GetUInt32Value( uint16 index ) const + { + ASSERT( index < m_valuesCount || PrintIndexError( index , false) ); + return m_uint32Values[ index ]; + } + + const uint64& GetUInt64Value( uint16 index ) const + { + ASSERT( index + 1 < m_valuesCount || PrintIndexError( index , false) ); + return *((uint64*)&(m_uint32Values[ index ])); + } + + const float& GetFloatValue( uint16 index ) const + { + ASSERT( index < m_valuesCount || PrintIndexError( index , false ) ); + return m_floatValues[ index ]; + } + + uint8 GetByteValue( uint16 index, uint8 offset) const + { + ASSERT( index < m_valuesCount || PrintIndexError( index , false) ); + ASSERT( offset < 4 ); + return *(((uint8*)&m_uint32Values[ index ])+offset); + } + + uint8 GetUInt16Value( uint16 index, uint8 offset) const + { + ASSERT( index < m_valuesCount || PrintIndexError( index , false) ); + ASSERT( offset < 2 ); + return *(((uint16*)&m_uint32Values[ index ])+offset); + } + + void SetInt32Value( uint16 index, int32 value ); + void SetUInt32Value( uint16 index, uint32 value ); + void SetUInt64Value( uint16 index, const uint64 &value ); + void SetFloatValue( uint16 index, float value ); + void SetByteValue( uint16 index, uint8 offset, uint8 value ); + void SetUInt16Value( uint16 index, uint8 offset, uint16 value ); + void SetInt16Value( uint16 index, uint8 offset, int16 value ) { SetUInt16Value(index,offset,(uint16)value); } + void SetStatFloatValue( uint16 index, float value); + void SetStatInt32Value( uint16 index, int32 value); + + void ApplyModUInt32Value(uint16 index, int32 val, bool apply); + void ApplyModInt32Value(uint16 index, int32 val, bool apply); + void ApplyModUInt64Value(uint16 index, int32 val, bool apply); + void ApplyModPositiveFloatValue( uint16 index, float val, bool apply); + void ApplyModSignedFloatValue( uint16 index, float val, bool apply); + + void ApplyPercentModFloatValue(uint16 index, float val, bool apply) + { + val = val != -100.0f ? val : -99.9f ; + SetFloatValue(index, GetFloatValue(index) * (apply?(100.0f+val)/100.0f : 100.0f / (100.0f+val)) ); + } + + void SetFlag( uint16 index, uint32 newFlag ); + void RemoveFlag( uint16 index, uint32 oldFlag ); + + void ToggleFlag( uint16 index, uint32 flag) + { + if(HasFlag(index, flag)) + RemoveFlag(index, flag); + else + SetFlag(index, flag); + } + + bool HasFlag( uint16 index, uint32 flag ) const + { + ASSERT( index < m_valuesCount || PrintIndexError( index , false ) ); + return (m_uint32Values[ index ] & flag) != 0; + } + + void ApplyModFlag( uint16 index, uint32 flag, bool apply) + { + if(apply) SetFlag(index,flag); else RemoveFlag(index,flag); + } + + void SetFlag64( uint16 index, uint64 newFlag ) + { + uint64 oldval = GetUInt64Value(index); + uint64 newval = oldval | newFlag; + SetUInt64Value(index,newval); + } + + void RemoveFlag64( uint16 index, uint64 oldFlag ) + { + uint64 oldval = GetUInt64Value(index); + uint64 newval = oldval & ~oldFlag; + SetUInt64Value(index,newval); + } + + void ToggleFlag64( uint16 index, uint64 flag) + { + if(HasFlag64(index, flag)) + RemoveFlag64(index, flag); + else + SetFlag64(index, flag); + } + + bool HasFlag64( uint16 index, uint64 flag ) const + { + ASSERT( index < m_valuesCount || PrintIndexError( index , false ) ); + return (GetUInt64Value( index ) & flag) != 0; + } + + void ApplyModFlag64( uint16 index, uint64 flag, bool apply) + { + if(apply) SetFlag64(index,flag); else RemoveFlag64(index,flag); + } + + void ClearUpdateMask(bool remove); + void SendUpdateObjectToAllExcept(Player* exceptPlayer); + + bool LoadValues(const char* data); + + uint16 GetValuesCount() const { return m_valuesCount; } + + void InitValues() { _InitValues(); } + + virtual bool hasQuest(uint32 /* quest_id */) const { return false; } + virtual bool hasInvolvedQuest(uint32 /* quest_id */) const { return false; } + protected: + + Object ( ); + + void _InitValues(); + void _Create (uint32 guidlow, uint32 entry, HighGuid guidhigh); + + virtual void _SetUpdateBits(UpdateMask *updateMask, Player *target) const; + + virtual void _SetCreateBits(UpdateMask *updateMask, Player *target) const; + void _BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2 ) const; + void _BuildValuesUpdate(uint8 updatetype, ByteBuffer *data, UpdateMask *updateMask, Player *target ) const; + + uint16 m_objectType; + + uint8 m_objectTypeId; + uint8 m_updateFlag; + + union + { + int32 *m_int32Values; + uint32 *m_uint32Values; + float *m_floatValues; + }; + + uint32 *m_uint32Values_mirror; + + uint16 m_valuesCount; + + bool m_objectUpdated; + + private: + bool m_inWorld; + + ByteBuffer m_PackGUID; + + // for output helpfull error messages from asserts + bool PrintIndexError(uint32 index, bool set) const; + Object(const Object&); // prevent generation copy constructor + Object& operator=(Object const&); // prevent generation assigment operator +}; + +class MANGOS_DLL_SPEC WorldObject : public Object +{ + public: + virtual ~WorldObject ( ) {} + + virtual void Update ( uint32 /*time_diff*/ ) { } + + void _Create( uint32 guidlow, HighGuid guidhigh, uint32 mapid ); + + void Relocate(float x, float y, float z, float orientation) + { + m_positionX = x; + m_positionY = y; + m_positionZ = z; + m_orientation = orientation; + } + + void Relocate(float x, float y, float z) + { + m_positionX = x; + m_positionY = y; + m_positionZ = z; + } + + void Relocate(WorldLocation const & loc) + { + SetMapId(loc.mapid); + Relocate(loc.x, loc.y, loc.z, loc.o); + } + + void SetOrientation(float orientation) { m_orientation = orientation; } + + float GetPositionX( ) const { return m_positionX; } + float GetPositionY( ) const { return m_positionY; } + float GetPositionZ( ) const { return m_positionZ; } + void GetPosition( float &x, float &y, float &z ) const + { x = m_positionX; y = m_positionY; z = m_positionZ; } + void GetPosition( WorldLocation &loc ) const + { loc.mapid = GetMapId(); GetPosition(loc.x, loc.y, loc.z); loc.o = GetOrientation(); } + float GetOrientation( ) const { return m_orientation; } + void GetNearPoint2D( float &x, float &y, float distance, float absAngle) const; + void GetNearPoint( WorldObject const* searcher, float &x, float &y, float &z, float searcher_size, float distance2d,float absAngle) const; + void GetClosePoint(float &x, float &y, float &z, float size, float distance2d = 0, float angle = 0) const + { + // angle calculated from current orientation + GetNearPoint(NULL,x,y,z,size,distance2d,GetOrientation() + angle); + } + void GetContactPoint( const WorldObject* obj, float &x, float &y, float &z, float distance2d = CONTACT_DISTANCE) const + { + // angle to face `obj` to `this` using distance includes size of `obj` + GetNearPoint(obj,x,y,z,obj->GetObjectSize(),distance2d,GetAngle( obj )); + } + + float GetObjectSize() const + { + return ( m_valuesCount > UNIT_FIELD_BOUNDINGRADIUS ) ? m_floatValues[UNIT_FIELD_BOUNDINGRADIUS] : DEFAULT_WORLD_OBJECT_SIZE; + } + bool IsPositionValid() const; + void UpdateGroundPositionZ(float x, float y, float &z) const; + + void GetRandomPoint( float x, float y, float z, float distance, float &rand_x, float &rand_y, float &rand_z ) const; + + void SetMapId(uint32 newMap) { m_mapId = newMap; } + + uint32 GetMapId() const { return m_mapId; } + + uint32 GetZoneId() const; + uint32 GetAreaId() const; + + InstanceData* GetInstanceData(); + + const char* GetName() const { return m_name.c_str(); } + void SetName(std::string newname) { m_name=newname; } + + float GetDistance( const WorldObject* obj ) const; + float GetDistance(const float x, const float y, const float z) const; + float GetDistance2d(const WorldObject* obj) const; + float GetDistance2d(const float x, const float y) const; + float GetDistanceZ(const WorldObject* obj) const; + bool IsInMap(const WorldObject* obj) const { return GetMapId()==obj->GetMapId() && GetInstanceId()==obj->GetInstanceId(); } + bool IsWithinDistInMap(const WorldObject* obj, const float dist2compare) const; + bool IsWithinLOS(const float x, const float y, const float z ) const; + bool IsWithinLOSInMap(const WorldObject* obj) const; + + float GetAngle( const WorldObject* obj ) const; + float GetAngle( const float x, const float y ) const; + bool HasInArc( const float arcangle, const WorldObject* obj ) const; + + virtual void SendMessageToSet(WorldPacket *data, bool self); + virtual void SendMessageToSetInRange(WorldPacket *data, float dist, bool self); + void BuildHeartBeatMsg( WorldPacket *data ) const; + void BuildTeleportAckMsg( WorldPacket *data, float x, float y, float z, float ang) const; + bool IsBeingTeleported() { return mSemaphoreTeleport; } + void SetSemaphoreTeleport(bool semphsetting) { mSemaphoreTeleport = semphsetting; } + + void MonsterSay(const char* text, uint32 language, uint64 TargetGuid); + void MonsterYell(const char* text, uint32 language, uint64 TargetGuid); + void MonsterTextEmote(const char* text, uint64 TargetGuid, bool IsBossEmote = false); + void MonsterWhisper(const char* text, uint64 receiver, bool IsBossWhisper = false); + void MonsterSay(int32 textId, uint32 language, uint64 TargetGuid); + void MonsterYell(int32 textId, uint32 language, uint64 TargetGuid); + void MonsterTextEmote(int32 textId, uint64 TargetGuid, bool IsBossEmote = false); + void MonsterWhisper(int32 textId, uint64 receiver, bool IsBossWhisper = false); + void BuildMonsterChat(WorldPacket *data, uint8 msgtype, char const* text, uint32 language, char const* name, uint64 TargetGuid) const; + + void SendObjectDeSpawnAnim(uint64 guid); + + virtual void SaveRespawnTime() {} + + uint32 GetInstanceId() const { return m_InstanceId; } + void SetInstanceId(uint32 val) { m_InstanceId = val; } + + void AddObjectToRemoveList(); + + // main visibility check function in normal case (ignore grey zone distance check) + bool isVisibleFor(Player const* u) const { return isVisibleForInState(u,false); } + + // low level function for visibility change code, must be define in all main world object subclasses + virtual bool isVisibleForInState(Player const* u, bool inVisibleList) const = 0; + + Map * GetMap() const; + Map const* GetBaseMap() const; + Creature* SummonCreature(uint32 id, float x, float y, float z, float ang,TempSummonType spwtype,uint32 despwtime); + + protected: + explicit WorldObject(); + std::string m_name; + + private: + uint32 m_mapId; + + float m_positionX; + float m_positionY; + float m_positionZ; + float m_orientation; + + bool mSemaphoreTeleport; + + uint32 m_InstanceId; +}; +#endif diff --git a/src/game/ObjectAccessor.cpp b/src/game/ObjectAccessor.cpp new file mode 100644 index 00000000000..702bdc72123 --- /dev/null +++ b/src/game/ObjectAccessor.cpp @@ -0,0 +1,648 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ObjectAccessor.h" +#include "ObjectMgr.h" +#include "Policies/SingletonImp.h" +#include "Player.h" +#include "Creature.h" +#include "GameObject.h" +#include "DynamicObject.h" +#include "Corpse.h" +#include "WorldSession.h" +#include "WorldPacket.h" +#include "Item.h" +#include "Corpse.h" +#include "GridNotifiers.h" +#include "MapManager.h" +#include "Map.h" +#include "CellImpl.h" +#include "GridNotifiersImpl.h" +#include "Opcodes.h" +#include "ObjectDefines.h" +#include "MapInstanced.h" + +#include + +#define CLASS_LOCK MaNGOS::ClassLevelLockable +INSTANTIATE_SINGLETON_2(ObjectAccessor, CLASS_LOCK); +INSTANTIATE_CLASS_MUTEX(ObjectAccessor, ZThread::FastMutex); + +namespace MaNGOS +{ + + struct MANGOS_DLL_DECL BuildUpdateForPlayer + { + Player &i_player; + UpdateDataMapType &i_updatePlayers; + + BuildUpdateForPlayer(Player &player, UpdateDataMapType &data_map) : i_player(player), i_updatePlayers(data_map) {} + + void Visit(PlayerMapType &m) + { + for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + { + if( iter->getSource() == &i_player ) + continue; + + UpdateDataMapType::iterator iter2 = i_updatePlayers.find(iter->getSource()); + if( iter2 == i_updatePlayers.end() ) + { + std::pair p = i_updatePlayers.insert( ObjectAccessor::UpdateDataValueType(iter->getSource(), UpdateData()) ); + assert(p.second); + iter2 = p.first; + } + + i_player.BuildValuesUpdateBlockForPlayer(&iter2->second, iter2->first); + } + } + + template void Visit(GridRefManager &) {} + }; +} + +ObjectAccessor::ObjectAccessor() {} +ObjectAccessor::~ObjectAccessor() {} + +Creature* +ObjectAccessor::GetNPCIfCanInteractWith(Player const &player, uint64 guid, uint32 npcflagmask) +{ + // unit checks + if (!guid) + return NULL; + + // exist + Creature *unit = GetCreature(player, guid); + if (!unit) + return NULL; + + // player check + if(!player.CanInteractWithNPCs(!unit->isSpiritService())) + return NULL; + + // appropriate npc type + if(npcflagmask && !unit->HasFlag( UNIT_NPC_FLAGS, npcflagmask )) + return NULL; + + // alive or spirit healer + if(!unit->isAlive() && (!unit->isSpiritService() || player.isAlive() )) + return NULL; + + // not allow interaction under control + if(unit->GetCharmerOrOwnerGUID()) + return NULL; + + // not enemy + if( unit->IsHostileTo(&player)) + return NULL; + + // not unfriendly + FactionTemplateEntry const* factionTemplate = sFactionTemplateStore.LookupEntry(unit->getFaction()); + if(factionTemplate) + { + FactionEntry const* faction = sFactionStore.LookupEntry(factionTemplate->faction); + if( faction->reputationListID >= 0 && player.GetReputationRank(faction) <= REP_UNFRIENDLY) + return NULL; + } + + // not too far + if(!unit->IsWithinDistInMap(&player,INTERACTION_DISTANCE)) + return NULL; + + return unit; +} + +Creature* +ObjectAccessor::GetCreatureOrPet(WorldObject const &u, uint64 guid) +{ + if(Creature *unit = GetPet(guid)) + return unit; + + return GetCreature(u, guid); +} + +Creature* +ObjectAccessor::GetCreature(WorldObject const &u, uint64 guid) +{ + Creature * ret = GetObjectInWorld(guid, (Creature*)NULL); + if(ret && ret->GetMapId() != u.GetMapId()) ret = NULL; + return ret; +} + +Unit* +ObjectAccessor::GetUnit(WorldObject const &u, uint64 guid) +{ + if(!guid) + return NULL; + + if(IS_PLAYER_GUID(guid)) + return FindPlayer(guid); + + return GetCreatureOrPet(u, guid); +} + +Corpse* +ObjectAccessor::GetCorpse(WorldObject const &u, uint64 guid) +{ + Corpse * ret = GetObjectInWorld(guid, (Corpse*)NULL); + if(ret && ret->GetMapId() != u.GetMapId()) ret = NULL; + return ret; +} + +Object* ObjectAccessor::GetObjectByTypeMask(Player const &p, uint64 guid, uint32 typemask) +{ + Object *obj = NULL; + + if(typemask & TYPEMASK_PLAYER) + { + obj = FindPlayer(guid); + if(obj) return obj; + } + + if(typemask & TYPEMASK_UNIT) + { + obj = GetCreatureOrPet(p,guid); + if(obj) return obj; + } + + if(typemask & TYPEMASK_GAMEOBJECT) + { + obj = GetGameObject(p,guid); + if(obj) return obj; + } + + if(typemask & TYPEMASK_DYNAMICOBJECT) + { + obj = GetDynamicObject(p,guid); + if(obj) return obj; + } + + if(typemask & TYPEMASK_ITEM) + { + obj = p.GetItemByGuid( guid ); + if(obj) return obj; + } + + return NULL; +} + +GameObject* +ObjectAccessor::GetGameObject(WorldObject const &u, uint64 guid) +{ + GameObject * ret = GetObjectInWorld(guid, (GameObject*)NULL); + if(ret && ret->GetMapId() != u.GetMapId()) ret = NULL; + return ret; +} + +DynamicObject* +ObjectAccessor::GetDynamicObject(Unit const &u, uint64 guid) +{ + DynamicObject * ret = GetObjectInWorld(guid, (DynamicObject*)NULL); + if(ret && ret->GetMapId() != u.GetMapId()) ret = NULL; + return ret; +} + +Player* +ObjectAccessor::FindPlayer(uint64 guid) +{ + return GetObjectInWorld(guid, (Player*)NULL); +} + +Player* +ObjectAccessor::FindPlayerByName(const char *name) +{ + //TODO: Player Guard + HashMapHolder::MapType& m = HashMapHolder::GetContainer(); + HashMapHolder::MapType::iterator iter = m.begin(); + for(; iter != m.end(); ++iter) + if( ::strcmp(name, iter->second->GetName()) == 0 ) + return iter->second; + return NULL; +} + +void +ObjectAccessor::SaveAllPlayers() +{ + Guard guard(*HashMapHolder::GetLock()); + HashMapHolder::MapType& m = HashMapHolder::GetContainer(); + HashMapHolder::MapType::iterator itr = m.begin(); + for(; itr != m.end(); ++itr) + itr->second->SaveToDB(); +} + +void +ObjectAccessor::_update() +{ + UpdateDataMapType update_players; + { + Guard guard(i_updateGuard); + while(!i_objects.empty()) + { + Object* obj = *i_objects.begin(); + i_objects.erase(i_objects.begin()); + if (!obj) + continue; + _buildUpdateObject(obj, update_players); + obj->ClearUpdateMask(false); + } + } + + WorldPacket packet; // here we allocate a std::vector with a size of 0x10000 + for(UpdateDataMapType::iterator iter = update_players.begin(); iter != update_players.end(); ++iter) + { + iter->second.BuildPacket(&packet); + iter->first->GetSession()->SendPacket(&packet); + packet.clear(); // clean the string + } +} + +void +ObjectAccessor::UpdateObject(Object* obj, Player* exceptPlayer) +{ + UpdateDataMapType update_players; + obj->BuildUpdate(update_players); + + WorldPacket packet; + for(UpdateDataMapType::iterator iter = update_players.begin(); iter != update_players.end(); ++iter) + { + if(iter->first == exceptPlayer) + continue; + + iter->second.BuildPacket(&packet); + iter->first->GetSession()->SendPacket(&packet); + packet.clear(); + } +} + +void +ObjectAccessor::AddUpdateObject(Object *obj) +{ + Guard guard(i_updateGuard); + i_objects.insert(obj); +} + +void +ObjectAccessor::RemoveUpdateObject(Object *obj) +{ + Guard guard(i_updateGuard); + std::set::iterator iter = i_objects.find(obj); + if( iter != i_objects.end() ) + i_objects.erase( iter ); +} + +void +ObjectAccessor::_buildUpdateObject(Object *obj, UpdateDataMapType &update_players) +{ + bool build_for_all = true; + Player *pl = NULL; + if( obj->isType(TYPEMASK_ITEM) ) + { + Item *item = static_cast(obj); + pl = item->GetOwner(); + build_for_all = false; + } + + if( pl != NULL ) + _buildPacket(pl, obj, update_players); + + // Capt: okey for all those fools who think its a real fix + // THIS IS A TEMP FIX + if( build_for_all ) + { + WorldObject * temp = dynamic_cast(obj); + + //assert(dynamic_cast(obj)!=NULL); + if (temp) + _buildChangeObjectForPlayer(temp, update_players); + else + sLog.outDebug("ObjectAccessor: Ln 405 Temp bug fix"); + } +} + +void +ObjectAccessor::_buildPacket(Player *pl, Object *obj, UpdateDataMapType &update_players) +{ + UpdateDataMapType::iterator iter = update_players.find(pl); + + if( iter == update_players.end() ) + { + std::pair p = update_players.insert( UpdateDataValueType(pl, UpdateData()) ); + assert(p.second); + iter = p.first; + } + + obj->BuildValuesUpdateBlockForPlayer(&iter->second, iter->first); +} + +void +ObjectAccessor::_buildChangeObjectForPlayer(WorldObject *obj, UpdateDataMapType &update_players) +{ + CellPair p = MaNGOS::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + WorldObjectChangeAccumulator notifier(*obj, update_players); + TypeContainerVisitor player_notifier(notifier); + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, player_notifier, *MapManager::Instance().GetMap(obj->GetMapId(), obj)); +} + +Pet* +ObjectAccessor::GetPet(uint64 guid) +{ + return GetObjectInWorld(guid, (Pet*)NULL); +} + +Corpse* +ObjectAccessor::GetCorpseForPlayerGUID(uint64 guid) +{ + Guard guard(i_corpseGuard); + + Player2CorpsesMapType::iterator iter = i_player2corpse.find(guid); + if( iter == i_player2corpse.end() ) return NULL; + + assert(iter->second->GetType() != CORPSE_BONES); + + return iter->second; +} + +void +ObjectAccessor::RemoveCorpse(Corpse *corpse) +{ + assert(corpse && corpse->GetType() != CORPSE_BONES); + + Guard guard(i_corpseGuard); + Player2CorpsesMapType::iterator iter = i_player2corpse.find(corpse->GetOwnerGUID()); + if( iter == i_player2corpse.end() ) + return; + + // build mapid*cellid -> guid_set map + CellPair cell_pair = MaNGOS::ComputeCellPair(corpse->GetPositionX(), corpse->GetPositionY()); + uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; + + objmgr.DeleteCorpseCellData(corpse->GetMapId(),cell_id,corpse->GetOwnerGUID()); + corpse->RemoveFromWorld(); + + i_player2corpse.erase(iter); +} + +void +ObjectAccessor::AddCorpse(Corpse *corpse) +{ + assert(corpse && corpse->GetType() != CORPSE_BONES); + + Guard guard(i_corpseGuard); + assert(i_player2corpse.find(corpse->GetOwnerGUID()) == i_player2corpse.end()); + i_player2corpse[corpse->GetOwnerGUID()] = corpse; + + // build mapid*cellid -> guid_set map + CellPair cell_pair = MaNGOS::ComputeCellPair(corpse->GetPositionX(), corpse->GetPositionY()); + uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; + + objmgr.AddCorpseCellData(corpse->GetMapId(),cell_id,corpse->GetOwnerGUID(),corpse->GetInstanceId()); +} + +void +ObjectAccessor::AddCorpsesToGrid(GridPair const& gridpair,GridType& grid,Map* map) +{ + Guard guard(i_corpseGuard); + for(Player2CorpsesMapType::iterator iter = i_player2corpse.begin(); iter != i_player2corpse.end(); ++iter) + if(iter->second->GetGrid()==gridpair) + { + // verify, if the corpse in our instance (add only corpses which are) + if (map->Instanceable()) + { + if (iter->second->GetInstanceId() == map->GetInstanceId()) + { + grid.AddWorldObject(iter->second,iter->second->GetGUID()); + } + } + else + { + grid.AddWorldObject(iter->second,iter->second->GetGUID()); + } + } +} + +Corpse* +ObjectAccessor::ConvertCorpseForPlayer(uint64 player_guid) +{ + Corpse *corpse = GetCorpseForPlayerGUID(player_guid); + if(!corpse) + { + //in fact this function is called from several places + //even when player doesn't have a corpse, not an error + //sLog.outError("ERROR: Try remove corpse that not in map for GUID %ul", player_guid); + return NULL; + } + + DEBUG_LOG("Deleting Corpse and spawning bones.\n"); + + // remove corpse from player_guid -> corpse map + RemoveCorpse(corpse); + + // remove resurrectble corpse from grid object registry (loaded state checked into call) + // do not load the map if it's not loaded + Map *map = MapManager::Instance().FindMap(corpse->GetMapId(), corpse->GetInstanceId()); + if(map) map->Remove(corpse,false); + + // remove corpse from DB + corpse->DeleteFromDB(); + + Corpse *bones = NULL; + // create the bones only if the map and the grid is loaded at the corpse's location + if(map && !map->IsRemovalGrid(corpse->GetPositionX(), corpse->GetPositionY())) + { + // Create bones, don't change Corpse + bones = new Corpse; + bones->Create(corpse->GetGUIDLow()); + + for (int i = 3; i < CORPSE_END; i++) // don't overwrite guid and object type + bones->SetUInt32Value(i, corpse->GetUInt32Value(i)); + + bones->SetGrid(corpse->GetGrid()); + // bones->m_time = m_time; // don't overwrite time + // bones->m_inWorld = m_inWorld; // don't overwrite world state + // bones->m_type = m_type; // don't overwrite type + bones->Relocate(corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetOrientation()); + bones->SetMapId(corpse->GetMapId()); + bones->SetInstanceId(corpse->GetInstanceId()); + + bones->SetUInt32Value(CORPSE_FIELD_FLAGS, CORPSE_FLAG_UNK2 | CORPSE_FLAG_BONES); + bones->SetUInt64Value(CORPSE_FIELD_OWNER, 0); + + for (int i = 0; i < EQUIPMENT_SLOT_END; i++) + { + if(corpse->GetUInt32Value(CORPSE_FIELD_ITEM + i)) + bones->SetUInt32Value(CORPSE_FIELD_ITEM + i, 0); + } + + // add bones in grid store if grid loaded where corpse placed + map->Add(bones); + } + + // all references to the corpse should be removed at this point + delete corpse; + + return bones; +} + +void +ObjectAccessor::Update(uint32 diff) +{ + { + typedef std::multimap CreatureLocationHolderType; + CreatureLocationHolderType creature_locations; + //TODO: Player guard + HashMapHolder::MapType& playerMap = HashMapHolder::GetContainer(); + for(HashMapHolder::MapType::iterator iter = playerMap.begin(); iter != playerMap.end(); ++iter) + { + if(iter->second->IsInWorld()) + { + iter->second->Update(diff); + creature_locations.insert( CreatureLocationHolderType::value_type(iter->second->GetMapId(), iter->second) ); + } + } + + Map *map; + + MaNGOS::ObjectUpdater updater(diff); + // for creature + TypeContainerVisitor grid_object_update(updater); + // for pets + TypeContainerVisitor world_object_update(updater); + + for(CreatureLocationHolderType::iterator iter=creature_locations.begin(); iter != creature_locations.end(); ++iter) + { + MapManager::Instance().GetMap((*iter).first, (*iter).second)->resetMarkedCells(); + } + + for(CreatureLocationHolderType::iterator iter=creature_locations.begin(); iter != creature_locations.end(); ++iter) + { + Player *player = (*iter).second; + map = MapManager::Instance().GetMap((*iter).first, player); + + CellPair standing_cell(MaNGOS::ComputeCellPair(player->GetPositionX(), player->GetPositionY())); + + // Check for correctness of standing_cell, it also avoids problems with update_cell + if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) + continue; + + // the overloaded operators handle range checking + // so ther's no need for range checking inside the loop + CellPair begin_cell(standing_cell), end_cell(standing_cell); + begin_cell << 1; begin_cell -= 1; // upper left + end_cell >> 1; end_cell += 1; // lower right + + for(uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; x++) + { + for(uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; y++) + { + uint32 cell_id = (y * TOTAL_NUMBER_OF_CELLS_PER_MAP) + x; + if( !map->isCellMarked(cell_id) ) + { + CellPair cell_pair(x,y); + map->markCell(cell_id); + Cell cell(cell_pair); + cell.data.Part.reserved = CENTER_DISTRICT; + cell.SetNoCreate(); + CellLock cell_lock(cell, cell_pair); + cell_lock->Visit(cell_lock, grid_object_update, *map); + cell_lock->Visit(cell_lock, world_object_update, *map); + } + } + } + } + } + + _update(); +} + +bool +ObjectAccessor::PlayersNearGrid(uint32 x, uint32 y, uint32 m_id, uint32 i_id) const +{ + CellPair cell_min(x*MAX_NUMBER_OF_CELLS, y*MAX_NUMBER_OF_CELLS); + CellPair cell_max(cell_min.x_coord + MAX_NUMBER_OF_CELLS, cell_min.y_coord+MAX_NUMBER_OF_CELLS); + cell_min << 2; + cell_min -= 2; + cell_max >> 2; + cell_max += 2; + + //TODO: Guard player + HashMapHolder::MapType& playerMap = HashMapHolder::GetContainer(); + for(HashMapHolder::MapType::const_iterator iter=playerMap.begin(); iter != playerMap.end(); ++iter) + { + if( m_id != iter->second->GetMapId() || i_id != iter->second->GetInstanceId() ) + continue; + + CellPair p = MaNGOS::ComputeCellPair(iter->second->GetPositionX(), iter->second->GetPositionY()); + if( (cell_min.x_coord <= p.x_coord && p.x_coord <= cell_max.x_coord) && + (cell_min.y_coord <= p.y_coord && p.y_coord <= cell_max.y_coord) ) + return true; + } + + return false; +} + +void +ObjectAccessor::WorldObjectChangeAccumulator::Visit(PlayerMapType &m) +{ + for(PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter) + if(iter->getSource()->HaveAtClient(&i_object)) + ObjectAccessor::_buildPacket(iter->getSource(), &i_object, i_updateDatas); +} + +void +ObjectAccessor::UpdateObjectVisibility(WorldObject *obj) +{ + CellPair p = MaNGOS::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()); + Cell cell(p); + + MapManager::Instance().GetMap(obj->GetMapId(), obj)->UpdateObjectVisibility(obj,cell,p); +} + +void ObjectAccessor::UpdateVisibilityForPlayer( Player* player ) +{ + CellPair p = MaNGOS::ComputeCellPair(player->GetPositionX(), player->GetPositionY()); + Cell cell(p); + Map* m = MapManager::Instance().GetMap(player->GetMapId(),player); + + m->UpdatePlayerVisibility(player,cell,p); + m->UpdateObjectsVisibilityFor(player,cell,p); +} + +/// Define the static member of HashMapHolder + +template HM_NAMESPACE::hash_map< uint64, T* > HashMapHolder::m_objectMap; +template ZThread::FastMutex HashMapHolder::i_lock; + +/// Global defintions for the hashmap storage + +template class HashMapHolder; +template class HashMapHolder; +template class HashMapHolder; +template class HashMapHolder; +template class HashMapHolder; +template class HashMapHolder; + +template Player* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, Player* /*fake*/); +template Pet* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, Pet* /*fake*/); +template Creature* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, Creature* /*fake*/); +template Corpse* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, Corpse* /*fake*/); +template GameObject* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, GameObject* /*fake*/); +template DynamicObject* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, DynamicObject* /*fake*/); diff --git a/src/game/ObjectAccessor.h b/src/game/ObjectAccessor.h new file mode 100644 index 00000000000..feb0780e36e --- /dev/null +++ b/src/game/ObjectAccessor.h @@ -0,0 +1,226 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_OBJECTACCESSOR_H +#define MANGOS_OBJECTACCESSOR_H + +#include "Platform/Define.h" +#include "Policies/Singleton.h" +#include "zthread/FastMutex.h" +#include "Utilities/HashMap.h" +#include "Policies/ThreadingModel.h" + +#include "ByteBuffer.h" +#include "UpdateData.h" + +#include "GridDefines.h" +#include "Object.h" +#include "Player.h" + +#include + +class Creature; +class Corpse; +class Unit; +class GameObject; +class DynamicObject; +class WorldObject; +class Map; + +template +class HashMapHolder +{ + public: + + typedef HM_NAMESPACE::hash_map< uint64, T* > MapType; + typedef ZThread::FastMutex LockType; + typedef MaNGOS::GeneralLock Guard; + + static void Insert(T* o) { m_objectMap[o->GetGUID()] = o; } + + static void Remove(T* o) + { + Guard guard(i_lock); + typename MapType::iterator itr = m_objectMap.find(o->GetGUID()); + if (itr != m_objectMap.end()) + m_objectMap.erase(itr); + } + + static T* Find(uint64 guid) + { + typename MapType::iterator itr = m_objectMap.find(guid); + return (itr != m_objectMap.end()) ? itr->second : NULL; + } + + static MapType& GetContainer() { return m_objectMap; } + + static LockType* GetLock() { return &i_lock; } + private: + + //Non instanciable only static + HashMapHolder() {} + + static LockType i_lock; + static MapType m_objectMap; +}; + +class MANGOS_DLL_DECL ObjectAccessor : public MaNGOS::Singleton > +{ + + friend class MaNGOS::OperatorNew; + ObjectAccessor(); + ~ObjectAccessor(); + ObjectAccessor(const ObjectAccessor &); + ObjectAccessor& operator=(const ObjectAccessor &); + + public: + typedef HM_NAMESPACE::hash_map Player2CorpsesMapType; + typedef HM_NAMESPACE::hash_map::value_type UpdateDataValueType; + + template static T* GetObjectInWorld(uint64 guid, T* /*fake*/) + { + return HashMapHolder::Find(guid); + } + + static Unit* GetObjectInWorld(uint64 guid, Unit* /*fake*/) + { + if(!guid) + return NULL; + + if (IS_PLAYER_GUID(guid)) + return (Unit*)HashMapHolder::Find(guid); + + if (Unit* u = (Unit*)HashMapHolder::Find(guid)) + return u; + + return (Unit*)HashMapHolder::Find(guid); + } + + template static T* GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, T* /*fake*/) + { + T* obj = HashMapHolder::Find(guid); + if(!obj || obj->GetMapId() != mapid) return NULL; + + CellPair p = MaNGOS::ComputeCellPair(x,y); + if(p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP ) + { + sLog.outError("ObjectAccessor::GetObjectInWorld: invalid coordinates supplied X:%f Y:%f grid cell [%u:%u]", x, y, p.x_coord, p.y_coord); + return NULL; + } + + CellPair q = MaNGOS::ComputeCellPair(obj->GetPositionX(),obj->GetPositionY()); + if(q.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || q.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP ) + { + sLog.outError("ObjectAccessor::GetObjecInWorld: object "I64FMTD" has invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUID(), obj->GetPositionX(), obj->GetPositionY(), q.x_coord, q.y_coord); + return NULL; + } + + int32 dx = int32(p.x_coord) - int32(q.x_coord); + int32 dy = int32(p.y_coord) - int32(q.y_coord); + + if (dx > -2 && dx < 2 && dy > -2 && dy < 2) return obj; + else return NULL; + } + + static Object* GetObjectByTypeMask(Player const &, uint64, uint32 typemask); + static Creature* GetNPCIfCanInteractWith(Player const &player, uint64 guid, uint32 npcflagmask); + static Creature* GetCreature(WorldObject const &, uint64); + static Creature* GetCreatureOrPet(WorldObject const &, uint64); + static Unit* GetUnit(WorldObject const &, uint64); + static Pet* GetPet(Unit const &, uint64 guid) { return GetPet(guid); } + static Player* GetPlayer(Unit const &, uint64 guid) { return FindPlayer(guid); } + static GameObject* GetGameObject(WorldObject const &, uint64); + static DynamicObject* GetDynamicObject(Unit const &, uint64); + static Corpse* GetCorpse(WorldObject const &u, uint64 guid); + static Pet* GetPet(uint64 guid); + static Player* FindPlayer(uint64); + + Player* FindPlayerByName(const char *name) ; + + HashMapHolder::MapType& GetPlayers() + { + return HashMapHolder::GetContainer(); + } + + template void AddObject(T *object) + { + HashMapHolder::Insert(object); + } + + template void RemoveObject(T *object) + { + HashMapHolder::Remove(object); + } + + void RemoveObject(Player *pl) + { + HashMapHolder::Remove(pl); + + Guard guard(i_updateGuard); + + std::set::iterator iter2 = std::find(i_objects.begin(), i_objects.end(), (Object *)pl); + if( iter2 != i_objects.end() ) + i_objects.erase(iter2); + } + + void SaveAllPlayers(); + + void AddUpdateObject(Object *obj); + void RemoveUpdateObject(Object *obj); + + void Update(uint32 diff); + + Corpse* GetCorpseForPlayerGUID(uint64 guid); + void RemoveCorpse(Corpse *corpse); + void AddCorpse(Corpse* corpse); + void AddCorpsesToGrid(GridPair const& gridpair,GridType& grid,Map* map); + Corpse* ConvertCorpseForPlayer(uint64 player_guid); + + bool PlayersNearGrid(uint32 x,uint32 y,uint32 m_id,uint32 i_id) const; + + static void UpdateObject(Object* obj, Player* exceptPlayer); + static void _buildUpdateObject(Object* obj, UpdateDataMapType &); + + static void UpdateObjectVisibility(WorldObject* obj); + static void UpdateVisibilityForPlayer(Player* player); + private: + struct WorldObjectChangeAccumulator + { + UpdateDataMapType &i_updateDatas; + WorldObject &i_object; + WorldObjectChangeAccumulator(WorldObject &obj, UpdateDataMapType &d) : i_updateDatas(d), i_object(obj) {} + void Visit(PlayerMapType &); + template void Visit(GridRefManager &) {} + }; + + friend struct WorldObjectChangeAccumulator; + Player2CorpsesMapType i_player2corpse; + + typedef ZThread::FastMutex LockType; + typedef MaNGOS::GeneralLock Guard; + + static void _buildChangeObjectForPlayer(WorldObject *, UpdateDataMapType &); + static void _buildPacket(Player *, Object *, UpdateDataMapType &); + void _update(void); + std::set i_objects; + LockType i_playerGuard; + LockType i_updateGuard; + LockType i_corpseGuard; + LockType i_petGuard; +}; +#endif diff --git a/src/game/ObjectDefines.h b/src/game/ObjectDefines.h new file mode 100644 index 00000000000..ca0fecef5a6 --- /dev/null +++ b/src/game/ObjectDefines.h @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_OBJECTDEFINES_H +#define MANGOS_OBJECTDEFINES_H + +#include "Platform/Define.h" + +// used for creating values for respawn for example +#define MAKE_PAIR64(l, h) uint64( uint32(l) | ( uint64(h) << 32 ) ) +#define PAIR64_HIPART(x) (uint32)((uint64(x) >> 32) & 0x00000000FFFFFFFFLL) +#define PAIR64_LOPART(x) (uint32)(uint64(x) & 0x00000000FFFFFFFFLL) + +#define MAKE_PAIR32(l, h) uint32( uint16(l) | ( uint32(h) << 16 ) ) +#define PAIR32_HIPART(x) (uint16)((uint32(x) >> 16) & 0x0000FFFF) +#define PAIR32_LOPART(x) (uint16)(uint32(x) & 0x0000FFFF) + +enum HighGuid +{ + HIGHGUID_ITEM = 0x4000, // blizz 4000 + HIGHGUID_CONTAINER = 0x4000, // blizz 4000 + HIGHGUID_PLAYER = 0x0000, // blizz 0000 + HIGHGUID_GAMEOBJECT = 0xF110, // blizz F110 + HIGHGUID_TRANSPORT = 0xF120, // blizz F120 (for GAMEOBJECT_TYPE_TRANSPORT) + HIGHGUID_UNIT = 0xF130, // blizz F130 + HIGHGUID_PET = 0xF140, // blizz F140 + HIGHGUID_DYNAMICOBJECT = 0xF100, // blizz F100 + HIGHGUID_CORPSE = 0xF101, // blizz F100 + HIGHGUID_MO_TRANSPORT = 0x1FC0, // blizz 1FC0 (for GAMEOBJECT_TYPE_MO_TRANSPORT) +}; + +#define IS_EMPTY_GUID(Guid) ( Guid == 0 ) + +#define IS_CREATURE_GUID(Guid) ( GUID_HIPART(Guid) == HIGHGUID_UNIT ) +#define IS_PET_GUID(Guid) ( GUID_HIPART(Guid) == HIGHGUID_PET ) +#define IS_CREATURE_OR_PET_GUID(Guid)( IS_CREATURE_GUID(Guid) || IS_PET_GUID(Guid) ) +#define IS_PLAYER_GUID(Guid) ( GUID_HIPART(Guid) == HIGHGUID_PLAYER && Guid!=0 ) +#define IS_UNIT_GUID(Guid) ( IS_CREATURE_OR_PET_GUID(Guid) || IS_PLAYER_GUID(Guid) ) + // special case for empty guid need check +#define IS_ITEM_GUID(Guid) ( GUID_HIPART(Guid) == HIGHGUID_ITEM ) +#define IS_GAMEOBJECT_GUID(Guid) ( GUID_HIPART(Guid) == HIGHGUID_GAMEOBJECT ) +#define IS_DYNAMICOBJECT_GUID(Guid) ( GUID_HIPART(Guid) == HIGHGUID_DYNAMICOBJECT ) +#define IS_CORPSE_GUID(Guid) ( GUID_HIPART(Guid) == HIGHGUID_CORPSE ) +#define IS_TRANSPORT(Guid) ( GUID_HIPART(Guid) == HIGHGUID_TRANSPORT ) +#define IS_MO_TRANSPORT(Guid) ( GUID_HIPART(Guid) == HIGHGUID_MO_TRANSPORT ) + +// l - OBJECT_FIELD_GUID +// e - OBJECT_FIELD_ENTRY for GO (except GAMEOBJECT_TYPE_MO_TRANSPORT) and creatures or UNIT_FIELD_PETNUMBER for pets +// h - OBJECT_FIELD_GUID + 1 +#define MAKE_NEW_GUID(l, e, h) uint64( uint64(l) | ( uint64(e) << 24 ) | ( uint64(h) << 48 ) ) + +#define GUID_HIPART(x) (uint32)((uint64(x) >> 48) & 0x0000FFFF) + +// We have different low and middle part size for different guid types +#define _GUID_ENPART_2(x) 0 +#define _GUID_ENPART_3(x) (uint32)((uint64(x) >> 24) & 0x0000000000FFFFFFLL) +#define _GUID_LOPART_2(x) (uint32)(uint64(x) & 0x00000000FFFFFFFFLL) +#define _GUID_LOPART_3(x) (uint32)(uint64(x) & 0x0000000000FFFFFFLL) + +inline bool IsGuidHaveEnPart(uint64 const& guid) +{ + switch(GUID_HIPART(guid)) + { + case HIGHGUID_ITEM: + case HIGHGUID_PLAYER: + case HIGHGUID_DYNAMICOBJECT: + case HIGHGUID_CORPSE: + return false; + case HIGHGUID_GAMEOBJECT: + case HIGHGUID_TRANSPORT: + case HIGHGUID_UNIT: + case HIGHGUID_PET: + case HIGHGUID_MO_TRANSPORT: + default: + return true; + } +} + +#define GUID_ENPART(x) (IsGuidHaveEnPart(x) ? _GUID_ENPART_3(x) : _GUID_ENPART_2(x)) +#define GUID_LOPART(x) (IsGuidHaveEnPart(x) ? _GUID_LOPART_3(x) : _GUID_LOPART_2(x)) + +inline char const* GetLogNameForGuid(uint64 guid) +{ + switch(GUID_HIPART(guid)) + { + case HIGHGUID_ITEM: return "item"; + case HIGHGUID_PLAYER: return guid ? "player" : "none"; + case HIGHGUID_GAMEOBJECT: return "gameobject"; + case HIGHGUID_TRANSPORT: return "transport"; + case HIGHGUID_UNIT: return "creature"; + case HIGHGUID_PET: return "pet"; + case HIGHGUID_DYNAMICOBJECT:return "dynobject"; + case HIGHGUID_CORPSE: return "corpse"; + case HIGHGUID_MO_TRANSPORT: return "mo_transport"; + default: + return ""; + } +} +#endif diff --git a/src/game/ObjectGridLoader.cpp b/src/game/ObjectGridLoader.cpp new file mode 100644 index 00000000000..2ce17d4650f --- /dev/null +++ b/src/game/ObjectGridLoader.cpp @@ -0,0 +1,304 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ObjectGridLoader.h" +#include "ObjectAccessor.h" +#include "ObjectMgr.h" +#include "MapManager.h" +#include "Creature.h" +#include "GameObject.h" +#include "DynamicObject.h" +#include "Corpse.h" +#include "World.h" +#include "CellImpl.h" + +class MANGOS_DLL_DECL ObjectGridRespawnMover +{ + public: + ObjectGridRespawnMover() {} + + void Move(GridType &grid); + + template void Visit(GridRefManager &) {} + void Visit(CreatureMapType &m); +}; + +void +ObjectGridRespawnMover::Move(GridType &grid) +{ + TypeContainerVisitor mover(*this); + grid.Visit(mover); +} + +void +ObjectGridRespawnMover::Visit(CreatureMapType &m) +{ + // creature in unloading grid can have respawn point in another grid + // if it will be unloaded then it will not respawn in original grid until unload/load original grid + // move to respwn point to prevent this case. For player view in respawn grid this wll be normal respawn. + for(CreatureMapType::iterator iter=m.begin(), next; iter != m.end(); iter = next) + { + next = iter; ++next; + + Creature * c = iter->getSource(); + + assert(!c->isPet() && "ObjectGridRespawnMover don't must be called for pets"); + + Cell const& cur_cell = c->GetCurrentCell(); + + float resp_x, resp_y, resp_z; + c->GetRespawnCoord(resp_x, resp_y, resp_z); + CellPair resp_val = MaNGOS::ComputeCellPair(resp_x, resp_y); + Cell resp_cell(resp_val); + + if(cur_cell.DiffGrid(resp_cell)) + { + MapManager::Instance().GetMap(c->GetMapId(), c)->CreatureRespawnRelocation(c); + // false result ignored: will be unload with other creatures at grid + } + } +} + +// for loading world object at grid loading (Corpses) +class ObjectWorldLoader +{ + public: + explicit ObjectWorldLoader(ObjectGridLoader& gloader) + : i_cell(gloader.i_cell), i_grid(gloader.i_grid), i_map(gloader.i_map), i_corpses (0) + {} + + void Visit(CorpseMapType &m); + + template void Visit(GridRefManager&) { } + + private: + Cell i_cell; + NGridType &i_grid; + Map* i_map; + public: + uint32 i_corpses; +}; + +template void addUnitState(T* /*obj*/, CellPair const& /*cell_pair*/) +{ +} + +template<> void addUnitState(Creature *obj, CellPair const& cell_pair) +{ + Cell cell(cell_pair); + + obj->SetCurrentCell(cell); + if(obj->isSpiritService()) + obj->setDeathState(DEAD); +} + +template +void LoadHelper(CellGuidSet const& guid_set, CellPair &cell, GridRefManager &m, uint32 &count, Map* map) +{ + for(CellGuidSet::const_iterator i_guid = guid_set.begin(); i_guid != guid_set.end(); ++i_guid) + { + T* obj = new T; + uint32 guid = *i_guid; + //sLog.outString("DEBUG: LoadHelper from table: %s for (guid: %u) Loading",table,guid); + if(!obj->LoadFromDB(guid, map)) + { + delete obj; + continue; + } + + obj->GetGridRef().link(&m, obj); + + addUnitState(obj,cell); + obj->AddToWorld(); + ++count; + + } +} + +void LoadHelper(CellCorpseSet const& cell_corpses, CellPair &cell, CorpseMapType &m, uint32 &count, Map* map) +{ + if(cell_corpses.empty()) + return; + + for(CellCorpseSet::const_iterator itr = cell_corpses.begin(); itr != cell_corpses.end(); ++itr) + { + if(itr->second != map->GetInstanceId()) + continue; + + uint32 player_guid = itr->first; + + Corpse *obj = ObjectAccessor::Instance().GetCorpseForPlayerGUID(player_guid); + if(!obj) + continue; + + obj->GetGridRef().link(&m, obj); + + addUnitState(obj,cell); + obj->AddToWorld(); + ++count; + } +} + +void +ObjectGridLoader::Visit(GameObjectMapType &m) +{ + uint32 x = (i_cell.GridX()*MAX_NUMBER_OF_CELLS) + i_cell.CellX(); + uint32 y = (i_cell.GridY()*MAX_NUMBER_OF_CELLS) + i_cell.CellY(); + CellPair cell_pair(x,y); + uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; + + CellObjectGuids const& cell_guids = objmgr.GetCellObjectGuids(i_map->GetId(), i_map->GetSpawnMode(), cell_id); + + LoadHelper(cell_guids.gameobjects, cell_pair, m, i_gameObjects, i_map); +} + +void +ObjectGridLoader::Visit(CreatureMapType &m) +{ + uint32 x = (i_cell.GridX()*MAX_NUMBER_OF_CELLS) + i_cell.CellX(); + uint32 y = (i_cell.GridY()*MAX_NUMBER_OF_CELLS) + i_cell.CellY(); + CellPair cell_pair(x,y); + uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; + + CellObjectGuids const& cell_guids = objmgr.GetCellObjectGuids(i_map->GetId(), i_map->GetSpawnMode(), cell_id); + + LoadHelper(cell_guids.creatures, cell_pair, m, i_creatures, i_map); +} + +void +ObjectWorldLoader::Visit(CorpseMapType &m) +{ + uint32 x = (i_cell.GridX()*MAX_NUMBER_OF_CELLS) + i_cell.CellX(); + uint32 y = (i_cell.GridY()*MAX_NUMBER_OF_CELLS) + i_cell.CellY(); + CellPair cell_pair(x,y); + uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; + + // corpses are always added to spawn mode 0 and they are spawned by their instance id + CellObjectGuids const& cell_guids = objmgr.GetCellObjectGuids(i_map->GetId(), 0, cell_id); + LoadHelper(cell_guids.corpses, cell_pair, m, i_corpses, i_map); +} + +void +ObjectGridLoader::Load(GridType &grid) +{ + { + TypeContainerVisitor loader(*this); + grid.Visit(loader); + } + + { + ObjectWorldLoader wloader(*this); + TypeContainerVisitor loader(wloader); + grid.Visit(loader); + i_corpses = wloader.i_corpses; + } +} + +void ObjectGridLoader::LoadN(void) +{ + i_gameObjects = 0; i_creatures = 0; i_corpses = 0; + i_cell.data.Part.cell_y = 0; + for(unsigned int x=0; x < MAX_NUMBER_OF_CELLS; ++x) + { + i_cell.data.Part.cell_x = x; + for(unsigned int y=0; y < MAX_NUMBER_OF_CELLS; ++y) + { + i_cell.data.Part.cell_y = y; + GridLoader loader; + loader.Load(i_grid(x, y), *this); + } + } + sLog.outDebug("%u GameObjects, %u Creatures, and %u Corpses/Bones loaded for grid %u on map %u", i_gameObjects, i_creatures, i_corpses,i_grid.GetGridId(), i_map->GetId()); +} + +void ObjectGridUnloader::MoveToRespawnN() +{ + for(unsigned int x=0; x < MAX_NUMBER_OF_CELLS; ++x) + { + for(unsigned int y=0; y < MAX_NUMBER_OF_CELLS; ++y) + { + ObjectGridRespawnMover mover; + mover.Move(i_grid(x, y)); + } + } +} + +void +ObjectGridUnloader::Unload(GridType &grid) +{ + TypeContainerVisitor unloader(*this); + grid.Visit(unloader); +} + +template +void +ObjectGridUnloader::Visit(GridRefManager &m) +{ + while(!m.isEmpty()) + { + T *obj = m.getFirst()->getSource(); + // if option set then object already saved at this moment + if(!sWorld.getConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATLY)) + obj->SaveRespawnTime(); + ///- object must be out of world before delete + obj->RemoveFromWorld(); + ///- object will get delinked from the manager when deleted + delete obj; + } +} + +template<> +void +ObjectGridUnloader::Visit(CreatureMapType &m) +{ + // remove all cross-reference before deleting + for(CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + iter->getSource()->CleanupsBeforeDelete(); + + while(!m.isEmpty()) + { + Creature *obj = m.getFirst()->getSource(); + // if option set then object already saved at this moment + if(!sWorld.getConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATLY)) + obj->SaveRespawnTime(); + ///- object will get delinked from the manager when deleted + delete obj; + } +} + +void +ObjectGridStoper::Stop(GridType &grid) +{ + TypeContainerVisitor stoper(*this); + grid.Visit(stoper); +} + +void +ObjectGridStoper::Visit(CreatureMapType &m) +{ + // stop any fights at grid de-activation and remove dynobjects created at cast by creatures + for(CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + { + iter->getSource()->CombatStop(); + iter->getSource()->DeleteThreatList(); + iter->getSource()->RemoveAllDynObjects(); + } +} + +template void ObjectGridUnloader::Visit(GameObjectMapType &); +template void ObjectGridUnloader::Visit(DynamicObjectMapType &); diff --git a/src/game/ObjectGridLoader.h b/src/game/ObjectGridLoader.h new file mode 100644 index 00000000000..26cc3543b60 --- /dev/null +++ b/src/game/ObjectGridLoader.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_OBJECTGRIDLOADER_H +#define MANGOS_OBJECTGRIDLOADER_H + +#include "Utilities/TypeList.h" +#include "Platform/Define.h" +#include "GameSystem/GridLoader.h" +#include "GridDefines.h" +#include "Cell.h" + +class ObjectWorldLoader; + +class MANGOS_DLL_DECL ObjectGridLoader +{ + friend class ObjectWorldLoader; + + public: + ObjectGridLoader(NGridType &grid, Map* map, const Cell &cell) + : i_cell(cell), i_grid(grid), i_map(map), i_gameObjects(0), i_creatures(0), i_corpses (0) + {} + + void Load(GridType &grid); + void Visit(GameObjectMapType &m); + void Visit(CreatureMapType &m); + void Visit(CorpseMapType &) {} + + void Visit(DynamicObjectMapType&) { } + + void LoadN(void); + + private: + Cell i_cell; + NGridType &i_grid; + Map* i_map; + uint32 i_gameObjects; + uint32 i_creatures; + uint32 i_corpses; +}; + +class MANGOS_DLL_DECL ObjectGridUnloader +{ + public: + ObjectGridUnloader(NGridType &grid) : i_grid(grid) {} + + void MoveToRespawnN(); + void UnloadN() + { + for(unsigned int x=0; x < MAX_NUMBER_OF_CELLS; ++x) + { + for(unsigned int y=0; y < MAX_NUMBER_OF_CELLS; ++y) + { + GridLoader loader; + loader.Unload(i_grid(x, y), *this); + } + } + } + + void Unload(GridType &grid); + template void Visit(GridRefManager &m); + private: + NGridType &i_grid; +}; + +class MANGOS_DLL_DECL ObjectGridStoper +{ + public: + ObjectGridStoper(NGridType &grid) : i_grid(grid) {} + + void MoveToRespawnN(); + void StopN() + { + for(unsigned int x=0; x < MAX_NUMBER_OF_CELLS; ++x) + { + for(unsigned int y=0; y < MAX_NUMBER_OF_CELLS; ++y) + { + GridLoader loader; + loader.Stop(i_grid(x, y), *this); + } + } + } + + void Stop(GridType &grid); + void Visit(CreatureMapType &m); + + template void Visit(GridRefManager &) {} + private: + NGridType &i_grid; +}; + +typedef GridLoader GridLoaderType; +#endif diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp new file mode 100644 index 00000000000..982ae3c4bc4 --- /dev/null +++ b/src/game/ObjectMgr.cpp @@ -0,0 +1,6512 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "Database/SQLStorage.h" + +#include "Log.h" +#include "MapManager.h" +#include "ObjectMgr.h" +#include "SpellMgr.h" +#include "UpdateMask.h" +#include "World.h" +#include "WorldSession.h" +#include "Group.h" +#include "Guild.h" +#include "ArenaTeam.h" +#include "Transports.h" +#include "ProgressBar.h" +#include "Policies/SingletonImp.h" +#include "Language.h" +#include "GameEvent.h" +#include "Spell.h" +#include "Chat.h" +#include "InstanceSaveMgr.h" +#include "SpellAuras.h" +#include "Util.h" + +INSTANTIATE_SINGLETON_1(ObjectMgr); + +ScriptMapMap sQuestEndScripts; +ScriptMapMap sQuestStartScripts; +ScriptMapMap sSpellScripts; +ScriptMapMap sGameObjectScripts; +ScriptMapMap sEventScripts; + +bool normalizePlayerName(std::string& name) +{ + if(name.empty()) + return false; + + wchar_t wstr_buf[MAX_INTERNAL_PLAYER_NAME+1]; + size_t wstr_len = MAX_INTERNAL_PLAYER_NAME; + + if(!Utf8toWStr(name,&wstr_buf[0],wstr_len)) + return false; + + wstr_buf[0] = wcharToUpper(wstr_buf[0]); + for(size_t i = 1; i < wstr_len; ++i) + wstr_buf[i] = wcharToLower(wstr_buf[i]); + + if(!WStrToUtf8(wstr_buf,wstr_len,name)) + return false; + + return true; +} + +ObjectMgr::ObjectMgr() +{ + m_hiCharGuid = 1; + m_hiCreatureGuid = 1; + m_hiPetGuid = 1; + m_hiItemGuid = 1; + m_hiGoGuid = 1; + m_hiDoGuid = 1; + m_hiCorpseGuid = 1; + + m_hiPetNumber = 1; + + mGuildBankTabPrice.resize(GUILD_BANK_MAX_TABS); + mGuildBankTabPrice[0] = 100; + mGuildBankTabPrice[1] = 250; + mGuildBankTabPrice[2] = 500; + mGuildBankTabPrice[3] = 1000; + mGuildBankTabPrice[4] = 2500; + mGuildBankTabPrice[5] = 5000; + + // Only zero condition left, others will be added while loading DB tables + mConditions.resize(1); +} + +ObjectMgr::~ObjectMgr() +{ + for( QuestMap::iterator i = mQuestTemplates.begin( ); i != mQuestTemplates.end( ); ++ i ) + { + delete i->second; + } + mQuestTemplates.clear( ); + + for( GossipTextMap::iterator i = mGossipText.begin( ); i != mGossipText.end( ); ++ i ) + { + delete i->second; + } + mGossipText.clear( ); + + mAreaTriggers.clear(); + + for(PetLevelInfoMap::iterator i = petInfo.begin( ); i != petInfo.end( ); ++ i ) + { + delete[] i->second; + } + petInfo.clear(); + + // free only if loaded + for (int class_ = 0; class_ < MAX_CLASSES; ++class_) + delete[] playerClassInfo[class_].levelInfo; + + for (int race = 0; race < MAX_RACES; ++race) + for (int class_ = 0; class_ < MAX_CLASSES; ++class_) + delete[] playerInfo[race][class_].levelInfo; + + // free group and guild objects + for (GroupSet::iterator itr = mGroupSet.begin(); itr != mGroupSet.end(); ++itr) + delete (*itr); + for (GuildSet::iterator itr = mGuildSet.begin(); itr != mGuildSet.end(); ++itr) + delete (*itr); + + for(ItemMap::iterator itr = mAitems.begin(); itr != mAitems.end(); ++itr) + delete itr->second; +} + +Group * ObjectMgr::GetGroupByLeader(const uint64 &guid) const +{ + for(GroupSet::const_iterator itr = mGroupSet.begin(); itr != mGroupSet.end(); ++itr) + if ((*itr)->GetLeaderGUID() == guid) + return *itr; + + return NULL; +} + +Guild * ObjectMgr::GetGuildById(const uint32 GuildId) const +{ + for(GuildSet::const_iterator itr = mGuildSet.begin(); itr != mGuildSet.end(); itr++) + if ((*itr)->GetId() == GuildId) + return *itr; + + return NULL; +} + +Guild * ObjectMgr::GetGuildByName(std::string guildname) const +{ + for(GuildSet::const_iterator itr = mGuildSet.begin(); itr != mGuildSet.end(); itr++) + if ((*itr)->GetName() == guildname) + return *itr; + + return NULL; +} + +std::string ObjectMgr::GetGuildNameById(const uint32 GuildId) const +{ + for(GuildSet::const_iterator itr = mGuildSet.begin(); itr != mGuildSet.end(); itr++) + if ((*itr)->GetId() == GuildId) + return (*itr)->GetName(); + + return ""; +} + +Guild* ObjectMgr::GetGuildByLeader(const uint64 &guid) const +{ + for(GuildSet::const_iterator itr = mGuildSet.begin(); itr != mGuildSet.end(); ++itr) + if( (*itr)->GetLeader() == guid) + return *itr; + + return NULL; +} + +ArenaTeam* ObjectMgr::GetArenaTeamById(const uint32 ArenaTeamId) const +{ + for(ArenaTeamSet::const_iterator itr = mArenaTeamSet.begin(); itr != mArenaTeamSet.end(); itr++) + if ((*itr)->GetId() == ArenaTeamId) + return *itr; + + return NULL; +} + +ArenaTeam* ObjectMgr::GetArenaTeamByName(std::string arenateamname) const +{ + for(ArenaTeamSet::const_iterator itr = mArenaTeamSet.begin(); itr != mArenaTeamSet.end(); itr++) + if ((*itr)->GetName() == arenateamname) + return *itr; + + return NULL; +} + +ArenaTeam* ObjectMgr::GetArenaTeamByCapitan(uint64 const& guid) const +{ + for(ArenaTeamSet::const_iterator itr = mArenaTeamSet.begin(); itr != mArenaTeamSet.end(); itr++) + if ((*itr)->GetCaptain() == guid) + return *itr; + + return NULL; +} + +AuctionHouseObject * ObjectMgr::GetAuctionsMap( uint32 location ) +{ + switch ( location ) + { + case 6: //horde + return & mHordeAuctions; + break; + case 2: //alliance + return & mAllianceAuctions; + break; + default: //neutral + return & mNeutralAuctions; + } +} + +uint32 ObjectMgr::GetAuctionCut(uint32 location, uint32 highBid) +{ + if (location == 7 && !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION)) + return (uint32) (0.15f * highBid * sWorld.getRate(RATE_AUCTION_CUT)); + else + return (uint32) (0.05f * highBid * sWorld.getRate(RATE_AUCTION_CUT)); +} + +uint32 ObjectMgr::GetAuctionDeposit(uint32 location, uint32 time, Item *pItem) +{ + float percentance; // in 0..1 + if ( location == 7 && !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION)) + percentance = 0.75f; + else + percentance = 0.15f; + + percentance *= sWorld.getRate(RATE_AUCTION_DEPOSIT); + + return uint32( percentance * pItem->GetProto()->SellPrice * pItem->GetCount() * (time / MIN_AUCTION_TIME ) ); +} + +/// the sum of outbid is (1% from current bid)*5, if bid is very small, it is 1c +uint32 ObjectMgr::GetAuctionOutBid(uint32 currentBid) +{ + uint32 outbid = (currentBid / 100) * 5; + if (!outbid) + outbid = 1; + return outbid; +} + +//does not clear ram +void ObjectMgr::SendAuctionWonMail( AuctionEntry *auction ) +{ + Item *pItem = objmgr.GetAItem(auction->item_guidlow); + if(!pItem) + return; + + uint64 bidder_guid = MAKE_NEW_GUID(auction->bidder, 0, HIGHGUID_PLAYER); + Player *bidder = objmgr.GetPlayer(bidder_guid); + + uint32 bidder_accId = 0; + + // data for gm.log + if( sWorld.getConfig(CONFIG_GM_LOG_TRADE) ) + { + uint32 bidder_security = 0; + std::string bidder_name; + if (bidder) + { + bidder_accId = bidder->GetSession()->GetAccountId(); + bidder_security = bidder->GetSession()->GetSecurity(); + bidder_name = bidder->GetName(); + } + else + { + bidder_accId = GetPlayerAccountIdByGUID(bidder_guid); + bidder_security = GetSecurityByAccount(bidder_accId); + + if(bidder_security > SEC_PLAYER ) // not do redundant DB requests + { + if(!GetPlayerNameByGUID(bidder_guid,bidder_name)) + bidder_name = GetMangosStringForDBCLocale(LANG_UNKNOWN); + } + } + + if( bidder_security > SEC_PLAYER ) + { + std::string owner_name; + if(!GetPlayerNameByGUID(auction->owner,owner_name)) + owner_name = GetMangosStringForDBCLocale(LANG_UNKNOWN); + + uint32 owner_accid = GetPlayerAccountIdByGUID(auction->owner); + + sLog.outCommand("GM %s (Account: %u) won item in auction: %s (Entry: %u Count: %u) and pay money: %u. Original owner %s (Account: %u)", + bidder_name.c_str(),bidder_accId,pItem->GetProto()->Name1,pItem->GetEntry(),pItem->GetCount(),auction->bid,owner_name.c_str(),owner_accid); + } + } + else if(!bidder) + bidder_accId = GetPlayerAccountIdByGUID(bidder_guid); + + // receiver exist + if(bidder || bidder_accId) + { + std::ostringstream msgAuctionWonSubject; + msgAuctionWonSubject << auction->item_template << ":0:" << AUCTION_WON; + + std::ostringstream msgAuctionWonBody; + msgAuctionWonBody.width(16); + msgAuctionWonBody << std::right << std::hex << auction->owner; + msgAuctionWonBody << std::dec << ":" << auction->bid << ":" << auction->buyout; + sLog.outDebug( "AuctionWon body string : %s", msgAuctionWonBody.str().c_str() ); + + //prepare mail data... : + uint32 itemTextId = this->CreateItemText( msgAuctionWonBody.str() ); + + // set owner to bidder (to prevent delete item with sender char deleting) + // owner in `data` will set at mail receive and item extracting + CharacterDatabase.PExecute("UPDATE item_instance SET owner_guid = '%u' WHERE guid='%u'",auction->bidder,pItem->GetGUIDLow()); + CharacterDatabase.CommitTransaction(); + + MailItemsInfo mi; + mi.AddItem(auction->item_guidlow, auction->item_template, pItem); + + if (bidder) + bidder->GetSession()->SendAuctionBidderNotification( auction->location, auction->Id, bidder_guid, 0, 0, auction->item_template); + else + objmgr.RemoveAItem(pItem->GetGUIDLow()); // we have to remove the item, before we delete it !! + + // will delete item or place to receiver mail list + WorldSession::SendMailTo(bidder, MAIL_AUCTION, MAIL_STATIONERY_AUCTION, auction->location, auction->bidder, msgAuctionWonSubject.str(), itemTextId, &mi, 0, 0, MAIL_CHECK_MASK_AUCTION); + } + // receiver not exist + else + { + CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid='%u'", pItem->GetGUIDLow()); + objmgr.RemoveAItem(pItem->GetGUIDLow()); // we have to remove the item, before we delete it !! + delete pItem; + } +} + +void ObjectMgr::SendAuctionSalePendingMail( AuctionEntry * auction ) +{ + uint64 owner_guid = MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER); + Player *owner = objmgr.GetPlayer(owner_guid); + + // owner exist (online or offline) + if(owner || GetPlayerAccountIdByGUID(owner_guid)) + { + std::ostringstream msgAuctionSalePendingSubject; + msgAuctionSalePendingSubject << auction->item_template << ":0:" << AUCTION_SALE_PENDING; + + std::ostringstream msgAuctionSalePendingBody; + uint32 auctionCut = GetAuctionCut(auction->location, auction->bid); + + time_t distrTime = time(NULL) + HOUR; + + msgAuctionSalePendingBody.width(16); + msgAuctionSalePendingBody << std::right << std::hex << auction->bidder; + msgAuctionSalePendingBody << std::dec << ":" << auction->bid << ":" << auction->buyout; + msgAuctionSalePendingBody << ":" << auction->deposit << ":" << auctionCut << ":0:"; + msgAuctionSalePendingBody << secsToTimeBitFields(distrTime); + + sLog.outDebug("AuctionSalePending body string : %s", msgAuctionSalePendingBody.str().c_str()); + + uint32 itemTextId = this->CreateItemText( msgAuctionSalePendingBody.str() ); + + WorldSession::SendMailTo(owner, MAIL_AUCTION, MAIL_STATIONERY_AUCTION, auction->location, auction->owner, msgAuctionSalePendingSubject.str(), itemTextId, NULL, 0, 0, MAIL_CHECK_MASK_AUCTION); + } +} + +//call this method to send mail to auction owner, when auction is successful, it does not clear ram +void ObjectMgr::SendAuctionSuccessfulMail( AuctionEntry * auction ) +{ + uint64 owner_guid = MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER); + Player *owner = objmgr.GetPlayer(owner_guid); + + uint32 owner_accId = 0; + if(!owner) + owner_accId = GetPlayerAccountIdByGUID(owner_guid); + + // owner exist + if(owner || owner_accId) + { + std::ostringstream msgAuctionSuccessfulSubject; + msgAuctionSuccessfulSubject << auction->item_template << ":0:" << AUCTION_SUCCESSFUL; + + std::ostringstream auctionSuccessfulBody; + uint32 auctionCut = GetAuctionCut(auction->location, auction->bid); + + auctionSuccessfulBody.width(16); + auctionSuccessfulBody << std::right << std::hex << auction->bidder; + auctionSuccessfulBody << std::dec << ":" << auction->bid << ":" << auction->buyout; + auctionSuccessfulBody << ":" << auction->deposit << ":" << auctionCut; + + sLog.outDebug("AuctionSuccessful body string : %s", auctionSuccessfulBody.str().c_str()); + + uint32 itemTextId = this->CreateItemText( auctionSuccessfulBody.str() ); + + uint32 profit = auction->bid + auction->deposit - auctionCut; + + if (owner) + { + //send auction owner notification, bidder must be current! + owner->GetSession()->SendAuctionOwnerNotification( auction ); + } + + WorldSession::SendMailTo(owner, MAIL_AUCTION, MAIL_STATIONERY_AUCTION, auction->location, auction->owner, msgAuctionSuccessfulSubject.str(), itemTextId, NULL, profit, 0, MAIL_CHECK_MASK_AUCTION, HOUR); + } +} + +//does not clear ram +void ObjectMgr::SendAuctionExpiredMail( AuctionEntry * auction ) +{ //return an item in auction to its owner by mail + Item *pItem = objmgr.GetAItem(auction->item_guidlow); + if(!pItem) + { + sLog.outError("Auction item (GUID: %u) not found, and lost.",auction->item_guidlow); + return; + } + + uint64 owner_guid = MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER); + Player *owner = objmgr.GetPlayer(owner_guid); + + uint32 owner_accId = 0; + if(!owner) + owner_accId = GetPlayerAccountIdByGUID(owner_guid); + + // owner exist + if(owner || owner_accId) + { + std::ostringstream subject; + subject << auction->item_template << ":0:" << AUCTION_EXPIRED; + + if ( owner ) + owner->GetSession()->SendAuctionOwnerNotification( auction ); + else + objmgr.RemoveAItem(pItem->GetGUIDLow()); // we have to remove the item, before we delete it !! + + MailItemsInfo mi; + mi.AddItem(auction->item_guidlow, auction->item_template, pItem); + + // will delete item or place to receiver mail list + WorldSession::SendMailTo(owner, MAIL_AUCTION, MAIL_STATIONERY_AUCTION, auction->location, GUID_LOPART(owner_guid), subject.str(), 0, &mi, 0, 0, MAIL_CHECK_MASK_NONE); + + } + // owner not found + else + { + CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid='%u'",pItem->GetGUIDLow()); + objmgr.RemoveAItem(pItem->GetGUIDLow()); // we have to remove the item, before we delete it !! + delete pItem; + } +} + +CreatureInfo const* ObjectMgr::GetCreatureTemplate(uint32 id) +{ + return sCreatureStorage.LookupEntry(id); +} + +void ObjectMgr::LoadCreatureLocales() +{ + QueryResult *result = WorldDatabase.Query("SELECT entry,name_loc1,subname_loc1,name_loc2,subname_loc2,name_loc3,subname_loc3,name_loc4,subname_loc4,name_loc5,subname_loc5,name_loc6,subname_loc6,name_loc7,subname_loc7,name_loc8,subname_loc8 FROM locales_creature"); + + if(!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(""); + sLog.outString(">> Loaded 0 creature locale strings. DB table `locales_creature` is empty."); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 entry = fields[0].GetUInt32(); + + CreatureLocale& data = mCreatureLocaleMap[entry]; + + for(int i = 1; i < MAX_LOCALE; ++i) + { + std::string str = fields[1+2*(i-1)].GetCppString(); + if(!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if(idx >= 0) + { + if(data.Name.size() <= idx) + data.Name.resize(idx+1); + + data.Name[idx] = str; + } + } + str = fields[1+2*(i-1)+1].GetCppString(); + if(!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if(idx >= 0) + { + if(data.SubName.size() <= idx) + data.SubName.resize(idx+1); + + data.SubName[idx] = str; + } + } + } + } while (result->NextRow()); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u creature locale strings", mCreatureLocaleMap.size() ); +} + +void ObjectMgr::LoadCreatureTemplates() +{ + sCreatureStorage.Load(); + + sLog.outString( ">> Loaded %u creature definitions", sCreatureStorage.RecordCount ); + sLog.outString(); + + std::set heroicEntries; // already loaded heroic value in creatures + std::set hasHeroicEntries; // already loaded creatures with heroic entry values + + // check data correctness + for(uint32 i = 1; i < sCreatureStorage.MaxEntry; ++i) + { + CreatureInfo const* cInfo = sCreatureStorage.LookupEntry(i); + if(!cInfo) + continue; + + if(cInfo->HeroicEntry) + { + CreatureInfo const* heroicInfo = GetCreatureTemplate(cInfo->HeroicEntry); + if(!heroicInfo) + { + sLog.outErrorDb("Creature (Entry: %u) have `heroic_entry`=%u but creature entry %u not exist.",cInfo->HeroicEntry,cInfo->HeroicEntry); + continue; + } + + if(heroicEntries.find(i)!=heroicEntries.end()) + { + sLog.outErrorDb("Creature (Entry: %u) listed as heroic but have value in `heroic_entry`.",i); + continue; + } + + if(heroicEntries.find(cInfo->HeroicEntry)!=heroicEntries.end()) + { + sLog.outErrorDb("Creature (Entry: %u) already listed as heroic for another entry.",cInfo->HeroicEntry); + continue; + } + + if(hasHeroicEntries.find(cInfo->HeroicEntry)!=hasHeroicEntries.end()) + { + sLog.outErrorDb("Creature (Entry: %u) have `heroic_entry`=%u but creature entry %u have heroic entry also.",i,cInfo->HeroicEntry,cInfo->HeroicEntry); + continue; + } + + if(cInfo->npcflag != heroicInfo->npcflag) + { + sLog.outErrorDb("Creature (Entry: %u) listed in `creature_template_substitution` has different `npcflag` in heroic mode.",i); + continue; + } + + if(cInfo->classNum != heroicInfo->classNum) + { + sLog.outErrorDb("Creature (Entry: %u) listed in `creature_template_substitution` has different `classNum` in heroic mode.",i); + continue; + } + + if(cInfo->race != heroicInfo->race) + { + sLog.outErrorDb("Creature (Entry: %u) listed in `creature_template_substitution` has different `race` in heroic mode.",i); + continue; + } + + if(cInfo->trainer_type != heroicInfo->trainer_type) + { + sLog.outErrorDb("Creature (Entry: %u) listed in `creature_template_substitution` has different `trainer_type` in heroic mode.",i); + continue; + } + + if(cInfo->trainer_spell != heroicInfo->trainer_spell) + { + sLog.outErrorDb("Creature (Entry: %u) listed in `creature_template_substitution` has different `trainer_spell` in heroic mode.",i); + continue; + } + + hasHeroicEntries.insert(i); + heroicEntries.insert(cInfo->HeroicEntry); + } + + FactionTemplateEntry const* factionTemplate = sFactionTemplateStore.LookupEntry(cInfo->faction_A); + if(!factionTemplate) + sLog.outErrorDb("Creature (Entry: %u) has non-existing faction_A template (%u)", cInfo->Entry, cInfo->faction_A); + + factionTemplate = sFactionTemplateStore.LookupEntry(cInfo->faction_H); + if(!factionTemplate) + sLog.outErrorDb("Creature (Entry: %u) has non-existing faction_H template (%u)", cInfo->Entry, cInfo->faction_H); + + CreatureModelInfo const* minfo = sCreatureModelStorage.LookupEntry(cInfo->DisplayID_A); + if (!minfo) + sLog.outErrorDb("Creature (Entry: %u) has non-existing modelId_A (%u)", cInfo->Entry, cInfo->DisplayID_A); + minfo = sCreatureModelStorage.LookupEntry(cInfo->DisplayID_H); + if (!minfo) + sLog.outErrorDb("Creature (Entry: %u) has non-existing modelId_H (%u)", cInfo->Entry, cInfo->DisplayID_H); + + if(cInfo->dmgschool >= MAX_SPELL_SCHOOL) + { + sLog.outErrorDb("Creature (Entry: %u) has invalid spell school value (%u) in `dmgschool`",cInfo->Entry,cInfo->dmgschool); + const_cast(cInfo)->dmgschool = SPELL_SCHOOL_NORMAL; + } + + if(cInfo->baseattacktime == 0) + const_cast(cInfo)->baseattacktime = BASE_ATTACK_TIME; + + if(cInfo->rangeattacktime == 0) + const_cast(cInfo)->rangeattacktime = BASE_ATTACK_TIME; + + if((cInfo->npcflag & UNIT_NPC_FLAG_TRAINER) && cInfo->trainer_type >= MAX_TRAINER_TYPE) + sLog.outErrorDb("Creature (Entry: %u) has wrong trainer type %u",cInfo->Entry,cInfo->trainer_type); + + if(cInfo->InhabitType <= 0 || cInfo->InhabitType > INHABIT_ANYWHERE) + { + sLog.outErrorDb("Creature (Entry: %u) has wrong value (%u) in `InhabitType`, creature will not correctly walk/swim/fly",cInfo->Entry,cInfo->InhabitType); + const_cast(cInfo)->InhabitType = INHABIT_ANYWHERE; + } + + if(cInfo->PetSpellDataId) + { + CreatureSpellDataEntry const* spellDataId = sCreatureSpellDataStore.LookupEntry(cInfo->PetSpellDataId); + if(!spellDataId) + sLog.outErrorDb("Creature (Entry: %u) has non-existing PetSpellDataId (%u)", cInfo->Entry, cInfo->PetSpellDataId); + } + + if(cInfo->MovementType >= MAX_DB_MOTION_TYPE) + { + sLog.outErrorDb("Creature (Entry: %u) has wrong movement generator type (%u), ignore and set to IDLE.",cInfo->Entry,cInfo->MovementType); + const_cast(cInfo)->MovementType = IDLE_MOTION_TYPE; + } + + if(cInfo->equipmentId > 0) // 0 no equipment + { + if(!GetEquipmentInfo(cInfo->equipmentId)) + { + sLog.outErrorDb("Table `creature_template` have creature (Entry: %u) with equipment_id %u not found in table `creature_equip_template`, set to no equipment.", cInfo->Entry, cInfo->equipmentId); + const_cast(cInfo)->equipmentId = 0; + } + } + + /// if not set custom creature scale then load scale from CreatureDisplayInfo.dbc + if(cInfo->scale <= 0.0f) + { + CreatureDisplayInfoEntry const* ScaleEntry = sCreatureDisplayInfoStore.LookupEntry(cInfo->DisplayID_A); + const_cast(cInfo)->scale = ScaleEntry ? ScaleEntry->scale : 1.0f; + } + } +} + +void ObjectMgr::ConvertCreatureAddonAuras(CreatureDataAddon* addon, char const* table, char const* guidEntryStr) +{ + // Now add the auras, format "spellid effectindex spellid effectindex..." + char *p,*s; + std::vector val; + s=p=(char*)reinterpret_cast(addon->auras); + if(p) + { + while (p[0]!=0) + { + ++p; + if (p[0]==' ') + { + val.push_back(atoi(s)); + s=++p; + } + } + if (p!=s) + val.push_back(atoi(s)); + + // free char* loaded memory + delete[] (char*)reinterpret_cast(addon->auras); + + // wrong list + if (val.size()%2) + { + addon->auras = NULL; + sLog.outErrorDb("Creature (%s: %u) has wrong `auras` data in `%s`.",guidEntryStr,addon->guidOrEntry,table); + return; + } + } + + // empty list + if(val.empty()) + { + addon->auras = NULL; + return; + } + + // replace by new strucutres array + const_cast(addon->auras) = new CreatureDataAddonAura[val.size()/2+1]; + + int i=0; + for(int j=0;j(addon->auras[i]); + cAura.spell_id = (uint32)val[2*j+0]; + cAura.effect_idx = (uint32)val[2*j+1]; + if ( cAura.effect_idx > 2 ) + { + sLog.outErrorDb("Creature (%s: %u) has wrong effect %u for spell %u in `auras` field in `%s`.",guidEntryStr,addon->guidOrEntry,cAura.effect_idx,cAura.spell_id,table); + continue; + } + SpellEntry const *AdditionalSpellInfo = sSpellStore.LookupEntry(cAura.spell_id); + if (!AdditionalSpellInfo) + { + sLog.outErrorDb("Creature (%s: %u) has wrong spell %u defined in `auras` field in `%s`.",guidEntryStr,addon->guidOrEntry,cAura.spell_id,table); + continue; + } + + if (!AdditionalSpellInfo->Effect[cAura.effect_idx] || !AdditionalSpellInfo->EffectApplyAuraName[cAura.effect_idx]) + { + sLog.outErrorDb("Creature (%s: %u) has not aura effect %u of spell %u defined in `auras` field in `%s`.",guidEntryStr,addon->guidOrEntry,cAura.effect_idx,cAura.spell_id,table); + continue; + } + + ++i; + } + + // fill terminator element (after last added) + CreatureDataAddonAura& endAura = const_cast(addon->auras[i]); + endAura.spell_id = 0; + endAura.effect_idx = 0; +} + +void ObjectMgr::LoadCreatureAddons() +{ + sCreatureInfoAddonStorage.Load(); + + sLog.outString( ">> Loaded %u creature template addons", sCreatureInfoAddonStorage.RecordCount ); + sLog.outString(); + + // check data correctness and convert 'auras' + for(uint32 i = 1; i < sCreatureInfoAddonStorage.MaxEntry; ++i) + { + CreatureDataAddon const* addon = sCreatureInfoAddonStorage.LookupEntry(i); + if(!addon) + continue; + + ConvertCreatureAddonAuras(const_cast(addon), "creature_template_addon", "Entry"); + + if(!sCreatureStorage.LookupEntry(addon->guidOrEntry)) + sLog.outErrorDb("Creature (Entry: %u) does not exist but has a record in `creature_template_addon`",addon->guidOrEntry); + } + + sCreatureDataAddonStorage.Load(); + + sLog.outString( ">> Loaded %u creature addons", sCreatureDataAddonStorage.RecordCount ); + sLog.outString(); + + // check data correctness and convert 'auras' + for(uint32 i = 1; i < sCreatureDataAddonStorage.MaxEntry; ++i) + { + CreatureDataAddon const* addon = sCreatureDataAddonStorage.LookupEntry(i); + if(!addon) + continue; + + ConvertCreatureAddonAuras(const_cast(addon), "creature_addon", "GUIDLow"); + + if(mCreatureDataMap.find(addon->guidOrEntry)==mCreatureDataMap.end()) + sLog.outErrorDb("Creature (GUID: %u) does not exist but has a record in `creature_addon`",addon->guidOrEntry); + } +} + +EquipmentInfo const* ObjectMgr::GetEquipmentInfo(uint32 entry) +{ + return sEquipmentStorage.LookupEntry(entry); +} + +void ObjectMgr::LoadEquipmentTemplates() +{ + sEquipmentStorage.Load(); + + sLog.outString( ">> Loaded %u equipment template", sEquipmentStorage.RecordCount ); + sLog.outString(); +} + +CreatureModelInfo const* ObjectMgr::GetCreatureModelInfo(uint32 modelid) +{ + return sCreatureModelStorage.LookupEntry(modelid); +} + +uint32 ObjectMgr::ChooseDisplayId(uint32 team, const CreatureInfo *cinfo, const CreatureData *data) +{ + // Load creature model (display id) + uint32 display_id; + if (!data || data->displayid == 0) // use defaults from the template + { + // DisplayID_A is used if no team is given + if (team == HORDE) + display_id = (cinfo->DisplayID_H2 != 0 && urand(0,1) == 0) ? cinfo->DisplayID_H2 : cinfo->DisplayID_H; + else + display_id = (cinfo->DisplayID_A2 != 0 && urand(0,1) == 0) ? cinfo->DisplayID_A2 : cinfo->DisplayID_A; + } + else // overriden in creature data + display_id = data->displayid; + + return display_id; +} + +CreatureModelInfo const* ObjectMgr::GetCreatureModelRandomGender(uint32 display_id) +{ + CreatureModelInfo const *minfo = GetCreatureModelInfo(display_id); + if(!minfo) + return NULL; + + // If a model for another gender exists, 50% chance to use it + if(minfo->modelid_other_gender != 0 && urand(0,1) == 0) + { + CreatureModelInfo const *minfo_tmp = GetCreatureModelInfo(minfo->modelid_other_gender); + if(!minfo_tmp) + { + sLog.outErrorDb("Model (Entry: %u) has modelid_other_gender %u not found in table `creature_model_info`. ", minfo->modelid, minfo->modelid_other_gender); + return minfo; // not fatal, just use the previous one + } + else + return minfo_tmp; + } + else + return minfo; +} + +void ObjectMgr::LoadCreatureModelInfo() +{ + sCreatureModelStorage.Load(); + + sLog.outString( ">> Loaded %u creature model based info", sCreatureModelStorage.RecordCount ); + sLog.outString(); +} + +void ObjectMgr::LoadCreatures() +{ + uint32 count = 0; + // 0 1 2 3 + QueryResult *result = WorldDatabase.Query("SELECT creature.guid, id, map, modelid," + // 4 5 6 7 8 9 10 11 + "equipment_id, position_x, position_y, position_z, orientation, spawntimesecs, spawndist, currentwaypoint," + // 12 13 14 15 16 17 + "curhealth, curmana, DeathState, MovementType, spawnMask, event " + "FROM creature LEFT OUTER JOIN game_event_creature ON creature.guid = game_event_creature.guid"); + + if(!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(""); + sLog.outErrorDb(">> Loaded 0 creature. DB table `creature` is empty."); + return; + } + + // build single time for check creature data + std::set heroicCreatures; + for(uint32 i = 0; i < sCreatureStorage.MaxEntry; ++i) + if(CreatureInfo const* cInfo = sCreatureStorage.LookupEntry(i)) + if(cInfo->HeroicEntry) + heroicCreatures.insert(cInfo->HeroicEntry); + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 guid = fields[0].GetUInt32(); + + CreatureData& data = mCreatureDataMap[guid]; + + data.id = fields[ 1].GetUInt32(); + data.mapid = fields[ 2].GetUInt32(); + data.displayid = fields[ 3].GetUInt32(); + data.equipmentId = fields[ 4].GetUInt32(); + data.posX = fields[ 5].GetFloat(); + data.posY = fields[ 6].GetFloat(); + data.posZ = fields[ 7].GetFloat(); + data.orientation = fields[ 8].GetFloat(); + data.spawntimesecs = fields[ 9].GetUInt32(); + data.spawndist = fields[10].GetFloat(); + data.currentwaypoint= fields[11].GetUInt32(); + data.curhealth = fields[12].GetUInt32(); + data.curmana = fields[13].GetUInt32(); + data.is_dead = fields[14].GetBool(); + data.movementType = fields[15].GetUInt8(); + data.spawnMask = fields[16].GetUInt8(); + int16 gameEvent = fields[17].GetInt16(); + + CreatureInfo const* cInfo = GetCreatureTemplate(data.id); + if(!cInfo) + { + sLog.outErrorDb("Table `creature` have creature (GUID: %u) with not existed creature entry %u, skipped.",guid,data.id ); + continue; + } + + if(heroicCreatures.find(data.id)!=heroicCreatures.end()) + { + sLog.outErrorDb("Table `creature` have creature (GUID: %u) that listed as heroic template in `creature_template_substitution`, skipped.",guid,data.id ); + continue; + } + + if(data.equipmentId > 0) // -1 no equipment, 0 use default + { + if(!GetEquipmentInfo(data.equipmentId)) + { + sLog.outErrorDb("Table `creature` have creature (Entry: %u) with equipment_id %u not found in table `creature_equip_template`, set to no equipment.", data.id, data.equipmentId); + data.equipmentId = -1; + } + } + + if(cInfo->RegenHealth && data.curhealth < cInfo->minhealth) + { + sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `creature_template`.`RegenHealth`=1 and low current health (%u), `creature_template`.`minhealth`=%u.",guid,data.id,data.curhealth, cInfo->minhealth ); + data.curhealth = cInfo->minhealth; + } + + if(data.curmana < cInfo->minmana) + { + sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with low current mana (%u), `creature_template`.`minmana`=%u.",guid,data.id,data.curmana, cInfo->minmana ); + data.curmana = cInfo->minmana; + } + + if(data.spawndist < 0.0f) + { + sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `spawndist`< 0, set to 0.",guid,data.id ); + data.spawndist = 0.0f; + } + else if(data.movementType == RANDOM_MOTION_TYPE) + { + if(data.spawndist == 0.0f) + { + sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `MovementType`=1 (random movement) but with `spawndist`=0, replace by idle movement type (0).",guid,data.id ); + data.movementType = IDLE_MOTION_TYPE; + } + } + else if(data.movementType == IDLE_MOTION_TYPE) + { + if(data.spawndist != 0.0f) + { + sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `MovementType`=0 (idle) have `spawndist`<>0, set to 0.",guid,data.id ); + data.spawndist = 0.0f; + } + } + + if (gameEvent==0) // if not this is to be managed by GameEvent System + AddCreatureToGrid(guid, &data); + ++count; + + } while (result->NextRow()); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u creatures", mCreatureDataMap.size() ); +} + +void ObjectMgr::AddCreatureToGrid(uint32 guid, CreatureData const* data) +{ + uint8 mask = data->spawnMask; + for(uint8 i = 0; mask != 0; i++, mask >>= 1) + { + if(mask & 1) + { + CellPair cell_pair = MaNGOS::ComputeCellPair(data->posX, data->posY); + uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; + + CellObjectGuids& cell_guids = mMapObjectGuids[MAKE_PAIR32(data->mapid,i)][cell_id]; + cell_guids.creatures.insert(guid); + } + } +} + +void ObjectMgr::RemoveCreatureFromGrid(uint32 guid, CreatureData const* data) +{ + uint8 mask = data->spawnMask; + for(uint8 i = 0; mask != 0; i++, mask >>= 1) + { + if(mask & 1) + { + CellPair cell_pair = MaNGOS::ComputeCellPair(data->posX, data->posY); + uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; + + CellObjectGuids& cell_guids = mMapObjectGuids[MAKE_PAIR32(data->mapid,i)][cell_id]; + cell_guids.creatures.erase(guid); + } + } +} + +void ObjectMgr::LoadGameobjects() +{ + uint32 count = 0; + + // 0 1 2 3 4 5 6 + QueryResult *result = WorldDatabase.Query("SELECT gameobject.guid, id, map, position_x, position_y, position_z, orientation," + // 7 8 9 10 11 12 13 14 15 + "rotation0, rotation1, rotation2, rotation3, spawntimesecs, animprogress, state, spawnMask, event " + "FROM gameobject LEFT OUTER JOIN game_event_gameobject ON gameobject.guid = game_event_gameobject.guid"); + + if(!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outErrorDb(">> Loaded 0 gameobjects. DB table `gameobject` is empty."); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 guid = fields[0].GetUInt32(); + + GameObjectData& data = mGameObjectDataMap[guid]; + + data.id = fields[ 1].GetUInt32(); + data.mapid = fields[ 2].GetUInt32(); + data.posX = fields[ 3].GetFloat(); + data.posY = fields[ 4].GetFloat(); + data.posZ = fields[ 5].GetFloat(); + data.orientation = fields[ 6].GetFloat(); + data.rotation0 = fields[ 7].GetFloat(); + data.rotation1 = fields[ 8].GetFloat(); + data.rotation2 = fields[ 9].GetFloat(); + data.rotation3 = fields[10].GetFloat(); + data.spawntimesecs = fields[11].GetInt32(); + data.animprogress = fields[12].GetUInt32(); + data.go_state = fields[13].GetUInt32(); + data.spawnMask = fields[14].GetUInt8(); + int16 gameEvent = fields[15].GetInt16(); + + GameObjectInfo const* gInfo = GetGameObjectInfo(data.id); + if(!gInfo) + { + sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u) with not existed gameobject entry %u, skipped.",guid,data.id ); + continue; + } + + if (gameEvent==0) // if not this is to be managed by GameEvent System + AddGameobjectToGrid(guid, &data); + ++count; + + } while (result->NextRow()); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u gameobjects", mGameObjectDataMap.size()); +} + +void ObjectMgr::AddGameobjectToGrid(uint32 guid, GameObjectData const* data) +{ + uint8 mask = data->spawnMask; + for(uint8 i = 0; mask != 0; i++, mask >>= 1) + { + if(mask & 1) + { + CellPair cell_pair = MaNGOS::ComputeCellPair(data->posX, data->posY); + uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; + + CellObjectGuids& cell_guids = mMapObjectGuids[MAKE_PAIR32(data->mapid,i)][cell_id]; + cell_guids.gameobjects.insert(guid); + } + } +} + +void ObjectMgr::RemoveGameobjectFromGrid(uint32 guid, GameObjectData const* data) +{ + uint8 mask = data->spawnMask; + for(uint8 i = 0; mask != 0; i++, mask >>= 1) + { + if(mask & 1) + { + CellPair cell_pair = MaNGOS::ComputeCellPair(data->posX, data->posY); + uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; + + CellObjectGuids& cell_guids = mMapObjectGuids[MAKE_PAIR32(data->mapid,i)][cell_id]; + cell_guids.gameobjects.erase(guid); + } + } +} + +void ObjectMgr::LoadCreatureRespawnTimes() +{ + // remove outdated data + WorldDatabase.DirectExecute("DELETE FROM creature_respawn WHERE respawntime <= UNIX_TIMESTAMP(NOW())"); + + uint32 count = 0; + + QueryResult *result = WorldDatabase.Query("SELECT guid,respawntime,instance FROM creature_respawn"); + + if(!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outString(">> Loaded 0 creature respawn time."); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 loguid = fields[0].GetUInt32(); + uint64 respawn_time = fields[1].GetUInt64(); + uint32 instance = fields[2].GetUInt32(); + + mCreatureRespawnTimes[MAKE_PAIR64(loguid,instance)] = time_t(respawn_time); + + ++count; + } while (result->NextRow()); + + delete result; + + sLog.outString( ">> Loaded %u creature respawn times", mCreatureRespawnTimes.size() ); + sLog.outString(); +} + +void ObjectMgr::LoadGameobjectRespawnTimes() +{ + // remove outdated data + WorldDatabase.DirectExecute("DELETE FROM gameobject_respawn WHERE respawntime <= UNIX_TIMESTAMP(NOW())"); + + uint32 count = 0; + + QueryResult *result = WorldDatabase.Query("SELECT guid,respawntime,instance FROM gameobject_respawn"); + + if(!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outString(">> Loaded 0 gameobject respawn time."); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 loguid = fields[0].GetUInt32(); + uint64 respawn_time = fields[1].GetUInt64(); + uint32 instance = fields[2].GetUInt32(); + + mGORespawnTimes[MAKE_PAIR64(loguid,instance)] = time_t(respawn_time); + + ++count; + } while (result->NextRow()); + + delete result; + + sLog.outString( ">> Loaded %u gameobject respawn times", mGORespawnTimes.size() ); + sLog.outString(); +} + +// name must be checked to correctness (if received) before call this function +uint64 ObjectMgr::GetPlayerGUIDByName(std::string name) const +{ + uint64 guid = 0; + + CharacterDatabase.escape_string(name); + + // Player name safe to sending to DB (checked at login) and this function using + QueryResult *result = CharacterDatabase.PQuery("SELECT guid FROM characters WHERE name = '%s'", name.c_str()); + if(result) + { + guid = MAKE_NEW_GUID((*result)[0].GetUInt32(), 0, HIGHGUID_PLAYER); + + delete result; + } + + return guid; +} + +bool ObjectMgr::GetPlayerNameByGUID(const uint64 &guid, std::string &name) const +{ + // prevent DB access for online player + if(Player* player = GetPlayer(guid)) + { + name = player->GetName(); + return true; + } + + QueryResult *result = CharacterDatabase.PQuery("SELECT name FROM characters WHERE guid = '%u'", GUID_LOPART(guid)); + + if(result) + { + name = (*result)[0].GetCppString(); + delete result; + return true; + } + + return false; +} + +uint32 ObjectMgr::GetPlayerTeamByGUID(const uint64 &guid) const +{ + QueryResult *result = CharacterDatabase.PQuery("SELECT race FROM characters WHERE guid = '%u'", GUID_LOPART(guid)); + + if(result) + { + uint8 race = (*result)[0].GetUInt8(); + delete result; + return Player::TeamForRace(race); + } + + return 0; +} + +uint32 ObjectMgr::GetPlayerAccountIdByGUID(const uint64 &guid) const +{ + QueryResult *result = CharacterDatabase.PQuery("SELECT account FROM characters WHERE guid = '%u'", GUID_LOPART(guid)); + if(result) + { + uint32 acc = (*result)[0].GetUInt32(); + delete result; + return acc; + } + + return 0; +} + +uint32 ObjectMgr::GetSecurityByAccount(uint32 acc_id) const +{ + QueryResult *result = loginDatabase.PQuery("SELECT gmlevel FROM account WHERE id = '%u'", acc_id); + if(result) + { + uint32 sec = (*result)[0].GetUInt32(); + delete result; + return sec; + } + + return 0; +} + +bool ObjectMgr::GetAccountNameByAccount(uint32 acc_id, std::string &name) const +{ + QueryResult *result = loginDatabase.PQuery("SELECT username FROM account WHERE id = '%u'", acc_id); + if(result) + { + name = (*result)[0].GetCppString(); + delete result; + return true; + } + + return false; +} + +uint32 ObjectMgr::GetAccountByAccountName(std::string name) const +{ + loginDatabase.escape_string(name); + QueryResult *result = loginDatabase.PQuery("SELECT id FROM account WHERE username = '%s'", name.c_str()); + if(result) + { + uint32 id = (*result)[0].GetUInt32(); + delete result; + return id; + } + + return 0; +} + +void ObjectMgr::LoadAuctions() +{ + QueryResult *result = CharacterDatabase.Query("SELECT COUNT(*) FROM auctionhouse"); + if( !result ) + return; + + Field *fields = result->Fetch(); + uint32 AuctionCount=fields[0].GetUInt32(); + delete result; + + if(!AuctionCount) + return; + + result = CharacterDatabase.Query( "SELECT id,auctioneerguid,itemguid,item_template,itemowner,buyoutprice,time,buyguid,lastbid,startbid,deposit,location FROM auctionhouse" ); + if( !result ) + return; + + barGoLink bar( AuctionCount ); + + AuctionEntry *aItem; + + do + { + fields = result->Fetch(); + + bar.step(); + + aItem = new AuctionEntry; + aItem->Id = fields[0].GetUInt32(); + aItem->auctioneer = fields[1].GetUInt32(); + aItem->item_guidlow = fields[2].GetUInt32(); + aItem->item_template = fields[3].GetUInt32(); + aItem->owner = fields[4].GetUInt32(); + aItem->buyout = fields[5].GetUInt32(); + aItem->time = fields[6].GetUInt32(); + aItem->bidder = fields[7].GetUInt32(); + aItem->bid = fields[8].GetUInt32(); + aItem->startbid = fields[9].GetUInt32(); + aItem->deposit = fields[10].GetUInt32(); + aItem->location = fields[11].GetUInt8(); + //check if sold item exists + if ( this->GetAItem( aItem->item_guidlow ) ) + { + GetAuctionsMap( aItem->location )->AddAuction(aItem); + } + else + { + CharacterDatabase.PExecute("DELETE FROM auctionhouse WHERE id = '%u'",aItem->Id); + sLog.outError("Auction %u has not a existing item : %u", aItem->Id, aItem->item_guidlow); + delete aItem; + } + } while (result->NextRow()); + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u auctions", AuctionCount ); + sLog.outString(); +} + +void ObjectMgr::LoadItemLocales() +{ + QueryResult *result = WorldDatabase.Query("SELECT entry,name_loc1,description_loc1,name_loc2,description_loc2,name_loc3,description_loc3,name_loc4,description_loc4,name_loc5,description_loc5,name_loc6,description_loc6,name_loc7,description_loc7,name_loc8,description_loc8 FROM locales_item"); + + if(!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(""); + sLog.outString(">> Loaded 0 Item locale strings. DB table `locales_item` is empty."); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 entry = fields[0].GetUInt32(); + + ItemLocale& data = mItemLocaleMap[entry]; + + for(int i = 1; i < MAX_LOCALE; ++i) + { + std::string str = fields[1+2*(i-1)].GetCppString(); + if(!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if(idx >= 0) + { + if(data.Name.size() <= idx) + data.Name.resize(idx+1); + + data.Name[idx] = str; + } + } + + str = fields[1+2*(i-1)+1].GetCppString(); + if(!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if(idx >= 0) + { + if(data.Description.size() <= idx) + data.Description.resize(idx+1); + + data.Description[idx] = str; + } + } + } + } while (result->NextRow()); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u Item locale strings", mItemLocaleMap.size() ); +} + +void ObjectMgr::LoadItemPrototypes() +{ + sItemStorage.Load (); + sLog.outString( ">> Loaded %u item prototypes", sItemStorage.RecordCount ); + sLog.outString(); + + // check data correctness + for(uint32 i = 1; i < sItemStorage.MaxEntry; ++i) + { + ItemPrototype const* proto = sItemStorage.LookupEntry(i); + ItemEntry const *dbcitem = sItemStore.LookupEntry(i); + if(!proto) + { + /* to many errors, and possible not all items really used in game + if (dbcitem) + sLog.outErrorDb("Item (Entry: %u) doesn't exists in DB, but must exist.",i); + */ + continue; + } + + if(dbcitem) + { + if(proto->InventoryType != dbcitem->InventoryType) + { + sLog.outErrorDb("Item (Entry: %u) not correct %u inventory type, must be %u (still using DB value).",i,proto->InventoryType,dbcitem->InventoryType); + // It safe let use InventoryType from DB + } + + if(proto->DisplayInfoID != dbcitem->DisplayId) + { + sLog.outErrorDb("Item (Entry: %u) not correct %u display id, must be %u (using it).",i,proto->DisplayInfoID,dbcitem->DisplayId); + const_cast(proto)->DisplayInfoID = dbcitem->DisplayId; + } + if(proto->Sheath != dbcitem->Sheath) + { + sLog.outErrorDb("Item (Entry: %u) not correct %u sheath, must be %u (using it).",i,proto->Sheath,dbcitem->Sheath); + const_cast(proto)->Sheath = dbcitem->Sheath; + } + } + else + { + sLog.outErrorDb("Item (Entry: %u) not correct (not listed in list of existed items).",i); + } + + if(proto->Class >= MAX_ITEM_CLASS) + { + sLog.outErrorDb("Item (Entry: %u) has wrong Class value (%u)",i,proto->Class); + const_cast(proto)->Class = ITEM_CLASS_JUNK; + } + + if(proto->SubClass >= MaxItemSubclassValues[proto->Class]) + { + sLog.outErrorDb("Item (Entry: %u) has wrong Subclass value (%u) for class %u",i,proto->SubClass,proto->Class); + const_cast(proto)->SubClass = 0;// exist for all item classes + } + + if(proto->Quality >= MAX_ITEM_QUALITY) + { + sLog.outErrorDb("Item (Entry: %u) has wrong Quality value (%u)",i,proto->Quality); + const_cast(proto)->Quality = ITEM_QUALITY_NORMAL; + } + + if(proto->BuyCount <= 0) + { + sLog.outErrorDb("Item (Entry: %u) has wrong BuyCount value (%u), set to default(1).",i,proto->BuyCount); + const_cast(proto)->BuyCount = 1; + } + + if(proto->InventoryType >= MAX_INVTYPE) + { + sLog.outErrorDb("Item (Entry: %u) has wrong InventoryType value (%u)",i,proto->InventoryType); + const_cast(proto)->InventoryType = INVTYPE_NON_EQUIP; + } + + if(proto->RequiredSkill >= MAX_SKILL_TYPE) + { + sLog.outErrorDb("Item (Entry: %u) has wrong RequiredSkill value (%u)",i,proto->RequiredSkill); + const_cast(proto)->RequiredSkill = 0; + } + + if(!(proto->AllowableClass & CLASSMASK_ALL_PLAYABLE)) + { + sLog.outErrorDb("Item (Entry: %u) not have in `AllowableClass` any playable classes (%u) and can't be equipped.",i,proto->AllowableClass); + } + + if(!(proto->AllowableRace & RACEMASK_ALL_PLAYABLE)) + { + sLog.outErrorDb("Item (Entry: %u) not have in `AllowableRace` any playable races (%u) and can't be equipped.",i,proto->AllowableRace); + } + + if(proto->RequiredSpell && !sSpellStore.LookupEntry(proto->RequiredSpell)) + { + sLog.outErrorDb("Item (Entry: %u) have wrong (non-existed) spell in RequiredSpell (%u)",i,proto->RequiredSpell); + const_cast(proto)->RequiredSpell = 0; + } + + if(proto->RequiredReputationRank >= MAX_REPUTATION_RANK) + sLog.outErrorDb("Item (Entry: %u) has wrong reputation rank in RequiredReputationRank (%u), item can't be used.",i,proto->RequiredReputationRank); + + if(proto->RequiredReputationFaction) + { + if(!sFactionStore.LookupEntry(proto->RequiredReputationFaction)) + { + sLog.outErrorDb("Item (Entry: %u) has wrong (not existing) faction in RequiredReputationFaction (%u)",i,proto->RequiredReputationFaction); + const_cast(proto)->RequiredReputationFaction = 0; + } + + if(proto->RequiredReputationRank == MIN_REPUTATION_RANK) + sLog.outErrorDb("Item (Entry: %u) has min. reputation rank in RequiredReputationRank (0) but RequiredReputationFaction > 0, faction setting is useless.",i); + } + else if(proto->RequiredReputationRank > MIN_REPUTATION_RANK) + sLog.outErrorDb("Item (Entry: %u) has RequiredReputationFaction ==0 but RequiredReputationRank > 0, rank setting is useless.",i); + + if(proto->Stackable==0) + { + sLog.outErrorDb("Item (Entry: %u) has wrong value in stackable (%u), replace by default 1.",i,proto->Stackable); + const_cast(proto)->Stackable = 1; + } + else if(proto->Stackable > 255) + { + sLog.outErrorDb("Item (Entry: %u) has too large value in stackable (%u), replace by hardcoded upper limit (255).",i,proto->Stackable); + const_cast(proto)->Stackable = 255; + } + + for (int j = 0; j < 10; j++) + { + // for ItemStatValue != 0 + if(proto->ItemStat[j].ItemStatValue && proto->ItemStat[j].ItemStatType >= MAX_ITEM_MOD) + { + sLog.outErrorDb("Item (Entry: %u) has wrong stat_type%d (%u)",i,j+1,proto->ItemStat[j].ItemStatType); + const_cast(proto)->ItemStat[j].ItemStatType = 0; + } + } + + for (int j = 0; j < 5; j++) + { + if(proto->Damage[j].DamageType >= MAX_SPELL_SCHOOL) + { + sLog.outErrorDb("Item (Entry: %u) has wrong dmg_type%d (%u)",i,j+1,proto->Damage[j].DamageType); + const_cast(proto)->Damage[j].DamageType = 0; + } + } + + // special format + if(proto->Spells[0].SpellId == SPELL_ID_GENERIC_LEARN) + { + // spell_1 + if(proto->Spells[0].SpellTrigger != ITEM_SPELLTRIGGER_ON_USE) + { + sLog.outErrorDb("Item (Entry: %u) has wrong item spell trigger value in spelltrigger_%d (%u) for special learning format",i,0+1,proto->Spells[0].SpellTrigger); + const_cast(proto)->Spells[0].SpellId = 0; + const_cast(proto)->Spells[0].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE; + const_cast(proto)->Spells[1].SpellId = 0; + const_cast(proto)->Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE; + } + + // spell_2 have learning spell + if(proto->Spells[1].SpellTrigger != ITEM_SPELLTRIGGER_LEARN_SPELL_ID) + { + sLog.outErrorDb("Item (Entry: %u) has wrong item spell trigger value in spelltrigger_%d (%u) for special learning format.",i,1+1,proto->Spells[1].SpellTrigger); + const_cast(proto)->Spells[0].SpellId = 0; + const_cast(proto)->Spells[1].SpellId = 0; + const_cast(proto)->Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE; + } + else if(!proto->Spells[1].SpellId) + { + sLog.outErrorDb("Item (Entry: %u) not has expected spell in spellid_%d in special learning format.",i,1+1); + const_cast(proto)->Spells[0].SpellId = 0; + const_cast(proto)->Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE; + } + else + { + SpellEntry const* spellInfo = sSpellStore.LookupEntry(proto->Spells[1].SpellId); + if(!spellInfo) + { + sLog.outErrorDb("Item (Entry: %u) has wrong (not existing) spell in spellid_%d (%u)",i,1+1,proto->Spells[1].SpellId); + const_cast(proto)->Spells[0].SpellId = 0; + const_cast(proto)->Spells[1].SpellId = 0; + const_cast(proto)->Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE; + } + // allowed only in special format + else if(proto->Spells[1].SpellId==SPELL_ID_GENERIC_LEARN) + { + sLog.outErrorDb("Item (Entry: %u) has broken spell in spellid_%d (%u)",i,1+1,proto->Spells[1].SpellId); + const_cast(proto)->Spells[0].SpellId = 0; + const_cast(proto)->Spells[1].SpellId = 0; + const_cast(proto)->Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE; + } + } + + // spell_3*,spell_4*,spell_5* is empty + for (int j = 2; j < 5; j++) + { + if(proto->Spells[j].SpellTrigger != ITEM_SPELLTRIGGER_ON_USE) + { + sLog.outErrorDb("Item (Entry: %u) has wrong item spell trigger value in spelltrigger_%d (%u)",i,j+1,proto->Spells[j].SpellTrigger); + const_cast(proto)->Spells[j].SpellId = 0; + const_cast(proto)->Spells[j].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE; + } + else if(proto->Spells[j].SpellId != 0) + { + sLog.outErrorDb("Item (Entry: %u) has wrong spell in spellid_%d (%u) for learning special format",i,j+1,proto->Spells[j].SpellId); + const_cast(proto)->Spells[j].SpellId = 0; + } + } + } + // normal spell list + else + { + for (int j = 0; j < 5; j++) + { + if(proto->Spells[j].SpellTrigger >= MAX_ITEM_SPELLTRIGGER || proto->Spells[j].SpellTrigger == ITEM_SPELLTRIGGER_LEARN_SPELL_ID) + { + sLog.outErrorDb("Item (Entry: %u) has wrong item spell trigger value in spelltrigger_%d (%u)",i,j+1,proto->Spells[j].SpellTrigger); + const_cast(proto)->Spells[j].SpellId = 0; + const_cast(proto)->Spells[j].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE; + } + + if(proto->Spells[j].SpellId) + { + SpellEntry const* spellInfo = sSpellStore.LookupEntry(proto->Spells[j].SpellId); + if(!spellInfo) + { + sLog.outErrorDb("Item (Entry: %u) has wrong (not existing) spell in spellid_%d (%u)",i,j+1,proto->Spells[j].SpellId); + const_cast(proto)->Spells[j].SpellId = 0; + } + // allowed only in special format + else if(proto->Spells[j].SpellId==SPELL_ID_GENERIC_LEARN) + { + sLog.outErrorDb("Item (Entry: %u) has broken spell in spellid_%d (%u)",i,j+1,proto->Spells[j].SpellId); + const_cast(proto)->Spells[j].SpellId = 0; + } + } + } + } + + if(proto->Bonding >= MAX_BIND_TYPE) + sLog.outErrorDb("Item (Entry: %u) has wrong Bonding value (%u)",i,proto->Bonding); + + if(proto->PageText && !sPageTextStore.LookupEntry(proto->PageText)) + sLog.outErrorDb("Item (Entry: %u) has non existing first page (Id:%u)", i,proto->PageText); + + if(proto->LockID && !sLockStore.LookupEntry(proto->LockID)) + sLog.outErrorDb("Item (Entry: %u) has wrong LockID (%u)",i,proto->LockID); + + if(proto->Sheath >= MAX_SHEATHETYPE) + { + sLog.outErrorDb("Item (Entry: %u) has wrong Sheath (%u)",i,proto->Sheath); + const_cast(proto)->Sheath = SHEATHETYPE_NONE; + } + + if(proto->RandomProperty && !sItemRandomPropertiesStore.LookupEntry(GetItemEnchantMod(proto->RandomProperty))) + { + sLog.outErrorDb("Item (Entry: %u) has unknown (wrong or not listed in `item_enchantment_template`) RandomProperty (%u)",i,proto->RandomProperty); + const_cast(proto)->RandomProperty = 0; + } + + if(proto->RandomSuffix && !sItemRandomSuffixStore.LookupEntry(GetItemEnchantMod(proto->RandomSuffix))) + { + sLog.outErrorDb("Item (Entry: %u) has wrong RandomSuffix (%u)",i,proto->RandomSuffix); + const_cast(proto)->RandomSuffix = 0; + } + + if(proto->ItemSet && !sItemSetStore.LookupEntry(proto->ItemSet)) + { + sLog.outErrorDb("Item (Entry: %u) have wrong ItemSet (%u)",i,proto->ItemSet); + const_cast(proto)->ItemSet = 0; + } + + if(proto->Area && !GetAreaEntryByAreaID(proto->Area)) + sLog.outErrorDb("Item (Entry: %u) has wrong Area (%u)",i,proto->Area); + + if(proto->Map && !sMapStore.LookupEntry(proto->Map)) + sLog.outErrorDb("Item (Entry: %u) has wrong Map (%u)",i,proto->Map); + + if(proto->TotemCategory && !sTotemCategoryStore.LookupEntry(proto->TotemCategory)) + sLog.outErrorDb("Item (Entry: %u) has wrong TotemCategory (%u)",i,proto->TotemCategory); + + for (int j = 0; j < 3; j++) + { + if(proto->Socket[j].Color && (proto->Socket[j].Color & SOCKET_COLOR_ALL) != proto->Socket[j].Color) + { + sLog.outErrorDb("Item (Entry: %u) has wrong socketColor_%d (%u)",i,j+1,proto->Socket[j].Color); + const_cast(proto)->Socket[j].Color = 0; + } + } + + if(proto->GemProperties && !sGemPropertiesStore.LookupEntry(proto->GemProperties)) + sLog.outErrorDb("Item (Entry: %u) has wrong GemProperties (%u)",i,proto->GemProperties); + + if(proto->FoodType >= MAX_PET_DIET) + { + sLog.outErrorDb("Item (Entry: %u) has wrong FoodType value (%u)",i,proto->FoodType); + const_cast(proto)->FoodType = 0; + } + } + + // this DBC used currently only for check item templates in DB. + sItemStore.Clear(); +} + +void ObjectMgr::LoadAuctionItems() +{ + QueryResult *result = CharacterDatabase.Query( "SELECT itemguid,item_template FROM auctionhouse" ); + + if( !result ) + return; + + barGoLink bar( result->GetRowCount() ); + + uint32 count = 0; + + Field *fields; + do + { + bar.step(); + + fields = result->Fetch(); + uint32 item_guid = fields[0].GetUInt32(); + uint32 item_template = fields[1].GetUInt32(); + + ItemPrototype const *proto = objmgr.GetItemPrototype(item_template); + + if(!proto) + { + sLog.outError( "ObjectMgr::LoadAuctionItems: Unknown item (GUID: %u id: #%u) in auction, skipped.", item_guid,item_template); + continue; + } + + Item *item = NewItemOrBag(proto); + + if(!item->LoadFromDB(item_guid,0)) + { + delete item; + continue; + } + AddAItem(item); + + ++count; + } + while( result->NextRow() ); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u auction items", count ); +} + +void ObjectMgr::LoadPetLevelInfo() +{ + // Loading levels data + { + // 0 1 2 3 4 5 6 7 8 9 + QueryResult *result = WorldDatabase.Query("SELECT creature_entry, level, hp, mana, str, agi, sta, inte, spi, armor FROM pet_levelstats"); + + uint32 count = 0; + + if (!result) + { + barGoLink bar( 1 ); + + sLog.outString(); + sLog.outString( ">> Loaded %u level pet stats definitions", count ); + sLog.outErrorDb( "Error loading `pet_levelstats` table or empty table."); + return; + } + + barGoLink bar( result->GetRowCount() ); + + do + { + Field* fields = result->Fetch(); + + uint32 creature_id = fields[0].GetUInt32(); + if(!sCreatureStorage.LookupEntry(creature_id)) + { + sLog.outErrorDb("Wrong creature id %u in `pet_levelstats` table, ignoring.",creature_id); + continue; + } + + uint32 current_level = fields[1].GetUInt32(); + if(current_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + { + if(current_level > 255) // hardcoded level maximum + sLog.outErrorDb("Wrong (> 255) level %u in `pet_levelstats` table, ignoring.",current_level); + else + sLog.outDetail("Unused (> MaxPlayerLevel in mangosd.conf) level %u in `pet_levelstats` table, ignoring.",current_level); + continue; + } + else if(current_level < 1) + { + sLog.outErrorDb("Wrong (<1) level %u in `pet_levelstats` table, ignoring.",current_level); + continue; + } + + PetLevelInfo*& pInfoMapEntry = petInfo[creature_id]; + + if(pInfoMapEntry==NULL) + pInfoMapEntry = new PetLevelInfo[sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)]; + + // data for level 1 stored in [0] array element, ... + PetLevelInfo* pLevelInfo = &pInfoMapEntry[current_level-1]; + + pLevelInfo->health = fields[2].GetUInt16(); + pLevelInfo->mana = fields[3].GetUInt16(); + pLevelInfo->armor = fields[9].GetUInt16(); + + for (int i = 0; i < MAX_STATS; i++) + { + pLevelInfo->stats[i] = fields[i+4].GetUInt16(); + } + + bar.step(); + ++count; + } + while (result->NextRow()); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u level pet stats definitions", count ); + } + + // Fill gaps and check integrity + for (PetLevelInfoMap::iterator itr = petInfo.begin(); itr != petInfo.end(); ++itr) + { + PetLevelInfo* pInfo = itr->second; + + // fatal error if no level 1 data + if(!pInfo || pInfo[0].health == 0 ) + { + sLog.outErrorDb("Creature %u does not have pet stats data for Level 1!",itr->first); + exit(1); + } + + // fill level gaps + for (uint32 level = 1; level < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); ++level) + { + if(pInfo[level].health == 0) + { + sLog.outErrorDb("Creature %u has no data for Level %i pet stats data, using data of Level %i.",itr->first,level+1, level); + pInfo[level] = pInfo[level-1]; + } + } + } +} + +PetLevelInfo const* ObjectMgr::GetPetLevelInfo(uint32 creature_id, uint32 level) const +{ + if(level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + level = sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); + + PetLevelInfoMap::const_iterator itr = petInfo.find(creature_id); + if(itr == petInfo.end()) + return NULL; + + return &itr->second[level-1]; // data for level 1 stored in [0] array element, ... +} + +void ObjectMgr::LoadPlayerInfo() +{ + // Load playercreate + { + // 0 1 2 3 4 5 6 + QueryResult *result = WorldDatabase.Query("SELECT race, class, map, zone, position_x, position_y, position_z FROM playercreateinfo"); + + uint32 count = 0; + + if (!result) + { + barGoLink bar( 1 ); + + sLog.outString(); + sLog.outString( ">> Loaded %u player create definitions", count ); + sLog.outErrorDb( "Error loading `playercreateinfo` table or empty table."); + exit(1); + } + + barGoLink bar( result->GetRowCount() ); + + do + { + Field* fields = result->Fetch(); + + uint32 current_race = fields[0].GetUInt32(); + uint32 current_class = fields[1].GetUInt32(); + uint32 mapId = fields[2].GetUInt32(); + uint32 zoneId = fields[3].GetUInt32(); + float positionX = fields[4].GetFloat(); + float positionY = fields[5].GetFloat(); + float positionZ = fields[6].GetFloat(); + + if(current_race >= MAX_RACES) + { + sLog.outErrorDb("Wrong race %u in `playercreateinfo` table, ignoring.",current_race); + continue; + } + + ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(current_race); + if(!rEntry) + { + sLog.outErrorDb("Wrong race %u in `playercreateinfo` table, ignoring.",current_race); + continue; + } + + if(current_class >= MAX_CLASSES) + { + sLog.outErrorDb("Wrong class %u in `playercreateinfo` table, ignoring.",current_class); + continue; + } + + if(!sChrClassesStore.LookupEntry(current_class)) + { + sLog.outErrorDb("Wrong class %u in `playercreateinfo` table, ignoring.",current_class); + continue; + } + + // accept DB data only for valid position (and non instanceable) + if( !MapManager::IsValidMapCoord(mapId,positionX,positionY,positionZ) ) + { + sLog.outErrorDb("Wrong home position for class %u race %u pair in `playercreateinfo` table, ignoring.",current_class,current_race); + continue; + } + + if( sMapStore.LookupEntry(mapId)->Instanceable() ) + { + sLog.outErrorDb("Home position in instanceable map for class %u race %u pair in `playercreateinfo` table, ignoring.",current_class,current_race); + continue; + } + + PlayerInfo* pInfo = &playerInfo[current_race][current_class]; + + pInfo->mapId = mapId; + pInfo->zoneId = zoneId; + pInfo->positionX = positionX; + pInfo->positionY = positionY; + pInfo->positionZ = positionZ; + + pInfo->displayId_m = rEntry->model_m; + pInfo->displayId_f = rEntry->model_f; + + bar.step(); + ++count; + } + while (result->NextRow()); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u player create definitions", count ); + } + + // Load playercreate items + { + // 0 1 2 3 + QueryResult *result = WorldDatabase.Query("SELECT race, class, itemid, amount FROM playercreateinfo_item"); + + uint32 count = 0; + + if (!result) + { + barGoLink bar( 1 ); + + sLog.outString(); + sLog.outString( ">> Loaded %u player create items", count ); + sLog.outErrorDb( "Error loading `playercreateinfo_item` table or empty table."); + } + else + { + barGoLink bar( result->GetRowCount() ); + + do + { + Field* fields = result->Fetch(); + + uint32 current_race = fields[0].GetUInt32(); + if(current_race >= MAX_RACES) + { + sLog.outErrorDb("Wrong race %u in `playercreateinfo_item` table, ignoring.",current_race); + continue; + } + + uint32 current_class = fields[1].GetUInt32(); + if(current_class >= MAX_CLASSES) + { + sLog.outErrorDb("Wrong class %u in `playercreateinfo_item` table, ignoring.",current_class); + continue; + } + + PlayerInfo* pInfo = &playerInfo[current_race][current_class]; + + uint32 item_id = fields[2].GetUInt32(); + + if(!GetItemPrototype(item_id)) + { + sLog.outErrorDb("Item id %u (race %u class %u) in `playercreateinfo_item` table but not listed in `item_template`, ignoring.",item_id,current_race,current_class); + continue; + } + + uint32 amount = fields[3].GetUInt32(); + + if(!amount) + { + sLog.outErrorDb("Item id %u (class %u race %u) have amount==0 in `playercreateinfo_item` table, ignoring.",item_id,current_race,current_class); + continue; + } + + pInfo->item.push_back(PlayerCreateInfoItem( item_id, amount)); + + bar.step(); + ++count; + } + while(result->NextRow()); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u player create items", count ); + } + } + + // Load playercreate spells + { + // 0 1 2 3 + QueryResult *result = WorldDatabase.Query("SELECT race, class, Spell, Active FROM playercreateinfo_spell"); + + uint32 count = 0; + + if (!result) + { + barGoLink bar( 1 ); + + sLog.outString(); + sLog.outString( ">> Loaded %u player create spells", count ); + sLog.outErrorDb( "Error loading `playercreateinfo_spell` table or empty table."); + } + else + { + barGoLink bar( result->GetRowCount() ); + + do + { + Field* fields = result->Fetch(); + + uint32 current_race = fields[0].GetUInt32(); + if(current_race >= MAX_RACES) + { + sLog.outErrorDb("Wrong race %u in `playercreateinfo_spell` table, ignoring.",current_race); + continue; + } + + uint32 current_class = fields[1].GetUInt32(); + if(current_class >= MAX_CLASSES) + { + sLog.outErrorDb("Wrong class %u in `playercreateinfo_spell` table, ignoring.",current_class); + continue; + } + + PlayerInfo* pInfo = &playerInfo[current_race][current_class]; + pInfo->spell.push_back(CreateSpellPair(fields[2].GetUInt16(), fields[3].GetUInt8())); + + bar.step(); + ++count; + } + while( result->NextRow() ); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u player create spells", count ); + } + } + + // Load playercreate actions + { + // 0 1 2 3 4 5 + QueryResult *result = WorldDatabase.Query("SELECT race, class, button, action, type, misc FROM playercreateinfo_action"); + + uint32 count = 0; + + if (!result) + { + barGoLink bar( 1 ); + + sLog.outString(); + sLog.outString( ">> Loaded %u player create actions", count ); + sLog.outErrorDb( "Error loading `playercreateinfo_action` table or empty table."); + } + else + { + barGoLink bar( result->GetRowCount() ); + + do + { + Field* fields = result->Fetch(); + + uint32 current_race = fields[0].GetUInt32(); + if(current_race >= MAX_RACES) + { + sLog.outErrorDb("Wrong race %u in `playercreateinfo_action` table, ignoring.",current_race); + continue; + } + + uint32 current_class = fields[1].GetUInt32(); + if(current_class >= MAX_CLASSES) + { + sLog.outErrorDb("Wrong class %u in `playercreateinfo_action` table, ignoring.",current_class); + continue; + } + + PlayerInfo* pInfo = &playerInfo[current_race][current_class]; + pInfo->action[0].push_back(fields[2].GetUInt16()); + pInfo->action[1].push_back(fields[3].GetUInt16()); + pInfo->action[2].push_back(fields[4].GetUInt16()); + pInfo->action[3].push_back(fields[5].GetUInt16()); + + bar.step(); + ++count; + } + while( result->NextRow() ); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u player create actions", count ); + } + } + + // Loading levels data (class only dependent) + { + // 0 1 2 3 + QueryResult *result = WorldDatabase.Query("SELECT class, level, basehp, basemana FROM player_classlevelstats"); + + uint32 count = 0; + + if (!result) + { + barGoLink bar( 1 ); + + sLog.outString(); + sLog.outString( ">> Loaded %u level health/mana definitions", count ); + sLog.outErrorDb( "Error loading `player_classlevelstats` table or empty table."); + exit(1); + } + + barGoLink bar( result->GetRowCount() ); + + do + { + Field* fields = result->Fetch(); + + uint32 current_class = fields[0].GetUInt32(); + if(current_class >= MAX_CLASSES) + { + sLog.outErrorDb("Wrong class %u in `player_classlevelstats` table, ignoring.",current_class); + continue; + } + + uint32 current_level = fields[1].GetUInt32(); + if(current_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + { + if(current_level > 255) // hardcoded level maximum + sLog.outErrorDb("Wrong (> 255) level %u in `player_classlevelstats` table, ignoring.",current_level); + else + sLog.outDetail("Unused (> MaxPlayerLevel in mangosd.conf) level %u in `player_classlevelstats` table, ignoring.",current_level); + continue; + } + + PlayerClassInfo* pClassInfo = &playerClassInfo[current_class]; + + if(!pClassInfo->levelInfo) + pClassInfo->levelInfo = new PlayerClassLevelInfo[sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)]; + + PlayerClassLevelInfo* pClassLevelInfo = &pClassInfo->levelInfo[current_level-1]; + + pClassLevelInfo->basehealth = fields[2].GetUInt16(); + pClassLevelInfo->basemana = fields[3].GetUInt16(); + + bar.step(); + ++count; + } + while (result->NextRow()); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u level health/mana definitions", count ); + } + + // Fill gaps and check integrity + for (int class_ = 0; class_ < MAX_CLASSES; ++class_) + { + // skip non existed classes + if(!sChrClassesStore.LookupEntry(class_)) + continue; + + PlayerClassInfo* pClassInfo = &playerClassInfo[class_]; + + // fatal error if no level 1 data + if(!pClassInfo->levelInfo || pClassInfo->levelInfo[0].basehealth == 0 ) + { + sLog.outErrorDb("Class %i Level 1 does not have health/mana data!",class_); + exit(1); + } + + // fill level gaps + for (uint32 level = 1; level < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); ++level) + { + if(pClassInfo->levelInfo[level].basehealth == 0) + { + sLog.outErrorDb("Class %i Level %i does not have health/mana data. Using stats data of level %i.",class_,level+1, level); + pClassInfo->levelInfo[level] = pClassInfo->levelInfo[level-1]; + } + } + } + + // Loading levels data (class/race dependent) + { + // 0 1 2 3 4 5 6 7 + QueryResult *result = WorldDatabase.Query("SELECT race, class, level, str, agi, sta, inte, spi FROM player_levelstats"); + + uint32 count = 0; + + if (!result) + { + barGoLink bar( 1 ); + + sLog.outString(); + sLog.outString( ">> Loaded %u level stats definitions", count ); + sLog.outErrorDb( "Error loading `player_levelstats` table or empty table."); + exit(1); + } + + barGoLink bar( result->GetRowCount() ); + + do + { + Field* fields = result->Fetch(); + + uint32 current_race = fields[0].GetUInt32(); + if(current_race >= MAX_RACES) + { + sLog.outErrorDb("Wrong race %u in `player_levelstats` table, ignoring.",current_race); + continue; + } + + uint32 current_class = fields[1].GetUInt32(); + if(current_class >= MAX_CLASSES) + { + sLog.outErrorDb("Wrong class %u in `player_levelstats` table, ignoring.",current_class); + continue; + } + + uint32 current_level = fields[2].GetUInt32(); + if(current_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + { + if(current_level > 255) // hardcoded level maximum + sLog.outErrorDb("Wrong (> 255) level %u in `player_levelstats` table, ignoring.",current_level); + else + sLog.outDetail("Unused (> MaxPlayerLevel in mangosd.conf) level %u in `player_levelstats` table, ignoring.",current_level); + continue; + } + + PlayerInfo* pInfo = &playerInfo[current_race][current_class]; + + if(!pInfo->levelInfo) + pInfo->levelInfo = new PlayerLevelInfo[sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)]; + + PlayerLevelInfo* pLevelInfo = &pInfo->levelInfo[current_level-1]; + + for (int i = 0; i < MAX_STATS; i++) + { + pLevelInfo->stats[i] = fields[i+3].GetUInt8(); + } + + bar.step(); + ++count; + } + while (result->NextRow()); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u level stats definitions", count ); + } + + // Fill gaps and check integrity + for (int race = 0; race < MAX_RACES; ++race) + { + // skip non existed races + if(!sChrRacesStore.LookupEntry(race)) + continue; + + for (int class_ = 0; class_ < MAX_CLASSES; ++class_) + { + // skip non existed classes + if(!sChrClassesStore.LookupEntry(class_)) + continue; + + PlayerInfo* pInfo = &playerInfo[race][class_]; + + // skip non loaded combinations + if(!pInfo->displayId_m || !pInfo->displayId_f) + continue; + + // skip expansion races if not playing with expansion + if (sWorld.getConfig(CONFIG_EXPANSION) < 1 && (race == RACE_BLOODELF || race == RACE_DRAENEI)) + continue; + + // fatal error if no level 1 data + if(!pInfo->levelInfo || pInfo->levelInfo[0].stats[0] == 0 ) + { + sLog.outErrorDb("Race %i Class %i Level 1 does not have stats data!",race,class_); + exit(1); + } + + // fill level gaps + for (uint32 level = 1; level < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); ++level) + { + if(pInfo->levelInfo[level].stats[0] == 0) + { + sLog.outErrorDb("Race %i Class %i Level %i does not have stats data. Using stats data of level %i.",race,class_,level+1, level); + pInfo->levelInfo[level] = pInfo->levelInfo[level-1]; + } + } + } + } +} + +void ObjectMgr::GetPlayerClassLevelInfo(uint32 class_, uint32 level, PlayerClassLevelInfo* info) const +{ + if(level < 1 || class_ >= MAX_CLASSES) + return; + + PlayerClassInfo const* pInfo = &playerClassInfo[class_]; + + if(level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + level = sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); + + *info = pInfo->levelInfo[level-1]; +} + +void ObjectMgr::GetPlayerLevelInfo(uint32 race, uint32 class_, uint32 level, PlayerLevelInfo* info) const +{ + if(level < 1 || race >= MAX_RACES || class_ >= MAX_CLASSES) + return; + + PlayerInfo const* pInfo = &playerInfo[race][class_]; + if(pInfo->displayId_m==0 || pInfo->displayId_f==0) + return; + + if(level <= sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + *info = pInfo->levelInfo[level-1]; + else + BuildPlayerLevelInfo(race,class_,level,info); +} + +void ObjectMgr::BuildPlayerLevelInfo(uint8 race, uint8 _class, uint8 level, PlayerLevelInfo* info) const +{ + // base data (last known level) + *info = playerInfo[race][_class].levelInfo[sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)-1]; + + for(int lvl = sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)-1; lvl < level; ++lvl) + { + switch(_class) + { + case CLASS_WARRIOR: + info->stats[STAT_STRENGTH] += (lvl > 23 ? 2: (lvl > 1 ? 1: 0)); + info->stats[STAT_STAMINA] += (lvl > 23 ? 2: (lvl > 1 ? 1: 0)); + info->stats[STAT_AGILITY] += (lvl > 36 ? 1: (lvl > 6 && (lvl%2) ? 1: 0)); + info->stats[STAT_INTELLECT] += (lvl > 9 && !(lvl%2) ? 1: 0); + info->stats[STAT_SPIRIT] += (lvl > 9 && !(lvl%2) ? 1: 0); + break; + case CLASS_PALADIN: + info->stats[STAT_STRENGTH] += (lvl > 3 ? 1: 0); + info->stats[STAT_STAMINA] += (lvl > 33 ? 2: (lvl > 1 ? 1: 0)); + info->stats[STAT_AGILITY] += (lvl > 38 ? 1: (lvl > 7 && !(lvl%2) ? 1: 0)); + info->stats[STAT_INTELLECT] += (lvl > 6 && (lvl%2) ? 1: 0); + info->stats[STAT_SPIRIT] += (lvl > 7 ? 1: 0); + break; + case CLASS_HUNTER: + info->stats[STAT_STRENGTH] += (lvl > 4 ? 1: 0); + info->stats[STAT_STAMINA] += (lvl > 4 ? 1: 0); + info->stats[STAT_AGILITY] += (lvl > 33 ? 2: (lvl > 1 ? 1: 0)); + info->stats[STAT_INTELLECT] += (lvl > 8 && (lvl%2) ? 1: 0); + info->stats[STAT_SPIRIT] += (lvl > 38 ? 1: (lvl > 9 && !(lvl%2) ? 1: 0)); + break; + case CLASS_ROGUE: + info->stats[STAT_STRENGTH] += (lvl > 5 ? 1: 0); + info->stats[STAT_STAMINA] += (lvl > 4 ? 1: 0); + info->stats[STAT_AGILITY] += (lvl > 16 ? 2: (lvl > 1 ? 1: 0)); + info->stats[STAT_INTELLECT] += (lvl > 8 && !(lvl%2) ? 1: 0); + info->stats[STAT_SPIRIT] += (lvl > 38 ? 1: (lvl > 9 && !(lvl%2) ? 1: 0)); + break; + case CLASS_PRIEST: + info->stats[STAT_STRENGTH] += (lvl > 9 && !(lvl%2) ? 1: 0); + info->stats[STAT_STAMINA] += (lvl > 5 ? 1: 0); + info->stats[STAT_AGILITY] += (lvl > 38 ? 1: (lvl > 8 && (lvl%2) ? 1: 0)); + info->stats[STAT_INTELLECT] += (lvl > 22 ? 2: (lvl > 1 ? 1: 0)); + info->stats[STAT_SPIRIT] += (lvl > 3 ? 1: 0); + break; + case CLASS_SHAMAN: + info->stats[STAT_STRENGTH] += (lvl > 34 ? 1: (lvl > 6 && (lvl%2) ? 1: 0)); + info->stats[STAT_STAMINA] += (lvl > 4 ? 1: 0); + info->stats[STAT_AGILITY] += (lvl > 7 && !(lvl%2) ? 1: 0); + info->stats[STAT_INTELLECT] += (lvl > 5 ? 1: 0); + info->stats[STAT_SPIRIT] += (lvl > 4 ? 1: 0); + break; + case CLASS_MAGE: + info->stats[STAT_STRENGTH] += (lvl > 9 && !(lvl%2) ? 1: 0); + info->stats[STAT_STAMINA] += (lvl > 5 ? 1: 0); + info->stats[STAT_AGILITY] += (lvl > 9 && !(lvl%2) ? 1: 0); + info->stats[STAT_INTELLECT] += (lvl > 24 ? 2: (lvl > 1 ? 1: 0)); + info->stats[STAT_SPIRIT] += (lvl > 33 ? 2: (lvl > 2 ? 1: 0)); + break; + case CLASS_WARLOCK: + info->stats[STAT_STRENGTH] += (lvl > 9 && !(lvl%2) ? 1: 0); + info->stats[STAT_STAMINA] += (lvl > 38 ? 2: (lvl > 3 ? 1: 0)); + info->stats[STAT_AGILITY] += (lvl > 9 && !(lvl%2) ? 1: 0); + info->stats[STAT_INTELLECT] += (lvl > 33 ? 2: (lvl > 2 ? 1: 0)); + info->stats[STAT_SPIRIT] += (lvl > 38 ? 2: (lvl > 3 ? 1: 0)); + break; + case CLASS_DRUID: + info->stats[STAT_STRENGTH] += (lvl > 38 ? 2: (lvl > 6 && (lvl%2) ? 1: 0)); + info->stats[STAT_STAMINA] += (lvl > 32 ? 2: (lvl > 4 ? 1: 0)); + info->stats[STAT_AGILITY] += (lvl > 38 ? 2: (lvl > 8 && (lvl%2) ? 1: 0)); + info->stats[STAT_INTELLECT] += (lvl > 38 ? 3: (lvl > 4 ? 1: 0)); + info->stats[STAT_SPIRIT] += (lvl > 38 ? 3: (lvl > 5 ? 1: 0)); + } + } +} + +void ObjectMgr::LoadGuilds() +{ + Guild *newguild; + uint32 count = 0; + + QueryResult *result = CharacterDatabase.Query( "SELECT guildid FROM guild" ); + + if( !result ) + { + + barGoLink bar( 1 ); + + bar.step(); + + sLog.outString(); + sLog.outString( ">> Loaded %u guild definitions", count ); + return; + } + + barGoLink bar( result->GetRowCount() ); + + do + { + Field *fields = result->Fetch(); + + bar.step(); + ++count; + + newguild = new Guild; + if(!newguild->LoadGuildFromDB(fields[0].GetUInt32())) + { + newguild->Disband(); + delete newguild; + continue; + } + AddGuild(newguild); + + }while( result->NextRow() ); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u guild definitions", count ); +} + +void ObjectMgr::LoadArenaTeams() +{ + uint32 count = 0; + + QueryResult *result = CharacterDatabase.Query( "SELECT arenateamid FROM arena_team" ); + + if( !result ) + { + + barGoLink bar( 1 ); + + bar.step(); + + sLog.outString(); + sLog.outString( ">> Loaded %u arenateam definitions", count ); + return; + } + + barGoLink bar( result->GetRowCount() ); + + do + { + Field *fields = result->Fetch(); + + bar.step(); + ++count; + + ArenaTeam *newarenateam = new ArenaTeam; + if(!newarenateam->LoadArenaTeamFromDB(fields[0].GetUInt32())) + { + delete newarenateam; + continue; + } + AddArenaTeam(newarenateam); + }while( result->NextRow() ); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u arenateam definitions", count ); +} + +void ObjectMgr::LoadGroups() +{ + // -- loading groups -- + Group *group = NULL; + uint64 leaderGuid = 0; + uint32 count = 0; + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + QueryResult *result = CharacterDatabase.PQuery("SELECT mainTank, mainAssistant, lootMethod, looterGuid, lootThreshold, icon1, icon2, icon3, icon4, icon5, icon6, icon7, icon8, isRaid, difficulty, leaderGuid FROM groups"); + + if( !result ) + { + barGoLink bar( 1 ); + + bar.step(); + + sLog.outString(); + sLog.outString( ">> Loaded %u group definitions", count ); + return; + } + + barGoLink bar( result->GetRowCount() ); + + do + { + bar.step(); + Field *fields = result->Fetch(); + ++count; + leaderGuid = MAKE_NEW_GUID(fields[15].GetUInt32(),0,HIGHGUID_PLAYER); + + group = new Group; + if(!group->LoadGroupFromDB(leaderGuid, result, false)) + { + group->Disband(); + delete group; + continue; + } + AddGroup(group); + }while( result->NextRow() ); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u group definitions", count ); + + // -- loading members -- + count = 0; + group = NULL; + leaderGuid = 0; + // 0 1 2 3 + result = CharacterDatabase.PQuery("SELECT memberGuid, assistant, subgroup, leaderGuid FROM group_member ORDER BY leaderGuid"); + if(!result) + { + barGoLink bar( 1 ); + bar.step(); + } + else + { + barGoLink bar( result->GetRowCount() ); + do + { + bar.step(); + Field *fields = result->Fetch(); + count++; + leaderGuid = MAKE_NEW_GUID(fields[3].GetUInt32(), 0, HIGHGUID_PLAYER); + if(!group || group->GetLeaderGUID() != leaderGuid) + { + group = GetGroupByLeader(leaderGuid); + if(!group) + { + sLog.outErrorDb("Incorrect entry in group_member table : no group with leader %d for member %d!", fields[3].GetUInt32(), fields[0].GetUInt32()); + CharacterDatabase.PExecute("DELETE FROM group_member WHERE memberGuid = '%d'", fields[0].GetUInt32()); + continue; + } + } + + if(!group->LoadMemberFromDB(fields[0].GetUInt32(), fields[2].GetUInt8(), fields[1].GetBool())) + { + sLog.outErrorDb("Incorrect entry in group_member table : member %d cannot be added to player %d's group!", fields[0].GetUInt32(), fields[3].GetUInt32()); + CharacterDatabase.PExecute("DELETE FROM group_member WHERE memberGuid = '%d'", fields[0].GetUInt32()); + } + }while( result->NextRow() ); + delete result; + } + + // clean groups + // TODO: maybe delete from the DB before loading in this case + for(GroupSet::iterator itr = mGroupSet.begin(); itr != mGroupSet.end();) + { + if((*itr)->GetMembersCount() < 2) + { + (*itr)->Disband(); + delete *itr; + mGroupSet.erase(itr++); + } + else + ++itr; + } + + // -- loading instances -- + count = 0; + group = NULL; + leaderGuid = 0; + result = CharacterDatabase.PQuery( + // 0 1 2 3 4 5 + "SELECT leaderGuid, map, instance, permanent, difficulty, resettime, " + // 6 + "(SELECT COUNT(*) FROM character_instance WHERE guid = leaderGuid AND instance = group_instance.instance AND permanent = 1 LIMIT 1) " + "FROM group_instance LEFT JOIN instance ON instance = id ORDER BY leaderGuid" + ); + + if(!result) + { + barGoLink bar( 1 ); + bar.step(); + } + else + { + barGoLink bar( result->GetRowCount() ); + do + { + bar.step(); + Field *fields = result->Fetch(); + count++; + leaderGuid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); + if(!group || group->GetLeaderGUID() != leaderGuid) + { + group = GetGroupByLeader(leaderGuid); + if(!group) + { + sLog.outErrorDb("Incorrect entry in group_instance table : no group with leader %d", fields[0].GetUInt32()); + continue; + } + } + + InstanceSave *save = sInstanceSaveManager.AddInstanceSave(fields[1].GetUInt32(), fields[2].GetUInt32(), fields[4].GetUInt8(), (time_t)fields[5].GetUInt64(), (fields[6].GetUInt32() == 0), true); + group->BindToInstance(save, fields[3].GetBool(), true); + }while( result->NextRow() ); + delete result; + } + + sLog.outString(); + sLog.outString( ">> Loaded %u group-instance binds total", count ); + + sLog.outString(); + sLog.outString( ">> Loaded %u group members total", count ); +} + +void ObjectMgr::LoadQuests() +{ + // For reload case + for(QuestMap::const_iterator itr=mQuestTemplates.begin(); itr != mQuestTemplates.end(); ++itr) + delete itr->second; + mQuestTemplates.clear(); + + mExclusiveQuestGroups.clear(); + + // 0 1 2 3 4 5 6 7 + QueryResult *result = WorldDatabase.Query("SELECT entry, ZoneOrSort, SkillOrClass, MinLevel, QuestLevel, Type, RequiredRaces, RequiredSkillValue," + // 8 9 10 11 12 13 14 15 + "RepObjectiveFaction, RepObjectiveValue, RequiredMinRepFaction, RequiredMinRepValue, RequiredMaxRepFaction, RequiredMaxRepValue, SuggestedPlayers, LimitTime," + // 16 17 18 19 20 21 22 23 24 25 + "QuestFlags, SpecialFlags, CharTitleId, PrevQuestId, NextQuestId, ExclusiveGroup, NextQuestInChain, SrcItemId, SrcItemCount, SrcSpell," + // 26 27 28 29 30 31 32 33 34 35 + "Title, Details, Objectives, OfferRewardText, RequestItemsText, EndText, ObjectiveText1, ObjectiveText2, ObjectiveText3, ObjectiveText4," + // 36 37 38 39 40 41 42 43 + "ReqItemId1, ReqItemId2, ReqItemId3, ReqItemId4, ReqItemCount1, ReqItemCount2, ReqItemCount3, ReqItemCount4," + // 44 45 46 47 48 49 50 51 52 53 54 55 + "ReqSourceId1, ReqSourceId2, ReqSourceId3, ReqSourceId4, ReqSourceCount1, ReqSourceCount2, ReqSourceCount3, ReqSourceCount4, ReqSourceRef1, ReqSourceRef2, ReqSourceRef3, ReqSourceRef4," + // 56 57 58 59 60 61 62 63 + "ReqCreatureOrGOId1, ReqCreatureOrGOId2, ReqCreatureOrGOId3, ReqCreatureOrGOId4, ReqCreatureOrGOCount1, ReqCreatureOrGOCount2, ReqCreatureOrGOCount3, ReqCreatureOrGOCount4," + // 64 65 66 67 + "ReqSpellCast1, ReqSpellCast2, ReqSpellCast3, ReqSpellCast4," + // 68 69 70 71 72 73 + "RewChoiceItemId1, RewChoiceItemId2, RewChoiceItemId3, RewChoiceItemId4, RewChoiceItemId5, RewChoiceItemId6," + // 74 75 76 77 78 79 + "RewChoiceItemCount1, RewChoiceItemCount2, RewChoiceItemCount3, RewChoiceItemCount4, RewChoiceItemCount5, RewChoiceItemCount6," + // 80 81 82 83 84 85 86 87 + "RewItemId1, RewItemId2, RewItemId3, RewItemId4, RewItemCount1, RewItemCount2, RewItemCount3, RewItemCount4," + // 88 89 90 91 92 93 94 95 96 97 + "RewRepFaction1, RewRepFaction2, RewRepFaction3, RewRepFaction4, RewRepFaction5, RewRepValue1, RewRepValue2, RewRepValue3, RewRepValue4, RewRepValue5," + // 98 99 100 101 102 103 104 105 106 107 + "RewOrReqMoney, RewMoneyMaxLevel, RewSpell, RewSpellCast, RewMailTemplateId, RewMailDelaySecs, PointMapId, PointX, PointY, PointOpt," + // 108 109 110 111 112 113 114 115 116 117 + "DetailsEmote1, DetailsEmote2, DetailsEmote3, DetailsEmote4,IncompleteEmote, CompleteEmote, OfferRewardEmote1, OfferRewardEmote2, OfferRewardEmote3, OfferRewardEmote4," + // 118 119 + "StartScript, CompleteScript" + " FROM quest_template"); + if(result == NULL) + { + barGoLink bar( 1 ); + bar.step(); + + sLog.outString(); + sLog.outString( ">> Loaded 0 quests definitions" ); + sLog.outErrorDb("`quest_template` table is empty!"); + return; + } + + // create multimap previous quest for each existed quest + // some quests can have many previous maps set by NextQuestId in previous quest + // for example set of race quests can lead to single not race specific quest + barGoLink bar( result->GetRowCount() ); + do + { + bar.step(); + Field *fields = result->Fetch(); + + Quest * newQuest = new Quest(fields); + mQuestTemplates[newQuest->GetQuestId()] = newQuest; + } while( result->NextRow() ); + + delete result; + + // Post processing + for (QuestMap::iterator iter = mQuestTemplates.begin(); iter != mQuestTemplates.end(); iter++) + { + Quest * qinfo = iter->second; + + // additional quest integrity checks (GO, creature_template and item_template must be loaded already) + + if (qinfo->QuestFlags & ~QUEST_MANGOS_FLAGS_DB_ALLOWED) + { + sLog.outErrorDb("Quest %u has `SpecialFlags` = %u > max allowed value. Correct `SpecialFlags` to value <= %u", + qinfo->GetQuestId(),qinfo->QuestFlags,QUEST_MANGOS_FLAGS_DB_ALLOWED >> 16); + qinfo->QuestFlags &= QUEST_MANGOS_FLAGS_DB_ALLOWED; + } + + if(qinfo->QuestFlags & QUEST_FLAGS_DAILY) + { + if(!(qinfo->QuestFlags & QUEST_MANGOS_FLAGS_REPEATABLE)) + { + sLog.outErrorDb("Daily Quest %u not marked as repeatable in `SpecialFlags`, added.",qinfo->GetQuestId()); + qinfo->QuestFlags |= QUEST_MANGOS_FLAGS_REPEATABLE; + } + } + + if(qinfo->QuestFlags & QUEST_FLAGS_AUTO_REWARDED) + { + // at auto-reward can be rewarded only RewChoiceItemId[0] + for(int j = 1; j < QUEST_REWARD_CHOICES_COUNT; ++j ) + { + if(uint32 id = qinfo->RewChoiceItemId[j]) + { + sLog.outErrorDb("Quest %u has `RewChoiceItemId%d` = %u but item from `RewChoiceItemId%d` can't be rewarded with quest flag QUEST_FLAGS_AUTO_REWARDED.", + qinfo->GetQuestId(),j+1,id,j+1); + // no changes, quest ignore this data + } + } + } + + // client quest log visual (area case) + if( qinfo->ZoneOrSort > 0 ) + { + if(!GetAreaEntryByAreaID(qinfo->ZoneOrSort)) + { + sLog.outErrorDb("Quest %u has `ZoneOrSort` = %u (zone case) but zone with this id does not exist.", + qinfo->GetQuestId(),qinfo->ZoneOrSort); + // no changes, quest not dependent from this value but can have problems at client + } + } + // client quest log visual (sort case) + if( qinfo->ZoneOrSort < 0 ) + { + QuestSortEntry const* qSort = sQuestSortStore.LookupEntry(-int32(qinfo->ZoneOrSort)); + if( !qSort ) + { + sLog.outErrorDb("Quest %u has `ZoneOrSort` = %i (sort case) but quest sort with this id does not exist.", + qinfo->GetQuestId(),qinfo->ZoneOrSort); + // no changes, quest not dependent from this value but can have problems at client (note some may be 0, we must allow this so no check) + } + //check SkillOrClass value (class case). + if( ClassByQuestSort(-int32(qinfo->ZoneOrSort)) ) + { + // SkillOrClass should not have class case when class case already set in ZoneOrSort. + if(qinfo->SkillOrClass < 0) + { + sLog.outErrorDb("Quest %u has `ZoneOrSort` = %i (class sort case) and `SkillOrClass` = %i (class case), redundant.", + qinfo->GetQuestId(),qinfo->ZoneOrSort,qinfo->SkillOrClass); + } + } + //check for proper SkillOrClass value (skill case) + if(int32 skill_id = SkillByQuestSort(-int32(qinfo->ZoneOrSort))) + { + // skill is positive value in SkillOrClass + if(qinfo->SkillOrClass != skill_id ) + { + sLog.outErrorDb("Quest %u has `ZoneOrSort` = %i (skill sort case) but `SkillOrClass` does not have a corresponding value (%i).", + qinfo->GetQuestId(),qinfo->ZoneOrSort,skill_id); + //override, and force proper value here? + } + } + } + + // SkillOrClass (class case) + if( qinfo->SkillOrClass < 0 ) + { + if( !sChrClassesStore.LookupEntry(-int32(qinfo->SkillOrClass)) ) + { + sLog.outErrorDb("Quest %u has `SkillOrClass` = %i (class case) but class (%i) does not exist", + qinfo->GetQuestId(),qinfo->SkillOrClass,-qinfo->SkillOrClass); + } + } + // SkillOrClass (skill case) + if( qinfo->SkillOrClass > 0 ) + { + if( !sSkillLineStore.LookupEntry(qinfo->SkillOrClass) ) + { + sLog.outErrorDb("Quest %u has `SkillOrClass` = %u (skill case) but skill (%i) does not exist", + qinfo->GetQuestId(),qinfo->SkillOrClass,qinfo->SkillOrClass); + } + } + + if( qinfo->RequiredSkillValue ) + { + if( qinfo->RequiredSkillValue > sWorld.GetConfigMaxSkillValue() ) + { + sLog.outErrorDb("Quest %u has `RequiredSkillValue` = %u but max possible skill is %u, quest can't be done.", + qinfo->GetQuestId(),qinfo->RequiredSkillValue,sWorld.GetConfigMaxSkillValue()); + // no changes, quest can't be done for this requirement + } + + if( qinfo->SkillOrClass <= 0 ) + { + sLog.outErrorDb("Quest %u has `RequiredSkillValue` = %u but `SkillOrClass` = %i (class case), value ignored.", + qinfo->GetQuestId(),qinfo->RequiredSkillValue,qinfo->SkillOrClass); + // no changes, quest can't be done for this requirement (fail at wrong skill id) + } + } + // else Skill quests can have 0 skill level, this is ok + + if(qinfo->RepObjectiveFaction && !sFactionStore.LookupEntry(qinfo->RepObjectiveFaction)) + { + sLog.outErrorDb("Quest %u has `RepObjectiveFaction` = %u but faction template %u does not exist, quest can't be done.", + qinfo->GetQuestId(),qinfo->RepObjectiveFaction,qinfo->RepObjectiveFaction); + // no changes, quest can't be done for this requirement + } + + if(qinfo->RequiredMinRepFaction && !sFactionStore.LookupEntry(qinfo->RequiredMinRepFaction)) + { + sLog.outErrorDb("Quest %u has `RequiredMinRepFaction` = %u but faction template %u does not exist, quest can't be done.", + qinfo->GetQuestId(),qinfo->RequiredMinRepFaction,qinfo->RequiredMinRepFaction); + // no changes, quest can't be done for this requirement + } + + if(qinfo->RequiredMaxRepFaction && !sFactionStore.LookupEntry(qinfo->RequiredMaxRepFaction)) + { + sLog.outErrorDb("Quest %u has `RequiredMaxRepFaction` = %u but faction template %u does not exist, quest can't be done.", + qinfo->GetQuestId(),qinfo->RequiredMaxRepFaction,qinfo->RequiredMaxRepFaction); + // no changes, quest can't be done for this requirement + } + + if(qinfo->RequiredMinRepValue && qinfo->RequiredMinRepValue > Player::Reputation_Cap) + { + sLog.outErrorDb("Quest %u has `RequiredMinRepValue` = %d but max reputation is %u, quest can't be done.", + qinfo->GetQuestId(),qinfo->RequiredMinRepValue,Player::Reputation_Cap); + // no changes, quest can't be done for this requirement + } + + if(qinfo->RequiredMinRepValue && qinfo->RequiredMaxRepValue && qinfo->RequiredMaxRepValue <= qinfo->RequiredMinRepValue) + { + sLog.outErrorDb("Quest %u has `RequiredMaxRepValue` = %d and `RequiredMinRepValue` = %d, quest can't be done.", + qinfo->GetQuestId(),qinfo->RequiredMaxRepValue,qinfo->RequiredMinRepValue); + // no changes, quest can't be done for this requirement + } + + if(!qinfo->RepObjectiveFaction && qinfo->RepObjectiveValue > 0 ) + { + sLog.outErrorDb("Quest %u has `RepObjectiveValue` = %d but `RepObjectiveFaction` is 0, value has no effect", + qinfo->GetQuestId(),qinfo->RepObjectiveValue); + // warning + } + + if(!qinfo->RequiredMinRepFaction && qinfo->RequiredMinRepValue > 0 ) + { + sLog.outErrorDb("Quest %u has `RequiredMinRepValue` = %d but `RequiredMinRepFaction` is 0, value has no effect", + qinfo->GetQuestId(),qinfo->RequiredMinRepValue); + // warning + } + + if(!qinfo->RequiredMaxRepFaction && qinfo->RequiredMaxRepValue > 0 ) + { + sLog.outErrorDb("Quest %u has `RequiredMaxRepValue` = %d but `RequiredMaxRepFaction` is 0, value has no effect", + qinfo->GetQuestId(),qinfo->RequiredMaxRepValue); + // warning + } + + if(qinfo->CharTitleId && !sCharTitlesStore.LookupEntry(qinfo->CharTitleId)) + { + sLog.outErrorDb("Quest %u has `CharTitleId` = %u but CharTitle Id %u does not exist, quest can't be rewarded with title.", + qinfo->GetQuestId(),qinfo->GetCharTitleId(),qinfo->GetCharTitleId()); + qinfo->CharTitleId = 0; + // quest can't reward this title + } + + if(qinfo->SrcItemId) + { + if(!sItemStorage.LookupEntry(qinfo->SrcItemId)) + { + sLog.outErrorDb("Quest %u has `SrcItemId` = %u but item with entry %u does not exist, quest can't be done.", + qinfo->GetQuestId(),qinfo->SrcItemId,qinfo->SrcItemId); + qinfo->SrcItemId = 0; // quest can't be done for this requirement + } + else if(qinfo->SrcItemCount==0) + { + sLog.outErrorDb("Quest %u has `SrcItemId` = %u but `SrcItemCount` = 0, set to 1 but need fix in DB.", + qinfo->GetQuestId(),qinfo->SrcItemId); + qinfo->SrcItemCount = 1; // update to 1 for allow quest work for backward comptibility with DB + } + } + else if(qinfo->SrcItemCount>0) + { + sLog.outErrorDb("Quest %u has `SrcItemId` = 0 but `SrcItemCount` = %u, useless value.", + qinfo->GetQuestId(),qinfo->SrcItemCount); + qinfo->SrcItemCount=0; // no quest work changes in fact + } + + if(qinfo->SrcSpell) + { + SpellEntry const* spellInfo = sSpellStore.LookupEntry(qinfo->SrcSpell); + if(!spellInfo) + { + sLog.outErrorDb("Quest %u has `SrcSpell` = %u but spell %u doesn't exist, quest can't be done.", + qinfo->GetQuestId(),qinfo->SrcSpell,qinfo->SrcSpell); + qinfo->SrcSpell = 0; // quest can't be done for this requirement + } + else if(!SpellMgr::IsSpellValid(spellInfo)) + { + sLog.outErrorDb("Quest %u has `SrcSpell` = %u but spell %u is broken, quest can't be done.", + qinfo->GetQuestId(),qinfo->SrcSpell,qinfo->SrcSpell); + qinfo->SrcSpell = 0; // quest can't be done for this requirement + } + } + + for(int j = 0; j < QUEST_OBJECTIVES_COUNT; ++j ) + { + uint32 id = qinfo->ReqItemId[j]; + if(id) + { + if(qinfo->ReqItemCount[j]==0) + { + sLog.outErrorDb("Quest %u has `ReqItemId%d` = %u but `ReqItemCount%d` = 0, quest can't be done.", + qinfo->GetQuestId(),j+1,id,j+1); + // no changes, quest can't be done for this requirement + } + + qinfo->SetFlag(QUEST_MANGOS_FLAGS_DELIVER); + + if(!sItemStorage.LookupEntry(id)) + { + sLog.outErrorDb("Quest %u has `ReqItemId%d` = %u but item with entry %u does not exist, quest can't be done.", + qinfo->GetQuestId(),j+1,id,id); + qinfo->ReqItemCount[j] = 0; // prevent incorrect work of quest + } + } + else if(qinfo->ReqItemCount[j]>0) + { + sLog.outErrorDb("Quest %u has `ReqItemId%d` = 0 but `ReqItemCount%d` = %u, quest can't be done.", + qinfo->GetQuestId(),j+1,j+1,qinfo->ReqItemCount[j]); + qinfo->ReqItemCount[j] = 0; // prevent incorrect work of quest + } + } + + for(int j = 0; j < QUEST_SOURCE_ITEM_IDS_COUNT; ++j ) + { + uint32 id = qinfo->ReqSourceId[j]; + if(id) + { + if(!sItemStorage.LookupEntry(id)) + { + sLog.outErrorDb("Quest %u has `ReqSourceId%d` = %u but item with entry %u does not exist, quest can't be done.", + qinfo->GetQuestId(),j+1,id,id); + // no changes, quest can't be done for this requirement + } + + if(!qinfo->ReqSourceCount[j]) + { + sLog.outErrorDb("Quest %u has `ReqSourceId%d` = %u but `ReqSourceCount%d` = 0, quest can't be done.", + qinfo->GetQuestId(),j+1,id,j+1); + qinfo->ReqSourceId[j] = 0; // prevent incorrect work of quest + } + + if(!qinfo->ReqSourceRef[j]) + { + sLog.outErrorDb("Quest %u has `ReqSourceId%d` = %u but `ReqSourceRef%d` = 0, quest can't be done.", + qinfo->GetQuestId(),j+1,id,j+1); + qinfo->ReqSourceId[j] = 0; // prevent incorrect work of quest + } + } + else + { + if(qinfo->ReqSourceCount[j]>0) + { + sLog.outErrorDb("Quest %u has `ReqSourceId%d` = 0 but `ReqSourceCount%d` = %u.", + qinfo->GetQuestId(),j+1,j+1,qinfo->ReqSourceCount[j]); + // no changes, quest ignore this data + } + + if(qinfo->ReqSourceRef[j]>0) + { + sLog.outErrorDb("Quest %u has `ReqSourceId%d` = 0 but `ReqSourceRef%d` = %u.", + qinfo->GetQuestId(),j+1,j+1,qinfo->ReqSourceRef[j]); + // no changes, quest ignore this data + } + } + } + + for(int j = 0; j < QUEST_SOURCE_ITEM_IDS_COUNT; ++j ) + { + uint32 ref = qinfo->ReqSourceRef[j]; + if(ref) + { + if(ref > QUEST_OBJECTIVES_COUNT) + { + sLog.outErrorDb("Quest %u has `ReqSourceRef%d` = %u but max value in `ReqSourceRef%d` is %u, quest can't be done.", + qinfo->GetQuestId(),j+1,ref,j+1,QUEST_OBJECTIVES_COUNT); + // no changes, quest can't be done for this requirement + } + else + if(!qinfo->ReqItemId[ref-1] && !qinfo->ReqSpell[ref-1]) + { + sLog.outErrorDb("Quest %u has `ReqSourceRef%d` = %u but `ReqItemId%u` = 0 and `ReqSpellCast%u` = 0, quest can't be done.", + qinfo->GetQuestId(),j+1,ref,ref,ref); + // no changes, quest can't be done for this requirement + } + else if(qinfo->ReqItemId[ref-1] && qinfo->ReqSpell[ref-1]) + { + sLog.outErrorDb("Quest %u has `ReqItemId%u` = %u and `ReqSpellCast%u` = %u, quest can't have both fields <> 0, then can't be done.", + qinfo->GetQuestId(),ref,qinfo->ReqItemId[ref-1],ref,qinfo->ReqSpell[ref-1]); + // no changes, quest can't be done for this requirement + qinfo->ReqSourceId[j] = 0; // prevent incorrect work of quest + } + } + } + + for(int j = 0; j < QUEST_OBJECTIVES_COUNT; ++j ) + { + uint32 id = qinfo->ReqSpell[j]; + if(id) + { + SpellEntry const* spellInfo = sSpellStore.LookupEntry(id); + if(!spellInfo) + { + sLog.outErrorDb("Quest %u has `ReqSpellCast%d` = %u but spell %u does not exist, quest can't be done.", + qinfo->GetQuestId(),j+1,id,id); + // no changes, quest can't be done for this requirement + } + + if(!qinfo->ReqCreatureOrGOId[j]) + { + bool found = false; + for(int k = 0; k < 3; ++k) + { + if( spellInfo->Effect[k]==SPELL_EFFECT_QUEST_COMPLETE && uint32(spellInfo->EffectMiscValue[k])==qinfo->QuestId || + spellInfo->Effect[k]==SPELL_EFFECT_SEND_EVENT) + { + found = true; + break; + } + } + + if(found) + { + if(!qinfo->HasFlag(QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT)) + { + sLog.outErrorDb("Spell (id: %u) have SPELL_EFFECT_QUEST_COMPLETE or SPELL_EFFECT_SEND_EVENT for quest %u and ReqCreatureOrGOId%d = 0, but quest not have flag QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT. Quest flags or ReqCreatureOrGOId%d must be fixed, quest modified to enable objective.",spellInfo->Id,qinfo->QuestId,j+1,j+1); + + // this will prevent quest completing without objective + const_cast(qinfo)->SetFlag(QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT); + } + } + else + { + sLog.outErrorDb("Quest %u has `ReqSpellCast%d` = %u and ReqCreatureOrGOId%d = 0 but spell %u does not have SPELL_EFFECT_QUEST_COMPLETE or SPELL_EFFECT_SEND_EVENT effect for this quest, quest can't be done.", + qinfo->GetQuestId(),j+1,id,j+1,id); + // no changes, quest can't be done for this requirement + } + } + } + } + + for(int j = 0; j < QUEST_OBJECTIVES_COUNT; ++j ) + { + int32 id = qinfo->ReqCreatureOrGOId[j]; + if(id < 0 && !sGOStorage.LookupEntry(-id)) + { + sLog.outErrorDb("Quest %u has `ReqCreatureOrGOId%d` = %i but gameobject %u does not exist, quest can't be done.", + qinfo->GetQuestId(),j+1,id,uint32(-id)); + qinfo->ReqCreatureOrGOId[j] = 0; // quest can't be done for this requirement + } + + if(id > 0 && !sCreatureStorage.LookupEntry(id)) + { + sLog.outErrorDb("Quest %u has `ReqCreatureOrGOId%d` = %i but creature with entry %u does not exist, quest can't be done.", + qinfo->GetQuestId(),j+1,id,uint32(id)); + qinfo->ReqCreatureOrGOId[j] = 0; // quest can't be done for this requirement + } + + if(id) + { + // In fact SpeakTo and Kill are quite same: either you can speak to mob:SpeakTo or you can't:Kill/Cast + + qinfo->SetFlag(QUEST_MANGOS_FLAGS_KILL_OR_CAST | QUEST_MANGOS_FLAGS_SPEAKTO); + + if(!qinfo->ReqCreatureOrGOCount[j]) + { + sLog.outErrorDb("Quest %u has `ReqCreatureOrGOId%d` = %u but `ReqCreatureOrGOCount%d` = 0, quest can't be done.", + qinfo->GetQuestId(),j+1,id,j+1); + // no changes, quest can be incorrectly done, but we already report this + } + } + else if(qinfo->ReqCreatureOrGOCount[j]>0) + { + sLog.outErrorDb("Quest %u has `ReqCreatureOrGOId%d` = 0 but `ReqCreatureOrGOCount%d` = %u.", + qinfo->GetQuestId(),j+1,j+1,qinfo->ReqCreatureOrGOCount[j]); + // no changes, quest ignore this data + } + } + + for(int j = 0; j < QUEST_REWARD_CHOICES_COUNT; ++j ) + { + uint32 id = qinfo->RewChoiceItemId[j]; + if(id) + { + if(!sItemStorage.LookupEntry(id)) + { + sLog.outErrorDb("Quest %u has `RewChoiceItemId%d` = %u but item with entry %u does not exist, quest will not reward this item.", + qinfo->GetQuestId(),j+1,id,id); + qinfo->RewChoiceItemId[j] = 0; // no changes, quest will not reward this + } + + if(!qinfo->RewChoiceItemCount[j]) + { + sLog.outErrorDb("Quest %u has `RewChoiceItemId%d` = %u but `RewChoiceItemCount%d` = 0, quest can't be done.", + qinfo->GetQuestId(),j+1,id,j+1); + // no changes, quest can't be done + } + } + else if(qinfo->RewChoiceItemCount[j]>0) + { + sLog.outErrorDb("Quest %u has `RewChoiceItemId%d` = 0 but `RewChoiceItemCount%d` = %u.", + qinfo->GetQuestId(),j+1,j+1,qinfo->RewChoiceItemCount[j]); + // no changes, quest ignore this data + } + } + + for(int j = 0; j < QUEST_REWARDS_COUNT; ++j ) + { + uint32 id = qinfo->RewItemId[j]; + if(id) + { + if(!sItemStorage.LookupEntry(id)) + { + sLog.outErrorDb("Quest %u has `RewItemId%d` = %u but item with entry %u does not exist, quest will not reward this item.", + qinfo->GetQuestId(),j+1,id,id); + qinfo->RewItemId[j] = 0; // no changes, quest will not reward this item + } + + if(!qinfo->RewItemCount[j]) + { + sLog.outErrorDb("Quest %u has `RewItemId%d` = %u but `RewItemCount%d` = 0, quest will not reward this item.", + qinfo->GetQuestId(),j+1,id,j+1); + // no changes + } + } + else if(qinfo->RewItemCount[j]>0) + { + sLog.outErrorDb("Quest %u has `RewItemId%d` = 0 but `RewItemCount%d` = %u.", + qinfo->GetQuestId(),j+1,j+1,qinfo->RewItemCount[j]); + // no changes, quest ignore this data + } + } + + for(int j = 0; j < QUEST_REPUTATIONS_COUNT; ++j) + { + if(qinfo->RewRepFaction[j]) + { + if(!qinfo->RewRepValue[j]) + { + sLog.outErrorDb("Quest %u has `RewRepFaction%d` = %u but `RewRepValue%d` = 0, quest will not reward this reputation.", + qinfo->GetQuestId(),j+1,qinfo->RewRepValue[j],j+1); + // no changes + } + + if(!sFactionStore.LookupEntry(qinfo->RewRepFaction[j])) + { + sLog.outErrorDb("Quest %u has `RewRepFaction%d` = %u but raw faction (faction.dbc) %u does not exist, quest will not reward reputation for this faction.", + qinfo->GetQuestId(),j+1,qinfo->RewRepFaction[j] ,qinfo->RewRepFaction[j] ); + qinfo->RewRepFaction[j] = 0; // quest will not reward this + } + } + else if(qinfo->RewRepValue[j]!=0) + { + sLog.outErrorDb("Quest %u has `RewRepFaction%d` = 0 but `RewRepValue%d` = %u.", + qinfo->GetQuestId(),j+1,j+1,qinfo->RewRepValue[j]); + // no changes, quest ignore this data + } + } + + if(qinfo->RewSpell) + { + SpellEntry const* spellInfo = sSpellStore.LookupEntry(qinfo->RewSpell); + + if(!spellInfo) + { + sLog.outErrorDb("Quest %u has `RewSpell` = %u but spell %u does not exist, spell removed as display reward.", + qinfo->GetQuestId(),qinfo->RewSpell,qinfo->RewSpell); + qinfo->RewSpell = 0; // no spell reward will display for this quest + } + + else if(!SpellMgr::IsSpellValid(spellInfo)) + { + sLog.outErrorDb("Quest %u has `RewSpell` = %u but spell %u is broken, quest can't be done.", + qinfo->GetQuestId(),qinfo->RewSpell,qinfo->RewSpell); + qinfo->RewSpell = 0; // no spell reward will display for this quest + } + + } + + if(qinfo->RewSpellCast) + { + SpellEntry const* spellInfo = sSpellStore.LookupEntry(qinfo->RewSpellCast); + + if(!spellInfo) + { + sLog.outErrorDb("Quest %u has `RewSpellCast` = %u but spell %u does not exist, quest will not have a spell reward.", + qinfo->GetQuestId(),qinfo->RewSpellCast,qinfo->RewSpellCast); + qinfo->RewSpellCast = 0; // no spell will be casted on player + } + + else if(!SpellMgr::IsSpellValid(spellInfo)) + { + sLog.outErrorDb("Quest %u has `RewSpellCast` = %u but spell %u is broken, quest can't be done.", + qinfo->GetQuestId(),qinfo->RewSpellCast,qinfo->RewSpellCast); + qinfo->RewSpellCast = 0; // no spell will be casted on player + } + + } + + if(qinfo->RewMailTemplateId) + { + if(!sMailTemplateStore.LookupEntry(qinfo->RewMailTemplateId)) + { + sLog.outErrorDb("Quest %u has `RewMailTemplateId` = %u but mail template %u does not exist, quest will not have a mail reward.", + qinfo->GetQuestId(),qinfo->RewMailTemplateId,qinfo->RewMailTemplateId); + qinfo->RewMailTemplateId = 0; // no mail will send to player + qinfo->RewMailDelaySecs = 0; // no mail will send to player + } + } + + if(qinfo->NextQuestInChain) + { + if(mQuestTemplates.find(qinfo->NextQuestInChain) == mQuestTemplates.end()) + { + sLog.outErrorDb("Quest %u has `NextQuestInChain` = %u but quest %u does not exist, quest chain will not work.", + qinfo->GetQuestId(),qinfo->NextQuestInChain ,qinfo->NextQuestInChain ); + qinfo->NextQuestInChain = 0; + } + else + mQuestTemplates[qinfo->NextQuestInChain]->prevChainQuests.push_back(qinfo->GetQuestId()); + } + + // fill additional data stores + if(qinfo->PrevQuestId) + { + if (mQuestTemplates.find(abs(qinfo->GetPrevQuestId())) == mQuestTemplates.end()) + { + sLog.outErrorDb("Quest %d has PrevQuestId %i, but no such quest", qinfo->GetQuestId(), qinfo->GetPrevQuestId()); + } + else + { + qinfo->prevQuests.push_back(qinfo->PrevQuestId); + } + } + + if(qinfo->NextQuestId) + { + if (mQuestTemplates.find(abs(qinfo->GetNextQuestId())) == mQuestTemplates.end()) + { + sLog.outErrorDb("Quest %d has NextQuestId %i, but no such quest", qinfo->GetQuestId(), qinfo->GetNextQuestId()); + } + else + { + int32 signedQuestId = qinfo->NextQuestId < 0 ? -int32(qinfo->GetQuestId()) : int32(qinfo->GetQuestId()); + mQuestTemplates[abs(qinfo->GetNextQuestId())]->prevQuests.push_back(signedQuestId); + } + } + + if(qinfo->ExclusiveGroup) + mExclusiveQuestGroups.insert(std::pair(qinfo->ExclusiveGroup, qinfo->GetQuestId())); + if(qinfo->LimitTime) + qinfo->SetFlag(QUEST_MANGOS_FLAGS_TIMED); + } + + // check QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT for spell with SPELL_EFFECT_QUEST_COMPLETE + for (uint32 i = 0; i < sSpellStore.GetNumRows(); ++i) + { + SpellEntry const *spellInfo = sSpellStore.LookupEntry(i); + if(!spellInfo) + continue; + + for(int j = 0; j < 3; ++j) + { + if(spellInfo->Effect[j] != SPELL_EFFECT_QUEST_COMPLETE) + continue; + + uint32 quest_id = spellInfo->EffectMiscValue[j]; + + Quest const* quest = GetQuestTemplate(quest_id); + + // some quest referenced in spells not exist (outdataed spells) + if(!quest) + continue; + + if(!quest->HasFlag(QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT)) + { + sLog.outErrorDb("Spell (id: %u) have SPELL_EFFECT_QUEST_COMPLETE for quest %u , but quest not have flag QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT. Quest flags must be fixed, quest modified to enable objective.",spellInfo->Id,quest_id); + + // this will prevent quest completing without objective + const_cast(quest)->SetFlag(QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT); + } + } + } + + sLog.outString(); + sLog.outString( ">> Loaded %u quests definitions", mQuestTemplates.size() ); +} + +void ObjectMgr::LoadQuestLocales() +{ + QueryResult *result = WorldDatabase.Query("SELECT entry," + "Title_loc1,Details_loc1,Objectives_loc1,OfferRewardText_loc1,RequestItemsText_loc1,EndText_loc1,ObjectiveText1_loc1,ObjectiveText2_loc1,ObjectiveText3_loc1,ObjectiveText4_loc1," + "Title_loc2,Details_loc2,Objectives_loc2,OfferRewardText_loc2,RequestItemsText_loc2,EndText_loc2,ObjectiveText1_loc2,ObjectiveText2_loc2,ObjectiveText3_loc2,ObjectiveText4_loc2," + "Title_loc3,Details_loc3,Objectives_loc3,OfferRewardText_loc3,RequestItemsText_loc3,EndText_loc3,ObjectiveText1_loc3,ObjectiveText2_loc3,ObjectiveText3_loc3,ObjectiveText4_loc3," + "Title_loc4,Details_loc4,Objectives_loc4,OfferRewardText_loc4,RequestItemsText_loc4,EndText_loc4,ObjectiveText1_loc4,ObjectiveText2_loc4,ObjectiveText3_loc4,ObjectiveText4_loc4," + "Title_loc5,Details_loc5,Objectives_loc5,OfferRewardText_loc5,RequestItemsText_loc5,EndText_loc5,ObjectiveText1_loc5,ObjectiveText2_loc5,ObjectiveText3_loc5,ObjectiveText4_loc5," + "Title_loc6,Details_loc6,Objectives_loc6,OfferRewardText_loc6,RequestItemsText_loc6,EndText_loc6,ObjectiveText1_loc6,ObjectiveText2_loc6,ObjectiveText3_loc6,ObjectiveText4_loc6," + "Title_loc7,Details_loc7,Objectives_loc7,OfferRewardText_loc7,RequestItemsText_loc7,EndText_loc7,ObjectiveText1_loc7,ObjectiveText2_loc7,ObjectiveText3_loc7,ObjectiveText4_loc7," + "Title_loc8,Details_loc8,Objectives_loc8,OfferRewardText_loc8,RequestItemsText_loc8,EndText_loc8,ObjectiveText1_loc8,ObjectiveText2_loc8,ObjectiveText3_loc8,ObjectiveText4_loc8" + " FROM locales_quest" + ); + + if(!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(""); + sLog.outString(">> Loaded 0 Quest locale strings. DB table `locales_quest` is empty."); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 entry = fields[0].GetUInt32(); + + QuestLocale& data = mQuestLocaleMap[entry]; + + for(int i = 1; i < MAX_LOCALE; ++i) + { + std::string str = fields[1+10*(i-1)].GetCppString(); + if(!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if(idx >= 0) + { + if(data.Title.size() <= idx) + data.Title.resize(idx+1); + + data.Title[idx] = str; + } + } + str = fields[1+10*(i-1)+1].GetCppString(); + if(!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if(idx >= 0) + { + if(data.Details.size() <= idx) + data.Details.resize(idx+1); + + data.Details[idx] = str; + } + } + str = fields[1+10*(i-1)+2].GetCppString(); + if(!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if(idx >= 0) + { + if(data.Objectives.size() <= idx) + data.Objectives.resize(idx+1); + + data.Objectives[idx] = str; + } + } + str = fields[1+10*(i-1)+3].GetCppString(); + if(!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if(idx >= 0) + { + if(data.OfferRewardText.size() <= idx) + data.OfferRewardText.resize(idx+1); + + data.OfferRewardText[idx] = str; + } + } + str = fields[1+10*(i-1)+4].GetCppString(); + if(!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if(idx >= 0) + { + if(data.RequestItemsText.size() <= idx) + data.RequestItemsText.resize(idx+1); + + data.RequestItemsText[idx] = str; + } + } + str = fields[1+10*(i-1)+5].GetCppString(); + if(!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if(idx >= 0) + { + if(data.EndText.size() <= idx) + data.EndText.resize(idx+1); + + data.EndText[idx] = str; + } + } + for(int k = 0; k < 4; ++k) + { + str = fields[1+10*(i-1)+6+k].GetCppString(); + if(!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if(idx >= 0) + { + if(data.ObjectiveText[k].size() <= idx) + data.ObjectiveText[k].resize(idx+1); + + data.ObjectiveText[k][idx] = str; + } + } + } + } + } while (result->NextRow()); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u Quest locale strings", mQuestLocaleMap.size() ); +} + +void ObjectMgr::LoadPetCreateSpells() +{ + QueryResult *result = WorldDatabase.PQuery("SELECT entry, Spell1, Spell2, Spell3, Spell4 FROM petcreateinfo_spell"); + if(!result) + { + barGoLink bar( 1 ); + bar.step(); + + sLog.outString(); + sLog.outString( ">> Loaded 0 pet create spells" ); + sLog.outErrorDb("`petcreateinfo_spell` table is empty!"); + return; + } + + uint32 count = 0; + + barGoLink bar( result->GetRowCount() ); + + mPetCreateSpell.clear(); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 creature_id = fields[0].GetUInt32(); + + if(!creature_id || !sCreatureStorage.LookupEntry(creature_id)) + continue; + + PetCreateSpellEntry PetCreateSpell; + for(int i = 0; i < 4; i++) + { + PetCreateSpell.spellid[i] = fields[i + 1].GetUInt32(); + + if(PetCreateSpell.spellid[i] && !sSpellStore.LookupEntry(PetCreateSpell.spellid[i])) + sLog.outErrorDb("Spell %u listed in `petcreateinfo_spell` does not exist",PetCreateSpell.spellid[i]); + } + + mPetCreateSpell[creature_id] = PetCreateSpell; + + ++count; + } + while (result->NextRow()); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u pet create spells", count ); +} + +void ObjectMgr::LoadScripts(ScriptMapMap& scripts, char const* tablename) +{ + if(sWorld.IsScriptScheduled()) // function don't must be called in time scripts use. + return; + + sLog.outString( "%s :", tablename); + + scripts.clear(); // need for reload support + + QueryResult *result = WorldDatabase.PQuery( "SELECT id,delay,command,datalong,datalong2,datatext, x, y, z, o FROM %s", tablename ); + + uint32 count = 0; + + if( !result ) + { + barGoLink bar( 1 ); + bar.step(); + + sLog.outString(); + sLog.outString( ">> Loaded %u script definitions", count ); + return; + } + + barGoLink bar( result->GetRowCount() ); + + do + { + bar.step(); + + Field *fields = result->Fetch(); + ScriptInfo tmp; + tmp.id = fields[0].GetUInt32(); + tmp.delay = fields[1].GetUInt32(); + tmp.command = fields[2].GetUInt32(); + tmp.datalong = fields[3].GetUInt32(); + tmp.datalong2 = fields[4].GetUInt32(); + tmp.datatext = fields[5].GetCppString(); + tmp.x = fields[6].GetFloat(); + tmp.y = fields[7].GetFloat(); + tmp.z = fields[8].GetFloat(); + tmp.o = fields[9].GetFloat(); + + // generic command args check + switch(tmp.command) + { + case SCRIPT_COMMAND_TALK: + { + if(tmp.datalong > 3) + { + sLog.outErrorDb("Table `%s` has invalid talk type (datalong = %u) in SCRIPT_COMMAND_TALK for script id %u",tablename,tmp.datalong,tmp.id); + continue; + } + break; + } + + case SCRIPT_COMMAND_TELEPORT_TO: + { + if(!sMapStore.LookupEntry(tmp.datalong)) + { + sLog.outErrorDb("Table `%s` has invalid map (Id: %u) in SCRIPT_COMMAND_TELEPORT_TO for script id %u",tablename,tmp.datalong,tmp.id); + continue; + } + + if(!MaNGOS::IsValidMapCoord(tmp.x,tmp.y,tmp.z,tmp.o)) + { + sLog.outErrorDb("Table `%s` has invalid coordinates (X: %f Y: %f) in SCRIPT_COMMAND_TELEPORT_TO for script id %u",tablename,tmp.x,tmp.y,tmp.id); + continue; + } + break; + } + + case SCRIPT_COMMAND_TEMP_SUMMON_CREATURE: + { + if(!MaNGOS::IsValidMapCoord(tmp.x,tmp.y,tmp.z,tmp.o)) + { + sLog.outErrorDb("Table `%s` has invalid coordinates (X: %f Y: %f) in SCRIPT_COMMAND_TEMP_SUMMON_CREATURE for script id %u",tablename,tmp.x,tmp.y,tmp.id); + continue; + } + + if(!GetCreatureTemplate(tmp.datalong)) + { + sLog.outErrorDb("Table `%s` has invalid creature (Entry: %u) in SCRIPT_COMMAND_TEMP_SUMMON_CREATURE for script id %u",tablename,tmp.datalong,tmp.id); + continue; + } + break; + } + + case SCRIPT_COMMAND_RESPAWN_GAMEOBJECT: + { + GameObjectData const* data = GetGOData(tmp.datalong); + if(!data) + { + sLog.outErrorDb("Table `%s` has invalid gameobject (GUID: %u) in SCRIPT_COMMAND_RESPAWN_GAMEOBJECT for script id %u",tablename,tmp.datalong,tmp.id); + continue; + } + + GameObjectInfo const* info = GetGameObjectInfo(data->id); + if(!info) + { + sLog.outErrorDb("Table `%s` has gameobject with invalid entry (GUID: %u Entry: %u) in SCRIPT_COMMAND_RESPAWN_GAMEOBJECT for script id %u",tablename,tmp.datalong,data->id,tmp.id); + continue; + } + + if( info->type==GAMEOBJECT_TYPE_FISHINGNODE || + info->type==GAMEOBJECT_TYPE_FISHINGHOLE || + info->type==GAMEOBJECT_TYPE_DOOR || + info->type==GAMEOBJECT_TYPE_BUTTON || + info->type==GAMEOBJECT_TYPE_TRAP ) + { + sLog.outErrorDb("Table `%s` have gameobject type (%u) unsupported by command SCRIPT_COMMAND_RESPAWN_GAMEOBJECT for script id %u",tablename,info->id,tmp.id); + continue; + } + break; + } + case SCRIPT_COMMAND_OPEN_DOOR: + case SCRIPT_COMMAND_CLOSE_DOOR: + { + GameObjectData const* data = GetGOData(tmp.datalong); + if(!data) + { + sLog.outErrorDb("Table `%s` has invalid gameobject (GUID: %u) in %s for script id %u",tablename,tmp.datalong,(tmp.command==SCRIPT_COMMAND_OPEN_DOOR ? "SCRIPT_COMMAND_OPEN_DOOR" : "SCRIPT_COMMAND_CLOSE_DOOR"),tmp.id); + continue; + } + + GameObjectInfo const* info = GetGameObjectInfo(data->id); + if(!info) + { + sLog.outErrorDb("Table `%s` has gameobject with invalid entry (GUID: %u Entry: %u) in %s for script id %u",tablename,tmp.datalong,data->id,(tmp.command==SCRIPT_COMMAND_OPEN_DOOR ? "SCRIPT_COMMAND_OPEN_DOOR" : "SCRIPT_COMMAND_CLOSE_DOOR"),tmp.id); + continue; + } + + if( info->type!=GAMEOBJECT_TYPE_DOOR) + { + sLog.outErrorDb("Table `%s` has gameobject type (%u) non supported by command %s for script id %u",tablename,info->id,(tmp.command==SCRIPT_COMMAND_OPEN_DOOR ? "SCRIPT_COMMAND_OPEN_DOOR" : "SCRIPT_COMMAND_CLOSE_DOOR"),tmp.id); + continue; + } + + break; + } + case SCRIPT_COMMAND_QUEST_EXPLORED: + { + Quest const* quest = objmgr.GetQuestTemplate(tmp.datalong); + if(!quest) + { + sLog.outErrorDb("Table `%s` has invalid quest (ID: %u) in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u",tablename,tmp.datalong,tmp.id); + continue; + } + + if(!quest->HasFlag(QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT)) + { + sLog.outErrorDb("Table `%s` has quest (ID: %u) in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u, but quest not have flag QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT in quest flags. Script command or quest flags wrong. Quest modified to require objective.",tablename,tmp.datalong,tmp.id); + + // this will prevent quest completing without objective + const_cast(quest)->SetFlag(QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT); + + // continue; - quest objective requiremet set and command can be allowed + } + + if(float(tmp.datalong2) > DEFAULT_VISIBILITY_DISTANCE) + { + sLog.outErrorDb("Table `%s` has too large distance (%u) for exploring objective complete in `datalong2` in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u",tablename,tmp.datalong2,tmp.id); + continue; + } + + if(tmp.datalong2 && float(tmp.datalong2) > DEFAULT_VISIBILITY_DISTANCE) + { + sLog.outErrorDb("Table `%s` has too large distance (%u) for exploring objective complete in `datalong2` in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u, max distance is %u or 0 for disable distance check",tablename,tmp.datalong2,tmp.id,uint32(DEFAULT_VISIBILITY_DISTANCE)); + continue; + } + + if(tmp.datalong2 && float(tmp.datalong2) < INTERACTION_DISTANCE) + { + sLog.outErrorDb("Table `%s` has too small distance (%u) for exploring objective complete in `datalong2` in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u, min distance is %u or 0 for disable distance check",tablename,tmp.datalong2,tmp.id,uint32(INTERACTION_DISTANCE)); + continue; + } + + break; + } + + case SCRIPT_COMMAND_REMOVE_AURA: + case SCRIPT_COMMAND_CAST_SPELL: + { + if(!sSpellStore.LookupEntry(tmp.datalong)) + { + sLog.outErrorDb("Table `%s` using non-existent spell (id: %u) in SCRIPT_COMMAND_REMOVE_AURA or SCRIPT_COMMAND_CAST_SPELL for script id %u",tablename,tmp.datalong,tmp.id); + continue; + } + break; + } + } + + if (scripts.find(tmp.id) == scripts.end()) + { + ScriptMap emptyMap; + scripts[tmp.id] = emptyMap; + } + scripts[tmp.id].insert(std::pair(tmp.delay, tmp)); + + ++count; + } while( result->NextRow() ); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u script definitions", count ); +} + +void ObjectMgr::LoadGameObjectScripts() +{ + LoadScripts(sGameObjectScripts, "gameobject_scripts"); + + // check ids + for(ScriptMapMap::const_iterator itr = sGameObjectScripts.begin(); itr != sGameObjectScripts.end(); ++itr) + { + if(!GetGOData(itr->first)) + sLog.outErrorDb("Table `gameobject_scripts` has not existing gameobject (GUID: %u) as script id",itr->first); + } +} + +void ObjectMgr::LoadQuestEndScripts() +{ + objmgr.LoadScripts(sQuestEndScripts, "quest_end_scripts"); + + // check ids + for(ScriptMapMap::const_iterator itr = sQuestEndScripts.begin(); itr != sQuestEndScripts.end(); ++itr) + { + if(!GetQuestTemplate(itr->first)) + sLog.outErrorDb("Table `quest_end_scripts` has not existing quest (Id: %u) as script id",itr->first); + } +} + +void ObjectMgr::LoadQuestStartScripts() +{ + objmgr.LoadScripts(sQuestStartScripts,"quest_start_scripts"); + + // check ids + for(ScriptMapMap::const_iterator itr = sQuestStartScripts.begin(); itr != sQuestStartScripts.end(); ++itr) + { + if(!GetQuestTemplate(itr->first)) + sLog.outErrorDb("Table `quest_start_scripts` has not existing quest (Id: %u) as script id",itr->first); + } +} + +void ObjectMgr::LoadSpellScripts() +{ + objmgr.LoadScripts(sSpellScripts, "spell_scripts"); + + // check ids + for(ScriptMapMap::const_iterator itr = sSpellScripts.begin(); itr != sSpellScripts.end(); ++itr) + { + SpellEntry const* spellInfo = sSpellStore.LookupEntry(itr->first); + + if(!spellInfo) + { + sLog.outErrorDb("Table `spell_scripts` has not existing spell (Id: %u) as script id",itr->first); + continue; + } + + //check for correct spellEffect + bool found = false; + for(int i=0; i<3; ++i) + { + // skip empty effects + if( !spellInfo->Effect[i] ) + continue; + + if( spellInfo->Effect[i] == SPELL_EFFECT_SCRIPT_EFFECT ) + { + found = true; + break; + } + } + + if(!found) + sLog.outErrorDb("Table `spell_scripts` has unsupported spell (Id: %u) without SPELL_EFFECT_SCRIPT_EFFECT (%u) spell effect",itr->first,SPELL_EFFECT_SCRIPT_EFFECT); + } +} + +void ObjectMgr::LoadEventScripts() +{ + objmgr.LoadScripts(sEventScripts, "event_scripts"); + + std::set evt_scripts; + // Load all possible script entries from gameobjects + for(uint32 i = 1; i < sGOStorage.MaxEntry; ++i) + { + GameObjectInfo const * goInfo = sGOStorage.LookupEntry(i); + if (goInfo) + { + switch(goInfo->type) + { + case GAMEOBJECT_TYPE_GOOBER: + if(goInfo->goober.eventId) + evt_scripts.insert(goInfo->goober.eventId); + break; + case GAMEOBJECT_TYPE_CHEST: + if(goInfo->chest.eventId) + evt_scripts.insert(goInfo->chest.eventId); + break; + default: + break; + } + } + } + // Load all possible script entries from spells + for(uint32 i = 1; i < sSpellStore.GetNumRows(); ++i) + { + SpellEntry const * spell = sSpellStore.LookupEntry(i); + if (spell) + { + for(int j=0; j<3; ++j) + { + if( spell->Effect[j] == SPELL_EFFECT_SEND_EVENT ) + { + if (spell->EffectMiscValue[j]) + evt_scripts.insert(spell->EffectMiscValue[j]); + } + } + } + } + // Then check if all scripts are in above list of possible script entries + for(ScriptMapMap::const_iterator itr = sEventScripts.begin(); itr != sEventScripts.end(); ++itr) + { + std::set::const_iterator itr2 = evt_scripts.find(itr->first); + if (itr2 == evt_scripts.end()) + sLog.outErrorDb("Table `event_scripts` has script (Id: %u) not refering to any gameobject_template type 10 data2 field or type 3 data6 field or any spell effect %u", itr->first, SPELL_EFFECT_SEND_EVENT); + } +} + +void ObjectMgr::LoadItemTexts() +{ + QueryResult *result = CharacterDatabase.PQuery("SELECT id, text FROM item_text"); + + uint32 count = 0; + + if( !result ) + { + barGoLink bar( 1 ); + bar.step(); + + sLog.outString(); + sLog.outString( ">> Loaded %u item pages", count ); + return; + } + + barGoLink bar( result->GetRowCount() ); + + Field* fields; + do + { + bar.step(); + + fields = result->Fetch(); + + mItemTexts[ fields[0].GetUInt32() ] = fields[1].GetCppString(); + + ++count; + + } while ( result->NextRow() ); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u item texts", count ); +} + +void ObjectMgr::LoadPageTexts() +{ + sPageTextStore.Free(); // for reload case + + sPageTextStore.Load(); + sLog.outString( ">> Loaded %u page texts", sPageTextStore.RecordCount ); + sLog.outString(); + + for(uint32 i = 1; i < sPageTextStore.MaxEntry; ++i) + { + // check data correctness + PageText const* page = sPageTextStore.LookupEntry(i); + if(!page) + continue; + + if(page->Next_Page && !sPageTextStore.LookupEntry(page->Next_Page)) + { + sLog.outErrorDb("Page text (Id: %u) has not existing next page (Id:%u)", i,page->Next_Page); + continue; + } + + // detect circular reference + std::set checkedPages; + for(PageText const* pageItr = page; pageItr; pageItr = sPageTextStore.LookupEntry(pageItr->Next_Page)) + { + if(!pageItr->Next_Page) + break; + checkedPages.insert(pageItr->Page_ID); + if(checkedPages.find(pageItr->Next_Page)!=checkedPages.end()) + { + std::ostringstream ss; + ss<< "The text page(s) "; + for (std::set::iterator itr= checkedPages.begin();itr!=checkedPages.end(); itr++) + ss << *itr << " "; + ss << "create(s) a circular reference, which can cause the server to freeze. Changing Next_Page of page " + << pageItr->Page_ID <<" to 0"; + sLog.outErrorDb(ss.str().c_str()); + const_cast(pageItr)->Next_Page = 0; + break; + } + } + } +} + +void ObjectMgr::LoadPageTextLocales() +{ + QueryResult *result = WorldDatabase.PQuery("SELECT entry,text_loc1,text_loc2,text_loc3,text_loc4,text_loc5,text_loc6,text_loc7,text_loc8 FROM locales_page_text"); + + if(!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(""); + sLog.outString(">> Loaded 0 PageText locale strings. DB table `locales_page_text` is empty."); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 entry = fields[0].GetUInt32(); + + PageTextLocale& data = mPageTextLocaleMap[entry]; + + for(int i = 1; i < MAX_LOCALE; ++i) + { + std::string str = fields[i].GetCppString(); + if(str.empty()) + continue; + + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if(idx >= 0) + { + if(data.Text.size() <= idx) + data.Text.resize(idx+1); + + data.Text[idx] = str; + } + } + + } while (result->NextRow()); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u PageText locale strings", mPageTextLocaleMap.size() ); +} + +void ObjectMgr::LoadInstanceTemplate() +{ + sInstanceTemplate.Load(); + + for(uint32 i = 0; i < sInstanceTemplate.MaxEntry; i++) + { + InstanceTemplate* temp = (InstanceTemplate*)GetInstanceTemplate(i); + if(!temp) continue; + const MapEntry* entry = sMapStore.LookupEntry(temp->map); + if(!entry) + { + sLog.outErrorDb("ObjectMgr::LoadInstanceTemplate: bad mapid %d for template!", temp->map); + continue; + } + else if(!entry->HasResetTime()) + continue; + + if(temp->reset_delay == 0) + { + // use defaults from the DBC + if(entry->SupportsHeroicMode()) + { + temp->reset_delay = entry->resetTimeHeroic / DAY; + } + else if (entry->resetTimeRaid && entry->map_type == MAP_RAID) + { + temp->reset_delay = entry->resetTimeRaid / DAY; + } + } + + // the reset_delay must be atleast one day + temp->reset_delay = std::max((uint32)1, (uint32)(temp->reset_delay * sWorld.getRate(RATE_INSTANCE_RESET_TIME))); + } + + sLog.outString( ">> Loaded %u Instance Template definitions", sInstanceTemplate.RecordCount ); + sLog.outString(); +} + +void ObjectMgr::AddGossipText(GossipText *pGText) +{ + ASSERT( pGText->Text_ID ); + ASSERT( mGossipText.find(pGText->Text_ID) == mGossipText.end() ); + mGossipText[pGText->Text_ID] = pGText; +} + +GossipText *ObjectMgr::GetGossipText(uint32 Text_ID) +{ + GossipTextMap::const_iterator itr; + for (itr = mGossipText.begin(); itr != mGossipText.end(); itr++) + { + if(itr->second->Text_ID == Text_ID) + return itr->second; + } + return NULL; +} + +void ObjectMgr::LoadGossipText() +{ + GossipText *pGText; + QueryResult *result = WorldDatabase.Query( "SELECT * FROM npc_text" ); + + int count = 0; + if( !result ) + { + barGoLink bar( 1 ); + bar.step(); + + sLog.outString(); + sLog.outString( ">> Loaded %u npc texts", count ); + return; + } + + int cic; + + barGoLink bar( result->GetRowCount() ); + + do + { + ++count; + cic = 0; + + Field *fields = result->Fetch(); + + bar.step(); + + pGText = new GossipText; + pGText->Text_ID = fields[cic++].GetUInt32(); + + for (int i=0; i< 8; i++) + { + pGText->Options[i].Text_0 = fields[cic++].GetCppString(); + pGText->Options[i].Text_1 = fields[cic++].GetCppString(); + + pGText->Options[i].Language = fields[cic++].GetUInt32(); + pGText->Options[i].Probability = fields[cic++].GetFloat(); + + pGText->Options[i].Emotes[0]._Delay = fields[cic++].GetUInt32(); + pGText->Options[i].Emotes[0]._Emote = fields[cic++].GetUInt32(); + + pGText->Options[i].Emotes[1]._Delay = fields[cic++].GetUInt32(); + pGText->Options[i].Emotes[1]._Emote = fields[cic++].GetUInt32(); + + pGText->Options[i].Emotes[2]._Delay = fields[cic++].GetUInt32(); + pGText->Options[i].Emotes[2]._Emote = fields[cic++].GetUInt32(); + } + + if ( !pGText->Text_ID ) continue; + AddGossipText( pGText ); + + } while( result->NextRow() ); + + sLog.outString(); + sLog.outString( ">> Loaded %u npc texts", count ); + delete result; +} + +void ObjectMgr::LoadNpcTextLocales() +{ + QueryResult *result = WorldDatabase.Query("SELECT entry," + "Text0_0_loc1,Text0_1_loc1,Text1_0_loc1,Text1_1_loc1,Text2_0_loc1,Text2_1_loc1,Text3_0_loc1,Text3_1_loc1,Text4_0_loc1,Text4_1_loc1,Text5_0_loc1,Text5_1_loc1,Text6_0_loc1,Text6_1_loc1,Text7_0_loc1,Text7_1_loc1," + "Text0_0_loc2,Text0_1_loc2,Text1_0_loc2,Text1_1_loc2,Text2_0_loc2,Text2_1_loc2,Text3_0_loc2,Text3_1_loc1,Text4_0_loc2,Text4_1_loc2,Text5_0_loc2,Text5_1_loc2,Text6_0_loc2,Text6_1_loc2,Text7_0_loc2,Text7_1_loc2," + "Text0_0_loc3,Text0_1_loc3,Text1_0_loc3,Text1_1_loc3,Text2_0_loc3,Text2_1_loc3,Text3_0_loc3,Text3_1_loc1,Text4_0_loc3,Text4_1_loc3,Text5_0_loc3,Text5_1_loc3,Text6_0_loc3,Text6_1_loc3,Text7_0_loc3,Text7_1_loc3," + "Text0_0_loc4,Text0_1_loc4,Text1_0_loc4,Text1_1_loc4,Text2_0_loc4,Text2_1_loc4,Text3_0_loc4,Text3_1_loc1,Text4_0_loc4,Text4_1_loc4,Text5_0_loc4,Text5_1_loc4,Text6_0_loc4,Text6_1_loc4,Text7_0_loc4,Text7_1_loc4," + "Text0_0_loc5,Text0_1_loc5,Text1_0_loc5,Text1_1_loc5,Text2_0_loc5,Text2_1_loc5,Text3_0_loc5,Text3_1_loc1,Text4_0_loc5,Text4_1_loc5,Text5_0_loc5,Text5_1_loc5,Text6_0_loc5,Text6_1_loc5,Text7_0_loc5,Text7_1_loc5," + "Text0_0_loc6,Text0_1_loc6,Text1_0_loc6,Text1_1_loc6,Text2_0_loc6,Text2_1_loc6,Text3_0_loc6,Text3_1_loc1,Text4_0_loc6,Text4_1_loc6,Text5_0_loc6,Text5_1_loc6,Text6_0_loc6,Text6_1_loc6,Text7_0_loc6,Text7_1_loc6," + "Text0_0_loc7,Text0_1_loc7,Text1_0_loc7,Text1_1_loc7,Text2_0_loc7,Text2_1_loc7,Text3_0_loc7,Text3_1_loc1,Text4_0_loc7,Text4_1_loc7,Text5_0_loc7,Text5_1_loc7,Text6_0_loc7,Text6_1_loc7,Text7_0_loc7,Text7_1_loc7, " + "Text0_0_loc8,Text0_1_loc8,Text1_0_loc8,Text1_1_loc8,Text2_0_loc8,Text2_1_loc8,Text3_0_loc8,Text3_1_loc1,Text4_0_loc8,Text4_1_loc8,Text5_0_loc8,Text5_1_loc8,Text6_0_loc8,Text6_1_loc8,Text7_0_loc8,Text7_1_loc8 " + " FROM locales_npc_text"); + + if(!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(""); + sLog.outString(">> Loaded 0 Quest locale strings. DB table `locales_npc_text` is empty."); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 entry = fields[0].GetUInt32(); + + NpcTextLocale& data = mNpcTextLocaleMap[entry]; + + for(int i=1; i= 0) + { + if(data.Text_0[j].size() <= idx) + data.Text_0[j].resize(idx+1); + + data.Text_0[j][idx] = str0; + } + } + std::string str1 = fields[1+8*2*(i-1)+2*j+1].GetCppString(); + if(!str1.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if(idx >= 0) + { + if(data.Text_1[j].size() <= idx) + data.Text_1[j].resize(idx+1); + + data.Text_1[j][idx] = str1; + } + } + } + } + } while (result->NextRow()); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u NpcText locale strings", mNpcTextLocaleMap.size() ); +} + +//not very fast function but it is called only once a day, or on starting-up +void ObjectMgr::ReturnOrDeleteOldMails(bool serverUp) +{ + time_t basetime = time(NULL); + sLog.outDebug("Returning mails current time: hour: %d, minute: %d, second: %d ", localtime(&basetime)->tm_hour, localtime(&basetime)->tm_min, localtime(&basetime)->tm_sec); + //delete all old mails without item and without body immediately, if starting server + if (!serverUp) + CharacterDatabase.PExecute("DELETE FROM mail WHERE expire_time < '" I64FMTD "' AND has_items = '0' AND itemTextId = 0", (uint64)basetime); + // 0 1 2 3 4 5 6 7 8 9 + QueryResult* result = CharacterDatabase.PQuery("SELECT id,messageType,sender,receiver,itemTextId,has_items,expire_time,cod,checked,mailTemplateId FROM mail WHERE expire_time < '" I64FMTD "'", (uint64)basetime); + if ( !result ) + return; // any mails need to be returned or deleted + Field *fields; + //std::ostringstream delitems, delmails; //will be here for optimization + //bool deletemail = false, deleteitem = false; + //delitems << "DELETE FROM item_instance WHERE guid IN ( "; + //delmails << "DELETE FROM mail WHERE id IN ( " + do + { + fields = result->Fetch(); + Mail *m = new Mail; + m->messageID = fields[0].GetUInt32(); + m->messageType = fields[1].GetUInt8(); + m->sender = fields[2].GetUInt32(); + m->receiver = fields[3].GetUInt32(); + m->itemTextId = fields[4].GetUInt32(); + bool has_items = fields[5].GetBool(); + m->expire_time = (time_t)fields[6].GetUInt64(); + m->deliver_time = 0; + m->COD = fields[7].GetUInt32(); + m->checked = fields[8].GetUInt32(); + m->mailTemplateId = fields[9].GetInt16(); + + Player *pl = 0; + if (serverUp) + pl = objmgr.GetPlayer((uint64)m->receiver); + if (pl && pl->m_mailsLoaded) + { //this code will run very improbably (the time is between 4 and 5 am, in game is online a player, who has old mail + //his in mailbox and he has already listed his mails ) + delete m; + continue; + } + //delete or return mail: + if (has_items) + { + QueryResult *resultItems = CharacterDatabase.PQuery("SELECT item_guid,item_template FROM mail_items WHERE mail_id='%u'", m->messageID); + if(resultItems) + { + do + { + Field *fields2 = resultItems->Fetch(); + + uint32 item_guid_low = fields2[0].GetUInt32(); + uint32 item_template = fields2[1].GetUInt32(); + + m->AddItem(item_guid_low, item_template); + } + while (resultItems->NextRow()); + + delete resultItems; + } + //if it is mail from AH, it shouldn't be returned, but deleted + if (m->messageType != MAIL_NORMAL || (m->checked & (MAIL_CHECK_MASK_AUCTION | MAIL_CHECK_MASK_COD_PAYMENT | MAIL_CHECK_MASK_RETURNED))) + { + // mail open and then not returned + for(std::vector::iterator itr2 = m->items.begin(); itr2 != m->items.end(); ++itr2) + CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid = '%u'", itr2->item_guid); + } + else + { + //mail will be returned: + CharacterDatabase.PExecute("UPDATE mail SET sender = '%u', receiver = '%u', expire_time = '" I64FMTD "', deliver_time = '" I64FMTD "',cod = '0', checked = '%u' WHERE id = '%u'", m->receiver, m->sender, (uint64)(basetime + 30*DAY), (uint64)basetime, MAIL_CHECK_MASK_RETURNED, m->messageID); + delete m; + continue; + } + } + + if (m->itemTextId) + CharacterDatabase.PExecute("DELETE FROM item_text WHERE id = '%u'", m->itemTextId); + + //deletemail = true; + //delmails << m->messageID << ", "; + CharacterDatabase.PExecute("DELETE FROM mail WHERE id = '%u'", m->messageID); + delete m; + } while (result->NextRow()); + delete result; +} + +void ObjectMgr::LoadQuestAreaTriggers() +{ + mQuestAreaTriggerMap.clear(); // need for reload case + + QueryResult *result = WorldDatabase.Query( "SELECT id,quest FROM areatrigger_involvedrelation" ); + + uint32 count = 0; + + if( !result ) + { + barGoLink bar( 1 ); + bar.step(); + + sLog.outString(); + sLog.outString( ">> Loaded %u quest trigger points", count ); + return; + } + + barGoLink bar( result->GetRowCount() ); + + do + { + ++count; + bar.step(); + + Field *fields = result->Fetch(); + + uint32 trigger_ID = fields[0].GetUInt32(); + uint32 quest_ID = fields[1].GetUInt32(); + + AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(trigger_ID); + if(!atEntry) + { + sLog.outErrorDb("Area trigger (ID:%u) does not exist in `AreaTrigger.dbc`.",trigger_ID); + continue; + } + + Quest const* quest = GetQuestTemplate(quest_ID); + + if(!quest) + { + sLog.outErrorDb("Table `areatrigger_involvedrelation` has record (id: %u) for not existing quest %u",trigger_ID,quest_ID); + continue; + } + + if(!quest->HasFlag(QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT)) + { + sLog.outErrorDb("Table `areatrigger_involvedrelation` has record (id: %u) for not quest %u, but quest not have flag QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT. Trigger or quest flags must be fixed, quest modified to require objective.",trigger_ID,quest_ID); + + // this will prevent quest completing without objective + const_cast(quest)->SetFlag(QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT); + + // continue; - quest modified to required obkective and trigger can be allowed. + } + + mQuestAreaTriggerMap[trigger_ID] = quest_ID; + + } while( result->NextRow() ); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u quest trigger points", count ); +} + +void ObjectMgr::LoadTavernAreaTriggers() +{ + mTavernAreaTriggerSet.clear(); // need for reload case + + QueryResult *result = WorldDatabase.Query("SELECT id FROM areatrigger_tavern"); + + uint32 count = 0; + + if( !result ) + { + barGoLink bar( 1 ); + bar.step(); + + sLog.outString(); + sLog.outString( ">> Loaded %u tavern triggers", count ); + return; + } + + barGoLink bar( result->GetRowCount() ); + + do + { + ++count; + bar.step(); + + Field *fields = result->Fetch(); + + uint32 Trigger_ID = fields[0].GetUInt32(); + + AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(Trigger_ID); + if(!atEntry) + { + sLog.outErrorDb("Area trigger (ID:%u) does not exist in `AreaTrigger.dbc`.",Trigger_ID); + continue; + } + + mTavernAreaTriggerSet.insert(Trigger_ID); + } while( result->NextRow() ); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u tavern triggers", count ); +} + +void ObjectMgr::LoadAreaTriggerScripts() +{ + mAreaTriggerScripts.clear(); // need for reload case + QueryResult *result = WorldDatabase.Query("SELECT entry, ScriptName FROM areatrigger_scripts"); + + uint32 count = 0; + + if( !result ) + { + barGoLink bar( 1 ); + bar.step(); + + sLog.outString(); + sLog.outString( ">> Loaded %u areatrigger scripts", count ); + return; + } + + barGoLink bar( result->GetRowCount() ); + + do + { + ++count; + bar.step(); + + Field *fields = result->Fetch(); + + uint32 Trigger_ID = fields[0].GetUInt32(); + std::string scriptName = fields[1].GetCppString(); + + AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(Trigger_ID); + if(!atEntry) + { + sLog.outErrorDb("Area trigger (ID:%u) does not exist in `AreaTrigger.dbc`.",Trigger_ID); + continue; + } + mAreaTriggerScripts[Trigger_ID] = scriptName; + } while( result->NextRow() ); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u areatrigger scripts", count ); +} +uint32 ObjectMgr::GetNearestTaxiNode( float x, float y, float z, uint32 mapid ) +{ + bool found = false; + float dist; + uint32 id = 0; + + for(uint32 i = 1; i < sTaxiNodesStore.GetNumRows(); ++i) + { + TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(i); + if(node && node->map_id == mapid) + { + float dist2 = (node->x - x)*(node->x - x)+(node->y - y)*(node->y - y)+(node->z - z)*(node->z - z); + if(found) + { + if(dist2 < dist) + { + dist = dist2; + id = i; + } + } + else + { + found = true; + dist = dist2; + id = i; + } + } + } + + return id; +} + +void ObjectMgr::GetTaxiPath( uint32 source, uint32 destination, uint32 &path, uint32 &cost) +{ + TaxiPathSetBySource::iterator src_i = sTaxiPathSetBySource.find(source); + if(src_i==sTaxiPathSetBySource.end()) + { + path = 0; + cost = 0; + return; + } + + TaxiPathSetForSource& pathSet = src_i->second; + + TaxiPathSetForSource::iterator dest_i = pathSet.find(destination); + if(dest_i==pathSet.end()) + { + path = 0; + cost = 0; + return; + } + + cost = dest_i->second.price; + path = dest_i->second.ID; +} + +uint16 ObjectMgr::GetTaxiMount( uint32 id, uint32 team ) +{ + uint16 mount_entry = 0; + uint16 mount_id = 0; + + TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(id); + if(node) + { + if (team == ALLIANCE) + { + mount_entry = node->alliance_mount_type; + CreatureInfo const *ci = objmgr.GetCreatureTemplate(mount_entry); + if(ci) + mount_id = ci->DisplayID_A; + } + if (team == HORDE) + { + mount_entry = node->horde_mount_type; + CreatureInfo const *ci = objmgr.GetCreatureTemplate(mount_entry); + if(ci) + mount_id = ci->DisplayID_H; + } + } + + CreatureModelInfo const *minfo = objmgr.GetCreatureModelInfo(mount_id); + if(!minfo) + { + sLog.outErrorDb("Taxi mount (Entry: %u) for taxi node (Id: %u) for team %u has model %u not found in table `creature_model_info`, can't load. ", + mount_entry,id,team,mount_id); + + return false; + } + if(minfo->modelid_other_gender!=0) + mount_id = urand(0,1) ? mount_id : minfo->modelid_other_gender; + + return mount_id; +} + +void ObjectMgr::GetTaxiPathNodes( uint32 path, Path &pathnodes, std::vector& mapIds) +{ + if(path >= sTaxiPathNodesByPath.size()) + return; + + TaxiPathNodeList& nodeList = sTaxiPathNodesByPath[path]; + + pathnodes.Resize(nodeList.size()); + mapIds.resize(nodeList.size()); + + for(size_t i = 0; i < nodeList.size(); ++i) + { + pathnodes[ i ].x = nodeList[i].x; + pathnodes[ i ].y = nodeList[i].y; + pathnodes[ i ].z = nodeList[i].z; + + mapIds[i] = nodeList[i].mapid; + } +} + +void ObjectMgr::GetTransportPathNodes( uint32 path, TransportPath &pathnodes ) +{ + if(path >= sTaxiPathNodesByPath.size()) + return; + + TaxiPathNodeList& nodeList = sTaxiPathNodesByPath[path]; + + pathnodes.Resize(nodeList.size()); + + for(size_t i = 0; i < nodeList.size(); ++i) + { + pathnodes[ i ].mapid = nodeList[i].mapid; + pathnodes[ i ].x = nodeList[i].x; + pathnodes[ i ].y = nodeList[i].y; + pathnodes[ i ].z = nodeList[i].z; + pathnodes[ i ].actionFlag = nodeList[i].actionFlag; + pathnodes[ i ].delay = nodeList[i].delay; + } +} + +void ObjectMgr::LoadGraveyardZones() +{ + mGraveYardMap.clear(); // need for reload case + + QueryResult *result = WorldDatabase.Query("SELECT id,ghost_zone,faction FROM game_graveyard_zone"); + + uint32 count = 0; + + if( !result ) + { + barGoLink bar( 1 ); + bar.step(); + + sLog.outString(); + sLog.outString( ">> Loaded %u graveyard-zone links", count ); + return; + } + + barGoLink bar( result->GetRowCount() ); + + do + { + ++count; + bar.step(); + + Field *fields = result->Fetch(); + + uint32 safeLocId = fields[0].GetUInt32(); + uint32 zoneId = fields[1].GetUInt32(); + uint32 team = fields[2].GetUInt32(); + + WorldSafeLocsEntry const* entry = sWorldSafeLocsStore.LookupEntry(safeLocId); + if(!entry) + { + sLog.outErrorDb("Table `game_graveyard_zone` has record for not existing graveyard (WorldSafeLocs.dbc id) %u, skipped.",safeLocId); + continue; + } + + AreaTableEntry const *areaEntry = GetAreaEntryByAreaID(zoneId); + if(!areaEntry) + { + sLog.outErrorDb("Table `game_graveyard_zone` has record for not existing zone id (%u), skipped.",zoneId); + continue; + } + + if(areaEntry->zone != 0) + { + sLog.outErrorDb("Table `game_graveyard_zone` has record subzone id (%u) instead of zone, skipped.",zoneId); + continue; + } + + if(team!=0 && team!=HORDE && team!=ALLIANCE) + { + sLog.outErrorDb("Table `game_graveyard_zone` has record for non player faction (%u), skipped.",team); + continue; + } + + if(entry->map_id != areaEntry->mapid && team != 0) + { + sLog.outErrorDb("Table `game_graveyard_zone` has record for ghost zone (%u) at map %u and graveyard (%u) at map %u for team %u, but in case maps are different, player faction setting is ignored. Use faction 0 instead.",zoneId,areaEntry->mapid, safeLocId, entry->map_id, team); + team = 0; + } + + if(!AddGraveYardLink(safeLocId,zoneId,team,false)) + sLog.outErrorDb("Table `game_graveyard_zone` has a duplicate record for Garveyard (ID: %u) and Zone (ID: %u), skipped.",safeLocId,zoneId); + } while( result->NextRow() ); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u graveyard-zone links", count ); +} + +WorldSafeLocsEntry const *ObjectMgr::GetClosestGraveYard(float x, float y, float z, uint32 MapId, uint32 team) +{ + // search for zone associated closest graveyard + uint32 zoneId = MapManager::Instance().GetZoneId(MapId,x,y); + + // Simulate std. algorithm: + // found some graveyard associated to (ghost_zone,ghost_map) + // + // if mapId == graveyard.mapId (ghost in plain zone or city or battleground) and search graveyard at same map + // then check faction + // if mapId != graveyard.mapId (ghost in instance) and search any graveyard associated + // then skip check faction + GraveYardMap::const_iterator graveLow = mGraveYardMap.lower_bound(zoneId); + GraveYardMap::const_iterator graveUp = mGraveYardMap.upper_bound(zoneId); + if(graveLow==graveUp) + { + sLog.outErrorDb("Table `game_graveyard_zone` incomplete: Zone %u Team %u does not have a linked graveyard.",zoneId,team); + return NULL; + } + + bool foundNear = false; + float distNear; + WorldSafeLocsEntry const* entryNear = NULL; + WorldSafeLocsEntry const* entryFar = NULL; + + for(GraveYardMap::const_iterator itr = graveLow; itr != graveUp; ++itr) + { + GraveYardData const& data = itr->second; + + WorldSafeLocsEntry const* entry = sWorldSafeLocsStore.LookupEntry(data.safeLocId); + if(!entry) + { + sLog.outErrorDb("Table `game_graveyard_zone` has record for not existing graveyard (WorldSafeLocs.dbc id) %u, skipped.",data.safeLocId); + continue; + } + + // remember first graveyard at another map and ignore other + if(MapId != entry->map_id) + { + if(!entryFar) + entryFar = entry; + continue; + } + + // skip enemy faction graveyard at same map (normal area, city, or battleground) + // team == 0 case can be at call from .neargrave + if(data.team != 0 && team != 0 && data.team != team) + continue; + + // find now nearest graveyard at same map + float dist2 = (entry->x - x)*(entry->x - x)+(entry->y - y)*(entry->y - y)+(entry->z - z)*(entry->z - z); + if(foundNear) + { + if(dist2 < distNear) + { + distNear = dist2; + entryNear = entry; + } + } + else + { + foundNear = true; + distNear = dist2; + entryNear = entry; + } + } + + if(entryNear) + return entryNear; + + return entryFar; +} + +GraveYardData const* ObjectMgr::FindGraveYardData(uint32 id, uint32 zoneId) +{ + GraveYardMap::const_iterator graveLow = mGraveYardMap.lower_bound(zoneId); + GraveYardMap::const_iterator graveUp = mGraveYardMap.upper_bound(zoneId); + + for(GraveYardMap::const_iterator itr = graveLow; itr != graveUp; ++itr) + { + if(itr->second.safeLocId==id) + return &itr->second; + } + + return NULL; +} + +bool ObjectMgr::AddGraveYardLink(uint32 id, uint32 zoneId, uint32 team, bool inDB) +{ + if(FindGraveYardData(id,zoneId)) + return false; + + // add link to loaded data + GraveYardData data; + data.safeLocId = id; + data.team = team; + + mGraveYardMap.insert(GraveYardMap::value_type(zoneId,data)); + + // add link to DB + if(inDB) + { + WorldDatabase.PExecuteLog("INSERT INTO game_graveyard_zone ( id,ghost_zone,faction) " + "VALUES ('%u', '%u','%u')",id,zoneId,team); + } + + return true; +} + +void ObjectMgr::LoadAreaTriggerTeleports() +{ + mAreaTriggers.clear(); // need for reload case + + uint32 count = 0; + + // 0 1 2 3 4 5 6 7 8 9 10 11 12 + QueryResult *result = WorldDatabase.Query("SELECT id, required_level, required_item, required_item2, heroic_key, heroic_key2, required_quest_done, required_failed_text, target_map, target_position_x, target_position_y, target_position_z, target_orientation FROM areatrigger_teleport"); + if( !result ) + { + + barGoLink bar( 1 ); + + bar.step(); + + sLog.outString(); + sLog.outString( ">> Loaded %u area trigger teleport definitions", count ); + return; + } + + barGoLink bar( result->GetRowCount() ); + + do + { + Field *fields = result->Fetch(); + + bar.step(); + + ++count; + + uint32 Trigger_ID = fields[0].GetUInt32(); + + AreaTrigger at; + + at.requiredLevel = fields[1].GetUInt8(); + at.requiredItem = fields[2].GetUInt32(); + at.requiredItem2 = fields[3].GetUInt32(); + at.heroicKey = fields[4].GetUInt32(); + at.heroicKey2 = fields[5].GetUInt32(); + at.requiredQuest = fields[6].GetUInt32(); + at.requiredFailedText = fields[7].GetCppString(); + at.target_mapId = fields[8].GetUInt32(); + at.target_X = fields[9].GetFloat(); + at.target_Y = fields[10].GetFloat(); + at.target_Z = fields[11].GetFloat(); + at.target_Orientation = fields[12].GetFloat(); + + AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(Trigger_ID); + if(!atEntry) + { + sLog.outErrorDb("Area trigger (ID:%u) does not exist in `AreaTrigger.dbc`.",Trigger_ID); + continue; + } + + if(at.requiredItem) + { + ItemPrototype const *pProto = objmgr.GetItemPrototype(at.requiredItem); + if(!pProto) + { + sLog.outError("Key item %u does not exist for trigger %u, removing key requirement.", at.requiredItem, Trigger_ID); + at.requiredItem = 0; + } + } + if(at.requiredItem2) + { + ItemPrototype const *pProto = objmgr.GetItemPrototype(at.requiredItem2); + if(!pProto) + { + sLog.outError("Second item %u not exist for trigger %u, remove key requirement.", at.requiredItem2, Trigger_ID); + at.requiredItem2 = 0; + } + } + + if(at.heroicKey) + { + ItemPrototype const *pProto = objmgr.GetItemPrototype(at.heroicKey); + if(!pProto) + { + sLog.outError("Heroic key item %u not exist for trigger %u, remove key requirement.", at.heroicKey, Trigger_ID); + at.heroicKey = 0; + } + } + + if(at.heroicKey2) + { + ItemPrototype const *pProto = objmgr.GetItemPrototype(at.heroicKey2); + if(!pProto) + { + sLog.outError("Heroic second key item %u not exist for trigger %u, remove key requirement.", at.heroicKey2, Trigger_ID); + at.heroicKey2 = 0; + } + } + + if(at.requiredQuest) + { + if(!mQuestTemplates[at.requiredQuest]) + { + sLog.outErrorDb("Required Quest %u not exist for trigger %u, remove quest done requirement.",at.requiredQuest,Trigger_ID); + at.requiredQuest = 0; + } + } + + MapEntry const* mapEntry = sMapStore.LookupEntry(at.target_mapId); + if(!mapEntry) + { + sLog.outErrorDb("Area trigger (ID:%u) target map (ID: %u) does not exist in `Map.dbc`.",Trigger_ID,at.target_mapId); + continue; + } + + if(at.target_X==0 && at.target_Y==0 && at.target_Z==0) + { + sLog.outErrorDb("Area trigger (ID:%u) target coordinates not provided.",Trigger_ID); + continue; + } + + mAreaTriggers[Trigger_ID] = at; + + } while( result->NextRow() ); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u area trigger teleport definitions", count ); +} + +AreaTrigger const* ObjectMgr::GetGoBackTrigger(uint32 Map) const +{ + const MapEntry *mapEntry = sMapStore.LookupEntry(Map); + if(!mapEntry) return NULL; + for (AreaTriggerMap::const_iterator itr = mAreaTriggers.begin(); itr != mAreaTriggers.end(); itr++) + { + if(itr->second.target_mapId == mapEntry->parent_map) + { + AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(itr->first); + if(atEntry && atEntry->mapid == Map) + return &itr->second; + } + } + return NULL; +} + +void ObjectMgr::SetHighestGuids() +{ + QueryResult *result = CharacterDatabase.Query( "SELECT MAX(guid) FROM characters" ); + if( result ) + { + m_hiCharGuid = (*result)[0].GetUInt32()+1; + + delete result; + } + + result = WorldDatabase.Query( "SELECT MAX(guid) FROM creature" ); + if( result ) + { + m_hiCreatureGuid = (*result)[0].GetUInt32()+1; + + delete result; + } + + result = CharacterDatabase.Query( "SELECT MAX(id) FROM character_pet" ); + if( result ) + { + m_hiPetGuid = (*result)[0].GetUInt32()+1; + + delete result; + } + + result = CharacterDatabase.Query( "SELECT MAX(guid) FROM item_instance" ); + if( result ) + { + m_hiItemGuid = (*result)[0].GetUInt32()+1; + + delete result; + } + + // Cleanup other tables from not existed guids (>=m_hiItemGuid) + CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE item >= '%u'", m_hiItemGuid); + CharacterDatabase.PExecute("DELETE FROM mail_items WHERE item_guid >= '%u'", m_hiItemGuid); + CharacterDatabase.PExecute("DELETE FROM auctionhouse WHERE itemguid >= '%u'", m_hiItemGuid); + CharacterDatabase.PExecute("DELETE FROM guild_bank_item WHERE item_guid >= '%u'", m_hiItemGuid); + + result = WorldDatabase.Query("SELECT MAX(guid) FROM gameobject" ); + if( result ) + { + m_hiGoGuid = (*result)[0].GetUInt32()+1; + + delete result; + } + + result = CharacterDatabase.Query("SELECT MAX(id) FROM auctionhouse" ); + if( result ) + { + m_auctionid = (*result)[0].GetUInt32()+1; + + delete result; + } + else + { + m_auctionid = 0; + } + result = CharacterDatabase.Query( "SELECT MAX(id) FROM mail" ); + if( result ) + { + m_mailid = (*result)[0].GetUInt32()+1; + + delete result; + } + else + { + m_mailid = 0; + } + result = CharacterDatabase.Query( "SELECT MAX(id) FROM item_text" ); + if( result ) + { + m_ItemTextId = (*result)[0].GetUInt32(); + + delete result; + } + else + m_ItemTextId = 0; + + result = CharacterDatabase.Query( "SELECT MAX(guid) FROM corpse" ); + if( result ) + { + m_hiCorpseGuid = (*result)[0].GetUInt32()+1; + + delete result; + } +} + +uint32 ObjectMgr::GenerateAuctionID() +{ + ++m_auctionid; + if(m_auctionid>=0xFFFFFFFF) + { + sLog.outError("Auctions ids overflow!! Can't continue, shuting down server. "); + sWorld.m_stopEvent = true; + } + return m_auctionid; +} + +uint32 ObjectMgr::GenerateMailID() +{ + ++m_mailid; + if(m_mailid>=0xFFFFFFFF) + { + sLog.outError("Mail ids overflow!! Can't continue, shuting down server. "); + sWorld.m_stopEvent = true; + } + return m_mailid; +} + +uint32 ObjectMgr::GenerateItemTextID() +{ + ++m_ItemTextId; + if(m_ItemTextId>=0xFFFFFFFF) + { + sLog.outError("Item text ids overflow!! Can't continue, shuting down server. "); + sWorld.m_stopEvent = true; + } + return m_ItemTextId; +} + +uint32 ObjectMgr::CreateItemText(std::string text) +{ + uint32 newItemTextId = GenerateItemTextID(); + //insert new itempage to container + mItemTexts[ newItemTextId ] = text; + //save new itempage + CharacterDatabase.escape_string(text); + //any Delete query needed, itemTextId is maximum of all ids + std::ostringstream query; + query << "INSERT INTO item_text (id,text) VALUES ( '" << newItemTextId << "', '" << text << "')"; + CharacterDatabase.Execute(query.str().c_str()); //needs to be run this way, because mail body may be more than 1024 characters + return newItemTextId; +} + +uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh) +{ + switch(guidhigh) + { + case HIGHGUID_ITEM: + ++m_hiItemGuid; + if(m_hiItemGuid>=0xFFFFFFFF) + { + sLog.outError("Item guid overflow!! Can't continue, shuting down server. "); + sWorld.m_stopEvent = true; + } + return m_hiItemGuid; + case HIGHGUID_UNIT: + ++m_hiCreatureGuid; + if(m_hiCreatureGuid>=0x00FFFFFF) + { + sLog.outError("Creature guid overflow!! Can't continue, shuting down server. "); + sWorld.m_stopEvent = true; + } + return m_hiCreatureGuid; + case HIGHGUID_PET: + ++m_hiPetGuid; + if(m_hiPetGuid>=0x00FFFFFF) + { + sLog.outError("Pet guid overflow!! Can't continue, shuting down server. "); + sWorld.m_stopEvent = true; + } + return m_hiPetGuid; + case HIGHGUID_PLAYER: + ++m_hiCharGuid; + if(m_hiCharGuid>=0xFFFFFFFF) + { + sLog.outError("Players guid overflow!! Can't continue, shuting down server. "); + sWorld.m_stopEvent = true; + } + return m_hiCharGuid; + case HIGHGUID_GAMEOBJECT: + ++m_hiGoGuid; + if(m_hiGoGuid>=0x00FFFFFF) + { + sLog.outError("Gameobject guid overflow!! Can't continue, shuting down server. "); + sWorld.m_stopEvent = true; + } + return m_hiGoGuid; + case HIGHGUID_CORPSE: + ++m_hiCorpseGuid; + if(m_hiCorpseGuid>=0xFFFFFFFF) + { + sLog.outError("Corpse guid overflow!! Can't continue, shuting down server. "); + sWorld.m_stopEvent = true; + } + return m_hiCorpseGuid; + case HIGHGUID_DYNAMICOBJECT: + ++m_hiDoGuid; + if(m_hiDoGuid>=0xFFFFFFFF) + { + sLog.outError("DynamicObject guid overflow!! Can't continue, shuting down server. "); + sWorld.m_stopEvent = true; + } + return m_hiDoGuid; + default: + ASSERT(0); + } + + ASSERT(0); + return 0; +} + +void ObjectMgr::LoadGameObjectLocales() +{ + QueryResult *result = WorldDatabase.Query("SELECT entry," + "name_loc1,name_loc2,name_loc3,name_loc4,name_loc5,name_loc6,name_loc7,name_loc8," + "castbarcaption_loc1,castbarcaption_loc2,castbarcaption_loc3,castbarcaption_loc4," + "castbarcaption_loc5,castbarcaption_loc6,castbarcaption_loc7,castbarcaption_loc8 FROM locales_gameobject"); + + if(!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(""); + sLog.outString(">> Loaded 0 gameobject locale strings. DB table `locales_gameobject` is empty."); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 entry = fields[0].GetUInt32(); + + GameObjectLocale& data = mGameObjectLocaleMap[entry]; + + for(int i = 1; i < MAX_LOCALE; ++i) + { + std::string str = fields[i].GetCppString(); + if(!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if(idx >= 0) + { + if(data.Name.size() <= idx) + data.Name.resize(idx+1); + + data.Name[idx] = str; + } + } + } + + for(int i = MAX_LOCALE; i < MAX_LOCALE*2-1; ++i) + { + std::string str = fields[i].GetCppString(); + if(!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if(idx >= 0) + { + if(data.CastBarCaption.size() <= idx) + data.CastBarCaption.resize(idx+1); + + data.CastBarCaption[idx] = str; + } + } + } + + } while (result->NextRow()); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u gameobject locale strings", mGameObjectLocaleMap.size() ); +} + +void ObjectMgr::LoadGameobjectInfo() +{ + sGOStorage.Load(); + + // some checks + for(uint32 id = 1; id < sGOStorage.MaxEntry; id++) + { + GameObjectInfo const* goInfo = sGOStorage.LookupEntry(id); + if(!goInfo) + continue; + + switch(goInfo->type) + { + case GAMEOBJECT_TYPE_DOOR: //0 + { + if(goInfo->door.lockId) + { + if(!sLockStore.LookupEntry(goInfo->door.lockId)) + sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data1=%u but lock (Id: %u) not found.", + id,goInfo->type,goInfo->door.lockId,goInfo->door.lockId); + } + break; + } + case GAMEOBJECT_TYPE_BUTTON: //1 + { + if(goInfo->button.lockId) + { + if(!sLockStore.LookupEntry(goInfo->button.lockId)) + sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data1=%u but lock (Id: %u) not found.", + id,goInfo->type,goInfo->button.lockId,goInfo->button.lockId); + } + break; + } + case GAMEOBJECT_TYPE_CHEST: //3 + { + if(goInfo->chest.lockId) + { + if(!sLockStore.LookupEntry(goInfo->chest.lockId)) + sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data0=%u but lock (Id: %u) not found.", + id,goInfo->type,goInfo->chest.lockId,goInfo->chest.lockId); + } + if(goInfo->chest.linkedTrapId) // linked trap + { + if(GameObjectInfo const* trapInfo = sGOStorage.LookupEntry(goInfo->chest.linkedTrapId)) + { + if(trapInfo->type!=GAMEOBJECT_TYPE_TRAP) + sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data7=%u but GO (Entry %u) have not GAMEOBJECT_TYPE_TRAP (%u) type.", + id,goInfo->type,goInfo->chest.linkedTrapId,goInfo->chest.linkedTrapId,GAMEOBJECT_TYPE_TRAP); + } + /* disable check for while + else + sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data2=%u but trap GO (Entry %u) not exist in `gameobject_template`.", + id,goInfo->type,goInfo->chest.linkedTrapId,goInfo->chest.linkedTrapId); + */ + } + break; + } + case GAMEOBJECT_TYPE_TRAP: //6 + { + /* disable check for while + if(goInfo->trap.spellId) // spell + { + if(!sSpellStore.LookupEntry(goInfo->trap.spellId)) + sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data3=%u but Spell (Entry %u) not exist.", + id,goInfo->type,goInfo->trap.spellId,goInfo->trap.spellId); + } + */ + break; + } + case GAMEOBJECT_TYPE_CHAIR: //7 + if(goInfo->chair.height > 2) + { + sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data1=%u but correct chair height in range 0..2.", + id,goInfo->type,goInfo->chair.height); + + // prevent client and server unexpected work + const_cast(goInfo)->chair.height = 0; + } + break; + case GAMEOBJECT_TYPE_SPELL_FOCUS: //8 + { + if(goInfo->spellFocus.focusId) + { + if(!sSpellFocusObjectStore.LookupEntry(goInfo->spellFocus.focusId)) + sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data0=%u but SpellFocus (Id: %u) not exist.", + id,goInfo->type,goInfo->spellFocus.focusId,goInfo->spellFocus.focusId); + } + + if(goInfo->spellFocus.linkedTrapId) // linked trap + { + if(GameObjectInfo const* trapInfo = sGOStorage.LookupEntry(goInfo->spellFocus.linkedTrapId)) + { + if(trapInfo->type!=GAMEOBJECT_TYPE_TRAP) + sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data2=%u but GO (Entry %u) have not GAMEOBJECT_TYPE_TRAP (%u) type.", + id,goInfo->type,goInfo->spellFocus.linkedTrapId,goInfo->spellFocus.linkedTrapId,GAMEOBJECT_TYPE_TRAP); + } + /* disable check for while + else + sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data2=%u but trap GO (Entry %u) not exist in `gameobject_template`.", + id,goInfo->type,goInfo->spellFocus.linkedTrapId,goInfo->spellFocus.linkedTrapId); + */ + } + break; + } + case GAMEOBJECT_TYPE_GOOBER: //10 + { + if(goInfo->goober.pageId) // pageId + { + if(!sPageTextStore.LookupEntry(goInfo->goober.pageId)) + sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data7=%u but PageText (Entry %u) not exist.", + id,goInfo->type,goInfo->goober.pageId,goInfo->goober.pageId); + } + /* disable check for while + if(goInfo->goober.spellId) // spell + { + if(!sSpellStore.LookupEntry(goInfo->goober.spellId)) + sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data2=%u but Spell (Entry %u) not exist.", + id,goInfo->type,goInfo->goober.spellId,goInfo->goober.spellId); + } + */ + if(goInfo->goober.linkedTrapId) // linked trap + { + if(GameObjectInfo const* trapInfo = sGOStorage.LookupEntry(goInfo->goober.linkedTrapId)) + { + if(trapInfo->type!=GAMEOBJECT_TYPE_TRAP) + sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data12=%u but GO (Entry %u) have not GAMEOBJECT_TYPE_TRAP (%u) type.", + id,goInfo->type,goInfo->goober.linkedTrapId,goInfo->goober.linkedTrapId,GAMEOBJECT_TYPE_TRAP); + } + /* disable check for while + else + sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data12=%u but trap GO (Entry %u) not exist in `gameobject_template`.", + id,goInfo->type,goInfo->goober.linkedTrapId,goInfo->goober.linkedTrapId); + */ + } + break; + } + case GAMEOBJECT_TYPE_MO_TRANSPORT: //15 + { + if(goInfo->moTransport.taxiPathId) + { + if(goInfo->moTransport.taxiPathId >= sTaxiPathNodesByPath.size() || sTaxiPathNodesByPath[goInfo->moTransport.taxiPathId].empty()) + sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data0=%u but TaxiPath (Id: %u) not exist.", + id,goInfo->type,goInfo->moTransport.taxiPathId,goInfo->moTransport.taxiPathId); + } + break; + } + case GAMEOBJECT_TYPE_SUMMONING_RITUAL: //18 + { + /* disabled + if(goInfo->summoningRitual.spellId) + { + if(!sSpellStore.LookupEntry(goInfo->summoningRitual.spellId)) + sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data1=%u but Spell (Entry %u) not exist.", + id,goInfo->type,goInfo->summoningRitual.spellId,goInfo->summoningRitual.spellId); + } + */ + break; + } + case GAMEOBJECT_TYPE_SPELLCASTER: //22 + { + if(goInfo->spellcaster.spellId) // spell + { + if(!sSpellStore.LookupEntry(goInfo->spellcaster.spellId)) + sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data3=%u but Spell (Entry %u) not exist.", + id,goInfo->type,goInfo->spellcaster.spellId,goInfo->spellcaster.spellId); + } + break; + } + } + } + + sLog.outString( ">> Loaded %u game object templates", sGOStorage.RecordCount ); + sLog.outString(); +} + +void ObjectMgr::LoadExplorationBaseXP() +{ + uint32 count = 0; + QueryResult *result = WorldDatabase.Query("SELECT level,basexp FROM exploration_basexp"); + + if( !result ) + { + barGoLink bar( 1 ); + + bar.step(); + + sLog.outString(); + sLog.outString( ">> Loaded %u BaseXP definitions", count ); + return; + } + + barGoLink bar( result->GetRowCount() ); + + do + { + bar.step(); + + Field *fields = result->Fetch(); + uint32 level = fields[0].GetUInt32(); + uint32 basexp = fields[1].GetUInt32(); + mBaseXPTable[level] = basexp; + ++count; + } + while (result->NextRow()); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u BaseXP definitions", count ); +} + +uint32 ObjectMgr::GetBaseXP(uint32 level) +{ + return mBaseXPTable[level] ? mBaseXPTable[level] : 0; +} + +void ObjectMgr::LoadPetNames() +{ + uint32 count = 0; + QueryResult *result = WorldDatabase.Query("SELECT word,entry,half FROM pet_name_generation"); + + if( !result ) + { + barGoLink bar( 1 ); + + bar.step(); + + sLog.outString(); + sLog.outString( ">> Loaded %u pet name parts", count ); + return; + } + + barGoLink bar( result->GetRowCount() ); + + do + { + bar.step(); + + Field *fields = result->Fetch(); + std::string word = fields[0].GetString(); + uint32 entry = fields[1].GetUInt32(); + bool half = fields[2].GetBool(); + if(half) + PetHalfName1[entry].push_back(word); + else + PetHalfName0[entry].push_back(word); + ++count; + } + while (result->NextRow()); + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u pet name parts", count ); +} + +void ObjectMgr::LoadPetNumber() +{ + QueryResult* result = CharacterDatabase.Query("SELECT MAX(id) FROM character_pet"); + if(result) + { + Field *fields = result->Fetch(); + m_hiPetNumber = fields[0].GetUInt32()+1; + delete result; + } + + barGoLink bar( 1 ); + bar.step(); + + sLog.outString(); + sLog.outString( ">> Loaded the max pet number: %d", m_hiPetNumber-1); +} + +std::string ObjectMgr::GeneratePetName(uint32 entry) +{ + std::vector & list0 = PetHalfName0[entry]; + std::vector & list1 = PetHalfName1[entry]; + + if(list0.empty() || list1.empty()) + { + CreatureInfo const *cinfo = objmgr.GetCreatureTemplate(entry); + char* petname = GetPetName(cinfo->family, sWorld.GetDefaultDbcLocale()); + if(!petname) + petname = cinfo->Name; + return std::string(petname); + } + + return *(list0.begin()+urand(0, list0.size()-1)) + *(list1.begin()+urand(0, list1.size()-1)); +} + +uint32 ObjectMgr::GeneratePetNumber() +{ + return ++m_hiPetNumber; +} + +void ObjectMgr::LoadCorpses() +{ + uint32 count = 0; + // 0 1 2 3 4 5 6 7 8 10 + QueryResult *result = CharacterDatabase.PQuery("SELECT position_x, position_y, position_z, orientation, map, data, time, corpse_type, instance, guid FROM corpse WHERE corpse_type <> 0"); + + if( !result ) + { + barGoLink bar( 1 ); + + bar.step(); + + sLog.outString(); + sLog.outString( ">> Loaded %u corpses", count ); + return; + } + + barGoLink bar( result->GetRowCount() ); + + do + { + bar.step(); + + Field *fields = result->Fetch(); + + uint32 guid = fields[result->GetFieldCount()-1].GetUInt32(); + + Corpse *corpse = new Corpse; + if(!corpse->LoadFromDB(guid,fields)) + { + delete corpse; + continue; + } + + ObjectAccessor::Instance().AddCorpse(corpse); + + ++count; + } + while (result->NextRow()); + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u corpses", count ); +} + +void ObjectMgr::LoadReputationOnKill() +{ + uint32 count = 0; + + // 0 1 2 + QueryResult *result = WorldDatabase.Query("SELECT creature_id, RewOnKillRepFaction1, RewOnKillRepFaction2," + // 3 4 5 6 7 8 9 + "IsTeamAward1, MaxStanding1, RewOnKillRepValue1, IsTeamAward2, MaxStanding2, RewOnKillRepValue2, TeamDependent " + "FROM creature_onkill_reputation"); + + if(!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outErrorDb(">> Loaded 0 creature award reputation definitions. DB table `creature_onkill_reputation` is empty."); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 creature_id = fields[0].GetUInt32(); + + ReputationOnKillEntry repOnKill; + repOnKill.repfaction1 = fields[1].GetUInt32(); + repOnKill.repfaction2 = fields[2].GetUInt32(); + repOnKill.is_teamaward1 = fields[3].GetBool(); + repOnKill.reputration_max_cap1 = fields[4].GetUInt32(); + repOnKill.repvalue1 = fields[5].GetInt32(); + repOnKill.is_teamaward2 = fields[6].GetBool(); + repOnKill.reputration_max_cap2 = fields[7].GetUInt32(); + repOnKill.repvalue2 = fields[8].GetInt32(); + repOnKill.team_dependent = fields[9].GetUInt8(); + + if(!GetCreatureTemplate(creature_id)) + { + sLog.outErrorDb("Table `creature_onkill_reputation` have data for not existed creature entry (%u), skipped",creature_id); + continue; + } + + if(repOnKill.repfaction1) + { + FactionEntry const *factionEntry1 = sFactionStore.LookupEntry(repOnKill.repfaction1); + if(!factionEntry1) + { + sLog.outErrorDb("Faction (faction.dbc) %u does not exist but is used in `creature_onkill_reputation`",repOnKill.repfaction1); + continue; + } + } + + if(repOnKill.repfaction2) + { + FactionEntry const *factionEntry2 = sFactionStore.LookupEntry(repOnKill.repfaction2); + if(!factionEntry2) + { + sLog.outErrorDb("Faction (faction.dbc) %u does not exist but is used in `creature_onkill_reputation`",repOnKill.repfaction2); + continue; + } + } + + mRepOnKill[creature_id] = repOnKill; + + ++count; + } while (result->NextRow()); + + delete result; + + sLog.outString(); + sLog.outString(">> Loaded %u creature award reputation definitions", count); +} + +void ObjectMgr::LoadWeatherZoneChances() +{ + uint32 count = 0; + + // 0 1 2 3 4 5 6 7 8 9 10 11 12 + QueryResult *result = WorldDatabase.Query("SELECT zone, spring_rain_chance, spring_snow_chance, spring_storm_chance, summer_rain_chance, summer_snow_chance, summer_storm_chance, fall_rain_chance, fall_snow_chance, fall_storm_chance, winter_rain_chance, winter_snow_chance, winter_storm_chance FROM game_weather"); + + if(!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outErrorDb(">> Loaded 0 weather definitions. DB table `game_weather` is empty."); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 zone_id = fields[0].GetUInt32(); + + WeatherZoneChances& wzc = mWeatherZoneMap[zone_id]; + + for(int season = 0; season < WEATHER_SEASONS; ++season) + { + wzc.data[season].rainChance = fields[season * (MAX_WEATHER_TYPE-1) + 1].GetUInt32(); + wzc.data[season].snowChance = fields[season * (MAX_WEATHER_TYPE-1) + 2].GetUInt32(); + wzc.data[season].stormChance = fields[season * (MAX_WEATHER_TYPE-1) + 3].GetUInt32(); + + if(wzc.data[season].rainChance > 100) + { + wzc.data[season].rainChance = 25; + sLog.outErrorDb("Weather for zone %u season %u has wrong rain chance > 100%",zone_id,season); + } + + if(wzc.data[season].snowChance > 100) + { + wzc.data[season].snowChance = 25; + sLog.outErrorDb("Weather for zone %u season %u has wrong snow chance > 100%",zone_id,season); + } + + if(wzc.data[season].stormChance > 100) + { + wzc.data[season].stormChance = 25; + sLog.outErrorDb("Weather for zone %u season %u has wrong storm chance > 100%",zone_id,season); + } + } + + ++count; + } while (result->NextRow()); + + delete result; + + sLog.outString(); + sLog.outString(">> Loaded %u weather definitions", count); +} + +void ObjectMgr::SaveCreatureRespawnTime(uint32 loguid, uint32 instance, time_t t) +{ + mCreatureRespawnTimes[MAKE_PAIR64(loguid,instance)] = t; + WorldDatabase.PExecute("DELETE FROM creature_respawn WHERE guid = '%u' AND instance = '%u'", loguid, instance); + if(t) + WorldDatabase.PExecute("INSERT INTO creature_respawn VALUES ( '%u', '" I64FMTD "', '%u' )", loguid, uint64(t), instance); +} + +void ObjectMgr::DeleteCreatureData(uint32 guid) +{ + // remove mapid*cellid -> guid_set map + CreatureData const* data = GetCreatureData(guid); + if(data) + RemoveCreatureFromGrid(guid, data); + + mCreatureDataMap.erase(guid); +} + +void ObjectMgr::SaveGORespawnTime(uint32 loguid, uint32 instance, time_t t) +{ + mGORespawnTimes[MAKE_PAIR64(loguid,instance)] = t; + WorldDatabase.PExecute("DELETE FROM gameobject_respawn WHERE guid = '%u' AND instance = '%u'", loguid, instance); + if(t) + WorldDatabase.PExecute("INSERT INTO gameobject_respawn VALUES ( '%u', '" I64FMTD "', '%u' )", loguid, uint64(t), instance); +} + +void ObjectMgr::DeleteRespawnTimeForInstance(uint32 instance) +{ + RespawnTimes::iterator next; + + for(RespawnTimes::iterator itr = mGORespawnTimes.begin(); itr != mGORespawnTimes.end(); itr = next) + { + next = itr; + ++next; + + if(GUID_HIPART(itr->first)==instance) + mGORespawnTimes.erase(itr); + } + + for(RespawnTimes::iterator itr = mCreatureRespawnTimes.begin(); itr != mCreatureRespawnTimes.end(); itr = next) + { + next = itr; + ++next; + + if(GUID_HIPART(itr->first)==instance) + mCreatureRespawnTimes.erase(itr); + } + + WorldDatabase.PExecute("DELETE FROM creature_respawn WHERE instance = '%u'", instance); + WorldDatabase.PExecute("DELETE FROM gameobject_respawn WHERE instance = '%u'", instance); +} + +void ObjectMgr::DeleteGOData(uint32 guid) +{ + // remove mapid*cellid -> guid_set map + GameObjectData const* data = GetGOData(guid); + if(data) + RemoveGameobjectFromGrid(guid, data); + + mGameObjectDataMap.erase(guid); +} + +void ObjectMgr::AddCorpseCellData(uint32 mapid, uint32 cellid, uint32 player_guid, uint32 instance) +{ + // corpses are always added to spawn mode 0 and they are spawned by their instance id + CellObjectGuids& cell_guids = mMapObjectGuids[MAKE_PAIR32(mapid,0)][cellid]; + cell_guids.corpses[player_guid] = instance; +} + +void ObjectMgr::DeleteCorpseCellData(uint32 mapid, uint32 cellid, uint32 player_guid) +{ + // corpses are always added to spawn mode 0 and they are spawned by their instance id + CellObjectGuids& cell_guids = mMapObjectGuids[MAKE_PAIR32(mapid,0)][cellid]; + cell_guids.corpses.erase(player_guid); +} + +void ObjectMgr::LoadQuestRelationsHelper(QuestRelations& map,char const* table) +{ + map.clear(); // need for reload case + + uint32 count = 0; + + QueryResult *result = WorldDatabase.PQuery("SELECT id,quest FROM %s",table); + + if(!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outErrorDb(">> Loaded 0 quest relations from %s. DB table `%s` is empty.",table,table); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 id = fields[0].GetUInt32(); + uint32 quest = fields[1].GetUInt32(); + + if(mQuestTemplates.find(quest) == mQuestTemplates.end()) + { + sLog.outErrorDb("Table `%s: Quest %u listed for entry %u does not exist.",table,quest,id); + continue; + } + + map.insert(QuestRelations::value_type(id,quest)); + + ++count; + } while (result->NextRow()); + + delete result; + + sLog.outString(); + sLog.outString(">> Loaded %u quest relations from %s", count,table); +} + +void ObjectMgr::LoadGameobjectQuestRelations() +{ + LoadQuestRelationsHelper(mGOQuestRelations,"gameobject_questrelation"); + + for(QuestRelations::iterator itr = mGOQuestRelations.begin(); itr != mGOQuestRelations.end(); ++itr) + { + GameObjectInfo const* goInfo = GetGameObjectInfo(itr->first); + if(!goInfo) + sLog.outErrorDb("Table `gameobject_questrelation` have data for not existed gameobject entry (%u) and existed quest %u",itr->first,itr->second); + else if(goInfo->type != GAMEOBJECT_TYPE_QUESTGIVER) + sLog.outErrorDb("Table `gameobject_questrelation` have data gameobject entry (%u) for quest %u, but GO is not GAMEOBJECT_TYPE_QUESTGIVER",itr->first,itr->second); + } +} + +void ObjectMgr::LoadGameobjectInvolvedRelations() +{ + LoadQuestRelationsHelper(mGOQuestInvolvedRelations,"gameobject_involvedrelation"); + + for(QuestRelations::iterator itr = mGOQuestInvolvedRelations.begin(); itr != mGOQuestInvolvedRelations.end(); ++itr) + { + GameObjectInfo const* goInfo = GetGameObjectInfo(itr->first); + if(!goInfo) + sLog.outErrorDb("Table `gameobject_involvedrelation` have data for not existed gameobject entry (%u) and existed quest %u",itr->first,itr->second); + else if(goInfo->type != GAMEOBJECT_TYPE_QUESTGIVER) + sLog.outErrorDb("Table `gameobject_involvedrelation` have data gameobject entry (%u) for quest %u, but GO is not GAMEOBJECT_TYPE_QUESTGIVER",itr->first,itr->second); + } +} + +void ObjectMgr::LoadCreatureQuestRelations() +{ + LoadQuestRelationsHelper(mCreatureQuestRelations,"creature_questrelation"); + + for(QuestRelations::iterator itr = mCreatureQuestRelations.begin(); itr != mCreatureQuestRelations.end(); ++itr) + { + CreatureInfo const* cInfo = GetCreatureTemplate(itr->first); + if(!cInfo) + sLog.outErrorDb("Table `creature_questrelation` have data for not existed creature entry (%u) and existed quest %u",itr->first,itr->second); + else if(!(cInfo->npcflag & UNIT_NPC_FLAG_QUESTGIVER)) + sLog.outErrorDb("Table `creature_questrelation` has creature entry (%u) for quest %u, but npcflag does not include UNIT_NPC_FLAG_QUESTGIVER",itr->first,itr->second); + } +} + +void ObjectMgr::LoadCreatureInvolvedRelations() +{ + LoadQuestRelationsHelper(mCreatureQuestInvolvedRelations,"creature_involvedrelation"); + + for(QuestRelations::iterator itr = mCreatureQuestInvolvedRelations.begin(); itr != mCreatureQuestInvolvedRelations.end(); ++itr) + { + CreatureInfo const* cInfo = GetCreatureTemplate(itr->first); + if(!cInfo) + sLog.outErrorDb("Table `creature_involvedrelation` have data for not existed creature entry (%u) and existed quest %u",itr->first,itr->second); + else if(!(cInfo->npcflag & UNIT_NPC_FLAG_QUESTGIVER)) + sLog.outErrorDb("Table `creature_involvedrelation` has creature entry (%u) for quest %u, but npcflag does not include UNIT_NPC_FLAG_QUESTGIVER",itr->first,itr->second); + } +} + +void ObjectMgr::LoadReservedPlayersNames() +{ + m_ReservedNames.clear(); // need for reload case + + QueryResult *result = WorldDatabase.PQuery("SELECT name FROM reserved_name"); + + uint32 count = 0; + + if( !result ) + { + barGoLink bar( 1 ); + bar.step(); + + sLog.outString(); + sLog.outString( ">> Loaded %u reserved player names", count ); + return; + } + + barGoLink bar( result->GetRowCount() ); + + Field* fields; + do + { + bar.step(); + fields = result->Fetch(); + std::string name= fields[0].GetCppString(); + if(normalizePlayerName(name)) + { + m_ReservedNames.insert(name); + ++count; + } + } while ( result->NextRow() ); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u reserved player names", count ); +} + +enum LanguageType +{ + LT_BASIC_LATIN = 0x0000, + LT_EXTENDEN_LATIN = 0x0001, + LT_CYRILLIC = 0x0002, + LT_EAST_ASIA = 0x0004, + LT_ANY = 0xFFFF +}; + +static LanguageType GetRealmLanguageType(bool create) +{ + switch(sWorld.getConfig(CONFIG_REALM_ZONE)) + { + case REALM_ZONE_UNKNOWN: // any language + case REALM_ZONE_DEVELOPMENT: + case REALM_ZONE_TEST_SERVER: + case REALM_ZONE_QA_SERVER: + return LT_ANY; + case REALM_ZONE_UNITED_STATES: // extended-Latin + case REALM_ZONE_OCEANIC: + case REALM_ZONE_LATIN_AMERICA: + case REALM_ZONE_ENGLISH: + case REALM_ZONE_GERMAN: + case REALM_ZONE_FRENCH: + case REALM_ZONE_SPANISH: + return LT_EXTENDEN_LATIN; + case REALM_ZONE_KOREA: // East-Asian + case REALM_ZONE_TAIWAN: + case REALM_ZONE_CHINA: + return LT_EAST_ASIA; + case REALM_ZONE_RUSSIAN: // Cyrillic + return LT_CYRILLIC; + default: + return create ? LT_BASIC_LATIN : LT_ANY; // basic-Latin at create, any at login + } +} + +bool isValidString(std::wstring wstr, uint32 strictMask, bool numericOrSpace, bool create = false) +{ + if(strictMask==0) // any language, ignore realm + { + if(isExtendedLatinString(wstr,numericOrSpace)) + return true; + if(isCyrillicString(wstr,numericOrSpace)) + return true; + if(isEastAsianString(wstr,numericOrSpace)) + return true; + return false; + } + + if(strictMask & 0x2) // realm zone specific + { + LanguageType lt = GetRealmLanguageType(create); + if(lt & LT_EXTENDEN_LATIN) + if(isExtendedLatinString(wstr,numericOrSpace)) + return true; + if(lt & LT_CYRILLIC) + if(isCyrillicString(wstr,numericOrSpace)) + return true; + if(lt & LT_EAST_ASIA) + if(isEastAsianString(wstr,numericOrSpace)) + return true; + } + + if(strictMask & 0x1) // basic latin + { + if(isBasicLatinString(wstr,numericOrSpace)) + return true; + } + + return false; +} + +bool ObjectMgr::IsValidName( std::string name, bool create ) +{ + std::wstring wname; + if(!Utf8toWStr(name,wname)) + return false; + + if(wname.size() < 1 || wname.size() > MAX_PLAYER_NAME) + return false; + + uint32 strictMask = sWorld.getConfig(CONFIG_STRICT_PLAYER_NAMES); + + return isValidString(wname,strictMask,false,create); +} + +bool ObjectMgr::IsValidCharterName( std::string name ) +{ + std::wstring wname; + if(!Utf8toWStr(name,wname)) + return false; + + if(wname.size() < 1) + return false; + + uint32 strictMask = sWorld.getConfig(CONFIG_STRICT_CHARTER_NAMES); + + return isValidString(wname,strictMask,true); +} + +bool ObjectMgr::IsValidPetName( std::string name ) +{ + std::wstring wname; + if(!Utf8toWStr(name,wname)) + return false; + + if(wname.size() < 1) + return false; + + uint32 strictMask = sWorld.getConfig(CONFIG_STRICT_PET_NAMES); + + return isValidString(wname,strictMask,false); +} + +int ObjectMgr::GetIndexForLocale( LocaleConstant loc ) +{ + if(loc==LOCALE_enUS) + return -1; + + for(size_t i=0;i < m_LocalForIndex.size(); ++i) + if(m_LocalForIndex[i]==loc) + return i; + + return -1; +} + +LocaleConstant ObjectMgr::GetLocaleForIndex(int i) +{ + if (i<0 || i>=m_LocalForIndex.size()) + return LOCALE_enUS; + + return m_LocalForIndex[i]; +} + +int ObjectMgr::GetOrNewIndexForLocale( LocaleConstant loc ) +{ + if(loc==LOCALE_enUS) + return -1; + + for(size_t i=0;i < m_LocalForIndex.size(); ++i) + if(m_LocalForIndex[i]==loc) + return i; + + m_LocalForIndex.push_back(loc); + return m_LocalForIndex.size()-1; +} + +void ObjectMgr::LoadBattleMastersEntry() +{ + mBattleMastersMap.clear(); // need for reload case + + QueryResult *result = WorldDatabase.Query( "SELECT entry,bg_template FROM battlemaster_entry" ); + + uint32 count = 0; + + if( !result ) + { + barGoLink bar( 1 ); + bar.step(); + + sLog.outString(); + sLog.outString( ">> Loaded 0 battlemaster entries - table is empty!" ); + return; + } + + barGoLink bar( result->GetRowCount() ); + + do + { + ++count; + bar.step(); + + Field *fields = result->Fetch(); + + uint32 entry = fields[0].GetUInt32(); + uint32 bgTypeId = fields[1].GetUInt32(); + + mBattleMastersMap[entry] = bgTypeId; + + } while( result->NextRow() ); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u battlemaster entries", count ); +} + +void ObjectMgr::LoadGameObjectForQuests() +{ + mGameObjectForQuestSet.clear(); // need for reload case + + uint32 count = 0; + + // collect GO entries for GO that must activated + for(uint32 go_entry = 1; go_entry < sGOStorage.MaxEntry; ++go_entry) + { + GameObjectInfo const* goInfo = sGOStorage.LookupEntry(go_entry); + if(!goInfo) + continue; + + switch(goInfo->type) + { + // scan GO chest with loot including quest items + case GAMEOBJECT_TYPE_CHEST: + { + uint32 loot_id = GameObject::GetLootId(goInfo); + + // find quest loot for GO + if(LootTemplates_Gameobject.HaveQuestLootFor(loot_id)) + { + mGameObjectForQuestSet.insert(go_entry); + ++count; + } + break; + } + case GAMEOBJECT_TYPE_GOOBER: + { + if(goInfo->goober.questId) //quests objects + { + mGameObjectForQuestSet.insert(go_entry); + count++; + } + break; + } + default: + break; + } + } + + sLog.outString(); + sLog.outString( ">> Loaded %u GameObject for quests", count ); +} + +bool ObjectMgr::LoadMangosStrings(DatabaseType& db, char const* table, bool positive_entries) +{ + // cleanup affected map part for reloading case + for(MangosStringLocaleMap::iterator itr = mMangosStringLocaleMap.begin(); itr != mMangosStringLocaleMap.end();) + { + if(itr->first > 0 && positive_entries || itr->first < 0 && !positive_entries) + { + MangosStringLocaleMap::iterator itr2 = itr; + ++itr; + mMangosStringLocaleMap.erase(itr2); + } + else + ++itr; + } + + QueryResult *result = db.PQuery("SELECT entry,content_default,content_loc1,content_loc2,content_loc3,content_loc4,content_loc5,content_loc6,content_loc7,content_loc8 FROM %s",table); + + if(!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(""); + if(positive_entries) // error only in case internal strings + sLog.outErrorDb(">> Loaded 0 mangos strings. DB table `%s` is empty. Cannot continue.",table); + else + sLog.outString(">> Loaded 0 mangos strings. DB table `%s` is empty.",table); + return false; + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + int32 entry = fields[0].GetInt32(); + + if(entry==0) + { + sLog.outString("Table `%s` contain reserved entry 0, ignored.",table); + continue; + } + else if(entry < 0) + { + if(positive_entries) + { + sLog.outString("Table `%s` contain unexpected negative entry %i, ignored.",table,entry); + continue; + } + } + else + { + if(!positive_entries) + { + sLog.outString("Table `%s` contain unexpected positive entry %i, ignored.",table,entry); + continue; + } + } + + MangosStringLocale& data = mMangosStringLocaleMap[entry]; + + if(data.Content.size() < 1) + data.Content.resize(1); + + // 0 -> default, idx in to idx+1 + data.Content[0] = fields[1].GetCppString(); + + for(int i = 1; i < MAX_LOCALE; ++i) + { + std::string str = fields[i+1].GetCppString(); + if(!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if(idx >= 0) + { + // 0 -> default, idx in to idx+1 + if(data.Content.size() <= idx+1) + data.Content.resize(idx+2); + + data.Content[idx+1] = str; + } + } + } + } while (result->NextRow()); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u MaNGOS strings from table %s", mMangosStringLocaleMap.size(),table); + return true; +} + +const char *ObjectMgr::GetMangosString(int32 entry, int locale_idx) const +{ + // locale_idx==-1 -> default, locale_idx >= 0 in to idx+1 + // Content[0] always exist if exist MangosStringLocale + if(MangosStringLocale const *msl = GetMangosStringLocale(entry)) + { + if(msl->Content.size() > locale_idx+1 && !msl->Content[locale_idx+1].empty()) + return msl->Content[locale_idx+1].c_str(); + else + return msl->Content[0].c_str(); + } + + if(entry > 0) + sLog.outErrorDb("Entry %i not found in `mangos_string` table.",entry); + else + sLog.outErrorDb("Mangos string entry %i not found in DB.",entry); + return ""; +} + +void ObjectMgr::LoadFishingBaseSkillLevel() +{ + mFishingBaseForArea.clear(); // for relaod case + + uint32 count = 0; + QueryResult *result = WorldDatabase.Query("SELECT entry,skill FROM skill_fishing_base_level"); + + if( !result ) + { + barGoLink bar( 1 ); + + bar.step(); + + sLog.outString(); + sLog.outErrorDb(">> Loaded `skill_fishing_base_level`, table is empty!"); + return; + } + + barGoLink bar( result->GetRowCount() ); + + do + { + bar.step(); + + Field *fields = result->Fetch(); + uint32 entry = fields[0].GetUInt32(); + int32 skill = fields[1].GetInt32(); + + AreaTableEntry const* fArea = GetAreaEntryByAreaID(entry); + if(!fArea) + { + sLog.outErrorDb("AreaId %u defined in `skill_fishing_base_level` does not exist",entry); + continue; + } + + mFishingBaseForArea[entry] = skill; + ++count; + } + while (result->NextRow()); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u areas for fishing base skill level", count ); +} + +// Searches for the same condition already in Conditions store +// Returns Id if found, else adds it to Conditions and returns Id +uint16 ObjectMgr::GetConditionId( ConditionType condition, uint32 value1, uint32 value2 ) +{ + PlayerCondition lc = PlayerCondition(condition, value1, value2); + for (uint16 i=0; i < mConditions.size(); ++i) + { + if (lc == mConditions[i]) + return i; + } + + mConditions.push_back(lc); + + if(mConditions.size() > 0xFFFF) + { + sLog.outError("Conditions store overflow! Current and later loaded conditions will ignored!"); + return 0; + } + + return mConditions.size() - 1; +} + +bool ObjectMgr::CheckDeclinedNames( std::wstring mainpart, DeclinedName const& names ) +{ + for(int i =0; i < MAX_DECLINED_NAME_CASES; ++i) + { + std::wstring wname; + if(!Utf8toWStr(names.name[i],wname)) + return false; + + if(mainpart!=GetMainPartOfName(wname,i+1)) + return false; + } + return true; +} + +const char* ObjectMgr::GetAreaTriggerScriptName(uint32 id) +{ + AreaTriggerScriptMap::const_iterator i = mAreaTriggerScripts.find(id); + if(i!= mAreaTriggerScripts.end()) + return i->second.c_str(); + return ""; +} + +// Checks if player meets the condition +bool PlayerCondition::Meets(Player const * player) const +{ + if( !player ) + return false; // player not present, return false + + switch (condition) + { + case CONDITION_NONE: + return true; // empty condition, always met + case CONDITION_AURA: + return player->HasAura(value1, value2); + case CONDITION_ITEM: + return player->HasItemCount(value1, value2); + case CONDITION_ITEM_EQUIPPED: + return player->GetItemOrItemWithGemEquipped(value1) != NULL; + case CONDITION_ZONEID: + return player->GetZoneId() == value1; + case CONDITION_REPUTATION_RANK: + { + FactionEntry const* faction = sFactionStore.LookupEntry(value1); + return faction && player->GetReputationRank(faction) >= value2; + } + case CONDITION_TEAM: + return player->GetTeam() == value1; + case CONDITION_SKILL: + return player->HasSkill(value1) && player->GetBaseSkillValue(value1) >= value2; + case CONDITION_QUESTREWARDED: + return player->GetQuestRewardStatus(value1); + case CONDITION_QUESTTAKEN: + { + QuestStatus status = player->GetQuestStatus(value1); + return (status == QUEST_STATUS_INCOMPLETE); + } + case CONDITION_AD_COMMISSION_AURA: + { + Unit::AuraMap const& auras = player->GetAuras(); + for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) + if((itr->second->GetSpellProto()->Attributes & 0x1000010) && itr->second->GetSpellProto()->SpellVisual==3580) + return true; + return false; + } + default: + return false; + } +} + +// Verification of condition values validity +bool PlayerCondition::IsValid(ConditionType condition, uint32 value1, uint32 value2) +{ + if( condition >= MAX_CONDITION) // Wrong condition type + { + sLog.outErrorDb("Condition has bad type of %u, skipped ", condition ); + return false; + } + + switch (condition) + { + case CONDITION_AURA: + { + if(!sSpellStore.LookupEntry(value1)) + { + sLog.outErrorDb("Aura condition requires to have non existing spell (Id: %d), skipped", value1); + return false; + } + if(value2 > 2) + { + sLog.outErrorDb("Aura condition requires to have non existing effect index (%u) (must be 0..2), skipped", value2); + return false; + } + break; + } + case CONDITION_ITEM: + { + ItemPrototype const *proto = objmgr.GetItemPrototype(value1); + if(!proto) + { + sLog.outErrorDb("Item condition requires to have non existing item (%u), skipped", value1); + return false; + } + break; + } + case CONDITION_ITEM_EQUIPPED: + { + ItemPrototype const *proto = objmgr.GetItemPrototype(value1); + if(!proto) + { + sLog.outErrorDb("ItemEquipped condition requires to have non existing item (%u) equipped, skipped", value1); + return false; + } + break; + } + case CONDITION_ZONEID: + { + AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(value1); + if(!areaEntry) + { + sLog.outErrorDb("Zone condition requires to be in non existing area (%u), skipped", value1); + return false; + } + if(areaEntry->zone != 0) + { + sLog.outErrorDb("Zone condition requires to be in area (%u) which is a subzone but zone expected, skipped", value1); + return false; + } + break; + } + case CONDITION_REPUTATION_RANK: + { + FactionEntry const* factionEntry = sFactionStore.LookupEntry(value1); + if(!factionEntry) + { + sLog.outErrorDb("Reputation condition requires to have reputation non existing faction (%u), skipped", value1); + return false; + } + break; + } + case CONDITION_TEAM: + { + if (value1 != ALLIANCE && value1 != HORDE) + { + sLog.outErrorDb("Team condition specifies unknown team (%u), skipped", value1); + return false; + } + break; + } + case CONDITION_SKILL: + { + SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(value1); + if (!pSkill) + { + sLog.outErrorDb("Skill condition specifies non-existing skill (%u), skipped", value1); + return false; + } + if (value2 < 1 || value2 > sWorld.GetConfigMaxSkillValue() ) + { + sLog.outErrorDb("Skill condition specifies invalid skill value (%u), skipped", value2); + return false; + } + break; + } + case CONDITION_QUESTREWARDED: + case CONDITION_QUESTTAKEN: + { + Quest const *Quest = objmgr.GetQuestTemplate(value1); + if (!Quest) + { + sLog.outErrorDb("Quest condition specifies non-existing quest (%u), skipped", value1); + return false; + } + if(value2) + sLog.outErrorDb("Quest condition has useless data in value2 (%u)!", value2); + break; + } + case CONDITION_AD_COMMISSION_AURA: + { + if(value1) + sLog.outErrorDb("Quest condition has useless data in value1 (%u)!", value1); + if(value2) + sLog.outErrorDb("Quest condition has useless data in value2 (%u)!", value2); + break; + } + } + return true; +} + +SkillRangeType GetSkillRangeType(SkillLineEntry const *pSkill, bool racial) +{ + switch(pSkill->categoryId) + { + case SKILL_CATEGORY_LANGUAGES: return SKILL_RANGE_LANGUAGE; + case SKILL_CATEGORY_WEAPON: + if(pSkill->id!=SKILL_FIST_WEAPONS) + return SKILL_RANGE_LEVEL; + else + return SKILL_RANGE_MONO; + case SKILL_CATEGORY_ARMOR: + case SKILL_CATEGORY_CLASS: + if(pSkill->id != SKILL_POISONS && pSkill->id != SKILL_LOCKPICKING) + return SKILL_RANGE_MONO; + else + return SKILL_RANGE_LEVEL; + case SKILL_CATEGORY_SECONDARY: + case SKILL_CATEGORY_PROFESSION: + // not set skills for professions and racial abilities + if(IsProfessionSkill(pSkill->id)) + return SKILL_RANGE_RANK; + else if(racial) + return SKILL_RANGE_NONE; + else + return SKILL_RANGE_MONO; + default: + case SKILL_CATEGORY_ATTRIBUTES: //not found in dbc + case SKILL_CATEGORY_NOT_DISPLAYED: //only GENEREC(DND) + return SKILL_RANGE_NONE; + } +} + +const char* GetAreaTriggerScriptNameById(uint32 id) +{ + return objmgr.GetAreaTriggerScriptName(id); +} + + +bool LoadMangosStrings(DatabaseType& db, char const* table) +{ + // for scripting localized strings allowed use _only_ negative entries + return objmgr.LoadMangosStrings(db,table,false); +} diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h new file mode 100644 index 00000000000..f7b7d0a3cca --- /dev/null +++ b/src/game/ObjectMgr.h @@ -0,0 +1,780 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _OBJECTMGR_H +#define _OBJECTMGR_H + +#include "Log.h" +#include "Object.h" +#include "Bag.h" +#include "Creature.h" +#include "Player.h" +#include "DynamicObject.h" +#include "GameObject.h" +#include "Corpse.h" +#include "QuestDef.h" +#include "Path.h" +#include "ItemPrototype.h" +#include "NPCHandler.h" +#include "Database/DatabaseEnv.h" +#include "AuctionHouseObject.h" +#include "Mail.h" +#include "Map.h" +#include "ObjectAccessor.h" +#include "ObjectDefines.h" +#include "Policies/Singleton.h" +#include "Database/SQLStorage.h" + +#include +#include + +extern SQLStorage sCreatureStorage; +extern SQLStorage sCreatureDataAddonStorage; +extern SQLStorage sCreatureInfoAddonStorage; +extern SQLStorage sCreatureModelStorage; +extern SQLStorage sEquipmentStorage; +extern SQLStorage sGOStorage; +extern SQLStorage sPageTextStore; +extern SQLStorage sItemStorage; +extern SQLStorage sInstanceTemplate; + +class Group; +class Guild; +class ArenaTeam; +class Path; +class TransportPath; +class Item; + +struct ScriptInfo +{ + uint32 id; + uint32 delay; + uint32 command; + uint32 datalong; + uint32 datalong2; + std::string datatext; + float x; + float y; + float z; + float o; +}; + +typedef std::multimap ScriptMap; +typedef std::map ScriptMapMap; +extern ScriptMapMap sQuestEndScripts; +extern ScriptMapMap sQuestStartScripts; +extern ScriptMapMap sSpellScripts; +extern ScriptMapMap sGameObjectScripts; +extern ScriptMapMap sEventScripts; + +struct AreaTrigger +{ + uint8 requiredLevel; + uint32 requiredItem; + uint32 requiredItem2; + uint32 heroicKey; + uint32 heroicKey2; + uint32 requiredQuest; + std::string requiredFailedText; + uint32 target_mapId; + float target_X; + float target_Y; + float target_Z; + float target_Orientation; +}; + +typedef std::set CellGuidSet; +typedef std::map CellCorpseSet; +struct CellObjectGuids +{ + CellGuidSet creatures; + CellGuidSet gameobjects; + CellCorpseSet corpses; +}; +typedef HM_NAMESPACE::hash_map CellObjectGuidsMap; +typedef HM_NAMESPACE::hash_map MapObjectGuids; + +typedef HM_NAMESPACE::hash_map RespawnTimes; + +struct MangosStringLocale +{ + std::vector Content; // 0 -> default, i -> i-1 locale index +}; + +typedef HM_NAMESPACE::hash_map CreatureDataMap; +typedef HM_NAMESPACE::hash_map GameObjectDataMap; +typedef HM_NAMESPACE::hash_map CreatureLocaleMap; +typedef HM_NAMESPACE::hash_map GameObjectLocaleMap; +typedef HM_NAMESPACE::hash_map ItemLocaleMap; +typedef HM_NAMESPACE::hash_map QuestLocaleMap; +typedef HM_NAMESPACE::hash_map NpcTextLocaleMap; +typedef HM_NAMESPACE::hash_map PageTextLocaleMap; +typedef HM_NAMESPACE::hash_map MangosStringLocaleMap; + +typedef std::multimap QuestRelations; + +struct PetLevelInfo +{ + PetLevelInfo() : health(0), mana(0) { for(int i=0; i < MAX_STATS; ++i ) stats[i] = 0; } + + uint16 stats[MAX_STATS]; + uint16 health; + uint16 mana; + uint16 armor; +}; + +struct ReputationOnKillEntry +{ + uint32 repfaction1; + uint32 repfaction2; + bool is_teamaward1; + uint32 reputration_max_cap1; + int32 repvalue1; + bool is_teamaward2; + uint32 reputration_max_cap2; + int32 repvalue2; + bool team_dependent; +}; + +struct PetCreateSpellEntry +{ + uint32 spellid[4]; +}; + +#define WEATHER_SEASONS 4 +struct WeatherSeasonChances +{ + uint32 rainChance; + uint32 snowChance; + uint32 stormChance; +}; + +struct WeatherZoneChances +{ + WeatherSeasonChances data[WEATHER_SEASONS]; +}; + +struct GraveYardData +{ + uint32 safeLocId; + uint32 team; +}; +typedef std::multimap GraveYardMap; + +enum ConditionType +{ // value1 value2 for the Condition enumed + CONDITION_NONE = 0, // 0 0 + CONDITION_AURA = 1, // spell_id effindex + CONDITION_ITEM = 2, // item_id count + CONDITION_ITEM_EQUIPPED = 3, // item_id 0 + CONDITION_ZONEID = 4, // zone_id 0 + CONDITION_REPUTATION_RANK = 5, // faction_id min_rank + CONDITION_TEAM = 6, // player_team 0, (469 - Alliance 67 - Horde) + CONDITION_SKILL = 7, // skill_id skill_value + CONDITION_QUESTREWARDED = 8, // quest_id 0 + CONDITION_QUESTTAKEN = 9, // quest_id 0, for condition true while quest active. + CONDITION_AD_COMMISSION_AURA = 10, // 0 0, for condition true while one from AD ñommission aura active +}; + +#define MAX_CONDITION 11 // maximum value in ConditionType enum + +struct PlayerCondition +{ + ConditionType condition; // additional condition type + uint32 value1; // data for the condition - see ConditionType definition + uint32 value2; + + PlayerCondition(uint8 _condition = 0, uint32 _value1 = 0, uint32 _value2 = 0) + : condition(ConditionType(_condition)), value1(_value1), value2(_value2) {} + + static bool IsValid(ConditionType condition, uint32 value1, uint32 value2); + // Checks correctness of values + bool Meets(Player const * APlayer) const; // Checks if the player meets the condition + bool operator == (PlayerCondition const& lc) const + { + return (lc.condition == condition && lc.value1 == value1 && lc.value2 == value2); + } +}; + +enum SkillRangeType +{ + SKILL_RANGE_LANGUAGE, // 300..300 + SKILL_RANGE_LEVEL, // 1..max skill for level + SKILL_RANGE_MONO, // 1..1, grey monolite bar + SKILL_RANGE_RANK, // 1..skill for known rank + SKILL_RANGE_NONE, // 0..0 always +}; + +SkillRangeType GetSkillRangeType(SkillLineEntry const *pSkill, bool racial); + +#define MAX_PLAYER_NAME 12 // max allowed by client name length +#define MAX_INTERNAL_PLAYER_NAME 15 // max server internal player name length ( > MAX_PLAYER_NAME for support declined names ) + +bool normalizePlayerName(std::string& name); + +class PlayerDumpReader; + +class ObjectMgr +{ + friend class PlayerDumpReader; + + public: + ObjectMgr(); + ~ObjectMgr(); + + typedef HM_NAMESPACE::hash_map ItemMap; + + typedef std::set< Group * > GroupSet; + typedef std::set< Guild * > GuildSet; + typedef std::set< ArenaTeam * > ArenaTeamSet; + + typedef HM_NAMESPACE::hash_map QuestMap; + + typedef HM_NAMESPACE::hash_map AreaTriggerMap; + + typedef HM_NAMESPACE::hash_map AreaTriggerScriptMap; + + typedef HM_NAMESPACE::hash_map RepOnKillMap; + + typedef HM_NAMESPACE::hash_map WeatherZoneMap; + + typedef HM_NAMESPACE::hash_map PetCreateSpellMap; + + Player* GetPlayer(const char* name) const { return ObjectAccessor::Instance().FindPlayerByName(name);} + Player* GetPlayer(uint64 guid) const { return ObjectAccessor::FindPlayer(guid); } + + static GameObjectInfo const *GetGameObjectInfo(uint32 id) { return sGOStorage.LookupEntry(id); } + + void LoadGameobjectInfo(); + void AddGameobjectInfo(GameObjectInfo *goinfo); + + Group * GetGroupByLeader(const uint64 &guid) const; + void AddGroup(Group* group) { mGroupSet.insert( group ); } + void RemoveGroup(Group* group) { mGroupSet.erase( group ); } + + Guild* GetGuildByLeader(uint64 const&guid) const; + Guild* GetGuildById(const uint32 GuildId) const; + Guild* GetGuildByName(std::string guildname) const; + std::string GetGuildNameById(const uint32 GuildId) const; + void AddGuild(Guild* guild) { mGuildSet.insert( guild ); } + void RemoveGuild(Guild* guild) { mGuildSet.erase( guild ); } + + ArenaTeam* GetArenaTeamById(const uint32 ArenaTeamId) const; + ArenaTeam* GetArenaTeamByName(std::string ArenaTeamName) const; + ArenaTeam* GetArenaTeamByCapitan(uint64 const& guid) const; + void AddArenaTeam(ArenaTeam* arenateam) { mArenaTeamSet.insert( arenateam ); } + void RemoveArenaTeam(ArenaTeam* arenateam) { mArenaTeamSet.erase( arenateam ); } + + static CreatureInfo const *GetCreatureTemplate( uint32 id ); + CreatureModelInfo const *GetCreatureModelInfo( uint32 modelid ); + CreatureModelInfo const* GetCreatureModelRandomGender(uint32 display_id); + uint32 ChooseDisplayId(uint32 team, const CreatureInfo *cinfo, const CreatureData *data = NULL); + EquipmentInfo const *GetEquipmentInfo( uint32 entry ); + static CreatureDataAddon const *GetCreatureAddon( uint32 lowguid ) + { + return sCreatureDataAddonStorage.LookupEntry(lowguid); + } + + static CreatureDataAddon const *GetCreatureTemplateAddon( uint32 entry ) + { + return sCreatureInfoAddonStorage.LookupEntry(entry); + } + + static ItemPrototype const* GetItemPrototype(uint32 id) { return sItemStorage.LookupEntry(id); } + + static InstanceTemplate const* GetInstanceTemplate(uint32 map) + { + return sInstanceTemplate.LookupEntry(map); + } + + Item* GetAItem(uint32 id) + { + ItemMap::const_iterator itr = mAitems.find(id); + if (itr != mAitems.end()) + { + return itr->second; + } + return NULL; + } + void AddAItem(Item* it) + { + ASSERT( it ); + ASSERT( mAitems.find(it->GetGUIDLow()) == mAitems.end()); + mAitems[it->GetGUIDLow()] = it; + } + bool RemoveAItem(uint32 id) + { + ItemMap::iterator i = mAitems.find(id); + if (i == mAitems.end()) + { + return false; + } + mAitems.erase(i); + return true; + } + AuctionHouseObject * GetAuctionsMap( uint32 location ); + + //auction messages + void SendAuctionWonMail( AuctionEntry * auction ); + void SendAuctionSalePendingMail( AuctionEntry * auction ); + void SendAuctionSuccessfulMail( AuctionEntry * auction ); + void SendAuctionExpiredMail( AuctionEntry * auction ); + static uint32 GetAuctionCut( uint32 location, uint32 highBid ); + static uint32 GetAuctionDeposit(uint32 location, uint32 time, Item *pItem); + static uint32 GetAuctionOutBid(uint32 currentBid); + + PetLevelInfo const* GetPetLevelInfo(uint32 creature_id, uint32 level) const; + + PlayerClassInfo const* GetPlayerClassInfo(uint32 class_) const + { + if(class_ >= MAX_CLASSES) return NULL; + return &playerClassInfo[class_]; + } + void GetPlayerClassLevelInfo(uint32 class_,uint32 level, PlayerClassLevelInfo* info) const; + + PlayerInfo const* GetPlayerInfo(uint32 race, uint32 class_) const + { + if(race >= MAX_RACES) return NULL; + if(class_ >= MAX_CLASSES) return NULL; + PlayerInfo const* info = &playerInfo[race][class_]; + if(info->displayId_m==0 || info->displayId_f==0) return NULL; + return info; + } + void GetPlayerLevelInfo(uint32 race, uint32 class_,uint32 level, PlayerLevelInfo* info) const; + + uint64 GetPlayerGUIDByName(std::string name) const; + bool GetPlayerNameByGUID(const uint64 &guid, std::string &name) const; + uint32 GetPlayerTeamByGUID(const uint64 &guid) const; + uint32 GetPlayerAccountIdByGUID(const uint64 &guid) const; + uint32 GetSecurityByAccount(uint32 acc_id) const; + bool GetAccountNameByAccount(uint32 acc_id, std::string &name) const; + uint32 GetAccountByAccountName(std::string name) const; + + uint32 GetNearestTaxiNode( float x, float y, float z, uint32 mapid ); + void GetTaxiPath( uint32 source, uint32 destination, uint32 &path, uint32 &cost); + uint16 GetTaxiMount( uint32 id, uint32 team ); + void GetTaxiPathNodes( uint32 path, Path &pathnodes, std::vector& mapIds ); + void GetTransportPathNodes( uint32 path, TransportPath &pathnodes ); + + Quest const* GetQuestTemplate(uint32 quest_id) const + { + QuestMap::const_iterator itr = mQuestTemplates.find(quest_id); + return itr != mQuestTemplates.end() ? itr->second : NULL; + } + QuestMap const& GetQuestTemplates() const { return mQuestTemplates; } + + uint32 GetQuestForAreaTrigger(uint32 Trigger_ID) const + { + QuestAreaTriggerMap::const_iterator itr = mQuestAreaTriggerMap.find(Trigger_ID); + if(itr != mQuestAreaTriggerMap.end()) + return itr->second; + return 0; + } + bool IsTavernAreaTrigger(uint32 Trigger_ID) const { return mTavernAreaTriggerSet.count(Trigger_ID) != 0; } + bool IsGameObjectForQuests(uint32 entry) const { return mGameObjectForQuestSet.count(entry) != 0; } + bool IsGuildVaultGameObject(Player *player, uint64 guid) const + { + if(GameObject *go = ObjectAccessor::GetGameObject(*player, guid)) + if(go->GetGoType() == GAMEOBJECT_TYPE_GUILD_BANK) + return true; + return false; + } + + uint32 GetBattleMasterBG(uint32 entry) const + { + BattleMastersMap::const_iterator itr = mBattleMastersMap.find(entry); + if(itr != mBattleMastersMap.end()) + return itr->second; + return 2; //BATTLEGROUND_WS - i will not add include only for constant usage! + } + + void AddGossipText(GossipText *pGText); + GossipText *GetGossipText(uint32 Text_ID); + + WorldSafeLocsEntry const *GetClosestGraveYard(float x, float y, float z, uint32 MapId, uint32 team); + bool AddGraveYardLink(uint32 id, uint32 zone, uint32 team, bool inDB = true); + void LoadGraveyardZones(); + GraveYardData const* FindGraveYardData(uint32 id, uint32 zone); + + AreaTrigger const* GetAreaTrigger(uint32 trigger) const + { + AreaTriggerMap::const_iterator itr = mAreaTriggers.find( trigger ); + if( itr != mAreaTriggers.end( ) ) + return &itr->second; + return NULL; + } + + AreaTrigger const* GetGoBackTrigger(uint32 Map) const; + + const char* GetAreaTriggerScriptName(uint32 id); + + ReputationOnKillEntry const* GetReputationOnKilEntry(uint32 id) const + { + RepOnKillMap::const_iterator itr = mRepOnKill.find(id); + if(itr != mRepOnKill.end()) + return &itr->second; + return NULL; + } + + PetCreateSpellEntry const* GetPetCreateSpellEntry(uint32 id) const + { + PetCreateSpellMap::const_iterator itr = mPetCreateSpell.find(id); + if(itr != mPetCreateSpell.end()) + return &itr->second; + return NULL; + } + + void LoadGuilds(); + void LoadArenaTeams(); + void LoadGroups(); + void LoadQuests(); + void LoadQuestRelations() + { + LoadGameobjectQuestRelations(); + LoadGameobjectInvolvedRelations(); + LoadCreatureQuestRelations(); + LoadCreatureInvolvedRelations(); + } + void LoadGameobjectQuestRelations(); + void LoadGameobjectInvolvedRelations(); + void LoadCreatureQuestRelations(); + void LoadCreatureInvolvedRelations(); + + QuestRelations mGOQuestRelations; + QuestRelations mGOQuestInvolvedRelations; + QuestRelations mCreatureQuestRelations; + QuestRelations mCreatureQuestInvolvedRelations; + + void LoadGameObjectScripts(); + void LoadQuestEndScripts(); + void LoadQuestStartScripts(); + void LoadEventScripts(); + void LoadSpellScripts(); + + bool LoadMangosStrings(DatabaseType& db, char const* table, bool positive_entries); + bool LoadMangosStrings() { return LoadMangosStrings(WorldDatabase,"mangos_string",true); } + void LoadPetCreateSpells(); + void LoadCreatureLocales(); + void LoadCreatureTemplates(); + void LoadCreatures(); + void LoadCreatureRespawnTimes(); + void LoadCreatureAddons(); + void LoadCreatureModelInfo(); + void LoadEquipmentTemplates(); + void LoadGameObjectLocales(); + void LoadGameobjects(); + void LoadGameobjectRespawnTimes(); + void LoadItemPrototypes(); + void LoadItemLocales(); + void LoadQuestLocales(); + void LoadNpcTextLocales(); + void LoadPageTextLocales(); + void LoadInstanceTemplate(); + + void LoadGossipText(); + + void LoadAreaTriggerTeleports(); + void LoadQuestAreaTriggers(); + void LoadAreaTriggerScripts(); + void LoadTavernAreaTriggers(); + void LoadBattleMastersEntry(); + void LoadGameObjectForQuests(); + + void LoadItemTexts(); + void LoadPageTexts(); + + //load first auction items, because of check if item exists, when loading + void LoadAuctionItems(); + void LoadAuctions(); + void LoadPlayerInfo(); + void LoadPetLevelInfo(); + void LoadExplorationBaseXP(); + void LoadPetNames(); + void LoadPetNumber(); + void LoadCorpses(); + void LoadFishingBaseSkillLevel(); + + void LoadReputationOnKill(); + + void LoadWeatherZoneChances(); + + std::string GeneratePetName(uint32 entry); + uint32 GetBaseXP(uint32 level); + + int32 GetFishingBaseSkillLevel(uint32 entry) const + { + FishingBaseSkillMap::const_iterator itr = mFishingBaseForArea.find(entry); + return itr != mFishingBaseForArea.end() ? itr->second : 0; + } + + void ReturnOrDeleteOldMails(bool serverUp); + + void SetHighestGuids(); + uint32 GenerateLowGuid(HighGuid guidhigh); + uint32 GenerateAuctionID(); + uint32 GenerateMailID(); + uint32 GenerateItemTextID(); + uint32 GeneratePetNumber(); + + uint32 CreateItemText(std::string text); + std::string GetItemText( uint32 id ) + { + ItemTextMap::const_iterator itr = mItemTexts.find( id ); + if ( itr != mItemTexts.end() ) + return itr->second; + else + return "There is no info for this item"; + } + + typedef std::multimap ExclusiveQuestGroups; + ExclusiveQuestGroups mExclusiveQuestGroups; + + WeatherZoneChances const* GetWeatherChances(uint32 zone_id) const + { + WeatherZoneMap::const_iterator itr = mWeatherZoneMap.find(zone_id); + if(itr != mWeatherZoneMap.end()) + return &itr->second; + else + return NULL; + } + + CellObjectGuids const& GetCellObjectGuids(uint16 mapid, uint8 spawnMode, uint32 cell_id) + { + return mMapObjectGuids[MAKE_PAIR32(mapid,spawnMode)][cell_id]; + } + + CreatureData const* GetCreatureData(uint32 guid) const + { + CreatureDataMap::const_iterator itr = mCreatureDataMap.find(guid); + if(itr==mCreatureDataMap.end()) return NULL; + return &itr->second; + } + CreatureData& NewOrExistCreatureData(uint32 guid) { return mCreatureDataMap[guid]; } + void DeleteCreatureData(uint32 guid); + CreatureLocale const* GetCreatureLocale(uint32 entry) const + { + CreatureLocaleMap::const_iterator itr = mCreatureLocaleMap.find(entry); + if(itr==mCreatureLocaleMap.end()) return NULL; + return &itr->second; + } + GameObjectLocale const* GetGameObjectLocale(uint32 entry) const + { + GameObjectLocaleMap::const_iterator itr = mGameObjectLocaleMap.find(entry); + if(itr==mGameObjectLocaleMap.end()) return NULL; + return &itr->second; + } + ItemLocale const* GetItemLocale(uint32 entry) const + { + ItemLocaleMap::const_iterator itr = mItemLocaleMap.find(entry); + if(itr==mItemLocaleMap.end()) return NULL; + return &itr->second; + } + QuestLocale const* GetQuestLocale(uint32 entry) const + { + QuestLocaleMap::const_iterator itr = mQuestLocaleMap.find(entry); + if(itr==mQuestLocaleMap.end()) return NULL; + return &itr->second; + } + NpcTextLocale const* GetNpcTextLocale(uint32 entry) const + { + NpcTextLocaleMap::const_iterator itr = mNpcTextLocaleMap.find(entry); + if(itr==mNpcTextLocaleMap.end()) return NULL; + return &itr->second; + } + PageTextLocale const* GetPageTextLocale(uint32 entry) const + { + PageTextLocaleMap::const_iterator itr = mPageTextLocaleMap.find(entry); + if(itr==mPageTextLocaleMap.end()) return NULL; + return &itr->second; + } + + GameObjectData const* GetGOData(uint32 guid) const + { + GameObjectDataMap::const_iterator itr = mGameObjectDataMap.find(guid); + if(itr==mGameObjectDataMap.end()) return NULL; + return &itr->second; + } + GameObjectData& NewGOData(uint32 guid) { return mGameObjectDataMap[guid]; } + void DeleteGOData(uint32 guid); + + MangosStringLocale const* GetMangosStringLocale(int32 entry) const + { + MangosStringLocaleMap::const_iterator itr = mMangosStringLocaleMap.find(entry); + if(itr==mMangosStringLocaleMap.end()) return NULL; + return &itr->second; + } + const char *GetMangosString(int32 entry, int locale_idx) const; + const char *GetMangosStringForDBCLocale(int32 entry) const { return GetMangosString(entry,DBCLocaleIndex); } + void SetDBCLocaleIndex(uint32 lang) { DBCLocaleIndex = GetIndexForLocale(LocaleConstant(lang)); } + + void AddCorpseCellData(uint32 mapid, uint32 cellid, uint32 player_guid, uint32 instance); + void DeleteCorpseCellData(uint32 mapid, uint32 cellid, uint32 player_guid); + + time_t GetCreatureRespawnTime(uint32 loguid, uint32 instance) { return mCreatureRespawnTimes[MAKE_PAIR64(loguid,instance)]; } + void SaveCreatureRespawnTime(uint32 loguid, uint32 instance, time_t t); + time_t GetGORespawnTime(uint32 loguid, uint32 instance) { return mGORespawnTimes[MAKE_PAIR64(loguid,instance)]; } + void SaveGORespawnTime(uint32 loguid, uint32 instance, time_t t); + void DeleteRespawnTimeForInstance(uint32 instance); + + // grid objects + void AddCreatureToGrid(uint32 guid, CreatureData const* data); + void RemoveCreatureFromGrid(uint32 guid, CreatureData const* data); + void AddGameobjectToGrid(uint32 guid, GameObjectData const* data); + void RemoveGameobjectFromGrid(uint32 guid, GameObjectData const* data); + + // reserved names + void LoadReservedPlayersNames(); + bool IsReservedName(std::string name) const + { + return m_ReservedNames.find(name) != m_ReservedNames.end(); + } + + // name with valid structure and symbols + static bool IsValidName( std::string name, bool create = false ); + static bool IsValidCharterName( std::string name ); + static bool IsValidPetName( std::string name ); + + static bool CheckDeclinedNames(std::wstring mainpart, DeclinedName const& names); + + int GetIndexForLocale(LocaleConstant loc); + LocaleConstant GetLocaleForIndex(int i); + // guild bank tabs + const uint32 GetGuildBankTabPrice(uint8 Index) { return Index < GUILD_BANK_MAX_TABS ? mGuildBankTabPrice[Index] : 0; } + + uint16 GetConditionId(ConditionType condition, uint32 value1, uint32 value2); + bool IsPlayerMeetToCondition(Player const* player, uint16 condition_id) const + { + if(condition_id >= mConditions.size()) + return false; + + return mConditions[condition_id].Meets(player); + } + protected: + uint32 m_auctionid; + uint32 m_mailid; + uint32 m_ItemTextId; + + uint32 m_hiCharGuid; + uint32 m_hiCreatureGuid; + uint32 m_hiPetGuid; + uint32 m_hiItemGuid; + uint32 m_hiGoGuid; + uint32 m_hiDoGuid; + uint32 m_hiCorpseGuid; + + uint32 m_hiPetNumber; + + QuestMap mQuestTemplates; + + typedef HM_NAMESPACE::hash_map GossipTextMap; + typedef HM_NAMESPACE::hash_map QuestAreaTriggerMap; + typedef HM_NAMESPACE::hash_map BattleMastersMap; + typedef HM_NAMESPACE::hash_map ItemTextMap; + typedef std::set TavernAreaTriggerSet; + typedef std::set GameObjectForQuestSet; + + GroupSet mGroupSet; + GuildSet mGuildSet; + ArenaTeamSet mArenaTeamSet; + + ItemMap mItems; + ItemMap mAitems; + + ItemTextMap mItemTexts; + + AuctionHouseObject mHordeAuctions; + AuctionHouseObject mAllianceAuctions; + AuctionHouseObject mNeutralAuctions; + + QuestAreaTriggerMap mQuestAreaTriggerMap; + BattleMastersMap mBattleMastersMap; + TavernAreaTriggerSet mTavernAreaTriggerSet; + GameObjectForQuestSet mGameObjectForQuestSet; + GossipTextMap mGossipText; + AreaTriggerMap mAreaTriggers; + AreaTriggerScriptMap mAreaTriggerScripts; + + RepOnKillMap mRepOnKill; + + WeatherZoneMap mWeatherZoneMap; + + PetCreateSpellMap mPetCreateSpell; + + //character reserved names + typedef std::set ReservedNamesMap; + ReservedNamesMap m_ReservedNames; + + GraveYardMap mGraveYardMap; + + typedef std::vector LocalForIndex; + LocalForIndex m_LocalForIndex; + int GetOrNewIndexForLocale(LocaleConstant loc); + + int DBCLocaleIndex; + private: + void LoadScripts(ScriptMapMap& scripts, char const* tablename); + void ConvertCreatureAddonAuras(CreatureDataAddon* addon, char const* table, char const* guidEntryStr); + void LoadQuestRelationsHelper(QuestRelations& map,char const* table); + + typedef std::map PetLevelInfoMap; + // PetLevelInfoMap[creature_id][level] + PetLevelInfoMap petInfo; // [creature_id][level] + + PlayerClassInfo playerClassInfo[MAX_CLASSES]; + + void BuildPlayerLevelInfo(uint8 race, uint8 class_, uint8 level, PlayerLevelInfo* plinfo) const; + PlayerInfo playerInfo[MAX_RACES][MAX_CLASSES]; + + typedef std::map BaseXPMap; // [area level][base xp] + BaseXPMap mBaseXPTable; + + typedef std::map FishingBaseSkillMap; // [areaId][base skill level] + FishingBaseSkillMap mFishingBaseForArea; + + typedef std::map > HalfNameMap; + HalfNameMap PetHalfName0; + HalfNameMap PetHalfName1; + + MapObjectGuids mMapObjectGuids; + CreatureDataMap mCreatureDataMap; + CreatureLocaleMap mCreatureLocaleMap; + GameObjectDataMap mGameObjectDataMap; + GameObjectLocaleMap mGameObjectLocaleMap; + ItemLocaleMap mItemLocaleMap; + QuestLocaleMap mQuestLocaleMap; + NpcTextLocaleMap mNpcTextLocaleMap; + PageTextLocaleMap mPageTextLocaleMap; + MangosStringLocaleMap mMangosStringLocaleMap; + RespawnTimes mCreatureRespawnTimes; + RespawnTimes mGORespawnTimes; + + typedef std::vector GuildBankTabPriceMap; + GuildBankTabPriceMap mGuildBankTabPrice; + + // Storage for Conditions. First element (index 0) is reserved for zero-condition (nothing required) + typedef std::vector ConditionStore; + ConditionStore mConditions; + +}; + +#define objmgr MaNGOS::Singleton::Instance() +#endif + +// scripting access functions +bool MANGOS_DLL_SPEC LoadMangosStrings(DatabaseType& db, char const* table); +MANGOS_DLL_SPEC const char* GetAreaTriggerScriptNameById(uint32 id); diff --git a/src/game/ObjectPosSelector.cpp b/src/game/ObjectPosSelector.cpp new file mode 100644 index 00000000000..5936152f9be --- /dev/null +++ b/src/game/ObjectPosSelector.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ObjectPosSelector.h" + +ObjectPosSelector::ObjectPosSelector(float x,float y,float size,float dist) +: m_center_x(x),m_center_y(y),m_size(size),m_dist(dist) +{ + m_anglestep = acos(m_dist/(m_dist+2*m_size)); + + m_nextUsedPos[USED_POS_PLUS] = m_UsedPosLists[USED_POS_PLUS].end(); + m_nextUsedPos[USED_POS_MINUS] = m_UsedPosLists[USED_POS_MINUS].end(); + + m_smallStepAngle[USED_POS_PLUS] = 0; + m_smallStepAngle[USED_POS_MINUS] = 0; + + m_smallStepOk[USED_POS_PLUS] = false; + m_smallStepOk[USED_POS_MINUS] = false; + + m_smallStepNextUsedPos[USED_POS_PLUS] = NULL; + m_smallStepNextUsedPos[USED_POS_MINUS] = NULL; +} + +ObjectPosSelector::UsedPosList::value_type const* ObjectPosSelector::nextUsedPos(UsedPosType uptype) +{ + UsedPosList::const_iterator itr = m_nextUsedPos[uptype]; + if(itr!=m_UsedPosLists[uptype].end()) + ++itr; + + if(itr==m_UsedPosLists[uptype].end()) + { + if(!m_UsedPosLists[~uptype].empty()) + return &*m_UsedPosLists[~uptype].rbegin(); + else + return NULL; + } + else + return &*itr; +} + +void ObjectPosSelector::AddUsedPos(float size,float angle,float dist) +{ + if(angle>=0) + m_UsedPosLists[USED_POS_PLUS].insert(UsedPosList::value_type(angle,UsedPos(1.0,size,dist))); + else + m_UsedPosLists[USED_POS_MINUS].insert(UsedPosList::value_type(-angle,UsedPos(-1.0,size,dist))); +} + +void ObjectPosSelector::InitializeAngle() +{ + m_nextUsedPos[USED_POS_PLUS] = m_UsedPosLists[USED_POS_PLUS].begin(); + m_nextUsedPos[USED_POS_MINUS] = m_UsedPosLists[USED_POS_MINUS].begin(); + + m_smallStepAngle[USED_POS_PLUS] = 0; + m_smallStepAngle[USED_POS_MINUS] = 0; + + m_smallStepOk[USED_POS_PLUS] = true; + m_smallStepOk[USED_POS_MINUS] = true; +} + +bool ObjectPosSelector::FirstAngle(float& angle) +{ + if(m_UsedPosLists[USED_POS_PLUS].empty() && !m_UsedPosLists[USED_POS_MINUS].empty() ) + return NextAngleFor(*m_UsedPosLists[USED_POS_MINUS].begin(),1.0,USED_POS_PLUS,angle); + else if(m_UsedPosLists[USED_POS_MINUS].empty() && !m_UsedPosLists[USED_POS_PLUS].empty() ) + return NextAngleFor(*m_UsedPosLists[USED_POS_PLUS].begin(),-1.0,USED_POS_MINUS,angle); + + return false; +} + +bool ObjectPosSelector::NextAngle(float& angle) +{ + while(m_nextUsedPos[USED_POS_PLUS]!=m_UsedPosLists[USED_POS_PLUS].end() || + m_nextUsedPos[USED_POS_MINUS]!=m_UsedPosLists[USED_POS_MINUS].end() || + m_smallStepOk[USED_POS_PLUS] || m_smallStepOk[USED_POS_MINUS] ) + { + // calculate next possible angle + if(NextPosibleAngle(angle)) + return true; + } + + return false; +} + +bool ObjectPosSelector::NextUsedAngle(float& angle) +{ + while(m_nextUsedPos[USED_POS_PLUS]!=m_UsedPosLists[USED_POS_PLUS].end() || + m_nextUsedPos[USED_POS_MINUS]!=m_UsedPosLists[USED_POS_MINUS].end() ) + { + // calculate next possible angle + if(!NextPosibleAngle(angle)) + return true; + } + + return false; +} + +bool ObjectPosSelector::NextPosibleAngle( float& angle ) +{ + // ++ direction less updated + if( m_nextUsedPos[USED_POS_PLUS]!=m_UsedPosLists[USED_POS_PLUS].end() && + (m_nextUsedPos[USED_POS_MINUS]==m_UsedPosLists[USED_POS_MINUS].end() || m_nextUsedPos[USED_POS_PLUS]->first <= m_nextUsedPos[USED_POS_MINUS]->first) ) + { + bool ok; + if(m_smallStepOk[USED_POS_PLUS]) + ok = NextSmallStepAngle(1.0,USED_POS_PLUS,angle); + else + ok = NextAngleFor(*m_nextUsedPos[USED_POS_PLUS],1.0,USED_POS_PLUS,angle); + + if(!ok) + ++m_nextUsedPos[USED_POS_PLUS]; // increase. only at fail (original or checked) + return ok; + } + // -- direction less updated + else if( m_nextUsedPos[USED_POS_MINUS]!=m_UsedPosLists[USED_POS_MINUS].end()) + { + bool ok; + if(m_smallStepOk[USED_POS_MINUS]) + ok = NextSmallStepAngle(-1.0,USED_POS_MINUS,angle); + else + ok = NextAngleFor(*m_nextUsedPos[USED_POS_MINUS],-1.0,USED_POS_MINUS,angle); + + if(!ok) + ++m_nextUsedPos[USED_POS_MINUS]; + return ok; + } + else // both list empty + { + if( m_smallStepOk[USED_POS_PLUS] && (!m_smallStepOk[USED_POS_MINUS] || m_smallStepAngle[USED_POS_PLUS] <= m_smallStepAngle[USED_POS_MINUS]) ) + { + return NextSmallStepAngle(1.0,USED_POS_PLUS,angle); + } + // -- direction less updated + else if( m_smallStepOk[USED_POS_MINUS] ) + { + return NextSmallStepAngle(-1.0,USED_POS_MINUS,angle); + } + } + + // no angles + return false; +} diff --git a/src/game/ObjectPosSelector.h b/src/game/ObjectPosSelector.h new file mode 100644 index 00000000000..7423c0a741c --- /dev/null +++ b/src/game/ObjectPosSelector.h @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _OBJECT_POS_SELECTOR_H +#define _OBJECT_POS_SELECTOR_H + +#include + +#include + +enum UsedPosType { USED_POS_PLUS, USED_POS_MINUS }; + +inline UsedPosType operator ~(UsedPosType uptype) +{ + return uptype==USED_POS_PLUS ? USED_POS_MINUS : USED_POS_PLUS; +} + +struct ObjectPosSelector +{ + struct UsedPos + { + UsedPos(float sign_, float size_,float dist_) : sign(sign_), size(size_),dist(dist_) {} + + float sign; + + float size; // size of point + float dist; // dist to central point (including central point size) + }; + + typedef std::multimap UsedPosList; // abs(angle)->Node + + ObjectPosSelector(float x,float y,float size,float dist); + + void AddUsedPos(float size,float angle,float dist); + void InitializeAngle(); + + bool FirstAngle(float& angle); + bool NextAngle(float& angle); + bool NextUsedAngle(float& angle); + + bool NextPosibleAngle( float& angle ); + + bool CheckAngle(UsedPosList::value_type const& nextUsedPos, float sign, float angle ) const + { + float angle_step2 = GetAngle(nextUsedPos.second); + + float next_angle = nextUsedPos.first; + if(nextUsedPos.second.sign * sign < 0) // last node from diff. list (-pi+alpha) + next_angle = 2*M_PI-next_angle; // move to positive + + return fabs(angle)+angle_step2 <= next_angle; + } + + bool CheckOriginal() const + { + return (m_UsedPosLists[USED_POS_PLUS].empty() || CheckAngle( *m_UsedPosLists[USED_POS_PLUS].begin(),1.0,0)) && + (m_UsedPosLists[USED_POS_MINUS].empty() || CheckAngle( *m_UsedPosLists[USED_POS_MINUS].begin(),-1.0,0)); + } + + bool IsNonBalanced() const { return m_UsedPosLists[USED_POS_PLUS].empty() != m_UsedPosLists[USED_POS_MINUS].empty(); } + + bool NextAngleFor( UsedPosList::value_type const& usedPos, float sign, UsedPosType uptype, float &angle ) + { + float angle_step = GetAngle(usedPos.second); + + // next possible angle + angle = usedPos.first * usedPos.second.sign + angle_step * sign; + + UsedPosList::value_type const* nextNode = nextUsedPos(uptype); + if(nextNode) + { + // if next node permit use selected angle, then do it + if(!CheckAngle(*nextNode, sign, angle)) + { + m_smallStepOk[uptype] = false; + return false; + } + } + + // possible more points + m_smallStepOk[uptype] = true; + m_smallStepAngle[uptype] = angle; + m_smallStepNextUsedPos[uptype] = nextNode; + + return true; + } + + bool NextSmallStepAngle( float sign, UsedPosType uptype, float &angle ) + { + // next possible angle + angle = m_smallStepAngle[uptype] + m_anglestep * sign; + + if(fabs(angle) > M_PI) + { + m_smallStepOk[uptype] = false; + return false; + } + + if(m_smallStepNextUsedPos[uptype]) + { + if(fabs(angle) >= m_smallStepNextUsedPos[uptype]->first) + { + m_smallStepOk[uptype] = false; + return false; + } + + // if next node permit use selected angle, then do it + if(!CheckAngle(*m_smallStepNextUsedPos[uptype], sign, angle)) + { + m_smallStepOk[uptype] = false; + return false; + } + } + + // possible more points + m_smallStepAngle[uptype] = angle; + return true; + } + + // next used post for m_nextUsedPos[uptype] + UsedPosList::value_type const* nextUsedPos(UsedPosType uptype); + + // angle from used pos to next possible free pos + float GetAngle(UsedPos const& usedPos) const { return acos(m_dist/(usedPos.dist+usedPos.size+m_size)); } + + float m_center_x; + float m_center_y; + float m_size; // size of object in center + float m_dist; // distance for searching pos (including central object size) + float m_anglestep; + + UsedPosList m_UsedPosLists[2]; + UsedPosList::const_iterator m_nextUsedPos[2]; + + // field for small step from first after next used pos until next pos + float m_smallStepAngle[2]; + bool m_smallStepOk[2]; + UsedPosList::value_type const* m_smallStepNextUsedPos[2]; +}; +#endif diff --git a/src/game/Opcodes.cpp b/src/game/Opcodes.cpp new file mode 100644 index 00000000000..ed37eca8759 --- /dev/null +++ b/src/game/Opcodes.cpp @@ -0,0 +1,1090 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** \file + \ingroup u2w +*/ + +#include "Opcodes.h" +#include "WorldSession.h" + +/// Correspondence between opcodes and their names +OpcodeHandler opcodeTable[NUM_MSG_TYPES] = +{ + /*0x000*/ { "MSG_NULL_ACTION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x001*/ { "CMSG_BOOTME", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x002*/ { "CMSG_DBLOOKUP", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x003*/ { "SMSG_DBLOOKUP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x004*/ { "CMSG_QUERY_OBJECT_POSITION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x005*/ { "SMSG_QUERY_OBJECT_POSITION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x006*/ { "CMSG_QUERY_OBJECT_ROTATION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x007*/ { "SMSG_QUERY_OBJECT_ROTATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x008*/ { "CMSG_WORLD_TELEPORT", STATUS_LOGGEDIN, &WorldSession::HandleWorldTeleportOpcode }, + /*0x009*/ { "CMSG_TELEPORT_TO_UNIT", STATUS_LOGGEDIN, &WorldSession::Handle_NULL }, + /*0x00A*/ { "CMSG_ZONE_MAP", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x00B*/ { "SMSG_ZONE_MAP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x00C*/ { "CMSG_DEBUG_CHANGECELLZONE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x00D*/ { "CMSG_EMBLAZON_TABARD_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x00E*/ { "CMSG_UNEMBLAZON_TABARD_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x00F*/ { "CMSG_RECHARGE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x010*/ { "CMSG_LEARN_SPELL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x011*/ { "CMSG_CREATEMONSTER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x012*/ { "CMSG_DESTROYMONSTER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x013*/ { "CMSG_CREATEITEM", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x014*/ { "CMSG_CREATEGAMEOBJECT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x015*/ { "SMSG_CHECK_FOR_BOTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x016*/ { "CMSG_MAKEMONSTERATTACKGUID", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x017*/ { "CMSG_BOT_DETECTED2", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x018*/ { "CMSG_FORCEACTION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x019*/ { "CMSG_FORCEACTIONONOTHER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x01A*/ { "CMSG_FORCEACTIONSHOW", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x01B*/ { "SMSG_FORCEACTIONSHOW", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x01C*/ { "CMSG_PETGODMODE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x01D*/ { "SMSG_PETGODMODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x01E*/ { "SMSG_DEBUGINFOSPELLMISS_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x01F*/ { "CMSG_WEATHER_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x020*/ { "CMSG_UNDRESSPLAYER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x021*/ { "CMSG_BEASTMASTER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x022*/ { "CMSG_GODMODE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x023*/ { "SMSG_GODMODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x024*/ { "CMSG_CHEAT_SETMONEY", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x025*/ { "CMSG_LEVEL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x026*/ { "CMSG_PET_LEVEL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x027*/ { "CMSG_SET_WORLDSTATE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x028*/ { "CMSG_COOLDOWN_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x029*/ { "CMSG_USE_SKILL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x02A*/ { "CMSG_FLAG_QUEST", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x02B*/ { "CMSG_FLAG_QUEST_FINISH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x02C*/ { "CMSG_CLEAR_QUEST", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x02D*/ { "CMSG_SEND_EVENT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x02E*/ { "CMSG_DEBUG_AISTATE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x02F*/ { "SMSG_DEBUG_AISTATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x030*/ { "CMSG_DISABLE_PVP_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x031*/ { "CMSG_ADVANCE_SPAWN_TIME", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x032*/ { "CMSG_PVP_PORT_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x033*/ { "CMSG_AUTH_SRP6_BEGIN", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x034*/ { "CMSG_AUTH_SRP6_PROOF", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x035*/ { "CMSG_AUTH_SRP6_RECODE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x036*/ { "CMSG_CHAR_CREATE", STATUS_AUTHED, &WorldSession::HandleCharCreateOpcode }, + /*0x037*/ { "CMSG_CHAR_ENUM", STATUS_AUTHED, &WorldSession::HandleCharEnumOpcode }, + /*0x038*/ { "CMSG_CHAR_DELETE", STATUS_AUTHED, &WorldSession::HandleCharDeleteOpcode }, + /*0x039*/ { "SMSG_AUTH_SRP6_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x03A*/ { "SMSG_CHAR_CREATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x03B*/ { "SMSG_CHAR_ENUM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x03C*/ { "SMSG_CHAR_DELETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x03D*/ { "CMSG_PLAYER_LOGIN", STATUS_AUTHED, &WorldSession::HandlePlayerLoginOpcode }, + /*0x03E*/ { "SMSG_NEW_WORLD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x03F*/ { "SMSG_TRANSFER_PENDING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x040*/ { "SMSG_TRANSFER_ABORTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x041*/ { "SMSG_CHARACTER_LOGIN_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x042*/ { "SMSG_LOGIN_SETTIMESPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x043*/ { "SMSG_GAMETIME_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x044*/ { "CMSG_GAMETIME_SET", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x045*/ { "SMSG_GAMETIME_SET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x046*/ { "CMSG_GAMESPEED_SET", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x047*/ { "SMSG_GAMESPEED_SET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x048*/ { "CMSG_SERVERTIME", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x049*/ { "SMSG_SERVERTIME", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x04A*/ { "CMSG_PLAYER_LOGOUT", STATUS_LOGGEDIN, &WorldSession::HandlePlayerLogoutOpcode }, + /*0x04B*/ { "CMSG_LOGOUT_REQUEST", STATUS_LOGGEDIN, &WorldSession::HandleLogoutRequestOpcode }, + /*0x04C*/ { "SMSG_LOGOUT_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x04D*/ { "SMSG_LOGOUT_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x04E*/ { "CMSG_LOGOUT_CANCEL", STATUS_LOGGEDIN, &WorldSession::HandleLogoutCancelOpcode }, + /*0x04F*/ { "SMSG_LOGOUT_CANCEL_ACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x050*/ { "CMSG_NAME_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleNameQueryOpcode }, + /*0x051*/ { "SMSG_NAME_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x052*/ { "CMSG_PET_NAME_QUERY", STATUS_LOGGEDIN, &WorldSession::HandlePetNameQuery }, + /*0x053*/ { "SMSG_PET_NAME_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x054*/ { "CMSG_GUILD_QUERY", STATUS_AUTHED, &WorldSession::HandleGuildQueryOpcode }, + /*0x055*/ { "SMSG_GUILD_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x056*/ { "CMSG_ITEM_QUERY_SINGLE", STATUS_LOGGEDIN, &WorldSession::HandleItemQuerySingleOpcode }, + /*0x057*/ { "CMSG_ITEM_QUERY_MULTIPLE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x058*/ { "SMSG_ITEM_QUERY_SINGLE_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x059*/ { "SMSG_ITEM_QUERY_MULTIPLE_RESPONSE",STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x05A*/ { "CMSG_PAGE_TEXT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandlePageQueryOpcode }, + /*0x05B*/ { "SMSG_PAGE_TEXT_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x05C*/ { "CMSG_QUEST_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleQuestQueryOpcode }, + /*0x05D*/ { "SMSG_QUEST_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x05E*/ { "CMSG_GAMEOBJECT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleGameObjectQueryOpcode }, + /*0x05F*/ { "SMSG_GAMEOBJECT_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x060*/ { "CMSG_CREATURE_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleCreatureQueryOpcode }, + /*0x061*/ { "SMSG_CREATURE_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x062*/ { "CMSG_WHO", STATUS_LOGGEDIN, &WorldSession::HandleWhoOpcode }, + /*0x063*/ { "SMSG_WHO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x064*/ { "CMSG_WHOIS", STATUS_LOGGEDIN, &WorldSession::HandleWhoisOpcode }, + /*0x065*/ { "SMSG_WHOIS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x066*/ { "CMSG_CONTACT_LIST", STATUS_LOGGEDIN, &WorldSession::HandleFriendListOpcode }, + /*0x067*/ { "SMSG_CONTACT_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x068*/ { "SMSG_FRIEND_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x069*/ { "CMSG_ADD_FRIEND", STATUS_LOGGEDIN, &WorldSession::HandleAddFriendOpcode }, + /*0x06A*/ { "CMSG_DEL_FRIEND", STATUS_LOGGEDIN, &WorldSession::HandleDelFriendOpcode }, + /*0x06B*/ { "CMSG_SET_CONTACT_NOTES", STATUS_LOGGEDIN, &WorldSession::HandleSetFriendNoteOpcode }, + /*0x06C*/ { "CMSG_ADD_IGNORE", STATUS_LOGGEDIN, &WorldSession::HandleAddIgnoreOpcode }, + /*0x06D*/ { "CMSG_DEL_IGNORE", STATUS_LOGGEDIN, &WorldSession::HandleDelIgnoreOpcode }, + /*0x06E*/ { "CMSG_GROUP_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleGroupInviteOpcode }, + /*0x06F*/ { "SMSG_GROUP_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x070*/ { "CMSG_GROUP_CANCEL", STATUS_LOGGEDIN, &WorldSession::Handle_Depricated }, + /*0x071*/ { "SMSG_GROUP_CANCEL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x072*/ { "CMSG_GROUP_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleGroupAcceptOpcode }, + /*0x073*/ { "CMSG_GROUP_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandleGroupDeclineOpcode }, + /*0x074*/ { "SMSG_GROUP_DECLINE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x075*/ { "CMSG_GROUP_UNINVITE", STATUS_LOGGEDIN, &WorldSession::HandleGroupUninviteNameOpcode }, + /*0x076*/ { "CMSG_GROUP_UNINVITE_GUID", STATUS_LOGGEDIN, &WorldSession::HandleGroupUninviteGuidOpcode }, + /*0x077*/ { "SMSG_GROUP_UNINVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x078*/ { "CMSG_GROUP_SET_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleGroupSetLeaderOpcode }, + /*0x079*/ { "SMSG_GROUP_SET_LEADER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x07A*/ { "CMSG_LOOT_METHOD", STATUS_LOGGEDIN, &WorldSession::HandleLootMethodOpcode }, + /*0x07B*/ { "CMSG_GROUP_DISBAND", STATUS_LOGGEDIN, &WorldSession::HandleGroupLeaveOpcode }, + /*0x07C*/ { "SMSG_GROUP_DESTROYED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x07D*/ { "SMSG_GROUP_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x07E*/ { "SMSG_PARTY_MEMBER_STATS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x07F*/ { "SMSG_PARTY_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x080*/ { "UMSG_UPDATE_GROUP_MEMBERS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x081*/ { "CMSG_GUILD_CREATE", STATUS_LOGGEDIN, &WorldSession::HandleGuildCreateOpcode }, + /*0x082*/ { "CMSG_GUILD_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleGuildInviteOpcode }, + /*0x083*/ { "SMSG_GUILD_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x084*/ { "CMSG_GUILD_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleGuildAcceptOpcode }, + /*0x085*/ { "CMSG_GUILD_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandleGuildDeclineOpcode }, + /*0x086*/ { "SMSG_GUILD_DECLINE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x087*/ { "CMSG_GUILD_INFO", STATUS_LOGGEDIN, &WorldSession::HandleGuildInfoOpcode }, + /*0x088*/ { "SMSG_GUILD_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x089*/ { "CMSG_GUILD_ROSTER", STATUS_LOGGEDIN, &WorldSession::HandleGuildRosterOpcode }, + /*0x08A*/ { "SMSG_GUILD_ROSTER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x08B*/ { "CMSG_GUILD_PROMOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildPromoteOpcode }, + /*0x08C*/ { "CMSG_GUILD_DEMOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildDemoteOpcode }, + /*0x08D*/ { "CMSG_GUILD_LEAVE", STATUS_LOGGEDIN, &WorldSession::HandleGuildLeaveOpcode }, + /*0x08E*/ { "CMSG_GUILD_REMOVE", STATUS_LOGGEDIN, &WorldSession::HandleGuildRemoveOpcode }, + /*0x08F*/ { "CMSG_GUILD_DISBAND", STATUS_LOGGEDIN, &WorldSession::HandleGuildDisbandOpcode }, + /*0x090*/ { "CMSG_GUILD_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleGuildLeaderOpcode }, + /*0x091*/ { "CMSG_GUILD_MOTD", STATUS_LOGGEDIN, &WorldSession::HandleGuildMOTDOpcode }, + /*0x092*/ { "SMSG_GUILD_EVENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x093*/ { "SMSG_GUILD_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x094*/ { "UMSG_UPDATE_GUILD", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x095*/ { "CMSG_MESSAGECHAT", STATUS_LOGGEDIN, &WorldSession::HandleMessagechatOpcode }, + /*0x096*/ { "SMSG_MESSAGECHAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x097*/ { "CMSG_JOIN_CHANNEL", STATUS_LOGGEDIN, &WorldSession::HandleChannelJoin }, + /*0x098*/ { "CMSG_LEAVE_CHANNEL", STATUS_LOGGEDIN, &WorldSession::HandleChannelLeave }, + /*0x099*/ { "SMSG_CHANNEL_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x09A*/ { "CMSG_CHANNEL_LIST", STATUS_LOGGEDIN, &WorldSession::HandleChannelList }, + /*0x09B*/ { "SMSG_CHANNEL_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x09C*/ { "CMSG_CHANNEL_PASSWORD", STATUS_LOGGEDIN, &WorldSession::HandleChannelPassword }, + /*0x09D*/ { "CMSG_CHANNEL_SET_OWNER", STATUS_LOGGEDIN, &WorldSession::HandleChannelSetOwner }, + /*0x09E*/ { "CMSG_CHANNEL_OWNER", STATUS_LOGGEDIN, &WorldSession::HandleChannelOwner }, + /*0x09F*/ { "CMSG_CHANNEL_MODERATOR", STATUS_LOGGEDIN, &WorldSession::HandleChannelModerator }, + /*0x0A0*/ { "CMSG_CHANNEL_UNMODERATOR", STATUS_LOGGEDIN, &WorldSession::HandleChannelUnmoderator }, + /*0x0A1*/ { "CMSG_CHANNEL_MUTE", STATUS_LOGGEDIN, &WorldSession::HandleChannelMute }, + /*0x0A2*/ { "CMSG_CHANNEL_UNMUTE", STATUS_LOGGEDIN, &WorldSession::HandleChannelUnmute }, + /*0x0A3*/ { "CMSG_CHANNEL_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleChannelInvite }, + /*0x0A4*/ { "CMSG_CHANNEL_KICK", STATUS_LOGGEDIN, &WorldSession::HandleChannelKick }, + /*0x0A5*/ { "CMSG_CHANNEL_BAN", STATUS_LOGGEDIN, &WorldSession::HandleChannelBan }, + /*0x0A6*/ { "CMSG_CHANNEL_UNBAN", STATUS_LOGGEDIN, &WorldSession::HandleChannelUnban }, + /*0x0A7*/ { "CMSG_CHANNEL_ANNOUNCEMENTS", STATUS_LOGGEDIN, &WorldSession::HandleChannelAnnounce }, + /*0x0A8*/ { "CMSG_CHANNEL_MODERATE", STATUS_LOGGEDIN, &WorldSession::HandleChannelModerate }, + /*0x0A9*/ { "SMSG_UPDATE_OBJECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0AA*/ { "SMSG_DESTROY_OBJECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0AB*/ { "CMSG_USE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleUseItemOpcode }, + /*0x0AC*/ { "CMSG_OPEN_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleOpenItemOpcode }, + /*0x0AD*/ { "CMSG_READ_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleReadItem }, + /*0x0AE*/ { "SMSG_READ_ITEM_OK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0AF*/ { "SMSG_READ_ITEM_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0B0*/ { "SMSG_ITEM_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0B1*/ { "CMSG_GAMEOBJ_USE", STATUS_LOGGEDIN, &WorldSession::HandleGameObjectUseOpcode }, + /*0x0B2*/ { "CMSG_GAMEOBJ_CHAIR_USE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0B3*/ { "SMSG_GAMEOBJECT_CUSTOM_ANIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0B4*/ { "CMSG_AREATRIGGER", STATUS_LOGGEDIN, &WorldSession::HandleAreaTriggerOpcode }, + /*0x0B5*/ { "MSG_MOVE_START_FORWARD", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0B6*/ { "MSG_MOVE_START_BACKWARD", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0B7*/ { "MSG_MOVE_STOP", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0B8*/ { "MSG_MOVE_START_STRAFE_LEFT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0B9*/ { "MSG_MOVE_START_STRAFE_RIGHT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0BA*/ { "MSG_MOVE_STOP_STRAFE", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0BB*/ { "MSG_MOVE_JUMP", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0BC*/ { "MSG_MOVE_START_TURN_LEFT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0BD*/ { "MSG_MOVE_START_TURN_RIGHT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0BE*/ { "MSG_MOVE_STOP_TURN", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0BF*/ { "MSG_MOVE_START_PITCH_UP", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0C0*/ { "MSG_MOVE_START_PITCH_DOWN", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0C1*/ { "MSG_MOVE_STOP_PITCH", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0C2*/ { "MSG_MOVE_SET_RUN_MODE", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0C3*/ { "MSG_MOVE_SET_WALK_MODE", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0C4*/ { "MSG_MOVE_TOGGLE_LOGGING", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0C5*/ { "MSG_MOVE_TELEPORT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0C6*/ { "MSG_MOVE_TELEPORT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0C7*/ { "MSG_MOVE_TELEPORT_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveTeleportAck }, + /*0x0C8*/ { "MSG_MOVE_TOGGLE_FALL_LOGGING", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0C9*/ { "MSG_MOVE_FALL_LAND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0CA*/ { "MSG_MOVE_START_SWIM", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0CB*/ { "MSG_MOVE_STOP_SWIM", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0CC*/ { "MSG_MOVE_SET_RUN_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0CD*/ { "MSG_MOVE_SET_RUN_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0CE*/ { "MSG_MOVE_SET_RUN_BACK_SPEED_CHEAT",STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0CF*/ { "MSG_MOVE_SET_RUN_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D0*/ { "MSG_MOVE_SET_WALK_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D1*/ { "MSG_MOVE_SET_WALK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D2*/ { "MSG_MOVE_SET_SWIM_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D3*/ { "MSG_MOVE_SET_SWIM_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D4*/ { "MSG_MOVE_SET_SWIM_BACK_SPEED_CHEAT",STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D5*/ { "MSG_MOVE_SET_SWIM_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D6*/ { "MSG_MOVE_SET_ALL_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D7*/ { "MSG_MOVE_SET_TURN_RATE_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D8*/ { "MSG_MOVE_SET_TURN_RATE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D9*/ { "MSG_MOVE_TOGGLE_COLLISION_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0DA*/ { "MSG_MOVE_SET_FACING", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0DB*/ { "MSG_MOVE_SET_PITCH", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0DC*/ { "MSG_MOVE_WORLDPORT_ACK", STATUS_TRANSFER_PENDING, &WorldSession::HandleMoveWorldportAckOpcode}, + /*0x0DD*/ { "SMSG_MONSTER_MOVE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0DE*/ { "SMSG_MOVE_WATER_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0DF*/ { "SMSG_MOVE_LAND_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0E0*/ { "MSG_MOVE_SET_RAW_POSITION_ACK", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0E1*/ { "CMSG_MOVE_SET_RAW_POSITION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0E2*/ { "SMSG_FORCE_RUN_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0E3*/ { "CMSG_FORCE_RUN_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + /*0x0E4*/ { "SMSG_FORCE_RUN_BACK_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0E5*/ { "CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK",STATUS_LOGGEDIN,&WorldSession::HandleForceSpeedChangeAck }, + /*0x0E6*/ { "SMSG_FORCE_SWIM_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0E7*/ { "CMSG_FORCE_SWIM_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + /*0x0E8*/ { "SMSG_FORCE_MOVE_ROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0E9*/ { "CMSG_FORCE_MOVE_ROOT_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveRootAck }, + /*0x0EA*/ { "SMSG_FORCE_MOVE_UNROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0EB*/ { "CMSG_FORCE_MOVE_UNROOT_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveUnRootAck }, + /*0x0EC*/ { "MSG_MOVE_ROOT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0ED*/ { "MSG_MOVE_UNROOT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0EE*/ { "MSG_MOVE_HEARTBEAT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0EF*/ { "SMSG_MOVE_KNOCK_BACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0F0*/ { "CMSG_MOVE_KNOCK_BACK_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveKnockBackAck }, + /*0x0F1*/ { "MSG_MOVE_KNOCK_BACK", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0F2*/ { "SMSG_MOVE_FEATHER_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0F3*/ { "SMSG_MOVE_NORMAL_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0F4*/ { "SMSG_MOVE_SET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0F5*/ { "SMSG_MOVE_UNSET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0F6*/ { "CMSG_MOVE_HOVER_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveHoverAck }, + /*0x0F7*/ { "MSG_MOVE_HOVER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0F8*/ { "CMSG_TRIGGER_CINEMATIC_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0F9*/ { "CMSG_OPENING_CINEMATIC", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0FA*/ { "SMSG_TRIGGER_CINEMATIC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0FB*/ { "CMSG_NEXT_CINEMATIC_CAMERA", STATUS_LOGGEDIN, &WorldSession::HandleNextCinematicCamera }, + /*0x0FC*/ { "CMSG_COMPLETE_CINEMATIC", STATUS_LOGGEDIN, &WorldSession::HandleCompleteCinema }, + /*0x0FD*/ { "SMSG_TUTORIAL_FLAGS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0FE*/ { "CMSG_TUTORIAL_FLAG", STATUS_LOGGEDIN, &WorldSession::HandleTutorialFlag }, + /*0x0FF*/ { "CMSG_TUTORIAL_CLEAR", STATUS_LOGGEDIN, &WorldSession::HandleTutorialClear }, + /*0x100*/ { "CMSG_TUTORIAL_RESET", STATUS_LOGGEDIN, &WorldSession::HandleTutorialReset }, + /*0x101*/ { "CMSG_STANDSTATECHANGE", STATUS_LOGGEDIN, &WorldSession::HandleStandStateChangeOpcode }, + /*0x102*/ { "CMSG_EMOTE", STATUS_LOGGEDIN, &WorldSession::HandleEmoteOpcode }, + /*0x103*/ { "SMSG_EMOTE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x104*/ { "CMSG_TEXT_EMOTE", STATUS_LOGGEDIN, &WorldSession::HandleTextEmoteOpcode }, + /*0x105*/ { "SMSG_TEXT_EMOTE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x106*/ { "CMSG_AUTOEQUIP_GROUND_ITEM", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x107*/ { "CMSG_AUTOSTORE_GROUND_ITEM", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x108*/ { "CMSG_AUTOSTORE_LOOT_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutostoreLootItemOpcode }, + /*0x109*/ { "CMSG_STORE_LOOT_IN_SLOT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x10A*/ { "CMSG_AUTOEQUIP_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoEquipItemOpcode }, + /*0x10B*/ { "CMSG_AUTOSTORE_BAG_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoStoreBagItemOpcode }, + /*0x10C*/ { "CMSG_SWAP_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSwapItem }, + /*0x10D*/ { "CMSG_SWAP_INV_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSwapInvItemOpcode }, + /*0x10E*/ { "CMSG_SPLIT_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSplitItemOpcode }, + /*0x10F*/ { "CMSG_AUTOEQUIP_ITEM_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleAutoEquipItemSlotOpcode }, + /*0x110*/ { "OBSOLETE_DROP_ITEM", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x111*/ { "CMSG_DESTROYITEM", STATUS_LOGGEDIN, &WorldSession::HandleDestroyItemOpcode }, + /*0x112*/ { "SMSG_INVENTORY_CHANGE_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x113*/ { "SMSG_OPEN_CONTAINER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x114*/ { "CMSG_INSPECT", STATUS_LOGGEDIN, &WorldSession::HandleInspectOpcode }, + /*0x115*/ { "SMSG_INSPECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x116*/ { "CMSG_INITIATE_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleInitiateTradeOpcode }, + /*0x117*/ { "CMSG_BEGIN_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleBeginTradeOpcode }, + /*0x118*/ { "CMSG_BUSY_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleBusyTradeOpcode }, + /*0x119*/ { "CMSG_IGNORE_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleIgnoreTradeOpcode }, + /*0x11A*/ { "CMSG_ACCEPT_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleAcceptTradeOpcode }, + /*0x11B*/ { "CMSG_UNACCEPT_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleUnacceptTradeOpcode }, + /*0x11C*/ { "CMSG_CANCEL_TRADE", STATUS_AUTHED, &WorldSession::HandleCancelTradeOpcode }, + // also send after logout complete + /*0x11D*/ { "CMSG_SET_TRADE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSetTradeItemOpcode }, + /*0x11E*/ { "CMSG_CLEAR_TRADE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleClearTradeItemOpcode }, + /*0x11F*/ { "CMSG_SET_TRADE_GOLD", STATUS_LOGGEDIN, &WorldSession::HandleSetTradeGoldOpcode }, + /*0x120*/ { "SMSG_TRADE_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x121*/ { "SMSG_TRADE_STATUS_EXTENDED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x122*/ { "SMSG_INITIALIZE_FACTIONS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x123*/ { "SMSG_SET_FACTION_VISIBLE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x124*/ { "SMSG_SET_FACTION_STANDING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x125*/ { "CMSG_SET_FACTION_ATWAR", STATUS_LOGGEDIN, &WorldSession::HandleSetFactionAtWar }, + /*0x126*/ { "CMSG_SET_FACTION_CHEAT", STATUS_LOGGEDIN, &WorldSession::HandleSetFactionCheat }, + /*0x127*/ { "SMSG_SET_PROFICIENCY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x128*/ { "CMSG_SET_ACTION_BUTTON", STATUS_LOGGEDIN, &WorldSession::HandleSetActionButtonOpcode }, + /*0x129*/ { "SMSG_ACTION_BUTTONS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x12A*/ { "SMSG_INITIAL_SPELLS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x12B*/ { "SMSG_LEARNED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x12C*/ { "SMSG_SUPERCEDED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x12D*/ { "CMSG_NEW_SPELL_SLOT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x12E*/ { "CMSG_CAST_SPELL", STATUS_LOGGEDIN, &WorldSession::HandleCastSpellOpcode }, + /*0x12F*/ { "CMSG_CANCEL_CAST", STATUS_LOGGEDIN, &WorldSession::HandleCancelCastOpcode }, + /*0x130*/ { "SMSG_CAST_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x131*/ { "SMSG_SPELL_START", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x132*/ { "SMSG_SPELL_GO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x133*/ { "SMSG_SPELL_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x134*/ { "SMSG_SPELL_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x135*/ { "SMSG_COOLDOWN_EVENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x136*/ { "CMSG_CANCEL_AURA", STATUS_LOGGEDIN, &WorldSession::HandleCancelAuraOpcode }, + /*0x137*/ { "SMSG_UPDATE_AURA_DURATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x138*/ { "SMSG_PET_CAST_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x139*/ { "MSG_CHANNEL_START", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x13A*/ { "MSG_CHANNEL_UPDATE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x13B*/ { "CMSG_CANCEL_CHANNELLING", STATUS_LOGGEDIN, &WorldSession::HandleCancelChanneling }, + /*0x13C*/ { "SMSG_AI_REACTION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x13D*/ { "CMSG_SET_SELECTION", STATUS_LOGGEDIN, &WorldSession::HandleSetSelectionOpcode }, + /*0x13E*/ { "CMSG_SET_TARGET_OBSOLETE", STATUS_LOGGEDIN, &WorldSession::HandleSetTargetOpcode }, + /*0x13F*/ { "CMSG_UNUSED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x140*/ { "CMSG_UNUSED2", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x141*/ { "CMSG_ATTACKSWING", STATUS_LOGGEDIN, &WorldSession::HandleAttackSwingOpcode }, + /*0x142*/ { "CMSG_ATTACKSTOP", STATUS_LOGGEDIN, &WorldSession::HandleAttackStopOpcode }, + /*0x143*/ { "SMSG_ATTACKSTART", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x144*/ { "SMSG_ATTACKSTOP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x145*/ { "SMSG_ATTACKSWING_NOTINRANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x146*/ { "SMSG_ATTACKSWING_BADFACING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x147*/ { "SMSG_ATTACKSWING_NOTSTANDING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x148*/ { "SMSG_ATTACKSWING_DEADTARGET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x149*/ { "SMSG_ATTACKSWING_CANT_ATTACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x14A*/ { "SMSG_ATTACKERSTATEUPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x14B*/ { "SMSG_VICTIMSTATEUPDATE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x14C*/ { "SMSG_DAMAGE_DONE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x14D*/ { "SMSG_DAMAGE_TAKEN_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x14E*/ { "SMSG_CANCEL_COMBAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x14F*/ { "SMSG_PLAYER_COMBAT_XP_GAIN_OBSOLETE",STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x150*/ { "SMSG_SPELLHEALLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x151*/ { "SMSG_SPELLENERGIZELOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x152*/ { "CMSG_SHEATHE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x153*/ { "CMSG_SAVE_PLAYER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x154*/ { "CMSG_SETDEATHBINDPOINT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x155*/ { "SMSG_BINDPOINTUPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x156*/ { "CMSG_GETDEATHBINDZONE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x157*/ { "SMSG_BINDZONEREPLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x158*/ { "SMSG_PLAYERBOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x159*/ { "SMSG_CLIENT_CONTROL_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x15A*/ { "CMSG_REPOP_REQUEST", STATUS_LOGGEDIN, &WorldSession::HandleRepopRequestOpcode }, + /*0x15B*/ { "SMSG_RESURRECT_REQUEST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x15C*/ { "CMSG_RESURRECT_RESPONSE", STATUS_LOGGEDIN, &WorldSession::HandleResurrectResponseOpcode }, + /*0x15D*/ { "CMSG_LOOT", STATUS_LOGGEDIN, &WorldSession::HandleLootOpcode }, + /*0x15E*/ { "CMSG_LOOT_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleLootMoneyOpcode }, + /*0x15F*/ { "CMSG_LOOT_RELEASE", STATUS_LOGGEDIN, &WorldSession::HandleLootReleaseOpcode }, + /*0x160*/ { "SMSG_LOOT_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x161*/ { "SMSG_LOOT_RELEASE_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x162*/ { "SMSG_LOOT_REMOVED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x163*/ { "SMSG_LOOT_MONEY_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x164*/ { "SMSG_LOOT_ITEM_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x165*/ { "SMSG_LOOT_CLEAR_MONEY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x166*/ { "SMSG_ITEM_PUSH_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x167*/ { "SMSG_DUEL_REQUESTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x168*/ { "SMSG_DUEL_OUTOFBOUNDS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x169*/ { "SMSG_DUEL_INBOUNDS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x16A*/ { "SMSG_DUEL_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x16B*/ { "SMSG_DUEL_WINNER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x16C*/ { "CMSG_DUEL_ACCEPTED", STATUS_LOGGEDIN, &WorldSession::HandleDuelAcceptedOpcode }, + /*0x16D*/ { "CMSG_DUEL_CANCELLED", STATUS_LOGGEDIN, &WorldSession::HandleDuelCancelledOpcode }, + /*0x16E*/ { "SMSG_MOUNTRESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x16F*/ { "SMSG_DISMOUNTRESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x170*/ { "SMSG_PUREMOUNT_CANCELLED_OBSOLETE",STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x171*/ { "CMSG_MOUNTSPECIAL_ANIM", STATUS_LOGGEDIN, &WorldSession::HandleMountSpecialAnimOpcode }, + /*0x172*/ { "SMSG_MOUNTSPECIAL_ANIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x173*/ { "SMSG_PET_TAME_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x174*/ { "CMSG_PET_SET_ACTION", STATUS_LOGGEDIN, &WorldSession::HandlePetSetAction }, + /*0x175*/ { "CMSG_PET_ACTION", STATUS_LOGGEDIN, &WorldSession::HandlePetAction }, + /*0x176*/ { "CMSG_PET_ABANDON", STATUS_LOGGEDIN, &WorldSession::HandlePetAbandon }, + /*0x177*/ { "CMSG_PET_RENAME", STATUS_LOGGEDIN, &WorldSession::HandlePetRename }, + /*0x178*/ { "SMSG_PET_NAME_INVALID", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x179*/ { "SMSG_PET_SPELLS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x17A*/ { "SMSG_PET_MODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x17B*/ { "CMSG_GOSSIP_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleGossipHelloOpcode }, + /*0x17C*/ { "CMSG_GOSSIP_SELECT_OPTION", STATUS_LOGGEDIN, &WorldSession::HandleGossipSelectOptionOpcode }, + /*0x17D*/ { "SMSG_GOSSIP_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x17E*/ { "SMSG_GOSSIP_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x17F*/ { "CMSG_NPC_TEXT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleNpcTextQueryOpcode }, + /*0x180*/ { "SMSG_NPC_TEXT_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x181*/ { "SMSG_NPC_WONT_TALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x182*/ { "CMSG_QUESTGIVER_STATUS_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverStatusQueryOpcode}, + /*0x183*/ { "SMSG_QUESTGIVER_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x184*/ { "CMSG_QUESTGIVER_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverHelloOpcode }, + /*0x185*/ { "SMSG_QUESTGIVER_QUEST_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x186*/ { "CMSG_QUESTGIVER_QUERY_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverQuestQueryOpcode}, + /*0x187*/ { "CMSG_QUESTGIVER_QUEST_AUTOLAUNCH", STATUS_LOGGEDIN, &WorldSession::HandleQuestAutoLaunch }, + /*0x188*/ { "SMSG_QUESTGIVER_QUEST_DETAILS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x189*/ { "CMSG_QUESTGIVER_ACCEPT_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverAcceptQuestOpcode}, + /*0x18A*/ { "CMSG_QUESTGIVER_COMPLETE_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestComplete }, + /*0x18B*/ { "SMSG_QUESTGIVER_REQUEST_ITEMS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x18C*/ { "CMSG_QUESTGIVER_REQUEST_REWARD", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverRequestRewardOpcode}, + /*0x18D*/ { "SMSG_QUESTGIVER_OFFER_REWARD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x18E*/ { "CMSG_QUESTGIVER_CHOOSE_REWARD", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverChooseRewardOpcode}, + /*0x18F*/ { "SMSG_QUESTGIVER_QUEST_INVALID", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x190*/ { "CMSG_QUESTGIVER_CANCEL", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverCancel }, + /*0x191*/ { "SMSG_QUESTGIVER_QUEST_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x192*/ { "SMSG_QUESTGIVER_QUEST_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x193*/ { "CMSG_QUESTLOG_SWAP_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestLogSwapQuest }, + /*0x194*/ { "CMSG_QUESTLOG_REMOVE_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestLogRemoveQuest }, + /*0x195*/ { "SMSG_QUESTLOG_FULL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x196*/ { "SMSG_QUESTUPDATE_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x197*/ { "SMSG_QUESTUPDATE_FAILEDTIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x198*/ { "SMSG_QUESTUPDATE_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x199*/ { "SMSG_QUESTUPDATE_ADD_KILL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x19A*/ { "SMSG_QUESTUPDATE_ADD_ITEM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x19B*/ { "CMSG_QUEST_CONFIRM_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleQuestConfirmAccept }, + /*0x19C*/ { "SMSG_QUEST_CONFIRM_ACCEPT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x19D*/ { "CMSG_PUSHQUESTTOPARTY", STATUS_LOGGEDIN, &WorldSession::HandleQuestPushToParty }, + /*0x19E*/ { "CMSG_LIST_INVENTORY", STATUS_LOGGEDIN, &WorldSession::HandleListInventoryOpcode }, + /*0x19F*/ { "SMSG_LIST_INVENTORY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1A0*/ { "CMSG_SELL_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSellItemOpcode }, + /*0x1A1*/ { "SMSG_SELL_ITEM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1A2*/ { "CMSG_BUY_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleBuyItemOpcode }, + /*0x1A3*/ { "CMSG_BUY_ITEM_IN_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleBuyItemInSlotOpcode }, + /*0x1A4*/ { "SMSG_BUY_ITEM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1A5*/ { "SMSG_BUY_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1A6*/ { "CMSG_TAXICLEARALLNODES", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1A7*/ { "CMSG_TAXIENABLEALLNODES", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1A8*/ { "CMSG_TAXISHOWNODES", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1A9*/ { "SMSG_SHOWTAXINODES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1AA*/ { "CMSG_TAXINODE_STATUS_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleTaxiNodeStatusQueryOpcode }, + /*0x1AB*/ { "SMSG_TAXINODE_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1AC*/ { "CMSG_TAXIQUERYAVAILABLENODES", STATUS_LOGGEDIN, &WorldSession::HandleTaxiQueryAvailableNodesOpcode}, + /*0x1AD*/ { "CMSG_ACTIVATETAXI", STATUS_LOGGEDIN, &WorldSession::HandleActivateTaxiOpcode }, + /*0x1AE*/ { "SMSG_ACTIVATETAXIREPLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1AF*/ { "SMSG_NEW_TAXI_PATH", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1B0*/ { "CMSG_TRAINER_LIST", STATUS_LOGGEDIN, &WorldSession::HandleTrainerListOpcode }, + /*0x1B1*/ { "SMSG_TRAINER_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1B2*/ { "CMSG_TRAINER_BUY_SPELL", STATUS_LOGGEDIN, &WorldSession::HandleTrainerBuySpellOpcode }, + /*0x1B3*/ { "SMSG_TRAINER_BUY_SUCCEEDED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1B4*/ { "SMSG_TRAINER_BUY_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1B5*/ { "CMSG_BINDER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleBinderActivateOpcode }, + /*0x1B6*/ { "SMSG_PLAYERBINDERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1B7*/ { "CMSG_BANKER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleBankerActivateOpcode }, + /*0x1B8*/ { "SMSG_SHOW_BANK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1B9*/ { "CMSG_BUY_BANK_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleBuyBankSlotOpcode }, + /*0x1BA*/ { "SMSG_BUY_BANK_SLOT_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1BB*/ { "CMSG_PETITION_SHOWLIST", STATUS_LOGGEDIN, &WorldSession::HandlePetitionShowListOpcode }, + /*0x1BC*/ { "SMSG_PETITION_SHOWLIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1BD*/ { "CMSG_PETITION_BUY", STATUS_LOGGEDIN, &WorldSession::HandlePetitionBuyOpcode }, + /*0x1BE*/ { "CMSG_PETITION_SHOW_SIGNATURES", STATUS_LOGGEDIN, &WorldSession::HandlePetitionShowSignOpcode }, + /*0x1BF*/ { "SMSG_PETITION_SHOW_SIGNATURES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1C0*/ { "CMSG_PETITION_SIGN", STATUS_LOGGEDIN, &WorldSession::HandlePetitionSignOpcode }, + /*0x1C1*/ { "SMSG_PETITION_SIGN_RESULTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1C2*/ { "MSG_PETITION_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandlePetitionDeclineOpcode }, + /*0x1C3*/ { "CMSG_OFFER_PETITION", STATUS_LOGGEDIN, &WorldSession::HandleOfferPetitionOpcode }, + /*0x1C4*/ { "CMSG_TURN_IN_PETITION", STATUS_LOGGEDIN, &WorldSession::HandleTurnInPetitionOpcode }, + /*0x1C5*/ { "SMSG_TURN_IN_PETITION_RESULTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1C6*/ { "CMSG_PETITION_QUERY", STATUS_LOGGEDIN, &WorldSession::HandlePetitionQueryOpcode }, + /*0x1C7*/ { "SMSG_PETITION_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1C8*/ { "SMSG_FISH_NOT_HOOKED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1C9*/ { "SMSG_FISH_ESCAPED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1CA*/ { "CMSG_BUG", STATUS_LOGGEDIN, &WorldSession::HandleBugOpcode }, + /*0x1CB*/ { "SMSG_NOTIFICATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1CC*/ { "CMSG_PLAYED_TIME", STATUS_LOGGEDIN, &WorldSession::HandlePlayedTime }, + /*0x1CD*/ { "SMSG_PLAYED_TIME", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1CE*/ { "CMSG_QUERY_TIME", STATUS_LOGGEDIN, &WorldSession::HandleQueryTimeOpcode }, + /*0x1CF*/ { "SMSG_QUERY_TIME_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1D0*/ { "SMSG_LOG_XPGAIN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1D1*/ { "SMSG_AURACASTLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1D2*/ { "CMSG_RECLAIM_CORPSE", STATUS_LOGGEDIN, &WorldSession::HandleCorpseReclaimOpcode }, + /*0x1D3*/ { "CMSG_WRAP_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleWrapItemOpcode }, + /*0x1D4*/ { "SMSG_LEVELUP_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1D5*/ { "MSG_MINIMAP_PING", STATUS_LOGGEDIN, &WorldSession::HandleMinimapPingOpcode }, + /*0x1D6*/ { "SMSG_RESISTLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1D7*/ { "SMSG_ENCHANTMENTLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1D8*/ { "CMSG_SET_SKILL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1D9*/ { "SMSG_START_MIRROR_TIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1DA*/ { "SMSG_PAUSE_MIRROR_TIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1DB*/ { "SMSG_STOP_MIRROR_TIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1DC*/ { "CMSG_PING", STATUS_NEVER, &WorldSession::Handle_EarlyProccess }, + /*0x1DD*/ { "SMSG_PONG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1DE*/ { "SMSG_CLEAR_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1DF*/ { "SMSG_GAMEOBJECT_PAGETEXT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1E0*/ { "CMSG_SETSHEATHED", STATUS_LOGGEDIN, &WorldSession::HandleSetSheathedOpcode }, + /*0x1E1*/ { "SMSG_COOLDOWN_CHEAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1E2*/ { "SMSG_SPELL_DELAYED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1E3*/ { "CMSG_PLAYER_MACRO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1E4*/ { "SMSG_PLAYER_MACRO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1E5*/ { "CMSG_GHOST", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1E6*/ { "CMSG_GM_INVIS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1E7*/ { "SMSG_INVALID_PROMOTION_CODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1E8*/ { "MSG_GM_BIND_OTHER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1E9*/ { "MSG_GM_SUMMON", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1EA*/ { "SMSG_ITEM_TIME_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1EB*/ { "SMSG_ITEM_ENCHANT_TIME_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1EC*/ { "SMSG_AUTH_CHALLENGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1ED*/ { "CMSG_AUTH_SESSION", STATUS_NEVER, &WorldSession::Handle_EarlyProccess }, + /*0x1EE*/ { "SMSG_AUTH_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1EF*/ { "MSG_GM_SHOWLABEL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1F0*/ { "CMSG_PET_CAST_SPELL", STATUS_LOGGEDIN, &WorldSession::HandleAddDynamicTargetObsoleteOpcode}, + /*0x1F1*/ { "MSG_SAVE_GUILD_EMBLEM", STATUS_LOGGEDIN, &WorldSession::HandleGuildSaveEmblemOpcode }, + /*0x1F2*/ { "MSG_TABARDVENDOR_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleTabardVendorActivateOpcode}, + /*0x1F3*/ { "SMSG_PLAY_SPELL_VISUAL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1F4*/ { "CMSG_ZONEUPDATE", STATUS_LOGGEDIN, &WorldSession::HandleZoneUpdateOpcode }, + /*0x1F5*/ { "SMSG_PARTYKILLLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1F6*/ { "SMSG_COMPRESSED_UPDATE_OBJECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1F7*/ { "SMSG_PLAY_SPELL_IMPACT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1F8*/ { "SMSG_EXPLORATION_EXPERIENCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1F9*/ { "CMSG_GM_SET_SECURITY_GROUP", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1FA*/ { "CMSG_GM_NUKE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1FB*/ { "MSG_RANDOM_ROLL", STATUS_LOGGEDIN, &WorldSession::HandleRandomRollOpcode }, + /*0x1FC*/ { "SMSG_ENVIRONMENTALDAMAGELOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1FD*/ { "CMSG_RWHOIS_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1FE*/ { "SMSG_RWHOIS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1FF*/ { "MSG_LOOKING_FOR_GROUP", STATUS_LOGGEDIN, &WorldSession::HandleLookingForGroup }, + /*0x200*/ { "CMSG_SET_LOOKING_FOR_GROUP", STATUS_LOGGEDIN, &WorldSession::HandleSetLfgOpcode }, + /*0x201*/ { "CMSG_UNLEARN_SPELL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x202*/ { "CMSG_UNLEARN_SKILL", STATUS_LOGGEDIN, &WorldSession::HandleUnlearnSkillOpcode }, + /*0x203*/ { "SMSG_REMOVED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x204*/ { "CMSG_DECHARGE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x205*/ { "CMSG_GMTICKET_CREATE", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketCreateOpcode }, + /*0x206*/ { "SMSG_GMTICKET_CREATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x207*/ { "CMSG_GMTICKET_UPDATETEXT", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketUpdateTextOpcode }, + /*0x208*/ { "SMSG_GMTICKET_UPDATETEXT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x209*/ { "SMSG_ACCOUNT_DATA_TIMES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x20A*/ { "CMSG_REQUEST_ACCOUNT_DATA", STATUS_LOGGEDIN, &WorldSession::HandleRequestAccountData }, + /*0x20B*/ { "CMSG_UPDATE_ACCOUNT_DATA", STATUS_LOGGEDIN, &WorldSession::HandleUpdateAccountData }, + /*0x20C*/ { "SMSG_UPDATE_ACCOUNT_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x20D*/ { "SMSG_CLEAR_FAR_SIGHT_IMMEDIATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x20E*/ { "SMSG_POWERGAINLOG_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x20F*/ { "CMSG_GM_TEACH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x210*/ { "CMSG_GM_CREATE_ITEM_TARGET", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x211*/ { "CMSG_GMTICKET_GETTICKET", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketGetTicketOpcode }, + /*0x212*/ { "SMSG_GMTICKET_GETTICKET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x213*/ { "CMSG_UNLEARN_TALENTS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x214*/ { "SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE",STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x215*/ { "SMSG_GAMEOBJECT_DESPAWN_ANIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x216*/ { "MSG_CORPSE_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleCorpseQueryOpcode }, + /*0x217*/ { "CMSG_GMTICKET_DELETETICKET", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketDeleteOpcode }, + /*0x218*/ { "SMSG_GMTICKET_DELETETICKET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x219*/ { "SMSG_CHAT_WRONG_FACTION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x21A*/ { "CMSG_GMTICKET_SYSTEMSTATUS", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketSystemStatusOpcode}, + /*0x21B*/ { "SMSG_GMTICKET_SYSTEMSTATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x21C*/ { "CMSG_SPIRIT_HEALER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleSpiritHealerActivateOpcode}, + /*0x21D*/ { "CMSG_SET_STAT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x21E*/ { "SMSG_SET_REST_START", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x21F*/ { "CMSG_SKILL_BUY_STEP", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x220*/ { "CMSG_SKILL_BUY_RANK", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x221*/ { "CMSG_XP_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x222*/ { "SMSG_SPIRIT_HEALER_CONFIRM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x223*/ { "CMSG_CHARACTER_POINT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x224*/ { "SMSG_GOSSIP_POI", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x225*/ { "CMSG_CHAT_IGNORED", STATUS_LOGGEDIN, &WorldSession::HandleChatIgnoredOpcode }, + /*0x226*/ { "CMSG_GM_VISION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x227*/ { "CMSG_SERVER_COMMAND", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x228*/ { "CMSG_GM_SILENCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x229*/ { "CMSG_GM_REVEALTO", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x22A*/ { "CMSG_GM_RESURRECT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x22B*/ { "CMSG_GM_SUMMONMOB", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x22C*/ { "CMSG_GM_MOVECORPSE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x22D*/ { "CMSG_GM_FREEZE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x22E*/ { "CMSG_GM_UBERINVIS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x22F*/ { "CMSG_GM_REQUEST_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x230*/ { "SMSG_GM_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x231*/ { "CMSG_GUILD_RANK", STATUS_LOGGEDIN, &WorldSession::HandleGuildRankOpcode }, + /*0x232*/ { "CMSG_GUILD_ADD_RANK", STATUS_LOGGEDIN, &WorldSession::HandleGuildAddRankOpcode }, + /*0x233*/ { "CMSG_GUILD_DEL_RANK", STATUS_LOGGEDIN, &WorldSession::HandleGuildDelRankOpcode }, + /*0x234*/ { "CMSG_GUILD_SET_PUBLIC_NOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildSetPublicNoteOpcode }, + /*0x235*/ { "CMSG_GUILD_SET_OFFICER_NOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildSetOfficerNoteOpcode }, + /*0x236*/ { "SMSG_LOGIN_VERIFY_WORLD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x237*/ { "CMSG_CLEAR_EXPLORATION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x238*/ { "CMSG_SEND_MAIL", STATUS_LOGGEDIN, &WorldSession::HandleSendMail }, + /*0x239*/ { "SMSG_SEND_MAIL_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x23A*/ { "CMSG_GET_MAIL_LIST", STATUS_LOGGEDIN, &WorldSession::HandleGetMail }, + /*0x23B*/ { "SMSG_MAIL_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x23C*/ { "CMSG_BATTLEFIELD_LIST", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundListOpcode }, + /*0x23D*/ { "SMSG_BATTLEFIELD_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x23E*/ { "CMSG_BATTLEFIELD_JOIN", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x23F*/ { "SMSG_BATTLEFIELD_WIN_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x240*/ { "SMSG_BATTLEFIELD_LOSE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x241*/ { "CMSG_TAXICLEARNODE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x242*/ { "CMSG_TAXIENABLENODE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x243*/ { "CMSG_ITEM_TEXT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleItemTextQuery }, + /*0x244*/ { "SMSG_ITEM_TEXT_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x245*/ { "CMSG_MAIL_TAKE_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleTakeMoney }, + /*0x246*/ { "CMSG_MAIL_TAKE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleTakeItem }, + /*0x247*/ { "CMSG_MAIL_MARK_AS_READ", STATUS_LOGGEDIN, &WorldSession::HandleMarkAsRead }, + /*0x248*/ { "CMSG_MAIL_RETURN_TO_SENDER", STATUS_LOGGEDIN, &WorldSession::HandleReturnToSender }, + /*0x249*/ { "CMSG_MAIL_DELETE", STATUS_LOGGEDIN, &WorldSession::HandleMailDelete }, + /*0x24A*/ { "CMSG_MAIL_CREATE_TEXT_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleMailCreateTextItem }, + /*0x24B*/ { "SMSG_SPELLLOGMISS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x24C*/ { "SMSG_SPELLLOGEXECUTE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x24D*/ { "SMSG_DEBUGAURAPROC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x24E*/ { "SMSG_PERIODICAURALOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x24F*/ { "SMSG_SPELLDAMAGESHIELD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x250*/ { "SMSG_SPELLNONMELEEDAMAGELOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x251*/ { "CMSG_LEARN_TALENT", STATUS_LOGGEDIN, &WorldSession::HandleLearnTalentOpcode }, + /*0x252*/ { "SMSG_RESURRECT_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x253*/ { "CMSG_TOGGLE_PVP", STATUS_LOGGEDIN, &WorldSession::HandleTogglePvP }, + /*0x254*/ { "SMSG_ZONE_UNDER_ATTACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x255*/ { "MSG_AUCTION_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleAuctionHelloOpcode }, + /*0x256*/ { "CMSG_AUCTION_SELL_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAuctionSellItem }, + /*0x257*/ { "CMSG_AUCTION_REMOVE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAuctionRemoveItem }, + /*0x258*/ { "CMSG_AUCTION_LIST_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleAuctionListItems }, + /*0x259*/ { "CMSG_AUCTION_LIST_OWNER_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleAuctionListOwnerItems }, + /*0x25A*/ { "CMSG_AUCTION_PLACE_BID", STATUS_LOGGEDIN, &WorldSession::HandleAuctionPlaceBid }, + /*0x25B*/ { "SMSG_AUCTION_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x25C*/ { "SMSG_AUCTION_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x25D*/ { "SMSG_AUCTION_OWNER_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x25E*/ { "SMSG_AUCTION_BIDDER_NOTIFICATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x25F*/ { "SMSG_AUCTION_OWNER_NOTIFICATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x260*/ { "SMSG_PROCRESIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x261*/ { "SMSG_STANDSTATE_CHANGE_FAILURE_OBSOLETE",STATUS_NEVER,&WorldSession::Handle_ServerSide }, + /*0x262*/ { "SMSG_DISPEL_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x263*/ { "SMSG_SPELLORDAMAGE_IMMUNE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x264*/ { "CMSG_AUCTION_LIST_BIDDER_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleAuctionListBidderItems }, + /*0x265*/ { "SMSG_AUCTION_BIDDER_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x266*/ { "SMSG_SET_FLAT_SPELL_MODIFIER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x267*/ { "SMSG_SET_PCT_SPELL_MODIFIER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x268*/ { "CMSG_SET_AMMO", STATUS_LOGGEDIN, &WorldSession::HandleSetAmmoOpcode }, + /*0x269*/ { "SMSG_CORPSE_RECLAIM_DELAY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x26A*/ { "CMSG_SET_ACTIVE_MOVER", STATUS_LOGGEDIN, &WorldSession::HandleSetActiveMoverOpcode }, + /*0x26B*/ { "CMSG_PET_CANCEL_AURA", STATUS_LOGGEDIN, &WorldSession::HandlePetCancelAuraOpcode }, + /*0x26C*/ { "CMSG_PLAYER_AI_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x26D*/ { "CMSG_CANCEL_AUTO_REPEAT_SPELL", STATUS_LOGGEDIN, &WorldSession::HandleCancelAutoRepeatSpellOpcode}, + /*0x26E*/ { "MSG_GM_ACCOUNT_ONLINE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x26F*/ { "MSG_LIST_STABLED_PETS", STATUS_LOGGEDIN, &WorldSession::HandleListStabledPetsOpcode }, + /*0x270*/ { "CMSG_STABLE_PET", STATUS_LOGGEDIN, &WorldSession::HandleStablePet }, + /*0x271*/ { "CMSG_UNSTABLE_PET", STATUS_LOGGEDIN, &WorldSession::HandleUnstablePet }, + /*0x272*/ { "CMSG_BUY_STABLE_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleBuyStableSlot }, + /*0x273*/ { "SMSG_STABLE_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x274*/ { "CMSG_STABLE_REVIVE_PET", STATUS_LOGGEDIN, &WorldSession::HandleStableRevivePet }, + /*0x275*/ { "CMSG_STABLE_SWAP_PET", STATUS_LOGGEDIN, &WorldSession::HandleStableSwapPet }, + /*0x276*/ { "MSG_QUEST_PUSH_RESULT", STATUS_LOGGEDIN, &WorldSession::HandleQuestPushResult }, + /*0x277*/ { "SMSG_PLAY_MUSIC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x278*/ { "SMSG_PLAY_OBJECT_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x279*/ { "CMSG_REQUEST_PET_INFO", STATUS_LOGGEDIN, &WorldSession::HandleRequestPetInfoOpcode }, + /*0x27A*/ { "CMSG_FAR_SIGHT", STATUS_LOGGEDIN, &WorldSession::HandleFarSightOpcode }, + /*0x27B*/ { "SMSG_SPELLDISPELLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x27C*/ { "SMSG_DAMAGE_CALC_LOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x27D*/ { "CMSG_ENABLE_DAMAGE_LOG", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x27E*/ { "CMSG_GROUP_CHANGE_SUB_GROUP", STATUS_LOGGEDIN, &WorldSession::HandleGroupChangeSubGroupOpcode }, + /*0x27F*/ { "CMSG_REQUEST_PARTY_MEMBER_STATS", STATUS_LOGGEDIN, &WorldSession::HandleRequestPartyMemberStatsOpcode}, + /*0x280*/ { "CMSG_GROUP_SWAP_SUB_GROUP", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x281*/ { "CMSG_RESET_FACTION_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x282*/ { "CMSG_AUTOSTORE_BANK_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoStoreBankItemOpcode }, + /*0x283*/ { "CMSG_AUTOBANK_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoBankItemOpcode }, + /*0x284*/ { "MSG_QUERY_NEXT_MAIL_TIME", STATUS_LOGGEDIN, &WorldSession::HandleMsgQueryNextMailtime }, + /*0x285*/ { "SMSG_RECEIVED_MAIL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x286*/ { "SMSG_RAID_GROUP_ONLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x287*/ { "CMSG_SET_DURABILITY_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x288*/ { "CMSG_SET_PVP_RANK_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x289*/ { "CMSG_ADD_PVP_MEDAL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x28A*/ { "CMSG_DEL_PVP_MEDAL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x28B*/ { "CMSG_SET_PVP_TITLE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x28C*/ { "SMSG_PVP_CREDIT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x28D*/ { "SMSG_AUCTION_REMOVED_NOTIFICATION",STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x28E*/ { "CMSG_GROUP_RAID_CONVERT", STATUS_LOGGEDIN, &WorldSession::HandleRaidConvertOpcode }, + /*0x28F*/ { "CMSG_GROUP_ASSISTANT_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleGroupAssistantOpcode }, + /*0x290*/ { "CMSG_BUYBACK_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleBuybackItem }, + /*0x291*/ { "SMSG_SERVER_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x292*/ { "CMSG_MEETINGSTONE_JOIN", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x293*/ { "CMSG_MEETINGSTONE_LEAVE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x294*/ { "CMSG_MEETINGSTONE_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x295*/ { "SMSG_MEETINGSTONE_SETQUEUE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x296*/ { "CMSG_MEETINGSTONE_INFO", STATUS_LOGGEDIN, &WorldSession::HandleMeetingStoneInfo }, + /*0x297*/ { "SMSG_MEETINGSTONE_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x298*/ { "SMSG_MEETINGSTONE_IN_PROGRESS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x299*/ { "SMSG_MEETINGSTONE_MEMBER_ADDED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x29A*/ { "CMSG_GMTICKETSYSTEM_TOGGLE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x29B*/ { "CMSG_CANCEL_GROWTH_AURA", STATUS_LOGGEDIN, &WorldSession::HandleCancelGrowthAuraOpcode }, + /*0x29C*/ { "SMSG_CANCEL_AUTO_REPEAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x29D*/ { "SMSG_STANDSTATE_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x29E*/ { "SMSG_LOOT_ALL_PASSED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x29F*/ { "SMSG_LOOT_ROLL_WON", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2A0*/ { "CMSG_LOOT_ROLL", STATUS_LOGGEDIN, &WorldSession::HandleLootRoll }, + /*0x2A1*/ { "SMSG_LOOT_START_ROLL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2A2*/ { "SMSG_LOOT_ROLL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2A3*/ { "CMSG_LOOT_MASTER_GIVE", STATUS_LOGGEDIN, &WorldSession::HandleLootMasterGiveOpcode }, + /*0x2A4*/ { "SMSG_LOOT_MASTER_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2A5*/ { "SMSG_SET_FORCED_REACTIONS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2A6*/ { "SMSG_SPELL_FAILED_OTHER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2A7*/ { "SMSG_GAMEOBJECT_RESET_STATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2A8*/ { "CMSG_REPAIR_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleRepairItemOpcode }, + /*0x2A9*/ { "SMSG_CHAT_PLAYER_NOT_FOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2AA*/ { "MSG_TALENT_WIPE_CONFIRM", STATUS_LOGGEDIN, &WorldSession::HandleTalentWipeOpcode }, + /*0x2AB*/ { "SMSG_SUMMON_REQUEST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2AC*/ { "CMSG_SUMMON_RESPONSE", STATUS_LOGGEDIN, &WorldSession::HandleSummonResponseOpcode }, + /*0x2AD*/ { "MSG_MOVE_TOGGLE_GRAVITY_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2AE*/ { "SMSG_MONSTER_MOVE_TRANSPORT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2AF*/ { "SMSG_PET_BROKEN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2B0*/ { "MSG_MOVE_FEATHER_FALL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2B1*/ { "MSG_MOVE_WATER_WALK", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2B2*/ { "CMSG_SERVER_BROADCAST", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2B3*/ { "CMSG_SELF_RES", STATUS_LOGGEDIN, &WorldSession::HandleSelfResOpcode }, + /*0x2B4*/ { "SMSG_FEIGN_DEATH_RESISTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2B5*/ { "CMSG_RUN_SCRIPT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2B6*/ { "SMSG_SCRIPT_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2B7*/ { "SMSG_DUEL_COUNTDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2B8*/ { "SMSG_AREA_TRIGGER_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2B9*/ { "CMSG_TOGGLE_HELM", STATUS_LOGGEDIN, &WorldSession::HandleToggleHelmOpcode }, + /*0x2BA*/ { "CMSG_TOGGLE_CLOAK", STATUS_LOGGEDIN, &WorldSession::HandleToggleCloakOpcode }, + /*0x2BB*/ { "SMSG_MEETINGSTONE_JOINFAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2BC*/ { "SMSG_PLAYER_SKINNED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2BD*/ { "SMSG_DURABILITY_DAMAGE_DEATH", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2BE*/ { "CMSG_SET_EXPLORATION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2BF*/ { "CMSG_SET_ACTIONBAR_TOGGLES", STATUS_AUTHED, &WorldSession::HandleSetActionBar }, + /*0x2C0*/ { "UMSG_DELETE_GUILD_CHARTER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2C1*/ { "MSG_PETITION_RENAME", STATUS_LOGGEDIN, &WorldSession::HandlePetitionRenameOpcode }, + /*0x2C2*/ { "SMSG_INIT_WORLD_STATES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2C3*/ { "SMSG_UPDATE_WORLD_STATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2C4*/ { "CMSG_ITEM_NAME_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleItemNameQueryOpcode }, + /*0x2C5*/ { "SMSG_ITEM_NAME_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2C6*/ { "SMSG_PET_ACTION_FEEDBACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2C7*/ { "CMSG_CHAR_RENAME", STATUS_AUTHED, &WorldSession::HandleChangePlayerNameOpcode }, + /*0x2C8*/ { "SMSG_CHAR_RENAME", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2C9*/ { "CMSG_MOVE_SPLINE_DONE", STATUS_LOGGEDIN, &WorldSession::HandleTaxiNextDestinationOpcode }, + /*0x2CA*/ { "CMSG_MOVE_FALL_RESET", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x2CB*/ { "SMSG_INSTANCE_SAVE_CREATED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2CC*/ { "SMSG_RAID_INSTANCE_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2CD*/ { "CMSG_REQUEST_RAID_INFO", STATUS_LOGGEDIN, &WorldSession::HandleRequestRaidInfoOpcode }, + /*0x2CE*/ { "CMSG_MOVE_TIME_SKIPPED", STATUS_LOGGEDIN, &WorldSession::HandleMoveTimeSkippedOpcode }, + /*0x2CF*/ { "CMSG_MOVE_FEATHER_FALL_ACK", STATUS_LOGGEDIN, &WorldSession::HandleFeatherFallAck }, + /*0x2D0*/ { "CMSG_MOVE_WATER_WALK_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveWaterWalkAck }, + /*0x2D1*/ { "CMSG_MOVE_NOT_ACTIVE_MOVER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2D2*/ { "SMSG_PLAY_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2D3*/ { "CMSG_BATTLEFIELD_STATUS", STATUS_LOGGEDIN, &WorldSession::HandleBattlefieldStatusOpcode }, + /*0x2D4*/ { "SMSG_BATTLEFIELD_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2D5*/ { "CMSG_BATTLEFIELD_PORT", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundPlayerPortOpcode}, + /*0x2D6*/ { "MSG_INSPECT_HONOR_STATS", STATUS_LOGGEDIN, &WorldSession::HandleInspectHonorStatsOpcode }, + /*0x2D7*/ { "CMSG_BATTLEMASTER_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundHelloOpcode }, + /*0x2D8*/ { "CMSG_MOVE_START_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2D9*/ { "CMSG_MOVE_STOP_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2DA*/ { "SMSG_FORCE_WALK_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2DB*/ { "CMSG_FORCE_WALK_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + /*0x2DC*/ { "SMSG_FORCE_SWIM_BACK_SPEED_CHANGE",STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2DD*/ { "CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK",STATUS_LOGGEDIN,&WorldSession::HandleForceSpeedChangeAck }, + /*0x2DE*/ { "SMSG_FORCE_TURN_RATE_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2DF*/ { "CMSG_FORCE_TURN_RATE_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + /*0x2E0*/ { "MSG_PVP_LOG_DATA", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundPVPlogdataOpcode}, + /*0x2E1*/ { "CMSG_LEAVE_BATTLEFIELD", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundLeaveOpcode }, + /*0x2E2*/ { "CMSG_AREA_SPIRIT_HEALER_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleAreaSpiritHealerQueryOpcode}, + /*0x2E3*/ { "CMSG_AREA_SPIRIT_HEALER_QUEUE", STATUS_LOGGEDIN, &WorldSession::HandleAreaSpiritHealerQueueOpcode}, + /*0x2E4*/ { "SMSG_AREA_SPIRIT_HEALER_TIME", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2E5*/ { "CMSG_GM_UNTEACH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2E6*/ { "SMSG_WARDEN_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2E7*/ { "CMSG_WARDEN_DATA", STATUS_LOGGEDIN, &WorldSession::HandleWardenDataOpcode }, + /*0x2E8*/ { "SMSG_GROUP_JOINED_BATTLEGROUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2E9*/ { "MSG_BATTLEGROUND_PLAYER_POSITIONS",STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundPlayerPositionsOpcode}, + /*0x2EA*/ { "CMSG_PET_STOP_ATTACK", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2EB*/ { "SMSG_BINDER_CONFIRM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2EC*/ { "SMSG_BATTLEGROUND_PLAYER_JOINED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2ED*/ { "SMSG_BATTLEGROUND_PLAYER_LEFT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2EE*/ { "CMSG_BATTLEMASTER_JOIN", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundJoinOpcode }, + /*0x2EF*/ { "SMSG_ADDON_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2F0*/ { "CMSG_PET_UNLEARN", STATUS_LOGGEDIN, &WorldSession::HandlePetUnlearnOpcode }, + /*0x2F1*/ { "SMSG_PET_UNLEARN_CONFIRM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2F2*/ { "SMSG_PARTY_MEMBER_STATS_FULL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2F3*/ { "CMSG_PET_SPELL_AUTOCAST", STATUS_LOGGEDIN, &WorldSession::HandlePetSpellAutocastOpcode }, + /*0x2F4*/ { "SMSG_WEATHER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2F5*/ { "SMSG_PLAY_TIME_WARNING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2F6*/ { "SMSG_MINIGAME_SETUP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2F7*/ { "SMSG_MINIGAME_STATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2F8*/ { "CMSG_MINIGAME_MOVE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2F9*/ { "SMSG_MINIGAME_MOVE_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2FA*/ { "SMSG_RAID_INSTANCE_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2FB*/ { "SMSG_COMPRESSED_MOVES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2FC*/ { "CMSG_GUILD_INFO_TEXT", STATUS_LOGGEDIN, &WorldSession::HandleGuildChangeInfoOpcode }, + /*0x2FD*/ { "SMSG_CHAT_RESTRICTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2FE*/ { "SMSG_SPLINE_SET_RUN_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2FF*/ { "SMSG_SPLINE_SET_RUN_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x300*/ { "SMSG_SPLINE_SET_SWIM_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x301*/ { "SMSG_SPLINE_SET_WALK_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x302*/ { "SMSG_SPLINE_SET_SWIM_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x303*/ { "SMSG_SPLINE_SET_TURN_RATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x304*/ { "SMSG_SPLINE_MOVE_UNROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x305*/ { "SMSG_SPLINE_MOVE_FEATHER_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x306*/ { "SMSG_SPLINE_MOVE_NORMAL_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x307*/ { "SMSG_SPLINE_MOVE_SET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x308*/ { "SMSG_SPLINE_MOVE_UNSET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x309*/ { "SMSG_SPLINE_MOVE_WATER_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x30A*/ { "SMSG_SPLINE_MOVE_LAND_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x30B*/ { "SMSG_SPLINE_MOVE_START_SWIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x30C*/ { "SMSG_SPLINE_MOVE_STOP_SWIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x30D*/ { "SMSG_SPLINE_MOVE_SET_RUN_MODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x30E*/ { "SMSG_SPLINE_MOVE_SET_WALK_MODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x30F*/ { "CMSG_GM_NUKE_ACCOUNT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x310*/ { "MSG_GM_DESTROY_CORPSE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x311*/ { "CMSG_GM_DESTROY_ONLINE_CORPSE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x312*/ { "CMSG_ACTIVATETAXIEXPRESS", STATUS_LOGGEDIN, &WorldSession::HandleActivateTaxiFarOpcode }, + /*0x313*/ { "SMSG_SET_FACTION_ATWAR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x314*/ { "SMSG_GAMETIMEBIAS_SET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x315*/ { "CMSG_DEBUG_ACTIONS_START", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x316*/ { "CMSG_DEBUG_ACTIONS_STOP", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x317*/ { "CMSG_SET_FACTION_INACTIVE", STATUS_LOGGEDIN, &WorldSession::HandleSetWatchedFactionInactiveOpcode}, + /*0x318*/ { "CMSG_SET_WATCHED_FACTION", STATUS_LOGGEDIN, &WorldSession::HandleSetWatchedFactionIndexOpcode}, + /*0x319*/ { "MSG_MOVE_TIME_SKIPPED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x31A*/ { "SMSG_SPLINE_MOVE_ROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x31B*/ { "CMSG_SET_EXPLORATION_ALL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x31C*/ { "SMSG_INVALIDATE_PLAYER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x31D*/ { "CMSG_RESET_INSTANCES", STATUS_LOGGEDIN, &WorldSession::HandleResetInstancesOpcode }, + /*0x31E*/ { "SMSG_INSTANCE_RESET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x31F*/ { "SMSG_INSTANCE_RESET_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x320*/ { "SMSG_UPDATE_LAST_INSTANCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x321*/ { "MSG_RAID_TARGET_UPDATE", STATUS_LOGGEDIN, &WorldSession::HandleRaidIconTargetOpcode }, + /*0x322*/ { "MSG_RAID_READY_CHECK", STATUS_LOGGEDIN, &WorldSession::HandleRaidReadyCheckOpcode }, + /*0x323*/ { "CMSG_LUA_USAGE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x324*/ { "SMSG_PET_ACTION_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x325*/ { "SMSG_PET_DISMISS_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x326*/ { "SMSG_GHOSTEE_GONE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x327*/ { "CMSG_GM_UPDATE_TICKET_STATUS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x328*/ { "SMSG_GM_TICKET_STATUS_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x329*/ { "MSG_SET_DUNGEON_DIFFICULTY", STATUS_LOGGEDIN, &WorldSession::HandleDungeonDifficultyOpcode }, + /*0x32A*/ { "CMSG_GMSURVEY_SUBMIT", STATUS_LOGGEDIN, &WorldSession::HandleGMSurveySubmit }, + /*0x32B*/ { "SMSG_UPDATE_INSTANCE_OWNERSHIP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x32C*/ { "CMSG_IGNORE_KNOCKBACK_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x32D*/ { "SMSG_CHAT_PLAYER_AMBIGUOUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x32E*/ { "MSG_DELAY_GHOST_TELEPORT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x32F*/ { "SMSG_SPELLINSTAKILLLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x330*/ { "SMSG_SPELL_UPDATE_CHAIN_TARGETS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x331*/ { "CMSG_CHAT_FILTERED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x332*/ { "SMSG_EXPECTED_SPAM_RECORDS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x333*/ { "SMSG_SPELLSTEALLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x334*/ { "CMSG_LOTTERY_QUERY_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x335*/ { "SMSG_LOTTERY_QUERY_RESULT_OBSOLETE",STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x336*/ { "CMSG_BUY_LOTTERY_TICKET_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x337*/ { "SMSG_LOTTERY_RESULT_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x338*/ { "SMSG_CHARACTER_PROFILE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x339*/ { "SMSG_CHARACTER_PROFILE_REALM_CONNECTED",STATUS_NEVER,&WorldSession::Handle_ServerSide }, + /*0x33A*/ { "SMSG_DEFENSE_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x33B*/ { "SMSG_INSTANCE_DIFFICULTY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x33C*/ { "MSG_GM_RESETINSTANCELIMIT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x33D*/ { "SMSG_MOTD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x33E*/ { "SMSG_MOVE_SET_FLIGHT_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x33F*/ { "SMSG_MOVE_UNSET_FLIGHT_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x340*/ { "CMSG_MOVE_FLIGHT_ACK_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x341*/ { "MSG_MOVE_START_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x342*/ { "MSG_MOVE_STOP_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x343*/ { "SMSG_MOVE_SET_CAN_FLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x344*/ { "SMSG_MOVE_UNSET_CAN_FLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x345*/ { "CMSG_MOVE_SET_CAN_FLY_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveFlyModeChangeAckOpcode}, + /*0x346*/ { "CMSG_MOVE_SET_FLY", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x347*/ { "CMSG_SOCKET_GEMS", STATUS_LOGGEDIN, &WorldSession::HandleSocketOpcode }, + /*0x348*/ { "CMSG_ARENA_TEAM_CREATE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x349*/ { "SMSG_ARENA_TEAM_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x34A*/ { "UMSG_UPDATE_ARENA_TEAM_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x34B*/ { "CMSG_ARENA_TEAM_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamQueryOpcode }, + /*0x34C*/ { "SMSG_ARENA_TEAM_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x34D*/ { "CMSG_ARENA_TEAM_ROSTER", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamRosterOpcode }, + /*0x34E*/ { "SMSG_ARENA_TEAM_ROSTER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x34F*/ { "CMSG_ARENA_TEAM_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamAddMemberOpcode }, + /*0x350*/ { "SMSG_ARENA_TEAM_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x351*/ { "CMSG_ARENA_TEAM_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamInviteAcceptOpcode}, + /*0x352*/ { "CMSG_ARENA_TEAM_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamInviteDeclineOpcode}, + /*0x353*/ { "CMSG_ARENA_TEAM_LEAVE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamLeaveOpcode }, + /*0x354*/ { "CMSG_ARENA_TEAM_REMOVE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamRemoveFromTeamOpcode}, + /*0x355*/ { "CMSG_ARENA_TEAM_DISBAND", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamDisbandOpcode }, + /*0x356*/ { "CMSG_ARENA_TEAM_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamPromoteToCaptainOpcode}, + /*0x357*/ { "SMSG_ARENA_TEAM_EVENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x358*/ { "CMSG_BATTLEMASTER_JOIN_ARENA", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundArenaJoin }, + /*0x359*/ { "MSG_MOVE_START_ASCEND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x35A*/ { "MSG_MOVE_STOP_ASCEND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x35B*/ { "SMSG_ARENA_TEAM_STATS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x35C*/ { "CMSG_LFG_SET_AUTOJOIN", STATUS_AUTHED, &WorldSession::HandleLfgAutoJoinOpcode }, + /*0x35D*/ { "CMSG_LFG_CLEAR_AUTOJOIN", STATUS_LOGGEDIN, &WorldSession::HandleLfgCancelAutoJoinOpcode }, + /*0x35E*/ { "CMSG_LFM_SET_AUTOFILL", STATUS_AUTHED, &WorldSession::HandleLfmAutoAddMembersOpcode }, + /*0x35F*/ { "CMSG_LFM_CLEAR_AUTOFILL", STATUS_LOGGEDIN, &WorldSession::HandleLfmCancelAutoAddmembersOpcode}, + /*0x360*/ { "CMSG_ACCEPT_LFG_MATCH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x361*/ { "CMSG_DECLINE_LFG_MATCH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x362*/ { "CMSG_CANCEL_PENDING_LFG", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x363*/ { "CMSG_CLEAR_LOOKING_FOR_GROUP", STATUS_LOGGEDIN, &WorldSession::HandleLfgClearOpcode }, + /*0x364*/ { "CMSG_CLEAR_LOOKING_FOR_MORE", STATUS_LOGGEDIN, &WorldSession::HandleLfmSetNoneOpcode }, + /*0x365*/ { "CMSG_SET_LOOKING_FOR_MORE", STATUS_LOGGEDIN, &WorldSession::HandleLfmSetOpcode }, + /*0x366*/ { "CMSG_SET_LFG_COMMENT", STATUS_LOGGEDIN, &WorldSession::HandleLfgSetCommentOpcode }, + /*0x367*/ { "SMSG_LFG_TIMEDOUT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x368*/ { "SMSG_LFG_OTHER_TIMEDOUT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x369*/ { "SMSG_LFG_AUTOJOIN_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x36A*/ { "SMSG_LFG_AUTOJOIN_FAILED_NO_PLAYER",STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x36B*/ { "SMSG_LFG_LEADER_IS_LFM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x36C*/ { "SMSG_LFG_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x36D*/ { "SMSG_LFG_UPDATE_LFM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x36E*/ { "SMSG_LFG_UPDATE_LFG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x36F*/ { "SMSG_LFG_UPDATE_QUEUED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x370*/ { "SMSG_LFG_PENDING_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x371*/ { "SMSG_LFG_PENDING_MATCH", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x372*/ { "SMSG_LFG_PENDING_MATCH_DONE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x373*/ { "SMSG_TITLE_EARNED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x374*/ { "CMSG_SET_TITLE", STATUS_LOGGEDIN, &WorldSession::HandleChooseTitleOpcode }, + /*0x375*/ { "CMSG_CANCEL_MOUNT_AURA", STATUS_LOGGEDIN, &WorldSession::HandleDismountOpcode }, + /*0x376*/ { "SMSG_ARENA_ERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x377*/ { "MSG_INSPECT_ARENA_TEAMS", STATUS_LOGGEDIN, &WorldSession::HandleInspectArenaStatsOpcode }, + /*0x378*/ { "SMSG_DEATH_RELEASE_LOC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x379*/ { "CMSG_CANCEL_TEMP_ENCHANTMENT", STATUS_LOGGEDIN, &WorldSession::HandleCancelTempItemEnchantmentOpcode}, + /*0x37A*/ { "SMSG_FORCED_DEATH_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x37B*/ { "CMSG_CHEAT_SET_HONOR_CURRENCY", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x37C*/ { "CMSG_CHEAT_SET_ARENA_CURRENCY", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x37D*/ { "MSG_MOVE_SET_FLIGHT_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x37E*/ { "MSG_MOVE_SET_FLIGHT_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x37F*/ { "MSG_MOVE_SET_FLIGHT_BACK_SPEED_CHEAT",STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x380*/ { "MSG_MOVE_SET_FLIGHT_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x381*/ { "SMSG_FORCE_FLIGHT_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x382*/ { "CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK",STATUS_LOGGEDIN,&WorldSession::HandleForceSpeedChangeAck }, + /*0x383*/ { "SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE",STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x384*/ { "CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK",STATUS_LOGGEDIN,&WorldSession::HandleForceSpeedChangeAck }, + /*0x385*/ { "SMSG_SPLINE_SET_FLIGHT_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x386*/ { "SMSG_SPLINE_SET_FLIGHT_BACK_SPEED",STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x387*/ { "CMSG_MAELSTROM_INVALIDATE_CACHE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x388*/ { "SMSG_FLIGHT_SPLINE_SYNC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x389*/ { "CMSG_SET_TAXI_BENCHMARK_MODE", STATUS_AUTHED, &WorldSession::HandleSetTaxiBenchmarkOpcode }, + /*0x38A*/ { "SMSG_JOINED_BATTLEGROUND_QUEUE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x38B*/ { "SMSG_REALM_SPLIT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x38C*/ { "CMSG_REALM_SPLIT", STATUS_AUTHED, &WorldSession::HandleRealmStateRequestOpcode }, + /*0x38D*/ { "CMSG_MOVE_CHNG_TRANSPORT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x38E*/ { "MSG_PARTY_ASSIGNMENT", STATUS_LOGGEDIN, &WorldSession::HandleGroupPromoteOpcode }, + /*0x38F*/ { "SMSG_OFFER_PETITION_ERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x390*/ { "SMSG_TIME_SYNC_REQ", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x391*/ { "CMSG_TIME_SYNC_RESP", STATUS_LOGGEDIN, &WorldSession::HandleAllowMoveAckOpcode }, + /*0x392*/ { "CMSG_SEND_LOCAL_EVENT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x393*/ { "CMSG_SEND_GENERAL_TRIGGER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x394*/ { "CMSG_SEND_COMBAT_TRIGGER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x395*/ { "CMSG_MAELSTROM_GM_SENT_MAIL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x396*/ { "SMSG_RESET_FAILED_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x397*/ { "SMSG_REAL_GROUP_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x398*/ { "SMSG_LFG_DISABLED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x399*/ { "CMSG_ACTIVE_PVP_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x39A*/ { "CMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x39B*/ { "SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE",STATUS_NEVER,&WorldSession::Handle_ServerSide }, + /*0x39C*/ { "SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE_WRITE_FILE",STATUS_NEVER,&WorldSession::Handle_ServerSide}, + /*0x39D*/ { "SMSG_UPDATE_COMBO_POINTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x39E*/ { "SMSG_VOICE_SESSION_ROSTER_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x39F*/ { "SMSG_VOICE_SESSION_LEAVE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3A0*/ { "SMSG_VOICE_SESSION_ADJUST_PRIORITY",STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3A1*/ { "CMSG_VOICE_SET_TALKER_MUTED_REQUEST",STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3A2*/ { "SMSG_VOICE_SET_TALKER_MUTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3A3*/ { "SMSG_INIT_EXTRA_AURA_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3A4*/ { "SMSG_SET_EXTRA_AURA_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3A5*/ { "SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE",STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3A6*/ { "SMSG_CLEAR_EXTRA_AURA_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3A7*/ { "MSG_MOVE_START_DESCEND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x3A8*/ { "CMSG_IGNORE_REQUIREMENTS_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3A9*/ { "SMSG_IGNORE_REQUIREMENTS_CHEAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3AA*/ { "SMSG_SPELL_CHANCE_PROC_LOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3AB*/ { "CMSG_MOVE_SET_RUN_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3AC*/ { "SMSG_DISMOUNT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3AD*/ { "MSG_MOVE_UPDATE_CAN_FLY", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3AE*/ { "MSG_RAID_READY_CHECK_CONFIRM", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3AF*/ { "CMSG_VOICE_SESSION_ENABLE", STATUS_AUTHED, &WorldSession::HandleVoiceSettingsOpcode }, + /*0x3B0*/ { "SMSG_VOICE_PARENTAL_CONTROLS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3B1*/ { "CMSG_GM_WHISPER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3B2*/ { "SMSG_GM_MESSAGECHAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3B3*/ { "MSG_GM_GEARRATING", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3B4*/ { "CMSG_COMMENTATOR_ENABLE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3B5*/ { "SMSG_COMMENTATOR_STATE_CHANGED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3B6*/ { "CMSG_COMMENTATOR_GET_MAP_INFO", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3B7*/ { "SMSG_COMMENTATOR_MAP_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3B8*/ { "CMSG_COMMENTATOR_GET_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3B9*/ { "SMSG_COMMENTATOR_GET_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3BA*/ { "SMSG_COMMENTATOR_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3BB*/ { "CMSG_COMMENTATOR_ENTER_INSTANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3BC*/ { "CMSG_COMMENTATOR_EXIT_INSTANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3BD*/ { "CMSG_COMMENTATOR_INSTANCE_COMMAND",STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3BE*/ { "SMSG_CLEAR_TARGET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3BF*/ { "CMSG_BOT_DETECTED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3C0*/ { "SMSG_CROSSED_INEBRIATION_THRESHOLD",STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3C1*/ { "CMSG_CHEAT_PLAYER_LOGIN", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3C2*/ { "CMSG_CHEAT_PLAYER_LOOKUP", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3C3*/ { "SMSG_CHEAT_PLAYER_LOOKUP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3C4*/ { "SMSG_KICK_REASON", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3C5*/ { "MSG_RAID_READY_CHECK_FINISHED", STATUS_LOGGEDIN, &WorldSession::HandleRaidReadyCheckFinishOpcode}, + /*0x3C6*/ { "CMSG_COMPLAIN", STATUS_LOGGEDIN, &WorldSession::HandleReportSpamOpcode }, + /*0x3C7*/ { "SMSG_COMPLAIN_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3C8*/ { "SMSG_FEATURE_SYSTEM_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3C9*/ { "CMSG_GM_SHOW_COMPLAINTS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3CA*/ { "CMSG_GM_UNSQUELCH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3CB*/ { "CMSG_CHANNEL_SILENCE_VOICE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3CC*/ { "CMSG_CHANNEL_SILENCE_ALL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3CD*/ { "CMSG_CHANNEL_UNSILENCE_VOICE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3CE*/ { "CMSG_CHANNEL_UNSILENCE_ALL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3CF*/ { "CMSG_TARGET_CAST", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3D0*/ { "CMSG_TARGET_SCRIPT_CAST", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3D1*/ { "CMSG_CHANNEL_DISPLAY_LIST", STATUS_LOGGEDIN, &WorldSession::HandleChannelRosterQuery }, + /*0x3D2*/ { "CMSG_SET_ACTIVE_VOICE_CHANNEL", STATUS_AUTHED, &WorldSession::HandleChannelVoiceChatQuery }, + /*0x3D3*/ { "CMSG_GET_CHANNEL_MEMBER_COUNT", STATUS_LOGGEDIN, &WorldSession::HandleChannelInfoQuery }, + /*0x3D4*/ { "SMSG_CHANNEL_MEMBER_COUNT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3D5*/ { "CMSG_CHANNEL_VOICE_ON", STATUS_LOGGEDIN, &WorldSession::HandleChannelEnableVoiceOpcode }, + /*0x3D6*/ { "CMSG_CHANNEL_VOICE_OFF", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3D7*/ { "CMSG_DEBUG_LIST_TARGETS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3D8*/ { "SMSG_DEBUG_LIST_TARGETS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3D9*/ { "SMSG_AVAILABLE_VOICE_CHANNEL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3DA*/ { "CMSG_ADD_VOICE_IGNORE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3DB*/ { "CMSG_DEL_VOICE_IGNORE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3DC*/ { "CMSG_PARTY_SILENCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3DD*/ { "CMSG_PARTY_UNSILENCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3DE*/ { "MSG_NOTIFY_PARTY_SQUELCH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3DF*/ { "SMSG_COMSAT_RECONNECT_TRY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3E0*/ { "SMSG_COMSAT_DISCONNECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3E1*/ { "SMSG_COMSAT_CONNECT_FAIL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3E2*/ { "SMSG_VOICE_CHAT_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3E3*/ { "CMSG_REPORT_PVP_AFK", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundReportAFK }, + /*0x3E4*/ { "CMSG_REPORT_PVP_AFK_RESULT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3E5*/ { "CMSG_GUILD_BANKER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankQuery }, + /*0x3E6*/ { "CMSG_GUILD_BANK_QUERY_TAB", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankTabColon }, + /*0x3E7*/ { "SMSG_GUILD_BANK_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3E8*/ { "CMSG_GUILD_BANK_SWAP_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankDepositItem }, + /*0x3E9*/ { "CMSG_GUILD_BANK_BUY_TAB", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankBuyTab }, + /*0x3EA*/ { "CMSG_GUILD_BANK_UPDATE_TAB", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankModifyTab }, + /*0x3EB*/ { "CMSG_GUILD_BANK_DEPOSIT_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankDeposit }, + /*0x3EC*/ { "CMSG_GUILD_BANK_WITHDRAW_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankWithdraw }, + /*0x3ED*/ { "MSG_GUILD_BANK_LOG_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankLog }, + /*0x3EE*/ { "CMSG_SET_CHANNEL_WATCH", STATUS_LOGGEDIN, &WorldSession::HandleChannelJoinNotify }, + /*0x3EF*/ { "SMSG_USERLIST_ADD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3F0*/ { "SMSG_USERLIST_REMOVE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3F1*/ { "SMSG_USERLIST_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3F2*/ { "CMSG_CLEAR_CHANNEL_WATCH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3F3*/ { "SMSG_INSPECT_TALENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3F4*/ { "SMSG_GOGOGO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3F5*/ { "SMSG_ECHO_PARTY_SQUELCH", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3F6*/ { "CMSG_SET_TITLE_SUFFIX", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3F7*/ { "CMSG_SPELLCLICK", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3F8*/ { "SMSG_LOOT_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3F9*/ { "CMSG_GM_CHARACTER_RESTORE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3FA*/ { "CMSG_GM_CHARACTER_SAVE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3FB*/ { "SMSG_VOICESESSION_FULL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3FC*/ { "MSG_GUILD_PERMISSIONS", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankGetRights }, + /*0x3FD*/ { "MSG_GUILD_BANK_MONEY_WITHDRAWN", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankGetMoneyAmount }, + /*0x3FE*/ { "MSG_GUILD_EVENT_LOG_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleGuildEventLogOpcode }, + /*0x3FF*/ { "CMSG_MAELSTROM_RENAME_GUILD", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x400*/ { "CMSG_GET_MIRRORIMAGE_DATA", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x401*/ { "SMSG_MIRRORIMAGE_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x402*/ { "SMSG_FORCE_DISPLAY_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x403*/ { "SMSG_SPELL_CHANCE_RESIST_PUSHBACK",STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x404*/ { "CMSG_IGNORE_DIMINISHING_RETURNS_CHEAT",STATUS_NEVER,&WorldSession::Handle_NULL }, + /*0x405*/ { "SMSG_IGNORE_DIMINISHING_RETURNS_CHEAT",STATUS_NEVER,&WorldSession::Handle_ServerSide }, + /*0x406*/ { "CMSG_KEEP_ALIVE", STATUS_NEVER, &WorldSession::Handle_EarlyProccess }, + /*0x407*/ { "SMSG_RAID_READY_CHECK_ERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x408*/ { "CMSG_OPT_OUT_OF_LOOT", STATUS_AUTHED, &WorldSession::HandleGroupPassOnLootOpcode }, + /*0x409*/ { "MSG_QUERY_GUILD_BANK_TEXT", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankTabText }, + /*0x40A*/ { "CMSG_SET_GUILD_BANK_TEXT", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankSetTabText }, + /*0x40B*/ { "CMSG_SET_GRANTABLE_LEVELS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x40C*/ { "CMSG_GRANT_LEVEL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x40D*/ { "CMSG_REFER_A_FRIEND", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x40E*/ { "MSG_GM_CHANGE_ARENA_RATING", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x40F*/ { "CMSG_DECLINE_CHANNEL_INVITE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x410*/ { "CMSG_GROUPACTION_THROTTLED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x411*/ { "SMSG_OVERRIDE_LIGHT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x412*/ { "SMSG_TOTEM_CREATED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x413*/ { "CMSG_TOTEM_DESTROYED", STATUS_LOGGEDIN, &WorldSession::HandleTotemDestroy }, + /*0x414*/ { "CMSG_EXPIRE_RAID_INSTANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x415*/ { "CMSG_NO_SPELL_VARIANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x416*/ { "CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY",STATUS_LOGGEDIN,&WorldSession::HandleQuestgiverStatusQueryMultipleOpcode}, + /*0x417*/ { "SMSG_QUESTGIVER_STATUS_MULTIPLE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x418*/ { "CMSG_SET_PLAYER_DECLINED_NAMES", STATUS_AUTHED, &WorldSession::HandleDeclinedPlayerNameOpcode }, + /*0x419*/ { "SMSG_SET_PLAYER_DECLINED_NAMES_RESULT",STATUS_NEVER,&WorldSession::Handle_ServerSide }, + /*0x41A*/ { "CMSG_QUERY_SERVER_BUCK_DATA", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x41B*/ { "CMSG_CLEAR_SERVER_BUCK_DATA", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x41C*/ { "SMSG_SERVER_BUCK_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x41D*/ { "SMSG_SEND_UNLEARN_SPELLS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x41E*/ { "SMSG_PROPOSE_LEVEL_GRANT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x41F*/ { "CMSG_ACCEPT_LEVEL_GRANT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x420*/ { "SMSG_REFER_A_FRIEND_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x421*/ { "SMSG_SPLINE_MOVE_SET_FLYING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x422*/ { "SMSG_SPLINE_MOVE_UNSET_FLYING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x423*/ { "SMSG_SUMMON_CANCEL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, +}; diff --git a/src/game/Opcodes.h b/src/game/Opcodes.h new file mode 100644 index 00000000000..423fad2351f --- /dev/null +++ b/src/game/Opcodes.h @@ -0,0 +1,1125 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/// \addtogroup u2w +/// @{ +/// \file + +#ifndef _OPCODES_H +#define _OPCODES_H + +#include "Common.h" + +/// List of Opcodes +enum Opcodes +{ + MSG_NULL_ACTION = 0x000, + CMSG_BOOTME = 0x001, + CMSG_DBLOOKUP = 0x002, + SMSG_DBLOOKUP = 0x003, + CMSG_QUERY_OBJECT_POSITION = 0x004, + SMSG_QUERY_OBJECT_POSITION = 0x005, + CMSG_QUERY_OBJECT_ROTATION = 0x006, + SMSG_QUERY_OBJECT_ROTATION = 0x007, + CMSG_WORLD_TELEPORT = 0x008, + CMSG_TELEPORT_TO_UNIT = 0x009, + CMSG_ZONE_MAP = 0x00A, + SMSG_ZONE_MAP = 0x00B, + CMSG_DEBUG_CHANGECELLZONE = 0x00C, + CMSG_EMBLAZON_TABARD_OBSOLETE = 0x00D, + CMSG_UNEMBLAZON_TABARD_OBSOLETE = 0x00E, + CMSG_RECHARGE = 0x00F, + CMSG_LEARN_SPELL = 0x010, + CMSG_CREATEMONSTER = 0x011, + CMSG_DESTROYMONSTER = 0x012, + CMSG_CREATEITEM = 0x013, + CMSG_CREATEGAMEOBJECT = 0x014, + SMSG_CHECK_FOR_BOTS = 0x015, + CMSG_MAKEMONSTERATTACKGUID = 0x016, + CMSG_BOT_DETECTED2 = 0x017, + CMSG_FORCEACTION = 0x018, + CMSG_FORCEACTIONONOTHER = 0x019, + CMSG_FORCEACTIONSHOW = 0x01A, + SMSG_FORCEACTIONSHOW = 0x01B, + CMSG_PETGODMODE = 0x01C, + SMSG_PETGODMODE = 0x01D, + SMSG_DEBUGINFOSPELLMISS_OBSOLETE = 0x01E, + CMSG_WEATHER_SPEED_CHEAT = 0x01F, + CMSG_UNDRESSPLAYER = 0x020, + CMSG_BEASTMASTER = 0x021, + CMSG_GODMODE = 0x022, + SMSG_GODMODE = 0x023, + CMSG_CHEAT_SETMONEY = 0x024, + CMSG_LEVEL_CHEAT = 0x025, + CMSG_PET_LEVEL_CHEAT = 0x026, + CMSG_SET_WORLDSTATE = 0x027, + CMSG_COOLDOWN_CHEAT = 0x028, + CMSG_USE_SKILL_CHEAT = 0x029, + CMSG_FLAG_QUEST = 0x02A, + CMSG_FLAG_QUEST_FINISH = 0x02B, + CMSG_CLEAR_QUEST = 0x02C, + CMSG_SEND_EVENT = 0x02D, + CMSG_DEBUG_AISTATE = 0x02E, + SMSG_DEBUG_AISTATE = 0x02F, + CMSG_DISABLE_PVP_CHEAT = 0x030, + CMSG_ADVANCE_SPAWN_TIME = 0x031, + CMSG_PVP_PORT_OBSOLETE = 0x032, + CMSG_AUTH_SRP6_BEGIN = 0x033, + CMSG_AUTH_SRP6_PROOF = 0x034, + CMSG_AUTH_SRP6_RECODE = 0x035, + CMSG_CHAR_CREATE = 0x036, + CMSG_CHAR_ENUM = 0x037, + CMSG_CHAR_DELETE = 0x038, + SMSG_AUTH_SRP6_RESPONSE = 0x039, + SMSG_CHAR_CREATE = 0x03A, + SMSG_CHAR_ENUM = 0x03B, + SMSG_CHAR_DELETE = 0x03C, + CMSG_PLAYER_LOGIN = 0x03D, + SMSG_NEW_WORLD = 0x03E, + SMSG_TRANSFER_PENDING = 0x03F, + SMSG_TRANSFER_ABORTED = 0x040, + SMSG_CHARACTER_LOGIN_FAILED = 0x041, + SMSG_LOGIN_SETTIMESPEED = 0x042, + SMSG_GAMETIME_UPDATE = 0x043, + CMSG_GAMETIME_SET = 0x044, + SMSG_GAMETIME_SET = 0x045, + CMSG_GAMESPEED_SET = 0x046, + SMSG_GAMESPEED_SET = 0x047, + CMSG_SERVERTIME = 0x048, + SMSG_SERVERTIME = 0x049, + CMSG_PLAYER_LOGOUT = 0x04A, + CMSG_LOGOUT_REQUEST = 0x04B, + SMSG_LOGOUT_RESPONSE = 0x04C, + SMSG_LOGOUT_COMPLETE = 0x04D, + CMSG_LOGOUT_CANCEL = 0x04E, + SMSG_LOGOUT_CANCEL_ACK = 0x04F, + CMSG_NAME_QUERY = 0x050, + SMSG_NAME_QUERY_RESPONSE = 0x051, + CMSG_PET_NAME_QUERY = 0x052, + SMSG_PET_NAME_QUERY_RESPONSE = 0x053, + CMSG_GUILD_QUERY = 0x054, + SMSG_GUILD_QUERY_RESPONSE = 0x055, + CMSG_ITEM_QUERY_SINGLE = 0x056, + CMSG_ITEM_QUERY_MULTIPLE = 0x057, + SMSG_ITEM_QUERY_SINGLE_RESPONSE = 0x058, + SMSG_ITEM_QUERY_MULTIPLE_RESPONSE = 0x059, + CMSG_PAGE_TEXT_QUERY = 0x05A, + SMSG_PAGE_TEXT_QUERY_RESPONSE = 0x05B, + CMSG_QUEST_QUERY = 0x05C, + SMSG_QUEST_QUERY_RESPONSE = 0x05D, + CMSG_GAMEOBJECT_QUERY = 0x05E, + SMSG_GAMEOBJECT_QUERY_RESPONSE = 0x05F, + CMSG_CREATURE_QUERY = 0x060, + SMSG_CREATURE_QUERY_RESPONSE = 0x061, + CMSG_WHO = 0x062, + SMSG_WHO = 0x063, + CMSG_WHOIS = 0x064, + SMSG_WHOIS = 0x065, + CMSG_CONTACT_LIST = 0x066, + SMSG_CONTACT_LIST = 0x067, + SMSG_FRIEND_STATUS = 0x068, + CMSG_ADD_FRIEND = 0x069, + CMSG_DEL_FRIEND = 0x06A, + CMSG_SET_CONTACT_NOTES = 0x06B, + CMSG_ADD_IGNORE = 0x06C, + CMSG_DEL_IGNORE = 0x06D, + CMSG_GROUP_INVITE = 0x06E, + SMSG_GROUP_INVITE = 0x06F, + CMSG_GROUP_CANCEL = 0x070, + SMSG_GROUP_CANCEL = 0x071, + CMSG_GROUP_ACCEPT = 0x072, + CMSG_GROUP_DECLINE = 0x073, + SMSG_GROUP_DECLINE = 0x074, + CMSG_GROUP_UNINVITE = 0x075, + CMSG_GROUP_UNINVITE_GUID = 0x076, + SMSG_GROUP_UNINVITE = 0x077, + CMSG_GROUP_SET_LEADER = 0x078, + SMSG_GROUP_SET_LEADER = 0x079, + CMSG_LOOT_METHOD = 0x07A, + CMSG_GROUP_DISBAND = 0x07B, + SMSG_GROUP_DESTROYED = 0x07C, + SMSG_GROUP_LIST = 0x07D, + SMSG_PARTY_MEMBER_STATS = 0x07E, + SMSG_PARTY_COMMAND_RESULT = 0x07F, + UMSG_UPDATE_GROUP_MEMBERS = 0x080, + CMSG_GUILD_CREATE = 0x081, + CMSG_GUILD_INVITE = 0x082, + SMSG_GUILD_INVITE = 0x083, + CMSG_GUILD_ACCEPT = 0x084, + CMSG_GUILD_DECLINE = 0x085, + SMSG_GUILD_DECLINE = 0x086, + CMSG_GUILD_INFO = 0x087, + SMSG_GUILD_INFO = 0x088, + CMSG_GUILD_ROSTER = 0x089, + SMSG_GUILD_ROSTER = 0x08A, + CMSG_GUILD_PROMOTE = 0x08B, + CMSG_GUILD_DEMOTE = 0x08C, + CMSG_GUILD_LEAVE = 0x08D, + CMSG_GUILD_REMOVE = 0x08E, + CMSG_GUILD_DISBAND = 0x08F, + CMSG_GUILD_LEADER = 0x090, + CMSG_GUILD_MOTD = 0x091, + SMSG_GUILD_EVENT = 0x092, + SMSG_GUILD_COMMAND_RESULT = 0x093, + UMSG_UPDATE_GUILD = 0x094, + CMSG_MESSAGECHAT = 0x095, + SMSG_MESSAGECHAT = 0x096, + CMSG_JOIN_CHANNEL = 0x097, + CMSG_LEAVE_CHANNEL = 0x098, + SMSG_CHANNEL_NOTIFY = 0x099, + CMSG_CHANNEL_LIST = 0x09A, + SMSG_CHANNEL_LIST = 0x09B, + CMSG_CHANNEL_PASSWORD = 0x09C, + CMSG_CHANNEL_SET_OWNER = 0x09D, + CMSG_CHANNEL_OWNER = 0x09E, + CMSG_CHANNEL_MODERATOR = 0x09F, + CMSG_CHANNEL_UNMODERATOR = 0x0A0, + CMSG_CHANNEL_MUTE = 0x0A1, + CMSG_CHANNEL_UNMUTE = 0x0A2, + CMSG_CHANNEL_INVITE = 0x0A3, + CMSG_CHANNEL_KICK = 0x0A4, + CMSG_CHANNEL_BAN = 0x0A5, + CMSG_CHANNEL_UNBAN = 0x0A6, + CMSG_CHANNEL_ANNOUNCEMENTS = 0x0A7, + CMSG_CHANNEL_MODERATE = 0x0A8, + SMSG_UPDATE_OBJECT = 0x0A9, + SMSG_DESTROY_OBJECT = 0x0AA, + CMSG_USE_ITEM = 0x0AB, + CMSG_OPEN_ITEM = 0x0AC, + CMSG_READ_ITEM = 0x0AD, + SMSG_READ_ITEM_OK = 0x0AE, + SMSG_READ_ITEM_FAILED = 0x0AF, + SMSG_ITEM_COOLDOWN = 0x0B0, + CMSG_GAMEOBJ_USE = 0x0B1, + CMSG_GAMEOBJ_CHAIR_USE_OBSOLETE = 0x0B2, + SMSG_GAMEOBJECT_CUSTOM_ANIM = 0x0B3, + CMSG_AREATRIGGER = 0x0B4, + MSG_MOVE_START_FORWARD = 0x0B5, + MSG_MOVE_START_BACKWARD = 0x0B6, + MSG_MOVE_STOP = 0x0B7, + MSG_MOVE_START_STRAFE_LEFT = 0x0B8, + MSG_MOVE_START_STRAFE_RIGHT = 0x0B9, + MSG_MOVE_STOP_STRAFE = 0x0BA, + MSG_MOVE_JUMP = 0x0BB, + MSG_MOVE_START_TURN_LEFT = 0x0BC, + MSG_MOVE_START_TURN_RIGHT = 0x0BD, + MSG_MOVE_STOP_TURN = 0x0BE, + MSG_MOVE_START_PITCH_UP = 0x0BF, + MSG_MOVE_START_PITCH_DOWN = 0x0C0, + MSG_MOVE_STOP_PITCH = 0x0C1, + MSG_MOVE_SET_RUN_MODE = 0x0C2, + MSG_MOVE_SET_WALK_MODE = 0x0C3, + MSG_MOVE_TOGGLE_LOGGING = 0x0C4, + MSG_MOVE_TELEPORT = 0x0C5, + MSG_MOVE_TELEPORT_CHEAT = 0x0C6, + MSG_MOVE_TELEPORT_ACK = 0x0C7, + MSG_MOVE_TOGGLE_FALL_LOGGING = 0x0C8, + MSG_MOVE_FALL_LAND = 0x0C9, + MSG_MOVE_START_SWIM = 0x0CA, + MSG_MOVE_STOP_SWIM = 0x0CB, + MSG_MOVE_SET_RUN_SPEED_CHEAT = 0x0CC, + MSG_MOVE_SET_RUN_SPEED = 0x0CD, + MSG_MOVE_SET_RUN_BACK_SPEED_CHEAT = 0x0CE, + MSG_MOVE_SET_RUN_BACK_SPEED = 0x0CF, + MSG_MOVE_SET_WALK_SPEED_CHEAT = 0x0D0, + MSG_MOVE_SET_WALK_SPEED = 0x0D1, + MSG_MOVE_SET_SWIM_SPEED_CHEAT = 0x0D2, + MSG_MOVE_SET_SWIM_SPEED = 0x0D3, + MSG_MOVE_SET_SWIM_BACK_SPEED_CHEAT = 0x0D4, + MSG_MOVE_SET_SWIM_BACK_SPEED = 0x0D5, + MSG_MOVE_SET_ALL_SPEED_CHEAT = 0x0D6, + MSG_MOVE_SET_TURN_RATE_CHEAT = 0x0D7, + MSG_MOVE_SET_TURN_RATE = 0x0D8, + MSG_MOVE_TOGGLE_COLLISION_CHEAT = 0x0D9, + MSG_MOVE_SET_FACING = 0x0DA, + MSG_MOVE_SET_PITCH = 0x0DB, + MSG_MOVE_WORLDPORT_ACK = 0x0DC, + SMSG_MONSTER_MOVE = 0x0DD, + SMSG_MOVE_WATER_WALK = 0x0DE, + SMSG_MOVE_LAND_WALK = 0x0DF, + MSG_MOVE_SET_RAW_POSITION_ACK = 0x0E0, + CMSG_MOVE_SET_RAW_POSITION = 0x0E1, + SMSG_FORCE_RUN_SPEED_CHANGE = 0x0E2, + CMSG_FORCE_RUN_SPEED_CHANGE_ACK = 0x0E3, + SMSG_FORCE_RUN_BACK_SPEED_CHANGE = 0x0E4, + CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK = 0x0E5, + SMSG_FORCE_SWIM_SPEED_CHANGE = 0x0E6, + CMSG_FORCE_SWIM_SPEED_CHANGE_ACK = 0x0E7, + SMSG_FORCE_MOVE_ROOT = 0x0E8, + CMSG_FORCE_MOVE_ROOT_ACK = 0x0E9, + SMSG_FORCE_MOVE_UNROOT = 0x0EA, + CMSG_FORCE_MOVE_UNROOT_ACK = 0x0EB, + MSG_MOVE_ROOT = 0x0EC, + MSG_MOVE_UNROOT = 0x0ED, + MSG_MOVE_HEARTBEAT = 0x0EE, + SMSG_MOVE_KNOCK_BACK = 0x0EF, + CMSG_MOVE_KNOCK_BACK_ACK = 0x0F0, + MSG_MOVE_KNOCK_BACK = 0x0F1, + SMSG_MOVE_FEATHER_FALL = 0x0F2, + SMSG_MOVE_NORMAL_FALL = 0x0F3, + SMSG_MOVE_SET_HOVER = 0x0F4, + SMSG_MOVE_UNSET_HOVER = 0x0F5, + CMSG_MOVE_HOVER_ACK = 0x0F6, + MSG_MOVE_HOVER = 0x0F7, + CMSG_TRIGGER_CINEMATIC_CHEAT = 0x0F8, + CMSG_OPENING_CINEMATIC = 0x0F9, + SMSG_TRIGGER_CINEMATIC = 0x0FA, + CMSG_NEXT_CINEMATIC_CAMERA = 0x0FB, + CMSG_COMPLETE_CINEMATIC = 0x0FC, + SMSG_TUTORIAL_FLAGS = 0x0FD, + CMSG_TUTORIAL_FLAG = 0x0FE, + CMSG_TUTORIAL_CLEAR = 0x0FF, + CMSG_TUTORIAL_RESET = 0x100, + CMSG_STANDSTATECHANGE = 0x101, + CMSG_EMOTE = 0x102, + SMSG_EMOTE = 0x103, + CMSG_TEXT_EMOTE = 0x104, + SMSG_TEXT_EMOTE = 0x105, + CMSG_AUTOEQUIP_GROUND_ITEM = 0x106, + CMSG_AUTOSTORE_GROUND_ITEM = 0x107, + CMSG_AUTOSTORE_LOOT_ITEM = 0x108, + CMSG_STORE_LOOT_IN_SLOT = 0x109, + CMSG_AUTOEQUIP_ITEM = 0x10A, + CMSG_AUTOSTORE_BAG_ITEM = 0x10B, + CMSG_SWAP_ITEM = 0x10C, + CMSG_SWAP_INV_ITEM = 0x10D, + CMSG_SPLIT_ITEM = 0x10E, + CMSG_AUTOEQUIP_ITEM_SLOT = 0x10F, + OBSOLETE_DROP_ITEM = 0x110, + CMSG_DESTROYITEM = 0x111, + SMSG_INVENTORY_CHANGE_FAILURE = 0x112, + SMSG_OPEN_CONTAINER = 0x113, + CMSG_INSPECT = 0x114, + SMSG_INSPECT = 0x115, + CMSG_INITIATE_TRADE = 0x116, + CMSG_BEGIN_TRADE = 0x117, + CMSG_BUSY_TRADE = 0x118, + CMSG_IGNORE_TRADE = 0x119, + CMSG_ACCEPT_TRADE = 0x11A, + CMSG_UNACCEPT_TRADE = 0x11B, + CMSG_CANCEL_TRADE = 0x11C, + CMSG_SET_TRADE_ITEM = 0x11D, + CMSG_CLEAR_TRADE_ITEM = 0x11E, + CMSG_SET_TRADE_GOLD = 0x11F, + SMSG_TRADE_STATUS = 0x120, + SMSG_TRADE_STATUS_EXTENDED = 0x121, + SMSG_INITIALIZE_FACTIONS = 0x122, + SMSG_SET_FACTION_VISIBLE = 0x123, + SMSG_SET_FACTION_STANDING = 0x124, + CMSG_SET_FACTION_ATWAR = 0x125, + CMSG_SET_FACTION_CHEAT = 0x126, + SMSG_SET_PROFICIENCY = 0x127, + CMSG_SET_ACTION_BUTTON = 0x128, + SMSG_ACTION_BUTTONS = 0x129, + SMSG_INITIAL_SPELLS = 0x12A, + SMSG_LEARNED_SPELL = 0x12B, + SMSG_SUPERCEDED_SPELL = 0x12C, + CMSG_NEW_SPELL_SLOT = 0x12D, + CMSG_CAST_SPELL = 0x12E, + CMSG_CANCEL_CAST = 0x12F, + SMSG_CAST_FAILED = 0x130, + SMSG_SPELL_START = 0x131, + SMSG_SPELL_GO = 0x132, + SMSG_SPELL_FAILURE = 0x133, + SMSG_SPELL_COOLDOWN = 0x134, + SMSG_COOLDOWN_EVENT = 0x135, + CMSG_CANCEL_AURA = 0x136, + SMSG_UPDATE_AURA_DURATION = 0x137, + SMSG_PET_CAST_FAILED = 0x138, + MSG_CHANNEL_START = 0x139, + MSG_CHANNEL_UPDATE = 0x13A, + CMSG_CANCEL_CHANNELLING = 0x13B, + SMSG_AI_REACTION = 0x13C, + CMSG_SET_SELECTION = 0x13D, + CMSG_SET_TARGET_OBSOLETE = 0x13E, + CMSG_UNUSED = 0x13F, + CMSG_UNUSED2 = 0x140, + CMSG_ATTACKSWING = 0x141, + CMSG_ATTACKSTOP = 0x142, + SMSG_ATTACKSTART = 0x143, + SMSG_ATTACKSTOP = 0x144, + SMSG_ATTACKSWING_NOTINRANGE = 0x145, + SMSG_ATTACKSWING_BADFACING = 0x146, + SMSG_ATTACKSWING_NOTSTANDING = 0x147, + SMSG_ATTACKSWING_DEADTARGET = 0x148, + SMSG_ATTACKSWING_CANT_ATTACK = 0x149, + SMSG_ATTACKERSTATEUPDATE = 0x14A, + SMSG_VICTIMSTATEUPDATE_OBSOLETE = 0x14B, + SMSG_DAMAGE_DONE_OBSOLETE = 0x14C, + SMSG_DAMAGE_TAKEN_OBSOLETE = 0x14D, + SMSG_CANCEL_COMBAT = 0x14E, + SMSG_PLAYER_COMBAT_XP_GAIN_OBSOLETE = 0x14F, + SMSG_SPELLHEALLOG = 0x150, + SMSG_SPELLENERGIZELOG = 0x151, + CMSG_SHEATHE_OBSOLETE = 0x152, + CMSG_SAVE_PLAYER = 0x153, + CMSG_SETDEATHBINDPOINT = 0x154, + SMSG_BINDPOINTUPDATE = 0x155, + CMSG_GETDEATHBINDZONE = 0x156, + SMSG_BINDZONEREPLY = 0x157, + SMSG_PLAYERBOUND = 0x158, + SMSG_CLIENT_CONTROL_UPDATE = 0x159, + CMSG_REPOP_REQUEST = 0x15A, + SMSG_RESURRECT_REQUEST = 0x15B, + CMSG_RESURRECT_RESPONSE = 0x15C, + CMSG_LOOT = 0x15D, + CMSG_LOOT_MONEY = 0x15E, + CMSG_LOOT_RELEASE = 0x15F, + SMSG_LOOT_RESPONSE = 0x160, + SMSG_LOOT_RELEASE_RESPONSE = 0x161, + SMSG_LOOT_REMOVED = 0x162, + SMSG_LOOT_MONEY_NOTIFY = 0x163, + SMSG_LOOT_ITEM_NOTIFY = 0x164, + SMSG_LOOT_CLEAR_MONEY = 0x165, + SMSG_ITEM_PUSH_RESULT = 0x166, + SMSG_DUEL_REQUESTED = 0x167, + SMSG_DUEL_OUTOFBOUNDS = 0x168, + SMSG_DUEL_INBOUNDS = 0x169, + SMSG_DUEL_COMPLETE = 0x16A, + SMSG_DUEL_WINNER = 0x16B, + CMSG_DUEL_ACCEPTED = 0x16C, + CMSG_DUEL_CANCELLED = 0x16D, + SMSG_MOUNTRESULT = 0x16E, + SMSG_DISMOUNTRESULT = 0x16F, + SMSG_PUREMOUNT_CANCELLED_OBSOLETE = 0x170, + CMSG_MOUNTSPECIAL_ANIM = 0x171, + SMSG_MOUNTSPECIAL_ANIM = 0x172, + SMSG_PET_TAME_FAILURE = 0x173, + CMSG_PET_SET_ACTION = 0x174, + CMSG_PET_ACTION = 0x175, + CMSG_PET_ABANDON = 0x176, + CMSG_PET_RENAME = 0x177, + SMSG_PET_NAME_INVALID = 0x178, + SMSG_PET_SPELLS = 0x179, + SMSG_PET_MODE = 0x17A, + CMSG_GOSSIP_HELLO = 0x17B, + CMSG_GOSSIP_SELECT_OPTION = 0x17C, + SMSG_GOSSIP_MESSAGE = 0x17D, + SMSG_GOSSIP_COMPLETE = 0x17E, + CMSG_NPC_TEXT_QUERY = 0x17F, + SMSG_NPC_TEXT_UPDATE = 0x180, + SMSG_NPC_WONT_TALK = 0x181, + CMSG_QUESTGIVER_STATUS_QUERY = 0x182, + SMSG_QUESTGIVER_STATUS = 0x183, + CMSG_QUESTGIVER_HELLO = 0x184, + SMSG_QUESTGIVER_QUEST_LIST = 0x185, + CMSG_QUESTGIVER_QUERY_QUEST = 0x186, + CMSG_QUESTGIVER_QUEST_AUTOLAUNCH = 0x187, + SMSG_QUESTGIVER_QUEST_DETAILS = 0x188, + CMSG_QUESTGIVER_ACCEPT_QUEST = 0x189, + CMSG_QUESTGIVER_COMPLETE_QUEST = 0x18A, + SMSG_QUESTGIVER_REQUEST_ITEMS = 0x18B, + CMSG_QUESTGIVER_REQUEST_REWARD = 0x18C, + SMSG_QUESTGIVER_OFFER_REWARD = 0x18D, + CMSG_QUESTGIVER_CHOOSE_REWARD = 0x18E, + SMSG_QUESTGIVER_QUEST_INVALID = 0x18F, + CMSG_QUESTGIVER_CANCEL = 0x190, + SMSG_QUESTGIVER_QUEST_COMPLETE = 0x191, + SMSG_QUESTGIVER_QUEST_FAILED = 0x192, + CMSG_QUESTLOG_SWAP_QUEST = 0x193, + CMSG_QUESTLOG_REMOVE_QUEST = 0x194, + SMSG_QUESTLOG_FULL = 0x195, + SMSG_QUESTUPDATE_FAILED = 0x196, + SMSG_QUESTUPDATE_FAILEDTIMER = 0x197, + SMSG_QUESTUPDATE_COMPLETE = 0x198, + SMSG_QUESTUPDATE_ADD_KILL = 0x199, + SMSG_QUESTUPDATE_ADD_ITEM = 0x19A, + CMSG_QUEST_CONFIRM_ACCEPT = 0x19B, + SMSG_QUEST_CONFIRM_ACCEPT = 0x19C, + CMSG_PUSHQUESTTOPARTY = 0x19D, + CMSG_LIST_INVENTORY = 0x19E, + SMSG_LIST_INVENTORY = 0x19F, + CMSG_SELL_ITEM = 0x1A0, + SMSG_SELL_ITEM = 0x1A1, + CMSG_BUY_ITEM = 0x1A2, + CMSG_BUY_ITEM_IN_SLOT = 0x1A3, + SMSG_BUY_ITEM = 0x1A4, + SMSG_BUY_FAILED = 0x1A5, + CMSG_TAXICLEARALLNODES = 0x1A6, + CMSG_TAXIENABLEALLNODES = 0x1A7, + CMSG_TAXISHOWNODES = 0x1A8, + SMSG_SHOWTAXINODES = 0x1A9, + CMSG_TAXINODE_STATUS_QUERY = 0x1AA, + SMSG_TAXINODE_STATUS = 0x1AB, + CMSG_TAXIQUERYAVAILABLENODES = 0x1AC, + CMSG_ACTIVATETAXI = 0x1AD, + SMSG_ACTIVATETAXIREPLY = 0x1AE, + SMSG_NEW_TAXI_PATH = 0x1AF, + CMSG_TRAINER_LIST = 0x1B0, + SMSG_TRAINER_LIST = 0x1B1, + CMSG_TRAINER_BUY_SPELL = 0x1B2, + SMSG_TRAINER_BUY_SUCCEEDED = 0x1B3, + SMSG_TRAINER_BUY_FAILED = 0x1B4, + CMSG_BINDER_ACTIVATE = 0x1B5, + SMSG_PLAYERBINDERROR = 0x1B6, + CMSG_BANKER_ACTIVATE = 0x1B7, + SMSG_SHOW_BANK = 0x1B8, + CMSG_BUY_BANK_SLOT = 0x1B9, + SMSG_BUY_BANK_SLOT_RESULT = 0x1BA, + CMSG_PETITION_SHOWLIST = 0x1BB, + SMSG_PETITION_SHOWLIST = 0x1BC, + CMSG_PETITION_BUY = 0x1BD, + CMSG_PETITION_SHOW_SIGNATURES = 0x1BE, + SMSG_PETITION_SHOW_SIGNATURES = 0x1BF, + CMSG_PETITION_SIGN = 0x1C0, + SMSG_PETITION_SIGN_RESULTS = 0x1C1, + MSG_PETITION_DECLINE = 0x1C2, + CMSG_OFFER_PETITION = 0x1C3, + CMSG_TURN_IN_PETITION = 0x1C4, + SMSG_TURN_IN_PETITION_RESULTS = 0x1C5, + CMSG_PETITION_QUERY = 0x1C6, + SMSG_PETITION_QUERY_RESPONSE = 0x1C7, + SMSG_FISH_NOT_HOOKED = 0x1C8, + SMSG_FISH_ESCAPED = 0x1C9, + CMSG_BUG = 0x1CA, + SMSG_NOTIFICATION = 0x1CB, + CMSG_PLAYED_TIME = 0x1CC, + SMSG_PLAYED_TIME = 0x1CD, + CMSG_QUERY_TIME = 0x1CE, + SMSG_QUERY_TIME_RESPONSE = 0x1CF, + SMSG_LOG_XPGAIN = 0x1D0, + SMSG_AURACASTLOG = 0x1D1, + CMSG_RECLAIM_CORPSE = 0x1D2, + CMSG_WRAP_ITEM = 0x1D3, + SMSG_LEVELUP_INFO = 0x1D4, + MSG_MINIMAP_PING = 0x1D5, + SMSG_RESISTLOG = 0x1D6, + SMSG_ENCHANTMENTLOG = 0x1D7, + CMSG_SET_SKILL_CHEAT = 0x1D8, + SMSG_START_MIRROR_TIMER = 0x1D9, + SMSG_PAUSE_MIRROR_TIMER = 0x1DA, + SMSG_STOP_MIRROR_TIMER = 0x1DB, + CMSG_PING = 0x1DC, + SMSG_PONG = 0x1DD, + SMSG_CLEAR_COOLDOWN = 0x1DE, + SMSG_GAMEOBJECT_PAGETEXT = 0x1DF, + CMSG_SETSHEATHED = 0x1E0, + SMSG_COOLDOWN_CHEAT = 0x1E1, + SMSG_SPELL_DELAYED = 0x1E2, + CMSG_PLAYER_MACRO_OBSOLETE = 0x1E3, + SMSG_PLAYER_MACRO_OBSOLETE = 0x1E4, + CMSG_GHOST = 0x1E5, + CMSG_GM_INVIS = 0x1E6, + SMSG_INVALID_PROMOTION_CODE = 0x1E7, + MSG_GM_BIND_OTHER = 0x1E8, + MSG_GM_SUMMON = 0x1E9, + SMSG_ITEM_TIME_UPDATE = 0x1EA, + SMSG_ITEM_ENCHANT_TIME_UPDATE = 0x1EB, + SMSG_AUTH_CHALLENGE = 0x1EC, + CMSG_AUTH_SESSION = 0x1ED, + SMSG_AUTH_RESPONSE = 0x1EE, + MSG_GM_SHOWLABEL = 0x1EF, + CMSG_PET_CAST_SPELL = 0x1F0, + MSG_SAVE_GUILD_EMBLEM = 0x1F1, + MSG_TABARDVENDOR_ACTIVATE = 0x1F2, + SMSG_PLAY_SPELL_VISUAL = 0x1F3, + CMSG_ZONEUPDATE = 0x1F4, + SMSG_PARTYKILLLOG = 0x1F5, + SMSG_COMPRESSED_UPDATE_OBJECT = 0x1F6, + SMSG_PLAY_SPELL_IMPACT = 0x1F7, + SMSG_EXPLORATION_EXPERIENCE = 0x1F8, + CMSG_GM_SET_SECURITY_GROUP = 0x1F9, + CMSG_GM_NUKE = 0x1FA, + MSG_RANDOM_ROLL = 0x1FB, + SMSG_ENVIRONMENTALDAMAGELOG = 0x1FC, + CMSG_RWHOIS_OBSOLETE = 0x1FD, + SMSG_RWHOIS = 0x1FE, + MSG_LOOKING_FOR_GROUP = 0x1FF, + CMSG_SET_LOOKING_FOR_GROUP = 0x200, + CMSG_UNLEARN_SPELL = 0x201, + CMSG_UNLEARN_SKILL = 0x202, + SMSG_REMOVED_SPELL = 0x203, + CMSG_DECHARGE = 0x204, + CMSG_GMTICKET_CREATE = 0x205, + SMSG_GMTICKET_CREATE = 0x206, + CMSG_GMTICKET_UPDATETEXT = 0x207, + SMSG_GMTICKET_UPDATETEXT = 0x208, + SMSG_ACCOUNT_DATA_TIMES = 0x209, + CMSG_REQUEST_ACCOUNT_DATA = 0x20A, + CMSG_UPDATE_ACCOUNT_DATA = 0x20B, + SMSG_UPDATE_ACCOUNT_DATA = 0x20C, + SMSG_CLEAR_FAR_SIGHT_IMMEDIATE = 0x20D, + SMSG_POWERGAINLOG_OBSOLETE = 0x20E, + CMSG_GM_TEACH = 0x20F, + CMSG_GM_CREATE_ITEM_TARGET = 0x210, + CMSG_GMTICKET_GETTICKET = 0x211, + SMSG_GMTICKET_GETTICKET = 0x212, + CMSG_UNLEARN_TALENTS = 0x213, + SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE = 0x214, + SMSG_GAMEOBJECT_DESPAWN_ANIM = 0x215, + MSG_CORPSE_QUERY = 0x216, + CMSG_GMTICKET_DELETETICKET = 0x217, + SMSG_GMTICKET_DELETETICKET = 0x218, + SMSG_CHAT_WRONG_FACTION = 0x219, + CMSG_GMTICKET_SYSTEMSTATUS = 0x21A, + SMSG_GMTICKET_SYSTEMSTATUS = 0x21B, + CMSG_SPIRIT_HEALER_ACTIVATE = 0x21C, + CMSG_SET_STAT_CHEAT = 0x21D, + SMSG_SET_REST_START = 0x21E, + CMSG_SKILL_BUY_STEP = 0x21F, + CMSG_SKILL_BUY_RANK = 0x220, + CMSG_XP_CHEAT = 0x221, + SMSG_SPIRIT_HEALER_CONFIRM = 0x222, + CMSG_CHARACTER_POINT_CHEAT = 0x223, + SMSG_GOSSIP_POI = 0x224, + CMSG_CHAT_IGNORED = 0x225, + CMSG_GM_VISION = 0x226, + CMSG_SERVER_COMMAND = 0x227, + CMSG_GM_SILENCE = 0x228, + CMSG_GM_REVEALTO = 0x229, + CMSG_GM_RESURRECT = 0x22A, + CMSG_GM_SUMMONMOB = 0x22B, + CMSG_GM_MOVECORPSE = 0x22C, + CMSG_GM_FREEZE = 0x22D, + CMSG_GM_UBERINVIS = 0x22E, + CMSG_GM_REQUEST_PLAYER_INFO = 0x22F, + SMSG_GM_PLAYER_INFO = 0x230, + CMSG_GUILD_RANK = 0x231, + CMSG_GUILD_ADD_RANK = 0x232, + CMSG_GUILD_DEL_RANK = 0x233, + CMSG_GUILD_SET_PUBLIC_NOTE = 0x234, + CMSG_GUILD_SET_OFFICER_NOTE = 0x235, + SMSG_LOGIN_VERIFY_WORLD = 0x236, + CMSG_CLEAR_EXPLORATION = 0x237, + CMSG_SEND_MAIL = 0x238, + SMSG_SEND_MAIL_RESULT = 0x239, + CMSG_GET_MAIL_LIST = 0x23A, + SMSG_MAIL_LIST_RESULT = 0x23B, + CMSG_BATTLEFIELD_LIST = 0x23C, + SMSG_BATTLEFIELD_LIST = 0x23D, + CMSG_BATTLEFIELD_JOIN = 0x23E, + SMSG_BATTLEFIELD_WIN_OBSOLETE = 0x23F, + SMSG_BATTLEFIELD_LOSE_OBSOLETE = 0x240, + CMSG_TAXICLEARNODE = 0x241, + CMSG_TAXIENABLENODE = 0x242, + CMSG_ITEM_TEXT_QUERY = 0x243, + SMSG_ITEM_TEXT_QUERY_RESPONSE = 0x244, + CMSG_MAIL_TAKE_MONEY = 0x245, + CMSG_MAIL_TAKE_ITEM = 0x246, + CMSG_MAIL_MARK_AS_READ = 0x247, + CMSG_MAIL_RETURN_TO_SENDER = 0x248, + CMSG_MAIL_DELETE = 0x249, + CMSG_MAIL_CREATE_TEXT_ITEM = 0x24A, + SMSG_SPELLLOGMISS = 0x24B, + SMSG_SPELLLOGEXECUTE = 0x24C, + SMSG_DEBUGAURAPROC = 0x24D, + SMSG_PERIODICAURALOG = 0x24E, + SMSG_SPELLDAMAGESHIELD = 0x24F, + SMSG_SPELLNONMELEEDAMAGELOG = 0x250, + CMSG_LEARN_TALENT = 0x251, + SMSG_RESURRECT_FAILED = 0x252, + CMSG_TOGGLE_PVP = 0x253, + SMSG_ZONE_UNDER_ATTACK = 0x254, + MSG_AUCTION_HELLO = 0x255, + CMSG_AUCTION_SELL_ITEM = 0x256, + CMSG_AUCTION_REMOVE_ITEM = 0x257, + CMSG_AUCTION_LIST_ITEMS = 0x258, + CMSG_AUCTION_LIST_OWNER_ITEMS = 0x259, + CMSG_AUCTION_PLACE_BID = 0x25A, + SMSG_AUCTION_COMMAND_RESULT = 0x25B, + SMSG_AUCTION_LIST_RESULT = 0x25C, + SMSG_AUCTION_OWNER_LIST_RESULT = 0x25D, + SMSG_AUCTION_BIDDER_NOTIFICATION = 0x25E, + SMSG_AUCTION_OWNER_NOTIFICATION = 0x25F, + SMSG_PROCRESIST = 0x260, + SMSG_STANDSTATE_CHANGE_FAILURE_OBSOLETE = 0x261, + SMSG_DISPEL_FAILED = 0x262, + SMSG_SPELLORDAMAGE_IMMUNE = 0x263, + CMSG_AUCTION_LIST_BIDDER_ITEMS = 0x264, + SMSG_AUCTION_BIDDER_LIST_RESULT = 0x265, + SMSG_SET_FLAT_SPELL_MODIFIER = 0x266, + SMSG_SET_PCT_SPELL_MODIFIER = 0x267, + CMSG_SET_AMMO = 0x268, + SMSG_CORPSE_RECLAIM_DELAY = 0x269, + CMSG_SET_ACTIVE_MOVER = 0x26A, + CMSG_PET_CANCEL_AURA = 0x26B, + CMSG_PLAYER_AI_CHEAT = 0x26C, + CMSG_CANCEL_AUTO_REPEAT_SPELL = 0x26D, + MSG_GM_ACCOUNT_ONLINE = 0x26E, + MSG_LIST_STABLED_PETS = 0x26F, + CMSG_STABLE_PET = 0x270, + CMSG_UNSTABLE_PET = 0x271, + CMSG_BUY_STABLE_SLOT = 0x272, + SMSG_STABLE_RESULT = 0x273, + CMSG_STABLE_REVIVE_PET = 0x274, + CMSG_STABLE_SWAP_PET = 0x275, + MSG_QUEST_PUSH_RESULT = 0x276, + SMSG_PLAY_MUSIC = 0x277, + SMSG_PLAY_OBJECT_SOUND = 0x278, + CMSG_REQUEST_PET_INFO = 0x279, + CMSG_FAR_SIGHT = 0x27A, + SMSG_SPELLDISPELLOG = 0x27B, + SMSG_DAMAGE_CALC_LOG = 0x27C, + CMSG_ENABLE_DAMAGE_LOG = 0x27D, + CMSG_GROUP_CHANGE_SUB_GROUP = 0x27E, + CMSG_REQUEST_PARTY_MEMBER_STATS = 0x27F, + CMSG_GROUP_SWAP_SUB_GROUP = 0x280, + CMSG_RESET_FACTION_CHEAT = 0x281, + CMSG_AUTOSTORE_BANK_ITEM = 0x282, + CMSG_AUTOBANK_ITEM = 0x283, + MSG_QUERY_NEXT_MAIL_TIME = 0x284, + SMSG_RECEIVED_MAIL = 0x285, + SMSG_RAID_GROUP_ONLY = 0x286, + CMSG_SET_DURABILITY_CHEAT = 0x287, + CMSG_SET_PVP_RANK_CHEAT = 0x288, + CMSG_ADD_PVP_MEDAL_CHEAT = 0x289, + CMSG_DEL_PVP_MEDAL_CHEAT = 0x28A, + CMSG_SET_PVP_TITLE = 0x28B, + SMSG_PVP_CREDIT = 0x28C, + SMSG_AUCTION_REMOVED_NOTIFICATION = 0x28D, + CMSG_GROUP_RAID_CONVERT = 0x28E, + CMSG_GROUP_ASSISTANT_LEADER = 0x28F, + CMSG_BUYBACK_ITEM = 0x290, + SMSG_SERVER_MESSAGE = 0x291, + CMSG_MEETINGSTONE_JOIN = 0x292, + CMSG_MEETINGSTONE_LEAVE = 0x293, + CMSG_MEETINGSTONE_CHEAT = 0x294, + SMSG_MEETINGSTONE_SETQUEUE = 0x295, + CMSG_MEETINGSTONE_INFO = 0x296, + SMSG_MEETINGSTONE_COMPLETE = 0x297, + SMSG_MEETINGSTONE_IN_PROGRESS = 0x298, + SMSG_MEETINGSTONE_MEMBER_ADDED = 0x299, + CMSG_GMTICKETSYSTEM_TOGGLE = 0x29A, + CMSG_CANCEL_GROWTH_AURA = 0x29B, + SMSG_CANCEL_AUTO_REPEAT = 0x29C, + SMSG_STANDSTATE_UPDATE = 0x29D, + SMSG_LOOT_ALL_PASSED = 0x29E, + SMSG_LOOT_ROLL_WON = 0x29F, + CMSG_LOOT_ROLL = 0x2A0, + SMSG_LOOT_START_ROLL = 0x2A1, + SMSG_LOOT_ROLL = 0x2A2, + CMSG_LOOT_MASTER_GIVE = 0x2A3, + SMSG_LOOT_MASTER_LIST = 0x2A4, + SMSG_SET_FORCED_REACTIONS = 0x2A5, + SMSG_SPELL_FAILED_OTHER = 0x2A6, + SMSG_GAMEOBJECT_RESET_STATE = 0x2A7, + CMSG_REPAIR_ITEM = 0x2A8, + SMSG_CHAT_PLAYER_NOT_FOUND = 0x2A9, + MSG_TALENT_WIPE_CONFIRM = 0x2AA, + SMSG_SUMMON_REQUEST = 0x2AB, + CMSG_SUMMON_RESPONSE = 0x2AC, + MSG_MOVE_TOGGLE_GRAVITY_CHEAT = 0x2AD, + SMSG_MONSTER_MOVE_TRANSPORT = 0x2AE, + SMSG_PET_BROKEN = 0x2AF, + MSG_MOVE_FEATHER_FALL = 0x2B0, + MSG_MOVE_WATER_WALK = 0x2B1, + CMSG_SERVER_BROADCAST = 0x2B2, + CMSG_SELF_RES = 0x2B3, + SMSG_FEIGN_DEATH_RESISTED = 0x2B4, + CMSG_RUN_SCRIPT = 0x2B5, + SMSG_SCRIPT_MESSAGE = 0x2B6, + SMSG_DUEL_COUNTDOWN = 0x2B7, + SMSG_AREA_TRIGGER_MESSAGE = 0x2B8, + CMSG_TOGGLE_HELM = 0x2B9, + CMSG_TOGGLE_CLOAK = 0x2BA, + SMSG_MEETINGSTONE_JOINFAILED = 0x2BB, + SMSG_PLAYER_SKINNED = 0x2BC, + SMSG_DURABILITY_DAMAGE_DEATH = 0x2BD, + CMSG_SET_EXPLORATION = 0x2BE, + CMSG_SET_ACTIONBAR_TOGGLES = 0x2BF, + UMSG_DELETE_GUILD_CHARTER = 0x2C0, + MSG_PETITION_RENAME = 0x2C1, + SMSG_INIT_WORLD_STATES = 0x2C2, + SMSG_UPDATE_WORLD_STATE = 0x2C3, + CMSG_ITEM_NAME_QUERY = 0x2C4, + SMSG_ITEM_NAME_QUERY_RESPONSE = 0x2C5, + SMSG_PET_ACTION_FEEDBACK = 0x2C6, + CMSG_CHAR_RENAME = 0x2C7, + SMSG_CHAR_RENAME = 0x2C8, + CMSG_MOVE_SPLINE_DONE = 0x2C9, + CMSG_MOVE_FALL_RESET = 0x2CA, + SMSG_INSTANCE_SAVE_CREATED = 0x2CB, + SMSG_RAID_INSTANCE_INFO = 0x2CC, + CMSG_REQUEST_RAID_INFO = 0x2CD, + CMSG_MOVE_TIME_SKIPPED = 0x2CE, + CMSG_MOVE_FEATHER_FALL_ACK = 0x2CF, + CMSG_MOVE_WATER_WALK_ACK = 0x2D0, + CMSG_MOVE_NOT_ACTIVE_MOVER = 0x2D1, + SMSG_PLAY_SOUND = 0x2D2, + CMSG_BATTLEFIELD_STATUS = 0x2D3, + SMSG_BATTLEFIELD_STATUS = 0x2D4, + CMSG_BATTLEFIELD_PORT = 0x2D5, + MSG_INSPECT_HONOR_STATS = 0x2D6, + CMSG_BATTLEMASTER_HELLO = 0x2D7, + CMSG_MOVE_START_SWIM_CHEAT = 0x2D8, + CMSG_MOVE_STOP_SWIM_CHEAT = 0x2D9, + SMSG_FORCE_WALK_SPEED_CHANGE = 0x2DA, + CMSG_FORCE_WALK_SPEED_CHANGE_ACK = 0x2DB, + SMSG_FORCE_SWIM_BACK_SPEED_CHANGE = 0x2DC, + CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK = 0x2DD, + SMSG_FORCE_TURN_RATE_CHANGE = 0x2DE, + CMSG_FORCE_TURN_RATE_CHANGE_ACK = 0x2DF, + MSG_PVP_LOG_DATA = 0x2E0, + CMSG_LEAVE_BATTLEFIELD = 0x2E1, + CMSG_AREA_SPIRIT_HEALER_QUERY = 0x2E2, + CMSG_AREA_SPIRIT_HEALER_QUEUE = 0x2E3, + SMSG_AREA_SPIRIT_HEALER_TIME = 0x2E4, + CMSG_GM_UNTEACH = 0x2E5, + SMSG_WARDEN_DATA = 0x2E6, + CMSG_WARDEN_DATA = 0x2E7, + SMSG_GROUP_JOINED_BATTLEGROUND = 0x2E8, + MSG_BATTLEGROUND_PLAYER_POSITIONS = 0x2E9, + CMSG_PET_STOP_ATTACK = 0x2EA, + SMSG_BINDER_CONFIRM = 0x2EB, + SMSG_BATTLEGROUND_PLAYER_JOINED = 0x2EC, + SMSG_BATTLEGROUND_PLAYER_LEFT = 0x2ED, + CMSG_BATTLEMASTER_JOIN = 0x2EE, + SMSG_ADDON_INFO = 0x2EF, + CMSG_PET_UNLEARN = 0x2F0, + SMSG_PET_UNLEARN_CONFIRM = 0x2F1, + SMSG_PARTY_MEMBER_STATS_FULL = 0x2F2, + CMSG_PET_SPELL_AUTOCAST = 0x2F3, + SMSG_WEATHER = 0x2F4, + SMSG_PLAY_TIME_WARNING = 0x2F5, + SMSG_MINIGAME_SETUP = 0x2F6, + SMSG_MINIGAME_STATE = 0x2F7, + CMSG_MINIGAME_MOVE = 0x2F8, + SMSG_MINIGAME_MOVE_FAILED = 0x2F9, + SMSG_RAID_INSTANCE_MESSAGE = 0x2FA, + SMSG_COMPRESSED_MOVES = 0x2FB, + CMSG_GUILD_INFO_TEXT = 0x2FC, + SMSG_CHAT_RESTRICTED = 0x2FD, + SMSG_SPLINE_SET_RUN_SPEED = 0x2FE, + SMSG_SPLINE_SET_RUN_BACK_SPEED = 0x2FF, + SMSG_SPLINE_SET_SWIM_SPEED = 0x300, + SMSG_SPLINE_SET_WALK_SPEED = 0x301, + SMSG_SPLINE_SET_SWIM_BACK_SPEED = 0x302, + SMSG_SPLINE_SET_TURN_RATE = 0x303, + SMSG_SPLINE_MOVE_UNROOT = 0x304, + SMSG_SPLINE_MOVE_FEATHER_FALL = 0x305, + SMSG_SPLINE_MOVE_NORMAL_FALL = 0x306, + SMSG_SPLINE_MOVE_SET_HOVER = 0x307, + SMSG_SPLINE_MOVE_UNSET_HOVER = 0x308, + SMSG_SPLINE_MOVE_WATER_WALK = 0x309, + SMSG_SPLINE_MOVE_LAND_WALK = 0x30A, + SMSG_SPLINE_MOVE_START_SWIM = 0x30B, + SMSG_SPLINE_MOVE_STOP_SWIM = 0x30C, + SMSG_SPLINE_MOVE_SET_RUN_MODE = 0x30D, + SMSG_SPLINE_MOVE_SET_WALK_MODE = 0x30E, + CMSG_GM_NUKE_ACCOUNT = 0x30F, + MSG_GM_DESTROY_CORPSE = 0x310, + CMSG_GM_DESTROY_ONLINE_CORPSE = 0x311, + CMSG_ACTIVATETAXIEXPRESS = 0x312, + SMSG_SET_FACTION_ATWAR = 0x313, + SMSG_GAMETIMEBIAS_SET = 0x314, + CMSG_DEBUG_ACTIONS_START = 0x315, + CMSG_DEBUG_ACTIONS_STOP = 0x316, + CMSG_SET_FACTION_INACTIVE = 0x317, + CMSG_SET_WATCHED_FACTION = 0x318, + MSG_MOVE_TIME_SKIPPED = 0x319, + SMSG_SPLINE_MOVE_ROOT = 0x31A, + CMSG_SET_EXPLORATION_ALL = 0x31B, + SMSG_INVALIDATE_PLAYER = 0x31C, + CMSG_RESET_INSTANCES = 0x31D, + SMSG_INSTANCE_RESET = 0x31E, + SMSG_INSTANCE_RESET_FAILED = 0x31F, + SMSG_UPDATE_LAST_INSTANCE = 0x320, + MSG_RAID_TARGET_UPDATE = 0x321, + MSG_RAID_READY_CHECK = 0x322, + CMSG_LUA_USAGE = 0x323, + SMSG_PET_ACTION_SOUND = 0x324, + SMSG_PET_DISMISS_SOUND = 0x325, + SMSG_GHOSTEE_GONE = 0x326, + CMSG_GM_UPDATE_TICKET_STATUS = 0x327, + SMSG_GM_TICKET_STATUS_UPDATE = 0x328, + MSG_SET_DUNGEON_DIFFICULTY = 0x329, + CMSG_GMSURVEY_SUBMIT = 0x32A, + SMSG_UPDATE_INSTANCE_OWNERSHIP = 0x32B, + CMSG_IGNORE_KNOCKBACK_CHEAT = 0x32C, + SMSG_CHAT_PLAYER_AMBIGUOUS = 0x32D, + MSG_DELAY_GHOST_TELEPORT = 0x32E, + SMSG_SPELLINSTAKILLLOG = 0x32F, + SMSG_SPELL_UPDATE_CHAIN_TARGETS = 0x330, + CMSG_CHAT_FILTERED = 0x331, + SMSG_EXPECTED_SPAM_RECORDS = 0x332, + SMSG_SPELLSTEALLOG = 0x333, + CMSG_LOTTERY_QUERY_OBSOLETE = 0x334, + SMSG_LOTTERY_QUERY_RESULT_OBSOLETE = 0x335, + CMSG_BUY_LOTTERY_TICKET_OBSOLETE = 0x336, + SMSG_LOTTERY_RESULT_OBSOLETE = 0x337, + SMSG_CHARACTER_PROFILE = 0x338, + SMSG_CHARACTER_PROFILE_REALM_CONNECTED = 0x339, + SMSG_DEFENSE_MESSAGE = 0x33A, + SMSG_INSTANCE_DIFFICULTY = 0x33B, + MSG_GM_RESETINSTANCELIMIT = 0x33C, + SMSG_MOTD = 0x33D, + SMSG_MOVE_SET_FLIGHT_OBSOLETE = 0x33E, + SMSG_MOVE_UNSET_FLIGHT_OBSOLETE = 0x33F, + CMSG_MOVE_FLIGHT_ACK_OBSOLETE = 0x340, + MSG_MOVE_START_SWIM_CHEAT = 0x341, + MSG_MOVE_STOP_SWIM_CHEAT = 0x342, + SMSG_MOVE_SET_CAN_FLY = 0x343, + SMSG_MOVE_UNSET_CAN_FLY = 0x344, + CMSG_MOVE_SET_CAN_FLY_ACK = 0x345, + CMSG_MOVE_SET_FLY = 0x346, + CMSG_SOCKET_GEMS = 0x347, + CMSG_ARENA_TEAM_CREATE = 0x348, + SMSG_ARENA_TEAM_COMMAND_RESULT = 0x349, + UMSG_UPDATE_ARENA_TEAM_OBSOLETE = 0x34A, + CMSG_ARENA_TEAM_QUERY = 0x34B, + SMSG_ARENA_TEAM_QUERY_RESPONSE = 0x34C, + CMSG_ARENA_TEAM_ROSTER = 0x34D, + SMSG_ARENA_TEAM_ROSTER = 0x34E, + CMSG_ARENA_TEAM_INVITE = 0x34F, + SMSG_ARENA_TEAM_INVITE = 0x350, + CMSG_ARENA_TEAM_ACCEPT = 0x351, + CMSG_ARENA_TEAM_DECLINE = 0x352, + CMSG_ARENA_TEAM_LEAVE = 0x353, + CMSG_ARENA_TEAM_REMOVE = 0x354, + CMSG_ARENA_TEAM_DISBAND = 0x355, + CMSG_ARENA_TEAM_LEADER = 0x356, + SMSG_ARENA_TEAM_EVENT = 0x357, + CMSG_BATTLEMASTER_JOIN_ARENA = 0x358, + MSG_MOVE_START_ASCEND = 0x359, + MSG_MOVE_STOP_ASCEND = 0x35A, + SMSG_ARENA_TEAM_STATS = 0x35B, + CMSG_LFG_SET_AUTOJOIN = 0x35C, + CMSG_LFG_CLEAR_AUTOJOIN = 0x35D, + CMSG_LFM_SET_AUTOFILL = 0x35E, + CMSG_LFM_CLEAR_AUTOFILL = 0x35F, + CMSG_ACCEPT_LFG_MATCH = 0x360, + CMSG_DECLINE_LFG_MATCH = 0x361, + CMSG_CANCEL_PENDING_LFG = 0x362, + CMSG_CLEAR_LOOKING_FOR_GROUP = 0x363, + CMSG_CLEAR_LOOKING_FOR_MORE = 0x364, + CMSG_SET_LOOKING_FOR_MORE = 0x365, + CMSG_SET_LFG_COMMENT = 0x366, + SMSG_LFG_TIMEDOUT = 0x367, + SMSG_LFG_OTHER_TIMEDOUT = 0x368, + SMSG_LFG_AUTOJOIN_FAILED = 0x369, + SMSG_LFG_AUTOJOIN_FAILED_NO_PLAYER = 0x36A, + SMSG_LFG_LEADER_IS_LFM = 0x36B, + SMSG_LFG_UPDATE = 0x36C, + SMSG_LFG_UPDATE_LFM = 0x36D, + SMSG_LFG_UPDATE_LFG = 0x36E, + SMSG_LFG_UPDATE_QUEUED = 0x36F, + SMSG_LFG_PENDING_INVITE = 0x370, + SMSG_LFG_PENDING_MATCH = 0x371, + SMSG_LFG_PENDING_MATCH_DONE = 0x372, + SMSG_TITLE_EARNED = 0x373, + CMSG_SET_TITLE = 0x374, + CMSG_CANCEL_MOUNT_AURA = 0x375, + SMSG_ARENA_ERROR = 0x376, + MSG_INSPECT_ARENA_TEAMS = 0x377, + SMSG_DEATH_RELEASE_LOC = 0x378, + CMSG_CANCEL_TEMP_ENCHANTMENT = 0x379, + SMSG_FORCED_DEATH_UPDATE = 0x37A, + CMSG_CHEAT_SET_HONOR_CURRENCY = 0x37B, + CMSG_CHEAT_SET_ARENA_CURRENCY = 0x37C, + MSG_MOVE_SET_FLIGHT_SPEED_CHEAT = 0x37D, + MSG_MOVE_SET_FLIGHT_SPEED = 0x37E, + MSG_MOVE_SET_FLIGHT_BACK_SPEED_CHEAT = 0x37F, + MSG_MOVE_SET_FLIGHT_BACK_SPEED = 0x380, + SMSG_FORCE_FLIGHT_SPEED_CHANGE = 0x381, + CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK = 0x382, + SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE = 0x383, + CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK = 0x384, + SMSG_SPLINE_SET_FLIGHT_SPEED = 0x385, + SMSG_SPLINE_SET_FLIGHT_BACK_SPEED = 0x386, + CMSG_MAELSTROM_INVALIDATE_CACHE = 0x387, + SMSG_FLIGHT_SPLINE_SYNC = 0x388, + CMSG_SET_TAXI_BENCHMARK_MODE = 0x389, + SMSG_JOINED_BATTLEGROUND_QUEUE = 0x38A, + SMSG_REALM_SPLIT = 0x38B, + CMSG_REALM_SPLIT = 0x38C, + CMSG_MOVE_CHNG_TRANSPORT = 0x38D, + MSG_PARTY_ASSIGNMENT = 0x38E, + SMSG_OFFER_PETITION_ERROR = 0x38F, + SMSG_TIME_SYNC_REQ = 0x390, + CMSG_TIME_SYNC_RESP = 0x391, + CMSG_SEND_LOCAL_EVENT = 0x392, + CMSG_SEND_GENERAL_TRIGGER = 0x393, + CMSG_SEND_COMBAT_TRIGGER = 0x394, + CMSG_MAELSTROM_GM_SENT_MAIL = 0x395, + SMSG_RESET_FAILED_NOTIFY = 0x396, + SMSG_REAL_GROUP_UPDATE = 0x397, + SMSG_LFG_DISABLED = 0x398, + CMSG_ACTIVE_PVP_CHEAT = 0x399, + CMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY = 0x39A, + SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE = 0x39B, + SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE_WRITE_FILE = 0x39C, + SMSG_UPDATE_COMBO_POINTS = 0x39D, + SMSG_VOICE_SESSION_ROSTER_UPDATE = 0x39E, + SMSG_VOICE_SESSION_LEAVE = 0x39F, + SMSG_VOICE_SESSION_ADJUST_PRIORITY = 0x3A0, + CMSG_VOICE_SET_TALKER_MUTED_REQUEST = 0x3A1, + SMSG_VOICE_SET_TALKER_MUTED = 0x3A2, + SMSG_INIT_EXTRA_AURA_INFO = 0x3A3, + SMSG_SET_EXTRA_AURA_INFO = 0x3A4, + SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE = 0x3A5, + SMSG_CLEAR_EXTRA_AURA_INFO = 0x3A6, + MSG_MOVE_START_DESCEND = 0x3A7, + CMSG_IGNORE_REQUIREMENTS_CHEAT = 0x3A8, + SMSG_IGNORE_REQUIREMENTS_CHEAT = 0x3A9, + SMSG_SPELL_CHANCE_PROC_LOG = 0x3AA, + CMSG_MOVE_SET_RUN_SPEED = 0x3AB, + SMSG_DISMOUNT = 0x3AC, + MSG_MOVE_UPDATE_CAN_FLY = 0x3AD, + MSG_RAID_READY_CHECK_CONFIRM = 0x3AE, + CMSG_VOICE_SESSION_ENABLE = 0x3AF, + SMSG_VOICE_PARENTAL_CONTROLS = 0x3B0, + CMSG_GM_WHISPER = 0x3B1, + SMSG_GM_MESSAGECHAT = 0x3B2, + MSG_GM_GEARRATING = 0x3B3, + CMSG_COMMENTATOR_ENABLE = 0x3B4, + SMSG_COMMENTATOR_STATE_CHANGED = 0x3B5, + CMSG_COMMENTATOR_GET_MAP_INFO = 0x3B6, + SMSG_COMMENTATOR_MAP_INFO = 0x3B7, + CMSG_COMMENTATOR_GET_PLAYER_INFO = 0x3B8, + SMSG_COMMENTATOR_GET_PLAYER_INFO = 0x3B9, + SMSG_COMMENTATOR_PLAYER_INFO = 0x3BA, + CMSG_COMMENTATOR_ENTER_INSTANCE = 0x3BB, + CMSG_COMMENTATOR_EXIT_INSTANCE = 0x3BC, + CMSG_COMMENTATOR_INSTANCE_COMMAND = 0x3BD, + SMSG_CLEAR_TARGET = 0x3BE, + CMSG_BOT_DETECTED = 0x3BF, + SMSG_CROSSED_INEBRIATION_THRESHOLD = 0x3C0, + CMSG_CHEAT_PLAYER_LOGIN = 0x3C1, + CMSG_CHEAT_PLAYER_LOOKUP = 0x3C2, + SMSG_CHEAT_PLAYER_LOOKUP = 0x3C3, + SMSG_KICK_REASON = 0x3C4, + MSG_RAID_READY_CHECK_FINISHED = 0x3C5, + CMSG_COMPLAIN = 0x3C6, + SMSG_COMPLAIN_RESULT = 0x3C7, + SMSG_FEATURE_SYSTEM_STATUS = 0x3C8, + CMSG_GM_SHOW_COMPLAINTS = 0x3C9, + CMSG_GM_UNSQUELCH = 0x3CA, + CMSG_CHANNEL_SILENCE_VOICE = 0x3CB, + CMSG_CHANNEL_SILENCE_ALL = 0x3CC, + CMSG_CHANNEL_UNSILENCE_VOICE = 0x3CD, + CMSG_CHANNEL_UNSILENCE_ALL = 0x3CE, + CMSG_TARGET_CAST = 0x3CF, + CMSG_TARGET_SCRIPT_CAST = 0x3D0, + CMSG_CHANNEL_DISPLAY_LIST = 0x3D1, + CMSG_SET_ACTIVE_VOICE_CHANNEL = 0x3D2, + CMSG_GET_CHANNEL_MEMBER_COUNT = 0x3D3, + SMSG_CHANNEL_MEMBER_COUNT = 0x3D4, + CMSG_CHANNEL_VOICE_ON = 0x3D5, + CMSG_CHANNEL_VOICE_OFF = 0x3D6, + CMSG_DEBUG_LIST_TARGETS = 0x3D7, + SMSG_DEBUG_LIST_TARGETS = 0x3D8, + SMSG_AVAILABLE_VOICE_CHANNEL = 0x3D9, + CMSG_ADD_VOICE_IGNORE = 0x3DA, + CMSG_DEL_VOICE_IGNORE = 0x3DB, + CMSG_PARTY_SILENCE = 0x3DC, + CMSG_PARTY_UNSILENCE = 0x3DD, + MSG_NOTIFY_PARTY_SQUELCH = 0x3DE, + SMSG_COMSAT_RECONNECT_TRY = 0x3DF, + SMSG_COMSAT_DISCONNECT = 0x3E0, + SMSG_COMSAT_CONNECT_FAIL = 0x3E1, + SMSG_VOICE_CHAT_STATUS = 0x3E2, + CMSG_REPORT_PVP_AFK = 0x3E3, + CMSG_REPORT_PVP_AFK_RESULT = 0x3E4, + CMSG_GUILD_BANKER_ACTIVATE = 0x3E5, + CMSG_GUILD_BANK_QUERY_TAB = 0x3E6, + SMSG_GUILD_BANK_LIST = 0x3E7, + CMSG_GUILD_BANK_SWAP_ITEMS = 0x3E8, + CMSG_GUILD_BANK_BUY_TAB = 0x3E9, + CMSG_GUILD_BANK_UPDATE_TAB = 0x3EA, + CMSG_GUILD_BANK_DEPOSIT_MONEY = 0x3EB, + CMSG_GUILD_BANK_WITHDRAW_MONEY = 0x3EC, + MSG_GUILD_BANK_LOG_QUERY = 0x3ED, + CMSG_SET_CHANNEL_WATCH = 0x3EE, + SMSG_USERLIST_ADD = 0x3EF, + SMSG_USERLIST_REMOVE = 0x3F0, + SMSG_USERLIST_UPDATE = 0x3F1, + CMSG_CLEAR_CHANNEL_WATCH = 0x3F2, + SMSG_INSPECT_TALENT = 0x3F3, + SMSG_GOGOGO_OBSOLETE = 0x3F4, + SMSG_ECHO_PARTY_SQUELCH = 0x3F5, + CMSG_SET_TITLE_SUFFIX = 0x3F6, + CMSG_SPELLCLICK = 0x3F7, + SMSG_LOOT_LIST = 0x3F8, + CMSG_GM_CHARACTER_RESTORE = 0x3F9, + CMSG_GM_CHARACTER_SAVE = 0x3FA, + SMSG_VOICESESSION_FULL = 0x3FB, + MSG_GUILD_PERMISSIONS = 0x3FC, + MSG_GUILD_BANK_MONEY_WITHDRAWN = 0x3FD, + MSG_GUILD_EVENT_LOG_QUERY = 0x3FE, + CMSG_MAELSTROM_RENAME_GUILD = 0x3FF, + CMSG_GET_MIRRORIMAGE_DATA = 0x400, + SMSG_MIRRORIMAGE_DATA = 0x401, + SMSG_FORCE_DISPLAY_UPDATE = 0x402, + SMSG_SPELL_CHANCE_RESIST_PUSHBACK = 0x403, + CMSG_IGNORE_DIMINISHING_RETURNS_CHEAT = 0x404, + SMSG_IGNORE_DIMINISHING_RETURNS_CHEAT = 0x405, + CMSG_KEEP_ALIVE = 0x406, + SMSG_RAID_READY_CHECK_ERROR = 0x407, + CMSG_OPT_OUT_OF_LOOT = 0x408, + MSG_QUERY_GUILD_BANK_TEXT = 0x409, + CMSG_SET_GUILD_BANK_TEXT = 0x40A, + CMSG_SET_GRANTABLE_LEVELS = 0x40B, + CMSG_GRANT_LEVEL = 0x40C, + CMSG_REFER_A_FRIEND = 0x40D, + MSG_GM_CHANGE_ARENA_RATING = 0x40E, + CMSG_DECLINE_CHANNEL_INVITE = 0x40F, + CMSG_GROUPACTION_THROTTLED = 0x410, + SMSG_OVERRIDE_LIGHT = 0x411, + SMSG_TOTEM_CREATED = 0x412, + CMSG_TOTEM_DESTROYED = 0x413, + CMSG_EXPIRE_RAID_INSTANCE = 0x414, + CMSG_NO_SPELL_VARIANCE = 0x415, + CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY = 0x416, + SMSG_QUESTGIVER_STATUS_MULTIPLE = 0x417, + CMSG_SET_PLAYER_DECLINED_NAMES = 0x418, + SMSG_SET_PLAYER_DECLINED_NAMES_RESULT = 0x419, + CMSG_QUERY_SERVER_BUCK_DATA = 0x41A, + CMSG_CLEAR_SERVER_BUCK_DATA = 0x41B, + SMSG_SERVER_BUCK_DATA = 0x41C, + SMSG_SEND_UNLEARN_SPELLS = 0x41D, + SMSG_PROPOSE_LEVEL_GRANT = 0x41E, + CMSG_ACCEPT_LEVEL_GRANT = 0x41F, + SMSG_REFER_A_FRIEND_FAILURE = 0x420, + SMSG_SPLINE_MOVE_SET_FLYING = 0x421, + SMSG_SPLINE_MOVE_UNSET_FLYING = 0x422, + SMSG_SUMMON_CANCEL = 0x423 +}; + +// Don't forget to change this value and add opcode name to Opcodes.cpp when you add new opcode! +#define NUM_MSG_TYPES 0x424 + +/// Player state +enum SessionStatus +{ + STATUS_AUTHED = 0, ///< Player authenticated + STATUS_LOGGEDIN, ///< Player in game + STATUS_TRANSFER_PENDING, ///< Player transferring to another map + STATUS_NEVER ///< Opcode not accepted from client (deprecated or server side only) +}; + +class WorldSession; +class WorldPacket; + +struct OpcodeHandler +{ + char const* name; + SessionStatus status; + void (WorldSession::*handler)(WorldPacket& recvPacket); +}; + +extern OpcodeHandler opcodeTable[NUM_MSG_TYPES]; + +/// Lookup opcode name for human understandable logging +inline const char* LookupOpcodeName(uint16 id) +{ + if (id >= NUM_MSG_TYPES) + return "Received unknown opcode, it's more than max!"; + return opcodeTable[id].name; +} +#endif +/// @} diff --git a/src/game/Path.h b/src/game/Path.h new file mode 100644 index 00000000000..2085e567def --- /dev/null +++ b/src/game/Path.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOSSERVER_PATH_H +#define MANGOSSERVER_PATH_H + +#include "Common.h" +#include + +class Path +{ + public: + struct PathNode + { + float x,y,z; + }; + + void SetLength(const unsigned int sz) + { + i_nodes.resize( sz ); + } + + unsigned int Size() const { return i_nodes.size(); } + bool Empty() const { return i_nodes.empty(); } + void Resize(unsigned int sz) { i_nodes.resize(sz); } + void Clear(void) { i_nodes.clear(); } + PathNode const* GetNodes(uint32 start = 0) const { return &i_nodes[start]; } + float GetTotalLength() const { return GetTotalLength(0,Size()); } + float GetTotalLength(uint32 start, uint32 end) const + { + float len = 0, xd, yd, zd; + for(unsigned int idx=start+1; idx < end; ++idx) + { + xd = i_nodes[ idx ].x - i_nodes[ idx-1 ].x; + yd = i_nodes[ idx ].y - i_nodes[ idx-1 ].y; + zd = i_nodes[ idx ].z - i_nodes[ idx-1 ].z; + len += sqrtf( xd*xd + yd*yd + zd*zd ); + } + return len; + } + + float GetPassedLength(uint32 curnode, float x, float y, float z) + { + float len = 0, xd, yd, zd; + for(unsigned int idx=1; idx < curnode; ++idx) + { + xd = i_nodes[ idx ].x - i_nodes[ idx-1 ].x; + yd = i_nodes[ idx ].y - i_nodes[ idx-1 ].y; + zd = i_nodes[ idx ].z - i_nodes[ idx-1 ].z; + len += sqrtf( xd*xd + yd*yd + zd*zd ); + } + + if(curnode > 0) + { + xd = x - i_nodes[curnode-1].x; + yd = y - i_nodes[curnode-1].y; + zd = z - i_nodes[curnode-1].z; + len += sqrtf( xd*xd + yd*yd + zd*zd ); + } + + return len; + } + + PathNode& operator[](const unsigned int idx) { return i_nodes[idx]; } + const PathNode& operator()(const unsigned int idx) const { return i_nodes[idx]; } + + protected: + std::vector i_nodes; +}; +#endif diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp new file mode 100644 index 00000000000..c80bbc8f673 --- /dev/null +++ b/src/game/Pet.cpp @@ -0,0 +1,1750 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "Log.h" +#include "WorldSession.h" +#include "WorldPacket.h" +#include "ObjectMgr.h" +#include "SpellMgr.h" +#include "Pet.h" +#include "MapManager.h" +#include "Formulas.h" +#include "SpellAuras.h" +#include "CreatureAI.h" +#include "Unit.h" +#include "Util.h" + +char const* petTypeSuffix[MAX_PET_TYPE] = +{ + "'s Minion", // SUMMON_PET + "'s Pet", // HUNTER_PET + "'s Guardian", // GUARDIAN_PET + "'s Companion" // MINI_PET +}; + +//numbers represent minutes * 100 while happy (you get 100 loyalty points per min while happy) +uint32 const LevelUpLoyalty[6] = +{ + 5500, + 11500, + 17000, + 23500, + 31000, + 39500, +}; + +uint32 const LevelStartLoyalty[6] = +{ + 2000, + 4500, + 7000, + 10000, + 13500, + 17500, +}; + +Pet::Pet(PetType type) : Creature() +{ + m_isPet = true; + m_name = "Pet"; + m_petType = type; + + m_removed = false; + m_regenTimer = 4000; + m_happinessTimer = 7500; + m_loyaltyTimer = 12000; + m_duration = 0; + m_bonusdamage = 0; + + m_loyaltyPoints = 0; + m_TrainingPoints = 0; + m_resetTalentsCost = 0; + m_resetTalentsTime = 0; + + m_auraUpdateMask = 0; + + // pets always have a charminfo, even if they are not actually charmed + CharmInfo* charmInfo = InitCharmInfo(this); + + if(type == MINI_PET) // always passive + charmInfo->SetReactState(REACT_PASSIVE); + else if(type == GUARDIAN_PET) // always aggressive + charmInfo->SetReactState(REACT_AGGRESSIVE); + + m_spells.clear(); + m_Auras.clear(); + m_CreatureSpellCooldowns.clear(); + m_CreatureCategoryCooldowns.clear(); + m_autospells.clear(); + m_declinedname = NULL; +} + +Pet::~Pet() +{ + if(m_uint32Values) // only for fully created Object + { + for (PetSpellMap::iterator i = m_spells.begin(); i != m_spells.end(); ++i) + delete i->second; + ObjectAccessor::Instance().RemoveObject(this); + } + + delete m_declinedname; +} + +void Pet::AddToWorld() +{ + ///- Register the pet for guid lookup + if(!IsInWorld()) ObjectAccessor::Instance().AddObject(this); + Unit::AddToWorld(); +} + +void Pet::RemoveFromWorld() +{ + ///- Remove the pet from the accessor + if(IsInWorld()) ObjectAccessor::Instance().RemoveObject(this); + ///- Don't call the function for Creature, normal mobs + totems go in a different storage + Unit::RemoveFromWorld(); +} + +bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool current ) +{ + uint32 ownerid = owner->GetGUIDLow(); + + QueryResult *result; + + if(petnumber) + // known petnumber entry 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 + result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND id = '%u'",ownerid, petnumber); + else if(current) + // current pet (slot 0) 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 + result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND slot = '0'",ownerid ); + else if(petentry) + // known petentry entry (unique for summoned pet, but non unique for hunter pet (only from current or not stabled pets) + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 + result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND entry = '%u' AND (slot = '0' OR slot = '3') ",ownerid, petentry ); + else + // any current or other non-stabled pet (for hunter "call pet") + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 + result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND (slot = '0' OR slot = '3') ",ownerid); + + if(!result) + return false; + + Field *fields = result->Fetch(); + + // update for case of current pet "slot = 0" + petentry = fields[1].GetUInt32(); + if(!petentry) + { + delete result; + return false; + } + + uint32 summon_spell_id = fields[21].GetUInt32(); + SpellEntry const* spellInfo = sSpellStore.LookupEntry(summon_spell_id); + + bool is_temporary_summoned = spellInfo && GetSpellDuration(spellInfo) > 0; + + // check temporary summoned pets like mage water elemental + if(current && is_temporary_summoned) + { + delete result; + return false; + } + + Map *map = owner->GetMap(); + uint32 guid=objmgr.GenerateLowGuid(HIGHGUID_PET); + uint32 pet_number = fields[0].GetUInt32(); + if(!Create(guid, map, petentry, pet_number)) + { + delete result; + return false; + } + + float px, py, pz; + owner->GetClosePoint(px, py, pz,GetObjectSize(),PET_FOLLOW_DIST,PET_FOLLOW_ANGLE); + + Relocate(px, py, pz, owner->GetOrientation()); + + if(!IsPositionValid()) + { + sLog.outError("ERROR: Pet (guidlow %d, entry %d) not loaded. Suggested coordinates isn't valid (X: %d Y: ^%d)", GetGUIDLow(), GetEntry(), GetPositionX(), GetPositionY()); + delete result; + return false; + } + + setPetType(PetType(fields[22].GetUInt8())); + SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,owner->getFaction()); + SetUInt32Value(UNIT_CREATED_BY_SPELL, summon_spell_id); + + CreatureInfo const *cinfo = GetCreatureInfo(); + if(cinfo->type == CREATURE_TYPE_CRITTER) + { + AIM_Initialize(); + map->Add((Creature*)this); + delete result; + return true; + } + if(getPetType()==HUNTER_PET || getPetType()==SUMMON_PET && cinfo->type == CREATURE_TYPE_DEMON && owner->getClass() == CLASS_WARLOCK) + m_charmInfo->SetPetNumber(pet_number, true); + else + m_charmInfo->SetPetNumber(pet_number, false); + SetUInt64Value(UNIT_FIELD_SUMMONEDBY, owner->GetGUID()); + SetDisplayId(fields[3].GetUInt32()); + SetNativeDisplayId(fields[3].GetUInt32()); + uint32 petlevel=fields[4].GetUInt32(); + SetUInt32Value(UNIT_NPC_FLAGS , 0); + SetName(fields[11].GetString()); + + switch(getPetType()) + { + + case SUMMON_PET: + petlevel=owner->getLevel(); + + SetUInt32Value(UNIT_FIELD_BYTES_0,2048); + SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); + // this enables popup window (pet dismiss, cancel) + break; + case HUNTER_PET: + SetUInt32Value(UNIT_FIELD_BYTES_0, 0x02020100); + SetByteValue(UNIT_FIELD_BYTES_1, 1, fields[8].GetUInt32()); + SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE ); + SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_UNK3 | UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5 ); + + if(fields[12].GetBool()) + SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_NOT_ALLOWED); + else + SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_ALLOWED); + + SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); + // this enables popup window (pet abandon, cancel) + SetTP(fields[9].GetInt32()); + SetMaxPower(POWER_HAPPINESS,GetCreatePowers(POWER_HAPPINESS)); + SetPower( POWER_HAPPINESS,fields[15].GetUInt32()); + setPowerType(POWER_FOCUS); + break; + default: + sLog.outError("Pet have incorrect type (%u) for pet loading.",getPetType()); + } + InitStatsForLevel( petlevel); + SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL)); + SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, fields[5].GetUInt32()); + SetUInt64Value(UNIT_FIELD_CREATEDBY, owner->GetGUID()); + + m_charmInfo->SetReactState( ReactStates( fields[6].GetUInt8() )); + m_loyaltyPoints = fields[7].GetInt32(); + + uint32 savedhealth = fields[13].GetUInt32(); + uint32 savedmana = fields[14].GetUInt32(); + + // set current pet as current + if(fields[10].GetUInt32() != 0) + { + CharacterDatabase.BeginTransaction(); + CharacterDatabase.PExecute("UPDATE character_pet SET slot = '3' WHERE owner = '%u' AND slot = '0' AND id <> '%u'",ownerid, m_charmInfo->GetPetNumber()); + CharacterDatabase.PExecute("UPDATE character_pet SET slot = '0' WHERE owner = '%u' AND id = '%u'",ownerid, m_charmInfo->GetPetNumber()); + CharacterDatabase.CommitTransaction(); + } + + if(!is_temporary_summoned) + { + // permanent controlled pets store state in DB + Tokens tokens = StrSplit(fields[16].GetString(), " "); + + if(tokens.size() != 20) + { + delete result; + return false; + } + + int index; + Tokens::iterator iter; + for(iter = tokens.begin(), index = 0; index < 10; ++iter, ++index ) + { + m_charmInfo->GetActionBarEntry(index)->Type = atol((*iter).c_str()); + ++iter; + m_charmInfo->GetActionBarEntry(index)->SpellOrAction = atol((*iter).c_str()); + } + + //init teach spells + tokens = StrSplit(fields[17].GetString(), " "); + for (iter = tokens.begin(), index = 0; index < 4; ++iter, ++index) + { + uint32 tmp = atol((*iter).c_str()); + + ++iter; + + if(tmp) + AddTeachSpell(tmp, atol((*iter).c_str())); + else + break; + } + } + + // since last save (in seconds) + uint32 timediff = (time(NULL) - fields[18].GetUInt32()); + + delete result; + + //load spells/cooldowns/auras + SetCanModifyStats(true); + _LoadAuras(timediff); + + //init AB + if(is_temporary_summoned) + { + // Temporary summoned pets always have initial spell list at load + InitPetCreateSpells(); + } + else + { + LearnPetPassives(); + CastPetAuras(current); + } + + if(getPetType() == SUMMON_PET && !current) //all (?) summon pets come with full health when called, but not when they are current + { + SetHealth(GetMaxHealth()); + SetPower(POWER_MANA, GetMaxPower(POWER_MANA)); + } + else + { + SetHealth(savedhealth > GetMaxHealth() ? GetMaxHealth() : savedhealth); + SetPower(POWER_MANA, savedmana > GetMaxPower(POWER_MANA) ? GetMaxPower(POWER_MANA) : savedmana); + } + + AIM_Initialize(); + map->Add((Creature*)this); + + // Spells should be loaded after pet is added to map, because in CanCast is check on it + _LoadSpells(); + _LoadSpellCooldowns(); + + owner->SetPet(this); // in DB stored only full controlled creature + sLog.outDebug("New Pet has guid %u", GetGUIDLow()); + + if(owner->GetTypeId() == TYPEID_PLAYER) + { + ((Player*)owner)->PetSpellInitialize(); + if(((Player*)owner)->GetGroup()) + ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_PET); + } + + if(owner->GetTypeId() == TYPEID_PLAYER && getPetType() == HUNTER_PET) + { + result = CharacterDatabase.PQuery("SELECT genitive, dative, accusative, instrumental, prepositional FROM character_pet_declinedname WHERE owner = '%u' AND id = '%u'",owner->GetGUIDLow(),GetCharmInfo()->GetPetNumber()); + + if(result) + { + if(m_declinedname) + delete m_declinedname; + + m_declinedname = new DeclinedName; + Field *fields = result->Fetch(); + for(int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) + { + m_declinedname->name[i] = fields[i].GetCppString(); + } + } + } + + return true; +} + +void Pet::SavePetToDB(PetSaveMode mode) +{ + if(!GetEntry()) + return; + + // save only fully controlled creature + if(!isControlled()) + return; + + uint32 curhealth = GetHealth(); + uint32 curmana = GetPower(POWER_MANA); + + switch(mode) + { + case PET_SAVE_IN_STABLE_SLOT_1: + case PET_SAVE_IN_STABLE_SLOT_2: + case PET_SAVE_NOT_IN_SLOT: + { + RemoveAllAuras(); + + //only alive hunter pets get auras saved, the others don't + if(!(getPetType() == HUNTER_PET && isAlive())) + m_Auras.clear(); + } + default: + break; + } + + _SaveSpells(); + _SaveSpellCooldowns(); + _SaveAuras(); + + switch(mode) + { + case PET_SAVE_AS_CURRENT: + case PET_SAVE_IN_STABLE_SLOT_1: + case PET_SAVE_IN_STABLE_SLOT_2: + case PET_SAVE_NOT_IN_SLOT: + { + uint32 loyalty =1; + if(getPetType()!=HUNTER_PET) + loyalty = GetLoyaltyLevel(); + + uint32 owner = GUID_LOPART(GetOwnerGUID()); + std::string name = m_name; + CharacterDatabase.escape_string(name); + CharacterDatabase.BeginTransaction(); + // remove current data + CharacterDatabase.PExecute("DELETE FROM character_pet WHERE owner = '%u' AND id = '%u'", owner,m_charmInfo->GetPetNumber() ); + + // prevent duplicate using slot (except PET_SAVE_NOT_IN_SLOT) + if(mode!=PET_SAVE_NOT_IN_SLOT) + CharacterDatabase.PExecute("UPDATE character_pet SET slot = 3 WHERE owner = '%u' AND slot = '%u'", owner, uint32(mode) ); + + // prevent existence another hunter pet in PET_SAVE_AS_CURRENT and PET_SAVE_NOT_IN_SLOT + if(getPetType()==HUNTER_PET && (mode==PET_SAVE_AS_CURRENT||mode==PET_SAVE_NOT_IN_SLOT)) + CharacterDatabase.PExecute("DELETE FROM character_pet WHERE owner = '%u' AND (slot = '0' OR slot = '3')", owner ); + // save pet + std::ostringstream ss; + ss << "INSERT INTO character_pet ( id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata,TeachSpelldata,savetime,resettalents_cost,resettalents_time,CreatedBySpell,PetType) " + << "VALUES (" + << m_charmInfo->GetPetNumber() << ", " + << GetEntry() << ", " + << owner << ", " + << GetNativeDisplayId() << ", " + << getLevel() << ", " + << GetUInt32Value(UNIT_FIELD_PETEXPERIENCE) << ", " + << uint32(m_charmInfo->GetReactState()) << ", " + << m_loyaltyPoints << ", " + << GetLoyaltyLevel() << ", " + << m_TrainingPoints << ", " + << uint32(mode) << ", '" + << name.c_str() << "', " + << uint32((GetByteValue(UNIT_FIELD_BYTES_2, 2) == UNIT_RENAME_ALLOWED)?0:1) << ", " + << (curhealth<1?1:curhealth) << ", " + << curmana << ", " + << GetPower(POWER_HAPPINESS) << ", '"; + + for(uint32 i = 0; i < 10; i++) + ss << uint32(m_charmInfo->GetActionBarEntry(i)->Type) << " " << uint32(m_charmInfo->GetActionBarEntry(i)->SpellOrAction) << " "; + ss << "', '"; + + //save spells the pet can teach to it's Master + { + int i = 0; + for(TeachSpellMap::iterator itr = m_teachspells.begin(); i < 4 && itr != m_teachspells.end(); ++i, ++itr) + ss << itr->first << " " << itr->second << " "; + for(; i < 4; ++i) + ss << uint32(0) << " " << uint32(0) << " "; + } + + ss << "', " + << time(NULL) << ", " + << uint32(m_resetTalentsCost) << ", " + << uint64(m_resetTalentsTime) << ", " + << GetUInt32Value(UNIT_CREATED_BY_SPELL) << ", " + << uint32(getPetType()) << ")"; + + CharacterDatabase.Execute( ss.str().c_str() ); + + CharacterDatabase.CommitTransaction(); + break; + } + case PET_SAVE_AS_DELETED: + { + RemoveAllAuras(); + uint32 owner = GUID_LOPART(GetOwnerGUID()); + DeleteFromDB(m_charmInfo->GetPetNumber()); + break; + } + default: + sLog.outError("Unknown pet save/remove mode: %d",mode); + } +} + +void Pet::DeleteFromDB(uint32 guidlow) +{ + CharacterDatabase.PExecute("DELETE FROM character_pet WHERE id = '%u'", guidlow); + CharacterDatabase.PExecute("DELETE FROM character_pet_declinedname WHERE id = '%u'", guidlow); + CharacterDatabase.PExecute("DELETE FROM pet_aura WHERE guid = '%u'", guidlow); + CharacterDatabase.PExecute("DELETE FROM pet_spell WHERE guid = '%u'", guidlow); + CharacterDatabase.PExecute("DELETE FROM pet_spell_cooldown WHERE guid = '%u'", guidlow); +} + +void Pet::setDeathState(DeathState s) // overwrite virtual Creature::setDeathState and Unit::setDeathState +{ + Creature::setDeathState(s); + if(getDeathState()==CORPSE) + { + //remove summoned pet (no corpse) + if(getPetType()==SUMMON_PET) + Remove(PET_SAVE_NOT_IN_SLOT); + // other will despawn at corpse desppawning (Pet::Update code) + else + { + // pet corpse non lootable and non skinnable + SetUInt32Value( UNIT_DYNAMIC_FLAGS, 0x00 ); + RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); + + //lose happiness when died and not in BG/Arena + MapEntry const* mapEntry = sMapStore.LookupEntry(GetMapId()); + if(!mapEntry || (mapEntry->map_type != MAP_ARENA && mapEntry->map_type != MAP_BATTLEGROUND)) + ModifyPower(POWER_HAPPINESS, -HAPPINESS_LEVEL_SIZE); + + SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE); + } + } + else if(getDeathState()==ALIVE) + { + RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE); + CastPetAuras(true); + } +} + +void Pet::Update(uint32 diff) +{ + if(m_removed) // pet already removed, just wait in remove queue, no updates + return; + + switch( m_deathState ) + { + case CORPSE: + { + if( m_deathTimer <= diff ) + { + assert(getPetType()!=SUMMON_PET && "Must be already removed."); + Remove(PET_SAVE_NOT_IN_SLOT); //hunters' pets never get removed because of death, NEVER! + return; + } + break; + } + case ALIVE: + { + // unsummon pet that lost owner + Unit* owner = GetOwner(); + if(!owner || !IsWithinDistInMap(owner, OWNER_MAX_DISTANCE) || isControlled() && !owner->GetPetGUID()) + { + Remove(PET_SAVE_NOT_IN_SLOT, true); + return; + } + + if(isControlled()) + { + if( owner->GetPetGUID() != GetGUID() ) + { + Remove(getPetType()==HUNTER_PET?PET_SAVE_AS_DELETED:PET_SAVE_NOT_IN_SLOT); + return; + } + } + + if(m_duration > 0) + { + if(m_duration > diff) + m_duration -= diff; + else + { + Remove(getPetType() != SUMMON_PET ? PET_SAVE_AS_DELETED:PET_SAVE_NOT_IN_SLOT); + return; + } + } + + if(getPetType() != HUNTER_PET) + break; + + //regenerate Focus + if(m_regenTimer <= diff) + { + RegenerateFocus(); + m_regenTimer = 4000; + } + else + m_regenTimer -= diff; + + if(m_happinessTimer <= diff) + { + LooseHappiness(); + m_happinessTimer = 7500; + } + else + m_happinessTimer -= diff; + + if(m_loyaltyTimer <= diff) + { + TickLoyaltyChange(); + m_loyaltyTimer = 12000; + } + else + m_loyaltyTimer -= diff; + + break; + } + default: + break; + } + Creature::Update(diff); +} + +void Pet::RegenerateFocus() +{ + uint32 curValue = GetPower(POWER_FOCUS); + uint32 maxValue = GetMaxPower(POWER_FOCUS); + + if (curValue >= maxValue) + return; + + float addvalue = 24 * sWorld.getRate(RATE_POWER_FOCUS); + + AuraList const& ModPowerRegenPCTAuras = GetAurasByType(SPELL_AURA_MOD_POWER_REGEN_PERCENT); + for(AuraList::const_iterator i = ModPowerRegenPCTAuras.begin(); i != ModPowerRegenPCTAuras.end(); ++i) + if ((*i)->GetModifier()->m_miscvalue == POWER_FOCUS) + addvalue *= ((*i)->GetModifier()->m_amount + 100) / 100.0f; + + ModifyPower(POWER_FOCUS, (int32)addvalue); +} + +void Pet::LooseHappiness() +{ + uint32 curValue = GetPower(POWER_HAPPINESS); + if (curValue <= 0) + return; + int32 addvalue = (140 >> GetLoyaltyLevel()) * 125; //value is 70/35/17/8/4 (per min) * 1000 / 8 (timer 7.5 secs) + if(isInCombat()) //we know in combat happiness fades faster, multiplier guess + addvalue = int32(addvalue * 1.5); + ModifyPower(POWER_HAPPINESS, -addvalue); +} + +void Pet::ModifyLoyalty(int32 addvalue) +{ + uint32 loyaltylevel = GetLoyaltyLevel(); + + if(addvalue > 0) //only gain influenced, not loss + addvalue = int32((float)addvalue * sWorld.getRate(RATE_LOYALTY)); + + if(loyaltylevel >= BEST_FRIEND && (addvalue + m_loyaltyPoints) > int32(GetMaxLoyaltyPoints(loyaltylevel))) + return; + + m_loyaltyPoints += addvalue; + + if(m_loyaltyPoints < 0) + { + if(loyaltylevel > REBELLIOUS) + { + //level down + --loyaltylevel; + SetLoyaltyLevel(LoyaltyLevel(loyaltylevel)); + m_loyaltyPoints = GetStartLoyaltyPoints(loyaltylevel); + SetTP(m_TrainingPoints - int32(getLevel())); + } + else + { + m_loyaltyPoints = 0; + Unit* owner = GetOwner(); + if(owner && owner->GetTypeId() == TYPEID_PLAYER) + { + WorldPacket data(SMSG_PET_BROKEN, 0); + ((Player*)owner)->GetSession()->SendPacket(&data); + + //run away + ((Player*)owner)->RemovePet(this,PET_SAVE_AS_DELETED); + } + } + } + //level up + else if(m_loyaltyPoints > int32(GetMaxLoyaltyPoints(loyaltylevel))) + { + ++loyaltylevel; + SetLoyaltyLevel(LoyaltyLevel(loyaltylevel)); + m_loyaltyPoints = GetStartLoyaltyPoints(loyaltylevel); + SetTP(m_TrainingPoints + getLevel()); + } +} + +void Pet::TickLoyaltyChange() +{ + int32 addvalue; + + switch(GetHappinessState()) + { + case HAPPY: addvalue = 20; break; + case CONTENT: addvalue = 10; break; + case UNHAPPY: addvalue = -20; break; + default: + return; + } + ModifyLoyalty(addvalue); +} + +void Pet::KillLoyaltyBonus(uint32 level) +{ + if(level > 100) + return; + + //at lower levels gain is faster | the lower loyalty the more loyalty is gained + uint32 bonus = uint32(((100 - level) / 10) + (6 - GetLoyaltyLevel())); + ModifyLoyalty(bonus); +} + +HappinessState Pet::GetHappinessState() +{ + if(GetPower(POWER_HAPPINESS) < HAPPINESS_LEVEL_SIZE) + return UNHAPPY; + else if(GetPower(POWER_HAPPINESS) >= HAPPINESS_LEVEL_SIZE * 2) + return HAPPY; + else + return CONTENT; +} + +void Pet::SetLoyaltyLevel(LoyaltyLevel level) +{ + SetByteValue(UNIT_FIELD_BYTES_1, 1, level); +} + +bool Pet::CanTakeMoreActiveSpells(uint32 spellid) +{ + uint8 activecount = 1; + uint32 chainstartstore[ACTIVE_SPELLS_MAX]; + + if(IsPassiveSpell(spellid)) + return true; + + chainstartstore[0] = spellmgr.GetFirstSpellInChain(spellid); + + for (PetSpellMap::iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr) + { + if(IsPassiveSpell(itr->first)) + continue; + + uint32 chainstart = spellmgr.GetFirstSpellInChain(itr->first); + + uint8 x; + + for(x = 0; x < activecount; x++) + { + if(chainstart == chainstartstore[x]) + break; + } + + if(x == activecount) //spellchain not yet saved -> add active count + { + ++activecount; + if(activecount > ACTIVE_SPELLS_MAX) + return false; + chainstartstore[x] = chainstart; + } + } + return true; +} + +bool Pet::HasTPForSpell(uint32 spellid) +{ + int32 neededtrainp = GetTPForSpell(spellid); + if((m_TrainingPoints - neededtrainp < 0 || neededtrainp < 0) && neededtrainp != 0) + return false; + return true; +} + +int32 Pet::GetTPForSpell(uint32 spellid) +{ + uint32 basetrainp = 0; + + SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(spellid); + SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(spellid); + for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx) + { + if(!_spell_idx->second->reqtrainpoints) + return 0; + + basetrainp = _spell_idx->second->reqtrainpoints; + break; + } + + uint32 spenttrainp = 0; + uint32 chainstart = spellmgr.GetFirstSpellInChain(spellid); + + for (PetSpellMap::iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr) + { + if(itr->second->state == PETSPELL_REMOVED) + continue; + + if(spellmgr.GetFirstSpellInChain(itr->first) == chainstart) + { + SkillLineAbilityMap::const_iterator _lower = spellmgr.GetBeginSkillLineAbilityMap(itr->first); + SkillLineAbilityMap::const_iterator _upper = spellmgr.GetEndSkillLineAbilityMap(itr->first); + + for(SkillLineAbilityMap::const_iterator _spell_idx2 = _lower; _spell_idx2 != _upper; ++_spell_idx2) + { + if(_spell_idx2->second->reqtrainpoints > spenttrainp) + { + spenttrainp = _spell_idx2->second->reqtrainpoints; + break; + } + } + } + } + + return int32(basetrainp) - int32(spenttrainp); +} + +uint32 Pet::GetMaxLoyaltyPoints(uint32 level) +{ + return LevelUpLoyalty[level - 1]; +} + +uint32 Pet::GetStartLoyaltyPoints(uint32 level) +{ + return LevelStartLoyalty[level - 1]; +} + +void Pet::SetTP(int32 TP) +{ + m_TrainingPoints = TP; + SetUInt32Value(UNIT_TRAINING_POINTS, (uint32)GetDispTP()); +} + +int32 Pet::GetDispTP() +{ + if(getPetType()!= HUNTER_PET) + return(0); + if(m_TrainingPoints < 0) + return -m_TrainingPoints; + else + return -(m_TrainingPoints + 1); +} + +void Pet::Remove(PetSaveMode mode, bool returnreagent) +{ + Unit* owner = GetOwner(); + + if(owner) + { + if(owner->GetTypeId()==TYPEID_PLAYER) + { + ((Player*)owner)->RemovePet(this,mode,returnreagent); + return; + } + + // only if current pet in slot + if(owner->GetPetGUID()==GetGUID()) + owner->SetPet(0); + } + + CleanupsBeforeDelete(); + AddObjectToRemoveList(); + m_removed = true; +} + +void Pet::GivePetXP(uint32 xp) +{ + if(getPetType() != HUNTER_PET) + return; + + if ( xp < 1 ) + return; + + if(!isAlive()) + return; + + uint32 level = getLevel(); + + // XP to money conversion processed in Player::RewardQuest + if(level >= sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + return; + + uint32 curXP = GetUInt32Value(UNIT_FIELD_PETEXPERIENCE); + uint32 nextLvlXP = GetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP); + uint32 newXP = curXP + xp; + + if(newXP >= nextLvlXP && level+1 > GetOwner()->getLevel()) + { + SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, nextLvlXP-1); + return; + } + + while( newXP >= nextLvlXP && level < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) ) + { + newXP -= nextLvlXP; + + SetLevel( level + 1 ); + SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, uint32((MaNGOS::XP::xp_to_level(level+1))/4)); + + level = getLevel(); + nextLvlXP = GetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP); + GivePetLevel(level); + } + + SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, newXP); + + if(getPetType() == HUNTER_PET) + KillLoyaltyBonus(level); +} + +void Pet::GivePetLevel(uint32 level) +{ + if(!level) + return; + + InitStatsForLevel( level); + + SetTP(m_TrainingPoints + (GetLoyaltyLevel() - 1)); +} + +bool Pet::CreateBaseAtCreature(Creature* creature) +{ + if(!creature) + { + sLog.outError("CRITICAL ERROR: NULL pointer parsed into CreateBaseAtCreature()"); + return false; + } + uint32 guid=objmgr.GenerateLowGuid(HIGHGUID_PET); + + sLog.outBasic("SetInstanceID()"); + SetInstanceId(creature->GetInstanceId()); + + sLog.outBasic("Create pet"); + uint32 pet_number = objmgr.GeneratePetNumber(); + if(!Create(guid, creature->GetMap(), creature->GetEntry(), pet_number)) + return false; + + Relocate(creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ(), creature->GetOrientation()); + + if(!IsPositionValid()) + { + sLog.outError("ERROR: Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %d Y: ^%d)", GetGUIDLow(), GetEntry(), GetPositionX(), GetPositionY()); + return false; + } + + CreatureInfo const *cinfo = GetCreatureInfo(); + if(!cinfo) + { + sLog.outError("ERROR: CreateBaseAtCreature() failed, creatureInfo is missing!"); + return false; + } + + if(cinfo->type == CREATURE_TYPE_CRITTER) + { + setPetType(MINI_PET); + return true; + } + SetDisplayId(creature->GetDisplayId()); + SetNativeDisplayId(creature->GetNativeDisplayId()); + SetMaxPower(POWER_HAPPINESS,GetCreatePowers(POWER_HAPPINESS)); + SetPower( POWER_HAPPINESS,166500); + setPowerType(POWER_FOCUS); + SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0); + SetUInt32Value(UNIT_FIELD_PETEXPERIENCE,0); + SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, uint32((MaNGOS::XP::xp_to_level(creature->getLevel()))/4)); + SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); + SetUInt32Value(UNIT_NPC_FLAGS , 0); + + CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(creature->GetCreatureInfo()->family); + if( char* familyname = cFamily->Name[sWorld.GetDefaultDbcLocale()] ) + SetName(familyname); + else + SetName(creature->GetName()); + + m_loyaltyPoints = 1000; + if(cinfo->type == CREATURE_TYPE_BEAST) + { + SetUInt32Value(UNIT_FIELD_BYTES_0, 0x02020100); + SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE ); + SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_UNK3 | UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5 ); + SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_ALLOWED); + + SetUInt32Value(UNIT_MOD_CAST_SPEED, creature->GetUInt32Value(UNIT_MOD_CAST_SPEED) ); + SetLoyaltyLevel(REBELLIOUS); + } + return true; +} + +bool Pet::InitStatsForLevel(uint32 petlevel) +{ + CreatureInfo const *cinfo = GetCreatureInfo(); + assert(cinfo); + + Unit* owner = GetOwner(); + if(!owner) + { + sLog.outError("ERROR: attempt to summon pet (Entry %u) without owner! Attempt terminated.", cinfo->Entry); + return false; + } + + uint32 creature_ID = (getPetType() == HUNTER_PET) ? 1 : cinfo->Entry; + + SetLevel( petlevel); + + SetMeleeDamageSchool(SpellSchools(cinfo->dmgschool)); + + SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(petlevel*50)); + + SetAttackTime(BASE_ATTACK, BASE_ATTACK_TIME); + SetAttackTime(OFF_ATTACK, BASE_ATTACK_TIME); + SetAttackTime(RANGED_ATTACK, BASE_ATTACK_TIME); + + SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0); + + CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cinfo->family); + if(cFamily && cFamily->minScale > 0.0f) + { + float scale; + if (getLevel() >= cFamily->maxScaleLevel) + scale = cFamily->maxScale; + else if (getLevel() <= cFamily->minScaleLevel) + scale = cFamily->minScale; + else + scale = cFamily->minScale + (getLevel() - cFamily->minScaleLevel) / cFamily->maxScaleLevel * (cFamily->maxScale - cFamily->minScale); + + SetFloatValue(OBJECT_FIELD_SCALE_X, scale); + } + m_bonusdamage = 0; + + int32 createResistance[MAX_SPELL_SCHOOL] = {0,0,0,0,0,0,0}; + + if(cinfo && getPetType() != HUNTER_PET) + { + createResistance[SPELL_SCHOOL_HOLY] = cinfo->resistance1; + createResistance[SPELL_SCHOOL_FIRE] = cinfo->resistance2; + createResistance[SPELL_SCHOOL_NATURE] = cinfo->resistance3; + createResistance[SPELL_SCHOOL_FROST] = cinfo->resistance4; + createResistance[SPELL_SCHOOL_SHADOW] = cinfo->resistance5; + createResistance[SPELL_SCHOOL_ARCANE] = cinfo->resistance6; + } + + switch(getPetType()) + { + case SUMMON_PET: + { + if(owner->GetTypeId() == TYPEID_PLAYER) + { + switch(owner->getClass()) + { + case CLASS_WARLOCK: + { + + //the damage bonus used for pets is either fire or shadow damage, whatever is higher + uint32 fire = owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FIRE); + uint32 shadow = owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_SHADOW); + uint32 val = (fire > shadow) ? fire : shadow; + + SetBonusDamage(int32 (val * 0.15f)); + //bonusAP += val * 0.57; + break; + } + case CLASS_MAGE: + { + //40% damage bonus of mage's frost damage + float val = owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FROST) * 0.4; + if(val < 0) + val = 0; + SetBonusDamage( int32(val)); + break; + } + default: + break; + } + } + + SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)) ); + SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4)) ); + + //SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, float(cinfo->attackpower)); + + PetLevelInfo const* pInfo = objmgr.GetPetLevelInfo(creature_ID, petlevel); + if(pInfo) // exist in DB + { + SetCreateHealth(pInfo->health); + SetCreateMana(pInfo->mana); + + if(pInfo->armor > 0) + SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(pInfo->armor)); + + for(int stat = 0; stat < MAX_STATS; ++stat) + { + SetCreateStat(Stats(stat),float(pInfo->stats[stat])); + } + } + else // not exist in DB, use some default fake data + { + sLog.outErrorDb("Summoned pet (Entry: %u) not have pet stats data in DB",cinfo->Entry); + + // remove elite bonuses included in DB values + SetCreateHealth(uint32(((float(cinfo->maxhealth) / cinfo->maxlevel) / (1 + 2 * cinfo->rank)) * petlevel) ); + SetCreateMana( uint32(((float(cinfo->maxmana) / cinfo->maxlevel) / (1 + 2 * cinfo->rank)) * petlevel) ); + + SetCreateStat(STAT_STRENGTH,22); + SetCreateStat(STAT_AGILITY,22); + SetCreateStat(STAT_STAMINA,25); + SetCreateStat(STAT_INTELLECT,28); + SetCreateStat(STAT_SPIRIT,27); + } + break; + } + case HUNTER_PET: + { + SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, uint32((MaNGOS::XP::xp_to_level(petlevel))/4)); + + //these formula may not be correct; however, it is designed to be close to what it should be + //this makes dps 0.5 of pets level + SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)) ); + //damage range is then petlevel / 2 + SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4)) ); + //damage is increased afterwards as strength and pet scaling modify attack power + + //stored standard pet stats are entry 1 in pet_levelinfo + PetLevelInfo const* pInfo = objmgr.GetPetLevelInfo(creature_ID, petlevel); + if(pInfo) // exist in DB + { + SetCreateHealth(pInfo->health); + SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(pInfo->armor)); + //SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, float(cinfo->attackpower)); + + for( int i = STAT_STRENGTH; i < MAX_STATS; i++) + { + SetCreateStat(Stats(i), float(pInfo->stats[i])); + } + } + else // not exist in DB, use some default fake data + { + sLog.outErrorDb("Hunter pet levelstats missing in DB"); + + // remove elite bonuses included in DB values + SetCreateHealth( uint32(((float(cinfo->maxhealth) / cinfo->maxlevel) / (1 + 2 * cinfo->rank)) * petlevel) ); + + SetCreateStat(STAT_STRENGTH,22); + SetCreateStat(STAT_AGILITY,22); + SetCreateStat(STAT_STAMINA,25); + SetCreateStat(STAT_INTELLECT,28); + SetCreateStat(STAT_SPIRIT,27); + } + break; + } + case GUARDIAN_PET: + SetUInt32Value(UNIT_FIELD_PETEXPERIENCE,0); + SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP,1000); + + SetCreateMana( 28 + 10*petlevel ); + SetCreateHealth( 28 + 30*petlevel ); + + // FIXME: this is wrong formula, possible each guardian pet have own damage formula + //these formula may not be correct; however, it is designed to be close to what it should be + //this makes dps 0.5 of pets level + SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)) ); + //damage range is then petlevel / 2 + SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4)) ); + break; + default: + sLog.outError("Pet have incorrect type (%u) for levelup.",getPetType()); break; + } + + for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i) + SetModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + i), BASE_VALUE, float(createResistance[i]) ); + + UpdateAllStats(); + + SetHealth(GetMaxHealth()); + SetPower(POWER_MANA, GetMaxPower(POWER_MANA)); + + return true; +} + +bool Pet::HaveInDiet(ItemPrototype const* item) const +{ + if (!item->FoodType) + return false; + + CreatureInfo const* cInfo = GetCreatureInfo(); + if(!cInfo) + return false; + + CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cInfo->family); + if(!cFamily) + return false; + + uint32 diet = cFamily->petFoodMask; + uint32 FoodMask = 1 << (item->FoodType-1); + return diet & FoodMask; +} + +uint32 Pet::GetCurrentFoodBenefitLevel(uint32 itemlevel) +{ + // -5 or greater food level + if(getLevel() <= itemlevel +5) //possible to feed level 60 pet with level 55 level food for full effect + return 35000; + // -10..-6 + else if(getLevel() <= itemlevel + 10) //pure guess, but sounds good + return 17000; + // -14..-11 + else if(getLevel() <= itemlevel + 14) //level 55 food gets green on 70, makes sense to me + return 8000; + // -15 or less + else + return 0; //food too low level +} + +void Pet::_LoadSpellCooldowns() +{ + m_CreatureSpellCooldowns.clear(); + m_CreatureCategoryCooldowns.clear(); + + QueryResult *result = CharacterDatabase.PQuery("SELECT spell,time FROM pet_spell_cooldown WHERE guid = '%u'",m_charmInfo->GetPetNumber()); + + if(result) + { + time_t curTime = time(NULL); + + WorldPacket data(SMSG_SPELL_COOLDOWN, (8+1+result->GetRowCount()*8)); + data << GetGUID(); + data << uint8(0x0); + + do + { + Field *fields = result->Fetch(); + + uint32 spell_id = fields[0].GetUInt32(); + time_t db_time = (time_t)fields[1].GetUInt64(); + + if(!sSpellStore.LookupEntry(spell_id)) + { + sLog.outError("Pet %u have unknown spell %u in `pet_spell_cooldown`, skipping.",m_charmInfo->GetPetNumber(),spell_id); + continue; + } + + // skip outdated cooldown + if(db_time <= curTime) + continue; + + data << uint32(spell_id); + data << uint32(uint32(db_time-curTime)*1000); // in m.secs + + _AddCreatureSpellCooldown(spell_id,db_time); + + sLog.outDebug("Pet (Number: %u) spell %u cooldown loaded (%u secs).",m_charmInfo->GetPetNumber(),spell_id,uint32(db_time-curTime)); + } + while( result->NextRow() ); + + delete result; + + if(!m_CreatureSpellCooldowns.empty() && GetOwner()) + { + ((Player*)GetOwner())->GetSession()->SendPacket(&data); + } + } +} + +void Pet::_SaveSpellCooldowns() +{ + CharacterDatabase.PExecute("DELETE FROM pet_spell_cooldown WHERE guid = '%u'", m_charmInfo->GetPetNumber()); + + time_t curTime = time(NULL); + + // remove oudated and save active + for(CreatureSpellCooldowns::iterator itr = m_CreatureSpellCooldowns.begin();itr != m_CreatureSpellCooldowns.end();) + { + if(itr->second <= curTime) + m_CreatureSpellCooldowns.erase(itr++); + else + { + CharacterDatabase.PExecute("INSERT INTO pet_spell_cooldown (guid,spell,time) VALUES ('%u', '%u', '" I64FMTD "')", m_charmInfo->GetPetNumber(), itr->first, uint64(itr->second)); + ++itr; + } + } +} + +void Pet::_LoadSpells() +{ + QueryResult *result = CharacterDatabase.PQuery("SELECT spell,slot,active FROM pet_spell WHERE guid = '%u'",m_charmInfo->GetPetNumber()); + + if(result) + { + do + { + Field *fields = result->Fetch(); + + addSpell(fields[0].GetUInt16(), fields[2].GetUInt16(), PETSPELL_UNCHANGED, fields[1].GetUInt16()); + } + while( result->NextRow() ); + + delete result; + } +} + +void Pet::_SaveSpells() +{ + for (PetSpellMap::const_iterator itr = m_spells.begin(), next = m_spells.begin(); itr != m_spells.end(); itr = next) + { + ++next; + if (itr->second->type == PETSPELL_FAMILY) continue; // prevent saving family passives to DB + if (itr->second->state == PETSPELL_REMOVED || itr->second->state == PETSPELL_CHANGED) + CharacterDatabase.PExecute("DELETE FROM pet_spell WHERE guid = '%u' and spell = '%u'", m_charmInfo->GetPetNumber(), itr->first); + if (itr->second->state == PETSPELL_NEW || itr->second->state == PETSPELL_CHANGED) + CharacterDatabase.PExecute("INSERT INTO pet_spell (guid,spell,slot,active) VALUES ('%u', '%u', '%u','%u')", m_charmInfo->GetPetNumber(), itr->first, itr->second->slotId,itr->second->active); + + if (itr->second->state == PETSPELL_REMOVED) + _removeSpell(itr->first); + else + itr->second->state = PETSPELL_UNCHANGED; + } +} + +void Pet::_LoadAuras(uint32 timediff) +{ + m_Auras.clear(); + for (int i = 0; i < TOTAL_AURAS; i++) + m_modAuras[i].clear(); + + // all aura related fields + for(int i = UNIT_FIELD_AURA; i <= UNIT_FIELD_AURASTATE; ++i) + SetUInt32Value(i, 0); + + QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,spell,effect_index,amount,maxduration,remaintime,remaincharges FROM pet_aura WHERE guid = '%u'",m_charmInfo->GetPetNumber()); + + if(result) + { + do + { + Field *fields = result->Fetch(); + uint64 caster_guid = fields[0].GetUInt64(); + uint32 spellid = fields[1].GetUInt32(); + uint32 effindex = fields[2].GetUInt32(); + int32 damage = (int32)fields[3].GetUInt32(); + int32 maxduration = (int32)fields[4].GetUInt32(); + int32 remaintime = (int32)fields[5].GetUInt32(); + int32 remaincharges = (int32)fields[6].GetUInt32(); + + SpellEntry const* spellproto = sSpellStore.LookupEntry(spellid); + if(!spellproto) + { + sLog.outError("Unknown aura (spellid %u, effindex %u), ignore.",spellid,effindex); + continue; + } + + if(effindex >= 3) + { + sLog.outError("Invalid effect index (spellid %u, effindex %u), ignore.",spellid,effindex); + continue; + } + + // negative effects should continue counting down after logout + if (remaintime != -1 && !IsPositiveEffect(spellid, effindex)) + { + if(remaintime <= int32(timediff)) + continue; + + remaintime -= timediff; + } + + // prevent wrong values of remaincharges + if(spellproto->procCharges) + { + if(remaincharges <= 0 || remaincharges > spellproto->procCharges) + remaincharges = spellproto->procCharges; + } + else + remaincharges = -1; + + Aura* aura = CreateAura(spellproto, effindex, NULL, this, NULL); + + if(!damage) + damage = aura->GetModifier()->m_amount; + aura->SetLoadedState(caster_guid,damage,maxduration,remaintime,remaincharges); + AddAura(aura); + } + while( result->NextRow() ); + + delete result; + } +} + +void Pet::_SaveAuras() +{ + CharacterDatabase.PExecute("DELETE FROM pet_aura WHERE guid = '%u'",m_charmInfo->GetPetNumber()); + + AuraMap const& auras = GetAuras(); + for(AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) + { + // skip all auras from spell that apply at cast SPELL_AURA_MOD_SHAPESHIFT or pet area auras. + SpellEntry const *spellInfo = itr->second->GetSpellProto(); + uint8 i; + for (i = 0; i < 3; i++) + if (spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_STEALTH || + spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_OWNER || + spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_PET ) + break; + + if (i == 3 && !itr->second->IsPassive()) + CharacterDatabase.PExecute("INSERT INTO pet_aura (guid,caster_guid,spell,effect_index,amount,maxduration,remaintime,remaincharges) " + "VALUES ('%u', '" I64FMTD "', '%u', '%u', '%d', '%d', '%d', '%d')", + m_charmInfo->GetPetNumber(), itr->second->GetCasterGUID(),(uint32)(*itr).second->GetId(), (uint32)(*itr).second->GetEffIndex(),(*itr).second->GetModifier()->m_amount,int((*itr).second->GetAuraMaxDuration()),int((*itr).second->GetAuraDuration()),int((*itr).second->m_procCharges)); + } +} + +bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, uint16 slot_id, PetSpellType type) +{ + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id); + if (!spellInfo) + { + // do pet spell book cleanup + if(state == PETSPELL_UNCHANGED) // spell load case + { + sLog.outError("Pet::addSpell: Non-existed in SpellStore spell #%u request, deleting for all pets in `pet_spell`.",spell_id); + CharacterDatabase.PExecute("DELETE FROM pet_spell WHERE spell = '%u'",spell_id); + } + else + sLog.outError("Pet::addSpell: Non-existed in SpellStore spell #%u request.",spell_id); + + return false; + } + + PetSpellMap::iterator itr = m_spells.find(spell_id); + if (itr != m_spells.end()) + { + if (itr->second->state == PETSPELL_REMOVED) + { + delete itr->second; + m_spells.erase(itr); + state = PETSPELL_CHANGED; + } + else if (state == PETSPELL_UNCHANGED && itr->second->state != PETSPELL_UNCHANGED) + { + // can be in case spell loading but learned at some previous spell loading + itr->second->state = PETSPELL_UNCHANGED; + return false; + } + else + return false; + } + + uint32 oldspell_id = 0; + + PetSpell *newspell = new PetSpell; + newspell->state = state; + newspell->type = type; + + if(active == ACT_DECIDE) //active was not used before, so we save it's autocast/passive state here + { + if(IsPassiveSpell(spell_id)) + newspell->active = ACT_PASSIVE; + else + newspell->active = ACT_DISABLED; + } + else + newspell->active = active; + + uint32 chainstart = spellmgr.GetFirstSpellInChain(spell_id); + + for (PetSpellMap::iterator itr = m_spells.begin(); itr != m_spells.end(); itr++) + { + if(itr->second->state == PETSPELL_REMOVED) continue; + + if(spellmgr.GetFirstSpellInChain(itr->first) == chainstart) + { + slot_id = itr->second->slotId; + newspell->active = itr->second->active; + + if(newspell->active == ACT_ENABLED) + ToggleAutocast(itr->first, false); + + oldspell_id = itr->first; + removeSpell(itr->first); + } + } + + uint16 tmpslot=slot_id; + + if (tmpslot == 0xffff) + { + uint16 maxid = 0; + PetSpellMap::iterator itr; + for (itr = m_spells.begin(); itr != m_spells.end(); ++itr) + { + if(itr->second->state == PETSPELL_REMOVED) continue; + if (itr->second->slotId > maxid) maxid = itr->second->slotId; + } + tmpslot = maxid + 1; + } + + newspell->slotId = tmpslot; + m_spells[spell_id] = newspell; + + if (IsPassiveSpell(spell_id)) + CastSpell(this, spell_id, true); + else if(state == PETSPELL_NEW) + m_charmInfo->AddSpellToAB(oldspell_id, spell_id); + + if(newspell->active == ACT_ENABLED) + ToggleAutocast(spell_id, true); + + return true; +} + +bool Pet::learnSpell(uint16 spell_id) +{ + // prevent duplicated entires in spell book + if (!addSpell(spell_id)) + return false; + + Unit* owner = GetOwner(); + if(owner->GetTypeId()==TYPEID_PLAYER) + ((Player*)owner)->PetSpellInitialize(); + return true; +} + +void Pet::removeSpell(uint16 spell_id) +{ + PetSpellMap::iterator itr = m_spells.find(spell_id); + if (itr == m_spells.end()) + return; + + if(itr->second->state == PETSPELL_REMOVED) + return; + + if(itr->second->state == PETSPELL_NEW) + { + delete itr->second; + m_spells.erase(itr); + } + else + itr->second->state = PETSPELL_REMOVED; + + RemoveAurasDueToSpell(spell_id); +} + +bool Pet::_removeSpell(uint16 spell_id) +{ + PetSpellMap::iterator itr = m_spells.find(spell_id); + if (itr != m_spells.end()) + { + delete itr->second; + m_spells.erase(itr); + return true; + } + return false; +} + +void Pet::InitPetCreateSpells() +{ + m_charmInfo->InitPetActionBar(); + + m_spells.clear(); + int32 usedtrainpoints = 0, petspellid; + PetCreateSpellEntry const* CreateSpells = objmgr.GetPetCreateSpellEntry(GetEntry()); + if(CreateSpells) + { + for(uint8 i = 0; i < 4; i++) + { + if(!CreateSpells->spellid[i]) + break; + + SpellEntry const *learn_spellproto = sSpellStore.LookupEntry(CreateSpells->spellid[i]); + if(!learn_spellproto) + continue; + + if(learn_spellproto->Effect[0] == SPELL_EFFECT_LEARN_SPELL || learn_spellproto->Effect[0] == SPELL_EFFECT_LEARN_PET_SPELL) + { + petspellid = learn_spellproto->EffectTriggerSpell[0]; + Unit* owner = GetOwner(); + if(owner->GetTypeId() == TYPEID_PLAYER && !((Player*)owner)->HasSpell(learn_spellproto->Id)) + { + if(IsPassiveSpell(petspellid)) //learn passive skills when tamed, not sure if thats right + ((Player*)owner)->learnSpell(learn_spellproto->Id); + else + AddTeachSpell(learn_spellproto->EffectTriggerSpell[0], learn_spellproto->Id); + } + } + else + petspellid = learn_spellproto->Id; + + addSpell(petspellid); + + SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(learn_spellproto->EffectTriggerSpell[0]); + SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(learn_spellproto->EffectTriggerSpell[0]); + + for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx) + { + usedtrainpoints += _spell_idx->second->reqtrainpoints; + break; + } + } + } + + LearnPetPassives(); + + CastPetAuras(false); + + SetTP(-usedtrainpoints); +} + +void Pet::CheckLearning(uint32 spellid) +{ + //charmed case -> prevent crash + if(GetTypeId() == TYPEID_PLAYER || getPetType() != HUNTER_PET) + return; + + Unit* owner = GetOwner(); + + if(m_teachspells.empty() || !owner || owner->GetTypeId() != TYPEID_PLAYER) + return; + + TeachSpellMap::iterator itr = m_teachspells.find(spellid); + if(itr == m_teachspells.end()) + return; + + if(urand(0, 100) < 10) + { + ((Player*)owner)->learnSpell(itr->second); + m_teachspells.erase(itr); + } +} + +uint32 Pet::resetTalentsCost() const +{ + uint32 days = (sWorld.GetGameTime() - m_resetTalentsTime)/DAY; + + // The first time reset costs 10 silver; after 1 day cost is reset to 10 silver + if(m_resetTalentsCost < 10*SILVER || days > 0) + return 10*SILVER; + // then 50 silver + else if(m_resetTalentsCost < 50*SILVER) + return 50*SILVER; + // then 1 gold + else if(m_resetTalentsCost < 1*GOLD) + return 1*GOLD; + // then increasing at a rate of 1 gold; cap 10 gold + else + return (m_resetTalentsCost + 1*GOLD > 10*GOLD ? 10*GOLD : m_resetTalentsCost + 1*GOLD); +} + +void Pet::ToggleAutocast(uint32 spellid, bool apply) +{ + if(IsPassiveSpell(spellid)) + return; + + PetSpellMap::const_iterator itr = m_spells.find((uint16)spellid); + + int i; + + if(apply) + { + for (i = 0; i < m_autospells.size() && m_autospells[i] != spellid; i++); + if (i == m_autospells.size()) + { + m_autospells.push_back(spellid); + itr->second->active = ACT_ENABLED; + itr->second->state = PETSPELL_CHANGED; + } + } + else + { + AutoSpellList::iterator itr2 = m_autospells.begin(); + for (i = 0; i < m_autospells.size() && m_autospells[i] != spellid; i++, itr2++); + if (i < m_autospells.size()) + { + m_autospells.erase(itr2); + itr->second->active = ACT_DISABLED; + itr->second->state = PETSPELL_CHANGED; + } + } +} + +bool Pet::Create(uint32 guidlow, Map *map, uint32 Entry, uint32 pet_number) +{ + SetMapId(map->GetId()); + SetInstanceId(map->GetInstanceId()); + + Object::_Create(guidlow, pet_number, HIGHGUID_PET); + + m_DBTableGuid = guidlow; + m_originalEntry = Entry; + + if(!InitEntry(Entry)) + return false; + + SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE ); + SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_UNK3 | UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5 ); + + if(getPetType() == MINI_PET) // always non-attackable + SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + return true; +} + +bool Pet::HasSpell(uint32 spell) const +{ + return (m_spells.find(spell) != m_spells.end()); +} + +// Get all passive spells in our skill line +void Pet::LearnPetPassives() +{ + CreatureInfo const* cInfo = GetCreatureInfo(); + if(!cInfo) + return; + + CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cInfo->family); + if(!cFamily) + return; + + PetFamilySpellsStore::const_iterator petStore = sPetFamilySpellsStore.find(cFamily->ID); + if(petStore != sPetFamilySpellsStore.end()) + { + for(PetFamilySpellsSet::const_iterator petSet = petStore->second.begin(); petSet != petStore->second.end(); ++petSet) + addSpell(*petSet, ACT_DECIDE, PETSPELL_NEW, 0xffff, PETSPELL_FAMILY); + } +} + +void Pet::CastPetAuras(bool current) +{ + Unit* owner = GetOwner(); + if(!owner) + return; + + if(getPetType() != HUNTER_PET && (getPetType() != SUMMON_PET || owner->getClass() != CLASS_WARLOCK)) + return; + + for(PetAuraSet::iterator itr = owner->m_petAuras.begin(); itr != owner->m_petAuras.end(); ) + { + PetAura const* pa = *itr; + ++itr; + + if(!current && pa->IsRemovedOnChangePet()) + owner->RemovePetAura(pa); + else + CastPetAura(pa); + } +} + +void Pet::CastPetAura(PetAura const* aura) +{ + uint16 auraId = aura->GetAura(GetEntry()); + if(!auraId) + return; + + if(auraId == 35696) // Demonic Knowledge + { + int32 basePoints = aura->GetDamage() * (GetStat(STAT_STAMINA) + GetStat(STAT_INTELLECT)) / 100; + CastCustomSpell(this,auraId,&basePoints, NULL, NULL, true ); + } + else + CastSpell(this, auraId, true); +} diff --git a/src/game/Pet.h b/src/game/Pet.h new file mode 100644 index 00000000000..f7866cbe0fc --- /dev/null +++ b/src/game/Pet.h @@ -0,0 +1,245 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOSSERVER_PET_H +#define MANGOSSERVER_PET_H + +#include "ObjectDefines.h" +#include "Creature.h" +#include "Unit.h" + +enum PetType +{ + SUMMON_PET = 0, + HUNTER_PET = 1, + GUARDIAN_PET = 2, + MINI_PET = 3, + MAX_PET_TYPE = 4 +}; + +extern char const* petTypeSuffix[MAX_PET_TYPE]; + +enum PetSaveMode +{ + PET_SAVE_AS_DELETED =-1, + PET_SAVE_AS_CURRENT = 0, + PET_SAVE_IN_STABLE_SLOT_1 = 1, + PET_SAVE_IN_STABLE_SLOT_2 = 2, + PET_SAVE_NOT_IN_SLOT = 3 +}; + +enum HappinessState +{ + UNHAPPY = 1, + CONTENT = 2, + HAPPY = 3 +}; + +enum LoyaltyLevel +{ + REBELLIOUS = 1, + UNRULY = 2, + SUBMISSIVE = 3, + DEPENDABLE = 4, + FAITHFUL = 5, + BEST_FRIEND = 6 +}; + +enum PetSpellState +{ + PETSPELL_UNCHANGED = 0, + PETSPELL_CHANGED = 1, + PETSPELL_NEW = 2, + PETSPELL_REMOVED = 3 +}; + +enum PetSpellType +{ + PETSPELL_NORMAL = 0, + PETSPELL_FAMILY = 1, +}; + +struct PetSpell +{ + uint16 slotId; + uint16 active; + PetSpellState state : 16; + PetSpellType type : 16; +}; + +enum ActionFeedback +{ + FEEDBACK_NONE = 0, + FEEDBACK_PET_DEAD = 1, + FEEDBACK_NOTHING_TO_ATT = 2, + FEEDBACK_CANT_ATT_TARGET = 3 +}; + +enum PetTalk +{ + PET_TALK_SPECIAL_SPELL = 0, + PET_TALK_ATTACK = 1 +}; + +typedef HM_NAMESPACE::hash_map PetSpellMap; +typedef std::map TeachSpellMap; +typedef std::vector AutoSpellList; + +#define HAPPINESS_LEVEL_SIZE 333000 + +extern const uint32 LevelUpLoyalty[6]; +extern const uint32 LevelStartLoyalty[6]; + +#define ACTIVE_SPELLS_MAX 4 + +#define OWNER_MAX_DISTANCE 100 + +#define PET_FOLLOW_DIST 1 +#define PET_FOLLOW_ANGLE (M_PI/2) + +class Pet : public Creature +{ + public: + explicit Pet(PetType type = MAX_PET_TYPE); + virtual ~Pet(); + + void AddToWorld(); + void RemoveFromWorld(); + + PetType getPetType() const { return m_petType; } + void setPetType(PetType type) { m_petType = type; } + bool isControlled() const { return getPetType()==SUMMON_PET || getPetType()==HUNTER_PET; } + bool isTemporarySummoned() const { return m_duration > 0; } + + bool Create (uint32 guidlow, Map *map, uint32 Entry, uint32 pet_number); + bool CreateBaseAtCreature( Creature* creature ); + bool LoadPetFromDB( Unit* owner,uint32 petentry = 0,uint32 petnumber = 0, bool current = false ); + void SavePetToDB(PetSaveMode mode); + void Remove(PetSaveMode mode, bool returnreagent = false); + static void DeleteFromDB(uint32 guidlow); + + void setDeathState(DeathState s); // overwrite virtual Creature::setDeathState and Unit::setDeathState + void Update(uint32 diff); // overwrite virtual Creature::Update and Unit::Update + + uint8 GetPetAutoSpellSize() const { return m_autospells.size(); } + uint32 GetPetAutoSpellOnPos(uint8 pos) const + { + if (pos >= m_autospells.size()) + return 0; + else + return m_autospells[pos]; + } + + void RegenerateFocus(); + void LooseHappiness(); + void TickLoyaltyChange(); + void ModifyLoyalty(int32 addvalue); + HappinessState GetHappinessState(); + uint32 GetMaxLoyaltyPoints(uint32 level); + uint32 GetStartLoyaltyPoints(uint32 level); + void KillLoyaltyBonus(uint32 level); + uint32 GetLoyaltyLevel() { return GetByteValue(UNIT_FIELD_BYTES_1, 1); } + void SetLoyaltyLevel(LoyaltyLevel level); + void GivePetXP(uint32 xp); + void GivePetLevel(uint32 level); + bool InitStatsForLevel(uint32 level); + bool HaveInDiet(ItemPrototype const* item) const; + uint32 GetCurrentFoodBenefitLevel(uint32 itemlevel); + void SetDuration(int32 dur) { m_duration = dur; } + + int32 GetBonusDamage() { return m_bonusdamage; } + void SetBonusDamage(int32 damage) { m_bonusdamage = damage; } + + bool UpdateStats(Stats stat); + bool UpdateAllStats(); + void UpdateResistances(uint32 school); + void UpdateArmor(); + void UpdateMaxHealth(); + void UpdateMaxPower(Powers power); + void UpdateAttackPowerAndDamage(bool ranged = false); + void UpdateDamagePhysical(WeaponAttackType attType); + + bool CanTakeMoreActiveSpells(uint32 SpellIconID); + void ToggleAutocast(uint32 spellid, bool apply); + bool HasTPForSpell(uint32 spellid); + int32 GetTPForSpell(uint32 spellid); + + bool HasSpell(uint32 spell) const; + void AddTeachSpell(uint32 learned_id, uint32 source_id) { m_teachspells[learned_id] = source_id; } + + void LearnPetPassives(); + void CastPetAuras(bool current); + void CastPetAura(PetAura const* aura); + + void _LoadSpellCooldowns(); + void _SaveSpellCooldowns(); + void _LoadAuras(uint32 timediff); + void _SaveAuras(); + void _LoadSpells(); + void _SaveSpells(); + + bool addSpell(uint16 spell_id,uint16 active = ACT_DECIDE, PetSpellState state = PETSPELL_NEW, uint16 slot_id=0xffff, PetSpellType type = PETSPELL_NORMAL); + bool learnSpell(uint16 spell_id); + void removeSpell(uint16 spell_id); + bool _removeSpell(uint16 spell_id); + + PetSpellMap m_spells; + TeachSpellMap m_teachspells; + AutoSpellList m_autospells; + + void InitPetCreateSpells(); + void CheckLearning(uint32 spellid); + uint32 resetTalentsCost() const; + + void SetTP(int32 TP); + int32 GetDispTP(); + + int32 m_TrainingPoints; + uint32 m_resetTalentsCost; + time_t m_resetTalentsTime; + + uint64 GetAuraUpdateMask() { return m_auraUpdateMask; } + void SetAuraUpdateMask(uint8 slot) { m_auraUpdateMask |= (uint64(1) << slot); } + void ResetAuraUpdateMask() { m_auraUpdateMask = 0; } + + DeclinedName const* GetDeclinedNames() const { return m_declinedname; } + + bool m_removed; // prevent overwrite pet state in DB at next Pet::Update if pet already removed(saved) + protected: + uint32 m_regenTimer; + uint32 m_happinessTimer; + uint32 m_loyaltyTimer; + PetType m_petType; + int32 m_duration; // time until unsummon (used mostly for summoned guardians and not used for controlled pets) + int32 m_loyaltyPoints; + int32 m_bonusdamage; + uint64 m_auraUpdateMask; + + DeclinedName *m_declinedname; + + private: + void SaveToDB(uint32, uint8) // overwrited of Creature::SaveToDB - don't must be called + { + assert(false); + } + void DeleteFromDB() // overwrited of Creature::DeleteFromDB - don't must be called + { + assert(false); + } +}; +#endif diff --git a/src/game/PetAI.cpp b/src/game/PetAI.cpp new file mode 100644 index 00000000000..c9aeaf66ec9 --- /dev/null +++ b/src/game/PetAI.cpp @@ -0,0 +1,352 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "PetAI.h" +#include "Errors.h" +#include "Pet.h" +#include "Player.h" +#include "Database/DBCStores.h" +#include "Spell.h" +#include "ObjectAccessor.h" +#include "SpellMgr.h" +#include "Creature.h" +#include "World.h" +#include "Util.h" + +int PetAI::Permissible(const Creature *creature) +{ + if( creature->isPet()) + return PERMIT_BASE_SPECIAL; + + return PERMIT_BASE_NO; +} + +PetAI::PetAI(Creature &c) : i_pet(c), i_victimGuid(0), i_tracker(TIME_INTERVAL_LOOK) +{ + m_AllySet.clear(); + UpdateAllies(); +} + +void PetAI::MoveInLineOfSight(Unit *u) +{ + if( !i_pet.getVictim() && i_pet.GetCharmInfo() && + i_pet.GetCharmInfo()->HasReactState(REACT_AGGRESSIVE) && + u->isTargetableForAttack() && i_pet.IsHostileTo( u ) && + u->isInAccessablePlaceFor(&i_pet)) + { + float attackRadius = i_pet.GetAttackDistance(u); + if(i_pet.IsWithinDistInMap(u, attackRadius) && i_pet.GetDistanceZ(u) <= CREATURE_Z_ATTACK_RANGE) + { + if(i_pet.IsWithinLOSInMap(u)) + { + AttackStart(u); + u->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + } + } + } +} + +void PetAI::AttackStart(Unit *u) +{ + if( i_pet.getVictim() || !u || i_pet.isPet() && ((Pet&)i_pet).getPetType()==MINI_PET ) + return; + + if(i_pet.Attack(u,true)) + { + i_pet.clearUnitState(UNIT_STAT_FOLLOW); + // TMGs call CreatureRelocation which via MoveInLineOfSight can call this function + // thus with the following clear the original TMG gets invalidated and crash, doh + // hope it doesn't start to leak memory without this :-/ + //i_pet->Clear(); + i_victimGuid = u->GetGUID(); + i_pet.GetMotionMaster()->MoveChase(u); + } +} + +void PetAI::EnterEvadeMode() +{ +} + +bool PetAI::IsVisible(Unit *pl) const +{ + return _isVisible(pl); +} + +bool PetAI::_needToStop() const +{ + if(!i_pet.getVictim() || !i_pet.isAlive()) + return true; + + // This is needed for charmed creatures, as once their target was reset other effects can trigger threat + if(i_pet.isCharmed() && i_pet.getVictim() == i_pet.GetCharmer()) + return true; + + return !i_pet.getVictim()->isTargetableForAttack(); +} + +void PetAI::_stopAttack() +{ + if( !i_victimGuid ) + return; + + Unit* victim = ObjectAccessor::GetUnit(i_pet, i_victimGuid ); + + if ( !victim ) + return; + + assert(!i_pet.getVictim() || i_pet.getVictim() == victim); + + if( !i_pet.isAlive() ) + { + DEBUG_LOG("Creature stoped attacking cuz his dead [guid=%u]", i_pet.GetGUIDLow()); + i_pet.StopMoving(); + i_pet.GetMotionMaster()->Clear(); + i_pet.GetMotionMaster()->MoveIdle(); + i_victimGuid = 0; + i_pet.CombatStop(); + i_pet.getHostilRefManager().deleteReferences(); + + return; + } + else if( !victim ) + { + DEBUG_LOG("Creature stopped attacking because victim is non exist [guid=%u]", i_pet.GetGUIDLow()); + } + else if( !victim->isAlive() ) + { + DEBUG_LOG("Creature stopped attacking cuz his victim is dead [guid=%u]", i_pet.GetGUIDLow()); + } + else if( victim->HasStealthAura() ) + { + DEBUG_LOG("Creature stopped attacking cuz his victim is stealth [guid=%u]", i_pet.GetGUIDLow()); + } + else if( victim->isInFlight() ) + { + DEBUG_LOG("Creature stopped attacking cuz his victim is fly away [guid=%u]", i_pet.GetGUIDLow()); + } + else + { + DEBUG_LOG("Creature stopped attacking due to target out run him [guid=%u]", i_pet.GetGUIDLow()); + } + + Unit* owner = i_pet.GetCharmerOrOwner(); + + if(owner && i_pet.GetCharmInfo() && i_pet.GetCharmInfo()->HasCommandState(COMMAND_FOLLOW)) + { + i_pet.GetMotionMaster()->MoveFollow(owner,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE); + } + else + { + i_pet.clearUnitState(UNIT_STAT_FOLLOW); + i_pet.GetMotionMaster()->Clear(); + i_pet.GetMotionMaster()->MoveIdle(); + } + i_victimGuid = 0; + i_pet.AttackStop(); +} + +void PetAI::UpdateAI(const uint32 diff) +{ + // update i_victimGuid if i_pet.getVictim() !=0 and changed + if(i_pet.getVictim()) + i_victimGuid = i_pet.getVictim()->GetGUID(); + + Unit* owner = i_pet.GetCharmerOrOwner(); + + if(m_updateAlliesTimer <= diff) + // UpdateAllies self set update timer + UpdateAllies(); + else + m_updateAlliesTimer -= diff; + + // i_pet.getVictim() can't be used for check in case stop fighting, i_pet.getVictim() clear at Unit death etc. + if( i_victimGuid ) + { + if( _needToStop() ) + { + DEBUG_LOG("Pet AI stoped attacking [guid=%u]", i_pet.GetGUIDLow()); + _stopAttack(); // i_victimGuid == 0 && i_pet.getVictim() == NULL now + return; + } + else if( i_pet.IsStopped() || i_pet.IsWithinDistInMap(i_pet.getVictim(), ATTACK_DISTANCE)) + { + // required to be stopped cases + if ( i_pet.IsStopped() && i_pet.IsNonMeleeSpellCasted(false) ) + { + if( i_pet.hasUnitState(UNIT_STAT_FOLLOW) ) + i_pet.InterruptNonMeleeSpells(false); + else + return; + } + // not required to be stopped case + else if( i_pet.isAttackReady() && i_pet.canReachWithAttack(i_pet.getVictim()) ) + { + i_pet.AttackerStateUpdate(i_pet.getVictim()); + + i_pet.resetAttackTimer(); + + if ( !i_pet.getVictim() ) + return; + + //if pet misses its target, it will also be the first in threat list + i_pet.getVictim()->AddThreat(&i_pet,0.0f); + + if( _needToStop() ) + _stopAttack(); + } + } + } + else if(owner && i_pet.GetCharmInfo()) + { + if(owner->isInCombat() && !(i_pet.GetCharmInfo()->HasReactState(REACT_PASSIVE) || i_pet.GetCharmInfo()->HasCommandState(COMMAND_STAY))) + { + AttackStart(owner->getAttackerForHelper()); + } + else if(i_pet.GetCharmInfo()->HasCommandState(COMMAND_FOLLOW)) + { + if (!i_pet.hasUnitState(UNIT_STAT_FOLLOW) ) + { + i_pet.GetMotionMaster()->MoveFollow(owner,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE); + } + } + } + + //Autocast + HM_NAMESPACE::hash_map targetMap; + targetMap.clear(); + SpellCastTargets NULLtargets; + + for (uint8 i = 0; i < i_pet.GetPetAutoSpellSize(); i++) + { + uint32 spellID = i_pet.GetPetAutoSpellOnPos(i); + if (!spellID) + continue; + + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellID); + if (!spellInfo) + continue; + + Spell *spell = new Spell(&i_pet, spellInfo, false, 0); + + if(!IsPositiveSpell(spellInfo->Id) && i_pet.getVictim() && !_needToStop() && !i_pet.hasUnitState(UNIT_STAT_FOLLOW) && spell->CanAutoCast(i_pet.getVictim())) + targetMap[spellID] = i_pet.getVictim(); + else + { + spell->m_targets = NULLtargets; + for(std::set::iterator tar = m_AllySet.begin(); tar != m_AllySet.end(); ++tar) + { + Unit* Target = ObjectAccessor::GetUnit(i_pet,*tar); + + //only buff targets that are in combat, unless the spell can only be cast while out of combat + if(!Target || (!Target->isInCombat() && !IsNonCombatSpell(spellInfo))) + continue; + if(spell->CanAutoCast(Target)) + targetMap[spellID] = Target; + } + } + + delete spell; + } + + //found units to cast on to + if(!targetMap.empty()) + { + uint32 index = urand(1, targetMap.size()); + HM_NAMESPACE::hash_map::iterator itr; + uint32 i; + for(itr = targetMap.begin(), i = 1; i < index; ++itr, ++i); + + SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first); + + Spell *spell = new Spell(&i_pet, spellInfo, false); + + SpellCastTargets targets; + targets.setUnitTarget( itr->second ); + + if(!i_pet.HasInArc(M_PI, itr->second)) + { + i_pet.SetInFront(itr->second); + if( itr->second->GetTypeId() == TYPEID_PLAYER ) + i_pet.SendUpdateToPlayer( (Player*)itr->second ); + + if(owner && owner->GetTypeId() == TYPEID_PLAYER) + i_pet.SendUpdateToPlayer( (Player*)owner ); + } + + i_pet.AddCreatureSpellCooldown(itr->first); + if(i_pet.isPet()) + ((Pet*)&i_pet)->CheckLearning(itr->first); + + spell->prepare(&targets); + } + targetMap.clear(); +} + +bool PetAI::_isVisible(Unit *u) const +{ + //return false; //( ((Creature*)&i_pet)->GetDistanceSq(u) * 1.0<= sWorld.getConfig(CONFIG_SIGHT_GUARDER) && !u->m_stealth && u->isAlive()); + return i_pet.GetDistance(u) < sWorld.getConfig(CONFIG_SIGHT_GUARDER) + && u->isVisibleForOrDetect(&i_pet,true); +} + +void PetAI::UpdateAllies() +{ + Unit* owner = i_pet.GetCharmerOrOwner(); + Group *pGroup = NULL; + + m_updateAlliesTimer = 10000; //update friendly targets every 10 seconds, lesser checks increase performance + + if(!owner) + return; + else if(owner->GetTypeId() == TYPEID_PLAYER) + pGroup = ((Player*)owner)->GetGroup(); + + //only pet and owner/not in group->ok + if(m_AllySet.size() == 2 && !pGroup) + return; + //owner is in group; group members filled in already (no raid -> subgroupcount = whole count) + if(pGroup && !pGroup->isRaidGroup() && m_AllySet.size() == (pGroup->GetMembersCount() + 2)) + return; + + m_AllySet.clear(); + m_AllySet.insert(i_pet.GetGUID()); + if(pGroup) //add group + { + for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player* Target = itr->getSource(); + if(!Target || !pGroup->SameSubGroup((Player*)owner, Target)) + continue; + + if(Target->GetGUID() == owner->GetGUID()) + continue; + + m_AllySet.insert(Target->GetGUID()); + } + } + else //remove group + m_AllySet.insert(owner->GetGUID()); +} + +void PetAI::AttackedBy(Unit *attacker) +{ + //when attacked, fight back in case 1)no victim already AND 2)not set to passive AND 3)not set to stay, unless can it can reach attacker with melee attack anyway + if(!i_pet.getVictim() && i_pet.GetCharmInfo() && !i_pet.GetCharmInfo()->HasReactState(REACT_PASSIVE) && + (!i_pet.GetCharmInfo()->HasCommandState(COMMAND_STAY) || i_pet.canReachWithAttack(attacker))) + AttackStart(attacker); +} diff --git a/src/game/PetAI.h b/src/game/PetAI.h new file mode 100644 index 00000000000..b8124bb3520 --- /dev/null +++ b/src/game/PetAI.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_PETAI_H +#define MANGOS_PETAI_H + +#include "CreatureAI.h" +#include "Timer.h" + +class Creature; + +class MANGOS_DLL_DECL PetAI : public CreatureAI +{ + public: + + PetAI(Creature &c); + + void MoveInLineOfSight(Unit *); + void AttackStart(Unit *); + void EnterEvadeMode(); + void DamageTaken(Unit *done_by, uint32& /*damage*/) { AttackedBy(done_by); } + void AttackedBy(Unit*); + bool IsVisible(Unit *) const; + + void UpdateAI(const uint32); + void UpdateAllies(); + static int Permissible(const Creature *); + + private: + bool _isVisible(Unit *) const; + bool _needToStop(void) const; + void _stopAttack(void); + + Creature &i_pet; + uint64 i_victimGuid; + TimeTracker i_tracker; + //uint32 i_RepeatAction; + std::set m_AllySet; + uint32 m_updateAlliesTimer; +}; +#endif diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp new file mode 100644 index 00000000000..3251d02d5b9 --- /dev/null +++ b/src/game/PetHandler.cpp @@ -0,0 +1,648 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "World.h" +#include "ObjectMgr.h" +#include "SpellMgr.h" +#include "Log.h" +#include "Opcodes.h" +#include "Spell.h" +#include "ObjectAccessor.h" +#include "MapManager.h" +#include "CreatureAI.h" +#include "Util.h" +#include "Pet.h" + +void WorldSession::HandlePetAction( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+2+2+8); + + uint64 guid1; + uint16 spellid; + uint16 flag; + uint64 guid2; + recv_data >> guid1; //pet guid + recv_data >> spellid; + recv_data >> flag; //delete = 0x0700 CastSpell = C100 + recv_data >> guid2; //tag guid + + // used also for charmed creature + Unit* pet= ObjectAccessor::GetUnit(*_player,guid1); + sLog.outDetail( "HandlePetAction.Pet %u flag is %u, spellid is %u, target %u.\n", uint32(GUID_LOPART(guid1)), flag, spellid, uint32(GUID_LOPART(guid2)) ); + if(!pet) + { + sLog.outError( "Pet %u not exist.\n", uint32(GUID_LOPART(guid1)) ); + return; + } + + if(pet != GetPlayer()->GetPet() && pet != GetPlayer()->GetCharm()) + { + sLog.outError( "HandlePetAction.Pet %u isn't pet of player %s .\n", uint32(GUID_LOPART(guid1)),GetPlayer()->GetName() ); + return; + } + + if(!pet->isAlive()) + return; + + if(pet->GetTypeId() == TYPEID_PLAYER && !(flag == ACT_COMMAND && spellid == COMMAND_ATTACK)) + return; + + CharmInfo *charmInfo = pet->GetCharmInfo(); + if(!charmInfo) + { + sLog.outError("WorldSession::HandlePetAction: object "I64FMTD" is considered pet-like but doesn't have a charminfo!", pet->GetGUID()); + return; + } + + switch(flag) + { + case ACT_COMMAND: //0x0700 + switch(spellid) + { + case COMMAND_STAY: //flat=1792 //STAY + pet->StopMoving(); + pet->GetMotionMaster()->Clear(); + pet->GetMotionMaster()->MoveIdle(); + charmInfo->SetCommandState( COMMAND_STAY ); + break; + case COMMAND_FOLLOW: //spellid=1792 //FOLLOW + pet->AttackStop(); + pet->GetMotionMaster()->MoveFollow(_player,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE); + charmInfo->SetCommandState( COMMAND_FOLLOW ); + break; + case COMMAND_ATTACK: //spellid=1792 //ATTACK + { + // only place where pet can be player + pet->clearUnitState(UNIT_STAT_FOLLOW); + uint64 selguid = _player->GetSelection(); + Unit *TargetUnit = ObjectAccessor::GetUnit(*_player, selguid); + if(!TargetUnit) + return; + + // not let attack friendly units. + if( GetPlayer()->IsFriendlyTo(TargetUnit)) + return; + + if(pet->getVictim()) + pet->AttackStop(); + + if(pet->GetTypeId() != TYPEID_PLAYER) + { + pet->GetMotionMaster()->Clear(); + if (((Creature*)pet)->AI()) + ((Creature*)pet)->AI()->AttackStart(TargetUnit); + + //10% chance to play special pet attack talk, else growl + if(((Creature*)pet)->isPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && urand(0, 100) < 10) + pet->SendPetTalk((uint32)PET_TALK_ATTACK); + else + { + // 90% chance for pet and 100% chance for charmed creature + pet->SendPetAIReaction(guid1); + } + } + else // charmed player + { + pet->Attack(TargetUnit,true); + pet->SendPetAIReaction(guid1); + } + break; + } + case COMMAND_ABANDON: // abandon (hunter pet) or dismiss (summoned pet) + if(((Creature*)pet)->isPet()) + { + Pet* p = (Pet*)pet; + if(p->getPetType() == HUNTER_PET) + _player->RemovePet(p,PET_SAVE_AS_DELETED); + else + //dismissing a summoned pet is like killing them (this prevents returning a soulshard...) + p->setDeathState(CORPSE); + } + else // charmed + _player->Uncharm(); + break; + default: + sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.\n", flag, spellid); + } + break; + case ACT_REACTION: // 0x600 + switch(spellid) + { + case REACT_PASSIVE: //passive + case REACT_DEFENSIVE: //recovery + case REACT_AGGRESSIVE: //activete + charmInfo->SetReactState( ReactStates(spellid) ); + break; + } + break; + case ACT_DISABLED: //0x8100 spell (disabled), ignore + case ACT_CAST: //0x0100 + case ACT_ENABLED: //0xc100 spell + { + Unit* unit_target; + if(guid2) + unit_target = ObjectAccessor::GetUnit(*_player,guid2); + else + unit_target = NULL; + + // do not cast unknown spells + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellid ); + if(!spellInfo) + { + sLog.outError("WORLD: unknown PET spell id %i\n", spellid); + return; + } + + for(uint32 i = 0; i < 3;i++) + { + if(spellInfo->EffectImplicitTargetA[i] == TARGET_ALL_ENEMY_IN_AREA || spellInfo->EffectImplicitTargetA[i] == TARGET_ALL_ENEMY_IN_AREA_INSTANT || spellInfo->EffectImplicitTargetA[i] == TARGET_ALL_ENEMY_IN_AREA_CHANNELED) + return; + } + + // do not cast not learned spells + if(!pet->HasSpell(spellid) || IsPassiveSpell(spellid)) + return; + + pet->clearUnitState(UNIT_STAT_FOLLOW); + + Spell *spell = new Spell(pet, spellInfo, false); + + int16 result = spell->PetCanCast(unit_target); + + //auto turn to target unless possessed + if(result == SPELL_FAILED_UNIT_NOT_INFRONT && !pet->HasAuraType(SPELL_AURA_MOD_POSSESS)) + { + pet->SetInFront(unit_target); + if( unit_target->GetTypeId() == TYPEID_PLAYER ) + pet->SendUpdateToPlayer( (Player*)unit_target ); + if(Unit* powner = pet->GetCharmerOrOwner()) + if(powner->GetTypeId() == TYPEID_PLAYER) + pet->SendUpdateToPlayer((Player*)powner); + result = -1; + } + + if(result == -1) + { + ((Creature*)pet)->AddCreatureSpellCooldown(spellid); + if (((Creature*)pet)->isPet()) + ((Pet*)pet)->CheckLearning(spellid); + + unit_target = spell->m_targets.getUnitTarget(); + + //10% chance to play special pet attack talk, else growl + //actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell + if(((Creature*)pet)->isPet() && (((Pet*)pet)->getPetType() == SUMMON_PET) && (pet != unit_target) && (urand(0, 100) < 10)) + pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); + else + { + pet->SendPetAIReaction(guid1); + } + + if( unit_target && !GetPlayer()->IsFriendlyTo(unit_target) && !pet->HasAuraType(SPELL_AURA_MOD_POSSESS)) + { + pet->clearUnitState(UNIT_STAT_FOLLOW); + if(pet->getVictim()) + pet->AttackStop(); + pet->GetMotionMaster()->Clear(); + if (((Creature*)pet)->AI()) + ((Creature*)pet)->AI()->AttackStart(unit_target); + } + + spell->prepare(&(spell->m_targets)); + } + else + { + if(pet->HasAuraType(SPELL_AURA_MOD_POSSESS)) + { + WorldPacket data(SMSG_CAST_FAILED, (4+1+1)); + data << uint32(spellid) << uint8(2) << uint8(result); + switch (result) + { + case SPELL_FAILED_REQUIRES_SPELL_FOCUS: + data << uint32(spellInfo->RequiresSpellFocus); + break; + case SPELL_FAILED_REQUIRES_AREA: + data << uint32(spellInfo->AreaId); + break; + } + SendPacket(&data); + } + else + pet->SendPetCastFail(spellid, result); + + if(!((Creature*)pet)->HasSpellCooldown(spellid)) + pet->SendPetClearCooldown(spellid); + + spell->finish(false); + delete spell; + } + break; + } + default: + sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.\n", flag, spellid); + } +} + +void WorldSession::HandlePetNameQuery( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,4+8); + + sLog.outDetail( "HandlePetNameQuery. CMSG_PET_NAME_QUERY\n" ); + + uint32 petnumber; + uint64 petguid; + + recv_data >> petnumber; + recv_data >> petguid; + + SendPetNameQuery(petguid,petnumber); +} + +void WorldSession::SendPetNameQuery( uint64 petguid, uint32 petnumber) +{ + Creature* pet = ObjectAccessor::GetCreatureOrPet(*_player, petguid); + if(!pet || !pet->GetCharmInfo() || pet->GetCharmInfo()->GetPetNumber() != petnumber) + return; + + std::string name = pet->GetName(); + + WorldPacket data(SMSG_PET_NAME_QUERY_RESPONSE, (4+4+name.size()+1)); + data << uint32(petnumber); + data << name.c_str(); + data << uint32(pet->GetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP)); + + if( pet->isPet() && ((Pet*)pet)->GetDeclinedNames() ) + { + data << uint8(1); + for(int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) + data << ((Pet*)pet)->GetDeclinedNames()->name[i]; + } + else + data << uint8(0); + + _player->GetSession()->SendPacket(&data); +} + +void WorldSession::HandlePetSetAction( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+4+2+2); + + sLog.outDetail( "HandlePetSetAction. CMSG_PET_SET_ACTION\n" ); + + uint64 petguid; + uint32 position; + uint16 spell_id; + uint16 act_state; + uint8 count; + + recv_data >> petguid; + + // FIXME: charmed case + //Pet* pet = ObjectAccessor::Instance().GetPet(petguid); + if(ObjectAccessor::FindPlayer(petguid)) + return; + + Creature* pet = ObjectAccessor::GetCreatureOrPet(*_player, petguid); + + if(!pet || (pet != _player->GetPet() && pet != _player->GetCharm())) + { + sLog.outError( "HandlePetSetAction: Unknown pet or pet owner.\n" ); + return; + } + + CharmInfo *charmInfo = pet->GetCharmInfo(); + if(!charmInfo) + { + sLog.outError("WorldSession::HandlePetSetAction: object "I64FMTD" is considered pet-like but doesn't have a charminfo!", pet->GetGUID()); + return; + } + + count = (recv_data.size() == 24) ? 2 : 1; + for(uint8 i = 0; i < count; i++) + { + recv_data >> position; + recv_data >> spell_id; + recv_data >> act_state; + + sLog.outDetail( "Player %s has changed pet spell action. Position: %u, Spell: %u, State: 0x%X\n", _player->GetName(), position, spell_id, act_state); + + //if it's act for spell (en/disable/cast) and there is a spell given (0 = remove spell) which pet doesn't know, don't add + if(!((act_state == ACT_ENABLED || act_state == ACT_DISABLED || act_state == ACT_CAST) && spell_id && !pet->HasSpell(spell_id))) + { + //sign for autocast + if(act_state == ACT_ENABLED && spell_id) + { + if(pet->isCharmed()) + charmInfo->ToggleCreatureAutocast(spell_id, true); + else + ((Pet*)pet)->ToggleAutocast(spell_id, true); + } + //sign for no/turn off autocast + else if(act_state == ACT_DISABLED && spell_id) + { + if(pet->isCharmed()) + charmInfo->ToggleCreatureAutocast(spell_id, false); + else + ((Pet*)pet)->ToggleAutocast(spell_id, false); + } + + charmInfo->GetActionBarEntry(position)->Type = act_state; + charmInfo->GetActionBarEntry(position)->SpellOrAction = spell_id; + } + } +} + +void WorldSession::HandlePetRename( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+1+1+1+1+1+1+1); + + sLog.outDetail( "HandlePetRename. CMSG_PET_RENAME\n" ); + + uint64 petguid; + uint8 isdeclined; + + std::string name; + DeclinedName declinedname; + + recv_data >> petguid; + recv_data >> name; + recv_data >> isdeclined; + + Pet* pet = ObjectAccessor::GetPet(petguid); + // check it! + if( !pet || !pet->isPet() || ((Pet*)pet)->getPetType()!= HUNTER_PET || + pet->GetByteValue(UNIT_FIELD_BYTES_2, 2) != UNIT_RENAME_ALLOWED || + pet->GetOwnerGUID() != _player->GetGUID() || !pet->GetCharmInfo() ) + return; + + if((!ObjectMgr::IsValidPetName(name)) || (objmgr.IsReservedName(name))) + { + SendNotification("Invalid name"); + return; + } + pet->SetName(name); + + Unit *owner = pet->GetOwner(); + if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup()) + ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_NAME); + + pet->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_NOT_ALLOWED); + + if(isdeclined) + { + for(int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) + recv_data >> declinedname.name[i]; + + std::wstring wname; + Utf8toWStr(name,wname); + if(!ObjectMgr::CheckDeclinedNames(GetMainPartOfName(wname,0),declinedname)) + { + SendNotification("Invalid name"); + return; + } + } + + CharacterDatabase.BeginTransaction(); + if(isdeclined) + { + for(int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) + CharacterDatabase.escape_string(declinedname.name[i]); + CharacterDatabase.PExecute("DELETE FROM character_pet_declinedname WHERE owner = '%u' AND id = '%u'", _player->GetGUIDLow(), pet->GetCharmInfo()->GetPetNumber()); + CharacterDatabase.PExecute("INSERT INTO character_pet_declinedname (id, owner, genitive, dative, accusative, instrumental, prepositional) VALUES ('%u','%u','%s','%s','%s','%s','%s')", + pet->GetCharmInfo()->GetPetNumber(), _player->GetGUIDLow(), declinedname.name[0].c_str(),declinedname.name[1].c_str(),declinedname.name[2].c_str(),declinedname.name[3].c_str(),declinedname.name[4].c_str()); + } + + CharacterDatabase.escape_string(name); + CharacterDatabase.PExecute("UPDATE character_pet SET name = '%s', renamed = '1' WHERE owner = '%u' AND id = '%u'", name.c_str(),_player->GetGUIDLow(),pet->GetCharmInfo()->GetPetNumber() ); + CharacterDatabase.CommitTransaction(); + + pet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL)); +} + +void WorldSession::HandlePetAbandon( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8); + + uint64 guid; + recv_data >> guid; //pet guid + sLog.outDetail( "HandlePetAbandon. CMSG_PET_ABANDON pet guid is %u", GUID_LOPART(guid) ); + + // pet/charmed + Creature* pet=ObjectAccessor::GetCreatureOrPet(*_player, guid); + if(pet) + { + if(pet->isPet()) + { + if(pet->GetGUID() == _player->GetPetGUID()) + { + uint32 feelty = pet->GetPower(POWER_HAPPINESS); + pet->SetPower(POWER_HAPPINESS ,(feelty-50000) > 0 ?(feelty-50000) : 0); + } + + _player->RemovePet((Pet*)pet,PET_SAVE_AS_DELETED); + } + else if(pet->GetGUID() == _player->GetCharmGUID()) + { + _player->Uncharm(); + } + } +} + +void WorldSession::HandlePetUnlearnOpcode(WorldPacket& recvPacket) +{ + CHECK_PACKET_SIZE(recvPacket,8); + + sLog.outDetail("CMSG_PET_UNLEARN"); + uint64 guid; + recvPacket >> guid; + + Pet* pet = _player->GetPet(); + + if(!pet || pet->getPetType() != HUNTER_PET || pet->m_spells.size() <= 1) + return; + + if(guid != pet->GetGUID()) + { + sLog.outError( "HandlePetUnlearnOpcode.Pet %u isn't pet of player %s .\n", uint32(GUID_LOPART(guid)),GetPlayer()->GetName() ); + return; + } + + CharmInfo *charmInfo = pet->GetCharmInfo(); + if(!charmInfo) + { + sLog.outError("WorldSession::HandlePetUnlearnOpcode: object "I64FMTD" is considered pet-like but doesn't have a charminfo!", pet->GetGUID()); + return; + } + + uint32 cost = pet->resetTalentsCost(); + + if (GetPlayer()->GetMoney() < cost) + { + GetPlayer()->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, 0, 0, 0); + return; + } + + for(PetSpellMap::iterator itr = pet->m_spells.begin(); itr != pet->m_spells.end();) + { + uint32 spell_id = itr->first; // Pet::removeSpell can invalidate iterator at erase NEW spell + ++itr; + pet->removeSpell(spell_id); + } + + pet->SetTP(pet->getLevel() * (pet->GetLoyaltyLevel() - 1)); + + for(uint8 i = 0; i < 10; i++) + { + if(charmInfo->GetActionBarEntry(i)->SpellOrAction && charmInfo->GetActionBarEntry(i)->Type == ACT_ENABLED || charmInfo->GetActionBarEntry(i)->Type == ACT_DISABLED) + charmInfo->GetActionBarEntry(i)->SpellOrAction = 0; + } + + // relearn pet passives + pet->LearnPetPassives(); + + pet->m_resetTalentsTime = time(NULL); + pet->m_resetTalentsCost = cost; + GetPlayer()->ModifyMoney(-(int32)cost); + + GetPlayer()->PetSpellInitialize(); +} + +void WorldSession::HandlePetSpellAutocastOpcode( WorldPacket& recvPacket ) +{ + CHECK_PACKET_SIZE(recvPacket,8+2+2+1); + + sLog.outDetail("CMSG_PET_SPELL_AUTOCAST"); + uint64 guid; + uint16 spellid; + uint16 spellid2; //maybe second spell, automatically toggled off when first toggled on? + uint8 state; //1 for on, 0 for off + recvPacket >> guid >> spellid >> spellid2 >> state; + + if(!_player->GetPet() && !_player->GetCharm()) + return; + + if(ObjectAccessor::FindPlayer(guid)) + return; + + Creature* pet=ObjectAccessor::GetCreatureOrPet(*_player,guid); + + if(!pet || (pet != _player->GetPet() && pet != _player->GetCharm())) + { + sLog.outError( "HandlePetSpellAutocastOpcode.Pet %u isn't pet of player %s .\n", uint32(GUID_LOPART(guid)),GetPlayer()->GetName() ); + return; + } + + // do not add not learned spells/ passive spells + if(!pet->HasSpell(spellid) || IsPassiveSpell(spellid)) + return; + + CharmInfo *charmInfo = pet->GetCharmInfo(); + if(!charmInfo) + { + sLog.outError("WorldSession::HandlePetSpellAutocastOpcod: object "I64FMTD" is considered pet-like but doesn't have a charminfo!", pet->GetGUID()); + return; + } + + if(pet->isCharmed()) + //state can be used as boolean + pet->GetCharmInfo()->ToggleCreatureAutocast(spellid, state); + else + ((Pet*)pet)->ToggleAutocast(spellid, state); + + for(uint8 i = 0; i < 10; ++i) + { + if((charmInfo->GetActionBarEntry(i)->Type == ACT_ENABLED || charmInfo->GetActionBarEntry(i)->Type == ACT_DISABLED) && spellid == charmInfo->GetActionBarEntry(i)->SpellOrAction) + charmInfo->GetActionBarEntry(i)->Type = state ? ACT_ENABLED : ACT_DISABLED; + } +} + +void WorldSession::HandleAddDynamicTargetObsoleteOpcode( WorldPacket& recvPacket ) +{ + sLog.outDetail("WORLD: CMSG_PET_CAST_SPELL"); + + CHECK_PACKET_SIZE(recvPacket,8+4); + uint64 guid; + uint32 spellid; + + recvPacket >> guid >> spellid; + + if(!_player->GetPet() && !_player->GetCharm()) + return; + + if(ObjectAccessor::FindPlayer(guid)) + return; + + Creature* pet=ObjectAccessor::GetCreatureOrPet(*_player,guid); + + if(!pet || (pet != _player->GetPet() && pet!= _player->GetCharm())) + { + sLog.outError( "HandleAddDynamicTargetObsoleteOpcode.Pet %u isn't pet of player %s .\n", uint32(GUID_LOPART(guid)),GetPlayer()->GetName() ); + return; + } + + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellid); + if(!spellInfo) + { + sLog.outError("WORLD: unknown PET spell id %i\n", spellid); + return; + } + + // do not cast not learned spells + if(!pet->HasSpell(spellid) || IsPassiveSpell(spellid)) + return; + + SpellCastTargets targets; + if(!targets.read(&recvPacket,pet)) + return; + + pet->clearUnitState(UNIT_STAT_FOLLOW); + + Spell *spell = new Spell(pet, spellInfo, false); + spell->m_targets = targets; + + int16 result = spell->PetCanCast(NULL); + if(result == -1) + { + pet->AddCreatureSpellCooldown(spellid); + if(pet->isPet()) + { + Pet* p = (Pet*)pet; + p->CheckLearning(spellid); + //10% chance to play special pet attack talk, else growl + //actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell + if(p->getPetType() == SUMMON_PET && (urand(0, 100) < 10)) + pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); + else + pet->SendPetAIReaction(guid); + } + + spell->prepare(&(spell->m_targets)); + } + else + { + pet->SendPetCastFail(spellid, result); + if(!pet->HasSpellCooldown(spellid)) + pet->SendPetClearCooldown(spellid); + + spell->finish(false); + delete spell; + } +} diff --git a/src/game/PetitionsHandler.cpp b/src/game/PetitionsHandler.cpp new file mode 100644 index 00000000000..6957634dc9e --- /dev/null +++ b/src/game/PetitionsHandler.cpp @@ -0,0 +1,936 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Language.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "World.h" +#include "ObjectMgr.h" +#include "Log.h" +#include "Opcodes.h" +#include "Guild.h" +#include "ArenaTeam.h" +#include "MapManager.h" +#include "GossipDef.h" +#include "SocialMgr.h" + +/*enum PetitionType // dbc data +{ + PETITION_TYPE_GUILD = 1, + PETITION_TYPE_ARENA_TEAM = 3 +};*/ + +// Charters ID in item_template +#define GUILD_CHARTER 5863 +#define GUILD_CHARTER_COST 1000 // 10 S +#define ARENA_TEAM_CHARTER_2v2 23560 +#define ARENA_TEAM_CHARTER_2v2_COST 800000 // 80 G +#define ARENA_TEAM_CHARTER_3v3 23561 +#define ARENA_TEAM_CHARTER_3v3_COST 1200000 // 120 G +#define ARENA_TEAM_CHARTER_5v5 23562 +#define ARENA_TEAM_CHARTER_5v5_COST 2000000 // 200 G + +void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data) +{ + CHECK_PACKET_SIZE(recv_data, 8+8+4+1+5*8+2+1+4+4); + + sLog.outDebug("Received opcode CMSG_PETITION_BUY"); + //recv_data.hexlike(); + + uint64 guidNPC; + uint64 unk1, unk3, unk4, unk5, unk6, unk7; + uint32 unk2; + std::string name; + uint16 unk8; + uint8 unk9; + uint32 unk10; // selected index + uint32 unk11; + recv_data >> guidNPC; // NPC GUID + recv_data >> unk1; // 0 + recv_data >> unk2; // 0 + recv_data >> name; // name + + // recheck + CHECK_PACKET_SIZE(recv_data, 8+8+4+(name.size()+1)+5*8+2+1+4+4); + + recv_data >> unk3; // 0 + recv_data >> unk4; // 0 + recv_data >> unk5; // 0 + recv_data >> unk6; // 0 + recv_data >> unk7; // 0 + recv_data >> unk8; // 0 + recv_data >> unk9; // 0 + recv_data >> unk10; // index + recv_data >> unk11; // 0 + sLog.outDebug("Petitioner with GUID %u tried sell petition: name %s", GUID_LOPART(guidNPC), name.c_str()); + + // prevent cheating + Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guidNPC,UNIT_NPC_FLAG_PETITIONER); + if (!pCreature) + { + sLog.outDebug("WORLD: HandlePetitionBuyOpcode - Unit (GUID: %u) not found or you can't interact with him.", GUID_LOPART(guidNPC)); + return; + } + + // remove fake death + if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + uint32 charterid = 0; + uint32 cost = 0; + uint32 type = 0; + if(pCreature->isTabardDesigner()) + { + // if tabard designer, then trying to buy a guild charter. + // do not let if already in guild. + if(_player->GetGuildId()) + return; + + charterid = GUILD_CHARTER; + cost = GUILD_CHARTER_COST; + type = 9; + } + else + { + // TODO: find correct opcode + if(_player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + { + SendNotification(GetMangosString(LANG_ARENA_ONE_TOOLOW), 70); + return; + } + + for(uint8 i = 0; i < MAX_ARENA_SLOT; i++) + { + if(_player->GetArenaTeamId(i) && (i == (unk10-1))) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM); + return; + } + } + switch(unk10) + { + case 1: + charterid = ARENA_TEAM_CHARTER_2v2; + cost = ARENA_TEAM_CHARTER_2v2_COST; + type = 2; // 2v2 + break; + case 2: + charterid = ARENA_TEAM_CHARTER_3v3; + cost = ARENA_TEAM_CHARTER_3v3_COST; + type = 3; // 3v3 + break; + case 3: + charterid = ARENA_TEAM_CHARTER_5v5; + cost = ARENA_TEAM_CHARTER_5v5_COST; + type = 5; // 5v5 + break; + default: + sLog.outDebug("unknown selection at buy petition: %u", unk10); + return; + } + } + + if(type == 9) + { + if(objmgr.GetGuildByName(name)) + { + SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_EXISTS); + return; + } + if(objmgr.IsReservedName(name)) + { + SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_INVALID); + return; + } + if(!ObjectMgr::IsValidCharterName(name)) + { + SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_INVALID); + return; + } + } + else + { + if(objmgr.GetArenaTeamByName(name)) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S); + return; + } + if(objmgr.IsReservedName(name)) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_INVALID); + return; + } + if(!ObjectMgr::IsValidCharterName(name)) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_INVALID); + return; + } + } + + ItemPrototype const *pProto = objmgr.GetItemPrototype(charterid); + if(!pProto) + { + _player->SendBuyError(BUY_ERR_CANT_FIND_ITEM, NULL, charterid, 0); + return; + } + + if(_player->GetMoney() < cost) + { //player hasn't got enough money + _player->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, charterid, 0); + return; + } + + ItemPosCountVec dest; + uint8 msg = _player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, charterid, pProto->BuyCount ); + if(msg != EQUIP_ERR_OK) + { + _player->SendBuyError(msg, pCreature, charterid, 0); + return; + } + + _player->ModifyMoney(-(int32)cost); + Item *charter = _player->StoreNewItem(dest, charterid, true); + if(!charter) + return; + + charter->SetUInt32Value(ITEM_FIELD_ENCHANTMENT, charter->GetGUIDLow()); + // ITEM_FIELD_ENCHANTMENT is guild/arenateam id + // ITEM_FIELD_ENCHANTMENT+1 is current signatures count (showed on item) + charter->SetState(ITEM_CHANGED, _player); + _player->SendNewItem(charter, 1, true, false); + + // a petition is invalid, if both the owner and the type matches + QueryResult *result = CharacterDatabase.PQuery("SELECT petitionguid FROM petition WHERE ownerguid = '%u' AND type = '%u'", _player->GetGUIDLow(), type); + + std::ostringstream ssInvalidPetitionGUIDs; + + if (result) + { + + do + { + Field *fields = result->Fetch(); + ssInvalidPetitionGUIDs << "'" << fields[0].GetUInt32() << "' , "; + } while (result->NextRow()); + + delete result; + } + + // delete petitions with the same guid as this one + ssInvalidPetitionGUIDs << "'" << charter->GetGUIDLow() << "'"; + + sLog.outDebug("Invalid petition GUIDs: %s", ssInvalidPetitionGUIDs.str().c_str()); + CharacterDatabase.escape_string(name); + CharacterDatabase.BeginTransaction(); + CharacterDatabase.PExecute("DELETE FROM petition WHERE petitionguid IN ( %s )", ssInvalidPetitionGUIDs.str().c_str()); + CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE petitionguid IN ( %s )", ssInvalidPetitionGUIDs.str().c_str()); + CharacterDatabase.PExecute("INSERT INTO petition (ownerguid, petitionguid, name, type) VALUES ('%u', '%u', '%s', '%u')", + _player->GetGUIDLow(), charter->GetGUIDLow(), name.c_str(), type); + CharacterDatabase.CommitTransaction(); +} + +void WorldSession::HandlePetitionShowSignOpcode(WorldPacket & recv_data) +{ + CHECK_PACKET_SIZE(recv_data, 8); + + // ok + sLog.outDebug("Received opcode CMSG_PETITION_SHOW_SIGNATURES"); + //recv_data.hexlike(); + + uint8 signs = 0; + uint64 petitionguid; + recv_data >> petitionguid; // petition guid + + // solve (possible) some strange compile problems with explicit use GUID_LOPART(petitionguid) at some GCC versions (wrong code optimization in compiler?) + uint32 petitionguid_low = GUID_LOPART(petitionguid); + + QueryResult *result = CharacterDatabase.PQuery("SELECT petitionguid, type FROM petition WHERE petitionguid = '%u'", petitionguid_low); + if(!result) + { + sLog.outError("any petition on server..."); + return; + } + Field *fields = result->Fetch(); + uint32 type = fields[1].GetUInt32(); + delete result; + // if guild petition and has guild => error, return; + if(type==9 && _player->GetGuildId()) + return; + + result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", petitionguid_low); + + // result==NULL also correct in case no sign yet + if(result) + signs = result->GetRowCount(); + + sLog.outDebug("CMSG_PETITION_SHOW_SIGNATURES petition entry: '%u'", petitionguid_low); + + WorldPacket data(SMSG_PETITION_SHOW_SIGNATURES, (8+8+4+1+signs*12)); + data << petitionguid; // petition guid + data << _player->GetGUID(); // owner guid + data << petitionguid_low; // guild guid (in mangos always same as GUID_LOPART(petitionguid) + data << signs; // sign's count + + for(uint8 i = 1; i <= signs; i++) + { + Field *fields = result->Fetch(); + uint64 plguid = fields[0].GetUInt64(); + + data << plguid; // Player GUID + data << (uint32)0; // there 0 ... + + result->NextRow(); + } + delete result; + SendPacket(&data); +} + +void WorldSession::HandlePetitionQueryOpcode(WorldPacket & recv_data) +{ + CHECK_PACKET_SIZE(recv_data, 4+8); + + sLog.outDebug("Received opcode CMSG_PETITION_QUERY"); // ok + //recv_data.hexlike(); + + uint32 guildguid; + uint64 petitionguid; + recv_data >> guildguid; // in mangos always same as GUID_LOPART(petitionguid) + recv_data >> petitionguid; // petition guid + sLog.outDebug("CMSG_PETITION_QUERY Petition GUID %u Guild GUID %u", GUID_LOPART(petitionguid), guildguid); + + SendPetitionQueryOpcode(petitionguid); +} + +void WorldSession::SendPetitionQueryOpcode(uint64 petitionguid) +{ + uint64 ownerguid = 0; + uint32 type; + std::string name = "NO_NAME_FOR_GUID"; + uint8 signs = 0; + + QueryResult *result = CharacterDatabase.PQuery( + "SELECT ownerguid, name, " + " (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs " + "FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid), GUID_LOPART(petitionguid)); + + if(result) + { + Field* fields = result->Fetch(); + ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); + name = fields[1].GetCppString(); + signs = fields[2].GetUInt8(); + delete result; + } + else + { + sLog.outDebug("CMSG_PETITION_QUERY failed for petition (GUID: %u)", GUID_LOPART(petitionguid)); + return; + } + + QueryResult *result2 = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); + + if(result2) + { + Field* fields = result2->Fetch(); + type = fields[0].GetUInt32(); + delete result2; + } + else + { + sLog.outDebug("CMSG_PETITION_QUERY failed for petition (GUID: %u)", GUID_LOPART(petitionguid)); + return; + } + + WorldPacket data(SMSG_PETITION_QUERY_RESPONSE, (4+8+name.size()+1+1+4*13)); + data << GUID_LOPART(petitionguid); // guild/team guid (in mangos always same as GUID_LOPART(petition guid) + data << ownerguid; // charter owner guid + data << name; // name (guild/arena team) + data << uint8(0); // 1 + if(type == 9) + { + data << uint32(9); + data << uint32(9); + data << uint32(0); // bypass client - side limitation, a different value is needed here for each petition + } + else + { + data << type-1; + data << type-1; + data << type; // bypass client - side limitation, a different value is needed here for each petition + } + data << uint32(0); // 5 + data << uint32(0); // 6 + data << uint32(0); // 7 + data << uint32(0); // 8 + data << uint16(0); // 9 2 bytes field + data << uint32(0); // 10 + data << uint32(0); // 11 + data << uint32(0); // 13 count of next strings? + data << uint32(0); // 14 + if(type == 9) + data << uint32(0); // 15 0 - guild, 1 - arena team + else + data << uint32(1); + SendPacket(&data); +} + +void WorldSession::HandlePetitionRenameOpcode(WorldPacket & recv_data) +{ + CHECK_PACKET_SIZE(recv_data, 8+1); + + sLog.outDebug("Received opcode MSG_PETITION_RENAME"); // ok + //recv_data.hexlike(); + + uint64 petitionguid; + uint32 type; + std::string newname; + + recv_data >> petitionguid; // guid + recv_data >> newname; // new name + + Item *item = _player->GetItemByGuid(petitionguid); + if(!item) + return; + + QueryResult *result2 = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); + + if(result2) + { + Field* fields = result2->Fetch(); + type = fields[0].GetUInt32(); + delete result2; + } + else + { + sLog.outDebug("CMSG_PETITION_QUERY failed for petition (GUID: %u)", GUID_LOPART(petitionguid)); + return; + } + + if(type == 9) + { + if(objmgr.GetGuildByName(newname)) + { + SendGuildCommandResult(GUILD_CREATE_S, newname, GUILD_NAME_EXISTS); + return; + } + if(objmgr.IsReservedName(newname)) + { + SendGuildCommandResult(GUILD_CREATE_S, newname, GUILD_NAME_INVALID); + return; + } + if(!ObjectMgr::IsValidCharterName(newname)) + { + SendGuildCommandResult(GUILD_CREATE_S, newname, GUILD_NAME_INVALID); + return; + } + } + else + { + if(objmgr.GetArenaTeamByName(newname)) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newname, "", ERR_ARENA_TEAM_NAME_EXISTS_S); + return; + } + if(objmgr.IsReservedName(newname)) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newname, "", ERR_ARENA_TEAM_NAME_INVALID); + return; + } + if(!ObjectMgr::IsValidCharterName(newname)) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newname, "", ERR_ARENA_TEAM_NAME_INVALID); + return; + } + } + + std::string db_newname = newname; + CharacterDatabase.escape_string(db_newname); + CharacterDatabase.PExecute("UPDATE petition SET name = '%s' WHERE petitionguid = '%u'", + db_newname.c_str(), GUID_LOPART(petitionguid)); + + sLog.outDebug("Petition (GUID: %u) renamed to '%s'", GUID_LOPART(petitionguid), newname.c_str()); + WorldPacket data(MSG_PETITION_RENAME, (8+newname.size()+1)); + data << petitionguid; + data << newname; + SendPacket(&data); +} + +void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data) +{ + CHECK_PACKET_SIZE(recv_data, 8+1); + + sLog.outDebug("Received opcode CMSG_PETITION_SIGN"); // ok + //recv_data.hexlike(); + + Field *fields; + uint64 petitionguid; + uint32 type; + uint8 unk; + uint64 ownerguid; + recv_data >> petitionguid; // petition guid + recv_data >> unk; + + uint8 signs = 0; + + QueryResult *result = CharacterDatabase.PQuery( + "SELECT ownerguid, " + " (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs " + "FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid), GUID_LOPART(petitionguid)); + + if(!result) + { + sLog.outError("any petition on server..."); + return; + } + + fields = result->Fetch(); + ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); + signs = fields[1].GetUInt8(); + + delete result; + + uint32 plguidlo = _player->GetGUIDLow(); + if(GUID_LOPART(ownerguid) == plguidlo) + return; + + // not let enemies sign guild charter + if(!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != objmgr.GetPlayerTeamByGUID(ownerguid)) + return; + + QueryResult *result2 = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); + + if(result2) + { + Field* fields = result2->Fetch(); + type = fields[0].GetUInt32(); + delete result2; + } + else + { + sLog.outDebug("CMSG_PETITION_QUERY failed for petition (GUID: %u)", GUID_LOPART(petitionguid)); + return; + } + + if(type != 9 && _player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + { + // player is too low level to join an arena team + SendNotification("You must be level %u to join an arena team!",sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); + return; + } + + signs += 1; + if(signs > type) // client signs maximum + return; + + //client doesn't allow to sign petition two times by one character, but not check sign by another character from same account + //not allow sign another player from already sign player account + result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE player_account = '%u' AND petitionguid = '%u'", GetAccountId(), GUID_LOPART(petitionguid)); + + if(result) + { + delete result; + WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8+8+4)); + data << petitionguid; + data << _player->GetGUID(); + data << (uint32)PETITION_SIGN_ALREADY_SIGNED; + + // close at signer side + SendPacket(&data); + + // update for owner if online + if(Player *owner = objmgr.GetPlayer(ownerguid)) + owner->GetSession()->SendPacket(&data); + return; + } + + CharacterDatabase.PExecute("INSERT INTO petition_sign (ownerguid,petitionguid, playerguid, player_account) VALUES ('%u', '%u', '%u','%u')", GUID_LOPART(ownerguid),GUID_LOPART(petitionguid), plguidlo,GetAccountId()); + + sLog.outDebug("PETITION SIGN: GUID %u by player: %s (GUID: %u Account: %u)", GUID_LOPART(petitionguid), _player->GetName(),plguidlo,GetAccountId()); + + WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8+8+4)); + data << petitionguid; + data << _player->GetGUID(); + data << (uint32)PETITION_SIGN_OK; + + // close at signer side + SendPacket(&data); + + // update signs count on charter, required testing... + //Item *item = _player->GetItemByGuid(petitionguid)); + //if(item) + // item->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+1, signs); + + // update for owner if online + if(Player *owner = objmgr.GetPlayer(ownerguid)) + owner->GetSession()->SendPacket(&data); +} + +void WorldSession::HandlePetitionDeclineOpcode(WorldPacket & recv_data) +{ + CHECK_PACKET_SIZE(recv_data, 8); + + sLog.outDebug("Received opcode MSG_PETITION_DECLINE"); // ok + //recv_data.hexlike(); + + uint64 petitionguid; + uint64 ownerguid; + recv_data >> petitionguid; // petition guid + sLog.outDebug("Petition %u declined by %u", GUID_LOPART(petitionguid), _player->GetGUIDLow()); + + QueryResult *result = CharacterDatabase.PQuery("SELECT ownerguid FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); + if(!result) + return; + + Field *fields = result->Fetch(); + ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); + delete result; + + Player *owner = objmgr.GetPlayer(ownerguid); + if(owner) // petition owner online + { + WorldPacket data(MSG_PETITION_DECLINE, 8); + data << _player->GetGUID(); + owner->GetSession()->SendPacket(&data); + } +} + +void WorldSession::HandleOfferPetitionOpcode(WorldPacket & recv_data) +{ + CHECK_PACKET_SIZE(recv_data, 4+8+8); + + sLog.outDebug("Received opcode CMSG_OFFER_PETITION"); // ok + //recv_data.hexlike(); + + uint8 signs = 0; + uint64 petitionguid, plguid; + uint32 petitiontype; + Player *player; + recv_data >> petitiontype; // 2.0.8 - petition type? + recv_data >> petitionguid; // petition guid + recv_data >> plguid; // player guid + sLog.outDebug("OFFER PETITION: type %u, GUID1 %u, to player id: %u", petitiontype, GUID_LOPART(petitionguid), GUID_LOPART(plguid)); + + player = ObjectAccessor::FindPlayer(plguid); + if(!player || player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow())) + return; + + // not let offer to enemies + if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != player->GetTeam() ) + return; + + QueryResult *result = CharacterDatabase.PQuery("SELECT petitionguid FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); + if(!result) + { + sLog.outError("any petition on server..."); + return; + } + + delete result; + + result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); + // result==NULL also correct charter without signs + if(result) + signs = result->GetRowCount(); + + WorldPacket data(SMSG_PETITION_SHOW_SIGNATURES, (8+8+4+signs+signs*12)); + data << petitionguid; // petition guid + data << _player->GetGUID(); // owner guid + data << GUID_LOPART(petitionguid); // guild guid (in mangos always same as GUID_LOPART(petition guid) + data << signs; // sign's count + + for(uint8 i = 1; i <= signs; i++) + { + Field *fields = result->Fetch(); + uint64 plguid = fields[0].GetUInt64(); + + data << plguid; // Player GUID + data << (uint32)0; // there 0 ... + + result->NextRow(); + } + + delete result; + player->GetSession()->SendPacket(&data); +} + +void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recv_data) +{ + CHECK_PACKET_SIZE(recv_data, 8); + + sLog.outDebug("Received opcode CMSG_TURN_IN_PETITION"); // ok + //recv_data.hexlike(); + + WorldPacket data; + uint64 petitionguid; + + uint32 ownerguidlo; + uint32 type; + std::string name; + + recv_data >> petitionguid; + + sLog.outDebug("Petition %u turned in by %u", GUID_LOPART(petitionguid), _player->GetGUIDLow()); + + // data + QueryResult *result = CharacterDatabase.PQuery("SELECT ownerguid, name, type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); + if(result) + { + Field *fields = result->Fetch(); + ownerguidlo = fields[0].GetUInt32(); + name = fields[1].GetCppString(); + type = fields[2].GetUInt32(); + delete result; + } + else + { + sLog.outError("petition table has broken data!"); + return; + } + + if(type == 9) + { + if(_player->GetGuildId()) + { + data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); + data << (uint32)PETITION_TURN_ALREADY_IN_GUILD; // already in guild + _player->GetSession()->SendPacket(&data); + return; + } + } + else + { + uint8 slot = ArenaTeam::GetSlotByType(type); + if(slot >= MAX_ARENA_SLOT) + return; + + if(_player->GetArenaTeamId(slot)) + { + //data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); + //data << (uint32)PETITION_TURN_ALREADY_IN_GUILD; // already in guild + //_player->GetSession()->SendPacket(&data); + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM); + return; + } + } + + if(_player->GetGUIDLow() != ownerguidlo) + return; + + // signs + uint8 signs; + result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); + if(result) + signs = result->GetRowCount(); + else + signs = 0; + + uint32 count; + //if(signs < sWorld.getConfig(CONFIG_MIN_PETITION_SIGNS)) + if(type == 9) + count = sWorld.getConfig(CONFIG_MIN_PETITION_SIGNS); + else + count = type-1; + if(signs < count) + { + data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); + data << (uint32)PETITION_TURN_NEED_MORE_SIGNATURES; // need more signatures... + SendPacket(&data); + delete result; + return; + } + + if(type == 9) + { + if(objmgr.GetGuildByName(name)) + { + SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_EXISTS); + delete result; + return; + } + } + else + { + if(objmgr.GetArenaTeamByName(name)) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S); + delete result; + return; + } + } + + // and at last charter item check + Item *item = _player->GetItemByGuid(petitionguid); + if(!item) + { + delete result; + return; + } + + // OK! + + // delete charter item + _player->DestroyItem(item->GetBagSlot(),item->GetSlot(), true); + + if(type == 9) // create guild + { + Guild* guild = new Guild; + if(!guild->create(_player->GetGUID(), name)) + { + delete guild; + delete result; + return; + } + + // register guild and add guildmaster + objmgr.AddGuild(guild); + + // add members + for(uint8 i = 0; i < signs; ++i) + { + Field* fields = result->Fetch(); + guild->AddMember(fields[0].GetUInt64(), guild->GetLowestRank()); + result->NextRow(); + } + } + else // or arena team + { + ArenaTeam* at = new ArenaTeam; + if(!at->create(_player->GetGUID(), type, name)) + { + sLog.outError("PetitionsHandler: arena team create failed."); + delete at; + delete result; + return; + } + + CHECK_PACKET_SIZE(recv_data, 8+5*4); + uint32 icon, iconcolor, border, bordercolor, backgroud; + recv_data >> backgroud >> icon >> iconcolor >> border >> bordercolor; + + at->SetEmblem(backgroud, icon, iconcolor, border, bordercolor); + + // register team and add captain + objmgr.AddArenaTeam(at); + sLog.outDebug("PetitonsHandler: arena team added to objmrg"); + + // add members + for(uint8 i = 0; i < signs; ++i) + { + Field* fields = result->Fetch(); + sLog.outDebug("PetitionsHandler: adding arena member %u", fields[0].GetUInt64()); + at->AddMember(fields[0].GetUInt64()); + result->NextRow(); + } + } + + delete result; + + CharacterDatabase.BeginTransaction(); + CharacterDatabase.PExecute("DELETE FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); + CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); + CharacterDatabase.CommitTransaction(); + + // created + sLog.outDebug("TURN IN PETITION GUID %u", GUID_LOPART(petitionguid)); + + data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); + data << (uint32)PETITION_TURN_OK; + SendPacket(&data); +} + +void WorldSession::HandlePetitionShowListOpcode(WorldPacket & recv_data) +{ + CHECK_PACKET_SIZE(recv_data, 8); + + sLog.outDebug("Received CMSG_PETITION_SHOWLIST"); // ok + //recv_data.hexlike(); + + uint64 guid; + recv_data >> guid; + + SendPetitionShowList(guid); +} + +void WorldSession::SendPetitionShowList(uint64 guid) +{ + Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_PETITIONER); + if (!pCreature) + { + sLog.outDebug("WORLD: HandlePetitionShowListOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); + return; + } + + // remove fake death + if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + uint8 count = 0; + if(pCreature->isTabardDesigner()) + count = 1; + else + count = 3; + + WorldPacket data(SMSG_PETITION_SHOWLIST, 8+1+4*6); + data << guid; // npc guid + data << count; // count + if(count == 1) + { + data << uint32(1); // index + data << uint32(GUILD_CHARTER); // charter entry + data << uint32(16161); // charter display id + data << uint32(GUILD_CHARTER_COST); // charter cost + data << uint32(0); // unknown + data << uint32(9); // required signs? + } + else + { + // 2v2 + data << uint32(1); // index + data << uint32(ARENA_TEAM_CHARTER_2v2); // charter entry + data << uint32(16161); // charter display id + data << uint32(ARENA_TEAM_CHARTER_2v2_COST); // charter cost + data << uint32(2); // unknown + data << uint32(2); // required signs? + // 3v3 + data << uint32(2); // index + data << uint32(ARENA_TEAM_CHARTER_3v3); // charter entry + data << uint32(16161); // charter display id + data << uint32(ARENA_TEAM_CHARTER_3v3_COST); // charter cost + data << uint32(3); // unknown + data << uint32(3); // required signs? + // 5v5 + data << uint32(3); // index + data << uint32(ARENA_TEAM_CHARTER_5v5); // charter entry + data << uint32(16161); // charter display id + data << uint32(ARENA_TEAM_CHARTER_5v5_COST); // charter cost + data << uint32(5); // unknown + data << uint32(5); // required signs? + } + //for(uint8 i = 0; i < count; i++) + //{ + // data << uint32(i); // index + // data << uint32(GUILD_CHARTER); // charter entry + // data << uint32(16161); // charter display id + // data << uint32(GUILD_CHARTER_COST+i); // charter cost + // data << uint32(0); // unknown + // data << uint32(9); // required signs? + //} + SendPacket(&data); + sLog.outDebug("Sent SMSG_PETITION_SHOWLIST"); +} diff --git a/src/game/Player.cpp b/src/game/Player.cpp new file mode 100644 index 00000000000..f93b44ba732 --- /dev/null +++ b/src/game/Player.cpp @@ -0,0 +1,18130 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Language.h" +#include "Database/DatabaseEnv.h" +#include "Log.h" +#include "Opcodes.h" +#include "ObjectMgr.h" +#include "SpellMgr.h" +#include "World.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "UpdateMask.h" +#include "Player.h" +#include "SkillDiscovery.h" +#include "QuestDef.h" +#include "GossipDef.h" +#include "UpdateData.h" +#include "Channel.h" +#include "ChannelMgr.h" +#include "MapManager.h" +#include "MapInstanced.h" +#include "InstanceSaveMgr.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" +#include "CellImpl.h" +#include "ObjectMgr.h" +#include "ObjectAccessor.h" +#include "CreatureAI.h" +#include "Formulas.h" +#include "Group.h" +#include "Guild.h" +#include "Pet.h" +#include "SpellAuras.h" +#include "Util.h" +#include "Transports.h" +#include "Weather.h" +#include "BattleGround.h" +#include "BattleGroundMgr.h" +#include "ArenaTeam.h" +#include "Chat.h" +#include "Database/DatabaseImpl.h" +#include "Spell.h" +#include "SocialMgr.h" + +#include + +#define ZONE_UPDATE_INTERVAL 1000 + +#define PLAYER_SKILL_INDEX(x) (PLAYER_SKILL_INFO_1_1 + ((x)*3)) +#define PLAYER_SKILL_VALUE_INDEX(x) (PLAYER_SKILL_INDEX(x)+1) +#define PLAYER_SKILL_BONUS_INDEX(x) (PLAYER_SKILL_INDEX(x)+2) + +#define SKILL_VALUE(x) PAIR32_LOPART(x) +#define SKILL_MAX(x) PAIR32_HIPART(x) +#define MAKE_SKILL_VALUE(v, m) MAKE_PAIR32(v,m) + +#define SKILL_TEMP_BONUS(x) int16(PAIR32_LOPART(x)) +#define SKILL_PERM_BONUS(x) int16(PAIR32_HIPART(x)) +#define MAKE_SKILL_BONUS(t, p) MAKE_PAIR32(t,p) + +enum CharacterFlags +{ + CHARACTER_FLAG_NONE = 0x00000000, + CHARACTER_FLAG_UNK1 = 0x00000001, + CHARACTER_FLAG_UNK2 = 0x00000002, + CHARACTER_LOCKED_FOR_TRANSFER = 0x00000004, + CHARACTER_FLAG_UNK4 = 0x00000008, + CHARACTER_FLAG_UNK5 = 0x00000010, + CHARACTER_FLAG_UNK6 = 0x00000020, + CHARACTER_FLAG_UNK7 = 0x00000040, + CHARACTER_FLAG_UNK8 = 0x00000080, + CHARACTER_FLAG_UNK9 = 0x00000100, + CHARACTER_FLAG_UNK10 = 0x00000200, + CHARACTER_FLAG_HIDE_HELM = 0x00000400, + CHARACTER_FLAG_HIDE_CLOAK = 0x00000800, + CHARACTER_FLAG_UNK13 = 0x00001000, + CHARACTER_FLAG_GHOST = 0x00002000, + CHARACTER_FLAG_RENAME = 0x00004000, + CHARACTER_FLAG_UNK16 = 0x00008000, + CHARACTER_FLAG_UNK17 = 0x00010000, + CHARACTER_FLAG_UNK18 = 0x00020000, + CHARACTER_FLAG_UNK19 = 0x00040000, + CHARACTER_FLAG_UNK20 = 0x00080000, + CHARACTER_FLAG_UNK21 = 0x00100000, + CHARACTER_FLAG_UNK22 = 0x00200000, + CHARACTER_FLAG_UNK23 = 0x00400000, + CHARACTER_FLAG_UNK24 = 0x00800000, + CHARACTER_FLAG_LOCKED_BY_BILLING = 0x01000000, + CHARACTER_FLAG_DECLINED = 0x02000000, + CHARACTER_FLAG_UNK27 = 0x04000000, + CHARACTER_FLAG_UNK28 = 0x08000000, + CHARACTER_FLAG_UNK29 = 0x10000000, + CHARACTER_FLAG_UNK30 = 0x20000000, + CHARACTER_FLAG_UNK31 = 0x40000000, + CHARACTER_FLAG_UNK32 = 0x80000000 +}; + +// corpse reclaim times +#define DEATH_EXPIRE_STEP (5*MINUTE) +#define MAX_DEATH_COUNT 3 + +static uint32 copseReclaimDelay[MAX_DEATH_COUNT] = { 30, 60, 120 }; + +//== PlayerTaxi ================================================ + +PlayerTaxi::PlayerTaxi() +{ + // Taxi nodes + memset(m_taximask, 0, sizeof(m_taximask)); +} + +void PlayerTaxi::InitTaxiNodesForLevel(uint32 race, uint32 level) +{ + // capital and taxi hub masks + switch(race) + { + case RACE_HUMAN: SetTaximaskNode(2); break; // Human + case RACE_ORC: SetTaximaskNode(23); break; // Orc + case RACE_DWARF: SetTaximaskNode(6); break; // Dwarf + case RACE_NIGHTELF: SetTaximaskNode(26); + SetTaximaskNode(27); break; // Night Elf + case RACE_UNDEAD_PLAYER: SetTaximaskNode(11); break;// Undead + case RACE_TAUREN: SetTaximaskNode(22); break; // Tauren + case RACE_GNOME: SetTaximaskNode(6); break; // Gnome + case RACE_TROLL: SetTaximaskNode(23); break; // Troll + case RACE_BLOODELF: SetTaximaskNode(82); break; // Blood Elf + case RACE_DRAENEI: SetTaximaskNode(94); break; // Draenei + } + // new continent starting masks (It will be accessible only at new map) + switch(Player::TeamForRace(race)) + { + case ALLIANCE: SetTaximaskNode(100); break; + case HORDE: SetTaximaskNode(99); break; + } + // level dependent taxi hubs + if(level>=68) + SetTaximaskNode(213); //Shattered Sun Staging Area +} + +void PlayerTaxi::LoadTaxiMask(const char* data) +{ + Tokens tokens = StrSplit(data, " "); + + int index; + Tokens::iterator iter; + for (iter = tokens.begin(), index = 0; + (index < TaxiMaskSize) && (iter != tokens.end()); ++iter, ++index) + { + // load and set bits only for existed taxi nodes + m_taximask[index] = sTaxiNodesMask[index] & uint32(atol((*iter).c_str())); + } +} + +void PlayerTaxi::AppendTaximaskTo( ByteBuffer& data, bool all ) +{ + if(all) + { + for (uint8 i=0; ic_str())); + AddTaxiDestination(node); + } + + if(m_TaxiDestinations.empty()) + return true; + + // Check integrity + if(m_TaxiDestinations.size() < 2) + return false; + + for(size_t i = 1; i < m_TaxiDestinations.size(); ++i) + { + uint32 cost; + uint32 path; + objmgr.GetTaxiPath(m_TaxiDestinations[i-1],m_TaxiDestinations[i],path,cost); + if(!path) + return false; + } + + return true; +} + +std::string PlayerTaxi::SaveTaxiDestinationsToString() +{ + if(m_TaxiDestinations.empty()) + return ""; + + std::ostringstream ss; + + for(size_t i=0; i < m_TaxiDestinations.size(); ++i) + ss << m_TaxiDestinations[i] << " "; + + return ss.str(); +} + +uint32 PlayerTaxi::GetCurrentTaxiPath() const +{ + if(m_TaxiDestinations.size() < 2) + return 0; + + uint32 path; + uint32 cost; + + objmgr.GetTaxiPath(m_TaxiDestinations[0],m_TaxiDestinations[1],path,cost); + + return path; +} + +//== Player ==================================================== + +const int32 Player::ReputationRank_Length[MAX_REPUTATION_RANK] = {36000, 3000, 3000, 3000, 6000, 12000, 21000, 1000}; + +UpdateMask Player::updateVisualBits; + +Player::Player (WorldSession *session): Unit() +{ + m_transport = 0; + + m_speakTime = 0; + m_speakCount = 0; + + m_objectType |= TYPEMASK_PLAYER; + m_objectTypeId = TYPEID_PLAYER; + + m_valuesCount = PLAYER_END; + + m_session = session; + + m_divider = 0; + + m_ExtraFlags = 0; + if(GetSession()->GetSecurity() >= SEC_GAMEMASTER) + SetAcceptTicket(true); + + // players always and GM if set in config accept whispers by default + if(GetSession()->GetSecurity() == SEC_PLAYER || sWorld.getConfig(CONFIG_GM_WISPERING_TO)) + SetAcceptWhispers(true); + + m_curSelection = 0; + m_lootGuid = 0; + + m_comboTarget = 0; + m_comboPoints = 0; + + m_usedTalentCount = 0; + + m_regenTimer = 0; + m_weaponChangeTimer = 0; + + m_zoneUpdateId = 0; + m_zoneUpdateTimer = 0; + + m_areaUpdateId = 0; + + m_nextSave = sWorld.getConfig(CONFIG_INTERVAL_SAVE); + + // randomize first save time in range [CONFIG_INTERVAL_SAVE] around [CONFIG_INTERVAL_SAVE] + // this must help in case next save after mass player load after server startup + m_nextSave = urand(m_nextSave/2,m_nextSave*3/2); + + clearResurrectRequestData(); + + m_SpellModRemoveCount = 0; + + memset(m_items, 0, sizeof(Item*)*PLAYER_SLOTS_COUNT); + + m_social = NULL; + + // group is initialized in the reference constructor + SetGroupInvite(NULL); + m_groupUpdateMask = 0; + m_auraUpdateMask = 0; + + duel = NULL; + + m_GuildIdInvited = 0; + m_ArenaTeamIdInvited = 0; + + m_atLoginFlags = AT_LOGIN_NONE; + + m_dontMove = false; + + pTrader = 0; + ClearTrade(); + + m_cinematic = 0; + + PlayerTalkClass = new PlayerMenu( GetSession() ); + m_currentBuybackSlot = BUYBACK_SLOT_START; + + for ( int aX = 0 ; aX < 8 ; aX++ ) + m_Tutorials[ aX ] = 0x00; + m_TutorialsChanged = false; + + m_DailyQuestChanged = false; + m_lastDailyQuestTime = 0; + + m_regenTimer = 0; + m_weaponChangeTimer = 0; + m_breathTimer = 0; + m_isunderwater = 0; + m_isInWater = false; + m_drunkTimer = 0; + m_drunk = 0; + m_restTime = 0; + m_deathTimer = 0; + m_deathExpireTime = 0; + + m_swingErrorMsg = 0; + + m_DetectInvTimer = 1000; + + m_bgBattleGroundID = 0; + for (int j=0; j < PLAYER_MAX_BATTLEGROUND_QUEUES; j++) + { + m_bgBattleGroundQueueID[j].bgType = 0; + m_bgBattleGroundQueueID[j].invited = false; + } + m_bgTeam = 0; + + m_logintime = time(NULL); + m_Last_tick = m_logintime; + m_WeaponProficiency = 0; + m_ArmorProficiency = 0; + m_canParry = false; + m_canDualWield = false; + m_ammoDPS = 0.0f; + + m_temporaryUnsummonedPetNumber = 0; + //cache for UNIT_CREATED_BY_SPELL to allow + //returning reagests for temporarily removed pets + //when dying/logging out + m_oldpetspell = 0; + + ////////////////////Rest System///////////////////// + time_inn_enter=0; + inn_pos_mapid=0; + inn_pos_x=0; + inn_pos_y=0; + inn_pos_z=0; + m_rest_bonus=0; + rest_type=REST_TYPE_NO; + ////////////////////Rest System///////////////////// + + m_mailsLoaded = false; + m_mailsUpdated = false; + unReadMails = 0; + m_nextMailDelivereTime = 0; + + m_resetTalentsCost = 0; + m_resetTalentsTime = 0; + m_itemUpdateQueueBlocked = false; + + for (int i = 0; i < MAX_MOVE_TYPE; ++i) + m_forced_speed_changes[i] = 0; + + m_stableSlots = 0; + + /////////////////// Instance System ///////////////////// + + m_HomebindTimer = 0; + m_InstanceValid = true; + m_dungeonDifficulty = DIFFICULTY_NORMAL; + + for (int i = 0; i < BASEMOD_END; i++) + { + m_auraBaseMod[i][FLAT_MOD] = 0.0f; + m_auraBaseMod[i][PCT_MOD] = 1.0f; + } + + // Honor System + m_lastHonorUpdateTime = time(NULL); + + // Player summoning + m_summon_expire = 0; + m_summon_mapid = 0; + m_summon_x = 0.0f; + m_summon_y = 0.0f; + m_summon_z = 0.0f; + + //Default movement to run mode + m_unit_movement_flags = 0; + + m_miniPet = 0; + m_bgAfkReportedTimer = 0; + m_contestedPvPTimer = 0; + + m_declinedname = NULL; +} + +Player::~Player () +{ + CleanupsBeforeDelete(); + + if(m_uint32Values) // only for fully created Object + { + sSocialMgr.RemovePlayerSocial(GetGUIDLow()); + } + + // Note: buy back item already deleted from DB when player was saved + for(int i = 0; i < PLAYER_SLOTS_COUNT; ++i) + { + if(m_items[i]) + delete m_items[i]; + } + CleanupChannels(); + + for (PlayerSpellMap::const_iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr) + delete itr->second; + + //all mailed items should be deleted, also all mail should be deallocated + for (PlayerMails::iterator itr = m_mail.begin(); itr != m_mail.end();++itr) + delete *itr; + + for (ItemMap::iterator iter = mMitems.begin(); iter != mMitems.end(); ++iter) + delete iter->second; //if item is duplicated... then server may crash ... but that item should be deallocated + + delete PlayerTalkClass; + + if (m_transport) + { + m_transport->RemovePassenger(this); + } + + for(size_t x = 0; x < ItemSetEff.size(); x++) + if(ItemSetEff[x]) + delete ItemSetEff[x]; + + // clean up player-instance binds, may unload some instance saves + for(uint8 i = 0; i < TOTAL_DIFFICULTIES; i++) + for(BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end(); ++itr) + itr->second.save->RemovePlayer(this); + + delete m_declinedname; +} + +void Player::CleanupsBeforeDelete() +{ + if(m_uint32Values) // only for fully created Object + { + TradeCancel(false); + DuelComplete(DUEL_INTERUPTED); + } + Unit::CleanupsBeforeDelete(); +} + +bool Player::Create( uint32 guidlow, std::string name, uint8 race, uint8 class_, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair, uint8 outfitId ) +{ + Object::_Create(guidlow, 0, HIGHGUID_PLAYER); + + m_name = name; + + PlayerInfo const* info = objmgr.GetPlayerInfo(race, class_); + if(!info) + { + sLog.outError("Player have incorrect race/class pair. Can't be loaded."); + return false; + } + + for (int i = 0; i < PLAYER_SLOTS_COUNT; i++) + m_items[i] = NULL; + + //for(int j = BUYBACK_SLOT_START; j < BUYBACK_SLOT_END; j++) + //{ + // SetUInt64Value(PLAYER_FIELD_VENDORBUYBACK_SLOT_1+j*2,0); + // SetUInt32Value(PLAYER_FIELD_BUYBACK_PRICE_1+j,0); + // SetUInt32Value(PLAYER_FIELD_BUYBACK_TIMESTAMP_1+j,0); + //} + + m_race = race; + m_class = class_; + + SetMapId(info->mapId); + Relocate(info->positionX,info->positionY,info->positionZ); + + ChrClassesEntry const* cEntry = sChrClassesStore.LookupEntry(class_); + if(!cEntry) + { + sLog.outError("Class %u not found in DBC (Wrong DBC files?)",class_); + return false; + } + + uint8 powertype = cEntry->powerType; + + uint32 unitfield; + + switch(powertype) + { + case POWER_ENERGY: + case POWER_MANA: + unitfield = 0x00000000; + break; + case POWER_RAGE: + unitfield = 0x00110000; + break; + default: + sLog.outError("Invalid default powertype %u for player (class %u)",powertype,class_); + return false; + } + + SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, DEFAULT_WORLD_OBJECT_SIZE ); + SetFloatValue(UNIT_FIELD_COMBATREACH, 1.5f ); + + switch(gender) + { + case GENDER_FEMALE: + SetDisplayId(info->displayId_f ); + SetNativeDisplayId(info->displayId_f ); + break; + case GENDER_MALE: + SetDisplayId(info->displayId_m ); + SetNativeDisplayId(info->displayId_m ); + break; + default: + sLog.outError("Invalid gender %u for player",gender); + return false; + break; + } + + setFactionForRace(m_race); + + SetUInt32Value(UNIT_FIELD_BYTES_0, ( ( race ) | ( class_ << 8 ) | ( gender << 16 ) | ( powertype << 24 ) ) ); + SetUInt32Value(UNIT_FIELD_BYTES_1, unitfield); + SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_UNK3 | UNIT_BYTE2_FLAG_UNK5 ); + SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE ); + SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0f); // fix cast time showed in spell tooltip on client + + //-1 is default value + SetUInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, uint32(-1)); + + SetUInt32Value(PLAYER_BYTES, (skin | (face << 8) | (hairStyle << 16) | (hairColor << 24))); + SetUInt32Value(PLAYER_BYTES_2, (facialHair | (0x00 << 8) | (0x00 << 16) | (0x02 << 24))); + SetByteValue(PLAYER_BYTES_3, 0, gender); + + SetUInt32Value( PLAYER_GUILDID, 0 ); + SetUInt32Value( PLAYER_GUILDRANK, 0 ); + SetUInt32Value( PLAYER_GUILD_TIMESTAMP, 0 ); + + SetUInt64Value( PLAYER__FIELD_KNOWN_TITLES, 0 ); // 0=disabled + SetUInt32Value( PLAYER_CHOSEN_TITLE, 0 ); + SetUInt32Value( PLAYER_FIELD_KILLS, 0 ); + SetUInt32Value( PLAYER_FIELD_LIFETIME_HONORBALE_KILLS, 0 ); + SetUInt32Value( PLAYER_FIELD_TODAY_CONTRIBUTION, 0 ); + SetUInt32Value( PLAYER_FIELD_YESTERDAY_CONTRIBUTION, 0 ); + + // set starting level + SetUInt32Value( UNIT_FIELD_LEVEL, sWorld.getConfig(CONFIG_START_PLAYER_LEVEL) ); + + // Played time + m_Last_tick = time(NULL); + m_Played_time[0] = 0; + m_Played_time[1] = 0; + + // base stats and related field values + InitStatsForLevel(); + InitTaxiNodesForLevel(); + InitTalentForLevel(); + InitPrimaryProffesions(); // to max set before any spell added + + // apply original stats mods before spell loading or item equipment that call before equip _RemoveStatsMods() + UpdateMaxHealth(); // Update max Health (for add bonus from stamina) + SetHealth(GetMaxHealth()); + if (getPowerType()==POWER_MANA) + { + UpdateMaxPower(POWER_MANA); // Update max Mana (for add bonus from intelect) + SetPower(POWER_MANA,GetMaxPower(POWER_MANA)); + } + + learnDefaultSpells(true); + + std::list::const_iterator action_itr[4]; + for(int i=0; i<4; i++) + action_itr[i] = info->action[i].begin(); + + for (; action_itr[0]!=info->action[0].end() && action_itr[1]!=info->action[1].end();) + { + uint16 taction[4]; + for(int i=0; i<4 ;i++) + taction[i] = (*action_itr[i]); + + addActionButton((uint8)taction[0], taction[1], (uint8)taction[2], (uint8)taction[3]); + + for(int i=0; i<4 ;i++) + ++action_itr[i]; + } + + UpdateBlockPercentage(); + + for (PlayerCreateInfoItems::const_iterator item_id_itr = info->item.begin(); item_id_itr!=info->item.end(); ++item_id_itr++) + { + uint32 titem_id = item_id_itr->item_id; + uint32 titem_amount = item_id_itr->item_amount; + + sLog.outDebug("STORAGE: Creating initial item, itemId = %u, count = %u",titem_id, titem_amount); + + // attempt equip + uint16 eDest; + uint8 msg = CanEquipNewItem( NULL_SLOT, eDest, titem_id, titem_amount, false ); + if( msg == EQUIP_ERR_OK ) + { + EquipNewItem( eDest, titem_id, titem_amount, true); + AutoUnequipOffhandIfNeed(); + continue; // equipped, to next + } + + // attempt store + ItemPosCountVec sDest; + // store in main bag to simplify second pass (special bags can be not equipped yet at this moment) + msg = CanStoreNewItem( INVENTORY_SLOT_BAG_0, NULL_SLOT, sDest, titem_id, titem_amount ); + if( msg == EQUIP_ERR_OK ) + { + StoreNewItem( sDest, titem_id, true, Item::GenerateItemRandomPropertyId(titem_id) ); + continue; // stored, to next + } + + // item can't be added + sLog.outError("STORAGE: Can't equip or store initial item %u for race %u class %u , error msg = %u",titem_id,race,class_,msg); + } + + // bags and main-hand weapon must equipped at this moment + // now second pass for not equipped (offhand weapon/shield if it attempt equipped before main-hand weapon) + // or ammo not equipped in special bag + for(int i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++) + { + if(Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i )) + { + uint16 eDest; + // equip offhand weapon/shield if it attempt equipped before main-hand weapon + uint8 msg = CanEquipItem( NULL_SLOT, eDest, pItem, false ); + if( msg == EQUIP_ERR_OK ) + { + RemoveItem(INVENTORY_SLOT_BAG_0, i,true); + EquipItem( eDest, pItem, true); + } + // move other items to more appropriate slots (ammo not equipped in special bag) + else + { + ItemPosCountVec sDest; + msg = CanStoreItem( NULL_BAG, NULL_SLOT, sDest, pItem, false ); + if( msg == EQUIP_ERR_OK ) + { + RemoveItem(INVENTORY_SLOT_BAG_0, i,true); + pItem = StoreItem( sDest, pItem, true); + } + + // if this is ammo then use it + uint8 msg = CanUseAmmo( pItem->GetProto()->ItemId ); + if( msg == EQUIP_ERR_OK ) + SetAmmo( pItem->GetProto()->ItemId ); + } + } + } + // all item positions resolved + + return true; +} + +void Player::StartMirrorTimer(MirrorTimerType Type, uint32 MaxValue) +{ + uint32 BreathRegen = (uint32)-1; + + WorldPacket data(SMSG_START_MIRROR_TIMER, (21)); + data << (uint32)Type; + data << MaxValue; + data << MaxValue; + data << BreathRegen; + data << (uint8)0; + data << (uint32)0; // spell id + GetSession()->SendPacket(&data); +} + +void Player::ModifyMirrorTimer(MirrorTimerType Type, uint32 MaxValue, uint32 CurrentValue, uint32 Regen) +{ + if(Type==BREATH_TIMER) + m_breathTimer = ((MaxValue + 1000) - CurrentValue) / Regen; + + WorldPacket data(SMSG_START_MIRROR_TIMER, (21)); + data << (uint32)Type; + data << CurrentValue; + data << MaxValue; + data << Regen; + data << (uint8)0; + data << (uint32)0; // spell id + GetSession()->SendPacket( &data ); +} + +void Player::StopMirrorTimer(MirrorTimerType Type) +{ + if(Type==BREATH_TIMER) + m_breathTimer = 0; + + WorldPacket data(SMSG_STOP_MIRROR_TIMER, 4); + data << (uint32)Type; + GetSession()->SendPacket( &data ); +} + +void Player::EnvironmentalDamage(uint64 guid, EnviromentalDamage type, uint32 damage) +{ + WorldPacket data(SMSG_ENVIRONMENTALDAMAGELOG, (21)); + data << (uint64)guid; + data << (uint8)(type!=DAMAGE_FALL_TO_VOID ? type : DAMAGE_FALL); + data << (uint32)damage; + data << (uint32)0; + data << (uint32)0; + //m_session->SendPacket(&data); + //Let other players see that you get damage + SendMessageToSet(&data, true); + DealDamage(this, damage, NULL, SELF_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + + if(type==DAMAGE_FALL && !isAlive()) // DealDamage not apply item durability loss at self damage + { + DEBUG_LOG("We are fall to death, loosing 10 percents durability"); + DurabilityLossAll(0.10f,false); + // durability lost message + WorldPacket data(SMSG_DURABILITY_DAMAGE_DEATH, 0); + GetSession()->SendPacket(&data); + } +} + +void Player::HandleDrowning() +{ + if(!m_isunderwater) + return; + + //if have water breath , then remove bar + if(waterbreath || isGameMaster() || !isAlive()) + { + StopMirrorTimer(BREATH_TIMER); + m_isunderwater = 0; + return; + } + + uint32 UnderWaterTime = 1*MINUTE*1000; // default leangthL 1 min + + AuraList const& mModWaterBreathing = GetAurasByType(SPELL_AURA_MOD_WATER_BREATHING); + for(AuraList::const_iterator i = mModWaterBreathing.begin(); i != mModWaterBreathing.end(); ++i) + UnderWaterTime = uint32(UnderWaterTime * (100.0f + (*i)->GetModifier()->m_amount) / 100.0f); + + if ((m_isunderwater & 0x01) && !(m_isunderwater & 0x80) && isAlive()) + { + //single trigger timer + if (!(m_isunderwater & 0x02)) + { + m_isunderwater|= 0x02; + m_breathTimer = UnderWaterTime + 1000; + } + //single trigger "Breathbar" + if ( m_breathTimer <= UnderWaterTime && !(m_isunderwater & 0x04)) + { + m_isunderwater|= 0x04; + StartMirrorTimer(BREATH_TIMER, UnderWaterTime); + } + //continius trigger drowning "Damage" + if ((m_breathTimer == 0) && (m_isunderwater & 0x01)) + { + //TODO: Check this formula + uint64 guid = GetGUID(); + uint32 damage = GetMaxHealth() / 5 + urand(0, getLevel()-1); + + EnvironmentalDamage(guid, DAMAGE_DROWNING,damage); + m_breathTimer = 2000; + } + } + //single trigger retract bar + else if (!(m_isunderwater & 0x01) && !(m_isunderwater & 0x08) && (m_isunderwater & 0x02) && (m_breathTimer > 0) && isAlive()) + { + m_isunderwater = 0x08; + + uint32 BreathRegen = 10; + ModifyMirrorTimer(BREATH_TIMER, UnderWaterTime, m_breathTimer,BreathRegen); + m_isunderwater = 0x10; + } + //remove bar + else if ((m_breathTimer < 50) && !(m_isunderwater & 0x01) && (m_isunderwater == 0x10)) + { + StopMirrorTimer(BREATH_TIMER); + m_isunderwater = 0; + } +} + +void Player::HandleLava() +{ + bool ValidArea = false; + + if ((m_isunderwater & 0x80) && isAlive()) + { + //Single trigger Set BreathTimer + if (!(m_isunderwater & 0x80)) + { + m_isunderwater|= 0x04; + m_breathTimer = 1000; + } + //Reset BreathTimer and still in the lava + if (!m_breathTimer) + { + uint64 guid = GetGUID(); + uint32 damage = urand(600, 700); // TODO: Get more detailed information about lava damage + uint32 dmgZone = GetZoneId(); // TODO: Find correct "lava dealing zone" flag in Area Table + + // Deal lava damage only in lava zones. + switch(dmgZone) + { + case 0x8D: + ValidArea = false; + break; + case 0x94: + ValidArea = false; + break; + case 0x2CE: + ValidArea = false; + break; + case 0x2CF: + ValidArea = false; + break; + default: + if (dmgZone / 5 & 0x408) + ValidArea = true; + } + + // if is valid area and is not gamemaster then deal damage + if ( ValidArea && !isGameMaster() ) + EnvironmentalDamage(guid, DAMAGE_LAVA, damage); + + m_breathTimer = 1000; + } + + } + //Death timer disabled and WaterFlags reset + else if (m_deathState == DEAD) + { + m_breathTimer = 0; + m_isunderwater = 0; + } +} + +///The player sobers by 256 every 10 seconds +void Player::HandleSobering() +{ + m_drunkTimer = 0; + + uint32 drunk = (m_drunk <= 256) ? 0 : (m_drunk - 256); + SetDrunkValue(drunk); +} + +DrunkenState Player::GetDrunkenstateByValue(uint16 value) +{ + if(value >= 23000) + return DRUNKEN_SMASHED; + if(value >= 12800) + return DRUNKEN_DRUNK; + if(value & 0xFFFE) + return DRUNKEN_TIPSY; + return DRUNKEN_SOBER; +} + +void Player::SetDrunkValue(uint16 newDrunkenValue, uint32 itemId) +{ + uint32 oldDrunkenState = Player::GetDrunkenstateByValue(m_drunk); + + m_drunk = newDrunkenValue; + SetUInt32Value(PLAYER_BYTES_3,(GetUInt32Value(PLAYER_BYTES_3) & 0xFFFF0001) | (m_drunk & 0xFFFE)); + + uint32 newDrunkenState = Player::GetDrunkenstateByValue(m_drunk); + + // special drunk invisibility detection + if(newDrunkenState >= DRUNKEN_DRUNK) + m_detectInvisibilityMask |= (1<<6); + else + m_detectInvisibilityMask &= ~(1<<6); + + if(newDrunkenState == oldDrunkenState) + return; + + WorldPacket data(SMSG_CROSSED_INEBRIATION_THRESHOLD, (8+4+4)); + data << GetGUID(); + data << uint32(newDrunkenState); + data << uint32(itemId); + + SendMessageToSet(&data, true); +} + +void Player::Update( uint32 p_time ) +{ + if(!IsInWorld()) + return; + + // undelivered mail + if(m_nextMailDelivereTime && m_nextMailDelivereTime <= time(NULL)) + { + SendNewMail(); + ++unReadMails; + + // It will be recalculate at mailbox open (for unReadMails important non-0 until mailbox open, it also will be recalculated) + m_nextMailDelivereTime = 0; + } + + Unit::Update( p_time ); + + // update player only attacks + if(uint32 ranged_att = getAttackTimer(RANGED_ATTACK)) + { + setAttackTimer(RANGED_ATTACK, (p_time >= ranged_att ? 0 : ranged_att - p_time) ); + } + + if(uint32 off_att = getAttackTimer(OFF_ATTACK)) + { + setAttackTimer(OFF_ATTACK, (p_time >= off_att ? 0 : off_att - p_time) ); + } + + time_t now = time (NULL); + + UpdatePvPFlag(now); + + UpdateContestedPvP(p_time); + + UpdateDuelFlag(now); + + CheckDuelDistance(now); + + UpdateAfkReport(now); + + CheckExploreSystem(); + + // Update items that have just a limited lifetime + if (now>m_Last_tick) + UpdateItemDuration(uint32(now- m_Last_tick)); + + if (!m_timedquests.empty()) + { + std::set::iterator iter = m_timedquests.begin(); + while (iter != m_timedquests.end()) + { + QuestStatusData& q_status = mQuestStatus[*iter]; + if( q_status.m_timer <= p_time ) + { + uint32 quest_id = *iter; + ++iter; // current iter will be removed in FailTimedQuest + FailTimedQuest( quest_id ); + } + else + { + q_status.m_timer -= p_time; + if (q_status.uState != QUEST_NEW) q_status.uState = QUEST_CHANGED; + ++iter; + } + } + } + + if (hasUnitState(UNIT_STAT_MELEE_ATTACKING)) + { + Unit *pVictim = getVictim(); + if( !IsNonMeleeSpellCasted(false) && pVictim) + { + // default combat reach 10 + // TODO add weapon,skill check + + float pldistance = ATTACK_DISTANCE; + + if (isAttackReady(BASE_ATTACK)) + { + if(!IsWithinDistInMap(pVictim, pldistance)) + { + setAttackTimer(BASE_ATTACK,100); + if(m_swingErrorMsg != 1) // send single time (client auto repeat) + { + SendAttackSwingNotInRange(); + m_swingErrorMsg = 1; + } + } + //120 degrees of radiant range + else if( !HasInArc( 2*M_PI/3, pVictim )) + { + setAttackTimer(BASE_ATTACK,100); + if(m_swingErrorMsg != 2) // send single time (client auto repeat) + { + SendAttackSwingBadFacingAttack(); + m_swingErrorMsg = 2; + } + } + else + { + m_swingErrorMsg = 0; // reset swing error state + + // prevent base and off attack in same time, delay attack at 0.2 sec + if(haveOffhandWeapon()) + { + uint32 off_att = getAttackTimer(OFF_ATTACK); + if(off_att < ATTACK_DISPLAY_DELAY) + setAttackTimer(OFF_ATTACK,ATTACK_DISPLAY_DELAY); + } + AttackerStateUpdate(pVictim, BASE_ATTACK); + resetAttackTimer(BASE_ATTACK); + } + } + + if ( haveOffhandWeapon() && isAttackReady(OFF_ATTACK)) + { + if(!IsWithinDistInMap(pVictim, pldistance)) + { + setAttackTimer(OFF_ATTACK,100); + } + else if( !HasInArc( 2*M_PI/3, pVictim )) + { + setAttackTimer(OFF_ATTACK,100); + } + else + { + // prevent base and off attack in same time, delay attack at 0.2 sec + uint32 base_att = getAttackTimer(BASE_ATTACK); + if(base_att < ATTACK_DISPLAY_DELAY) + setAttackTimer(BASE_ATTACK,ATTACK_DISPLAY_DELAY); + // do attack + AttackerStateUpdate(pVictim, OFF_ATTACK); + resetAttackTimer(OFF_ATTACK); + } + } + + Unit *owner = pVictim->GetOwner(); + Unit *u = owner ? owner : pVictim; + if(u->IsPvP() && (!duel || duel->opponent != u)) + { + UpdatePvP(true); + RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); + } + } + } + + if(HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING)) + { + if(roll_chance_i(3) && GetTimeInnEnter() > 0) //freeze update + { + int time_inn = time(NULL)-GetTimeInnEnter(); + if (time_inn >= 10) //freeze update + { + float bubble = 0.125*sWorld.getRate(RATE_REST_INGAME); + //speed collect rest bonus (section/in hour) + SetRestBonus( GetRestBonus()+ time_inn*((float)GetUInt32Value(PLAYER_NEXT_LEVEL_XP)/72000)*bubble ); + UpdateInnerTime(time(NULL)); + } + } + } + + if(m_regenTimer > 0) + { + if(p_time >= m_regenTimer) + m_regenTimer = 0; + else + m_regenTimer -= p_time; + } + + if (m_weaponChangeTimer > 0) + { + if(p_time >= m_weaponChangeTimer) + m_weaponChangeTimer = 0; + else + m_weaponChangeTimer -= p_time; + } + + if (m_zoneUpdateTimer > 0) + { + if(p_time >= m_zoneUpdateTimer) + { + uint32 newzone = GetZoneId(); + if( m_zoneUpdateId != newzone ) + UpdateZone(newzone); // also update area + else + { + // use area updates as well + // needed for free far all arenas for example + uint32 newarea = GetAreaId(); + if( m_areaUpdateId != newarea ) + UpdateArea(newarea); + + m_zoneUpdateTimer = ZONE_UPDATE_INTERVAL; + } + } + else + m_zoneUpdateTimer -= p_time; + } + + if (isAlive()) + { + RegenerateAll(); + } + + if (m_deathState == JUST_DIED) + { + KillPlayer(); + } + + if(m_nextSave > 0) + { + if(p_time >= m_nextSave) + { + // m_nextSave reseted in SaveToDB call + SaveToDB(); + sLog.outDetail("Player '%s' (GUID: %u) saved", GetName(), GetGUIDLow()); + } + else + { + m_nextSave -= p_time; + } + } + + //Breathtimer + if(m_breathTimer > 0) + { + if(p_time >= m_breathTimer) + m_breathTimer = 0; + else + m_breathTimer -= p_time; + + } + + //Handle Water/drowning + HandleDrowning(); + + //Handle lava + HandleLava(); + + //Handle detect stealth players + if (m_DetectInvTimer > 0) + { + if (p_time >= m_DetectInvTimer) + { + m_DetectInvTimer = 3000; + HandleStealthedUnitsDetection(); + } + else + m_DetectInvTimer -= p_time; + } + + // Played time + if (now > m_Last_tick) + { + uint32 elapsed = uint32(now - m_Last_tick); + m_Played_time[0] += elapsed; // Total played time + m_Played_time[1] += elapsed; // Level played time + m_Last_tick = now; + } + + if (m_drunk) + { + m_drunkTimer += p_time; + + if (m_drunkTimer > 10000) + HandleSobering(); + } + + // not auto-free ghost from body in instances + if(m_deathTimer > 0 && !GetBaseMap()->Instanceable()) + { + if(p_time >= m_deathTimer) + { + m_deathTimer = 0; + BuildPlayerRepop(); + RepopAtGraveyard(); + } + else + m_deathTimer -= p_time; + } + + UpdateEnchantTime(p_time); + UpdateHomebindTime(p_time); + + // group update + SendUpdateToOutOfRangeGroupMembers(); + + Pet* pet = GetPet(); + if(pet && !IsWithinDistInMap(pet, OWNER_MAX_DISTANCE)) + { + RemovePet(pet, PET_SAVE_NOT_IN_SLOT, true); + return; + } +} + +void Player::setDeathState(DeathState s) +{ + uint32 ressSpellId = 0; + + bool cur = isAlive(); + + if(s == JUST_DIED && cur) + { + // drunken state is cleared on death + SetDrunkValue(0); + // lost combo points at any target (targeted combo points clear in Unit::setDeathState) + ClearComboPoints(); + + clearResurrectRequestData(); + + // remove form before other mods to prevent incorrect stats calculation + RemoveAurasDueToSpell(m_ShapeShiftFormSpellId); + + //FIXME: is pet dismissed at dying or releasing spirit? if second, add setDeathState(DEAD) to HandleRepopRequestOpcode and define pet unsummon here with (s == DEAD) + RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true); + + // remove uncontrolled pets + RemoveMiniPet(); + RemoveGuardians(); + + // save value before aura remove in Unit::setDeathState + ressSpellId = GetUInt32Value(PLAYER_SELF_RES_SPELL); + + // passive spell + if(!ressSpellId) + ressSpellId = GetResurrectionSpellId(); + } + Unit::setDeathState(s); + + // restore resurrection spell id for player after aura remove + if(s == JUST_DIED && cur && ressSpellId) + SetUInt32Value(PLAYER_SELF_RES_SPELL, ressSpellId); + + if(isAlive() && !cur) + { + //clear aura case after resurrection by another way (spells will be applied before next death) + SetUInt32Value(PLAYER_SELF_RES_SPELL, 0); + + // restore default warrior stance + if(getClass()== CLASS_WARRIOR) + CastSpell(this,SPELL_ID_PASSIVE_BATTLE_STANCE,true); + } +} + +void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data ) +{ + *p_data << GetGUID(); + *p_data << m_name; + + *p_data << getRace(); + uint8 pClass = getClass(); + *p_data << pClass; + *p_data << getGender(); + + uint32 bytes = GetUInt32Value(PLAYER_BYTES); + *p_data << uint8(bytes); + *p_data << uint8(bytes >> 8); + *p_data << uint8(bytes >> 16); + *p_data << uint8(bytes >> 24); + + bytes = GetUInt32Value(PLAYER_BYTES_2); + *p_data << uint8(bytes); + + *p_data << uint8(getLevel()); // player level + // do not use GetMap! it will spawn a new instance since the bound instances are not loaded + uint32 zoneId = MapManager::Instance().GetZoneId(GetMapId(), GetPositionX(),GetPositionY()); + + *p_data << zoneId; + *p_data << GetMapId(); + + *p_data << GetPositionX(); + *p_data << GetPositionY(); + *p_data << GetPositionZ(); + + *p_data << GetUInt32Value(PLAYER_GUILDID); // guild id + + uint32 char_flags = 0; + if(HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_HELM)) + char_flags |= CHARACTER_FLAG_HIDE_HELM; + if(HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_CLOAK)) + char_flags |= CHARACTER_FLAG_HIDE_CLOAK; + if(HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) + char_flags |= CHARACTER_FLAG_GHOST; + if(HasAtLoginFlag(AT_LOGIN_RENAME)) + char_flags |= CHARACTER_FLAG_RENAME; + // always send the flag if declined names aren't used + // to let the client select a default method of declining the name + if(!sWorld.getConfig(CONFIG_DECLINED_NAMES_USED) || (result && result->Fetch()[12].GetCppString() != "")) + char_flags |= CHARACTER_FLAG_DECLINED; + + *p_data << (uint32)char_flags; // character flags + + *p_data << (uint8)1; // unknown + + // Pets info + { + uint32 petDisplayId = 0; + uint32 petLevel = 0; + uint32 petFamily = 0; + + // show pet at selection character in character list only for non-ghost character + if(result && isAlive() && (pClass == CLASS_WARLOCK || pClass == CLASS_HUNTER)) + { + Field* fields = result->Fetch(); + + uint32 entry = fields[9].GetUInt32(); + CreatureInfo const* cInfo = sCreatureStorage.LookupEntry(entry); + if(cInfo) + { + petDisplayId = fields[10].GetUInt32(); + petLevel = fields[11].GetUInt32(); + petFamily = cInfo->family; + } + } + + *p_data << (uint32)petDisplayId; + *p_data << (uint32)petLevel; + *p_data << (uint32)petFamily; + } + + /*ItemPrototype const *items[EQUIPMENT_SLOT_END]; + for (int i = 0; i < EQUIPMENT_SLOT_END; i++) + items[i] = NULL; + + QueryResult *result = CharacterDatabase.PQuery("SELECT slot,item_template FROM character_inventory WHERE guid = '%u' AND bag = 0",GetGUIDLow()); + if (result) + { + do + { + Field *fields = result->Fetch(); + uint8 slot = fields[0].GetUInt8() & 255; + uint32 item_id = fields[1].GetUInt32(); + if( slot >= EQUIPMENT_SLOT_END ) + continue; + + items[slot] = objmgr.GetItemPrototype(item_id); + if(!items[slot]) + { + sLog.outError( "Player::BuildEnumData: Player %s have unknown item (id: #%u) in inventory, skipped.", GetName(),item_id ); + continue; + } + } while (result->NextRow()); + delete result; + }*/ + + for (uint8 slot = 0; slot < EQUIPMENT_SLOT_END; slot++) + { + uint32 visualbase = PLAYER_VISIBLE_ITEM_1_0 + (slot * MAX_VISIBLE_ITEM_OFFSET); + uint32 item_id = GetUInt32Value(visualbase); + const ItemPrototype * proto = objmgr.GetItemPrototype(item_id); + SpellItemEnchantmentEntry const *enchant = NULL; + + for(uint8 enchantSlot = PERM_ENCHANTMENT_SLOT; enchantSlot<=TEMP_ENCHANTMENT_SLOT; enchantSlot++) + { + uint32 enchantId = GetUInt32Value(visualbase+1+enchantSlot); + if(enchant = sSpellItemEnchantmentStore.LookupEntry(enchantId)) + break; + } + + if (proto != NULL) + { + *p_data << (uint32)proto->DisplayInfoID; + *p_data << (uint8)proto->InventoryType; + *p_data << (uint32)(enchant?enchant->aura_id:0); + } + else + { + *p_data << (uint32)0; + *p_data << (uint8)0; + *p_data << (uint32)0; // enchant? + } + } + *p_data << (uint32)0; // first bag display id + *p_data << (uint8)0; // first bag inventory type + *p_data << (uint32)0; // enchant? +} + +bool Player::ToggleAFK() +{ + ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_AFK); + + bool state = HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_AFK); + + // afk player not allowed in battleground + if(state && InBattleGround()) + LeaveBattleground(); + + return state; +} + +bool Player::ToggleDND() +{ + ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_DND); + + return HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_DND); +} + +uint8 Player::chatTag() const +{ + // it's bitmask + // 0x8 - ?? + // 0x4 - gm + // 0x2 - dnd + // 0x1 - afk + if(isGameMaster()) + return 4; + else if(isDND()) + return 3; + if(isAFK()) + return 1; + else + return 0; +} + +bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options) +{ + if(!MapManager::IsValidMapCoord(mapid, x, y, z, orientation)) + { + sLog.outError("TeleportTo: invalid map %d or absent instance template.", mapid); + return false; + } + + // preparing unsummon pet if lost (we must get pet before teleportation or will not find it later) + Pet* pet = GetPet(); + + MapEntry const* mEntry = sMapStore.LookupEntry(mapid); + + // don't let enter battlegrounds without assigned battleground id (for example through areatrigger)... + if(!InBattleGround() && mEntry->IsBattleGround() && !GetSession()->GetSecurity()) + return false; + + bool tbc = GetSession()->IsTBC() && sWorld.getConfig(CONFIG_EXPANSION) > 0; + + // normal client and TBC map + if(!tbc && mEntry->IsExpansionMap()) + { + sLog.outDebug("Player %s using Normal client and tried teleport to non existing map %u", GetName(), mapid); + + if(GetTransport()) + RepopAtGraveyard(); // teleport to near graveyard if on transport, looks blizz like :) + + SendTransferAborted(mapid, TRANSFER_ABORT_INSUF_EXPAN_LVL1); + + return false; // normal client can't teleport to this map... + } + else if(tbc) // can teleport to any existing map + { + sLog.outDebug("Player %s have TBC client and will teleported to map %u", GetName(), mapid); + } + else + { + sLog.outDebug("Player %s have normal client and will teleported to standard map %u", GetName(), mapid); + } + /* + only TBC (no 0x80000 and 0x10 flags...) + 3604590=0x37006E=0x200000 + 0x100000 + 0x40000 + 0x20000 + 0x10000 + 0x40 + 0x20 + 0x8 + 0x4 + 0x2 + + Kharazan (normal/TBC??), but not have 0x10 flag (accessible by normal client?) + 4128878=0x3F006E=0x200000 + 0x100000 + 0x80000 + 0x40000 + 0x20000 + 0x10000 + 0x40 + 0x20 + 0x8 + 0x4 + 0x2 + + normal+TBC maps + 4128894=0x3F007E=0x200000 + 0x100000 + 0x80000 + 0x40000 + 0x20000 + 0x10000 + 0x40 + 0x20 + 0x10 + 0x8 + 0x4 + 0x2 + + normal+TBC maps + 8323198=0x7F007E=0x400000 + 0x200000 + 0x100000 + 0x80000 + 0x40000 + 0x20000 + 0x10000 + 0x40 + 0x20 + 0x10 + 0x8 + 0x4 + 0x2 + */ + + // if we were on a transport, leave + if (!(options & TELE_TO_NOT_LEAVE_TRANSPORT) && m_transport) + { + m_transport->RemovePassenger(this); + m_transport = NULL; + m_movementInfo.t_x = 0.0f; + m_movementInfo.t_y = 0.0f; + m_movementInfo.t_z = 0.0f; + m_movementInfo.t_o = 0.0f; + m_movementInfo.t_time = 0; + } + + SetSemaphoreTeleport(true); + + // The player was ported to another map and looses the duel immediatly. + // We have to perform this check before the teleport, otherwise the + // ObjectAccessor won't find the flag. + if (duel && this->GetMapId()!=mapid) + { + GameObject* obj = ObjectAccessor::GetGameObject(*this, GetUInt64Value(PLAYER_DUEL_ARBITER)); + if (obj) + DuelComplete(DUEL_FLED); + } + + // reset movement flags at teleport, because player will continue move with these flags after teleport + SetUnitMovementFlags(0); + + if ((this->GetMapId() == mapid) && (!m_transport)) + { + // prepare zone change detect + uint32 old_zone = GetZoneId(); + + // near teleport + if(!GetSession()->PlayerLogout()) + { + WorldPacket data; + BuildTeleportAckMsg(&data, x, y, z, orientation); + GetSession()->SendPacket(&data); + SetPosition( x, y, z, orientation, true); + } + else + // this will be used instead of the current location in SaveToDB + m_teleport_dest = WorldLocation(mapid, x, y, z, orientation); + + //BuildHeartBeatMsg(&data); + //SendMessageToSet(&data, true); + if (!(options & TELE_TO_NOT_UNSUMMON_PET)) + { + //same map, only remove pet if out of range + if(pet && !IsWithinDistInMap(pet, OWNER_MAX_DISTANCE)) + { + if(pet->isControlled() && !pet->isTemporarySummoned() ) + m_temporaryUnsummonedPetNumber = pet->GetCharmInfo()->GetPetNumber(); + else + m_temporaryUnsummonedPetNumber = 0; + + RemovePet(pet, PET_SAVE_NOT_IN_SLOT); + } + } + + if(!(options & TELE_TO_NOT_LEAVE_COMBAT)) + CombatStop(); + + if (!(options & TELE_TO_NOT_UNSUMMON_PET)) + { + // resummon pet + if(pet && m_temporaryUnsummonedPetNumber) + { + Pet* NewPet = new Pet; + if(!NewPet->LoadPetFromDB(this, 0, m_temporaryUnsummonedPetNumber, true)) + delete NewPet; + + m_temporaryUnsummonedPetNumber = 0; + } + } + + SetSemaphoreTeleport(false); + + if(!GetSession()->PlayerLogout()) + UpdateZone(GetZoneId()); + + // new zone + if(old_zone != GetZoneId()) + { + // honorless target + if(pvpInfo.inHostileArea) + CastSpell(this, 2479, true); + } + } + else + { + // far teleport to another map + Map* oldmap = IsInWorld() ? MapManager::Instance().GetMap(GetMapId(), this) : NULL; + // check if we can enter before stopping combat / removing pet / totems / interrupting spells + + // Check enter rights before map getting to avoid creating instance copy for player + // this check not dependent from map instance copy and same for all instance copies of selected map + if (!MapManager::Instance().CanPlayerEnter(mapid, this)) + { + SetSemaphoreTeleport(false); + return false; + } + + // If the map is not created, assume it is possible to enter it. + // It will be created in the WorldPortAck. + Map *map = MapManager::Instance().FindMap(mapid); + if (!map || map->CanEnter(this)) + { + SetSelection(0); + + CombatStop(); + + ResetContestedPvP(); + + // remove player from battleground on far teleport (when changing maps) + if(BattleGround const* bg = GetBattleGround()) + { + // Note: at battleground join battleground id set before teleport + // and we already will found "current" battleground + // just need check that this is targeted map or leave + if(bg->GetMapId() != mapid) + LeaveBattleground(false); // don't teleport to entry point + } + + // remove pet on map change + if (pet) + { + //leaving map -> delete pet right away (doing this later will cause problems) + if(pet->isControlled() && !pet->isTemporarySummoned()) + m_temporaryUnsummonedPetNumber = pet->GetCharmInfo()->GetPetNumber(); + else + m_temporaryUnsummonedPetNumber = 0; + + RemovePet(pet, PET_SAVE_NOT_IN_SLOT); + } + + // remove all dyn objects + RemoveAllDynObjects(); + + // stop spellcasting + // not attempt interrupt teleportation spell at caster teleport + if(!(options & TELE_TO_SPELL)) + if(IsNonMeleeSpellCasted(true)) + InterruptNonMeleeSpells(true); + + if(!GetSession()->PlayerLogout()) + { + // send transfer packets + WorldPacket data(SMSG_TRANSFER_PENDING, (4+4+4)); + data << uint32(mapid); + if (m_transport) + { + data << m_transport->GetEntry() << GetMapId(); + } + GetSession()->SendPacket(&data); + + data.Initialize(SMSG_NEW_WORLD, (20)); + if (m_transport) + { + data << (uint32)mapid << m_movementInfo.t_x << m_movementInfo.t_y << m_movementInfo.t_z << m_movementInfo.t_o; + } + else + { + data << (uint32)mapid << (float)x << (float)y << (float)z << (float)orientation; + } + GetSession()->SendPacket( &data ); + SendSavedInstances(); + + // remove from old map now + if(oldmap) oldmap->Remove(this, false); + } + + // new final coordinates + float final_x = x; + float final_y = y; + float final_z = z; + float final_o = orientation; + + if(m_transport) + { + final_x += m_movementInfo.t_x; + final_y += m_movementInfo.t_y; + final_z += m_movementInfo.t_z; + final_o += m_movementInfo.t_o; + } + + m_teleport_dest = WorldLocation(mapid, final_x, final_y, final_z, final_o); + // if the player is saved before worldportack (at logout for example) + // this will be used instead of the current location in SaveToDB + + RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CHANGE_MAP); + + // move packet sent by client always after far teleport + // SetPosition(final_x, final_y, final_z, final_o, true); + SetDontMove(true); + + // code for finish transfer to new map called in WorldSession::HandleMoveWorldportAckOpcode at client packet + } + else + return false; + } + return true; +} + +void Player::AddToWorld() +{ + ///- Do not add/remove the player from the object storage + ///- It will crash when updating the ObjectAccessor + ///- The player should only be added when logging in + Unit::AddToWorld(); + + for(int i = PLAYER_SLOT_START; i < PLAYER_SLOT_END; i++) + { + if(m_items[i]) + m_items[i]->AddToWorld(); + } +} + +void Player::RemoveFromWorld() +{ + // cleanup + if(IsInWorld()) + { + ///- Release charmed creatures, unsummon totems and remove pets/guardians + Uncharm(); + UnsummonAllTotems(); + RemoveMiniPet(); + RemoveGuardians(); + } + + for(int i = PLAYER_SLOT_START; i < PLAYER_SLOT_END; i++) + { + if(m_items[i]) + m_items[i]->RemoveFromWorld(); + } + + ///- Do not add/remove the player from the object storage + ///- It will crash when updating the ObjectAccessor + ///- The player should only be removed when logging out + Unit::RemoveFromWorld(); +} + +void Player::RewardRage( uint32 damage, uint32 weaponSpeedHitFactor, bool attacker ) +{ + float addRage; + + float rageconversion = ((0.0091107836 * getLevel()*getLevel())+3.225598133*getLevel())+4.2652911; + + if(attacker) + { + addRage = ((damage/rageconversion*7.5 + weaponSpeedHitFactor)/2); + + // talent who gave more rage on attack + addRage *= 1.0f + GetTotalAuraModifier(SPELL_AURA_MOD_RAGE_FROM_DAMAGE_DEALT) / 100.0f; + } + else + { + addRage = damage/rageconversion*2.5; + + // Berserker Rage effect + if(HasAura(18499,0)) + addRage *= 1.3; + } + + addRage *= sWorld.getRate(RATE_POWER_RAGE_INCOME); + + ModifyPower(POWER_RAGE, uint32(addRage*10)); +} + +void Player::RegenerateAll() +{ + if (m_regenTimer != 0) + return; + uint32 regenDelay = 2000; + + // Not in combat or they have regeneration + if( !isInCombat() || HasAuraType(SPELL_AURA_MOD_REGEN_DURING_COMBAT) || + HasAuraType(SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT) || IsPolymorphed() ) + { + RegenerateHealth(); + if (!isInCombat() && !HasAuraType(SPELL_AURA_INTERRUPT_REGEN)) + Regenerate(POWER_RAGE); + } + + Regenerate( POWER_ENERGY ); + + Regenerate( POWER_MANA ); + + m_regenTimer = regenDelay; +} + +void Player::Regenerate(Powers power) +{ + uint32 curValue = GetPower(power); + uint32 maxValue = GetMaxPower(power); + + float addvalue = 0.0f; + + switch (power) + { + case POWER_MANA: + { + bool recentCast = IsUnderLastManaUseEffect(); + float ManaIncreaseRate = sWorld.getRate(RATE_POWER_MANA); + if (recentCast) + { + // Mangos Updates Mana in intervals of 2s, which is correct + addvalue = GetFloatValue(PLAYER_FIELD_MOD_MANA_REGEN_INTERRUPT) * ManaIncreaseRate * 2.00f; + } + else + { + addvalue = GetFloatValue(PLAYER_FIELD_MOD_MANA_REGEN) * ManaIncreaseRate * 2.00f; + } + } break; + case POWER_RAGE: // Regenerate rage + { + float RageDecreaseRate = sWorld.getRate(RATE_POWER_RAGE_LOSS); + addvalue = 30 * RageDecreaseRate; // 3 rage by tick + } break; + case POWER_ENERGY: // Regenerate energy (rogue) + addvalue = 20; + break; + case POWER_FOCUS: + case POWER_HAPPINESS: + break; + } + + // Mana regen calculated in Player::UpdateManaRegen() + // Exist only for POWER_MANA, POWER_ENERGY, POWER_FOCUS auras + if(power != POWER_MANA) + { + AuraList const& ModPowerRegenPCTAuras = GetAurasByType(SPELL_AURA_MOD_POWER_REGEN_PERCENT); + for(AuraList::const_iterator i = ModPowerRegenPCTAuras.begin(); i != ModPowerRegenPCTAuras.end(); ++i) + if ((*i)->GetModifier()->m_miscvalue == power) + addvalue *= ((*i)->GetModifier()->m_amount + 100) / 100.0f; + } + + if (power != POWER_RAGE) + { + curValue += uint32(addvalue); + if (curValue > maxValue) + curValue = maxValue; + } + else + { + if(curValue <= uint32(addvalue)) + curValue = 0; + else + curValue -= uint32(addvalue); + } + SetPower(power, curValue); +} + +void Player::RegenerateHealth() +{ + uint32 curValue = GetHealth(); + uint32 maxValue = GetMaxHealth(); + + if (curValue >= maxValue) return; + + float HealthIncreaseRate = sWorld.getRate(RATE_HEALTH); + + float addvalue = 0.0f; + + // polymorphed case + if ( IsPolymorphed() ) + addvalue = GetMaxHealth()/3; + // normal regen case (maybe partly in combat case) + else if (!isInCombat() || HasAuraType(SPELL_AURA_MOD_REGEN_DURING_COMBAT) ) + { + addvalue = OCTRegenHPPerSpirit()* HealthIncreaseRate; + if (!isInCombat()) + { + AuraList const& mModHealthRegenPct = GetAurasByType(SPELL_AURA_MOD_HEALTH_REGEN_PERCENT); + for(AuraList::const_iterator i = mModHealthRegenPct.begin(); i != mModHealthRegenPct.end(); ++i) + addvalue *= (100.0f + (*i)->GetModifier()->m_amount) / 100.0f; + } + else if(HasAuraType(SPELL_AURA_MOD_REGEN_DURING_COMBAT)) + addvalue *= GetTotalAuraModifier(SPELL_AURA_MOD_REGEN_DURING_COMBAT) / 100.0f; + + if(!IsStandState()) + addvalue *= 1.5; + } + + // always regeneration bonus (including combat) + addvalue += GetTotalAuraModifier(SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT); + + if(addvalue < 0) + addvalue = 0; + + ModifyHealth(int32(addvalue)); +} + +bool Player::CanInteractWithNPCs(bool alive) const +{ + if(alive && !isAlive()) + return false; + if(isInFlight()) + return false; + + return true; +} + +bool Player::IsUnderWater() const +{ + return IsInWater() && + GetPositionZ() < (MapManager::Instance().GetBaseMap(GetMapId())->GetWaterLevel(GetPositionX(),GetPositionY())-2); +} + +void Player::SetInWater(bool apply) +{ + if(m_isInWater==apply) + return; + + //define player in water by opcodes + //move player's guid into HateOfflineList of those mobs + //which can't swim and move guid back into ThreatList when + //on surface. + //TODO: exist also swimming mobs, and function must be symmetric to enter/leave water + m_isInWater = apply; + + // remove auras that need water/land + RemoveAurasWithInterruptFlags(apply ? AURA_INTERRUPT_FLAG_NOT_ABOVEWATER : AURA_INTERRUPT_FLAG_NOT_UNDERWATER); + + getHostilRefManager().updateThreatTables(); +} + +void Player::SetGameMaster(bool on) +{ + if(on) + { + m_ExtraFlags |= PLAYER_EXTRA_GM_ON; + setFaction(35); + SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_GM); + + RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP); + ResetContestedPvP(); + + getHostilRefManager().setOnlineOfflineState(false); + CombatStop(); + } + else + { + m_ExtraFlags &= ~ PLAYER_EXTRA_GM_ON; + setFactionForRace(getRace()); + RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GM); + + // restore FFA PvP Server state + if(sWorld.IsFFAPvPRealm()) + SetFlag(PLAYER_FLAGS,PLAYER_FLAGS_FFA_PVP); + + // restore FFA PvP area state, remove not allowed for GM mounts + UpdateArea(m_areaUpdateId); + + getHostilRefManager().setOnlineOfflineState(true); + } + + ObjectAccessor::UpdateVisibilityForPlayer(this); +} + +void Player::SetGMVisible(bool on) +{ + if(on) + { + m_ExtraFlags &= ~PLAYER_EXTRA_GM_INVISIBLE; //remove flag + + // Reapply stealth/invisibility if active or show if not any + if(HasAuraType(SPELL_AURA_MOD_STEALTH)) + SetVisibility(VISIBILITY_GROUP_STEALTH); + else if(HasAuraType(SPELL_AURA_MOD_INVISIBILITY)) + SetVisibility(VISIBILITY_GROUP_INVISIBILITY); + else + SetVisibility(VISIBILITY_ON); + } + else + { + m_ExtraFlags |= PLAYER_EXTRA_GM_INVISIBLE; //add flag + + SetAcceptWhispers(false); + SetGameMaster(true); + + SetVisibility(VISIBILITY_OFF); + } +} + +bool Player::IsGroupVisibleFor(Player* p) const +{ + switch(sWorld.getConfig(CONFIG_GROUP_VISIBILITY)) + { + default: return IsInSameGroupWith(p); + case 1: return IsInSameRaidWith(p); + case 2: return GetTeam()==p->GetTeam(); + } +} + +bool Player::IsInSameGroupWith(Player const* p) const +{ + return p==this || GetGroup() != NULL && + GetGroup() == p->GetGroup() && + GetGroup()->SameSubGroup((Player*)this, (Player*)p); +} + +///- If the player is invited, remove him. If the group if then only 1 person, disband the group. +/// \todo Shouldn't we also check if there is no other invitees before disbanding the group? +void Player::UninviteFromGroup() +{ + if(GetGroupInvite()) // uninvited invitee + { + Group* group = GetGroupInvite(); + group->RemoveInvite(this); + + if(group->GetMembersCount() <= 1) // group has just 1 member => disband + { + if(group->IsCreated()) + { + group->Disband(true); + objmgr.RemoveGroup(group); + } + else + group->RemoveAllInvites(); + + delete group; + } + } +} + +void Player::RemoveFromGroup(Group* group, uint64 guid) +{ + if(group) + { + if (group->RemoveMember(guid, 0) <= 1) + { + // group->Disband(); already disbanded in RemoveMember + objmgr.RemoveGroup(group); + delete group; + // removemember sets the player's group pointer to NULL + } + } +} + +void Player::SendLogXPGain(uint32 GivenXP, Unit* victim, uint32 RestXP) +{ + WorldPacket data(SMSG_LOG_XPGAIN, 21); + data << uint64(victim ? victim->GetGUID() : 0); // guid + data << uint32(GivenXP+RestXP); // given experience + data << uint8(victim ? 0 : 1); // 00-kill_xp type, 01-non_kill_xp type + if(victim) + { + data << uint32(GivenXP); // experience without rested bonus + data << float(1); // 1 - none 0 - 100% group bonus output + } + data << uint8(0); // new 2.4.0 + GetSession()->SendPacket(&data); +} + +void Player::GiveXP(uint32 xp, Unit* victim) +{ + if ( xp < 1 ) + return; + + if(!isAlive()) + return; + + uint32 level = getLevel(); + + // XP to money conversion processed in Player::RewardQuest + if(level >= sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + return; + + // handle SPELL_AURA_MOD_XP_PCT auras + Unit::AuraList const& ModXPPctAuras = GetAurasByType(SPELL_AURA_MOD_XP_PCT); + for(Unit::AuraList::const_iterator i = ModXPPctAuras.begin();i != ModXPPctAuras.end(); ++i) + xp = uint32(xp*(1.0f + (*i)->GetModifier()->m_amount / 100.0f)); + + // XP resting bonus for kill + uint32 rested_bonus_xp = victim ? GetXPRestBonus(xp) : 0; + + SendLogXPGain(xp,victim,rested_bonus_xp); + + uint32 curXP = GetUInt32Value(PLAYER_XP); + uint32 nextLvlXP = GetUInt32Value(PLAYER_NEXT_LEVEL_XP); + uint32 newXP = curXP + xp + rested_bonus_xp; + + while( newXP >= nextLvlXP && level < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) ) + { + newXP -= nextLvlXP; + + if ( level < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) ) + GiveLevel(level + 1); + + level = getLevel(); + nextLvlXP = GetUInt32Value(PLAYER_NEXT_LEVEL_XP); + } + + SetUInt32Value(PLAYER_XP, newXP); +} + +// Update player to next level +// Current player experience not update (must be update by caller) +void Player::GiveLevel(uint32 level) +{ + if ( level == getLevel() ) + return; + + PlayerLevelInfo info; + objmgr.GetPlayerLevelInfo(getRace(),getClass(),level,&info); + + PlayerClassLevelInfo classInfo; + objmgr.GetPlayerClassLevelInfo(getClass(),level,&classInfo); + + // send levelup info to client + WorldPacket data(SMSG_LEVELUP_INFO, (4+4+MAX_POWERS*4+MAX_STATS*4)); + data << uint32(level); + data << uint32(int32(classInfo.basehealth) - int32(GetCreateHealth())); + // for(int i = 0; i < MAX_POWERS; ++i) // Powers loop (0-6) + data << uint32(int32(classInfo.basemana) - int32(GetCreateMana())); + data << uint32(0); + data << uint32(0); + data << uint32(0); + data << uint32(0); + // end for + for(int i = STAT_STRENGTH; i < MAX_STATS; ++i) // Stats loop (0-4) + data << uint32(int32(info.stats[i]) - GetCreateStat(Stats(i))); + + GetSession()->SendPacket(&data); + + SetUInt32Value(PLAYER_NEXT_LEVEL_XP, MaNGOS::XP::xp_to_level(level)); + + //update level, max level of skills + if(getLevel()!= level) + m_Played_time[1] = 0; // Level Played Time reset + SetLevel(level); + UpdateMaxSkills(); + + // save base values (bonuses already included in stored stats + for(int i = STAT_STRENGTH; i < MAX_STATS; ++i) + SetCreateStat(Stats(i), info.stats[i]); + + SetCreateHealth(classInfo.basehealth); + SetCreateMana(classInfo.basemana); + + InitTalentForLevel(); + InitTaxiNodesForLevel(); + + UpdateAllStats(); + + // set current level health and mana/energy to maximum after applying all mods. + SetHealth(GetMaxHealth()); + SetPower(POWER_MANA, GetMaxPower(POWER_MANA)); + SetPower(POWER_ENERGY, GetMaxPower(POWER_ENERGY)); + if(GetPower(POWER_RAGE) > GetMaxPower(POWER_RAGE)) + SetPower(POWER_RAGE, GetMaxPower(POWER_RAGE)); + SetPower(POWER_FOCUS, 0); + SetPower(POWER_HAPPINESS, 0); + + // give level to summoned pet + Pet* pet = GetPet(); + if(pet && pet->getPetType()==SUMMON_PET) + pet->GivePetLevel(level); +} + +void Player::InitTalentForLevel() +{ + uint32 level = getLevel(); + // talents base at level diff ( talents = level - 9 but some can be used already) + if(level < 10) + { + // Remove all talent points + if(m_usedTalentCount > 0) // Free any used talents + { + resetTalents(true); + SetFreeTalentPoints(0); + } + } + else + { + uint32 talentPointsForLevel = uint32((level-9)*sWorld.getRate(RATE_TALENT)); + // if used more that have then reset + if(m_usedTalentCount > talentPointsForLevel) + { + if (GetSession()->GetSecurity() < SEC_ADMINISTRATOR) + resetTalents(true); + else + SetFreeTalentPoints(0); + } + // else update amount of free points + else + SetFreeTalentPoints(talentPointsForLevel-m_usedTalentCount); + } +} + +void Player::InitStatsForLevel(bool reapplyMods) +{ + if(reapplyMods) //reapply stats values only on .reset stats (level) command + _RemoveAllStatBonuses(); + + PlayerClassLevelInfo classInfo; + objmgr.GetPlayerClassLevelInfo(getClass(),getLevel(),&classInfo); + + PlayerLevelInfo info; + objmgr.GetPlayerLevelInfo(getRace(),getClass(),getLevel(),&info); + + SetUInt32Value(PLAYER_FIELD_MAX_LEVEL, sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) ); + SetUInt32Value(PLAYER_NEXT_LEVEL_XP, MaNGOS::XP::xp_to_level(getLevel())); + + UpdateMaxSkills (); + + // set default cast time multiplier + SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0f); + + // reset size before reapply auras + SetFloatValue(OBJECT_FIELD_SCALE_X,1.0f); + + // save base values (bonuses already included in stored stats + for(int i = STAT_STRENGTH; i < MAX_STATS; ++i) + SetCreateStat(Stats(i), info.stats[i]); + + for(int i = STAT_STRENGTH; i < MAX_STATS; ++i) + SetStat(Stats(i), info.stats[i]); + + SetCreateHealth(classInfo.basehealth); + + //set create powers + SetCreateMana(classInfo.basemana); + + SetArmor(int32(m_createStats[STAT_AGILITY]*2)); + + InitStatBuffMods(); + + //reset rating fields values + for(uint16 index = PLAYER_FIELD_COMBAT_RATING_1; index < PLAYER_FIELD_COMBAT_RATING_1 + MAX_COMBAT_RATING; ++index) + SetUInt32Value(index, 0); + + SetUInt32Value(PLAYER_FIELD_MOD_HEALING_DONE_POS,0); + for (int i = 0; i < 7; i++) + { + SetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG+i, 0); + SetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i, 0); + SetFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT+i, 1.00f); + } + + //reset attack power, damage and attack speed fields + SetFloatValue(UNIT_FIELD_BASEATTACKTIME, 2000.0f ); + SetFloatValue(UNIT_FIELD_BASEATTACKTIME + 1, 2000.0f ); // offhand attack time + SetFloatValue(UNIT_FIELD_RANGEDATTACKTIME, 2000.0f ); + + SetFloatValue(UNIT_FIELD_MINDAMAGE, 0.0f ); + SetFloatValue(UNIT_FIELD_MAXDAMAGE, 0.0f ); + SetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE, 0.0f ); + SetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE, 0.0f ); + SetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE, 0.0f ); + SetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE, 0.0f ); + + SetUInt32Value(UNIT_FIELD_ATTACK_POWER, 0 ); + SetUInt32Value(UNIT_FIELD_ATTACK_POWER_MODS, 0 ); + SetFloatValue(UNIT_FIELD_ATTACK_POWER_MULTIPLIER,0.0f); + SetUInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER, 0 ); + SetUInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER_MODS,0 ); + SetFloatValue(UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER,0.0f); + + // Base crit values (will be recalculated in UpdateAllStats() at loading and in _ApplyAllStatBonuses() at reset + SetFloatValue(PLAYER_CRIT_PERCENTAGE,0.0f); + SetFloatValue(PLAYER_OFFHAND_CRIT_PERCENTAGE,0.0f); + SetFloatValue(PLAYER_RANGED_CRIT_PERCENTAGE,0.0f); + + // Init spell schools (will be recalculated in UpdateAllStats() at loading and in _ApplyAllStatBonuses() at reset + for (uint8 i = 0; i < 7; ++i) + SetFloatValue(PLAYER_SPELL_CRIT_PERCENTAGE1+i, 0.0f); + + // Base parry percents + SetFloatValue(PLAYER_PARRY_PERCENTAGE, 5.0f); + + //Base block percentage + SetFloatValue(PLAYER_BLOCK_PERCENTAGE, 5.0f); + + SetUInt32Value(PLAYER_SHIELD_BLOCK, 0); + + // Dodge percentage + SetFloatValue(PLAYER_DODGE_PERCENTAGE, 0.0f); + + // set armor (resistance 0) to original value (create_agility*2) + SetArmor(int32(m_createStats[STAT_AGILITY]*2)); + SetResistanceBuffMods(SpellSchools(0), true, 0.0f); + SetResistanceBuffMods(SpellSchools(0), false, 0.0f); + // set other resistance to original value (0) + for (int i = 1; i < MAX_SPELL_SCHOOL; i++) + { + SetResistance(SpellSchools(i), 0); + SetResistanceBuffMods(SpellSchools(i), true, 0.0f); + SetResistanceBuffMods(SpellSchools(i), false, 0.0f); + } + + SetUInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE,0); + SetUInt32Value(PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE,0); + for(int i = 0; i < MAX_SPELL_SCHOOL; ++i) + { + SetFloatValue(UNIT_FIELD_POWER_COST_MODIFIER+i,0.0f); + SetFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER+i,0.0f); + } + // Init data for form but skip reapply item mods for form + InitDataForForm(reapplyMods); + + // save new stats + for (int i = POWER_MANA; i < MAX_POWERS; i++) + SetMaxPower(Powers(i), uint32(GetCreatePowers(Powers(i)))); + + SetMaxHealth(classInfo.basehealth); // stamina bonus will applied later + + // cleanup mounted state (it will set correctly at aura loading if player saved at mount. + SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, 0); + + // cleanup unit flags (will be re-applied if need at aura load). + RemoveFlag( UNIT_FIELD_FLAGS, + UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_ATTACKABLE_1 | + UNIT_FLAG_PET_IN_COMBAT | UNIT_FLAG_SILENCED | UNIT_FLAG_PACIFIED | + UNIT_FLAG_DISABLE_ROTATE | UNIT_FLAG_IN_COMBAT | UNIT_FLAG_DISARMED | + UNIT_FLAG_CONFUSED | UNIT_FLAG_FLEEING | UNIT_FLAG_NOT_SELECTABLE | + UNIT_FLAG_SKINNABLE | UNIT_FLAG_MOUNT | UNIT_FLAG_TAXI_FLIGHT ); + SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE ); // must be set + + // cleanup player flags (will be re-applied if need at aura load), to avoid have ghost flag without ghost aura, for example. + RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_AFK | PLAYER_FLAGS_DND | PLAYER_FLAGS_GM | PLAYER_FLAGS_GHOST | PLAYER_FLAGS_FFA_PVP); + + SetByteValue(UNIT_FIELD_BYTES_1, 2, 0x00); // one form stealth modified bytes + + // restore if need some important flags + SetUInt32Value(PLAYER_FIELD_BYTES2, 0 ); // flags empty by default + + if(reapplyMods) //reapply stats values only on .reset stats (level) command + _ApplyAllStatBonuses(); + + // set current level health and mana/energy to maximum after applying all mods. + SetHealth(GetMaxHealth()); + SetPower(POWER_MANA, GetMaxPower(POWER_MANA)); + SetPower(POWER_ENERGY, GetMaxPower(POWER_ENERGY)); + if(GetPower(POWER_RAGE) > GetMaxPower(POWER_RAGE)) + SetPower(POWER_RAGE, GetMaxPower(POWER_RAGE)); + SetPower(POWER_FOCUS, 0); + SetPower(POWER_HAPPINESS, 0); +} + +void Player::SendInitialSpells() +{ + uint16 spellCount = 0; + + WorldPacket data(SMSG_INITIAL_SPELLS, (1+2+4*m_spells.size()+2+m_spellCooldowns.size()*(2+2+2+4+4))); + data << uint8(0); + + size_t countPos = data.wpos(); + data << uint16(spellCount); // spell count placeholder + + for (PlayerSpellMap::const_iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr) + { + if(itr->second->state == PLAYERSPELL_REMOVED) + continue; + + if(!itr->second->active || itr->second->disabled) + continue; + + data << uint16(itr->first); + //data << uint16(itr->second->slotId); + data << uint16(0); // it's not slot id + + spellCount +=1; + } + + data.put(countPos,spellCount); // write real count value + + uint16 spellCooldowns = m_spellCooldowns.size(); + data << uint16(spellCooldowns); + for(SpellCooldowns::const_iterator itr=m_spellCooldowns.begin(); itr!=m_spellCooldowns.end(); itr++) + { + SpellEntry const *sEntry = sSpellStore.LookupEntry(itr->first); + if(!sEntry) + continue; + + data << uint16(itr->first); + + time_t cooldown = 0; + time_t curTime = time(NULL); + if(itr->second.end > curTime) + cooldown = (itr->second.end-curTime)*1000; + + data << uint16(itr->second.itemid); // cast item id + data << uint16(sEntry->Category); // spell category + if(sEntry->Category) // may be wrong, but anyway better than nothing... + { + data << uint32(0); + data << uint32(cooldown); + } + else + { + data << uint32(cooldown); + data << uint32(0); + } + } + + GetSession()->SendPacket(&data); + + sLog.outDetail( "CHARACTER: Sent Initial Spells" ); +} + +void Player::RemoveMail(uint32 id) +{ + for(PlayerMails::iterator itr = m_mail.begin(); itr != m_mail.end();++itr) + { + if ((*itr)->messageID == id) + { + //do not delete item, because Player::removeMail() is called when returning mail to sender. + m_mail.erase(itr); + return; + } + } +} + +void Player::SendMailResult(uint32 mailId, uint32 mailAction, uint32 mailError, uint32 equipError, uint32 item_guid, uint32 item_count) +{ + WorldPacket data(SMSG_SEND_MAIL_RESULT, (4+4+4+(mailError == MAIL_ERR_BAG_FULL?4:(mailAction == MAIL_ITEM_TAKEN?4+4:0)))); + data << (uint32) mailId; + data << (uint32) mailAction; + data << (uint32) mailError; + if ( mailError == MAIL_ERR_BAG_FULL ) + data << (uint32) equipError; + else if( mailAction == MAIL_ITEM_TAKEN ) + { + data << (uint32) item_guid; // item guid low? + data << (uint32) item_count; // item count? + } + GetSession()->SendPacket(&data); +} + +void Player::SendNewMail() +{ + // deliver undelivered mail + WorldPacket data(SMSG_RECEIVED_MAIL, 4); + data << (uint32) 0; + GetSession()->SendPacket(&data); +} + +void Player::UpdateNextMailTimeAndUnreads() +{ + // calculate next delivery time (min. from non-delivered mails + // and recalculate unReadMail + time_t cTime = time(NULL); + m_nextMailDelivereTime = 0; + unReadMails = 0; + for(PlayerMails::iterator itr = m_mail.begin(); itr != m_mail.end(); ++itr) + { + if((*itr)->deliver_time > cTime) + { + if(!m_nextMailDelivereTime || m_nextMailDelivereTime > (*itr)->deliver_time) + m_nextMailDelivereTime = (*itr)->deliver_time; + } + else if(((*itr)->checked & MAIL_CHECK_MASK_READ) == 0) + ++unReadMails; + } +} + +void Player::AddNewMailDeliverTime(time_t deliver_time) +{ + if(deliver_time <= time(NULL)) // ready now + { + ++unReadMails; + SendNewMail(); + } + else // not ready and no have ready mails + { + if(!m_nextMailDelivereTime || m_nextMailDelivereTime > deliver_time) + m_nextMailDelivereTime = deliver_time; + } +} + +bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool loading, uint16 slot_id, bool disabled) +{ + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id); + if (!spellInfo) + { + // do character spell book cleanup (all characters) + if(loading && !learning) // spell load case + { + sLog.outError("Player::addSpell: Non-existed in SpellStore spell #%u request, deleting for all characters in `character_spell`.",spell_id); + CharacterDatabase.PExecute("DELETE FROM character_spell WHERE spell = '%u'",spell_id); + } + else + sLog.outError("Player::addSpell: Non-existed in SpellStore spell #%u request.",spell_id); + + return false; + } + + if(!SpellMgr::IsSpellValid(spellInfo,this,false)) + { + // do character spell book cleanup (all characters) + if(loading && !learning) // spell load case + { + sLog.outError("Player::addSpell: Broken spell #%u learning not allowed, deleting for all characters in `character_spell`.",spell_id); + CharacterDatabase.PExecute("DELETE FROM character_spell WHERE spell = '%u'",spell_id); + } + else + sLog.outError("Player::addSpell: Broken spell #%u learning not allowed.",spell_id); + + return false; + } + + PlayerSpellState state = learning ? PLAYERSPELL_NEW : PLAYERSPELL_UNCHANGED; + + bool disabled_case = false; + bool superceded_old = false; + + PlayerSpellMap::iterator itr = m_spells.find(spell_id); + if (itr != m_spells.end()) + { + // update active state for known spell + if(itr->second->active != active && itr->second->state != PLAYERSPELL_REMOVED && !itr->second->disabled) + { + itr->second->active = active; + + // loading && !learning == explicitly load from DB and then exist in it already and set correctly + if(loading && !learning) + itr->second->state = PLAYERSPELL_UNCHANGED; + else if(itr->second->state != PLAYERSPELL_NEW) + itr->second->state = PLAYERSPELL_CHANGED; + + if(!active) + { + WorldPacket data(SMSG_REMOVED_SPELL, 4); + data << uint16(spell_id); + GetSession()->SendPacket(&data); + } + return active; // learn (show in spell book if active now) + } + + if(itr->second->disabled != disabled && itr->second->state != PLAYERSPELL_REMOVED) + { + if(itr->second->state != PLAYERSPELL_NEW) + itr->second->state = PLAYERSPELL_CHANGED; + itr->second->disabled = disabled; + + if(disabled) + return false; + + disabled_case = true; + } + else switch(itr->second->state) + { + case PLAYERSPELL_UNCHANGED: // known saved spell + return false; + case PLAYERSPELL_REMOVED: // re-learning removed not saved spell + { + delete itr->second; + m_spells.erase(itr); + state = PLAYERSPELL_CHANGED; + break; // need re-add + } + default: // known not saved yet spell (new or modified) + { + // can be in case spell loading but learned at some previous spell loading + if(loading && !learning) + itr->second->state = PLAYERSPELL_UNCHANGED; + + return false; + } + } + } + + if(!disabled_case) // skip new spell adding if spell already known (disabled spells case) + { + // talent: unlearn all other talent ranks (high and low) + if(TalentSpellPos const* talentPos = GetTalentSpellPos(spell_id)) + { + if(TalentEntry const *talentInfo = sTalentStore.LookupEntry( talentPos->talent_id )) + { + for(int i=0; i <5; ++i) + { + // skip learning spell and no rank spell case + uint32 rankSpellId = talentInfo->RankID[i]; + if(!rankSpellId || rankSpellId==spell_id) + continue; + + // skip unknown ranks + if(!HasSpell(rankSpellId)) + continue; + + removeSpell(rankSpellId); + } + } + } + // non talent spell: learn low ranks (recursive call) + else if(uint32 prev_spell = spellmgr.GetPrevSpellInChain(spell_id)) + { + if(loading) // at spells loading, no output, but allow save + addSpell(prev_spell,active,true,loading,SPELL_WITHOUT_SLOT_ID,disabled); + else // at normal learning + learnSpell(prev_spell); + } + + PlayerSpell *newspell = new PlayerSpell; + newspell->active = active; + newspell->state = state; + newspell->disabled = disabled; + + // replace spells in action bars and spellbook to bigger rank if only one spell rank must be accessible + if(newspell->active && !newspell->disabled && !SpellMgr::canStackSpellRanks(spellInfo) && spellmgr.GetSpellRank(spellInfo->Id) != 0) + { + for( PlayerSpellMap::iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr ) + { + if(itr->second->state == PLAYERSPELL_REMOVED) continue; + SpellEntry const *i_spellInfo = sSpellStore.LookupEntry(itr->first); + if(!i_spellInfo) continue; + + if( spellmgr.IsRankSpellDueToSpell(spellInfo,itr->first) ) + { + if(itr->second->active) + { + if(spellmgr.IsHighRankOfSpell(spell_id,itr->first)) + { + if(!loading) // not send spell (re-/over-)learn packets at loading + { + WorldPacket data(SMSG_SUPERCEDED_SPELL, (4)); + data << uint16(itr->first); + data << uint16(spell_id); + GetSession()->SendPacket( &data ); + } + + // mark old spell as disable (SMSG_SUPERCEDED_SPELL replace it in client by new) + itr->second->active = false; + itr->second->state = PLAYERSPELL_CHANGED; + superceded_old = true; // new spell replace old in action bars and spell book. + } + else if(spellmgr.IsHighRankOfSpell(itr->first,spell_id)) + { + if(!loading) // not send spell (re-/over-)learn packets at loading + { + WorldPacket data(SMSG_SUPERCEDED_SPELL, (4)); + data << uint16(spell_id); + data << uint16(itr->first); + GetSession()->SendPacket( &data ); + } + + // mark new spell as disable (not learned yet for client and will not learned) + newspell->active = false; + if(newspell->state != PLAYERSPELL_NEW) + newspell->state = PLAYERSPELL_CHANGED; + } + } + } + } + } + + uint16 tmpslot=slot_id; + + if (tmpslot == SPELL_WITHOUT_SLOT_ID) + { + uint16 maxid = 0; + PlayerSpellMap::iterator itr; + for (itr = m_spells.begin(); itr != m_spells.end(); ++itr) + { + if(itr->second->state == PLAYERSPELL_REMOVED) + continue; + if (itr->second->slotId > maxid) + maxid = itr->second->slotId; + } + tmpslot = maxid + 1; + } + + newspell->slotId = tmpslot; + m_spells[spell_id] = newspell; + + // return false if spell disabled + if (newspell->disabled) + return false; + } + + uint32 talentCost = GetTalentSpellCost(spell_id); + + // cast talents with SPELL_EFFECT_LEARN_SPELL (other dependent spells will learned later as not auto-learned) + // note: all spells with SPELL_EFFECT_LEARN_SPELL isn't passive + if( talentCost > 0 && IsSpellHaveEffect(spellInfo,SPELL_EFFECT_LEARN_SPELL) ) + { + // ignore stance requirement for talent learn spell (stance set for spell only for client spell description show) + CastSpell(this, spell_id, true); + } + // also cast passive spells (including all talents without SPELL_EFFECT_LEARN_SPELL) with additional checks + else if (IsPassiveSpell(spell_id)) + { + // if spell doesn't require a stance or the player is in the required stance + if( ( !spellInfo->Stances && + spell_id != 5420 && spell_id != 5419 && spell_id != 7376 && + spell_id != 7381 && spell_id != 21156 && spell_id != 21009 && + spell_id != 21178 && spell_id != 33948 && spell_id != 40121 ) || + m_form != 0 && (spellInfo->Stances & (1<<(m_form-1))) || + (spell_id == 5420 && m_form == FORM_TREE) || + (spell_id == 5419 && m_form == FORM_TRAVEL) || + (spell_id == 7376 && m_form == FORM_DEFENSIVESTANCE) || + (spell_id == 7381 && m_form == FORM_BERSERKERSTANCE) || + (spell_id == 21156 && m_form == FORM_BATTLESTANCE)|| + (spell_id == 21178 && (m_form == FORM_BEAR || m_form == FORM_DIREBEAR) ) || + (spell_id == 33948 && m_form == FORM_FLIGHT) || + (spell_id == 40121 && m_form == FORM_FLIGHT_EPIC) ) + //Check CasterAuraStates + if (!spellInfo->CasterAuraState || HasAuraState(AuraState(spellInfo->CasterAuraState))) + CastSpell(this, spell_id, true); + } + else if( IsSpellHaveEffect(spellInfo,SPELL_EFFECT_SKILL_STEP) ) + { + CastSpell(this, spell_id, true); + return false; + } + + // update used talent points count + m_usedTalentCount += talentCost; + + // update free primary prof.points (if any, can be none in case GM .learn prof. learning) + if(uint32 freeProfs = GetFreePrimaryProffesionPoints()) + { + if(spellmgr.IsPrimaryProfessionFirstRankSpell(spell_id)) + SetFreePrimaryProffesions(freeProfs-1); + } + + // add dependent skills + uint16 maxskill = GetMaxSkillValueForLevel(); + + SpellLearnSkillNode const* spellLearnSkill = spellmgr.GetSpellLearnSkill(spell_id); + + if(spellLearnSkill) + { + uint32 skill_value = GetPureSkillValue(spellLearnSkill->skill); + uint32 skill_max_value = GetPureMaxSkillValue(spellLearnSkill->skill); + + if(skill_value < spellLearnSkill->value) + skill_value = spellLearnSkill->value; + + uint32 new_skill_max_value = spellLearnSkill->maxvalue == 0 ? maxskill : spellLearnSkill->maxvalue; + + if(skill_max_value < new_skill_max_value) + skill_max_value = new_skill_max_value; + + SetSkill(spellLearnSkill->skill,skill_value,skill_max_value); + } + else + { + // not ranked skills + SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(spell_id); + SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(spell_id); + + for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx) + { + SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(_spell_idx->second->skillId); + if(!pSkill) + continue; + + if(HasSkill(pSkill->id)) + continue; + + if(_spell_idx->second->learnOnGetSkill == ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL || + // poison special case, not have ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL + pSkill->id==SKILL_POISONS && _spell_idx->second->max_value==0 || + // lockpicking special case, not have ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL + pSkill->id==SKILL_LOCKPICKING && _spell_idx->second->max_value==0 ) + { + switch(GetSkillRangeType(pSkill,_spell_idx->second->racemask!=0)) + { + case SKILL_RANGE_LANGUAGE: + SetSkill(pSkill->id, 300, 300 ); + break; + case SKILL_RANGE_LEVEL: + SetSkill(pSkill->id, 1, GetMaxSkillValueForLevel() ); + break; + case SKILL_RANGE_MONO: + SetSkill(pSkill->id, 1, 1 ); + break; + default: + break; + } + } + } + } + + // learn dependent spells + SpellLearnSpellMap::const_iterator spell_begin = spellmgr.GetBeginSpellLearnSpell(spell_id); + SpellLearnSpellMap::const_iterator spell_end = spellmgr.GetEndSpellLearnSpell(spell_id); + + for(SpellLearnSpellMap::const_iterator itr = spell_begin; itr != spell_end; ++itr) + { + if(!itr->second.autoLearned) + { + if(loading) // at spells loading, no output, but allow save + addSpell(itr->second.spell,true,true,loading); + else // at normal learning + learnSpell(itr->second.spell); + } + } + + // return true (for send learn packet) only if spell active (in case ranked spells) and not replace old spell + return active && !disabled && !superceded_old; +} + +void Player::learnSpell(uint32 spell_id) +{ + PlayerSpellMap::iterator itr = m_spells.find(spell_id); + + bool disabled = (itr != m_spells.end()) ? itr->second->disabled : false; + bool active = disabled ? itr->second->active : true; + + bool learning = addSpell(spell_id,active); + + // learn all disabled higher ranks (recursive) + SpellChainMapNext const& nextMap = spellmgr.GetSpellChainNext(); + for(SpellChainMapNext::const_iterator i = nextMap.lower_bound(spell_id); i != nextMap.upper_bound(spell_id); ++i) + { + PlayerSpellMap::iterator iter = m_spells.find(i->second); + if (disabled && iter != m_spells.end() && iter->second->disabled) + learnSpell(i->second); + } + + // prevent duplicated entires in spell book + if(!learning) + return; + + WorldPacket data(SMSG_LEARNED_SPELL, 4); + data << uint32(spell_id); + GetSession()->SendPacket(&data); +} + +void Player::removeSpell(uint32 spell_id, bool disabled) +{ + PlayerSpellMap::iterator itr = m_spells.find(spell_id); + if (itr == m_spells.end()) + return; + + if(itr->second->state == PLAYERSPELL_REMOVED || disabled && itr->second->disabled) + return; + + // unlearn non talent higher ranks (recursive) + SpellChainMapNext const& nextMap = spellmgr.GetSpellChainNext(); + for(SpellChainMapNext::const_iterator itr2 = nextMap.lower_bound(spell_id); itr2 != nextMap.upper_bound(spell_id); ++itr2) + if(HasSpell(itr2->second) && !GetTalentSpellPos(itr2->second)) + removeSpell(itr2->second,disabled); + + // removing + WorldPacket data(SMSG_REMOVED_SPELL, 4); + data << uint16(spell_id); + GetSession()->SendPacket(&data); + + if (disabled) + { + itr->second->disabled = disabled; + if(itr->second->state != PLAYERSPELL_NEW) + itr->second->state = PLAYERSPELL_CHANGED; + } + else + { + if(itr->second->state == PLAYERSPELL_NEW) + { + delete itr->second; + m_spells.erase(itr); + } + else + itr->second->state = PLAYERSPELL_REMOVED; + } + + RemoveAurasDueToSpell(spell_id); + + // remove pet auras + if(PetAura const* petSpell = spellmgr.GetPetAura(spell_id)) + RemovePetAura(petSpell); + + // free talent points + uint32 talentCosts = GetTalentSpellCost(spell_id); + if(talentCosts > 0) + { + if(talentCosts < m_usedTalentCount) + m_usedTalentCount -= talentCosts; + else + m_usedTalentCount = 0; + } + + // update free primary prof.points (if not overflow setting, can be in case GM use before .learn prof. learning) + if(spellmgr.IsPrimaryProfessionFirstRankSpell(spell_id)) + { + uint32 freeProfs = GetFreePrimaryProffesionPoints()+1; + if(freeProfs <= sWorld.getConfig(CONFIG_MAX_PRIMARY_TRADE_SKILL)) + SetFreePrimaryProffesions(freeProfs); + } + + // remove dependent skill + SpellLearnSkillNode const* spellLearnSkill = spellmgr.GetSpellLearnSkill(spell_id); + if(spellLearnSkill) + { + uint32 prev_spell = spellmgr.GetPrevSpellInChain(spell_id); + if(!prev_spell) // first rank, remove skill + SetSkill(spellLearnSkill->skill,0,0); + else + { + // search prev. skill setting by spell ranks chain + SpellLearnSkillNode const* prevSkill = spellmgr.GetSpellLearnSkill(prev_spell); + while(!prevSkill && prev_spell) + { + prev_spell = spellmgr.GetPrevSpellInChain(prev_spell); + prevSkill = spellmgr.GetSpellLearnSkill(spellmgr.GetFirstSpellInChain(prev_spell)); + } + + if(!prevSkill) // not found prev skill setting, remove skill + SetSkill(spellLearnSkill->skill,0,0); + else // set to prev. skill setting values + { + uint32 skill_value = GetPureSkillValue(prevSkill->skill); + uint32 skill_max_value = GetPureMaxSkillValue(prevSkill->skill); + + if(skill_value > prevSkill->value) + skill_value = prevSkill->value; + + uint32 new_skill_max_value = prevSkill->maxvalue == 0 ? GetMaxSkillValueForLevel() : prevSkill->maxvalue; + + if(skill_max_value > new_skill_max_value) + skill_max_value = new_skill_max_value; + + SetSkill(prevSkill->skill,skill_value,skill_max_value); + } + } + + } + else + { + // not ranked skills + SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(spell_id); + SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(spell_id); + + for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx) + { + SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(_spell_idx->second->skillId); + if(!pSkill) + continue; + + if(_spell_idx->second->learnOnGetSkill == ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL || + // poison special case, not have ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL + pSkill->id==SKILL_POISONS && _spell_idx->second->max_value==0 || + // lockpicking special case, not have ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL + pSkill->id==SKILL_LOCKPICKING && _spell_idx->second->max_value==0 ) + { + // not reset skills for professions and racial abilities + if( (pSkill->categoryId==SKILL_CATEGORY_SECONDARY || pSkill->categoryId==SKILL_CATEGORY_PROFESSION) && + (IsProfessionSkill(pSkill->id) || _spell_idx->second->racemask!=0) ) + continue; + + SetSkill(pSkill->id, 0, 0 ); + } + } + } + + // remove dependent spells + SpellLearnSpellMap::const_iterator spell_begin = spellmgr.GetBeginSpellLearnSpell(spell_id); + SpellLearnSpellMap::const_iterator spell_end = spellmgr.GetEndSpellLearnSpell(spell_id); + + for(SpellLearnSpellMap::const_iterator itr2 = spell_begin; itr2 != spell_end; ++itr2) + removeSpell(itr2->second.spell, disabled); +} + +void Player::RemoveArenaSpellCooldowns() +{ + // remove cooldowns on spells that has < 15 min CD + SpellCooldowns::iterator itr, next; + // iterate spell cooldowns + for(itr = m_spellCooldowns.begin();itr != m_spellCooldowns.end(); itr = next) + { + next = itr; + ++next; + SpellEntry const * entry = sSpellStore.LookupEntry(itr->first); + // check if spellentry is present and if the cooldown is less than 15 mins + if( entry && + entry->RecoveryTime <= 15 * MINUTE * 1000 && + entry->CategoryRecoveryTime <= 15 * MINUTE * 1000 ) + { + // notify player + WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8)); + data << uint32(itr->first); + data << GetGUID(); + GetSession()->SendPacket(&data); + // remove cooldown + m_spellCooldowns.erase(itr); + } + } +} + +void Player::RemoveAllSpellCooldown() +{ + if(!m_spellCooldowns.empty()) + { + for(SpellCooldowns::const_iterator itr = m_spellCooldowns.begin();itr != m_spellCooldowns.end(); ++itr) + { + WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8)); + data << uint32(itr->first); + data << uint64(GetGUID()); + GetSession()->SendPacket(&data); + } + m_spellCooldowns.clear(); + } +} + +void Player::_LoadSpellCooldowns(QueryResult *result) +{ + m_spellCooldowns.clear(); + + //QueryResult *result = CharacterDatabase.PQuery("SELECT spell,item,time FROM character_spell_cooldown WHERE guid = '%u'",GetGUIDLow()); + + if(result) + { + time_t curTime = time(NULL); + + do + { + Field *fields = result->Fetch(); + + uint32 spell_id = fields[0].GetUInt32(); + uint32 item_id = fields[1].GetUInt32(); + time_t db_time = (time_t)fields[2].GetUInt64(); + + if(!sSpellStore.LookupEntry(spell_id)) + { + sLog.outError("Player %u have unknown spell %u in `character_spell_cooldown`, skipping.",GetGUIDLow(),spell_id); + continue; + } + + // skip outdated cooldown + if(db_time <= curTime) + continue; + + AddSpellCooldown(spell_id, item_id, db_time); + + sLog.outDebug("Player (GUID: %u) spell %u, item %u cooldown loaded (%u secs).", GetGUIDLow(), spell_id, item_id, uint32(db_time-curTime)); + } + while( result->NextRow() ); + + delete result; + } +} + +void Player::_SaveSpellCooldowns() +{ + CharacterDatabase.PExecute("DELETE FROM character_spell_cooldown WHERE guid = '%u'", GetGUIDLow()); + + time_t curTime = time(NULL); + + // remove outdated and save active + for(SpellCooldowns::iterator itr = m_spellCooldowns.begin();itr != m_spellCooldowns.end();) + { + if(itr->second.end <= curTime) + m_spellCooldowns.erase(itr++); + else + { + CharacterDatabase.PExecute("INSERT INTO character_spell_cooldown (guid,spell,item,time) VALUES ('%u', '%u', '%u', '" I64FMTD "')", GetGUIDLow(), itr->first, itr->second.itemid, uint64(itr->second.end)); + ++itr; + } + } +} + +uint32 Player::resetTalentsCost() const +{ + // The first time reset costs 1 gold + if(m_resetTalentsCost < 1*GOLD) + return 1*GOLD; + // then 5 gold + else if(m_resetTalentsCost < 5*GOLD) + return 5*GOLD; + // After that it increases in increments of 5 gold + else if(m_resetTalentsCost < 10*GOLD) + return 10*GOLD; + else + { + uint32 months = (sWorld.GetGameTime() - m_resetTalentsTime)/MONTH; + if(months > 0) + { + // This cost will be reduced by a rate of 5 gold per month + int32 new_cost = int32(m_resetTalentsCost) - 5*GOLD*months; + // to a minimum of 10 gold. + return (new_cost < 10*GOLD ? 10*GOLD : new_cost); + } + else + { + // After that it increases in increments of 5 gold + int32 new_cost = m_resetTalentsCost + 5*GOLD; + // until it hits a cap of 50 gold. + if(new_cost > 50*GOLD) + new_cost = 50*GOLD; + return new_cost; + } + } +} + +bool Player::resetTalents(bool no_cost) +{ + // not need after this call + if(HasAtLoginFlag(AT_LOGIN_RESET_TALENTS)) + { + m_atLoginFlags = m_atLoginFlags & ~AT_LOGIN_RESET_TALENTS; + CharacterDatabase.PExecute("UPDATE characters set at_login = at_login & ~ %u WHERE guid ='%u'", uint32(AT_LOGIN_RESET_TALENTS), GetGUIDLow()); + } + + uint32 level = getLevel(); + uint32 talentPointsForLevel = level < 10 ? 0 : uint32((level-9)*sWorld.getRate(RATE_TALENT)); + + if (m_usedTalentCount == 0) + { + SetFreeTalentPoints(talentPointsForLevel); + return false; + } + + uint32 cost = 0; + + if(!no_cost) + { + cost = resetTalentsCost(); + + if (GetMoney() < cost) + { + SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, 0, 0, 0); + return false; + } + } + + for (unsigned int i = 0; i < sTalentStore.GetNumRows(); i++) + { + TalentEntry const *talentInfo = sTalentStore.LookupEntry(i); + + if (!talentInfo) continue; + + TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry( talentInfo->TalentTab ); + + if(!talentTabInfo) + continue; + + // unlearn only talents for character class + // some spell learned by one class as normal spells or know at creation but another class learn it as talent, + // to prevent unexpected lost normal learned spell skip another class talents + if( (getClassMask() & talentTabInfo->ClassMask) == 0 ) + continue; + + for (int j = 0; j < 5; j++) + { + for(PlayerSpellMap::iterator itr = GetSpellMap().begin(); itr != GetSpellMap().end();) + { + if(itr->second->state == PLAYERSPELL_REMOVED || itr->second->disabled) + { + ++itr; + continue; + } + + // remove learned spells (all ranks) + uint32 itrFirstId = spellmgr.GetFirstSpellInChain(itr->first); + + // unlearn if first rank is talent or learned by talent + if (itrFirstId == talentInfo->RankID[j] || spellmgr.IsSpellLearnToSpell(talentInfo->RankID[j],itrFirstId)) + { + removeSpell(itr->first,!IsPassiveSpell(itr->first)); + itr = GetSpellMap().begin(); + continue; + } + else + ++itr; + } + } + } + + SetFreeTalentPoints(talentPointsForLevel); + + if(!no_cost) + { + ModifyMoney(-(int32)cost); + + m_resetTalentsCost = cost; + m_resetTalentsTime = time(NULL); + } + + //FIXME: remove pet before or after unlearn spells? for now after unlearn to allow removing of talent related, pet affecting auras + RemovePet(NULL,PET_SAVE_NOT_IN_SLOT, true); + + return true; +} + +bool Player::_removeSpell(uint16 spell_id) +{ + PlayerSpellMap::iterator itr = m_spells.find(spell_id); + if (itr != m_spells.end()) + { + delete itr->second; + m_spells.erase(itr); + return true; + } + return false; +} + +Mail* Player::GetMail(uint32 id) +{ + for(PlayerMails::iterator itr = m_mail.begin(); itr != m_mail.end(); itr++) + { + if ((*itr)->messageID == id) + { + return (*itr); + } + } + return NULL; +} + +void Player::_SetCreateBits(UpdateMask *updateMask, Player *target) const +{ + if(target == this) + { + Object::_SetCreateBits(updateMask, target); + } + else + { + for(uint16 index = 0; index < m_valuesCount; index++) + { + if(GetUInt32Value(index) != 0 && updateVisualBits.GetBit(index)) + updateMask->SetBit(index); + } + } +} + +void Player::_SetUpdateBits(UpdateMask *updateMask, Player *target) const +{ + if(target == this) + { + Object::_SetUpdateBits(updateMask, target); + } + else + { + Object::_SetUpdateBits(updateMask, target); + *updateMask &= updateVisualBits; + } +} + +void Player::InitVisibleBits() +{ + updateVisualBits.SetCount(PLAYER_END); + + updateVisualBits.SetBit(OBJECT_FIELD_GUID); + updateVisualBits.SetBit(OBJECT_FIELD_TYPE); + updateVisualBits.SetBit(OBJECT_FIELD_SCALE_X); + + updateVisualBits.SetBit(UNIT_FIELD_CHARM); + updateVisualBits.SetBit(UNIT_FIELD_CHARM+1); + + updateVisualBits.SetBit(UNIT_FIELD_SUMMON); + updateVisualBits.SetBit(UNIT_FIELD_SUMMON+1); + + updateVisualBits.SetBit(UNIT_FIELD_CHARMEDBY); + + updateVisualBits.SetBit(UNIT_FIELD_TARGET); + updateVisualBits.SetBit(UNIT_FIELD_TARGET+1); + + updateVisualBits.SetBit(UNIT_FIELD_CHANNEL_OBJECT); + updateVisualBits.SetBit(UNIT_FIELD_CHANNEL_OBJECT+1); + + updateVisualBits.SetBit(UNIT_FIELD_HEALTH); + updateVisualBits.SetBit(UNIT_FIELD_POWER1); + updateVisualBits.SetBit(UNIT_FIELD_POWER2); + updateVisualBits.SetBit(UNIT_FIELD_POWER3); + updateVisualBits.SetBit(UNIT_FIELD_POWER4); + updateVisualBits.SetBit(UNIT_FIELD_POWER5); + + updateVisualBits.SetBit(UNIT_FIELD_MAXHEALTH); + updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER1); + updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER2); + updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER3); + updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER4); + updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER5); + + updateVisualBits.SetBit(UNIT_FIELD_LEVEL); + updateVisualBits.SetBit(UNIT_FIELD_FACTIONTEMPLATE); + updateVisualBits.SetBit(UNIT_FIELD_BYTES_0); + updateVisualBits.SetBit(UNIT_FIELD_FLAGS); + updateVisualBits.SetBit(UNIT_FIELD_FLAGS_2); + for(uint16 i = UNIT_FIELD_AURA; i < UNIT_FIELD_AURASTATE; ++i) + updateVisualBits.SetBit(i); + updateVisualBits.SetBit(UNIT_FIELD_AURASTATE); + updateVisualBits.SetBit(UNIT_FIELD_BASEATTACKTIME); + updateVisualBits.SetBit(UNIT_FIELD_BASEATTACKTIME + 1); + updateVisualBits.SetBit(UNIT_FIELD_RANGEDATTACKTIME); + updateVisualBits.SetBit(UNIT_FIELD_BOUNDINGRADIUS); + updateVisualBits.SetBit(UNIT_FIELD_COMBATREACH); + updateVisualBits.SetBit(UNIT_FIELD_DISPLAYID); + updateVisualBits.SetBit(UNIT_FIELD_NATIVEDISPLAYID); + updateVisualBits.SetBit(UNIT_FIELD_MOUNTDISPLAYID); + updateVisualBits.SetBit(UNIT_FIELD_BYTES_1); + updateVisualBits.SetBit(UNIT_FIELD_MOUNTDISPLAYID); + updateVisualBits.SetBit(UNIT_FIELD_PETNUMBER); + updateVisualBits.SetBit(UNIT_FIELD_PET_NAME_TIMESTAMP); + updateVisualBits.SetBit(UNIT_DYNAMIC_FLAGS); + updateVisualBits.SetBit(UNIT_CHANNEL_SPELL); + updateVisualBits.SetBit(UNIT_MOD_CAST_SPEED); + updateVisualBits.SetBit(UNIT_FIELD_BYTES_2); + + updateVisualBits.SetBit(PLAYER_FLAGS); + updateVisualBits.SetBit(PLAYER_BYTES); + updateVisualBits.SetBit(PLAYER_BYTES_2); + updateVisualBits.SetBit(PLAYER_BYTES_3); + updateVisualBits.SetBit(PLAYER_GUILDID); + updateVisualBits.SetBit(PLAYER_GUILDRANK); + updateVisualBits.SetBit(PLAYER_GUILD_TIMESTAMP); + updateVisualBits.SetBit(PLAYER_DUEL_TEAM); + updateVisualBits.SetBit(PLAYER_DUEL_ARBITER); + updateVisualBits.SetBit(PLAYER_DUEL_ARBITER+1); + + // PLAYER_QUEST_LOG_x also visible bit on official (but only on party/raid)... + for(uint16 i = PLAYER_QUEST_LOG_1_1; i < PLAYER_QUEST_LOG_25_2; i+=4) + updateVisualBits.SetBit(i); + + for(uint16 i = 0; i < INVENTORY_SLOT_BAG_END; i++) + { + updateVisualBits.SetBit((uint16)(PLAYER_FIELD_INV_SLOT_HEAD + i*2)); + updateVisualBits.SetBit((uint16)(PLAYER_FIELD_INV_SLOT_HEAD + (i*2) + 1)); + } + //Players visible items are not inventory stuff + //431) = 884 (0x374) = main weapon + for(uint16 i = 0; i < EQUIPMENT_SLOT_END; i++) + { + // item creator + updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_CREATOR + (i*MAX_VISIBLE_ITEM_OFFSET) + 0); + updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_CREATOR + (i*MAX_VISIBLE_ITEM_OFFSET) + 1); + + uint16 visual_base = PLAYER_VISIBLE_ITEM_1_0 + (i*MAX_VISIBLE_ITEM_OFFSET); + + // item entry + updateVisualBits.SetBit(visual_base + 0); + + // item enchantment IDs + for(uint8 j = 0; j < MAX_INSPECTED_ENCHANTMENT_SLOT; ++j) + updateVisualBits.SetBit(visual_base + 1 + j); + + // random properties + updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_PROPERTIES + 0 + (i*MAX_VISIBLE_ITEM_OFFSET)); + updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_PROPERTIES + 1 + (i*MAX_VISIBLE_ITEM_OFFSET)); + } + + updateVisualBits.SetBit(PLAYER_CHOSEN_TITLE); + + updateVisualBits.SetBit(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY); + updateVisualBits.SetBit(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY + 1); + updateVisualBits.SetBit(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY + 2); + updateVisualBits.SetBit(UNIT_VIRTUAL_ITEM_INFO); + updateVisualBits.SetBit(UNIT_VIRTUAL_ITEM_INFO + 1); + updateVisualBits.SetBit(UNIT_VIRTUAL_ITEM_INFO + 2); + updateVisualBits.SetBit(UNIT_VIRTUAL_ITEM_INFO + 3); + updateVisualBits.SetBit(UNIT_VIRTUAL_ITEM_INFO + 4); + updateVisualBits.SetBit(UNIT_VIRTUAL_ITEM_INFO + 5); +} + +void Player::BuildCreateUpdateBlockForPlayer( UpdateData *data, Player *target ) const +{ + for(int i = 0; i < EQUIPMENT_SLOT_END; i++) + { + if(m_items[i] == NULL) + continue; + + m_items[i]->BuildCreateUpdateBlockForPlayer( data, target ); + } + + if(target == this) + { + + for(int i = INVENTORY_SLOT_BAG_START; i < BANK_SLOT_BAG_END; i++) + { + if(m_items[i] == NULL) + continue; + + m_items[i]->BuildCreateUpdateBlockForPlayer( data, target ); + } + for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++) + { + if(m_items[i] == NULL) + continue; + + m_items[i]->BuildCreateUpdateBlockForPlayer( data, target ); + } + } + + Unit::BuildCreateUpdateBlockForPlayer( data, target ); +} + +void Player::DestroyForPlayer( Player *target ) const +{ + Unit::DestroyForPlayer( target ); + + for(int i = 0; i < INVENTORY_SLOT_BAG_END; i++) + { + if(m_items[i] == NULL) + continue; + + m_items[i]->DestroyForPlayer( target ); + } + + if(target == this) + { + + for(int i = INVENTORY_SLOT_BAG_START; i < BANK_SLOT_BAG_END; i++) + { + if(m_items[i] == NULL) + continue; + + m_items[i]->DestroyForPlayer( target ); + } + for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++) + { + if(m_items[i] == NULL) + continue; + + m_items[i]->DestroyForPlayer( target ); + } + } +} + +bool Player::HasSpell(uint32 spell) const +{ + PlayerSpellMap::const_iterator itr = m_spells.find((uint16)spell); + return (itr != m_spells.end() && itr->second->state != PLAYERSPELL_REMOVED && !itr->second->disabled); +} + +TrainerSpellState Player::GetTrainerSpellState(TrainerSpell const* trainer_spell) const +{ + if (!trainer_spell) + return TRAINER_SPELL_RED; + + if (!trainer_spell->spell) + return TRAINER_SPELL_RED; + + // known spell + if(HasSpell(trainer_spell->spell->Id)) + return TRAINER_SPELL_GRAY; + + // check race/class requirement + if(!IsSpellFitByClassAndRace(trainer_spell->spell->Id)) + return TRAINER_SPELL_RED; + + // check level requirement + if(getLevel() < ( trainer_spell->reqlevel ? trainer_spell->reqlevel : trainer_spell->spell->spellLevel)) + return TRAINER_SPELL_RED; + + if(SpellChainNode const* spell_chain = spellmgr.GetSpellChainNode(trainer_spell->spell->Id)) + { + // check prev.rank requirement + if(spell_chain->prev && !HasSpell(spell_chain->prev)) + return TRAINER_SPELL_RED; + + // check additional spell requirement + if(spell_chain->req && !HasSpell(spell_chain->req)) + return TRAINER_SPELL_RED; + } + + // check skill requirement + if(trainer_spell->reqskill && GetBaseSkillValue(trainer_spell->reqskill) < trainer_spell->reqskillvalue) + return TRAINER_SPELL_RED; + + // secondary prof. or not prof. spell + uint32 skill = trainer_spell->spell->EffectMiscValue[1]; + + if(trainer_spell->spell->Effect[1] != SPELL_EFFECT_SKILL || !IsPrimaryProfessionSkill(skill)) + return TRAINER_SPELL_GREEN; + + // check primary prof. limit + if(spellmgr.IsPrimaryProfessionFirstRankSpell(trainer_spell->spell->Id) && GetFreePrimaryProffesionPoints() == 0) + return TRAINER_SPELL_RED; + + return TRAINER_SPELL_GREEN; +} + +void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmChars) +{ + uint32 guid = GUID_LOPART(playerguid); + + // convert corpse to bones if exist (to prevent exiting Corpse in World without DB entry) + // bones will be deleted by corpse/bones deleting thread shortly + ObjectAccessor::Instance().ConvertCorpseForPlayer(playerguid); + + // remove from guild + uint32 guildId = GetGuildIdFromDB(playerguid); + if(guildId != 0) + { + Guild* guild = objmgr.GetGuildById(guildId); + if(guild) + guild->DelMember(guid); + } + + // the player was uninvited already on logout so just remove from group + QueryResult *resultGroup = CharacterDatabase.PQuery("SELECT leaderGuid FROM group_member WHERE memberGuid='%u'", guid); + if(resultGroup) + { + uint64 leaderGuid = MAKE_NEW_GUID((*resultGroup)[0].GetUInt32(), 0, HIGHGUID_PLAYER); + delete resultGroup; + Group* group = objmgr.GetGroupByLeader(leaderGuid); + if(group) + { + RemoveFromGroup(group, playerguid); + } + } + + // remove signs from petitions (also remove petitions if owner); + RemovePetitionsAndSigns(playerguid, 10); + + // return back all mails with COD and Item 0 1 2 3 4 5 6 + QueryResult *resultMail = CharacterDatabase.PQuery("SELECT id,mailTemplateId,sender,subject,itemTextId,money,has_items FROM mail WHERE receiver='%u' AND has_items<>0 AND cod<>0", guid); + if(resultMail) + { + do + { + Field *fields = resultMail->Fetch(); + + uint32 mail_id = fields[0].GetUInt32(); + uint16 mailTemplateId= fields[1].GetUInt16(); + uint32 sender = fields[2].GetUInt32(); + std::string subject = fields[3].GetCppString(); + uint32 itemTextId = fields[4].GetUInt32(); + uint32 money = fields[5].GetUInt32(); + bool has_items = fields[6].GetBool(); + + //we can return mail now + //so firstly delete the old one + CharacterDatabase.PExecute("DELETE FROM mail WHERE id = '%u'", mail_id); + + MailItemsInfo mi; + if(has_items) + { + QueryResult *resultItems = CharacterDatabase.PQuery("SELECT item_guid,item_template FROM mail_items WHERE mail_id='%u'", mail_id); + if(resultItems) + { + do + { + Field *fields2 = resultItems->Fetch(); + + uint32 item_guidlow = fields2[0].GetUInt32(); + uint32 item_template = fields2[1].GetUInt32(); + + ItemPrototype const* itemProto = objmgr.GetItemPrototype(item_template); + if(!itemProto) + { + CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid = '%u'", item_guidlow); + continue; + } + + Item *pItem = NewItemOrBag(itemProto); + if(!pItem->LoadFromDB(item_guidlow, MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER))) + { + pItem->FSetState(ITEM_REMOVED); + pItem->SaveToDB(); // it also deletes item object ! + continue; + } + + mi.AddItem(item_guidlow, item_template, pItem); + } + while (resultItems->NextRow()); + + delete resultItems; + } + } + + CharacterDatabase.PExecute("DELETE FROM mail_items WHERE mail_id = '%u'", mail_id); + + uint32 pl_account = objmgr.GetPlayerAccountIdByGUID(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER)); + + WorldSession::SendReturnToSender(MAIL_NORMAL, pl_account, guid, sender, subject, itemTextId, &mi, money, 0, mailTemplateId); + } + while (resultMail->NextRow()); + + delete resultMail; + } + + // unsummon and delete for pets in world is not required: player deleted from CLI or character list with not loaded pet. + // Get guids of character's pets, will deleted in transaction + QueryResult *resultPets = CharacterDatabase.PQuery("SELECT id FROM character_pet WHERE owner = '%u'",guid); + + // NOW we can finally clear other DB data related to character + CharacterDatabase.BeginTransaction(); + if (resultPets) + { + do + { + Field *fields3 = resultPets->Fetch(); + uint32 petguidlow = fields3[0].GetUInt32(); + Pet::DeleteFromDB(petguidlow); + } while (resultPets->NextRow()); + delete resultPets; + } + + CharacterDatabase.PExecute("DELETE FROM characters WHERE guid = '%u'",guid); + CharacterDatabase.PExecute("DELETE FROM character_declinedname WHERE guid = '%u'",guid); + CharacterDatabase.PExecute("DELETE FROM character_action WHERE guid = '%u'",guid); + CharacterDatabase.PExecute("DELETE FROM character_aura WHERE guid = '%u'",guid); + CharacterDatabase.PExecute("DELETE FROM character_gifts WHERE guid = '%u'",guid); + CharacterDatabase.PExecute("DELETE FROM character_homebind WHERE guid = '%u'",guid); + CharacterDatabase.PExecute("DELETE FROM character_instance WHERE guid = '%u'",guid); + CharacterDatabase.PExecute("DELETE FROM group_instance WHERE leaderGuid = '%u'",guid); + CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE guid = '%u'",guid); + CharacterDatabase.PExecute("DELETE FROM character_queststatus WHERE guid = '%u'",guid); + CharacterDatabase.PExecute("DELETE FROM character_reputation WHERE guid = '%u'",guid); + CharacterDatabase.PExecute("DELETE FROM character_spell WHERE guid = '%u'",guid); + CharacterDatabase.PExecute("DELETE FROM character_spell_cooldown WHERE guid = '%u'",guid); + CharacterDatabase.PExecute("DELETE FROM character_ticket WHERE guid = '%u'",guid); + CharacterDatabase.PExecute("DELETE FROM item_instance WHERE owner_guid = '%u'",guid); + CharacterDatabase.PExecute("DELETE FROM character_social WHERE guid = '%u' OR friend='%u'",guid,guid); + CharacterDatabase.PExecute("DELETE FROM mail WHERE receiver = '%u'",guid); + CharacterDatabase.PExecute("DELETE FROM mail_items WHERE receiver = '%u'",guid); + CharacterDatabase.PExecute("DELETE FROM character_pet WHERE owner = '%u'",guid); + CharacterDatabase.PExecute("DELETE FROM character_pet_declinedname WHERE owner = '%u'",guid); + CharacterDatabase.CommitTransaction(); + + //loginDatabase.PExecute("UPDATE realmcharacters SET numchars = numchars - 1 WHERE acctid = %d AND realmid = %d", accountId, realmID); + if(updateRealmChars) sWorld.UpdateRealmCharCount(accountId); +} + +void Player::SetMovement(PlayerMovementType pType) +{ + WorldPacket data; + switch(pType) + { + case MOVE_ROOT: data.Initialize(SMSG_FORCE_MOVE_ROOT, GetPackGUID().size()+4); break; + case MOVE_UNROOT: data.Initialize(SMSG_FORCE_MOVE_UNROOT, GetPackGUID().size()+4); break; + case MOVE_WATER_WALK: data.Initialize(SMSG_MOVE_WATER_WALK, GetPackGUID().size()+4); break; + case MOVE_LAND_WALK: data.Initialize(SMSG_MOVE_LAND_WALK, GetPackGUID().size()+4); break; + default: + sLog.outError("Player::SetMovement: Unsupported move type (%d), data not sent to client.",pType); + return; + } + data.append(GetPackGUID()); + data << uint32(0); + GetSession()->SendPacket( &data ); +} + +/* Preconditions: + - a resurrectable corpse must not be loaded for the player (only bones) + - the player must be in world +*/ +void Player::BuildPlayerRepop() +{ + if(getRace() == RACE_NIGHTELF) + CastSpell(this, 20584, true); // auras SPELL_AURA_INCREASE_SPEED(+speed in wisp form), SPELL_AURA_INCREASE_SWIM_SPEED(+swim speed in wisp form), SPELL_AURA_TRANSFORM (to wisp form) + CastSpell(this, 8326, true); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?) + + // there must be SMSG.FORCE_RUN_SPEED_CHANGE, SMSG.FORCE_SWIM_SPEED_CHANGE, SMSG.MOVE_WATER_WALK + // there must be SMSG.STOP_MIRROR_TIMER + // there we must send 888 opcode + + // the player cannot have a corpse already, only bones which are not returned by GetCorpse + if(GetCorpse()) + { + sLog.outError("BuildPlayerRepop: player %s(%d) already has a corpse", GetName(), GetGUIDLow()); + assert(false); + } + + // create a corpse and place it at the player's location + CreateCorpse(); + Corpse *corpse = GetCorpse(); + if(!corpse) + { + sLog.outError("Error creating corpse for Player %s [%u]", GetName(), GetGUIDLow()); + return; + } + GetMap()->Add(corpse); + + // convert player body to ghost + SetHealth( 1 ); + + SetMovement(MOVE_WATER_WALK); + if(!GetSession()->isLogingOut()) + SetMovement(MOVE_UNROOT); + + // BG - remove insignia related + RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); + + SendCorpseReclaimDelay(); + + // to prevent cheating + corpse->ResetGhostTime(); + + StopMirrorTimers(); //disable timers(bars) + + SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, (float)1.0); //see radius of death player? + + SetByteValue(UNIT_FIELD_BYTES_1, 3, PLAYER_STATE_FLAG_ALWAYS_STAND); +} + +void Player::SendDelayResponse(const uint32 ml_seconds) +{ + WorldPacket data( SMSG_QUERY_TIME_RESPONSE, 4+4 ); + data << (uint32)time(NULL); + data << (uint32)0; + GetSession()->SendPacket( &data ); +} + +void Player::ResurrectPlayer(float restore_percent, bool updateToWorld, bool applySickness) +{ + WorldPacket data(SMSG_DEATH_RELEASE_LOC, 4*4); // remove spirit healer position + data << uint32(-1); + data << float(0); + data << float(0); + data << float(0); + GetSession()->SendPacket(&data); + + // speed change, land walk + + // remove death flag + set aura + SetByteValue(UNIT_FIELD_BYTES_1, 3, 0x00); + if(getRace() == RACE_NIGHTELF) + RemoveAurasDueToSpell(20584); // speed bonuses + RemoveAurasDueToSpell(8326); // SPELL_AURA_GHOST + + setDeathState(ALIVE); + + SetMovement(MOVE_LAND_WALK); + SetMovement(MOVE_UNROOT); + + m_deathTimer = 0; + + // set health/powers (0- will be set in caller) + if(restore_percent>0.0f) + { + SetHealth(uint32(GetMaxHealth()*restore_percent)); + SetPower(POWER_MANA, uint32(GetMaxPower(POWER_MANA)*restore_percent)); + SetPower(POWER_RAGE, 0); + SetPower(POWER_ENERGY, uint32(GetMaxPower(POWER_ENERGY)*restore_percent)); + } + + // update visbility + ObjectAccessor::UpdateVisibilityForPlayer(this); + + // some items limited to specific map + DestroyZoneLimitedItem( true, GetZoneId()); + + if(!applySickness || getLevel() <= 10) + return; + + //Characters from level 1-10 are not affected by resurrection sickness. + //Characters from level 11-19 will suffer from one minute of sickness + //for each level they are above 10. + //Characters level 20 and up suffer from ten minutes of sickness. + int32 startLevel = sWorld.getConfig(CONFIG_DEATH_SICKNESS_LEVEL); + + if(int32(getLevel()) >= startLevel) + { + // set resurrection sickness + CastSpell(this,SPELL_ID_PASSIVE_RESURRECTION_SICKNESS,true); + + // not full duration + if(int32(getLevel()) < startLevel+9) + { + int32 delta = (int32(getLevel()) - startLevel + 1)*MINUTE; + + for(int i =0; i < 3; ++i) + { + if(Aura* Aur = GetAura(SPELL_ID_PASSIVE_RESURRECTION_SICKNESS,i)) + { + Aur->SetAuraDuration(delta*1000); + Aur->UpdateAuraDuration(); + } + } + } + } +} + +void Player::KillPlayer() +{ + SetMovement(MOVE_ROOT); + + StopMirrorTimers(); //disable timers(bars) + + setDeathState(CORPSE); + //SetFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_IN_PVP ); + + SetFlag(UNIT_DYNAMIC_FLAGS, 0x00); + ApplyModFlag(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTE_RELEASE_TIMER, !sMapStore.LookupEntry(GetMapId())->Instanceable()); + + // 6 minutes until repop at graveyard + m_deathTimer = 6*MINUTE*1000; + + UpdateCorpseReclaimDelay(); // dependent at use SetDeathPvP() call before kill + + // don't create corpse at this moment, player might be falling + + // update visibility + ObjectAccessor::UpdateObjectVisibility(this); +} + +void Player::CreateCorpse() +{ + // prevent existence 2 corpse for player + SpawnCorpseBones(); + + uint32 _uf, _pb, _pb2, _cfb1, _cfb2; + + Corpse *corpse = new Corpse( (m_ExtraFlags & PLAYER_EXTRA_PVP_DEATH) ? CORPSE_RESURRECTABLE_PVP : CORPSE_RESURRECTABLE_PVE ); + SetPvPDeath(false); + + if(!corpse->Create(objmgr.GenerateLowGuid(HIGHGUID_CORPSE), this, GetMapId(), GetPositionX(), + GetPositionY(), GetPositionZ(), GetOrientation())) + { + delete corpse; + return; + } + + _uf = GetUInt32Value(UNIT_FIELD_BYTES_0); + _pb = GetUInt32Value(PLAYER_BYTES); + _pb2 = GetUInt32Value(PLAYER_BYTES_2); + + uint8 race = (uint8)(_uf); + uint8 skin = (uint8)(_pb); + uint8 face = (uint8)(_pb >> 8); + uint8 hairstyle = (uint8)(_pb >> 16); + uint8 haircolor = (uint8)(_pb >> 24); + uint8 facialhair = (uint8)(_pb2); + + _cfb1 = ((0x00) | (race << 8) | (getGender() << 16) | (skin << 24)); + _cfb2 = ((face) | (hairstyle << 8) | (haircolor << 16) | (facialhair << 24)); + + corpse->SetUInt32Value( CORPSE_FIELD_BYTES_1, _cfb1 ); + corpse->SetUInt32Value( CORPSE_FIELD_BYTES_2, _cfb2 ); + + uint32 flags = CORPSE_FLAG_UNK2; + if(HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_HELM)) + flags |= CORPSE_FLAG_HIDE_HELM; + if(HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_CLOAK)) + flags |= CORPSE_FLAG_HIDE_CLOAK; + if(InBattleGround()) + flags |= CORPSE_FLAG_LOOTABLE; // to be able to remove insignia + corpse->SetUInt32Value( CORPSE_FIELD_FLAGS, flags ); + + corpse->SetUInt32Value( CORPSE_FIELD_DISPLAY_ID, GetNativeDisplayId() ); + + corpse->SetUInt32Value( CORPSE_FIELD_GUILD, GetGuildId() ); + + uint32 iDisplayID; + uint16 iIventoryType; + uint32 _cfi; + for (int i = 0; i < EQUIPMENT_SLOT_END; i++) + { + if(m_items[i]) + { + iDisplayID = m_items[i]->GetProto()->DisplayInfoID; + iIventoryType = (uint16)m_items[i]->GetProto()->InventoryType; + + _cfi = (uint16(iDisplayID)) | (iIventoryType)<< 24; + corpse->SetUInt32Value(CORPSE_FIELD_ITEM + i,_cfi); + } + } + + // we don't SaveToDB for players in battlegrounds so don't do it for corpses either + const MapEntry *entry = sMapStore.LookupEntry(corpse->GetMapId()); + assert(entry); + if(entry->map_type != MAP_BATTLEGROUND) + corpse->SaveToDB(); + + // register for player, but not show + ObjectAccessor::Instance().AddCorpse(corpse); +} + +void Player::SpawnCorpseBones() +{ + if(ObjectAccessor::Instance().ConvertCorpseForPlayer(GetGUID())) + SaveToDB(); // prevent loading as ghost without corpse +} + +Corpse* Player::GetCorpse() const +{ + return ObjectAccessor::Instance().GetCorpseForPlayerGUID(GetGUID()); +} + +void Player::DurabilityLossAll(double percent, bool inventory) +{ + for(int i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; i++) + if(Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i )) + DurabilityLoss(pItem,percent); + + if(inventory) + { + // bags not have durability + // for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) + + for(int i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++) + if(Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i )) + DurabilityLoss(pItem,percent); + + // keys not have durability + //for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++) + + for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) + if(Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i )) + if(ItemPrototype const *pBagProto = pBag->GetProto()) + for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + if(Item* pItem = GetItemByPos( i, j )) + DurabilityLoss(pItem,percent); + } +} + +void Player::DurabilityLoss(Item* item, double percent) +{ + if(!item ) + return; + + uint32 pMaxDurability = item ->GetUInt32Value(ITEM_FIELD_MAXDURABILITY); + + if(!pMaxDurability) + return; + + uint32 pDurabilityLoss = uint32(pMaxDurability*percent); + + if(pDurabilityLoss < 1 ) + pDurabilityLoss = 1; + + DurabilityPointsLoss(item,pDurabilityLoss); +} + +void Player::DurabilityPointsLossAll(int32 points, bool inventory) +{ + for(int i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; i++) + if(Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i )) + DurabilityPointsLoss(pItem,points); + + if(inventory) + { + // bags not have durability + // for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) + + for(int i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++) + if(Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i )) + DurabilityPointsLoss(pItem,points); + + // keys not have durability + //for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++) + + for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) + if(Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i )) + if(ItemPrototype const *pBagProto = pBag->GetProto()) + for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + if(Item* pItem = GetItemByPos( i, j )) + DurabilityPointsLoss(pItem,points); + } +} + +void Player::DurabilityPointsLoss(Item* item, int32 points) +{ + int32 pMaxDurability = item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY); + int32 pOldDurability = item->GetUInt32Value(ITEM_FIELD_DURABILITY); + int32 pNewDurability = pOldDurability - points; + + if (pNewDurability < 0) + pNewDurability = 0; + else if (pNewDurability > pMaxDurability) + pNewDurability = pMaxDurability; + + if (pOldDurability != pNewDurability) + { + // modify item stats _before_ Durability set to 0 to pass _ApplyItemMods internal check + if ( pNewDurability == 0 && pOldDurability > 0 && item->IsEquipped()) + _ApplyItemMods(item,item->GetSlot(), false); + + item->SetUInt32Value(ITEM_FIELD_DURABILITY, pNewDurability); + + // modify item stats _after_ restore durability to pass _ApplyItemMods internal check + if ( pNewDurability > 0 && pOldDurability == 0 && item->IsEquipped()) + _ApplyItemMods(item,item->GetSlot(), true); + + item->SetState(ITEM_CHANGED, this); + } +} + +void Player::DurabilityPointLossForEquipSlot(EquipmentSlots slot) +{ + if(Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, slot )) + DurabilityPointsLoss(pItem,1); +} + +uint32 Player::DurabilityRepairAll(bool cost, float discountMod, bool guildBank) +{ + uint32 TotalCost = 0; + // equipped, backpack, bags itself + for(int i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; i++) + TotalCost += DurabilityRepair(( (INVENTORY_SLOT_BAG_0 << 8) | i ),cost,discountMod, guildBank); + + // bank, buyback and keys not repaired + + // items in inventory bags + for(int j = INVENTORY_SLOT_BAG_START; j < INVENTORY_SLOT_BAG_END; j++) + for(int i = 0; i < MAX_BAG_SIZE; i++) + TotalCost += DurabilityRepair(( (j << 8) | i ),cost,discountMod, guildBank); + return TotalCost; +} + +uint32 Player::DurabilityRepair(uint16 pos, bool cost, float discountMod, bool guildBank) +{ + Item* item = GetItemByPos(pos); + + uint32 TotalCost = 0; + if(!item) + return TotalCost; + + uint32 maxDurability = item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY); + if(!maxDurability) + return TotalCost; + + uint32 curDurability = item->GetUInt32Value(ITEM_FIELD_DURABILITY); + + if(cost) + { + uint32 LostDurability = maxDurability - curDurability; + if(LostDurability>0) + { + ItemPrototype const *ditemProto = sItemStorage.LookupEntry(item->GetEntry()); + if(!ditemProto) + { + sLog.outError("ERROR: RepairDurability: Unknown item id %u", ditemProto); + return TotalCost; + } + + DurabilityCostsEntry const *dcost = sDurabilityCostsStore.LookupEntry(ditemProto->ItemLevel); + if(!dcost) + { + sLog.outError("ERROR: RepairDurability: Wrong item lvl %u", dcost); + return TotalCost; + } + + DurabilityQualityEntry const *dQualitymodEntry = sDurabilityQualityStore.LookupEntry((ditemProto->Quality+1)*2); + if(!dQualitymodEntry) + { + sLog.outError("ERROR: RepairDurability: Wrong dQualityModEntry %u", dQualitymodEntry); + return TotalCost; + } + + uint32 dmultiplier = dcost->multiplier[ItemSubClassToDurabilityMultiplierId(ditemProto->Class,ditemProto->SubClass)]; + uint32 costs = uint32(LostDurability*dmultiplier*double(dQualitymodEntry->quality_mod)); + + costs = uint32(costs * discountMod); + + if (costs==0) //fix for ITEM_QUALITY_ARTIFACT + costs = 1; + + if (guildBank) + { + if (GetGuildId()==0) + { + DEBUG_LOG("You are not member of a guild"); + return TotalCost; + } + + Guild *pGuild = objmgr.GetGuildById(GetGuildId()); + if (!pGuild) + return TotalCost; + + if (!pGuild->HasRankRight(GetRank(), GR_RIGHT_WITHDRAW_REPAIR)) + { + DEBUG_LOG("You do not have rights to withdraw for repairs"); + return TotalCost; + } + + if (pGuild->GetMemberMoneyWithdrawRem(GetGUIDLow()) < costs) + { + DEBUG_LOG("You do not have enough money withdraw amount remaining"); + return TotalCost; + } + + if (pGuild->GetGuildBankMoney() < costs) + { + DEBUG_LOG("There is not enough money in bank"); + return TotalCost; + } + + pGuild->MemberMoneyWithdraw(costs, GetGUIDLow()); + TotalCost = costs; + } + else if (GetMoney() < costs) + { + DEBUG_LOG("You do not have enough money"); + return TotalCost; + } + else + ModifyMoney( -int32(costs) ); + } + } + + item->SetUInt32Value(ITEM_FIELD_DURABILITY, maxDurability); + item->SetState(ITEM_CHANGED, this); + + // reapply mods for total broken and repaired item if equipped + if(IsEquipmentPos(pos) && !curDurability) + _ApplyItemMods(item,pos & 255, true); + return TotalCost; +} + +void Player::RepopAtGraveyard() +{ + // note: this can be called also when the player is alive + // for example from WorldSession::HandleMovementOpcodes + + AreaTableEntry const *zone = GetAreaEntryByAreaID(GetAreaId()); + + // Such zones are considered unreachable as a ghost and the player must be automatically revived + if(!isAlive() && zone && zone->flags & AREA_FLAG_NEED_FLY || GetTransport()) + { + ResurrectPlayer(0.5f); + SpawnCorpseBones(); + } + + WorldSafeLocsEntry const *ClosestGrave = NULL; + + // Special handle for battleground maps + BattleGround *bg = sBattleGroundMgr.GetBattleGround(GetBattleGroundId()); + + if(bg && (bg->GetTypeID() == BATTLEGROUND_AB || bg->GetTypeID() == BATTLEGROUND_EY)) + ClosestGrave = bg->GetClosestGraveYard(GetPositionX(), GetPositionY(), GetPositionZ(), GetTeam()); + else + ClosestGrave = objmgr.GetClosestGraveYard( GetPositionX(), GetPositionY(), GetPositionZ(), GetMapId(), GetTeam() ); + + // stop countdown until repop + m_deathTimer = 0; + + // if no grave found, stay at the current location + // and don't show spirit healer location + if(ClosestGrave) + { + TeleportTo(ClosestGrave->map_id, ClosestGrave->x, ClosestGrave->y, ClosestGrave->z, GetOrientation()); + if(isDead()) // not send if alive, because it used in TeleportTo() + { + WorldPacket data(SMSG_DEATH_RELEASE_LOC, 4*4); // show spirit healer position on minimap + data << ClosestGrave->map_id; + data << ClosestGrave->x; + data << ClosestGrave->y; + data << ClosestGrave->z; + GetSession()->SendPacket(&data); + } + } +} + +void Player::JoinedChannel(Channel *c) +{ + m_channels.push_back(c); +} + +void Player::LeftChannel(Channel *c) +{ + m_channels.remove(c); +} + +void Player::CleanupChannels() +{ + while(!m_channels.empty()) + { + Channel* ch = *m_channels.begin(); + m_channels.erase(m_channels.begin()); // remove from player's channel list + ch->Leave(GetGUID(), false); // not send to client, not remove from player's channel list + if (ChannelMgr* cMgr = channelMgr(GetTeam())) + cMgr->LeftChannel(ch->GetName()); // deleted channel if empty + + } + sLog.outDebug("Player: channels cleaned up!"); +} + +void Player::UpdateLocalChannels(uint32 newZone ) +{ + if(m_channels.empty()) + return; + + AreaTableEntry const* current_zone = GetAreaEntryByAreaID(newZone); + if(!current_zone) + return; + + ChannelMgr* cMgr = channelMgr(GetTeam()); + if(!cMgr) + return; + + std::string current_zone_name = current_zone->area_name[GetSession()->GetSessionDbcLocale()]; + + for(JoinedChannelsList::iterator i = m_channels.begin(), next; i != m_channels.end(); i = next) + { + next = i; ++next; + + // skip non built-in channels + if(!(*i)->IsConstant()) + continue; + + ChatChannelsEntry const* ch = GetChannelEntryFor((*i)->GetChannelId()); + if(!ch) + continue; + + if((ch->flags & 4) == 4) // global channel without zone name in pattern + continue; + + // new channel + char new_channel_name_buf[100]; + snprintf(new_channel_name_buf,100,ch->pattern[m_session->GetSessionDbcLocale()],current_zone_name.c_str()); + Channel* new_channel = cMgr->GetJoinChannel(new_channel_name_buf,ch->ChannelID); + + if((*i)!=new_channel) + { + new_channel->Join(GetGUID(),""); // will output Changed Channel: N. Name + + // leave old channel + (*i)->Leave(GetGUID(),false); // not send leave channel, it already replaced at client + std::string name = (*i)->GetName(); // stroe name, (*i)erase in LeftChannel + LeftChannel(*i); // remove from player's channel list + cMgr->LeftChannel(name); // delete if empty + } + } + sLog.outDebug("Player: channels cleaned up!"); +} + +void Player::LeaveLFGChannel() +{ + for(JoinedChannelsList::iterator i = m_channels.begin(); i != m_channels.end(); ++i ) + { + if((*i)->IsLFG()) + { + (*i)->Leave(GetGUID()); + break; + } + } +} + +void Player::UpdateDefense() +{ + uint32 defense_skill_gain = sWorld.getConfig(CONFIG_SKILL_GAIN_DEFENSE); + + if(UpdateSkill(SKILL_DEFENSE,defense_skill_gain)) + { + // update dependent from defense skill part + UpdateDefenseBonusesMod(); + } +} + +void Player::HandleBaseModValue(BaseModGroup modGroup, BaseModType modType, float amount, bool apply, bool affectStats) +{ + if(modGroup >= BASEMOD_END || modType >= MOD_END) + { + sLog.outError("ERROR in HandleBaseModValue(): nonexisted BaseModGroup of wrong BaseModType!"); + return; + } + + float val = 1.0f; + + switch(modType) + { + case FLAT_MOD: + m_auraBaseMod[modGroup][modType] += apply ? amount : -amount; + break; + case PCT_MOD: + if(amount <= -100.0f) + amount = -200.0f; + + val = (100.0f + amount) / 100.0f; + m_auraBaseMod[modGroup][modType] *= apply ? val : (1.0f/val); + break; + } + + if(!CanModifyStats()) + return; + + switch(modGroup) + { + case CRIT_PERCENTAGE: UpdateCritPercentage(BASE_ATTACK); break; + case RANGED_CRIT_PERCENTAGE: UpdateCritPercentage(RANGED_ATTACK); break; + case OFFHAND_CRIT_PERCENTAGE: UpdateCritPercentage(OFF_ATTACK); break; + case SHIELD_BLOCK_VALUE: UpdateShieldBlockValue(); break; + default: break; + } +} + +float Player::GetBaseModValue(BaseModGroup modGroup, BaseModType modType) const +{ + if(modGroup >= BASEMOD_END || modType > MOD_END) + { + sLog.outError("ERROR: trial to access nonexisted BaseModGroup or wrong BaseModType!"); + return 0.0f; + } + + if(modType == PCT_MOD && m_auraBaseMod[modGroup][PCT_MOD] <= 0.0f) + return 0.0f; + + return m_auraBaseMod[modGroup][modType]; +} + +float Player::GetTotalBaseModValue(BaseModGroup modGroup) const +{ + if(modGroup >= BASEMOD_END) + { + sLog.outError("ERROR: wrong BaseModGroup in GetTotalBaseModValue()!"); + return 0.0f; + } + + if(m_auraBaseMod[modGroup][PCT_MOD] <= 0.0f) + return 0.0f; + + return m_auraBaseMod[modGroup][FLAT_MOD] * m_auraBaseMod[modGroup][PCT_MOD]; +} + +uint32 Player::GetShieldBlockValue() const +{ + BaseModGroup modGroup = SHIELD_BLOCK_VALUE; + + float value = GetTotalBaseModValue(modGroup) + GetStat(STAT_STRENGTH)/20 - 1; + + value = (value < 0) ? 0 : value; + + return uint32(value); +} + +float Player::GetMeleeCritFromAgility() +{ + uint32 level = getLevel(); + uint32 pclass = getClass(); + + if (level>GT_MAX_LEVEL) level = GT_MAX_LEVEL; + + GtChanceToMeleeCritBaseEntry const *critBase = sGtChanceToMeleeCritBaseStore.LookupEntry(pclass-1); + GtChanceToMeleeCritEntry const *critRatio = sGtChanceToMeleeCritStore.LookupEntry((pclass-1)*GT_MAX_LEVEL + level-1); + if (critBase==NULL || critRatio==NULL) + return 0.0f; + + float crit=critBase->base + GetStat(STAT_AGILITY)*critRatio->ratio; + return crit*100.0f; +} + +float Player::GetDodgeFromAgility() +{ + // Table for base dodge values + float dodge_base[MAX_CLASSES] = { + 0.0075f, // Warrior + 0.00652f, // Paladin + -0.0545f, // Hunter + -0.0059f, // Rogue + 0.03183f, // Priest + 0.0114f, // DK + 0.0167f, // Shaman + 0.034575f, // Mage + 0.02011f, // Warlock + 0.0f, // ?? + -0.0187f // Druid + }; + // Crit/agility to dodge/agility coefficient multipliers + float crit_to_dodge[MAX_CLASSES] = { + 1.1f, // Warrior + 1.0f, // Paladin + 1.6f, // Hunter + 2.0f, // Rogue + 1.0f, // Priest + 1.0f, // DK? + 1.0f, // Shaman + 1.0f, // Mage + 1.0f, // Warlock + 0.0f, // ?? + 1.7f // Druid + }; + + uint32 level = getLevel(); + uint32 pclass = getClass(); + + if (level>GT_MAX_LEVEL) level = GT_MAX_LEVEL; + + // Dodge per agility for most classes equal crit per agility (but for some classes need apply some multiplier) + GtChanceToMeleeCritEntry const *dodgeRatio = sGtChanceToMeleeCritStore.LookupEntry((pclass-1)*GT_MAX_LEVEL + level-1); + if (dodgeRatio==NULL || pclass > MAX_CLASSES) + return 0.0f; + + float dodge=dodge_base[pclass-1] + GetStat(STAT_AGILITY) * dodgeRatio->ratio * crit_to_dodge[pclass-1]; + return dodge*100.0f; +} + +float Player::GetSpellCritFromIntellect() +{ + uint32 level = getLevel(); + uint32 pclass = getClass(); + + if (level>GT_MAX_LEVEL) level = GT_MAX_LEVEL; + + GtChanceToSpellCritBaseEntry const *critBase = sGtChanceToSpellCritBaseStore.LookupEntry(pclass-1); + GtChanceToSpellCritEntry const *critRatio = sGtChanceToSpellCritStore.LookupEntry((pclass-1)*GT_MAX_LEVEL + level-1); + if (critBase==NULL || critRatio==NULL) + return 0.0f; + + float crit=critBase->base + GetStat(STAT_INTELLECT)*critRatio->ratio; + return crit*100.0f; +} + +float Player::GetRatingCoefficient(CombatRating cr) const +{ + uint32 level = getLevel(); + + if (level>GT_MAX_LEVEL) level = GT_MAX_LEVEL; + + GtCombatRatingsEntry const *Rating = sGtCombatRatingsStore.LookupEntry(cr*GT_MAX_LEVEL+level-1); + if (Rating == NULL) + return 1.0f; // By default use minimum coefficient (not must be called) + + return Rating->ratio; +} + +float Player::GetRatingBonusValue(CombatRating cr) const +{ + return float(GetUInt32Value(PLAYER_FIELD_COMBAT_RATING_1 + cr)) / GetRatingCoefficient(cr); +} + +uint32 Player::GetMeleeCritDamageReduction(uint32 damage) const +{ + float melee = GetRatingBonusValue(CR_CRIT_TAKEN_MELEE)*2.0f; + if (melee>25.0f) melee = 25.0f; + return uint32 (melee * damage /100.0f); +} + +uint32 Player::GetRangedCritDamageReduction(uint32 damage) const +{ + float ranged = GetRatingBonusValue(CR_CRIT_TAKEN_RANGED)*2.0f; + if (ranged>25.0f) ranged=25.0f; + return uint32 (ranged * damage /100.0f); +} + +uint32 Player::GetSpellCritDamageReduction(uint32 damage) const +{ + float spell = GetRatingBonusValue(CR_CRIT_TAKEN_SPELL)*2.0f; + // In wow script resilience limited to 25% + if (spell>25.0f) + spell = 25.0f; + return uint32 (spell * damage / 100.0f); +} + +uint32 Player::GetDotDamageReduction(uint32 damage) const +{ + float spellDot = GetRatingBonusValue(CR_CRIT_TAKEN_SPELL); + // Dot resilience not limited (limit it by 100%) + if (spellDot > 100.0f) + spellDot = 100.0f; + return uint32 (spellDot * damage / 100.0f); +} + +float Player::GetExpertiseDodgeOrParryReduction(WeaponAttackType attType) const +{ + switch (attType) + { + case BASE_ATTACK: + return GetUInt32Value(PLAYER_EXPERTISE) / 4.0f; + case OFF_ATTACK: + return GetUInt32Value(PLAYER_OFFHAND_EXPERTISE) / 4.0f; + default: + break; + } + return 0.0f; +} + +float Player::OCTRegenHPPerSpirit() +{ + uint32 level = getLevel(); + uint32 pclass = getClass(); + + if (level>GT_MAX_LEVEL) level = GT_MAX_LEVEL; + + GtOCTRegenHPEntry const *baseRatio = sGtOCTRegenHPStore.LookupEntry((pclass-1)*GT_MAX_LEVEL + level-1); + GtRegenHPPerSptEntry const *moreRatio = sGtRegenHPPerSptStore.LookupEntry((pclass-1)*GT_MAX_LEVEL + level-1); + if (baseRatio==NULL || moreRatio==NULL) + return 0.0f; + + // Formula from PaperDollFrame script + float spirit = GetStat(STAT_SPIRIT); + float baseSpirit = spirit; + if (baseSpirit>50) baseSpirit = 50; + float moreSpirit = spirit - baseSpirit; + float regen = baseSpirit * baseRatio->ratio + moreSpirit * moreRatio->ratio; + return regen; +} + +float Player::OCTRegenMPPerSpirit() +{ + uint32 level = getLevel(); + uint32 pclass = getClass(); + + if (level>GT_MAX_LEVEL) level = GT_MAX_LEVEL; + +// GtOCTRegenMPEntry const *baseRatio = sGtOCTRegenMPStore.LookupEntry((pclass-1)*GT_MAX_LEVEL + level-1); + GtRegenMPPerSptEntry const *moreRatio = sGtRegenMPPerSptStore.LookupEntry((pclass-1)*GT_MAX_LEVEL + level-1); + if (moreRatio==NULL) + return 0.0f; + + // Formula get from PaperDollFrame script + float spirit = GetStat(STAT_SPIRIT); + float regen = spirit * moreRatio->ratio; + return regen; +} + +void Player::ApplyRatingMod(CombatRating cr, int32 value, bool apply) +{ + ApplyModUInt32Value(PLAYER_FIELD_COMBAT_RATING_1 + cr, value, apply); + + float RatingCoeffecient = GetRatingCoefficient(cr); + float RatingChange = 0.0f; + + bool affectStats = CanModifyStats(); + + switch (cr) + { + case CR_WEAPON_SKILL: // Implemented in Unit::RollMeleeOutcomeAgainst + case CR_DEFENSE_SKILL: + UpdateDefenseBonusesMod(); + break; + case CR_DODGE: + UpdateDodgePercentage(); + break; + case CR_PARRY: + UpdateParryPercentage(); + break; + case CR_BLOCK: + UpdateBlockPercentage(); + break; + case CR_HIT_MELEE: + RatingChange = value / RatingCoeffecient; + m_modMeleeHitChance += apply ? RatingChange : -RatingChange; + break; + case CR_HIT_RANGED: + RatingChange = value / RatingCoeffecient; + m_modRangedHitChance += apply ? RatingChange : -RatingChange; + break; + case CR_HIT_SPELL: + RatingChange = value / RatingCoeffecient; + m_modSpellHitChance += apply ? RatingChange : -RatingChange; + break; + case CR_CRIT_MELEE: + if(affectStats) + { + UpdateCritPercentage(BASE_ATTACK); + UpdateCritPercentage(OFF_ATTACK); + } + break; + case CR_CRIT_RANGED: + if(affectStats) + UpdateCritPercentage(RANGED_ATTACK); + break; + case CR_CRIT_SPELL: + if(affectStats) + UpdateAllSpellCritChances(); + break; + case CR_HIT_TAKEN_MELEE: // Implemented in Unit::MeleeMissChanceCalc + case CR_HIT_TAKEN_RANGED: + break; + case CR_HIT_TAKEN_SPELL: // Implemented in Unit::MagicSpellHitResult + break; + case CR_CRIT_TAKEN_MELEE: // Implemented in Unit::RollMeleeOutcomeAgainst (only for chance to crit) + case CR_CRIT_TAKEN_RANGED: + break; + case CR_CRIT_TAKEN_SPELL: // Implemented in Unit::SpellCriticalBonus (only for chance to crit) + break; + case CR_HASTE_MELEE: + RatingChange = value / RatingCoeffecient; + ApplyAttackTimePercentMod(BASE_ATTACK,RatingChange,apply); + ApplyAttackTimePercentMod(OFF_ATTACK,RatingChange,apply); + break; + case CR_HASTE_RANGED: + RatingChange = value / RatingCoeffecient; + ApplyAttackTimePercentMod(RANGED_ATTACK, RatingChange, apply); + break; + case CR_HASTE_SPELL: + RatingChange = value / RatingCoeffecient; + ApplyCastTimePercentMod(RatingChange,apply); + break; + case CR_WEAPON_SKILL_MAINHAND: // Implemented in Unit::RollMeleeOutcomeAgainst + case CR_WEAPON_SKILL_OFFHAND: + case CR_WEAPON_SKILL_RANGED: + break; + case CR_EXPERTISE: + if(affectStats) + { + UpdateExpertise(BASE_ATTACK); + UpdateExpertise(OFF_ATTACK); + } + break; + } +} + +void Player::SetRegularAttackTime() +{ + for(int i = 0; i < MAX_ATTACK; ++i) + { + Item *tmpitem = GetWeaponForAttack(WeaponAttackType(i)); + if(tmpitem && !tmpitem->IsBroken()) + { + ItemPrototype const *proto = tmpitem->GetProto(); + if(proto->Delay) + SetAttackTime(WeaponAttackType(i), proto->Delay); + else + SetAttackTime(WeaponAttackType(i), BASE_ATTACK_TIME); + } + } +} + +//skill+step, checking for max value +bool Player::UpdateSkill(uint32 skill_id, uint32 step) +{ + if(!skill_id) + return false; + + uint16 i=0; + for (; i < PLAYER_MAX_SKILLS; i++) + if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill_id) + break; + + if(i>=PLAYER_MAX_SKILLS) + return false; + + uint32 data = GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i)); + uint32 value = SKILL_VALUE(data); + uint32 max = SKILL_MAX(data); + + if ((!max) || (!value) || (value >= max)) + return false; + + if (value*512 < max*urand(0,512)) + { + uint32 new_value = value+step; + if(new_value > max) + new_value = max; + + SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(new_value,max)); + return true; + } + + return false; +} + +inline int SkillGainChance(uint32 SkillValue, uint32 GrayLevel, uint32 GreenLevel, uint32 YellowLevel) +{ + if ( SkillValue >= GrayLevel ) + return sWorld.getConfig(CONFIG_SKILL_CHANCE_GREY)*10; + if ( SkillValue >= GreenLevel ) + return sWorld.getConfig(CONFIG_SKILL_CHANCE_GREEN)*10; + if ( SkillValue >= YellowLevel ) + return sWorld.getConfig(CONFIG_SKILL_CHANCE_YELLOW)*10; + return sWorld.getConfig(CONFIG_SKILL_CHANCE_ORANGE)*10; +} + +bool Player::UpdateCraftSkill(uint32 spellid) +{ + sLog.outDebug("UpdateCraftSkill spellid %d", spellid); + + SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(spellid); + SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(spellid); + + for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx) + { + if(_spell_idx->second->skillId) + { + uint32 SkillValue = GetPureSkillValue(_spell_idx->second->skillId); + + // Alchemy Discoveries here + SpellEntry const* spellEntry = sSpellStore.LookupEntry(spellid); + if(spellEntry && spellEntry->Mechanic==MECHANIC_DISCOVERY) + { + if(uint32 discoveredSpell = GetSkillDiscoverySpell(_spell_idx->second->skillId, spellid, this)) + learnSpell(discoveredSpell); + } + + uint32 craft_skill_gain = sWorld.getConfig(CONFIG_SKILL_GAIN_CRAFTING); + + return UpdateSkillPro(_spell_idx->second->skillId, SkillGainChance(SkillValue, + _spell_idx->second->max_value, + (_spell_idx->second->max_value + _spell_idx->second->min_value)/2, + _spell_idx->second->min_value), + craft_skill_gain); + } + } + return false; +} + +bool Player::UpdateGatherSkill(uint32 SkillId, uint32 SkillValue, uint32 RedLevel, uint32 Multiplicator ) +{ + sLog.outDebug("UpdateGatherSkill(SkillId %d SkillLevel %d RedLevel %d)", SkillId, SkillValue, RedLevel); + + uint32 gathering_skill_gain = sWorld.getConfig(CONFIG_SKILL_GAIN_GATHERING); + + // For skinning and Mining chance decrease with level. 1-74 - no decrease, 75-149 - 2 times, 225-299 - 8 times + switch (SkillId) + { + case SKILL_HERBALISM: + case SKILL_LOCKPICKING: + case SKILL_JEWELCRAFTING: + return UpdateSkillPro(SkillId, SkillGainChance(SkillValue, RedLevel+100, RedLevel+50, RedLevel+25)*Multiplicator,gathering_skill_gain); + case SKILL_SKINNING: + if( sWorld.getConfig(CONFIG_SKILL_CHANCE_SKINNING_STEPS)==0) + return UpdateSkillPro(SkillId, SkillGainChance(SkillValue, RedLevel+100, RedLevel+50, RedLevel+25)*Multiplicator,gathering_skill_gain); + else + return UpdateSkillPro(SkillId, (SkillGainChance(SkillValue, RedLevel+100, RedLevel+50, RedLevel+25)*Multiplicator) >> (SkillValue/sWorld.getConfig(CONFIG_SKILL_CHANCE_SKINNING_STEPS)), gathering_skill_gain); + case SKILL_MINING: + if (sWorld.getConfig(CONFIG_SKILL_CHANCE_MINING_STEPS)==0) + return UpdateSkillPro(SkillId, SkillGainChance(SkillValue, RedLevel+100, RedLevel+50, RedLevel+25)*Multiplicator,gathering_skill_gain); + else + return UpdateSkillPro(SkillId, (SkillGainChance(SkillValue, RedLevel+100, RedLevel+50, RedLevel+25)*Multiplicator) >> (SkillValue/sWorld.getConfig(CONFIG_SKILL_CHANCE_MINING_STEPS)),gathering_skill_gain); + } + return false; +} + +bool Player::UpdateFishingSkill() +{ + sLog.outDebug("UpdateFishingSkill"); + + uint32 SkillValue = GetPureSkillValue(SKILL_FISHING); + + int32 chance = SkillValue < 75 ? 100 : 2500/(SkillValue-50); + + uint32 gathering_skill_gain = sWorld.getConfig(CONFIG_SKILL_GAIN_GATHERING); + + return UpdateSkillPro(SKILL_FISHING,chance*10,gathering_skill_gain); +} + +bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step) +{ + sLog.outDebug("UpdateSkillPro(SkillId %d, Chance %3.1f%%)", SkillId, Chance/10.0); + if ( !SkillId ) + return false; + + if(Chance <= 0) // speedup in 0 chance case + { + sLog.outDebug("Player::UpdateSkillPro Chance=%3.1f%% missed", Chance/10.0); + return false; + } + + uint16 i=0; + for (; i < PLAYER_MAX_SKILLS; i++) + if ( SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_INDEX(i))) == SkillId ) break; + if ( i >= PLAYER_MAX_SKILLS ) + return false; + + uint32 data = GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i)); + uint16 SkillValue = SKILL_VALUE(data); + uint16 MaxValue = SKILL_MAX(data); + + if ( !MaxValue || !SkillValue || SkillValue >= MaxValue ) + return false; + + int32 Roll = irand(1,1000); + + if ( Roll <= Chance ) + { + uint32 new_value = SkillValue+step; + if(new_value > MaxValue) + new_value = MaxValue; + + SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(new_value,MaxValue)); + sLog.outDebug("Player::UpdateSkillPro Chance=%3.1f%% taken", Chance/10.0); + return true; + } + + sLog.outDebug("Player::UpdateSkillPro Chance=%3.1f%% missed", Chance/10.0); + return false; +} + +void Player::UpdateWeaponSkill (WeaponAttackType attType) +{ + // no skill gain in pvp + Unit *pVictim = getVictim(); + if(pVictim && pVictim->GetTypeId() == TYPEID_PLAYER) + return; + + if(IsInFeralForm()) + return; // always maximized SKILL_FERAL_COMBAT in fact + + if(m_form == FORM_TREE) + return; // use weapon but not skill up + + uint32 weapon_skill_gain = sWorld.getConfig(CONFIG_SKILL_GAIN_WEAPON); + + switch(attType) + { + case BASE_ATTACK: + { + Item *tmpitem = GetWeaponForAttack(attType,true); + + if (!tmpitem) + UpdateSkill(SKILL_UNARMED,weapon_skill_gain); + else if(tmpitem->GetProto()->SubClass != ITEM_SUBCLASS_WEAPON_FISHING_POLE) + UpdateSkill(tmpitem->GetSkill(),weapon_skill_gain); + break; + } + case OFF_ATTACK: + case RANGED_ATTACK: + { + Item *tmpitem = GetWeaponForAttack(attType,true); + if (tmpitem) + UpdateSkill(tmpitem->GetSkill(),weapon_skill_gain); + break; + } + } + UpdateAllCritPercentages(); +} + +void Player::UpdateCombatSkills(Unit *pVictim, WeaponAttackType attType, MeleeHitOutcome outcome, bool defence) +{ + switch(outcome) + { + case MELEE_HIT_CRIT: + case MELEE_HIT_DODGE: + case MELEE_HIT_PARRY: + case MELEE_HIT_BLOCK: + case MELEE_HIT_BLOCK_CRIT: + return; + + default: + break; + } + + uint32 plevel = getLevel(); // if defense than pVictim == attacker + uint32 greylevel = MaNGOS::XP::GetGrayLevel(plevel); + uint32 moblevel = pVictim->getLevelForTarget(this); + if(moblevel < greylevel) + return; + + if (moblevel > plevel + 5) + moblevel = plevel + 5; + + uint32 lvldif = moblevel - greylevel; + if(lvldif < 3) + lvldif = 3; + + uint32 skilldif = 5 * plevel - (defence ? GetBaseDefenseSkillValue() : GetBaseWeaponSkillValue(attType)); + if(skilldif <= 0) + return; + + float chance = float(3 * lvldif * skilldif) / plevel; + if(!defence) + { + if(getClass() == CLASS_WARRIOR || getClass() == CLASS_ROGUE) + chance *= 0.1f * GetStat(STAT_INTELLECT); + } + + chance = chance < 1.0f ? 1.0f : chance; //minimum chance to increase skill is 1% + + if(roll_chance_f(chance)) + { + if(defence) + UpdateDefense(); + else + UpdateWeaponSkill(attType); + } + else + return; +} + +void Player::ModifySkillBonus(uint32 skillid,int32 val, bool talent) +{ + for (uint16 i=0; i < PLAYER_MAX_SKILLS; i++) + if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skillid) + { + uint32 bonus_val = GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i)); + int16 temp_bonus = SKILL_TEMP_BONUS(bonus_val); + int16 perm_bonus = SKILL_PERM_BONUS(bonus_val); + + if(talent) // permanent bonus stored in high part + SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i),MAKE_SKILL_BONUS(temp_bonus,perm_bonus+val)); + else // temporary/item bonus stored in low part + SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i),MAKE_SKILL_BONUS(temp_bonus+val,perm_bonus)); + return; + } +} + +void Player::UpdateMaxSkills() +{ + uint16 maxconfskill = sWorld.GetConfigMaxSkillValue(); + + for (uint16 i=0; i < PLAYER_MAX_SKILLS; i++) + if (GetUInt32Value(PLAYER_SKILL_INDEX(i))) + { + uint32 pskill = GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF; + + SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(pskill); + if(!pSkill) + continue; + + if(GetSkillRangeType(pSkill,false) != SKILL_RANGE_LEVEL) + continue; + + uint32 data = GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i)); + uint32 max = SKILL_MAX(data); + uint32 val = SKILL_VALUE(data); + + // update only level dependent max skill values + if(max!=1 && max != maxconfskill) + { + uint32 max_Skill = GetMaxSkillValueForLevel(); + SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(val,max_Skill)); + } + } +} + +void Player::UpdateSkillsToMaxSkillsForLevel() +{ + for (uint16 i=0; i < PLAYER_MAX_SKILLS; i++) + if (GetUInt32Value(PLAYER_SKILL_INDEX(i))) + { + uint32 pskill = GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF; + if( IsProfessionSkill(pskill) || pskill == SKILL_RIDING ) + continue; + uint32 data = GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i)); + + uint32 max = SKILL_MAX(data); + + if(max > 1) + SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(max,max)); + + if(pskill == SKILL_DEFENSE) + { + UpdateBlockPercentage(); + } + } +} + +// This functions sets a skill line value (and adds if doesn't exist yet) +// To "remove" a skill line, set it's values to zero +void Player::SetSkill(uint32 id, uint16 currVal, uint16 maxVal) +{ + if(!id) + return; + + uint16 i=0; + for (; i < PLAYER_MAX_SKILLS; i++) + if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == id) break; + + if(isecond->state == PLAYERSPELL_REMOVED) + continue; + + SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(itr->first); + SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(itr->first); + + for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx) + { + if (_spell_idx->second->skillId == id) + { + // this may remove more than one spell (dependants) + removeSpell(itr->first); + next = m_spells.begin(); + break; + } + } + } + } + } + else if(currVal) //add + { + for (i=0; i < PLAYER_MAX_SKILLS; i++) + if (!GetUInt32Value(PLAYER_SKILL_INDEX(i))) + { + SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(id); + if(!pSkill) + { + sLog.outError("Skill not found in SkillLineStore: skill #%u", id); + return; + } + // enable unlearn button for primary professions only + if (pSkill->categoryId == SKILL_CATEGORY_PROFESSION) + SetUInt32Value(PLAYER_SKILL_INDEX(i), MAKE_PAIR32(id,1)); + else + SetUInt32Value(PLAYER_SKILL_INDEX(i), MAKE_PAIR32(id,0)); + SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(currVal,maxVal)); + + // apply skill bonuses + SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i),0); + + // temporary bonuses + AuraList const& mModSkill = GetAurasByType(SPELL_AURA_MOD_SKILL); + for(AuraList::const_iterator i = mModSkill.begin(); i != mModSkill.end(); ++i) + if ((*i)->GetModifier()->m_miscvalue == int32(id)) + (*i)->ApplyModifier(true); + + // permanent bonuses + AuraList const& mModSkillTalent = GetAurasByType(SPELL_AURA_MOD_SKILL_TALENT); + for(AuraList::const_iterator i = mModSkillTalent.begin(); i != mModSkillTalent.end(); ++i) + if ((*i)->GetModifier()->m_miscvalue == int32(id)) + (*i)->ApplyModifier(true); + + // Learn all spells for skill + learnSkillRewardedSpells(id); + return; + } + } +} + +bool Player::HasSkill(uint32 skill) const +{ + if(!skill)return false; + for (uint16 i=0; i < PLAYER_MAX_SKILLS; i++) + { + if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill) + { + return true; + } + } + return false; +} + +uint16 Player::GetSkillValue(uint32 skill) const +{ + if(!skill) + return 0; + + for (uint16 i=0; i < PLAYER_MAX_SKILLS; i++) + { + if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill) + { + uint32 bonus = GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i)); + + int32 result = int32(SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i)))); + result += SKILL_TEMP_BONUS(bonus); + result += SKILL_PERM_BONUS(bonus); + return result < 0 ? 0 : result; + } + } + return 0; +} + +uint16 Player::GetMaxSkillValue(uint32 skill) const +{ + if(!skill)return 0; + for (uint16 i=0; i < PLAYER_MAX_SKILLS; i++) + { + if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill) + { + uint32 bonus = GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i)); + + int32 result = int32(SKILL_MAX(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i)))); + result += SKILL_TEMP_BONUS(bonus); + result += SKILL_PERM_BONUS(bonus); + return result < 0 ? 0 : result; + } + } + return 0; +} + +uint16 Player::GetPureMaxSkillValue(uint32 skill) const +{ + if(!skill)return 0; + for (uint16 i=0; i < PLAYER_MAX_SKILLS; i++) + { + if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill) + { + return SKILL_MAX(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i))); + } + } + return 0; +} + +uint16 Player::GetBaseSkillValue(uint32 skill) const +{ + if(!skill)return 0; + for (uint16 i=0; i < PLAYER_MAX_SKILLS; i++) + { + if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill) + { + int32 result = int32(SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i)))); + result += SKILL_PERM_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i))); + return result < 0 ? 0 : result; + } + } + return 0; +} + +uint16 Player::GetPureSkillValue(uint32 skill) const +{ + if(!skill)return 0; + for (uint16 i=0; i < PLAYER_MAX_SKILLS; i++) + { + if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill) + { + return SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i))); + } + } + return 0; +} + +int16 Player::GetSkillTempBonusValue(uint32 skill) const +{ + if(!skill) + return 0; + + for (int i = 0; i < PLAYER_MAX_SKILLS; i++) + { + if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill) + { + return SKILL_TEMP_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i))); + } + } + + return 0; +} + +void Player::SendInitialActionButtons() +{ + sLog.outDetail( "Initializing Action Buttons for '%u'", GetGUIDLow() ); + + WorldPacket data(SMSG_ACTION_BUTTONS, (MAX_ACTION_BUTTONS*4)); + for(int button = 0; button < MAX_ACTION_BUTTONS; ++button) + { + ActionButtonList::const_iterator itr = m_actionButtons.find(button); + if(itr != m_actionButtons.end() && itr->second.uState != ACTIONBUTTON_DELETED) + { + data << uint16(itr->second.action); + data << uint8(itr->second.misc); + data << uint8(itr->second.type); + } + else + { + data << uint32(0); + } + } + + GetSession()->SendPacket( &data ); + sLog.outDetail( "Action Buttons for '%u' Initialized", GetGUIDLow() ); +} + +void Player::addActionButton(const uint8 button, const uint16 action, const uint8 type, const uint8 misc) +{ + if(button >= MAX_ACTION_BUTTONS) + { + sLog.outError( "Action %u not added into button %u for player %s: button must be < 132", action, button, GetName() ); + return; + } + + // check cheating with adding non-known spells to action bar + if(type==ACTION_BUTTON_SPELL) + { + if(!sSpellStore.LookupEntry(action)) + { + sLog.outError( "Action %u not added into button %u for player %s: spell not exist", action, button, GetName() ); + return; + } + + if(!HasSpell(action)) + { + sLog.outError( "Action %u not added into button %u for player %s: player don't known this spell", action, button, GetName() ); + return; + } + } + + ActionButtonList::iterator buttonItr = m_actionButtons.find(button); + + if (buttonItr==m_actionButtons.end()) + { // just add new button + m_actionButtons[button] = ActionButton(action,type,misc); + } + else + { // change state of current button + ActionButtonUpdateState uState = buttonItr->second.uState; + buttonItr->second = ActionButton(action,type,misc); + if (uState != ACTIONBUTTON_NEW) buttonItr->second.uState = ACTIONBUTTON_CHANGED; + }; + + sLog.outDetail( "Player '%u' Added Action '%u' to Button '%u'", GetGUIDLow(), action, button ); +} + +void Player::removeActionButton(uint8 button) +{ + ActionButtonList::iterator buttonItr = m_actionButtons.find(button); + if (buttonItr==m_actionButtons.end()) + return; + + if(buttonItr->second.uState==ACTIONBUTTON_NEW) + m_actionButtons.erase(buttonItr); // new and not saved + else + buttonItr->second.uState = ACTIONBUTTON_DELETED; // saved, will deleted at next save + + sLog.outDetail( "Action Button '%u' Removed from Player '%u'", button, GetGUIDLow() ); +} + +void Player::SetDontMove(bool dontMove) +{ + m_dontMove = dontMove; +} + +bool Player::SetPosition(float x, float y, float z, float orientation, bool teleport) +{ + // prevent crash when a bad coord is sent by the client + if(!MaNGOS::IsValidMapCoord(x,y,z,orientation)) + { + sLog.outDebug("Player::SetPosition(%f, %f, %f, %f, %d) .. bad coordinates for player %d!",x,y,z,orientation,teleport,GetGUIDLow()); + return false; + } + + Map *m = MapManager::Instance().GetMap(GetMapId(), this); + + const float old_x = GetPositionX(); + const float old_y = GetPositionY(); + const float old_z = GetPositionZ(); + const float old_r = GetOrientation(); + + if( teleport || old_x != x || old_y != y || old_z != z || old_r != orientation ) + { + if (teleport || old_x != x || old_y != y || old_z != z) + RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOVE | AURA_INTERRUPT_FLAG_TURNING); + else + RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TURNING); + + // move and update visible state if need + m->PlayerRelocation(this, x, y, z, orientation); + + // reread after Map::Relocation + m = MapManager::Instance().GetMap(GetMapId(), this); + x = GetPositionX(); + y = GetPositionY(); + z = GetPositionZ(); + } + + // code block for underwater state update + UpdateUnderwaterState(m, x, y, z); + + + CheckExploreSystem(); + + // group update + if(GetGroup()) + SetGroupUpdateFlag(GROUP_UPDATE_FLAG_POSITION); + + return true; +} + +void Player::SaveRecallPosition() +{ + m_recallMap = GetMapId(); + m_recallX = GetPositionX(); + m_recallY = GetPositionY(); + m_recallZ = GetPositionZ(); + m_recallO = GetOrientation(); +} + +void Player::SendMessageToSet(WorldPacket *data, bool self) +{ + MapManager::Instance().GetMap(GetMapId(), this)->MessageBroadcast(this, data, self); +} + +void Player::SendMessageToSetInRange(WorldPacket *data, float dist, bool self) +{ + MapManager::Instance().GetMap(GetMapId(), this)->MessageDistBroadcast(this, data, dist, self); +} + +void Player::SendMessageToSetInRange(WorldPacket *data, float dist, bool self, bool own_team_only) +{ + MapManager::Instance().GetMap(GetMapId(), this)->MessageDistBroadcast(this, data, dist, self,own_team_only); +} + +void Player::SendDirectMessage(WorldPacket *data) +{ + GetSession()->SendPacket(data); +} + +void Player::CheckExploreSystem() +{ + if (!isAlive()) + return; + + if (isInFlight()) + return; + + uint16 areaFlag=MapManager::Instance().GetBaseMap(GetMapId())->GetAreaFlag(GetPositionX(),GetPositionY()); + if(areaFlag==0xffff) + return; + int offset = areaFlag / 32; + + if(offset >= 128) + { + sLog.outError("ERROR: Wrong area flag %u in map data for (X: %f Y: %f) point to field PLAYER_EXPLORED_ZONES_1 + %u ( %u must be < 64 ).",areaFlag,GetPositionX(),GetPositionY(),offset,offset); + return; + } + + uint32 val = (uint32)(1 << (areaFlag % 32)); + uint32 currFields = GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset); + + if( !(currFields & val) ) + { + SetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset, (uint32)(currFields | val)); + + AreaTableEntry const *p = GetAreaEntryByAreaFlagAndMap(areaFlag,GetMapId()); + if(!p) + { + sLog.outError("PLAYER: Player %u discovered unknown area (x: %f y: %f map: %u", GetGUIDLow(), GetPositionX(),GetPositionY(),GetMapId()); + } + else if(p->area_level > 0) + { + uint32 area = p->ID; + if (getLevel() >= sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + { + SendExplorationExperience(area,0); + } + else + { + int32 diff = int32(getLevel()) - p->area_level; + uint32 XP = 0; + if (diff < -5) + { + XP = uint32(objmgr.GetBaseXP(getLevel()+5)*sWorld.getRate(RATE_XP_EXPLORE)); + } + else if (diff > 5) + { + int32 exploration_percent = (100-((diff-5)*5)); + if (exploration_percent > 100) + exploration_percent = 100; + else if (exploration_percent < 0) + exploration_percent = 0; + + XP = uint32(objmgr.GetBaseXP(p->area_level)*exploration_percent/100*sWorld.getRate(RATE_XP_EXPLORE)); + } + else + { + XP = uint32(objmgr.GetBaseXP(p->area_level)*sWorld.getRate(RATE_XP_EXPLORE)); + } + + GiveXP( XP, NULL ); + SendExplorationExperience(area,XP); + } + sLog.outDetail("PLAYER: Player %u discovered a new area: %u", GetGUIDLow(), area); + } + } +} + +uint32 Player::TeamForRace(uint8 race) +{ + ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(race); + if(!rEntry) + { + sLog.outError("Race %u not found in DBC: wrong DBC files?",uint32(race)); + return ALLIANCE; + } + + switch(rEntry->TeamID) + { + case 7: return ALLIANCE; + case 1: return HORDE; + } + + sLog.outError("Race %u have wrong team id in DBC: wrong DBC files?",uint32(race),rEntry->TeamID); + return ALLIANCE; +} + +uint32 Player::getFactionForRace(uint8 race) +{ + ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(race); + if(!rEntry) + { + sLog.outError("Race %u not found in DBC: wrong DBC files?",uint32(race)); + return 0; + } + + return rEntry->FactionID; +} + +void Player::setFactionForRace(uint8 race) +{ + m_team = TeamForRace(race); + setFaction( getFactionForRace(race) ); +} + +void Player::UpdateReputation() const +{ + sLog.outDetail( "WORLD: Player::UpdateReputation" ); + + for(FactionStateList::const_iterator itr = m_factions.begin(); itr != m_factions.end(); ++itr) + { + SendFactionState(&(itr->second)); + } +} + +void Player::SendFactionState(FactionState const* faction) const +{ + if(faction->Flags & FACTION_FLAG_VISIBLE) //If faction is visible then update it + { + WorldPacket data(SMSG_SET_FACTION_STANDING, (16)); // last check 2.4.0 + data << (float) 0; // unk 2.4.0 + data << (uint32) 1; // count + // for + data << (uint32) faction->ReputationListID; + data << (uint32) faction->Standing; + // end for + GetSession()->SendPacket(&data); + } +} + +void Player::SendInitialReputations() +{ + WorldPacket data(SMSG_INITIALIZE_FACTIONS, (4+128*5)); + data << uint32 (0x00000080); + + RepListID a = 0; + + for (FactionStateList::const_iterator itr = m_factions.begin(); itr != m_factions.end(); itr++) + { + // fill in absent fields + for (; a != itr->first; a++) + { + data << uint8 (0x00); + data << uint32 (0x00000000); + } + + // fill in encountered data + data << uint8 (itr->second.Flags); + data << uint32 (itr->second.Standing); + + ++a; + } + + // fill in absent fields + for (; a != 128; a++) + { + data << uint8 (0x00); + data << uint32 (0x00000000); + } + + GetSession()->SendPacket(&data); +} + +FactionState const* Player::GetFactionState( FactionEntry const* factionEntry) const +{ + FactionStateList::const_iterator itr = m_factions.find(factionEntry->reputationListID); + if (itr != m_factions.end()) + return &itr->second; + + return NULL; +} + +void Player::SetFactionAtWar(FactionState* faction, bool atWar) +{ + // not allow declare war to own faction + if(atWar && (faction->Flags & FACTION_FLAG_PEACE_FORCED) ) + return; + + // already set + if(((faction->Flags & FACTION_FLAG_AT_WAR) != 0) == atWar) + return; + + if( atWar ) + faction->Flags |= FACTION_FLAG_AT_WAR; + else + faction->Flags &= ~FACTION_FLAG_AT_WAR; + + faction->Changed = true; +} + +void Player::SetFactionInactive(FactionState* faction, bool inactive) +{ + // always invisible or hidden faction can't be inactive + if(inactive && ((faction->Flags & (FACTION_FLAG_INVISIBLE_FORCED|FACTION_FLAG_HIDDEN)) || !(faction->Flags & FACTION_FLAG_VISIBLE) ) ) + return; + + // already set + if(((faction->Flags & FACTION_FLAG_INACTIVE) != 0) == inactive) + return; + + if(inactive) + faction->Flags |= FACTION_FLAG_INACTIVE; + else + faction->Flags &= ~FACTION_FLAG_INACTIVE; + + faction->Changed = true; +} + +void Player::SetFactionVisibleForFactionTemplateId(uint32 FactionTemplateId) +{ + FactionTemplateEntry const*factionTemplateEntry = sFactionTemplateStore.LookupEntry(FactionTemplateId); + + if(!factionTemplateEntry) + return; + + SetFactionVisibleForFactionId(factionTemplateEntry->faction); +} + +void Player::SetFactionVisibleForFactionId(uint32 FactionId) +{ + FactionEntry const *factionEntry = sFactionStore.LookupEntry(FactionId); + if(!factionEntry) + return; + + if(factionEntry->reputationListID < 0) + return; + + FactionStateList::iterator itr = m_factions.find(factionEntry->reputationListID); + if (itr == m_factions.end()) + return; + + SetFactionVisible(&itr->second); +} + +void Player::SetFactionVisible(FactionState* faction) +{ + // always invisible or hidden faction can't be make visible + if(faction->Flags & (FACTION_FLAG_INVISIBLE_FORCED|FACTION_FLAG_HIDDEN)) + return; + + // already set + if(faction->Flags & FACTION_FLAG_VISIBLE) + return; + + faction->Flags |= FACTION_FLAG_VISIBLE; + faction->Changed = true; + + if(!m_session->PlayerLoading()) + { + // make faction visible in reputation list at client + WorldPacket data(SMSG_SET_FACTION_VISIBLE, 4); + data << faction->ReputationListID; + GetSession()->SendPacket(&data); + } +} + +void Player::SetInitialFactions() +{ + for(unsigned int i = 1; i < sFactionStore.GetNumRows(); i++) + { + FactionEntry const *factionEntry = sFactionStore.LookupEntry(i); + + if( factionEntry && (factionEntry->reputationListID >= 0)) + { + FactionState newFaction; + newFaction.ID = factionEntry->ID; + newFaction.ReputationListID = factionEntry->reputationListID; + newFaction.Standing = 0; + newFaction.Flags = GetDefaultReputationFlags(factionEntry); + newFaction.Changed = true; + + m_factions[newFaction.ReputationListID] = newFaction; + } + } +} + +uint32 Player::GetDefaultReputationFlags(const FactionEntry *factionEntry) const +{ + if (!factionEntry) + return 0; + + uint32 raceMask = getRaceMask(); + uint32 classMask = getClassMask(); + for (int i=0; i < 4; i++) + { + if( (factionEntry->BaseRepRaceMask[i] & raceMask) && + (factionEntry->BaseRepClassMask[i]==0 || + (factionEntry->BaseRepClassMask[i] & classMask) ) ) + return factionEntry->ReputationFlags[i]; + } + return 0; +} + +int32 Player::GetBaseReputation(const FactionEntry *factionEntry) const +{ + if (!factionEntry) + return 0; + + uint32 raceMask = getRaceMask(); + uint32 classMask = getClassMask(); + for (int i=0; i < 4; i++) + { + if( (factionEntry->BaseRepRaceMask[i] & raceMask) && + (factionEntry->BaseRepClassMask[i]==0 || + (factionEntry->BaseRepClassMask[i] & classMask) ) ) + return factionEntry->BaseRepValue[i]; + } + + // in faction.dbc exist factions with (RepListId >=0, listed in character reputation list) with all BaseRepRaceMask[i]==0 + return 0; +} + +int32 Player::GetReputation(uint32 faction_id) const +{ + FactionEntry const *factionEntry = sFactionStore.LookupEntry(faction_id); + + if (!factionEntry) + { + sLog.outError("Player::GetReputation: Can't get reputation of %s for unknown faction (faction template id) #%u.",GetName(), faction_id); + return 0; + } + + return GetReputation(factionEntry); +} + +int32 Player::GetReputation(const FactionEntry *factionEntry) const +{ + // Faction without recorded reputation. Just ignore. + if(!factionEntry) + return 0; + + FactionStateList::const_iterator itr = m_factions.find(factionEntry->reputationListID); + if (itr != m_factions.end()) + return GetBaseReputation(factionEntry) + itr->second.Standing; + + return 0; +} + +ReputationRank Player::GetReputationRank(uint32 faction) const +{ + FactionEntry const*factionEntry = sFactionStore.LookupEntry(faction); + if(!factionEntry) + return MIN_REPUTATION_RANK; + + return GetReputationRank(factionEntry); +} + +ReputationRank Player::ReputationToRank(int32 standing) const +{ + int32 Limit = Reputation_Cap + 1; + for (int i = MAX_REPUTATION_RANK-1; i >= MIN_REPUTATION_RANK; --i) + { + Limit -= ReputationRank_Length[i]; + if (standing >= Limit ) + return ReputationRank(i); + } + return MIN_REPUTATION_RANK; +} + +ReputationRank Player::GetReputationRank(const FactionEntry *factionEntry) const +{ + int32 Reputation = GetReputation(factionEntry); + return ReputationToRank(Reputation); +} + +ReputationRank Player::GetBaseReputationRank(const FactionEntry *factionEntry) const +{ + int32 Reputation = GetBaseReputation(factionEntry); + return ReputationToRank(Reputation); +} + +bool Player::ModifyFactionReputation(uint32 FactionTemplateId, int32 DeltaReputation) +{ + FactionTemplateEntry const* factionTemplateEntry = sFactionTemplateStore.LookupEntry(FactionTemplateId); + + if(!factionTemplateEntry) + { + sLog.outError("Player::ModifyFactionReputation: Can't update reputation of %s for unknown faction (faction template id) #%u.", GetName(), FactionTemplateId); + return false; + } + + FactionEntry const *factionEntry = sFactionStore.LookupEntry(factionTemplateEntry->faction); + + // Faction without recorded reputation. Just ignore. + if(!factionEntry) + return false; + + return ModifyFactionReputation(factionEntry, DeltaReputation); +} + +bool Player::ModifyFactionReputation(FactionEntry const* factionEntry, int32 standing) +{ + SimpleFactionsList const* flist = GetFactionTeamList(factionEntry->ID); + if (flist) + { + bool res = false; + for (SimpleFactionsList::const_iterator itr = flist->begin();itr != flist->end();++itr) + { + FactionEntry const *factionEntryCalc = sFactionStore.LookupEntry(*itr); + if(factionEntryCalc) + res = ModifyOneFactionReputation(factionEntryCalc, standing); + } + return res; + } + else + return ModifyOneFactionReputation(factionEntry, standing); +} + +bool Player::ModifyOneFactionReputation(FactionEntry const* factionEntry, int32 standing) +{ + FactionStateList::iterator itr = m_factions.find(factionEntry->reputationListID); + if (itr != m_factions.end()) + { + int32 BaseRep = GetBaseReputation(factionEntry); + int32 new_rep = BaseRep + itr->second.Standing + standing; + + if (new_rep > Reputation_Cap) + new_rep = Reputation_Cap; + else + if (new_rep < Reputation_Bottom) + new_rep = Reputation_Bottom; + + if(ReputationToRank(new_rep) <= REP_HOSTILE) + SetFactionAtWar(&itr->second,true); + + itr->second.Standing = new_rep - BaseRep; + itr->second.Changed = true; + + SetFactionVisible(&itr->second); + + for( int i = 0; i < MAX_QUEST_LOG_SIZE; i++ ) + { + if(uint32 questid = GetQuestSlotQuestId(i)) + { + Quest const* qInfo = objmgr.GetQuestTemplate(questid); + if( qInfo && qInfo->GetRepObjectiveFaction() == factionEntry->ID ) + { + QuestStatusData& q_status = mQuestStatus[questid]; + if( q_status.m_status == QUEST_STATUS_INCOMPLETE ) + { + if(GetReputation(factionEntry) >= qInfo->GetRepObjectiveValue()) + if ( CanCompleteQuest( questid ) ) + CompleteQuest( questid ); + } + else if( q_status.m_status == QUEST_STATUS_COMPLETE ) + { + if(GetReputation(factionEntry) < qInfo->GetRepObjectiveValue()) + IncompleteQuest( questid ); + } + } + } + } + + SendFactionState(&(itr->second)); + + return true; + } + return false; +} + +bool Player::SetFactionReputation(uint32 FactionTemplateId, int32 standing) +{ + FactionTemplateEntry const* factionTemplateEntry = sFactionTemplateStore.LookupEntry(FactionTemplateId); + + if(!factionTemplateEntry) + { + sLog.outError("Player::SetFactionReputation: Can't set reputation of %s for unknown faction (faction template id) #%u.", GetName(), FactionTemplateId); + return false; + } + + FactionEntry const *factionEntry = sFactionStore.LookupEntry(factionTemplateEntry->faction); + + // Faction without recorded reputation. Just ignore. + if(!factionEntry) + return false; + + return SetFactionReputation(factionEntry, standing); +} + +bool Player::SetFactionReputation(FactionEntry const* factionEntry, int32 standing) +{ + SimpleFactionsList const* flist = GetFactionTeamList(factionEntry->ID); + if (flist) + { + bool res = false; + for (SimpleFactionsList::const_iterator itr = flist->begin();itr != flist->end();++itr) + { + FactionEntry const *factionEntryCalc = sFactionStore.LookupEntry(*itr); + if(factionEntryCalc) + res = SetOneFactionReputation(factionEntryCalc, standing); + } + return res; + } + else + return SetOneFactionReputation(factionEntry, standing); +} + +bool Player::SetOneFactionReputation(FactionEntry const* factionEntry, int32 standing) +{ + FactionStateList::iterator itr = m_factions.find(factionEntry->reputationListID); + if (itr != m_factions.end()) + { + if (standing > Reputation_Cap) + standing = Reputation_Cap; + else + if (standing < Reputation_Bottom) + standing = Reputation_Bottom; + + int32 BaseRep = GetBaseReputation(factionEntry); + itr->second.Standing = standing - BaseRep; + itr->second.Changed = true; + + SetFactionVisible(&itr->second); + + if(ReputationToRank(standing) <= REP_HOSTILE) + SetFactionAtWar(&itr->second,true); + + SendFactionState(&(itr->second)); + return true; + } + return false; +} + +//Calculate total reputation percent player gain with quest/creature level +int32 Player::CalculateReputationGain(uint32 creatureOrQuestLevel, int32 rep, bool for_quest) +{ + // for grey creature kill received 20%, in other case 100. + int32 percent = (!for_quest && (creatureOrQuestLevel <= MaNGOS::XP::GetGrayLevel(getLevel()))) ? 20 : 100; + + int32 repMod = GetTotalAuraModifier(SPELL_AURA_MOD_REPUTATION_GAIN); + + percent += rep > 0 ? repMod : -repMod; + + if(percent <=0) + return 0; + + return int32(sWorld.getRate(RATE_REPUTATION_GAIN)*rep*percent/100); +} + +//Calculates how many reputation points player gains in victim's enemy factions +void Player::RewardReputation(Unit *pVictim, float rate) +{ + if(!pVictim || pVictim->GetTypeId() == TYPEID_PLAYER) + return; + + ReputationOnKillEntry const* Rep = objmgr.GetReputationOnKilEntry(pVictim->GetEntry()); + + if(!Rep) + return; + + if(Rep->repfaction1 && (!Rep->team_dependent || GetTeam()==ALLIANCE)) + { + int32 donerep1 = CalculateReputationGain(pVictim->getLevel(),Rep->repvalue1,false); + donerep1 = int32(donerep1*rate); + FactionEntry const *factionEntry1 = sFactionStore.LookupEntry(Rep->repfaction1); + uint32 current_reputation_rank1 = GetReputationRank(factionEntry1); + if(factionEntry1 && current_reputation_rank1 <= Rep->reputration_max_cap1) + ModifyFactionReputation(factionEntry1, donerep1); + + // Wiki: Team factions value divided by 2 + if(Rep->is_teamaward1) + { + FactionEntry const *team1_factionEntry = sFactionStore.LookupEntry(factionEntry1->team); + if(team1_factionEntry) + ModifyFactionReputation(team1_factionEntry, donerep1 / 2); + } + } + + if(Rep->repfaction2 && (!Rep->team_dependent || GetTeam()==HORDE)) + { + int32 donerep2 = CalculateReputationGain(pVictim->getLevel(),Rep->repvalue2,false); + donerep2 = int32(donerep2*rate); + FactionEntry const *factionEntry2 = sFactionStore.LookupEntry(Rep->repfaction2); + uint32 current_reputation_rank2 = GetReputationRank(factionEntry2); + if(factionEntry2 && current_reputation_rank2 <= Rep->reputration_max_cap2) + ModifyFactionReputation(factionEntry2, donerep2); + + // Wiki: Team factions value divided by 2 + if(Rep->is_teamaward2) + { + FactionEntry const *team2_factionEntry = sFactionStore.LookupEntry(factionEntry2->team); + if(team2_factionEntry) + ModifyFactionReputation(team2_factionEntry, donerep2 / 2); + } + } +} + +//Calculate how many reputation points player gain with the quest +void Player::RewardReputation(Quest const *pQuest) +{ + // quest reputation reward/loss + for(int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) + { + if(pQuest->RewRepFaction[i] && pQuest->RewRepValue[i] ) + { + int32 rep = CalculateReputationGain(pQuest->GetQuestLevel(),pQuest->RewRepValue[i],true); + FactionEntry const* factionEntry = sFactionStore.LookupEntry(pQuest->RewRepFaction[i]); + if(factionEntry) + ModifyFactionReputation(factionEntry, rep); + } + } + + // TODO: implement reputation spillover +} + +void Player::UpdateArenaFields(void) +{ + /* arena calcs go here */ +} + +void Player::UpdateHonorFields() +{ + /// called when rewarding honor and at each save + uint64 now = time(NULL); + uint64 today = uint64(time(NULL) / DAY) * DAY; + + if(m_lastHonorUpdateTime < today) + { + uint64 yesterday = today - DAY; + + uint16 kills_today = PAIR32_LOPART(GetUInt32Value(PLAYER_FIELD_KILLS)); + + // update yesterday's contribution + if(m_lastHonorUpdateTime >= yesterday ) + { + SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, GetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION)); + + // this is the first update today, reset today's contribution + SetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, 0); + SetUInt32Value(PLAYER_FIELD_KILLS, MAKE_PAIR32(0,kills_today)); + } + else + { + // no honor/kills yesterday or today, reset + SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, 0); + SetUInt32Value(PLAYER_FIELD_KILLS, 0); + } + } + + m_lastHonorUpdateTime = now; +} + +///Calculate the amount of honor gained based on the victim +///and the size of the group for which the honor is divided +///An exact honor value can also be given (overriding the calcs) +bool Player::RewardHonor(Unit *uVictim, uint32 groupsize, float honor) +{ + // 'Inactive' this aura prevents the player from gaining honor points and battleground tokens + if(GetDummyAura(SPELL_AURA_PLAYER_INACTIVE)) + return false; + + uint64 victim_guid = 0; + uint32 victim_rank = 0; + time_t now = time(NULL); + + // need call before fields update to have chance move yesterday data to appropriate fields before today data change. + UpdateHonorFields(); + + if(honor <= 0) + { + if(!uVictim || uVictim == this || uVictim->HasAuraType(SPELL_AURA_NO_PVP_CREDIT)) + return false; + + victim_guid = uVictim->GetGUID(); + + if( uVictim->GetTypeId() == TYPEID_PLAYER ) + { + Player *pVictim = (Player *)uVictim; + + if( GetTeam() == pVictim->GetTeam() && !sWorld.IsFFAPvPRealm() ) + return false; + + float f = 1; //need for total kills (?? need more info) + uint32 k_grey = 0; + uint32 k_level = getLevel(); + uint32 v_level = pVictim->getLevel(); + + { + // PLAYER_CHOSEN_TITLE VALUES DESCRIPTION + // [0] Just name + // [1..14] Alliance honor titles and player name + // [15..28] Horde honor titles and player name + // [29..38] Other title and player name + // [39+] Nothing + uint32 victim_title = pVictim->GetUInt32Value(PLAYER_CHOSEN_TITLE); + // Get Killer titles, CharTitlesEntry::bit_index + // Ranks: + // title[1..14] -> rank[5..18] + // title[15..28] -> rank[5..18] + // title[other] -> 0 + if (victim_title == 0) + victim_guid = 0; // Don't show HK: message, only log. + else if (victim_title < 15) + victim_rank = victim_title + 4; + else if (victim_title < 29) + victim_rank = victim_title - 14 + 4; + else + victim_guid = 0; // Don't show HK: message, only log. + } + + if(k_level <= 5) + k_grey = 0; + else if( k_level <= 39 ) + k_grey = k_level - 5 - k_level/10; + else + k_grey = k_level - 1 - k_level/5; + + if(v_level<=k_grey) + return false; + + float diff_level = (k_level == k_grey) ? 1 : ((float(v_level) - float(k_grey)) / (float(k_level) - float(k_grey))); + + int32 v_rank =1; //need more info + + honor = ((f * diff_level * (190 + v_rank*10))/6); + honor *= ((float)k_level) / 70.0f; //factor of dependence on levels of the killer + + // count the number of playerkills in one day + ApplyModUInt32Value(PLAYER_FIELD_KILLS, 1, true); + // and those in a lifetime + ApplyModUInt32Value(PLAYER_FIELD_LIFETIME_HONORBALE_KILLS, 1, true); + } + else + { + Creature *cVictim = (Creature *)uVictim; + + if (!cVictim->isRacialLeader()) + return false; + + honor = 100; // ??? need more info + victim_rank = 19; // HK: Leader + } + } + + if (uVictim != NULL) + { + honor *= sWorld.getRate(RATE_HONOR); + + if(groupsize > 1) + honor /= groupsize; + + honor *= (((float)urand(8,12))/10); // approx honor: 80% - 120% of real honor + } + + // honor - for show honor points in log + // victim_guid - for show victim name in log + // victim_rank [1..4] HK: + // victim_rank [5..19] HK: + // victim_rank [0,20+] HK: <> + WorldPacket data(SMSG_PVP_CREDIT,4+8+4); + data << (uint32) honor; + data << (uint64) victim_guid; + data << (uint32) victim_rank; + + GetSession()->SendPacket(&data); + + // add honor points + ModifyHonorPoints(int32(honor)); + + ApplyModUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, uint32(honor), true); + return true; +} + +void Player::ModifyHonorPoints( int32 value ) +{ + if(value < 0) + { + if (GetHonorPoints() > sWorld.getConfig(CONFIG_MAX_HONOR_POINTS)) + SetUInt32Value(PLAYER_FIELD_HONOR_CURRENCY, sWorld.getConfig(CONFIG_MAX_HONOR_POINTS) + value); + else + SetUInt32Value(PLAYER_FIELD_HONOR_CURRENCY, GetHonorPoints() > uint32(-value) ? GetHonorPoints() + value : 0); + } + else + SetUInt32Value(PLAYER_FIELD_HONOR_CURRENCY, GetHonorPoints() < sWorld.getConfig(CONFIG_MAX_HONOR_POINTS) - value ? GetHonorPoints() + value : sWorld.getConfig(CONFIG_MAX_HONOR_POINTS)); +} + +void Player::ModifyArenaPoints( int32 value ) +{ + if(value < 0) + { + if (GetArenaPoints() > sWorld.getConfig(CONFIG_MAX_ARENA_POINTS)) + SetUInt32Value(PLAYER_FIELD_ARENA_CURRENCY, sWorld.getConfig(CONFIG_MAX_ARENA_POINTS) + value); + else + SetUInt32Value(PLAYER_FIELD_ARENA_CURRENCY, GetArenaPoints() > uint32(-value) ? GetArenaPoints() + value : 0); + } + else + SetUInt32Value(PLAYER_FIELD_ARENA_CURRENCY, GetArenaPoints() < sWorld.getConfig(CONFIG_MAX_ARENA_POINTS) - value ? GetArenaPoints() + value : sWorld.getConfig(CONFIG_MAX_ARENA_POINTS)); +} + +uint32 Player::GetGuildIdFromDB(uint64 guid) +{ + std::ostringstream ss; + ss<<"SELECT guildid FROM guild_member WHERE guid='"<Fetch()[0].GetUInt32(); + delete result; + return v; + } + else + return 0; +} + +uint32 Player::GetRankFromDB(uint64 guid) +{ + std::ostringstream ss; + ss<<"SELECT rank FROM guild_member WHERE guid='"<Fetch()[0].GetUInt32(); + delete result; + return v; + } + else + return 0; +} + +uint32 Player::GetArenaTeamIdFromDB(uint64 guid, uint8 type) +{ + // need fix it! + QueryResult *result = CharacterDatabase.PQuery("SELECT arenateamid FROM arena_team_member WHERE guid='%u'", GUID_LOPART(guid)); + if(result) + { + // init id to 0, check the arena type before assigning a value to id + uint32 id = 0; + do + { + QueryResult *result2 = CharacterDatabase.PQuery("SELECT type FROM arena_team WHERE arenateamid='%u'", id); + if(result2) + { + uint8 dbtype = (*result2)[0].GetUInt32(); + delete result2; + if(dbtype == type) + { + // if the type matches, we've found the id + id = (*result)[0].GetUInt32(); + break; + } + } + } while(result->NextRow()); + delete result; + return id; + } + // no arenateam for the specified guid, return 0 + return 0; +} + +uint32 Player::GetZoneIdFromDB(uint64 guid) +{ + std::ostringstream ss; + + ss<<"SELECT zone FROM characters WHERE guid='"<Fetch(); + uint32 zone = fields[0].GetUInt32(); + delete result; + + if (!zone) + { + // stored zone is zero, use generic and slow zone detection + ss.str(""); + ss<<"SELECT map,position_x,position_y FROM characters WHERE guid='"<Fetch(); + uint32 map = fields[0].GetUInt32(); + float posx = fields[1].GetFloat(); + float posy = fields[2].GetFloat(); + delete result; + + zone = MapManager::Instance().GetZoneId(map,posx,posy); + + ss.str(""); + ss << "UPDATE characters SET zone='"<flags & AREA_FLAG_ARENA)) + { + if(!isGameMaster()) + SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP); + } + else + { + // remove ffa flag only if not ffapvp realm + // removal in sanctuaries and capitals is handled in zone update + if(HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP) && !sWorld.IsFFAPvPRealm()) + RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP); + } + + UpdateAreaDependentAuras(newArea); +} + +void Player::UpdateZone(uint32 newZone) +{ + m_zoneUpdateId = newZone; + m_zoneUpdateTimer = ZONE_UPDATE_INTERVAL; + + // zone changed, so area changed as well, update it + UpdateArea(GetAreaId()); + + AreaTableEntry const* zone = GetAreaEntryByAreaID(newZone); + if(!zone) + return; + + if (sWorld.getConfig(CONFIG_WEATHER)) + { + Weather *wth = sWorld.FindWeather(zone->ID); + if(wth) + { + wth->SendWeatherUpdateToPlayer(this); + } + else + { + if(!sWorld.AddWeather(zone->ID)) + { + // send fine weather packet to remove old zone's weather + Weather::SendFineWeatherUpdateToPlayer(this); + } + } + } + + pvpInfo.inHostileArea = + GetTeam() == ALLIANCE && zone->team == AREATEAM_HORDE || + GetTeam() == HORDE && zone->team == AREATEAM_ALLY || + sWorld.IsPvPRealm() && zone->team == AREATEAM_NONE || + InBattleGround(); // overwrite for battlegrounds, maybe batter some zone flags but current known not 100% fit to this + + if(pvpInfo.inHostileArea) // in hostile area + { + if(!IsPvP() || pvpInfo.endTimer != 0) + UpdatePvP(true, true); + } + else // in friendly area + { + if(IsPvP() && !HasFlag(PLAYER_FLAGS,PLAYER_FLAGS_IN_PVP) && pvpInfo.endTimer == 0) + pvpInfo.endTimer = time(0); // start toggle-off + } + + if(zone->flags & AREA_FLAG_SANCTUARY) // in sanctuary + { + SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_SANCTUARY); + if(sWorld.IsFFAPvPRealm()) + RemoveFlag(PLAYER_FLAGS,PLAYER_FLAGS_FFA_PVP); + } + else + { + RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_SANCTUARY); + } + + if(zone->flags & AREA_FLAG_CAPITAL) // in capital city + { + SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING); + SetRestType(REST_TYPE_IN_CITY); + InnEnter(time(0),GetMapId(),0,0,0); + + if(sWorld.IsFFAPvPRealm()) + RemoveFlag(PLAYER_FLAGS,PLAYER_FLAGS_FFA_PVP); + } + else // anywhere else + { + if(HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING)) // but resting (walk from city or maybe in tavern or leave tavern recently) + { + if(GetRestType()==REST_TYPE_IN_TAVERN) // has been in tavern. Is still in? + { + if(GetMapId()!=GetInnPosMapId() || sqrt((GetPositionX()-GetInnPosX())*(GetPositionX()-GetInnPosX())+(GetPositionY()-GetInnPosY())*(GetPositionY()-GetInnPosY())+(GetPositionZ()-GetInnPosZ())*(GetPositionZ()-GetInnPosZ()))>40) + { + RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING); + SetRestType(REST_TYPE_NO); + + if(sWorld.IsFFAPvPRealm()) + SetFlag(PLAYER_FLAGS,PLAYER_FLAGS_FFA_PVP); + } + } + else // not in tavern (leave city then) + { + RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING); + SetRestType(REST_TYPE_NO); + + // Set player to FFA PVP when not in rested enviroment. + if(sWorld.IsFFAPvPRealm()) + SetFlag(PLAYER_FLAGS,PLAYER_FLAGS_FFA_PVP); + } + } + } + + // remove items with area/map limitations (delete only for alive player to allow back in ghost mode) + // if player resurrected at teleport this will be applied in resurrect code + if(isAlive()) + DestroyZoneLimitedItem( true, newZone ); + + // recent client version not send leave/join channel packets for built-in local channels + UpdateLocalChannels( newZone ); + + // group update + if(GetGroup()) + SetGroupUpdateFlag(GROUP_UPDATE_FLAG_ZONE); + + UpdateZoneDependentAuras(newZone); +} + +//If players are too far way of duel flag... then player loose the duel +void Player::CheckDuelDistance(time_t currTime) +{ + if(!duel) + return; + + uint64 duelFlagGUID = GetUInt64Value(PLAYER_DUEL_ARBITER); + GameObject* obj = ObjectAccessor::GetGameObject(*this, duelFlagGUID); + if(!obj) + return; + + if(duel->outOfBound == 0) + { + if(!IsWithinDistInMap(obj, 50)) + { + duel->outOfBound = currTime; + + WorldPacket data(SMSG_DUEL_OUTOFBOUNDS, 0); + GetSession()->SendPacket(&data); + } + } + else + { + if(IsWithinDistInMap(obj, 40)) + { + duel->outOfBound = 0; + + WorldPacket data(SMSG_DUEL_INBOUNDS, 0); + GetSession()->SendPacket(&data); + } + else if(currTime >= (duel->outOfBound+10)) + { + DuelComplete(DUEL_FLED); + } + } +} + +void Player::DuelComplete(DuelCompleteType type) +{ + // duel not requested + if(!duel) + return; + + WorldPacket data(SMSG_DUEL_COMPLETE, (1)); + data << (uint8)((type != DUEL_INTERUPTED) ? 1 : 0); + GetSession()->SendPacket(&data); + duel->opponent->GetSession()->SendPacket(&data); + + if(type != DUEL_INTERUPTED) + { + data.Initialize(SMSG_DUEL_WINNER, (1+20)); // we guess size + data << (uint8)((type==DUEL_WON) ? 0 : 1); // 0 = just won; 1 = fled + data << duel->opponent->GetName(); + data << GetName(); + SendMessageToSet(&data,true); + } + + // cool-down duel spell + /*data.Initialize(SMSG_SPELL_COOLDOWN, 17); + + data<SendPacket(&data); + data.Initialize(SMSG_SPELL_COOLDOWN, 17); + data<opponent->GetGUID(); + data<opponent->GetSession()->SendPacket(&data);*/ + + //Remove Duel Flag object + GameObject* obj = ObjectAccessor::GetGameObject(*this, GetUInt64Value(PLAYER_DUEL_ARBITER)); + if(obj) + duel->initiator->RemoveGameObject(obj,true); + + /* remove auras */ + std::vector auras2remove; + AuraMap const& vAuras = duel->opponent->GetAuras(); + for (AuraMap::const_iterator i = vAuras.begin(); i != vAuras.end(); i++) + { + if (!i->second->IsPositive() && i->second->GetCasterGUID() == GetGUID() && i->second->GetAuraApplyTime() >= duel->startTime) + auras2remove.push_back(i->second->GetId()); + } + + for(size_t i=0; iopponent->RemoveAurasDueToSpell(auras2remove[i]); + + auras2remove.clear(); + AuraMap const& auras = GetAuras(); + for (AuraMap::const_iterator i = auras.begin(); i != auras.end(); i++) + { + if (!i->second->IsPositive() && i->second->GetCasterGUID() == duel->opponent->GetGUID() && i->second->GetAuraApplyTime() >= duel->startTime) + auras2remove.push_back(i->second->GetId()); + } + for(size_t i=0; iopponent->GetGUID()) + ClearComboPoints(); + else if(GetComboTarget()==duel->opponent->GetPetGUID()) + ClearComboPoints(); + + if(duel->opponent->GetComboTarget()==GetGUID()) + duel->opponent->ClearComboPoints(); + else if(duel->opponent->GetComboTarget()==GetPetGUID()) + duel->opponent->ClearComboPoints(); + + //cleanups + SetUInt64Value(PLAYER_DUEL_ARBITER, 0); + SetUInt32Value(PLAYER_DUEL_TEAM, 0); + duel->opponent->SetUInt64Value(PLAYER_DUEL_ARBITER, 0); + duel->opponent->SetUInt32Value(PLAYER_DUEL_TEAM, 0); + + delete duel->opponent->duel; + duel->opponent->duel = NULL; + delete duel; + duel = NULL; +} + +//---------------------------------------------------------// + +void Player::_ApplyItemMods(Item *item, uint8 slot,bool apply) +{ + if(slot >= INVENTORY_SLOT_BAG_END || !item) + return; + + // not apply/remove mods for broken item + if(item->IsBroken()) + return; + + ItemPrototype const *proto = item->GetProto(); + + if(!proto) + return; + + sLog.outDetail("applying mods for item %u ",item->GetGUIDLow()); + + uint32 attacktype = Player::GetAttackBySlot(slot); + if(attacktype < MAX_ATTACK) + _ApplyWeaponDependentAuraMods(item,WeaponAttackType(attacktype),apply); + + _ApplyItemBonuses(proto,slot,apply); + + if( slot==EQUIPMENT_SLOT_RANGED ) + _ApplyAmmoBonuses(); + + ApplyItemEquipSpell(item,apply); + ApplyEnchantment(item, apply); + + if(proto->Socket[0].Color) //only (un)equipping of items with sockets can influence metagems, so no need to waste time with normal items + CorrectMetaGemEnchants(slot, apply); + + sLog.outDebug("_ApplyItemMods complete."); +} + +void Player::_ApplyItemBonuses(ItemPrototype const *proto,uint8 slot,bool apply) +{ + if(slot >= INVENTORY_SLOT_BAG_END || !proto) + return; + + for (int i = 0; i < 10; i++) + { + float val = float (proto->ItemStat[i].ItemStatValue); + + if(val==0) + continue; + + switch (proto->ItemStat[i].ItemStatType) + { + case ITEM_MOD_MANA: + HandleStatModifier(UNIT_MOD_MANA, BASE_VALUE, float(val), apply); + break; + case ITEM_MOD_HEALTH: // modify HP + HandleStatModifier(UNIT_MOD_HEALTH, BASE_VALUE, float(val), apply); + break; + case ITEM_MOD_AGILITY: // modify agility + HandleStatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply); + ApplyStatBuffMod(STAT_AGILITY, val, apply); + break; + case ITEM_MOD_STRENGTH: //modify strength + HandleStatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply); + ApplyStatBuffMod(STAT_STRENGTH, val, apply); + break; + case ITEM_MOD_INTELLECT: //modify intellect + HandleStatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply); + ApplyStatBuffMod(STAT_INTELLECT, val, apply); + break; + case ITEM_MOD_SPIRIT: //modify spirit + HandleStatModifier(UNIT_MOD_STAT_SPIRIT, BASE_VALUE, float(val), apply); + ApplyStatBuffMod(STAT_SPIRIT, val, apply); + break; + case ITEM_MOD_STAMINA: //modify stamina + HandleStatModifier(UNIT_MOD_STAT_STAMINA, BASE_VALUE, float(val), apply); + ApplyStatBuffMod(STAT_STAMINA, val, apply); + break; + case ITEM_MOD_DEFENSE_SKILL_RATING: + ApplyRatingMod(CR_DEFENSE_SKILL, int32(val), apply); + break; + case ITEM_MOD_DODGE_RATING: + ApplyRatingMod(CR_DODGE, int32(val), apply); + break; + case ITEM_MOD_PARRY_RATING: + ApplyRatingMod(CR_PARRY, int32(val), apply); + break; + case ITEM_MOD_BLOCK_RATING: + ApplyRatingMod(CR_BLOCK, int32(val), apply); + break; + case ITEM_MOD_HIT_MELEE_RATING: + ApplyRatingMod(CR_HIT_MELEE, int32(val), apply); + break; + case ITEM_MOD_HIT_RANGED_RATING: + ApplyRatingMod(CR_HIT_RANGED, int32(val), apply); + break; + case ITEM_MOD_HIT_SPELL_RATING: + ApplyRatingMod(CR_HIT_SPELL, int32(val), apply); + break; + case ITEM_MOD_CRIT_MELEE_RATING: + ApplyRatingMod(CR_CRIT_MELEE, int32(val), apply); + break; + case ITEM_MOD_CRIT_RANGED_RATING: + ApplyRatingMod(CR_CRIT_RANGED, int32(val), apply); + break; + case ITEM_MOD_CRIT_SPELL_RATING: + ApplyRatingMod(CR_CRIT_SPELL, int32(val), apply); + break; + case ITEM_MOD_HIT_TAKEN_MELEE_RATING: + ApplyRatingMod(CR_HIT_TAKEN_MELEE, int32(val), apply); + break; + case ITEM_MOD_HIT_TAKEN_RANGED_RATING: + ApplyRatingMod(CR_HIT_TAKEN_RANGED, int32(val), apply); + break; + case ITEM_MOD_HIT_TAKEN_SPELL_RATING: + ApplyRatingMod(CR_HIT_TAKEN_SPELL, int32(val), apply); + break; + case ITEM_MOD_CRIT_TAKEN_MELEE_RATING: + ApplyRatingMod(CR_CRIT_TAKEN_MELEE, int32(val), apply); + break; + case ITEM_MOD_CRIT_TAKEN_RANGED_RATING: + ApplyRatingMod(CR_CRIT_TAKEN_RANGED, int32(val), apply); + break; + case ITEM_MOD_CRIT_TAKEN_SPELL_RATING: + ApplyRatingMod(CR_CRIT_TAKEN_SPELL, int32(val), apply); + break; + case ITEM_MOD_HASTE_MELEE_RATING: + ApplyRatingMod(CR_HASTE_MELEE, int32(val), apply); + break; + case ITEM_MOD_HASTE_RANGED_RATING: + ApplyRatingMod(CR_HASTE_RANGED, int32(val), apply); + break; + case ITEM_MOD_HASTE_SPELL_RATING: + ApplyRatingMod(CR_HASTE_SPELL, int32(val), apply); + break; + case ITEM_MOD_HIT_RATING: + ApplyRatingMod(CR_HIT_MELEE, int32(val), apply); + ApplyRatingMod(CR_HIT_RANGED, int32(val), apply); + ApplyRatingMod(CR_HIT_SPELL, int32(val), apply); + break; + case ITEM_MOD_CRIT_RATING: + ApplyRatingMod(CR_CRIT_MELEE, int32(val), apply); + ApplyRatingMod(CR_CRIT_RANGED, int32(val), apply); + ApplyRatingMod(CR_CRIT_SPELL, int32(val), apply); + break; + case ITEM_MOD_HIT_TAKEN_RATING: + ApplyRatingMod(CR_HIT_TAKEN_MELEE, int32(val), apply); + ApplyRatingMod(CR_HIT_TAKEN_RANGED, int32(val), apply); + ApplyRatingMod(CR_HIT_TAKEN_SPELL, int32(val), apply); + break; + case ITEM_MOD_CRIT_TAKEN_RATING: + ApplyRatingMod(CR_CRIT_TAKEN_MELEE, int32(val), apply); + ApplyRatingMod(CR_CRIT_TAKEN_RANGED, int32(val), apply); + ApplyRatingMod(CR_CRIT_TAKEN_SPELL, int32(val), apply); + break; + case ITEM_MOD_RESILIENCE_RATING: + ApplyRatingMod(CR_CRIT_TAKEN_MELEE, int32(val), apply); + ApplyRatingMod(CR_CRIT_TAKEN_RANGED, int32(val), apply); + ApplyRatingMod(CR_CRIT_TAKEN_SPELL, int32(val), apply); + break; + case ITEM_MOD_HASTE_RATING: + ApplyRatingMod(CR_HASTE_MELEE, int32(val), apply); + ApplyRatingMod(CR_HASTE_RANGED, int32(val), apply); + ApplyRatingMod(CR_HASTE_SPELL, int32(val), apply); + break; + case ITEM_MOD_EXPERTISE_RATING: + ApplyRatingMod(CR_EXPERTISE, int32(val), apply); + break; + } + } + + if (proto->Armor) + HandleStatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(proto->Armor), apply); + + if (proto->Block) + HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(proto->Block), apply); + + if (proto->HolyRes) + HandleStatModifier(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(proto->HolyRes), apply); + + if (proto->FireRes) + HandleStatModifier(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(proto->FireRes), apply); + + if (proto->NatureRes) + HandleStatModifier(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(proto->NatureRes), apply); + + if (proto->FrostRes) + HandleStatModifier(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(proto->FrostRes), apply); + + if (proto->ShadowRes) + HandleStatModifier(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(proto->ShadowRes), apply); + + if (proto->ArcaneRes) + HandleStatModifier(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(proto->ArcaneRes), apply); + + WeaponAttackType attType = BASE_ATTACK; + float damage = 0.0f; + + if( slot == EQUIPMENT_SLOT_RANGED && ( + proto->InventoryType == INVTYPE_RANGED || proto->InventoryType == INVTYPE_THROWN || + proto->InventoryType == INVTYPE_RANGEDRIGHT )) + { + attType = RANGED_ATTACK; + } + else if(slot==EQUIPMENT_SLOT_OFFHAND) + { + attType = OFF_ATTACK; + } + + if (proto->Damage[0].DamageMin > 0 ) + { + damage = apply ? proto->Damage[0].DamageMin : BASE_MINDAMAGE; + SetBaseWeaponDamage(attType, MINDAMAGE, damage); + //sLog.outError("applying mindam: assigning %f to weapon mindamage, now is: %f", damage, GetWeaponDamageRange(attType, MINDAMAGE)); + } + + if (proto->Damage[0].DamageMax > 0 ) + { + damage = apply ? proto->Damage[0].DamageMax : BASE_MAXDAMAGE; + SetBaseWeaponDamage(attType, MAXDAMAGE, damage); + } + + if(!IsUseEquipedWeapon(slot==EQUIPMENT_SLOT_MAINHAND)) + return; + + if (proto->Delay) + { + if(slot == EQUIPMENT_SLOT_RANGED) + SetAttackTime(RANGED_ATTACK, apply ? proto->Delay: BASE_ATTACK_TIME); + else if(slot==EQUIPMENT_SLOT_MAINHAND) + SetAttackTime(BASE_ATTACK, apply ? proto->Delay: BASE_ATTACK_TIME); + else if(slot==EQUIPMENT_SLOT_OFFHAND) + SetAttackTime(OFF_ATTACK, apply ? proto->Delay: BASE_ATTACK_TIME); + } + + if(CanModifyStats() && (damage || proto->Delay)) + UpdateDamagePhysical(attType); +} + +void Player::_ApplyWeaponDependentAuraMods(Item *item,WeaponAttackType attackType,bool apply) +{ + AuraList const& auraCritList = GetAurasByType(SPELL_AURA_MOD_CRIT_PERCENT); + for(AuraList::const_iterator itr = auraCritList.begin(); itr!=auraCritList.end();++itr) + _ApplyWeaponDependentAuraCritMod(item,attackType,*itr,apply); + + AuraList const& auraDamageFlatList = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE); + for(AuraList::const_iterator itr = auraDamageFlatList.begin(); itr!=auraDamageFlatList.end();++itr) + _ApplyWeaponDependentAuraDamageMod(item,attackType,*itr,apply); + + AuraList const& auraDamagePCTList = GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); + for(AuraList::const_iterator itr = auraDamagePCTList.begin(); itr!=auraDamagePCTList.end();++itr) + _ApplyWeaponDependentAuraDamageMod(item,attackType,*itr,apply); +} + +void Player::_ApplyWeaponDependentAuraCritMod(Item *item, WeaponAttackType attackType, Aura* aura, bool apply) +{ + // generic not weapon specific case processes in aura code + if(aura->GetSpellProto()->EquippedItemClass == -1) + return; + + BaseModGroup mod = BASEMOD_END; + switch(attackType) + { + case BASE_ATTACK: mod = CRIT_PERCENTAGE; break; + case OFF_ATTACK: mod = OFFHAND_CRIT_PERCENTAGE;break; + case RANGED_ATTACK: mod = RANGED_CRIT_PERCENTAGE; break; + default: return; + } + + if (item->IsFitToSpellRequirements(aura->GetSpellProto())) + { + HandleBaseModValue(mod, FLAT_MOD, float (aura->GetModifier()->m_amount), apply); + } +} + +void Player::_ApplyWeaponDependentAuraDamageMod(Item *item, WeaponAttackType attackType, Aura* aura, bool apply) +{ + // ignore spell mods for not wands + Modifier const* modifier = aura->GetModifier(); + if((modifier->m_miscvalue & SPELL_SCHOOL_MASK_NORMAL)==0 && (getClassMask() & CLASSMASK_WAND_USERS)==0) + return; + + // generic not weapon specific case processes in aura code + if(aura->GetSpellProto()->EquippedItemClass == -1) + return; + + UnitMods unitMod = UNIT_MOD_END; + switch(attackType) + { + case BASE_ATTACK: unitMod = UNIT_MOD_DAMAGE_MAINHAND; break; + case OFF_ATTACK: unitMod = UNIT_MOD_DAMAGE_OFFHAND; break; + case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED; break; + default: return; + } + + UnitModifierType unitModType = TOTAL_VALUE; + switch(modifier->m_auraname) + { + case SPELL_AURA_MOD_DAMAGE_DONE: unitModType = TOTAL_VALUE; break; + case SPELL_AURA_MOD_DAMAGE_PERCENT_DONE: unitModType = TOTAL_PCT; break; + default: return; + } + + if (item->IsFitToSpellRequirements(aura->GetSpellProto())) + { + HandleStatModifier(unitMod, unitModType, float(modifier->m_amount),apply); + } +} + +void Player::ApplyItemEquipSpell(Item *item, bool apply, bool form_change) +{ + if(!item) + return; + + ItemPrototype const *proto = item->GetProto(); + if(!proto) + return; + + for (int i = 0; i < 5; i++) + { + _Spell const& spellData = proto->Spells[i]; + + // no spell + if(!spellData.SpellId ) + continue; + + // wrong triggering type + if(apply && spellData.SpellTrigger != ITEM_SPELLTRIGGER_ON_EQUIP) + continue; + + // check if it is valid spell + SpellEntry const* spellproto = sSpellStore.LookupEntry(spellData.SpellId); + if(!spellproto) + continue; + + ApplyEquipSpell(spellproto,item,apply,form_change); + } +} + +void Player::ApplyEquipSpell(SpellEntry const* spellInfo, Item* item, bool apply, bool form_change) +{ + if(apply) + { + // Cannot be used in this stance/form + if(GetErrorAtShapeshiftedCast(spellInfo, m_form)!=0) + return; + + if(form_change) // check aura active state from other form + { + bool found = false; + for (int k=0; k < 3; ++k) + { + spellEffectPair spair = spellEffectPair(spellInfo->Id, k); + for (AuraMap::iterator iter = m_Auras.lower_bound(spair); iter != m_Auras.upper_bound(spair); ++iter) + { + if(!item || iter->second->GetCastItemGUID() == item->GetGUID()) + { + found = true; + break; + } + } + if(found) + break; + } + + if(found) // and skip re-cast already active aura at form change + return; + } + + DEBUG_LOG("WORLD: cast %s Equip spellId - %i", (item ? "item" : "itemset"), spellInfo->Id); + + CastSpell(this,spellInfo,true,item); + } + else + { + if(form_change) // check aura compatibility + { + // Cannot be used in this stance/form + if(GetErrorAtShapeshiftedCast(spellInfo, m_form)==0) + return; // and remove only not compatible at form change + } + + if(item) + RemoveAurasDueToItemSpell(item,spellInfo->Id); // un-apply all spells , not only at-equipped + else + RemoveAurasDueToSpell(spellInfo->Id); // un-apply spell (item set case) + } +} + +void Player::UpdateEquipSpellsAtFormChange() +{ + for (int i = 0; i < INVENTORY_SLOT_BAG_END; i++) + { + if(m_items[i] && !m_items[i]->IsBroken()) + { + ApplyItemEquipSpell(m_items[i],false,true); // remove spells that not fit to form + ApplyItemEquipSpell(m_items[i],true,true); // add spells that fit form but not active + } + } + + // item set bonuses not dependent from item broken state + for(size_t setindex = 0; setindex < ItemSetEff.size(); ++setindex) + { + ItemSetEffect* eff = ItemSetEff[setindex]; + if(!eff) + continue; + + for(uint32 y=0;y<8; ++y) + { + SpellEntry const* spellInfo = eff->spells[y]; + if(!spellInfo) + continue; + + ApplyEquipSpell(spellInfo,NULL,false,true); // remove spells that not fit to form + ApplyEquipSpell(spellInfo,NULL,true,true); // add spells that fit form but not active + } + } +} + +void Player::CastItemCombatSpell(Item *item,Unit* Target, WeaponAttackType attType) +{ + if(!item || item->IsBroken()) + return; + + ItemPrototype const *proto = item->GetProto(); + if(!proto) + return; + + if (!Target || Target == this ) + return; + + for (int i = 0; i < 5; i++) + { + _Spell const& spellData = proto->Spells[i]; + + // no spell + if(!spellData.SpellId ) + continue; + + // wrong triggering type + if(spellData.SpellTrigger != ITEM_SPELLTRIGGER_CHANCE_ON_HIT) + continue; + + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellData.SpellId); + if(!spellInfo) + { + sLog.outError("WORLD: unknown Item spellid %i", spellData.SpellId); + continue; + } + + // not allow proc extra attack spell at extra attack + if( m_extraAttacks && IsSpellHaveEffect(spellInfo,SPELL_EFFECT_ADD_EXTRA_ATTACKS) ) + return; + + float chance = spellInfo->procChance; + + if(spellData.SpellPPMRate) + { + uint32 WeaponSpeed = GetAttackTime(attType); + chance = GetPPMProcChance(WeaponSpeed, spellData.SpellPPMRate); + } + else if(chance > 100.0f) + { + chance = GetWeaponProcChance(); + } + + if (roll_chance_f(chance)) + this->CastSpell(Target, spellInfo->Id, true, item); + } + + // item combat enchantments + for(int e_slot = 0; e_slot < MAX_ENCHANTMENT_SLOT; ++e_slot) + { + uint32 enchant_id = item->GetEnchantmentId(EnchantmentSlot(e_slot)); + SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id); + if(!pEnchant) continue; + for (int s=0;s<3;s++) + { + if(pEnchant->type[s]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL) + continue; + + SpellEntry const *spellInfo = sSpellStore.LookupEntry(pEnchant->spellid[s]); + if (!spellInfo) + { + sLog.outError("Player::CastItemCombatSpell Enchant %i, cast unknown spell %i", pEnchant->ID, pEnchant->spellid[s]); + continue; + } + + float chance = pEnchant->amount[s] != 0 ? float(pEnchant->amount[s]) : GetWeaponProcChance(); + if (roll_chance_f(chance)) + { + if(IsPositiveSpell(pEnchant->spellid[s])) + CastSpell(this, pEnchant->spellid[s], true, item); + else + CastSpell(Target, pEnchant->spellid[s], true, item); + } + } + } +} + +void Player::_RemoveAllItemMods() +{ + sLog.outDebug("_RemoveAllItemMods start."); + + for (int i = 0; i < INVENTORY_SLOT_BAG_END; i++) + { + if(m_items[i]) + { + ItemPrototype const *proto = m_items[i]->GetProto(); + if(!proto) + continue; + + // item set bonuses not dependent from item broken state + if(proto->ItemSet) + RemoveItemsSetItem(this,proto); + + if(m_items[i]->IsBroken()) + continue; + + ApplyItemEquipSpell(m_items[i],false); + ApplyEnchantment(m_items[i], false); + } + } + + for (int i = 0; i < INVENTORY_SLOT_BAG_END; i++) + { + if(m_items[i]) + { + if(m_items[i]->IsBroken()) + continue; + ItemPrototype const *proto = m_items[i]->GetProto(); + if(!proto) + continue; + + uint32 attacktype = Player::GetAttackBySlot(i); + if(attacktype < MAX_ATTACK) + _ApplyWeaponDependentAuraMods(m_items[i],WeaponAttackType(attacktype),false); + + _ApplyItemBonuses(proto,i, false); + + if( i == EQUIPMENT_SLOT_RANGED ) + _ApplyAmmoBonuses(); + } + } + + sLog.outDebug("_RemoveAllItemMods complete."); +} + +void Player::_ApplyAllItemMods() +{ + sLog.outDebug("_ApplyAllItemMods start."); + + for (int i = 0; i < INVENTORY_SLOT_BAG_END; i++) + { + if(m_items[i]) + { + if(m_items[i]->IsBroken()) + continue; + + ItemPrototype const *proto = m_items[i]->GetProto(); + if(!proto) + continue; + + uint32 attacktype = Player::GetAttackBySlot(i); + if(attacktype < MAX_ATTACK) + _ApplyWeaponDependentAuraMods(m_items[i],WeaponAttackType(attacktype),true); + + _ApplyItemBonuses(proto,i, true); + + if( i == EQUIPMENT_SLOT_RANGED ) + _ApplyAmmoBonuses(); + } + } + + for (int i = 0; i < INVENTORY_SLOT_BAG_END; i++) + { + if(m_items[i]) + { + ItemPrototype const *proto = m_items[i]->GetProto(); + if(!proto) + continue; + + // item set bonuses not dependent from item broken state + if(proto->ItemSet) + AddItemsSetItem(this,m_items[i]); + + if(m_items[i]->IsBroken()) + continue; + + ApplyItemEquipSpell(m_items[i],true); + ApplyEnchantment(m_items[i], true); + } + } + + sLog.outDebug("_ApplyAllItemMods complete."); +} + +void Player::_ApplyAmmoBonuses() +{ + // check ammo + uint32 ammo_id = GetUInt32Value(PLAYER_AMMO_ID); + if(!ammo_id) + return; + + float currentAmmoDPS; + + ItemPrototype const *ammo_proto = objmgr.GetItemPrototype( ammo_id ); + if( !ammo_proto || ammo_proto->Class!=ITEM_CLASS_PROJECTILE || !CheckAmmoCompatibility(ammo_proto)) + currentAmmoDPS = 0.0f; + else + currentAmmoDPS = ammo_proto->Damage[0].DamageMin; + + if(currentAmmoDPS == GetAmmoDPS()) + return; + + m_ammoDPS = currentAmmoDPS; + + if(CanModifyStats()) + UpdateDamagePhysical(RANGED_ATTACK); +} + +bool Player::CheckAmmoCompatibility(const ItemPrototype *ammo_proto) const +{ + if(!ammo_proto) + return false; + + // check ranged weapon + Item *weapon = GetWeaponForAttack( RANGED_ATTACK ); + if(!weapon || weapon->IsBroken() ) + return false; + + ItemPrototype const* weapon_proto = weapon->GetProto(); + if(!weapon_proto || weapon_proto->Class!=ITEM_CLASS_WEAPON ) + return false; + + // check ammo ws. weapon compatibility + switch(weapon_proto->SubClass) + { + case ITEM_SUBCLASS_WEAPON_BOW: + case ITEM_SUBCLASS_WEAPON_CROSSBOW: + if(ammo_proto->SubClass!=ITEM_SUBCLASS_ARROW) + return false; + break; + case ITEM_SUBCLASS_WEAPON_GUN: + if(ammo_proto->SubClass!=ITEM_SUBCLASS_BULLET) + return false; + break; + default: + return false; + } + + return true; +} + +/* If in a battleground a player dies, and an enemy removes the insignia, the player's bones is lootable + Called by remove insignia spell effect */ +void Player::RemovedInsignia(Player* looterPlr) +{ + if (!GetBattleGroundId()) + return; + + // If not released spirit, do it ! + if(m_deathTimer > 0) + { + m_deathTimer = 0; + BuildPlayerRepop(); + RepopAtGraveyard(); + } + + Corpse *corpse = GetCorpse(); + if (!corpse) + return; + + // We have to convert player corpse to bones, not to be able to resurrect there + // SpawnCorpseBones isn't handy, 'cos it saves player while he in BG + Corpse *bones = ObjectAccessor::Instance().ConvertCorpseForPlayer(GetGUID()); + if (!bones) + return; + + // Now we must make bones lootable, and send player loot + bones->SetFlag(CORPSE_FIELD_DYNAMIC_FLAGS, CORPSE_DYNFLAG_LOOTABLE); + + // We store the level of our player in the gold field + // We retrieve this information at Player::SendLoot() + bones->loot.gold = getLevel(); + bones->lootRecipient = looterPlr; + looterPlr->SendLoot(bones->GetGUID(), LOOT_INSIGNIA); +} + +/*Loot type MUST be +1-corpse, go +2-skinning +3-Fishing +*/ + +void Player::SendLootRelease( uint64 guid ) +{ + WorldPacket data( SMSG_LOOT_RELEASE_RESPONSE, (8+1) ); + data << uint64(guid) << uint8(1); + SendDirectMessage( &data ); +} + +void Player::SendLoot(uint64 guid, LootType loot_type) +{ + Loot *loot = 0; + PermissionTypes permission = ALL_PERMISSION; + + sLog.outDebug("Player::SendLoot"); + if (IS_GAMEOBJECT_GUID(guid)) + { + sLog.outDebug(" IS_GAMEOBJECT_GUID(guid)"); + GameObject *go = + ObjectAccessor::GetGameObject(*this, guid); + + // not check distance for GO in case owned GO (fishing bobber case, for example) + // And permit out of range GO with no owner in case fishing hole + if (!go || (loot_type != LOOT_FISHINGHOLE && (loot_type != LOOT_FISHING || go->GetOwnerGUID() != GetGUID()) && !go->IsWithinDistInMap(this,INTERACTION_DISTANCE))) + { + SendLootRelease(guid); + return; + } + + loot = &go->loot; + + if(go->getLootState() == GO_READY) + { + uint32 lootid = go->GetLootId(); + + if(lootid) + { + sLog.outDebug(" if(lootid)"); + loot->clear(); + loot->FillLoot(lootid, LootTemplates_Gameobject, this); + } + + if(loot_type == LOOT_FISHING) + go->getFishLoot(loot); + + go->SetLootState(GO_ACTIVATED); + } + } + else if (IS_ITEM_GUID(guid)) + { + Item *item = GetItemByGuid( guid ); + + if (!item) + { + SendLootRelease(guid); + return; + } + + if(loot_type == LOOT_DISENCHANTING) + { + loot = &item->loot; + + if(!item->m_lootGenerated) + { + item->m_lootGenerated = true; + loot->clear(); + loot->FillLoot(item->GetProto()->DisenchantID, LootTemplates_Disenchant, this); + } + } + else if(loot_type == LOOT_PROSPECTING) + { + loot = &item->loot; + + if(!item->m_lootGenerated) + { + item->m_lootGenerated = true; + loot->clear(); + loot->FillLoot(item->GetEntry(), LootTemplates_Prospecting, this); + } + } + else + { + loot = &item->loot; + + if(!item->m_lootGenerated) + { + item->m_lootGenerated = true; + loot->clear(); + loot->FillLoot(item->GetEntry(), LootTemplates_Item, this); + + loot->generateMoneyLoot(item->GetProto()->MinMoneyLoot,item->GetProto()->MaxMoneyLoot); + } + } + } + else if (IS_CORPSE_GUID(guid)) // remove insignia + { + Corpse *bones = ObjectAccessor::GetCorpse(*this, guid); + + if (!bones || !((loot_type == LOOT_CORPSE) || (loot_type == LOOT_INSIGNIA)) || (bones->GetType() != CORPSE_BONES) ) + { + SendLootRelease(guid); + return; + } + + loot = &bones->loot; + + if (!bones->lootForBody) + { + bones->lootForBody = true; + uint32 pLevel = bones->loot.gold; + bones->loot.clear(); + // It may need a better formula + // Now it works like this: lvl10: ~6copper, lvl70: ~9silver + bones->loot.gold = (uint32)( urand(50, 150) * 0.016f * pow( ((float)pLevel)/5.76f, 2.5f) * sWorld.getRate(RATE_DROP_MONEY) ); + } + + if (bones->lootRecipient != this) + permission = NONE_PERMISSION; + } + else + { + Creature *creature = ObjectAccessor::GetCreature(*this, guid); + + // must be in range and creature must be alive for pickpocket and must be dead for another loot + if (!creature || creature->isAlive()!=(loot_type == LOOT_PICKPOCKETING) || !creature->IsWithinDistInMap(this,INTERACTION_DISTANCE)) + { + SendLootRelease(guid); + return; + } + + if(loot_type == LOOT_PICKPOCKETING && IsFriendlyTo(creature)) + { + SendLootRelease(guid); + return; + } + + loot = &creature->loot; + + if(loot_type == LOOT_PICKPOCKETING) + { + if ( !creature->lootForPickPocketed ) + { + creature->lootForPickPocketed = true; + loot->clear(); + + if (uint32 lootid = creature->GetCreatureInfo()->pickpocketLootId) + loot->FillLoot(lootid, LootTemplates_Pickpocketing, this); + + // Generate extra money for pick pocket loot + const uint32 a = urand(0, creature->getLevel()/2); + const uint32 b = urand(0, getLevel()/2); + loot->gold = uint32(10 * (a + b) * sWorld.getRate(RATE_DROP_MONEY)); + } + } + else + { + // the player whose group may loot the corpse + Player *recipient = creature->GetLootRecipient(); + if (!recipient) + { + creature->SetLootRecipient(this); + recipient = this; + } + + if (creature->lootForPickPocketed) + { + creature->lootForPickPocketed = false; + loot->clear(); + } + + if(!creature->lootForBody) + { + creature->lootForBody = true; + loot->clear(); + + if (uint32 lootid = creature->GetCreatureInfo()->lootid) + loot->FillLoot(lootid, LootTemplates_Creature, recipient); + + loot->generateMoneyLoot(creature->GetCreatureInfo()->mingold,creature->GetCreatureInfo()->maxgold); + + if(Group* group = recipient->GetGroup()) + { + group->UpdateLooterGuid(creature,true); + + switch (group->GetLootMethod()) + { + case GROUP_LOOT: + // GroupLoot delete items over threshold (threshold even not implemented), and roll them. Items with qualityGroupLoot(recipient->GetGUID(), loot, creature); + break; + case NEED_BEFORE_GREED: + group->NeedBeforeGreed(recipient->GetGUID(), loot, creature); + break; + case MASTER_LOOT: + group->MasterLoot(recipient->GetGUID(), loot, creature); + break; + default: + break; + } + } + } + + // possible only if creature->lootForBody && loot->empty() at spell cast check + if (loot_type == LOOT_SKINNING) + { + loot->clear(); + loot->FillLoot(creature->GetCreatureInfo()->SkinLootId, LootTemplates_Skinning, this); + } + // set group rights only for loot_type != LOOT_SKINNING + else + { + if(Group* group = GetGroup()) + { + if( group == recipient->GetGroup() ) + { + if(group->GetLootMethod() == FREE_FOR_ALL) + permission = ALL_PERMISSION; + else if(group->GetLooterGuid() == GetGUID()) + { + if(group->GetLootMethod() == MASTER_LOOT) + permission = MASTER_PERMISSION; + else + permission = ALL_PERMISSION; + } + else + permission = GROUP_PERMISSION; + } + else + permission = NONE_PERMISSION; + } + else if(recipient == this) + permission = ALL_PERMISSION; + else + permission = NONE_PERMISSION; + } + } + } + + SetLootGUID(guid); + + QuestItemList *q_list = 0; + if (permission != NONE_PERMISSION) + { + QuestItemMap const& lootPlayerQuestItems = loot->GetPlayerQuestItems(); + QuestItemMap::const_iterator itr = lootPlayerQuestItems.find(GetGUIDLow()); + if (itr == lootPlayerQuestItems.end()) + q_list = loot->FillQuestLoot(this); + else + q_list = itr->second; + } + + QuestItemList *ffa_list = 0; + if (permission != NONE_PERMISSION) + { + QuestItemMap const& lootPlayerFFAItems = loot->GetPlayerFFAItems(); + QuestItemMap::const_iterator itr = lootPlayerFFAItems.find(GetGUIDLow()); + if (itr == lootPlayerFFAItems.end()) + ffa_list = loot->FillFFALoot(this); + else + ffa_list = itr->second; + } + + QuestItemList *conditional_list = 0; + if (permission != NONE_PERMISSION) + { + QuestItemMap const& lootPlayerNonQuestNonFFAConditionalItems = loot->GetPlayerNonQuestNonFFAConditionalItems(); + QuestItemMap::const_iterator itr = lootPlayerNonQuestNonFFAConditionalItems.find(GetGUIDLow()); + if (itr == lootPlayerNonQuestNonFFAConditionalItems.end()) + conditional_list = loot->FillNonQuestNonFFAConditionalLoot(this); + else + conditional_list = itr->second; + } + + // LOOT_PICKPOCKETING, LOOT_PROSPECTING, LOOT_DISENCHANTING and LOOT_INSIGNIA unsupported by client, sending LOOT_SKINNING instead + if(loot_type == LOOT_PICKPOCKETING || loot_type == LOOT_DISENCHANTING || loot_type == LOOT_PROSPECTING || loot_type == LOOT_INSIGNIA) + loot_type = LOOT_SKINNING; + + if(loot_type == LOOT_FISHINGHOLE) + loot_type = LOOT_FISHING; + + WorldPacket data(SMSG_LOOT_RESPONSE, (9+50)); // we guess size + + data << uint64(guid); + data << uint8(loot_type); + data << LootView(*loot, q_list, ffa_list, conditional_list, this, permission); + + SendDirectMessage(&data); + + // add 'this' player as one of the players that are looting 'loot' + if (permission != NONE_PERMISSION) + loot->AddLooter(GetGUID()); + + if ( loot_type == LOOT_CORPSE && !IS_ITEM_GUID(guid) ) + SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_LOOTING); +} + +void Player::SendNotifyLootMoneyRemoved() +{ + WorldPacket data(SMSG_LOOT_CLEAR_MONEY, 0); + GetSession()->SendPacket( &data ); +} + +void Player::SendNotifyLootItemRemoved(uint8 lootSlot) +{ + WorldPacket data(SMSG_LOOT_REMOVED, 1); + data << uint8(lootSlot); + GetSession()->SendPacket( &data ); +} + +void Player::SendUpdateWorldState(uint32 Field, uint32 Value) +{ + WorldPacket data(SMSG_UPDATE_WORLD_STATE, 8); + data << Field; + data << Value; + GetSession()->SendPacket(&data); +} + +void Player::SendInitWorldStates() +{ + // data depends on zoneid/mapid... + BattleGround* bg = GetBattleGround(); + uint16 NumberOfFields = 0; + uint32 mapid = GetMapId(); + uint32 zoneid = GetZoneId(); + uint32 areaid = GetAreaId(); + sLog.outDebug("Sending SMSG_INIT_WORLD_STATES to Map:%u, Zone: %u", mapid, zoneid); + // may be exist better way to do this... + switch(zoneid) + { + case 0: + case 1: + case 4: + case 8: + case 10: + case 11: + case 12: + case 36: + case 38: + case 40: + case 41: + case 51: + case 267: + case 1519: + case 1537: + case 2257: + case 2918: + NumberOfFields = 6; + break; + case 2597: + NumberOfFields = 81; + break; + case 3277: + NumberOfFields = 14; + break; + case 3358: + case 3820: + NumberOfFields = 38; + break; + case 3483: + NumberOfFields = 22; + break; + case 3519: + NumberOfFields = 36; + break; + case 3521: + NumberOfFields = 35; + break; + case 3698: + case 3702: + case 3968: + NumberOfFields = 9; + break; + case 3703: + NumberOfFields = 9; + break; + default: + NumberOfFields = 10; + break; + } + + WorldPacket data(SMSG_INIT_WORLD_STATES, (4+4+4+2+(NumberOfFields*8))); + data << uint32(mapid); // mapid + data << uint32(zoneid); // zone id + data << uint32(areaid); // area id, new 2.1.0 + data << uint16(NumberOfFields); // count of uint64 blocks + data << uint32(0x8d8) << uint32(0x0); // 1 + data << uint32(0x8d7) << uint32(0x0); // 2 + data << uint32(0x8d6) << uint32(0x0); // 3 + data << uint32(0x8d5) << uint32(0x0); // 4 + data << uint32(0x8d4) << uint32(0x0); // 5 + data << uint32(0x8d3) << uint32(0x0); // 6 + if(mapid == 530) // Outland + { + data << uint32(0x9bf) << uint32(0x0); // 7 + data << uint32(0x9bd) << uint32(0xF); // 8 + data << uint32(0x9bb) << uint32(0xF); // 9 + } + switch(zoneid) + { + case 1: + case 11: + case 12: + case 38: + case 40: + case 51: + case 1519: + case 1537: + case 2257: + break; + case 2597: // AV + data << uint32(0x7ae) << uint32(0x1); // 7 + data << uint32(0x532) << uint32(0x1); // 8 + data << uint32(0x531) << uint32(0x0); // 9 + data << uint32(0x52e) << uint32(0x0); // 10 + data << uint32(0x571) << uint32(0x0); // 11 + data << uint32(0x570) << uint32(0x0); // 12 + data << uint32(0x567) << uint32(0x1); // 13 + data << uint32(0x566) << uint32(0x1); // 14 + data << uint32(0x550) << uint32(0x1); // 15 + data << uint32(0x544) << uint32(0x0); // 16 + data << uint32(0x536) << uint32(0x0); // 17 + data << uint32(0x535) << uint32(0x1); // 18 + data << uint32(0x518) << uint32(0x0); // 19 + data << uint32(0x517) << uint32(0x0); // 20 + data << uint32(0x574) << uint32(0x0); // 21 + data << uint32(0x573) << uint32(0x0); // 22 + data << uint32(0x572) << uint32(0x0); // 23 + data << uint32(0x56f) << uint32(0x0); // 24 + data << uint32(0x56e) << uint32(0x0); // 25 + data << uint32(0x56d) << uint32(0x0); // 26 + data << uint32(0x56c) << uint32(0x0); // 27 + data << uint32(0x56b) << uint32(0x0); // 28 + data << uint32(0x56a) << uint32(0x1); // 29 + data << uint32(0x569) << uint32(0x1); // 30 + data << uint32(0x568) << uint32(0x1); // 13 + data << uint32(0x565) << uint32(0x0); // 32 + data << uint32(0x564) << uint32(0x0); // 33 + data << uint32(0x563) << uint32(0x0); // 34 + data << uint32(0x562) << uint32(0x0); // 35 + data << uint32(0x561) << uint32(0x0); // 36 + data << uint32(0x560) << uint32(0x0); // 37 + data << uint32(0x55f) << uint32(0x0); // 38 + data << uint32(0x55e) << uint32(0x0); // 39 + data << uint32(0x55d) << uint32(0x0); // 40 + data << uint32(0x3c6) << uint32(0x4); // 41 + data << uint32(0x3c4) << uint32(0x6); // 42 + data << uint32(0x3c2) << uint32(0x4); // 43 + data << uint32(0x516) << uint32(0x1); // 44 + data << uint32(0x515) << uint32(0x0); // 45 + data << uint32(0x3b6) << uint32(0x6); // 46 + data << uint32(0x55c) << uint32(0x0); // 47 + data << uint32(0x55b) << uint32(0x0); // 48 + data << uint32(0x55a) << uint32(0x0); // 49 + data << uint32(0x559) << uint32(0x0); // 50 + data << uint32(0x558) << uint32(0x0); // 51 + data << uint32(0x557) << uint32(0x0); // 52 + data << uint32(0x556) << uint32(0x0); // 53 + data << uint32(0x555) << uint32(0x0); // 54 + data << uint32(0x554) << uint32(0x1); // 55 + data << uint32(0x553) << uint32(0x1); // 56 + data << uint32(0x552) << uint32(0x1); // 57 + data << uint32(0x551) << uint32(0x1); // 58 + data << uint32(0x54f) << uint32(0x0); // 59 + data << uint32(0x54e) << uint32(0x0); // 60 + data << uint32(0x54d) << uint32(0x1); // 61 + data << uint32(0x54c) << uint32(0x0); // 62 + data << uint32(0x54b) << uint32(0x0); // 63 + data << uint32(0x545) << uint32(0x0); // 64 + data << uint32(0x543) << uint32(0x1); // 65 + data << uint32(0x542) << uint32(0x0); // 66 + data << uint32(0x540) << uint32(0x0); // 67 + data << uint32(0x53f) << uint32(0x0); // 68 + data << uint32(0x53e) << uint32(0x0); // 69 + data << uint32(0x53d) << uint32(0x0); // 70 + data << uint32(0x53c) << uint32(0x0); // 71 + data << uint32(0x53b) << uint32(0x0); // 72 + data << uint32(0x53a) << uint32(0x1); // 73 + data << uint32(0x539) << uint32(0x0); // 74 + data << uint32(0x538) << uint32(0x0); // 75 + data << uint32(0x537) << uint32(0x0); // 76 + data << uint32(0x534) << uint32(0x0); // 77 + data << uint32(0x533) << uint32(0x0); // 78 + data << uint32(0x530) << uint32(0x0); // 79 + data << uint32(0x52f) << uint32(0x0); // 80 + data << uint32(0x52d) << uint32(0x1); // 81 + break; + case 3277: // WS + if (bg && bg->GetTypeID() == BATTLEGROUND_WS) + bg->FillInitialWorldStates(data); + else + { + data << uint32(0x62d) << uint32(0x0); // 7 1581 alliance flag captures + data << uint32(0x62e) << uint32(0x0); // 8 1582 horde flag captures + data << uint32(0x609) << uint32(0x0); // 9 1545 unk, set to 1 on alliance flag pickup... + data << uint32(0x60a) << uint32(0x0); // 10 1546 unk, set to 1 on horde flag pickup, after drop it's -1 + data << uint32(0x60b) << uint32(0x2); // 11 1547 unk + data << uint32(0x641) << uint32(0x3); // 12 1601 unk (max flag captures?) + data << uint32(0x922) << uint32(0x1); // 13 2338 horde (0 - hide, 1 - flag ok, 2 - flag picked up (flashing), 3 - flag picked up (not flashing) + data << uint32(0x923) << uint32(0x1); // 14 2339 alliance (0 - hide, 1 - flag ok, 2 - flag picked up (flashing), 3 - flag picked up (not flashing) + } + break; + case 3358: // AB + if (bg && bg->GetTypeID() == BATTLEGROUND_AB) + bg->FillInitialWorldStates(data); + else + { + data << uint32(0x6e7) << uint32(0x0); // 7 1767 stables alliance + data << uint32(0x6e8) << uint32(0x0); // 8 1768 stables horde + data << uint32(0x6e9) << uint32(0x0); // 9 1769 unk, ST? + data << uint32(0x6ea) << uint32(0x0); // 10 1770 stables (show/hide) + data << uint32(0x6ec) << uint32(0x0); // 11 1772 farm (0 - horde controlled, 1 - alliance controlled) + data << uint32(0x6ed) << uint32(0x0); // 12 1773 farm (show/hide) + data << uint32(0x6ee) << uint32(0x0); // 13 1774 farm color + data << uint32(0x6ef) << uint32(0x0); // 14 1775 gold mine color, may be FM? + data << uint32(0x6f0) << uint32(0x0); // 15 1776 alliance resources + data << uint32(0x6f1) << uint32(0x0); // 16 1777 horde resources + data << uint32(0x6f2) << uint32(0x0); // 17 1778 horde bases + data << uint32(0x6f3) << uint32(0x0); // 18 1779 alliance bases + data << uint32(0x6f4) << uint32(0x7d0); // 19 1780 max resources (2000) + data << uint32(0x6f6) << uint32(0x0); // 20 1782 blacksmith color + data << uint32(0x6f7) << uint32(0x0); // 21 1783 blacksmith (show/hide) + data << uint32(0x6f8) << uint32(0x0); // 22 1784 unk, bs? + data << uint32(0x6f9) << uint32(0x0); // 23 1785 unk, bs? + data << uint32(0x6fb) << uint32(0x0); // 24 1787 gold mine (0 - horde contr, 1 - alliance contr) + data << uint32(0x6fc) << uint32(0x0); // 25 1788 gold mine (0 - conflict, 1 - horde) + data << uint32(0x6fd) << uint32(0x0); // 26 1789 gold mine (1 - show/0 - hide) + data << uint32(0x6fe) << uint32(0x0); // 27 1790 gold mine color + data << uint32(0x700) << uint32(0x0); // 28 1792 gold mine color, wtf?, may be LM? + data << uint32(0x701) << uint32(0x0); // 29 1793 lumber mill color (0 - conflict, 1 - horde contr) + data << uint32(0x702) << uint32(0x0); // 30 1794 lumber mill (show/hide) + data << uint32(0x703) << uint32(0x0); // 31 1795 lumber mill color color + data << uint32(0x732) << uint32(0x1); // 32 1842 stables (1 - uncontrolled) + data << uint32(0x733) << uint32(0x1); // 33 1843 gold mine (1 - uncontrolled) + data << uint32(0x734) << uint32(0x1); // 34 1844 lumber mill (1 - uncontrolled) + data << uint32(0x735) << uint32(0x1); // 35 1845 farm (1 - uncontrolled) + data << uint32(0x736) << uint32(0x1); // 36 1846 blacksmith (1 - uncontrolled) + data << uint32(0x745) << uint32(0x2); // 37 1861 unk + data << uint32(0x7a3) << uint32(0x708); // 38 1955 warning limit (1800) + } + break; + case 3820: // EY + if (bg && bg->GetTypeID() == BATTLEGROUND_EY) + bg->FillInitialWorldStates(data); + else + { + data << uint32(0xac1) << uint32(0x0); // 7 2753 Horde Bases + data << uint32(0xac0) << uint32(0x0); // 8 2752 Alliance Bases + data << uint32(0xab6) << uint32(0x0); // 9 2742 Mage Tower - Horde conflict + data << uint32(0xab5) << uint32(0x0); // 10 2741 Mage Tower - Alliance conflict + data << uint32(0xab4) << uint32(0x0); // 11 2740 Fel Reaver - Horde conflict + data << uint32(0xab3) << uint32(0x0); // 12 2739 Fel Reaver - Alliance conflict + data << uint32(0xab2) << uint32(0x0); // 13 2738 Draenei - Alliance conflict + data << uint32(0xab1) << uint32(0x0); // 14 2737 Draenei - Horde conflict + data << uint32(0xab0) << uint32(0x0); // 15 2736 unk // 0 at start + data << uint32(0xaaf) << uint32(0x0); // 16 2735 unk // 0 at start + data << uint32(0xaad) << uint32(0x0); // 17 2733 Draenei - Horde control + data << uint32(0xaac) << uint32(0x0); // 18 2732 Draenei - Alliance control + data << uint32(0xaab) << uint32(0x1); // 19 2731 Draenei uncontrolled (1 - yes, 0 - no) + data << uint32(0xaaa) << uint32(0x0); // 20 2730 Mage Tower - Alliance control + data << uint32(0xaa9) << uint32(0x0); // 21 2729 Mage Tower - Horde control + data << uint32(0xaa8) << uint32(0x1); // 22 2728 Mage Tower uncontrolled (1 - yes, 0 - no) + data << uint32(0xaa7) << uint32(0x0); // 23 2727 Fel Reaver - Horde control + data << uint32(0xaa6) << uint32(0x0); // 24 2726 Fel Reaver - Alliance control + data << uint32(0xaa5) << uint32(0x1); // 25 2725 Fel Reaver uncontroled (1 - yes, 0 - no) + data << uint32(0xaa4) << uint32(0x0); // 26 2724 Boold Elf - Horde control + data << uint32(0xaa3) << uint32(0x0); // 27 2723 Boold Elf - Alliance control + data << uint32(0xaa2) << uint32(0x1); // 28 2722 Boold Elf uncontrolled (1 - yes, 0 - no) + data << uint32(0xac5) << uint32(0x1); // 29 2757 Flag (1 - show, 0 - hide) - doesn't work exactly this way! + data << uint32(0xad2) << uint32(0x1); // 30 2770 Horde top-stats (1 - show, 0 - hide) // 02 -> horde picked up the flag + data << uint32(0xad1) << uint32(0x1); // 31 2769 Alliance top-stats (1 - show, 0 - hide) // 02 -> alliance picked up the flag + data << uint32(0xabe) << uint32(0x0); // 32 2750 Horde resources + data << uint32(0xabd) << uint32(0x0); // 33 2749 Alliance resources + data << uint32(0xa05) << uint32(0x8e); // 34 2565 unk, constant? + data << uint32(0xaa0) << uint32(0x0); // 35 2720 Capturing progress-bar (100 -> empty (only grey), 0 -> blue|red (no grey), default 0) + data << uint32(0xa9f) << uint32(0x0); // 36 2719 Capturing progress-bar (0 - left, 100 - right) + data << uint32(0xa9e) << uint32(0x0); // 37 2718 Capturing progress-bar (1 - show, 0 - hide) + data << uint32(0xc0d) << uint32(0x17b); // 38 3085 unk + // and some more ... unknown + } + break; + case 3483: // Hellfire Peninsula + data << uint32(0x9ba) << uint32(0x1); // 10 + data << uint32(0x9b9) << uint32(0x1); // 11 + data << uint32(0x9b5) << uint32(0x0); // 12 + data << uint32(0x9b4) << uint32(0x1); // 13 + data << uint32(0x9b3) << uint32(0x0); // 14 + data << uint32(0x9b2) << uint32(0x0); // 15 + data << uint32(0x9b1) << uint32(0x1); // 16 + data << uint32(0x9b0) << uint32(0x0); // 17 + data << uint32(0x9ae) << uint32(0x0); // 18 horde pvp objectives captured + data << uint32(0x9ac) << uint32(0x0); // 19 + data << uint32(0x9a8) << uint32(0x0); // 20 + data << uint32(0x9a7) << uint32(0x0); // 21 + data << uint32(0x9a6) << uint32(0x1); // 22 + break; + case 3519: // Terokkar Forest + data << uint32(0xa41) << uint32(0x0); // 10 + data << uint32(0xa40) << uint32(0x14); // 11 + data << uint32(0xa3f) << uint32(0x0); // 12 + data << uint32(0xa3e) << uint32(0x0); // 13 + data << uint32(0xa3d) << uint32(0x5); // 14 + data << uint32(0xa3c) << uint32(0x0); // 15 + data << uint32(0xa87) << uint32(0x0); // 16 + data << uint32(0xa86) << uint32(0x0); // 17 + data << uint32(0xa85) << uint32(0x0); // 18 + data << uint32(0xa84) << uint32(0x0); // 19 + data << uint32(0xa83) << uint32(0x0); // 20 + data << uint32(0xa82) << uint32(0x0); // 21 + data << uint32(0xa81) << uint32(0x0); // 22 + data << uint32(0xa80) << uint32(0x0); // 23 + data << uint32(0xa7e) << uint32(0x0); // 24 + data << uint32(0xa7d) << uint32(0x0); // 25 + data << uint32(0xa7c) << uint32(0x0); // 26 + data << uint32(0xa7b) << uint32(0x0); // 27 + data << uint32(0xa7a) << uint32(0x0); // 28 + data << uint32(0xa79) << uint32(0x0); // 29 + data << uint32(0x9d0) << uint32(0x5); // 30 + data << uint32(0x9ce) << uint32(0x0); // 31 + data << uint32(0x9cd) << uint32(0x0); // 32 + data << uint32(0x9cc) << uint32(0x0); // 33 + data << uint32(0xa88) << uint32(0x0); // 34 + data << uint32(0xad0) << uint32(0x0); // 35 + data << uint32(0xacf) << uint32(0x1); // 36 + break; + case 3521: // Zangarmarsh + data << uint32(0x9e1) << uint32(0x0); // 10 + data << uint32(0x9e0) << uint32(0x0); // 11 + data << uint32(0x9df) << uint32(0x0); // 12 + data << uint32(0xa5d) << uint32(0x1); // 13 + data << uint32(0xa5c) << uint32(0x0); // 14 + data << uint32(0xa5b) << uint32(0x1); // 15 + data << uint32(0xa5a) << uint32(0x0); // 16 + data << uint32(0xa59) << uint32(0x1); // 17 + data << uint32(0xa58) << uint32(0x0); // 18 + data << uint32(0xa57) << uint32(0x0); // 19 + data << uint32(0xa56) << uint32(0x0); // 20 + data << uint32(0xa55) << uint32(0x1); // 21 + data << uint32(0xa54) << uint32(0x0); // 22 + data << uint32(0x9e7) << uint32(0x0); // 23 + data << uint32(0x9e6) << uint32(0x0); // 24 + data << uint32(0x9e5) << uint32(0x0); // 25 + data << uint32(0xa00) << uint32(0x0); // 26 + data << uint32(0x9ff) << uint32(0x1); // 27 + data << uint32(0x9fe) << uint32(0x0); // 28 + data << uint32(0x9fd) << uint32(0x0); // 29 + data << uint32(0x9fc) << uint32(0x1); // 30 + data << uint32(0x9fb) << uint32(0x0); // 31 + data << uint32(0xa62) << uint32(0x0); // 32 + data << uint32(0xa61) << uint32(0x1); // 33 + data << uint32(0xa60) << uint32(0x1); // 34 + data << uint32(0xa5f) << uint32(0x0); // 35 + break; + case 3698: // Nagrand Arena + data << uint32(0xa0f) << uint32(0x0); // 7 + data << uint32(0xa10) << uint32(0x0); // 8 + data << uint32(0xa11) << uint32(0x0); // 9 + break; + case 3702: // Blade's Edge Arena + data << uint32(0x9f0) << uint32(0x0); // 7 + data << uint32(0x9f1) << uint32(0x0); // 8 + data << uint32(0x9f3) << uint32(0x0); // 9 + break; + case 3968: // Ruins of Lordaeron + data << uint32(0xbb8) << uint32(0x0); // 7 + data << uint32(0xbb9) << uint32(0x0); // 8 + data << uint32(0xbba) << uint32(0x0); // 9 + break; + case 3703: // Shattrath City + break; + default: + data << uint32(0x914) << uint32(0x0); // 7 + data << uint32(0x913) << uint32(0x0); // 8 + data << uint32(0x912) << uint32(0x0); // 9 + data << uint32(0x915) << uint32(0x0); // 10 + break; + } + GetSession()->SendPacket(&data); +} + +uint32 Player::GetXPRestBonus(uint32 xp) +{ + uint32 rested_bonus = (uint32)GetRestBonus(); // xp for each rested bonus + + if(rested_bonus > xp) // max rested_bonus == xp or (r+x) = 200% xp + rested_bonus = xp; + + SetRestBonus( GetRestBonus() - rested_bonus); + + sLog.outDetail("Player gain %u xp (+ %u Rested Bonus). Rested points=%f",xp+rested_bonus,rested_bonus,GetRestBonus()); + return rested_bonus; +} + +void Player::SetBindPoint(uint64 guid) +{ + WorldPacket data(SMSG_BINDER_CONFIRM, 8); + data << uint64(guid); + GetSession()->SendPacket( &data ); +} + +void Player::SendTalentWipeConfirm(uint64 guid) +{ + WorldPacket data(MSG_TALENT_WIPE_CONFIRM, (8+4)); + data << uint64(guid); + data << uint32(resetTalentsCost()); + GetSession()->SendPacket( &data ); +} + +void Player::SendPetSkillWipeConfirm() +{ + Pet* pet = GetPet(); + if(!pet) + return; + WorldPacket data(SMSG_PET_UNLEARN_CONFIRM, (8+4)); + data << pet->GetGUID(); + data << uint32(pet->resetTalentsCost()); + GetSession()->SendPacket( &data ); +} + +/*********************************************************/ +/*** STORAGE SYSTEM ***/ +/*********************************************************/ + +void Player::SetVirtualItemSlot( uint8 i, Item* item) +{ + assert(i < 3); + if(i < 2 && item) + { + if(!item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT)) + return; + uint32 charges = item->GetEnchantmentCharges(TEMP_ENCHANTMENT_SLOT); + if(charges == 0) + return; + if(charges > 1) + item->SetEnchantmentCharges(TEMP_ENCHANTMENT_SLOT,charges-1); + else if(charges <= 1) + { + ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,false); + item->ClearEnchantment(TEMP_ENCHANTMENT_SLOT); + } + } +} + +void Player::SetSheath( uint32 sheathed ) +{ + switch (sheathed) + { + case SHEATH_STATE_UNARMED: // no prepared weapon + SetVirtualItemSlot(0,NULL); + SetVirtualItemSlot(1,NULL); + SetVirtualItemSlot(2,NULL); + break; + case SHEATH_STATE_MELEE: // prepared melee weapon + { + SetVirtualItemSlot(0,GetWeaponForAttack(BASE_ATTACK,true)); + SetVirtualItemSlot(1,GetWeaponForAttack(OFF_ATTACK,true)); + SetVirtualItemSlot(2,NULL); + }; break; + case SHEATH_STATE_RANGED: // prepared ranged weapon + SetVirtualItemSlot(0,NULL); + SetVirtualItemSlot(1,NULL); + SetVirtualItemSlot(2,GetWeaponForAttack(RANGED_ATTACK,true)); + break; + default: + SetVirtualItemSlot(0,NULL); + SetVirtualItemSlot(1,NULL); + SetVirtualItemSlot(2,NULL); + break; + } + SetByteValue(UNIT_FIELD_BYTES_2, 0, sheathed); // this must visualize Sheath changing for other players... +} + +uint8 Player::FindEquipSlot( ItemPrototype const* proto, uint32 slot, bool swap ) const +{ + uint8 pClass = getClass(); + + uint8 slots[4]; + slots[0] = NULL_SLOT; + slots[1] = NULL_SLOT; + slots[2] = NULL_SLOT; + slots[3] = NULL_SLOT; + switch( proto->InventoryType ) + { + case INVTYPE_HEAD: + slots[0] = EQUIPMENT_SLOT_HEAD; + break; + case INVTYPE_NECK: + slots[0] = EQUIPMENT_SLOT_NECK; + break; + case INVTYPE_SHOULDERS: + slots[0] = EQUIPMENT_SLOT_SHOULDERS; + break; + case INVTYPE_BODY: + slots[0] = EQUIPMENT_SLOT_BODY; + break; + case INVTYPE_CHEST: + slots[0] = EQUIPMENT_SLOT_CHEST; + break; + case INVTYPE_ROBE: + slots[0] = EQUIPMENT_SLOT_CHEST; + break; + case INVTYPE_WAIST: + slots[0] = EQUIPMENT_SLOT_WAIST; + break; + case INVTYPE_LEGS: + slots[0] = EQUIPMENT_SLOT_LEGS; + break; + case INVTYPE_FEET: + slots[0] = EQUIPMENT_SLOT_FEET; + break; + case INVTYPE_WRISTS: + slots[0] = EQUIPMENT_SLOT_WRISTS; + break; + case INVTYPE_HANDS: + slots[0] = EQUIPMENT_SLOT_HANDS; + break; + case INVTYPE_FINGER: + slots[0] = EQUIPMENT_SLOT_FINGER1; + slots[1] = EQUIPMENT_SLOT_FINGER2; + break; + case INVTYPE_TRINKET: + slots[0] = EQUIPMENT_SLOT_TRINKET1; + slots[1] = EQUIPMENT_SLOT_TRINKET2; + break; + case INVTYPE_CLOAK: + slots[0] = EQUIPMENT_SLOT_BACK; + break; + case INVTYPE_WEAPON: + { + slots[0] = EQUIPMENT_SLOT_MAINHAND; + + // suggest offhand slot only if know dual wielding + // (this will be replace mainhand weapon at auto equip instead unwonted "you don't known dual wielding" ... + if(CanDualWield()) + slots[1] = EQUIPMENT_SLOT_OFFHAND; + };break; + case INVTYPE_SHIELD: + slots[0] = EQUIPMENT_SLOT_OFFHAND; + break; + case INVTYPE_RANGED: + slots[0] = EQUIPMENT_SLOT_RANGED; + break; + case INVTYPE_2HWEAPON: + slots[0] = EQUIPMENT_SLOT_MAINHAND; + break; + case INVTYPE_TABARD: + slots[0] = EQUIPMENT_SLOT_TABARD; + break; + case INVTYPE_WEAPONMAINHAND: + slots[0] = EQUIPMENT_SLOT_MAINHAND; + break; + case INVTYPE_WEAPONOFFHAND: + slots[0] = EQUIPMENT_SLOT_OFFHAND; + break; + case INVTYPE_HOLDABLE: + slots[0] = EQUIPMENT_SLOT_OFFHAND; + break; + case INVTYPE_THROWN: + slots[0] = EQUIPMENT_SLOT_RANGED; + break; + case INVTYPE_RANGEDRIGHT: + slots[0] = EQUIPMENT_SLOT_RANGED; + break; + case INVTYPE_BAG: + slots[0] = INVENTORY_SLOT_BAG_1; + slots[1] = INVENTORY_SLOT_BAG_2; + slots[2] = INVENTORY_SLOT_BAG_3; + slots[3] = INVENTORY_SLOT_BAG_4; + break; + case INVTYPE_RELIC: + { + switch(proto->SubClass) + { + case ITEM_SUBCLASS_ARMOR_LIBRAM: + if (pClass == CLASS_PALADIN) + slots[0] = EQUIPMENT_SLOT_RANGED; + break; + case ITEM_SUBCLASS_ARMOR_IDOL: + if (pClass == CLASS_DRUID) + slots[0] = EQUIPMENT_SLOT_RANGED; + break; + case ITEM_SUBCLASS_ARMOR_TOTEM: + if (pClass == CLASS_SHAMAN) + slots[0] = EQUIPMENT_SLOT_RANGED; + break; + case ITEM_SUBCLASS_ARMOR_MISC: + if (pClass == CLASS_WARLOCK) + slots[0] = EQUIPMENT_SLOT_RANGED; + break; + } + break; + } + default : + return NULL_SLOT; + } + + if( slot != NULL_SLOT ) + { + if( swap || !GetItemByPos( INVENTORY_SLOT_BAG_0, slot ) ) + { + for (int i = 0; i < 4; i++) + { + if ( slots[i] == slot ) + return slot; + } + } + } + else + { + // search free slot at first + for (int i = 0; i < 4; i++) + { + if ( slots[i] != NULL_SLOT && !GetItemByPos( INVENTORY_SLOT_BAG_0, slots[i] ) ) + { + // in case 2hand equipped weapon offhand slot empty but not free + if(slots[i]==EQUIPMENT_SLOT_OFFHAND) + { + Item* mainItem = GetItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND ); + if(!mainItem || mainItem->GetProto()->InventoryType != INVTYPE_2HWEAPON) + return slots[i]; + } + else + return slots[i]; + } + } + + // if not found free and can swap return first appropriate from used + for (int i = 0; i < 4; i++) + { + if ( slots[i] != NULL_SLOT && swap ) + return slots[i]; + } + } + + // no free position + return NULL_SLOT; +} + +uint8 Player::CanUnequipItems( uint32 item, uint32 count ) const +{ + Item *pItem; + uint32 tempcount = 0; + + uint8 res = EQUIP_ERR_OK; + + for(int i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_BAG_END; i++) + { + pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pItem && pItem->GetEntry() == item ) + { + uint8 ires = CanUnequipItem(INVENTORY_SLOT_BAG_0 << 8 | i, false); + if(ires==EQUIP_ERR_OK) + { + tempcount += pItem->GetCount(); + if( tempcount >= count ) + return EQUIP_ERR_OK; + } + else + res = ires; + } + } + for(int i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++) + { + pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pItem && pItem->GetEntry() == item ) + { + tempcount += pItem->GetCount(); + if( tempcount >= count ) + return EQUIP_ERR_OK; + } + } + for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++) + { + pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pItem && pItem->GetEntry() == item ) + { + tempcount += pItem->GetCount(); + if( tempcount >= count ) + return EQUIP_ERR_OK; + } + } + Bag *pBag; + ItemPrototype const *pBagProto; + for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) + { + pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pBag ) + { + pBagProto = pBag->GetProto(); + if( pBagProto ) + { + for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + { + pItem = GetItemByPos( i, j ); + if( pItem && pItem->GetEntry() == item ) + { + tempcount += pItem->GetCount(); + if( tempcount >= count ) + return EQUIP_ERR_OK; + } + } + } + } + } + + // not found req. item count and have unequippable items + return res; +} + +uint32 Player::GetItemCount( uint32 item, bool inBankAlso, Item* skipItem ) const +{ + uint32 count = 0; + for(int i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; i++) + { + Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pItem && pItem != skipItem && pItem->GetEntry() == item ) + count += pItem->GetCount(); + } + for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++) + { + Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pItem && pItem != skipItem && pItem->GetEntry() == item ) + count += pItem->GetCount(); + } + for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) + { + Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pBag ) + count += pBag->GetItemCount(item,skipItem); + } + + if(skipItem && skipItem->GetProto()->GemProperties) + { + for(int i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; i++) + { + Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pItem && pItem != skipItem && pItem->GetProto()->Socket[0].Color ) + count += pItem->GetGemCountWithID(item); + } + } + + if(inBankAlso) + { + for(int i = BANK_SLOT_ITEM_START; i < BANK_SLOT_ITEM_END; i++) + { + Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pItem && pItem != skipItem && pItem->GetEntry() == item ) + count += pItem->GetCount(); + } + for(int i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; i++) + { + Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pBag ) + count += pBag->GetItemCount(item,skipItem); + } + + if(skipItem && skipItem->GetProto()->GemProperties) + { + for(int i = BANK_SLOT_ITEM_START; i < BANK_SLOT_ITEM_END; i++) + { + Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pItem && pItem != skipItem && pItem->GetProto()->Socket[0].Color ) + count += pItem->GetGemCountWithID(item); + } + } + } + + return count; +} + +Item* Player::GetItemByGuid( uint64 guid ) const +{ + for(int i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; i++) + { + Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pItem && pItem->GetGUID() == guid ) + return pItem; + } + for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++) + { + Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pItem && pItem->GetGUID() == guid ) + return pItem; + } + + for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) + { + Bag *pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pBag ) + { + ItemPrototype const *pBagProto = pBag->GetProto(); + if( pBagProto ) + { + for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + { + Item* pItem = pBag->GetItemByPos( j ); + if( pItem && pItem->GetGUID() == guid ) + return pItem; + } + } + } + } + for(int i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; i++) + { + Bag *pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pBag ) + { + ItemPrototype const *pBagProto = pBag->GetProto(); + if( pBagProto ) + { + for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + { + Item* pItem = pBag->GetItemByPos( j ); + if( pItem && pItem->GetGUID() == guid ) + return pItem; + } + } + } + } + + return NULL; +} + +Item* Player::GetItemByPos( uint16 pos ) const +{ + uint8 bag = pos >> 8; + uint8 slot = pos & 255; + return GetItemByPos( bag, slot ); +} + +Item* Player::GetItemByPos( uint8 bag, uint8 slot ) const +{ + if( bag == INVENTORY_SLOT_BAG_0 && ( slot < BANK_SLOT_BAG_END || slot >= KEYRING_SLOT_START && slot < KEYRING_SLOT_END ) ) + return m_items[slot]; + else if(bag >= INVENTORY_SLOT_BAG_START && bag < INVENTORY_SLOT_BAG_END + || bag >= BANK_SLOT_BAG_START && bag < BANK_SLOT_BAG_END ) + { + Bag *pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, bag ); + if ( pBag ) + return pBag->GetItemByPos(slot); + } + return NULL; +} + +Item* Player::GetWeaponForAttack(WeaponAttackType attackType, bool useable) const +{ + uint16 slot; + switch (attackType) + { + case BASE_ATTACK: slot = EQUIPMENT_SLOT_MAINHAND; break; + case OFF_ATTACK: slot = EQUIPMENT_SLOT_OFFHAND; break; + case RANGED_ATTACK: slot = EQUIPMENT_SLOT_RANGED; break; + default: return NULL; + } + + Item* item = GetItemByPos(INVENTORY_SLOT_BAG_0, slot); + if (!item || item->GetProto()->Class != ITEM_CLASS_WEAPON) + return NULL; + + if(!useable) + return item; + + if( item->IsBroken() || !IsUseEquipedWeapon(attackType==BASE_ATTACK) ) + return NULL; + + return item; +} + +Item* Player::GetShield(bool useable) const +{ + Item* item = GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); + if (!item || item->GetProto()->Class != ITEM_CLASS_ARMOR) + return NULL; + + if(!useable) + return item; + + if( item->IsBroken()) + return NULL; + + return item; +} + +uint32 Player::GetAttackBySlot( uint8 slot ) +{ + switch(slot) + { + case EQUIPMENT_SLOT_MAINHAND: return BASE_ATTACK; + case EQUIPMENT_SLOT_OFFHAND: return OFF_ATTACK; + case EQUIPMENT_SLOT_RANGED: return RANGED_ATTACK; + default: return MAX_ATTACK; + } +} + +bool Player::HasBankBagSlot( uint8 slot ) const +{ + uint32 maxslot = GetByteValue(PLAYER_BYTES_2, 2) + BANK_SLOT_BAG_START; + if( slot < maxslot ) + return true; + return false; +} + +bool Player::IsInventoryPos( uint8 bag, uint8 slot ) +{ + if( bag == INVENTORY_SLOT_BAG_0 && slot == NULL_SLOT ) + return true; + if( bag == INVENTORY_SLOT_BAG_0 && ( slot >= INVENTORY_SLOT_ITEM_START && slot < INVENTORY_SLOT_ITEM_END ) ) + return true; + if( bag >= INVENTORY_SLOT_BAG_START && bag < INVENTORY_SLOT_BAG_END ) + return true; + if( bag == INVENTORY_SLOT_BAG_0 && ( slot >= KEYRING_SLOT_START && slot < KEYRING_SLOT_END ) ) + return true; + return false; +} + +bool Player::IsEquipmentPos( uint8 bag, uint8 slot ) +{ + if( bag == INVENTORY_SLOT_BAG_0 && ( slot < EQUIPMENT_SLOT_END ) ) + return true; + if( bag == INVENTORY_SLOT_BAG_0 && ( slot >= INVENTORY_SLOT_BAG_START && slot < INVENTORY_SLOT_BAG_END ) ) + return true; + return false; +} + +bool Player::IsBankPos( uint8 bag, uint8 slot ) +{ + if( bag == INVENTORY_SLOT_BAG_0 && ( slot >= BANK_SLOT_ITEM_START && slot < BANK_SLOT_ITEM_END ) ) + return true; + if( bag == INVENTORY_SLOT_BAG_0 && ( slot >= BANK_SLOT_BAG_START && slot < BANK_SLOT_BAG_END ) ) + return true; + if( bag >= BANK_SLOT_BAG_START && bag < BANK_SLOT_BAG_END ) + return true; + return false; +} + +bool Player::IsBagPos( uint16 pos ) +{ + uint8 bag = pos >> 8; + uint8 slot = pos & 255; + if( bag == INVENTORY_SLOT_BAG_0 && ( slot >= INVENTORY_SLOT_BAG_START && slot < INVENTORY_SLOT_BAG_END ) ) + return true; + if( bag == INVENTORY_SLOT_BAG_0 && ( slot >= BANK_SLOT_BAG_START && slot < BANK_SLOT_BAG_END ) ) + return true; + return false; +} + +bool Player::HasItemCount( uint32 item, uint32 count, bool inBankAlso ) const +{ + uint32 tempcount = 0; + for(int i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; i++) + { + Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pItem && pItem->GetEntry() == item ) + { + tempcount += pItem->GetCount(); + if( tempcount >= count ) + return true; + } + } + for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++) + { + Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pItem && pItem->GetEntry() == item ) + { + tempcount += pItem->GetCount(); + if( tempcount >= count ) + return true; + } + } + for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) + { + if(Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i )) + { + if(ItemPrototype const *pBagProto = pBag->GetProto()) + { + for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + { + Item* pItem = GetItemByPos( i, j ); + if( pItem && pItem->GetEntry() == item ) + { + tempcount += pItem->GetCount(); + if( tempcount >= count ) + return true; + } + } + } + } + } + + if(inBankAlso) + { + for(int i = BANK_SLOT_ITEM_START; i < BANK_SLOT_ITEM_END; i++) + { + Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pItem && pItem->GetEntry() == item ) + { + tempcount += pItem->GetCount(); + if( tempcount >= count ) + return true; + } + } + for(int i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; i++) + { + if(Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i )) + { + if(ItemPrototype const *pBagProto = pBag->GetProto()) + { + for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + { + Item* pItem = GetItemByPos( i, j ); + if( pItem && pItem->GetEntry() == item ) + { + tempcount += pItem->GetCount(); + if( tempcount >= count ) + return true; + } + } + } + } + } + } + + return false; +} + +Item* Player::GetItemOrItemWithGemEquipped( uint32 item ) const +{ + Item *pItem; + for(int i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; i++) + { + pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pItem && pItem->GetEntry() == item ) + return pItem; + } + + ItemPrototype const *pProto = objmgr.GetItemPrototype(item); + if (pProto && pProto->GemProperties) + { + for(int i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; i++) + { + pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pItem && pItem->GetProto()->Socket[0].Color ) + { + if (pItem->GetGemCountWithID(item) > 0 ) + return pItem; + } + } + } + + return NULL; +} + +uint8 Player::_CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item* pItem, uint32* no_space_count ) const +{ + ItemPrototype const *pProto = objmgr.GetItemPrototype(entry); + if( !pProto ) + { + if(no_space_count) + *no_space_count = count; + return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; + } + + // no maximum + if(pProto->MaxCount == 0) + return EQUIP_ERR_OK; + + uint32 curcount = GetItemCount(pProto->ItemId,true,pItem); + + if( curcount + count > pProto->MaxCount ) + { + if(no_space_count) + *no_space_count = count +curcount - pProto->MaxCount; + return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; + } + + return EQUIP_ERR_OK; +} + +bool Player::HasItemTotemCategory( uint32 TotemCategory ) const +{ + Item *pItem; + for(uint8 i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; ++i) + { + pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pItem && IsTotemCategoryCompatiableWith(pItem->GetProto()->TotemCategory,TotemCategory )) + return true; + } + for(uint8 i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; ++i) + { + pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pItem && IsTotemCategoryCompatiableWith(pItem->GetProto()->TotemCategory,TotemCategory )) + return true; + } + Bag *pBag; + ItemPrototype const *pBagProto; + for(uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i) + { + pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pBag ) + { + pBagProto = pBag->GetProto(); + if( pBagProto ) + { + for(uint32 j = 0; j < pBagProto->ContainerSlots; ++j) + { + pItem = GetItemByPos( i, j ); + if( pItem && IsTotemCategoryCompatiableWith(pItem->GetProto()->TotemCategory,TotemCategory )) + return true; + } + } + } + } + return false; +} + +uint8 Player::_CanStoreItem_InSpecificSlot( uint8 bag, uint8 slot, ItemPosCountVec &dest, ItemPrototype const *pProto, uint32& count, bool swap, Item* pSrcItem ) const +{ + Item* pItem2 = GetItemByPos( bag, slot ); + + // ignore move item (this slot will be empty at move) + if(pItem2==pSrcItem) + pItem2 = NULL; + + uint32 need_space; + + // empty specific slot - check item fit to slot + if( !pItem2 || swap ) + { + if( bag == INVENTORY_SLOT_BAG_0 ) + { + // keyring case + if(slot >= KEYRING_SLOT_START && slot < KEYRING_SLOT_START+GetMaxKeyringSize() && !(pProto->BagFamily & BAG_FAMILY_MASK_KEYS)) + return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG; + + // prevent cheating + if(slot >= BUYBACK_SLOT_START && slot < BUYBACK_SLOT_END || slot >= PLAYER_SLOT_END) + return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG; + } + else + { + Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, bag ); + if( !pBag ) + return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG; + + ItemPrototype const* pBagProto = pBag->GetProto(); + if( !pBagProto ) + return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG; + + if( !ItemCanGoIntoBag(pProto,pBagProto) ) + return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG; + } + + // non empty stack with space + need_space = pProto->Stackable; + } + // non empty slot, check item type + else + { + // check item type + if(pItem2->GetEntry() != pProto->ItemId) + return EQUIP_ERR_ITEM_CANT_STACK; + + // check free space + if(pItem2->GetCount() >= pProto->Stackable) + return EQUIP_ERR_ITEM_CANT_STACK; + + need_space = pProto->Stackable - pItem2->GetCount(); + } + + if(need_space > count) + need_space = count; + + ItemPosCount newPosition = ItemPosCount((bag << 8) | slot, need_space); + if(!newPosition.isContainedIn(dest)) + { + dest.push_back(newPosition); + count -= need_space; + } + return EQUIP_ERR_OK; +} + +uint8 Player::_CanStoreItem_InBag( uint8 bag, ItemPosCountVec &dest, ItemPrototype const *pProto, uint32& count, bool merge, bool non_specialized, Item* pSrcItem, uint8 skip_bag, uint8 skip_slot ) const +{ + // skip specific bag already processed in first called _CanStoreItem_InBag + if(bag==skip_bag) + return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG; + + Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, bag ); + if( !pBag ) + return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG; + + ItemPrototype const* pBagProto = pBag->GetProto(); + if( !pBagProto ) + return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG; + + // specialized bag mode or non-specilized + if( non_specialized != (pBagProto->Class == ITEM_CLASS_CONTAINER && pBagProto->SubClass == ITEM_SUBCLASS_CONTAINER) ) + return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG; + + if( !ItemCanGoIntoBag(pProto,pBagProto) ) + return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG; + + for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + { + // skip specific slot already processed in first called _CanStoreItem_InSpecificSlot + if(j==skip_slot) + continue; + + Item* pItem2 = GetItemByPos( bag, j ); + + // ignore move item (this slot will be empty at move) + if(pItem2==pSrcItem) + pItem2 = NULL; + + // if merge skip empty, if !merge skip non-empty + if((pItem2!=NULL)!=merge) + continue; + + if( pItem2 ) + { + if(pItem2->GetEntry() == pProto->ItemId && pItem2->GetCount() < pProto->Stackable ) + { + uint32 need_space = pProto->Stackable - pItem2->GetCount(); + if(need_space > count) + need_space = count; + + ItemPosCount newPosition = ItemPosCount((bag << 8) | j, need_space); + if(!newPosition.isContainedIn(dest)) + { + dest.push_back(newPosition); + count -= need_space; + + if(count==0) + return EQUIP_ERR_OK; + } + } + } + else + { + uint32 need_space = pProto->Stackable; + if(need_space > count) + need_space = count; + + ItemPosCount newPosition = ItemPosCount((bag << 8) | j, need_space); + if(!newPosition.isContainedIn(dest)) + { + dest.push_back(newPosition); + count -= need_space; + + if(count==0) + return EQUIP_ERR_OK; + } + } + } + return EQUIP_ERR_OK; +} + +uint8 Player::_CanStoreItem_InInventorySlots( uint8 slot_begin, uint8 slot_end, ItemPosCountVec &dest, ItemPrototype const *pProto, uint32& count, bool merge, Item* pSrcItem, uint8 skip_bag, uint8 skip_slot ) const +{ + for(uint32 j = slot_begin; j < slot_end; j++) + { + // skip specific slot already processed in first called _CanStoreItem_InSpecificSlot + if(INVENTORY_SLOT_BAG_0==skip_bag && j==skip_slot) + continue; + + Item* pItem2 = GetItemByPos( INVENTORY_SLOT_BAG_0, j ); + + // ignore move item (this slot will be empty at move) + if(pItem2==pSrcItem) + pItem2 = NULL; + + // if merge skip empty, if !merge skip non-empty + if((pItem2!=NULL)!=merge) + continue; + + if( pItem2 ) + { + if(pItem2->GetEntry() == pProto->ItemId && pItem2->GetCount() < pProto->Stackable ) + { + uint32 need_space = pProto->Stackable - pItem2->GetCount(); + if(need_space > count) + need_space = count; + ItemPosCount newPosition = ItemPosCount((INVENTORY_SLOT_BAG_0 << 8) | j, need_space); + if(!newPosition.isContainedIn(dest)) + { + dest.push_back(newPosition); + count -= need_space; + + if(count==0) + return EQUIP_ERR_OK; + } + } + } + else + { + uint32 need_space = pProto->Stackable; + if(need_space > count) + need_space = count; + + ItemPosCount newPosition = ItemPosCount((INVENTORY_SLOT_BAG_0 << 8) | j, need_space); + if(!newPosition.isContainedIn(dest)) + { + dest.push_back(newPosition); + count -= need_space; + + if(count==0) + return EQUIP_ERR_OK; + } + } + } + return EQUIP_ERR_OK; +} + +uint8 Player::_CanStoreItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, uint32 entry, uint32 count, Item *pItem, bool swap, uint32* no_space_count ) const +{ + sLog.outDebug( "STORAGE: CanStoreItem bag = %u, slot = %u, item = %u, count = %u", bag, slot, entry, count); + + ItemPrototype const *pProto = objmgr.GetItemPrototype(entry); + if( !pProto ) + { + if(no_space_count) + *no_space_count = count; + return swap ? EQUIP_ERR_ITEMS_CANT_BE_SWAPPED :EQUIP_ERR_ITEM_NOT_FOUND; + } + + if(pItem && pItem->IsBindedNotWith(GetGUID())) + { + if(no_space_count) + *no_space_count = count; + return EQUIP_ERR_DONT_OWN_THAT_ITEM; + } + + // check count of items (skip for auto move for same player from bank) + uint32 no_similar_count = 0; // can't store this amount similar items + uint8 res = _CanTakeMoreSimilarItems(entry,count,pItem,&no_similar_count); + if(res!=EQUIP_ERR_OK) + { + if(count==no_similar_count) + { + if(no_space_count) + *no_space_count = no_similar_count; + return res; + } + count -= no_similar_count; + } + + // in specific slot + if( bag != NULL_BAG && slot != NULL_SLOT ) + { + res = _CanStoreItem_InSpecificSlot(bag,slot,dest,pProto,count,swap,pItem); + if(res!=EQUIP_ERR_OK) + { + if(no_space_count) + *no_space_count = count + no_similar_count; + return res; + } + + if(count==0) + { + if(no_similar_count==0) + return EQUIP_ERR_OK; + + if(no_space_count) + *no_space_count = count + no_similar_count; + return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; + } + } + + // not specific slot or have spece for partly store only in specific slot + + // in specific bag + if( bag != NULL_BAG ) + { + // search stack in bag for merge to + if( pProto->Stackable > 1 ) + { + if( bag == INVENTORY_SLOT_BAG_0 ) // inventory + { + res = _CanStoreItem_InInventorySlots(KEYRING_SLOT_START,KEYRING_SLOT_END,dest,pProto,count,true,pItem,bag,slot); + if(res!=EQUIP_ERR_OK) + { + if(no_space_count) + *no_space_count = count + no_similar_count; + return res; + } + + if(count==0) + { + if(no_similar_count==0) + return EQUIP_ERR_OK; + + if(no_space_count) + *no_space_count = count + no_similar_count; + return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; + } + + res = _CanStoreItem_InInventorySlots(INVENTORY_SLOT_ITEM_START,INVENTORY_SLOT_ITEM_END,dest,pProto,count,true,pItem,bag,slot); + if(res!=EQUIP_ERR_OK) + { + if(no_space_count) + *no_space_count = count + no_similar_count; + return res; + } + + if(count==0) + { + if(no_similar_count==0) + return EQUIP_ERR_OK; + + if(no_space_count) + *no_space_count = count + no_similar_count; + return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; + } + } + else // equipped bag + { + // we need check 2 time (specilized/non_specialized), use NULL_BAG to prevent skipping bag + res = _CanStoreItem_InBag(bag,dest,pProto,count,true,false,pItem,NULL_BAG,slot); + if(res!=EQUIP_ERR_OK) + res = _CanStoreItem_InBag(bag,dest,pProto,count,true,true,pItem,NULL_BAG,slot); + + if(res!=EQUIP_ERR_OK) + { + if(no_space_count) + *no_space_count = count + no_similar_count; + return res; + } + + if(count==0) + { + if(no_similar_count==0) + return EQUIP_ERR_OK; + + if(no_space_count) + *no_space_count = count + no_similar_count; + return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; + } + } + } + + // search free slot in bag for place to + if( bag == INVENTORY_SLOT_BAG_0 ) // inventory + { + // search free slot - keyring case + if(pProto->BagFamily & BAG_FAMILY_MASK_KEYS) + { + uint32 keyringSize = GetMaxKeyringSize(); + res = _CanStoreItem_InInventorySlots(KEYRING_SLOT_START,KEYRING_SLOT_START+keyringSize,dest,pProto,count,false,pItem,bag,slot); + if(res!=EQUIP_ERR_OK) + { + if(no_space_count) + *no_space_count = count + no_similar_count; + return res; + } + + if(count==0) + { + if(no_similar_count==0) + return EQUIP_ERR_OK; + + if(no_space_count) + *no_space_count = count + no_similar_count; + return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; + } + } + + res = _CanStoreItem_InInventorySlots(INVENTORY_SLOT_ITEM_START,INVENTORY_SLOT_ITEM_END,dest,pProto,count,false,pItem,bag,slot); + if(res!=EQUIP_ERR_OK) + { + if(no_space_count) + *no_space_count = count + no_similar_count; + return res; + } + + if(count==0) + { + if(no_similar_count==0) + return EQUIP_ERR_OK; + + if(no_space_count) + *no_space_count = count + no_similar_count; + return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; + } + } + else // equipped bag + { + res = _CanStoreItem_InBag(bag,dest,pProto,count,false,false,pItem,NULL_BAG,slot); + if(res!=EQUIP_ERR_OK) + res = _CanStoreItem_InBag(bag,dest,pProto,count,false,true,pItem,NULL_BAG,slot); + + if(res!=EQUIP_ERR_OK) + { + if(no_space_count) + *no_space_count = count + no_similar_count; + return res; + } + + if(count==0) + { + if(no_similar_count==0) + return EQUIP_ERR_OK; + + if(no_space_count) + *no_space_count = count + no_similar_count; + return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; + } + } + } + + // not specific bag or have space for partly store only in specific bag + + // search stack for merge to + if( pProto->Stackable > 1 ) + { + res = _CanStoreItem_InInventorySlots(KEYRING_SLOT_START,KEYRING_SLOT_END,dest,pProto,count,true,pItem,bag,slot); + if(res!=EQUIP_ERR_OK) + { + if(no_space_count) + *no_space_count = count + no_similar_count; + return res; + } + + if(count==0) + { + if(no_similar_count==0) + return EQUIP_ERR_OK; + + if(no_space_count) + *no_space_count = count + no_similar_count; + return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; + } + + res = _CanStoreItem_InInventorySlots(INVENTORY_SLOT_ITEM_START,INVENTORY_SLOT_ITEM_END,dest,pProto,count,true,pItem,bag,slot); + if(res!=EQUIP_ERR_OK) + { + if(no_space_count) + *no_space_count = count + no_similar_count; + return res; + } + + if(count==0) + { + if(no_similar_count==0) + return EQUIP_ERR_OK; + + if(no_space_count) + *no_space_count = count + no_similar_count; + return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; + } + + if( pProto->BagFamily ) + { + for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) + { + res = _CanStoreItem_InBag(i,dest,pProto,count,true,false,pItem,bag,slot); + if(res!=EQUIP_ERR_OK) + continue; + + if(count==0) + { + if(no_similar_count==0) + return EQUIP_ERR_OK; + + if(no_space_count) + *no_space_count = count + no_similar_count; + return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; + } + } + } + + for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) + { + res = _CanStoreItem_InBag(i,dest,pProto,count,true,true,pItem,bag,slot); + if(res!=EQUIP_ERR_OK) + continue; + + if(count==0) + { + if(no_similar_count==0) + return EQUIP_ERR_OK; + + if(no_space_count) + *no_space_count = count + no_similar_count; + return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; + } + } + } + + // search free slot - special bag case + if( pProto->BagFamily ) + { + if(pProto->BagFamily & BAG_FAMILY_MASK_KEYS) + { + uint32 keyringSize = GetMaxKeyringSize(); + res = _CanStoreItem_InInventorySlots(KEYRING_SLOT_START,KEYRING_SLOT_START+keyringSize,dest,pProto,count,false,pItem,bag,slot); + if(res!=EQUIP_ERR_OK) + { + if(no_space_count) + *no_space_count = count + no_similar_count; + return res; + } + + if(count==0) + { + if(no_similar_count==0) + return EQUIP_ERR_OK; + + if(no_space_count) + *no_space_count = count + no_similar_count; + return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; + } + } + + for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) + { + res = _CanStoreItem_InBag(i,dest,pProto,count,false,false,pItem,bag,slot); + if(res!=EQUIP_ERR_OK) + continue; + + if(count==0) + { + if(no_similar_count==0) + return EQUIP_ERR_OK; + + if(no_space_count) + *no_space_count = count + no_similar_count; + return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; + } + } + } + + // search free slot + res = _CanStoreItem_InInventorySlots(INVENTORY_SLOT_ITEM_START,INVENTORY_SLOT_ITEM_END,dest,pProto,count,false,pItem,bag,slot); + if(res!=EQUIP_ERR_OK) + { + if(no_space_count) + *no_space_count = count + no_similar_count; + return res; + } + + if(count==0) + { + if(no_similar_count==0) + return EQUIP_ERR_OK; + + if(no_space_count) + *no_space_count = count + no_similar_count; + return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; + } + + for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) + { + res = _CanStoreItem_InBag(i,dest,pProto,count,false,true,pItem,bag,slot); + if(res!=EQUIP_ERR_OK) + continue; + + if(count==0) + { + if(no_similar_count==0) + return EQUIP_ERR_OK; + + if(no_space_count) + *no_space_count = count + no_similar_count; + return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; + } + } + + if(no_space_count) + *no_space_count = count + no_similar_count; + + return EQUIP_ERR_INVENTORY_FULL; +} + +////////////////////////////////////////////////////////////////////////// +uint8 Player::CanStoreItems( Item **pItems,int count) const +{ + Item *pItem2; + + // fill space table + int inv_slot_items[INVENTORY_SLOT_ITEM_END-INVENTORY_SLOT_ITEM_START]; + int inv_bags[INVENTORY_SLOT_BAG_END-INVENTORY_SLOT_BAG_START][MAX_BAG_SIZE]; + int inv_keys[KEYRING_SLOT_END-KEYRING_SLOT_START]; + + memset(inv_slot_items,0,sizeof(int)*(INVENTORY_SLOT_ITEM_END-INVENTORY_SLOT_ITEM_START)); + memset(inv_bags,0,sizeof(int)*(INVENTORY_SLOT_BAG_END-INVENTORY_SLOT_BAG_START)*MAX_BAG_SIZE); + memset(inv_keys,0,sizeof(int)*(KEYRING_SLOT_END-KEYRING_SLOT_START)); + + for(int i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++) + { + pItem2 = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + + if (pItem2 && !pItem2->IsInTrade()) + { + inv_slot_items[i-INVENTORY_SLOT_ITEM_START] = pItem2->GetCount(); + } + } + + for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++) + { + pItem2 = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + + if (pItem2 && !pItem2->IsInTrade()) + { + inv_keys[i-KEYRING_SLOT_START] = pItem2->GetCount(); + } + } + + for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) + { + Bag *pBag; + ItemPrototype const *pBagProto; + + pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pBag ) + { + pBagProto = pBag->GetProto(); + + if( pBagProto ) + { + for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + { + pItem2 = GetItemByPos( i, j ); + if (pItem2 && !pItem2->IsInTrade()) + { + inv_bags[i-INVENTORY_SLOT_BAG_START][j] = pItem2->GetCount(); + } + } + } + } + } + + // check free space for all items + for (int k=0;kGetEntry(), pItem->GetCount()); + ItemPrototype const *pProto = pItem->GetProto(); + + // strange item + if( !pProto ) + return EQUIP_ERR_ITEM_NOT_FOUND; + + // item it 'bind' + if(pItem->IsBindedNotWith(GetGUID())) + return EQUIP_ERR_DONT_OWN_THAT_ITEM; + + Bag *pBag; + ItemPrototype const *pBagProto; + + // item is 'one item only' + uint8 res = CanTakeMoreSimilarItems(pItem); + if(res != EQUIP_ERR_OK) + return res; + + // search stack for merge to + if( pProto->Stackable > 1 ) + { + bool b_found = false; + + for(int t = KEYRING_SLOT_START; t < KEYRING_SLOT_END; t++) + { + pItem2 = GetItemByPos( INVENTORY_SLOT_BAG_0, t ); + if( pItem2 && pItem2->GetEntry() == pItem->GetEntry() && inv_keys[t-KEYRING_SLOT_START] + pItem->GetCount() <= pProto->Stackable ) + { + inv_keys[t-KEYRING_SLOT_START] += pItem->GetCount(); + b_found = true; + break; + } + } + if (b_found) continue; + + for(int t = INVENTORY_SLOT_ITEM_START; t < INVENTORY_SLOT_ITEM_END; t++) + { + pItem2 = GetItemByPos( INVENTORY_SLOT_BAG_0, t ); + if( pItem2 && pItem2->GetEntry() == pItem->GetEntry() && inv_slot_items[t-INVENTORY_SLOT_ITEM_START] + pItem->GetCount() <= pProto->Stackable ) + { + inv_slot_items[t-INVENTORY_SLOT_ITEM_START] += pItem->GetCount(); + b_found = true; + break; + } + } + if (b_found) continue; + + for(int t = INVENTORY_SLOT_BAG_START; !b_found && t < INVENTORY_SLOT_BAG_END; t++) + { + pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, t ); + if( pBag ) + { + pBagProto = pBag->GetProto(); + if( pBagProto ) + { + for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + { + pItem2 = GetItemByPos( t, j ); + if( pItem2 && pItem2->GetEntry() == pItem->GetEntry() && inv_bags[t-INVENTORY_SLOT_BAG_START][j] + pItem->GetCount() <= pProto->Stackable ) + { + inv_bags[t-INVENTORY_SLOT_BAG_START][j] += pItem->GetCount(); + b_found = true; + break; + } + } + } + } + } + if (b_found) continue; + } + + // special bag case + if( pProto->BagFamily ) + { + bool b_found = false; + if(pProto->BagFamily & BAG_FAMILY_MASK_KEYS) + { + uint32 keyringSize = GetMaxKeyringSize(); + for(uint32 t = KEYRING_SLOT_START; t < KEYRING_SLOT_START+keyringSize; ++t) + { + if( inv_keys[t-KEYRING_SLOT_START] == 0 ) + { + inv_keys[t-KEYRING_SLOT_START] = 1; + b_found = true; + break; + } + } + } + + if (b_found) continue; + + for(int t = INVENTORY_SLOT_BAG_START; !b_found && t < INVENTORY_SLOT_BAG_END; t++) + { + pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, t ); + if( pBag ) + { + pBagProto = pBag->GetProto(); + + // not plain container check + if( pBagProto && (pBagProto->Class != ITEM_CLASS_CONTAINER || pBagProto->SubClass != ITEM_SUBCLASS_CONTAINER) && + ItemCanGoIntoBag(pProto,pBagProto) ) + { + for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + { + if( inv_bags[t-INVENTORY_SLOT_BAG_START][j] == 0 ) + { + inv_bags[t-INVENTORY_SLOT_BAG_START][j] = 1; + b_found = true; + break; + } + } + } + } + } + if (b_found) continue; + } + + // search free slot + bool b_found = false; + for(int t = INVENTORY_SLOT_ITEM_START; t < INVENTORY_SLOT_ITEM_END; t++) + { + if( inv_slot_items[t-INVENTORY_SLOT_ITEM_START] == 0 ) + { + inv_slot_items[t-INVENTORY_SLOT_ITEM_START] = 1; + b_found = true; + break; + } + } + if (b_found) continue; + + // search free slot in bags + for(int t = INVENTORY_SLOT_BAG_START; !b_found && t < INVENTORY_SLOT_BAG_END; t++) + { + pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, t ); + if( pBag ) + { + pBagProto = pBag->GetProto(); + if( pBagProto && ItemCanGoIntoBag(pProto,pBagProto)) + { + for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + { + if( inv_bags[t-INVENTORY_SLOT_BAG_START][j] == 0 ) + { + inv_bags[t-INVENTORY_SLOT_BAG_START][j] = 1; + b_found = true; + break; + } + } + } + } + } + + // no free slot found? + if (!b_found) + return EQUIP_ERR_INVENTORY_FULL; + } + + return EQUIP_ERR_OK; +} + +////////////////////////////////////////////////////////////////////////// +uint8 Player::CanEquipNewItem( uint8 slot, uint16 &dest, uint32 item, uint32 count, bool swap ) const +{ + dest = 0; + Item *pItem = Item::CreateItem( item, count, this ); + if( pItem ) + { + uint8 result = CanEquipItem(slot, dest, pItem, swap ); + delete pItem; + return result; + } + + return EQUIP_ERR_ITEM_NOT_FOUND; +} + +uint8 Player::CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, bool swap, bool not_loading ) const +{ + dest = 0; + if( pItem ) + { + sLog.outDebug( "STORAGE: CanEquipItem slot = %u, item = %u, count = %u", slot, pItem->GetEntry(), pItem->GetCount()); + ItemPrototype const *pProto = pItem->GetProto(); + if( pProto ) + { + if(pItem->IsBindedNotWith(GetGUID())) + return EQUIP_ERR_DONT_OWN_THAT_ITEM; + + // check count of items (skip for auto move for same player from bank) + uint8 res = CanTakeMoreSimilarItems(pItem); + if(res != EQUIP_ERR_OK) + return res; + + // do not allow equipping gear except weapons, offhands, projectiles, relics in + // - combat + // - in-progress arenas + if( !pProto->CanChangeEquipStateInCombat() ) + { + if( isInCombat() ) + return EQUIP_ERR_NOT_IN_COMBAT; + + if(BattleGround* bg = GetBattleGround()) + if( bg->isArena() && bg->GetStatus() == STATUS_IN_PROGRESS ) + return EQUIP_ERR_NOT_DURING_ARENA_MATCH; + } + + if(isInCombat()&& pProto->Class == ITEM_CLASS_WEAPON && m_weaponChangeTimer != 0) + return EQUIP_ERR_CANT_DO_RIGHT_NOW; // maybe exist better err + + uint8 eslot = FindEquipSlot( pProto, slot, swap ); + if( eslot == NULL_SLOT ) + return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED; + + uint8 msg = CanUseItem( pItem , not_loading ); + if( msg != EQUIP_ERR_OK ) + return msg; + if( !swap && GetItemByPos( INVENTORY_SLOT_BAG_0, eslot ) ) + return EQUIP_ERR_NO_EQUIPMENT_SLOT_AVAILABLE; + + // check unique-equipped on item + if (pProto->Flags & ITEM_FLAGS_UNIQUE_EQUIPPED) + { + // there is an equip limit on this item + Item* tItem = GetItemOrItemWithGemEquipped(pProto->ItemId); + if (tItem && (!swap || tItem->GetSlot() != eslot ) ) + return EQUIP_ERR_ITEM_UNIQUE_EQUIPABLE; + } + + // check unique-equipped on gems + for(uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+3; ++enchant_slot) + { + uint32 enchant_id = pItem->GetEnchantmentId(EnchantmentSlot(enchant_slot)); + if(!enchant_id) + continue; + SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id); + if(!enchantEntry) + continue; + + ItemPrototype const* pGem = objmgr.GetItemPrototype(enchantEntry->GemID); + if(pGem && (pGem->Flags & ITEM_FLAGS_UNIQUE_EQUIPPED)) + { + Item* tItem = GetItemOrItemWithGemEquipped(enchantEntry->GemID); + if(tItem && (!swap || tItem->GetSlot() != eslot )) + return EQUIP_ERR_ITEM_UNIQUE_EQUIPABLE; + } + } + + // check unique-equipped special item classes + if (pProto->Class == ITEM_CLASS_QUIVER) + { + for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i) + { + if( Item* pBag = GetItemByPos( INVENTORY_SLOT_BAG_0, i ) ) + { + if( ItemPrototype const* pBagProto = pBag->GetProto() ) + { + if( pBagProto->Class==pProto->Class && pBagProto->SubClass==pProto->SubClass && + (!swap || pBag->GetSlot() != eslot ) ) + { + if(pBagProto->SubClass == ITEM_SUBCLASS_AMMO_POUCH) + return EQUIP_ERR_CAN_EQUIP_ONLY1_AMMOPOUCH; + else + return EQUIP_ERR_CAN_EQUIP_ONLY1_QUIVER; + } + } + } + } + } + + uint32 type = pProto->InventoryType; + + if(eslot == EQUIPMENT_SLOT_OFFHAND) + { + if( type == INVTYPE_WEAPON || type == INVTYPE_WEAPONOFFHAND ) + { + if(!CanDualWield()) + return EQUIP_ERR_CANT_DUAL_WIELD; + } + + Item *mainItem = GetItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND ); + if(mainItem) + { + if(mainItem->GetProto()->InventoryType == INVTYPE_2HWEAPON) + return EQUIP_ERR_CANT_EQUIP_WITH_TWOHANDED; + } + } + + // equip two-hand weapon case (with possible unequip 2 items) + if( type == INVTYPE_2HWEAPON ) + { + if(eslot != EQUIPMENT_SLOT_MAINHAND) + return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED; + + // offhand item must can be stored in inventitory for offhand item and it also must be unequipped + Item *offItem = GetItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND ); + ItemPosCountVec off_dest; + if( offItem && (!not_loading || + CanUnequipItem(uint16(INVENTORY_SLOT_BAG_0) << 8 | EQUIPMENT_SLOT_OFFHAND,false) != EQUIP_ERR_OK || + CanStoreItem( NULL_BAG, NULL_SLOT, off_dest, offItem, false ) != EQUIP_ERR_OK ) ) + return swap ? EQUIP_ERR_ITEMS_CANT_BE_SWAPPED : EQUIP_ERR_INVENTORY_FULL; + } + dest = ((INVENTORY_SLOT_BAG_0 << 8) | eslot); + return EQUIP_ERR_OK; + } + } + if( !swap ) + return EQUIP_ERR_ITEM_NOT_FOUND; + else + return EQUIP_ERR_ITEMS_CANT_BE_SWAPPED; +} + +uint8 Player::CanUnequipItem( uint16 pos, bool swap ) const +{ + // Applied only to equipped items and bank bags + if(!IsEquipmentPos(pos) && !IsBagPos(pos)) + return EQUIP_ERR_OK; + + Item* pItem = GetItemByPos(pos); + + // Applied only to existed equipped item + if( !pItem ) + return EQUIP_ERR_OK; + + sLog.outDebug( "STORAGE: CanUnequipItem slot = %u, item = %u, count = %u", pos, pItem->GetEntry(), pItem->GetCount()); + + ItemPrototype const *pProto = pItem->GetProto(); + if( !pProto ) + return EQUIP_ERR_ITEM_NOT_FOUND; + + // do not allow unequipping gear except weapons, offhands, projectiles, relics in + // - combat + // - in-progress arenas + if( !pProto->CanChangeEquipStateInCombat() ) + { + if( isInCombat() ) + return EQUIP_ERR_NOT_IN_COMBAT; + + if(BattleGround* bg = GetBattleGround()) + if( bg->isArena() && bg->GetStatus() == STATUS_IN_PROGRESS ) + return EQUIP_ERR_NOT_DURING_ARENA_MATCH; + } + + if(!swap && pItem->IsBag() && !((Bag*)pItem)->IsEmpty()) + return EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS; + + return EQUIP_ERR_OK; +} + +uint8 Player::CanBankItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, Item *pItem, bool swap, bool not_loading ) const +{ + if( !pItem ) + return swap ? EQUIP_ERR_ITEMS_CANT_BE_SWAPPED : EQUIP_ERR_ITEM_NOT_FOUND; + + uint32 count = pItem->GetCount(); + + sLog.outDebug( "STORAGE: CanBankItem bag = %u, slot = %u, item = %u, count = %u", bag, slot, pItem->GetEntry(), pItem->GetCount()); + ItemPrototype const *pProto = pItem->GetProto(); + if( !pProto ) + return swap ? EQUIP_ERR_ITEMS_CANT_BE_SWAPPED : EQUIP_ERR_ITEM_NOT_FOUND; + + if( pItem->IsBindedNotWith(GetGUID()) ) + return EQUIP_ERR_DONT_OWN_THAT_ITEM; + + // check count of items (skip for auto move for same player from bank) + uint8 res = CanTakeMoreSimilarItems(pItem); + if(res != EQUIP_ERR_OK) + return res; + + // in specific slot + if( bag != NULL_BAG && slot != NULL_SLOT ) + { + if( pProto->InventoryType == INVTYPE_BAG ) + { + Bag *pBag = (Bag*)pItem; + if( pBag ) + { + if( slot >= BANK_SLOT_BAG_START && slot < BANK_SLOT_BAG_END ) + { + if( !HasBankBagSlot( slot ) ) + return EQUIP_ERR_MUST_PURCHASE_THAT_BAG_SLOT; + if( uint8 cantuse = CanUseItem( pItem, not_loading ) != EQUIP_ERR_OK ) + return cantuse; + } + else + { + if( !pBag->IsEmpty() ) + return EQUIP_ERR_NONEMPTY_BAG_OVER_OTHER_BAG; + } + } + } + else + { + if( slot >= BANK_SLOT_BAG_START && slot < BANK_SLOT_BAG_END ) + return EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT; + } + + res = _CanStoreItem_InSpecificSlot(bag,slot,dest,pProto,count,swap,pItem); + if(res!=EQUIP_ERR_OK) + return res; + + if(count==0) + return EQUIP_ERR_OK; + } + + // not specific slot or have spece for partly store only in specific slot + + // in specific bag + if( bag != NULL_BAG ) + { + if( pProto->InventoryType == INVTYPE_BAG ) + { + Bag *pBag = (Bag*)pItem; + if( pBag && !pBag->IsEmpty() ) + return EQUIP_ERR_NONEMPTY_BAG_OVER_OTHER_BAG; + } + + // search stack in bag for merge to + if( pProto->Stackable > 1 ) + { + if( bag == INVENTORY_SLOT_BAG_0 ) + { + res = _CanStoreItem_InInventorySlots(BANK_SLOT_ITEM_START,BANK_SLOT_ITEM_END,dest,pProto,count,true,pItem,bag,slot); + if(res!=EQUIP_ERR_OK) + return res; + + if(count==0) + return EQUIP_ERR_OK; + } + else + { + res = _CanStoreItem_InBag(bag,dest,pProto,count,true,false,pItem,NULL_BAG,slot); + if(res!=EQUIP_ERR_OK) + res = _CanStoreItem_InBag(bag,dest,pProto,count,true,true,pItem,NULL_BAG,slot); + + if(res!=EQUIP_ERR_OK) + return res; + + if(count==0) + return EQUIP_ERR_OK; + } + } + + // search free slot in bag + if( bag == INVENTORY_SLOT_BAG_0 ) + { + res = _CanStoreItem_InInventorySlots(BANK_SLOT_ITEM_START,BANK_SLOT_ITEM_END,dest,pProto,count,false,pItem,bag,slot); + if(res!=EQUIP_ERR_OK) + return res; + + if(count==0) + return EQUIP_ERR_OK; + } + else + { + res = _CanStoreItem_InBag(bag,dest,pProto,count,false,false,pItem,NULL_BAG,slot); + if(res!=EQUIP_ERR_OK) + res = _CanStoreItem_InBag(bag,dest,pProto,count,false,true,pItem,NULL_BAG,slot); + + if(res!=EQUIP_ERR_OK) + return res; + + if(count==0) + return EQUIP_ERR_OK; + } + } + + // not specific bag or have spece for partly store only in specific bag + + // search stack for merge to + if( pProto->Stackable > 1 ) + { + // in slots + res = _CanStoreItem_InInventorySlots(BANK_SLOT_ITEM_START,BANK_SLOT_ITEM_END,dest,pProto,count,true,pItem,bag,slot); + if(res!=EQUIP_ERR_OK) + return res; + + if(count==0) + return EQUIP_ERR_OK; + + // in special bags + if( pProto->BagFamily ) + { + for(int i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; i++) + { + res = _CanStoreItem_InBag(i,dest,pProto,count,true,false,pItem,bag,slot); + if(res!=EQUIP_ERR_OK) + continue; + + if(count==0) + return EQUIP_ERR_OK; + } + } + + for(int i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; i++) + { + res = _CanStoreItem_InBag(i,dest,pProto,count,true,true,pItem,bag,slot); + if(res!=EQUIP_ERR_OK) + continue; + + if(count==0) + return EQUIP_ERR_OK; + } + } + + // search free place in special bag + if( pProto->BagFamily ) + { + for(int i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; i++) + { + res = _CanStoreItem_InBag(i,dest,pProto,count,false,false,pItem,bag,slot); + if(res!=EQUIP_ERR_OK) + continue; + + if(count==0) + return EQUIP_ERR_OK; + } + } + + // search free space + res = _CanStoreItem_InInventorySlots(BANK_SLOT_ITEM_START,BANK_SLOT_ITEM_END,dest,pProto,count,false,pItem,bag,slot); + if(res!=EQUIP_ERR_OK) + return res; + + if(count==0) + return EQUIP_ERR_OK; + + for(int i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; i++) + { + res = _CanStoreItem_InBag(i,dest,pProto,count,false,true,pItem,bag,slot); + if(res!=EQUIP_ERR_OK) + continue; + + if(count==0) + return EQUIP_ERR_OK; + } + return EQUIP_ERR_BANK_FULL; +} + +uint8 Player::CanUseItem( Item *pItem, bool not_loading ) const +{ + if( pItem ) + { + sLog.outDebug( "STORAGE: CanUseItem item = %u", pItem->GetEntry()); + if( !isAlive() && not_loading ) + return EQUIP_ERR_YOU_ARE_DEAD; + //if( isStunned() ) + // return EQUIP_ERR_YOU_ARE_STUNNED; + ItemPrototype const *pProto = pItem->GetProto(); + if( pProto ) + { + if( pItem->IsBindedNotWith(GetGUID()) ) + return EQUIP_ERR_DONT_OWN_THAT_ITEM; + if( (pProto->AllowableClass & getClassMask()) == 0 || (pProto->AllowableRace & getRaceMask()) == 0 ) + return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM; + if( pItem->GetSkill() != 0 ) + { + if( GetSkillValue( pItem->GetSkill() ) == 0 ) + return EQUIP_ERR_NO_REQUIRED_PROFICIENCY; + } + if( pProto->RequiredSkill != 0 ) + { + if( GetSkillValue( pProto->RequiredSkill ) == 0 ) + return EQUIP_ERR_NO_REQUIRED_PROFICIENCY; + else if( GetSkillValue( pProto->RequiredSkill ) < pProto->RequiredSkillRank ) + return EQUIP_ERR_ERR_CANT_EQUIP_SKILL; + } + if( pProto->RequiredSpell != 0 && !HasSpell( pProto->RequiredSpell ) ) + return EQUIP_ERR_NO_REQUIRED_PROFICIENCY; + if( pProto->RequiredReputationFaction && uint32(GetReputationRank(pProto->RequiredReputationFaction)) < pProto->RequiredReputationRank ) + return EQUIP_ERR_CANT_EQUIP_REPUTATION; + if( getLevel() < pProto->RequiredLevel ) + return EQUIP_ERR_CANT_EQUIP_LEVEL_I; + return EQUIP_ERR_OK; + } + } + return EQUIP_ERR_ITEM_NOT_FOUND; +} + +bool Player::CanUseItem( ItemPrototype const *pProto ) +{ + // Used by group, function NeedBeforeGreed, to know if a prototype can be used by a player + + if( pProto ) + { + if( (pProto->AllowableClass & getClassMask()) == 0 || (pProto->AllowableRace & getRaceMask()) == 0 ) + return false; + if( pProto->RequiredSkill != 0 ) + { + if( GetSkillValue( pProto->RequiredSkill ) == 0 ) + return false; + else if( GetSkillValue( pProto->RequiredSkill ) < pProto->RequiredSkillRank ) + return false; + } + if( pProto->RequiredSpell != 0 && !HasSpell( pProto->RequiredSpell ) ) + return false; + if( getLevel() < pProto->RequiredLevel ) + return false; + return true; + } + return false; +} + +uint8 Player::CanUseAmmo( uint32 item ) const +{ + sLog.outDebug( "STORAGE: CanUseAmmo item = %u", item); + if( !isAlive() ) + return EQUIP_ERR_YOU_ARE_DEAD; + //if( isStunned() ) + // return EQUIP_ERR_YOU_ARE_STUNNED; + ItemPrototype const *pProto = objmgr.GetItemPrototype( item ); + if( pProto ) + { + if( pProto->InventoryType!= INVTYPE_AMMO ) + return EQUIP_ERR_ONLY_AMMO_CAN_GO_HERE; + if( (pProto->AllowableClass & getClassMask()) == 0 || (pProto->AllowableRace & getRaceMask()) == 0 ) + return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM; + if( pProto->RequiredSkill != 0 ) + { + if( GetSkillValue( pProto->RequiredSkill ) == 0 ) + return EQUIP_ERR_NO_REQUIRED_PROFICIENCY; + else if( GetSkillValue( pProto->RequiredSkill ) < pProto->RequiredSkillRank ) + return EQUIP_ERR_ERR_CANT_EQUIP_SKILL; + } + if( pProto->RequiredSpell != 0 && !HasSpell( pProto->RequiredSpell ) ) + return EQUIP_ERR_NO_REQUIRED_PROFICIENCY; + /*if( GetReputation() < pProto->RequiredReputation ) + return EQUIP_ERR_CANT_EQUIP_REPUTATION; + */ + if( getLevel() < pProto->RequiredLevel ) + return EQUIP_ERR_CANT_EQUIP_LEVEL_I; + + // Requires No Ammo + if(GetDummyAura(46699)) + return EQUIP_ERR_BAG_FULL6; + + return EQUIP_ERR_OK; + } + return EQUIP_ERR_ITEM_NOT_FOUND; +} + +void Player::SetAmmo( uint32 item ) +{ + if(!item) + return; + + // already set + if( GetUInt32Value(PLAYER_AMMO_ID) == item ) + return; + + // check ammo + if(item) + { + uint8 msg = CanUseAmmo( item ); + if( msg != EQUIP_ERR_OK ) + { + SendEquipError( msg, NULL, NULL ); + return; + } + } + + SetUInt32Value(PLAYER_AMMO_ID, item); + + _ApplyAmmoBonuses(); +} + +void Player::RemoveAmmo() +{ + SetUInt32Value(PLAYER_AMMO_ID, 0); + + m_ammoDPS = 0.0f; + + if(CanModifyStats()) + UpdateDamagePhysical(RANGED_ATTACK); +} + +// Return stored item (if stored to stack, it can diff. from pItem). And pItem ca be deleted in this case. +Item* Player::StoreNewItem( ItemPosCountVec const& dest, uint32 item, bool update,int32 randomPropertyId ) +{ + uint32 count = 0; + for(ItemPosCountVec::const_iterator itr = dest.begin(); itr != dest.end(); ++itr) + count += itr->count; + + Item *pItem = Item::CreateItem( item, count, this ); + if( pItem ) + { + ItemAddedQuestCheck( item, count ); + if(randomPropertyId) + pItem->SetItemRandomProperties(randomPropertyId); + pItem = StoreItem( dest, pItem, update ); + } + return pItem; +} + +Item* Player::StoreItem( ItemPosCountVec const& dest, Item* pItem, bool update ) +{ + if( !pItem ) + return NULL; + + Item* lastItem = pItem; + + for(ItemPosCountVec::const_iterator itr = dest.begin(); itr != dest.end(); ) + { + uint16 pos = itr->pos; + uint32 count = itr->count; + + ++itr; + + if(itr == dest.end()) + { + lastItem = _StoreItem(pos,pItem,count,false,update); + break; + } + + lastItem = _StoreItem(pos,pItem,count,true,update); + } + + return lastItem; +} + +// Return stored item (if stored to stack, it can diff. from pItem). And pItem ca be deleted in this case. +Item* Player::_StoreItem( uint16 pos, Item *pItem, uint32 count, bool clone, bool update ) +{ + if( !pItem ) + return NULL; + + uint8 bag = pos >> 8; + uint8 slot = pos & 255; + + sLog.outDebug( "STORAGE: StoreItem bag = %u, slot = %u, item = %u, count = %u", bag, slot, pItem->GetEntry(), count); + + Item *pItem2 = GetItemByPos( bag, slot ); + + if( !pItem2 ) + { + if(clone) + pItem = pItem->CloneItem(count,this); + else + pItem->SetCount(count); + + if(!pItem) + return NULL; + + if( pItem->GetProto()->Bonding == BIND_WHEN_PICKED_UP || + pItem->GetProto()->Bonding == BIND_QUEST_ITEM || + pItem->GetProto()->Bonding == BIND_WHEN_EQUIPED && IsBagPos(pos) ) + pItem->SetBinding( true ); + + if( bag == INVENTORY_SLOT_BAG_0 ) + { + m_items[slot] = pItem; + SetUInt64Value( (uint16)(PLAYER_FIELD_INV_SLOT_HEAD + (slot * 2) ), pItem->GetGUID() ); + pItem->SetUInt64Value( ITEM_FIELD_CONTAINED, GetGUID() ); + pItem->SetUInt64Value( ITEM_FIELD_OWNER, GetGUID() ); + + pItem->SetSlot( slot ); + pItem->SetContainer( NULL ); + + if( IsInWorld() && update ) + { + pItem->AddToWorld(); + pItem->SendUpdateToPlayer( this ); + } + + pItem->SetState(ITEM_CHANGED, this); + } + else + { + Bag *pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, bag ); + if( pBag ) + { + pBag->StoreItem( slot, pItem, update ); + if( IsInWorld() && update ) + { + pItem->AddToWorld(); + pItem->SendUpdateToPlayer( this ); + } + pItem->SetState(ITEM_CHANGED, this); + pBag->SetState(ITEM_CHANGED, this); + } + } + + AddEnchantmentDurations(pItem); + AddItemDurations(pItem); + + return pItem; + } + else + { + if( pItem2->GetProto()->Bonding == BIND_WHEN_PICKED_UP || + pItem2->GetProto()->Bonding == BIND_QUEST_ITEM || + pItem2->GetProto()->Bonding == BIND_WHEN_EQUIPED && IsBagPos(pos) ) + pItem2->SetBinding( true ); + + pItem2->SetCount( pItem2->GetCount() + count ); + if( IsInWorld() && update ) + pItem2->SendUpdateToPlayer( this ); + + if(!clone) + { + // delete item (it not in any slot currently) + if( IsInWorld() && update ) + { + pItem->RemoveFromWorld(); + pItem->DestroyForPlayer( this ); + } + + RemoveEnchantmentDurations(pItem); + RemoveItemDurations(pItem); + + pItem->SetOwnerGUID(GetGUID()); // prevent error at next SetState in case trade/mail/buy from vendor + pItem->SetState(ITEM_REMOVED, this); + } + // AddItemDurations(pItem2); - pItem2 already have duration listed for player + AddEnchantmentDurations(pItem2); + + pItem2->SetState(ITEM_CHANGED, this); + + return pItem2; + } +} + +Item* Player::EquipNewItem( uint16 pos, uint32 item, uint32 count, bool update ) +{ + Item *pItem = Item::CreateItem( item, count, this ); + if( pItem ) + { + ItemAddedQuestCheck( item, count ); + Item * retItem = EquipItem( pos, pItem, update ); + + return retItem; + } + return NULL; +} + +Item* Player::EquipItem( uint16 pos, Item *pItem, bool update ) +{ + if( pItem ) + { + AddEnchantmentDurations(pItem); + AddItemDurations(pItem); + + uint8 bag = pos >> 8; + uint8 slot = pos & 255; + + Item *pItem2 = GetItemByPos( bag, slot ); + + if( !pItem2 ) + { + VisualizeItem( slot, pItem); + + if(isAlive()) + { + ItemPrototype const *pProto = pItem->GetProto(); + + // item set bonuses applied only at equip and removed at unequip, and still active for broken items + if(pProto && pProto->ItemSet) + AddItemsSetItem(this,pItem); + + _ApplyItemMods(pItem, slot, true); + + if(pProto && isInCombat()&& pProto->Class == ITEM_CLASS_WEAPON && m_weaponChangeTimer == 0) + { + m_weaponChangeTimer = DEFAULT_SWITCH_WEAPON; + if (getClass() == CLASS_ROGUE) + m_weaponChangeTimer = ROGUE_SWITCH_WEAPON; + } + } + + if( IsInWorld() && update ) + { + pItem->AddToWorld(); + pItem->SendUpdateToPlayer( this ); + } + + ApplyEquipCooldown(pItem); + + if( slot == EQUIPMENT_SLOT_MAINHAND ) + UpdateExpertise(BASE_ATTACK); + else if( slot == EQUIPMENT_SLOT_OFFHAND ) + UpdateExpertise(OFF_ATTACK); + } + else + { + pItem2->SetCount( pItem2->GetCount() + pItem->GetCount() ); + if( IsInWorld() && update ) + pItem2->SendUpdateToPlayer( this ); + + // delete item (it not in any slot currently) + //pItem->DeleteFromDB(); + if( IsInWorld() && update ) + { + pItem->RemoveFromWorld(); + pItem->DestroyForPlayer( this ); + } + + RemoveEnchantmentDurations(pItem); + RemoveItemDurations(pItem); + + pItem->SetOwnerGUID(GetGUID()); // prevent error at next SetState in case trade/mail/buy from vendor + pItem->SetState(ITEM_REMOVED, this); + pItem2->SetState(ITEM_CHANGED, this); + + ApplyEquipCooldown(pItem2); + + return pItem2; + } + } + + return pItem; +} + +void Player::QuickEquipItem( uint16 pos, Item *pItem) +{ + if( pItem ) + { + AddEnchantmentDurations(pItem); + AddItemDurations(pItem); + + uint8 slot = pos & 255; + VisualizeItem( slot, pItem); + + if( IsInWorld() ) + { + pItem->AddToWorld(); + pItem->SendUpdateToPlayer( this ); + } + } +} + +void Player::SetVisibleItemSlot(uint8 slot, Item *pItem) +{ + // PLAYER_VISIBLE_ITEM_i_CREATOR // Size: 2 + // PLAYER_VISIBLE_ITEM_i_0 // Size: 12 + // entry // Size: 1 + // inspected enchantments // Size: 6 + // ? // Size: 5 + // PLAYER_VISIBLE_ITEM_i_PROPERTIES // Size: 1 (property,suffix factor) + // PLAYER_VISIBLE_ITEM_i_PAD // Size: 1 + // // = 16 + + if(pItem) + { + SetUInt64Value(PLAYER_VISIBLE_ITEM_1_CREATOR + (slot * MAX_VISIBLE_ITEM_OFFSET), pItem->GetUInt64Value(ITEM_FIELD_CREATOR)); + + int VisibleBase = PLAYER_VISIBLE_ITEM_1_0 + (slot * MAX_VISIBLE_ITEM_OFFSET); + SetUInt32Value(VisibleBase + 0, pItem->GetEntry()); + + for(int i = 0; i < MAX_INSPECTED_ENCHANTMENT_SLOT; ++i) + SetUInt32Value(VisibleBase + 1 + i, pItem->GetEnchantmentId(EnchantmentSlot(i))); + + // Use SetInt16Value to prevent set high part to FFFF for negative value + SetInt16Value( PLAYER_VISIBLE_ITEM_1_PROPERTIES + (slot * MAX_VISIBLE_ITEM_OFFSET), 0, pItem->GetItemRandomPropertyId()); + SetUInt32Value(PLAYER_VISIBLE_ITEM_1_PROPERTIES + 1 + (slot * MAX_VISIBLE_ITEM_OFFSET), pItem->GetItemSuffixFactor()); + } + else + { + SetUInt64Value(PLAYER_VISIBLE_ITEM_1_CREATOR + (slot * MAX_VISIBLE_ITEM_OFFSET), 0); + + int VisibleBase = PLAYER_VISIBLE_ITEM_1_0 + (slot * MAX_VISIBLE_ITEM_OFFSET); + SetUInt32Value(VisibleBase + 0, 0); + + for(int i = 0; i < MAX_INSPECTED_ENCHANTMENT_SLOT; ++i) + SetUInt32Value(VisibleBase + 1 + i, 0); + + SetUInt32Value(PLAYER_VISIBLE_ITEM_1_PROPERTIES + 0 + (slot * MAX_VISIBLE_ITEM_OFFSET), 0); + SetUInt32Value(PLAYER_VISIBLE_ITEM_1_PROPERTIES + 1 + (slot * MAX_VISIBLE_ITEM_OFFSET), 0); + } +} + +void Player::VisualizeItem( uint8 slot, Item *pItem) +{ + if(!pItem) + return; + + // check also BIND_WHEN_PICKED_UP and BIND_QUEST_ITEM for .additem or .additemset case by GM (not binded at adding to inventory) + if( pItem->GetProto()->Bonding == BIND_WHEN_EQUIPED || pItem->GetProto()->Bonding == BIND_WHEN_PICKED_UP || pItem->GetProto()->Bonding == BIND_QUEST_ITEM ) + pItem->SetBinding( true ); + + sLog.outDebug( "STORAGE: EquipItem slot = %u, item = %u", slot, pItem->GetEntry()); + + m_items[slot] = pItem; + SetUInt64Value( (uint16)(PLAYER_FIELD_INV_SLOT_HEAD + (slot * 2) ), pItem->GetGUID() ); + pItem->SetUInt64Value( ITEM_FIELD_CONTAINED, GetGUID() ); + pItem->SetUInt64Value( ITEM_FIELD_OWNER, GetGUID() ); + pItem->SetSlot( slot ); + pItem->SetContainer( NULL ); + + if( slot < EQUIPMENT_SLOT_END ) + SetVisibleItemSlot(slot,pItem); + + pItem->SetState(ITEM_CHANGED, this); +} + +void Player::RemoveItem( uint8 bag, uint8 slot, bool update ) +{ + // note: removeitem does not actually change the item + // it only takes the item out of storage temporarily + // note2: if removeitem is to be used for delinking + // the item must be removed from the player's updatequeue + + Item *pItem = GetItemByPos( bag, slot ); + if( pItem ) + { + sLog.outDebug( "STORAGE: RemoveItem bag = %u, slot = %u, item = %u", bag, slot, pItem->GetEntry()); + + RemoveEnchantmentDurations(pItem); + RemoveItemDurations(pItem); + + if( bag == INVENTORY_SLOT_BAG_0 ) + { + if ( slot < INVENTORY_SLOT_BAG_END ) + { + ItemPrototype const *pProto = pItem->GetProto(); + // item set bonuses applied only at equip and removed at unequip, and still active for broken items + + if(pProto && pProto->ItemSet) + RemoveItemsSetItem(this,pProto); + + _ApplyItemMods(pItem, slot, false); + + // remove item dependent auras and casts (only weapon and armor slots) + if(slot < EQUIPMENT_SLOT_END) + RemoveItemDependentAurasAndCasts(pItem); + + // remove held enchantments + if ( slot == EQUIPMENT_SLOT_MAINHAND ) + { + if (pItem->GetItemSuffixFactor()) + { + pItem->ClearEnchantment(PROP_ENCHANTMENT_SLOT_3); + pItem->ClearEnchantment(PROP_ENCHANTMENT_SLOT_4); + } + else + { + pItem->ClearEnchantment(PROP_ENCHANTMENT_SLOT_0); + pItem->ClearEnchantment(PROP_ENCHANTMENT_SLOT_1); + } + } + } + + m_items[slot] = NULL; + SetUInt64Value((uint16)(PLAYER_FIELD_INV_SLOT_HEAD + (slot*2)), 0); + + if ( slot < EQUIPMENT_SLOT_END ) + SetVisibleItemSlot(slot,NULL); + } + else + { + Bag *pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, bag ); + if( pBag ) + pBag->RemoveItem(slot, update); + } + pItem->SetUInt64Value( ITEM_FIELD_CONTAINED, 0 ); + // pItem->SetUInt64Value( ITEM_FIELD_OWNER, 0 ); not clear owner at remove (it will be set at store). This used in mail and auction code + pItem->SetSlot( NULL_SLOT ); + if( IsInWorld() && update ) + pItem->SendUpdateToPlayer( this ); + + if( slot == EQUIPMENT_SLOT_MAINHAND ) + UpdateExpertise(BASE_ATTACK); + else if( slot == EQUIPMENT_SLOT_OFFHAND ) + UpdateExpertise(OFF_ATTACK); + } +} + +// Common operation need to remove item from inventory without delete in trade, auction, guild bank, mail.... +void Player::MoveItemFromInventory(uint8 bag, uint8 slot, bool update) +{ + if(Item* it = GetItemByPos(bag,slot)) + { + ItemRemovedQuestCheck(it->GetEntry(),it->GetCount()); + RemoveItem( bag,slot,update); + it->RemoveFromUpdateQueueOf(this); + if(it->IsInWorld()) + { + it->RemoveFromWorld(); + it->DestroyForPlayer( this ); + } + } +} + +// Common operation need to add item from inventory without delete in trade, guild bank, mail.... +void Player::MoveItemToInventory(ItemPosCountVec const& dest, Item* pItem, bool update, bool in_characterInventoryDB) +{ + // update quest counters + ItemAddedQuestCheck(pItem->GetEntry(),pItem->GetCount()); + + // store item + Item* pLastItem = StoreItem( dest, pItem, update); + + // only set if not merged to existed stack (pItem can be deleted already but we can compare pointers any way) + if(pLastItem==pItem) + { + // update owner for last item (this can be original item with wrong owner + if(pLastItem->GetOwnerGUID() != GetGUID()) + pLastItem->SetOwnerGUID(GetGUID()); + + // if this original item then it need create record in inventory + // in case trade we laready have item in other player inventory + pLastItem->SetState(in_characterInventoryDB ? ITEM_CHANGED : ITEM_NEW, this); + } +} + +void Player::DestroyItem( uint8 bag, uint8 slot, bool update ) +{ + Item *pItem = GetItemByPos( bag, slot ); + if( pItem ) + { + sLog.outDebug( "STORAGE: DestroyItem bag = %u, slot = %u, item = %u", bag, slot, pItem->GetEntry()); + + // start from destroy contained items (only equipped bag can have its) + if (pItem->IsBag() && pItem->IsEquipped()) // this also prevent infinity loop if empty bag stored in bag==slot + { + for (int i = 0; i < MAX_BAG_SIZE; i++) + DestroyItem(slot,i,update); + } + + if(pItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED)) + CharacterDatabase.PExecute("DELETE FROM character_gifts WHERE item_guid = '%u'", pItem->GetGUIDLow()); + + ItemPrototype const *pProto = pItem->GetProto(); + + RemoveEnchantmentDurations(pItem); + RemoveItemDurations(pItem); + + ItemRemovedQuestCheck( pItem->GetEntry(), pItem->GetCount() ); + + if( bag == INVENTORY_SLOT_BAG_0 ) + { + + SetUInt64Value((uint16)(PLAYER_FIELD_INV_SLOT_HEAD + (slot*2)), 0); + + // equipment and equipped bags can have applied bonuses + if ( slot < INVENTORY_SLOT_BAG_END ) + { + ItemPrototype const *pProto = pItem->GetProto(); + + // item set bonuses applied only at equip and removed at unequip, and still active for broken items + if(pProto && pProto->ItemSet) + RemoveItemsSetItem(this,pProto); + + _ApplyItemMods(pItem, slot, false); + } + + if ( slot < EQUIPMENT_SLOT_END ) + { + // remove item dependent auras and casts (only weapon and armor slots) + RemoveItemDependentAurasAndCasts(pItem); + + // equipment visual show + SetVisibleItemSlot(slot,NULL); + } + + m_items[slot] = NULL; + } + else if(Bag *pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, bag )) + pBag->RemoveItem(slot, update); + + if( IsInWorld() && update ) + { + pItem->RemoveFromWorld(); + pItem->DestroyForPlayer(this); + } + + //pItem->SetOwnerGUID(0); + pItem->SetUInt64Value( ITEM_FIELD_CONTAINED, 0 ); + pItem->SetSlot( NULL_SLOT ); + pItem->SetState(ITEM_REMOVED, this); + } +} + +void Player::DestroyItemCount( uint32 item, uint32 count, bool update, bool unequip_check) +{ + sLog.outDebug( "STORAGE: DestroyItemCount item = %u, count = %u", item, count); + Item *pItem; + ItemPrototype const *pProto; + uint32 remcount = 0; + + // in inventory + for(int i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++) + { + pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pItem && pItem->GetEntry() == item ) + { + if( pItem->GetCount() + remcount <= count ) + { + // all items in inventory can unequipped + remcount += pItem->GetCount(); + DestroyItem( INVENTORY_SLOT_BAG_0, i, update); + + if(remcount >=count) + return; + } + else + { + pProto = pItem->GetProto(); + ItemRemovedQuestCheck( pItem->GetEntry(), count - remcount ); + pItem->SetCount( pItem->GetCount() - count + remcount ); + if( IsInWorld() & update ) + pItem->SendUpdateToPlayer( this ); + pItem->SetState(ITEM_CHANGED, this); + return; + } + } + } + for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++) + { + pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pItem && pItem->GetEntry() == item ) + { + if( pItem->GetCount() + remcount <= count ) + { + // all keys can be unequipped + remcount += pItem->GetCount(); + DestroyItem( INVENTORY_SLOT_BAG_0, i, update); + + if(remcount >=count) + return; + } + else + { + pProto = pItem->GetProto(); + ItemRemovedQuestCheck( pItem->GetEntry(), count - remcount ); + pItem->SetCount( pItem->GetCount() - count + remcount ); + if( IsInWorld() & update ) + pItem->SendUpdateToPlayer( this ); + pItem->SetState(ITEM_CHANGED, this); + return; + } + } + } + + // in inventory bags + Bag *pBag; + ItemPrototype const *pBagProto; + for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) + { + pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pBag ) + { + pBagProto = pBag->GetProto(); + if( pBagProto ) + { + for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + { + pItem = pBag->GetItemByPos(j); + if( pItem && pItem->GetEntry() == item ) + { + // all items in bags can be unequipped + if( pItem->GetCount() + remcount <= count ) + { + remcount += pItem->GetCount(); + DestroyItem( i, j, update ); + + if(remcount >=count) + return; + } + else + { + pProto = pItem->GetProto(); + ItemRemovedQuestCheck( pItem->GetEntry(), count - remcount ); + pItem->SetCount( pItem->GetCount() - count + remcount ); + if( IsInWorld() && update ) + pItem->SendUpdateToPlayer( this ); + pItem->SetState(ITEM_CHANGED, this); + return; + } + } + } + } + } + } + + // in equipment and bag list + for(int i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_BAG_END; i++) + { + pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pItem && pItem->GetEntry() == item ) + { + if( pItem->GetCount() + remcount <= count ) + { + if(!unequip_check || CanUnequipItem(INVENTORY_SLOT_BAG_0 << 8 | i,false) == EQUIP_ERR_OK ) + { + remcount += pItem->GetCount(); + DestroyItem( INVENTORY_SLOT_BAG_0, i, update); + + if(remcount >=count) + return; + } + } + else + { + pProto = pItem->GetProto(); + ItemRemovedQuestCheck( pItem->GetEntry(), count - remcount ); + pItem->SetCount( pItem->GetCount() - count + remcount ); + if( IsInWorld() & update ) + pItem->SendUpdateToPlayer( this ); + pItem->SetState(ITEM_CHANGED, this); + return; + } + } + } +} + +void Player::DestroyZoneLimitedItem( bool update, uint32 new_zone ) +{ + sLog.outDebug( "STORAGE: DestroyZoneLimitedItem in map %u and area %u", GetMapId(), new_zone ); + + // in inventory + for(int i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++) + { + Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pItem && pItem->IsLimitedToAnotherMapOrZone(GetMapId(),new_zone) ) + DestroyItem( INVENTORY_SLOT_BAG_0, i, update); + } + for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++) + { + Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pItem && pItem->IsLimitedToAnotherMapOrZone(GetMapId(),new_zone) ) + DestroyItem( INVENTORY_SLOT_BAG_0, i, update); + } + + // in inventory bags + for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) + { + Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pBag ) + { + ItemPrototype const *pBagProto = pBag->GetProto(); + if( pBagProto ) + { + for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + { + Item* pItem = pBag->GetItemByPos(j); + if( pItem && pItem->IsLimitedToAnotherMapOrZone(GetMapId(),new_zone) ) + DestroyItem( i, j, update); + } + } + } + } + + // in equipment and bag list + for(int i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_BAG_END; i++) + { + Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pItem && pItem->IsLimitedToAnotherMapOrZone(GetMapId(),new_zone) ) + DestroyItem( INVENTORY_SLOT_BAG_0, i, update); + } +} + +void Player::DestroyConjuredItems( bool update ) +{ + // used when entering arena + // distroys all conjured items + sLog.outDebug( "STORAGE: DestroyConjuredItems" ); + + // in inventory + for(int i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++) + { + Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pItem && pItem->GetProto() && + (pItem->GetProto()->Class == ITEM_CLASS_CONSUMABLE) && + (pItem->GetProto()->Flags & ITEM_FLAGS_CONJURED) ) + DestroyItem( INVENTORY_SLOT_BAG_0, i, update); + } + + // in inventory bags + for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) + { + Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pBag ) + { + ItemPrototype const *pBagProto = pBag->GetProto(); + if( pBagProto ) + { + for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + { + Item* pItem = pBag->GetItemByPos(j); + if( pItem && pItem->GetProto() && + (pItem->GetProto()->Class == ITEM_CLASS_CONSUMABLE) && + (pItem->GetProto()->Flags & ITEM_FLAGS_CONJURED) ) + DestroyItem( i, j, update); + } + } + } + } + + // in equipment and bag list + for(int i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_BAG_END; i++) + { + Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pItem && pItem->GetProto() && + (pItem->GetProto()->Class == ITEM_CLASS_CONSUMABLE) && + (pItem->GetProto()->Flags & ITEM_FLAGS_CONJURED) ) + DestroyItem( INVENTORY_SLOT_BAG_0, i, update); + } +} + +void Player::DestroyItemCount( Item* pItem, uint32 &count, bool update ) +{ + if(!pItem) + return; + + sLog.outDebug( "STORAGE: DestroyItemCount item (GUID: %u, Entry: %u) count = %u", pItem->GetGUIDLow(),pItem->GetEntry(), count); + + if( pItem->GetCount() <= count ) + { + count-= pItem->GetCount(); + + DestroyItem( pItem->GetBagSlot(),pItem->GetSlot(), update); + } + else + { + ItemRemovedQuestCheck( pItem->GetEntry(), count); + pItem->SetCount( pItem->GetCount() - count ); + count = 0; + if( IsInWorld() & update ) + pItem->SendUpdateToPlayer( this ); + pItem->SetState(ITEM_CHANGED, this); + } +} + +void Player::SplitItem( uint16 src, uint16 dst, uint32 count ) +{ + uint8 srcbag = src >> 8; + uint8 srcslot = src & 255; + + uint8 dstbag = dst >> 8; + uint8 dstslot = dst & 255; + + Item *pSrcItem = GetItemByPos( srcbag, srcslot ); + if( !pSrcItem ) + { + SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, pSrcItem, NULL ); + return; + } + + // not let split all items (can be only at cheating) + if(pSrcItem->GetCount() == count) + { + SendEquipError( EQUIP_ERR_COULDNT_SPLIT_ITEMS, pSrcItem, NULL ); + return; + } + + // not let split more existed items (can be only at cheating) + if(pSrcItem->GetCount() < count) + { + SendEquipError( EQUIP_ERR_TRIED_TO_SPLIT_MORE_THAN_COUNT, pSrcItem, NULL ); + return; + } + + if(pSrcItem->m_lootGenerated) // prevent split looting item (item + { + //best error message found for attempting to split while looting + SendEquipError( EQUIP_ERR_COULDNT_SPLIT_ITEMS, pSrcItem, NULL ); + return; + } + + sLog.outDebug( "STORAGE: SplitItem bag = %u, slot = %u, item = %u, count = %u", dstbag, dstslot, pSrcItem->GetEntry(), count); + Item *pNewItem = pSrcItem->CloneItem( count, this ); + if( !pNewItem ) + { + SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, pSrcItem, NULL ); + return; + } + + if( IsInventoryPos( dst ) ) + { + // change item amount before check (for unique max count check) + pSrcItem->SetCount( pSrcItem->GetCount() - count ); + + ItemPosCountVec dest; + uint8 msg = CanStoreItem( dstbag, dstslot, dest, pNewItem, false ); + if( msg != EQUIP_ERR_OK ) + { + delete pNewItem; + pSrcItem->SetCount( pSrcItem->GetCount() + count ); + SendEquipError( msg, pSrcItem, NULL ); + return; + } + + if( IsInWorld() ) + pSrcItem->SendUpdateToPlayer( this ); + pSrcItem->SetState(ITEM_CHANGED, this); + StoreItem( dest, pNewItem, true); + } + else if( IsBankPos ( dst ) ) + { + // change item amount before check (for unique max count check) + pSrcItem->SetCount( pSrcItem->GetCount() - count ); + + ItemPosCountVec dest; + uint8 msg = CanBankItem( dstbag, dstslot, dest, pNewItem, false ); + if( msg != EQUIP_ERR_OK ) + { + delete pNewItem; + pSrcItem->SetCount( pSrcItem->GetCount() + count ); + SendEquipError( msg, pSrcItem, NULL ); + return; + } + + if( IsInWorld() ) + pSrcItem->SendUpdateToPlayer( this ); + pSrcItem->SetState(ITEM_CHANGED, this); + BankItem( dest, pNewItem, true); + } + else if( IsEquipmentPos ( dst ) ) + { + // change item amount before check (for unique max count check), provide space for splitted items + pSrcItem->SetCount( pSrcItem->GetCount() - count ); + + uint16 dest; + uint8 msg = CanEquipItem( dstslot, dest, pNewItem, false ); + if( msg != EQUIP_ERR_OK ) + { + delete pNewItem; + pSrcItem->SetCount( pSrcItem->GetCount() + count ); + SendEquipError( msg, pSrcItem, NULL ); + return; + } + + if( IsInWorld() ) + pSrcItem->SendUpdateToPlayer( this ); + pSrcItem->SetState(ITEM_CHANGED, this); + EquipItem( dest, pNewItem, true); + AutoUnequipOffhandIfNeed(); + } +} + +void Player::SwapItem( uint16 src, uint16 dst ) +{ + uint8 srcbag = src >> 8; + uint8 srcslot = src & 255; + + uint8 dstbag = dst >> 8; + uint8 dstslot = dst & 255; + + Item *pSrcItem = GetItemByPos( srcbag, srcslot ); + Item *pDstItem = GetItemByPos( dstbag, dstslot ); + + if( !pSrcItem ) + return; + + sLog.outDebug( "STORAGE: SwapItem bag = %u, slot = %u, item = %u", dstbag, dstslot, pSrcItem->GetEntry()); + + if(!isAlive() ) + { + SendEquipError( EQUIP_ERR_YOU_ARE_DEAD, pSrcItem, pDstItem ); + return; + } + + if(pSrcItem->m_lootGenerated) // prevent swap looting item + { + //best error message found for attempting to swap while looting + SendEquipError( EQUIP_ERR_CANT_DO_RIGHT_NOW, pSrcItem, NULL ); + return; + } + + // check unequip potability for equipped items and bank bags + if(IsEquipmentPos ( src ) || IsBagPos ( src )) + { + // bags can be swapped with empty bag slots + uint8 msg = CanUnequipItem( src, !IsBagPos ( src ) || IsBagPos ( dst )); + if(msg != EQUIP_ERR_OK) + { + SendEquipError( msg, pSrcItem, pDstItem ); + return; + } + } + + // prevent put equipped/bank bag in self + if( IsBagPos ( src ) && srcslot == dstbag) + { + SendEquipError( EQUIP_ERR_NONEMPTY_BAG_OVER_OTHER_BAG, pSrcItem, pDstItem ); + return; + } + + if( !pDstItem ) + { + if( IsInventoryPos( dst ) ) + { + ItemPosCountVec dest; + uint8 msg = CanStoreItem( dstbag, dstslot, dest, pSrcItem, false ); + if( msg != EQUIP_ERR_OK ) + { + SendEquipError( msg, pSrcItem, NULL ); + return; + } + + RemoveItem(srcbag, srcslot, true); + StoreItem( dest, pSrcItem, true); + } + else if( IsBankPos ( dst ) ) + { + ItemPosCountVec dest; + uint8 msg = CanBankItem( dstbag, dstslot, dest, pSrcItem, false); + if( msg != EQUIP_ERR_OK ) + { + SendEquipError( msg, pSrcItem, NULL ); + return; + } + + RemoveItem(srcbag, srcslot, true); + BankItem( dest, pSrcItem, true); + } + else if( IsEquipmentPos ( dst ) ) + { + uint16 dest; + uint8 msg = CanEquipItem( dstslot, dest, pSrcItem, false ); + if( msg != EQUIP_ERR_OK ) + { + SendEquipError( msg, pSrcItem, NULL ); + return; + } + + RemoveItem(srcbag, srcslot, true); + EquipItem( dest, pSrcItem, true); + AutoUnequipOffhandIfNeed(); + } + } + else // if (!pDstItem) + { + if(pDstItem->m_lootGenerated) // prevent swap looting item + { + //best error message found for attempting to swap while looting + SendEquipError( EQUIP_ERR_CANT_DO_RIGHT_NOW, pDstItem, NULL ); + return; + } + + // check unequip potability for equipped items and bank bags + if(IsEquipmentPos ( dst ) || IsBagPos ( dst )) + { + // bags can be swapped with empty bag slots + uint8 msg = CanUnequipItem( dst, !IsBagPos ( dst ) || IsBagPos ( src ) ); + if(msg != EQUIP_ERR_OK) + { + SendEquipError( msg, pSrcItem, pDstItem ); + return; + } + } + + // attempt merge to / fill target item + { + uint8 msg; + ItemPosCountVec sDest; + uint16 eDest; + if( IsInventoryPos( dst ) ) + msg = CanStoreItem( dstbag, dstslot, sDest, pSrcItem, false ); + else if( IsBankPos ( dst ) ) + msg = CanBankItem( dstbag, dstslot, sDest, pSrcItem, false ); + else if( IsEquipmentPos ( dst ) ) + msg = CanEquipItem( dstslot, eDest, pSrcItem, false ); + else + return; + + // can be merge/fill + if(msg == EQUIP_ERR_OK) + { + if( pSrcItem->GetCount() + pDstItem->GetCount() <= pSrcItem->GetProto()->Stackable ) + { + RemoveItem(srcbag, srcslot, true); + + if( IsInventoryPos( dst ) ) + StoreItem( sDest, pSrcItem, true); + else if( IsBankPos ( dst ) ) + BankItem( sDest, pSrcItem, true); + else if( IsEquipmentPos ( dst ) ) + { + EquipItem( eDest, pSrcItem, true); + AutoUnequipOffhandIfNeed(); + } + } + else + { + pSrcItem->SetCount( pSrcItem->GetCount() + pDstItem->GetCount() - pSrcItem->GetProto()->Stackable ); + pDstItem->SetCount( pSrcItem->GetProto()->Stackable ); + pSrcItem->SetState(ITEM_CHANGED, this); + pDstItem->SetState(ITEM_CHANGED, this); + if( IsInWorld() ) + { + pSrcItem->SendUpdateToPlayer( this ); + pDstItem->SendUpdateToPlayer( this ); + } + } + return; + } + } + + // impossible merge/fill, do real swap + uint8 msg; + + // check src->dest move possibility + ItemPosCountVec sDest; + uint16 eDest; + if( IsInventoryPos( dst ) ) + msg = CanStoreItem( dstbag, dstslot, sDest, pSrcItem, true ); + else if( IsBankPos( dst ) ) + msg = CanBankItem( dstbag, dstslot, sDest, pSrcItem, true ); + else if( IsEquipmentPos( dst ) ) + { + msg = CanEquipItem( dstslot, eDest, pSrcItem, true ); + if( msg == EQUIP_ERR_OK ) + msg = CanUnequipItem( eDest, true ); + } + + if( msg != EQUIP_ERR_OK ) + { + SendEquipError( msg, pSrcItem, pDstItem ); + return; + } + + // check dest->src move possibility + ItemPosCountVec sDest2; + uint16 eDest2; + if( IsInventoryPos( src ) ) + msg = CanStoreItem( srcbag, srcslot, sDest2, pDstItem, true ); + else if( IsBankPos( src ) ) + msg = CanBankItem( srcbag, srcslot, sDest2, pDstItem, true ); + else if( IsEquipmentPos( src ) ) + { + msg = CanEquipItem( srcslot, eDest2, pDstItem, true); + if( msg == EQUIP_ERR_OK ) + msg = CanUnequipItem( eDest2, true); + } + + if( msg != EQUIP_ERR_OK ) + { + SendEquipError( msg, pDstItem, pSrcItem ); + return; + } + + // now do moves, remove... + RemoveItem(dstbag, dstslot, false); + RemoveItem(srcbag, srcslot, false); + + // add to dest + if( IsInventoryPos( dst ) ) + StoreItem(sDest, pSrcItem, true); + else if( IsBankPos( dst ) ) + BankItem(sDest, pSrcItem, true); + else if( IsEquipmentPos( dst ) ) + EquipItem(eDest, pSrcItem, true); + + // add to src + if( IsInventoryPos( src ) ) + StoreItem(sDest2, pDstItem, true); + else if( IsBankPos( src ) ) + BankItem(sDest2, pDstItem, true); + else if( IsEquipmentPos( src ) ) + EquipItem(eDest2, pDstItem, true); + + AutoUnequipOffhandIfNeed(); + } +} + +void Player::AddItemToBuyBackSlot( Item *pItem ) +{ + if( pItem ) + { + uint32 slot = m_currentBuybackSlot; + // if current back slot non-empty search oldest or free + if(m_items[slot]) + { + uint32 oldest_time = GetUInt32Value( PLAYER_FIELD_BUYBACK_TIMESTAMP_1 ); + uint32 oldest_slot = BUYBACK_SLOT_START; + + for(uint32 i = BUYBACK_SLOT_START+1; i < BUYBACK_SLOT_END; ++i ) + { + // found empty + if(!m_items[i]) + { + slot = i; + break; + } + + uint32 i_time = GetUInt32Value( PLAYER_FIELD_BUYBACK_TIMESTAMP_1 + i - BUYBACK_SLOT_START); + + if(oldest_time > i_time) + { + oldest_time = i_time; + oldest_slot = i; + } + } + + // find oldest + slot = oldest_slot; + } + + RemoveItemFromBuyBackSlot( slot, true ); + sLog.outDebug( "STORAGE: AddItemToBuyBackSlot item = %u, slot = %u", pItem->GetEntry(), slot); + + m_items[slot] = pItem; + time_t base = time(NULL); + uint32 etime = uint32(base - m_logintime + (30 * 3600)); + uint32 eslot = slot - BUYBACK_SLOT_START; + + SetUInt64Value( PLAYER_FIELD_VENDORBUYBACK_SLOT_1 + eslot * 2, pItem->GetGUID() ); + ItemPrototype const *pProto = pItem->GetProto(); + if( pProto ) + SetUInt32Value( PLAYER_FIELD_BUYBACK_PRICE_1 + eslot, pProto->SellPrice * pItem->GetCount() ); + else + SetUInt32Value( PLAYER_FIELD_BUYBACK_PRICE_1 + eslot, 0 ); + SetUInt32Value( PLAYER_FIELD_BUYBACK_TIMESTAMP_1 + eslot, (uint32)etime ); + + // move to next (for non filled list is move most optimized choice) + if(m_currentBuybackSlot < BUYBACK_SLOT_END-1) + ++m_currentBuybackSlot; + } +} + +Item* Player::GetItemFromBuyBackSlot( uint32 slot ) +{ + sLog.outDebug( "STORAGE: GetItemFromBuyBackSlot slot = %u", slot); + if( slot >= BUYBACK_SLOT_START && slot < BUYBACK_SLOT_END ) + return m_items[slot]; + return NULL; +} + +void Player::RemoveItemFromBuyBackSlot( uint32 slot, bool del ) +{ + sLog.outDebug( "STORAGE: RemoveItemFromBuyBackSlot slot = %u", slot); + if( slot >= BUYBACK_SLOT_START && slot < BUYBACK_SLOT_END ) + { + Item *pItem = m_items[slot]; + if( pItem ) + { + pItem->RemoveFromWorld(); + if(del) pItem->SetState(ITEM_REMOVED, this); + } + + m_items[slot] = NULL; + + uint32 eslot = slot - BUYBACK_SLOT_START; + SetUInt64Value( PLAYER_FIELD_VENDORBUYBACK_SLOT_1 + eslot * 2, 0 ); + SetUInt32Value( PLAYER_FIELD_BUYBACK_PRICE_1 + eslot, 0 ); + SetUInt32Value( PLAYER_FIELD_BUYBACK_TIMESTAMP_1 + eslot, 0 ); + + // if current backslot is filled set to now free slot + if(m_items[m_currentBuybackSlot]) + m_currentBuybackSlot = slot; + } +} + +void Player::SendEquipError( uint8 msg, Item* pItem, Item *pItem2 ) +{ + sLog.outDebug( "WORLD: Sent SMSG_INVENTORY_CHANGE_FAILURE (%u)",msg); + WorldPacket data( SMSG_INVENTORY_CHANGE_FAILURE, (msg == EQUIP_ERR_CANT_EQUIP_LEVEL_I ? 22 : 18) ); + data << uint8(msg); + + if(msg) + { + data << uint64(pItem ? pItem->GetGUID() : 0); + data << uint64(pItem2 ? pItem2->GetGUID() : 0); + data << uint8(0); // not 0 there... + + if(msg == EQUIP_ERR_CANT_EQUIP_LEVEL_I) + { + uint32 level = 0; + + if(pItem) + if(ItemPrototype const* proto = pItem->GetProto()) + level = proto->RequiredLevel; + + data << uint32(level); // new 2.4.0 + } + } + GetSession()->SendPacket(&data); +} + +void Player::SendBuyError( uint8 msg, Creature* pCreature, uint32 item, uint32 param ) +{ + sLog.outDebug( "WORLD: Sent SMSG_BUY_FAILED" ); + WorldPacket data( SMSG_BUY_FAILED, (8+4+4+1) ); + data << uint64(pCreature ? pCreature->GetGUID() : 0); + data << uint32(item); + if( param > 0 ) + data << uint32(param); + data << uint8(msg); + GetSession()->SendPacket(&data); +} + +void Player::SendSellError( uint8 msg, Creature* pCreature, uint64 guid, uint32 param ) +{ + sLog.outDebug( "WORLD: Sent SMSG_SELL_ITEM" ); + WorldPacket data( SMSG_SELL_ITEM,(8+8+(param?4:0)+1)); // last check 2.0.10 + data << uint64(pCreature ? pCreature->GetGUID() : 0); + data << uint64(guid); + if( param > 0 ) + data << uint32(param); + data << uint8(msg); + GetSession()->SendPacket(&data); +} + +void Player::ClearTrade() +{ + tradeGold = 0; + acceptTrade = false; + for(int i = 0; i < TRADE_SLOT_COUNT; i++) + tradeItems[i] = NULL_SLOT; +} + +void Player::TradeCancel(bool sendback) +{ + if(pTrader) + { + // send yellow "Trade cancelled" message to both traders + WorldSession* ws; + ws = GetSession(); + if(sendback) + ws->SendCancelTrade(); + ws = pTrader->GetSession(); + if(!ws->PlayerLogout()) + ws->SendCancelTrade(); + + // cleanup + ClearTrade(); + pTrader->ClearTrade(); + // prevent loss of reference + pTrader->pTrader = NULL; + pTrader = NULL; + } +} + +void Player::UpdateItemDuration(uint32 time, bool realtimeonly) +{ + if(m_itemDuration.empty()) + return; + + sLog.outDebug("Player::UpdateItemDuration(%u,%u)", time,realtimeonly); + + for(ItemDurationList::iterator itr = m_itemDuration.begin();itr != m_itemDuration.end(); ) + { + Item* item = *itr; + ++itr; // current element can be erased in UpdateDuration + + if (realtimeonly && item->GetProto()->Duration < 0 || !realtimeonly) + item->UpdateDuration(this,time); + } +} + +void Player::UpdateEnchantTime(uint32 time) +{ + for(EnchantDurationList::iterator itr = m_enchantDuration.begin(),next;itr != m_enchantDuration.end();itr=next) + { + assert(itr->item); + next=itr; + if(!itr->item->GetEnchantmentId(itr->slot)) + { + next = m_enchantDuration.erase(itr); + } + else if(itr->leftduration <= time) + { + ApplyEnchantment(itr->item,itr->slot,false,false); + itr->item->ClearEnchantment(itr->slot); + next = m_enchantDuration.erase(itr); + } + else if(itr->leftduration > time) + { + itr->leftduration -= time; + ++next; + } + } +} + +void Player::AddEnchantmentDurations(Item *item) +{ + for(int x=0;xGetEnchantmentId(EnchantmentSlot(x))) + continue; + + uint32 duration = item->GetEnchantmentDuration(EnchantmentSlot(x)); + if( duration > 0 ) + AddEnchantmentDuration(item,EnchantmentSlot(x),duration); + } +} + +void Player::RemoveEnchantmentDurations(Item *item) +{ + for(EnchantDurationList::iterator itr = m_enchantDuration.begin();itr != m_enchantDuration.end();) + { + if(itr->item == item) + { + // save duration in item + item->SetEnchantmentDuration(EnchantmentSlot(itr->slot),itr->leftduration); + itr = m_enchantDuration.erase(itr); + } + else + ++itr; + } +} + + +void Player::RemoveAllEnchantments(EnchantmentSlot slot) +{ + // remove enchantments from equipped items first to clean up the m_enchantDuration list + for(EnchantDurationList::iterator itr = m_enchantDuration.begin(),next;itr != m_enchantDuration.end();itr=next) + { + next = itr; + if(itr->slot==slot) + { + if(itr->item && itr->item->GetEnchantmentId(slot)) + { + // remove from stats + ApplyEnchantment(itr->item,slot,false,false); + // remove visual + itr->item->ClearEnchantment(slot); + } + // remove from update list + next = m_enchantDuration.erase(itr); + } + else + ++next; + } + + // remove enchants from inventory items + // NOTE: no need to remove these from stats, since these aren't equipped + // in inventory + for(int i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++) + { + Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pItem && pItem->GetEnchantmentId(slot) ) + pItem->ClearEnchantment(slot); + } + + // in inventory bags + for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) + { + Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if( pBag ) + { + ItemPrototype const *pBagProto = pBag->GetProto(); + if( pBagProto ) + { + for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + { + Item* pItem = pBag->GetItemByPos(j); + if( pItem && pItem->GetEnchantmentId(slot) ) + pItem->ClearEnchantment(slot); + } + } + } + } +} + +// duration == 0 will remove item enchant +void Player::AddEnchantmentDuration(Item *item,EnchantmentSlot slot,uint32 duration) +{ + if(!item) + return; + + if(slot >= MAX_ENCHANTMENT_SLOT) + return; + + for(EnchantDurationList::iterator itr = m_enchantDuration.begin();itr != m_enchantDuration.end();++itr) + { + if(itr->item == item && itr->slot == slot) + { + itr->item->SetEnchantmentDuration(itr->slot,itr->leftduration); + m_enchantDuration.erase(itr); + break; + } + } + if(item && duration > 0 ) + { + GetSession()->SendItemEnchantTimeUpdate(GetGUID(), item->GetGUID(),slot,uint32(duration/1000)); + m_enchantDuration.push_back(EnchantDuration(item,slot,duration)); + } +} + +void Player::ApplyEnchantment(Item *item,bool apply) +{ + for(uint32 slot = 0; slot < MAX_ENCHANTMENT_SLOT; ++slot) + ApplyEnchantment(item, EnchantmentSlot(slot), apply); +} + +void Player::ApplyEnchantment(Item *item,EnchantmentSlot slot,bool apply, bool apply_dur, bool ignore_condition) +{ + if(!item) + return; + + if(!item->IsEquipped()) + return; + + if(slot >= MAX_ENCHANTMENT_SLOT) + return; + + uint32 enchant_id = item->GetEnchantmentId(slot); + if(!enchant_id) + return; + + SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id); + if(!pEnchant) + return; + + if(!ignore_condition && pEnchant->EnchantmentCondition && !((Player*)this)->EnchantmentFitsRequirements(pEnchant->EnchantmentCondition, -1)) + return; + + for (int s=0; s<3; s++) + { + uint32 enchant_display_type = pEnchant->type[s]; + uint32 enchant_amount = pEnchant->amount[s]; + uint32 enchant_spell_id = pEnchant->spellid[s]; + + switch(enchant_display_type) + { + case ITEM_ENCHANTMENT_TYPE_NONE: + break; + case ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL: + // processed in Player::CastItemCombatSpell + break; + case ITEM_ENCHANTMENT_TYPE_DAMAGE: + if (item->GetSlot() == EQUIPMENT_SLOT_MAINHAND) + HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(enchant_amount), apply); + else if (item->GetSlot() == EQUIPMENT_SLOT_OFFHAND) + HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(enchant_amount), apply); + else if (item->GetSlot() == EQUIPMENT_SLOT_RANGED) + HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(enchant_amount), apply); + break; + case ITEM_ENCHANTMENT_TYPE_EQUIP_SPELL: + if(enchant_spell_id) + { + if(apply) + { + int32 basepoints = int32(enchant_amount); + // Random Property Exist - try found basepoints for spell (basepoints depencs from item suffix factor) + if (item->GetItemRandomPropertyId() !=0 && !enchant_amount) + { + ItemRandomSuffixEntry const *item_rand = sItemRandomSuffixStore.LookupEntry(abs(item->GetItemRandomPropertyId())); + if (item_rand) + { + // Search enchant_amount + for (int k=0; k<3; k++) + { + if(item_rand->enchant_id[k] == enchant_id) + { + basepoints = int32((item_rand->prefix[k]*item->GetItemSuffixFactor()) / 10000 ); + break; + } + } + } + } + // Cast custom spell vs all equal basepoints getted from enchant_amount + if (basepoints) + CastCustomSpell(this,enchant_spell_id,&basepoints,&basepoints,&basepoints,true,item); + else + CastSpell(this,enchant_spell_id,true,item); + } + else + RemoveAurasDueToItemSpell(item,enchant_spell_id); + } + break; + case ITEM_ENCHANTMENT_TYPE_RESISTANCE: + if (!enchant_amount) + { + ItemRandomSuffixEntry const *item_rand = sItemRandomSuffixStore.LookupEntry(abs(item->GetItemRandomPropertyId())); + if(item_rand) + { + for (int k=0; k<3; k++) + { + if(item_rand->enchant_id[k] == enchant_id) + { + enchant_amount = uint32((item_rand->prefix[k]*item->GetItemSuffixFactor()) / 10000 ); + break; + } + } + } + } + + HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + enchant_spell_id), TOTAL_VALUE, float(enchant_amount), apply); + break; + case ITEM_ENCHANTMENT_TYPE_STAT: + { + if (!enchant_amount) + { + ItemRandomSuffixEntry const *item_rand_suffix = sItemRandomSuffixStore.LookupEntry(abs(item->GetItemRandomPropertyId())); + if(item_rand_suffix) + { + for (int k=0; k<3; k++) + { + if(item_rand_suffix->enchant_id[k] == enchant_id) + { + enchant_amount = uint32((item_rand_suffix->prefix[k]*item->GetItemSuffixFactor()) / 10000 ); + break; + } + } + } + } + + sLog.outDebug("Adding %u to stat nb %u",enchant_amount,enchant_spell_id); + switch (enchant_spell_id) + { + case ITEM_MOD_AGILITY: + sLog.outDebug("+ %u AGILITY",enchant_amount); + HandleStatModifier(UNIT_MOD_STAT_AGILITY, TOTAL_VALUE, float(enchant_amount), apply); + ApplyStatBuffMod(STAT_AGILITY, enchant_amount, apply); + break; + case ITEM_MOD_STRENGTH: + sLog.outDebug("+ %u STRENGTH",enchant_amount); + HandleStatModifier(UNIT_MOD_STAT_STRENGTH, TOTAL_VALUE, float(enchant_amount), apply); + ApplyStatBuffMod(STAT_STRENGTH, enchant_amount, apply); + break; + case ITEM_MOD_INTELLECT: + sLog.outDebug("+ %u INTELLECT",enchant_amount); + HandleStatModifier(UNIT_MOD_STAT_INTELLECT, TOTAL_VALUE, float(enchant_amount), apply); + ApplyStatBuffMod(STAT_INTELLECT, enchant_amount, apply); + break; + case ITEM_MOD_SPIRIT: + sLog.outDebug("+ %u SPIRIT",enchant_amount); + HandleStatModifier(UNIT_MOD_STAT_SPIRIT, TOTAL_VALUE, float(enchant_amount), apply); + ApplyStatBuffMod(STAT_SPIRIT, enchant_amount, apply); + break; + case ITEM_MOD_STAMINA: + sLog.outDebug("+ %u STAMINA",enchant_amount); + HandleStatModifier(UNIT_MOD_STAT_STAMINA, TOTAL_VALUE, float(enchant_amount), apply); + ApplyStatBuffMod(STAT_STAMINA, enchant_amount, apply); + break; + case ITEM_MOD_DEFENSE_SKILL_RATING: + ((Player*)this)->ApplyRatingMod(CR_DEFENSE_SKILL, enchant_amount, apply); + sLog.outDebug("+ %u DEFENCE", enchant_amount); + break; + case ITEM_MOD_DODGE_RATING: + ((Player*)this)->ApplyRatingMod(CR_DODGE, enchant_amount, apply); + sLog.outDebug("+ %u DODGE", enchant_amount); + break; + case ITEM_MOD_PARRY_RATING: + ((Player*)this)->ApplyRatingMod(CR_PARRY, enchant_amount, apply); + sLog.outDebug("+ %u PARRY", enchant_amount); + break; + case ITEM_MOD_BLOCK_RATING: + ((Player*)this)->ApplyRatingMod(CR_BLOCK, enchant_amount, apply); + sLog.outDebug("+ %u SHIELD_BLOCK", enchant_amount); + break; + case ITEM_MOD_HIT_MELEE_RATING: + ((Player*)this)->ApplyRatingMod(CR_HIT_MELEE, enchant_amount, apply); + sLog.outDebug("+ %u MELEE_HIT", enchant_amount); + break; + case ITEM_MOD_HIT_RANGED_RATING: + ((Player*)this)->ApplyRatingMod(CR_HIT_RANGED, enchant_amount, apply); + sLog.outDebug("+ %u RANGED_HIT", enchant_amount); + break; + case ITEM_MOD_HIT_SPELL_RATING: + ((Player*)this)->ApplyRatingMod(CR_HIT_SPELL, enchant_amount, apply); + sLog.outDebug("+ %u SPELL_HIT", enchant_amount); + break; + case ITEM_MOD_CRIT_MELEE_RATING: + ((Player*)this)->ApplyRatingMod(CR_CRIT_MELEE, enchant_amount, apply); + sLog.outDebug("+ %u MELEE_CRIT", enchant_amount); + break; + case ITEM_MOD_CRIT_RANGED_RATING: + ((Player*)this)->ApplyRatingMod(CR_CRIT_RANGED, enchant_amount, apply); + sLog.outDebug("+ %u RANGED_CRIT", enchant_amount); + break; + case ITEM_MOD_CRIT_SPELL_RATING: + ((Player*)this)->ApplyRatingMod(CR_CRIT_SPELL, enchant_amount, apply); + sLog.outDebug("+ %u SPELL_CRIT", enchant_amount); + break; +// Values from ITEM_STAT_MELEE_HA_RATING to ITEM_MOD_HASTE_RANGED_RATING are never used +// in Enchantments +// case ITEM_MOD_HIT_TAKEN_MELEE_RATING: +// ((Player*)this)->ApplyRatingMod(CR_HIT_TAKEN_MELEE, enchant_amount, apply); +// break; +// case ITEM_MOD_HIT_TAKEN_RANGED_RATING: +// ((Player*)this)->ApplyRatingMod(CR_HIT_TAKEN_RANGED, enchant_amount, apply); +// break; +// case ITEM_MOD_HIT_TAKEN_SPELL_RATING: +// ((Player*)this)->ApplyRatingMod(CR_HIT_TAKEN_SPELL, enchant_amount, apply); +// break; +// case ITEM_MOD_CRIT_TAKEN_MELEE_RATING: +// ((Player*)this)->ApplyRatingMod(CR_CRIT_TAKEN_MELEE, enchant_amount, apply); +// break; +// case ITEM_MOD_CRIT_TAKEN_RANGED_RATING: +// ((Player*)this)->ApplyRatingMod(CR_CRIT_TAKEN_RANGED, enchant_amount, apply); +// break; +// case ITEM_MOD_CRIT_TAKEN_SPELL_RATING: +// ((Player*)this)->ApplyRatingMod(CR_CRIT_TAKEN_SPELL, enchant_amount, apply); +// break; +// case ITEM_MOD_HASTE_MELEE_RATING: +// ((Player*)this)->ApplyRatingMod(CR_HASTE_MELEE, enchant_amount, apply); +// break; +// case ITEM_MOD_HASTE_RANGED_RATING: +// ((Player*)this)->ApplyRatingMod(CR_HASTE_RANGED, enchant_amount, apply); +// break; + case ITEM_MOD_HASTE_SPELL_RATING: + ((Player*)this)->ApplyRatingMod(CR_HASTE_SPELL, enchant_amount, apply); + break; + case ITEM_MOD_HIT_RATING: + ((Player*)this)->ApplyRatingMod(CR_HIT_MELEE, enchant_amount, apply); + ((Player*)this)->ApplyRatingMod(CR_HIT_RANGED, enchant_amount, apply); + ((Player*)this)->ApplyRatingMod(CR_HIT_SPELL, enchant_amount, apply); + sLog.outDebug("+ %u HIT", enchant_amount); + break; + case ITEM_MOD_CRIT_RATING: + ((Player*)this)->ApplyRatingMod(CR_CRIT_MELEE, enchant_amount, apply); + ((Player*)this)->ApplyRatingMod(CR_CRIT_RANGED, enchant_amount, apply); + ((Player*)this)->ApplyRatingMod(CR_CRIT_SPELL, enchant_amount, apply); + sLog.outDebug("+ %u CRITICAL", enchant_amount); + break; +// Values ITEM_MOD_HIT_TAKEN_RATING and ITEM_MOD_CRIT_TAKEN_RATING are never used in Enchantment +// case ITEM_MOD_HIT_TAKEN_RATING: +// ((Player*)this)->ApplyRatingMod(CR_HIT_TAKEN_MELEE, enchant_amount, apply); +// ((Player*)this)->ApplyRatingMod(CR_HIT_TAKEN_RANGED, enchant_amount, apply); +// ((Player*)this)->ApplyRatingMod(CR_HIT_TAKEN_SPELL, enchant_amount, apply); +// break; +// case ITEM_MOD_CRIT_TAKEN_RATING: +// ((Player*)this)->ApplyRatingMod(CR_CRIT_TAKEN_MELEE, enchant_amount, apply); +// ((Player*)this)->ApplyRatingMod(CR_CRIT_TAKEN_RANGED, enchant_amount, apply); +// ((Player*)this)->ApplyRatingMod(CR_CRIT_TAKEN_SPELL, enchant_amount, apply); +// break; + case ITEM_MOD_RESILIENCE_RATING: + ((Player*)this)->ApplyRatingMod(CR_CRIT_TAKEN_MELEE, enchant_amount, apply); + ((Player*)this)->ApplyRatingMod(CR_CRIT_TAKEN_RANGED, enchant_amount, apply); + ((Player*)this)->ApplyRatingMod(CR_CRIT_TAKEN_SPELL, enchant_amount, apply); + sLog.outDebug("+ %u RESILIENCE", enchant_amount); + break; + case ITEM_MOD_HASTE_RATING: + ((Player*)this)->ApplyRatingMod(CR_HASTE_MELEE, enchant_amount, apply); + ((Player*)this)->ApplyRatingMod(CR_HASTE_RANGED, enchant_amount, apply); + ((Player*)this)->ApplyRatingMod(CR_HASTE_SPELL, enchant_amount, apply); + sLog.outDebug("+ %u HASTE", enchant_amount); + break; + case ITEM_MOD_EXPERTISE_RATING: + ((Player*)this)->ApplyRatingMod(CR_EXPERTISE, enchant_amount, apply); + sLog.outDebug("+ %u EXPERTISE", enchant_amount); + break; + default: + break; + } + break; + } + case ITEM_ENCHANTMENT_TYPE_TOTEM: // Shaman Rockbiter Weapon + { + if(getClass() == CLASS_SHAMAN) + { + float addValue = 0.0f; + if(item->GetSlot() == EQUIPMENT_SLOT_MAINHAND) + { + addValue = float(enchant_amount * item->GetProto()->Delay/1000.0f); + HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, addValue, apply); + } + else if(item->GetSlot() == EQUIPMENT_SLOT_OFFHAND ) + { + addValue = float(enchant_amount * item->GetProto()->Delay/1000.0f); + HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, addValue, apply); + } + } + break; + } + default: + sLog.outError("Unknown item enchantment display type: %d",enchant_display_type); + break; + } /*switch(enchant_display_type)*/ + } /*for*/ + + // visualize enchantment at player and equipped items + if(slot < MAX_INSPECTED_ENCHANTMENT_SLOT) + { + int VisibleBase = PLAYER_VISIBLE_ITEM_1_0 + (item->GetSlot() * MAX_VISIBLE_ITEM_OFFSET); + SetUInt32Value(VisibleBase + 1 + slot, apply? item->GetEnchantmentId(slot) : 0); + } + + if(apply_dur) + { + if(apply) + { + // set duration + uint32 duration = item->GetEnchantmentDuration(slot); + if(duration > 0) + AddEnchantmentDuration(item,slot,duration); + } + else + { + // duration == 0 will remove EnchantDuration + AddEnchantmentDuration(item,slot,0); + } + } +} + +void Player::SendEnchantmentDurations() +{ + for(EnchantDurationList::iterator itr = m_enchantDuration.begin();itr != m_enchantDuration.end();++itr) + { + GetSession()->SendItemEnchantTimeUpdate(GetGUID(), itr->item->GetGUID(),itr->slot,uint32(itr->leftduration)/1000); + } +} + +void Player::SendItemDurations() +{ + for(ItemDurationList::iterator itr = m_itemDuration.begin();itr != m_itemDuration.end();++itr) + { + (*itr)->SendTimeUpdate(this); + } +} + +void Player::SendNewItem(Item *item, uint32 count, bool received, bool created, bool broadcast) +{ + if(!item) // prevent crash + return; + + // last check 2.0.10 + WorldPacket data( SMSG_ITEM_PUSH_RESULT, (8+4+4+4+1+4+4+4+4+4) ); + data << GetGUID(); // player GUID + data << uint32(received); // 0=looted, 1=from npc + data << uint32(created); // 0=received, 1=created + data << uint32(1); // always 0x01 (probably meant to be count of listed items) + data << (uint8)item->GetBagSlot(); // bagslot + // item slot, but when added to stack: 0xFFFFFFFF + data << (uint32) ((item->GetCount()==count) ? item->GetSlot() : -1); + data << uint32(item->GetEntry()); // item id + data << uint32(item->GetItemSuffixFactor()); // SuffixFactor + data << uint32(item->GetItemRandomPropertyId()); // random item property id + data << uint32(count); // count of items + data << GetItemCount(item->GetEntry()); // count of items in inventory + + if (broadcast && GetGroup()) + GetGroup()->BroadcastPacket(&data); + else + GetSession()->SendPacket(&data); +} + +/*********************************************************/ +/*** QUEST SYSTEM ***/ +/*********************************************************/ + +void Player::PrepareQuestMenu( uint64 guid ) +{ + Object *pObject; + QuestRelations* pObjectQR; + QuestRelations* pObjectQIR; + Creature *pCreature = ObjectAccessor::GetCreature(*this, guid); + if( pCreature ) + { + pObject = (Object*)pCreature; + pObjectQR = &objmgr.mCreatureQuestRelations; + pObjectQIR = &objmgr.mCreatureQuestInvolvedRelations; + } + else + { + GameObject *pGameObject = ObjectAccessor::GetGameObject(*this, guid); + if( pGameObject ) + { + pObject = (Object*)pGameObject; + pObjectQR = &objmgr.mGOQuestRelations; + pObjectQIR = &objmgr.mGOQuestInvolvedRelations; + } + else + return; + } + + QuestMenu *qm = PlayerTalkClass->GetQuestMenu(); + qm->ClearMenu(); + + for(QuestRelations::const_iterator i = pObjectQIR->lower_bound(pObject->GetEntry()); i != pObjectQIR->upper_bound(pObject->GetEntry()); ++i) + { + uint32 quest_id = i->second; + QuestStatus status = GetQuestStatus( quest_id ); + if ( status == QUEST_STATUS_COMPLETE && !GetQuestRewardStatus( quest_id ) ) + qm->AddMenuItem(quest_id, DIALOG_STATUS_REWARD_REP); + else if ( status == QUEST_STATUS_INCOMPLETE ) + qm->AddMenuItem(quest_id, DIALOG_STATUS_INCOMPLETE); + else if (status == QUEST_STATUS_AVAILABLE ) + qm->AddMenuItem(quest_id, DIALOG_STATUS_CHAT); + } + + for(QuestRelations::const_iterator i = pObjectQR->lower_bound(pObject->GetEntry()); i != pObjectQR->upper_bound(pObject->GetEntry()); ++i) + { + uint32 quest_id = i->second; + Quest const* pQuest = objmgr.GetQuestTemplate(quest_id); + if(!pQuest) continue; + + QuestStatus status = GetQuestStatus( quest_id ); + + if (pQuest->IsAutoComplete() && CanTakeQuest(pQuest, false)) + qm->AddMenuItem(quest_id, DIALOG_STATUS_REWARD_REP); + else if ( status == QUEST_STATUS_NONE && CanTakeQuest( pQuest, false ) ) + qm->AddMenuItem(quest_id, DIALOG_STATUS_AVAILABLE); + } +} + +void Player::SendPreparedQuest( uint64 guid ) +{ + QuestMenu* pQuestMenu = PlayerTalkClass->GetQuestMenu(); + if( !pQuestMenu || pQuestMenu->MenuItemCount() < 1 ) + return; + + uint32 status = pQuestMenu->GetItem(0).m_qIcon; + if ( pQuestMenu->MenuItemCount() == 1 ) + { + // Auto open -- maybe also should verify there is no greeting + uint32 quest_id = pQuestMenu->GetItem(0).m_qId; + Quest const* pQuest = objmgr.GetQuestTemplate(quest_id); + if ( pQuest ) + { + if( status == DIALOG_STATUS_REWARD_REP && !GetQuestRewardStatus( quest_id ) ) + PlayerTalkClass->SendQuestGiverRequestItems( pQuest, guid, CanRewardQuest(pQuest,false), true ); + else if( status == DIALOG_STATUS_INCOMPLETE ) + PlayerTalkClass->SendQuestGiverRequestItems( pQuest, guid, false, true ); + // Send completable on repeatable quest if player don't have quest + else if( pQuest->IsRepeatable() ) + PlayerTalkClass->SendQuestGiverRequestItems( pQuest, guid, CanCompleteRepeatableQuest(pQuest), true ); + else + PlayerTalkClass->SendQuestGiverQuestDetails( pQuest, guid, true ); + } + } + else + { + QEmote qe; + qe._Delay = 0; + qe._Emote = 0; + std::string title = ""; + Creature *pCreature = ObjectAccessor::GetCreature(*this, guid); + if( pCreature ) + { + uint32 textid = pCreature->GetNpcTextId(); + GossipText * gossiptext = objmgr.GetGossipText(textid); + if( !gossiptext ) + { + qe._Delay = 0; //TEXTEMOTE_MESSAGE; //zyg: player emote + qe._Emote = 0; //TEXTEMOTE_HELLO; //zyg: NPC emote + title = ""; + } + else + { + qe = gossiptext->Options[0].Emotes[0]; + + if(!gossiptext->Options[0].Text_0.empty()) + { + title = gossiptext->Options[0].Text_0; + + int loc_idx = GetSession()->GetSessionDbLocaleIndex(); + if (loc_idx >= 0) + { + NpcTextLocale const *nl = objmgr.GetNpcTextLocale(textid); + if (nl) + { + if (nl->Text_0[0].size() > loc_idx && !nl->Text_0[0][loc_idx].empty()) + title = nl->Text_0[0][loc_idx]; + } + } + } + else + { + title = gossiptext->Options[0].Text_1; + + int loc_idx = GetSession()->GetSessionDbLocaleIndex(); + if (loc_idx >= 0) + { + NpcTextLocale const *nl = objmgr.GetNpcTextLocale(textid); + if (nl) + { + if (nl->Text_1[0].size() > loc_idx && !nl->Text_1[0][loc_idx].empty()) + title = nl->Text_1[0][loc_idx]; + } + } + } + } + } + PlayerTalkClass->SendQuestGiverQuestList( qe, title, guid ); + } +} + +bool Player::IsActiveQuest( uint32 quest_id ) const +{ + QuestStatusMap::const_iterator itr = mQuestStatus.find(quest_id); + + return itr != mQuestStatus.end() && itr->second.m_status != QUEST_STATUS_NONE; +} + +Quest const * Player::GetNextQuest( uint64 guid, Quest const *pQuest ) +{ + Object *pObject; + QuestRelations* pObjectQR; + QuestRelations* pObjectQIR; + + Creature *pCreature = ObjectAccessor::GetCreature(*this, guid); + if( pCreature ) + { + pObject = (Object*)pCreature; + pObjectQR = &objmgr.mCreatureQuestRelations; + pObjectQIR = &objmgr.mCreatureQuestInvolvedRelations; + } + else + { + GameObject *pGameObject = ObjectAccessor::GetGameObject(*this, guid); + if( pGameObject ) + { + pObject = (Object*)pGameObject; + pObjectQR = &objmgr.mGOQuestRelations; + pObjectQIR = &objmgr.mGOQuestInvolvedRelations; + } + else + return NULL; + } + + uint32 nextQuestID = pQuest->GetNextQuestInChain(); + for(QuestRelations::const_iterator itr = pObjectQR->lower_bound(pObject->GetEntry()); itr != pObjectQR->upper_bound(pObject->GetEntry()); ++itr) + { + if (itr->second == nextQuestID) + return objmgr.GetQuestTemplate(nextQuestID); + } + + return NULL; +} + +bool Player::CanSeeStartQuest( Quest const *pQuest ) +{ + if( SatisfyQuestRace( pQuest, false ) && SatisfyQuestSkillOrClass( pQuest, false ) && + SatisfyQuestExclusiveGroup( pQuest, false ) && SatisfyQuestReputation( pQuest, false ) && + SatisfyQuestPreviousQuest( pQuest, false ) && SatisfyQuestNextChain( pQuest, false ) && + SatisfyQuestPrevChain( pQuest, false ) && SatisfyQuestDay( pQuest, false ) ) + { + return getLevel() + sWorld.getConfig(CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF) >= pQuest->GetMinLevel(); + } + + return false; +} + +bool Player::CanTakeQuest( Quest const *pQuest, bool msg ) +{ + return SatisfyQuestStatus( pQuest, msg ) && SatisfyQuestExclusiveGroup( pQuest, msg ) + && SatisfyQuestRace( pQuest, msg ) && SatisfyQuestLevel( pQuest, msg ) + && SatisfyQuestSkillOrClass( pQuest, msg ) && SatisfyQuestReputation( pQuest, msg ) + && SatisfyQuestPreviousQuest( pQuest, msg ) && SatisfyQuestTimed( pQuest, msg ) + && SatisfyQuestNextChain( pQuest, msg ) && SatisfyQuestPrevChain( pQuest, msg ) + && SatisfyQuestDay( pQuest, msg ); +} + +bool Player::CanAddQuest( Quest const *pQuest, bool msg ) +{ + if( !SatisfyQuestLog( msg ) ) + return false; + + uint32 srcitem = pQuest->GetSrcItemId(); + if( srcitem > 0 ) + { + uint32 count = pQuest->GetSrcItemCount(); + ItemPosCountVec dest; + uint8 msg = CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, srcitem, count ); + + // player already have max number (in most case 1) source item, no additional item needed and quest can be added. + if( msg == EQUIP_ERR_CANT_CARRY_MORE_OF_THIS ) + return true; + else if( msg != EQUIP_ERR_OK ) + { + SendEquipError( msg, NULL, NULL ); + return false; + } + } + return true; +} + +bool Player::CanCompleteQuest( uint32 quest_id ) +{ + if( quest_id ) + { + QuestStatusData& q_status = mQuestStatus[quest_id]; + if( q_status.m_status == QUEST_STATUS_COMPLETE ) + return false; // not allow re-complete quest + + Quest const* qInfo = objmgr.GetQuestTemplate(quest_id); + + if(!qInfo) + return false; + + // auto complete quest + if (qInfo->IsAutoComplete() && CanTakeQuest(qInfo, false)) + return true; + + if ( q_status.m_status == QUEST_STATUS_INCOMPLETE ) + { + + if ( qInfo->HasFlag( QUEST_MANGOS_FLAGS_DELIVER ) ) + { + for(int i = 0; i < QUEST_OBJECTIVES_COUNT; i++) + { + if( qInfo->ReqItemCount[i]!= 0 && q_status.m_itemcount[i] < qInfo->ReqItemCount[i] ) + return false; + } + } + + if ( qInfo->HasFlag(QUEST_MANGOS_FLAGS_KILL_OR_CAST | QUEST_MANGOS_FLAGS_SPEAKTO) ) + { + for(int i = 0; i < QUEST_OBJECTIVES_COUNT; i++) + { + if( qInfo->ReqCreatureOrGOId[i] == 0 ) + continue; + + if( qInfo->ReqCreatureOrGOCount[i] != 0 && q_status.m_creatureOrGOcount[i] < qInfo->ReqCreatureOrGOCount[i] ) + return false; + } + } + + if ( qInfo->HasFlag( QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT ) && !q_status.m_explored ) + return false; + + if ( qInfo->HasFlag( QUEST_MANGOS_FLAGS_TIMED ) && q_status.m_timer == 0 ) + return false; + + if ( qInfo->GetRewOrReqMoney() < 0 ) + { + if ( GetMoney() < uint32(-qInfo->GetRewOrReqMoney()) ) + return false; + } + + uint32 repFacId = qInfo->GetRepObjectiveFaction(); + if ( repFacId && GetReputation(repFacId) < qInfo->GetRepObjectiveValue() ) + return false; + + return true; + } + } + return false; +} + +bool Player::CanCompleteRepeatableQuest( Quest const *pQuest ) +{ + // Solve problem that player don't have the quest and try complete it. + // if repeatable she must be able to complete event if player don't have it. + // Seem that all repeatable quest are DELIVER Flag so, no need to add more. + if( !CanTakeQuest(pQuest, false) ) + return false; + + if (pQuest->HasFlag( QUEST_MANGOS_FLAGS_DELIVER) ) + for(int i = 0; i < QUEST_OBJECTIVES_COUNT; i++) + if( pQuest->ReqItemId[i] && pQuest->ReqItemCount[i] && !HasItemCount(pQuest->ReqItemId[i],pQuest->ReqItemCount[i]) ) + return false; + + if( !CanRewardQuest(pQuest, false) ) + return false; + + return true; +} + +bool Player::CanRewardQuest( Quest const *pQuest, bool msg ) +{ + // not auto complete quest and not completed quest (only cheating case, then ignore without message) + if(!pQuest->IsAutoComplete() && GetQuestStatus(pQuest->GetQuestId()) != QUEST_STATUS_COMPLETE) + return false; + + // daily quest can't be rewarded (10 daily quest already completed) + if(!SatisfyQuestDay(pQuest,true)) + return false; + + // rewarded and not repeatable quest (only cheating case, then ignore without message) + if(GetQuestRewardStatus(pQuest->GetQuestId())) + return false; + + // prevent receive reward with quest items in bank + if ( pQuest->HasFlag( QUEST_MANGOS_FLAGS_DELIVER ) ) + { + for(int i = 0; i < QUEST_OBJECTIVES_COUNT; i++) + { + if( pQuest->ReqItemCount[i]!= 0 && + GetItemCount(pQuest->ReqItemId[i]) < pQuest->ReqItemCount[i] ) + { + if(msg) + SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); + return false; + } + } + } + + // prevent receive reward with low money and GetRewOrReqMoney() < 0 + if(pQuest->GetRewOrReqMoney() < 0 && GetMoney() < uint32(-pQuest->GetRewOrReqMoney()) ) + return false; + + return true; +} + +bool Player::CanRewardQuest( Quest const *pQuest, uint32 reward, bool msg ) +{ + // prevent receive reward with quest items in bank or for not completed quest + if(!CanRewardQuest(pQuest,msg)) + return false; + + if ( pQuest->GetRewChoiceItemsCount() > 0 ) + { + if( pQuest->RewChoiceItemId[reward] ) + { + ItemPosCountVec dest; + uint8 res = CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, pQuest->RewChoiceItemId[reward], pQuest->RewChoiceItemCount[reward] ); + if( res != EQUIP_ERR_OK ) + { + SendEquipError( res, NULL, NULL ); + return false; + } + } + } + + if ( pQuest->GetRewItemsCount() > 0 ) + { + for (uint32 i = 0; i < pQuest->GetRewItemsCount(); ++i) + { + if( pQuest->RewItemId[i] ) + { + ItemPosCountVec dest; + uint8 res = CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, pQuest->RewItemId[i], pQuest->RewItemCount[i] ); + if( res != EQUIP_ERR_OK ) + { + SendEquipError( res, NULL, NULL ); + return false; + } + } + } + } + + return true; +} + +void Player::AddQuest( Quest const *pQuest, Object *questGiver ) +{ + uint16 log_slot = FindQuestSlot( 0 ); + assert(log_slot < MAX_QUEST_LOG_SIZE); + + uint32 quest_id = pQuest->GetQuestId(); + + // if not exist then created with set uState==NEW and rewarded=false + QuestStatusData& questStatusData = mQuestStatus[quest_id]; + if (questStatusData.uState != QUEST_NEW) + questStatusData.uState = QUEST_CHANGED; + + // check for repeatable quests status reset + questStatusData.m_status = QUEST_STATUS_INCOMPLETE; + questStatusData.m_explored = false; + + if ( pQuest->HasFlag( QUEST_MANGOS_FLAGS_DELIVER ) ) + { + for(int i = 0; i < QUEST_OBJECTIVES_COUNT; i++) + questStatusData.m_itemcount[i] = 0; + } + + if ( pQuest->HasFlag(QUEST_MANGOS_FLAGS_KILL_OR_CAST | QUEST_MANGOS_FLAGS_SPEAKTO) ) + { + for(int i = 0; i < QUEST_OBJECTIVES_COUNT; i++) + questStatusData.m_creatureOrGOcount[i] = 0; + } + + GiveQuestSourceItem( pQuest ); + AdjustQuestReqItemCount( pQuest ); + + if( pQuest->GetRepObjectiveFaction() ) + SetFactionVisibleForFactionId(pQuest->GetRepObjectiveFaction()); + + uint32 qtime = 0; + if( pQuest->HasFlag( QUEST_MANGOS_FLAGS_TIMED ) ) + { + uint32 limittime = pQuest->GetLimitTime(); + + // shared timed quest + if(questGiver && questGiver->GetTypeId()==TYPEID_PLAYER) + limittime = ((Player*)questGiver)->getQuestStatusMap()[quest_id].m_timer / 1000; + + AddTimedQuest( quest_id ); + questStatusData.m_timer = limittime * 1000; + qtime = static_cast(time(NULL)) + limittime; + } + else + questStatusData.m_timer = 0; + + SetQuestSlot(log_slot, quest_id, qtime); + + //starting initial quest script + if(questGiver && pQuest->GetQuestStartScript()!=0) + sWorld.ScriptsStart(sQuestStartScripts, pQuest->GetQuestStartScript(), questGiver, this); + + UpdateForQuestsGO(); +} + +void Player::CompleteQuest( uint32 quest_id ) +{ + if( quest_id ) + { + SetQuestStatus( quest_id, QUEST_STATUS_COMPLETE ); + + uint16 log_slot = FindQuestSlot( quest_id ); + if( log_slot < MAX_QUEST_LOG_SIZE) + SetQuestSlotState(log_slot,QUEST_STATE_COMPLETE); + + if(Quest const* qInfo = objmgr.GetQuestTemplate(quest_id)) + { + if( qInfo->HasFlag(QUEST_FLAGS_AUTO_REWARDED) ) + RewardQuest(qInfo,0,this,false); + else + SendQuestComplete( quest_id ); + } + } +} + +void Player::IncompleteQuest( uint32 quest_id ) +{ + if( quest_id ) + { + SetQuestStatus( quest_id, QUEST_STATUS_INCOMPLETE ); + + uint16 log_slot = FindQuestSlot( quest_id ); + if( log_slot < MAX_QUEST_LOG_SIZE) + RemoveQuestSlotState(log_slot,QUEST_STATE_COMPLETE); + } +} + +void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver, bool announce ) +{ + uint32 quest_id = pQuest->GetQuestId(); + + for (int i = 0; i < QUEST_OBJECTIVES_COUNT; i++ ) + { + if ( pQuest->ReqItemId[i] ) + DestroyItemCount( pQuest->ReqItemId[i], pQuest->ReqItemCount[i], true); + } + + //if( qInfo->HasSpecialFlag( QUEST_FLAGS_TIMED ) ) + // SetTimedQuest( 0 ); + m_timedquests.erase(pQuest->GetQuestId()); + + if ( pQuest->GetRewChoiceItemsCount() > 0 ) + { + if( pQuest->RewChoiceItemId[reward] ) + { + ItemPosCountVec dest; + if( CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, pQuest->RewChoiceItemId[reward], pQuest->RewChoiceItemCount[reward] ) == EQUIP_ERR_OK ) + { + Item* item = StoreNewItem( dest, pQuest->RewChoiceItemId[reward], true); + SendNewItem(item, pQuest->RewChoiceItemCount[reward], true, false); + } + } + } + + if ( pQuest->GetRewItemsCount() > 0 ) + { + for (uint32 i=0; i < pQuest->GetRewItemsCount(); ++i) + { + if( pQuest->RewItemId[i] ) + { + ItemPosCountVec dest; + if( CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, pQuest->RewItemId[i], pQuest->RewItemCount[i] ) == EQUIP_ERR_OK ) + { + Item* item = StoreNewItem( dest, pQuest->RewItemId[i], true); + SendNewItem(item, pQuest->RewItemCount[i], true, false); + } + } + } + } + + RewardReputation( pQuest ); + + if( pQuest->GetRewSpellCast() > 0 ) + CastSpell( this, pQuest->GetRewSpellCast(), true); + else if( pQuest->GetRewSpell() > 0) + CastSpell( this, pQuest->GetRewSpell(), true); + + uint16 log_slot = FindQuestSlot( quest_id ); + if( log_slot < MAX_QUEST_LOG_SIZE) + SetQuestSlot(log_slot,0); + + QuestStatusData& q_status = mQuestStatus[quest_id]; + + // Not give XP in case already completed once repeatable quest + uint32 XP = q_status.m_rewarded ? 0 : uint32(pQuest->XPValue( this )*sWorld.getRate(RATE_XP_QUEST)); + + if ( getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) ) + GiveXP( XP , NULL ); + else + ModifyMoney( int32(pQuest->GetRewMoneyMaxLevel() * sWorld.getRate(RATE_DROP_MONEY)) ); + + // Give player extra money if GetRewOrReqMoney > 0 and get ReqMoney if negative + ModifyMoney( pQuest->GetRewOrReqMoney() ); + + // title reward + if(pQuest->GetCharTitleId()) + { + if(CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(pQuest->GetCharTitleId())) + SetFlag64(PLAYER__FIELD_KNOWN_TITLES, (uint64(1) << titleEntry->bit_index)); + } + + // Send reward mail + if(pQuest->GetRewMailTemplateId()) + { + MailMessageType mailType; + uint32 senderGuidOrEntry; + switch(questGiver->GetTypeId()) + { + case TYPEID_UNIT: + mailType = MAIL_CREATURE; + senderGuidOrEntry = questGiver->GetEntry(); + break; + case TYPEID_GAMEOBJECT: + mailType = MAIL_GAMEOBJECT; + senderGuidOrEntry = questGiver->GetEntry(); + break; + case TYPEID_ITEM: + mailType = MAIL_ITEM; + senderGuidOrEntry = questGiver->GetEntry(); + break; + case TYPEID_PLAYER: + mailType = MAIL_NORMAL; + senderGuidOrEntry = questGiver->GetGUIDLow(); + break; + default: + mailType = MAIL_NORMAL; + senderGuidOrEntry = GetGUIDLow(); + break; + } + + Loot questMailLoot; + + questMailLoot.FillLoot(pQuest->GetQuestId(), LootTemplates_QuestMail, this); + + // fill mail + MailItemsInfo mi; // item list preparing + + for(size_t i = 0; mi.size() < MAX_MAIL_ITEMS && i < questMailLoot.items.size(); ++i) + { + if(LootItem* lootitem = questMailLoot.LootItemInSlot(i,this)) + { + if(Item* item = Item::CreateItem(lootitem->itemid,lootitem->count,this)) + { + item->SaveToDB(); // save for prevent lost at next mail load, if send fail then item will deleted + mi.AddItem(item->GetGUIDLow(), item->GetEntry(), item); + } + } + } + + for(size_t i = 0; mi.size() < MAX_MAIL_ITEMS && i < questMailLoot.quest_items.size(); ++i) + { + if(LootItem* lootitem = questMailLoot.LootItemInSlot(i+questMailLoot.items.size(),this)) + { + if(Item* item = Item::CreateItem(lootitem->itemid,lootitem->count,this)) + { + item->SaveToDB(); // save for prevent lost at next mail load, if send fail then item will deleted + mi.AddItem(item->GetGUIDLow(), item->GetEntry(), item); + } + } + } + + WorldSession::SendMailTo(this, mailType, MAIL_STATIONERY_NORMAL, senderGuidOrEntry, GetGUIDLow(), "", 0, &mi, 0, 0, MAIL_CHECK_MASK_NONE,pQuest->GetRewMailDelaySecs(),pQuest->GetRewMailTemplateId()); + } + + if(pQuest->IsDaily()) + SetDailyQuestStatus(quest_id); + + if ( !pQuest->IsRepeatable() ) + SetQuestStatus(quest_id, QUEST_STATUS_COMPLETE); + else + SetQuestStatus(quest_id, QUEST_STATUS_NONE); + + q_status.m_rewarded = true; + + if(announce) + SendQuestReward( pQuest, XP, questGiver ); + + if (q_status.uState != QUEST_NEW) q_status.uState = QUEST_CHANGED; +} + +void Player::FailQuest( uint32 quest_id ) +{ + if( quest_id ) + { + IncompleteQuest( quest_id ); + + uint16 log_slot = FindQuestSlot( quest_id ); + if( log_slot < MAX_QUEST_LOG_SIZE) + { + SetQuestSlotTimer(log_slot, 1 ); + SetQuestSlotState(log_slot,QUEST_STATE_FAIL); + } + SendQuestFailed( quest_id ); + } +} + +void Player::FailTimedQuest( uint32 quest_id ) +{ + if( quest_id ) + { + QuestStatusData& q_status = mQuestStatus[quest_id]; + + if (q_status.uState != QUEST_NEW) q_status.uState = QUEST_CHANGED; + q_status.m_timer = 0; + + IncompleteQuest( quest_id ); + + uint16 log_slot = FindQuestSlot( quest_id ); + if( log_slot < MAX_QUEST_LOG_SIZE) + { + SetQuestSlotTimer(log_slot, 1 ); + SetQuestSlotState(log_slot,QUEST_STATE_FAIL); + } + SendQuestTimerFailed( quest_id ); + } +} + +bool Player::SatisfyQuestSkillOrClass( Quest const* qInfo, bool msg ) +{ + int32 zoneOrSort = qInfo->GetZoneOrSort(); + int32 skillOrClass = qInfo->GetSkillOrClass(); + + // skip zone zoneOrSort and 0 case skillOrClass + if( zoneOrSort >= 0 && skillOrClass == 0 ) + return true; + + int32 questSort = -zoneOrSort; + uint8 reqSortClass = ClassByQuestSort(questSort); + + // check class sort cases in zoneOrSort + if( reqSortClass != 0 && getClass() != reqSortClass) + { + if( msg ) + SendCanTakeQuestResponse( INVALIDREASON_DONT_HAVE_REQ ); + return false; + } + + // check class + if( skillOrClass < 0 ) + { + uint8 reqClass = -int32(skillOrClass); + if(getClass() != reqClass) + { + if( msg ) + SendCanTakeQuestResponse( INVALIDREASON_DONT_HAVE_REQ ); + return false; + } + } + // check skill + else if( skillOrClass > 0 ) + { + uint32 reqSkill = skillOrClass; + if( GetSkillValue( reqSkill ) < qInfo->GetRequiredSkillValue() ) + { + if( msg ) + SendCanTakeQuestResponse( INVALIDREASON_DONT_HAVE_REQ ); + return false; + } + } + + return true; +} + +bool Player::SatisfyQuestLevel( Quest const* qInfo, bool msg ) +{ + if( getLevel() < qInfo->GetMinLevel() ) + { + if( msg ) + SendCanTakeQuestResponse( INVALIDREASON_DONT_HAVE_REQ ); + return false; + } + return true; +} + +bool Player::SatisfyQuestLog( bool msg ) +{ + // exist free slot + if( FindQuestSlot(0) < MAX_QUEST_LOG_SIZE ) + return true; + + if( msg ) + { + WorldPacket data( SMSG_QUESTLOG_FULL, 0 ); + GetSession()->SendPacket( &data ); + sLog.outDebug( "WORLD: Sent QUEST_LOG_FULL_MESSAGE" ); + } + return false; +} + +bool Player::SatisfyQuestPreviousQuest( Quest const* qInfo, bool msg ) +{ + // No previous quest (might be first quest in a series) + if( qInfo->prevQuests.empty()) + return true; + + for(Quest::PrevQuests::const_iterator iter = qInfo->prevQuests.begin(); iter != qInfo->prevQuests.end(); ++iter ) + { + uint32 prevId = abs(*iter); + + QuestStatusMap::iterator i_prevstatus = mQuestStatus.find( prevId ); + Quest const* qPrevInfo = objmgr.GetQuestTemplate(prevId); + + if( qPrevInfo && i_prevstatus != mQuestStatus.end() ) + { + // If any of the positive previous quests completed, return true + if( *iter > 0 && i_prevstatus->second.m_rewarded ) + { + // skip one-from-all exclusive group + if(qPrevInfo->GetExclusiveGroup() >= 0) + return true; + + // each-from-all exclusive group ( < 0) + // can be start if only all quests in prev quest exclusive group complited and rewarded + ObjectMgr::ExclusiveQuestGroups::iterator iter = objmgr.mExclusiveQuestGroups.lower_bound(qPrevInfo->GetExclusiveGroup()); + ObjectMgr::ExclusiveQuestGroups::iterator end = objmgr.mExclusiveQuestGroups.upper_bound(qPrevInfo->GetExclusiveGroup()); + + assert(iter!=end); // always must be found if qPrevInfo->ExclusiveGroup != 0 + + for(; iter != end; ++iter) + { + uint32 exclude_Id = iter->second; + + // skip checked quest id, only state of other quests in group is interesting + if(exclude_Id == prevId) + continue; + + QuestStatusMap::iterator i_exstatus = mQuestStatus.find( exclude_Id ); + + // alternative quest from group also must be completed and rewarded(reported) + if( i_exstatus == mQuestStatus.end() || !i_exstatus->second.m_rewarded ) + { + if( msg ) + SendCanTakeQuestResponse( INVALIDREASON_DONT_HAVE_REQ ); + return false; + } + } + return true; + } + // If any of the negative previous quests active, return true + if( *iter < 0 && (i_prevstatus->second.m_status == QUEST_STATUS_INCOMPLETE + || (i_prevstatus->second.m_status == QUEST_STATUS_COMPLETE && !GetQuestRewardStatus(prevId)))) + { + // skip one-from-all exclusive group + if(qPrevInfo->GetExclusiveGroup() >= 0) + return true; + + // each-from-all exclusive group ( < 0) + // can be start if only all quests in prev quest exclusive group active + ObjectMgr::ExclusiveQuestGroups::iterator iter = objmgr.mExclusiveQuestGroups.lower_bound(qPrevInfo->GetExclusiveGroup()); + ObjectMgr::ExclusiveQuestGroups::iterator end = objmgr.mExclusiveQuestGroups.upper_bound(qPrevInfo->GetExclusiveGroup()); + + assert(iter!=end); // always must be found if qPrevInfo->ExclusiveGroup != 0 + + for(; iter != end; ++iter) + { + uint32 exclude_Id = iter->second; + + // skip checked quest id, only state of other quests in group is interesting + if(exclude_Id == prevId) + continue; + + QuestStatusMap::iterator i_exstatus = mQuestStatus.find( exclude_Id ); + + // alternative quest from group also must be active + if( i_exstatus == mQuestStatus.end() || + i_exstatus->second.m_status != QUEST_STATUS_INCOMPLETE && + (i_prevstatus->second.m_status != QUEST_STATUS_COMPLETE || GetQuestRewardStatus(prevId)) ) + { + if( msg ) + SendCanTakeQuestResponse( INVALIDREASON_DONT_HAVE_REQ ); + return false; + } + } + return true; + } + } + } + + // Has only positive prev. quests in non-rewarded state + // and negative prev. quests in non-active state + if( msg ) + SendCanTakeQuestResponse( INVALIDREASON_DONT_HAVE_REQ ); + + return false; +} + +bool Player::SatisfyQuestRace( Quest const* qInfo, bool msg ) +{ + uint32 reqraces = qInfo->GetRequiredRaces(); + if ( reqraces == 0 ) + return true; + if( (reqraces & getRaceMask()) == 0 ) + { + if( msg ) + SendCanTakeQuestResponse( INVALIDREASON_QUEST_FAILED_WRONG_RACE ); + return false; + } + return true; +} + +bool Player::SatisfyQuestReputation( Quest const* qInfo, bool msg ) +{ + uint32 fIdMin = qInfo->GetRequiredMinRepFaction(); //Min required rep + if(fIdMin && GetReputation(fIdMin) < qInfo->GetRequiredMinRepValue()) + { + if( msg ) + SendCanTakeQuestResponse( INVALIDREASON_DONT_HAVE_REQ ); + return false; + } + + uint32 fIdMax = qInfo->GetRequiredMaxRepFaction(); //Max required rep + if(fIdMax && GetReputation(fIdMax) >= qInfo->GetRequiredMaxRepValue()) + { + if( msg ) + SendCanTakeQuestResponse( INVALIDREASON_DONT_HAVE_REQ ); + return false; + } + + return true; +} + +bool Player::SatisfyQuestStatus( Quest const* qInfo, bool msg ) +{ + QuestStatusMap::iterator itr = mQuestStatus.find( qInfo->GetQuestId() ); + if ( itr != mQuestStatus.end() && itr->second.m_status != QUEST_STATUS_NONE ) + { + if( msg ) + SendCanTakeQuestResponse( INVALIDREASON_QUEST_ALREADY_ON ); + return false; + } + return true; +} + +bool Player::SatisfyQuestTimed( Quest const* qInfo, bool msg ) +{ + if ( (find(m_timedquests.begin(), m_timedquests.end(), qInfo->GetQuestId()) != m_timedquests.end()) && qInfo->HasFlag(QUEST_MANGOS_FLAGS_TIMED) ) + { + if( msg ) + SendCanTakeQuestResponse( INVALIDREASON_QUEST_ONLY_ONE_TIMED ); + return false; + } + return true; +} + +bool Player::SatisfyQuestExclusiveGroup( Quest const* qInfo, bool msg ) +{ + // non positive exclusive group, if > 0 then can be start if any other quest in exclusive group already started/completed + if(qInfo->GetExclusiveGroup() <= 0) + return true; + + ObjectMgr::ExclusiveQuestGroups::iterator iter = objmgr.mExclusiveQuestGroups.lower_bound(qInfo->GetExclusiveGroup()); + ObjectMgr::ExclusiveQuestGroups::iterator end = objmgr.mExclusiveQuestGroups.upper_bound(qInfo->GetExclusiveGroup()); + + assert(iter!=end); // always must be found if qInfo->ExclusiveGroup != 0 + + for(; iter != end; ++iter) + { + uint32 exclude_Id = iter->second; + + // skip checked quest id, only state of other quests in group is interesting + if(exclude_Id == qInfo->GetQuestId()) + continue; + + QuestStatusMap::iterator i_exstatus = mQuestStatus.find( exclude_Id ); + + // alternative quest already started or completed + if( i_exstatus != mQuestStatus.end() + && (i_exstatus->second.m_status == QUEST_STATUS_COMPLETE || i_exstatus->second.m_status == QUEST_STATUS_INCOMPLETE) ) + { + if( msg ) + SendCanTakeQuestResponse( INVALIDREASON_DONT_HAVE_REQ ); + return false; + } + } + return true; +} + +bool Player::SatisfyQuestNextChain( Quest const* qInfo, bool msg ) +{ + if(!qInfo->GetNextQuestInChain()) + return true; + + // next quest in chain already started or completed + QuestStatusMap::iterator itr = mQuestStatus.find( qInfo->GetNextQuestInChain() ); + if( itr != mQuestStatus.end() + && (itr->second.m_status == QUEST_STATUS_COMPLETE || itr->second.m_status == QUEST_STATUS_INCOMPLETE) ) + { + if( msg ) + SendCanTakeQuestResponse( INVALIDREASON_DONT_HAVE_REQ ); + return false; + } + + // check for all quests further up the chain + // only necessary if there are quest chains with more than one quest that can be skipped + //return SatisfyQuestNextChain( qInfo->GetNextQuestInChain(), msg ); + return true; +} + +bool Player::SatisfyQuestPrevChain( Quest const* qInfo, bool msg ) +{ + // No previous quest in chain + if( qInfo->prevChainQuests.empty()) + return true; + + for(Quest::PrevChainQuests::const_iterator iter = qInfo->prevChainQuests.begin(); iter != qInfo->prevChainQuests.end(); ++iter ) + { + uint32 prevId = *iter; + + QuestStatusMap::iterator i_prevstatus = mQuestStatus.find( prevId ); + + if( i_prevstatus != mQuestStatus.end() ) + { + // If any of the previous quests in chain active, return false + if( i_prevstatus->second.m_status == QUEST_STATUS_INCOMPLETE + || (i_prevstatus->second.m_status == QUEST_STATUS_COMPLETE && !GetQuestRewardStatus(prevId))) + { + if( msg ) + SendCanTakeQuestResponse( INVALIDREASON_DONT_HAVE_REQ ); + return false; + } + } + + // check for all quests further down the chain + // only necessary if there are quest chains with more than one quest that can be skipped + //if( !SatisfyQuestPrevChain( prevId, msg ) ) + // return false; + } + + // No previous quest in chain active + return true; +} + +bool Player::SatisfyQuestDay( Quest const* qInfo, bool msg ) +{ + if(!qInfo->IsDaily()) + return true; + + bool have_slot = false; + for(uint32 quest_daily_idx = 0; quest_daily_idx < PLAYER_MAX_DAILY_QUESTS; ++quest_daily_idx) + { + uint32 id = GetUInt32Value(PLAYER_FIELD_DAILY_QUESTS_1+quest_daily_idx); + if(qInfo->GetQuestId()==id) + return false; + + if(!id) + have_slot = true; + } + + if(!have_slot) + { + if( msg ) + SendCanTakeQuestResponse( INVALIDREASON_DAILY_QUESTS_REMAINING ); + return false; + } + + return true; +} + +bool Player::GiveQuestSourceItem( Quest const *pQuest ) +{ + uint32 srcitem = pQuest->GetSrcItemId(); + if( srcitem > 0 ) + { + uint32 count = pQuest->GetSrcItemCount(); + if( count <= 0 ) + count = 1; + + ItemPosCountVec dest; + uint8 msg = CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, srcitem, count ); + if( msg == EQUIP_ERR_OK ) + { + Item * item = StoreNewItem(dest, srcitem, true); + SendNewItem(item, count, true, false); + return true; + } + // player already have max amount required item, just report success + else if( msg == EQUIP_ERR_CANT_CARRY_MORE_OF_THIS ) + return true; + else + SendEquipError( msg, NULL, NULL ); + return false; + } + + return true; +} + +bool Player::TakeQuestSourceItem( uint32 quest_id, bool msg ) +{ + Quest const* qInfo = objmgr.GetQuestTemplate(quest_id); + if( qInfo ) + { + uint32 srcitem = qInfo->GetSrcItemId(); + if( srcitem > 0 ) + { + uint32 count = qInfo->GetSrcItemCount(); + if( count <= 0 ) + count = 1; + + // exist one case when destroy source quest item not possible: + // non un-equippable item (equipped non-empty bag, for example) + uint8 res = CanUnequipItems(srcitem,count); + if(res != EQUIP_ERR_OK) + { + if(msg) + SendEquipError( res, NULL, NULL ); + return false; + } + + DestroyItemCount(srcitem, count, true, true); + } + } + return true; +} + +bool Player::GetQuestRewardStatus( uint32 quest_id ) const +{ + Quest const* qInfo = objmgr.GetQuestTemplate(quest_id); + if( qInfo ) + { + // for repeatable quests: rewarded field is set after first reward only to prevent getting XP more than once + QuestStatusMap::const_iterator itr = mQuestStatus.find( quest_id ); + if( itr != mQuestStatus.end() && itr->second.m_status != QUEST_STATUS_NONE + && !qInfo->IsRepeatable() ) + return itr->second.m_rewarded; + + return false; + } + return false; +} + +QuestStatus Player::GetQuestStatus( uint32 quest_id ) const +{ + if( quest_id ) + { + QuestStatusMap::const_iterator itr = mQuestStatus.find( quest_id ); + if( itr != mQuestStatus.end() ) + return itr->second.m_status; + } + return QUEST_STATUS_NONE; +} + +bool Player::CanShareQuest(uint32 quest_id) const +{ + Quest const* qInfo = objmgr.GetQuestTemplate(quest_id); + if( qInfo && qInfo->HasFlag(QUEST_FLAGS_SHARABLE) ) + { + QuestStatusMap::const_iterator itr = mQuestStatus.find( quest_id ); + if( itr != mQuestStatus.end() ) + return itr->second.m_status == QUEST_STATUS_NONE || itr->second.m_status == QUEST_STATUS_INCOMPLETE; + } + return false; +} + +void Player::SetQuestStatus( uint32 quest_id, QuestStatus status ) +{ + Quest const* qInfo = objmgr.GetQuestTemplate(quest_id); + if( qInfo ) + { + if( status == QUEST_STATUS_NONE || status == QUEST_STATUS_INCOMPLETE || status == QUEST_STATUS_COMPLETE ) + { + if( qInfo->HasFlag( QUEST_MANGOS_FLAGS_TIMED ) ) + m_timedquests.erase(qInfo->GetQuestId()); + } + + QuestStatusData& q_status = mQuestStatus[quest_id]; + + q_status.m_status = status; + if (q_status.uState != QUEST_NEW) q_status.uState = QUEST_CHANGED; + } + + UpdateForQuestsGO(); +} + +// not used in MaNGOS, but used in scripting code +uint32 Player::GetReqKillOrCastCurrentCount(uint32 quest_id, int32 entry) +{ + Quest const* qInfo = objmgr.GetQuestTemplate(quest_id); + if( !qInfo ) + return 0; + + for (int j = 0; j < QUEST_OBJECTIVES_COUNT; j++) + if ( qInfo->ReqCreatureOrGOId[j] == entry ) + return mQuestStatus[quest_id].m_creatureOrGOcount[j]; + + return 0; +} + +void Player::AdjustQuestReqItemCount( Quest const* pQuest ) +{ + if ( pQuest->HasFlag( QUEST_MANGOS_FLAGS_DELIVER ) ) + { + for(int i = 0; i < QUEST_OBJECTIVES_COUNT; i++) + { + uint32 reqitemcount = pQuest->ReqItemCount[i]; + if( reqitemcount != 0 ) + { + uint32 quest_id = pQuest->GetQuestId(); + uint32 curitemcount = GetItemCount(pQuest->ReqItemId[i],true); + + QuestStatusData& q_status = mQuestStatus[quest_id]; + q_status.m_itemcount[i] = std::min(curitemcount, reqitemcount); + if (q_status.uState != QUEST_NEW) q_status.uState = QUEST_CHANGED; + } + } + } +} + +uint16 Player::FindQuestSlot( uint32 quest_id ) const +{ + for ( uint16 i = 0; i < MAX_QUEST_LOG_SIZE; i++ ) + if ( GetQuestSlotQuestId(i) == quest_id ) + return i; + + return MAX_QUEST_LOG_SIZE; +} + +void Player::AreaExploredOrEventHappens( uint32 questId ) +{ + if( questId ) + { + uint16 log_slot = FindQuestSlot( questId ); + if( log_slot < MAX_QUEST_LOG_SIZE) + { + QuestStatusData& q_status = mQuestStatus[questId]; + + if(!q_status.m_explored) + { + q_status.m_explored = true; + if (q_status.uState != QUEST_NEW) + q_status.uState = QUEST_CHANGED; + } + } + if( CanCompleteQuest( questId ) ) + CompleteQuest( questId ); + } +} + +//not used in mangosd, function for external script library +void Player::GroupEventHappens( uint32 questId, WorldObject const* pEventObject ) +{ + if( Group *pGroup = GetGroup() ) + { + for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *pGroupGuy = itr->getSource(); + + // for any leave or dead (with not released body) group member at appropriate distance + if( pGroupGuy && pGroupGuy->IsAtGroupRewardDistance(pEventObject) && !pGroupGuy->GetCorpse() ) + pGroupGuy->AreaExploredOrEventHappens(questId); + } + } + else + AreaExploredOrEventHappens(questId); +} + +void Player::ItemAddedQuestCheck( uint32 entry, uint32 count ) +{ + for( int i = 0; i < MAX_QUEST_LOG_SIZE; i++ ) + { + uint32 questid = GetQuestSlotQuestId(i); + if ( questid == 0 ) + continue; + + QuestStatusData& q_status = mQuestStatus[questid]; + + if ( q_status.m_status != QUEST_STATUS_INCOMPLETE ) + continue; + + Quest const* qInfo = objmgr.GetQuestTemplate(questid); + if( !qInfo || !qInfo->HasFlag( QUEST_MANGOS_FLAGS_DELIVER ) ) + continue; + + for (int j = 0; j < QUEST_OBJECTIVES_COUNT; j++) + { + uint32 reqitem = qInfo->ReqItemId[j]; + if ( reqitem == entry ) + { + uint32 reqitemcount = qInfo->ReqItemCount[j]; + uint32 curitemcount = q_status.m_itemcount[j]; + if ( curitemcount < reqitemcount ) + { + uint32 additemcount = ( curitemcount + count <= reqitemcount ? count : reqitemcount - curitemcount); + q_status.m_itemcount[j] += additemcount; + if (q_status.uState != QUEST_NEW) q_status.uState = QUEST_CHANGED; + + SendQuestUpdateAddItem( qInfo, j, additemcount ); + } + if ( CanCompleteQuest( questid ) ) + CompleteQuest( questid ); + return; + } + } + } + UpdateForQuestsGO(); +} + +void Player::ItemRemovedQuestCheck( uint32 entry, uint32 count ) +{ + for( int i = 0; i < MAX_QUEST_LOG_SIZE; i++ ) + { + uint32 questid = GetQuestSlotQuestId(i); + if(!questid) + continue; + Quest const* qInfo = objmgr.GetQuestTemplate(questid); + if ( !qInfo ) + continue; + if( !qInfo->HasFlag( QUEST_MANGOS_FLAGS_DELIVER ) ) + continue; + + for (int j = 0; j < QUEST_OBJECTIVES_COUNT; j++) + { + uint32 reqitem = qInfo->ReqItemId[j]; + if ( reqitem == entry ) + { + QuestStatusData& q_status = mQuestStatus[questid]; + + uint32 reqitemcount = qInfo->ReqItemCount[j]; + uint32 curitemcount; + if( q_status.m_status != QUEST_STATUS_COMPLETE ) + curitemcount = q_status.m_itemcount[j]; + else + curitemcount = GetItemCount(entry,true); + if ( curitemcount < reqitemcount + count ) + { + uint32 remitemcount = ( curitemcount <= reqitemcount ? count : count + reqitemcount - curitemcount); + q_status.m_itemcount[j] = curitemcount - remitemcount; + if (q_status.uState != QUEST_NEW) q_status.uState = QUEST_CHANGED; + + IncompleteQuest( questid ); + } + return; + } + } + } + UpdateForQuestsGO(); +} + +void Player::KilledMonster( uint32 entry, uint64 guid ) +{ + uint32 addkillcount = 1; + for( int i = 0; i < MAX_QUEST_LOG_SIZE; i++ ) + { + uint32 questid = GetQuestSlotQuestId(i); + if(!questid) + continue; + + Quest const* qInfo = objmgr.GetQuestTemplate(questid); + if( !qInfo ) + continue; + // just if !ingroup || !noraidgroup || raidgroup + QuestStatusData& q_status = mQuestStatus[questid]; + if( q_status.m_status == QUEST_STATUS_INCOMPLETE && (!GetGroup() || !GetGroup()->isRaidGroup() || qInfo->GetType() == QUEST_TYPE_RAID)) + { + if( qInfo->HasFlag( QUEST_MANGOS_FLAGS_KILL_OR_CAST) ) + { + for (int j = 0; j < QUEST_OBJECTIVES_COUNT; j++) + { + // skip GO activate objective or none + if(qInfo->ReqCreatureOrGOId[j] <=0) + continue; + + // skip Cast at creature objective + if(qInfo->ReqSpell[j] !=0 ) + continue; + + uint32 reqkill = qInfo->ReqCreatureOrGOId[j]; + + if ( reqkill == entry ) + { + uint32 reqkillcount = qInfo->ReqCreatureOrGOCount[j]; + uint32 curkillcount = q_status.m_creatureOrGOcount[j]; + if ( curkillcount < reqkillcount ) + { + q_status.m_creatureOrGOcount[j] = curkillcount + addkillcount; + if (q_status.uState != QUEST_NEW) q_status.uState = QUEST_CHANGED; + + SendQuestUpdateAddCreatureOrGo( qInfo, guid, j, curkillcount, addkillcount); + } + if ( CanCompleteQuest( questid ) ) + CompleteQuest( questid ); + + // same objective target can be in many active quests, but not in 2 objectives for single quest (code optimization). + continue; + } + } + } + } + } +} + +void Player::CastedCreatureOrGO( uint32 entry, uint64 guid, uint32 spell_id ) +{ + bool isCreature = IS_CREATURE_GUID(guid); + + uint32 addCastCount = 1; + for( int i = 0; i < MAX_QUEST_LOG_SIZE; i++ ) + { + uint32 questid = GetQuestSlotQuestId(i); + if(!questid) + continue; + + Quest const* qInfo = objmgr.GetQuestTemplate(questid); + if ( !qInfo ) + continue; + + QuestStatusData& q_status = mQuestStatus[questid]; + + if ( q_status.m_status == QUEST_STATUS_INCOMPLETE ) + { + if( qInfo->HasFlag( QUEST_MANGOS_FLAGS_KILL_OR_CAST ) ) + { + for (int j = 0; j < QUEST_OBJECTIVES_COUNT; j++) + { + // skip kill creature objective (0) or wrong spell casts + if(qInfo->ReqSpell[j] != spell_id ) + continue; + + uint32 reqTarget = 0; + + if(isCreature) + { + // creature activate objectives + if(qInfo->ReqCreatureOrGOId[j] > 0) + // checked at quest_template loading + reqTarget = qInfo->ReqCreatureOrGOId[j]; + } + else + { + // GO activate objective + if(qInfo->ReqCreatureOrGOId[j] < 0) + // checked at quest_template loading + reqTarget = - qInfo->ReqCreatureOrGOId[j]; + } + + // other not this creature/GO related objectives + if( reqTarget != entry ) + continue; + + uint32 reqCastCount = qInfo->ReqCreatureOrGOCount[j]; + uint32 curCastCount = q_status.m_creatureOrGOcount[j]; + if ( curCastCount < reqCastCount ) + { + q_status.m_creatureOrGOcount[j] = curCastCount + addCastCount; + if (q_status.uState != QUEST_NEW) q_status.uState = QUEST_CHANGED; + + SendQuestUpdateAddCreatureOrGo( qInfo, guid, j, curCastCount, addCastCount); + } + + if ( CanCompleteQuest( questid ) ) + CompleteQuest( questid ); + + // same objective target can be in many active quests, but not in 2 objectives for single quest (code optimization). + break; + } + } + } + } +} + +void Player::TalkedToCreature( uint32 entry, uint64 guid ) +{ + uint32 addTalkCount = 1; + for( int i = 0; i < MAX_QUEST_LOG_SIZE; i++ ) + { + uint32 questid = GetQuestSlotQuestId(i); + if(!questid) + continue; + + Quest const* qInfo = objmgr.GetQuestTemplate(questid); + if ( !qInfo ) + continue; + + QuestStatusData& q_status = mQuestStatus[questid]; + + if ( q_status.m_status == QUEST_STATUS_INCOMPLETE ) + { + if( qInfo->HasFlag( QUEST_MANGOS_FLAGS_KILL_OR_CAST | QUEST_MANGOS_FLAGS_SPEAKTO ) ) + { + for (int j = 0; j < QUEST_OBJECTIVES_COUNT; j++) + { + // skip spell casts and Gameobject objectives + if(qInfo->ReqSpell[j] > 0 || qInfo->ReqCreatureOrGOId[j] < 0) + continue; + + uint32 reqTarget = 0; + + if(qInfo->ReqCreatureOrGOId[j] > 0) // creature activate objectives + // checked at quest_template loading + reqTarget = qInfo->ReqCreatureOrGOId[j]; + else + continue; + + if ( reqTarget == entry ) + { + uint32 reqTalkCount = qInfo->ReqCreatureOrGOCount[j]; + uint32 curTalkCount = q_status.m_creatureOrGOcount[j]; + if ( curTalkCount < reqTalkCount ) + { + q_status.m_creatureOrGOcount[j] = curTalkCount + addTalkCount; + if (q_status.uState != QUEST_NEW) q_status.uState = QUEST_CHANGED; + + SendQuestUpdateAddCreatureOrGo( qInfo, guid, j, curTalkCount, addTalkCount); + } + if ( CanCompleteQuest( questid ) ) + CompleteQuest( questid ); + + // same objective target can be in many active quests, but not in 2 objectives for single quest (code optimization). + continue; + } + } + } + } + } +} + +void Player::MoneyChanged( uint32 count ) +{ + for( int i = 0; i < MAX_QUEST_LOG_SIZE; i++ ) + { + uint32 questid = GetQuestSlotQuestId(i); + if (!questid) + continue; + + Quest const* qInfo = objmgr.GetQuestTemplate(questid); + if( qInfo && qInfo->GetRewOrReqMoney() < 0 ) + { + QuestStatusData& q_status = mQuestStatus[questid]; + + if( q_status.m_status == QUEST_STATUS_INCOMPLETE ) + { + if(int32(count) >= -qInfo->GetRewOrReqMoney()) + { + if ( CanCompleteQuest( questid ) ) + CompleteQuest( questid ); + } + } + else if( q_status.m_status == QUEST_STATUS_COMPLETE ) + { + if(int32(count) < -qInfo->GetRewOrReqMoney()) + IncompleteQuest( questid ); + } + } + } +} + +bool Player::HasQuestForItem( uint32 itemid ) const +{ + for( QuestStatusMap::const_iterator i = mQuestStatus.begin( ); i != mQuestStatus.end( ); ++i ) + { + QuestStatusData const& q_status = i->second; + + if (q_status.m_status == QUEST_STATUS_INCOMPLETE) + { + Quest const* qinfo = objmgr.GetQuestTemplate(i->first); + if(!qinfo) + continue; + + // hide quest if player is in raid-group and quest is no raid quest + if(GetGroup() && GetGroup()->isRaidGroup() && qinfo->GetType() != QUEST_TYPE_RAID) + continue; + + // There should be no mixed ReqItem/ReqSource drop + // This part for ReqItem drop + for (int j = 0; j < QUEST_OBJECTIVES_COUNT; j++) + { + if(itemid == qinfo->ReqItemId[j] && q_status.m_itemcount[j] < qinfo->ReqItemCount[j] ) + return true; + } + // This part - for ReqSource + for (int j = 0; j < QUEST_SOURCE_ITEM_IDS_COUNT; j++) + { + // examined item is a source item + if (qinfo->ReqSourceId[j] == itemid && qinfo->ReqSourceRef[j] > 0 && qinfo->ReqSourceRef[j] <= QUEST_OBJECTIVES_COUNT) + { + uint32 idx = qinfo->ReqSourceRef[j]-1; + + // total count of created ReqItems and SourceItems is less than ReqItemCount + if(qinfo->ReqItemId[idx] != 0 && + q_status.m_itemcount[idx] * qinfo->ReqSourceCount[j] + GetItemCount(itemid,true) < qinfo->ReqItemCount[idx] * qinfo->ReqSourceCount[j]) + return true; + + // total count of casted ReqCreatureOrGOs and SourceItems is less than ReqCreatureOrGOCount + if (qinfo->ReqCreatureOrGOId[idx] != 0) + { + if(q_status.m_creatureOrGOcount[idx] * qinfo->ReqSourceCount[j] + GetItemCount(itemid,true) < qinfo->ReqCreatureOrGOCount[idx] * qinfo->ReqSourceCount[j]) + return true; + } + // spell with SPELL_EFFECT_QUEST_COMPLETE or SPELL_EFFECT_SEND_EVENT (with script) case + else if(qinfo->ReqSpell[idx] != 0) + { + // not casted and need more reagents/item for use. + if(!q_status.m_explored && GetItemCount(itemid,true) < qinfo->ReqSourceCount[j]) + return true; + } + } + } + } + } + return false; +} + +void Player::SendQuestComplete( uint32 quest_id ) +{ + if( quest_id ) + { + WorldPacket data( SMSG_QUESTUPDATE_COMPLETE, 4 ); + data << quest_id; + GetSession()->SendPacket( &data ); + sLog.outDebug( "WORLD: Sent SMSG_QUESTUPDATE_COMPLETE quest = %u", quest_id ); + } +} + +void Player::SendQuestReward( Quest const *pQuest, uint32 XP, Object * questGiver ) +{ + uint32 questid = pQuest->GetQuestId(); + sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_QUEST_COMPLETE quest = %u", questid ); + WorldPacket data( SMSG_QUESTGIVER_QUEST_COMPLETE, (4+4+4+4+4+4+pQuest->GetRewItemsCount()*8) ); + data << questid; + data << uint32(0x03); + + if ( getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) ) + { + data << XP; + data << uint32(pQuest->GetRewOrReqMoney()); + } + else + { + data << uint32(0); + data << uint32(pQuest->GetRewOrReqMoney() + int32(pQuest->GetRewMoneyMaxLevel() * sWorld.getRate(RATE_DROP_MONEY))); + } + data << uint32(0); // new 2.3.0, HonorPoints? + data << uint32( pQuest->GetRewItemsCount() ); // max is 5 + + for (uint32 i = 0; i < pQuest->GetRewItemsCount(); ++i) + { + if ( pQuest->RewItemId[i] > 0 ) + data << pQuest->RewItemId[i] << pQuest->RewItemCount[i]; + else + data << uint32(0) << uint32(0); + } + GetSession()->SendPacket( &data ); + + if (pQuest->GetQuestCompleteScript() != 0) + sWorld.ScriptsStart(sQuestEndScripts, pQuest->GetQuestCompleteScript(), questGiver, this); +} + +void Player::SendQuestFailed( uint32 quest_id ) +{ + if( quest_id ) + { + WorldPacket data( SMSG_QUESTGIVER_QUEST_FAILED, 4 ); + data << quest_id; + GetSession()->SendPacket( &data ); + sLog.outDebug("WORLD: Sent SMSG_QUESTGIVER_QUEST_FAILED"); + } +} + +void Player::SendQuestTimerFailed( uint32 quest_id ) +{ + if( quest_id ) + { + WorldPacket data( SMSG_QUESTUPDATE_FAILEDTIMER, 4 ); + data << quest_id; + GetSession()->SendPacket( &data ); + sLog.outDebug("WORLD: Sent SMSG_QUESTUPDATE_FAILEDTIMER"); + } +} + +void Player::SendCanTakeQuestResponse( uint32 msg ) +{ + WorldPacket data( SMSG_QUESTGIVER_QUEST_INVALID, 4 ); + data << uint32(msg); + GetSession()->SendPacket( &data ); + sLog.outDebug("WORLD: Sent SMSG_QUESTGIVER_QUEST_INVALID"); +} + +void Player::SendPushToPartyResponse( Player *pPlayer, uint32 msg ) +{ + if( pPlayer ) + { + WorldPacket data( MSG_QUEST_PUSH_RESULT, (8+1) ); + data << uint64(pPlayer->GetGUID()); + data << uint8(msg); // valid values: 0-8 + GetSession()->SendPacket( &data ); + sLog.outDebug("WORLD: Sent MSG_QUEST_PUSH_RESULT"); + } +} + +void Player::SendQuestUpdateAddItem( Quest const* pQuest, uint32 item_idx, uint32 count ) +{ + WorldPacket data( SMSG_QUESTUPDATE_ADD_ITEM, (4+4) ); + sLog.outDebug( "WORLD: Sent SMSG_QUESTUPDATE_ADD_ITEM" ); + data << pQuest->ReqItemId[item_idx]; + data << count; + GetSession()->SendPacket( &data ); +} + +void Player::SendQuestUpdateAddCreatureOrGo( Quest const* pQuest, uint64 guid, uint32 creatureOrGO_idx, uint32 old_count, uint32 add_count ) +{ + assert(old_count + add_count < 256 && "mob/GO count store in 8 bits 2^8 = 256 (0..256)"); + + int32 entry = pQuest->ReqCreatureOrGOId[ creatureOrGO_idx ]; + if (entry < 0) + // client expected gameobject template id in form (id|0x80000000) + entry = (-entry) | 0x80000000; + + WorldPacket data( SMSG_QUESTUPDATE_ADD_KILL, (4*4+8) ); + sLog.outDebug( "WORLD: Sent SMSG_QUESTUPDATE_ADD_KILL" ); + data << uint32(pQuest->GetQuestId()); + data << uint32(entry); + data << uint32(old_count + add_count); + data << uint32(pQuest->ReqCreatureOrGOCount[ creatureOrGO_idx ]); + data << uint64(guid); + GetSession()->SendPacket(&data); + + uint16 log_slot = FindQuestSlot( pQuest->GetQuestId() ); + if( log_slot < MAX_QUEST_LOG_SIZE) + SetQuestSlotCounter(log_slot,creatureOrGO_idx,GetQuestSlotCounter(log_slot,creatureOrGO_idx)+add_count); +} + +/*********************************************************/ +/*** LOAD SYSTEM ***/ +/*********************************************************/ + +bool Player::MinimalLoadFromDB( QueryResult *result, uint32 guid ) +{ + bool delete_result = true; + if(!result) + { + // 0 1 2 3 4 5 6 7 8 + result = CharacterDatabase.PQuery("SELECT data, name, position_x, position_y, position_z, map, totaltime, leveltime, at_login FROM characters WHERE guid = '%u'",guid); + if(!result) return false; + } + else delete_result = false; + + Field *fields = result->Fetch(); + + if(!LoadValues( fields[0].GetString())) + { + sLog.outError("ERROR: Player #%d have broken data in `data` field. Can't be loaded.",GUID_LOPART(guid)); + if(delete_result) delete result; + return false; + } + + // overwrite possible wrong/corrupted guid + SetUInt64Value(OBJECT_FIELD_GUID, MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER)); + + m_name = fields[1].GetCppString(); + + Relocate(fields[2].GetFloat(),fields[3].GetFloat(),fields[4].GetFloat()); + SetMapId(fields[5].GetUInt32()); + // the instance id is not needed at character enum + + m_Played_time[0] = fields[6].GetUInt32(); + m_Played_time[1] = fields[7].GetUInt32(); + + m_atLoginFlags = fields[8].GetUInt32(); + + // I don't see these used anywhere .. + /*_LoadGroup(); + + _LoadBoundInstances();*/ + + if (delete_result) delete result; + + for (int i = 0; i < PLAYER_SLOTS_COUNT; i++) + m_items[i] = NULL; + + if( HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST) ) + m_deathState = DEAD; + + return true; +} + +void Player::_LoadDeclinedNames(QueryResult* result) +{ + if(!result) + return; + + if(m_declinedname) + delete m_declinedname; + + m_declinedname = new DeclinedName; + Field *fields = result->Fetch(); + for(int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) + m_declinedname->name[i] = fields[i].GetCppString(); + + delete result; +} + +bool Player::LoadPositionFromDB(uint32& mapid, float& x,float& y,float& z,float& o, bool& in_flight, uint64 guid) +{ + QueryResult *result = CharacterDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map,taxi_path FROM characters WHERE guid = '%u'",GUID_LOPART(guid)); + if(!result) + return false; + + Field *fields = result->Fetch(); + + x = fields[0].GetFloat(); + y = fields[1].GetFloat(); + z = fields[2].GetFloat(); + o = fields[3].GetFloat(); + mapid = fields[4].GetUInt32(); + in_flight = !fields[5].GetCppString().empty(); + + delete result; + return true; +} + +bool Player::LoadValuesArrayFromDB(Tokens& data, uint64 guid) +{ + QueryResult *result = CharacterDatabase.PQuery("SELECT data FROM characters WHERE guid='%u'",GUID_LOPART(guid)); + if( !result ) + return false; + + Field *fields = result->Fetch(); + + data = StrSplit(fields[0].GetCppString(), " "); + + delete result; + + return true; +} + +uint32 Player::GetUInt32ValueFromArray(Tokens const& data, uint16 index) +{ + if(index >= data.size()) + return 0; + + return (uint32)atoi(data[index].c_str()); +} + +float Player::GetFloatValueFromArray(Tokens const& data, uint16 index) +{ + float result; + uint32 temp = Player::GetUInt32ValueFromArray(data,index); + memcpy(&result, &temp, sizeof(result)); + + return result; +} + +uint32 Player::GetUInt32ValueFromDB(uint16 index, uint64 guid) +{ + Tokens data; + if(!LoadValuesArrayFromDB(data,guid)) + return 0; + + return GetUInt32ValueFromArray(data,index); +} + +float Player::GetFloatValueFromDB(uint16 index, uint64 guid) +{ + float result; + uint32 temp = Player::GetUInt32ValueFromDB(index, guid); + memcpy(&result, &temp, sizeof(result)); + + return result; +} + +bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) +{ + //// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 [28] [29] 30 31 32 + //QueryResult *result = CharacterDatabase.PQuery("SELECT guid, account, data, name, race, class, position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, gmstate, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeon_difficulty FROM characters WHERE guid = '%u'", guid); + QueryResult *result = holder->GetResult(PLAYER_LOGIN_QUERY_LOADFROM); + + if(!result) + { + sLog.outError("ERROR: Player (GUID: %u) not found in table `characters`, can't load. ",guid); + return false; + } + + Field *fields = result->Fetch(); + + uint32 dbAccountId = fields[1].GetUInt32(); + + // check if the character's account in the db and the logged in account match. + // player should be able to load/delete character only with correct account! + if( dbAccountId != GetSession()->GetAccountId() ) + { + sLog.outError("ERROR: Player (GUID: %u) loading from wrong account (is: %u, should be: %u)",guid,GetSession()->GetAccountId(),dbAccountId); + delete result; + return false; + } + + Object::_Create( guid, 0, HIGHGUID_PLAYER ); + + m_name = fields[3].GetCppString(); + + // check name limitations + if(!ObjectMgr::IsValidName(m_name) || GetSession()->GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(m_name)) + { + delete result; + CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '%u' WHERE guid ='%u'", uint32(AT_LOGIN_RENAME),guid); + return false; + } + + if(!LoadValues( fields[2].GetString())) + { + sLog.outError("ERROR: Player #%d have broken data in `data` field. Can't be loaded.",GUID_LOPART(guid)); + delete result; + return false; + } + + // overwrite possible wrong/corrupted guid + SetUInt64Value(OBJECT_FIELD_GUID, MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER)); + + // cleanup inventory related item value fields (its will be filled correctly in _LoadInventory) + for(uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; ++slot) + { + SetUInt64Value( (uint16)(PLAYER_FIELD_INV_SLOT_HEAD + (slot * 2) ), 0 ); + SetVisibleItemSlot(slot,NULL); + + if (m_items[slot]) + { + delete m_items[slot]; + m_items[slot] = NULL; + } + } + + // update money limits + if(GetMoney() > MAX_MONEY_AMOUNT) + SetMoney(MAX_MONEY_AMOUNT); + + sLog.outDebug("Load Basic value of player %s is: ", m_name.c_str()); + outDebugValues(); + + m_race = fields[4].GetUInt8(); + //Need to call it to initialize m_team (m_team can be calculated from m_race) + //Other way is to saves m_team into characters table. + setFactionForRace(m_race); + SetCharm(0); + + m_class = fields[5].GetUInt8(); + + PlayerInfo const *info = objmgr.GetPlayerInfo(m_race, m_class); + if(!info) + { + sLog.outError("Player have incorrect race/class pair. Can't be loaded."); + delete result; + return false; + } + + InitPrimaryProffesions(); // to max set before any spell loaded + + uint32 transGUID = fields[24].GetUInt32(); + Relocate(fields[6].GetFloat(),fields[7].GetFloat(),fields[8].GetFloat(),fields[10].GetFloat()); + SetMapId(fields[9].GetUInt32()); + SetDifficulty(fields[32].GetUInt32()); // may be changed in _LoadGroup + + _LoadGroup(holder->GetResult(PLAYER_LOGIN_QUERY_LOADGROUP)); + + // check arena teams integrity + for(uint32 arena_slot = 0; arena_slot < MAX_ARENA_SLOT; ++arena_slot) + { + uint32 arena_team_id = GetArenaTeamId(arena_slot); + if(!arena_team_id) + continue; + + if(ArenaTeam * at = objmgr.GetArenaTeamById(arena_team_id)) + if(at->HaveMember(GetGUID())) + continue; + + // arena team not exist or not member, cleanup fields + for(int j =0; j < 6; ++j) + SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arena_slot * 6 + j, 0); + } + + _LoadBoundInstances(holder->GetResult(PLAYER_LOGIN_QUERY_LOADBOUNDINSTANCES)); + + if(!IsPositionValid()) + { + sLog.outError("ERROR: Player (guidlow %d) have invalid coordinates (X: %f Y: %f Z: %f O: %f). Teleport to default race/class locations.",guid,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation()); + + SetMapId(info->mapId); + Relocate(info->positionX,info->positionY,info->positionZ,0.0f); + + transGUID = 0; + + m_movementInfo.t_x = 0.0f; + m_movementInfo.t_y = 0.0f; + m_movementInfo.t_z = 0.0f; + m_movementInfo.t_o = 0.0f; + } + + // load the player's map here if it's not already loaded + Map *map = GetMap(); + // since the player may not be bound to the map yet, make sure subsequent + // getmap calls won't create new maps + SetInstanceId(map->GetInstanceId()); + + SaveRecallPosition(); + + if (transGUID != 0) + { + m_movementInfo.t_x = fields[20].GetFloat(); + m_movementInfo.t_y = fields[21].GetFloat(); + m_movementInfo.t_z = fields[22].GetFloat(); + m_movementInfo.t_o = fields[23].GetFloat(); + + if( !MaNGOS::IsValidMapCoord( + GetPositionX()+m_movementInfo.t_x,GetPositionY()+m_movementInfo.t_y, + GetPositionZ()+m_movementInfo.t_z,GetOrientation()+m_movementInfo.t_o) || + // transport size limited + m_movementInfo.t_x > 50 || m_movementInfo.t_y > 50 || m_movementInfo.t_z > 50 ) + { + sLog.outError("ERROR: Player (guidlow %d) have invalid transport coordinates (X: %f Y: %f Z: %f O: %f). Teleport to default race/class locations.", + guid,GetPositionX()+m_movementInfo.t_x,GetPositionY()+m_movementInfo.t_y, + GetPositionZ()+m_movementInfo.t_z,GetOrientation()+m_movementInfo.t_o); + + SetMapId(info->mapId); + Relocate(info->positionX,info->positionY,info->positionZ,0.0f); + + m_movementInfo.t_x = 0.0f; + m_movementInfo.t_y = 0.0f; + m_movementInfo.t_z = 0.0f; + m_movementInfo.t_o = 0.0f; + + transGUID = 0; + } + } + + if (transGUID != 0) + { + for (MapManager::TransportSet::iterator iter = MapManager::Instance().m_Transports.begin(); iter != MapManager::Instance().m_Transports.end(); ++iter) + { + if( (*iter)->GetGUIDLow() == transGUID) + { + m_transport = *iter; + m_transport->AddPassenger(this); + SetMapId(m_transport->GetMapId()); + break; + } + } + + if(!m_transport) + { + sLog.outError("ERROR: Player (guidlow %d) have invalid transport guid (%u). Teleport to default race/class locations.", + guid,transGUID); + + SetMapId(info->mapId); + Relocate(info->positionX,info->positionY,info->positionZ,0.0f); + + m_movementInfo.t_x = 0.0f; + m_movementInfo.t_y = 0.0f; + m_movementInfo.t_z = 0.0f; + m_movementInfo.t_o = 0.0f; + + transGUID = 0; + } + } + + time_t now = time(NULL); + time_t logoutTime = time_t(fields[16].GetUInt64()); + + // since last logout (in seconds) + uint64 time_diff = uint64(now - logoutTime); + + // set value, including drunk invisibility detection + // calculate sobering. after 15 minutes logged out, the player will be sober again + float soberFactor; + if(time_diff > 15*MINUTE) + soberFactor = 0; + else + soberFactor = 1-time_diff/(15.0f*MINUTE); + uint16 newDrunkenValue = uint16(soberFactor*(GetUInt32Value(PLAYER_BYTES_3) & 0xFFFE)); + SetDrunkValue(newDrunkenValue); + + m_rest_bonus = fields[15].GetFloat(); + //speed collect rest bonus in offline, in logout, far from tavern, city (section/in hour) + float bubble0 = 0.031; + //speed collect rest bonus in offline, in logout, in tavern, city (section/in hour) + float bubble1 = 0.125; + + if((int32)fields[16].GetUInt32() > 0) + { + float bubble = fields[17].GetUInt32() > 0 + ? bubble1*sWorld.getRate(RATE_REST_OFFLINE_IN_TAVERN_OR_CITY) + : bubble0*sWorld.getRate(RATE_REST_OFFLINE_IN_WILDERNESS); + + SetRestBonus(GetRestBonus()+ time_diff*((float)GetUInt32Value(PLAYER_NEXT_LEVEL_XP)/72000)*bubble); + } + + m_cinematic = fields[12].GetUInt32(); + m_Played_time[0]= fields[13].GetUInt32(); + m_Played_time[1]= fields[14].GetUInt32(); + + m_resetTalentsCost = fields[18].GetUInt32(); + m_resetTalentsTime = time_t(fields[19].GetUInt64()); + + // reserve some flags + uint32 old_safe_flags = GetUInt32Value(PLAYER_FLAGS) & ( PLAYER_FLAGS_HIDE_CLOAK | PLAYER_FLAGS_HIDE_HELM ); + + if( HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GM) ) + SetUInt32Value(PLAYER_FLAGS, 0 | old_safe_flags); + + m_taxi.LoadTaxiMask( fields[11].GetString() ); // must be before InitTaxiNodesForLevel + + uint32 gmstate = fields[25].GetUInt32(); + + m_stableSlots = fields[26].GetUInt32(); + if(m_stableSlots > 2) + { + sLog.outError("Player can have not more 2 stable slots, but have in DB %u",uint32(m_stableSlots)); + m_stableSlots = 2; + } + + m_atLoginFlags = fields[27].GetUInt32(); + + // Honor system + // Update Honor kills data + m_lastHonorUpdateTime = logoutTime; + UpdateHonorFields(); + + m_deathExpireTime = (time_t)fields[30].GetUInt64(); + if(m_deathExpireTime > now+MAX_DEATH_COUNT*DEATH_EXPIRE_STEP) + m_deathExpireTime = now+MAX_DEATH_COUNT*DEATH_EXPIRE_STEP-1; + + std::string taxi_nodes = fields[31].GetCppString(); + + delete result; + + // clear channel spell data (if saved at channel spell casting) + SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, 0); + SetUInt32Value(UNIT_CHANNEL_SPELL,0); + + // clear charm/summon related fields + SetUInt64Value(UNIT_FIELD_CHARM,0); + SetUInt64Value(UNIT_FIELD_SUMMON,0); + SetUInt64Value(UNIT_FIELD_CHARMEDBY,0); + SetUInt64Value(UNIT_FIELD_SUMMONEDBY,0); + SetUInt64Value(UNIT_FIELD_CREATEDBY,0); + + // reset some aura modifiers before aura apply + SetUInt64Value(PLAYER_FARSIGHT, 0); + SetUInt32Value(PLAYER_TRACK_CREATURES, 0 ); + SetUInt32Value(PLAYER_TRACK_RESOURCES, 0 ); + + // reset skill modifiers and set correct unlearn flags + for (uint32 i = 0; i < PLAYER_MAX_SKILLS; i++) + { + SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i),0); + + // set correct unlearn bit + uint32 id = GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF; + if(!id) continue; + + SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(id); + if(!pSkill) continue; + + // enable unlearn button for primary professions only + if (pSkill->categoryId == SKILL_CATEGORY_PROFESSION) + SetUInt32Value(PLAYER_SKILL_INDEX(i), MAKE_PAIR32(id,1)); + else + SetUInt32Value(PLAYER_SKILL_INDEX(i), MAKE_PAIR32(id,0)); + } + + // make sure the unit is considered out of combat for proper loading + ClearInCombat(); + + // make sure the unit is considered not in duel for proper loading + SetUInt64Value(PLAYER_DUEL_ARBITER, 0); + SetUInt32Value(PLAYER_DUEL_TEAM, 0); + + // remember loaded power/health values to restore after stats initialization and modifier applying + uint32 savedHealth = GetHealth(); + uint32 savedPower[MAX_POWERS]; + for(uint32 i = 0; i < MAX_POWERS; ++i) + savedPower[i] = GetPower(Powers(i)); + + // reset stats before loading any modifiers + InitStatsForLevel(); + InitTaxiNodesForLevel(); + + // apply original stats mods before spell loading or item equipment that call before equip _RemoveStatsMods() + + //mails are loaded only when needed ;-) - when player in game click on mailbox. + //_LoadMail(); + + _LoadAuras(holder->GetResult(PLAYER_LOGIN_QUERY_LOADAURAS), time_diff); + + // add ghost flag (must be after aura load: PLAYER_FLAGS_GHOST set in aura) + if( HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST) ) + m_deathState = DEAD; + + _LoadSpells(holder->GetResult(PLAYER_LOGIN_QUERY_LOADSPELLS)); + + // after spell load + InitTalentForLevel(); + learnSkillRewardedSpells(); + + // after spell load, learn rewarded spell if need also + _LoadQuestStatus(holder->GetResult(PLAYER_LOGIN_QUERY_LOADQUESTSTATUS)); + _LoadDailyQuestStatus(holder->GetResult(PLAYER_LOGIN_QUERY_LOADDAILYQUESTSTATUS)); + + _LoadTutorials(holder->GetResult(PLAYER_LOGIN_QUERY_LOADTUTORIALS)); + + // must be before inventory (some items required reputation check) + _LoadReputation(holder->GetResult(PLAYER_LOGIN_QUERY_LOADREPUTATION)); + + _LoadInventory(holder->GetResult(PLAYER_LOGIN_QUERY_LOADINVENTORY), time_diff); + + // update items with duration and realtime + UpdateItemDuration(time_diff, true); + + _LoadActions(holder->GetResult(PLAYER_LOGIN_QUERY_LOADACTIONS)); + + // unread mails and next delivery time, actual mails not loaded + _LoadMailInit(holder->GetResult(PLAYER_LOGIN_QUERY_LOADMAILCOUNT), holder->GetResult(PLAYER_LOGIN_QUERY_LOADMAILDATE)); + + m_social = sSocialMgr.LoadFromDB(holder->GetResult(PLAYER_LOGIN_QUERY_LOADSOCIALLIST), GetGUIDLow()); + + if(!_LoadHomeBind(holder->GetResult(PLAYER_LOGIN_QUERY_LOADHOMEBIND))) + return false; + + // check PLAYER_CHOSEN_TITLE compatibility with PLAYER__FIELD_KNOWN_TITLES + // note: PLAYER__FIELD_KNOWN_TITLES updated at quest status loaded + if(uint32 curTitle = GetUInt32Value(PLAYER_CHOSEN_TITLE)) + { + if(!HasFlag64(PLAYER__FIELD_KNOWN_TITLES,uint64(1) << curTitle)) + SetUInt32Value(PLAYER_CHOSEN_TITLE,0); + } + + // Not finish taxi flight path + if(!m_taxi.LoadTaxiDestinationsFromString(taxi_nodes)) + { + // problems with taxi path loading + TaxiNodesEntry const* nodeEntry = NULL; + if(uint32 node_id = m_taxi.GetTaxiSource()) + nodeEntry = sTaxiNodesStore.LookupEntry(node_id); + + if(!nodeEntry) // don't know taxi start node, to homebind + { + sLog.outError("Character %u have wrong data in taxi destination list, teleport to homebind.",GetGUIDLow()); + SetMapId(m_homebindMapId); + Relocate( m_homebindX, m_homebindY, m_homebindZ,0.0f); + SaveRecallPosition(); // save as recall also to prevent recall and fall from sky + } + else // have start node, to it + { + sLog.outError("Character %u have too short taxi destination list, teleport to original node.",GetGUIDLow()); + SetMapId(nodeEntry->map_id); + Relocate(nodeEntry->x, nodeEntry->y, nodeEntry->z,0.0f); + SaveRecallPosition(); // save as recall also to prevent recall and fall from sky + } + m_taxi.ClearTaxiDestinations(); + } + else if(uint32 node_id = m_taxi.GetTaxiSource()) + { + // save source node as recall coord to prevent recall and fall from sky + TaxiNodesEntry const* nodeEntry = sTaxiNodesStore.LookupEntry(node_id); + assert(nodeEntry); // checked in m_taxi.LoadTaxiDestinationsFromString + m_recallMap = nodeEntry->map_id; + m_recallX = nodeEntry->x; + m_recallY = nodeEntry->y; + m_recallZ = nodeEntry->z; + + // flight will started later + } + + _LoadSpellCooldowns(holder->GetResult(PLAYER_LOGIN_QUERY_LOADSPELLCOOLDOWNS)); + + // Spell code allow apply any auras to dead character in load time in aura/spell/item loading + // Do now before stats re-calculation cleanup for ghost state unexpected auras + if(!isAlive()) + RemoveAllAurasOnDeath(); + + //apply all stat bonuses from items and auras + SetCanModifyStats(true); + UpdateAllStats(); + + // restore remembered power/health values (but not more max values) + SetHealth(savedHealth > GetMaxHealth() ? GetMaxHealth() : savedHealth); + for(uint32 i = 0; i < MAX_POWERS; ++i) + SetPower(Powers(i),savedPower[i] > GetMaxPower(Powers(i)) ? GetMaxPower(Powers(i)) : savedPower[i]); + + sLog.outDebug("The value of player %s after load item and aura is: ", m_name.c_str()); + outDebugValues(); + + // GM state + if(GetSession()->GetSecurity() > SEC_PLAYER) + { + switch(sWorld.getConfig(CONFIG_GM_LOGIN_STATE)) + { + case 0: // disable + break; + case 1: // enable + SetGameMaster(true); + break; + case 2: // save state + if(gmstate) + SetGameMaster(true); + break; + default: + break; + } + } + + //Unmount Player from previous mount, so speed bug with mount is no more... + if(IsMounted()) + { + Unmount(); + RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); + } + + _LoadDeclinedNames(holder->GetResult(PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES)); + + return true; +} + +bool Player::isAllowedToLoot(Creature* creature) +{ + if(Player* recipient = creature->GetLootRecipient()) + { + if (recipient == this) + return true; + if( Group* otherGroup = recipient->GetGroup()) + { + Group* thisGroup = GetGroup(); + if(!thisGroup) + return false; + return thisGroup == otherGroup; + } + return false; + } + else + // prevent other players from looting if the recipient got disconnected + return !creature->hasLootRecipient(); +} + +void Player::_LoadActions(QueryResult *result) +{ + m_actionButtons.clear(); + + //QueryResult *result = CharacterDatabase.PQuery("SELECT button,action,type,misc FROM character_action WHERE guid = '%u' ORDER BY button",GetGUIDLow()); + + if(result) + { + do + { + Field *fields = result->Fetch(); + + uint8 button = fields[0].GetUInt8(); + + addActionButton(button, fields[1].GetUInt16(), fields[2].GetUInt8(), fields[3].GetUInt8()); + + m_actionButtons[button].uState = ACTIONBUTTON_UNCHANGED; + } + while( result->NextRow() ); + + delete result; + } +} + +void Player::_LoadAuras(QueryResult *result, uint32 timediff) +{ + m_Auras.clear(); + for (int i = 0; i < TOTAL_AURAS; i++) + m_modAuras[i].clear(); + + // all aura related fields + for(int i = UNIT_FIELD_AURA; i <= UNIT_FIELD_AURASTATE; ++i) + SetUInt32Value(i, 0); + + //QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,spell,effect_index,amount,maxduration,remaintime,remaincharges FROM character_aura WHERE guid = '%u'",GetGUIDLow()); + + if(result) + { + do + { + Field *fields = result->Fetch(); + uint64 caster_guid = fields[0].GetUInt64(); + uint32 spellid = fields[1].GetUInt32(); + uint32 effindex = fields[2].GetUInt32(); + int32 damage = (int32)fields[3].GetUInt32(); + int32 maxduration = (int32)fields[4].GetUInt32(); + int32 remaintime = (int32)fields[5].GetUInt32(); + int32 remaincharges = (int32)fields[6].GetUInt32(); + + SpellEntry const* spellproto = sSpellStore.LookupEntry(spellid); + if(!spellproto) + { + sLog.outError("Unknown aura (spellid %u, effindex %u), ignore.",spellid,effindex); + continue; + } + + if(effindex >= 3) + { + sLog.outError("Invalid effect index (spellid %u, effindex %u), ignore.",spellid,effindex); + continue; + } + + // negative effects should continue counting down after logout + if (remaintime != -1 && !IsPositiveEffect(spellid, effindex)) + { + if(remaintime <= int32(timediff)) + continue; + + remaintime -= timediff; + } + + // prevent wrong values of remaincharges + if(spellproto->procCharges) + { + if(remaincharges <= 0 || remaincharges > spellproto->procCharges) + remaincharges = spellproto->procCharges; + } + else + remaincharges = -1; + + //do not load single target auras (unless they were cast by the player) + if (caster_guid != GetGUID() && IsSingleTargetSpell(spellproto)) + continue; + + Aura* aura = CreateAura(spellproto, effindex, NULL, this, NULL); + if(!damage) + damage = aura->GetModifier()->m_amount; + aura->SetLoadedState(caster_guid,damage,maxduration,remaintime,remaincharges); + AddAura(aura); + } + while( result->NextRow() ); + + delete result; + } + + if(m_class == CLASS_WARRIOR) + CastSpell(this,SPELL_ID_PASSIVE_BATTLE_STANCE,true); +} + +void Player::LoadCorpse() +{ + if( isAlive() ) + { + ObjectAccessor::Instance().ConvertCorpseForPlayer(GetGUID()); + } + else + { + if(Corpse *corpse = GetCorpse()) + { + ApplyModFlag(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTE_RELEASE_TIMER, corpse && !sMapStore.LookupEntry(corpse->GetMapId())->Instanceable() ); + } + else + { + //Prevent Dead Player login without corpse + ResurrectPlayer(0.5f); + } + } +} + +void Player::_LoadInventory(QueryResult *result, uint32 timediff) +{ + //QueryResult *result = CharacterDatabase.PQuery("SELECT data,bag,slot,item,item_template FROM character_inventory JOIN item_instance ON character_inventory.item = item_instance.guid WHERE character_inventory.guid = '%u' ORDER BY bag,slot", GetGUIDLow()); + std::map bagMap; // fast guid lookup for bags + //NOTE: the "order by `bag`" is important because it makes sure + //the bagMap is filled before items in the bags are loaded + //NOTE2: the "order by `slot`" is needed becaue mainhand weapons are (wrongly?) + //expected to be equipped before offhand items (TODO: fixme) + + uint32 zone = GetZoneId(); + + if (result) + { + std::list problematicItems; + + // prevent items from being added to the queue when stored + m_itemUpdateQueueBlocked = true; + do + { + Field *fields = result->Fetch(); + uint32 bag_guid = fields[1].GetUInt32(); + uint8 slot = fields[2].GetUInt8(); + uint32 item_guid = fields[3].GetUInt32(); + uint32 item_id = fields[4].GetUInt32(); + + ItemPrototype const * proto = objmgr.GetItemPrototype(item_id); + + if(!proto) + { + CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE item = '%u'", item_guid); + CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid = '%u'", item_guid); + sLog.outError( "Player::_LoadInventory: Player %s has an unknown item (id: #%u) in inventory, deleted.", GetName(),item_id ); + continue; + } + + Item *item = NewItemOrBag(proto); + + if(!item->LoadFromDB(item_guid, GetGUID(), result)) + { + sLog.outError( "Player::_LoadInventory: Player %s has broken item (id: #%u) in inventory, deleted.", GetName(),item_id ); + CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE item = '%u'", item_guid); + item->FSetState(ITEM_REMOVED); + item->SaveToDB(); // it also deletes item object ! + continue; + } + + // not allow have in alive state item limited to another map/zone + if(isAlive() && item->IsLimitedToAnotherMapOrZone(GetMapId(),zone) ) + { + CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE item = '%u'", item_guid); + item->FSetState(ITEM_REMOVED); + item->SaveToDB(); // it also deletes item object ! + continue; + } + + // "Conjured items disappear if you are logged out for more than 15 minutes" + if ((timediff > 15*60) && (item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_CONJURED))) + { + CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE item = '%u'", item_guid); + item->FSetState(ITEM_REMOVED); + item->SaveToDB(); // it also deletes item object ! + continue; + } + + bool success = true; + + if (!bag_guid) + { + // the item is not in a bag + item->SetContainer( NULL ); + item->SetSlot(slot); + + if( IsInventoryPos( INVENTORY_SLOT_BAG_0, slot ) ) + { + ItemPosCountVec dest; + if( CanStoreItem( INVENTORY_SLOT_BAG_0, slot, dest, item, false ) == EQUIP_ERR_OK ) + item = StoreItem(dest, item, true); + else + success = false; + } + else if( IsEquipmentPos( INVENTORY_SLOT_BAG_0, slot ) ) + { + uint16 dest; + if( CanEquipItem( slot, dest, item, false, false ) == EQUIP_ERR_OK ) + QuickEquipItem(dest, item); + else + success = false; + } + else if( IsBankPos( INVENTORY_SLOT_BAG_0, slot ) ) + { + ItemPosCountVec dest; + if( CanBankItem( INVENTORY_SLOT_BAG_0, slot, dest, item, false, false ) == EQUIP_ERR_OK ) + item = BankItem(dest, item, true); + else + success = false; + } + + if(success) + { + // store bags that may contain items in them + if(item->IsBag() && IsBagPos(item->GetPos())) + bagMap[item_guid] = (Bag*)item; + } + } + else + { + item->SetSlot(NULL_SLOT); + // the item is in a bag, find the bag + std::map::iterator itr = bagMap.find(bag_guid); + if(itr != bagMap.end()) + itr->second->StoreItem(slot, item, true ); + else + success = false; + } + + // item's state may have changed after stored + if (success) + item->SetState(ITEM_UNCHANGED, this); + else + { + sLog.outError("Player::_LoadInventory: Player %s has item (GUID: %u Entry: %u) can't be loaded to inventory (Bag GUID: %u Slot: %u) by some reason, will send by mail.", GetName(),item_guid, item_id, bag_guid, slot); + CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE item = '%u'", item_guid); + problematicItems.push_back(item); + } + } while (result->NextRow()); + + delete result; + m_itemUpdateQueueBlocked = false; + + // send by mail problematic items + while(!problematicItems.empty()) + { + // fill mail + MailItemsInfo mi; // item list prepering + + for(int i = 0; !problematicItems.empty() && i < MAX_MAIL_ITEMS; ++i) + { + Item* item = problematicItems.front(); + problematicItems.pop_front(); + + mi.AddItem(item->GetGUIDLow(), item->GetEntry(), item); + } + + std::string subject = GetSession()->GetMangosString(LANG_NOT_EQUIPPED_ITEM); + + WorldSession::SendMailTo(this, MAIL_NORMAL, MAIL_STATIONERY_GM, GetGUIDLow(), GetGUIDLow(), subject, 0, &mi, 0, 0, MAIL_CHECK_MASK_NONE); + } + } + //if(isAlive()) + _ApplyAllItemMods(); +} + +// load mailed item which should receive current player +void Player::_LoadMailedItems(Mail *mail) +{ + QueryResult* result = CharacterDatabase.PQuery("SELECT item_guid, item_template FROM mail_items WHERE mail_id='%u'", mail->messageID); + if(!result) + return; + + do + { + Field *fields = result->Fetch(); + uint32 item_guid_low = fields[0].GetUInt32(); + uint32 item_template = fields[1].GetUInt32(); + + mail->AddItem(item_guid_low, item_template); + + ItemPrototype const *proto = objmgr.GetItemPrototype(item_template); + + if(!proto) + { + sLog.outError( "Player %u have unknown item_template (ProtoType) in mailed items(GUID: %u template: %u) in mail (%u), deleted.", GetGUIDLow(), item_guid_low, item_template,mail->messageID); + CharacterDatabase.PExecute("DELETE FROM mail_items WHERE item_guid = '%u'", item_guid_low); + CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid = '%u'", item_guid_low); + continue; + } + + Item *item = NewItemOrBag(proto); + + if(!item->LoadFromDB(item_guid_low, 0)) + { + sLog.outError( "Player::_LoadMailedItems - Item in mail (%u) doesn't exist !!!! - item guid: %u, deleted from mail", mail->messageID, item_guid_low); + CharacterDatabase.PExecute("DELETE FROM mail_items WHERE item_guid = '%u'", item_guid_low); + item->FSetState(ITEM_REMOVED); + item->SaveToDB(); // it also deletes item object ! + continue; + } + + AddMItem(item); + } while (result->NextRow()); + + delete result; +} + +void Player::_LoadMailInit(QueryResult *resultUnread, QueryResult *resultDelivery) +{ + //set a count of unread mails + //QueryResult *resultMails = CharacterDatabase.PQuery("SELECT COUNT(id) FROM mail WHERE receiver = '%u' AND (checked & 1)=0 AND deliver_time <= '" I64FMTD "'", GUID_LOPART(playerGuid),(uint64)cTime); + if (resultUnread) + { + Field *fieldMail = resultUnread->Fetch(); + unReadMails = fieldMail[0].GetUInt8(); + delete resultUnread; + } + + // store nearest delivery time (it > 0 and if it < current then at next player update SendNewMaill will be called) + //resultMails = CharacterDatabase.PQuery("SELECT MIN(deliver_time) FROM mail WHERE receiver = '%u' AND (checked & 1)=0", GUID_LOPART(playerGuid)); + if (resultDelivery) + { + Field *fieldMail = resultDelivery->Fetch(); + m_nextMailDelivereTime = (time_t)fieldMail[0].GetUInt64(); + delete resultDelivery; + } +} + +void Player::_LoadMail() +{ + m_mail.clear(); + //mails are in right order 0 1 2 3 4 5 6 7 8 9 10 11 12 13 + QueryResult *result = CharacterDatabase.PQuery("SELECT id,messageType,sender,receiver,subject,itemTextId,has_items,expire_time,deliver_time,money,cod,checked,stationery,mailTemplateId FROM mail WHERE receiver = '%u' ORDER BY id DESC",GetGUIDLow()); + if(result) + { + do + { + Field *fields = result->Fetch(); + Mail *m = new Mail; + m->messageID = fields[0].GetUInt32(); + m->messageType = fields[1].GetUInt8(); + m->sender = fields[2].GetUInt32(); + m->receiver = fields[3].GetUInt32(); + m->subject = fields[4].GetCppString(); + m->itemTextId = fields[5].GetUInt32(); + bool has_items = fields[6].GetBool(); + m->expire_time = (time_t)fields[7].GetUInt64(); + m->deliver_time = (time_t)fields[8].GetUInt64(); + m->money = fields[9].GetUInt32(); + m->COD = fields[10].GetUInt32(); + m->checked = fields[11].GetUInt32(); + m->stationery = fields[12].GetUInt8(); + m->mailTemplateId = fields[13].GetInt16(); + + if(m->mailTemplateId && !sMailTemplateStore.LookupEntry(m->mailTemplateId)) + { + sLog.outError( "Player::_LoadMail - Mail (%u) have not existed MailTemplateId (%u), remove at load", m->messageID, m->mailTemplateId); + m->mailTemplateId = 0; + } + + m->state = MAIL_STATE_UNCHANGED; + + if (has_items) + _LoadMailedItems(m); + + m_mail.push_back(m); + } while( result->NextRow() ); + delete result; + } + m_mailsLoaded = true; +} + +void Player::LoadPet() +{ + //fixme: the pet should still be loaded if the player is not in world + // just not added to the map + if(IsInWorld()) + { + Pet *pet = new Pet; + if(!pet->LoadPetFromDB(this,0,0,true)) + delete pet; + } +} + +void Player::_LoadQuestStatus(QueryResult *result) +{ + mQuestStatus.clear(); + + uint32 slot = 0; + + //// 0 1 2 3 4 5 6 7 8 9 10 11 12 + //QueryResult *result = CharacterDatabase.PQuery("SELECT quest, status, rewarded, explored, timer, mobcount1, mobcount2, mobcount3, mobcount4, itemcount1, itemcount2, itemcount3, itemcount4 FROM character_queststatus WHERE guid = '%u'", GetGUIDLow()); + + if(result) + { + do + { + Field *fields = result->Fetch(); + + uint32 quest_id = fields[0].GetUInt32(); + // used to be new, no delete? + Quest const* pQuest = objmgr.GetQuestTemplate(quest_id); + if( pQuest ) + { + // find or create + QuestStatusData& questStatusData = mQuestStatus[quest_id]; + + uint32 qstatus = fields[1].GetUInt32(); + if(qstatus < MAX_QUEST_STATUS) + questStatusData.m_status = QuestStatus(qstatus); + else + { + questStatusData.m_status = QUEST_STATUS_NONE; + sLog.outError("Player %s have invalid quest %d status (%d), replaced by QUEST_STATUS_NONE(0).",GetName(),quest_id,qstatus); + } + + questStatusData.m_rewarded = ( fields[2].GetUInt8() > 0 ); + questStatusData.m_explored = ( fields[3].GetUInt8() > 0 ); + + time_t quest_time = time_t(fields[4].GetUInt64()); + + if( pQuest->HasFlag( QUEST_MANGOS_FLAGS_TIMED ) && !GetQuestRewardStatus(quest_id) && questStatusData.m_status != QUEST_STATUS_NONE ) + { + AddTimedQuest( quest_id ); + + if (quest_time <= sWorld.GetGameTime()) + questStatusData.m_timer = 1; + else + questStatusData.m_timer = (quest_time - sWorld.GetGameTime()) * 1000; + } + else + quest_time = 0; + + questStatusData.m_creatureOrGOcount[0] = fields[5].GetUInt32(); + questStatusData.m_creatureOrGOcount[1] = fields[6].GetUInt32(); + questStatusData.m_creatureOrGOcount[2] = fields[7].GetUInt32(); + questStatusData.m_creatureOrGOcount[3] = fields[8].GetUInt32(); + questStatusData.m_itemcount[0] = fields[9].GetUInt32(); + questStatusData.m_itemcount[1] = fields[10].GetUInt32(); + questStatusData.m_itemcount[2] = fields[11].GetUInt32(); + questStatusData.m_itemcount[3] = fields[12].GetUInt32(); + + questStatusData.uState = QUEST_UNCHANGED; + + // add to quest log + if( slot < MAX_QUEST_LOG_SIZE && + ( questStatusData.m_status==QUEST_STATUS_INCOMPLETE || + questStatusData.m_status==QUEST_STATUS_COMPLETE && !questStatusData.m_rewarded ) ) + { + SetQuestSlot(slot,quest_id,quest_time); + + if(questStatusData.m_status == QUEST_STATUS_COMPLETE) + SetQuestSlotState(slot,QUEST_STATE_COMPLETE); + + for(uint8 idx = 0; idx < QUEST_OBJECTIVES_COUNT; ++idx) + if(questStatusData.m_creatureOrGOcount[idx]) + SetQuestSlotCounter(slot,idx,questStatusData.m_creatureOrGOcount[idx]); + + ++slot; + } + + if(questStatusData.m_rewarded) + { + // learn rewarded spell if unknown + learnQuestRewardedSpells(pQuest); + + // set rewarded title if any + if(pQuest->GetCharTitleId()) + { + if(CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(pQuest->GetCharTitleId())) + SetFlag64(PLAYER__FIELD_KNOWN_TITLES, (uint64(1) << titleEntry->bit_index)); + } + } + + sLog.outDebug("Quest status is {%u} for quest {%u} for player (GUID: %u)", questStatusData.m_status, quest_id, GetGUIDLow()); + } + } + while( result->NextRow() ); + + delete result; + } + + // clear quest log tail + for ( uint16 i = slot; i < MAX_QUEST_LOG_SIZE; ++i ) + SetQuestSlot(i,0); +} + +void Player::_LoadDailyQuestStatus(QueryResult *result) +{ + for(uint32 quest_daily_idx = 0; quest_daily_idx < PLAYER_MAX_DAILY_QUESTS; ++quest_daily_idx) + SetUInt32Value(PLAYER_FIELD_DAILY_QUESTS_1+quest_daily_idx,0); + + //QueryResult *result = CharacterDatabase.PQuery("SELECT quest,time FROM character_queststatus_daily WHERE guid = '%u'", GetGUIDLow()); + + if(result) + { + uint32 quest_daily_idx = 0; + + do + { + if(quest_daily_idx >= PLAYER_MAX_DAILY_QUESTS) // max amount with exist data in query + { + sLog.outError("Player (GUID: %u) have more 25 daily quest records in `charcter_queststatus_daily`",GetGUIDLow()); + break; + } + + Field *fields = result->Fetch(); + + uint32 quest_id = fields[0].GetUInt32(); + + // save _any_ from daily quest times (it must be after last reset anyway) + m_lastDailyQuestTime = (time_t)fields[1].GetUInt64(); + + Quest const* pQuest = objmgr.GetQuestTemplate(quest_id); + if( !pQuest ) + continue; + + SetUInt32Value(PLAYER_FIELD_DAILY_QUESTS_1+quest_daily_idx,quest_id); + ++quest_daily_idx; + + sLog.outDebug("Daily quest {%u} cooldown for player (GUID: %u)", quest_id, GetGUIDLow()); + } + while( result->NextRow() ); + + delete result; + } + + m_DailyQuestChanged = false; +} + +void Player::_LoadReputation(QueryResult *result) +{ + m_factions.clear(); + + // Set initial reputations (so everything is nifty before DB data load) + SetInitialFactions(); + + //QueryResult *result = CharacterDatabase.PQuery("SELECT faction,standing,flags FROM character_reputation WHERE guid = '%u'",GetGUIDLow()); + + if(result) + { + do + { + Field *fields = result->Fetch(); + + FactionEntry const *factionEntry = sFactionStore.LookupEntry(fields[0].GetUInt32()); + if( factionEntry && (factionEntry->reputationListID >= 0)) + { + FactionState* faction = &m_factions[factionEntry->reputationListID]; + + // update standing to current + faction->Standing = int32(fields[1].GetUInt32()); + + uint32 dbFactionFlags = fields[2].GetUInt32(); + + if( dbFactionFlags & FACTION_FLAG_VISIBLE ) + SetFactionVisible(faction); // have internal checks for forced invisibility + + if( dbFactionFlags & FACTION_FLAG_INACTIVE) + SetFactionInactive(faction,true); // have internal checks for visibility requirement + + if( dbFactionFlags & FACTION_FLAG_AT_WAR ) // DB at war + SetFactionAtWar(faction,true); // have internal checks for FACTION_FLAG_PEACE_FORCED + else // DB not at war + { + // allow remove if visible (and then not FACTION_FLAG_INVISIBLE_FORCED or FACTION_FLAG_HIDDEN) + if( faction->Flags & FACTION_FLAG_VISIBLE ) + SetFactionAtWar(faction,false); // have internal checks for FACTION_FLAG_PEACE_FORCED + } + + // set atWar for hostile + if(GetReputationRank(factionEntry) <= REP_HOSTILE) + SetFactionAtWar(faction,true); + + // reset changed flag if values similar to saved in DB + if(faction->Flags==dbFactionFlags) + faction->Changed = false; + } + } + while( result->NextRow() ); + + delete result; + } +} + +void Player::_LoadSpells(QueryResult *result) +{ + for (PlayerSpellMap::iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr) + delete itr->second; + m_spells.clear(); + + //QueryResult *result = CharacterDatabase.PQuery("SELECT spell,slot,active FROM character_spell WHERE guid = '%u'",GetGUIDLow()); + + if(result) + { + do + { + Field *fields = result->Fetch(); + + addSpell(fields[0].GetUInt16(), fields[2].GetBool(), false, true, fields[1].GetUInt16(), fields[3].GetBool()); + } + while( result->NextRow() ); + + delete result; + } +} + +void Player::_LoadTutorials(QueryResult *result) +{ + //QueryResult *result = CharacterDatabase.PQuery("SELECT tut0,tut1,tut2,tut3,tut4,tut5,tut6,tut7 FROM character_tutorial WHERE account = '%u' AND realmid = '%u'", GetAccountId(), realmid); + + if(result) + { + do + { + Field *fields = result->Fetch(); + + for (int iI=0; iI<8; iI++) + m_Tutorials[iI] = fields[iI].GetUInt32(); + } + while( result->NextRow() ); + + delete result; + } + + m_TutorialsChanged = false; +} + +void Player::_LoadGroup(QueryResult *result) +{ + //QueryResult *result = CharacterDatabase.PQuery("SELECT leaderGuid FROM group_member WHERE memberGuid='%u'", GetGUIDLow()); + if(result) + { + uint64 leaderGuid = MAKE_NEW_GUID((*result)[0].GetUInt32(), 0, HIGHGUID_PLAYER); + delete result; + Group* group = objmgr.GetGroupByLeader(leaderGuid); + if(group) + { + uint8 subgroup = group->GetMemberGroup(GetGUID()); + SetGroup(group, subgroup); + if(getLevel() >= LEVELREQUIREMENT_HEROIC) + { + // the group leader may change the instance difficulty while the player is offline + SetDifficulty(group->GetDifficulty()); + } + } + } +} + +void Player::_LoadBoundInstances(QueryResult *result) +{ + for(uint8 i = 0; i < TOTAL_DIFFICULTIES; i++) + m_boundInstances[i].clear(); + + Group *group = GetGroup(); + + //QueryResult *result = CharacterDatabase.PQuery("SELECT id, permanent, map, difficulty, resettime FROM character_instance LEFT JOIN instance ON instance = id WHERE guid = '%u'", GUID_LOPART(m_guid)); + if(result) + { + do + { + Field *fields = result->Fetch(); + bool perm = fields[1].GetBool(); + uint32 mapId = fields[2].GetUInt32(); + uint32 instanceId = fields[0].GetUInt32(); + uint8 difficulty = fields[3].GetUInt8(); + time_t resetTime = (time_t)fields[4].GetUInt64(); + // the resettime for normal instances is only saved when the InstanceSave is unloaded + // so the value read from the DB may be wrong here but only if the InstanceSave is loaded + // and in that case it is not used + + if(!perm && group) + { + sLog.outError("_LoadBoundInstances: player %s(%d) is in group %d but has a non-permanent character bind to map %d,%d,%d", GetName(), GetGUIDLow(), GUID_LOPART(group->GetLeaderGUID()), mapId, instanceId, difficulty); + CharacterDatabase.PExecute("DELETE FROM character_instance WHERE guid = '%d' AND instance = '%d'", GetGUIDLow(), instanceId); + continue; + } + + // since non permanent binds are always solo bind, they can always be reset + InstanceSave *save = sInstanceSaveManager.AddInstanceSave(mapId, instanceId, difficulty, resetTime, !perm, true); + if(save) BindToInstance(save, perm, true); + } while(result->NextRow()); + delete result; + } +} + +InstancePlayerBind* Player::GetBoundInstance(uint32 mapid, uint8 difficulty) +{ + // some instances only have one difficulty + const MapEntry* entry = sMapStore.LookupEntry(mapid); + if(!entry || !entry->SupportsHeroicMode()) difficulty = DIFFICULTY_NORMAL; + + BoundInstancesMap::iterator itr = m_boundInstances[difficulty].find(mapid); + if(itr != m_boundInstances[difficulty].end()) + return &itr->second; + else + return NULL; +} + +void Player::UnbindInstance(uint32 mapid, uint8 difficulty, bool unload) +{ + BoundInstancesMap::iterator itr = m_boundInstances[difficulty].find(mapid); + UnbindInstance(itr, difficulty, unload); +} + +void Player::UnbindInstance(BoundInstancesMap::iterator &itr, uint8 difficulty, bool unload) +{ + if(itr != m_boundInstances[difficulty].end()) + { + if(!unload) CharacterDatabase.PExecute("DELETE FROM character_instance WHERE guid = '%u' AND instance = '%u'", GetGUIDLow(), itr->second.save->GetInstanceId()); + itr->second.save->RemovePlayer(this); // save can become invalid + m_boundInstances[difficulty].erase(itr++); + } +} + +InstancePlayerBind* Player::BindToInstance(InstanceSave *save, bool permanent, bool load) +{ + if(save) + { + InstancePlayerBind& bind = m_boundInstances[save->GetDifficulty()][save->GetMapId()]; + if(bind.save) + { + // update the save when the group kills a boss + if(permanent != bind.perm || save != bind.save) + if(!load) CharacterDatabase.PExecute("UPDATE character_instance SET instance = '%u', permanent = '%u' WHERE guid = '%u' AND instance = '%u'", save->GetInstanceId(), permanent, GetGUIDLow(), bind.save->GetInstanceId()); + } + else + if(!load) CharacterDatabase.PExecute("INSERT INTO character_instance (guid, instance, permanent) VALUES ('%u', '%u', '%u')", GetGUIDLow(), save->GetInstanceId(), permanent); + + if(bind.save != save) + { + if(bind.save) bind.save->RemovePlayer(this); + save->AddPlayer(this); + } + + if(permanent) save->SetCanReset(false); + + bind.save = save; + bind.perm = permanent; + if(!load) sLog.outDebug("Player::BindToInstance: %s(%d) is now bound to map %d, instance %d, difficulty %d", GetName(), GetGUIDLow(), save->GetMapId(), save->GetInstanceId(), save->GetDifficulty()); + return &bind; + } + else + return NULL; +} + +void Player::SendRaidInfo() +{ + WorldPacket data(SMSG_RAID_INSTANCE_INFO, 4); + + uint32 counter = 0, i; + for(i = 0; i < TOTAL_DIFFICULTIES; i++) + for (BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end(); itr++) + if(itr->second.perm) counter++; + + data << counter; + for(i = 0; i < TOTAL_DIFFICULTIES; i++) + { + for (BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end(); itr++) + { + if(itr->second.perm) + { + InstanceSave *save = itr->second.save; + data << (save->GetMapId()); + data << (uint32)(save->GetResetTime() - time(NULL)); + data << save->GetInstanceId(); + data << uint32(counter); + counter--; + } + } + } + GetSession()->SendPacket(&data); +} + +/* +- called on every successful teleportation to a map +*/ +void Player::SendSavedInstances() +{ + bool hasBeenSaved = false; + WorldPacket data; + + for(uint8 i = 0; i < TOTAL_DIFFICULTIES; i++) + { + for (BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end(); ++itr) + { + if(itr->second.perm) // only permanent binds are sent + { + hasBeenSaved = true; + break; + } + } + } + + //Send opcode 811. true or flase means, whether you have current raid/heroic instances + data.Initialize(SMSG_UPDATE_INSTANCE_OWNERSHIP); + data << uint32(hasBeenSaved); + GetSession()->SendPacket(&data); + + if(!hasBeenSaved) + return; + + for(uint8 i = 0; i < TOTAL_DIFFICULTIES; i++) + { + for (BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end(); ++itr) + { + if(itr->second.perm) + { + data.Initialize(SMSG_UPDATE_LAST_INSTANCE); + data << uint32(itr->second.save->GetMapId()); + GetSession()->SendPacket(&data); + } + } + } +} + +/// convert the player's binds to the group +void Player::ConvertInstancesToGroup(Player *player, Group *group, uint64 player_guid) +{ + bool has_binds = false; + bool has_solo = false; + + if(player) { player_guid = player->GetGUID(); if(!group) group = player->GetGroup(); } + assert(player_guid); + + // copy all binds to the group, when changing leader it's assumed the character + // will not have any solo binds + + if(player) + { + for(uint8 i = 0; i < TOTAL_DIFFICULTIES; i++) + { + for (BoundInstancesMap::iterator itr = player->m_boundInstances[i].begin(); itr != player->m_boundInstances[i].end();) + { + has_binds = true; + if(group) group->BindToInstance(itr->second.save, itr->second.perm, true); + // permanent binds are not removed + if(!itr->second.perm) + { + player->UnbindInstance(itr, i, true); // increments itr + has_solo = true; + } + else + ++itr; + } + } + } + + // if the player's not online we don't know what binds it has + if(!player || !group || has_binds) CharacterDatabase.PExecute("INSERT INTO group_instance SELECT guid, instance, permanent FROM character_instance WHERE guid = '%u'", GUID_LOPART(player_guid)); + // the following should not get executed when changing leaders + if(!player || has_solo) CharacterDatabase.PExecute("DELETE FROM character_instance WHERE guid = '%d' AND permanent = 0", GUID_LOPART(player_guid)); +} + +bool Player::_LoadHomeBind(QueryResult *result) +{ + bool ok = false; + //QueryResult *result = CharacterDatabase.PQuery("SELECT map,zone,position_x,position_y,position_z FROM character_homebind WHERE guid = '%u'", GUID_LOPART(playerGuid)); + if (result) + { + Field *fields = result->Fetch(); + m_homebindMapId = fields[0].GetUInt32(); + m_homebindZoneId = fields[1].GetUInt16(); + m_homebindX = fields[2].GetFloat(); + m_homebindY = fields[3].GetFloat(); + m_homebindZ = fields[4].GetFloat(); + delete result; + + // accept saved data only for valid position (and non instanceable) + if( MapManager::IsValidMapCoord(m_homebindMapId,m_homebindX,m_homebindY,m_homebindZ) && + !sMapStore.LookupEntry(m_homebindMapId)->Instanceable() ) + { + ok = true; + } + else + CharacterDatabase.PExecute("DELETE FROM character_homebind WHERE guid = '%u'", GetGUIDLow()); + } + + if(!ok) + { + PlayerInfo const *info = objmgr.GetPlayerInfo(getRace(), getClass()); + if(!info) return false; + + m_homebindMapId = info->mapId; + m_homebindZoneId = info->zoneId; + m_homebindX = info->positionX; + m_homebindY = info->positionY; + m_homebindZ = info->positionZ; + + CharacterDatabase.PExecute("INSERT INTO character_homebind (guid,map,zone,position_x,position_y,position_z) VALUES ('%u', '%u', '%u', '%f', '%f', '%f')", GetGUIDLow(), m_homebindMapId, (uint32)m_homebindZoneId, m_homebindX, m_homebindY, m_homebindZ); + } + + DEBUG_LOG("Setting player home position: mapid is: %u, zoneid is %u, X is %f, Y is %f, Z is %f\n", + m_homebindMapId, m_homebindZoneId, m_homebindX, m_homebindY, m_homebindZ); + + return true; +} + +/*********************************************************/ +/*** SAVE SYSTEM ***/ +/*********************************************************/ + +void Player::SaveToDB() +{ + // delay auto save at any saves (manual, in code, or autosave) + m_nextSave = sWorld.getConfig(CONFIG_INTERVAL_SAVE); + + // first save/honor gain after midnight will also update the player's honor fields + UpdateHonorFields(); + + // Must saved before enter into BattleGround + if(InBattleGround()) + return; + + int is_save_resting = HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) ? 1 : 0; + //save, far from tavern/city + //save, but in tavern/city + sLog.outDebug("The value of player %s at save: ", m_name.c_str()); + outDebugValues(); + + // save state (after auras removing), if aura remove some flags then it must set it back by self) + uint32 tmp_bytes = GetUInt32Value(UNIT_FIELD_BYTES_1); + uint32 tmp_bytes2 = GetUInt32Value(UNIT_FIELD_BYTES_2); + uint32 tmp_flags = GetUInt32Value(UNIT_FIELD_FLAGS); + uint32 tmp_pflags = GetUInt32Value(PLAYER_FLAGS); + uint32 tmp_displayid = GetDisplayId(); + + // Set player sit state to standing on save, also stealth and shifted form + SetByteValue(UNIT_FIELD_BYTES_1, 0, 0); // stand state + SetByteValue(UNIT_FIELD_BYTES_2, 3, 0); // shapeshift + SetByteValue(UNIT_FIELD_BYTES_1, 3, 0); // stand flags? + RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE); + SetDisplayId(GetNativeDisplayId()); + + bool inworld = IsInWorld(); + + CharacterDatabase.BeginTransaction(); + + CharacterDatabase.PExecute("DELETE FROM characters WHERE guid = '%u'",GetGUIDLow()); + + std::string sql_name = m_name; + CharacterDatabase.escape_string(sql_name); + + std::ostringstream ss; + ss << "INSERT INTO characters (guid,account,name,race,class," + "map, dungeon_difficulty, position_x, position_y, position_z, orientation, data, " + "taximask, online, cinematic, " + "totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, " + "trans_x, trans_y, trans_z, trans_o, transguid, gmstate, stable_slots, at_login, zone, " + "death_expire_time, taxi_path) VALUES (" + << GetGUIDLow() << ", " + << GetSession()->GetAccountId() << ", '" + << sql_name << "', " + << m_race << ", " + << m_class << ", "; + + bool save_to_dest = false; + if(IsBeingTeleported()) + { + // don't save to battlegrounds or arenas + const MapEntry *entry = sMapStore.LookupEntry(GetTeleportDest().mapid); + if(entry && entry->map_type != MAP_BATTLEGROUND && entry->map_type != MAP_ARENA) + save_to_dest = true; + } + + if(!save_to_dest) + { + ss << GetMapId() << ", " + << (uint32)GetDifficulty() << ", " + << finiteAlways(GetPositionX()) << ", " + << finiteAlways(GetPositionY()) << ", " + << finiteAlways(GetPositionZ()) << ", " + << finiteAlways(GetOrientation()) << ", '"; + } + else + { + ss << GetTeleportDest().mapid << ", " + << (uint32)GetDifficulty() << ", " + << finiteAlways(GetTeleportDest().x) << ", " + << finiteAlways(GetTeleportDest().y) << ", " + << finiteAlways(GetTeleportDest().z) << ", " + << finiteAlways(GetTeleportDest().o) << ", '"; + } + + uint16 i; + for( i = 0; i < m_valuesCount; i++ ) + { + ss << GetUInt32Value(i) << " "; + } + + ss << "', '"; + + for( i = 0; i < 8; i++ ) + ss << m_taxi.GetTaximask(i) << " "; + + ss << "', "; + ss << (inworld ? 1 : 0); + + ss << ", "; + ss << m_cinematic; + + ss << ", "; + ss << m_Played_time[0]; + ss << ", "; + ss << m_Played_time[1]; + + ss << ", "; + ss << finiteAlways(m_rest_bonus); + ss << ", "; + ss << (uint64)time(NULL); + ss << ", "; + ss << is_save_resting; + ss << ", "; + ss << m_resetTalentsCost; + ss << ", "; + ss << (uint64)m_resetTalentsTime; + + ss << ", "; + ss << finiteAlways(m_movementInfo.t_x); + ss << ", "; + ss << finiteAlways(m_movementInfo.t_y); + ss << ", "; + ss << finiteAlways(m_movementInfo.t_z); + ss << ", "; + ss << finiteAlways(m_movementInfo.t_o); + ss << ", "; + if (m_transport) + ss << m_transport->GetGUIDLow(); + else + ss << "0"; + + ss << ", "; + ss << (isGameMaster()? 1 : 0); + + ss << ", "; + ss << uint32(m_stableSlots); // to prevent save uint8 as char + + ss << ", "; + ss << uint32(m_atLoginFlags); + + ss << ", "; + ss << GetZoneId(); + + ss << ", "; + ss << (uint64)m_deathExpireTime; + + ss << ", '"; + ss << m_taxi.SaveTaxiDestinationsToString(); + ss << "' )"; + + CharacterDatabase.Execute( ss.str().c_str() ); + + if(m_mailsUpdated) //save mails only when needed + _SaveMail(); + + _SaveInventory(); + _SaveQuestStatus(); + _SaveDailyQuestStatus(); + _SaveTutorials(); + _SaveSpells(); + _SaveSpellCooldowns(); + _SaveActions(); + _SaveAuras(); + _SaveReputation(); + + CharacterDatabase.CommitTransaction(); + + // restore state (before aura apply, if aura remove flag then aura must set it ack by self) + SetDisplayId(tmp_displayid); + SetUInt32Value(UNIT_FIELD_BYTES_1, tmp_bytes); + SetUInt32Value(UNIT_FIELD_BYTES_2, tmp_bytes2); + SetUInt32Value(UNIT_FIELD_FLAGS, tmp_flags); + SetUInt32Value(PLAYER_FLAGS, tmp_pflags); + + // save pet (hunter pet level and experience and all type pets health/mana). + if(Pet* pet = GetPet()) + pet->SavePetToDB(PET_SAVE_AS_CURRENT); +} + +// fast save function for item/money cheating preventing - save only inventory and money state +void Player::SaveInventoryAndGoldToDB() +{ + _SaveInventory(); + SetUInt32ValueInDB(PLAYER_FIELD_COINAGE,GetMoney(),GetGUID()); +} + +void Player::_SaveActions() +{ + for(ActionButtonList::iterator itr = m_actionButtons.begin(); itr != m_actionButtons.end(); ) + { + switch (itr->second.uState) + { + case ACTIONBUTTON_NEW: + CharacterDatabase.PExecute("INSERT INTO character_action (guid,button,action,type,misc) VALUES ('%u', '%u', '%u', '%u', '%u')", + GetGUIDLow(), (uint32)itr->first, (uint32)itr->second.action, (uint32)itr->second.type, (uint32)itr->second.misc ); + itr->second.uState = ACTIONBUTTON_UNCHANGED; + ++itr; + break; + case ACTIONBUTTON_CHANGED: + CharacterDatabase.PExecute("UPDATE character_action SET action = '%u', type = '%u', misc= '%u' WHERE guid= '%u' AND button= '%u' ", + (uint32)itr->second.action, (uint32)itr->second.type, (uint32)itr->second.misc, GetGUIDLow(), (uint32)itr->first ); + itr->second.uState = ACTIONBUTTON_UNCHANGED; + ++itr; + break; + case ACTIONBUTTON_DELETED: + CharacterDatabase.PExecute("DELETE FROM character_action WHERE guid = '%u' and button = '%u'", GetGUIDLow(), (uint32)itr->first ); + m_actionButtons.erase(itr++); + break; + default: + ++itr; + break; + }; + } +} + +void Player::_SaveAuras() +{ + CharacterDatabase.PExecute("DELETE FROM character_aura WHERE guid = '%u'",GetGUIDLow()); + + AuraMap const& auras = GetAuras(); + for(AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) + { + SpellEntry const *spellInfo = itr->second->GetSpellProto(); + + //skip all auras from spells that are passive or need a shapeshift + if (itr->second->IsPassive() || itr->second->IsRemovedOnShapeLost()) + continue; + + //do not save single target auras (unless they were cast by the player) + if (itr->second->GetCasterGUID() != GetGUID() && IsSingleTargetSpell(spellInfo)) + continue; + + uint8 i; + // or apply at cast SPELL_AURA_MOD_SHAPESHIFT or SPELL_AURA_MOD_STEALTH auras + for (i = 0; i < 3; i++) + if (spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_SHAPESHIFT || + spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_STEALTH) + break; + + if (i == 3) + { + CharacterDatabase.PExecute("DELETE FROM character_aura WHERE guid = '%u' and spell = '%u' and effect_index= '%u'",GetGUIDLow(),(uint32)(*itr).second->GetId(), (uint32)(*itr).second->GetEffIndex()); + CharacterDatabase.PExecute("INSERT INTO character_aura (guid,caster_guid,spell,effect_index,amount,maxduration,remaintime,remaincharges) " + "VALUES ('%u', '" I64FMTD "' ,'%u', '%u', '%d', '%d', '%d', '%d')", + GetGUIDLow(), itr->second->GetCasterGUID(), (uint32)(*itr).second->GetId(), (uint32)(*itr).second->GetEffIndex(), (*itr).second->GetModifier()->m_amount,int((*itr).second->GetAuraMaxDuration()),int((*itr).second->GetAuraDuration()),int((*itr).second->m_procCharges)); + } + } +} + +void Player::_SaveInventory() +{ + // force items in buyback slots to new state + // and remove those that aren't already + for (uint8 i = BUYBACK_SLOT_START; i < BUYBACK_SLOT_END; i++) + { + Item *item = m_items[i]; + if (!item || item->GetState() == ITEM_NEW) continue; + CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE item = '%u'", item->GetGUIDLow()); + CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid = '%u'", item->GetGUIDLow()); + m_items[i]->FSetState(ITEM_NEW); + } + + // update enchantment durations + for(EnchantDurationList::iterator itr = m_enchantDuration.begin();itr != m_enchantDuration.end();++itr) + { + itr->item->SetEnchantmentDuration(itr->slot,itr->leftduration); + } + + // if no changes + if (m_itemUpdateQueue.empty()) return; + + // do not save if the update queue is corrupt + bool error = false; + for(size_t i = 0; i < m_itemUpdateQueue.size(); i++) + { + Item *item = m_itemUpdateQueue[i]; + if(!item || item->GetState() == ITEM_REMOVED) continue; + Item *test = GetItemByPos( item->GetBagSlot(), item->GetSlot()); + + if (test == NULL) + { + sLog.outError("Player(GUID: %u Name: %s)::_SaveInventory - the bag(%d) and slot(%d) values for the item with guid %d are incorrect, the player doesn't have an item at that position!", GetGUIDLow(), GetName(), item->GetBagSlot(), item->GetSlot(), item->GetGUIDLow()); + error = true; + } + else if (test != item) + { + sLog.outError("Player(GUID: %u Name: %s)::_SaveInventory - the bag(%d) and slot(%d) values for the item with guid %d are incorrect, the item with guid %d is there instead!", GetGUIDLow(), GetName(), item->GetBagSlot(), item->GetSlot(), item->GetGUIDLow(), test->GetGUIDLow()); + error = true; + } + } + + if (error) + { + sLog.outError("Player::_SaveInventory - one or more errors occurred save aborted!"); + ChatHandler(this).SendSysMessage(LANG_ITEM_SAVE_FAILED); + return; + } + + for(size_t i = 0; i < m_itemUpdateQueue.size(); i++) + { + Item *item = m_itemUpdateQueue[i]; + if(!item) continue; + + Bag *container = item->GetContainer(); + uint32 bag_guid = container ? container->GetGUIDLow() : 0; + + switch(item->GetState()) + { + case ITEM_NEW: + CharacterDatabase.PExecute("INSERT INTO character_inventory (guid,bag,slot,item,item_template) VALUES ('%u', '%u', '%u', '%u', '%u')", GetGUIDLow(), bag_guid, item->GetSlot(), item->GetGUIDLow(), item->GetEntry()); + break; + case ITEM_CHANGED: + CharacterDatabase.PExecute("UPDATE character_inventory SET guid='%u', bag='%u', slot='%u', item_template='%u' WHERE item='%u'", GetGUIDLow(), bag_guid, item->GetSlot(), item->GetEntry(), item->GetGUIDLow()); + break; + case ITEM_REMOVED: + CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE item = '%u'", item->GetGUIDLow()); + break; + case ITEM_UNCHANGED: + break; + } + + item->SaveToDB(); // item have unchanged inventory record and can be save standalone + } + m_itemUpdateQueue.clear(); +} + +void Player::_SaveMail() +{ + if (!m_mailsLoaded) + return; + + for (PlayerMails::iterator itr = m_mail.begin(); itr != m_mail.end(); itr++) + { + Mail *m = (*itr); + if (m->state == MAIL_STATE_CHANGED) + { + CharacterDatabase.PExecute("UPDATE mail SET itemTextId = '%u',has_items = '%u',expire_time = '" I64FMTD "', deliver_time = '" I64FMTD "',money = '%u',cod = '%u',checked = '%u' WHERE id = '%u'", + m->itemTextId, m->HasItems() ? 1 : 0, (uint64)m->expire_time, (uint64)m->deliver_time, m->money, m->COD, m->checked, m->messageID); + if(m->removedItems.size()) + { + for(std::vector::iterator itr2 = m->removedItems.begin(); itr2 != m->removedItems.end(); ++itr2) + CharacterDatabase.PExecute("DELETE FROM mail_items WHERE item_guid = '%u'", *itr2); + m->removedItems.clear(); + } + m->state = MAIL_STATE_UNCHANGED; + } + else if (m->state == MAIL_STATE_DELETED) + { + if (m->HasItems()) + for(std::vector::iterator itr2 = m->items.begin(); itr2 != m->items.end(); ++itr2) + CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid = '%u'", itr2->item_guid); + if (m->itemTextId) + CharacterDatabase.PExecute("DELETE FROM item_text WHERE id = '%u'", m->itemTextId); + CharacterDatabase.PExecute("DELETE FROM mail WHERE id = '%u'", m->messageID); + CharacterDatabase.PExecute("DELETE FROM mail_items WHERE mail_id = '%u'", m->messageID); + } + } + + //deallocate deleted mails... + for (PlayerMails::iterator itr = m_mail.begin(); itr != m_mail.end(); ) + { + if ((*itr)->state == MAIL_STATE_DELETED) + { + Mail* m = *itr; + m_mail.erase(itr); + delete m; + itr = m_mail.begin(); + } + else + ++itr; + } + + m_mailsUpdated = false; +} + +void Player::_SaveQuestStatus() +{ + // we don't need transactions here. + for( QuestStatusMap::iterator i = mQuestStatus.begin( ); i != mQuestStatus.end( ); ++i ) + { + switch (i->second.uState) + { + case QUEST_NEW : + CharacterDatabase.PExecute("INSERT INTO character_queststatus (guid,quest,status,rewarded,explored,timer,mobcount1,mobcount2,mobcount3,mobcount4,itemcount1,itemcount2,itemcount3,itemcount4) " + "VALUES ('%u', '%u', '%u', '%u', '%u', '" I64FMTD "', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u')", + GetGUIDLow(), i->first, i->second.m_status, i->second.m_rewarded, i->second.m_explored, uint64(i->second.m_timer / 1000 + sWorld.GetGameTime()), i->second.m_creatureOrGOcount[0], i->second.m_creatureOrGOcount[1], i->second.m_creatureOrGOcount[2], i->second.m_creatureOrGOcount[3], i->second.m_itemcount[0], i->second.m_itemcount[1], i->second.m_itemcount[2], i->second.m_itemcount[3]); + break; + case QUEST_CHANGED : + CharacterDatabase.PExecute("UPDATE character_queststatus SET status = '%u',rewarded = '%u',explored = '%u',timer = '" I64FMTD "',mobcount1 = '%u',mobcount2 = '%u',mobcount3 = '%u',mobcount4 = '%u',itemcount1 = '%u',itemcount2 = '%u',itemcount3 = '%u',itemcount4 = '%u' WHERE guid = '%u' AND quest = '%u' ", + i->second.m_status, i->second.m_rewarded, i->second.m_explored, uint64(i->second.m_timer / 1000 + sWorld.GetGameTime()), i->second.m_creatureOrGOcount[0], i->second.m_creatureOrGOcount[1], i->second.m_creatureOrGOcount[2], i->second.m_creatureOrGOcount[3], i->second.m_itemcount[0], i->second.m_itemcount[1], i->second.m_itemcount[2], i->second.m_itemcount[3], GetGUIDLow(), i->first ); + break; + case QUEST_UNCHANGED: + break; + }; + i->second.uState = QUEST_UNCHANGED; + } +} + +void Player::_SaveDailyQuestStatus() +{ + if(!m_DailyQuestChanged) + return; + + m_DailyQuestChanged = false; + + // save last daily quest time for all quests: we need only mostly reset time for reset check anyway + + // we don't need transactions here. + CharacterDatabase.PExecute("DELETE FROM character_queststatus_daily WHERE guid = '%u'",GetGUIDLow()); + for(uint32 quest_daily_idx = 0; quest_daily_idx < PLAYER_MAX_DAILY_QUESTS; ++quest_daily_idx) + if(GetUInt32Value(PLAYER_FIELD_DAILY_QUESTS_1+quest_daily_idx)) + CharacterDatabase.PExecute("INSERT INTO character_queststatus_daily (guid,quest,time) VALUES ('%u', '%u','" I64FMTD "')", + GetGUIDLow(), GetUInt32Value(PLAYER_FIELD_DAILY_QUESTS_1+quest_daily_idx),uint64(m_lastDailyQuestTime)); +} + +void Player::_SaveReputation() +{ + for(FactionStateList::iterator itr = m_factions.begin(); itr != m_factions.end(); ++itr) + { + if (itr->second.Changed) + { + CharacterDatabase.PExecute("DELETE FROM character_reputation WHERE guid = '%u' AND faction='%u'", GetGUIDLow(), itr->second.ID); + CharacterDatabase.PExecute("INSERT INTO character_reputation (guid,faction,standing,flags) VALUES ('%u', '%u', '%i', '%u')", GetGUIDLow(), itr->second.ID, itr->second.Standing, itr->second.Flags); + itr->second.Changed = false; + } + } +} + +void Player::_SaveSpells() +{ + for (PlayerSpellMap::const_iterator itr = m_spells.begin(), next = m_spells.begin(); itr != m_spells.end(); itr = next) + { + ++next; + if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->state == PLAYERSPELL_CHANGED) + CharacterDatabase.PExecute("DELETE FROM character_spell WHERE guid = '%u' and spell = '%u'", GetGUIDLow(), itr->first); + if (itr->second->state == PLAYERSPELL_NEW || itr->second->state == PLAYERSPELL_CHANGED) + CharacterDatabase.PExecute("INSERT INTO character_spell (guid,spell,slot,active,disabled) VALUES ('%u', '%u', '%u','%u','%u')", GetGUIDLow(), itr->first, itr->second->slotId,itr->second->active ? 1 : 0,itr->second->disabled ? 1 : 0); + + if (itr->second->state == PLAYERSPELL_REMOVED) + _removeSpell(itr->first); + else + itr->second->state = PLAYERSPELL_UNCHANGED; + } +} + +void Player::_SaveTutorials() +{ + if(!m_TutorialsChanged) + return; + + uint32 Rows=0; + // it's better than rebuilding indexes multiple times + QueryResult *result = CharacterDatabase.PQuery("SELECT count(*) AS r FROM character_tutorial WHERE account = '%u' AND realmid = '%u'", GetSession()->GetAccountId(), realmID ); + if(result) + { + Rows = result->Fetch()[0].GetUInt32(); + delete result; + } + + if (Rows) + { + CharacterDatabase.PExecute("UPDATE character_tutorial SET tut0='%u', tut1='%u', tut2='%u', tut3='%u', tut4='%u', tut5='%u', tut6='%u', tut7='%u' WHERE account = '%u' AND realmid = '%u'", + m_Tutorials[0], m_Tutorials[1], m_Tutorials[2], m_Tutorials[3], m_Tutorials[4], m_Tutorials[5], m_Tutorials[6], m_Tutorials[7], GetSession()->GetAccountId(), realmID ); + } + else + { + CharacterDatabase.PExecute("INSERT INTO character_tutorial (account,realmid,tut0,tut1,tut2,tut3,tut4,tut5,tut6,tut7) VALUES ('%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u')", GetSession()->GetAccountId(), realmID, m_Tutorials[0], m_Tutorials[1], m_Tutorials[2], m_Tutorials[3], m_Tutorials[4], m_Tutorials[5], m_Tutorials[6], m_Tutorials[7]); + }; + + m_TutorialsChanged = false; +} + +void Player::outDebugValues() const +{ + if(!sLog.IsOutDebug()) // optimize disabled debug output + return; + + sLog.outDebug("HP is: \t\t\t%u\t\tMP is: \t\t\t%u",GetMaxHealth(), GetMaxPower(POWER_MANA)); + sLog.outDebug("AGILITY is: \t\t%f\t\tSTRENGTH is: \t\t%f",GetStat(STAT_AGILITY), GetStat(STAT_STRENGTH)); + sLog.outDebug("INTELLECT is: \t\t%f\t\tSPIRIT is: \t\t%f",GetStat(STAT_INTELLECT), GetStat(STAT_SPIRIT)); + sLog.outDebug("STAMINA is: \t\t%f\t\tSPIRIT is: \t\t%f",GetStat(STAT_STAMINA), GetStat(STAT_SPIRIT)); + sLog.outDebug("Armor is: \t\t%u\t\tBlock is: \t\t%f",GetArmor(), GetFloatValue(PLAYER_BLOCK_PERCENTAGE)); + sLog.outDebug("HolyRes is: \t\t%u\t\tFireRes is: \t\t%u",GetResistance(SPELL_SCHOOL_HOLY), GetResistance(SPELL_SCHOOL_FIRE)); + sLog.outDebug("NatureRes is: \t\t%u\t\tFrostRes is: \t\t%u",GetResistance(SPELL_SCHOOL_NATURE), GetResistance(SPELL_SCHOOL_FROST)); + sLog.outDebug("ShadowRes is: \t\t%u\t\tArcaneRes is: \t\t%u",GetResistance(SPELL_SCHOOL_SHADOW), GetResistance(SPELL_SCHOOL_ARCANE)); + sLog.outDebug("MIN_DAMAGE is: \t\t%f\tMAX_DAMAGE is: \t\t%f",GetFloatValue(UNIT_FIELD_MINDAMAGE), GetFloatValue(UNIT_FIELD_MAXDAMAGE)); + sLog.outDebug("MIN_OFFHAND_DAMAGE is: \t%f\tMAX_OFFHAND_DAMAGE is: \t%f",GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE), GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE)); + sLog.outDebug("MIN_RANGED_DAMAGE is: \t%f\tMAX_RANGED_DAMAGE is: \t%f",GetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE), GetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE)); + sLog.outDebug("ATTACK_TIME is: \t%u\t\tRANGE_ATTACK_TIME is: \t%u",GetAttackTime(BASE_ATTACK), GetAttackTime(RANGED_ATTACK)); +} + +/*********************************************************/ +/*** FLOOD FILTER SYSTEM ***/ +/*********************************************************/ + +void Player::UpdateSpeakTime() +{ + // ignore chat spam protection for GMs in any mode + if(GetSession()->GetSecurity() > SEC_PLAYER) + return; + + time_t current = time (NULL); + if(m_speakTime > current) + { + uint32 max_count = sWorld.getConfig(CONFIG_CHATFLOOD_MESSAGE_COUNT); + if(!max_count) + return; + + ++m_speakCount; + if(m_speakCount >= max_count) + { + // prevent overwrite mute time, if message send just before mutes set, for example. + time_t new_mute = current + sWorld.getConfig(CONFIG_CHATFLOOD_MUTE_TIME); + if(GetSession()->m_muteTime < new_mute) + GetSession()->m_muteTime = new_mute; + + m_speakCount = 0; + } + } + else + m_speakCount = 0; + + m_speakTime = current + sWorld.getConfig(CONFIG_CHATFLOOD_MESSAGE_DELAY); +} + +bool Player::CanSpeak() const +{ + return GetSession()->m_muteTime <= time (NULL); +} + +/*********************************************************/ +/*** LOW LEVEL FUNCTIONS:Notifiers ***/ +/*********************************************************/ + +void Player::SendAttackSwingNotInRange() +{ + WorldPacket data(SMSG_ATTACKSWING_NOTINRANGE, 0); + GetSession()->SendPacket( &data ); +} + +void Player::SavePositionInDB(uint32 mapid, float x,float y,float z,float o,uint32 zone,uint64 guid) +{ + std::ostringstream ss; + ss << "UPDATE characters SET position_x='"<= tokens.size()) + return; + + tokens[index] = buf; +} + +void Player::SetUInt32ValueInDB(uint16 index, uint32 value, uint64 guid) +{ + Tokens tokens; + if(!LoadValuesArrayFromDB(tokens,guid)) + return; + + if(index >= tokens.size()) + return; + + char buf[11]; + snprintf(buf,11,"%u",value); + tokens[index] = buf; + + SaveValuesArrayInDB(tokens,guid); +} + +void Player::SetFloatValueInDB(uint16 index, float value, uint64 guid) +{ + uint32 temp; + memcpy(&temp, &value, sizeof(value)); + Player::SetUInt32ValueInDB(index, temp, guid); +} + +void Player::SendAttackSwingNotStanding() +{ + WorldPacket data(SMSG_ATTACKSWING_NOTSTANDING, 0); + GetSession()->SendPacket( &data ); +} + +void Player::SendAttackSwingDeadTarget() +{ + WorldPacket data(SMSG_ATTACKSWING_DEADTARGET, 0); + GetSession()->SendPacket( &data ); +} + +void Player::SendAttackSwingCantAttack() +{ + WorldPacket data(SMSG_ATTACKSWING_CANT_ATTACK, 0); + GetSession()->SendPacket( &data ); +} + +void Player::SendAttackSwingCancelAttack() +{ + WorldPacket data(SMSG_CANCEL_COMBAT, 0); + GetSession()->SendPacket( &data ); +} + +void Player::SendAttackSwingBadFacingAttack() +{ + WorldPacket data(SMSG_ATTACKSWING_BADFACING, 0); + GetSession()->SendPacket( &data ); +} + +void Player::SendAutoRepeatCancel() +{ + WorldPacket data(SMSG_CANCEL_AUTO_REPEAT, 0); + GetSession()->SendPacket( &data ); +} + +void Player::PlaySound(uint32 Sound, bool OnlySelf) +{ + WorldPacket data(SMSG_PLAY_SOUND, 4); + data << Sound; + if (OnlySelf) + GetSession()->SendPacket( &data ); + else + SendMessageToSet( &data, true ); +} + +void Player::SendExplorationExperience(uint32 Area, uint32 Experience) +{ + WorldPacket data( SMSG_EXPLORATION_EXPERIENCE, 8 ); + data << Area; + data << Experience; + GetSession()->SendPacket(&data); +} + +void Player::SendDungeonDifficulty(bool IsInGroup) +{ + uint8 val = 0x00000001; + WorldPacket data(MSG_SET_DUNGEON_DIFFICULTY, 12); + data << (uint32)GetDifficulty(); + data << uint32(val); + data << uint32(IsInGroup); + GetSession()->SendPacket(&data); +} + +void Player::SendResetFailedNotify(uint32 mapid) +{ + WorldPacket data(SMSG_RESET_FAILED_NOTIFY, 4); + data << uint32(mapid); + GetSession()->SendPacket(&data); +} + +/// Reset all solo instances and optionally send a message on success for each +void Player::ResetInstances(uint8 method) +{ + // method can be INSTANCE_RESET_ALL, INSTANCE_RESET_CHANGE_DIFFICULTY, INSTANCE_RESET_GROUP_JOIN + + // we assume that when the difficulty changes, all instances that can be reset will be + uint8 dif = GetDifficulty(); + + for (BoundInstancesMap::iterator itr = m_boundInstances[dif].begin(); itr != m_boundInstances[dif].end();) + { + InstanceSave *p = itr->second.save; + const MapEntry *entry = sMapStore.LookupEntry(itr->first); + if(!entry || !p->CanReset()) + { + ++itr; + continue; + } + + if(method == INSTANCE_RESET_ALL) + { + // the "reset all instances" method can only reset normal maps + if(dif == DIFFICULTY_HEROIC || entry->map_type == MAP_RAID) + { + ++itr; + continue; + } + } + + // if the map is loaded, reset it + Map *map = MapManager::Instance().FindMap(p->GetMapId(), p->GetInstanceId()); + if(map && map->IsDungeon()) + ((InstanceMap*)map)->Reset(method); + + // since this is a solo instance there should not be any players inside + if(method == INSTANCE_RESET_ALL || method == INSTANCE_RESET_CHANGE_DIFFICULTY) + SendResetInstanceSuccess(p->GetMapId()); + + p->DeleteFromDB(); + m_boundInstances[dif].erase(itr++); + + // the following should remove the instance save from the manager and delete it as well + p->RemovePlayer(this); + } +} + +void Player::SendResetInstanceSuccess(uint32 MapId) +{ + WorldPacket data(SMSG_INSTANCE_RESET, 4); + data << MapId; + GetSession()->SendPacket(&data); +} + +void Player::SendResetInstanceFailed(uint32 reason, uint32 MapId) +{ + // TODO: find what other fail reasons there are besides players in the instance + WorldPacket data(SMSG_INSTANCE_RESET_FAILED, 4); + data << reason; + data << MapId; + GetSession()->SendPacket(&data); +} + +/*********************************************************/ +/*** Update timers ***/ +/*********************************************************/ + +///checks the 15 afk reports per 5 minutes limit +void Player::UpdateAfkReport(time_t currTime) +{ + if(m_bgAfkReportedTimer <= currTime) + { + m_bgAfkReportedCount = 0; + m_bgAfkReportedTimer = currTime+5*MINUTE; + } +} + +void Player::UpdateContestedPvP(uint32 diff) +{ + if(!m_contestedPvPTimer||isInCombat()) + return; + if(m_contestedPvPTimer <= diff) + { + ResetContestedPvP(); + } + else + m_contestedPvPTimer -= diff; +} + +void Player::UpdatePvPFlag(time_t currTime) +{ + if(!IsPvP()) + return; + if(pvpInfo.endTimer == 0 || currTime < (pvpInfo.endTimer + 300)) + return; + + UpdatePvP(false); +} + +void Player::UpdateDuelFlag(time_t currTime) +{ + if(!duel || duel->startTimer == 0 ||currTime < duel->startTimer + 3) + return; + + SetUInt32Value(PLAYER_DUEL_TEAM, 1); + duel->opponent->SetUInt32Value(PLAYER_DUEL_TEAM, 2); + + duel->startTimer = 0; + duel->startTime = currTime; + duel->opponent->duel->startTimer = 0; + duel->opponent->duel->startTime = currTime; +} + +void Player::RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent) +{ + if(!pet) + pet = GetPet(); + + if(returnreagent && (pet || m_temporaryUnsummonedPetNumber)) + { + //returning of reagents only for players, so best done here + uint32 spellId = pet ? pet->GetUInt32Value(UNIT_CREATED_BY_SPELL) : m_oldpetspell; + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); + + if(spellInfo) + { + for(uint32 i = 0; i < 7; ++i) + { + if(spellInfo->Reagent[i] > 0) + { + ItemPosCountVec dest; //for succubus, voidwalker, felhunter and felguard credit soulshard when despawn reason other than death (out of range, logout) + uint8 msg = CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, spellInfo->Reagent[i], spellInfo->ReagentCount[i] ); + if( msg == EQUIP_ERR_OK ) + { + Item* item = StoreNewItem( dest, spellInfo->Reagent[i], true); + if(IsInWorld()) + SendNewItem(item,spellInfo->ReagentCount[i],true,false); + } + } + } + } + m_temporaryUnsummonedPetNumber = 0; + } + + if(!pet || pet->GetOwnerGUID()!=GetGUID()) + return; + + // only if current pet in slot + switch(pet->getPetType()) + { + case MINI_PET: + m_miniPet = 0; + break; + case GUARDIAN_PET: + m_guardianPets.erase(pet->GetGUID()); + break; + default: + if(GetPetGUID()==pet->GetGUID()) + SetPet(0); + break; + } + + pet->CombatStop(); + + if(returnreagent) + { + switch(pet->GetEntry()) + { + //warlock pets except imp are removed(?) when logging out + case 1860: + case 1863: + case 417: + case 17252: + mode = PET_SAVE_NOT_IN_SLOT; + break; + } + } + + pet->SavePetToDB(mode); + + pet->CleanupsBeforeDelete(); + pet->AddObjectToRemoveList(); + pet->m_removed = true; + + if(pet->isControlled()) + { + WorldPacket data(SMSG_PET_SPELLS, 8); + data << uint64(0); + GetSession()->SendPacket(&data); + + if(GetGroup()) + SetGroupUpdateFlag(GROUP_UPDATE_PET); + } +} + + +void Player::RemoveMiniPet() +{ + if(Pet* pet = GetMiniPet()) + { + pet->Remove(PET_SAVE_AS_DELETED); + m_miniPet = 0; + } +} + +Pet* Player::GetMiniPet() +{ + if(!m_miniPet) + return NULL; + return ObjectAccessor::GetPet(m_miniPet); +} + +void Player::RemoveGuardians() +{ + while(!m_guardianPets.empty()) + { + uint64 guid = *m_guardianPets.begin(); + if(Pet* pet = ObjectAccessor::GetPet(guid)) + pet->Remove(PET_SAVE_AS_DELETED); + + m_guardianPets.erase(guid); + } +} + +bool Player::HasGuardianWithEntry(uint32 entry) +{ + // pet guid middle part is entry (and creature also) + // and in guardian list must be guardians with same entry _always_ + for(GuardianPetList::const_iterator itr = m_guardianPets.begin(); itr != m_guardianPets.end(); ++itr) + if(GUID_ENPART(*itr)==entry) + return true; + + return false; +} + +void Player::Uncharm() +{ + Unit* charm = GetCharm(); + if(!charm) + return; + + charm->RemoveSpellsCausingAura(SPELL_AURA_MOD_CHARM); + charm->RemoveSpellsCausingAura(SPELL_AURA_MOD_POSSESS); +} + +void Player::BuildPlayerChat(WorldPacket *data, uint8 msgtype, std::string text, uint32 language) const +{ + bool pre = (msgtype==CHAT_MSG_EMOTE); + + *data << (uint8)msgtype; + *data << (uint32)language; + *data << (uint64)GetGUID(); + *data << (uint32)language; //language 2.1.0 ? + *data << (uint64)GetGUID(); + *data << (uint32)(text.length()+1+(pre?3:0)); + if(pre) + data->append("%s ",3); + *data << text; + *data << (uint8)chatTag(); +} + +void Player::Say(const std::string text, const uint32 language) +{ + WorldPacket data(SMSG_MESSAGECHAT, 200); + BuildPlayerChat(&data, CHAT_MSG_SAY, text, language); + SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_SAY),true); +} + +void Player::Yell(const std::string text, const uint32 language) +{ + WorldPacket data(SMSG_MESSAGECHAT, 200); + BuildPlayerChat(&data, CHAT_MSG_YELL, text, language); + SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_YELL),true); +} + +void Player::TextEmote(const std::string text) +{ + WorldPacket data(SMSG_MESSAGECHAT, 200); + BuildPlayerChat(&data, CHAT_MSG_EMOTE, text, LANG_UNIVERSAL); + SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),true, !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT) ); +} + +void Player::Whisper(std::string text, uint32 language,uint64 receiver) +{ + if (language != LANG_ADDON) // if not addon data + language = LANG_UNIVERSAL; // whispers should always be readable + + Player *rPlayer = objmgr.GetPlayer(receiver); + + // when player you are whispering to is dnd, he cannot receive your message, unless you are in gm mode + if(!rPlayer->isDND() || isGameMaster()) + { + WorldPacket data(SMSG_MESSAGECHAT, 200); + BuildPlayerChat(&data, CHAT_MSG_WHISPER, text, language); + rPlayer->GetSession()->SendPacket(&data); + + data.Initialize(SMSG_MESSAGECHAT, 200); + rPlayer->BuildPlayerChat(&data, CHAT_MSG_REPLY, text, language); + GetSession()->SendPacket(&data); + } + else + { + // announce to player that player he is whispering to is dnd and cannot receive his message + ChatHandler(this).PSendSysMessage(LANG_PLAYER_DND, rPlayer->GetName(), rPlayer->dndMsg.c_str()); + } + + if(!isAcceptWhispers()) + { + SetAcceptWhispers(true); + ChatHandler(this).SendSysMessage(LANG_COMMAND_WHISPERON); + } + + // announce to player that player he is whispering to is afk + if(rPlayer->isAFK()) + ChatHandler(this).PSendSysMessage(LANG_PLAYER_AFK, rPlayer->GetName(), rPlayer->afkMsg.c_str()); + + // if player whisper someone, auto turn of dnd to be able to receive an answer + if(isDND() && !rPlayer->isGameMaster()) + ToggleDND(); +} + +void Player::PetSpellInitialize() +{ + Pet* pet = GetPet(); + + if(pet) + { + uint8 addlist = 0; + + sLog.outDebug("Pet Spells Groups"); + + CreatureInfo const *cinfo = pet->GetCreatureInfo(); + + if(pet->isControlled() && (pet->getPetType() == HUNTER_PET || cinfo && cinfo->type == CREATURE_TYPE_DEMON && getClass() == CLASS_WARLOCK)) + { + for(PetSpellMap::iterator itr = pet->m_spells.begin();itr != pet->m_spells.end();itr++) + { + if(itr->second->state == PETSPELL_REMOVED) + continue; + ++addlist; + } + } + + // first line + actionbar + spellcount + spells + last adds + WorldPacket data(SMSG_PET_SPELLS, 16+40+1+4*addlist+25); + + CharmInfo *charmInfo = pet->GetCharmInfo(); + + //16 + data << (uint64)pet->GetGUID() << uint32(0x00000000) << uint8(charmInfo->GetReactState()) << uint8(charmInfo->GetCommandState()) << uint16(0); + + for(uint32 i = 0; i < 10; i++) //40 + { + data << uint16(charmInfo->GetActionBarEntry(i)->SpellOrAction) << uint16(charmInfo->GetActionBarEntry(i)->Type); + } + + data << uint8(addlist); //1 + + if(addlist && pet->isControlled()) + { + for (PetSpellMap::iterator itr = pet->m_spells.begin(); itr != pet->m_spells.end(); ++itr) + { + if(itr->second->state == PETSPELL_REMOVED) + continue; + + data << uint16(itr->first); + data << uint16(itr->second->active); // pet spell active state isn't boolean + } + } + + //data << uint8(0x01) << uint32(0x6010) << uint32(0x01) << uint32(0x05) << uint16(0x00); //15 + uint8 count = 3; //1+8+8+8=25 + + // if count = 0, then end of packet... + data << count; + // uint32 value is spell id... + // uint64 value is constant 0, unknown... + data << uint32(0x6010) << uint64(0); // if count = 1, 2 or 3 + //data << uint32(0x5fd1) << uint64(0); // if count = 2 + data << uint32(0x8e8c) << uint64(0); // if count = 3 + data << uint32(0x8e8b) << uint64(0); // if count = 3 + + GetSession()->SendPacket(&data); + } +} + +void Player::PossessSpellInitialize() +{ + Unit* charm = GetCharm(); + + if(!charm) + return; + + CharmInfo *charmInfo = charm->GetCharmInfo(); + + if(!charmInfo) + { + sLog.outError("Player::PossessSpellInitialize(): charm ("I64FMTD") has no charminfo!", charm->GetGUID()); + return; + } + + uint8 addlist = 0; + WorldPacket data(SMSG_PET_SPELLS, 16+40+1+4*addlist+25);// first line + actionbar + spellcount + spells + last adds + + //16 + data << (uint64)charm->GetGUID() << uint32(0x00000000) << uint8(0) << uint8(0) << uint16(0); + + for(uint32 i = 0; i < 10; i++) //40 + { + data << uint16(charmInfo->GetActionBarEntry(i)->SpellOrAction) << uint16(charmInfo->GetActionBarEntry(i)->Type); + } + + data << uint8(addlist); //1 + + uint8 count = 3; + data << count; + data << uint32(0x6010) << uint64(0); // if count = 1, 2 or 3 + data << uint32(0x8e8c) << uint64(0); // if count = 3 + data << uint32(0x8e8b) << uint64(0); // if count = 3 + + GetSession()->SendPacket(&data); +} + +void Player::CharmSpellInitialize() +{ + Unit* charm = GetCharm(); + + if(!charm) + return; + + CharmInfo *charmInfo = charm->GetCharmInfo(); + if(!charmInfo) + { + sLog.outError("Player::CharmSpellInitialize(): the player's charm ("I64FMTD") has no charminfo!", charm->GetGUID()); + return; + } + + uint8 addlist = 0; + + if(charm->GetTypeId() != TYPEID_PLAYER) + { + CreatureInfo const *cinfo = ((Creature*)charm)->GetCreatureInfo(); + + if(cinfo && cinfo->type == CREATURE_TYPE_DEMON && getClass() == CLASS_WARLOCK) + { + for(uint32 i = 0; i < CREATURE_MAX_SPELLS; ++i) + { + if(charmInfo->GetCharmSpell(i)->spellId) + ++addlist; + } + } + } + + WorldPacket data(SMSG_PET_SPELLS, 16+40+1+4*addlist+25);// first line + actionbar + spellcount + spells + last adds + + data << (uint64)charm->GetGUID() << uint32(0x00000000); + + if(charm->GetTypeId() != TYPEID_PLAYER) + data << uint8(charmInfo->GetReactState()) << uint8(charmInfo->GetCommandState()); + else + data << uint8(0) << uint8(0); + + data << uint16(0); + + for(uint32 i = 0; i < 10; i++) //40 + { + data << uint16(charmInfo->GetActionBarEntry(i)->SpellOrAction) << uint16(charmInfo->GetActionBarEntry(i)->Type); + } + + data << uint8(addlist); //1 + + if(addlist) + { + for(uint32 i = 0; i < CREATURE_MAX_SPELLS; ++i) + { + CharmSpellEntry *cspell = charmInfo->GetCharmSpell(i); + if(cspell->spellId) + { + data << uint16(cspell->spellId); + data << uint16(cspell->active); + } + } + } + + uint8 count = 3; + data << count; + data << uint32(0x6010) << uint64(0); // if count = 1, 2 or 3 + data << uint32(0x8e8c) << uint64(0); // if count = 3 + data << uint32(0x8e8b) << uint64(0); // if count = 3 + + GetSession()->SendPacket(&data); +} + +int32 Player::GetTotalFlatMods(uint32 spellId, SpellModOp op) +{ + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); + if (!spellInfo) return 0; + int32 total = 0; + for (SpellModList::iterator itr = m_spellMods[op].begin(); itr != m_spellMods[op].end(); ++itr) + { + SpellModifier *mod = *itr; + + if(!IsAffectedBySpellmod(spellInfo,mod)) + continue; + + if (mod->type == SPELLMOD_FLAT) + total += mod->value; + } + return total; +} + +int32 Player::GetTotalPctMods(uint32 spellId, SpellModOp op) +{ + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); + if (!spellInfo) return 0; + int32 total = 0; + for (SpellModList::iterator itr = m_spellMods[op].begin(); itr != m_spellMods[op].end(); ++itr) + { + SpellModifier *mod = *itr; + + if(!IsAffectedBySpellmod(spellInfo,mod)) + continue; + + if (mod->type == SPELLMOD_PCT) + total += mod->value; + } + return total; +} + +bool Player::IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell const* spell) +{ + if (!mod || !spellInfo) + return false; + + if(mod->charges == -1 && mod->lastAffected ) // marked as expired but locked until spell casting finish + { + // prevent apply to any spell except spell that trigger expire + if(spell) + { + if(mod->lastAffected != spell) + return false; + } + else if(mod->lastAffected != FindCurrentSpellBySpellId(spellInfo->Id)) + return false; + } + + return spellmgr.IsAffectedBySpell(spellInfo,mod->spellId,mod->effectId,mod->mask); +} + +void Player::AddSpellMod(SpellModifier* mod, bool apply) +{ + uint16 Opcode= (mod->type == SPELLMOD_FLAT) ? SMSG_SET_FLAT_SPELL_MODIFIER : SMSG_SET_PCT_SPELL_MODIFIER; + + for(int eff=0;eff<64;++eff) + { + uint64 _mask = uint64(1) << eff; + if ( mod->mask & _mask) + { + int32 val = 0; + for (SpellModList::iterator itr = m_spellMods[mod->op].begin(); itr != m_spellMods[mod->op].end(); ++itr) + { + if ((*itr)->type == mod->type && (*itr)->mask & _mask) + val += (*itr)->value; + } + val += apply ? mod->value : -(mod->value); + WorldPacket data(Opcode, (1+1+4)); + data << uint8(eff); + data << uint8(mod->op); + data << int32(val); + SendDirectMessage(&data); + } + } + + if (apply) + m_spellMods[mod->op].push_back(mod); + else + { + if (mod->charges == -1) + --m_SpellModRemoveCount; + m_spellMods[mod->op].remove(mod); + delete mod; + } +} + +void Player::RemoveSpellMods(Spell const* spell) +{ + if(!spell || (m_SpellModRemoveCount == 0)) + return; + + for(int i=0;icharges == -1 && (mod->lastAffected == spell || mod->lastAffected==NULL)) + { + RemoveAurasDueToSpell(mod->spellId); + if (m_spellMods[i].empty()) + break; + else + itr = m_spellMods[i].begin(); + } + } + } +} + +// send Proficiency +void Player::SendProficiency(uint8 pr1, uint32 pr2) +{ + WorldPacket data(SMSG_SET_PROFICIENCY, 8); + data << pr1 << pr2; + GetSession()->SendPacket (&data); +} + +void Player::RemovePetitionsAndSigns(uint64 guid, uint32 type) +{ + QueryResult *result = NULL; + if(type==10) + result = CharacterDatabase.PQuery("SELECT ownerguid,petitionguid FROM petition_sign WHERE playerguid = '%u'", GUID_LOPART(guid)); + else + result = CharacterDatabase.PQuery("SELECT ownerguid,petitionguid FROM petition_sign WHERE playerguid = '%u' AND type = '%u'", GUID_LOPART(guid), type); + if(result) + { + do // this part effectively does nothing, since the deletion / modification only takes place _after_ the PetitionQuery. Though I don't know if the result remains intact if I execute the delete query beforehand. + { // and SendPetitionQueryOpcode reads data from the DB + Field *fields = result->Fetch(); + uint64 ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); + uint64 petitionguid = MAKE_NEW_GUID(fields[1].GetUInt32(), 0, HIGHGUID_ITEM); + + // send update if charter owner in game + Player* owner = objmgr.GetPlayer(ownerguid); + if(owner) + owner->GetSession()->SendPetitionQueryOpcode(petitionguid); + + } while ( result->NextRow() ); + + delete result; + + if(type==10) + CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE playerguid = '%u'", GUID_LOPART(guid)); + else + CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE playerguid = '%u' AND type = '%u'", GUID_LOPART(guid), type); + } + + CharacterDatabase.BeginTransaction(); + if(type == 10) + { + CharacterDatabase.PExecute("DELETE FROM petition WHERE ownerguid = '%u'", GUID_LOPART(guid)); + CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE ownerguid = '%u'", GUID_LOPART(guid)); + } + else + { + CharacterDatabase.PExecute("DELETE FROM petition WHERE ownerguid = '%u' AND type = '%u'", GUID_LOPART(guid), type); + CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE ownerguid = '%u' AND type = '%u'", GUID_LOPART(guid), type); + } + CharacterDatabase.CommitTransaction(); +} + +void Player::SetRestBonus (float rest_bonus_new) +{ + // Prevent resting on max level + if(getLevel() >= sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + rest_bonus_new = 0; + + if(rest_bonus_new < 0) + rest_bonus_new = 0; + + float rest_bonus_max = (float)GetUInt32Value(PLAYER_NEXT_LEVEL_XP)*1.5/2; + + if(rest_bonus_new > rest_bonus_max) + m_rest_bonus = rest_bonus_max; + else + m_rest_bonus = rest_bonus_new; + + // update data for client + if(m_rest_bonus>10) + SetByteValue(PLAYER_BYTES_2, 3, 0x01); // Set Reststate = Rested + else if(m_rest_bonus<=1) + SetByteValue(PLAYER_BYTES_2, 3, 0x02); // Set Reststate = Normal + + //RestTickUpdate + SetUInt32Value(PLAYER_REST_STATE_EXPERIENCE, uint32(m_rest_bonus)); +} + +void Player::HandleStealthedUnitsDetection() +{ + std::list stealthedUnits; + + CellPair p(MaNGOS::ComputeCellPair(GetPositionX(),GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + MaNGOS::AnyStealthedCheck u_check; + MaNGOS::UnitListSearcher searcher(stealthedUnits, u_check); + + TypeContainerVisitor, WorldTypeMapContainer > world_unit_searcher(searcher); + TypeContainerVisitor, GridTypeMapContainer > grid_unit_searcher(searcher); + + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, world_unit_searcher, *MapManager::Instance().GetMap(GetMapId(), this)); + cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::Instance().GetMap(GetMapId(), this)); + + for (std::list::iterator i = stealthedUnits.begin(); i != stealthedUnits.end();) + { + if((*i)==this) + { + i = stealthedUnits.erase(i); + continue; + } + + if ((*i)->isVisibleForOrDetect(this,true)) + { + + (*i)->SendUpdateToPlayer(this); + m_clientGUIDs.insert((*i)->GetGUID()); + + #ifdef MANGOS_DEBUG + if((sLog.getLogFilter() & LOG_FILTER_VISIBILITY_CHANGES)==0) + sLog.outDebug("Object %u (Type: %u) is detected in stealth by player %u. Distance = %f",(*i)->GetGUIDLow(),(*i)->GetTypeId(),GetGUIDLow(),GetDistance(*i)); + #endif + + // target aura duration for caster show only if target exist at caster client + // send data at target visibility change (adding to client) + if((*i)!=this && (*i)->isType(TYPEMASK_UNIT)) + SendAuraDurationsForTarget(*i); + + i = stealthedUnits.erase(i); + continue; + } + + ++i; + } +} + +bool Player::ActivateTaxiPathTo(std::vector const& nodes, uint32 mount_id, Creature* npc) +{ + if(nodes.size() < 2) + return false; + + // not let cheating with start flight mounted + if(IsMounted()) + { + WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4); + data << uint32(ERR_TAXIPLAYERALREADYMOUNTED); + GetSession()->SendPacket(&data); + return false; + } + + if( m_ShapeShiftFormSpellId && m_form != FORM_BATTLESTANCE && m_form != FORM_BERSERKERSTANCE && m_form != FORM_DEFENSIVESTANCE && m_form != FORM_SHADOW ) + { + WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4); + data << uint32(ERR_TAXIPLAYERSHAPESHIFTED); + GetSession()->SendPacket(&data); + return false; + } + + // not let cheating with start flight in time of logout process || if casting not finished || while in combat || if not use Spell's with EffectSendTaxi + if(GetSession()->isLogingOut() || + (!m_currentSpells[CURRENT_GENERIC_SPELL] || + m_currentSpells[CURRENT_GENERIC_SPELL]->m_spellInfo->Effect[0] != SPELL_EFFECT_SEND_TAXI)&& + IsNonMeleeSpellCasted(false) || + isInCombat()) + { + WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4); + data << uint32(ERR_TAXIPLAYERBUSY); + GetSession()->SendPacket(&data); + return false; + } + + if(HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE)) + return false; + + uint32 sourcenode = nodes[0]; + + // starting node too far away (cheat?) + TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(sourcenode); + if( !node || node->map_id != GetMapId() || + (node->x - GetPositionX())*(node->x - GetPositionX())+ + (node->y - GetPositionY())*(node->y - GetPositionY())+ + (node->z - GetPositionZ())*(node->z - GetPositionZ()) > + (2*INTERACTION_DISTANCE)*(2*INTERACTION_DISTANCE)*(2*INTERACTION_DISTANCE) ) + { + WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4); + data << uint32(ERR_TAXIUNSPECIFIEDSERVERERROR); + GetSession()->SendPacket(&data); + return false; + } + + // Prepare to flight start now + + // stop combat at start taxi flight if any + CombatStop(); + + // stop trade (client cancel trade at taxi map open but cheating tools can be used for reopen it) + TradeCancel(true); + + // clean not finished taxi path if any + m_taxi.ClearTaxiDestinations(); + + // 0 element current node + m_taxi.AddTaxiDestination(sourcenode); + + // fill destinations path tail + uint32 sourcepath = 0; + uint32 totalcost = 0; + + uint32 prevnode = sourcenode; + uint32 lastnode = 0; + + for(uint32 i = 1; i < nodes.size(); ++i) + { + uint32 path, cost; + + lastnode = nodes[i]; + objmgr.GetTaxiPath(prevnode, lastnode, path, cost); + + if(!path) + { + m_taxi.ClearTaxiDestinations(); + return false; + } + + totalcost += cost; + + if(prevnode == sourcenode) + sourcepath = path; + + m_taxi.AddTaxiDestination(lastnode); + + prevnode = lastnode; + } + + if(!mount_id) // if not provide then attempt use default. + mount_id = objmgr.GetTaxiMount(sourcenode, GetTeam()); + + if (mount_id == 0 || sourcepath == 0) + { + WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4); + data << uint32(ERR_TAXIUNSPECIFIEDSERVERERROR); + GetSession()->SendPacket(&data); + m_taxi.ClearTaxiDestinations(); + return false; + } + + uint32 money = GetMoney(); + + if(npc) + { + totalcost = (uint32)ceil(totalcost*GetReputationPriceDiscount(npc)); + } + + if(money < totalcost) + { + WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4); + data << uint32(ERR_TAXINOTENOUGHMONEY); + GetSession()->SendPacket(&data); + m_taxi.ClearTaxiDestinations(); + return false; + } + + //Checks and preparations done, DO FLIGHT + ModifyMoney(-(int32)totalcost); + + // prevent stealth flight + RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4); + data << uint32(ERR_TAXIOK); + GetSession()->SendPacket(&data); + + sLog.outDebug("WORLD: Sent SMSG_ACTIVATETAXIREPLY"); + + GetSession()->SendDoFlight(mount_id, sourcepath); + + return true; +} + +void Player::ProhibitSpellScholl(SpellSchoolMask idSchoolMask, uint32 unTimeMs ) +{ + // last check 2.0.10 + WorldPacket data(SMSG_SPELL_COOLDOWN, 8+1+m_spells.size()*8); + data << GetGUID(); + data << uint8(0x0); + time_t curTime = time(NULL); + for(PlayerSpellMap::const_iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr) + { + if (itr->second->state == PLAYERSPELL_REMOVED) + continue; + uint32 unSpellId = itr->first; + SpellEntry const *spellInfo = sSpellStore.LookupEntry(unSpellId); + if (!spellInfo) + { + ASSERT(spellInfo); + continue; + } + + // Not send cooldown for this spells + if (spellInfo->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE) + continue; + + if((idSchoolMask & GetSpellSchoolMask(spellInfo)) && GetSpellCooldownDelay(unSpellId) < unTimeMs ) + { + data << unSpellId; + data << unTimeMs; // in m.secs + AddSpellCooldown(unSpellId, 0, curTime + unTimeMs/1000); + } + } + GetSession()->SendPacket(&data); +} + +void Player::InitDataForForm(bool reapplyMods) +{ + SpellShapeshiftEntry const* ssEntry = sSpellShapeshiftStore.LookupEntry(m_form); + if(ssEntry && ssEntry->attackSpeed) + { + SetAttackTime(BASE_ATTACK,ssEntry->attackSpeed); + SetAttackTime(OFF_ATTACK,ssEntry->attackSpeed); + SetAttackTime(RANGED_ATTACK, BASE_ATTACK_TIME); + } + else + SetRegularAttackTime(); + + switch(m_form) + { + case FORM_CAT: + { + if(getPowerType()!=POWER_ENERGY) + setPowerType(POWER_ENERGY); + break; + } + case FORM_BEAR: + case FORM_DIREBEAR: + { + if(getPowerType()!=POWER_RAGE) + setPowerType(POWER_RAGE); + break; + } + default: // 0, for example + { + ChrClassesEntry const* cEntry = sChrClassesStore.LookupEntry(getClass()); + if(cEntry && cEntry->powerType < MAX_POWERS && uint32(getPowerType()) != cEntry->powerType) + setPowerType(Powers(cEntry->powerType)); + break; + } + } + + // update auras at form change, ignore this at mods reapply (.reset stats/etc) when form not change. + if (!reapplyMods) + UpdateEquipSpellsAtFormChange(); + + UpdateAttackPowerAndDamage(); + UpdateAttackPowerAndDamage(true); +} + +// Return true is the bought item has a max count to force refresh of window by caller +bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint64 bagguid, uint8 slot) +{ + // cheating attempt + if(count < 1) count = 1; + + if(!isAlive()) + return false; + + ItemPrototype const *pProto = objmgr.GetItemPrototype( item ); + if( !pProto ) + { + SendBuyError( BUY_ERR_CANT_FIND_ITEM, NULL, item, 0); + return false; + } + + Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*this, vendorguid,UNIT_NPC_FLAG_VENDOR); + if (!pCreature) + { + sLog.outDebug( "WORLD: BuyItemFromVendor - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(vendorguid)) ); + SendBuyError( BUY_ERR_DISTANCE_TOO_FAR, NULL, item, 0); + return false; + } + + // load vendor items if not yet + pCreature->LoadGoods(); + + CreatureItem* crItem = pCreature->FindItem(item); + if(!crItem) + { + SendBuyError( BUY_ERR_CANT_FIND_ITEM, pCreature, item, 0); + return false; + } + + if( crItem->maxcount != 0 && crItem->count < count ) + { + SendBuyError( BUY_ERR_ITEM_ALREADY_SOLD, pCreature, item, 0); + return false; + } + + if( uint32(GetReputationRank(pProto->RequiredReputationFaction)) < pProto->RequiredReputationRank) + { + SendBuyError( BUY_ERR_REPUTATION_REQUIRE, pCreature, item, 0); + return false; + } + + if(crItem->ExtendedCost) + { + ItemExtendedCostEntry const* iece = sItemExtendedCostStore.LookupEntry(crItem->ExtendedCost); + if(!iece) + { + sLog.outError("Item %u have wrong ExtendedCost field value %u", pProto->ItemId, crItem->ExtendedCost); + return false; + } + + // honor points price + if(GetHonorPoints() < (iece->reqhonorpoints * count)) + { + SendEquipError(EQUIP_ERR_NOT_ENOUGH_HONOR_POINTS, NULL, NULL); + return false; + } + + // arena points price + if(GetArenaPoints() < (iece->reqarenapoints * count)) + { + SendEquipError(EQUIP_ERR_NOT_ENOUGH_ARENA_POINTS, NULL, NULL); + return false; + } + + // item base price + for (uint8 i = 0; i < 5; ++i) + { + if(iece->reqitem[i] && !HasItemCount(iece->reqitem[i], (iece->reqitemcount[i] * count))) + { + SendEquipError(EQUIP_ERR_VENDOR_MISSING_TURNINS, NULL, NULL); + return false; + } + } + + // check for personal arena rating requirement + if( GetMaxPersonalArenaRatingRequirement() < iece->reqpersonalarenarating ) + { + // probably not the proper equip err + SendEquipError(EQUIP_ERR_CANT_EQUIP_RANK,NULL,NULL); + return false; + } + } + + uint32 price = pProto->BuyPrice * count; + + // reputation discount + price = uint32(floor(price * GetReputationPriceDiscount(pCreature))); + + if( GetMoney() < price ) + { + SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, item, 0); + return false; + } + + uint8 bag = 0; // init for case invalid bagGUID + + if (bagguid != NULL_BAG && slot != NULL_SLOT) + { + Bag *pBag; + if( bagguid == GetGUID() ) + { + bag = INVENTORY_SLOT_BAG_0; + } + else + { + for (int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END;i++) + { + pBag = (Bag*)GetItemByPos(INVENTORY_SLOT_BAG_0,i); + if( pBag ) + { + if( bagguid == pBag->GetGUID() ) + { + bag = i; + break; + } + } + } + } + } + + if( IsInventoryPos( bag, slot ) || (bagguid == NULL_BAG && slot == NULL_SLOT) ) + { + ItemPosCountVec dest; + uint8 msg = CanStoreNewItem( bag, slot, dest, item, pProto->BuyCount * count ); + if( msg != EQUIP_ERR_OK ) + { + SendEquipError( msg, NULL, NULL ); + return false; + } + + ModifyMoney( -(int32)price ); + if(crItem->ExtendedCost) // case for new honor system + { + ItemExtendedCostEntry const* iece = sItemExtendedCostStore.LookupEntry(crItem->ExtendedCost); + if(iece->reqhonorpoints) + ModifyHonorPoints( - int32(iece->reqhonorpoints * count)); + if(iece->reqarenapoints) + ModifyArenaPoints( - int32(iece->reqarenapoints * count)); + for (uint8 i = 0; i < 5; ++i) + { + if(iece->reqitem[i]) + DestroyItemCount(iece->reqitem[i], (iece->reqitemcount[i] * count), true); + } + } + + if(Item *it = StoreNewItem( dest, item, true )) + { + if( crItem->maxcount != 0 ) + crItem->count -= pProto->BuyCount * count; + + WorldPacket data(SMSG_BUY_ITEM, (8+4+4+4)); + data << pCreature->GetGUID(); + data << (uint32)crItem->id; // entry + data << (uint32)crItem->count; + data << (uint32)count; + GetSession()->SendPacket(&data); + + SendNewItem(it, count, true, false, false); + } + } + else if( IsEquipmentPos( bag, slot ) ) + { + uint16 dest; + uint8 msg = CanEquipNewItem( slot, dest, item, pProto->BuyCount * count, false ); + if( msg != EQUIP_ERR_OK ) + { + SendEquipError( msg, NULL, NULL ); + return false; + } + + ModifyMoney( -(int32)price ); + if(crItem->ExtendedCost) // case for new honor system + { + ItemExtendedCostEntry const* iece = sItemExtendedCostStore.LookupEntry(crItem->ExtendedCost); + if(iece->reqhonorpoints) + ModifyHonorPoints( - int32(iece->reqhonorpoints)); + if(iece->reqarenapoints) + ModifyArenaPoints( - int32(iece->reqarenapoints)); + for (uint8 i = 0; i < 5; ++i) + { + if(iece->reqitem[i]) + DestroyItemCount(iece->reqitem[i], iece->reqitemcount[i], true); + } + } + + if(Item *it = EquipNewItem( dest, item, pProto->BuyCount * count, true )) + { + if( crItem->maxcount != 0 ) + crItem->count -= pProto->BuyCount * count; + + WorldPacket data(SMSG_BUY_ITEM, (8+4+4+4)); + data << pCreature->GetGUID(); + data << (uint32)crItem->id; // entry + data << (uint32)crItem->count; + data << (uint32)count; + GetSession()->SendPacket(&data); + + SendNewItem(it, count, true, false, false); + + AutoUnequipOffhandIfNeed(); + } + } + else + { + SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL ); + return false; + } + + return crItem->maxcount!=0?true:false; +} + +uint32 Player::GetMaxPersonalArenaRatingRequirement() +{ + // returns the maximal personal arena rating that can be used to purchase items requiring this condition + // the personal rating of the arena team must match the required limit as well + // so return max[in arenateams](min(personalrating[teamtype], teamrating[teamtype])) + uint32 max_personal_rating = 0; + for(int i = 0; i < MAX_ARENA_SLOT; ++i) + { + if(ArenaTeam * at = objmgr.GetArenaTeamById(GetArenaTeamId(i))) + { + uint32 p_rating = GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (i * 6) + 5); + uint32 t_rating = at->GetRating(); + p_rating = p_ratingSendPacket(&data); + } + // instance is valid, reset homebind timer + m_HomebindTimer = 0; + } + else if (m_HomebindTimer > 0) + { + if (time >= m_HomebindTimer) + { + // teleport to homebind location + TeleportTo(m_homebindMapId, m_homebindX, m_homebindY, m_homebindZ, GetOrientation()); + } + else + m_HomebindTimer -= time; + } + else + { + // instance is invalid, start homebind timer + m_HomebindTimer = 60000; + // send message to player + WorldPacket data(SMSG_RAID_GROUP_ONLY, 4+4); + data << m_HomebindTimer; + data << uint32(1); + GetSession()->SendPacket(&data); + sLog.outDebug("PLAYER: Player '%s' (GUID: %u) will be teleported to homebind in 60 seconds", GetName(),GetGUIDLow()); + } +} + +void Player::UpdatePvP(bool state, bool ovrride) +{ + if(!state || ovrride) + { + SetPvP(state); + if(Pet* pet = GetPet()) + pet->SetPvP(state); + if(Unit* charmed = GetCharm()) + charmed->SetPvP(state); + + pvpInfo.endTimer = 0; + } + else + { + if(pvpInfo.endTimer != 0) + pvpInfo.endTimer = time(NULL); + else + { + SetPvP(state); + + if(Pet* pet = GetPet()) + pet->SetPvP(state); + if(Unit* charmed = GetCharm()) + charmed->SetPvP(state); + } + } +} + +void Player::AddSpellCooldown(uint32 spellid, uint32 itemid, time_t end_time) +{ + SpellCooldown sc; + sc.end = end_time; + sc.itemid = itemid; + m_spellCooldowns[spellid] = sc; +} + +void Player::SendCooldownEvent(SpellEntry const *spellInfo) +{ + if ( !(spellInfo->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE) ) + return; + + // Get spell cooldwn + int32 cooldown = GetSpellRecoveryTime(spellInfo); + // Apply spellmods + ApplySpellMod(spellInfo->Id, SPELLMOD_COOLDOWN, cooldown); + if (cooldown < 0) + cooldown = 0; + // Add cooldown + AddSpellCooldown(spellInfo->Id, 0, time(NULL) + cooldown / 1000); + // Send activate + WorldPacket data(SMSG_COOLDOWN_EVENT, (4+8)); + data << spellInfo->Id; + data << GetGUID(); + SendDirectMessage(&data); +} + //slot to be excluded while counting +bool Player::EnchantmentFitsRequirements(uint32 enchantmentcondition, int8 slot) +{ + if(!enchantmentcondition) + return true; + + SpellItemEnchantmentConditionEntry const *Condition = sSpellItemEnchantmentConditionStore.LookupEntry(enchantmentcondition); + + if(!Condition) + return true; + + uint8 curcount[4] = {0, 0, 0, 0}; + + //counting current equipped gem colors + for(uint8 i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; ++i) + { + if(i == slot) + continue; + Item *pItem2 = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if(pItem2 && pItem2->GetProto()->Socket[0].Color) + { + for(uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+3; ++enchant_slot) + { + uint32 enchant_id = pItem2->GetEnchantmentId(EnchantmentSlot(enchant_slot)); + if(!enchant_id) + continue; + + SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id); + if(!enchantEntry) + continue; + + uint32 gemid = enchantEntry->GemID; + if(!gemid) + continue; + + ItemPrototype const* gemProto = sItemStorage.LookupEntry(gemid); + if(!gemProto) + continue; + + GemPropertiesEntry const* gemProperty = sGemPropertiesStore.LookupEntry(gemProto->GemProperties); + if(!gemProperty) + continue; + + uint8 GemColor = gemProperty->color; + + for(uint8 b = 0, tmpcolormask = 1; b < 4; b++, tmpcolormask <<= 1) + { + if(tmpcolormask & GemColor) + ++curcount[b]; + } + } + } + } + + bool activate = true; + + for(int i = 0; i < 5; i++) + { + if(!Condition->Color[i]) + continue; + + uint32 _cur_gem = curcount[Condition->Color[i] - 1]; + + // if have use them as count, else use from Condition + uint32 _cmp_gem = Condition->CompareColor[i] ? curcount[Condition->CompareColor[i] - 1]: Condition->Value[i]; + + switch(Condition->Comparator[i]) + { + case 2: // requires less than ( || ) gems + activate &= (_cur_gem < _cmp_gem) ? true : false; + break; + case 3: // requires more than ( || ) gems + activate &= (_cur_gem > _cmp_gem) ? true : false; + break; + case 5: // requires at least than ( || ) gems + activate &= (_cur_gem >= _cmp_gem) ? true : false; + break; + } + } + + sLog.outDebug("Checking Condition %u, there are %u Meta Gems, %u Red Gems, %u Yellow Gems and %u Blue Gems, Activate:%s", enchantmentcondition, curcount[0], curcount[1], curcount[2], curcount[3], activate ? "yes" : "no"); + + return activate; +} + +void Player::CorrectMetaGemEnchants(uint8 exceptslot, bool apply) +{ + //cycle all equipped items + for(uint32 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; ++slot) + { + //enchants for the slot being socketed are handled by Player::ApplyItemMods + if(slot == exceptslot) + continue; + + Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, slot ); + + if(!pItem || !pItem->GetProto()->Socket[0].Color) + continue; + + for(uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+3; ++enchant_slot) + { + uint32 enchant_id = pItem->GetEnchantmentId(EnchantmentSlot(enchant_slot)); + if(!enchant_id) + continue; + + SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id); + if(!enchantEntry) + continue; + + uint32 condition = enchantEntry->EnchantmentCondition; + if(condition) + { + //was enchant active with/without item? + bool wasactive = EnchantmentFitsRequirements(condition, apply ? exceptslot : -1); + //should it now be? + if(wasactive ^ EnchantmentFitsRequirements(condition, apply ? -1 : exceptslot)) + { + // ignore item gem conditions + //if state changed, (dis)apply enchant + ApplyEnchantment(pItem,EnchantmentSlot(enchant_slot),!wasactive,true,true); + } + } + } + } +} + + //if false -> then toggled off if was on| if true -> toggled on if was off AND meets requirements +void Player::ToggleMetaGemsActive(uint8 exceptslot, bool apply) +{ + //cycle all equipped items + for(int slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; ++slot) + { + //enchants for the slot being socketed are handled by WorldSession::HandleSocketOpcode(WorldPacket& recv_data) + if(slot == exceptslot) + continue; + + Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, slot ); + + if(!pItem || !pItem->GetProto()->Socket[0].Color) //if item has no sockets or no item is equipped go to next item + continue; + + //cycle all (gem)enchants + for(uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+3; ++enchant_slot) + { + uint32 enchant_id = pItem->GetEnchantmentId(EnchantmentSlot(enchant_slot)); + if(!enchant_id) //if no enchant go to next enchant(slot) + continue; + + SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id); + if(!enchantEntry) + continue; + + //only metagems to be (de)activated, so only enchants with condition + uint32 condition = enchantEntry->EnchantmentCondition; + if(condition) + ApplyEnchantment(pItem,EnchantmentSlot(enchant_slot), apply); + } + } +} + +void Player::LeaveBattleground(bool teleportToEntryPoint) +{ + if(BattleGround *bg = GetBattleGround()) + { + bool need_debuf = bg->isBattleGround() && (bg->GetStatus() == STATUS_IN_PROGRESS) && sWorld.getConfig(CONFIG_BATTLEGROUND_CAST_DESERTER); + + bg->RemovePlayerAtLeave(GetGUID(), teleportToEntryPoint, true); + + // call after remove to be sure that player resurrected for correct cast + if(need_debuf) + CastSpell(this, 26013, true); // Deserter + } +} + +bool Player::CanJoinToBattleground() const +{ + // check Deserter debuff + if(GetDummyAura(26013)) + return false; + + return true; +} + +bool Player::CanReportAfkDueToLimit() +{ + // a player can complain about 15 people per 5 minutes + if(m_bgAfkReportedCount >= 15) + return false; + ++m_bgAfkReportedCount; + return true; +} + +///This player has been blamed to be inactive in a battleground +void Player::ReportedAfkBy(Player* reporter) +{ + BattleGround *bg = GetBattleGround(); + if(!bg || bg != reporter->GetBattleGround() || GetTeam() != reporter->GetTeam()) + return; + + // check if player has 'Idle' or 'Inactive' debuff + if(m_bgAfkReporter.find(reporter->GetGUIDLow())==m_bgAfkReporter.end() && !HasAura(43680,0) && !HasAura(43681,0) && reporter->CanReportAfkDueToLimit()) + { + m_bgAfkReporter.insert(reporter->GetGUIDLow()); + // 3 players have to complain to apply debuff + if(m_bgAfkReporter.size() >= 3) + { + // cast 'Idle' spell + CastSpell(this, 43680, true); + m_bgAfkReporter.clear(); + } + } +} + +bool Player::IsVisibleInGridForPlayer( Player* pl ) const +{ + // gamemaster in GM mode see all, including ghosts + if(pl->isGameMaster() && GetSession()->GetSecurity() <= pl->GetSession()->GetSecurity()) + return true; + + // It seems in battleground everyone sees everyone, except the enemy-faction ghosts + if (InBattleGround()) + { + if (!(isAlive() || m_deathTimer > 0) && !IsFriendlyTo(pl) ) + return false; + return true; + } + + // Live player see live player or dead player with not realized corpse + if(pl->isAlive() || pl->m_deathTimer > 0) + { + return isAlive() || m_deathTimer > 0; + } + + // Ghost see other friendly ghosts, that's for sure + if(!(isAlive() || m_deathTimer > 0) && IsFriendlyTo(pl)) + return true; + + // Dead player see live players near own corpse + if(isAlive()) + { + Corpse *corpse = pl->GetCorpse(); + if(corpse) + { + // 20 - aggro distance for same level, 25 - max additional distance if player level less that creature level + if(corpse->IsWithinDistInMap(this,(20+25)*sWorld.getRate(RATE_CREATURE_AGGRO))) + return true; + } + } + + // and not see any other + return false; +} + +bool Player::IsVisibleGloballyFor( Player* u ) const +{ + if(!u) + return false; + + // Always can see self + if (u==this) + return true; + + // Visible units, always are visible for all players + if (GetVisibility() == VISIBILITY_ON) + return true; + + // GMs are visible for higher gms (or players are visible for gms) + if (u->GetSession()->GetSecurity() > SEC_PLAYER) + return GetSession()->GetSecurity() <= u->GetSession()->GetSecurity(); + + // non faction visibility non-breakable for non-GMs + if (GetVisibility() == VISIBILITY_OFF) + return false; + + // non-gm stealth/invisibility not hide from global player lists + return true; +} + +void Player::UpdateVisibilityOf(WorldObject* target) +{ + if(HaveAtClient(target)) + { + if(!target->isVisibleForInState(this,true)) + { + target->DestroyForPlayer(this); + m_clientGUIDs.erase(target->GetGUID()); + + #ifdef MANGOS_DEBUG + if((sLog.getLogFilter() & LOG_FILTER_VISIBILITY_CHANGES)==0) + sLog.outDebug("Object %u (Type: %u) out of range for player %u. Distance = %f",target->GetGUIDLow(),target->GetTypeId(),GetGUIDLow(),GetDistance(target)); + #endif + } + } + else + { + if(target->isVisibleForInState(this,false)) + { + target->SendUpdateToPlayer(this); + if(target->GetTypeId()!=TYPEID_GAMEOBJECT||!((GameObject*)target)->IsTransport()) + m_clientGUIDs.insert(target->GetGUID()); + + #ifdef MANGOS_DEBUG + if((sLog.getLogFilter() & LOG_FILTER_VISIBILITY_CHANGES)==0) + sLog.outDebug("Object %u (Type: %u) is visible now for player %u. Distance = %f",target->GetGUIDLow(),target->GetTypeId(),GetGUIDLow(),GetDistance(target)); + #endif + + // target aura duration for caster show only if target exist at caster client + // send data at target visibility change (adding to client) + if(target!=this && target->isType(TYPEMASK_UNIT)) + SendAuraDurationsForTarget((Unit*)target); + + if(target->GetTypeId()==TYPEID_UNIT && ((Creature*)target)->isAlive()) + ((Creature*)target)->SendMonsterMoveWithSpeedToCurrentDestination(this); + } + } +} + +template +inline void UpdateVisibilityOf_helper(std::set& s64, T* target) +{ + s64.insert(target->GetGUID()); +} + +template<> +inline void UpdateVisibilityOf_helper(std::set& s64, GameObject* target) +{ + if(!target->IsTransport()) + s64.insert(target->GetGUID()); +} + +template +void Player::UpdateVisibilityOf(T* target, UpdateData& data, UpdateDataMapType& data_updates, std::set& visibleNow) +{ + if(HaveAtClient(target)) + { + if(!target->isVisibleForInState(this,true)) + { + target->BuildOutOfRangeUpdateBlock(&data); + m_clientGUIDs.erase(target->GetGUID()); + + #ifdef MANGOS_DEBUG + if((sLog.getLogFilter() & LOG_FILTER_VISIBILITY_CHANGES)==0) + sLog.outDebug("Object %u (Type: %u, Entry: %u) is out of range for player %u. Distance = %f",target->GetGUIDLow(),target->GetTypeId(),target->GetEntry(),GetGUIDLow(),GetDistance(target)); + #endif + } + } + else + { + if(target->isVisibleForInState(this,false)) + { + visibleNow.insert(target); + target->BuildUpdate(data_updates); + target->BuildCreateUpdateBlockForPlayer(&data, this); + UpdateVisibilityOf_helper(m_clientGUIDs,target); + + #ifdef MANGOS_DEBUG + if((sLog.getLogFilter() & LOG_FILTER_VISIBILITY_CHANGES)==0) + sLog.outDebug("Object %u (Type: %u, Entry: %u) is visible now for player %u. Distance = %f",target->GetGUIDLow(),target->GetTypeId(),target->GetEntry(),GetGUIDLow(),GetDistance(target)); + #endif + } + } +} + +template void Player::UpdateVisibilityOf(Player* target, UpdateData& data, UpdateDataMapType& data_updates, std::set& visibleNow); +template void Player::UpdateVisibilityOf(Creature* target, UpdateData& data, UpdateDataMapType& data_updates, std::set& visibleNow); +template void Player::UpdateVisibilityOf(Corpse* target, UpdateData& data, UpdateDataMapType& data_updates, std::set& visibleNow); +template void Player::UpdateVisibilityOf(GameObject* target, UpdateData& data, UpdateDataMapType& data_updates, std::set& visibleNow); +template void Player::UpdateVisibilityOf(DynamicObject* target, UpdateData& data, UpdateDataMapType& data_updates, std::set& visibleNow); + +void Player::InitPrimaryProffesions() +{ + SetFreePrimaryProffesions(sWorld.getConfig(CONFIG_MAX_PRIMARY_TRADE_SKILL)); +} + +void Player::SendComboPoints() +{ + Unit *combotarget = ObjectAccessor::GetUnit(*this, m_comboTarget); + if (combotarget) + { + WorldPacket data(SMSG_UPDATE_COMBO_POINTS, combotarget->GetPackGUID().size()+1); + data.append(combotarget->GetPackGUID()); + data << uint8(m_comboPoints); + GetSession()->SendPacket(&data); + } +} + +void Player::AddComboPoints(Unit* target, int8 count) +{ + if(!count) + return; + + // without combo points lost (duration checked in aura) + RemoveSpellsCausingAura(SPELL_AURA_RETAIN_COMBO_POINTS); + + if(target->GetGUID() == m_comboTarget) + { + m_comboPoints += count; + } + else + { + if(m_comboTarget) + if(Unit* target = ObjectAccessor::GetUnit(*this,m_comboTarget)) + target->RemoveComboPointHolder(GetGUIDLow()); + + m_comboTarget = target->GetGUID(); + m_comboPoints = count; + + target->AddComboPointHolder(GetGUIDLow()); + } + + if (m_comboPoints > 5) m_comboPoints = 5; + if (m_comboPoints < 0) m_comboPoints = 0; + + SendComboPoints(); +} + +void Player::ClearComboPoints() +{ + if(!m_comboTarget) + return; + + // without combopoints lost (duration checked in aura) + RemoveSpellsCausingAura(SPELL_AURA_RETAIN_COMBO_POINTS); + + m_comboPoints = 0; + + SendComboPoints(); + + if(Unit* target = ObjectAccessor::GetUnit(*this,m_comboTarget)) + target->RemoveComboPointHolder(GetGUIDLow()); + + m_comboTarget = 0; +} + +void Player::SetGroup(Group *group, int8 subgroup) +{ + if(group == NULL) m_group.unlink(); + else + { + // never use SetGroup without a subgroup unless you specify NULL for group + assert(subgroup >= 0); + m_group.link(group, this); + m_group.setSubGroup((uint8)subgroup); + } +} + +void Player::SendInitialPacketsBeforeAddToMap() +{ + WorldPacket data(SMSG_SET_REST_START, 4); + data << uint32(0); // unknown, may be rest state time or expirience + GetSession()->SendPacket(&data); + + // Homebind + data.Initialize(SMSG_BINDPOINTUPDATE, 5*4); + data << m_homebindX << m_homebindY << m_homebindZ; + data << (uint32) m_homebindMapId; + data << (uint32) m_homebindZoneId; + GetSession()->SendPacket(&data); + + // SMSG_SET_PROFICIENCY + // SMSG_UPDATE_AURA_DURATION + + // tutorial stuff + data.Initialize(SMSG_TUTORIAL_FLAGS, 8*4); + for (int i = 0; i < 8; ++i) + data << uint32( GetTutorialInt(i) ); + GetSession()->SendPacket(&data); + + SendInitialSpells(); + + data.Initialize(SMSG_SEND_UNLEARN_SPELLS, 4); + data << uint32(0); // count, for(count) uint32; + GetSession()->SendPacket(&data); + + SendInitialActionButtons(); + SendInitialReputations(); + UpdateZone(GetZoneId()); + SendInitWorldStates(); + + // SMSG_SET_AURA_SINGLE + + data.Initialize(SMSG_LOGIN_SETTIMESPEED, 8); + data << uint32(secsToTimeBitFields(sWorld.GetGameTime())); + data << (float)0.01666667f; // game speed + GetSession()->SendPacket( &data ); +} + +void Player::SendInitialPacketsAfterAddToMap() +{ + CastSpell(this, 836, true); // LOGINEFFECT + + // set some aura effects that send packet to player client after add player to map + // SendMessageToSet not send it to player not it map, only for aura that not changed anything at re-apply + // same auras state lost at far teleport, send it one more time in this case also + static const AuraType auratypes[] = + { + SPELL_AURA_MOD_FEAR, SPELL_AURA_TRANSFORM, SPELL_AURA_WATER_WALK, + SPELL_AURA_FEATHER_FALL, SPELL_AURA_HOVER, SPELL_AURA_SAFE_FALL, + SPELL_AURA_FLY, SPELL_AURA_NONE + }; + for(AuraType const* itr = &auratypes[0]; itr && itr[0] != SPELL_AURA_NONE; ++itr) + { + Unit::AuraList const& auraList = GetAurasByType(*itr); + if(!auraList.empty()) + auraList.front()->ApplyModifier(true,true); + } + + if(HasAuraType(SPELL_AURA_MOD_STUN)) + SetMovement(MOVE_ROOT); + + // manual send package (have code in ApplyModifier(true,true); that don't must be re-applied. + if(HasAuraType(SPELL_AURA_MOD_ROOT)) + { + WorldPacket data(SMSG_FORCE_MOVE_ROOT, 10); + data.append(GetPackGUID()); + data << (uint32)2; + SendMessageToSet(&data,true); + } + + SendEnchantmentDurations(); // must be after add to map + SendItemDurations(); // must be after add to map +} + +void Player::SendUpdateToOutOfRangeGroupMembers() +{ + if (m_groupUpdateMask == GROUP_UPDATE_FLAG_NONE) + return; + if(Group* group = GetGroup()) + group->UpdatePlayerOutOfRange(this); + + m_groupUpdateMask = GROUP_UPDATE_FLAG_NONE; + m_auraUpdateMask = 0; + if(Pet *pet = GetPet()) + pet->ResetAuraUpdateMask(); +} + +void Player::SendTransferAborted(uint32 mapid, uint16 reason) +{ + WorldPacket data(SMSG_TRANSFER_ABORTED, 4+2); + data << uint32(mapid); + data << uint16(reason); // transfer abort reason + GetSession()->SendPacket(&data); +} + +void Player::SendInstanceResetWarning(uint32 mapid, uint32 time) +{ + // type of warning, based on the time remaining until reset + uint32 type; + if(time > 3600) + type = RAID_INSTANCE_WELCOME; + else if(time > 900 && time <= 3600) + type = RAID_INSTANCE_WARNING_HOURS; + else if(time > 300 && time <= 900) + type = RAID_INSTANCE_WARNING_MIN; + else + type = RAID_INSTANCE_WARNING_MIN_SOON; + WorldPacket data(SMSG_RAID_INSTANCE_MESSAGE, 4+4+4); + data << uint32(type); + data << uint32(mapid); + data << uint32(time); + GetSession()->SendPacket(&data); +} + +void Player::ApplyEquipCooldown( Item * pItem ) +{ + for(int i = 0; i <5; ++i) + { + _Spell const& spellData = pItem->GetProto()->Spells[i]; + + // no spell + if( !spellData.SpellId ) + continue; + + // wrong triggering type (note: ITEM_SPELLTRIGGER_ON_NO_DELAY_USE not have cooldown) + if( spellData.SpellTrigger != ITEM_SPELLTRIGGER_ON_USE ) + continue; + + AddSpellCooldown(spellData.SpellId, pItem->GetEntry(), time(NULL) + 30); + + WorldPacket data(SMSG_ITEM_COOLDOWN, 12); + data << pItem->GetGUID(); + data << uint32(spellData.SpellId); + GetSession()->SendPacket(&data); + } +} + +void Player::resetSpells() +{ + // not need after this call + if(HasAtLoginFlag(AT_LOGIN_RESET_SPELLS)) + { + m_atLoginFlags = m_atLoginFlags & ~AT_LOGIN_RESET_SPELLS; + CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login & ~ %u WHERE guid ='%u'", uint32(AT_LOGIN_RESET_SPELLS), GetGUIDLow()); + } + + // make full copy of map (spells removed and marked as deleted at another spell remove + // and we can't use original map for safe iterative with visit each spell at loop end + PlayerSpellMap smap = GetSpellMap(); + + for(PlayerSpellMap::const_iterator iter = smap.begin();iter != smap.end(); ++iter) + removeSpell(iter->first); // only iter->first can be accessed, object by iter->second can be deleted already + + learnDefaultSpells(); + learnQuestRewardedSpells(); +} + +void Player::learnDefaultSpells(bool loading) +{ + // learn default race/class spells + PlayerInfo const *info = objmgr.GetPlayerInfo(getRace(),getClass()); + std::list::const_iterator spell_itr; + for (spell_itr = info->spell.begin(); spell_itr!=info->spell.end(); ++spell_itr) + { + uint16 tspell = spell_itr->first; + if (tspell) + { + sLog.outDebug("PLAYER: Adding initial spell, id = %u",tspell); + if(loading || !spell_itr->second) // not care about passive spells or loading case + addSpell(tspell,spell_itr->second); + else // but send in normal spell in game learn case + learnSpell(tspell); + } + } +} + +void Player::learnQuestRewardedSpells(Quest const* quest) +{ + uint32 spell_id = quest->GetRewSpellCast(); + + // skip quests without rewarded spell + if( !spell_id ) + return; + + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id); + if(!spellInfo) + return; + + // check learned spells state + bool found = false; + for(int i=0; i < 3; ++i) + { + if(spellInfo->Effect[i] == SPELL_EFFECT_LEARN_SPELL && !HasSpell(spellInfo->EffectTriggerSpell[i])) + { + found = true; + break; + } + } + + // skip quests with not teaching spell or already known spell + if(!found) + return; + + // prevent learn non first rank unknown profession and second specialization for same profession) + uint32 learned_0 = spellInfo->EffectTriggerSpell[0]; + if( spellmgr.GetSpellRank(learned_0) > 1 && !HasSpell(learned_0) ) + { + // not have first rank learned (unlearned prof?) + uint32 first_spell = spellmgr.GetFirstSpellInChain(learned_0); + if( !HasSpell(first_spell) ) + return; + + SpellEntry const *learnedInfo = sSpellStore.LookupEntry(learned_0); + if(!learnedInfo) + return; + + // specialization + if(learnedInfo->Effect[0]==SPELL_EFFECT_TRADE_SKILL && learnedInfo->Effect[1]==0) + { + // search other specialization for same prof + for(PlayerSpellMap::const_iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr) + { + if(itr->second->state == PLAYERSPELL_REMOVED || itr->first==learned_0) + continue; + + SpellEntry const *itrInfo = sSpellStore.LookupEntry(itr->first); + if(!itrInfo) + return; + + // compare only specializations + if(itrInfo->Effect[0]!=SPELL_EFFECT_TRADE_SKILL || itrInfo->Effect[1]!=0) + continue; + + // compare same chain spells + if(spellmgr.GetFirstSpellInChain(itr->first) != first_spell) + continue; + + // now we have 2 specialization, learn possible only if found is lesser specialization rank + if(!spellmgr.IsHighRankOfSpell(learned_0,itr->first)) + return; + } + } + } + + CastSpell( this, spell_id, true); +} + +void Player::learnQuestRewardedSpells() +{ + // learn spells received from quest completing + for(QuestStatusMap::const_iterator itr = mQuestStatus.begin(); itr != mQuestStatus.end(); ++itr) + { + // skip no rewarded quests + if(!itr->second.m_rewarded) + continue; + + Quest const* quest = objmgr.GetQuestTemplate(itr->first); + if( !quest ) + continue; + + learnQuestRewardedSpells(quest); + } +} + +void Player::learnSkillRewardedSpells(uint32 skill_id ) +{ + uint32 raceMask = getRaceMask(); + uint32 classMask = getClassMask(); + for (uint32 j=0; jskillId!=skill_id || pAbility->learnOnGetSkill != ABILITY_LEARNED_ON_GET_PROFESSION_SKILL) + continue; + // Check race if set + if (pAbility->racemask && !(pAbility->racemask & raceMask)) + continue; + // Check class if set + if (pAbility->classmask && !(pAbility->classmask & classMask)) + continue; + + if (SpellEntry const* spellentry = sSpellStore.LookupEntry(pAbility->spellId)) + { + // Ok need learn spell + learnSpell(pAbility->spellId); + } + } +} + +void Player::learnSkillRewardedSpells() +{ + for (uint16 i=0; i < PLAYER_MAX_SKILLS; i++) + { + if(!GetUInt32Value(PLAYER_SKILL_INDEX(i))) + continue; + + uint32 pskill = GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF; + + learnSkillRewardedSpells(pskill); + } +} + +void Player::SendAuraDurationsForTarget(Unit* target) +{ + for(Unit::AuraMap::const_iterator itr = target->GetAuras().begin(); itr != target->GetAuras().end(); ++itr) + { + Aura* aura = itr->second; + if(aura->GetAuraSlot() >= MAX_AURAS || aura->IsPassive() || aura->GetCasterGUID()!=GetGUID()) + continue; + + aura->SendAuraDurationForCaster(this); + } +} + +void Player::SetDailyQuestStatus( uint32 quest_id ) +{ + for(uint32 quest_daily_idx = 0; quest_daily_idx < PLAYER_MAX_DAILY_QUESTS; ++quest_daily_idx) + { + if(!GetUInt32Value(PLAYER_FIELD_DAILY_QUESTS_1+quest_daily_idx)) + { + SetUInt32Value(PLAYER_FIELD_DAILY_QUESTS_1+quest_daily_idx,quest_id); + m_lastDailyQuestTime = time(NULL); // last daily quest time + m_DailyQuestChanged = true; + break; + } + } +} + +void Player::ResetDailyQuestStatus() +{ + for(uint32 quest_daily_idx = 0; quest_daily_idx < PLAYER_MAX_DAILY_QUESTS; ++quest_daily_idx) + SetUInt32Value(PLAYER_FIELD_DAILY_QUESTS_1+quest_daily_idx,0); + + // DB data deleted in caller + m_DailyQuestChanged = false; + m_lastDailyQuestTime = 0; +} + +BattleGround* Player::GetBattleGround() const +{ + if(GetBattleGroundId()==0) + return NULL; + + return sBattleGroundMgr.GetBattleGround(GetBattleGroundId()); +} + +bool Player::InArena() const +{ + BattleGround *bg = GetBattleGround(); + if(!bg || !bg->isArena()) + return false; + + return true; +} + +bool Player::GetBGAccessByLevel(uint32 bgTypeId) const +{ + BattleGround *bg = sBattleGroundMgr.GetBattleGround(bgTypeId); + if(!bg) + return false; + + if(getLevel() < bg->GetMinLevel() || getLevel() > bg->GetMaxLevel()) + return false; + + return true; +} + +uint32 Player::GetMinLevelForBattleGroundQueueId(uint32 queue_id) +{ + if(queue_id < 1) + return 0; + + if(queue_id >=6) + queue_id = 6; + + return 10*(queue_id+1); +} + +uint32 Player::GetMaxLevelForBattleGroundQueueId(uint32 queue_id) +{ + if(queue_id >=6) + return 255; // hardcoded max level + + return 10*(queue_id+2)-1; +} + +uint32 Player::GetBattleGroundQueueIdFromLevel() const +{ + uint32 level = getLevel(); + if(level <= 19) + return 0; + else if (level > 69) + return 6; + else + return level/10 - 1; // 20..29 -> 1, 30-39 -> 2, ... +} + +float Player::GetReputationPriceDiscount( Creature const* pCreature ) const +{ + FactionTemplateEntry const* vendor_faction = pCreature->getFactionTemplateEntry(); + if(!vendor_faction) + return 1.0f; + + ReputationRank rank = GetReputationRank(vendor_faction->faction); + if(rank <= REP_NEUTRAL) + return 1.0f; + + return 1.0f - 0.05f* (rank - REP_NEUTRAL); +} + +bool Player::IsSpellFitByClassAndRace( uint32 spell_id ) const +{ + uint32 racemask = getRaceMask(); + uint32 classmask = getClassMask(); + + SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(spell_id); + SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(spell_id); + + for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx) + { + // skip wrong race skills + if( _spell_idx->second->racemask && (_spell_idx->second->racemask & racemask) == 0) + return false; + + // skip wrong class skills + if( _spell_idx->second->classmask && (_spell_idx->second->classmask & classmask) == 0) + return false; + } + return true; +} + +bool Player::HasQuestForGO(int32 GOId) +{ + for( QuestStatusMap::iterator i = mQuestStatus.begin( ); i != mQuestStatus.end( ); ++i ) + { + QuestStatusData qs=i->second; + if (qs.m_status == QUEST_STATUS_INCOMPLETE) + { + Quest const* qinfo = objmgr.GetQuestTemplate(i->first); + if(!qinfo) + continue; + + if(GetGroup() && GetGroup()->isRaidGroup() && qinfo->GetType() != QUEST_TYPE_RAID) + continue; + + for (int j = 0; j < QUEST_OBJECTIVES_COUNT; j++) + { + if (qinfo->ReqCreatureOrGOId[j]>=0) //skip non GO case + continue; + + if((-1)*GOId == qinfo->ReqCreatureOrGOId[j] && qs.m_creatureOrGOcount[j] < qinfo->ReqCreatureOrGOCount[j]) + return true; + } + } + } + return false; +} + +void Player::UpdateForQuestsGO() +{ + if(m_clientGUIDs.empty()) + return; + + UpdateData udata; + WorldPacket packet; + for(ClientGUIDs::iterator itr=m_clientGUIDs.begin(); itr!=m_clientGUIDs.end(); ++itr) + { + if(IS_GAMEOBJECT_GUID(*itr)) + { + GameObject *obj = HashMapHolder::Find(*itr); + if(obj) + obj->BuildValuesUpdateBlockForPlayer(&udata,this); + } + } + udata.BuildPacket(&packet); + GetSession()->SendPacket(&packet); +} + +void Player::SummonIfPossible(bool agree) +{ + if(!agree) + { + m_summon_expire = 0; + return; + } + + // expire and auto declined + if(m_summon_expire < time(NULL)) + return; + + // stop taxi flight at summon + if(isInFlight()) + { + GetMotionMaster()->MovementExpired(); + m_taxi.ClearTaxiDestinations(); + } + + // drop flag at summon + if(BattleGround *bg = GetBattleGround()) + bg->EventPlayerDroppedFlag(this); + + m_summon_expire = 0; + + TeleportTo(m_summon_mapid, m_summon_x, m_summon_y, m_summon_z,GetOrientation()); +} + +void Player::RemoveItemDurations( Item *item ) +{ + for(ItemDurationList::iterator itr = m_itemDuration.begin();itr != m_itemDuration.end(); ++itr) + { + if(*itr==item) + { + m_itemDuration.erase(itr); + break; + } + } +} + +void Player::AddItemDurations( Item *item ) +{ + if(item->GetUInt32Value(ITEM_FIELD_DURATION)) + { + m_itemDuration.push_back(item); + item->SendTimeUpdate(this); + } +} + +void Player::AutoUnequipOffhandIfNeed() +{ + Item *offItem = GetItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND ); + if(!offItem) + return; + + Item *mainItem = GetItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND ); + + if(!mainItem || mainItem->GetProto()->InventoryType != INVTYPE_2HWEAPON) + return; + + ItemPosCountVec off_dest; + uint8 off_msg = CanStoreItem( NULL_BAG, NULL_SLOT, off_dest, offItem, false ); + if( off_msg == EQUIP_ERR_OK ) + { + RemoveItem(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND, true); + StoreItem( off_dest, offItem, true ); + } + else + { + sLog.outError("Player::EquipItem: Can's store offhand item at 2hand item equip for player (GUID: %u).",GetGUIDLow()); + } +} + +bool Player::HasItemFitToSpellReqirements(SpellEntry const* spellInfo, Item const* ignoreItem) +{ + if(spellInfo->EquippedItemClass < 0) + return true; + + // scan other equipped items for same requirements (mostly 2 daggers/etc) + // for optimize check 2 used cases only + switch(spellInfo->EquippedItemClass) + { + case ITEM_CLASS_WEAPON: + { + for(int i= EQUIPMENT_SLOT_MAINHAND; i < EQUIPMENT_SLOT_TABARD; ++i) + if(Item *item = GetItemByPos( INVENTORY_SLOT_BAG_0, i )) + if(item!=ignoreItem && item->IsFitToSpellRequirements(spellInfo)) + return true; + break; + } + case ITEM_CLASS_ARMOR: + { + // tabard not have dependent spells + for(int i= EQUIPMENT_SLOT_START; i< EQUIPMENT_SLOT_MAINHAND; ++i) + if(Item *item = GetItemByPos( INVENTORY_SLOT_BAG_0, i )) + if(item!=ignoreItem && item->IsFitToSpellRequirements(spellInfo)) + return true; + + // shields can be equipped to offhand slot + if(Item *item = GetItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND)) + if(item!=ignoreItem && item->IsFitToSpellRequirements(spellInfo)) + return true; + + // ranged slot can have some armor subclasses + if(Item *item = GetItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED)) + if(item!=ignoreItem && item->IsFitToSpellRequirements(spellInfo)) + return true; + + break; + } + default: + sLog.outError("HasItemFitToSpellReqirements: Not handeled spell reqirement for item class %u",spellInfo->EquippedItemClass); + break; + } + + return false; +} + +void Player::RemoveItemDependentAurasAndCasts( Item * pItem ) +{ + AuraMap& auras = GetAuras(); + for(AuraMap::iterator itr = auras.begin(); itr != auras.end(); ) + { + Aura* aura = itr->second; + + // skip passive (passive item dependent spells work in another way) and not self applied auras + SpellEntry const* spellInfo = aura->GetSpellProto(); + if(aura->IsPassive() || aura->GetCasterGUID()!=GetGUID()) + { + ++itr; + continue; + } + + // skip if not item dependent or have alternative item + if(HasItemFitToSpellReqirements(spellInfo,pItem)) + { + ++itr; + continue; + } + + // no alt item, remove aura, restart check + RemoveAurasDueToSpell(aura->GetId()); + itr = auras.begin(); + } + + // currently casted spells can be dependent from item + for (uint32 i = 0; i < CURRENT_MAX_SPELL; i++) + { + if( m_currentSpells[i] && m_currentSpells[i]->getState()!=SPELL_STATE_DELAYED && + !HasItemFitToSpellReqirements(m_currentSpells[i]->m_spellInfo,pItem) ) + InterruptSpell(i); + } +} + +uint32 Player::GetResurrectionSpellId() +{ + // search priceless resurrection possabilities + uint32 prio = 0; + uint32 spell_id = 0; + AuraList const& dummyAuras = GetAurasByType(SPELL_AURA_DUMMY); + for(AuraList::const_iterator itr = dummyAuras.begin(); itr != dummyAuras.end(); ++itr) + { + // Soulstone Resurrection // prio: 3 (max, non death persistent) + if( prio < 2 && (*itr)->GetSpellProto()->SpellVisual == 99 && (*itr)->GetSpellProto()->SpellIconID == 92 ) + { + switch((*itr)->GetId()) + { + case 20707: spell_id = 3026; break; // rank 1 + case 20762: spell_id = 20758; break; // rank 2 + case 20763: spell_id = 20759; break; // rank 3 + case 20764: spell_id = 20760; break; // rank 4 + case 20765: spell_id = 20761; break; // rank 5 + case 27239: spell_id = 27240; break; // rank 6 + default: + sLog.outError("Unhandled spell %%u: S.Resurrection",(*itr)->GetId()); + continue; + } + + prio = 3; + } + // Twisting Nether // prio: 2 (max) + else if((*itr)->GetId()==23701 && roll_chance_i(10)) + { + prio = 2; + spell_id = 23700; + } + } + + // Reincarnation (passive spell) // prio: 1 + if(prio < 1 && HasSpell(20608) && !HasSpellCooldown(21169) && HasItemCount(17030,1)) + spell_id = 21169; + + return spell_id; +} + +bool Player::RewardPlayerAndGroupAtKill(Unit* pVictim) +{ + bool PvP = pVictim->isCharmedOwnedByPlayerOrPlayer(); + + // prepare data for near group iteration (PvP and !PvP cases) + uint32 xp = 0; + bool honored_kill = false; + + if(Group *pGroup = GetGroup()) + { + uint32 count = 0; + uint32 sum_level = 0; + Player* member_with_max_level = NULL; + + pGroup->GetDataForXPAtKill(pVictim,count,sum_level,member_with_max_level); + + if(member_with_max_level) + { + xp = PvP ? 0 : MaNGOS::XP::Gain(member_with_max_level, pVictim); + + // skip in check PvP case (for speed, not used) + bool is_raid = PvP ? false : sMapStore.LookupEntry(GetMapId())->IsRaid() && pGroup->isRaidGroup(); + bool is_dungeon = PvP ? false : sMapStore.LookupEntry(GetMapId())->IsDungeon(); + float group_rate = MaNGOS::XP::xp_in_group_rate(count,is_raid); + + for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player* pGroupGuy = itr->getSource(); + if(!pGroupGuy) + continue; + + if(!pGroupGuy->IsAtGroupRewardDistance(pVictim)) + continue; // member (alive or dead) or his corpse at req. distance + + // honor can be in PvP and !PvP (racial leader) cases (for alive) + if(pGroupGuy->isAlive() && pGroupGuy->RewardHonor(pVictim,count) && pGroupGuy==this) + honored_kill = true; + + // xp and reputation only in !PvP case + if(!PvP) + { + float rate = group_rate * float(pGroupGuy->getLevel()) / sum_level; + + // if is in dungeon then all receive full reputation at kill + // rewarded any alive/dead/near_corpse group member + pGroupGuy->RewardReputation(pVictim,is_dungeon ? 1.0f : rate); + + // XP updated only for alive group member + if(pGroupGuy->isAlive()) + { + uint32 itr_xp = uint32(xp*rate); + + pGroupGuy->GiveXP(itr_xp, pVictim); + if(Pet* pet = pGroupGuy->GetPet()) + pet->GivePetXP(itr_xp/2); + } + + // quest objectives updated only for alive group member or dead but with not released body + if(pGroupGuy->isAlive()|| !pGroupGuy->GetCorpse()) + { + // normal creature (not pet/etc) can be only in !PvP case + if(pVictim->GetTypeId()==TYPEID_UNIT) + pGroupGuy->KilledMonster(pVictim->GetEntry(), pVictim->GetGUID()); + } + } + } + } + } + else // if (!pGroup) + { + xp = PvP ? 0 : MaNGOS::XP::Gain(this, pVictim); + + // honor can be in PvP and !PvP (racial leader) cases + if(RewardHonor(pVictim,1)) + honored_kill = true; + + // xp and reputation only in !PvP case + if(!PvP) + { + RewardReputation(pVictim,1); + GiveXP(xp, pVictim); + + if(Pet* pet = GetPet()) + pet->GivePetXP(xp); + + // normal creature (not pet/etc) can be only in !PvP case + if(pVictim->GetTypeId()==TYPEID_UNIT) + KilledMonster(pVictim->GetEntry(),pVictim->GetGUID()); + } + } + return xp || honored_kill; +} + +bool Player::IsAtGroupRewardDistance(WorldObject const* pRewardSource) const +{ + if(pRewardSource->GetDistance(this) <= sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE)) + return true; + + if(isAlive()) + return false; + + Corpse* corpse = GetCorpse(); + if(!corpse) + return false; + + return pRewardSource->GetDistance(corpse) <= sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE); +} + +uint32 Player::GetBaseWeaponSkillValue (WeaponAttackType attType) const +{ + Item* item = GetWeaponForAttack(attType,true); + + // unarmmed only with base attack + if(attType != BASE_ATTACK && !item) + return 0; + + // weapon skill or (unarmed for base attack) + uint32 skill = item ? item->GetSkill() : SKILL_UNARMED; + return GetBaseSkillValue(skill); +} + +void Player::ResurectUsingRequestData() +{ + ResurrectPlayer(0.0f,false); + + if(GetMaxHealth() > m_resurrectHealth) + SetHealth( m_resurrectHealth ); + else + SetHealth( GetMaxHealth() ); + + if(GetMaxPower(POWER_MANA) > m_resurrectMana) + SetPower(POWER_MANA, m_resurrectMana ); + else + SetPower(POWER_MANA, GetMaxPower(POWER_MANA) ); + + SetPower(POWER_RAGE, 0 ); + + SetPower(POWER_ENERGY, GetMaxPower(POWER_ENERGY) ); + + SpawnCorpseBones(); + + TeleportTo(m_resurrectMap, m_resurrectX, m_resurrectY, m_resurrectZ, GetOrientation()); +} + +void Player::SetClientControl(Unit* target, uint8 allowMove) +{ + WorldPacket data(SMSG_CLIENT_CONTROL_UPDATE, target->GetPackGUID().size()+1); + data.append(target->GetPackGUID()); + data << uint8(allowMove); + GetSession()->SendPacket(&data); +} + +void Player::UpdateZoneDependentAuras( uint32 newZone ) +{ + // remove new continent flight forms + if( !isGameMaster() && + GetVirtualMapForMapAndZone(GetMapId(),newZone) != 530) + { + RemoveSpellsCausingAura(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED); + RemoveSpellsCausingAura(SPELL_AURA_FLY); + } + + // Some spells applied at enter into zone (with subzones) + // Human Illusion + // NOTE: these are removed by RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CHANGE_MAP); + if ( newZone == 2367 ) // Old Hillsbrad Foothills + { + uint32 spellid = 0; + // all horde races + if( GetTeam() == HORDE ) + spellid = getGender() == GENDER_FEMALE ? 35481 : 35480; + // and some alliance races + else if( getRace() == RACE_NIGHTELF || getRace() == RACE_DRAENEI ) + spellid = getGender() == GENDER_FEMALE ? 35483 : 35482; + + if(spellid && !HasAura(spellid,0) ) + CastSpell(this,spellid,true); + } +} + +void Player::UpdateAreaDependentAuras( uint32 newArea ) +{ + // remove auras from spells with area limitations + for(AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();) + { + // use m_zoneUpdateId for speed: UpdateArea called from UpdateZone or instead UpdateZone in both cases m_zoneUpdateId up-to-date + if(!IsSpellAllowedInLocation(iter->second->GetSpellProto(),GetMapId(),m_zoneUpdateId,newArea)) + RemoveAura(iter); + else + ++iter; + } + + // unmount if enter in this subzone + if( newArea == 35) + RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); + // Dragonmaw Illusion + else if( newArea == 3759 || newArea == 3966 || newArea == 3939 ) + { + if( GetDummyAura(40214) ) + { + if( !HasAura(40216,0) ) + CastSpell(this,40216,true); + if( !HasAura(42016,0) ) + CastSpell(this,42016,true); + } + } +} + +uint32 Player::GetCorpseReclaimDelay(bool pvp) const +{ + if( pvp && !sWorld.getConfig(CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVP) || + !pvp && !sWorld.getConfig(CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVE) ) + { + return copseReclaimDelay[0]; + } + + time_t now = time(NULL); + // 0..2 full period + uint32 count = (now < m_deathExpireTime) ? (m_deathExpireTime - now)/DEATH_EXPIRE_STEP : 0; + return copseReclaimDelay[count]; +} + +void Player::UpdateCorpseReclaimDelay() +{ + bool pvp = m_ExtraFlags & PLAYER_EXTRA_PVP_DEATH; + + if( pvp && !sWorld.getConfig(CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVP) || + !pvp && !sWorld.getConfig(CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVE) ) + return; + + time_t now = time(NULL); + if(now < m_deathExpireTime) + { + // full and partly periods 1..3 + uint32 count = (m_deathExpireTime - now)/DEATH_EXPIRE_STEP +1; + if(count < MAX_DEATH_COUNT) + m_deathExpireTime = now+(count+1)*DEATH_EXPIRE_STEP; + else + m_deathExpireTime = now+MAX_DEATH_COUNT*DEATH_EXPIRE_STEP; + } + else + m_deathExpireTime = now+DEATH_EXPIRE_STEP; +} + +void Player::SendCorpseReclaimDelay(bool load) +{ + Corpse* corpse = GetCorpse(); + if(!corpse) + return; + + uint32 delay; + if(load) + { + if(corpse->GetGhostTime() > m_deathExpireTime) + return; + + bool pvp = corpse->GetType()==CORPSE_RESURRECTABLE_PVP; + + uint32 count; + if( pvp && sWorld.getConfig(CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVP) || + !pvp && sWorld.getConfig(CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVE) ) + { + count = (m_deathExpireTime-corpse->GetGhostTime())/DEATH_EXPIRE_STEP; + if(count>=MAX_DEATH_COUNT) + count = MAX_DEATH_COUNT-1; + } + else + count=0; + + time_t expected_time = corpse->GetGhostTime()+copseReclaimDelay[count]; + + time_t now = time(NULL); + if(now >= expected_time) + return; + + delay = expected_time-now; + } + else + delay = GetCorpseReclaimDelay(corpse->GetType()==CORPSE_RESURRECTABLE_PVP); + + //! corpse reclaim delay 30 * 1000ms or longer at often deaths + WorldPacket data(SMSG_CORPSE_RECLAIM_DELAY, 4); + data << uint32(delay*1000); + GetSession()->SendPacket( &data ); +} + +Player* Player::GetNextRandomRaidMember(float radius) +{ + Group *pGroup = GetGroup(); + if(!pGroup) + return NULL; + + std::vector nearMembers; + nearMembers.reserve(pGroup->GetMembersCount()); + + for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player* Target = itr->getSource(); + + // IsHostileTo check duel and controlled by enemy + if( Target && Target != this && IsWithinDistInMap(Target, radius) && + !Target->HasInvisibilityAura() && !IsHostileTo(Target) ) + nearMembers.push_back(Target); + } + + if (nearMembers.empty()) + return NULL; + + uint32 randTarget = urand(0,nearMembers.size()-1); + return nearMembers[randTarget]; +} + +void Player::UpdateUnderwaterState( Map* m, float x, float y, float z ) +{ + float water_z = m->GetWaterLevel(x,y); + float height_z = m->GetHeight(x,y,z, false); // use .map base surface height + uint8 flag1 = m->GetTerrainType(x,y); + + //!Underwater check, not in water if underground or above water level + if (height_z <= INVALID_HEIGHT || z < (height_z-2) || z > (water_z - 2) ) + m_isunderwater &= 0x7A; + else if ((z < (water_z - 2)) && (flag1 & 0x01)) + m_isunderwater |= 0x01; + + //!in lava check, anywhere under lava level + if ((height_z <= INVALID_HEIGHT || z < (height_z - 0)) && (flag1 == 0x00) && IsInWater()) + m_isunderwater |= 0x80; +} + +bool ItemPosCount::isContainedIn(ItemPosCountVec &vec) +{ + for(ItemPosCountVec::const_iterator itr = vec.begin(); itr != vec.end();++itr) + { + if(itr->pos == this->pos/* && itr->count == this.count*/) + { + return true; + } + } + return false; +} + diff --git a/src/game/Player.h b/src/game/Player.h new file mode 100644 index 00000000000..d30d8e56622 --- /dev/null +++ b/src/game/Player.h @@ -0,0 +1,2310 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _PLAYER_H +#define _PLAYER_H + +#include "Common.h" +#include "ItemPrototype.h" +#include "Unit.h" +#include "Item.h" + +#include "Database/DatabaseEnv.h" +#include "NPCHandler.h" +#include "QuestDef.h" +#include "Group.h" +#include "Bag.h" +#include "WorldSession.h" +#include "Pet.h" +#include "Util.h" // for Tokens typedef + +#include +#include + +struct Mail; +class Channel; +class DynamicObject; +class Creature; +class Pet; +class PlayerMenu; +class Transport; +class UpdateMask; +class PlayerSocial; + +typedef std::deque PlayerMails; + +#define PLAYER_MAX_SKILLS 127 +#define PLAYER_MAX_DAILY_QUESTS 25 + +// Note: SPELLMOD_* values is aura types in fact +enum SpellModType +{ + SPELLMOD_FLAT = 107, // SPELL_AURA_ADD_FLAT_MODIFIER + SPELLMOD_PCT = 108 // SPELL_AURA_ADD_PCT_MODIFIER +}; + +enum PlayerSpellState +{ + PLAYERSPELL_UNCHANGED = 0, + PLAYERSPELL_CHANGED = 1, + PLAYERSPELL_NEW = 2, + PLAYERSPELL_REMOVED = 3 +}; + +struct PlayerSpell +{ + uint16 slotId : 16; + PlayerSpellState state : 8; + bool active : 1; + bool disabled : 1; +}; + +#define SPELL_WITHOUT_SLOT_ID uint16(-1) + +struct SpellModifier +{ + SpellModOp op : 8; + SpellModType type : 8; + int16 charges : 16; + int32 value; + uint64 mask; + uint32 spellId; + uint32 effectId; + Spell const* lastAffected; +}; + +typedef HM_NAMESPACE::hash_map PlayerSpellMap; +typedef std::list SpellModList; + +struct SpellCooldown +{ + time_t end; + uint16 itemid; +}; + +typedef std::map SpellCooldowns; + +enum TrainerSpellState +{ + TRAINER_SPELL_GREEN = 0, + TRAINER_SPELL_RED = 1, + TRAINER_SPELL_GRAY = 2 +}; + +enum ActionButtonUpdateState +{ + ACTIONBUTTON_UNCHANGED = 0, + ACTIONBUTTON_CHANGED = 1, + ACTIONBUTTON_NEW = 2, + ACTIONBUTTON_DELETED = 3 +}; + +struct ActionButton +{ + ActionButton() : action(0), type(0), misc(0), uState( ACTIONBUTTON_NEW ) {} + ActionButton(uint16 _action, uint8 _type, uint8 _misc) : action(_action), type(_type), misc(_misc), uState( ACTIONBUTTON_NEW ) {} + + uint16 action; + uint8 type; + uint8 misc; + ActionButtonUpdateState uState; +}; + +enum ActionButtonType +{ + ACTION_BUTTON_SPELL = 0, + ACTION_BUTTON_MACRO = 64, + ACTION_BUTTON_CMACRO= 65, + ACTION_BUTTON_ITEM = 128 +}; + +#define MAX_ACTION_BUTTONS 132 //checked in 2.3.0 + +typedef std::map ActionButtonList; + +typedef std::pair CreateSpellPair; + +struct PlayerCreateInfoItem +{ + PlayerCreateInfoItem(uint32 id, uint32 amount) : item_id(id), item_amount(amount) {} + + uint32 item_id; + uint32 item_amount; +}; + +typedef std::list PlayerCreateInfoItems; + +struct PlayerClassLevelInfo +{ + PlayerClassLevelInfo() : basehealth(0), basemana(0) {} + uint16 basehealth; + uint16 basemana; +}; + +struct PlayerClassInfo +{ + PlayerClassInfo() : levelInfo(NULL) { } + + PlayerClassLevelInfo* levelInfo; //[level-1] 0..MaxPlayerLevel-1 +}; + +struct PlayerLevelInfo +{ + PlayerLevelInfo() { for(int i=0; i < MAX_STATS; ++i ) stats[i] = 0; } + + uint8 stats[MAX_STATS]; +}; + +struct PlayerInfo +{ + // existence checked by displayId != 0 // existence checked by displayId != 0 + PlayerInfo() : displayId_m(0),displayId_f(0),levelInfo(NULL) + { + } + + uint32 mapId; + uint32 zoneId; + float positionX; + float positionY; + float positionZ; + uint16 displayId_m; + uint16 displayId_f; + PlayerCreateInfoItems item; + std::list spell; + std::list action[4]; + + PlayerLevelInfo* levelInfo; //[level-1] 0..MaxPlayerLevel-1 +}; + +struct PvPInfo +{ + PvPInfo() : inHostileArea(false), endTimer(0) {} + + bool inHostileArea; + time_t endTimer; +}; + +struct DuelInfo +{ + DuelInfo() : initiator(NULL), opponent(NULL), startTimer(0), startTime(0), outOfBound(0) {} + + Player *initiator; + Player *opponent; + time_t startTimer; + time_t startTime; + time_t outOfBound; +}; + +struct Areas +{ + uint32 areaID; + uint32 areaFlag; + float x1; + float x2; + float y1; + float y2; +}; + +enum FactionFlags +{ + FACTION_FLAG_VISIBLE = 0x01, // makes visible in client (set or can be set at interaction with target of this faction) + FACTION_FLAG_AT_WAR = 0x02, // enable AtWar-button in client. player controlled (except opposition team always war state), Flag only set on initial creation + FACTION_FLAG_HIDDEN = 0x04, // hidden faction from reputation pane in client (player can gain reputation, but this update not sent to client) + FACTION_FLAG_INVISIBLE_FORCED = 0x08, // always overwrite FACTION_FLAG_VISIBLE and hide faction in rep.list, used for hide opposite team factions + FACTION_FLAG_PEACE_FORCED = 0x10, // always overwrite FACTION_FLAG_AT_WAR, used for prevent war with own team factions + FACTION_FLAG_INACTIVE = 0x20, // player controlled, state stored in characters.data ( CMSG_SET_FACTION_INACTIVE ) + FACTION_FLAG_RIVAL = 0x40 // flag for the two competing outland factions +}; + +typedef uint32 RepListID; +struct FactionState +{ + uint32 ID; + RepListID ReputationListID; + uint32 Flags; + int32 Standing; + bool Changed; +}; + +typedef std::map FactionStateList; + +typedef std::map ForcedReactions; + +typedef std::set GuardianPetList; + +struct EnchantDuration +{ + EnchantDuration() : item(NULL), slot(MAX_ENCHANTMENT_SLOT), leftduration(0) {}; + EnchantDuration(Item * _item, EnchantmentSlot _slot, uint32 _leftduration) : item(_item), slot(_slot), leftduration(_leftduration) { assert(item); }; + + Item * item; + EnchantmentSlot slot; + uint32 leftduration; +}; + +typedef std::list EnchantDurationList; +typedef std::list ItemDurationList; + +struct LookingForGroupSlot +{ + LookingForGroupSlot() : entry(0), type(0) {} + bool Empty() const { return !entry && !type; } + void Clear() { entry = 0; type = 0; } + void Set(uint32 _entry, uint32 _type ) { entry = _entry; type = _type; } + bool Is(uint32 _entry, uint32 _type) const { return entry==_entry && type==_type; } + bool canAutoJoin() const { return entry && (type == 1 || type == 5); } + + uint32 entry; + uint32 type; +}; + +#define MAX_LOOKING_FOR_GROUP_SLOT 3 + +struct LookingForGroup +{ + LookingForGroup() {} + bool HaveInSlot(LookingForGroupSlot const& slot) const { return HaveInSlot(slot.entry,slot.type); } + bool HaveInSlot(uint32 _entry, uint32 _type) const + { + for(int i = 0; i < MAX_LOOKING_FOR_GROUP_SLOT; ++i) + if(slots[i].Is(_entry,_type)) + return true; + return false; + } + + bool canAutoJoin() const + { + for(int i = 0; i < MAX_LOOKING_FOR_GROUP_SLOT; ++i) + if(slots[i].canAutoJoin()) + return true; + return false; + } + + bool Empty() const + { + for(int i = 0; i < MAX_LOOKING_FOR_GROUP_SLOT; ++i) + if(!slots[i].Empty()) + return false; + return more.Empty(); + } + + LookingForGroupSlot slots[MAX_LOOKING_FOR_GROUP_SLOT]; + LookingForGroupSlot more; + std::string comment; +}; + +enum PlayerMovementType +{ + MOVE_ROOT = 1, + MOVE_UNROOT = 2, + MOVE_WATER_WALK = 3, + MOVE_LAND_WALK = 4 +}; + +enum DrunkenState +{ + DRUNKEN_SOBER = 0, + DRUNKEN_TIPSY = 1, + DRUNKEN_DRUNK = 2, + DRUNKEN_SMASHED = 3 +}; + +enum PlayerStateType +{ + /* + PLAYER_STATE_DANCE + PLAYER_STATE_SLEEP + PLAYER_STATE_SIT + PLAYER_STATE_STAND + PLAYER_STATE_READYUNARMED + PLAYER_STATE_WORK + PLAYER_STATE_POINT(DNR) + PLAYER_STATE_NONE // not used or just no state, just standing there? + PLAYER_STATE_STUN + PLAYER_STATE_DEAD + PLAYER_STATE_KNEEL + PLAYER_STATE_USESTANDING + PLAYER_STATE_STUN_NOSHEATHE + PLAYER_STATE_USESTANDING_NOSHEATHE + PLAYER_STATE_WORK_NOSHEATHE + PLAYER_STATE_SPELLPRECAST + PLAYER_STATE_READYRIFLE + PLAYER_STATE_WORK_NOSHEATHE_MINING + PLAYER_STATE_WORK_NOSHEATHE_CHOPWOOD + PLAYER_STATE_AT_EASE + PLAYER_STATE_READY1H + PLAYER_STATE_SPELLKNEELSTART + PLAYER_STATE_SUBMERGED + */ + + PLAYER_STATE_NONE = 0, + PLAYER_STATE_SIT = 1, + PLAYER_STATE_SIT_CHAIR = 2, + PLAYER_STATE_SLEEP = 3, + PLAYER_STATE_SIT_LOW_CHAIR = 4, + PLAYER_STATE_SIT_MEDIUM_CHAIR = 5, + PLAYER_STATE_SIT_HIGH_CHAIR = 6, + PLAYER_STATE_DEAD = 7, + PLAYER_STATE_KNEEL = 8, + + PLAYER_STATE_FORM_ALL = 0x00FF0000, + + PLAYER_STATE_FLAG_ALWAYS_STAND = 0x01, // byte 4 + PLAYER_STATE_FLAG_CREEP = 0x02000000, + PLAYER_STATE_FLAG_UNTRACKABLE = 0x04000000, + PLAYER_STATE_FLAG_ALL = 0xFF000000, +}; + +enum PlayerFlags +{ + PLAYER_FLAGS_GROUP_LEADER = 0x00000001, + PLAYER_FLAGS_AFK = 0x00000002, + PLAYER_FLAGS_DND = 0x00000004, + PLAYER_FLAGS_GM = 0x00000008, + PLAYER_FLAGS_GHOST = 0x00000010, + PLAYER_FLAGS_RESTING = 0x00000020, + PLAYER_FLAGS_FFA_PVP = 0x00000080, + PLAYER_FLAGS_CONTESTED_PVP = 0x00000100, // Player has been involved in a PvP combat and will be attacked by contested guards + PLAYER_FLAGS_IN_PVP = 0x00000200, + PLAYER_FLAGS_HIDE_HELM = 0x00000400, + PLAYER_FLAGS_HIDE_CLOAK = 0x00000800, + PLAYER_FLAGS_UNK1 = 0x00001000, // played long time + PLAYER_FLAGS_UNK2 = 0x00002000, // played too long time + PLAYER_FLAGS_UNK3 = 0x00008000, // strange visual effect (2.0.1), looks like PLAYER_FLAGS_GHOST flag + PLAYER_FLAGS_SANCTUARY = 0x00010000, // player entered sanctuary + PLAYER_FLAGS_UNK4 = 0x00020000, // taxi benchmark mode (on/off) (2.0.1) + PLAYER_UNK = 0x00040000, // 2.0.8... +}; + +// used for PLAYER__FIELD_KNOWN_TITLES field (uint64), (1< QuestStatusMap; + +enum QuestSlotOffsets +{ + QUEST_ID_OFFSET = 0, + QUEST_STATE_OFFSET = 1, + QUEST_COUNTS_OFFSET = 2, + QUEST_TIME_OFFSET = 3 +}; + +#define MAX_QUEST_OFFSET 4 + +enum QuestSlotStateMask +{ + QUEST_STATE_NONE = 0x0000, + QUEST_STATE_COMPLETE = 0x0001, + QUEST_STATE_FAIL = 0x0002 +}; + +class Quest; +class Spell; +class Item; +class WorldSession; + +enum PlayerSlots +{ + // first slot for item stored (in any way in player m_items data) + PLAYER_SLOT_START = 0, + // last+1 slot for item stored (in any way in player m_items data) + PLAYER_SLOT_END = 118, + PLAYER_SLOTS_COUNT = (PLAYER_SLOT_END - PLAYER_SLOT_START) +}; + +enum EquipmentSlots +{ + EQUIPMENT_SLOT_START = 0, + EQUIPMENT_SLOT_HEAD = 0, + EQUIPMENT_SLOT_NECK = 1, + EQUIPMENT_SLOT_SHOULDERS = 2, + EQUIPMENT_SLOT_BODY = 3, + EQUIPMENT_SLOT_CHEST = 4, + EQUIPMENT_SLOT_WAIST = 5, + EQUIPMENT_SLOT_LEGS = 6, + EQUIPMENT_SLOT_FEET = 7, + EQUIPMENT_SLOT_WRISTS = 8, + EQUIPMENT_SLOT_HANDS = 9, + EQUIPMENT_SLOT_FINGER1 = 10, + EQUIPMENT_SLOT_FINGER2 = 11, + EQUIPMENT_SLOT_TRINKET1 = 12, + EQUIPMENT_SLOT_TRINKET2 = 13, + EQUIPMENT_SLOT_BACK = 14, + EQUIPMENT_SLOT_MAINHAND = 15, + EQUIPMENT_SLOT_OFFHAND = 16, + EQUIPMENT_SLOT_RANGED = 17, + EQUIPMENT_SLOT_TABARD = 18, + EQUIPMENT_SLOT_END = 19 +}; + +enum InventorySlots +{ + INVENTORY_SLOT_BAG_0 = 255, + INVENTORY_SLOT_BAG_START = 19, + INVENTORY_SLOT_BAG_1 = 19, + INVENTORY_SLOT_BAG_2 = 20, + INVENTORY_SLOT_BAG_3 = 21, + INVENTORY_SLOT_BAG_4 = 22, + INVENTORY_SLOT_BAG_END = 23, + + INVENTORY_SLOT_ITEM_START = 23, + INVENTORY_SLOT_ITEM_1 = 23, + INVENTORY_SLOT_ITEM_2 = 24, + INVENTORY_SLOT_ITEM_3 = 25, + INVENTORY_SLOT_ITEM_4 = 26, + INVENTORY_SLOT_ITEM_5 = 27, + INVENTORY_SLOT_ITEM_6 = 28, + INVENTORY_SLOT_ITEM_7 = 29, + INVENTORY_SLOT_ITEM_8 = 30, + INVENTORY_SLOT_ITEM_9 = 31, + INVENTORY_SLOT_ITEM_10 = 32, + INVENTORY_SLOT_ITEM_11 = 33, + INVENTORY_SLOT_ITEM_12 = 34, + INVENTORY_SLOT_ITEM_13 = 35, + INVENTORY_SLOT_ITEM_14 = 36, + INVENTORY_SLOT_ITEM_15 = 37, + INVENTORY_SLOT_ITEM_16 = 38, + INVENTORY_SLOT_ITEM_END = 39 +}; + +enum BankSlots +{ + BANK_SLOT_ITEM_START = 39, + BANK_SLOT_ITEM_1 = 39, + BANK_SLOT_ITEM_2 = 40, + BANK_SLOT_ITEM_3 = 41, + BANK_SLOT_ITEM_4 = 42, + BANK_SLOT_ITEM_5 = 43, + BANK_SLOT_ITEM_6 = 44, + BANK_SLOT_ITEM_7 = 45, + BANK_SLOT_ITEM_8 = 46, + BANK_SLOT_ITEM_9 = 47, + BANK_SLOT_ITEM_10 = 48, + BANK_SLOT_ITEM_11 = 49, + BANK_SLOT_ITEM_12 = 50, + BANK_SLOT_ITEM_13 = 51, + BANK_SLOT_ITEM_14 = 52, + BANK_SLOT_ITEM_15 = 53, + BANK_SLOT_ITEM_16 = 54, + BANK_SLOT_ITEM_17 = 55, + BANK_SLOT_ITEM_18 = 56, + BANK_SLOT_ITEM_19 = 57, + BANK_SLOT_ITEM_20 = 58, + BANK_SLOT_ITEM_21 = 59, + BANK_SLOT_ITEM_22 = 60, + BANK_SLOT_ITEM_23 = 61, + BANK_SLOT_ITEM_24 = 62, + BANK_SLOT_ITEM_25 = 63, + BANK_SLOT_ITEM_26 = 64, + BANK_SLOT_ITEM_27 = 65, + BANK_SLOT_ITEM_28 = 66, + BANK_SLOT_ITEM_END = 67, + + BANK_SLOT_BAG_START = 67, + BANK_SLOT_BAG_1 = 67, + BANK_SLOT_BAG_2 = 68, + BANK_SLOT_BAG_3 = 69, + BANK_SLOT_BAG_4 = 70, + BANK_SLOT_BAG_5 = 71, + BANK_SLOT_BAG_6 = 72, + BANK_SLOT_BAG_7 = 73, + BANK_SLOT_BAG_END = 74 +}; + +enum BuyBackSlots +{ + // stored in m_buybackitems + BUYBACK_SLOT_START = 74, + BUYBACK_SLOT_1 = 74, + BUYBACK_SLOT_2 = 75, + BUYBACK_SLOT_3 = 76, + BUYBACK_SLOT_4 = 77, + BUYBACK_SLOT_5 = 78, + BUYBACK_SLOT_6 = 79, + BUYBACK_SLOT_7 = 80, + BUYBACK_SLOT_8 = 81, + BUYBACK_SLOT_9 = 82, + BUYBACK_SLOT_10 = 83, + BUYBACK_SLOT_11 = 84, + BUYBACK_SLOT_12 = 85, + BUYBACK_SLOT_END = 86 +}; + +enum KeyRingSlots +{ + KEYRING_SLOT_START = 86, + KEYRING_SLOT_END = 118 +}; + +struct ItemPosCount +{ + ItemPosCount(uint16 _pos, uint8 _count) : pos(_pos), count(_count) {} + bool isContainedIn(std::vector&); + uint16 pos; + uint8 count; +}; +typedef std::vector ItemPosCountVec; + +enum SwitchWeapon +{ + DEFAULT_SWITCH_WEAPON = 1500, //cooldown in ms + ROGUE_SWITCH_WEAPON = 1000 +}; + +enum TradeSlots +{ + TRADE_SLOT_COUNT = 7, + TRADE_SLOT_TRADED_COUNT = 6, + TRADE_SLOT_NONTRADED = 6 +}; + +enum TransferAbortReason +{ + TRANSFER_ABORT_MAX_PLAYERS = 0x0001, // Transfer Aborted: instance is full + TRANSFER_ABORT_NOT_FOUND = 0x0002, // Transfer Aborted: instance not found + TRANSFER_ABORT_TOO_MANY_INSTANCES = 0x0003, // You have entered too many instances recently. + TRANSFER_ABORT_ZONE_IN_COMBAT = 0x0005, // Unable to zone in while an encounter is in progress. + TRANSFER_ABORT_INSUF_EXPAN_LVL1 = 0x0106, // You must have TBC expansion installed to access this area. + TRANSFER_ABORT_DIFFICULTY1 = 0x0007, // Normal difficulty mode is not available for %s. + TRANSFER_ABORT_DIFFICULTY2 = 0x0107, // Heroic difficulty mode is not available for %s. + TRANSFER_ABORT_DIFFICULTY3 = 0x0207 // Epic difficulty mode is not available for %s. +}; + +enum InstanceResetWarningType +{ + RAID_INSTANCE_WARNING_HOURS = 1, // WARNING! %s is scheduled to reset in %d hour(s). + RAID_INSTANCE_WARNING_MIN = 2, // WARNING! %s is scheduled to reset in %d minute(s)! + RAID_INSTANCE_WARNING_MIN_SOON = 3, // WARNING! %s is scheduled to reset in %d minute(s). Please exit the zone or you will be returned to your bind location! + RAID_INSTANCE_WELCOME = 4 // Welcome to %s. This raid instance is scheduled to reset in %s. +}; + +struct MovementInfo +{ + // common + //uint32 flags; + uint8 unk1; + uint32 time; + float x, y, z, o; + // transport + uint64 t_guid; + float t_x, t_y, t_z, t_o; + uint32 t_time; + // swimming and unk + float s_pitch; + // last fall time + uint32 fallTime; + // jumping + float j_unk, j_sinAngle, j_cosAngle, j_xyspeed; + // spline + float u_unk1; + + MovementInfo() + { + //flags = + time = t_time = fallTime = 0; + unk1 = 0; + x = y = z = o = t_x = t_y = t_z = t_o = s_pitch = j_unk = j_sinAngle = j_cosAngle = j_xyspeed = u_unk1 = 0.0f; + t_guid = 0; + } + + /*void SetMovementFlags(uint32 _flags) + { + flags = _flags; + }*/ +}; + +// flags that use in movement check for example at spell casting +MovementFlags const movementFlagsMask = MovementFlags( + MOVEMENTFLAG_FORWARD |MOVEMENTFLAG_BACKWARD |MOVEMENTFLAG_STRAFE_LEFT|MOVEMENTFLAG_STRAFE_RIGHT| + MOVEMENTFLAG_PITCH_UP|MOVEMENTFLAG_PITCH_DOWN|MOVEMENTFLAG_FLY_UNK1 | + MOVEMENTFLAG_JUMPING |MOVEMENTFLAG_FALLING |MOVEMENTFLAG_FLY_UP | + MOVEMENTFLAG_FLYING |MOVEMENTFLAG_SPLINE +); + +MovementFlags const movementOrTurningFlagsMask = MovementFlags( + movementFlagsMask | MOVEMENTFLAG_LEFT | MOVEMENTFLAG_RIGHT +); +class InstanceSave; + +enum RestType +{ + REST_TYPE_NO = 0, + REST_TYPE_IN_TAVERN = 1, + REST_TYPE_IN_CITY = 2 +}; + +enum DuelCompleteType +{ + DUEL_INTERUPTED = 0, + DUEL_WON = 1, + DUEL_FLED = 2 +}; + +enum TeleportToOptions +{ + TELE_TO_GM_MODE = 0x01, + TELE_TO_NOT_LEAVE_TRANSPORT = 0x02, + TELE_TO_NOT_LEAVE_COMBAT = 0x04, + TELE_TO_NOT_UNSUMMON_PET = 0x08, + TELE_TO_SPELL = 0x10, +}; + +/// Type of environmental damages +enum EnviromentalDamage +{ + DAMAGE_EXHAUSTED = 0, + DAMAGE_DROWNING = 1, + DAMAGE_FALL = 2, + DAMAGE_LAVA = 3, + DAMAGE_SLIME = 4, + DAMAGE_FIRE = 5, + DAMAGE_FALL_TO_VOID = 6 // custom case for fall without durability loss +}; + +// used at player loading query list preparing, and later result selection +enum PlayerLoginQueryIndex +{ + PLAYER_LOGIN_QUERY_LOADFROM = 0, + PLAYER_LOGIN_QUERY_LOADGROUP = 1, + PLAYER_LOGIN_QUERY_LOADBOUNDINSTANCES = 2, + PLAYER_LOGIN_QUERY_LOADAURAS = 3, + PLAYER_LOGIN_QUERY_LOADSPELLS = 4, + PLAYER_LOGIN_QUERY_LOADQUESTSTATUS = 5, + PLAYER_LOGIN_QUERY_LOADDAILYQUESTSTATUS = 6, + PLAYER_LOGIN_QUERY_LOADTUTORIALS = 7, // common for all characters for some account at specific realm + PLAYER_LOGIN_QUERY_LOADREPUTATION = 8, + PLAYER_LOGIN_QUERY_LOADINVENTORY = 9, + PLAYER_LOGIN_QUERY_LOADACTIONS = 10, + PLAYER_LOGIN_QUERY_LOADMAILCOUNT = 11, + PLAYER_LOGIN_QUERY_LOADMAILDATE = 12, + PLAYER_LOGIN_QUERY_LOADSOCIALLIST = 13, + PLAYER_LOGIN_QUERY_LOADHOMEBIND = 14, + PLAYER_LOGIN_QUERY_LOADSPELLCOOLDOWNS = 15, + PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES = 16, + PLAYER_LOGIN_QUERY_LOADGUILD = 17, +}; + +#define MAX_PLAYER_LOGIN_QUERY 18 + +// Player summoning auto-decline time (in secs) +#define MAX_PLAYER_SUMMON_DELAY (2*MINUTE) +#define MAX_MONEY_AMOUNT (0x7FFFFFFF-1) + +struct InstancePlayerBind +{ + InstanceSave *save; + bool perm; + /* permanent PlayerInstanceBinds are created in Raid/Heroic instances for players + that aren't already permanently bound when they are inside when a boss is killed + or when they enter an instance that the group leader is permanently bound to. */ + InstancePlayerBind() : save(NULL), perm(false) {} +}; + +class MANGOS_DLL_SPEC PlayerTaxi +{ + public: + PlayerTaxi(); + ~PlayerTaxi() {} + // Nodes + void InitTaxiNodesForLevel(uint32 race, uint32 level); + void LoadTaxiMask(const char* data); + void SaveTaxiMask(const char* data); + + uint32 GetTaximask( uint8 index ) const { return m_taximask[index]; } + bool IsTaximaskNodeKnown(uint32 nodeidx) const + { + uint8 field = uint8((nodeidx - 1) / 32); + uint32 submask = 1<<((nodeidx-1)%32); + return (m_taximask[field] & submask) == submask; + } + bool SetTaximaskNode(uint32 nodeidx) + { + uint8 field = uint8((nodeidx - 1) / 32); + uint32 submask = 1<<((nodeidx-1)%32); + if ((m_taximask[field] & submask) != submask ) + { + m_taximask[field] |= submask; + return true; + } + else + return false; + } + void AppendTaximaskTo(ByteBuffer& data,bool all); + + // Destinations + bool LoadTaxiDestinationsFromString(std::string values); + std::string SaveTaxiDestinationsToString(); + + void ClearTaxiDestinations() { m_TaxiDestinations.clear(); } + void AddTaxiDestination(uint32 dest) { m_TaxiDestinations.push_back(dest); } + uint32 GetTaxiSource() const { return m_TaxiDestinations.empty() ? 0 : m_TaxiDestinations.front(); } + uint32 GetTaxiDestination() const { return m_TaxiDestinations.size() < 2 ? 0 : m_TaxiDestinations[1]; } + uint32 GetCurrentTaxiPath() const; + uint32 NextTaxiDestination() + { + m_TaxiDestinations.pop_front(); + return GetTaxiDestination(); + } + bool empty() const { return m_TaxiDestinations.empty(); } + private: + TaxiMask m_taximask; + std::deque m_TaxiDestinations; +}; + +class MANGOS_DLL_SPEC Player : public Unit +{ + friend class WorldSession; + friend void Item::AddToUpdateQueueOf(Player *player); + friend void Item::RemoveFromUpdateQueueOf(Player *player); + public: + explicit Player (WorldSession *session); + ~Player ( ); + + void CleanupsBeforeDelete(); + + static UpdateMask updateVisualBits; + static void InitVisibleBits(); + + void AddToWorld(); + void RemoveFromWorld(); + + bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options = 0); + + bool TeleportTo(WorldLocation const &loc, uint32 options = 0) + { + return TeleportTo(loc.mapid, loc.x, loc.y, loc.z, options); + } + + void SetSummonPoint(uint32 mapid, float x, float y, float z) + { + m_summon_expire = time(NULL) + MAX_PLAYER_SUMMON_DELAY; + m_summon_mapid = mapid; + m_summon_x = x; + m_summon_y = y; + m_summon_z = z; + } + void SummonIfPossible(bool agree); + + bool Create( uint32 guidlow, std::string name, uint8 race, uint8 class_, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair, uint8 outfitId ); + + void Update( uint32 time ); + + void BuildEnumData( QueryResult * result, WorldPacket * p_data ); + + void SetInWater(bool apply); + + bool IsInWater() const { return m_isInWater; } + bool IsUnderWater() const; + + void SendInitialPacketsBeforeAddToMap(); + void SendInitialPacketsAfterAddToMap(); + void SendTransferAborted(uint32 mapid, uint16 reason); + void SendInstanceResetWarning(uint32 mapid, uint32 time); + + bool CanInteractWithNPCs(bool alive = true) const; + + bool ToggleAFK(); + bool ToggleDND(); + bool isAFK() const { return HasFlag(PLAYER_FLAGS,PLAYER_FLAGS_AFK); }; + bool isDND() const { return HasFlag(PLAYER_FLAGS,PLAYER_FLAGS_DND); }; + uint8 chatTag() const; + std::string afkMsg; + std::string dndMsg; + + PlayerSocial *GetSocial() { return m_social; } + + PlayerTaxi m_taxi; + void InitTaxiNodesForLevel() { m_taxi.InitTaxiNodesForLevel(getRace(),getLevel()); } + bool ActivateTaxiPathTo(std::vector const& nodes, uint32 mount_id = 0 , Creature* npc = NULL); + // mount_id can be used in scripting calls + bool isAcceptTickets() const { return GetSession()->GetSecurity() >= SEC_GAMEMASTER && (m_ExtraFlags & PLAYER_EXTRA_GM_ACCEPT_TICKETS); } + void SetAcceptTicket(bool on) { if(on) m_ExtraFlags |= PLAYER_EXTRA_GM_ACCEPT_TICKETS; else m_ExtraFlags &= ~PLAYER_EXTRA_GM_ACCEPT_TICKETS; } + bool isAcceptWhispers() const { return m_ExtraFlags & PLAYER_EXTRA_ACCEPT_WHISPERS; } + void SetAcceptWhispers(bool on) { if(on) m_ExtraFlags |= PLAYER_EXTRA_ACCEPT_WHISPERS; else m_ExtraFlags &= ~PLAYER_EXTRA_ACCEPT_WHISPERS; } + bool isGameMaster() const { return m_ExtraFlags & PLAYER_EXTRA_GM_ON; } + void SetGameMaster(bool on); + bool isTaxiCheater() const { return m_ExtraFlags & PLAYER_EXTRA_TAXICHEAT; } + void SetTaxiCheater(bool on) { if(on) m_ExtraFlags |= PLAYER_EXTRA_TAXICHEAT; else m_ExtraFlags &= ~PLAYER_EXTRA_TAXICHEAT; } + bool isGMVisible() const { return !(m_ExtraFlags & PLAYER_EXTRA_GM_INVISIBLE); } + void SetGMVisible(bool on); + void SetPvPDeath(bool on) { if(on) m_ExtraFlags |= PLAYER_EXTRA_PVP_DEATH; else m_ExtraFlags &= ~PLAYER_EXTRA_PVP_DEATH; } + + void GiveXP(uint32 xp, Unit* victim); + void GiveLevel(uint32 level); + void InitStatsForLevel(bool reapplyMods = false); + + // Played Time Stuff + time_t m_logintime; + time_t m_Last_tick; + uint32 m_Played_time[2]; + uint32 GetTotalPlayedTime() { return m_Played_time[0]; }; + uint32 GetLevelPlayedTime() { return m_Played_time[1]; }; + + void setDeathState(DeathState s); // overwrite Unit::setDeathState + + void InnEnter (int time,uint32 mapid, float x,float y,float z) + { + inn_pos_mapid = mapid; + inn_pos_x = x; + inn_pos_y = y; + inn_pos_z = z; + time_inn_enter = time; + }; + + float GetRestBonus() const { return m_rest_bonus; }; + void SetRestBonus(float rest_bonus_new); + + RestType GetRestType() const { return rest_type; }; + void SetRestType(RestType n_r_type) { rest_type = n_r_type; }; + + uint32 GetInnPosMapId() const { return inn_pos_mapid; }; + float GetInnPosX() const { return inn_pos_x; }; + float GetInnPosY() const { return inn_pos_y; }; + float GetInnPosZ() const { return inn_pos_z; }; + + int GetTimeInnEnter() const { return time_inn_enter; }; + void UpdateInnerTime (int time) { time_inn_enter = time; }; + + void RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent = false); + void RemoveMiniPet(); + Pet* GetMiniPet(); + void SetMiniPet(Pet* pet) { m_miniPet = pet->GetGUID(); } + void RemoveGuardians(); + bool HasGuardianWithEntry(uint32 entry); + void AddGuardian(Pet* pet) { m_guardianPets.insert(pet->GetGUID()); } + GuardianPetList const& GetGuardians() const { return m_guardianPets; } + void Uncharm(); + + void Say(std::string text, const uint32 language); + void Yell(std::string text, const uint32 language); + void TextEmote(std::string text); + void Whisper(std::string text, const uint32 language,uint64 receiver); + void BuildPlayerChat(WorldPacket *data, uint8 msgtype, std::string text, uint32 language) const; + + /*********************************************************/ + /*** STORAGE SYSTEM ***/ + /*********************************************************/ + + void SetVirtualItemSlot( uint8 i, Item* item); + void SetSheath( uint32 sheathed ); + uint8 FindEquipSlot( ItemPrototype const* proto, uint32 slot, bool swap ) const; + uint32 GetItemCount( uint32 item, bool inBankAlso = false, Item* skipItem = NULL ) const; + Item* GetItemByGuid( uint64 guid ) const; + Item* GetItemByPos( uint16 pos ) const; + Item* GetItemByPos( uint8 bag, uint8 slot ) const; + Item* GetWeaponForAttack(WeaponAttackType attackType, bool useable = false) const; + Item* GetShield(bool useable = false) const; + static uint32 GetAttackBySlot( uint8 slot ); // MAX_ATTACK if not weapon slot + std::vector &GetItemUpdateQueue() { return m_itemUpdateQueue; } + static bool IsInventoryPos( uint16 pos ) { return IsInventoryPos(pos >> 8,pos & 255); } + static bool IsInventoryPos( uint8 bag, uint8 slot ); + static bool IsEquipmentPos( uint16 pos ) { return IsEquipmentPos(pos >> 8,pos & 255); } + static bool IsEquipmentPos( uint8 bag, uint8 slot ); + static bool IsBagPos( uint16 pos ); + static bool IsBankPos( uint16 pos ) { return IsBankPos(pos >> 8,pos & 255); } + static bool IsBankPos( uint8 bag, uint8 slot ); + bool HasBankBagSlot( uint8 slot ) const; + bool HasItemCount( uint32 item, uint32 count, bool inBankAlso = false ) const; + bool HasItemFitToSpellReqirements(SpellEntry const* spellInfo, Item const* ignoreItem = NULL); + Item* GetItemOrItemWithGemEquipped( uint32 item ) const; + uint8 CanTakeMoreSimilarItems(Item* pItem) const { return _CanTakeMoreSimilarItems(pItem->GetEntry(),pItem->GetCount(),pItem); } + uint8 CanTakeMoreSimilarItems(uint32 entry, uint32 count) const { return _CanTakeMoreSimilarItems(entry,count,NULL); } + uint8 CanStoreNewItem( uint8 bag, uint8 slot, ItemPosCountVec& dest, uint32 item, uint32 count, uint32* no_space_count = NULL ) const + { + return _CanStoreItem(bag, slot, dest, item, count, NULL, false, no_space_count ); + } + uint8 CanStoreItem( uint8 bag, uint8 slot, ItemPosCountVec& dest, Item *pItem, bool swap = false ) const + { + if(!pItem) + return EQUIP_ERR_ITEM_NOT_FOUND; + uint32 count = pItem->GetCount(); + return _CanStoreItem( bag, slot, dest, pItem->GetEntry(), count, pItem, swap, NULL ); + + } + uint8 CanStoreItems( Item **pItem,int count) const; + uint8 CanEquipNewItem( uint8 slot, uint16 &dest, uint32 item, uint32 count, bool swap ) const; + uint8 CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, bool swap, bool not_loading = true ) const; + uint8 CanUnequipItems( uint32 item, uint32 count ) const; + uint8 CanUnequipItem( uint16 src, bool swap ) const; + uint8 CanBankItem( uint8 bag, uint8 slot, ItemPosCountVec& dest, Item *pItem, bool swap, bool not_loading = true ) const; + uint8 CanUseItem( Item *pItem, bool not_loading = true ) const; + bool HasItemTotemCategory( uint32 TotemCategory ) const; + bool CanUseItem( ItemPrototype const *pItem ); + uint8 CanUseAmmo( uint32 item ) const; + Item* StoreNewItem( ItemPosCountVec const& pos, uint32 item, bool update,int32 randomPropertyId = 0 ); + Item* StoreItem( ItemPosCountVec const& pos, Item *pItem, bool update ); + Item* EquipNewItem( uint16 pos, uint32 item, uint32 count, bool update ); + Item* EquipItem( uint16 pos, Item *pItem, bool update ); + void AutoUnequipOffhandIfNeed(); + + uint8 _CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item* pItem, uint32* no_space_count = NULL) const; + uint8 _CanStoreItem( uint8 bag, uint8 slot, ItemPosCountVec& dest, uint32 entry, uint32 count, Item *pItem = NULL, bool swap = false, uint32* no_space_count = NULL ) const; + + void ApplyEquipCooldown( Item * pItem ); + void SetAmmo( uint32 item ); + void RemoveAmmo(); + float GetAmmoDPS() const { return m_ammoDPS; } + bool CheckAmmoCompatibility(const ItemPrototype *ammo_proto) const; + void QuickEquipItem( uint16 pos, Item *pItem); + void VisualizeItem( uint8 slot, Item *pItem); + void SetVisibleItemSlot(uint8 slot, Item *pItem); + Item* BankItem( ItemPosCountVec const& dest, Item *pItem, bool update ) + { + return StoreItem( dest, pItem, update); + } + Item* BankItem( uint16 pos, Item *pItem, bool update ); + void RemoveItem( uint8 bag, uint8 slot, bool update ); + void MoveItemFromInventory(uint8 bag, uint8 slot, bool update); + // in trade, auction, guild bank, mail.... + void MoveItemToInventory(ItemPosCountVec const& dest, Item* pItem, bool update, bool in_characterInventoryDB = false); + // in trade, guild bank, mail.... + void RemoveItemDependentAurasAndCasts( Item * pItem ); + void DestroyItem( uint8 bag, uint8 slot, bool update ); + void DestroyItemCount( uint32 item, uint32 count, bool update, bool unequip_check = false); + void DestroyItemCount( Item* item, uint32& count, bool update ); + void DestroyConjuredItems( bool update ); + void DestroyZoneLimitedItem( bool update, uint32 new_zone ); + void SplitItem( uint16 src, uint16 dst, uint32 count ); + void SwapItem( uint16 src, uint16 dst ); + void AddItemToBuyBackSlot( Item *pItem ); + Item* GetItemFromBuyBackSlot( uint32 slot ); + void RemoveItemFromBuyBackSlot( uint32 slot, bool del ); + uint32 GetMaxKeyringSize() const { return KEYRING_SLOT_END-KEYRING_SLOT_START; } + void SendEquipError( uint8 msg, Item* pItem, Item *pItem2 ); + void SendBuyError( uint8 msg, Creature* pCreature, uint32 item, uint32 param ); + void SendSellError( uint8 msg, Creature* pCreature, uint64 guid, uint32 param ); + void AddWeaponProficiency(uint32 newflag) { m_WeaponProficiency |= newflag; } + void AddArmorProficiency(uint32 newflag) { m_ArmorProficiency |= newflag; } + uint32 GetWeaponProficiency() const { return m_WeaponProficiency; } + uint32 GetArmorProficiency() const { return m_ArmorProficiency; } + bool IsInFeralForm() const { return m_form == FORM_CAT || m_form == FORM_BEAR || m_form == FORM_DIREBEAR; } + bool IsUseEquipedWeapon( bool mainhand ) const + { + // disarm applied only to mainhand weapon + return !IsInFeralForm() && (!mainhand || !HasFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISARMED) ); + } + void SendNewItem( Item *item, uint32 count, bool received, bool created, bool broadcast = false ); + bool BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint64 bagguid, uint8 slot); + + float GetReputationPriceDiscount( Creature const* pCreature ) const; + Player* GetTrader() const { return pTrader; } + void ClearTrade(); + void TradeCancel(bool sendback); + uint16 GetItemPosByTradeSlot(uint32 slot) const { return tradeItems[slot]; } + + void UpdateEnchantTime(uint32 time); + void UpdateItemDuration(uint32 time, bool realtimeonly=false); + void AddEnchantmentDurations(Item *item); + void RemoveEnchantmentDurations(Item *item); + void RemoveAllEnchantments(EnchantmentSlot slot); + void AddEnchantmentDuration(Item *item,EnchantmentSlot slot,uint32 duration); + void ApplyEnchantment(Item *item,EnchantmentSlot slot,bool apply, bool apply_dur = true, bool ignore_condition = false); + void ApplyEnchantment(Item *item,bool apply); + void SendEnchantmentDurations(); + void AddItemDurations(Item *item); + void RemoveItemDurations(Item *item); + void SendItemDurations(); + void LoadCorpse(); + void LoadPet(); + + uint32 m_stableSlots; + + /*********************************************************/ + /*** QUEST SYSTEM ***/ + /*********************************************************/ + + void PrepareQuestMenu( uint64 guid ); + void SendPreparedQuest( uint64 guid ); + bool IsActiveQuest( uint32 quest_id ) const; + Quest const *GetNextQuest( uint64 guid, Quest const *pQuest ); + bool CanSeeStartQuest( Quest const *pQuest ); + bool CanTakeQuest( Quest const *pQuest, bool msg ); + bool CanAddQuest( Quest const *pQuest, bool msg ); + bool CanCompleteQuest( uint32 quest_id ); + bool CanCompleteRepeatableQuest(Quest const *pQuest); + bool CanRewardQuest( Quest const *pQuest, bool msg ); + bool CanRewardQuest( Quest const *pQuest, uint32 reward, bool msg ); + void AddQuest( Quest const *pQuest, Object *questGiver ); + void CompleteQuest( uint32 quest_id ); + void IncompleteQuest( uint32 quest_id ); + void RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver, bool announce = true ); + void FailQuest( uint32 quest_id ); + void FailTimedQuest( uint32 quest_id ); + bool SatisfyQuestSkillOrClass( Quest const* qInfo, bool msg ); + bool SatisfyQuestLevel( Quest const* qInfo, bool msg ); + bool SatisfyQuestLog( bool msg ); + bool SatisfyQuestPreviousQuest( Quest const* qInfo, bool msg ); + bool SatisfyQuestRace( Quest const* qInfo, bool msg ); + bool SatisfyQuestReputation( Quest const* qInfo, bool msg ); + bool SatisfyQuestStatus( Quest const* qInfo, bool msg ); + bool SatisfyQuestTimed( Quest const* qInfo, bool msg ); + bool SatisfyQuestExclusiveGroup( Quest const* qInfo, bool msg ); + bool SatisfyQuestNextChain( Quest const* qInfo, bool msg ); + bool SatisfyQuestPrevChain( Quest const* qInfo, bool msg ); + bool SatisfyQuestDay( Quest const* qInfo, bool msg ); + bool GiveQuestSourceItem( Quest const *pQuest ); + bool TakeQuestSourceItem( uint32 quest_id, bool msg ); + bool GetQuestRewardStatus( uint32 quest_id ) const; + QuestStatus GetQuestStatus( uint32 quest_id ) const; + void SetQuestStatus( uint32 quest_id, QuestStatus status ); + + void SetDailyQuestStatus( uint32 quest_id ); + void ResetDailyQuestStatus(); + + uint16 FindQuestSlot( uint32 quest_id ) const; + uint32 GetQuestSlotQuestId(uint16 slot) const { return GetUInt32Value(PLAYER_QUEST_LOG_1_1 + slot*MAX_QUEST_OFFSET + QUEST_ID_OFFSET); } + uint32 GetQuestSlotState(uint16 slot) const { return GetUInt32Value(PLAYER_QUEST_LOG_1_1 + slot*MAX_QUEST_OFFSET + QUEST_STATE_OFFSET); } + uint32 GetQuestSlotCounters(uint16 slot)const { return GetUInt32Value(PLAYER_QUEST_LOG_1_1 + slot*MAX_QUEST_OFFSET + QUEST_COUNTS_OFFSET); } + uint8 GetQuestSlotCounter(uint16 slot,uint8 counter) const { return GetByteValue(PLAYER_QUEST_LOG_1_1 + slot*MAX_QUEST_OFFSET + QUEST_COUNTS_OFFSET,counter); } + uint32 GetQuestSlotTime(uint16 slot) const { return GetUInt32Value(PLAYER_QUEST_LOG_1_1 + slot*MAX_QUEST_OFFSET + QUEST_TIME_OFFSET); } + void SetQuestSlot(uint16 slot,uint32 quest_id, uint32 timer = 0) + { + SetUInt32Value(PLAYER_QUEST_LOG_1_1 + slot*MAX_QUEST_OFFSET + QUEST_ID_OFFSET,quest_id); + SetUInt32Value(PLAYER_QUEST_LOG_1_1 + slot*MAX_QUEST_OFFSET + QUEST_STATE_OFFSET,0); + SetUInt32Value(PLAYER_QUEST_LOG_1_1 + slot*MAX_QUEST_OFFSET + QUEST_COUNTS_OFFSET,0); + SetUInt32Value(PLAYER_QUEST_LOG_1_1 + slot*MAX_QUEST_OFFSET + QUEST_TIME_OFFSET,timer); + } + void SetQuestSlotCounter(uint16 slot,uint8 counter,uint8 count) { SetByteValue(PLAYER_QUEST_LOG_1_1 + slot*MAX_QUEST_OFFSET + QUEST_COUNTS_OFFSET,counter,count); } + void SetQuestSlotState(uint16 slot,uint32 state) { SetFlag(PLAYER_QUEST_LOG_1_1 + slot*MAX_QUEST_OFFSET + QUEST_STATE_OFFSET,state); } + void RemoveQuestSlotState(uint16 slot,uint32 state) { RemoveFlag(PLAYER_QUEST_LOG_1_1 + slot*MAX_QUEST_OFFSET + QUEST_STATE_OFFSET,state); } + void SetQuestSlotTimer(uint16 slot,uint32 timer) { SetUInt32Value(PLAYER_QUEST_LOG_1_1 + slot*MAX_QUEST_OFFSET + QUEST_TIME_OFFSET,timer); } + void SwapQuestSlot(uint16 slot1,uint16 slot2) + { + for (int i = 0; i < MAX_QUEST_OFFSET ; ++i ) + { + uint32 temp1 = GetUInt32Value(PLAYER_QUEST_LOG_1_1 + MAX_QUEST_OFFSET *slot1 + i); + uint32 temp2 = GetUInt32Value(PLAYER_QUEST_LOG_1_1 + MAX_QUEST_OFFSET *slot2 + i); + + SetUInt32Value(PLAYER_QUEST_LOG_1_1 + MAX_QUEST_OFFSET *slot1 + i, temp2); + SetUInt32Value(PLAYER_QUEST_LOG_1_1 + MAX_QUEST_OFFSET *slot2 + i, temp1); + } + } + uint32 GetReqKillOrCastCurrentCount(uint32 quest_id, int32 entry); + void AdjustQuestReqItemCount( Quest const* pQuest ); + void AreaExploredOrEventHappens( uint32 questId ); + void GroupEventHappens( uint32 questId, WorldObject const* pEventObject ); + void ItemAddedQuestCheck( uint32 entry, uint32 count ); + void ItemRemovedQuestCheck( uint32 entry, uint32 count ); + void KilledMonster( uint32 entry, uint64 guid ); + void CastedCreatureOrGO( uint32 entry, uint64 guid, uint32 spell_id ); + void TalkedToCreature( uint32 entry, uint64 guid ); + void MoneyChanged( uint32 value ); + bool HasQuestForItem( uint32 itemid ) const; + bool HasQuestForGO(int32 GOId); + void UpdateForQuestsGO(); + bool CanShareQuest(uint32 quest_id) const; + + void SendQuestComplete( uint32 quest_id ); + void SendQuestReward( Quest const *pQuest, uint32 XP, Object* questGiver ); + void SendQuestFailed( uint32 quest_id ); + void SendQuestTimerFailed( uint32 quest_id ); + void SendCanTakeQuestResponse( uint32 msg ); + void SendPushToPartyResponse( Player *pPlayer, uint32 msg ); + void SendQuestUpdateAddItem( Quest const* pQuest, uint32 item_idx, uint32 count ); + void SendQuestUpdateAddCreatureOrGo( Quest const* pQuest, uint64 guid, uint32 creatureOrGO_idx, uint32 old_count, uint32 add_count ); + + uint64 GetDivider() { return m_divider; }; + void SetDivider( uint64 guid ) { m_divider = guid; }; + + uint32 GetInGameTime() { return m_ingametime; }; + + void SetInGameTime( uint32 time ) { m_ingametime = time; }; + + void AddTimedQuest( uint32 quest_id ) { m_timedquests.insert(quest_id); } + + /*********************************************************/ + /*** LOAD SYSTEM ***/ + /*********************************************************/ + + bool LoadFromDB(uint32 guid, SqlQueryHolder *holder); + bool MinimalLoadFromDB(QueryResult *result, uint32 guid); + static bool LoadValuesArrayFromDB(Tokens& data,uint64 guid); + static uint32 GetUInt32ValueFromArray(Tokens const& data, uint16 index); + static float GetFloatValueFromArray(Tokens const& data, uint16 index); + static uint32 GetUInt32ValueFromDB(uint16 index, uint64 guid); + static float GetFloatValueFromDB(uint16 index, uint64 guid); + static uint32 GetZoneIdFromDB(uint64 guid); + static bool LoadPositionFromDB(uint32& mapid, float& x,float& y,float& z,float& o, bool& in_flight, uint64 guid); + + /*********************************************************/ + /*** SAVE SYSTEM ***/ + /*********************************************************/ + + void SaveToDB(); + void SaveInventoryAndGoldToDB(); // fast save function for item/money cheating preventing + void SaveGoldToDB() { SetUInt32ValueInDB(PLAYER_FIELD_COINAGE,GetMoney(),GetGUID()); } + static bool SaveValuesArrayInDB(Tokens const& data,uint64 guid); + static void SetUInt32ValueInArray(Tokens& data,uint16 index, uint32 value); + static void SetFloatValueInArray(Tokens& data,uint16 index, float value); + static void SetUInt32ValueInDB(uint16 index, uint32 value, uint64 guid); + static void SetFloatValueInDB(uint16 index, float value, uint64 guid); + static void SavePositionInDB(uint32 mapid, float x,float y,float z,float o,uint32 zone,uint64 guid); + + bool m_mailsLoaded; + bool m_mailsUpdated; + + void SetBindPoint(uint64 guid); + void SendTalentWipeConfirm(uint64 guid); + void RewardRage( uint32 damage, uint32 weaponSpeedHitFactor, bool attacker ); + void SendPetSkillWipeConfirm(); + void CalcRage( uint32 damage,bool attacker ); + void RegenerateAll(); + void Regenerate(Powers power); + void RegenerateHealth(); + void setRegenTimer(uint32 time) {m_regenTimer = time;} + void setWeaponChangeTimer(uint32 time) {m_weaponChangeTimer = time;} + + uint32 GetMoney() { return GetUInt32Value (PLAYER_FIELD_COINAGE); } + void ModifyMoney( int32 d ) + { + if(d < 0) + SetMoney (GetMoney() > uint32(-d) ? GetMoney() + d : 0); + else + SetMoney (GetMoney() < MAX_MONEY_AMOUNT - d ? GetMoney() + d : MAX_MONEY_AMOUNT); + + // "At Gold Limit" + if(GetMoney() >= MAX_MONEY_AMOUNT) + SendEquipError(EQUIP_ERR_TOO_MUCH_GOLD,NULL,NULL); + } + void SetMoney( uint32 value ) + { + SetUInt32Value (PLAYER_FIELD_COINAGE, value); + MoneyChanged( value ); + } + + uint32 GetTutorialInt(uint32 intId ) + { + ASSERT( (intId < 8) ); + return m_Tutorials[intId]; + } + + void SetTutorialInt(uint32 intId, uint32 value) + { + ASSERT( (intId < 8) ); + if(m_Tutorials[intId]!=value) + { + m_Tutorials[intId] = value; + m_TutorialsChanged = true; + } + } + + QuestStatusMap& getQuestStatusMap() { return mQuestStatus; }; + + const uint64& GetSelection( ) const { return m_curSelection; } + void SetSelection(const uint64 &guid) { m_curSelection = guid; SetUInt64Value(UNIT_FIELD_TARGET, guid); } + + uint8 GetComboPoints() { return m_comboPoints; } + uint64 GetComboTarget() { return m_comboTarget; } + + void AddComboPoints(Unit* target, int8 count); + void ClearComboPoints(); + void SendComboPoints(); + + void SendMailResult(uint32 mailId, uint32 mailAction, uint32 mailError, uint32 equipError = 0, uint32 item_guid = 0, uint32 item_count = 0); + void SendNewMail(); + void UpdateNextMailTimeAndUnreads(); + void AddNewMailDeliverTime(time_t deliver_time); + bool IsMailsLoaded() const { return m_mailsLoaded; } + + //void SetMail(Mail *m); + void RemoveMail(uint32 id); + + void AddMail(Mail* mail) { m_mail.push_front(mail);}// for call from WorldSession::SendMailTo + uint32 GetMailSize() { return m_mail.size();}; + Mail* GetMail(uint32 id); + + PlayerMails::iterator GetmailBegin() { return m_mail.begin();}; + PlayerMails::iterator GetmailEnd() { return m_mail.end();}; + + /*********************************************************/ + /*** MAILED ITEMS SYSTEM ***/ + /*********************************************************/ + + uint8 unReadMails; + time_t m_nextMailDelivereTime; + + typedef HM_NAMESPACE::hash_map ItemMap; + + ItemMap mMitems; //template defined in objectmgr.cpp + + Item* GetMItem(uint32 id) + { + ItemMap::const_iterator itr = mMitems.find(id); + if (itr != mMitems.end()) + return itr->second; + + return NULL; + } + + void AddMItem(Item* it) + { + ASSERT( it ); + //assert deleted, because items can be added before loading + mMitems[it->GetGUIDLow()] = it; + } + + bool RemoveMItem(uint32 id) + { + ItemMap::iterator i = mMitems.find(id); + if (i == mMitems.end()) + return false; + + mMitems.erase(i); + return true; + } + + void PetSpellInitialize(); + void CharmSpellInitialize(); + void PossessSpellInitialize(); + bool HasSpell(uint32 spell) const; + TrainerSpellState GetTrainerSpellState(TrainerSpell const* trainer_spell) const; + bool IsSpellFitByClassAndRace( uint32 spell_id ) const; + + void SendProficiency(uint8 pr1, uint32 pr2); + void SendInitialSpells(); + bool addSpell(uint32 spell_id, bool active, bool learning = true, bool loading = false, uint16 slot_id=SPELL_WITHOUT_SLOT_ID, bool disabled = false); + void learnSpell(uint32 spell_id); + void removeSpell(uint32 spell_id, bool disabled = false); + void resetSpells(); + void learnDefaultSpells(bool loading = false); + void learnQuestRewardedSpells(); + void learnQuestRewardedSpells(Quest const* quest); + + uint32 GetFreeTalentPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS1); } + void SetFreeTalentPoints(uint32 points) { SetUInt32Value(PLAYER_CHARACTER_POINTS1,points); } + bool resetTalents(bool no_cost = false); + uint32 resetTalentsCost() const; + void InitTalentForLevel(); + + uint32 GetFreePrimaryProffesionPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS2); } + void SetFreePrimaryProffesions(uint16 profs) { SetUInt32Value(PLAYER_CHARACTER_POINTS2,profs); } + void InitPrimaryProffesions(); + + PlayerSpellMap const& GetSpellMap() const { return m_spells; } + PlayerSpellMap & GetSpellMap() { return m_spells; } + + void AddSpellMod(SpellModifier* mod, bool apply); + int32 GetTotalFlatMods(uint32 spellId, SpellModOp op); + int32 GetTotalPctMods(uint32 spellId, SpellModOp op); + bool IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell const* spell = NULL); + template T ApplySpellMod(uint32 spellId, SpellModOp op, T &basevalue, Spell const* spell = NULL); + void RemoveSpellMods(Spell const* spell); + + bool HasSpellCooldown(uint32 spell_id) const + { + SpellCooldowns::const_iterator itr = m_spellCooldowns.find(spell_id); + return itr != m_spellCooldowns.end() && itr->second.end > time(NULL); + } + uint32 GetSpellCooldownDelay(uint32 spell_id) const + { + SpellCooldowns::const_iterator itr = m_spellCooldowns.find(spell_id); + time_t t = time(NULL); + return itr != m_spellCooldowns.end() && itr->second.end > t ? itr->second.end - t : 0; + } + void AddSpellCooldown(uint32 spell_id, uint32 itemid, time_t end_time); + void SendCooldownEvent(SpellEntry const *spellInfo); + void ProhibitSpellScholl(SpellSchoolMask idSchoolMask, uint32 unTimeMs ); + void RemoveSpellCooldown(uint32 spell_id) { m_spellCooldowns.erase(spell_id); } + void RemoveArenaSpellCooldowns(); + void RemoveAllSpellCooldown(); + void _LoadSpellCooldowns(QueryResult *result); + void _SaveSpellCooldowns(); + + void setResurrectRequestData(uint64 guid, uint32 mapId, float X, float Y, float Z, uint32 health, uint32 mana) + { + m_resurrectGUID = guid; + m_resurrectMap = mapId; + m_resurrectX = X; + m_resurrectY = Y; + m_resurrectZ = Z; + m_resurrectHealth = health; + m_resurrectMana = mana; + }; + void clearResurrectRequestData() { setResurrectRequestData(0,0,0.0f,0.0f,0.0f,0,0); } + bool isRessurectRequestedBy(uint64 guid) const { return m_resurrectGUID == guid; } + bool isRessurectRequested() const { return m_resurrectGUID != 0; } + void ResurectUsingRequestData(); + + int getCinematic() + { + return m_cinematic; + } + void setCinematic(int cine) + { + m_cinematic = cine; + } + + void addActionButton(uint8 button, uint16 action, uint8 type, uint8 misc); + void removeActionButton(uint8 button); + void SendInitialActionButtons(); + + PvPInfo pvpInfo; + void UpdatePvP(bool state, bool ovrride=false); + void UpdateZone(uint32 newZone); + void UpdateArea(uint32 newArea); + + void UpdateZoneDependentAuras( uint32 zone_id ); // zones + void UpdateAreaDependentAuras( uint32 area_id ); // subzones + + void UpdateAfkReport(time_t currTime); + void UpdatePvPFlag(time_t currTime); + void UpdateContestedPvP(uint32 currTime); + void SetContestedPvPTimer(uint32 newTime) {m_contestedPvPTimer = newTime;} + void ResetContestedPvP() + { + clearUnitState(UNIT_STAT_ATTACK_PLAYER); + RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP); + m_contestedPvPTimer = 0; + } + + /** todo: -maybe move UpdateDuelFlag+DuelComplete to independent DuelHandler.. **/ + DuelInfo *duel; + void UpdateDuelFlag(time_t currTime); + void CheckDuelDistance(time_t currTime); + void DuelComplete(DuelCompleteType type); + + bool IsGroupVisibleFor(Player* p) const; + bool IsInSameGroupWith(Player const* p) const; + bool IsInSameRaidWith(Player const* p) const { return p==this || (GetGroup() != NULL && GetGroup() == p->GetGroup()); } + void UninviteFromGroup(); + static void RemoveFromGroup(Group* group, uint64 guid); + void RemoveFromGroup() { RemoveFromGroup(GetGroup(),GetGUID()); } + void SendUpdateToOutOfRangeGroupMembers(); + + void SetInGuild(uint32 GuildId) { SetUInt32Value(PLAYER_GUILDID, GuildId); Player::SetUInt32ValueInDB(PLAYER_GUILDID, GuildId, this->GetGUID()); } + void SetRank(uint32 rankId){ SetUInt32Value(PLAYER_GUILDRANK, rankId); Player::SetUInt32ValueInDB(PLAYER_GUILDRANK, rankId, this->GetGUID()); } + void SetGuildIdInvited(uint32 GuildId) { m_GuildIdInvited = GuildId; } + uint32 GetGuildId() { return GetUInt32Value(PLAYER_GUILDID); } + static uint32 GetGuildIdFromDB(uint64 guid); + uint32 GetRank(){ return GetUInt32Value(PLAYER_GUILDRANK); } + static uint32 GetRankFromDB(uint64 guid); + int GetGuildIdInvited() { return m_GuildIdInvited; } + static void RemovePetitionsAndSigns(uint64 guid, uint32 type); + + // Arena Team + void SetInArenaTeam(uint32 ArenaTeamId, uint8 slot) + { + SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * 6), ArenaTeamId); + SetUInt32ValueInDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * 6), ArenaTeamId, this->GetGUID()); + } + uint32 GetArenaTeamId(uint8 slot) { return GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * 6)); } + static uint32 GetArenaTeamIdFromDB(uint64 guid, uint8 slot); + void SetArenaTeamIdInvited(uint32 ArenaTeamId) { m_ArenaTeamIdInvited = ArenaTeamId; } + uint32 GetArenaTeamIdInvited() { return m_ArenaTeamIdInvited; } + + void SetDifficulty(uint32 dungeon_difficulty) { m_dungeonDifficulty = dungeon_difficulty; } + uint8 GetDifficulty() { return m_dungeonDifficulty; } + + bool UpdateSkill(uint32 skill_id, uint32 step); + bool UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step); + + bool UpdateCraftSkill(uint32 spellid); + bool UpdateGatherSkill(uint32 SkillId, uint32 SkillValue, uint32 RedLevel, uint32 Multiplicator = 1); + bool UpdateFishingSkill(); + + uint32 GetBaseDefenseSkillValue() const { return GetBaseSkillValue(SKILL_DEFENSE); } + uint32 GetBaseWeaponSkillValue(WeaponAttackType attType) const; + + uint32 GetSpellByProto(ItemPrototype *proto); + + float GetHealthBonusFromStamina(); + float GetManaBonusFromIntellect(); + + bool UpdateStats(Stats stat); + bool UpdateAllStats(); + void UpdateResistances(uint32 school); + void UpdateArmor(); + void UpdateMaxHealth(); + void UpdateMaxPower(Powers power); + void UpdateAttackPowerAndDamage(bool ranged = false); + void UpdateShieldBlockValue(); + void UpdateDamagePhysical(WeaponAttackType attType); + void UpdateSpellDamageAndHealingBonus(); + + void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, float& min_damage, float& max_damage); + + void UpdateDefenseBonusesMod(); + void ApplyRatingMod(CombatRating cr, int32 value, bool apply); + float GetMeleeCritFromAgility(); + float GetDodgeFromAgility(); + float GetSpellCritFromIntellect(); + float OCTRegenHPPerSpirit(); + float OCTRegenMPPerSpirit(); + float GetRatingCoefficient(CombatRating cr) const; + float GetRatingBonusValue(CombatRating cr) const; + uint32 GetMeleeCritDamageReduction(uint32 damage) const; + uint32 GetRangedCritDamageReduction(uint32 damage) const; + uint32 GetSpellCritDamageReduction(uint32 damage) const; + uint32 GetDotDamageReduction(uint32 damage) const; + + float GetExpertiseDodgeOrParryReduction(WeaponAttackType attType) const; + void UpdateBlockPercentage(); + void UpdateCritPercentage(WeaponAttackType attType); + void UpdateAllCritPercentages(); + void UpdateParryPercentage(); + void UpdateDodgePercentage(); + void UpdateAllSpellCritChances(); + void UpdateSpellCritChance(uint32 school); + void UpdateExpertise(WeaponAttackType attType); + void UpdateManaRegen(); + + const uint64& GetLootGUID() const { return m_lootGuid; } + void SetLootGUID(const uint64 &guid) { m_lootGuid = guid; } + + void RemovedInsignia(Player* looterPlr); + + WorldSession* GetSession() const { return m_session; } + void SetSession(WorldSession *s) { m_session = s; } + + void BuildCreateUpdateBlockForPlayer( UpdateData *data, Player *target ) const; + void DestroyForPlayer( Player *target ) const; + void SendDelayResponse(const uint32); + void SendLogXPGain(uint32 GivenXP,Unit* victim,uint32 RestXP); + + //Low Level Packets + void PlaySound(uint32 Sound, bool OnlySelf); + //notifiers + void SendAttackSwingCantAttack(); + void SendAttackSwingCancelAttack(); + void SendAttackSwingDeadTarget(); + void SendAttackSwingNotStanding(); + void SendAttackSwingNotInRange(); + void SendAttackSwingBadFacingAttack(); + void SendAutoRepeatCancel(); + void SendExplorationExperience(uint32 Area, uint32 Experience); + + void SendDungeonDifficulty(bool IsInGroup); + void ResetInstances(uint8 method); + void SendResetInstanceSuccess(uint32 MapId); + void SendResetInstanceFailed(uint32 reason, uint32 MapId); + void SendResetFailedNotify(uint32 mapid); + + bool SetPosition(float x, float y, float z, float orientation, bool teleport = false); + void UpdateUnderwaterState( Map * m, float x, float y, float z ); + + void SendMessageToSet(WorldPacket *data, bool self);// overwrite Object::SendMessageToSet + void SendMessageToSetInRange(WorldPacket *data, float fist, bool self); + // overwrite Object::SendMessageToSetInRange + void SendMessageToSetInRange(WorldPacket *data, float dist, bool self, bool own_team_only); + + static void DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmChars = true); + + Corpse *GetCorpse() const; + void SpawnCorpseBones(); + void CreateCorpse(); + void KillPlayer(); + uint32 GetResurrectionSpellId(); + void ResurrectPlayer(float restore_percent, bool updateToWorld = true, bool applySickness = false); + void BuildPlayerRepop(); + void RepopAtGraveyard(); + + void DurabilityLossAll(double percent, bool inventory); + void DurabilityLoss(Item* item, double percent); + void DurabilityPointsLossAll(int32 points, bool inventory); + void DurabilityPointsLoss(Item* item, int32 points); + void DurabilityPointLossForEquipSlot(EquipmentSlots slot); + uint32 DurabilityRepairAll(bool cost, float discountMod, bool guildBank); + uint32 DurabilityRepair(uint16 pos, bool cost, float discountMod, bool guildBank); + + void StopMirrorTimers() + { + StopMirrorTimer(FATIGUE_TIMER); + StopMirrorTimer(BREATH_TIMER); + StopMirrorTimer(FIRE_TIMER); + } + + void SetMovement(PlayerMovementType pType); + + void JoinedChannel(Channel *c); + void LeftChannel(Channel *c); + void CleanupChannels(); + void UpdateLocalChannels( uint32 newZone ); + void LeaveLFGChannel(); + + void UpdateDefense(); + void UpdateWeaponSkill (WeaponAttackType attType); + void UpdateCombatSkills(Unit *pVictim, WeaponAttackType attType, MeleeHitOutcome outcome, bool defence); + + void SetSkill(uint32 id, uint16 currVal, uint16 maxVal); + uint16 GetMaxSkillValue(uint32 skill) const; // max + perm. bonus + uint16 GetPureMaxSkillValue(uint32 skill) const; // max + uint16 GetSkillValue(uint32 skill) const; // skill value + perm. bonus + temp bonus + uint16 GetBaseSkillValue(uint32 skill) const; // skill value + perm. bonus + uint16 GetPureSkillValue(uint32 skill) const; // skill value + int16 GetSkillTempBonusValue(uint32 skill) const; + bool HasSkill(uint32 skill) const; + void learnSkillRewardedSpells( uint32 id ); + void learnSkillRewardedSpells(); + + void SetDontMove(bool dontMove); + bool GetDontMove() const { return m_dontMove; } + + void CheckExploreSystem(void); + + static uint32 TeamForRace(uint8 race); + uint32 GetTeam() const { return m_team; } + static uint32 getFactionForRace(uint8 race); + void setFactionForRace(uint8 race); + + bool IsAtGroupRewardDistance(WorldObject const* pRewardSource) const; + bool RewardPlayerAndGroupAtKill(Unit* pVictim); + + FactionStateList m_factions; + ForcedReactions m_forcedReactions; + uint32 GetDefaultReputationFlags(const FactionEntry *factionEntry) const; + int32 GetBaseReputation(const FactionEntry *factionEntry) const; + int32 GetReputation(uint32 faction_id) const; + int32 GetReputation(const FactionEntry *factionEntry) const; + ReputationRank GetReputationRank(uint32 faction) const; + ReputationRank GetReputationRank(const FactionEntry *factionEntry) const; + ReputationRank GetBaseReputationRank(const FactionEntry *factionEntry) const; + ReputationRank ReputationToRank(int32 standing) const; + const static int32 ReputationRank_Length[MAX_REPUTATION_RANK]; + const static int32 Reputation_Cap = 42999; + const static int32 Reputation_Bottom = -42000; + bool ModifyFactionReputation(uint32 FactionTemplateId, int32 DeltaReputation); + bool ModifyFactionReputation(FactionEntry const* factionEntry, int32 standing); + bool ModifyOneFactionReputation(FactionEntry const* factionEntry, int32 standing); + bool SetFactionReputation(uint32 FactionTemplateId, int32 standing); + bool SetFactionReputation(FactionEntry const* factionEntry, int32 standing); + bool SetOneFactionReputation(FactionEntry const* factionEntry, int32 standing); + int32 CalculateReputationGain(uint32 creatureOrQuestLevel, int32 rep, bool for_quest); + void RewardReputation(Unit *pVictim, float rate); + void RewardReputation(Quest const *pQuest); + void SetInitialFactions(); + void UpdateReputation() const; + void SendFactionState(FactionState const* faction) const; + void SendInitialReputations(); + FactionState const* GetFactionState( FactionEntry const* factionEntry) const; + void SetFactionAtWar(FactionState* faction, bool atWar); + void SetFactionInactive(FactionState* faction, bool inactive); + void SetFactionVisible(FactionState* faction); + void SetFactionVisibleForFactionTemplateId(uint32 FactionTemplateId); + void SetFactionVisibleForFactionId(uint32 FactionId); + void UpdateMaxSkills(); + void UpdateSkillsToMaxSkillsForLevel(); // for .levelup + void ModifySkillBonus(uint32 skillid,int32 val, bool talent); + + /*********************************************************/ + /*** PVP SYSTEM ***/ + /*********************************************************/ + void UpdateArenaFields(); + void UpdateHonorFields(); + bool RewardHonor(Unit *pVictim, uint32 groupsize, float honor = -1); + uint32 GetHonorPoints() { return GetUInt32Value(PLAYER_FIELD_HONOR_CURRENCY); } + uint32 GetArenaPoints() { return GetUInt32Value(PLAYER_FIELD_ARENA_CURRENCY); } + void ModifyHonorPoints( int32 value ); + void ModifyArenaPoints( int32 value ); + uint32 GetMaxPersonalArenaRatingRequirement(); + + //End of PvP System + + void SetDrunkValue(uint16 newDrunkValue, uint32 itemid=0); + uint16 GetDrunkValue() const { return m_drunk; } + static DrunkenState GetDrunkenstateByValue(uint16 value); + + uint32 GetDeathTimer() const { return m_deathTimer; } + uint32 GetCorpseReclaimDelay(bool pvp) const; + void UpdateCorpseReclaimDelay(); + void SendCorpseReclaimDelay(bool load = false); + + uint32 GetShieldBlockValue() const; // overwrite Unit version (virtual) + bool CanParry() const { return m_canParry; } + void SetCanParry(bool value) { m_canParry = value; } + bool CanDualWield() const { return m_canDualWield; } + void SetCanDualWield(bool value) { m_canDualWield = value; } + + void SetRegularAttackTime(); + void SetBaseModValue(BaseModGroup modGroup, BaseModType modType, float value) { m_auraBaseMod[modGroup][modType] = value; } + void HandleBaseModValue(BaseModGroup modGroup, BaseModType modType, float amount, bool apply, bool affectStats = true); + float GetBaseModValue(BaseModGroup modGroup, BaseModType modType) const; + float GetTotalBaseModValue(BaseModGroup modGroup) const; + float GetTotalPercentageModValue(BaseModGroup modGroup) const { return m_auraBaseMod[modGroup][FLAT_MOD] + m_auraBaseMod[modGroup][PCT_MOD]; } + void _ApplyAllStatBonuses(); + void _RemoveAllStatBonuses(); + + void _ApplyWeaponDependentAuraMods(Item *item,WeaponAttackType attackType,bool apply); + void _ApplyWeaponDependentAuraCritMod(Item *item, WeaponAttackType attackType, Aura* aura, bool apply); + void _ApplyWeaponDependentAuraDamageMod(Item *item, WeaponAttackType attackType, Aura* aura, bool apply); + + void _ApplyItemMods(Item *item,uint8 slot,bool apply); + void _RemoveAllItemMods(); + void _ApplyAllItemMods(); + void _ApplyItemBonuses(ItemPrototype const *proto,uint8 slot,bool apply); + void _ApplyAmmoBonuses(); + bool EnchantmentFitsRequirements(uint32 enchantmentcondition, int8 slot); + void ToggleMetaGemsActive(uint8 exceptslot, bool apply); + void CorrectMetaGemEnchants(uint8 slot, bool apply); + void InitDataForForm(bool reapplyMods = false); + + void ApplyItemEquipSpell(Item *item, bool apply, bool form_change = false); + void ApplyEquipSpell(SpellEntry const* spellInfo, Item* item, bool apply, bool form_change = false); + void UpdateEquipSpellsAtFormChange(); + void CastItemCombatSpell(Item *item,Unit* Target, WeaponAttackType attType); + + void SendInitWorldStates(); + void SendUpdateWorldState(uint32 Field, uint32 Value); + void SendDirectMessage(WorldPacket *data); + + void SendAuraDurationsForTarget(Unit* target); + + PlayerMenu* PlayerTalkClass; + std::vector ItemSetEff; + + void SendLoot(uint64 guid, LootType loot_type); + void SendLootRelease( uint64 guid ); + void SendNotifyLootItemRemoved(uint8 lootSlot); + void SendNotifyLootMoneyRemoved(); + + /*********************************************************/ + /*** BATTLEGROUND SYSTEM ***/ + /*********************************************************/ + + bool InBattleGround() const { return m_bgBattleGroundID != 0; } + uint32 GetBattleGroundId() const { return m_bgBattleGroundID; } + BattleGround* GetBattleGround() const; + bool InArena() const; + + static uint32 GetMinLevelForBattleGroundQueueId(uint32 queue_id); + static uint32 GetMaxLevelForBattleGroundQueueId(uint32 queue_id); + uint32 GetBattleGroundQueueIdFromLevel() const; + + uint32 GetBattleGroundQueueId(uint32 index) const { return m_bgBattleGroundQueueID[index].bgType; } + uint32 GetBattleGroundQueueIndex(uint32 bgType) const + { + for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) + if (m_bgBattleGroundQueueID[i].bgType == bgType) + return i; + return PLAYER_MAX_BATTLEGROUND_QUEUES; + } + bool IsInvitedForBattleGroundType(uint32 bgType) const + { + for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) + if (m_bgBattleGroundQueueID[i].bgType == bgType) + return m_bgBattleGroundQueueID[i].invited; + return PLAYER_MAX_BATTLEGROUND_QUEUES; + } + bool InBattleGroundQueueForBattleGroundType(uint32 bgType) const + { + return GetBattleGroundQueueIndex(bgType) < PLAYER_MAX_BATTLEGROUND_QUEUES; + } + + void SetBattleGroundId(uint32 val) { m_bgBattleGroundID = val; } + uint32 AddBattleGroundQueueId(uint32 val) + { + for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) + { + if (m_bgBattleGroundQueueID[i].bgType == 0 || m_bgBattleGroundQueueID[i].bgType == val) + { + m_bgBattleGroundQueueID[i].bgType = val; + m_bgBattleGroundQueueID[i].invited = false; + return i; + } + } + return PLAYER_MAX_BATTLEGROUND_QUEUES; + } + void RemoveBattleGroundQueueId(uint32 val) + { + for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) + { + if (m_bgBattleGroundQueueID[i].bgType == val) + { + m_bgBattleGroundQueueID[i].bgType = 0; + m_bgBattleGroundQueueID[i].invited = false; + return; + } + } + } + void SetInviteForBattleGroundType(uint32 bgType) + { + for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) + if (m_bgBattleGroundQueueID[i].bgType == bgType) + m_bgBattleGroundQueueID[i].invited = true; + } + + uint32 GetBattleGroundEntryPointMap() const { return m_bgEntryPointMap; } + float GetBattleGroundEntryPointX() const { return m_bgEntryPointX; } + float GetBattleGroundEntryPointY() const { return m_bgEntryPointY; } + float GetBattleGroundEntryPointZ() const { return m_bgEntryPointZ; } + float GetBattleGroundEntryPointO() const { return m_bgEntryPointO; } + void SetBattleGroundEntryPoint(uint32 Map, float PosX, float PosY, float PosZ, float PosO ) + { + m_bgEntryPointMap = Map; + m_bgEntryPointX = PosX; + m_bgEntryPointY = PosY; + m_bgEntryPointZ = PosZ; + m_bgEntryPointO = PosO; + } + + void SetBGTeam(uint32 team) { m_bgTeam = team; } + uint32 GetBGTeam() const { return m_bgTeam ? m_bgTeam : GetTeam(); } + + void LeaveBattleground(bool teleportToEntryPoint = true); + bool CanJoinToBattleground() const; + bool CanReportAfkDueToLimit(); + void ReportedAfkBy(Player* reporter); + void ClearAfkReports() { m_bgAfkReporter.clear(); } + + bool GetBGAccessByLevel(uint32 bgTypeId) const; + + /*********************************************************/ + /*** REST SYSTEM ***/ + /*********************************************************/ + + bool isRested() const { return GetRestTime() >= 10000; } + uint32 GetXPRestBonus(uint32 xp); + uint32 GetRestTime() const { return m_restTime;}; + void SetRestTime(uint32 v) { m_restTime = v;}; + + /*********************************************************/ + /*** ENVIROMENTAL SYSTEM ***/ + /*********************************************************/ + + void EnvironmentalDamage(uint64 guid, EnviromentalDamage type, uint32 damage); + + /*********************************************************/ + /*** FLOOD FILTER SYSTEM ***/ + /*********************************************************/ + + void UpdateSpeakTime(); + bool CanSpeak() const; + void ChangeSpeakTime(int utime); + + /*********************************************************/ + /*** VARIOUS SYSTEMS ***/ + /*********************************************************/ + MovementInfo m_movementInfo; + bool isMoving() const { return HasUnitMovementFlag(movementFlagsMask); } + bool isMovingOrTurning() const { return HasUnitMovementFlag(movementOrTurningFlagsMask); } + + bool CanFly() const { return HasUnitMovementFlag(MOVEMENTFLAG_CAN_FLY); } + bool IsFlying() const { return HasUnitMovementFlag(MOVEMENTFLAG_FLYING); } + + void HandleDrowning(); + + void SetClientControl(Unit* target, uint8 allowMove); + + // Transports + Transport * GetTransport() const { return m_transport; } + void SetTransport(Transport * t) { m_transport = t; } + + float GetTransOffsetX() const { return m_movementInfo.t_x; } + float GetTransOffsetY() const { return m_movementInfo.t_y; } + float GetTransOffsetZ() const { return m_movementInfo.t_z; } + float GetTransOffsetO() const { return m_movementInfo.t_o; } + uint32 GetTransTime() const { return m_movementInfo.t_time; } + + uint32 GetSaveTimer() const { return m_nextSave; } + void SetSaveTimer(uint32 timer) { m_nextSave = timer; } + + // Recall position + uint32 m_recallMap; + float m_recallX; + float m_recallY; + float m_recallZ; + float m_recallO; + void SaveRecallPosition(); + + // Homebind coordinates + uint32 m_homebindMapId; + uint16 m_homebindZoneId; + float m_homebindX; + float m_homebindY; + float m_homebindZ; + + // currently visible objects at player client + typedef std::set ClientGUIDs; + ClientGUIDs m_clientGUIDs; + + bool HaveAtClient(WorldObject const* u) { return u==this || m_clientGUIDs.find(u->GetGUID())!=m_clientGUIDs.end(); } + + bool IsVisibleInGridForPlayer(Player* pl) const; + bool IsVisibleGloballyFor(Player* pl) const; + + void UpdateVisibilityOf(WorldObject* target); + + template + void UpdateVisibilityOf(T* target, UpdateData& data, UpdateDataMapType& data_updates, std::set& visibleNow); + + // Stealth detection system + uint32 m_DetectInvTimer; + void HandleStealthedUnitsDetection(); + + uint8 m_forced_speed_changes[MAX_MOVE_TYPE]; + + bool HasAtLoginFlag(AtLoginFlags f) const { return m_atLoginFlags & f; } + void SetAtLoginFlag(AtLoginFlags f) { m_atLoginFlags |= f; } + + LookingForGroup m_lookingForGroup; + + // Temporarily removed pet cache + uint32 GetTemporaryUnsummonedPetNumber() const { return m_temporaryUnsummonedPetNumber; } + void SetTemporaryUnsummonedPetNumber(uint32 petnumber) { m_temporaryUnsummonedPetNumber = petnumber; } + uint32 GetOldPetSpell() const { return m_oldpetspell; } + void SetOldPetSpell(uint32 petspell) { m_oldpetspell = petspell; } + + /*********************************************************/ + /*** INSTANCE SYSTEM ***/ + /*********************************************************/ + + typedef HM_NAMESPACE::hash_map< uint32 /*mapId*/, InstancePlayerBind > BoundInstancesMap; + + void UpdateHomebindTime(uint32 time); + + uint32 m_HomebindTimer; + bool m_InstanceValid; + // permanent binds and solo binds by difficulty + BoundInstancesMap m_boundInstances[TOTAL_DIFFICULTIES]; + InstancePlayerBind* GetBoundInstance(uint32 mapid, uint8 difficulty); + BoundInstancesMap& GetBoundInstances(uint8 difficulty) { return m_boundInstances[difficulty]; } + void UnbindInstance(uint32 mapid, uint8 difficulty, bool unload = false); + void UnbindInstance(BoundInstancesMap::iterator &itr, uint8 difficulty, bool unload = false); + InstancePlayerBind* BindToInstance(InstanceSave *save, bool permanent, bool load = false); + void SendRaidInfo(); + void SendSavedInstances(); + static void ConvertInstancesToGroup(Player *player, Group *group = NULL, uint64 player_guid = 0); + + /*********************************************************/ + /*** GROUP SYSTEM ***/ + /*********************************************************/ + + Group * GetGroupInvite() { return m_groupInvite; } + void SetGroupInvite(Group *group) { m_groupInvite = group; } + Group * GetGroup() { return m_group.getTarget(); } + const Group * GetGroup() const { return (const Group*)m_group.getTarget(); } + GroupReference& GetGroupRef() { return m_group; } + void SetGroup(Group *group, int8 subgroup = -1); + uint8 GetSubGroup() const { return m_group.getSubGroup(); } + uint32 GetGroupUpdateFlag() { return m_groupUpdateMask; } + void SetGroupUpdateFlag(uint32 flag) { m_groupUpdateMask |= flag; } + uint64 GetAuraUpdateMask() { return m_auraUpdateMask; } + void SetAuraUpdateMask(uint8 slot) { m_auraUpdateMask |= (uint64(1) << slot); } + Player* GetNextRandomRaidMember(float radius); + + GridReference &GetGridRef() { return m_gridRef; } + bool isAllowedToLoot(Creature* creature); + + WorldLocation& GetTeleportDest() { return m_teleport_dest; } + + DeclinedName const* GetDeclinedNames() const { return m_declinedname; } + + protected: + + /*********************************************************/ + /*** BATTLEGROUND SYSTEM ***/ + /*********************************************************/ + + /* this variable is set to bg->m_InstanceID, when player is teleported to BG - (it is battleground's GUID)*/ + uint32 m_bgBattleGroundID; + /* + this is an array of BG queues (BgTypeIDs) in which is player + */ + struct BgBattleGroundQueueID_Rec + { + uint32 bgType; + bool invited; + }; + BgBattleGroundQueueID_Rec m_bgBattleGroundQueueID[PLAYER_MAX_BATTLEGROUND_QUEUES]; + uint32 m_bgEntryPointMap; + float m_bgEntryPointX; + float m_bgEntryPointY; + float m_bgEntryPointZ; + float m_bgEntryPointO; + + std::set m_bgAfkReporter; + uint8 m_bgAfkReportedCount; + time_t m_bgAfkReportedTimer; + uint32 m_contestedPvPTimer; + + uint32 m_bgTeam; // what side the player will be added to + + /*********************************************************/ + /*** QUEST SYSTEM ***/ + /*********************************************************/ + + std::set m_timedquests; + + uint64 m_divider; + uint32 m_ingametime; + + /*********************************************************/ + /*** LOAD SYSTEM ***/ + /*********************************************************/ + + void _LoadActions(QueryResult *result); + void _LoadAuras(QueryResult *result, uint32 timediff); + void _LoadBoundInstances(QueryResult *result); + void _LoadInventory(QueryResult *result, uint32 timediff); + void _LoadMailInit(QueryResult *resultUnread, QueryResult *resultDelivery); + void _LoadMail(); + void _LoadMailedItems(Mail *mail); + void _LoadQuestStatus(QueryResult *result); + void _LoadDailyQuestStatus(QueryResult *result); + void _LoadGroup(QueryResult *result); + void _LoadReputation(QueryResult *result); + void _LoadSpells(QueryResult *result); + void _LoadTutorials(QueryResult *result); + void _LoadFriendList(QueryResult *result); + bool _LoadHomeBind(QueryResult *result); + void _LoadDeclinedNames(QueryResult *result); + + /*********************************************************/ + /*** SAVE SYSTEM ***/ + /*********************************************************/ + + void _SaveActions(); + void _SaveAuras(); + void _SaveInventory(); + void _SaveMail(); + void _SaveQuestStatus(); + void _SaveDailyQuestStatus(); + void _SaveReputation(); + void _SaveSpells(); + void _SaveTutorials(); + + void _SetCreateBits(UpdateMask *updateMask, Player *target) const; + void _SetUpdateBits(UpdateMask *updateMask, Player *target) const; + + /*********************************************************/ + /*** ENVIRONMENTAL SYSTEM ***/ + /*********************************************************/ + void HandleLava(); + void HandleSobering(); + void StartMirrorTimer(MirrorTimerType Type, uint32 MaxValue); + void ModifyMirrorTimer(MirrorTimerType Type, uint32 MaxValue, uint32 CurrentValue, uint32 Regen); + void StopMirrorTimer(MirrorTimerType Type); + uint8 m_isunderwater; + bool m_isInWater; + + /*********************************************************/ + /*** HONOR SYSTEM ***/ + /*********************************************************/ + time_t m_lastHonorUpdateTime; + + void outDebugValues() const; + bool _removeSpell(uint16 spell_id); + uint64 m_lootGuid; + + uint32 m_race; + uint32 m_class; + uint32 m_team; + uint32 m_nextSave; + time_t m_speakTime; + uint32 m_speakCount; + uint32 m_dungeonDifficulty; + + uint32 m_atLoginFlags; + + Item* m_items[PLAYER_SLOTS_COUNT]; + uint32 m_currentBuybackSlot; + + std::vector m_itemUpdateQueue; + bool m_itemUpdateQueueBlocked; + + uint32 m_ExtraFlags; + uint64 m_curSelection; + + uint64 m_comboTarget; + int8 m_comboPoints; + + QuestStatusMap mQuestStatus; + + uint32 m_GuildIdInvited; + uint32 m_ArenaTeamIdInvited; + + PlayerMails m_mail; + PlayerSpellMap m_spells; + SpellCooldowns m_spellCooldowns; + + ActionButtonList m_actionButtons; + + float m_auraBaseMod[BASEMOD_END][MOD_END]; + + SpellModList m_spellMods[MAX_SPELLMOD]; + int32 m_SpellModRemoveCount; + EnchantDurationList m_enchantDuration; + ItemDurationList m_itemDuration; + + uint64 m_resurrectGUID; + uint32 m_resurrectMap; + float m_resurrectX, m_resurrectY, m_resurrectZ; + uint32 m_resurrectHealth, m_resurrectMana; + + WorldSession *m_session; + + typedef std::list JoinedChannelsList; + JoinedChannelsList m_channels; + + bool m_dontMove; + + int m_cinematic; + + Player *pTrader; + bool acceptTrade; + uint16 tradeItems[TRADE_SLOT_COUNT]; + uint32 tradeGold; + + time_t m_nextThinkTime; + + uint32 m_Tutorials[8]; + bool m_TutorialsChanged; + + bool m_DailyQuestChanged; + time_t m_lastDailyQuestTime; + + uint32 m_regenTimer; + uint32 m_breathTimer; + uint32 m_drunkTimer; + uint16 m_drunk; + uint32 m_weaponChangeTimer; + + uint32 m_zoneUpdateId; + uint32 m_zoneUpdateTimer; + uint32 m_areaUpdateId; + + uint32 m_deathTimer; + time_t m_deathExpireTime; + + uint32 m_restTime; + + uint32 m_WeaponProficiency; + uint32 m_ArmorProficiency; + bool m_canParry; + bool m_canDualWield; + uint8 m_swingErrorMsg; + float m_ammoDPS; + ////////////////////Rest System///////////////////// + int time_inn_enter; + uint32 inn_pos_mapid; + float inn_pos_x; + float inn_pos_y; + float inn_pos_z; + float m_rest_bonus; + RestType rest_type; + ////////////////////Rest System///////////////////// + + // Transports + Transport * m_transport; + + uint32 m_resetTalentsCost; + time_t m_resetTalentsTime; + uint32 m_usedTalentCount; + + // Social + PlayerSocial *m_social; + + // Groups + GroupReference m_group; + Group *m_groupInvite; + uint32 m_groupUpdateMask; + uint64 m_auraUpdateMask; + + // Temporarily removed pet cache + uint32 m_temporaryUnsummonedPetNumber; + uint32 m_oldpetspell; + + uint64 m_miniPet; + GuardianPetList m_guardianPets; + + // Player summoning + time_t m_summon_expire; + uint32 m_summon_mapid; + float m_summon_x; + float m_summon_y; + float m_summon_z; + + // Far Teleport + WorldLocation m_teleport_dest; + + DeclinedName *m_declinedname; + private: + // internal common parts for CanStore/StoreItem functions + uint8 _CanStoreItem_InSpecificSlot( uint8 bag, uint8 slot, ItemPosCountVec& dest, ItemPrototype const *pProto, uint32& count, bool swap, Item *pSrcItem ) const; + uint8 _CanStoreItem_InBag( uint8 bag, ItemPosCountVec& dest, ItemPrototype const *pProto, uint32& count, bool merge, bool non_specialized, Item *pSrcItem, uint8 skip_bag, uint8 skip_slot ) const; + uint8 _CanStoreItem_InInventorySlots( uint8 slot_begin, uint8 slot_end, ItemPosCountVec& dest, ItemPrototype const *pProto, uint32& count, bool merge, Item *pSrcItem, uint8 skip_bag, uint8 skip_slot ) const; + Item* _StoreItem( uint16 pos, Item *pItem, uint32 count, bool clone, bool update ); + + GridReference m_gridRef; +}; + +void AddItemsSetItem(Player*player,Item *item); +void RemoveItemsSetItem(Player*player,ItemPrototype const *proto); + +// "the bodies of template functions must be made available in a header file" +template T Player::ApplySpellMod(uint32 spellId, SpellModOp op, T &basevalue, Spell const* spell) +{ + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); + if (!spellInfo) return 0; + int32 totalpct = 0; + int32 totalflat = 0; + for (SpellModList::iterator itr = m_spellMods[op].begin(); itr != m_spellMods[op].end(); ++itr) + { + SpellModifier *mod = *itr; + + if(!IsAffectedBySpellmod(spellInfo,mod,spell)) + continue; + if (mod->type == SPELLMOD_FLAT) + totalflat += mod->value; + else if (mod->type == SPELLMOD_PCT) + { + // skip percent mods for null basevalue (most important for spell mods with charges ) + if(basevalue == T(0)) + continue; + + // special case (skip >10sec spell casts for instant cast setting) + if( mod->op==SPELLMOD_CASTING_TIME && basevalue >= T(10000) && mod->value <= -100) + continue; + + totalpct += mod->value; + } + + if (mod->charges > 0 ) + { + --mod->charges; + if (mod->charges == 0) + { + mod->charges = -1; + mod->lastAffected = spell; + if(!mod->lastAffected) + mod->lastAffected = FindCurrentSpellBySpellId(spellId); + ++m_SpellModRemoveCount; + } + } + } + + float diff = (float)basevalue*(float)totalpct/100.0f + (float)totalflat; + basevalue = T((float)basevalue + diff); + return T(diff); +} +#endif diff --git a/src/game/PlayerDump.cpp b/src/game/PlayerDump.cpp new file mode 100644 index 00000000000..413f006b501 --- /dev/null +++ b/src/game/PlayerDump.cpp @@ -0,0 +1,605 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "PlayerDump.h" +#include "Database/DatabaseEnv.h" +#include "Database/SQLStorage.h" +#include "UpdateFields.h" +#include "ObjectMgr.h" + +// Character Dump tables +#define DUMP_TABLE_COUNT 20 + +struct DumpTable +{ + char const* name; + DumpTableType type; +}; + +static DumpTable dumpTables[DUMP_TABLE_COUNT] = +{ + { "characters", DTT_CHARACTER }, + { "character_queststatus", DTT_CHAR_TABLE }, + { "character_reputation", DTT_CHAR_TABLE }, + { "character_spell", DTT_CHAR_TABLE }, + { "character_spell_cooldown", DTT_CHAR_TABLE }, + { "character_action", DTT_CHAR_TABLE }, + { "character_aura", DTT_CHAR_TABLE }, + { "character_homebind", DTT_CHAR_TABLE }, + { "character_ticket", DTT_CHAR_TABLE }, + { "character_inventory", DTT_INVENTORY }, + { "mail", DTT_MAIL }, + { "mail_items", DTT_MAIL_ITEM }, + { "item_instance", DTT_ITEM }, + { "character_gifts", DTT_ITEM_GIFT }, + { "item_text", DTT_ITEM_TEXT }, + { "character_pet", DTT_PET }, + { "pet_aura", DTT_PET_TABLE }, + { "pet_spell", DTT_PET_TABLE }, + { "pet_spell_cooldown", DTT_PET_TABLE }, +}; + +// Low level functions +static bool findtoknth(std::string &str, int n, std::string::size_type &s, std::string::size_type &e) +{ + int i; s = e = 0; + std::string::size_type size = str.size(); + for(i = 1; s < size && i < n; s++) if(str[s] == ' ') ++i; + if (i < n) + return false; + + e = str.find(' ', s); + + return e != std::string::npos; +} + +std::string gettoknth(std::string &str, int n) +{ + std::string::size_type s = 0, e = 0; + if(!findtoknth(str, n, s, e)) + return ""; + + return str.substr(s, e-s); +} + +bool findnth(std::string &str, int n, std::string::size_type &s, std::string::size_type &e) +{ + s = str.find("VALUES ('")+9; + if (s == std::string::npos) return false; + + do + { + e = str.find("'",s); + if (e == std::string::npos) return false; + } while(str[e-1] == '\\'); + + for(int i = 1; i < n; i++) + { + do + { + s = e+4; + e = str.find("'",s); + if (e == std::string::npos) return false; + } while (str[e-1] == '\\'); + } + return true; +} + +std::string gettablename(std::string &str) +{ + std::string::size_type s = 13; + std::string::size_type e = str.find(_TABLE_SIM_, s); + if (e == std::string::npos) + return ""; + + return str.substr(s, e-s); +} + +bool changenth(std::string &str, int n, const char *with, bool insert = false, bool nonzero = false) +{ + std::string::size_type s, e; + if(!findnth(str,n,s,e)) + return false; + + if(nonzero && str.substr(s,e-s) == "0") + return true; // not an error + if(!insert) + str.replace(s,e-s, with); + else + str.insert(s, with); + + return true; +} + +std::string getnth(std::string &str, int n) +{ + std::string::size_type s, e; + if(!findnth(str,n,s,e)) + return ""; + + return str.substr(s, e-s); +} + +bool changetoknth(std::string &str, int n, const char *with, bool insert = false, bool nonzero = false) +{ + std::string::size_type s = 0, e = 0; + if(!findtoknth(str, n, s, e)) + return false; + if(nonzero && str.substr(s,e-s) == "0") + return true; // not an error + if(!insert) + str.replace(s, e-s, with); + else + str.insert(s, with); + + return true; +} + +uint32 registerNewGuid(uint32 oldGuid, std::map &guidMap, uint32 hiGuid) +{ + std::map::iterator itr = guidMap.find(oldGuid); + if(itr != guidMap.end()) + return itr->second; + + uint32 newguid = hiGuid + guidMap.size(); + guidMap[oldGuid] = newguid; + return newguid; +} + +bool changeGuid(std::string &str, int n, std::map &guidMap, uint32 hiGuid, bool nonzero = false) +{ + char chritem[20]; + uint32 oldGuid = atoi(getnth(str, n).c_str()); + if (nonzero && oldGuid == 0) + return true; // not an error + + uint32 newGuid = registerNewGuid(oldGuid, guidMap, hiGuid); + snprintf(chritem, 20, "%d", newGuid); + + return changenth(str, n, chritem, false, nonzero); +} + +bool changetokGuid(std::string &str, int n, std::map &guidMap, uint32 hiGuid, bool nonzero = false) +{ + char chritem[20]; + uint32 oldGuid = atoi(gettoknth(str, n).c_str()); + if (nonzero && oldGuid == 0) + return true; // not an error + + uint32 newGuid = registerNewGuid(oldGuid, guidMap, hiGuid); + snprintf(chritem, 20, "%d", newGuid); + + return changetoknth(str, n, chritem, false, nonzero); +} + +std::string CreateDumpString(char const* tableName, QueryResult *result) +{ + if(!tableName || !result) return ""; + std::ostringstream ss; + ss << "INSERT INTO "<< _TABLE_SIM_ << tableName << _TABLE_SIM_ << " VALUES ("; + Field *fields = result->Fetch(); + for(uint32 i = 0; i < result->GetFieldCount(); i++) + { + if (i == 0) ss << "'"; + else ss << ", '"; + + std::string s = fields[i].GetCppString(); + CharacterDatabase.escape_string(s); + ss << s; + + ss << "'"; + } + ss << ");"; + return ss.str(); +} + +std::string PlayerDumpWriter::GenerateWhereStr(char const* field, uint32 guid) +{ + std::ostringstream wherestr; + wherestr << field << " = '" << guid << "'"; + return wherestr.str(); +} + +std::string PlayerDumpWriter::GenerateWhereStr(char const* field, GUIDs const& guids, GUIDs::const_iterator& itr) +{ + std::ostringstream wherestr; + wherestr << field << " IN ('"; + for(; itr != guids.end(); ++itr) + { + wherestr << *itr; + + if(wherestr.str().size() > MAX_QUERY_LEN - 50) // near to max query + { + ++itr; + break; + } + + GUIDs::const_iterator itr2 = itr; + if(++itr2 != guids.end()) + wherestr << "','"; + } + wherestr << "')"; + return wherestr.str(); +} + +void StoreGUID(QueryResult *result,uint32 field,std::set& guids) +{ + Field* fields = result->Fetch(); + uint32 guid = fields[field].GetUInt32(); + if(guid) + guids.insert(guid); +} + +void StoreGUID(QueryResult *result,uint32 data,uint32 field, std::set& guids) +{ + Field* fields = result->Fetch(); + std::string dataStr = fields[data].GetCppString(); + uint32 guid = atoi(gettoknth(dataStr, field).c_str()); + if(guid) + guids.insert(guid); +} + +// Writing - High-level functions +bool PlayerDumpWriter::DumpTable(std::string& dump, uint32 guid, char const*tableFrom, char const*tableTo, DumpTableType type) +{ + if (!tableFrom || !tableTo) + return false; + + GUIDs const* guids = NULL; + char const* fieldname = NULL; + + switch ( type ) + { + case DTT_ITEM: fieldname = "guid"; guids = &items; break; + case DTT_ITEM_GIFT: fieldname = "item_guid"; guids = &items; break; + case DTT_PET: fieldname = "owner"; break; + case DTT_PET_TABLE: fieldname = "guid"; guids = &pets; break; + case DTT_MAIL: fieldname = "receiver"; break; + case DTT_MAIL_ITEM: fieldname = "mail_id"; guids = &mails; break; + case DTT_ITEM_TEXT: fieldname = "id"; guids = &texts; break; + default: fieldname = "guid"; break; + } + + // for guid set stop if set is empty + if(guids && guids->empty()) + return true; // nothing to do + + // setup for guids case start position + GUIDs::const_iterator guids_itr; + if(guids) + guids_itr = guids->begin(); + + do + { + std::string wherestr; + + if(guids) // set case, get next guids string + wherestr = GenerateWhereStr(fieldname,*guids,guids_itr); + else // not set case, get single guid string + wherestr = GenerateWhereStr(fieldname,guid); + + QueryResult *result = CharacterDatabase.PQuery("SELECT * FROM %s WHERE %s", tableFrom, wherestr.c_str()); + if(!result) + return false; + + do + { + // collect guids + switch ( type ) + { + case DTT_INVENTORY: + StoreGUID(result,3,items); break; // item guid collection + case DTT_ITEM: + StoreGUID(result,0,ITEM_FIELD_ITEM_TEXT_ID,texts); break; + // item text id collection + case DTT_PET: + StoreGUID(result,0,pets); break; // pet guid collection + case DTT_MAIL: + StoreGUID(result,0,mails); // mail id collection + StoreGUID(result,6,texts); break; // item text id collection + case DTT_MAIL_ITEM: + StoreGUID(result,1,items); break; // item guid collection + default: break; + } + + dump += CreateDumpString(tableTo, result); + dump += "\n"; + } + while (result->NextRow()); + + delete result; + } + while(guids && guids_itr != guids->end()); // not set case iterate single time, set case iterate for all guids + + return true; +} + +std::string PlayerDumpWriter::GetDump(uint32 guid) +{ + std::string dump; + for(int i = 0; i < DUMP_TABLE_COUNT; i++) + DumpTable(dump, guid, dumpTables[i].name, dumpTables[i].name, dumpTables[i].type); + + // TODO: Add instance/group/gifts.. + // TODO: Add a dump level option to skip some non-important tables + + return dump; +} + +bool PlayerDumpWriter::WriteDump(std::string file, uint32 guid) +{ + FILE *fout = fopen(file.c_str(), "w"); + if (!fout) { sLog.outError("Failed to open file!\r\n"); return false; } + + std::string dump = GetDump(guid); + + fprintf(fout,"%s\n",dump.c_str()); + fclose(fout); + return true; +} + +// Reading - High-level functions +#define ROLLBACK {CharacterDatabase.RollbackTransaction(); fclose(fin); return false;} + +bool PlayerDumpReader::LoadDump(std::string file, uint32 account, std::string name, uint32 guid) +{ + // check character count + { + QueryResult *result = CharacterDatabase.PQuery("SELECT COUNT(guid) FROM characters WHERE account = '%d'", account); + uint8 charcount = 0; + if ( result ) + { + Field *fields=result->Fetch(); + charcount = fields[0].GetUInt8(); + delete result; + + if (charcount >= 10) + { + return false; + } + } + } + FILE *fin = fopen(file.c_str(), "r"); + if(!fin) return false; + + QueryResult * result = NULL; + char newguid[20], chraccount[20], newpetid[20], currpetid[20], lastpetid[20]; + + // make sure the same guid doesn't already exist and is safe to use + bool incHighest = true; + if(guid != 0 && guid < objmgr.m_hiCharGuid) + { + result = CharacterDatabase.PQuery("SELECT * FROM characters WHERE guid = '%d'", guid); + if (result) + { + guid = objmgr.m_hiCharGuid; // use first free if exists + delete result; + } + else incHighest = false; + } + else guid = objmgr.m_hiCharGuid; + + // normalize the name if specified and check if it exists + if(!normalizePlayerName(name)) + name = ""; + + if(ObjectMgr::IsValidName(name,true)) + { + CharacterDatabase.escape_string(name); // for safe, we use name only for sql quearies anyway + result = CharacterDatabase.PQuery("SELECT * FROM characters WHERE name = '%s'", name.c_str()); + if (result) + { + name = ""; // use the one from the dump + delete result; + } + } + else name = ""; + + // name encoded or empty + + snprintf(newguid, 20, "%d", guid); + snprintf(chraccount, 20, "%d", account); + snprintf(newpetid, 20, "%d", objmgr.GeneratePetNumber()); + snprintf(lastpetid, 20, "%s", ""); + + std::map items; + std::map mails; + char buf[32000] = ""; + + typedef std::map PetIds; // old->new petid relation + typedef PetIds::value_type PetIdsPair; + PetIds petids; + + CharacterDatabase.BeginTransaction(); + while(!feof(fin)) + { + if(!fgets(buf, 32000, fin)) + { + if(feof(fin)) break; + sLog.outError("LoadPlayerDump: File read error!"); + ROLLBACK; + } + + std::string line; line.assign(buf); + + // skip empty strings + if(line.find_first_not_of(" \t\n\r\7")==std::string::npos) + continue; + + // determine table name and load type + std::string tn = gettablename(line); + if(tn.empty()) + { + sLog.outError("LoadPlayerDump: Can't extract table name from line: '%s'!", line.c_str()); + ROLLBACK; + } + + DumpTableType type; + uint8 i; + for(i = 0; i < DUMP_TABLE_COUNT; i++) + { + if (tn == dumpTables[i].name) + { + type = dumpTables[i].type; + break; + } + } + + if (i == DUMP_TABLE_COUNT) + { + sLog.outError("LoadPlayerDump: Unknown table: '%s'!", tn.c_str()); + ROLLBACK; + } + + // change the data to server values + switch(type) + { + case DTT_CHAR_TABLE: + if(!changenth(line, 1, newguid)) ROLLBACK; + break; + + case DTT_CHARACTER: // character t. + { + if(!changenth(line, 1, newguid)) ROLLBACK; + + // guid, data field:guid, items + if(!changenth(line, 2, chraccount)) ROLLBACK; + std::string vals = getnth(line, 3); + if(!changetoknth(vals, OBJECT_FIELD_GUID+1, newguid)) ROLLBACK; + for(uint16 field = PLAYER_FIELD_INV_SLOT_HEAD; field < PLAYER_FARSIGHT; field++) + if(!changetokGuid(vals, field+1, items, objmgr.m_hiItemGuid, true)) ROLLBACK; + if(!changenth(line, 3, vals.c_str())) ROLLBACK; + if (name == "") + { + // check if the original name already exists + name = getnth(line, 4); + CharacterDatabase.escape_string(name); + + result = CharacterDatabase.PQuery("SELECT * FROM characters WHERE name = '%s'", name.c_str()); + if (result) + { + delete result; + // rename on login: `at_login` field 30 in raw field list + if(!changenth(line, 30, "1")) ROLLBACK; + } + } + else if(!changenth(line, 4, name.c_str())) ROLLBACK; + + break; + } + case DTT_INVENTORY: // character_inventory t. + { + if(!changenth(line, 1, newguid)) ROLLBACK; + + // bag, item + if(!changeGuid(line, 2, items, objmgr.m_hiItemGuid, true)) ROLLBACK; + if(!changeGuid(line, 4, items, objmgr.m_hiItemGuid)) ROLLBACK; + break; + } + case DTT_ITEM: // item_instance t. + { + // item, owner, data field:item, owner guid + if(!changeGuid(line, 1, items, objmgr.m_hiItemGuid)) ROLLBACK; + if(!changenth(line, 2, newguid)) ROLLBACK; + std::string vals = getnth(line,3); + if(!changetokGuid(vals, OBJECT_FIELD_GUID+1, items, objmgr.m_hiItemGuid)) ROLLBACK; + if(!changetoknth(vals, ITEM_FIELD_OWNER+1, newguid)) ROLLBACK; + if(!changenth(line, 3, vals.c_str())) ROLLBACK; + break; + } + case DTT_ITEM_GIFT: // character_gift + { + // guid,item_guid, + if(!changenth(line, 1, newguid)) ROLLBACK; + if(!changeGuid(line, 2, items, objmgr.m_hiItemGuid)) ROLLBACK; + break; + } + case DTT_PET: // character_pet t + { + //store a map of old pet id to new inserted pet id for use by type 5 tables + snprintf(currpetid, 20, "%s", getnth(line, 1).c_str()); + if(strlen(lastpetid)==0) snprintf(lastpetid, 20, "%s", currpetid); + if(strcmp(lastpetid,currpetid)!=0) + { + snprintf(newpetid, 20, "%d", objmgr.GeneratePetNumber()); + snprintf(lastpetid, 20, "%s", currpetid); + } + + std::map :: const_iterator petids_iter = petids.find(atoi(currpetid)); + + if(petids_iter == petids.end()) + { + petids.insert(PetIdsPair(atoi(currpetid), atoi(newpetid))); + } + + // item, entry, owner, ... + if(!changenth(line, 1, newpetid)) ROLLBACK; + if(!changenth(line, 3, newguid)) ROLLBACK; + + break; + } + case DTT_PET_TABLE: // pet_aura, pet_spell, pet_spell_cooldown t + { + snprintf(currpetid, 20, "%s", getnth(line, 1).c_str()); + + // lookup currpetid and match to new inserted pet id + std::map :: const_iterator petids_iter = petids.find(atoi(currpetid)); + if(petids_iter == petids.end()) ROLLBACK; // couldn't find new inserted id + + snprintf(newpetid, 20, "%d", petids_iter->second); + + if(!changenth(line, 1, newpetid)) ROLLBACK; + + break; + } + case DTT_MAIL: // mail + { + // id,messageType,stationery,sender,receiver + if(!changeGuid(line, 1, mails, objmgr.m_mailid)) ROLLBACK; + if(!changenth(line, 5, newguid)) ROLLBACK; + break; + } + case DTT_MAIL_ITEM: // mail_items + { + // mail_id,item_guid,item_template,receiver + if(!changeGuid(line, 1, mails, objmgr.m_mailid)) ROLLBACK; + if(!changeGuid(line, 2, items, objmgr.m_hiItemGuid)) ROLLBACK; + if(!changenth(line, 4, newguid)) ROLLBACK; + break; + } + default: + sLog.outError("Unknown dump table type: %u",type); + break; + } + + if(!CharacterDatabase.Execute(line.c_str())) ROLLBACK; + } + + CharacterDatabase.CommitTransaction(); + + objmgr.m_hiItemGuid += items.size(); + objmgr.m_mailid += mails.size(); + + if(incHighest) + ++objmgr.m_hiCharGuid; + + fclose(fin); + + return true; +} diff --git a/src/game/PlayerDump.h b/src/game/PlayerDump.h new file mode 100644 index 00000000000..dfcb2e8b528 --- /dev/null +++ b/src/game/PlayerDump.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _PLAYER_DUMP_H +#define _PLAYER_DUMP_H +/* +#include "Log.h" +#include "Object.h" +#include "Bag.h" +#include "Creature.h" +#include "Player.h" +#include "DynamicObject.h" +#include "GameObject.h" +#include "Corpse.h" +#include "QuestDef.h" +#include "Path.h" +#include "ItemPrototype.h" +#include "NPCHandler.h" +#include "Database/DatabaseEnv.h" +#include "AuctionHouseObject.h" +#include "Mail.h" +#include "Map.h" +#include "ObjectAccessor.h" +#include "ObjectDefines.h" +#include "Policies/Singleton.h" +#include "Database/SQLStorage.h" +*/ +#include +#include +#include + +enum DumpTableType +{ + DTT_CHARACTER, // // characters + + DTT_CHAR_TABLE, // // character_action, character_aura, character_homebind, + // character_queststatus, character_reputation, + // character_spell, character_spell_cooldown, character_ticket, + // character_tutorial + + DTT_INVENTORY, // -> item guids collection // character_inventory + + DTT_MAIL, // -> mail ids collection // mail + // -> item_text + + DTT_MAIL_ITEM, // <- mail ids // mail_items + // -> item guids collection + + DTT_ITEM, // <- item guids // item_instance + // -> item_text + + DTT_ITEM_GIFT, // <- item guids // character_gifts + + DTT_PET, // -> pet guids collection // character_pet + DTT_PET_TABLE, // <- pet guids // pet_aura, pet_spell, pet_spell_cooldown + DTT_ITEM_TEXT, // <- item_text // item_text +}; + +class PlayerDump +{ + protected: + PlayerDump() {} +}; + +class PlayerDumpWriter : public PlayerDump +{ + public: + PlayerDumpWriter() {} + + std::string GetDump(uint32 guid); + bool WriteDump(std::string file, uint32 guid); + private: + typedef std::set GUIDs; + + bool DumpTable(std::string& dump, uint32 guid, char const*tableFrom, char const*tableTo, DumpTableType type); + std::string GenerateWhereStr(char const* field, GUIDs const& guids, GUIDs::const_iterator& itr); + std::string GenerateWhereStr(char const* field, uint32 guid); + + GUIDs pets; + GUIDs mails; + GUIDs items; + GUIDs texts; +}; + +class PlayerDumpReader : public PlayerDump +{ + public: + PlayerDumpReader() {} + + bool LoadDump(std::string file, uint32 account, std::string name, uint32 guid); +}; + +#endif diff --git a/src/game/PointMovementGenerator.cpp b/src/game/PointMovementGenerator.cpp new file mode 100644 index 00000000000..c784c799351 --- /dev/null +++ b/src/game/PointMovementGenerator.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "PointMovementGenerator.h" +#include "Errors.h" +#include "Creature.h" +#include "CreatureAI.h" +#include "MapManager.h" +#include "DestinationHolderImp.h" + +//----- Point Movement Generator +template +void PointMovementGenerator::Initialize(T &unit) +{ + unit.StopMoving(); + Traveller traveller(unit); + i_destinationHolder.SetDestination(traveller,i_x,i_y,i_z); +} + +template +bool PointMovementGenerator::Update(T &unit, const uint32 &diff) +{ + if(!&unit) + return false; + + if(unit.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED)) + return true; + + Traveller traveller(unit); + + i_destinationHolder.UpdateTraveller(traveller, diff, false); + + if(i_destinationHolder.HasArrived()) + { + unit.StopMoving(); + MovementInform(unit); + return false; + } + + return true; +} + +template +void PointMovementGenerator::MovementInform(T &unit) +{ +} + +template <> void PointMovementGenerator::MovementInform(Creature &unit) +{ + unit.AI()->MovementInform(POINT_MOTION_TYPE, id); +} + +template void PointMovementGenerator::Initialize(Player&); +template bool PointMovementGenerator::Update(Player &, const uint32 &diff); +template void PointMovementGenerator::MovementInform(Player&); + +template void PointMovementGenerator::Initialize(Creature&); +template bool PointMovementGenerator::Update(Creature&, const uint32 &diff); diff --git a/src/game/PointMovementGenerator.h b/src/game/PointMovementGenerator.h new file mode 100644 index 00000000000..7127bbecee5 --- /dev/null +++ b/src/game/PointMovementGenerator.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_POINTMOVEMENTGENERATOR_H +#define MANGOS_POINTMOVEMENTGENERATOR_H + +#include "MovementGenerator.h" +#include "DestinationHolder.h" +#include "Traveller.h" +#include "FollowerReference.h" + +template +class MANGOS_DLL_SPEC PointMovementGenerator +: public MovementGeneratorMedium< T, PointMovementGenerator > +{ + public: + PointMovementGenerator(uint32 _id, float _x, float _y, float _z) : id(_id), + i_x(_x), i_y(_y), i_z(_z), i_nextMoveTime(0) {} + + void Initialize(T &); + void Finalize(T &){} + void Reset(T &unit){unit.StopMoving();} + bool Update(T &, const uint32 &diff); + + void MovementInform(T &); + + MovementGeneratorType GetMovementGeneratorType() { return POINT_MOTION_TYPE; } + + bool GetDestination(float& x, float& y, float& z) const { x=i_x; y=i_y; z=i_z; return true; } + private: + TimeTracker i_nextMoveTime; + float i_x,i_y,i_z; + uint32 id; + DestinationHolder< Traveller > i_destinationHolder; +}; +#endif diff --git a/src/game/QueryHandler.cpp b/src/game/QueryHandler.cpp new file mode 100644 index 00000000000..e04c4a909e4 --- /dev/null +++ b/src/game/QueryHandler.cpp @@ -0,0 +1,430 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Language.h" +#include "Database/DatabaseEnv.h" +#include "Database/DatabaseImpl.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Opcodes.h" +#include "Log.h" +#include "World.h" +#include "ObjectMgr.h" +#include "Player.h" +#include "UpdateMask.h" +#include "NPCHandler.h" +#include "ObjectAccessor.h" +#include "Pet.h" + +void WorldSession::SendNameQueryOpcode(Player *p) +{ + if(!p) + return; + + // guess size + WorldPacket data( SMSG_NAME_QUERY_RESPONSE, (8+1+4+4+4+10) ); + data << p->GetGUID(); + data << p->GetName(); + data << uint8(0); // realm name for cross realm BG usage + data << uint32(p->getRace()); + data << uint32(p->getGender()); + data << uint32(p->getClass()); + if(DeclinedName const* names = p->GetDeclinedNames()) + { + data << uint8(1); // is declined + for(int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) + data << names->name[i]; + } + else + data << uint8(0); // is not declined + + SendPacket(&data); +} + +void WorldSession::SendNameQueryOpcodeFromDB(uint64 guid) +{ + CharacterDatabase.AsyncPQuery(&WorldSession::SendNameQueryOpcodeFromDBCallBack, GetAccountId(), + !sWorld.getConfig(CONFIG_DECLINED_NAMES_USED) ? + // ------- Query Without Declined Names -------- + // 0 1 2 + "SELECT guid, name, SUBSTRING(data, LENGTH(SUBSTRING_INDEX(data, ' ', '%u'))+2, LENGTH(SUBSTRING_INDEX(data, ' ', '%u')) - LENGTH(SUBSTRING_INDEX(data, ' ', '%u'))-1) " + "FROM characters WHERE guid = '%u'" + : + // --------- Query With Declined Names --------- + // 0 1 2 + "SELECT characters.guid, name, SUBSTRING(data, LENGTH(SUBSTRING_INDEX(data, ' ', '%u'))+2, LENGTH(SUBSTRING_INDEX(data, ' ', '%u')) - LENGTH(SUBSTRING_INDEX(data, ' ', '%u'))-1), " + // 3 4 5 6 7 + "genitive, dative, accusative, instrumental, prepositional " + "FROM characters LEFT JOIN character_declinedname ON characters.guid = character_declinedname.guid WHERE characters.guid = '%u'", + UNIT_FIELD_BYTES_0, UNIT_FIELD_BYTES_0+1, UNIT_FIELD_BYTES_0, GUID_LOPART(guid)); +} + +void WorldSession::SendNameQueryOpcodeFromDBCallBack(QueryResult *result, uint32 accountId) +{ + if(!result) + return; + + WorldSession * session = sWorld.FindSession(accountId); + if(!session) + { + delete result; + return; + } + + Field *fields = result->Fetch(); + uint32 guid = fields[0].GetUInt32(); + std::string name = fields[1].GetCppString(); + uint32 field = 0; + if(name == "") + name = session->GetMangosString(LANG_NON_EXIST_CHARACTER); + else + field = fields[2].GetUInt32(); + + // guess size + WorldPacket data( SMSG_NAME_QUERY_RESPONSE, (8+1+4+4+4+10) ); + data << MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER); + data << name; + data << (uint8)0; + data << (uint32)(field & 0xFF); + data << (uint32)((field >> 16) & 0xFF); + data << (uint32)((field >> 8) & 0xFF); + + // if the first declined name field (3) is empty, the rest must be too + if(sWorld.getConfig(CONFIG_DECLINED_NAMES_USED) && fields[3].GetCppString() != "") + { + data << (uint8)1; // is declined + for(int i = 3; i < MAX_DECLINED_NAME_CASES+3; ++i) + data << fields[i].GetCppString(); + } + else + data << (uint8)0; // is declined + + session->SendPacket( &data ); + delete result; +} + +void WorldSession::HandleNameQueryOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8); + + uint64 guid; + + recv_data >> guid; + + Player *pChar = objmgr.GetPlayer(guid); + + if (pChar) + SendNameQueryOpcode(pChar); + else + SendNameQueryOpcodeFromDB(guid); +} + +void WorldSession::HandleQueryTimeOpcode( WorldPacket & /*recv_data*/ ) +{ + WorldPacket data( SMSG_QUERY_TIME_RESPONSE, 4+4 ); + data << (uint32)time(NULL); + data << (uint32)0; + SendPacket( &data ); +} + +/// Only _static_ data send in this packet !!! +void WorldSession::HandleCreatureQueryOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,4+8); + + uint32 entry; + recv_data >> entry; + + CreatureInfo const *ci = objmgr.GetCreatureTemplate(entry); + if (ci) + { + + std::string Name, SubName; + Name = ci->Name; + SubName = ci->SubName; + + int loc_idx = GetSessionDbLocaleIndex(); + if (loc_idx >= 0) + { + CreatureLocale const *cl = objmgr.GetCreatureLocale(entry); + if (cl) + { + if (cl->Name.size() > loc_idx && !cl->Name[loc_idx].empty()) + Name = cl->Name[loc_idx]; + if (cl->SubName.size() > loc_idx && !cl->SubName[loc_idx].empty()) + SubName = cl->SubName[loc_idx]; + } + } + sLog.outDetail("WORLD: CMSG_CREATURE_QUERY '%s' - Entry: %u.", ci->Name, entry); + // guess size + WorldPacket data( SMSG_CREATURE_QUERY_RESPONSE, 100 ); + data << (uint32)entry; // creature entry + data << Name; + data << uint8(0) << uint8(0) << uint8(0); // name2, name3, name4, always empty + data << SubName; + data << ci->IconName; // "Directions" for guard, string for Icons 2.3.0 + data << (uint32)ci->flag1; // flags wdbFeild7=wad flags1 + data << (uint32)ci->type; + data << (uint32)ci->family; // family wdbFeild9 + data << (uint32)ci->rank; // rank wdbFeild10 + data << (uint32)0; // unknown wdbFeild11 + data << (uint32)ci->PetSpellDataId; // Id from CreatureSpellData.dbc wdbField12 + data << (uint32)ci->DisplayID_A; // modelid_male1 + data << (uint32)ci->DisplayID_H; // modelid_female1 ? + data << (uint32)ci->DisplayID_A2; // modelid_male2 ? + data << (uint32)ci->DisplayID_H2; // modelid_femmale2 ? + data << (float)1.0f; // unk + data << (float)1.0f; // unk + data << (uint8)ci->RacialLeader; + SendPacket( &data ); + sLog.outDebug( "WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE " ); + } + else + { + uint64 guid; + recv_data >> guid; + + sLog.outDebug( "WORLD: CMSG_CREATURE_QUERY - (%u) NO CREATURE INFO! (GUID: %u, ENTRY: %u)", uint32(GUID_LOPART(guid)), guid, entry ); + WorldPacket data( SMSG_CREATURE_QUERY_RESPONSE, 4 ); + data << uint32(entry | 0x80000000); + SendPacket( &data ); + sLog.outDebug( "WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE " ); + } +} + +/// Only _static_ data send in this packet !!! +void WorldSession::HandleGameObjectQueryOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,4+8); + + uint32 entryID; + recv_data >> entryID; + + const GameObjectInfo *info = objmgr.GetGameObjectInfo(entryID); + if(info) + { + + std::string Name; + std::string CastBarCaption; + + Name = info->name; + CastBarCaption = info->castBarCaption; + + int loc_idx = GetSessionDbLocaleIndex(); + if (loc_idx >= 0) + { + GameObjectLocale const *gl = objmgr.GetGameObjectLocale(entryID); + if (gl) + { + if (gl->Name.size() > loc_idx && !gl->Name[loc_idx].empty()) + Name = gl->Name[loc_idx]; + if (gl->CastBarCaption.size() > loc_idx && !gl->CastBarCaption[loc_idx].empty()) + CastBarCaption = gl->CastBarCaption[loc_idx]; + } + } + sLog.outDetail("WORLD: CMSG_GAMEOBJECT_QUERY '%s' - Entry: %u. ", info->name, entryID); + WorldPacket data ( SMSG_GAMEOBJECT_QUERY_RESPONSE, 150 ); + data << entryID; + data << (uint32)info->type; + data << (uint32)info->displayId; + data << Name; + data << uint8(0) << uint8(0) << uint8(0); // name2, name3, name4 + data << uint8(0); // 2.0.3, string + data << CastBarCaption; // 2.0.3, string. Text will appear in Cast Bar when using GO (ex: "Collecting") + data << uint8(0); // 2.0.3, probably string + data.append(info->raw.data,24); + SendPacket( &data ); + sLog.outDebug( "WORLD: Sent CMSG_GAMEOBJECT_QUERY " ); + } + else + { + + uint64 guid; + recv_data >> guid; + + sLog.outDebug( "WORLD: CMSG_GAMEOBJECT_QUERY - (%u) Missing gameobject info for (GUID: %u, ENTRY: %u)", uint32(GUID_LOPART(guid)), guid, entryID ); + WorldPacket data ( SMSG_GAMEOBJECT_QUERY_RESPONSE, 4 ); + data << uint32(entryID | 0x80000000); + SendPacket( &data ); + sLog.outDebug( "WORLD: Sent CMSG_GAMEOBJECT_QUERY " ); + } +} + +void WorldSession::HandleCorpseQueryOpcode(WorldPacket & /*recv_data*/) +{ + sLog.outDetail("WORLD: Received MSG_CORPSE_QUERY"); + + Corpse *corpse = GetPlayer()->GetCorpse(); + + uint8 found = 1; + if(!corpse) + found = 0; + + WorldPacket data(MSG_CORPSE_QUERY, (1+found*(5*4))); + data << uint8(found); + if(found) + { + data << corpse->GetMapId(); + data << corpse->GetPositionX(); + data << corpse->GetPositionY(); + data << corpse->GetPositionZ(); + data << _player->GetMapId(); + } + SendPacket(&data); +} + +void WorldSession::HandleNpcTextQueryOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,4+8); + + uint32 textID; + uint64 guid; + GossipText *pGossip; + std::string GossipStr; + + recv_data >> textID; + sLog.outDetail("WORLD: CMSG_NPC_TEXT_QUERY ID '%u'", textID); + + recv_data >> guid; + GetPlayer()->SetUInt64Value(UNIT_FIELD_TARGET, guid); + + pGossip = objmgr.GetGossipText(textID); + + WorldPacket data( SMSG_NPC_TEXT_UPDATE, 100 ); // guess size + data << textID; + + if (!pGossip) + { + for(uint32 i = 0; i < 8; ++i) + { + data << float(0); + data << "Greetings $N"; + data << "Greetings $N"; + data << uint32(0); + data << uint32(0); + data << uint32(0); + data << uint32(0); + data << uint32(0); + data << uint32(0); + data << uint32(0); + } + } + else + { + std::string Text_0[8], Text_1[8]; + for (int i=0;i<8;i++) + { + Text_0[i]=pGossip->Options[i].Text_0; + Text_1[i]=pGossip->Options[i].Text_1; + } + + int loc_idx = GetSessionDbLocaleIndex(); + if (loc_idx >= 0) + { + NpcTextLocale const *nl = objmgr.GetNpcTextLocale(textID); + if (nl) + { + for (int i=0;i<8;i++) + { + if (nl->Text_0[i].size() > loc_idx && !nl->Text_0[i][loc_idx].empty()) + Text_0[i]=nl->Text_0[i][loc_idx]; + if (nl->Text_1[i].size() > loc_idx && !nl->Text_1[i][loc_idx].empty()) + Text_1[i]=nl->Text_1[i][loc_idx]; + } + } + } + + for (int i=0; i<8; i++) + { + data << pGossip->Options[i].Probability; + + if ( Text_0[i].empty() ) + data << Text_1[i]; + else + data << Text_0[i]; + + if ( Text_1[i].empty() ) + data << Text_0[i]; + else + data << Text_1[i]; + + data << pGossip->Options[i].Language; + + data << pGossip->Options[i].Emotes[0]._Delay; + data << pGossip->Options[i].Emotes[0]._Emote; + + data << pGossip->Options[i].Emotes[1]._Delay; + data << pGossip->Options[i].Emotes[1]._Emote; + + data << pGossip->Options[i].Emotes[2]._Delay; + data << pGossip->Options[i].Emotes[2]._Emote; + } + } + + SendPacket( &data ); + + sLog.outDebug( "WORLD: Sent SMSG_NPC_TEXT_UPDATE " ); +} + +void WorldSession::HandlePageQueryOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,4); + + uint32 pageID; + + recv_data >> pageID; + sLog.outDetail("WORLD: Received CMSG_PAGE_TEXT_QUERY for pageID '%u'", pageID); + + while (pageID) + { + PageText const *pPage = sPageTextStore.LookupEntry( pageID ); + // guess size + WorldPacket data( SMSG_PAGE_TEXT_QUERY_RESPONSE, 50 ); + data << pageID; + + if (!pPage) + { + data << "Item page missing."; + data << uint32(0); + pageID = 0; + } + else + { + std::string Text = pPage->Text; + + int loc_idx = GetSessionDbLocaleIndex(); + if (loc_idx >= 0) + { + PageTextLocale const *pl = objmgr.GetPageTextLocale(pageID); + if (pl) + { + if (pl->Text.size() > loc_idx && !pl->Text[loc_idx].empty()) + Text = pl->Text[loc_idx]; + } + } + + data << Text; + data << uint32(pPage->Next_Page); + pageID = pPage->Next_Page; + } + SendPacket( &data ); + + sLog.outDebug( "WORLD: Sent SMSG_PAGE_TEXT_QUERY_RESPONSE " ); + } +} diff --git a/src/game/QuestDef.cpp b/src/game/QuestDef.cpp new file mode 100644 index 00000000000..c92bb9b7b6a --- /dev/null +++ b/src/game/QuestDef.cpp @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "QuestDef.h" +#include "Player.h" +#include "World.h" + +Quest::Quest(Field * questRecord) +{ + QuestId = questRecord[0].GetUInt32(); + ZoneOrSort = questRecord[1].GetInt32(); + SkillOrClass = questRecord[2].GetInt32(); + MinLevel = questRecord[3].GetUInt32(); + QuestLevel = questRecord[4].GetUInt32(); + Type = questRecord[5].GetUInt32(); + RequiredRaces = questRecord[6].GetUInt32(); + RequiredSkillValue = questRecord[7].GetUInt32(); + RepObjectiveFaction = questRecord[8].GetUInt32(); + RepObjectiveValue = questRecord[9].GetInt32(); + RequiredMinRepFaction = questRecord[10].GetUInt32(); + RequiredMinRepValue = questRecord[11].GetInt32(); + RequiredMaxRepFaction = questRecord[12].GetUInt32(); + RequiredMaxRepValue = questRecord[13].GetInt32(); + SuggestedPlayers = questRecord[14].GetUInt32(); + LimitTime = questRecord[15].GetUInt32(); + QuestFlags = questRecord[16].GetUInt16(); + uint32 SpecialFlags = questRecord[17].GetUInt16(); + CharTitleId = questRecord[18].GetUInt32(); + PrevQuestId = questRecord[19].GetInt32(); + NextQuestId = questRecord[20].GetInt32(); + ExclusiveGroup = questRecord[21].GetInt32(); + NextQuestInChain = questRecord[22].GetUInt32(); + SrcItemId = questRecord[23].GetUInt32(); + SrcItemCount = questRecord[24].GetUInt32(); + SrcSpell = questRecord[25].GetUInt32(); + Title = questRecord[26].GetCppString(); + Details = questRecord[27].GetCppString(); + Objectives = questRecord[28].GetCppString(); + OfferRewardText = questRecord[29].GetCppString(); + RequestItemsText = questRecord[30].GetCppString(); + EndText = questRecord[31].GetCppString(); + + for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) + ObjectiveText[i] = questRecord[32+i].GetCppString(); + + for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) + ReqItemId[i] = questRecord[36+i].GetUInt32(); + + for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) + ReqItemCount[i] = questRecord[40+i].GetUInt32(); + + for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i) + ReqSourceId[i] = questRecord[44+i].GetUInt32(); + + for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i) + ReqSourceCount[i] = questRecord[48+i].GetUInt32(); + + for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i) + ReqSourceRef[i] = questRecord[52+i].GetUInt32(); + + for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) + ReqCreatureOrGOId[i] = questRecord[56+i].GetInt32(); + + for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) + ReqCreatureOrGOCount[i] = questRecord[60+i].GetUInt32(); + + for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) + ReqSpell[i] = questRecord[64+i].GetUInt32(); + + for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i) + RewChoiceItemId[i] = questRecord[68+i].GetUInt32(); + + for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i) + RewChoiceItemCount[i] = questRecord[74+i].GetUInt32(); + + for (int i = 0; i < QUEST_REWARDS_COUNT; ++i) + RewItemId[i] = questRecord[80+i].GetUInt32(); + + for (int i = 0; i < QUEST_REWARDS_COUNT; ++i) + RewItemCount[i] = questRecord[84+i].GetUInt32(); + + for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) + RewRepFaction[i] = questRecord[88+i].GetUInt32(); + + for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) + RewRepValue[i] = questRecord[93+i].GetInt32(); + + RewOrReqMoney = questRecord[98].GetInt32(); + RewMoneyMaxLevel = questRecord[99].GetUInt32(); + RewSpell = questRecord[100].GetUInt32(); + RewSpellCast = questRecord[101].GetUInt32(); + RewMailTemplateId = questRecord[102].GetUInt32(); + RewMailDelaySecs = questRecord[103].GetUInt32(); + PointMapId = questRecord[104].GetUInt32(); + PointX = questRecord[105].GetFloat(); + PointY = questRecord[106].GetFloat(); + PointOpt = questRecord[107].GetUInt32(); + + for (int i = 0; i < QUEST_EMOTE_COUNT; ++i) + DetailsEmote[i] = questRecord[108+i].GetUInt32(); + + IncompleteEmote = questRecord[112].GetUInt32(); + CompleteEmote = questRecord[113].GetUInt32(); + + for (int i = 0; i < QUEST_EMOTE_COUNT; ++i) + OfferRewardEmote[i] = questRecord[114+i].GetInt32(); + + QuestStartScript = questRecord[118].GetUInt32(); + QuestCompleteScript = questRecord[119].GetUInt32(); + + QuestFlags |= SpecialFlags << 16; + + m_reqitemscount = 0; + m_reqCreatureOrGOcount = 0; + m_rewitemscount = 0; + m_rewchoiceitemscount = 0; + + for (int i=0; i < QUEST_OBJECTIVES_COUNT; i++) + { + if ( ReqItemId[i] ) + ++m_reqitemscount; + if ( ReqCreatureOrGOId[i] ) + ++m_reqCreatureOrGOcount; + } + + for (int i=0; i < QUEST_REWARDS_COUNT; i++) + { + if ( RewItemId[i] ) + ++m_rewitemscount; + } + + for (int i=0; i < QUEST_REWARD_CHOICES_COUNT; i++) + { + if (RewChoiceItemId[i]) + ++m_rewchoiceitemscount; + } +} + +uint32 Quest::XPValue( Player *pPlayer ) const +{ + if( pPlayer ) + { + if( RewMoneyMaxLevel > 0 ) + { + uint32 pLevel = pPlayer->getLevel(); + uint32 qLevel = QuestLevel; + float fullxp = 0; + if (qLevel >= 65) + fullxp = RewMoneyMaxLevel / 6.0f; + else if (qLevel == 64) + fullxp = RewMoneyMaxLevel / 4.8f; + else if (qLevel == 63) + fullxp = RewMoneyMaxLevel / 3.6f; + else if (qLevel == 62) + fullxp = RewMoneyMaxLevel / 2.4f; + else if (qLevel == 61) + fullxp = RewMoneyMaxLevel / 1.2f; + else if (qLevel > 0 && qLevel <= 60) + fullxp = RewMoneyMaxLevel / 0.6f; + + if( pLevel <= qLevel + 5 ) + return (uint32)fullxp; + else if( pLevel == qLevel + 6 ) + return (uint32)(fullxp * 0.8f); + else if( pLevel == qLevel + 7 ) + return (uint32)(fullxp * 0.6f); + else if( pLevel == qLevel + 8 ) + return (uint32)(fullxp * 0.4f); + else if( pLevel == qLevel + 9 ) + return (uint32)(fullxp * 0.2f); + else + return (uint32)(fullxp * 0.1f); + } + } + return 0; +} + +int32 Quest::GetRewOrReqMoney() const +{ + if(RewOrReqMoney <=0) + return RewOrReqMoney; + + return int32(RewOrReqMoney * sWorld.getRate(RATE_DROP_MONEY)); +} diff --git a/src/game/QuestDef.h b/src/game/QuestDef.h new file mode 100644 index 00000000000..ddd24bf57f0 --- /dev/null +++ b/src/game/QuestDef.h @@ -0,0 +1,330 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOSSERVER_QUEST_H +#define MANGOSSERVER_QUEST_H + +#include "Platform/Define.h" +#include "Database/DatabaseEnv.h" + +#include +#include + +class Player; + +class ObjectMgr; + +#define MAX_QUEST_LOG_SIZE 25 + +#define QUEST_OBJECTIVES_COUNT 4 +#define QUEST_SOURCE_ITEM_IDS_COUNT 4 +#define QUEST_REWARD_CHOICES_COUNT 6 +#define QUEST_REWARDS_COUNT 4 +#define QUEST_DEPLINK_COUNT 10 +#define QUEST_REPUTATIONS_COUNT 5 +#define QUEST_EMOTE_COUNT 4 + +enum QuestFailedReasons +{ + INVALIDREASON_DONT_HAVE_REQ = 0, + INVALIDREASON_QUEST_FAILED_LOW_LEVEL = 1, //You are not high enough level for that quest. + INVALIDREASON_QUEST_FAILED_WRONG_RACE = 6, //That quest is not available to your race. + INVALIDREASON_QUEST_ALREADY_DONE = 7, //You have completed that quest. + INVALIDREASON_QUEST_ONLY_ONE_TIMED = 12, //You can only be on one timed quest at a time. + INVALIDREASON_QUEST_ALREADY_ON = 13, //You are already on that quest + INVALIDREASON_QUEST_FAILED_EXPANSION = 16, //This quest requires an expansion enabled account. + INVALIDREASON_QUEST_ALREADY_ON2 = 18, //You are already on that quest + INVALIDREASON_QUEST_FAILED_MISSING_ITEMS = 21, //You don't have the required items with you. Check storage. + INVALIDREASON_QUEST_FAILED_NOT_ENOUGH_MONEY = 23, //You don't have enough money for that quest. + INVALIDREASON_DAILY_QUESTS_REMAINING = 26, //You have already completed 10 daily quests today + INVALIDREASON_QUEST_FAILED_CAIS = 27, //You cannot complete quests once you have reached tired time +}; + +enum QuestShareMessages +{ + QUEST_PARTY_MSG_SHARING_QUEST = 0, + QUEST_PARTY_MSG_CANT_TAKE_QUEST = 1, + QUEST_PARTY_MSG_ACCEPT_QUEST = 2, + QUEST_PARTY_MSG_REFUSE_QUEST = 3, + QUEST_PARTY_MSG_TOO_FAR = 4, + QUEST_PARTY_MSG_BUSY = 5, + QUEST_PARTY_MSG_LOG_FULL = 6, + QUEST_PARTY_MSG_HAVE_QUEST = 7, + QUEST_PARTY_MSG_FINISH_QUEST = 8, +}; + +enum __QuestTradeSkill +{ + QUEST_TRSKILL_NONE = 0, + QUEST_TRSKILL_ALCHEMY = 1, + QUEST_TRSKILL_BLACKSMITHING = 2, + QUEST_TRSKILL_COOKING = 3, + QUEST_TRSKILL_ENCHANTING = 4, + QUEST_TRSKILL_ENGINEERING = 5, + QUEST_TRSKILL_FIRSTAID = 6, + QUEST_TRSKILL_HERBALISM = 7, + QUEST_TRSKILL_LEATHERWORKING = 8, + QUEST_TRSKILL_POISONS = 9, + QUEST_TRSKILL_TAILORING = 10, + QUEST_TRSKILL_MINING = 11, + QUEST_TRSKILL_FISHING = 12, + QUEST_TRSKILL_SKINNING = 13, + QUEST_TRSKILL_JEWELCRAFTING = 14, +}; + +enum QuestStatus +{ + QUEST_STATUS_NONE = 0, + QUEST_STATUS_COMPLETE = 1, + QUEST_STATUS_UNAVAILABLE = 2, + QUEST_STATUS_INCOMPLETE = 3, + QUEST_STATUS_AVAILABLE = 4, + MAX_QUEST_STATUS +}; + +enum __QuestGiverStatus +{ + DIALOG_STATUS_NONE = 0, + DIALOG_STATUS_UNAVAILABLE = 1, + DIALOG_STATUS_CHAT = 2, + DIALOG_STATUS_INCOMPLETE = 3, + DIALOG_STATUS_REWARD_REP = 4, + DIALOG_STATUS_AVAILABLE_REP = 5, + DIALOG_STATUS_AVAILABLE = 6, + DIALOG_STATUS_REWARD2 = 7, // not yellow dot on minimap + DIALOG_STATUS_REWARD = 8 // yellow dot on minimap +}; + +enum __QuestFlags +{ + // Flags used at server and sended to client + QUEST_FLAGS_STAY_ALIVE = 1, // Not used currently + QUEST_FLAGS_EVENT = 2, // Not used currently + QUEST_FLAGS_EXPLORATION = 4, // Not used currently + QUEST_FLAGS_SHARABLE = 8, // Can be shared: Player::CanShareQuest() + //QUEST_FLAGS_NONE2 = 16, // Not used currently + QUEST_FLAGS_EPIC = 32, // Not used currently: Unsure of content + QUEST_FLAGS_RAID = 64, // Not used currently + QUEST_FLAGS_TBC = 128, // Not used currently: Available if TBC expension enabled only + QUEST_FLAGS_UNK2 = 256, // Not used currently: _DELIVER_MORE Quest needs more than normal _q-item_ drops from mobs + QUEST_FLAGS_HIDDEN_REWARDS = 512, // Items and money rewarded only sent in SMSG_QUESTGIVER_OFFER_REWARD (not in SMSG_QUESTGIVER_QUEST_DETAILS or in client quest log(SMSG_QUEST_QUERY_RESPONSE)) + QUEST_FLAGS_AUTO_REWARDED = 1024, // These quests are automatically rewarded on quest complete and they will never appear in quest log client side. + QUEST_FLAGS_TBC_RACES = 2048, // Not used currently: Bloodelf/draenei starting zone quests + QUEST_FLAGS_DAILY = 4096, // Used to know quest is Daily one + + // Mangos flags for set SpecialFlags in DB if required but used only at server + QUEST_MANGOS_FLAGS_REPEATABLE = 0x010000, // Set by 1 in SpecialFlags from DB + QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT = 0x020000, // Set by 2 in SpecialFlags from DB (if reequired area explore, spell SPELL_EFFECT_QUEST_COMPLETE casting, table `*_script` command SCRIPT_COMMAND_QUEST_EXPLORED use, set from script DLL) + QUEST_MANGOS_FLAGS_DB_ALLOWED = 0xFFFF | QUEST_MANGOS_FLAGS_REPEATABLE | QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT, + + // Mangos flags for internal use only + QUEST_MANGOS_FLAGS_DELIVER = 0x040000, // Internal flag computed only + QUEST_MANGOS_FLAGS_SPEAKTO = 0x080000, // Internal flag computed only + QUEST_MANGOS_FLAGS_KILL_OR_CAST = 0x100000, // Internal flag computed only + QUEST_MANGOS_FLAGS_TIMED = 0x200000, // Internal flag computed only +}; + +struct QuestLocale +{ + QuestLocale() { ObjectiveText.resize(QUEST_OBJECTIVES_COUNT); } + + std::vector Title; + std::vector Details; + std::vector Objectives; + std::vector OfferRewardText; + std::vector RequestItemsText; + std::vector EndText; + std::vector< std::vector > ObjectiveText; +}; + +// This Quest class provides a convenient way to access a few pretotaled (cached) quest details, +// all base quest information, and any utility functions such as generating the amount of +// xp to give +class Quest +{ + friend class ObjectMgr; + public: + Quest(Field * questRecord); + uint32 XPValue( Player *pPlayer ) const; + + bool HasFlag( uint32 flag ) const { return ( QuestFlags & flag ) != 0; } + void SetFlag( uint32 flag ) { QuestFlags |= flag; } + + // table data accessors: + uint32 GetQuestId() const { return QuestId; } + int32 GetZoneOrSort() const { return ZoneOrSort; } + int32 GetSkillOrClass() const { return SkillOrClass; } + uint32 GetMinLevel() const { return MinLevel; } + uint32 GetQuestLevel() const { return QuestLevel; } + uint32 GetType() const { return Type; } + uint32 GetRequiredRaces() const { return RequiredRaces; } + uint32 GetRequiredSkillValue() const { return RequiredSkillValue; } + uint32 GetRepObjectiveFaction() const { return RepObjectiveFaction; } + int32 GetRepObjectiveValue() const { return RepObjectiveValue; } + uint32 GetRequiredMinRepFaction() const { return RequiredMinRepFaction; } + int32 GetRequiredMinRepValue() const { return RequiredMinRepValue; } + uint32 GetRequiredMaxRepFaction() const { return RequiredMaxRepFaction; } + int32 GetRequiredMaxRepValue() const { return RequiredMaxRepValue; } + uint32 GetSuggestedPlayers() const { return SuggestedPlayers; } + uint32 GetLimitTime() const { return LimitTime; } + int32 GetPrevQuestId() const { return PrevQuestId; } + int32 GetNextQuestId() const { return NextQuestId; } + int32 GetExclusiveGroup() const { return ExclusiveGroup; } + uint32 GetNextQuestInChain() const { return NextQuestInChain; } + uint32 GetCharTitleId() const { return CharTitleId; } + uint32 GetSrcItemId() const { return SrcItemId; } + uint32 GetSrcItemCount() const { return SrcItemCount; } + uint32 GetSrcSpell() const { return SrcSpell; } + std::string GetTitle() const { return Title; } + std::string GetDetails() const { return Details; } + std::string GetObjectives() const { return Objectives; } + std::string GetOfferRewardText() const { return OfferRewardText; } + std::string GetRequestItemsText() const { return RequestItemsText; } + std::string GetEndText() const { return EndText; } + int32 GetRewOrReqMoney() const; + uint32 GetRewMoneyMaxLevel() const { return RewMoneyMaxLevel; } + // use in XP calculation at client + uint32 GetRewSpell() const { return RewSpell; } + uint32 GetRewSpellCast() const { return RewSpellCast; } + uint32 GetRewMailTemplateId() const { return RewMailTemplateId; } + uint32 GetRewMailDelaySecs() const { return RewMailDelaySecs; } + uint32 GetPointMapId() const { return PointMapId; } + float GetPointX() const { return PointX; } + float GetPointY() const { return PointY; } + uint32 GetPointOpt() const { return PointOpt; } + uint32 GetIncompleteEmote() const { return IncompleteEmote; } + uint32 GetCompleteEmote() const { return CompleteEmote; } + uint32 GetQuestStartScript() const { return QuestStartScript; } + uint32 GetQuestCompleteScript() const { return QuestCompleteScript; } + bool IsRepeatable() const { return QuestFlags & QUEST_MANGOS_FLAGS_REPEATABLE; } + bool IsAutoComplete() const { return Objectives.empty(); } + uint32 GetFlags() const { return QuestFlags; } + bool IsDaily() const { return QuestFlags & QUEST_FLAGS_DAILY; } + + // multiple values + std::string ObjectiveText[QUEST_OBJECTIVES_COUNT]; + uint32 ReqItemId[QUEST_OBJECTIVES_COUNT]; + uint32 ReqItemCount[QUEST_OBJECTIVES_COUNT]; + uint32 ReqSourceId[QUEST_SOURCE_ITEM_IDS_COUNT]; + uint32 ReqSourceCount[QUEST_SOURCE_ITEM_IDS_COUNT]; + uint32 ReqSourceRef[QUEST_SOURCE_ITEM_IDS_COUNT]; + int32 ReqCreatureOrGOId[QUEST_OBJECTIVES_COUNT]; // >0 Creature <0 Gameobject + uint32 ReqCreatureOrGOCount[QUEST_OBJECTIVES_COUNT]; + uint32 ReqSpell[QUEST_OBJECTIVES_COUNT]; + uint32 RewChoiceItemId[QUEST_REWARD_CHOICES_COUNT]; + uint32 RewChoiceItemCount[QUEST_REWARD_CHOICES_COUNT]; + uint32 RewItemId[QUEST_REWARDS_COUNT]; + uint32 RewItemCount[QUEST_REWARDS_COUNT]; + uint32 RewRepFaction[QUEST_REPUTATIONS_COUNT]; + int32 RewRepValue[QUEST_REPUTATIONS_COUNT]; + uint32 DetailsEmote[QUEST_EMOTE_COUNT]; + uint32 OfferRewardEmote[QUEST_EMOTE_COUNT]; + + uint32 GetReqItemsCount() const { return m_reqitemscount; } + uint32 GetReqCreatureOrGOcount() const { return m_reqCreatureOrGOcount; } + uint32 GetRewChoiceItemsCount() const { return m_rewchoiceitemscount; } + uint32 GetRewItemsCount() const { return m_rewitemscount; } + + typedef std::vector PrevQuests; + PrevQuests prevQuests; + typedef std::vector PrevChainQuests; + PrevChainQuests prevChainQuests; + + // cached data + private: + uint32 m_reqitemscount; + uint32 m_reqCreatureOrGOcount; + uint32 m_rewchoiceitemscount; + uint32 m_rewitemscount; + + // table data + protected: + uint32 QuestId; + int32 ZoneOrSort; + int32 SkillOrClass; + uint32 MinLevel; + uint32 QuestLevel; + uint32 Type; + uint32 RequiredRaces; + uint32 RequiredSkillValue; + uint32 RepObjectiveFaction; + int32 RepObjectiveValue; + uint32 RequiredMinRepFaction; + int32 RequiredMinRepValue; + uint32 RequiredMaxRepFaction; + int32 RequiredMaxRepValue; + uint32 SuggestedPlayers; + uint32 LimitTime; + uint32 QuestFlags; + uint32 CharTitleId; + int32 PrevQuestId; + int32 NextQuestId; + int32 ExclusiveGroup; + uint32 NextQuestInChain; + uint32 SrcItemId; + uint32 SrcItemCount; + uint32 SrcSpell; + std::string Title; + std::string Details; + std::string Objectives; + std::string OfferRewardText; + std::string RequestItemsText; + std::string EndText; + int32 RewOrReqMoney; + uint32 RewMoneyMaxLevel; + uint32 RewSpell; + uint32 RewSpellCast; + uint32 RewMailTemplateId; + uint32 RewMailDelaySecs; + uint32 PointMapId; + float PointX; + float PointY; + uint32 PointOpt; + uint32 IncompleteEmote; + uint32 CompleteEmote; + uint32 QuestStartScript; + uint32 QuestCompleteScript; +}; + +enum QuestUpdateState +{ + QUEST_UNCHANGED = 0, + QUEST_CHANGED = 1, + QUEST_NEW = 2 +}; + +struct QuestStatusData +{ + QuestStatusData() + : m_status(QUEST_STATUS_NONE),m_rewarded(false), + m_explored(false), m_timer(0), uState(QUEST_NEW) + { + memset(m_itemcount, 0, QUEST_OBJECTIVES_COUNT * sizeof(uint32)); + memset(m_creatureOrGOcount, 0, QUEST_OBJECTIVES_COUNT * sizeof(uint32)); + } + + QuestStatus m_status; + bool m_rewarded; + bool m_explored; + uint32 m_timer; + QuestUpdateState uState; + + uint32 m_itemcount[ QUEST_OBJECTIVES_COUNT ]; + uint32 m_creatureOrGOcount[ QUEST_OBJECTIVES_COUNT ]; +}; +#endif diff --git a/src/game/QuestHandler.cpp b/src/game/QuestHandler.cpp new file mode 100644 index 00000000000..56ff45d7ef1 --- /dev/null +++ b/src/game/QuestHandler.cpp @@ -0,0 +1,651 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Log.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Opcodes.h" +#include "World.h" +#include "ObjectMgr.h" +#include "Player.h" +#include "GossipDef.h" +#include "QuestDef.h" +#include "ObjectAccessor.h" +#include "ScriptCalls.h" +#include "Group.h" + +void WorldSession::HandleQuestgiverStatusQueryOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8); + + uint64 guid; + recv_data >> guid; + uint8 questStatus = DIALOG_STATUS_NONE; + uint8 defstatus = DIALOG_STATUS_NONE; + + Object* questgiver = ObjectAccessor::GetObjectByTypeMask(*_player, guid,TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT); + if(!questgiver) + { + sLog.outDetail("Error in CMSG_QUESTGIVER_STATUS_QUERY, called for not found questgiver (Typeid: %u GUID: %u)",GuidHigh2TypeId(GUID_HIPART(guid)),GUID_LOPART(guid)); + return; + } + + switch(questgiver->GetTypeId()) + { + case TYPEID_UNIT: + { + sLog.outDebug( "WORLD: Received CMSG_QUESTGIVER_STATUS_QUERY for npc, guid = %u",uint32(GUID_LOPART(guid)) ); + Creature* cr_questgiver=(Creature*)questgiver; + if( !cr_questgiver->IsHostileTo(_player)) // not show quest status to enemies + { + questStatus = Script->NPCDialogStatus(_player, cr_questgiver); + if( questStatus > 6 ) + questStatus = getDialogStatus(_player, cr_questgiver, defstatus); + } + break; + } + case TYPEID_GAMEOBJECT: + { + sLog.outDebug( "WORLD: Received CMSG_QUESTGIVER_STATUS_QUERY for GameObject guid = %u",uint32(GUID_LOPART(guid)) ); + GameObject* go_questgiver=(GameObject*)questgiver; + questStatus = Script->GODialogStatus(_player, go_questgiver); + if( questStatus > 6 ) + questStatus = getDialogStatus(_player, go_questgiver, defstatus); + break; + } + default: + sLog.outError("QuestGiver called for unexpected type %u", questgiver->GetTypeId()); + break; + } + + //inform client about status of quest + _player->PlayerTalkClass->SendQuestGiverStatus(questStatus, guid); +} + +void WorldSession::HandleQuestgiverHelloOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8); + + uint64 guid; + recv_data >> guid; + + sLog.outDebug( "WORLD: Received CMSG_QUESTGIVER_HELLO npc = %u",guid ); + + Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_NONE); + if (!pCreature) + { + sLog.outDebug( "WORLD: HandleQuestgiverHelloOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); + return; + } + + // remove fake death + if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + // Stop the npc if moving + pCreature->StopMoving(); + + if(Script->GossipHello( _player, pCreature ) ) + return; + + pCreature->prepareGossipMenu(_player,0); + pCreature->sendPreparedGossip( _player ); +} + +void WorldSession::HandleQuestgiverAcceptQuestOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+4); + + uint64 guid; + uint32 quest; + recv_data >> guid >> quest; + + if(!GetPlayer()->isAlive()) + return; + + sLog.outDebug( "WORLD: Received CMSG_QUESTGIVER_ACCEPT_QUEST npc = %u, quest = %u",uint32(GUID_LOPART(guid)),quest ); + + Object* pObject = ObjectAccessor::GetObjectByTypeMask(*_player, guid,TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT|TYPEMASK_ITEM|TYPEMASK_PLAYER); + + // no or incorrect quest giver + if(!pObject + || (pObject->GetTypeId()!=TYPEID_PLAYER && !pObject->hasQuest(quest)) + || (pObject->GetTypeId()==TYPEID_PLAYER && !((Player*)pObject)->CanShareQuest(quest)) + ) + { + _player->PlayerTalkClass->CloseGossip(); + _player->SetDivider( 0 ); + return; + } + + Quest const* qInfo = objmgr.GetQuestTemplate(quest); + if ( qInfo ) + { + // prevent cheating + if(!GetPlayer()->CanTakeQuest(qInfo,true) ) + { + _player->PlayerTalkClass->CloseGossip(); + _player->SetDivider( 0 ); + return; + } + + if( _player->GetDivider() != 0 ) + { + Player *pPlayer = ObjectAccessor::FindPlayer( _player->GetDivider() ); + if( pPlayer ) + { + pPlayer->SendPushToPartyResponse( _player, QUEST_PARTY_MSG_ACCEPT_QUEST ); + _player->SetDivider( 0 ); + } + } + + if( _player->CanAddQuest( qInfo, true ) ) + { + _player->AddQuest( qInfo, pObject ); + + if ( _player->CanCompleteQuest( quest ) ) + _player->CompleteQuest( quest ); + + switch(pObject->GetTypeId()) + { + case TYPEID_UNIT: + Script->QuestAccept(_player, ((Creature*)pObject), qInfo ); + break; + case TYPEID_ITEM: + case TYPEID_CONTAINER: + { + Script->ItemQuestAccept(_player, ((Item*)pObject), qInfo ); + + // destroy not required for quest finish quest starting item + bool destroyItem = true; + for(int i = 0; i < QUEST_OBJECTIVES_COUNT; i++) + { + if ((qInfo->ReqItemId[i] == ((Item*)pObject)->GetEntry()) && (((Item*)pObject)->GetProto()->MaxCount != 0)) + { + destroyItem = false; + break; + } + } + + if(destroyItem) + _player->DestroyItem(((Item*)pObject)->GetBagSlot(),((Item*)pObject)->GetSlot(),true); + + break; + } + case TYPEID_GAMEOBJECT: + Script->GOQuestAccept(_player, ((GameObject*)pObject), qInfo ); + break; + } + _player->PlayerTalkClass->CloseGossip(); + + if( qInfo->GetSrcSpell() > 0 ) + _player->CastSpell( _player, qInfo->GetSrcSpell(), true); + + return; + } + } + + _player->PlayerTalkClass->CloseGossip(); +} + +void WorldSession::HandleQuestgiverQuestQueryOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+4); + + uint64 guid; + uint32 quest; + recv_data >> guid >> quest; + sLog.outDebug( "WORLD: Received CMSG_QUESTGIVER_QUERY_QUEST npc = %u, quest = %u",uint32(GUID_LOPART(guid)),quest ); + + // Verify that the guid is valid and is a questgiver or involved in the requested quest + Object* pObject = ObjectAccessor::GetObjectByTypeMask(*_player, guid,TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT|TYPEMASK_ITEM); + if(!pObject||!pObject->hasQuest(quest) && !pObject->hasInvolvedQuest(quest)) + { + _player->PlayerTalkClass->CloseGossip(); + return; + } + + Quest const* pQuest = objmgr.GetQuestTemplate(quest); + if ( pQuest ) + { + _player->PlayerTalkClass->SendQuestGiverQuestDetails(pQuest, pObject->GetGUID(), true); + } +} + +void WorldSession::HandleQuestQueryOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,4); + + uint32 quest; + recv_data >> quest; + sLog.outDebug( "WORLD: Received CMSG_QUEST_QUERY quest = %u",quest ); + + Quest const *pQuest = objmgr.GetQuestTemplate(quest); + if ( pQuest ) + { + _player->PlayerTalkClass->SendQuestQueryResponse( pQuest ); + } +} + +void WorldSession::HandleQuestgiverChooseRewardOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+4+4); + + uint32 quest, reward; + uint64 guid; + recv_data >> guid >> quest >> reward; + + if(reward >= QUEST_REWARD_CHOICES_COUNT) + { + sLog.outError("Error in CMSG_QUESTGIVER_CHOOSE_REWARD: player %s (guid %d) tried to get invalid reward (%u) (probably packet hacking)", _player->GetName(), _player->GetGUIDLow(), reward); + return; + } + + if(!GetPlayer()->isAlive()) + return; + + sLog.outDebug( "WORLD: Received CMSG_QUESTGIVER_CHOOSE_REWARD npc = %u, quest = %u, reward = %u",uint32(GUID_LOPART(guid)),quest,reward ); + + Object* pObject = ObjectAccessor::GetObjectByTypeMask(*_player, guid,TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT); + if(!pObject) + return; + + if(!pObject->hasInvolvedQuest(quest)) + return; + + Quest const *pQuest = objmgr.GetQuestTemplate(quest); + if( pQuest ) + { + if( _player->CanRewardQuest( pQuest, reward, true ) ) + { + _player->RewardQuest( pQuest, reward, pObject ); + + switch(pObject->GetTypeId()) + { + case TYPEID_UNIT: + if( !(Script->ChooseReward( _player, ((Creature*)pObject), pQuest, reward )) ) + { + // Send next quest + if(Quest const* nextquest = _player->GetNextQuest( guid ,pQuest ) ) + _player->PlayerTalkClass->SendQuestGiverQuestDetails(nextquest,guid,true); + } + break; + case TYPEID_GAMEOBJECT: + if( !Script->GOChooseReward( _player, ((GameObject*)pObject), pQuest, reward ) ) + { + // Send next quest + if(Quest const* nextquest = _player->GetNextQuest( guid ,pQuest ) ) + _player->PlayerTalkClass->SendQuestGiverQuestDetails(nextquest,guid,true); + } + break; + } + } + else + _player->PlayerTalkClass->SendQuestGiverOfferReward( pQuest, guid, true ); + } +} + +void WorldSession::HandleQuestgiverRequestRewardOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+4); + + uint32 quest; + uint64 guid; + recv_data >> guid >> quest; + + if(!GetPlayer()->isAlive()) + return; + + sLog.outDebug( "WORLD: Received CMSG_QUESTGIVER_REQUEST_REWARD npc = %u, quest = %u",uint32(GUID_LOPART(guid)),quest ); + + Object* pObject = ObjectAccessor::GetObjectByTypeMask(*_player, guid,TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT); + if(!pObject||!pObject->hasInvolvedQuest(quest)) + return; + + if ( _player->CanCompleteQuest( quest ) ) + _player->CompleteQuest( quest ); + + if( _player->GetQuestStatus( quest ) != QUEST_STATUS_COMPLETE ) + return; + + if(Quest const *pQuest = objmgr.GetQuestTemplate(quest)) + _player->PlayerTalkClass->SendQuestGiverOfferReward( pQuest, guid, true ); +} + +void WorldSession::HandleQuestgiverCancel(WorldPacket& /*recv_data*/ ) +{ + sLog.outDebug( "WORLD: Received CMSG_QUESTGIVER_CANCEL" ); + + _player->PlayerTalkClass->CloseGossip(); +} + +void WorldSession::HandleQuestLogSwapQuest(WorldPacket& recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,1+1); + + uint8 slot1, slot2; + recv_data >> slot1 >> slot2; + + if(slot1 == slot2 || slot1 >= MAX_QUEST_LOG_SIZE || slot2 >= MAX_QUEST_LOG_SIZE) + return; + + sLog.outDebug( "WORLD: Received CMSG_QUESTLOG_SWAP_QUEST slot 1 = %u, slot 2 = %u", slot1, slot2 ); + + GetPlayer()->SwapQuestSlot(slot1,slot2); +} + +void WorldSession::HandleQuestLogRemoveQuest(WorldPacket& recv_data) +{ + CHECK_PACKET_SIZE(recv_data,1); + + uint8 slot; + recv_data >> slot; + + sLog.outDebug( "WORLD: Received CMSG_QUESTLOG_REMOVE_QUEST slot = %u",slot ); + + if( slot < MAX_QUEST_LOG_SIZE ) + { + if(uint32 quest = _player->GetQuestSlotQuestId(slot)) + { + if(!_player->TakeQuestSourceItem( quest, true )) + return; // can't un-equip some items, reject quest cancel + + _player->SetQuestStatus( quest, QUEST_STATUS_NONE); + } + + _player->SetQuestSlot(slot, 0); + } +} + +void WorldSession::HandleQuestConfirmAccept(WorldPacket& recv_data) +{ + CHECK_PACKET_SIZE(recv_data,4); + + uint32 quest; + recv_data >> quest; + + sLog.outDebug( "WORLD: Received CMSG_QUEST_CONFIRM_ACCEPT quest = %u",quest ); +} + +void WorldSession::HandleQuestComplete(WorldPacket& recv_data) +{ + CHECK_PACKET_SIZE(recv_data,8+4); + + uint32 quest; + uint64 guid; + recv_data >> guid >> quest; + + if(!GetPlayer()->isAlive()) + return; + + sLog.outDebug( "WORLD: Received CMSG_QUESTGIVER_COMPLETE_QUEST npc = %u, quest = %u",uint32(GUID_LOPART(guid)),quest ); + + Quest const *pQuest = objmgr.GetQuestTemplate(quest); + if( pQuest ) + { + if( _player->GetQuestStatus( quest ) != QUEST_STATUS_COMPLETE ) + { + if( pQuest->IsRepeatable() ) + _player->PlayerTalkClass->SendQuestGiverRequestItems(pQuest, guid, _player->CanCompleteRepeatableQuest(pQuest), false); + else + _player->PlayerTalkClass->SendQuestGiverRequestItems(pQuest, guid, _player->CanRewardQuest(pQuest,false), false); + } + else + _player->PlayerTalkClass->SendQuestGiverRequestItems(pQuest, guid, _player->CanRewardQuest(pQuest,false), false); + } +} + +void WorldSession::HandleQuestAutoLaunch(WorldPacket& /*recvPacket*/) +{ + sLog.outDebug( "WORLD: Received CMSG_QUESTGIVER_QUEST_AUTOLAUNCH (Send your log to anakin if you see this message)" ); +} + +void WorldSession::HandleQuestPushToParty(WorldPacket& recvPacket) +{ + CHECK_PACKET_SIZE(recvPacket,4); + + uint32 quest; + recvPacket >> quest; + + sLog.outDebug( "WORLD: Received CMSG_PUSHQUESTTOPARTY quest = %u", quest ); + + Quest const *pQuest = objmgr.GetQuestTemplate(quest); + if( pQuest ) + { + if( _player->GetGroup() ) + { + Group *pGroup = _player->GetGroup(); + if( pGroup ) + { + for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *pPlayer = itr->getSource(); + if (!pPlayer || pPlayer == _player) // skip self + continue; + + _player->SendPushToPartyResponse(pPlayer, QUEST_PARTY_MSG_SHARING_QUEST); + + if( _player->GetDistance( pPlayer ) > 10 ) + { + _player->SendPushToPartyResponse( pPlayer, QUEST_PARTY_MSG_TOO_FAR ); + continue; + } + + if( !pPlayer->SatisfyQuestStatus( pQuest, false ) ) + { + _player->SendPushToPartyResponse( pPlayer, QUEST_PARTY_MSG_HAVE_QUEST ); + continue; + } + + if( pPlayer->GetQuestStatus( quest ) == QUEST_STATUS_COMPLETE ) + { + _player->SendPushToPartyResponse( pPlayer, QUEST_PARTY_MSG_FINISH_QUEST ); + continue; + } + + if( !pPlayer->CanTakeQuest( pQuest, false ) ) + { + _player->SendPushToPartyResponse( pPlayer, QUEST_PARTY_MSG_CANT_TAKE_QUEST ); + continue; + } + + if( !pPlayer->SatisfyQuestLog( false ) ) + { + _player->SendPushToPartyResponse( pPlayer, QUEST_PARTY_MSG_LOG_FULL ); + continue; + } + + if( pPlayer->GetDivider() != 0 ) + { + _player->SendPushToPartyResponse( pPlayer, QUEST_PARTY_MSG_BUSY ); + continue; + } + + pPlayer->PlayerTalkClass->SendQuestGiverQuestDetails( pQuest, _player->GetGUID(), true ); + pPlayer->SetDivider( _player->GetGUID() ); + } + } + } + } +} + +void WorldSession::HandleQuestPushResult(WorldPacket& recvPacket) +{ + CHECK_PACKET_SIZE(recvPacket,8+1); + + uint64 guid; + uint8 msg; + recvPacket >> guid >> msg; + + sLog.outDebug( "WORLD: Received MSG_QUEST_PUSH_RESULT" ); + + if( _player->GetDivider() != 0 ) + { + Player *pPlayer = ObjectAccessor::FindPlayer( _player->GetDivider() ); + if( pPlayer ) + { + WorldPacket data( MSG_QUEST_PUSH_RESULT, (8+1) ); + data << uint64(guid); + data << uint8(msg); // valid values: 0-8 + pPlayer->GetSession()->SendPacket(&data); + _player->SetDivider( 0 ); + } + } +} + +uint32 WorldSession::getDialogStatus(Player *pPlayer, Object* questgiver, uint32 defstatus) +{ + uint32 result = defstatus; + + QuestRelations const* qir; + QuestRelations const* qr; + + switch(questgiver->GetTypeId()) + { + case TYPEID_GAMEOBJECT: + { + qir = &objmgr.mGOQuestInvolvedRelations; + qr = &objmgr.mGOQuestRelations; + break; + } + case TYPEID_UNIT: + { + qir = &objmgr.mCreatureQuestInvolvedRelations; + qr = &objmgr.mCreatureQuestRelations; + break; + } + default: + //its imposible, but check ^) + sLog.outError("Warning: GetDialogStatus called for unexpected type %u", questgiver->GetTypeId()); + return DIALOG_STATUS_NONE; + } + + for(QuestRelations::const_iterator i = qir->lower_bound(questgiver->GetEntry()); i != qir->upper_bound(questgiver->GetEntry()); ++i ) + { + uint32 result2 = 0; + uint32 quest_id = i->second; + Quest const *pQuest = objmgr.GetQuestTemplate(quest_id); + if ( !pQuest ) continue; + + QuestStatus status = pPlayer->GetQuestStatus( quest_id ); + if( (status == QUEST_STATUS_COMPLETE && !pPlayer->GetQuestRewardStatus(quest_id)) || + (pQuest->IsAutoComplete() && pPlayer->CanTakeQuest(pQuest, false)) ) + { + if ( pQuest->IsAutoComplete() && pQuest->IsRepeatable() ) + result2 = DIALOG_STATUS_REWARD_REP; + else + result2 = DIALOG_STATUS_REWARD; + } + else if ( status == QUEST_STATUS_INCOMPLETE ) + result2 = DIALOG_STATUS_INCOMPLETE; + + if (result2 > result) + result = result2; + } + + for(QuestRelations::const_iterator i = qr->lower_bound(questgiver->GetEntry()); i != qr->upper_bound(questgiver->GetEntry()); ++i ) + { + uint32 result2 = 0; + uint32 quest_id = i->second; + Quest const *pQuest = objmgr.GetQuestTemplate(quest_id); + if ( !pQuest ) + continue; + + QuestStatus status = pPlayer->GetQuestStatus( quest_id ); + if ( status == QUEST_STATUS_NONE ) + { + if ( pPlayer->CanSeeStartQuest( pQuest ) ) + { + if ( pPlayer->SatisfyQuestLevel(pQuest, false) ) + { + if ( pQuest->IsAutoComplete() || (pQuest->IsRepeatable() && pPlayer->getQuestStatusMap()[quest_id].m_rewarded)) + result2 = DIALOG_STATUS_REWARD_REP; + else if (pPlayer->getLevel() <= pQuest->GetQuestLevel() + sWorld.getConfig(CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF) ) + { + if (pQuest->HasFlag(QUEST_FLAGS_DAILY)) + result2 = DIALOG_STATUS_AVAILABLE_REP; + else + result2 = DIALOG_STATUS_AVAILABLE; + } + else + result2 = DIALOG_STATUS_CHAT; + } + else + result2 = DIALOG_STATUS_UNAVAILABLE; + } + } + + if (result2 > result) + result = result2; + } + + if(questgiver->GetTypeId()==TYPEID_UNIT && ((Creature*)questgiver)->isCanTrainingAndResetTalentsOf(pPlayer) && result < DIALOG_STATUS_CHAT) + result = DIALOG_STATUS_CHAT; + + return result; +} + +void WorldSession::HandleQuestgiverStatusQueryMultipleOpcode(WorldPacket& /*recvPacket*/) +{ + sLog.outDebug("WORLD: Received CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY"); + + uint32 count = 0; + + WorldPacket data(SMSG_QUESTGIVER_STATUS_MULTIPLE, 4); + data << uint32(count); // placeholder + + for(Player::ClientGUIDs::iterator itr = _player->m_clientGUIDs.begin(); itr != _player->m_clientGUIDs.end(); ++itr) + { + uint8 questStatus = DIALOG_STATUS_NONE; + uint8 defstatus = DIALOG_STATUS_NONE; + + if(IS_CREATURE_GUID(*itr)) + { + Creature *questgiver = ObjectAccessor::GetCreature(*_player, *itr); + if(!questgiver || questgiver->IsHostileTo(_player)) + continue; + if(!questgiver->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER)) + continue; + questStatus = Script->NPCDialogStatus(_player, questgiver); + if( questStatus > 6 ) + questStatus = getDialogStatus(_player, questgiver, defstatus); + + data << uint64(questgiver->GetGUID()); + data << uint8(questStatus); + ++count; + } + else if(IS_GAMEOBJECT_GUID(*itr)) + { + GameObject *questgiver = ObjectAccessor::GetGameObject(*_player, *itr); + if(!questgiver) + continue; + if(questgiver->GetGoType() != GAMEOBJECT_TYPE_QUESTGIVER) + continue; + questStatus = Script->GODialogStatus(_player, questgiver); + if( questStatus > 6 ) + questStatus = getDialogStatus(_player, questgiver, defstatus); + + data << uint64(questgiver->GetGUID()); + data << uint8(questStatus); + ++count; + } + } + + data.put(0, count); // write real count + SendPacket(&data); +} diff --git a/src/game/RandomMovementGenerator.cpp b/src/game/RandomMovementGenerator.cpp new file mode 100644 index 00000000000..1022a0699f6 --- /dev/null +++ b/src/game/RandomMovementGenerator.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Creature.h" +#include "MapManager.h" +#include "RandomMovementGenerator.h" +#include "DestinationHolderImp.h" +#include "Map.h" +#include "Util.h" + +#define RUNNING_CHANCE_RANDOMMV 20 //will be "1 / RUNNING_CHANCE_RANDOMMV" + +template<> +void +RandomMovementGenerator::_setRandomLocation(Creature &creature) +{ + float X,Y,Z,z,nx,ny,nz,wander_distance,ori,dist; + + creature.GetRespawnCoord(X, Y, Z); + creature.GetRespawnCoord(X, Y, Z, &ori, &wander_distance); + + z = creature.GetPositionZ(); + uint32 mapid=creature.GetMapId(); + Map const* map = MapManager::Instance().GetBaseMap(mapid); + + // For 2D/3D system selection + bool is_land_ok = creature.canWalk(); + bool is_water_ok = creature.canSwim(); + bool is_air_ok = creature.canFly(); + + const float angle = rand_norm()*(M_PI*2); + const float range = rand_norm()*wander_distance; + const float distanceX = range * cos(angle); + const float distanceY = range * sin(angle); + + nx = X + distanceX; + ny = Y + distanceY; + dist = distanceX*distanceX + distanceY*distanceY; + + if (is_air_ok) // 3D system above ground and above water (flying mode) + { + const float distanceZ = rand_norm() * sqrtf(dist)/2; // Limit height change + nz = Z + distanceZ; + float tz = map->GetHeight(nx, ny, nz-2.0f, false); // Map check only, vmap needed here but need to alter vmaps checks for height. + float wz = map->GetWaterLevel(nx, ny); + if (tz >= nz || wz >= nz) + return; // Problem here, we must fly above the ground and water, not under. Let's try on next tick + } + //else if (is_water_ok) // 3D system under water and above ground (swimming mode) + else // 2D only + { + dist = dist>=100.0f ? 10.0f : sqrtf(dist); // 10.0 is the max that vmap high can check (MAX_CAN_FALL_DISTANCE) + // The fastest way to get an accurate result 90% of the time. + // Better result can be obtained like 99% accuracy with a ray light, but the cost is too high and the code is too long. + nz = map->GetHeight(nx,ny,Z+dist-2.0f,false); // Map check + if (fabs(nz-Z)>dist) + { + nz = map->GetHeight(nx,ny,Z-2.0f,true); // Vmap Horizontal or above + if (fabs(nz-Z)>dist) + { + nz = map->GetHeight(nx,ny,Z+dist-2.0f,true); // Vmap Higher + if (fabs(nz-Z)>dist) + return; // let's forget this bad coords where a z cannot be find and retry at next tick + } + } + } + + Traveller traveller(creature); + creature.SetOrientation(creature.GetAngle(nx,ny)); + i_destinationHolder.SetDestination(traveller, nx, ny, nz); + creature.addUnitState(UNIT_STAT_ROAMING); + if (is_air_ok) + { + i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime()); + creature.SetUnitMovementFlags(MOVEMENTFLAG_FLYING2); + } + //else if (is_water_ok) // Swimming mode to be done with more than this check + else + { + i_nextMoveTime.Reset(urand(500+i_destinationHolder.GetTotalTravelTime(),5000+i_destinationHolder.GetTotalTravelTime())); + creature.SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); + } +} + +template<> +void +RandomMovementGenerator::Initialize(Creature &creature) +{ + if(!creature.isAlive()) + return; + + if (creature.canFly()) + creature.SetUnitMovementFlags(MOVEMENTFLAG_FLYING2); + else + creature.SetUnitMovementFlags(irand(0,RUNNING_CHANCE_RANDOMMV) > 0 ? MOVEMENTFLAG_WALK_MODE : MOVEMENTFLAG_NONE ); + _setRandomLocation(creature); +} + +template<> +void +RandomMovementGenerator::Reset(Creature &creature) +{ + Initialize(creature); +} + +template<> +bool +RandomMovementGenerator::Update(Creature &creature, const uint32 &diff) +{ + if(creature.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED | UNIT_STAT_DISTRACTED)) + { + i_nextMoveTime.Update(i_nextMoveTime.GetExpiry()); // Expire the timer + creature.clearUnitState(UNIT_STAT_ROAMING); + return true; + } + + i_nextMoveTime.Update(diff); + + if(i_destinationHolder.HasArrived() && !creature.IsStopped() && !creature.canFly()) + creature.clearUnitState(UNIT_STAT_ROAMING); + + if(!i_destinationHolder.HasArrived() && creature.IsStopped()) + creature.addUnitState(UNIT_STAT_ROAMING); + + CreatureTraveller traveller(creature); + + if( i_destinationHolder.UpdateTraveller(traveller, diff, false, true) ) + { + if(i_nextMoveTime.Passed()) + { + if (creature.canFly()) + creature.SetUnitMovementFlags(MOVEMENTFLAG_FLYING2); + else + creature.SetUnitMovementFlags(irand(0,RUNNING_CHANCE_RANDOMMV) > 0 ? MOVEMENTFLAG_WALK_MODE : MOVEMENTFLAG_NONE); + _setRandomLocation(creature); + } + else if(creature.isPet() && creature.GetOwner() && creature.GetDistance(creature.GetOwner()) > PET_FOLLOW_DIST+2.5f) + { + creature.SetUnitMovementFlags(MOVEMENTFLAG_NONE); + _setRandomLocation(creature); + } + } + return true; +} diff --git a/src/game/RandomMovementGenerator.h b/src/game/RandomMovementGenerator.h new file mode 100644 index 00000000000..62b836e4261 --- /dev/null +++ b/src/game/RandomMovementGenerator.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_RANDOMMOTIONGENERATOR_H +#define MANGOS_RANDOMMOTIONGENERATOR_H + +#include "MovementGenerator.h" +#include "DestinationHolder.h" +#include "Traveller.h" + + +template +class MANGOS_DLL_SPEC RandomMovementGenerator +: public MovementGeneratorMedium< T, RandomMovementGenerator > +{ + public: + RandomMovementGenerator(const Unit &) : i_nextMoveTime(0) {} + + void _setRandomLocation(T &); + void Initialize(T &); + void Finalize(T &) {} + void Reset(T &); + bool Update(T &, const uint32 &); + void UpdateMapPosition(uint32 mapid, float &x ,float &y, float &z) + { + i_destinationHolder.GetLocationNow(mapid, x,y,z); + } + MovementGeneratorType GetMovementGeneratorType() { return RANDOM_MOTION_TYPE; } + private: + TimeTrackerSmall i_nextMoveTime; + + DestinationHolder< Traveller > i_destinationHolder; + uint32 i_nextMove; +}; +#endif diff --git a/src/game/ReactorAI.cpp b/src/game/ReactorAI.cpp new file mode 100644 index 00000000000..a91af776e6d --- /dev/null +++ b/src/game/ReactorAI.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ByteBuffer.h" +#include "ReactorAI.h" +#include "Errors.h" +#include "Creature.h" +#include "Log.h" +#include "ObjectAccessor.h" + +#define REACTOR_VISIBLE_RANGE (26.46f) + +int +ReactorAI::Permissible(const Creature *creature) +{ + if( creature->isCivilian() || creature->IsNeutralToAll() ) + return PERMIT_BASE_REACTIVE; + + return PERMIT_BASE_NO; +} + +void +ReactorAI::MoveInLineOfSight(Unit *) +{ +} + +void +ReactorAI::AttackStart(Unit *p) +{ + if(!p) + return; + + if(i_creature.Attack(p,true)) + { + DEBUG_LOG("Tag unit GUID: %u (TypeId: %u) as a victim", p->GetGUIDLow(), p->GetTypeId()); + i_creature.SetInCombatWith(p); + p->SetInCombatWith(&i_creature); + + i_creature.AddThreat(p, 0.0f); + i_victimGuid = p->GetGUID(); + i_creature.GetMotionMaster()->MoveChase(p); + } +} + +bool +ReactorAI::IsVisible(Unit *) const +{ + return false; +} + +void +ReactorAI::UpdateAI(const uint32 /*time_diff*/) +{ + // update i_victimGuid if i_creature.getVictim() !=0 and changed + if(!i_creature.SelectHostilTarget() || !i_creature.getVictim()) + return; + + i_victimGuid = i_creature.getVictim()->GetGUID(); + + if( i_creature.isAttackReady() ) + { + if( i_creature.IsWithinDistInMap(i_creature.getVictim(), ATTACK_DISTANCE)) + { + i_creature.AttackerStateUpdate(i_creature.getVictim()); + i_creature.resetAttackTimer(); + } + } +} + +void +ReactorAI::EnterEvadeMode() +{ + if( !i_creature.isAlive() ) + { + DEBUG_LOG("Creature stoped attacking cuz his dead [guid=%u]", i_creature.GetGUIDLow()); + i_creature.GetMotionMaster()->MovementExpired(); + i_creature.GetMotionMaster()->MoveIdle(); + i_victimGuid = 0; + i_creature.CombatStop(); + i_creature.DeleteThreatList(); + return; + } + + Unit* victim = ObjectAccessor::GetUnit(i_creature, i_victimGuid ); + + if( !victim ) + { + DEBUG_LOG("Creature stopped attacking because victim is non exist [guid=%u]", i_creature.GetGUIDLow()); + } + else if( victim->HasStealthAura() ) + { + DEBUG_LOG("Creature stopped attacking cuz his victim is stealth [guid=%u]", i_creature.GetGUIDLow()); + } + else if( victim->isInFlight() ) + { + DEBUG_LOG("Creature stopped attacking cuz his victim is fly away [guid=%u]", i_creature.GetGUIDLow()); + } + else + { + DEBUG_LOG("Creature stopped attacking due to target %s [guid=%u]", victim->isAlive() ? "out run him" : "is dead", i_creature.GetGUIDLow()); + } + + i_creature.RemoveAllAuras(); + i_creature.DeleteThreatList(); + i_victimGuid = 0; + i_creature.CombatStop(); + i_creature.SetLootRecipient(NULL); + + // Remove TargetedMovementGenerator from MotionMaster stack list, and add HomeMovementGenerator instead + if( i_creature.GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE ) + i_creature.GetMotionMaster()->MoveTargetedHome(); +} diff --git a/src/game/ReactorAI.h b/src/game/ReactorAI.h new file mode 100644 index 00000000000..a64208b89ef --- /dev/null +++ b/src/game/ReactorAI.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_REACTORAI_H +#define MANGOS_REACTORAI_H + +#include "CreatureAI.h" + +class Unit; + +class MANGOS_DLL_DECL ReactorAI : public CreatureAI +{ + public: + + ReactorAI(Creature &c) : i_creature(c), i_victimGuid(0) {} + + void MoveInLineOfSight(Unit *); + void AttackStart(Unit *); + void EnterEvadeMode(); + bool IsVisible(Unit *) const; + + void UpdateAI(const uint32); + static int Permissible(const Creature *); + + private: + Creature &i_creature; + uint64 i_victimGuid; +}; +#endif diff --git a/src/game/ScriptCalls.cpp b/src/game/ScriptCalls.cpp new file mode 100644 index 00000000000..c3021958804 --- /dev/null +++ b/src/game/ScriptCalls.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef WIN32 +#include +#endif + +#include "Platform/Define.h" +#include "ScriptCalls.h" + +ScriptsSet Script=NULL; + +void UnloadScriptingModule() +{ + if(Script) + { + //todo: some check if some func from script library is called right now + Script->ScriptsFree(); + MANGOS_CLOSE_LIBRARY(Script->hScriptsLib); + delete Script; + Script = NULL; + } +} + +bool LoadScriptingModule(char const* libName) +{ + ScriptsSet testScript=new _ScriptSet; + + std::string name = strlen(libName) ? libName : MANGOS_SCRIPT_NAME; + name += MANGOS_SCRIPT_EXT; + + testScript->hScriptsLib=MANGOS_LOAD_LIBRARY(name.c_str()); + + if(!testScript->hScriptsLib ) + { + printf("Error loading Scripts Library %s !\n",name.c_str()); + delete testScript; + return false; + } + + if( !(testScript->ScriptsInit =(scriptCallScriptsInit )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"ScriptsInit" )) + ||!(testScript->ScriptsFree =(scriptCallScriptsFree )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"ScriptsFree" )) + ||!(testScript->GossipHello =(scriptCallGossipHello )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"GossipHello" )) + ||!(testScript->GOChooseReward =(scriptCallGOChooseReward )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"GOChooseReward" )) + ||!(testScript->QuestAccept =(scriptCallQuestAccept )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"QuestAccept" )) + ||!(testScript->GossipSelect =(scriptCallGossipSelect )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"GossipSelect" )) + ||!(testScript->GossipSelectWithCode=(scriptCallGossipSelectWithCode)MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"GossipSelectWithCode")) + ||!(testScript->QuestSelect =(scriptCallQuestSelect )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"QuestSelect" )) + ||!(testScript->QuestComplete =(scriptCallQuestComplete )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"QuestComplete" )) + ||!(testScript->NPCDialogStatus =(scriptCallNPCDialogStatus )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"NPCDialogStatus" )) + ||!(testScript->GODialogStatus =(scriptCallGODialogStatus )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"GODialogStatus" )) + ||!(testScript->ChooseReward =(scriptCallChooseReward )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"ChooseReward" )) + ||!(testScript->ItemHello =(scriptCallItemHello )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"ItemHello" )) + ||!(testScript->GOHello =(scriptCallGOHello )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"GOHello" )) + ||!(testScript->scriptAreaTrigger =(scriptCallAreaTrigger )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"AreaTrigger" )) + ||!(testScript->ItemQuestAccept =(scriptCallItemQuestAccept )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"ItemQuestAccept" )) + ||!(testScript->GOQuestAccept =(scriptCallGOQuestAccept )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"GOQuestAccept" )) + ||!(testScript->ReceiveEmote =(scriptCallReceiveEmote )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"ReceiveEmote" )) + ||!(testScript->ItemUse =(scriptCallItemUse )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"ItemUse" )) + ||!(testScript->GetAI =(scriptCallGetAI )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"GetAI" )) + ||!(testScript->CreateInstanceData =(scriptCallCreateInstanceData )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"CreateInstanceData" )) + ) + { + printf("Error loading Scripts Library %s !\n Library missing required functions.",name.c_str()); + MANGOS_CLOSE_LIBRARY(testScript->hScriptsLib); + delete testScript; + return false; + } + + printf("Scripts Library %s was successfully loaded.\n",name.c_str()); + + //heh we are still there :P we have a valid library + //we reload script + UnloadScriptingModule(); + + Script=testScript; + Script->ScriptsInit(); + + return true; +} diff --git a/src/game/ScriptCalls.h b/src/game/ScriptCalls.h new file mode 100644 index 00000000000..07c415497ad --- /dev/null +++ b/src/game/ScriptCalls.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __SCRIPT_CALLS_H +#define __SCRIPT_CALLS_H + +#include "Common.h" +#include "ObjectMgr.h" + +class Creature; +class CreatureAI; +class GameObject; +class Item; +class Player; +class Quest; +class SpellCastTargets; +class Map; +class InstanceData; + +bool LoadScriptingModule(char const* libName = ""); +void UnloadScriptingModule(); + +typedef void(MANGOS_IMPORT * scriptCallScriptsInit) (); +typedef void(MANGOS_IMPORT * scriptCallScriptsFree) (); + +typedef bool(MANGOS_IMPORT * scriptCallGossipHello) (Player *player, Creature *_Creature ); +typedef bool(MANGOS_IMPORT * scriptCallQuestAccept) (Player *player, Creature *_Creature, Quest const *); +typedef bool(MANGOS_IMPORT * scriptCallGossipSelect)(Player *player, Creature *_Creature, uint32 sender, uint32 action); +typedef bool(MANGOS_IMPORT * scriptCallGossipSelectWithCode)( Player *player, Creature *_Creature, uint32 sender, uint32 action, const char* sCode ); +typedef bool(MANGOS_IMPORT * scriptCallQuestSelect)( Player *player, Creature *_Creature, Quest const* ); +typedef bool(MANGOS_IMPORT * scriptCallQuestComplete)(Player *player, Creature *_Creature, Quest const*); +typedef uint32(MANGOS_IMPORT * scriptCallNPCDialogStatus)( Player *player, Creature *_Creature); +typedef uint32(MANGOS_IMPORT * scriptCallGODialogStatus)( Player *player, GameObject * _GO); +typedef bool(MANGOS_IMPORT * scriptCallChooseReward)( Player *player, Creature *_Creature, Quest const*, uint32 opt ); +typedef bool(MANGOS_IMPORT * scriptCallItemHello)( Player *player, Item *, Quest const*); +typedef bool(MANGOS_IMPORT * scriptCallGOHello)( Player *player, GameObject * ); +typedef bool(MANGOS_IMPORT * scriptCallAreaTrigger)( Player *player, AreaTriggerEntry const* ); +typedef bool(MANGOS_IMPORT * scriptCallItemQuestAccept)(Player *player, Item *, Quest const*); +typedef bool(MANGOS_IMPORT * scriptCallGOQuestAccept)(Player *player, GameObject *, Quest const*); +typedef bool(MANGOS_IMPORT * scriptCallGOChooseReward)(Player *player, GameObject *, Quest const*, uint32 opt ); +typedef bool(MANGOS_IMPORT * scriptCallReceiveEmote) ( Player *player, Creature *_Creature, uint32 emote ); +typedef bool(MANGOS_IMPORT * scriptCallItemUse) (Player *player, Item *_Item, SpellCastTargets const& targets); +typedef CreatureAI* (MANGOS_IMPORT * scriptCallGetAI) ( Creature *_Creature ); +typedef InstanceData* (MANGOS_IMPORT * scriptCallCreateInstanceData) (Map *map); + +typedef struct +{ + scriptCallScriptsInit ScriptsInit; + scriptCallScriptsFree ScriptsFree; + + scriptCallGossipHello GossipHello; + scriptCallGOChooseReward GOChooseReward; + scriptCallQuestAccept QuestAccept; + scriptCallGossipSelect GossipSelect; + scriptCallGossipSelectWithCode GossipSelectWithCode; + scriptCallQuestSelect QuestSelect; + scriptCallQuestComplete QuestComplete; + scriptCallNPCDialogStatus NPCDialogStatus; + scriptCallGODialogStatus GODialogStatus; + scriptCallChooseReward ChooseReward; + scriptCallItemHello ItemHello; + scriptCallGOHello GOHello; + scriptCallAreaTrigger scriptAreaTrigger; + scriptCallItemQuestAccept ItemQuestAccept; + scriptCallGOQuestAccept GOQuestAccept; + scriptCallReceiveEmote ReceiveEmote; + scriptCallItemUse ItemUse; + scriptCallGetAI GetAI; + scriptCallCreateInstanceData CreateInstanceData; + + MANGOS_LIBRARY_HANDLE hScriptsLib; +}_ScriptSet,*ScriptsSet; + +extern ScriptsSet Script; +#endif diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h new file mode 100644 index 00000000000..06c6daead2a --- /dev/null +++ b/src/game/SharedDefines.h @@ -0,0 +1,1997 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_SHAREDDEFINES_H +#define MANGOS_SHAREDDEFINES_H + +#include "Platform/Define.h" +#include + +enum Gender +{ + GENDER_MALE = 0, + GENDER_FEMALE = 1, + GENDER_NONE = 2 +}; + +// Race value is index in ChrRaces.dbc +enum Races +{ + RACE_HUMAN = 1, + RACE_ORC = 2, + RACE_DWARF = 3, + RACE_NIGHTELF = 4, + RACE_UNDEAD_PLAYER = 5, + RACE_TAUREN = 6, + RACE_GNOME = 7, + RACE_TROLL = 8, + RACE_GOBLIN = 9, + RACE_BLOODELF = 10, + RACE_DRAENEI = 11, + RACE_FEL_ORC = 12, + RACE_NAGA = 13, + RACE_BROKEN = 14, + RACE_SKELETON = 15, + MAX_RACES = 16 +}; + +#define RACEMASK_ALL_PLAYABLE \ + ((1<<(RACE_HUMAN-1)) |(1<<(RACE_ORC-1)) |(1<<(RACE_DWARF-1)) | \ + (1<<(RACE_NIGHTELF-1))|(1<<(RACE_UNDEAD_PLAYER-1))|(1<<(RACE_TAUREN-1)) | \ + (1<<(RACE_GNOME-1)) |(1<<(RACE_TROLL-1)) |(1<<(RACE_BLOODELF-1))| \ + (1<<(RACE_DRAENEI-1)) ) + +// Class value is index in ChrClasses.dbc +enum Classes +{ + CLASS_WARRIOR = 1, + CLASS_PALADIN = 2, + CLASS_HUNTER = 3, + CLASS_ROGUE = 4, + CLASS_PRIEST = 5, + // CLASS_UNK1 = 6, DK + CLASS_SHAMAN = 7, + CLASS_MAGE = 8, + CLASS_WARLOCK = 9, + // CLASS_UNK2 = 10,unused + CLASS_DRUID = 11, + MAX_CLASSES = 12 +}; + +#define CLASSMASK_ALL_PLAYABLE \ + ((1<<(CLASS_WARRIOR-1))|(1<<(CLASS_PALADIN-1))|(1<<(CLASS_HUNTER-1))| \ + (1<<(CLASS_ROGUE-1)) |(1<<(CLASS_PRIEST-1)) |(1<<(CLASS_SHAMAN-1))| \ + (1<<(CLASS_MAGE-1)) |(1<<(CLASS_WARLOCK-1))|(1<<(CLASS_DRUID-1)) ) + +#define CLASSMASK_WAND_USERS ((1<<(CLASS_PRIEST-1))|(1<<(CLASS_MAGE-1))|(1<<(CLASS_WARLOCK-1))) + +#define PLAYER_MAX_BATTLEGROUND_QUEUES 3 + +enum ReputationRank +{ + REP_HATED = 0, + REP_HOSTILE = 1, + REP_UNFRIENDLY = 2, + REP_NEUTRAL = 3, + REP_FRIENDLY = 4, + REP_HONORED = 5, + REP_REVERED = 6, + REP_EXALTED = 7 +}; + +#define MIN_REPUTATION_RANK (REP_HATED) +#define MAX_REPUTATION_RANK 8 + +enum MoneyConstants +{ + COPPER = 1, + SILVER = COPPER*100, + GOLD = SILVER*100 +}; + +enum Stats +{ + STAT_STRENGTH = 0, + STAT_AGILITY = 1, + STAT_STAMINA = 2, + STAT_INTELLECT = 3, + STAT_SPIRIT = 4 +}; + +#define MAX_STATS 5 + +enum Powers +{ + POWER_MANA = 0, + POWER_RAGE = 1, + POWER_FOCUS = 2, + POWER_ENERGY = 3, + POWER_HAPPINESS = 4, + POWER_RUNES = 5, + POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value) +}; + +#define MAX_POWERS 5 // not count POWER_RUNES for now + +enum SpellSchools +{ + SPELL_SCHOOL_NORMAL = 0, + SPELL_SCHOOL_HOLY = 1, + SPELL_SCHOOL_FIRE = 2, + SPELL_SCHOOL_NATURE = 3, + SPELL_SCHOOL_FROST = 4, + SPELL_SCHOOL_SHADOW = 5, + SPELL_SCHOOL_ARCANE = 6 +}; + +#define MAX_SPELL_SCHOOL 7 + +enum SpellSchoolMask +{ + SPELL_SCHOOL_MASK_NONE = 0x00, // not exist + SPELL_SCHOOL_MASK_NORMAL = (1 << SPELL_SCHOOL_NORMAL), // PHYSICAL (Armor) + SPELL_SCHOOL_MASK_HOLY = (1 << SPELL_SCHOOL_HOLY ), + SPELL_SCHOOL_MASK_FIRE = (1 << SPELL_SCHOOL_FIRE ), + SPELL_SCHOOL_MASK_NATURE = (1 << SPELL_SCHOOL_NATURE), + SPELL_SCHOOL_MASK_FROST = (1 << SPELL_SCHOOL_FROST ), + SPELL_SCHOOL_MASK_SHADOW = (1 << SPELL_SCHOOL_SHADOW), + SPELL_SCHOOL_MASK_ARCANE = (1 << SPELL_SCHOOL_ARCANE), + + // unions + + // 124, not include normal and holy damage + SPELL_SCHOOL_MASK_SPELL = ( SPELL_SCHOOL_MASK_FIRE | + SPELL_SCHOOL_MASK_NATURE | SPELL_SCHOOL_MASK_FROST | + SPELL_SCHOOL_MASK_SHADOW | SPELL_SCHOOL_MASK_ARCANE ), + // 126 + SPELL_SCHOOL_MASK_MAGIC = ( SPELL_SCHOOL_MASK_HOLY | SPELL_SCHOOL_MASK_SPELL ), + + // 127 + SPELL_SCHOOL_MASK_ALL = ( SPELL_SCHOOL_MASK_NORMAL | SPELL_SCHOOL_MASK_MAGIC ) +}; + +#define SPELL_SCHOOL_MASK_MAGIC \ + ( SPELL_SCHOOL_MASK_HOLY | SPELL_SCHOOL_MASK_FIRE | SPELL_SCHOOL_MASK_NATURE | \ + SPELL_SCHOOL_MASK_FROST | SPELL_SCHOOL_MASK_SHADOW | \ + SPELL_SCHOOL_MASK_ARCANE ) + +inline SpellSchools GetFirstSchoolInMask(SpellSchoolMask mask) +{ + for(int i = 0; i < MAX_SPELL_SCHOOL; ++i) + if(mask & (1 << i)) + return SpellSchools(i); + + return SPELL_SCHOOL_NORMAL; +} + +enum ItemQualities +{ + ITEM_QUALITY_POOR = 0, //GREY + ITEM_QUALITY_NORMAL = 1, //WHITE + ITEM_QUALITY_UNCOMMON = 2, //GREEN + ITEM_QUALITY_RARE = 3, //BLUE + ITEM_QUALITY_EPIC = 4, //PURPLE + ITEM_QUALITY_LEGENDARY = 5, //ORANGE + ITEM_QUALITY_ARTIFACT = 6 //LIGHT YELLOW +}; + +#define MAX_ITEM_QUALITY 7 + +// *********************************** +// Spell Attributes definitions +// *********************************** + +#define SPELL_ATTR_UNK0 0x00000001 // 0 +#define SPELL_ATTR_RANGED 0x00000002 // 1 All ranged abilites have this flag +#define SPELL_ATTR_ON_NEXT_SWING_1 0x00000004 // 2 on next swing +#define SPELL_ATTR_UNK3 0x00000008 // 3 not set in 2.4.2 +#define SPELL_ATTR_UNK4 0x00000010 // 4 +#define SPELL_ATTR_UNK5 0x00000020 // 5 trade spells? +#define SPELL_ATTR_PASSIVE 0x00000040 // 6 Passive spell +#define SPELL_ATTR_UNK7 0x00000080 // 7 visible? +#define SPELL_ATTR_UNK8 0x00000100 // 8 +#define SPELL_ATTR_UNK9 0x00000200 // 9 +#define SPELL_ATTR_ON_NEXT_SWING_2 0x00000400 // 10 on next swing 2 +#define SPELL_ATTR_UNK11 0x00000800 // 11 +#define SPELL_ATTR_DAYTIME_ONLY 0x00001000 // 12 only useable at daytime, not set in 2.4.2 +#define SPELL_ATTR_NIGHT_ONLY 0x00002000 // 13 only useable at night, not set in 2.4.2 +#define SPELL_ATTR_INDOORS_ONLY 0x00004000 // 14 only useable indoors, not set in 2.4.2 +#define SPELL_ATTR_OUTDOORS_ONLY 0x00008000 // 15 Only useable outdoors. +#define SPELL_ATTR_NOT_SHAPESHIFT 0x00010000 // 16 Not while shapeshifted +#define SPELL_ATTR_ONLY_STEALTHED 0x00020000 // 17 Must be in stealth +#define SPELL_ATTR_UNK18 0x00040000 // 18 +#define SPELL_ATTR_LEVEL_DAMAGE_CALCULATION 0x00080000 // 19 spelldamage depends on caster level +#define SPELL_ATTR_STOP_ATTACK_TARGET 0x00100000 // 20 Stop attack after use this spell (and not begin attack if use) +#define SPELL_ATTR_IMPOSSIBLE_DODGE_PARRY_BLOCK 0x00200000 // 21 Cannot be dodged/parried/blocked +#define SPELL_ATTR_UNK22 0x00400000 // 22 +#define SPELL_ATTR_UNK23 0x00800000 // 23 castable while dead? +#define SPELL_ATTR_CASTABLE_WHILE_MOUNTED 0x01000000 // 24 castable while mounted +#define SPELL_ATTR_DISABLED_WHILE_ACTIVE 0x02000000 // 25 Activate and start cooldown after aura fade or remove summoned creature or go +#define SPELL_ATTR_UNK26 0x04000000 // 26 +#define SPELL_ATTR_CASTABLE_WHILE_SITTING 0x08000000 // 27 castable while sitting +#define SPELL_ATTR_CANT_USED_IN_COMBAT 0x10000000 // 28 Cannot be used in combat +#define SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY 0x20000000 // 29 unaffected by invulnerability (hmm possible not...) +#define SPELL_ATTR_UNK30 0x40000000 // 30 breakable by damage? +#define SPELL_ATTR_CANT_CANCEL 0x80000000 // 31 positive aura can't be canceled + +#define SPELL_ATTR_EX_UNK0 0x00000001 // 0 +#define SPELL_ATTR_EX_DRAIN_ALL_POWER 0x00000002 // 1 use all power (Only paladin Lay of Hands and Bunyanize) +#define SPELL_ATTR_EX_CHANNELED_1 0x00000004 // 2 channeled 1 +#define SPELL_ATTR_EX_UNK3 0x00000008 // 3 +#define SPELL_ATTR_EX_UNK4 0x00000010 // 4 +#define SPELL_ATTR_EX_NOT_BREAK_STEALTH 0x00000020 // 5 Not break stealth +#define SPELL_ATTR_EX_CHANNELED_2 0x00000040 // 6 channeled 2 +#define SPELL_ATTR_EX_NEGATIVE 0x00000080 // 7 +#define SPELL_ATTR_EX_NOT_IN_COMBAT_TARGET 0x00000100 // 8 Spell req target not to be in combat state +#define SPELL_ATTR_EX_UNK9 0x00000200 // 9 +#define SPELL_ATTR_EX_UNK10 0x00000400 // 10 +#define SPELL_ATTR_EX_UNK11 0x00000800 // 11 +#define SPELL_ATTR_EX_UNK12 0x00001000 // 12 +#define SPELL_ATTR_EX_UNK13 0x00002000 // 13 +#define SPELL_ATTR_EX_UNK14 0x00004000 // 14 +#define SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY 0x00008000 // 15 remove auras on immunity +#define SPELL_ATTR_EX_UNAFFECTED_BY_SCHOOL_IMMUNE 0x00010000 // 16 unaffected by school immunity +#define SPELL_ATTR_EX_UNK17 0x00020000 // 17 +#define SPELL_ATTR_EX_UNK18 0x00040000 // 18 +#define SPELL_ATTR_EX_UNK19 0x00080000 // 19 +#define SPELL_ATTR_EX_REQ_COMBO_POINTS1 0x00100000 // 20 Req combo points on target +#define SPELL_ATTR_EX_UNK21 0x00200000 // 21 +#define SPELL_ATTR_EX_REQ_COMBO_POINTS2 0x00400000 // 22 Req combo points on target +#define SPELL_ATTR_EX_UNK23 0x00800000 // 23 +#define SPELL_ATTR_EX_UNK24 0x01000000 // 24 Req fishing pole?? +#define SPELL_ATTR_EX_UNK25 0x02000000 // 25 not set in 2.4.2 +#define SPELL_ATTR_EX_UNK26 0x04000000 // 26 +#define SPELL_ATTR_EX_UNK27 0x08000000 // 27 +#define SPELL_ATTR_EX_UNK28 0x10000000 // 28 +#define SPELL_ATTR_EX_UNK29 0x20000000 // 29 +#define SPELL_ATTR_EX_UNK30 0x40000000 // 30 overpower +#define SPELL_ATTR_EX_UNK31 0x80000000 // 31 + +#define SPELL_ATTR_EX2_UNK0 0x00000001 // 0 +#define SPELL_ATTR_EX2_UNK1 0x00000002 // 1 +#define SPELL_ATTR_EX2_UNK2 0x00000004 // 2 +#define SPELL_ATTR_EX2_UNK3 0x00000008 // 3 +#define SPELL_ATTR_EX2_UNK4 0x00000010 // 4 +#define SPELL_ATTR_EX2_UNK5 0x00000020 // 5 +#define SPELL_ATTR_EX2_UNK6 0x00000040 // 6 +#define SPELL_ATTR_EX2_UNK7 0x00000080 // 7 +#define SPELL_ATTR_EX2_UNK8 0x00000100 // 8 not set in 2.4.2 +#define SPELL_ATTR_EX2_UNK9 0x00000200 // 9 +#define SPELL_ATTR_EX2_UNK10 0x00000400 // 10 +#define SPELL_ATTR_EX2_HEALTH_FUNNEL 0x00000800 // 11 +#define SPELL_ATTR_EX2_UNK12 0x00001000 // 12 +#define SPELL_ATTR_EX2_UNK13 0x00002000 // 13 +#define SPELL_ATTR_EX2_UNK14 0x00004000 // 14 +#define SPELL_ATTR_EX2_UNK15 0x00008000 // 15 not set in 2.4.2 +#define SPELL_ATTR_EX2_UNK16 0x00010000 // 16 +#define SPELL_ATTR_EX2_UNK17 0x00020000 // 17 Hunters Shot and Stings only have this flag +#define SPELL_ATTR_EX2_UNK18 0x00040000 // 18 Only Revive pet - possible req dead pet +#define SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT 0x00080000 // 19 does not necessarly need shapeshift +#define SPELL_ATTR_EX2_UNK20 0x00100000 // 20 +#define SPELL_ATTR_EX2_UNK21 0x00200000 // 21 +#define SPELL_ATTR_EX2_UNK22 0x00400000 // 22 +#define SPELL_ATTR_EX2_UNK23 0x00800000 // 23 Only mage Arcane Concentration have this flag +#define SPELL_ATTR_EX2_UNK24 0x01000000 // 24 +#define SPELL_ATTR_EX2_UNK25 0x02000000 // 25 +#define SPELL_ATTR_EX2_UNK26 0x04000000 // 26 unaffected by school immunity +#define SPELL_ATTR_EX2_UNK27 0x08000000 // 27 +#define SPELL_ATTR_EX2_UNK28 0x10000000 // 28 +#define SPELL_ATTR_EX2_CANT_CRIT 0x20000000 // 29 Spell can't crit +#define SPELL_ATTR_EX2_UNK30 0x40000000 // 30 +#define SPELL_ATTR_EX2_UNK31 0x80000000 // 31 + +#define SPELL_ATTR_EX3_UNK0 0x00000001 // 0 +#define SPELL_ATTR_EX3_UNK1 0x00000002 // 1 +#define SPELL_ATTR_EX3_UNK2 0x00000004 // 2 +#define SPELL_ATTR_EX3_UNK3 0x00000008 // 3 +#define SPELL_ATTR_EX3_UNK4 0x00000010 // 4 Druid Rebirth only this spell have this flag +#define SPELL_ATTR_EX3_UNK5 0x00000020 // 5 +#define SPELL_ATTR_EX3_UNK6 0x00000040 // 6 +#define SPELL_ATTR_EX3_UNK7 0x00000080 // 7 +#define SPELL_ATTR_EX3_UNK8 0x00000100 // 8 +#define SPELL_ATTR_EX3_UNK9 0x00000200 // 9 +#define SPELL_ATTR_EX3_MAIN_HAND 0x00000400 // 10 Main hand weapon required +#define SPELL_ATTR_EX3_BATTLEGROUND 0x00000800 // 11 Can casted only on battleground +#define SPELL_ATTR_EX3_UNK12 0x00001000 // 12 +#define SPELL_ATTR_EX3_UNK13 0x00002000 // 13 +#define SPELL_ATTR_EX3_UNK14 0x00004000 // 14 "Honorless Target" only this spells have this flag +#define SPELL_ATTR_EX3_UNK15 0x00008000 // 15 Auto Shoot, Shoot, Throw, - this is autoshot flag +#define SPELL_ATTR_EX3_UNK16 0x00010000 // 16 +#define SPELL_ATTR_EX3_NO_INITIAL_AGGRO 0x00020000 // 17 no initial aggro +#define SPELL_ATTR_EX3_UNK18 0x00040000 // 18 +#define SPELL_ATTR_EX3_UNK19 0x00080000 // 19 +#define SPELL_ATTR_EX3_DEATH_PERSISTENT 0x00100000 // 20 Death persistent spells +#define SPELL_ATTR_EX3_UNK21 0x00200000 // 21 +#define SPELL_ATTR_EX3_REQ_WAND 0x00400000 // 22 Req wand +#define SPELL_ATTR_EX3_UNK23 0x00800000 // 23 +#define SPELL_ATTR_EX3_REQ_OFFHAND 0x01000000 // 24 Req offhand weapon +#define SPELL_ATTR_EX3_UNK25 0x02000000 // 25 +#define SPELL_ATTR_EX3_UNK26 0x04000000 // 26 +#define SPELL_ATTR_EX3_UNK27 0x08000000 // 27 +#define SPELL_ATTR_EX3_UNK28 0x10000000 // 28 +#define SPELL_ATTR_EX3_UNK29 0x20000000 // 29 +#define SPELL_ATTR_EX3_UNK30 0x40000000 // 30 +#define SPELL_ATTR_EX3_UNK31 0x80000000 // 31 + +#define SPELL_ATTR_EX4_UNK0 0x00000001 // 0 +#define SPELL_ATTR_EX4_UNK1 0x00000002 // 1 proc on finishing move? +#define SPELL_ATTR_EX4_UNK2 0x00000004 // 2 +#define SPELL_ATTR_EX4_UNK3 0x00000008 // 3 +#define SPELL_ATTR_EX4_UNK4 0x00000010 // 4 +#define SPELL_ATTR_EX4_UNK5 0x00000020 // 5 +#define SPELL_ATTR_EX4_UNK6 0x00000040 // 6 +#define SPELL_ATTR_EX4_UNK7 0x00000080 // 7 +#define SPELL_ATTR_EX4_UNK8 0x00000100 // 8 +#define SPELL_ATTR_EX4_UNK9 0x00000200 // 9 +#define SPELL_ATTR_EX4_SPELL_VS_EXTEND_COST 0x00000400 // 10 Rogue Shiv have this flag +#define SPELL_ATTR_EX4_UNK11 0x00000800 // 11 +#define SPELL_ATTR_EX4_UNK12 0x00001000 // 12 +#define SPELL_ATTR_EX4_UNK13 0x00002000 // 13 +#define SPELL_ATTR_EX4_UNK14 0x00004000 // 14 +#define SPELL_ATTR_EX4_UNK15 0x00008000 // 15 +#define SPELL_ATTR_EX4_NOT_USABLE_IN_ARENA 0x00010000 // 16 not usable in arena +#define SPELL_ATTR_EX4_USABLE_IN_ARENA 0x00020000 // 17 usable in arena +#define SPELL_ATTR_EX4_UNK18 0x00040000 // 18 +#define SPELL_ATTR_EX4_UNK19 0x00080000 // 19 +#define SPELL_ATTR_EX4_UNK20 0x00100000 // 20 +#define SPELL_ATTR_EX4_UNK21 0x00200000 // 21 +#define SPELL_ATTR_EX4_UNK22 0x00400000 // 22 +#define SPELL_ATTR_EX4_UNK23 0x00800000 // 23 +#define SPELL_ATTR_EX4_UNK24 0x01000000 // 24 +#define SPELL_ATTR_EX4_UNK25 0x02000000 // 25 pet scaling auras +#define SPELL_ATTR_EX4_CAST_ONLY_IN_OUTLAND 0x04000000 // 26 Can only be used in Outland. +#define SPELL_ATTR_EX4_UNK27 0x08000000 // 27 +#define SPELL_ATTR_EX4_UNK28 0x10000000 // 28 +#define SPELL_ATTR_EX4_UNK29 0x20000000 // 29 +#define SPELL_ATTR_EX4_UNK30 0x40000000 // 30 +#define SPELL_ATTR_EX4_UNK31 0x80000000 // 31 + +#define SPELL_ATTR_EX5_UNK0 0x00000001 // 0 +#define SPELL_ATTR_EX5_NO_REAGENT_WHILE_PREP 0x00000002 // 1 not need reagents if UNIT_FLAG_PREPARATION +#define SPELL_ATTR_EX5_UNK2 0x00000004 // 2 +#define SPELL_ATTR_EX5_USABLE_WHILE_STUNNED 0x00000008 // 3 usable while stunned +#define SPELL_ATTR_EX5_UNK4 0x00000010 // 4 +#define SPELL_ATTR_EX5_SINGLE_TARGET_SPELL 0x00000020 // 5 Only one target can be apply at a time +#define SPELL_ATTR_EX5_UNK6 0x00000040 // 6 +#define SPELL_ATTR_EX5_UNK7 0x00000080 // 7 +#define SPELL_ATTR_EX5_UNK8 0x00000100 // 8 +#define SPELL_ATTR_EX5_UNK9 0x00000200 // 9 +#define SPELL_ATTR_EX5_UNK10 0x00000400 // 10 +#define SPELL_ATTR_EX5_UNK11 0x00000800 // 11 +#define SPELL_ATTR_EX5_UNK12 0x00001000 // 12 +#define SPELL_ATTR_EX5_UNK13 0x00002000 // 13 +#define SPELL_ATTR_EX5_UNK14 0x00004000 // 14 +#define SPELL_ATTR_EX5_UNK15 0x00008000 // 15 +#define SPELL_ATTR_EX5_UNK16 0x00010000 // 16 +#define SPELL_ATTR_EX5_USABLE_WHILE_FEARED 0x00020000 // 17 usable while feared +#define SPELL_ATTR_EX5_USABLE_WHILE_CONFUSED 0x00040000 // 18 usable while confused +#define SPELL_ATTR_EX5_UNK19 0x00080000 // 19 +#define SPELL_ATTR_EX5_UNK20 0x00100000 // 20 +#define SPELL_ATTR_EX5_UNK21 0x00200000 // 21 +#define SPELL_ATTR_EX5_UNK22 0x00400000 // 22 +#define SPELL_ATTR_EX5_UNK23 0x00800000 // 23 +#define SPELL_ATTR_EX5_UNK24 0x01000000 // 24 +#define SPELL_ATTR_EX5_UNK25 0x02000000 // 25 +#define SPELL_ATTR_EX5_UNK26 0x04000000 // 26 +#define SPELL_ATTR_EX5_UNK27 0x08000000 // 27 +#define SPELL_ATTR_EX5_UNK28 0x10000000 // 28 +#define SPELL_ATTR_EX5_UNK29 0x20000000 // 29 +#define SPELL_ATTR_EX5_UNK30 0x40000000 // 30 +#define SPELL_ATTR_EX5_UNK31 0x80000000 // 31 Forces all nearby enemies to focus attacks caster + +#define SPELL_ATTR_EX6_UNK0 0x00000001 // 0 Only Move spell have this flag +#define SPELL_ATTR_EX6_UNK1 0x00000002 // 1 not set in 2.4.2 +#define SPELL_ATTR_EX6_UNK2 0x00000004 // 2 +#define SPELL_ATTR_EX6_UNK3 0x00000008 // 3 +#define SPELL_ATTR_EX6_UNK4 0x00000010 // 4 not set in 2.4.2 +#define SPELL_ATTR_EX6_UNK5 0x00000020 // 5 +#define SPELL_ATTR_EX6_UNK6 0x00000040 // 6 +#define SPELL_ATTR_EX6_UNK7 0x00000080 // 7 +#define SPELL_ATTR_EX6_UNK8 0x00000100 // 8 +#define SPELL_ATTR_EX6_UNK9 0x00000200 // 9 not set in 2.4.2 +#define SPELL_ATTR_EX6_UNK10 0x00000400 // 10 +#define SPELL_ATTR_EX6_UNK11 0x00000800 // 11 +#define SPELL_ATTR_EX6_UNK12 0x00001000 // 12 not set in 2.4.2 +#define SPELL_ATTR_EX6_UNK13 0x00002000 // 13 not set in 2.4.2 +#define SPELL_ATTR_EX6_UNK14 0x00004000 // 14 not set in 2.4.2 +#define SPELL_ATTR_EX6_UNK15 0x00008000 // 15 not set in 2.4.2 +#define SPELL_ATTR_EX6_UNK16 0x00010000 // 16 not set in 2.4.2 +#define SPELL_ATTR_EX6_UNK17 0x00020000 // 17 not set in 2.4.2 +#define SPELL_ATTR_EX6_UNK18 0x00040000 // 18 not set in 2.4.2 +#define SPELL_ATTR_EX6_UNK19 0x00080000 // 19 not set in 2.4.2 +#define SPELL_ATTR_EX6_UNK20 0x00100000 // 20 not set in 2.4.2 +#define SPELL_ATTR_EX6_UNK21 0x00200000 // 21 not set in 2.4.2 +#define SPELL_ATTR_EX6_UNK22 0x00400000 // 22 not set in 2.4.2 +#define SPELL_ATTR_EX6_UNK23 0x00800000 // 23 not set in 2.4.2 +#define SPELL_ATTR_EX6_UNK24 0x01000000 // 24 not set in 2.4.2 +#define SPELL_ATTR_EX6_UNK25 0x02000000 // 25 not set in 2.4.2 +#define SPELL_ATTR_EX6_UNK26 0x04000000 // 26 not set in 2.4.2 +#define SPELL_ATTR_EX6_UNK27 0x08000000 // 27 not set in 2.4.2 +#define SPELL_ATTR_EX6_UNK28 0x10000000 // 28 not set in 2.4.2 +#define SPELL_ATTR_EX6_UNK29 0x20000000 // 29 not set in 2.4.2 +#define SPELL_ATTR_EX6_UNK30 0x40000000 // 30 not set in 2.4.2 +#define SPELL_ATTR_EX6_UNK31 0x80000000 // 31 not set in 2.4.2 + +enum SheathTypes +{ + SHEATHETYPE_NONE = 0, + SHEATHETYPE_MAINHAND = 1, + SHEATHETYPE_OFFHAND = 2, + SHEATHETYPE_LARGEWEAPONLEFT = 3, + SHEATHETYPE_LARGEWEAPONRIGHT = 4, + SHEATHETYPE_HIPWEAPONLEFT = 5, + SHEATHETYPE_HIPWEAPONRIGHT = 6, + SHEATHETYPE_SHIELD = 7 +}; + +#define MAX_SHEATHETYPE 8 + +enum CharacterSlot +{ + SLOT_HEAD = 0, + SLOT_NECK = 1, + SLOT_SHOULDERS = 2, + SLOT_SHIRT = 3, + SLOT_CHEST = 4, + SLOT_WAIST = 5, + SLOT_LEGS = 6, + SLOT_FEET = 7, + SLOT_WRISTS = 8, + SLOT_HANDS = 9, + SLOT_FINGER1 = 10, + SLOT_FINGER2 = 11, + SLOT_TRINKET1 = 12, + SLOT_TRINKET2 = 13, + SLOT_BACK = 14, + SLOT_MAIN_HAND = 15, + SLOT_OFF_HAND = 16, + SLOT_RANGED = 17, + SLOT_TABARD = 18, + SLOT_EMPTY = 19 +}; + +enum Language +{ + LANG_UNIVERSAL = 0, + LANG_ORCISH = 1, + LANG_DARNASSIAN = 2, + LANG_TAURAHE = 3, + LANG_DWARVISH = 6, + LANG_COMMON = 7, + LANG_DEMONIC = 8, + LANG_TITAN = 9, + LANG_THALASSIAN = 10, + LANG_DRACONIC = 11, + LANG_KALIMAG = 12, + LANG_GNOMISH = 13, + LANG_TROLL = 14, + LANG_GUTTERSPEAK = 33, + LANG_DRAENEI = 35, + LANG_ZOMBIE = 36, + LANG_GNOMISH_BINARY = 37, + LANG_GOBLIN_BINARY = 38, + LANG_ADDON = 0xFFFFFFFF // used by addons, in 2.4.0 not exit, replaced by messagetype? +}; + +#define LANGUAGES_COUNT 19 + +enum Team +{ + HORDE = 67, + ALLIANCE = 469, + //TEAM_STEAMWHEEDLE_CARTEL = 169, // not used in code + //TEAM_ALLIANCE_FORCES = 891, + //TEAM_HORDE_FORCES = 892, + //TEAM_SANCTUARY = 936, + //TEAM_OUTLAND = 980, + //TEAM_OTHER = 0, // if ReputationListId > 0 && Flags != FACTION_FLAG_TEAM_HEADER +}; + +enum SpellEffects +{ + SPELL_EFFECT_INSTAKILL = 1, + SPELL_EFFECT_SCHOOL_DAMAGE = 2, + SPELL_EFFECT_DUMMY = 3, + SPELL_EFFECT_PORTAL_TELEPORT = 4, + SPELL_EFFECT_TELEPORT_UNITS = 5, + SPELL_EFFECT_APPLY_AURA = 6, + SPELL_EFFECT_ENVIRONMENTAL_DAMAGE = 7, + SPELL_EFFECT_POWER_DRAIN = 8, + SPELL_EFFECT_HEALTH_LEECH = 9, + SPELL_EFFECT_HEAL = 10, + SPELL_EFFECT_BIND = 11, + SPELL_EFFECT_PORTAL = 12, + SPELL_EFFECT_RITUAL_BASE = 13, + SPELL_EFFECT_RITUAL_SPECIALIZE = 14, + SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL = 15, + SPELL_EFFECT_QUEST_COMPLETE = 16, + SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL = 17, + SPELL_EFFECT_RESURRECT = 18, + SPELL_EFFECT_ADD_EXTRA_ATTACKS = 19, + SPELL_EFFECT_DODGE = 20, + SPELL_EFFECT_EVADE = 21, + SPELL_EFFECT_PARRY = 22, + SPELL_EFFECT_BLOCK = 23, + SPELL_EFFECT_CREATE_ITEM = 24, + SPELL_EFFECT_WEAPON = 25, + SPELL_EFFECT_DEFENSE = 26, + SPELL_EFFECT_PERSISTENT_AREA_AURA = 27, + SPELL_EFFECT_SUMMON = 28, + SPELL_EFFECT_LEAP = 29, + SPELL_EFFECT_ENERGIZE = 30, + SPELL_EFFECT_WEAPON_PERCENT_DAMAGE = 31, + SPELL_EFFECT_TRIGGER_MISSILE = 32, + SPELL_EFFECT_OPEN_LOCK = 33, + SPELL_EFFECT_SUMMON_CHANGE_ITEM = 34, + SPELL_EFFECT_APPLY_AREA_AURA_PARTY = 35, + SPELL_EFFECT_LEARN_SPELL = 36, + SPELL_EFFECT_SPELL_DEFENSE = 37, + SPELL_EFFECT_DISPEL = 38, + SPELL_EFFECT_LANGUAGE = 39, + SPELL_EFFECT_DUAL_WIELD = 40, + SPELL_EFFECT_SUMMON_WILD = 41, + SPELL_EFFECT_SUMMON_GUARDIAN = 42, + SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER= 43, + SPELL_EFFECT_SKILL_STEP = 44, + SPELL_EFFECT_UNDEFINED_45 = 45, + SPELL_EFFECT_SPAWN = 46, + SPELL_EFFECT_TRADE_SKILL = 47, + SPELL_EFFECT_STEALTH = 48, + SPELL_EFFECT_DETECT = 49, + // SPELL_EFFECT_SUMMON_OBJECT = 50, + SPELL_EFFECT_TRANS_DOOR = 50, + SPELL_EFFECT_FORCE_CRITICAL_HIT = 51, + SPELL_EFFECT_GUARANTEE_HIT = 52, + SPELL_EFFECT_ENCHANT_ITEM = 53, + SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY = 54, + SPELL_EFFECT_TAMECREATURE = 55, + SPELL_EFFECT_SUMMON_PET = 56, + SPELL_EFFECT_LEARN_PET_SPELL = 57, + SPELL_EFFECT_WEAPON_DAMAGE = 58, + SPELL_EFFECT_OPEN_LOCK_ITEM = 59, + SPELL_EFFECT_PROFICIENCY = 60, + SPELL_EFFECT_SEND_EVENT = 61, + SPELL_EFFECT_POWER_BURN = 62, + SPELL_EFFECT_THREAT = 63, + SPELL_EFFECT_TRIGGER_SPELL = 64, + SPELL_EFFECT_HEALTH_FUNNEL = 65, + SPELL_EFFECT_POWER_FUNNEL = 66, + SPELL_EFFECT_HEAL_MAX_HEALTH = 67, + SPELL_EFFECT_INTERRUPT_CAST = 68, + SPELL_EFFECT_DISTRACT = 69, + SPELL_EFFECT_PULL = 70, + SPELL_EFFECT_PICKPOCKET = 71, + SPELL_EFFECT_ADD_FARSIGHT = 72, + SPELL_EFFECT_SUMMON_POSSESSED = 73, + SPELL_EFFECT_SUMMON_TOTEM = 74, + SPELL_EFFECT_HEAL_MECHANICAL = 75, + SPELL_EFFECT_SUMMON_OBJECT_WILD = 76, + SPELL_EFFECT_SCRIPT_EFFECT = 77, + SPELL_EFFECT_ATTACK = 78, + SPELL_EFFECT_SANCTUARY = 79, + SPELL_EFFECT_ADD_COMBO_POINTS = 80, + SPELL_EFFECT_CREATE_HOUSE = 81, + SPELL_EFFECT_BIND_SIGHT = 82, + SPELL_EFFECT_DUEL = 83, + SPELL_EFFECT_STUCK = 84, + SPELL_EFFECT_SUMMON_PLAYER = 85, + SPELL_EFFECT_ACTIVATE_OBJECT = 86, + SPELL_EFFECT_SUMMON_TOTEM_SLOT1 = 87, + SPELL_EFFECT_SUMMON_TOTEM_SLOT2 = 88, + SPELL_EFFECT_SUMMON_TOTEM_SLOT3 = 89, + SPELL_EFFECT_SUMMON_TOTEM_SLOT4 = 90, + SPELL_EFFECT_THREAT_ALL = 91, + SPELL_EFFECT_ENCHANT_HELD_ITEM = 92, + SPELL_EFFECT_SUMMON_PHANTASM = 93, + SPELL_EFFECT_SELF_RESURRECT = 94, + SPELL_EFFECT_SKINNING = 95, + SPELL_EFFECT_CHARGE = 96, + SPELL_EFFECT_SUMMON_CRITTER = 97, + SPELL_EFFECT_KNOCK_BACK = 98, + SPELL_EFFECT_DISENCHANT = 99, + SPELL_EFFECT_INEBRIATE = 100, + SPELL_EFFECT_FEED_PET = 101, + SPELL_EFFECT_DISMISS_PET = 102, + SPELL_EFFECT_REPUTATION = 103, + SPELL_EFFECT_SUMMON_OBJECT_SLOT1 = 104, + SPELL_EFFECT_SUMMON_OBJECT_SLOT2 = 105, + SPELL_EFFECT_SUMMON_OBJECT_SLOT3 = 106, + SPELL_EFFECT_SUMMON_OBJECT_SLOT4 = 107, + SPELL_EFFECT_DISPEL_MECHANIC = 108, + SPELL_EFFECT_SUMMON_DEAD_PET = 109, + SPELL_EFFECT_DESTROY_ALL_TOTEMS = 110, + SPELL_EFFECT_DURABILITY_DAMAGE = 111, + SPELL_EFFECT_SUMMON_DEMON = 112, + SPELL_EFFECT_RESURRECT_NEW = 113, + SPELL_EFFECT_ATTACK_ME = 114, + SPELL_EFFECT_DURABILITY_DAMAGE_PCT = 115, + SPELL_EFFECT_SKIN_PLAYER_CORPSE = 116, + SPELL_EFFECT_SPIRIT_HEAL = 117, + SPELL_EFFECT_SKILL = 118, + SPELL_EFFECT_APPLY_AREA_AURA_PET = 119, + SPELL_EFFECT_TELEPORT_GRAVEYARD = 120, + SPELL_EFFECT_NORMALIZED_WEAPON_DMG = 121, + SPELL_EFFECT_122 = 122, + SPELL_EFFECT_SEND_TAXI = 123, + SPELL_EFFECT_PLAYER_PULL = 124, + SPELL_EFFECT_MODIFY_THREAT_PERCENT = 125, + SPELL_EFFECT_STEAL_BENEFICIAL_BUFF = 126, + SPELL_EFFECT_PROSPECTING = 127, + SPELL_EFFECT_APPLY_AREA_AURA_FRIEND = 128, + SPELL_EFFECT_APPLY_AREA_AURA_ENEMY = 129, + SPELL_EFFECT_REDIRECT_THREAT = 130, + SPELL_EFFECT_131 = 131, + SPELL_EFFECT_132 = 132, + SPELL_EFFECT_UNLEARN_SPECIALIZATION = 133, + SPELL_EFFECT_KILL_CREDIT = 134, + SPELL_EFFECT_135 = 135, + SPELL_EFFECT_HEAL_PCT = 136, + SPELL_EFFECT_ENERGIZE_PCT = 137, + SPELL_EFFECT_138 = 138, + SPELL_EFFECT_139 = 139, + SPELL_EFFECT_FORCE_CAST = 140, + SPELL_EFFECT_141 = 141, + SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE = 142, + SPELL_EFFECT_APPLY_AREA_AURA_OWNER = 143, + SPELL_EFFECT_144 = 144, + SPELL_EFFECT_145 = 145, + SPELL_EFFECT_146 = 146, + SPELL_EFFECT_QUEST_FAIL = 147, + SPELL_EFFECT_148 = 148, + SPELL_EFFECT_149 = 149, + SPELL_EFFECT_150 = 150, + SPELL_EFFECT_TRIGGER_SPELL_2 = 151, + SPELL_EFFECT_152 = 152, + SPELL_EFFECT_153 = 153, + TOTAL_SPELL_EFFECTS = 154 +}; + +// Spell aura states +enum AuraState +{ // (C) used in caster aura state (T) used in target aura state + // (c) used in caster aura state-not (t) used in target aura state-not + AURA_STATE_DEFENSE = 1, // C | + AURA_STATE_HEALTHLESS_20_PERCENT = 2, // CcT | + AURA_STATE_BERSERKING = 3, // C T | + //AURA_STATE_UNKNOWN4 = 4, // c t| some limitation to charge spells (?) and target test spells + AURA_STATE_JUDGEMENT = 5, // C | + //AURA_STATE_UNKNOWN6 = 6, // | not used + AURA_STATE_HUNTER_PARRY = 7, // C | + AURA_STATE_ROGUE_ATTACK_FROM_STEALTH = 7, // C | FIX ME: not implemented yet! + //AURA_STATE_UNKNOWN7c = 7, // c | random/focused bursts spells (?) + //AURA_STATE_UNKNOWN8 = 8, // | not used + //AURA_STATE_UNKNOWN9 = 9, // | not used + AURA_STATE_WARRIOR_VICTORY_RUSH = 10, // C | warrior victory rush + AURA_STATE_HUNTER_CRIT_STRIKE = 10, // C | hunter crit strike + AURA_STATE_CRIT = 11, // C | + AURA_STATE_FAERIE_FIRE = 12, // c t| + AURA_STATE_HEALTHLESS_35_PERCENT = 13, // C T | + AURA_STATE_IMMOLATE = 14, // T | + AURA_STATE_SWIFTMEND = 15, // T | + AURA_STATE_DEADLY_POISON = 16, // T | + AURA_STATE_FORBEARANCE = 17, // c t| + AURA_STATE_WEAKENED_SOUL = 18, // t| + AURA_STATE_HYPOTHERMIA = 19 // c | +}; + +// Spell mechanics +enum Mechanics +{ + MECHANIC_NONE = 0, + MECHANIC_CHARM = 1, + MECHANIC_CONFUSED = 2, + MECHANIC_DISARM = 3, + MECHANIC_DISTRACT = 4, + MECHANIC_FEAR = 5, + MECHANIC_FUMBLE = 6, + MECHANIC_ROOT = 7, + MECHANIC_PACIFY = 8, //0 spells use this mechanic + MECHANIC_SILENCE = 9, + MECHANIC_SLEEP = 10, + MECHANIC_SNARE = 11, + MECHANIC_STUN = 12, + MECHANIC_FREEZE = 13, + MECHANIC_KNOCKOUT = 14, + MECHANIC_BLEED = 15, + MECHANIC_BANDAGE = 16, + MECHANIC_POLYMORPH = 17, + MECHANIC_BANISH = 18, + MECHANIC_SHIELD = 19, + MECHANIC_SHACKLE = 20, + MECHANIC_MOUNT = 21, + MECHANIC_PERSUADE = 22, //0 spells use this mechanic + MECHANIC_TURN = 23, + MECHANIC_HORROR = 24, + MECHANIC_INVULNERABILITY = 25, + MECHANIC_INTERRUPT = 26, + MECHANIC_DAZE = 27, + MECHANIC_DISCOVERY = 28, + MECHANIC_IMMUNE_SHIELD = 29, // Divine (Blessing) Shield/Protection and Ice Block + MECHANIC_SAPPED = 30 +}; + +// Used for spell 42292 Immune Movement Impairment and Loss of Control (0x49967da6) +#define IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK ( \ + (1<(only this effect in the spell) can't cast to it, +//some aura(related to Mechanics or ImmuneToState) can't apply to it. +enum SpellImmunity +{ + IMMUNITY_EFFECT = 0, // enum SpellEffects + IMMUNITY_STATE = 1, // enum AuraType + IMMUNITY_SCHOOL = 2, // enum SpellSchoolMask + IMMUNITY_DAMAGE = 3, // enum SpellSchoolMask + IMMUNITY_DISPEL = 4, // enum DispelType + IMMUNITY_MECHANIC = 5 // enum Mechanics +}; + +#define MAX_SPELL_IMMUNITY 6 + +enum Targets +{ + TARGET_SELF = 1, + TARGET_RANDOM_ENEMY_CHAIN_IN_AREA = 2, // only one spell has that, but regardless, it's a target type after all + TARGET_PET = 5, + TARGET_CHAIN_DAMAGE = 6, + TARGET_AREAEFFECT_CUSTOM = 8, + TARGET_INNKEEPER_COORDINATES = 9, // uses in teleport to innkeeper spells + TARGET_ALL_ENEMY_IN_AREA = 15, + TARGET_ALL_ENEMY_IN_AREA_INSTANT = 16, + TARGET_TABLE_X_Y_Z_COORDINATES = 17, // uses in teleport spells and some other + TARGET_EFFECT_SELECT = 18, // highly depends on the spell effect + TARGET_ALL_PARTY_AROUND_CASTER = 20, + TARGET_SINGLE_FRIEND = 21, + TARGET_ALL_AROUND_CASTER = 22, // used only in TargetA, target selection dependent from TargetB + TARGET_GAMEOBJECT = 23, + TARGET_IN_FRONT_OF_CASTER = 24, + TARGET_DUELVSPLAYER = 25, + TARGET_GAMEOBJECT_ITEM = 26, + TARGET_MASTER = 27, + TARGET_ALL_ENEMY_IN_AREA_CHANNELED = 28, + TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER = 30, // in TargetB used only with TARGET_ALL_AROUND_CASTER and in self casting range in TargetA + TARGET_ALL_FRIENDLY_UNITS_IN_AREA = 31, + TARGET_MINION = 32, + TARGET_ALL_PARTY = 33, + TARGET_ALL_PARTY_AROUND_CASTER_2 = 34, // used in Tranquility + TARGET_SINGLE_PARTY = 35, + TARGET_AREAEFFECT_PARTY = 37, + TARGET_SCRIPT = 38, + TARGET_SELF_FISHING = 39, + TARGET_TOTEM_EARTH = 41, + TARGET_TOTEM_WATER = 42, + TARGET_TOTEM_AIR = 43, + TARGET_TOTEM_FIRE = 44, + TARGET_CHAIN_HEAL = 45, + TARGET_SCRIPT_COORDINATES = 46, + TARGET_DYNAMIC_OBJECT = 47, + TARGET_SUMMON = 48, + TARGET_AREAEFFECT_CUSTOM_2 = 52, + TARGET_CURRENT_ENEMY_COORDINATES = 53, // set unit coordinates as dest, only 16 target B imlemented + TARGET_RANDOM_RAID_MEMBER = 56, + TARGET_SINGLE_FRIEND_2 = 57, + TARGET_AREAEFFECT_PARTY_AND_CLASS = 61, + TARGET_DUELVSPLAYER_COORDINATES = 63, + TARGET_BEHIND_VICTIM = 65, // uses in teleport behind spells + TARGET_SINGLE_ENEMY = 77, + TARGET_SELF2 = 87, + TARGET_NONCOMBAT_PET = 90, +}; + +enum SpellMissInfo +{ + SPELL_MISS_NONE = 0, + SPELL_MISS_MISS = 1, + SPELL_MISS_RESIST = 2, + SPELL_MISS_DODGE = 3, + SPELL_MISS_PARRY = 4, + SPELL_MISS_BLOCK = 5, + SPELL_MISS_EVADE = 6, + SPELL_MISS_IMMUNE = 7, + SPELL_MISS_IMMUNE2 = 8, + SPELL_MISS_DEFLECT = 9, + SPELL_MISS_ABSORB = 10, + SPELL_MISS_REFLECT = 11, +}; + +enum SpellHitType +{ + SPELL_HIT_TYPE_UNK1 = 0x00001, + SPELL_HIT_TYPE_CRIT = 0x00002, + SPELL_HIT_TYPE_UNK2 = 0x00004, + SPELL_HIT_TYPE_UNK3 = 0x00008, + SPELL_HIT_TYPE_UNK4 = 0x00020 +}; + +enum SpellDmgClass +{ + SPELL_DAMAGE_CLASS_NONE = 0, + SPELL_DAMAGE_CLASS_MAGIC = 1, + SPELL_DAMAGE_CLASS_MELEE = 2, + SPELL_DAMAGE_CLASS_RANGED = 3 +}; + +enum SpellPreventionType +{ + SPELL_PREVENTION_TYPE_NONE = 0, + SPELL_PREVENTION_TYPE_SILENCE = 1, + SPELL_PREVENTION_TYPE_PACIFY = 2 +}; + +enum GameobjectTypes +{ + GAMEOBJECT_TYPE_DOOR = 0, + GAMEOBJECT_TYPE_BUTTON = 1, + GAMEOBJECT_TYPE_QUESTGIVER = 2, + GAMEOBJECT_TYPE_CHEST = 3, + GAMEOBJECT_TYPE_BINDER = 4, + GAMEOBJECT_TYPE_GENERIC = 5, + GAMEOBJECT_TYPE_TRAP = 6, + GAMEOBJECT_TYPE_CHAIR = 7, + GAMEOBJECT_TYPE_SPELL_FOCUS = 8, + GAMEOBJECT_TYPE_TEXT = 9, + GAMEOBJECT_TYPE_GOOBER = 10, + GAMEOBJECT_TYPE_TRANSPORT = 11, + GAMEOBJECT_TYPE_AREADAMAGE = 12, + GAMEOBJECT_TYPE_CAMERA = 13, + GAMEOBJECT_TYPE_MAP_OBJECT = 14, + GAMEOBJECT_TYPE_MO_TRANSPORT = 15, + GAMEOBJECT_TYPE_DUEL_ARBITER = 16, + GAMEOBJECT_TYPE_FISHINGNODE = 17, + GAMEOBJECT_TYPE_SUMMONING_RITUAL = 18, + GAMEOBJECT_TYPE_MAILBOX = 19, + GAMEOBJECT_TYPE_AUCTIONHOUSE = 20, + GAMEOBJECT_TYPE_GUARDPOST = 21, + GAMEOBJECT_TYPE_SPELLCASTER = 22, + GAMEOBJECT_TYPE_MEETINGSTONE = 23, + GAMEOBJECT_TYPE_FLAGSTAND = 24, + GAMEOBJECT_TYPE_FISHINGHOLE = 25, + GAMEOBJECT_TYPE_FLAGDROP = 26, + GAMEOBJECT_TYPE_MINI_GAME = 27, + GAMEOBJECT_TYPE_LOTTERY_KIOSK = 28, + GAMEOBJECT_TYPE_CAPTURE_POINT = 29, + GAMEOBJECT_TYPE_AURA_GENERATOR = 30, + GAMEOBJECT_TYPE_DUNGEON_DIFFICULTY = 31, + GAMEOBJECT_TYPE_DO_NOT_USE_YET = 32, + GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING = 33, + GAMEOBJECT_TYPE_GUILD_BANK = 34, +}; + +#define MAX_GAMEOBJECT_TYPE 35 // sending to client this or greater value can crash client. + +#define GAMEOBJECT_FISHINGNODE_ENTRY 35591 // Better to define it somewhere instead of hardcoding everywhere + +enum GameObjectFlags +{ + GO_FLAG_IN_USE = 0x01, //disables interaction while animated + GO_FLAG_LOCKED = 0x02, //require key, spell, event, etc to be opened. Makes "Locked" appear in tooltip + GO_FLAG_INTERACT_COND = 0x04, //cannot interact (condition to interact) + GO_FLAG_TRANSPORT = 0x08, //any kind of transport? Object can transport (elevator, boat, car) + GO_FLAG_UNK1 = 0x10, // + GO_FLAG_NODESPAWN = 0x20, //never despawn, typically for doors, they just change state + GO_FLAG_TRIGGERED = 0x40, //typically, summoned objects. Triggered by spell or other events +}; + +enum TextEmotes +{ + TEXTEMOTE_AGREE = 1, + TEXTEMOTE_AMAZE = 2, + TEXTEMOTE_ANGRY = 3, + TEXTEMOTE_APOLOGIZE = 4, + TEXTEMOTE_APPLAUD = 5, + TEXTEMOTE_BASHFUL = 6, + TEXTEMOTE_BECKON = 7, + TEXTEMOTE_BEG = 8, + TEXTEMOTE_BITE = 9, + TEXTEMOTE_BLEED = 10, + TEXTEMOTE_BLINK = 11, + TEXTEMOTE_BLUSH = 12, + TEXTEMOTE_BONK = 13, + TEXTEMOTE_BORED = 14, + TEXTEMOTE_BOUNCE = 15, + TEXTEMOTE_BRB = 16, + TEXTEMOTE_BOW = 17, + TEXTEMOTE_BURP = 18, + TEXTEMOTE_BYE = 19, + TEXTEMOTE_CACKLE = 20, + TEXTEMOTE_CHEER = 21, + TEXTEMOTE_CHICKEN = 22, + TEXTEMOTE_CHUCKLE = 23, + TEXTEMOTE_CLAP = 24, + TEXTEMOTE_CONFUSED = 25, + TEXTEMOTE_CONGRATULATE = 26, + TEXTEMOTE_COUGH = 27, + TEXTEMOTE_COWER = 28, + TEXTEMOTE_CRACK = 29, + TEXTEMOTE_CRINGE = 30, + TEXTEMOTE_CRY = 31, + TEXTEMOTE_CURIOUS = 32, + TEXTEMOTE_CURTSEY = 33, + TEXTEMOTE_DANCE = 34, + TEXTEMOTE_DRINK = 35, + TEXTEMOTE_DROOL = 36, + TEXTEMOTE_EAT = 37, + TEXTEMOTE_EYE = 38, + TEXTEMOTE_FART = 39, + TEXTEMOTE_FIDGET = 40, + TEXTEMOTE_FLEX = 41, + TEXTEMOTE_FROWN = 42, + TEXTEMOTE_GASP = 43, + TEXTEMOTE_GAZE = 44, + TEXTEMOTE_GIGGLE = 45, + TEXTEMOTE_GLARE = 46, + TEXTEMOTE_GLOAT = 47, + TEXTEMOTE_GREET = 48, + TEXTEMOTE_GRIN = 49, + TEXTEMOTE_GROAN = 50, + TEXTEMOTE_GROVEL = 51, + TEXTEMOTE_GUFFAW = 52, + TEXTEMOTE_HAIL = 53, + TEXTEMOTE_HAPPY = 54, + TEXTEMOTE_HELLO = 55, + TEXTEMOTE_HUG = 56, + TEXTEMOTE_HUNGRY = 57, + TEXTEMOTE_KISS = 58, + TEXTEMOTE_KNEEL = 59, + TEXTEMOTE_LAUGH = 60, + TEXTEMOTE_LAYDOWN = 61, + TEXTEMOTE_MESSAGE = 62, + TEXTEMOTE_MOAN = 63, + TEXTEMOTE_MOON = 64, + TEXTEMOTE_MOURN = 65, + TEXTEMOTE_NO = 66, + TEXTEMOTE_NOD = 67, + TEXTEMOTE_NOSEPICK = 68, + TEXTEMOTE_PANIC = 69, + TEXTEMOTE_PEER = 70, + TEXTEMOTE_PLEAD = 71, + TEXTEMOTE_POINT = 72, + TEXTEMOTE_POKE = 73, + TEXTEMOTE_PRAY = 74, + TEXTEMOTE_ROAR = 75, + TEXTEMOTE_ROFL = 76, + TEXTEMOTE_RUDE = 77, + TEXTEMOTE_SALUTE = 78, + TEXTEMOTE_SCRATCH = 79, + TEXTEMOTE_SEXY = 80, + TEXTEMOTE_SHAKE = 81, + TEXTEMOTE_SHOUT = 82, + TEXTEMOTE_SHRUG = 83, + TEXTEMOTE_SHY = 84, + TEXTEMOTE_SIGH = 85, + TEXTEMOTE_SIT = 86, + TEXTEMOTE_SLEEP = 87, + TEXTEMOTE_SNARL = 88, + TEXTEMOTE_SPIT = 89, + TEXTEMOTE_STARE = 90, + TEXTEMOTE_SURPRISED = 91, + TEXTEMOTE_SURRENDER = 92, + TEXTEMOTE_TALK = 93, + TEXTEMOTE_TALKEX = 94, + TEXTEMOTE_TALKQ = 95, + TEXTEMOTE_TAP = 96, + TEXTEMOTE_THANK = 97, + TEXTEMOTE_THREATEN = 98, + TEXTEMOTE_TIRED = 99, + TEXTEMOTE_VICTORY = 100, + TEXTEMOTE_WAVE = 101, + TEXTEMOTE_WELCOME = 102, + TEXTEMOTE_WHINE = 103, + TEXTEMOTE_WHISTLE = 104, + TEXTEMOTE_WORK = 105, + TEXTEMOTE_YAWN = 106, + TEXTEMOTE_BOGGLE = 107, + TEXTEMOTE_CALM = 108, + TEXTEMOTE_COLD = 109, + TEXTEMOTE_COMFORT = 110, + TEXTEMOTE_CUDDLE = 111, + TEXTEMOTE_DUCK = 112, + TEXTEMOTE_INSULT = 113, + TEXTEMOTE_INTRODUCE = 114, + TEXTEMOTE_JK = 115, + TEXTEMOTE_LICK = 116, + TEXTEMOTE_LISTEN = 117, + TEXTEMOTE_LOST = 118, + TEXTEMOTE_MOCK = 119, + TEXTEMOTE_PONDER = 120, + TEXTEMOTE_POUNCE = 121, + TEXTEMOTE_PRAISE = 122, + TEXTEMOTE_PURR = 123, + TEXTEMOTE_PUZZLE = 124, + TEXTEMOTE_RAISE = 125, + TEXTEMOTE_READY = 126, + TEXTEMOTE_SHIMMY = 127, + TEXTEMOTE_SHIVER = 128, + TEXTEMOTE_SHOO = 129, + TEXTEMOTE_SLAP = 130, + TEXTEMOTE_SMIRK = 131, + TEXTEMOTE_SNIFF = 132, + TEXTEMOTE_SNUB = 133, + TEXTEMOTE_SOOTHE = 134, + TEXTEMOTE_STINK = 135, + TEXTEMOTE_TAUNT = 136, + TEXTEMOTE_TEASE = 137, + TEXTEMOTE_THIRSTY = 138, + TEXTEMOTE_VETO = 139, + TEXTEMOTE_SNICKER = 140, + TEXTEMOTE_STAND = 141, + TEXTEMOTE_TICKLE = 142, + TEXTEMOTE_VIOLIN = 143, + TEXTEMOTE_SMILE = 163, + TEXTEMOTE_RASP = 183, + TEXTEMOTE_PITY = 203, + TEXTEMOTE_GROWL = 204, + TEXTEMOTE_BARK = 205, + TEXTEMOTE_SCARED = 223, + TEXTEMOTE_FLOP = 224, + TEXTEMOTE_LOVE = 225, + TEXTEMOTE_MOO = 226, + TEXTEMOTE_OPENFIRE = 327, + TEXTEMOTE_FLIRT = 328, + TEXTEMOTE_JOKE = 329, + TEXTEMOTE_COMMEND = 243, + TEXTEMOTE_WINK = 363, + TEXTEMOTE_PAT = 364, + TEXTEMOTE_SERIOUS = 365, + TEXTEMOTE_MOUNTSPECIAL = 366, + TEXTEMOTE_GOODLUCK = 367, + TEXTEMOTE_BLAME = 368, + TEXTEMOTE_BLANK = 369, + TEXTEMOTE_BRANDISH = 370, + TEXTEMOTE_BREATH = 371, + TEXTEMOTE_DISAGREE = 372, + TEXTEMOTE_DOUBT = 373, + TEXTEMOTE_EMBARRASS = 374, + TEXTEMOTE_ENCOURAGE = 375, + TEXTEMOTE_ENEMY = 376, + TEXTEMOTE_EYEBROW = 377, + TEXTEMOTE_TOAST = 378 +}; + +enum Emote +{ + EMOTE_ONESHOT_NONE = 0, + EMOTE_ONESHOT_TALK = 1, + EMOTE_ONESHOT_BOW = 2, + EMOTE_ONESHOT_WAVE = 3, + EMOTE_ONESHOT_CHEER = 4, + EMOTE_ONESHOT_EXCLAMATION = 5, + EMOTE_ONESHOT_QUESTION = 6, + EMOTE_ONESHOT_EAT = 7, + EMOTE_STATE_DANCE = 10, + EMOTE_ONESHOT_LAUGH = 11, + EMOTE_STATE_SLEEP = 12, + EMOTE_STATE_SIT = 13, + EMOTE_ONESHOT_RUDE = 14, + EMOTE_ONESHOT_ROAR = 15, + EMOTE_ONESHOT_KNEEL = 16, + EMOTE_ONESHOT_KISS = 17, + EMOTE_ONESHOT_CRY = 18, + EMOTE_ONESHOT_CHICKEN = 19, + EMOTE_ONESHOT_BEG = 20, + EMOTE_ONESHOT_APPLAUD = 21, + EMOTE_ONESHOT_SHOUT = 22, + EMOTE_ONESHOT_FLEX = 23, + EMOTE_ONESHOT_SHY = 24, + EMOTE_ONESHOT_POINT = 25, + EMOTE_STATE_STAND = 26, + EMOTE_STATE_READYUNARMED = 27, + EMOTE_STATE_WORK = 28, + EMOTE_STATE_POINT = 29, + EMOTE_STATE_NONE = 30, + EMOTE_ONESHOT_WOUND = 33, + EMOTE_ONESHOT_WOUNDCRITICAL = 34, + EMOTE_ONESHOT_ATTACKUNARMED = 35, + EMOTE_ONESHOT_ATTACK1H = 36, + EMOTE_ONESHOT_ATTACK2HTIGHT = 37, + EMOTE_ONESHOT_ATTACK2HLOOSE = 38, + EMOTE_ONESHOT_PARRYUNARMED = 39, + EMOTE_ONESHOT_PARRYSHIELD = 43, + EMOTE_ONESHOT_READYUNARMED = 44, + EMOTE_ONESHOT_READY1H = 45, + EMOTE_ONESHOT_READYBOW = 48, + EMOTE_ONESHOT_SPELLPRECAST = 50, + EMOTE_ONESHOT_SPELLCAST = 51, + EMOTE_ONESHOT_BATTLEROAR = 53, + EMOTE_ONESHOT_SPECIALATTACK1H = 54, + EMOTE_ONESHOT_KICK = 60, + EMOTE_ONESHOT_ATTACKTHROWN = 61, + EMOTE_STATE_STUN = 64, + EMOTE_STATE_DEAD = 65, + EMOTE_ONESHOT_SALUTE = 66, + EMOTE_STATE_KNEEL = 68, + EMOTE_STATE_USESTANDING = 69, + EMOTE_ONESHOT_WAVE_NOSHEATHE = 70, + EMOTE_ONESHOT_CHEER_NOSHEATHE = 71, + EMOTE_ONESHOT_EAT_NOSHEATHE = 92, + EMOTE_STATE_STUN_NOSHEATHE = 93, + EMOTE_ONESHOT_DANCE = 94, + EMOTE_ONESHOT_SALUTE_NOSHEATH = 113, + EMOTE_STATE_USESTANDING_NOSHEATHE = 133, + EMOTE_ONESHOT_LAUGH_NOSHEATHE = 153, + EMOTE_STATE_WORK_NOSHEATHE = 173, + EMOTE_STATE_SPELLPRECAST = 193, + EMOTE_ONESHOT_READYRIFLE = 213, + EMOTE_STATE_READYRIFLE = 214, + EMOTE_STATE_WORK_NOSHEATHE_MINING = 233, + EMOTE_STATE_WORK_NOSHEATHE_CHOPWOOD= 234, + EMOTE_zzOLDONESHOT_LIFTOFF = 253, + EMOTE_ONESHOT_LIFTOFF = 254, + EMOTE_ONESHOT_YES = 273, + EMOTE_ONESHOT_NO = 274, + EMOTE_ONESHOT_TRAIN = 275, + EMOTE_ONESHOT_LAND = 293, + EMOTE_STATE_AT_EASE = 313, + EMOTE_STATE_READY1H = 333, + EMOTE_STATE_SPELLKNEELSTART = 353, + EMOTE_STATE_SUBMERGED = 373, + EMOTE_ONESHOT_SUBMERGE = 374, + EMOTE_STATE_READY2H = 375, + EMOTE_STATE_READYBOW = 376, + EMOTE_ONESHOT_MOUNTSPECIAL = 377, + EMOTE_STATE_TALK = 378, + EMOTE_STATE_FISHING = 379, + EMOTE_ONESHOT_FISHING = 380, + EMOTE_ONESHOT_LOOT = 381, + EMOTE_STATE_WHIRLWIND = 382, + EMOTE_STATE_DROWNED = 383, + EMOTE_STATE_HOLD_BOW = 384, + EMOTE_STATE_HOLD_RIFLE = 385, + EMOTE_STATE_HOLD_THROWN = 386, + EMOTE_ONESHOT_DROWN = 387, + EMOTE_ONESHOT_STOMP = 388, + EMOTE_ONESHOT_ATTACKOFF = 389, + EMOTE_ONESHOT_ATTACKOFFPIERCE = 390, + EMOTE_STATE_ROAR = 391, + EMOTE_STATE_LAUGH = 392, + EMOTE_ONESHOT_CREATURE_SPECIAL = 393, + EMOTE_ONESHOT_JUMPLANDRUN = 394, + EMOTE_ONESHOT_JUMPEND = 395, + EMOTE_ONESHOT_TALK_NOSHEATHE = 396, + EMOTE_ONESHOT_POINT_NOSHEATHE = 397, + EMOTE_STATE_CANNIBALIZE = 398, + EMOTE_ONESHOT_JUMPSTART = 399, + EMOTE_STATE_DANCESPECIAL = 400, + EMOTE_ONESHOT_DANCESPECIAL = 401, + EMOTE_ONESHOT_CUSTOMSPELL01 = 402, + EMOTE_ONESHOT_CUSTOMSPELL02 = 403, + EMOTE_ONESHOT_CUSTOMSPELL03 = 404, + EMOTE_ONESHOT_CUSTOMSPELL04 = 405, + EMOTE_ONESHOT_CUSTOMSPELL05 = 406, + EMOTE_ONESHOT_CUSTOMSPELL06 = 407, + EMOTE_ONESHOT_CUSTOMSPELL07 = 408, + EMOTE_ONESHOT_CUSTOMSPELL08 = 409, + EMOTE_ONESHOT_CUSTOMSPELL09 = 410, + EMOTE_ONESHOT_CUSTOMSPELL10 = 411, + EMOTE_STATE_EXCLAIM = 412, + EMOTE_STATE_SIT_CHAIR_MED = 415, + EMOTE_STATE_SPELLEFFECT_HOLD = 422 +}; + +enum Anim +{ + ANIM_STAND = 0x0, + ANIM_DEATH = 0x1, + ANIM_SPELL = 0x2, + ANIM_STOP = 0x3, + ANIM_WALK = 0x4, + ANIM_RUN = 0x5, + ANIM_DEAD = 0x6, + ANIM_RISE = 0x7, + ANIM_STANDWOUND = 0x8, + ANIM_COMBATWOUND = 0x9, + ANIM_COMBATCRITICAL = 0xA, + ANIM_SHUFFLE_LEFT = 0xB, + ANIM_SHUFFLE_RIGHT = 0xC, + ANIM_WALK_BACKWARDS = 0xD, + ANIM_STUN = 0xE, + ANIM_HANDS_CLOSED = 0xF, + ANIM_ATTACKUNARMED = 0x10, + ANIM_ATTACK1H = 0x11, + ANIM_ATTACK2HTIGHT = 0x12, + ANIM_ATTACK2HLOOSE = 0x13, + ANIM_PARRYUNARMED = 0x14, + ANIM_PARRY1H = 0x15, + ANIM_PARRY2HTIGHT = 0x16, + ANIM_PARRY2HLOOSE = 0x17, + ANIM_PARRYSHIELD = 0x18, + ANIM_READYUNARMED = 0x19, + ANIM_READY1H = 0x1A, + ANIM_READY2HTIGHT = 0x1B, + ANIM_READY2HLOOSE = 0x1C, + ANIM_READYBOW = 0x1D, + ANIM_DODGE = 0x1E, + ANIM_SPELLPRECAST = 0x1F, + ANIM_SPELLCAST = 0x20, + ANIM_SPELLCASTAREA = 0x21, + ANIM_NPCWELCOME = 0x22, + ANIM_NPCGOODBYE = 0x23, + ANIM_BLOCK = 0x24, + ANIM_JUMPSTART = 0x25, + ANIM_JUMP = 0x26, + ANIM_JUMPEND = 0x27, + ANIM_FALL = 0x28, + ANIM_SWIMIDLE = 0x29, + ANIM_SWIM = 0x2A, + ANIM_SWIM_LEFT = 0x2B, + ANIM_SWIM_RIGHT = 0x2C, + ANIM_SWIM_BACKWARDS = 0x2D, + ANIM_ATTACKBOW = 0x2E, + ANIM_FIREBOW = 0x2F, + ANIM_READYRIFLE = 0x30, + ANIM_ATTACKRIFLE = 0x31, + ANIM_LOOT = 0x32, + ANIM_SPELL_PRECAST_DIRECTED = 0x33, + ANIM_SPELL_PRECAST_OMNI = 0x34, + ANIM_SPELL_CAST_DIRECTED = 0x35, + ANIM_SPELL_CAST_OMNI = 0x36, + ANIM_SPELL_BATTLEROAR = 0x37, + ANIM_SPELL_READYABILITY = 0x38, + ANIM_SPELL_SPECIAL1H = 0x39, + ANIM_SPELL_SPECIAL2H = 0x3A, + ANIM_SPELL_SHIELDBASH = 0x3B, + ANIM_EMOTE_TALK = 0x3C, + ANIM_EMOTE_EAT = 0x3D, + ANIM_EMOTE_WORK = 0x3E, + ANIM_EMOTE_USE_STANDING = 0x3F, + ANIM_EMOTE_EXCLAMATION = 0x40, + ANIM_EMOTE_QUESTION = 0x41, + ANIM_EMOTE_BOW = 0x42, + ANIM_EMOTE_WAVE = 0x43, + ANIM_EMOTE_CHEER = 0x44, + ANIM_EMOTE_DANCE = 0x45, + ANIM_EMOTE_LAUGH = 0x46, + ANIM_EMOTE_SLEEP = 0x47, + ANIM_EMOTE_SIT_GROUND = 0x48, + ANIM_EMOTE_RUDE = 0x49, + ANIM_EMOTE_ROAR = 0x4A, + ANIM_EMOTE_KNEEL = 0x4B, + ANIM_EMOTE_KISS = 0x4C, + ANIM_EMOTE_CRY = 0x4D, + ANIM_EMOTE_CHICKEN = 0x4E, + ANIM_EMOTE_BEG = 0x4F, + ANIM_EMOTE_APPLAUD = 0x50, + ANIM_EMOTE_SHOUT = 0x51, + ANIM_EMOTE_FLEX = 0x52, + ANIM_EMOTE_SHY = 0x53, + ANIM_EMOTE_POINT = 0x54, + ANIM_ATTACK1HPIERCE = 0x55, + ANIM_ATTACK2HLOOSEPIERCE = 0x56, + ANIM_ATTACKOFF = 0x57, + ANIM_ATTACKOFFPIERCE = 0x58, + ANIM_SHEATHE = 0x59, + ANIM_HIPSHEATHE = 0x5A, + ANIM_MOUNT = 0x5B, + ANIM_RUN_LEANRIGHT = 0x5C, + ANIM_RUN_LEANLEFT = 0x5D, + ANIM_MOUNT_SPECIAL = 0x5E, + ANIM_KICK = 0x5F, + ANIM_SITDOWN = 0x60, + ANIM_SITTING = 0x61, + ANIM_SITUP = 0x62, + ANIM_SLEEPDOWN = 0x63, + ANIM_SLEEPING = 0x64, + ANIM_SLEEPUP = 0x65, + ANIM_SITCHAIRLOW = 0x66, + ANIM_SITCHAIRMEDIUM = 0x67, + ANIM_SITCHAIRHIGH = 0x68, + ANIM_LOADBOW = 0x69, + ANIM_LOADRIFLE = 0x6A, + ANIM_ATTACKTHROWN = 0x6B, + ANIM_READYTHROWN = 0x6C, + ANIM_HOLDBOW = 0x6D, + ANIM_HOLDRIFLE = 0x6E, + ANIM_HOLDTHROWN = 0x6F, + ANIM_LOADTHROWN = 0x70, + ANIM_EMOTE_SALUTE = 0x71, + ANIM_KNEELDOWN = 0x72, + ANIM_KNEELING = 0x73, + ANIM_KNEELUP = 0x74, + ANIM_ATTACKUNARMEDOFF = 0x75, + ANIM_SPECIALUNARMED = 0x76, + ANIM_STEALTHWALK = 0x77, + ANIM_STEALTHSTAND = 0x78, + ANIM_KNOCKDOWN = 0x79, + ANIM_EATING = 0x7A, + ANIM_USESTANDINGLOOP = 0x7B, + ANIM_CHANNELCASTDIRECTED = 0x7C, + ANIM_CHANNELCASTOMNI = 0x7D, + ANIM_WHIRLWIND = 0x7E, + ANIM_BIRTH = 0x7F, + ANIM_USESTANDINGSTART = 0x80, + ANIM_USESTANDINGEND = 0x81, + ANIM_HOWL = 0x82, + ANIM_DROWN = 0x83, + ANIM_DROWNED = 0x84, + ANIM_FISHINGCAST = 0x85, + ANIM_FISHINGLOOP = 0x86, + ANIM_FLY = 0x87, + ANIM_EMOTE_WORK_NO_SHEATHE = 0x88, + ANIM_EMOTE_STUN_NO_SHEATHE = 0x89, + ANIM_EMOTE_USE_STANDING_NO_SHEATHE= 0x8A, + ANIM_SPELL_SLEEP_DOWN = 0x8B, + ANIM_SPELL_KNEEL_START = 0x8C, + ANIM_SPELL_KNEEL_LOOP = 0x8D, + ANIM_SPELL_KNEEL_END = 0x8E, + ANIM_SPRINT = 0x8F, + ANIM_IN_FIGHT = 0x90, + + ANIM_GAMEOBJ_SPAWN = 145, + ANIM_GAMEOBJ_CLOSE = 146, + ANIM_GAMEOBJ_CLOSED = 147, + ANIM_GAMEOBJ_OPEN = 148, + ANIM_GAMEOBJ_OPENED = 149, + ANIM_GAMEOBJ_DESTROY = 150, + ANIM_GAMEOBJ_DESTROYED = 151, + ANIM_GAMEOBJ_REBUILD = 152, + ANIM_GAMEOBJ_CUSTOM0 = 153, + ANIM_GAMEOBJ_CUSTOM1 = 154, + ANIM_GAMEOBJ_CUSTOM2 = 155, + ANIM_GAMEOBJ_CUSTOM3 = 156, + ANIM_GAMEOBJ_DESPAWN = 157, + ANIM_HOLD = 158, + ANIM_DECAY = 159, + ANIM_BOWPULL = 160, + ANIM_BOWRELEASE = 161, + ANIM_SHIPSTART = 162, + ANIM_SHIPMOVEING = 163, + ANIM_SHIPSTOP = 164, + ANIM_GROUPARROW = 165, + ANIM_ARROW = 166, + ANIM_CORPSEARROW = 167, + ANIM_GUIDEARROW = 168, + ANIM_SWAY = 169, + ANIM_DRUIDCATPOUNCE = 170, + ANIM_DRUIDCATRIP = 171, + ANIM_DRUIDCATRAKE = 172, + ANIM_DRUIDCATRAVAGE = 173, + ANIM_DRUIDCATCLAW = 174, + ANIM_DRUIDCATCOWER = 175, + ANIM_DRUIDBEARSWIPE = 176, + ANIM_DRUIDBEARBITE = 177, + ANIM_DRUIDBEARMAUL = 178, + ANIM_DRUIDBEARBASH = 179, + ANIM_DRAGONTAIL = 180, + ANIM_DRAGONSTOMP = 181, + ANIM_DRAGONSPIT = 182, + ANIM_DRAGONSPITHOVER = 183, + ANIM_DRAGONSPITFLY = 184, + ANIM_EMOTEYES = 185, + ANIM_EMOTENO = 186, + ANIM_JUMPLANDRUN = 187, + ANIM_LOOTHOLD = 188, + ANIM_LOOTUP = 189, + ANIM_STANDHIGH = 190, + ANIM_IMPACT = 191, + ANIM_LIFTOFF = 192, + ANIM_HOVER = 193, + ANIM_SUCCUBUSENTICE = 194, + ANIM_EMOTETRAIN = 195, + ANIM_EMOTEDEAD = 196, + ANIM_EMOTEDANCEONCE = 197, + ANIM_DEFLECT = 198, + ANIM_EMOTEEATNOSHEATHE = 199, + ANIM_LAND = 200, + ANIM_SUBMERGE = 201, + ANIM_SUBMERGED = 202, + ANIM_CANNIBALIZE = 203, + ANIM_ARROWBIRTH = 204, + ANIM_GROURARROWBIRTH = 205, + ANIM_CORPSEARROWBIRTH = 206, + ANIM_GUIDEARROWBIRTH = 207, + ANIM_EMOTETALKNOSHEATHE = 208, + ANIM_EMOTEPOINTNOSHEATHE = 209, + ANIM_EMOTESALUTENOSHEATHE = 210, + ANIM_EMOTEDANCESPECIAL = 211, + ANIM_MUTILATE = 212, + ANIM_CUSTOMSPELL01 = 213, + ANIM_CUSTOMSPELL02 = 214, + ANIM_CUSTOMSPELL03 = 215, + ANIM_CUSTOMSPELL04 = 216, + ANIM_CUSTOMSPELL05 = 217, + ANIM_CUSTOMSPELL06 = 218, + ANIM_CUSTOMSPELL07 = 219, + ANIM_CUSTOMSPELL08 = 220, + ANIM_CUSTOMSPELL09 = 221, + ANIM_CUSTOMSPELL10 = 222, + ANIM_StealthRun = 223 +}; + +enum LockKeyType +{ + LOCK_KEY_NONE = 0, + LOCK_KEY_ITEM = 1, + LOCK_KEY_SKILL = 2 +}; + +enum LockType +{ + LOCKTYPE_PICKLOCK = 1, + LOCKTYPE_HERBALISM = 2, + LOCKTYPE_MINING = 3, + LOCKTYPE_DISARM_TRAP = 4, + LOCKTYPE_OPEN = 5, + LOCKTYPE_TREASURE = 6, + LOCKTYPE_CALCIFIED_ELVEN_GEMS = 7, + LOCKTYPE_CLOSE = 8, + LOCKTYPE_ARM_TRAP = 9, + LOCKTYPE_QUICK_OPEN = 10, + LOCKTYPE_QUICK_CLOSE = 11, + LOCKTYPE_OPEN_TINKERING = 12, + LOCKTYPE_OPEN_KNEELING = 13, + LOCKTYPE_OPEN_ATTACKING = 14, + LOCKTYPE_GAHZRIDIAN = 15, + LOCKTYPE_BLASTING = 16, + LOCKTYPE_SLOW_OPEN = 17, + LOCKTYPE_SLOW_CLOSE = 18, + LOCKTYPE_FISHING = 19 +}; + +enum TrainerType // this is important type for npcs! +{ + TRAINER_TYPE_CLASS = 0, + TRAINER_TYPE_MOUNTS = 1, // on blizz it's 2 + TRAINER_TYPE_TRADESKILLS = 2, + TRAINER_TYPE_PETS = 3 +}; + +#define MAX_TRAINER_TYPE 4 + +enum CreatureType +{ + CREATURE_TYPE_BEAST = 1, + CREATURE_TYPE_DRAGON = 2, + CREATURE_TYPE_DEMON = 3, + CREATURE_TYPE_ELEMENTAL = 4, + CREATURE_TYPE_GIANT = 5, + CREATURE_TYPE_UNDEAD = 6, + CREATURE_TYPE_HUMANOID = 7, + CREATURE_TYPE_CRITTER = 8, + CREATURE_TYPE_MECHANICAL = 9, + CREATURE_TYPE_NOTSPECIFIED = 10, + CREATURE_TYPE_TOTEM = 11, + CREATURE_TYPE_NON_COMBAT_PET = 12, + CREATURE_TYPE_GAS_CLOUD = 13 +}; + +uint32 const CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD = (1 << (CREATURE_TYPE_HUMANOID-1)) | (1 << (CREATURE_TYPE_UNDEAD-1)); + +enum CreatureFamily +{ + CREATURE_FAMILY_WOLF = 1, + CREATURE_FAMILY_CAT = 2, + CREATURE_FAMILY_SPIDER = 3, + CREATURE_FAMILY_BEAR = 4, + CREATURE_FAMILY_BOAR = 5, + CREATURE_FAMILY_CROCILISK = 6, + CREATURE_FAMILY_CARRION_BIRD = 7, + CREATURE_FAMILY_CRAB = 8, + CREATURE_FAMILY_GORILLA = 9, + CREATURE_FAMILY_RAPTOR = 11, + CREATURE_FAMILY_TALLSTRIDER = 12, + CREATURE_FAMILY_FELHUNTER = 15, + CREATURE_FAMILY_VOIDWALKER = 16, + CREATURE_FAMILY_SUCCUBUS = 17, + CREATURE_FAMILY_DOOMGUARD = 19, + CREATURE_FAMILY_SCORPID = 20, + CREATURE_FAMILY_TURTLE = 21, + CREATURE_FAMILY_IMP = 23, + CREATURE_FAMILY_BAT = 24, + CREATURE_FAMILY_HYENA = 25, + CREATURE_FAMILY_OWL = 26, + CREATURE_FAMILY_WIND_SERPENT = 27, + CREATURE_FAMILY_REMOTE_CONTROL = 28, + CREATURE_FAMILY_FELGUARD = 29, + CREATURE_FAMILY_DRAGONHAWK = 30, + CREATURE_FAMILY_RAVAGER = 31, + CREATURE_FAMILY_WARP_STALKER = 32, + CREATURE_FAMILY_SPOREBAT = 33, + CREATURE_FAMILY_NETHER_RAY = 34, + CREATURE_FAMILY_SERPENT = 35, + CREATURE_FAMILY_SEA_LION = 36 +}; + +enum CreatureEliteType +{ + CREATURE_ELITE_NORMAL = 0, + CREATURE_ELITE_ELITE = 1, + CREATURE_ELITE_RAREELITE = 2, + CREATURE_ELITE_WORLDBOSS = 3, + CREATURE_ELITE_RARE = 4, + CREATURE_UNKNOWN = 5 // found in 2.2.3 for 2 mobs +}; + +// values based at QuestInfo.dbc +enum QuestTypes +{ + QUEST_TYPE_ELITE = 1, + QUEST_TYPE_LIFE = 21, + QUEST_TYPE_PVP = 41, + QUEST_TYPE_RAID = 62, + QUEST_TYPE_DUNGEON = 81, + QUEST_TYPE_WORLD_EVENT = 82, + QUEST_TYPE_LEGENDARY = 83, + QUEST_TYPE_ESCORT = 84, + QUEST_TYPE_HEROIC = 85, +}; + +// values based at QuestSort.dbc +enum QuestSort +{ + QUEST_SORT_EPIC = 1, + QUEST_SORT_WAILING_CAVERNS_OLD = 21, + QUEST_SORT_SEASONAL = 22, + QUEST_SORT_UNDERCITY_OLD = 23, + QUEST_SORT_HERBALISM = 24, + QUEST_SORT_SCARLET_MONASTERY_OLD= 25, + QUEST_SORT_ULDAMN_OLD = 41, + QUEST_SORT_WARLOCK = 61, + QUEST_SORT_WARRIOR = 81, + QUEST_SORT_SHAMAN = 82, + QUEST_SORT_FISHING = 101, + QUEST_SORT_BLACKSMITHING = 121, + QUEST_SORT_PALADIN = 141, + QUEST_SORT_MAGE = 161, + QUEST_SORT_ROGUE = 162, + QUEST_SORT_ALCHEMY = 181, + QUEST_SORT_LEATHERWORKING = 182, + QUEST_SORT_ENGINERING = 201, + QUEST_SORT_TREASURE_MAP = 221, + QUEST_SORT_SUNKEN_TEMPLE_OLD = 241, + QUEST_SORT_HUNTER = 261, + QUEST_SORT_PRIEST = 262, + QUEST_SORT_DRUID = 263, + QUEST_SORT_TAILORING = 264, + QUEST_SORT_SPECIAL = 284, + QUEST_SORT_COOKING = 304, + QUEST_SORT_FIRST_AID = 324, + QUEST_SORT_LEGENDARY = 344, + QUEST_SORT_DARKMOON_FAIRE = 364, + QUEST_SORT_AHN_QIRAJ_WAR = 365, + QUEST_SORT_LUNAR_FESTIVAL = 366, + QUEST_SORT_REPUTATION = 367, + QUEST_SORT_INVASION = 368, + QUEST_SORT_MIDSUMMER = 369, + QUEST_SORT_BREWFEST = 370 +}; + +inline uint8 ClassByQuestSort(int32 QuestSort) +{ + switch(QuestSort) + { + case QUEST_SORT_WARLOCK: return CLASS_WARLOCK; + case QUEST_SORT_WARRIOR: return CLASS_WARRIOR; + case QUEST_SORT_SHAMAN: return CLASS_SHAMAN; + case QUEST_SORT_PALADIN: return CLASS_PALADIN; + case QUEST_SORT_MAGE: return CLASS_MAGE; + case QUEST_SORT_ROGUE: return CLASS_ROGUE; + case QUEST_SORT_HUNTER: return CLASS_HUNTER; + case QUEST_SORT_PRIEST: return CLASS_PRIEST; + case QUEST_SORT_DRUID: return CLASS_DRUID; + } + return 0; +} + +enum SkillType +{ + SKILL_FROST = 6, + SKILL_FIRE = 8, + SKILL_ARMS = 26, + SKILL_COMBAT = 38, + SKILL_SUBTLETY = 39, + SKILL_POISONS = 40, + SKILL_SWORDS = 43, + SKILL_AXES = 44, + SKILL_BOWS = 45, + SKILL_GUNS = 46, + SKILL_BEAST_MASTERY = 50, + SKILL_SURVIVAL = 51, + SKILL_MACES = 54, + SKILL_HOLY = 56, + SKILL_2H_SWORDS = 55, + SKILL_SHADOW = 78, + SKILL_DEFENSE = 95, + SKILL_LANG_COMMON = 98, + SKILL_RACIAL_DWARVEN = 101, + SKILL_LANG_ORCISH = 109, + SKILL_LANG_DWARVEN = 111, + SKILL_LANG_DARNASSIAN = 113, + SKILL_LANG_TAURAHE = 115, + SKILL_DUAL_WIELD = 118, + SKILL_RACIAL_TAUREN = 124, + SKILL_ORC_RACIAL = 125, + SKILL_RACIAL_NIGHT_ELF = 126, + SKILL_FIRST_AID = 129, + SKILL_FERAL_COMBAT = 134, + SKILL_STAVES = 136, + SKILL_LANG_THALASSIAN = 137, + SKILL_LANG_DRACONIC = 138, + SKILL_LANG_DEMON_TONGUE = 139, + SKILL_LANG_TITAN = 140, + SKILL_LANG_OLD_TONGUE = 141, + SKILL_SURVIVAL2 = 142, + SKILL_RIDING_HORSE = 148, + SKILL_RIDING_WOLF = 149, + SKILL_RIDING_RAM = 152, + SKILL_RIDING_TIGER = 150, + SKILL_SWIMING = 155, + SKILL_2H_MACES = 160, + SKILL_UNARMED = 162, + SKILL_MARKSMANSHIP = 163, + SKILL_BLACKSMITHING = 164, + SKILL_LEATHERWORKING = 165, + SKILL_ALCHEMY = 171, + SKILL_2H_AXES = 172, + SKILL_DAGGERS = 173, + SKILL_THROWN = 176, + SKILL_HERBALISM = 182, + SKILL_GENERIC_DND = 183, + SKILL_RETRIBUTION = 184, + SKILL_COOKING = 185, + SKILL_MINING = 186, + SKILL_PET_IMP = 188, + SKILL_PET_FELHUNTER = 189, + SKILL_TAILORING = 197, + SKILL_ENGINERING = 202, + SKILL_PET_SPIDER = 203, + SKILL_PET_VOIDWALKER = 204, + SKILL_PET_SUCCUBUS = 205, + SKILL_PET_INFERNAL = 206, + SKILL_PET_DOOMGUARD = 207, + SKILL_PET_WOLF = 208, + SKILL_PET_CAT = 209, + SKILL_PET_BEAR = 210, + SKILL_PET_BOAR = 211, + SKILL_PET_CROCILISK = 212, + SKILL_PET_CARRION_BIRD = 213, + SKILL_PET_GORILLA = 215, + SKILL_PET_CRAB = 214, + SKILL_PET_RAPTOR = 217, + SKILL_PET_TALLSTRIDER = 218, + SKILL_RACIAL_UNDED = 220, + SKILL_WEAPON_TALENTS = 222, + SKILL_CROSSBOWS = 226, + SKILL_SPEARS = 227, + SKILL_WANDS = 228, + SKILL_POLEARMS = 229, + SKILL_PET_SCORPID = 236, + SKILL_ARCANE = 237, + SKILL_OPEN_LOCK = 242, + SKILL_PET_TURTLE = 251, + SKILL_ASSASSINATION = 253, + SKILL_FURY = 256, + SKILL_PROTECTION = 257, + SKILL_BEAST_TRAINING = 261, + SKILL_PROTECTION2 = 267, + SKILL_PET_TALENTS = 270, + SKILL_PLATE_MAIL = 293, + SKILL_LANG_GNOMISH = 313, + SKILL_LANG_TROLL = 315, + SKILL_ENCHANTING = 333, + SKILL_DEMONOLOGY = 354, + SKILL_AFFLICTION = 355, + SKILL_FISHING = 356, + SKILL_ENHANCEMENT = 373, + SKILL_RESTORATION = 374, + SKILL_ELEMENTAL_COMBAT = 375, + SKILL_SKINNING = 393, + SKILL_MAIL = 413, + SKILL_LEATHER = 414, + SKILL_CLOTH = 415, + SKILL_SHIELD = 433, + SKILL_FIST_WEAPONS = 473, + SKILL_RIDING_RAPTOR = 533, + SKILL_RIDING_MECHANOSTRIDER = 553, + SKILL_RIDING_UNDEAD_HORSE = 554, + SKILL_RESTORATION2 = 573, + SKILL_BALANCE = 574, + SKILL_DESTRUCTION = 593, + SKILL_HOLY2 = 594, + SKILL_DISCIPLINE = 613, + SKILL_LOCKPICKING = 633, + SKILL_PET_BAT = 653, + SKILL_PET_HYENA = 654, + SKILL_PET_OWL = 655, + SKILL_PET_WIND_SERPENT = 656, + SKILL_LANG_GUTTERSPEAK = 673, + SKILL_RIDING_KODO = 713, + SKILL_RACIAL_TROLL = 733, + SKILL_RACIAL_GNOME = 753, + SKILL_RACIAL_HUMAN = 754, + SKILL_JEWELCRAFTING = 755, + SKILL_RACIAL_BLOODELF = 756, + SKILL_PET_EVENT_RC = 758, + SKILL_LANG_DRAENEI = 759, + SKILL_RACIAL_DRAENEI = 760, + SKILL_PET_FELGUARD = 761, + SKILL_RIDING = 762, + SKILL_PET_DRAGONHAWK = 763, + SKILL_PET_NETHER_RAY = 764, + SKILL_PET_SPOREBAT = 765, + SKILL_PET_WARP_STALKER = 766, + SKILL_PET_RAVAGER = 767, + SKILL_PET_SERPENT = 768, + SKILL_INTERNAL = 769 +}; + +#define MAX_SKILL_TYPE 770 + +inline uint32 SkillByQuestSort(int32 QuestSort) +{ + switch(QuestSort) + { + case QUEST_SORT_HERBALISM: return SKILL_HERBALISM; + case QUEST_SORT_FISHING: return SKILL_FISHING; + case QUEST_SORT_BLACKSMITHING: return SKILL_BLACKSMITHING; + case QUEST_SORT_ALCHEMY: return SKILL_ALCHEMY; + case QUEST_SORT_LEATHERWORKING: return SKILL_LEATHERWORKING; + case QUEST_SORT_ENGINERING: return SKILL_ENGINERING; + case QUEST_SORT_TAILORING: return SKILL_TAILORING; + case QUEST_SORT_COOKING: return SKILL_COOKING; + case QUEST_SORT_FIRST_AID: return SKILL_FIRST_AID; + } + return 0; +} + +enum SkillCategory +{ + SKILL_CATEGORY_ATTRIBUTES = 5, + SKILL_CATEGORY_WEAPON = 6, + SKILL_CATEGORY_CLASS = 7, + SKILL_CATEGORY_ARMOR = 8, + SKILL_CATEGORY_SECONDARY = 9, // secondary professions + SKILL_CATEGORY_LANGUAGES = 10, + SKILL_CATEGORY_PROFESSION = 11, // primary professions + SKILL_CATEGORY_NOT_DISPLAYED = 12 +}; + +enum TotemCategory +{ + TC_SKINNING_SKIFE = 1, + TC_EARTH_TOTEM = 2, + TC_AIR_TOTEM = 3, + TC_FIRE_TOTEM = 4, + TC_WATER_TOTEM = 5, + TC_COPPER_ROD = 6, + TC_SILVER_ROD = 7, + TC_GOLDEN_ROD = 8, + TC_TRUESILVER_ROD = 9, + TC_ARCANITE_ROD = 10, + TC_MINING_PICK = 11, + TC_PHILOSOPHERS_STONE = 12, + TC_BLACKSMITH_HAMMER = 13, + TC_ARCLIGHT_SPANNER = 14, + TC_GYROMATIC_MA = 15, + TC_MASTER_TOTEM = 21, + TC_FEL_IRON_ROD = 41, + TC_ADAMANTITE_ROD = 62, + TC_ETERNIUM_ROD = 63 +}; + +enum UnitDynFlags +{ + UNIT_DYNFLAG_LOOTABLE = 0x0001, + UNIT_DYNFLAG_TRACK_UNIT = 0x0002, + UNIT_DYNFLAG_OTHER_TAGGER = 0x0004, + UNIT_DYNFLAG_ROOTED = 0x0008, + UNIT_DYNFLAG_SPECIALINFO = 0x0010, + UNIT_DYNFLAG_DEAD = 0x0020 +}; + +enum CorpseDynFlags +{ + CORPSE_DYNFLAG_LOOTABLE = 0x0001 +}; + +// Passive Spell codes explicit used in code +#define SPELL_ID_GENERIC_LEARN 483 +#define SPELL_ID_PASSIVE_BATTLE_STANCE 2457 +#define SPELL_ID_PASSIVE_RESURRECTION_SICKNESS 15007 + +enum WeatherType +{ + WEATHER_TYPE_FINE = 0, + WEATHER_TYPE_RAIN = 1, + WEATHER_TYPE_SNOW = 2, + WEATHER_TYPE_STORM = 3, + WEATHER_TYPE_THUNDERS = 86, + WEATHER_TYPE_BLACKRAIN = 90 +}; + +#define MAX_WEATHER_TYPE 4 + +enum ChatMsg +{ + CHAT_MSG_ADDON = 0xFFFFFFFF, + CHAT_MSG_SYSTEM = 0x00, + CHAT_MSG_SAY = 0x01, + CHAT_MSG_PARTY = 0x02, + CHAT_MSG_RAID = 0x03, + CHAT_MSG_GUILD = 0x04, + CHAT_MSG_OFFICER = 0x05, + CHAT_MSG_YELL = 0x06, + CHAT_MSG_WHISPER = 0x07, + CHAT_MSG_WHISPER_INFORM = 0x08, + CHAT_MSG_REPLY = 0x09, + CHAT_MSG_EMOTE = 0x0A, + CHAT_MSG_TEXT_EMOTE = 0x0B, + CHAT_MSG_MONSTER_SAY = 0x0C, + CHAT_MSG_MONSTER_PARTY = 0x0D, + CHAT_MSG_MONSTER_YELL = 0x0E, + CHAT_MSG_MONSTER_WHISPER = 0x0F, + CHAT_MSG_MONSTER_EMOTE = 0x10, + CHAT_MSG_CHANNEL = 0x11, + CHAT_MSG_CHANNEL_JOIN = 0x12, + CHAT_MSG_CHANNEL_LEAVE = 0x13, + CHAT_MSG_CHANNEL_LIST = 0x14, + CHAT_MSG_CHANNEL_NOTICE = 0x15, + CHAT_MSG_CHANNEL_NOTICE_USER = 0x16, + CHAT_MSG_AFK = 0x17, + CHAT_MSG_DND = 0x18, + CHAT_MSG_IGNORED = 0x19, + CHAT_MSG_SKILL = 0x1A, + CHAT_MSG_LOOT = 0x1B, + CHAT_MSG_MONEY = 0x1C, + CHAT_MSG_OPENING = 0x1D, + CHAT_MSG_TRADESKILLS = 0x1E, + CHAT_MSG_PET_INFO = 0x1F, + CHAT_MSG_COMBAT_MISC_INFO = 0x20, + CHAT_MSG_COMBAT_XP_GAIN = 0x21, + CHAT_MSG_COMBAT_HONOR_GAIN = 0x22, + CHAT_MSG_COMBAT_FACTION_CHANGE = 0x23, + CHAT_MSG_BG_SYSTEM_NEUTRAL = 0x24, + CHAT_MSG_BG_SYSTEM_ALLIANCE = 0x25, + CHAT_MSG_BG_SYSTEM_HORDE = 0x26, + CHAT_MSG_RAID_LEADER = 0x27, + CHAT_MSG_RAID_WARNING = 0x28, + CHAT_MSG_RAID_BOSS_WHISPER = 0x29, + CHAT_MSG_RAID_BOSS_EMOTE = 0x2A, + CHAT_MSG_FILTERED = 0x2B, + CHAT_MSG_BATTLEGROUND = 0x2C, + CHAT_MSG_BATTLEGROUND_LEADER = 0x2D, + CHAT_MSG_RESTRICTED = 0x2E, +}; + +#define MAX_CHAT_MSG_TYPE 0x2F + +// Values from ItemPetFood (power of (value-1) used for compare with CreatureFamilyEntry.petDietMask +enum PetDiet +{ + PET_DIET_MEAT = 1, + PET_DIET_FISH = 2, + PET_DIET_CHEESE = 3, + PET_DIET_BREAD = 4, + PET_DIET_FUNGAS = 5, + PET_DIET_FRUIT = 6, + PET_DIET_RAW_MEAT = 7, + PET_DIET_RAW_FISH = 8 +}; + +#define MAX_PET_DIET 9 + +#define CHAIN_SPELL_JUMP_RADIUS 10 + +// Max values for Guild & Guild Bank +#define GUILD_BANK_MAX_TABS 6 +#define GUILD_BANK_MAX_SLOTS 98 +#define GUILD_BANK_MAX_LOGS 24 +#define GUILD_EVENTLOG_MAX_ENTRIES 100 +#define GUILD_MAX_RANKS 10 + +enum AiReaction +{ + AI_REACTION_UNK1 = 1, + AI_REACTION_AGGRO = 2, + AI_REACTION_UNK3 = 3, + AI_REACTION_UNK4 = 4 +}; + +// Diminishing Returns Types +enum DiminishingReturnsType +{ + DRTYPE_NONE = 0, // this spell is not diminished, but may have limited it's duration to 10s + DRTYPE_PLAYER = 1, // this spell is diminished only when applied on players + DRTYPE_ALL = 2 // this spell is diminished in every case +}; + +// Diminishing Return Groups +enum DiminishingGroup +{ + // Common Groups + DIMINISHING_NONE, + DIMINISHING_CONTROL_STUN, // Player Controlled stuns + DIMINISHING_TRIGGER_STUN, // By aura proced stuns, usualy chance on hit talents + DIMINISHING_SLEEP, + DIMINISHING_CONTROL_ROOT, // Immobilizing effects from casted spells + DIMINISHING_TRIGGER_ROOT, // Immobilizing effects from triggered spells like Frostbite + DIMINISHING_FEAR, // Non-warlock fears + DIMINISHING_CHARM, + // Mage Specific + DIMINISHING_POLYMORPH, + // Rogue Specific + DIMINISHING_KIDNEYSHOT, // Kidney Shot is not diminished with Cheap Shot + // Warlock Specific + DIMINISHING_DEATHCOIL, // Death Coil Diminish only with another Death Coil + DIMINISHING_WARLOCK_FEAR, // Also with Sedduction + // Shared Class Specific + DIMINISHING_BLIND_CYCLONE, // From 2.3.0 + DIMINISHING_DISARM, // From 2.3.0 + DIMINISHING_SILENCE, // From 2.3.0 + DIMINISHING_FREEZE, // Hunter's Freezing Trap + DIMINISHING_KNOCKOUT, // Also with Sap, all Knockout mechanics are here + DIMINISHING_BANISH, + // Other + // Don't Diminish, but limit duration to 10s + DIMINISHING_LIMITONLY +}; + +enum DungeonDifficulties +{ + DIFFICULTY_NORMAL = 0, + DIFFICULTY_HEROIC = 1, + TOTAL_DIFFICULTIES +}; + +enum SummonType +{ + SUMMON_TYPE_CRITTER = 41, + SUMMON_TYPE_GUARDIAN = 61, + SUMMON_TYPE_TOTEM_SLOT1 = 63, + SUMMON_TYPE_WILD = 64, + SUMMON_TYPE_POSESSED = 65, + SUMMON_TYPE_DEMON = 66, + SUMMON_TYPE_SUMMON = 67, + SUMMON_TYPE_TOTEM_SLOT2 = 81, + SUMMON_TYPE_TOTEM_SLOT3 = 82, + SUMMON_TYPE_TOTEM_SLOT4 = 83, + SUMMON_TYPE_TOTEM = 121, + SUMMON_TYPE_UNKNOWN3 = 181, + SUMMON_TYPE_UNKNOWN4 = 187, + SUMMON_TYPE_UNKNOWN1 = 247, + SUMMON_TYPE_UNKNOWN5 = 307, + SUMMON_TYPE_CRITTER2 = 407, + SUMMON_TYPE_UNKNOWN6 = 409, + SUMMON_TYPE_UNKNOWN2 = 427, + SUMMON_TYPE_POSESSED2 = 428 +}; +#endif diff --git a/src/game/SkillDiscovery.cpp b/src/game/SkillDiscovery.cpp new file mode 100644 index 00000000000..388d06ad184 --- /dev/null +++ b/src/game/SkillDiscovery.cpp @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Database/DatabaseEnv.h" +#include "Log.h" +#include "ProgressBar.h" +#include "Policies/SingletonImp.h" +#include "ObjectAccessor.h" +#include "World.h" +#include "Util.h" +#include "SkillDiscovery.h" +#include "SpellMgr.h" +#include + +struct SkillDiscoveryEntry +{ + uint32 spellId; + float chance; + + SkillDiscoveryEntry() + : spellId(0), chance(0) {} + + SkillDiscoveryEntry(uint16 _spellId, float _chance) + : spellId(_spellId), chance(_chance) {} +}; + +typedef std::list SkillDiscoveryList; +typedef HM_NAMESPACE::hash_map SkillDiscoveryMap; + +static SkillDiscoveryMap SkillDiscoveryStore; + +void LoadSkillDiscoveryTable() +{ + + SkillDiscoveryStore.clear(); // need for reload + + uint32 count = 0; + + // 0 1 2 + QueryResult *result = WorldDatabase.PQuery("SELECT spellId, reqSpell, chance FROM skill_discovery_template"); + + if (result) + { + barGoLink bar(result->GetRowCount()); + + std::ostringstream ssNonDiscoverableEntries; + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 spellId = fields[0].GetUInt32(); + int32 reqSkillOrSpell = fields[1].GetInt32(); + float chance = fields[2].GetFloat(); + + if( chance <= 0 ) // chance + { + ssNonDiscoverableEntries << "spellId = " << spellId << " reqSkillOrSpell = " << reqSkillOrSpell << " chance = " << chance << "\n"; + continue; + } + + if(reqSkillOrSpell > 0) // spell case + { + SpellEntry const* spellEntry = sSpellStore.LookupEntry(reqSkillOrSpell); + if( !spellEntry ) + { + sLog.outErrorDb("Spell (ID: %u) have not existed spell (ID: %i) in `reqSpell` field in `skill_discovery_template` table",spellId,reqSkillOrSpell); + continue; + } + + if( spellEntry->Mechanic != MECHANIC_DISCOVERY ) + { + sLog.outErrorDb("Spell (ID: %u) not have have MECHANIC_DISCOVERY (28) value in Mechanic field in spell.dbc but listed in `skill_discovery_template` table",spellId); + continue; + } + + SkillDiscoveryStore[reqSkillOrSpell].push_back( SkillDiscoveryEntry(spellId, chance) ); + } + else if( reqSkillOrSpell == 0 ) // skill case + { + SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(spellId); + SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(spellId); + + if(lower==upper) + { + sLog.outErrorDb("Spell (ID: %u) not listed in `SkillLineAbility.dbc` but listed with `reqSpell`=0 in `skill_discovery_template` table",spellId); + continue; + } + + for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx) + { + SkillDiscoveryStore[-int32(_spell_idx->second->skillId)].push_back( SkillDiscoveryEntry(spellId, chance) ); + } + } + else + { + sLog.outErrorDb("Spell (ID: %u) have negative value in `reqSpell` field in `skill_discovery_template` table",spellId); + continue; + } + ++count; + } while (result->NextRow()); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u skill discovery definitions", count ); + if(!ssNonDiscoverableEntries.str().empty()) + sLog.outErrorDb("Some items can't be successfully discovered: have in chance field value < 0.000001 in `skill_discovery_template` DB table . List:\n%s",ssNonDiscoverableEntries.str().c_str()); + } + else + { + sLog.outString(); + sLog.outString( ">> Loaded 0 skill discovery definitions. DB table `skill_discovery_template` is empty." ); + } +} + +uint32 GetSkillDiscoverySpell(uint32 skillId, uint32 spellId, Player* player) +{ + // check spell case + SkillDiscoveryMap::iterator tab = SkillDiscoveryStore.find(spellId); + + if(tab != SkillDiscoveryStore.end()) + { + for(SkillDiscoveryList::iterator item_iter = tab->second.begin(); item_iter != tab->second.end(); ++item_iter) + { + if( roll_chance_f(item_iter->chance * sWorld.getRate(RATE_SKILL_DISCOVERY)) + && !player->HasSpell(item_iter->spellId) ) + return item_iter->spellId; + } + + return 0; + } + + // check skill line case + tab = SkillDiscoveryStore.find(-(int32)skillId); + if(tab != SkillDiscoveryStore.end()) + { + for(SkillDiscoveryList::iterator item_iter = tab->second.begin(); item_iter != tab->second.end(); ++item_iter) + { + if( roll_chance_f(item_iter->chance * sWorld.getRate(RATE_SKILL_DISCOVERY)) + && !player->HasSpell(item_iter->spellId) ) + return item_iter->spellId; + } + + return 0; + } + + return 0; +} diff --git a/src/game/SkillDiscovery.h b/src/game/SkillDiscovery.h new file mode 100644 index 00000000000..6a7a16c3849 --- /dev/null +++ b/src/game/SkillDiscovery.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_SKILLDISCOVERY_H +#define MANGOS_SKILLDISCOVERY_H + +#include "Common.h" + +class Player; + +void LoadSkillDiscoveryTable(); +uint32 GetSkillDiscoverySpell(uint32 skillId, uint32 spellId, Player* player); +#endif diff --git a/src/game/SkillExtraItems.cpp b/src/game/SkillExtraItems.cpp new file mode 100644 index 00000000000..42e465be41d --- /dev/null +++ b/src/game/SkillExtraItems.cpp @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "SkillExtraItems.h" +#include "Database/DatabaseEnv.h" +#include "Log.h" +#include "ProgressBar.h" +#include "Player.h" +#include + +// some type definitions +// no use putting them in the header file, they're only used in this .cpp + +// struct to store information about extra item creation +// one entry for every spell that is able to create an extra item +struct SkillExtraItemEntry +{ + // the spell id of the specialization required to create extra items + uint32 requiredSpecialization; + // the chance to create one additional item + float additionalCreateChance; + // maximum number of extra items created per crafting + uint8 additionalMaxNum; + + SkillExtraItemEntry() + : requiredSpecialization(0), additionalCreateChance(0.0f), additionalMaxNum(0) {} + + SkillExtraItemEntry(uint32 rS, float aCC, uint8 aMN) + : requiredSpecialization(rS), additionalCreateChance(aCC), additionalMaxNum(aMN) {} +}; + +// map to store the extra item creation info, the key is the spellId of the creation spell, the mapped value is the assigned SkillExtraItemEntry +typedef std::map SkillExtraItemMap; + +SkillExtraItemMap SkillExtraItemStore; + +// loads the extra item creation info from DB +void LoadSkillExtraItemTable() +{ + uint32 count = 0; + + SkillExtraItemStore.clear(); // need for reload + + // 0 1 2 3 + QueryResult *result = WorldDatabase.PQuery("SELECT spellId, requiredSpecialization, additionalCreateChance, additionalMaxNum FROM skill_extra_item_template"); + + if (result) + { + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 spellId = fields[0].GetUInt32(); + + if(!sSpellStore.LookupEntry(spellId)) + { + sLog.outError("Skill specialization %u has non-existent spell id in `skill_extra_item_template`!", spellId); + continue; + } + + uint32 requiredSpecialization = fields[1].GetUInt32(); + if(!sSpellStore.LookupEntry(requiredSpecialization)) + { + sLog.outError("Skill specialization %u have not existed required specialization spell id %u in `skill_extra_item_template`!", spellId,requiredSpecialization); + continue; + } + + float additionalCreateChance = fields[2].GetFloat(); + if(additionalCreateChance <= 0.0f) + { + sLog.outError("Skill specialization %u has too low additional create chance in `skill_extra_item_template`!", spellId); + continue; + } + + uint8 additionalMaxNum = fields[3].GetUInt8(); + if(!additionalMaxNum) + { + sLog.outError("Skill specialization %u has 0 max number of extra items in `skill_extra_item_template`!", spellId); + continue; + } + + SkillExtraItemEntry& skillExtraItemEntry = SkillExtraItemStore[spellId]; + + skillExtraItemEntry.requiredSpecialization = requiredSpecialization; + skillExtraItemEntry.additionalCreateChance = additionalCreateChance; + skillExtraItemEntry.additionalMaxNum = additionalMaxNum; + + ++count; + } while (result->NextRow()); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u spell specialization definitions", count ); + } + else + { + sLog.outString(); + sLog.outString( ">> Loaded 0 spell specialization definitions. DB table `skill_extra_item_template` is empty." ); + } +} + +bool canCreateExtraItems(Player * player, uint32 spellId, float &additionalChance, uint8 &additionalMax) +{ + // get the info for the specified spell + SkillExtraItemMap::const_iterator ret = SkillExtraItemStore.find(spellId); + if(ret==SkillExtraItemStore.end()) + return false; + + SkillExtraItemEntry const* specEntry = &ret->second; + + // if no entry, then no extra items can be created + if(!specEntry) + return false; + + // the player doesn't have the required specialization, return false + if(!player->HasSpell(specEntry->requiredSpecialization)) + return false; + + // set the arguments to the appropriate values + additionalChance = specEntry->additionalCreateChance; + additionalMax = specEntry->additionalMaxNum; + + // enable extra item creation + return true; +} diff --git a/src/game/SkillExtraItems.h b/src/game/SkillExtraItems.h new file mode 100644 index 00000000000..51d34da40dd --- /dev/null +++ b/src/game/SkillExtraItems.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_SKILL_EXTRA_ITEMS_H +#define MANGOS_SKILL_EXTRA_ITEMS_H + +#include "Common.h" + +// predef classes used in functions +class Player; +// returns true and sets the appropriate info if the player can create extra items with the given spellId +bool canCreateExtraItems(Player * player, uint32 spellId, float &additionalChance, uint8 &additionalMax); +// function to load the extra item creation info from DB +void LoadSkillExtraItemTable(); +#endif diff --git a/src/game/SkillHandler.cpp b/src/game/SkillHandler.cpp new file mode 100644 index 00000000000..18016018ecd --- /dev/null +++ b/src/game/SkillHandler.cpp @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "Opcodes.h" +#include "Log.h" +#include "Player.h" +#include "World.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "ObjectAccessor.h" +#include "UpdateMask.h" +#include "SpellAuras.h" + +void WorldSession::HandleLearnTalentOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,4+4); + + uint32 talent_id, requested_rank; + recv_data >> talent_id >> requested_rank; + + uint32 CurTalentPoints = GetPlayer()->GetFreeTalentPoints(); + + if(CurTalentPoints == 0) + return; + + if (requested_rank > 4) + return; + + TalentEntry const *talentInfo = sTalentStore.LookupEntry( talent_id ); + + if(!talentInfo) + return; + + TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry( talentInfo->TalentTab ); + + if(!talentTabInfo) + return; + + Player * player = GetPlayer(); + + // prevent learn talent for different class (cheating) + if( (player->getClassMask() & talentTabInfo->ClassMask) == 0 ) + return; + + // prevent skip talent ranks (cheating) + if(requested_rank > 0 && !player->HasSpell(talentInfo->RankID[requested_rank-1])) + return; + + // Check if it requires another talent + if (talentInfo->DependsOn > 0) + { + if(TalentEntry const *depTalentInfo = sTalentStore.LookupEntry(talentInfo->DependsOn)) + { + bool hasEnoughRank = false; + for (int i = talentInfo->DependsOnRank; i <= 4; i++) + { + if (depTalentInfo->RankID[i] != 0) + if (player->HasSpell(depTalentInfo->RankID[i])) + hasEnoughRank = true; + } + if (!hasEnoughRank) + return; + } + } + + // Check if it requires spell + if( talentInfo->DependsOnSpell && !player->HasSpell(talentInfo->DependsOnSpell) ) + return; + + // Find out how many points we have in this field + uint32 spentPoints = 0; + + uint32 tTab = talentInfo->TalentTab; + if (talentInfo->Row > 0) + { + unsigned int numRows = sTalentStore.GetNumRows(); + for (unsigned int i = 0; i < numRows; i++) // Loop through all talents. + { + // Someday, someone needs to revamp + const TalentEntry *tmpTalent = sTalentStore.LookupEntry(i); + if (tmpTalent) // the way talents are tracked + { + if (tmpTalent->TalentTab == tTab) + { + for (int j = 0; j <= 4; j++) + { + if (tmpTalent->RankID[j] != 0) + { + if (player->HasSpell(tmpTalent->RankID[j])) + { + spentPoints += j + 1; + } + } + } + } + } + } + } + + // not have required min points spent in talent tree + if(spentPoints < (talentInfo->Row * 5)) + return; + + // spell not set in talent.dbc + uint32 spellid = talentInfo->RankID[requested_rank]; + if( spellid == 0 ) + { + sLog.outError("Talent.dbc have for talent: %u Rank: %u spell id = 0", talent_id, requested_rank); + return; + } + + // already known + if(GetPlayer( )->HasSpell(spellid)) + return; + + // learn! (other talent ranks will unlearned at learning) + GetPlayer( )->learnSpell(spellid); + sLog.outDetail("TalentID: %u Rank: %u Spell: %u\n", talent_id, requested_rank, spellid); + + // update free talent points + GetPlayer()->SetFreeTalentPoints(CurTalentPoints - 1); +} + +void WorldSession::HandleTalentWipeOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8); + + sLog.outDetail("MSG_TALENT_WIPE_CONFIRM"); + uint64 guid; + recv_data >> guid; + + Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_TRAINER); + if (!unit) + { + sLog.outDebug( "WORLD: HandleTalentWipeOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); + return; + } + + // remove fake death + if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + if(!(_player->resetTalents())) + { + WorldPacket data( MSG_TALENT_WIPE_CONFIRM, 8+4); //you have not any talent + data << uint64(0); + data << uint32(0); + SendPacket( &data ); + return; + } + + unit->CastSpell(_player, 14867, true); //spell: "Untalent Visual Effect" +} + +void WorldSession::HandleUnlearnSkillOpcode(WorldPacket & recv_data) +{ + CHECK_PACKET_SIZE(recv_data,4); + + uint32 skill_id; + recv_data >> skill_id; + GetPlayer()->SetSkill(skill_id, 0, 0); +} diff --git a/src/game/SocialMgr.cpp b/src/game/SocialMgr.cpp new file mode 100644 index 00000000000..85afb48108a --- /dev/null +++ b/src/game/SocialMgr.cpp @@ -0,0 +1,309 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "SocialMgr.h" +#include "Policies/SingletonImp.h" +#include "Database/DatabaseEnv.h" +#include "Opcodes.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Player.h" +#include "ObjectMgr.h" +#include "World.h" +#include "Util.h" + +INSTANTIATE_SINGLETON_1( SocialMgr ); + +PlayerSocial::PlayerSocial() +{ + m_playerGUID = 0; +} + +PlayerSocial::~PlayerSocial() +{ + m_playerSocialMap.clear(); +} + +bool PlayerSocial::AddToSocialList(uint32 friend_guid, bool ignore) +{ + // prevent list (client-side) overflow + if(m_playerSocialMap.size() >= (255-1)) + return false; + + uint32 flag = SOCIAL_FLAG_FRIEND; + if(ignore) + flag = SOCIAL_FLAG_IGNORED; + + PlayerSocialMap::iterator itr = m_playerSocialMap.find(friend_guid); + if(itr != m_playerSocialMap.end()) + { + CharacterDatabase.PExecute("UPDATE character_social SET flags = (flags | %u) WHERE guid = '%u' AND friend = '%u'", flag, GetPlayerGUID(), friend_guid); + m_playerSocialMap[friend_guid].Flags |= flag; + } + else + { + CharacterDatabase.PExecute("INSERT INTO character_social (guid, friend, flags) VALUES ('%u', '%u', '%u')", GetPlayerGUID(), friend_guid, flag); + FriendInfo fi; + fi.Flags |= flag; + m_playerSocialMap[friend_guid] = fi; + } + return true; +} + +void PlayerSocial::RemoveFromSocialList(uint32 friend_guid, bool ignore) +{ + PlayerSocialMap::iterator itr = m_playerSocialMap.find(friend_guid); + if(itr == m_playerSocialMap.end()) // not exist + return; + + uint32 flag = SOCIAL_FLAG_FRIEND; + if(ignore) + flag = SOCIAL_FLAG_IGNORED; + + itr->second.Flags &= ~flag; + if(itr->second.Flags == 0) + { + CharacterDatabase.PExecute("DELETE FROM character_social WHERE guid = '%u' AND friend = '%u'", GetPlayerGUID(), friend_guid); + m_playerSocialMap.erase(itr); + } + else + { + CharacterDatabase.PExecute("UPDATE character_social SET flags = (flags & ~%u) WHERE guid = '%u' AND friend = '%u'", flag, GetPlayerGUID(), friend_guid); + } +} + +void PlayerSocial::SetFriendNote(uint32 friend_guid, std::string note) +{ + PlayerSocialMap::iterator itr = m_playerSocialMap.find(friend_guid); + if(itr == m_playerSocialMap.end()) // not exist + return; + + utf8truncate(note,48); // DB and client size limitation + + CharacterDatabase.escape_string(note); + CharacterDatabase.PExecute("UPDATE character_social SET note = '%s' WHERE guid = '%u' AND friend = '%u'", note.c_str(), GetPlayerGUID(), friend_guid); + m_playerSocialMap[friend_guid].Note = note; +} + +void PlayerSocial::SendSocialList() +{ + Player *plr = objmgr.GetPlayer(GetPlayerGUID()); + if(!plr) + return; + + uint32 size = m_playerSocialMap.size(); + + WorldPacket data(SMSG_CONTACT_LIST, (4+4+size*25)); // just can guess size + data << uint32(7); // unk flag (0x1, 0x2, 0x4), 0x7 if it include ignore list + data << uint32(size); // friends count + + for(PlayerSocialMap::iterator itr = m_playerSocialMap.begin(); itr != m_playerSocialMap.end(); ++itr) + { + sSocialMgr.GetFriendInfo(plr, itr->first, itr->second); + + data << uint64(itr->first); // player guid + data << uint32(itr->second.Flags); // player flag (0x1-friend?, 0x2-ignored?, 0x4-muted?) + data << itr->second.Note; // string note + if(itr->second.Flags & SOCIAL_FLAG_FRIEND) // if IsFriend() + { + data << uint8(itr->second.Status); // online/offline/etc? + if(itr->second.Status) // if online + { + data << uint32(itr->second.Area); // player area + data << uint32(itr->second.Level); // player level + data << uint32(itr->second.Class); // player class + } + } + } + + plr->GetSession()->SendPacket(&data); + sLog.outDebug("WORLD: Sent SMSG_CONTACT_LIST"); +} + +bool PlayerSocial::HasFriend(uint32 friend_guid) +{ + PlayerSocialMap::iterator itr = m_playerSocialMap.find(friend_guid); + if(itr != m_playerSocialMap.end()) + return itr->second.Flags & SOCIAL_FLAG_FRIEND; + return false; +} + +bool PlayerSocial::HasIgnore(uint32 ignore_guid) +{ + PlayerSocialMap::iterator itr = m_playerSocialMap.find(ignore_guid); + if(itr != m_playerSocialMap.end()) + return itr->second.Flags & SOCIAL_FLAG_IGNORED; + return false; +} + +SocialMgr::SocialMgr() +{ + +} + +SocialMgr::~SocialMgr() +{ + +} + +void SocialMgr::RemovePlayerSocial(uint32 guid) +{ + SocialMap::iterator itr = m_socialMap.find(guid); + if(itr != m_socialMap.end()) + m_socialMap.erase(itr); +} + +void SocialMgr::GetFriendInfo(Player *player, uint32 friendGUID, FriendInfo &friendInfo) +{ + if(!player) + return; + + Player *pFriend = ObjectAccessor::FindPlayer(friendGUID); + + uint32 team = player->GetTeam(); + uint32 security = player->GetSession()->GetSecurity(); + bool allowTwoSideWhoList = sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_WHO_LIST); + bool gmInWhoList = sWorld.getConfig(CONFIG_GM_IN_WHO_LIST) || security > SEC_PLAYER; + + // PLAYER see his team only and PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters + // MODERATOR, GAME MASTER, ADMINISTRATOR can see all + if( pFriend && pFriend->GetName() && + ( security > SEC_PLAYER || + ( pFriend->GetTeam() == team || allowTwoSideWhoList ) && + ( pFriend->GetSession()->GetSecurity() == SEC_PLAYER || gmInWhoList && pFriend->IsVisibleGloballyFor(player) ))) + { + friendInfo.Status = FRIEND_STATUS_ONLINE; + if(pFriend->isAFK()) + friendInfo.Status = FRIEND_STATUS_AFK; + if(pFriend->isDND()) + friendInfo.Status = FRIEND_STATUS_DND; + friendInfo.Area = pFriend->GetZoneId(); + friendInfo.Level = pFriend->getLevel(); + friendInfo.Class = pFriend->getClass(); + } + else + { + friendInfo.Status = FRIEND_STATUS_OFFLINE; + friendInfo.Area = 0; + friendInfo.Level = 0; + friendInfo.Class = 0; + } +} + +void SocialMgr::MakeFriendStatusPacket(FriendsResult result, uint32 guid, WorldPacket *data) +{ + data->Initialize(SMSG_FRIEND_STATUS, 5); + *data << uint8(result); + *data << uint64(guid); +} + +void SocialMgr::SendFriendStatus(Player *player, FriendsResult result, uint32 friend_guid, std::string name, bool broadcast) +{ + FriendInfo fi; + + WorldPacket data; + MakeFriendStatusPacket(result, friend_guid, &data); + switch(result) + { + case FRIEND_ONLINE: + GetFriendInfo(player, friend_guid, fi); + data << uint8(fi.Status); + data << uint32(fi.Area); + data << uint32(fi.Level); + data << uint32(fi.Class); + break; + case FRIEND_ADDED_ONLINE: + GetFriendInfo(player, friend_guid, fi); + data << name; + data << uint8(fi.Status); + data << uint32(fi.Area); + data << uint32(fi.Level); + data << uint32(fi.Class); + break; + case FRIEND_ADDED_OFFLINE: + data << name; + break; + } + + if(broadcast) + BroadcastToFriendListers(player, &data); + else + player->GetSession()->SendPacket(&data); +} + +void SocialMgr::BroadcastToFriendListers(Player *player, WorldPacket *packet) +{ + if(!player) + return; + + uint32 team = player->GetTeam(); + uint32 security = player->GetSession()->GetSecurity(); + uint32 guid = player->GetGUIDLow(); + bool gmInWhoList = sWorld.getConfig(CONFIG_GM_IN_WHO_LIST); + bool allowTwoSideWhoList = sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_WHO_LIST); + + for(SocialMap::iterator itr = m_socialMap.begin(); itr != m_socialMap.end(); ++itr) + { + PlayerSocialMap::iterator itr2 = itr->second.m_playerSocialMap.find(guid); + if(itr2 != itr->second.m_playerSocialMap.end() && (itr2->second.Flags & SOCIAL_FLAG_FRIEND)) + { + Player *pFriend = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER)); + + // PLAYER see his team only and PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters + // MODERATOR, GAME MASTER, ADMINISTRATOR can see all + if( pFriend && pFriend->IsInWorld() && + ( pFriend->GetSession()->GetSecurity() > SEC_PLAYER || + ( pFriend->GetTeam() == team || allowTwoSideWhoList ) && + (security == SEC_PLAYER || gmInWhoList && player->IsVisibleGloballyFor(pFriend) ))) + { + pFriend->GetSession()->SendPacket(packet); + } + } + } +} + +PlayerSocial *SocialMgr::LoadFromDB(QueryResult *result, uint32 guid) +{ + PlayerSocial *social = &m_socialMap[guid]; + social->SetPlayerGUID(guid); + + if(!result) + return social; + + uint32 friend_guid = 0; + uint32 flags = 0; + std::string note = ""; + + do + { + Field *fields = result->Fetch(); + + friend_guid = fields[0].GetUInt32(); + flags = fields[1].GetUInt32(); + note = fields[2].GetCppString(); + + social->m_playerSocialMap[friend_guid] = FriendInfo(flags, note); + + // prevent list (client-side) overflow + if(social->m_playerSocialMap.size() >= 255) + break; + } + while( result->NextRow() ); + delete result; + return social; +} diff --git a/src/game/SocialMgr.h b/src/game/SocialMgr.h new file mode 100644 index 00000000000..332ddafa51d --- /dev/null +++ b/src/game/SocialMgr.h @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __MANGOS_SOCIALMGR_H +#define __MANGOS_SOCIALMGR_H + +#include "Policies/Singleton.h" +#include "Database/DatabaseEnv.h" +#include "Common.h" + +class SocialMgr; +class PlayerSocial; +class Player; +class WorldPacket; + +enum FriendStatus +{ + FRIEND_STATUS_OFFLINE = 0, + FRIEND_STATUS_ONLINE = 1, + FRIEND_STATUS_AFK = 2, + FRIEND_STATUS_UNK3 = 3, + FRIEND_STATUS_DND = 4 +}; + +enum SocialFlag +{ + SOCIAL_FLAG_FRIEND = 0x01, + SOCIAL_FLAG_IGNORED = 0x02, + SOCIAL_FLAG_MUTED = 0x04 // guessed +}; + +struct FriendInfo +{ + FriendStatus Status; + uint32 Flags; + uint32 Area; + uint32 Level; + uint32 Class; + std::string Note; + + FriendInfo() + { + Status = FRIEND_STATUS_OFFLINE; + Flags = 0; + Area = 0; + Level = 0; + Class = 0; + Note = ""; + } + + FriendInfo(uint32 flags, std::string note) + { + Status = FRIEND_STATUS_OFFLINE; + Flags = flags; + Area = 0; + Level = 0; + Class = 0; + Note = note; + } +}; + +typedef std::map PlayerSocialMap; +typedef std::map SocialMap; + +/// Results of friend related commands +enum FriendsResult +{ + FRIEND_DB_ERROR = 0x00, + FRIEND_LIST_FULL = 0x01, + FRIEND_ONLINE = 0x02, + FRIEND_OFFLINE = 0x03, + FRIEND_NOT_FOUND = 0x04, + FRIEND_REMOVED = 0x05, + FRIEND_ADDED_ONLINE = 0x06, + FRIEND_ADDED_OFFLINE = 0x07, + FRIEND_ALREADY = 0x08, + FRIEND_SELF = 0x09, + FRIEND_ENEMY = 0x0A, + FRIEND_IGNORE_FULL = 0x0B, + FRIEND_IGNORE_SELF = 0x0C, + FRIEND_IGNORE_NOT_FOUND = 0x0D, + FRIEND_IGNORE_ALREADY = 0x0E, + FRIEND_IGNORE_ADDED = 0x0F, + FRIEND_IGNORE_REMOVED = 0x10, + FRIEND_IGNORE_AMBIGUOUS = 0x11, // That name is ambiguous, type more of the player's server name + FRIEND_MUTE_FULL = 0x12, + FRIEND_MUTE_SELF = 0x13, + FRIEND_MUTE_NOT_FOUND = 0x14, + FRIEND_MUTE_ALREADY = 0x15, + FRIEND_MUTE_ADDED = 0x16, + FRIEND_MUTE_REMOVED = 0x17, + FRIEND_MUTE_AMBIGUOUS = 0x18, // That name is ambiguous, type more of the player's server name + FRIEND_UNK7 = 0x19, // no message at client + FRIEND_UNKNOWN = 0x1A // Unknown friend response from server +}; + +class PlayerSocial +{ + friend class SocialMgr; + public: + PlayerSocial(); + ~PlayerSocial(); + // adding/removing + bool AddToSocialList(uint32 friend_guid, bool ignore); + void RemoveFromSocialList(uint32 friend_guid, bool ignore); + void SetFriendNote(uint32 friend_guid, std::string note); + // Packet send's + void SendSocialList(); + // Misc + bool HasFriend(uint32 friend_guid); + bool HasIgnore(uint32 ignore_guid); + uint32 GetPlayerGUID() { return m_playerGUID; } + void SetPlayerGUID(uint32 guid) { m_playerGUID = guid; } + private: + PlayerSocialMap m_playerSocialMap; + uint32 m_playerGUID; +}; + +class SocialMgr +{ + public: + SocialMgr(); + ~SocialMgr(); + // Misc + void RemovePlayerSocial(uint32 guid); + void GetFriendInfo(Player *player, uint32 friendGUID, FriendInfo &friendInfo); + // Packet management + void MakeFriendStatusPacket(FriendsResult result, uint32 friend_guid, WorldPacket *data); + void SendFriendStatus(Player *player, FriendsResult result, uint32 friend_guid, std::string name, bool broadcast); + void BroadcastToFriendListers(Player *player, WorldPacket *packet); + // Loading + PlayerSocial *LoadFromDB(QueryResult *result, uint32 guid); + private: + SocialMap m_socialMap; +}; + +#define sSocialMgr MaNGOS::Singleton::Instance() +#endif diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp new file mode 100644 index 00000000000..95e9ac1b745 --- /dev/null +++ b/src/game/Spell.cpp @@ -0,0 +1,5115 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" +#include "Opcodes.h" +#include "Log.h" +#include "UpdateMask.h" +#include "World.h" +#include "ObjectMgr.h" +#include "SpellMgr.h" +#include "Player.h" +#include "Pet.h" +#include "Unit.h" +#include "Spell.h" +#include "DynamicObject.h" +#include "SpellAuras.h" +#include "Group.h" +#include "UpdateData.h" +#include "MapManager.h" +#include "ObjectAccessor.h" +#include "CellImpl.h" +#include "Policies/SingletonImp.h" +#include "SharedDefines.h" +#include "Tools.h" +#include "LootMgr.h" +#include "VMapFactory.h" +#include "BattleGround.h" +#include "Util.h" + +#define SPELL_CHANNEL_UPDATE_INTERVAL 1000 + +extern pEffect SpellEffects[TOTAL_SPELL_EFFECTS]; + +bool IsQuestTameSpell(uint32 spellId) +{ + SpellEntry const *spellproto = sSpellStore.LookupEntry(spellId); + if (!spellproto) return false; + + return spellproto->Effect[0] == SPELL_EFFECT_THREAT + && spellproto->Effect[1] == SPELL_EFFECT_APPLY_AURA && spellproto->EffectApplyAuraName[1] == SPELL_AURA_DUMMY; +} + +SpellCastTargets::SpellCastTargets() +{ + m_unitTarget = NULL; + m_itemTarget = NULL; + m_GOTarget = NULL; + + m_unitTargetGUID = 0; + m_GOTargetGUID = 0; + m_CorpseTargetGUID = 0; + m_itemTargetGUID = 0; + m_itemTargetEntry = 0; + + m_srcX = m_srcY = m_srcZ = m_destX = m_destY = m_destZ = 0; + m_strTarget = ""; + m_targetMask = 0; +} + +SpellCastTargets::~SpellCastTargets() +{ +} + +void SpellCastTargets::setUnitTarget(Unit *target) +{ + if (!target) + return; + + m_destX = target->GetPositionX(); + m_destY = target->GetPositionY(); + m_destZ = target->GetPositionZ(); + m_unitTarget = target; + m_unitTargetGUID = target->GetGUID(); + m_targetMask |= TARGET_FLAG_UNIT; +} + +void SpellCastTargets::setDestination(float x, float y, float z) +{ + m_destX = x; + m_destY = y; + m_destZ = z; + m_targetMask |= TARGET_FLAG_DEST_LOCATION; +} + +void SpellCastTargets::setGOTarget(GameObject *target) +{ + m_GOTarget = target; + m_GOTargetGUID = target->GetGUID(); + // m_targetMask |= TARGET_FLAG_OBJECT; +} + +void SpellCastTargets::setItemTarget(Item* item) +{ + if(!item) + return; + + m_itemTarget = item; + m_itemTargetGUID = item->GetGUID(); + m_itemTargetEntry = item->GetEntry(); + m_targetMask |= TARGET_FLAG_ITEM; +} + +void SpellCastTargets::setCorpseTarget(Corpse* corpse) +{ + m_CorpseTargetGUID = corpse->GetGUID(); +} + +void SpellCastTargets::Update(Unit* caster) +{ + m_GOTarget = m_GOTargetGUID ? ObjectAccessor::GetGameObject(*caster,m_GOTargetGUID) : NULL; + m_unitTarget = m_unitTargetGUID ? + ( m_unitTargetGUID==caster->GetGUID() ? caster : ObjectAccessor::GetUnit(*caster, m_unitTargetGUID) ) : + NULL; + + m_itemTarget = NULL; + if(caster->GetTypeId()==TYPEID_PLAYER) + { + if(m_targetMask & TARGET_FLAG_ITEM) + m_itemTarget = ((Player*)caster)->GetItemByGuid(m_itemTargetGUID); + else + { + Player* pTrader = ((Player*)caster)->GetTrader(); + if(pTrader && m_itemTargetGUID < TRADE_SLOT_COUNT) + m_itemTarget = pTrader->GetItemByPos(pTrader->GetItemPosByTradeSlot(m_itemTargetGUID)); + } + if(m_itemTarget) + m_itemTargetEntry = m_itemTarget->GetEntry(); + } +} + +bool SpellCastTargets::read ( WorldPacket * data, Unit *caster ) +{ + if(data->rpos()+4 > data->size()) + return false; + + *data >> m_targetMask; + + if(m_targetMask == TARGET_FLAG_SELF) + { + m_destX = caster->GetPositionX(); + m_destY = caster->GetPositionY(); + m_destZ = caster->GetPositionZ(); + m_unitTarget = caster; + m_unitTargetGUID = caster->GetGUID(); + return true; + } + // TARGET_FLAG_UNK2 is used for non-combat pets, maybe other? + if( m_targetMask & (TARGET_FLAG_UNIT|TARGET_FLAG_UNK2) ) + if(!readGUID(*data, m_unitTargetGUID)) + return false; + + if( m_targetMask & ( TARGET_FLAG_OBJECT | TARGET_FLAG_OBJECT_UNK )) + if(!readGUID(*data, m_GOTargetGUID)) + return false; + + if(( m_targetMask & ( TARGET_FLAG_ITEM | TARGET_FLAG_TRADE_ITEM )) && caster->GetTypeId() == TYPEID_PLAYER) + if(!readGUID(*data, m_itemTargetGUID)) + return false; + + if( m_targetMask & TARGET_FLAG_SOURCE_LOCATION ) + { + if(data->rpos()+4+4+4 > data->size()) + return false; + + *data >> m_srcX >> m_srcY >> m_srcZ; + if(!MaNGOS::IsValidMapCoord(m_srcX, m_srcY, m_srcZ)) + return false; + } + + if( m_targetMask & TARGET_FLAG_DEST_LOCATION ) + { + if(data->rpos()+4+4+4 > data->size()) + return false; + + *data >> m_destX >> m_destY >> m_destZ; + if(!MaNGOS::IsValidMapCoord(m_destX, m_destY, m_destZ)) + return false; + } + + if( m_targetMask & TARGET_FLAG_STRING ) + { + if(data->rpos()+1 > data->size()) + return false; + + *data >> m_strTarget; + } + + if( m_targetMask & (TARGET_FLAG_CORPSE | TARGET_FLAG_PVP_CORPSE ) ) + if(!readGUID(*data, m_CorpseTargetGUID)) + return false; + + // find real units/GOs + Update(caster); + return true; +} + +void SpellCastTargets::write ( WorldPacket * data ) +{ + *data << uint32(m_targetMask); + + if( m_targetMask & ( TARGET_FLAG_UNIT | TARGET_FLAG_PVP_CORPSE | TARGET_FLAG_OBJECT | TARGET_FLAG_CORPSE | TARGET_FLAG_UNK2 ) ) + { + if(m_targetMask & TARGET_FLAG_UNIT) + { + if(m_unitTarget) + data->append(m_unitTarget->GetPackGUID()); + else + *data << uint8(0); + } + else if( m_targetMask & ( TARGET_FLAG_OBJECT | TARGET_FLAG_OBJECT_UNK ) ) + { + if(m_GOTarget) + data->append(m_GOTarget->GetPackGUID()); + else + *data << uint8(0); + } + else if( m_targetMask & ( TARGET_FLAG_CORPSE | TARGET_FLAG_PVP_CORPSE ) ) + data->appendPackGUID(m_CorpseTargetGUID); + else + *data << uint8(0); + } + + if( m_targetMask & ( TARGET_FLAG_ITEM | TARGET_FLAG_TRADE_ITEM ) ) + { + if(m_itemTarget) + data->append(m_itemTarget->GetPackGUID()); + else + *data << uint8(0); + } + + if( m_targetMask & TARGET_FLAG_SOURCE_LOCATION ) + *data << m_srcX << m_srcY << m_srcZ; + + if( m_targetMask & TARGET_FLAG_DEST_LOCATION ) + *data << m_destX << m_destY << m_destZ; + + if( m_targetMask & TARGET_FLAG_STRING ) + *data << m_strTarget; +} + +Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 originalCasterGUID, Spell** triggeringContainer ) +{ + ASSERT( Caster != NULL && info != NULL ); + ASSERT( info == sSpellStore.LookupEntry( info->Id ) && "`info` must be pointer to sSpellStore element"); + + m_spellInfo = info; + m_caster = Caster; + m_selfContainer = NULL; + m_triggeringContainer = triggeringContainer; + m_deletable = true; + m_delayAtDamageCount = 0; + + m_applyMultiplierMask = 0; + + // Get data for type of attack + switch (m_spellInfo->DmgClass) + { + case SPELL_DAMAGE_CLASS_MELEE: + if (m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQ_OFFHAND) + m_attackType = OFF_ATTACK; + else + m_attackType = BASE_ATTACK; + break; + case SPELL_DAMAGE_CLASS_RANGED: + m_attackType = RANGED_ATTACK; + break; + default: + // Wands + if (m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQ_WAND) + m_attackType = RANGED_ATTACK; + else + m_attackType = BASE_ATTACK; + break; + } + + m_spellSchoolMask = GetSpellSchoolMask(info); // Can be override for some spell (wand shoot for example) + + if(m_attackType == RANGED_ATTACK) + { + // wand case + if((m_caster->getClassMask() & CLASSMASK_WAND_USERS) != 0 && m_caster->GetTypeId()==TYPEID_PLAYER) + { + if(Item* pItem = ((Player*)m_caster)->GetWeaponForAttack(RANGED_ATTACK)) + m_spellSchoolMask = SpellSchoolMask(1 << pItem->GetProto()->Damage->DamageType); + } + } + + if(originalCasterGUID) + m_originalCasterGUID = originalCasterGUID; + else + m_originalCasterGUID = m_caster->GetGUID(); + + if(m_originalCasterGUID==m_caster->GetGUID()) + m_originalCaster = m_caster; + else + { + m_originalCaster = ObjectAccessor::GetUnit(*m_caster,m_originalCasterGUID); + if(m_originalCaster && !m_originalCaster->IsInWorld()) m_originalCaster = NULL; + } + + for(int i=0; i <3; ++i) + m_currentBasePoints[i] = m_spellInfo->EffectBasePoints[i]; + + m_spellState = SPELL_STATE_NULL; + + m_castPositionX = m_castPositionY = m_castPositionZ = 0; + m_TriggerSpells.clear(); + m_IsTriggeredSpell = triggered; + //m_AreaAura = false; + m_CastItem = NULL; + + unitTarget = NULL; + itemTarget = NULL; + gameObjTarget = NULL; + focusObject = NULL; + m_cast_count = 0; + m_triggeredByAuraSpell = NULL; + + //Auto Shot & Shoot + if( m_spellInfo->AttributesEx2 == 0x000020 && !triggered ) + m_autoRepeat = true; + else + m_autoRepeat = false; + + m_powerCost = 0; // setup to correct value in Spell::prepare, don't must be used before. + m_casttime = 0; // setup to correct value in Spell::prepare, don't must be used before. + m_timer = 0; // will set to castime in preper + + m_needAliveTargetMask = 0; + + // determine reflection + m_canReflect = false; + + if(m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC && (m_spellInfo->AttributesEx2 & 0x4)==0) + { + for(int j=0;j<3;j++) + { + if (m_spellInfo->Effect[j]==0) + continue; + + if(!IsPositiveTarget(m_spellInfo->EffectImplicitTargetA[j],m_spellInfo->EffectImplicitTargetB[j])) + m_canReflect = true; + else + m_canReflect = (m_spellInfo->AttributesEx & (1<<7)) ? true : false; + + if(m_canReflect) + continue; + else + break; + } + } + + CleanupTargetList(); +} + +Spell::~Spell() +{ +} + +void Spell::FillTargetMap() +{ + // TODO: ADD the correct target FILLS!!!!!! + + for(uint32 i=0;i<3;i++) + { + // not call for empty effect. + // Also some spells use not used effect targets for store targets for dummy effect in triggered spells + if(m_spellInfo->Effect[i]==0) + continue; + + // targets for TARGET_SCRIPT_COORDINATES (A) and TARGET_SCRIPT filled in Spell::canCast call + if( m_spellInfo->EffectImplicitTargetA[i] == TARGET_SCRIPT_COORDINATES || + m_spellInfo->EffectImplicitTargetA[i] == TARGET_SCRIPT || + m_spellInfo->EffectImplicitTargetB[i] == TARGET_SCRIPT && m_spellInfo->EffectImplicitTargetA[i] != TARGET_SELF ) + continue; + + // TODO: find a way so this is not needed? + // for area auras always add caster as target (needed for totems for example) + if(IsAreaAuraEffect(m_spellInfo->Effect[i])) + AddUnitTarget(m_caster, i); + + std::list tmpUnitMap; + + // TargetA/TargetB dependent from each other, we not switch to full support this dependences + // but need it support in some know cases + switch(m_spellInfo->EffectImplicitTargetA[i]) + { + case TARGET_ALL_AROUND_CASTER: + if( m_spellInfo->EffectImplicitTargetB[i]==TARGET_ALL_PARTY || + m_spellInfo->EffectImplicitTargetB[i]==TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER || + m_spellInfo->EffectImplicitTargetB[i]==TARGET_RANDOM_RAID_MEMBER ) + { + SetTargetMap(i,m_spellInfo->EffectImplicitTargetB[i],tmpUnitMap); + } + // Note: this hack with search required until GO casting not implemented + // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support + // currently each enemy selected explicitly and self cast damage + else if(m_spellInfo->EffectImplicitTargetB[i]==TARGET_ALL_ENEMY_IN_AREA && m_spellInfo->Effect[i]==SPELL_EFFECT_ENVIRONMENTAL_DAMAGE) + { + if(m_targets.getUnitTarget()) + tmpUnitMap.push_back(m_targets.getUnitTarget()); + } + else + { + SetTargetMap(i,m_spellInfo->EffectImplicitTargetA[i],tmpUnitMap); + SetTargetMap(i,m_spellInfo->EffectImplicitTargetB[i],tmpUnitMap); + } + break; + case TARGET_TABLE_X_Y_Z_COORDINATES: + // Only if target A, for target B (used in teleports) dest select in effect + SetTargetMap(i,m_spellInfo->EffectImplicitTargetA[i],tmpUnitMap); + break; + default: + switch(m_spellInfo->EffectImplicitTargetB[i]) + { + case TARGET_SCRIPT_COORDINATES: // B case filled in canCast but we need fill unit list base at A case + SetTargetMap(i,m_spellInfo->EffectImplicitTargetA[i],tmpUnitMap); + break; + default: + SetTargetMap(i,m_spellInfo->EffectImplicitTargetA[i],tmpUnitMap); + SetTargetMap(i,m_spellInfo->EffectImplicitTargetB[i],tmpUnitMap); + break; + } + break; + } + + if( (m_spellInfo->EffectImplicitTargetA[i]==0 || m_spellInfo->EffectImplicitTargetA[i]==TARGET_EFFECT_SELECT) && + (m_spellInfo->EffectImplicitTargetB[i]==0 || m_spellInfo->EffectImplicitTargetB[i]==TARGET_EFFECT_SELECT) ) + { + // add here custom effects that need default target. + // FOR EVERY TARGET TYPE THERE IS A DIFFERENT FILL!! + switch(m_spellInfo->Effect[i]) + { + case SPELL_EFFECT_DUMMY: + { + switch(m_spellInfo->Id) + { + case 20577: // Cannibalize + { + // non-standard target selection + SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex); + float max_range = GetSpellMaxRange(srange); + + CellPair p(MaNGOS::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + WorldObject* result = NULL; + + MaNGOS::CannibalizeObjectCheck u_check(m_caster, max_range); + MaNGOS::WorldObjectSearcher searcher(result, u_check); + + TypeContainerVisitor, GridTypeMapContainer > grid_searcher(searcher); + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, grid_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)); + + if(!result) + { + TypeContainerVisitor, WorldTypeMapContainer > world_searcher(searcher); + cell_lock->Visit(cell_lock, world_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)); + } + + if(result) + { + switch(result->GetTypeId()) + { + case TYPEID_UNIT: + case TYPEID_PLAYER: + tmpUnitMap.push_back((Unit*)result); + break; + case TYPEID_CORPSE: + m_targets.setCorpseTarget((Corpse*)result); + if(Player* owner = ObjectAccessor::FindPlayer(((Corpse*)result)->GetOwnerGUID())) + tmpUnitMap.push_back(owner); + break; + } + } + else + { + // clear cooldown at fail + if(m_caster->GetTypeId()==TYPEID_PLAYER) + { + ((Player*)m_caster)->RemoveSpellCooldown(m_spellInfo->Id); + + WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8)); + data << uint32(m_spellInfo->Id); + data << uint64(m_caster->GetGUID()); + ((Player*)m_caster)->GetSession()->SendPacket(&data); + } + + SendCastResult(SPELL_FAILED_NO_EDIBLE_CORPSES); + finish(false); + } + break; + } + default: + if(m_targets.getUnitTarget()) + tmpUnitMap.push_back(m_targets.getUnitTarget()); + break; + } + break; + } + case SPELL_EFFECT_RESURRECT: + case SPELL_EFFECT_PARRY: + case SPELL_EFFECT_CREATE_ITEM: + case SPELL_EFFECT_TRIGGER_SPELL: + case SPELL_EFFECT_TRIGGER_MISSILE: + case SPELL_EFFECT_LEARN_SPELL: + case SPELL_EFFECT_SKILL_STEP: + case SPELL_EFFECT_PROFICIENCY: + case SPELL_EFFECT_SUMMON_POSSESSED: + case SPELL_EFFECT_SUMMON_OBJECT_WILD: + case SPELL_EFFECT_SELF_RESURRECT: + case SPELL_EFFECT_REPUTATION: + if(m_targets.getUnitTarget()) + tmpUnitMap.push_back(m_targets.getUnitTarget()); + break; + case SPELL_EFFECT_SUMMON_PLAYER: + if(m_caster->GetTypeId()==TYPEID_PLAYER && ((Player*)m_caster)->GetSelection()) + { + Player* target = objmgr.GetPlayer(((Player*)m_caster)->GetSelection()); + if(target) + tmpUnitMap.push_back(target); + } + break; + case SPELL_EFFECT_RESURRECT_NEW: + if(m_targets.getUnitTarget()) + tmpUnitMap.push_back(m_targets.getUnitTarget()); + if(m_targets.getCorpseTargetGUID()) + { + Corpse *corpse = ObjectAccessor::GetCorpse(*m_caster,m_targets.getCorpseTargetGUID()); + if(corpse) + { + Player* owner = ObjectAccessor::FindPlayer(corpse->GetOwnerGUID()); + if(owner) + tmpUnitMap.push_back(owner); + } + } + break; + case SPELL_EFFECT_SUMMON: + if(m_spellInfo->EffectMiscValueB[i] == SUMMON_TYPE_POSESSED || m_spellInfo->EffectMiscValueB[i] == SUMMON_TYPE_POSESSED2) + { + if(m_targets.getUnitTarget()) + tmpUnitMap.push_back(m_targets.getUnitTarget()); + } + else + tmpUnitMap.push_back(m_caster); + break; + case SPELL_EFFECT_SUMMON_CHANGE_ITEM: + case SPELL_EFFECT_SUMMON_WILD: + case SPELL_EFFECT_SUMMON_GUARDIAN: + case SPELL_EFFECT_TRANS_DOOR: + case SPELL_EFFECT_ADD_FARSIGHT: + case SPELL_EFFECT_STUCK: + case SPELL_EFFECT_DESTROY_ALL_TOTEMS: + case SPELL_EFFECT_SUMMON_DEMON: + case SPELL_EFFECT_SKILL: + tmpUnitMap.push_back(m_caster); + break; + case SPELL_EFFECT_LEARN_PET_SPELL: + if(Pet* pet = m_caster->GetPet()) + tmpUnitMap.push_back(pet); + break; + case SPELL_EFFECT_ENCHANT_ITEM: + case SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY: + case SPELL_EFFECT_DISENCHANT: + case SPELL_EFFECT_FEED_PET: + case SPELL_EFFECT_PROSPECTING: + if(m_targets.getItemTarget()) + AddItemTarget(m_targets.getItemTarget(), i); + break; + case SPELL_EFFECT_APPLY_AURA: + switch(m_spellInfo->EffectApplyAuraName[i]) + { + case SPELL_AURA_ADD_FLAT_MODIFIER: // some spell mods auras have 0 target modes instead expected TARGET_SELF(1) (and present for other ranks for same spell for example) + case SPELL_AURA_ADD_PCT_MODIFIER: + tmpUnitMap.push_back(m_caster); + break; + default: // apply to target in other case + if(m_targets.getUnitTarget()) + tmpUnitMap.push_back(m_targets.getUnitTarget()); + break; + } + break; + case SPELL_EFFECT_APPLY_AREA_AURA_PARTY: + // AreaAura + if(m_spellInfo->Attributes == 0x9050000 || m_spellInfo->Attributes == 0x10000) + SetTargetMap(i,TARGET_AREAEFFECT_PARTY,tmpUnitMap); + break; + case SPELL_EFFECT_SKIN_PLAYER_CORPSE: + if(m_targets.getUnitTarget()) + { + tmpUnitMap.push_back(m_targets.getUnitTarget()); + } + else if (m_targets.getCorpseTargetGUID()) + { + Corpse *corpse = ObjectAccessor::GetCorpse(*m_caster,m_targets.getCorpseTargetGUID()); + if(corpse) + { + Player* owner = ObjectAccessor::FindPlayer(corpse->GetOwnerGUID()); + if(owner) + tmpUnitMap.push_back(owner); + } + } + break; + default: + break; + } + } + if(IsChanneledSpell(m_spellInfo) && !tmpUnitMap.empty()) + m_needAliveTargetMask |= (1<GetTypeId() == TYPEID_PLAYER) + { + Player *me = (Player*)m_caster; + for (std::list::const_iterator itr = tmpUnitMap.begin(); itr != tmpUnitMap.end(); itr++) + { + Unit *owner = (*itr)->GetOwner(); + Unit *u = owner ? owner : (*itr); + if(u!=m_caster && u->IsPvP() && (!me->duel || me->duel->opponent != u)) + { + me->UpdatePvP(true); + me->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); + break; + } + } + } + + for (std::list::iterator itr = tmpUnitMap.begin() ; itr != tmpUnitMap.end();) + { + if(!CheckTarget(*itr, i, false )) + { + itr = tmpUnitMap.erase(itr); + continue; + } + else + ++itr; + } + + for(std::list::iterator iunit= tmpUnitMap.begin();iunit != tmpUnitMap.end();++iunit) + AddUnitTarget((*iunit), i); + } +} + +void Spell::CleanupTargetList() +{ + m_UniqueTargetInfo.clear(); + m_UniqueGOTargetInfo.clear(); + m_UniqueItemInfo.clear(); + m_countOfHit = 0; + m_countOfMiss = 0; + m_delayMoment = 0; +} + +void Spell::AddUnitTarget(Unit* pVictim, uint32 effIndex) +{ + if( m_spellInfo->Effect[effIndex]==0 ) + return; + + uint64 targetGUID = pVictim->GetGUID(); + + // Lookup target in already in list + for(std::list::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit) + { + if (targetGUID == ihit->targetGUID) // Found in list + { + ihit->effectMask |= 1<SpellHitResult(pVictim, m_spellInfo, m_canReflect); + if (target.missCondition == SPELL_MISS_NONE) + ++m_countOfHit; + else + ++m_countOfMiss; + + // Spell have speed - need calculate incoming time + if (m_spellInfo->speed > 0.0f) + { + // calculate spell incoming interval + float dist = m_caster->GetDistance(pVictim->GetPositionX(), pVictim->GetPositionY(), pVictim->GetPositionZ()); + if (dist < 5.0f) dist = 5.0f; + target.timeDelay = (uint64) floor(dist / m_spellInfo->speed * 1000.0f); + + // Calculate minimum incoming time + if (m_delayMoment==0 || m_delayMoment>target.timeDelay) + m_delayMoment = target.timeDelay; + } + else + target.timeDelay = 0LL; + + // If target reflect spell back to caster + if (target.missCondition==SPELL_MISS_REFLECT) + { + // Calculate reflected spell result on caster + target.reflectResult = m_caster->SpellHitResult(m_caster, m_spellInfo, m_canReflect); + + if (target.reflectResult == SPELL_MISS_REFLECT) // Impossible reflect again, so simply deflect spell + target.reflectResult = SPELL_MISS_PARRY; + + // Increase time interval for reflected spells by 1.5 + target.timeDelay+=target.timeDelay>>1; + } + else + target.reflectResult = SPELL_MISS_NONE; + + // Add target to list + m_UniqueTargetInfo.push_back(target); +} + +void Spell::AddUnitTarget(uint64 unitGUID, uint32 effIndex) +{ + Unit* unit = m_caster->GetGUID()==unitGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, unitGUID); + if (unit) + AddUnitTarget(unit, effIndex); +} + +void Spell::AddGOTarget(GameObject* pVictim, uint32 effIndex) +{ + if( m_spellInfo->Effect[effIndex]==0 ) + return; + + uint64 targetGUID = pVictim->GetGUID(); + + // Lookup target in already in list + for(std::list::iterator ihit= m_UniqueGOTargetInfo.begin();ihit != m_UniqueGOTargetInfo.end();++ihit) + { + if (targetGUID == ihit->targetGUID) // Found in list + { + ihit->effectMask |= 1<speed > 0.0f) + { + // calculate spell incoming interval + float dist = m_caster->GetDistance(pVictim->GetPositionX(), pVictim->GetPositionY(), pVictim->GetPositionZ()); + if (dist < 5.0f) dist = 5.0f; + target.timeDelay = (uint64) floor(dist / m_spellInfo->speed * 1000.0f); + if (m_delayMoment==0 || m_delayMoment>target.timeDelay) + m_delayMoment = target.timeDelay; + } + else + target.timeDelay = 0LL; + + ++m_countOfHit; + + // Add target to list + m_UniqueGOTargetInfo.push_back(target); +} + +void Spell::AddGOTarget(uint64 goGUID, uint32 effIndex) +{ + GameObject* go = ObjectAccessor::GetGameObject(*m_caster, goGUID); + if (go) + AddGOTarget(go, effIndex); +} + +void Spell::AddItemTarget(Item* pitem, uint32 effIndex) +{ + if( m_spellInfo->Effect[effIndex]==0 ) + return; + + // Lookup target in already in list + for(std::list::iterator ihit= m_UniqueItemInfo.begin();ihit != m_UniqueItemInfo.end();++ihit) + { + if (pitem == ihit->item) // Found in list + { + ihit->effectMask |= 1<GetTypeId()== TYPEID_PLAYER) + ((Player*)m_caster)->UpdateWeaponSkill(BASE_ATTACK); + + m_caster->CastMeleeProcDamageAndSpell(unitTarget, 0, damageSchoolMask, m_attackType, MELEE_HIT_MISS, m_spellInfo, m_IsTriggeredSpell); + break; + case SPELL_MISS_RESIST: + m_caster->ProcDamageAndSpell(unitTarget, PROC_FLAG_TARGET_RESISTS, PROC_FLAG_RESIST_SPELL, 0, damageSchoolMask, m_spellInfo, m_IsTriggeredSpell); + break; + case SPELL_MISS_DODGE: + if(unitTarget->GetTypeId() == TYPEID_PLAYER) + ((Player*)unitTarget)->UpdateDefense(); + + // Overpower + if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->getClass() == CLASS_WARRIOR) + { + ((Player*) m_caster)->AddComboPoints(unitTarget, 1); + m_caster->StartReactiveTimer( REACTIVE_OVERPOWER ); + } + + // Riposte + if (unitTarget->getClass() != CLASS_ROGUE) + { + unitTarget->ModifyAuraState(AURA_STATE_DEFENSE, true); + unitTarget->StartReactiveTimer( REACTIVE_DEFENSE ); + } + + m_caster->CastMeleeProcDamageAndSpell(unitTarget, 0, damageSchoolMask, m_attackType, MELEE_HIT_DODGE, m_spellInfo, m_IsTriggeredSpell); + break; + case SPELL_MISS_PARRY: + // Update victim defense ? + if(unitTarget->GetTypeId() == TYPEID_PLAYER) + ((Player*)unitTarget)->UpdateDefense(); + // Mongoose bite - set only Counterattack here + if (unitTarget->getClass() == CLASS_HUNTER) + { + unitTarget->ModifyAuraState(AURA_STATE_HUNTER_PARRY,true); + unitTarget->StartReactiveTimer( REACTIVE_HUNTER_PARRY ); + } + else + { + unitTarget->ModifyAuraState(AURA_STATE_DEFENSE, true); + unitTarget->StartReactiveTimer( REACTIVE_DEFENSE ); + } + m_caster->CastMeleeProcDamageAndSpell(unitTarget, 0, damageSchoolMask, m_attackType, MELEE_HIT_PARRY, m_spellInfo, m_IsTriggeredSpell); + break; + case SPELL_MISS_BLOCK: + unitTarget->ModifyAuraState(AURA_STATE_DEFENSE, true); + unitTarget->StartReactiveTimer( REACTIVE_DEFENSE ); + + m_caster->CastMeleeProcDamageAndSpell(unitTarget, 0, damageSchoolMask, m_attackType, MELEE_HIT_BLOCK, m_spellInfo, m_IsTriggeredSpell); + break; + // Trigger from this events not supported + case SPELL_MISS_EVADE: + case SPELL_MISS_IMMUNE: + case SPELL_MISS_IMMUNE2: + case SPELL_MISS_DEFLECT: + case SPELL_MISS_ABSORB: + // Trigger from reflects need do after get reflect result + case SPELL_MISS_REFLECT: + break; + default: + break; + } + } +} + +void Spell::DoAllEffectOnTarget(TargetInfo *target) +{ + if (target->processed) // Check target + return; + target->processed = true; // Target checked in apply effects procedure + + // Get mask of effects for target + uint32 mask = target->effectMask; + if (mask == 0) // No effects + return; + + Unit* unit = m_caster->GetGUID()==target->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster,target->targetGUID); + if (!unit) + return; + + SpellMissInfo missInfo = target->missCondition; + // Need init unitTarget by default unit (can changed in code on reflect) + // Or on missInfo!=SPELL_MISS_NONE unitTarget undefined (but need in trigger subsystem) + unitTarget = unit; + + if (missInfo==SPELL_MISS_NONE) // In case spell hit target, do all effect on that target + DoSpellHitOnUnit(unit, mask); + else if (missInfo == SPELL_MISS_REFLECT) // In case spell reflect from target, do all effect on caster (if hit) + { + if (target->reflectResult == SPELL_MISS_NONE) // If reflected spell hit caster -> do all effect on him + DoSpellHitOnUnit(m_caster, mask); + } + + // Do triggers only on miss/resist/parry/dodge + if (missInfo!=SPELL_MISS_NONE) + doTriggers(missInfo); + + // Call scripted function for AI if this spell is casted upon a creature (except pets) + if(IS_CREATURE_GUID(target->targetGUID)) + { + // cast at creature (or GO) quest objectives update at successful cast finished (+channel finished) + // ignore autorepeat/melee casts for speed (not exist quest for spells (hm... ) + if( m_caster->GetTypeId() == TYPEID_PLAYER && !IsAutoRepeat() && !IsNextMeleeSwingSpell() && !IsChannelActive() ) + ((Player*)m_caster)->CastedCreatureOrGO(unit->GetEntry(),unit->GetGUID(),m_spellInfo->Id); + + if(((Creature*)unit)->AI()) + ((Creature*)unit)->AI()->SpellHit(m_caster ,m_spellInfo); + } +} + +void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) +{ + if(!unit || !effectMask) + return; + + // Recheck immune (only for delayed spells) + if( m_spellInfo->speed && ( + unit->IsImmunedToDamage(GetSpellSchoolMask(m_spellInfo),true) || + unit->IsImmunedToSpell(m_spellInfo,true) )) + { + m_caster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_IMMUNE); + return; + } + + if( m_caster != unit ) + { + if( !m_caster->IsFriendlyTo(unit) ) + { + // for delayed spells ignore not visible explicit target + if(m_spellInfo->speed > 0.0f && unit==m_targets.getUnitTarget() && !unit->isVisibleForOrDetect(m_caster,false)) + { + m_caster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_EVADE); + return; + } + + // exclude Arcane Missiles Dummy Aura aura for now (attack on hit) + // TODO: find way to not need this? + if(!(m_spellInfo->SpellFamilyName == SPELLFAMILY_MAGE && + m_spellInfo->SpellFamilyFlags & 0x800LL)) + { + unit->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + if( !(m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_NO_INITIAL_AGGRO) ) + { + if(!unit->IsStandState() && !unit->hasUnitState(UNIT_STAT_STUNDED)) + unit->SetStandState(PLAYER_STATE_NONE); + + if(!unit->isInCombat() && unit->GetTypeId() != TYPEID_PLAYER && ((Creature*)unit)->AI()) + ((Creature*)unit)->AI()->AttackStart(m_caster); + + unit->SetInCombatWith(m_caster); + m_caster->SetInCombatWith(unit); + + if(Player *attackedPlayer = unit->GetCharmerOrOwnerPlayerOrPlayerItself()) + { + m_caster->SetContestedPvP(attackedPlayer); + } + unit->AddThreat(m_caster, 0.0f); + } + } + } + else + { + // for delayed spells ignore negative spells (after duel end) for friendly targets + if(m_spellInfo->speed > 0.0f && !IsPositiveSpell(m_spellInfo->Id)) + { + m_caster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_EVADE); + return; + } + + // assisting case, healing and resurrection + if(unit->hasUnitState(UNIT_STAT_ATTACK_PLAYER)) + m_caster->SetContestedPvP(); + if( unit->isInCombat() && !(m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_NO_INITIAL_AGGRO) ) + { + m_caster->SetInCombatState(unit->GetCombatTimer() > 0); + unit->getHostilRefManager().threatAssist(m_caster, 0.0f); + } + } + } + + // Get Data Needed for Diminishing Returns, some effects may have multiple auras, so this must be done on spell hit, not aura add + m_diminishGroup = GetDiminishingReturnsGroupForSpell(m_spellInfo,m_triggeredByAuraSpell); + m_diminishLevel = unit->GetDiminishing(m_diminishGroup); + // Increase Diminishing on unit, current informations for actually casts will use values above + if((GetDiminishingReturnsGroupType(m_diminishGroup) == DRTYPE_PLAYER && unit->GetTypeId() == TYPEID_PLAYER) || GetDiminishingReturnsGroupType(m_diminishGroup) == DRTYPE_ALL) + unit->IncrDiminishing(m_diminishGroup); + + for(uint32 effectNumber=0;effectNumber<3;effectNumber++) + { + if (effectMask & (1<DmgMultiplier[effectNumber]; + // Apply multiplier mods + if(Player* modOwner = m_originalCaster->GetSpellModOwner()) + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_EFFECT_PAST_FIRST, multiplier,this); + m_damageMultipliers[effectNumber] *= multiplier; + } + } + } +} + +void Spell::DoAllEffectOnTarget(GOTargetInfo *target) +{ + if (target->processed) // Check target + return; + target->processed = true; // Target checked in apply effects procedure + + uint32 effectMask = target->effectMask; + if(!effectMask) + return; + + GameObject* go = ObjectAccessor::GetGameObject(*m_caster, target->targetGUID); + if(!go) + return; + + for(uint32 effectNumber=0;effectNumber<3;effectNumber++) + if (effectMask & (1<GetTypeId() == TYPEID_PLAYER && !IsAutoRepeat() && !IsNextMeleeSwingSpell() && !IsChannelActive() ) + ((Player*)m_caster)->CastedCreatureOrGO(go->GetEntry(),go->GetGUID(),m_spellInfo->Id); +} + +void Spell::DoAllEffectOnTarget(ItemTargetInfo *target) +{ + uint32 effectMask = target->effectMask; + if(!target->item || !effectMask) + return; + + for(uint32 effectNumber=0;effectNumber<3;effectNumber++) + if (effectMask & (1<item, NULL, effectNumber); +} + +bool Spell::IsAliveUnitPresentInTargetList() +{ + // Not need check return true + if (m_needAliveTargetMask == 0) + return true; + + uint8 needAliveTargetMask = m_needAliveTargetMask; + + for(std::list::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit) + { + if( ihit->missCondition == SPELL_MISS_NONE && (needAliveTargetMask & ihit->effectMask) ) + { + Unit *unit = m_caster->GetGUID()==ihit->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID); + + if (unit && unit->isAlive()) + needAliveTargetMask &= ~ihit->effectMask; // remove from need alive mask effect that have alive target + } + } + + // is all effects from m_needAliveTargetMask have alive targets + return needAliveTargetMask==0; +} + +// Helper for Chain Healing +// Spell target first +// Raidmates then descending by injury suffered (MaxHealth - Health) +// Other players/mobs then descending by injury suffered (MaxHealth - Health) +struct ChainHealingOrder : public std::binary_function +{ + const Unit* MainTarget; + ChainHealingOrder(Unit const* Target) : MainTarget(Target) {}; + // functor for operator ">" + bool operator()(Unit const* _Left, Unit const* _Right) const + { + return (ChainHealingHash(_Left) < ChainHealingHash(_Right)); + } + int32 ChainHealingHash(Unit const* Target) const + { + if (Target == MainTarget) + return 0; + else if (Target->GetTypeId() == TYPEID_PLAYER && MainTarget->GetTypeId() == TYPEID_PLAYER && + ((Player const*)Target)->IsInSameRaidWith((Player const*)MainTarget)) + { + if (Target->GetHealth() == Target->GetMaxHealth()) + return 40000; + else + return 20000 - Target->GetMaxHealth() + Target->GetHealth(); + } + else + return 40000 - Target->GetMaxHealth() + Target->GetHealth(); + } +}; + +class ChainHealingFullHealth: std::unary_function +{ + public: + const Unit* MainTarget; + ChainHealingFullHealth(const Unit* Target) : MainTarget(Target) {}; + + bool operator()(const Unit* Target) + { + return (Target != MainTarget && Target->GetHealth() == Target->GetMaxHealth()); + } +}; + +// Helper for targets nearest to the spell target +// The spell target is always first unless there is a target at _completely_ the same position (unbelievable case) +struct TargetDistanceOrder : public std::binary_function +{ + const Unit* MainTarget; + TargetDistanceOrder(const Unit* Target) : MainTarget(Target) {}; + // functor for operator ">" + bool operator()(const Unit* _Left, const Unit* _Right) const + { + return (MainTarget->GetDistance(_Left) < MainTarget->GetDistance(_Right)); + } +}; + +void Spell::SetTargetMap(uint32 i,uint32 cur,std::list &TagUnitMap) +{ + float radius; + if (m_spellInfo->EffectRadiusIndex[i]) + radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + else + radius = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex)); + + if(m_originalCaster) + if(Player* modOwner = m_originalCaster->GetSpellModOwner()) + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius,this); + + uint32 EffectChainTarget = m_spellInfo->EffectChainTarget[i]; + if(m_originalCaster) + if(Player* modOwner = m_originalCaster->GetSpellModOwner()) + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_JUMP_TARGETS, EffectChainTarget, this); + + uint32 unMaxTargets = m_spellInfo->MaxAffectedTargets; + switch(cur) + { + case TARGET_TOTEM_EARTH: + case TARGET_TOTEM_WATER: + case TARGET_TOTEM_AIR: + case TARGET_TOTEM_FIRE: + case TARGET_SELF: + case TARGET_SELF2: + case TARGET_DYNAMIC_OBJECT: + case TARGET_AREAEFFECT_CUSTOM: + case TARGET_AREAEFFECT_CUSTOM_2: + case TARGET_SUMMON: + { + TagUnitMap.push_back(m_caster); + break; + } + case TARGET_RANDOM_ENEMY_CHAIN_IN_AREA: + { + m_targets.m_targetMask = 0; + unMaxTargets = EffectChainTarget; + float max_range = radius + unMaxTargets * CHAIN_SPELL_JUMP_RADIUS; + + CellPair p(MaNGOS::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + std::list tempUnitMap; + + { + MaNGOS::AnyAoETargetUnitInObjectRangeCheck u_check(m_caster, m_caster, max_range); + MaNGOS::UnitListSearcher searcher(tempUnitMap, u_check); + + TypeContainerVisitor, WorldTypeMapContainer > world_unit_searcher(searcher); + TypeContainerVisitor, GridTypeMapContainer > grid_unit_searcher(searcher); + + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, world_unit_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)); + cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)); + } + + if(tempUnitMap.empty()) + break; + + tempUnitMap.sort(TargetDistanceOrder(m_caster)); + + //Now to get us a random target that's in the initial range of the spell + uint32 t = 0; + std::list::iterator itr = tempUnitMap.begin(); + while(itr!= tempUnitMap.end() && (*itr)->GetDistance(m_caster) < radius) + ++t, ++itr; + + if(!t) + break; + + itr = tempUnitMap.begin(); + std::advance(itr, rand()%t); + Unit *pUnitTarget = *itr; + TagUnitMap.push_back(pUnitTarget); + + tempUnitMap.erase(itr); + + tempUnitMap.sort(TargetDistanceOrder(pUnitTarget)); + + t = unMaxTargets - 1; + Unit *prev = pUnitTarget; + std::list::iterator next = tempUnitMap.begin(); + + while(t && next != tempUnitMap.end() ) + { + if(prev->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS) + break; + + if(!prev->IsWithinLOSInMap(*next)) + { + ++next; + continue; + } + + prev = *next; + TagUnitMap.push_back(prev); + tempUnitMap.erase(next); + tempUnitMap.sort(TargetDistanceOrder(prev)); + next = tempUnitMap.begin(); + + --t; + } + }break; + case TARGET_PET: + { + Pet* tmpUnit = m_caster->GetPet(); + if (!tmpUnit) break; + TagUnitMap.push_back(tmpUnit); + break; + } + case TARGET_CHAIN_DAMAGE: + { + if (EffectChainTarget <= 1) + { + Unit* pUnitTarget = SelectMagnetTarget(); + if(pUnitTarget) + TagUnitMap.push_back(pUnitTarget); + } + else + { + Unit* pUnitTarget = m_targets.getUnitTarget(); + if(!pUnitTarget) + break; + + unMaxTargets = EffectChainTarget; + + float max_range; + if(m_spellInfo->DmgClass==SPELL_DAMAGE_CLASS_MELEE) + max_range = radius; // + else + //FIXME: This very like horrible hack and wrong for most spells + max_range = radius + unMaxTargets * CHAIN_SPELL_JUMP_RADIUS; + + CellPair p(MaNGOS::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + Unit* originalCaster = GetOriginalCaster(); + if(originalCaster) + { + std::list tempUnitMap; + + { + MaNGOS::AnyAoETargetUnitInObjectRangeCheck u_check(pUnitTarget, originalCaster, max_range); + MaNGOS::UnitListSearcher searcher(tempUnitMap, u_check); + + TypeContainerVisitor, WorldTypeMapContainer > world_unit_searcher(searcher); + TypeContainerVisitor, GridTypeMapContainer > grid_unit_searcher(searcher); + + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, world_unit_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)); + cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)); + } + + tempUnitMap.sort(TargetDistanceOrder(pUnitTarget)); + + if(tempUnitMap.empty()) + break; + + if(*tempUnitMap.begin() == pUnitTarget) + tempUnitMap.erase(tempUnitMap.begin()); + + TagUnitMap.push_back(pUnitTarget); + uint32 t = unMaxTargets - 1; + Unit *prev = pUnitTarget; + std::list::iterator next = tempUnitMap.begin(); + + while(t && next != tempUnitMap.end() ) + { + if(prev->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS) + break; + + if(!prev->IsWithinLOSInMap(*next)) + { + ++next; + continue; + } + + prev = *next; + TagUnitMap.push_back(prev); + tempUnitMap.erase(next); + tempUnitMap.sort(TargetDistanceOrder(prev)); + next = tempUnitMap.begin(); + + --t; + } + } + } + }break; + case TARGET_ALL_ENEMY_IN_AREA: + { + }break; + case TARGET_ALL_ENEMY_IN_AREA_INSTANT: + { + // targets the ground, not the units in the area + if (m_spellInfo->Effect[i]!=SPELL_EFFECT_PERSISTENT_AREA_AURA) + { + CellPair p(MaNGOS::ComputeCellPair(m_targets.m_destX, m_targets.m_destY)); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + MaNGOS::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, PUSH_DEST_CENTER,SPELL_TARGETS_AOE_DAMAGE); + + TypeContainerVisitor world_object_notifier(notifier); + TypeContainerVisitor grid_object_notifier(notifier); + + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, world_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)); + cell_lock->Visit(cell_lock, grid_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)); + + // exclude caster (this can be important if this not original caster) + TagUnitMap.remove(m_caster); + } + }break; + case TARGET_DUELVSPLAYER_COORDINATES: + { + if(Unit* currentTarget = m_targets.getUnitTarget()) + { + m_targets.setDestination(currentTarget->GetPositionX(), currentTarget->GetPositionY(), currentTarget->GetPositionZ()); + TagUnitMap.push_back(currentTarget); + } + }break; + case TARGET_ALL_PARTY_AROUND_CASTER: + case TARGET_ALL_PARTY_AROUND_CASTER_2: + case TARGET_ALL_PARTY: + { + Player *pTarget = m_caster->GetCharmerOrOwnerPlayerOrPlayerItself(); + Group *pGroup = pTarget ? pTarget->GetGroup() : NULL; + + if(pGroup) + { + uint8 subgroup = pTarget->GetSubGroup(); + + for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player* Target = itr->getSource(); + + // IsHostileTo check duel and controlled by enemy + if( Target && Target->GetSubGroup()==subgroup && !m_caster->IsHostileTo(Target) ) + { + if( m_caster->IsWithinDistInMap(Target, radius) ) + TagUnitMap.push_back(Target); + + if(Pet* pet = Target->GetPet()) + if( m_caster->IsWithinDistInMap(pet, radius) ) + TagUnitMap.push_back(pet); + } + } + } + else + { + Unit* ownerOrSelf = pTarget ? pTarget : m_caster->GetCharmerOrOwnerOrSelf(); + if(ownerOrSelf==m_caster || m_caster->IsWithinDistInMap(ownerOrSelf, radius)) + TagUnitMap.push_back(ownerOrSelf); + if(Pet* pet = ownerOrSelf->GetPet()) + if( m_caster->IsWithinDistInMap(pet, radius) ) + TagUnitMap.push_back(pet); + } + }break; + case TARGET_RANDOM_RAID_MEMBER: + { + if (m_caster->GetTypeId() == TYPEID_PLAYER) + if(Player* target = ((Player*)m_caster)->GetNextRandomRaidMember(radius)) + TagUnitMap.push_back(target); + }break; + case TARGET_SINGLE_FRIEND: + case TARGET_SINGLE_FRIEND_2: + { + if(m_targets.getUnitTarget()) + TagUnitMap.push_back(m_targets.getUnitTarget()); + }break; + case TARGET_NONCOMBAT_PET: + { + if(Unit* target = m_targets.getUnitTarget()) + if( target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isPet() && ((Pet*)target)->getPetType() == MINI_PET) + TagUnitMap.push_back(target); + }break; + case TARGET_ALL_AROUND_CASTER: + { + CellPair p(MaNGOS::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + MaNGOS::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, PUSH_SELF_CENTER,SPELL_TARGETS_AOE_DAMAGE); + + TypeContainerVisitor world_object_notifier(notifier); + TypeContainerVisitor grid_object_notifier(notifier); + + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, world_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)); + cell_lock->Visit(cell_lock, grid_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)); + }break; + case TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER: + { + CellPair p(MaNGOS::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + MaNGOS::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, PUSH_SELF_CENTER,SPELL_TARGETS_FRIENDLY); + + TypeContainerVisitor world_object_notifier(notifier); + TypeContainerVisitor grid_object_notifier(notifier); + + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, world_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)); + cell_lock->Visit(cell_lock, grid_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)); + }break; + case TARGET_ALL_FRIENDLY_UNITS_IN_AREA: + { + CellPair p(MaNGOS::ComputeCellPair(m_targets.m_destX, m_targets.m_destY)); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + MaNGOS::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, PUSH_DEST_CENTER,SPELL_TARGETS_FRIENDLY); + + TypeContainerVisitor world_object_notifier(notifier); + TypeContainerVisitor grid_object_notifier(notifier); + + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, world_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)); + cell_lock->Visit(cell_lock, grid_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)); + }break; + // TARGET_SINGLE_PARTY means that the spells can only be casted on a party member and not on the caster (some sceals, fire shield from imp, etc..) + case TARGET_SINGLE_PARTY: + { + Unit *target = m_targets.getUnitTarget(); + // Thoses spells apparently can't be casted on the caster. + if( target && target != m_caster) + { + // Can only be casted on group's members or its pets + Group *pGroup = NULL; + + Unit* owner = m_caster->GetCharmerOrOwner(); + Unit *targetOwner = target->GetCharmerOrOwner(); + if(owner) + { + if(owner->GetTypeId() == TYPEID_PLAYER) + { + if( target == owner ) + { + TagUnitMap.push_back(target); + break; + } + pGroup = ((Player*)owner)->GetGroup(); + } + } + else if (m_caster->GetTypeId() == TYPEID_PLAYER) + { + if( targetOwner == m_caster && target->GetTypeId()==TYPEID_UNIT && ((Creature*)target)->isPet()) + { + TagUnitMap.push_back(target); + break; + } + pGroup = ((Player*)m_caster)->GetGroup(); + } + + if(pGroup) + { + // Our target can also be a player's pet who's grouped with us or our pet. But can't be controlled player + if(targetOwner) + { + if( targetOwner->GetTypeId() == TYPEID_PLAYER && + target->GetTypeId()==TYPEID_UNIT && (((Creature*)target)->isPet()) && + target->GetOwnerGUID()==targetOwner->GetGUID() && + pGroup->IsMember(((Player*)targetOwner)->GetGUID())) + { + TagUnitMap.push_back(target); + } + } + // 1Our target can be a player who is on our group + else if (target->GetTypeId() == TYPEID_PLAYER && pGroup->IsMember(((Player*)target)->GetGUID())) + { + TagUnitMap.push_back(target); + } + } + } + }break; + case TARGET_GAMEOBJECT: + { + if(m_targets.getGOTarget()) + AddGOTarget(m_targets.getGOTarget(), i); + }break; + case TARGET_IN_FRONT_OF_CASTER: + { + CellPair p(MaNGOS::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + bool inFront = m_spellInfo->SpellVisual != 3879; + MaNGOS::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, inFront ? PUSH_IN_FRONT : PUSH_IN_BACK,SPELL_TARGETS_AOE_DAMAGE); + + TypeContainerVisitor world_object_notifier(notifier); + TypeContainerVisitor grid_object_notifier(notifier); + + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, world_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)); + cell_lock->Visit(cell_lock, grid_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)); + }break; + case TARGET_DUELVSPLAYER: + { + Unit *target = m_targets.getUnitTarget(); + if(target) + { + if(m_caster->IsFriendlyTo(target)) + { + TagUnitMap.push_back(target); + } + else + { + Unit* pUnitTarget = SelectMagnetTarget(); + if(pUnitTarget) + TagUnitMap.push_back(pUnitTarget); + } + } + }break; + case TARGET_GAMEOBJECT_ITEM: + { + if(m_targets.getGOTargetGUID()) + AddGOTarget(m_targets.getGOTarget(), i); + else if(m_targets.getItemTarget()) + AddItemTarget(m_targets.getItemTarget(), i); + break; + } + case TARGET_MASTER: + { + if(Unit* owner = m_caster->GetCharmerOrOwner()) + TagUnitMap.push_back(owner); + break; + } + case TARGET_ALL_ENEMY_IN_AREA_CHANNELED: + { + // targets the ground, not the units in the area + if (m_spellInfo->Effect[i]!=SPELL_EFFECT_PERSISTENT_AREA_AURA) + { + CellPair p(MaNGOS::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + MaNGOS::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, PUSH_DEST_CENTER,SPELL_TARGETS_AOE_DAMAGE); + + TypeContainerVisitor world_object_notifier(notifier); + TypeContainerVisitor grid_object_notifier(notifier); + + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, world_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)); + cell_lock->Visit(cell_lock, grid_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)); + } + }break; + case TARGET_MINION: + { + if(m_spellInfo->Effect[i] != SPELL_EFFECT_DUEL) + TagUnitMap.push_back(m_caster); + }break; + case TARGET_SINGLE_ENEMY: + { + Unit* pUnitTarget = SelectMagnetTarget(); + if(pUnitTarget) + TagUnitMap.push_back(pUnitTarget); + }break; + case TARGET_AREAEFFECT_PARTY: + { + Unit* owner = m_caster->GetCharmerOrOwner(); + Player *pTarget = NULL; + + if(owner) + { + TagUnitMap.push_back(m_caster); + if(owner->GetTypeId() == TYPEID_PLAYER) + pTarget = (Player*)owner; + } + else if (m_caster->GetTypeId() == TYPEID_PLAYER) + { + if(Unit* target = m_targets.getUnitTarget()) + { + if( target->GetTypeId() != TYPEID_PLAYER) + { + if(((Creature*)target)->isPet()) + { + Unit *targetOwner = target->GetOwner(); + if(targetOwner->GetTypeId() == TYPEID_PLAYER) + pTarget = (Player*)targetOwner; + } + } + else + pTarget = (Player*)target; + } + } + + Group* pGroup = pTarget ? pTarget->GetGroup() : NULL; + + if(pGroup) + { + uint8 subgroup = pTarget->GetSubGroup(); + + for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player* Target = itr->getSource(); + + // IsHostileTo check duel and controlled by enemy + if(Target && Target->GetSubGroup()==subgroup && !m_caster->IsHostileTo(Target)) + { + if( pTarget->IsWithinDistInMap(Target, radius) ) + TagUnitMap.push_back(Target); + + if(Pet* pet = Target->GetPet()) + if( pTarget->IsWithinDistInMap(pet, radius) ) + TagUnitMap.push_back(pet); + } + } + } + else if (owner) + { + if(m_caster->IsWithinDistInMap(owner, radius)) + TagUnitMap.push_back(owner); + } + else if(pTarget) + { + TagUnitMap.push_back(pTarget); + + if(Pet* pet = pTarget->GetPet()) + if( m_caster->IsWithinDistInMap(pet, radius) ) + TagUnitMap.push_back(pet); + } + + }break; + case TARGET_SCRIPT: + { + if(m_targets.getUnitTarget()) + TagUnitMap.push_back(m_targets.getUnitTarget()); + if(m_targets.getItemTarget()) + AddItemTarget(m_targets.getItemTarget(), i); + }break; + case TARGET_SELF_FISHING: + { + TagUnitMap.push_back(m_caster); + }break; + case TARGET_CHAIN_HEAL: + { + Unit* pUnitTarget = m_targets.getUnitTarget(); + if(!pUnitTarget) + break; + + if (EffectChainTarget <= 1) + TagUnitMap.push_back(pUnitTarget); + else + { + unMaxTargets = EffectChainTarget; + float max_range = radius + unMaxTargets * CHAIN_SPELL_JUMP_RADIUS; + + std::list tempUnitMap; + + { + CellPair p(MaNGOS::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + MaNGOS::SpellNotifierCreatureAndPlayer notifier(*this, tempUnitMap, max_range, PUSH_SELF_CENTER, SPELL_TARGETS_FRIENDLY); + + TypeContainerVisitor world_object_notifier(notifier); + TypeContainerVisitor grid_object_notifier(notifier); + + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, world_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)); + cell_lock->Visit(cell_lock, grid_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)); + + } + + if(m_caster != pUnitTarget && std::find(tempUnitMap.begin(),tempUnitMap.end(),m_caster) == tempUnitMap.end() ) + tempUnitMap.push_front(m_caster); + + tempUnitMap.sort(TargetDistanceOrder(pUnitTarget)); + + if(tempUnitMap.empty()) + break; + + if(*tempUnitMap.begin() == pUnitTarget) + tempUnitMap.erase(tempUnitMap.begin()); + + TagUnitMap.push_back(pUnitTarget); + uint32 t = unMaxTargets - 1; + Unit *prev = pUnitTarget; + std::list::iterator next = tempUnitMap.begin(); + + while(t && next != tempUnitMap.end() ) + { + if(prev->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS) + break; + + if(!prev->IsWithinLOSInMap(*next)) + { + ++next; + continue; + } + + if((*next)->GetHealth() == (*next)->GetMaxHealth()) + { + next = tempUnitMap.erase(next); + continue; + } + + prev = *next; + TagUnitMap.push_back(prev); + tempUnitMap.erase(next); + tempUnitMap.sort(TargetDistanceOrder(prev)); + next = tempUnitMap.begin(); + + --t; + } + } + }break; + case TARGET_CURRENT_ENEMY_COORDINATES: + { + Unit* currentTarget = m_targets.getUnitTarget(); + if(currentTarget) + { + TagUnitMap.push_back(currentTarget); + m_targets.setDestination(currentTarget->GetPositionX(), currentTarget->GetPositionY(), currentTarget->GetPositionZ()); + if(m_spellInfo->EffectImplicitTargetB[i]==TARGET_ALL_ENEMY_IN_AREA_INSTANT) + { + CellPair p(MaNGOS::ComputeCellPair(currentTarget->GetPositionX(), currentTarget->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + MaNGOS::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius,PUSH_TARGET_CENTER, SPELL_TARGETS_AOE_DAMAGE); + TypeContainerVisitor world_notifier(notifier); + TypeContainerVisitor grid_notifier(notifier); + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, world_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)); + cell_lock->Visit(cell_lock, grid_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)); + } + } + }break; + case TARGET_AREAEFFECT_PARTY_AND_CLASS: + { + Player* targetPlayer = m_targets.getUnitTarget() && m_targets.getUnitTarget()->GetTypeId() == TYPEID_PLAYER + ? (Player*)m_targets.getUnitTarget() : NULL; + + Group* pGroup = targetPlayer ? targetPlayer->GetGroup() : NULL; + if(pGroup) + { + for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player* Target = itr->getSource(); + + // IsHostileTo check duel and controlled by enemy + if( Target && targetPlayer->IsWithinDistInMap(Target, radius) && + targetPlayer->getClass() == Target->getClass() && + !m_caster->IsHostileTo(Target) ) + { + TagUnitMap.push_back(Target); + } + } + } + else if(m_targets.getUnitTarget()) + TagUnitMap.push_back(m_targets.getUnitTarget()); + break; + } + case TARGET_TABLE_X_Y_Z_COORDINATES: + { + SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id); + if(st) + { + if (st->target_mapId == m_caster->GetMapId()) + m_targets.setDestination(st->target_X, st->target_Y, st->target_Z); + + // if B==TARGET_TABLE_X_Y_Z_COORDINATES then A already fill all required targets + if (m_spellInfo->EffectImplicitTargetB[i] && m_spellInfo->EffectImplicitTargetB[i]!=TARGET_TABLE_X_Y_Z_COORDINATES) + { + CellPair p(MaNGOS::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + SpellTargets targetB = SPELL_TARGETS_AOE_DAMAGE; + // Select friendly targets for positive effect + if (IsPositiveEffect(m_spellInfo->Id, i)) + targetB = SPELL_TARGETS_FRIENDLY; + + MaNGOS::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius,PUSH_DEST_CENTER, targetB); + + TypeContainerVisitor world_notifier(notifier); + TypeContainerVisitor grid_notifier(notifier); + + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, world_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)); + cell_lock->Visit(cell_lock, grid_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)); + } + } + else + sLog.outError( "SPELL: unknown target coordinates for spell ID %u\n", m_spellInfo->Id ); + }break; + case TARGET_BEHIND_VICTIM: + { + Unit *pTarget = m_caster->getVictim(); + if(!pTarget && m_caster->GetTypeId() == TYPEID_PLAYER) + pTarget = ObjectAccessor::GetUnit(*m_caster, ((Player*)m_caster)->GetSelection()); + + if(pTarget) + { + float _target_x, _target_y, _target_z; + pTarget->GetClosePoint(_target_x, _target_y, _target_z, m_caster->GetObjectSize(), CONTACT_DISTANCE, M_PI); + if(pTarget->IsWithinLOS(_target_x,_target_y,_target_z)) + m_targets.setDestination(_target_x, _target_y, _target_z); + } + }break; + default: + break; + } + + if (unMaxTargets && TagUnitMap.size() > unMaxTargets) + { + // make sure one unit is always removed per iteration + uint32 removed_utarget = 0; + for (std::list::iterator itr = TagUnitMap.begin(), next; itr != TagUnitMap.end(); itr = next) + { + next = itr; + ++next; + if (!*itr) continue; + if ((*itr) == m_targets.getUnitTarget()) + { + TagUnitMap.erase(itr); + removed_utarget = 1; + // break; + } + } + // remove random units from the map + while (TagUnitMap.size() > unMaxTargets - removed_utarget) + { + uint32 poz = urand(0, TagUnitMap.size()-1); + for (std::list::iterator itr = TagUnitMap.begin(); itr != TagUnitMap.end(); ++itr, --poz) + { + if (!*itr) continue; + if (!poz) + { + TagUnitMap.erase(itr); + break; + } + } + } + // the player's target will always be added to the map + if (removed_utarget && m_targets.getUnitTarget()) + TagUnitMap.push_back(m_targets.getUnitTarget()); + } +} + +void Spell::prepare(SpellCastTargets * targets, Aura* triggeredByAura) +{ + m_targets = *targets; + + m_spellState = SPELL_STATE_PREPARING; + + m_castPositionX = m_caster->GetPositionX(); + m_castPositionY = m_caster->GetPositionY(); + m_castPositionZ = m_caster->GetPositionZ(); + m_castOrientation = m_caster->GetOrientation(); + + if(triggeredByAura) + m_triggeredByAuraSpell = triggeredByAura->GetSpellProto(); + + // create and add update event for this spell + SpellEvent* Event = new SpellEvent(this); + m_caster->m_Events.AddEvent(Event, m_caster->m_Events.CalculateTime(1)); + + //Prevent casting at cast another spell (ServerSide check) + if(m_caster->IsNonMeleeSpellCasted(false, true) && m_cast_count) + { + SendCastResult(SPELL_FAILED_SPELL_IN_PROGRESS); + finish(false); + return; + } + + // Fill cost data + m_powerCost = CalculatePowerCost(); + + uint8 result = CanCast(true); + if(result != 0 && !IsAutoRepeat()) //always cast autorepeat dummy for triggering + { + if(triggeredByAura) + { + SendChannelUpdate(0); + triggeredByAura->SetAuraDuration(0); + } + SendCastResult(result); + finish(false); + return; + } + + // calculate cast time (calculated after first CanCast check to prevent charge counting for first CanCast fail) + m_casttime = GetSpellCastTime(m_spellInfo, this); + + // set timer base at cast time + ReSetTimer(); + + // stealth must be removed at cast starting (at show channel bar) + // skip triggered spell (item equip spell casting and other not explicit character casts/item uses) + if ( !m_IsTriggeredSpell && isSpellBreakStealth(m_spellInfo) ) + { + m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + m_caster->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + } + + if(m_IsTriggeredSpell) + cast(true); + else + { + m_caster->SetCurrentCastedSpell( this ); + m_selfContainer = &(m_caster->m_currentSpells[GetCurrentContainer()]); + SendSpellStart(); + } +} + +void Spell::cancel() +{ + if(m_spellState == SPELL_STATE_FINISHED) + return; + + m_autoRepeat = false; + switch (m_spellState) + { + case SPELL_STATE_PREPARING: + case SPELL_STATE_DELAYED: + { + SendInterrupted(0); + SendCastResult(SPELL_FAILED_INTERRUPTED); + } break; + + case SPELL_STATE_CASTING: + { + for(std::list::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit) + { + if( ihit->missCondition == SPELL_MISS_NONE ) + { + Unit* unit = m_caster->GetGUID()==(*ihit).targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID); + if( unit && unit->isAlive() ) + unit->RemoveAurasDueToSpell(m_spellInfo->Id); + } + } + + m_caster->RemoveAurasDueToSpell(m_spellInfo->Id); + SendChannelUpdate(0); + SendInterrupted(0); + SendCastResult(SPELL_FAILED_INTERRUPTED); + } break; + + default: + { + } break; + } + + finish(false); + m_caster->RemoveDynObject(m_spellInfo->Id); + m_caster->RemoveGameObject(m_spellInfo->Id,true); +} + +void Spell::cast(bool skipCheck) +{ + uint8 castResult = 0; + + // update pointers base at GUIDs to prevent access to non-existed already object + UpdatePointers(); + + // cancel at lost main target unit + if(!m_targets.getUnitTarget() && m_targets.getUnitTargetGUID() && m_targets.getUnitTargetGUID() != m_caster->GetGUID()) + { + cancel(); + return; + } + + if(m_caster->GetTypeId() != TYPEID_PLAYER && m_targets.getUnitTarget() && m_targets.getUnitTarget() != m_caster) + m_caster->SetInFront(m_targets.getUnitTarget()); + + castResult = CheckPower(); + if(castResult != 0) + { + SendCastResult(castResult); + finish(false); + return; + } + + // triggered cast called from Spell::prepare where it was already checked + if(!skipCheck) + { + castResult = CanCast(false); + if(castResult != 0) + { + SendCastResult(castResult); + finish(false); + return; + } + } + + // Conflagrate - consumes immolate + if ((m_spellInfo->TargetAuraState == AURA_STATE_IMMOLATE) && m_targets.getUnitTarget()) + { + // for caster applied auras only + Unit::AuraList const &mPeriodic = m_targets.getUnitTarget()->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); + for(Unit::AuraList::const_iterator i = mPeriodic.begin(); i != mPeriodic.end(); ++i) + { + if( (*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && ((*i)->GetSpellProto()->SpellFamilyFlags & 4) && + (*i)->GetCasterGUID()==m_caster->GetGUID() ) + { + m_targets.getUnitTarget()->RemoveAura((*i)->GetId(), (*i)->GetEffIndex()); + break; + } + } + } + + // traded items have trade slot instead of guid in m_itemTargetGUID + // set to real guid to be sent later to the client + m_targets.updateTradeSlotItem(); + + // CAST SPELL + SendSpellCooldown(); + + TakePower(); + TakeReagents(); // we must remove reagents before HandleEffects to allow place crafted item in same slot + FillTargetMap(); + + if(m_spellState == SPELL_STATE_FINISHED) // stop cast if spell marked as finish somewhere in Take*/FillTargetMap + return; + + SendCastResult(castResult); + SendSpellGo(); // we must send smsg_spell_go packet before m_castItem delete in TakeCastItem()... + + // Pass cast spell event to handler (not send triggered by aura spells) + if (m_spellInfo->DmgClass != SPELL_DAMAGE_CLASS_MELEE && m_spellInfo->DmgClass != SPELL_DAMAGE_CLASS_RANGED && !m_triggeredByAuraSpell) + { + m_caster->ProcDamageAndSpell(m_targets.getUnitTarget(), PROC_FLAG_CAST_SPELL, PROC_FLAG_NONE, 0, SPELL_SCHOOL_MASK_NONE, m_spellInfo, m_IsTriggeredSpell); + + // update pointers base at GUIDs to prevent access to non-existed already object + UpdatePointers(); // pointers can be invalidate at triggered spell casting + } + + // Okay, everything is prepared. Now we need to distinguish between immediate and evented delayed spells + if (m_spellInfo->speed > 0.0f) + { + + // Remove used for cast item if need (it can be already NULL after TakeReagents call + // in case delayed spell remove item at cast delay start + TakeCastItem(); + + // Okay, maps created, now prepare flags + m_immediateHandled = false; + m_spellState = SPELL_STATE_DELAYED; + SetDelayStart(0); + } + else + { + // Immediate spell, no big deal + handle_immediate(); + } +} + +void Spell::handle_immediate() +{ + // start channeling if applicable + if(IsChanneledSpell(m_spellInfo)) + { + m_spellState = SPELL_STATE_CASTING; + SendChannelStart(GetSpellDuration(m_spellInfo)); + } + + // process immediate effects (items, ground, etc.) also initialize some variables + _handle_immediate_phase(); + + for(std::list::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit) + DoAllEffectOnTarget(&(*ihit)); + + for(std::list::iterator ihit= m_UniqueGOTargetInfo.begin();ihit != m_UniqueGOTargetInfo.end();++ihit) + DoAllEffectOnTarget(&(*ihit)); + + // spell is finished, perform some last features of the spell here + _handle_finish_phase(); + + // Remove used for cast item if need (it can be already NULL after TakeReagents call + TakeCastItem(); + + if(m_spellState != SPELL_STATE_CASTING) + finish(true); // successfully finish spell cast (not last in case autorepeat or channel spell) +} + +uint64 Spell::handle_delayed(uint64 t_offset) +{ + uint64 next_time = 0; + + if (!m_immediateHandled) + { + _handle_immediate_phase(); + m_immediateHandled = true; + } + + // now recheck units targeting correctness (need before any effects apply to prevent adding immunity at first effect not allow apply second spell effect and similar cases) + for(std::list::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end();++ihit) + { + if (ihit->processed == false) + { + if ( ihit->timeDelay <= t_offset ) + DoAllEffectOnTarget(&(*ihit)); + else if( next_time == 0 || ihit->timeDelay < next_time ) + next_time = ihit->timeDelay; + } + } + + // now recheck gameobject targeting correctness + for(std::list::iterator ighit= m_UniqueGOTargetInfo.begin(); ighit != m_UniqueGOTargetInfo.end();++ighit) + { + if (ighit->processed == false) + { + if ( ighit->timeDelay <= t_offset ) + DoAllEffectOnTarget(&(*ighit)); + else if( next_time == 0 || ighit->timeDelay < next_time ) + next_time = ighit->timeDelay; + } + } + // All targets passed - need finish phase + if (next_time == 0) + { + // spell is finished, perform some last features of the spell here + _handle_finish_phase(); + + finish(true); // successfully finish spell cast + + // return zero, spell is finished now + return 0; + } + else + { + // spell is unfinished, return next execution time + return next_time; + } +} + +void Spell::_handle_immediate_phase() +{ + // handle some immediate features of the spell here + HandleThreatSpells(m_spellInfo->Id); + + m_needSpellLog = IsNeedSendToClient(); + for(uint32 j = 0;j<3;j++) + { + if(m_spellInfo->Effect[j]==0) + continue; + + // apply Send Event effect to ground in case empty target lists + if( m_spellInfo->Effect[j] == SPELL_EFFECT_SEND_EVENT && !HaveTargetsForEffect(j) ) + { + HandleEffects(NULL,NULL,NULL, j); + continue; + } + + // Don't do spell log, if is school damage spell + if(m_spellInfo->Effect[j] == SPELL_EFFECT_SCHOOL_DAMAGE || m_spellInfo->Effect[j] == 0) + m_needSpellLog = false; + + uint32 EffectChainTarget = m_spellInfo->EffectChainTarget[j]; + if(m_originalCaster) + if(Player* modOwner = m_originalCaster->GetSpellModOwner()) + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_JUMP_TARGETS, EffectChainTarget, this); + + // initialize multipliers + m_damageMultipliers[j] = 1.0f; + if( (m_spellInfo->EffectImplicitTargetA[j] == TARGET_CHAIN_DAMAGE || m_spellInfo->EffectImplicitTargetA[j] == TARGET_CHAIN_HEAL) && + (EffectChainTarget > 1) ) + m_applyMultiplierMask |= 1 << j; + } + + // initialize Diminishing Returns Data + m_diminishLevel = DIMINISHING_LEVEL_1; + m_diminishGroup = DIMINISHING_NONE; + + // process items + for(std::list::iterator ihit= m_UniqueItemInfo.begin();ihit != m_UniqueItemInfo.end();++ihit) + DoAllEffectOnTarget(&(*ihit)); + + // process ground + for(uint32 j = 0;j<3;j++) + { + // persistent area auras target only the ground + if(m_spellInfo->Effect[j] == SPELL_EFFECT_PERSISTENT_AREA_AURA) + HandleEffects(NULL,NULL,NULL, j); + } +} + +void Spell::_handle_finish_phase() +{ + // spell log + if(m_needSpellLog) + SendLogExecute(); +} + +void Spell::SendSpellCooldown() +{ + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + Player* _player = (Player*)m_caster; + // Add cooldown for max (disable spell) + // Cooldown started on SendCooldownEvent call + if (m_spellInfo->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE) + { + _player->AddSpellCooldown(m_spellInfo->Id, 0, time(NULL) - 1); + return; + } + + // init cooldown values + uint32 cat = 0; + int32 rec = -1; + int32 catrec = -1; + + // some special item spells without correct cooldown in SpellInfo + // cooldown information stored in item prototype + // This used in same way in WorldSession::HandleItemQuerySingleOpcode data sending to client. + + if(m_CastItem) + { + ItemPrototype const* proto = m_CastItem->GetProto(); + if(proto) + { + for(int idx = 0; idx < 5; ++idx) + { + if(proto->Spells[idx].SpellId == m_spellInfo->Id) + { + cat = proto->Spells[idx].SpellCategory; + rec = proto->Spells[idx].SpellCooldown; + catrec = proto->Spells[idx].SpellCategoryCooldown; + break; + } + } + } + } + + // if no cooldown found above then base at DBC data + if(rec < 0 && catrec < 0) + { + cat = m_spellInfo->Category; + rec = m_spellInfo->RecoveryTime; + catrec = m_spellInfo->CategoryRecoveryTime; + } + + // shoot spells used equipped item cooldown values already assigned in GetAttackTime(RANGED_ATTACK) + // prevent 0 cooldowns set by another way + if (rec <= 0 && catrec <= 0 && (cat == 76 || cat == 351)) + rec = _player->GetAttackTime(RANGED_ATTACK); + + // Now we have cooldown data (if found any), time to apply mods + if(rec > 0) + _player->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COOLDOWN, rec, this); + + if(catrec > 0) + _player->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COOLDOWN, catrec, this); + + // replace negative cooldowns by 0 + if (rec < 0) rec = 0; + if (catrec < 0) catrec = 0; + + // no cooldown after applying spell mods + if( rec == 0 && catrec == 0) + return; + + time_t curTime = time(NULL); + + time_t catrecTime = catrec ? curTime+catrec/1000 : 0; // in secs + time_t recTime = rec ? curTime+rec/1000 : catrecTime;// in secs + + // self spell cooldown + if(recTime > 0) + _player->AddSpellCooldown(m_spellInfo->Id, m_CastItem ? m_CastItem->GetEntry() : 0, recTime); + + // category spells + if (catrec > 0) + { + SpellCategoryStore::const_iterator i_scstore = sSpellCategoryStore.find(cat); + if(i_scstore != sSpellCategoryStore.end()) + { + for(SpellCategorySet::const_iterator i_scset = i_scstore->second.begin(); i_scset != i_scstore->second.end(); ++i_scset) + { + if(*i_scset == m_spellInfo->Id) // skip main spell, already handled above + continue; + + _player->AddSpellCooldown(m_spellInfo->Id, m_CastItem ? m_CastItem->GetEntry() : 0, catrecTime); + } + } + } +} + +void Spell::update(uint32 difftime) +{ + // update pointers based at it's GUIDs + UpdatePointers(); + + if(m_targets.getUnitTargetGUID() && !m_targets.getUnitTarget()) + { + cancel(); + return; + } + + // check if the player caster has moved before the spell finished + if ((m_caster->GetTypeId() == TYPEID_PLAYER && m_timer != 0) && + (m_castPositionX != m_caster->GetPositionX() || m_castPositionY != m_caster->GetPositionY() || m_castPositionZ != m_caster->GetPositionZ()) && + (m_spellInfo->Effect[0] != SPELL_EFFECT_STUCK || !m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING))) + { + // always cancel for channeled spells + if( m_spellState == SPELL_STATE_CASTING ) + cancel(); + // don't cancel for melee, autorepeat, triggered and instant spells + else if(!IsNextMeleeSwingSpell() && !IsAutoRepeat() && !m_IsTriggeredSpell && (m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT)) + cancel(); + } + + switch(m_spellState) + { + case SPELL_STATE_PREPARING: + { + if(m_timer) + { + if(difftime >= m_timer) + m_timer = 0; + else + m_timer -= difftime; + } + + if(m_timer == 0 && !IsNextMeleeSwingSpell() && !IsAutoRepeat()) + cast(); + } break; + case SPELL_STATE_CASTING: + { + if(m_timer > 0) + { + if( m_caster->GetTypeId() == TYPEID_PLAYER ) + { + // check if player has jumped before the channeling finished + if(m_caster->HasUnitMovementFlag(MOVEMENTFLAG_JUMPING)) + cancel(); + + // check for incapacitating player states + if( m_caster->hasUnitState(UNIT_STAT_STUNDED | UNIT_STAT_CONFUSED)) + cancel(); + + // check if player has turned if flag is set + if( m_spellInfo->ChannelInterruptFlags & CHANNEL_FLAG_TURNING && m_castOrientation != m_caster->GetOrientation() ) + cancel(); + } + + // check if there are alive targets left + if (!IsAliveUnitPresentInTargetList()) + { + SendChannelUpdate(0); + finish(); + } + + if(difftime >= m_timer) + m_timer = 0; + else + m_timer -= difftime; + } + + if(m_timer == 0) + { + SendChannelUpdate(0); + + // channeled spell processed independently for quest targeting + // cast at creature (or GO) quest objectives update at successful cast channel finished + // ignore autorepeat/melee casts for speed (not exist quest for spells (hm... ) + if( m_caster->GetTypeId() == TYPEID_PLAYER && !IsAutoRepeat() && !IsNextMeleeSwingSpell() ) + { + for(std::list::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit) + { + TargetInfo* target = &*ihit; + if(!IS_CREATURE_GUID(target->targetGUID)) + continue; + + Unit* unit = m_caster->GetGUID()==target->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster,target->targetGUID); + if (unit==NULL) + continue; + + ((Player*)m_caster)->CastedCreatureOrGO(unit->GetEntry(),unit->GetGUID(),m_spellInfo->Id); + } + + for(std::list::iterator ihit= m_UniqueGOTargetInfo.begin();ihit != m_UniqueGOTargetInfo.end();++ihit) + { + GOTargetInfo* target = &*ihit; + + GameObject* go = ObjectAccessor::GetGameObject(*m_caster, target->targetGUID); + if(!go) + continue; + + ((Player*)m_caster)->CastedCreatureOrGO(go->GetEntry(),go->GetGUID(),m_spellInfo->Id); + } + } + + finish(); + } + } break; + default: + { + }break; + } +} + +void Spell::finish(bool ok) +{ + if(!m_caster) + return; + + if(m_spellState == SPELL_STATE_FINISHED) + return; + + m_spellState = SPELL_STATE_FINISHED; + + //remove spell mods + if (m_caster->GetTypeId() == TYPEID_PLAYER) + ((Player*)m_caster)->RemoveSpellMods(this); + + // other code related only to successfully finished spells + if(!ok) + return; + + //handle SPELL_AURA_ADD_TARGET_TRIGGER auras + Unit::AuraList const& targetTriggers = m_caster->GetAurasByType(SPELL_AURA_ADD_TARGET_TRIGGER); + for(Unit::AuraList::const_iterator i = targetTriggers.begin(); i != targetTriggers.end(); ++i) + { + SpellEntry const *auraSpellInfo = (*i)->GetSpellProto(); + uint32 auraSpellIdx = (*i)->GetEffIndex(); + if (IsAffectedBy(auraSpellInfo, auraSpellIdx)) + { + for(std::list::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit) + if( ihit->effectMask & (1<GetGUID() let load auras at login and speedup most often case + Unit *unit = m_caster->GetGUID()== ihit->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID); + if (unit && unit->isAlive()) + { + // Calculate chance at that moment (can be depend for example from combo points) + int32 chance = m_caster->CalculateSpellDamage(auraSpellInfo, auraSpellIdx, (*i)->GetBasePoints(),unit); + + if(roll_chance_i(chance)) + m_caster->CastSpell(unit, auraSpellInfo->EffectTriggerSpell[auraSpellIdx], true, NULL, (*i)); + } + } + } + } + + if (IsMeleeAttackResetSpell()) + { + m_caster->resetAttackTimer(BASE_ATTACK); + if(m_caster->haveOffhandWeapon()) + m_caster->resetAttackTimer(OFF_ATTACK); + } + + /*if (IsRangedAttackResetSpell()) + m_caster->resetAttackTimer(RANGED_ATTACK);*/ + + // Clear combo at finish state + if(m_caster->GetTypeId() == TYPEID_PLAYER && NeedsComboPoints(m_spellInfo)) + ((Player*)m_caster)->ClearComboPoints(); + + // call triggered spell only at successful cast (after clear combo points -> for add some if need) + if(!m_TriggerSpells.empty()) + TriggerSpell(); + + // Stop Attack for some spells + if( m_spellInfo->Attributes & SPELL_ATTR_STOP_ATTACK_TARGET ) + m_caster->AttackStop(); +} + +void Spell::SendCastResult(uint8 result) +{ + if (m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + if(((Player*)m_caster)->GetSession()->PlayerLoading()) // don't send cast results at loading time + return; + + if(result != 0) + { + WorldPacket data(SMSG_CAST_FAILED, (4+1+1)); + data << uint32(m_spellInfo->Id); + data << uint8(result); // problem + data << uint8(m_cast_count); // single cast or multi 2.3 (0/1) + switch (result) + { + case SPELL_FAILED_REQUIRES_SPELL_FOCUS: + data << uint32(m_spellInfo->RequiresSpellFocus); + break; + case SPELL_FAILED_REQUIRES_AREA: + // hardcode areas limitation case + if( m_spellInfo->Id==41618 || m_spellInfo->Id==41620 ) + data << uint32(3842); + else if( m_spellInfo->Id==41617 || m_spellInfo->Id==41619 ) + data << uint32(3905); + // normal case + else + data << uint32(m_spellInfo->AreaId); + break; + case SPELL_FAILED_TOTEMS: + if(m_spellInfo->Totem[0]) + data << uint32(m_spellInfo->Totem[0]); + if(m_spellInfo->Totem[1]) + data << uint32(m_spellInfo->Totem[1]); + break; + case SPELL_FAILED_TOTEM_CATEGORY: + if(m_spellInfo->TotemCategory[0]) + data << uint32(m_spellInfo->TotemCategory[0]); + if(m_spellInfo->TotemCategory[1]) + data << uint32(m_spellInfo->TotemCategory[1]); + break; + case SPELL_FAILED_EQUIPPED_ITEM_CLASS: + data << uint32(m_spellInfo->EquippedItemClass); + data << uint32(m_spellInfo->EquippedItemSubClassMask); + data << uint32(m_spellInfo->EquippedItemInventoryTypeMask); + break; + } + ((Player*)m_caster)->GetSession()->SendPacket(&data); + } + else + { + WorldPacket data(SMSG_CLEAR_EXTRA_AURA_INFO, (8+4)); + data.append(m_caster->GetPackGUID()); + data << uint32(m_spellInfo->Id); + ((Player*)m_caster)->GetSession()->SendPacket(&data); + } +} + +void Spell::SendSpellStart() +{ + if(!IsNeedSendToClient()) + return; + + sLog.outDebug("Sending SMSG_SPELL_START id=%u",m_spellInfo->Id); + + uint16 castFlags = CAST_FLAG_UNKNOWN1; + if(IsRangedSpell()) + castFlags |= CAST_FLAG_AMMO; + + Unit * target; + if(!m_targets.getUnitTarget()) + target = m_caster; + else + target = m_targets.getUnitTarget(); + + WorldPacket data(SMSG_SPELL_START, (8+8+4+4+2)); + if(m_CastItem) + data.append(m_CastItem->GetPackGUID()); + else + data.append(m_caster->GetPackGUID()); + + data.append(m_caster->GetPackGUID()); + data << uint32(m_spellInfo->Id); + data << uint8(m_cast_count); // single cast or multi 2.3 (0/1) + data << uint16(castFlags); + data << uint32(m_timer); + + m_targets.write(&data); + + if( castFlags & CAST_FLAG_AMMO ) + WriteAmmoToPacket(&data); + + m_caster->SendMessageToSet(&data, true); +} + +void Spell::SendSpellGo() +{ + // not send invisible spell casting + if(!IsNeedSendToClient()) + return; + + sLog.outDebug("Sending SMSG_SPELL_GO id=%u",m_spellInfo->Id); + + Unit * target; + if(!m_targets.getUnitTarget()) + target = m_caster; + else + target = m_targets.getUnitTarget(); + + uint16 castFlags = CAST_FLAG_UNKNOWN3; + if(IsRangedSpell()) + castFlags |= CAST_FLAG_AMMO; + + WorldPacket data(SMSG_SPELL_GO, 50); // guess size + if(m_CastItem) + data.append(m_CastItem->GetPackGUID()); + else + data.append(m_caster->GetPackGUID()); + + data.append(m_caster->GetPackGUID()); + data << uint32(m_spellInfo->Id); + data << uint16(castFlags); + data << uint32(getMSTime()); // timestamp + + WriteSpellGoTargets(&data); + + m_targets.write(&data); + + if( castFlags & CAST_FLAG_AMMO ) + WriteAmmoToPacket(&data); + + m_caster->SendMessageToSet(&data, true); +} + +void Spell::WriteAmmoToPacket( WorldPacket * data ) +{ + uint32 ammoInventoryType = 0; + uint32 ammoDisplayID = 0; + + if (m_caster->GetTypeId() == TYPEID_PLAYER) + { + Item *pItem = ((Player*)m_caster)->GetWeaponForAttack( RANGED_ATTACK ); + if(pItem) + { + ammoInventoryType = pItem->GetProto()->InventoryType; + if( ammoInventoryType == INVTYPE_THROWN ) + ammoDisplayID = pItem->GetProto()->DisplayInfoID; + else + { + uint32 ammoID = ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID); + if(ammoID) + { + ItemPrototype const *pProto = objmgr.GetItemPrototype( ammoID ); + if(pProto) + { + ammoDisplayID = pProto->DisplayInfoID; + ammoInventoryType = pProto->InventoryType; + } + } + else if(m_caster->GetDummyAura(46699)) // Requires No Ammo + { + ammoDisplayID = 5996; // normal arrow + ammoInventoryType = INVTYPE_AMMO; + } + } + } + } + // TODO: implement selection ammo data based at ranged weapon stored in equipmodel/equipinfo/equipslot fields + + *data << uint32(ammoDisplayID); + *data << uint32(ammoInventoryType); +} + +void Spell::WriteSpellGoTargets( WorldPacket * data ) +{ + *data << (uint8)m_countOfHit; + for(std::list::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit) + if ((*ihit).missCondition == SPELL_MISS_NONE) // Add only hits + *data << uint64(ihit->targetGUID); + + for(std::list::iterator ighit= m_UniqueGOTargetInfo.begin();ighit != m_UniqueGOTargetInfo.end();++ighit) + *data << uint64(ighit->targetGUID); // Always hits + + *data << (uint8)m_countOfMiss; + for(std::list::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit) + { + if( ihit->missCondition != SPELL_MISS_NONE ) // Add only miss + { + *data << uint64(ihit->targetGUID); + *data << uint8(ihit->missCondition); + if( ihit->missCondition == SPELL_MISS_REFLECT ) + *data << uint8(ihit->reflectResult); + } + } +} + +void Spell::SendLogExecute() +{ + Unit *target = m_targets.getUnitTarget() ? m_targets.getUnitTarget() : m_caster; + + WorldPacket data(SMSG_SPELLLOGEXECUTE, (8+4+4+4+4+8)); + + if(m_caster->GetTypeId() == TYPEID_PLAYER) + data.append(m_caster->GetPackGUID()); + else + data.append(target->GetPackGUID()); + + data << uint32(m_spellInfo->Id); + uint32 count1 = 1; + data << uint32(count1); // count1 (effect count?) + for(uint32 i = 0; i < count1; ++i) + { + data << uint32(m_spellInfo->Effect[0]); // spell effect? + uint32 count2 = 1; + data << uint32(count2); // count2 (target count?) + for(uint32 j = 0; j < count2; ++j) + { + switch(m_spellInfo->Effect[0]) + { + case SPELL_EFFECT_POWER_DRAIN: + if(Unit *unit = m_targets.getUnitTarget()) + data.append(unit->GetPackGUID()); + else + data << uint8(0); + data << uint32(0); + data << uint32(0); + data << float(0); + break; + case SPELL_EFFECT_ADD_EXTRA_ATTACKS: + if(Unit *unit = m_targets.getUnitTarget()) + data.append(unit->GetPackGUID()); + else + data << uint8(0); + data << uint32(0); // count? + break; + case SPELL_EFFECT_INTERRUPT_CAST: + if(Unit *unit = m_targets.getUnitTarget()) + data.append(unit->GetPackGUID()); + else + data << uint8(0); + data << uint32(0); // spellid + break; + case SPELL_EFFECT_DURABILITY_DAMAGE: + if(Unit *unit = m_targets.getUnitTarget()) + data.append(unit->GetPackGUID()); + else + data << uint8(0); + data << uint32(0); + data << uint32(0); + break; + case SPELL_EFFECT_OPEN_LOCK: + case SPELL_EFFECT_OPEN_LOCK_ITEM: + if(Item *item = m_targets.getItemTarget()) + data.append(item->GetPackGUID()); + else + data << uint8(0); + break; + case SPELL_EFFECT_CREATE_ITEM: + data << uint32(m_spellInfo->EffectItemType[0]); + break; + case SPELL_EFFECT_SUMMON: + case SPELL_EFFECT_SUMMON_WILD: + case SPELL_EFFECT_SUMMON_GUARDIAN: + case SPELL_EFFECT_TRANS_DOOR: + case SPELL_EFFECT_SUMMON_PET: + case SPELL_EFFECT_SUMMON_POSSESSED: + case SPELL_EFFECT_SUMMON_TOTEM: + case SPELL_EFFECT_SUMMON_OBJECT_WILD: + case SPELL_EFFECT_CREATE_HOUSE: + case SPELL_EFFECT_DUEL: + case SPELL_EFFECT_SUMMON_TOTEM_SLOT1: + case SPELL_EFFECT_SUMMON_TOTEM_SLOT2: + case SPELL_EFFECT_SUMMON_TOTEM_SLOT3: + case SPELL_EFFECT_SUMMON_TOTEM_SLOT4: + case SPELL_EFFECT_SUMMON_PHANTASM: + case SPELL_EFFECT_SUMMON_CRITTER: + case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: + case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: + case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: + case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: + case SPELL_EFFECT_SUMMON_DEMON: + case SPELL_EFFECT_150: + if(Unit *unit = m_targets.getUnitTarget()) + data.append(unit->GetPackGUID()); + else if(m_targets.getItemTargetGUID()) + data.appendPackGUID(m_targets.getItemTargetGUID()); + else if(GameObject *go = m_targets.getGOTarget()) + data.append(go->GetPackGUID()); + else + data << uint8(0); // guid + break; + case SPELL_EFFECT_FEED_PET: + data << uint32(m_targets.getItemTargetEntry()); + break; + case SPELL_EFFECT_DISMISS_PET: + if(Unit *unit = m_targets.getUnitTarget()) + data.append(unit->GetPackGUID()); + else + data << uint8(0); + break; + default: + return; + } + } + } + + m_caster->SendMessageToSet(&data, true); +} + +void Spell::SendInterrupted(uint8 result) +{ + WorldPacket data(SMSG_SPELL_FAILURE, (8+4+1)); + data.append(m_caster->GetPackGUID()); + data << m_spellInfo->Id; + data << result; + m_caster->SendMessageToSet(&data, true); + + data.Initialize(SMSG_SPELL_FAILED_OTHER, (8+4)); + data.append(m_caster->GetPackGUID()); + data << m_spellInfo->Id; + m_caster->SendMessageToSet(&data, true); +} + +void Spell::SendChannelUpdate(uint32 time) +{ + if(time == 0) + { + m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT,0); + m_caster->SetUInt32Value(UNIT_CHANNEL_SPELL,0); + } + + if (m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + WorldPacket data( MSG_CHANNEL_UPDATE, 8+4 ); + data.append(m_caster->GetPackGUID()); + data << time; + + ((Player*)m_caster)->GetSession()->SendPacket( &data ); +} + +void Spell::SendChannelStart(uint32 duration) +{ + WorldObject* target = NULL; + + // select first not rsusted target from target list for _0_ effect + if(!m_UniqueTargetInfo.empty()) + { + for(std::list::iterator itr= m_UniqueTargetInfo.begin();itr != m_UniqueTargetInfo.end();++itr) + { + if( (itr->effectMask & (1<<0)) && itr->reflectResult==SPELL_MISS_NONE && itr->targetGUID != m_caster->GetGUID()) + { + target = ObjectAccessor::GetUnit(*m_caster, itr->targetGUID); + break; + } + } + } + else if(!m_UniqueGOTargetInfo.empty()) + { + for(std::list::iterator itr= m_UniqueGOTargetInfo.begin();itr != m_UniqueGOTargetInfo.end();++itr) + { + if(itr->effectMask & (1<<0) ) + { + target = ObjectAccessor::GetGameObject(*m_caster, itr->targetGUID); + break; + } + } + } + + if (m_caster->GetTypeId() == TYPEID_PLAYER) + { + WorldPacket data( MSG_CHANNEL_START, (8+4+4) ); + data.append(m_caster->GetPackGUID()); + data << m_spellInfo->Id; + data << duration; + + ((Player*)m_caster)->GetSession()->SendPacket( &data ); + } + + m_timer = duration; + if(target) + m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, target->GetGUID()); + m_caster->SetUInt32Value(UNIT_CHANNEL_SPELL, m_spellInfo->Id); +} + +void Spell::SendResurrectRequest(Player* target) +{ + WorldPacket data(SMSG_RESURRECT_REQUEST, (8+4+2+4)); + data << m_caster->GetGUID(); + data << uint32(1) << uint16(0) << uint32(1); + + target->GetSession()->SendPacket(&data); +} + +void Spell::SendPlaySpellVisual(uint32 SpellID) +{ + if (m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + WorldPacket data(SMSG_PLAY_SPELL_VISUAL, 12); + data << m_caster->GetGUID(); + data << SpellID; + ((Player*)m_caster)->GetSession()->SendPacket(&data); +} + +void Spell::TakeCastItem() +{ + if(!m_CastItem || m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + // not remove cast item at triggered spell (equipping, weapon damage, etc) + if(m_IsTriggeredSpell) + return; + + ItemPrototype const *proto = m_CastItem->GetProto(); + + if(!proto) + { + // This code is to avoid a crash + // I'm not sure, if this is really an error, but I guess every item needs a prototype + sLog.outError("Cast item has no item prototype highId=%d, lowId=%d",m_CastItem->GetGUIDHigh(), m_CastItem->GetGUIDLow()); + return; + } + + bool expendable = false; + bool withoutCharges = false; + + for (int i = 0; i<5; i++) + { + if (proto->Spells[i].SpellId) + { + // item has limited charges + if (proto->Spells[i].SpellCharges) + { + if (proto->Spells[i].SpellCharges < 0) + expendable = true; + + int32 charges = m_CastItem->GetSpellCharges(i); + + // item has charges left + if (charges) + { + (charges > 0) ? --charges : ++charges; // abs(charges) less at 1 after use + if (proto->Stackable < 2) + m_CastItem->SetSpellCharges(i, charges); + m_CastItem->SetState(ITEM_CHANGED, (Player*)m_caster); + } + + // all charges used + withoutCharges = (charges == 0); + } + } + } + + if (expendable && withoutCharges) + { + uint32 count = 1; + ((Player*)m_caster)->DestroyItemCount(m_CastItem, count, true); + + // prevent crash at access to deleted m_targets.getItemTarget + if(m_CastItem==m_targets.getItemTarget()) + m_targets.setItemTarget(NULL); + + m_CastItem = NULL; + } +} + +void Spell::TakePower() +{ + if(m_CastItem || m_triggeredByAuraSpell) + return; + + // health as power used + if(m_spellInfo->powerType == POWER_HEALTH) + { + m_caster->ModifyHealth( -(int32)m_powerCost ); + return; + } + + if(m_spellInfo->powerType >= MAX_POWERS) + { + sLog.outError("Spell::TakePower: Unknown power type '%d'", m_spellInfo->powerType); + return; + } + + Powers powerType = Powers(m_spellInfo->powerType); + + m_caster->ModifyPower(powerType, -(int32)m_powerCost); + + // Set the five second timer + if (powerType == POWER_MANA && m_powerCost > 0) + m_caster->SetLastManaUse(getMSTime()); +} + +void Spell::TakeReagents() +{ + if(m_IsTriggeredSpell) // reagents used in triggered spell removed by original spell or don't must be removed. + return; + + if (m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + if (m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_NO_REAGENT_WHILE_PREP && + m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION)) + return; + + Player* p_caster = (Player*)m_caster; + + for(uint32 x=0;x<8;x++) + { + if(m_spellInfo->Reagent[x] <= 0) + continue; + + uint32 itemid = m_spellInfo->Reagent[x]; + uint32 itemcount = m_spellInfo->ReagentCount[x]; + + // if CastItem is also spell reagent + if (m_CastItem) + { + ItemPrototype const *proto = m_CastItem->GetProto(); + if( proto && proto->ItemId == itemid ) + { + for(int s=0;s<5;s++) + { + // CastItem will be used up and does not count as reagent + int32 charges = m_CastItem->GetSpellCharges(s); + if (proto->Spells[s].SpellCharges < 0 && abs(charges) < 2) + { + ++itemcount; + break; + } + } + + m_CastItem = NULL; + } + } + + // if getItemTarget is also spell reagent + if (m_targets.getItemTargetEntry()==itemid) + m_targets.setItemTarget(NULL); + + p_caster->DestroyItemCount(itemid, itemcount, true); + } +} + +void Spell::HandleThreatSpells(uint32 spellId) +{ + if(!m_targets.getUnitTarget() || !spellId) + return; + + if(!m_targets.getUnitTarget()->CanHaveThreatList()) + return; + + SpellThreatEntry const *threatSpell = sSpellThreatStore.LookupEntry(spellId); + if(!threatSpell) + return; + + m_targets.getUnitTarget()->AddThreat(m_caster, float(threatSpell->threat)); + + DEBUG_LOG("Spell %u, rank %u, added an additional %i threat", spellId, spellmgr.GetSpellRank(spellId), threatSpell->threat); +} + +void Spell::HandleEffects(Unit *pUnitTarget,Item *pItemTarget,GameObject *pGOTarget,uint32 i, float DamageMultiplier) +{ + unitTarget = pUnitTarget; + itemTarget = pItemTarget; + gameObjTarget = pGOTarget; + + uint8 eff = m_spellInfo->Effect[i]; + uint32 mechanic = m_spellInfo->EffectMechanic[i]; + + damage = int32(CalculateDamage((uint8)i,unitTarget)*DamageMultiplier); + + sLog.outDebug( "Spell: Effect : %u", eff); + + //Simply return. Do not display "immune" in red text on client + if(unitTarget && unitTarget->IsImmunedToSpellEffect(eff, mechanic)) + return; + + if(eff TOTAL_SPELL_EFFECTS ", eff); + if (m_CastItem) + EffectEnchantItemTmp(i); + else + { + sLog.outError("SPELL: unknown effect %u spell id %u\n", + eff, m_spellInfo->Id); + } + } + */ +} + +void Spell::TriggerSpell() +{ + for(TriggerSpells::iterator si=m_TriggerSpells.begin(); si!=m_TriggerSpells.end(); ++si) + { + Spell* spell = new Spell(m_caster, (*si), true, m_originalCasterGUID, this->m_selfContainer); + spell->prepare(&m_targets); // use original spell original targets + } +} + +uint8 Spell::CanCast(bool strict) +{ + // check cooldowns to prevent cheating + if(m_caster->GetTypeId()==TYPEID_PLAYER && ((Player*)m_caster)->HasSpellCooldown(m_spellInfo->Id)) + { + if(m_triggeredByAuraSpell) + return SPELL_FAILED_DONT_REPORT; + else + return SPELL_FAILED_NOT_READY; + } + + // only allow triggered spells if at an ended battleground + if( !m_IsTriggeredSpell && m_caster->GetTypeId() == TYPEID_PLAYER) + if(BattleGround * bg = ((Player*)m_caster)->GetBattleGround()) + if(bg->GetStatus() == STATUS_WAIT_LEAVE) + return SPELL_FAILED_DONT_REPORT; + + // only check at first call, Stealth auras are already removed at second call + // for now, ignore triggered spells + if( strict && !m_IsTriggeredSpell) + { + // Cannot be used in this stance/form + if(uint8 shapeError = GetErrorAtShapeshiftedCast(m_spellInfo, m_caster->m_form)) + return shapeError; + + if ((m_spellInfo->Attributes & SPELL_ATTR_ONLY_STEALTHED) && !(m_caster->HasStealthAura())) + return SPELL_FAILED_ONLY_STEALTHED; + } + + // caster state requirements + if(m_spellInfo->CasterAuraState && !m_caster->HasAuraState(AuraState(m_spellInfo->CasterAuraState))) + return SPELL_FAILED_CASTER_AURASTATE; + if(m_spellInfo->CasterAuraStateNot && m_caster->HasAuraState(AuraState(m_spellInfo->CasterAuraStateNot))) + return SPELL_FAILED_CASTER_AURASTATE; + + // cancel autorepeat spells if cast start when moving + // (not wand currently autorepeat cast delayed to moving stop anyway in spell update code) + if( m_caster->GetTypeId()==TYPEID_PLAYER && ((Player*)m_caster)->isMoving() ) + { + // skip stuck spell to allow use it in falling case and apply spell limitations at movement + if( (!m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING) || m_spellInfo->Effect[0] != SPELL_EFFECT_STUCK) && + (IsAutoRepeat() || (m_spellInfo->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) != 0) ) + return SPELL_FAILED_MOVING; + } + + Unit *target = m_targets.getUnitTarget(); + + if(target) + { + // target state requirements (not allowed state), apply to self also + if(m_spellInfo->TargetAuraStateNot && target->HasAuraState(AuraState(m_spellInfo->TargetAuraStateNot))) + return SPELL_FAILED_TARGET_AURASTATE; + + + if(target != m_caster) + { + // target state requirements (apply to non-self only), to allow cast affects to self like Dirty Deeds + if(m_spellInfo->TargetAuraState && !target->HasAuraState(AuraState(m_spellInfo->TargetAuraState))) + return SPELL_FAILED_TARGET_AURASTATE; + + // Not allow casting on flying player + if (target->isInFlight()) + return SPELL_FAILED_BAD_TARGETS; + + if(VMAP::VMapFactory::checkSpellForLoS(m_spellInfo->Id) && !m_caster->IsWithinLOSInMap(target)) + return SPELL_FAILED_LINE_OF_SIGHT; + + // auto selection spell rank implemented in WorldSession::HandleCastSpellOpcode + // this case can be triggered if rank not found (too low-level target for first rank) + if(m_caster->GetTypeId() == TYPEID_PLAYER && !IsPassiveSpell(m_spellInfo->Id) && !m_CastItem) + { + for(int i=0;i<3;i++) + { + if(IsPositiveEffect(m_spellInfo->Id, i) && m_spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA) + if(target->getLevel() + 10 < m_spellInfo->spellLevel) + return SPELL_FAILED_LOWLEVEL; + } + } + } + + // check pet presents + for(int j=0;j<3;j++) + { + if(m_spellInfo->EffectImplicitTargetA[j] == TARGET_PET) + { + target = m_caster->GetPet(); + if(!target) + { + if(m_triggeredByAuraSpell) // not report pet not existence for triggered spells + return SPELL_FAILED_DONT_REPORT; + else + return SPELL_FAILED_NO_PET; + } + break; + } + } + + //check creature type + //ignore self casts (including area casts when caster selected as target) + if(target != m_caster) + { + if(!CheckTargetCreatureType(target)) + { + if(target->GetTypeId()==TYPEID_PLAYER) + return SPELL_FAILED_TARGET_IS_PLAYER; + else + return SPELL_FAILED_BAD_TARGETS; + } + } + + // TODO: this check can be applied and for player to prevent cheating when IsPositiveSpell will return always correct result. + // check target for pet/charmed casts (not self targeted), self targeted cast used for area effects and etc + if(m_caster != target && m_caster->GetTypeId()==TYPEID_UNIT && m_caster->GetCharmerOrOwnerGUID()) + { + // check correctness positive/negative cast target (pet cast real check and cheating check) + if(IsPositiveSpell(m_spellInfo->Id)) + { + if(m_caster->IsHostileTo(target)) + return SPELL_FAILED_BAD_TARGETS; + } + else + { + if(m_caster->IsFriendlyTo(target)) + return SPELL_FAILED_BAD_TARGETS; + } + } + + if(IsPositiveSpell(m_spellInfo->Id)) + { + if(target->IsImmunedToSpell(m_spellInfo,false)) + return SPELL_FAILED_TARGET_AURASTATE; + } + + //Must be behind the target. + if( m_spellInfo->AttributesEx2 == 0x100000 && (m_spellInfo->AttributesEx & 0x200) == 0x200 && target->HasInArc(M_PI, m_caster) ) + { + SendInterrupted(2); + return SPELL_FAILED_NOT_BEHIND; + } + + //Target must be facing you. + if((m_spellInfo->Attributes == 0x150010) && !target->HasInArc(M_PI, m_caster) ) + { + SendInterrupted(2); + return SPELL_FAILED_NOT_INFRONT; + } + + // check if target is in combat + if (target != m_caster && (m_spellInfo->AttributesEx & SPELL_ATTR_EX_NOT_IN_COMBAT_TARGET) && target->isInCombat()) + { + return SPELL_FAILED_TARGET_AFFECTING_COMBAT; + } + } + // Spell casted only on battleground + if((m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_BATTLEGROUND) && m_caster->GetTypeId()==TYPEID_PLAYER) + if(!((Player*)m_caster)->InBattleGround()) + return SPELL_FAILED_ONLY_BATTLEGROUNDS; + + // do not allow spells to be cast in arenas + // - with greater than 15 min CD without SPELL_ATTR_EX4_USABLE_IN_ARENA flag + // - with SPELL_ATTR_EX4_NOT_USABLE_IN_ARENA flag + if( (m_spellInfo->AttributesEx4 & SPELL_ATTR_EX4_NOT_USABLE_IN_ARENA) || + GetSpellRecoveryTime(m_spellInfo) > 15 * MINUTE * 1000 && !(m_spellInfo->AttributesEx4 & SPELL_ATTR_EX4_USABLE_IN_ARENA) ) + if(MapEntry const* mapEntry = sMapStore.LookupEntry(m_caster->GetMapId())) + if(mapEntry->IsBattleArena()) + return SPELL_FAILED_NOT_IN_ARENA; + + // zone check + if(!IsSpellAllowedInLocation(m_spellInfo,m_caster->GetMapId(),m_caster->GetZoneId(),m_caster->GetAreaId())) + return SPELL_FAILED_REQUIRES_AREA; + + // not let players cast spells at mount (and let do it to creatures) + if( m_caster->IsMounted() && m_caster->GetTypeId()==TYPEID_PLAYER && !m_IsTriggeredSpell && + !IsPassiveSpell(m_spellInfo->Id) && !(m_spellInfo->Attributes & SPELL_ATTR_CASTABLE_WHILE_MOUNTED) ) + { + if(m_caster->isInFlight()) + return SPELL_FAILED_NOT_FLYING; + else + return SPELL_FAILED_NOT_MOUNTED; + } + + // always (except passive spells) check items (focus object can be required for any type casts) + if(!IsPassiveSpell(m_spellInfo->Id)) + if(uint8 castResult = CheckItems()) + return castResult; + + //ImpliciteTargetA-B = 38, If fact there is 0 Spell with ImpliciteTargetB=38 + if(m_UniqueTargetInfo.empty()) // skip second canCast apply (for delayed spells for example) + { + for(uint8 j = 0; j < 3; j++) + { + if( m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT || + m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT && m_spellInfo->EffectImplicitTargetA[j] != TARGET_SELF || + m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES || + m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT_COORDINATES ) + { + bool okDoo = false; + + SpellScriptTarget::const_iterator lower = spellmgr.GetBeginSpellScriptTarget(m_spellInfo->Id); + SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(m_spellInfo->Id); + if(lower==upper) + sLog.outErrorDb("Spell (ID: %u) has effect EffectImplicitTargetA/EffectImplicitTargetB = TARGET_SCRIPT or TARGET_SCRIPT_COORDINATES, but does not have record in `spell_script_target`",m_spellInfo->Id); + + SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex); + float range = GetSpellMaxRange(srange); + + Creature* creatureScriptTarget = NULL; + GameObject* goScriptTarget = NULL; + + for(SpellScriptTarget::const_iterator i_spellST = lower; i_spellST != upper; ++i_spellST) + { + switch(i_spellST->second.type) + { + case SPELL_TARGET_TYPE_GAMEOBJECT: + { + GameObject* p_GameObject = NULL; + + if(i_spellST->second.targetEntry) + { + CellPair p(MaNGOS::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + + MaNGOS::NearestGameObjectEntryInObjectRangeCheck go_check(*m_caster,i_spellST->second.targetEntry,range); + MaNGOS::GameObjectLastSearcher checker(p_GameObject,go_check); + + TypeContainerVisitor, GridTypeMapContainer > object_checker(checker); + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, object_checker, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)); + + if(p_GameObject) + { + // remember found target and range, next attempt will find more near target with another entry + creatureScriptTarget = NULL; + goScriptTarget = p_GameObject; + range = go_check.GetLastRange(); + } + } + else if( focusObject ) //Focus Object + { + float frange = m_caster->GetDistance(focusObject); + if(range >= frange) + { + creatureScriptTarget = NULL; + goScriptTarget = focusObject; + range = frange; + } + } + break; + } + case SPELL_TARGET_TYPE_CREATURE: + case SPELL_TARGET_TYPE_DEAD: + default: + { + Creature *p_Creature = NULL; + + CellPair p(MaNGOS::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); // Really don't know what is that??? + + MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*m_caster,i_spellST->second.targetEntry,i_spellST->second.type!=SPELL_TARGET_TYPE_DEAD,range); + MaNGOS::CreatureLastSearcher searcher(p_Creature, u_check); + + TypeContainerVisitor, GridTypeMapContainer > grid_creature_searcher(searcher); + + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, grid_creature_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)); + + if(p_Creature ) + { + creatureScriptTarget = p_Creature; + goScriptTarget = NULL; + range = u_check.GetLastRange(); + } + break; + } + } + } + + if(creatureScriptTarget) + { + // store coordinates for TARGET_SCRIPT_COORDINATES + if (m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES || + m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT_COORDINATES ) + { + m_targets.setDestination(creatureScriptTarget->GetPositionX(),creatureScriptTarget->GetPositionY(),creatureScriptTarget->GetPositionZ()); + + if(m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES && m_spellInfo->EffectImplicitTargetB[j] == 0 && m_spellInfo->Effect[j]!=SPELL_EFFECT_PERSISTENT_AREA_AURA) + AddUnitTarget(creatureScriptTarget, j); + } + // store explicit target for TARGET_SCRIPT + else + AddUnitTarget(creatureScriptTarget, j); + } + else if(goScriptTarget) + { + // store coordinates for TARGET_SCRIPT_COORDINATES + if (m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES || + m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT_COORDINATES ) + { + m_targets.setDestination(goScriptTarget->GetPositionX(),goScriptTarget->GetPositionY(),goScriptTarget->GetPositionZ()); + + if(m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES && m_spellInfo->EffectImplicitTargetB[j] == 0 && m_spellInfo->Effect[j]!=SPELL_EFFECT_PERSISTENT_AREA_AURA) + AddGOTarget(goScriptTarget, j); + } + // store explicit target for TARGET_SCRIPT + else + AddGOTarget(goScriptTarget, j); + } + //Missing DB Entry or targets for this spellEffect. + else + { + // not report target not existence for triggered spells + if(m_triggeredByAuraSpell || m_IsTriggeredSpell) + return SPELL_FAILED_DONT_REPORT; + else + return SPELL_FAILED_BAD_TARGETS; + } + } + } + } + + if(uint8 castResult = CheckRange(strict)) + return castResult; + + { + if(uint8 castResult = CheckPower()) + return castResult; + } + + if(!m_triggeredByAuraSpell) // triggered spell not affected by stun/etc + if(uint8 castResult = CheckCasterAuras()) + return castResult; + + for (int i = 0; i < 3; i++) + { + // for effects of spells that have only one target + switch(m_spellInfo->Effect[i]) + { + case SPELL_EFFECT_DUMMY: + { + // Execute + if(m_spellInfo->SpellIconID == 1648) + { + if(!m_targets.getUnitTarget() || m_targets.getUnitTarget()->GetHealth() > m_targets.getUnitTarget()->GetMaxHealth()*0.2) + return SPELL_FAILED_BAD_TARGETS; + } + else if (m_spellInfo->Id == 51582) + { + if(m_caster->IsInWater()) + return SPELL_FAILED_ONLY_ABOVEWATER; + } + break; + } + case SPELL_EFFECT_SCHOOL_DAMAGE: + { + // Hammer of Wrath + if(m_spellInfo->SpellVisual == 7250) + { + if (!m_targets.getUnitTarget()) + return SPELL_FAILED_BAD_IMPLICIT_TARGETS; + + if(m_targets.getUnitTarget()->GetHealth() > m_targets.getUnitTarget()->GetMaxHealth()*0.2) + return SPELL_FAILED_BAD_TARGETS; + } + break; + } + case SPELL_EFFECT_TAMECREATURE: + { + if (!m_targets.getUnitTarget() || m_targets.getUnitTarget()->GetTypeId() == TYPEID_PLAYER) + return SPELL_FAILED_BAD_IMPLICIT_TARGETS; + + if (m_targets.getUnitTarget()->getLevel() > m_caster->getLevel()) + return SPELL_FAILED_HIGHLEVEL; + + CreatureInfo const *cinfo = ((Creature*)m_targets.getUnitTarget())->GetCreatureInfo(); + if( cinfo->type != CREATURE_TYPE_BEAST ) + return SPELL_FAILED_BAD_TARGETS; + + // use SMSG_PET_TAME_FAILURE? + if( !(cinfo->flag1 & 1) || !(cinfo->family) ) + return SPELL_FAILED_BAD_TARGETS; + + if(m_caster->GetPetGUID()) + return SPELL_FAILED_ALREADY_HAVE_SUMMON; + + if(m_caster->GetCharmGUID()) + return SPELL_FAILED_ALREADY_HAVE_CHARM; + + break; + } + case SPELL_EFFECT_LEARN_SPELL: + { + if(m_spellInfo->EffectImplicitTargetA[i] != TARGET_PET) + break; + + Pet* pet = m_caster->GetPet(); + + if(!pet) + return SPELL_FAILED_NO_PET; + + SpellEntry const *learn_spellproto = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]); + + if(!learn_spellproto) + return SPELL_FAILED_NOT_KNOWN; + + if(!pet->CanTakeMoreActiveSpells(learn_spellproto->Id)) + return SPELL_FAILED_TOO_MANY_SKILLS; + + if(m_spellInfo->spellLevel > pet->getLevel()) + return SPELL_FAILED_LOWLEVEL; + + if(!pet->HasTPForSpell(learn_spellproto->Id)) + return SPELL_FAILED_TRAINING_POINTS; + + break; + } + case SPELL_EFFECT_LEARN_PET_SPELL: + { + Pet* pet = m_caster->GetPet(); + + if(!pet) + return SPELL_FAILED_NO_PET; + + SpellEntry const *learn_spellproto = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]); + + if(!learn_spellproto) + return SPELL_FAILED_NOT_KNOWN; + + if(!pet->CanTakeMoreActiveSpells(learn_spellproto->Id)) + return SPELL_FAILED_TOO_MANY_SKILLS; + + if(m_spellInfo->spellLevel > pet->getLevel()) + return SPELL_FAILED_LOWLEVEL; + + if(!pet->HasTPForSpell(learn_spellproto->Id)) + return SPELL_FAILED_TRAINING_POINTS; + + break; + } + case SPELL_EFFECT_FEED_PET: + { + if (m_caster->GetTypeId() != TYPEID_PLAYER || !m_targets.getItemTarget() ) + return SPELL_FAILED_BAD_TARGETS; + + Pet* pet = m_caster->GetPet(); + + if(!pet) + return SPELL_FAILED_NO_PET; + + if(!pet->HaveInDiet(m_targets.getItemTarget()->GetProto())) + return SPELL_FAILED_WRONG_PET_FOOD; + + if(!pet->GetCurrentFoodBenefitLevel(m_targets.getItemTarget()->GetProto()->ItemLevel)) + return SPELL_FAILED_FOOD_LOWLEVEL; + + if(m_caster->isInCombat() || pet->isInCombat()) + return SPELL_FAILED_AFFECTING_COMBAT; + + break; + } + case SPELL_EFFECT_POWER_BURN: + case SPELL_EFFECT_POWER_DRAIN: + { + // Can be area effect, Check only for players and not check if target - caster (spell can have multiply drain/burn effects) + if(m_caster->GetTypeId() == TYPEID_PLAYER) + if(Unit* target = m_targets.getUnitTarget()) + if(target!=m_caster && target->getPowerType()!=m_spellInfo->EffectMiscValue[i]) + return SPELL_FAILED_BAD_TARGETS; + break; + } + case SPELL_EFFECT_CHARGE: + { + if (m_caster->hasUnitState(UNIT_STAT_ROOT)) + return SPELL_FAILED_ROOTED; + + break; + } + case SPELL_EFFECT_SKINNING: + { + if (m_caster->GetTypeId() != TYPEID_PLAYER || !m_targets.getUnitTarget() || m_targets.getUnitTarget()->GetTypeId() != TYPEID_UNIT) + return SPELL_FAILED_BAD_TARGETS; + + if( !(m_targets.getUnitTarget()->GetUInt32Value(UNIT_FIELD_FLAGS) & UNIT_FLAG_SKINNABLE) ) + return SPELL_FAILED_TARGET_UNSKINNABLE; + + Creature* creature = (Creature*)m_targets.getUnitTarget(); + if ( creature->GetCreatureType() != CREATURE_TYPE_CRITTER && ( !creature->lootForBody || !creature->loot.empty() ) ) + { + return SPELL_FAILED_TARGET_NOT_LOOTED; + } + + uint32 skill; + if(creature->GetCreatureInfo()->flag1 & 256) + skill = SKILL_HERBALISM; // special case + else if(creature->GetCreatureInfo()->flag1 & 512) + skill = SKILL_MINING; // special case + else + skill = SKILL_SKINNING; // normal case + + int32 skillValue = ((Player*)m_caster)->GetSkillValue(skill); + int32 TargetLevel = m_targets.getUnitTarget()->getLevel(); + int32 ReqValue = (skillValue < 100 ? (TargetLevel-10)*10 : TargetLevel*5); + if (ReqValue > skillValue) + return SPELL_FAILED_LOW_CASTLEVEL; + + // chance for fail at orange skinning attempt + if( (m_selfContainer && (*m_selfContainer) == this) && + skillValue < sWorld.GetConfigMaxSkillValue() && + (ReqValue < 0 ? 0 : ReqValue) > irand(skillValue-25, skillValue+37) ) + return SPELL_FAILED_TRY_AGAIN; + + break; + } + case SPELL_EFFECT_OPEN_LOCK_ITEM: + case SPELL_EFFECT_OPEN_LOCK: + { + if( m_spellInfo->EffectImplicitTargetA[i] != TARGET_GAMEOBJECT && + m_spellInfo->EffectImplicitTargetA[i] != TARGET_GAMEOBJECT_ITEM ) + break; + + if( m_caster->GetTypeId() != TYPEID_PLAYER // only players can open locks, gather etc. + // we need a go target in case of TARGET_GAMEOBJECT + || m_spellInfo->EffectImplicitTargetA[i] == TARGET_GAMEOBJECT && !m_targets.getGOTarget() + // we need a go target, or an openable item target in case of TARGET_GAMEOBJECT_ITEM + || m_spellInfo->EffectImplicitTargetA[i] == TARGET_GAMEOBJECT_ITEM && !m_targets.getGOTarget() && + (!m_targets.getItemTarget() || !m_targets.getItemTarget()->GetProto()->LockID || m_targets.getItemTarget()->GetOwner() != m_caster ) ) + return SPELL_FAILED_BAD_TARGETS; + + // get the lock entry + LockEntry const *lockInfo = NULL; + if (GameObject* go=m_targets.getGOTarget()) + lockInfo = sLockStore.LookupEntry(go->GetLockId()); + else if(Item* itm=m_targets.getItemTarget()) + lockInfo = sLockStore.LookupEntry(itm->GetProto()->LockID); + + // check lock compatibility + if (lockInfo) + { + // check for lock - key pair (checked by client also, just prevent cheating + bool ok_key = false; + for(int it = 0; it < 5; ++it) + { + switch(lockInfo->keytype[it]) + { + case LOCK_KEY_NONE: + break; + case LOCK_KEY_ITEM: + { + if(lockInfo->key[it]) + { + if(m_CastItem && m_CastItem->GetEntry()==lockInfo->key[it]) + ok_key =true; + break; + } + } + case LOCK_KEY_SKILL: + { + if(uint32(m_spellInfo->EffectMiscValue[i])!=lockInfo->key[it]) + break; + + switch(lockInfo->key[it]) + { + case LOCKTYPE_HERBALISM: + if(((Player*)m_caster)->HasSkill(SKILL_HERBALISM)) + ok_key =true; + break; + case LOCKTYPE_MINING: + if(((Player*)m_caster)->HasSkill(SKILL_MINING)) + ok_key =true; + break; + default: + ok_key =true; + break; + } + } + } + if(ok_key) + break; + } + + if(!ok_key) + return SPELL_FAILED_BAD_TARGETS; + } + + // chance for fail at orange mining/herb/LockPicking gathering attempt + if (!m_selfContainer || ((*m_selfContainer) != this)) + break; + + // get the skill value of the player + int32 SkillValue = 0; + bool canFailAtMax = true; + if (m_spellInfo->EffectMiscValue[i] == LOCKTYPE_HERBALISM) + { + SkillValue = ((Player*)m_caster)->GetSkillValue(SKILL_HERBALISM); + canFailAtMax = false; + } + else if (m_spellInfo->EffectMiscValue[i] == LOCKTYPE_MINING) + { + SkillValue = ((Player*)m_caster)->GetSkillValue(SKILL_MINING); + canFailAtMax = false; + } + else if (m_spellInfo->EffectMiscValue[i] == LOCKTYPE_PICKLOCK) + SkillValue = ((Player*)m_caster)->GetSkillValue(SKILL_LOCKPICKING); + + // castitem check: rogue using skeleton keys. the skill values should not be added in this case. + if(m_CastItem) + SkillValue = 0; + + // add the damage modifier from the spell casted (cheat lock / skeleton key etc.) (use m_currentBasePoints, CalculateDamage returns wrong value) + SkillValue += m_currentBasePoints[i]+1; + + // get the required lock value + int32 ReqValue=0; + if (lockInfo) + { + // check for lock - key pair + bool ok = false; + for(int it = 0; it < 5; ++it) + { + if(lockInfo->keytype[it]==LOCK_KEY_ITEM && lockInfo->key[it] && m_CastItem && m_CastItem->GetEntry()==lockInfo->key[it]) + { + // if so, we're good to go + ok = true; + break; + } + } + if(ok) + break; + + if (m_spellInfo->EffectMiscValue[i] == LOCKTYPE_PICKLOCK) + ReqValue = lockInfo->requiredlockskill; + else + ReqValue = lockInfo->requiredminingskill; + } + + // skill doesn't meet the required value + if (ReqValue > SkillValue) + return SPELL_FAILED_LOW_CASTLEVEL; + + // chance for failure in orange gather / lockpick (gathering skill can't fail at maxskill) + if((canFailAtMax || SkillValue < sWorld.GetConfigMaxSkillValue()) && ReqValue > irand(SkillValue-25, SkillValue+37)) + return SPELL_FAILED_TRY_AGAIN; + + break; + } + case SPELL_EFFECT_SUMMON_DEAD_PET: + { + Creature *pet = m_caster->GetPet(); + if(!pet) + return SPELL_FAILED_NO_PET; + + if(pet->isAlive()) + return SPELL_FAILED_ALREADY_HAVE_SUMMON; + + break; + } + // This is generic summon effect now and don't make this check for summon types similar + // SPELL_EFFECT_SUMMON_CRITTER, SPELL_EFFECT_SUMMON_WILD or SPELL_EFFECT_SUMMON_GUARDIAN. + // These won't show up in m_caster->GetPetGUID() + case SPELL_EFFECT_SUMMON: + { + switch(m_spellInfo->EffectMiscValueB[i]) + { + case SUMMON_TYPE_POSESSED: + case SUMMON_TYPE_POSESSED2: + case SUMMON_TYPE_DEMON: + case SUMMON_TYPE_SUMMON: + { + if(m_caster->GetPetGUID()) + return SPELL_FAILED_ALREADY_HAVE_SUMMON; + + if(m_caster->GetCharmGUID()) + return SPELL_FAILED_ALREADY_HAVE_CHARM; + break; + } + } + break; + } + // Don't make this check for SPELL_EFFECT_SUMMON_CRITTER, SPELL_EFFECT_SUMMON_WILD or SPELL_EFFECT_SUMMON_GUARDIAN. + // These won't show up in m_caster->GetPetGUID() + case SPELL_EFFECT_SUMMON_POSSESSED: + case SPELL_EFFECT_SUMMON_PHANTASM: + case SPELL_EFFECT_SUMMON_DEMON: + { + if(m_caster->GetPetGUID()) + return SPELL_FAILED_ALREADY_HAVE_SUMMON; + + if(m_caster->GetCharmGUID()) + return SPELL_FAILED_ALREADY_HAVE_CHARM; + + break; + } + case SPELL_EFFECT_SUMMON_PET: + { + if(m_caster->GetPetGUID()) //let warlock do a replacement summon + { + + Pet* pet = ((Player*)m_caster)->GetPet(); + + if (m_caster->GetTypeId()==TYPEID_PLAYER && m_caster->getClass()==CLASS_WARLOCK) + { + if (strict) //starting cast, trigger pet stun (cast by pet so it doesn't attack player) + pet->CastSpell(pet, 32752, true, NULL, NULL, pet->GetGUID()); + } + else + return SPELL_FAILED_ALREADY_HAVE_SUMMON; + } + + if(m_caster->GetCharmGUID()) + return SPELL_FAILED_ALREADY_HAVE_CHARM; + + break; + } + case SPELL_EFFECT_SUMMON_PLAYER: + { + if(m_caster->GetTypeId()!=TYPEID_PLAYER) + return SPELL_FAILED_BAD_TARGETS; + if(!((Player*)m_caster)->GetSelection()) + return SPELL_FAILED_BAD_TARGETS; + + Player* target = objmgr.GetPlayer(((Player*)m_caster)->GetSelection()); + if( !target || ((Player*)m_caster)==target || !target->IsInSameRaidWith((Player*)m_caster) ) + return SPELL_FAILED_BAD_TARGETS; + + // check if our map is dungeon + if( sMapStore.LookupEntry(m_caster->GetMapId())->IsDungeon() ) + { + InstanceTemplate const* instance = ObjectMgr::GetInstanceTemplate(m_caster->GetMapId()); + if(!instance) + return SPELL_FAILED_TARGET_NOT_IN_INSTANCE; + if ( instance->levelMin > target->getLevel() ) + return SPELL_FAILED_LOWLEVEL; + if ( instance->levelMax && instance->levelMax < target->getLevel() ) + return SPELL_FAILED_HIGHLEVEL; + } + break; + } + case SPELL_EFFECT_LEAP: + case SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER: + { + float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + float fx = m_caster->GetPositionX() + dis * cos(m_caster->GetOrientation()); + float fy = m_caster->GetPositionY() + dis * sin(m_caster->GetOrientation()); + // teleport a bit above terrain level to avoid falling below it + float fz = MapManager::Instance().GetBaseMap(m_caster->GetMapId())->GetHeight(fx,fy,m_caster->GetPositionZ(),true); + if(fz <= INVALID_HEIGHT) // note: this also will prevent use effect in instances without vmaps height enabled + return SPELL_FAILED_TRY_AGAIN; + + float caster_pos_z = m_caster->GetPositionZ(); + // Control the caster to not climb or drop when +-fz > 8 + if(!(fz<=caster_pos_z+8 && fz>=caster_pos_z-8)) + return SPELL_FAILED_TRY_AGAIN; + + // not allow use this effect at battleground until battleground start + if(m_caster->GetTypeId()==TYPEID_PLAYER) + if(BattleGround const *bg = ((Player*)m_caster)->GetBattleGround()) + if(bg->GetStatus() != STATUS_IN_PROGRESS) + return SPELL_FAILED_TRY_AGAIN; + break; + } + case SPELL_EFFECT_STEAL_BENEFICIAL_BUFF: + { + if (m_targets.getUnitTarget()==m_caster) + return SPELL_FAILED_BAD_TARGETS; + break; + } + default:break; + } + } + + for (int i = 0; i < 3; i++) + { + switch(m_spellInfo->EffectApplyAuraName[i]) + { + case SPELL_AURA_MOD_POSSESS: + case SPELL_AURA_MOD_CHARM: + { + if(m_caster->GetPetGUID()) + return SPELL_FAILED_ALREADY_HAVE_SUMMON; + + if(m_caster->GetCharmGUID()) + return SPELL_FAILED_ALREADY_HAVE_CHARM; + + if(m_caster->GetCharmerGUID()) + return SPELL_FAILED_CHARMED; + + if(!m_targets.getUnitTarget()) + return SPELL_FAILED_BAD_IMPLICIT_TARGETS; + + if(m_targets.getUnitTarget()->GetCharmerGUID()) + return SPELL_FAILED_CHARMED; + + if(int32(m_targets.getUnitTarget()->getLevel()) > CalculateDamage(i,m_targets.getUnitTarget())) + return SPELL_FAILED_HIGHLEVEL; + };break; + case SPELL_AURA_MOUNTED: + { + if (m_caster->IsInWater()) + return SPELL_FAILED_ONLY_ABOVEWATER; + + if (m_caster->GetTypeId()==TYPEID_PLAYER && ((Player*)m_caster)->GetTransport()) + return SPELL_FAILED_NO_MOUNTS_ALLOWED; + + // Ignore map check if spell have AreaId. AreaId already checked and this prevent special mount spells + if (m_caster->GetTypeId()==TYPEID_PLAYER && !sMapStore.LookupEntry(m_caster->GetMapId())->IsMountAllowed() && !m_IsTriggeredSpell && !m_spellInfo->AreaId) + return SPELL_FAILED_NO_MOUNTS_ALLOWED; + + if (m_caster->GetAreaId()==35) + return SPELL_FAILED_NO_MOUNTS_ALLOWED; + + ShapeshiftForm form = m_caster->m_form; + if( form == FORM_CAT || form == FORM_TREE || form == FORM_TRAVEL || + form == FORM_AQUA || form == FORM_BEAR || form == FORM_DIREBEAR || + form == FORM_CREATUREBEAR || form == FORM_GHOSTWOLF || form == FORM_FLIGHT || + form == FORM_FLIGHT_EPIC || form == FORM_MOONKIN ) + return SPELL_FAILED_NOT_SHAPESHIFT; + + break; + } + case SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS: + { + if(!m_targets.getUnitTarget()) + return SPELL_FAILED_BAD_IMPLICIT_TARGETS; + + // can be casted at non-friendly unit or own pet/charm + if(m_caster->IsFriendlyTo(m_targets.getUnitTarget())) + return SPELL_FAILED_TARGET_FRIENDLY; + };break; + case SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED: + case SPELL_AURA_FLY: + { + // not allow cast fly spells at old maps by players (all spells is self target) + if(m_caster->GetTypeId()==TYPEID_PLAYER) + { + if( !((Player*)m_caster)->isGameMaster() && + GetVirtualMapForMapAndZone(m_caster->GetMapId(),m_caster->GetZoneId()) != 530) + return SPELL_FAILED_NOT_HERE; + } + };break; + case SPELL_AURA_PERIODIC_MANA_LEECH: + { + if (!m_targets.getUnitTarget()) + return SPELL_FAILED_BAD_IMPLICIT_TARGETS; + + if (m_caster->GetTypeId()!=TYPEID_PLAYER || m_CastItem) + break; + + if(m_targets.getUnitTarget()->getPowerType()!=POWER_MANA) + return SPELL_FAILED_BAD_TARGETS; + break; + } + default:break; + } + } + + // all ok + return 0; +} + +int16 Spell::PetCanCast(Unit* target) +{ + if(!m_caster->isAlive()) + return SPELL_FAILED_CASTER_DEAD; + + if(m_caster->IsNonMeleeSpellCasted(false)) //prevent spellcast interuption by another spellcast + return SPELL_FAILED_SPELL_IN_PROGRESS; + if(m_caster->isInCombat() && IsNonCombatSpell(m_spellInfo)) + return SPELL_FAILED_AFFECTING_COMBAT; + + if(m_caster->GetTypeId()==TYPEID_UNIT && (((Creature*)m_caster)->isPet() || m_caster->isCharmed())) + { + //dead owner (pets still alive when owners ressed?) + if(m_caster->GetCharmerOrOwner() && !m_caster->GetCharmerOrOwner()->isAlive()) + return SPELL_FAILED_CASTER_DEAD; + + if(!target && m_targets.getUnitTarget()) + target = m_targets.getUnitTarget(); + + bool need = false; + for(uint32 i = 0;i<3;i++) + { + if(m_spellInfo->EffectImplicitTargetA[i] == TARGET_CHAIN_DAMAGE || m_spellInfo->EffectImplicitTargetA[i] == TARGET_SINGLE_FRIEND || m_spellInfo->EffectImplicitTargetA[i] == TARGET_DUELVSPLAYER || m_spellInfo->EffectImplicitTargetA[i] == TARGET_SINGLE_PARTY || m_spellInfo->EffectImplicitTargetA[i] == TARGET_CURRENT_ENEMY_COORDINATES) + { + need = true; + if(!target) + return SPELL_FAILED_BAD_IMPLICIT_TARGETS; + break; + } + } + if(need) + m_targets.setUnitTarget(target); + + Unit* _target = m_targets.getUnitTarget(); + + if(_target) //for target dead/target not valid + { + if(!_target->isAlive()) + return SPELL_FAILED_BAD_TARGETS; + + if(IsPositiveSpell(m_spellInfo->Id)) + { + if(m_caster->IsHostileTo(_target)) + return SPELL_FAILED_BAD_TARGETS; + } + else + { + bool duelvsplayertar = false; + for(int j=0;j<3;j++) + { + //TARGET_DUELVSPLAYER is positive AND negative + duelvsplayertar |= (m_spellInfo->EffectImplicitTargetA[j] == TARGET_DUELVSPLAYER); + } + if(m_caster->IsFriendlyTo(target) && !duelvsplayertar) + { + return SPELL_FAILED_BAD_TARGETS; + } + } + } + //cooldown + if(((Creature*)m_caster)->HasSpellCooldown(m_spellInfo->Id)) + return SPELL_FAILED_NOT_READY; + } + + uint16 result = CanCast(true); + if(result != 0) + return result; + else + return -1; //this allows to check spell fail 0, in combat +} + +uint8 Spell::CheckCasterAuras() const +{ + // Flag drop spells totally immuned to caster auras + // FIXME: find more nice check for all totally immuned spells + // AttributesEx3 & 0x10000000? + if(m_spellInfo->Id==23336 || m_spellInfo->Id==23334 || m_spellInfo->Id==34991) + return 0; + + uint8 school_immune = 0; + uint32 mechanic_immune = 0; + uint32 dispel_immune = 0; + + //Check if the spell grants school or mechanic immunity. + //We use bitmasks so the loop is done only once and not on every aura check below. + if ( m_spellInfo->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY ) + { + for(int i = 0;i < 3; i ++) + { + if(m_spellInfo->EffectApplyAuraName[i] == SPELL_AURA_SCHOOL_IMMUNITY) + school_immune |= uint32(m_spellInfo->EffectMiscValue[i]); + else if(m_spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MECHANIC_IMMUNITY) + mechanic_immune |= 1 << uint32(m_spellInfo->EffectMiscValue[i]); + else if(m_spellInfo->EffectApplyAuraName[i] == SPELL_AURA_DISPEL_IMMUNITY) + dispel_immune |= GetDispellMask(DispelType(m_spellInfo->EffectMiscValue[i])); + } + //immune movement impairement and loss of control + if(m_spellInfo->Id==(uint32)42292) + mechanic_immune = IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK; + } + + //Check whether the cast should be prevented by any state you might have. + uint8 prevented_reason = 0; + // Have to check if there is a stun aura. Otherwise will have problems with ghost aura apply while logging out + if(!(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_STUNNED) && m_caster->HasAuraType(SPELL_AURA_MOD_STUN)) + prevented_reason = SPELL_FAILED_STUNNED; + else if(m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED) && !(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_CONFUSED)) + prevented_reason = SPELL_FAILED_CONFUSED; + else if(m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING) && !(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_FEARED)) + prevented_reason = SPELL_FAILED_FLEEING; + else if(m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED) && m_spellInfo->PreventionType==SPELL_PREVENTION_TYPE_SILENCE) + prevented_reason = SPELL_FAILED_SILENCED; + else if(m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED) && m_spellInfo->PreventionType==SPELL_PREVENTION_TYPE_PACIFY) + prevented_reason = SPELL_FAILED_PACIFIED; + + // Attr must make flag drop spell totally immuned from all effects + if(prevented_reason) + { + if(school_immune || mechanic_immune || dispel_immune) + { + //Checking auras is needed now, because you are prevented by some state but the spell grants immunity. + Unit::AuraMap const& auras = m_caster->GetAuras(); + for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); itr++) + { + if(itr->second) + { + if( GetSpellMechanicMask(itr->second->GetSpellProto(), itr->second->GetEffIndex()) & mechanic_immune ) + continue; + if( GetSpellSchoolMask(itr->second->GetSpellProto()) & school_immune ) + continue; + if( (1<<(itr->second->GetSpellProto()->Dispel)) & dispel_immune) + continue; + + //Make a second check for spell failed so the right SPELL_FAILED message is returned. + //That is needed when your casting is prevented by multiple states and you are only immune to some of them. + switch(itr->second->GetModifier()->m_auraname) + { + case SPELL_AURA_MOD_STUN: + if (!(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_STUNNED)) + return SPELL_FAILED_STUNNED; + break; + case SPELL_AURA_MOD_CONFUSE: + if (!(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_CONFUSED)) + return SPELL_FAILED_CONFUSED; + break; + case SPELL_AURA_MOD_FEAR: + if (!(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_FEARED)) + return SPELL_FAILED_FLEEING; + break; + case SPELL_AURA_MOD_SILENCE: + case SPELL_AURA_MOD_PACIFY: + case SPELL_AURA_MOD_PACIFY_SILENCE: + if( m_spellInfo->PreventionType==SPELL_PREVENTION_TYPE_PACIFY) + return SPELL_FAILED_PACIFIED; + else if ( m_spellInfo->PreventionType==SPELL_PREVENTION_TYPE_SILENCE) + return SPELL_FAILED_SILENCED; + break; + } + } + } + } + //You are prevented from casting and the spell casted does not grant immunity. Return a failed error. + else + return prevented_reason; + } + return 0; // all ok +} + +bool Spell::CanAutoCast(Unit* target) +{ + uint64 targetguid = target->GetGUID(); + + for(uint32 j = 0;j<3;j++) + { + if(m_spellInfo->Effect[j] == SPELL_EFFECT_APPLY_AURA) + { + if( m_spellInfo->StackAmount <= 1) + { + if( target->HasAura(m_spellInfo->Id, j) ) + return false; + } + else + { + if( target->GetAuras().count(Unit::spellEffectPair(m_spellInfo->Id, j)) >= m_spellInfo->StackAmount) + return false; + } + } + else if ( IsAreaAuraEffect( m_spellInfo->Effect[j] )) + { + if( target->HasAura(m_spellInfo->Id, j) ) + return false; + } + } + + int16 result = PetCanCast(target); + + if(result == -1 || result == SPELL_FAILED_UNIT_NOT_INFRONT) + { + FillTargetMap(); + //check if among target units, our WANTED target is as well (->only self cast spells return false) + for(std::list::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit) + if( ihit->targetGUID == targetguid ) + return true; + } + return false; //target invalid +} + +uint8 Spell::CheckRange(bool strict) +{ + float range_mod; + + // self cast doesn't need range checking -- also for Starshards fix + if (m_spellInfo->rangeIndex == 1) return 0; + + if (strict) //add radius of caster + range_mod = 1.25; + else //add radius of caster and ~5 yds "give" + range_mod = 6.25; + + SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex); + float max_range = GetSpellMaxRange(srange) + range_mod; + float min_range = GetSpellMinRange(srange); + + if(Player* modOwner = m_caster->GetSpellModOwner()) + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, max_range, this); + + Unit *target = m_targets.getUnitTarget(); + + if(target && target != m_caster) + { + // distance from target center in checks + float dist = m_caster->GetDistance(target->GetPositionX(),target->GetPositionY(),target->GetPositionZ()); + if(dist > max_range) + return SPELL_FAILED_OUT_OF_RANGE; //0x5A; + if(dist < min_range) + return SPELL_FAILED_TOO_CLOSE; + if( !m_IsTriggeredSpell && m_caster->GetTypeId() == TYPEID_PLAYER && + !IsPositiveSpell(m_spellInfo->Id) && !m_caster->HasInArc( M_PI, target ) ) + { + // Spell-Family Related Checks + switch (m_spellInfo->SpellFamilyName) + { + case SPELLFAMILY_PRIEST: + { + // Shadow Word: Death, castable without facing + if (m_spellInfo->SpellFamilyFlags & 0x200000000LL) + return 0; // this is not TARGET_FLAG_DEST_LOCATION so we can return safely + break; + } + case SPELLFAMILY_PALADIN: + { + // Holy Shock, require facing + if (m_spellInfo->SpellFamilyFlags & 0x200000LL) + return SPELL_FAILED_UNIT_NOT_INFRONT; + break; + } + case SPELLFAMILY_WARRIOR: + { + // Charge, require facing + if (m_spellInfo->SpellFamilyFlags & 1) + return SPELL_FAILED_UNIT_NOT_INFRONT; + break; + } + } + + // Ranged Weapon + if (IsRangedSpell()) + return SPELL_FAILED_UNIT_NOT_INFRONT; + + // Melee Combat + if (m_spellInfo->rangeIndex == 2) + return SPELL_FAILED_UNIT_NOT_INFRONT; + + // Missile Effect + if (m_spellInfo->speed > 0) + return SPELL_FAILED_UNIT_NOT_INFRONT; + + // Channeled Spells need facing + if (IsChanneledSpell(m_spellInfo)) + return SPELL_FAILED_UNIT_NOT_INFRONT; + + // Direct Damage and charge effects + for (uint8 i=0;i<3;++i) + { + if (m_spellInfo->Effect[i] == SPELL_EFFECT_SCHOOL_DAMAGE || + m_spellInfo->Effect[i] == SPELL_EFFECT_POWER_BURN || + m_spellInfo->Effect[i] == SPELL_EFFECT_HEALTH_LEECH || + m_spellInfo->Effect[i] == SPELL_EFFECT_CHARGE) + return SPELL_FAILED_UNIT_NOT_INFRONT; + } + } + } + + if(m_targets.m_targetMask == TARGET_FLAG_DEST_LOCATION && m_targets.m_destX != 0 && m_targets.m_destY != 0 && m_targets.m_destZ != 0) + { + float dist = m_caster->GetDistance(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ); + if(dist > max_range) + return SPELL_FAILED_OUT_OF_RANGE; + if(dist < min_range) + return SPELL_FAILED_TOO_CLOSE; + } + + return 0; // ok +} + +int32 Spell::CalculatePowerCost() +{ + // item cast not used power + if(m_CastItem) + return 0; + + // Spell drain all exist power on cast (Only paladin lay of Hands) + if (m_spellInfo->AttributesEx & SPELL_ATTR_EX_DRAIN_ALL_POWER) + { + // If power type - health drain all + if (m_spellInfo->powerType == POWER_HEALTH) + return m_caster->GetHealth(); + // Else drain all power + if (m_spellInfo->powerType < MAX_POWERS) + return m_caster->GetPower(Powers(m_spellInfo->powerType)); + sLog.outError("Spell::CalculateManaCost: Unknown power type '%d' in spell %d", m_spellInfo->powerType, m_spellInfo->Id); + return 0; + } + + // Base powerCost + int32 powerCost = m_spellInfo->manaCost; + // PCT cost from total amount + if (m_spellInfo->ManaCostPercentage) + { + switch (m_spellInfo->powerType) + { + // health as power used + case POWER_HEALTH: + powerCost += m_spellInfo->ManaCostPercentage * m_caster->GetCreateHealth() / 100; + break; + case POWER_MANA: + powerCost += m_spellInfo->ManaCostPercentage * m_caster->GetCreateMana() / 100; + break; + case POWER_RAGE: + case POWER_FOCUS: + case POWER_ENERGY: + case POWER_HAPPINESS: + // case POWER_RUNES: + powerCost += m_spellInfo->ManaCostPercentage * m_caster->GetMaxPower(Powers(m_spellInfo->powerType)) / 100; + break; + default: + sLog.outError("Spell::CalculateManaCost: Unknown power type '%d' in spell %d", m_spellInfo->powerType, m_spellInfo->Id); + return 0; + } + } + SpellSchools school = GetFirstSchoolInMask(m_spellSchoolMask); + // Flat mod from caster auras by spell school + powerCost += m_caster->GetInt32Value(UNIT_FIELD_POWER_COST_MODIFIER + school); + // Shiv - costs 20 + weaponSpeed*10 energy (apply only to non-triggered spell with energy cost) + if ( m_spellInfo->AttributesEx4 & SPELL_ATTR_EX4_SPELL_VS_EXTEND_COST ) + powerCost += m_caster->GetAttackTime(OFF_ATTACK)/100; + // Apply cost mod by spell + if(Player* modOwner = m_caster->GetSpellModOwner()) + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, powerCost, this); + + if(m_spellInfo->Attributes & SPELL_ATTR_LEVEL_DAMAGE_CALCULATION) + powerCost = int32(powerCost/ (1.117f* m_spellInfo->spellLevel / m_caster->getLevel() -0.1327f)); + + // PCT mod from user auras by school + powerCost = int32(powerCost * (1.0f+m_caster->GetFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER+school))); + if (powerCost < 0) + powerCost = 0; + return powerCost; +} + +uint8 Spell::CheckPower() +{ + // item cast not used power + if(m_CastItem) + return 0; + + // health as power used - need check health amount + if(m_spellInfo->powerType == POWER_HEALTH) + { + if(m_caster->GetHealth() <= m_powerCost) + return SPELL_FAILED_CASTER_AURASTATE; + return 0; + } + // Check valid power type + if( m_spellInfo->powerType >= MAX_POWERS ) + { + sLog.outError("Spell::CheckMana: Unknown power type '%d'", m_spellInfo->powerType); + return SPELL_FAILED_UNKNOWN; + } + // Check power amount + Powers powerType = Powers(m_spellInfo->powerType); + if(m_caster->GetPower(powerType) < m_powerCost) + return SPELL_FAILED_NO_POWER; + else + return 0; +} + +uint8 Spell::CheckItems() +{ + if (m_caster->GetTypeId() != TYPEID_PLAYER) + return 0; + + uint32 itemid, itemcount; + Player* p_caster = (Player*)m_caster; + + if(m_CastItem) + { + itemid = m_CastItem->GetEntry(); + if( !p_caster->HasItemCount(itemid,1) ) + return SPELL_FAILED_ITEM_NOT_READY; + else + { + ItemPrototype const *proto = m_CastItem->GetProto(); + if(!proto) + return SPELL_FAILED_ITEM_NOT_READY; + + for (int i = 0; i<5; i++) + { + if (proto->Spells[i].SpellCharges) + { + if(m_CastItem->GetSpellCharges(i)==0) + return SPELL_FAILED_NO_CHARGES_REMAIN; + } + } + + uint32 ItemClass = proto->Class; + if (ItemClass == ITEM_CLASS_CONSUMABLE && m_targets.getUnitTarget()) + { + for (int i = 0; i < 3; i++) + { + // skip check, pet not required like checks, and for TARGET_PET m_targets.getUnitTarget() is not the real target but the caster + if (m_spellInfo->EffectImplicitTargetA[i] == TARGET_PET) + continue; + + if (m_spellInfo->Effect[i] == SPELL_EFFECT_HEAL) + if (m_targets.getUnitTarget()->GetHealth() == m_targets.getUnitTarget()->GetMaxHealth()) + return (uint8)SPELL_FAILED_ALREADY_AT_FULL_HEALTH; + + // Mana Potion, Rage Potion, Thistle Tea(Rogue), ... + if (m_spellInfo->Effect[i] == SPELL_EFFECT_ENERGIZE) + { + if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS) + return (uint8)SPELL_FAILED_ALREADY_AT_FULL_POWER; + + Powers power = Powers(m_spellInfo->EffectMiscValue[i]); + + if (m_targets.getUnitTarget()->GetPower(power) == m_targets.getUnitTarget()->GetMaxPower(power)) + return (uint8)SPELL_FAILED_ALREADY_AT_FULL_POWER; + } + } + } + } + } + + if(m_targets.getItemTargetGUID()) + { + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return SPELL_FAILED_BAD_TARGETS; + + if(!m_targets.getItemTarget()) + return SPELL_FAILED_ITEM_GONE; + + if(!m_targets.getItemTarget()->IsFitToSpellRequirements(m_spellInfo)) + return SPELL_FAILED_EQUIPPED_ITEM_CLASS; + } + // if not item target then required item must be equipped + else + { + if(m_caster->GetTypeId() == TYPEID_PLAYER && !((Player*)m_caster)->HasItemFitToSpellReqirements(m_spellInfo)) + return SPELL_FAILED_EQUIPPED_ITEM_CLASS; + } + + if(m_spellInfo->RequiresSpellFocus) + { + CellPair p(MaNGOS::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + + GameObject* ok = NULL; + MaNGOS::GameObjectFocusCheck go_check(m_caster,m_spellInfo->RequiresSpellFocus); + MaNGOS::GameObjectSearcher checker(ok,go_check); + + TypeContainerVisitor, GridTypeMapContainer > object_checker(checker); + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, object_checker, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)); + + if(!ok) + return (uint8)SPELL_FAILED_REQUIRES_SPELL_FOCUS; + + focusObject = ok; // game object found in range + } + + if (!(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_NO_REAGENT_WHILE_PREP && + m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION))) + { + for(uint32 i=0;i<8;i++) + { + if(m_spellInfo->Reagent[i] <= 0) + continue; + + itemid = m_spellInfo->Reagent[i]; + itemcount = m_spellInfo->ReagentCount[i]; + + // if CastItem is also spell reagent + if( m_CastItem && m_CastItem->GetEntry() == itemid ) + { + ItemPrototype const *proto = m_CastItem->GetProto(); + if(!proto) + return SPELL_FAILED_ITEM_NOT_READY; + for(int s=0;s<5;s++) + { + // CastItem will be used up and does not count as reagent + int32 charges = m_CastItem->GetSpellCharges(s); + if (proto->Spells[s].SpellCharges < 0 && abs(charges) < 2) + { + ++itemcount; + break; + } + } + } + if( !p_caster->HasItemCount(itemid,itemcount) ) + return (uint8)SPELL_FAILED_ITEM_NOT_READY; //0x54 + } + } + + uint32 totems = 2; + for(int i=0;i<2;++i) + { + if(m_spellInfo->Totem[i] != 0) + { + if( p_caster->HasItemCount(m_spellInfo->Totem[i],1) ) + { + totems -= 1; + continue; + } + }else + totems -= 1; + } + if(totems != 0) + return (uint8)SPELL_FAILED_TOTEMS; //0x7C + + //Check items for TotemCategory + uint32 TotemCategory = 2; + for(int i=0;i<2;++i) + { + if(m_spellInfo->TotemCategory[i] != 0) + { + if( p_caster->HasItemTotemCategory(m_spellInfo->TotemCategory[i]) ) + { + TotemCategory -= 1; + continue; + } + } + else + TotemCategory -= 1; + } + if(TotemCategory != 0) + return (uint8)SPELL_FAILED_TOTEM_CATEGORY; //0x7B + + for(int i = 0; i < 3; i++) + { + switch (m_spellInfo->Effect[i]) + { + case SPELL_EFFECT_CREATE_ITEM: + { + if (!m_IsTriggeredSpell && m_spellInfo->EffectItemType[i]) + { + ItemPosCountVec dest; + uint8 msg = p_caster->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, m_spellInfo->EffectItemType[i], 1 ); + if (msg != EQUIP_ERR_OK ) + { + p_caster->SendEquipError( msg, NULL, NULL ); + return SPELL_FAILED_DONT_REPORT; + } + } + break; + } + case SPELL_EFFECT_ENCHANT_ITEM: + { + Item* targetItem = m_targets.getItemTarget(); + if(!targetItem) + return SPELL_FAILED_ITEM_NOT_FOUND; + + if( targetItem->GetProto()->ItemLevel < m_spellInfo->baseLevel ) + return SPELL_FAILED_LOWLEVEL; + // Not allow enchant in trade slot for some enchant type + if( targetItem->GetOwner() != m_caster ) + { + uint32 enchant_id = m_spellInfo->EffectMiscValue[i]; + SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id); + if(!pEnchant) + return SPELL_FAILED_ERROR; + if (pEnchant->slot & ENCHANTMENT_CAN_SOULBOUND) + return SPELL_FAILED_NOT_TRADEABLE; + } + break; + } + case SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY: + { + Item *item = m_targets.getItemTarget(); + if(!item) + return SPELL_FAILED_ITEM_NOT_FOUND; + // Not allow enchant in trade slot for some enchant type + if( item->GetOwner() != m_caster ) + { + uint32 enchant_id = m_spellInfo->EffectMiscValue[i]; + SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id); + if(!pEnchant) + return SPELL_FAILED_ERROR; + if (pEnchant->slot & ENCHANTMENT_CAN_SOULBOUND) + return SPELL_FAILED_NOT_TRADEABLE; + } + break; + } + case SPELL_EFFECT_ENCHANT_HELD_ITEM: + // check item existence in effect code (not output errors at offhand hold item effect to main hand for example + break; + case SPELL_EFFECT_DISENCHANT: + { + if(!m_targets.getItemTarget()) + return SPELL_FAILED_CANT_BE_DISENCHANTED; + + // prevent disenchanting in trade slot + if( m_targets.getItemTarget()->GetOwnerGUID() != m_caster->GetGUID() ) + return SPELL_FAILED_CANT_BE_DISENCHANTED; + + ItemPrototype const* itemProto = m_targets.getItemTarget()->GetProto(); + if(!itemProto) + return SPELL_FAILED_CANT_BE_DISENCHANTED; + + uint32 item_quality = itemProto->Quality; + // 2.0.x addon: Check player enchanting level agains the item desenchanting requirements + uint32 item_disenchantskilllevel = itemProto->RequiredDisenchantSkill; + if (item_disenchantskilllevel == uint32(-1)) + return SPELL_FAILED_CANT_BE_DISENCHANTED; + if (item_disenchantskilllevel > p_caster->GetSkillValue(SKILL_ENCHANTING)) + return SPELL_FAILED_LOW_CASTLEVEL; + if(item_quality > 4 || item_quality < 2) + return SPELL_FAILED_CANT_BE_DISENCHANTED; + if(itemProto->Class != ITEM_CLASS_WEAPON && itemProto->Class != ITEM_CLASS_ARMOR) + return SPELL_FAILED_CANT_BE_DISENCHANTED; + if (!itemProto->DisenchantID) + return SPELL_FAILED_CANT_BE_DISENCHANTED; + break; + } + case SPELL_EFFECT_PROSPECTING: + { + if(!m_targets.getItemTarget()) + return SPELL_FAILED_CANT_BE_PROSPECTED; + //ensure item is a prospectable ore + if(!(m_targets.getItemTarget()->GetProto()->BagFamily & BAG_FAMILY_MASK_MINING_SUPP) || m_targets.getItemTarget()->GetProto()->Class != ITEM_CLASS_TRADE_GOODS) + return SPELL_FAILED_CANT_BE_PROSPECTED; + //prevent prospecting in trade slot + if( m_targets.getItemTarget()->GetOwnerGUID() != m_caster->GetGUID() ) + return SPELL_FAILED_CANT_BE_PROSPECTED; + //Check for enough skill in jewelcrafting + uint32 item_prospectingskilllevel = m_targets.getItemTarget()->GetProto()->RequiredSkillRank; + if(item_prospectingskilllevel >p_caster->GetSkillValue(SKILL_JEWELCRAFTING)) + return SPELL_FAILED_LOW_CASTLEVEL; + //make sure the player has the required ores in inventory + if(m_targets.getItemTarget()->GetCount() < 5) + return SPELL_FAILED_PROSPECT_NEED_MORE; + + if(!LootTemplates_Prospecting.HaveLootFor(m_targets.getItemTargetEntry())) + return SPELL_FAILED_CANT_BE_PROSPECTED; + + break; + } + case SPELL_EFFECT_WEAPON_DAMAGE: + case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: + { + if(m_caster->GetTypeId() != TYPEID_PLAYER) return SPELL_FAILED_TARGET_NOT_PLAYER; + if( m_attackType != RANGED_ATTACK ) + break; + Item *pItem = ((Player*)m_caster)->GetWeaponForAttack(m_attackType); + if(!pItem || pItem->IsBroken()) + return SPELL_FAILED_EQUIPPED_ITEM; + + switch(pItem->GetProto()->SubClass) + { + case ITEM_SUBCLASS_WEAPON_THROWN: + { + uint32 ammo = pItem->GetEntry(); + if( !((Player*)m_caster)->HasItemCount( ammo, 1 ) ) + return SPELL_FAILED_NO_AMMO; + }; break; + case ITEM_SUBCLASS_WEAPON_GUN: + case ITEM_SUBCLASS_WEAPON_BOW: + case ITEM_SUBCLASS_WEAPON_CROSSBOW: + { + uint32 ammo = ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID); + if(!ammo) + { + // Requires No Ammo + if(m_caster->GetDummyAura(46699)) + break; // skip other checks + + return SPELL_FAILED_NO_AMMO; + } + + ItemPrototype const *ammoProto = objmgr.GetItemPrototype( ammo ); + if(!ammoProto) + return SPELL_FAILED_NO_AMMO; + + if(ammoProto->Class != ITEM_CLASS_PROJECTILE) + return SPELL_FAILED_NO_AMMO; + + // check ammo ws. weapon compatibility + switch(pItem->GetProto()->SubClass) + { + case ITEM_SUBCLASS_WEAPON_BOW: + case ITEM_SUBCLASS_WEAPON_CROSSBOW: + if(ammoProto->SubClass!=ITEM_SUBCLASS_ARROW) + return SPELL_FAILED_NO_AMMO; + break; + case ITEM_SUBCLASS_WEAPON_GUN: + if(ammoProto->SubClass!=ITEM_SUBCLASS_BULLET) + return SPELL_FAILED_NO_AMMO; + break; + default: + return SPELL_FAILED_NO_AMMO; + } + + if( !((Player*)m_caster)->HasItemCount( ammo, 1 ) ) + return SPELL_FAILED_NO_AMMO; + }; break; + case ITEM_SUBCLASS_WEAPON_WAND: + default: + break; + } + break; + } + default:break; + } + } + + return uint8(0); +} + +void Spell::Delayed() +{ + if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + if (m_spellState == SPELL_STATE_DELAYED) + return; // spell is active and can't be time-backed + + // spells not loosing casting time ( slam, dynamites, bombs.. ) + if(!(m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_DAMAGE)) + return; + + //check resist chance + int32 resistChance = 100; //must be initialized to 100 for percent modifiers + ((Player*)m_caster)->ApplySpellMod(m_spellInfo->Id,SPELLMOD_NOT_LOSE_CASTING_TIME,resistChance, this); + resistChance += m_caster->GetTotalAuraModifier(SPELL_AURA_RESIST_PUSHBACK) - 100; + if (roll_chance_i(resistChance)) + return; + + int32 delaytime = GetNextDelayAtDamageMsTime(); + + if(int32(m_timer) + delaytime > m_casttime) + { + delaytime = m_casttime - m_timer; + m_timer = m_casttime; + } + else + m_timer += delaytime; + + sLog.outDetail("Spell %u partially interrupted for (%d) ms at damage",m_spellInfo->Id,delaytime); + + WorldPacket data(SMSG_SPELL_DELAYED, 8+4); + data.append(m_caster->GetPackGUID()); + data << uint32(delaytime); + + m_caster->SendMessageToSet(&data,true); +} + +void Spell::DelayedChannel() +{ + if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER || getState() != SPELL_STATE_CASTING) + return; + + //check resist chance + int32 resistChance = 100; //must be initialized to 100 for percent modifiers + ((Player*)m_caster)->ApplySpellMod(m_spellInfo->Id,SPELLMOD_NOT_LOSE_CASTING_TIME,resistChance, this); + resistChance += m_caster->GetTotalAuraModifier(SPELL_AURA_RESIST_PUSHBACK) - 100; + if (roll_chance_i(resistChance)) + return; + + int32 delaytime = GetNextDelayAtDamageMsTime(); + + if(int32(m_timer) < delaytime) + { + delaytime = m_timer; + m_timer = 0; + } + else + m_timer -= delaytime; + + sLog.outDebug("Spell %u partially interrupted for %i ms, new duration: %u ms", m_spellInfo->Id, delaytime, m_timer); + + for(std::list::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit) + { + if ((*ihit).missCondition == SPELL_MISS_NONE) + { + Unit* unit = m_caster->GetGUID()==ihit->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID); + if (unit) + { + for (int j=0;j<3;j++) + if( ihit->effectMask & (1<DelayAura(m_spellInfo->Id, j, delaytime); + } + + } + } + + for(int j = 0; j < 3; j++) + { + // partially interrupt persistent area auras + DynamicObject* dynObj = m_caster->GetDynObject(m_spellInfo->Id, j); + if(dynObj) + dynObj->Delay(delaytime); + } + + SendChannelUpdate(m_timer); +} + +void Spell::UpdatePointers() +{ + if(m_originalCasterGUID==m_caster->GetGUID()) + m_originalCaster = m_caster; + else + { + m_originalCaster = ObjectAccessor::GetUnit(*m_caster,m_originalCasterGUID); + if(m_originalCaster && !m_originalCaster->IsInWorld()) m_originalCaster = NULL; + } + + m_targets.Update(m_caster); +} + +bool Spell::IsAffectedBy(SpellEntry const *spellInfo, uint32 effectId) +{ + return spellmgr.IsAffectedBySpell(m_spellInfo,spellInfo->Id,effectId,spellInfo->EffectItemType[effectId]); +} + +bool Spell::CheckTargetCreatureType(Unit* target) const +{ + uint32 spellCreatureTargetMask = m_spellInfo->TargetCreatureType; + + // Curse of Doom : not find another way to fix spell target check :/ + if(m_spellInfo->SpellFamilyName==SPELLFAMILY_WARLOCK && m_spellInfo->SpellFamilyFlags == 0x0200000000LL) + { + // not allow cast at player + if(target->GetTypeId()==TYPEID_PLAYER) + return false; + + spellCreatureTargetMask = 0x7FF; + } + + // Dismiss Pet and Taming Lesson skipped + if(m_spellInfo->Id == 2641 || m_spellInfo->Id == 23356) + spellCreatureTargetMask = 0; + + if (spellCreatureTargetMask) + { + uint32 TargetCreatureType = target->GetCreatureTypeMask(); + + return !TargetCreatureType || (spellCreatureTargetMask & TargetCreatureType); + } + return true; +} + +CurrentSpellTypes Spell::GetCurrentContainer() +{ + if (IsNextMeleeSwingSpell()) + return(CURRENT_MELEE_SPELL); + else if (IsAutoRepeat()) + return(CURRENT_AUTOREPEAT_SPELL); + else if (IsChanneledSpell(m_spellInfo)) + return(CURRENT_CHANNELED_SPELL); + else + return(CURRENT_GENERIC_SPELL); +} + +bool Spell::CheckTarget( Unit* target, uint32 eff, bool hitPhase ) +{ + // Check targets for creature type mask and remove not appropriate (skip explicit self target case, maybe need other explicit targets) + if(m_spellInfo->EffectImplicitTargetA[eff]!=TARGET_SELF ) + { + if (!CheckTargetCreatureType(target)) + return false; + } + + // Check targets for not_selectable unit flag and remove + // A player can cast spells on his pet (or other controlled unit) though in any state + if (target != m_caster && target->GetCharmerOrOwnerGUID() != m_caster->GetGUID()) + { + // any unattackable target skipped + if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return false; + + // unselectable targets skipped in all cases except TARGET_SCRIPT targeting + // in case TARGET_SCRIPT target selected by server always and can't be cheated + if( target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE) && + m_spellInfo->EffectImplicitTargetA[eff] != TARGET_SCRIPT && + m_spellInfo->EffectImplicitTargetB[eff] != TARGET_SCRIPT ) + return false; + } + + //Check player targets and remove if in GM mode or GM invisibility (for not self casting case) + if( target != m_caster && target->GetTypeId()==TYPEID_PLAYER) + { + if(((Player*)target)->GetVisibility()==VISIBILITY_OFF) + return false; + + if(((Player*)target)->isGameMaster() && !IsPositiveSpell(m_spellInfo->Id)) + return false; + } + + //Check targets for LOS visibility (except spells without range limitations ) + switch(m_spellInfo->Effect[eff]) + { + case SPELL_EFFECT_SUMMON_PLAYER: // from anywhere + break; + case SPELL_EFFECT_DUMMY: + if(m_spellInfo->Id!=20577) // Cannibalize + break; + //fall through + case SPELL_EFFECT_RESURRECT_NEW: + // player far away, maybe his corpse near? + if(target!=m_caster && !target->IsWithinLOSInMap(m_caster)) + { + if(!m_targets.getCorpseTargetGUID()) + return false; + + Corpse *corpse = ObjectAccessor::GetCorpse(*m_caster,m_targets.getCorpseTargetGUID()); + if(!corpse) + return false; + + if(target->GetGUID()!=corpse->GetOwnerGUID()) + return false; + + if(!corpse->IsWithinLOSInMap(m_caster)) + return false; + } + + // all ok by some way or another, skip normal check + break; + default: // normal case + if(target!=m_caster && !target->IsWithinLOSInMap(m_caster)) + return false; + break; + } + + return true; +} + +Unit* Spell::SelectMagnetTarget() +{ + Unit* target = m_targets.getUnitTarget(); + + if(target && target->HasAuraType(SPELL_AURA_SPELL_MAGNET) && !(m_spellInfo->Attributes & 0x10)) + { + Unit::AuraList const& magnetAuras = target->GetAurasByType(SPELL_AURA_SPELL_MAGNET); + for(Unit::AuraList::const_iterator itr = magnetAuras.begin(); itr != magnetAuras.end(); ++itr) + { + if(Unit* magnet = (*itr)->GetCaster()) + { + if(magnet->IsWithinLOSInMap(m_caster)) + { + target = magnet; + m_targets.setUnitTarget(target); + break; + } + } + } + } + + return target; +} + +bool Spell::IsNeedSendToClient() const +{ + return m_spellInfo->SpellVisual!=0 || IsChanneledSpell(m_spellInfo) || + m_spellInfo->speed > 0.0f || !m_triggeredByAuraSpell && !m_IsTriggeredSpell; +} + +bool Spell::HaveTargetsForEffect( uint8 effect ) const +{ + for(std::list::const_iterator itr= m_UniqueTargetInfo.begin();itr != m_UniqueTargetInfo.end();++itr) + if(itr->effectMask & (1<::const_iterator itr= m_UniqueGOTargetInfo.begin();itr != m_UniqueGOTargetInfo.end();++itr) + if(itr->effectMask & (1<::const_iterator itr= m_UniqueItemInfo.begin();itr != m_UniqueItemInfo.end();++itr) + if(itr->effectMask & (1<getState() != SPELL_STATE_FINISHED) + m_Spell->cancel(); + + if (m_Spell->IsDeletable()) + { + delete m_Spell; + } + else + { + sLog.outError("~SpellEvent: %s %u tried to delete non-deletable spell %u. Was not deleted, causes memory leak.", + (m_Spell->GetCaster()->GetTypeId()==TYPEID_PLAYER?"Player":"Creature"), m_Spell->GetCaster()->GetGUIDLow(),m_Spell->m_spellInfo->Id); + } +} + +bool SpellEvent::Execute(uint64 e_time, uint32 p_time) +{ + // update spell if it is not finished + if (m_Spell->getState() != SPELL_STATE_FINISHED) + m_Spell->update(p_time); + + // check spell state to process + switch (m_Spell->getState()) + { + case SPELL_STATE_FINISHED: + { + // spell was finished, check deletable state + if (m_Spell->IsDeletable()) + { + // check, if we do have unfinished triggered spells + + return(true); // spell is deletable, finish event + } + // event will be re-added automatically at the end of routine) + } break; + + case SPELL_STATE_CASTING: + { + // this spell is in channeled state, process it on the next update + // event will be re-added automatically at the end of routine) + } break; + + case SPELL_STATE_DELAYED: + { + // first, check, if we have just started + if (m_Spell->GetDelayStart() != 0) + { + // no, we aren't, do the typical update + // check, if we have channeled spell on our hands + if (IsChanneledSpell(m_Spell->m_spellInfo)) + { + // evented channeled spell is processed separately, casted once after delay, and not destroyed till finish + // check, if we have casting anything else except this channeled spell and autorepeat + if (m_Spell->GetCaster()->IsNonMeleeSpellCasted(false, true, true)) + { + // another non-melee non-delayed spell is casted now, abort + m_Spell->cancel(); + } + else + { + // do the action (pass spell to channeling state) + m_Spell->handle_immediate(); + } + // event will be re-added automatically at the end of routine) + } + else + { + // run the spell handler and think about what we can do next + uint64 t_offset = e_time - m_Spell->GetDelayStart(); + uint64 n_offset = m_Spell->handle_delayed(t_offset); + if (n_offset) + { + // re-add us to the queue + m_Spell->GetCaster()->m_Events.AddEvent(this, m_Spell->GetDelayStart() + n_offset, false); + return(false); // event not complete + } + // event complete + // finish update event will be re-added automatically at the end of routine) + } + } + else + { + // delaying had just started, record the moment + m_Spell->SetDelayStart(e_time); + // re-plan the event for the delay moment + m_Spell->GetCaster()->m_Events.AddEvent(this, e_time + m_Spell->GetDelayMoment(), false); + return(false); // event not complete + } + } break; + + default: + { + // all other states + // event will be re-added automatically at the end of routine) + } break; + } + + // spell processing not complete, plan event on the next update interval + m_Spell->GetCaster()->m_Events.AddEvent(this, e_time + 1, false); + return(false); // event not complete +} + +void SpellEvent::Abort(uint64 /*e_time*/) +{ + // oops, the spell we try to do is aborted + if (m_Spell->getState() != SPELL_STATE_FINISHED) + m_Spell->cancel(); +} diff --git a/src/game/Spell.h b/src/game/Spell.h new file mode 100644 index 00000000000..898d74de0f2 --- /dev/null +++ b/src/game/Spell.h @@ -0,0 +1,694 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __SPELL_H +#define __SPELL_H + +#include "GridDefines.h" + +class WorldSession; +class Unit; +class DynamicObj; +class Player; +class GameObject; +class Group; +class Aura; + +enum SpellCastTargetFlags +{ + /*TARGET_FLAG_NONE = 0x0000, + TARGET_FLAG_SWIMMER = 0x0002, + TARGET_FLAG_ITEM = 0x0010, + TARGET_FLAG_SOURCE_AREA = 0x0020, + TARGET_FLAG_DEST_AREA = 0x0040, + TARGET_FLAG_UNKNOWN = 0x0080, + TARGET_FLAG_SELF = 0x0100, + TARGET_FLAG_PVP_CORPSE = 0x0200, + TARGET_FLAG_MASS_SPIRIT_HEAL = 0x0400, + TARGET_FLAG_BEAST_CORPSE = 0x0402, + TARGET_FLAG_OBJECT = 0x4000, + TARGET_FLAG_RESURRECTABLE = 0x8000*/ + + TARGET_FLAG_SELF = 0x00000000, + TARGET_FLAG_UNIT = 0x00000002, // pguid + TARGET_FLAG_ITEM = 0x00000010, // pguid + TARGET_FLAG_SOURCE_LOCATION = 0x00000020, // 3 float + TARGET_FLAG_DEST_LOCATION = 0x00000040, // 3 float + TARGET_FLAG_OBJECT_UNK = 0x00000080, // ? + TARGET_FLAG_PVP_CORPSE = 0x00000200, // pguid + TARGET_FLAG_OBJECT = 0x00000800, // pguid + TARGET_FLAG_TRADE_ITEM = 0x00001000, // pguid + TARGET_FLAG_STRING = 0x00002000, // string + TARGET_FLAG_UNK1 = 0x00004000, // ? + TARGET_FLAG_CORPSE = 0x00008000, // pguid + TARGET_FLAG_UNK2 = 0x00010000 // pguid +}; + +enum SpellCastFlags +{ + CAST_FLAG_UNKNOWN1 = 0x00000002, + CAST_FLAG_UNKNOWN2 = 0x00000010, + CAST_FLAG_AMMO = 0x00000020, + CAST_FLAG_UNKNOWN3 = 0x00000100 +}; + +enum SpellNotifyPushType +{ + PUSH_IN_FRONT, + PUSH_IN_BACK, + PUSH_SELF_CENTER, + PUSH_DEST_CENTER, + PUSH_TARGET_CENTER +}; + +bool IsQuestTameSpell(uint32 spellId); + +namespace MaNGOS +{ + struct SpellNotifierPlayer; + struct SpellNotifierCreatureAndPlayer; +} + +class SpellCastTargets +{ + public: + SpellCastTargets(); + ~SpellCastTargets(); + + bool read ( WorldPacket * data, Unit *caster ); + void write ( WorldPacket * data ); + + SpellCastTargets& operator=(const SpellCastTargets &target) + { + m_unitTarget = target.m_unitTarget; + m_itemTarget = target.m_itemTarget; + m_GOTarget = target.m_GOTarget; + + m_unitTargetGUID = target.m_unitTargetGUID; + m_GOTargetGUID = target.m_GOTargetGUID; + m_CorpseTargetGUID = target.m_CorpseTargetGUID; + m_itemTargetGUID = target.m_itemTargetGUID; + + m_itemTargetEntry = target.m_itemTargetEntry; + + m_srcX = target.m_srcX; + m_srcY = target.m_srcY; + m_srcZ = target.m_srcZ; + + m_destX = target.m_destX; + m_destY = target.m_destY; + m_destZ = target.m_destZ; + + m_strTarget = target.m_strTarget; + + m_targetMask = target.m_targetMask; + + return *this; + } + + uint64 getUnitTargetGUID() const { return m_unitTargetGUID; } + Unit *getUnitTarget() const { return m_unitTarget; } + void setUnitTarget(Unit *target); + void setDestination(float x, float y, float z); + + uint64 getGOTargetGUID() const { return m_GOTargetGUID; } + GameObject *getGOTarget() const { return m_GOTarget; } + void setGOTarget(GameObject *target); + + uint64 getCorpseTargetGUID() const { return m_CorpseTargetGUID; } + void setCorpseTarget(Corpse* corpse); + uint64 getItemTargetGUID() const { return m_itemTargetGUID; } + Item* getItemTarget() const { return m_itemTarget; } + uint32 getItemTargetEntry() const { return m_itemTargetEntry; } + void setItemTarget(Item* item); + void updateTradeSlotItem() + { + if(m_itemTarget && (m_targetMask & TARGET_FLAG_TRADE_ITEM)) + { + m_itemTargetGUID = m_itemTarget->GetGUID(); + m_itemTargetEntry = m_itemTarget->GetEntry(); + } + } + + bool IsEmpty() const { return m_GOTargetGUID==0 && m_unitTargetGUID==0 && m_itemTarget==0 && m_CorpseTargetGUID==0; } + + void Update(Unit* caster); + + float m_srcX, m_srcY, m_srcZ; + float m_destX, m_destY, m_destZ; + std::string m_strTarget; + + uint32 m_targetMask; + private: + // objects (can be used at spell creating and after Update at casting + Unit *m_unitTarget; + GameObject *m_GOTarget; + Item *m_itemTarget; + + // object GUID/etc, can be used always + uint64 m_unitTargetGUID; + uint64 m_GOTargetGUID; + uint64 m_CorpseTargetGUID; + uint64 m_itemTargetGUID; + uint32 m_itemTargetEntry; +}; + +enum SpellState +{ + SPELL_STATE_NULL = 0, + SPELL_STATE_PREPARING = 1, + SPELL_STATE_CASTING = 2, + SPELL_STATE_FINISHED = 3, + SPELL_STATE_IDLE = 4, + SPELL_STATE_DELAYED = 5 +}; + +#define SPELL_SPELL_CHANNEL_UPDATE_INTERVAL 1000 + +typedef std::multimap SpellTargetTimeMap; + +class Spell +{ + friend struct MaNGOS::SpellNotifierPlayer; + friend struct MaNGOS::SpellNotifierCreatureAndPlayer; + public: + + void EffectNULL(uint32 ); + void EffectUnused(uint32 ); + void EffectDistract(uint32 i); + void EffectPull(uint32 i); + void EffectSchoolDMG(uint32 i); + void EffectEnvirinmentalDMG(uint32 i); + void EffectInstaKill(uint32 i); + void EffectDummy(uint32 i); + void EffectTeleportUnits(uint32 i); + void EffectApplyAura(uint32 i); + void EffectSendEvent(uint32 i); + void EffectPowerBurn(uint32 i); + void EffectPowerDrain(uint32 i); + void EffectHeal(uint32 i); + void EffectHealthLeech(uint32 i); + void EffectQuestComplete(uint32 i); + void EffectCreateItem(uint32 i); + void EffectPersistentAA(uint32 i); + void EffectEnergize(uint32 i); + void EffectOpenLock(uint32 i); + void EffectSummonChangeItem(uint32 i); + void EffectOpenSecretSafe(uint32 i); + void EffectProficiency(uint32 i); + void EffectApplyAreaAura(uint32 i); + void EffectSummonType(uint32 i); + void EffectSummon(uint32 i); + void EffectLearnSpell(uint32 i); + void EffectDispel(uint32 i); + void EffectDualWield(uint32 i); + void EffectPickPocket(uint32 i); + void EffectAddFarsight(uint32 i); + void EffectSummonWild(uint32 i); + void EffectSummonGuardian(uint32 i); + void EffectHealMechanical(uint32 i); + void EffectTeleUnitsFaceCaster(uint32 i); + void EffectLearnSkill(uint32 i); + void EffectAddHonor(uint32 i); + void EffectTradeSkill(uint32 i); + void EffectEnchantItemPerm(uint32 i); + void EffectEnchantItemTmp(uint32 i); + void EffectTameCreature(uint32 i); + void EffectSummonPet(uint32 i); + void EffectLearnPetSpell(uint32 i); + void EffectWeaponDmg(uint32 i); + void EffectForceCast(uint32 i); + void EffectTriggerSpell(uint32 i); + void EffectTriggerMissileSpell(uint32 i); + void EffectThreat(uint32 i); + void EffectHealMaxHealth(uint32 i); + void EffectInterruptCast(uint32 i); + void EffectSummonObjectWild(uint32 i); + void EffectScriptEffect(uint32 i); + void EffectSanctuary(uint32 i); + void EffectAddComboPoints(uint32 i); + void EffectDuel(uint32 i); + void EffectStuck(uint32 i); + void EffectSummonPlayer(uint32 i); + void EffectActivateObject(uint32 i); + void EffectSummonTotem(uint32 i); + void EffectEnchantHeldItem(uint32 i); + void EffectSummonObject(uint32 i); + void EffectResurrect(uint32 i); + void EffectParry(uint32 i); + void EffectMomentMove(uint32 i); + void EffectTransmitted(uint32 i); + void EffectDisEnchant(uint32 i); + void EffectInebriate(uint32 i); + void EffectFeedPet(uint32 i); + void EffectDismissPet(uint32 i); + void EffectReputation(uint32 i); + void EffectSelfResurrect(uint32 i); + void EffectSkinning(uint32 i); + void EffectCharge(uint32 i); + void EffectProspecting(uint32 i); + void EffectSendTaxi(uint32 i); + void EffectSummonCritter(uint32 i); + void EffectKnockBack(uint32 i); + void EffectPlayerPull(uint32 i); + void EffectDispelMechanic(uint32 i); + void EffectSummonDeadPet(uint32 i); + void EffectDestroyAllTotems(uint32 i); + void EffectDurabilityDamage(uint32 i); + void EffectSkill(uint32 i); + void EffectTaunt(uint32 i); + void EffectDurabilityDamagePCT(uint32 i); + void EffectModifyThreatPercent(uint32 i); + void EffectResurrectNew(uint32 i); + void EffectAddExtraAttacks(uint32 i); + void EffectSpiritHeal(uint32 i); + void EffectSkinPlayerCorpse(uint32 i); + void EffectSummonDemon(uint32 i); + void EffectStealBeneficialBuff(uint32 i); + void EffectUnlearnSpecialization(uint32 i); + void EffectHealPct(uint32 i); + void EffectEnergisePct(uint32 i); + void EffectTriggerSpellWithValue(uint32 i); + void EffectTriggerRitualOfSummoning(uint32 i); + void EffectKillCredit(uint32 i); + void EffectQuestFail(uint32 i); + + Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 originalCasterGUID = 0, Spell** triggeringContainer = NULL ); + ~Spell(); + + void prepare(SpellCastTargets * targets, Aura* triggeredByAura = NULL); + void cancel(); + void update(uint32 difftime); + void cast(bool skipCheck = false); + void finish(bool ok = true); + void TakePower(); + void TakeReagents(); + void TakeCastItem(); + void TriggerSpell(); + uint8 CanCast(bool strict); + int16 PetCanCast(Unit* target); + bool CanAutoCast(Unit* target); + + // handlers + void handle_immediate(); + uint64 handle_delayed(uint64 t_offset); + // handler helpers + void _handle_immediate_phase(); + void _handle_finish_phase(); + + uint8 CheckItems(); + uint8 CheckRange(bool strict); + uint8 CheckPower(); + uint8 CheckCasterAuras() const; + + int32 CalculateDamage(uint8 i, Unit* target) { return m_caster->CalculateSpellDamage(m_spellInfo,i,m_currentBasePoints[i],target); } + int32 CalculatePowerCost(); + + bool HaveTargetsForEffect(uint8 effect) const; + void Delayed(); + void DelayedChannel(); + inline uint32 getState() const { return m_spellState; } + void setState(uint32 state) { m_spellState = state; } + + void DoCreateItem(uint32 i, uint32 itemtype); + + void WriteSpellGoTargets( WorldPacket * data ); + void WriteAmmoToPacket( WorldPacket * data ); + void FillTargetMap(); + + void SetTargetMap(uint32 i,uint32 cur,std::list &TagUnitMap); + + Unit* SelectMagnetTarget(); + bool CheckTarget( Unit* target, uint32 eff, bool hitPhase ); + + void SendCastResult(uint8 result); + void SendSpellStart(); + void SendSpellGo(); + void SendSpellCooldown(); + void SendLogExecute(); + void SendInterrupted(uint8 result); + void SendChannelUpdate(uint32 time); + void SendChannelStart(uint32 duration); + void SendResurrectRequest(Player* target); + void SendPlaySpellVisual(uint32 SpellID); + + void HandleEffects(Unit *pUnitTarget,Item *pItemTarget,GameObject *pGOTarget,uint32 i, float DamageMultiplier = 1.0); + void HandleThreatSpells(uint32 spellId); + //void HandleAddAura(Unit* Target); + + SpellEntry const* m_spellInfo; + int32 m_currentBasePoints[3]; // cache SpellEntry::EffectBasePoints and use for set custom base points + Item* m_CastItem; + uint8 m_cast_count; + SpellCastTargets m_targets; + + int32 GetCastTime() const { return m_casttime; } + bool IsAutoRepeat() const { return m_autoRepeat; } + void SetAutoRepeat(bool rep) { m_autoRepeat = rep; } + void ReSetTimer() { m_timer = m_casttime > 0 ? m_casttime : 0; } + bool IsNextMeleeSwingSpell() const + { + return m_spellInfo->Attributes & (SPELL_ATTR_ON_NEXT_SWING_1|SPELL_ATTR_ON_NEXT_SWING_2); + } + bool IsRangedSpell() const + { + return m_spellInfo->Attributes & SPELL_ATTR_RANGED; + } + bool IsChannelActive() const { return m_caster->GetUInt32Value(UNIT_CHANNEL_SPELL) != 0; } + bool IsMeleeAttackResetSpell() const { return !m_IsTriggeredSpell && (m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_AUTOATTACK); } + bool IsRangedAttackResetSpell() const { return !m_IsTriggeredSpell && IsRangedSpell() && (m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_AUTOATTACK); } + + bool IsDeletable() const { return m_deletable; } + void SetDeletable(bool deletable) { m_deletable = deletable; } + uint64 GetDelayStart() const { return m_delayStart; } + void SetDelayStart(uint64 m_time) { m_delayStart = m_time; } + uint64 GetDelayMoment() const { return m_delayMoment; } + + bool IsNeedSendToClient() const; + + CurrentSpellTypes GetCurrentContainer(); + + Unit* GetCaster() const { return m_caster; } + Unit* GetOriginalCaster() const { return m_originalCaster; } + int32 GetPowerCost() const { return m_powerCost; } + + void UpdatePointers(); // must be used at call Spell code after time delay (non triggered spell cast/update spell call/etc) + + bool IsAffectedBy(SpellEntry const *spellInfo, uint32 effectId); + + bool CheckTargetCreatureType(Unit* target) const; + + void AddTriggeredSpell(SpellEntry const* spell) { m_TriggerSpells.push_back(spell); } + + void CleanupTargetList(); + protected: + + void SendLoot(uint64 guid, LootType loottype); + + Unit* m_caster; + + uint64 m_originalCasterGUID; // real source of cast (aura caster/etc), used for spell targets selection + // e.g. damage around area spell trigered by victim aura and da,age emeies of aura caster + Unit* m_originalCaster; // cached pointer for m_originalCaster, updated at Spell::UpdatePointers() + + Spell** m_selfContainer; // pointer to our spell container (if applicable) + Spell** m_triggeringContainer; // pointer to container with spell that has triggered us + + //Spell data + SpellSchoolMask m_spellSchoolMask; // Spell school (can be overwrite for some spells (wand shoot for example) + WeaponAttackType m_attackType; // For weapon based attack + int32 m_powerCost; // Calculated spell cost initialized only in Spell::prepare + int32 m_casttime; // Calculated spell cast time initialized only in Spell::prepare + bool m_canReflect; // can reflect this spell? + bool m_autoRepeat; + + uint8 m_delayAtDamageCount; + int32 GetNextDelayAtDamageMsTime() { return m_delayAtDamageCount < 5 ? 1000 - (m_delayAtDamageCount++)* 200 : 200; } + + // Delayed spells system + uint64 m_delayStart; // time of spell delay start, filled by event handler, zero = just started + uint64 m_delayMoment; // moment of next delay call, used internally + bool m_immediateHandled; // were immediate actions handled? (used by delayed spells only) + + // These vars are used in both delayed spell system and modified immediate spell system + bool m_deletable; // is the spell pending deletion or must be updated till permitted to delete? + bool m_needSpellLog; // need to send spell log? + uint8 m_applyMultiplierMask; // by effect: damage multiplier needed? + float m_damageMultipliers[3]; // by effect: damage multiplier + + // Current targets, to be used in SpellEffects (MUST BE USED ONLY IN SPELL EFFECTS) + Unit* unitTarget; + Item* itemTarget; + GameObject* gameObjTarget; + int32 damage; + + // this is set in Spell Hit, but used in Apply Aura handler + DiminishingLevels m_diminishLevel; + DiminishingGroup m_diminishGroup; + + // ------------------------------------------- + GameObject* focusObject; + + //****************************************** + // Spell trigger system + //****************************************** + void doTriggers(SpellMissInfo missInfo, uint32 damage=0, SpellSchoolMask damageSchoolMask = SPELL_SCHOOL_MASK_NONE, uint32 block=0, uint32 absorb=0, bool crit=false); + + //***************************************** + // Spell target subsystem + //***************************************** + // Targets store structures and data + uint32 m_countOfHit; + uint32 m_countOfMiss; + struct TargetInfo + { + uint64 targetGUID; + uint64 timeDelay; + SpellMissInfo missCondition:8; + SpellMissInfo reflectResult:8; + uint8 effectMask:8; + bool processed:1; + }; + std::list m_UniqueTargetInfo; + uint8 m_needAliveTargetMask; // Mask req. alive targets + + struct GOTargetInfo + { + uint64 targetGUID; + uint64 timeDelay; + uint8 effectMask:8; + bool processed:1; + }; + std::list m_UniqueGOTargetInfo; + + struct ItemTargetInfo + { + Item *item; + uint8 effectMask; + }; + std::list m_UniqueItemInfo; + + void AddUnitTarget(Unit* target, uint32 effIndex); + void AddUnitTarget(uint64 unitGUID, uint32 effIndex); + void AddGOTarget(GameObject* target, uint32 effIndex); + void AddGOTarget(uint64 goGUID, uint32 effIndex); + void AddItemTarget(Item* target, uint32 effIndex); + void DoAllEffectOnTarget(TargetInfo *target); + void DoSpellHitOnUnit(Unit *unit, uint32 effectMask); + void DoAllEffectOnTarget(GOTargetInfo *target); + void DoAllEffectOnTarget(ItemTargetInfo *target); + bool IsAliveUnitPresentInTargetList(); + // ------------------------------------------- + + //List For Triggered Spells + typedef std::list TriggerSpells; + TriggerSpells m_TriggerSpells; + + uint32 m_spellState; + uint32 m_timer; + + float m_castPositionX; + float m_castPositionY; + float m_castPositionZ; + float m_castOrientation; + bool m_IsTriggeredSpell; + + // if need this can be replaced by Aura copy + // we can't store original aura link to prevent access to deleted auras + // and in same time need aura data and after aura deleting. + SpellEntry const* m_triggeredByAuraSpell; +}; + +enum ReplenishType +{ + REPLENISH_UNDEFINED = 0, + REPLENISH_HEALTH = 20, + REPLENISH_MANA = 21, + REPLENISH_RAGE = 22 +}; + +enum SpellTargets +{ + SPELL_TARGETS_HOSTILE, + SPELL_TARGETS_NOT_FRIENDLY, + SPELL_TARGETS_NOT_HOSTILE, + SPELL_TARGETS_FRIENDLY, + SPELL_TARGETS_AOE_DAMAGE +}; + +namespace MaNGOS +{ + struct MANGOS_DLL_DECL SpellNotifierPlayer + { + std::list &i_data; + Spell &i_spell; + const uint32& i_index; + float i_radius; + Unit* i_originalCaster; + + SpellNotifierPlayer(Spell &spell, std::list &data, const uint32 &i, float radius) + : i_data(data), i_spell(spell), i_index(i), i_radius(radius) + { + i_originalCaster = i_spell.GetOriginalCaster(); + } + + void Visit(PlayerMapType &m) + { + if(!i_originalCaster) + return; + + for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + Player * pPlayer = itr->getSource(); + if( !pPlayer->isAlive() || pPlayer->isInFlight()) + continue; + + if( i_originalCaster->IsFriendlyTo(pPlayer) ) + continue; + + if( pPlayer->GetDistance(i_spell.m_targets.m_destX, i_spell.m_targets.m_destY, i_spell.m_targets.m_destZ) < i_radius ) + i_data.push_back(pPlayer); + } + } + template void Visit(GridRefManager &) {} + }; + + struct MANGOS_DLL_DECL SpellNotifierCreatureAndPlayer + { + std::list *i_data; + Spell &i_spell; + const uint32& i_push_type; + float i_radius; + SpellTargets i_TargetType; + Unit* i_originalCaster; + + SpellNotifierCreatureAndPlayer(Spell &spell, std::list &data, float radius, const uint32 &type, + SpellTargets TargetType = SPELL_TARGETS_NOT_FRIENDLY) + : i_data(&data), i_spell(spell), i_push_type(type), i_radius(radius), i_TargetType(TargetType) + { + i_originalCaster = spell.GetOriginalCaster(); + } + + template inline void Visit(GridRefManager &m) + { + assert(i_data); + + if(!i_originalCaster) + return; + + for(typename GridRefManager::iterator itr = m.begin(); itr != m.end(); ++itr) + { + if( !itr->getSource()->isAlive() || (itr->getSource()->GetTypeId() == TYPEID_PLAYER && ((Player*)itr->getSource())->isInFlight())) + continue; + + switch (i_TargetType) + { + case SPELL_TARGETS_HOSTILE: + if (!itr->getSource()->isTargetableForAttack() || !i_originalCaster->IsHostileTo( itr->getSource() )) + continue; + break; + case SPELL_TARGETS_NOT_FRIENDLY: + if (!itr->getSource()->isTargetableForAttack() || i_originalCaster->IsFriendlyTo( itr->getSource() )) + continue; + break; + case SPELL_TARGETS_NOT_HOSTILE: + if (!itr->getSource()->isTargetableForAttack() || i_originalCaster->IsHostileTo( itr->getSource() )) + continue; + break; + case SPELL_TARGETS_FRIENDLY: + if (!itr->getSource()->isTargetableForAttack() || !i_originalCaster->IsFriendlyTo( itr->getSource() )) + continue; + break; + case SPELL_TARGETS_AOE_DAMAGE: + { + if(itr->getSource()->GetTypeId()==TYPEID_UNIT && ((Creature*)itr->getSource())->isTotem()) + continue; + if(!itr->getSource()->isTargetableForAttack()) + continue; + + Unit* check = i_originalCaster->GetCharmerOrOwnerOrSelf(); + + if( check->GetTypeId()==TYPEID_PLAYER ) + { + if (check->IsFriendlyTo( itr->getSource() )) + continue; + } + else + { + if (!check->IsHostileTo( itr->getSource() )) + continue; + } + } + break; + default: continue; + } + + switch(i_push_type) + { + case PUSH_IN_FRONT: + if(i_spell.GetCaster()->isInFront((Unit*)(itr->getSource()), i_radius, 2*M_PI/3 )) + i_data->push_back(itr->getSource()); + break; + case PUSH_IN_BACK: + if(i_spell.GetCaster()->isInBack((Unit*)(itr->getSource()), i_radius, 2*M_PI/3 )) + i_data->push_back(itr->getSource()); + break; + case PUSH_SELF_CENTER: + if(i_spell.GetCaster()->IsWithinDistInMap((Unit*)(itr->getSource()), i_radius)) + i_data->push_back(itr->getSource()); + break; + case PUSH_DEST_CENTER: + if((itr->getSource()->GetDistance(i_spell.m_targets.m_destX, i_spell.m_targets.m_destY, i_spell.m_targets.m_destZ) < i_radius )) + i_data->push_back(itr->getSource()); + break; + case PUSH_TARGET_CENTER: + if(i_spell.m_targets.getUnitTarget()->IsWithinDistInMap((Unit*)(itr->getSource()), i_radius)) + i_data->push_back(itr->getSource()); + break; + } + } + } + + #ifdef WIN32 + template<> inline void Visit(CorpseMapType & ) {} + template<> inline void Visit(GameObjectMapType & ) {} + template<> inline void Visit(DynamicObjectMapType & ) {} + #endif + }; + + #ifndef WIN32 + template<> inline void SpellNotifierCreatureAndPlayer::Visit(CorpseMapType& ) {} + template<> inline void SpellNotifierCreatureAndPlayer::Visit(GameObjectMapType& ) {} + template<> inline void SpellNotifierCreatureAndPlayer::Visit(DynamicObjectMapType& ) {} + #endif +} + +typedef void(Spell::*pEffect)(uint32 i); + +class SpellEvent : public BasicEvent +{ + public: + SpellEvent(Spell* spell); + virtual ~SpellEvent(); + + virtual bool Execute(uint64 e_time, uint32 p_time); + virtual void Abort(uint64 e_time); + protected: + Spell* m_Spell; +}; +#endif diff --git a/src/game/SpellAuraDefines.h b/src/game/SpellAuraDefines.h new file mode 100644 index 00000000000..e9dbbb12adf --- /dev/null +++ b/src/game/SpellAuraDefines.h @@ -0,0 +1,313 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef MANGOS_SPELLAURADEFINES_H +#define MANGOS_SPELLAURADEFINES_H + +#define MAX_AURAS 56 +#define MAX_POSITIVE_AURAS 40 + +enum AURA_FLAGS +{ + AFLAG_NEGATIVE = 0x09, + AFLAG_POSITIVE = 0x1F, + AFLAG_MASK = 0xFF +}; + +//m_schoolAbsorb +enum DAMAGE_ABSORB_TYPE +{ + ALL_DAMAGE_ABSORB = -2, + ONLY_MAGIC_ABSORB = -1, +}; + +enum AuraType +{ + SPELL_AURA_NONE = 0, + SPELL_AURA_BIND_SIGHT = 1, + SPELL_AURA_MOD_POSSESS = 2, + SPELL_AURA_PERIODIC_DAMAGE = 3, + SPELL_AURA_DUMMY = 4, + SPELL_AURA_MOD_CONFUSE = 5, + SPELL_AURA_MOD_CHARM = 6, + SPELL_AURA_MOD_FEAR = 7, + SPELL_AURA_PERIODIC_HEAL = 8, + SPELL_AURA_MOD_ATTACKSPEED = 9, + SPELL_AURA_MOD_THREAT = 10, + SPELL_AURA_MOD_TAUNT = 11, + SPELL_AURA_MOD_STUN = 12, + SPELL_AURA_MOD_DAMAGE_DONE = 13, + SPELL_AURA_MOD_DAMAGE_TAKEN = 14, + SPELL_AURA_DAMAGE_SHIELD = 15, + SPELL_AURA_MOD_STEALTH = 16, + SPELL_AURA_MOD_DETECT = 17, + SPELL_AURA_MOD_INVISIBILITY = 18, + SPELL_AURA_MOD_INVISIBILITY_DETECTION = 19, + SPELL_AURA_OBS_MOD_HEALTH = 20, //20,21 unofficial + SPELL_AURA_OBS_MOD_MANA = 21, + SPELL_AURA_MOD_RESISTANCE = 22, + SPELL_AURA_PERIODIC_TRIGGER_SPELL = 23, + SPELL_AURA_PERIODIC_ENERGIZE = 24, + SPELL_AURA_MOD_PACIFY = 25, + SPELL_AURA_MOD_ROOT = 26, + SPELL_AURA_MOD_SILENCE = 27, + SPELL_AURA_REFLECT_SPELLS = 28, + SPELL_AURA_MOD_STAT = 29, + SPELL_AURA_MOD_SKILL = 30, + SPELL_AURA_MOD_INCREASE_SPEED = 31, + SPELL_AURA_MOD_INCREASE_MOUNTED_SPEED = 32, + SPELL_AURA_MOD_DECREASE_SPEED = 33, + SPELL_AURA_MOD_INCREASE_HEALTH = 34, + SPELL_AURA_MOD_INCREASE_ENERGY = 35, + SPELL_AURA_MOD_SHAPESHIFT = 36, + SPELL_AURA_EFFECT_IMMUNITY = 37, + SPELL_AURA_STATE_IMMUNITY = 38, + SPELL_AURA_SCHOOL_IMMUNITY = 39, + SPELL_AURA_DAMAGE_IMMUNITY = 40, + SPELL_AURA_DISPEL_IMMUNITY = 41, + SPELL_AURA_PROC_TRIGGER_SPELL = 42, + SPELL_AURA_PROC_TRIGGER_DAMAGE = 43, + SPELL_AURA_TRACK_CREATURES = 44, + SPELL_AURA_TRACK_RESOURCES = 45, + SPELL_AURA_MOD_PARRY_SKILL = 46, + SPELL_AURA_MOD_PARRY_PERCENT = 47, + SPELL_AURA_MOD_DODGE_SKILL = 48, + SPELL_AURA_MOD_DODGE_PERCENT = 49, + SPELL_AURA_MOD_BLOCK_SKILL = 50, + SPELL_AURA_MOD_BLOCK_PERCENT = 51, + SPELL_AURA_MOD_CRIT_PERCENT = 52, + SPELL_AURA_PERIODIC_LEECH = 53, + SPELL_AURA_MOD_HIT_CHANCE = 54, + SPELL_AURA_MOD_SPELL_HIT_CHANCE = 55, + SPELL_AURA_TRANSFORM = 56, + SPELL_AURA_MOD_SPELL_CRIT_CHANCE = 57, + SPELL_AURA_MOD_INCREASE_SWIM_SPEED = 58, + SPELL_AURA_MOD_DAMAGE_DONE_CREATURE = 59, + SPELL_AURA_MOD_PACIFY_SILENCE = 60, + SPELL_AURA_MOD_SCALE = 61, + SPELL_AURA_PERIODIC_HEALTH_FUNNEL = 62, + SPELL_AURA_PERIODIC_MANA_FUNNEL = 63, + SPELL_AURA_PERIODIC_MANA_LEECH = 64, + SPELL_AURA_MOD_CASTING_SPEED = 65, + SPELL_AURA_FEIGN_DEATH = 66, + SPELL_AURA_MOD_DISARM = 67, + SPELL_AURA_MOD_STALKED = 68, + SPELL_AURA_SCHOOL_ABSORB = 69, + SPELL_AURA_EXTRA_ATTACKS = 70, + SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL = 71, + SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT = 72, + SPELL_AURA_MOD_POWER_COST_SCHOOL = 73, + SPELL_AURA_REFLECT_SPELLS_SCHOOL = 74, + SPELL_AURA_MOD_LANGUAGE = 75, + SPELL_AURA_FAR_SIGHT = 76, + SPELL_AURA_MECHANIC_IMMUNITY = 77, + SPELL_AURA_MOUNTED = 78, + SPELL_AURA_MOD_DAMAGE_PERCENT_DONE = 79, + SPELL_AURA_MOD_PERCENT_STAT = 80, + SPELL_AURA_SPLIT_DAMAGE_PCT = 81, + SPELL_AURA_WATER_BREATHING = 82, + SPELL_AURA_MOD_BASE_RESISTANCE = 83, + SPELL_AURA_MOD_REGEN = 84, + SPELL_AURA_MOD_POWER_REGEN = 85, + SPELL_AURA_CHANNEL_DEATH_ITEM = 86, + SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN = 87, + SPELL_AURA_MOD_HEALTH_REGEN_PERCENT = 88, + SPELL_AURA_PERIODIC_DAMAGE_PERCENT = 89, + SPELL_AURA_MOD_RESIST_CHANCE = 90, + SPELL_AURA_MOD_DETECT_RANGE = 91, + SPELL_AURA_PREVENTS_FLEEING = 92, + SPELL_AURA_MOD_UNATTACKABLE = 93, + SPELL_AURA_INTERRUPT_REGEN = 94, + SPELL_AURA_GHOST = 95, + SPELL_AURA_SPELL_MAGNET = 96, + SPELL_AURA_MANA_SHIELD = 97, + SPELL_AURA_MOD_SKILL_TALENT = 98, + SPELL_AURA_MOD_ATTACK_POWER = 99, + SPELL_AURA_AURAS_VISIBLE = 100, + SPELL_AURA_MOD_RESISTANCE_PCT = 101, + SPELL_AURA_MOD_MELEE_ATTACK_POWER_VERSUS = 102, + SPELL_AURA_MOD_TOTAL_THREAT = 103, + SPELL_AURA_WATER_WALK = 104, + SPELL_AURA_FEATHER_FALL = 105, + SPELL_AURA_HOVER = 106, + SPELL_AURA_ADD_FLAT_MODIFIER = 107, + SPELL_AURA_ADD_PCT_MODIFIER = 108, + SPELL_AURA_ADD_TARGET_TRIGGER = 109, + SPELL_AURA_MOD_POWER_REGEN_PERCENT = 110, + SPELL_AURA_ADD_CASTER_HIT_TRIGGER = 111, + SPELL_AURA_OVERRIDE_CLASS_SCRIPTS = 112, + SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN = 113, + SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT = 114, + SPELL_AURA_MOD_HEALING = 115, + SPELL_AURA_MOD_REGEN_DURING_COMBAT = 116, + SPELL_AURA_MOD_MECHANIC_RESISTANCE = 117, + SPELL_AURA_MOD_HEALING_PCT = 118, + SPELL_AURA_SHARE_PET_TRACKING = 119, + SPELL_AURA_UNTRACKABLE = 120, + SPELL_AURA_EMPATHY = 121, + SPELL_AURA_MOD_OFFHAND_DAMAGE_PCT = 122, + SPELL_AURA_MOD_TARGET_RESISTANCE = 123, + SPELL_AURA_MOD_RANGED_ATTACK_POWER = 124, + SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN = 125, + SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN_PCT = 126, + SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS = 127, + SPELL_AURA_MOD_POSSESS_PET = 128, + SPELL_AURA_MOD_SPEED_ALWAYS = 129, + SPELL_AURA_MOD_MOUNTED_SPEED_ALWAYS = 130, + SPELL_AURA_MOD_RANGED_ATTACK_POWER_VERSUS = 131, + SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT = 132, + SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT = 133, + SPELL_AURA_MOD_MANA_REGEN_INTERRUPT = 134, + SPELL_AURA_MOD_HEALING_DONE = 135, + SPELL_AURA_MOD_HEALING_DONE_PERCENT = 136, + SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE = 137, + SPELL_AURA_MOD_HASTE = 138, + SPELL_AURA_FORCE_REACTION = 139, + SPELL_AURA_MOD_RANGED_HASTE = 140, + SPELL_AURA_MOD_RANGED_AMMO_HASTE = 141, + SPELL_AURA_MOD_BASE_RESISTANCE_PCT = 142, + SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE = 143, + SPELL_AURA_SAFE_FALL = 144, + SPELL_AURA_CHARISMA = 145, + SPELL_AURA_PERSUADED = 146, + SPELL_AURA_ADD_CREATURE_IMMUNITY = 147, + SPELL_AURA_RETAIN_COMBO_POINTS = 148, + SPELL_AURA_RESIST_PUSHBACK = 149, // Resist Pushback + SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT = 150, + SPELL_AURA_TRACK_STEALTHED = 151, // Track Stealthed + SPELL_AURA_MOD_DETECTED_RANGE = 152, // Mod Detected Range + SPELL_AURA_SPLIT_DAMAGE_FLAT = 153, // Split Damage Flat + SPELL_AURA_MOD_STEALTH_LEVEL = 154, // Stealth Level Modifier + SPELL_AURA_MOD_WATER_BREATHING = 155, // Mod Water Breathing + SPELL_AURA_MOD_REPUTATION_GAIN = 156, // Mod Reputation Gain + SPELL_AURA_PET_DAMAGE_MULTI = 157, // Mod Pet Damage + SPELL_AURA_MOD_SHIELD_BLOCKVALUE = 158, + SPELL_AURA_NO_PVP_CREDIT = 159, + SPELL_AURA_MOD_AOE_AVOIDANCE = 160, + SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT = 161, + SPELL_AURA_POWER_BURN_MANA = 162, + SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE = 163, + SPELL_AURA_164 = 164, + SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS = 165, + SPELL_AURA_MOD_ATTACK_POWER_PCT = 166, + SPELL_AURA_MOD_RANGED_ATTACK_POWER_PCT = 167, + SPELL_AURA_MOD_DAMAGE_DONE_VERSUS = 168, + SPELL_AURA_MOD_CRIT_PERCENT_VERSUS = 169, + SPELL_AURA_DETECT_AMORE = 170, + SPELL_AURA_MOD_SPEED_NOT_STACK = 171, + SPELL_AURA_MOD_MOUNTED_SPEED_NOT_STACK = 172, + SPELL_AURA_ALLOW_CHAMPION_SPELLS = 173, + SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT = 174, // by defeult intelect, dependent from SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT + SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT = 175, + SPELL_AURA_SPIRIT_OF_REDEMPTION = 176, + SPELL_AURA_AOE_CHARM = 177, + SPELL_AURA_MOD_DEBUFF_RESISTANCE = 178, + SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE = 179, + SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS = 180, + SPELL_AURA_MOD_FLAT_SPELL_CRIT_DAMAGE_VERSUS = 181, // unused - possible flat spell crit damage versus + SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT = 182, + SPELL_AURA_MOD_CRITICAL_THREAT = 183, + SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE = 184, + SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE= 185, + SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE = 186, + SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_CHANCE = 187, + SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_CHANCE = 188, + SPELL_AURA_MOD_RATING = 189, + SPELL_AURA_MOD_FACTION_REPUTATION_GAIN = 190, + SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED = 191, + SPELL_AURA_HASTE_MELEE = 192, + SPELL_AURA_MELEE_SLOW = 193, + SPELL_AURA_MOD_DEPRICATED_1 = 194, // not used now, old SPELL_AURA_MOD_SPELL_DAMAGE_OF_INTELLECT + SPELL_AURA_MOD_DEPRICATED_2 = 195, // not used now, old SPELL_AURA_MOD_SPELL_HEALING_OF_INTELLECT + SPELL_AURA_MOD_COOLDOWN = 196, // only 24818 Noxious Breath + SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE = 197, + SPELL_AURA_MOD_ALL_WEAPON_SKILLS = 198, + SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT = 199, + SPELL_AURA_MOD_XP_PCT = 200, + SPELL_AURA_FLY = 201, + SPELL_AURA_IGNORE_COMBAT_RESULT = 202, + SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE = 203, + SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE = 204, + SPELL_AURA_205 = 205, // unused + SPELL_AURA_MOD_SPEED_MOUNTED = 206, // ? used in strange spells + SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED = 207, + SPELL_AURA_MOD_SPEED_FLIGHT = 208, + SPELL_AURA_MOD_FLIGHT_SPEED_ALWAYS = 209, + SPELL_AURA_210 = 210, // unused + SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK = 211, + SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT = 212, + SPELL_AURA_MOD_RAGE_FROM_DAMAGE_DEALT = 213, + SPELL_AURA_214 = 214, + SPELL_AURA_ARENA_PREPARATION = 215, + SPELL_AURA_HASTE_SPELLS = 216, + SPELL_AURA_217 = 217, + SPELL_AURA_HASTE_RANGED = 218, + SPELL_AURA_MOD_MANA_REGEN_FROM_STAT = 219, + SPELL_AURA_MOD_RATING_FROM_STAT = 220, + SPELL_AURA_221 = 221, + SPELL_AURA_222 = 222, + SPELL_AURA_223 = 223, + SPELL_AURA_224 = 224, + SPELL_AURA_PRAYER_OF_MENDING = 225, + SPELL_AURA_PERIODIC_DUMMY = 226, + SPELL_AURA_227 = 227, + SPELL_AURA_DETECT_STEALTH = 228, + SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE = 229, + SPELL_AURA_230 = 230, + SPELL_AURA_231 = 231, + SPELL_AURA_MECHANIC_DURATION_MOD = 232, + SPELL_AURA_233 = 233, + SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK = 234, + SPELL_AURA_MOD_DISPEL_RESIST = 235, + SPELL_AURA_236 = 236, + SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER = 237, + SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER = 238, + SPELL_AURA_MOD_SCALE_2 = 239, + SPELL_AURA_MOD_EXPERTISE = 240, + SPELL_AURA_FORCE_MOVE_FORWARD = 241, + SPELL_AURA_MOD_SPELL_DAMAGE_FROM_HEALING = 242, + SPELL_AURA_243 = 243, + SPELL_AURA_COMPREHEND_LANGUAGE = 244, + SPELL_AURA_MOD_DURATION_OF_MAGIC_EFFECTS = 245, + SPELL_AURA_246 = 246, + SPELL_AURA_247 = 247, + SPELL_AURA_MOD_COMBAT_RESULT_CHANCE = 248, + SPELL_AURA_249 = 249, + SPELL_AURA_MOD_INCREASE_HEALTH_2 = 250, + SPELL_AURA_MOD_ENEMY_DODGE = 251, + SPELL_AURA_252 = 252, + SPELL_AURA_253 = 253, + SPELL_AURA_254 = 254, + SPELL_AURA_255 = 255, + SPELL_AURA_256 = 256, + SPELL_AURA_257 = 257, + SPELL_AURA_258 = 258, + SPELL_AURA_259 = 259, + SPELL_AURA_260 = 260, + SPELL_AURA_261 = 261, + TOTAL_AURAS=262 +}; + +enum AreaAuraType +{ + AREA_AURA_PARTY, + AREA_AURA_FRIEND, + AREA_AURA_ENEMY, + AREA_AURA_PET, + AREA_AURA_OWNER +}; +#endif diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp new file mode 100644 index 00000000000..e5abe4d842f --- /dev/null +++ b/src/game/SpellAuras.cpp @@ -0,0 +1,6360 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Opcodes.h" +#include "Log.h" +#include "UpdateMask.h" +#include "World.h" +#include "ObjectMgr.h" +#include "SpellMgr.h" +#include "Player.h" +#include "Unit.h" +#include "Spell.h" +#include "SpellAuras.h" +#include "DynamicObject.h" +#include "Group.h" +#include "UpdateData.h" +#include "MapManager.h" +#include "ObjectAccessor.h" +#include "Policies/SingletonImp.h" +#include "Totem.h" +#include "Creature.h" +#include "Formulas.h" +#include "BattleGround.h" +#include "CreatureAI.h" +#include "Util.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" +#include "CellImpl.h" + +#define NULL_AURA_SLOT 0xFF + +pAuraHandler AuraHandler[TOTAL_AURAS]= +{ + &Aura::HandleNULL, // 0 SPELL_AURA_NONE + &Aura::HandleBindSight, // 1 SPELL_AURA_BIND_SIGHT + &Aura::HandleModPossess, // 2 SPELL_AURA_MOD_POSSESS + &Aura::HandlePeriodicDamage, // 3 SPELL_AURA_PERIODIC_DAMAGE + &Aura::HandleAuraDummy, // 4 SPELL_AURA_DUMMY + &Aura::HandleModConfuse, // 5 SPELL_AURA_MOD_CONFUSE + &Aura::HandleModCharm, // 6 SPELL_AURA_MOD_CHARM + &Aura::HandleModFear, // 7 SPELL_AURA_MOD_FEAR + &Aura::HandlePeriodicHeal, // 8 SPELL_AURA_PERIODIC_HEAL + &Aura::HandleModAttackSpeed, // 9 SPELL_AURA_MOD_ATTACKSPEED + &Aura::HandleModThreat, // 10 SPELL_AURA_MOD_THREAT + &Aura::HandleModTaunt, // 11 SPELL_AURA_MOD_TAUNT + &Aura::HandleAuraModStun, // 12 SPELL_AURA_MOD_STUN + &Aura::HandleModDamageDone, // 13 SPELL_AURA_MOD_DAMAGE_DONE + &Aura::HandleNoImmediateEffect, // 14 SPELL_AURA_MOD_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus + &Aura::HandleNoImmediateEffect, // 15 SPELL_AURA_DAMAGE_SHIELD implemented in Unit::DoAttackDamage + &Aura::HandleModStealth, // 16 SPELL_AURA_MOD_STEALTH + &Aura::HandleNoImmediateEffect, // 17 SPELL_AURA_MOD_STEALTH_DETECT + &Aura::HandleInvisibility, // 18 SPELL_AURA_MOD_INVISIBILITY + &Aura::HandleInvisibilityDetect, // 19 SPELL_AURA_MOD_INVISIBILITY_DETECTION + &Aura::HandleAuraModTotalHealthPercentRegen, // 20 SPELL_AURA_OBS_MOD_HEALTH + &Aura::HandleAuraModTotalManaPercentRegen, // 21 SPELL_AURA_OBS_MOD_MANA + &Aura::HandleAuraModResistance, // 22 SPELL_AURA_MOD_RESISTANCE + &Aura::HandlePeriodicTriggerSpell, // 23 SPELL_AURA_PERIODIC_TRIGGER_SPELL + &Aura::HandlePeriodicEnergize, // 24 SPELL_AURA_PERIODIC_ENERGIZE + &Aura::HandleAuraModPacify, // 25 SPELL_AURA_MOD_PACIFY + &Aura::HandleAuraModRoot, // 26 SPELL_AURA_MOD_ROOT + &Aura::HandleAuraModSilence, // 27 SPELL_AURA_MOD_SILENCE + &Aura::HandleNoImmediateEffect, // 28 SPELL_AURA_REFLECT_SPELLS implement in Unit::SpellHitResult + &Aura::HandleAuraModStat, // 29 SPELL_AURA_MOD_STAT + &Aura::HandleAuraModSkill, // 30 SPELL_AURA_MOD_SKILL + &Aura::HandleAuraModIncreaseSpeed, // 31 SPELL_AURA_MOD_INCREASE_SPEED + &Aura::HandleAuraModIncreaseMountedSpeed, // 32 SPELL_AURA_MOD_INCREASE_MOUNTED_SPEED + &Aura::HandleAuraModDecreaseSpeed, // 33 SPELL_AURA_MOD_DECREASE_SPEED + &Aura::HandleAuraModIncreaseHealth, // 34 SPELL_AURA_MOD_INCREASE_HEALTH + &Aura::HandleAuraModIncreaseEnergy, // 35 SPELL_AURA_MOD_INCREASE_ENERGY + &Aura::HandleAuraModShapeshift, // 36 SPELL_AURA_MOD_SHAPESHIFT + &Aura::HandleAuraModEffectImmunity, // 37 SPELL_AURA_EFFECT_IMMUNITY + &Aura::HandleAuraModStateImmunity, // 38 SPELL_AURA_STATE_IMMUNITY + &Aura::HandleAuraModSchoolImmunity, // 39 SPELL_AURA_SCHOOL_IMMUNITY + &Aura::HandleAuraModDmgImmunity, // 40 SPELL_AURA_DAMAGE_IMMUNITY + &Aura::HandleAuraModDispelImmunity, // 41 SPELL_AURA_DISPEL_IMMUNITY + &Aura::HandleAuraProcTriggerSpell, // 42 SPELL_AURA_PROC_TRIGGER_SPELL implemented in Unit::ProcDamageAndSpellFor and Unit::HandleProcTriggerSpell + &Aura::HandleNoImmediateEffect, // 43 SPELL_AURA_PROC_TRIGGER_DAMAGE implemented in Unit::ProcDamageAndSpellFor + &Aura::HandleAuraTrackCreatures, // 44 SPELL_AURA_TRACK_CREATURES + &Aura::HandleAuraTrackResources, // 45 SPELL_AURA_TRACK_RESOURCES + &Aura::HandleUnused, // 46 SPELL_AURA_MOD_PARRY_SKILL obsolete? + &Aura::HandleAuraModParryPercent, // 47 SPELL_AURA_MOD_PARRY_PERCENT + &Aura::HandleUnused, // 48 SPELL_AURA_MOD_DODGE_SKILL obsolete? + &Aura::HandleAuraModDodgePercent, // 49 SPELL_AURA_MOD_DODGE_PERCENT + &Aura::HandleUnused, // 50 SPELL_AURA_MOD_BLOCK_SKILL obsolete? + &Aura::HandleAuraModBlockPercent, // 51 SPELL_AURA_MOD_BLOCK_PERCENT + &Aura::HandleAuraModCritPercent, // 52 SPELL_AURA_MOD_CRIT_PERCENT + &Aura::HandlePeriodicLeech, // 53 SPELL_AURA_PERIODIC_LEECH + &Aura::HandleModHitChance, // 54 SPELL_AURA_MOD_HIT_CHANCE + &Aura::HandleModSpellHitChance, // 55 SPELL_AURA_MOD_SPELL_HIT_CHANCE + &Aura::HandleAuraTransform, // 56 SPELL_AURA_TRANSFORM + &Aura::HandleModSpellCritChance, // 57 SPELL_AURA_MOD_SPELL_CRIT_CHANCE + &Aura::HandleAuraModIncreaseSwimSpeed, // 58 SPELL_AURA_MOD_INCREASE_SWIM_SPEED + &Aura::HandleNoImmediateEffect, // 59 SPELL_AURA_MOD_DAMAGE_DONE_CREATURE implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus + &Aura::HandleAuraModPacifyAndSilence, // 60 SPELL_AURA_MOD_PACIFY_SILENCE + &Aura::HandleAuraModScale, // 61 SPELL_AURA_MOD_SCALE + &Aura::HandleNULL, // 62 SPELL_AURA_PERIODIC_HEALTH_FUNNEL + &Aura::HandleUnused, // 63 SPELL_AURA_PERIODIC_MANA_FUNNEL obsolete? + &Aura::HandlePeriodicManaLeech, // 64 SPELL_AURA_PERIODIC_MANA_LEECH + &Aura::HandleModCastingSpeed, // 65 SPELL_AURA_MOD_CASTING_SPEED + &Aura::HandleFeignDeath, // 66 SPELL_AURA_FEIGN_DEATH + &Aura::HandleAuraModDisarm, // 67 SPELL_AURA_MOD_DISARM + &Aura::HandleAuraModStalked, // 68 SPELL_AURA_MOD_STALKED + &Aura::HandleSchoolAbsorb, // 69 SPELL_AURA_SCHOOL_ABSORB implemented in Unit::CalcAbsorbResist + &Aura::HandleUnused, // 70 SPELL_AURA_EXTRA_ATTACKS Useless, used by only one spell that has only visual effect + &Aura::HandleModSpellCritChanceShool, // 71 SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL + &Aura::HandleModPowerCostPCT, // 72 SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT + &Aura::HandleModPowerCost, // 73 SPELL_AURA_MOD_POWER_COST_SCHOOL + &Aura::HandleNoImmediateEffect, // 74 SPELL_AURA_REFLECT_SPELLS_SCHOOL implemented in Unit::SpellHitResult + &Aura::HandleNoImmediateEffect, // 75 SPELL_AURA_MOD_LANGUAGE + &Aura::HandleFarSight, // 76 SPELL_AURA_FAR_SIGHT + &Aura::HandleModMechanicImmunity, // 77 SPELL_AURA_MECHANIC_IMMUNITY + &Aura::HandleAuraMounted, // 78 SPELL_AURA_MOUNTED + &Aura::HandleModDamagePercentDone, // 79 SPELL_AURA_MOD_DAMAGE_PERCENT_DONE + &Aura::HandleModPercentStat, // 80 SPELL_AURA_MOD_PERCENT_STAT + &Aura::HandleNoImmediateEffect, // 81 SPELL_AURA_SPLIT_DAMAGE_PCT + &Aura::HandleWaterBreathing, // 82 SPELL_AURA_WATER_BREATHING + &Aura::HandleModBaseResistance, // 83 SPELL_AURA_MOD_BASE_RESISTANCE + &Aura::HandleModRegen, // 84 SPELL_AURA_MOD_REGEN + &Aura::HandleModPowerRegen, // 85 SPELL_AURA_MOD_POWER_REGEN + &Aura::HandleChannelDeathItem, // 86 SPELL_AURA_CHANNEL_DEATH_ITEM + &Aura::HandleNoImmediateEffect, // 87 SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus + &Aura::HandleNoImmediateEffect, // 88 SPELL_AURA_MOD_HEALTH_REGEN_PERCENT + &Aura::HandlePeriodicDamagePCT, // 89 SPELL_AURA_PERIODIC_DAMAGE_PERCENT + &Aura::HandleUnused, // 90 SPELL_AURA_MOD_RESIST_CHANCE Useless + &Aura::HandleNoImmediateEffect, // 91 SPELL_AURA_MOD_DETECT_RANGE implemented in Creature::GetAttackDistance + &Aura::HandlePreventFleeing, // 92 SPELL_AURA_PREVENTS_FLEEING + &Aura::HandleModUnattackable, // 93 SPELL_AURA_MOD_UNATTACKABLE + &Aura::HandleNoImmediateEffect, // 94 SPELL_AURA_INTERRUPT_REGEN implemented in Player::RegenerateAll + &Aura::HandleAuraGhost, // 95 SPELL_AURA_GHOST + &Aura::HandleNoImmediateEffect, // 96 SPELL_AURA_SPELL_MAGNET implemented in Spell::SelectMagnetTarget + &Aura::HandleManaShield, // 97 SPELL_AURA_MANA_SHIELD implemented in Unit::CalcAbsorbResist + &Aura::HandleAuraModSkill, // 98 SPELL_AURA_MOD_SKILL_TALENT + &Aura::HandleAuraModAttackPower, // 99 SPELL_AURA_MOD_ATTACK_POWER + &Aura::HandleUnused, //100 SPELL_AURA_AURAS_VISIBLE obsolete? all player can see all auras now + &Aura::HandleModResistancePercent, //101 SPELL_AURA_MOD_RESISTANCE_PCT + &Aura::HandleNoImmediateEffect, //102 SPELL_AURA_MOD_MELEE_ATTACK_POWER_VERSUS implemented in Unit::MeleeDamageBonus + &Aura::HandleAuraModTotalThreat, //103 SPELL_AURA_MOD_TOTAL_THREAT + &Aura::HandleAuraWaterWalk, //104 SPELL_AURA_WATER_WALK + &Aura::HandleAuraFeatherFall, //105 SPELL_AURA_FEATHER_FALL + &Aura::HandleAuraHover, //106 SPELL_AURA_HOVER + &Aura::HandleAddModifier, //107 SPELL_AURA_ADD_FLAT_MODIFIER + &Aura::HandleAddModifier, //108 SPELL_AURA_ADD_PCT_MODIFIER + &Aura::HandleNoImmediateEffect, //109 SPELL_AURA_ADD_TARGET_TRIGGER + &Aura::HandleModPowerRegenPCT, //110 SPELL_AURA_MOD_POWER_REGEN_PERCENT + &Aura::HandleNULL, //111 SPELL_AURA_ADD_CASTER_HIT_TRIGGER + &Aura::HandleNoImmediateEffect, //112 SPELL_AURA_OVERRIDE_CLASS_SCRIPTS + &Aura::HandleNoImmediateEffect, //113 SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus + &Aura::HandleNoImmediateEffect, //114 SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT implemented in Unit::MeleeDamageBonus + &Aura::HandleAuraHealing, //115 SPELL_AURA_MOD_HEALING + &Aura::HandleNoImmediateEffect, //116 SPELL_AURA_MOD_REGEN_DURING_COMBAT + &Aura::HandleNoImmediateEffect, //117 SPELL_AURA_MOD_MECHANIC_RESISTANCE implemented in Unit::MagicSpellHitResult + &Aura::HandleAuraHealingPct, //118 SPELL_AURA_MOD_HEALING_PCT + &Aura::HandleUnused, //119 SPELL_AURA_SHARE_PET_TRACKING useless + &Aura::HandleAuraUntrackable, //120 SPELL_AURA_UNTRACKABLE + &Aura::HandleAuraEmpathy, //121 SPELL_AURA_EMPATHY + &Aura::HandleModOffhandDamagePercent, //122 SPELL_AURA_MOD_OFFHAND_DAMAGE_PCT + &Aura::HandleModTargetResistance, //123 SPELL_AURA_MOD_TARGET_RESISTANCE + &Aura::HandleAuraModRangedAttackPower, //124 SPELL_AURA_MOD_RANGED_ATTACK_POWER + &Aura::HandleNoImmediateEffect, //125 SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus + &Aura::HandleNoImmediateEffect, //126 SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN_PCT implemented in Unit::MeleeDamageBonus + &Aura::HandleNoImmediateEffect, //127 SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS implemented in Unit::MeleeDamageBonus + &Aura::HandleModPossessPet, //128 SPELL_AURA_MOD_POSSESS_PET + &Aura::HandleAuraModIncreaseSpeed, //129 SPELL_AURA_MOD_SPEED_ALWAYS + &Aura::HandleAuraModIncreaseMountedSpeed, //130 SPELL_AURA_MOD_MOUNTED_SPEED_ALWAYS + &Aura::HandleNoImmediateEffect, //131 SPELL_AURA_MOD_RANGED_ATTACK_POWER_VERSUS implemented in Unit::MeleeDamageBonus + &Aura::HandleAuraModIncreaseEnergyPercent, //132 SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT + &Aura::HandleAuraModIncreaseHealthPercent, //133 SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT + &Aura::HandleAuraModRegenInterrupt, //134 SPELL_AURA_MOD_MANA_REGEN_INTERRUPT + &Aura::HandleModHealingDone, //135 SPELL_AURA_MOD_HEALING_DONE + &Aura::HandleAuraHealingPct, //136 SPELL_AURA_MOD_HEALING_DONE_PERCENT implemented in Unit::SpellHealingBonus + &Aura::HandleModTotalPercentStat, //137 SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE + &Aura::HandleHaste, //138 SPELL_AURA_MOD_HASTE + &Aura::HandleForceReaction, //139 SPELL_AURA_FORCE_REACTION + &Aura::HandleAuraModRangedHaste, //140 SPELL_AURA_MOD_RANGED_HASTE + &Aura::HandleRangedAmmoHaste, //141 SPELL_AURA_MOD_RANGED_AMMO_HASTE + &Aura::HandleAuraModBaseResistancePCT, //142 SPELL_AURA_MOD_BASE_RESISTANCE_PCT + &Aura::HandleAuraModResistanceExclusive, //143 SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE + &Aura::HandleNoImmediateEffect, //144 SPELL_AURA_SAFE_FALL implemented in WorldSession::HandleMovementOpcodes + &Aura::HandleUnused, //145 SPELL_AURA_CHARISMA obsolete? + &Aura::HandleUnused, //146 SPELL_AURA_PERSUADED obsolete? + &Aura::HandleNULL, //147 SPELL_AURA_ADD_CREATURE_IMMUNITY + &Aura::HandleAuraRetainComboPoints, //148 SPELL_AURA_RETAIN_COMBO_POINTS + &Aura::HandleNoImmediateEffect, //149 SPELL_AURA_RESIST_PUSHBACK + &Aura::HandleShieldBlockValue, //150 SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT + &Aura::HandleAuraTrackStealthed, //151 SPELL_AURA_TRACK_STEALTHED + &Aura::HandleNoImmediateEffect, //152 SPELL_AURA_MOD_DETECTED_RANGE implemented in Creature::GetAttackDistance + &Aura::HandleNoImmediateEffect, //153 SPELL_AURA_SPLIT_DAMAGE_FLAT + &Aura::HandleNoImmediateEffect, //154 SPELL_AURA_MOD_STEALTH_LEVEL + &Aura::HandleNoImmediateEffect, //155 SPELL_AURA_MOD_WATER_BREATHING + &Aura::HandleNoImmediateEffect, //156 SPELL_AURA_MOD_REPUTATION_GAIN + &Aura::HandleNULL, //157 SPELL_AURA_PET_DAMAGE_MULTI + &Aura::HandleShieldBlockValue, //158 SPELL_AURA_MOD_SHIELD_BLOCKVALUE + &Aura::HandleNoImmediateEffect, //159 SPELL_AURA_NO_PVP_CREDIT only for Honorless Target spell + &Aura::HandleNoImmediateEffect, //160 SPELL_AURA_MOD_AOE_AVOIDANCE implemended in Unit::MagicSpellHitResult + &Aura::HandleNoImmediateEffect, //161 SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT + &Aura::HandleAuraPowerBurn, //162 SPELL_AURA_POWER_BURN_MANA + &Aura::HandleNoImmediateEffect, //163 SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE + &Aura::HandleUnused, //164 useless, only one test spell + &Aura::HandleAuraAttackPowerAttacker, //165 SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS implemented in Unit::MeleeDamageBonus + &Aura::HandleAuraModAttackPowerPercent, //166 SPELL_AURA_MOD_ATTACK_POWER_PCT + &Aura::HandleAuraModRangedAttackPowerPercent, //167 SPELL_AURA_MOD_RANGED_ATTACK_POWER_PCT + &Aura::HandleNoImmediateEffect, //168 SPELL_AURA_MOD_DAMAGE_DONE_VERSUS implemented in Unit::SpellDamageBonus, Unit::MeleeDamageBonus + &Aura::HandleNoImmediateEffect, //169 SPELL_AURA_MOD_CRIT_PERCENT_VERSUS implemented in Unit::DealDamageBySchool, Unit::DoAttackDamage, Unit::SpellCriticalBonus + &Aura::HandleNULL, //170 SPELL_AURA_DETECT_AMORE only for Detect Amore spell + &Aura::HandleAuraModIncreaseSpeed, //171 SPELL_AURA_MOD_SPEED_NOT_STACK + &Aura::HandleAuraModIncreaseMountedSpeed, //172 SPELL_AURA_MOD_MOUNTED_SPEED_NOT_STACK + &Aura::HandleUnused, //173 SPELL_AURA_ALLOW_CHAMPION_SPELLS only for Proclaim Champion spell + &Aura::HandleModSpellDamagePercentFromStat, //174 SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT implemented in Unit::SpellBaseDamageBonus (by defeult intelect, dependent from SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT) + &Aura::HandleModSpellHealingPercentFromStat, //175 SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT implemented in Unit::SpellBaseHealingBonus + &Aura::HandleSpiritOfRedemption, //176 SPELL_AURA_SPIRIT_OF_REDEMPTION only for Spirit of Redemption spell, die at aura end + &Aura::HandleNULL, //177 SPELL_AURA_AOE_CHARM + &Aura::HandleNoImmediateEffect, //178 SPELL_AURA_MOD_DEBUFF_RESISTANCE implemented in Unit::MagicSpellHitResult + &Aura::HandleNoImmediateEffect, //179 SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE implemented in Unit::SpellCriticalBonus + &Aura::HandleNoImmediateEffect, //180 SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS implemented in Unit::SpellDamageBonus + &Aura::HandleUnused, //181 SPELL_AURA_MOD_FLAT_SPELL_CRIT_DAMAGE_VERSUS unused + &Aura::HandleAuraModResistenceOfStatPercent, //182 SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT + &Aura::HandleNULL, //183 SPELL_AURA_MOD_CRITICAL_THREAT + &Aura::HandleNoImmediateEffect, //184 SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst + &Aura::HandleNoImmediateEffect, //185 SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst + &Aura::HandleNoImmediateEffect, //186 SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE implemented in Unit::MagicSpellHitResult + &Aura::HandleNoImmediateEffect, //187 SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_CHANCE implemended in Unit::GetUnitCriticalChance + &Aura::HandleNoImmediateEffect, //188 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_CHANCE implemented in Unit::GetUnitCriticalChance + &Aura::HandleModRating, //189 SPELL_AURA_MOD_RATING + &Aura::HandleNULL, //190 SPELL_AURA_MOD_FACTION_REPUTATION_GAIN + &Aura::HandleAuraModUseNormalSpeed, //191 SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED + &Aura::HandleModMeleeRangedSpeedPct, //192 SPELL_AURA_HASTE_MELEE + &Aura::HandleModCombatSpeedPct, //193 SPELL_AURA_MELEE_SLOW (in fact combat (any type attack) speed pct) + &Aura::HandleUnused, //194 SPELL_AURA_MOD_DEPRICATED_1 not used now (old SPELL_AURA_MOD_SPELL_DAMAGE_OF_INTELLECT) + &Aura::HandleUnused, //195 SPELL_AURA_MOD_DEPRICATED_2 not used now (old SPELL_AURA_MOD_SPELL_HEALING_OF_INTELLECT) + &Aura::HandleNULL, //196 SPELL_AURA_MOD_COOLDOWN + &Aura::HandleNoImmediateEffect, //197 SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE implemented in Unit::SpellCriticalBonus Unit::GetUnitCriticalChance + &Aura::HandleUnused, //198 SPELL_AURA_MOD_ALL_WEAPON_SKILLS + &Aura::HandleNoImmediateEffect, //199 SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT implemented in Unit::MagicSpellHitResult + &Aura::HandleNoImmediateEffect, //200 SPELL_AURA_MOD_XP_PCT implemented in Player::GiveXP + &Aura::HandleAuraAllowFlight, //201 SPELL_AURA_FLY this aura enable flight mode... + &Aura::HandleNoImmediateEffect, //202 SPELL_AURA_CANNOT_BE_DODGED implemented in Unit::RollPhysicalOutcomeAgainst + &Aura::HandleNoImmediateEffect, //203 SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE implemented in Unit::DoAttackDamage + &Aura::HandleNoImmediateEffect, //204 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE implemented in Unit::DoAttackDamage + &Aura::HandleNULL, //205 vulnerable to school dmg? + &Aura::HandleNULL, //206 SPELL_AURA_MOD_SPEED_MOUNTED + &Aura::HandleAuraModIncreaseFlightSpeed, //207 SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED + &Aura::HandleAuraModIncreaseFlightSpeed, //208 SPELL_AURA_MOD_SPEED_FLIGHT, used only in spell: Flight Form (Passive) + &Aura::HandleAuraModIncreaseFlightSpeed, //209 SPELL_AURA_MOD_FLIGHT_SPEED_ALWAYS + &Aura::HandleNULL, //210 Commentator's Command + &Aura::HandleAuraModIncreaseFlightSpeed, //211 SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK + &Aura::HandleAuraModRangedAttackPowerOfStatPercent, //212 SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT + &Aura::HandleNoImmediateEffect, //213 SPELL_AURA_MOD_RAGE_FROM_DAMAGE_DEALT implemented in Player::RewardRage + &Aura::HandleNULL, //214 Tamed Pet Passive + &Aura::HandleArenaPreparation, //215 SPELL_AURA_ARENA_PREPARATION + &Aura::HandleModCastingSpeed, //216 SPELL_AURA_HASTE_SPELLS + &Aura::HandleUnused, //217 unused + &Aura::HandleAuraModRangedHaste, //218 SPELL_AURA_HASTE_RANGED + &Aura::HandleModManaRegen, //219 SPELL_AURA_MOD_MANA_REGEN_FROM_STAT + &Aura::HandleNULL, //220 SPELL_AURA_MOD_RATING_FROM_STAT + &Aura::HandleNULL, //221 ignored + &Aura::HandleUnused, //222 unused + &Aura::HandleNULL, //223 Cold Stare + &Aura::HandleUnused, //224 unused + &Aura::HandleNoImmediateEffect, //225 SPELL_AURA_PRAYER_OF_MENDING + &Aura::HandleAuraPeriodicDummy, //226 SPELL_AURA_PERIODIC_DUMMY + &Aura::HandleNULL, //227 periodic trigger spell + &Aura::HandleNoImmediateEffect, //228 stealth detection + &Aura::HandleNULL, //229 SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE + &Aura::HandleAuraModIncreaseMaxHealth, //230 Commanding Shout + &Aura::HandleNULL, //231 + &Aura::HandleNoImmediateEffect, //232 SPELL_AURA_MECHANIC_DURATION_MOD implement in Unit::CalculateSpellDuration + &Aura::HandleNULL, //233 set model id to the one of the creature with id m_modifier.m_miscvalue + &Aura::HandleNoImmediateEffect, //234 SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK implement in Unit::CalculateSpellDuration + &Aura::HandleAuraModDispelResist, //235 SPELL_AURA_MOD_DISPEL_RESIST implement in Unit::MagicSpellHitResult + &Aura::HandleUnused, //236 unused + &Aura::HandleModSpellDamagePercentFromAttackPower, //237 SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER implemented in Unit::SpellBaseDamageBonus + &Aura::HandleModSpellHealingPercentFromAttackPower, //238 SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER implemented in Unit::SpellBaseHealingBonus + &Aura::HandleAuraModScale, //239 SPELL_AURA_MOD_SCALE_2 only in Noggenfogger Elixir (16595) before 2.3.0 aura 61 + &Aura::HandleAuraModExpertise, //240 SPELL_AURA_MOD_EXPERTISE + &Aura::HandleForceMoveForward, //241 Forces the player to move forward + &Aura::HandleUnused, //242 SPELL_AURA_MOD_SPELL_DAMAGE_FROM_HEALING + &Aura::HandleUnused, //243 used by two test spells + &Aura::HandleComprehendLanguage, //244 Comprehend language + &Aura::HandleUnused, //245 SPELL_AURA_MOD_DURATION_OF_MAGIC_EFFECTS + &Aura::HandleUnused, //246 unused + &Aura::HandleUnused, //247 unused + &Aura::HandleNoImmediateEffect, //248 SPELL_AURA_MOD_COMBAT_RESULT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst + &Aura::HandleNULL, //249 + &Aura::HandleAuraModIncreaseHealth, //250 SPELL_AURA_MOD_INCREASE_HEALTH_2 + &Aura::HandleNULL, //251 SPELL_AURA_MOD_ENEMY_DODGE + &Aura::HandleUnused, //252 unused + &Aura::HandleUnused, //253 unused + &Aura::HandleUnused, //254 unused + &Aura::HandleUnused, //255 unused + &Aura::HandleUnused, //256 unused + &Aura::HandleUnused, //257 unused + &Aura::HandleUnused, //258 unused + &Aura::HandleUnused, //259 unused + &Aura::HandleUnused, //260 unused + &Aura::HandleNULL //261 SPELL_AURA_261 some phased state (44856 spell) +}; + +Aura::Aura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster, Item* castItem) : +m_procCharges(0), m_spellmod(NULL), m_effIndex(eff), m_caster_guid(0), m_target(target), +m_timeCla(1000), m_castItemGuid(castItem?castItem->GetGUID():0), m_auraSlot(MAX_AURAS), +m_positive(false), m_permanent(false), m_isPeriodic(false), m_isTrigger(false), m_isAreaAura(false), +m_isPersistent(false), m_updated(false), m_removeMode(AURA_REMOVE_BY_DEFAULT), m_isRemovedOnShapeLost(true), m_in_use(false), +m_periodicTimer(0), m_PeriodicEventId(0), m_AuraDRGroup(DIMINISHING_NONE) +{ + assert(target); + + assert(spellproto && spellproto == sSpellStore.LookupEntry( spellproto->Id ) && "`info` must be pointer to sSpellStore element"); + + m_spellProto = spellproto; + + m_currentBasePoints = currentBasePoints ? *currentBasePoints : m_spellProto->EffectBasePoints[eff]; + + m_isPassive = IsPassiveSpell(GetId()); + m_positive = IsPositiveEffect(GetId(), m_effIndex); + + m_applyTime = time(NULL); + + int32 damage; + if(!caster) + { + m_caster_guid = target->GetGUID(); + damage = m_currentBasePoints+1; // stored value-1 + m_maxduration = target->CalculateSpellDuration(m_spellProto, m_effIndex, target); + } + else + { + m_caster_guid = caster->GetGUID(); + + damage = caster->CalculateSpellDamage(m_spellProto,m_effIndex,m_currentBasePoints,target); + m_maxduration = caster->CalculateSpellDuration(m_spellProto, m_effIndex, target); + + if (!damage && castItem && castItem->GetItemSuffixFactor()) + { + ItemRandomSuffixEntry const *item_rand_suffix = sItemRandomSuffixStore.LookupEntry(abs(castItem->GetItemRandomPropertyId())); + if(item_rand_suffix) + { + for (int k=0; k<3; k++) + { + SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(item_rand_suffix->enchant_id[k]); + if(pEnchant) + { + for (int t=0; t<3; t++) + if(pEnchant->spellid[t] == m_spellProto->Id) + { + damage = uint32((item_rand_suffix->prefix[k]*castItem->GetItemSuffixFactor()) / 10000 ); + break; + } + } + + if(damage) + break; + } + } + } + } + + if(m_maxduration == -1 || m_isPassive && m_spellProto->DurationIndex == 0) + m_permanent = true; + + Player* modOwner = caster ? caster->GetSpellModOwner() : NULL; + + if(!m_permanent && modOwner) + modOwner->ApplySpellMod(GetId(), SPELLMOD_DURATION, m_maxduration); + + m_duration = m_maxduration; + + if(modOwner) + modOwner->ApplySpellMod(GetId(), SPELLMOD_ACTIVATION_TIME, m_periodicTimer); + + sLog.outDebug("Aura: construct Spellid : %u, Aura : %u Duration : %d Target : %d Damage : %d", m_spellProto->Id, m_spellProto->EffectApplyAuraName[eff], m_maxduration, m_spellProto->EffectImplicitTargetA[eff],damage); + + m_effIndex = eff; + SetModifier(AuraType(m_spellProto->EffectApplyAuraName[eff]), damage, m_spellProto->EffectAmplitude[eff], m_spellProto->EffectMiscValue[eff]); + + m_isDeathPersist = IsDeathPersistentSpell(m_spellProto); + + if(m_spellProto->procCharges) + { + m_procCharges = m_spellProto->procCharges; + + if(modOwner) + modOwner->ApplySpellMod(GetId(), SPELLMOD_CHARGES, m_procCharges); + } + else + m_procCharges = -1; + + m_isRemovedOnShapeLost = (m_caster_guid==m_target->GetGUID() && m_spellProto->Stances && + !(m_spellProto->AttributesEx2 & 0x80000) && !(m_spellProto->Attributes & 0x10000)); +} + +Aura::~Aura() +{ +} + +AreaAura::AreaAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, +Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, caster, castItem) +{ + m_isAreaAura = true; + + // caster==NULL in constructor args if target==caster in fact + Unit* caster_ptr = caster ? caster : target; + + m_radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(GetSpellProto()->EffectRadiusIndex[m_effIndex])); + if(Player* modOwner = caster_ptr->GetSpellModOwner()) + modOwner->ApplySpellMod(GetId(), SPELLMOD_RADIUS, m_radius); + + switch(spellproto->Effect[eff]) + { + case SPELL_EFFECT_APPLY_AREA_AURA_PARTY: + m_areaAuraType = AREA_AURA_PARTY; + if(target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isTotem()) + m_modifier.m_auraname = SPELL_AURA_NONE; + break; + case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND: + m_areaAuraType = AREA_AURA_FRIEND; + break; + case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY: + m_areaAuraType = AREA_AURA_ENEMY; + if(target == caster_ptr) + m_modifier.m_auraname = SPELL_AURA_NONE; // Do not do any effect on self + break; + case SPELL_EFFECT_APPLY_AREA_AURA_PET: + m_areaAuraType = AREA_AURA_PET; + break; + case SPELL_EFFECT_APPLY_AREA_AURA_OWNER: + m_areaAuraType = AREA_AURA_OWNER; + if(target == caster_ptr) + m_modifier.m_auraname = SPELL_AURA_NONE; + break; + default: + sLog.outError("Wrong spell effect in AreaAura constructor"); + ASSERT(false); + break; + } +} + +AreaAura::~AreaAura() +{ +} + +PersistentAreaAura::PersistentAreaAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, +Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, caster, castItem) +{ + m_isPersistent = true; +} + +PersistentAreaAura::~PersistentAreaAura() +{ +} + +SingleEnemyTargetAura::SingleEnemyTargetAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, +Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, caster, castItem) +{ + if (caster) + m_casters_target_guid = caster->GetTypeId()==TYPEID_PLAYER ? ((Player*)caster)->GetSelection() : caster->GetUInt64Value(UNIT_FIELD_TARGET); + else + m_casters_target_guid = 0; +} + +SingleEnemyTargetAura::~SingleEnemyTargetAura() +{ +} + +Unit* SingleEnemyTargetAura::GetTriggerTarget() const +{ + return ObjectAccessor::GetUnit(*m_target, m_casters_target_guid); +} + +Aura* CreateAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster, Item* castItem) +{ + if (IsAreaAuraEffect(spellproto->Effect[eff])) + return new AreaAura(spellproto, eff, currentBasePoints, target, caster, castItem); + + uint32 triggeredSpellId = spellproto->EffectTriggerSpell[eff]; + + SpellEntry const* triggredSpellInfo = sSpellStore.LookupEntry(triggeredSpellId); + if (triggredSpellInfo) + for (int i = 0; i < 3; ++i) + if (triggredSpellInfo->EffectImplicitTargetA[i] == TARGET_SINGLE_ENEMY) + return new SingleEnemyTargetAura(spellproto, eff, currentBasePoints, target, caster, castItem); + + return new Aura(spellproto, eff, currentBasePoints, target, caster, castItem); +} + +Unit* Aura::GetCaster() const +{ + if(m_caster_guid==m_target->GetGUID()) + return m_target; + + //return ObjectAccessor::GetUnit(*m_target,m_caster_guid); + //must return caster even if it's in another grid/map + Unit *unit = ObjectAccessor::GetObjectInWorld(m_caster_guid, (Unit*)NULL); + return unit && unit->IsInWorld() ? unit : NULL; +} + +void Aura::SetModifier(AuraType t, int32 a, uint32 pt, int32 miscValue) +{ + m_modifier.m_auraname = t; + m_modifier.m_amount = a; + m_modifier.m_miscvalue = miscValue; + m_modifier.periodictime = pt; +} + +void Aura::Update(uint32 diff) +{ + if (m_duration > 0) + { + m_duration -= diff; + if (m_duration < 0) + m_duration = 0; + m_timeCla -= diff; + + // GetEffIndex()==0 prevent double/triple apply manaPerSecond/manaPerSecondPerLevel to same spell with many auras + // all spells with manaPerSecond/manaPerSecondPerLevel have aura in effect 0 + if(GetEffIndex()==0 && m_timeCla <= 0) + { + if(Unit* caster = GetCaster()) + { + Powers powertype = Powers(m_spellProto->powerType); + int32 manaPerSecond = m_spellProto->manaPerSecond + m_spellProto->manaPerSecondPerLevel * caster->getLevel(); + m_timeCla = 1000; + if (manaPerSecond) + { + if(powertype==POWER_HEALTH) + caster->ModifyHealth(-manaPerSecond); + else + caster->ModifyPower(powertype,-manaPerSecond); + } + } + } + } + + // Channeled aura required check distance from caster + if(IsChanneledSpell(m_spellProto) && m_caster_guid != m_target->GetGUID()) + { + Unit* caster = GetCaster(); + if(!caster) + { + m_target->RemoveAura(GetId(),GetEffIndex()); + return; + } + + // Get spell range + float radius; + SpellModOp mod; + if (m_spellProto->EffectRadiusIndex[GetEffIndex()]) + { + radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellProto->EffectRadiusIndex[GetEffIndex()])); + mod = SPELLMOD_RADIUS; + } + else + { + radius = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellProto->rangeIndex)); + mod = SPELLMOD_RANGE; + } + + if(Player* modOwner = caster->GetSpellModOwner()) + modOwner->ApplySpellMod(GetId(), mod, radius,NULL); + + if(!caster->IsWithinDistInMap(m_target,radius)) + { + m_target->RemoveAura(GetId(),GetEffIndex()); + return; + } + } + + if(m_isPeriodic && (m_duration >= 0 || m_isPassive || m_permanent)) + { + m_periodicTimer -= diff; + if(m_periodicTimer <= 0) // tick also at m_periodicTimer==0 to prevent lost last tick in case max m_duration == (max m_periodicTimer)*N + { + if( m_modifier.m_auraname == SPELL_AURA_MOD_REGEN || + m_modifier.m_auraname == SPELL_AURA_MOD_POWER_REGEN || + // Cannibalize, eating items and other spells + m_modifier.m_auraname == SPELL_AURA_OBS_MOD_HEALTH || + // Eating items and other spells + m_modifier.m_auraname == SPELL_AURA_OBS_MOD_MANA ) + { + ApplyModifier(true); + return; + } + // update before applying (aura can be removed in TriggerSpell or PeriodicTick calls) + m_periodicTimer += m_modifier.periodictime; + + if(m_isTrigger) + TriggerSpell(); + else + PeriodicTick(); + } + } +} + +void AreaAura::Update(uint32 diff) +{ + // update for the caster of the aura + if(m_caster_guid == m_target->GetGUID()) + { + Unit* caster = m_target; + + if( !caster->hasUnitState(UNIT_STAT_ISOLATED) ) + { + Unit* owner = caster->GetCharmerOrOwner(); + if (!owner) + owner = caster; + std::list targets; + + switch(m_areaAuraType) + { + case AREA_AURA_PARTY: + { + Group *pGroup = NULL; + + if (owner->GetTypeId() == TYPEID_PLAYER) + pGroup = ((Player*)owner)->GetGroup(); + + if( pGroup) + { + uint8 subgroup = ((Player*)owner)->GetSubGroup(); + for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player* Target = itr->getSource(); + if(Target && Target->isAlive() && Target->GetSubGroup()==subgroup && caster->IsFriendlyTo(Target)) + { + if(caster->IsWithinDistInMap(Target, m_radius)) + targets.push_back(Target); + Pet *pet = Target->GetPet(); + if(pet && pet->isAlive() && caster->IsWithinDistInMap(pet, m_radius)) + targets.push_back(pet); + } + } + } + else + { + // add owner + if( owner != caster && caster->IsWithinDistInMap(owner, m_radius) ) + targets.push_back(owner); + // add caster's pet + Unit* pet = caster->GetPet(); + if( pet && caster->IsWithinDistInMap(pet, m_radius)) + targets.push_back(pet); + } + break; + } + case AREA_AURA_FRIEND: + { + CellPair p(MaNGOS::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + MaNGOS::AnyFriendlyUnitInObjectRangeCheck u_check(caster, owner, m_radius); + MaNGOS::UnitListSearcher searcher(targets, u_check); + TypeContainerVisitor, WorldTypeMapContainer > world_unit_searcher(searcher); + TypeContainerVisitor, GridTypeMapContainer > grid_unit_searcher(searcher); + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, world_unit_searcher, *MapManager::Instance().GetMap(caster->GetMapId(), caster)); + cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::Instance().GetMap(caster->GetMapId(), caster)); + break; + } + case AREA_AURA_ENEMY: + { + CellPair p(MaNGOS::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + MaNGOS::AnyAoETargetUnitInObjectRangeCheck u_check(caster, owner, m_radius); // No GetCharmer in searcher + MaNGOS::UnitListSearcher searcher(targets, u_check); + TypeContainerVisitor, WorldTypeMapContainer > world_unit_searcher(searcher); + TypeContainerVisitor, GridTypeMapContainer > grid_unit_searcher(searcher); + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, world_unit_searcher, *MapManager::Instance().GetMap(caster->GetMapId(), caster)); + cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::Instance().GetMap(caster->GetMapId(), caster)); + break; + } + case AREA_AURA_OWNER: + case AREA_AURA_PET: + { + if(owner != caster) + targets.push_back(owner); + break; + } + } + + for(std::list::iterator tIter = targets.begin(); tIter != targets.end(); tIter++) + { + if((*tIter)->HasAura(GetId(), m_effIndex)) + continue; + + if(SpellEntry const *actualSpellInfo = spellmgr.SelectAuraRankForPlayerLevel(GetSpellProto(), (*tIter)->getLevel())) + { + int32 actualBasePoints = m_currentBasePoints; + // recalculate basepoints for lower rank (all AreaAura spell not use custom basepoints?) + if(actualSpellInfo != GetSpellProto()) + actualBasePoints = actualSpellInfo->EffectBasePoints[m_effIndex]; + AreaAura *aur = new AreaAura(actualSpellInfo, m_effIndex, &actualBasePoints, (*tIter), caster, NULL); + (*tIter)->AddAura(aur); + } + } + } + Aura::Update(diff); + } + else // aura at non-caster + { + Unit * tmp_target = m_target; + Unit* caster = GetCaster(); + uint32 tmp_spellId = GetId(), tmp_effIndex = m_effIndex; + + // WARNING: the aura may get deleted during the update + // DO NOT access its members after update! + Aura::Update(diff); + + // remove aura if out-of-range from caster (after teleport for example) + // or caster is isolated or caster no longer has the aura + // or caster is (no longer) friendly + bool needFriendly = (m_areaAuraType == AREA_AURA_ENEMY ? false : true); + if( !caster || caster->hasUnitState(UNIT_STAT_ISOLATED) || + !caster->IsWithinDistInMap(tmp_target, m_radius) || + !caster->HasAura(tmp_spellId, tmp_effIndex) || + caster->IsFriendlyTo(tmp_target) != needFriendly + ) + { + tmp_target->RemoveAura(tmp_spellId, tmp_effIndex); + } + else if( m_areaAuraType == AREA_AURA_PARTY) // check if in same sub group + { + // not check group if target == owner or target == pet + if (caster->GetCharmerOrOwnerGUID() != tmp_target->GetGUID() && caster->GetGUID() != tmp_target->GetCharmerOrOwnerGUID()) + { + Player* check = caster->GetCharmerOrOwnerPlayerOrPlayerItself(); + + Group *pGroup = check ? check->GetGroup() : NULL; + if( pGroup ) + { + Player* checkTarget = tmp_target->GetCharmerOrOwnerPlayerOrPlayerItself(); + if(!checkTarget || !pGroup->SameSubGroup(check, checkTarget)) + tmp_target->RemoveAura(tmp_spellId, tmp_effIndex); + } + else + tmp_target->RemoveAura(tmp_spellId, tmp_effIndex); + } + } + else if( m_areaAuraType == AREA_AURA_PET || m_areaAuraType == AREA_AURA_OWNER ) + { + if( tmp_target->GetGUID() != caster->GetCharmerOrOwnerGUID() ) + tmp_target->RemoveAura(tmp_spellId, tmp_effIndex); + } + } +} + +void PersistentAreaAura::Update(uint32 diff) +{ + bool remove = false; + + // remove the aura if its caster or the dynamic object causing it was removed + // or if the target moves too far from the dynamic object + Unit *caster = GetCaster(); + if (caster) + { + DynamicObject *dynObj = caster->GetDynObject(GetId(), GetEffIndex()); + if (dynObj) + { + if (!m_target->IsWithinDistInMap(dynObj, dynObj->GetRadius())) + remove = true; + } + else + remove = true; + } + else + remove = true; + + Unit *tmp_target = m_target; + uint32 tmp_id = GetId(), tmp_index = GetEffIndex(); + + // WARNING: the aura may get deleted during the update + // DO NOT access its members after update! + Aura::Update(diff); + + if(remove) + tmp_target->RemoveAura(tmp_id, tmp_index); +} + +void Aura::ApplyModifier(bool apply, bool Real) +{ + AuraType aura = m_modifier.m_auraname; + + m_in_use = true; + if(aura= MAX_AURAS || m_isPassive) + return; + + if( m_target->GetTypeId() == TYPEID_PLAYER) + { + WorldPacket data(SMSG_UPDATE_AURA_DURATION, 5); + data << (uint8)m_auraSlot << (uint32)m_duration; + ((Player*)m_target)->SendDirectMessage(&data); + + data.Initialize(SMSG_SET_EXTRA_AURA_INFO, (8+1+4+4+4)); + data.append(m_target->GetPackGUID()); + data << uint8(m_auraSlot); + data << uint32(GetId()); + data << uint32(GetAuraMaxDuration()); + data << uint32(GetAuraDuration()); + ((Player*)m_target)->SendDirectMessage(&data); + } + + // not send in case player loading (will not work anyway until player not added to map), sent in visibility change code + if(m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading()) + return; + + Unit* caster = GetCaster(); + + if(caster && caster->GetTypeId() == TYPEID_PLAYER && caster != m_target) + SendAuraDurationForCaster((Player*)caster); +} + +void Aura::SendAuraDurationForCaster(Player* caster) +{ + WorldPacket data(SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE, (8+1+4+4+4)); + data.append(m_target->GetPackGUID()); + data << uint8(m_auraSlot); + data << uint32(GetId()); + data << uint32(GetAuraMaxDuration()); // full + data << uint32(GetAuraDuration()); // remain + caster->GetSession()->SendPacket(&data); +} + +void Aura::_AddAura() +{ + if (!GetId()) + return; + if(!m_target) + return; + + // we can found aura in NULL_AURA_SLOT and then need store state instead check slot != NULL_AURA_SLOT + bool samespell = false; + bool secondaura = false; + uint8 slot = NULL_AURA_SLOT; + + for(uint8 i = 0; i < 3; i++) + { + Unit::spellEffectPair spair = Unit::spellEffectPair(GetId(), i); + for(Unit::AuraMap::const_iterator itr = m_target->GetAuras().lower_bound(spair); itr != m_target->GetAuras().upper_bound(spair); ++itr) + { + // allow use single slot only by auras from same caster + if(itr->second->GetCasterGUID()==GetCasterGUID()) + { + samespell = true; + if (m_effIndex > itr->second->GetEffIndex()) + secondaura = true; + slot = itr->second->GetAuraSlot(); + break; + } + } + + if(samespell) + break; + } + + // not call total regen auras at adding + switch (m_modifier.m_auraname) + { + case SPELL_AURA_OBS_MOD_HEALTH: + case SPELL_AURA_OBS_MOD_MANA: + m_periodicTimer = m_modifier.periodictime; + break; + case SPELL_AURA_MOD_REGEN: + case SPELL_AURA_MOD_POWER_REGEN: + case SPELL_AURA_MOD_MANA_REGEN_FROM_STAT: + m_periodicTimer = 5000; + break; + } + + // register aura + if (getDiminishGroup() != DIMINISHING_NONE ) + m_target->ApplyDiminishingAura(getDiminishGroup(),true); + + Unit* caster = GetCaster(); + + // passive auras (except totem auras) do not get placed in the slots + // area auras with SPELL_AURA_NONE are not shown on target + if((!m_isPassive || (caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem())) && + (m_spellProto->Effect[GetEffIndex()] != SPELL_EFFECT_APPLY_AREA_AURA_ENEMY || m_target != caster)) + { + if(!samespell) // new slot need + { + if (IsPositive()) // empty positive slot + { + for (uint8 i = 0; i < MAX_POSITIVE_AURAS; i++) + { + if (m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURA + i)) == 0) + { + slot = i; + break; + } + } + } + else // empty negative slot + { + for (uint8 i = MAX_POSITIVE_AURAS; i < MAX_AURAS; i++) + { + if (m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURA + i)) == 0) + { + slot = i; + break; + } + } + } + + SetAuraSlot( slot ); + + // Not update fields for not first spell's aura, all data already in fields + if(!secondaura) + { + if(slot < MAX_AURAS) // slot found + { + SetAura(slot, false); + SetAuraFlag(slot, true); + SetAuraLevel(slot,caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); + UpdateAuraCharges(); + + // update for out of range group members + m_target->UpdateAuraForGroup(slot); + } + + UpdateAuraDuration(); + } + } + else // use found slot + { + SetAuraSlot( slot ); + // Not recalculate stack count for second aura of the same spell + if (!secondaura) + UpdateSlotCounterAndDuration(true); + } + + // Update Seals information + if( IsSealSpell(GetSpellProto()) ) + m_target->ModifyAuraState(AURA_STATE_JUDGEMENT, true); + + // Conflagrate aura state + if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 4)) + m_target->ModifyAuraState(AURA_STATE_IMMOLATE, true); + + if(GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID + && (GetSpellProto()->SpellFamilyFlags == 0x40 || GetSpellProto()->SpellFamilyFlags == 0x10)) + { + m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, true); + } + } +} + +void Aura::_RemoveAura() +{ + // Remove all triggered by aura spells vs unlimited duration + // except same aura replace case + if(m_removeMode!=AURA_REMOVE_BY_STACK) + CleanupTriggeredSpells(); + + Unit* caster = GetCaster(); + + if(caster && IsPersistent()) + { + DynamicObject *dynObj = caster->GetDynObject(GetId(), GetEffIndex()); + if (dynObj) + dynObj->RemoveAffected(m_target); + } + + // unregister aura + if (getDiminishGroup() != DIMINISHING_NONE ) + m_target->ApplyDiminishingAura(getDiminishGroup(),false); + + //passive auras do not get put in slots + // Note: but totem can be not accessible for aura target in time remove (to far for find in grid) + //if(m_isPassive && !(caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem())) + // return; + + uint8 slot = GetAuraSlot(); + + if(slot >= MAX_AURAS) // slot not set + return; + + if(m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURA + slot)) == 0) + return; + + bool samespell = false; + bool sameaura = false; + + // find other aura in same slot (current already removed from list) + for(uint8 i = 0; i < 3; i++) + { + Unit::spellEffectPair spair = Unit::spellEffectPair(GetId(), i); + for(Unit::AuraMap::const_iterator itr = m_target->GetAuras().lower_bound(spair); itr != m_target->GetAuras().upper_bound(spair); ++itr) + { + if(itr->second->GetAuraSlot()==slot) + { + samespell = true; + + if(GetEffIndex()==i) + sameaura = true; + + break; + } + } + if(samespell) + break; + } + + // only remove icon when the last aura of the spell is removed (current aura already removed from list) + if (!samespell) + { + SetAura(slot, true); + SetAuraFlag(slot, false); + SetAuraLevel(slot,caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); + + SetAuraApplication(slot, 0); + // update for out of range group members + m_target->UpdateAuraForGroup(slot); + + if( IsSealSpell(GetSpellProto()) ) + m_target->ModifyAuraState(AURA_STATE_JUDGEMENT,false); + + // Conflagrate aura state + if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 4)) + m_target->ModifyAuraState(AURA_STATE_IMMOLATE, false); + + // Swiftmend aura state + if(GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID + && (GetSpellProto()->SpellFamilyFlags == 0x40 || GetSpellProto()->SpellFamilyFlags == 0x10)) + { + bool found = false; + Unit::AuraList const& RejorRegr = m_target->GetAurasByType(SPELL_AURA_PERIODIC_HEAL); + for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i) + { + if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID + && ((*i)->GetSpellProto()->SpellFamilyFlags == 0x40 || (*i)->GetSpellProto()->SpellFamilyFlags == 0x10) ) + { + found = true; + break; + } + } + if(!found) + m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, false); + } + + // reset cooldown state for spells + if(caster && caster->GetTypeId() == TYPEID_PLAYER) + { + if ( GetSpellProto()->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE ) + ((Player*)caster)->SendCooldownEvent(GetSpellProto()); + } + } + else if(sameaura) // decrease count for spell, only for same aura effect, or this spell auras in remove proccess. + UpdateSlotCounterAndDuration(false); +} + +void Aura::SetAuraFlag(uint32 slot, bool add) +{ + uint32 index = slot / 4; + uint32 byte = (slot % 4) * 8; + uint32 val = m_target->GetUInt32Value(UNIT_FIELD_AURAFLAGS + index); + val &= ~((uint32)AFLAG_MASK << byte); + if(add) + { + if (IsPositive()) + val |= ((uint32)AFLAG_POSITIVE << byte); + else + val |= ((uint32)AFLAG_NEGATIVE << byte); + } + m_target->SetUInt32Value(UNIT_FIELD_AURAFLAGS + index, val); +} + +void Aura::SetAuraLevel(uint32 slot,uint32 level) +{ + uint32 index = slot / 4; + uint32 byte = (slot % 4) * 8; + uint32 val = m_target->GetUInt32Value(UNIT_FIELD_AURALEVELS + index); + val &= ~(0xFF << byte); + val |= (level << byte); + m_target->SetUInt32Value(UNIT_FIELD_AURALEVELS + index, val); +} + +void Aura::SetAuraApplication(uint32 slot, int8 count) +{ + uint32 index = slot / 4; + uint32 byte = (slot % 4) * 8; + uint32 val = m_target->GetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS + index); + val &= ~(0xFF << byte); + val |= ((uint8(count)) << byte); + m_target->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS + index, val); +} + +void Aura::UpdateSlotCounterAndDuration(bool add) +{ + uint8 slot = GetAuraSlot(); + if(slot >= MAX_AURAS) + return; + + // calculate amount of similar auras by same effect index (similar different spells) + int8 count = 0; + + // calculate auras and update durations in case aura adding + Unit::AuraList const& aura_list = m_target->GetAurasByType(GetModifier()->m_auraname); + for(Unit::AuraList::const_iterator i = aura_list.begin();i != aura_list.end(); ++i) + { + if( (*i)->GetId()==GetId() && (*i)->GetEffIndex()==m_effIndex && + (*i)->GetCasterGUID()==GetCasterGUID() ) + { + ++count; + + if(add) + (*i)->SetAuraDuration(GetAuraDuration()); + } + } + + // at aura add aura not added yet, at aura remove aura already removed + // in field stored (count-1) + if(!add) + --count; + + SetAuraApplication(slot, count); + + UpdateAuraDuration(); +} + +/*********************************************************/ +/*** BASIC AURA FUNCTION ***/ +/*********************************************************/ +void Aura::HandleAddModifier(bool apply, bool Real) +{ + if(m_target->GetTypeId() != TYPEID_PLAYER || !Real) + return; + + SpellEntry const *spellInfo = GetSpellProto(); + if(!spellInfo) + return; + + if(m_modifier.m_miscvalue >= MAX_SPELLMOD) + return; + + if (apply) + { + // Add custom charges for some mod aura + switch (m_spellProto->Id) + { + case 17941: // Shadow Trance + case 22008: // Netherwind Focus + case 34936: // Backlash + m_procCharges = 1; + break; + } + + SpellModifier *mod = new SpellModifier; + mod->op = SpellModOp(m_modifier.m_miscvalue); + mod->value = m_modifier.m_amount; + mod->type = SpellModType(m_modifier.m_auraname); // SpellModType value == spell aura types + mod->spellId = GetId(); + mod->effectId = m_effIndex; + mod->lastAffected = NULL; + + uint64 spellAffectMask = spellmgr.GetSpellAffectMask(GetId(), m_effIndex); + + if (spellAffectMask) + mod->mask = spellAffectMask; + else + mod->mask = spellInfo->EffectItemType[m_effIndex]; + + if (m_procCharges > 0) + mod->charges = m_procCharges; + else + mod->charges = 0; + + m_spellmod = mod; + } + + uint64 spellFamilyMask = m_spellmod->mask; + + ((Player*)m_target)->AddSpellMod(m_spellmod, apply); + + // reapply some passive spells after add/remove related spellmods + if(spellInfo->SpellFamilyName==SPELLFAMILY_WARRIOR && (spellFamilyMask & 0x0000100000000000LL)) + { + m_target->RemoveAurasDueToSpell(45471); + + if(apply) + m_target->CastSpell(m_target,45471,true); + } +} + +void Aura::TriggerSpell() +{ + Unit* caster = GetCaster(); + Unit* target = GetTriggerTarget(); + + if(!caster || !target) + return; + + // generic casting code with custom spells and target/caster customs + uint32 trigger_spell_id = GetSpellProto()->EffectTriggerSpell[m_effIndex]; + + uint64 originalCasterGUID = GetCasterGUID(); + + SpellEntry const *triggredSpellInfo = sSpellStore.LookupEntry(trigger_spell_id); + SpellEntry const *auraSpellInfo = GetSpellProto(); + uint32 auraId = auraSpellInfo->Id; + + // specific code for cases with no trigger spell provided in field + if (triggredSpellInfo == NULL) + { + switch(auraSpellInfo->SpellFamilyName) + { + case SPELLFAMILY_GENERIC: + { + switch(auraId) + { + // Firestone Passive (1-5 rangs) + case 758: + case 17945: + case 17947: + case 17949: + case 27252: + { + if (caster->GetTypeId()!=TYPEID_PLAYER) + return; + Item* item = ((Player*)caster)->GetWeaponForAttack(BASE_ATTACK); + if (!item) + return; + uint32 enchant_id = 0; + switch (GetId()) + { + case 758: enchant_id = 1803; break; // Rank 1 + case 17945: enchant_id = 1823; break; // Rank 2 + case 17947: enchant_id = 1824; break; // Rank 3 + case 17949: enchant_id = 1825; break; // Rank 4 + case 27252: enchant_id = 2645; break; // Rank 5 + default: + return; + } + // remove old enchanting before applying new + ((Player*)caster)->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,false); + item->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, m_modifier.periodictime+1000, 0); + // add new enchanting + ((Player*)caster)->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,true); + return; + } +// // Periodic Mana Burn +// case 812: break; +// // Polymorphic Ray +// case 6965: break; +// // Fire Nova (1-7 Rangs) +// case 8350: +// case 8508: +// case 8509: +// case 11312: +// case 11313: +// case 25540: +// case 25544: +// break; + // Thaumaturgy Channel + case 9712: trigger_spell_id = 21029; break; +// // Egan's Blaster +// case 17368: break; +// // Haunted +// case 18347: break; +// // Ranshalla Waiting +// case 18953: break; +// // Inferno +// case 19695: break; +// // Frostwolf Muzzle DND +// case 21794: break; +// // Alterac Ram Collar DND +// case 21866: break; +// // Celebras Waiting +// case 21916: break; + // Brood Affliction: Bronze + case 23170: + { + m_target->CastSpell(m_target, 23171, true, 0, this); + return; + } +// // Mark of Frost +// case 23184: break; + // Restoration + case 23493: + { + int32 heal = caster->GetMaxHealth() / 10; + caster->ModifyHealth( heal ); + caster->SendHealSpellLog(caster, 23493, heal); + + int32 mana = caster->GetMaxPower(POWER_MANA); + if (mana) + { + mana /= 10; + caster->ModifyPower( POWER_MANA, mana ); + caster->SendEnergizeSpellLog(caster, 23493, mana, POWER_MANA); + } + break; + } +// // Stoneclaw Totem Passive TEST +// case 23792: break; +// // Axe Flurry +// case 24018: break; +// // Mark of Arlokk +// case 24210: break; +// // Restoration +// case 24379: break; +// // Happy Pet +// case 24716: break; +// // Dream Fog +// case 24780: break; +// // Cannon Prep +// case 24832: break; +// // Shadow Bolt Whirl +// case 24834: break; +// // Stink Trap +// case 24918: break; +// // Mark of Nature +// case 25041: break; +// // Agro Drones +// case 25152: break; +// // Consume +// case 25371: break; +// // Pain Spike +// case 25572: break; +// // Rotate 360 +// case 26009: break; +// // Rotate -360 +// case 26136: break; +// // Consume +// case 26196: break; +// // Berserk +// case 26615: break; +// // Defile +// case 27177: break; +// // Teleport: IF/UC +// case 27601: break; +// // Five Fat Finger Exploding Heart Technique +// case 27673: break; +// // Nitrous Boost +// case 27746: break; +// // Steam Tank Passive +// case 27747: break; +// // Frost Blast +// case 27808: break; +// // Detonate Mana +// case 27819: break; +// // Controller Timer +// case 28095: break; +// // Stalagg Chain +// case 28096: break; +// // Stalagg Tesla Passive +// case 28097: break; +// // Feugen Tesla Passive +// case 28109: break; +// // Feugen Chain +// case 28111: break; +// // Mark of Didier +// case 28114: break; +// // Communique Timer, camp +// case 28346: break; +// // Icebolt +// case 28522: break; +// // Silithyst +// case 29519: break; +// // Inoculate Nestlewood Owlkin + case 29528: trigger_spell_id = 28713; break; +// // Overload +// case 29768: break; +// // Return Fire +// case 29788: break; +// // Return Fire +// case 29793: break; +// // Return Fire +// case 29794: break; +// // Guardian of Icecrown Passive +// case 29897: break; + // Feed Captured Animal + case 29917: trigger_spell_id = 29916; break; +// // Flame Wreath +// case 29946: break; +// // Flame Wreath +// case 29947: break; +// // Mind Exhaustion Passive +// case 30025: break; +// // Nether Beam - Serenity +// case 30401: break; + // Extract Gas + case 30427: + { + // move loot to player inventory and despawn target + if(caster->GetTypeId() ==TYPEID_PLAYER && + target->GetTypeId() == TYPEID_UNIT && + ((Creature*)target)->GetCreatureInfo()->type == CREATURE_TYPE_GAS_CLOUD) + { + Player* player = (Player*)caster; + Creature* creature = (Creature*)target; + // missing lootid has been reported on startup - just return + if (!creature->GetCreatureInfo()->SkinLootId) + { + return; + } + Loot *loot = &creature->loot; + loot->clear(); + loot->FillLoot(creature->GetCreatureInfo()->SkinLootId, LootTemplates_Skinning, NULL); + for(uint8 i=0;iitems.size();i++) + { + LootItem *item = loot->LootItemInSlot(i,player); + ItemPosCountVec dest; + uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, item->itemid, item->count ); + if ( msg == EQUIP_ERR_OK ) + { + Item * newitem = player->StoreNewItem( dest, item->itemid, true, item->randomPropertyId); + + player->SendNewItem(newitem, uint32(item->count), false, false, true); + } + else + player->SendEquipError( msg, NULL, NULL ); + } + creature->setDeathState(JUST_DIED); + creature->RemoveCorpse(); + creature->SetHealth(0); // just for nice GM-mode view + } + return; + break; + } + // Quake + case 30576: trigger_spell_id = 30571; break; +// // Burning Maul +// case 30598: break; +// // Regeneration +// case 30799: +// case 30800: +// case 30801: +// break; +// // Despawn Self - Smoke cloud +// case 31269: break; +// // Time Rift Periodic +// case 31320: break; +// // Corrupt Medivh +// case 31326: break; + // Doom + case 31347: + { + m_target->CastSpell(m_target,31350,true); + m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + return; + } + // Spellcloth + case 31373: + { + // Summon Elemental after create item + caster->SummonCreature(17870, 0, 0, 0, caster->GetOrientation(), TEMPSUMMON_DEAD_DESPAWN, 0); + return; + } +// // Bloodmyst Tesla +// case 31611: break; +// // Doomfire +// case 31944: break; +// // Teleport Test +// case 32236: break; +// // Earthquake +// case 32686: break; +// // Possess +// case 33401: break; +// // Draw Shadows +// case 33563: break; +// // Murmur's Touch +// case 33711: break; + // Flame Quills + case 34229: + { + // cast 24 spells 34269-34289, 34314-34316 + for(uint32 spell_id = 34269; spell_id != 34290; ++spell_id) + caster->CastSpell(m_target,spell_id,true); + for(uint32 spell_id = 34314; spell_id != 34317; ++spell_id) + caster->CastSpell(m_target,spell_id,true); + return; + } +// // Gravity Lapse +// case 34480: break; +// // Tornado +// case 34683: break; +// // Frostbite Rotate +// case 34748: break; +// // Arcane Flurry +// case 34821: break; +// // Interrupt Shutdown +// case 35016: break; +// // Interrupt Shutdown +// case 35176: break; +// // Inferno +// case 35268: break; +// // Salaadin's Tesla +// case 35515: break; +// // Ethereal Channel (Red) +// case 35518: break; +// // Nether Vapor +// case 35879: break; +// // Dark Portal Storm +// case 36018: break; +// // Burning Maul +// case 36056: break; +// // Living Grove Defender Lifespan +// case 36061: break; +// // Professor Dabiri Talks +// case 36064: break; +// // Kael Gaining Power +// case 36091: break; +// // They Must Burn Bomb Aura +// case 36344: break; +// // They Must Burn Bomb Aura (self) +// case 36350: break; +// // Stolen Ravenous Ravager Egg +// case 36401: break; +// // Activated Cannon +// case 36410: break; +// // Stolen Ravenous Ravager Egg +// case 36418: break; +// // Enchanted Weapons +// case 36510: break; +// // Cursed Scarab Periodic +// case 36556: break; +// // Cursed Scarab Despawn Periodic +// case 36561: break; +// // Vision Guide +// case 36573: break; +// // Cannon Charging (platform) +// case 36785: break; +// // Cannon Charging (self) +// case 36860: break; + // Remote Toy + case 37027: trigger_spell_id = 37029; break; +// // Mark of Death +// case 37125: break; +// // Arcane Flurry +// case 37268: break; +// // Spout +// case 37429: break; +// // Spout +// case 37430: break; +// // Karazhan - Chess NPC AI, Snapshot timer +// case 37440: break; +// // Karazhan - Chess NPC AI, action timer +// case 37504: break; +// // Karazhan - Chess: Is Square OCCUPIED aura (DND) +// case 39400: break; +// // Banish +// case 37546: break; +// // Shriveling Gaze +// case 37589: break; +// // Fake Aggro Radius (2 yd) +// case 37815: break; +// // Corrupt Medivh +// case 37853: break; + // Eye of Grillok + case 38495: + { + m_target->CastSpell(m_target, 38530, true); + return; + } + // Absorb Eye of Grillok (Zezzak's Shard) + case 38554: + { + if(m_target->GetTypeId() != TYPEID_UNIT) + return; + + caster->CastSpell(caster, 38495, true); + + Creature* creatureTarget = (Creature*)m_target; + + creatureTarget->setDeathState(JUST_DIED); + creatureTarget->RemoveCorpse(); + creatureTarget->SetHealth(0); // just for nice GM-mode view + return; + } +// // Magic Sucker Device timer +// case 38672: break; +// // Tomb Guarding Charging +// case 38751: break; +// // Murmur's Touch +// case 38794: break; +// // Activate Nether-wraith Beacon (31742 Nether-wraith Beacon item) +// case 39105: break; +// // Drain World Tree Visual +// case 39140: break; +// // Quest - Dustin's Undead Dragon Visual aura +// case 39259: break; +// // Hellfire - The Exorcism, Jules releases darkness, aura +// case 39306: break; +// // Inferno +// case 39346: break; +// // Enchanted Weapons +// case 39489: break; +// // Shadow Bolt Whirl +// case 39630: break; +// // Shadow Bolt Whirl +// case 39634: break; +// // Shadow Inferno +// case 39645: break; + // Tear of Azzinoth Summon Channel - it's not really supposed to do anything,and this only prevents the console spam + case 39857: trigger_spell_id = 39856; break; +// // Soulgrinder Ritual Visual (Smashed) +// case 39974: break; +// // Simon Game Pre-game timer +// case 40041: break; +// // Knockdown Fel Cannon: The Aggro Check Aura +// case 40113: break; +// // Spirit Lance +// case 40157: break; +// // Demon Transform 2 +// case 40398: break; +// // Demon Transform 1 +// case 40511: break; +// // Ancient Flames +// case 40657: break; +// // Ethereal Ring Cannon: Cannon Aura +// case 40734: break; +// // Cage Trap +// case 40760: break; +// // Random Periodic +// case 40867: break; +// // Prismatic Shield +// case 40879: break; +// // Aura of Desire +// case 41350: break; +// // Dementia +// case 41404: break; +// // Chaos Form +// case 41629: break; +// // Alert Drums +// case 42177: break; +// // Spout +// case 42581: break; +// // Spout +// case 42582: break; +// // Return to the Spirit Realm +// case 44035: break; +// // Curse of Boundless Agony +// case 45050: break; +// // Earthquake +// case 46240: break; + // Personalized Weather + case 46736: trigger_spell_id = 46737; break; +// // Stay Submerged +// case 46981: break; +// // Dragonblight Ram +// case 47015: break; +// // Party G.R.E.N.A.D.E. +// case 51510: break; + default: + break; + } + break; + } + case SPELLFAMILY_MAGE: + { + switch(auraId) + { + // Invisibility + case 66: + { + if(!m_duration) + m_target->CastSpell(m_target, 32612, true, NULL, this); + return; + } + default: + break; + } + break; + } +// case SPELLFAMILY_WARRIOR: +// { +// switch(auraId) +// { +// // Wild Magic +// case 23410: break; +// // Corrupted Totems +// case 23425: break; +// default: +// break; +// } +// break; +// } +// case SPELLFAMILY_PRIEST: +// { +// switch(auraId) +// { +// // Blue Beam +// case 32930: break; +// // Fury of the Dreghood Elders +// case 35460: break; +// default: +// break; +// } + // break; + // } + case SPELLFAMILY_DRUID: + { + switch(auraId) + { + // Cat Form + // trigger_spell_id not set and unknown effect triggered in this case, ignoring for while + case 768: + return; + // Frenzied Regeneration + case 22842: + case 22895: + case 22896: + case 26999: + { + int32 LifePerRage = GetModifier()->m_amount; + + int32 lRage = m_target->GetPower(POWER_RAGE); + if(lRage > 100) // rage stored as rage*10 + lRage = 100; + m_target->ModifyPower(POWER_RAGE, -lRage); + int32 FRTriggerBasePoints = int32(lRage*LifePerRage/10); + m_target->CastCustomSpell(m_target,22845,&FRTriggerBasePoints,NULL,NULL,true,NULL,this); + return; + } + default: + break; + } + break; + } + +// case SPELLFAMILY_HUNTER: +// { +// switch(auraId) +// { +// //Frost Trap Aura +// case 13810: +// return; +// //Rizzle's Frost Trap +// case 39900: +// return; +// // Tame spells +// case 19597: // Tame Ice Claw Bear +// case 19676: // Tame Snow Leopard +// case 19677: // Tame Large Crag Boar +// case 19678: // Tame Adult Plainstrider +// case 19679: // Tame Prairie Stalker +// case 19680: // Tame Swoop +// case 19681: // Tame Dire Mottled Boar +// case 19682: // Tame Surf Crawler +// case 19683: // Tame Armored Scorpid +// case 19684: // Tame Webwood Lurker +// case 19685: // Tame Nightsaber Stalker +// case 19686: // Tame Strigid Screecher +// case 30100: // Tame Crazed Dragonhawk +// case 30103: // Tame Elder Springpaw +// case 30104: // Tame Mistbat +// case 30647: // Tame Barbed Crawler +// case 30648: // Tame Greater Timberstrider +// case 30652: // Tame Nightstalker +// return; +// default: +// break; +// } +// break; +// } + case SPELLFAMILY_SHAMAN: + { + switch(auraId) + { + // Lightning Shield (The Earthshatterer set trigger after cast Lighting Shield) + case 28820: + { + // Need remove self if Lightning Shield not active + Unit::AuraMap const& auras = target->GetAuras(); + for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) + { + SpellEntry const* spell = itr->second->GetSpellProto(); + if( spell->SpellFamilyName == SPELLFAMILY_SHAMAN && + spell->SpellFamilyFlags & 0x0000000000000400L) + return; + } + target->RemoveAurasDueToSpell(28820); + return; + } + // Totemic Mastery (Skyshatter Regalia (Shaman Tier 6) - bonus) + case 38443: + { + bool all = true; + for(int i = 0; i < MAX_TOTEM; ++i) + { + if(!caster->m_TotemSlot[i]) + { + all = false; + break; + } + } + + if(all) + caster->CastSpell(caster,38437,true); + else + caster->RemoveAurasDueToSpell(38437); + return; + } + default: + break; + } + break; + } + default: + break; + } + // Reget trigger spell proto + triggredSpellInfo = sSpellStore.LookupEntry(trigger_spell_id); + if(triggredSpellInfo == NULL) + { + sLog.outError("Aura::TriggerSpell: Spell %u have 0 in EffectTriggered[%d], not handled custom case?",GetId(),GetEffIndex()); + return; + } + } + else + { + // Spell exist but require costum code + switch(auraId) + { + // Curse of Idiocy + case 1010: + { + // TODO: spell casted by result in correct way mostly + // BUT: + // 1) target show casting at each triggered cast: target don't must show casting animation for any triggered spell + // but must show affect apply like item casting + // 2) maybe aura must be replace by new with accumulative stat mods insteed stacking + + // prevent cast by triggered auras + if(m_caster_guid == m_target->GetGUID()) + return; + + // stop triggering after each affected stats lost > 90 + int32 intelectLoss = 0; + int32 spiritLoss = 0; + + Unit::AuraList const& mModStat = m_target->GetAurasByType(SPELL_AURA_MOD_STAT); + for(Unit::AuraList::const_iterator i = mModStat.begin(); i != mModStat.end(); ++i) + { + if ((*i)->GetId() == 1010) + { + switch((*i)->GetModifier()->m_miscvalue) + { + case STAT_INTELLECT: intelectLoss += (*i)->GetModifier()->m_amount; break; + case STAT_SPIRIT: spiritLoss += (*i)->GetModifier()->m_amount; break; + default: break; + } + } + } + + if(intelectLoss <= -90 && spiritLoss <= -90) + return; + + caster = target; + originalCasterGUID = 0; + break; + } + // Mana Tide + case 16191: + { + caster->CastCustomSpell(target, trigger_spell_id, &m_modifier.m_amount, NULL, NULL, true, NULL, this, originalCasterGUID); + return; + } + } + } + // All ok cast by default case + Spell *spell = new Spell(caster, triggredSpellInfo, true, originalCasterGUID ); + + SpellCastTargets targets; + targets.setUnitTarget( target ); + + // if spell create dynamic object extract area from it + if(DynamicObject* dynObj = caster->GetDynObject(GetId())) + targets.setDestination(dynObj->GetPositionX(),dynObj->GetPositionY(),dynObj->GetPositionZ()); + + spell->prepare(&targets, this); +} + +/*********************************************************/ +/*** AURA EFFECTS ***/ +/*********************************************************/ + +void Aura::HandleAuraDummy(bool apply, bool Real) +{ + // spells required only Real aura add/remove + if(!Real) + return; + + Unit* caster = GetCaster(); + + // AT APPLY + if(apply) + { + switch(GetId()) + { + case 1515: // Tame beast + // FIX_ME: this is 2.0.12 threat effect replaced in 2.1.x by dummy aura, must be checked for correctness + if( caster && m_target->CanHaveThreatList()) + m_target->AddThreat(caster, 10.0f); + return; + case 13139: // net-o-matic + // root to self part of (root_target->charge->root_self sequence + if(caster) + caster->CastSpell(caster,13138,true,NULL,this); + return; + case 39850: // Rocket Blast + if(roll_chance_i(20)) // backfire stun + m_target->CastSpell(m_target, 51581, true, NULL, this); + return; + case 46354: // Blood Elf Illusion + if(caster) + { + switch(caster->getGender()) + { + case GENDER_FEMALE: + caster->CastSpell(m_target,46356,true,NULL,this); + break; + case GENDER_MALE: + caster->CastSpell(m_target,46355,true,NULL,this); + break; + default: + break; + } + } + return; + case 46699: // Requires No Ammo + if(m_target->GetTypeId()==TYPEID_PLAYER) + ((Player*)m_target)->RemoveAmmo(); // not use ammo and not allow use + return; + } + + // Earth Shield + if ( caster && GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN && (GetSpellProto()->SpellFamilyFlags & 0x40000000000LL)) + { + // prevent double apply bonuses + if(m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading()) + m_modifier.m_amount = caster->SpellHealingBonus(GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE, m_target); + return; + } + } + // AT REMOVE + else + { + if( m_target->GetTypeId() == TYPEID_PLAYER && + ( GetSpellProto()->Effect[0]==72 || GetSpellProto()->Effect[0]==6 && + ( GetSpellProto()->EffectApplyAuraName[0]==1 || GetSpellProto()->EffectApplyAuraName[0]==128 ) ) ) + { + // spells with SpellEffect=72 and aura=4: 6196, 6197, 21171, 21425 + m_target->SetUInt64Value(PLAYER_FARSIGHT, 0); + WorldPacket data(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, 0); + ((Player*)m_target)->GetSession()->SendPacket(&data); + return; + } + + if( (IsQuestTameSpell(GetId())) && caster && caster->isAlive() && m_target->isAlive()) + { + uint32 finalSpelId = 0; + switch(GetId()) + { + case 19548: finalSpelId = 19597; break; + case 19674: finalSpelId = 19677; break; + case 19687: finalSpelId = 19676; break; + case 19688: finalSpelId = 19678; break; + case 19689: finalSpelId = 19679; break; + case 19692: finalSpelId = 19680; break; + case 19693: finalSpelId = 19684; break; + case 19694: finalSpelId = 19681; break; + case 19696: finalSpelId = 19682; break; + case 19697: finalSpelId = 19683; break; + case 19699: finalSpelId = 19685; break; + case 19700: finalSpelId = 19686; break; + case 30646: finalSpelId = 30647; break; + case 30653: finalSpelId = 30648; break; + case 30654: finalSpelId = 30652; break; + case 30099: finalSpelId = 30100; break; + case 30102: finalSpelId = 30103; break; + case 30105: finalSpelId = 30104; break; + } + + if(finalSpelId) + caster->CastSpell(m_target,finalSpelId,true,NULL,this); + return; + } + // Dark Fiend + if(GetId()==45934) + { + // Kill target if dispeled + if (m_removeMode==AURA_REMOVE_BY_DISPEL) + m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + return; + } + + // Burning Winds + if(GetId()==46308) // casted only at creatures at spawn + { + m_target->CastSpell(m_target,47287,true,NULL,this); + return; + } + } + + // AT APPLY & REMOVE + + switch(m_spellProto->SpellFamilyName) + { + case SPELLFAMILY_GENERIC: + { + // Unstable Power + if( GetId()==24658 ) + { + uint32 spellId = 24659; + if (apply) + { + const SpellEntry *spell = sSpellStore.LookupEntry(spellId); + if (!spell) + return; + for (int i=0; i < spell->StackAmount; ++i) + caster->CastSpell(m_target, spell->Id, true, NULL, NULL, GetCasterGUID()); + return; + } + m_target->RemoveAurasDueToSpell(spellId); + return; + } + // Restless Strength + if( GetId()==24661 ) + { + uint32 spellId = 24662; + if (apply) + { + const SpellEntry *spell = sSpellStore.LookupEntry(spellId); + if (!spell) + return; + for (int i=0; i < spell->StackAmount; ++i) + caster->CastSpell(m_target, spell->Id, true, NULL, NULL, GetCasterGUID()); + return; + } + m_target->RemoveAurasDueToSpell(spellId); + return; + } + // Victorious + if(GetId()==32216 && m_target->getClass()==CLASS_WARRIOR) + { + m_target->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, apply); + return; + } + //Summon Fire Elemental + if (GetId() == 40133 && caster) + { + Unit *owner = caster->GetOwner(); + if (owner && owner->GetTypeId() == TYPEID_PLAYER) + { + if(apply) + owner->CastSpell(owner,8985,true); + else + ((Player*)owner)->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true); + } + return; + } + + //Summon Earth Elemental + if (GetId() == 40132 && caster) + { + Unit *owner = caster->GetOwner(); + if (owner && owner->GetTypeId() == TYPEID_PLAYER) + { + if(apply) + owner->CastSpell(owner,19704,true); + else + ((Player*)owner)->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true); + } + return; + } + break; + } + case SPELLFAMILY_MAGE: + { + // Hypothermia + if( GetId()==41425 ) + { + m_target->ModifyAuraState(AURA_STATE_HYPOTHERMIA,apply); + return; + } + break; + } + case SPELLFAMILY_DRUID: + { + // Lifebloom + if ( GetSpellProto()->SpellFamilyFlags & 0x1000000000LL ) + { + if ( apply ) + { + if ( caster ) + // prevent double apply bonuses + if(m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading()) + m_modifier.m_amount = caster->SpellHealingBonus(GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE, m_target); + } + else + { + // Final heal only on dispelled or duration end + if ( !(GetAuraDuration() <= 0 || m_removeMode==AURA_REMOVE_BY_DISPEL) ) + return; + + // have a look if there is still some other Lifebloom dummy aura + Unit::AuraList auras = m_target->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraList::iterator itr = auras.begin(); itr!=auras.end(); itr++) + if((*itr)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID && + (*itr)->GetSpellProto()->SpellFamilyFlags & 0x1000000000LL) + return; + + // final heal + m_target->CastCustomSpell(m_target,33778,&m_modifier.m_amount,NULL,NULL,true,NULL,this,GetCasterGUID()); + } + return; + } + + // Predatory Strikes + if(m_target->GetTypeId()==TYPEID_PLAYER && GetSpellProto()->SpellIconID == 1563) + { + ((Player*)m_target)->UpdateAttackPowerAndDamage(); + return; + } + // Idol of the Emerald Queen + if ( GetId() == 34246 && m_target->GetTypeId()==TYPEID_PLAYER ) + { + if(apply) + { + SpellModifier *mod = new SpellModifier; + mod->op = SPELLMOD_DOT; + mod->value = m_modifier.m_amount/7; + mod->type = SPELLMOD_FLAT; + mod->spellId = GetId(); + mod->effectId = m_effIndex; + mod->lastAffected = NULL; + mod->mask = 0x001000000000LL; + mod->charges = 0; + + m_spellmod = mod; + } + + ((Player*)m_target)->AddSpellMod(m_spellmod, apply); + return; + } + break; + } + case SPELLFAMILY_HUNTER: + { + // Improved Aspect of the Viper + if( GetId()==38390 && m_target->GetTypeId()==TYPEID_PLAYER ) + { + if(apply) + { + // + effect value for Aspect of the Viper + SpellModifier *mod = new SpellModifier; + mod->op = SPELLMOD_EFFECT1; + mod->value = m_modifier.m_amount; + mod->type = SPELLMOD_FLAT; + mod->spellId = GetId(); + mod->effectId = m_effIndex; + mod->lastAffected = NULL; + mod->mask = 0x4000000000000LL; + mod->charges = 0; + + m_spellmod = mod; + } + + ((Player*)m_target)->AddSpellMod(m_spellmod, apply); + return; + } + break; + } + case SPELLFAMILY_SHAMAN: + { + // Improved Weapon Totems + if( GetSpellProto()->SpellIconID == 57 && m_target->GetTypeId()==TYPEID_PLAYER ) + { + if(apply) + { + SpellModifier *mod = new SpellModifier; + mod->op = SPELLMOD_EFFECT1; + mod->value = m_modifier.m_amount; + mod->type = SPELLMOD_PCT; + mod->spellId = GetId(); + mod->effectId = m_effIndex; + mod->lastAffected = NULL; + switch (m_effIndex) + { + case 0: + mod->mask = 0x00200000000LL; // Windfury Totem + break; + case 1: + mod->mask = 0x00400000000LL; // Flametongue Totem + break; + } + mod->charges = 0; + + m_spellmod = mod; + } + + ((Player*)m_target)->AddSpellMod(m_spellmod, apply); + return; + } + break; + } + } + + // pet auras + if(PetAura const* petSpell = spellmgr.GetPetAura(GetId())) + { + if(apply) + m_target->AddPetAura(petSpell); + else + m_target->RemovePetAura(petSpell); + return; + } +} + +void Aura::HandleAuraPeriodicDummy(bool apply, bool Real) +{ + // spells required only Real aura add/remove + if(!Real) + return; + + SpellEntry const*spell = GetSpellProto(); + switch( spell->SpellFamilyName) + { + case SPELLFAMILY_ROGUE: + { + // Master of Subtlety + if (spell->Id==31666 && !apply && Real) + { + m_target->RemoveAurasDueToSpell(31665); + break; + } + break; + } + case SPELLFAMILY_HUNTER: + { + // Aspect of the Viper + if (spell->SpellFamilyFlags&0x0004000000000000LL) + { + // Update regen on remove + if (!apply && m_target->GetTypeId() == TYPEID_PLAYER) + ((Player*)m_target)->UpdateManaRegen(); + break; + } + break; + } + } + + m_isPeriodic = apply; +} + +void Aura::HandleAuraMounted(bool apply, bool Real) +{ + if(apply) + { + CreatureInfo const* ci = objmgr.GetCreatureTemplate(m_modifier.m_miscvalue); + if(!ci) + { + sLog.outErrorDb("AuraMounted: `creature_template`='%u' not found in database (only need it modelid)", m_modifier.m_miscvalue); + return; + } + + uint32 team = 0; + if (m_target->GetTypeId()==TYPEID_PLAYER) + team = ((Player*)m_target)->GetTeam(); + + uint32 display_id = objmgr.ChooseDisplayId(team,ci); + CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id); + if (minfo) + display_id = minfo->modelid; + + m_target->Mount(display_id); + } + else + { + m_target->Unmount(); + } +} + +void Aura::HandleAuraWaterWalk(bool apply, bool Real) +{ + // only at real add/remove aura + if(!Real) + return; + + WorldPacket data; + if(apply) + data.Initialize(SMSG_MOVE_WATER_WALK, 8+4); + else + data.Initialize(SMSG_MOVE_LAND_WALK, 8+4); + data.append(m_target->GetPackGUID()); + data << uint32(0); + m_target->SendMessageToSet(&data,true); +} + +void Aura::HandleAuraFeatherFall(bool apply, bool Real) +{ + // only at real add/remove aura + if(!Real) + return; + + WorldPacket data; + if(apply) + data.Initialize(SMSG_MOVE_FEATHER_FALL, 8+4); + else + data.Initialize(SMSG_MOVE_NORMAL_FALL, 8+4); + data.append(m_target->GetPackGUID()); + data << (uint32)0; + m_target->SendMessageToSet(&data,true); +} + +void Aura::HandleAuraHover(bool apply, bool Real) +{ + // only at real add/remove aura + if(!Real) + return; + + WorldPacket data; + if(apply) + data.Initialize(SMSG_MOVE_SET_HOVER, 8+4); + else + data.Initialize(SMSG_MOVE_UNSET_HOVER, 8+4); + data.append(m_target->GetPackGUID()); + data << uint32(0); + m_target->SendMessageToSet(&data,true); +} + +void Aura::HandleWaterBreathing(bool apply, bool Real) +{ + if(apply) + m_target->waterbreath = true; + else if(m_target->GetAurasByType(SPELL_AURA_WATER_BREATHING).empty()) + { + m_target->waterbreath = false; + + // update for enable timer in case not moving target + if(m_target->GetTypeId()==TYPEID_PLAYER && m_target->IsInWorld()) + { + ((Player*)m_target)->UpdateUnderwaterState(m_target->GetMap(),m_target->GetPositionX(),m_target->GetPositionY(),m_target->GetPositionZ()); + ((Player*)m_target)->HandleDrowning(); + } + } +} + +void Aura::HandleAuraModShapeshift(bool apply, bool Real) +{ + if(!Real) + return; + + uint32 modelid = 0; + Powers PowerType = POWER_MANA; + ShapeshiftForm form = ShapeshiftForm(m_modifier.m_miscvalue); + switch(form) + { + case FORM_CAT: + if(Player::TeamForRace(m_target->getRace())==ALLIANCE) + modelid = 892; + else + modelid = 8571; + PowerType = POWER_ENERGY; + break; + case FORM_TRAVEL: + modelid = 632; + break; + case FORM_AQUA: + if(Player::TeamForRace(m_target->getRace())==ALLIANCE) + modelid = 2428; + else + modelid = 2428; + break; + case FORM_BEAR: + if(Player::TeamForRace(m_target->getRace())==ALLIANCE) + modelid = 2281; + else + modelid = 2289; + PowerType = POWER_RAGE; + break; + case FORM_GHOUL: + if(Player::TeamForRace(m_target->getRace())==ALLIANCE) + modelid = 10045; + break; + case FORM_DIREBEAR: + if(Player::TeamForRace(m_target->getRace())==ALLIANCE) + modelid = 2281; + else + modelid = 2289; + PowerType = POWER_RAGE; + break; + case FORM_CREATUREBEAR: + modelid = 902; + break; + case FORM_GHOSTWOLF: + modelid = 4613; + break; + case FORM_FLIGHT: + if(Player::TeamForRace(m_target->getRace())==ALLIANCE) + modelid = 20857; + else + modelid = 20872; + break; + case FORM_MOONKIN: + if(Player::TeamForRace(m_target->getRace())==ALLIANCE) + modelid = 15374; + else + modelid = 15375; + break; + case FORM_FLIGHT_EPIC: + if(Player::TeamForRace(m_target->getRace())==ALLIANCE) + modelid = 21243; + else + modelid = 21244; + break; + case FORM_AMBIENT: + case FORM_SHADOW: + case FORM_STEALTH: + break; + case FORM_TREE: + modelid = 864; + break; + case FORM_BATTLESTANCE: + case FORM_BERSERKERSTANCE: + case FORM_DEFENSIVESTANCE: + PowerType = POWER_RAGE; + break; + case FORM_SPIRITOFREDEMPTION: + modelid = 16031; + break; + default: + sLog.outError("Auras: Unknown Shapeshift Type: %u", m_modifier.m_miscvalue); + } + + // remove polymorph before changing display id to keep new display id + switch ( form ) + { + case FORM_CAT: + case FORM_TREE: + case FORM_TRAVEL: + case FORM_AQUA: + case FORM_BEAR: + case FORM_DIREBEAR: + case FORM_FLIGHT_EPIC: + case FORM_FLIGHT: + case FORM_MOONKIN: + // remove movement affects + m_target->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT); + m_target->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED); + + // and polymorphic affects + if(m_target->IsPolymorphed()) + m_target->RemoveAurasDueToSpell(m_target->getTransForm()); + break; + default: + break; + } + + if(apply) + { + // remove other shapeshift before applying a new one + if(m_target->m_ShapeShiftFormSpellId) + { + m_target->RemoveAurasDueToSpell(m_target->m_ShapeShiftFormSpellId,this); + } + + m_target->SetByteValue(UNIT_FIELD_BYTES_2, 3, form); + + if(modelid > 0) + { + m_target->SetDisplayId(modelid); + } + + if(PowerType != POWER_MANA) + { + // reset power to default values only at power change + if(m_target->getPowerType()!=PowerType) + m_target->setPowerType(PowerType); + + switch(form) + { + case FORM_CAT: + case FORM_BEAR: + case FORM_DIREBEAR: + { + // get furor proc chance + uint32 FurorChance = 0; + Unit::AuraList const& mDummy = m_target->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraList::const_iterator i = mDummy.begin(); i != mDummy.end(); ++i) + { + if ((*i)->GetSpellProto()->SpellIconID == 238) + { + FurorChance = (*i)->GetModifier()->m_amount; + break; + } + } + + if (m_modifier.m_miscvalue == FORM_CAT) + { + m_target->SetPower(POWER_ENERGY,0); + if(urand(1,100) <= FurorChance) + { + m_target->CastSpell(m_target,17099,true,NULL,this); + } + } + else + { + m_target->SetPower(POWER_RAGE,0); + if(urand(1,100) <= FurorChance) + { + m_target->CastSpell(m_target,17057,true,NULL,this); + } + } + break; + } + case FORM_BATTLESTANCE: + case FORM_DEFENSIVESTANCE: + case FORM_BERSERKERSTANCE: + { + uint32 Rage_val = 0; + // Stance mastery + Tactical mastery (both passive, and last have aura only in defense stance, but need apply at any stance switch) + if(m_target->GetTypeId() == TYPEID_PLAYER) + { + PlayerSpellMap const& sp_list = ((Player *)m_target)->GetSpellMap(); + for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr) + { + if(itr->second->state == PLAYERSPELL_REMOVED) continue; + SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first); + if (spellInfo && spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR && spellInfo->SpellIconID == 139) + Rage_val += m_target->CalculateSpellDamage(spellInfo,0,spellInfo->EffectBasePoints[0],m_target) * 10; + } + } + + if (m_target->GetPower(POWER_RAGE) > Rage_val) + m_target->SetPower(POWER_RAGE,Rage_val); + break; + } + default: + break; + } + } + + m_target->m_ShapeShiftFormSpellId = GetId(); + m_target->m_form = form; + } + else + { + m_target->SetDisplayId(m_target->GetNativeDisplayId()); + m_target->SetByteValue(UNIT_FIELD_BYTES_2, 3, FORM_NONE); + if(m_target->getClass() == CLASS_DRUID) + m_target->setPowerType(POWER_MANA); + m_target->m_ShapeShiftFormSpellId = 0; + m_target->m_form = FORM_NONE; + + switch(form) + { + // Nordrassil Harness - bonus + case FORM_BEAR: + case FORM_DIREBEAR: + case FORM_CAT: + { + if(Aura* dummy = m_target->GetDummyAura(37315) ) + m_target->CastSpell(m_target,37316,true,NULL,dummy); + break; + } + // Nordrassil Regalia - bonus + case FORM_MOONKIN: + { + if(Aura* dummy = m_target->GetDummyAura(37324) ) + m_target->CastSpell(m_target,37325,true,NULL,dummy); + break; + } + } + } + + // adding/removing linked auras + // add/remove the shapeshift aura's boosts + HandleShapeshiftBoosts(apply); + + if(m_target->GetTypeId()==TYPEID_PLAYER) + ((Player*)m_target)->InitDataForForm(); +} + +void Aura::HandleAuraTransform(bool apply, bool Real) +{ + if (apply) + { + // special case (spell specific functionality) + if(m_modifier.m_miscvalue==0) + { + // player applied only + if(m_target->GetTypeId()!=TYPEID_PLAYER) + return; + + switch(GetId()) + { + // Orb of Deception + case 16739: + { + uint32 orb_model = m_target->GetNativeDisplayId(); + switch(orb_model) + { + // Troll Female + case 1479: m_target->SetDisplayId(10134); break; + // Troll Male + case 1478: m_target->SetDisplayId(10135); break; + // Tauren Male + case 59: m_target->SetDisplayId(10136); break; + // Human Male + case 49: m_target->SetDisplayId(10137); break; + // Human Female + case 50: m_target->SetDisplayId(10138); break; + // Orc Male + case 51: m_target->SetDisplayId(10139); break; + // Orc Female + case 52: m_target->SetDisplayId(10140); break; + // Dwarf Male + case 53: m_target->SetDisplayId(10141); break; + // Dwarf Female + case 54: m_target->SetDisplayId(10142); break; + // NightElf Male + case 55: m_target->SetDisplayId(10143); break; + // NightElf Female + case 56: m_target->SetDisplayId(10144); break; + // Undead Female + case 58: m_target->SetDisplayId(10145); break; + // Undead Male + case 57: m_target->SetDisplayId(10146); break; + // Tauren Female + case 60: m_target->SetDisplayId(10147); break; + // Gnome Male + case 1563: m_target->SetDisplayId(10148); break; + // Gnome Female + case 1564: m_target->SetDisplayId(10149); break; + // BloodElf Female + case 15475: m_target->SetDisplayId(17830); break; + // BloodElf Male + case 15476: m_target->SetDisplayId(17829); break; + // Dranei Female + case 16126: m_target->SetDisplayId(17828); break; + // Dranei Male + case 16125: m_target->SetDisplayId(17827); break; + default: break; + } + break; + } + // Murloc costume + case 42365: m_target->SetDisplayId(21723); break; + default: break; + } + } + else + { + CreatureInfo const * ci = objmgr.GetCreatureTemplate(m_modifier.m_miscvalue); + if(!ci) + { + //pig pink ^_^ + m_target->SetDisplayId(16358); + sLog.outError("Auras: unknown creature id = %d (only need its modelid) Form Spell Aura Transform in Spell ID = %d", m_modifier.m_miscvalue, GetId()); + } + else + { + // Will use the default model here + m_target->SetDisplayId(ci->DisplayID_A); + + // Dragonmaw Illusion (set mount model also) + if(GetId()==42016 && m_target->GetMountID() && !m_target->GetAurasByType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED).empty()) + m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314); + } + m_target->setTransForm(GetId()); + } + + // polymorph case + if( Real && m_target->GetTypeId() == TYPEID_PLAYER && m_target->IsPolymorphed()) + { + // for players, start regeneration after 1s (in polymorph fast regeneration case) + // only if caster is Player (after patch 2.4.2) + if(IS_PLAYER_GUID(GetCasterGUID()) ) + ((Player*)m_target)->setRegenTimer(1000); + + //dismount polymorphed target (after patch 2.4.2) + if (m_target->IsMounted()) + m_target->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); + } + } + else + { + Unit::AuraList const& otherTransforms = m_target->GetAurasByType(SPELL_AURA_TRANSFORM); + if(otherTransforms.empty()) + { + m_target->SetDisplayId(m_target->GetNativeDisplayId()); + m_target->setTransForm(0); + } + else + { + // look for other transform auras + Aura* handledAura = *otherTransforms.begin(); + for(Unit::AuraList::const_iterator i = otherTransforms.begin();i != otherTransforms.end(); ++i) + { + // negative auras are prefered + if(!IsPositiveSpell((*i)->GetSpellProto()->Id)) + { + handledAura = *i; + break; + } + } + handledAura->ApplyModifier(true); + } + + // Dragonmaw Illusion (restore mount model) + if(GetId()==42016 && m_target->GetMountID()==16314) + { + if(!m_target->GetAurasByType(SPELL_AURA_MOUNTED).empty()) + { + uint32 cr_id = m_target->GetAurasByType(SPELL_AURA_MOUNTED).front()->GetModifier()->m_miscvalue; + if(CreatureInfo const* ci = objmgr.GetCreatureTemplate(cr_id)) + { + uint32 team = 0; + if (m_target->GetTypeId()==TYPEID_PLAYER) + team = ((Player*)m_target)->GetTeam(); + + uint32 display_id = objmgr.ChooseDisplayId(team,ci); + CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id); + if (minfo) + display_id = minfo->modelid; + + m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,display_id); + } + } + } + } +} + +void Aura::HandleForceReaction(bool apply, bool Real) +{ + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + + if(!Real) + return; + + Player* player = (Player*)m_target; + + uint32 faction_id = m_modifier.m_miscvalue; + uint32 faction_rank = m_modifier.m_amount; + + if(apply) + player->m_forcedReactions[faction_id] = ReputationRank(faction_rank); + else + player->m_forcedReactions.erase(faction_id); + + WorldPacket data; + data.Initialize(SMSG_SET_FORCED_REACTIONS, 4+player->m_forcedReactions.size()*(4+4)); + data << uint32(player->m_forcedReactions.size()); + for(ForcedReactions::const_iterator itr = player->m_forcedReactions.begin(); itr != player->m_forcedReactions.end(); ++itr) + { + data << uint32(itr->first); // faction_id (Faction.dbc) + data << uint32(itr->second); // reputation rank + } + player->SendDirectMessage(&data); +} + +void Aura::HandleAuraModSkill(bool apply, bool Real) +{ + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + + uint32 prot=GetSpellProto()->EffectMiscValue[m_effIndex]; + int32 points = GetModifier()->m_amount; + + ((Player*)m_target)->ModifySkillBonus(prot,(apply ? points: -points),m_modifier.m_auraname==SPELL_AURA_MOD_SKILL_TALENT); + if(prot == SKILL_DEFENSE) + ((Player*)m_target)->UpdateDefenseBonusesMod(); +} + +void Aura::HandleChannelDeathItem(bool apply, bool Real) +{ + if(Real && !apply) + { + Unit* caster = GetCaster(); + Unit* victim = GetTarget(); + if(!caster || caster->GetTypeId() != TYPEID_PLAYER || !victim || m_removeMode!=AURA_REMOVE_BY_DEATH) + return; + + SpellEntry const *spellInfo = GetSpellProto(); + if(spellInfo->EffectItemType[m_effIndex] == 0) + return; + + // Soul Shard only from non-grey units + if( spellInfo->EffectItemType[m_effIndex] == 6265 && + (victim->getLevel() <= MaNGOS::XP::GetGrayLevel(caster->getLevel()) || + victim->GetTypeId()==TYPEID_UNIT && !((Player*)caster)->isAllowedToLoot((Creature*)victim)) ) + return; + ItemPosCountVec dest; + uint8 msg = ((Player*)caster)->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, spellInfo->EffectItemType[m_effIndex], 1 ); + if( msg != EQUIP_ERR_OK ) + { + ((Player*)caster)->SendEquipError( msg, NULL, NULL ); + return; + } + + Item* newitem = ((Player*)caster)->StoreNewItem(dest, spellInfo->EffectItemType[m_effIndex], true); + ((Player*)caster)->SendNewItem(newitem, 1, true, false); + } +} + +void Aura::HandleBindSight(bool apply, bool Real) +{ + Unit* caster = GetCaster(); + if(!caster || caster->GetTypeId() != TYPEID_PLAYER) + return; + + caster->SetUInt64Value(PLAYER_FARSIGHT,apply ? m_target->GetGUID() : 0); +} + +void Aura::HandleFarSight(bool apply, bool Real) +{ + Unit* caster = GetCaster(); + if(!caster || caster->GetTypeId() != TYPEID_PLAYER) + return; + + caster->SetUInt64Value(PLAYER_FARSIGHT,apply ? m_modifier.m_miscvalue : 0); +} + +void Aura::HandleAuraTrackCreatures(bool apply, bool Real) +{ + if(m_target->GetTypeId()!=TYPEID_PLAYER) + return; + + if(apply) + m_target->RemoveNoStackAurasDueToAura(this); + m_target->SetUInt32Value(PLAYER_TRACK_CREATURES, apply ? ((uint32)1)<<(m_modifier.m_miscvalue-1) : 0 ); +} + +void Aura::HandleAuraTrackResources(bool apply, bool Real) +{ + if(m_target->GetTypeId()!=TYPEID_PLAYER) + return; + + if(apply) + m_target->RemoveNoStackAurasDueToAura(this); + m_target->SetUInt32Value(PLAYER_TRACK_RESOURCES, apply ? ((uint32)1)<<(m_modifier.m_miscvalue-1): 0 ); +} + +void Aura::HandleAuraTrackStealthed(bool apply, bool Real) +{ + if(m_target->GetTypeId()!=TYPEID_PLAYER) + return; + + if(apply) + m_target->RemoveNoStackAurasDueToAura(this); + + m_target->ApplyModFlag(PLAYER_FIELD_BYTES,PLAYER_FIELD_BYTE_TRACK_STEALTHED,apply); +} + +void Aura::HandleAuraModScale(bool apply, bool Real) +{ + m_target->ApplyPercentModFloatValue(OBJECT_FIELD_SCALE_X,m_modifier.m_amount,apply); +} + +void Aura::HandleModPossess(bool apply, bool Real) +{ + if(!Real) + return; + + if(m_target->getLevel() > m_modifier.m_amount) + return; + + // not possess yourself + if(GetCasterGUID() == m_target->GetGUID()) + return; + + Unit* caster = GetCaster(); + if(!caster) + return; + + if( apply ) + { + m_target->SetCharmerGUID(GetCasterGUID()); + m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,caster->getFaction()); + caster->SetCharm(m_target); + + m_target->CombatStop(); + m_target->DeleteThreatList(); + if(m_target->GetTypeId() == TYPEID_UNIT) + { + m_target->StopMoving(); + m_target->GetMotionMaster()->Clear(); + m_target->GetMotionMaster()->MoveIdle(); + CharmInfo *charmInfo = ((Creature*)m_target)->InitCharmInfo(m_target); + charmInfo->InitPossessCreateSpells(); + } + + if(caster->GetTypeId() == TYPEID_PLAYER) + { + ((Player*)caster)->PossessSpellInitialize(); + } + } + else + { + m_target->SetCharmerGUID(0); + + if(m_target->GetTypeId() == TYPEID_PLAYER) + { + ((Player*)m_target)->setFactionForRace(m_target->getRace()); + } + else if(m_target->GetTypeId() == TYPEID_UNIT) + { + CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo(); + m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A); + } + + caster->SetCharm(0); + + if(caster->GetTypeId() == TYPEID_PLAYER) + { + WorldPacket data(SMSG_PET_SPELLS, 8); + data << uint64(0); + ((Player*)caster)->GetSession()->SendPacket(&data); + } + if(m_target->GetTypeId() == TYPEID_UNIT) + { + ((Creature*)m_target)->AIM_Initialize(); + + if (((Creature*)m_target)->AI()) + ((Creature*)m_target)->AI()->AttackStart(caster); + } + } + if(caster->GetTypeId() == TYPEID_PLAYER) + caster->SetUInt64Value(PLAYER_FARSIGHT,apply ? m_target->GetGUID() : 0); +} + +void Aura::HandleModPossessPet(bool apply, bool Real) +{ + if(!Real) + return; + + Unit* caster = GetCaster(); + if(!caster || caster->GetTypeId() != TYPEID_PLAYER) + return; + if(caster->GetPet() != m_target) + return; + + if(apply) + { + caster->SetUInt64Value(PLAYER_FARSIGHT, m_target->GetGUID()); + m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); + } + else + { + caster->SetUInt64Value(PLAYER_FARSIGHT, 0); + m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); + } +} + +void Aura::HandleModCharm(bool apply, bool Real) +{ + if(!Real) + return; + + // not charm yourself + if(GetCasterGUID() == m_target->GetGUID()) + return; + + Unit* caster = GetCaster(); + if(!caster) + return; + + if(int32(m_target->getLevel()) <= m_modifier.m_amount) + { + if( apply ) + { + m_target->SetCharmerGUID(GetCasterGUID()); + m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,caster->getFaction()); + m_target->CastStop(m_target==caster ? GetId() : 0); + caster->SetCharm(m_target); + + m_target->CombatStop(); + m_target->DeleteThreatList(); + + if(m_target->GetTypeId() == TYPEID_UNIT) + { + ((Creature*)m_target)->AIM_Initialize(); + CharmInfo *charmInfo = ((Creature*)m_target)->InitCharmInfo(m_target); + charmInfo->InitCharmCreateSpells(); + charmInfo->SetReactState( REACT_DEFENSIVE ); + + if(caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK) + { + CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo(); + if(cinfo && cinfo->type == CREATURE_TYPE_DEMON) + { + //to prevent client crash + m_target->SetFlag(UNIT_FIELD_BYTES_0, 2048); + //just to enable stat window + charmInfo->SetPetNumber(objmgr.GeneratePetNumber(), true); + //if charmed two demons the same session, the 2nd gets the 1st one's name + m_target->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL)); + } + } + } + + if(caster->GetTypeId() == TYPEID_PLAYER) + { + ((Player*)caster)->CharmSpellInitialize(); + } + } + else + { + m_target->SetCharmerGUID(0); + + if(m_target->GetTypeId() == TYPEID_PLAYER) + { + ((Player*)m_target)->setFactionForRace(m_target->getRace()); + } + else + { + CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo(); + + // restore faction + if(((Creature*)m_target)->isPet()) + { + if(Unit* owner = m_target->GetOwner()) + m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,owner->getFaction()); + else if(cinfo) + m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A); + } + else if(cinfo) // normal creature + m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A); + + // restore UNIT_FIELD_BYTES_0 + if(cinfo && caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK && cinfo->type == CREATURE_TYPE_DEMON) + { + CreatureDataAddon const *cainfo = ((Creature*)m_target)->GetCreatureAddon(); + if(cainfo && cainfo->bytes0 != 0) + m_target->SetUInt32Value(UNIT_FIELD_BYTES_0, cainfo->bytes0); + else + m_target->RemoveFlag(UNIT_FIELD_BYTES_0, 2048); + + if(m_target->GetCharmInfo()) + m_target->GetCharmInfo()->SetPetNumber(0, true); + else + sLog.outError("Aura::HandleModCharm: target="I64FMTD" with typeid=%d has a charm aura but no charm info!", m_target->GetGUID(), m_target->GetTypeId()); + } + } + + caster->SetCharm(0); + + if(caster->GetTypeId() == TYPEID_PLAYER) + { + WorldPacket data(SMSG_PET_SPELLS, 8); + data << uint64(0); + ((Player*)caster)->GetSession()->SendPacket(&data); + } + if(m_target->GetTypeId() == TYPEID_UNIT) + { + ((Creature*)m_target)->AIM_Initialize(); + if (((Creature*)m_target)->AI()) + ((Creature*)m_target)->AI()->AttackStart(caster); + } + } + } +} + +void Aura::HandleModConfuse(bool apply, bool Real) +{ + if(!Real) + return; + + m_target->SetConfused(apply, GetCasterGUID(), GetId()); +} + +void Aura::HandleModFear(bool apply, bool Real) +{ + if (!Real) + return; + + m_target->SetFeared(apply, GetCasterGUID(), GetId()); +} + +void Aura::HandleFeignDeath(bool apply, bool Real) +{ + if(!Real) + return; + + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + + if( apply ) + { + /* + WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9); + data<GetGUID(); + data<SendMessageToSet(&data,true); + */ + // blizz like 2.0.x + m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN6); + // blizz like 2.0.x + m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH); + // blizz like 2.0.x + m_target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD); + + m_target->addUnitState(UNIT_STAT_DIED); + m_target->CombatStop(); + + // prevent interrupt message + if(m_caster_guid==m_target->GetGUID() && m_target->m_currentSpells[CURRENT_GENERIC_SPELL]) + m_target->m_currentSpells[CURRENT_GENERIC_SPELL]->finish(); + m_target->InterruptNonMeleeSpells(true); + m_target->getHostilRefManager().deleteReferences(); + } + else + { + /* + WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9); + data<GetGUID(); + data<SendMessageToSet(&data,true); + */ + // blizz like 2.0.x + m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN6); + // blizz like 2.0.x + m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH); + // blizz like 2.0.x + m_target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD); + + m_target->clearUnitState(UNIT_STAT_DIED); + } +} + +void Aura::HandleAuraModDisarm(bool apply, bool Real) +{ + if(!Real) + return; + + if(!apply && m_target->HasAuraType(SPELL_AURA_MOD_DISARM)) + return; + + // not sure for it's correctness + if(apply) + m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED); + else + m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED); + + // only at real add/remove aura + if (m_target->GetTypeId() != TYPEID_PLAYER) + return; + + // main-hand attack speed already set to special value for feral form already and don't must chnage and reset at remove. + if (((Player *)m_target)->IsInFeralForm()) + return; + + if (apply) + m_target->SetAttackTime(BASE_ATTACK,BASE_ATTACK_TIME); + else + ((Player *)m_target)->SetRegularAttackTime(); + + m_target->UpdateDamagePhysical(BASE_ATTACK); +} + +void Aura::HandleAuraModStun(bool apply, bool Real) +{ + if(!Real) + return; + + if (apply) + { + m_target->addUnitState(UNIT_STAT_STUNDED); + m_target->SetUInt64Value(UNIT_FIELD_TARGET, 0); + + m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE); + m_target->CastStop(m_target->GetGUID() == GetCasterGUID() ? GetId() : 0); + + // Creature specific + if(m_target->GetTypeId() != TYPEID_PLAYER) + ((Creature*)m_target)->StopMoving(); + else + m_target->SetUnitMovementFlags(0); //Clear movement flags + + WorldPacket data(SMSG_FORCE_MOVE_ROOT, 8); + + data.append(m_target->GetPackGUID()); + data << uint32(0); + m_target->SendMessageToSet(&data,true); + } + else + { + // Real remove called after current aura remove from lists, check if other similar auras active + if(m_target->HasAuraType(SPELL_AURA_MOD_STUN)) + return; + + m_target->clearUnitState(UNIT_STAT_STUNDED); + m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE); + + if(!m_target->hasUnitState(UNIT_STAT_ROOT)) // prevent allow move if have also root effect + { + if(m_target->getVictim() && m_target->isAlive()) + m_target->SetUInt64Value(UNIT_FIELD_TARGET,m_target->getVictim()->GetGUID() ); + + WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 8+4); + data.append(m_target->GetPackGUID()); + data << uint32(0); + m_target->SendMessageToSet(&data,true); + } + + // Wyvern Sting + if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_HUNTER && GetSpellProto()->SpellIconID == 1721) + { + Unit* caster = GetCaster(); + if( !caster || caster->GetTypeId()!=TYPEID_PLAYER ) + return; + + uint32 spell_id = 0; + + switch(GetId()) + { + case 19386: spell_id = 24131; break; + case 24132: spell_id = 24134; break; + case 24133: spell_id = 24135; break; + case 27068: spell_id = 27069; break; + default: + sLog.outError("Spell selection called for unexpected original spell %u, new spell for this spell family?",GetId()); + return; + } + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id); + + if(!spellInfo) + return; + + caster->CastSpell(m_target,spellInfo,true,NULL,this); + return; + } + } +} + +void Aura::HandleModStealth(bool apply, bool Real) +{ + if(apply) + { + // drop flag at stealth in bg + if(Real && m_target->GetTypeId()==TYPEID_PLAYER && ((Player*)m_target)->InBattleGround()) + if(BattleGround *bg = ((Player*)m_target)->GetBattleGround()) + bg->EventPlayerDroppedFlag((Player*)m_target); + + // only at real aura add + if(Real) + { + m_target->SetByteValue(UNIT_FIELD_BYTES_1, 2, 0x02); + if(m_target->GetTypeId()==TYPEID_PLAYER) + m_target->SetFlag(PLAYER_FIELD_BYTES2, 0x2000); + + // apply only if not in GM invisibility (and overwrite invisibility state) + if(m_target->GetVisibility()!=VISIBILITY_OFF) + { + m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT); + m_target->SetVisibility(VISIBILITY_GROUP_STEALTH); + } + + // for RACE_NIGHTELF stealth + if(m_target->GetTypeId()==TYPEID_PLAYER && GetId()==20580) + m_target->CastSpell(m_target, 21009, true, NULL, this); + } + } + else + { + // only at real aura remove + if(Real) + { + // for RACE_NIGHTELF stealth + if(m_target->GetTypeId()==TYPEID_PLAYER && GetId()==20580) + m_target->RemoveAurasDueToSpell(21009); + + // if last SPELL_AURA_MOD_STEALTH and no GM invisibility + if(!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH) && m_target->GetVisibility()!=VISIBILITY_OFF) + { + m_target->SetByteValue(UNIT_FIELD_BYTES_1, 2, 0x00); + if(m_target->GetTypeId()==TYPEID_PLAYER) + m_target->RemoveFlag(PLAYER_FIELD_BYTES2, 0x2000); + + // restore invisibility if any + if(m_target->HasAuraType(SPELL_AURA_MOD_INVISIBILITY)) + { + m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT); + m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY); + } + else + m_target->SetVisibility(VISIBILITY_ON); + } + } + } + + // Master of Subtlety + Unit::AuraList const& mDummyAuras = m_target->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i) + { + if ((*i)->GetSpellProto()->SpellIconID == 2114) + { + if (apply) + { + int32 bp = (*i)->GetModifier()->m_amount; + m_target->CastCustomSpell(m_target,31665,&bp,NULL,NULL,true); + } + else + m_target->CastSpell(m_target,31666,true); + break; + } + } +} + +void Aura::HandleInvisibility(bool apply, bool Real) +{ + if(apply) + { + m_target->m_invisibilityMask |= (1 << m_modifier.m_miscvalue); + + if(Real && m_target->GetTypeId()==TYPEID_PLAYER) + { + // apply glow vision + m_target->SetFlag(PLAYER_FIELD_BYTES2,PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW); + + // drop flag at invisible in bg + if(((Player*)m_target)->InBattleGround()) + if(BattleGround *bg = ((Player*)m_target)->GetBattleGround()) + bg->EventPlayerDroppedFlag((Player*)m_target); + } + + // apply only if not in GM invisibility and not stealth + if(m_target->GetVisibility()==VISIBILITY_ON) + { + // Aura not added yet but visibility code expect temporary add aura + m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT); + m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY); + } + } + else + { + // recalculate value at modifier remove (current aura already removed) + m_target->m_invisibilityMask = 0; + Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY); + for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) + m_target->m_invisibilityMask |= (1 << m_modifier.m_miscvalue); + + // only at real aura remove and if not have different invisibility auras. + if(Real && m_target->m_invisibilityMask==0) + { + // remove glow vision + if(m_target->GetTypeId() == TYPEID_PLAYER) + m_target->RemoveFlag(PLAYER_FIELD_BYTES2,PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW); + + // apply only if not in GM invisibility & not stealthed while invisible + if(m_target->GetVisibility()!=VISIBILITY_OFF) + { + // if have stealth aura then already have stealth visibility + if(!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH)) + m_target->SetVisibility(VISIBILITY_ON); + } + } + } +} + +void Aura::HandleInvisibilityDetect(bool apply, bool Real) +{ + if(apply) + { + m_target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue); + } + else + { + // recalculate value at modifier remove (current aura already removed) + m_target->m_detectInvisibilityMask = 0; + Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY_DETECTION); + for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) + m_target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue); + } + if(Real && m_target->GetTypeId()==TYPEID_PLAYER) + ObjectAccessor::UpdateVisibilityForPlayer((Player*)m_target); +} + +void Aura::HandleAuraModRoot(bool apply, bool Real) +{ + // only at real add/remove aura + if(!Real) + return; + + uint32 apply_stat = UNIT_STAT_ROOT; + if (apply) + { + m_target->addUnitState(UNIT_STAT_ROOT); + m_target->SetUInt64Value (UNIT_FIELD_TARGET, 0); + // probably wrong + m_target->SetFlag(UNIT_FIELD_FLAGS,(apply_stat<<16)); + + //Save last orientation + if( m_target->getVictim() ) + m_target->SetOrientation(m_target->GetAngle(m_target->getVictim())); + + if(m_target->GetTypeId() == TYPEID_PLAYER) + { + WorldPacket data(SMSG_FORCE_MOVE_ROOT, 10); + data.append(m_target->GetPackGUID()); + data << (uint32)2; + m_target->SendMessageToSet(&data,true); + + //Clear unit movement flags + m_target->SetUnitMovementFlags(0); + } + else + ((Creature *)m_target)->StopMoving(); + } + else + { + // Real remove called after current aura remove from lists, check if other similar auras active + if(m_target->HasAuraType(SPELL_AURA_MOD_ROOT)) + return; + + m_target->clearUnitState(UNIT_STAT_ROOT); + // probably wrong + m_target->RemoveFlag(UNIT_FIELD_FLAGS,(apply_stat<<16)); + + if(!m_target->hasUnitState(UNIT_STAT_STUNDED)) // prevent allow move if have also stun effect + { + if(m_target->getVictim() && m_target->isAlive()) + m_target->SetUInt64Value (UNIT_FIELD_TARGET,m_target->getVictim()->GetGUID() ); + + if(m_target->GetTypeId() == TYPEID_PLAYER) + { + WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 10); + data.append(m_target->GetPackGUID()); + data << (uint32)2; + m_target->SendMessageToSet(&data,true); + } + } + } +} + +void Aura::HandleAuraModSilence(bool apply, bool Real) +{ + // only at real add/remove aura + if(!Real) + return; + + if(apply) + { + m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED); + // Stop cast only spells vs PreventionType == SPELL_PREVENTION_TYPE_SILENCE + for (uint32 i = CURRENT_MELEE_SPELL; i < CURRENT_MAX_SPELL;i++) + { + Spell* currentSpell = m_target->m_currentSpells[i]; + if (currentSpell && currentSpell->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE) + { + uint32 state = currentSpell->getState(); + // Stop spells on prepere or casting state + if ( state == SPELL_STATE_PREPARING || state == SPELL_STATE_CASTING ) + { + currentSpell->cancel(); + currentSpell->SetDeletable(true); + m_target->m_currentSpells[i] = NULL; + } + } + } + + switch (GetId()) + { + // Arcane Torrent (Energy) + case 25046: + { + Unit * caster = GetCaster(); + if (!caster) + return; + + // Search Mana Tap auras on caster + int32 energy = 0; + Unit::AuraList const& m_dummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraList::const_iterator i = m_dummyAuras.begin(); i != m_dummyAuras.end(); ++i) + if ((*i)->GetId() == 28734) + ++energy; + if (energy) + { + energy *= 10; + caster->CastCustomSpell(caster, 25048, &energy, NULL, NULL, true); + caster->RemoveAurasDueToSpell(28734); + } + } + } + } + else + { + // Real remove called after current aura remove from lists, check if other similar auras active + if(m_target->HasAuraType(SPELL_AURA_MOD_SILENCE)) + return; + + m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED); + } +} + +void Aura::HandleModThreat(bool apply, bool Real) +{ + // only at real add/remove aura + if(!Real) + return; + + if(!m_target->isAlive()) + return; + + Unit* caster = GetCaster(); + + if(!caster || !caster->isAlive()) + return; + + int level_diff = 0; + int multiplier = 0; + switch (GetId()) + { + // Arcane Shroud + case 26400: + level_diff = m_target->getLevel() - 60; + multiplier = 2; + break; + // The Eye of Diminution + case 28862: + level_diff = m_target->getLevel() - 60; + multiplier = 1; + break; + } + if (level_diff > 0) + m_modifier.m_amount += multiplier * level_diff; + + for(int8 x=0;x < MAX_SPELL_SCHOOL;x++) + { + if(m_modifier.m_miscvalue & int32(1<GetTypeId() == TYPEID_PLAYER) + ApplyPercentModFloatVar(m_target->m_threatModifier[x], m_positive ? m_modifier.m_amount : -m_modifier.m_amount, apply); + } + } +} + +void Aura::HandleAuraModTotalThreat(bool apply, bool Real) +{ + // only at real add/remove aura + if(!Real) + return; + + if(!m_target->isAlive() || m_target->GetTypeId()!= TYPEID_PLAYER) + return; + + Unit* caster = GetCaster(); + + if(!caster || !caster->isAlive()) + return; + + float threatMod = 0.0f; + if(apply) + threatMod = float(m_modifier.m_amount); + else + threatMod = float(-m_modifier.m_amount); + + m_target->getHostilRefManager().threatAssist(caster, threatMod); +} + +void Aura::HandleModTaunt(bool apply, bool Real) +{ + // only at real add/remove aura + if(!Real) + return; + + if(!m_target->isAlive() || !m_target->CanHaveThreatList()) + return; + + Unit* caster = GetCaster(); + + if(!caster || !caster->isAlive() || caster->GetTypeId() != TYPEID_PLAYER) + return; + + if(apply) + { + m_target->TauntApply(caster); + } + else + { + // When taunt aura fades out, mob will switch to previous target if current has less than 1.1 * secondthreat + m_target->TauntFadeOut(caster); + } +} + +/*********************************************************/ +/*** MODIFY SPEED ***/ +/*********************************************************/ +void Aura::HandleAuraModIncreaseSpeed(bool apply, bool Real) +{ + // all applied/removed only at real aura add/remove + if(!Real) + return; + + m_target->UpdateSpeed(MOVE_RUN, true); +} + +void Aura::HandleAuraModIncreaseMountedSpeed(bool apply, bool Real) +{ + // all applied/removed only at real aura add/remove + if(!Real) + return; + + m_target->UpdateSpeed(MOVE_RUN, true); +} + +void Aura::HandleAuraModIncreaseFlightSpeed(bool apply, bool Real) +{ + // all applied/removed only at real aura add/remove + if(!Real) + return; + + // Enable Fly mode for flying mounts + if (m_modifier.m_auraname == SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED) + { + WorldPacket data; + if(apply) + data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12); + else + data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 12); + data.append(m_target->GetPackGUID()); + data << uint32(0); // unknown + m_target->SendMessageToSet(&data, true); + + //Players on flying mounts must be immune to polymorph + if (m_target->GetTypeId()==TYPEID_PLAYER) + m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,MECHANIC_POLYMORPH,apply); + + // Dragonmaw Illusion (overwrite mount model, mounted aura already applied) + if( apply && m_target->HasAura(42016,0) && m_target->GetMountID()) + m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314); + } + + m_target->UpdateSpeed(MOVE_FLY, true); +} + +void Aura::HandleAuraModIncreaseSwimSpeed(bool apply, bool Real) +{ + // all applied/removed only at real aura add/remove + if(!Real) + return; + + m_target->UpdateSpeed(MOVE_SWIM, true); +} + +void Aura::HandleAuraModDecreaseSpeed(bool apply, bool Real) +{ + // all applied/removed only at real aura add/remove + if(!Real) + return; + + m_target->UpdateSpeed(MOVE_RUN, true); + m_target->UpdateSpeed(MOVE_SWIM, true); + m_target->UpdateSpeed(MOVE_FLY, true); +} + +void Aura::HandleAuraModUseNormalSpeed(bool apply, bool Real) +{ + // all applied/removed only at real aura add/remove + if(!Real) + return; + + m_target->UpdateSpeed(MOVE_RUN, true); + m_target->UpdateSpeed(MOVE_SWIM, true); + m_target->UpdateSpeed(MOVE_FLY, true); +} + +/*********************************************************/ +/*** IMMUNITY ***/ +/*********************************************************/ + +void Aura::HandleModMechanicImmunity(bool apply, bool Real) +{ + uint32 mechanic = 1 << m_modifier.m_miscvalue; + + //immune movement impairment and loss of control + if(GetId()==42292) + mechanic=IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK; + + if(apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY) + { + Unit::AuraMap& Auras = m_target->GetAuras(); + for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next) + { + next = iter; + ++next; + SpellEntry const *spell = iter->second->GetSpellProto(); + if (!( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) // spells unaffected by invulnerability + && !iter->second->IsPositive() // only remove negative spells + && spell->Id != GetId()) + { + //check for mechanic mask + if(GetSpellMechanicMask(spell, iter->second->GetEffIndex()) & mechanic) + { + m_target->RemoveAurasDueToSpell(spell->Id); + if(Auras.empty()) + break; + else + next = Auras.begin(); + } + } + } + } + + m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,m_modifier.m_miscvalue,apply); + + // special cases + switch(m_modifier.m_miscvalue) + { + case MECHANIC_INVULNERABILITY: + m_target->ModifyAuraState(AURA_STATE_FORBEARANCE,apply); + break; + case MECHANIC_SHIELD: + m_target->ModifyAuraState(AURA_STATE_WEAKENED_SOUL,apply); + break; + } + + // Bestial Wrath + if ( GetSpellProto()->SpellFamilyName == SPELLFAMILY_HUNTER && GetSpellProto()->SpellIconID == 1680) + { + // The Beast Within cast on owner if talent present + if ( Unit* owner = m_target->GetOwner() ) + { + // Search talent + Unit::AuraList const& m_dummyAuras = owner->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraList::const_iterator i = m_dummyAuras.begin(); i != m_dummyAuras.end(); ++i) + { + if ( (*i)->GetSpellProto()->SpellIconID == 2229 ) + { + if (apply) + owner->CastSpell(owner, 34471, true, 0, this); + else + owner->RemoveAurasDueToSpell(34471); + break; + } + } + } + } + + // The Beast Within and Bestial Wrath - immunity + if(GetId() == 19574 || GetId() == 34471) + { + if(apply) + { + m_target->CastSpell(m_target,24395,true); + m_target->CastSpell(m_target,24396,true); + m_target->CastSpell(m_target,24397,true); + m_target->CastSpell(m_target,26592,true); + } + else + { + m_target->RemoveAurasDueToSpell(24395); + m_target->RemoveAurasDueToSpell(24396); + m_target->RemoveAurasDueToSpell(24397); + m_target->RemoveAurasDueToSpell(26592); + } + } +} + +void Aura::HandleAuraModEffectImmunity(bool apply, bool Real) +{ + if(!apply) + { + if(m_target->GetTypeId() == TYPEID_PLAYER) + { + if(((Player*)m_target)->InBattleGround()) + { + BattleGround *bg = ((Player*)m_target)->GetBattleGround(); + if(bg) + { + switch(bg->GetTypeID()) + { + case BATTLEGROUND_AV: + { + break; + } + case BATTLEGROUND_WS: + { + // Warsong Flag, horde // Silverwing Flag, alliance + if(GetId() == 23333 || GetId() == 23335) + bg->EventPlayerDroppedFlag(((Player*)m_target)); + break; + } + case BATTLEGROUND_AB: + { + break; + } + case BATTLEGROUND_EY: + { + if(GetId() == 34976) + bg->EventPlayerDroppedFlag(((Player*)m_target)); + break; + } + } + } + } + } + } + + m_target->ApplySpellImmune(GetId(),IMMUNITY_EFFECT,m_modifier.m_miscvalue,apply); +} + +void Aura::HandleAuraModStateImmunity(bool apply, bool Real) +{ + if(apply && Real && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY) + { + Unit::AuraList const& auraList = m_target->GetAurasByType(AuraType(m_modifier.m_miscvalue)); + for(Unit::AuraList::const_iterator itr = auraList.begin(); itr != auraList.end();) + { + if (auraList.front() != this) // skip itself aura (it already added) + { + m_target->RemoveAurasDueToSpell(auraList.front()->GetId()); + itr = auraList.begin(); + } + else + ++itr; + } + } + + m_target->ApplySpellImmune(GetId(),IMMUNITY_STATE,m_modifier.m_miscvalue,apply); +} + +void Aura::HandleAuraModSchoolImmunity(bool apply, bool Real) +{ + m_target->ApplySpellImmune(GetId(),IMMUNITY_SCHOOL,m_modifier.m_miscvalue,apply); + + if(Real && apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY) + { + if(IsPositiveSpell(GetId())) //Only positive immunity removes auras + { + uint32 school_mask = m_modifier.m_miscvalue; + Unit::AuraMap& Auras = m_target->GetAuras(); + for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next) + { + next = iter; + ++next; + SpellEntry const *spell = iter->second->GetSpellProto(); + if((GetSpellSchoolMask(spell) & school_mask)//Check for school mask + && !( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) //Spells unaffected by invulnerability + && !iter->second->IsPositive() //Don't remove positive spells + && spell->Id != GetId() ) //Don't remove self + { + m_target->RemoveAurasDueToSpell(spell->Id); + if(Auras.empty()) + break; + else + next = Auras.begin(); + } + } + } + } + if( Real && GetSpellProto()->Mechanic == MECHANIC_BANISH ) + { + if( apply ) + m_target->addUnitState(UNIT_STAT_ISOLATED); + else + m_target->clearUnitState(UNIT_STAT_ISOLATED); + } +} + +void Aura::HandleAuraModDmgImmunity(bool apply, bool Real) +{ + m_target->ApplySpellImmune(GetId(),IMMUNITY_DAMAGE,m_modifier.m_miscvalue,apply); +} + +void Aura::HandleAuraModDispelImmunity(bool apply, bool Real) +{ + // all applied/removed only at real aura add/remove + if(!Real) + return; + + m_target->ApplySpellDispelImmunity(m_spellProto, DispelType(m_modifier.m_miscvalue), apply); +} + +void Aura::HandleAuraProcTriggerSpell(bool apply, bool Real) +{ + if(!Real) + return; + + if(apply) + { + // some spell have charges by functionality not have its in spell data + switch (GetId()) + { + case 28200: // Ascendance (Talisman of Ascendance trinket) + m_procCharges = 6; + UpdateAuraCharges(); + break; + default: break; + } + } +} + +void Aura::HandleAuraModStalked(bool apply, bool Real) +{ + // used by spells: Hunter's Mark, Mind Vision, Syndicate Tracker (MURP) DND + if(apply) + m_target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TRACK_UNIT); + else + m_target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TRACK_UNIT); +} + +/*********************************************************/ +/*** PERIODIC ***/ +/*********************************************************/ + +void Aura::HandlePeriodicTriggerSpell(bool apply, bool Real) +{ + if (m_periodicTimer <= 0) + m_periodicTimer += m_modifier.periodictime; + + m_isPeriodic = apply; + m_isTrigger = apply; + + // Curse of the Plaguebringer + if (!apply && m_spellProto->Id == 29213 && m_removeMode!=AURA_REMOVE_BY_DISPEL) + { + // Cast Wrath of the Plaguebringer if not dispelled + m_target->CastSpell(m_target, 29214, true, 0, this); + } +} + +void Aura::HandlePeriodicEnergize(bool apply, bool Real) +{ + if (m_periodicTimer <= 0) + m_periodicTimer += m_modifier.periodictime; + + m_isPeriodic = apply; +} + +void Aura::HandlePeriodicHeal(bool apply, bool Real) +{ + if (m_periodicTimer <= 0) + m_periodicTimer += m_modifier.periodictime; + + m_isPeriodic = apply; + + // only at real apply + if (Real && apply && GetSpellProto()->Mechanic == MECHANIC_BANDAGE) + { + // provided m_target as original caster to prevent apply aura caster selection for this negative buff + m_target->CastSpell(m_target,11196,true,NULL,this,m_target->GetGUID()); + } + + // For prevent double apply bonuses + bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading()); + + if(!loading && apply) + { + switch (m_spellProto->SpellFamilyName) + { + case SPELLFAMILY_DRUID: + { + // Rejuvenation + if(m_spellProto->SpellFamilyFlags & 0x0000000000000010LL) + { + if(Unit* caster = GetCaster()) + { + Unit::AuraList const& classScripts = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + for(Unit::AuraList::const_iterator k = classScripts.begin(); k != classScripts.end(); ++k) + { + int32 tickcount = GetSpellDuration(m_spellProto) / m_spellProto->EffectAmplitude[m_effIndex]; + switch((*k)->GetModifier()->m_miscvalue) + { + case 4953: // Increased Rejuvenation Healing - Harold's Rejuvenating Broach Aura + case 4415: // Increased Rejuvenation Healing - Idol of Rejuvenation Aura + { + m_modifier.m_amount += (*k)->GetModifier()->m_amount / tickcount; + break; + } + } + } + } + } + } + } + } +} + +void Aura::HandlePeriodicDamage(bool apply, bool Real) +{ + // spells required only Real aura add/remove + if(!Real) + return; + + if (m_periodicTimer <= 0) + m_periodicTimer += m_modifier.periodictime; + + m_isPeriodic = apply; + + // For prevent double apply bonuses + bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading()); + + Unit *caster = GetCaster(); + + switch (m_spellProto->SpellFamilyName) + { + case SPELLFAMILY_GENERIC: + { + // Pounce Bleed + if ( m_spellProto->SpellIconID == 147 && m_spellProto->SpellVisual == 0 ) + { + // $AP*0.18/6 bonus per tick + if (apply && !loading && caster) + m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 100); + return; + } + break; + } + case SPELLFAMILY_WARRIOR: + { + // Rend + if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL) + { + // 0.00743*(($MWB+$mwb)/2+$AP/14*$MWS) bonus per tick + if (apply && !loading && caster) + { + float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK); + int32 mws = caster->GetAttackTime(BASE_ATTACK); + float mwb_min = caster->GetWeaponDamageRange(BASE_ATTACK,MINDAMAGE); + float mwb_max = caster->GetWeaponDamageRange(BASE_ATTACK,MAXDAMAGE); + // WARNING! in 3.0 multipler 0.00743f change to 0.6 + m_modifier.m_amount+=int32(((mwb_min+mwb_max)/2+ap*mws/14000)*0.00743f); + } + return; + } + break; + } + case SPELLFAMILY_DRUID: + { + // Rake + if (m_spellProto->SpellFamilyFlags & 0x0000000000001000LL) + { + // $AP*0.06/3 bonus per tick + if (apply && !loading && caster) + m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 2 / 100); + return; + } + // Lacerate + if (m_spellProto->SpellFamilyFlags & 0x000000010000000000LL) + { + // $AP*0.05/5 bonus per tick + if (apply && !loading && caster) + m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100); + return; + } + // Rip + if (m_spellProto->SpellFamilyFlags & 0x000000000000800000LL) + { + // $AP * min(0.06*$cp, 0.24)/6 [Yes, there is no difference, wheather 4 or 5 CPs are being used] + if (apply && !loading && caster && caster->GetTypeId() == TYPEID_PLAYER) + { + uint8 cp = ((Player*)caster)->GetComboPoints(); + + // Idol of Feral Shadows. Cant be handled as SpellMod in SpellAura:Dummy due its dependency from CPs + Unit::AuraList const& dummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraList::const_iterator itr = dummyAuras.begin(); itr != dummyAuras.end(); ++itr) + { + if((*itr)->GetId()==34241) + { + m_modifier.m_amount += cp * (*itr)->GetModifier()->m_amount; + break; + } + } + + if (cp > 4) cp = 4; + m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100); + } + return; + } + break; + } + case SPELLFAMILY_ROGUE: + { + // Deadly poison aura state + if((m_spellProto->SpellFamilyFlags & 0x10000) && m_spellProto->SpellVisual==5100) + { + if(apply) + m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON,true); + else + { + // current aura already removed, search present of another + bool found = false; + Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); + for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) + { + SpellEntry const* itr_spell = (*itr)->GetSpellProto(); + if(itr_spell && itr_spell->SpellFamilyName==SPELLFAMILY_ROGUE && (itr_spell->SpellFamilyFlags & 0x10000) && itr_spell->SpellVisual==5100) + { + found = true; + break; + } + } + // this has been last deadly poison aura + if(!found) + m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON,false); + } + return; + } + // Rupture + if (m_spellProto->SpellFamilyFlags & 0x000000000000100000LL) + { + // Dmg/tick = $AP*min(0.01*$cp, 0.03) [Like Rip: only the first three CP inrease the contribution from AP] + if (apply && !loading && caster && caster->GetTypeId() == TYPEID_PLAYER) + { + uint8 cp = ((Player*)caster)->GetComboPoints(); + if (cp > 3) cp = 3; + m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100); + } + return; + } + // Garrote + if (m_spellProto->SpellFamilyFlags & 0x000000000000000100LL) + { + // $AP*0.18/6 bonus per tick + if (apply && !loading && caster) + m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 100); + return; + } + break; + } + case SPELLFAMILY_HUNTER: + { + // Serpent Sting + if (m_spellProto->SpellFamilyFlags & 0x0000000000004000LL) + { + // $RAP*0.1/5 bonus per tick + if (apply && !loading && caster) + m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500); + return; + } + // Immolation Trap + if (m_spellProto->SpellFamilyFlags & 0x0000000000000004LL && m_spellProto->SpellIconID == 678) + { + // $RAP*0.1/5 bonus per tick + if (apply && !loading && caster) + m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500); + return; + } + break; + } + case SPELLFAMILY_PALADIN: + { + // Consecration + if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL) + { + if (apply && !loading) + { + if(Unit* caster = GetCaster()) + { + Unit::AuraList const& classScripts = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + for(Unit::AuraList::const_iterator k = classScripts.begin(); k != classScripts.end(); ++k) + { + int32 tickcount = GetSpellDuration(m_spellProto) / m_spellProto->EffectAmplitude[m_effIndex]; + switch((*k)->GetModifier()->m_miscvalue) + { + case 5147: // Improved Consecration - Libram of the Eternal Rest + { + m_modifier.m_amount += (*k)->GetModifier()->m_amount / tickcount; + break; + } + } + } + } + } + return; + } + break; + } + default: + break; + } +} + +void Aura::HandlePeriodicDamagePCT(bool apply, bool Real) +{ + if (m_periodicTimer <= 0) + m_periodicTimer += m_modifier.periodictime; + + m_isPeriodic = apply; +} + +void Aura::HandlePeriodicLeech(bool apply, bool Real) +{ + if (m_periodicTimer <= 0) + m_periodicTimer += m_modifier.periodictime; + + m_isPeriodic = apply; +} + +void Aura::HandlePeriodicManaLeech(bool apply, bool Real) +{ + if (m_periodicTimer <= 0) + m_periodicTimer += m_modifier.periodictime; + + m_isPeriodic = apply; +} + +/*********************************************************/ +/*** MODIFY STATS ***/ +/*********************************************************/ + +/********************************/ +/*** RESISTANCE ***/ +/********************************/ + +void Aura::HandleAuraModResistanceExclusive(bool apply, bool Real) +{ + for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++) + { + if(m_modifier.m_miscvalue & int32(1<HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_VALUE, float(m_modifier.m_amount), apply); + if(m_target->GetTypeId() == TYPEID_PLAYER) + m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,m_modifier.m_amount, apply); + } + } +} + +void Aura::HandleAuraModResistance(bool apply, bool Real) +{ + for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++) + { + if(m_modifier.m_miscvalue & int32(1<HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(m_modifier.m_amount), apply); + if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet()) + m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,m_modifier.m_amount, apply); + } + } + + // Faerie Fire (druid versions) + if( m_spellProto->SpellIconID == 109 && + m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && + m_spellProto->SpellFamilyFlags & 0x0000000000000400LL ) + { + m_target->ModifyAuraState(AURA_STATE_FAERIE_FIRE,apply); + } +} + +void Aura::HandleAuraModBaseResistancePCT(bool apply, bool Real) +{ + // only players have base stats + if(m_target->GetTypeId() != TYPEID_PLAYER) + { + //pets only have base armor + if(((Creature*)m_target)->isPet() && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL)) + { + m_target->HandleStatModifier(UNIT_MOD_ARMOR, BASE_PCT, float(m_modifier.m_amount), apply); + } + } + else + { + for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++) + { + if(m_modifier.m_miscvalue & int32(1<HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, float(m_modifier.m_amount), apply); + } + } + } +} + +void Aura::HandleModResistancePercent(bool apply, bool Real) +{ + for(int8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++) + { + if(m_modifier.m_miscvalue & int32(1<HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(m_modifier.m_amount), apply); + if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet()) + { + m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),true,m_modifier.m_amount, apply); + m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),false,m_modifier.m_amount, apply); + } + } + } +} + +void Aura::HandleModBaseResistance(bool apply, bool Real) +{ + // only players have base stats + if(m_target->GetTypeId() != TYPEID_PLAYER) + { + //only pets have base stats + if(((Creature*)m_target)->isPet() && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL)) + m_target->HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(m_modifier.m_amount), apply); + } + else + { + for(int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++) + if(m_modifier.m_miscvalue & (1<HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_VALUE, float(m_modifier.m_amount), apply); + } +} + +/********************************/ +/*** STAT ***/ +/********************************/ + +void Aura::HandleAuraModStat(bool apply, bool Real) +{ + if (m_modifier.m_miscvalue < -2 || m_modifier.m_miscvalue > 4) + { + sLog.outError("WARNING: Spell %u effect %u have unsupported misc value (%i) for SPELL_AURA_MOD_STAT ",GetId(),GetEffIndex(),m_modifier.m_miscvalue); + return; + } + + for(int32 i = STAT_STRENGTH; i < MAX_STATS; i++) + { + // -1 or -2 is all stats ( misc < -2 checked in function beginning ) + if (m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue == i) + { + //m_target->ApplyStatMod(Stats(i), m_modifier.m_amount,apply); + m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(m_modifier.m_amount), apply); + if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet()) + m_target->ApplyStatBuffMod(Stats(i),m_modifier.m_amount,apply); + } + } +} + +void Aura::HandleModPercentStat(bool apply, bool Real) +{ + if (m_modifier.m_miscvalue < -1 || m_modifier.m_miscvalue > 4) + { + sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid"); + return; + } + + // only players have base stats + if (m_target->GetTypeId() != TYPEID_PLAYER) + return; + + for (int32 i = STAT_STRENGTH; i < MAX_STATS; ++i) + { + if(m_modifier.m_miscvalue == i || m_modifier.m_miscvalue == -1) + { + m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(m_modifier.m_amount), apply); + } + } +} + +void Aura::HandleModSpellDamagePercentFromStat(bool apply, bool Real) +{ + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + + // Magic damage modifiers implemented in Unit::SpellDamageBonus + // This information for client side use only + // Recalculate bonus + ((Player*)m_target)->UpdateSpellDamageAndHealingBonus(); +} + +void Aura::HandleModSpellHealingPercentFromStat(bool apply, bool Real) +{ + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + + // Recalculate bonus + ((Player*)m_target)->UpdateSpellDamageAndHealingBonus(); +} + +void Aura::HandleAuraModDispelResist(bool apply, bool Real) +{ + if(!Real || !apply) + return; + + if(GetId()==33206) + m_target->CastSpell(m_target,44416,true,NULL,this,GetCasterGUID()); +} + +void Aura::HandleModSpellDamagePercentFromAttackPower(bool apply, bool Real) +{ + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + + // Magic damage modifiers implemented in Unit::SpellDamageBonus + // This information for client side use only + // Recalculate bonus + ((Player*)m_target)->UpdateSpellDamageAndHealingBonus(); +} + +void Aura::HandleModSpellHealingPercentFromAttackPower(bool apply, bool Real) +{ + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + + // Recalculate bonus + ((Player*)m_target)->UpdateSpellDamageAndHealingBonus(); +} + +void Aura::HandleModHealingDone(bool apply, bool Real) +{ + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + // implemented in Unit::SpellHealingBonus + // this information is for client side only + ((Player*)m_target)->UpdateSpellDamageAndHealingBonus(); +} + +void Aura::HandleModTotalPercentStat(bool apply, bool Real) +{ + if (m_modifier.m_miscvalue < -1 || m_modifier.m_miscvalue > 4) + { + sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid"); + return; + } + + //save current and max HP before applying aura + uint32 curHPValue = m_target->GetHealth(); + uint32 maxHPValue = m_target->GetMaxHealth(); + + for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++) + { + if(m_modifier.m_miscvalue == i || m_modifier.m_miscvalue == -1) + { + m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(m_modifier.m_amount), apply); + if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet()) + m_target->ApplyStatPercentBuffMod(Stats(i), m_modifier.m_amount, apply ); + } + } + + //recalculate current HP/MP after applying aura modifications (only for spells with 0x10 flag) + if ((m_modifier.m_miscvalue == STAT_STAMINA) && (maxHPValue > 0) && (m_spellProto->Attributes & 0x10)) + { + // newHP = (curHP / maxHP) * newMaxHP = (newMaxHP * curHP) / maxHP -> which is better because no int -> double -> int conversion is needed + uint32 newHPValue = (m_target->GetMaxHealth() * curHPValue) / maxHPValue; + m_target->SetHealth(newHPValue); + } +} + +void Aura::HandleAuraModResistenceOfStatPercent(bool apply, bool Real) +{ + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + + if(m_modifier.m_miscvalue != SPELL_SCHOOL_MASK_NORMAL) + { + // support required adding replace UpdateArmor by loop by UpdateResistence at intelect update + // and include in UpdateResistence same code as in UpdateArmor for aura mod apply. + sLog.outError("Aura SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT(182) need adding support for non-armor resistences!"); + return; + } + + // Recalculate Armor + m_target->UpdateArmor(); +} + +/********************************/ +/*** HEAL & ENERGIZE ***/ +/********************************/ +void Aura::HandleAuraModTotalHealthPercentRegen(bool apply, bool Real) +{ + /* + Need additional checking for auras who reduce or increase healing, magic effect like Dumpen Magic, + so this aura not fully working. + */ + if(apply) + { + if(!m_target->isAlive()) + return; + + if((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && !m_target->IsSitState()) + m_target->SetStandState(PLAYER_STATE_SIT); + + if(m_periodicTimer <= 0) + { + m_periodicTimer += m_modifier.periodictime; + + if(m_target->GetHealth() < m_target->GetMaxHealth()) + { + // PeriodicTick can cast triggered spells with stats changes + PeriodicTick(); + } + } + } + + m_isPeriodic = apply; +} + +void Aura::HandleAuraModTotalManaPercentRegen(bool apply, bool Real) +{ + if((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && apply && !m_target->IsSitState()) + m_target->SetStandState(PLAYER_STATE_SIT); + if(apply) + { + if(m_modifier.periodictime == 0) + m_modifier.periodictime = 1000; + if(m_periodicTimer <= 0 && m_target->getPowerType() == POWER_MANA) + { + m_periodicTimer += m_modifier.periodictime; + + if(m_target->GetPower(POWER_MANA) < m_target->GetMaxPower(POWER_MANA)) + { + // PeriodicTick can cast triggered spells with stats changes + PeriodicTick(); + } + } + } + + m_isPeriodic = apply; +} + +void Aura::HandleModRegen(bool apply, bool Real) // eating +{ + if(apply) + { + if(!m_target->isAlive()) + return; + + if ((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && !m_target->IsSitState()) + m_target->SetStandState(PLAYER_STATE_SIT); + + if(m_periodicTimer <= 0) + { + m_periodicTimer += 5000; + int32 gain = m_target->ModifyHealth(m_modifier.m_amount); + Unit *caster = GetCaster(); + if (caster) + { + SpellEntry const *spellProto = GetSpellProto(); + if (spellProto) + m_target->getHostilRefManager().threatAssist(caster, float(gain) * 0.5f, spellProto); + } + } + } + + m_isPeriodic = apply; +} + +void Aura::HandleModPowerRegen(bool apply, bool Real) // drinking +{ + if ((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && apply && !m_target->IsSitState()) + m_target->SetStandState(PLAYER_STATE_SIT); + + if(apply && m_periodicTimer <= 0) + { + m_periodicTimer += 2000; + + Powers pt = m_target->getPowerType(); + if(int32(pt) != m_modifier.m_miscvalue) + return; + + if ( GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED ) + { + // eating anim + m_target->HandleEmoteCommand(EMOTE_ONESHOT_EAT); + } + else if( GetId() == 20577 ) + { + // cannibalize anim + m_target->HandleEmoteCommand(398); + } + + // Warrior talent, gain 1 rage every 3 seconds while in combat + if(pt == POWER_RAGE && m_target->isInCombat()) + { + m_target->ModifyPower(pt, m_modifier.m_amount*10/17); + m_periodicTimer += 1000; + } + } + m_isPeriodic = apply; + if (Real && m_target->GetTypeId() == TYPEID_PLAYER && m_modifier.m_miscvalue == POWER_MANA) + ((Player*)m_target)->UpdateManaRegen(); +} + +void Aura::HandleModPowerRegenPCT(bool apply, bool Real) +{ + // spells required only Real aura add/remove + if(!Real) + return; + + if (m_target->GetTypeId() != TYPEID_PLAYER) + return; + + // Update manaregen value + if (m_modifier.m_miscvalue == POWER_MANA) + ((Player*)m_target)->UpdateManaRegen(); +} + +void Aura::HandleModManaRegen(bool apply, bool Real) +{ + // spells required only Real aura add/remove + if(!Real) + return; + + if (m_target->GetTypeId() != TYPEID_PLAYER) + return; + + //Note: an increase in regen does NOT cause threat. + ((Player*)m_target)->UpdateManaRegen(); +} + +void Aura::HandleComprehendLanguage(bool apply, bool Real) +{ + if(apply) + m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_COMPREHEND_LANG); + else + m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_COMPREHEND_LANG); +} + +void Aura::HandleAuraModIncreaseHealth(bool apply, bool Real) +{ + // Special case with temporary increase max/current health + switch(GetId()) + { + case 12976: // Warrior Last Stand triggered spell + case 28726: // Nightmare Seed ( Nightmare Seed ) + case 34511: // Valor (Bulwark of Kings, Bulwark of the Ancient Kings) + case 44055: // Tremendous Fortitude (Battlemaster's Alacrity) + { + if(Real) + { + if(apply) + { + m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply); + m_target->ModifyHealth(m_modifier.m_amount); + } + else + { + if (int32(m_target->GetHealth()) > m_modifier.m_amount) + m_target->ModifyHealth(-m_modifier.m_amount); + else + m_target->SetHealth(1); + m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply); + } + } + return; + } + } + + // generic case + m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply); +} + +void Aura::HandleAuraModIncreaseMaxHealth(bool apply, bool Real) +{ + uint32 oldhealth = m_target->GetHealth(); + double healthPercentage = (double)oldhealth / (double)m_target->GetMaxHealth(); + + m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply); + + // refresh percentage + if(oldhealth > 0) + { + uint32 newhealth = uint32(ceil((double)m_target->GetMaxHealth() * healthPercentage)); + if(newhealth==0) + newhealth = 1; + + m_target->SetHealth(newhealth); + } +} + +void Aura::HandleAuraModIncreaseEnergy(bool apply, bool Real) +{ + Powers powerType = m_target->getPowerType(); + if(int32(powerType) != m_modifier.m_miscvalue) + return; + + m_target->HandleStatModifier(UnitMods(UNIT_MOD_POWER_START + powerType), TOTAL_VALUE, float(m_modifier.m_amount), apply); +} + +void Aura::HandleAuraModIncreaseEnergyPercent(bool apply, bool Real) +{ + Powers powerType = m_target->getPowerType(); + if(int32(powerType) != m_modifier.m_miscvalue) + return; + + m_target->HandleStatModifier(UnitMods(UNIT_MOD_POWER_START + powerType), TOTAL_PCT, float(m_modifier.m_amount), apply); +} + +void Aura::HandleAuraModIncreaseHealthPercent(bool apply, bool Real) +{ + //m_target->ApplyMaxHealthPercentMod(m_modifier.m_amount,apply); + m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(m_modifier.m_amount), apply); +} + +/********************************/ +/*** FIGHT ***/ +/********************************/ + +void Aura::HandleAuraModParryPercent(bool apply, bool Real) +{ + if(m_target->GetTypeId()!=TYPEID_PLAYER) + return; + + ((Player*)m_target)->UpdateParryPercentage(); +} + +void Aura::HandleAuraModDodgePercent(bool apply, bool Real) +{ + if(m_target->GetTypeId()!=TYPEID_PLAYER) + return; + + ((Player*)m_target)->UpdateDodgePercentage(); + //sLog.outError("BONUS DODGE CHANCE: + %f", float(m_modifier.m_amount)); +} + +void Aura::HandleAuraModBlockPercent(bool apply, bool Real) +{ + if(m_target->GetTypeId()!=TYPEID_PLAYER) + return; + + ((Player*)m_target)->UpdateBlockPercentage(); + //sLog.outError("BONUS BLOCK CHANCE: + %f", float(m_modifier.m_amount)); +} + +void Aura::HandleAuraModRegenInterrupt(bool apply, bool Real) +{ + // spells required only Real aura add/remove + if(!Real) + return; + + if(m_target->GetTypeId()!=TYPEID_PLAYER) + return; + + ((Player*)m_target)->UpdateManaRegen(); +} + +void Aura::HandleAuraModCritPercent(bool apply, bool Real) +{ + if(m_target->GetTypeId()!=TYPEID_PLAYER) + return; + + // apply item specific bonuses for already equipped weapon + if(Real) + { + for(int i = 0; i < MAX_ATTACK; ++i) + if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i))) + ((Player*)m_target)->_ApplyWeaponDependentAuraCritMod(pItem,WeaponAttackType(i),this,apply); + } + + // mods must be applied base at equipped weapon class and subclass comparison + // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask + // m_modifier.m_miscvalue comparison with item generated damage types + + if (GetSpellProto()->EquippedItemClass == -1) + { + ((Player*)m_target)->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply); + ((Player*)m_target)->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply); + ((Player*)m_target)->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply); + } + else + { + // done in Player::_ApplyWeaponDependentAuraMods + } +} + +void Aura::HandleModHitChance(bool apply, bool Real) +{ + m_target->m_modMeleeHitChance += apply ? m_modifier.m_amount : (-m_modifier.m_amount); + m_target->m_modRangedHitChance += apply ? m_modifier.m_amount : (-m_modifier.m_amount); +} + +void Aura::HandleModSpellHitChance(bool apply, bool Real) +{ + m_target->m_modSpellHitChance += apply ? m_modifier.m_amount: (-m_modifier.m_amount); +} + +void Aura::HandleModSpellCritChance(bool apply, bool Real) +{ + // spells required only Real aura add/remove + if(!Real) + return; + + if(m_target->GetTypeId() == TYPEID_PLAYER) + { + ((Player*)m_target)->UpdateAllSpellCritChances(); + } + else + { + m_target->m_baseSpellCritChance += apply ? m_modifier.m_amount:(-m_modifier.m_amount); + } +} + +void Aura::HandleModSpellCritChanceShool(bool apply, bool Real) +{ + // spells required only Real aura add/remove + if(!Real) + return; + + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + + for(int school = SPELL_SCHOOL_NORMAL; school < MAX_SPELL_SCHOOL; ++school) + if (m_modifier.m_miscvalue & (1<UpdateSpellCritChance(school); +} + +/********************************/ +/*** ATTACK SPEED ***/ +/********************************/ + +void Aura::HandleModCastingSpeed(bool apply, bool Real) +{ + m_target->ApplyCastTimePercentMod(m_modifier.m_amount,apply); +} + +void Aura::HandleModMeleeRangedSpeedPct(bool apply, bool Real) +{ + m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply); + m_target->ApplyAttackTimePercentMod(OFF_ATTACK,m_modifier.m_amount,apply); + m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply); +} + +void Aura::HandleModCombatSpeedPct(bool apply, bool Real) +{ + m_target->ApplyCastTimePercentMod(m_modifier.m_amount,apply); + m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply); + m_target->ApplyAttackTimePercentMod(OFF_ATTACK,m_modifier.m_amount,apply); + m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply); +} + +void Aura::HandleModAttackSpeed(bool apply, bool Real) +{ + if(!m_target->isAlive() ) + return; + + m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply); +} + +void Aura::HandleHaste(bool apply, bool Real) +{ + m_target->ApplyAttackTimePercentMod(BASE_ATTACK, m_modifier.m_amount,apply); + m_target->ApplyAttackTimePercentMod(OFF_ATTACK, m_modifier.m_amount,apply); + m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,m_modifier.m_amount,apply); +} + +void Aura::HandleAuraModRangedHaste(bool apply, bool Real) +{ + m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply); +} + +void Aura::HandleRangedAmmoHaste(bool apply, bool Real) +{ + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,m_modifier.m_amount, apply); +} + +/********************************/ +/*** ATTACK POWER ***/ +/********************************/ + +void Aura::HandleAuraModAttackPower(bool apply, bool Real) +{ + m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(m_modifier.m_amount), apply); +} + +void Aura::HandleAuraModRangedAttackPower(bool apply, bool Real) +{ + if((m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0) + return; + + m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(m_modifier.m_amount), apply); +} + +void Aura::HandleAuraAttackPowerAttacker(bool apply, bool Real) +{ + // spells required only Real aura add/remove + if(!Real) + return; + Unit *caster = GetCaster(); + + if (!caster) + return; + + // Hunter's Mark + if (m_spellProto->SpellFamilyName == SPELLFAMILY_HUNTER && m_spellProto->SpellFamilyFlags & 0x0000000000000400LL) + { + // Check Improved Hunter's Mark bonus on caster + Unit::AuraList const& mOverrideClassScript = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + for(Unit::AuraList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i) + { + Modifier* mod = (*i)->GetModifier(); + // mproved Hunter's Mark script from 5236 to 5240 + if (mod->m_miscvalue >= 5236 && mod->m_miscvalue <= 5240) + { + // Get amount of ranged bonus for this spell.. + int32 ranged_bonus = caster->CalculateSpellDamage(m_spellProto, 1, m_spellProto->EffectBasePoints[1], m_target); + // Set melee attack power bonus % from ranged depends from Improved mask aura + m_modifier.m_amount = mod->m_amount * ranged_bonus / 100; + m_currentBasePoints = m_modifier.m_amount; + break; + } + } + return; + } +} + +void Aura::HandleAuraModAttackPowerPercent(bool apply, bool Real) +{ + //UNIT_FIELD_ATTACK_POWER_MULTIPLIER = multiplier - 1 + m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, float(m_modifier.m_amount), apply); +} + +void Aura::HandleAuraModRangedAttackPowerPercent(bool apply, bool Real) +{ + if((m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0) + return; + + //UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = multiplier - 1 + m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(m_modifier.m_amount), apply); +} + +void Aura::HandleAuraModRangedAttackPowerOfStatPercent(bool apply, bool Real) +{ + // spells required only Real aura add/remove + if(!Real) + return; + + if(m_target->GetTypeId() == TYPEID_PLAYER && (m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0) + return; + + if(m_modifier.m_miscvalue != STAT_INTELLECT) + { + // support required adding UpdateAttackPowerAndDamage calls at stat update + sLog.outError("Aura SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT (212) need support non-intelect stats!"); + return; + } + + // Recalculate bonus + ((Player*)m_target)->UpdateAttackPowerAndDamage(true); +} + +/********************************/ +/*** DAMAGE BONUS ***/ +/********************************/ +void Aura::HandleModDamageDone(bool apply, bool Real) +{ + // apply item specific bonuses for already equipped weapon + if(Real && m_target->GetTypeId()==TYPEID_PLAYER) + { + for(int i = 0; i < MAX_ATTACK; ++i) + if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i))) + ((Player*)m_target)->_ApplyWeaponDependentAuraDamageMod(pItem,WeaponAttackType(i),this,apply); + } + + // m_modifier.m_miscvalue is bitmask of spell schools + // 1 ( 0-bit ) - normal school damage (SPELL_SCHOOL_MASK_NORMAL) + // 126 - full bitmask all magic damages (SPELL_SCHOOL_MASK_MAGIC) including wands + // 127 - full bitmask any damages + // + // mods must be applied base at equipped weapon class and subclass comparison + // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask + // m_modifier.m_miscvalue comparison with item generated damage types + + if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) != 0) + { + // apply generic physical damage bonuses including wand case + if (GetSpellProto()->EquippedItemClass == -1 || m_target->GetTypeId() != TYPEID_PLAYER) + { + m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(m_modifier.m_amount), apply); + m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(m_modifier.m_amount), apply); + m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(m_modifier.m_amount), apply); + } + else + { + // done in Player::_ApplyWeaponDependentAuraMods + } + + if(m_target->GetTypeId() == TYPEID_PLAYER) + { + if(m_positive) + m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS,m_modifier.m_amount,apply); + else + m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG,m_modifier.m_amount,apply); + } + } + + // Skip non magic case for speedup + if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_MAGIC) == 0) + return; + + if( GetSpellProto()->EquippedItemClass != -1 || GetSpellProto()->EquippedItemInventoryTypeMask != 0 ) + { + // wand magic case (skip generic to all item spell bonuses) + // done in Player::_ApplyWeaponDependentAuraMods + + // Skip item specific requirements for not wand magic damage + return; + } + + // Magic damage modifiers implemented in Unit::SpellDamageBonus + // This information for client side use only + if(m_target->GetTypeId() == TYPEID_PLAYER) + { + if(m_positive) + { + for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++) + { + if((m_modifier.m_miscvalue & (1<ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i,m_modifier.m_amount,apply); + } + } + else + { + for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++) + { + if((m_modifier.m_miscvalue & (1<ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG+i,m_modifier.m_amount,apply); + } + } + Pet* pet = m_target->GetPet(); + if(pet) + pet->UpdateAttackPowerAndDamage(); + } +} + +void Aura::HandleModDamagePercentDone(bool apply, bool Real) +{ + sLog.outDebug("AURA MOD DAMAGE type:%u negative:%u", m_modifier.m_miscvalue, m_positive ? 0 : 1); + + // apply item specific bonuses for already equipped weapon + if(Real && m_target->GetTypeId()==TYPEID_PLAYER) + { + for(int i = 0; i < MAX_ATTACK; ++i) + if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i))) + ((Player*)m_target)->_ApplyWeaponDependentAuraDamageMod(pItem,WeaponAttackType(i),this,apply); + } + + // m_modifier.m_miscvalue is bitmask of spell schools + // 1 ( 0-bit ) - normal school damage (SPELL_SCHOOL_MASK_NORMAL) + // 126 - full bitmask all magic damages (SPELL_SCHOOL_MASK_MAGIC) including wand + // 127 - full bitmask any damages + // + // mods must be applied base at equipped weapon class and subclass comparison + // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask + // m_modifier.m_miscvalue comparison with item generated damage types + + if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) != 0) + { + // apply generic physical damage bonuses including wand case + if (GetSpellProto()->EquippedItemClass == -1 || m_target->GetTypeId() != TYPEID_PLAYER) + { + m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(m_modifier.m_amount), apply); + m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(m_modifier.m_amount), apply); + m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(m_modifier.m_amount), apply); + } + else + { + // done in Player::_ApplyWeaponDependentAuraMods + } + // For show in client + if(m_target->GetTypeId() == TYPEID_PLAYER) + m_target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT,m_modifier.m_amount/100.0f,apply); + } + + // Skip non magic case for speedup + if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_MAGIC) == 0) + return; + + if( GetSpellProto()->EquippedItemClass != -1 || GetSpellProto()->EquippedItemInventoryTypeMask != 0 ) + { + // wand magic case (skip generic to all item spell bonuses) + // done in Player::_ApplyWeaponDependentAuraMods + + // Skip item specific requirements for not wand magic damage + return; + } + + // Magic damage percent modifiers implemented in Unit::SpellDamageBonus + // Send info to client + if(m_target->GetTypeId() == TYPEID_PLAYER) + for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i) + m_target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT+i,m_modifier.m_amount/100.0f,apply); +} + +void Aura::HandleModOffhandDamagePercent(bool apply, bool Real) +{ + // spells required only Real aura add/remove + if(!Real) + return; + + sLog.outDebug("AURA MOD OFFHAND DAMAGE"); + + m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(m_modifier.m_amount), apply); +} + +/********************************/ +/*** POWER COST ***/ +/********************************/ + +void Aura::HandleModPowerCostPCT(bool apply, bool Real) +{ + // spells required only Real aura add/remove + if(!Real) + return; + + float amount = m_modifier.m_amount/100.0f; + for(int i = 0; i < MAX_SPELL_SCHOOL; ++i) + if(m_modifier.m_miscvalue & (1<ApplyModSignedFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER+i,amount,apply); +} + +void Aura::HandleModPowerCost(bool apply, bool Real) +{ + // spells required only Real aura add/remove + if(!Real) + return; + + for(int i = 0; i < MAX_SPELL_SCHOOL; ++i) + if(m_modifier.m_miscvalue & (1<ApplyModInt32Value(UNIT_FIELD_POWER_COST_MODIFIER+i,m_modifier.m_amount,apply); +} + +/*********************************************************/ +/*** OTHERS ***/ +/*********************************************************/ + +void Aura::HandleShapeshiftBoosts(bool apply) +{ + uint32 spellId = 0; + uint32 spellId2 = 0; + uint32 HotWSpellId = 0; + + switch(GetModifier()->m_miscvalue) + { + case FORM_CAT: + spellId = 3025; + HotWSpellId = 24900; + break; + case FORM_TREE: + spellId = 5420; + break; + case FORM_TRAVEL: + spellId = 5419; + break; + case FORM_AQUA: + spellId = 5421; + break; + case FORM_BEAR: + spellId = 1178; + spellId2 = 21178; + HotWSpellId = 24899; + break; + case FORM_DIREBEAR: + spellId = 9635; + spellId2 = 21178; + HotWSpellId = 24899; + break; + case FORM_BATTLESTANCE: + spellId = 21156; + break; + case FORM_DEFENSIVESTANCE: + spellId = 7376; + break; + case FORM_BERSERKERSTANCE: + spellId = 7381; + break; + case FORM_MOONKIN: + spellId = 24905; + // aura from effect trigger spell + spellId2 = 24907; + break; + case FORM_FLIGHT: + spellId = 33948; + break; + case FORM_FLIGHT_EPIC: + spellId = 40122; + spellId2 = 40121; + break; + case FORM_SPIRITOFREDEMPTION: + spellId = 27792; + spellId2 = 27795; // must be second, this important at aura remove to prevent to early iterator invalidation. + break; + case FORM_GHOSTWOLF: + case FORM_AMBIENT: + case FORM_GHOUL: + case FORM_SHADOW: + case FORM_STEALTH: + case FORM_CREATURECAT: + case FORM_CREATUREBEAR: + spellId = 0; + break; + } + + uint32 form = GetModifier()->m_miscvalue-1; + + if(apply) + { + if (spellId) m_target->CastSpell(m_target, spellId, true, NULL, this ); + if (spellId2) m_target->CastSpell(m_target, spellId2, true, NULL, this); + + if(m_target->GetTypeId() == TYPEID_PLAYER) + { + const PlayerSpellMap& sp_list = ((Player *)m_target)->GetSpellMap(); + for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr) + { + if(itr->second->state == PLAYERSPELL_REMOVED) continue; + if(itr->first==spellId || itr->first==spellId2) continue; + SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first); + if (!spellInfo || !(spellInfo->Attributes & ((1<<6) | (1<<7)))) continue; + if (spellInfo->Stances & (1<CastSpell(m_target, itr->first, true, NULL, this); + } + //LotP + if (((Player*)m_target)->HasSpell(17007)) + { + SpellEntry const *spellInfo = sSpellStore.LookupEntry(24932); + if (spellInfo && spellInfo->Stances & (1<CastSpell(m_target, 24932, true, NULL, this); + } + // HotW + if (HotWSpellId) + { + Unit::AuraList const& mModTotalStatPct = m_target->GetAurasByType(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE); + for(Unit::AuraList::const_iterator i = mModTotalStatPct.begin(); i != mModTotalStatPct.end(); ++i) + { + if ((*i)->GetSpellProto()->SpellIconID == 240 && (*i)->GetModifier()->m_miscvalue == 3) + { + int32 HotWMod = (*i)->GetModifier()->m_amount; + if(GetModifier()->m_miscvalue == FORM_CAT) + HotWMod /= 2; + + m_target->CastCustomSpell(m_target, HotWSpellId, &HotWMod, NULL, NULL, true, NULL, this); + break; + } + } + } + } + } + else + { + m_target->RemoveAurasDueToSpell(spellId); + m_target->RemoveAurasDueToSpell(spellId2); + + Unit::AuraMap& tAuras = m_target->GetAuras(); + for (Unit::AuraMap::iterator itr = tAuras.begin(); itr != tAuras.end();) + { + if (itr->second->IsRemovedOnShapeLost()) + { + m_target->RemoveAurasDueToSpell(itr->second->GetId()); + itr = tAuras.begin(); + } + else + { + ++itr; + } + } + } + + /*double healthPercentage = (double)m_target->GetHealth() / (double)m_target->GetMaxHealth(); + m_target->SetHealth(uint32(ceil((double)m_target->GetMaxHealth() * healthPercentage)));*/ +} + +void Aura::HandleAuraEmpathy(bool apply, bool Real) +{ + if(m_target->GetTypeId() != TYPEID_UNIT) + return; + + CreatureInfo const * ci = objmgr.GetCreatureTemplate(m_target->GetEntry()); + if(ci && ci->type == CREATURE_TYPE_BEAST) + { + m_target->ApplyModUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_SPECIALINFO, apply); + } +} + +void Aura::HandleAuraUntrackable(bool apply, bool Real) +{ + if(apply) + m_target->SetFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_UNTRACKABLE); + else + m_target->RemoveFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_UNTRACKABLE); +} + +void Aura::HandleAuraModPacify(bool apply, bool Real) +{ + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + + if(apply) + m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED); + else + m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED); +} + +void Aura::HandleAuraModPacifyAndSilence(bool apply, bool Real) +{ + HandleAuraModPacify(apply,Real); + HandleAuraModSilence(apply,Real); +} + +void Aura::HandleAuraGhost(bool apply, bool Real) +{ + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + + if(apply) + { + m_target->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST); + } + else + { + m_target->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST); + } +} + +void Aura::HandleAuraAllowFlight(bool apply, bool Real) +{ + // all applied/removed only at real aura add/remove + if(!Real) + return; + + // allow fly + WorldPacket data; + if(apply) + data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12); + else + data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 12); + data.append(m_target->GetPackGUID()); + data << uint32(0); // unk + m_target->SendMessageToSet(&data, true); +} + +void Aura::HandleModRating(bool apply, bool Real) +{ + // spells required only Real aura add/remove + if(!Real) + return; + + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + + for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating) + if (m_modifier.m_miscvalue & (1 << rating)) + ((Player*)m_target)->ApplyRatingMod(CombatRating(rating), m_modifier.m_amount, apply); +} + +void Aura::HandleForceMoveForward(bool apply, bool Real) +{ + if(!Real || m_target->GetTypeId() != TYPEID_PLAYER) + return; + if(apply) + m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FORCE_MOVE); + else + m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FORCE_MOVE); +} + +void Aura::HandleAuraModExpertise(bool apply, bool Real) +{ + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + + ((Player*)m_target)->UpdateExpertise(BASE_ATTACK); + ((Player*)m_target)->UpdateExpertise(OFF_ATTACK); +} + +void Aura::HandleModTargetResistance(bool apply, bool Real) +{ + // spells required only Real aura add/remove + if(!Real) + return; + // applied to damage as HandleNoImmediateEffect in Unit::CalcAbsorbResist and Unit::CalcArmorReducedDamage + + // show armor penetration + if (m_target->GetTypeId() == TYPEID_PLAYER && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL)) + m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE,m_modifier.m_amount, apply); + + // show as spell penetration only full spell penetration bonuses (all resistances except armor and holy + if (m_target->GetTypeId() == TYPEID_PLAYER && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_SPELL)==SPELL_SCHOOL_MASK_SPELL) + m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE,m_modifier.m_amount, apply); +} + +//HandleNoImmediateEffect auras implementation to support new stat system +void Aura::HandleAuraHealing(bool apply, bool Real) +{ + //m_target->HandleStatModifier(UNIT_MOD_HEALING, TOTAL_VALUE, float(m_modifier.m_amount), apply); +} + +void Aura::HandleAuraHealingPct(bool apply, bool Real) +{ + //m_target->HandleStatModifier(UNIT_MOD_HEALING, TOTAL_PCT, float(m_modifier.m_amount), apply); +} + +void Aura::HandleShieldBlockValue(bool apply, bool Real) +{ + BaseModType modType = FLAT_MOD; + if(m_modifier.m_auraname == SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT) + modType = PCT_MOD; + + if(m_target->GetTypeId() == TYPEID_PLAYER) + ((Player*)m_target)->HandleBaseModValue(SHIELD_BLOCK_VALUE, modType, float(m_modifier.m_amount), apply); +} + +void Aura::HandleAuraRetainComboPoints(bool apply, bool Real) +{ + // spells required only Real aura add/remove + if(!Real) + return; + + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + + Player *target = (Player*)m_target; + + // combo points was added in SPELL_EFFECT_ADD_COMBO_POINTS handler + // remove only if aura expire by time (in case combo points amount change aura removed without combo points lost) + if( !apply && m_duration==0 && target->GetComboTarget()) + if(Unit* unit = ObjectAccessor::GetUnit(*m_target,target->GetComboTarget())) + target->AddComboPoints(unit, -m_modifier.m_amount); +} + +void Aura::HandleModUnattackable( bool Apply, bool Real ) +{ + if(Real && Apply) + m_target->CombatStop(); + + m_target->ApplyModFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE,Apply); +} + +void Aura::HandleSpiritOfRedemption( bool apply, bool Real ) +{ + // spells required only Real aura add/remove + if(!Real) + return; + + // prepare spirit state + if(apply) + { + if(m_target->GetTypeId()==TYPEID_PLAYER) + { + // disable breath/etc timers + ((Player*)m_target)->StopMirrorTimers(); + + // set stand state (expected in this form) + if(!m_target->IsStandState()) + m_target->SetStandState(PLAYER_STATE_NONE); + } + + m_target->SetHealth(1); + } + // die at aura end + else + m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, GetSpellProto(), false); +} + +void Aura::CleanupTriggeredSpells() +{ + uint32 tSpellId = m_spellProto->EffectTriggerSpell[GetEffIndex()]; + if(!tSpellId) + return; + + SpellEntry const* tProto = sSpellStore.LookupEntry(tSpellId); + if(!tProto) + return; + + if(GetSpellDuration(tProto) != -1) + return; + + // needed for spell 43680, maybe others + // TODO: is there a spell flag, which can solve this in a more sophisticated way? + if(m_spellProto->EffectApplyAuraName[GetEffIndex()] == SPELL_AURA_PERIODIC_TRIGGER_SPELL && + GetSpellDuration(m_spellProto) == m_spellProto->EffectAmplitude[GetEffIndex()]) + return; + m_target->RemoveAurasDueToSpell(tSpellId); +} + +void Aura::HandleAuraPowerBurn(bool apply, bool Real) +{ + if (m_periodicTimer <= 0) + m_periodicTimer += m_modifier.periodictime; + + m_isPeriodic = apply; +} + +void Aura::HandleSchoolAbsorb(bool apply, bool Real) +{ + if(!Real) + return; + + // prevent double apply bonuses + if(apply && (m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading())) + { + if(Unit* caster = GetCaster()) + { + float DoneActualBenefit = 0.0f; + switch(m_spellProto->SpellFamilyName) + { + case SPELLFAMILY_PRIEST: + if(m_spellProto->SpellFamilyFlags == 0x1) //PW:S + { + //+30% from +healing bonus + DoneActualBenefit = caster->SpellBaseHealingBonus(GetSpellSchoolMask(m_spellProto)) * 0.3f; + break; + } + break; + case SPELLFAMILY_MAGE: + if(m_spellProto->SpellFamilyFlags == 0x80100 || m_spellProto->SpellFamilyFlags == 0x8 || m_spellProto->SpellFamilyFlags == 0x100000000LL) + { + //frost ward, fire ward, ice barrier + //+10% from +spd bonus + DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.1f; + break; + } + break; + case SPELLFAMILY_WARLOCK: + if(m_spellProto->SpellFamilyFlags == 0x00) + { + //shadow ward + //+10% from +spd bonus + DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.1f; + break; + } + break; + default: + break; + } + + DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto()); + + m_modifier.m_amount += (int32)DoneActualBenefit; + } + } +} + +void Aura::PeriodicTick() +{ + if(!m_target->isAlive()) + return; + + switch(m_modifier.m_auraname) + { + case SPELL_AURA_PERIODIC_DAMAGE: + case SPELL_AURA_PERIODIC_DAMAGE_PERCENT: + { + Unit *pCaster = GetCaster(); + if(!pCaster) + return; + + if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA && + pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE) + return; + + // Check for immune (not use charges) + if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto()))) + return; + + // some auras remove at specific health level or more + if(m_modifier.m_auraname==SPELL_AURA_PERIODIC_DAMAGE) + { + switch(GetId()) + { + case 43093: case 31956: case 38801: + case 35321: case 38363: case 39215: + if(m_target->GetHealth() == m_target->GetMaxHealth() ) + { + m_target->RemoveAurasDueToSpell(GetId()); + return; + } + break; + case 38772: + { + uint32 percent = + GetEffIndex() < 2 && GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_DUMMY ? + pCaster->CalculateSpellDamage(GetSpellProto(),GetEffIndex()+1,GetSpellProto()->EffectBasePoints[GetEffIndex()+1],m_target) : + 100; + if(m_target->GetHealth()*100 >= m_target->GetMaxHealth()*percent ) + { + m_target->RemoveAurasDueToSpell(GetId()); + return; + } + break; + } + default: + break; + } + } + + uint32 absorb=0; + uint32 resist=0; + CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL ); + + // ignore non positive values (can be result apply spellmods to aura damage + uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0; + + uint32 pdamage; + + if(m_modifier.m_auraname == SPELL_AURA_PERIODIC_DAMAGE) + { + pdamage = amount; + + // Calculate armor mitigation if it is a physical spell + // But not for bleed mechanic spells + if ( GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL && + GetEffectMechanic(GetSpellProto(), m_effIndex) != MECHANIC_BLEED) + { + uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage); + cleanDamage.damage += pdamage - pdamageReductedArmor; + pdamage = pdamageReductedArmor; + } + + pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),pdamage,DOT); + + // Curse of Agony damage-per-tick calculation + if (GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 0x0000000000000400LL) && GetSpellProto()->SpellIconID==544) + { + // 1..4 ticks, 1/2 from normal tick damage + if (m_duration>=((m_maxduration-m_modifier.periodictime)*2/3)) + pdamage = pdamage/2; + // 9..12 ticks, 3/2 from normal tick damage + else if(m_duration<((m_maxduration-m_modifier.periodictime)/3)) + pdamage += (pdamage+1)/2; // +1 prevent 0.5 damage possible lost at 1..4 ticks + // 5..8 ticks have normal tick damage + } + } + else + pdamage = uint32(m_target->GetMaxHealth()*amount/100); + + //As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit + // Reduce dot damage from resilience for players + if (m_target->GetTypeId()==TYPEID_PLAYER) + pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage); + + pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist); + + sLog.outDetail("PeriodicTick: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u abs is %u", + GetCasterGUID(), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb); + + WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size + data.append(m_target->GetPackGUID()); + data.appendPackGUID(GetCasterGUID()); + data << uint32(GetId()); + data << uint32(1); + data << uint32(m_modifier.m_auraname); + data << (uint32)pdamage; + data << (uint32)GetSpellSchoolMask(GetSpellProto()); // will be mask in 2.4.x + data << (uint32)absorb; + data << (uint32)resist; + m_target->SendMessageToSet(&data,true); + + Unit* target = m_target; // aura can be deleted in DealDamage + SpellEntry const* spellProto = GetSpellProto(); + + pCaster->DealDamage(m_target, (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist), &cleanDamage, DOT, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true); + + // DO NOT ACCESS MEMBERS OF THE AURA FROM NOW ON (DealDamage can delete aura) + + pCaster->ProcDamageAndSpell(target, PROC_FLAG_HIT_SPELL, PROC_FLAG_TAKE_DAMAGE, (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist), GetSpellSchoolMask(spellProto), spellProto); + break; + } + case SPELL_AURA_PERIODIC_LEECH: + { + Unit *pCaster = GetCaster(); + if(!pCaster) + return; + + if(!pCaster->isAlive()) + return; + + if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA && + pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE) + return; + + // Check for immune (not use charges) + if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto()))) + return; + + uint32 absorb=0; + uint32 resist=0; + CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL ); + + uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0; + + //Calculate armor mitigation if it is a physical spell + if (GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL) + { + uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage); + cleanDamage.damage += pdamage - pdamageReductedArmor; + pdamage = pdamageReductedArmor; + } + + pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),pdamage,DOT); + + // talent Soul Siphon add bonus to Drain Life spells + if( GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 0x8) ) + { + // find talent max bonus percentage + Unit::AuraList const& mClassScriptAuras = pCaster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + for(Unit::AuraList::const_iterator i = mClassScriptAuras.begin(); i != mClassScriptAuras.end(); ++i) + { + if ((*i)->GetModifier()->m_miscvalue == 4992 || (*i)->GetModifier()->m_miscvalue == 4993) + { + if((*i)->GetEffIndex()!=1) + { + sLog.outError("Expected spell %u structure change, need code update",(*i)->GetId()); + break; + } + + // effect 1 m_amount + int32 maxPercent = (*i)->GetModifier()->m_amount; + // effect 0 m_amount + int32 stepPercent = pCaster->CalculateSpellDamage((*i)->GetSpellProto(),0,(*i)->GetSpellProto()->EffectBasePoints[0],pCaster); + + // count affliction effects and calc additional damage in percentage + int32 modPercent = 0; + Unit::AuraMap const& victimAuras = m_target->GetAuras(); + for (Unit::AuraMap::const_iterator itr = victimAuras.begin(); itr != victimAuras.end(); ++itr) + { + Aura* aura = itr->second; + if (aura->IsPositive())continue; + SpellEntry const* m_spell = aura->GetSpellProto(); + if (m_spell->SpellFamilyName != SPELLFAMILY_WARLOCK) + continue; + + SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(m_spell->Id); + SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(m_spell->Id); + + for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx) + { + if(_spell_idx->second->skillId == SKILL_AFFLICTION) + { + modPercent += stepPercent; + if (modPercent >= maxPercent) + { + modPercent = maxPercent; + break; + } + } + } + } + pdamage += (pdamage*modPercent/100); + break; + } + } + } + + //As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit + // Reduce dot damage from resilience for players + if (m_target->GetTypeId()==TYPEID_PLAYER) + pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage); + + pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist); + + if(m_target->GetHealth() < pdamage) + pdamage = uint32(m_target->GetHealth()); + + sLog.outDetail("PeriodicTick: %u (TypeId: %u) health leech of %u (TypeId: %u) for %u dmg inflicted by %u abs is %u", + GetCasterGUID(), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb); + + pCaster->SendSpellNonMeleeDamageLog(m_target, GetId(), pdamage, GetSpellSchoolMask(GetSpellProto()), absorb, resist, false, 0); + + + Unit* target = m_target; // aura can be deleted in DealDamage + SpellEntry const* spellProto = GetSpellProto(); + float multiplier = spellProto->EffectMultipleValue[GetEffIndex()] > 0 ? spellProto->EffectMultipleValue[GetEffIndex()] : 1; + + uint32 new_damage = pCaster->DealDamage(m_target, (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist), &cleanDamage, DOT, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), false); + + // DO NOT ACCESS MEMBERS OF THE AURA FROM NOW ON (DealDamage can delete aura) + + pCaster->ProcDamageAndSpell(target, PROC_FLAG_HIT_SPELL, PROC_FLAG_TAKE_DAMAGE, new_damage, GetSpellSchoolMask(spellProto), spellProto); + if (!target->isAlive() && pCaster->IsNonMeleeSpellCasted(false)) + { + for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++) + { + if (pCaster->m_currentSpells[i] && pCaster->m_currentSpells[i]->m_spellInfo->Id == spellProto->Id) + pCaster->m_currentSpells[i]->cancel(); + } + } + + + if(Player *modOwner = pCaster->GetSpellModOwner()) + modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_MULTIPLE_VALUE, multiplier); + + uint32 heal = pCaster->SpellHealingBonus(spellProto, uint32(new_damage * multiplier), DOT, pCaster); + + int32 gain = pCaster->ModifyHealth(heal); + pCaster->getHostilRefManager().threatAssist(pCaster, gain * 0.5f, spellProto); + + pCaster->SendHealSpellLog(pCaster, spellProto->Id, heal); + break; + } + case SPELL_AURA_PERIODIC_HEAL: + case SPELL_AURA_OBS_MOD_HEALTH: + { + Unit *pCaster = GetCaster(); + if(!pCaster) + return; + + // heal for caster damage (must be alive) + if(m_target != pCaster && GetSpellProto()->SpellVisual==163 && !pCaster->isAlive()) + return; + + // ignore non positive values (can be result apply spellmods to aura damage + uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0; + + uint32 pdamage; + + if(m_modifier.m_auraname==SPELL_AURA_OBS_MOD_HEALTH) + pdamage = uint32(m_target->GetMaxHealth() * amount/100); + else + pdamage = amount; + + pdamage = pCaster->SpellHealingBonus(GetSpellProto(), pdamage, DOT, m_target); + + sLog.outDetail("PeriodicTick: %u (TypeId: %u) heal of %u (TypeId: %u) for %u health inflicted by %u", + GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId()); + + WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size + data.append(m_target->GetPackGUID()); + data.appendPackGUID(GetCasterGUID()); + data << uint32(GetId()); + data << uint32(1); + data << uint32(m_modifier.m_auraname); + data << (uint32)pdamage; + m_target->SendMessageToSet(&data,true); + + int32 gain = m_target->ModifyHealth(pdamage); + + // add HoTs to amount healed in bgs + if( pCaster->GetTypeId() == TYPEID_PLAYER ) + if( BattleGround *bg = ((Player*)pCaster)->GetBattleGround() ) + bg->UpdatePlayerScore(((Player*)pCaster), SCORE_HEALING_DONE, gain); + + //Do check before because m_modifier.auraName can be invalidate by DealDamage. + bool procSpell = (m_modifier.m_auraname == SPELL_AURA_PERIODIC_HEAL && m_target != pCaster); + + m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto()); + + Unit* target = m_target; // aura can be deleted in DealDamage + SpellEntry const* spellProto = GetSpellProto(); + bool haveCastItem = GetCastItemGUID()!=0; + + // heal for caster damage + if(m_target!=pCaster && spellProto->SpellVisual==163) + { + uint32 dmg = spellProto->manaPerSecond; + if(pCaster->GetHealth() <= dmg && pCaster->GetTypeId()==TYPEID_PLAYER) + { + pCaster->RemoveAurasDueToSpell(GetId()); + + // finish current generic/channeling spells, don't affect autorepeat + if(pCaster->m_currentSpells[CURRENT_GENERIC_SPELL]) + { + pCaster->m_currentSpells[CURRENT_GENERIC_SPELL]->finish(); + } + if(pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL]) + { + pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL]->SendChannelUpdate(0); + pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL]->finish(); + } + } + else + { + pCaster->SendSpellNonMeleeDamageLog(pCaster, GetId(), gain, GetSpellSchoolMask(GetSpellProto()), 0, 0, false, 0, false); + + CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL ); + pCaster->DealDamage(pCaster, gain, &cleanDamage, NODAMAGE, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true); + } + } + + // ignore item heals + if(procSpell && !haveCastItem) + pCaster->ProcDamageAndSpell(target,PROC_FLAG_HEAL, PROC_FLAG_HEALED, pdamage, SPELL_SCHOOL_MASK_NONE, spellProto); + break; + } + case SPELL_AURA_PERIODIC_MANA_LEECH: + { + Unit *pCaster = GetCaster(); + if(!pCaster) + return; + + if(!pCaster->isAlive()) + return; + + if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA && + pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE) + return; + + // Check for immune (not use charges) + if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto()))) + return; + + // ignore non positive values (can be result apply spellmods to aura damage + uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0; + + sLog.outDetail("PeriodicTick: %u (TypeId: %u) power leech of %u (TypeId: %u) for %u dmg inflicted by %u", + GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId()); + + if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue > 4) + break; + + Powers power = Powers(m_modifier.m_miscvalue); + + // power type might have changed between aura applying and tick (druid's shapeshift) + if(m_target->getPowerType() != power) + break; + + int32 drain_amount = m_target->GetPower(power) > pdamage ? pdamage : m_target->GetPower(power); + + // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4) + if (power == POWER_MANA && m_target->GetTypeId() == TYPEID_PLAYER) + drain_amount -= ((Player*)m_target)->GetSpellCritDamageReduction(drain_amount); + + m_target->ModifyPower(power, -drain_amount); + + float gain_multiplier = 0; + + if(pCaster->GetMaxPower(power) > 0) + { + gain_multiplier = GetSpellProto()->EffectMultipleValue[GetEffIndex()]; + + if(Player *modOwner = pCaster->GetSpellModOwner()) + modOwner->ApplySpellMod(GetId(), SPELLMOD_MULTIPLE_VALUE, gain_multiplier); + } + + WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size + data.append(m_target->GetPackGUID()); + data.appendPackGUID(GetCasterGUID()); + data << uint32(GetId()); + data << uint32(1); + data << uint32(m_modifier.m_auraname); + data << (uint32)power; // power type + data << (uint32)drain_amount; + data << (float)gain_multiplier; + m_target->SendMessageToSet(&data,true); + + int32 gain_amount = int32(drain_amount*gain_multiplier); + + if(gain_amount) + { + int32 gain = pCaster->ModifyPower(power,gain_amount); + m_target->AddThreat(pCaster, float(gain) * 0.5f, GetSpellSchoolMask(GetSpellProto()), GetSpellProto()); + } + break; + } + case SPELL_AURA_PERIODIC_ENERGIZE: + { + // ignore non positive values (can be result apply spellmods to aura damage + uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0; + + sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u dmg inflicted by %u", + GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId()); + + if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue > 4) + break; + + Powers power = Powers(m_modifier.m_miscvalue); + + if(m_target->GetMaxPower(power) == 0) + break; + + WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size + data.append(m_target->GetPackGUID()); + data.appendPackGUID(GetCasterGUID()); + data << uint32(GetId()); + data << uint32(1); + data << uint32(m_modifier.m_auraname); + data << (uint32)power; // power type + data << (uint32)pdamage; + m_target->SendMessageToSet(&data,true); + + int32 gain = m_target->ModifyPower(power,pdamage); + + if(Unit* pCaster = GetCaster()) + m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto()); + break; + } + case SPELL_AURA_OBS_MOD_MANA: + { + // ignore non positive values (can be result apply spellmods to aura damage + uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0; + + uint32 pdamage = uint32(m_target->GetMaxPower(POWER_MANA) * amount/100); + + sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u mana inflicted by %u", + GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId()); + + if(m_target->GetMaxPower(POWER_MANA) == 0) + break; + + WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size + data.append(m_target->GetPackGUID()); + data.appendPackGUID(GetCasterGUID()); + data << uint32(GetId()); + data << uint32(1); + data << uint32(m_modifier.m_auraname); + data << (uint32)0; // ? + data << (uint32)pdamage; + m_target->SendMessageToSet(&data,true); + + int32 gain = m_target->ModifyPower(POWER_MANA, pdamage); + + if(Unit* pCaster = GetCaster()) + m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto()); + break; + } + case SPELL_AURA_POWER_BURN_MANA: + { + Unit *pCaster = GetCaster(); + if(!pCaster) + return; + + // Check for immune (not use charges) + if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto()))) + return; + + int32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0; + + Powers powerType = Powers(m_modifier.m_miscvalue); + + if(!m_target->isAlive() || m_target->getPowerType() != powerType) + return; + + // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4) + if (powerType == POWER_MANA && m_target->GetTypeId() == TYPEID_PLAYER) + pdamage -= ((Player*)m_target)->GetSpellCritDamageReduction(pdamage); + + uint32 gain = uint32(-m_target->ModifyPower(powerType, -pdamage)); + + gain = uint32(gain * GetSpellProto()->EffectMultipleValue[GetEffIndex()]); + + //maybe has to be sent different to client, but not by SMSG_PERIODICAURALOG + pCaster->SpellNonMeleeDamageLog(m_target, GetId(), gain); + break; + } + // Here tick dummy auras + case SPELL_AURA_PERIODIC_DUMMY: + { + PeriodicDummyTick(); + break; + } + default: + break; + } +} + +void Aura::PeriodicDummyTick() +{ + SpellEntry const* spell = GetSpellProto(); + switch (spell->Id) + { + // Drink + case 430: + case 431: + case 432: + case 1133: + case 1135: + case 1137: + case 10250: + case 22734: + case 27089: + case 34291: + case 43706: + case 46755: + { + if (m_target->GetTypeId() != TYPEID_PLAYER) + return; + // Search SPELL_AURA_MOD_POWER_REGEN aura for this spell and add bonus + Unit::AuraList const& aura = m_target->GetAurasByType(SPELL_AURA_MOD_POWER_REGEN); + for(Unit::AuraList::const_iterator i = aura.begin(); i != aura.end(); ++i) + { + if ((*i)->GetId() == GetId()) + { + // Get tick number + int32 tick = (m_maxduration - m_duration) / m_modifier.periodictime; + // Default case (not on arenas) + if (tick == 0) + { + (*i)->GetModifier()->m_amount = m_modifier.m_amount; + ((Player*)m_target)->UpdateManaRegen(); + // Disable continue + m_isPeriodic = false; + } + return; + //********************************************** + // Code commended since arena patch not added + // This feature uses only in arenas + //********************************************** + // Here need increase mana regen per tick (6 second rule) + // on 0 tick - 0 (handled in 2 second) + // on 1 tick - 166% (handled in 4 second) + // on 2 tick - 133% (handled in 6 second) + // Not need update after 3 tick + /* + if (tick > 3) + return; + // Apply bonus for 0 - 3 tick + switch (tick) + { + case 0: // 0% + (*i)->GetModifier()->m_amount = m_modifier.m_amount = 0; + break; + case 1: // 166% + (*i)->GetModifier()->m_amount = m_modifier.m_amount * 5 / 3; + break; + case 2: // 133% + (*i)->GetModifier()->m_amount = m_modifier.m_amount * 4 / 3; + break; + default: // 100% - normal regen + (*i)->GetModifier()->m_amount = m_modifier.m_amount; + break; + } + ((Player*)m_target)->UpdateManaRegen(); + return;*/ + } + } + return; + } +// // Panda +// case 19230: break; +// // Master of Subtlety +// case 31666: break; +// // Gossip NPC Periodic - Talk +// case 33208: break; +// // Gossip NPC Periodic - Despawn +// case 33209: break; +// // Force of Nature +// case 33831: break; + // Aspect of the Viper + case 34074: + { + if (m_target->GetTypeId() != TYPEID_PLAYER) + return; + // Should be manauser + if (m_target->getPowerType()!=POWER_MANA) + return; + Unit *caster = GetCaster(); + if (!caster) + return; + // Regen amount is max (100% from spell) on 21% or less mana and min on 92.5% or greater mana (20% from spell) + int mana = m_target->GetPower(POWER_MANA); + int max_mana = m_target->GetMaxPower(POWER_MANA); + int32 base_regen = caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_currentBasePoints, m_target); + float regen_pct = 1.20f - 1.1f * mana / max_mana; + if (regen_pct > 1.0f) regen_pct = 1.0f; + else if (regen_pct < 0.2f) regen_pct = 0.2f; + m_modifier.m_amount = int32 (base_regen * regen_pct); + ((Player*)m_target)->UpdateManaRegen(); + return; + } +// // Steal Weapon +// case 36207: break; +// // Simon Game START timer, (DND) +// case 39993: break; +// // Harpooner's Mark +// case 40084: break; +// // Knockdown Fel Cannon: break; The Aggro Burst +// case 40119: break; +// // Old Mount Spell +// case 40154: break; +// // Magnetic Pull +// case 40581: break; +// // Ethereal Ring: break; The Bolt Burst +// case 40801: break; +// // Crystal Prison +// case 40846: break; +// // Copy Weapon +// case 41054: break; +// // Ethereal Ring Visual, Lightning Aura +// case 41477: break; +// // Ethereal Ring Visual, Lightning Aura (Fork) +// case 41525: break; +// // Ethereal Ring Visual, Lightning Jumper Aura +// case 41567: break; +// // No Man's Land +// case 41955: break; +// // Headless Horseman - Fire +// case 42074: break; +// // Headless Horseman - Visual - Large Fire +// case 42075: break; +// // Headless Horseman - Start Fire, Periodic Aura +// case 42140: break; +// // Ram Speed Boost +// case 42152: break; +// // Headless Horseman - Fires Out Victory Aura +// case 42235: break; +// // Pumpkin Life Cycle +// case 42280: break; +// // Brewfest Request Chick Chuck Mug Aura +// case 42537: break; +// // Squashling +// case 42596: break; +// // Headless Horseman Climax, Head: Periodic +// case 42603: break; +// // Fire Bomb +// case 42621: break; +// // Headless Horseman - Conflagrate, Periodic Aura +// case 42637: break; +// // Headless Horseman - Create Pumpkin Treats Aura +// case 42774: break; +// // Headless Horseman Climax - Summoning Rhyme Aura +// case 42879: break; +// // Tricky Treat +// case 42919: break; +// // Giddyup! +// case 42924: break; +// // Ram - Trot +// case 42992: break; +// // Ram - Canter +// case 42993: break; +// // Ram - Gallop +// case 42994: break; +// // Ram Level - Neutral +// case 43310: break; +// // Headless Horseman - Maniacal Laugh, Maniacal, Delayed 17 +// case 43884: break; +// // Headless Horseman - Maniacal Laugh, Maniacal, other, Delayed 17 +// case 44000: break; +// // Energy Feedback +// case 44328: break; +// // Romantic Picnic +// case 45102: break; +// // Romantic Picnic +// case 45123: break; +// // Looking for Love +// case 45124: break; +// // Kite - Lightning Strike Kite Aura +// case 45197: break; +// // Rocket Chicken +// case 45202: break; +// // Copy Offhand Weapon +// case 45205: break; +// // Upper Deck - Kite - Lightning Periodic Aura +// case 45207: break; +// // Kite -Sky Lightning Strike Kite Aura +// case 45251: break; +// // Ribbon Pole Dancer Check Aura +// case 45390: break; +// // Holiday - Midsummer, Ribbon Pole Periodic Visual +// case 45406: break; +// // Parachute +// case 45472: break; +// // Alliance Flag, Extra Damage Debuff +// case 45898: break; +// // Horde Flag, Extra Damage Debuff +// case 45899: break; +// // Ahune - Summoning Rhyme Aura +// case 45926: break; +// // Ahune - Slippery Floor +// case 45945: break; +// // Ahune's Shield +// case 45954: break; +// // Nether Vapor Lightning +// case 45960: break; +// // Darkness +// case 45996: break; +// // Summon Blood Elves Periodic +// case 46041: break; +// // Transform Visual Missile Periodic +// case 46205: break; +// // Find Opening Beam End +// case 46333: break; +// // Ice Spear Control Aura +// case 46371: break; +// // Hailstone Chill +// case 46458: break; +// // Hailstone Chill, Internal +// case 46465: break; +// // Chill, Internal Shifter +// case 46549: break; +// // Summon Ice Spear Knockback Delayer +// case 46878: break; +// // Burninate Effect +// case 47214: break; +// // Fizzcrank Practice Parachute +// case 47228: break; +// // Send Mug Control Aura +// case 47369: break; +// // Direbrew's Disarm (precast) +// case 47407: break; +// // Mole Machine Port Schedule +// case 47489: break; +// // Mole Machine Portal Schedule +// case 49466: break; +// // Drink Coffee +// case 49472: break; +// // Listening to Music +// case 50493: break; +// // Love Rocket Barrage +// case 50530: break; + default: + break; + } +} + +void Aura::HandlePreventFleeing(bool apply, bool Real) +{ + if(!Real) + return; + + Unit::AuraList const& fearAuras = m_target->GetAurasByType(SPELL_AURA_MOD_FEAR); + if( !fearAuras.empty() ) + { + if (apply) + m_target->SetFeared(false, fearAuras.front()->GetCasterGUID()); + else + m_target->SetFeared(true); + } +} + +void Aura::HandleManaShield(bool apply, bool Real) +{ + if(!Real) + return; + + // prevent double apply bonuses + if(apply && (m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading())) + { + if(Unit* caster = GetCaster()) + { + float DoneActualBenefit = 0.0f; + switch(m_spellProto->SpellFamilyName) + { + case SPELLFAMILY_MAGE: + if(m_spellProto->SpellFamilyFlags & 0x8000) + { + // Mana Shield + // +50% from +spd bonus + DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.5f; + break; + } + break; + default: + break; + } + + DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto()); + + m_modifier.m_amount += (int32)DoneActualBenefit; + } + } +} + +void Aura::HandleArenaPreparation(bool apply, bool Real) +{ + if(!Real) + return; + + if(apply) + m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION); + else + m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION); +} diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h new file mode 100644 index 00000000000..24b94202978 --- /dev/null +++ b/src/game/SpellAuras.h @@ -0,0 +1,375 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef MANGOS_SPELLAURAS_H +#define MANGOS_SPELLAURAS_H + +#include "SpellAuraDefines.h" + +struct DamageManaShield +{ + uint32 m_spellId; + uint32 m_modType; + int32 m_schoolType; + uint32 m_totalAbsorb; + uint32 m_currAbsorb; +}; + +struct Modifier +{ + AuraType m_auraname; + int32 m_amount; + int32 m_miscvalue; + uint32 periodictime; +}; + +class Unit; +struct SpellEntry; +struct SpellModifier; +struct ProcTriggerSpell; + +// forward decl +class Aura; + +typedef void(Aura::*pAuraHandler)(bool Apply, bool Real); +// Real == true at aura add/remove +// Real == false at aura mod unapply/reapply; when adding/removing dependent aura/item/stat mods +// +// Code in aura handler can be guarded by if(Real) check if it should execution only at real add/remove of aura +// +// MAIN RULE: Code MUST NOT be guarded by if(Real) check if it modifies any stats +// (percent auras, stats mods, etc) +// Second rule: Code must be guarded by if(Real) check if it modifies object state (start/stop attack, send packets to client, etc) +// +// Other case choice: each code line moved under if(Real) check is mangos speedup, +// each setting object update field code line moved under if(Real) check is significant mangos speedup, and less server->client data sends +// each packet sending code moved under if(Real) check is _large_ mangos speedup, and lot less server->client data sends + +class MANGOS_DLL_SPEC Aura +{ + friend Aura* CreateAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster, Item* castItem); + + public: + //aura handlers + void HandleNULL(bool, bool) + { + // NOT IMPLEMENTED + } + void HandleUnused(bool, bool) + { + // NOT USED BY ANY SPELL OR USELESS + } + void HandleNoImmediateEffect(bool, bool) + { + // aura not have immediate effect at add/remove and handled by ID in other code place + } + void HandleBindSight(bool Apply, bool Real); + void HandleModPossess(bool Apply, bool Real); + void HandlePeriodicDamage(bool Apply, bool Real); + void HandleAuraDummy(bool Apply, bool Real); + void HandleAuraPeriodicDummy(bool apply, bool Real); + void HandleModConfuse(bool Apply, bool Real); + void HandleModCharm(bool Apply, bool Real); + void HandleModFear(bool Apply, bool Real); + void HandlePeriodicHeal(bool Apply, bool Real); + void HandleModAttackSpeed(bool Apply, bool Real); + void HandleModMeleeRangedSpeedPct(bool apply, bool Real); + void HandleModCombatSpeedPct(bool apply, bool Real); + void HandleModThreat(bool Apply, bool Real); + void HandleModTaunt(bool Apply, bool Real); + void HandleFeignDeath(bool Apply, bool Real); + void HandleAuraModDisarm(bool Apply, bool Real); + void HandleAuraModStalked(bool Apply, bool Real); + void HandleAuraWaterWalk(bool Apply, bool Real); + void HandleAuraFeatherFall(bool Apply, bool Real); + void HandleAuraHover(bool Apply, bool Real); + void HandleAddModifier(bool Apply, bool Real); + void HandleAuraModStun(bool Apply, bool Real); + void HandleModDamageDone(bool Apply, bool Real); + void HandleAuraUntrackable(bool Apply, bool Real); + void HandleAuraEmpathy(bool Apply, bool Real); + void HandleModOffhandDamagePercent(bool apply, bool Real); + void HandleAuraModRangedAttackPower(bool Apply, bool Real); + void HandleAuraModIncreaseEnergyPercent(bool Apply, bool Real); + void HandleAuraModIncreaseHealthPercent(bool Apply, bool Real); + void HandleAuraModRegenInterrupt(bool Apply, bool Real); + void HandleHaste(bool Apply, bool Real); + void HandlePeriodicTriggerSpell(bool Apply, bool Real); + void HandlePeriodicEnergize(bool Apply, bool Real); + void HandleAuraModResistanceExclusive(bool Apply, bool Real); + void HandleModStealth(bool Apply, bool Real); + void HandleInvisibility(bool Apply, bool Real); + void HandleInvisibilityDetect(bool Apply, bool Real); + void HandleAuraModTotalHealthPercentRegen(bool Apply, bool Real); + void HandleAuraModTotalManaPercentRegen(bool Apply, bool Real); + void HandleAuraModResistance(bool Apply, bool Real); + void HandleAuraModRoot(bool Apply, bool Real); + void HandleAuraModSilence(bool Apply, bool Real); + void HandleAuraModStat(bool Apply, bool Real); + void HandleAuraModIncreaseSpeed(bool Apply, bool Real); + void HandleAuraModIncreaseMountedSpeed(bool Apply, bool Real); + void HandleAuraModIncreaseFlightSpeed(bool Apply, bool Real); + void HandleAuraModDecreaseSpeed(bool Apply, bool Real); + void HandleAuraModUseNormalSpeed(bool Apply, bool Real); + void HandleAuraModIncreaseHealth(bool Apply, bool Real); + void HandleAuraModIncreaseEnergy(bool Apply, bool Real); + void HandleAuraModShapeshift(bool Apply, bool Real); + void HandleAuraModEffectImmunity(bool Apply, bool Real); + void HandleAuraModStateImmunity(bool Apply, bool Real); + void HandleAuraModSchoolImmunity(bool Apply, bool Real); + void HandleAuraModDmgImmunity(bool Apply, bool Real); + void HandleAuraModDispelImmunity(bool Apply, bool Real); + void HandleAuraProcTriggerSpell(bool Apply, bool Real); + void HandleAuraTrackCreatures(bool Apply, bool Real); + void HandleAuraTrackResources(bool Apply, bool Real); + void HandleAuraModParryPercent(bool Apply, bool Real); + void HandleAuraModDodgePercent(bool Apply, bool Real); + void HandleAuraModBlockPercent(bool Apply, bool Real); + void HandleAuraModCritPercent(bool Apply, bool Real); + void HandlePeriodicLeech(bool Apply, bool Real); + void HandleModHitChance(bool Apply, bool Real); + void HandleModSpellHitChance(bool Apply, bool Real); + void HandleAuraModScale(bool Apply, bool Real); + void HandlePeriodicManaLeech(bool Apply, bool Real); + void HandleModCastingSpeed(bool Apply, bool Real); + void HandleAuraMounted(bool Apply, bool Real); + void HandleWaterBreathing(bool Apply, bool Real); + void HandleModBaseResistance(bool Apply, bool Real); + void HandleModRegen(bool Apply, bool Real); + void HandleModPowerRegen(bool Apply, bool Real); + void HandleModPowerRegenPCT(bool Apply, bool Real); + void HandleChannelDeathItem(bool Apply, bool Real); + void HandlePeriodicDamagePCT(bool Apply, bool Real); + void HandleAuraModAttackPower(bool Apply, bool Real); + void HandleAuraTransform(bool Apply, bool Real); + void HandleModSpellCritChance(bool Apply, bool Real); + void HandleAuraModIncreaseSwimSpeed(bool Apply, bool Real); + void HandleModPowerCostPCT(bool Apply, bool Real); + void HandleModPowerCost(bool Apply, bool Real); + void HandleFarSight(bool Apply, bool Real); + void HandleModPossessPet(bool Apply, bool Real); + void HandleModMechanicImmunity(bool Apply, bool Real); + void HandleAuraModSkill(bool Apply, bool Real); + void HandleModDamagePercentDone(bool Apply, bool Real); + void HandleModPercentStat(bool Apply, bool Real); + void HandleModResistancePercent(bool Apply, bool Real); + void HandleAuraModBaseResistancePCT(bool Apply, bool Real); + void HandleModShieldBlockPCT(bool Apply, bool Real); + void HandleAuraTrackStealthed(bool Apply, bool Real); + void HandleModShieldBlock(bool Apply, bool Real); + void HandleForceReaction(bool Apply, bool Real); + void HandleAuraModRangedHaste(bool Apply, bool Real); + void HandleRangedAmmoHaste(bool Apply, bool Real); + void HandleModHealingDone(bool Apply, bool Real); + void HandleModTotalPercentStat(bool Apply, bool Real); + void HandleAuraModTotalThreat(bool Apply, bool Real); + void HandleModUnattackable(bool Apply, bool Real); + void HandleAuraModPacify(bool Apply, bool Real); + void HandleAuraGhost(bool Apply, bool Real); + void HandleAuraAllowFlight(bool Apply, bool Real); + void HandleModRating(bool apply, bool Real); + void HandleModTargetResistance(bool apply, bool Real); + void HandleAuraAttackPowerAttacker(bool apply, bool Real); + void HandleAuraModAttackPowerPercent(bool apply, bool Real); + void HandleAuraModRangedAttackPowerPercent(bool apply, bool Real); + void HandleAuraModRangedAttackPowerOfStatPercent(bool apply, bool Real); + void HandleSpiritOfRedemption(bool apply, bool Real); + void HandleAuraHealingPct(bool apply, bool Real); + void HandleModManaRegen(bool apply, bool Real); + void HandleComprehendLanguage(bool apply, bool Real); + void HandleAuraHealing(bool apply, bool Real); + void HandleShieldBlockValue(bool apply, bool Real); + void HandleModSpellCritChanceShool(bool apply, bool Real); + void HandleAuraRetainComboPoints(bool apply, bool Real); + void HandleModSpellDamagePercentFromStat(bool apply, bool Real); + void HandleModSpellHealingPercentFromStat(bool apply, bool Real); + void HandleAuraModDispelResist(bool apply, bool Real); + void HandleModSpellDamagePercentFromAttackPower(bool apply, bool Real); + void HandleModSpellHealingPercentFromAttackPower(bool apply, bool Real); + void HandleAuraModPacifyAndSilence(bool Apply, bool Real); + void HandleAuraModIncreaseMaxHealth(bool apply, bool Real); + void HandleAuraModExpertise(bool apply, bool Real); + void HandleForceMoveForward(bool apply, bool Real); + void HandleAuraModResistenceOfStatPercent(bool apply, bool Real); + void HandleAuraPowerBurn(bool apply, bool Real); + void HandleSchoolAbsorb(bool apply, bool Real); + void HandlePreventFleeing(bool apply, bool Real); + void HandleManaShield(bool apply, bool Real); + void HandleArenaPreparation(bool apply, bool Real); + + virtual ~Aura(); + + void SetModifier(AuraType t, int32 a, uint32 pt, int32 miscValue); + Modifier* GetModifier() {return &m_modifier;} + int32 GetMiscValue() {return m_spellProto->EffectMiscValue[m_effIndex];} + int32 GetMiscBValue() {return m_spellProto->EffectMiscValueB[m_effIndex];} + + SpellEntry const* GetSpellProto() const { return m_spellProto; } + uint32 GetId() const{ return m_spellProto->Id; } + uint64 GetCastItemGUID() const { return m_castItemGuid; } + uint32 GetEffIndex() const{ return m_effIndex; } + int32 GetBasePoints() const { return m_currentBasePoints; } + + int32 GetAuraMaxDuration() const { return m_maxduration; } + void SetAuraMaxDuration(int32 duration) { m_maxduration = duration; } + int32 GetAuraDuration() const { return m_duration; } + void SetAuraDuration(int32 duration) { m_duration = duration; } + time_t GetAuraApplyTime() { return m_applyTime; } + void UpdateAuraDuration(); + void SendAuraDurationForCaster(Player* caster); + + uint64 const& GetCasterGUID() const { return m_caster_guid; } + Unit* GetCaster() const; + Unit* GetTarget() const { return m_target; } + void SetTarget(Unit* target) { m_target = target; } + void SetLoadedState(uint64 caster_guid,int32 damage,int32 maxduration,int32 duration,int32 charges) + { + m_caster_guid = caster_guid; + m_modifier.m_amount = damage; + m_maxduration = maxduration; + m_duration = duration; + m_procCharges = charges; + } + + uint8 GetAuraSlot() const { return m_auraSlot; } + void SetAuraSlot(uint8 slot) { m_auraSlot = slot; } + void UpdateAuraCharges() + { + uint8 slot = GetAuraSlot(); + + // only aura inslot with charges and without stack limitation + if (slot < MAX_AURAS && m_procCharges >= 1 && GetSpellProto()->StackAmount==0) + SetAuraApplication(slot, m_procCharges - 1); + } + + bool IsPositive() { return m_positive; } + void SetNegative() { m_positive = false; } + void SetPositive() { m_positive = true; } + + bool IsPermanent() const { return m_permanent; } + bool IsAreaAura() const { return m_isAreaAura; } + bool IsPeriodic() const { return m_isPeriodic; } + bool IsTrigger() const { return m_isTrigger; } + bool IsPassive() const { return m_isPassive; } + bool IsPersistent() const { return m_isPersistent; } + bool IsDeathPersistent() const { return m_isDeathPersist; } + bool IsRemovedOnShapeLost() const { return m_isRemovedOnShapeLost; } + bool IsInUse() const { return m_in_use;} + + virtual void Update(uint32 diff); + void ApplyModifier(bool apply, bool Real = false); + + void _AddAura(); + void _RemoveAura(); + + void TriggerSpell(); + + bool IsUpdated() { return m_updated; } + void SetUpdated(bool val) { m_updated = val; } + void SetRemoveMode(AuraRemoveMode mode) { m_removeMode = mode; } + + int32 m_procCharges; + + virtual Unit* GetTriggerTarget() const { return m_target; } + + // add/remove SPELL_AURA_MOD_SHAPESHIFT (36) linked auras + void HandleShapeshiftBoosts(bool apply); + + // Allow Apply Aura Handler to modify and access m_AuraDRGroup + void setDiminishGroup(DiminishingGroup group) { m_AuraDRGroup = group; } + DiminishingGroup getDiminishGroup() const { return m_AuraDRGroup; } + + void PeriodicTick(); + void PeriodicDummyTick(); + protected: + Aura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster = NULL, Item* castItem = NULL); + + Modifier m_modifier; + SpellModifier *m_spellmod; + uint32 m_effIndex; + SpellEntry const *m_spellProto; + int32 m_currentBasePoints; // cache SpellEntry::EffectBasePoints and use for set custom base points + uint64 m_caster_guid; + Unit* m_target; + int32 m_maxduration; + int32 m_duration; + int32 m_timeCla; + uint64 m_castItemGuid; // it is NOT safe to keep a pointer to the item because it may get deleted + time_t m_applyTime; + + AuraRemoveMode m_removeMode; + + uint8 m_auraSlot; + + bool m_positive:1; + bool m_permanent:1; + bool m_isPeriodic:1; + bool m_isTrigger:1; + bool m_isAreaAura:1; + bool m_isPassive:1; + bool m_isPersistent:1; + bool m_isDeathPersist:1; + bool m_isRemovedOnShapeLost:1; + bool m_updated:1; + bool m_in_use:1; // true while in Aura::ApplyModifier call + + int32 m_periodicTimer; + uint32 m_PeriodicEventId; + DiminishingGroup m_AuraDRGroup; + private: + void UpdateSlotCounterAndDuration(bool add); + void CleanupTriggeredSpells(); + void SetAura(uint32 slot, bool remove) { m_target->SetUInt32Value(UNIT_FIELD_AURA + slot, remove ? 0 : GetId()); } + void SetAuraFlag(uint32 slot, bool add); + void SetAuraLevel(uint32 slot, uint32 level); + void SetAuraApplication(uint32 slot, int8 count); +}; + +class MANGOS_DLL_SPEC AreaAura : public Aura +{ + public: + AreaAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster = NULL, Item* castItem = NULL); + ~AreaAura(); + void Update(uint32 diff); + private: + float m_radius; + AreaAuraType m_areaAuraType; +}; + +class MANGOS_DLL_SPEC PersistentAreaAura : public Aura +{ + public: + PersistentAreaAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster = NULL, Item* castItem = NULL); + ~PersistentAreaAura(); + void Update(uint32 diff); +}; + +class MANGOS_DLL_SPEC SingleEnemyTargetAura : public Aura +{ + friend Aura* CreateAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster, Item* castItem); + + public: + ~SingleEnemyTargetAura(); + Unit* GetTriggerTarget() const; + + protected: + SingleEnemyTargetAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster = NULL, Item* castItem = NULL); + uint64 m_casters_target_guid; +}; + +Aura* CreateAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster = NULL, Item* castItem = NULL); +#endif diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp new file mode 100644 index 00000000000..fa037fcdb24 --- /dev/null +++ b/src/game/SpellEffects.cpp @@ -0,0 +1,6090 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "SharedDefines.h" +#include "Database/DatabaseEnv.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Opcodes.h" +#include "Log.h" +#include "UpdateMask.h" +#include "World.h" +#include "ObjectMgr.h" +#include "SpellMgr.h" +#include "Player.h" +#include "SkillExtraItems.h" +#include "Unit.h" +#include "CreatureAI.h" +#include "Spell.h" +#include "DynamicObject.h" +#include "SpellAuras.h" +#include "Group.h" +#include "UpdateData.h" +#include "MapManager.h" +#include "ObjectAccessor.h" +#include "SharedDefines.h" +#include "Pet.h" +#include "GameObject.h" +#include "GossipDef.h" +#include "Creature.h" +#include "Totem.h" +#include "CreatureAI.h" +#include "BattleGround.h" +#include "BattleGroundEY.h" +#include "BattleGroundWS.h" +#include "VMapFactory.h" +#include "Language.h" +#include "SocialMgr.h" +#include "Util.h" + +pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= +{ + &Spell::EffectNULL, // 0 + &Spell::EffectInstaKill, // 1 SPELL_EFFECT_INSTAKILL + &Spell::EffectSchoolDMG, // 2 SPELL_EFFECT_SCHOOL_DAMAGE + &Spell::EffectDummy, // 3 SPELL_EFFECT_DUMMY + &Spell::EffectUnused, // 4 SPELL_EFFECT_PORTAL_TELEPORT unused + &Spell::EffectTeleportUnits, // 5 SPELL_EFFECT_TELEPORT_UNITS + &Spell::EffectApplyAura, // 6 SPELL_EFFECT_APPLY_AURA + &Spell::EffectEnvirinmentalDMG, // 7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE + &Spell::EffectPowerDrain, // 8 SPELL_EFFECT_POWER_DRAIN + &Spell::EffectHealthLeech, // 9 SPELL_EFFECT_HEALTH_LEECH + &Spell::EffectHeal, // 10 SPELL_EFFECT_HEAL + &Spell::EffectUnused, // 11 SPELL_EFFECT_BIND + &Spell::EffectNULL, // 12 SPELL_EFFECT_PORTAL + &Spell::EffectUnused, // 13 SPELL_EFFECT_RITUAL_BASE unused + &Spell::EffectUnused, // 14 SPELL_EFFECT_RITUAL_SPECIALIZE unused + &Spell::EffectUnused, // 15 SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL unused + &Spell::EffectQuestComplete, // 16 SPELL_EFFECT_QUEST_COMPLETE + &Spell::EffectWeaponDmg, // 17 SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL + &Spell::EffectResurrect, // 18 SPELL_EFFECT_RESURRECT + &Spell::EffectAddExtraAttacks, // 19 SPELL_EFFECT_ADD_EXTRA_ATTACKS + &Spell::EffectUnused, // 20 SPELL_EFFECT_DODGE one spell: Dodge + &Spell::EffectUnused, // 21 SPELL_EFFECT_EVADE one spell: Evade (DND) + &Spell::EffectParry, // 22 SPELL_EFFECT_PARRY + &Spell::EffectUnused, // 23 SPELL_EFFECT_BLOCK one spell: Block + &Spell::EffectCreateItem, // 24 SPELL_EFFECT_CREATE_ITEM + &Spell::EffectUnused, // 25 SPELL_EFFECT_WEAPON + &Spell::EffectUnused, // 26 SPELL_EFFECT_DEFENSE one spell: Defense + &Spell::EffectPersistentAA, // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA + &Spell::EffectSummonType, // 28 SPELL_EFFECT_SUMMON + &Spell::EffectMomentMove, // 29 SPELL_EFFECT_LEAP + &Spell::EffectEnergize, // 30 SPELL_EFFECT_ENERGIZE + &Spell::EffectWeaponDmg, // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE + &Spell::EffectTriggerMissileSpell, // 32 SPELL_EFFECT_TRIGGER_MISSILE + &Spell::EffectOpenLock, // 33 SPELL_EFFECT_OPEN_LOCK + &Spell::EffectSummonChangeItem, // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM + &Spell::EffectApplyAreaAura, // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY + &Spell::EffectLearnSpell, // 36 SPELL_EFFECT_LEARN_SPELL + &Spell::EffectUnused, // 37 SPELL_EFFECT_SPELL_DEFENSE one spell: SPELLDEFENSE (DND) + &Spell::EffectDispel, // 38 SPELL_EFFECT_DISPEL + &Spell::EffectUnused, // 39 SPELL_EFFECT_LANGUAGE + &Spell::EffectDualWield, // 40 SPELL_EFFECT_DUAL_WIELD + &Spell::EffectSummonWild, // 41 SPELL_EFFECT_SUMMON_WILD + &Spell::EffectSummonGuardian, // 42 SPELL_EFFECT_SUMMON_GUARDIAN + &Spell::EffectTeleUnitsFaceCaster, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER + &Spell::EffectLearnSkill, // 44 SPELL_EFFECT_SKILL_STEP + &Spell::EffectAddHonor, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related + &Spell::EffectNULL, // 46 SPELL_EFFECT_SPAWN we must spawn pet there + &Spell::EffectTradeSkill, // 47 SPELL_EFFECT_TRADE_SKILL + &Spell::EffectUnused, // 48 SPELL_EFFECT_STEALTH one spell: Base Stealth + &Spell::EffectUnused, // 49 SPELL_EFFECT_DETECT one spell: Detect + &Spell::EffectTransmitted, // 50 SPELL_EFFECT_TRANS_DOOR + &Spell::EffectUnused, // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT unused + &Spell::EffectUnused, // 52 SPELL_EFFECT_GUARANTEE_HIT one spell: zzOLDCritical Shot + &Spell::EffectEnchantItemPerm, // 53 SPELL_EFFECT_ENCHANT_ITEM + &Spell::EffectEnchantItemTmp, // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY + &Spell::EffectTameCreature, // 55 SPELL_EFFECT_TAMECREATURE + &Spell::EffectSummonPet, // 56 SPELL_EFFECT_SUMMON_PET + &Spell::EffectLearnPetSpell, // 57 SPELL_EFFECT_LEARN_PET_SPELL + &Spell::EffectWeaponDmg, // 58 SPELL_EFFECT_WEAPON_DAMAGE + &Spell::EffectOpenSecretSafe, // 59 SPELL_EFFECT_OPEN_LOCK_ITEM + &Spell::EffectProficiency, // 60 SPELL_EFFECT_PROFICIENCY + &Spell::EffectSendEvent, // 61 SPELL_EFFECT_SEND_EVENT + &Spell::EffectPowerBurn, // 62 SPELL_EFFECT_POWER_BURN + &Spell::EffectThreat, // 63 SPELL_EFFECT_THREAT + &Spell::EffectTriggerSpell, // 64 SPELL_EFFECT_TRIGGER_SPELL + &Spell::EffectUnused, // 65 SPELL_EFFECT_HEALTH_FUNNEL unused + &Spell::EffectUnused, // 66 SPELL_EFFECT_POWER_FUNNEL unused + &Spell::EffectHealMaxHealth, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH + &Spell::EffectInterruptCast, // 68 SPELL_EFFECT_INTERRUPT_CAST + &Spell::EffectDistract, // 69 SPELL_EFFECT_DISTRACT + &Spell::EffectPull, // 70 SPELL_EFFECT_PULL one spell: Distract Move + &Spell::EffectPickPocket, // 71 SPELL_EFFECT_PICKPOCKET + &Spell::EffectAddFarsight, // 72 SPELL_EFFECT_ADD_FARSIGHT + &Spell::EffectSummonGuardian, // 73 SPELL_EFFECT_SUMMON_POSSESSED + &Spell::EffectSummonTotem, // 74 SPELL_EFFECT_SUMMON_TOTEM + &Spell::EffectHealMechanical, // 75 SPELL_EFFECT_HEAL_MECHANICAL one spell: Mechanical Patch Kit + &Spell::EffectSummonObjectWild, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD + &Spell::EffectScriptEffect, // 77 SPELL_EFFECT_SCRIPT_EFFECT + &Spell::EffectUnused, // 78 SPELL_EFFECT_ATTACK + &Spell::EffectSanctuary, // 79 SPELL_EFFECT_SANCTUARY + &Spell::EffectAddComboPoints, // 80 SPELL_EFFECT_ADD_COMBO_POINTS + &Spell::EffectUnused, // 81 SPELL_EFFECT_CREATE_HOUSE one spell: Create House (TEST) + &Spell::EffectNULL, // 82 SPELL_EFFECT_BIND_SIGHT + &Spell::EffectDuel, // 83 SPELL_EFFECT_DUEL + &Spell::EffectStuck, // 84 SPELL_EFFECT_STUCK + &Spell::EffectSummonPlayer, // 85 SPELL_EFFECT_SUMMON_PLAYER + &Spell::EffectActivateObject, // 86 SPELL_EFFECT_ACTIVATE_OBJECT + &Spell::EffectSummonTotem, // 87 SPELL_EFFECT_SUMMON_TOTEM_SLOT1 + &Spell::EffectSummonTotem, // 88 SPELL_EFFECT_SUMMON_TOTEM_SLOT2 + &Spell::EffectSummonTotem, // 89 SPELL_EFFECT_SUMMON_TOTEM_SLOT3 + &Spell::EffectSummonTotem, // 90 SPELL_EFFECT_SUMMON_TOTEM_SLOT4 + &Spell::EffectUnused, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash + &Spell::EffectEnchantHeldItem, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM + &Spell::EffectUnused, // 93 SPELL_EFFECT_SUMMON_PHANTASM + &Spell::EffectSelfResurrect, // 94 SPELL_EFFECT_SELF_RESURRECT + &Spell::EffectSkinning, // 95 SPELL_EFFECT_SKINNING + &Spell::EffectCharge, // 96 SPELL_EFFECT_CHARGE + &Spell::EffectSummonCritter, // 97 SPELL_EFFECT_SUMMON_CRITTER + &Spell::EffectKnockBack, // 98 SPELL_EFFECT_KNOCK_BACK + &Spell::EffectDisEnchant, // 99 SPELL_EFFECT_DISENCHANT + &Spell::EffectInebriate, //100 SPELL_EFFECT_INEBRIATE + &Spell::EffectFeedPet, //101 SPELL_EFFECT_FEED_PET + &Spell::EffectDismissPet, //102 SPELL_EFFECT_DISMISS_PET + &Spell::EffectReputation, //103 SPELL_EFFECT_REPUTATION + &Spell::EffectSummonObject, //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1 + &Spell::EffectSummonObject, //105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2 + &Spell::EffectSummonObject, //106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3 + &Spell::EffectSummonObject, //107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4 + &Spell::EffectDispelMechanic, //108 SPELL_EFFECT_DISPEL_MECHANIC + &Spell::EffectSummonDeadPet, //109 SPELL_EFFECT_SUMMON_DEAD_PET + &Spell::EffectDestroyAllTotems, //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS + &Spell::EffectDurabilityDamage, //111 SPELL_EFFECT_DURABILITY_DAMAGE + &Spell::EffectSummonDemon, //112 SPELL_EFFECT_SUMMON_DEMON + &Spell::EffectResurrectNew, //113 SPELL_EFFECT_RESURRECT_NEW + &Spell::EffectTaunt, //114 SPELL_EFFECT_ATTACK_ME + &Spell::EffectDurabilityDamagePCT, //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT + &Spell::EffectSkinPlayerCorpse, //116 SPELL_EFFECT_SKIN_PLAYER_CORPSE one spell: Remove Insignia, bg usage, required special corpse flags... + &Spell::EffectSpiritHeal, //117 SPELL_EFFECT_SPIRIT_HEAL one spell: Spirit Heal + &Spell::EffectSkill, //118 SPELL_EFFECT_SKILL professions and more + &Spell::EffectApplyAreaAura, //119 SPELL_EFFECT_APPLY_AREA_AURA_PET + &Spell::EffectUnused, //120 SPELL_EFFECT_TELEPORT_GRAVEYARD one spell: Graveyard Teleport Test + &Spell::EffectWeaponDmg, //121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG + &Spell::EffectUnused, //122 SPELL_EFFECT_122 unused + &Spell::EffectSendTaxi, //123 SPELL_EFFECT_SEND_TAXI taxi/flight related (misc value is taxi path id) + &Spell::EffectPlayerPull, //124 SPELL_EFFECT_PLAYER_PULL opposite of knockback effect (pulls player twoard caster) + &Spell::EffectModifyThreatPercent, //125 SPELL_EFFECT_MODIFY_THREAT_PERCENT + &Spell::EffectStealBeneficialBuff, //126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF spell steal effect? + &Spell::EffectProspecting, //127 SPELL_EFFECT_PROSPECTING Prospecting spell + &Spell::EffectApplyAreaAura, //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND + &Spell::EffectApplyAreaAura, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY + &Spell::EffectNULL, //130 SPELL_EFFECT_REDIRECT_THREAT + &Spell::EffectUnused, //131 SPELL_EFFECT_131 used in some test spells + &Spell::EffectNULL, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value + &Spell::EffectUnlearnSpecialization, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization + &Spell::EffectKillCredit, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry + &Spell::EffectNULL, //135 SPELL_EFFECT_CALL_PET + &Spell::EffectHealPct, //136 SPELL_EFFECT_HEAL_PCT + &Spell::EffectEnergisePct, //137 SPELL_EFFECT_ENERGIZE_PCT + &Spell::EffectNULL, //138 SPELL_EFFECT_138 Leap + &Spell::EffectUnused, //139 SPELL_EFFECT_139 unused + &Spell::EffectForceCast, //140 SPELL_EFFECT_FORCE_CAST + &Spell::EffectNULL, //141 SPELL_EFFECT_141 damage and reduce speed? + &Spell::EffectTriggerSpellWithValue, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE + &Spell::EffectApplyAreaAura, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER + &Spell::EffectNULL, //144 SPELL_EFFECT_144 Spectral Blast + &Spell::EffectNULL, //145 SPELL_EFFECT_145 Black Hole Effect + &Spell::EffectUnused, //146 SPELL_EFFECT_146 unused + &Spell::EffectQuestFail, //147 SPELL_EFFECT_QUEST_FAIL quest fail + &Spell::EffectUnused, //148 SPELL_EFFECT_148 unused + &Spell::EffectNULL, //149 SPELL_EFFECT_149 swoop + &Spell::EffectUnused, //150 SPELL_EFFECT_150 unused + &Spell::EffectTriggerRitualOfSummoning, //151 SPELL_EFFECT_TRIGGER_SPELL_2 + &Spell::EffectNULL, //152 SPELL_EFFECT_152 summon Refer-a-Friend + &Spell::EffectNULL, //153 SPELL_EFFECT_CREATE_PET misc value is creature entry +}; + +void Spell::EffectNULL(uint32 /*i*/) +{ + sLog.outDebug("WORLD: Spell Effect DUMMY"); +} + +void Spell::EffectUnused(uint32 /*i*/) +{ + // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN MANGOS +} + +void Spell::EffectResurrectNew(uint32 i) +{ + if(!unitTarget || unitTarget->isAlive()) + return; + + if(unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + if(!unitTarget->IsInWorld()) + return; + + Player* pTarget = ((Player*)unitTarget); + + if(pTarget->isRessurectRequested()) // already have one active request + return; + + uint32 health = damage; + uint32 mana = m_spellInfo->EffectMiscValue[i]; + pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana); + SendResurrectRequest(pTarget); +} + +void Spell::EffectInstaKill(uint32 /*i*/) +{ + if( !unitTarget || !unitTarget->isAlive() ) + return; + + // Demonic Sacrifice + if(m_spellInfo->Id==18788 && unitTarget->GetTypeId()==TYPEID_UNIT) + { + uint32 entry = unitTarget->GetEntry(); + uint32 spellID; + switch(entry) + { + case 416: spellID=18789; break; //imp + case 417: spellID=18792; break; //fellhunter + case 1860: spellID=18790; break; //void + case 1863: spellID=18791; break; //succubus + case 17252: spellID=35701; break; //fellguard + default: + sLog.outError("EffectInstaKill: Unhandled creature entry (%u) case.",entry); + return; + } + + m_caster->CastSpell(m_caster,spellID,true); + } + + if(m_caster==unitTarget) // prevent interrupt message + finish(); + + uint32 health = unitTarget->GetHealth(); + m_caster->DealDamage(unitTarget, health, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); +} + +void Spell::EffectEnvirinmentalDMG(uint32 i) +{ + uint32 absorb = 0; + uint32 resist = 0; + + // Note: this hack with damage replace required until GO casting not implemented + // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support + // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc + damage = m_spellInfo->EffectBasePoints[i]+m_spellInfo->EffectBaseDice[i]; + + m_caster->CalcAbsorbResist(m_caster,GetSpellSchoolMask(m_spellInfo), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist); + + m_caster->SendSpellNonMeleeDamageLog(m_caster, m_spellInfo->Id, damage, GetSpellSchoolMask(m_spellInfo), absorb, resist, false, 0, false); + if(m_caster->GetTypeId() == TYPEID_PLAYER) + ((Player*)m_caster)->EnvironmentalDamage(m_caster->GetGUID(),DAMAGE_FIRE,damage); +} + +void Spell::EffectSchoolDMG(uint32 effect_idx) +{ + if( unitTarget && unitTarget->isAlive()) + { + switch(m_spellInfo->SpellFamilyName) + { + case SPELLFAMILY_GENERIC: + { + //Gore + if(m_spellInfo->SpellIconID == 2269 ) + { + damage+= rand()%2 ? damage : 0; + } + + switch(m_spellInfo->Id) // better way to check unknown + { + // Meteor like spells (divided damage to targets) + case 24340: case 26558: case 28884: // Meteor + case 36837: case 38903: case 41276: // Meteor + case 26789: // Shard of the Fallen Star + case 31436: // Malevolent Cleave + case 35181: // Dive Bomb + case 40810: case 43267: case 43268: // Saber Lash + case 42384: // Brutal Swipe + case 45150: // Meteor Slash + { + uint32 count = 0; + for(std::list::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit) + if(ihit->effectMask & (1<GetHealth() / 2; + if(damage < 200) + damage = 200; + break; + } + } + break; + } + + case SPELLFAMILY_MAGE: + { + // Arcane Blast + if(m_spellInfo->SpellFamilyFlags & 0x20000000LL) + { + m_caster->CastSpell(m_caster,36032,true); + } + break; + } + case SPELLFAMILY_WARRIOR: + { + // Bloodthirst + if(m_spellInfo->SpellFamilyFlags & 0x40000000000LL) + { + damage = uint32(damage * (m_caster->GetTotalAttackPowerValue(BASE_ATTACK)) / 100); + } + // Shield Slam + else if(m_spellInfo->SpellFamilyFlags & 0x100000000LL) + damage += int32(m_caster->GetShieldBlockValue()); + // Victory Rush + else if(m_spellInfo->SpellFamilyFlags & 0x10000000000LL) + { + damage = uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100); + m_caster->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, false); + } + break; + } + case SPELLFAMILY_WARLOCK: + { + // Incinerate Rank 1 & 2 + if((m_spellInfo->SpellFamilyFlags & 0x00004000000000LL) && m_spellInfo->SpellIconID==2128) + { + // Incinerate does more dmg (dmg*0.25) if the target is Immolated. + if(unitTarget->HasAuraState(AURA_STATE_IMMOLATE)) + damage += int32(damage*0.25); + } + break; + } + case SPELLFAMILY_DRUID: + { + // Ferocious Bite + if((m_spellInfo->SpellFamilyFlags & 0x000800000) && m_spellInfo->SpellVisual==6587) + { + // converts each extra point of energy into ($f1+$AP/630) additional damage + float multiple = m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 630 + m_spellInfo->DmgMultiplier[effect_idx]; + damage += int32(m_caster->GetPower(POWER_ENERGY) * multiple); + m_caster->SetPower(POWER_ENERGY,0); + } + // Rake + else if(m_spellInfo->SpellFamilyFlags & 0x0000000000001000LL) + { + damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100); + } + // Swipe + else if(m_spellInfo->SpellFamilyFlags & 0x0010000000000000LL) + { + damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.08f); + } + // Starfire + else if ( m_spellInfo->SpellFamilyFlags & 0x0004LL ) + { + Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + for(Unit::AuraList::const_iterator i = m_OverrideClassScript.begin(); i != m_OverrideClassScript.end(); ++i) + { + // Starfire Bonus (caster) + switch((*i)->GetModifier()->m_miscvalue) + { + case 5481: // Nordrassil Regalia - bonus + { + Unit::AuraList const& m_periodicDamageAuras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); + for(Unit::AuraList::const_iterator itr = m_periodicDamageAuras.begin(); itr != m_periodicDamageAuras.end(); ++itr) + { + // Moonfire or Insect Swarm (target debuff from any casters) + if ( (*itr)->GetSpellProto()->SpellFamilyFlags & 0x00200002LL ) + { + int32 mod = (*i)->GetModifier()->m_amount; + damage += damage*mod/100; + break; + } + } + break; + } + case 5148: //Improved Starfire - Ivory Idol of the Moongoddes Aura + { + damage += (*i)->GetModifier()->m_amount; + break; + } + } + } + } + //Mangle Bonus for the initial damage of Lacerate and Rake + if((m_spellInfo->SpellFamilyFlags==0x0000000000001000LL && m_spellInfo->SpellIconID==494) || + (m_spellInfo->SpellFamilyFlags==0x0000010000000000LL && m_spellInfo->SpellIconID==2246)) + { + Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i) + if((*i)->GetSpellProto()->SpellFamilyFlags & 0x0000044000000000LL && (*i)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_DRUID) + { + damage = int32(damage*(100.0f+(*i)->GetModifier()->m_amount)/100.0f); + break; + } + } + break; + } + case SPELLFAMILY_ROGUE: + { + // Envenom + if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x800000000LL)) + { + // consume from stack dozes not more that have combo-points + if(uint32 combo = ((Player*)m_caster)->GetComboPoints()) + { + // count consumed deadly poison doses at target + uint32 doses = 0; + + // remove consumed poison doses + Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); + for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end() && combo;) + { + // Deadly poison (only attacker applied) + if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE && ((*itr)->GetSpellProto()->SpellFamilyFlags & 0x10000) && + (*itr)->GetSpellProto()->SpellVisual==5100 && (*itr)->GetCasterGUID()==m_caster->GetGUID() ) + { + --combo; + ++doses; + + unitTarget->RemoveSingleAuraFromStack((*itr)->GetId(), (*itr)->GetEffIndex()); + + itr = auras.begin(); + } + else + ++itr; + } + + damage *= doses; + damage += int32(((Player*)m_caster)->GetTotalAttackPowerValue(BASE_ATTACK) * 0.03f * doses); + + // Eviscerate and Envenom Bonus Damage (item set effect) + if(m_caster->GetDummyAura(37169)) + damage += ((Player*)m_caster)->GetComboPoints()*40; + } + } + // Eviscerate + else if((m_spellInfo->SpellFamilyFlags & 0x00020000LL) && m_caster->GetTypeId()==TYPEID_PLAYER) + { + if(uint32 combo = ((Player*)m_caster)->GetComboPoints()) + { + damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * combo * 0.03f); + + // Eviscerate and Envenom Bonus Damage (item set effect) + if(m_caster->GetDummyAura(37169)) + damage += combo*40; + } + } + break; + } + case SPELLFAMILY_HUNTER: + { + // Mongoose Bite + if((m_spellInfo->SpellFamilyFlags & 0x000000002) && m_spellInfo->SpellVisual==342) + { + damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2); + } + // Arcane Shot + else if((m_spellInfo->SpellFamilyFlags & 0x00000800) && m_spellInfo->maxLevel > 0) + { + damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.15); + } + // Steady Shot + else if(m_spellInfo->SpellFamilyFlags & 0x100000000LL) + { + int32 base = irand((int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MINDAMAGE),(int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MAXDAMAGE)); + damage += int32(float(base)/m_caster->GetAttackTime(RANGED_ATTACK)*2800 + m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.2f); + } + //Explosive Trap Effect + else if(m_spellInfo->SpellFamilyFlags & 0x00000004) + { + damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1); + } + break; + } + case SPELLFAMILY_PALADIN: + { + //Judgement of Vengeance + if((m_spellInfo->SpellFamilyFlags & 0x800000000LL) && m_spellInfo->SpellIconID==2292) + { + uint32 stacks = 0; + Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); + for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr) + if((*itr)->GetId() == 31803 && (*itr)->GetCasterGUID()==m_caster->GetGUID()) + ++stacks; + if(!stacks) + //No damage if the target isn't affected by this + damage = -1; + else + damage *= stacks; + } + break; + } + } + + if(damage >= 0) + { + uint32 finalDamage; + if(m_originalCaster) // m_caster only passive source of cast + finalDamage = m_originalCaster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage, m_IsTriggeredSpell, true); + else + finalDamage = m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage, m_IsTriggeredSpell, true); + + // post effects + switch(m_spellInfo->SpellFamilyName) + { + case SPELLFAMILY_WARRIOR: + { + // Bloodthirst + if(m_spellInfo->SpellFamilyFlags & 0x40000000000LL) + { + uint32 BTAura = 0; + switch(m_spellInfo->Id) + { + case 23881: BTAura = 23885; break; + case 23892: BTAura = 23886; break; + case 23893: BTAura = 23887; break; + case 23894: BTAura = 23888; break; + case 25251: BTAura = 25252; break; + case 30335: BTAura = 30339; break; + default: + sLog.outError("Spell::EffectSchoolDMG: Spell %u not handled in BTAura",m_spellInfo->Id); + break; + } + + if (BTAura) + m_caster->CastSpell(m_caster,BTAura,true); + } + break; + } + case SPELLFAMILY_PRIEST: + { + // Shadow Word: Death + if(finalDamage > 0 && (m_spellInfo->SpellFamilyFlags & 0x0000000200000000LL) && unitTarget->isAlive()) + // deals damage equal to damage done to caster if victim is not killed + m_caster->SpellNonMeleeDamageLog( m_caster, m_spellInfo->Id, finalDamage, m_IsTriggeredSpell, false); + + break; + } + case SPELLFAMILY_PALADIN: + { + // Judgement of Blood + if(finalDamage > 0 && (m_spellInfo->SpellFamilyFlags & 0x0000000800000000LL) && m_spellInfo->SpellIconID==153) + { + int32 damagePoint = finalDamage * 33 / 100; + m_caster->CastCustomSpell(m_caster, 32220, &damagePoint, NULL, NULL, true); + } + break; + } + } + } + } +} + +void Spell::EffectDummy(uint32 i) +{ + if(!unitTarget && !gameObjTarget && !itemTarget) + return; + + // selection by spell family + switch(m_spellInfo->SpellFamilyName) + { + case SPELLFAMILY_GENERIC: + // Gnomish Poultryizer trinket + switch(m_spellInfo->Id ) + { + case 8063: // Deviate Fish + { + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + uint32 spell_id = 0; + switch(urand(1,5)) + { + case 1: spell_id = 8064; break; // Sleepy + case 2: spell_id = 8065; break; // Invigorate + case 3: spell_id = 8066; break; // Shrink + case 4: spell_id = 8067; break; // Party Time! + case 5: spell_id = 8068; break; // Healthy Spirit + } + m_caster->CastSpell(m_caster,spell_id,true,NULL); + return; + } + case 8213: // Savory Deviate Delight + { + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + uint32 spell_id = 0; + switch(urand(1,2)) + { + // Flip Out - ninja + case 1: spell_id = (m_caster->getGender() == GENDER_MALE ? 8219 : 8220); break; + // Yaaarrrr - pirate + case 2: spell_id = (m_caster->getGender() == GENDER_MALE ? 8221 : 8222); break; + } + m_caster->CastSpell(m_caster,spell_id,true,NULL); + return; + } + case 8593: // Symbol of life (restore creature to life) + case 31225: // Shimmering Vessel (restore creature to life) + { + if(!unitTarget || unitTarget->GetTypeId()!=TYPEID_UNIT) + return; + ((Creature*)unitTarget)->setDeathState(JUST_ALIVED); + return; + } + case 12162: // Deep wounds + case 12850: // (now good common check for this spells) + case 12868: + { + if(!unitTarget) + return; + + float damage; + // DW should benefit of attack power, damage percent mods etc. + // TODO: check if using offhand damage is correct and if it should be divided by 2 + if (m_caster->haveOffhandWeapon() && m_caster->getAttackTimer(BASE_ATTACK) > m_caster->getAttackTimer(OFF_ATTACK)) + damage = (m_caster->GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE))/2; + else + damage = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE))/2; + + switch (m_spellInfo->Id) + { + case 12850: damage *= 0.2f; break; + case 12162: damage *= 0.4f; break; + case 12868: damage *= 0.6f; break; + default: + sLog.outError("Spell::EffectDummy: Spell %u not handled in DW",m_spellInfo->Id); + return; + }; + + int32 deepWoundsDotBasePoints0 = int32(damage / 4); + m_caster->CastCustomSpell(unitTarget, 12721, &deepWoundsDotBasePoints0, NULL, NULL, true, NULL); + return; + } + case 12975: //Last Stand + { + int32 healthModSpellBasePoints0 = int32(m_caster->GetMaxHealth()*0.3); + m_caster->CastCustomSpell(m_caster, 12976, &healthModSpellBasePoints0, NULL, NULL, true, NULL); + return; + } + case 13120: // net-o-matic + { + if(!unitTarget) + return; + + uint32 spell_id = 0; + + uint32 roll = urand(0, 99); + + if(roll < 2) // 2% for 30 sec self root (off-like chance unknown) + spell_id = 16566; + else if(roll < 4) // 2% for 20 sec root, charge to target (off-like chance unknown) + spell_id = 13119; + else // normal root + spell_id = 13099; + + m_caster->CastSpell(unitTarget,spell_id,true,NULL); + return; + } + case 13567: // Dummy Trigger + { + // can be used for different aura triggreing, so select by aura + if(!m_triggeredByAuraSpell || !unitTarget) + return; + + switch(m_triggeredByAuraSpell->Id) + { + case 26467: // Persistent Shield + m_caster->CastCustomSpell(unitTarget, 26470, &damage, NULL, NULL, true); + break; + default: + sLog.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u",m_triggeredByAuraSpell->Id); + break; + } + return; + } + case 14185: // Preparation Rogue + { + if(m_caster->GetTypeId()!=TYPEID_PLAYER) + return; + + //immediately finishes the cooldown on certain Rogue abilities + const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap(); + for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr) + { + uint32 classspell = itr->first; + SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell); + + if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & 0x26000000860LL)) + { + ((Player*)m_caster)->RemoveSpellCooldown(classspell); + + WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8)); + data << uint32(classspell); + data << uint64(m_caster->GetGUID()); + ((Player*)m_caster)->GetSession()->SendPacket(&data); + } + } + return; + } + case 15998: // Capture Worg Pup + case 29435: // Capture Female Kaliri Hatchling + { + if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT) + return; + + Creature* creatureTarget = (Creature*)unitTarget; + creatureTarget->setDeathState(JUST_DIED); + creatureTarget->RemoveCorpse(); + creatureTarget->SetHealth(0); // just for nice GM-mode view + return; + } + case 16589: // Noggenfogger Elixir + { + if(m_caster->GetTypeId()!=TYPEID_PLAYER) + return; + + uint32 spell_id = 0; + switch(urand(1,3)) + { + case 1: spell_id = 16595; break; + case 2: spell_id = 16593; break; + default:spell_id = 16591; break; + } + + m_caster->CastSpell(m_caster,spell_id,true,NULL); + return; + } + case 17251: // Spirit Healer Res + { + if(!unitTarget || !m_originalCaster) + return; + + if(m_originalCaster->GetTypeId() == TYPEID_PLAYER) + { + WorldPacket data(SMSG_SPIRIT_HEALER_CONFIRM, 8); + data << unitTarget->GetGUID(); + ((Player*)m_originalCaster)->GetSession()->SendPacket( &data ); + } + return; + } + case 17271: // Test Fetid Skull + { + if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER) + return; + + uint32 spell_id = roll_chance_i(50) ? 17269 : 17270; + + m_caster->CastSpell(m_caster,spell_id,true,NULL); + return; + } + case 20577: // Cannibalize + if (unitTarget) + m_caster->CastSpell(m_caster,20578,false,NULL); + return; + case 23019: // Crystal Prison Dummy DND + { + if(!unitTarget || !unitTarget->isAlive() || unitTarget->GetTypeId() != TYPEID_UNIT || ((Creature*)unitTarget)->isPet()) + return; + + Creature* creatureTarget = (Creature*)unitTarget; + if(creatureTarget->isPet()) + return; + + creatureTarget->setDeathState(JUST_DIED); + creatureTarget->RemoveCorpse(); + creatureTarget->SetHealth(0); // just for nice GM-mode view + + GameObject* pGameObj = new GameObject; + + Map *map = creatureTarget->GetMap(); + + if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), 179644, map, + creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(), + creatureTarget->GetOrientation(), 0, 0, 0, 0, 100, 1) ) + { + delete pGameObj; + return; + } + + pGameObj->SetRespawnTime(creatureTarget->GetRespawnTime()-time(NULL)); + pGameObj->SetOwnerGUID(m_caster->GetGUID() ); + pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() ); + pGameObj->SetSpellId(m_spellInfo->Id); + + DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy\n"); + map->Add(pGameObj); + + WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8); + data << uint64(pGameObj->GetGUID()); + m_caster->SendMessageToSet(&data,true); + + return; + } + case 23074: // Arc. Dragonling + if (!m_CastItem) return; + m_caster->CastSpell(m_caster,19804,true,m_CastItem); + return; + case 23075: // Mithril Mechanical Dragonling + if (!m_CastItem) return; + m_caster->CastSpell(m_caster,12749,true,m_CastItem); + return; + case 23076: // Mechanical Dragonling + if (!m_CastItem) return; + m_caster->CastSpell(m_caster,4073,true,m_CastItem); + return; + case 23133: // Gnomish Battle Chicken + if (!m_CastItem) return; + m_caster->CastSpell(m_caster,13166,true,m_CastItem); + return; + case 23448: // Ultrasafe Transporter: Gadgetzan - backfires + { + int32 r = irand(0, 119); + if ( r < 20 ) // 1/6 polymorph + m_caster->CastSpell(m_caster,23444,true); + else if ( r < 100 ) // 4/6 evil twin + m_caster->CastSpell(m_caster,23445,true); + else // 1/6 miss the target + m_caster->CastSpell(m_caster,36902,true); + return; + } + case 23453: // Ultrasafe Transporter: Gadgetzan + if ( roll_chance_i(50) ) // success + m_caster->CastSpell(m_caster,23441,true); + else // failure + m_caster->CastSpell(m_caster,23446,true); + return; + case 23645: // Hourglass Sand + m_caster->RemoveAurasDueToSpell(23170); + return; + case 23725: // Gift of Life (warrior bwl trinket) + m_caster->CastSpell(m_caster,23782,true); + m_caster->CastSpell(m_caster,23783,true); + return; + case 25860: // Reindeer Transformation + { + if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED)) + return; + + float flyspeed = m_caster->GetSpeedRate(MOVE_FLY); + float speed = m_caster->GetSpeedRate(MOVE_RUN); + + m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); + + //5 different spells used depending on mounted speed and if mount can fly or not + if (flyspeed >= 4.1f) + m_caster->CastSpell(m_caster, 44827, true); //310% flying Reindeer + else if (flyspeed >= 3.8f) + m_caster->CastSpell(m_caster, 44825, true); //280% flying Reindeer + else if (flyspeed >= 1.6f) + m_caster->CastSpell(m_caster, 44824, true); //60% flying Reindeer + else if (speed >= 2.0f) + m_caster->CastSpell(m_caster, 25859, true); //100% ground Reindeer + else + m_caster->CastSpell(m_caster, 25858, true); //60% ground Reindeer + + return; + } + //case 26074: // Holiday Cheer + // return; -- implemented at client side + case 28006: // Arcane Cloaking + { + if( unitTarget->GetTypeId() == TYPEID_PLAYER ) + m_caster->CastSpell(unitTarget,29294,true); + return; + } + case 28730: // Arcane Torrent (Mana) + { + int32 count = 0; + Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraList::const_iterator i = m_dummyAuras.begin(); i != m_dummyAuras.end(); ++i) + if ((*i)->GetId() == 28734) + ++count; + if (count) + { + m_caster->RemoveAurasDueToSpell(28734); + int32 bp = damage * count; + m_caster->CastCustomSpell(m_caster, 28733, &bp, NULL, NULL, true); + } + return; + } + case 29200: // Purify Helboar Meat + { + if( m_caster->GetTypeId() != TYPEID_PLAYER ) + return; + + uint32 spell_id = roll_chance_i(50) ? 29277 : 29278; + + m_caster->CastSpell(m_caster,spell_id,true,NULL); + return; + } + case 29858: // Soulshatter + if (unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT && unitTarget->IsHostileTo(m_caster)) + m_caster->CastSpell(unitTarget,32835,true); + return; + case 30458: // Nigh Invulnerability + if (!m_CastItem) return; + if(roll_chance_i(86)) // success + m_caster->CastSpell(m_caster, 30456, true, m_CastItem); + else // backfire in 14% casts + m_caster->CastSpell(m_caster, 30457, true, m_CastItem); + return; + case 30507: // Poultryizer + if (!m_CastItem) return; + if(roll_chance_i(80)) // success + m_caster->CastSpell(unitTarget, 30501, true, m_CastItem); + else // backfire 20% + m_caster->CastSpell(unitTarget, 30504, true, m_CastItem); + return; + case 33060: // Make a Wish + { + if(m_caster->GetTypeId()!=TYPEID_PLAYER) + return; + + uint32 spell_id = 0; + + switch(urand(1,5)) + { + case 1: spell_id = 33053; break; + case 2: spell_id = 33057; break; + case 3: spell_id = 33059; break; + case 4: spell_id = 33062; break; + case 5: spell_id = 33064; break; + } + + m_caster->CastSpell(m_caster,spell_id,true,NULL); + return; + } + case 35745: + { + uint32 spell_id; + switch(m_caster->GetAreaId()) + { + case 3900: spell_id = 35743; break; + case 3742: spell_id = 35744; break; + default: return; + } + + m_caster->CastSpell(m_caster,spell_id,true); + return; + } + case 37674: // Chaos Blast + if(unitTarget) + m_caster->CastSpell(unitTarget,37675,true); + return; + case 44875: // Complete Raptor Capture + { + if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT) + return; + + Creature* creatureTarget = (Creature*)unitTarget; + + creatureTarget->setDeathState(JUST_DIED); + creatureTarget->RemoveCorpse(); + creatureTarget->SetHealth(0); // just for nice GM-mode view + + //cast spell Raptor Capture Credit + m_caster->CastSpell(m_caster,42337,true,NULL); + return; + } + case 45030: // Impale Emissary + { + // Emissary of Hate Credit + m_caster->CastSpell(m_caster,45088,true); + return; + } + case 50243: // Teach Language + { + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + // spell has a 1/3 chance to trigger one of the below + if(roll_chance_i(66)) + return; + if(((Player*)m_caster)->GetTeam() == ALLIANCE) + { + // 1000001 - gnomish binary + m_caster->CastSpell(m_caster, 50242, true); + } + else + { + // 01001000 - goblin binary + m_caster->CastSpell(m_caster, 50246, true); + } + + return; + } + case 51582: //Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite) + { + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + if(BattleGround* bg = ((Player*)m_caster)->GetBattleGround()) + bg->EventPlayerDroppedFlag((Player*)m_caster); + + m_caster->CastSpell(m_caster, 30452, true, NULL); + return; + } + } + + //All IconID Check in there + switch(m_spellInfo->SpellIconID) + { + // Berserking (troll racial traits) + case 1661: + { + uint32 healthPerc = uint32((float(m_caster->GetHealth())/m_caster->GetMaxHealth())*100); + int32 melee_mod = 10; + if (healthPerc <= 40) + melee_mod = 30; + if (healthPerc < 100 && healthPerc > 40) + melee_mod = 10+(100-healthPerc)/3; + + int32 hasteModBasePoints0 = melee_mod; // (EffectBasePoints[0]+1)-1+(5-melee_mod) = (melee_mod-1+1)-1+5-melee_mod = 5-1 + int32 hasteModBasePoints1 = (5-melee_mod); + int32 hasteModBasePoints2 = 5; + + // FIXME: custom spell required this aura state by some unknown reason, we not need remove it anyway + m_caster->ModifyAuraState(AURA_STATE_BERSERKING,true); + m_caster->CastCustomSpell(m_caster,26635,&hasteModBasePoints0,&hasteModBasePoints1,&hasteModBasePoints2,true,NULL); + return; + } + } + break; + case SPELLFAMILY_MAGE: + switch(m_spellInfo->Id ) + { + case 11958: // Cold Snap + { + if(m_caster->GetTypeId()!=TYPEID_PLAYER) + return; + + // immediately finishes the cooldown on Frost spells + const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap(); + for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr) + { + if (itr->second->state == PLAYERSPELL_REMOVED) + continue; + + uint32 classspell = itr->first; + SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell); + + if( spellInfo->SpellFamilyName == SPELLFAMILY_MAGE && + (GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_FROST) && + spellInfo->Id != 11958 && GetSpellRecoveryTime(spellInfo) > 0 ) + { + ((Player*)m_caster)->RemoveSpellCooldown(classspell); + + WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8)); + data << uint32(classspell); + data << uint64(m_caster->GetGUID()); + ((Player*)m_caster)->GetSession()->SendPacket(&data); + } + } + return; + } + } + break; + case SPELLFAMILY_WARRIOR: + // Charge + if(m_spellInfo->SpellFamilyFlags & 0x1 && m_spellInfo->SpellVisual == 867) + { + int32 chargeBasePoints0 = damage; + m_caster->CastCustomSpell(m_caster,34846,&chargeBasePoints0,NULL,NULL,true); + return; + } + // Execute + if(m_spellInfo->SpellFamilyFlags & 0x20000000) + { + if(!unitTarget) + return; + + int32 basePoints0 = damage+int32(m_caster->GetPower(POWER_RAGE) * m_spellInfo->DmgMultiplier[i]); + m_caster->CastCustomSpell(unitTarget, 20647, &basePoints0, NULL, NULL, true, 0); + m_caster->SetPower(POWER_RAGE,0); + return; + } + if(m_spellInfo->Id==21977) //Warrior's Wrath + { + if(!unitTarget) + return; + + m_caster->CastSpell(unitTarget,21887,true); // spell mod + return; + } + break; + case SPELLFAMILY_WARLOCK: + //Life Tap (only it have this with dummy effect) + if (m_spellInfo->SpellFamilyFlags == 0x40000) + { + float cost = m_currentBasePoints[0]+1; + + if(Player* modOwner = m_caster->GetSpellModOwner()) + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, cost,this); + + int32 dmg = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(cost > 0 ? cost : 0), SPELL_DIRECT_DAMAGE); + + if(int32(m_caster->GetHealth()) > dmg) + { + // Shouldn't Appear in Combat Log + m_caster->ModifyHealth(-dmg); + + int32 mana = dmg; + + Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr) + { + // only Imp. Life Tap have this in combination with dummy aura + if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 208) + mana = ((*itr)->GetModifier()->m_amount + 100)* mana / 100; + } + + m_caster->CastCustomSpell(m_caster,31818,&mana,NULL,NULL,true,NULL); + + // Mana Feed + int32 manaFeedVal = m_caster->CalculateSpellDamage(m_spellInfo,1, m_spellInfo->EffectBasePoints[1],m_caster); + manaFeedVal = manaFeedVal * mana / 100; + if(manaFeedVal > 0) + m_caster->CastCustomSpell(m_caster,32553,&manaFeedVal,NULL,NULL,true,NULL); + } + else + SendCastResult(SPELL_FAILED_FIZZLE); + return; + } + break; + case SPELLFAMILY_PRIEST: + switch(m_spellInfo->Id ) + { + case 28598: // Touch of Weakness triggered spell + { + if(!unitTarget || !m_triggeredByAuraSpell) + return; + + uint32 spellid = 0; + switch(m_triggeredByAuraSpell->Id) + { + case 2652: spellid = 2943; break; // Rank 1 + case 19261: spellid = 19249; break; // Rank 2 + case 19262: spellid = 19251; break; // Rank 3 + case 19264: spellid = 19252; break; // Rank 4 + case 19265: spellid = 19253; break; // Rank 5 + case 19266: spellid = 19254; break; // Rank 6 + case 25461: spellid = 25460; break; // Rank 7 + default: + sLog.outError("Spell::EffectDummy: Spell 28598 triggered by unhandeled spell %u",m_triggeredByAuraSpell->Id); + return; + } + m_caster->CastSpell(unitTarget, spellid, true, NULL); + return; + } + } + break; + case SPELLFAMILY_DRUID: + switch(m_spellInfo->Id ) + { + case 5420: // Tree of Life passive + { + // Tree of Life area effect + int32 health_mod = int32(m_caster->GetStat(STAT_SPIRIT)/4); + m_caster->CastCustomSpell(m_caster,34123,&health_mod,NULL,NULL,true,NULL); + return; + } + } + break; + case SPELLFAMILY_ROGUE: + switch(m_spellInfo->Id ) + { + case 31231: // Cheat Death + { + m_caster->CastSpell(m_caster,45182,true); + return; + } + case 5938: // Shiv + { + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + Player *pCaster = ((Player*)m_caster); + + Item *item = pCaster->GetWeaponForAttack(OFF_ATTACK); + if(!item) + return; + + // all poison enchantments is temporary + uint32 enchant_id = item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT); + if(!enchant_id) + return; + + SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id); + if(!pEnchant) + return; + + for (int s=0;s<3;s++) + { + if(pEnchant->type[s]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL) + continue; + + SpellEntry const* combatEntry = sSpellStore.LookupEntry(pEnchant->spellid[s]); + if(!combatEntry || combatEntry->Dispel != DISPEL_POISON) + continue; + + m_caster->CastSpell(unitTarget, combatEntry, true, item); + } + + m_caster->CastSpell(unitTarget, 5940, true); + return; + } + } + break; + case SPELLFAMILY_HUNTER: + // Steady Shot + if(m_spellInfo->SpellFamilyFlags & 0x100000000LL) + { + if( !unitTarget || !unitTarget->isAlive()) + return; + + bool found = false; + + // check dazed affect + Unit::AuraList const& decSpeedList = unitTarget->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED); + for(Unit::AuraList::const_iterator iter = decSpeedList.begin(); iter != decSpeedList.end(); ++iter) + { + if((*iter)->GetSpellProto()->SpellIconID==15 && (*iter)->GetSpellProto()->Dispel==0) + { + found = true; + break; + } + } + + if(found) + m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage, m_IsTriggeredSpell, true); + return; + } + // Kill command + if(m_spellInfo->SpellFamilyFlags & 0x00080000000000LL) + { + if(m_caster->getClass()!=CLASS_HUNTER) + return; + + // clear hunter crit aura state + m_caster->ModifyAuraState(AURA_STATE_HUNTER_CRIT_STRIKE,false); + + // additional damage from pet to pet target + Pet* pet = m_caster->GetPet(); + if(!pet || !pet->getVictim()) + return; + + uint32 spell_id = 0; + switch (m_spellInfo->Id) + { + case 34026: spell_id = 34027; break; // rank 1 + default: + sLog.outError("Spell::EffectDummy: Spell %u not handled in KC",m_spellInfo->Id); + return; + } + + pet->CastSpell(pet->getVictim(), spell_id, true); + return; + } + + switch(m_spellInfo->Id) + { + case 23989: //Readiness talent + { + if(m_caster->GetTypeId()!=TYPEID_PLAYER) + return; + + //immediately finishes the cooldown for hunter abilities + const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap(); + for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr) + { + uint32 classspell = itr->first; + SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell); + + if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->Id != 23989 && GetSpellRecoveryTime(spellInfo) > 0 ) + { + ((Player*)m_caster)->RemoveSpellCooldown(classspell); + + WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8)); + data << uint32(classspell); + data << uint64(m_caster->GetGUID()); + ((Player*)m_caster)->GetSession()->SendPacket(&data); + } + } + return; + } + case 37506: // Scatter Shot + { + if (m_caster->GetTypeId()!=TYPEID_PLAYER) + return; + + // break Auto Shot and autohit + m_caster->InterruptSpell(CURRENT_AUTOREPEAT_SPELL); + m_caster->AttackStop(); + ((Player*)m_caster)->SendAttackSwingCancelAttack(); + return; + } + } + break; + case SPELLFAMILY_PALADIN: + switch(m_spellInfo->SpellIconID) + { + case 156: // Holy Shock + { + if(!unitTarget) + return; + + int hurt = 0; + int heal = 0; + + switch(m_spellInfo->Id) + { + case 20473: hurt = 25912; heal = 25914; break; + case 20929: hurt = 25911; heal = 25913; break; + case 20930: hurt = 25902; heal = 25903; break; + case 27174: hurt = 27176; heal = 27175; break; + case 33072: hurt = 33073; heal = 33074; break; + default: + sLog.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo->Id); + return; + } + + if(m_caster->IsFriendlyTo(unitTarget)) + m_caster->CastSpell(unitTarget, heal, true, 0); + else + m_caster->CastSpell(unitTarget, hurt, true, 0); + + return; + } + case 561: // Judgement of command + { + if(!unitTarget) + return; + + uint32 spell_id = m_currentBasePoints[i]+1; + SpellEntry const* spell_proto = sSpellStore.LookupEntry(spell_id); + if(!spell_proto) + return; + + if( !unitTarget->hasUnitState(UNIT_STAT_STUNDED) && m_caster->GetTypeId()==TYPEID_PLAYER) + { + // decreased damage (/2) for non-stunned target. + SpellModifier *mod = new SpellModifier; + mod->op = SPELLMOD_DAMAGE; + mod->value = -50; + mod->type = SPELLMOD_PCT; + mod->spellId = m_spellInfo->Id; + mod->effectId = i; + mod->lastAffected = NULL; + mod->mask = 0x0000020000000000LL; + mod->charges = 0; + + ((Player*)m_caster)->AddSpellMod(mod, true); + m_caster->CastSpell(unitTarget,spell_proto,true,NULL); + // mod deleted + ((Player*)m_caster)->AddSpellMod(mod, false); + } + else + m_caster->CastSpell(unitTarget,spell_proto,true,NULL); + + return; + } + } + + switch(m_spellInfo->Id) + { + case 31789: // Righteous Defense (step 1) + { + // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target) + + // non-standard cast requirement check + if (!unitTarget || unitTarget->getAttackers().empty()) + { + // clear cooldown at fail + if(m_caster->GetTypeId()==TYPEID_PLAYER) + { + ((Player*)m_caster)->RemoveSpellCooldown(m_spellInfo->Id); + + WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8)); + data << uint32(m_spellInfo->Id); + data << uint64(m_caster->GetGUID()); + ((Player*)m_caster)->GetSession()->SendPacket(&data); + } + + SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT); + return; + } + + // Righteous Defense (step 2) (in old version 31980 dummy effect) + // Clear targets for eff 1 + for(std::list::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit) + ihit->effectMask &= ~(1<<1); + + // not empty (checked) + Unit::AttackerSet const& attackers = unitTarget->getAttackers(); + + // chance to be selected from list + float chance = 100.0f/attackers.size(); + uint32 count=0; + for(Unit::AttackerSet::const_iterator aItr = attackers.begin(); aItr != attackers.end() && count < 3; ++aItr) + { + if(!roll_chance_f(chance)) + continue; + ++count; + AddUnitTarget((*aItr), 1); + } + + // now let next effect cast spell at each target. + return; + } + case 37877: // Blessing of Faith + { + if(!unitTarget) + return; + + uint32 spell_id = 0; + switch(unitTarget->getClass()) + { + case CLASS_DRUID: spell_id = 37878; break; + case CLASS_PALADIN: spell_id = 37879; break; + case CLASS_PRIEST: spell_id = 37880; break; + case CLASS_SHAMAN: spell_id = 37881; break; + default: return; // ignore for not healing classes + } + + m_caster->CastSpell(m_caster,spell_id,true); + return; + } + } + break; + case SPELLFAMILY_SHAMAN: + //Shaman Rockbiter Weapon + if (m_spellInfo->SpellFamilyFlags == 0x400000) + { + uint32 spell_id = 0; + switch(m_spellInfo->Id) + { + case 8017: spell_id = 36494; break; // Rank 1 + case 8018: spell_id = 36750; break; // Rank 2 + case 8019: spell_id = 36755; break; // Rank 3 + case 10399: spell_id = 36759; break; // Rank 4 + case 16314: spell_id = 36763; break; // Rank 5 + case 16315: spell_id = 36766; break; // Rank 6 + case 16316: spell_id = 36771; break; // Rank 7 + case 25479: spell_id = 36775; break; // Rank 8 + case 25485: spell_id = 36499; break; // Rank 9 + default: + sLog.outError("Spell::EffectDummy: Spell %u not handled in RW",m_spellInfo->Id); + return; + } + + SpellEntry const *spellInfo = sSpellStore.LookupEntry( spell_id ); + + if(!spellInfo) + { + sLog.outError("WORLD: unknown spell id %i\n", spell_id); + return; + } + + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + for(int i = BASE_ATTACK; i <= OFF_ATTACK; ++i) + { + if(Item* item = ((Player*)m_caster)->GetWeaponForAttack(WeaponAttackType(i))) + { + if(item->IsFitToSpellRequirements(m_spellInfo)) + { + Spell *spell = new Spell(m_caster, spellInfo, true); + + // enchanting spell selected by calculated damage-per-sec in enchanting effect + // at calculation applied affect from Elemental Weapons talent + // real enchantment damage-1 + spell->m_currentBasePoints[1] = damage-1; + + SpellCastTargets targets; + targets.setItemTarget( item ); + spell->prepare(&targets); + } + } + } + return; + } + + if(m_spellInfo->Id == 39610) // Mana-Tide Totem effect + { + if(!unitTarget || unitTarget->getPowerType() != POWER_MANA) + return; + + // Regenerate 6% of Total Mana Every 3 secs + int32 EffectBasePoints0 = unitTarget->GetMaxPower(POWER_MANA) * damage / 100; + m_caster->CastCustomSpell(unitTarget,39609,&EffectBasePoints0,NULL,NULL,true,NULL,NULL,m_originalCasterGUID); + return; + } + + break; + } + + // pet auras + if(PetAura const* petSpell = spellmgr.GetPetAura(m_spellInfo->Id)) + { + m_caster->AddPetAura(petSpell); + return; + } +} + +void Spell::EffectTriggerSpellWithValue(uint32 i) +{ + uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i]; + + // normal case + SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id ); + + if(!spellInfo) + { + sLog.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i\n", m_spellInfo->Id,triggered_spell_id); + return; + } + + int32 bp = damage; + m_caster->CastCustomSpell(unitTarget,triggered_spell_id,&bp,&bp,&bp,true,NULL,NULL,m_originalCasterGUID); +} + +void Spell::EffectTriggerRitualOfSummoning(uint32 i) +{ + uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i]; + SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id ); + + if(!spellInfo) + { + sLog.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id); + return; + } + + finish(); + Spell *spell = new Spell(m_caster, spellInfo, true); + + SpellCastTargets targets; + targets.setUnitTarget( unitTarget); + spell->prepare(&targets); + + m_caster->SetCurrentCastedSpell(spell); + spell->m_selfContainer = &(m_caster->m_currentSpells[spell->GetCurrentContainer()]); + +} + +void Spell::EffectForceCast(uint32 i) +{ + if( !unitTarget ) + return; + + uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i]; + + // normal case + SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id ); + + if(!spellInfo) + { + sLog.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id); + return; + } + + unitTarget->CastSpell(unitTarget,spellInfo,true,NULL,NULL,m_originalCasterGUID); +} + +void Spell::EffectTriggerSpell(uint32 i) +{ + uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i]; + + // special cases + switch(triggered_spell_id) + { + // Vanish + case 18461: + { + m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT); + m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED); + m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED); + + // if this spell is given to NPC it must handle rest by it's own AI + if ( m_caster->GetTypeId() != TYPEID_PLAYER ) + return; + + // get highest rank of the Stealth spell + uint32 spellId = 0; + const PlayerSpellMap& sp_list = ((Player*)m_caster)->GetSpellMap(); + for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr) + { + // only highest rank is shown in spell book, so simply check if shown in spell book + if(!itr->second->active || itr->second->disabled || itr->second->state == PLAYERSPELL_REMOVED) + continue; + + SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first); + if (!spellInfo) + continue; + + if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_STEALTH) + { + spellId = spellInfo->Id; + break; + } + } + + // no Stealth spell found + if (!spellId) + return; + + // reset cooldown on it if needed + if(((Player*)m_caster)->HasSpellCooldown(spellId)) + ((Player*)m_caster)->RemoveSpellCooldown(spellId); + + m_caster->CastSpell(m_caster, spellId, true); + return; + } + // just skip + case 23770: // Sayge's Dark Fortune of * + // not exist, common cooldown can be implemented in scripts if need. + return; + // Brittle Armor - (need add max stack of 24575 Brittle Armor) + case 29284: + { + const SpellEntry *spell = sSpellStore.LookupEntry(24575); + if (!spell) + return; + + for (int i=0; i < spell->StackAmount; ++i) + m_caster->CastSpell(unitTarget,spell->Id, true, m_CastItem, NULL, m_originalCasterGUID); + return; + } + // Mercurial Shield - (need add max stack of 26464 Mercurial Shield) + case 29286: + { + const SpellEntry *spell = sSpellStore.LookupEntry(26464); + if (!spell) + return; + + for (int i=0; i < spell->StackAmount; ++i) + m_caster->CastSpell(unitTarget,spell->Id, true, m_CastItem, NULL, m_originalCasterGUID); + return; + } + // Righteous Defense + case 31980: + { + m_caster->CastSpell(unitTarget, 31790, true,m_CastItem,NULL,m_originalCasterGUID); + return; + } + // Cloak of Shadows + case 35729 : + { + Unit::AuraMap& Auras = m_caster->GetAuras(); + for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end(); ++iter) + { + // remove all harmful spells on you... + if( // ignore positive and passive auras + !iter->second->IsPositive() && !iter->second->IsPassive() && + // ignore physical auras + (GetSpellSchoolMask(iter->second->GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL)==0 && + // ignore immunity persistent spells + !( iter->second->GetSpellProto()->AttributesEx & 0x10000 ) ) + { + m_caster->RemoveAurasDueToSpell(iter->second->GetSpellProto()->Id); + iter = Auras.begin(); + } + } + return; + } + // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet + case 41967: + { + if (Unit *pet = m_caster->GetPet()) + pet->CastSpell(pet, 28305, true); + return; + } + } + + // normal case + SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id ); + + if(!spellInfo) + { + sLog.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id); + return; + } + + // some triggered spells require specific equipment + if(spellInfo->EquippedItemClass >=0 && m_caster->GetTypeId()==TYPEID_PLAYER) + { + // main hand weapon required + if(spellInfo->AttributesEx3 & SPELL_ATTR_EX3_MAIN_HAND) + { + Item* item = ((Player*)m_caster)->GetWeaponForAttack(BASE_ATTACK); + + // skip spell if no weapon in slot or broken + if(!item || item->IsBroken() ) + return; + + // skip spell if weapon not fit to triggered spell + if(!item->IsFitToSpellRequirements(spellInfo)) + return; + } + + // offhand hand weapon required + if(spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQ_OFFHAND) + { + Item* item = ((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK); + + // skip spell if no weapon in slot or broken + if(!item || item->IsBroken() ) + return; + + // skip spell if weapon not fit to triggered spell + if(!item->IsFitToSpellRequirements(spellInfo)) + return; + } + } + + // some triggered spells must be casted instantly (for example, if next effect case instant kill caster) + bool instant = false; + for(uint32 j = i+1; j < 3; ++j) + { + if(m_spellInfo->Effect[j]==SPELL_EFFECT_INSTAKILL && m_spellInfo->EffectImplicitTargetA[j]==TARGET_SELF) + { + instant = true; + break; + } + } + + if(instant) + { + if (unitTarget) + m_caster->CastSpell(unitTarget,spellInfo,true,m_CastItem,NULL,m_originalCasterGUID); + } + else + m_TriggerSpells.push_back(spellInfo); +} + +void Spell::EffectTriggerMissileSpell(uint32 effect_idx) +{ + uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[effect_idx]; + + // normal case + SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id ); + + if(!spellInfo) + { + sLog.outError("EffectTriggerMissileSpell of spell %u: triggering unknown spell id %effect_idx", m_spellInfo->Id,triggered_spell_id); + return; + } + + if (m_CastItem) + DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id); + + Spell *spell = new Spell(m_caster, spellInfo, true, m_originalCasterGUID ); + + SpellCastTargets targets; + targets.setDestination(m_targets.m_destX,m_targets.m_destY,m_targets.m_destZ); + spell->m_CastItem = m_CastItem; + spell->prepare(&targets, NULL); +} + +void Spell::EffectTeleportUnits(uint32 i) +{ + if(!unitTarget || unitTarget->isInFlight()) + return; + + switch (m_spellInfo->EffectImplicitTargetB[i]) + { + case TARGET_INNKEEPER_COORDINATES: + { + // Only players can teleport to innkeeper + if (unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + ((Player*)unitTarget)->TeleportTo(((Player*)unitTarget)->m_homebindMapId,((Player*)unitTarget)->m_homebindX,((Player*)unitTarget)->m_homebindY,((Player*)unitTarget)->m_homebindZ,unitTarget->GetOrientation(),unitTarget==m_caster ? TELE_TO_SPELL : 0); + return; + } + case TARGET_TABLE_X_Y_Z_COORDINATES: + { + // TODO: Only players can teleport? + if (unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id); + if(!st) + { + sLog.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u\n", m_spellInfo->Id ); + return; + } + ((Player*)unitTarget)->TeleportTo(st->target_mapId,st->target_X,st->target_Y,st->target_Z,st->target_Orientation,unitTarget==m_caster ? TELE_TO_SPELL : 0); + break; + } + case TARGET_BEHIND_VICTIM: + { + // Get selected target for player (or victim for units) + Unit *pTarget = NULL; + if(m_caster->GetTypeId() == TYPEID_PLAYER) + pTarget = ObjectAccessor::GetUnit(*m_caster, ((Player*)m_caster)->GetSelection()); + else + pTarget = m_caster->getVictim(); + // No target present - return + if (!pTarget) + return; + // Init dest coordinates + uint32 mapid = m_caster->GetMapId(); + float x = m_targets.m_destX; + float y = m_targets.m_destY; + float z = m_targets.m_destZ; + float orientation = pTarget->GetOrientation(); + // Teleport + if(unitTarget->GetTypeId() == TYPEID_PLAYER) + ((Player*)unitTarget)->TeleportTo(mapid, x, y, z, orientation, TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0)); + else + { + MapManager::Instance().GetMap(mapid, m_caster)->CreatureRelocation((Creature*)unitTarget, x, y, z, orientation); + WorldPacket data; + unitTarget->BuildTeleportAckMsg(&data, x, y, z, orientation); + unitTarget->SendMessageToSet(&data, false); + } + return; + } + default: + { + // If not exist data for dest location - return + if(!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)) + { + sLog.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u\n", i, m_spellInfo->EffectImplicitTargetB[i], m_spellInfo->Id ); + return; + } + // Init dest coordinates + uint32 mapid = m_caster->GetMapId(); + float x = m_targets.m_destX; + float y = m_targets.m_destY; + float z = m_targets.m_destZ; + float orientation = unitTarget->GetOrientation(); + // Teleport + if(unitTarget->GetTypeId() == TYPEID_PLAYER) + ((Player*)unitTarget)->TeleportTo(mapid, x, y, z, orientation, TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0)); + else + { + MapManager::Instance().GetMap(mapid, m_caster)->CreatureRelocation((Creature*)unitTarget, x, y, z, orientation); + WorldPacket data; + unitTarget->BuildTeleportAckMsg(&data, x, y, z, orientation); + unitTarget->SendMessageToSet(&data, false); + } + return; + } + } + + // post effects for TARGET_TABLE_X_Y_Z_COORDINATES + switch ( m_spellInfo->Id ) + { + // Dimensional Ripper - Everlook + case 23442: + { + int32 r = irand(0, 119); + if ( r >= 70 ) // 7/12 success + { + if ( r < 100 ) // 4/12 evil twin + m_caster->CastSpell(m_caster,23445,true); + else // 1/12 fire + m_caster->CastSpell(m_caster,23449,true); + } + return; + } + // Ultrasafe Transporter: Toshley's Station + case 36941: + { + if ( roll_chance_i(50) ) // 50% success + { + int32 rand_eff = urand(1,7); + switch ( rand_eff ) + { + case 1: + // soul split - evil + m_caster->CastSpell(m_caster,36900,true); + break; + case 2: + // soul split - good + m_caster->CastSpell(m_caster,36901,true); + break; + case 3: + // Increase the size + m_caster->CastSpell(m_caster,36895,true); + break; + case 4: + // Decrease the size + m_caster->CastSpell(m_caster,36893,true); + break; + case 5: + // Transform + { + if (((Player*)m_caster)->GetTeam() == ALLIANCE ) + m_caster->CastSpell(m_caster,36897,true); + else + m_caster->CastSpell(m_caster,36899,true); + break; + } + case 6: + // chicken + m_caster->CastSpell(m_caster,36940,true); + break; + case 7: + // evil twin + m_caster->CastSpell(m_caster,23445,true); + break; + } + } + return; + } + // Dimensional Ripper - Area 52 + case 36890: + { + if ( roll_chance_i(50) ) // 50% success + { + int32 rand_eff = urand(1,4); + switch ( rand_eff ) + { + case 1: + // soul split - evil + m_caster->CastSpell(m_caster,36900,true); + break; + case 2: + // soul split - good + m_caster->CastSpell(m_caster,36901,true); + break; + case 3: + // Increase the size + m_caster->CastSpell(m_caster,36895,true); + break; + case 4: + // Transform + { + if (((Player*)m_caster)->GetTeam() == ALLIANCE ) + m_caster->CastSpell(m_caster,36897,true); + else + m_caster->CastSpell(m_caster,36899,true); + break; + } + } + } + return; + } + } +} + +void Spell::EffectApplyAura(uint32 i) +{ + if(!unitTarget) + return; + + SpellImmuneList const& list = unitTarget->m_spellImmune[IMMUNITY_STATE]; + for(SpellImmuneList::const_iterator itr = list.begin(); itr != list.end(); ++itr) + if(itr->type == m_spellInfo->EffectApplyAuraName[i]) + return; + + // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load) + if( !unitTarget->isAlive() && m_spellInfo->Id != 20584 && m_spellInfo->Id != 8326 && + (unitTarget->GetTypeId()!=TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) ) + return; + + Unit* caster = m_originalCasterGUID ? m_originalCaster : m_caster; + if(!caster) + return; + + sLog.outDebug("Spell: Aura is: %u", m_spellInfo->EffectApplyAuraName[i]); + + Aura* Aur = CreateAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, caster, m_CastItem); + + // Now Reduce spell duration using data received at spell hit + int32 duration = Aur->GetAuraMaxDuration(); + unitTarget->ApplyDiminishingToDuration(m_diminishGroup,duration,m_caster,m_diminishLevel); + Aur->setDiminishGroup(m_diminishGroup); + + // if Aura removed and deleted, do not continue. + if(duration== 0 && !(Aur->IsPermanent())) + { + delete Aur; + return; + } + + if(duration != Aur->GetAuraMaxDuration()) + { + Aur->SetAuraMaxDuration(duration); + Aur->SetAuraDuration(duration); + } + + bool added = unitTarget->AddAura(Aur); + + // Aura not added and deleted in AddAura call; + if (!added) + return; + + // found crash at character loading, broken pointer to Aur... + // Aur was deleted in AddAura()... + if(!Aur) + return; + + // TODO Make a way so it works for every related spell! + if(unitTarget->GetTypeId()==TYPEID_PLAYER) // Negative buff should only be applied on players + { + uint32 spellId = 0; + if(m_spellInfo->CasterAuraStateNot==AURA_STATE_WEAKENED_SOUL || m_spellInfo->TargetAuraStateNot==AURA_STATE_WEAKENED_SOUL) + spellId = 6788; // Weakened Soul + else if(m_spellInfo->CasterAuraStateNot==AURA_STATE_FORBEARANCE || m_spellInfo->TargetAuraStateNot==AURA_STATE_FORBEARANCE) + spellId = 25771; // Forbearance + else if(m_spellInfo->CasterAuraStateNot==AURA_STATE_HYPOTHERMIA) + spellId = 41425; // Hypothermia + else if (m_spellInfo->Mechanic == MECHANIC_BANDAGE) // Bandages + spellId = 11196; // Recently Bandaged + else if( (m_spellInfo->AttributesEx & 0x20) && (m_spellInfo->AttributesEx2 & 0x20000) ) + spellId = 23230; // Blood Fury - Healing Reduction + + SpellEntry const *AdditionalSpellInfo = sSpellStore.LookupEntry(spellId); + if (AdditionalSpellInfo) + { + // applied at target by target + Aura* AdditionalAura = CreateAura(AdditionalSpellInfo, 0, &m_currentBasePoints[0], unitTarget,unitTarget, 0); + unitTarget->AddAura(AdditionalAura); + sLog.outDebug("Spell: Additional Aura is: %u", AdditionalSpellInfo->EffectApplyAuraName[0]); + } + } + + // Prayer of Mending (jump animation), we need formal caster instead original for correct animation + if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (m_spellInfo->SpellFamilyFlags & 0x00002000000000LL)) + m_caster->CastSpell(unitTarget,41637,true,NULL,Aur); +} + +void Spell::EffectUnlearnSpecialization( uint32 i ) +{ + if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + Player *_player = (Player*)unitTarget; + uint32 spellToUnlearn = m_spellInfo->EffectTriggerSpell[i]; + + _player->removeSpell(spellToUnlearn); + + sLog.outDebug( "Spell: Player %u have unlearned spell %u from NpcGUID: %u", _player->GetGUIDLow(), spellToUnlearn, m_caster->GetGUIDLow() ); +} + +void Spell::EffectPowerDrain(uint32 i) +{ + if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS) + return; + + Powers drain_power = Powers(m_spellInfo->EffectMiscValue[i]); + + if(!unitTarget) + return; + if(!unitTarget->isAlive()) + return; + if(unitTarget->getPowerType() != drain_power) + return; + if(damage < 0) + return; + + uint32 curPower = unitTarget->GetPower(drain_power); + + //add spell damage bonus + damage=m_caster->SpellDamageBonus(unitTarget,m_spellInfo,uint32(damage),SPELL_DIRECT_DAMAGE); + + // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4) + uint32 power = damage; + if ( drain_power == POWER_MANA && unitTarget->GetTypeId() == TYPEID_PLAYER ) + power -= ((Player*)unitTarget)->GetSpellCritDamageReduction(power); + + int32 new_damage; + if(curPower < power) + new_damage = curPower; + else + new_damage = power; + + unitTarget->ModifyPower(drain_power,-new_damage); + + if(drain_power == POWER_MANA) + { + float manaMultiplier = m_spellInfo->EffectMultipleValue[i]; + if(manaMultiplier==0) + manaMultiplier = 1; + + if(Player *modOwner = m_caster->GetSpellModOwner()) + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, manaMultiplier); + + int32 gain = int32(new_damage*manaMultiplier); + + m_caster->ModifyPower(POWER_MANA,gain); + //send log + m_caster->SendEnergizeSpellLog(m_caster, m_spellInfo->Id,gain,POWER_MANA,false); + } +} + +void Spell::EffectSendEvent(uint32 EffectIndex) +{ + if (m_caster->GetTypeId() == TYPEID_PLAYER && ((Player*)m_caster)->InBattleGround()) + { + BattleGround* bg = ((Player *)m_caster)->GetBattleGround(); + if(bg && bg->GetStatus() == STATUS_IN_PROGRESS) + { + switch(m_spellInfo->Id) + { + case 23333: // Pickup Horde Flag + /*do not uncomment . + if(bg->GetTypeID()==BATTLEGROUND_WS) + bg->EventPlayerClickedOnFlag((Player*)m_caster, this->gameObjTarget); + sLog.outDebug("Send Event Horde Flag Picked Up"); + break; + /* not used : + case 23334: // Drop Horde Flag + if(bg->GetTypeID()==BATTLEGROUND_WS) + bg->EventPlayerDroppedFlag((Player*)m_caster); + sLog.outDebug("Drop Horde Flag"); + break; + */ + case 23335: // Pickup Alliance Flag + /*do not uncomment ... (it will cause crash, because of null targetobject!) anyway this is a bad way to call that event, because it would cause recursion + if(bg->GetTypeID()==BATTLEGROUND_WS) + bg->EventPlayerClickedOnFlag((Player*)m_caster, this->gameObjTarget); + sLog.outDebug("Send Event Alliance Flag Picked Up"); + break; + /* not used : + case 23336: // Drop Alliance Flag + if(bg->GetTypeID()==BATTLEGROUND_WS) + bg->EventPlayerDroppedFlag((Player*)m_caster); + sLog.outDebug("Drop Alliance Flag"); + break; + case 23385: // Alliance Flag Returns + if(bg->GetTypeID()==BATTLEGROUND_WS) + bg->EventPlayerClickedOnFlag((Player*)m_caster, this->gameObjTarget); + sLog.outDebug("Alliance Flag Returned"); + break; + case 23386: // Horde Flag Returns + if(bg->GetTypeID()==BATTLEGROUND_WS) + bg->EventPlayerClickedOnFlag((Player*)m_caster, this->gameObjTarget); + sLog.outDebug("Horde Flag Returned"); + break;*/ + case 34976: + /* + if(bg->GetTypeID()==BATTLEGROUND_EY) + bg->EventPlayerClickedOnFlag((Player*)m_caster, this->gameObjTarget); + */ + break; + default: + sLog.outDebug("Unknown spellid %u in BG event", m_spellInfo->Id); + break; + } + } + } + sLog.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo->EffectMiscValue[EffectIndex], m_spellInfo->Id); + sWorld.ScriptsStart(sEventScripts, m_spellInfo->EffectMiscValue[EffectIndex], m_caster, focusObject); +} + +void Spell::EffectPowerBurn(uint32 i) +{ + if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS) + return; + + Powers powertype = Powers(m_spellInfo->EffectMiscValue[i]); + + if(!unitTarget) + return; + if(!unitTarget->isAlive()) + return; + if(unitTarget->getPowerType()!=powertype) + return; + if(damage < 0) + return; + + int32 curPower = int32(unitTarget->GetPower(powertype)); + + // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4) + uint32 power = damage; + if ( powertype == POWER_MANA && unitTarget->GetTypeId() == TYPEID_PLAYER ) + power -= ((Player*)unitTarget)->GetSpellCritDamageReduction(power); + + int32 new_damage = (curPower < power) ? curPower : power; + + unitTarget->ModifyPower(powertype,-new_damage); + float multiplier = m_spellInfo->EffectMultipleValue[i]; + + if(Player *modOwner = m_caster->GetSpellModOwner()) + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier); + + new_damage = int32(new_damage*multiplier); + m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, new_damage, m_IsTriggeredSpell, true); +} + +void Spell::EffectHeal( uint32 /*i*/ ) +{ + if( unitTarget && unitTarget->isAlive() && damage >= 0) + { + // Try to get original caster + Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster; + + // Skip if m_originalCaster not available + if (!caster) + return; + + int32 addhealth = damage; + + // Vessel of the Naaru (Vial of the Sunwell trinket) + if (m_spellInfo->Id == 45064) + { + // Amount of heal - depends from stacked Holy Energy + int damageAmount = 0; + Unit::AuraList const& mDummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i) + if((*i)->GetId() == 45062) + damageAmount+=(*i)->GetModifier()->m_amount; + if (damageAmount) + m_caster->RemoveAurasDueToSpell(45062); + + addhealth += damageAmount; + } + // Swiftmend - consumes Regrowth or Rejuvenation + else if (m_spellInfo->TargetAuraState == AURA_STATE_SWIFTMEND && unitTarget->HasAuraState(AURA_STATE_SWIFTMEND)) + { + Unit::AuraList const& RejorRegr = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_HEAL); + // find most short by duration + Aura *targetAura = NULL; + for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i) + { + if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID + && ((*i)->GetSpellProto()->SpellFamilyFlags == 0x40 || (*i)->GetSpellProto()->SpellFamilyFlags == 0x10) ) + { + if(!targetAura || (*i)->GetAuraDuration() < targetAura->GetAuraDuration()) + targetAura = *i; + } + } + + if(!targetAura) + { + sLog.outError("Target(GUID:" I64FMTD ") has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget->GetGUID()); + return; + } + int idx = 0; + while(idx < 3) + { + if(targetAura->GetSpellProto()->EffectApplyAuraName[idx] == SPELL_AURA_PERIODIC_HEAL) + break; + idx++; + } + + int32 tickheal = caster->SpellHealingBonus(targetAura->GetSpellProto(), targetAura->GetModifier()->m_amount, DOT, unitTarget); + int32 tickcount = GetSpellDuration(targetAura->GetSpellProto()) / targetAura->GetSpellProto()->EffectAmplitude[idx]; + unitTarget->RemoveAurasDueToSpell(targetAura->GetId()); + + addhealth += tickheal * tickcount; + } + else + addhealth = caster->SpellHealingBonus(m_spellInfo, addhealth,HEAL, unitTarget); + + bool crit = caster->isSpellCrit(unitTarget, m_spellInfo, m_spellSchoolMask, m_attackType); + if (crit) + addhealth = caster->SpellCriticalBonus(m_spellInfo, addhealth, unitTarget); + caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, crit); + + int32 gain = unitTarget->ModifyHealth( int32(addhealth) ); + unitTarget->getHostilRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo); + + if(caster->GetTypeId()==TYPEID_PLAYER) + if(BattleGround *bg = ((Player*)caster)->GetBattleGround()) + bg->UpdatePlayerScore(((Player*)caster), SCORE_HEALING_DONE, gain); + + // ignore item heals + if(m_CastItem) + return; + + uint32 procHealer = PROC_FLAG_HEAL; + if (crit) + procHealer |= PROC_FLAG_CRIT_HEAL; + + m_caster->ProcDamageAndSpell(unitTarget,procHealer,PROC_FLAG_HEALED,addhealth,SPELL_SCHOOL_MASK_NONE,m_spellInfo,m_IsTriggeredSpell); + } +} + +void Spell::EffectHealPct( uint32 /*i*/ ) +{ + if( unitTarget && unitTarget->isAlive() && damage >= 0) + { + // Try to get original caster + Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster; + + // Skip if m_originalCaster not available + if (!caster) + return; + + uint32 addhealth = unitTarget->GetMaxHealth() * damage / 100; + caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false); + + int32 gain = unitTarget->ModifyHealth( int32(addhealth) ); + unitTarget->getHostilRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo); + + if(caster->GetTypeId()==TYPEID_PLAYER) + if(BattleGround *bg = ((Player*)caster)->GetBattleGround()) + bg->UpdatePlayerScore(((Player*)caster), SCORE_HEALING_DONE, gain); + } +} + +void Spell::EffectHealMechanical( uint32 /*i*/ ) +{ + // Mechanic creature type should be correctly checked by targetCreatureType field + if( unitTarget && unitTarget->isAlive() && damage >= 0) + { + // Try to get original caster + Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster; + + // Skip if m_originalCaster not available + if (!caster) + return; + + uint32 addhealth = caster->SpellHealingBonus(m_spellInfo, uint32(damage), HEAL, unitTarget); + caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false); + unitTarget->ModifyHealth( int32(damage) ); + } +} + +void Spell::EffectHealthLeech(uint32 i) +{ + if(!unitTarget) + return; + if(!unitTarget->isAlive()) + return; + + if(damage < 0) + return; + + sLog.outDebug("HealthLeech :%i", damage); + + float multiplier = m_spellInfo->EffectMultipleValue[i]; + + if(Player *modOwner = m_caster->GetSpellModOwner()) + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier); + + int32 new_damage = int32(damage*multiplier); + uint32 curHealth = unitTarget->GetHealth(); + new_damage = m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, new_damage, m_IsTriggeredSpell, true); + if(curHealth < new_damage) + new_damage = curHealth; + + if(m_caster->isAlive()) + { + new_damage = m_caster->SpellHealingBonus(m_spellInfo, new_damage, HEAL, m_caster); + + m_caster->ModifyHealth(new_damage); + + if(m_caster->GetTypeId() == TYPEID_PLAYER) + m_caster->SendHealSpellLog(m_caster, m_spellInfo->Id, uint32(new_damage)); + } +} + +void Spell::DoCreateItem(uint32 i, uint32 itemtype) +{ + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + Player* player = (Player*)unitTarget; + + uint32 newitemid = itemtype; + ItemPrototype const *pProto = objmgr.GetItemPrototype( newitemid ); + if(!pProto) + { + player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); + return; + } + + uint32 num_to_add; + + // TODO: maybe all this can be replaced by using correct calculated `damage` value + if(pProto->Class != ITEM_CLASS_CONSUMABLE || m_spellInfo->SpellFamilyName != SPELLFAMILY_MAGE) + { + int32 basePoints = m_currentBasePoints[i]; + int32 randomPoints = m_spellInfo->EffectDieSides[i]; + if (randomPoints) + num_to_add = basePoints + irand(1, randomPoints); + else + num_to_add = basePoints + 1; + } + else if (pProto->MaxCount == 1) + num_to_add = 1; + else if(player->getLevel() >= m_spellInfo->spellLevel) + { + int32 basePoints = m_currentBasePoints[i]; + float pointPerLevel = m_spellInfo->EffectRealPointsPerLevel[i]; + num_to_add = basePoints + 1 + uint32((player->getLevel() - m_spellInfo->spellLevel)*pointPerLevel); + } + else + num_to_add = 2; + + if (num_to_add < 1) + num_to_add = 1; + if (num_to_add > pProto->Stackable) + num_to_add = pProto->Stackable; + + // init items_count to 1, since 1 item will be created regardless of specialization + int items_count=1; + // the chance to create additional items + float additionalCreateChance=0.0f; + // the maximum number of created additional items + uint8 additionalMaxNum=0; + // get the chance and maximum number for creating extra items + if ( canCreateExtraItems(player, m_spellInfo->Id, additionalCreateChance, additionalMaxNum) ) + { + // roll with this chance till we roll not to create or we create the max num + while ( roll_chance_f(additionalCreateChance) && items_count<=additionalMaxNum ) + ++items_count; + } + + // really will be created more items + num_to_add *= items_count; + + // can the player store the new item? + ItemPosCountVec dest; + uint32 no_space = 0; + uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, newitemid, num_to_add, &no_space ); + if( msg != EQUIP_ERR_OK ) + { + // convert to possible store amount + if( msg == EQUIP_ERR_INVENTORY_FULL || msg == EQUIP_ERR_CANT_CARRY_MORE_OF_THIS ) + num_to_add -= no_space; + else + { + // if not created by another reason from full inventory or unique items amount limitation + player->SendEquipError( msg, NULL, NULL ); + return; + } + } + + if(num_to_add) + { + // create the new item and store it + Item* pItem = player->StoreNewItem( dest, newitemid, true, Item::GenerateItemRandomPropertyId(newitemid)); + + // was it successful? return error if not + if(!pItem) + { + player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); + return; + } + + // set the "Crafted by ..." property of the item + if( pItem->GetProto()->Class != ITEM_CLASS_CONSUMABLE && pItem->GetProto()->Class != ITEM_CLASS_QUEST) + pItem->SetUInt32Value(ITEM_FIELD_CREATOR,player->GetGUIDLow()); + + // send info to the client + if(pItem) + player->SendNewItem(pItem, num_to_add, true, true); + + // we succeeded in creating at least one item, so a levelup is possible + player->UpdateCraftSkill(m_spellInfo->Id); + } + + // for battleground marks send by mail if not add all expected + if(no_space > 0 ) + { + BattleGroundTypeId bgType; + switch(m_spellInfo->Id) + { + case SPELL_AV_MARK_WINNER: + case SPELL_AV_MARK_LOSER: + bgType = BATTLEGROUND_AV; + break; + case SPELL_WS_MARK_WINNER: + case SPELL_WS_MARK_LOSER: + bgType = BATTLEGROUND_WS; + break; + case SPELL_AB_MARK_WINNER: + case SPELL_AB_MARK_LOSER: + bgType = BATTLEGROUND_AB; + break; + default: + return; + } + + if(BattleGround* bg = sBattleGroundMgr.GetBattleGround(bgType)) + bg->SendRewardMarkByMail(player,newitemid,no_space); + } +} + +void Spell::EffectCreateItem(uint32 i) +{ + DoCreateItem(i,m_spellInfo->EffectItemType[i]); +} + +void Spell::EffectPersistentAA(uint32 i) +{ + float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + + if(Player* modOwner = m_caster->GetSpellModOwner()) + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius); + + int32 duration = GetSpellDuration(m_spellInfo); + DynamicObject* dynObj = new DynamicObject; + if(!dynObj->Create(objmgr.GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, i, m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, duration, radius)) + { + delete dynObj; + return; + } + dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65); + dynObj->SetUInt32Value(GAMEOBJECT_DISPLAYID, 368003); + dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x01eeeeee); + m_caster->AddDynObject(dynObj); + MapManager::Instance().GetMap(dynObj->GetMapId(), dynObj)->Add(dynObj); +} + +void Spell::EffectEnergize(uint32 i) +{ + if(!unitTarget) + return; + if(!unitTarget->isAlive()) + return; + + if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS) + return; + + // Some level depends spells + int multipler = 0; + int level_diff = 0; + switch (m_spellInfo->Id) + { + // Restore Energy + case 9512: + level_diff = m_caster->getLevel() - 40; + multipler = 2; + break; + // Blood Fury + case 24571: + level_diff = m_caster->getLevel() - 60; + multipler = 10; + break; + // Burst of Energy + case 24532: + level_diff = m_caster->getLevel() - 60; + multipler = 4; + break; + default: + break; + } + + if (level_diff > 0) + damage -= multipler * level_diff; + + if(damage < 0) + return; + + Powers power = Powers(m_spellInfo->EffectMiscValue[i]); + + if(unitTarget->GetMaxPower(power) == 0) + return; + + unitTarget->ModifyPower(power,damage); + m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, damage, power); + + // Mad Alchemist's Potion + if (m_spellInfo->Id == 45051) + { + // find elixirs on target + uint32 elixir_mask = 0; + Unit::AuraMap& Auras = unitTarget->GetAuras(); + for(Unit::AuraMap::iterator itr = Auras.begin(); itr != Auras.end(); ++itr) + { + uint32 spell_id = itr->second->GetId(); + if(uint32 mask = spellmgr.GetSpellElixirMask(spell_id)) + elixir_mask |= mask; + } + + // get available elixir mask any not active type from battle/guardian (and flask if no any) + elixir_mask = (elixir_mask & ELIXIR_FLASK_MASK) ^ ELIXIR_FLASK_MASK; + + // get all available elixirs by mask and spell level + std::vector elixirs; + SpellElixirMap const& m_spellElixirs = spellmgr.GetSpellElixirMap(); + for(SpellElixirMap::const_iterator itr = m_spellElixirs.begin(); itr != m_spellElixirs.end(); ++itr) + { + if (itr->second & elixir_mask) + { + if (itr->second & (ELIXIR_UNSTABLE_MASK | ELIXIR_SHATTRATH_MASK)) + continue; + + SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first); + if (spellInfo && (spellInfo->spellLevel < m_spellInfo->spellLevel || spellInfo->spellLevel > unitTarget->getLevel())) + continue; + + elixirs.push_back(itr->first); + } + } + + if (!elixirs.empty()) + { + // cast random elixir on target + uint32 rand_spell = urand(0,elixirs.size()-1); + m_caster->CastSpell(unitTarget,elixirs[rand_spell],true,m_CastItem); + } + } +} + +void Spell::EffectEnergisePct(uint32 i) +{ + if(!unitTarget) + return; + if(!unitTarget->isAlive()) + return; + + if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS) + return; + + Powers power = Powers(m_spellInfo->EffectMiscValue[i]); + + uint32 maxPower = unitTarget->GetMaxPower(power); + if(maxPower == 0) + return; + + uint32 gain = damage * maxPower / 100; + unitTarget->ModifyPower(power, gain); + m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, damage, power); +} + +void Spell::SendLoot(uint64 guid, LootType loottype) +{ + Player* player = (Player*)m_caster; + if (!player) + return; + + if (gameObjTarget) + { + switch (gameObjTarget->GetGoType()) + { + case GAMEOBJECT_TYPE_DOOR: + case GAMEOBJECT_TYPE_BUTTON: + gameObjTarget->UseDoorOrButton(); + sWorld.ScriptsStart(sGameObjectScripts, gameObjTarget->GetDBTableGUIDLow(), player, gameObjTarget); + return; + + case GAMEOBJECT_TYPE_QUESTGIVER: + // start or end quest + player->PrepareQuestMenu(guid); + player->SendPreparedQuest(guid); + return; + + case GAMEOBJECT_TYPE_SPELL_FOCUS: + // triggering linked GO + if(uint32 trapEntry = gameObjTarget->GetGOInfo()->spellFocus.linkedTrapId) + gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster); + return; + + case GAMEOBJECT_TYPE_GOOBER: + // goober_scripts can be triggered if the player don't have the quest + if (gameObjTarget->GetGOInfo()->goober.eventId) + { + sLog.outDebug("Goober ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->goober.eventId,gameObjTarget->GetDBTableGUIDLow()); + sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->goober.eventId, player, gameObjTarget); + } + + // cast goober spell + if (gameObjTarget->GetGOInfo()->goober.questId) + ///Quest require to be active for GO using + if(player->GetQuestStatus(gameObjTarget->GetGOInfo()->goober.questId) != QUEST_STATUS_INCOMPLETE) + return; + + gameObjTarget->AddUniqueUse(player); + gameObjTarget->SetLootState(GO_JUST_DEACTIVATED); + + //TODO? Objective counting called without spell check but with quest objective check + // if send spell id then this line will duplicate to spell casting call (double counting) + // So we or have this line and not required in quest_template have reqSpellIdN + // or must remove this line and required in DB have data in quest_template have reqSpellIdN for all quest using cases. + player->CastedCreatureOrGO(gameObjTarget->GetEntry(), gameObjTarget->GetGUID(), 0); + + // triggering linked GO + if(uint32 trapEntry = gameObjTarget->GetGOInfo()->goober.linkedTrapId) + gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster); + + return; + + case GAMEOBJECT_TYPE_CHEST: + // TODO: possible must be moved to loot release (in different from linked triggering) + if (gameObjTarget->GetGOInfo()->chest.eventId) + { + sLog.outDebug("Chest ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->chest.eventId,gameObjTarget->GetDBTableGUIDLow()); + sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->chest.eventId, player, gameObjTarget); + } + + // triggering linked GO + if(uint32 trapEntry = gameObjTarget->GetGOInfo()->chest.linkedTrapId) + gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster); + + // Don't return, let loots been taken + } + } + + // Send loot + player->SendLoot(guid, loottype); +} + +void Spell::EffectOpenLock(uint32 /*i*/) +{ + if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER) + { + sLog.outDebug( "WORLD: Open Lock - No Player Caster!"); + return; + } + + Player* player = (Player*)m_caster; + + LootType loottype = LOOT_CORPSE; + uint32 lockId = 0; + uint64 guid = 0; + + // Get lockId + if(gameObjTarget) + { + GameObjectInfo const* goInfo = gameObjTarget->GetGOInfo(); + // Arathi Basin banner opening ! + if( goInfo->type == GAMEOBJECT_TYPE_BUTTON && goInfo->button.noDamageImmune || + goInfo->type == GAMEOBJECT_TYPE_GOOBER && goInfo->goober.losOK ) + { + if(BattleGround *bg = player->GetBattleGround())// in battleground + { + if( !player->IsMounted() && // not mounted + !player->HasStealthAura() && // not stealthed + !player->HasInvisibilityAura() && // not invisible + player->isAlive() ) // live player + { + // check if it's correct bg + if(bg && bg->GetTypeID() == BATTLEGROUND_AB) + bg->EventPlayerClickedOnFlag(player, gameObjTarget); + + return; + } + } + } + else if (goInfo->type == GAMEOBJECT_TYPE_FLAGSTAND) + { + if(BattleGround *bg = player->GetBattleGround()) + if(bg->GetTypeID() == BATTLEGROUND_EY) + bg->EventPlayerClickedOnFlag(player, gameObjTarget); + return; + } + lockId = gameObjTarget->GetLockId(); + guid = gameObjTarget->GetGUID(); + } + else if(itemTarget) + { + lockId = itemTarget->GetProto()->LockID; + guid = itemTarget->GetGUID(); + } + else + { + sLog.outDebug( "WORLD: Open Lock - No GameObject/Item Target!"); + return; + } + + if(!lockId) // possible case for GO and maybe for items. + { + SendLoot(guid, loottype); + return; + } + + // Get LockInfo + LockEntry const *lockInfo = sLockStore.LookupEntry(lockId); + + if (!lockInfo) + { + sLog.outError( "Spell::EffectOpenLock: %s [guid = %u] has an unknown lockId: %u!", + (gameObjTarget ? "gameobject" : "item"), GUID_LOPART(guid), lockId); + SendCastResult(SPELL_FAILED_BAD_TARGETS); + return; + } + + // check key + for(int i = 0; i < 5; ++i) + { + // type==1 This means lockInfo->key[i] is an item + if(lockInfo->keytype[i]==LOCK_KEY_ITEM && lockInfo->key[i] && m_CastItem && m_CastItem->GetEntry()==lockInfo->key[i]) + { + SendLoot(guid, loottype); + return; + } + } + + uint32 SkillId = 0; + // Check and skill-up skill + if( m_spellInfo->Effect[1] == SPELL_EFFECT_SKILL ) + SkillId = m_spellInfo->EffectMiscValue[1]; + // pickpocketing spells + else if( m_spellInfo->EffectMiscValue[0] == LOCKTYPE_PICKLOCK ) + SkillId = SKILL_LOCKPICKING; + + // skill bonus provided by casting spell (mostly item spells) + uint32 spellSkillBonus = uint32(m_currentBasePoints[0]+1); + + uint32 reqSkillValue = lockInfo->requiredminingskill; + + if(lockInfo->requiredlockskill) // required pick lock skill applying + { + if(SkillId != SKILL_LOCKPICKING) // wrong skill (cheating?) + { + SendCastResult(SPELL_FAILED_FIZZLE); + return; + } + + reqSkillValue = lockInfo->requiredlockskill; + } + else if(SkillId == SKILL_LOCKPICKING) // apply picklock skill to wrong target + { + SendCastResult(SPELL_FAILED_BAD_TARGETS); + return; + } + + if ( SkillId ) + { + loottype = LOOT_SKINNING; + if ( player->GetSkillValue(SkillId) + spellSkillBonus < reqSkillValue ) + { + SendCastResult(SPELL_FAILED_LOW_CASTLEVEL); + return; + } + + // update skill if really known + uint32 SkillValue = player->GetPureSkillValue(SkillId); + if(SkillValue) // non only item base skill + { + if(gameObjTarget) + { + // Allow one skill-up until respawned + if ( !gameObjTarget->IsInSkillupList( player->GetGUIDLow() ) && + player->UpdateGatherSkill(SkillId, SkillValue, reqSkillValue) ) + gameObjTarget->AddToSkillupList( player->GetGUIDLow() ); + } + else if(itemTarget) + { + // Do one skill-up + uint32 SkillValue = player->GetPureSkillValue(SkillId); + player->UpdateGatherSkill(SkillId, SkillValue, reqSkillValue); + } + } + } + + SendLoot(guid, loottype); +} + +void Spell::EffectSummonChangeItem(uint32 i) +{ + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + Player *player = (Player*)m_caster; + + // applied only to using item + if(!m_CastItem) + return; + + // ... only to item in own inventory/bank/equip_slot + if(m_CastItem->GetOwnerGUID()!=player->GetGUID()) + return; + + uint32 newitemid = m_spellInfo->EffectItemType[i]; + if(!newitemid) + return; + + uint16 pos = m_CastItem->GetPos(); + + Item *pNewItem = Item::CreateItem( newitemid, 1, player); + if( !pNewItem ) + return; + + for(uint8 i= PERM_ENCHANTMENT_SLOT; i<=TEMP_ENCHANTMENT_SLOT; ++i) + { + if(m_CastItem->GetEnchantmentId(EnchantmentSlot(i))) + pNewItem->SetEnchantment(EnchantmentSlot(i), m_CastItem->GetEnchantmentId(EnchantmentSlot(i)), m_CastItem->GetEnchantmentDuration(EnchantmentSlot(i)), m_CastItem->GetEnchantmentCharges(EnchantmentSlot(i))); + } + + if(m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) < m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY)) + { + double loosePercent = 1 - m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) / double(m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY)); + player->DurabilityLoss(pNewItem, loosePercent); + } + + if( player->IsInventoryPos( pos ) ) + { + ItemPosCountVec dest; + uint8 msg = player->CanStoreItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true ); + if( msg == EQUIP_ERR_OK ) + { + player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true); + + // prevent crash at access and unexpected charges counting with item update queue corrupt + if(m_CastItem==m_targets.getItemTarget()) + m_targets.setItemTarget(NULL); + + m_CastItem = NULL; + + player->StoreItem( dest, pNewItem, true); + return; + } + } + else if( player->IsBankPos ( pos ) ) + { + ItemPosCountVec dest; + uint8 msg = player->CanBankItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true ); + if( msg == EQUIP_ERR_OK ) + { + player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true); + + // prevent crash at access and unexpected charges counting with item update queue corrupt + if(m_CastItem==m_targets.getItemTarget()) + m_targets.setItemTarget(NULL); + + m_CastItem = NULL; + + player->BankItem( dest, pNewItem, true); + return; + } + } + else if( player->IsEquipmentPos ( pos ) ) + { + uint16 dest; + uint8 msg = player->CanEquipItem( m_CastItem->GetSlot(), dest, pNewItem, true ); + if( msg == EQUIP_ERR_OK ) + { + player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true); + + // prevent crash at access and unexpected charges counting with item update queue corrupt + if(m_CastItem==m_targets.getItemTarget()) + m_targets.setItemTarget(NULL); + + m_CastItem = NULL; + + player->EquipItem( dest, pNewItem, true); + player->AutoUnequipOffhandIfNeed(); + return; + } + } + + // fail + delete pNewItem; +} + +void Spell::EffectOpenSecretSafe(uint32 i) +{ + EffectOpenLock(i); //no difference for now +} + +void Spell::EffectProficiency(uint32 /*i*/) +{ + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + Player *p_target = (Player*)unitTarget; + + uint32 subClassMask = m_spellInfo->EquippedItemSubClassMask; + if(m_spellInfo->EquippedItemClass == 2 && !(p_target->GetWeaponProficiency() & subClassMask)) + { + p_target->AddWeaponProficiency(subClassMask); + p_target->SendProficiency(uint8(0x02),p_target->GetWeaponProficiency()); + } + if(m_spellInfo->EquippedItemClass == 4 && !(p_target->GetArmorProficiency() & subClassMask)) + { + p_target->AddArmorProficiency(subClassMask); + p_target->SendProficiency(uint8(0x04),p_target->GetArmorProficiency()); + } +} + +void Spell::EffectApplyAreaAura(uint32 i) +{ + if(!unitTarget) + return; + if(!unitTarget->isAlive()) + return; + + AreaAura* Aur = new AreaAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, m_caster, m_CastItem); + unitTarget->AddAura(Aur); +} + +void Spell::EffectSummonType(uint32 i) +{ + switch(m_spellInfo->EffectMiscValueB[i]) + { + case SUMMON_TYPE_GUARDIAN: + case SUMMON_TYPE_POSESSED: + case SUMMON_TYPE_POSESSED2: + EffectSummonGuardian(i); + break; + case SUMMON_TYPE_WILD: + EffectSummonWild(i); + break; + case SUMMON_TYPE_DEMON: + EffectSummonDemon(i); + break; + case SUMMON_TYPE_SUMMON: + EffectSummon(i); + break; + case SUMMON_TYPE_CRITTER: + case SUMMON_TYPE_CRITTER2: + EffectSummonCritter(i); + break; + case SUMMON_TYPE_TOTEM_SLOT1: + case SUMMON_TYPE_TOTEM_SLOT2: + case SUMMON_TYPE_TOTEM_SLOT3: + case SUMMON_TYPE_TOTEM_SLOT4: + case SUMMON_TYPE_TOTEM: + EffectSummonTotem(i); + break; + case SUMMON_TYPE_UNKNOWN1: + case SUMMON_TYPE_UNKNOWN2: + case SUMMON_TYPE_UNKNOWN3: + case SUMMON_TYPE_UNKNOWN4: + case SUMMON_TYPE_UNKNOWN5: + case SUMMON_TYPE_UNKNOWN6: + break; + default: + sLog.outError("EffectSummonType: Unhandled summon type %u", m_spellInfo->EffectMiscValueB[i]); + break; + } +} + +void Spell::EffectSummon(uint32 i) +{ + if(m_caster->GetPetGUID()) + return; + + if(!unitTarget) + return; + uint32 pet_entry = m_spellInfo->EffectMiscValue[i]; + if(!pet_entry) + return; + uint32 level = m_caster->getLevel(); + Pet* spawnCreature = new Pet(SUMMON_PET); + + if(spawnCreature->LoadPetFromDB(m_caster,pet_entry)) + { + // set timer for unsummon + int32 duration = GetSpellDuration(m_spellInfo); + if(duration > 0) + spawnCreature->SetDuration(duration); + + return; + } + + Map *map = m_caster->GetMap(); + uint32 pet_number = objmgr.GeneratePetNumber(); + if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET),map,m_spellInfo->EffectMiscValue[i], pet_number)) + { + sLog.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo->EffectMiscValue[i]); + delete spawnCreature; + return; + } + + // Summon in dest location + float x,y,z; + if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) + { + x = m_targets.m_destX; + y = m_targets.m_destY; + z = m_targets.m_destZ; + } + else + m_caster->GetClosePoint(x,y,z,spawnCreature->GetObjectSize()); + + spawnCreature->Relocate(x,y,z,-m_caster->GetOrientation()); + + if(!spawnCreature->IsPositionValid()) + { + sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %d Y: ^%d)", spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY()); + delete spawnCreature; + return; + } + + // set timer for unsummon + int32 duration = GetSpellDuration(m_spellInfo); + if(duration > 0) + spawnCreature->SetDuration(duration); + + spawnCreature->SetUInt64Value(UNIT_FIELD_SUMMONEDBY,m_caster->GetGUID()); + spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS , 0); + spawnCreature->setPowerType(POWER_MANA); + spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction()); + spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS,0); + spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_0,2048); + spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1,0); + spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0); + spawnCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE,0); + spawnCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP,1000); + spawnCreature->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID()); + spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id); + + spawnCreature->InitStatsForLevel(level); + + spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false); + + spawnCreature->AIM_Initialize(); + spawnCreature->InitPetCreateSpells(); + spawnCreature->SetHealth(spawnCreature->GetMaxHealth()); + spawnCreature->SetPower(POWER_MANA, spawnCreature->GetMaxPower(POWER_MANA)); + + std::string name = m_caster->GetName(); + name.append(petTypeSuffix[spawnCreature->getPetType()]); + spawnCreature->SetName( name ); + + map->Add((Creature*)spawnCreature); + + if(m_caster->GetTypeId() == TYPEID_PLAYER) + { + m_caster->SetPet(spawnCreature); + spawnCreature->GetCharmInfo()->SetReactState( REACT_DEFENSIVE ); + spawnCreature->SavePetToDB(PET_SAVE_AS_CURRENT); + ((Player*)m_caster)->PetSpellInitialize(); + } +} + +void Spell::EffectLearnSpell(uint32 i) +{ + if(!unitTarget) + return; + + if(unitTarget->GetTypeId() != TYPEID_PLAYER) + { + if(m_caster->GetTypeId() == TYPEID_PLAYER) + EffectLearnPetSpell(i); + + return; + } + + Player *player = (Player*)unitTarget; + + uint32 spellToLearn = (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) ? damage : m_spellInfo->EffectTriggerSpell[i]; + player->learnSpell(spellToLearn); + + sLog.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() ); +} + +void Spell::EffectDispel(uint32 i) +{ + if(!unitTarget) + return; + + // Fill possible dispell list + std::vector dispel_list; + + // Create dispel mask by dispel type + uint32 dispel_type = m_spellInfo->EffectMiscValue[i]; + uint32 dispelMask = GetDispellMask( DispelType(dispel_type) ); + Unit::AuraMap const& auras = unitTarget->GetAuras(); + for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) + { + Aura *aur = (*itr).second; + if (aur && (1<GetSpellProto()->Dispel) & dispelMask) + { + if(aur->GetSpellProto()->Dispel == DISPEL_MAGIC) + { + bool positive = true; + if (!aur->IsPositive()) + positive = false; + else + positive = (aur->GetSpellProto()->AttributesEx & SPELL_ATTR_EX_NEGATIVE)==0; + + // do not remove positive auras if friendly target + // negative auras if non-friendly target + if(positive == unitTarget->IsFriendlyTo(m_caster)) + continue; + } + // Add aura to dispel list + dispel_list.push_back(aur); + } + } + // Ok if exist some buffs for dispel try dispel it + if (!dispel_list.empty()) + { + std::list < std::pair > success_list;// (spell_id,casterGuid) + std::list < uint32 > fail_list; // spell_id + int32 list_size = dispel_list.size(); + // Dispell N = damage buffs (or while exist buffs for dispel) + for (int32 count=0; count < damage && list_size > 0; ++count) + { + // Random select buff for dispel + Aura *aur = dispel_list[urand(0, list_size-1)]; + + SpellEntry const* spellInfo = aur->GetSpellProto(); + // Base dispel chance + // TODO: possible chance depend from spell level?? + int32 miss_chance = 0; + // Apply dispel mod from aura caster + if (Unit *caster = aur->GetCaster()) + { + if ( Player* modOwner = caster->GetSpellModOwner() ) + modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_RESIST_DISPEL_CHANCE, miss_chance, this); + } + // Try dispel + if (roll_chance_i(miss_chance)) + fail_list.push_back(aur->GetId()); + else + success_list.push_back(std::pair(aur->GetId(),aur->GetCasterGUID())); + // Remove buff from list for prevent doubles + for (std::vector::iterator j = dispel_list.begin(); j != dispel_list.end(); ) + { + Aura *dispeled = *j; + if (dispeled->GetId() == aur->GetId() && dispeled->GetCasterGUID() == aur->GetCasterGUID()) + { + j = dispel_list.erase(j); + --list_size; + } + else + ++j; + } + } + // Send success log and really remove auras + if (!success_list.empty()) + { + int32 count = success_list.size(); + WorldPacket data(SMSG_SPELLDISPELLOG, 8+8+4+1+4+count*5); + data.append(unitTarget->GetPackGUID()); // Victim GUID + data.append(m_caster->GetPackGUID()); // Caster GUID + data << uint32(m_spellInfo->Id); // Dispell spell id + data << uint8(0); // not used + data << uint32(count); // count + for (std::list >::iterator j = success_list.begin(); j != success_list.end(); ++j) + { + SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first); + data << uint32(spellInfo->Id); // Spell Id + data << uint8(0); // 0 - dispeled !=0 cleansed + unitTarget->RemoveAurasDueToSpellByDispel(spellInfo->Id, j->second, m_caster); + } + m_caster->SendMessageToSet(&data, true); + + // On succes dispel + // Devour Magic + if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->Category == 12) + { + uint32 heal_spell = 0; + switch (m_spellInfo->Id) + { + case 19505: heal_spell = 19658; break; + case 19731: heal_spell = 19732; break; + case 19734: heal_spell = 19733; break; + case 19736: heal_spell = 19735; break; + case 27276: heal_spell = 27278; break; + case 27277: heal_spell = 27279; break; + default: + sLog.outDebug("Spell for Devour Magic %d not handled in Spell::EffectDispel", m_spellInfo->Id); + break; + } + if (heal_spell) + m_caster->CastSpell(m_caster, heal_spell, true); + } + } + // Send fail log to client + if (!fail_list.empty()) + { + // Failed to dispell + WorldPacket data(SMSG_DISPEL_FAILED, 8+8+4+4*fail_list.size()); + data << uint64(m_caster->GetGUID()); // Caster GUID + data << uint64(unitTarget->GetGUID()); // Victim GUID + data << uint32(m_spellInfo->Id); // Dispell spell id + for (std::list< uint32 >::iterator j = fail_list.begin(); j != fail_list.end(); ++j) + data << uint32(*j); // Spell Id + m_caster->SendMessageToSet(&data, true); + } + } +} + +void Spell::EffectDualWield(uint32 /*i*/) +{ + if (unitTarget->GetTypeId() == TYPEID_PLAYER) + ((Player*)unitTarget)->SetCanDualWield(true); +} + +void Spell::EffectPull(uint32 /*i*/) +{ + // TODO: create a proper pull towards distract spell center for distract + sLog.outDebug("WORLD: Spell Effect DUMMY"); +} + +void Spell::EffectDistract(uint32 /*i*/) +{ + // Check for possible target + if (!unitTarget || unitTarget->isInCombat()) + return; + + // target must be OK to do this + if( unitTarget->hasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_STUNDED | UNIT_STAT_FLEEING ) ) + return; + + float angle = unitTarget->GetAngle(m_targets.m_destX, m_targets.m_destY); + + if ( unitTarget->GetTypeId() == TYPEID_PLAYER ) + { + // For players just turn them + WorldPacket data; + ((Player*)unitTarget)->BuildTeleportAckMsg(&data, unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle); + ((Player*)unitTarget)->GetSession()->SendPacket( &data ); + ((Player*)unitTarget)->SetPosition(unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle, false); + } + else + { + // Set creature Distracted, Stop it, And turn it + unitTarget->SetOrientation(angle); + unitTarget->StopMoving(); + unitTarget->GetMotionMaster()->MoveDistract(damage*1000); + } +} + +void Spell::EffectPickPocket(uint32 /*i*/) +{ + if( m_caster->GetTypeId() != TYPEID_PLAYER ) + return; + + // victim must be creature and attackable + if( !unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->IsFriendlyTo(unitTarget) ) + return; + + // victim have to be alive and humanoid or undead + if( unitTarget->isAlive() && (unitTarget->GetCreatureTypeMask() &CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) != 0) + { + int32 chance = 10 + int32(m_caster->getLevel()) - int32(unitTarget->getLevel()); + + if (chance > irand(0, 19)) + { + // Stealing successful + //sLog.outDebug("Sending loot from pickpocket"); + ((Player*)m_caster)->SendLoot(unitTarget->GetGUID(),LOOT_PICKPOCKETING); + } + else + { + // Reveal action + get attack + m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + if (((Creature*)unitTarget)->AI()) + ((Creature*)unitTarget)->AI()->AttackStart(m_caster); + } + } +} + +void Spell::EffectAddFarsight(uint32 i) +{ + float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + int32 duration = GetSpellDuration(m_spellInfo); + DynamicObject* dynObj = new DynamicObject; + if(!dynObj->Create(objmgr.GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, i, m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, duration, radius)) + { + delete dynObj; + return; + } + dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65); + dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x80000002); + m_caster->AddDynObject(dynObj); + MapManager::Instance().GetMap(dynObj->GetMapId(), dynObj)->Add(dynObj); + m_caster->SetUInt64Value(PLAYER_FARSIGHT, dynObj->GetGUID()); +} + +void Spell::EffectSummonWild(uint32 i) +{ + uint32 creature_entry = m_spellInfo->EffectMiscValue[i]; + if(!creature_entry) + return; + + uint32 level = m_caster->getLevel(); + + // level of creature summoned using engineering item based at engineering skill level + if(m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem) + { + ItemPrototype const *proto = m_CastItem->GetProto(); + if(proto && proto->RequiredSkill == SKILL_ENGINERING) + { + uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING); + if(skill202) + { + level = skill202/5; + } + } + } + + // select center of summon position + float center_x = m_targets.m_destX; + float center_y = m_targets.m_destY; + float center_z = m_targets.m_destZ; + + float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + + int32 amount = damage > 0 ? damage : 1; + + for(int32 count = 0; count < amount; ++count) + { + float px, py, pz; + // If dest location if present + if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) + { + // Summon 1 unit in dest location + if (count == 0) + { + px = m_targets.m_destX; + py = m_targets.m_destY; + pz = m_targets.m_destZ; + } + // Summon in random point all other units if location present + else + m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz); + } + // Summon if dest location not present near caster + else + m_caster->GetClosePoint(px,py,pz,3.0f); + + int32 duration = GetSpellDuration(m_spellInfo); + + TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_OR_DEAD_DESPAWN; + + m_caster->SummonCreature(creature_entry,px,py,pz,m_caster->GetOrientation(),summonType,duration); + } +} + +void Spell::EffectSummonGuardian(uint32 i) +{ + uint32 pet_entry = m_spellInfo->EffectMiscValue[i]; + if(!pet_entry) + return; + + // Jewelery statue case (totem like) + if(m_spellInfo->SpellIconID==2056) + { + EffectSummonTotem(i); + return; + } + + // set timer for unsummon + int32 duration = GetSpellDuration(m_spellInfo); + + // Search old Guardian only for players (if casted spell not have duration or cooldown) + // FIXME: some guardians have control spell applied and controlled by player and anyway player can't summon in this time + // so this code hack in fact + if( m_caster->GetTypeId() == TYPEID_PLAYER && (duration <= 0 || GetSpellRecoveryTime(m_spellInfo)==0) ) + if(((Player*)m_caster)->HasGuardianWithEntry(pet_entry)) + return; // find old guardian, ignore summon + + // in another case summon new + uint32 level = m_caster->getLevel(); + + // level of pet summoned using engineering item based at engineering skill level + if(m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem) + { + ItemPrototype const *proto = m_CastItem->GetProto(); + if(proto && proto->RequiredSkill == SKILL_ENGINERING) + { + uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING); + if(skill202) + { + level = skill202/5; + } + } + } + + // select center of summon position + float center_x = m_targets.m_destX; + float center_y = m_targets.m_destY; + float center_z = m_targets.m_destZ; + + float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + + int32 amount = damage > 0 ? damage : 1; + + for(int32 count = 0; count < amount; ++count) + { + Pet* spawnCreature = new Pet(GUARDIAN_PET); + + Map *map = m_caster->GetMap(); + uint32 pet_number = objmgr.GeneratePetNumber(); + if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map,m_spellInfo->EffectMiscValue[i], pet_number)) + { + sLog.outError("no such creature entry %u",m_spellInfo->EffectMiscValue[i]); + delete spawnCreature; + return; + } + + float px, py, pz; + // If dest location if present + if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) + { + // Summon 1 unit in dest location + if (count == 0) + { + px = m_targets.m_destX; + py = m_targets.m_destY; + pz = m_targets.m_destZ; + } + // Summon in random point all other units if location present + else + m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz); + } + // Summon if dest location not present near caster + else + m_caster->GetClosePoint(px,py,pz,spawnCreature->GetObjectSize()); + + spawnCreature->Relocate(px,py,pz,m_caster->GetOrientation()); + + if(!spawnCreature->IsPositionValid()) + { + sLog.outError("ERROR: Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %d Y: ^%d)", spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY()); + delete spawnCreature; + return; + } + + if(duration > 0) + spawnCreature->SetDuration(duration); + + spawnCreature->SetUInt64Value(UNIT_FIELD_SUMMONEDBY,m_caster->GetGUID()); + spawnCreature->setPowerType(POWER_MANA); + spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS , 0); + spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction()); + spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS,0); + spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1,0); + spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0); + spawnCreature->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID()); + spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id); + + spawnCreature->InitStatsForLevel(level); + spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false); + + spawnCreature->AIM_Initialize(); + + if(m_caster->GetTypeId()==TYPEID_PLAYER) + ((Player*)m_caster)->AddGuardian(spawnCreature); + + map->Add((Creature*)spawnCreature); + } +} + +void Spell::EffectTeleUnitsFaceCaster(uint32 i) +{ + if(!unitTarget) + return; + + if(unitTarget->isInFlight()) + return; + + uint32 mapid = m_caster->GetMapId(); + float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + + float fx,fy,fz; + m_caster->GetClosePoint(fx,fy,fz,unitTarget->GetObjectSize(),dis); + + if(unitTarget->GetTypeId() == TYPEID_PLAYER) + ((Player*)unitTarget)->TeleportTo(mapid, fx, fy, fz, -m_caster->GetOrientation(), TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0)); + else + MapManager::Instance().GetMap(mapid, m_caster)->CreatureRelocation((Creature*)m_caster, fx, fy, fz, -m_caster->GetOrientation()); +} + +void Spell::EffectLearnSkill(uint32 i) +{ + if(unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + if(damage < 0) + return; + + uint32 skillid = m_spellInfo->EffectMiscValue[i]; + uint16 skillval = ((Player*)unitTarget)->GetPureSkillValue(skillid); + ((Player*)unitTarget)->SetSkill(skillid, skillval?skillval:1, damage*75); +} + +void Spell::EffectAddHonor(uint32 /*i*/) +{ + if(unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + sLog.outDebug("SpellEffect::AddHonor called for spell_id %u , that rewards %d honor points to player: %u", m_spellInfo->Id, this->damage, ((Player*)unitTarget)->GetGUIDLow()); + + // TODO: find formula for honor reward based on player's level! + + // now fixed only for level 70 players: + if (((Player*)unitTarget)->getLevel() == 70) + ((Player*)unitTarget)->RewardHonor(NULL, 1, this->damage); +} + +void Spell::EffectTradeSkill(uint32 /*i*/) +{ + if(unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + // uint32 skillid = m_spellInfo->EffectMiscValue[i]; + // uint16 skillmax = ((Player*)unitTarget)->(skillid); + // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75); +} + +void Spell::EffectEnchantItemPerm(uint32 i) +{ + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; + if (!itemTarget) + return; + + Player* p_caster = (Player*)m_caster; + + p_caster->UpdateCraftSkill(m_spellInfo->Id); + + if (m_spellInfo->EffectMiscValue[i]) + { + uint32 enchant_id = m_spellInfo->EffectMiscValue[i]; + + SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id); + if(!pEnchant) + return; + + // item can be in trade slot and have owner diff. from caster + Player* item_owner = itemTarget->GetOwner(); + if(!item_owner) + return; + + if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) ) + sLog.outCommand("GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)", + p_caster->GetName(),p_caster->GetSession()->GetAccountId(), + itemTarget->GetProto()->Name1,itemTarget->GetEntry(), + item_owner->GetName(),item_owner->GetSession()->GetAccountId()); + + // remove old enchanting before applying new if equipped + item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,false); + + itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0); + + // add new enchanting if equipped + item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,true); + } +} + +void Spell::EffectEnchantItemTmp(uint32 i) +{ + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + Player* p_caster = (Player*)m_caster; + + if(!itemTarget) + return; + + uint32 enchant_id = m_spellInfo->EffectMiscValue[i]; + + // Shaman Rockbiter Weapon + if(i==0 && m_spellInfo->Effect[1]==SPELL_EFFECT_DUMMY) + { + int32 enchnting_damage = m_currentBasePoints[1]+1; + + // enchanting id selected by calculated damage-per-sec stored in Effect[1] base value + // with already applied percent bonus from Elemental Weapons talent + // Note: damage calculated (correctly) with rounding int32(float(v)) but + // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime + switch(enchnting_damage) + { + // Rank 1 + case 2: enchant_id = 29; break; // 0% [ 7% == 2, 14% == 2, 20% == 2] + // Rank 2 + case 4: enchant_id = 6; break; // 0% [ 7% == 4, 14% == 4] + case 5: enchant_id = 3025; break; // 20% + // Rank 3 + case 6: enchant_id = 1; break; // 0% [ 7% == 6, 14% == 6] + case 7: enchant_id = 3027; break; // 20% + // Rank 4 + case 9: enchant_id = 3032; break; // 0% [ 7% == 6] + case 10: enchant_id = 503; break; // 14% + case 11: enchant_id = 3031; break; // 20% + // Rank 5 + case 15: enchant_id = 3035; break; // 0% + case 16: enchant_id = 1663; break; // 7% + case 17: enchant_id = 3033; break; // 14% + case 18: enchant_id = 3034; break; // 20% + // Rank 6 + case 28: enchant_id = 3038; break; // 0% + case 29: enchant_id = 683; break; // 7% + case 31: enchant_id = 3036; break; // 14% + case 33: enchant_id = 3037; break; // 20% + // Rank 7 + case 40: enchant_id = 3041; break; // 0% + case 42: enchant_id = 1664; break; // 7% + case 45: enchant_id = 3039; break; // 14% + case 48: enchant_id = 3040; break; // 20% + // Rank 8 + case 49: enchant_id = 3044; break; // 0% + case 52: enchant_id = 2632; break; // 7% + case 55: enchant_id = 3042; break; // 14% + case 58: enchant_id = 3043; break; // 20% + // Rank 9 + case 62: enchant_id = 2633; break; // 0% + case 66: enchant_id = 3018; break; // 7% + case 70: enchant_id = 3019; break; // 14% + case 74: enchant_id = 3020; break; // 20% + default: + sLog.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",enchnting_damage); + return; + } + } + + if (!enchant_id) + { + sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo->Id,i); + return; + } + + SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id); + if(!pEnchant) + { + sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo->Id,i,enchant_id); + return; + } + + // select enchantment duration + uint32 duration; + + // rogue family enchantments exception by duration + if(m_spellInfo->Id==38615) + duration = 1800; // 30 mins + // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints) + else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE) + duration = 3600; // 1 hour + // shaman family enchantments + else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_SHAMAN) + duration = 1800; // 30 mins + // other cases with this SpellVisual already selected + else if(m_spellInfo->SpellVisual==215) + duration = 1800; // 30 mins + // some fishing pole bonuses + else if(m_spellInfo->SpellVisual==563) + duration = 600; // 10 mins + // shaman rockbiter enchantments + else if(m_spellInfo->SpellVisual==0) + duration = 1800; // 30 mins + else if(m_spellInfo->Id==29702) + duration = 300; // 5 mins + else if(m_spellInfo->Id==37360) + duration = 300; // 5 mins + // default case + else + duration = 3600; // 1 hour + + // item can be in trade slot and have owner diff. from caster + Player* item_owner = itemTarget->GetOwner(); + if(!item_owner) + return; + + if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) ) + sLog.outCommand("GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)", + p_caster->GetName(),p_caster->GetSession()->GetAccountId(), + itemTarget->GetProto()->Name1,itemTarget->GetEntry(), + item_owner->GetName(),item_owner->GetSession()->GetAccountId()); + + // remove old enchanting before applying new if equipped + item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT,false); + + itemTarget->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, duration*1000, 0); + + // add new enchanting if equipped + item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT,true); +} + +void Spell::EffectTameCreature(uint32 /*i*/) +{ + if(m_caster->GetPetGUID()) + return; + + if(!unitTarget) + return; + + if(unitTarget->GetTypeId() == TYPEID_PLAYER) + return; + + Creature* creatureTarget = (Creature*)unitTarget; + + if(creatureTarget->isPet()) + return; + + if(m_caster->getClass() == CLASS_HUNTER) + { + // cast finish successfully + //SendChannelUpdate(0); + finish(); + + Pet* pet = new Pet(HUNTER_PET); + + if(!pet->CreateBaseAtCreature(creatureTarget)) + { + delete pet; + return; + } + + creatureTarget->setDeathState(JUST_DIED); + creatureTarget->RemoveCorpse(); + creatureTarget->SetHealth(0); // just for nice GM-mode view + + pet->SetUInt64Value(UNIT_FIELD_SUMMONEDBY, m_caster->GetGUID()); + pet->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID()); + pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction()); + pet->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id); + + if(!pet->InitStatsForLevel(creatureTarget->getLevel())) + { + sLog.outError("ERROR: InitStatsForLevel() in EffectTameCreature failed! Pet deleted."); + delete pet; + return; + } + + // prepare visual effect for levelup + pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()-1); + + pet->GetCharmInfo()->SetPetNumber(objmgr.GeneratePetNumber(), true); + // this enables pet details window (Shift+P) + pet->AIM_Initialize(); + pet->InitPetCreateSpells(); + pet->SetHealth(pet->GetMaxHealth()); + + MapManager::Instance().GetMap(pet->GetMapId(), pet)->Add((Creature*)pet); + + // visual effect for levelup + pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()); + + if(m_caster->GetTypeId() == TYPEID_PLAYER) + { + m_caster->SetPet(pet); + pet->SavePetToDB(PET_SAVE_AS_CURRENT); + ((Player*)m_caster)->PetSpellInitialize(); + } + } +} + +void Spell::EffectSummonPet(uint32 i) +{ + uint32 petentry = m_spellInfo->EffectMiscValue[i]; + + Pet *OldSummon = m_caster->GetPet(); + + // if pet requested type already exist + if( OldSummon ) + { + if(petentry == 0 || OldSummon->GetEntry() == petentry) + { + // pet in corpse state can't be summoned + if( OldSummon->isDead() ) + return; + + MapManager::Instance().GetMap(OldSummon->GetMapId(), OldSummon)->Remove((Creature*)OldSummon,false); + OldSummon->SetMapId(m_caster->GetMapId()); + + float px, py, pz; + m_caster->GetClosePoint(px, py, pz, OldSummon->GetObjectSize()); + + OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation()); + MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)->Add((Creature*)OldSummon); + + if(m_caster->GetTypeId() == TYPEID_PLAYER && OldSummon->isControlled() ) + { + ((Player*)m_caster)->PetSpellInitialize(); + } + return; + } + + if(m_caster->GetTypeId() == TYPEID_PLAYER) + ((Player*)m_caster)->RemovePet(OldSummon,(OldSummon->getPetType()==HUNTER_PET ? PET_SAVE_AS_DELETED : PET_SAVE_NOT_IN_SLOT),false); + else + return; + } + + Pet* NewSummon = new Pet; + + // petentry==0 for hunter "call pet" (current pet summoned if any) + if(NewSummon->LoadPetFromDB(m_caster,petentry)) + { + if(NewSummon->getPetType()==SUMMON_PET) + { + // Remove Demonic Sacrifice auras (known pet) + Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();) + { + if((*itr)->GetModifier()->m_miscvalue==2228) + { + m_caster->RemoveAurasDueToSpell((*itr)->GetId()); + itr = auraClassScripts.begin(); + } + else + ++itr; + } + } + + return; + } + + // not error in case fail hunter call pet + if(!petentry) + { + delete NewSummon; + return; + } + + CreatureInfo const* cInfo = sCreatureStorage.LookupEntry(petentry); + + if(!cInfo) + { + sLog.outError("EffectSummonPet: creature entry %u not found.",petentry); + delete NewSummon; + return; + } + + Map *map = m_caster->GetMap(); + uint32 pet_number = objmgr.GeneratePetNumber(); + if(!NewSummon->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, petentry, pet_number)) + { + delete NewSummon; + return; + } + + float px, py, pz; + m_caster->GetClosePoint(px, py, pz, NewSummon->GetObjectSize()); + + NewSummon->Relocate(px, py, pz, m_caster->GetOrientation()); + + if(!NewSummon->IsPositionValid()) + { + sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %d Y: ^%d)", NewSummon->GetGUIDLow(), NewSummon->GetEntry(), NewSummon->GetPositionX(), NewSummon->GetPositionY()); + delete NewSummon; + return; + } + + uint32 petlevel = m_caster->getLevel(); + NewSummon->setPetType(SUMMON_PET); + + uint32 faction = m_caster->getFaction(); + if(m_caster->GetTypeId() == TYPEID_UNIT && ((Creature*)m_caster)->isTotem()) + { + Unit* owner = ((Totem*)m_caster)->GetOwner(); + if(owner) + faction = owner->getFaction(); + NewSummon->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE); + } + + NewSummon->SetUInt64Value(UNIT_FIELD_SUMMONEDBY, m_caster->GetGUID()); + NewSummon->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID()); + NewSummon->SetUInt32Value(UNIT_NPC_FLAGS , 0); + NewSummon->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, faction); + NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_0,2048); + NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_1,0); + NewSummon->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,time(NULL)); + NewSummon->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE,0); + NewSummon->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP,1000); + NewSummon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id); + + NewSummon->GetCharmInfo()->SetPetNumber(pet_number, true); + // this enables pet details window (Shift+P) + + // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later + NewSummon->SetUInt32Value(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE); + + NewSummon->InitStatsForLevel( petlevel); + NewSummon->InitPetCreateSpells(); + + if(NewSummon->getPetType()==SUMMON_PET) + { + // Remove Demonic Sacrifice auras (new pet) + Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();) + { + if((*itr)->GetModifier()->m_miscvalue==2228) + { + m_caster->RemoveAurasDueToSpell((*itr)->GetId()); + itr = auraClassScripts.begin(); + } + else + ++itr; + } + + // generate new name for summon pet + std::string new_name=objmgr.GeneratePetName(petentry); + if(!new_name.empty()) + NewSummon->SetName(new_name); + } + else if(NewSummon->getPetType()==HUNTER_PET) + NewSummon->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_NOT_ALLOWED); + + NewSummon->AIM_Initialize(); + NewSummon->SetHealth(NewSummon->GetMaxHealth()); + NewSummon->SetPower(POWER_MANA, NewSummon->GetMaxPower(POWER_MANA)); + + map->Add((Creature*)NewSummon); + + m_caster->SetPet(NewSummon); + sLog.outDebug("New Pet has guid %u", NewSummon->GetGUIDLow()); + + if(m_caster->GetTypeId() == TYPEID_PLAYER) + { + NewSummon->SavePetToDB(PET_SAVE_AS_CURRENT); + ((Player*)m_caster)->PetSpellInitialize(); + } +} + +void Spell::EffectLearnPetSpell(uint32 i) +{ + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + Player *_player = (Player*)m_caster; + + Pet *pet = _player->GetPet(); + if(!pet) + return; + if(!pet->isAlive()) + return; + + SpellEntry const *learn_spellproto = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]); + if(!learn_spellproto) + return; + + pet->SetTP(pet->m_TrainingPoints - pet->GetTPForSpell(learn_spellproto->Id)); + pet->learnSpell(learn_spellproto->Id); + + pet->SavePetToDB(PET_SAVE_AS_CURRENT); + _player->PetSpellInitialize(); +} + +void Spell::EffectTaunt(uint32 /*i*/) +{ + // this effect use before aura Taunt apply for prevent taunt already attacking target + // for spell as marked "non effective at already attacking target" + if(unitTarget && unitTarget->GetTypeId() != TYPEID_PLAYER) + { + if(unitTarget->getVictim()==m_caster) + { + SendCastResult(SPELL_FAILED_DONT_REPORT); + return; + } + } + + // Also use this effect to set the taunter's threat to the taunted creature's highest value + if(unitTarget->CanHaveThreatList() && unitTarget->getThreatManager().getCurrentVictim()) + unitTarget->getThreatManager().addThreat(m_caster,unitTarget->getThreatManager().getCurrentVictim()->getThreat()); +} + +void Spell::EffectWeaponDmg(uint32 i) +{ + if(!unitTarget) + return; + if(!unitTarget->isAlive()) + return; + + // multiple weapon dmg effect workaround + // execute only the last weapon damage + // and handle all effects at once + for (int j = 0; j < 3; j++) + { + switch(m_spellInfo->Effect[j]) + { + case SPELL_EFFECT_WEAPON_DAMAGE: + case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: + case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: + case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: + if (j < i) // we must calculate only at last weapon effect + return; + break; + } + } + + // some spell specific modifiers + bool customBonusDamagePercentMod = false; + float bonusDamagePercentMod = 1.0f; // applied to fixed effect damage bonus if set customBonusDamagePercentMod + float weaponDamagePercentMod = 1.0f; // applied to weapon damage (and to fixed effect damage bonus if customBonusDamagePercentMod not set + float totalDamagePercentMod = 1.0f; // applied to final bonus+weapon damage + bool normalized = false; + + int32 spell_bonus = 0; // bonus specific for spell + switch(m_spellInfo->SpellFamilyName) + { + case SPELLFAMILY_WARRIOR: + { + // Whirlwind, single only spell with 2 weapon white damage apply if have + if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x00000400000000LL)) + { + if(((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK,true)) + spell_bonus += m_caster->CalculateDamage (OFF_ATTACK, normalized); + } + // Devastate bonus and sunder armor refresh + else if(m_spellInfo->SpellVisual == 671 && m_spellInfo->SpellIconID == 1508) + { + customBonusDamagePercentMod = true; + bonusDamagePercentMod = 0.0f; // only applied if auras found + + Unit::AuraList const& list = unitTarget->GetAurasByType(SPELL_AURA_MOD_RESISTANCE); + for(Unit::AuraList::const_iterator itr=list.begin();itr!=list.end();++itr) + { + SpellEntry const *proto = (*itr)->GetSpellProto(); + if(proto->SpellVisual == 406 && proto->SpellIconID == 565) + { + int32 duration = GetSpellDuration(proto); + (*itr)->SetAuraDuration(duration); + (*itr)->UpdateAuraDuration(); + bonusDamagePercentMod += 1.0f; // +100% + } + } + } + break; + } + case SPELLFAMILY_ROGUE: + { + // Ambush + if(m_spellInfo->SpellFamilyFlags & 0x00000200LL) + { + customBonusDamagePercentMod = true; + bonusDamagePercentMod = 2.5f; // 250% + } + // Mutilate (for each hand) + else if(m_spellInfo->SpellFamilyFlags & 0x600000000LL) + { + bool found = false; + // fast check + if(unitTarget->HasAuraState(AURA_STATE_DEADLY_POISON)) + found = true; + // full aura scan + else + { + Unit::AuraMap const& auras = unitTarget->GetAuras(); + for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr) + { + if(itr->second->GetSpellProto()->Dispel == DISPEL_POISON) + { + found = true; + break; + } + } + } + + if(found) + totalDamagePercentMod *= 1.5f; // 150% if poisoned + } + break; + } + case SPELLFAMILY_PALADIN: + { + // Seal of Command - receive benefit from Spell Damage and Healing + if(m_spellInfo->SpellFamilyFlags & 0x00000002000000LL) + { + spell_bonus += int32(0.20f*m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo))); + spell_bonus += int32(0.29f*m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget)); + } + break; + } + case SPELLFAMILY_SHAMAN: + { + // Skyshatter Harness item set bonus + // Stormstrike + if(m_spellInfo->SpellFamilyFlags & 0x001000000000LL) + { + Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + for(Unit::AuraList::const_iterator i = m_OverrideClassScript.begin(); i != m_OverrideClassScript.end(); ++i) + { + // Stormstrike AP Buff + if ( (*i)->GetModifier()->m_miscvalue == 5634 ) + { + m_caster->CastSpell(m_caster,38430,true,NULL,*i); + break; + } + } + } + } + } + + int32 fixed_bonus = 0; + for (int j = 0; j < 3; j++) + { + switch(m_spellInfo->Effect[j]) + { + case SPELL_EFFECT_WEAPON_DAMAGE: + case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: + fixed_bonus += CalculateDamage(j,unitTarget); + break; + case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: + fixed_bonus += CalculateDamage(j,unitTarget); + normalized = true; + break; + case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: + weaponDamagePercentMod *= float(CalculateDamage(j,unitTarget)) / 100.0f; + + // applied only to prev.effects fixed damage + if(customBonusDamagePercentMod) + fixed_bonus = int32(fixed_bonus*bonusDamagePercentMod); + else + fixed_bonus = int32(fixed_bonus*weaponDamagePercentMod); + break; + default: + break; // not weapon damage effect, just skip + } + } + + // non-weapon damage + int32 bonus = spell_bonus + fixed_bonus; + + // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage + if(bonus) + { + UnitMods unitMod; + switch(m_attackType) + { + default: + case BASE_ATTACK: unitMod = UNIT_MOD_DAMAGE_MAINHAND; break; + case OFF_ATTACK: unitMod = UNIT_MOD_DAMAGE_OFFHAND; break; + case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED; break; + } + + float weapon_total_pct = m_caster->GetModifierValue(unitMod, TOTAL_PCT); + bonus = int32(bonus*weapon_total_pct); + } + + // + weapon damage with applied weapon% dmg to base weapon damage in call + bonus += int32(m_caster->CalculateDamage(m_attackType, normalized)*weaponDamagePercentMod); + + // total damage + bonus = int32(bonus*totalDamagePercentMod); + + // prevent negative damage + uint32 eff_damage = uint32(bonus > 0 ? bonus : 0); + + const uint32 nohitMask = HITINFO_ABSORB | HITINFO_RESIST | HITINFO_MISS; + + uint32 hitInfo = 0; + VictimState victimState = VICTIMSTATE_NORMAL; + uint32 blocked_dmg = 0; + uint32 absorbed_dmg = 0; + uint32 resisted_dmg = 0; + CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL ); + + m_caster->DoAttackDamage(unitTarget, &eff_damage, &cleanDamage, &blocked_dmg, m_spellSchoolMask, &hitInfo, &victimState, &absorbed_dmg, &resisted_dmg, m_attackType, m_spellInfo, m_IsTriggeredSpell); + + if ((hitInfo & nohitMask) && m_attackType != RANGED_ATTACK) // not send ranged miss/etc + m_caster->SendAttackStateUpdate(hitInfo & nohitMask, unitTarget, 1, m_spellSchoolMask, eff_damage, absorbed_dmg, resisted_dmg, VICTIMSTATE_NORMAL, blocked_dmg); + + bool criticalhit = (hitInfo & HITINFO_CRITICALHIT); + m_caster->SendSpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, eff_damage, m_spellSchoolMask, absorbed_dmg, resisted_dmg, false, blocked_dmg, criticalhit); + + if (eff_damage > (absorbed_dmg + resisted_dmg + blocked_dmg)) + { + eff_damage -= (absorbed_dmg + resisted_dmg + blocked_dmg); + } + else + { + cleanDamage.damage += eff_damage; + eff_damage = 0; + } + + // SPELL_SCHOOL_NORMAL use for weapon-like threat and rage calculation + m_caster->DealDamage(unitTarget, eff_damage, &cleanDamage, SPELL_DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, true); + + // Hemorrhage + if(m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & 0x2000000)) + { + if(m_caster->GetTypeId()==TYPEID_PLAYER) + ((Player*)m_caster)->AddComboPoints(unitTarget, 1); + } + // Mangle (Cat): CP + if(m_spellInfo->SpellFamilyName==SPELLFAMILY_DRUID && (m_spellInfo->SpellFamilyFlags==0x0000040000000000LL)) + { + if(m_caster->GetTypeId()==TYPEID_PLAYER) + ((Player*)m_caster)->AddComboPoints(unitTarget,1); + } + + + // take ammo + if(m_attackType == RANGED_ATTACK && m_caster->GetTypeId() == TYPEID_PLAYER) + { + Item *pItem = ((Player*)m_caster)->GetWeaponForAttack( RANGED_ATTACK ); + + // wands don't have ammo + if(!pItem || pItem->IsBroken() || pItem->GetProto()->SubClass==ITEM_SUBCLASS_WEAPON_WAND) + return; + + if( pItem->GetProto()->InventoryType == INVTYPE_THROWN ) + { + if(pItem->GetMaxStackCount()==1) + { + // decrease durability for non-stackable throw weapon + ((Player*)m_caster)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED); + } + else + { + // decrease items amount for stackable throw weapon + uint32 count = 1; + ((Player*)m_caster)->DestroyItemCount( pItem, count, true); + } + } + else if(uint32 ammo = ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID)) + ((Player*)m_caster)->DestroyItemCount(ammo, 1, true); + } +} + +void Spell::EffectThreat(uint32 /*i*/) +{ + if(!unitTarget || !unitTarget->isAlive() || !m_caster->isAlive()) + return; + + if(!unitTarget->CanHaveThreatList()) + return; + + unitTarget->AddThreat(m_caster, float(damage)); +} + +void Spell::EffectHealMaxHealth(uint32 /*i*/) +{ + if(!unitTarget) + return; + if(!unitTarget->isAlive()) + return; + + uint32 heal = m_caster->GetMaxHealth(); + + int32 gain = unitTarget->ModifyHealth(heal); + unitTarget->getHostilRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo); + + m_caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, heal); +} + +void Spell::EffectInterruptCast(uint32 /*i*/) +{ + if(!unitTarget) + return; + if(!unitTarget->isAlive()) + return; + + // TODO: not all spells that used this effect apply cooldown at school spells + // also exist case: apply cooldown to interrupted cast only and to all spells + for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++) + { + if (unitTarget->m_currentSpells[i]) + { + // check if we can interrupt spell + if ( unitTarget->m_currentSpells[i]->m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_INTERRUPT && unitTarget->m_currentSpells[i]->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE ) + { + unitTarget->ProhibitSpellScholl(GetSpellSchoolMask(unitTarget->m_currentSpells[i]->m_spellInfo), GetSpellDuration(m_spellInfo)); + unitTarget->InterruptSpell(i,false); + } + } + } +} + +void Spell::EffectSummonObjectWild(uint32 i) +{ + uint32 gameobject_id = m_spellInfo->EffectMiscValue[i]; + + GameObject* pGameObj = new GameObject; + + WorldObject* target = focusObject; + if( !target ) + target = m_caster; + + float x,y,z; + if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) + { + x = m_targets.m_destX; + y = m_targets.m_destY; + z = m_targets.m_destZ; + } + else + m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE); + + Map *map = target->GetMap(); + + if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map, + x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1)) + { + delete pGameObj; + return; + } + + int32 duration = GetSpellDuration(m_spellInfo); + pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0); + pGameObj->SetSpellId(m_spellInfo->Id); + + if(pGameObj->GetGoType() != GAMEOBJECT_TYPE_FLAGDROP) // make dropped flag clickable for other players (not set owner guid (created by) for this)... + m_caster->AddGameObject(pGameObj); + map->Add(pGameObj); + + if(pGameObj->GetMapId() == 489 && pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP) //WS + { + if(m_caster->GetTypeId() == TYPEID_PLAYER) + { + Player *pl = (Player*)m_caster; + BattleGround* bg = ((Player *)m_caster)->GetBattleGround(); + if(bg && bg->GetTypeID()==BATTLEGROUND_WS && bg->GetStatus() == STATUS_IN_PROGRESS) + { + uint32 team = ALLIANCE; + + if(pl->GetTeam() == team) + team = HORDE; + + ((BattleGroundWS*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID(),team); + } + } + } + + if(pGameObj->GetMapId() == 566 && pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP) //EY + { + if(m_caster->GetTypeId() == TYPEID_PLAYER) + { + BattleGround* bg = ((Player *)m_caster)->GetBattleGround(); + if(bg && bg->GetTypeID()==BATTLEGROUND_EY && bg->GetStatus() == STATUS_IN_PROGRESS) + { + ((BattleGroundEY*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID()); + } + } + } + + if(uint32 linkedEntry = pGameObj->GetLinkedGameObjectEntry()) + { + GameObject* linkedGO = new GameObject; + if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, map, + x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1)) + { + linkedGO->SetRespawnTime(duration > 0 ? duration/1000 : 0); + linkedGO->SetSpellId(m_spellInfo->Id); + + m_caster->AddGameObject(linkedGO); + map->Add(linkedGO); + } + else + { + delete linkedGO; + linkedGO = NULL; + return; + } + } +} + +void Spell::EffectScriptEffect(uint32 effIndex) +{ + // TODO: we must implement hunter pet summon at login there (spell 6962) + + // by spell id + switch(m_spellInfo->Id) + { + // Bending Shinbone + case 8856: + { + if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER) + return; + + uint32 spell_id = 0; + switch(urand(1,5)) + { + case 1: spell_id = 8854; break; + default: spell_id = 8855; break; + } + + m_caster->CastSpell(m_caster,spell_id,true,NULL); + return; + } + + // Healthstone creating spells + case 6201: + case 6202: + case 5699: + case 11729: + case 11730: + case 27230: + { + uint32 itemtype; + uint32 rank = 0; + Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i) + { + if((*i)->GetId() == 18692) + { + rank = 1; + break; + } + else if((*i)->GetId() == 18693) + { + rank = 2; + break; + } + } + + static uint32 const itypes[6][3] = { + { 5512,19004,19005}, // Minor Healthstone + { 5511,19006,19007}, // Lesser Healthstone + { 5509,19008,19009}, // Healthstone + { 5510,19010,19011}, // Greater Healthstone + { 9421,19012,19013}, // Major Healthstone + {22103,22104,22105} // Master Healthstone + }; + + switch(m_spellInfo->Id) + { + case 6201: itemtype=itypes[0][rank];break; // Minor Healthstone + case 6202: itemtype=itypes[1][rank];break; // Lesser Healthstone + case 5699: itemtype=itypes[2][rank];break; // Healthstone + case 11729: itemtype=itypes[3][rank];break; // Greater Healthstone + case 11730: itemtype=itypes[4][rank];break; // Major Healthstone + case 27230: itemtype=itypes[5][rank];break; // Master Healthstone + default: + return; + } + DoCreateItem( effIndex, itemtype ); + return; + } + // Brittle Armor - need remove one 24575 Brittle Armor aura + case 24590: + unitTarget->RemoveSingleAuraFromStack(24575, 0); + unitTarget->RemoveSingleAuraFromStack(24575, 1); + return; + // Mercurial Shield - need remove one 26464 Mercurial Shield aura + case 26465: + unitTarget->RemoveSingleAuraFromStack(26464, 0); + return; + // Orb teleport spells + case 25140: + case 25143: + case 25650: + case 25652: + case 29128: + case 29129: + case 35376: + case 35727: + { + if(!unitTarget) + return; + + uint32 spellid; + switch(m_spellInfo->Id) + { + case 25140: spellid = 32571; break; + case 25143: spellid = 32572; break; + case 25650: spellid = 30140; break; + case 25652: spellid = 30141; break; + case 29128: spellid = 32568; break; + case 29129: spellid = 32569; break; + case 35376: spellid = 25649; break; + case 35727: spellid = 35730; break; + default: + return; + } + + unitTarget->CastSpell(unitTarget,spellid,false); + return; + } + + // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell) + case 22539: + case 22972: + case 22975: + case 22976: + case 22977: + case 22978: + case 22979: + case 22980: + case 22981: + case 22982: + case 22983: + case 22984: + case 22985: + { + if(!unitTarget || !unitTarget->isAlive()) + return; + + // Onyxia Scale Cloak + if(unitTarget->GetDummyAura(22683)) + return; + + // Shadow Flame + m_caster->CastSpell(unitTarget, 22682, true); + return; + } + break; + + // Summon Black Qiraji Battle Tank + case 26656: + { + if(!unitTarget) + return; + + // Prevent stacking of mounts + unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); + + // Two separate mounts depending on area id (allows use both in and out of specific instance) + if (unitTarget->GetAreaId() == 3428) + unitTarget->CastSpell(unitTarget, 25863, false); + else + unitTarget->CastSpell(unitTarget, 26655, false); + break; + } + // Piccolo of the Flaming Fire + case 17512: + { + if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE); + break; + } + + // Dreaming Glory + case 28698: + { + if(!unitTarget) + return; + unitTarget->CastSpell(unitTarget, 28694, true); + break; + } + + // Netherbloom + case 28702: + { + if(!unitTarget) + return; + // 25% chance of casting a random buff + if(roll_chance_i(75)) + return; + + // triggered spells are 28703 to 28707 + // Note: some sources say, that there was the possibility of + // receiving a debuff. However, this seems to be removed by a patch. + const uint32 spellid = 28703; + + // don't overwrite an existing aura + for(uint8 i=0; i<5; i++) + if(unitTarget->HasAura(spellid+i, 0)) + return; + unitTarget->CastSpell(unitTarget, spellid+urand(0, 4), true); + break; + } + + // Nightmare Vine + case 28720: + { + if(!unitTarget) + return; + // 25% chance of casting Nightmare Pollen + if(roll_chance_i(75)) + return; + unitTarget->CastSpell(unitTarget, 28721, true); + break; + } + + // Mirren's Drinking Hat + case 29830: + { + uint32 item = 0; + switch ( urand(1,6) ) + { + case 1: case 2: case 3: item = 23584; break;// Loch Modan Lager + case 4: case 5: item = 23585; break;// Stouthammer Lite + case 6: item = 23586; break;// Aerie Peak Pale Ale + } + if (item) + DoCreateItem(effIndex,item); + break; + } + // Improved Sprint + case 30918: + { + // Removes snares and roots. + uint32 mechanic_mask = (1<GetAuras(); + for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next) + { + next = iter; + ++next; + Aura *aur = iter->second; + if (!aur->IsPositive()) //only remove negative spells + { + // check for mechanic mask + if(GetSpellMechanicMask(aur->GetSpellProto(), aur->GetEffIndex()) & mechanic_mask) + { + unitTarget->RemoveAurasDueToSpell(aur->GetId()); + if(Auras.empty()) + break; + else + next = Auras.begin(); + } + } + } + break; + } + case 41126: // Flame Crash + { + if(!unitTarget) + return; + + unitTarget->CastSpell(unitTarget, 41131, true); + break; + } + case 44876: // Force Cast - Portal Effect: Sunwell Isle + { + if(!unitTarget) + return; + + unitTarget->CastSpell(unitTarget, 44870, true); + break; + } + + // Goblin Weather Machine + case 46203: + { + if(!unitTarget) + return; + + uint32 spellId; + switch(rand()%4) + { + case 0: + spellId=46740; + break; + case 1: + spellId=46739; + break; + case 2: + spellId=46738; + break; + case 3: + spellId=46736; + break; + } + unitTarget->CastSpell(unitTarget, spellId, true); + break; + } + } + + if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN ) + { + switch(m_spellInfo->SpellFamilyFlags) + { + // Judgement + case 0x800000: + { + if(!unitTarget || !unitTarget->isAlive()) + return; + uint32 spellId2 = 0; + + // all seals have aura dummy + Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraList::const_iterator itr = m_dummyAuras.begin(); itr != m_dummyAuras.end(); ++itr) + { + SpellEntry const *spellInfo = (*itr)->GetSpellProto(); + + // search seal (all seals have judgement's aura dummy spell id in 2 effect + if ( !spellInfo || !IsSealSpell((*itr)->GetSpellProto()) || (*itr)->GetEffIndex() != 2 ) + continue; + + // must be calculated base at raw base points in spell proto, GetModifier()->m_value for S.Righteousness modified by SPELLMOD_DAMAGE + spellId2 = (*itr)->GetSpellProto()->EffectBasePoints[2]+1; + + if(spellId2 <= 1) + continue; + + // found, remove seal + m_caster->RemoveAurasDueToSpell((*itr)->GetId()); + + // Sanctified Judgement + Unit::AuraList const& m_auras = m_caster->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraList::const_iterator i = m_auras.begin(); i != m_auras.end(); ++i) + { + if ((*i)->GetSpellProto()->SpellIconID == 205 && (*i)->GetSpellProto()->Attributes == 0x01D0LL) + { + int32 chance = (*i)->GetModifier()->m_amount; + if ( roll_chance_i(chance) ) + { + int32 mana = spellInfo->manaCost; + if ( Player* modOwner = m_caster->GetSpellModOwner() ) + modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_COST, mana); + mana = int32(mana* 0.8f); + m_caster->CastCustomSpell(m_caster,31930,&mana,NULL,NULL,true,NULL,*i); + } + break; + } + } + + break; + } + + m_caster->CastSpell(unitTarget,spellId2,true); + return; + } + } + } + + // normal DB scripted effect + if(!unitTarget) + return; + + sLog.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo->Id); + sWorld.ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget); +} + +void Spell::EffectSanctuary(uint32 /*i*/) +{ + if(!unitTarget) + return; + //unitTarget->CombatStop(); + + unitTarget->CombatStop(); + unitTarget->getHostilRefManager().deleteReferences(); // stop all fighting + // Vanish allows to remove all threat and cast regular stealth so other spells can be used + if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_VANISH)) + { + ((Player *)m_caster)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT); + } +} + +void Spell::EffectAddComboPoints(uint32 /*i*/) +{ + if(!unitTarget) + return; + + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + if(damage <= 0) + return; + + ((Player*)m_caster)->AddComboPoints(unitTarget, damage); +} + +void Spell::EffectDuel(uint32 i) +{ + if(!m_caster || !unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + Player *caster = (Player*)m_caster; + Player *target = (Player*)unitTarget; + + // caster or target already have requested duel + if( caster->duel || target->duel || target->GetSocial()->HasIgnore(caster->GetGUIDLow()) ) + return; + + // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities) + // Don't have to check the target's map since you cannot challenge someone across maps + if( caster->GetMapId() != 0 && caster->GetMapId() != 1 && caster->GetMapId() != 530) + { + SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here + return; + } + + AreaTableEntry const* casterAreaEntry = GetAreaEntryByAreaID(caster->GetZoneId()); + if(casterAreaEntry && (casterAreaEntry->flags & AREA_FLAG_CAPITAL) ) + { + SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here + return; + } + + AreaTableEntry const* targetAreaEntry = GetAreaEntryByAreaID(target->GetZoneId()); + if(targetAreaEntry && (targetAreaEntry->flags & AREA_FLAG_CAPITAL) ) + { + SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here + return; + } + + //CREATE DUEL FLAG OBJECT + GameObject* pGameObj = new GameObject; + + uint32 gameobject_id = m_spellInfo->EffectMiscValue[i]; + + Map *map = m_caster->GetMap(); + if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map, + m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2 , + m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2 , + m_caster->GetPositionZ(), + m_caster->GetOrientation(), 0, 0, 0, 0, 0, 1)) + { + delete pGameObj; + return; + } + + pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction() ); + pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1 ); + int32 duration = GetSpellDuration(m_spellInfo); + pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0); + pGameObj->SetSpellId(m_spellInfo->Id); + + m_caster->AddGameObject(pGameObj); + map->Add(pGameObj); + //END + + // Send request + WorldPacket data(SMSG_DUEL_REQUESTED, 16); + data << pGameObj->GetGUID(); + data << caster->GetGUID(); + caster->GetSession()->SendPacket(&data); + target->GetSession()->SendPacket(&data); + + // create duel-info + DuelInfo *duel = new DuelInfo; + duel->initiator = caster; + duel->opponent = target; + duel->startTime = 0; + duel->startTimer = 0; + caster->duel = duel; + + DuelInfo *duel2 = new DuelInfo; + duel2->initiator = caster; + duel2->opponent = caster; + duel2->startTime = 0; + duel2->startTimer = 0; + target->duel = duel2; + + caster->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID()); + target->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID()); +} + +void Spell::EffectStuck(uint32 /*i*/) +{ + if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + if(!sWorld.getConfig(CONFIG_CAST_UNSTUCK)) + return; + + Player* pTarget = (Player*)unitTarget; + + sLog.outDebug("Spell Effect: Stuck"); + sLog.outDetail("Player %s (guid %u) used auto-unstuck future at map %u (%f, %f, %f)", pTarget->GetName(), pTarget->GetGUIDLow(), m_caster->GetMapId(), m_caster->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ()); + + if(pTarget->isInFlight()) + return; + + // homebind location is loaded always + pTarget->TeleportTo(pTarget->m_homebindMapId,pTarget->m_homebindX,pTarget->m_homebindY,pTarget->m_homebindZ,pTarget->GetOrientation(), (unitTarget==m_caster ? TELE_TO_SPELL : 0)); + + // Stuck spell trigger Hearthstone cooldown + SpellEntry const *spellInfo = sSpellStore.LookupEntry(8690); + if(!spellInfo) + return; + Spell spell(pTarget,spellInfo,true,0); + spell.SendSpellCooldown(); +} + +void Spell::EffectSummonPlayer(uint32 /*i*/) +{ + if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + // Evil Twin (ignore player summon, but hide this for summoner) + if(unitTarget->GetDummyAura(23445)) + return; + + float x,y,z; + m_caster->GetClosePoint(x,y,z,unitTarget->GetObjectSize()); + + ((Player*)unitTarget)->SetSummonPoint(m_caster->GetMapId(),x,y,z); + + WorldPacket data(SMSG_SUMMON_REQUEST, 8+4+4); + data << uint64(m_caster->GetGUID()); // summoner guid + data << uint32(m_caster->GetZoneId()); // summoner zone + data << uint32(MAX_PLAYER_SUMMON_DELAY*1000); // auto decline after msecs + ((Player*)unitTarget)->GetSession()->SendPacket(&data); +} + +static ScriptInfo generateActivateCommand() +{ + ScriptInfo si; + si.command = SCRIPT_COMMAND_ACTIVATE_OBJECT; + return si; +} + +void Spell::EffectActivateObject(uint32 effect_idx) +{ + if(!gameObjTarget) + return; + + static ScriptInfo activateCommand = generateActivateCommand(); + + int32 delay_secs = m_spellInfo->EffectMiscValue[effect_idx]; + + sWorld.ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget); +} + +void Spell::EffectSummonTotem(uint32 i) +{ + uint8 slot = 0; + switch(m_spellInfo->EffectMiscValueB[i]) + { + case SUMMON_TYPE_TOTEM_SLOT1: slot = 0; break; + case SUMMON_TYPE_TOTEM_SLOT2: slot = 1; break; + case SUMMON_TYPE_TOTEM_SLOT3: slot = 2; break; + case SUMMON_TYPE_TOTEM_SLOT4: slot = 3; break; + // Battle standard case + case SUMMON_TYPE_TOTEM: slot = 254; break; + // jewelery statue case, like totem without slot + case SUMMON_TYPE_GUARDIAN: slot = 255; break; + default: return; + } + + if(slot < MAX_TOTEM) + { + uint64 guid = m_caster->m_TotemSlot[slot]; + if(guid != 0) + { + Creature *OldTotem = ObjectAccessor::GetCreature(*m_caster, guid); + if(OldTotem && OldTotem->isTotem()) + ((Totem*)OldTotem)->UnSummon(); + } + } + + uint32 team = 0; + if (m_caster->GetTypeId()==TYPEID_PLAYER) + team = ((Player*)m_caster)->GetTeam(); + + Totem* pTotem = new Totem; + + if(!pTotem->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMap(), m_spellInfo->EffectMiscValue[i], team )) + { + delete pTotem; + return; + } + + float angle = slot < MAX_TOTEM ? M_PI/MAX_TOTEM - (slot*2*M_PI/MAX_TOTEM) : 0; + + float x,y,z; + m_caster->GetClosePoint(x,y,z,pTotem->GetObjectSize(),2.0f,angle); + + // totem must be at same Z in case swimming caster and etc. + if( fabs( z - m_caster->GetPositionZ() ) > 5 ) + z = m_caster->GetPositionZ(); + + pTotem->Relocate(x, y, z, m_caster->GetOrientation()); + + if(slot < MAX_TOTEM) + m_caster->m_TotemSlot[slot] = pTotem->GetGUID(); + + pTotem->SetOwner(m_caster->GetGUID()); + pTotem->SetTypeBySummonSpell(m_spellInfo); // must be after Create call where m_spells initilized + + int32 duration=GetSpellDuration(m_spellInfo); + if(Player* modOwner = m_caster->GetSpellModOwner()) + modOwner->ApplySpellMod(m_spellInfo->Id,SPELLMOD_DURATION, duration); + pTotem->SetDuration(duration); + + if (damage) // if not spell info, DB values used + { + pTotem->SetMaxHealth(damage); + pTotem->SetHealth(damage); + } + + pTotem->SetUInt32Value(UNIT_CREATED_BY_SPELL,m_spellInfo->Id); + pTotem->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE); + + pTotem->ApplySpellImmune(m_spellInfo->Id,IMMUNITY_STATE,SPELL_AURA_MOD_FEAR,true); + pTotem->ApplySpellImmune(m_spellInfo->Id,IMMUNITY_STATE,SPELL_AURA_TRANSFORM,true); + + pTotem->Summon(m_caster); + + if(slot < MAX_TOTEM && m_caster->GetTypeId() == TYPEID_PLAYER) + { + WorldPacket data(SMSG_TOTEM_CREATED, 1+8+4+4); + data << uint8(slot); + data << uint64(pTotem->GetGUID()); + data << uint32(duration); + data << uint32(m_spellInfo->Id); + ((Player*)m_caster)->SendDirectMessage(&data); + } +} + +void Spell::EffectEnchantHeldItem(uint32 i) +{ + // this is only item spell effect applied to main-hand weapon of target player (players in area) + if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + Player* item_owner = (Player*)unitTarget; + Item* item = item_owner->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND); + + if(!item ) + return; + + // must be equipped + if(!item ->IsEquipped()) + return; + + if (m_spellInfo->EffectMiscValue[i]) + { + uint32 enchant_id = m_spellInfo->EffectMiscValue[i]; + int32 duration = GetSpellDuration(m_spellInfo); //Try duration index first .. + if(!duration) + duration = m_currentBasePoints[i]+1; //Base points after .. + if(!duration) + duration = 10; //10 seconds for enchants which don't have listed duration + + SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id); + if(!pEnchant) + return; + + // Always go to temp enchantment slot + EnchantmentSlot slot = TEMP_ENCHANTMENT_SLOT; + + // Enchantment will not be applied if a different one already exists + if(item->GetEnchantmentId(slot) && item->GetEnchantmentId(slot) != enchant_id) + return; + + // Apply the temporary enchantment + item->SetEnchantment(slot, enchant_id, duration*1000, 0); + item_owner->ApplyEnchantment(item,slot,true); + } +} + +void Spell::EffectDisEnchant(uint32 /*i*/) +{ + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + Player* p_caster = (Player*)m_caster; + if(!itemTarget || !itemTarget->GetProto()->DisenchantID) + return; + + p_caster->UpdateCraftSkill(m_spellInfo->Id); + + ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(),LOOT_DISENCHANTING); + + // item will be removed at disenchanting end +} + +void Spell::EffectInebriate(uint32 /*i*/) +{ + if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + Player *player = (Player*)unitTarget; + uint16 currentDrunk = player->GetDrunkValue(); + uint16 drunkMod = damage * 256; + if (currentDrunk + drunkMod > 0xFFFF) + currentDrunk = 0xFFFF; + else + currentDrunk += drunkMod; + player->SetDrunkValue(currentDrunk, m_CastItem?m_CastItem->GetEntry():0); +} + +void Spell::EffectFeedPet(uint32 i) +{ + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + Player *_player = (Player*)m_caster; + + if(!itemTarget) + return; + + Pet *pet = _player->GetPet(); + if(!pet) + return; + + if(!pet->isAlive()) + return; + + int32 benefit = pet->GetCurrentFoodBenefitLevel(itemTarget->GetProto()->ItemLevel); + if(benefit <= 0) + return; + + uint32 count = 1; + _player->DestroyItemCount(itemTarget,count,true); + // TODO: fix crash when a spell has two effects, both pointed at the same item target + + m_caster->CastCustomSpell(m_caster,m_spellInfo->EffectTriggerSpell[i],&benefit,NULL,NULL,true); +} + +void Spell::EffectDismissPet(uint32 /*i*/) +{ + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + Pet* pet = m_caster->GetPet(); + + // not let dismiss dead pet + if(!pet||!pet->isAlive()) + return; + + ((Player*)m_caster)->RemovePet(pet,PET_SAVE_NOT_IN_SLOT); +} + +void Spell::EffectSummonObject(uint32 i) +{ + uint32 go_id = m_spellInfo->EffectMiscValue[i]; + + uint8 slot = 0; + switch(m_spellInfo->Effect[i]) + { + case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: slot = 0; break; + case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: slot = 1; break; + case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: slot = 2; break; + case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: slot = 3; break; + default: return; + } + + uint64 guid = m_caster->m_ObjectSlot[slot]; + if(guid != 0) + { + GameObject* obj = NULL; + if( m_caster ) + obj = ObjectAccessor::GetGameObject(*m_caster, guid); + + if(obj) obj->Delete(); + m_caster->m_ObjectSlot[slot] = 0; + } + + GameObject* pGameObj = new GameObject; + + float rot2 = sin(m_caster->GetOrientation()/2); + float rot3 = cos(m_caster->GetOrientation()/2); + + float x,y,z; + // If dest location if present + if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) + { + x = m_targets.m_destX; + y = m_targets.m_destY; + z = m_targets.m_destZ; + } + // Summon in random point all other units if location present + else + m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE); + + Map *map = m_caster->GetMap(); + if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map, x, y, z, m_caster->GetOrientation(), 0, 0, rot2, rot3, 0, 1)) + { + delete pGameObj; + return; + } + + pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL,m_caster->getLevel()); + int32 duration = GetSpellDuration(m_spellInfo); + pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0); + pGameObj->SetSpellId(m_spellInfo->Id); + m_caster->AddGameObject(pGameObj); + + map->Add(pGameObj); + WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8); + data << pGameObj->GetGUID(); + m_caster->SendMessageToSet(&data,true); + + m_caster->m_ObjectSlot[slot] = pGameObj->GetGUID(); +} + +void Spell::EffectResurrect(uint32 i) +{ + if(!unitTarget) + return; + if(unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + if(unitTarget->isAlive()) + return; + if(!unitTarget->IsInWorld()) + return; + + switch (m_spellInfo->Id) + { + // Defibrillate (Goblin Jumper Cables) have 33% chance on success + case 8342: + if (roll_chance_i(67)) + { + m_caster->CastSpell(m_caster, 8338, true, m_CastItem); + return; + } + break; + // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success + case 22999: + if (roll_chance_i(50)) + { + m_caster->CastSpell(m_caster, 23055, true, m_CastItem); + return; + } + break; + default: + break; + } + + Player* pTarget = ((Player*)unitTarget); + + if(pTarget->isRessurectRequested()) // already have one active request + return; + + uint32 health = pTarget->GetMaxHealth() * damage / 100; + uint32 mana = pTarget->GetMaxPower(POWER_MANA) * damage / 100; + + pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana); + SendResurrectRequest(pTarget); +} + +void Spell::EffectAddExtraAttacks(uint32 /*i*/) +{ + if(!unitTarget || !unitTarget->isAlive()) + return; + + if( unitTarget->m_extraAttacks ) + return; + + unitTarget->m_extraAttacks = damage; +} + +void Spell::EffectParry(uint32 /*i*/) +{ + if (unitTarget->GetTypeId() == TYPEID_PLAYER) + { + ((Player*)unitTarget)->SetCanParry(true); + } +} + +void Spell::EffectMomentMove(uint32 i) +{ + if(unitTarget->isInFlight()) + return; + + if( m_spellInfo->rangeIndex== 1) //self range + { + uint32 mapid = m_caster->GetMapId(); + float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + + // before caster + float fx,fy,fz; + unitTarget->GetClosePoint(fx,fy,fz,unitTarget->GetObjectSize(),dis); + float ox,oy,oz; + unitTarget->GetPosition(ox,oy,oz); + + float fx2,fy2,fz2; // getObjectHitPos overwrite last args in any result case + if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(mapid, ox,oy,oz+0.5, fx,fy,oz+0.5,fx2,fy2,fz2, -0.5)) + { + fx = fx2; + fy = fy2; + fz = fz2; + unitTarget->UpdateGroundPositionZ(fx,fy,fz); + } + + if(unitTarget->GetTypeId() == TYPEID_PLAYER) + ((Player*)unitTarget)->TeleportTo(mapid, fx, fy, fz, unitTarget->GetOrientation(), TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0)); + else + MapManager::Instance().GetMap(mapid, unitTarget)->CreatureRelocation((Creature*)unitTarget, fx, fy, fz, unitTarget->GetOrientation()); + } +} + +void Spell::EffectReputation(uint32 i) +{ + if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + Player *_player = (Player*)unitTarget; + + int32 rep_change = m_currentBasePoints[i]+1; // field store reputation change -1 + + uint32 faction_id = m_spellInfo->EffectMiscValue[i]; + + FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id); + + if(!factionEntry) + return; + + _player->ModifyFactionReputation(factionEntry,rep_change); +} + +void Spell::EffectQuestComplete(uint32 i) +{ + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + Player *_player = (Player*)m_caster; + + uint32 quest_id = m_spellInfo->EffectMiscValue[i]; + _player->AreaExploredOrEventHappens(quest_id); +} + +void Spell::EffectSelfResurrect(uint32 i) +{ + if(!unitTarget || unitTarget->isAlive()) + return; + if(unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + if(!unitTarget->IsInWorld()) + return; + + uint32 health = 0; + uint32 mana = 0; + + // flat case + if(damage < 0) + { + health = uint32(-damage); + mana = m_spellInfo->EffectMiscValue[i]; + } + // percent case + else + { + health = uint32(damage/100.0f*unitTarget->GetMaxHealth()); + if(unitTarget->GetMaxPower(POWER_MANA) > 0) + mana = uint32(damage/100.0f*unitTarget->GetMaxPower(POWER_MANA)); + } + + Player *plr = ((Player*)unitTarget); + plr->ResurrectPlayer(0.0f); + + plr->SetHealth( health ); + plr->SetPower(POWER_MANA, mana ); + plr->SetPower(POWER_RAGE, 0 ); + plr->SetPower(POWER_ENERGY, plr->GetMaxPower(POWER_ENERGY) ); + + plr->SpawnCorpseBones(); + + plr->SaveToDB(); +} + +void Spell::EffectSkinning(uint32 /*i*/) +{ + if(unitTarget->GetTypeId() != TYPEID_UNIT ) + return; + if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + Creature* creature = (Creature*) unitTarget; + int32 targetLevel = creature->getLevel(); + + uint32 skill; + if(creature->GetCreatureInfo()->flag1 & 256) + skill = SKILL_HERBALISM; // special case + else if(creature->GetCreatureInfo()->flag1 & 512) + skill = SKILL_MINING; // special case + else + skill = SKILL_SKINNING; // normal case + + ((Player*)m_caster)->SendLoot(creature->GetGUID(),LOOT_SKINNING); + creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); + + int32 reqValue = targetLevel < 10 ? 0 : targetLevel < 20 ? (targetLevel-10)*10 : targetLevel*5; + + int32 skillValue = ((Player*)m_caster)->GetPureSkillValue(skill); + + // Double chances for elites + ((Player*)m_caster)->UpdateGatherSkill(skill, skillValue, reqValue, creature->isElite() ? 2 : 1 ); +} + +void Spell::EffectCharge(uint32 /*i*/) +{ + if(!unitTarget || !m_caster) + return; + + float x, y, z; + unitTarget->GetContactPoint(m_caster, x, y, z); + if(unitTarget->GetTypeId() != TYPEID_PLAYER) + ((Creature *)unitTarget)->StopMoving(); + + // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags + m_caster->SendMonsterMove(x, y, z, 0, MOVEMENTFLAG_WALK_MODE, 1); + + if(m_caster->GetTypeId() != TYPEID_PLAYER) + MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)->CreatureRelocation((Creature*)m_caster,x,y,z,m_caster->GetOrientation()); + + // not all charge effects used in negative spells + if ( !IsPositiveSpell(m_spellInfo->Id)) + m_caster->Attack(unitTarget,true); +} + +void Spell::EffectSummonCritter(uint32 i) +{ + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; + Player* player = (Player*)m_caster; + + uint32 pet_entry = m_spellInfo->EffectMiscValue[i]; + if(!pet_entry) + return; + + Pet* old_critter = player->GetMiniPet(); + + // for same pet just despawn + if(old_critter && old_critter->GetEntry() == pet_entry) + { + player->RemoveMiniPet(); + return; + } + + // despawn old pet before summon new + if(old_critter) + player->RemoveMiniPet(); + + // summon new pet + Pet* critter = new Pet(MINI_PET); + + Map *map = m_caster->GetMap(); + uint32 pet_number = objmgr.GeneratePetNumber(); + if(!critter->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), + map, pet_entry, pet_number)) + { + sLog.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo->Id, pet_entry); + delete critter; + return; + } + + float x,y,z; + // If dest location if present + if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) + { + x = m_targets.m_destX; + y = m_targets.m_destY; + z = m_targets.m_destZ; + } + // Summon if dest location not present near caster + else + m_caster->GetClosePoint(x,y,z,critter->GetObjectSize()); + + critter->Relocate(x,y,z,m_caster->GetOrientation()); + + if(!critter->IsPositionValid()) + { + sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %d Y: ^%d)", critter->GetGUIDLow(), critter->GetEntry(), critter->GetPositionX(), critter->GetPositionY()); + delete critter; + return; + } + + critter->SetUInt64Value(UNIT_FIELD_SUMMONEDBY,m_caster->GetGUID()); + critter->SetUInt64Value(UNIT_FIELD_CREATEDBY,m_caster->GetGUID()); + critter->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction()); + critter->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id); + + critter->AIM_Initialize(); + critter->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter... + critter->SetMaxHealth(1); + critter->SetHealth(1); + critter->SetLevel(1); + + // set timer for unsummon + int32 duration = GetSpellDuration(m_spellInfo); + if(duration > 0) + critter->SetDuration(duration); + + std::string name = player->GetName(); + name.append(petTypeSuffix[critter->getPetType()]); + critter->SetName( name ); + player->SetMiniPet(critter); + + map->Add((Creature*)critter); +} + +void Spell::EffectKnockBack(uint32 i) +{ + if(!unitTarget || !m_caster) + return; + + // Effect only works on players + if(unitTarget->GetTypeId()!=TYPEID_PLAYER) + return; + + float vsin = sin(m_caster->GetAngle(unitTarget)); + float vcos = cos(m_caster->GetAngle(unitTarget)); + + WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4)); + data.append(unitTarget->GetPackGUID()); + data << uint32(0); // Sequence + data << float(vcos); // x direction + data << float(vsin); // y direction + data << float(m_spellInfo->EffectMiscValue[i])/10; // Horizontal speed + data << float(damage/-10); // Z Movement speed (vertical) + + ((Player*)unitTarget)->GetSession()->SendPacket(&data); +} + +void Spell::EffectSendTaxi(uint32 i) +{ + if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(m_spellInfo->EffectMiscValue[i]); + if(!entry) + return; + + std::vector nodes; + + nodes.resize(2); + nodes[0] = entry->from; + nodes[1] = entry->to; + + uint32 mountid = 0; + switch(m_spellInfo->Id) + { + case 31606: //Stormcrow Amulet + mountid = 17447; + break; + case 45071: //Quest - Sunwell Daily - Dead Scar Bombing Run + case 45113: //Quest - Sunwell Daily - Ship Bombing Run + case 45353: //Quest - Sunwell Daily - Ship Bombing Run Return + mountid = 22840; + break; + case 34905: //Stealth Flight + mountid = 6851; + break; + } + + ((Player*)unitTarget)->ActivateTaxiPathTo(nodes,mountid); + +} + +void Spell::EffectPlayerPull(uint32 i) +{ + if(!unitTarget || !m_caster) + return; + + // Effect only works on players + if(unitTarget->GetTypeId()!=TYPEID_PLAYER) + return; + + float vsin = sin(unitTarget->GetAngle(m_caster)); + float vcos = cos(unitTarget->GetAngle(m_caster)); + + WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4)); + data.append(unitTarget->GetPackGUID()); + data << uint32(0); // Sequence + data << float(vcos); // x direction + data << float(vsin); // y direction + // Horizontal speed + data << float(damage ? damage : unitTarget->GetDistance2d(m_caster)); + data << float(m_spellInfo->EffectMiscValue[i])/-10; // Z Movement speed + + ((Player*)unitTarget)->GetSession()->SendPacket(&data); +} + +void Spell::EffectDispelMechanic(uint32 i) +{ + if(!unitTarget) + return; + + uint32 mechanic = m_spellInfo->EffectMiscValue[i]; + + Unit::AuraMap& Auras = unitTarget->GetAuras(); + for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next) + { + next = iter; + ++next; + SpellEntry const *spell = sSpellStore.LookupEntry(iter->second->GetSpellProto()->Id); + if(spell->Mechanic == mechanic || spell->EffectMechanic[iter->second->GetEffIndex()] == mechanic) + { + unitTarget->RemoveAurasDueToSpell(spell->Id); + if(Auras.empty()) + break; + else + next = Auras.begin(); + } + } + return; +} + +void Spell::EffectSummonDeadPet(uint32 /*i*/) +{ + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; + Player *_player = (Player*)m_caster; + Pet *pet = _player->GetPet(); + if(!pet) + return; + if(pet->isAlive()) + return; + if(damage < 0) + return; + pet->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0); + pet->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); + pet->setDeathState( ALIVE ); + pet->clearUnitState(UNIT_STAT_ALL_STATE); + pet->SetHealth( uint32(pet->GetMaxHealth()*(float(damage)/100))); + + pet->AIM_Initialize(); + + _player->PetSpellInitialize(); + pet->SavePetToDB(PET_SAVE_AS_CURRENT); +} + +void Spell::EffectDestroyAllTotems(uint32 /*i*/) +{ + float mana = 0; + for(int slot = 0; slot < MAX_TOTEM; ++slot) + { + if(!m_caster->m_TotemSlot[slot]) + continue; + + Creature* totem = ObjectAccessor::GetCreature(*m_caster,m_caster->m_TotemSlot[slot]); + if(totem && totem->isTotem()) + { + uint32 spell_id = totem->GetUInt32Value(UNIT_CREATED_BY_SPELL); + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id); + if(spellInfo) + mana += spellInfo->manaCost * damage / 100; + ((Totem*)totem)->UnSummon(); + } + } + + int32 gain = m_caster->ModifyPower(POWER_MANA,int32(mana)); + m_caster->SendEnergizeSpellLog(m_caster, m_spellInfo->Id, gain, POWER_MANA); +} + +void Spell::EffectDurabilityDamage(uint32 i) +{ + if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + int32 slot = m_spellInfo->EffectMiscValue[i]; + + // FIXME: some spells effects have value -1/-2 + // Possibly its mean -1 all player equipped items and -2 all items + if(slot < 0) + { + ((Player*)unitTarget)->DurabilityPointsLossAll(damage,(slot < -1)); + return; + } + + // invalid slot value + if(slot >= INVENTORY_SLOT_BAG_END) + return; + + if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0,slot)) + ((Player*)unitTarget)->DurabilityPointsLoss(item,damage); +} + +void Spell::EffectDurabilityDamagePCT(uint32 i) +{ + if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + int32 slot = m_spellInfo->EffectMiscValue[i]; + + // FIXME: some spells effects have value -1/-2 + // Possibly its mean -1 all player equipped items and -2 all items + if(slot < 0) + { + ((Player*)unitTarget)->DurabilityLossAll(double(damage)/100.0f,(slot < -1)); + return; + } + + // invalid slot value + if(slot >= INVENTORY_SLOT_BAG_END) + return; + + if(damage <= 0) + return; + + if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0,slot)) + ((Player*)unitTarget)->DurabilityLoss(item,double(damage)/100.0f); +} + +void Spell::EffectModifyThreatPercent(uint32 /*effIndex*/) +{ + if(!unitTarget) + return; + + unitTarget->getThreatManager().modifyThreatPercent(m_caster, damage); +} + +void Spell::EffectTransmitted(uint32 effIndex) +{ + uint32 name_id = m_spellInfo->EffectMiscValue[effIndex]; + + GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(name_id); + + if (!goinfo) + { + sLog.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id, m_spellInfo->Id); + return; + } + + float fx,fy,fz; + + if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) + { + fx = m_targets.m_destX; + fy = m_targets.m_destY; + fz = m_targets.m_destZ; + } + //FIXME: this can be better check for most objects but still hack + else if(m_spellInfo->EffectRadiusIndex[effIndex] && m_spellInfo->speed==0) + { + float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[effIndex])); + m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis); + } + else + { + float min_dis = GetSpellMinRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex)); + float max_dis = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex)); + float dis = rand_norm() * (max_dis - min_dis) + min_dis; + + m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis); + } + + Map *cMap = m_caster->GetMap(); + + if(goinfo->type==GAMEOBJECT_TYPE_FISHINGNODE) + { + if ( !cMap->IsInWater(fx,fy,fz-0.5f)) // Hack to prevent fishing bobber from failing to land on fishing hole + { // but this is not proper, we really need to ignore not materialized objects + SendCastResult(SPELL_FAILED_NOT_HERE); + SendChannelUpdate(0); + return; + } + + // replace by water level in this case + fz = cMap->GetWaterLevel(fx,fy); + } + // if gameobject is summoning object, it should be spawned right on caster's position + else if(goinfo->type==GAMEOBJECT_TYPE_SUMMONING_RITUAL) + { + m_caster->GetPosition(fx,fy,fz); + } + + GameObject* pGameObj = new GameObject; + + if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id, cMap, + fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1)) + { + delete pGameObj; + return; + } + + int32 duration = GetSpellDuration(m_spellInfo); + + switch(goinfo->type) + { + case GAMEOBJECT_TYPE_FISHINGNODE: + { + m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT,pGameObj->GetGUID()); + // Orientation3 + pGameObj->SetFloatValue(GAMEOBJECT_ROTATION + 2, 0.88431775569915771 ); + // Orientation4 + pGameObj->SetFloatValue(GAMEOBJECT_ROTATION + 3, -0.4668855369091033 ); + m_caster->AddGameObject(pGameObj); // will removed at spell cancel + + // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo)) + // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME) + int32 lastSec; + switch(urand(0, 3)) + { + case 0: lastSec = 3; break; + case 1: lastSec = 7; break; + case 2: lastSec = 13; break; + case 3: lastSec = 17; break; + } + + duration = duration - lastSec*1000 + FISHING_BOBBER_READY_TIME*1000; + break; + } + case GAMEOBJECT_TYPE_SUMMONING_RITUAL: + { + if(m_caster->GetTypeId()==TYPEID_PLAYER) + { + pGameObj->AddUniqueUse((Player*)m_caster); + m_caster->AddGameObject(pGameObj); // will removed at spell cancel + } + break; + } + case GAMEOBJECT_TYPE_FISHINGHOLE: + case GAMEOBJECT_TYPE_CHEST: + default: + { + break; + } + } + + pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0); + + pGameObj->SetOwnerGUID(m_caster->GetGUID() ); + + pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() ); + pGameObj->SetSpellId(m_spellInfo->Id); + + DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted\n"); + //m_caster->AddGameObject(pGameObj); + //m_ObjToDel.push_back(pGameObj); + + cMap->Add(pGameObj); + + WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8); + data << uint64(pGameObj->GetGUID()); + m_caster->SendMessageToSet(&data,true); + + if(uint32 linkedEntry = pGameObj->GetLinkedGameObjectEntry()) + { + GameObject* linkedGO = new GameObject; + if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, cMap, + fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1)) + { + linkedGO->SetRespawnTime(duration > 0 ? duration/1000 : 0); + linkedGO->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() ); + linkedGO->SetSpellId(m_spellInfo->Id); + linkedGO->SetOwnerGUID(m_caster->GetGUID() ); + + MapManager::Instance().GetMap(linkedGO->GetMapId(), linkedGO)->Add(linkedGO); + } + else + { + delete linkedGO; + linkedGO = NULL; + return; + } + } +} + +void Spell::EffectProspecting(uint32 /*i*/) +{ + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + Player* p_caster = (Player*)m_caster; + if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_MINING_SUPP)) + return; + + if(itemTarget->GetCount() < 5) + return; + + if( sWorld.getConfig(CONFIG_SKILL_PROSPECTING)) + { + uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_JEWELCRAFTING); + uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank; + p_caster->UpdateGatherSkill(SKILL_JEWELCRAFTING, SkillValue, reqSkillValue); + } + + ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_PROSPECTING); +} + +void Spell::EffectSkill(uint32 /*i*/) +{ + sLog.outDebug("WORLD: SkillEFFECT"); +} + +void Spell::EffectSummonDemon(uint32 i) +{ + float px = m_targets.m_destX; + float py = m_targets.m_destY; + float pz = m_targets.m_destZ; + + Creature* Charmed = m_caster->SummonCreature(m_spellInfo->EffectMiscValue[i], px, py, pz, m_caster->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,3600000); + if (!Charmed) + return; + + // might not always work correctly, maybe the creature that dies from CoD casts the effect on itself and is therefore the caster? + Charmed->SetLevel(m_caster->getLevel()); + + // TODO: Add damage/mana/hp according to level + + if (m_spellInfo->EffectMiscValue[i] == 89) // Inferno summon + { + // Enslave demon effect, without mana cost and cooldown + m_caster->CastSpell(Charmed, 20882, true); // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved + + // Inferno effect + Charmed->CastSpell(Charmed, 22703, true, 0); + } +} + +/* There is currently no need for this effect. We handle it in BattleGround.cpp + If we would handle the resurrection here, the spiritguide would instantly disappear as the + player revives, and so we wouldn't see the spirit heal visual effect on the npc. + This is why we use a half sec delay between the visual effect and the resurrection itself */ +void Spell::EffectSpiritHeal(uint32 /*i*/) +{ + /* + if(!unitTarget || unitTarget->isAlive()) + return; + if(unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + if(!unitTarget->IsInWorld()) + return; + + //m_spellInfo->EffectBasePoints[i]; == 99 (percent?) + //((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetMaxHealth(), unitTarget->GetMaxPower(POWER_MANA)); + ((Player*)unitTarget)->ResurrectPlayer(1.0f); + ((Player*)unitTarget)->SpawnCorpseBones(); + */ +} + +// remove insignia spell effect +void Spell::EffectSkinPlayerCorpse(uint32 /*i*/) +{ + sLog.outDebug("Effect: SkinPlayerCorpse"); + if ( (m_caster->GetTypeId() != TYPEID_PLAYER) || (unitTarget->GetTypeId() != TYPEID_PLAYER) || (unitTarget->isAlive()) ) + return; + + ((Player*)unitTarget)->RemovedInsignia( (Player*)m_caster ); +} + +void Spell::EffectStealBeneficialBuff(uint32 i) +{ + sLog.outDebug("Effect: StealBeneficialBuff"); + + if(!unitTarget || unitTarget==m_caster) // can't steal from self + return; + + std::vector steal_list; + // Create dispel mask by dispel type + uint32 dispelMask = GetDispellMask( DispelType(m_spellInfo->EffectMiscValue[i]) ); + Unit::AuraMap const& auras = unitTarget->GetAuras(); + for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) + { + Aura *aur = (*itr).second; + if (aur && (1<GetSpellProto()->Dispel) & dispelMask) + { + // Need check for passive? this + if (aur->IsPositive() && !aur->IsPassive()) + steal_list.push_back(aur); + } + } + // Ok if exist some buffs for dispel try dispel it + if (!steal_list.empty()) + { + std::list < std::pair > success_list; + int32 list_size = steal_list.size(); + // Dispell N = damage buffs (or while exist buffs for dispel) + for (int32 count=0; count < damage && list_size > 0; ++count) + { + // Random select buff for dispel + Aura *aur = steal_list[urand(0, list_size-1)]; + // Not use chance for steal + // TODO possible need do it + success_list.push_back( std::pair(aur->GetId(),aur->GetCasterGUID())); + + // Remove buff from list for prevent doubles + for (std::vector::iterator j = steal_list.begin(); j != steal_list.end(); ) + { + Aura *stealed = *j; + if (stealed->GetId() == aur->GetId() && stealed->GetCasterGUID() == aur->GetCasterGUID()) + { + j = steal_list.erase(j); + --list_size; + } + else + ++j; + } + } + // Really try steal and send log + if (!success_list.empty()) + { + int32 count = success_list.size(); + WorldPacket data(SMSG_SPELLSTEALLOG, 8+8+4+1+4+count*5); + data.append(unitTarget->GetPackGUID()); // Victim GUID + data.append(m_caster->GetPackGUID()); // Caster GUID + data << uint32(m_spellInfo->Id); // Dispell spell id + data << uint8(0); // not used + data << uint32(count); // count + for (std::list >::iterator j = success_list.begin(); j != success_list.end(); ++j) + { + SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first); + data << uint32(spellInfo->Id); // Spell Id + data << uint8(0); // 0 - steals !=0 transfers + unitTarget->RemoveAurasDueToSpellBySteal(spellInfo->Id, j->second, m_caster); + } + m_caster->SendMessageToSet(&data, true); + } + } +} + +void Spell::EffectKillCredit(uint32 i) +{ + if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + ((Player*)unitTarget)->KilledMonster(m_spellInfo->EffectMiscValue[i], 0); +} + +void Spell::EffectQuestFail(uint32 i) +{ + if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + ((Player*)unitTarget)->FailQuest(m_spellInfo->EffectMiscValue[i]); +} diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp new file mode 100644 index 00000000000..7bad99b38b5 --- /dev/null +++ b/src/game/SpellHandler.cpp @@ -0,0 +1,460 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Database/DBCStores.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "World.h" +#include "ObjectMgr.h" +#include "SpellMgr.h" +#include "Log.h" +#include "Opcodes.h" +#include "Spell.h" +#include "SpellAuras.h" +#include "BattleGround.h" +#include "MapManager.h" +#include "ScriptCalls.h" +#include "Totem.h" + +void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) +{ + // TODO: add targets.read() check + CHECK_PACKET_SIZE(recvPacket,1+1+1+1+8); + + Player* pUser = _player; + uint8 bagIndex, slot; + uint8 spell_count; // number of spells at item, not used + uint8 cast_count; // next cast if exists (single or not) + uint64 item_guid; + + recvPacket >> bagIndex >> slot >> spell_count >> cast_count >> item_guid; + + Item *pItem = pUser->GetItemByPos(bagIndex, slot); + if(!pItem) + { + pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); + return; + } + + sLog.outDetail("WORLD: CMSG_USE_ITEM packet, bagIndex: %u, slot: %u, spell_count: %u , cast_count: %u, Item: %u, data length = %i", bagIndex, slot, spell_count, cast_count, pItem->GetEntry(), recvPacket.size()); + + ItemPrototype const *proto = pItem->GetProto(); + if(!proto) + { + pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, NULL ); + return; + } + + // some item classes can be used only in equipped state + if(proto->InventoryType != INVTYPE_NON_EQUIP && !pItem->IsEquipped()) + { + pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, NULL ); + return; + } + + uint8 msg = pUser->CanUseItem(pItem); + if( msg != EQUIP_ERR_OK ) + { + pUser->SendEquipError( msg, pItem, NULL ); + return; + } + + // only allow conjured consumable, bandage, poisons (all should have the 2^21 item flag set in DB) + if( proto->Class == ITEM_CLASS_CONSUMABLE && + !(proto->Flags & ITEM_FLAGS_USEABLE_IN_ARENA) && + pUser->InArena()) + { + pUser->SendEquipError(EQUIP_ERR_NOT_DURING_ARENA_MATCH,pItem,NULL); + return; + } + + if (pUser->isInCombat()) + { + for(int i = 0; i < 5; ++i) + { + if (SpellEntry const *spellInfo = sSpellStore.LookupEntry(proto->Spells[i].SpellId)) + { + if (IsNonCombatSpell(spellInfo)) + { + pUser->SendEquipError(EQUIP_ERR_NOT_IN_COMBAT,pItem,NULL); + return; + } + } + } + } + + // check also BIND_WHEN_PICKED_UP and BIND_QUEST_ITEM for .additem or .additemset case by GM (not binded at adding to inventory) + if( pItem->GetProto()->Bonding == BIND_WHEN_USE || pItem->GetProto()->Bonding == BIND_WHEN_PICKED_UP || pItem->GetProto()->Bonding == BIND_QUEST_ITEM ) + { + if (!pItem->IsSoulBound()) + { + pItem->SetState(ITEM_CHANGED, pUser); + pItem->SetBinding( true ); + } + } + + SpellCastTargets targets; + if(!targets.read(&recvPacket, pUser)) + return; + + //Note: If script stop casting it must send appropriate data to client to prevent stuck item in gray state. + if(!Script->ItemUse(pUser,pItem,targets)) + { + // no script or script not process request by self + + // special learning case + if(pItem->GetProto()->Spells[0].SpellId==SPELL_ID_GENERIC_LEARN) + { + uint32 learning_spell_id = pItem->GetProto()->Spells[1].SpellId; + + SpellEntry const *spellInfo = sSpellStore.LookupEntry(SPELL_ID_GENERIC_LEARN); + if(!spellInfo) + { + sLog.outError("Item (Entry: %u) in have wrong spell id %u, ignoring ",proto->ItemId, SPELL_ID_GENERIC_LEARN); + pUser->SendEquipError(EQUIP_ERR_NONE,pItem,NULL); + return; + } + + Spell *spell = new Spell(pUser, spellInfo, false); + spell->m_CastItem = pItem; + spell->m_cast_count = cast_count; //set count of casts + spell->m_currentBasePoints[0] = learning_spell_id; + spell->prepare(&targets); + return; + } + + // use triggered flag only for items with many spell casts and for not first cast + int count = 0; + + for(int i = 0; i < 5; ++i) + { + _Spell const& spellData = pItem->GetProto()->Spells[i]; + + // no spell + if(!spellData.SpellId) + continue; + + // wrong triggering type + if( spellData.SpellTrigger != ITEM_SPELLTRIGGER_ON_USE && spellData.SpellTrigger != ITEM_SPELLTRIGGER_ON_NO_DELAY_USE) + continue; + + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellData.SpellId); + if(!spellInfo) + { + sLog.outError("Item (Entry: %u) in have wrong spell id %u, ignoring ",proto->ItemId, spellData.SpellId); + continue; + } + + Spell *spell = new Spell(pUser, spellInfo, (count > 0)); + spell->m_CastItem = pItem; + spell->m_cast_count = cast_count; //set count of casts + spell->prepare(&targets); + + ++count; + } + } +} + +#define OPEN_CHEST 11437 +#define OPEN_SAFE 11535 +#define OPEN_CAGE 11792 +#define OPEN_BOOTY_CHEST 5107 +#define OPEN_STRONGBOX 8517 + +void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket) +{ + CHECK_PACKET_SIZE(recvPacket,1+1); + + sLog.outDetail("WORLD: CMSG_OPEN_ITEM packet, data length = %i",recvPacket.size()); + + Player* pUser = _player; + uint8 bagIndex, slot; + + recvPacket >> bagIndex >> slot; + + sLog.outDetail("bagIndex: %u, slot: %u",bagIndex,slot); + + Item *pItem = pUser->GetItemByPos(bagIndex, slot); + if(!pItem) + { + pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); + return; + } + + ItemPrototype const *proto = pItem->GetProto(); + if(!proto) + { + pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, NULL ); + return; + } + + // locked item + uint32 lockId = proto->LockID; + if(lockId) + { + LockEntry const *lockInfo = sLockStore.LookupEntry(lockId); + + if (!lockInfo) + { + pUser->SendEquipError(EQUIP_ERR_ITEM_LOCKED, pItem, NULL ); + sLog.outError( "WORLD::OpenItem: item [guid = %u] has an unknown lockId: %u!", pItem->GetGUIDLow() , lockId); + return; + } + + // required picklocking + if(lockInfo->requiredlockskill || lockInfo->requiredminingskill) + { + pUser->SendEquipError(EQUIP_ERR_ITEM_LOCKED, pItem, NULL ); + return; + } + } + + if(pItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED))// wrapped? + { + QueryResult *result = CharacterDatabase.PQuery("SELECT entry, flags FROM character_gifts WHERE item_guid = '%u'", pItem->GetGUIDLow()); + if (result) + { + Field *fields = result->Fetch(); + uint32 entry = fields[0].GetUInt32(); + uint32 flags = fields[1].GetUInt32(); + + pItem->SetUInt64Value(ITEM_FIELD_GIFTCREATOR, 0); + pItem->SetUInt32Value(OBJECT_FIELD_ENTRY, entry); + pItem->SetUInt32Value(ITEM_FIELD_FLAGS, flags); + pItem->SetState(ITEM_CHANGED, pUser); + delete result; + } + else + { + sLog.outError("Wrapped item %u don't have record in character_gifts table and will deleted", pItem->GetGUIDLow()); + pUser->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true); + return; + } + CharacterDatabase.PExecute("DELETE FROM character_gifts WHERE item_guid = '%u'", pItem->GetGUIDLow()); + } + else + pUser->SendLoot(pItem->GetGUID(),LOOT_CORPSE); +} + +void WorldSession::HandleGameObjectUseOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8); + + uint64 guid; + uint32 spellId = OPEN_CHEST; + + recv_data >> guid; + + sLog.outDebug( "WORLD: Recvd CMSG_GAMEOBJ_USE Message [guid=%u]", guid); + GameObject *obj = ObjectAccessor::GetGameObject(*_player, guid); + + if(!obj) + return; + + if (Script->GOHello(_player, obj)) + return; + + obj->Use(_player); +} + +void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) +{ + CHECK_PACKET_SIZE(recvPacket,4+1+2); + + uint32 spellId; + uint8 cast_count; + recvPacket >> spellId; + recvPacket >> cast_count; + + sLog.outDebug("WORLD: got cast spell packet, spellId - %u, cast_count: %u data length = %i", + spellId, cast_count, recvPacket.size()); + + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId ); + + if(!spellInfo) + { + sLog.outError("WORLD: unknown spell id %u", spellId); + return; + } + + // not have spell or spell passive and not casted by client + if ( !_player->HasSpell (spellId) || IsPassiveSpell(spellId) ) + { + //cheater? kick? ban? + return; + } + + // client provided targets + SpellCastTargets targets; + if(!targets.read(&recvPacket,_player)) + return; + + // auto-selection buff level base at target level (in spellInfo) + if(targets.getUnitTarget()) + { + SpellEntry const *actualSpellInfo = spellmgr.SelectAuraRankForPlayerLevel(spellInfo,targets.getUnitTarget()->getLevel()); + + // if rank not found then function return NULL but in explicit cast case original spell can be casted and later failed with appropriate error message + if(actualSpellInfo) + spellInfo = actualSpellInfo; + } + + Spell *spell = new Spell(_player, spellInfo, false); + spell->m_cast_count = cast_count; //set count of casts + spell->prepare(&targets); +} + +void WorldSession::HandleCancelCastOpcode(WorldPacket& recvPacket) +{ + CHECK_PACKET_SIZE(recvPacket,4); + + uint32 spellId; + recvPacket >> spellId; + + //FIXME: hack, ignore unexpected client cancel Deadly Throw cast + if(spellId==26679) + return; + + if(_player->IsNonMeleeSpellCasted(false)) + _player->InterruptNonMeleeSpells(false,spellId); +} + +void WorldSession::HandleCancelAuraOpcode( WorldPacket& recvPacket) +{ + CHECK_PACKET_SIZE(recvPacket,4); + + uint32 spellId; + recvPacket >> spellId; + + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); + if (!spellInfo) + return; + + // not allow remove non positive spells and spells with attr SPELL_ATTR_CANT_CANCEL + if(!IsPositiveSpell(spellId) || (spellInfo->Attributes & SPELL_ATTR_CANT_CANCEL)) + return; + + _player->RemoveAurasDueToSpellByCancel(spellId); + + if (spellId == 2584) // Waiting to resurrect spell cancel, we must remove player from resurrect queue + { + BattleGround *bg = _player->GetBattleGround(); + if(!bg) + return; + bg->RemovePlayerFromResurrectQueue(_player->GetGUID()); + } +} + +void WorldSession::HandlePetCancelAuraOpcode( WorldPacket& recvPacket) +{ + CHECK_PACKET_SIZE(recvPacket, 8+4); + + uint64 guid; + uint32 spellId; + + recvPacket >> guid; + recvPacket >> spellId; + + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId ); + if(!spellInfo) + { + sLog.outError("WORLD: unknown PET spell id %u", spellId); + return; + } + + Creature* pet=ObjectAccessor::GetCreatureOrPet(*_player,guid); + + if(!pet) + { + sLog.outError( "Pet %u not exist.", uint32(GUID_LOPART(guid)) ); + return; + } + + if(pet != GetPlayer()->GetPet() && pet != GetPlayer()->GetCharm()) + { + sLog.outError( "HandlePetCancelAura.Pet %u isn't pet of player %s", uint32(GUID_LOPART(guid)),GetPlayer()->GetName() ); + return; + } + + if(!pet->isAlive()) + { + pet->SendPetActionFeedback(FEEDBACK_PET_DEAD); + return; + } + + pet->RemoveAurasDueToSpell(spellId); + + pet->AddCreatureSpellCooldown(spellId); +} + +void WorldSession::HandleCancelGrowthAuraOpcode( WorldPacket& /*recvPacket*/) +{ + // nothing do +} + +void WorldSession::HandleCancelAutoRepeatSpellOpcode( WorldPacket& /*recvPacket*/) +{ + // may be better send SMSG_CANCEL_AUTO_REPEAT? + // cancel and prepare for deleting + _player->InterruptSpell(CURRENT_AUTOREPEAT_SPELL); +} + +/// \todo Complete HandleCancelChanneling function +void WorldSession::HandleCancelChanneling( WorldPacket & /*recv_data */) +{ + /* + CHECK_PACKET_SIZE(recv_data, 4); + + uint32 spellid; + recv_data >> spellid; + */ +} + +void WorldSession::HandleTotemDestroy( WorldPacket& recvPacket) +{ + CHECK_PACKET_SIZE(recvPacket, 1); + + uint8 slotId; + + recvPacket >> slotId; + + if (slotId >= MAX_TOTEM) + return; + + if(!_player->m_TotemSlot[slotId]) + return; + + Creature* totem = ObjectAccessor::GetCreature(*_player,_player->m_TotemSlot[slotId]); + if(totem && totem->isTotem()) + ((Totem*)totem)->UnSummon(); +} + +void WorldSession::HandleSelfResOpcode( WorldPacket & /*recv_data*/ ) +{ + sLog.outDebug("WORLD: CMSG_SELF_RES"); // empty opcode + + if(_player->GetUInt32Value(PLAYER_SELF_RES_SPELL)) + { + SpellEntry const *spellInfo = sSpellStore.LookupEntry(_player->GetUInt32Value(PLAYER_SELF_RES_SPELL)); + if(spellInfo) + _player->CastSpell(_player,spellInfo,false,0); + + _player->SetUInt32Value(PLAYER_SELF_RES_SPELL, 0); + } +} diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp new file mode 100644 index 00000000000..fc8c5d43b7b --- /dev/null +++ b/src/game/SpellMgr.cpp @@ -0,0 +1,2268 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "SpellMgr.h" +#include "ObjectMgr.h" +#include "SpellAuraDefines.h" +#include "ProgressBar.h" +#include "Database/DBCStores.h" +#include "World.h" +#include "Chat.h" +#include "Spell.h" + +SpellMgr::SpellMgr() +{ +} + +SpellMgr::~SpellMgr() +{ +} + +SpellMgr& SpellMgr::Instance() +{ + static SpellMgr spellMgr; + return spellMgr; +} + +int32 GetSpellDuration(SpellEntry const *spellInfo) +{ + if(!spellInfo) + return 0; + SpellDurationEntry const *du = sSpellDurationStore.LookupEntry(spellInfo->DurationIndex); + if(!du) + return 0; + return (du->Duration[0] == -1) ? -1 : abs(du->Duration[0]); +} + +int32 GetSpellMaxDuration(SpellEntry const *spellInfo) +{ + if(!spellInfo) + return 0; + SpellDurationEntry const *du = sSpellDurationStore.LookupEntry(spellInfo->DurationIndex); + if(!du) + return 0; + return (du->Duration[2] == -1) ? -1 : abs(du->Duration[2]); +} + +uint32 GetSpellCastTime(SpellEntry const* spellInfo, Spell const* spell) +{ + SpellCastTimesEntry const *spellCastTimeEntry = sSpellCastTimesStore.LookupEntry(spellInfo->CastingTimeIndex); + + // not all spells have cast time index and this is all is pasiive abilities + if(!spellCastTimeEntry) + return 0; + + int32 castTime = spellCastTimeEntry->CastTime; + + if (spell) + { + if(Player* modOwner = spell->GetCaster()->GetSpellModOwner()) + modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CASTING_TIME, castTime, spell); + + if( !(spellInfo->Attributes & (SPELL_ATTR_UNK4|SPELL_ATTR_UNK5)) ) + castTime = int32(castTime * spell->GetCaster()->GetFloatValue(UNIT_MOD_CAST_SPEED)); + else + { + if (spell->IsRangedSpell() && !spell->IsAutoRepeat()) + castTime = int32(castTime * spell->GetCaster()->m_modAttackSpeedPct[RANGED_ATTACK]); + } + } + + if (spellInfo->Attributes & SPELL_ATTR_RANGED && (!spell || !(spell->IsAutoRepeat()))) + castTime += 500; + + return (castTime > 0) ? uint32(castTime) : 0; +} + +bool IsPassiveSpell(uint32 spellId) +{ + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); + if (!spellInfo) + return false; + return (spellInfo->Attributes & SPELL_ATTR_PASSIVE) != 0; +} + +bool IsNoStackAuraDueToAura(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_2, uint32 effIndex_2) +{ + SpellEntry const *spellInfo_1 = sSpellStore.LookupEntry(spellId_1); + SpellEntry const *spellInfo_2 = sSpellStore.LookupEntry(spellId_2); + if(!spellInfo_1 || !spellInfo_2) return false; + if(spellInfo_1->Id == spellId_2) return false; + + if (spellInfo_1->Effect[effIndex_1] != spellInfo_2->Effect[effIndex_2] || + spellInfo_1->EffectItemType[effIndex_1] != spellInfo_2->EffectItemType[effIndex_2] || + spellInfo_1->EffectMiscValue[effIndex_1] != spellInfo_2->EffectMiscValue[effIndex_2] || + spellInfo_1->EffectApplyAuraName[effIndex_1] != spellInfo_2->EffectApplyAuraName[effIndex_2]) + return false; + + return true; +} + +int32 CompareAuraRanks(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_2, uint32 effIndex_2) +{ + SpellEntry const*spellInfo_1 = sSpellStore.LookupEntry(spellId_1); + SpellEntry const*spellInfo_2 = sSpellStore.LookupEntry(spellId_2); + if(!spellInfo_1 || !spellInfo_2) return 0; + if (spellId_1 == spellId_2) return 0; + + int32 diff = spellInfo_1->EffectBasePoints[effIndex_1] - spellInfo_2->EffectBasePoints[effIndex_2]; + if (spellInfo_1->EffectBasePoints[effIndex_1]+1 < 0 && spellInfo_2->EffectBasePoints[effIndex_2]+1 < 0) return -diff; + else return diff; +} + +SpellSpecific GetSpellSpecific(uint32 spellId) +{ + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); + if(!spellInfo) + return SPELL_NORMAL; + + switch(spellInfo->SpellFamilyName) + { + case SPELLFAMILY_MAGE: + { + // family flags 18(Molten), 25(Frost/Ice), 28(Mage) + if (spellInfo->SpellFamilyFlags & 0x12040000) + return SPELL_MAGE_ARMOR; + + if ((spellInfo->SpellFamilyFlags & 0x1000000) && spellInfo->EffectApplyAuraName[0]==SPELL_AURA_MOD_CONFUSE) + return SPELL_MAGE_POLYMORPH; + + break; + } + case SPELLFAMILY_WARRIOR: + { + if (spellInfo->SpellFamilyFlags & 0x00008000010000LL) + return SPELL_POSITIVE_SHOUT; + + break; + } + case SPELLFAMILY_WARLOCK: + { + // only warlock curses have this + if (spellInfo->Dispel == DISPEL_CURSE) + return SPELL_CURSE; + + // family flag 37 (only part spells have family name) + if (spellInfo->SpellFamilyFlags & 0x2000000000LL) + return SPELL_WARLOCK_ARMOR; + + break; + } + case SPELLFAMILY_HUNTER: + { + // only hunter stings have this + if (spellInfo->Dispel == DISPEL_POISON) + return SPELL_STING; + + break; + } + case SPELLFAMILY_PALADIN: + { + if (IsSealSpell(spellInfo)) + return SPELL_SEAL; + + if (spellInfo->SpellFamilyFlags & 0x10000100LL) + return SPELL_BLESSING; + + if ((spellInfo->SpellFamilyFlags & 0x00000820180400LL) && (spellInfo->AttributesEx3 & 0x200)) + return SPELL_JUDGEMENT; + + for (int i = 0; i < 3; i++) + { + // only paladin auras have this + if (spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_PARTY) + return SPELL_AURA; + } + break; + } + case SPELLFAMILY_SHAMAN: + { + if (IsElementalShield(spellInfo)) + return SPELL_ELEMENTAL_SHIELD; + + break; + } + + case SPELLFAMILY_POTION: + return spellmgr.GetSpellElixirSpecific(spellInfo->Id); + } + + // only warlock armor/skin have this (in additional to family cases) + if( spellInfo->SpellVisual == 130 && spellInfo->SpellIconID == 89) + { + return SPELL_WARLOCK_ARMOR; + } + + // only hunter aspects have this (but not all aspects in hunter family) + if( spellInfo->activeIconID == 122 && (GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_NATURE) && + (spellInfo->Attributes & 0x50000) != 0 && (spellInfo->Attributes & 0x9000010) == 0) + { + return SPELL_ASPECT; + } + + for(int i = 0; i < 3; i++) + if( spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA && ( + spellInfo->EffectApplyAuraName[i] == SPELL_AURA_TRACK_CREATURES || + spellInfo->EffectApplyAuraName[i] == SPELL_AURA_TRACK_RESOURCES || + spellInfo->EffectApplyAuraName[i] == SPELL_AURA_TRACK_STEALTHED ) ) + return SPELL_TRACKER; + + // elixirs can have different families, but potion most ofc. + if(SpellSpecific sp = spellmgr.GetSpellElixirSpecific(spellInfo->Id)) + return sp; + + return SPELL_NORMAL; +} + +bool IsSingleFromSpellSpecificPerCaster(uint32 spellSpec1,uint32 spellSpec2) +{ + switch(spellSpec1) + { + case SPELL_SEAL: + case SPELL_BLESSING: + case SPELL_AURA: + case SPELL_STING: + case SPELL_CURSE: + case SPELL_ASPECT: + case SPELL_TRACKER: + case SPELL_WARLOCK_ARMOR: + case SPELL_MAGE_ARMOR: + case SPELL_MAGE_POLYMORPH: + case SPELL_POSITIVE_SHOUT: + case SPELL_JUDGEMENT: + return spellSpec1==spellSpec2; + case SPELL_BATTLE_ELIXIR: + return spellSpec2==SPELL_BATTLE_ELIXIR + || spellSpec2==SPELL_FLASK_ELIXIR; + case SPELL_GUARDIAN_ELIXIR: + return spellSpec2==SPELL_GUARDIAN_ELIXIR + || spellSpec2==SPELL_FLASK_ELIXIR; + case SPELL_FLASK_ELIXIR: + return spellSpec2==SPELL_BATTLE_ELIXIR + || spellSpec2==SPELL_GUARDIAN_ELIXIR + || spellSpec2==SPELL_FLASK_ELIXIR; + default: + return false; + } +} + +bool IsPositiveTarget(uint32 targetA, uint32 targetB) +{ + // non-positive targets + switch(targetA) + { + case TARGET_CHAIN_DAMAGE: + case TARGET_ALL_ENEMY_IN_AREA: + case TARGET_ALL_ENEMY_IN_AREA_INSTANT: + case TARGET_IN_FRONT_OF_CASTER: + case TARGET_ALL_ENEMY_IN_AREA_CHANNELED: + case TARGET_CURRENT_ENEMY_COORDINATES: + case TARGET_SINGLE_ENEMY: + return false; + case TARGET_ALL_AROUND_CASTER: + return (targetB == TARGET_ALL_PARTY || targetB == TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER); + default: + break; + } + if (targetB) + return IsPositiveTarget(targetB, 0); + return true; +} + +bool IsPositiveEffect(uint32 spellId, uint32 effIndex) +{ + SpellEntry const *spellproto = sSpellStore.LookupEntry(spellId); + if (!spellproto) return false; + + switch(spellId) + { + case 23333: // BG spell + case 23335: // BG spell + case 34976: // BG spell + return true; + case 28441: // not positive dummy spell + case 37675: // Chaos Blast + return false; + } + + switch(spellproto->Effect[effIndex]) + { + // always positive effects (check before target checks that provided non-positive result in some case for positive effects) + case SPELL_EFFECT_HEAL: + case SPELL_EFFECT_LEARN_SPELL: + case SPELL_EFFECT_SKILL_STEP: + case SPELL_EFFECT_HEAL_PCT: + case SPELL_EFFECT_ENERGIZE_PCT: + return true; + + // non-positive aura use + case SPELL_EFFECT_APPLY_AURA: + case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND: + { + switch(spellproto->EffectApplyAuraName[effIndex]) + { + case SPELL_AURA_DUMMY: + { + // dummy aura can be positive or negative dependent from casted spell + switch(spellproto->Id) + { + case 13139: // net-o-matic special effect + case 23445: // evil twin + return false; + default: + break; + } + } break; + case SPELL_AURA_MOD_STAT: + case SPELL_AURA_MOD_DAMAGE_DONE: // dependent from bas point sign (negative -> negative) + case SPELL_AURA_MOD_HEALING_DONE: + { + if(spellproto->EffectBasePoints[effIndex]+int32(spellproto->EffectBaseDice[effIndex]) < 0) + return false; + break; + } + case SPELL_AURA_ADD_TARGET_TRIGGER: + return true; + case SPELL_AURA_PERIODIC_TRIGGER_SPELL: + if(spellId != spellproto->EffectTriggerSpell[effIndex]) + { + uint32 spellTriggeredId = spellproto->EffectTriggerSpell[effIndex]; + SpellEntry const *spellTriggeredProto = sSpellStore.LookupEntry(spellTriggeredId); + + if(spellTriggeredProto) + { + // non-positive targets of main spell return early + for(int i = 0; i < 3; ++i) + { + // if non-positive trigger cast targeted to positive target this main cast is non-positive + // this will place this spell auras as debuffs + if(IsPositiveTarget(spellTriggeredProto->EffectImplicitTargetA[effIndex],spellTriggeredProto->EffectImplicitTargetB[effIndex]) && !IsPositiveEffect(spellTriggeredId,i)) + return false; + } + } + } + break; + case SPELL_AURA_PROC_TRIGGER_SPELL: + // many positive auras have negative triggered spells at damage for example and this not make it negative (it can be canceled for example) + break; + case SPELL_AURA_MOD_STUN: //have positive and negative spells, we can't sort its correctly at this moment. + if(effIndex==0 && spellproto->Effect[1]==0 && spellproto->Effect[2]==0) + return false; // but all single stun aura spells is negative + + // Petrification + if(spellproto->Id == 17624) + return false; + break; + case SPELL_AURA_MOD_ROOT: + case SPELL_AURA_MOD_SILENCE: + case SPELL_AURA_GHOST: + case SPELL_AURA_PERIODIC_LEECH: + case SPELL_AURA_MOD_PACIFY_SILENCE: + case SPELL_AURA_MOD_STALKED: + case SPELL_AURA_PERIODIC_DAMAGE_PERCENT: + return false; + case SPELL_AURA_PERIODIC_DAMAGE: // used in positive spells also. + // part of negative spell if casted at self (prevent cancel) + if(spellproto->EffectImplicitTargetA[effIndex] == TARGET_SELF) + return false; + break; + case SPELL_AURA_MOD_DECREASE_SPEED: // used in positive spells also + // part of positive spell if casted at self + if(spellproto->EffectImplicitTargetA[effIndex] != TARGET_SELF) + return false; + // but not this if this first effect (don't found batter check) + if(spellproto->Attributes & 0x4000000 && effIndex==0) + return false; + break; + case SPELL_AURA_TRANSFORM: + // some spells negative + switch(spellproto->Id) + { + case 36897: // Transporter Malfunction (race mutation to horde) + case 36899: // Transporter Malfunction (race mutation to alliance) + return false; + } + break; + case SPELL_AURA_MOD_SCALE: + // some spells negative + switch(spellproto->Id) + { + case 36900: // Soul Split: Evil! + case 36901: // Soul Split: Good + case 36893: // Transporter Malfunction (decrease size case) + case 36895: // Transporter Malfunction (increase size case) + return false; + } + break; + case SPELL_AURA_MECHANIC_IMMUNITY: + { + // non-positive immunities + switch(spellproto->EffectMiscValue[effIndex]) + { + case MECHANIC_BANDAGE: + case MECHANIC_SHIELD: + case MECHANIC_MOUNT: + case MECHANIC_INVULNERABILITY: + return false; + default: + break; + } + } break; + case SPELL_AURA_ADD_FLAT_MODIFIER: // mods + case SPELL_AURA_ADD_PCT_MODIFIER: + { + // non-positive mods + switch(spellproto->EffectMiscValue[effIndex]) + { + case SPELLMOD_COST: // dependent from bas point sign (negative -> positive) + if(spellproto->EffectBasePoints[effIndex]+int32(spellproto->EffectBaseDice[effIndex]) > 0) + return false; + break; + default: + break; + } + } break; + case SPELL_AURA_MOD_HEALING_PCT: + if(spellproto->EffectBasePoints[effIndex]+int32(spellproto->EffectBaseDice[effIndex]) < 0) + return false; + break; + case SPELL_AURA_MOD_SKILL: + if(spellproto->EffectBasePoints[effIndex]+int32(spellproto->EffectBaseDice[effIndex]) < 0) + return false; + break; + case SPELL_AURA_FORCE_REACTION: + if(spellproto->Id==42792) // Recently Dropped Flag (prevent cancel) + return false; + break; + default: + break; + } + break; + } + default: + break; + } + + // non-positive targets + if(!IsPositiveTarget(spellproto->EffectImplicitTargetA[effIndex],spellproto->EffectImplicitTargetB[effIndex])) + return false; + + // AttributesEx check + if(spellproto->AttributesEx & (1<<7)) + return false; + + // ok, positive + return true; +} + +bool IsPositiveSpell(uint32 spellId) +{ + SpellEntry const *spellproto = sSpellStore.LookupEntry(spellId); + if (!spellproto) return false; + + // spells with atleast one negative effect are considered negative + // some self-applied spells have negative effects but in self casting case negative check ignored. + for (int i = 0; i < 3; i++) + if (!IsPositiveEffect(spellId, i)) + return false; + return true; +} + +bool IsSingleTargetSpell(SpellEntry const *spellInfo) +{ + // all other single target spells have if it has AttributesEx5 + if ( spellInfo->AttributesEx5 & SPELL_ATTR_EX5_SINGLE_TARGET_SPELL ) + return true; + + // TODO - need found Judgements rule + switch(GetSpellSpecific(spellInfo->Id)) + { + case SPELL_JUDGEMENT: + return true; + } + + // single target triggered spell. + // Not real client side single target spell, but it' not triggered until prev. aura expired. + // This is allow store it in single target spells list for caster for spell proc checking + if(spellInfo->Id==38324) // Regeneration (triggered by 38299 (HoTs on Heals)) + return true; + + return false; +} + +bool IsSingleTargetSpells(SpellEntry const *spellInfo1, SpellEntry const *spellInfo2) +{ + // TODO - need better check + // Equal icon and spellfamily + if( spellInfo1->SpellFamilyName == spellInfo2->SpellFamilyName && + spellInfo1->SpellIconID == spellInfo2->SpellIconID ) + return true; + + // TODO - need found Judgements rule + SpellSpecific spec1 = GetSpellSpecific(spellInfo1->Id); + // spell with single target specific types + switch(spec1) + { + case SPELL_JUDGEMENT: + if(GetSpellSpecific(spellInfo2->Id) == spec1) + return true; + break; + } + + return false; +} + +uint8 GetErrorAtShapeshiftedCast (SpellEntry const *spellInfo, uint32 form) +{ + // talents that learn spells can have stance requirements that need ignore + // (this requirement only for client-side stance show in talent description) + if( GetTalentSpellCost(spellInfo->Id) > 0 && + (spellInfo->Effect[0]==SPELL_EFFECT_LEARN_SPELL || spellInfo->Effect[1]==SPELL_EFFECT_LEARN_SPELL || spellInfo->Effect[2]==SPELL_EFFECT_LEARN_SPELL) ) + return 0; + + uint32 stanceMask = (form ? 1 << (form - 1) : 0); + + if (stanceMask & spellInfo->StancesNot) // can explicitly not be casted in this stance + return SPELL_FAILED_NOT_SHAPESHIFT; + + if (stanceMask & spellInfo->Stances) // can explicitly be casted in this stance + return 0; + + bool actAsShifted = false; + if (form > 0) + { + SpellShapeshiftEntry const *shapeInfo = sSpellShapeshiftStore.LookupEntry(form); + if (!shapeInfo) + { + sLog.outError("GetErrorAtShapeshiftedCast: unknown shapeshift %u", form); + return 0; + } + actAsShifted = !(shapeInfo->flags1 & 1); // shapeshift acts as normal form for spells + } + + if(actAsShifted) + { + if (spellInfo->Attributes & SPELL_ATTR_NOT_SHAPESHIFT) // not while shapeshifted + return SPELL_FAILED_NOT_SHAPESHIFT; + else if (spellInfo->Stances != 0) // needs other shapeshift + return SPELL_FAILED_ONLY_SHAPESHIFT; + } + else + { + // needs shapeshift + if(!(spellInfo->AttributesEx2 & SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT) && spellInfo->Stances != 0) + return SPELL_FAILED_ONLY_SHAPESHIFT; + } + + return 0; +} + +void SpellMgr::LoadSpellTargetPositions() +{ + mSpellTargetPositions.clear(); // need for reload case + + uint32 count = 0; + + // 0 1 2 3 4 5 + QueryResult *result = WorldDatabase.Query("SELECT id, target_map, target_position_x, target_position_y, target_position_z, target_orientation FROM spell_target_position"); + if( !result ) + { + + barGoLink bar( 1 ); + + bar.step(); + + sLog.outString(); + sLog.outString( ">> Loaded %u spell target coordinates", count ); + return; + } + + barGoLink bar( result->GetRowCount() ); + + do + { + Field *fields = result->Fetch(); + + bar.step(); + + ++count; + + uint32 Spell_ID = fields[0].GetUInt32(); + + SpellTargetPosition st; + + st.target_mapId = fields[1].GetUInt32(); + st.target_X = fields[2].GetFloat(); + st.target_Y = fields[3].GetFloat(); + st.target_Z = fields[4].GetFloat(); + st.target_Orientation = fields[5].GetFloat(); + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(Spell_ID); + if(!spellInfo) + { + sLog.outErrorDb("Spell (ID:%u) listed in `spell_target_position` does not exist.",Spell_ID); + continue; + } + + bool found = false; + for(int i = 0; i < 3; ++i) + { + if( spellInfo->EffectImplicitTargetA[i]==TARGET_TABLE_X_Y_Z_COORDINATES || spellInfo->EffectImplicitTargetB[i]==TARGET_TABLE_X_Y_Z_COORDINATES ) + { + found = true; + break; + } + } + if(!found) + { + sLog.outErrorDb("Spell (Id: %u) listed in `spell_target_position` does not have target TARGET_TABLE_X_Y_Z_COORDINATES (17).",Spell_ID); + continue; + } + + MapEntry const* mapEntry = sMapStore.LookupEntry(st.target_mapId); + if(!mapEntry) + { + sLog.outErrorDb("Spell (ID:%u) target map (ID: %u) does not exist in `Map.dbc`.",Spell_ID,st.target_mapId); + continue; + } + + if(st.target_X==0 && st.target_Y==0 && st.target_Z==0) + { + sLog.outErrorDb("Spell (ID:%u) target coordinates not provided.",Spell_ID); + continue; + } + + mSpellTargetPositions[Spell_ID] = st; + + } while( result->NextRow() ); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u spell teleport coordinates", count ); +} + +void SpellMgr::LoadSpellAffects() +{ + mSpellAffectMap.clear(); // need for reload case + + uint32 count = 0; + + // 0 1 2 + QueryResult *result = WorldDatabase.Query("SELECT entry, effectId, SpellFamilyMask FROM spell_affect"); + if( !result ) + { + + barGoLink bar( 1 ); + + bar.step(); + + sLog.outString(); + sLog.outString( ">> Loaded %u spell affect definitions", count ); + return; + } + + barGoLink bar( result->GetRowCount() ); + + do + { + Field *fields = result->Fetch(); + + bar.step(); + + uint16 entry = fields[0].GetUInt16(); + uint8 effectId = fields[1].GetUInt8(); + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(entry); + + if (!spellInfo) + { + sLog.outErrorDb("Spell %u listed in `spell_affect` does not exist", entry); + continue; + } + + if (effectId >= 3) + { + sLog.outErrorDb("Spell %u listed in `spell_affect` have invalid effect index (%u)", entry,effectId); + continue; + } + + if( spellInfo->Effect[effectId] != SPELL_EFFECT_APPLY_AURA || + spellInfo->EffectApplyAuraName[effectId] != SPELL_AURA_ADD_FLAT_MODIFIER && + spellInfo->EffectApplyAuraName[effectId] != SPELL_AURA_ADD_PCT_MODIFIER && + spellInfo->EffectApplyAuraName[effectId] != SPELL_AURA_ADD_TARGET_TRIGGER ) + { + sLog.outErrorDb("Spell %u listed in `spell_affect` have not SPELL_AURA_ADD_FLAT_MODIFIER (%u) or SPELL_AURA_ADD_PCT_MODIFIER (%u) or SPELL_AURA_ADD_TARGET_TRIGGER (%u) for effect index (%u)", entry,SPELL_AURA_ADD_FLAT_MODIFIER,SPELL_AURA_ADD_PCT_MODIFIER,SPELL_AURA_ADD_TARGET_TRIGGER,effectId); + continue; + } + + uint64 spellAffectMask = fields[2].GetUInt64(); + + // Spell.dbc have own data for low part of SpellFamilyMask + if( spellInfo->EffectItemType[effectId]) + { + if(spellInfo->EffectItemType[effectId] == spellAffectMask) + { + sLog.outErrorDb("Spell %u listed in `spell_affect` have redundant (same with EffectItemType%d) data for effect index (%u) and not needed, skipped.", entry,effectId+1,effectId); + continue; + } + + // 24429 have wrong data in EffectItemType and overwrites by DB, possible bug in client + if(spellInfo->Id!=24429 && spellInfo->EffectItemType[effectId] != spellAffectMask) + { + sLog.outErrorDb("Spell %u listed in `spell_affect` have different low part from EffectItemType%d for effect index (%u) and not needed, skipped.", entry,effectId+1,effectId); + continue; + } + } + + mSpellAffectMap.insert(SpellAffectMap::value_type((entry<<8) + effectId,spellAffectMask)); + + ++count; + } while( result->NextRow() ); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u spell affect definitions", count ); + + /* + // Commented for now, as it still produces many errors (still quite many spells miss spell_affect) + for (uint32 id = 0; id < sSpellStore.GetNumRows(); ++id) + { + SpellEntry const* spellInfo = sSpellStore.LookupEntry(id); + if (!spellInfo) + continue; + + for (int effectId = 0; effectId < 3; ++effectId) + { + if( spellInfo->Effect[effectId] != SPELL_EFFECT_APPLY_AURA || + (spellInfo->EffectApplyAuraName[effectId] != SPELL_AURA_ADD_FLAT_MODIFIER && + spellInfo->EffectApplyAuraName[effectId] != SPELL_AURA_ADD_PCT_MODIFIER && + spellInfo->EffectApplyAuraName[effectId] != SPELL_AURA_ADD_TARGET_TRIGGER) ) + continue; + + if(spellInfo->EffectItemType[effectId] != 0) + continue; + + if(mSpellAffectMap.find((id<<8) + effectId) != mSpellAffectMap.end()) + continue; + + sLog.outErrorDb("Spell %u (%s) misses spell_affect for effect %u",id,spellInfo->SpellName[sWorld.GetDBClang()], effectId); + } + } + */ +} + +bool SpellMgr::IsAffectedBySpell(SpellEntry const *spellInfo, uint32 spellId, uint8 effectId, uint64 familyFlags) const +{ + // false for spellInfo == NULL + if (!spellInfo) + return false; + + SpellEntry const *affect_spell = sSpellStore.LookupEntry(spellId); + // false for affect_spell == NULL + if (!affect_spell) + return false; + + // False if spellFamily not equal + if (affect_spell->SpellFamilyName != spellInfo->SpellFamilyName) + return false; + + // If familyFlags == 0 + if (!familyFlags) + { + // Get it from spellAffect table + familyFlags = GetSpellAffectMask(spellId,effectId); + // false if familyFlags == 0 + if (!familyFlags) + return false; + } + + // true + if (familyFlags & spellInfo->SpellFamilyFlags) + return true; + + return false; +} + +void SpellMgr::LoadSpellProcEvents() +{ + mSpellProcEventMap.clear(); // need for reload case + + uint32 count = 0; + + // 0 1 2 3 4 5 6 7 8 + QueryResult *result = WorldDatabase.Query("SELECT entry, SchoolMask, Category, SkillID, SpellFamilyName, SpellFamilyMask, procFlags, ppmRate, cooldown FROM spell_proc_event"); + if( !result ) + { + + barGoLink bar( 1 ); + + bar.step(); + + sLog.outString(); + sLog.outString( ">> Loaded %u spell proc event conditions", count ); + return; + } + + barGoLink bar( result->GetRowCount() ); + + do + { + Field *fields = result->Fetch(); + + bar.step(); + + uint16 entry = fields[0].GetUInt16(); + + if (!sSpellStore.LookupEntry(entry)) + { + sLog.outErrorDb("Spell %u listed in `spell_proc_event` does not exist", entry); + continue; + } + + SpellProcEventEntry spe; + + spe.schoolMask = fields[1].GetUInt32(); + spe.category = fields[2].GetUInt32(); + spe.skillId = fields[3].GetUInt32(); + spe.spellFamilyName = fields[4].GetUInt32(); + spe.spellFamilyMask = fields[5].GetUInt64(); + spe.procFlags = fields[6].GetUInt32(); + spe.ppmRate = fields[7].GetFloat(); + spe.cooldown = fields[8].GetUInt32(); + + mSpellProcEventMap[entry] = spe; + + ++count; + } while( result->NextRow() ); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u spell proc event conditions", count ); + + /* + // Commented for now, as it still produces many errors (still quite many spells miss spell_proc_event) + for (uint32 id = 0; id < sSpellStore.GetNumRows(); ++id) + { + SpellEntry const* spellInfo = sSpellStore.LookupEntry(id); + if (!spellInfo) + continue; + + bool found = false; + for (int effectId = 0; effectId < 3; ++effectId) + { + // at this moment check only SPELL_AURA_PROC_TRIGGER_SPELL + if( spellInfo->EffectApplyAuraName[effectId] == SPELL_AURA_PROC_TRIGGER_SPELL ) + { + found = true; + break; + } + } + + if(!found) + continue; + + if(GetSpellProcEvent(id)) + continue; + + sLog.outErrorDb("Spell %u (%s) misses spell_proc_event",id,spellInfo->SpellName[sWorld.GetDBClang()]); + } + */ +} + +bool SpellMgr::IsSpellProcEventCanTriggeredBy( SpellProcEventEntry const * spellProcEvent, SpellEntry const * procSpell, uint32 procFlags ) +{ + if((procFlags & spellProcEvent->procFlags) == 0) + return false; + + // Additional checks in case spell cast/hit/crit is the event + // Check (if set) school, category, skill line, spell talent mask + if(spellProcEvent->schoolMask && (!procSpell || (GetSpellSchoolMask(procSpell) & spellProcEvent->schoolMask) == 0)) + return false; + if(spellProcEvent->category && (!procSpell || procSpell->Category != spellProcEvent->category)) + return false; + if(spellProcEvent->skillId) + { + if (!procSpell) + return false; + + SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(procSpell->Id); + SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(procSpell->Id); + + bool found = false; + for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx) + { + if(_spell_idx->second->skillId == spellProcEvent->skillId) + { + found = true; + break; + } + } + if (!found) + return false; + } + if(spellProcEvent->spellFamilyName && (!procSpell || spellProcEvent->spellFamilyName != procSpell->SpellFamilyName)) + return false; + if(spellProcEvent->spellFamilyMask && (!procSpell || (spellProcEvent->spellFamilyMask & procSpell->SpellFamilyFlags) == 0)) + return false; + + return true; +} + +void SpellMgr::LoadSpellElixirs() +{ + mSpellElixirs.clear(); // need for reload case + + uint32 count = 0; + + // 0 1 + QueryResult *result = WorldDatabase.Query("SELECT entry, mask FROM spell_elixir"); + if( !result ) + { + + barGoLink bar( 1 ); + + bar.step(); + + sLog.outString(); + sLog.outString( ">> Loaded %u spell elixir definitions", count ); + return; + } + + barGoLink bar( result->GetRowCount() ); + + do + { + Field *fields = result->Fetch(); + + bar.step(); + + uint16 entry = fields[0].GetUInt16(); + uint8 mask = fields[1].GetUInt8(); + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(entry); + + if (!spellInfo) + { + sLog.outErrorDb("Spell %u listed in `spell_elixir` does not exist", entry); + continue; + } + + mSpellElixirs[entry] = mask; + + ++count; + } while( result->NextRow() ); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u spell elixir definitions", count ); +} + +void SpellMgr::LoadSpellThreats() +{ + sSpellThreatStore.Free(); // for reload + + sSpellThreatStore.Load(); + + sLog.outString( ">> Loaded %u aggro generating spells", sSpellThreatStore.RecordCount ); + sLog.outString(); +} + +bool SpellMgr::IsRankSpellDueToSpell(SpellEntry const *spellInfo_1,uint32 spellId_2) const +{ + SpellEntry const *spellInfo_2 = sSpellStore.LookupEntry(spellId_2); + if(!spellInfo_1 || !spellInfo_2) return false; + if(spellInfo_1->Id == spellId_2) return false; + + return GetFirstSpellInChain(spellInfo_1->Id)==GetFirstSpellInChain(spellId_2); +} + +bool SpellMgr::canStackSpellRanks(SpellEntry const *spellInfo) +{ + if(spellInfo->powerType != POWER_MANA && spellInfo->powerType != POWER_HEALTH) + return false; + if(IsProfessionSpell(spellInfo->Id)) + return false; + + // All stance spells. if any better way, change it. + for (int i = 0; i < 3; i++) + { + // Paladin aura Spell + if(spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN + && spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AREA_AURA_PARTY) + return false; + // Druid form Spell + if(spellInfo->SpellFamilyName == SPELLFAMILY_DRUID + && spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AURA + && spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_SHAPESHIFT) + return false; + // Rogue Stealth + if(spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE + && spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AURA + && spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_SHAPESHIFT) + return false; + } + return true; +} + +bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) const +{ + SpellEntry const *spellInfo_1 = sSpellStore.LookupEntry(spellId_1); + SpellEntry const *spellInfo_2 = sSpellStore.LookupEntry(spellId_2); + + if(!spellInfo_1 || !spellInfo_2) + return false; + + if(spellInfo_1->Id == spellId_2) + return false; + + //I think we don't check this correctly because i need a exception for spell: + //72,11327,18461...(called from 1856,1857...) Call Aura 16,31, after trigger another spell who call aura 77 and 77 remove 16 and 31, this should not happen. + if(spellInfo_2->SpellFamilyFlags == 2048) + return false; + + // Resurrection sickness + if((spellInfo_1->Id == SPELL_ID_PASSIVE_RESURRECTION_SICKNESS) != (spellInfo_2->Id==SPELL_ID_PASSIVE_RESURRECTION_SICKNESS)) + return false; + + // Specific spell family spells + switch(spellInfo_1->SpellFamilyName) + { + case SPELLFAMILY_GENERIC: + switch(spellInfo_2->SpellFamilyName) + { + case SPELLFAMILY_GENERIC: // same family case + { + // Thunderfury + if( spellInfo_1->Id == 21992 && spellInfo_2->Id == 27648 || spellInfo_2->Id == 21992 && spellInfo_1->Id == 27648 ) + return false; + + // Lightning Speed (Mongoose) and Fury of the Crashing Waves (Tsunami Talisman) + if( spellInfo_1->Id == 28093 && spellInfo_2->Id == 42084 || + spellInfo_2->Id == 28093 && spellInfo_1->Id == 42084 ) + return false; + + // Soulstone Resurrection and Twisting Nether (resurrector) + if( spellInfo_1->SpellIconID == 92 && spellInfo_2->SpellIconID == 92 && ( + spellInfo_1->SpellVisual == 99 && spellInfo_2->SpellVisual == 0 || + spellInfo_2->SpellVisual == 99 && spellInfo_1->SpellVisual == 0 ) ) + return false; + + // Heart of the Wild and (Primal Instinct (Idol of Terror) triggering spell or Agility) + if( spellInfo_1->SpellIconID == 240 && spellInfo_2->SpellIconID == 240 && ( + spellInfo_1->SpellVisual == 0 && spellInfo_2->SpellVisual == 78 || + spellInfo_2->SpellVisual == 0 && spellInfo_1->SpellVisual == 78 ) ) + return false; + + // Personalized Weather (thunder effect should overwrite rainy aura) + if(spellInfo_1->SpellIconID == 2606 && spellInfo_2->SpellIconID == 2606) + return false; + + // Brood Affliction: Bronze + if( (spellInfo_1->Id == 23170 && spellInfo_2->Id == 23171) || + (spellInfo_2->Id == 23170 && spellInfo_1->Id == 23171) ) + return false; + + break; + } + case SPELLFAMILY_WARRIOR: + { + // Scroll of Protection and Defensive Stance (multi-family check) + if( spellInfo_1->SpellIconID == 276 && spellInfo_1->SpellVisual == 196 && spellInfo_2->Id == 71) + return false; + + // Improved Hamstring -> Hamstring (multi-family check) + if( (spellInfo_2->SpellFamilyFlags & 2) && spellInfo_1->Id == 23694 ) + return false; + + break; + } + case SPELLFAMILY_DRUID: + { + // Scroll of Stamina and Leader of the Pack (multi-family check) + if( spellInfo_1->SpellIconID == 312 && spellInfo_1->SpellVisual == 216 && spellInfo_2->Id == 24932 ) + return false; + + // Dragonmaw Illusion (multi-family check) + if (spellId_1 == 40216 && spellId_2 == 42016 ) + return false; + + break; + } + case SPELLFAMILY_ROGUE: + { + // Garrote-Silence -> Garrote (multi-family check) + if( spellInfo_1->SpellIconID == 498 && spellInfo_1->SpellVisual == 0 && spellInfo_2->SpellIconID == 498 ) + return false; + + break; + } + case SPELLFAMILY_HUNTER: + { + // Concussive Shot and Imp. Concussive Shot (multi-family check) + if( spellInfo_1->Id == 19410 && spellInfo_2->Id == 5116 ) + return false; + + // Improved Wing Clip -> Wing Clip (multi-family check) + if( (spellInfo_2->SpellFamilyFlags & 0x40) && spellInfo_1->Id == 19229 ) + return false; + break; + } + case SPELLFAMILY_PALADIN: + { + // Unstable Currents and other -> *Sanctity Aura (multi-family check) + if( spellInfo_2->SpellIconID==502 && spellInfo_1->SpellIconID==502 && spellInfo_1->SpellVisual==969 ) + return false; + + // *Band of Eternal Champion and Seal of Command(multi-family check) + if( spellId_1 == 35081 && spellInfo_2->SpellIconID==561 && spellInfo_2->SpellVisual==7992) + return false; + + break; + } + } + break; + case SPELLFAMILY_MAGE: + if( spellInfo_2->SpellFamilyName == SPELLFAMILY_MAGE ) + { + // Blizzard & Chilled (and some other stacked with blizzard spells + if( (spellInfo_1->SpellFamilyFlags & 0x80) && (spellInfo_2->SpellFamilyFlags & 0x100000) || + (spellInfo_2->SpellFamilyFlags & 0x80) && (spellInfo_1->SpellFamilyFlags & 0x100000) ) + return false; + + // Blink & Improved Blink + if( (spellInfo_1->SpellFamilyFlags & 0x0000000000010000LL) && (spellInfo_2->SpellVisual == 72 && spellInfo_2->SpellIconID == 1499) || + (spellInfo_2->SpellFamilyFlags & 0x0000000000010000LL) && (spellInfo_1->SpellVisual == 72 && spellInfo_1->SpellIconID == 1499) ) + return false; + } + // Detect Invisibility and Mana Shield (multi-family check) + if( spellInfo_2->Id == 132 && spellInfo_1->SpellIconID == 209 && spellInfo_1->SpellVisual == 968 ) + return false; + + // Combustion and Fire Protection Aura (multi-family check) + if( spellInfo_1->Id == 11129 && spellInfo_2->SpellIconID == 33 && spellInfo_2->SpellVisual == 321 ) + return false; + + break; + case SPELLFAMILY_WARLOCK: + if( spellInfo_2->SpellFamilyName == SPELLFAMILY_WARLOCK ) + { + // Siphon Life and Drain Life + if( spellInfo_1->SpellIconID == 152 && spellInfo_2->SpellIconID == 546 || + spellInfo_2->SpellIconID == 152 && spellInfo_1->SpellIconID == 546 ) + return false; + + //Corruption & Seed of corruption + if( spellInfo_1->SpellIconID == 313 && spellInfo_2->SpellIconID == 1932 || + spellInfo_2->SpellIconID == 313 && spellInfo_1->SpellIconID == 1932 ) + if(spellInfo_1->SpellVisual != 0 && spellInfo_2->SpellVisual != 0) + return true; // can't be stacked + + // Corruption and Unstable Affliction + if( spellInfo_1->SpellIconID == 313 && spellInfo_2->SpellIconID == 2039 || + spellInfo_2->SpellIconID == 313 && spellInfo_1->SpellIconID == 2039 ) + return false; + + // (Corruption or Unstable Affliction) and (Curse of Agony or Curse of Doom) + if( (spellInfo_1->SpellIconID == 313 || spellInfo_1->SpellIconID == 2039) && (spellInfo_2->SpellIconID == 544 || spellInfo_2->SpellIconID == 91) || + (spellInfo_2->SpellIconID == 313 || spellInfo_2->SpellIconID == 2039) && (spellInfo_1->SpellIconID == 544 || spellInfo_1->SpellIconID == 91) ) + return false; + } + // Detect Invisibility and Mana Shield (multi-family check) + if( spellInfo_1->Id == 132 && spellInfo_2->SpellIconID == 209 && spellInfo_2->SpellVisual == 968 ) + return false; + break; + case SPELLFAMILY_WARRIOR: + if( spellInfo_2->SpellFamilyName == SPELLFAMILY_WARRIOR ) + { + // Rend and Deep Wound + if( (spellInfo_1->SpellFamilyFlags & 0x20) && (spellInfo_2->SpellFamilyFlags & 0x1000000000LL) || + (spellInfo_2->SpellFamilyFlags & 0x20) && (spellInfo_1->SpellFamilyFlags & 0x1000000000LL) ) + return false; + + // Battle Shout and Rampage + if( (spellInfo_1->SpellIconID == 456 && spellInfo_2->SpellIconID == 2006) || + (spellInfo_2->SpellIconID == 456 && spellInfo_1->SpellIconID == 2006) ) + return false; + } + + // Hamstring -> Improved Hamstring (multi-family check) + if( (spellInfo_1->SpellFamilyFlags & 2) && spellInfo_2->Id == 23694 ) + return false; + + // Defensive Stance and Scroll of Protection (multi-family check) + if( spellInfo_1->Id == 71 && spellInfo_2->SpellIconID == 276 && spellInfo_2->SpellVisual == 196 ) + return false; + + // Bloodlust and Bloodthirst (multi-family check) + if( spellInfo_2->Id == 2825 && spellInfo_1->SpellIconID == 38 && spellInfo_1->SpellVisual == 0 ) + return false; + + break; + case SPELLFAMILY_PRIEST: + if( spellInfo_2->SpellFamilyName == SPELLFAMILY_PRIEST ) + { + //Devouring Plague and Shadow Vulnerability + if( (spellInfo_1->SpellFamilyFlags & 0x2000000) && (spellInfo_2->SpellFamilyFlags & 0x800000000LL) || + (spellInfo_2->SpellFamilyFlags & 0x2000000) && (spellInfo_1->SpellFamilyFlags & 0x800000000LL) ) + return false; + + //StarShards and Shadow Word: Pain + if( (spellInfo_1->SpellFamilyFlags & 0x200000) && (spellInfo_2->SpellFamilyFlags & 0x8000) || + (spellInfo_2->SpellFamilyFlags & 0x200000) && (spellInfo_1->SpellFamilyFlags & 0x8000) ) + return false; + } + break; + case SPELLFAMILY_DRUID: + if( spellInfo_2->SpellFamilyName == SPELLFAMILY_DRUID ) + { + //Omen of Clarity and Blood Frenzy + if( (spellInfo_1->SpellFamilyFlags == 0x0 && spellInfo_1->SpellIconID == 108) && (spellInfo_2->SpellFamilyFlags & 0x20000000000000LL) || + (spellInfo_2->SpellFamilyFlags == 0x0 && spellInfo_2->SpellIconID == 108) && (spellInfo_1->SpellFamilyFlags & 0x20000000000000LL) ) + return false; + + // Tree of Life (Shapeshift) and 34123 Tree of Life (Passive) + if ((spellId_1 == 33891 && spellId_2 == 34123) || + (spellId_2 == 33891 && spellId_1 == 34123)) + return false; + + // Wrath of Elune and Nature's Grace + if( spellInfo_1->Id == 16886 && spellInfo_2->Id == 46833 || spellInfo_2->Id == 16886 && spellInfo_1->Id == 46833 ) + return false; + + // Bear Rage (Feral T4 (2)) and Omen of Clarity + if( spellInfo_1->Id == 16864 && spellInfo_2->Id == 37306 || spellInfo_2->Id == 16864 && spellInfo_1->Id == 37306 ) + return false; + + // Cat Energy (Feral T4 (2)) and Omen of Clarity + if( spellInfo_1->Id == 16864 && spellInfo_2->Id == 37311 || spellInfo_2->Id == 16864 && spellInfo_1->Id == 37311 ) + return false; + } + + // Leader of the Pack and Scroll of Stamina (multi-family check) + if( spellInfo_1->Id == 24932 && spellInfo_2->SpellIconID == 312 && spellInfo_2->SpellVisual == 216 ) + return false; + + // Dragonmaw Illusion (multi-family check) + if (spellId_1 == 42016 && spellId_2 == 40216 ) + return false; + + break; + case SPELLFAMILY_ROGUE: + if( spellInfo_2->SpellFamilyName == SPELLFAMILY_ROGUE ) + { + // Master of Subtlety + if (spellId_1 == 31665 && spellId_2 == 31666 || spellId_1 == 31666 && spellId_2 == 31665 ) + return false; + } + + // Garrote -> Garrote-Silence (multi-family check) + if( spellInfo_1->SpellIconID == 498 && spellInfo_2->SpellIconID == 498 && spellInfo_2->SpellVisual == 0 ) + return false; + break; + case SPELLFAMILY_HUNTER: + if( spellInfo_2->SpellFamilyName == SPELLFAMILY_HUNTER ) + { + // Rapid Fire & Quick Shots + if( (spellInfo_1->SpellFamilyFlags & 0x20) && (spellInfo_2->SpellFamilyFlags & 0x20000000000LL) || + (spellInfo_2->SpellFamilyFlags & 0x20) && (spellInfo_1->SpellFamilyFlags & 0x20000000000LL) ) + return false; + + // Serpent Sting & (Immolation/Explosive Trap Effect) + if( (spellInfo_1->SpellFamilyFlags & 0x4) && (spellInfo_2->SpellFamilyFlags & 0x00000004000LL) || + (spellInfo_2->SpellFamilyFlags & 0x4) && (spellInfo_1->SpellFamilyFlags & 0x00000004000LL) ) + return false; + + // Bestial Wrath + if( spellInfo_1->SpellIconID == 1680 && spellInfo_2->SpellIconID == 1680 ) + return false; + } + + // Wing Clip -> Improved Wing Clip (multi-family check) + if( (spellInfo_1->SpellFamilyFlags & 0x40) && spellInfo_2->Id == 19229 ) + return false; + + // Concussive Shot and Imp. Concussive Shot (multi-family check) + if( spellInfo_2->Id == 19410 && spellInfo_1->Id == 5116 ) + return false; + break; + case SPELLFAMILY_PALADIN: + if( spellInfo_2->SpellFamilyName == SPELLFAMILY_PALADIN ) + { + // Paladin Seals + if( IsSealSpell(spellInfo_1) && IsSealSpell(spellInfo_2) ) + return true; + } + // Combustion and Fire Protection Aura (multi-family check) + if( spellInfo_2->Id == 11129 && spellInfo_1->SpellIconID == 33 && spellInfo_1->SpellVisual == 321 ) + return false; + + // *Sanctity Aura -> Unstable Currents and other (multi-family check) + if( spellInfo_1->SpellIconID==502 && spellInfo_2->SpellFamilyName == SPELLFAMILY_GENERIC && spellInfo_2->SpellIconID==502 && spellInfo_2->SpellVisual==969 ) + return false; + + // *Seal of Command and Band of Eternal Champion (multi-family check) + if( spellInfo_1->SpellIconID==561 && spellInfo_1->SpellVisual==7992 && spellId_2 == 35081) + return false; + break; + case SPELLFAMILY_SHAMAN: + if( spellInfo_2->SpellFamilyName == SPELLFAMILY_SHAMAN ) + { + // shaman shields + if( IsElementalShield(spellInfo_1) && IsElementalShield(spellInfo_2) ) + return true; + + // Windfury weapon + if( spellInfo_1->SpellIconID==220 && spellInfo_2->SpellIconID==220 && + spellInfo_1->SpellFamilyFlags != spellInfo_2->SpellFamilyFlags ) + return false; + } + // Bloodlust and Bloodthirst (multi-family check) + if( spellInfo_1->Id == 2825 && spellInfo_2->SpellIconID == 38 && spellInfo_2->SpellVisual == 0 ) + return false; + break; + default: + break; + } + + // more generic checks + if (spellInfo_1->SpellIconID == spellInfo_2->SpellIconID && + spellInfo_1->SpellIconID != 0 && spellInfo_2->SpellIconID != 0) + { + bool isModifier = false; + for (int i = 0; i < 3; i++) + { + if (spellInfo_1->EffectApplyAuraName[i] == SPELL_AURA_ADD_FLAT_MODIFIER || + spellInfo_1->EffectApplyAuraName[i] == SPELL_AURA_ADD_PCT_MODIFIER || + spellInfo_2->EffectApplyAuraName[i] == SPELL_AURA_ADD_FLAT_MODIFIER || + spellInfo_2->EffectApplyAuraName[i] == SPELL_AURA_ADD_PCT_MODIFIER ) + isModifier = true; + } + + if (!isModifier) + return true; + } + + if (IsRankSpellDueToSpell(spellInfo_1, spellId_2)) + return true; + + if (spellInfo_1->SpellFamilyName == 0 || spellInfo_2->SpellFamilyName == 0) + return false; + + if (spellInfo_1->SpellFamilyName != spellInfo_2->SpellFamilyName) + return false; + + for (int i = 0; i < 3; ++i) + if (spellInfo_1->Effect[i] != spellInfo_2->Effect[i] || + spellInfo_1->EffectItemType[i] != spellInfo_2->EffectItemType[i] || + spellInfo_1->EffectMiscValue[i] != spellInfo_2->EffectMiscValue[i] || + spellInfo_1->EffectApplyAuraName[i] != spellInfo_2->EffectApplyAuraName[i]) + return false; + + return true; +} + +bool SpellMgr::IsProfessionSpell(uint32 spellId) +{ + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); + if(!spellInfo) + return false; + + if(spellInfo->Effect[1] != SPELL_EFFECT_SKILL) + return false; + + uint32 skill = spellInfo->EffectMiscValue[1]; + + return IsProfessionSkill(skill); +} + +bool SpellMgr::IsPrimaryProfessionSpell(uint32 spellId) +{ + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); + if(!spellInfo) + return false; + + if(spellInfo->Effect[1] != SPELL_EFFECT_SKILL) + return false; + + uint32 skill = spellInfo->EffectMiscValue[1]; + + return IsPrimaryProfessionSkill(skill); +} + +bool SpellMgr::IsPrimaryProfessionFirstRankSpell(uint32 spellId) const +{ + return IsPrimaryProfessionSpell(spellId) && GetSpellRank(spellId)==1; +} + +SpellEntry const* SpellMgr::SelectAuraRankForPlayerLevel(SpellEntry const* spellInfo, uint32 playerLevel) const +{ + // ignore passive spells + if(IsPassiveSpell(spellInfo->Id)) + return spellInfo; + + bool needRankSelection = false; + for(int i=0;i<3;i++) + { + if( IsPositiveEffect(spellInfo->Id, i) && ( + spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA || + spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_PARTY + ) ) + { + needRankSelection = true; + break; + } + } + + // not required + if(!needRankSelection) + return spellInfo; + + for(uint32 nextSpellId = spellInfo->Id; nextSpellId != 0; nextSpellId = GetPrevSpellInChain(nextSpellId)) + { + SpellEntry const *nextSpellInfo = sSpellStore.LookupEntry(nextSpellId); + if(!nextSpellInfo) + break; + + // if found appropriate level + if(playerLevel + 10 >= nextSpellInfo->spellLevel) + return nextSpellInfo; + + // one rank less then + } + + // not found + return NULL; +} + +void SpellMgr::LoadSpellChains() +{ + mSpellChains.clear(); // need for reload case + mSpellChainsNext.clear(); // need for reload case + + QueryResult *result = WorldDatabase.PQuery("SELECT spell_id, prev_spell, first_spell, rank, req_spell FROM spell_chain"); + if(result == NULL) + { + barGoLink bar( 1 ); + bar.step(); + + sLog.outString(); + sLog.outString( ">> Loaded 0 spell chain records" ); + sLog.outErrorDb("`spell_chains` table is empty!"); + return; + } + + uint32 count = 0; + + barGoLink bar( result->GetRowCount() ); + do + { + bar.step(); + Field *fields = result->Fetch(); + + uint32 spell_id = fields[0].GetUInt32(); + + SpellChainNode node; + node.prev = fields[1].GetUInt32(); + node.first = fields[2].GetUInt32(); + node.rank = fields[3].GetUInt8(); + node.req = fields[4].GetUInt32(); + + if(!sSpellStore.LookupEntry(spell_id)) + { + sLog.outErrorDb("Spell %u listed in `spell_chain` does not exist",spell_id); + continue; + } + + if(node.prev!=0 && !sSpellStore.LookupEntry(node.prev)) + { + sLog.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not existed previous rank spell.", + spell_id,node.prev,node.first,node.rank,node.req); + continue; + } + + if(!sSpellStore.LookupEntry(node.first)) + { + sLog.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not existing first rank spell.", + spell_id,node.prev,node.first,node.rank,node.req); + continue; + } + + // check basic spell chain data integrity (note: rank can be equal 0 or 1 for first/single spell) + if( (spell_id == node.first) != (node.rank <= 1) || + (spell_id == node.first) != (node.prev == 0) || + (node.rank <= 1) != (node.prev == 0) ) + { + sLog.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not compatible chain data.", + spell_id,node.prev,node.first,node.rank,node.req); + continue; + } + + if(node.req!=0 && !sSpellStore.LookupEntry(node.req)) + { + sLog.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not existing required spell.", + spell_id,node.prev,node.first,node.rank,node.req); + continue; + } + + // talents not required data in spell chain for work, but must be checked if present for intergrity + if(TalentSpellPos const* pos = GetTalentSpellPos(spell_id)) + { + if(node.rank!=pos->rank+1) + { + sLog.outErrorDb("Talent %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has wrong rank.", + spell_id,node.prev,node.first,node.rank,node.req); + continue; + } + + if(TalentEntry const* talentEntry = sTalentStore.LookupEntry(pos->talent_id)) + { + if(node.first!=talentEntry->RankID[0]) + { + sLog.outErrorDb("Talent %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has wrong first rank spell.", + spell_id,node.prev,node.first,node.rank,node.req); + continue; + } + + if(node.rank > 1 && node.prev != talentEntry->RankID[node.rank-1-1]) + { + sLog.outErrorDb("Talent %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has wrong prev rank spell.", + spell_id,node.prev,node.first,node.rank,node.req); + continue; + } + + if(node.req!=talentEntry->DependsOnSpell) + { + sLog.outErrorDb("Talent %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has wrong required spell.", + spell_id,node.prev,node.first,node.rank,node.req); + continue; + } + } + } + + mSpellChains[spell_id] = node; + + if(node.prev) + mSpellChainsNext.insert(SpellChainMapNext::value_type(node.prev,spell_id)); + + if(node.req) + mSpellChainsNext.insert(SpellChainMapNext::value_type(node.req,spell_id)); + + ++count; + } while( result->NextRow() ); + + // additional integrity checks + for(SpellChainMap::iterator i = mSpellChains.begin(); i != mSpellChains.end(); ++i) + { + if(i->second.prev) + { + SpellChainMap::iterator i_prev = mSpellChains.find(i->second.prev); + if(i_prev == mSpellChains.end()) + { + sLog.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not found previous rank spell in table.", + i->first,i->second.prev,i->second.first,i->second.rank,i->second.req); + } + else if( i_prev->second.first != i->second.first ) + { + sLog.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has different first spell in chain compared to previous rank spell (prev: %u, first: %u, rank: %d, req: %u).", + i->first,i->second.prev,i->second.first,i->second.rank,i->second.req, + i_prev->second.prev,i_prev->second.first,i_prev->second.rank,i_prev->second.req); + } + else if( i_prev->second.rank+1 != i->second.rank ) + { + sLog.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has different rank compared to previous rank spell (prev: %u, first: %u, rank: %d, req: %u).", + i->first,i->second.prev,i->second.first,i->second.rank,i->second.req, + i_prev->second.prev,i_prev->second.first,i_prev->second.rank,i_prev->second.req); + } + } + + if(i->second.req) + { + SpellChainMap::iterator i_req = mSpellChains.find(i->second.req); + if(i_req == mSpellChains.end()) + { + sLog.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not found required rank spell in table.", + i->first,i->second.prev,i->second.first,i->second.rank,i->second.req); + } + else if( i_req->second.first == i->second.first ) + { + sLog.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has required rank spell from same spell chain (prev: %u, first: %u, rank: %d, req: %u).", + i->first,i->second.prev,i->second.first,i->second.rank,i->second.req, + i_req->second.prev,i_req->second.first,i_req->second.rank,i_req->second.req); + } + else if( i_req->second.req ) + { + sLog.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has required rank spell with required spell (prev: %u, first: %u, rank: %d, req: %u).", + i->first,i->second.prev,i->second.first,i->second.rank,i->second.req, + i_req->second.prev,i_req->second.first,i_req->second.rank,i_req->second.req); + } + } + } + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u spell chain records", count ); +} + +void SpellMgr::LoadSpellLearnSkills() +{ + mSpellLearnSkills.clear(); // need for reload case + + // search auto-learned skills and add its to map also for use in unlearn spells/talents + uint32 dbc_count = 0; + for(uint32 spell = 0; spell < sSpellStore.GetNumRows(); ++spell) + { + SpellEntry const* entry = sSpellStore.LookupEntry(spell); + + if(!entry) + continue; + + for(int i = 0; i < 3; ++i) + { + if(entry->Effect[i]==SPELL_EFFECT_SKILL) + { + SpellLearnSkillNode dbc_node; + dbc_node.skill = entry->EffectMiscValue[i]; + if ( dbc_node.skill != SKILL_RIDING ) + dbc_node.value = 1; + else + dbc_node.value = (entry->EffectBasePoints[i]+1)*75; + dbc_node.maxvalue = (entry->EffectBasePoints[i]+1)*75; + + SpellLearnSkillNode const* db_node = GetSpellLearnSkill(spell); + + mSpellLearnSkills[spell] = dbc_node; + ++dbc_count; + break; + } + } + } + + sLog.outString(); + sLog.outString( ">> Loaded %u Spell Learn Skills from DBC", dbc_count ); +} + +void SpellMgr::LoadSpellLearnSpells() +{ + mSpellLearnSpells.clear(); // need for reload case + + QueryResult *result = WorldDatabase.PQuery("SELECT entry, SpellID FROM spell_learn_spell"); + if(!result) + { + barGoLink bar( 1 ); + bar.step(); + + sLog.outString(); + sLog.outString( ">> Loaded 0 spell learn spells" ); + sLog.outErrorDb("`spell_learn_spell` table is empty!"); + return; + } + + uint32 count = 0; + + barGoLink bar( result->GetRowCount() ); + do + { + bar.step(); + Field *fields = result->Fetch(); + + uint32 spell_id = fields[0].GetUInt32(); + + SpellLearnSpellNode node; + node.spell = fields[1].GetUInt32(); + node.autoLearned= false; + + if(!sSpellStore.LookupEntry(spell_id)) + { + sLog.outErrorDb("Spell %u listed in `spell_learn_spell` does not exist",spell_id); + continue; + } + + if(!sSpellStore.LookupEntry(node.spell)) + { + sLog.outErrorDb("Spell %u listed in `spell_learn_spell` does not exist",node.spell); + continue; + } + + mSpellLearnSpells.insert(SpellLearnSpellMap::value_type(spell_id,node)); + + ++count; + } while( result->NextRow() ); + + delete result; + + // search auto-learned spells and add its to map also for use in unlearn spells/talents + uint32 dbc_count = 0; + for(uint32 spell = 0; spell < sSpellStore.GetNumRows(); ++spell) + { + SpellEntry const* entry = sSpellStore.LookupEntry(spell); + + if(!entry) + continue; + + for(int i = 0; i < 3; ++i) + { + if(entry->Effect[i]==SPELL_EFFECT_LEARN_SPELL) + { + SpellLearnSpellNode dbc_node; + dbc_node.spell = entry->EffectTriggerSpell[i]; + dbc_node.autoLearned = true; + + SpellLearnSpellMap::const_iterator db_node_begin = GetBeginSpellLearnSpell(spell); + SpellLearnSpellMap::const_iterator db_node_end = GetEndSpellLearnSpell(spell); + + bool found = false; + for(SpellLearnSpellMap::const_iterator itr = db_node_begin; itr != db_node_end; ++itr) + { + if(itr->second.spell == dbc_node.spell) + { + sLog.outErrorDb("Spell %u auto-learn spell %u in spell.dbc then the record in `spell_learn_spell` is redundant, please fix DB.", + spell,dbc_node.spell); + found = true; + break; + } + } + + if(!found) // add new spell-spell pair if not found + { + mSpellLearnSpells.insert(SpellLearnSpellMap::value_type(spell,dbc_node)); + ++dbc_count; + } + } + } + } + + sLog.outString(); + sLog.outString( ">> Loaded %u spell learn spells + %u found in DBC", count, dbc_count ); +} + +void SpellMgr::LoadSpellScriptTarget() +{ + mSpellScriptTarget.clear(); // need for reload case + + uint32 count = 0; + + QueryResult *result = WorldDatabase.Query("SELECT entry,type,targetEntry FROM spell_script_target"); + + if(!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outErrorDb(">> Loaded 0 SpellScriptTarget. DB table `spell_script_target` is empty."); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 spellId = fields[0].GetUInt32(); + uint32 type = fields[1].GetUInt32(); + uint32 targetEntry = fields[2].GetUInt32(); + + SpellEntry const* spellProto = sSpellStore.LookupEntry(spellId); + + if(!spellProto) + { + sLog.outErrorDb("Table `spell_script_target`: spellId %u listed for TargetEntry %u does not exist.",spellId,targetEntry); + continue; + } + + bool targetfound = false; + for(int i = 0; i <3; ++i) + { + if( spellProto->EffectImplicitTargetA[i]==TARGET_SCRIPT || + spellProto->EffectImplicitTargetB[i]==TARGET_SCRIPT || + spellProto->EffectImplicitTargetA[i]==TARGET_SCRIPT_COORDINATES || + spellProto->EffectImplicitTargetB[i]==TARGET_SCRIPT_COORDINATES ) + { + targetfound = true; + break; + } + } + if(!targetfound) + { + sLog.outErrorDb("Table `spell_script_target`: spellId %u listed for TargetEntry %u does not have any implicit target TARGET_SCRIPT(38) or TARGET_SCRIPT_COORDINATES (46).",spellId,targetEntry); + continue; + } + + if( type >= MAX_SPELL_TARGET_TYPE ) + { + sLog.outErrorDb("Table `spell_script_target`: target type %u for TargetEntry %u is incorrect.",type,targetEntry); + continue; + } + + switch(type) + { + case SPELL_TARGET_TYPE_GAMEOBJECT: + { + if( targetEntry==0 ) + break; + + if(!sGOStorage.LookupEntry(targetEntry)) + { + sLog.outErrorDb("Table `spell_script_target`: gameobject template entry %u does not exist.",targetEntry); + continue; + } + break; + } + default: + { + if( targetEntry==0 ) + { + sLog.outErrorDb("Table `spell_script_target`: target entry == 0 for not GO target type (%u).",type); + continue; + } + if(!sCreatureStorage.LookupEntry(targetEntry)) + { + sLog.outErrorDb("Table `spell_script_target`: creature template entry %u does not exist.",targetEntry); + continue; + } + const CreatureInfo* cInfo = sCreatureStorage.LookupEntry(targetEntry); + + if(spellId == 30427 && !cInfo->SkinLootId) + { + sLog.outErrorDb("Table `spell_script_target` has creature %u as a target of spellid 30427, but this creature has no skinlootid. Gas extraction will not work!", cInfo->Entry); + continue; + } + break; + } + } + + mSpellScriptTarget.insert(SpellScriptTarget::value_type(spellId,SpellTargetEntry(SpellTargetType(type),targetEntry))); + + ++count; + } while (result->NextRow()); + + delete result; + + // Check all spells + /* Disabled (lot errors at this moment) + for(uint32 i = 1; i < sSpellStore.nCount; ++i) + { + SpellEntry const * spellInfo = sSpellStore.LookupEntry(i); + if(!spellInfo) + continue; + + bool found = false; + for(int j=0; j<3; ++j) + { + if( spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT || spellInfo->EffectImplicitTargetA[j] != TARGET_SELF && spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT ) + { + SpellScriptTarget::const_iterator lower = spellmgr.GetBeginSpellScriptTarget(spellInfo->Id); + SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(spellInfo->Id); + if(lower==upper) + { + sLog.outErrorDb("Spell (ID: %u) has effect EffectImplicitTargetA/EffectImplicitTargetB = %u (TARGET_SCRIPT), but does not have record in `spell_script_target`",spellInfo->Id,TARGET_SCRIPT); + break; // effects of spell + } + } + } + } + */ + + sLog.outString(); + sLog.outString(">> Loaded %u Spell Script Targets", count); +} + +void SpellMgr::LoadSpellPetAuras() +{ + mSpellPetAuraMap.clear(); // need for reload case + + uint32 count = 0; + + // 0 1 2 + QueryResult *result = WorldDatabase.Query("SELECT spell, pet, aura FROM spell_pet_auras"); + if( !result ) + { + + barGoLink bar( 1 ); + + bar.step(); + + sLog.outString(); + sLog.outString( ">> Loaded %u spell pet auras", count ); + return; + } + + barGoLink bar( result->GetRowCount() ); + + do + { + Field *fields = result->Fetch(); + + bar.step(); + + uint16 spell = fields[0].GetUInt16(); + uint16 pet = fields[1].GetUInt16(); + uint16 aura = fields[2].GetUInt16(); + + SpellPetAuraMap::iterator itr = mSpellPetAuraMap.find(spell); + if(itr != mSpellPetAuraMap.end()) + { + itr->second.AddAura(pet, aura); + } + else + { + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell); + if (!spellInfo) + { + sLog.outErrorDb("Spell %u listed in `spell_pet_auras` does not exist", spell); + continue; + } + int i = 0; + for(; i < 3; ++i) + if((spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA && + spellInfo->EffectApplyAuraName[i] == SPELL_AURA_DUMMY) || + spellInfo->Effect[i] == SPELL_EFFECT_DUMMY) + break; + + if(i == 3) + { + sLog.outError("Spell %u listed in `spell_pet_auras` does not have dummy aura or dummy effect", spell); + continue; + } + + SpellEntry const* spellInfo2 = sSpellStore.LookupEntry(aura); + if (!spellInfo2) + { + sLog.outErrorDb("Aura %u listed in `spell_pet_auras` does not exist", aura); + continue; + } + + PetAura pa(pet, aura, spellInfo->EffectImplicitTargetA[i] == TARGET_PET, spellInfo->EffectBasePoints[i] + spellInfo->EffectBaseDice[i]); + mSpellPetAuraMap[spell] = pa; + } + + ++count; + } while( result->NextRow() ); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u spell pet auras", count ); +} + +/// Some checks for spells, to prevent adding depricated/broken spells for trainers, spell book, etc +bool SpellMgr::IsSpellValid(SpellEntry const* spellInfo, Player* pl, bool msg) +{ + // not exist + if(!spellInfo) + return false; + + bool need_check_reagents = false; + + // check effects + for(int i=0; i<3; ++i) + { + switch(spellInfo->Effect[i]) + { + case 0: + continue; + + // craft spell for crafting non-existed item (break client recipes list show) + case SPELL_EFFECT_CREATE_ITEM: + { + if(!ObjectMgr::GetItemPrototype( spellInfo->EffectItemType[i] )) + { + if(msg) + { + if(pl) + ChatHandler(pl).PSendSysMessage("Craft spell %u create not-exist in DB item (Entry: %u) and then...",spellInfo->Id,spellInfo->EffectItemType[i]); + else + sLog.outErrorDb("Craft spell %u create not-exist in DB item (Entry: %u) and then...",spellInfo->Id,spellInfo->EffectItemType[i]); + } + return false; + } + + need_check_reagents = true; + break; + } + case SPELL_EFFECT_LEARN_SPELL: + { + SpellEntry const* spellInfo2 = sSpellStore.LookupEntry(spellInfo->EffectTriggerSpell[0]); + if( !IsSpellValid(spellInfo2,pl,msg) ) + { + if(msg) + { + if(pl) + ChatHandler(pl).PSendSysMessage("Spell %u learn to broken spell %u, and then...",spellInfo->Id,spellInfo->EffectTriggerSpell[0]); + else + sLog.outErrorDb("Spell %u learn to invalid spell %u, and then...",spellInfo->Id,spellInfo->EffectTriggerSpell[0]); + } + return false; + } + break; + } + } + } + + if(need_check_reagents) + { + for(int j = 0; j < 8; ++j) + { + if(spellInfo->Reagent[j] > 0 && !ObjectMgr::GetItemPrototype( spellInfo->Reagent[j] )) + { + if(msg) + { + if(pl) + ChatHandler(pl).PSendSysMessage("Craft spell %u have not-exist reagent in DB item (Entry: %u) and then...",spellInfo->Id,spellInfo->Reagent[j]); + else + sLog.outErrorDb("Craft spell %u have not-exist reagent in DB item (Entry: %u) and then...",spellInfo->Id,spellInfo->Reagent[j]); + } + return false; + } + } + } + + return true; +} + +bool IsSpellAllowedInLocation(SpellEntry const *spellInfo,uint32 map_id,uint32 zone_id,uint32 area_id) +{ + // normal case + if( spellInfo->AreaId && spellInfo->AreaId != zone_id && spellInfo->AreaId != area_id ) + return false; + + // elixirs (all area dependent elixirs have family SPELLFAMILY_POTION, use this for speedup) + if(spellInfo->SpellFamilyName==SPELLFAMILY_POTION) + { + if(uint32 mask = spellmgr.GetSpellElixirMask(spellInfo->Id)) + { + if(mask & ELIXIR_UNSTABLE_MASK) + { + // in the Blade's Edge Mountains Plateaus and Gruul's Lair. + return zone_id ==3522 || map_id==565; + } + if(mask & ELIXIR_UNSTABLE_MASK) + { + // in Tempest Keep, Serpentshrine Cavern, Caverns of Time: Mount Hyjal, Black Temple + // TODO: and the Sunwell Plateau + if(zone_id ==3607 || map_id==534 || map_id==564) + return true; + + MapEntry const* mapEntry = sMapStore.LookupEntry(map_id); + if(!mapEntry) + return false; + + return mapEntry->multimap_id==206; + } + + // elixirs not have another limitations + return true; + } + } + + // special cases zone check (maps checked by multimap common id) + switch(spellInfo->Id) + { + case 41618: + case 41620: + { + MapEntry const* mapEntry = sMapStore.LookupEntry(map_id); + if(!mapEntry) + return false; + + return mapEntry->multimap_id==206; + } + + case 41617: + case 41619: + { + MapEntry const* mapEntry = sMapStore.LookupEntry(map_id); + if(!mapEntry) + return false; + + return mapEntry->multimap_id==207; + } + // Dragonmaw Illusion + case 40216: + case 42016: + { + if ( area_id != 3759 && area_id != 3966 && area_id != 3939 ) + return false; + break; + } + } + + return true; +} + +void SpellMgr::LoadSkillLineAbilityMap() +{ + mSkillLineAbilityMap.clear(); + + uint32 count = 0; + + for (uint32 i = 0; i < sSkillLineAbilityStore.GetNumRows(); i++) + { + SkillLineAbilityEntry const *SkillInfo = sSkillLineAbilityStore.LookupEntry(i); + if(!SkillInfo) + continue; + + mSkillLineAbilityMap.insert(SkillLineAbilityMap::value_type(SkillInfo->spellId,SkillInfo)); + ++count; + } + + sLog.outString(); + sLog.outString(">> Loaded %u SkillLineAbility MultiMap", count); +} + +DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellEntry const* spellproto, bool triggered) +{ + // Explicit Diminishing Groups + switch(spellproto->SpellFamilyName) + { + case SPELLFAMILY_MAGE: + { + // Polymorph + if ((spellproto->SpellFamilyFlags & 0x00001000000LL) && spellproto->EffectApplyAuraName[0]==SPELL_AURA_MOD_CONFUSE) + return DIMINISHING_POLYMORPH; + break; + } + case SPELLFAMILY_ROGUE: + { + // Kidney Shot + if (spellproto->SpellFamilyFlags & 0x00000200000LL) + return DIMINISHING_KIDNEYSHOT; + // Blind + else if (spellproto->SpellFamilyFlags & 0x00001000000LL) + return DIMINISHING_BLIND_CYCLONE; + break; + } + case SPELLFAMILY_WARLOCK: + { + // Death Coil + if (spellproto->SpellFamilyFlags & 0x00000080000LL) + return DIMINISHING_DEATHCOIL; + // Fear + else if (spellproto->SpellFamilyFlags & 0x40840000000LL) + return DIMINISHING_WARLOCK_FEAR; + // Curses/etc + else if (spellproto->SpellFamilyFlags & 0x00080000000LL) + return DIMINISHING_LIMITONLY; + break; + } + case SPELLFAMILY_DRUID: + { + // Cyclone + if (spellproto->SpellFamilyFlags & 0x02000000000LL) + return DIMINISHING_BLIND_CYCLONE; + break; + } + case SPELLFAMILY_WARRIOR: + { + // Hamstring - limit duration to 10s in PvP + if (spellproto->SpellFamilyFlags & 0x00000000002LL) + return DIMINISHING_LIMITONLY; + break; + } + default: + break; + } + + // Get by mechanic + for (uint8 i=0;i<3;++i) + { + if (spellproto->Mechanic == MECHANIC_STUN || spellproto->EffectMechanic[i] == MECHANIC_STUN) + return triggered ? DIMINISHING_TRIGGER_STUN : DIMINISHING_CONTROL_STUN; + else if (spellproto->Mechanic == MECHANIC_SLEEP || spellproto->EffectMechanic[i] == MECHANIC_SLEEP) + return DIMINISHING_SLEEP; + else if (spellproto->Mechanic == MECHANIC_ROOT || spellproto->EffectMechanic[i] == MECHANIC_ROOT) + return triggered ? DIMINISHING_TRIGGER_ROOT : DIMINISHING_CONTROL_ROOT; + else if (spellproto->Mechanic == MECHANIC_FEAR || spellproto->EffectMechanic[i] == MECHANIC_FEAR) + return DIMINISHING_FEAR; + else if (spellproto->Mechanic == MECHANIC_CHARM || spellproto->EffectMechanic[i] == MECHANIC_CHARM) + return DIMINISHING_CHARM; + else if (spellproto->Mechanic == MECHANIC_SILENCE || spellproto->EffectMechanic[i] == MECHANIC_SILENCE) + return DIMINISHING_SILENCE; + else if (spellproto->Mechanic == MECHANIC_DISARM || spellproto->EffectMechanic[i] == MECHANIC_DISARM) + return DIMINISHING_DISARM; + else if (spellproto->Mechanic == MECHANIC_FREEZE || spellproto->EffectMechanic[i] == MECHANIC_FREEZE) + return DIMINISHING_FREEZE; + else if (spellproto->Mechanic == MECHANIC_KNOCKOUT|| spellproto->EffectMechanic[i] == MECHANIC_KNOCKOUT || + spellproto->Mechanic == MECHANIC_SAPPED || spellproto->EffectMechanic[i] == MECHANIC_SAPPED) + return DIMINISHING_KNOCKOUT; + else if (spellproto->Mechanic == MECHANIC_BANISH || spellproto->EffectMechanic[i] == MECHANIC_BANISH) + return DIMINISHING_BANISH; + } + + return DIMINISHING_NONE; +} + +bool IsDiminishingReturnsGroupDurationLimited(DiminishingGroup group) +{ + switch(group) + { + case DIMINISHING_CONTROL_STUN: + case DIMINISHING_TRIGGER_STUN: + case DIMINISHING_KIDNEYSHOT: + case DIMINISHING_SLEEP: + case DIMINISHING_CONTROL_ROOT: + case DIMINISHING_TRIGGER_ROOT: + case DIMINISHING_FEAR: + case DIMINISHING_WARLOCK_FEAR: + case DIMINISHING_CHARM: + case DIMINISHING_POLYMORPH: + case DIMINISHING_FREEZE: + case DIMINISHING_KNOCKOUT: + case DIMINISHING_BLIND_CYCLONE: + case DIMINISHING_BANISH: + case DIMINISHING_LIMITONLY: + return true; + } + return false; +} + +DiminishingReturnsType GetDiminishingReturnsGroupType(DiminishingGroup group) +{ + switch(group) + { + case DIMINISHING_BLIND_CYCLONE: + case DIMINISHING_CONTROL_STUN: + case DIMINISHING_TRIGGER_STUN: + case DIMINISHING_KIDNEYSHOT: + return DRTYPE_ALL; + case DIMINISHING_SLEEP: + case DIMINISHING_CONTROL_ROOT: + case DIMINISHING_TRIGGER_ROOT: + case DIMINISHING_FEAR: + case DIMINISHING_CHARM: + case DIMINISHING_POLYMORPH: + case DIMINISHING_SILENCE: + case DIMINISHING_DISARM: + case DIMINISHING_DEATHCOIL: + case DIMINISHING_FREEZE: + case DIMINISHING_BANISH: + case DIMINISHING_WARLOCK_FEAR: + case DIMINISHING_KNOCKOUT: + return DRTYPE_PLAYER; + } + + return DRTYPE_NONE; +} diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h new file mode 100644 index 00000000000..7e8ffc82564 --- /dev/null +++ b/src/game/SpellMgr.h @@ -0,0 +1,859 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _SPELLMGR_H +#define _SPELLMGR_H + +// For static or at-server-startup loaded spell data +// For more high level function for sSpellStore data + +#include "SharedDefines.h" +#include "Database/DBCStructure.h" +#include "Database/SQLStorage.h" + +#include "Utilities/HashMap.h" +#include + +class Player; +class Spell; + +extern SQLStorage sSpellThreatStore; + +enum SpellFailedReason +{ + SPELL_FAILED_AFFECTING_COMBAT = 0x00, + SPELL_FAILED_ALREADY_AT_FULL_HEALTH = 0x01, + SPELL_FAILED_ALREADY_AT_FULL_MANA = 0x02, + SPELL_FAILED_ALREADY_AT_FULL_POWER = 0x03, + SPELL_FAILED_ALREADY_BEING_TAMED = 0x04, + SPELL_FAILED_ALREADY_HAVE_CHARM = 0x05, + SPELL_FAILED_ALREADY_HAVE_SUMMON = 0x06, + SPELL_FAILED_ALREADY_OPEN = 0x07, + SPELL_FAILED_AURA_BOUNCED = 0x08, + SPELL_FAILED_AUTOTRACK_INTERRUPTED = 0x09, + SPELL_FAILED_BAD_IMPLICIT_TARGETS = 0x0A, + SPELL_FAILED_BAD_TARGETS = 0x0B, + SPELL_FAILED_CANT_BE_CHARMED = 0x0C, + SPELL_FAILED_CANT_BE_DISENCHANTED = 0x0D, + SPELL_FAILED_CANT_BE_DISENCHANTED_SKILL = 0x0E, + SPELL_FAILED_CANT_BE_PROSPECTED = 0x0F, + SPELL_FAILED_CANT_CAST_ON_TAPPED = 0x10, + SPELL_FAILED_CANT_DUEL_WHILE_INVISIBLE = 0x11, + SPELL_FAILED_CANT_DUEL_WHILE_STEALTHED = 0x12, + SPELL_FAILED_CANT_STEALTH = 0x13, + SPELL_FAILED_CASTER_AURASTATE = 0x14, + SPELL_FAILED_CASTER_DEAD = 0x15, + SPELL_FAILED_CHARMED = 0x16, + SPELL_FAILED_CHEST_IN_USE = 0x17, + SPELL_FAILED_CONFUSED = 0x18, + SPELL_FAILED_DONT_REPORT = 0x19, + SPELL_FAILED_EQUIPPED_ITEM = 0x1A, + SPELL_FAILED_EQUIPPED_ITEM_CLASS = 0x1B, + SPELL_FAILED_EQUIPPED_ITEM_CLASS_MAINHAND = 0x1C, + SPELL_FAILED_EQUIPPED_ITEM_CLASS_OFFHAND = 0x1D, + SPELL_FAILED_ERROR = 0x1E, + SPELL_FAILED_FIZZLE = 0x1F, + SPELL_FAILED_FLEEING = 0x20, + SPELL_FAILED_FOOD_LOWLEVEL = 0x21, + SPELL_FAILED_HIGHLEVEL = 0x22, + SPELL_FAILED_HUNGER_SATIATED = 0x23, + SPELL_FAILED_IMMUNE = 0x24, + SPELL_FAILED_INTERRUPTED = 0x25, + SPELL_FAILED_INTERRUPTED_COMBAT = 0x26, + SPELL_FAILED_ITEM_ALREADY_ENCHANTED = 0x27, + SPELL_FAILED_ITEM_GONE = 0x28, + SPELL_FAILED_ITEM_NOT_FOUND = 0x29, + SPELL_FAILED_ITEM_NOT_READY = 0x2A, + SPELL_FAILED_LEVEL_REQUIREMENT = 0x2B, + SPELL_FAILED_LINE_OF_SIGHT = 0x2C, + SPELL_FAILED_LOWLEVEL = 0x2D, + SPELL_FAILED_LOW_CASTLEVEL = 0x2E, + SPELL_FAILED_MAINHAND_EMPTY = 0x2F, + SPELL_FAILED_MOVING = 0x30, + SPELL_FAILED_NEED_AMMO = 0x31, + SPELL_FAILED_NEED_AMMO_POUCH = 0x32, + SPELL_FAILED_NEED_EXOTIC_AMMO = 0x33, + SPELL_FAILED_NOPATH = 0x34, + SPELL_FAILED_NOT_BEHIND = 0x35, + SPELL_FAILED_NOT_FISHABLE = 0x36, + SPELL_FAILED_NOT_FLYING = 0x37, + SPELL_FAILED_NOT_HERE = 0x38, + SPELL_FAILED_NOT_INFRONT = 0x39, + SPELL_FAILED_NOT_IN_CONTROL = 0x3A, + SPELL_FAILED_NOT_KNOWN = 0x3B, + SPELL_FAILED_NOT_MOUNTED = 0x3C, + SPELL_FAILED_NOT_ON_TAXI = 0x3D, + SPELL_FAILED_NOT_ON_TRANSPORT = 0x3E, + SPELL_FAILED_NOT_READY = 0x3F, + SPELL_FAILED_NOT_SHAPESHIFT = 0x40, + SPELL_FAILED_NOT_STANDING = 0x41, + SPELL_FAILED_NOT_TRADEABLE = 0x42, + SPELL_FAILED_NOT_TRADING = 0x43, + SPELL_FAILED_NOT_UNSHEATHED = 0x44, + SPELL_FAILED_NOT_WHILE_GHOST = 0x45, + SPELL_FAILED_NO_AMMO = 0x46, + SPELL_FAILED_NO_CHARGES_REMAIN = 0x47, + SPELL_FAILED_NO_CHAMPION = 0x48, + SPELL_FAILED_NO_COMBO_POINTS = 0x49, + SPELL_FAILED_NO_DUELING = 0x4A, + SPELL_FAILED_NO_ENDURANCE = 0x4B, + SPELL_FAILED_NO_FISH = 0x4C, + SPELL_FAILED_NO_ITEMS_WHILE_SHAPESHIFTED = 0x4D, + SPELL_FAILED_NO_MOUNTS_ALLOWED = 0x4E, + SPELL_FAILED_NO_PET = 0x4F, + SPELL_FAILED_NO_POWER = 0x50, + SPELL_FAILED_NOTHING_TO_DISPEL = 0x51, + SPELL_FAILED_NOTHING_TO_STEAL = 0x52, + SPELL_FAILED_ONLY_ABOVEWATER = 0x53, + SPELL_FAILED_ONLY_DAYTIME = 0x54, + SPELL_FAILED_ONLY_INDOORS = 0x55, + SPELL_FAILED_ONLY_MOUNTED = 0x56, + SPELL_FAILED_ONLY_NIGHTTIME = 0x57, + SPELL_FAILED_ONLY_OUTDOORS = 0x58, + SPELL_FAILED_ONLY_SHAPESHIFT = 0x59, + SPELL_FAILED_ONLY_STEALTHED = 0x5A, + SPELL_FAILED_ONLY_UNDERWATER = 0x5B, + SPELL_FAILED_OUT_OF_RANGE = 0x5C, + SPELL_FAILED_PACIFIED = 0x5D, + SPELL_FAILED_POSSESSED = 0x5E, + SPELL_FAILED_REAGENTS = 0x5F, + SPELL_FAILED_REQUIRES_AREA = 0x60, + SPELL_FAILED_REQUIRES_SPELL_FOCUS = 0x61, + SPELL_FAILED_ROOTED = 0x62, + SPELL_FAILED_SILENCED = 0x63, + SPELL_FAILED_SPELL_IN_PROGRESS = 0x64, + SPELL_FAILED_SPELL_LEARNED = 0x65, + SPELL_FAILED_SPELL_UNAVAILABLE = 0x66, + SPELL_FAILED_STUNNED = 0x67, + SPELL_FAILED_TARGETS_DEAD = 0x68, + SPELL_FAILED_TARGET_AFFECTING_COMBAT = 0x69, + SPELL_FAILED_TARGET_AURASTATE = 0x6A, + SPELL_FAILED_TARGET_DUELING = 0x6B, + SPELL_FAILED_TARGET_ENEMY = 0x6C, + SPELL_FAILED_TARGET_ENRAGED = 0x6D, + SPELL_FAILED_TARGET_FRIENDLY = 0x6E, + SPELL_FAILED_TARGET_IN_COMBAT = 0x6F, + SPELL_FAILED_TARGET_IS_PLAYER = 0x70, + SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED = 0x71, + SPELL_FAILED_TARGET_NOT_DEAD = 0x72, + SPELL_FAILED_TARGET_NOT_IN_PARTY = 0x73, + SPELL_FAILED_TARGET_NOT_LOOTED = 0x74, + SPELL_FAILED_TARGET_NOT_PLAYER = 0x75, + SPELL_FAILED_TARGET_NO_POCKETS = 0x76, + SPELL_FAILED_TARGET_NO_WEAPONS = 0x77, + SPELL_FAILED_TARGET_UNSKINNABLE = 0x78, + SPELL_FAILED_THIRST_SATIATED = 0x79, + SPELL_FAILED_TOO_CLOSE = 0x7A, + SPELL_FAILED_TOO_MANY_OF_ITEM = 0x7B, + SPELL_FAILED_TOTEM_CATEGORY = 0x7C, + SPELL_FAILED_TOTEMS = 0x7D, + SPELL_FAILED_TRAINING_POINTS = 0x7E, + SPELL_FAILED_TRY_AGAIN = 0x7F, + SPELL_FAILED_UNIT_NOT_BEHIND = 0x80, + SPELL_FAILED_UNIT_NOT_INFRONT = 0x81, + SPELL_FAILED_WRONG_PET_FOOD = 0x82, + SPELL_FAILED_NOT_WHILE_FATIGUED = 0x83, + SPELL_FAILED_TARGET_NOT_IN_INSTANCE = 0x84, + SPELL_FAILED_NOT_WHILE_TRADING = 0x85, + SPELL_FAILED_TARGET_NOT_IN_RAID = 0x86, + SPELL_FAILED_DISENCHANT_WHILE_LOOTING = 0x87, + SPELL_FAILED_PROSPECT_WHILE_LOOTING = 0x88, + SPELL_FAILED_PROSPECT_NEED_MORE = 0x89, + SPELL_FAILED_TARGET_FREEFORALL = 0x8A, + SPELL_FAILED_NO_EDIBLE_CORPSES = 0x8B, + SPELL_FAILED_ONLY_BATTLEGROUNDS = 0x8C, + SPELL_FAILED_TARGET_NOT_GHOST = 0x8D, + SPELL_FAILED_TOO_MANY_SKILLS = 0x8E, + SPELL_FAILED_TRANSFORM_UNUSABLE = 0x8F, + SPELL_FAILED_WRONG_WEATHER = 0x90, + SPELL_FAILED_DAMAGE_IMMUNE = 0x91, + SPELL_FAILED_PREVENTED_BY_MECHANIC = 0x92, + SPELL_FAILED_PLAY_TIME = 0x93, + SPELL_FAILED_REPUTATION = 0x94, + SPELL_FAILED_MIN_SKILL = 0x95, + SPELL_FAILED_NOT_IN_ARENA = 0x96, + SPELL_FAILED_NOT_ON_SHAPESHIFT = 0x97, + SPELL_FAILED_NOT_ON_STEALTHED = 0x98, + SPELL_FAILED_NOT_ON_DAMAGE_IMMUNE = 0x99, + SPELL_FAILED_NOT_ON_MOUNTED = 0x9A, + SPELL_FAILED_TOO_SHALLOW = 0x9B, + SPELL_FAILED_TARGET_NOT_IN_SANCTUARY = 0x9C, + SPELL_FAILED_TARGET_IS_TRIVIAL = 0x9D, + SPELL_FAILED_BM_OR_INVISGOD = 0x9E, + SPELL_FAILED_EXPERT_RIDING_REQUIREMENT = 0x9F, + SPELL_FAILED_ARTISAN_RIDING_REQUIREMENT = 0xA0, + SPELL_FAILED_NOT_IDLE = 0xA1, + SPELL_FAILED_NOT_INACTIVE = 0xA2, + SPELL_FAILED_PARTIAL_PLAYTIME = 0xA3, + SPELL_FAILED_NO_PLAYTIME = 0xA4, + SPELL_FAILED_NOT_IN_BATTLEGROUND = 0xA5, + SPELL_FAILED_ONLY_IN_ARENA = 0xA6, + SPELL_FAILED_TARGET_LOCKED_TO_RAID_INSTANCE = 0xA7, + SPELL_FAILED_UNKNOWN = 0xA8, +}; + +enum SpellFamilyNames +{ + SPELLFAMILY_GENERIC = 0, + SPELLFAMILY_UNK1 = 1, // events, holidays + // 2 - unused + SPELLFAMILY_MAGE = 3, + SPELLFAMILY_WARRIOR = 4, + SPELLFAMILY_WARLOCK = 5, + SPELLFAMILY_PRIEST = 6, + SPELLFAMILY_DRUID = 7, + SPELLFAMILY_ROGUE = 8, + SPELLFAMILY_HUNTER = 9, + SPELLFAMILY_PALADIN = 10, + SPELLFAMILY_SHAMAN = 11, + SPELLFAMILY_UNK2 = 12, + SPELLFAMILY_POTION = 13 +}; + +//Some SpellFamilyFlags +#define SPELLFAMILYFLAG_ROGUE_VANISH 0x000000800LL +#define SPELLFAMILYFLAG_ROGUE_STEALTH 0x000400000LL +#define SPELLFAMILYFLAG_ROGUE_BACKSTAB 0x000800004LL +#define SPELLFAMILYFLAG_ROGUE_SAP 0x000000080LL +#define SPELLFAMILYFLAG_ROGUE_FEINT 0x008000000LL +#define SPELLFAMILYFLAG_ROGUE_KIDNEYSHOT 0x000200000LL +#define SPELLFAMILYFLAG_ROGUE__FINISHING_MOVE 0x9003E0000LL + +// Spell clasification +enum SpellSpecific +{ + SPELL_NORMAL = 0, + SPELL_SEAL = 1, + SPELL_BLESSING = 2, + SPELL_AURA = 3, + SPELL_STING = 4, + SPELL_CURSE = 5, + SPELL_ASPECT = 6, + SPELL_TRACKER = 7, + SPELL_WARLOCK_ARMOR = 8, + SPELL_MAGE_ARMOR = 9, + SPELL_ELEMENTAL_SHIELD = 10, + SPELL_MAGE_POLYMORPH = 11, + SPELL_POSITIVE_SHOUT = 12, + SPELL_JUDGEMENT = 13, + SPELL_BATTLE_ELIXIR = 14, + SPELL_GUARDIAN_ELIXIR = 15, + SPELL_FLASK_ELIXIR = 16 +}; + +SpellSpecific GetSpellSpecific(uint32 spellId); + +// Different spell properties +inline float GetSpellRadius(SpellRadiusEntry const *radius) { return (radius ? radius->Radius : 0); } +uint32 GetSpellCastTime(SpellEntry const* spellInfo, Spell const* spell = NULL); +inline float GetSpellMinRange(SpellRangeEntry const *range) { return (range ? range->minRange : 0); } +inline float GetSpellMaxRange(SpellRangeEntry const *range) { return (range ? range->maxRange : 0); } +inline uint32 GetSpellRecoveryTime(SpellEntry const *spellInfo) { return spellInfo->RecoveryTime > spellInfo->CategoryRecoveryTime ? spellInfo->RecoveryTime : spellInfo->CategoryRecoveryTime; } +int32 GetSpellDuration(SpellEntry const *spellInfo); +int32 GetSpellMaxDuration(SpellEntry const *spellInfo); + +inline bool IsSpellHaveEffect(SpellEntry const *spellInfo, SpellEffects effect) +{ + for(int i= 0; i < 3; ++i) + if(spellInfo->Effect[i]==effect) + return true; + return false; +} + +bool IsNoStackAuraDueToAura(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_2, uint32 effIndex_2); + +inline bool IsSealSpell(SpellEntry const *spellInfo) +{ + //Collection of all the seal family flags. No other paladin spell has any of those. + return spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && + ( spellInfo->SpellFamilyFlags & 0x4000A000200LL ); +} + +inline bool IsElementalShield(SpellEntry const *spellInfo) +{ + // family flags 10 (Lightning), 42 (Earth), 37 (Water), proc shield from T2 8 pieces bonus + return (spellInfo->SpellFamilyFlags & 0x42000000400LL) || spellInfo->Id == 23552; +} + +int32 CompareAuraRanks(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_2, uint32 effIndex_2); +bool IsSingleFromSpellSpecificPerCaster(uint32 spellSpec1,uint32 spellSpec2); +bool IsPassiveSpell(uint32 spellId); + +inline bool IsDeathPersistentSpell(SpellEntry const *spellInfo) +{ + switch(spellInfo->Id) + { + case 40214: // Dragonmaw Illusion + case 35480: case 35481: case 35482: // Human Illusion + case 35483: case 39824: // Human Illusion + return true; + } + + return spellInfo->AttributesEx3 & SPELL_ATTR_EX3_DEATH_PERSISTENT; +} + +inline bool IsNonCombatSpell(SpellEntry const *spellInfo) +{ + return (spellInfo->Attributes & SPELL_ATTR_CANT_USED_IN_COMBAT) != 0; +} + +bool IsPositiveSpell(uint32 spellId); +bool IsPositiveEffect(uint32 spellId, uint32 effIndex); +bool IsPositiveTarget(uint32 targetA, uint32 targetB); + +bool IsSingleTargetSpell(SpellEntry const *spellInfo); +bool IsSingleTargetSpells(SpellEntry const *spellInfo1, SpellEntry const *spellInfo2); + +bool IsSpellAllowedInLocation(SpellEntry const *spellInfo,uint32 map_id,uint32 zone_id,uint32 area_id); + +inline bool IsAreaEffectTarget( Targets target ) +{ + switch (target ) + { + case TARGET_AREAEFFECT_CUSTOM: + case TARGET_ALL_ENEMY_IN_AREA: + case TARGET_ALL_ENEMY_IN_AREA_INSTANT: + case TARGET_ALL_PARTY_AROUND_CASTER: + case TARGET_ALL_AROUND_CASTER: + case TARGET_ALL_ENEMY_IN_AREA_CHANNELED: + case TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER: + case TARGET_ALL_PARTY: + case TARGET_ALL_PARTY_AROUND_CASTER_2: + case TARGET_AREAEFFECT_PARTY: + case TARGET_AREAEFFECT_CUSTOM_2: + case TARGET_AREAEFFECT_PARTY_AND_CLASS: + case TARGET_IN_FRONT_OF_CASTER: + case TARGET_ALL_FRIENDLY_UNITS_IN_AREA: + return true; + default: + break; + } + return false; +} + +inline bool IsAreaOfEffectSpell(SpellEntry const *spellInfo) +{ + if(IsAreaEffectTarget(Targets(spellInfo->EffectImplicitTargetA[0])) || IsAreaEffectTarget(Targets(spellInfo->EffectImplicitTargetB[0]))) + return true; + if(IsAreaEffectTarget(Targets(spellInfo->EffectImplicitTargetA[1])) || IsAreaEffectTarget(Targets(spellInfo->EffectImplicitTargetB[1]))) + return true; + if(IsAreaEffectTarget(Targets(spellInfo->EffectImplicitTargetA[2])) || IsAreaEffectTarget(Targets(spellInfo->EffectImplicitTargetB[2]))) + return true; + return false; +} + +inline bool IsAreaAuraEffect(uint32 effect) +{ + if( effect == SPELL_EFFECT_APPLY_AREA_AURA_PARTY || + effect == SPELL_EFFECT_APPLY_AREA_AURA_FRIEND || + effect == SPELL_EFFECT_APPLY_AREA_AURA_ENEMY || + effect == SPELL_EFFECT_APPLY_AREA_AURA_PET || + effect == SPELL_EFFECT_APPLY_AREA_AURA_OWNER) + return true; + return false; +} + +inline bool IsDispelSpell(SpellEntry const *spellInfo) +{ + if (spellInfo->Effect[0] == SPELL_EFFECT_DISPEL || + spellInfo->Effect[1] == SPELL_EFFECT_DISPEL || + spellInfo->Effect[2] == SPELL_EFFECT_DISPEL ) + return true; + return false; +} +inline bool isSpellBreakStealth(SpellEntry const* spellInfo) +{ + return !(spellInfo->AttributesEx & SPELL_ATTR_EX_NOT_BREAK_STEALTH); +} + +uint8 GetErrorAtShapeshiftedCast (SpellEntry const *spellInfo, uint32 form); + +inline bool IsChanneledSpell(SpellEntry const* spellInfo) +{ + return (spellInfo->AttributesEx & (SPELL_ATTR_EX_CHANNELED_1 | SPELL_ATTR_EX_CHANNELED_2)); +} + +inline bool NeedsComboPoints(SpellEntry const* spellInfo) +{ + return (spellInfo->AttributesEx & (SPELL_ATTR_EX_REQ_COMBO_POINTS1 | SPELL_ATTR_EX_REQ_COMBO_POINTS2)); +} + +inline SpellSchoolMask GetSpellSchoolMask(SpellEntry const* spellInfo) +{ + return SpellSchoolMask(spellInfo->SchoolMask); +} + +inline uint32 GetSpellMechanicMask(SpellEntry const* spellInfo, int32 effect) +{ + uint32 mask = 0; + if (spellInfo->Mechanic) + mask |= 1<Mechanic; + if (spellInfo->EffectMechanic[effect]) + mask |= 1<EffectMechanic[effect]; + return mask; +} + +inline Mechanics GetEffectMechanic(SpellEntry const* spellInfo, int32 effect) +{ + if (spellInfo->EffectMechanic[effect]) + return Mechanics(spellInfo->EffectMechanic[effect]); + if (spellInfo->Mechanic) + return Mechanics(spellInfo->Mechanic); + return MECHANIC_NONE; +} + +inline uint32 GetDispellMask(DispelType dispel) +{ + // If dispell all + if (dispel == DISPEL_ALL) + return DISPEL_ALL_MASK; + else + return (1 << dispel); +} + +// Diminishing Returns interaction with spells +DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellEntry const* spellproto, bool triggered); +bool IsDiminishingReturnsGroupDurationLimited(DiminishingGroup group); +DiminishingReturnsType GetDiminishingReturnsGroupType(DiminishingGroup group); + +// Spell affects related declarations (accessed using SpellMgr functions) +typedef std::map SpellAffectMap; + +// Spell proc event related declarations (accessed using SpellMgr functions) +enum ProcFlags +{ + PROC_FLAG_NONE = 0x00000000, // None + PROC_FLAG_HIT_MELEE = 0x00000001, // On melee hit + PROC_FLAG_STRUCK_MELEE = 0x00000002, // On being struck melee + PROC_FLAG_KILL_XP_GIVER = 0x00000004, // On kill target giving XP or honor + PROC_FLAG_SPECIAL_DROP = 0x00000008, // + PROC_FLAG_DODGE = 0x00000010, // On dodge melee attack + PROC_FLAG_PARRY = 0x00000020, // On parry melee attack + PROC_FLAG_BLOCK = 0x00000040, // On block attack + PROC_FLAG_TOUCH = 0x00000080, // On being touched (for bombs, probably?) + PROC_FLAG_TARGET_LOW_HEALTH = 0x00000100, // On deal damage to enemy with 20% or less health + PROC_FLAG_LOW_HEALTH = 0x00000200, // On health dropped below 20% + PROC_FLAG_STRUCK_RANGED = 0x00000400, // On being struck ranged + PROC_FLAG_HIT_SPECIAL = 0x00000800, // (!)Removed, may be reassigned in future + PROC_FLAG_CRIT_MELEE = 0x00001000, // On crit melee + PROC_FLAG_STRUCK_CRIT_MELEE = 0x00002000, // On being critically struck in melee + PROC_FLAG_CAST_SPELL = 0x00004000, // On cast spell + PROC_FLAG_TAKE_DAMAGE = 0x00008000, // On take damage + PROC_FLAG_CRIT_SPELL = 0x00010000, // On crit spell + PROC_FLAG_HIT_SPELL = 0x00020000, // On hit spell + PROC_FLAG_STRUCK_CRIT_SPELL = 0x00040000, // On being critically struck by a spell + PROC_FLAG_HIT_RANGED = 0x00080000, // On getting ranged hit + PROC_FLAG_STRUCK_SPELL = 0x00100000, // On being struck by a spell + PROC_FLAG_TRAP = 0x00200000, // On trap activation (?) + PROC_FLAG_CRIT_RANGED = 0x00400000, // On getting ranged crit + PROC_FLAG_STRUCK_CRIT_RANGED = 0x00800000, // On being critically struck by a ranged attack + PROC_FLAG_RESIST_SPELL = 0x01000000, // On resist enemy spell + PROC_FLAG_TARGET_RESISTS = 0x02000000, // On enemy resisted spell + PROC_FLAG_TARGET_DODGE_OR_PARRY = 0x04000000, // On enemy dodges/parries + PROC_FLAG_HEAL = 0x08000000, // On heal + PROC_FLAG_CRIT_HEAL = 0x10000000, // On critical healing effect + PROC_FLAG_HEALED = 0x20000000, // On healing + PROC_FLAG_TARGET_BLOCK = 0x40000000, // On enemy blocks + PROC_FLAG_MISS = 0x80000000 // On miss melee attack +}; + +struct SpellProcEventEntry +{ + uint32 schoolMask; // if nonzero - bit mask for matching proc condition based on spell candidate's school: Fire=2, Mask=1<<(2-1)=2 + uint32 category; // if nonzero - match proc condition based on candidate spell's category + uint32 skillId; // if nonzero - for matching proc condition based on candidate spell's skillId from SkillLineAbility.dbc (Shadow Bolt = Destruction) + uint32 spellFamilyName; // if nonzero - for matching proc condition based on candidate spell's SpellFamilyNamer value + uint64 spellFamilyMask; // if nonzero - for matching proc condition based on candidate spell's SpellFamilyFlags (like auras 107 and 108 do) + uint32 procFlags; // bitmask for matching proc event + float ppmRate; // for melee (ranged?) damage spells - proc rate per minute. if zero, falls back to flat chance from Spell.dbc + uint32 cooldown; // hidden cooldown used for some spell proc events, applied to _triggered_spell_ +}; + +typedef HM_NAMESPACE::hash_map SpellProcEventMap; + +#define ELIXIR_BATTLE_MASK 0x1 +#define ELIXIR_GUARDIAN_MASK 0x2 +#define ELIXIR_FLASK_MASK (ELIXIR_BATTLE_MASK|ELIXIR_GUARDIAN_MASK) +#define ELIXIR_UNSTABLE_MASK 0x4 +#define ELIXIR_SHATTRATH_MASK 0x8 + +typedef std::map SpellElixirMap; + +// Spell script target related declarations (accessed using SpellMgr functions) +enum SpellTargetType +{ + SPELL_TARGET_TYPE_GAMEOBJECT = 0, + SPELL_TARGET_TYPE_CREATURE = 1, + SPELL_TARGET_TYPE_DEAD = 2 +}; + +#define MAX_SPELL_TARGET_TYPE 3 + +struct SpellTargetEntry +{ + SpellTargetEntry(SpellTargetType type_,uint32 targetEntry_) : type(type_), targetEntry(targetEntry_) {} + SpellTargetType type; + uint32 targetEntry; +}; + +typedef std::multimap SpellScriptTarget; + +// coordinates for spells (accessed using SpellMgr functions) +struct SpellTargetPosition +{ + uint32 target_mapId; + float target_X; + float target_Y; + float target_Z; + float target_Orientation; +}; + +typedef HM_NAMESPACE::hash_map SpellTargetPositionMap; + +// Spell pet auras +class PetAura +{ + public: + PetAura() + { + auras.clear(); + } + + PetAura(uint16 petEntry, uint16 aura, bool _removeOnChangePet, int _damage) : + removeOnChangePet(_removeOnChangePet), damage(_damage) + { + auras[petEntry] = aura; + } + + uint16 GetAura(uint16 petEntry) const + { + std::map::const_iterator itr = auras.find(petEntry); + if(itr != auras.end()) + return itr->second; + else + { + std::map::const_iterator itr = auras.find(0); + if(itr != auras.end()) + return itr->second; + else + return 0; + } + } + + void AddAura(uint16 petEntry, uint16 aura) + { + auras[petEntry] = aura; + } + + bool IsRemovedOnChangePet() const + { + return removeOnChangePet; + } + + int32 GetDamage() const + { + return damage; + } + + private: + std::map auras; + bool removeOnChangePet; + int32 damage; +}; +typedef std::map SpellPetAuraMap; + +// Spell rank chain (accessed using SpellMgr functions) +struct SpellChainNode +{ + uint32 prev; + uint32 first; + uint32 req; + uint8 rank; +}; + +typedef HM_NAMESPACE::hash_map SpellChainMap; +typedef std::multimap SpellChainMapNext; + +// Spell learning properties (accessed using SpellMgr functions) +struct SpellLearnSkillNode +{ + uint32 skill; + uint32 value; // 0 - max skill value for player level + uint32 maxvalue; // 0 - max skill value for player level +}; + +typedef std::map SpellLearnSkillMap; + +struct SpellLearnSpellNode +{ + uint32 spell; + bool autoLearned; +}; + +typedef std::multimap SpellLearnSpellMap; + +typedef std::multimap SkillLineAbilityMap; + +inline bool IsPrimaryProfessionSkill(uint32 skill) +{ + SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(skill); + if(!pSkill) + return false; + + if(pSkill->categoryId != SKILL_CATEGORY_PROFESSION) + return false; + + return true; +} + +inline bool IsProfessionSkill(uint32 skill) +{ + return IsPrimaryProfessionSkill(skill) || skill == SKILL_FISHING || skill == SKILL_COOKING || skill == SKILL_FIRST_AID; +} + +class SpellMgr +{ + // Constructors + public: + SpellMgr(); + ~SpellMgr(); + + // Accessors (const or static functions) + public: + // Spell affects + uint64 GetSpellAffectMask(uint16 spellId, uint8 effectId) const + { + SpellAffectMap::const_iterator itr = mSpellAffectMap.find((spellId<<8) + effectId); + if( itr != mSpellAffectMap.end( ) ) + return itr->second; + return 0; + } + + bool IsAffectedBySpell(SpellEntry const *spellInfo, uint32 spellId, uint8 effectId, uint64 familyFlags) const; + + SpellElixirMap const& GetSpellElixirMap() const { return mSpellElixirs; } + + uint32 GetSpellElixirMask(uint32 spellid) const + { + SpellElixirMap::const_iterator itr = mSpellElixirs.find(spellid); + if(itr==mSpellElixirs.end()) + return 0x0; + + return itr->second; + } + + SpellSpecific GetSpellElixirSpecific(uint32 spellid) const + { + uint32 mask = GetSpellElixirMask(spellid); + if((mask & ELIXIR_FLASK_MASK)==ELIXIR_FLASK_MASK) + return SPELL_FLASK_ELIXIR; + else if(mask & ELIXIR_BATTLE_MASK) + return SPELL_BATTLE_ELIXIR; + else if(mask & ELIXIR_GUARDIAN_MASK) + return SPELL_GUARDIAN_ELIXIR; + else + return SPELL_NORMAL; + } + + // Spell proc events + SpellProcEventEntry const* GetSpellProcEvent(uint32 spellId) const + { + SpellProcEventMap::const_iterator itr = mSpellProcEventMap.find(spellId); + if( itr != mSpellProcEventMap.end( ) ) + return &itr->second; + return NULL; + } + + static bool IsSpellProcEventCanTriggeredBy( SpellProcEventEntry const * spellProcEvent, SpellEntry const * procSpell, uint32 procFlags ); + + // Spell target coordinates + SpellTargetPosition const* GetSpellTargetPosition(uint32 spell_id) const + { + SpellTargetPositionMap::const_iterator itr = mSpellTargetPositions.find( spell_id ); + if( itr != mSpellTargetPositions.end( ) ) + return &itr->second; + return NULL; + } + + // Spell ranks chains + SpellChainNode const* GetSpellChainNode(uint32 spell_id) const + { + SpellChainMap::const_iterator itr = mSpellChains.find(spell_id); + if(itr == mSpellChains.end()) + return NULL; + + return &itr->second; + } + + uint32 GetFirstSpellInChain(uint32 spell_id) const + { + if(SpellChainNode const* node = GetSpellChainNode(spell_id)) + return node->first; + + return spell_id; + } + + uint32 GetPrevSpellInChain(uint32 spell_id) const + { + if(SpellChainNode const* node = GetSpellChainNode(spell_id)) + return node->prev; + + return 0; + } + + SpellChainMapNext const& GetSpellChainNext() const { return mSpellChainsNext; } + + // Note: not use rank for compare to spell ranks: spell chains isn't linear order + // Use IsHighRankOfSpell instead + uint8 GetSpellRank(uint32 spell_id) const + { + if(SpellChainNode const* node = GetSpellChainNode(spell_id)) + return node->rank; + + return 0; + } + + uint8 IsHighRankOfSpell(uint32 spell1,uint32 spell2) const + { + SpellChainMap::const_iterator itr = mSpellChains.find(spell1); + + uint32 rank2 = GetSpellRank(spell2); + + // not ordered correctly by rank value + if(itr == mSpellChains.end() || !rank2 || itr->second.rank <= rank2) + return false; + + // check present in same rank chain + for(; itr != mSpellChains.end(); itr = mSpellChains.find(itr->second.prev)) + if(itr->second.prev==spell2) + return true; + + return false; + } + + bool IsRankSpellDueToSpell(SpellEntry const *spellInfo_1,uint32 spellId_2) const; + static bool canStackSpellRanks(SpellEntry const *spellInfo); + bool IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) const; + + SpellEntry const* SelectAuraRankForPlayerLevel(SpellEntry const* spellInfo, uint32 playerLevel) const; + + // Spell learning + SpellLearnSkillNode const* GetSpellLearnSkill(uint32 spell_id) const + { + SpellLearnSkillMap::const_iterator itr = mSpellLearnSkills.find(spell_id); + if(itr != mSpellLearnSkills.end()) + return &itr->second; + else + return NULL; + } + + bool IsSpellLearnSpell(uint32 spell_id) const + { + return mSpellLearnSpells.count(spell_id)!=0; + } + + SpellLearnSpellMap::const_iterator GetBeginSpellLearnSpell(uint32 spell_id) const + { + return mSpellLearnSpells.lower_bound(spell_id); + } + + SpellLearnSpellMap::const_iterator GetEndSpellLearnSpell(uint32 spell_id) const + { + return mSpellLearnSpells.upper_bound(spell_id); + } + + bool IsSpellLearnToSpell(uint32 spell_id1,uint32 spell_id2) const + { + SpellLearnSpellMap::const_iterator b = GetBeginSpellLearnSpell(spell_id1); + SpellLearnSpellMap::const_iterator e = GetEndSpellLearnSpell(spell_id1); + for(SpellLearnSpellMap::const_iterator i = b; i != e; ++i) + if(i->second.spell==spell_id2) + return true; + return false; + } + + static bool IsProfessionSpell(uint32 spellId); + static bool IsPrimaryProfessionSpell(uint32 spellId); + bool IsPrimaryProfessionFirstRankSpell(uint32 spellId) const; + + // Spell script targets + SpellScriptTarget::const_iterator GetBeginSpellScriptTarget(uint32 spell_id) const + { + return mSpellScriptTarget.lower_bound(spell_id); + } + + SpellScriptTarget::const_iterator GetEndSpellScriptTarget(uint32 spell_id) const + { + return mSpellScriptTarget.upper_bound(spell_id); + } + + // Spell correctess for client using + static bool IsSpellValid(SpellEntry const * spellInfo, Player* pl = NULL, bool msg = true); + + SkillLineAbilityMap::const_iterator GetBeginSkillLineAbilityMap(uint32 spell_id) const + { + return mSkillLineAbilityMap.lower_bound(spell_id); + } + + SkillLineAbilityMap::const_iterator GetEndSkillLineAbilityMap(uint32 spell_id) const + { + return mSkillLineAbilityMap.upper_bound(spell_id); + } + + PetAura const* GetPetAura(uint16 spell_id) + { + SpellPetAuraMap::const_iterator itr = mSpellPetAuraMap.find(spell_id); + if(itr != mSpellPetAuraMap.end()) + return &itr->second; + else + return NULL; + } + + // Modifiers + public: + static SpellMgr& Instance(); + + // Loading data at server startup + void LoadSpellChains(); + void LoadSpellLearnSkills(); + void LoadSpellLearnSpells(); + void LoadSpellScriptTarget(); + void LoadSpellAffects(); + void LoadSpellElixirs(); + void LoadSpellProcEvents(); + void LoadSpellTargetPositions(); + void LoadSpellThreats(); + void LoadSkillLineAbilityMap(); + void LoadSpellPetAuras(); + + private: + SpellScriptTarget mSpellScriptTarget; + SpellChainMap mSpellChains; + SpellChainMapNext mSpellChainsNext; + SpellLearnSkillMap mSpellLearnSkills; + SpellLearnSpellMap mSpellLearnSpells; + SpellTargetPositionMap mSpellTargetPositions; + SpellAffectMap mSpellAffectMap; + SpellElixirMap mSpellElixirs; + SpellProcEventMap mSpellProcEventMap; + SkillLineAbilityMap mSkillLineAbilityMap; + SpellPetAuraMap mSpellPetAuraMap; +}; + +#define spellmgr SpellMgr::Instance() +#endif diff --git a/src/game/StatSystem.cpp b/src/game/StatSystem.cpp new file mode 100644 index 00000000000..b89346d937a --- /dev/null +++ b/src/game/StatSystem.cpp @@ -0,0 +1,955 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Unit.h" +#include "Player.h" +#include "Pet.h" +#include "Creature.h" +#include "SharedDefines.h" +#include "SpellAuras.h" + +/*####################################### +######## ######## +######## PLAYERS STAT SYSTEM ######## +######## ######## +#######################################*/ + +bool Player::UpdateStats(Stats stat) +{ + if(stat > STAT_SPIRIT) + return false; + + // value = ((base_value * base_pct) + total_value) * total_pct + float value = GetTotalStatValue(stat); + + SetStat(stat, int32(value)); + + if(stat == STAT_STAMINA || stat == STAT_INTELLECT) + { + Pet *pet = GetPet(); + if(pet) + pet->UpdateStats(stat); + } + + switch(stat) + { + case STAT_STRENGTH: + UpdateAttackPowerAndDamage(); + UpdateShieldBlockValue(); + break; + case STAT_AGILITY: + UpdateArmor(); + UpdateAttackPowerAndDamage(true); + if(getClass() == CLASS_ROGUE || getClass() == CLASS_HUNTER || getClass() == CLASS_DRUID && m_form==FORM_CAT) + UpdateAttackPowerAndDamage(); + + UpdateAllCritPercentages(); + UpdateDodgePercentage(); + break; + + case STAT_STAMINA: UpdateMaxHealth(); break; + case STAT_INTELLECT: + UpdateMaxPower(POWER_MANA); + UpdateAllSpellCritChances(); + UpdateAttackPowerAndDamage(true); //SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT, only intelect currently + UpdateArmor(); //SPELL_AURA_MOD_RESISTANCE_OF_INTELLECT_PERCENT, only armor currently + break; + + case STAT_SPIRIT: + break; + + default: + break; + } + UpdateSpellDamageAndHealingBonus(); + UpdateManaRegen(); + return true; +} + +void Player::UpdateSpellDamageAndHealingBonus() +{ + // Magic damage modifiers implemented in Unit::SpellDamageBonus + // This information for client side use only + // Get healing bonus for all schools + SetStatInt32Value(PLAYER_FIELD_MOD_HEALING_DONE_POS, SpellBaseHealingBonus(SPELL_SCHOOL_MASK_ALL)); + // Get damage bonus for all schools + for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++) + SetStatInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i, SpellBaseDamageBonus(SpellSchoolMask(1 << i))); +} + +bool Player::UpdateAllStats() +{ + for (int i = STAT_STRENGTH; i < MAX_STATS; i++) + { + float value = GetTotalStatValue(Stats(i)); + SetStat(Stats(i), (int32)value); + } + + UpdateAttackPowerAndDamage(); + UpdateAttackPowerAndDamage(true); + UpdateArmor(); + UpdateMaxHealth(); + + for(int i = POWER_MANA; i < MAX_POWERS; i++) + UpdateMaxPower(Powers(i)); + + UpdateAllCritPercentages(); + UpdateAllSpellCritChances(); + UpdateDefenseBonusesMod(); + UpdateShieldBlockValue(); + UpdateSpellDamageAndHealingBonus(); + UpdateManaRegen(); + UpdateExpertise(BASE_ATTACK); + UpdateExpertise(OFF_ATTACK); + for (int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++) + UpdateResistances(i); + + return true; +} + +void Player::UpdateResistances(uint32 school) +{ + if(school > SPELL_SCHOOL_NORMAL) + { + float value = GetTotalAuraModValue(UnitMods(UNIT_MOD_RESISTANCE_START + school)); + SetResistance(SpellSchools(school), int32(value)); + + Pet *pet = GetPet(); + if(pet) + pet->UpdateResistances(school); + } + else + UpdateArmor(); +} + +void Player::UpdateArmor() +{ + float value = 0.0f; + UnitMods unitMod = UNIT_MOD_ARMOR; + + value = GetModifierValue(unitMod, BASE_VALUE); // base armor (from items) + value *= GetModifierValue(unitMod, BASE_PCT); // armor percent from items + value += GetStat(STAT_AGILITY) * 2.0f; // armor bonus from stats + value += GetModifierValue(unitMod, TOTAL_VALUE); + + //add dynamic flat mods + AuraList const& mResbyIntellect = GetAurasByType(SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT); + for(AuraList::const_iterator i = mResbyIntellect.begin();i != mResbyIntellect.end(); ++i) + { + Modifier* mod = (*i)->GetModifier(); + if(mod->m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) + value += int32(GetStat(Stats((*i)->GetMiscBValue())) * mod->m_amount / 100.0f); + } + + value *= GetModifierValue(unitMod, TOTAL_PCT); + + SetArmor(int32(value)); + + Pet *pet = GetPet(); + if(pet) + pet->UpdateArmor(); +} + +float Player::GetHealthBonusFromStamina() +{ + float stamina = GetStat(STAT_STAMINA); + + float baseStam = stamina < 20 ? stamina : 20; + float moreStam = stamina - baseStam; + + return baseStam + (moreStam*10.0f); +} + +float Player::GetManaBonusFromIntellect() +{ + float intellect = GetStat(STAT_INTELLECT); + + float baseInt = intellect < 20 ? intellect : 20; + float moreInt = intellect - baseInt; + + return baseInt + (moreInt*15.0f); +} + +void Player::UpdateMaxHealth() +{ + UnitMods unitMod = UNIT_MOD_HEALTH; + + float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreateHealth(); + value *= GetModifierValue(unitMod, BASE_PCT); + value += GetModifierValue(unitMod, TOTAL_VALUE) + GetHealthBonusFromStamina(); + value *= GetModifierValue(unitMod, TOTAL_PCT); + + SetMaxHealth((uint32)value); +} + +void Player::UpdateMaxPower(Powers power) +{ + UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + power); + + float bonusPower = (power == POWER_MANA) ? GetManaBonusFromIntellect() : 0; + + float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power); + value *= GetModifierValue(unitMod, BASE_PCT); + value += GetModifierValue(unitMod, TOTAL_VALUE) + bonusPower; + value *= GetModifierValue(unitMod, TOTAL_PCT); + + SetMaxPower(power, uint32(value)); +} + +void Player::UpdateAttackPowerAndDamage(bool ranged ) +{ + float val2 = 0.0f; + float level = float(getLevel()); + + UnitMods unitMod = ranged ? UNIT_MOD_ATTACK_POWER_RANGED : UNIT_MOD_ATTACK_POWER; + + uint16 index = UNIT_FIELD_ATTACK_POWER; + uint16 index_mod = UNIT_FIELD_ATTACK_POWER_MODS; + uint16 index_mult = UNIT_FIELD_ATTACK_POWER_MULTIPLIER; + + if(ranged) + { + index = UNIT_FIELD_RANGED_ATTACK_POWER; + index_mod = UNIT_FIELD_RANGED_ATTACK_POWER_MODS; + index_mult = UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER; + + switch(getClass()) + { + case CLASS_HUNTER: val2 = level * 2.0f + GetStat(STAT_AGILITY) - 10.0f; break; + case CLASS_ROGUE: val2 = level + GetStat(STAT_AGILITY) - 10.0f; break; + case CLASS_WARRIOR:val2 = level + GetStat(STAT_AGILITY) - 10.0f; break; + case CLASS_DRUID: + switch(m_form) + { + case FORM_CAT: + case FORM_BEAR: + case FORM_DIREBEAR: + val2 = 0.0f; break; + default: + val2 = GetStat(STAT_AGILITY) - 10.0f; break; + } + break; + default: val2 = GetStat(STAT_AGILITY) - 10.0f; break; + } + } + else + { + switch(getClass()) + { + case CLASS_WARRIOR: val2 = level*3.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; + case CLASS_PALADIN: val2 = level*3.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; + case CLASS_ROGUE: val2 = level*2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f; break; + case CLASS_HUNTER: val2 = level*2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f; break; + case CLASS_SHAMAN: val2 = level*2.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; + case CLASS_DRUID: + { + //Check if Predatory Strikes is skilled + float mLevelMult = 0.0; + switch(m_form) + { + case FORM_CAT: + case FORM_BEAR: + case FORM_DIREBEAR: + case FORM_MOONKIN: + { + Unit::AuraList const& mDummy = GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraList::const_iterator itr = mDummy.begin(); itr != mDummy.end(); ++itr) + { + // Predatory Strikes + if ((*itr)->GetSpellProto()->SpellIconID == 1563) + { + mLevelMult = (*itr)->GetModifier()->m_amount / 100.0f; + break; + } + } + break; + } + } + + switch(m_form) + { + case FORM_CAT: + val2 = getLevel()*(mLevelMult+2.0f) + GetStat(STAT_STRENGTH)*2.0f + GetStat(STAT_AGILITY) - 20.0f; break; + case FORM_BEAR: + case FORM_DIREBEAR: + val2 = getLevel()*(mLevelMult+3.0f) + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; + case FORM_MOONKIN: + val2 = getLevel()*(mLevelMult+1.5f) + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; + default: + val2 = GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; + } + break; + } + case CLASS_MAGE: val2 = GetStat(STAT_STRENGTH) - 10.0f; break; + case CLASS_PRIEST: val2 = GetStat(STAT_STRENGTH) - 10.0f; break; + case CLASS_WARLOCK: val2 = GetStat(STAT_STRENGTH) - 10.0f; break; + } + } + + SetModifierValue(unitMod, BASE_VALUE, val2); + + float base_attPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT); + float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE); + + //add dynamic flat mods + if( ranged && (getClassMask() & CLASSMASK_WAND_USERS)==0) + { + AuraList const& mRAPbyIntellect = GetAurasByType(SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT); + for(AuraList::const_iterator i = mRAPbyIntellect.begin();i != mRAPbyIntellect.end(); ++i) + attPowerMod += int32(GetStat(Stats((*i)->GetModifier()->m_miscvalue)) * (*i)->GetModifier()->m_amount / 100.0f); + } + + float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f; + + SetUInt32Value(index, (uint32)base_attPower); //UNIT_FIELD_(RANGED)_ATTACK_POWER field + SetUInt32Value(index_mod, (uint32)attPowerMod); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS field + SetFloatValue(index_mult, attPowerMultiplier); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field + + //automatically update weapon damage after attack power modification + if(ranged) + { + UpdateDamagePhysical(RANGED_ATTACK); + + Pet *pet = GetPet(); //update pet's AP + if(pet) + pet->UpdateAttackPowerAndDamage(); + } + else + { + UpdateDamagePhysical(BASE_ATTACK); + if(CanDualWield() && haveOffhandWeapon()) //allow update offhand damage only if player knows DualWield Spec and has equipped offhand weapon + UpdateDamagePhysical(OFF_ATTACK); + } +} + +void Player::UpdateShieldBlockValue() +{ + SetUInt32Value(PLAYER_SHIELD_BLOCK, GetShieldBlockValue()); +} + +void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, float& min_damage, float& max_damage) +{ + UnitMods unitMod; + UnitMods attPower; + + switch(attType) + { + case BASE_ATTACK: + default: + unitMod = UNIT_MOD_DAMAGE_MAINHAND; + attPower = UNIT_MOD_ATTACK_POWER; + break; + case OFF_ATTACK: + unitMod = UNIT_MOD_DAMAGE_OFFHAND; + attPower = UNIT_MOD_ATTACK_POWER; + break; + case RANGED_ATTACK: + unitMod = UNIT_MOD_DAMAGE_RANGED; + attPower = UNIT_MOD_ATTACK_POWER_RANGED; + break; + } + + float att_speed = GetAPMultiplier(attType,normalized); + + float base_value = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType)/ 14.0f * att_speed; + float base_pct = GetModifierValue(unitMod, BASE_PCT); + float total_value = GetModifierValue(unitMod, TOTAL_VALUE); + float total_pct = GetModifierValue(unitMod, TOTAL_PCT); + + float weapon_mindamage = GetWeaponDamageRange(attType, MINDAMAGE); + float weapon_maxdamage = GetWeaponDamageRange(attType, MAXDAMAGE); + + if (IsInFeralForm()) //check if player is druid and in cat or bear forms + { + uint32 lvl = getLevel(); + if ( lvl > 60 ) lvl = 60; + + weapon_mindamage = lvl*0.85*att_speed; + weapon_maxdamage = lvl*1.25*att_speed; + } + else if(!IsUseEquipedWeapon(attType==BASE_ATTACK)) //check if player not in form but still can't use weapon (broken/etc) + { + weapon_mindamage = BASE_MINDAMAGE; + weapon_maxdamage = BASE_MAXDAMAGE; + } + else if(attType == RANGED_ATTACK) //add ammo DPS to ranged damage + { + weapon_mindamage += GetAmmoDPS() * att_speed; + weapon_maxdamage += GetAmmoDPS() * att_speed; + } + + min_damage = ((base_value + weapon_mindamage) * base_pct + total_value) * total_pct; + max_damage = ((base_value + weapon_maxdamage) * base_pct + total_value) * total_pct; +} + +void Player::UpdateDamagePhysical(WeaponAttackType attType) +{ + float mindamage; + float maxdamage; + + CalculateMinMaxDamage(attType,false,mindamage,maxdamage); + + switch(attType) + { + case BASE_ATTACK: + default: + SetStatFloatValue(UNIT_FIELD_MINDAMAGE,mindamage); + SetStatFloatValue(UNIT_FIELD_MAXDAMAGE,maxdamage); + break; + case OFF_ATTACK: + SetStatFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE,mindamage); + SetStatFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE,maxdamage); + break; + case RANGED_ATTACK: + SetStatFloatValue(UNIT_FIELD_MINRANGEDDAMAGE,mindamage); + SetStatFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE,maxdamage); + break; + } +} + +void Player::UpdateDefenseBonusesMod() +{ + UpdateBlockPercentage(); + UpdateParryPercentage(); + UpdateDodgePercentage(); +} + +void Player::UpdateBlockPercentage() +{ + // Base value + float value = 5.0f; + // Modify value from defense skill + value += (int32(GetDefenseSkillValue()) - int32(GetMaxSkillValueForLevel())) * 0.04f; + // Increase from SPELL_AURA_MOD_BLOCK_PERCENT aura + value += GetTotalAuraModifier(SPELL_AURA_MOD_BLOCK_PERCENT); + // Increase from rating + value += GetRatingBonusValue(CR_BLOCK); + value = value < 0.0f ? 0.0f : value; + SetStatFloatValue(PLAYER_BLOCK_PERCENTAGE, value); +} + +void Player::UpdateCritPercentage(WeaponAttackType attType) +{ + BaseModGroup modGroup; + uint16 index; + CombatRating cr; + + switch(attType) + { + case OFF_ATTACK: + modGroup = OFFHAND_CRIT_PERCENTAGE; + index = PLAYER_OFFHAND_CRIT_PERCENTAGE; + cr = CR_CRIT_MELEE; + break; + case RANGED_ATTACK: + modGroup = RANGED_CRIT_PERCENTAGE; + index = PLAYER_RANGED_CRIT_PERCENTAGE; + cr = CR_CRIT_RANGED; + break; + case BASE_ATTACK: + default: + modGroup = CRIT_PERCENTAGE; + index = PLAYER_CRIT_PERCENTAGE; + cr = CR_CRIT_MELEE; + break; + } + + float value = GetTotalPercentageModValue(modGroup) + GetRatingBonusValue(cr); + // Modify crit from weapon skill and maximized defense skill of same level victim difference + value += (int32(GetWeaponSkillValue(attType)) - int32(GetMaxSkillValueForLevel())) * 0.04f; + value = value < 0.0f ? 0.0f : value; + SetStatFloatValue(index, value); +} + +void Player::UpdateAllCritPercentages() +{ + float value = GetMeleeCritFromAgility(); + + SetBaseModValue(CRIT_PERCENTAGE, PCT_MOD, value); + SetBaseModValue(OFFHAND_CRIT_PERCENTAGE, PCT_MOD, value); + SetBaseModValue(RANGED_CRIT_PERCENTAGE, PCT_MOD, value); + + UpdateCritPercentage(BASE_ATTACK); + UpdateCritPercentage(OFF_ATTACK); + UpdateCritPercentage(RANGED_ATTACK); +} + +void Player::UpdateParryPercentage() +{ + // Base parry + float value = 5.0f; + // Modify value from defense skill + value += (int32(GetDefenseSkillValue()) - int32(GetMaxSkillValueForLevel())) * 0.04f; + // Parry from SPELL_AURA_MOD_PARRY_PERCENT aura + value += GetTotalAuraModifier(SPELL_AURA_MOD_PARRY_PERCENT); + // Parry from rating + value += GetRatingBonusValue(CR_PARRY); + value = value < 0.0f ? 0.0f : value; + SetStatFloatValue(PLAYER_PARRY_PERCENTAGE, value); +} + +void Player::UpdateDodgePercentage() +{ + // Dodge from agility + float value = GetDodgeFromAgility(); + // Modify value from defense skill + value += (int32(GetDefenseSkillValue()) - int32(GetMaxSkillValueForLevel())) * 0.04f; + // Dodge from SPELL_AURA_MOD_DODGE_PERCENT aura + value += GetTotalAuraModifier(SPELL_AURA_MOD_DODGE_PERCENT); + // Dodge from rating + value += GetRatingBonusValue(CR_DODGE); + value = value < 0.0f ? 0.0f : value; + SetStatFloatValue(PLAYER_DODGE_PERCENTAGE, value); +} + +void Player::UpdateSpellCritChance(uint32 school) +{ + // For normal school set zero crit chance + if(school == SPELL_SCHOOL_NORMAL) + { + SetFloatValue(PLAYER_SPELL_CRIT_PERCENTAGE1, 0.0f); + return; + } + // For others recalculate it from: + float crit = 0.0f; + // Crit from Intellect + crit += GetSpellCritFromIntellect(); + // Increase crit from SPELL_AURA_MOD_SPELL_CRIT_CHANCE + crit += GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_CRIT_CHANCE); + // Increase crit by school from SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL + crit += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL, 1<GetSpellProto()->EquippedItemClass == -1) + expertise += (*itr)->GetModifier()->m_amount; + // item dependent spell + else if(weapon && weapon->IsFitToSpellRequirements((*itr)->GetSpellProto())) + expertise += (*itr)->GetModifier()->m_amount; + } + + if(expertise < 0) + expertise = 0; + + switch(attack) + { + case BASE_ATTACK: SetUInt32Value(PLAYER_EXPERTISE, expertise); break; + case OFF_ATTACK: SetUInt32Value(PLAYER_OFFHAND_EXPERTISE, expertise); break; + default: break; + } +} + +void Player::UpdateManaRegen() +{ + float Intellect = GetStat(STAT_INTELLECT); + // Mana regen from spirit and intellect + float power_regen = sqrt(Intellect) * OCTRegenMPPerSpirit(); + // Apply PCT bonus from SPELL_AURA_MOD_POWER_REGEN_PERCENT aura on spirit base regen + power_regen *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, POWER_MANA); + + // Mana regen from SPELL_AURA_MOD_POWER_REGEN aura + float power_regen_mp5 = GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA) / 5.0f; + + // Get bonus from SPELL_AURA_MOD_MANA_REGEN_FROM_STAT aura + AuraList const& regenAura = GetAurasByType(SPELL_AURA_MOD_MANA_REGEN_FROM_STAT); + for(AuraList::const_iterator i = regenAura.begin();i != regenAura.end(); ++i) + { + Modifier* mod = (*i)->GetModifier(); + power_regen_mp5 += GetStat(Stats(mod->m_miscvalue)) * mod->m_amount / 500.0f; + } + + // Bonus from some dummy auras + AuraList const& mDummyAuras = GetAurasByType(SPELL_AURA_PERIODIC_DUMMY); + for(AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i) + if((*i)->GetId() == 34074) // Aspect of the Viper + { + power_regen_mp5 += (*i)->GetModifier()->m_amount * Intellect / 500.0f; + // Add regen bonus from level in this dummy + power_regen_mp5 += getLevel() * 35 / 100; + } + + // Set regen rate in cast state apply only on spirit based regen + int32 modManaRegenInterrupt = GetTotalAuraModifier(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT); + if (modManaRegenInterrupt > 100) + modManaRegenInterrupt = 100; + SetStatFloatValue(PLAYER_FIELD_MOD_MANA_REGEN_INTERRUPT, power_regen_mp5 + power_regen * modManaRegenInterrupt / 100.0f); + + SetStatFloatValue(PLAYER_FIELD_MOD_MANA_REGEN, power_regen_mp5 + power_regen); +} + +void Player::_ApplyAllStatBonuses() +{ + SetCanModifyStats(false); + + _ApplyAllAuraMods(); + _ApplyAllItemMods(); + + SetCanModifyStats(true); + + UpdateAllStats(); +} + +void Player::_RemoveAllStatBonuses() +{ + SetCanModifyStats(false); + + _RemoveAllItemMods(); + _RemoveAllAuraMods(); + + SetCanModifyStats(true); + + UpdateAllStats(); +} + +/*####################################### +######## ######## +######## MOBS STAT SYSTEM ######## +######## ######## +#######################################*/ + +bool Creature::UpdateStats(Stats /*stat*/) +{ + return true; +} + +bool Creature::UpdateAllStats() +{ + UpdateMaxHealth(); + UpdateAttackPowerAndDamage(); + + for(int i = POWER_MANA; i < MAX_POWERS; ++i) + UpdateMaxPower(Powers(i)); + + for(int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; ++i) + UpdateResistances(i); + + return true; +} + +void Creature::UpdateResistances(uint32 school) +{ + if(school > SPELL_SCHOOL_NORMAL) + { + float value = GetTotalAuraModValue(UnitMods(UNIT_MOD_RESISTANCE_START + school)); + SetResistance(SpellSchools(school), int32(value)); + } + else + UpdateArmor(); +} + +void Creature::UpdateArmor() +{ + float value = GetTotalAuraModValue(UNIT_MOD_ARMOR); + SetArmor(int32(value)); +} + +void Creature::UpdateMaxHealth() +{ + float value = GetTotalAuraModValue(UNIT_MOD_HEALTH); + SetMaxHealth((uint32)value); +} + +void Creature::UpdateMaxPower(Powers power) +{ + UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + power); + + float value = GetTotalAuraModValue(unitMod); + SetMaxPower(power, uint32(value)); +} + +void Creature::UpdateAttackPowerAndDamage(bool ranged) +{ + if(ranged) + return; + + //automatically update weapon damage after attack power modification + UpdateDamagePhysical(BASE_ATTACK); +} + +void Creature::UpdateDamagePhysical(WeaponAttackType attType) +{ + if(attType > BASE_ATTACK) + return; + + UnitMods unitMod = UNIT_MOD_DAMAGE_MAINHAND; + + float att_speed = float(GetAttackTime(BASE_ATTACK))/1000.0f; + + float base_value = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType)/ 14.0f * att_speed; + float base_pct = GetModifierValue(unitMod, BASE_PCT); + float total_value = GetModifierValue(unitMod, TOTAL_VALUE); + float total_pct = GetModifierValue(unitMod, TOTAL_PCT); + + float weapon_mindamage = GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE); + float weapon_maxdamage = GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE); + + float mindamage = ((base_value + weapon_mindamage) * base_pct + total_value) * total_pct ; + float maxdamage = ((base_value + weapon_maxdamage) * base_pct + total_value) * total_pct ; + + SetStatFloatValue(UNIT_FIELD_MINDAMAGE, mindamage); + SetStatFloatValue(UNIT_FIELD_MAXDAMAGE, maxdamage); +} + +/*####################################### +######## ######## +######## PETS STAT SYSTEM ######## +######## ######## +#######################################*/ + +bool Pet::UpdateStats(Stats stat) +{ + if(stat > STAT_SPIRIT) + return false; + + // value = ((base_value * base_pct) + total_value) * total_pct + float value = GetTotalStatValue(stat); + + Unit *owner = GetOwner(); + if ( stat == STAT_STAMINA ) + { + if(owner) + value += float(owner->GetStat(stat)) * 0.3f; + } + //warlock's and mage's pets gain 30% of owner's intellect + else if ( stat == STAT_INTELLECT && getPetType() == SUMMON_PET ) + { + if(owner && (owner->getClass() == CLASS_WARLOCK || owner->getClass() == CLASS_MAGE) ) + value += float(owner->GetStat(stat)) * 0.3f; + } + + SetStat(stat, int32(value)); + + switch(stat) + { + case STAT_STRENGTH: UpdateAttackPowerAndDamage(); break; + case STAT_AGILITY: UpdateArmor(); break; + case STAT_STAMINA: UpdateMaxHealth(); break; + case STAT_INTELLECT: UpdateMaxPower(POWER_MANA); break; + case STAT_SPIRIT: + default: + break; + } + + return true; +} + +bool Pet::UpdateAllStats() +{ + for (int i = STAT_STRENGTH; i < MAX_STATS; i++) + UpdateStats(Stats(i)); + + for(int i = POWER_MANA; i < MAX_POWERS; i++) + UpdateMaxPower(Powers(i)); + + for (int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++) + UpdateResistances(i); + + return true; +} + +void Pet::UpdateResistances(uint32 school) +{ + if(school > SPELL_SCHOOL_NORMAL) + { + float value = GetTotalAuraModValue(UnitMods(UNIT_MOD_RESISTANCE_START + school)); + + Unit *owner = GetOwner(); + // hunter and warlock pets gain 40% of owner's resistance + if(owner && (getPetType() == HUNTER_PET || getPetType() == SUMMON_PET && owner->getClass() == CLASS_WARLOCK)) + value += float(owner->GetResistance(SpellSchools(school))) * 0.4f; + + SetResistance(SpellSchools(school), int32(value)); + } + else + UpdateArmor(); +} + +void Pet::UpdateArmor() +{ + float value = 0.0f; + float bonus_armor = 0.0f; + UnitMods unitMod = UNIT_MOD_ARMOR; + + Unit *owner = GetOwner(); + // hunter and warlock pets gain 35% of owner's armor value + if(owner && (getPetType() == HUNTER_PET || getPetType() == SUMMON_PET && owner->getClass() == CLASS_WARLOCK)) + bonus_armor = 0.35f * float(owner->GetArmor()); + + value = GetModifierValue(unitMod, BASE_VALUE); + value *= GetModifierValue(unitMod, BASE_PCT); + value += GetStat(STAT_AGILITY) * 2.0f; + value += GetModifierValue(unitMod, TOTAL_VALUE) + bonus_armor; + value *= GetModifierValue(unitMod, TOTAL_PCT); + + SetArmor(int32(value)); +} + +void Pet::UpdateMaxHealth() +{ + UnitMods unitMod = UNIT_MOD_HEALTH; + float stamina = GetStat(STAT_STAMINA) - GetCreateStat(STAT_STAMINA); + + float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreateHealth(); + value *= GetModifierValue(unitMod, BASE_PCT); + value += GetModifierValue(unitMod, TOTAL_VALUE) + stamina * 10.0f; + value *= GetModifierValue(unitMod, TOTAL_PCT); + + SetMaxHealth((uint32)value); +} + +void Pet::UpdateMaxPower(Powers power) +{ + UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + power); + float addValue = (power == POWER_MANA) ? GetStat(STAT_INTELLECT) - GetCreateStat(STAT_INTELLECT) : 0.0f; + + float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power); + value *= GetModifierValue(unitMod, BASE_PCT); + value += GetModifierValue(unitMod, TOTAL_VALUE) + addValue * 15.0f; + value *= GetModifierValue(unitMod, TOTAL_PCT); + + SetMaxPower(power, uint32(value)); +} + +void Pet::UpdateAttackPowerAndDamage(bool ranged) +{ + if(ranged) + return; + + float val = 0.0f; + float bonusAP = 0.0f; + UnitMods unitMod = UNIT_MOD_ATTACK_POWER; + + if(GetEntry() == 416) // imp's attack power + val = GetStat(STAT_STRENGTH) - 10.0f; + else + val = 2 * GetStat(STAT_STRENGTH) - 20.0f; + + Unit* owner = GetOwner(); + if( owner && owner->GetTypeId()==TYPEID_PLAYER) + { + if(getPetType() == HUNTER_PET) //hunter pets benefit from owner's attack power + { + bonusAP = owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.22f; + SetBonusDamage( int32(owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.125f)); + } + //demons benefit from warlocks shadow or fire damage + else if(getPetType() == SUMMON_PET && owner->getClass() == CLASS_WARLOCK) + { + int32 fire = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FIRE)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FIRE); + int32 shadow = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_SHADOW)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_SHADOW); + int32 maximum = (fire > shadow) ? fire : shadow; + if(maximum < 0) + maximum = 0; + SetBonusDamage( int32(maximum * 0.15f)); + bonusAP = maximum * 0.57f; + } + //water elementals benefit from mage's frost damage + else if(getPetType() == SUMMON_PET && owner->getClass() == CLASS_MAGE) + { + int32 frost = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FROST)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FROST); + if(frost < 0) + frost = 0; + SetBonusDamage( int32(frost * 0.4f)); + } + } + + SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, val + bonusAP); + + //in BASE_VALUE of UNIT_MOD_ATTACK_POWER for creatures we store data of meleeattackpower field in DB + float base_attPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT); + float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE); + float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f; + + //UNIT_FIELD_(RANGED)_ATTACK_POWER field + SetUInt32Value(UNIT_FIELD_ATTACK_POWER, (uint32)base_attPower); + //UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS field + SetUInt32Value(UNIT_FIELD_ATTACK_POWER_MODS, (uint32)attPowerMod); + //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field + SetFloatValue(UNIT_FIELD_ATTACK_POWER_MULTIPLIER, attPowerMultiplier); + + //automatically update weapon damage after attack power modification + UpdateDamagePhysical(BASE_ATTACK); +} + +void Pet::UpdateDamagePhysical(WeaponAttackType attType) +{ + if(attType > BASE_ATTACK) + return; + + UnitMods unitMod = UNIT_MOD_DAMAGE_MAINHAND; + + float att_speed = float(GetAttackTime(BASE_ATTACK))/1000.0f; + + float base_value = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType)/ 14.0f * att_speed; + float base_pct = GetModifierValue(unitMod, BASE_PCT); + float total_value = GetModifierValue(unitMod, TOTAL_VALUE); + float total_pct = GetModifierValue(unitMod, TOTAL_PCT); + + float weapon_mindamage = GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE); + float weapon_maxdamage = GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE); + + float mindamage = ((base_value + weapon_mindamage) * base_pct + total_value) * total_pct; + float maxdamage = ((base_value + weapon_maxdamage) * base_pct + total_value) * total_pct; + + // Pet's base damage changes depending on happiness + if (getPetType() == HUNTER_PET && attType == BASE_ATTACK) + { + switch(GetHappinessState()) + { + case HAPPY: + // 125% of normal damage + mindamage = mindamage * 1.25; + maxdamage = maxdamage * 1.25; + break; + case CONTENT: + // 100% of normal damage, nothing to modify + break; + case UNHAPPY: + // 75% of normal damage + mindamage = mindamage * 0.75; + maxdamage = maxdamage * 0.75; + break; + } + } + + SetStatFloatValue(UNIT_FIELD_MINDAMAGE, mindamage); + SetStatFloatValue(UNIT_FIELD_MAXDAMAGE, maxdamage); +} diff --git a/src/game/TargetedMovementGenerator.cpp b/src/game/TargetedMovementGenerator.cpp new file mode 100644 index 00000000000..bba7426938d --- /dev/null +++ b/src/game/TargetedMovementGenerator.cpp @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ByteBuffer.h" +#include "TargetedMovementGenerator.h" +#include "Errors.h" +#include "Creature.h" +#include "MapManager.h" +#include "DestinationHolderImp.h" +#include "World.h" + +#define SMALL_ALPHA 0.05f + +#include +/* +struct StackCleaner +{ + Creature &i_creature; + StackCleaner(Creature &creature) : i_creature(creature) {} + void Done(void) { i_creature.StopMoving(); } + ~StackCleaner() + { + i_creature->Clear(); + } +}; +*/ + +template +void +TargetedMovementGenerator::_setTargetLocation(T &owner) +{ + if( !i_target.isValid() || !&owner ) + return; + + if( owner.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED | UNIT_STAT_DISTRACTED) ) + return; + + // prevent redundant micro-movement for pets, other followers. + if(i_offset && i_target->IsWithinDistInMap(&owner,2*i_offset)) + return; + + float x, y, z; + if(!i_offset) + { + // to nearest contact position + i_target->GetContactPoint( &owner, x, y, z ); + } + else + { + // to at i_offset distance from target and i_angle from target facing + i_target->GetClosePoint(x,y,z,owner.GetObjectSize(),i_offset,i_angle); + } + + /* + We MUST not check the distance difference and avoid setting the new location for smaller distances. + By that we risk having far too many GetContactPoint() calls freezing the whole system. + In TargetedMovementGenerator::Update() we check the distance to the target and at + some range we calculate a new position. The calculation takes some processor cycles due to vmaps. + If the distance to the target it too large to ignore, + but the distance to the new contact point is short enough to be ignored, + we will calculate a new contact point each update loop, but will never move to it. + The system will freeze. + ralf + + //We don't update Mob Movement, if the difference between New destination and last destination is < BothObjectSize + float bothObjectSize = i_target->GetObjectSize() + owner.GetObjectSize() + CONTACT_DISTANCE; + if( i_destinationHolder.HasDestination() && i_destinationHolder.GetDestinationDiff(x,y,z) < bothObjectSize ) + return; + */ + Traveller traveller(owner); + i_destinationHolder.SetDestination(traveller, x, y, z); + owner.addUnitState(UNIT_STAT_CHASE); +} + +template +void +TargetedMovementGenerator::Initialize(T &owner) +{ + if(!&owner) + return; + owner.RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + _setTargetLocation(owner); +} + +template +void +TargetedMovementGenerator::Finalize(T &owner) +{ + owner.clearUnitState(UNIT_STAT_CHASE); +} + +template +void +TargetedMovementGenerator::Reset(T &owner) +{ + Initialize(owner); +} + +template +bool +TargetedMovementGenerator::Update(T &owner, const uint32 & time_diff) +{ + if(!i_target.isValid()) + return false; + + if( !&owner || !owner.isAlive()) + return true; + + if( owner.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED | UNIT_STAT_FLEEING | UNIT_STAT_DISTRACTED) ) + return true; + + // prevent movement while casting spells with cast time or channel time + if ( owner.IsNonMeleeSpellCasted(false, false, true)) + { + if (!owner.IsStopped()) + owner.StopMoving(); + return true; + } + + // prevent crash after creature killed pet + if (!owner.hasUnitState(UNIT_STAT_FOLLOW) && owner.getVictim() != i_target.getTarget()) + return true; + + Traveller traveller(owner); + + if( !i_destinationHolder.HasDestination() ) + _setTargetLocation(owner); + if( owner.IsStopped() && !i_destinationHolder.HasArrived() ) + { + owner.addUnitState(UNIT_STAT_CHASE); + i_destinationHolder.StartTravel(traveller); + return true; + } + + if (i_destinationHolder.UpdateTraveller(traveller, time_diff, false)) + { + // put targeted movement generators on a higher priority + if (owner.GetObjectSize()) + i_destinationHolder.ResetUpdate(50); + + float dist = i_target->GetObjectSize() + owner.GetObjectSize() + sWorld.getRate(RATE_TARGET_POS_RECALCULATION_RANGE); + + //More distance let have better performance, less distance let have more sensitive reaction at target move. + + // try to counter precision differences + if( i_destinationHolder.GetDistance2dFromDestSq(*i_target.getTarget()) >= dist * dist) + { + owner.SetInFront(i_target.getTarget()); // Set new Angle For Map:: + _setTargetLocation(owner); //Calculate New Dest and Send data To Player + } + // Update the Angle of the target only for Map::, no need to send packet for player + else if ( !i_angle && !owner.HasInArc( 0.01f, i_target.getTarget() ) ) + owner.SetInFront(i_target.getTarget()); + + if(( owner.IsStopped() && !i_destinationHolder.HasArrived() ) || i_recalculateTravel ) + { + i_recalculateTravel = false; + //Angle update will take place into owner.StopMoving() + owner.SetInFront(i_target.getTarget()); + + owner.StopMoving(); + if(owner.canReachWithAttack(i_target.getTarget()) && !owner.hasUnitState(UNIT_STAT_FOLLOW)) + owner.Attack(i_target.getTarget(),true); + } + } + return true; +} + +template +Unit* +TargetedMovementGenerator::GetTarget() const +{ + return i_target.getTarget(); +} + +template void TargetedMovementGenerator::_setTargetLocation(Player &); +template void TargetedMovementGenerator::_setTargetLocation(Creature &); +template void TargetedMovementGenerator::Initialize(Player &); +template void TargetedMovementGenerator::Initialize(Creature &); +template void TargetedMovementGenerator::Finalize(Player &); +template void TargetedMovementGenerator::Finalize(Creature &); +template void TargetedMovementGenerator::Reset(Player &); +template void TargetedMovementGenerator::Reset(Creature &); +template bool TargetedMovementGenerator::Update(Player &, const uint32 &); +template bool TargetedMovementGenerator::Update(Creature &, const uint32 &); +template Unit* TargetedMovementGenerator::GetTarget() const; +template Unit* TargetedMovementGenerator::GetTarget() const; diff --git a/src/game/TargetedMovementGenerator.h b/src/game/TargetedMovementGenerator.h new file mode 100644 index 00000000000..725f07224ba --- /dev/null +++ b/src/game/TargetedMovementGenerator.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_TARGETEDMOVEMENTGENERATOR_H +#define MANGOS_TARGETEDMOVEMENTGENERATOR_H + +#include "MovementGenerator.h" +#include "DestinationHolder.h" +#include "Traveller.h" +#include "FollowerReference.h" + +class MANGOS_DLL_SPEC TargetedMovementGeneratorBase +{ + public: + TargetedMovementGeneratorBase(Unit &target) { i_target.link(&target, this); } + void stopFollowing() { } + protected: + FollowerReference i_target; +}; + +template +class MANGOS_DLL_SPEC TargetedMovementGenerator +: public MovementGeneratorMedium< T, TargetedMovementGenerator >, public TargetedMovementGeneratorBase +{ + public: + + TargetedMovementGenerator(Unit &target) + : TargetedMovementGeneratorBase(target), i_offset(0), i_angle(0), i_recalculateTravel(false) {} + TargetedMovementGenerator(Unit &target, float offset, float angle) + : TargetedMovementGeneratorBase(target), i_offset(offset), i_angle(angle), i_recalculateTravel(false) {} + ~TargetedMovementGenerator() {} + + void Initialize(T &); + void Finalize(T &); + void Reset(T &); + bool Update(T &, const uint32 &); + MovementGeneratorType GetMovementGeneratorType() { return TARGETED_MOTION_TYPE; } + + Unit* GetTarget() const; + + bool GetDestination(float &x, float &y, float &z) const + { + if(!i_destinationHolder.HasDestination()) return false; + i_destinationHolder.GetDestination(x,y,z); + return true; + } + + void unitSpeedChanged() { i_recalculateTravel=true; } + private: + + void _setTargetLocation(T &); + + float i_offset; + float i_angle; + DestinationHolder< Traveller > i_destinationHolder; + bool i_recalculateTravel; +}; +#endif diff --git a/src/game/TaxiHandler.cpp b/src/game/TaxiHandler.cpp new file mode 100644 index 00000000000..e804bec8463 --- /dev/null +++ b/src/game/TaxiHandler.cpp @@ -0,0 +1,278 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Opcodes.h" +#include "Log.h" +#include "World.h" +#include "ObjectMgr.h" +#include "Player.h" +#include "UpdateMask.h" +#include "Path.h" +#include "WaypointMovementGenerator.h" +#include "DestinationHolderImp.h" + +#include + +void WorldSession::HandleTaxiNodeStatusQueryOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8); + + sLog.outDebug( "WORLD: Received CMSG_TAXINODE_STATUS_QUERY" ); + + uint64 guid; + + recv_data >> guid; + SendTaxiStatus( guid ); +} + +void WorldSession::SendTaxiStatus( uint64 guid ) +{ + // cheating checks + Creature *unit = ObjectAccessor::GetCreature(*_player, guid); + if (!unit) + { + sLog.outDebug( "WorldSession::SendTaxiStatus - Unit (GUID: %u) not found.", uint32(GUID_LOPART(guid)) ); + return; + } + + uint32 curloc = objmgr.GetNearestTaxiNode(unit->GetPositionX(),unit->GetPositionY(),unit->GetPositionZ(),unit->GetMapId()); + + // not found nearest + if(curloc == 0) + return; + + sLog.outDebug( "WORLD: current location %u ",curloc); + + WorldPacket data( SMSG_TAXINODE_STATUS, 9 ); + data << guid; + data << uint8( GetPlayer( )->m_taxi.IsTaximaskNodeKnown(curloc) ? 1 : 0 ); + SendPacket( &data ); + sLog.outDebug( "WORLD: Sent SMSG_TAXINODE_STATUS" ); +} + +void WorldSession::HandleTaxiQueryAvailableNodesOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8); + + sLog.outDebug( "WORLD: Received CMSG_TAXIQUERYAVAILABLENODES" ); + + uint64 guid; + recv_data >> guid; + + // cheating checks + Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_FLIGHTMASTER); + if (!unit) + { + sLog.outDebug( "WORLD: HandleTaxiQueryAvailableNodesOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); + return; + } + + // remove fake death + if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + // unknown taxi node case + if( SendLearnNewTaxiNode(unit) ) + return; + + // known taxi node case + SendTaxiMenu( unit ); +} + +void WorldSession::SendTaxiMenu( Creature* unit ) +{ + // find current node + uint32 curloc = objmgr.GetNearestTaxiNode(unit->GetPositionX(),unit->GetPositionY(),unit->GetPositionZ(),unit->GetMapId()); + + if ( curloc == 0 ) + return; + + sLog.outDebug( "WORLD: CMSG_TAXINODE_STATUS_QUERY %u ",curloc); + + WorldPacket data( SMSG_SHOWTAXINODES, (4+8+4+8*4) ); + data << uint32( 1 ); + data << uint64( unit->GetGUID() ); + data << uint32( curloc ); + GetPlayer()->m_taxi.AppendTaximaskTo(data,GetPlayer()->isTaxiCheater()); + SendPacket( &data ); + + sLog.outDebug( "WORLD: Sent SMSG_SHOWTAXINODES" ); +} + +void WorldSession::SendDoFlight( uint16 MountId, uint32 path, uint32 pathNode ) +{ + // remove fake death + if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + while(GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType()==FLIGHT_MOTION_TYPE) + GetPlayer()->GetMotionMaster()->MovementExpired(false); + + GetPlayer()->Mount( MountId ); + GetPlayer()->GetMotionMaster()->MoveTaxiFlight(path,pathNode); +} + +bool WorldSession::SendLearnNewTaxiNode( Creature* unit ) +{ + // find current node + uint32 curloc = objmgr.GetNearestTaxiNode(unit->GetPositionX(),unit->GetPositionY(),unit->GetPositionZ(),unit->GetMapId()); + + if ( curloc == 0 ) + return true; // `true` send to avoid WorldSession::SendTaxiMenu call with one more curlock seartch with same false result. + + if( GetPlayer()->m_taxi.SetTaximaskNode(curloc) ) + { + WorldPacket msg(SMSG_NEW_TAXI_PATH, 0); + SendPacket( &msg ); + + WorldPacket update( SMSG_TAXINODE_STATUS, 9 ); + update << uint64( unit->GetGUID() ); + update << uint8( 1 ); + SendPacket( &update ); + + return true; + } + else + return false; +} + +void WorldSession::HandleActivateTaxiFarOpcode ( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+4+4); + + sLog.outDebug( "WORLD: Received CMSG_ACTIVATETAXIEXPRESS" ); + + uint64 guid; + uint32 node_count, _totalcost; + + recv_data >> guid >> _totalcost >> node_count; + + Creature *npc = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_FLIGHTMASTER); + if (!npc) + { + sLog.outDebug( "WORLD: HandleActivateTaxiFarOpcode - Unit (GUID: %u) not found or you can't interact with it.", uint32(GUID_LOPART(guid)) ); + return; + } + // recheck + CHECK_PACKET_SIZE(recv_data,8+4+4+node_count*4); + + std::vector nodes; + + for(uint32 i = 0; i < node_count; ++i) + { + uint32 node; + recv_data >> node; + nodes.push_back(node); + } + + if(nodes.empty()) + return; + + sLog.outDebug( "WORLD: Received CMSG_ACTIVATETAXIEXPRESS from %d to %d" ,nodes.front(),nodes.back()); + + GetPlayer()->ActivateTaxiPathTo(nodes, 0, npc); +} + +void WorldSession::HandleTaxiNextDestinationOpcode(WorldPacket& /*recv_data*/) +{ + sLog.outDebug( "WORLD: Received CMSG_MOVE_SPLINE_DONE" ); + + // in taxi flight packet received in 2 case: + // 1) end taxi path in far (multi-node) flight + // 2) switch from one map to other in case multim-map taxi path + // we need proccess only (1) + uint32 curDest = GetPlayer()->m_taxi.GetTaxiDestination(); + if(!curDest) + return; + + TaxiNodesEntry const* curDestNode = sTaxiNodesStore.LookupEntry(curDest); + + // far teleport case + if(curDestNode && curDestNode->map_id != GetPlayer()->GetMapId()) + { + if(GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType()==FLIGHT_MOTION_TYPE) + { + // short preparations to continue flight + FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top()); + + flight->SetCurrentNodeAfterTeleport(); + Path::PathNode const& node = flight->GetPath()[flight->GetCurrentNode()]; + flight->SkipCurrentNode(); + + GetPlayer()->TeleportTo(curDestNode->map_id,node.x,node.y,node.z,GetPlayer()->GetOrientation()); + } + return; + } + + uint32 destinationnode = GetPlayer()->m_taxi.NextTaxiDestination(); + if ( destinationnode > 0 ) // if more destinations to go + { + // current source node for next destination + uint32 sourcenode = GetPlayer()->m_taxi.GetTaxiSource(); + + // Add to taximask middle hubs in taxicheat mode (to prevent having player with disabled taxicheat and not having back flight path) + if (GetPlayer()->isTaxiCheater()) + { + if(GetPlayer()->m_taxi.SetTaximaskNode(sourcenode)) + { + WorldPacket data(SMSG_NEW_TAXI_PATH, 0); + _player->GetSession()->SendPacket( &data ); + } + } + + sLog.outDebug( "WORLD: Taxi has to go from %u to %u", sourcenode, destinationnode ); + + uint16 MountId = objmgr.GetTaxiMount(sourcenode, GetPlayer()->GetTeam()); + + uint32 path, cost; + objmgr.GetTaxiPath( sourcenode, destinationnode, path, cost); + + if(path && MountId) + SendDoFlight( MountId, path, 1 ); // skip start fly node + else + GetPlayer()->m_taxi.ClearTaxiDestinations(); // clear problematic path and next + } + else + GetPlayer()->m_taxi.ClearTaxiDestinations(); // not destinations, clear source node +} + +void WorldSession::HandleActivateTaxiOpcode( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data,8+4+4); + + sLog.outDebug( "WORLD: Received CMSG_ACTIVATETAXI" ); + + uint64 guid; + std::vector nodes; + nodes.resize(2); + + recv_data >> guid >> nodes[0] >> nodes[1]; + sLog.outDebug( "WORLD: Received CMSG_ACTIVATETAXI from %d to %d" ,nodes[0],nodes[1]); + Creature *npc = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_FLIGHTMASTER); + if (!npc) + { + sLog.outDebug( "WORLD: HandleActivateTaxiOpcode - Unit (GUID: %u) not found or you can't interact with it.", uint32(GUID_LOPART(guid)) ); + return; + } + + GetPlayer()->ActivateTaxiPathTo(nodes, 0, npc); +} diff --git a/src/game/TemporarySummon.cpp b/src/game/TemporarySummon.cpp new file mode 100644 index 00000000000..130c4a7904a --- /dev/null +++ b/src/game/TemporarySummon.cpp @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "TemporarySummon.h" +#include "WorldPacket.h" +#include "MapManager.h" +#include "Log.h" +#include "ObjectAccessor.h" +#include "CreatureAI.h" + +TemporarySummon::TemporarySummon( uint64 summoner ) : +Creature(), m_type(TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN), m_timer(0), m_lifetime(0), m_summoner(summoner) +{ +} + +void TemporarySummon::Update( uint32 diff ) +{ + switch(m_type) + { + case TEMPSUMMON_MANUAL_DESPAWN: + break; + case TEMPSUMMON_TIMED_DESPAWN: + { + if (m_timer <= diff) + { + UnSummon(); + return; + } + + m_timer -= diff; + break; + } + case TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT: + { + if (!isInCombat()) + { + if (m_timer <= diff) + { + UnSummon(); + return; + } + + m_timer -= diff; + } + else if (m_timer != m_lifetime) + m_timer = m_lifetime; + + break; + } + + case TEMPSUMMON_CORPSE_TIMED_DESPAWN: + { + if ( m_deathState == CORPSE) + { + if (m_timer <= diff) + { + UnSummon(); + return; + } + + m_timer -= diff; + } + break; + } + case TEMPSUMMON_CORPSE_DESPAWN: + { + // if m_deathState is DEAD, CORPSE was skipped + if ( m_deathState == CORPSE || m_deathState == DEAD) + { + UnSummon(); + return; + } + + break; + } + case TEMPSUMMON_DEAD_DESPAWN: + { + if ( m_deathState == DEAD ) + { + UnSummon(); + return; + } + break; + } + case TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN: + { + // if m_deathState is DEAD, CORPSE was skipped + if ( m_deathState == CORPSE || m_deathState == DEAD) + { + UnSummon(); + return; + } + + if (!isInCombat()) + { + if (m_timer <= diff) + { + UnSummon(); + return; + } + else + m_timer -= diff; + } + else if (m_timer != m_lifetime) + m_timer = m_lifetime; + break; + } + case TEMPSUMMON_TIMED_OR_DEAD_DESPAWN: + { + // if m_deathState is DEAD, CORPSE was skipped + if (m_deathState == DEAD) + { + UnSummon(); + return; + } + + if (!isInCombat() && isAlive() ) + { + if (m_timer <= diff) + { + UnSummon(); + return; + } + else + m_timer -= diff; + } + else if (m_timer != m_lifetime) + m_timer = m_lifetime; + break; + } + default: + UnSummon(); + sLog.outError("Temporary summoned creature (entry: %u) have unknown type %u of ",GetEntry(),m_type); + break; + } + + Creature::Update( diff ); +} + +void TemporarySummon::Summon(TempSummonType type, uint32 lifetime) +{ + m_type = type; + m_timer = lifetime; + m_lifetime = lifetime; + + MapManager::Instance().GetMap(GetMapId(), this)->Add((Creature*)this); + + AIM_Initialize(); +} + +void TemporarySummon::UnSummon() +{ + CombatStop(); + + CleanupsBeforeDelete(); + AddObjectToRemoveList(); + + Unit* sum = m_summoner ? ObjectAccessor::GetUnit(*this, m_summoner) : NULL; + if (sum && sum->GetTypeId() == TYPEID_UNIT && ((Creature*)sum)->AI()) + { + ((Creature*)sum)->AI()->SummonedCreatureDespawn(this); + } +} + +void TemporarySummon::SaveToDB() +{ +} diff --git a/src/game/TemporarySummon.h b/src/game/TemporarySummon.h new file mode 100644 index 00000000000..8007b853938 --- /dev/null +++ b/src/game/TemporarySummon.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOSSERVER_TEMPSUMMON_H +#define MANGOSSERVER_TEMPSUMMON_H + +#include "Creature.h" +#include "ObjectAccessor.h" + +class TemporarySummon : public Creature +{ + public: + explicit TemporarySummon(uint64 summoner = 0); + virtual ~TemporarySummon(){}; + void Update(uint32 time); + void Summon(TempSummonType type, uint32 lifetime); + void UnSummon(); + void SaveToDB(); + Unit* GetSummoner() const { return m_summoner ? ObjectAccessor::GetUnit(*this, m_summoner) : NULL; } + private: + TempSummonType m_type; + uint32 m_timer; + uint32 m_lifetime; + uint64 m_summoner; +}; +#endif diff --git a/src/game/ThreatManager.cpp b/src/game/ThreatManager.cpp new file mode 100644 index 00000000000..b9fd7a44f87 --- /dev/null +++ b/src/game/ThreatManager.cpp @@ -0,0 +1,472 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ThreatManager.h" +#include "Unit.h" +#include "Creature.h" +#include "CreatureAI.h" +#include "Map.h" +#include "MapManager.h" +#include "Player.h" +#include "ObjectAccessor.h" +#include "UnitEvents.h" + +//============================================================== +//================= ThreatCalcHelper =========================== +//============================================================== + +// The pHatingUnit is not used yet +float ThreatCalcHelper::calcThreat(Unit* pHatedUnit, Unit* pHatingUnit, float pThreat, SpellSchoolMask schoolMask, SpellEntry const *pThreatSpell) +{ + if(pThreatSpell) + { + if( Player* modOwner = pHatingUnit->GetSpellModOwner() ) + modOwner->ApplySpellMod(pThreatSpell->Id, SPELLMOD_THREAT, pThreat); + } + + float threat = pHatedUnit->ApplyTotalThreatModifier(pThreat, schoolMask); + return threat; +} + +//============================================================ +//================= HostilReference ========================== +//============================================================ + +HostilReference::HostilReference(Unit* pUnit, ThreatManager *pThreatManager, float pThreat) +{ + iThreat = pThreat; + iTempThreatModifyer = 0.0f; + link(pUnit, pThreatManager); + iUnitGuid = pUnit->GetGUID(); + iOnline = true; + iAccessible = true; +} + +//============================================================ +// Tell our refTo (target) object that we have a link +void HostilReference::targetObjectBuildLink() +{ + getTarget()->addHatedBy(this); +} + +//============================================================ +// Tell our refTo (taget) object, that the link is cut +void HostilReference::targetObjectDestroyLink() +{ + getTarget()->removeHatedBy(this); +} + +//============================================================ +// Tell our refFrom (source) object, that the link is cut (Target destroyed) + +void HostilReference::sourceObjectDestroyLink() +{ + setOnlineOfflineState(false); +} + +//============================================================ +// Inform the source, that the status of the reference changed + +void HostilReference::fireStatusChanged(const ThreatRefStatusChangeEvent& pThreatRefStatusChangeEvent) +{ + if(getSource()) + getSource()->processThreatEvent(&pThreatRefStatusChangeEvent); +} + +//============================================================ + +void HostilReference::addThreat(float pMod) +{ + iThreat += pMod; + // the threat is changed. Source and target unit have to be availabe + // if the link was cut before relink it again + if(!isOnline()) + updateOnlineStatus(); + if(pMod != 0.0f) + fireStatusChanged(ThreatRefStatusChangeEvent(UEV_THREAT_REF_THREAT_CHANGE, this, pMod)); + if(isValid() && pMod >= 0) + { + Unit* victim_owner = getTarget()->GetOwner(); + if(victim_owner && victim_owner->isAlive()) + getSource()->addThreat(victim_owner, 0.0f); // create a threat to the owner of a pet, if the pet attacks + } +} + +//============================================================ +// check, if source can reach target and set the status + +void HostilReference::updateOnlineStatus() +{ + bool online = false; + bool accessible = false; + + if(!isValid()) + { + Unit* target = ObjectAccessor::GetUnit(*getSourceUnit(), getUnitGuid()); + if(target) + link(target, getSource()); + } + // only check for online status if + // ref is valid + // target is no player or not gamemaster + // target is not in flight + if(isValid() && + ((getTarget()->GetTypeId() != TYPEID_PLAYER || !((Player*)getTarget())->isGameMaster()) || + !getTarget()->hasUnitState(UNIT_STAT_IN_FLIGHT))) + { + Creature* creature = (Creature* ) getSourceUnit(); + online = getTarget()->isInAccessablePlaceFor(creature); + if(!online) + { + if(creature->AI()->canReachByRangeAttack(getTarget())) + online = true; // not accessable but stays online + } + else + accessible = true; + + } + setAccessibleState(accessible); + setOnlineOfflineState(online); +} + +//============================================================ +// set the status and fire the event on status change + +void HostilReference::setOnlineOfflineState(bool pIsOnline) +{ + if(iOnline != pIsOnline) + { + iOnline = pIsOnline; + if(!iOnline) + setAccessibleState(false); // if not online that not accessable as well + fireStatusChanged(ThreatRefStatusChangeEvent(UEV_THREAT_REF_ONLINE_STATUS, this)); + } +} + +//============================================================ + +void HostilReference::setAccessibleState(bool pIsAccessible) +{ + if(iAccessible != pIsAccessible) + { + iAccessible = pIsAccessible; + fireStatusChanged(ThreatRefStatusChangeEvent(UEV_THREAT_REF_ASSECCIBLE_STATUS, this)); + } +} + +//============================================================ +// prepare the reference for deleting +// this is called be the target + +void HostilReference::removeReference() +{ + invalidate(); + fireStatusChanged(ThreatRefStatusChangeEvent(UEV_THREAT_REF_REMOVE_FROM_LIST, this)); +} + +//============================================================ + +Unit* HostilReference::getSourceUnit() +{ + return (getSource()->getOwner()); +} + +//============================================================ +//================ ThreatContainer =========================== +//============================================================ + +void ThreatContainer::clearReferences() +{ + for(std::list::iterator i = iThreatList.begin(); i != iThreatList.end(); i++) + { + (*i)->unlink(); + delete (*i); + } + iThreatList.clear(); +} + +//============================================================ +// Return the HostilReference of NULL, if not found +HostilReference* ThreatContainer::getReferenceByTarget(Unit* pVictim) +{ + HostilReference* result = NULL; + uint64 guid = pVictim->GetGUID(); + for(std::list::iterator i = iThreatList.begin(); i != iThreatList.end(); i++) + { + if((*i)->getUnitGuid() == guid) + { + result = (*i); + break; + } + } + + return result; +} + +//============================================================ +// Add the threat, if we find the reference + +HostilReference* ThreatContainer::addThreat(Unit* pVictim, float pThreat) +{ + HostilReference* ref = getReferenceByTarget(pVictim); + if(ref) + ref->addThreat(pThreat); + return ref; +} + +//============================================================ + +void ThreatContainer::modifyThreatPercent(Unit *pVictim, int32 pPercent) +{ + if(HostilReference* ref = getReferenceByTarget(pVictim)) + ref->addThreatPercent(pPercent); +} + +//============================================================ + +bool HostilReferenceSortPredicate(const HostilReference* lhs, const HostilReference* rhs) +{ + // std::list::sort ordering predicate must be: (Pred(x,y)&&Pred(y,x))==false + return lhs->getThreat() > rhs->getThreat(); // reverse sorting +} + +//============================================================ +// Check if the list is dirty and sort if necessary + +void ThreatContainer::update() +{ + if(iDirty && iThreatList.size() >1) + { + iThreatList.sort(HostilReferenceSortPredicate); + } + iDirty = false; +} + +//============================================================ +// return the next best victim +// could be the current victim + +HostilReference* ThreatContainer::selectNextVictim(Creature* pAttacker, HostilReference* pCurrentVictim) +{ + HostilReference* currentRef = NULL; + bool found = false; + for(std::list::iterator iter = iThreatList.begin(); iter != iThreatList.end() && !found; ++iter) + { + currentRef = (*iter); + + Unit* target = currentRef->getTarget(); + assert(target); // if the ref has status online the target must be there ! + + if(!pAttacker->IsOutOfThreatArea(target)) // skip non attackable currently targets + { + if(pCurrentVictim) // select 1.3/1.1 better target in comparison current target + { + // list sorted and and we check current target, then this is best case + if(pCurrentVictim == currentRef || currentRef->getThreat() <= 1.1f * pCurrentVictim->getThreat() ) + { + currentRef = pCurrentVictim; // for second case + found = true; + break; + } + + if( currentRef->getThreat() > 1.3f * pCurrentVictim->getThreat() || + currentRef->getThreat() > 1.1f * pCurrentVictim->getThreat() && pAttacker->IsWithinDistInMap(target, ATTACK_DISTANCE) ) + { //implement 110% threat rule for targets in melee range + found = true; //and 130% rule for targets in ranged distances + break; //for selecting alive targets + } + } + else // select any + { + found = true; + break; + } + } + } + if(!found) + currentRef = NULL; + + return currentRef; +} + +//============================================================ +//=================== ThreatManager ========================== +//============================================================ + +ThreatManager::ThreatManager(Unit* owner) : iCurrentVictim(NULL), iOwner(owner) +{ +} + +//============================================================ + +void ThreatManager::clearReferences() +{ + iThreatContainer.clearReferences(); + iThreatOfflineContainer.clearReferences(); + iCurrentVictim = NULL; +} + +//============================================================ + +void ThreatManager::addThreat(Unit* pVictim, float pThreat, SpellSchoolMask schoolMask, SpellEntry const *pThreatSpell) +{ + //function deals with adding threat and adding players and pets into ThreatList + //mobs, NPCs, guards have ThreatList and HateOfflineList + //players and pets have only InHateListOf + //HateOfflineList is used co contain unattackable victims (in-flight, in-water, GM etc.) + + if (pVictim == getOwner()) // only for same creatures :) + return; + + if(!pVictim || (pVictim->GetTypeId() == TYPEID_PLAYER && ((Player*)pVictim)->isGameMaster()) ) + return; + + assert(getOwner()->GetTypeId()== TYPEID_UNIT); + + float threat = ThreatCalcHelper::calcThreat(pVictim, iOwner, pThreat, schoolMask, pThreatSpell); + + HostilReference* ref = iThreatContainer.addThreat(pVictim, threat); + // Ref is not in the online refs, search the offline refs next + if(!ref) + ref = iThreatOfflineContainer.addThreat(pVictim, threat); + + if(!ref) // there was no ref => create a new one + { + // threat has to be 0 here + HostilReference* hostilReference = new HostilReference(pVictim, this, 0); + iThreatContainer.addReference(hostilReference); + hostilReference->addThreat(threat); // now we add the real threat + if(pVictim->GetTypeId() == TYPEID_PLAYER && ((Player*)pVictim)->isGameMaster()) + hostilReference->setOnlineOfflineState(false); // GM is always offline + } +} + +//============================================================ + +void ThreatManager::modifyThreatPercent(Unit *pVictim, int32 pPercent) +{ + iThreatContainer.modifyThreatPercent(pVictim, pPercent); +} + +//============================================================ + +Unit* ThreatManager::getHostilTarget() +{ + iThreatContainer.update(); + HostilReference* nextVictim = iThreatContainer.selectNextVictim((Creature*) getOwner(), getCurrentVictim()); + setCurrentVictim(nextVictim); + return getCurrentVictim() != NULL ? getCurrentVictim()->getTarget() : NULL; +} + +//============================================================ + +float ThreatManager::getThreat(Unit *pVictim, bool pAlsoSearchOfflineList) +{ + float threat = 0.0f; + HostilReference* ref = iThreatContainer.getReferenceByTarget(pVictim); + if(!ref && pAlsoSearchOfflineList) + ref = iThreatOfflineContainer.getReferenceByTarget(pVictim); + if(ref) + threat = ref->getThreat(); + return threat; +} + +//============================================================ + +void ThreatManager::tauntApply(Unit* pTaunter) +{ + HostilReference* ref = iThreatContainer.getReferenceByTarget(pTaunter); + if(getCurrentVictim() && ref && (ref->getThreat() < getCurrentVictim()->getThreat())) + { + if(ref->getTempThreatModifyer() == 0.0f) + // Ok, temp threat is unused + ref->setTempThreat(getCurrentVictim()->getThreat()); + } +} + +//============================================================ + +void ThreatManager::tauntFadeOut(Unit *pTaunter) +{ + HostilReference* ref = iThreatContainer.getReferenceByTarget(pTaunter); + if(ref) + ref->resetTempThreat(); +} + +//============================================================ + +void ThreatManager::setCurrentVictim(HostilReference* pHostilReference) +{ + iCurrentVictim = pHostilReference; +} + +//============================================================ +// The hated unit is gone, dead or deleted +// return true, if the event is consumed + +bool ThreatManager::processThreatEvent(const UnitBaseEvent* pUnitBaseEvent) +{ + bool consumed = false; + + ThreatRefStatusChangeEvent* threatRefStatusChangeEvent; + HostilReference* hostilReference; + + threatRefStatusChangeEvent = (ThreatRefStatusChangeEvent*) pUnitBaseEvent; + threatRefStatusChangeEvent->setThreatManager(this); // now we can set the threat manager + hostilReference = threatRefStatusChangeEvent->getReference(); + + switch(pUnitBaseEvent->getType()) + { + case UEV_THREAT_REF_THREAT_CHANGE: + if((getCurrentVictim() == hostilReference && threatRefStatusChangeEvent->getFValue()<0.0f) || + (getCurrentVictim() != hostilReference && threatRefStatusChangeEvent->getFValue()>0.0f)) + setDirty(true); // the order in the threat list might have changed + break; + case UEV_THREAT_REF_ONLINE_STATUS: + if(!hostilReference->isOnline()) + { + if (hostilReference == getCurrentVictim()) + { + setCurrentVictim(NULL); + setDirty(true); + } + iThreatContainer.remove(hostilReference); + iThreatOfflineContainer.addReference(hostilReference); + } + else + { + if(getCurrentVictim() && hostilReference->getThreat() > (1.1f * getCurrentVictim()->getThreat())) + setDirty(true); + iThreatContainer.addReference(hostilReference); + iThreatOfflineContainer.remove(hostilReference); + } + break; + case UEV_THREAT_REF_REMOVE_FROM_LIST: + if (hostilReference == getCurrentVictim()) + { + setCurrentVictim(NULL); + setDirty(true); + } + if(hostilReference->isOnline()) + iThreatContainer.remove(hostilReference); + else + iThreatOfflineContainer.remove(hostilReference); + break; + } + return consumed; +} diff --git a/src/game/ThreatManager.h b/src/game/ThreatManager.h new file mode 100644 index 00000000000..ab0270645f7 --- /dev/null +++ b/src/game/ThreatManager.h @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _THREATMANAGER +#define _THREATMANAGER + +#include "Common.h" +#include "SharedDefines.h" +#include "Utilities/LinkedReference/Reference.h" +#include "UnitEvents.h" + +#include + +//============================================================== + +class Unit; +class Creature; +class ThreatManager; +struct SpellEntry; + +//============================================================== +// Class to calculate the real threat based + +class ThreatCalcHelper +{ + public: + static float calcThreat(Unit* pHatedUnit, Unit* pHatingUnit, float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellEntry const *threatSpell = NULL); +}; + +//============================================================== + +class MANGOS_DLL_SPEC HostilReference : public Reference +{ + private: + float iThreat; + float iTempThreatModifyer; // used for taunt + uint64 iUnitGuid; + bool iOnline; + bool iAccessible; + private: + // Inform the source, that the status of that reference was changed + void fireStatusChanged(const ThreatRefStatusChangeEvent& pThreatRefStatusChangeEvent); + + Unit* getSourceUnit(); + public: + HostilReference(Unit* pUnit, ThreatManager *pThreatManager, float pThreat); + + //================================================= + void addThreat(float pMod); + + void setThreat(float pThreat) { addThreat(pThreat - getThreat()); } + + void addThreatPercent(int32 pPercent) { float tmpThreat = iThreat; tmpThreat = tmpThreat * (pPercent+100) / 100; addThreat(tmpThreat-iThreat); } + + float getThreat() const { return iThreat; } + + bool isOnline() const { return iOnline; } + + // The Unit might be in water and the creature can not enter the water, but has range attack + // in this case online = true, but accessable = false + bool isAccessable() const { return iAccessible; } + + // used for temporary setting a threat and reducting it later again. + // the threat modification is stored + void setTempThreat(float pThreat) { iTempThreatModifyer = pThreat - getThreat(); if(iTempThreatModifyer != 0.0f) addThreat(iTempThreatModifyer); } + + void resetTempThreat() + { + if(iTempThreatModifyer != 0.0f) + { + addThreat(-iTempThreatModifyer); iTempThreatModifyer = 0.0f; + } + } + + float getTempThreatModifyer() { return iTempThreatModifyer; } + + //================================================= + // check, if source can reach target and set the status + void updateOnlineStatus(); + + void setOnlineOfflineState(bool pIsOnline); + + void setAccessibleState(bool pIsAccessible); + //================================================= + + bool operator ==(const HostilReference& pHostilReference) const { return pHostilReference.getUnitGuid() == getUnitGuid(); } + + //================================================= + + uint64 getUnitGuid() const { return iUnitGuid; } + + //================================================= + // reference is not needed anymore. realy delete it ! + + void removeReference(); + + //================================================= + + HostilReference* next() { return ((HostilReference* ) Reference::next()); } + + //================================================= + + // Tell our refTo (target) object that we have a link + void targetObjectBuildLink(); + + // Tell our refTo (taget) object, that the link is cut + void targetObjectDestroyLink(); + + // Tell our refFrom (source) object, that the link is cut (Target destroyed) + void sourceObjectDestroyLink(); +}; + +//============================================================== +class ThreatManager; + +class MANGOS_DLL_SPEC ThreatContainer +{ + private: + std::list iThreatList; + bool iDirty; + protected: + friend class ThreatManager; + + void remove(HostilReference* pRef) { iThreatList.remove(pRef); } + void addReference(HostilReference* pHostilReference) { iThreatList.push_back(pHostilReference); } + void clearReferences(); + // Sort the list if necessary + void update(); + public: + ThreatContainer() { iDirty = false; } + ~ThreatContainer() { clearReferences(); } + + HostilReference* addThreat(Unit* pVictim, float pThreat); + + void modifyThreatPercent(Unit *pVictim, int32 percent); + + HostilReference* selectNextVictim(Creature* pAttacker, HostilReference* pCurrentVictim); + + void setDirty(bool pDirty) { iDirty = pDirty; } + + bool isDirty() { return iDirty; } + + bool empty() { return(iThreatList.empty()); } + + HostilReference* getMostHated() { return iThreatList.empty() ? NULL : iThreatList.front(); } + + HostilReference* getReferenceByTarget(Unit* pVictim); + + std::list& getThreatList() { return iThreatList; } +}; + +//================================================= + +class MANGOS_DLL_SPEC ThreatManager +{ + private: + HostilReference* iCurrentVictim; + Unit* iOwner; + ThreatContainer iThreatContainer; + ThreatContainer iThreatOfflineContainer; + public: + explicit ThreatManager(Unit *pOwner); + + ~ThreatManager() { clearReferences(); } + + void clearReferences(); + + void addThreat(Unit* pVictim, float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellEntry const *threatSpell = NULL); + void modifyThreatPercent(Unit *pVictim, int32 pPercent); + + float getThreat(Unit *pVictim, bool pAlsoSearchOfflineList = false); + + bool isThreatListEmpty() { return iThreatContainer.empty();} + + bool processThreatEvent(const UnitBaseEvent* pUnitBaseEvent); + + HostilReference* getCurrentVictim() { return iCurrentVictim; } + + Unit* getOwner() { return iOwner; } + + Unit* getHostilTarget(); + + void tauntApply(Unit* pTaunter); + void tauntFadeOut(Unit *pTaunter); + + void setCurrentVictim(HostilReference* pHostilReference); + + void setDirty(bool pDirty) { iThreatContainer.setDirty(pDirty); } + + // methods to access the lists from the outside to do sume dirty manipulation (scriping and such) + // I hope they are used as little as possible. + inline std::list& getThreatList() { return iThreatContainer.getThreatList(); } + inline std::list& getOfflieThreatList() { return iThreatOfflineContainer.getThreatList(); } + inline ThreatContainer& getOnlineContainer() { return iThreatContainer; } + inline ThreatContainer& getOfflineContainer() { return iThreatOfflineContainer; } +}; + +//================================================= +#endif diff --git a/src/game/Tools.h b/src/game/Tools.h new file mode 100644 index 00000000000..d9615b7df63 --- /dev/null +++ b/src/game/Tools.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef MANGOS_TOOLS_H +#define MANGOS_TOOLS_H + +#include "Common.h" +#include "WorldPacket.h" + +bool readGUID(WorldPacket & data, uint64& guid); +void writeGUID(WorldPacket & data, uint64 & guid); +#endif diff --git a/src/game/Totem.cpp b/src/game/Totem.cpp new file mode 100644 index 00000000000..5415e4dbe87 --- /dev/null +++ b/src/game/Totem.cpp @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Totem.h" +#include "WorldPacket.h" +#include "MapManager.h" +#include "Log.h" +#include "Group.h" +#include "Player.h" +#include "ObjectMgr.h" +#include "SpellMgr.h" + +Totem::Totem() : Creature() +{ + m_isTotem = true; + m_duration = 0; + m_type = TOTEM_PASSIVE; +} + +void Totem::Update( uint32 time ) +{ + Unit *owner = GetOwner(); + if (!owner || !owner->isAlive() || !this->isAlive()) + { + UnSummon(); // remove self + return; + } + + if (m_duration <= time) + { + UnSummon(); // remove self + return; + } + else + m_duration -= time; + + Creature::Update( time ); +} + +void Totem::Summon(Unit* owner) +{ + sLog.outDebug("AddObject at Totem.cpp line 49"); + + SetInstanceId(owner->GetInstanceId()); + owner->GetMap()->Add((Creature*)this); + + // select totem model in dependent from owner team + CreatureInfo const *cinfo = GetCreatureInfo(); + if(owner->GetTypeId()==TYPEID_PLAYER && cinfo) + { + if(((Player*)owner)->GetTeam()==HORDE) + SetDisplayId(cinfo->DisplayID_H); + else + SetDisplayId(cinfo->DisplayID_A); + } + + WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8); + data << GetGUID(); + SendMessageToSet(&data,true); + + AIM_Initialize(); + + switch(m_type) + { + case TOTEM_PASSIVE: CastSpell(this, GetSpell(), true); break; + case TOTEM_STATUE: CastSpell(GetOwner(), GetSpell(), true); break; + default: break; + } +} + +void Totem::UnSummon() +{ + SendObjectDeSpawnAnim(GetGUID()); + + CombatStop(); + RemoveAurasDueToSpell(GetSpell()); + Unit *owner = this->GetOwner(); + if (owner) + { + // clear owenr's totem slot + for(int i = 0; i < MAX_TOTEM; ++i) + { + if(owner->m_TotemSlot[i]==GetGUID()) + { + owner->m_TotemSlot[i] = 0; + break; + } + } + + owner->RemoveAurasDueToSpell(GetSpell()); + + //remove aura all party members too + Group *pGroup = NULL; + if (owner->GetTypeId() == TYPEID_PLAYER) + { + // Not only the player can summon the totem (scripted AI) + pGroup = ((Player*)owner)->GetGroup(); + if (pGroup) + { + for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player* Target = itr->getSource(); + if(Target && pGroup->SameSubGroup((Player*)owner, Target)) + Target->RemoveAurasDueToSpell(GetSpell()); + } + } + } + } + + CleanupsBeforeDelete(); + AddObjectToRemoveList(); +} + +void Totem::SetOwner(uint64 guid) +{ + SetUInt64Value(UNIT_FIELD_SUMMONEDBY, guid); + SetUInt64Value(UNIT_FIELD_CREATEDBY, guid); + Unit *owner = this->GetOwner(); + if (owner) + { + this->setFaction(owner->getFaction()); + this->SetLevel(owner->getLevel()); + } +} + +Unit *Totem::GetOwner() +{ + uint64 ownerid = GetOwnerGUID(); + if(!ownerid) + return NULL; + return ObjectAccessor::GetUnit(*this, ownerid); +} + +void Totem::SetTypeBySummonSpell(SpellEntry const * spellProto) +{ + // Get spell casted by totem + SpellEntry const * totemSpell = sSpellStore.LookupEntry(GetSpell()); + if (totemSpell) + { + // If spell have cast time -> so its active totem + if (GetSpellCastTime(totemSpell)) + m_type = TOTEM_ACTIVE; + } + if(spellProto->SpellIconID==2056) + m_type = TOTEM_STATUE; //Jewelery statue +} diff --git a/src/game/Totem.h b/src/game/Totem.h new file mode 100644 index 00000000000..34bf440c68e --- /dev/null +++ b/src/game/Totem.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOSSERVER_TOTEM_H +#define MANGOSSERVER_TOTEM_H + +#include "Creature.h" + +enum TotemType +{ + TOTEM_PASSIVE = 0, + TOTEM_ACTIVE = 1, + TOTEM_STATUE = 2 +}; + +class Totem : public Creature +{ + public: + explicit Totem(); + virtual ~Totem(){}; + void Update( uint32 time ); + void Summon(Unit* owner); + void UnSummon(); + uint32 GetSpell() const { return m_spells[0]; } + uint32 GetTotemDuration() const { return m_duration; } + Unit *GetOwner(); + TotemType GetTotemType() const { return m_type; } + void SetTypeBySummonSpell(SpellEntry const * spellProto); + void SetDuration(uint32 dur) { m_duration = dur; } + void SetOwner(uint64 guid); + + bool UpdateStats(Stats /*stat*/) { return true; } + bool UpdateAllStats() { return true; } + void UpdateResistances(uint32 /*school*/) {} + void UpdateArmor() {} + void UpdateMaxHealth() {} + void UpdateMaxPower(Powers /*power*/) {} + void UpdateAttackPowerAndDamage(bool /*ranged*/ ) {} + void UpdateDamagePhysical(WeaponAttackType /*attType*/) {} + + protected: + TotemType m_type; + uint32 m_duration; +}; +#endif diff --git a/src/game/TotemAI.cpp b/src/game/TotemAI.cpp new file mode 100644 index 00000000000..8fc038a8946 --- /dev/null +++ b/src/game/TotemAI.cpp @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "TotemAI.h" +#include "Totem.h" +#include "Creature.h" +#include "Player.h" +#include "Database/DBCStores.h" +#include "MapManager.h" +#include "ObjectAccessor.h" +#include "SpellMgr.h" + +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" +#include "CellImpl.h" + +int +TotemAI::Permissible(const Creature *creature) +{ + if( creature->isTotem() ) + return PERMIT_BASE_PROACTIVE; + + return PERMIT_BASE_NO; +} + +TotemAI::TotemAI(Creature &c) : i_totem(static_cast(c)), i_victimGuid(0) +{ +} + +void +TotemAI::MoveInLineOfSight(Unit *) +{ +} + +void TotemAI::EnterEvadeMode() +{ + i_totem.CombatStop(); +} + +void +TotemAI::UpdateAI(const uint32 /*diff*/) +{ + if (i_totem.GetTotemType() != TOTEM_ACTIVE) + return; + + if (!i_totem.isAlive() || i_totem.IsNonMeleeSpellCasted(false)) + return; + + // Search spell + SpellEntry const *spellInfo = sSpellStore.LookupEntry(i_totem.GetSpell()); + if (!spellInfo) + return; + + // Get spell rangy + SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(spellInfo->rangeIndex); + float max_range = GetSpellMaxRange(srange); + + // SPELLMOD_RANGE not applied in this place just because not existence range mods for attacking totems + + // pointer to appropriate target if found any + Unit* victim = i_victimGuid ? ObjectAccessor::GetUnit(i_totem, i_victimGuid) : NULL; + + // Search victim if no, not attackable, or out of range, or friendly (possible in case duel end) + if( !victim || + !victim->isTargetableForAttack() || !i_totem.IsWithinDistInMap(victim, max_range) || + i_totem.IsFriendlyTo(victim) || !victim->isVisibleForOrDetect(&i_totem,false) ) + { + CellPair p(MaNGOS::ComputeCellPair(i_totem.GetPositionX(),i_totem.GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + + victim = NULL; + + MaNGOS::NearestAttackableUnitInObjectRangeCheck u_check(&i_totem, &i_totem, max_range); + MaNGOS::UnitLastSearcher checker(victim, u_check); + + TypeContainerVisitor, GridTypeMapContainer > grid_object_checker(checker); + TypeContainerVisitor, WorldTypeMapContainer > world_object_checker(checker); + + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, grid_object_checker, *MapManager::Instance().GetMap(i_totem.GetMapId(), &i_totem)); + cell_lock->Visit(cell_lock, world_object_checker, *MapManager::Instance().GetMap(i_totem.GetMapId(), &i_totem)); + } + + // If have target + if (victim) + { + // remember + i_victimGuid = victim->GetGUID(); + + // attack + i_totem.SetInFront(victim); // client change orientation by self + i_totem.CastSpell(victim, i_totem.GetSpell(), false); + } + else + i_victimGuid = 0; +} + +bool +TotemAI::IsVisible(Unit *) const +{ + return false; +} + +void +TotemAI::AttackStart(Unit *) +{ +} diff --git a/src/game/TotemAI.h b/src/game/TotemAI.h new file mode 100644 index 00000000000..e113ac441a1 --- /dev/null +++ b/src/game/TotemAI.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_TOTEMAI_H +#define MANGOS_TOTEMAI_H + +#include "CreatureAI.h" +#include "Timer.h" + +class Creature; +class Totem; + +class MANGOS_DLL_DECL TotemAI : public CreatureAI +{ + public: + + TotemAI(Creature &c); + + void MoveInLineOfSight(Unit *); + void AttackStart(Unit *); + void EnterEvadeMode(); + bool IsVisible(Unit *) const; + + void UpdateAI(const uint32); + static int Permissible(const Creature *); + + private: + Totem &i_totem; + uint64 i_victimGuid; +}; +#endif diff --git a/src/game/TradeHandler.cpp b/src/game/TradeHandler.cpp new file mode 100644 index 00000000000..eb874f82ffb --- /dev/null +++ b/src/game/TradeHandler.cpp @@ -0,0 +1,633 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "World.h" +#include "ObjectAccessor.h" +#include "Log.h" +#include "Opcodes.h" +#include "Player.h" +#include "Item.h" +#include "SocialMgr.h" + +enum TradeStatus +{ + TRADE_STATUS_BUSY = 0, + TRADE_STATUS_BEGIN_TRADE = 1, + TRADE_STATUS_OPEN_WINDOW = 2, + TRADE_STATUS_TRADE_CANCELED = 3, + TRADE_STATUS_TRADE_ACCEPT = 4, + TRADE_STATUS_BUSY_2 = 5, + TRADE_STATUS_NO_TARGET = 6, + TRADE_STATUS_BACK_TO_TRADE = 7, + TRADE_STATUS_TRADE_COMPLETE = 8, + // 9? + TRADE_STATUS_TARGET_TO_FAR = 10, + TRADE_STATUS_WRONG_FACTION = 11, + TRADE_STATUS_CLOSE_WINDOW = 12, + // 13? + TRADE_STATUS_IGNORE_YOU = 14, + TRADE_STATUS_YOU_STUNNED = 15, + TRADE_STATUS_TARGET_STUNNED = 16, + TRADE_STATUS_YOU_DEAD = 17, + TRADE_STATUS_TARGET_DEAD = 18, + TRADE_STATUS_YOU_LOGOUT = 19, + TRADE_STATUS_TARGET_LOGOUT = 20, + TRADE_STATUS_TRIAL_ACCOUNT = 21, // Trial accounts can not perform that action + TRADE_STATUS_ONLY_CONJURED = 22 // You can only trade conjured items... (cross realm BG related). +}; + +void WorldSession::SendTradeStatus(uint32 status) +{ + WorldPacket data; + + switch(status) + { + case TRADE_STATUS_BEGIN_TRADE: + data.Initialize(SMSG_TRADE_STATUS, 4+8); + data << uint32(status); + data << uint64(0); + break; + case TRADE_STATUS_OPEN_WINDOW: + data.Initialize(SMSG_TRADE_STATUS, 4+4); + data << uint32(status); + data << uint32(0); // added in 2.4.0 + break; + case TRADE_STATUS_CLOSE_WINDOW: + data.Initialize(SMSG_TRADE_STATUS, 4+4+1+4); + data << uint32(status); + data << uint32(0); + data << uint8(0); + data << uint32(0); + break; + case TRADE_STATUS_ONLY_CONJURED: + data.Initialize(SMSG_TRADE_STATUS, 4+1); + data << uint32(status); + data << uint8(0); + break; + default: + data.Initialize(SMSG_TRADE_STATUS, 4); + data << uint32(status); + break; + } + + SendPacket(&data); +} + +void WorldSession::HandleIgnoreTradeOpcode(WorldPacket& /*recvPacket*/) +{ + sLog.outDebug( "WORLD: Ignore Trade %u",_player->GetGUIDLow()); + // recvPacket.print_storage(); +} + +void WorldSession::HandleBusyTradeOpcode(WorldPacket& /*recvPacket*/) +{ + sLog.outDebug( "WORLD: Busy Trade %u",_player->GetGUIDLow()); + // recvPacket.print_storage(); +} + +void WorldSession::SendUpdateTrade() +{ + Item *item = NULL; + + if( !_player || !_player->pTrader ) + return; + + // reset trade status + if (_player->acceptTrade) + { + _player->acceptTrade = false; + SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); + } + + if (_player->pTrader->acceptTrade) + { + _player->pTrader->acceptTrade = false; + _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); + } + + WorldPacket data(SMSG_TRADE_STATUS_EXTENDED, (100)); // guess size + data << (uint8 ) 1; // can be different (only seen 0 and 1) + data << (uint32) 0; // added in 2.4.0, this value must be equal to value from TRADE_STATUS_OPEN_WINDOW status packet (different value for different players to block multiple trades?) + data << (uint32) TRADE_SLOT_COUNT; // trade slots count/number?, = next field in most cases + data << (uint32) TRADE_SLOT_COUNT; // trade slots count/number?, = prev field in most cases + data << (uint32) _player->pTrader->tradeGold; // trader gold + data << (uint32) 0; // spell casted on lowest slot item + + for(uint8 i = 0; i < TRADE_SLOT_COUNT; i++) + { + item = (_player->pTrader->tradeItems[i] != NULL_SLOT ? _player->pTrader->GetItemByPos( _player->pTrader->tradeItems[i] ) : NULL); + + data << (uint8) i; // trade slot number, if not specified, then end of packet + + if(item) + { + data << (uint32) item->GetProto()->ItemId; // entry + // display id + data << (uint32) item->GetProto()->DisplayInfoID; + // stack count + data << (uint32) item->GetUInt32Value(ITEM_FIELD_STACK_COUNT); + data << (uint32) 0; // probably gift=1, created_by=0? + // gift creator + data << (uint64) item->GetUInt64Value(ITEM_FIELD_GIFTCREATOR); + data << (uint32) item->GetEnchantmentId(PERM_ENCHANTMENT_SLOT); + for(uint8 j = 0; j < 3; ++j) + data << (uint32) 0; // enchantment id (permanent/gems?) + // creator + data << (uint64) item->GetUInt64Value(ITEM_FIELD_CREATOR); + data << (uint32) item->GetSpellCharges(); // charges + data << (uint32) item->GetItemSuffixFactor(); // SuffixFactor + // random properties id + data << (uint32) item->GetItemRandomPropertyId(); + data << (uint32) item->GetProto()->LockID; // lock id + // max durability + data << (uint32) item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY); + // durability + data << (uint32) item->GetUInt32Value(ITEM_FIELD_DURABILITY); + } + else + { + for(uint8 j = 0; j < 18; j++) + data << uint32(0); + } + } + SendPacket(&data); +} + +//============================================================== +// transfer the items to the players + +void WorldSession::moveItems(Item* myItems[], Item* hisItems[]) +{ + for(int i=0; ipTrader->CanStoreItem( NULL_BAG, NULL_SLOT, traderDst, myItems[i], false ) == EQUIP_ERR_OK); + bool playerCanTrade = (hisItems[i]==NULL || _player->CanStoreItem( NULL_BAG, NULL_SLOT, playerDst, hisItems[i], false ) == EQUIP_ERR_OK); + if(traderCanTrade && playerCanTrade ) + { + // Ok, if trade item exists and can be stored + // If we trade in both directions we had to check, if the trade will work before we actually do it + // A roll back is not possible after we stored it + if(myItems[i]) + { + // logging + sLog.outDebug("partner storing: %u",myItems[i]->GetGUIDLow()); + if( _player->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) ) + sLog.outCommand("GM %s (Account: %u) trade: %s (Entry: %d Count: %u) to player: %s (Account: %u)", + _player->GetName(),_player->GetSession()->GetAccountId(), + myItems[i]->GetProto()->Name1,myItems[i]->GetEntry(),myItems[i]->GetCount(), + _player->pTrader->GetName(),_player->pTrader->GetSession()->GetAccountId()); + + // store + _player->pTrader->MoveItemToInventory( traderDst, myItems[i], true, true); + } + if(hisItems[i]) + { + // logging + sLog.outDebug("player storing: %u",hisItems[i]->GetGUIDLow()); + if( _player->pTrader->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) ) + sLog.outCommand("GM %s (Account: %u) trade: %s (Entry: %d Count: %u) to player: %s (Account: %u)", + _player->pTrader->GetName(),_player->pTrader->GetSession()->GetAccountId(), + hisItems[i]->GetProto()->Name1,hisItems[i]->GetEntry(),hisItems[i]->GetCount(), + _player->GetName(),_player->GetSession()->GetAccountId()); + + // store + _player->MoveItemToInventory( playerDst, hisItems[i], true, true); + } + } + else + { + // in case of fatal error log error message + // return the already removed items to the original owner + if(myItems[i]) + { + if(!traderCanTrade) + sLog.outError("trader can't store item: %u",myItems[i]->GetGUIDLow()); + if(_player->CanStoreItem( NULL_BAG, NULL_SLOT, playerDst, myItems[i], false ) == EQUIP_ERR_OK) + _player->MoveItemToInventory(playerDst, myItems[i], true, true); + else + sLog.outError("player can't take item back: %u",myItems[i]->GetGUIDLow()); + } + // return the already removed items to the original owner + if(hisItems[i]) + { + if(!playerCanTrade) + sLog.outError("player can't store item: %u",hisItems[i]->GetGUIDLow()); + if(_player->pTrader->CanStoreItem( NULL_BAG, NULL_SLOT, traderDst, hisItems[i], false ) == EQUIP_ERR_OK) + _player->pTrader->MoveItemToInventory(traderDst, hisItems[i], true, true); + else + sLog.outError("trader can't take item back: %u",hisItems[i]->GetGUIDLow()); + } + } + } +} + +//============================================================== + +void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/) +{ + Item *myItems[TRADE_SLOT_TRADED_COUNT] = { NULL, NULL, NULL, NULL, NULL, NULL }; + Item *hisItems[TRADE_SLOT_TRADED_COUNT] = { NULL, NULL, NULL, NULL, NULL, NULL }; + bool myCanCompleteTrade=true,hisCanCompleteTrade=true; + + if ( !GetPlayer()->pTrader ) + return; + + // not accept case incorrect money amount + if( _player->tradeGold > _player->GetMoney() ) + { + SendNotification( "You do not have enough gold" ); + _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); + _player->acceptTrade = false; + return; + } + + // not accept case incorrect money amount + if( _player->pTrader->tradeGold > _player->pTrader->GetMoney() ) + { + _player->pTrader->GetSession( )->SendNotification( "You do not have enough gold" ); + SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); + _player->pTrader->acceptTrade = false; + return; + } + + // not accept if some items now can't be trade (cheating) + for(int i=0; itradeItems[i] != NULL_SLOT ) + { + if(Item* item =_player->GetItemByPos( _player->tradeItems[i] )) + { + if(!item->CanBeTraded()) + { + SendTradeStatus(TRADE_STATUS_TRADE_CANCELED); + return; + } + } + } + if(_player->pTrader->tradeItems[i] != NULL_SLOT) + { + if(Item* item =_player->pTrader->GetItemByPos( _player->pTrader->tradeItems[i]) ) + { + if(!item->CanBeTraded()) + { + SendTradeStatus(TRADE_STATUS_TRADE_CANCELED); + return; + } + } + } + } + + _player->acceptTrade = true; + if (_player->pTrader->acceptTrade ) + { + // inform partner client + _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_TRADE_ACCEPT); + + // store items in local list and set 'in-trade' flag + for(int i=0; itradeItems[i] != NULL_SLOT ) + { + sLog.outDebug("player trade item bag: %u slot: %u",_player->tradeItems[i] >> 8, _player->tradeItems[i] & 255 ); + //Can return NULL + myItems[i]=_player->GetItemByPos( _player->tradeItems[i] ); + if (myItems[i]) + myItems[i]->SetInTrade(); + } + if(_player->pTrader->tradeItems[i] != NULL_SLOT) + { + sLog.outDebug("partner trade item bag: %u slot: %u",_player->pTrader->tradeItems[i] >> 8,_player->pTrader->tradeItems[i] & 255); + //Can return NULL + hisItems[i]=_player->pTrader->GetItemByPos( _player->pTrader->tradeItems[i]); + if(hisItems[i]) + hisItems[i]->SetInTrade(); + } + } + + // test if item will fit in each inventory + hisCanCompleteTrade = (_player->pTrader->CanStoreItems( myItems,TRADE_SLOT_TRADED_COUNT )== EQUIP_ERR_OK); + myCanCompleteTrade = (_player->CanStoreItems( hisItems,TRADE_SLOT_TRADED_COUNT ) == EQUIP_ERR_OK); + + // clear 'in-trade' flag + for(int i=0; iSetInTrade(false); + if(hisItems[i]) hisItems[i]->SetInTrade(false); + } + + // in case of missing space report error + if(!myCanCompleteTrade) + { + SendNotification("You do not have enough free slots"); + GetPlayer( )->pTrader->GetSession( )->SendNotification("Your partner does not have enough free bag slots"); + SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); + _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); + return; + } + else if (!hisCanCompleteTrade) + { + SendNotification("Your partner does not have enough free bag slots"); + GetPlayer()->pTrader->GetSession()->SendNotification("You do not have enough free slots"); + SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); + _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); + return; + } + + // execute trade: 1. remove + for(int i=0; iSetUInt64Value( ITEM_FIELD_GIFTCREATOR,_player->GetGUID()); + _player->MoveItemFromInventory(_player->tradeItems[i] >> 8, _player->tradeItems[i] & 255, true); + } + if(hisItems[i]) + { + hisItems[i]->SetUInt64Value( ITEM_FIELD_GIFTCREATOR,_player->pTrader->GetGUID()); + _player->pTrader->MoveItemFromInventory(_player->pTrader->tradeItems[i] >> 8, _player->pTrader->tradeItems[i] & 255, true); + } + } + + // execute trade: 2. store + moveItems(myItems, hisItems); + + // logging money + if(sWorld.getConfig(CONFIG_GM_LOG_TRADE)) + { + if( _player->GetSession()->GetSecurity() > SEC_PLAYER && _player->tradeGold > 0) + sLog.outCommand("GM %s (Account: %u) give money (Amount: %u) to player: %s (Account: %u)", + _player->GetName(),_player->GetSession()->GetAccountId(), + _player->tradeGold, + _player->pTrader->GetName(),_player->pTrader->GetSession()->GetAccountId()); + if( _player->pTrader->GetSession()->GetSecurity() > SEC_PLAYER && _player->pTrader->tradeGold > 0) + sLog.outCommand("GM %s (Account: %u) give money (Amount: %u) to player: %s (Account: %u)", + _player->pTrader->GetName(),_player->pTrader->GetSession()->GetAccountId(), + _player->pTrader->tradeGold, + _player->GetName(),_player->GetSession()->GetAccountId()); + } + + // update money + _player->ModifyMoney( -int32(_player->tradeGold) ); + _player->ModifyMoney(_player->pTrader->tradeGold ); + _player->pTrader->ModifyMoney( -int32(_player->pTrader->tradeGold) ); + _player->pTrader->ModifyMoney(_player->tradeGold ); + + _player->ClearTrade(); + _player->pTrader->ClearTrade(); + + // desynchronized with the other saves here (SaveInventoryAndGoldToDB() not have own transaction guards) + CharacterDatabase.BeginTransaction(); + _player->SaveInventoryAndGoldToDB(); + _player->pTrader->SaveInventoryAndGoldToDB(); + CharacterDatabase.CommitTransaction(); + + _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_TRADE_COMPLETE); + SendTradeStatus(TRADE_STATUS_TRADE_COMPLETE); + + _player->pTrader->pTrader = NULL; + _player->pTrader = NULL; + } + else + { + _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_TRADE_ACCEPT); + } +} + +void WorldSession::HandleUnacceptTradeOpcode(WorldPacket& /*recvPacket*/) +{ + if ( !GetPlayer()->pTrader ) + return; + + _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); + _player->acceptTrade = false; +} + +void WorldSession::HandleBeginTradeOpcode(WorldPacket& /*recvPacket*/) +{ + if(!_player->pTrader) + return; + + _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_OPEN_WINDOW); + _player->pTrader->ClearTrade(); + + SendTradeStatus(TRADE_STATUS_OPEN_WINDOW); + _player->ClearTrade(); +} + +void WorldSession::SendCancelTrade() +{ + SendTradeStatus(TRADE_STATUS_TRADE_CANCELED); +} + +void WorldSession::HandleCancelTradeOpcode(WorldPacket& /*recvPacket*/) +{ + // sended also after LOGOUT COMPLETE + if(_player) // needed because STATUS_AUTHED + _player->TradeCancel(true); +} + +void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket) +{ + CHECK_PACKET_SIZE(recvPacket,8); + + if( GetPlayer()->pTrader ) + return; + + uint64 ID; + + if( !GetPlayer()->isAlive() ) + { + SendTradeStatus(TRADE_STATUS_YOU_DEAD); + return; + } + + if( GetPlayer()->hasUnitState(UNIT_STAT_STUNDED) ) + { + SendTradeStatus(TRADE_STATUS_YOU_STUNNED); + return; + } + + if( isLogingOut() ) + { + SendTradeStatus(TRADE_STATUS_YOU_LOGOUT); + return; + } + + if( GetPlayer()->isInFlight() ) + { + SendTradeStatus(TRADE_STATUS_TARGET_TO_FAR); + return; + } + + recvPacket >> ID; + + Player* pOther = ObjectAccessor::FindPlayer( ID ); + + if( !pOther ) + { + SendTradeStatus(TRADE_STATUS_NO_TARGET); + return; + } + + if( pOther == GetPlayer() || pOther->pTrader ) + { + SendTradeStatus(TRADE_STATUS_BUSY); + return; + } + + if( !pOther->isAlive() ) + { + SendTradeStatus(TRADE_STATUS_TARGET_DEAD); + return; + } + + if( pOther->isInFlight() ) + { + SendTradeStatus(TRADE_STATUS_TARGET_TO_FAR); + return; + } + + if( pOther->hasUnitState(UNIT_STAT_STUNDED) ) + { + SendTradeStatus(TRADE_STATUS_TARGET_STUNNED); + return; + } + + if( pOther->GetSession()->isLogingOut() ) + { + SendTradeStatus(TRADE_STATUS_TARGET_LOGOUT); + return; + } + + if( pOther->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow()) ) + { + SendTradeStatus(TRADE_STATUS_IGNORE_YOU); + return; + } + + if(pOther->GetTeam() !=_player->GetTeam() ) + { + SendTradeStatus(TRADE_STATUS_WRONG_FACTION); + return; + } + + if( pOther->GetDistance2d( _player ) > 10.0f ) + { + SendTradeStatus(TRADE_STATUS_TARGET_TO_FAR); + return; + } + + // OK start trade + _player->pTrader = pOther; + pOther->pTrader =_player; + + WorldPacket data(SMSG_TRADE_STATUS, 12); + data << (uint32) TRADE_STATUS_BEGIN_TRADE; + data << (uint64)_player->GetGUID(); + _player->pTrader->GetSession()->SendPacket(&data); +} + +void WorldSession::HandleSetTradeGoldOpcode(WorldPacket& recvPacket) +{ + CHECK_PACKET_SIZE(recvPacket,4); + + if(!_player->pTrader) + return; + + uint32 gold; + + recvPacket >> gold; + + // gold can be incorrect, but this is checked at trade finished. + _player->tradeGold = gold; + + _player->pTrader->GetSession()->SendUpdateTrade(); +} + +void WorldSession::HandleSetTradeItemOpcode(WorldPacket& recvPacket) +{ + CHECK_PACKET_SIZE(recvPacket,1+1+1); + + if(!_player->pTrader) + return; + + // send update + uint8 tradeSlot; + uint8 bag; + uint8 slot; + + recvPacket >> tradeSlot; + recvPacket >> bag; + recvPacket >> slot; + + // invalid slot number + if(tradeSlot >= TRADE_SLOT_COUNT) + { + SendTradeStatus(TRADE_STATUS_TRADE_CANCELED); + return; + } + + // check cheating, can't fail with correct client operations + Item* item = _player->GetItemByPos(bag,slot); + if(!item || tradeSlot!=TRADE_SLOT_NONTRADED && !item->CanBeTraded()) + { + SendTradeStatus(TRADE_STATUS_TRADE_CANCELED); + return; + } + + uint16 pos = (bag << 8) | slot; + + // prevent place single item into many trade slots using cheating and client bugs + for(int i = 0; i < TRADE_SLOT_COUNT; ++i) + { + if(_player->tradeItems[i]==pos) + { + // cheating attempt + SendTradeStatus(TRADE_STATUS_TRADE_CANCELED); + return; + } + } + + _player->tradeItems[tradeSlot] = pos; + + _player->pTrader->GetSession()->SendUpdateTrade(); +} + +void WorldSession::HandleClearTradeItemOpcode(WorldPacket& recvPacket) +{ + CHECK_PACKET_SIZE(recvPacket,1); + + if(!_player->pTrader) + return; + + uint8 tradeSlot; + recvPacket >> tradeSlot; + + // invalid slot number + if(tradeSlot >= TRADE_SLOT_COUNT) + return; + + _player->tradeItems[tradeSlot] = NULL_SLOT; + + _player->pTrader->GetSession()->SendUpdateTrade(); +} diff --git a/src/game/Transports.cpp b/src/game/Transports.cpp new file mode 100644 index 00000000000..be5fa09606f --- /dev/null +++ b/src/game/Transports.cpp @@ -0,0 +1,525 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" + +#include "Transports.h" +#include "MapManager.h" +#include "ObjectMgr.h" +#include "Path.h" + +#include "WorldPacket.h" +#include "Database/DBCStores.h" +#include "ProgressBar.h" + +void MapManager::LoadTransports() +{ + QueryResult *result = WorldDatabase.Query("SELECT entry, name, period FROM transports"); + + uint32 count = 0; + + if( !result ) + { + barGoLink bar( 1 ); + bar.step(); + + sLog.outString(); + sLog.outString( ">> Loaded %u transports", count ); + return; + } + + barGoLink bar( result->GetRowCount() ); + + do + { + bar.step(); + + Transport *t = new Transport; + + Field *fields = result->Fetch(); + + uint32 entry = fields[0].GetUInt32(); + std::string name = fields[1].GetCppString(); + t->m_period = fields[2].GetUInt32(); + + const GameObjectInfo *goinfo = objmgr.GetGameObjectInfo(entry); + + if(!goinfo) + { + sLog.outErrorDb("Transport ID:%u, Name: %s, will not be loaded, gameobject_template missing", entry, name.c_str()); + delete t; + continue; + } + + if(goinfo->type != GAMEOBJECT_TYPE_MO_TRANSPORT) + { + sLog.outErrorDb("Transport ID:%u, Name: %s, will not be loaded, gameobject_template type wrong", entry, name.c_str()); + delete t; + continue; + } + + // sLog.outString("Loading transport %d between %s, %s", entry, name.c_str(), goinfo->name); + + std::set mapsUsed; + + if(!t->GenerateWaypoints(goinfo->moTransport.taxiPathId, mapsUsed)) + // skip transports with empty waypoints list + { + sLog.outErrorDb("Transport (path id %u) path size = 0. Transport ignored, check DBC files or transport GO data0 field.",goinfo->moTransport.taxiPathId); + delete t; + continue; + } + + t->m_name = goinfo->name; + + float x, y, z, o; + uint32 mapid; + x = t->m_WayPoints[0].x; y = t->m_WayPoints[0].y; z = t->m_WayPoints[0].z; mapid = t->m_WayPoints[0].mapid; o = 1; + + // creates the Gameobject + if(!t->Create(entry, mapid, x, y, z, o, 100, 0)) + { + delete t; + continue; + } + + m_Transports.insert(t); + + for (std::set::iterator i = mapsUsed.begin(); i != mapsUsed.end(); ++i) + m_TransportsByMap[*i].insert(t); + + //If we someday decide to use the grid to track transports, here: + //MapManager::Instance().LoadGrid(mapid,x,y,true); + //MapManager::Instance().GetMap(t->GetMapId())->Add((GameObject *)t); + ++count; + } while(result->NextRow()); + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u transports", count ); + + // check transport data DB integrity + result = WorldDatabase.PQuery("SELECT gameobject.guid,gameobject.id,transports.name FROM gameobject,transports WHERE gameobject.id = transports.entry"); + if(result) // wrong data found + { + do + { + Field *fields = result->Fetch(); + + uint32 guid = fields[0].GetUInt32(); + uint32 entry = fields[1].GetUInt32(); + std::string name = fields[2].GetCppString(); + sLog.outErrorDb("Transport %u '%s' have record (GUID: %u) in `gameobject`. Transports DON'T must have any records in `gameobject` or its behavior will be unpredictable/bugged.",entry,name.c_str(),guid); + } + while(result->NextRow()); + + delete result; + } +} + +Transport::Transport() : GameObject() +{ + // 2.3.2 - 0x5A + m_updateFlag = (UPDATEFLAG_TRANSPORT | UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HASPOSITION); +} + +bool Transport::Create(uint32 guidlow, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress, uint32 dynflags) +{ + Relocate(x,y,z,ang); + + SetMapId(mapid); + + if(!IsPositionValid()) + { + sLog.outError("ERROR: Transport (GUID: %u) not created. Suggested coordinates isn't valid (X: %d Y: ^%d)",guidlow,x,y); + return false; + } + + Object::_Create(guidlow, 0, HIGHGUID_MO_TRANSPORT); + + GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(guidlow); + + if (!goinfo) + { + sLog.outErrorDb("Transport not created: entry in `gameobject_template` not found, guidlow: %u map: %u (X: %f Y: %f Z: %f) ang: %f",guidlow, mapid, x, y, z, ang); + return false; + } + + m_goInfo = goinfo; + + SetFloatValue(OBJECT_FIELD_SCALE_X, goinfo->size); + + SetUInt32Value(GAMEOBJECT_FACTION, goinfo->faction); + SetUInt32Value(GAMEOBJECT_FLAGS, goinfo->flags); + + SetUInt32Value(OBJECT_FIELD_ENTRY, goinfo->id); + + SetUInt32Value(GAMEOBJECT_DISPLAYID, goinfo->displayId); + + SetGoState(1); + SetGoType(GameobjectTypes(goinfo->type)); + + SetGoAnimProgress(animprogress); + if(dynflags) + SetUInt32Value(GAMEOBJECT_DYN_FLAGS, dynflags); + + return true; +} + +struct keyFrame +{ + keyFrame(float _x, float _y, float _z, uint32 _mapid, int _actionflag, int _delay) + { + x = _x; y = _y; z = _z; mapid = _mapid; actionflag = _actionflag; delay = _delay; distFromPrev = -1; distSinceStop = -1; distUntilStop = -1; + tFrom = 0; tTo = 0; + } + + float x; + float y; + float z; + uint32 mapid; + int actionflag; + int delay; + float distSinceStop; + float distUntilStop; + float distFromPrev; + float tFrom, tTo; +}; + +bool Transport::GenerateWaypoints(uint32 pathid, std::set &mapids) +{ + TransportPath path; + objmgr.GetTransportPathNodes(pathid, path); + + if (path.Empty()) + return false; + + std::vector keyFrames; + int mapChange = 0; + mapids.clear(); + for (size_t i = 1; i < path.Size() - 1; i++) + { + if (mapChange == 0) + { + if ((path[i].mapid == path[i+1].mapid)) + { + keyFrame k(path[i].x, path[i].y, path[i].z, path[i].mapid, path[i].actionFlag, path[i].delay); + keyFrames.push_back(k); + mapids.insert(k.mapid); + } + else + { + mapChange = 1; + } + } + else + { + --mapChange; + } + } + + int lastStop = -1; + int firstStop = -1; + + // first cell is arrived at by teleportation :S + keyFrames[0].distFromPrev = 0; + if (keyFrames[0].actionflag == 2) + { + lastStop = 0; + } + + // find the rest of the distances between key points + for (size_t i = 1; i < keyFrames.size(); i++) + { + if ((keyFrames[i].actionflag == 1) || (keyFrames[i].mapid != keyFrames[i-1].mapid)) + { + keyFrames[i].distFromPrev = 0; + } + else + { + keyFrames[i].distFromPrev = + sqrt(pow(keyFrames[i].x - keyFrames[i - 1].x, 2) + + pow(keyFrames[i].y - keyFrames[i - 1].y, 2) + + pow(keyFrames[i].z - keyFrames[i - 1].z, 2)); + } + if (keyFrames[i].actionflag == 2) + { + // remember first stop frame + if(firstStop == -1) + firstStop = i; + lastStop = i; + } + } + + float tmpDist = 0; + for (size_t i = 0; i < keyFrames.size(); i++) + { + int j = (i + lastStop) % keyFrames.size(); + if (keyFrames[j].actionflag == 2) + tmpDist = 0; + else + tmpDist += keyFrames[j].distFromPrev; + keyFrames[j].distSinceStop = tmpDist; + } + + for (int i = int(keyFrames.size()) - 1; i >= 0; i--) + { + int j = (i + (firstStop+1)) % keyFrames.size(); + tmpDist += keyFrames[(j + 1) % keyFrames.size()].distFromPrev; + keyFrames[j].distUntilStop = tmpDist; + if (keyFrames[j].actionflag == 2) + tmpDist = 0; + } + + for (size_t i = 0; i < keyFrames.size(); i++) + { + if (keyFrames[i].distSinceStop < (30 * 30 * 0.5f)) + keyFrames[i].tFrom = sqrt(2 * keyFrames[i].distSinceStop); + else + keyFrames[i].tFrom = ((keyFrames[i].distSinceStop - (30 * 30 * 0.5f)) / 30) + 30; + + if (keyFrames[i].distUntilStop < (30 * 30 * 0.5f)) + keyFrames[i].tTo = sqrt(2 * keyFrames[i].distUntilStop); + else + keyFrames[i].tTo = ((keyFrames[i].distUntilStop - (30 * 30 * 0.5f)) / 30) + 30; + + keyFrames[i].tFrom *= 1000; + keyFrames[i].tTo *= 1000; + } + + // for (int i = 0; i < keyFrames.size(); i++) { + // sLog.outString("%f, %f, %f, %f, %f, %f, %f", keyFrames[i].x, keyFrames[i].y, keyFrames[i].distUntilStop, keyFrames[i].distSinceStop, keyFrames[i].distFromPrev, keyFrames[i].tFrom, keyFrames[i].tTo); + // } + + // Now we're completely set up; we can move along the length of each waypoint at 100 ms intervals + // speed = max(30, t) (remember x = 0.5s^2, and when accelerating, a = 1 unit/s^2 + int t = 0; + bool teleport = false; + if (keyFrames[keyFrames.size() - 1].mapid != keyFrames[0].mapid) + teleport = true; + + WayPoint pos(keyFrames[0].mapid, keyFrames[0].x, keyFrames[0].y, keyFrames[0].z, teleport); + m_WayPoints[0] = pos; + t += keyFrames[0].delay * 1000; + + uint32 cM = keyFrames[0].mapid; + for (size_t i = 0; i < keyFrames.size() - 1; i++) + { + float d = 0; + float tFrom = keyFrames[i].tFrom; + float tTo = keyFrames[i].tTo; + + // keep the generation of all these points; we use only a few now, but may need the others later + if (((d < keyFrames[i + 1].distFromPrev) && (tTo > 0))) + { + while ((d < keyFrames[i + 1].distFromPrev) && (tTo > 0)) + { + tFrom += 100; + tTo -= 100; + + if (d > 0) + { + float newX, newY, newZ; + newX = keyFrames[i].x + (keyFrames[i + 1].x - keyFrames[i].x) * d / keyFrames[i + 1].distFromPrev; + newY = keyFrames[i].y + (keyFrames[i + 1].y - keyFrames[i].y) * d / keyFrames[i + 1].distFromPrev; + newZ = keyFrames[i].z + (keyFrames[i + 1].z - keyFrames[i].z) * d / keyFrames[i + 1].distFromPrev; + + bool teleport = false; + if (keyFrames[i].mapid != cM) + { + teleport = true; + cM = keyFrames[i].mapid; + } + + // sLog.outString("T: %d, D: %f, x: %f, y: %f, z: %f", t, d, newX, newY, newZ); + WayPoint pos(keyFrames[i].mapid, newX, newY, newZ, teleport); + if (teleport) + m_WayPoints[t] = pos; + } + + if (tFrom < tTo) // caught in tFrom dock's "gravitational pull" + { + if (tFrom <= 30000) + { + d = 0.5f * (tFrom / 1000) * (tFrom / 1000); + } + else + { + d = 0.5f * 30 * 30 + 30 * ((tFrom - 30000) / 1000); + } + d = d - keyFrames[i].distSinceStop; + } + else + { + if (tTo <= 30000) + { + d = 0.5f * (tTo / 1000) * (tTo / 1000); + } + else + { + d = 0.5f * 30 * 30 + 30 * ((tTo - 30000) / 1000); + } + d = keyFrames[i].distUntilStop - d; + } + t += 100; + } + t -= 100; + } + + if (keyFrames[i + 1].tFrom > keyFrames[i + 1].tTo) + t += 100 - ((long)keyFrames[i + 1].tTo % 100); + else + t += (long)keyFrames[i + 1].tTo % 100; + + bool teleport = false; + if ((keyFrames[i + 1].actionflag == 1) || (keyFrames[i + 1].mapid != keyFrames[i].mapid)) + { + teleport = true; + cM = keyFrames[i + 1].mapid; + } + + WayPoint pos(keyFrames[i + 1].mapid, keyFrames[i + 1].x, keyFrames[i + 1].y, keyFrames[i + 1].z, teleport); + + // sLog.outString("T: %d, x: %f, y: %f, z: %f, t:%d", t, pos.x, pos.y, pos.z, teleport); + + //if (teleport) + m_WayPoints[t] = pos; + + t += keyFrames[i + 1].delay * 1000; + // sLog.outString("------"); + } + + uint32 timer = t; + + // sLog.outDetail(" Generated %d waypoints, total time %u.", m_WayPoints.size(), timer); + + m_curr = m_WayPoints.begin(); + m_curr = GetNextWayPoint(); + m_next = GetNextWayPoint(); + m_pathTime = timer; + + m_nextNodeTime = m_curr->first; + + return true; +} + +Transport::WayPointMap::iterator Transport::GetNextWayPoint() +{ + WayPointMap::iterator iter = m_curr; + ++iter; + if (iter == m_WayPoints.end()) + iter = m_WayPoints.begin(); + return iter; +} + +void Transport::TeleportTransport(uint32 newMapid, float x, float y, float z) +{ + //MapManager::Instance().GetMap(oldMapid)->Remove((GameObject *)this, false); + SetMapId(newMapid); + //MapManager::Instance().LoadGrid(newMapid,x,y,true); + Relocate(x, y, z); + //MapManager::Instance().GetMap(newMapid)->Add((GameObject *)this); + + for(PlayerSet::iterator itr = m_passengers.begin(); itr != m_passengers.end();) + { + PlayerSet::iterator it2 = itr; + ++itr; + + Player *plr = *it2; + if(!plr) + { + m_passengers.erase(it2); + continue; + } + + if (plr->isDead() && !plr->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) + { + plr->ResurrectPlayer(1.0); + } + plr->TeleportTo(newMapid, x, y, z, GetOrientation(), TELE_TO_NOT_LEAVE_TRANSPORT); + + //WorldPacket data(SMSG_811, 4); + //data << uint32(0); + //plr->GetSession()->SendPacket(&data); + } +} + +bool Transport::AddPassenger(Player* passenger) +{ + if (m_passengers.find(passenger) == m_passengers.end()) + { + sLog.outDetail("Player %s boarded transport %s.", passenger->GetName(), this->m_name.c_str()); + m_passengers.insert(passenger); + } + return true; +} + +bool Transport::RemovePassenger(Player* passenger) +{ + if (m_passengers.find(passenger) != m_passengers.end()) + { + sLog.outDetail("Player %s removed from transport %s.", passenger->GetName(), this->m_name.c_str()); + m_passengers.erase(passenger); + } + return true; +} + +void Transport::Update(uint32 /*p_time*/) +{ + if (m_WayPoints.size() <= 1) + return; + + m_timer = getMSTime() % m_period; + while (((m_timer - m_curr->first) % m_pathTime) > ((m_next->first - m_curr->first) % m_pathTime)) + { + m_curr = GetNextWayPoint(); + m_next = GetNextWayPoint(); + + // first check help in case client-server transport coordinates de-synchronization + if (m_curr->second.mapid != GetMapId() || m_curr->second.teleport) + { + TeleportTransport(m_curr->second.mapid, m_curr->second.x, m_curr->second.y, m_curr->second.z); + } + else + { + //MapManager::Instance().GetMap(m_curr->second.mapid)->GameobjectRelocation((GameObject *)this, m_curr->second.x, m_curr->second.y, m_curr->second.z, this->m_orientation); + Relocate(m_curr->second.x, m_curr->second.y, m_curr->second.z); + } + + /* + for(PlayerSet::iterator itr = m_passengers.begin(); itr != m_passengers.end();) + { + PlayerSet::iterator it2 = itr; + ++itr; + //(*it2)->SetPosition( m_curr->second.x + (*it2)->GetTransOffsetX(), m_curr->second.y + (*it2)->GetTransOffsetY(), m_curr->second.z + (*it2)->GetTransOffsetZ(), (*it2)->GetTransOffsetO() ); + } + */ + + m_nextNodeTime = m_curr->first; + + if (m_curr == m_WayPoints.begin() && (sLog.getLogFilter() & LOG_FILTER_TRANSPORT_MOVES)==0) + sLog.outDetail(" ************ BEGIN ************** %s", this->m_name.c_str()); + + // MapManager::Instance().GetMap(m_curr->second.mapid)->Add(&this); // -> // ->Add(t); + //MapManager::Instance().GetMap(m_curr->second.mapid)->Remove((GameObject *)this, false); // -> // ->Add(t); + //MapManager::Instance().GetMap(m_curr->second.mapid)->Add((GameObject *)this); // -> // ->Add(t); + + if ((sLog.getLogFilter() & LOG_FILTER_TRANSPORT_MOVES)==0) + sLog.outDetail("%s moved to %f %f %f %d", this->m_name.c_str(), m_curr->second.x, m_curr->second.y, m_curr->second.z, m_curr->second.mapid); + } +} diff --git a/src/game/Transports.h b/src/game/Transports.h new file mode 100644 index 00000000000..e104012c850 --- /dev/null +++ b/src/game/Transports.h @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRANSPORTS_H +#define TRANSPORTS_H + +#include "GameObject.h" + +#include +#include +#include + +class TransportPath +{ + public: + struct PathNode + { + uint32 mapid; + float x,y,z; + uint32 actionFlag; + uint32 delay; + }; + + inline void SetLength(const unsigned int sz) + { + i_nodes.resize( sz ); + } + + inline unsigned int Size(void) const { return i_nodes.size(); } + inline bool Empty(void) const { return i_nodes.empty(); } + inline void Resize(unsigned int sz) { i_nodes.resize(sz); } + inline void Clear(void) { i_nodes.clear(); } + inline PathNode* GetNodes(void) { return static_cast(&i_nodes[0]); } + + PathNode& operator[](const unsigned int idx) { return i_nodes[idx]; } + const PathNode& operator()(const unsigned int idx) const { return i_nodes[idx]; } + + protected: + std::vector i_nodes; +}; + +class Transport : private GameObject +{ + public: + explicit Transport(); + + // prevent using Transports as normal GO, but allow call some inherited functions + using GameObject::IsTransport; + using GameObject::GetEntry; + using GameObject::GetGUID; + using GameObject::GetGUIDLow; + using GameObject::GetMapId; + using GameObject::GetPositionX; + using GameObject::GetPositionY; + using GameObject::GetPositionZ; + using GameObject::BuildCreateUpdateBlockForPlayer; + using GameObject::BuildOutOfRangeUpdateBlock; + + bool Create(uint32 guidlow, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress, uint32 dynflags); + bool GenerateWaypoints(uint32 pathid, std::set &mapids); + void Update(uint32 p_time); + bool AddPassenger(Player* passenger); + bool RemovePassenger(Player* passenger); + + typedef std::set PlayerSet; + PlayerSet const& GetPassengers() const { return m_passengers; } + + std::string m_name; + private: + struct WayPoint + { + WayPoint() : mapid(0), x(0), y(0), z(0), teleport(false) {} + WayPoint(uint32 _mapid, float _x, float _y, float _z, bool _teleport) : + mapid(_mapid), x(_x), y(_y), z(_z), teleport(_teleport) {} + uint32 mapid; + float x; + float y; + float z; + bool teleport; + }; + + typedef std::map WayPointMap; + + WayPointMap::iterator m_curr; + WayPointMap::iterator m_next; + uint32 m_pathTime; + uint32 m_timer; + + PlayerSet m_passengers; + + public: + WayPointMap m_WayPoints; + uint32 m_nextNodeTime; + uint32 m_period; + + private: + void TeleportTransport(uint32 newMapid, float x, float y, float z); + WayPointMap::iterator GetNextWayPoint(); +}; +#endif diff --git a/src/game/Traveller.h b/src/game/Traveller.h new file mode 100644 index 00000000000..07a02bb3056 --- /dev/null +++ b/src/game/Traveller.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_TRAVELLER_H +#define MANGOS_TRAVELLER_H + +#include "MapManager.h" +#include "Creature.h" +#include "Player.h" +#include + +/** Traveller is a wrapper for units (creatures or players) that + * travel from point A to point B using the destination holder. + */ +#define PLAYER_FLIGHT_SPEED 32.0f + +template +struct MANGOS_DLL_DECL Traveller +{ + T &i_traveller; + Traveller(T &t) : i_traveller(t) {} + Traveller(const Traveller &obj) : i_traveller(obj) {} + Traveller& operator=(const Traveller &obj) + { + this->~Traveller(); + new (this) Traveller(obj); + return *this; + } + + operator T&(void) { return i_traveller; } + operator const T&(void) { return i_traveller; } + inline float GetPositionX() const { return i_traveller.GetPositionX(); } + inline float GetPositionY() const { return i_traveller.GetPositionY(); } + inline float GetPositionZ() const { return i_traveller.GetPositionZ(); } + inline T& GetTraveller(void) { return i_traveller; } + + float Speed(void) { assert(false); return 0.0f; } + void Relocation(float x, float y, float z, float orientation) {} + void Relocation(float x, float y, float z) { Relocation(x, y, z, i_traveller.GetOrientation()); } + void MoveTo(float x, float y, float z, uint32 t) {} +}; + +// specialization for creatures +template<> +inline float Traveller::Speed() +{ + return i_traveller.GetSpeed( i_traveller.HasUnitMovementFlag(MOVEMENTFLAG_WALK_MODE) ? MOVE_WALK : MOVE_RUN); +} + +template<> +inline void Traveller::Relocation(float x, float y, float z, float orientation) +{ + MapManager::Instance().GetMap(i_traveller.GetMapId(), &i_traveller)->CreatureRelocation(&i_traveller, x, y, z, orientation); +} + +template<> +inline void Traveller::MoveTo(float x, float y, float z, uint32 t) +{ + i_traveller.AI_SendMoveToPacket(x, y, z, t, i_traveller.GetUnitMovementFlags(), 0); +} + +// specialization for players +template<> +inline float Traveller::Speed() +{ + if (i_traveller.isInFlight()) + return PLAYER_FLIGHT_SPEED; + else + return i_traveller.GetSpeed(i_traveller.HasUnitMovementFlag(MOVEMENTFLAG_WALK_MODE) ? MOVE_WALK : MOVE_RUN); +} + +template<> +inline void Traveller::Relocation(float x, float y, float z, float orientation) +{ + MapManager::Instance().GetMap(i_traveller.GetMapId(), &i_traveller)->PlayerRelocation(&i_traveller, x, y, z, orientation); +} + +template<> +inline void Traveller::MoveTo(float x, float y, float z, uint32 t) +{ + //Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags + i_traveller.SendMonsterMove(x, y, z, 0, MOVEMENTFLAG_WALK_MODE, t); +} + +typedef Traveller CreatureTraveller; +typedef Traveller PlayerTraveller; +#endif diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp new file mode 100644 index 00000000000..442dbc1057b --- /dev/null +++ b/src/game/Unit.cpp @@ -0,0 +1,10808 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Log.h" +#include "Opcodes.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "World.h" +#include "ObjectMgr.h" +#include "SpellMgr.h" +#include "Unit.h" +#include "QuestDef.h" +#include "Player.h" +#include "Creature.h" +#include "Spell.h" +#include "Group.h" +#include "SpellAuras.h" +#include "MapManager.h" +#include "ObjectAccessor.h" +#include "CreatureAI.h" +#include "Formulas.h" +#include "Pet.h" +#include "Util.h" +#include "Totem.h" +#include "BattleGround.h" +#include "InstanceSaveMgr.h" +#include "GridNotifiersImpl.h" +#include "CellImpl.h" +#include "Path.h" + +#include + +float baseMoveSpeed[MAX_MOVE_TYPE] = +{ + 2.5f, // MOVE_WALK + 7.0f, // MOVE_RUN + 1.25f, // MOVE_WALKBACK + 4.722222f, // MOVE_SWIM + 4.5f, // MOVE_SWIMBACK + 3.141594f, // MOVE_TURN + 7.0f, // MOVE_FLY + 4.5f, // MOVE_FLYBACK +}; + +// auraTypes contains attacker auras capable of proc'ing cast auras +static Unit::AuraTypeSet GenerateAttakerProcCastAuraTypes() +{ + static Unit::AuraTypeSet auraTypes; + auraTypes.insert(SPELL_AURA_DUMMY); + auraTypes.insert(SPELL_AURA_PROC_TRIGGER_SPELL); + auraTypes.insert(SPELL_AURA_MOD_HASTE); + auraTypes.insert(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + return auraTypes; +} + +// auraTypes contains victim auras capable of proc'ing cast auras +static Unit::AuraTypeSet GenerateVictimProcCastAuraTypes() +{ + static Unit::AuraTypeSet auraTypes; + auraTypes.insert(SPELL_AURA_DUMMY); + auraTypes.insert(SPELL_AURA_PRAYER_OF_MENDING); + auraTypes.insert(SPELL_AURA_PROC_TRIGGER_SPELL); + return auraTypes; +} + +// auraTypes contains auras capable of proc effect/damage (but not cast) for attacker +static Unit::AuraTypeSet GenerateAttakerProcEffectAuraTypes() +{ + static Unit::AuraTypeSet auraTypes; + auraTypes.insert(SPELL_AURA_MOD_DAMAGE_DONE); + auraTypes.insert(SPELL_AURA_PROC_TRIGGER_DAMAGE); + auraTypes.insert(SPELL_AURA_MOD_CASTING_SPEED); + auraTypes.insert(SPELL_AURA_MOD_RATING); + return auraTypes; +} + +// auraTypes contains auras capable of proc effect/damage (but not cast) for victim +static Unit::AuraTypeSet GenerateVictimProcEffectAuraTypes() +{ + static Unit::AuraTypeSet auraTypes; + auraTypes.insert(SPELL_AURA_MOD_RESISTANCE); + auraTypes.insert(SPELL_AURA_PROC_TRIGGER_DAMAGE); + auraTypes.insert(SPELL_AURA_MOD_PARRY_PERCENT); + auraTypes.insert(SPELL_AURA_MOD_BLOCK_PERCENT); + auraTypes.insert(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN); + return auraTypes; +} + +static Unit::AuraTypeSet attackerProcCastAuraTypes = GenerateAttakerProcCastAuraTypes(); +static Unit::AuraTypeSet attackerProcEffectAuraTypes = GenerateAttakerProcEffectAuraTypes(); + +static Unit::AuraTypeSet victimProcCastAuraTypes = GenerateVictimProcCastAuraTypes(); +static Unit::AuraTypeSet victimProcEffectAuraTypes = GenerateVictimProcEffectAuraTypes(); + +// auraTypes contains auras capable of proc'ing for attacker and victim +static Unit::AuraTypeSet GenerateProcAuraTypes() +{ + Unit::AuraTypeSet auraTypes; + auraTypes.insert(attackerProcCastAuraTypes.begin(),attackerProcCastAuraTypes.end()); + auraTypes.insert(attackerProcEffectAuraTypes.begin(),attackerProcEffectAuraTypes.end()); + auraTypes.insert(victimProcCastAuraTypes.begin(),victimProcCastAuraTypes.end()); + auraTypes.insert(victimProcEffectAuraTypes.begin(),victimProcEffectAuraTypes.end()); + return auraTypes; +} + +static Unit::AuraTypeSet procAuraTypes = GenerateProcAuraTypes(); + +bool IsPassiveStackableSpell( uint32 spellId ) +{ + if(!IsPassiveSpell(spellId)) + return false; + + SpellEntry const* spellProto = sSpellStore.LookupEntry(spellId); + if(!spellProto) + return false; + + for(int j = 0; j < 3; ++j) + { + if(std::find(procAuraTypes.begin(),procAuraTypes.end(),spellProto->EffectApplyAuraName[j])!=procAuraTypes.end()) + return false; + } + + return true; +} + +Unit::Unit() +: WorldObject(), i_motionMaster(this), m_ThreatManager(this), m_HostilRefManager(this) +{ + m_objectType |= TYPEMASK_UNIT; + m_objectTypeId = TYPEID_UNIT; + // 2.3.2 - 0x70 + m_updateFlag = (UPDATEFLAG_HIGHGUID | UPDATEFLAG_LIVING | UPDATEFLAG_HASPOSITION); + + m_attackTimer[BASE_ATTACK] = 0; + m_attackTimer[OFF_ATTACK] = 0; + m_attackTimer[RANGED_ATTACK] = 0; + m_modAttackSpeedPct[BASE_ATTACK] = 1.0f; + m_modAttackSpeedPct[OFF_ATTACK] = 1.0f; + m_modAttackSpeedPct[RANGED_ATTACK] = 1.0f; + + m_extraAttacks = 0; + + m_state = 0; + m_form = FORM_NONE; + m_deathState = ALIVE; + + for (uint32 i = 0; i < CURRENT_MAX_SPELL; i++) + m_currentSpells[i] = NULL; + + m_addDmgOnce = 0; + + for(int i = 0; i < MAX_TOTEM; ++i) + m_TotemSlot[i] = 0; + + m_ObjectSlot[0] = m_ObjectSlot[1] = m_ObjectSlot[2] = m_ObjectSlot[3] = 0; + //m_Aura = NULL; + //m_AurasCheck = 2000; + //m_removeAuraTimer = 4; + //tmpAura = NULL; + waterbreath = false; + + m_Visibility = VISIBILITY_ON; + + m_detectInvisibilityMask = 0; + m_invisibilityMask = 0; + m_transform = 0; + m_ShapeShiftFormSpellId = 0; + m_canModifyStats = false; + + for (int i = 0; i < MAX_SPELL_IMMUNITY; i++) + m_spellImmune[i].clear(); + for (int i = 0; i < UNIT_MOD_END; i++) + { + m_auraModifiersGroup[i][BASE_VALUE] = 0.0f; + m_auraModifiersGroup[i][BASE_PCT] = 1.0f; + m_auraModifiersGroup[i][TOTAL_VALUE] = 0.0f; + m_auraModifiersGroup[i][TOTAL_PCT] = 1.0f; + } + // implement 50% base damage from offhand + m_auraModifiersGroup[UNIT_MOD_DAMAGE_OFFHAND][TOTAL_PCT] = 0.5f; + + for (int i = 0; i < 3; i++) + { + m_weaponDamage[i][MINDAMAGE] = BASE_MINDAMAGE; + m_weaponDamage[i][MAXDAMAGE] = BASE_MAXDAMAGE; + } + for (int i = 0; i < MAX_STATS; i++) + m_createStats[i] = 0.0f; + + m_attacking = NULL; + m_modMeleeHitChance = 0.0f; + m_modRangedHitChance = 0.0f; + m_modSpellHitChance = 0.0f; + m_baseSpellCritChance = 5; + + m_CombatTimer = 0; + m_lastManaUse = 0; + + //m_victimThreat = 0.0f; + for (int i = 0; i < MAX_SPELL_SCHOOL; ++i) + m_threatModifier[i] = 1.0f; + m_isSorted = true; + for (int i = 0; i < MAX_MOVE_TYPE; ++i) + m_speed_rate[i] = 1.0f; + + m_removedAuras = 0; + m_charmInfo = NULL; + m_unit_movement_flags = 0; + + // remove aurastates allowing special moves + for(int i=0; i < MAX_REACTIVE; ++i) + m_reactiveTimer[i] = 0; +} + +Unit::~Unit() +{ + // set current spells as deletable + for (uint32 i = 0; i < CURRENT_MAX_SPELL; i++) + { + // spell may be safely deleted now + if (m_currentSpells[i]) m_currentSpells[i]->SetDeletable(true); + m_currentSpells[i] = NULL; + } + + RemoveAllGameObjects(); + RemoveAllDynObjects(); + + if(m_charmInfo) delete m_charmInfo; +} + +void Unit::Update( uint32 p_time ) +{ + /*if(p_time > m_AurasCheck) + { + m_AurasCheck = 2000; + _UpdateAura(); + }else + m_AurasCheck -= p_time;*/ + + // WARNING! Order of execution here is important, do not change. + // Spells must be processed with event system BEFORE they go to _UpdateSpells. + // Or else we may have some SPELL_STATE_FINISHED spells stalled in pointers, that is bad. + m_Events.Update( p_time ); + _UpdateSpells( p_time ); + + // update combat timer only for players and pets + if (isInCombat() && (GetTypeId() == TYPEID_PLAYER || ((Creature*)this)->isPet() || ((Creature*)this)->isCharmed())) + { + // Check UNIT_STAT_MELEE_ATTACKING or UNIT_STAT_CHASE (without UNIT_STAT_FOLLOW in this case) so pets can reach far away + // targets without stopping half way there and running off. + // These flags are reset after target dies or another command is given. + if( m_HostilRefManager.isEmpty() ) + { + // m_CombatTimer set at aura start and it will be freeze until aura removing + if ( m_CombatTimer <= p_time ) + ClearInCombat(); + else + m_CombatTimer -= p_time; + } + } + + if(uint32 base_att = getAttackTimer(BASE_ATTACK)) + { + setAttackTimer(BASE_ATTACK, (p_time >= base_att ? 0 : base_att - p_time) ); + } + + // update abilities available only for fraction of time + UpdateReactives( p_time ); + + ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, GetHealth() < GetMaxHealth()*0.20f); + ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, GetHealth() < GetMaxHealth()*0.35f); + + i_motionMaster.UpdateMotion(p_time); +} + +bool Unit::haveOffhandWeapon() const +{ + if(GetTypeId() == TYPEID_PLAYER) + return ((Player*)this)->GetWeaponForAttack(OFF_ATTACK,true); + else + return false; +} + +void Unit::SendMonsterMoveWithSpeedToCurrentDestination(Player* player) +{ + float x, y, z; + if(GetMotionMaster()->GetDestination(x, y, z)) + SendMonsterMoveWithSpeed(x, y, z, GetUnitMovementFlags(), 0, player); +} + +void Unit::SendMonsterMoveWithSpeed(float x, float y, float z, uint32 MovementFlags, uint32 transitTime, Player* player) +{ + if (!transitTime) + { + float dx = x - GetPositionX(); + float dy = y - GetPositionY(); + float dz = z - GetPositionZ(); + + float dist = ((dx*dx) + (dy*dy) + (dz*dz)); + if(dist<0) + dist = 0; + else + dist = sqrt(dist); + + double speed = GetSpeed((MovementFlags & MOVEMENTFLAG_WALK_MODE) ? MOVE_WALK : MOVE_RUN); + if(speed<=0) + speed = 2.5f; + speed *= 0.001f; + transitTime = static_cast(dist / speed + 0.5); + } + //float orientation = (float)atan2((double)dy, (double)dx); + SendMonsterMove(x, y, z, 0, MovementFlags, transitTime, player); +} + +void Unit::SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, uint32 MovementFlags, uint32 Time, Player* player) +{ + WorldPacket data( SMSG_MONSTER_MOVE, (41 + GetPackGUID().size()) ); + data.append(GetPackGUID()); + + // Point A, starting location + data << GetPositionX() << GetPositionY() << GetPositionZ(); + // unknown field - unrelated to orientation + // seems to increment about 1000 for every 1.7 seconds + // for now, we'll just use mstime + data << getMSTime(); + + data << uint8(type); // unknown + switch(type) + { + case 0: // normal packet + break; + case 1: // stop packet + SendMessageToSet( &data, true ); + return; + case 3: // not used currently + data << uint64(0); // probably target guid + break; + case 4: // not used currently + data << float(0); // probably orientation + break; + } + + //Movement Flags (0x0 = walk, 0x100 = run, 0x200 = fly/swim) + data << uint32(MovementFlags); + + data << Time; // Time in between points + data << uint32(1); // 1 single waypoint + data << NewPosX << NewPosY << NewPosZ; // the single waypoint Point B + + if(player) + player->GetSession()->SendPacket(&data); + else + SendMessageToSet( &data, true ); +} + +void Unit::SendMonsterMoveByPath(Path const& path, uint32 start, uint32 end, uint32 MovementFlags) +{ + uint32 traveltime = uint32(path.GetTotalLength(start, end) * 32); + + uint32 pathSize = end-start; + + WorldPacket data( SMSG_MONSTER_MOVE, (GetPackGUID().size()+4+4+4+4+1+4+4+4+pathSize*4*3) ); + data.append(GetPackGUID()); + data << GetPositionX( ) + << GetPositionY( ) + << GetPositionZ( ); + data << GetOrientation( ); + data << uint8( 0 ); + data << uint32( MovementFlags ); + data << uint32( traveltime ); + data << uint32( pathSize ); + data.append( (char*)path.GetNodes(start), pathSize * 4 * 3 ); + + //WPAssert( data.size() == 37 + pathnodes.Size( ) * 4 * 3 ); + SendMessageToSet(&data, true); +} + +void Unit::resetAttackTimer(WeaponAttackType type) +{ + m_attackTimer[type] = uint32(GetAttackTime(type) * m_modAttackSpeedPct[type]); +} + +bool Unit::canReachWithAttack(Unit *pVictim) const +{ + assert(pVictim); + float reach = GetFloatValue(UNIT_FIELD_COMBATREACH); + if( reach <= 0.0f ) + reach = 1.0f; + return IsWithinDistInMap(pVictim, reach); +} + +void Unit::RemoveSpellsCausingAura(AuraType auraType) +{ + if (auraType >= TOTAL_AURAS) return; + AuraList::iterator iter, next; + for (iter = m_modAuras[auraType].begin(); iter != m_modAuras[auraType].end(); iter = next) + { + next = iter; + ++next; + + if (*iter) + { + RemoveAurasDueToSpell((*iter)->GetId()); + if (!m_modAuras[auraType].empty()) + next = m_modAuras[auraType].begin(); + else + return; + } + } +} + +bool Unit::HasAuraType(AuraType auraType) const +{ + return (!m_modAuras[auraType].empty()); +} + +/* Called by DealDamage for auras that have a chance to be dispelled on damage taken. */ +void Unit::RemoveSpellbyDamageTaken(AuraType auraType, uint32 damage) +{ + if(!HasAuraType(auraType)) + return; + + // The chance to dispell an aura depends on the damage taken with respect to the casters level. + uint32 max_dmg = getLevel() > 8 ? 25 * getLevel() - 150 : 50; + float chance = float(damage) / max_dmg * 100.0f; + if (roll_chance_f(chance)) + RemoveSpellsCausingAura(auraType); +} + +uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellEntry const *spellProto, bool durabilityLoss) +{ + if (!pVictim->isAlive() || pVictim->isInFlight() || pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode()) + return 0; + + //You don't lose health from damage taken from another player while in a sanctuary + //You still see it in the combat log though + if(pVictim != this && GetTypeId() == TYPEID_PLAYER && pVictim->GetTypeId() == TYPEID_PLAYER) + { + const AreaTableEntry *area = GetAreaEntryByAreaID(pVictim->GetAreaId()); + if(area && area->flags & AREA_FLAG_SANCTUARY) //sanctuary + return 0; + } + + // remove affects from victim (including from 0 damage and DoTs) + if(pVictim != this) + pVictim->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + // remove affects from attacker at any non-DoT damage (including 0 damage) + if( damagetype != DOT) + { + RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + if(pVictim != this) + RemoveSpellsCausingAura(SPELL_AURA_MOD_INVISIBILITY); + + if(pVictim->GetTypeId() == TYPEID_PLAYER && !pVictim->IsStandState() && !pVictim->hasUnitState(UNIT_STAT_STUNDED)) + pVictim->SetStandState(PLAYER_STATE_NONE); + } + + //Script Event damage Deal + if( GetTypeId()== TYPEID_UNIT && ((Creature *)this)->AI()) + ((Creature *)this)->AI()->DamageDeal(pVictim, damage); + //Script Event damage taken + if( pVictim->GetTypeId()== TYPEID_UNIT && ((Creature *)pVictim)->AI() ) + ((Creature *)pVictim)->AI()->DamageTaken(this, damage); + + if(!damage) + { + // Rage from physical damage received . + if(cleanDamage && cleanDamage->damage && (damageSchoolMask & SPELL_SCHOOL_MASK_NORMAL) && pVictim->GetTypeId() == TYPEID_PLAYER && (pVictim->getPowerType() == POWER_RAGE)) + ((Player*)pVictim)->RewardRage(cleanDamage->damage, 0, false); + + return 0; + } + + pVictim->RemoveSpellbyDamageTaken(SPELL_AURA_MOD_FEAR, damage); + // root type spells do not dispell the root effect + if(!spellProto || spellProto->Mechanic != MECHANIC_ROOT) + pVictim->RemoveSpellbyDamageTaken(SPELL_AURA_MOD_ROOT, damage); + + if(pVictim->GetTypeId() != TYPEID_PLAYER) + { + // no xp,health if type 8 /critters/ + if ( pVictim->GetCreatureType() == CREATURE_TYPE_CRITTER) + { + pVictim->setDeathState(JUST_DIED); + pVictim->SetHealth(0); + + // allow loot only if has loot_id in creature_template + CreatureInfo const* cInfo = ((Creature*)pVictim)->GetCreatureInfo(); + if(cInfo && cInfo->lootid) + pVictim->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + + // some critters required for quests + if(GetTypeId() == TYPEID_PLAYER) + ((Player*)this)->KilledMonster(pVictim->GetEntry(),pVictim->GetGUID()); + + return damage; + } + + if(!pVictim->isInCombat() && ((Creature*)pVictim)->AI()) + ((Creature*)pVictim)->AI()->AttackStart(this); + } + + DEBUG_LOG("DealDamageStart"); + + uint32 health = pVictim->GetHealth(); + sLog.outDetail("deal dmg:%d to health:%d ",damage,health); + + // duel ends when player has 1 or less hp + bool duel_hasEnded = false; + if(pVictim->GetTypeId() == TYPEID_PLAYER && ((Player*)pVictim)->duel && damage >= (health-1)) + { + // prevent kill only if killed in duel and killed by opponent or opponent controlled creature + if(((Player*)pVictim)->duel->opponent==this || ((Player*)pVictim)->duel->opponent->GetGUID() == GetOwnerGUID()) + damage = health-1; + + duel_hasEnded = true; + } + //Get in CombatState + if(pVictim != this && damagetype != DOT) + { + SetInCombatWith(pVictim); + pVictim->SetInCombatWith(this); + + if(Player* attackedPlayer = pVictim->GetCharmerOrOwnerPlayerOrPlayerItself()) + SetContestedPvP(attackedPlayer); + } + + // Rage from Damage made (only from direct weapon damage) + if( cleanDamage && damagetype==DIRECT_DAMAGE && this != pVictim && GetTypeId() == TYPEID_PLAYER && (getPowerType() == POWER_RAGE)) + { + uint32 weaponSpeedHitFactor; + + switch(cleanDamage->attackType) + { + case BASE_ATTACK: + { + if(cleanDamage->hitOutCome == MELEE_HIT_CRIT) + weaponSpeedHitFactor = uint32(GetAttackTime(cleanDamage->attackType)/1000.0f * 7); + else + weaponSpeedHitFactor = uint32(GetAttackTime(cleanDamage->attackType)/1000.0f * 3.5f); + + ((Player*)this)->RewardRage(damage, weaponSpeedHitFactor, true); + + break; + } + case OFF_ATTACK: + { + if(cleanDamage->hitOutCome == MELEE_HIT_CRIT) + weaponSpeedHitFactor = uint32(GetAttackTime(cleanDamage->attackType)/1000.0f * 3.5f); + else + weaponSpeedHitFactor = uint32(GetAttackTime(cleanDamage->attackType)/1000.0f * 1.75f); + + ((Player*)this)->RewardRage(damage, weaponSpeedHitFactor, true); + + break; + } + case RANGED_ATTACK: + break; + } + } + + if(pVictim->GetTypeId() == TYPEID_PLAYER && GetTypeId() == TYPEID_PLAYER) + { + if(((Player*)pVictim)->InBattleGround()) + { + Player *killer = ((Player*)this); + if(killer != ((Player*)pVictim)) + if(BattleGround *bg = killer->GetBattleGround()) + bg->UpdatePlayerScore(killer, SCORE_DAMAGE_DONE, damage); + } + } + + if (pVictim->GetTypeId() == TYPEID_UNIT && !((Creature*)pVictim)->isPet() && !((Creature*)pVictim)->hasLootRecipient()) + ((Creature*)pVictim)->SetLootRecipient(this); + if (health <= damage) + { + // battleground things + if(pVictim->GetTypeId() == TYPEID_PLAYER && (((Player*)pVictim)->InBattleGround())) + { + Player *killed = ((Player*)pVictim); + Player *killer = NULL; + if(GetTypeId() == TYPEID_PLAYER) + killer = ((Player*)this); + else if(GetTypeId() == TYPEID_UNIT && ((Creature*)this)->isPet()) + { + Unit *owner = GetOwner(); + if(owner && owner->GetTypeId() == TYPEID_PLAYER) + killer = ((Player*)owner); + } + + if(killer) + if(BattleGround *bg = killed->GetBattleGround()) + bg->HandleKillPlayer(killed, killer); // drop flags and etc + } + + DEBUG_LOG("DealDamage: victim just died"); + + // find player: owner of controlled `this` or `this` itself maybe + Player *player = GetCharmerOrOwnerPlayerOrPlayerItself(); + + if(pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->GetLootRecipient()) + player = ((Creature*)pVictim)->GetLootRecipient(); + // Reward player, his pets, and group/raid members + // call kill spell proc event (before real die and combat stop to triggering auras removed at death/combat stop) + if(player && player!=pVictim) + if(player->RewardPlayerAndGroupAtKill(pVictim)) + player->ProcDamageAndSpell(pVictim,PROC_FLAG_KILL_XP_GIVER,PROC_FLAG_NONE); + + DEBUG_LOG("DealDamageAttackStop"); + + // stop combat + pVictim->CombatStop(); + pVictim->getHostilRefManager().deleteReferences(); + + bool damageFromSpiritOfRedemtionTalent = spellProto && spellProto->Id == 27795; + + // if talent known but not triggered (check priest class for speedup check) + Aura* spiritOfRedemtionTalentReady = NULL; + if( !damageFromSpiritOfRedemtionTalent && // not called from SPELL_AURA_SPIRIT_OF_REDEMPTION + pVictim->GetTypeId()==TYPEID_PLAYER && pVictim->getClass()==CLASS_PRIEST ) + { + AuraList const& vDummyAuras = pVictim->GetAurasByType(SPELL_AURA_DUMMY); + for(AuraList::const_iterator itr = vDummyAuras.begin(); itr != vDummyAuras.end(); ++itr) + { + if((*itr)->GetSpellProto()->SpellIconID==1654) + { + spiritOfRedemtionTalentReady = *itr; + break; + } + } + } + + DEBUG_LOG("SET JUST_DIED"); + if(!spiritOfRedemtionTalentReady) + pVictim->setDeathState(JUST_DIED); + + DEBUG_LOG("DealDamageHealth1"); + + if(spiritOfRedemtionTalentReady) + { + // save value before aura remove + uint32 ressSpellId = pVictim->GetUInt32Value(PLAYER_SELF_RES_SPELL); + if(!ressSpellId) + ressSpellId = ((Player*)pVictim)->GetResurrectionSpellId(); + + //Remove all expected to remove at death auras (most important negative case like DoT or periodic triggers) + pVictim->RemoveAllAurasOnDeath(); + + // restore for use at real death + pVictim->SetUInt32Value(PLAYER_SELF_RES_SPELL,ressSpellId); + + // FORM_SPIRITOFREDEMPTION and related auras + pVictim->CastSpell(pVictim,27827,true,NULL,spiritOfRedemtionTalentReady); + } + else + pVictim->SetHealth(0); + + // remember victim PvP death for corpse type and corpse reclaim delay + // at original death (not at SpiritOfRedemtionTalent timeout) + if( pVictim->GetTypeId()==TYPEID_PLAYER && !damageFromSpiritOfRedemtionTalent ) + ((Player*)pVictim)->SetPvPDeath(player!=NULL); + + // Call KilledUnit for creatures + if (GetTypeId() == TYPEID_UNIT && ((Creature*)this)->AI()) + ((Creature*)this)->AI()->KilledUnit(pVictim); + + // 10% durability loss on death + // clean InHateListOf + if (pVictim->GetTypeId() == TYPEID_PLAYER) + { + // only if not player and not controlled by player pet. And not at BG + if (durabilityLoss && !player && !((Player*)pVictim)->InBattleGround()) + { + DEBUG_LOG("We are dead, loosing 10 percents durability"); + ((Player*)pVictim)->DurabilityLossAll(0.10f,false); + // durability lost message + WorldPacket data(SMSG_DURABILITY_DAMAGE_DEATH, 0); + ((Player*)pVictim)->GetSession()->SendPacket(&data); + } + } + else // creature died + { + DEBUG_LOG("DealDamageNotPlayer"); + Creature *cVictim = (Creature*)pVictim; + + if(!cVictim->isPet()) + { + cVictim->DeleteThreatList(); + cVictim->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + // Call creature just died function + if (cVictim->AI()) + cVictim->AI()->JustDied(this); + + // Dungeon specific stuff, only applies to players killing creatures + if(cVictim->GetInstanceId()) + { + Map *m = cVictim->GetMap(); + Player *creditedPlayer = GetCharmerOrOwnerPlayerOrPlayerItself(); + // TODO: do instance binding anyway if the charmer/owner is offline + + if(m->IsDungeon() && creditedPlayer) + { + if(m->IsRaid() || m->IsHeroic()) + { + if(cVictim->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_INSTANCE_BIND) + ((InstanceMap *)m)->PermBindAllPlayers(creditedPlayer); + } + else + { + // the reset time is set but not added to the scheduler + // until the players leave the instance + time_t resettime = cVictim->GetRespawnTimeEx() + 2 * HOUR; + if(InstanceSave *save = sInstanceSaveManager.GetInstanceSave(cVictim->GetInstanceId())) + if(save->GetResetTime() < resettime) save->SetResetTime(resettime); + } + } + } + } + + // last damage from non duel opponent or opponent controlled creature + if(duel_hasEnded) + { + assert(pVictim->GetTypeId()==TYPEID_PLAYER); + Player *he = (Player*)pVictim; + + assert(he->duel); + + he->duel->opponent->CombatStopWithPets(true); + he->CombatStopWithPets(true); + + he->DuelComplete(DUEL_INTERUPTED); + } + } + else // if (health <= damage) + { + DEBUG_LOG("DealDamageAlive"); + + pVictim->ModifyHealth(- (int32)damage); + + // Check if health is below 20% (apply damage before to prevent case when after ProcDamageAndSpell health < damage + if(pVictim->GetHealth()*5 < pVictim->GetMaxHealth()) + { + uint32 procVictim = PROC_FLAG_NONE; + + // if just dropped below 20% (for CheatDeath) + if((pVictim->GetHealth()+damage)*5 > pVictim->GetMaxHealth()) + procVictim = PROC_FLAG_LOW_HEALTH; + + ProcDamageAndSpell(pVictim,PROC_FLAG_TARGET_LOW_HEALTH,procVictim); + } + + if(damagetype != DOT) + { + if(getVictim()) + { + // if have target and damage pVictim just call AI recation + if(pVictim != getVictim() && pVictim->GetTypeId()==TYPEID_UNIT && ((Creature*)pVictim)->AI()) + ((Creature*)pVictim)->AI()->AttackedBy(this); + } + else + { + // if not have main target then attack state with target (including AI call) + //start melee attacks only after melee hit + Attack(pVictim,(damagetype == DIRECT_DAMAGE)); + } + } + + // polymorphed and other negative transformed cases + if(pVictim->getTransForm() && pVictim->hasUnitState(UNIT_STAT_CONFUSED)) + pVictim->RemoveAurasDueToSpell(pVictim->getTransForm()); + + if(damagetype == DIRECT_DAMAGE|| damagetype == SPELL_DIRECT_DAMAGE) + pVictim->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_DIRECT_DAMAGE); + + if (pVictim->GetTypeId() != TYPEID_PLAYER) + { + if(spellProto && IsDamageToThreatSpell(spellProto)) + pVictim->AddThreat(this, damage*2, damageSchoolMask, spellProto); + else + pVictim->AddThreat(this, damage, damageSchoolMask, spellProto); + } + else // victim is a player + { + // Rage from damage received + if(this != pVictim && pVictim->getPowerType() == POWER_RAGE) + { + uint32 rage_damage = damage + (cleanDamage ? cleanDamage->damage : 0); + ((Player*)pVictim)->RewardRage(rage_damage, 0, false); + } + + // random durability for items (HIT TAKEN) + if (roll_chance_f(sWorld.getRate(RATE_DURABILITY_LOSS_DAMAGE))) + { + EquipmentSlots slot = EquipmentSlots(urand(0,EQUIPMENT_SLOT_END-1)); + ((Player*)pVictim)->DurabilityPointLossForEquipSlot(slot); + } + } + + if(GetTypeId()==TYPEID_PLAYER) + { + // random durability for items (HIT DONE) + if (roll_chance_f(sWorld.getRate(RATE_DURABILITY_LOSS_DAMAGE))) + { + EquipmentSlots slot = EquipmentSlots(urand(0,EQUIPMENT_SLOT_END-1)); + ((Player*)this)->DurabilityPointLossForEquipSlot(slot); + } + } + + // TODO: Store auras by interrupt flag to speed this up. + AuraMap& vAuras = pVictim->GetAuras(); + for (AuraMap::iterator i = vAuras.begin(), next; i != vAuras.end(); i = next) + { + const SpellEntry *se = i->second->GetSpellProto(); + next = i; ++next; + if( se->AuraInterruptFlags & AURA_INTERRUPT_FLAG_DAMAGE ) + { + bool remove = true; + if (se->procFlags & (1<<3)) + { + if (!roll_chance_i(se->procChance)) + remove = false; + } + if (remove) + { + pVictim->RemoveAurasDueToSpell(i->second->GetId()); + // FIXME: this may cause the auras with proc chance to be rerolled several times + next = vAuras.begin(); + } + } + } + + if (damagetype != NODAMAGE && damage && pVictim->GetTypeId() == TYPEID_PLAYER) + { + if( damagetype != DOT ) + { + for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++) + { + // skip channeled spell (processed differently below) + if (i == CURRENT_CHANNELED_SPELL) + continue; + + if(Spell* spell = pVictim->m_currentSpells[i]) + if(spell->getState() == SPELL_STATE_PREPARING) + spell->Delayed(); + } + } + + if(Spell* spell = pVictim->m_currentSpells[CURRENT_CHANNELED_SPELL]) + { + if (spell->getState() == SPELL_STATE_CASTING) + { + uint32 channelInterruptFlags = spell->m_spellInfo->ChannelInterruptFlags; + if( channelInterruptFlags & CHANNEL_FLAG_DELAY ) + { + if(pVictim!=this) //don't shorten the duration of channeling if you damage yourself + spell->DelayedChannel(); + } + else if( (channelInterruptFlags & (CHANNEL_FLAG_DAMAGE | CHANNEL_FLAG_DAMAGE2)) ) + { + sLog.outDetail("Spell %u canceled at damage!",spell->m_spellInfo->Id); + pVictim->InterruptSpell(CURRENT_CHANNELED_SPELL); + } + } + else if (spell->getState() == SPELL_STATE_DELAYED) + // break channeled spell in delayed state on damage + { + sLog.outDetail("Spell %u canceled at damage!",spell->m_spellInfo->Id); + pVictim->InterruptSpell(CURRENT_CHANNELED_SPELL); + } + } + } + + // last damage from duel opponent + if(duel_hasEnded) + { + assert(pVictim->GetTypeId()==TYPEID_PLAYER); + Player *he = (Player*)pVictim; + + assert(he->duel); + + he->SetHealth(1); + + he->duel->opponent->CombatStopWithPets(true); + he->CombatStopWithPets(true); + + he->CastSpell(he, 7267, true); // beg + he->DuelComplete(DUEL_WON); + } + } + + DEBUG_LOG("DealDamageEnd returned %d damage", damage); + + return damage; +} + +void Unit::CastStop(uint32 except_spellid) +{ + for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++) + if (m_currentSpells[i] && m_currentSpells[i]->m_spellInfo->Id!=except_spellid) + InterruptSpell(i,false); +} + +void Unit::CastSpell(Unit* Victim, uint32 spellId, bool triggered, Item *castItem, Aura* triggredByAura, uint64 originalCaster) +{ + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId ); + + if(!spellInfo) + { + sLog.outError("CastSpell: unknown spell id %i by caster: %s %u)", spellId,(GetTypeId()==TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"),(GetTypeId()==TYPEID_PLAYER ? GetGUIDLow() : GetEntry())); + return; + } + + CastSpell(Victim,spellInfo,triggered,castItem,triggredByAura, originalCaster); +} + +void Unit::CastSpell(Unit* Victim,SpellEntry const *spellInfo, bool triggered, Item *castItem, Aura* triggredByAura, uint64 originalCaster) +{ + if(!spellInfo) + { + sLog.outError("CastSpell: unknown spell by caster: %s %u)", (GetTypeId()==TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"),(GetTypeId()==TYPEID_PLAYER ? GetGUIDLow() : GetEntry())); + return; + } + + if (castItem) + DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id); + + if(!originalCaster && triggredByAura) + originalCaster = triggredByAura->GetCasterGUID(); + + Spell *spell = new Spell(this, spellInfo, triggered, originalCaster ); + + SpellCastTargets targets; + targets.setUnitTarget( Victim ); + spell->m_CastItem = castItem; + spell->prepare(&targets, triggredByAura); +} + +void Unit::CastCustomSpell(Unit* Victim,uint32 spellId, int32 const* bp0, int32 const* bp1, int32 const* bp2, bool triggered, Item *castItem, Aura* triggredByAura, uint64 originalCaster) +{ + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId ); + + if(!spellInfo) + { + sLog.outError("CastCustomSpell: unknown spell id %i\n", spellId); + return; + } + + CastCustomSpell(Victim,spellInfo,bp0,bp1,bp2,triggered,castItem,triggredByAura, originalCaster); +} + +void Unit::CastCustomSpell(Unit* Victim,SpellEntry const *spellInfo, int32 const* bp0, int32 const* bp1, int32 const* bp2, bool triggered, Item *castItem, Aura* triggredByAura, uint64 originalCaster) +{ + if(!spellInfo) + { + sLog.outError("CastCustomSpell: unknown spell"); + return; + } + + if (castItem) + DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id); + + if(!originalCaster && triggredByAura) + originalCaster = triggredByAura->GetCasterGUID(); + + Spell *spell = new Spell(this, spellInfo, triggered, originalCaster); + + if(bp0) + spell->m_currentBasePoints[0] = *bp0-int32(spellInfo->EffectBaseDice[0]); + + if(bp1) + spell->m_currentBasePoints[1] = *bp1-int32(spellInfo->EffectBaseDice[1]); + + if(bp2) + spell->m_currentBasePoints[2] = *bp2-int32(spellInfo->EffectBaseDice[2]); + + SpellCastTargets targets; + targets.setUnitTarget( Victim ); + spell->m_CastItem = castItem; + spell->prepare(&targets, triggredByAura); +} + +// used for scripting +void Unit::CastSpell(float x, float y, float z, uint32 spellId, bool triggered, Item *castItem, Aura* triggredByAura, uint64 originalCaster) +{ + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId ); + + if(!spellInfo) + { + sLog.outError("CastSpell(x,y,z): unknown spell id %i by caster: %s %u)", spellId,(GetTypeId()==TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"),(GetTypeId()==TYPEID_PLAYER ? GetGUIDLow() : GetEntry())); + return; + } + + CastSpell(x, y, z,spellInfo,triggered,castItem,triggredByAura, originalCaster); +} + +// used for scripting +void Unit::CastSpell(float x, float y, float z, SpellEntry const *spellInfo, bool triggered, Item *castItem, Aura* triggredByAura, uint64 originalCaster) +{ + if(!spellInfo) + { + sLog.outError("CastSpell(x,y,z): unknown spell by caster: %s %u)", (GetTypeId()==TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"),(GetTypeId()==TYPEID_PLAYER ? GetGUIDLow() : GetEntry())); + return; + } + + if (castItem) + DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id); + + if(!originalCaster && triggredByAura) + originalCaster = triggredByAura->GetCasterGUID(); + + Spell *spell = new Spell(this, spellInfo, triggered, originalCaster ); + + SpellCastTargets targets; + targets.setDestination(x, y, z); + spell->m_CastItem = castItem; + spell->prepare(&targets, triggredByAura); +} + +void Unit::DealFlatDamage(Unit *pVictim, SpellEntry const *spellInfo, uint32 *damage, CleanDamage *cleanDamage, bool *crit, bool isTriggeredSpell) +{ + // TODO this in only generic way, check for exceptions + DEBUG_LOG("DealFlatDamage (BEFORE) >> DMG:%u", *damage); + + // Per-damage calss calculation + switch (spellInfo->DmgClass) + { + // Melee and Ranged Spells + case SPELL_DAMAGE_CLASS_RANGED: + case SPELL_DAMAGE_CLASS_MELEE: + { + // Calculate physical outcome + MeleeHitOutcome outcome = RollPhysicalOutcomeAgainst(pVictim, BASE_ATTACK, spellInfo); + + //Used to store the Hit Outcome + cleanDamage->hitOutCome = outcome; + + // Return miss/evade first (sends miss message) + switch(outcome) + { + case MELEE_HIT_EVADE: + { + SendAttackStateUpdate(HITINFO_MISS, pVictim, 1, GetSpellSchoolMask(spellInfo), 0, 0,0,VICTIMSTATE_EVADES,0); + *damage = 0; + return; + } + case MELEE_HIT_MISS: + { + SendAttackStateUpdate(HITINFO_MISS, pVictim, 1, GetSpellSchoolMask(spellInfo), 0, 0,0,VICTIMSTATE_NORMAL,0); + *damage = 0; + + if(GetTypeId()== TYPEID_PLAYER) + ((Player*)this)->UpdateWeaponSkill(BASE_ATTACK); + + CastMeleeProcDamageAndSpell(pVictim,0,GetSpellSchoolMask(spellInfo),BASE_ATTACK,MELEE_HIT_MISS,spellInfo,isTriggeredSpell); + return; + } + } + + // Hitinfo, Victimstate + uint32 hitInfo = HITINFO_NORMALSWING; + VictimState victimState = VICTIMSTATE_NORMAL; + + // Physical Damage + if ( GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_NORMAL ) + { + uint32 modDamage=*damage; + + // apply spellmod to Done damage + if(Player* modOwner = GetSpellModOwner()) + modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_DAMAGE, *damage); + + //Calculate armor mitigation + uint32 damageAfterArmor = CalcArmorReducedDamage(pVictim, *damage); + + // random durability for main hand weapon (ABSORB) + if(damageAfterArmor < *damage) + if(pVictim->GetTypeId() == TYPEID_PLAYER) + if (roll_chance_f(sWorld.getRate(RATE_DURABILITY_LOSS_ABSORB))) + ((Player*)pVictim)->DurabilityPointLossForEquipSlot(EquipmentSlots(urand(EQUIPMENT_SLOT_START,EQUIPMENT_SLOT_BACK))); + + cleanDamage->damage += *damage - damageAfterArmor; + *damage = damageAfterArmor; + } + // Magical Damage + else + { + // Calculate damage bonus + *damage = SpellDamageBonus(pVictim, spellInfo, *damage, SPELL_DIRECT_DAMAGE); + } + + // Classify outcome + switch (outcome) + { + case MELEE_HIT_BLOCK_CRIT: + case MELEE_HIT_CRIT: + { + uint32 bonusDmg = *damage; + + // Apply crit_damage bonus + if(Player* modOwner = GetSpellModOwner()) + modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CRIT_DAMAGE_BONUS, bonusDmg); + + uint32 creatureTypeMask = pVictim->GetCreatureTypeMask(); + AuraList const& mDamageDoneVersus = GetAurasByType(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS); + for(AuraList::const_iterator i = mDamageDoneVersus.begin();i != mDamageDoneVersus.end(); ++i) + if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue)) + bonusDmg = uint32(bonusDmg * ((*i)->GetModifier()->m_amount+100.0f)/100.0f); + + *damage += bonusDmg; + + // Resilience - reduce crit damage + if (pVictim->GetTypeId()==TYPEID_PLAYER) + { + uint32 resilienceReduction = ((Player*)pVictim)->GetMeleeCritDamageReduction(*damage); + cleanDamage->damage += resilienceReduction; + *damage -= resilienceReduction; + } + + *crit = true; + hitInfo |= HITINFO_CRITICALHIT; + + ModifyAuraState(AURA_STATE_CRIT, true); + StartReactiveTimer( REACTIVE_CRIT ); + + if(getClass()==CLASS_HUNTER) + { + ModifyAuraState(AURA_STATE_HUNTER_CRIT_STRIKE, true); + StartReactiveTimer( REACTIVE_HUNTER_CRIT ); + } + + if ( outcome == MELEE_HIT_BLOCK_CRIT ) + { + uint32 blocked_amount = uint32(pVictim->GetShieldBlockValue()); + if (blocked_amount >= *damage) + { + hitInfo |= HITINFO_SWINGNOHITSOUND; + victimState = VICTIMSTATE_BLOCKS; + cleanDamage->damage += *damage; // To Help Calculate Rage + *damage = 0; + } + else + { + // To Help Calculate Rage + cleanDamage->damage += blocked_amount; + *damage = *damage - blocked_amount; + } + + pVictim->ModifyAuraState(AURA_STATE_DEFENSE, true); + pVictim->StartReactiveTimer( REACTIVE_DEFENSE ); + + if(pVictim->GetTypeId() == TYPEID_PLAYER) + { + // Update defense + ((Player*)pVictim)->UpdateDefense(); + + // random durability for main hand weapon (BLOCK) + if (roll_chance_f(sWorld.getRate(RATE_DURABILITY_LOSS_BLOCK))) + ((Player*)pVictim)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_OFFHAND); + } + } + break; + } + case MELEE_HIT_PARRY: + { + cleanDamage->damage += *damage; // To Help Calculate Rage + *damage = 0; + victimState = VICTIMSTATE_PARRY; + + // Counter-attack ( explained in Unit::DoAttackDamage() ) + if(pVictim->GetTypeId()==TYPEID_PLAYER || !(((Creature*)pVictim)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_NO_PARRY_HASTEN) ) + { + // Get attack timers + float offtime = float(pVictim->getAttackTimer(OFF_ATTACK)); + float basetime = float(pVictim->getAttackTimer(BASE_ATTACK)); + + // Reduce attack time + if (pVictim->haveOffhandWeapon() && offtime < basetime) + { + float percent20 = pVictim->GetAttackTime(OFF_ATTACK) * 0.20; + float percent60 = 3 * percent20; + if(offtime > percent20 && offtime <= percent60) + { + pVictim->setAttackTimer(OFF_ATTACK, uint32(percent20)); + } + else if(offtime > percent60) + { + offtime -= 2 * percent20; + pVictim->setAttackTimer(OFF_ATTACK, uint32(offtime)); + } + } + else + { + float percent20 = pVictim->GetAttackTime(BASE_ATTACK) * 0.20; + float percent60 = 3 * percent20; + if(basetime > percent20 && basetime <= percent60) + { + pVictim->setAttackTimer(BASE_ATTACK, uint32(percent20)); + } + else if(basetime > percent60) + { + basetime -= 2 * percent20; + pVictim->setAttackTimer(BASE_ATTACK, uint32(basetime)); + } + } + } + + if(pVictim->GetTypeId() == TYPEID_PLAYER) + { + // Update victim defense ? + ((Player*)pVictim)->UpdateDefense(); + + // random durability for main hand weapon (PARRY) + if (roll_chance_f(sWorld.getRate(RATE_DURABILITY_LOSS_PARRY))) + ((Player*)pVictim)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_MAINHAND); + } + + // Set parry flags + pVictim->HandleEmoteCommand(EMOTE_ONESHOT_PARRYUNARMED); + + // Mongoose bite - set only Counterattack here + if (pVictim->getClass() == CLASS_HUNTER) + { + pVictim->ModifyAuraState(AURA_STATE_HUNTER_PARRY,true); + pVictim->StartReactiveTimer( REACTIVE_HUNTER_PARRY ); + } + else + { + pVictim->ModifyAuraState(AURA_STATE_DEFENSE, true); + pVictim->StartReactiveTimer( REACTIVE_DEFENSE ); + } + break; + } + case MELEE_HIT_DODGE: + { + if(pVictim->GetTypeId() == TYPEID_PLAYER) + ((Player*)pVictim)->UpdateDefense(); + + cleanDamage->damage += *damage; // To Help Calculate Rage + *damage = 0; + hitInfo |= HITINFO_SWINGNOHITSOUND; + victimState = VICTIMSTATE_DODGE; + + // Set dodge flags + pVictim->HandleEmoteCommand(EMOTE_ONESHOT_PARRYUNARMED); + + // Overpower + if (GetTypeId() == TYPEID_PLAYER && getClass() == CLASS_WARRIOR) + { + ((Player*)this)->AddComboPoints(pVictim, 1); + StartReactiveTimer( REACTIVE_OVERPOWER ); + } + + // Riposte + if (pVictim->getClass() != CLASS_ROGUE) + { + pVictim->ModifyAuraState(AURA_STATE_DEFENSE, true); + pVictim->StartReactiveTimer( REACTIVE_DEFENSE ); + } + break; + } + case MELEE_HIT_BLOCK: + { + uint32 blocked_amount = uint32(pVictim->GetShieldBlockValue()); + if (blocked_amount >= *damage) + { + hitInfo |= HITINFO_SWINGNOHITSOUND; + victimState = VICTIMSTATE_BLOCKS; + cleanDamage->damage += *damage; // To Help Calculate Rage + *damage = 0; + } + else + { + // To Help Calculate Rage + cleanDamage->damage += blocked_amount; + *damage = *damage - blocked_amount; + } + + pVictim->ModifyAuraState(AURA_STATE_DEFENSE, true); + pVictim->StartReactiveTimer( REACTIVE_DEFENSE ); + + if(pVictim->GetTypeId() == TYPEID_PLAYER) + { + // Update defense + ((Player*)pVictim)->UpdateDefense(); + + // random durability for main hand weapon (BLOCK) + if (roll_chance_f(sWorld.getRate(RATE_DURABILITY_LOSS_BLOCK))) + ((Player*)pVictim)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_OFFHAND); + } + break; + } + case MELEE_HIT_EVADE: // already processed early + case MELEE_HIT_MISS: // already processed early + case MELEE_HIT_GLANCING: + case MELEE_HIT_CRUSHING: + case MELEE_HIT_NORMAL: + break; + } + + // do all damage=0 cases here + if(*damage == 0) + CastMeleeProcDamageAndSpell(pVictim,0,GetSpellSchoolMask(spellInfo),BASE_ATTACK,outcome,spellInfo,isTriggeredSpell); + + break; + } + // Magical Attacks + case SPELL_DAMAGE_CLASS_NONE: + case SPELL_DAMAGE_CLASS_MAGIC: + { + // Calculate damage bonus + *damage = SpellDamageBonus(pVictim, spellInfo, *damage, SPELL_DIRECT_DAMAGE); + + *crit = isSpellCrit(pVictim, spellInfo, GetSpellSchoolMask(spellInfo), BASE_ATTACK); + if (*crit) + { + *damage = SpellCriticalBonus(spellInfo, *damage, pVictim); + + // Resilience - reduce crit damage + if (pVictim && pVictim->GetTypeId()==TYPEID_PLAYER) + { + uint32 damage_reduction = ((Player *)pVictim)->GetSpellCritDamageReduction(*damage); + if(*damage > damage_reduction) + *damage -= damage_reduction; + else + *damage = 0; + } + + cleanDamage->hitOutCome = MELEE_HIT_CRIT; + } + // spell proc all magic damage==0 case in this function + if(*damage == 0) + { + // Procflags + uint32 procAttacker = PROC_FLAG_HIT_SPELL; + uint32 procVictim = (PROC_FLAG_STRUCK_SPELL|PROC_FLAG_TAKE_DAMAGE); + + ProcDamageAndSpell(pVictim, procAttacker, procVictim, 0, GetSpellSchoolMask(spellInfo), spellInfo, isTriggeredSpell); + } + + break; + } + } + + // TODO this in only generic way, check for exceptions + DEBUG_LOG("DealFlatDamage (AFTER) >> DMG:%u", *damage); +} + +uint32 Unit::SpellNonMeleeDamageLog(Unit *pVictim, uint32 spellID, uint32 damage, bool isTriggeredSpell, bool useSpellDamage) +{ + if(!this || !pVictim) + return 0; + if(!this->isAlive() || !pVictim->isAlive()) + return 0; + + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellID); + if(!spellInfo) + return 0; + + CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL); + bool crit = false; + + if (useSpellDamage) + DealFlatDamage(pVictim, spellInfo, &damage, &cleanDamage, &crit, isTriggeredSpell); + + // If we actually dealt some damage (spell proc's for 0 damage (normal and magic) called in DealFlatDamage) + if(damage > 0) + { + // Calculate absorb & resists + uint32 absorb = 0; + uint32 resist = 0; + + CalcAbsorbResist(pVictim,GetSpellSchoolMask(spellInfo), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist); + + //No more damage left, target absorbed and/or resisted all damage + if (damage > absorb + resist) + damage -= absorb + resist; //Remove Absorbed and Resisted from damage actually dealt + else + { + uint32 HitInfo = HITINFO_SWINGNOHITSOUND; + + if (absorb) + HitInfo |= HITINFO_ABSORB; + if (resist) + { + HitInfo |= HITINFO_RESIST; + ProcDamageAndSpell(pVictim, PROC_FLAG_TARGET_RESISTS, PROC_FLAG_RESIST_SPELL, 0, GetSpellSchoolMask(spellInfo), spellInfo,isTriggeredSpell); + } + + //Send resist + SendAttackStateUpdate(HitInfo, pVictim, 1, GetSpellSchoolMask(spellInfo), damage, absorb,resist,VICTIMSTATE_NORMAL,0); + return 0; + } + + // Deal damage done + damage = DealDamage(pVictim, damage, &cleanDamage, SPELL_DIRECT_DAMAGE, GetSpellSchoolMask(spellInfo), spellInfo, true); + + // Send damage log + sLog.outDetail("SpellNonMeleeDamageLog: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u,absorb is %u,resist is %u", + GetGUIDLow(), GetTypeId(), pVictim->GetGUIDLow(), pVictim->GetTypeId(), damage, spellID, absorb,resist); + + // Actual log sent to client + SendSpellNonMeleeDamageLog(pVictim, spellID, damage, GetSpellSchoolMask(spellInfo), absorb, resist, false, 0, crit); + + // Procflags + uint32 procAttacker = PROC_FLAG_HIT_SPELL; + uint32 procVictim = (PROC_FLAG_STRUCK_SPELL|PROC_FLAG_TAKE_DAMAGE); + + if (crit) + { + procAttacker |= PROC_FLAG_CRIT_SPELL; + procVictim |= PROC_FLAG_STRUCK_CRIT_SPELL; + } + + ProcDamageAndSpell(pVictim, procAttacker, procVictim, damage, GetSpellSchoolMask(spellInfo), spellInfo, isTriggeredSpell); + + return damage; + } + else + { + // all spell proc for 0 normal and magic damage called in DealFlatDamage + + //Check for rage + if(cleanDamage.damage) + // Rage from damage received. + if(pVictim->GetTypeId() == TYPEID_PLAYER && (pVictim->getPowerType() == POWER_RAGE)) + ((Player*)pVictim)->RewardRage(cleanDamage.damage, 0, false); + + return 0; + } +} + +void Unit::HandleEmoteCommand(uint32 anim_id) +{ + WorldPacket data( SMSG_EMOTE, 12 ); + data << anim_id << GetGUID(); + WPAssert(data.size() == 12); + + SendMessageToSet(&data, true); +} + +uint32 Unit::CalcArmorReducedDamage(Unit* pVictim, const uint32 damage) +{ + uint32 newdamage = 0; + float armor = pVictim->GetArmor(); + // Ignore enemy armor by SPELL_AURA_MOD_TARGET_RESISTANCE aura + armor += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, SPELL_SCHOOL_MASK_NORMAL); + + if (armor<0.0f) armor=0.0f; + + float tmpvalue = 0.0f; + if(getLevel() <= 59) //Level 1-59 + tmpvalue = armor / (armor + 400.0f + 85.0f * getLevel()); + else if(getLevel() < 70) //Level 60-69 + tmpvalue = armor / (armor - 22167.5f + 467.5f * getLevel()); + else //Level 70+ + tmpvalue = armor / (armor + 10557.5f); + + if(tmpvalue < 0.0f) + tmpvalue = 0.0f; + if(tmpvalue > 0.75f) + tmpvalue = 0.75f; + newdamage = uint32(damage - (damage * tmpvalue)); + + return (newdamage > 1) ? newdamage : 1; +} + +void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffectType damagetype, const uint32 damage, uint32 *absorb, uint32 *resist) +{ + if(!pVictim || !pVictim->isAlive() || !damage) + return; + + // Magic damage, check for resists + if ((schoolMask & SPELL_SCHOOL_MASK_NORMAL)==0) + { + // Get base victim resistance for school + float tmpvalue2 = (float)pVictim->GetResistance(GetFirstSchoolInMask(schoolMask)); + // Ignore resistance by self SPELL_AURA_MOD_TARGET_RESISTANCE aura + tmpvalue2 += (float)GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, schoolMask); + + tmpvalue2 *= (float)(0.15f / getLevel()); + if (tmpvalue2 < 0.0f) + tmpvalue2 = 0.0f; + if (tmpvalue2 > 0.75f) + tmpvalue2 = 0.75f; + uint32 ran = urand(0, 100); + uint32 faq[4] = {24,6,4,6}; + uint8 m = 0; + float Binom = 0.0f; + for (uint8 i = 0; i < 4; i++) + { + Binom += 2400 *( powf(tmpvalue2, i) * powf( (1-tmpvalue2), (4-i)))/faq[i]; + if (ran > Binom ) + ++m; + else + break; + } + if (damagetype == DOT && m == 4) + *resist += uint32(damage - 1); + else + *resist += uint32(damage * m / 4); + if(*resist > damage) + *resist = damage; + } + else + *resist = 0; + + int32 RemainingDamage = damage - *resist; + + // absorb without mana cost + int32 reflectDamage = 0; + Aura* reflectAura = NULL; + AuraList const& vSchoolAbsorb = pVictim->GetAurasByType(SPELL_AURA_SCHOOL_ABSORB); + for(AuraList::const_iterator i = vSchoolAbsorb.begin(), next; i != vSchoolAbsorb.end() && RemainingDamage > 0; i = next) + { + next = i; ++next; + + if (((*i)->GetModifier()->m_miscvalue & schoolMask)==0) + continue; + + // Cheat Death + if((*i)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE && (*i)->GetSpellProto()->SpellIconID == 2109) + { + if (((Player*)pVictim)->HasSpellCooldown(31231)) + continue; + if (pVictim->GetHealth() <= RemainingDamage) + { + int32 chance = (*i)->GetModifier()->m_amount; + if (roll_chance_i(chance)) + { + pVictim->CastSpell(pVictim,31231,true); + ((Player*)pVictim)->AddSpellCooldown(31231,0,time(NULL)+60); + + // with health > 10% lost health until health==10%, in other case no losses + uint32 health10 = pVictim->GetMaxHealth()/10; + RemainingDamage = pVictim->GetHealth() > health10 ? pVictim->GetHealth() - health10 : 0; + } + } + continue; + } + + int32 currentAbsorb; + + //Reflective Shield + if ((pVictim != this) && (*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_PRIEST && (*i)->GetSpellProto()->SpellFamilyFlags == 0x1) + { + if(Unit* caster = (*i)->GetCaster()) + { + AuraList const& vOverRideCS = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + for(AuraList::const_iterator k = vOverRideCS.begin(); k != vOverRideCS.end(); ++k) + { + switch((*k)->GetModifier()->m_miscvalue) + { + case 5065: // Rank 1 + case 5064: // Rank 2 + case 5063: // Rank 3 + case 5062: // Rank 4 + case 5061: // Rank 5 + { + if(RemainingDamage >= (*i)->GetModifier()->m_amount) + reflectDamage = (*i)->GetModifier()->m_amount * (*k)->GetModifier()->m_amount/100; + else + reflectDamage = (*k)->GetModifier()->m_amount * RemainingDamage/100; + reflectAura = *i; + + } break; + default: break; + } + + if(reflectDamage) + break; + } + } + } + + if (RemainingDamage >= (*i)->GetModifier()->m_amount) + { + currentAbsorb = (*i)->GetModifier()->m_amount; + pVictim->RemoveAurasDueToSpell((*i)->GetId()); + next = vSchoolAbsorb.begin(); + } + else + { + currentAbsorb = RemainingDamage; + (*i)->GetModifier()->m_amount -= RemainingDamage; + } + + RemainingDamage -= currentAbsorb; + } + // do not cast spells while looping auras; auras can get invalid otherwise + if (reflectDamage) + pVictim->CastCustomSpell(this, 33619, &reflectDamage, NULL, NULL, true, NULL, reflectAura); + + // absorb by mana cost + AuraList const& vManaShield = pVictim->GetAurasByType(SPELL_AURA_MANA_SHIELD); + for(AuraList::const_iterator i = vManaShield.begin(), next; i != vManaShield.end() && RemainingDamage > 0; i = next) + { + next = i; ++next; + + // check damage school mask + if(((*i)->GetModifier()->m_miscvalue & schoolMask)==0) + continue; + + int32 currentAbsorb; + if (RemainingDamage >= (*i)->GetModifier()->m_amount) + currentAbsorb = (*i)->GetModifier()->m_amount; + else + currentAbsorb = RemainingDamage; + + float manaMultiplier = (*i)->GetSpellProto()->EffectMultipleValue[(*i)->GetEffIndex()]; + if(Player *modOwner = GetSpellModOwner()) + modOwner->ApplySpellMod((*i)->GetId(), SPELLMOD_MULTIPLE_VALUE, manaMultiplier); + + int32 maxAbsorb = int32(pVictim->GetPower(POWER_MANA) / manaMultiplier); + if (currentAbsorb > maxAbsorb) + currentAbsorb = maxAbsorb; + + (*i)->GetModifier()->m_amount -= currentAbsorb; + if((*i)->GetModifier()->m_amount <= 0) + { + pVictim->RemoveAurasDueToSpell((*i)->GetId()); + next = vManaShield.begin(); + } + + int32 manaReduction = int32(currentAbsorb * manaMultiplier); + pVictim->ApplyPowerMod(POWER_MANA, manaReduction, false); + + RemainingDamage -= currentAbsorb; + } + + AuraList const& vSplitDamageFlat = pVictim->GetAurasByType(SPELL_AURA_SPLIT_DAMAGE_FLAT); + for(AuraList::const_iterator i = vSplitDamageFlat.begin(), next; i != vSplitDamageFlat.end() && RemainingDamage >= 0; i = next) + { + next = i; ++next; + + // check damage school mask + if(((*i)->GetModifier()->m_miscvalue & schoolMask)==0) + continue; + + // Damage can be splitted only if aura has an alive caster + Unit *caster = (*i)->GetCaster(); + if(!caster || caster == pVictim || !caster->IsInWorld() || !caster->isAlive()) + continue; + + int32 currentAbsorb; + if (RemainingDamage >= (*i)->GetModifier()->m_amount) + currentAbsorb = (*i)->GetModifier()->m_amount; + else + currentAbsorb = RemainingDamage; + + RemainingDamage -= currentAbsorb; + + SendSpellNonMeleeDamageLog(caster, (*i)->GetSpellProto()->Id, currentAbsorb, schoolMask, 0, 0, false, 0, false); + + CleanDamage cleanDamage = CleanDamage(currentAbsorb, BASE_ATTACK, MELEE_HIT_NORMAL); + DealDamage(caster, currentAbsorb, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*i)->GetSpellProto(), false); + } + + AuraList const& vSplitDamagePct = pVictim->GetAurasByType(SPELL_AURA_SPLIT_DAMAGE_PCT); + for(AuraList::const_iterator i = vSplitDamagePct.begin(), next; i != vSplitDamagePct.end() && RemainingDamage >= 0; i = next) + { + next = i; ++next; + + // check damage school mask + if(((*i)->GetModifier()->m_miscvalue & schoolMask)==0) + continue; + + // Damage can be splitted only if aura has an alive caster + Unit *caster = (*i)->GetCaster(); + if(!caster || caster == pVictim || !caster->IsInWorld() || !caster->isAlive()) + continue; + + int32 splitted = int32(RemainingDamage * (*i)->GetModifier()->m_amount / 100.0f); + + RemainingDamage -= splitted; + + SendSpellNonMeleeDamageLog(caster, (*i)->GetSpellProto()->Id, splitted, schoolMask, 0, 0, false, 0, false); + + CleanDamage cleanDamage = CleanDamage(splitted, BASE_ATTACK, MELEE_HIT_NORMAL); + DealDamage(caster, splitted, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*i)->GetSpellProto(), false); + } + + *absorb = damage - RemainingDamage - *resist; +} + +void Unit::DoAttackDamage (Unit *pVictim, uint32 *damage, CleanDamage *cleanDamage, uint32 *blocked_amount, SpellSchoolMask damageSchoolMask, uint32 *hitInfo, VictimState *victimState, uint32 *absorbDamage, uint32 *resistDamage, WeaponAttackType attType, SpellEntry const *spellCasted, bool isTriggeredSpell) +{ + MeleeHitOutcome outcome; + + // If is casted Melee spell, calculate like physical + if(!spellCasted) + outcome = RollMeleeOutcomeAgainst (pVictim, attType); + else + outcome = RollPhysicalOutcomeAgainst (pVictim, attType, spellCasted); + + if(outcome == MELEE_HIT_MISS ||outcome == MELEE_HIT_DODGE ||outcome == MELEE_HIT_BLOCK ||outcome == MELEE_HIT_PARRY) + pVictim->AddThreat(this, 0.0f); + switch(outcome) + { + case MELEE_HIT_EVADE: + { + *hitInfo |= HITINFO_MISS; + *damage = 0; + cleanDamage->damage = 0; + return; + } + case MELEE_HIT_MISS: + { + *hitInfo |= HITINFO_MISS; + *damage = 0; + cleanDamage->damage = 0; + if(GetTypeId()== TYPEID_PLAYER) + ((Player*)this)->UpdateWeaponSkill(attType); + return; + } + } + + /// If this is a creature and it attacks from behind it has a probability to daze it's victim + if( (outcome==MELEE_HIT_CRIT || outcome==MELEE_HIT_CRUSHING || outcome==MELEE_HIT_NORMAL || outcome==MELEE_HIT_GLANCING) && + GetTypeId() != TYPEID_PLAYER && !((Creature*)this)->GetCharmerOrOwnerGUID() && !pVictim->HasInArc(M_PI, this) ) + { + // -probability is between 0% and 40% + // 20% base chance + float Probability = 20; + + //there is a newbie protection, at level 10 just 7% base chance; assuming linear function + if( pVictim->getLevel() < 30 ) + Probability = 0.65f*pVictim->getLevel()+0.5; + + uint32 VictimDefense=pVictim->GetDefenseSkillValue(this); + uint32 AttackerMeleeSkill=GetUnitMeleeSkill(pVictim); + + Probability *= AttackerMeleeSkill/(float)VictimDefense; + + if(Probability > 40.0f) + Probability = 40.0f; + + if(roll_chance_f(Probability)) + CastSpell(pVictim, 1604, true); + } + + //Calculate the damage after armor mitigation if SPELL_SCHOOL_NORMAL + if (damageSchoolMask & SPELL_SCHOOL_MASK_NORMAL) + { + uint32 damageAfterArmor = CalcArmorReducedDamage(pVictim, *damage); + + // random durability for main hand weapon (ABSORB) + if(damageAfterArmor < *damage) + if(pVictim->GetTypeId() == TYPEID_PLAYER) + if (roll_chance_f(sWorld.getRate(RATE_DURABILITY_LOSS_ABSORB))) + ((Player*)pVictim)->DurabilityPointLossForEquipSlot(EquipmentSlots(urand(EQUIPMENT_SLOT_START,EQUIPMENT_SLOT_BACK))); + + cleanDamage->damage += *damage - damageAfterArmor; + *damage = damageAfterArmor; + } + + if(GetTypeId() == TYPEID_PLAYER && pVictim->GetTypeId() != TYPEID_PLAYER && pVictim->GetCreatureType() != CREATURE_TYPE_CRITTER ) + ((Player*)this)->UpdateCombatSkills(pVictim, attType, outcome, false); + + if(GetTypeId() != TYPEID_PLAYER && pVictim->GetTypeId() == TYPEID_PLAYER) + ((Player*)pVictim)->UpdateCombatSkills(this, attType, outcome, true); + + switch (outcome) + { + case MELEE_HIT_BLOCK_CRIT: + case MELEE_HIT_CRIT: + { + //*hitInfo = 0xEA; + // 0xEA + *hitInfo = HITINFO_CRITICALHIT | HITINFO_NORMALSWING2 | 0x8; + + // Crit bonus calc + uint32 crit_bonus; + crit_bonus = *damage; + + // Apply crit_damage bonus for melee spells + if (spellCasted) + { + if(Player* modOwner = GetSpellModOwner()) + modOwner->ApplySpellMod(spellCasted->Id, SPELLMOD_CRIT_DAMAGE_BONUS, crit_bonus); + + uint32 creatureTypeMask = pVictim->GetCreatureTypeMask(); + AuraList const& mDamageDoneVersus = GetAurasByType(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS); + for(AuraList::const_iterator i = mDamageDoneVersus.begin();i != mDamageDoneVersus.end(); ++i) + if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue)) + crit_bonus = uint32(crit_bonus * ((*i)->GetModifier()->m_amount+100.0f)/100.0f); + } + + *damage += crit_bonus; + + uint32 resilienceReduction = 0; + + if(attType == RANGED_ATTACK) + { + int32 mod = pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE); + *damage = int32((*damage) * float((100.0f + mod)/100.0f)); + // Resilience - reduce crit damage + if (pVictim->GetTypeId()==TYPEID_PLAYER) + resilienceReduction = ((Player*)pVictim)->GetRangedCritDamageReduction(*damage); + } + else + { + int32 mod = pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE); + mod += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE); + *damage = int32((*damage) * float((100.0f + mod)/100.0f)); + // Resilience - reduce crit damage + if (pVictim->GetTypeId()==TYPEID_PLAYER) + resilienceReduction = ((Player*)pVictim)->GetMeleeCritDamageReduction(*damage); + } + + *damage -= resilienceReduction; + cleanDamage->damage += resilienceReduction; + + if(GetTypeId() == TYPEID_PLAYER && pVictim->GetTypeId() != TYPEID_PLAYER && pVictim->GetCreatureType() != CREATURE_TYPE_CRITTER ) + ((Player*)this)->UpdateWeaponSkill(attType); + + ModifyAuraState(AURA_STATE_CRIT, true); + StartReactiveTimer( REACTIVE_CRIT ); + + if(getClass()==CLASS_HUNTER) + { + ModifyAuraState(AURA_STATE_HUNTER_CRIT_STRIKE, true); + StartReactiveTimer( REACTIVE_HUNTER_CRIT ); + } + + if ( outcome == MELEE_HIT_BLOCK_CRIT ) + { + *blocked_amount = pVictim->GetShieldBlockValue(); + + if (pVictim->GetUnitBlockChance()) + pVictim->HandleEmoteCommand(EMOTE_ONESHOT_PARRYSHIELD); + else + pVictim->HandleEmoteCommand(EMOTE_ONESHOT_PARRYUNARMED); + + //Only set VICTIMSTATE_BLOCK on a full block + if (*blocked_amount >= uint32(*damage)) + { + *victimState = VICTIMSTATE_BLOCKS; + *blocked_amount = uint32(*damage); + } + + if(pVictim->GetTypeId() == TYPEID_PLAYER) + { + // Update defense + ((Player*)pVictim)->UpdateDefense(); + + // random durability for main hand weapon (BLOCK) + if (roll_chance_f(sWorld.getRate(RATE_DURABILITY_LOSS_BLOCK))) + ((Player*)pVictim)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_OFFHAND); + } + + pVictim->ModifyAuraState(AURA_STATE_DEFENSE,true); + pVictim->StartReactiveTimer( REACTIVE_DEFENSE ); + break; + } + + pVictim->HandleEmoteCommand(EMOTE_ONESHOT_WOUNDCRITICAL); + break; + } + case MELEE_HIT_PARRY: + { + if(attType == RANGED_ATTACK) //range attack - no parry + { + outcome = MELEE_HIT_NORMAL; + break; + } + + cleanDamage->damage += *damage; + *damage = 0; + *victimState = VICTIMSTATE_PARRY; + + // instant (maybe with small delay) counter attack + { + float offtime = float(pVictim->getAttackTimer(OFF_ATTACK)); + float basetime = float(pVictim->getAttackTimer(BASE_ATTACK)); + + // after parry nearest next attack time will reduced at %40 from full attack time. + // The delay cannot be reduced to less than 20% of your weapon's base swing delay. + if (pVictim->haveOffhandWeapon() && offtime < basetime) + { + float percent20 = pVictim->GetAttackTime(OFF_ATTACK)*0.20; + float percent60 = 3*percent20; + // set to 20% if in range 20%...20+40% of full time + if(offtime > percent20 && offtime <= percent60) + { + pVictim->setAttackTimer(OFF_ATTACK,uint32(percent20)); + } + // decrease at %40 from full time + else if(offtime > percent60) + { + offtime -= 2*percent20; + pVictim->setAttackTimer(OFF_ATTACK,uint32(offtime)); + } + // ELSE not changed + } + else + { + float percent20 = pVictim->GetAttackTime(BASE_ATTACK)*0.20; + float percent60 = 3*percent20; + // set to 20% if in range 20%...20+40% of full time + if(basetime > percent20 && basetime <= percent60) + { + pVictim->setAttackTimer(BASE_ATTACK,uint32(percent20)); + } + // decrease at %40 from full time + else if(basetime > percent60) + { + basetime -= 2*percent20; + pVictim->setAttackTimer(BASE_ATTACK,uint32(basetime)); + } + // ELSE not changed + } + } + + if(pVictim->GetTypeId() == TYPEID_PLAYER) + { + // Update victim defense ? + ((Player*)pVictim)->UpdateDefense(); + + // random durability for main hand weapon (PARRY) + if (roll_chance_f(sWorld.getRate(RATE_DURABILITY_LOSS_PARRY))) + ((Player*)pVictim)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_MAINHAND); + } + + pVictim->HandleEmoteCommand(EMOTE_ONESHOT_PARRYUNARMED); + + if (pVictim->getClass() == CLASS_HUNTER) + { + pVictim->ModifyAuraState(AURA_STATE_HUNTER_PARRY,true); + pVictim->StartReactiveTimer( REACTIVE_HUNTER_PARRY ); + } + else + { + pVictim->ModifyAuraState(AURA_STATE_DEFENSE, true); + pVictim->StartReactiveTimer( REACTIVE_DEFENSE ); + } + + CastMeleeProcDamageAndSpell(pVictim, 0, damageSchoolMask, attType, outcome, spellCasted, isTriggeredSpell); + return; + } + case MELEE_HIT_DODGE: + { + if(attType == RANGED_ATTACK) //range attack - no dodge + { + outcome = MELEE_HIT_NORMAL; + break; + } + + cleanDamage->damage += *damage; + *damage = 0; + *victimState = VICTIMSTATE_DODGE; + + if(pVictim->GetTypeId() == TYPEID_PLAYER) + ((Player*)pVictim)->UpdateDefense(); + + pVictim->HandleEmoteCommand(EMOTE_ONESHOT_PARRYUNARMED); + + if (pVictim->getClass() != CLASS_ROGUE) // Riposte + { + pVictim->ModifyAuraState(AURA_STATE_DEFENSE, true); + pVictim->StartReactiveTimer( REACTIVE_DEFENSE ); + } + + // Overpower + if (GetTypeId() == TYPEID_PLAYER && getClass() == CLASS_WARRIOR) + { + ((Player*)this)->AddComboPoints(pVictim, 1); + StartReactiveTimer( REACTIVE_OVERPOWER ); + } + + CastMeleeProcDamageAndSpell(pVictim, 0, damageSchoolMask, attType, outcome, spellCasted, isTriggeredSpell); + return; + } + case MELEE_HIT_BLOCK: + { + *blocked_amount = pVictim->GetShieldBlockValue(); + + if (pVictim->GetUnitBlockChance()) + pVictim->HandleEmoteCommand(EMOTE_ONESHOT_PARRYSHIELD); + else + pVictim->HandleEmoteCommand(EMOTE_ONESHOT_PARRYUNARMED); + + //Only set VICTIMSTATE_BLOCK on a full block + if (*blocked_amount >= uint32(*damage)) + { + *victimState = VICTIMSTATE_BLOCKS; + *blocked_amount = uint32(*damage); + } + + if(pVictim->GetTypeId() == TYPEID_PLAYER) + { + // Update defense + ((Player*)pVictim)->UpdateDefense(); + + // random durability for main hand weapon (BLOCK) + if (roll_chance_f(sWorld.getRate(RATE_DURABILITY_LOSS_BLOCK))) + ((Player*)pVictim)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_OFFHAND); + } + + pVictim->ModifyAuraState(AURA_STATE_DEFENSE,true); + pVictim->StartReactiveTimer( REACTIVE_DEFENSE ); + + break; + } + case MELEE_HIT_GLANCING: + { + float reducePercent = 1.0f; //damage factor + + // calculate base values and mods + float baseLowEnd = 1.3; + float baseHighEnd = 1.2; + switch(getClass()) // lowering base values for casters + { + case CLASS_SHAMAN: + case CLASS_PRIEST: + case CLASS_MAGE: + case CLASS_WARLOCK: + case CLASS_DRUID: + baseLowEnd -= 0.7; + baseHighEnd -= 0.3; + break; + } + + float maxLowEnd = 0.6; + switch(getClass()) // upper for melee classes + { + case CLASS_WARRIOR: + case CLASS_ROGUE: + maxLowEnd = 0.91; //If the attacker is a melee class then instead the lower value of 0.91 + } + + // calculate values + int32 diff = int32(pVictim->GetDefenseSkillValue(this)) - int32(GetWeaponSkillValue(attType,pVictim)); + float lowEnd = baseLowEnd - ( 0.05f * diff ); + float highEnd = baseHighEnd - ( 0.03f * diff ); + + // apply max/min bounds + if ( lowEnd < 0.01f ) //the low end must not go bellow 0.01f + lowEnd = 0.01f; + else if ( lowEnd > maxLowEnd ) //the smaller value of this and 0.6 is kept as the low end + lowEnd = maxLowEnd; + + if ( highEnd < 0.2f ) //high end limits + highEnd = 0.2f; + if ( highEnd > 0.99f ) + highEnd = 0.99f; + + if(lowEnd > highEnd) // prevent negative range size + lowEnd = highEnd; + + reducePercent = lowEnd + rand_norm() * ( highEnd - lowEnd ); + + *damage = uint32(reducePercent * *damage); + cleanDamage->damage += *damage; + *hitInfo |= HITINFO_GLANCING; + break; + } + case MELEE_HIT_CRUSHING: + { + // 150% normal damage + *damage += (*damage / 2); + cleanDamage->damage = *damage; + *hitInfo |= HITINFO_CRUSHING; + // TODO: victimState, victim animation? + break; + } + default: + break; + } + + // apply melee damage bonus and absorb only if base damage not fully blocked to prevent negative damage or damage with full block + if(*victimState != VICTIMSTATE_BLOCKS) + { + MeleeDamageBonus(pVictim, damage,attType,spellCasted); + CalcAbsorbResist(pVictim, damageSchoolMask, DIRECT_DAMAGE, *damage-*blocked_amount, absorbDamage, resistDamage); + } + + if (*absorbDamage) *hitInfo |= HITINFO_ABSORB; + if (*resistDamage) *hitInfo |= HITINFO_RESIST; + + cleanDamage->damage += *blocked_amount; + + if (*damage <= *absorbDamage + *resistDamage + *blocked_amount) + { + //*hitInfo = 0x00010020; + //*hitInfo |= HITINFO_SWINGNOHITSOUND; + //*damageType = 0; + CastMeleeProcDamageAndSpell(pVictim, 0, damageSchoolMask, attType, outcome, spellCasted, isTriggeredSpell); + return; + } + + // update at damage Judgement aura duration that applied by attacker at victim + if(*damage) + { + AuraMap const& vAuras = pVictim->GetAuras(); + for(AuraMap::const_iterator itr = vAuras.begin(); itr != vAuras.end(); ++itr) + { + SpellEntry const *spellInfo = (*itr).second->GetSpellProto(); + if( (spellInfo->AttributesEx3 & 0x40000) && spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && + ((*itr).second->GetCasterGUID() == GetGUID() && (!spellCasted || spellCasted->Id == 35395)) ) + { + (*itr).second->SetAuraDuration((*itr).second->GetAuraMaxDuration()); + (*itr).second->UpdateAuraDuration(); + } + } + } + + CastMeleeProcDamageAndSpell(pVictim, (*damage - *absorbDamage - *resistDamage - *blocked_amount), damageSchoolMask, attType, outcome, spellCasted, isTriggeredSpell); + + // victim's damage shield + // yet another hack to fix crashes related to the aura getting removed during iteration + std::set alreadyDone; + uint32 removedAuras = pVictim->m_removedAuras; + AuraList const& vDamageShields = pVictim->GetAurasByType(SPELL_AURA_DAMAGE_SHIELD); + for(AuraList::const_iterator i = vDamageShields.begin(), next = vDamageShields.begin(); i != vDamageShields.end(); i = next) + { + ++next; + if (alreadyDone.find(*i) == alreadyDone.end()) + { + alreadyDone.insert(*i); + pVictim->SpellNonMeleeDamageLog(this, (*i)->GetId(), (*i)->GetModifier()->m_amount, false, false); + if (pVictim->m_removedAuras > removedAuras) + { + removedAuras = pVictim->m_removedAuras; + next = vDamageShields.begin(); + } + } + } +} + +void Unit::AttackerStateUpdate (Unit *pVictim, WeaponAttackType attType, bool extra ) +{ + if(hasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_STUNDED | UNIT_STAT_FLEEING) || HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED) ) + return; + + if (!pVictim->isAlive()) + return; + + if(IsNonMeleeSpellCasted(false)) + return; + + uint32 hitInfo; + if (attType == BASE_ATTACK) + hitInfo = HITINFO_NORMALSWING2; + else if (attType == OFF_ATTACK) + hitInfo = HITINFO_LEFTSWING; + else + return; // ignore ranaged case + + uint32 extraAttacks = m_extraAttacks; + + // melee attack spell casted at main hand attack only + if (attType == BASE_ATTACK && m_currentSpells[CURRENT_MELEE_SPELL]) + { + m_currentSpells[CURRENT_MELEE_SPELL]->cast(); + + // not recent extra attack only at any non extra attack (melee spell case) + if(!extra && extraAttacks) + { + while(m_extraAttacks) + { + AttackerStateUpdate(pVictim, BASE_ATTACK, true); + if(m_extraAttacks > 0) + --m_extraAttacks; + } + } + + return; + } + + VictimState victimState = VICTIMSTATE_NORMAL; + + CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL ); + uint32 blocked_dmg = 0; + uint32 absorbed_dmg = 0; + uint32 resisted_dmg = 0; + + SpellSchoolMask meleeSchoolMask = GetMeleeDamageSchoolMask(); + + if(pVictim->IsImmunedToDamage(meleeSchoolMask,true)) // use charges + { + SendAttackStateUpdate (HITINFO_NORMALSWING, pVictim, 1, meleeSchoolMask, 0, 0, 0, VICTIMSTATE_IS_IMMUNE, 0); + + // not recent extra attack only at any non extra attack (miss case) + if(!extra && extraAttacks) + { + while(m_extraAttacks) + { + AttackerStateUpdate(pVictim, BASE_ATTACK, true); + if(m_extraAttacks > 0) + --m_extraAttacks; + } + } + + return; + } + + uint32 damage = CalculateDamage (attType, false); + + DoAttackDamage (pVictim, &damage, &cleanDamage, &blocked_dmg, meleeSchoolMask, &hitInfo, &victimState, &absorbed_dmg, &resisted_dmg, attType); + + if (hitInfo & HITINFO_MISS) + //send miss + SendAttackStateUpdate (hitInfo, pVictim, 1, meleeSchoolMask, damage, absorbed_dmg, resisted_dmg, victimState, blocked_dmg); + else + { + //do animation + SendAttackStateUpdate (hitInfo, pVictim, 1, meleeSchoolMask, damage, absorbed_dmg, resisted_dmg, victimState, blocked_dmg); + + if (damage > (absorbed_dmg + resisted_dmg + blocked_dmg)) + damage -= (absorbed_dmg + resisted_dmg + blocked_dmg); + else + damage = 0; + + DealDamage (pVictim, damage, &cleanDamage, DIRECT_DAMAGE, meleeSchoolMask, NULL, true); + + if(GetTypeId() == TYPEID_PLAYER && pVictim->isAlive()) + { + for(int i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; i++) + ((Player*)this)->CastItemCombatSpell(((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0,i),pVictim,attType); + } + } + + if (GetTypeId() == TYPEID_PLAYER) + DEBUG_LOG("AttackerStateUpdate: (Player) %u attacked %u (TypeId: %u) for %u dmg, absorbed %u, blocked %u, resisted %u.", + GetGUIDLow(), pVictim->GetGUIDLow(), pVictim->GetTypeId(), damage, absorbed_dmg, blocked_dmg, resisted_dmg); + else + DEBUG_LOG("AttackerStateUpdate: (NPC) %u attacked %u (TypeId: %u) for %u dmg, absorbed %u, blocked %u, resisted %u.", + GetGUIDLow(), pVictim->GetGUIDLow(), pVictim->GetTypeId(), damage, absorbed_dmg, blocked_dmg, resisted_dmg); + + // extra attack only at any non extra attack (normal case) + if(!extra && extraAttacks) + { + while(m_extraAttacks) + { + AttackerStateUpdate(pVictim, BASE_ATTACK, true); + if(m_extraAttacks > 0) + --m_extraAttacks; + } + } +} + +MeleeHitOutcome Unit::RollPhysicalOutcomeAgainst (Unit const *pVictim, WeaponAttackType attType, SpellEntry const *spellInfo) +{ + // Miss chance based on melee + float miss_chance = MeleeMissChanceCalc(pVictim, attType); + + // Critical hit chance + float crit_chance = GetUnitCriticalChance(attType, pVictim); + // this is to avoid compiler issue when declaring variables inside if + float block_chance, parry_chance, dodge_chance; + + // cannot be dodged/parried/blocked + if(spellInfo->Attributes & SPELL_ATTR_IMPOSSIBLE_DODGE_PARRY_BLOCK) + { + block_chance = 0.0f; + parry_chance = 0.0f; + dodge_chance = 0.0f; + } + else + { + // parry can be avoided only by some abilites + parry_chance = pVictim->GetUnitParryChance(); + // block might be bypassed by it as well + block_chance = pVictim->GetUnitBlockChance(); + // stunned target cannot dodge and this is check in GetUnitDodgeChance() + dodge_chance = pVictim->GetUnitDodgeChance(); + } + + // Only players can have Talent&Spell bonuses + if (GetTypeId() == TYPEID_PLAYER) + { + // Increase from SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL aura + crit_chance += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL, spellInfo->SchoolMask); + + if( dodge_chance != 0.0f ) // if dodge chance is already 0, ignore talents fpr speed + { + AuraList const& mCanNotBeDodge = GetAurasByType(SPELL_AURA_IGNORE_COMBAT_RESULT); + for(AuraList::const_iterator i = mCanNotBeDodge.begin(); i != mCanNotBeDodge.end(); ++i) + { + // can't be dodged rogue finishing move + if((*i)->GetModifier()->m_miscvalue == VICTIMSTATE_DODGE) + { + if(spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE__FINISHING_MOVE)) + { + dodge_chance = 0.0f; + break; + } + } + } + } + } + + // Spellmods + if(Player* modOwner = GetSpellModOwner()) + modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CRITICAL_CHANCE, crit_chance); + + DEBUG_LOG("PHYSICAL OUTCOME: miss %f crit %f dodge %f parry %f block %f",miss_chance,crit_chance,dodge_chance,parry_chance, block_chance); + + return RollMeleeOutcomeAgainst(pVictim, attType, int32(crit_chance*100), int32(miss_chance*100),int32(dodge_chance*100),int32(parry_chance*100),int32(block_chance*100), true); +} + +MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(const Unit *pVictim, WeaponAttackType attType) const +{ + // This is only wrapper + + // Miss chance based on melee + float miss_chance = MeleeMissChanceCalc(pVictim, attType); + + // Critical hit chance + float crit_chance = GetUnitCriticalChance(attType, pVictim); + + // stunned target cannot dodge and this is check in GetUnitDodgeChance() (returned 0 in this case) + float dodge_chance = pVictim->GetUnitDodgeChance(); + float block_chance = pVictim->GetUnitBlockChance(); + float parry_chance = pVictim->GetUnitParryChance(); + + // Useful if want to specify crit & miss chances for melee, else it could be removed + DEBUG_LOG("MELEE OUTCOME: miss %f crit %f dodge %f parry %f block %f", miss_chance,crit_chance,dodge_chance,parry_chance,block_chance); + + return RollMeleeOutcomeAgainst(pVictim, attType, int32(crit_chance*100), int32(miss_chance*100), int32(dodge_chance*100),int32(parry_chance*100),int32(block_chance*100), false); +} + +MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType, int32 crit_chance, int32 miss_chance, int32 dodge_chance, int32 parry_chance, int32 block_chance, bool SpellCasted ) const +{ + if(pVictim->GetTypeId()==TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode()) + return MELEE_HIT_EVADE; + + int32 attackerMaxSkillValueForLevel = GetMaxSkillValueForLevel(pVictim); + int32 victimMaxSkillValueForLevel = pVictim->GetMaxSkillValueForLevel(this); + + int32 attackerWeaponSkill = GetWeaponSkillValue(attType,pVictim); + int32 victimDefenseSkill = pVictim->GetDefenseSkillValue(this); + + // bonus from skills is 0.04% + int32 skillBonus = 4 * ( attackerWeaponSkill - victimMaxSkillValueForLevel ); + int32 skillBonus2 = 4 * ( attackerMaxSkillValueForLevel - victimDefenseSkill ); + int32 sum = 0, tmp = 0; + int32 roll = urand (0, 10000); + + DEBUG_LOG ("RollMeleeOutcomeAgainst: skill bonus of %d for attacker", skillBonus); + DEBUG_LOG ("RollMeleeOutcomeAgainst: rolled %d, miss %d, dodge %d, parry %d, block %d, crit %d", + roll, miss_chance, dodge_chance, parry_chance, block_chance, crit_chance); + + tmp = miss_chance; + + if (tmp > 0 && roll < (sum += tmp )) + { + DEBUG_LOG ("RollMeleeOutcomeAgainst: MISS"); + return MELEE_HIT_MISS; + } + + // always crit against a sitting target (except 0 crit chance) + if( pVictim->GetTypeId() == TYPEID_PLAYER && crit_chance > 0 && !pVictim->IsStandState() ) + { + DEBUG_LOG ("RollMeleeOutcomeAgainst: CRIT (sitting victim)"); + return MELEE_HIT_CRIT; + } + + // Dodge chance + + // only players can't dodge if attacker is behind + if (pVictim->GetTypeId() == TYPEID_PLAYER && !pVictim->HasInArc(M_PI,this)) + { + DEBUG_LOG ("RollMeleeOutcomeAgainst: attack came from behind and victim was a player."); + } + else + { + // Reduce dodge chance by attacker expertise rating + if (GetTypeId() == TYPEID_PLAYER) + dodge_chance -= int32(((Player*)this)->GetExpertiseDodgeOrParryReduction(attType)*100); + + // Modify dodge chance by attacker SPELL_AURA_MOD_COMBAT_RESULT_CHANCE + dodge_chance+= GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_COMBAT_RESULT_CHANCE, VICTIMSTATE_DODGE); + + tmp = dodge_chance; + if ( (tmp > 0) // check if unit _can_ dodge + && ((tmp -= skillBonus) > 0) + && roll < (sum += tmp)) + { + DEBUG_LOG ("RollMeleeOutcomeAgainst: DODGE <%d, %d)", sum-tmp, sum); + return MELEE_HIT_DODGE; + } + } + + // parry & block chances + + // check if attack comes from behind, nobody can parry or block if attacker is behind + if (!pVictim->HasInArc(M_PI,this)) + { + DEBUG_LOG ("RollMeleeOutcomeAgainst: attack came from behind."); + } + else + { + // Reduce parry chance by attacker expertise rating + if (GetTypeId() == TYPEID_PLAYER) + parry_chance-= int32(((Player*)this)->GetExpertiseDodgeOrParryReduction(attType)*100); + + if(pVictim->GetTypeId()==TYPEID_PLAYER || !(((Creature*)pVictim)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_NO_PARRY) ) + { + int32 tmp = int32(parry_chance); + if ( (tmp > 0) // check if unit _can_ parry + && ((tmp -= skillBonus) > 0) + && (roll < (sum += tmp))) + { + DEBUG_LOG ("RollMeleeOutcomeAgainst: PARRY <%d, %d)", sum-tmp, sum); + return MELEE_HIT_PARRY; + } + } + + if(pVictim->GetTypeId()==TYPEID_PLAYER || !(((Creature*)pVictim)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_NO_BLOCK) ) + { + tmp = block_chance; + if ( (tmp > 0) // check if unit _can_ block + && ((tmp -= skillBonus) > 0) + && (roll < (sum += tmp))) + { + // Critical chance + tmp = crit_chance + skillBonus2; + if ( GetTypeId() == TYPEID_PLAYER && SpellCasted && tmp > 0 ) + { + if ( roll_chance_i(tmp/100)) + { + DEBUG_LOG ("RollMeleeOutcomeAgainst: BLOCKED CRIT"); + return MELEE_HIT_BLOCK_CRIT; + } + } + DEBUG_LOG ("RollMeleeOutcomeAgainst: BLOCK <%d, %d)", sum-tmp, sum); + return MELEE_HIT_BLOCK; + } + } + } + + // Critical chance + tmp = crit_chance + skillBonus2; + + if (tmp > 0 && roll < (sum += tmp)) + { + DEBUG_LOG ("RollMeleeOutcomeAgainst: CRIT <%d, %d)", sum-tmp, sum); + return MELEE_HIT_CRIT; + } + + // Max 40% chance to score a glancing blow against mobs that are higher level (can do only players and pets and not with ranged weapon) + if( attType != RANGED_ATTACK && !SpellCasted && + (GetTypeId() == TYPEID_PLAYER || ((Creature*)this)->isPet()) && + pVictim->GetTypeId() != TYPEID_PLAYER && !((Creature*)pVictim)->isPet() && + getLevel() < pVictim->getLevelForTarget(this) ) + { + // cap possible value (with bonuses > max skill) + int32 skill = attackerWeaponSkill; + int32 maxskill = attackerMaxSkillValueForLevel; + skill = (skill > maxskill) ? maxskill : skill; + + tmp = (10 + (victimDefenseSkill - skill)) * 100; + tmp = tmp > 4000 ? 4000 : tmp; + if (roll < (sum += tmp)) + { + DEBUG_LOG ("RollMeleeOutcomeAgainst: GLANCING <%d, %d)", sum-4000, sum); + return MELEE_HIT_GLANCING; + } + } + + if(GetTypeId()!=TYPEID_PLAYER && !(((Creature*)this)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_NO_CRUSH) && !((Creature*)this)->isPet() ) + { + // mobs can score crushing blows if they're 3 or more levels above victim + // or when their weapon skill is 15 or more above victim's defense skill + tmp = victimDefenseSkill; + int32 tmpmax = victimMaxSkillValueForLevel; + // having defense above your maximum (from items, talents etc.) has no effect + tmp = tmp > tmpmax ? tmpmax : tmp; + // tmp = mob's level * 5 - player's current defense skill + tmp = attackerMaxSkillValueForLevel - tmp; + if(tmp >= 15) + { + // add 2% chance per lacking skill point, min. is 15% + tmp = tmp * 200 - 1500; + if (roll < (sum += tmp)) + { + DEBUG_LOG ("RollMeleeOutcomeAgainst: CRUSHING <%d, %d)", sum-tmp, sum); + return MELEE_HIT_CRUSHING; + } + } + } + + DEBUG_LOG ("RollMeleeOutcomeAgainst: NORMAL"); + return MELEE_HIT_NORMAL; +} + +uint32 Unit::CalculateDamage (WeaponAttackType attType, bool normalized) +{ + float min_damage, max_damage; + + if (normalized && GetTypeId()==TYPEID_PLAYER) + ((Player*)this)->CalculateMinMaxDamage(attType,normalized,min_damage, max_damage); + else + { + switch (attType) + { + case RANGED_ATTACK: + min_damage = GetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE); + max_damage = GetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE); + break; + case BASE_ATTACK: + min_damage = GetFloatValue(UNIT_FIELD_MINDAMAGE); + max_damage = GetFloatValue(UNIT_FIELD_MAXDAMAGE); + break; + case OFF_ATTACK: + min_damage = GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE); + max_damage = GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE); + break; + // Just for good manner + default: + min_damage = 0.0f; + max_damage = 0.0f; + break; + } + } + + if (min_damage > max_damage) + { + std::swap(min_damage,max_damage); + } + + if(max_damage == 0.0f) + max_damage = 5.0f; + + return urand((uint32)min_damage, (uint32)max_damage); +} + +float Unit::CalculateLevelPenalty(SpellEntry const* spellProto) const +{ + if(spellProto->spellLevel <= 0) + return 1.0f; + + float LvlPenalty = 0.0f; + + if(spellProto->spellLevel < 20) + LvlPenalty = 20.0f - spellProto->spellLevel * 3.75f; + float LvlFactor = (float(spellProto->spellLevel) + 6.0f) / float(getLevel()); + if(LvlFactor > 1.0f) + LvlFactor = 1.0f; + + return (100.0f - LvlPenalty) * LvlFactor / 100.0f; +} + +void Unit::SendAttackStart(Unit* pVictim) +{ + WorldPacket data( SMSG_ATTACKSTART, 16 ); + data << GetGUID(); + data << pVictim->GetGUID(); + + SendMessageToSet(&data, true); + DEBUG_LOG( "WORLD: Sent SMSG_ATTACKSTART" ); +} + +void Unit::SendAttackStop(Unit* victim) +{ + if(!victim) + return; + + WorldPacket data( SMSG_ATTACKSTOP, (4+16) ); // we guess size + data.append(GetPackGUID()); + data.append(victim->GetPackGUID()); // can be 0x00... + data << uint32(0); // can be 0x1 + SendMessageToSet(&data, true); + sLog.outDetail("%s %u stopped attacking %s %u", (GetTypeId()==TYPEID_PLAYER ? "player" : "creature"), GetGUIDLow(), (victim->GetTypeId()==TYPEID_PLAYER ? "player" : "creature"),victim->GetGUIDLow()); + + /*if(victim->GetTypeId() == TYPEID_UNIT) + ((Creature*)victim)->AI().EnterEvadeMode(this);*/ +} + +/* +// Melee based spells can be miss, parry or dodge on this step +// Crit or block - determined on damage calculation phase! (and can be both in some time) +float Unit::MeleeSpellMissChance(Unit *pVictim, WeaponAttackType attType, int32 skillDiff, SpellEntry const *spell) +{ + // Calculate hit chance (more correct for chance mod) + int32 HitChance; + + // PvP - PvE melee chances + int32 lchance = pVictim->GetTypeId() == TYPEID_PLAYER ? 5 : 7; + int32 leveldif = pVictim->getLevelForTarget(this) - getLevelForTarget(pVictim); + if(leveldif < 3) + HitChance = 95 - leveldif; + else + HitChance = 93 - (leveldif - 2) * lchance; + + // Hit chance depends from victim auras + if(attType == RANGED_ATTACK) + HitChance += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE); + else + HitChance += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE); + + // Spellmod from SPELLMOD_RESIST_MISS_CHANCE + if(Player *modOwner = GetSpellModOwner()) + modOwner->ApplySpellMod(spell->Id, SPELLMOD_RESIST_MISS_CHANCE, HitChance); + + // Miss = 100 - hit + float miss_chance= 100.0f - HitChance; + + // Bonuses from attacker aura and ratings + if (attType == RANGED_ATTACK) + miss_chance -= m_modRangedHitChance; + else + miss_chance -= m_modMeleeHitChance; + + // bonus from skills is 0.04% + miss_chance -= skillDiff * 0.04f; + + // Limit miss chance from 0 to 60% + if (miss_chance < 0.0f) + return 0.0f; + if (miss_chance > 60.0f) + return 60.0f; + return miss_chance; +} + +// Melee based spells hit result calculations +SpellMissInfo Unit::MeleeSpellHitResult(Unit *pVictim, SpellEntry const *spell) +{ + WeaponAttackType attType = BASE_ATTACK; + + if (spell->DmgClass == SPELL_DAMAGE_CLASS_RANGED) + attType = RANGED_ATTACK; + + // bonus from skills is 0.04% per skill Diff + int32 attackerWeaponSkill = int32(GetWeaponSkillValue(attType,pVictim)); + int32 skillDiff = attackerWeaponSkill - int32(pVictim->GetMaxSkillValueForLevel(this)); + int32 fullSkillDiff = attackerWeaponSkill - int32(pVictim->GetDefenseSkillValue(this)); + + uint32 roll = urand (0, 10000); + uint32 missChance = uint32(MeleeSpellMissChance(pVictim, attType, fullSkillDiff, spell)*100.0f); + + // Roll miss + uint32 tmp = missChance; + if (roll < tmp) + return SPELL_MISS_MISS; + + // Same spells cannot be parry/dodge + if (spell->Attributes & SPELL_ATTR_IMPOSSIBLE_DODGE_PARRY_BLOCK) + return SPELL_MISS_NONE; + + // Ranged attack can`t miss too + if (attType == RANGED_ATTACK) + return SPELL_MISS_NONE; + + bool attackFromBehind = !pVictim->HasInArc(M_PI,this); + + // Roll dodge + int32 dodgeChance = int32(pVictim->GetUnitDodgeChance()*100.0f) - skillDiff * 4; + // Reduce enemy dodge chance by SPELL_AURA_MOD_COMBAT_RESULT_CHANCE + dodgeChance+= GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_COMBAT_RESULT_CHANCE, VICTIMSTATE_DODGE); + + // Reduce dodge chance by attacker expertise rating + if (GetTypeId() == TYPEID_PLAYER) + dodgeChance-=int32(((Player*)this)->GetExpertiseDodgeOrParryReduction(attType) * 100.0f); + if (dodgeChance < 0) + dodgeChance = 0; + + // Can`t dodge from behind in PvP (but its possible in PvE) + if (GetTypeId() == TYPEID_PLAYER && pVictim->GetTypeId() == TYPEID_PLAYER && attackFromBehind) + dodgeChance = 0; + + // Rogue talent`s cant be dodged + AuraList const& mCanNotBeDodge = GetAurasByType(SPELL_AURA_IGNORE_COMBAT_RESULT); + for(AuraList::const_iterator i = mCanNotBeDodge.begin(); i != mCanNotBeDodge.end(); ++i) + { + if((*i)->GetModifier()->m_miscvalue == VICTIMSTATE_DODGE) // can't be dodged rogue finishing move + { + if(spell->SpellFamilyName==SPELLFAMILY_ROGUE && (spell->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE__FINISHING_MOVE)) + { + dodgeChance = 0; + break; + } + } + } + + tmp += dodgeChance; + if (roll < tmp) + return SPELL_MISS_DODGE; + + // Roll parry + int32 parryChance = int32(pVictim->GetUnitParryChance()*100.0f) - skillDiff * 4; + // Reduce parry chance by attacker expertise rating + if (GetTypeId() == TYPEID_PLAYER) + parryChance-=int32(((Player*)this)->GetExpertiseDodgeOrParryReduction(attType) * 100.0f); + // Can`t parry from behind + if (parryChance < 0 || attackFromBehind) + parryChance = 0; + + tmp += parryChance; + if (roll < tmp) + return SPELL_MISS_PARRY; + + return SPELL_MISS_NONE; +}*/ + +// TODO need use unit spell resistances in calculations +SpellMissInfo Unit::MagicSpellHitResult(Unit *pVictim, SpellEntry const *spell) +{ + // Can`t miss on dead target (on skinning for example) + if (!pVictim->isAlive()) + return SPELL_MISS_NONE; + + SpellSchoolMask schoolMask = GetSpellSchoolMask(spell); + // PvP - PvE spell misschances per leveldif > 2 + int32 lchance = pVictim->GetTypeId() == TYPEID_PLAYER ? 7 : 11; + int32 leveldif = int32(pVictim->getLevelForTarget(this)) - int32(getLevelForTarget(pVictim)); + + // Base hit chance from attacker and victim levels + int32 modHitChance; + if(leveldif < 3) + modHitChance = 96 - leveldif; + else + modHitChance = 94 - (leveldif - 2) * lchance; + + // Spellmod from SPELLMOD_RESIST_MISS_CHANCE + if(Player *modOwner = GetSpellModOwner()) + modOwner->ApplySpellMod(spell->Id, SPELLMOD_RESIST_MISS_CHANCE, modHitChance); + // Increase from attacker SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT auras + modHitChance+=GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT, schoolMask); + // Chance hit from victim SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE auras + modHitChance+= pVictim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE, schoolMask); + // Reduce spell hit chance for Area of effect spells from victim SPELL_AURA_MOD_AOE_AVOIDANCE aura + if (IsAreaOfEffectSpell(spell)) + modHitChance-=pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_AOE_AVOIDANCE); + // Reduce spell hit chance for dispel mechanic spells from victim SPELL_AURA_MOD_DISPEL_RESIST + if (IsDispelSpell(spell)) + modHitChance-=pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_DISPEL_RESIST); + // Chance resist mechanic (select max value from every mechanic spell effect) + int32 resist_mech = 0; + // Get effects mechanic and chance + for(int eff = 0; eff < 3; ++eff) + { + int32 effect_mech = GetEffectMechanic(spell, eff); + if (effect_mech) + { + int32 temp = pVictim->GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_MECHANIC_RESISTANCE, effect_mech); + if (resist_mech < temp) + resist_mech = temp; + } + } + // Apply mod + modHitChance-=resist_mech; + + // Chance resist debuff + modHitChance-=pVictim->GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_DEBUFF_RESISTANCE, int32(spell->Dispel)); + + int32 HitChance = modHitChance * 100; + // Increase hit chance from attacker SPELL_AURA_MOD_SPELL_HIT_CHANCE and attacker ratings + HitChance += int32(m_modSpellHitChance*100.0f); + + // Decrease hit chance from victim rating bonus + if (pVictim->GetTypeId()==TYPEID_PLAYER) + HitChance -= int32(((Player*)pVictim)->GetRatingBonusValue(CR_HIT_TAKEN_SPELL)*100.0f); + + if (HitChance < 100) HitChance = 100; + if (HitChance > 9900) HitChance = 9900; + + uint32 rand = urand(0,10000); + if (rand > HitChance) + return SPELL_MISS_RESIST; + return SPELL_MISS_NONE; +} + +SpellMissInfo Unit::SpellHitResult(Unit *pVictim, SpellEntry const *spell, bool CanReflect) +{ + // Return evade for units in evade mode + if (pVictim->GetTypeId()==TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode()) + return SPELL_MISS_EVADE; + + // Check for immune (use charges) + if (pVictim->IsImmunedToSpell(spell,true)) + return SPELL_MISS_IMMUNE; + + // All positive spells can`t miss + // TODO: client not show miss log for this spells - so need find info for this in dbc and use it! + if (IsPositiveSpell(spell->Id)) + return SPELL_MISS_NONE; + + // Check for immune (use charges) + if (pVictim->IsImmunedToDamage(GetSpellSchoolMask(spell),true)) + return SPELL_MISS_IMMUNE; + + // Try victim reflect spell + if (CanReflect) + { + // specialized first + Unit::AuraList const& mReflectSpellsSchool = pVictim->GetAurasByType(SPELL_AURA_REFLECT_SPELLS_SCHOOL); + for(Unit::AuraList::const_iterator i = mReflectSpellsSchool.begin(); i != mReflectSpellsSchool.end(); ++i) + { + if((*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spell)) + { + int32 reflectchance = (*i)->GetModifier()->m_amount; + if (reflectchance > 0 && roll_chance_i(reflectchance)) + { + if((*i)->m_procCharges > 0) + { + --(*i)->m_procCharges; + if((*i)->m_procCharges==0) + pVictim->RemoveAurasDueToSpell((*i)->GetId()); + } + return SPELL_MISS_REFLECT; + } + } + } + + // generic reflection + Unit::AuraList const& mReflectSpells = pVictim->GetAurasByType(SPELL_AURA_REFLECT_SPELLS); + for(Unit::AuraList::const_iterator i = mReflectSpells.begin(); i != mReflectSpells.end(); ++i) + { + int32 reflectchance = (*i)->GetModifier()->m_amount; + if (reflectchance > 0 && roll_chance_i(reflectchance)) + { + if((*i)->m_procCharges > 0) + { + --(*i)->m_procCharges; + if((*i)->m_procCharges==0) + pVictim->RemoveAurasDueToSpell((*i)->GetId()); + } + return SPELL_MISS_REFLECT; + } + } + } + + // Temporary solution for melee based spells and spells vs SPELL_SCHOOL_NORMAL (hit result calculated after) + for (int i=0;i<3;i++) + { + if (spell->Effect[i] == SPELL_EFFECT_WEAPON_DAMAGE || + spell->Effect[i] == SPELL_EFFECT_WEAPON_PERCENT_DAMAGE || + spell->Effect[i] == SPELL_EFFECT_NORMALIZED_WEAPON_DMG || + spell->Effect[i] == SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL) + return SPELL_MISS_NONE; + } + + // TODO need use this code for spell hit result calculation + // now code commented for compotability + switch (spell->DmgClass) + { + case SPELL_DAMAGE_CLASS_RANGED: + case SPELL_DAMAGE_CLASS_MELEE: +// return MeleeSpellHitResult(pVictim, spell); + return SPELL_MISS_NONE; + case SPELL_DAMAGE_CLASS_NONE: + case SPELL_DAMAGE_CLASS_MAGIC: + return MagicSpellHitResult(pVictim, spell); + } + return SPELL_MISS_NONE; +} + +float Unit::MeleeMissChanceCalc(const Unit *pVictim, WeaponAttackType attType) const +{ + if(!pVictim) + return 0.0f; + + // Base misschance 5% + float misschance = 5.0f; + + // DualWield - Melee spells and physical dmg spells - 5% , white damage 24% + if (haveOffhandWeapon() && attType != RANGED_ATTACK) + { + bool isNormal = false; + for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++) + { + if( m_currentSpells[i] && (GetSpellSchoolMask(m_currentSpells[i]->m_spellInfo) & SPELL_SCHOOL_MASK_NORMAL) ) + { + isNormal = true; + break; + } + } + if (isNormal || m_currentSpells[CURRENT_MELEE_SPELL]) + { + misschance = 5.0f; + } + else + { + misschance = 24.0f; + } + } + + // PvP : PvE melee misschances per leveldif > 2 + int32 chance = pVictim->GetTypeId() == TYPEID_PLAYER ? 5 : 7; + + int32 leveldif = int32(pVictim->getLevelForTarget(this)) - int32(getLevelForTarget(pVictim)); + if(leveldif < 0) + leveldif = 0; + + // Hit chance from attacker based on ratings and auras + float m_modHitChance; + if (attType == RANGED_ATTACK) + m_modHitChance = m_modRangedHitChance; + else + m_modHitChance = m_modMeleeHitChance; + + if(leveldif < 3) + misschance += (leveldif - m_modHitChance); + else + misschance += ((leveldif - 2) * chance - m_modHitChance); + + // Hit chance for victim based on ratings + if (pVictim->GetTypeId()==TYPEID_PLAYER) + { + if (attType == RANGED_ATTACK) + misschance += ((Player*)pVictim)->GetRatingBonusValue(CR_HIT_TAKEN_RANGED); + else + misschance += ((Player*)pVictim)->GetRatingBonusValue(CR_HIT_TAKEN_MELEE); + } + + // Modify miss chance by victim auras + if(attType == RANGED_ATTACK) + misschance -= pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE); + else + misschance -= pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE); + + // Modify miss chance from skill difference ( bonus from skills is 0.04% ) + int32 skillBonus = int32(GetWeaponSkillValue(attType,pVictim)) - int32(pVictim->GetDefenseSkillValue(this)); + misschance -= skillBonus * 0.04f; + + // Limit miss chance from 0 to 60% + if ( misschance < 0.0f) + return 0.0f; + if ( misschance > 60.0f) + return 60.0f; + + return misschance; +} + +uint32 Unit::GetDefenseSkillValue(Unit const* target) const +{ + if(GetTypeId() == TYPEID_PLAYER) + { + // in PvP use full skill instead current skill value + uint32 value = (target && target->GetTypeId() == TYPEID_PLAYER) + ? ((Player*)this)->GetMaxSkillValue(SKILL_DEFENSE) + : ((Player*)this)->GetSkillValue(SKILL_DEFENSE); + value += uint32(((Player*)this)->GetRatingBonusValue(CR_DEFENSE_SKILL)); + return value; + } + else + return GetUnitMeleeSkill(target); +} + +float Unit::GetUnitDodgeChance() const +{ + if(hasUnitState(UNIT_STAT_STUNDED)) + return 0.0f; + if( GetTypeId() == TYPEID_PLAYER ) + return GetFloatValue(PLAYER_DODGE_PERCENTAGE); + else + { + if(((Creature const*)this)->isTotem()) + return 0.0f; + else + { + float dodge = 5.0f; + dodge += GetTotalAuraModifier(SPELL_AURA_MOD_DODGE_PERCENT); + return dodge > 0.0f ? dodge : 0.0f; + } + } +} + +float Unit::GetUnitParryChance() const +{ + if ( IsNonMeleeSpellCasted(false) || hasUnitState(UNIT_STAT_STUNDED)) + return 0.0f; + + float chance = 0.0f; + + if(GetTypeId() == TYPEID_PLAYER) + { + Player const* player = (Player const*)this; + if(player->CanParry() ) + { + Item *tmpitem = ((Player*)this)->GetWeaponForAttack(BASE_ATTACK,true); + if(!tmpitem) + tmpitem = ((Player*)this)->GetWeaponForAttack(OFF_ATTACK,true); + + if(tmpitem) + chance = GetFloatValue(PLAYER_PARRY_PERCENTAGE); + } + } + else if(GetTypeId() == TYPEID_UNIT) + { + if(GetCreatureType() == CREATURE_TYPE_HUMANOID) + { + chance = 5.0f; + chance += GetTotalAuraModifier(SPELL_AURA_MOD_PARRY_PERCENT); + } + } + + return chance > 0.0f ? chance : 0.0f; +} + +float Unit::GetUnitBlockChance() const +{ + if ( IsNonMeleeSpellCasted(false) || hasUnitState(UNIT_STAT_STUNDED)) + return 0.0f; + + if(GetTypeId() == TYPEID_PLAYER) + { + Item *tmpitem = ((Player const*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); + if(tmpitem && !tmpitem->IsBroken() && tmpitem->GetProto()->Block) + return GetFloatValue(PLAYER_BLOCK_PERCENTAGE); + else + return 0.0f; + } + else + { + if(((Creature const*)this)->isTotem()) + return 0.0f; + else + { + float block = 5.0f; + block += GetTotalAuraModifier(SPELL_AURA_MOD_BLOCK_PERCENT); + return block > 0.0f ? block : 0.0f; + } + } +} + +float Unit::GetUnitCriticalChance(WeaponAttackType attackType, const Unit *pVictim) const +{ + float crit; + + if(GetTypeId() == TYPEID_PLAYER) + { + switch(attackType) + { + case BASE_ATTACK: + crit = GetFloatValue( PLAYER_CRIT_PERCENTAGE ); + break; + case OFF_ATTACK: + crit = GetFloatValue( PLAYER_OFFHAND_CRIT_PERCENTAGE ); + break; + case RANGED_ATTACK: + crit = GetFloatValue( PLAYER_RANGED_CRIT_PERCENTAGE ); + break; + // Just for good manner + default: + crit = 0.0f; + break; + } + } + else + { + crit = 5.0f; + crit += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_PERCENT); + } + + // flat aura mods + if(attackType == RANGED_ATTACK) + crit += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_CHANCE); + else + crit += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_CHANCE); + + crit += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE); + + // reduce crit chance from Rating for players + if (pVictim->GetTypeId()==TYPEID_PLAYER) + { + if (attackType==RANGED_ATTACK) + crit -= ((Player*)pVictim)->GetRatingBonusValue(CR_CRIT_TAKEN_RANGED); + else + crit -= ((Player*)pVictim)->GetRatingBonusValue(CR_CRIT_TAKEN_MELEE); + } + + if (crit < 0.0f) + crit = 0.0f; + return crit; +} + +uint32 Unit::GetWeaponSkillValue (WeaponAttackType attType, Unit const* target) const +{ + uint32 value = 0; + if(GetTypeId() == TYPEID_PLAYER) + { + Item* item = ((Player*)this)->GetWeaponForAttack(attType,true); + + // feral or unarmed skill only for base attack + if(attType != BASE_ATTACK && !item ) + return 0; + + if(((Player*)this)->IsInFeralForm()) + return GetMaxSkillValueForLevel(); // always maximized SKILL_FERAL_COMBAT in fact + + // weaon skill or (unarmed for base attack) + uint32 skill = item ? item->GetSkill() : SKILL_UNARMED; + + // in PvP use full skill instead current skill value + value = (target && target->GetTypeId() == TYPEID_PLAYER) + ? ((Player*)this)->GetMaxSkillValue(skill) + : ((Player*)this)->GetSkillValue(skill); + // Modify value from ratings + value += uint32(((Player*)this)->GetRatingBonusValue(CR_WEAPON_SKILL)); + switch (attType) + { + case BASE_ATTACK: value+=uint32(((Player*)this)->GetRatingBonusValue(CR_WEAPON_SKILL_MAINHAND));break; + case OFF_ATTACK: value+=uint32(((Player*)this)->GetRatingBonusValue(CR_WEAPON_SKILL_OFFHAND));break; + case RANGED_ATTACK: value+=uint32(((Player*)this)->GetRatingBonusValue(CR_WEAPON_SKILL_RANGED));break; + } + } + else + value = GetUnitMeleeSkill(target); + return value; +} + +void Unit::_UpdateSpells( uint32 time ) +{ + if(m_currentSpells[CURRENT_AUTOREPEAT_SPELL]) + _UpdateAutoRepeatSpell(); + + // remove finished spells from current pointers + for (uint32 i = 0; i < CURRENT_MAX_SPELL; i++) + { + if (m_currentSpells[i] && m_currentSpells[i]->getState() == SPELL_STATE_FINISHED) + { + m_currentSpells[i]->SetDeletable(true); // spell may be safely deleted now + m_currentSpells[i] = NULL; // remove pointer + } + } + + // TODO: Find a better way to prevent crash when multiple auras are removed. + m_removedAuras = 0; + for (AuraMap::iterator i = m_Auras.begin(); i != m_Auras.end(); ++i) + if ((*i).second) + (*i).second->SetUpdated(false); + + for (AuraMap::iterator i = m_Auras.begin(), next; i != m_Auras.end(); i = next) + { + next = i; + ++next; + if ((*i).second) + { + // prevent double update + if ((*i).second->IsUpdated()) + continue; + (*i).second->SetUpdated(true); + (*i).second->Update( time ); + // several auras can be deleted due to update + if (m_removedAuras) + { + if (m_Auras.empty()) break; + next = m_Auras.begin(); + m_removedAuras = 0; + } + } + } + + for (AuraMap::iterator i = m_Auras.begin(); i != m_Auras.end();) + { + if ((*i).second) + { + if ( !(*i).second->GetAuraDuration() && !((*i).second->IsPermanent() || ((*i).second->IsPassive())) ) + { + RemoveAura(i); + } + else + { + ++i; + } + } + else + { + ++i; + } + } + + if(!m_gameObj.empty()) + { + std::list::iterator ite1, dnext1; + for (ite1 = m_gameObj.begin(); ite1 != m_gameObj.end(); ite1 = dnext1) + { + dnext1 = ite1; + //(*i)->Update( difftime ); + if( !(*ite1)->isSpawned() ) + { + (*ite1)->SetOwnerGUID(0); + (*ite1)->SetRespawnTime(0); + (*ite1)->Delete(); + dnext1 = m_gameObj.erase(ite1); + } + else + ++dnext1; + } + } +} + +void Unit::_UpdateAutoRepeatSpell() +{ + //check "realtime" interrupts + if ( (GetTypeId() == TYPEID_PLAYER && ((Player*)this)->isMoving()) || IsNonMeleeSpellCasted(false,false,true) ) + { + // cancel wand shoot + if(m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Category == 351) + InterruptSpell(CURRENT_AUTOREPEAT_SPELL); + m_AutoRepeatFirstCast = true; + return; + } + + //apply delay + if ( m_AutoRepeatFirstCast && getAttackTimer(RANGED_ATTACK) < 500 ) + setAttackTimer(RANGED_ATTACK,500); + m_AutoRepeatFirstCast = false; + + //castroutine + if (isAttackReady(RANGED_ATTACK)) + { + // Check if able to cast + if(m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->CanCast(true)) + { + InterruptSpell(CURRENT_AUTOREPEAT_SPELL); + return; + } + + // we want to shoot + Spell* spell = new Spell(this, m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo, true, 0); + spell->prepare(&(m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_targets)); + + // all went good, reset attack + resetAttackTimer(RANGED_ATTACK); + } +} + +void Unit::SetCurrentCastedSpell( Spell * pSpell ) +{ + assert(pSpell); // NULL may be never passed here, use InterruptSpell or InterruptNonMeleeSpells + + uint32 CSpellType = pSpell->GetCurrentContainer(); + + pSpell->SetDeletable(false); // spell will not be deleted until gone from current pointers + if (pSpell == m_currentSpells[CSpellType]) return; // avoid breaking self + + // break same type spell if it is not delayed + InterruptSpell(CSpellType,false); + + // special breakage effects: + switch (CSpellType) + { + case CURRENT_GENERIC_SPELL: + { + // generic spells always break channeled not delayed spells + InterruptSpell(CURRENT_CHANNELED_SPELL,false); + + // autorepeat breaking + if ( m_currentSpells[CURRENT_AUTOREPEAT_SPELL] ) + { + // break autorepeat if not Auto Shot + if (m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Category == 351) + InterruptSpell(CURRENT_AUTOREPEAT_SPELL); + m_AutoRepeatFirstCast = true; + } + } break; + + case CURRENT_CHANNELED_SPELL: + { + // channel spells always break generic non-delayed and any channeled spells + InterruptSpell(CURRENT_GENERIC_SPELL,false); + InterruptSpell(CURRENT_CHANNELED_SPELL); + + // it also does break autorepeat if not Auto Shot + if ( m_currentSpells[CURRENT_AUTOREPEAT_SPELL] && + m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Category == 351 ) + InterruptSpell(CURRENT_AUTOREPEAT_SPELL); + } break; + + case CURRENT_AUTOREPEAT_SPELL: + { + // only Auto Shoot does not break anything + if (pSpell->m_spellInfo->Category == 351) + { + // generic autorepeats break generic non-delayed and channeled non-delayed spells + InterruptSpell(CURRENT_GENERIC_SPELL,false); + InterruptSpell(CURRENT_CHANNELED_SPELL,false); + } + // special action: set first cast flag + m_AutoRepeatFirstCast = true; + } break; + + default: + { + // other spell types don't break anything now + } break; + } + + // current spell (if it is still here) may be safely deleted now + if (m_currentSpells[CSpellType]) + m_currentSpells[CSpellType]->SetDeletable(true); + + // set new current spell + m_currentSpells[CSpellType] = pSpell; +} + +void Unit::InterruptSpell(uint32 spellType, bool withDelayed) +{ + assert(spellType < CURRENT_MAX_SPELL); + + if(m_currentSpells[spellType] && (withDelayed || m_currentSpells[spellType]->getState() != SPELL_STATE_DELAYED) ) + { + // send autorepeat cancel message for autorepeat spells + if (spellType == CURRENT_AUTOREPEAT_SPELL) + { + if(GetTypeId()==TYPEID_PLAYER) + ((Player*)this)->SendAutoRepeatCancel(); + } + + if (m_currentSpells[spellType]->getState() != SPELL_STATE_FINISHED) + m_currentSpells[spellType]->cancel(); + m_currentSpells[spellType]->SetDeletable(true); + m_currentSpells[spellType] = NULL; + } +} + +bool Unit::IsNonMeleeSpellCasted(bool withDelayed, bool skipChanneled, bool skipAutorepeat) const +{ + // We don't do loop here to explicitly show that melee spell is excluded. + // Maybe later some special spells will be excluded too. + + // generic spells are casted when they are not finished and not delayed + if ( m_currentSpells[CURRENT_GENERIC_SPELL] && + (m_currentSpells[CURRENT_GENERIC_SPELL]->getState() != SPELL_STATE_FINISHED) && + (withDelayed || m_currentSpells[CURRENT_GENERIC_SPELL]->getState() != SPELL_STATE_DELAYED) ) + return(true); + + // channeled spells may be delayed, but they are still considered casted + else if ( !skipChanneled && m_currentSpells[CURRENT_CHANNELED_SPELL] && + (m_currentSpells[CURRENT_CHANNELED_SPELL]->getState() != SPELL_STATE_FINISHED) ) + return(true); + + // autorepeat spells may be finished or delayed, but they are still considered casted + else if ( !skipAutorepeat && m_currentSpells[CURRENT_AUTOREPEAT_SPELL] ) + return(true); + + return(false); +} + +void Unit::InterruptNonMeleeSpells(bool withDelayed, uint32 spell_id) +{ + // generic spells are interrupted if they are not finished or delayed + if (m_currentSpells[CURRENT_GENERIC_SPELL] && (!spell_id || m_currentSpells[CURRENT_GENERIC_SPELL]->m_spellInfo->Id==spell_id)) + { + if ( (m_currentSpells[CURRENT_GENERIC_SPELL]->getState() != SPELL_STATE_FINISHED) && + (withDelayed || m_currentSpells[CURRENT_GENERIC_SPELL]->getState() != SPELL_STATE_DELAYED) ) + m_currentSpells[CURRENT_GENERIC_SPELL]->cancel(); + m_currentSpells[CURRENT_GENERIC_SPELL]->SetDeletable(true); + m_currentSpells[CURRENT_GENERIC_SPELL] = NULL; + } + + // autorepeat spells are interrupted if they are not finished or delayed + if (m_currentSpells[CURRENT_AUTOREPEAT_SPELL] && (!spell_id || m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Id==spell_id)) + { + // send disable autorepeat packet in any case + if(GetTypeId()==TYPEID_PLAYER) + ((Player*)this)->SendAutoRepeatCancel(); + + if ( (m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->getState() != SPELL_STATE_FINISHED) && + (withDelayed || m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->getState() != SPELL_STATE_DELAYED) ) + m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->cancel(); + m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->SetDeletable(true); + m_currentSpells[CURRENT_AUTOREPEAT_SPELL] = NULL; + } + + // channeled spells are interrupted if they are not finished, even if they are delayed + if (m_currentSpells[CURRENT_CHANNELED_SPELL] && (!spell_id || m_currentSpells[CURRENT_CHANNELED_SPELL]->m_spellInfo->Id==spell_id)) + { + if (m_currentSpells[CURRENT_CHANNELED_SPELL]->getState() != SPELL_STATE_FINISHED) + m_currentSpells[CURRENT_CHANNELED_SPELL]->cancel(); + m_currentSpells[CURRENT_CHANNELED_SPELL]->SetDeletable(true); + m_currentSpells[CURRENT_CHANNELED_SPELL] = NULL; + } +} + +Spell* Unit::FindCurrentSpellBySpellId(uint32 spell_id) const +{ + for (uint32 i = 0; i < CURRENT_MAX_SPELL; i++) + if(m_currentSpells[i] && m_currentSpells[i]->m_spellInfo->Id==spell_id) + return m_currentSpells[i]; + return NULL; +} + +bool Unit::isInFront(Unit const* target, float distance, float arc) const +{ + return IsWithinDistInMap(target, distance) && HasInArc( arc, target ); +} + +void Unit::SetInFront(Unit const* target) +{ + SetOrientation(GetAngle(target)); +} + +bool Unit::isInBack(Unit const* target, float distance, float arc) const +{ + return IsWithinDistInMap(target, distance) && !HasInArc( 2 * M_PI - arc, target ); +} + +bool Unit::isInAccessablePlaceFor(Creature const* c) const +{ + if(IsInWater()) + return c->canSwim(); + else + return c->canWalk(); +} + +bool Unit::IsInWater() const +{ + return MapManager::Instance().GetBaseMap(GetMapId())->IsInWater(GetPositionX(),GetPositionY(), GetPositionZ()); +} + +bool Unit::IsUnderWater() const +{ + return MapManager::Instance().GetBaseMap(GetMapId())->IsUnderWater(GetPositionX(),GetPositionY(),GetPositionZ()); +} + +void Unit::DeMorph() +{ + SetDisplayId(GetNativeDisplayId()); +} + +int32 Unit::GetTotalAuraModifier(AuraType auratype) const +{ + int32 modifier = 0; + + AuraList const& mTotalAuraList = GetAurasByType(auratype); + for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i) + modifier += (*i)->GetModifier()->m_amount; + + return modifier; +} + +float Unit::GetTotalAuraMultiplier(AuraType auratype) const +{ + float multipler = 1.0f; + + AuraList const& mTotalAuraList = GetAurasByType(auratype); + for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i) + multipler *= (100.0f + (*i)->GetModifier()->m_amount)/100.0f; + + return multipler; +} + +int32 Unit::GetMaxPositiveAuraModifier(AuraType auratype) const +{ + int32 modifier = 0; + + AuraList const& mTotalAuraList = GetAurasByType(auratype); + for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i) + if ((*i)->GetModifier()->m_amount > modifier) + modifier = (*i)->GetModifier()->m_amount; + + return modifier; +} + +int32 Unit::GetMaxNegativeAuraModifier(AuraType auratype) const +{ + int32 modifier = 0; + + AuraList const& mTotalAuraList = GetAurasByType(auratype); + for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i) + if ((*i)->GetModifier()->m_amount < modifier) + modifier = (*i)->GetModifier()->m_amount; + + return modifier; +} + +int32 Unit::GetTotalAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const +{ + int32 modifier = 0; + + AuraList const& mTotalAuraList = GetAurasByType(auratype); + for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i) + { + Modifier* mod = (*i)->GetModifier(); + if (mod->m_miscvalue & misc_mask) + modifier += mod->m_amount; + } + return modifier; +} + +float Unit::GetTotalAuraMultiplierByMiscMask(AuraType auratype, uint32 misc_mask) const +{ + float multipler = 1.0f; + + AuraList const& mTotalAuraList = GetAurasByType(auratype); + for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i) + { + Modifier* mod = (*i)->GetModifier(); + if (mod->m_miscvalue & misc_mask) + multipler *= (100.0f + mod->m_amount)/100.0f; + } + return multipler; +} + +int32 Unit::GetMaxPositiveAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const +{ + int32 modifier = 0; + + AuraList const& mTotalAuraList = GetAurasByType(auratype); + for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i) + { + Modifier* mod = (*i)->GetModifier(); + if (mod->m_miscvalue & misc_mask && mod->m_amount > modifier) + modifier = mod->m_amount; + } + + return modifier; +} + +int32 Unit::GetMaxNegativeAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const +{ + int32 modifier = 0; + + AuraList const& mTotalAuraList = GetAurasByType(auratype); + for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i) + { + Modifier* mod = (*i)->GetModifier(); + if (mod->m_miscvalue & misc_mask && mod->m_amount < modifier) + modifier = mod->m_amount; + } + + return modifier; +} + +int32 Unit::GetTotalAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const +{ + int32 modifier = 0; + + AuraList const& mTotalAuraList = GetAurasByType(auratype); + for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i) + { + Modifier* mod = (*i)->GetModifier(); + if (mod->m_miscvalue == misc_value) + modifier += mod->m_amount; + } + return modifier; +} + +float Unit::GetTotalAuraMultiplierByMiscValue(AuraType auratype, int32 misc_value) const +{ + float multipler = 1.0f; + + AuraList const& mTotalAuraList = GetAurasByType(auratype); + for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i) + { + Modifier* mod = (*i)->GetModifier(); + if (mod->m_miscvalue == misc_value) + multipler *= (100.0f + mod->m_amount)/100.0f; + } + return multipler; +} + +int32 Unit::GetMaxPositiveAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const +{ + int32 modifier = 0; + + AuraList const& mTotalAuraList = GetAurasByType(auratype); + for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i) + { + Modifier* mod = (*i)->GetModifier(); + if (mod->m_miscvalue == misc_value && mod->m_amount > modifier) + modifier = mod->m_amount; + } + + return modifier; +} + +int32 Unit::GetMaxNegativeAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const +{ + int32 modifier = 0; + + AuraList const& mTotalAuraList = GetAurasByType(auratype); + for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i) + { + Modifier* mod = (*i)->GetModifier(); + if (mod->m_miscvalue == misc_value && mod->m_amount < modifier) + modifier = mod->m_amount; + } + + return modifier; +} + +bool Unit::AddAura(Aura *Aur) +{ + // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load) + if( !isAlive() && Aur->GetId() != 20584 && Aur->GetId() != 8326 && Aur->GetId() != 2584 && + (GetTypeId()!=TYPEID_PLAYER || !((Player*)this)->GetSession()->PlayerLoading()) ) + { + delete Aur; + return false; + } + + if(Aur->GetTarget() != this) + { + sLog.outError("Aura (spell %u eff %u) add to aura list of %s (lowguid: %u) but Aura target is %s (lowguid: %u)", + Aur->GetId(),Aur->GetEffIndex(),(GetTypeId()==TYPEID_PLAYER?"player":"creature"),GetGUIDLow(), + (Aur->GetTarget()->GetTypeId()==TYPEID_PLAYER?"player":"creature"),Aur->GetTarget()->GetGUIDLow()); + delete Aur; + return false; + } + + SpellEntry const* aurSpellInfo = Aur->GetSpellProto(); + + spellEffectPair spair = spellEffectPair(Aur->GetId(), Aur->GetEffIndex()); + AuraMap::iterator i = m_Auras.find( spair ); + + // take out same spell + if (i != m_Auras.end()) + { + // passive and persistent auras can stack with themselves any number of times + if (!Aur->IsPassive() && !Aur->IsPersistent()) + { + // replace aura if next will > spell StackAmount + if(aurSpellInfo->StackAmount) + { + if(m_Auras.count(spair) >= aurSpellInfo->StackAmount) + RemoveAura(i,AURA_REMOVE_BY_STACK); + } + // if StackAmount==0 not allow auras from same caster + else + { + for(AuraMap::iterator i2 = m_Auras.lower_bound(spair); i2 != m_Auras.upper_bound(spair); ++i2) + { + if(i2->second->GetCasterGUID()==Aur->GetCasterGUID()) + { + // can be only single (this check done at _each_ aura add + RemoveAura(i2,AURA_REMOVE_BY_STACK); + break; + } + + bool stop = false; + switch(aurSpellInfo->EffectApplyAuraName[Aur->GetEffIndex()]) + { + // DoT/HoT/etc + case SPELL_AURA_PERIODIC_DAMAGE: // allow stack + case SPELL_AURA_PERIODIC_DAMAGE_PERCENT: + case SPELL_AURA_PERIODIC_LEECH: + case SPELL_AURA_PERIODIC_HEAL: + case SPELL_AURA_OBS_MOD_HEALTH: + case SPELL_AURA_PERIODIC_MANA_LEECH: + case SPELL_AURA_PERIODIC_ENERGIZE: + case SPELL_AURA_OBS_MOD_MANA: + case SPELL_AURA_POWER_BURN_MANA: + break; + default: // not allow + // can be only single (this check done at _each_ aura add + RemoveAura(i2,AURA_REMOVE_BY_STACK); + stop = true; + break; + } + + if(stop) + break; + } + } + } + } + + // passive auras stack with all (except passive spell proc auras) + if ((!Aur->IsPassive() || !IsPassiveStackableSpell(Aur->GetId())) && + !(Aur->GetId() == 20584 || Aur->GetId() == 8326)) + { + if (!RemoveNoStackAurasDueToAura(Aur)) + { + delete Aur; + return false; // couldnt remove conflicting aura with higher rank + } + } + + // update single target auras list (before aura add to aura list, to prevent unexpected remove recently added aura) + if (IsSingleTargetSpell(aurSpellInfo) && Aur->GetTarget()) + { + // caster pointer can be deleted in time aura remove, find it by guid at each iteration + for(;;) + { + Unit* caster = Aur->GetCaster(); + if(!caster) // caster deleted and not required adding scAura + break; + + bool restart = false; + AuraList& scAuras = caster->GetSingleCastAuras(); + for(AuraList::iterator itr = scAuras.begin(); itr != scAuras.end(); ++itr) + { + if( (*itr)->GetTarget() != Aur->GetTarget() && + IsSingleTargetSpells((*itr)->GetSpellProto(),aurSpellInfo) ) + { + if ((*itr)->IsInUse()) + { + sLog.outError("Aura (Spell %u Effect %u) is in process but attempt removed at aura (Spell %u Effect %u) adding, need add stack rule for IsSingleTargetSpell", (*itr)->GetId(), (*itr)->GetEffIndex(),Aur->GetId(), Aur->GetEffIndex()); + continue; + } + (*itr)->GetTarget()->RemoveAura((*itr)->GetId(), (*itr)->GetEffIndex()); + restart = true; + break; + } + } + + if(!restart) + { + // done + scAuras.push_back(Aur); + break; + } + } + } + + // add aura, register in lists and arrays + Aur->_AddAura(); + m_Auras.insert(AuraMap::value_type(spellEffectPair(Aur->GetId(), Aur->GetEffIndex()), Aur)); + if (Aur->GetModifier()->m_auraname < TOTAL_AURAS) + { + m_modAuras[Aur->GetModifier()->m_auraname].push_back(Aur); + } + + Aur->ApplyModifier(true,true); + sLog.outDebug("Aura %u now is in use", Aur->GetModifier()->m_auraname); + return true; +} + +void Unit::RemoveRankAurasDueToSpell(uint32 spellId) +{ + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); + if(!spellInfo) + return; + AuraMap::iterator i,next; + for (i = m_Auras.begin(); i != m_Auras.end(); i = next) + { + next = i; + ++next; + uint32 i_spellId = (*i).second->GetId(); + if((*i).second && i_spellId && i_spellId != spellId) + { + if(spellmgr.IsRankSpellDueToSpell(spellInfo,i_spellId)) + { + RemoveAurasDueToSpell(i_spellId); + + if( m_Auras.empty() ) + break; + else + next = m_Auras.begin(); + } + } + } +} + +bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur) +{ + if (!Aur) + return false; + + SpellEntry const* spellProto = Aur->GetSpellProto(); + if (!spellProto) + return false; + + uint32 spellId = Aur->GetId(); + uint32 effIndex = Aur->GetEffIndex(); + + SpellSpecific spellId_spec = GetSpellSpecific(spellId); + + AuraMap::iterator i,next; + for (i = m_Auras.begin(); i != m_Auras.end(); i = next) + { + next = i; + ++next; + if (!(*i).second) continue; + + SpellEntry const* i_spellProto = (*i).second->GetSpellProto(); + + if (!i_spellProto) + continue; + + uint32 i_spellId = i_spellProto->Id; + + if(IsPassiveSpell(i_spellId)) + { + if(IsPassiveStackableSpell(i_spellId)) + continue; + + // passive non-stackable spells not stackable only with another rank of same spell + if (!spellmgr.IsRankSpellDueToSpell(spellProto, i_spellId)) + continue; + } + + uint32 i_effIndex = (*i).second->GetEffIndex(); + + if(i_spellId == spellId) continue; + + bool is_triggered_by_spell = false; + // prevent triggered aura of removing aura that triggered it + for(int j = 0; j < 3; ++j) + if (i_spellProto->EffectTriggerSpell[j] == spellProto->Id) + is_triggered_by_spell = true; + if (is_triggered_by_spell) continue; + + for(int j = 0; j < 3; ++j) + { + // prevent remove dummy triggered spells at next effect aura add + switch(spellProto->Effect[j]) // main spell auras added added after triggred spell + { + case SPELL_EFFECT_DUMMY: + switch(spellId) + { + case 5420: if(i_spellId==34123) is_triggered_by_spell = true; break; + } + break; + } + + if(is_triggered_by_spell) + break; + + // prevent remove form main spell by triggred passive spells + switch(i_spellProto->EffectApplyAuraName[j]) // main aura added before triggered spell + { + case SPELL_AURA_MOD_SHAPESHIFT: + switch(i_spellId) + { + case 24858: if(spellId==24905) is_triggered_by_spell = true; break; + case 33891: if(spellId==5420 || spellId==34123) is_triggered_by_spell = true; break; + case 34551: if(spellId==22688) is_triggered_by_spell = true; break; + } + break; + } + } + + if(!is_triggered_by_spell) + { + SpellSpecific i_spellId_spec = GetSpellSpecific(i_spellId); + + bool is_sspc = IsSingleFromSpellSpecificPerCaster(spellId_spec,i_spellId_spec); + + if( is_sspc && Aur->GetCasterGUID() == (*i).second->GetCasterGUID() ) + { + // cannot remove higher rank + if (spellmgr.IsRankSpellDueToSpell(spellProto, i_spellId)) + if(CompareAuraRanks(spellId, effIndex, i_spellId, i_effIndex) < 0) + return false; + + // Its a parent aura (create this aura in ApplyModifier) + if ((*i).second->IsInUse()) + { + sLog.outError("Aura (Spell %u Effect %u) is in process but attempt removed at aura (Spell %u Effect %u) adding, need add stack rule for Unit::RemoveNoStackAurasDueToAura", i->second->GetId(), i->second->GetEffIndex(),Aur->GetId(), Aur->GetEffIndex()); + continue; + } + RemoveAurasDueToSpell(i_spellId); + + if( m_Auras.empty() ) + break; + else + next = m_Auras.begin(); + } + else if( !is_sspc && spellmgr.IsNoStackSpellDueToSpell(spellId, i_spellId) ) + { + // Its a parent aura (create this aura in ApplyModifier) + if ((*i).second->IsInUse()) + { + sLog.outError("Aura (Spell %u Effect %u) is in process but attempt removed at aura (Spell %u Effect %u) adding, need add stack rule for Unit::RemoveNoStackAurasDueToAura", i->second->GetId(), i->second->GetEffIndex(),Aur->GetId(), Aur->GetEffIndex()); + continue; + } + RemoveAurasDueToSpell(i_spellId); + + if( m_Auras.empty() ) + break; + else + next = m_Auras.begin(); + } + // Potions stack aura by aura (elixirs/flask already checked) + else if( spellProto->SpellFamilyName == SPELLFAMILY_POTION && i_spellProto->SpellFamilyName == SPELLFAMILY_POTION ) + { + if (IsNoStackAuraDueToAura(spellId, effIndex, i_spellId, i_effIndex)) + { + if(CompareAuraRanks(spellId, effIndex, i_spellId, i_effIndex) < 0) + return false; // cannot remove higher rank + + // Its a parent aura (create this aura in ApplyModifier) + if ((*i).second->IsInUse()) + { + sLog.outError("Aura (Spell %u Effect %u) is in process but attempt removed at aura (Spell %u Effect %u) adding, need add stack rule for Unit::RemoveNoStackAurasDueToAura", i->second->GetId(), i->second->GetEffIndex(),Aur->GetId(), Aur->GetEffIndex()); + continue; + } + RemoveAura(i); + next = i; + } + } + } + } + return true; +} + +void Unit::RemoveAura(uint32 spellId, uint32 effindex, Aura* except) +{ + spellEffectPair spair = spellEffectPair(spellId, effindex); + for(AuraMap::iterator iter = m_Auras.lower_bound(spair); iter != m_Auras.upper_bound(spair);) + { + if(iter->second!=except) + { + RemoveAura(iter); + iter = m_Auras.lower_bound(spair); + } + else + ++iter; + } +} + +void Unit::RemoveAurasDueToSpellByDispel(uint32 spellId, uint64 casterGUID, Unit *dispeler) +{ + for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end(); ) + { + Aura *aur = iter->second; + if (aur->GetId() == spellId && aur->GetCasterGUID() == casterGUID) + { + // Custom dispel case + // Unstable Affliction + if (aur->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (aur->GetSpellProto()->SpellFamilyFlags & 0x010000000000LL)) + { + int32 damage = aur->GetModifier()->m_amount*9; + uint64 caster_guid = aur->GetCasterGUID(); + + // Remove aura + RemoveAura(iter, AURA_REMOVE_BY_DISPEL); + + // backfire damage and silence + dispeler->CastCustomSpell(dispeler, 31117, &damage, NULL, NULL, true, NULL, NULL,caster_guid); + + iter = m_Auras.begin(); // iterator can be invalidate at cast if self-dispel + } + else + RemoveAura(iter, AURA_REMOVE_BY_DISPEL); + } + else + ++iter; + } +} + +void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit *stealer) +{ + for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end(); ) + { + Aura *aur = iter->second; + if (aur->GetId() == spellId && aur->GetCasterGUID() == casterGUID) + { + int32 basePoints = aur->GetBasePoints(); + // construct the new aura for the attacker + Aura * new_aur = CreateAura(aur->GetSpellProto(), aur->GetEffIndex(), &basePoints, stealer); + if(!new_aur) + continue; + + // set its duration and maximum duration + // max duration 2 minutes (in msecs) + int32 dur = aur->GetAuraDuration(); + const int32 max_dur = 2*MINUTE*1000; + new_aur->SetAuraMaxDuration( max_dur > dur ? dur : max_dur ); + new_aur->SetAuraDuration( max_dur > dur ? dur : max_dur ); + + // add the new aura to stealer + stealer->AddAura(new_aur); + + // Remove aura as dispel + RemoveAura(iter, AURA_REMOVE_BY_DISPEL); + } + else + ++iter; + } +} + +void Unit::RemoveAurasDueToSpellByCancel(uint32 spellId) +{ + for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end(); ) + { + if (iter->second->GetId() == spellId) + RemoveAura(iter, AURA_REMOVE_BY_CANCEL); + else + ++iter; + } +} + +void Unit::RemoveAurasWithDispelType( DispelType type ) +{ + // Create dispel mask by dispel type + uint32 dispelMask = GetDispellMask(type); + // Dispel all existing auras vs current dispell type + AuraMap& auras = GetAuras(); + for(AuraMap::iterator itr = auras.begin(); itr != auras.end(); ) + { + SpellEntry const* spell = itr->second->GetSpellProto(); + if( (1<Dispel) & dispelMask ) + { + // Dispel aura + RemoveAurasDueToSpell(spell->Id); + itr = auras.begin(); + } + else + ++itr; + } +} + +void Unit::RemoveSingleAuraFromStack(uint32 spellId, uint32 effindex) +{ + AuraMap::iterator iter = m_Auras.find(spellEffectPair(spellId, effindex)); + if(iter != m_Auras.end()) + RemoveAura(iter); +} + +void Unit::RemoveAurasDueToSpell(uint32 spellId, Aura* except) +{ + for (int i = 0; i < 3; ++i) + RemoveAura(spellId,i,except); +} + +void Unit::RemoveAurasDueToItemSpell(Item* castItem,uint32 spellId) +{ + for (int k=0; k < 3; ++k) + { + spellEffectPair spair = spellEffectPair(spellId, k); + for (AuraMap::iterator iter = m_Auras.lower_bound(spair); iter != m_Auras.upper_bound(spair);) + { + if (iter->second->GetCastItemGUID() == castItem->GetGUID()) + { + RemoveAura(iter); + iter = m_Auras.upper_bound(spair); // overwrite by more appropriate + } + else + ++iter; + } + } +} + +void Unit::RemoveAurasWithInterruptFlags(uint32 flags) +{ + for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end(); ) + { + if (iter->second->GetSpellProto()->AuraInterruptFlags & flags) + RemoveAura(iter); + else + ++iter; + } +} + +void Unit::RemoveNotOwnSingleTargetAuras() +{ + // single target auras from other casters + for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end(); ) + { + if (iter->second->GetCasterGUID()!=GetGUID() && IsSingleTargetSpell(iter->second->GetSpellProto())) + RemoveAura(iter); + else + ++iter; + } + + // single target auras at other targets + AuraList& scAuras = GetSingleCastAuras(); + for (AuraList::iterator iter = scAuras.begin(); iter != scAuras.end(); ) + { + Aura* aura = *iter; + if (aura->GetTarget()!=this) + { + scAuras.erase(iter); // explicitly remove, instead waiting remove in RemoveAura + aura->GetTarget()->RemoveAura(aura->GetId(),aura->GetEffIndex()); + iter = scAuras.begin(); + } + else + ++iter; + } + +} + +void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode) +{ + if (IsSingleTargetSpell((*i).second->GetSpellProto())) + { + if(Unit* caster = (*i).second->GetCaster()) + { + AuraList& scAuras = caster->GetSingleCastAuras(); + scAuras.remove((*i).second); + } + else + { + sLog.outError("Couldn't find the caster of the single target aura, may crash later!"); + assert(false); + } + } + + if ((*i).second->GetModifier()->m_auraname < TOTAL_AURAS) + { + m_modAuras[(*i).second->GetModifier()->m_auraname].remove((*i).second); + } + + // remove from list before mods removing (prevent cyclic calls, mods added before including to aura list - use reverse order) + Aura* Aur = i->second; + // Set remove mode + Aur->SetRemoveMode(mode); + // some ShapeshiftBoosts at remove trigger removing other auras including parent Shapeshift aura + // remove aura from list before to prevent deleting it before + m_Auras.erase(i); + ++m_removedAuras; // internal count used by unit update + + // Status unsummoned at aura remove + Totem* statue = NULL; + if(IsChanneledSpell(Aur->GetSpellProto())) + if(Unit* caster = Aur->GetCaster()) + if(caster->GetTypeId()==TYPEID_UNIT && ((Creature*)caster)->isTotem() && ((Totem*)caster)->GetTotemType()==TOTEM_STATUE) + statue = ((Totem*)caster); + + sLog.outDebug("Aura %u now is remove mode %d",Aur->GetModifier()->m_auraname, mode); + Aur->ApplyModifier(false,true); + Aur->_RemoveAura(); + delete Aur; + + if(statue) + statue->UnSummon(); + + // only way correctly remove all auras from list + if( m_Auras.empty() ) + i = m_Auras.end(); + else + i = m_Auras.begin(); +} + +void Unit::RemoveAllAuras() +{ + while (!m_Auras.empty()) + { + AuraMap::iterator iter = m_Auras.begin(); + RemoveAura(iter); + } +} + +void Unit::RemoveAllAurasOnDeath() +{ + // used just after dieing to remove all visible auras + // and disable the mods for the passive ones + for(AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();) + { + if (!iter->second->IsPassive() && !iter->second->IsDeathPersistent()) + RemoveAura(iter, AURA_REMOVE_BY_DEATH); + else + ++iter; + } +} + +void Unit::DelayAura(uint32 spellId, uint32 effindex, int32 delaytime) +{ + AuraMap::iterator iter = m_Auras.find(spellEffectPair(spellId, effindex)); + if (iter != m_Auras.end()) + { + if (iter->second->GetAuraDuration() < delaytime) + iter->second->SetAuraDuration(0); + else + iter->second->SetAuraDuration(iter->second->GetAuraDuration() - delaytime); + iter->second->UpdateAuraDuration(); + sLog.outDebug("Aura %u partially interrupted on unit %u, new duration: %u ms",iter->second->GetModifier()->m_auraname, GetGUIDLow(), iter->second->GetAuraDuration()); + } +} + +void Unit::_RemoveAllAuraMods() +{ + for (AuraMap::iterator i = m_Auras.begin(); i != m_Auras.end(); ++i) + { + (*i).second->ApplyModifier(false); + } +} + +void Unit::_ApplyAllAuraMods() +{ + for (AuraMap::iterator i = m_Auras.begin(); i != m_Auras.end(); ++i) + { + (*i).second->ApplyModifier(true); + } +} + +Aura* Unit::GetAura(uint32 spellId, uint32 effindex) +{ + AuraMap::iterator iter = m_Auras.find(spellEffectPair(spellId, effindex)); + if (iter != m_Auras.end()) + return iter->second; + return NULL; +} + +void Unit::AddDynObject(DynamicObject* dynObj) +{ + m_dynObjGUIDs.push_back(dynObj->GetGUID()); +} + +void Unit::RemoveDynObject(uint32 spellid) +{ + if(m_dynObjGUIDs.empty()) + return; + for (DynObjectGUIDs::iterator i = m_dynObjGUIDs.begin(); i != m_dynObjGUIDs.end();) + { + DynamicObject* dynObj = ObjectAccessor::GetDynamicObject(*this,*m_dynObjGUIDs.begin()); + if(!dynObj) + { + i = m_dynObjGUIDs.erase(i); + } + else if(spellid == 0 || dynObj->GetSpellId() == spellid) + { + dynObj->Delete(); + i = m_dynObjGUIDs.erase(i); + } + else + ++i; + } +} + +void Unit::RemoveAllDynObjects() +{ + while(!m_dynObjGUIDs.empty()) + { + DynamicObject* dynObj = ObjectAccessor::GetDynamicObject(*this,*m_dynObjGUIDs.begin()); + if(dynObj) + dynObj->Delete(); + m_dynObjGUIDs.erase(m_dynObjGUIDs.begin()); + } +} + +DynamicObject * Unit::GetDynObject(uint32 spellId, uint32 effIndex) +{ + for (DynObjectGUIDs::iterator i = m_dynObjGUIDs.begin(); i != m_dynObjGUIDs.end();) + { + DynamicObject* dynObj = ObjectAccessor::GetDynamicObject(*this,*m_dynObjGUIDs.begin()); + if(!dynObj) + { + i = m_dynObjGUIDs.erase(i); + continue; + } + + if (dynObj->GetSpellId() == spellId && dynObj->GetEffIndex() == effIndex) + return dynObj; + ++i; + } + return NULL; +} + +DynamicObject * Unit::GetDynObject(uint32 spellId) +{ + for (DynObjectGUIDs::iterator i = m_dynObjGUIDs.begin(); i != m_dynObjGUIDs.end();) + { + DynamicObject* dynObj = ObjectAccessor::GetDynamicObject(*this,*m_dynObjGUIDs.begin()); + if(!dynObj) + { + i = m_dynObjGUIDs.erase(i); + continue; + } + + if (dynObj->GetSpellId() == spellId) + return dynObj; + ++i; + } + return NULL; +} + +void Unit::AddGameObject(GameObject* gameObj) +{ + assert(gameObj && gameObj->GetOwnerGUID()==0); + m_gameObj.push_back(gameObj); + gameObj->SetOwnerGUID(GetGUID()); +} + +void Unit::RemoveGameObject(GameObject* gameObj, bool del) +{ + assert(gameObj && gameObj->GetOwnerGUID()==GetGUID()); + + // GO created by some spell + if ( GetTypeId()==TYPEID_PLAYER && gameObj->GetSpellId() ) + { + SpellEntry const* createBySpell = sSpellStore.LookupEntry(gameObj->GetSpellId()); + // Need activate spell use for owner + if (createBySpell && createBySpell->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE) + ((Player*)this)->SendCooldownEvent(createBySpell); + } + gameObj->SetOwnerGUID(0); + m_gameObj.remove(gameObj); + if(del) + { + gameObj->SetRespawnTime(0); + gameObj->Delete(); + } +} + +void Unit::RemoveGameObject(uint32 spellid, bool del) +{ + if(m_gameObj.empty()) + return; + std::list::iterator i, next; + for (i = m_gameObj.begin(); i != m_gameObj.end(); i = next) + { + next = i; + if(spellid == 0 || (*i)->GetSpellId() == spellid) + { + (*i)->SetOwnerGUID(0); + if(del) + { + (*i)->SetRespawnTime(0); + (*i)->Delete(); + } + + next = m_gameObj.erase(i); + } + else + ++next; + } +} + +void Unit::RemoveAllGameObjects() +{ + // remove references to unit + for(std::list::iterator i = m_gameObj.begin(); i != m_gameObj.end();) + { + (*i)->SetOwnerGUID(0); + (*i)->SetRespawnTime(0); + (*i)->Delete(); + i = m_gameObj.erase(i); + } +} + +void Unit::SendSpellNonMeleeDamageLog(Unit *target,uint32 SpellID,uint32 Damage, SpellSchoolMask damageSchoolMask,uint32 AbsorbedDamage, uint32 Resist,bool PhysicalDamage, uint32 Blocked, bool CriticalHit) +{ + sLog.outDebug("Sending: SMSG_SPELLNONMELEEDAMAGELOG"); + WorldPacket data(SMSG_SPELLNONMELEEDAMAGELOG, (16+4+4+1+4+4+1+1+4+4+1)); // we guess size + data.append(target->GetPackGUID()); + data.append(GetPackGUID()); + data << uint32(SpellID); + data << uint32(Damage-AbsorbedDamage-Resist-Blocked); + data << uint8(damageSchoolMask); // spell school + data << uint32(AbsorbedDamage); // AbsorbedDamage + data << uint32(Resist); // resist + data << uint8(PhysicalDamage); // if 1, then client show spell name (example: %s's ranged shot hit %s for %u school or %s suffers %u school damage from %s's spell_name + data << uint8(0); // unk isFromAura + data << uint32(Blocked); // blocked + data << uint32(CriticalHit ? 0x27 : 0x25); // hitType, flags: 0x2 - SPELL_HIT_TYPE_CRIT, 0x10 - replace caster? + data << uint8(0); // isDebug? + SendMessageToSet( &data, true ); +} + +void Unit::SendSpellMiss(Unit *target, uint32 spellID, SpellMissInfo missInfo) +{ + WorldPacket data(SMSG_SPELLLOGMISS, (4+8+1+4+8+1)); + data << uint32(spellID); + data << uint64(GetGUID()); + data << uint8(0); // can be 0 or 1 + data << uint32(1); // target count + // for(i = 0; i < target count; ++i) + data << uint64(target->GetGUID()); // target GUID + data << uint8(missInfo); + // end loop + SendMessageToSet(&data, true); +} + +void Unit::SendAttackStateUpdate(uint32 HitInfo, Unit *target, uint8 SwingType, SpellSchoolMask damageSchoolMask, uint32 Damage, uint32 AbsorbDamage, uint32 Resist, VictimState TargetState, uint32 BlockedAmount) +{ + sLog.outDebug("WORLD: Sending SMSG_ATTACKERSTATEUPDATE"); + + WorldPacket data(SMSG_ATTACKERSTATEUPDATE, (16+45)); // we guess size + data << (uint32)HitInfo; + data.append(GetPackGUID()); + data.append(target->GetPackGUID()); + data << (uint32)(Damage-AbsorbDamage-Resist-BlockedAmount); + + data << (uint8)SwingType; // count? + + // for(i = 0; i < SwingType; ++i) + data << (uint32)damageSchoolMask; + data << (float)(Damage-AbsorbDamage-Resist-BlockedAmount); + // still need to double check damage + data << (uint32)(Damage-AbsorbDamage-Resist-BlockedAmount); + data << (uint32)AbsorbDamage; + data << (uint32)Resist; + // end loop + + data << (uint32)TargetState; + + if( AbsorbDamage == 0 ) //also 0x3E8 = 0x3E8, check when that happens + data << (uint32)0; + else + data << (uint32)-1; + + data << (uint32)0; + data << (uint32)BlockedAmount; + + SendMessageToSet( &data, true ); +} + +void Unit::ProcDamageAndSpell(Unit *pVictim, uint32 procAttacker, uint32 procVictim, uint32 damage, SpellSchoolMask damageSchoolMask, SpellEntry const *procSpell, bool isTriggeredSpell, WeaponAttackType attType) +{ + sLog.outDebug("ProcDamageAndSpell: attacker flags are 0x%x, victim flags 0x%x", procAttacker, procVictim); + if(procSpell) + sLog.outDebug("ProcDamageAndSpell: invoked due to spell id %u %s", procSpell->Id, (isTriggeredSpell?"(triggered)":"")); + + // Assign melee/ranged proc flags for magic attacks, that are actually melee/ranged abilities + // not assign for spell proc triggered spell to prevent infinity (or unexpacted 2-3 times) melee damage spell proc call with melee damage effect + // That is the question though if it's fully correct + if(procSpell && !isTriggeredSpell) + { + if(procSpell->DmgClass == SPELL_DAMAGE_CLASS_MELEE) + { + if(procAttacker & PROC_FLAG_HIT_SPELL) procAttacker |= PROC_FLAG_HIT_MELEE; + if(procAttacker & PROC_FLAG_CRIT_SPELL) procAttacker |= PROC_FLAG_CRIT_MELEE; + if(procVictim & PROC_FLAG_STRUCK_SPELL) procVictim |= PROC_FLAG_STRUCK_MELEE; + if(procVictim & PROC_FLAG_STRUCK_CRIT_SPELL) procVictim |= PROC_FLAG_STRUCK_CRIT_MELEE; + attType = BASE_ATTACK; // Melee abilities are assumed to be dealt with mainhand weapon + } + else if (procSpell->DmgClass == SPELL_DAMAGE_CLASS_RANGED) + { + if(procAttacker & PROC_FLAG_HIT_SPELL) procAttacker |= PROC_FLAG_HIT_RANGED; + if(procAttacker & PROC_FLAG_CRIT_SPELL) procAttacker |= PROC_FLAG_CRIT_RANGED; + if(procVictim & PROC_FLAG_STRUCK_SPELL) procVictim |= PROC_FLAG_STRUCK_RANGED; + if(procVictim & PROC_FLAG_STRUCK_CRIT_SPELL) procVictim |= PROC_FLAG_STRUCK_CRIT_RANGED; + attType = RANGED_ATTACK; + } + } + if(damage && (procVictim & (PROC_FLAG_STRUCK_MELEE|PROC_FLAG_STRUCK_RANGED|PROC_FLAG_STRUCK_SPELL))) + procVictim |= (PROC_FLAG_TAKE_DAMAGE|PROC_FLAG_TOUCH); + + // Not much to do if no flags are set. + if (procAttacker) + { + // procces auras that not generate casts at proc event before auras that generate casts to prevent proc aura added at prev. proc aura execute in set + ProcDamageAndSpellFor(false,pVictim,procAttacker,attackerProcEffectAuraTypes,attType, procSpell, damage, damageSchoolMask); + ProcDamageAndSpellFor(false,pVictim,procAttacker,attackerProcCastAuraTypes,attType, procSpell, damage, damageSchoolMask); + } + + // Now go on with a victim's events'n'auras + // Not much to do if no flags are set or there is no victim + if(pVictim && pVictim->isAlive() && procVictim) + { + // procces auras that not generate casts at proc event before auras that generate casts to prevent proc aura added at prev. proc aura execute in set + pVictim->ProcDamageAndSpellFor(true,this,procVictim,victimProcEffectAuraTypes,attType,procSpell, damage, damageSchoolMask); + pVictim->ProcDamageAndSpellFor(true,this,procVictim,victimProcCastAuraTypes,attType,procSpell, damage, damageSchoolMask); + } +} + +void Unit::CastMeleeProcDamageAndSpell(Unit* pVictim, uint32 damage, SpellSchoolMask damageSchoolMask, WeaponAttackType attType, MeleeHitOutcome outcome, SpellEntry const *spellCasted, bool isTriggeredSpell) +{ + if(!pVictim) + return; + + uint32 procAttacker = PROC_FLAG_NONE; + uint32 procVictim = PROC_FLAG_NONE; + + switch(outcome) + { + case MELEE_HIT_EVADE: + return; + case MELEE_HIT_MISS: + if(attType == BASE_ATTACK || attType == OFF_ATTACK) + { + procAttacker = PROC_FLAG_MISS; + } + break; + case MELEE_HIT_BLOCK_CRIT: + case MELEE_HIT_CRIT: + if(spellCasted && attType == BASE_ATTACK) + { + procAttacker |= PROC_FLAG_CRIT_SPELL; + procVictim |= PROC_FLAG_STRUCK_CRIT_SPELL; + if ( outcome == MELEE_HIT_BLOCK_CRIT ) + { + procVictim |= PROC_FLAG_BLOCK; + procAttacker |= PROC_FLAG_TARGET_BLOCK; + } + } + else if(attType == BASE_ATTACK || attType == OFF_ATTACK) + { + procAttacker = PROC_FLAG_HIT_MELEE | PROC_FLAG_CRIT_MELEE; + procVictim = PROC_FLAG_STRUCK_MELEE | PROC_FLAG_STRUCK_CRIT_MELEE; + } + else + { + procAttacker = PROC_FLAG_HIT_RANGED | PROC_FLAG_CRIT_RANGED; + procVictim = PROC_FLAG_STRUCK_RANGED | PROC_FLAG_STRUCK_CRIT_RANGED; + } + break; + case MELEE_HIT_PARRY: + procAttacker = PROC_FLAG_TARGET_DODGE_OR_PARRY; + procVictim = PROC_FLAG_PARRY; + break; + case MELEE_HIT_BLOCK: + procAttacker = PROC_FLAG_TARGET_BLOCK; + procVictim = PROC_FLAG_BLOCK; + break; + case MELEE_HIT_DODGE: + procAttacker = PROC_FLAG_TARGET_DODGE_OR_PARRY; + procVictim = PROC_FLAG_DODGE; + break; + case MELEE_HIT_CRUSHING: + if(attType == BASE_ATTACK || attType == OFF_ATTACK) + { + procAttacker = PROC_FLAG_HIT_MELEE | PROC_FLAG_CRIT_MELEE; + procVictim = PROC_FLAG_STRUCK_MELEE | PROC_FLAG_STRUCK_CRIT_MELEE; + } + else + { + procAttacker = PROC_FLAG_HIT_RANGED | PROC_FLAG_CRIT_RANGED; + procVictim = PROC_FLAG_STRUCK_RANGED | PROC_FLAG_STRUCK_CRIT_RANGED; + } + break; + default: + if(attType == BASE_ATTACK || attType == OFF_ATTACK) + { + procAttacker = PROC_FLAG_HIT_MELEE; + procVictim = PROC_FLAG_STRUCK_MELEE; + } + else + { + procAttacker = PROC_FLAG_HIT_RANGED; + procVictim = PROC_FLAG_STRUCK_RANGED; + } + break; + } + + if(damage > 0) + procVictim |= PROC_FLAG_TAKE_DAMAGE; + + if(procAttacker != PROC_FLAG_NONE || procVictim != PROC_FLAG_NONE) + ProcDamageAndSpell(pVictim, procAttacker, procVictim, damage, damageSchoolMask, spellCasted, isTriggeredSpell, attType); +} + +bool Unit::HandleHasteAuraProc(Unit *pVictim, SpellEntry const *hasteSpell, uint32 /*effIndex*/, uint32 damage, Aura* triggeredByAura, SpellEntry const * procSpell, uint32 /*procFlag*/, uint32 cooldown) +{ + Item* castItem = triggeredByAura->GetCastItemGUID() && GetTypeId()==TYPEID_PLAYER + ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetCastItemGUID()) : NULL; + + uint32 triggered_spell_id = 0; + Unit* target = pVictim; + int32 basepoints0 = 0; + + switch(hasteSpell->SpellFamilyName) + { + case SPELLFAMILY_ROGUE: + { + switch(hasteSpell->Id) + { + // Blade Flurry + case 13877: + case 33735: + { + target = SelectNearbyTarget(); + if(!target) + return false; + basepoints0 = damage; + triggered_spell_id = 22482; + break; + } + } + break; + } + } + + // processed charge only counting case + if(!triggered_spell_id) + return true; + + SpellEntry const* triggerEntry = sSpellStore.LookupEntry(triggered_spell_id); + + if(!triggerEntry) + { + sLog.outError("Unit::HandleHasteAuraProc: Spell %u have not existed triggered spell %u",hasteSpell->Id,triggered_spell_id); + return false; + } + + // default case + if(!target || target!=this && !target->isAlive()) + return false; + + if( cooldown && GetTypeId()==TYPEID_PLAYER && ((Player*)this)->HasSpellCooldown(triggered_spell_id)) + return false; + + if(basepoints0) + CastCustomSpell(target,triggered_spell_id,&basepoints0,NULL,NULL,true,castItem,triggeredByAura); + else + CastSpell(target,triggered_spell_id,true,castItem,triggeredByAura); + + if( cooldown && GetTypeId()==TYPEID_PLAYER ) + ((Player*)this)->AddSpellCooldown(triggered_spell_id,0,time(NULL) + cooldown); + + return true; +} + +bool Unit::HandleDummyAuraProc(Unit *pVictim, SpellEntry const *dummySpell, uint32 effIndex, uint32 damage, Aura* triggeredByAura, SpellEntry const * procSpell, uint32 procFlag, uint32 cooldown) +{ + Item* castItem = triggeredByAura->GetCastItemGUID() && GetTypeId()==TYPEID_PLAYER + ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetCastItemGUID()) : NULL; + + uint32 triggered_spell_id = 0; + Unit* target = pVictim; + int32 basepoints0 = 0; + + switch(dummySpell->SpellFamilyName) + { + case SPELLFAMILY_GENERIC: + { + switch (dummySpell->Id) + { + // Eye of Eye + case 9799: + case 25988: + { + // prevent damage back from weapon special attacks + if (!procSpell || procSpell->DmgClass != SPELL_DAMAGE_CLASS_MAGIC ) + return false; + + // return damage % to attacker but < 50% own total health + basepoints0 = triggeredByAura->GetModifier()->m_amount*int32(damage)/100; + if(basepoints0 > GetMaxHealth()/2) + basepoints0 = GetMaxHealth()/2; + + triggered_spell_id = 25997; + break; + } + // Sweeping Strikes + case 12328: + case 18765: + case 35429: + { + // prevent chain of triggred spell from same triggred spell + if(procSpell && procSpell->Id==26654) + return false; + + target = SelectNearbyTarget(); + if(!target) + return false; + + triggered_spell_id = 26654; + break; + } + // Unstable Power + case 24658: + { + if (!procSpell || procSpell->Id == 24659) + return false; + // Need remove one 24659 aura + RemoveSingleAuraFromStack(24659, 0); + RemoveSingleAuraFromStack(24659, 1); + return true; + } + // Restless Strength + case 24661: + { + // Need remove one 24662 aura + RemoveSingleAuraFromStack(24662, 0); + return true; + } + // Adaptive Warding (Frostfire Regalia set) + case 28764: + { + if(!procSpell) + return false; + + // find Mage Armor + bool found = false; + AuraList const& mRegenInterupt = GetAurasByType(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT); + for(AuraList::const_iterator iter = mRegenInterupt.begin(); iter != mRegenInterupt.end(); ++iter) + { + if(SpellEntry const* iterSpellProto = (*iter)->GetSpellProto()) + { + if(iterSpellProto->SpellFamilyName==SPELLFAMILY_MAGE && (iterSpellProto->SpellFamilyFlags & 0x10000000)) + { + found=true; + break; + } + } + } + if(!found) + return false; + + switch(GetFirstSchoolInMask(GetSpellSchoolMask(procSpell))) + { + case SPELL_SCHOOL_NORMAL: + case SPELL_SCHOOL_HOLY: + return false; // ignored + case SPELL_SCHOOL_FIRE: triggered_spell_id = 28765; break; + case SPELL_SCHOOL_NATURE: triggered_spell_id = 28768; break; + case SPELL_SCHOOL_FROST: triggered_spell_id = 28766; break; + case SPELL_SCHOOL_SHADOW: triggered_spell_id = 28769; break; + case SPELL_SCHOOL_ARCANE: triggered_spell_id = 28770; break; + default: + return false; + } + + target = this; + break; + } + // Obsidian Armor (Justice Bearer`s Pauldrons shoulder) + case 27539: + { + if(!procSpell) + return false; + + // not from DoT + bool found = false; + for(int j = 0; j < 3; ++j) + { + if(procSpell->EffectApplyAuraName[j]==SPELL_AURA_PERIODIC_DAMAGE||procSpell->EffectApplyAuraName[j]==SPELL_AURA_PERIODIC_DAMAGE_PERCENT) + { + found = true; + break; + } + } + if(found) + return false; + + switch(GetFirstSchoolInMask(GetSpellSchoolMask(procSpell))) + { + case SPELL_SCHOOL_NORMAL: + return false; // ignore + case SPELL_SCHOOL_HOLY: triggered_spell_id = 27536; break; + case SPELL_SCHOOL_FIRE: triggered_spell_id = 27533; break; + case SPELL_SCHOOL_NATURE: triggered_spell_id = 27538; break; + case SPELL_SCHOOL_FROST: triggered_spell_id = 27534; break; + case SPELL_SCHOOL_SHADOW: triggered_spell_id = 27535; break; + case SPELL_SCHOOL_ARCANE: triggered_spell_id = 27540; break; + default: + return false; + } + + target = this; + break; + } + // Mana Leech (Passive) (Priest Pet Aura) + case 28305: + { + // Cast on owner + target = GetOwner(); + if(!target) + return false; + + basepoints0 = int32(damage * 2.5f); // manaregen + triggered_spell_id = 34650; + break; + } + // Mark of Malice + case 33493: + { + // Cast finish spell at last charge + if (triggeredByAura->m_procCharges > 1) + return false; + + target = this; + triggered_spell_id = 33494; + break; + } + // Twisted Reflection (boss spell) + case 21063: + triggered_spell_id = 21064; + break; + // Vampiric Aura (boss spell) + case 38196: + { + basepoints0 = 3 * damage; // 300% + if (basepoints0 < 0) + return false; + + triggered_spell_id = 31285; + target = this; + break; + } + // Aura of Madness (Darkmoon Card: Madness trinket) + //===================================================== + // 39511 Sociopath: +35 strength (Paladin, Rogue, Druid, Warrior) + // 40997 Delusional: +70 attack power (Rogue, Hunter, Paladin, Warrior, Druid) + // 40998 Kleptomania: +35 agility (Warrior, Rogue, Paladin, Hunter, Druid) + // 40999 Megalomania: +41 damage/healing (Druid, Shaman, Priest, Warlock, Mage, Paladin) + // 41002 Paranoia: +35 spell/melee/ranged crit strike rating (All classes) + // 41005 Manic: +35 haste (spell, melee and ranged) (All classes) + // 41009 Narcissism: +35 intellect (Druid, Shaman, Priest, Warlock, Mage, Paladin, Hunter) + // 41011 Martyr Complex: +35 stamina (All classes) + // 41406 Dementia: Every 5 seconds either gives you +5% damage/healing. (Druid, Shaman, Priest, Warlock, Mage, Paladin) + // 41409 Dementia: Every 5 seconds either gives you -5% damage/healing. (Druid, Shaman, Priest, Warlock, Mage, Paladin) + case 39446: + { + if(GetTypeId() != TYPEID_PLAYER) + return false; + + // Select class defined buff + switch (getClass()) + { + case CLASS_PALADIN: // 39511,40997,40998,40999,41002,41005,41009,41011,41409 + case CLASS_DRUID: // 39511,40997,40998,40999,41002,41005,41009,41011,41409 + { + uint32 RandomSpell[]={39511,40997,40998,40999,41002,41005,41009,41011,41409}; + triggered_spell_id = RandomSpell[ irand(0, sizeof(RandomSpell)/sizeof(uint32) - 1) ]; + break; + } + case CLASS_ROGUE: // 39511,40997,40998,41002,41005,41011 + case CLASS_WARRIOR: // 39511,40997,40998,41002,41005,41011 + { + uint32 RandomSpell[]={39511,40997,40998,41002,41005,41011}; + triggered_spell_id = RandomSpell[ irand(0, sizeof(RandomSpell)/sizeof(uint32) - 1) ]; + break; + } + case CLASS_PRIEST: // 40999,41002,41005,41009,41011,41406,41409 + case CLASS_SHAMAN: // 40999,41002,41005,41009,41011,41406,41409 + case CLASS_MAGE: // 40999,41002,41005,41009,41011,41406,41409 + case CLASS_WARLOCK: // 40999,41002,41005,41009,41011,41406,41409 + { + uint32 RandomSpell[]={40999,41002,41005,41009,41011,41406,41409}; + triggered_spell_id = RandomSpell[ irand(0, sizeof(RandomSpell)/sizeof(uint32) - 1) ]; + break; + } + case CLASS_HUNTER: // 40997,40999,41002,41005,41009,41011,41406,41409 + { + uint32 RandomSpell[]={40997,40999,41002,41005,41009,41011,41406,41409}; + triggered_spell_id = RandomSpell[ irand(0, sizeof(RandomSpell)/sizeof(uint32) - 1) ]; + break; + } + default: + return false; + } + + target = this; + if (roll_chance_i(10)) + ((Player*)this)->Say("This is Madness!", LANG_UNIVERSAL); + break; + } + /* + // TODO: need find item for aura and triggered spells + // Sunwell Exalted Caster Neck (??? neck) + // cast ??? Light's Wrath if Exalted by Aldor + // cast ??? Arcane Bolt if Exalted by Scryers*/ + case 46569: + return false; // disable for while + /* + { + if(GetTypeId() != TYPEID_PLAYER) + return false; + + // Get Aldor reputation rank + if (((Player *)this)->GetReputationRank(932) == REP_EXALTED) + { + target = this; + triggered_spell_id = ??? + break; + } + // Get Scryers reputation rank + if (((Player *)this)->GetReputationRank(934) == REP_EXALTED) + { + triggered_spell_id = ??? + break; + } + return false; + }/**/ + // Sunwell Exalted Caster Neck (Shattered Sun Pendant of Acumen neck) + // cast 45479 Light's Wrath if Exalted by Aldor + // cast 45429 Arcane Bolt if Exalted by Scryers + case 45481: + { + if(GetTypeId() != TYPEID_PLAYER) + return false; + + // Get Aldor reputation rank + if (((Player *)this)->GetReputationRank(932) == REP_EXALTED) + { + target = this; + triggered_spell_id = 45479; + break; + } + // Get Scryers reputation rank + if (((Player *)this)->GetReputationRank(934) == REP_EXALTED) + { + triggered_spell_id = 45429; + break; + } + return false; + } + // Sunwell Exalted Melee Neck (Shattered Sun Pendant of Might neck) + // cast 45480 Light's Strength if Exalted by Aldor + // cast 45428 Arcane Strike if Exalted by Scryers + case 45482: + { + if(GetTypeId() != TYPEID_PLAYER) + return false; + + // Get Aldor reputation rank + if (((Player *)this)->GetReputationRank(932) == REP_EXALTED) + { + target = this; + triggered_spell_id = 45480; + break; + } + // Get Scryers reputation rank + if (((Player *)this)->GetReputationRank(934) == REP_EXALTED) + { + triggered_spell_id = 45428; + break; + } + return false; + } + // Sunwell Exalted Tank Neck (Shattered Sun Pendant of Resolve neck) + // cast 45431 Arcane Insight if Exalted by Aldor + // cast 45432 Light's Ward if Exalted by Scryers + case 45483: + { + if(GetTypeId() != TYPEID_PLAYER) + return false; + + // Get Aldor reputation rank + if (((Player *)this)->GetReputationRank(932) == REP_EXALTED) + { + target = this; + triggered_spell_id = 45432; + break; + } + // Get Scryers reputation rank + if (((Player *)this)->GetReputationRank(934) == REP_EXALTED) + { + target = this; + triggered_spell_id = 45431; + break; + } + return false; + } + // Sunwell Exalted Healer Neck (Shattered Sun Pendant of Restoration neck) + // cast 45478 Light's Salvation if Exalted by Aldor + // cast 45430 Arcane Surge if Exalted by Scryers + case 45484: + { + if(GetTypeId() != TYPEID_PLAYER) + return false; + + // Get Aldor reputation rank + if (((Player *)this)->GetReputationRank(932) == REP_EXALTED) + { + target = this; + triggered_spell_id = 45478; + break; + } + // Get Scryers reputation rank + if (((Player *)this)->GetReputationRank(934) == REP_EXALTED) + { + triggered_spell_id = 45430; + break; + } + return false; + } + } + break; + } + case SPELLFAMILY_MAGE: + { + // Magic Absorption + if (dummySpell->SpellIconID == 459) // only this spell have SpellIconID == 459 and dummy aura + { + if (getPowerType() != POWER_MANA) + return false; + + // mana reward + basepoints0 = (triggeredByAura->GetModifier()->m_amount * GetMaxPower(POWER_MANA) / 100); + target = this; + triggered_spell_id = 29442; + break; + } + // Master of Elements + if (dummySpell->SpellIconID == 1920) + { + if(!procSpell) + return false; + + // mana cost save + basepoints0 = procSpell->manaCost * triggeredByAura->GetModifier()->m_amount/100; + if( basepoints0 <=0 ) + return false; + + target = this; + triggered_spell_id = 29077; + break; + } + switch(dummySpell->Id) + { + // Ignite + case 11119: + case 11120: + case 12846: + case 12847: + case 12848: + { + switch (dummySpell->Id) + { + case 11119: basepoints0 = int32(0.04f*damage); break; + case 11120: basepoints0 = int32(0.08f*damage); break; + case 12846: basepoints0 = int32(0.12f*damage); break; + case 12847: basepoints0 = int32(0.16f*damage); break; + case 12848: basepoints0 = int32(0.20f*damage); break; + default: + sLog.outError("Unit::HandleDummyAuraProc: non handled spell id: %u (IG)",dummySpell->Id); + return false; + } + + triggered_spell_id = 12654; + break; + } + // Combustion + case 11129: + { + //last charge and crit + if( triggeredByAura->m_procCharges <= 1 && (procFlag & PROC_FLAG_CRIT_SPELL) ) + { + RemoveAurasDueToSpell(28682); //-> remove Combustion auras + return true; // charge counting (will removed) + } + + CastSpell(this, 28682, true, castItem, triggeredByAura); + return(procFlag & PROC_FLAG_CRIT_SPELL);// charge update only at crit hits, no hidden cooldowns + } + } + break; + } + case SPELLFAMILY_WARRIOR: + { + // Retaliation + if(dummySpell->SpellFamilyFlags==0x0000000800000000LL) + { + // check attack comes not from behind + if (!HasInArc(M_PI, pVictim)) + return false; + + triggered_spell_id = 22858; + break; + } + break; + } + case SPELLFAMILY_WARLOCK: + { + // Seed of Corruption + if (dummySpell->SpellFamilyFlags & 0x0000001000000000LL) + { + Modifier* mod = triggeredByAura->GetModifier(); + // if damage is more than need or target die from damage deal finish spell + // FIX ME: not triggered currently at death + if( mod->m_amount <= damage || GetHealth() <= damage ) + { + // remember guid before aura delete + uint64 casterGuid = triggeredByAura->GetCasterGUID(); + + // Remove aura (before cast for prevent infinite loop handlers) + RemoveAurasDueToSpell(triggeredByAura->GetId()); + + // Cast finish spell (triggeredByAura already not exist!) + CastSpell(this, 27285, true, castItem, NULL, casterGuid); + return true; // no hidden cooldown + } + + // Damage counting + mod->m_amount-=damage; + return true; + } + // Seed of Corruption (Mobs cast) - no die req + if (dummySpell->SpellFamilyFlags == 0x00LL && dummySpell->SpellIconID == 1932) + { + Modifier* mod = triggeredByAura->GetModifier(); + // if damage is more than need deal finish spell + if( mod->m_amount <= damage ) + { + // remember guid before aura delete + uint64 casterGuid = triggeredByAura->GetCasterGUID(); + + // Remove aura (before cast for prevent infinite loop handlers) + RemoveAurasDueToSpell(triggeredByAura->GetId()); + + // Cast finish spell (triggeredByAura already not exist!) + CastSpell(this, 32865, true, castItem, NULL, casterGuid); + return true; // no hidden cooldown + } + // Damage counting + mod->m_amount-=damage; + return true; + } + switch(dummySpell->Id) + { + // Nightfall + case 18094: + case 18095: + { + target = this; + triggered_spell_id = 17941; + break; + } + //Soul Leech + case 30293: + case 30295: + case 30296: + { + // health + basepoints0 = int32(damage*triggeredByAura->GetModifier()->m_amount/100); + target = this; + triggered_spell_id = 30294; + break; + } + // Shadowflame (Voidheart Raiment set bonus) + case 37377: + { + triggered_spell_id = 37379; + break; + } + // Pet Healing (Corruptor Raiment or Rift Stalker Armor) + case 37381: + { + target = GetPet(); + if(!target) + return false; + + // heal amount + basepoints0 = damage * triggeredByAura->GetModifier()->m_amount/100; + triggered_spell_id = 37382; + break; + } + // Shadowflame Hellfire (Voidheart Raiment set bonus) + case 39437: + { + triggered_spell_id = 37378; + break; + } + } + break; + } + case SPELLFAMILY_PRIEST: + { + // Vampiric Touch + if( dummySpell->SpellFamilyFlags & 0x0000040000000000LL ) + { + if(!pVictim || !pVictim->isAlive()) + return false; + + // pVictim is caster of aura + if(triggeredByAura->GetCasterGUID() != pVictim->GetGUID()) + return false; + + // energize amount + basepoints0 = triggeredByAura->GetModifier()->m_amount*damage/100; + pVictim->CastCustomSpell(pVictim,34919,&basepoints0,NULL,NULL,true,castItem,triggeredByAura); + return true; // no hidden cooldown + } + switch(dummySpell->Id) + { + // Vampiric Embrace + case 15286: + { + if(!pVictim || !pVictim->isAlive()) + return false; + + // pVictim is caster of aura + if(triggeredByAura->GetCasterGUID() != pVictim->GetGUID()) + return false; + + // heal amount + basepoints0 = triggeredByAura->GetModifier()->m_amount*damage/100; + pVictim->CastCustomSpell(pVictim,15290,&basepoints0,NULL,NULL,true,castItem,triggeredByAura); + return true; // no hidden cooldown + } + // Priest Tier 6 Trinket (Ashtongue Talisman of Acumen) + case 40438: + { + // Shadow Word: Pain + if( procSpell->SpellFamilyFlags & 0x0000000000008000LL ) + triggered_spell_id = 40441; + // Renew + else if( procSpell->SpellFamilyFlags & 0x0000000000000010LL ) + triggered_spell_id = 40440; + else + return false; + + target = this; + break; + } + // Oracle Healing Bonus ("Garments of the Oracle" set) + case 26169: + { + // heal amount + basepoints0 = int32(damage * 10/100); + target = this; + triggered_spell_id = 26170; + break; + } + // Frozen Shadoweave (Shadow's Embrace set) warning! its not only priest set + case 39372: + { + if(!procSpell || (GetSpellSchoolMask(procSpell) & (SPELL_SCHOOL_MASK_FROST | SPELL_SCHOOL_MASK_SHADOW))==0 ) + return false; + + // heal amount + basepoints0 = int32(damage * 2 / 100); + target = this; + triggered_spell_id = 39373; + break; + } + // Vestments of Faith (Priest Tier 3) - 4 pieces bonus + case 28809: + { + triggered_spell_id = 28810; + break; + } + } + break; + } + case SPELLFAMILY_DRUID: + { + switch(dummySpell->Id) + { + // Healing Touch (Dreamwalker Raiment set) + case 28719: + { + // mana back + basepoints0 = int32(procSpell->manaCost * 30 / 100); + target = this; + triggered_spell_id = 28742; + break; + } + // Healing Touch Refund (Idol of Longevity trinket) + case 28847: + { + target = this; + triggered_spell_id = 28848; + break; + } + // Mana Restore (Malorne Raiment set / Malorne Regalia set) + case 37288: + case 37295: + { + target = this; + triggered_spell_id = 37238; + break; + } + // Druid Tier 6 Trinket + case 40442: + { + float chance; + + // Starfire + if( procSpell->SpellFamilyFlags & 0x0000000000000004LL ) + { + triggered_spell_id = 40445; + chance = 25.f; + } + // Rejuvenation + else if( procSpell->SpellFamilyFlags & 0x0000000000000010LL ) + { + triggered_spell_id = 40446; + chance = 25.f; + } + // Mangle (cat/bear) + else if( procSpell->SpellFamilyFlags & 0x0000044000000000LL ) + { + triggered_spell_id = 40452; + chance = 40.f; + } + else + return false; + + if (!roll_chance_f(chance)) + return false; + + target = this; + break; + } + // Maim Interrupt + case 44835: + { + // Deadly Interrupt Effect + triggered_spell_id = 32747; + break; + } + } + break; + } + case SPELLFAMILY_ROGUE: + { + switch(dummySpell->Id) + { + // Deadly Throw Interrupt + case 32748: + { + // Prevent cast Deadly Throw Interrupt on self from last effect (apply dummy) of Deadly Throw + if(this == pVictim) + return false; + + triggered_spell_id = 32747; + break; + } + } + // Quick Recovery + if( dummySpell->SpellIconID == 2116 ) + { + if(!procSpell) + return false; + + // only rogue's finishing moves (maybe need additional checks) + if( procSpell->SpellFamilyName!=SPELLFAMILY_ROGUE || + (procSpell->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE__FINISHING_MOVE) == 0) + return false; + + // energy cost save + basepoints0 = procSpell->manaCost * triggeredByAura->GetModifier()->m_amount/100; + if(basepoints0 <= 0) + return false; + + target = this; + triggered_spell_id = 31663; + break; + } + break; + } + case SPELLFAMILY_HUNTER: + { + // Thrill of the Hunt + if ( dummySpell->SpellIconID == 2236 ) + { + if(!procSpell) + return false; + + // mana cost save + basepoints0 = procSpell->manaCost * 40/100; + if(basepoints0 <= 0) + return false; + + target = this; + triggered_spell_id = 34720; + break; + } + break; + } + case SPELLFAMILY_PALADIN: + { + // Seal of Righteousness - melee proc dummy + if (dummySpell->SpellFamilyFlags&0x000000008000000LL && triggeredByAura->GetEffIndex()==0) + { + if(GetTypeId() != TYPEID_PLAYER) + return false; + + uint32 spellId; + switch (triggeredByAura->GetId()) + { + case 21084: spellId = 25742; break; // Rank 1 + case 20287: spellId = 25740; break; // Rank 2 + case 20288: spellId = 25739; break; // Rank 3 + case 20289: spellId = 25738; break; // Rank 4 + case 20290: spellId = 25737; break; // Rank 5 + case 20291: spellId = 25736; break; // Rank 6 + case 20292: spellId = 25735; break; // Rank 7 + case 20293: spellId = 25713; break; // Rank 8 + case 27155: spellId = 27156; break; // Rank 9 + default: + sLog.outError("Unit::HandleDummyAuraProc: non handled possibly SoR (Id = %u)", triggeredByAura->GetId()); + return false; + } + Item *item = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND); + float speed = (item ? item->GetProto()->Delay : BASE_ATTACK_TIME)/1000.0f; + + float damageBasePoints; + if(item && item->GetProto()->InventoryType == INVTYPE_2HWEAPON) + // two hand weapon + damageBasePoints=1.20f*triggeredByAura->GetModifier()->m_amount * 1.2f * 1.03f * speed/100.0f + 1; + else + // one hand weapon/no weapon + damageBasePoints=0.85f*ceil(triggeredByAura->GetModifier()->m_amount * 1.2f * 1.03f * speed/100.0f) - 1; + + int32 damagePoint = int32(damageBasePoints + 0.03f * (GetWeaponDamageRange(BASE_ATTACK,MINDAMAGE)+GetWeaponDamageRange(BASE_ATTACK,MAXDAMAGE))/2.0f) + 1; + + // apply damage bonuses manually + if(damagePoint >= 0) + damagePoint = SpellDamageBonus(pVictim, dummySpell, damagePoint, SPELL_DIRECT_DAMAGE); + + CastCustomSpell(pVictim,spellId,&damagePoint,NULL,NULL,true,NULL, triggeredByAura); + return true; // no hidden cooldown + } + // Seal of Blood do damage trigger + if(dummySpell->SpellFamilyFlags & 0x0000040000000000LL) + { + switch(triggeredByAura->GetEffIndex()) + { + case 0: + // prevent chain triggering + if(procSpell && procSpell->Id==31893 ) + return false; + + triggered_spell_id = 31893; + break; + case 1: + { + // damage + basepoints0 = triggeredByAura->GetModifier()->m_amount * damage / 100; + target = this; + triggered_spell_id = 32221; + break; + } + } + } + + switch(dummySpell->Id) + { + // Holy Power (Redemption Armor set) + case 28789: + { + if(!pVictim) + return false; + + // Set class defined buff + switch (pVictim->getClass()) + { + case CLASS_PALADIN: + case CLASS_PRIEST: + case CLASS_SHAMAN: + case CLASS_DRUID: + triggered_spell_id = 28795; // Increases the friendly target's mana regeneration by $s1 per 5 sec. for $d. + break; + case CLASS_MAGE: + case CLASS_WARLOCK: + triggered_spell_id = 28793; // Increases the friendly target's spell damage and healing by up to $s1 for $d. + break; + case CLASS_HUNTER: + case CLASS_ROGUE: + triggered_spell_id = 28791; // Increases the friendly target's attack power by $s1 for $d. + break; + case CLASS_WARRIOR: + triggered_spell_id = 28790; // Increases the friendly target's armor + break; + default: + return false; + } + break; + } + //Seal of Vengeance + case 31801: + { + if(effIndex != 0) // effect 1,2 used by seal unleashing code + return false; + + triggered_spell_id = 31803; + break; + } + // Spiritual Att. + case 31785: + case 33776: + { + // if healed by another unit (pVictim) + if(this == pVictim) + return false; + + // heal amount + basepoints0 = triggeredByAura->GetModifier()->m_amount*damage/100; + target = this; + triggered_spell_id = 31786; + break; + } + // Paladin Tier 6 Trinket (Ashtongue Talisman of Zeal) + case 40470: + { + if( !procSpell ) + return false; + + float chance; + + // Flash of light/Holy light + if( procSpell->SpellFamilyFlags & 0x00000000C0000000LL) + { + triggered_spell_id = 40471; + chance = 15.f; + } + // Judgement + else if( procSpell->SpellFamilyFlags & 0x0000000000800000LL ) + { + triggered_spell_id = 40472; + chance = 50.f; + } + else + return false; + + if (!roll_chance_f(chance)) + return false; + + break; + } + } + break; + } + case SPELLFAMILY_SHAMAN: + { + switch(dummySpell->Id) + { + // Totemic Power (The Earthshatterer set) + case 28823: + { + if( !pVictim ) + return false; + + // Set class defined buff + switch (pVictim->getClass()) + { + case CLASS_PALADIN: + case CLASS_PRIEST: + case CLASS_SHAMAN: + case CLASS_DRUID: + triggered_spell_id = 28824; // Increases the friendly target's mana regeneration by $s1 per 5 sec. for $d. + break; + case CLASS_MAGE: + case CLASS_WARLOCK: + triggered_spell_id = 28825; // Increases the friendly target's spell damage and healing by up to $s1 for $d. + break; + case CLASS_HUNTER: + case CLASS_ROGUE: + triggered_spell_id = 28826; // Increases the friendly target's attack power by $s1 for $d. + break; + case CLASS_WARRIOR: + triggered_spell_id = 28827; // Increases the friendly target's armor + break; + default: + return false; + } + break; + } + // Lesser Healing Wave (Totem of Flowing Water Relic) + case 28849: + { + target = this; + triggered_spell_id = 28850; + break; + } + // Windfury Weapon (Passive) 1-5 Ranks + case 33757: + { + if(GetTypeId()!=TYPEID_PLAYER) + return false; + + if(!castItem || !castItem->IsEquipped()) + return false; + + // custom cooldown processing case + if( cooldown && ((Player*)this)->HasSpellCooldown(dummySpell->Id)) + return false; + + uint32 spellId; + switch (castItem->GetEnchantmentId(EnchantmentSlot(TEMP_ENCHANTMENT_SLOT))) + { + case 283: spellId = 33757; break; //1 Rank + case 284: spellId = 33756; break; //2 Rank + case 525: spellId = 33755; break; //3 Rank + case 1669:spellId = 33754; break; //4 Rank + case 2636:spellId = 33727; break; //5 Rank + default: + { + sLog.outError("Unit::HandleDummyAuraProc: non handled item enchantment (rank?) %u for spell id: %u (Windfury)", + castItem->GetEnchantmentId(EnchantmentSlot(TEMP_ENCHANTMENT_SLOT)),dummySpell->Id); + return false; + } + } + + SpellEntry const* windfurySpellEntry = sSpellStore.LookupEntry(spellId); + if(!windfurySpellEntry) + { + sLog.outError("Unit::HandleDummyAuraProc: non existed spell id: %u (Windfury)",spellId); + return false; + } + + int32 extra_attack_power = CalculateSpellDamage(windfurySpellEntry,0,windfurySpellEntry->EffectBasePoints[0],pVictim); + + // Off-Hand case + if ( castItem->GetSlot() == EQUIPMENT_SLOT_OFFHAND ) + { + // Value gained from additional AP + basepoints0 = int32(extra_attack_power/14.0f * GetAttackTime(OFF_ATTACK)/1000/2); + triggered_spell_id = 33750; + } + // Main-Hand case + else + { + // Value gained from additional AP + basepoints0 = int32(extra_attack_power/14.0f * GetAttackTime(BASE_ATTACK)/1000); + triggered_spell_id = 25504; + } + + // apply cooldown before cast to prevent processing itself + if( cooldown ) + ((Player*)this)->AddSpellCooldown(dummySpell->Id,0,time(NULL) + cooldown); + + // Attack Twice + for ( uint32 i = 0; i<2; ++i ) + CastCustomSpell(pVictim,triggered_spell_id,&basepoints0,NULL,NULL,true,castItem,triggeredByAura); + + return true; + } + // Shaman Tier 6 Trinket + case 40463: + { + if( !procSpell ) + return false; + + float chance; + if (procSpell->SpellFamilyFlags & 0x0000000000000001LL) + { + triggered_spell_id = 40465; // Lightning Bolt + chance = 15.f; + } + else if (procSpell->SpellFamilyFlags & 0x0000000000000080LL) + { + triggered_spell_id = 40465; // Lesser Healing Wave + chance = 10.f; + } + else if (procSpell->SpellFamilyFlags & 0x0000001000000000LL) + { + triggered_spell_id = 40466; // Stormstrike + chance = 50.f; + } + else + return false; + + if (!roll_chance_f(chance)) + return false; + + target = this; + break; + } + } + + // Earth Shield + if(dummySpell->SpellFamilyFlags==0x40000000000LL) + { + if(GetTypeId() != TYPEID_PLAYER) + return false; + + // heal + basepoints0 = triggeredByAura->GetModifier()->m_amount; + target = this; + triggered_spell_id = 379; + break; + } + // Lightning Overload + if (dummySpell->SpellIconID == 2018) // only this spell have SpellFamily Shaman SpellIconID == 2018 and dummy aura + { + if(!procSpell || GetTypeId() != TYPEID_PLAYER || !pVictim ) + return false; + + // custom cooldown processing case + if( cooldown && GetTypeId()==TYPEID_PLAYER && ((Player*)this)->HasSpellCooldown(dummySpell->Id)) + return false; + + uint32 spellId = 0; + // Every Lightning Bolt and Chain Lightning spell have dublicate vs half damage and zero cost + switch (procSpell->Id) + { + // Lightning Bolt + case 403: spellId = 45284; break; // Rank 1 + case 529: spellId = 45286; break; // Rank 2 + case 548: spellId = 45287; break; // Rank 3 + case 915: spellId = 45288; break; // Rank 4 + case 943: spellId = 45289; break; // Rank 5 + case 6041: spellId = 45290; break; // Rank 6 + case 10391: spellId = 45291; break; // Rank 7 + case 10392: spellId = 45292; break; // Rank 8 + case 15207: spellId = 45293; break; // Rank 9 + case 15208: spellId = 45294; break; // Rank 10 + case 25448: spellId = 45295; break; // Rank 11 + case 25449: spellId = 45296; break; // Rank 12 + // Chain Lightning + case 421: spellId = 45297; break; // Rank 1 + case 930: spellId = 45298; break; // Rank 2 + case 2860: spellId = 45299; break; // Rank 3 + case 10605: spellId = 45300; break; // Rank 4 + case 25439: spellId = 45301; break; // Rank 5 + case 25442: spellId = 45302; break; // Rank 6 + default: + sLog.outError("Unit::HandleDummyAuraProc: non handled spell id: %u (LO)", procSpell->Id); + return false; + } + // No thread generated mod + SpellModifier *mod = new SpellModifier; + mod->op = SPELLMOD_THREAT; + mod->value = -100; + mod->type = SPELLMOD_PCT; + mod->spellId = dummySpell->Id; + mod->effectId = 0; + mod->lastAffected = NULL; + mod->mask = 0x0000000000000003LL; + mod->charges = 0; + ((Player*)this)->AddSpellMod(mod, true); + + // Remove cooldown (Chain Lightning - have Category Recovery time) + if (procSpell->SpellFamilyFlags & 0x0000000000000002LL) + ((Player*)this)->RemoveSpellCooldown(spellId); + + // Hmmm.. in most case spells alredy set half basepoints but... + // Lightning Bolt (2-10 rank) have full basepoint and half bonus from level + // As on wiki: + // BUG: Rank 2 to 10 (and maybe 11) of Lightning Bolt will proc another Bolt with FULL damage (not halved). This bug is known and will probably be fixed soon. + // So - no add changes :) + CastSpell(pVictim, spellId, true, castItem, triggeredByAura); + + ((Player*)this)->AddSpellMod(mod, false); + + if( cooldown && GetTypeId()==TYPEID_PLAYER ) + ((Player*)this)->AddSpellCooldown(dummySpell->Id,0,time(NULL) + cooldown); + + return true; + } + break; + } + default: + break; + } + + // processed charge only counting case + if(!triggered_spell_id) + return true; + + SpellEntry const* triggerEntry = sSpellStore.LookupEntry(triggered_spell_id); + + if(!triggerEntry) + { + sLog.outError("Unit::HandleDummyAuraProc: Spell %u have not existed triggered spell %u",dummySpell->Id,triggered_spell_id); + return false; + } + + // default case + if(!target || target!=this && !target->isAlive()) + return false; + + if( cooldown && GetTypeId()==TYPEID_PLAYER && ((Player*)this)->HasSpellCooldown(triggered_spell_id)) + return false; + + if(basepoints0) + CastCustomSpell(target,triggered_spell_id,&basepoints0,NULL,NULL,true,castItem,triggeredByAura); + else + CastSpell(target,triggered_spell_id,true,castItem,triggeredByAura); + + if( cooldown && GetTypeId()==TYPEID_PLAYER ) + ((Player*)this)->AddSpellCooldown(triggered_spell_id,0,time(NULL) + cooldown); + + return true; +} + +bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlags,WeaponAttackType attackType, uint32 cooldown) +{ + SpellEntry const* auraSpellInfo = triggeredByAura->GetSpellProto(); + + Item* castItem = triggeredByAura->GetCastItemGUID() && GetTypeId()==TYPEID_PLAYER + ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetCastItemGUID()) : NULL; + + uint32 triggered_spell_id = auraSpellInfo->EffectTriggerSpell[triggeredByAura->GetEffIndex()]; + Unit* target = !(procFlags & PROC_FLAG_HEAL) && IsPositiveSpell(triggered_spell_id) ? this : pVictim; + int32 basepoints0 = 0; + + switch(auraSpellInfo->SpellFamilyName) + { + case SPELLFAMILY_GENERIC: + { + switch(auraSpellInfo->Id) + { + // Aegis of Preservation + case 23780: + //Aegis Heal (instead non-existed triggered spell) + triggered_spell_id = 23781; + target = this; + break; + // Elune's Touch (moonkin mana restore) + case 24905: + { + // Elune's Touch (instead non-existed triggered spell) + triggered_spell_id = 33926; + basepoints0 = int32(0.3f * GetTotalAttackPowerValue(BASE_ATTACK)); + target = this; + break; + } + // Enlightenment + case 29601: + { + // only for cast with mana price + if(!procSpell || procSpell->powerType!=POWER_MANA || procSpell->manaCost==0 && procSpell->ManaCostPercentage==0 && procSpell->manaCostPerlevel==0) + return false; + break; // fall through to normal cast + } + // Health Restore + case 33510: + { + // at melee hit call std triggered spell + if(procFlags & PROC_FLAG_HIT_MELEE) + break; // fall through to normal cast + + // Mark of Conquest - else (at range hit) called custom case + triggered_spell_id = 39557; + target = this; + break; + } + // Shaleskin + case 36576: + return true; // nothing to do + // Forgotten Knowledge (Blade of Wizardry) + case 38319: + // only for harmful enemy targeted spell + if(!pVictim || pVictim==this || !procSpell || IsPositiveSpell(procSpell->Id)) + return false; + break; // fall through to normal cast + // Aura of Wrath (Darkmoon Card: Wrath trinket bonus) + case 39442: + { + // proc only at non-crit hits + if(procFlags & (PROC_FLAG_CRIT_MELEE|PROC_FLAG_CRIT_RANGED|PROC_FLAG_CRIT_SPELL)) + return false; + break; // fall through to normal cast + } + // Augment Pain (Timbal's Focusing Crystal trinket bonus) + case 45054: + { + if(!procSpell) + return false; + + //only periodic damage can trigger spell + bool found = false; + for(int j = 0; j < 3; ++j) + { + if( procSpell->EffectApplyAuraName[j]==SPELL_AURA_PERIODIC_DAMAGE || + procSpell->EffectApplyAuraName[j]==SPELL_AURA_PERIODIC_DAMAGE_PERCENT || + procSpell->EffectApplyAuraName[j]==SPELL_AURA_PERIODIC_LEECH ) + { + found = true; + break; + } + } + if(!found) + return false; + + break; // fall through to normal cast + } + // Evasive Maneuvers (Commendation of Kael'thas) + case 45057: + { + // damage taken that reduces below 35% health + // does NOT mean you must have been >= 35% before + if (int32(GetHealth())-int32(damage) >= int32(GetMaxHealth()*0.35f)) + return false; + break; // fall through to normal cast + } + } + + switch(triggered_spell_id) + { + // Setup + case 15250: + { + // applied only for main target + if(!pVictim || pVictim != getVictim()) + return false; + + // continue normal case + break; + } + // Shamanistic Rage triggered spell + case 30824: + basepoints0 = int32(GetTotalAttackPowerValue(BASE_ATTACK)*triggeredByAura->GetModifier()->m_amount/100); + break; + } + break; + } + case SPELLFAMILY_MAGE: + { + switch(auraSpellInfo->SpellIconID) + { + // Blazing Speed + case 2127: + //Blazing Speed (instead non-existed triggered spell) + triggered_spell_id = 31643; + target = this; + break; + } + switch(auraSpellInfo->Id) + { + // Persistent Shield (Scarab Brooch) + case 26467: + basepoints0 = int32(damage * 0.15f); + break; + } + break; + } + case SPELLFAMILY_WARRIOR: + { + //Rampage + if((auraSpellInfo->SpellFamilyFlags & 0x100000) && auraSpellInfo->SpellIconID==2006) + { + //all ranks have effect[0]==AURA (Proc Trigger Spell, non-existed) + //and effect[1]==TriggerSpell + if(auraSpellInfo->Effect[1]!=SPELL_EFFECT_TRIGGER_SPELL) + { + sLog.outError("Unit::HandleProcTriggerSpell: Spell %u have wrong effect in RM",triggeredByAura->GetSpellProto()->Id); + return false; + } + triggered_spell_id = auraSpellInfo->EffectTriggerSpell[1]; + break; // fall through to normal cast + } + break; + } + case SPELLFAMILY_WARLOCK: + { + // Pyroclasm + if(auraSpellInfo->SpellFamilyFlags == 0x0000000000000000 && auraSpellInfo->SpellIconID==1137) + { + // last case for Hellfire that damage caster also but don't must stun caster + if( pVictim == this ) + return false; + + // custom chnace + float chance = 0; + switch (triggeredByAura->GetId()) + { + case 18096: chance = 13.0f; break; + case 18073: chance = 26.0f; break; + } + if (!roll_chance_f(chance)) + return false; + + // Pyroclasm (instead non-existed triggered spell) + triggered_spell_id = 18093; + target = pVictim; + break; + } + // Drain Soul + if(auraSpellInfo->SpellFamilyFlags & 0x0000000000004000) + { + bool found = false; + Unit::AuraList const& mAddFlatModifier = GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER); + for(Unit::AuraList::const_iterator i = mAddFlatModifier.begin(); i != mAddFlatModifier.end(); ++i) + { + //Improved Drain Soul + if ((*i)->GetModifier()->m_miscvalue == SPELLMOD_CHANCE_OF_SUCCESS && (*i)->GetSpellProto()->SpellIconID == 113) + { + int32 value2 = CalculateSpellDamage((*i)->GetSpellProto(),2,(*i)->GetSpellProto()->EffectBasePoints[2],this); + basepoints0 = value2 * GetMaxPower(POWER_MANA) / 100; + + // Drain Soul + triggered_spell_id = 18371; + target = this; + found = true; + break; + } + } + if(!found) + return false; + break; // fall through to normal cast + } + break; + } + case SPELLFAMILY_PRIEST: + { + //Blessed Recovery + if(auraSpellInfo->SpellFamilyFlags == 0x00000000LL && auraSpellInfo->SpellIconID==1875) + { + switch (triggeredByAura->GetSpellProto()->Id) + { + case 27811: triggered_spell_id = 27813; break; + case 27815: triggered_spell_id = 27817; break; + case 27816: triggered_spell_id = 27818; break; + default: + sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in BR",triggeredByAura->GetSpellProto()->Id); + return false; + } + + int32 heal_amount = damage * triggeredByAura->GetModifier()->m_amount / 100; + basepoints0 = heal_amount/3; + target = this; + break; + } + // Shadowguard + if((auraSpellInfo->SpellFamilyFlags & 0x80000000LL) && auraSpellInfo->SpellVisual==7958) + { + switch(triggeredByAura->GetSpellProto()->Id) + { + case 18137: + triggered_spell_id = 28377; break; // Rank 1 + case 19308: + triggered_spell_id = 28378; break; // Rank 2 + case 19309: + triggered_spell_id = 28379; break; // Rank 3 + case 19310: + triggered_spell_id = 28380; break; // Rank 4 + case 19311: + triggered_spell_id = 28381; break; // Rank 5 + case 19312: + triggered_spell_id = 28382; break; // Rank 6 + case 25477: + triggered_spell_id = 28385; break; // Rank 7 + default: + sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in SG",triggeredByAura->GetSpellProto()->Id); + return false; + } + target = pVictim; + break; + } + break; + } + case SPELLFAMILY_DRUID: + { + switch(auraSpellInfo->Id) + { + // Leader of the Pack (triggering Improved Leader of the Pack heal) + case 24932: + { + if (triggeredByAura->GetModifier()->m_amount == 0) + return false; + basepoints0 = triggeredByAura->GetModifier()->m_amount * GetMaxHealth() / 100; + triggered_spell_id = 34299; + break; + }; + // Druid Forms Trinket (Druid Tier5 Trinket, triggers different spells per Form) + case 37336: + { + switch(m_form) + { + case FORM_BEAR: + case FORM_DIREBEAR: + triggered_spell_id=37340; break;// Ursine Blessing + case FORM_CAT: + triggered_spell_id=37341; break;// Feline Blessing + case FORM_TREE: + triggered_spell_id=37342; break;// Slyvan Blessing + case FORM_MOONKIN: + triggered_spell_id=37343; break;// Lunar Blessing + case FORM_NONE: + triggered_spell_id=37344; break;// Cenarion Blessing (for caster form, except FORM_MOONKIN) + default: + return false; + } + + target = this; + break; + } + } + break; + } + case SPELLFAMILY_ROGUE: + { + if(auraSpellInfo->SpellFamilyFlags == 0x0000000000000000LL) + { + switch(auraSpellInfo->SpellIconID) + { + // Combat Potency + case 2260: + { + // skip non offhand attacks + if(attackType!=OFF_ATTACK) + return false; + break; // fall through to normal cast + } + } + } + break; + } + case SPELLFAMILY_PALADIN: + { + if(auraSpellInfo->SpellFamilyFlags == 0x00000000LL) + { + switch(auraSpellInfo->Id) + { + // Lightning Capacitor + case 37657: + { + // trinket ProcTriggerSpell but for safe checks for player + if(!castItem || !pVictim || !pVictim->isAlive() || GetTypeId()!=TYPEID_PLAYER) + return false; + + if(((Player*)this)->HasSpellCooldown(37657)) + return false; + + // stacking + CastSpell(this, 37658, true, castItem, triggeredByAura); + // 2.5s cooldown before it can stack again, current system allow 1 sec step in cooldown + ((Player*)this)->AddSpellCooldown(37657,0,time(NULL)+(roll_chance_i(50) ? 2 : 3)); + + // counting + uint32 count = 0; + AuraList const& dummyAura = GetAurasByType(SPELL_AURA_DUMMY); + for(AuraList::const_iterator itr = dummyAura.begin(); itr != dummyAura.end(); ++itr) + if((*itr)->GetId()==37658) + ++count; + + // release at 3 aura in stack + if(count <= 2) + return true; // main triggered spell casted anyway + + RemoveAurasDueToSpell(37658); + CastSpell(pVictim, 37661, true, castItem, triggeredByAura); + return true; + } + // Healing Discount + case 37705: + // Healing Trance (instead non-existed triggered spell) + triggered_spell_id = 37706; + target = this; + break; + // HoTs on Heals (Fel Reaver's Piston trinket) + case 38299: + { + // at direct heal effect + if(!procSpell || !IsSpellHaveEffect(procSpell,SPELL_EFFECT_HEAL)) + return false; + + // single proc at time + AuraList const& scAuras = GetSingleCastAuras(); + for(AuraList::const_iterator itr = scAuras.begin(); itr != scAuras.end(); ++itr) + if((*itr)->GetId()==triggered_spell_id) + return false; + + // positive cast at victim instead self + target = pVictim; + break; + } + } + switch(auraSpellInfo->SpellIconID) + { + case 241: + { + switch(auraSpellInfo->EffectTriggerSpell[0]) + { + //Illumination + case 18350: + { + if(!procSpell) + return false; + + // procspell is triggered spell but we need mana cost of original casted spell + uint32 originalSpellId = procSpell->Id; + + // Holy Shock + if(procSpell->SpellFamilyName == SPELLFAMILY_PALADIN) + { + if(procSpell->SpellFamilyFlags & 0x0001000000000000LL) + { + switch(procSpell->Id) + { + case 25914: originalSpellId = 20473; break; + case 25913: originalSpellId = 20929; break; + case 25903: originalSpellId = 20930; break; + case 27175: originalSpellId = 27174; break; + case 33074: originalSpellId = 33072; break; + default: + sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in HShock",procSpell->Id); + return false; + } + } + } + + SpellEntry const *originalSpell = sSpellStore.LookupEntry(originalSpellId); + if(!originalSpell) + { + sLog.outError("Unit::HandleProcTriggerSpell: Spell %u unknown but selected as original in Illu",originalSpellId); + return false; + } + + // percent stored in effect 1 (class scripts) base points + int32 percent = auraSpellInfo->EffectBasePoints[1]+1; + + basepoints0 = originalSpell->manaCost*percent/100; + triggered_spell_id = 20272; + target = this; + break; + } + } + break; + } + } + } + if(auraSpellInfo->SpellFamilyFlags & 0x00080000) + { + switch(auraSpellInfo->SpellIconID) + { + //Judgement of Wisdom (overwrite non existing triggered spell call in spell.dbc + case 206: + { + if(!pVictim || !pVictim->isAlive()) + return false; + + uint32 spell = 0; + switch(triggeredByAura->GetSpellProto()->Id) + { + case 20186: + triggered_spell_id = 20268; // Rank 1 + break; + case 20354: + triggered_spell_id = 20352; // Rank 2 + break; + case 20355: + triggered_spell_id = 20353; // Rank 3 + break; + case 27164: + triggered_spell_id = 27165; // Rank 4 + break; + default: + sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in JoW",triggeredByAura->GetSpellProto()->Id); + return false; + } + + pVictim->CastSpell(pVictim,triggered_spell_id,true,castItem,triggeredByAura,GetGUID()); + return true; // no hidden cooldown + } + //Judgement of Light + case 299: + { + if(!pVictim || !pVictim->isAlive()) + return false; + + // overwrite non existing triggered spell call in spell.dbc + uint32 spell = 0; + switch(triggeredByAura->GetSpellProto()->Id) + { + case 20185: + triggered_spell_id = 20267; // Rank 1 + break; + case 20344: + triggered_spell_id = 20341; // Rank 2 + break; + case 20345: + triggered_spell_id = 20342; // Rank 3 + break; + case 20346: + triggered_spell_id = 20343; // Rank 4 + break; + case 27162: + triggered_spell_id = 27163; // Rank 5 + break; + default: + sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in JoL",triggeredByAura->GetSpellProto()->Id); + return false; + } + pVictim->CastSpell(pVictim,triggered_spell_id,true,castItem,triggeredByAura,GetGUID()); + return true; // no hidden cooldown + } + } + } + // custom check for proc spell + switch(auraSpellInfo->Id) + { + // Bonus Healing (item spell) + case 40971: + { + if(!pVictim || !pVictim->isAlive()) + return false; + + // bonus if health < 50% + if(pVictim->GetHealth() >= pVictim->GetMaxHealth()*triggeredByAura->GetModifier()->m_amount/100) + return false; + + // cast at target positive spell + target = pVictim; + break; + } + } + switch(triggered_spell_id) + { + // Seal of Command + case 20424: + // prevent chain of triggered spell from same triggered spell + if(procSpell && procSpell->Id==20424) + return false; + break; + } + break; + } + case SPELLFAMILY_SHAMAN: + { + if(auraSpellInfo->SpellFamilyFlags == 0x0000000000000000) + { + switch(auraSpellInfo->SpellIconID) + { + case 19: + { + switch(auraSpellInfo->Id) + { + case 23551: // Lightning Shield - Tier2: 8 pieces proc shield + { + // Lightning Shield (overwrite non existing triggered spell call in spell.dbc) + triggered_spell_id = 23552; + target = pVictim; + break; + } + case 23552: // Lightning Shield - trigger shield damage + { + // Lightning Shield (overwrite non existing triggered spell call in spell.dbc) + triggered_spell_id = 27635; + target = pVictim; + break; + } + } + break; + } + // Mana Surge (Shaman T1 bonus) + case 87: + { + if(!procSpell) + return false; + + basepoints0 = procSpell->manaCost * 35/100; + triggered_spell_id = 23571; + target = this; + break; + } + //Nature's Guardian + case 2013: + { + if(GetTypeId()!=TYPEID_PLAYER) + return false; + + // damage taken that reduces below 30% health + // does NOT mean you must have been >= 30% before + if (10*(int32(GetHealth())-int32(damage)) >= 3*GetMaxHealth()) + return false; + + triggered_spell_id = 31616; + + // need check cooldown now + if( cooldown && ((Player*)this)->HasSpellCooldown(triggered_spell_id)) + return false; + + basepoints0 = triggeredByAura->GetModifier()->m_amount * GetMaxHealth() / 100; + target = this; + if(pVictim && pVictim->isAlive()) + pVictim->getThreatManager().modifyThreatPercent(this,-10); + break; + } + } + } + + // Water Shield (we can't set cooldown for main spell - it's player casted spell + if((auraSpellInfo->SpellFamilyFlags & 0x0000002000000000LL) && auraSpellInfo->SpellVisual==7358) + { + target = this; + break; + } + + // Lightning Shield + if((auraSpellInfo->SpellFamilyFlags & 0x00000400) && auraSpellInfo->SpellVisual==37) + { + // overwrite non existing triggered spell call in spell.dbc + switch(triggeredByAura->GetSpellProto()->Id) + { + case 324: + triggered_spell_id = 26364; break; // Rank 1 + case 325: + triggered_spell_id = 26365; break; // Rank 2 + case 905: + triggered_spell_id = 26366; break; // Rank 3 + case 945: + triggered_spell_id = 26367; break; // Rank 4 + case 8134: + triggered_spell_id = 26369; break; // Rank 5 + case 10431: + triggered_spell_id = 26370; break; // Rank 6 + case 10432: + triggered_spell_id = 26363; break; // Rank 7 + case 25469: + triggered_spell_id = 26371; break; // Rank 8 + case 25472: + triggered_spell_id = 26372; break; // Rank 9 + default: + sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in LShield",triggeredByAura->GetSpellProto()->Id); + return false; + } + + target = pVictim; + break; + } + break; + } + } + + // standard non-dummy case + if(!triggered_spell_id) + { + sLog.outError("Unit::HandleProcTriggerSpell: Spell %u have 0 in EffectTriggered[%d], not handled custom case?",auraSpellInfo->Id,triggeredByAura->GetEffIndex()); + return false; + } + + SpellEntry const* triggerEntry = sSpellStore.LookupEntry(triggered_spell_id); + + if(!triggerEntry) + { + sLog.outError("Unit::HandleProcTriggerSpell: Spell %u have not existed EffectTriggered[%d]=%u, not handled custom case?",auraSpellInfo->Id,triggeredByAura->GetEffIndex(),triggered_spell_id); + return false; + } + + // not allow proc extra attack spell at extra attack + if( m_extraAttacks && IsSpellHaveEffect(triggerEntry,SPELL_EFFECT_ADD_EXTRA_ATTACKS) ) + return false; + + if( cooldown && GetTypeId()==TYPEID_PLAYER && ((Player*)this)->HasSpellCooldown(triggered_spell_id)) + return false; + + // default case + if(!target || target!=this && !target->isAlive()) + return false; + + if(basepoints0) + CastCustomSpell(target,triggered_spell_id,&basepoints0,NULL,NULL,true,castItem,triggeredByAura); + else + CastSpell(target,triggered_spell_id,true,castItem,triggeredByAura); + + if( cooldown && GetTypeId()==TYPEID_PLAYER ) + ((Player*)this)->AddSpellCooldown(triggered_spell_id,0,time(NULL) + cooldown); + + return true; +} + +bool Unit::HandleOverrideClassScriptAuraProc(Unit *pVictim, int32 scriptId, uint32 damage, Aura *triggeredByAura, SpellEntry const *procSpell, uint32 cooldown) +{ + if(!pVictim || !pVictim->isAlive()) + return false; + + Item* castItem = triggeredByAura->GetCastItemGUID() && GetTypeId()==TYPEID_PLAYER + ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetCastItemGUID()) : NULL; + + uint32 triggered_spell_id = 0; + + switch(scriptId) + { + case 836: // Improved Blizzard (Rank 1) + { + if( !procSpell || procSpell->SpellVisual!=9487 ) + return false; + triggered_spell_id = 12484; + break; + } + case 988: // Improved Blizzard (Rank 2) + { + if( !procSpell || procSpell->SpellVisual!=9487 ) + return false; + triggered_spell_id = 12485; + break; + } + case 989: // Improved Blizzard (Rank 3) + { + if( !procSpell || procSpell->SpellVisual!=9487 ) + return false; + triggered_spell_id = 12486; + break; + } + case 4086: // Improved Mend Pet (Rank 1) + case 4087: // Improved Mend Pet (Rank 2) + { + int32 chance = triggeredByAura->GetSpellProto()->EffectBasePoints[triggeredByAura->GetEffIndex()]; + if(!roll_chance_i(chance)) + return false; + + triggered_spell_id = 24406; + break; + } + case 4533: // Dreamwalker Raiment 2 pieces bonus + { + // Chance 50% + if (!roll_chance_i(50)) + return false; + + switch (pVictim->getPowerType()) + { + case POWER_MANA: triggered_spell_id = 28722; break; + case POWER_RAGE: triggered_spell_id = 28723; break; + case POWER_ENERGY: triggered_spell_id = 28724; break; + default: + return false; + } + break; + } + case 4537: // Dreamwalker Raiment 6 pieces bonus + triggered_spell_id = 28750; // Blessing of the Claw + break; + case 5497: // Improved Mana Gems (Serpent-Coil Braid) + triggered_spell_id = 37445; // Mana Surge + break; + } + + // not processed + if(!triggered_spell_id) + return false; + + // standard non-dummy case + SpellEntry const* triggerEntry = sSpellStore.LookupEntry(triggered_spell_id); + + if(!triggerEntry) + { + sLog.outError("Unit::HandleOverrideClassScriptAuraProc: Spell %u triggering for class script id %u",triggered_spell_id,scriptId); + return false; + } + + if( cooldown && GetTypeId()==TYPEID_PLAYER && ((Player*)this)->HasSpellCooldown(triggered_spell_id)) + return false; + + CastSpell(pVictim, triggered_spell_id, true, castItem, triggeredByAura); + + if( cooldown && GetTypeId()==TYPEID_PLAYER ) + ((Player*)this)->AddSpellCooldown(triggered_spell_id,0,time(NULL) + cooldown); + + return true; +} + +void Unit::setPowerType(Powers new_powertype) +{ + SetByteValue(UNIT_FIELD_BYTES_0, 3, new_powertype); + + if(GetTypeId() == TYPEID_PLAYER) + { + if(((Player*)this)->GetGroup()) + ((Player*)this)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_POWER_TYPE); + } + else if(((Creature*)this)->isPet()) + { + Pet *pet = ((Pet*)this); + if(pet->isControlled()) + { + Unit *owner = GetOwner(); + if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup()) + ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_POWER_TYPE); + } + } + + switch(new_powertype) + { + default: + case POWER_MANA: + break; + case POWER_RAGE: + SetMaxPower(POWER_RAGE,GetCreatePowers(POWER_RAGE)); + SetPower( POWER_RAGE,0); + break; + case POWER_FOCUS: + SetMaxPower(POWER_FOCUS,GetCreatePowers(POWER_FOCUS)); + SetPower( POWER_FOCUS,GetCreatePowers(POWER_FOCUS)); + break; + case POWER_ENERGY: + SetMaxPower(POWER_ENERGY,GetCreatePowers(POWER_ENERGY)); + SetPower( POWER_ENERGY,0); + break; + case POWER_HAPPINESS: + SetMaxPower(POWER_HAPPINESS,GetCreatePowers(POWER_HAPPINESS)); + SetPower(POWER_HAPPINESS,GetCreatePowers(POWER_HAPPINESS)); + break; + } +} + +FactionTemplateEntry const* Unit::getFactionTemplateEntry() const +{ + FactionTemplateEntry const* entry = sFactionTemplateStore.LookupEntry(getFaction()); + if(!entry) + { + static uint64 guid = 0; // prevent repeating spam same faction problem + + if(GetGUID() != guid) + { + if(GetTypeId() == TYPEID_PLAYER) + sLog.outError("Player %s have invalid faction (faction template id) #%u", ((Player*)this)->GetName(), getFaction()); + else + sLog.outError("Creature (template id: %u) have invalid faction (faction template id) #%u", ((Creature*)this)->GetCreatureInfo()->Entry, getFaction()); + guid = GetGUID(); + } + } + return entry; +} + +bool Unit::IsHostileTo(Unit const* unit) const +{ + // always non-hostile to self + if(unit==this) + return false; + + // always non-hostile to GM in GM mode + if(unit->GetTypeId()==TYPEID_PLAYER && ((Player const*)unit)->isGameMaster()) + return false; + + // always hostile to enemy + if(getVictim()==unit || unit->getVictim()==this) + return true; + + // test pet/charm masters instead pers/charmeds + Unit const* testerOwner = GetCharmerOrOwner(); + Unit const* targetOwner = unit->GetCharmerOrOwner(); + + // always hostile to owner's enemy + if(testerOwner && (testerOwner->getVictim()==unit || unit->getVictim()==testerOwner)) + return true; + + // always hostile to enemy owner + if(targetOwner && (getVictim()==targetOwner || targetOwner->getVictim()==this)) + return true; + + // always hostile to owner of owner's enemy + if(testerOwner && targetOwner && (testerOwner->getVictim()==targetOwner || targetOwner->getVictim()==testerOwner)) + return true; + + Unit const* tester = testerOwner ? testerOwner : this; + Unit const* target = targetOwner ? targetOwner : unit; + + // always non-hostile to target with common owner, or to owner/pet + if(tester==target) + return false; + + // special cases (Duel, etc) + if(tester->GetTypeId()==TYPEID_PLAYER && target->GetTypeId()==TYPEID_PLAYER) + { + Player const* pTester = (Player const*)tester; + Player const* pTarget = (Player const*)target; + + // Duel + if(pTester->duel && pTester->duel->opponent == pTarget && pTester->duel->startTime != 0) + return true; + + // Group + if(pTester->GetGroup() && pTester->GetGroup()==pTarget->GetGroup()) + return false; + + // Sanctuary + if(pTarget->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_SANCTUARY) && pTester->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_SANCTUARY)) + return false; + + // PvP FFA state + if(pTester->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP) && pTarget->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP)) + return true; + + //= PvP states + // Green/Blue (can't attack) + if(pTester->GetTeam()==pTarget->GetTeam()) + return false; + + // Red (can attack) if true, Blue/Yellow (can't attack) in another case + return pTester->IsPvP() && pTarget->IsPvP(); + } + + // faction base cases + FactionTemplateEntry const*tester_faction = tester->getFactionTemplateEntry(); + FactionTemplateEntry const*target_faction = target->getFactionTemplateEntry(); + if(!tester_faction || !target_faction) + return false; + + if(target->isAttackingPlayer() && tester->IsContestedGuard()) + return true; + + // PvC forced reaction and reputation case + if(tester->GetTypeId()==TYPEID_PLAYER) + { + // forced reaction + ForcedReactions::const_iterator forceItr = ((Player*)tester)->m_forcedReactions.find(target_faction->faction); + if(forceItr!=((Player*)tester)->m_forcedReactions.end()) + return forceItr->second <= REP_HOSTILE; + + // if faction have reputation then hostile state for tester at 100% dependent from at_war state + if(FactionEntry const* raw_target_faction = sFactionStore.LookupEntry(target_faction->faction)) + if(raw_target_faction->reputationListID >=0) + if(FactionState const* factionState = ((Player*)tester)->GetFactionState(raw_target_faction)) + return (factionState->Flags & FACTION_FLAG_AT_WAR); + } + // CvP forced reaction and reputation case + else if(target->GetTypeId()==TYPEID_PLAYER) + { + // forced reaction + ForcedReactions::const_iterator forceItr = ((Player const*)target)->m_forcedReactions.find(tester_faction->faction); + if(forceItr!=((Player const*)target)->m_forcedReactions.end()) + return forceItr->second <= REP_HOSTILE; + + // apply reputation state + FactionEntry const* raw_tester_faction = sFactionStore.LookupEntry(tester_faction->faction); + if(raw_tester_faction && raw_tester_faction->reputationListID >=0 ) + return ((Player const*)target)->GetReputationRank(raw_tester_faction) <= REP_HOSTILE; + } + + // common faction based case (CvC,PvC,CvP) + return tester_faction->IsHostileTo(*target_faction); +} + +bool Unit::IsFriendlyTo(Unit const* unit) const +{ + // always friendly to self + if(unit==this) + return true; + + // always friendly to GM in GM mode + if(unit->GetTypeId()==TYPEID_PLAYER && ((Player const*)unit)->isGameMaster()) + return true; + + // always non-friendly to enemy + if(getVictim()==unit || unit->getVictim()==this) + return false; + + // test pet/charm masters instead pers/charmeds + Unit const* testerOwner = GetCharmerOrOwner(); + Unit const* targetOwner = unit->GetCharmerOrOwner(); + + // always non-friendly to owner's enemy + if(testerOwner && (testerOwner->getVictim()==unit || unit->getVictim()==testerOwner)) + return false; + + // always non-friendly to enemy owner + if(targetOwner && (getVictim()==targetOwner || targetOwner->getVictim()==this)) + return false; + + // always non-friendly to owner of owner's enemy + if(testerOwner && targetOwner && (testerOwner->getVictim()==targetOwner || targetOwner->getVictim()==testerOwner)) + return false; + + Unit const* tester = testerOwner ? testerOwner : this; + Unit const* target = targetOwner ? targetOwner : unit; + + // always friendly to target with common owner, or to owner/pet + if(tester==target) + return true; + + // special cases (Duel) + if(tester->GetTypeId()==TYPEID_PLAYER && target->GetTypeId()==TYPEID_PLAYER) + { + Player const* pTester = (Player const*)tester; + Player const* pTarget = (Player const*)target; + + // Duel + if(pTester->duel && pTester->duel->opponent == target && pTester->duel->startTime != 0) + return false; + + // Group + if(pTester->GetGroup() && pTester->GetGroup()==pTarget->GetGroup()) + return true; + + // Sanctuary + if(pTarget->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_SANCTUARY) && pTester->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_SANCTUARY)) + return true; + + // PvP FFA state + if(pTester->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP) && pTarget->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP)) + return false; + + //= PvP states + // Green/Blue (non-attackable) + if(pTester->GetTeam()==pTarget->GetTeam()) + return true; + + // Blue (friendly/non-attackable) if not PVP, or Yellow/Red in another case (attackable) + return !pTarget->IsPvP(); + } + + // faction base cases + FactionTemplateEntry const*tester_faction = tester->getFactionTemplateEntry(); + FactionTemplateEntry const*target_faction = target->getFactionTemplateEntry(); + if(!tester_faction || !target_faction) + return false; + + if(target->isAttackingPlayer() && tester->IsContestedGuard()) + return false; + + // PvC forced reaction and reputation case + if(tester->GetTypeId()==TYPEID_PLAYER) + { + // forced reaction + ForcedReactions::const_iterator forceItr = ((Player const*)tester)->m_forcedReactions.find(target_faction->faction); + if(forceItr!=((Player const*)tester)->m_forcedReactions.end()) + return forceItr->second >= REP_FRIENDLY; + + // if faction have reputation then friendly state for tester at 100% dependent from at_war state + if(FactionEntry const* raw_target_faction = sFactionStore.LookupEntry(target_faction->faction)) + if(raw_target_faction->reputationListID >=0) + if(FactionState const* FactionState = ((Player*)tester)->GetFactionState(raw_target_faction)) + return !(FactionState->Flags & FACTION_FLAG_AT_WAR); + } + // CvP forced reaction and reputation case + else if(target->GetTypeId()==TYPEID_PLAYER) + { + // forced reaction + ForcedReactions::const_iterator forceItr = ((Player const*)target)->m_forcedReactions.find(tester_faction->faction); + if(forceItr!=((Player const*)target)->m_forcedReactions.end()) + return forceItr->second >= REP_FRIENDLY; + + // apply reputation state + if(FactionEntry const* raw_tester_faction = sFactionStore.LookupEntry(tester_faction->faction)) + if(raw_tester_faction->reputationListID >=0 ) + return ((Player const*)target)->GetReputationRank(raw_tester_faction) >= REP_FRIENDLY; + } + + // common faction based case (CvC,PvC,CvP) + return tester_faction->IsFriendlyTo(*target_faction); +} + +bool Unit::IsHostileToPlayers() const +{ + FactionTemplateEntry const* my_faction = getFactionTemplateEntry(); + if(!my_faction) + return false; + + FactionEntry const* raw_faction = sFactionStore.LookupEntry(my_faction->faction); + if(raw_faction && raw_faction->reputationListID >=0 ) + return false; + + return my_faction->IsHostileToPlayers(); +} + +bool Unit::IsNeutralToAll() const +{ + FactionTemplateEntry const* my_faction = getFactionTemplateEntry(); + if(!my_faction) + return true; + + FactionEntry const* raw_faction = sFactionStore.LookupEntry(my_faction->faction); + if(raw_faction && raw_faction->reputationListID >=0 ) + return false; + + return my_faction->IsNeutralToAll(); +} + +bool Unit::Attack(Unit *victim, bool meleeAttack) +{ + if(!victim || victim == this) + return false; + + // dead units can neither attack nor be attacked + if(!isAlive() || !victim->isAlive()) + return false; + + // player cannot attack in mount state + if(GetTypeId()==TYPEID_PLAYER && IsMounted()) + return false; + + // nobody can attack GM in GM-mode + if(victim->GetTypeId()==TYPEID_PLAYER) + { + if(((Player*)victim)->isGameMaster()) + return false; + } + else + { + if(((Creature*)victim)->IsInEvadeMode()) + return false; + } + + // remove SPELL_AURA_MOD_UNATTACKABLE at attack (in case non-interruptible spells stun aura applied also that not let attack) + if(HasAuraType(SPELL_AURA_MOD_UNATTACKABLE)) + RemoveSpellsCausingAura(SPELL_AURA_MOD_UNATTACKABLE); + + if (m_attacking) + { + if (m_attacking == victim) + { + // switch to melee attack from ranged/magic + if( meleeAttack && !hasUnitState(UNIT_STAT_MELEE_ATTACKING) ) + { + addUnitState(UNIT_STAT_MELEE_ATTACKING); + SendAttackStart(victim); + return true; + } + return false; + } + AttackStop(); + } + + //Set our target + SetUInt64Value(UNIT_FIELD_TARGET, victim->GetGUID()); + + if(meleeAttack) + addUnitState(UNIT_STAT_MELEE_ATTACKING); + m_attacking = victim; + m_attacking->_addAttacker(this); + + if(m_attacking->GetTypeId()==TYPEID_UNIT && ((Creature*)m_attacking)->AI()) + ((Creature*)m_attacking)->AI()->AttackedBy(this); + + if(GetTypeId()==TYPEID_UNIT) + { + WorldPacket data(SMSG_AI_REACTION, 12); + data << GetGUID(); + data << uint32(AI_REACTION_AGGRO); // Aggro sound + ((WorldObject*)this)->SendMessageToSet(&data, true); + + ((Creature*)this)->CallAssistence(); + ((Creature*)this)->SetCombatStartPosition(GetPositionX(), GetPositionY(), GetPositionZ()); + } + + // delay offhand weapon attack to next attack time + if(haveOffhandWeapon()) + resetAttackTimer(OFF_ATTACK); + + if(meleeAttack) + SendAttackStart(victim); + + return true; +} + +bool Unit::AttackStop() +{ + if (!m_attacking) + return false; + + Unit* victim = m_attacking; + + m_attacking->_removeAttacker(this); + m_attacking = NULL; + + //Clear our target + SetUInt64Value(UNIT_FIELD_TARGET, 0); + + clearUnitState(UNIT_STAT_MELEE_ATTACKING); + + InterruptSpell(CURRENT_MELEE_SPELL); + + if( GetTypeId()==TYPEID_UNIT ) + { + // reset call assistance + ((Creature*)this)->SetNoCallAssistence(false); + } + + SendAttackStop(victim); + + return true; +} + +void Unit::CombatStop(bool cast) +{ + if(cast& IsNonMeleeSpellCasted(false)) + InterruptNonMeleeSpells(false); + + AttackStop(); + RemoveAllAttackers(); + if( GetTypeId()==TYPEID_PLAYER ) + ((Player*)this)->SendAttackSwingCancelAttack(); // melee and ranged forced attack cancel + ClearInCombat(); +} + +void Unit::CombatStopWithPets(bool cast) +{ + CombatStop(cast); + if(Pet* pet = GetPet()) + pet->CombatStop(cast); + if(Unit* charm = GetCharm()) + charm->CombatStop(cast); + if(GetTypeId()==TYPEID_PLAYER) + { + GuardianPetList const& guardians = ((Player*)this)->GetGuardians(); + for(GuardianPetList::const_iterator itr = guardians.begin(); itr != guardians.end(); ++itr) + if(Unit* guardian = Unit::GetUnit(*this,*itr)) + guardian->CombatStop(cast); + } +} + +bool Unit::isAttackingPlayer() const +{ + if(hasUnitState(UNIT_STAT_ATTACK_PLAYER)) + return true; + + Pet* pet = GetPet(); + if(pet && pet->isAttackingPlayer()) + return true; + + Unit* charmed = GetCharm(); + if(charmed && charmed->isAttackingPlayer()) + return true; + + for (int8 i = 0; i < MAX_TOTEM; i++) + { + if(m_TotemSlot[i]) + { + Creature *totem = ObjectAccessor::GetCreature(*this, m_TotemSlot[i]); + if(totem && totem->isAttackingPlayer()) + return true; + } + } + + return false; +} + +void Unit::RemoveAllAttackers() +{ + while (!m_attackers.empty()) + { + AttackerSet::iterator iter = m_attackers.begin(); + if(!(*iter)->AttackStop()) + { + sLog.outError("WORLD: Unit has an attacker that isnt attacking it!"); + m_attackers.erase(iter); + } + } +} + +void Unit::ModifyAuraState(AuraState flag, bool apply) +{ + if (apply) + { + if (!HasFlag(UNIT_FIELD_AURASTATE, 1<<(flag-1))) + { + SetFlag(UNIT_FIELD_AURASTATE, 1<<(flag-1)); + if(GetTypeId() == TYPEID_PLAYER) + { + const PlayerSpellMap& sp_list = ((Player*)this)->GetSpellMap(); + for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr) + { + if(itr->second->state == PLAYERSPELL_REMOVED) continue; + SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first); + if (!spellInfo || !IsPassiveSpell(itr->first)) continue; + if (spellInfo->CasterAuraState == flag) + CastSpell(this, itr->first, true, NULL); + } + } + } + } + else + { + if (HasFlag(UNIT_FIELD_AURASTATE,1<<(flag-1))) + { + RemoveFlag(UNIT_FIELD_AURASTATE, 1<<(flag-1)); + Unit::AuraMap& tAuras = GetAuras(); + for (Unit::AuraMap::iterator itr = tAuras.begin(); itr != tAuras.end();) + { + SpellEntry const* spellProto = (*itr).second->GetSpellProto(); + if (spellProto->CasterAuraState == flag) + { + // exceptions (applied at state but not removed at state change) + // Rampage + if(spellProto->SpellIconID==2006 && spellProto->SpellFamilyName==SPELLFAMILY_WARRIOR && spellProto->SpellFamilyFlags==0x100000) + { + ++itr; + continue; + } + + RemoveAura(itr); + } + else + ++itr; + } + } + } +} + +Unit *Unit::GetOwner() const +{ + uint64 ownerid = GetOwnerGUID(); + if(!ownerid) + return NULL; + return ObjectAccessor::GetUnit(*this, ownerid); +} + +Unit *Unit::GetCharmer() const +{ + if(uint64 charmerid = GetCharmerGUID()) + return ObjectAccessor::GetUnit(*this, charmerid); + return NULL; +} + +Player* Unit::GetCharmerOrOwnerPlayerOrPlayerItself() +{ + uint64 guid = GetCharmerOrOwnerGUID(); + if(IS_PLAYER_GUID(guid)) + return ObjectAccessor::GetPlayer(*this, guid); + + return GetTypeId()==TYPEID_PLAYER ? (Player*)this : NULL; +} + +Pet* Unit::GetPet() const +{ + if(uint64 pet_guid = GetPetGUID()) + { + if(Pet* pet = ObjectAccessor::GetPet(pet_guid)) + return pet; + + sLog.outError("Unit::GetPet: Pet %u not exist.",GUID_LOPART(pet_guid)); + const_cast(this)->SetPet(0); + } + + return NULL; +} + +Unit* Unit::GetCharm() const +{ + if(uint64 charm_guid = GetCharmGUID()) + { + if(Unit* pet = ObjectAccessor::GetUnit(*this, charm_guid)) + return pet; + + sLog.outError("Unit::GetCharm: Charmed creature %u not exist.",GUID_LOPART(charm_guid)); + const_cast(this)->SetCharm(0); + } + + return NULL; +} + +void Unit::SetPet(Pet* pet) +{ + SetUInt64Value(UNIT_FIELD_SUMMON,pet ? pet->GetGUID() : 0); + + // FIXME: hack, speed must be set only at follow + if(pet) + for(int i = 0; i < MAX_MOVE_TYPE; ++i) + pet->SetSpeed(UnitMoveType(i),m_speed_rate[i],true); +} + +void Unit::SetCharm(Unit* charmed) +{ + SetUInt64Value(UNIT_FIELD_CHARM,charmed ? charmed->GetGUID() : 0); +} + +void Unit::UnsummonAllTotems() +{ + for (int8 i = 0; i < MAX_TOTEM; ++i) + { + if(!m_TotemSlot[i]) + continue; + + Creature *OldTotem = ObjectAccessor::GetCreature(*this, m_TotemSlot[i]); + if (OldTotem && OldTotem->isTotem()) + ((Totem*)OldTotem)->UnSummon(); + } +} + +void Unit::SendHealSpellLog(Unit *pVictim, uint32 SpellID, uint32 Damage, bool critical) +{ + // we guess size + WorldPacket data(SMSG_SPELLHEALLOG, (8+8+4+4+1)); + data.append(pVictim->GetPackGUID()); + data.append(GetPackGUID()); + data << uint32(SpellID); + data << uint32(Damage); + data << uint8(critical ? 1 : 0); + data << uint8(0); // unused in client? + SendMessageToSet(&data, true); +} + +void Unit::SendEnergizeSpellLog(Unit *pVictim, uint32 SpellID, uint32 Damage, Powers powertype, bool critical) +{ + WorldPacket data(SMSG_SPELLENERGIZELOG, (8+8+4+4+4+1)); + data.append(pVictim->GetPackGUID()); + data.append(GetPackGUID()); + data << uint32(SpellID); + data << uint32(powertype); + data << uint32(Damage); + //data << uint8(critical ? 1 : 0); // removed in 2.4.0 + SendMessageToSet(&data, true); +} + +uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint32 pdamage, DamageEffectType damagetype) +{ + if(!spellProto || !pVictim || damagetype==DIRECT_DAMAGE ) + return pdamage; + + int32 BonusDamage = 0; + if( GetTypeId()==TYPEID_UNIT ) + { + // Pets just add their bonus damage to their spell damage + // note that their spell damage is just gain of their own auras + if (((Creature*)this)->isPet()) + { + BonusDamage = ((Pet*)this)->GetBonusDamage(); + } + // For totems get damage bonus from owner (statue isn't totem in fact) + else if (((Creature*)this)->isTotem() && ((Totem*)this)->GetTotemType()!=TOTEM_STATUE) + { + if(Unit* owner = GetOwner()) + return owner->SpellDamageBonus(pVictim, spellProto, pdamage, damagetype); + } + } + + // Damage Done + uint32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto); + + // Taken/Done fixed damage bonus auras + int32 DoneAdvertisedBenefit = SpellBaseDamageBonus(GetSpellSchoolMask(spellProto))+BonusDamage; + int32 TakenAdvertisedBenefit = SpellBaseDamageBonusForVictim(GetSpellSchoolMask(spellProto), pVictim); + + // Damage over Time spells bonus calculation + float DotFactor = 1.0f; + if(damagetype == DOT) + { + int32 DotDuration = GetSpellDuration(spellProto); + // 200% limit + if(DotDuration > 0) + { + if(DotDuration > 30000) DotDuration = 30000; + if(!IsChanneledSpell(spellProto)) DotFactor = DotDuration / 15000.0f; + int x = 0; + for(int j = 0; j < 3; j++) + { + if( spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && ( + spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_DAMAGE || + spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH) ) + { + x = j; + break; + } + } + int DotTicks = 6; + if(spellProto->EffectAmplitude[x] != 0) + DotTicks = DotDuration / spellProto->EffectAmplitude[x]; + if(DotTicks) + { + DoneAdvertisedBenefit /= DotTicks; + TakenAdvertisedBenefit /= DotTicks; + } + } + } + + // Taken/Done total percent damage auras + float DoneTotalMod = 1.0f; + float TakenTotalMod = 1.0f; + + // ..done + AuraList const& mModDamagePercentDone = GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); + for(AuraList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i) + { + if( ((*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellProto)) && + (*i)->GetSpellProto()->EquippedItemClass == -1 && + // -1 == any item class (not wand then) + (*i)->GetSpellProto()->EquippedItemInventoryTypeMask == 0 ) + // 0 == any inventory type (not wand then) + { + DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; + } + } + + uint32 creatureTypeMask = pVictim->GetCreatureTypeMask(); + AuraList const& mDamageDoneVersus = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE_VERSUS); + for(AuraList::const_iterator i = mDamageDoneVersus.begin();i != mDamageDoneVersus.end(); ++i) + if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue)) + DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; + + // ..taken + AuraList const& mModDamagePercentTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN); + for(AuraList::const_iterator i = mModDamagePercentTaken.begin(); i != mModDamagePercentTaken.end(); ++i) + if( (*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellProto) ) + TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; + + // .. taken pct: scripted (increases damage of * against targets *) + AuraList const& mOverrideClassScript = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + for(AuraList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i) + { + switch((*i)->GetModifier()->m_miscvalue) + { + //Molten Fury + case 4920: case 4919: + if(pVictim->HasAuraState(AURA_STATE_HEALTHLESS_20_PERCENT)) + TakenTotalMod *= (100.0f+(*i)->GetModifier()->m_amount)/100.0f; break; + } + } + // .. taken pct: dummy auras + AuraList const& mDummyAuras = pVictim->GetAurasByType(SPELL_AURA_DUMMY); + for(AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i) + { + switch((*i)->GetSpellProto()->SpellIconID) + { + //Cheat Death + case 2109: + if( ((*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellProto)) ) + { + if(pVictim->GetTypeId() != TYPEID_PLAYER) + continue; + float mod = -((Player*)pVictim)->GetRatingBonusValue(CR_CRIT_TAKEN_SPELL)*2*4; + if (mod < (*i)->GetModifier()->m_amount) + mod = (*i)->GetModifier()->m_amount; + TakenTotalMod *= (mod+100.0f)/100.0f; + } + break; + //Mangle + case 2312: + for(int j=0;j<3;j++) + { + if(GetEffectMechanic(spellProto, j)==MECHANIC_BLEED) + { + TakenTotalMod *= (100.0f+(*i)->GetModifier()->m_amount)/100.0f; + break; + } + } + break; + } + } + + // Distribute Damage over multiple effects, reduce by AoE + CastingTime = GetCastingTimeForBonus( spellProto, damagetype, CastingTime ); + + // 50% for damage and healing spells for leech spells from damage bonus and 0% from healing + for(int j = 0; j < 3; ++j) + { + if( spellProto->Effect[j] == SPELL_EFFECT_HEALTH_LEECH || + spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH ) + { + CastingTime /= 2; + break; + } + } + + switch(spellProto->SpellFamilyName) + { + case SPELLFAMILY_MAGE: + // Ignite - do not modify, it is (8*Rank)% damage of procing Spell + if(spellProto->Id==12654) + { + return pdamage; + } + // Ice Lance + else if((spellProto->SpellFamilyFlags & 0x20000LL) && spellProto->SpellIconID == 186) + { + CastingTime /= 3; // applied 1/3 bonuses in case generic target + if(pVictim->isFrozen()) // and compensate this for frozen target. + TakenTotalMod *= 3.0f; + } + // Pyroblast - 115% of Fire Damage, DoT - 20% of Fire Damage + else if((spellProto->SpellFamilyFlags & 0x400000LL) && spellProto->SpellIconID == 184 ) + { + DotFactor = damagetype == DOT ? 0.2f : 1.0f; + CastingTime = damagetype == DOT ? 3500 : 4025; + } + // Fireball - 100% of Fire Damage, DoT - 0% of Fire Damage + else if((spellProto->SpellFamilyFlags & 0x1LL) && spellProto->SpellIconID == 185) + { + CastingTime = 3500; + DotFactor = damagetype == DOT ? 0.0f : 1.0f; + } + // Molten armor + else if (spellProto->SpellFamilyFlags & 0x0000000800000000LL) + { + CastingTime = 0; + } + // Arcane Missiles triggered spell + else if ((spellProto->SpellFamilyFlags & 0x200000LL) && spellProto->SpellIconID == 225) + { + CastingTime = 1000; + } + // Blizzard triggered spell + else if ((spellProto->SpellFamilyFlags & 0x80080LL) && spellProto->SpellIconID == 285) + { + CastingTime = 500; + } + break; + case SPELLFAMILY_WARLOCK: + // Life Tap + if((spellProto->SpellFamilyFlags & 0x40000LL) && spellProto->SpellIconID == 208) + { + CastingTime = 2800; // 80% from +shadow damage + DoneTotalMod = 1.0f; + TakenTotalMod = 1.0f; + } + // Dark Pact + else if((spellProto->SpellFamilyFlags & 0x80000000LL) && spellProto->SpellIconID == 154 && GetPetGUID()) + { + CastingTime = 3360; // 96% from +shadow damage + DoneTotalMod = 1.0f; + TakenTotalMod = 1.0f; + } + // Soul Fire - 115% of Fire Damage + else if((spellProto->SpellFamilyFlags & 0x8000000000LL) && spellProto->SpellIconID == 184) + { + CastingTime = 4025; + } + // Curse of Agony - 120% of Shadow Damage + else if((spellProto->SpellFamilyFlags & 0x0000000400LL) && spellProto->SpellIconID == 544) + { + DotFactor = 1.2f; + } + // Drain Mana - 0% of Shadow Damage + else if((spellProto->SpellFamilyFlags & 0x10LL) && spellProto->SpellIconID == 548) + { + CastingTime = 0; + } + // Drain Soul 214.3% + else if ((spellProto->SpellFamilyFlags & 0x4000LL) && spellProto->SpellIconID == 113 ) + { + CastingTime = 7500; + } + // Hellfire + else if ((spellProto->SpellFamilyFlags & 0x40LL) && spellProto->SpellIconID == 937) + { + CastingTime = damagetype == DOT ? 5000 : 500; // self damage seems to be so + } + // Unstable Affliction - 180% + else if (spellProto->Id == 31117 && spellProto->SpellIconID == 232) + { + CastingTime = 6300; + } + // Corruption 93% + else if ((spellProto->SpellFamilyFlags & 0x2LL) && spellProto->SpellIconID == 313) + { + DotFactor = 0.93f; + } + break; + case SPELLFAMILY_PALADIN: + // Consecration - 95% of Holy Damage + if((spellProto->SpellFamilyFlags & 0x20LL) && spellProto->SpellIconID == 51) + { + DotFactor = 0.95f; + CastingTime = 3500; + } + // Seal of Righteousness - 10.2%/9.8% ( based on weapon type ) of Holy Damage, multiplied by weapon speed + else if((spellProto->SpellFamilyFlags & 0x8000000LL) && spellProto->SpellIconID == 25) + { + Item *item = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND); + float wspeed = GetAttackTime(BASE_ATTACK)/1000.0f; + + if( item && item->GetProto()->InventoryType == INVTYPE_2HWEAPON) + CastingTime = uint32(wspeed*3500*0.102f); + else + CastingTime = uint32(wspeed*3500*0.098f); + } + // Judgement of Righteousness - 73% + else if ((spellProto->SpellFamilyFlags & 1024) && spellProto->SpellIconID == 25) + { + CastingTime = 2555; + } + // Seal of Vengeance - 17% per Fully Stacked Tick - 5 Applications + else if ((spellProto->SpellFamilyFlags & 0x80000000000LL) && spellProto->SpellIconID == 2292) + { + DotFactor = 0.17f; + CastingTime = 3500; + } + // Holy shield - 5% of Holy Damage + else if ((spellProto->SpellFamilyFlags & 0x4000000000LL) && spellProto->SpellIconID == 453) + { + CastingTime = 175; + } + // Blessing of Sanctuary - 0% + else if ((spellProto->SpellFamilyFlags & 0x10000000LL) && spellProto->SpellIconID == 29) + { + CastingTime = 0; + } + // Seal of Righteousness trigger - already computed for parent spell + else if ( spellProto->SpellFamilyName==SPELLFAMILY_PALADIN && spellProto->SpellIconID==25 && spellProto->AttributesEx4 & 0x00800000LL ) + { + return pdamage; + } + break; + case SPELLFAMILY_SHAMAN: + // totem attack + if (spellProto->SpellFamilyFlags & 0x000040000000LL) + { + if (spellProto->SpellIconID == 33) // Fire Nova totem attack must be 21.4%(untested) + CastingTime = 749; // ignore CastingTime and use as modifier + else if (spellProto->SpellIconID == 680) // Searing Totem attack 8% + CastingTime = 280; // ignore CastingTime and use as modifier + else if (spellProto->SpellIconID == 37) // Magma totem attack must be 6.67%(untested) + CastingTime = 234; // ignore CastingTimePenalty and use as modifier + } + // Lightning Shield (and proc shield from T2 8 pieces bonus ) 33% per charge + else if( (spellProto->SpellFamilyFlags & 0x00000000400LL) || spellProto->Id == 23552) + CastingTime = 1155; // ignore CastingTimePenalty and use as modifier + break; + case SPELLFAMILY_PRIEST: + // Mana Burn - 0% of Shadow Damage + if((spellProto->SpellFamilyFlags & 0x10LL) && spellProto->SpellIconID == 212) + { + CastingTime = 0; + } + // Mind Flay - 59% of Shadow Damage + else if((spellProto->SpellFamilyFlags & 0x800000LL) && spellProto->SpellIconID == 548) + { + CastingTime = 2065; + } + // Holy Fire - 86.71%, DoT - 16.5% + else if ((spellProto->SpellFamilyFlags & 0x100000LL) && spellProto->SpellIconID == 156) + { + DotFactor = damagetype == DOT ? 0.165f : 1.0f; + CastingTime = damagetype == DOT ? 3500 : 3035; + } + // Shadowguard - 28% per charge + else if ((spellProto->SpellFamilyFlags & 0x2000000LL) && spellProto->SpellIconID == 19) + { + CastingTime = 980; + } + // Touch of Weakeness - 10% + else if ((spellProto->SpellFamilyFlags & 0x80000LL) && spellProto->SpellIconID == 1591) + { + CastingTime = 350; + } + // Reflective Shield (back damage) - 0% (other spells fit to check not have damage effects/auras) + else if (spellProto->SpellFamilyFlags == 0 && spellProto->SpellIconID == 566) + { + CastingTime = 0; + } + // Holy Nova - 14% + else if ((spellProto->SpellFamilyFlags & 0x400000LL) && spellProto->SpellIconID == 1874) + { + CastingTime = 500; + } + break; + case SPELLFAMILY_DRUID: + // Hurricane triggered spell + if((spellProto->SpellFamilyFlags & 0x400000LL) && spellProto->SpellIconID == 220) + { + CastingTime = 500; + } + break; + case SPELLFAMILY_WARRIOR: + case SPELLFAMILY_HUNTER: + case SPELLFAMILY_ROGUE: + CastingTime = 0; + break; + default: + break; + } + + float LvlPenalty = CalculateLevelPenalty(spellProto); + + // Spellmod SpellDamage + float SpellModSpellDamage = 100.0f; + + if(Player* modOwner = GetSpellModOwner()) + modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_SPELL_BONUS_DAMAGE,SpellModSpellDamage); + + SpellModSpellDamage /= 100.0f; + + float DoneActualBenefit = DoneAdvertisedBenefit * (CastingTime / 3500.0f) * DotFactor * SpellModSpellDamage * LvlPenalty; + float TakenActualBenefit = TakenAdvertisedBenefit * (CastingTime / 3500.0f) * DotFactor * LvlPenalty; + + float tmpDamage = (float(pdamage)+DoneActualBenefit)*DoneTotalMod; + + // Add flat bonus from spell damage versus + tmpDamage += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS, creatureTypeMask); + + // apply spellmod to Done damage + if(Player* modOwner = GetSpellModOwner()) + modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, tmpDamage); + + tmpDamage = (tmpDamage+TakenActualBenefit)*TakenTotalMod; + + if( GetTypeId() == TYPEID_UNIT && !((Creature*)this)->isPet() ) + tmpDamage *= ((Creature*)this)->GetSpellDamageMod(((Creature*)this)->GetCreatureInfo()->rank); + + return tmpDamage > 0 ? uint32(tmpDamage) : 0; +} + +int32 Unit::SpellBaseDamageBonus(SpellSchoolMask schoolMask) +{ + int32 DoneAdvertisedBenefit = 0; + + // ..done + AuraList const& mDamageDone = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE); + for(AuraList::const_iterator i = mDamageDone.begin();i != mDamageDone.end(); ++i) + if(((*i)->GetModifier()->m_miscvalue & schoolMask) != 0 && + (*i)->GetSpellProto()->EquippedItemClass == -1 && + // -1 == any item class (not wand then) + (*i)->GetSpellProto()->EquippedItemInventoryTypeMask == 0 ) + // 0 == any inventory type (not wand then) + DoneAdvertisedBenefit += (*i)->GetModifier()->m_amount; + + if (GetTypeId() == TYPEID_PLAYER) + { + // Damage bonus from stats + AuraList const& mDamageDoneOfStatPercent = GetAurasByType(SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT); + for(AuraList::const_iterator i = mDamageDoneOfStatPercent.begin();i != mDamageDoneOfStatPercent.end(); ++i) + { + if((*i)->GetModifier()->m_miscvalue & schoolMask) + { + SpellEntry const* iSpellProto = (*i)->GetSpellProto(); + uint8 eff = (*i)->GetEffIndex(); + + // stat used dependent from next effect aura SPELL_AURA_MOD_SPELL_HEALING presence and misc value (stat index) + Stats usedStat = STAT_INTELLECT; + if(eff < 2 && iSpellProto->EffectApplyAuraName[eff+1]==SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT) + usedStat = Stats(iSpellProto->EffectMiscValue[eff+1]); + + DoneAdvertisedBenefit += int32(GetStat(usedStat) * (*i)->GetModifier()->m_amount / 100.0f); + } + } + // ... and attack power + AuraList const& mDamageDonebyAP = GetAurasByType(SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER); + for(AuraList::const_iterator i =mDamageDonebyAP.begin();i != mDamageDonebyAP.end(); ++i) + if ((*i)->GetModifier()->m_miscvalue & schoolMask) + DoneAdvertisedBenefit += int32(GetTotalAttackPowerValue(BASE_ATTACK) * (*i)->GetModifier()->m_amount / 100.0f); + + } + return DoneAdvertisedBenefit; +} + +int32 Unit::SpellBaseDamageBonusForVictim(SpellSchoolMask schoolMask, Unit *pVictim) +{ + uint32 creatureTypeMask = pVictim->GetCreatureTypeMask(); + + int32 TakenAdvertisedBenefit = 0; + // ..done (for creature type by mask) in taken + AuraList const& mDamageDoneCreature = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE_CREATURE); + for(AuraList::const_iterator i = mDamageDoneCreature.begin();i != mDamageDoneCreature.end(); ++i) + if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue)) + TakenAdvertisedBenefit += (*i)->GetModifier()->m_amount; + + // ..taken + AuraList const& mDamageTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_TAKEN); + for(AuraList::const_iterator i = mDamageTaken.begin();i != mDamageTaken.end(); ++i) + if(((*i)->GetModifier()->m_miscvalue & schoolMask) != 0) + TakenAdvertisedBenefit += (*i)->GetModifier()->m_amount; + + return TakenAdvertisedBenefit; +} + +bool Unit::isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType) +{ + // not criting spell + if((spellProto->AttributesEx2 & SPELL_ATTR_EX2_CANT_CRIT)) + return false; + + float crit_chance = 0.0f; + switch(spellProto->DmgClass) + { + case SPELL_DAMAGE_CLASS_NONE: + return false; + case SPELL_DAMAGE_CLASS_MAGIC: + { + if (schoolMask & SPELL_SCHOOL_MASK_NORMAL) + crit_chance = 0.0f; + // For other schools + else if (GetTypeId() == TYPEID_PLAYER) + crit_chance = GetFloatValue( PLAYER_SPELL_CRIT_PERCENTAGE1 + GetFirstSchoolInMask(schoolMask)); + else + { + crit_chance = m_baseSpellCritChance; + crit_chance += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL, schoolMask); + } + // taken + if (pVictim && !IsPositiveSpell(spellProto->Id)) + { + // Modify critical chance by victim SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE + crit_chance += pVictim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE, schoolMask); + // Modify critical chance by victim SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE + crit_chance += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE); + // Modify by player victim resilience + if (pVictim->GetTypeId() == TYPEID_PLAYER) + crit_chance -= ((Player*)pVictim)->GetRatingBonusValue(CR_CRIT_TAKEN_SPELL); + // scripted (increase crit chance ... against ... target by x% + if(pVictim->isFrozen()) // Shatter + { + AuraList const& mOverrideClassScript = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + for(AuraList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i) + { + switch((*i)->GetModifier()->m_miscvalue) + { + case 849: crit_chance+= 10.0f; break; //Shatter Rank 1 + case 910: crit_chance+= 20.0f; break; //Shatter Rank 2 + case 911: crit_chance+= 30.0f; break; //Shatter Rank 3 + case 912: crit_chance+= 40.0f; break; //Shatter Rank 4 + case 913: crit_chance+= 50.0f; break; //Shatter Rank 5 + } + } + } + } + break; + } + case SPELL_DAMAGE_CLASS_MELEE: + case SPELL_DAMAGE_CLASS_RANGED: + { + if (pVictim) + { + crit_chance = GetUnitCriticalChance(attackType, pVictim); + crit_chance+= (int32(GetMaxSkillValueForLevel(pVictim)) - int32(pVictim->GetDefenseSkillValue(this))) * 0.04f; + crit_chance+= GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL, schoolMask); + } + break; + } + default: + return false; + } + // percent done + // only players use intelligence for critical chance computations + if(Player* modOwner = GetSpellModOwner()) + modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_CRITICAL_CHANCE, crit_chance); + + crit_chance = crit_chance > 0.0f ? crit_chance : 0.0f; + if (roll_chance_f(crit_chance)) + return true; + return false; +} + +uint32 Unit::SpellCriticalBonus(SpellEntry const *spellProto, uint32 damage, Unit *pVictim) +{ + // Calculate critical bonus + int32 crit_bonus; + switch(spellProto->DmgClass) + { + case SPELL_DAMAGE_CLASS_MELEE: // for melee based spells is 100% + case SPELL_DAMAGE_CLASS_RANGED: + // TODO: write here full calculation for melee/ranged spells + crit_bonus = damage; + break; + default: + crit_bonus = damage / 2; // for spells is 50% + break; + } + + // adds additional damage to crit_bonus (from talents) + if(Player* modOwner = GetSpellModOwner()) + modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_CRIT_DAMAGE_BONUS, crit_bonus); + + if(pVictim) + { + uint32 creatureTypeMask = pVictim->GetCreatureTypeMask(); + crit_bonus = int32(crit_bonus * GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, creatureTypeMask)); + } + + if(crit_bonus > 0) + damage += crit_bonus; + + return damage; +} + +uint32 Unit::SpellHealingBonus(SpellEntry const *spellProto, uint32 healamount, DamageEffectType damagetype, Unit *pVictim) +{ + // For totems get healing bonus from owner (statue isn't totem in fact) + if( GetTypeId()==TYPEID_UNIT && ((Creature*)this)->isTotem() && ((Totem*)this)->GetTotemType()!=TOTEM_STATUE) + if(Unit* owner = GetOwner()) + return owner->SpellHealingBonus(spellProto, healamount, damagetype, pVictim); + + // Healing Done + + // These Spells are doing fixed amount of healing (TODO found less hack-like check) + if(spellProto->Id == 15290 || spellProto->Id == 39373 || spellProto->Id == 33778 || spellProto->Id == 379 || spellProto->Id == 38395) + return healamount; + + + int32 AdvertisedBenefit = SpellBaseHealingBonus(GetSpellSchoolMask(spellProto)); + uint32 CastingTime = GetSpellCastTime(spellProto); + + // Healing Taken + AdvertisedBenefit += SpellBaseHealingBonusForVictim(GetSpellSchoolMask(spellProto), pVictim); + + // Blessing of Light dummy effects healing taken from Holy Light and Flash of Light + if (spellProto->SpellFamilyName == SPELLFAMILY_PALADIN && (spellProto->SpellFamilyFlags & 0x00000000C0000000LL)) + { + AuraList const& mDummyAuras = pVictim->GetAurasByType(SPELL_AURA_DUMMY); + for(AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i) + { + if((*i)->GetSpellProto()->SpellVisual == 9180) + { + // Flash of Light + if ((spellProto->SpellFamilyFlags & 0x0000000040000000LL) && (*i)->GetEffIndex() == 1) + AdvertisedBenefit += (*i)->GetModifier()->m_amount; + // Holy Light + else if ((spellProto->SpellFamilyFlags & 0x0000000080000000LL) && (*i)->GetEffIndex() == 0) + AdvertisedBenefit += (*i)->GetModifier()->m_amount; + } + } + } + + float ActualBenefit = 0.0f; + + if (AdvertisedBenefit != 0) + { + // Healing over Time spells + float DotFactor = 1.0f; + if(damagetype == DOT) + { + int32 DotDuration = GetSpellDuration(spellProto); + if(DotDuration > 0) + { + // 200% limit + if(DotDuration > 30000) DotDuration = 30000; + if(!IsChanneledSpell(spellProto)) DotFactor = DotDuration / 15000.0f; + int x = 0; + for(int j = 0; j < 3; j++) + { + if( spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && ( + spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_HEAL || + spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH) ) + { + x = j; + break; + } + } + int DotTicks = 6; + if(spellProto->EffectAmplitude[x] != 0) + DotTicks = DotDuration / spellProto->EffectAmplitude[x]; + if(DotTicks) + AdvertisedBenefit /= DotTicks; + } + } + + // distribute healing to all effects, reduce AoE damage + CastingTime = GetCastingTimeForBonus( spellProto, damagetype, CastingTime ); + + // 0% bonus for damage and healing spells for leech spells from healing bonus + for(int j = 0; j < 3; ++j) + { + if( spellProto->Effect[j] == SPELL_EFFECT_HEALTH_LEECH || + spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH ) + { + CastingTime = 0; + break; + } + } + + // Exception + switch (spellProto->SpellFamilyName) + { + case SPELLFAMILY_SHAMAN: + // Healing stream from totem (add 6% per tick from hill bonus owner) + if (spellProto->SpellFamilyFlags & 0x000000002000LL) + CastingTime = 210; + // Earth Shield 30% per charge + else if (spellProto->SpellFamilyFlags & 0x40000000000LL) + CastingTime = 1050; + break; + case SPELLFAMILY_DRUID: + // Lifebloom + if (spellProto->SpellFamilyFlags & 0x1000000000LL) + { + CastingTime = damagetype == DOT ? 3500 : 1200; + DotFactor = damagetype == DOT ? 0.519f : 1.0f; + } + // Tranquility triggered spell + else if (spellProto->SpellFamilyFlags & 0x80LL) + CastingTime = 667; + // Rejuvenation + else if (spellProto->SpellFamilyFlags & 0x10LL) + DotFactor = 0.845f; + // Regrowth + else if (spellProto->SpellFamilyFlags & 0x40LL) + { + DotFactor = damagetype == DOT ? 0.705f : 1.0f; + CastingTime = damagetype == DOT ? 3500 : 1010; + } + break; + case SPELLFAMILY_PRIEST: + // Holy Nova - 14% + if ((spellProto->SpellFamilyFlags & 0x8000000LL) && spellProto->SpellIconID == 1874) + CastingTime = 500; + break; + case SPELLFAMILY_PALADIN: + // Seal and Judgement of Light + if ( spellProto->SpellFamilyFlags & 0x100040000LL ) + CastingTime = 0; + break; + case SPELLFAMILY_WARRIOR: + case SPELLFAMILY_ROGUE: + case SPELLFAMILY_HUNTER: + CastingTime = 0; + break; + } + + float LvlPenalty = CalculateLevelPenalty(spellProto); + + // Spellmod SpellDamage + float SpellModSpellDamage = 100.0f; + + if(Player* modOwner = GetSpellModOwner()) + modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_SPELL_BONUS_DAMAGE,SpellModSpellDamage); + + SpellModSpellDamage /= 100.0f; + + ActualBenefit = (float)AdvertisedBenefit * ((float)CastingTime / 3500.0f) * DotFactor * SpellModSpellDamage * LvlPenalty; + } + + // use float as more appropriate for negative values and percent applying + float heal = healamount + ActualBenefit; + + // TODO: check for ALL/SPELLS type + // Healing done percent + AuraList const& mHealingDonePct = GetAurasByType(SPELL_AURA_MOD_HEALING_DONE_PERCENT); + for(AuraList::const_iterator i = mHealingDonePct.begin();i != mHealingDonePct.end(); ++i) + heal *= (100.0f + (*i)->GetModifier()->m_amount) / 100.0f; + + // apply spellmod to Done amount + if(Player* modOwner = GetSpellModOwner()) + modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, heal); + + // Healing Wave cast + if (spellProto->SpellFamilyName == SPELLFAMILY_SHAMAN && spellProto->SpellFamilyFlags & 0x0000000000000040LL) + { + // Search for Healing Way on Victim (stack up to 3 time) + int32 pctMod = 0; + Unit::AuraList const& auraDummy = pVictim->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr!=auraDummy.end(); ++itr) + if((*itr)->GetId() == 29203) + pctMod += (*itr)->GetModifier()->m_amount; + // Apply bonus + if (pctMod) + heal = heal * (100 + pctMod) / 100; + } + + // Healing taken percent + float minval = pVictim->GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HEALING_PCT); + if(minval) + heal *= (100.0f + minval) / 100.0f; + + float maxval = pVictim->GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HEALING_PCT); + if(maxval) + heal *= (100.0f + maxval) / 100.0f; + + if (heal < 0) heal = 0; + + return uint32(heal); +} + +int32 Unit::SpellBaseHealingBonus(SpellSchoolMask schoolMask) +{ + int32 AdvertisedBenefit = 0; + + AuraList const& mHealingDone = GetAurasByType(SPELL_AURA_MOD_HEALING_DONE); + for(AuraList::const_iterator i = mHealingDone.begin();i != mHealingDone.end(); ++i) + if(((*i)->GetModifier()->m_miscvalue & schoolMask) != 0) + AdvertisedBenefit += (*i)->GetModifier()->m_amount; + + // Healing bonus of spirit, intellect and strength + if (GetTypeId() == TYPEID_PLAYER) + { + // Healing bonus from stats + AuraList const& mHealingDoneOfStatPercent = GetAurasByType(SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT); + for(AuraList::const_iterator i = mHealingDoneOfStatPercent.begin();i != mHealingDoneOfStatPercent.end(); ++i) + { + // stat used dependent from misc value (stat index) + Stats usedStat = Stats((*i)->GetSpellProto()->EffectMiscValue[(*i)->GetEffIndex()]); + AdvertisedBenefit += int32(GetStat(usedStat) * (*i)->GetModifier()->m_amount / 100.0f); + } + + // ... and attack power + AuraList const& mHealingDonebyAP = GetAurasByType(SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER); + for(AuraList::const_iterator i = mHealingDonebyAP.begin();i != mHealingDonebyAP.end(); ++i) + if ((*i)->GetModifier()->m_miscvalue & schoolMask) + AdvertisedBenefit += int32(GetTotalAttackPowerValue(BASE_ATTACK) * (*i)->GetModifier()->m_amount / 100.0f); + } + return AdvertisedBenefit; +} + +int32 Unit::SpellBaseHealingBonusForVictim(SpellSchoolMask schoolMask, Unit *pVictim) +{ + int32 AdvertisedBenefit = 0; + AuraList const& mDamageTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_HEALING); + for(AuraList::const_iterator i = mDamageTaken.begin();i != mDamageTaken.end(); ++i) + if(((*i)->GetModifier()->m_miscvalue & schoolMask) != 0) + AdvertisedBenefit += (*i)->GetModifier()->m_amount; + return AdvertisedBenefit; +} + +bool Unit::IsImmunedToDamage(SpellSchoolMask shoolMask, bool useCharges) +{ + // no charges dependent checks + SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL]; + for (SpellImmuneList::const_iterator itr = schoolList.begin(); itr != schoolList.end(); ++itr) + if(itr->type & shoolMask) + return true; + + // charges dependent checks + SpellImmuneList const& damageList = m_spellImmune[IMMUNITY_DAMAGE]; + for (SpellImmuneList::const_iterator itr = damageList.begin(); itr != damageList.end(); ++itr) + { + if(itr->type & shoolMask) + { + if(useCharges) + { + AuraList const& auraDamageImmunity = GetAurasByType(SPELL_AURA_DAMAGE_IMMUNITY); + for(AuraList::const_iterator auraItr = auraDamageImmunity.begin(); auraItr != auraDamageImmunity.end(); ++auraItr) + { + if((*auraItr)->GetId()==itr->spellId) + { + if((*auraItr)->m_procCharges > 0) + { + --(*auraItr)->m_procCharges; + if((*auraItr)->m_procCharges==0) + RemoveAurasDueToSpell(itr->spellId); + } + break; + } + } + } + return true; + } + } + + return false; +} + +bool Unit::IsImmunedToSpell(SpellEntry const* spellInfo, bool useCharges) +{ + if (!spellInfo) + return false; + + // no charges first + + //FIX ME this hack: don't get feared if stunned + if (spellInfo->Mechanic == MECHANIC_FEAR ) + { + if ( hasUnitState(UNIT_STAT_STUNDED) ) + return true; + } + + // not have spells with charges currently + SpellImmuneList const& dispelList = m_spellImmune[IMMUNITY_DISPEL]; + for(SpellImmuneList::const_iterator itr = dispelList.begin(); itr != dispelList.end(); ++itr) + if(itr->type == spellInfo->Dispel) + return true; + + if( !(spellInfo->AttributesEx & SPELL_ATTR_EX_UNAFFECTED_BY_SCHOOL_IMMUNE)) // unaffected by school immunity + { + // not have spells with charges currently + SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL]; + for(SpellImmuneList::const_iterator itr = schoolList.begin(); itr != schoolList.end(); ++itr) + if( !(IsPositiveSpell(itr->spellId) && IsPositiveSpell(spellInfo->Id)) && + (itr->type & GetSpellSchoolMask(spellInfo)) ) + return true; + } + + // charges dependent checks + + SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC]; + for(SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr) + { + if(itr->type == spellInfo->Mechanic) + { + if(useCharges) + { + AuraList const& auraMechImmunity = GetAurasByType(SPELL_AURA_MECHANIC_IMMUNITY); + for(AuraList::const_iterator auraItr = auraMechImmunity.begin(); auraItr != auraMechImmunity.end(); ++auraItr) + { + if((*auraItr)->GetId()==itr->spellId) + { + if((*auraItr)->m_procCharges > 0) + { + --(*auraItr)->m_procCharges; + if((*auraItr)->m_procCharges==0) + RemoveAurasDueToSpell(itr->spellId); + } + break; + } + } + } + return true; + } + } + + return false; +} + +bool Unit::IsImmunedToSpellEffect(uint32 effect, uint32 mechanic) const +{ + //If m_immuneToEffect type contain this effect type, IMMUNE effect. + SpellImmuneList const& effectList = m_spellImmune[IMMUNITY_EFFECT]; + for (SpellImmuneList::const_iterator itr = effectList.begin(); itr != effectList.end(); ++itr) + if(itr->type == effect) + return true; + + SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC]; + for (SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr) + if(itr->type == mechanic) + return true; + + return false; +} + +bool Unit::IsDamageToThreatSpell(SpellEntry const * spellInfo) const +{ + if(!spellInfo) + return false; + + uint32 family = spellInfo->SpellFamilyName; + uint64 flags = spellInfo->SpellFamilyFlags; + + if((family == 5 && flags == 256) || //Searing Pain + (family == 6 && flags == 8192) || //Mind Blast + (family == 11 && flags == 1048576)) //Earth Shock + return true; + + return false; +} + +void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage,WeaponAttackType attType, SpellEntry const *spellProto) +{ + if(!pVictim) + return; + + if(*pdamage == 0) + return; + + uint32 creatureTypeMask = pVictim->GetCreatureTypeMask(); + + // Taken/Done fixed damage bonus auras + int32 DoneFlatBenefit = 0; + int32 TakenFlatBenefit = 0; + + // ..done (for creature type by mask) in taken + AuraList const& mDamageDoneCreature = this->GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE_CREATURE); + for(AuraList::const_iterator i = mDamageDoneCreature.begin();i != mDamageDoneCreature.end(); ++i) + if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue)) + DoneFlatBenefit += (*i)->GetModifier()->m_amount; + + // ..done + // SPELL_AURA_MOD_DAMAGE_DONE included in weapon damage + + // ..done (base at attack power for marked target and base at attack power for creature type) + int32 APbonus = 0; + if(attType == RANGED_ATTACK) + { + APbonus += pVictim->GetTotalAuraModifier(SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS); + + // ..done (base at attack power and creature type) + AuraList const& mCreatureAttackPower = GetAurasByType(SPELL_AURA_MOD_RANGED_ATTACK_POWER_VERSUS); + for(AuraList::const_iterator i = mCreatureAttackPower.begin();i != mCreatureAttackPower.end(); ++i) + if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue)) + APbonus += (*i)->GetModifier()->m_amount; + } + else + { + APbonus += pVictim->GetTotalAuraModifier(SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS); + + // ..done (base at attack power and creature type) + AuraList const& mCreatureAttackPower = GetAurasByType(SPELL_AURA_MOD_MELEE_ATTACK_POWER_VERSUS); + for(AuraList::const_iterator i = mCreatureAttackPower.begin();i != mCreatureAttackPower.end(); ++i) + if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue)) + APbonus += (*i)->GetModifier()->m_amount; + } + + if (APbonus!=0) // Can be negative + { + bool normalized = false; + if(spellProto) + { + for (uint8 i = 0; i<3;i++) + { + if (spellProto->Effect[i] == SPELL_EFFECT_NORMALIZED_WEAPON_DMG) + { + normalized = true; + break; + } + } + } + + DoneFlatBenefit += int32(APbonus/14.0f * GetAPMultiplier(attType,normalized)); + } + + // ..taken + AuraList const& mDamageTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_TAKEN); + for(AuraList::const_iterator i = mDamageTaken.begin();i != mDamageTaken.end(); ++i) + if((*i)->GetModifier()->m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) + TakenFlatBenefit += (*i)->GetModifier()->m_amount; + + if(attType!=RANGED_ATTACK) + TakenFlatBenefit += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN); + else + TakenFlatBenefit += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN); + + // Done/Taken total percent damage auras + float DoneTotalMod = 1; + float TakenTotalMod = 1; + + // ..done + // SPELL_AURA_MOD_DAMAGE_PERCENT_DONE included in weapon damage + // SPELL_AURA_MOD_OFFHAND_DAMAGE_PCT included in weapon damage + + AuraList const& mDamageDoneVersus = this->GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE_VERSUS); + for(AuraList::const_iterator i = mDamageDoneVersus.begin();i != mDamageDoneVersus.end(); ++i) + if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue)) + DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; + + // ..taken + AuraList const& mModDamagePercentTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN); + for(AuraList::const_iterator i = mModDamagePercentTaken.begin(); i != mModDamagePercentTaken.end(); ++i) + if((*i)->GetModifier()->m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) + TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; + + // .. taken pct: dummy auras + AuraList const& mDummyAuras = pVictim->GetAurasByType(SPELL_AURA_DUMMY); + for(AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i) + { + switch((*i)->GetSpellProto()->SpellIconID) + { + //Cheat Death + case 2109: + if((*i)->GetModifier()->m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) + { + if(pVictim->GetTypeId() != TYPEID_PLAYER) + continue; + float mod = ((Player*)pVictim)->GetRatingBonusValue(CR_CRIT_TAKEN_MELEE)*(-8.0f); + if (mod < (*i)->GetModifier()->m_amount) + mod = (*i)->GetModifier()->m_amount; + TakenTotalMod *= (mod+100.0f)/100.0f; + } + break; + //Mangle + case 2312: + if(spellProto==NULL) + break; + // Should increase Shred (initial Damage of Lacerate and Rake handled in Spell::EffectSchoolDMG) + if(spellProto->SpellFamilyName==SPELLFAMILY_DRUID && (spellProto->SpellFamilyFlags==0x00008000LL)) + TakenTotalMod *= (100.0f+(*i)->GetModifier()->m_amount)/100.0f; + break; + } + } + + // .. taken pct: class scripts + AuraList const& mclassScritAuras = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + for(AuraList::const_iterator i = mclassScritAuras.begin(); i != mclassScritAuras.end(); ++i) + { + switch((*i)->GetMiscValue()) + { + case 6427: case 6428: // Dirty Deeds + if(pVictim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT)) + { + Aura* eff0 = GetAura((*i)->GetId(),0); + if(!eff0 || (*i)->GetEffIndex()!=1) + { + sLog.outError("Spell structure of DD (%u) changed.",(*i)->GetId()); + continue; + } + + // effect 0 have expected value but in negative state + TakenTotalMod *= (-eff0->GetModifier()->m_amount+100.0f)/100.0f; + } + break; + } + } + + if(attType != RANGED_ATTACK) + { + AuraList const& mModMeleeDamageTakenPercent = pVictim->GetAurasByType(SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN_PCT); + for(AuraList::const_iterator i = mModMeleeDamageTakenPercent.begin(); i != mModMeleeDamageTakenPercent.end(); ++i) + TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; + } + else + { + AuraList const& mModRangedDamageTakenPercent = pVictim->GetAurasByType(SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT); + for(AuraList::const_iterator i = mModRangedDamageTakenPercent.begin(); i != mModRangedDamageTakenPercent.end(); ++i) + TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; + } + + float tmpDamage = float(int32(*pdamage) + DoneFlatBenefit) * DoneTotalMod; + + // apply spellmod to Done damage + if(spellProto) + { + if(Player* modOwner = GetSpellModOwner()) + modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_DAMAGE, tmpDamage); + } + + tmpDamage = (tmpDamage + TakenFlatBenefit)*TakenTotalMod; + + // bonus result can be negative + *pdamage = tmpDamage > 0 ? uint32(tmpDamage) : 0; +} + +void Unit::ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply) +{ + if (apply) + { + for (SpellImmuneList::iterator itr = m_spellImmune[op].begin(), next; itr != m_spellImmune[op].end(); itr = next) + { + next = itr; ++next; + if(itr->type == type) + { + m_spellImmune[op].erase(itr); + next = m_spellImmune[op].begin(); + } + } + SpellImmune Immune; + Immune.spellId = spellId; + Immune.type = type; + m_spellImmune[op].push_back(Immune); + } + else + { + for (SpellImmuneList::iterator itr = m_spellImmune[op].begin(); itr != m_spellImmune[op].end(); ++itr) + { + if(itr->spellId == spellId) + { + m_spellImmune[op].erase(itr); + break; + } + } + } + +} + +void Unit::ApplySpellDispelImmunity(const SpellEntry * spellProto, DispelType type, bool apply) +{ + ApplySpellImmune(spellProto->Id,IMMUNITY_DISPEL, type, apply); + + if (apply && spellProto->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY) + RemoveAurasWithDispelType(type); +} + +float Unit::GetWeaponProcChance() const +{ + // normalized proc chance for weapon attack speed + // (odd formulae...) + if(isAttackReady(BASE_ATTACK)) + return (GetAttackTime(BASE_ATTACK) * 1.8f / 1000.0f); + else if (haveOffhandWeapon() && isAttackReady(OFF_ATTACK)) + return (GetAttackTime(OFF_ATTACK) * 1.6f / 1000.0f); + return 0; +} + +float Unit::GetPPMProcChance(uint32 WeaponSpeed, float PPM) const +{ + // proc per minute chance calculation + if (PPM <= 0) return 0.0f; + uint32 result = uint32((WeaponSpeed * PPM) / 600.0f); // result is chance in percents (probability = Speed_in_sec * (PPM / 60)) + return result; +} + +void Unit::Mount(uint32 mount) +{ + if(!mount) + return; + + RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOUNTING); + + SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, mount); + + SetFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNT ); + + // unsummon pet + if(GetTypeId() == TYPEID_PLAYER) + { + Pet* pet = GetPet(); + if(pet) + { + if(pet->isControlled()) + { + ((Player*)this)->SetTemporaryUnsummonedPetNumber(pet->GetCharmInfo()->GetPetNumber()); + ((Player*)this)->SetOldPetSpell(pet->GetUInt32Value(UNIT_CREATED_BY_SPELL)); + } + + ((Player*)this)->RemovePet(NULL,PET_SAVE_NOT_IN_SLOT); + } + else + ((Player*)this)->SetTemporaryUnsummonedPetNumber(0); + } +} + +void Unit::Unmount() +{ + if(!IsMounted()) + return; + + RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_NOT_MOUNTED); + + SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, 0); + RemoveFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNT ); + + // only resummon old pet if the player is already added to a map + // this prevents adding a pet to a not created map which would otherwise cause a crash + // (it could probably happen when logging in after a previous crash) + if(GetTypeId() == TYPEID_PLAYER && IsInWorld() && ((Player*)this)->GetTemporaryUnsummonedPetNumber() && isAlive()) + { + Pet* NewPet = new Pet; + if(!NewPet->LoadPetFromDB(this, 0, ((Player*)this)->GetTemporaryUnsummonedPetNumber(), true)) + delete NewPet; + + ((Player*)this)->SetTemporaryUnsummonedPetNumber(0); + } +} + +void Unit::SetInCombatWith(Unit* enemy) +{ + Unit* eOwner = enemy->GetCharmerOrOwnerOrSelf(); + if(eOwner->IsPvP()) + { + SetInCombatState(true); + return; + } + + //check for duel + if(eOwner->GetTypeId() == TYPEID_PLAYER && ((Player*)eOwner)->duel) + { + Unit const* myOwner = GetCharmerOrOwnerOrSelf(); + if(((Player const*)eOwner)->duel->opponent == myOwner) + { + SetInCombatState(true); + return; + } + } + SetInCombatState(false); +} + +void Unit::SetInCombatState(bool PvP) +{ + // only alive units can be in combat + if(!isAlive()) + return; + + if(PvP) + m_CombatTimer = 5000; + SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); + + if(isCharmed() || (GetTypeId()!=TYPEID_PLAYER && ((Creature*)this)->isPet())) + SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT); +} + +void Unit::ClearInCombat() +{ + m_CombatTimer = 0; + RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); + + if(isCharmed() || (GetTypeId()!=TYPEID_PLAYER && ((Creature*)this)->isPet())) + RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT); + + // Player's state will be cleared in Player::UpdateContestedPvP + if(GetTypeId()!=TYPEID_PLAYER) + clearUnitState(UNIT_STAT_ATTACK_PLAYER); +} + +bool Unit::isTargetableForAttack() const +{ + if (GetTypeId()==TYPEID_PLAYER && ((Player *)this)->isGameMaster()) + return false; + + if(HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE)) + return false; + + return isAlive() && !hasUnitState(UNIT_STAT_DIED)&& !isInFlight() /*&& !isStealth()*/; +} + +int32 Unit::ModifyHealth(int32 dVal) +{ + int32 gain = 0; + + if(dVal==0) + return 0; + + int32 curHealth = (int32)GetHealth(); + + int32 val = dVal + curHealth; + if(val <= 0) + { + SetHealth(0); + return -curHealth; + } + + int32 maxHealth = (int32)GetMaxHealth(); + + if(val < maxHealth) + { + SetHealth(val); + gain = val - curHealth; + } + else if(curHealth != maxHealth) + { + SetHealth(maxHealth); + gain = maxHealth - curHealth; + } + + return gain; +} + +int32 Unit::ModifyPower(Powers power, int32 dVal) +{ + int32 gain = 0; + + if(dVal==0) + return 0; + + int32 curPower = (int32)GetPower(power); + + int32 val = dVal + curPower; + if(val <= 0) + { + SetPower(power,0); + return -curPower; + } + + int32 maxPower = (int32)GetMaxPower(power); + + if(val < maxPower) + { + SetPower(power,val); + gain = val - curPower; + } + else if(curPower != maxPower) + { + SetPower(power,maxPower); + gain = maxPower - curPower; + } + + return gain; +} + +bool Unit::isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList) const +{ + if(!u) + return false; + + // Always can see self + if (u==this) + return true; + + // player visible for other player if not logout and at same transport + // including case when player is out of world + bool at_same_transport = + GetTypeId() == TYPEID_PLAYER && u->GetTypeId()==TYPEID_PLAYER && + !((Player*)this)->GetSession()->PlayerLogout() && !((Player*)u)->GetSession()->PlayerLogout() && + !((Player*)this)->GetSession()->PlayerLoading() && !((Player*)u)->GetSession()->PlayerLoading() && + ((Player*)this)->GetTransport() && ((Player*)this)->GetTransport() == ((Player*)u)->GetTransport(); + + // not in world + if(!at_same_transport && (!IsInWorld() || !u->IsInWorld())) + return false; + + // forbidden to seen (at GM respawn command) + if(m_Visibility==VISIBILITY_RESPAWN) + return false; + + // always seen by owner + if(GetCharmerOrOwnerGUID()==u->GetGUID()) + return true; + + // Grid dead/alive checks + if( u->GetTypeId()==TYPEID_PLAYER) + { + // non visible at grid for any stealth state + if(!IsVisibleInGridForPlayer((Player *)u)) + return false; + + // if player is dead then he can't detect anyone in anycases + if(!u->isAlive()) + detect = false; + } + else + { + // all dead creatures/players not visible for any creatures + if(!u->isAlive() || !isAlive()) + return false; + } + + // different visible distance checks + if(u->isInFlight()) // what see player in flight + { + // use object grey distance for all (only see objects any way) + if (!IsWithinDistInMap(u,World::GetMaxVisibleDistanceInFlight()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f))) + return false; + } + else if(!isAlive()) // distance for show body + { + if (!IsWithinDistInMap(u,World::GetMaxVisibleDistanceForObject()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f))) + return false; + } + else if(GetTypeId()==TYPEID_PLAYER) // distance for show player + { + if(u->GetTypeId()==TYPEID_PLAYER) + { + // Players far than max visible distance for player or not in our map are not visible too + if (!at_same_transport && !IsWithinDistInMap(u,World::GetMaxVisibleDistanceForPlayer()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f))) + return false; + } + else + { + // Units far than max visible distance for creature or not in our map are not visible too + if (!IsWithinDistInMap(u,World::GetMaxVisibleDistanceForCreature()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f))) + return false; + } + } + else if(GetCharmerOrOwnerGUID()) // distance for show pet/charmed + { + // Pet/charmed far than max visible distance for player or not in our map are not visible too + if (!IsWithinDistInMap(u,World::GetMaxVisibleDistanceForPlayer()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f))) + return false; + } + else // distance for show creature + { + // Units far than max visible distance for creature or not in our map are not visible too + if (!IsWithinDistInMap(u,World::GetMaxVisibleDistanceForCreature()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f))) + return false; + } + + // Visible units, always are visible for all units, except for units under invisibility + if (m_Visibility == VISIBILITY_ON && u->m_invisibilityMask==0) + return true; + + // GMs see any players, not higher GMs and all units + if (u->GetTypeId() == TYPEID_PLAYER && ((Player *)u)->isGameMaster()) + { + if(GetTypeId() == TYPEID_PLAYER) + return ((Player *)this)->GetSession()->GetSecurity() <= ((Player *)u)->GetSession()->GetSecurity(); + else + return true; + } + + // non faction visibility non-breakable for non-GMs + if (m_Visibility == VISIBILITY_OFF) + return false; + + // raw invisibility + bool invisible = (m_invisibilityMask != 0 || u->m_invisibilityMask !=0); + + // detectable invisibility case + if( invisible && ( + // Invisible units, always are visible for units under same invisibility type + (m_invisibilityMask & u->m_invisibilityMask)!=0 || + // Invisible units, always are visible for unit that can detect this invisibility (have appropriate level for detect) + u->canDetectInvisibilityOf(this) || + // Units that can detect invisibility always are visible for units that can be detected + canDetectInvisibilityOf(u) )) + { + invisible = false; + } + + // special cases for always overwrite invisibility/stealth + if(invisible || m_Visibility == VISIBILITY_GROUP_STEALTH) + { + // non-hostile case + if (!u->IsHostileTo(this)) + { + // player see other player with stealth/invisibility only if he in same group or raid or same team (raid/team case dependent from conf setting) + if(GetTypeId()==TYPEID_PLAYER && u->GetTypeId()==TYPEID_PLAYER) + { + if(((Player*)this)->IsGroupVisibleFor(((Player*)u))) + return true; + + // else apply same rules as for hostile case (detecting check for stealth) + } + } + // hostile case + else + { + // Hunter mark functionality + AuraList const& auras = GetAurasByType(SPELL_AURA_MOD_STALKED); + for(AuraList::const_iterator iter = auras.begin(); iter != auras.end(); ++iter) + if((*iter)->GetCasterGUID()==u->GetGUID()) + return true; + + // else apply detecting check for stealth + } + + // none other cases for detect invisibility, so invisible + if(invisible) + return false; + + // else apply stealth detecting check + } + + // unit got in stealth in this moment and must ignore old detected state + if (m_Visibility == VISIBILITY_GROUP_NO_DETECT) + return false; + + // GM invisibility checks early, invisibility if any detectable, so if not stealth then visible + if (m_Visibility != VISIBILITY_GROUP_STEALTH) + return true; + + // NOW ONLY STEALTH CASE + + // stealth and detected and visible for some seconds + if (u->GetTypeId() == TYPEID_PLAYER && ((Player*)u)->m_DetectInvTimer > 300 && ((Player*)u)->HaveAtClient(this)) + return true; + + //if in non-detect mode then invisible for unit + if (!detect) + return false; + + // Special cases + + // If is attacked then stealth is lost, some creature can use stealth too + if( !getAttackers().empty() ) + return true; + + // If there is collision rogue is seen regardless of level difference + // TODO: check sizes in DB + float distance = GetDistance(u); + if (distance < 0.24f) + return true; + + //If a mob or player is stunned he will not be able to detect stealth + if (u->hasUnitState(UNIT_STAT_STUNDED) && (u != this)) + return false; + + // Creature can detect target only in aggro radius + if(u->GetTypeId() != TYPEID_PLAYER) + { + //Always invisible from back and out of aggro range + bool isInFront = u->isInFront(this,((Creature const*)u)->GetAttackDistance(this)); + if(!isInFront) + return false; + } + else + { + //Always invisible from back + bool isInFront = u->isInFront(this,(GetTypeId()==TYPEID_PLAYER || GetCharmerOrOwnerGUID()) ? World::GetMaxVisibleDistanceForPlayer() : World::GetMaxVisibleDistanceForCreature()); + if(!isInFront) + return false; + } + + // if doesn't have stealth detection (Shadow Sight), then check how stealthy the unit is, otherwise just check los + if(!u->HasAuraType(SPELL_AURA_DETECT_STEALTH)) + { + //Calculation if target is in front + + //Visible distance based on stealth value (stealth rank 4 300MOD, 10.5 - 3 = 7.5) + float visibleDistance = 10.5f - (GetTotalAuraModifier(SPELL_AURA_MOD_STEALTH)/100.0f); + + //Visible distance is modified by + //-Level Diff (every level diff = 1.0f in visible distance) + visibleDistance += int32(u->getLevelForTarget(this)) - int32(this->getLevelForTarget(u)); + + //This allows to check talent tree and will add addition stealth dependent on used points) + int32 stealthMod = GetTotalAuraModifier(SPELL_AURA_MOD_STEALTH_LEVEL); + if(stealthMod < 0) + stealthMod = 0; + + //-Stealth Mod(positive like Master of Deception) and Stealth Detection(negative like paranoia) + //based on wowwiki every 5 mod we have 1 more level diff in calculation + visibleDistance += (int32(u->GetTotalAuraModifier(SPELL_AURA_MOD_DETECT)) - stealthMod)/5.0f; + + if(distance > visibleDistance) + return false; + } + + // Now check is target visible with LoS + float ox,oy,oz; + u->GetPosition(ox,oy,oz); + return IsWithinLOS(ox,oy,oz); +} + +void Unit::SetVisibility(UnitVisibility x) +{ + m_Visibility = x; + + if(IsInWorld()) + { + Map *m = MapManager::Instance().GetMap(GetMapId(), this); + + if(GetTypeId()==TYPEID_PLAYER) + m->PlayerRelocation((Player*)this,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation()); + else + m->CreatureRelocation((Creature*)this,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation()); + } +} + +bool Unit::canDetectInvisibilityOf(Unit const* u) const +{ + if(uint32 mask = (m_detectInvisibilityMask & u->m_invisibilityMask)) + { + for(uint32 i = 0; i < 10; ++i) + { + if(((1 << i) & mask)==0) + continue; + + // find invisibility level + uint32 invLevel = 0; + Unit::AuraList const& iAuras = u->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY); + for(Unit::AuraList::const_iterator itr = iAuras.begin(); itr != iAuras.end(); ++itr) + if(((*itr)->GetModifier()->m_miscvalue)==i && invLevel < (*itr)->GetModifier()->m_amount) + invLevel = (*itr)->GetModifier()->m_amount; + + // find invisibility detect level + uint32 detectLevel = 0; + Unit::AuraList const& dAuras = GetAurasByType(SPELL_AURA_MOD_INVISIBILITY_DETECTION); + for(Unit::AuraList::const_iterator itr = dAuras.begin(); itr != dAuras.end(); ++itr) + if(((*itr)->GetModifier()->m_miscvalue)==i && detectLevel < (*itr)->GetModifier()->m_amount) + detectLevel = (*itr)->GetModifier()->m_amount; + + if(i==6 && GetTypeId()==TYPEID_PLAYER) // special drunk detection case + { + detectLevel = ((Player*)this)->GetDrunkValue(); + } + + if(invLevel <= detectLevel) + return true; + } + } + + return false; +} + +void Unit::UpdateSpeed(UnitMoveType mtype, bool forced) +{ + int32 main_speed_mod = 0; + float stack_bonus = 1.0f; + float non_stack_bonus = 1.0f; + + switch(mtype) + { + case MOVE_WALK: + return; + case MOVE_RUN: + { + if (IsMounted()) // Use on mount auras + { + main_speed_mod = GetMaxPositiveAuraModifier(SPELL_AURA_MOD_INCREASE_MOUNTED_SPEED); + stack_bonus = GetTotalAuraMultiplier(SPELL_AURA_MOD_MOUNTED_SPEED_ALWAYS); + non_stack_bonus = (100.0f + GetMaxPositiveAuraModifier(SPELL_AURA_MOD_MOUNTED_SPEED_NOT_STACK))/100.0f; + } + else + { + main_speed_mod = GetMaxPositiveAuraModifier(SPELL_AURA_MOD_INCREASE_SPEED); + stack_bonus = GetTotalAuraMultiplier(SPELL_AURA_MOD_SPEED_ALWAYS); + non_stack_bonus = (100.0f + GetMaxPositiveAuraModifier(SPELL_AURA_MOD_SPEED_NOT_STACK))/100.0f; + } + break; + } + case MOVE_WALKBACK: + return; + case MOVE_SWIM: + { + main_speed_mod = GetMaxPositiveAuraModifier(SPELL_AURA_MOD_INCREASE_SWIM_SPEED); + break; + } + case MOVE_SWIMBACK: + return; + case MOVE_FLY: + { + if (IsMounted()) // Use on mount auras + main_speed_mod = GetMaxPositiveAuraModifier(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED); + else // Use not mount (shapeshift for example) auras (should stack) + main_speed_mod = GetTotalAuraModifier(SPELL_AURA_MOD_SPEED_FLIGHT); + stack_bonus = GetTotalAuraMultiplier(SPELL_AURA_MOD_FLIGHT_SPEED_ALWAYS); + non_stack_bonus = (100.0 + GetMaxPositiveAuraModifier(SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK))/100.0f; + break; + } + case MOVE_FLYBACK: + return; + default: + sLog.outError("Unit::UpdateSpeed: Unsupported move type (%d)", mtype); + return; + } + + float bonus = non_stack_bonus > stack_bonus ? non_stack_bonus : stack_bonus; + // now we ready for speed calculation + float speed = main_speed_mod ? bonus*(100.0f + main_speed_mod)/100.0f : bonus; + + switch(mtype) + { + case MOVE_RUN: + case MOVE_SWIM: + case MOVE_FLY: + { + // Normalize speed by 191 aura SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED if need + // TODO: possible affect only on MOVE_RUN + if(int32 normalization = GetMaxPositiveAuraModifier(SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED)) + { + // Use speed from aura + float max_speed = normalization / baseMoveSpeed[mtype]; + if (speed > max_speed) + speed = max_speed; + } + break; + } + default: + break; + } + + // Apply strongest slow aura mod to speed + int32 slow = GetMaxNegativeAuraModifier(SPELL_AURA_MOD_DECREASE_SPEED); + if (slow) + speed *=(100.0f + slow)/100.0f; + SetSpeed(mtype, speed, forced); +} + +float Unit::GetSpeed( UnitMoveType mtype ) const +{ + return m_speed_rate[mtype]*baseMoveSpeed[mtype]; +} + +void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced) +{ + if (rate < 0) + rate = 0.0f; + + // Update speed only on change + if (m_speed_rate[mtype] == rate) + return; + + m_speed_rate[mtype] = rate; + + propagateSpeedChange(); + + // Send speed change packet only for player + if (GetTypeId()!=TYPEID_PLAYER) + return; + + WorldPacket data; + if(!forced) + { + switch(mtype) + { + case MOVE_WALK: + data.Initialize(MSG_MOVE_SET_WALK_SPEED, 8+4+1+4+4+4+4+4+4+4); + break; + case MOVE_RUN: + data.Initialize(MSG_MOVE_SET_RUN_SPEED, 8+4+1+4+4+4+4+4+4+4); + break; + case MOVE_WALKBACK: + data.Initialize(MSG_MOVE_SET_RUN_BACK_SPEED, 8+4+1+4+4+4+4+4+4+4); + break; + case MOVE_SWIM: + data.Initialize(MSG_MOVE_SET_SWIM_SPEED, 8+4+1+4+4+4+4+4+4+4); + break; + case MOVE_SWIMBACK: + data.Initialize(MSG_MOVE_SET_SWIM_BACK_SPEED, 8+4+1+4+4+4+4+4+4+4); + break; + case MOVE_TURN: + data.Initialize(MSG_MOVE_SET_TURN_RATE, 8+4+1+4+4+4+4+4+4+4); + break; + case MOVE_FLY: + data.Initialize(MSG_MOVE_SET_FLIGHT_SPEED, 8+4+1+4+4+4+4+4+4+4); + break; + case MOVE_FLYBACK: + data.Initialize(MSG_MOVE_SET_FLIGHT_BACK_SPEED, 8+4+1+4+4+4+4+4+4+4); + break; + default: + sLog.outError("Unit::SetSpeed: Unsupported move type (%d), data not sent to client.",mtype); + return; + } + + data.append(GetPackGUID()); + data << uint32(0); //movement flags + data << uint8(0); //unk + data << uint32(getMSTime()); + data << float(GetPositionX()); + data << float(GetPositionY()); + data << float(GetPositionZ()); + data << float(GetOrientation()); + data << uint32(0); //flag unk + data << float(GetSpeed(mtype)); + SendMessageToSet( &data, true ); + } + else + { + // register forced speed changes for WorldSession::HandleForceSpeedChangeAck + // and do it only for real sent packets and use run for run/mounted as client expected + ++((Player*)this)->m_forced_speed_changes[mtype]; + switch(mtype) + { + case MOVE_WALK: + data.Initialize(SMSG_FORCE_WALK_SPEED_CHANGE, 16); + break; + case MOVE_RUN: + data.Initialize(SMSG_FORCE_RUN_SPEED_CHANGE, 17); + break; + case MOVE_WALKBACK: + data.Initialize(SMSG_FORCE_RUN_BACK_SPEED_CHANGE, 16); + break; + case MOVE_SWIM: + data.Initialize(SMSG_FORCE_SWIM_SPEED_CHANGE, 16); + break; + case MOVE_SWIMBACK: + data.Initialize(SMSG_FORCE_SWIM_BACK_SPEED_CHANGE, 16); + break; + case MOVE_TURN: + data.Initialize(SMSG_FORCE_TURN_RATE_CHANGE, 16); + break; + case MOVE_FLY: + data.Initialize(SMSG_FORCE_FLIGHT_SPEED_CHANGE, 16); + break; + case MOVE_FLYBACK: + data.Initialize(SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE, 16); + break; + default: + sLog.outError("Unit::SetSpeed: Unsupported move type (%d), data not sent to client.",mtype); + return; + } + data.append(GetPackGUID()); + data << (uint32)0; + if (mtype == MOVE_RUN) + data << uint8(0); // new 2.1.0 + data << float(GetSpeed(mtype)); + SendMessageToSet( &data, true ); + } + if(Pet* pet = GetPet()) + pet->SetSpeed(MOVE_RUN, m_speed_rate[mtype],forced); +} + +void Unit::SetHover(bool on) +{ + if(on) + CastSpell(this,11010,true); + else + RemoveAurasDueToSpell(11010); +} + +void Unit::setDeathState(DeathState s) +{ + if (s != ALIVE && s!= JUST_ALIVED) + { + CombatStop(); + DeleteThreatList(); + ClearComboPointHolders(); // any combo points pointed to unit lost at it death + + if(IsNonMeleeSpellCasted(false)) + InterruptNonMeleeSpells(false); + } + + if (s == JUST_DIED) + { + RemoveAllAurasOnDeath(); + UnsummonAllTotems(); + + ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false); + ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false); + // remove aurastates allowing special moves + ClearAllReactives(); + ClearDiminishings(); + } + else if(s == JUST_ALIVED) + { + RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); // clear skinnable for creature and player (at battleground) + } + + if (m_deathState != ALIVE && s == ALIVE) + { + //_ApplyAllAuraMods(); + } + m_deathState = s; +} + +/*######################################## +######## ######## +######## AGGRO SYSTEM ######## +######## ######## +########################################*/ +bool Unit::CanHaveThreatList() const +{ + // only creatures can have threat list + if( GetTypeId() != TYPEID_UNIT ) + return false; + + // only alive units can have threat list + if( !isAlive() ) + return false; + + // pets and totems can not have threat list + if( ((Creature*)this)->isPet() || ((Creature*)this)->isTotem() ) + return false; + + return true; +} + +//====================================================================== + +float Unit::ApplyTotalThreatModifier(float threat, SpellSchoolMask schoolMask) +{ + if(!HasAuraType(SPELL_AURA_MOD_THREAT)) + return threat; + + SpellSchools school = GetFirstSchoolInMask(schoolMask); + + return threat * m_threatModifier[school]; +} + +//====================================================================== + +void Unit::AddThreat(Unit* pVictim, float threat, SpellSchoolMask schoolMask, SpellEntry const *threatSpell) +{ + // Only mobs can manage threat lists + if(CanHaveThreatList()) + m_ThreatManager.addThreat(pVictim, threat, schoolMask, threatSpell); +} + +//====================================================================== + +void Unit::DeleteThreatList() +{ + m_ThreatManager.clearReferences(); +} + +//====================================================================== + +void Unit::TauntApply(Unit* taunter) +{ + assert(GetTypeId()== TYPEID_UNIT); + + if(!taunter || (taunter->GetTypeId() == TYPEID_PLAYER && ((Player*)taunter)->isGameMaster())) + return; + + if(!CanHaveThreatList()) + return; + + Unit *target = getVictim(); + if(target && target == taunter) + return; + + SetInFront(taunter); + if (((Creature*)this)->AI()) + ((Creature*)this)->AI()->AttackStart(taunter); + + m_ThreatManager.tauntApply(taunter); +} + +//====================================================================== + +void Unit::TauntFadeOut(Unit *taunter) +{ + assert(GetTypeId()== TYPEID_UNIT); + + if(!taunter || (taunter->GetTypeId() == TYPEID_PLAYER && ((Player*)taunter)->isGameMaster())) + return; + + if(!CanHaveThreatList()) + return; + + Unit *target = getVictim(); + if(!target || target != taunter) + return; + + if(m_ThreatManager.isThreatListEmpty()) + { + if(((Creature*)this)->AI()) + ((Creature*)this)->AI()->EnterEvadeMode(); + return; + } + + m_ThreatManager.tauntFadeOut(taunter); + target = m_ThreatManager.getHostilTarget(); + + if (target && target != taunter) + { + SetInFront(target); + if (((Creature*)this)->AI()) + ((Creature*)this)->AI()->AttackStart(target); + } +} + +//====================================================================== + +bool Unit::SelectHostilTarget() +{ + //function provides main threat functionality + //next-victim-selection algorithm and evade mode are called + //threat list sorting etc. + + assert(GetTypeId()== TYPEID_UNIT); + Unit* target = NULL; + + //This function only useful once AI has been initilazied + if (!((Creature*)this)->AI()) + return false; + + if(!m_ThreatManager.isThreatListEmpty()) + { + if(!HasAuraType(SPELL_AURA_MOD_TAUNT)) + { + target = m_ThreatManager.getHostilTarget(); + } + } + + if(target) + { + if(!hasUnitState(UNIT_STAT_STUNDED)) + SetInFront(target); + ((Creature*)this)->AI()->AttackStart(target); + return true; + } + + // no target but something prevent go to evade mode + if( !isInCombat() || HasAuraType(SPELL_AURA_MOD_TAUNT) ) + return false; + + // last case when creature don't must go to evade mode: + // it in combat but attacker not make any damage and not enter to aggro radius to have record in threat list + // for example at owner command to pet attack some far away creature + // Note: creature not have targeted movement generator but have attacker in this case + if( GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE ) + { + for(AttackerSet::const_iterator itr = m_attackers.begin(); itr != m_attackers.end(); ++itr) + { + if( (*itr)->IsInMap(this) && (*itr)->isTargetableForAttack() && (*itr)->isInAccessablePlaceFor((Creature*)this) ) + return false; + } + } + + // enter in evade mode in other case + ((Creature*)this)->AI()->EnterEvadeMode(); + + return false; +} + +//====================================================================== +//====================================================================== +//====================================================================== + +int32 Unit::CalculateSpellDamage(SpellEntry const* spellProto, uint8 effect_index, int32 effBasePoints, Unit const* target) +{ + Player* unitPlayer = (GetTypeId() == TYPEID_PLAYER) ? (Player*)this : NULL; + + uint8 comboPoints = unitPlayer ? unitPlayer->GetComboPoints() : 0; + + int32 level = int32(getLevel()) - int32(spellProto->spellLevel); + if (level > spellProto->maxLevel && spellProto->maxLevel > 0) + level = spellProto->maxLevel; + + float basePointsPerLevel = spellProto->EffectRealPointsPerLevel[effect_index]; + float randomPointsPerLevel = spellProto->EffectDicePerLevel[effect_index]; + int32 basePoints = int32(effBasePoints + level * basePointsPerLevel); + int32 randomPoints = int32(spellProto->EffectDieSides[effect_index] + level * randomPointsPerLevel); + float comboDamage = spellProto->EffectPointsPerComboPoint[effect_index]; + + // prevent random generator from getting confused by spells casted with Unit::CastCustomSpell + int32 randvalue = spellProto->EffectBaseDice[effect_index] >= randomPoints ? spellProto->EffectBaseDice[effect_index]:irand(spellProto->EffectBaseDice[effect_index], randomPoints); + int32 value = basePoints + randvalue; + //random damage + if(comboDamage != 0 && unitPlayer && target && (target->GetGUID() == unitPlayer->GetComboTarget())) + value += (int32)(comboDamage * comboPoints); + + if(Player* modOwner = GetSpellModOwner()) + { + modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_ALL_EFFECTS, value); + switch(effect_index) + { + case 0: + modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_EFFECT1, value); + break; + case 1: + modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_EFFECT2, value); + break; + case 2: + modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_EFFECT3, value); + break; + } + } + + if(spellProto->Attributes & SPELL_ATTR_LEVEL_DAMAGE_CALCULATION && spellProto->spellLevel && + spellProto->Effect[effect_index] != SPELL_EFFECT_WEAPON_PERCENT_DAMAGE && + spellProto->Effect[effect_index] != SPELL_EFFECT_KNOCK_BACK) + value = int32(value*0.25f*exp(getLevel()*(70-spellProto->spellLevel)/1000.0f)); + + return value; +} + +int32 Unit::CalculateSpellDuration(SpellEntry const* spellProto, uint8 effect_index, Unit const* target) +{ + Player* unitPlayer = (GetTypeId() == TYPEID_PLAYER) ? (Player*)this : NULL; + + uint8 comboPoints = unitPlayer ? unitPlayer->GetComboPoints() : 0; + + int32 minduration = GetSpellDuration(spellProto); + int32 maxduration = GetSpellMaxDuration(spellProto); + + int32 duration; + + if( minduration != -1 && minduration != maxduration ) + duration = minduration + int32((maxduration - minduration) * comboPoints / 5); + else + duration = minduration; + + if (duration > 0) + { + int32 mechanic = GetEffectMechanic(spellProto, effect_index); + // Find total mod value (negative bonus) + int32 durationMod_always = target->GetTotalAuraModifierByMiscValue(SPELL_AURA_MECHANIC_DURATION_MOD, mechanic); + // Find max mod (negative bonus) + int32 durationMod_not_stack = target->GetMaxNegativeAuraModifierByMiscValue(SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK, mechanic); + + int32 durationMod = 0; + // Select strongest negative mod + if (durationMod_always > durationMod_not_stack) + durationMod = durationMod_not_stack; + else + durationMod = durationMod_always; + + if (durationMod != 0) + duration = int32(int64(duration) * (100+durationMod) /100); + + if (duration < 0) duration = 0; + } + + return duration; +} + +DiminishingLevels Unit::GetDiminishing(DiminishingGroup group) +{ + for(Diminishing::iterator i = m_Diminishing.begin(); i != m_Diminishing.end(); ++i) + { + if(i->DRGroup != group) + continue; + + if(!i->hitCount) + return DIMINISHING_LEVEL_1; + + if(!i->hitTime) + return DIMINISHING_LEVEL_1; + + // If last spell was casted more than 15 seconds ago - reset the count. + if(i->stack==0 && getMSTimeDiff(i->hitTime,getMSTime()) > 15000) + { + i->hitCount = DIMINISHING_LEVEL_1; + return DIMINISHING_LEVEL_1; + } + // or else increase the count. + else + { + return DiminishingLevels(i->hitCount); + } + } + return DIMINISHING_LEVEL_1; +} + +void Unit::IncrDiminishing(DiminishingGroup group) +{ + // Checking for existing in the table + bool IsExist = false; + for(Diminishing::iterator i = m_Diminishing.begin(); i != m_Diminishing.end(); ++i) + { + if(i->DRGroup != group) + continue; + + IsExist = true; + if(i->hitCount < DIMINISHING_LEVEL_IMMUNE) + i->hitCount += 1; + + break; + } + + if(!IsExist) + m_Diminishing.push_back(DiminishingReturn(group,getMSTime(),DIMINISHING_LEVEL_2)); +} + +void Unit::ApplyDiminishingToDuration(DiminishingGroup group, int32 &duration,Unit* caster,DiminishingLevels Level) +{ + if(duration == -1 || group == DIMINISHING_NONE || caster->IsFriendlyTo(this) ) + return; + + // Duration of crowd control abilities on pvp target is limited by 10 sec. (2.2.0) + if(duration > 10000 && IsDiminishingReturnsGroupDurationLimited(group)) + { + // test pet/charm masters instead pets/charmeds + Unit const* targetOwner = GetCharmerOrOwner(); + Unit const* casterOwner = caster->GetCharmerOrOwner(); + + Unit const* target = targetOwner ? targetOwner : this; + Unit const* source = casterOwner ? casterOwner : caster; + + if(target->GetTypeId() == TYPEID_PLAYER && source->GetTypeId() == TYPEID_PLAYER) + duration = 10000; + } + + float mod = 1.0f; + + // Some diminishings applies to mobs too (for example, Stun) + if((GetDiminishingReturnsGroupType(group) == DRTYPE_PLAYER && GetTypeId() == TYPEID_PLAYER) || GetDiminishingReturnsGroupType(group) == DRTYPE_ALL) + { + DiminishingLevels diminish = Level; + switch(diminish) + { + case DIMINISHING_LEVEL_1: break; + case DIMINISHING_LEVEL_2: mod = 0.5f; break; + case DIMINISHING_LEVEL_3: mod = 0.25f; break; + case DIMINISHING_LEVEL_IMMUNE: mod = 0.0f;break; + default: break; + } + } + + duration = int32(duration * mod); +} + +void Unit::ApplyDiminishingAura( DiminishingGroup group, bool apply ) +{ + // Checking for existing in the table + for(Diminishing::iterator i = m_Diminishing.begin(); i != m_Diminishing.end(); ++i) + { + if(i->DRGroup != group) + continue; + + i->hitTime = getMSTime(); + + if(apply) + i->stack += 1; + else if(i->stack) + i->stack -= 1; + + break; + } +} + +Unit* Unit::GetUnit(WorldObject& object, uint64 guid) +{ + return ObjectAccessor::GetUnit(object,guid); +} + +bool Unit::isVisibleForInState( Player const* u, bool inVisibleList ) const +{ + return isVisibleForOrDetect(u,false,inVisibleList); +} + +uint32 Unit::GetCreatureType() const +{ + if(GetTypeId() == TYPEID_PLAYER) + { + SpellShapeshiftEntry const* ssEntry = sSpellShapeshiftStore.LookupEntry(((Player*)this)->m_form); + if(ssEntry && ssEntry->creatureType > 0) + return ssEntry->creatureType; + else + return CREATURE_TYPE_HUMANOID; + } + else + return ((Creature*)this)->GetCreatureInfo()->type; +} + +/*####################################### +######## ######## +######## STAT SYSTEM ######## +######## ######## +#######################################*/ + +bool Unit::HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, float amount, bool apply) +{ + if(unitMod >= UNIT_MOD_END || modifierType >= MODIFIER_TYPE_END) + { + sLog.outError("ERROR in HandleStatModifier(): nonexisted UnitMods or wrong UnitModifierType!"); + return false; + } + + float val = 1.0f; + + switch(modifierType) + { + case BASE_VALUE: + case TOTAL_VALUE: + m_auraModifiersGroup[unitMod][modifierType] += apply ? amount : -amount; + break; + case BASE_PCT: + case TOTAL_PCT: + if(amount <= -100.0f) //small hack-fix for -100% modifiers + amount = -200.0f; + + val = (100.0f + amount) / 100.0f; + m_auraModifiersGroup[unitMod][modifierType] *= apply ? val : (1.0f/val); + break; + + default: + break; + } + + if(!CanModifyStats()) + return false; + + switch(unitMod) + { + case UNIT_MOD_STAT_STRENGTH: + case UNIT_MOD_STAT_AGILITY: + case UNIT_MOD_STAT_STAMINA: + case UNIT_MOD_STAT_INTELLECT: + case UNIT_MOD_STAT_SPIRIT: UpdateStats(GetStatByAuraGroup(unitMod)); break; + + case UNIT_MOD_ARMOR: UpdateArmor(); break; + case UNIT_MOD_HEALTH: UpdateMaxHealth(); break; + + case UNIT_MOD_MANA: + case UNIT_MOD_RAGE: + case UNIT_MOD_FOCUS: + case UNIT_MOD_ENERGY: + case UNIT_MOD_HAPPINESS: UpdateMaxPower(GetPowerTypeByAuraGroup(unitMod)); break; + + case UNIT_MOD_RESISTANCE_HOLY: + case UNIT_MOD_RESISTANCE_FIRE: + case UNIT_MOD_RESISTANCE_NATURE: + case UNIT_MOD_RESISTANCE_FROST: + case UNIT_MOD_RESISTANCE_SHADOW: + case UNIT_MOD_RESISTANCE_ARCANE: UpdateResistances(GetSpellSchoolByAuraGroup(unitMod)); break; + + case UNIT_MOD_ATTACK_POWER: UpdateAttackPowerAndDamage(); break; + case UNIT_MOD_ATTACK_POWER_RANGED: UpdateAttackPowerAndDamage(true); break; + + case UNIT_MOD_DAMAGE_MAINHAND: UpdateDamagePhysical(BASE_ATTACK); break; + case UNIT_MOD_DAMAGE_OFFHAND: UpdateDamagePhysical(OFF_ATTACK); break; + case UNIT_MOD_DAMAGE_RANGED: UpdateDamagePhysical(RANGED_ATTACK); break; + + default: + break; + } + + return true; +} + +float Unit::GetModifierValue(UnitMods unitMod, UnitModifierType modifierType) const +{ + if( unitMod >= UNIT_MOD_END || modifierType >= MODIFIER_TYPE_END) + { + sLog.outError("ERROR: trial to access nonexisted modifier value from UnitMods!"); + return 0.0f; + } + + if(modifierType == TOTAL_PCT && m_auraModifiersGroup[unitMod][modifierType] <= 0.0f) + return 0.0f; + + return m_auraModifiersGroup[unitMod][modifierType]; +} + +float Unit::GetTotalStatValue(Stats stat) const +{ + UnitMods unitMod = UnitMods(UNIT_MOD_STAT_START + stat); + + if(m_auraModifiersGroup[unitMod][TOTAL_PCT] <= 0.0f) + return 0.0f; + + // value = ((base_value * base_pct) + total_value) * total_pct + float value = m_auraModifiersGroup[unitMod][BASE_VALUE] + GetCreateStat(stat); + value *= m_auraModifiersGroup[unitMod][BASE_PCT]; + value += m_auraModifiersGroup[unitMod][TOTAL_VALUE]; + value *= m_auraModifiersGroup[unitMod][TOTAL_PCT]; + + return value; +} + +float Unit::GetTotalAuraModValue(UnitMods unitMod) const +{ + if(unitMod >= UNIT_MOD_END) + { + sLog.outError("ERROR: trial to access nonexisted UnitMods in GetTotalAuraModValue()!"); + return 0.0f; + } + + if(m_auraModifiersGroup[unitMod][TOTAL_PCT] <= 0.0f) + return 0.0f; + + float value = m_auraModifiersGroup[unitMod][BASE_VALUE]; + value *= m_auraModifiersGroup[unitMod][BASE_PCT]; + value += m_auraModifiersGroup[unitMod][TOTAL_VALUE]; + value *= m_auraModifiersGroup[unitMod][TOTAL_PCT]; + + return value; +} + +SpellSchools Unit::GetSpellSchoolByAuraGroup(UnitMods unitMod) const +{ + SpellSchools school = SPELL_SCHOOL_NORMAL; + + switch(unitMod) + { + case UNIT_MOD_RESISTANCE_HOLY: school = SPELL_SCHOOL_HOLY; break; + case UNIT_MOD_RESISTANCE_FIRE: school = SPELL_SCHOOL_FIRE; break; + case UNIT_MOD_RESISTANCE_NATURE: school = SPELL_SCHOOL_NATURE; break; + case UNIT_MOD_RESISTANCE_FROST: school = SPELL_SCHOOL_FROST; break; + case UNIT_MOD_RESISTANCE_SHADOW: school = SPELL_SCHOOL_SHADOW; break; + case UNIT_MOD_RESISTANCE_ARCANE: school = SPELL_SCHOOL_ARCANE; break; + + default: + break; + } + + return school; +} + +Stats Unit::GetStatByAuraGroup(UnitMods unitMod) const +{ + Stats stat = STAT_STRENGTH; + + switch(unitMod) + { + case UNIT_MOD_STAT_STRENGTH: stat = STAT_STRENGTH; break; + case UNIT_MOD_STAT_AGILITY: stat = STAT_AGILITY; break; + case UNIT_MOD_STAT_STAMINA: stat = STAT_STAMINA; break; + case UNIT_MOD_STAT_INTELLECT: stat = STAT_INTELLECT; break; + case UNIT_MOD_STAT_SPIRIT: stat = STAT_SPIRIT; break; + + default: + break; + } + + return stat; +} + +Powers Unit::GetPowerTypeByAuraGroup(UnitMods unitMod) const +{ + Powers power = POWER_MANA; + + switch(unitMod) + { + case UNIT_MOD_MANA: power = POWER_MANA; break; + case UNIT_MOD_RAGE: power = POWER_RAGE; break; + case UNIT_MOD_FOCUS: power = POWER_FOCUS; break; + case UNIT_MOD_ENERGY: power = POWER_ENERGY; break; + case UNIT_MOD_HAPPINESS: power = POWER_HAPPINESS; break; + + default: + break; + } + + return power; +} + +float Unit::GetTotalAttackPowerValue(WeaponAttackType attType) const +{ + UnitMods unitMod = (attType == RANGED_ATTACK) ? UNIT_MOD_ATTACK_POWER_RANGED : UNIT_MOD_ATTACK_POWER; + + float val = GetTotalAuraModValue(unitMod); + if(val < 0.0f) + val = 0.0f; + + return val; +} + +float Unit::GetWeaponDamageRange(WeaponAttackType attType ,WeaponDamageRange type) const +{ + if (attType == OFF_ATTACK && !haveOffhandWeapon()) + return 0.0f; + + return m_weaponDamage[attType][type]; +} + +void Unit::SetLevel(uint32 lvl) +{ + SetUInt32Value(UNIT_FIELD_LEVEL, lvl); + + // group update + if ((GetTypeId() == TYPEID_PLAYER) && ((Player*)this)->GetGroup()) + ((Player*)this)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_LEVEL); +} + +void Unit::SetHealth(uint32 val) +{ + uint32 maxHealth = GetMaxHealth(); + if(maxHealth < val) + val = maxHealth; + + SetUInt32Value(UNIT_FIELD_HEALTH, val); + + // group update + if(GetTypeId() == TYPEID_PLAYER) + { + if(((Player*)this)->GetGroup()) + ((Player*)this)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_CUR_HP); + } + else if(((Creature*)this)->isPet()) + { + Pet *pet = ((Pet*)this); + if(pet->isControlled()) + { + Unit *owner = GetOwner(); + if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup()) + ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_CUR_HP); + } + } +} + +void Unit::SetMaxHealth(uint32 val) +{ + uint32 health = GetHealth(); + SetUInt32Value(UNIT_FIELD_MAXHEALTH, val); + + // group update + if(GetTypeId() == TYPEID_PLAYER) + { + if(((Player*)this)->GetGroup()) + ((Player*)this)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_MAX_HP); + } + else if(((Creature*)this)->isPet()) + { + Pet *pet = ((Pet*)this); + if(pet->isControlled()) + { + Unit *owner = GetOwner(); + if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup()) + ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MAX_HP); + } + } + + if(val < health) + SetHealth(val); +} + +void Unit::SetPower(Powers power, uint32 val) +{ + uint32 maxPower = GetMaxPower(power); + if(maxPower < val) + val = maxPower; + + SetStatInt32Value(UNIT_FIELD_POWER1 + power, val); + + // group update + if(GetTypeId() == TYPEID_PLAYER) + { + if(((Player*)this)->GetGroup()) + ((Player*)this)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_CUR_POWER); + } + else if(((Creature*)this)->isPet()) + { + Pet *pet = ((Pet*)this); + if(pet->isControlled()) + { + Unit *owner = GetOwner(); + if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup()) + ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_CUR_POWER); + } + + // Update the pet's character sheet with happiness damage bonus + if(pet->getPetType() == HUNTER_PET && power == POWER_HAPPINESS) + { + pet->UpdateDamagePhysical(BASE_ATTACK); + } + } +} + +void Unit::SetMaxPower(Powers power, uint32 val) +{ + uint32 cur_power = GetPower(power); + SetStatInt32Value(UNIT_FIELD_MAXPOWER1 + power, val); + + // group update + if(GetTypeId() == TYPEID_PLAYER) + { + if(((Player*)this)->GetGroup()) + ((Player*)this)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_MAX_POWER); + } + else if(((Creature*)this)->isPet()) + { + Pet *pet = ((Pet*)this); + if(pet->isControlled()) + { + Unit *owner = GetOwner(); + if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup()) + ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MAX_POWER); + } + } + + if(val < cur_power) + SetPower(power, val); +} + +void Unit::ApplyPowerMod(Powers power, uint32 val, bool apply) +{ + ApplyModUInt32Value(UNIT_FIELD_POWER1+power, val, apply); + + // group update + if(GetTypeId() == TYPEID_PLAYER) + { + if(((Player*)this)->GetGroup()) + ((Player*)this)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_CUR_POWER); + } + else if(((Creature*)this)->isPet()) + { + Pet *pet = ((Pet*)this); + if(pet->isControlled()) + { + Unit *owner = GetOwner(); + if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup()) + ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_CUR_POWER); + } + } +} + +void Unit::ApplyMaxPowerMod(Powers power, uint32 val, bool apply) +{ + ApplyModUInt32Value(UNIT_FIELD_MAXPOWER1+power, val, apply); + + // group update + if(GetTypeId() == TYPEID_PLAYER) + { + if(((Player*)this)->GetGroup()) + ((Player*)this)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_MAX_POWER); + } + else if(((Creature*)this)->isPet()) + { + Pet *pet = ((Pet*)this); + if(pet->isControlled()) + { + Unit *owner = GetOwner(); + if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup()) + ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MAX_POWER); + } + } +} + +void Unit::ApplyAuraProcTriggerDamage( Aura* aura, bool apply ) +{ + AuraList& tAuraProcTriggerDamage = m_modAuras[SPELL_AURA_PROC_TRIGGER_DAMAGE]; + if(apply) + tAuraProcTriggerDamage.push_back(aura); + else + tAuraProcTriggerDamage.remove(aura); +} + +uint32 Unit::GetCreatePowers( Powers power ) const +{ + // POWER_FOCUS and POWER_HAPPINESS only have hunter pet + switch(power) + { + case POWER_MANA: return GetCreateMana(); + case POWER_RAGE: return 1000; + case POWER_FOCUS: return (GetTypeId()==TYPEID_PLAYER || !((Creature const*)this)->isPet() || ((Pet const*)this)->getPetType()!=HUNTER_PET ? 0 : 100); + case POWER_ENERGY: return 100; + case POWER_HAPPINESS: return (GetTypeId()==TYPEID_PLAYER || !((Creature const*)this)->isPet() || ((Pet const*)this)->getPetType()!=HUNTER_PET ? 0 : 1050000); + } + + return 0; +} + +void Unit::AddToWorld() +{ + Object::AddToWorld(); +} + +void Unit::RemoveFromWorld() +{ + // cleanup + if(IsInWorld()) + { + RemoveNotOwnSingleTargetAuras(); + } + + Object::RemoveFromWorld(); +} + +void Unit::CleanupsBeforeDelete() +{ + if(m_uint32Values) // only for fully created object + { + InterruptNonMeleeSpells(true); + m_Events.KillAllEvents(); + CombatStop(); + ClearComboPointHolders(); + DeleteThreatList(); + getHostilRefManager().setOnlineOfflineState(false); + RemoveAllAuras(); + RemoveAllGameObjects(); + RemoveAllDynObjects(); + GetMotionMaster()->Clear(false); // remove different non-standard movement generators. + } + RemoveFromWorld(); +} + +CharmInfo* Unit::InitCharmInfo(Unit *charm) +{ + if(!m_charmInfo) + m_charmInfo = new CharmInfo(charm); + return m_charmInfo; +} + +CharmInfo::CharmInfo(Unit* unit) +: m_unit(unit), m_CommandState(COMMAND_FOLLOW), m_ReactSate(REACT_PASSIVE), m_petnumber(0) +{ + for(int i =0; i<4; ++i) + { + m_charmspells[i].spellId = 0; + m_charmspells[i].active = ACT_DISABLED; + } +} + +void CharmInfo::InitPetActionBar() +{ + // the first 3 SpellOrActions are attack, follow and stay + for(uint32 i = 0; i < 3; i++) + { + PetActionBar[i].Type = ACT_COMMAND; + PetActionBar[i].SpellOrAction = COMMAND_ATTACK - i; + + PetActionBar[i + 7].Type = ACT_REACTION; + PetActionBar[i + 7].SpellOrAction = COMMAND_ATTACK - i; + } + for(uint32 i=0; i < 4; i++) + { + PetActionBar[i + 3].Type = ACT_DISABLED; + PetActionBar[i + 3].SpellOrAction = 0; + } +} + +void CharmInfo::InitEmptyActionBar() +{ + for(uint32 x = 1; x < 10; ++x) + { + PetActionBar[x].Type = ACT_CAST; + PetActionBar[x].SpellOrAction = 0; + } + PetActionBar[0].Type = ACT_COMMAND; + PetActionBar[0].SpellOrAction = COMMAND_ATTACK; +} + +void CharmInfo::InitPossessCreateSpells() +{ + if(m_unit->GetTypeId() == TYPEID_PLAYER) + return; + + InitEmptyActionBar(); //charm action bar + + for(uint32 x = 0; x < CREATURE_MAX_SPELLS; ++x) + { + if (IsPassiveSpell(((Creature*)m_unit)->m_spells[x])) + m_unit->CastSpell(m_unit, ((Creature*)m_unit)->m_spells[x], true); + else + AddSpellToAB(0, ((Creature*)m_unit)->m_spells[x], ACT_CAST); + } +} + +void CharmInfo::InitCharmCreateSpells() +{ + if(m_unit->GetTypeId() == TYPEID_PLAYER) //charmed players don't have spells + { + InitEmptyActionBar(); + return; + } + + InitPetActionBar(); + + for(uint32 x = 0; x < CREATURE_MAX_SPELLS; ++x) + { + uint32 spellId = ((Creature*)m_unit)->m_spells[x]; + m_charmspells[x].spellId = spellId; + + if(!spellId) + continue; + + if (IsPassiveSpell(spellId)) + { + m_unit->CastSpell(m_unit, spellId, true); + m_charmspells[x].active = ACT_PASSIVE; + } + else + { + ActiveStates newstate; + bool onlyselfcast = true; + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); + + if(!spellInfo) onlyselfcast = false; + for(uint32 i = 0;i<3 && onlyselfcast;++i) //non existent spell will not make any problems as onlyselfcast would be false -> break right away + { + if(spellInfo->EffectImplicitTargetA[i] != TARGET_SELF && spellInfo->EffectImplicitTargetA[i] != 0) + onlyselfcast = false; + } + + if(onlyselfcast || !IsPositiveSpell(spellId)) //only self cast and spells versus enemies are autocastable + newstate = ACT_DISABLED; + else + newstate = ACT_CAST; + + AddSpellToAB(0, spellId, newstate); + } + } +} + +bool CharmInfo::AddSpellToAB(uint32 oldid, uint32 newid, ActiveStates newstate) +{ + for(uint8 i = 0; i < 10; i++) + { + if((PetActionBar[i].Type == ACT_DISABLED || PetActionBar[i].Type == ACT_ENABLED || PetActionBar[i].Type == ACT_CAST) && PetActionBar[i].SpellOrAction == oldid) + { + PetActionBar[i].SpellOrAction = newid; + if(!oldid) + { + if(newstate == ACT_DECIDE) + PetActionBar[i].Type = ACT_DISABLED; + else + PetActionBar[i].Type = newstate; + } + + return true; + } + } + return false; +} + +void CharmInfo::ToggleCreatureAutocast(uint32 spellid, bool apply) +{ + if(IsPassiveSpell(spellid)) + return; + + for(uint32 x = 0; x < CREATURE_MAX_SPELLS; ++x) + { + if(spellid == m_charmspells[x].spellId) + { + m_charmspells[x].active = apply ? ACT_ENABLED : ACT_DISABLED; + } + } +} + +void CharmInfo::SetPetNumber(uint32 petnumber, bool statwindow) +{ + m_petnumber = petnumber; + if(statwindow) + m_unit->SetUInt32Value(UNIT_FIELD_PETNUMBER, m_petnumber); + else + m_unit->SetUInt32Value(UNIT_FIELD_PETNUMBER, 0); +} + +bool Unit::isFrozen() const +{ + AuraList const& mRoot = GetAurasByType(SPELL_AURA_MOD_ROOT); + for(AuraList::const_iterator i = mRoot.begin(); i != mRoot.end(); ++i) + if( GetSpellSchoolMask((*i)->GetSpellProto()) & SPELL_SCHOOL_MASK_FROST) + return true; + return false; +} + +struct ProcTriggeredData +{ + ProcTriggeredData(SpellEntry const * _spellInfo, uint32 _spellParam, Aura* _triggeredByAura, uint32 _cooldown) + : spellInfo(_spellInfo), spellParam(_spellParam), triggeredByAura(_triggeredByAura), + triggeredByAura_SpellPair(Unit::spellEffectPair(triggeredByAura->GetId(),triggeredByAura->GetEffIndex())), + cooldown(_cooldown) + {} + + SpellEntry const * spellInfo; + uint32 spellParam; + Aura* triggeredByAura; + Unit::spellEffectPair triggeredByAura_SpellPair; + uint32 cooldown; +}; + +typedef std::list< ProcTriggeredData > ProcTriggeredList; + +void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag, AuraTypeSet const& procAuraTypes, WeaponAttackType attType, SpellEntry const * procSpell, uint32 damage, SpellSchoolMask damageSchoolMask ) +{ + for(AuraTypeSet::const_iterator aur = procAuraTypes.begin(); aur != procAuraTypes.end(); ++aur) + { + // List of spells (effects) that proceed. Spell prototype and aura-specific value (damage for TRIGGER_DAMAGE) + ProcTriggeredList procTriggered; + + AuraList const& auras = GetAurasByType(*aur); + for(AuraList::const_iterator i = auras.begin(), next; i != auras.end(); i = next) + { + next = i; ++next; + + SpellEntry const *spellProto = (*i)->GetSpellProto(); + if(!spellProto) + continue; + + SpellProcEventEntry const *spellProcEvent = spellmgr.GetSpellProcEvent(spellProto->Id); + if(!spellProcEvent) + { + // used to prevent spam in log about same non-handled spells + static std::set nonHandledSpellProcSet; + + if(spellProto->procFlags != 0 && nonHandledSpellProcSet.find(spellProto->Id)==nonHandledSpellProcSet.end()) + { + sLog.outError("ProcDamageAndSpell: spell %u (%s aura source) not have record in `spell_proc_event`)",spellProto->Id,(isVictim?"a victim's":"an attacker's")); + nonHandledSpellProcSet.insert(spellProto->Id); + } + + // spell.dbc use totally different flags, that only can create problems if used. + continue; + } + + // Check spellProcEvent data requirements + if(!SpellMgr::IsSpellProcEventCanTriggeredBy(spellProcEvent, procSpell,procFlag)) + continue; + + // Check if current equipment allows aura to proc + if(!isVictim && GetTypeId() == TYPEID_PLAYER ) + { + if(spellProto->EquippedItemClass == ITEM_CLASS_WEAPON) + { + Item *item = ((Player*)this)->GetWeaponForAttack(attType,true); + + if(!item || !((1<GetProto()->SubClass) & spellProto->EquippedItemSubClassMask)) + continue; + } + else if(spellProto->EquippedItemClass == ITEM_CLASS_ARMOR) + { + // Check if player is wearing shield + Item *item = ((Player*)this)->GetShield(true); + if(!item || !((1<GetProto()->SubClass) & spellProto->EquippedItemSubClassMask)) + continue; + } + } + + float chance = (float)spellProto->procChance; + + if(Player* modOwner = GetSpellModOwner()) + modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_CHANCE_OF_SUCCESS,chance); + + if(!isVictim && spellProcEvent->ppmRate != 0) + { + uint32 WeaponSpeed = GetAttackTime(attType); + chance = GetPPMProcChance(WeaponSpeed, spellProcEvent->ppmRate); + } + + if(roll_chance_f(chance)) + { + uint32 cooldown = spellProcEvent->cooldown; + + uint32 i_spell_eff = (*i)->GetEffIndex(); + + int32 i_spell_param; + switch(*aur) + { + case SPELL_AURA_PROC_TRIGGER_SPELL: + i_spell_param = procFlag; + break; + case SPELL_AURA_DUMMY: + case SPELL_AURA_PRAYER_OF_MENDING: + case SPELL_AURA_MOD_HASTE: + i_spell_param = i_spell_eff; + break; + case SPELL_AURA_OVERRIDE_CLASS_SCRIPTS: + i_spell_param = (*i)->GetModifier()->m_miscvalue; + break; + default: + i_spell_param = (*i)->GetModifier()->m_amount; + break; + } + + procTriggered.push_back( ProcTriggeredData(spellProto,i_spell_param,*i, cooldown) ); + } + } + + // Handle effects proceed this time + for(ProcTriggeredList::iterator i = procTriggered.begin(); i != procTriggered.end(); ++i) + { + // Some auras can be deleted in function called in this loop (except first, ofc) + // Until storing auras in std::multimap to hard check deleting by another way + if(i != procTriggered.begin()) + { + bool found = false; + AuraMap::const_iterator lower = GetAuras().lower_bound(i->triggeredByAura_SpellPair); + AuraMap::const_iterator upper = GetAuras().upper_bound(i->triggeredByAura_SpellPair); + for(AuraMap::const_iterator itr = lower; itr!= upper; ++itr) + { + if(itr->second==i->triggeredByAura) + { + found = true; + break; + } + } + + if(!found) + { + sLog.outError("Spell aura %u (id:%u effect:%u) has been deleted before call spell proc event handler",*aur,i->triggeredByAura_SpellPair.first,i->triggeredByAura_SpellPair.second); + sLog.outError("It can be deleted one from early proccesed auras:"); + for(ProcTriggeredList::iterator i2 = procTriggered.begin(); i != i2; ++i2) + sLog.outError(" Spell aura %u (id:%u effect:%u)",*aur,i2->triggeredByAura_SpellPair.first,i2->triggeredByAura_SpellPair.second); + sLog.outError(" "); + continue; + } + } + + // save charges existence before processing to prevent crash at access to deleted triggered aura after + bool triggeredByAuraWithCharges = i->triggeredByAura->m_procCharges > 0; + + bool casted = false; + switch(*aur) + { + case SPELL_AURA_PROC_TRIGGER_SPELL: + { + sLog.outDebug("ProcDamageAndSpell: casting spell %u (triggered by %s aura of spell %u)", i->spellInfo->Id,(isVictim?"a victim's":"an attacker's"),i->triggeredByAura->GetId()); + casted = HandleProcTriggerSpell(pTarget, damage, i->triggeredByAura, procSpell,i->spellParam,attType,i->cooldown); + break; + } + case SPELL_AURA_PROC_TRIGGER_DAMAGE: + { + sLog.outDebug("ProcDamageAndSpell: doing %u damage from spell id %u (triggered by %s aura of spell %u)", i->spellParam, i->spellInfo->Id,(isVictim?"a victim's":"an attacker's"),i->triggeredByAura->GetId()); + uint32 damage = i->spellParam; + SpellNonMeleeDamageLog(pTarget, i->spellInfo->Id, damage, true, true); + casted = true; + break; + } + case SPELL_AURA_DUMMY: + { + sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s dummy aura of spell %u)", i->spellInfo->Id,(isVictim?"a victim's":"an attacker's"),i->triggeredByAura->GetId()); + casted = HandleDummyAuraProc(pTarget, i->spellInfo, i->spellParam, damage, i->triggeredByAura, procSpell, procFlag,i->cooldown); + break; + } + case SPELL_AURA_PRAYER_OF_MENDING: + { + sLog.outDebug("ProcDamageAndSpell(mending): casting spell id %u (triggered by %s dummy aura of spell %u)", i->spellInfo->Id,(isVictim?"a victim's":"an attacker's"),i->triggeredByAura->GetId()); + + // aura can be deleted at casts + int32 heal = i->triggeredByAura->GetModifier()->m_amount; + uint64 caster_guid = i->triggeredByAura->GetCasterGUID(); + + // jumps + int32 jumps = i->triggeredByAura->m_procCharges-1; + + // current aura expire + i->triggeredByAura->m_procCharges = 1; // will removed at next charges decrease + + // next target selection + if(jumps > 0 && GetTypeId()==TYPEID_PLAYER && IS_PLAYER_GUID(caster_guid)) + { + Aura* aura = i->triggeredByAura; + + SpellEntry const* spellProto = aura->GetSpellProto(); + uint32 effIdx = aura->GetEffIndex(); + + float radius; + if (spellProto->EffectRadiusIndex[effIdx]) + radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(spellProto->EffectRadiusIndex[effIdx])); + else + radius = GetSpellMaxRange(sSpellRangeStore.LookupEntry(spellProto->rangeIndex)); + + if(Player* caster = ((Player*)aura->GetCaster())) + { + caster->ApplySpellMod(spellProto->Id, SPELLMOD_RADIUS, radius,NULL); + + if(Player* target = ((Player*)this)->GetNextRandomRaidMember(radius)) + { + // aura will applied from caster, but spell casted from current aura holder + SpellModifier *mod = new SpellModifier; + mod->op = SPELLMOD_CHARGES; + mod->value = jumps-5; // negative + mod->type = SPELLMOD_FLAT; + mod->spellId = spellProto->Id; + mod->effectId = effIdx; + mod->lastAffected = NULL; + mod->mask = spellProto->SpellFamilyFlags; + mod->charges = 0; + + caster->AddSpellMod(mod, true); + CastCustomSpell(target,spellProto->Id,&heal,NULL,NULL,true,NULL,aura,caster->GetGUID()); + caster->AddSpellMod(mod, false); + } + } + } + + // heal + CastCustomSpell(this,33110,&heal,NULL,NULL,true,NULL,NULL,caster_guid); + casted = true; + break; + } + case SPELL_AURA_MOD_HASTE: + { + sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s haste aura of spell %u)", i->spellInfo->Id,(isVictim?"a victim's":"an attacker's"),i->triggeredByAura->GetId()); + casted = HandleHasteAuraProc(pTarget, i->spellInfo, i->spellParam, damage, i->triggeredByAura, procSpell, procFlag,i->cooldown); + break; + } + case SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN: + { + // nothing do, just charges counter + // but count only in case appropriate school damage + casted = i->triggeredByAura->GetModifier()->m_miscvalue & damageSchoolMask; + break; + } + case SPELL_AURA_OVERRIDE_CLASS_SCRIPTS: + { + sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", i->spellInfo->Id,(isVictim?"a victim's":"an attacker's"),i->triggeredByAura->GetId()); + casted = HandleOverrideClassScriptAuraProc(pTarget, i->spellParam, damage, i->triggeredByAura, procSpell,i->cooldown); + break; + } + default: + { + // nothing do, just charges counter + casted = true; + break; + } + } + + // Update charge (aura can be removed by triggers) + if(casted && triggeredByAuraWithCharges) + { + // need found aura (can be dropped by triggers) + AuraMap::const_iterator lower = GetAuras().lower_bound(i->triggeredByAura_SpellPair); + AuraMap::const_iterator upper = GetAuras().upper_bound(i->triggeredByAura_SpellPair); + for(AuraMap::const_iterator itr = lower; itr!= upper; ++itr) + { + if(itr->second == i->triggeredByAura) + { + if(i->triggeredByAura->m_procCharges > 0) + i->triggeredByAura->m_procCharges -= 1; + + i->triggeredByAura->UpdateAuraCharges(); + break; + } + } + } + } + + // Safely remove auras with zero charges + for(AuraList::const_iterator i = auras.begin(), next; i != auras.end(); i = next) + { + next = i; ++next; + if((*i)->m_procCharges == 0) + { + RemoveAurasDueToSpell((*i)->GetId()); + next = auras.begin(); + } + } + } +} + +SpellSchoolMask Unit::GetMeleeDamageSchoolMask() const +{ + return SPELL_SCHOOL_MASK_NORMAL; +} + +Player* Unit::GetSpellModOwner() +{ + if(GetTypeId()==TYPEID_PLAYER) + return (Player*)this; + if(((Creature*)this)->isPet() || ((Creature*)this)->isTotem()) + { + Unit* owner = GetOwner(); + if(owner && owner->GetTypeId()==TYPEID_PLAYER) + return (Player*)owner; + } + return NULL; +} + +///----------Pet responses methods----------------- +void Unit::SendPetCastFail(uint32 spellid, uint8 msg) +{ + Unit *owner = GetCharmerOrOwner(); + if(!owner || owner->GetTypeId() != TYPEID_PLAYER) + return; + + WorldPacket data(SMSG_PET_CAST_FAILED, (4+1)); + data << uint32(spellid); + data << uint8(msg); + ((Player*)owner)->GetSession()->SendPacket(&data); +} + +void Unit::SendPetActionFeedback (uint8 msg) +{ + Unit* owner = GetOwner(); + if(!owner || owner->GetTypeId() != TYPEID_PLAYER) + return; + + WorldPacket data(SMSG_PET_ACTION_FEEDBACK, 1); + data << uint8(msg); + ((Player*)owner)->GetSession()->SendPacket(&data); +} + +void Unit::SendPetTalk (uint32 pettalk) +{ + Unit* owner = GetOwner(); + if(!owner || owner->GetTypeId() != TYPEID_PLAYER) + return; + + WorldPacket data(SMSG_PET_ACTION_SOUND, 8+4); + data << uint64(GetGUID()); + data << uint32(pettalk); + ((Player*)owner)->GetSession()->SendPacket(&data); +} + +void Unit::SendPetSpellCooldown (uint32 spellid, time_t cooltime) +{ + Unit* owner = GetOwner(); + if(!owner || owner->GetTypeId() != TYPEID_PLAYER) + return; + + WorldPacket data(SMSG_SPELL_COOLDOWN, 8+1+4+4); + data << uint64(GetGUID()); + data << uint8(0x0); + data << uint32(spellid); + data << uint32(cooltime); + + ((Player*)owner)->GetSession()->SendPacket(&data); +} + +void Unit::SendPetClearCooldown (uint32 spellid) +{ + Unit* owner = GetOwner(); + if(!owner || owner->GetTypeId() != TYPEID_PLAYER) + return; + + WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8)); + data << uint32(spellid); + data << uint64(GetGUID()); + ((Player*)owner)->GetSession()->SendPacket(&data); +} + +void Unit::SendPetAIReaction(uint64 guid) +{ + Unit* owner = GetOwner(); + if(!owner || owner->GetTypeId() != TYPEID_PLAYER) + return; + + WorldPacket data(SMSG_AI_REACTION, 12); + data << uint64(guid) << uint32(00000002); + ((Player*)owner)->GetSession()->SendPacket(&data); +} + +///----------End of Pet responses methods---------- + +void Unit::StopMoving() +{ + clearUnitState(UNIT_STAT_MOVING); + + // send explicit stop packet + // rely on vmaps here because for exemple stormwind is in air + float z = MapManager::Instance().GetBaseMap(GetMapId())->GetHeight(GetPositionX(), GetPositionY(), GetPositionZ(), true); + //if (fabs(GetPositionZ() - z) < 2.0f) + // Relocate(GetPositionX(), GetPositionY(), z); + Relocate(GetPositionX(), GetPositionY(),GetPositionZ()); + + SendMonsterMove(GetPositionX(), GetPositionY(), GetPositionZ(), 0, true, 0); + + // update position and orientation; + WorldPacket data; + BuildHeartBeatMsg(&data); + SendMessageToSet(&data,false); +} + +void Unit::SetFeared(bool apply, uint64 casterGUID, uint32 spellID) +{ + if( apply ) + { + if(HasAuraType(SPELL_AURA_PREVENTS_FLEEING)) + return; + + SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); + + GetMotionMaster()->MovementExpired(false); + CastStop(GetGUID()==casterGUID ? spellID : 0); + + Unit* caster = ObjectAccessor::GetUnit(*this,casterGUID); + + GetMotionMaster()->MoveFleeing(caster); // caster==NULL processed in MoveFleeing + } + else + { + RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); + + GetMotionMaster()->MovementExpired(false); + + if( GetTypeId() != TYPEID_PLAYER && isAlive() ) + { + // restore appropriate movement generator + if(getVictim()) + GetMotionMaster()->MoveChase(getVictim()); + else + GetMotionMaster()->Initialize(); + + // attack caster if can + Unit* caster = ObjectAccessor::GetObjectInWorld(casterGUID, (Unit*)NULL); + if(caster && caster != getVictim() && ((Creature*)this)->AI()) + ((Creature*)this)->AI()->AttackStart(caster); + } + } + + if (GetTypeId() == TYPEID_PLAYER) + ((Player*)this)->SetClientControl(this, !apply); +} + +void Unit::SetConfused(bool apply, uint64 casterGUID, uint32 spellID) +{ + if( apply ) + { + SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED); + + CastStop(GetGUID()==casterGUID ? spellID : 0); + + GetMotionMaster()->MoveConfused(); + } + else + { + RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED); + + GetMotionMaster()->MovementExpired(false); + + if (GetTypeId() == TYPEID_UNIT) + { + // if in combat restore movement generator + if(getVictim()) + GetMotionMaster()->MoveChase(getVictim()); + } + } + + if(GetTypeId() == TYPEID_PLAYER) + ((Player*)this)->SetClientControl(this, !apply); +} + +bool Unit::IsSitState() const +{ + uint8 s = getStandState(); + return s == PLAYER_STATE_SIT_CHAIR || s == PLAYER_STATE_SIT_LOW_CHAIR || + s == PLAYER_STATE_SIT_MEDIUM_CHAIR || s == PLAYER_STATE_SIT_HIGH_CHAIR || + s == PLAYER_STATE_SIT; +} + +bool Unit::IsStandState() const +{ + uint8 s = getStandState(); + return !IsSitState() && s != PLAYER_STATE_SLEEP && s != PLAYER_STATE_KNEEL; +} + +void Unit::SetStandState(uint8 state) +{ + SetByteValue(UNIT_FIELD_BYTES_1, 0, state); + + if (IsStandState()) + RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_NOT_SEATED); + + if(GetTypeId()==TYPEID_PLAYER) + { + WorldPacket data(SMSG_STANDSTATE_UPDATE, 1); + data << (uint8)state; + ((Player*)this)->GetSession()->SendPacket(&data); + } +} + +bool Unit::IsPolymorphed() const +{ + return GetSpellSpecific(getTransForm())==SPELL_MAGE_POLYMORPH; +} + +void Unit::SetDisplayId(uint32 modelId) +{ + SetUInt32Value(UNIT_FIELD_DISPLAYID, modelId); + + if(GetTypeId() == TYPEID_UNIT && ((Creature*)this)->isPet()) + { + Pet *pet = ((Pet*)this); + if(!pet->isControlled()) + return; + Unit *owner = GetOwner(); + if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup()) + ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MODEL_ID); + } +} + +void Unit::ClearComboPointHolders() +{ + while(!m_ComboPointHolders.empty()) + { + uint32 lowguid = *m_ComboPointHolders.begin(); + + Player* plr = objmgr.GetPlayer(MAKE_NEW_GUID(lowguid, 0, HIGHGUID_PLAYER)); + if(plr && plr->GetComboTarget()==GetGUID()) // recheck for safe + plr->ClearComboPoints(); // remove also guid from m_ComboPointHolders; + else + m_ComboPointHolders.erase(lowguid); // or remove manually + } +} + +void Unit::ClearAllReactives() +{ + + for(int i=0; i < MAX_REACTIVE; ++i) + m_reactiveTimer[i] = 0; + + if (HasAuraState( AURA_STATE_DEFENSE)) + ModifyAuraState(AURA_STATE_DEFENSE, false); + if (getClass() == CLASS_HUNTER && HasAuraState( AURA_STATE_HUNTER_PARRY)) + ModifyAuraState(AURA_STATE_HUNTER_PARRY, false); + if (HasAuraState( AURA_STATE_CRIT)) + ModifyAuraState(AURA_STATE_CRIT, false); + if (getClass() == CLASS_HUNTER && HasAuraState( AURA_STATE_HUNTER_CRIT_STRIKE) ) + ModifyAuraState(AURA_STATE_HUNTER_CRIT_STRIKE, false); + + if(getClass() == CLASS_WARRIOR && GetTypeId() == TYPEID_PLAYER) + ((Player*)this)->ClearComboPoints(); +} + +void Unit::UpdateReactives( uint32 p_time ) +{ + for(int i = 0; i < MAX_REACTIVE; ++i) + { + ReactiveType reactive = ReactiveType(i); + + if(!m_reactiveTimer[reactive]) + continue; + + if ( m_reactiveTimer[reactive] <= p_time) + { + m_reactiveTimer[reactive] = 0; + + switch ( reactive ) + { + case REACTIVE_DEFENSE: + if (HasAuraState(AURA_STATE_DEFENSE)) + ModifyAuraState(AURA_STATE_DEFENSE, false); + break; + case REACTIVE_HUNTER_PARRY: + if ( getClass() == CLASS_HUNTER && HasAuraState(AURA_STATE_HUNTER_PARRY)) + ModifyAuraState(AURA_STATE_HUNTER_PARRY, false); + break; + case REACTIVE_CRIT: + if (HasAuraState(AURA_STATE_CRIT)) + ModifyAuraState(AURA_STATE_CRIT, false); + break; + case REACTIVE_HUNTER_CRIT: + if ( getClass() == CLASS_HUNTER && HasAuraState(AURA_STATE_HUNTER_CRIT_STRIKE) ) + ModifyAuraState(AURA_STATE_HUNTER_CRIT_STRIKE, false); + break; + case REACTIVE_OVERPOWER: + if(getClass() == CLASS_WARRIOR && GetTypeId() == TYPEID_PLAYER) + ((Player*)this)->ClearComboPoints(); + break; + default: + break; + } + } + else + { + m_reactiveTimer[reactive] -= p_time; + } + } +} + +Unit* Unit::SelectNearbyTarget() const +{ + CellPair p(MaNGOS::ComputeCellPair(GetPositionX(), GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + std::list targets; + + { + MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck u_check(this, this, ATTACK_DISTANCE); + MaNGOS::UnitListSearcher searcher(targets, u_check); + + TypeContainerVisitor, WorldTypeMapContainer > world_unit_searcher(searcher); + TypeContainerVisitor, GridTypeMapContainer > grid_unit_searcher(searcher); + + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, world_unit_searcher, *MapManager::Instance().GetMap(GetMapId(), this)); + cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::Instance().GetMap(GetMapId(), this)); + } + + // remove current target + if(getVictim()) + targets.remove(getVictim()); + + // remove not LoS targets + for(std::list::iterator tIter = targets.begin(); tIter != targets.end();) + { + if(!IsWithinLOSInMap(*tIter)) + { + std::list::iterator tIter2 = tIter; + ++tIter; + targets.erase(tIter2); + } + else + ++tIter; + } + + // no appropriate targets + if(targets.empty()) + return NULL; + + // select random + uint32 rIdx = urand(0,targets.size()-1); + std::list::const_iterator tcIter = targets.begin(); + for(uint32 i = 0; i < rIdx; ++i) + ++tcIter; + + return *tcIter; +} + +void Unit::ApplyAttackTimePercentMod( WeaponAttackType att,float val, bool apply ) +{ + if(val > 0) + { + ApplyPercentModFloatVar(m_modAttackSpeedPct[att], val, !apply); + ApplyPercentModFloatValue(UNIT_FIELD_BASEATTACKTIME+att,val,!apply); + } + else + { + ApplyPercentModFloatVar(m_modAttackSpeedPct[att], -val, apply); + ApplyPercentModFloatValue(UNIT_FIELD_BASEATTACKTIME+att,-val,apply); + } +} + +void Unit::ApplyCastTimePercentMod(float val, bool apply ) +{ + if(val > 0) + ApplyPercentModFloatValue(UNIT_MOD_CAST_SPEED,val,!apply); + else + ApplyPercentModFloatValue(UNIT_MOD_CAST_SPEED,-val,apply); +} + +uint32 Unit::GetCastingTimeForBonus( SpellEntry const *spellProto, DamageEffectType damagetype, uint32 CastingTime ) +{ + if (CastingTime > 7000) CastingTime = 7000; + if (CastingTime < 1500) CastingTime = 1500; + + if(damagetype == DOT && !IsChanneledSpell(spellProto)) + CastingTime = 3500; + + int32 overTime = 0; + uint8 effects = 0; + bool DirectDamage = false; + bool AreaEffect = false; + + for ( uint32 i=0; i<3;i++) + { + switch ( spellProto->Effect[i] ) + { + case SPELL_EFFECT_SCHOOL_DAMAGE: + case SPELL_EFFECT_POWER_DRAIN: + case SPELL_EFFECT_HEALTH_LEECH: + case SPELL_EFFECT_ENVIRONMENTAL_DAMAGE: + case SPELL_EFFECT_POWER_BURN: + case SPELL_EFFECT_HEAL: + DirectDamage = true; + break; + case SPELL_EFFECT_APPLY_AURA: + switch ( spellProto->EffectApplyAuraName[i] ) + { + case SPELL_AURA_PERIODIC_DAMAGE: + case SPELL_AURA_PERIODIC_HEAL: + case SPELL_AURA_PERIODIC_LEECH: + if ( GetSpellDuration(spellProto) ) + overTime = GetSpellDuration(spellProto); + break; + default: + // -5% per additional effect + ++effects; + break; + } + default: + break; + } + + if(IsAreaEffectTarget(Targets(spellProto->EffectImplicitTargetA[i])) || IsAreaEffectTarget(Targets(spellProto->EffectImplicitTargetB[i]))) + AreaEffect = true; + } + + // Combined Spells with Both Over Time and Direct Damage + if ( overTime > 0 && CastingTime > 0 && DirectDamage ) + { + // mainly for DoTs which are 3500 here otherwise + uint32 OriginalCastTime = GetSpellCastTime(spellProto); + if (OriginalCastTime > 7000) OriginalCastTime = 7000; + if (OriginalCastTime < 1500) OriginalCastTime = 1500; + // Portion to Over Time + float PtOT = (overTime / 15000.f) / ((overTime / 15000.f) + (OriginalCastTime / 3500.f)); + + if ( damagetype == DOT ) + CastingTime = uint32(CastingTime * PtOT); + else if ( PtOT < 1.0f ) + CastingTime = uint32(CastingTime * (1 - PtOT)); + else + CastingTime = 0; + } + + // Area Effect Spells receive only half of bonus + if ( AreaEffect ) + CastingTime /= 2; + + // -5% of total per any additional effect + for ( uint8 i=0; i 175 ) + { + CastingTime -= 175; + } + else + { + CastingTime = 0; + break; + } + } + + return CastingTime; +} + +void Unit::UpdateAuraForGroup(uint8 slot) +{ + if(GetTypeId() == TYPEID_PLAYER) + { + Player* player = (Player*)this; + if(player->GetGroup()) + { + player->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_AURAS); + player->SetAuraUpdateMask(slot); + } + } + else if(GetTypeId() == TYPEID_UNIT && ((Creature*)this)->isPet()) + { + Pet *pet = ((Pet*)this); + if(pet->isControlled()) + { + Unit *owner = GetOwner(); + if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup()) + { + ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_AURAS); + pet->SetAuraUpdateMask(slot); + } + } + } +} + +float Unit::GetAPMultiplier(WeaponAttackType attType, bool normalized) +{ + if (!normalized || GetTypeId() != TYPEID_PLAYER) + return float(GetAttackTime(attType))/1000.0f; + + Item *Weapon = ((Player*)this)->GetWeaponForAttack(attType); + if (!Weapon) + return 2.4; // fist attack + + switch (Weapon->GetProto()->InventoryType) + { + case INVTYPE_2HWEAPON: + return 3.3; + case INVTYPE_RANGED: + case INVTYPE_RANGEDRIGHT: + case INVTYPE_THROWN: + return 2.8; + case INVTYPE_WEAPON: + case INVTYPE_WEAPONMAINHAND: + case INVTYPE_WEAPONOFFHAND: + default: + return Weapon->GetProto()->SubClass==ITEM_SUBCLASS_WEAPON_DAGGER ? 1.7 : 2.4; + } +} + +Aura* Unit::GetDummyAura( uint32 spell_id ) const +{ + Unit::AuraList const& mDummy = GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraList::const_iterator itr = mDummy.begin(); itr != mDummy.end(); ++itr) + if ((*itr)->GetId() == spell_id) + return *itr; + + return NULL; +} + +bool Unit::IsUnderLastManaUseEffect() const +{ + return getMSTimeDiff(m_lastManaUse,getMSTime()) < 5000; +} + +void Unit::SetContestedPvP(Player *attackedPlayer) +{ + Player* player = GetCharmerOrOwnerPlayerOrPlayerItself(); + + if(!player || attackedPlayer && (attackedPlayer == player || player->duel && player->duel->opponent == attackedPlayer)) + return; + + player->SetContestedPvPTimer(30000); + if(!player->hasUnitState(UNIT_STAT_ATTACK_PLAYER)) + { + player->addUnitState(UNIT_STAT_ATTACK_PLAYER); + player->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP); + // call MoveInLineOfSight for nearby contested guards + SetVisibility(GetVisibility()); + } + if(!hasUnitState(UNIT_STAT_ATTACK_PLAYER)) + { + addUnitState(UNIT_STAT_ATTACK_PLAYER); + // call MoveInLineOfSight for nearby contested guards + SetVisibility(GetVisibility()); + } +} + +void Unit::AddPetAura(PetAura const* petSpell) +{ + m_petAuras.insert(petSpell); + if(Pet* pet = GetPet()) + pet->CastPetAura(petSpell); +} + +void Unit::RemovePetAura(PetAura const* petSpell) +{ + m_petAuras.erase(petSpell); + if(Pet* pet = GetPet()) + pet->RemoveAurasDueToSpell(petSpell->GetAura(pet->GetEntry())); +} diff --git a/src/game/Unit.h b/src/game/Unit.h new file mode 100644 index 00000000000..b16b5e9ab2d --- /dev/null +++ b/src/game/Unit.h @@ -0,0 +1,1331 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __UNIT_H +#define __UNIT_H + +#include "Common.h" +#include "Object.h" +#include "Opcodes.h" +#include "Mthread.h" +#include "SpellAuraDefines.h" +#include "UpdateFields.h" +#include "SharedDefines.h" +#include "ThreatManager.h" +#include "HostilRefManager.h" +#include "FollowerReference.h" +#include "FollowerRefManager.h" +#include "Utilities/EventProcessor.h" +#include "MotionMaster.h" +#include "Database/DBCStructure.h" +#include + +enum SpellInterruptFlags +{ + SPELL_INTERRUPT_FLAG_MOVEMENT = 0x01, + SPELL_INTERRUPT_FLAG_DAMAGE = 0x02, + SPELL_INTERRUPT_FLAG_INTERRUPT = 0x04, + SPELL_INTERRUPT_FLAG_AUTOATTACK = 0x08, + //SPELL_INTERRUPT_FLAG_TURNING = 0x10 // not turning - maybe _complete_ interrupt on direct damage? +}; + +enum SpellChannelInterruptFlags +{ + CHANNEL_FLAG_DAMAGE = 0x0002, + CHANNEL_FLAG_MOVEMENT = 0x0008, + CHANNEL_FLAG_TURNING = 0x0010, + CHANNEL_FLAG_DAMAGE2 = 0x0080, + CHANNEL_FLAG_DELAY = 0x4000 +}; + +enum SpellAuraInterruptFlags +{ + AURA_INTERRUPT_FLAG_UNK0 = 0x00000001, // 0 removed when getting hit by a negative spell? + AURA_INTERRUPT_FLAG_DAMAGE = 0x00000002, // 1 removed by any damage + AURA_INTERRUPT_FLAG_UNK2 = 0x00000004, // 2 + AURA_INTERRUPT_FLAG_MOVE = 0x00000008, // 3 removed by any movement + AURA_INTERRUPT_FLAG_TURNING = 0x00000010, // 4 removed by any turning + AURA_INTERRUPT_FLAG_ENTER_COMBAT = 0x00000020, // 5 removed by entering combat + AURA_INTERRUPT_FLAG_NOT_MOUNTED = 0x00000040, // 6 removed by unmounting + AURA_INTERRUPT_FLAG_NOT_ABOVEWATER = 0x00000080, // 7 removed by entering water + AURA_INTERRUPT_FLAG_NOT_UNDERWATER = 0x00000100, // 8 removed by leaving water + AURA_INTERRUPT_FLAG_NOT_SHEATHED = 0x00000200, // 9 removed by unsheathing + AURA_INTERRUPT_FLAG_UNK10 = 0x00000400, // 10 + AURA_INTERRUPT_FLAG_UNK11 = 0x00000800, // 11 + AURA_INTERRUPT_FLAG_UNK12 = 0x00001000, // 12 removed by attack? + AURA_INTERRUPT_FLAG_UNK13 = 0x00002000, // 13 + AURA_INTERRUPT_FLAG_UNK14 = 0x00004000, // 14 + AURA_INTERRUPT_FLAG_UNK15 = 0x00008000, // 15 removed by casting a spell? + AURA_INTERRUPT_FLAG_UNK16 = 0x00010000, // 16 + AURA_INTERRUPT_FLAG_MOUNTING = 0x00020000, // 17 removed by mounting + AURA_INTERRUPT_FLAG_NOT_SEATED = 0x00040000, // 18 removed by standing up + AURA_INTERRUPT_FLAG_CHANGE_MAP = 0x00080000, // 19 leaving map/getting teleported + AURA_INTERRUPT_FLAG_UNK20 = 0x00100000, // 20 + AURA_INTERRUPT_FLAG_UNK21 = 0x00200000, // 21 + AURA_INTERRUPT_FLAG_UNK22 = 0x00400000, // 22 + AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT = 0x00800000, // 23 removed by entering pvp combat + AURA_INTERRUPT_FLAG_DIRECT_DAMAGE = 0x01000000 // 24 removed by any direct damage +}; + +enum SpellModOp +{ + SPELLMOD_DAMAGE = 0, + SPELLMOD_DURATION = 1, + SPELLMOD_THREAT = 2, + SPELLMOD_EFFECT1 = 3, + SPELLMOD_CHARGES = 4, + SPELLMOD_RANGE = 5, + SPELLMOD_RADIUS = 6, + SPELLMOD_CRITICAL_CHANCE = 7, + SPELLMOD_ALL_EFFECTS = 8, + SPELLMOD_NOT_LOSE_CASTING_TIME = 9, + SPELLMOD_CASTING_TIME = 10, + SPELLMOD_COOLDOWN = 11, + SPELLMOD_EFFECT2 = 12, + // spellmod 13 unused + SPELLMOD_COST = 14, + SPELLMOD_CRIT_DAMAGE_BONUS = 15, + SPELLMOD_RESIST_MISS_CHANCE = 16, + SPELLMOD_JUMP_TARGETS = 17, + SPELLMOD_CHANCE_OF_SUCCESS = 18, + SPELLMOD_ACTIVATION_TIME = 19, + SPELLMOD_EFFECT_PAST_FIRST = 20, + SPELLMOD_CASTING_TIME_OLD = 21, + SPELLMOD_DOT = 22, + SPELLMOD_EFFECT3 = 23, + SPELLMOD_SPELL_BONUS_DAMAGE = 24, + // spellmod 25, 26 unused + SPELLMOD_MULTIPLE_VALUE = 27, + SPELLMOD_RESIST_DISPEL_CHANCE = 28 +}; + +#define MAX_SPELLMOD 32 + +#define BASE_MINDAMAGE 1.0f +#define BASE_MAXDAMAGE 2.0f +#define BASE_ATTACK_TIME 2000 + +// high byte (3 from 0..3) of UNIT_FIELD_BYTES_2 +enum ShapeshiftForm +{ + FORM_NONE = 0x00, + FORM_CAT = 0x01, + FORM_TREE = 0x02, + FORM_TRAVEL = 0x03, + FORM_AQUA = 0x04, + FORM_BEAR = 0x05, + FORM_AMBIENT = 0x06, + FORM_GHOUL = 0x07, + FORM_DIREBEAR = 0x08, + FORM_CREATUREBEAR = 0x0E, + FORM_CREATURECAT = 0x0F, + FORM_GHOSTWOLF = 0x10, + FORM_BATTLESTANCE = 0x11, + FORM_DEFENSIVESTANCE = 0x12, + FORM_BERSERKERSTANCE = 0x13, + FORM_TEST = 0x14, + FORM_ZOMBIE = 0x15, + FORM_FLIGHT_EPIC = 0x1B, + FORM_SHADOW = 0x1C, + FORM_FLIGHT = 0x1D, + FORM_STEALTH = 0x1E, + FORM_MOONKIN = 0x1F, + FORM_SPIRITOFREDEMPTION = 0x20 +}; + +// low byte ( 0 from 0..3 ) of UNIT_FIELD_BYTES_2 +enum SheathState +{ + SHEATH_STATE_UNARMED = 0, // non prepared weapon + SHEATH_STATE_MELEE = 1, // prepared melee weapon + SHEATH_STATE_RANGED = 2 // prepared ranged weapon +}; + +// byte (1 from 0..3) of UNIT_FIELD_BYTES_2 +enum UnitBytes2_Flags +{ + UNIT_BYTE2_FLAG_UNK0 = 0x01, + UNIT_BYTE2_FLAG_UNK1 = 0x02, + UNIT_BYTE2_FLAG_UNK2 = 0x04, + UNIT_BYTE2_FLAG_UNK3 = 0x08, + UNIT_BYTE2_FLAG_AURAS = 0x10, // show possitive auras as positive, and allow its dispel + UNIT_BYTE2_FLAG_UNK5 = 0x20, + UNIT_BYTE2_FLAG_UNK6 = 0x40, + UNIT_BYTE2_FLAG_UNK7 = 0x80 +}; + +// byte (2 from 0..3) of UNIT_FIELD_BYTES_2 +enum UnitRename +{ + UNIT_RENAME_NOT_ALLOWED = 0x02, + UNIT_RENAME_ALLOWED = 0x03 +}; + +#define CREATURE_MAX_SPELLS 4 + +enum Swing +{ + NOSWING = 0, + SINGLEHANDEDSWING = 1, + TWOHANDEDSWING = 2 +}; + +enum VictimState +{ + VICTIMSTATE_UNKNOWN1 = 0, + VICTIMSTATE_NORMAL = 1, + VICTIMSTATE_DODGE = 2, + VICTIMSTATE_PARRY = 3, + VICTIMSTATE_INTERRUPT = 4, + VICTIMSTATE_BLOCKS = 5, + VICTIMSTATE_EVADES = 6, + VICTIMSTATE_IS_IMMUNE = 7, + VICTIMSTATE_DEFLECTS = 8 +}; + +enum HitInfo +{ + HITINFO_NORMALSWING = 0x00000000, + HITINFO_UNK1 = 0x00000001, // req correct packet structure + HITINFO_NORMALSWING2 = 0x00000002, + HITINFO_LEFTSWING = 0x00000004, + HITINFO_MISS = 0x00000010, + HITINFO_ABSORB = 0x00000020, // plays absorb sound + HITINFO_RESIST = 0x00000040, // resisted atleast some damage + HITINFO_CRITICALHIT = 0x00000080, + HITINFO_GLANCING = 0x00004000, + HITINFO_CRUSHING = 0x00008000, + HITINFO_NOACTION = 0x00010000, + HITINFO_SWINGNOHITSOUND = 0x00080000 +}; + +//i would like to remove this: (it is defined in item.h +enum InventorySlot +{ + NULL_BAG = 0, + NULL_SLOT = 255 +}; + +struct FactionTemplateEntry; +struct Modifier; +struct SpellEntry; +struct SpellEntryExt; + +class Aura; +class Creature; +class Spell; +class DynamicObject; +class GameObject; +class Item; +class Pet; +class Path; +class PetAura; + +struct SpellImmune +{ + uint32 type; + uint32 spellId; +}; + +typedef std::list SpellImmuneList; + +enum UnitModifierType +{ + BASE_VALUE = 0, + BASE_PCT = 1, + TOTAL_VALUE = 2, + TOTAL_PCT = 3, + MODIFIER_TYPE_END = 4 +}; + +enum WeaponDamageRange +{ + MINDAMAGE, + MAXDAMAGE +}; + +enum DamageTypeToSchool +{ + RESISTANCE, + DAMAGE_DEALT, + DAMAGE_TAKEN +}; + +enum AuraRemoveMode +{ + AURA_REMOVE_BY_DEFAULT, + AURA_REMOVE_BY_STACK, // at replace by semillar aura + AURA_REMOVE_BY_CANCEL, + AURA_REMOVE_BY_DISPEL, + AURA_REMOVE_BY_DEATH +}; + +enum UnitMods +{ + UNIT_MOD_STAT_STRENGTH, // UNIT_MOD_STAT_STRENGTH..UNIT_MOD_STAT_SPIRIT must be in existed order, it's accessed by index values of Stats enum. + UNIT_MOD_STAT_AGILITY, + UNIT_MOD_STAT_STAMINA, + UNIT_MOD_STAT_INTELLECT, + UNIT_MOD_STAT_SPIRIT, + UNIT_MOD_HEALTH, + UNIT_MOD_MANA, // UNIT_MOD_MANA..UNIT_MOD_HAPPINESS must be in existed order, it's accessed by index values of Powers enum. + UNIT_MOD_RAGE, + UNIT_MOD_FOCUS, + UNIT_MOD_ENERGY, + UNIT_MOD_HAPPINESS, + UNIT_MOD_ARMOR, // UNIT_MOD_ARMOR..UNIT_MOD_RESISTANCE_ARCANE must be in existed order, it's accessed by index values of SpellSchools enum. + UNIT_MOD_RESISTANCE_HOLY, + UNIT_MOD_RESISTANCE_FIRE, + UNIT_MOD_RESISTANCE_NATURE, + UNIT_MOD_RESISTANCE_FROST, + UNIT_MOD_RESISTANCE_SHADOW, + UNIT_MOD_RESISTANCE_ARCANE, + UNIT_MOD_ATTACK_POWER, + UNIT_MOD_ATTACK_POWER_RANGED, + UNIT_MOD_DAMAGE_MAINHAND, + UNIT_MOD_DAMAGE_OFFHAND, + UNIT_MOD_DAMAGE_RANGED, + UNIT_MOD_END, + // synonyms + UNIT_MOD_STAT_START = UNIT_MOD_STAT_STRENGTH, + UNIT_MOD_STAT_END = UNIT_MOD_STAT_SPIRIT + 1, + UNIT_MOD_RESISTANCE_START = UNIT_MOD_ARMOR, + UNIT_MOD_RESISTANCE_END = UNIT_MOD_RESISTANCE_ARCANE + 1, + UNIT_MOD_POWER_START = UNIT_MOD_MANA, + UNIT_MOD_POWER_END = UNIT_MOD_HAPPINESS + 1 +}; + +enum BaseModGroup +{ + CRIT_PERCENTAGE, + RANGED_CRIT_PERCENTAGE, + OFFHAND_CRIT_PERCENTAGE, + SHIELD_BLOCK_VALUE, + BASEMOD_END +}; + +enum BaseModType +{ + FLAT_MOD, + PCT_MOD +}; + +#define MOD_END (PCT_MOD+1) + +enum DeathState +{ + ALIVE = 0, + JUST_DIED = 1, + CORPSE = 2, + DEAD = 3, + JUST_ALIVED = 4 +}; + +enum UnitState +{ + UNIT_STAT_DIED = 0x0001, + UNIT_STAT_MELEE_ATTACKING = 0x0002, // player is melee attacking someone + //UNIT_STAT_MELEE_ATTACK_BY = 0x0004, // player is melee attack by someone + UNIT_STAT_STUNDED = 0x0008, + UNIT_STAT_ROAMING = 0x0010, + UNIT_STAT_CHASE = 0x0020, + UNIT_STAT_SEARCHING = 0x0040, + UNIT_STAT_FLEEING = 0x0080, + UNIT_STAT_MOVING = (UNIT_STAT_ROAMING | UNIT_STAT_CHASE | UNIT_STAT_SEARCHING | UNIT_STAT_FLEEING), + UNIT_STAT_IN_FLIGHT = 0x0100, // player is in flight mode + UNIT_STAT_FOLLOW = 0x0200, + UNIT_STAT_ROOT = 0x0400, + UNIT_STAT_CONFUSED = 0x0800, + UNIT_STAT_DISTRACTED = 0x1000, + UNIT_STAT_ISOLATED = 0x2000, // area auras do not affect other players + UNIT_STAT_ATTACK_PLAYER = 0x4000, + UNIT_STAT_ALL_STATE = 0xffff //(UNIT_STAT_STOPPED | UNIT_STAT_MOVING | UNIT_STAT_IN_COMBAT | UNIT_STAT_IN_FLIGHT) +}; + +enum UnitMoveType +{ + MOVE_WALK = 0, + MOVE_RUN = 1, + MOVE_WALKBACK = 2, + MOVE_SWIM = 3, + MOVE_SWIMBACK = 4, + MOVE_TURN = 5, + MOVE_FLY = 6, + MOVE_FLYBACK = 7 +}; + +#define MAX_MOVE_TYPE 8 + +extern float baseMoveSpeed[MAX_MOVE_TYPE]; + +enum WeaponAttackType +{ + BASE_ATTACK = 0, + OFF_ATTACK = 1, + RANGED_ATTACK = 2 +}; + +#define MAX_ATTACK 3 + +enum CombatRating +{ + CR_WEAPON_SKILL = 0, + CR_DEFENSE_SKILL = 1, + CR_DODGE = 2, + CR_PARRY = 3, + CR_BLOCK = 4, + CR_HIT_MELEE = 5, + CR_HIT_RANGED = 6, + CR_HIT_SPELL = 7, + CR_CRIT_MELEE = 8, + CR_CRIT_RANGED = 9, + CR_CRIT_SPELL = 10, + CR_HIT_TAKEN_MELEE = 11, + CR_HIT_TAKEN_RANGED = 12, + CR_HIT_TAKEN_SPELL = 13, + CR_CRIT_TAKEN_MELEE = 14, + CR_CRIT_TAKEN_RANGED = 15, + CR_CRIT_TAKEN_SPELL = 16, + CR_HASTE_MELEE = 17, + CR_HASTE_RANGED = 18, + CR_HASTE_SPELL = 19, + CR_WEAPON_SKILL_MAINHAND = 20, + CR_WEAPON_SKILL_OFFHAND = 21, + CR_WEAPON_SKILL_RANGED = 22, + CR_EXPERTISE = 23 +}; + +#define MAX_COMBAT_RATING 24 + +enum DamageEffectType +{ + DIRECT_DAMAGE = 0, // used for normal weapon damage (not for class abilities or spells) + SPELL_DIRECT_DAMAGE = 1, // spell/class abilities damage + DOT = 2, + HEAL = 3, + NODAMAGE = 4, // used also in case when damage applied to health but not applied to spell channelInterruptFlags/etc + SELF_DAMAGE = 5 +}; + +enum UnitVisibility +{ + VISIBILITY_OFF = 0, // absolute, not detectable, GM-like, can see all other + VISIBILITY_ON = 1, + VISIBILITY_GROUP_STEALTH = 2, // detect chance, seen and can see group members + VISIBILITY_GROUP_INVISIBILITY = 3, // invisibility, can see and can be seen only another invisible unit or invisible detection unit, set only if not stealthed, and in checks not used (mask used instead) + VISIBILITY_GROUP_NO_DETECT = 4, // state just at stealth apply for update Grid state. Don't remove, otherwise stealth spells will break + VISIBILITY_RESPAWN = 5 // special totally not detectable visibility for force delete object at respawn command +}; + +// Value masks for UNIT_FIELD_FLAGS +enum UnitFlags +{ + UNIT_FLAG_UNKNOWN7 = 0x00000001, + UNIT_FLAG_NON_ATTACKABLE = 0x00000002, // not attackable + UNIT_FLAG_DISABLE_MOVE = 0x00000004, + UNIT_FLAG_PVP_ATTACKABLE = 0x00000008, // allow apply pvp rules to attackable state in addition to faction dependent state + UNIT_FLAG_RENAME = 0x00000010, + UNIT_FLAG_PREPARATION = 0x00000020, // don't take reagents for spells with SPELL_ATTR_EX5_NO_REAGENT_WHILE_PREP + UNIT_FLAG_UNKNOWN9 = 0x00000040, + UNIT_FLAG_NOT_ATTACKABLE_1 = 0x00000080, // ?? (UNIT_FLAG_PVP_ATTACKABLE | UNIT_FLAG_NOT_ATTACKABLE_1) is NON_PVP_ATTACKABLE + UNIT_FLAG_UNKNOWN2 = 0x00000100, // 2.0.8 + UNIT_FLAG_UNKNOWN11 = 0x00000200, + UNIT_FLAG_LOOTING = 0x00000400, // loot animation + UNIT_FLAG_PET_IN_COMBAT = 0x00000800, // in combat?, 2.0.8 + UNIT_FLAG_PVP = 0x00001000, + UNIT_FLAG_SILENCED = 0x00002000, // silenced, 2.1.1 + UNIT_FLAG_UNKNOWN4 = 0x00004000, // 2.0.8 + UNIT_FLAG_UNKNOWN13 = 0x00008000, + UNIT_FLAG_UNKNOWN14 = 0x00010000, + UNIT_FLAG_PACIFIED = 0x00020000, + UNIT_FLAG_DISABLE_ROTATE = 0x00040000, // stunned, 2.1.1 + UNIT_FLAG_IN_COMBAT = 0x00080000, + UNIT_FLAG_TAXI_FLIGHT = 0x00100000, // disable casting at client side spell not allowed by taxi flight (mounted?), probably used with 0x4 flag + UNIT_FLAG_DISARMED = 0x00200000, // disable melee spells casting..., "Required melee weapon" added to melee spells tooltip. + UNIT_FLAG_CONFUSED = 0x00400000, + UNIT_FLAG_FLEEING = 0x00800000, + UNIT_FLAG_UNKNOWN5 = 0x01000000, // used in spell Eyes of the Beast for pet... + UNIT_FLAG_NOT_SELECTABLE = 0x02000000, + UNIT_FLAG_SKINNABLE = 0x04000000, + UNIT_FLAG_MOUNT = 0x08000000, + UNIT_FLAG_UNKNOWN17 = 0x10000000, + UNIT_FLAG_UNKNOWN6 = 0x20000000, // used in Feing Death spell + UNIT_FLAG_SHEATHE = 0x40000000 +}; + +// Value masks for UNIT_FIELD_FLAGS_2 +enum UnitFlags2 +{ + UNIT_FLAG2_FEIGN_DEATH = 0x00000001, + UNIT_FLAG2_COMPREHEND_LANG= 0x00000008, + UNIT_FLAG2_FORCE_MOVE = 0x00000040 +}; + +/// Non Player Character flags +enum NPCFlags +{ + UNIT_NPC_FLAG_NONE = 0x00000000, + UNIT_NPC_FLAG_GOSSIP = 0x00000001, // 100% + UNIT_NPC_FLAG_QUESTGIVER = 0x00000002, // guessed, probably ok + UNIT_NPC_FLAG_UNK1 = 0x00000004, + UNIT_NPC_FLAG_UNK2 = 0x00000008, + UNIT_NPC_FLAG_TRAINER = 0x00000010, // 100% + UNIT_NPC_FLAG_TRAINER_CLASS = 0x00000020, // 100% + UNIT_NPC_FLAG_TRAINER_PROFESSION = 0x00000040, // 100% + UNIT_NPC_FLAG_VENDOR = 0x00000080, // 100% + UNIT_NPC_FLAG_VENDOR_AMMO = 0x00000100, // 100%, general goods vendor + UNIT_NPC_FLAG_VENDOR_FOOD = 0x00000200, // 100% + UNIT_NPC_FLAG_VENDOR_POISON = 0x00000400, // guessed + UNIT_NPC_FLAG_VENDOR_REAGENT = 0x00000800, // 100% + UNIT_NPC_FLAG_REPAIR = 0x00001000, // 100% + UNIT_NPC_FLAG_FLIGHTMASTER = 0x00002000, // 100% + UNIT_NPC_FLAG_SPIRITHEALER = 0x00004000, // guessed + UNIT_NPC_FLAG_SPIRITGUIDE = 0x00008000, // guessed + UNIT_NPC_FLAG_INNKEEPER = 0x00010000, // 100% + UNIT_NPC_FLAG_BANKER = 0x00020000, // 100% + UNIT_NPC_FLAG_PETITIONER = 0x00040000, // 100% 0xC0000 = guild petitions, 0x40000 = arena team petitions + UNIT_NPC_FLAG_TABARDDESIGNER = 0x00080000, // 100% + UNIT_NPC_FLAG_BATTLEMASTER = 0x00100000, // 100% + UNIT_NPC_FLAG_AUCTIONEER = 0x00200000, // 100% + UNIT_NPC_FLAG_STABLEMASTER = 0x00400000, // 100% + UNIT_NPC_FLAG_GUILD_BANKER = 0x00800000, // cause client to send 997 opcode + UNIT_NPC_FLAG_UNK3 = 0x01000000, // cause client to send 1015 opcode + UNIT_NPC_FLAG_GUARD = 0x10000000, // custom flag for guards +}; + +enum MovementFlags +{ + MOVEMENTFLAG_NONE = 0x00000000, + MOVEMENTFLAG_FORWARD = 0x00000001, + MOVEMENTFLAG_BACKWARD = 0x00000002, + MOVEMENTFLAG_STRAFE_LEFT = 0x00000004, + MOVEMENTFLAG_STRAFE_RIGHT = 0x00000008, + MOVEMENTFLAG_LEFT = 0x00000010, + MOVEMENTFLAG_RIGHT = 0x00000020, + MOVEMENTFLAG_PITCH_UP = 0x00000040, + MOVEMENTFLAG_PITCH_DOWN = 0x00000080, + MOVEMENTFLAG_WALK_MODE = 0x00000100, // Walking + MOVEMENTFLAG_ONTRANSPORT = 0x00000200, // Used for flying on some creatures + MOVEMENTFLAG_LEVITATING = 0x00000400, + MOVEMENTFLAG_FLY_UNK1 = 0x00000800, + MOVEMENTFLAG_JUMPING = 0x00001000, + MOVEMENTFLAG_UNK4 = 0x00002000, + MOVEMENTFLAG_FALLING = 0x00004000, + // 0x8000, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000 + MOVEMENTFLAG_SWIMMING = 0x00200000, // appears with fly flag also + MOVEMENTFLAG_FLY_UP = 0x00400000, + MOVEMENTFLAG_CAN_FLY = 0x00800000, + MOVEMENTFLAG_FLYING = 0x01000000, + MOVEMENTFLAG_FLYING2 = 0x02000000, // Actual flying mode + MOVEMENTFLAG_SPLINE = 0x04000000, // used for flight paths + MOVEMENTFLAG_SPLINE2 = 0x08000000, // used for flight paths + MOVEMENTFLAG_WATERWALKING = 0x10000000, // prevent unit from falling through water + MOVEMENTFLAG_SAFE_FALL = 0x20000000, // active rogue safe fall spell (passive) + MOVEMENTFLAG_UNK3 = 0x40000000 +}; + +enum DiminishingLevels +{ + DIMINISHING_LEVEL_1 = 0, + DIMINISHING_LEVEL_2 = 1, + DIMINISHING_LEVEL_3 = 2, + DIMINISHING_LEVEL_IMMUNE = 3 +}; + +struct DiminishingReturn +{ + DiminishingReturn(DiminishingGroup group, uint32 t, uint32 count) : DRGroup(group), hitTime(t), hitCount(count), stack(0) {} + + DiminishingGroup DRGroup:16; + uint16 stack:16; + uint32 hitTime; + uint32 hitCount; +}; + +enum MeleeHitOutcome +{ + MELEE_HIT_EVADE, MELEE_HIT_MISS, MELEE_HIT_DODGE, MELEE_HIT_BLOCK, MELEE_HIT_PARRY, + MELEE_HIT_GLANCING, MELEE_HIT_CRIT, MELEE_HIT_CRUSHING, MELEE_HIT_NORMAL, MELEE_HIT_BLOCK_CRIT +}; +struct CleanDamage +{ + CleanDamage(uint32 _damage, WeaponAttackType _attackType, MeleeHitOutcome _hitOutCome) : + damage(_damage), attackType(_attackType), hitOutCome(_hitOutCome) {} + + uint32 damage; + WeaponAttackType attackType; + MeleeHitOutcome hitOutCome; +}; + +struct UnitActionBarEntry +{ + uint32 Type; + uint32 SpellOrAction; +}; + +#define MAX_DECLINED_NAME_CASES 5 + +struct DeclinedName +{ + std::string name[MAX_DECLINED_NAME_CASES]; +}; + +enum CurrentSpellTypes +{ + CURRENT_MELEE_SPELL = 0, + CURRENT_FIRST_NON_MELEE_SPELL = 1, // just counter + CURRENT_GENERIC_SPELL = 1, + CURRENT_AUTOREPEAT_SPELL = 2, + CURRENT_CHANNELED_SPELL = 3, + CURRENT_MAX_SPELL = 4 // just counter +}; + +enum ActiveStates +{ + ACT_ENABLED = 0xC100, + ACT_DISABLED = 0x8100, + ACT_COMMAND = 0x0700, + ACT_REACTION = 0x0600, + ACT_CAST = 0x0100, + ACT_PASSIVE = 0x0000, + ACT_DECIDE = 0x0001 +}; + +enum ReactStates +{ + REACT_PASSIVE = 0, + REACT_DEFENSIVE = 1, + REACT_AGGRESSIVE = 2 +}; + +enum CommandStates +{ + COMMAND_STAY = 0, + COMMAND_FOLLOW = 1, + COMMAND_ATTACK = 2, + COMMAND_ABANDON = 3 +}; + +struct CharmSpellEntry +{ + uint16 spellId; + uint16 active; +}; + +struct CharmInfo +{ + public: + explicit CharmInfo(Unit* unit); + uint32 GetPetNumber() const { return m_petnumber; } + void SetPetNumber(uint32 petnumber, bool statwindow); + + void SetCommandState(CommandStates st) { m_CommandState = st; } + CommandStates GetCommandState() { return m_CommandState; } + bool HasCommandState(CommandStates state) { return (m_CommandState == state); } + void SetReactState(ReactStates st) { m_ReactSate = st; } + ReactStates GetReactState() { return m_ReactSate; } + bool HasReactState(ReactStates state) { return (m_ReactSate == state); } + + void InitPossessCreateSpells(); + void InitCharmCreateSpells(); + void InitPetActionBar(); + void InitEmptyActionBar(); + //return true if successful + bool AddSpellToAB(uint32 oldid, uint32 newid, ActiveStates newstate = ACT_DECIDE); + void ToggleCreatureAutocast(uint32 spellid, bool apply); + + UnitActionBarEntry* GetActionBarEntry(uint8 index) { return &(PetActionBar[index]); } + CharmSpellEntry* GetCharmSpell(uint8 index) { return &(m_charmspells[index]); } + private: + Unit* m_unit; + UnitActionBarEntry PetActionBar[10]; + CharmSpellEntry m_charmspells[4]; + CommandStates m_CommandState; + ReactStates m_ReactSate; + uint32 m_petnumber; +}; + +// for clearing special attacks +#define REACTIVE_TIMER_START 4000 + +enum ReactiveType +{ + REACTIVE_DEFENSE = 1, + REACTIVE_HUNTER_PARRY = 2, + REACTIVE_CRIT = 3, + REACTIVE_HUNTER_CRIT = 4, + REACTIVE_OVERPOWER = 5 +}; + +#define MAX_REACTIVE 6 +#define MAX_TOTEM 4 + +// delay time next attack to prevent client attack animation problems +#define ATTACK_DISPLAY_DELAY 200 + +class MANGOS_DLL_SPEC Unit : public WorldObject +{ + public: + typedef std::set AttackerSet; + typedef std::pair spellEffectPair; + typedef std::multimap< spellEffectPair, Aura*> AuraMap; + typedef std::list AuraList; + typedef std::list Diminishing; + typedef std::set AuraTypeSet; + typedef std::set ComboPointHolderSet; + + virtual ~Unit ( ); + + void AddToWorld(); + void RemoveFromWorld(); + + void CleanupsBeforeDelete(); // used in ~Creature/~Player (or before mass creature delete to remove cross-references to already deleted units) + + DiminishingLevels GetDiminishing(DiminishingGroup group); + void IncrDiminishing(DiminishingGroup group); + void ApplyDiminishingToDuration(DiminishingGroup group, int32 &duration,Unit* caster, DiminishingLevels Level); + void ApplyDiminishingAura(DiminishingGroup group, bool apply); + void ClearDiminishings() { m_Diminishing.clear(); } + + virtual void Update( uint32 time ); + + void setAttackTimer(WeaponAttackType type, uint32 time) { m_attackTimer[type] = time; } + void resetAttackTimer(WeaponAttackType type = BASE_ATTACK); + uint32 getAttackTimer(WeaponAttackType type) const { return m_attackTimer[type]; } + bool isAttackReady(WeaponAttackType type = BASE_ATTACK) const { return m_attackTimer[type] == 0; } + bool haveOffhandWeapon() const; + bool canReachWithAttack(Unit *pVictim) const; + uint32 m_extraAttacks; + + void _addAttacker(Unit *pAttacker) // must be called only from Unit::Attack(Unit*) + { + AttackerSet::iterator itr = m_attackers.find(pAttacker); + if(itr == m_attackers.end()) + m_attackers.insert(pAttacker); + } + void _removeAttacker(Unit *pAttacker) // must be called only from Unit::AttackStop() + { + AttackerSet::iterator itr = m_attackers.find(pAttacker); + if(itr != m_attackers.end()) + m_attackers.erase(itr); + } + Unit * getAttackerForHelper() // If someone wants to help, who to give them + { + if (getVictim() != NULL) + return getVictim(); + + if (!m_attackers.empty()) + return *(m_attackers.begin()); + + return NULL; + } + bool Attack(Unit *victim, bool meleeAttack); + void CastStop(uint32 except_spellid = 0); + bool AttackStop(); + void RemoveAllAttackers(); + AttackerSet const& getAttackers() const { return m_attackers; } + bool isAttackingPlayer() const; + Unit* getVictim() const { return m_attacking; } + void CombatStop(bool cast = false); + void CombatStopWithPets(bool cast = false); + Unit* SelectNearbyTarget() const; + + void addUnitState(uint32 f) { m_state |= f; } + bool hasUnitState(const uint32 f) const { return (m_state & f); } + void clearUnitState(uint32 f) { m_state &= ~f; } + bool CanFreeMove() const + { + return !hasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING | UNIT_STAT_IN_FLIGHT | + UNIT_STAT_ROOT | UNIT_STAT_STUNDED | UNIT_STAT_DISTRACTED ) && GetOwnerGUID()==0; + } + + uint32 getLevel() const { return GetUInt32Value(UNIT_FIELD_LEVEL); } + virtual uint32 getLevelForTarget(Unit const* /*target*/) const { return getLevel(); } + void SetLevel(uint32 lvl); + uint8 getRace() const { return GetByteValue(UNIT_FIELD_BYTES_0, 0); } + uint32 getRaceMask() const { return 1 << (getRace()-1); } + uint8 getClass() const { return GetByteValue(UNIT_FIELD_BYTES_0, 1); } + uint32 getClassMask() const { return 1 << (getClass()-1); } + uint8 getGender() const { return GetByteValue(UNIT_FIELD_BYTES_0, 2); } + + float GetStat(Stats stat) const { return float(GetUInt32Value(UNIT_FIELD_STAT0+stat)); } + void SetStat(Stats stat, int32 val) { SetStatInt32Value(UNIT_FIELD_STAT0+stat, val); } + uint32 GetArmor() const { return GetResistance(SPELL_SCHOOL_NORMAL) ; } + void SetArmor(int32 val) { SetResistance(SPELL_SCHOOL_NORMAL, val); } + + uint32 GetResistance(SpellSchools school) const { return GetUInt32Value(UNIT_FIELD_RESISTANCES+school); } + void SetResistance(SpellSchools school, int32 val) { SetStatInt32Value(UNIT_FIELD_RESISTANCES+school,val); } + + uint32 GetHealth() const { return GetUInt32Value(UNIT_FIELD_HEALTH); } + uint32 GetMaxHealth() const { return GetUInt32Value(UNIT_FIELD_MAXHEALTH); } + void SetHealth( uint32 val); + void SetMaxHealth(uint32 val); + int32 ModifyHealth(int32 val); + + Powers getPowerType() const { return Powers(GetByteValue(UNIT_FIELD_BYTES_0, 3)); } + void setPowerType(Powers power); + uint32 GetPower( Powers power) const { return GetUInt32Value(UNIT_FIELD_POWER1 +power); } + uint32 GetMaxPower(Powers power) const { return GetUInt32Value(UNIT_FIELD_MAXPOWER1+power); } + void SetPower( Powers power, uint32 val); + void SetMaxPower(Powers power, uint32 val); + int32 ModifyPower(Powers power, int32 val); + void ApplyPowerMod(Powers power, uint32 val, bool apply); + void ApplyMaxPowerMod(Powers power, uint32 val, bool apply); + + uint32 GetAttackTime(WeaponAttackType att) const { return (uint32)(GetFloatValue(UNIT_FIELD_BASEATTACKTIME+att)/m_modAttackSpeedPct[att]); } + void SetAttackTime(WeaponAttackType att, uint32 val) { SetFloatValue(UNIT_FIELD_BASEATTACKTIME+att,val*m_modAttackSpeedPct[att]); } + void ApplyAttackTimePercentMod(WeaponAttackType att,float val, bool apply); + void ApplyCastTimePercentMod(float val, bool apply); + + // faction template id + uint32 getFaction() const { return GetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE); } + void setFaction(uint32 faction) { SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, faction ); } + FactionTemplateEntry const* getFactionTemplateEntry() const; + bool IsHostileTo(Unit const* unit) const; + bool IsHostileToPlayers() const; + bool IsFriendlyTo(Unit const* unit) const; + bool IsNeutralToAll() const; + bool IsContestedGuard() const + { + if(FactionTemplateEntry const* entry = getFactionTemplateEntry()) + return entry->IsContestedGuardFaction(); + + return false; + } + bool IsPvP() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP); } + void SetPvP(bool state) { if(state) SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP); else RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP); } + uint32 GetCreatureType() const; + uint32 GetCreatureTypeMask() const + { + uint32 creatureType = GetCreatureType(); + return (creatureType >= 1) ? (1 << (creatureType - 1)) : 0; + } + + uint8 getStandState() const { return GetByteValue(UNIT_FIELD_BYTES_1, 0); } + bool IsSitState() const; + bool IsStandState() const; + void SetStandState(uint8 state); + + bool IsMounted() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNT ); } + uint32 GetMountID() const { return GetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID); } + void Mount(uint32 mount); + void Unmount(); + + uint16 GetMaxSkillValueForLevel(Unit const* target = NULL) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; } + uint32 DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellEntry const *spellProto, bool durabilityLoss); + void DealFlatDamage(Unit *pVictim, SpellEntry const *spellInfo, uint32 *damage, CleanDamage *cleanDamage, bool *crit = false, bool isTriggeredSpell = false); + void DoAttackDamage(Unit *pVictim, uint32 *damage, CleanDamage *cleanDamage, uint32 *blocked_amount, SpellSchoolMask damageSchoolMask, uint32 *hitInfo, VictimState *victimState, uint32 *absorbDamage, uint32 *resistDamage, WeaponAttackType attType, SpellEntry const *spellCasted = NULL, bool isTriggeredSpell = false); + + void CastMeleeProcDamageAndSpell(Unit* pVictim, uint32 damage, SpellSchoolMask damageSchoolMask, WeaponAttackType attType, MeleeHitOutcome outcome, SpellEntry const *spellCasted = NULL, bool isTriggeredSpell = false); + void ProcDamageAndSpell(Unit *pVictim, uint32 procAttacker, uint32 procVictim, uint32 damage = 0, SpellSchoolMask damageSchoolMask = SPELL_SCHOOL_MASK_NONE, SpellEntry const *procSpell = NULL, bool isTriggeredSpell = false, WeaponAttackType attType = BASE_ATTACK); + void HandleEmoteCommand(uint32 anim_id); + void AttackerStateUpdate (Unit *pVictim, WeaponAttackType attType = BASE_ATTACK, bool extra = false ); + + float MeleeMissChanceCalc(const Unit *pVictim, WeaponAttackType attType) const; + SpellMissInfo MagicSpellHitResult(Unit *pVictim, SpellEntry const *spell); + SpellMissInfo SpellHitResult(Unit *pVictim, SpellEntry const *spell, bool canReflect = false); + + float GetUnitDodgeChance() const; + float GetUnitParryChance() const; + float GetUnitBlockChance() const; + float GetUnitCriticalChance(WeaponAttackType attackType, const Unit *pVictim) const; + + virtual uint32 GetShieldBlockValue() const =0; + uint32 GetUnitMeleeSkill(Unit const* target = NULL) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; } + uint32 GetDefenseSkillValue(Unit const* target = NULL) const; + uint32 GetWeaponSkillValue(WeaponAttackType attType, Unit const* target = NULL) const; + float GetWeaponProcChance() const; + float GetPPMProcChance(uint32 WeaponSpeed, float PPM) const; + MeleeHitOutcome RollPhysicalOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType, SpellEntry const *spellInfo); + MeleeHitOutcome RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType) const; + MeleeHitOutcome RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType, int32 crit_chance, int32 miss_chance, int32 dodge_chance, int32 parry_chance, int32 block_chance, bool SpellCasted ) const; + + bool isVendor() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_VENDOR ); } + bool isTrainer() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_TRAINER ); } + bool isQuestGiver() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER ); } + bool isGossip() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP ); } + bool isTaxi() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_FLIGHTMASTER ); } + bool isGuildMaster() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PETITIONER ); } + bool isBattleMaster() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_BATTLEMASTER ); } + bool isBanker() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_BANKER ); } + bool isInnkeeper() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_INNKEEPER ); } + bool isSpiritHealer() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPIRITHEALER ); } + bool isSpiritGuide() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPIRITGUIDE ); } + bool isTabardDesigner()const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_TABARDDESIGNER ); } + bool isAuctioner() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_AUCTIONEER ); } + bool isArmorer() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_REPAIR ); } + bool isServiceProvider() const + { + return HasFlag( UNIT_NPC_FLAGS, + UNIT_NPC_FLAG_VENDOR | UNIT_NPC_FLAG_TRAINER | UNIT_NPC_FLAG_FLIGHTMASTER | + UNIT_NPC_FLAG_PETITIONER | UNIT_NPC_FLAG_BATTLEMASTER | UNIT_NPC_FLAG_BANKER | + UNIT_NPC_FLAG_INNKEEPER | UNIT_NPC_FLAG_GUARD | UNIT_NPC_FLAG_SPIRITHEALER | + UNIT_NPC_FLAG_SPIRITGUIDE | UNIT_NPC_FLAG_TABARDDESIGNER | UNIT_NPC_FLAG_AUCTIONEER ); + } + bool isSpiritService() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPIRITHEALER | UNIT_NPC_FLAG_SPIRITGUIDE ); } + + //Need fix or use this + bool isGuard() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GUARD); } + + bool isInFlight() const { return hasUnitState(UNIT_STAT_IN_FLIGHT); } + + bool isInCombat() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); } + void SetInCombatState(bool PvP); + void SetInCombatWith(Unit* enemy); + void ClearInCombat(); + uint32 GetCombatTimer() const { return m_CombatTimer; } + + bool HasAuraType(AuraType auraType) const; + bool HasAura(uint32 spellId, uint32 effIndex) const + { return m_Auras.find(spellEffectPair(spellId, effIndex)) != m_Auras.end(); } + + bool virtual HasSpell(uint32 /*spellID*/) const { return false; } + + bool HasStealthAura() const { return HasAuraType(SPELL_AURA_MOD_STEALTH); } + bool HasInvisibilityAura() const { return HasAuraType(SPELL_AURA_MOD_INVISIBILITY); } + bool isFeared() const { return HasAuraType(SPELL_AURA_MOD_FEAR); } + bool isInRoots() const { return HasAuraType(SPELL_AURA_MOD_ROOT); } + bool IsPolymorphed() const; + + bool isFrozen() const; + + void RemoveSpellbyDamageTaken(AuraType auraType, uint32 damage); + + bool isTargetableForAttack() const; + virtual bool IsInWater() const; + virtual bool IsUnderWater() const; + bool isInAccessablePlaceFor(Creature const* c) const; + + void SendHealSpellLog(Unit *pVictim, uint32 SpellID, uint32 Damage, bool critical = false); + void SendEnergizeSpellLog(Unit *pVictim, uint32 SpellID, uint32 Damage,Powers powertype, bool critical = false); + uint32 SpellNonMeleeDamageLog(Unit *pVictim, uint32 spellID, uint32 damage, bool isTriggeredSpell = false, bool useSpellDamage = true); + void CastSpell(Unit* Victim, uint32 spellId, bool triggered, Item *castItem = NULL, Aura* triggredByAura = NULL, uint64 originalCaster = 0); + void CastSpell(Unit* Victim,SpellEntry const *spellInfo, bool triggered, Item *castItem= NULL, Aura* triggredByAura = NULL, uint64 originalCaster = 0); + void CastCustomSpell(Unit* Victim, uint32 spellId, int32 const* bp0, int32 const* bp1, int32 const* bp2, bool triggered, Item *castItem= NULL, Aura* triggredByAura = NULL, uint64 originalCaster = 0); + void CastCustomSpell(Unit* Victim,SpellEntry const *spellInfo, int32 const* bp0, int32 const* bp1, int32 const* bp2, bool triggered, Item *castItem= NULL, Aura* triggredByAura = NULL, uint64 originalCaster = 0); + void CastSpell(float x, float y, float z, uint32 spellId, bool triggered, Item *castItem = NULL, Aura* triggredByAura = NULL, uint64 originalCaster = 0); + void CastSpell(float x, float y, float z, SpellEntry const *spellInfo, bool triggered, Item *castItem = NULL, Aura* triggredByAura = NULL, uint64 originalCaster = 0); + + bool IsDamageToThreatSpell(SpellEntry const * spellInfo) const; + + void DeMorph(); + + void SendAttackStateUpdate(uint32 HitInfo, Unit *target, uint8 SwingType, SpellSchoolMask damageSchoolMask, uint32 Damage, uint32 AbsorbDamage, uint32 Resist, VictimState TargetState, uint32 BlockedAmount); + void SendSpellNonMeleeDamageLog(Unit *target,uint32 SpellID,uint32 Damage, SpellSchoolMask damageSchoolMask,uint32 AbsorbedDamage, uint32 Resist,bool PhysicalDamage, uint32 Blocked, bool CriticalHit = false); + void SendSpellMiss(Unit *target, uint32 spellID, SpellMissInfo missInfo); + + void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, uint32 MovementFlags, uint32 Time, Player* player = NULL); + void SendMonsterMoveByPath(Path const& path, uint32 start, uint32 end, uint32 MovementFlags); + void SendMonsterMoveWithSpeed(float x, float y, float z, uint32 MovementFlags, uint32 transitTime = 0, Player* player = NULL); + void SendMonsterMoveWithSpeedToCurrentDestination(Player* player = NULL); + + virtual void MoveOutOfRange(Player &) { }; + + bool isAlive() const { return (m_deathState == ALIVE); }; + bool isDead() const { return ( m_deathState == DEAD || m_deathState == CORPSE ); }; + DeathState getDeathState() { return m_deathState; }; + virtual void setDeathState(DeathState s); // overwrited in Creature/Player/Pet + + uint64 const& GetOwnerGUID() const { return GetUInt64Value(UNIT_FIELD_SUMMONEDBY); } + uint64 GetPetGUID() const { return GetUInt64Value(UNIT_FIELD_SUMMON); } + uint64 GetCharmerGUID() const { return GetUInt64Value(UNIT_FIELD_CHARMEDBY); } + uint64 GetCharmGUID() const { return GetUInt64Value(UNIT_FIELD_CHARM); } + void SetCharmerGUID(uint64 owner) { SetUInt64Value(UNIT_FIELD_CHARMEDBY, owner); } + + uint64 GetCharmerOrOwnerGUID() const { return GetCharmerGUID() ? GetCharmerGUID() : GetOwnerGUID(); } + uint64 GetCharmerOrOwnerOrOwnGUID() const + { + if(uint64 guid = GetCharmerOrOwnerGUID()) + return guid; + return GetGUID(); + } + bool isCharmedOwnedByPlayerOrPlayer() const { return IS_PLAYER_GUID(GetCharmerOrOwnerOrOwnGUID()); } + + Player* GetSpellModOwner(); + + Unit* GetOwner() const; + Pet* GetPet() const; + Unit* GetCharmer() const; + Unit* GetCharm() const; + Unit* GetCharmerOrOwner() const { return GetCharmerGUID() ? GetCharmer() : GetOwner(); } + Unit* GetCharmerOrOwnerOrSelf() + { + if(Unit* u = GetCharmerOrOwner()) + return u; + + return this; + } + Player* GetCharmerOrOwnerPlayerOrPlayerItself(); + + void SetPet(Pet* pet); + void SetCharm(Unit* pet); + bool isCharmed() const { return GetCharmerGUID() != 0; } + + CharmInfo* GetCharmInfo() { return m_charmInfo; } + CharmInfo* InitCharmInfo(Unit* charm); + + bool AddAura(Aura *aur); + + void RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT); + void RemoveAura(uint32 spellId, uint32 effindex, Aura* except = NULL); + void RemoveSingleAuraFromStack(uint32 spellId, uint32 effindex); + void RemoveAurasDueToSpell(uint32 spellId, Aura* except = NULL); + void RemoveAurasDueToItemSpell(Item* castItem,uint32 spellId); + void RemoveAurasDueToSpellByDispel(uint32 spellId, uint64 casterGUID, Unit *dispeler); + void RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit *stealer); + void RemoveAurasDueToSpellByCancel(uint32 spellId); + void RemoveNotOwnSingleTargetAuras(); + + void RemoveSpellsCausingAura(AuraType auraType); + void RemoveRankAurasDueToSpell(uint32 spellId); + bool RemoveNoStackAurasDueToAura(Aura *Aur); + void RemoveAurasWithInterruptFlags(uint32 flags); + void RemoveAurasWithDispelType( DispelType type ); + + void RemoveAllAuras(); + void RemoveAllAurasOnDeath(); + void DelayAura(uint32 spellId, uint32 effindex, int32 delaytime); + + float GetResistanceBuffMods(SpellSchools school, bool positive) const { return GetFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE+school ); } + void SetResistanceBuffMods(SpellSchools school, bool positive, float val) { SetFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE+school,val); } + void ApplyResistanceBuffModsMod(SpellSchools school, bool positive, float val, bool apply) { ApplyModSignedFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE+school, val, apply); } + void ApplyResistanceBuffModsPercentMod(SpellSchools school, bool positive, float val, bool apply) { ApplyPercentModFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE+school, val, apply); } + void InitStatBuffMods() + { + for(int i = STAT_STRENGTH; i < MAX_STATS; ++i) SetFloatValue(UNIT_FIELD_POSSTAT0+i, 0); + for(int i = STAT_STRENGTH; i < MAX_STATS; ++i) SetFloatValue(UNIT_FIELD_NEGSTAT0+i, 0); + } + void ApplyStatBuffMod(Stats stat, float val, bool apply) { ApplyModSignedFloatValue((val > 0 ? UNIT_FIELD_POSSTAT0+stat : UNIT_FIELD_NEGSTAT0+stat), val, apply); } + void ApplyStatPercentBuffMod(Stats stat, float val, bool apply) + { + ApplyPercentModFloatValue(UNIT_FIELD_POSSTAT0+stat, val, apply); + ApplyPercentModFloatValue(UNIT_FIELD_NEGSTAT0+stat, val, apply); + } + void SetCreateStat(Stats stat, float val) { m_createStats[stat] = val; } + void SetCreateHealth(uint32 val) { SetUInt32Value(UNIT_FIELD_BASE_HEALTH, val); } + uint32 GetCreateHealth() const { return GetUInt32Value(UNIT_FIELD_BASE_HEALTH); } + void SetCreateMana(uint32 val) { SetUInt32Value(UNIT_FIELD_BASE_MANA, val); } + uint32 GetCreateMana() const { return GetUInt32Value(UNIT_FIELD_BASE_MANA); } + uint32 GetCreatePowers(Powers power) const; + float GetPosStat(Stats stat) const { return GetFloatValue(UNIT_FIELD_POSSTAT0+stat); } + float GetNegStat(Stats stat) const { return GetFloatValue(UNIT_FIELD_NEGSTAT0+stat); } + float GetCreateStat(Stats stat) const { return m_createStats[stat]; } + + void SetCurrentCastedSpell(Spell * pSpell); + virtual void ProhibitSpellScholl(SpellSchoolMask /*idSchoolMask*/, uint32 /*unTimeMs*/ ) { } + void InterruptSpell(uint32 spellType, bool withDelayed = true); + + // set withDelayed to true to account delayed spells as casted + // delayed+channeled spells are always accounted as casted + // we can skip channeled or delayed checks using flags + bool IsNonMeleeSpellCasted(bool withDelayed, bool skipChanneled = false, bool skipAutorepeat = false) const; + + // set withDelayed to true to interrupt delayed spells too + // delayed+channeled spells are always interrupted + void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid = 0); + + Spell* FindCurrentSpellBySpellId(uint32 spell_id) const; + + Spell* m_currentSpells[CURRENT_MAX_SPELL]; + + uint32 m_addDmgOnce; + uint64 m_TotemSlot[MAX_TOTEM]; + uint64 m_ObjectSlot[4]; + uint32 m_detectInvisibilityMask; + uint32 m_invisibilityMask; + uint32 m_ShapeShiftFormSpellId; + ShapeshiftForm m_form; + float m_modMeleeHitChance; + float m_modRangedHitChance; + float m_modSpellHitChance; + int32 m_baseSpellCritChance; + + float m_threatModifier[MAX_SPELL_SCHOOL]; + float m_modAttackSpeedPct[3]; + + // Event handler + EventProcessor m_Events; + + // stat system + bool HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, float amount, bool apply); + void SetModifierValue(UnitMods unitMod, UnitModifierType modifierType, float value) { m_auraModifiersGroup[unitMod][modifierType] = value; } + float GetModifierValue(UnitMods unitMod, UnitModifierType modifierType) const; + float GetTotalStatValue(Stats stat) const; + float GetTotalAuraModValue(UnitMods unitMod) const; + SpellSchools GetSpellSchoolByAuraGroup(UnitMods unitMod) const; + Stats GetStatByAuraGroup(UnitMods unitMod) const; + Powers GetPowerTypeByAuraGroup(UnitMods unitMod) const; + bool CanModifyStats() const { return m_canModifyStats; } + void SetCanModifyStats(bool modifyStats) { m_canModifyStats = modifyStats; } + virtual bool UpdateStats(Stats stat) = 0; + virtual bool UpdateAllStats() = 0; + virtual void UpdateResistances(uint32 school) = 0; + virtual void UpdateArmor() = 0; + virtual void UpdateMaxHealth() = 0; + virtual void UpdateMaxPower(Powers power) = 0; + virtual void UpdateAttackPowerAndDamage(bool ranged = false) = 0; + virtual void UpdateDamagePhysical(WeaponAttackType attType) = 0; + float GetTotalAttackPowerValue(WeaponAttackType attType) const; + float GetWeaponDamageRange(WeaponAttackType attType ,WeaponDamageRange type) const; + void SetBaseWeaponDamage(WeaponAttackType attType ,WeaponDamageRange damageRange, float value) { m_weaponDamage[attType][damageRange] = value; } + + bool isInFront(Unit const* target,float distance, float arc = M_PI) const; + void SetInFront(Unit const* target); + bool isInBack(Unit const* target, float distance, float arc = M_PI) const; + + // Visibility system + UnitVisibility GetVisibility() const { return m_Visibility; } + void SetVisibility(UnitVisibility x); + + // common function for visibility checks for player/creatures with detection code + bool isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList = false) const; + bool canDetectInvisibilityOf(Unit const* u) const; + + // virtual functions for all world objects types + bool isVisibleForInState(Player const* u, bool inVisibleList) const; + // function for low level grid visibility checks in player/creature cases + virtual bool IsVisibleInGridForPlayer(Player* pl) const = 0; + + bool waterbreath; + AuraList & GetSingleCastAuras() { return m_scAuras; } + AuraList const& GetSingleCastAuras() const { return m_scAuras; } + SpellImmuneList m_spellImmune[MAX_SPELL_IMMUNITY]; + + // Threat related methodes + bool CanHaveThreatList() const; + void AddThreat(Unit* pVictim, float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellEntry const *threatSpell = NULL); + float ApplyTotalThreatModifier(float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL); + void DeleteThreatList(); + bool SelectHostilTarget(); + void TauntApply(Unit* pVictim); + void TauntFadeOut(Unit *taunter); + ThreatManager& getThreatManager() { return m_ThreatManager; } + void addHatedBy(HostilReference* pHostilReference) { m_HostilRefManager.insertFirst(pHostilReference); }; + void removeHatedBy(HostilReference* /*pHostilReference*/ ) { /* nothing to do yet */ } + HostilRefManager& getHostilRefManager() { return m_HostilRefManager; } + + Aura* GetAura(uint32 spellId, uint32 effindex); + AuraMap & GetAuras() { return m_Auras; } + AuraMap const& GetAuras() const { return m_Auras; } + AuraList const& GetAurasByType(AuraType type) const { return m_modAuras[type]; } + void ApplyAuraProcTriggerDamage(Aura* aura, bool apply); + + int32 GetTotalAuraModifier(AuraType auratype) const; + float GetTotalAuraMultiplier(AuraType auratype) const; + int32 GetMaxPositiveAuraModifier(AuraType auratype) const; + int32 GetMaxNegativeAuraModifier(AuraType auratype) const; + + int32 GetTotalAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const; + float GetTotalAuraMultiplierByMiscMask(AuraType auratype, uint32 misc_mask) const; + int32 GetMaxPositiveAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const; + int32 GetMaxNegativeAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const; + + int32 GetTotalAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const; + float GetTotalAuraMultiplierByMiscValue(AuraType auratype, int32 misc_value) const; + int32 GetMaxPositiveAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const; + int32 GetMaxNegativeAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const; + + Aura* GetDummyAura(uint32 spell_id) const; + + uint32 GetDisplayId() { return GetUInt32Value(UNIT_FIELD_DISPLAYID); } + void SetDisplayId(uint32 modelId); + uint32 GetNativeDisplayId() { return GetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID); } + void SetNativeDisplayId(uint32 modelId) { SetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID, modelId); } + void setTransForm(uint32 spellid) { m_transform = spellid;} + uint32 getTransForm() const { return m_transform;} + void AddDynObject(DynamicObject* dynObj); + void RemoveDynObject(uint32 spellid); + void RemoveDynObjectWithGUID(uint64 guid) { m_dynObjGUIDs.remove(guid); } + void RemoveAllDynObjects(); + void AddGameObject(GameObject* gameObj); + void RemoveGameObject(GameObject* gameObj, bool del); + void RemoveGameObject(uint32 spellid, bool del); + void RemoveAllGameObjects(); + DynamicObject *GetDynObject(uint32 spellId, uint32 effIndex); + DynamicObject *GetDynObject(uint32 spellId); + uint32 CalculateDamage(WeaponAttackType attType, bool normalized); + float GetAPMultiplier(WeaponAttackType attType, bool normalized); + void ModifyAuraState(AuraState flag, bool apply); + bool HasAuraState(AuraState flag) const { return HasFlag(UNIT_FIELD_AURASTATE, 1<<(flag-1)); } + void UnsummonAllTotems(); + int32 SpellBaseDamageBonus(SpellSchoolMask schoolMask); + int32 SpellBaseHealingBonus(SpellSchoolMask schoolMask); + int32 SpellBaseDamageBonusForVictim(SpellSchoolMask schoolMask, Unit *pVictim); + int32 SpellBaseHealingBonusForVictim(SpellSchoolMask schoolMask, Unit *pVictim); + uint32 SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint32 damage, DamageEffectType damagetype); + uint32 SpellHealingBonus(SpellEntry const *spellProto, uint32 healamount, DamageEffectType damagetype, Unit *pVictim); + bool isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType); + uint32 SpellCriticalBonus(SpellEntry const *spellProto, uint32 damage, Unit *pVictim); + + void SetLastManaUse(uint32 spellCastTime) { m_lastManaUse = spellCastTime; } + bool IsUnderLastManaUseEffect() const; + + void SetContestedPvP(Player *attackedPlayer = NULL); + + void MeleeDamageBonus(Unit *pVictim, uint32 *damage, WeaponAttackType attType, SpellEntry const *spellProto = NULL); + uint32 GetCastingTimeForBonus( SpellEntry const *spellProto, DamageEffectType damagetype, uint32 CastingTime ); + + void ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply); + void ApplySpellDispelImmunity(const SpellEntry * spellProto, DispelType type, bool apply); + virtual bool IsImmunedToSpell(SpellEntry const* spellInfo, bool useCharges = false); + // redefined in Creature + bool IsImmunedToDamage(SpellSchoolMask meleeSchoolMask, bool useCharges = false); + virtual bool IsImmunedToSpellEffect(uint32 effect, uint32 mechanic) const; + // redefined in Creature + + uint32 CalcArmorReducedDamage(Unit* pVictim, const uint32 damage); + void CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEffectType damagetype, const uint32 damage, uint32 *absorb, uint32 *resist); + + void UpdateSpeed(UnitMoveType mtype, bool forced); + float GetSpeed( UnitMoveType mtype ) const; + float GetSpeedRate( UnitMoveType mtype ) const { return m_speed_rate[mtype]; } + void SetSpeed(UnitMoveType mtype, float rate, bool forced = false); + + void SetHover(bool on); + bool isHover() const { return HasAuraType(SPELL_AURA_HOVER); } + + void _RemoveAllAuraMods(); + void _ApplyAllAuraMods(); + + int32 CalculateSpellDamage(SpellEntry const* spellProto, uint8 effect_index, int32 basePoints, Unit const* target); + int32 CalculateSpellDuration(SpellEntry const* spellProto, uint8 effect_index, Unit const* target); + float CalculateLevelPenalty(SpellEntry const* spellProto) const; + + void addFollower(FollowerReference* pRef) { m_FollowingRefManager.insertFirst(pRef); } + void removeFollower(FollowerReference* /*pRef*/ ) { /* nothing to do yet */ } + static Unit* GetUnit(WorldObject& object, uint64 guid); + + MotionMaster* GetMotionMaster() { return &i_motionMaster; } + + bool IsStopped() const { return !(hasUnitState(UNIT_STAT_MOVING)); } + void StopMoving(); + + void AddUnitMovementFlag(uint32 f) { m_unit_movement_flags |= f; } + void RemoveUnitMovementFlag(uint32 f) + { + uint32 oldval = m_unit_movement_flags; + m_unit_movement_flags = oldval & ~f; + } + uint32 HasUnitMovementFlag(uint32 f) const { return m_unit_movement_flags & f; } + uint32 GetUnitMovementFlags() const { return m_unit_movement_flags; } + void SetUnitMovementFlags(uint32 f) { m_unit_movement_flags = f; } + + void SetFeared(bool apply, uint64 casterGUID = 0, uint32 spellID = 0); + void SetConfused(bool apply, uint64 casterGUID = 0, uint32 spellID = 0); + + void AddComboPointHolder(uint32 lowguid) { m_ComboPointHolders.insert(lowguid); } + void RemoveComboPointHolder(uint32 lowguid) { m_ComboPointHolders.erase(lowguid); } + void ClearComboPointHolders(); + + ///----------Pet responses methods----------------- + void SendPetCastFail(uint32 spellid, uint8 msg); + void SendPetActionFeedback (uint8 msg); + void SendPetTalk (uint32 pettalk); + void SendPetSpellCooldown (uint32 spellid, time_t cooltime); + void SendPetClearCooldown (uint32 spellid); + void SendPetAIReaction(uint64 guid); + ///----------End of Pet responses methods---------- + + void propagateSpeedChange() { GetMotionMaster()->propagateSpeedChange(); } + + // reactive attacks + void ClearAllReactives(); + void StartReactiveTimer( ReactiveType reactive ) { m_reactiveTimer[reactive] = REACTIVE_TIMER_START;} + void UpdateReactives(uint32 p_time); + + // group updates + void UpdateAuraForGroup(uint8 slot); + + // pet auras + typedef std::set PetAuraSet; + PetAuraSet m_petAuras; + void AddPetAura(PetAura const* petSpell); + void RemovePetAura(PetAura const* petSpell); + + protected: + explicit Unit (); + + void _UpdateSpells(uint32 time); + + void _UpdateAutoRepeatSpell(); + bool m_AutoRepeatFirstCast; + + uint32 m_attackTimer[MAX_ATTACK]; + + float m_createStats[MAX_STATS]; + + AttackerSet m_attackers; + Unit* m_attacking; + + DeathState m_deathState; + + AuraMap m_Auras; + + std::list m_scAuras; // casted singlecast auras + + typedef std::list DynObjectGUIDs; + DynObjectGUIDs m_dynObjGUIDs; + + std::list m_gameObj; + bool m_isSorted; + uint32 m_transform; + uint32 m_removedAuras; + + AuraList m_modAuras[TOTAL_AURAS]; + float m_auraModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_END]; + float m_weaponDamage[MAX_ATTACK][2]; + bool m_canModifyStats; + //std::list< spellEffectPair > AuraSpells[TOTAL_AURAS]; // TODO: use this if ok for mem + + float m_speed_rate[MAX_MOVE_TYPE]; + + CharmInfo *m_charmInfo; + + virtual SpellSchoolMask GetMeleeDamageSchoolMask() const; + + MotionMaster i_motionMaster; + uint32 m_unit_movement_flags; + + uint32 m_reactiveTimer[MAX_REACTIVE]; + + private: + void SendAttackStop(Unit* victim); // only from AttackStop(Unit*) + void SendAttackStart(Unit* pVictim); // only from Unit::AttackStart(Unit*) + + void ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag, AuraTypeSet const& procAuraTypes, WeaponAttackType attType, SpellEntry const * procSpell, uint32 damage, SpellSchoolMask damageSchoolMask ); + bool HandleDummyAuraProc(Unit *pVictim, SpellEntry const *spellProto, uint32 effIndex, uint32 damage, Aura* triggredByAura, SpellEntry const * procSpell, uint32 procFlag,uint32 cooldown); + bool HandleProcTriggerSpell(Unit *pVictim,uint32 damage, Aura* triggredByAura, SpellEntry const *procSpell, uint32 procFlags,WeaponAttackType attType,uint32 cooldown); + bool HandleHasteAuraProc(Unit *pVictim, SpellEntry const *spellProto, uint32 effIndex, uint32 damage, Aura* triggredByAura, SpellEntry const * procSpell, uint32 procFlag,uint32 cooldown); + bool HandleOverrideClassScriptAuraProc(Unit *pVictim, int32 scriptId, uint32 damage, Aura* triggredByAura, SpellEntry const *procSpell,uint32 cooldown); + uint32 m_state; // Even derived shouldn't modify + uint32 m_CombatTimer; + uint32 m_lastManaUse; // msecs + + UnitVisibility m_Visibility; + + Diminishing m_Diminishing; + // Manage all Units threatening us + ThreatManager m_ThreatManager; + // Manage all Units that are threatened by us + HostilRefManager m_HostilRefManager; + + FollowerRefManager m_FollowingRefManager; + + ComboPointHolderSet m_ComboPointHolders; +}; +#endif diff --git a/src/game/UnitEvents.h b/src/game/UnitEvents.h new file mode 100644 index 00000000000..4ff99535035 --- /dev/null +++ b/src/game/UnitEvents.h @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _UNITEVENTS +#define _UNITEVENTS + +#include "Common.h" + +class ThreatContainer; +class ThreatManager; +class HostilReference; + +//============================================================== +//============================================================== + +enum UNIT_EVENT_TYPE +{ + // Player/Pet changed on/offline status + UEV_THREAT_REF_ONLINE_STATUS = 1<<0, + + // Threat for Player/Pet changed + UEV_THREAT_REF_THREAT_CHANGE = 1<<1, + + // Player/Pet will be removed from list (dead) [for internal use] + UEV_THREAT_REF_REMOVE_FROM_LIST = 1<<2, + + // Player/Pet entered/left water or some other place where it is/was not accessible for the creature + UEV_THREAT_REF_ASSECCIBLE_STATUS = 1<<3, + + // Threat list is going to be sorted (if dirty flag is set) + UEV_THREAT_SORT_LIST = 1<<4, + + // New target should be fetched, could tbe the current target as well + UEV_THREAT_SET_NEXT_TARGET = 1<<5, + + // A new victim (target) was set. Could be NULL + UEV_THREAT_VICTIM_CHANGED = 1<<6, + + // Future use + //UEV_UNIT_KILLED = 1<<7, + + //Future use + //UEV_UNIT_HEALTH_CHANGE = 1<<8, +}; + +#define UEV_THREAT_REF_EVENT_MASK ( UEV_THREAT_REF_ONLINE_STATUS | UEV_THREAT_REF_THREAT_CHANGE | UEV_THREAT_REF_REMOVE_FROM_LIST | UEV_THREAT_REF_ASSECCIBLE_STATUS) +#define UEV_THREAT_MANAGER_EVENT_MASK (UEV_THREAT_SORT_LIST | UEV_THREAT_SET_NEXT_TARGET | UEV_THREAT_VICTIM_CHANGED) +#define UEV_ALL_EVENT_MASK (0xffffffff) + +// Future use +//#define UEV_UNIT_EVENT_MASK (UEV_UNIT_KILLED | UEV_UNIT_HEALTH_CHANGE) + +//============================================================== + +class MANGOS_DLL_SPEC UnitBaseEvent +{ + private: + uint32 iType; + public: + UnitBaseEvent(uint32 pType) { iType = pType; } + uint32 getType() const { return iType; } + bool matchesTypeMask(uint32 pMask) const { return iType & pMask; } + + void setType(uint32 pType) { iType = pType; } + +}; + +//============================================================== + +class MANGOS_DLL_SPEC ThreatRefStatusChangeEvent : public UnitBaseEvent +{ + private: + HostilReference* iHostilReference; + union + { + float iFValue; + int32 iIValue; + bool iBValue; + }; + ThreatManager* iThreatManager; + public: + ThreatRefStatusChangeEvent(uint32 pType) : UnitBaseEvent(pType) { iHostilReference = NULL; } + + ThreatRefStatusChangeEvent(uint32 pType, HostilReference* pHostilReference) : UnitBaseEvent(pType) { iHostilReference = pHostilReference; } + + ThreatRefStatusChangeEvent(uint32 pType, HostilReference* pHostilReference, float pValue) : UnitBaseEvent(pType) { iHostilReference = pHostilReference; iFValue = pValue; } + + ThreatRefStatusChangeEvent(uint32 pType, HostilReference* pHostilReference, bool pValue) : UnitBaseEvent(pType) { iHostilReference = pHostilReference; iBValue = pValue; } + + int32 getIValue() const { return iIValue; } + + float getFValue() const { return iFValue; } + + bool getBValue() const { return iBValue; } + + void setBValue(bool pValue) { iBValue = pValue; } + + HostilReference* getReference() const { return iHostilReference; } + + void setThreatManager(ThreatManager* pThreatManager) { iThreatManager = pThreatManager; } + + ThreatManager* getThreatManager() const { return iThreatManager; } +}; + +//============================================================== + +class MANGOS_DLL_SPEC ThreatManagerEvent : public ThreatRefStatusChangeEvent +{ + private: + ThreatContainer* iThreatContainer; + public: + ThreatManagerEvent(uint32 pType) : ThreatRefStatusChangeEvent(pType) {} + ThreatManagerEvent(uint32 pType, HostilReference* pHostilReference) : ThreatRefStatusChangeEvent(pType, pHostilReference) {} + + void setThreatContainer(ThreatContainer* pThreatContainer) { iThreatContainer = pThreatContainer; } + + ThreatContainer* getThreatContainer() const { return iThreatContainer; } +}; + +//============================================================== +#endif diff --git a/src/game/UpdateData.cpp b/src/game/UpdateData.cpp new file mode 100644 index 00000000000..eded8cb7395 --- /dev/null +++ b/src/game/UpdateData.cpp @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "ByteBuffer.h" +#include "WorldPacket.h" +#include "UpdateData.h" +#include "Log.h" +#include "Opcodes.h" +#include "World.h" +#include + +UpdateData::UpdateData() : m_blockCount(0) +{ +} + +void UpdateData::AddOutOfRangeGUID(std::set& guids) +{ + m_outOfRangeGUIDs.insert(guids.begin(),guids.end()); +} + +void UpdateData::AddOutOfRangeGUID(const uint64 &guid) +{ + m_outOfRangeGUIDs.insert(guid); +} + +void UpdateData::AddUpdateBlock(const ByteBuffer &block) +{ + m_data.append(block); + ++m_blockCount; +} + +void UpdateData::Compress(void* dst, uint32 *dst_size, void* src, int src_size) +{ + z_stream c_stream; + + c_stream.zalloc = (alloc_func)0; + c_stream.zfree = (free_func)0; + c_stream.opaque = (voidpf)0; + + // default Z_BEST_SPEED (1) + int z_res = deflateInit(&c_stream, sWorld.getConfig(CONFIG_COMPRESSION)); + if (z_res != Z_OK) + { + sLog.outError("Can't compress update packet (zlib: deflateInit) Error code: %i (%s)",z_res,zError(z_res)); + *dst_size = 0; + return; + } + + c_stream.next_out = (Bytef*)dst; + c_stream.avail_out = *dst_size; + c_stream.next_in = (Bytef*)src; + c_stream.avail_in = (uInt)src_size; + + z_res = deflate(&c_stream, Z_NO_FLUSH); + if (z_res != Z_OK) + { + sLog.outError("Can't compress update packet (zlib: deflate) Error code: %i (%s)",z_res,zError(z_res)); + *dst_size = 0; + return; + } + + if (c_stream.avail_in != 0) + { + sLog.outError("Can't compress update packet (zlib: deflate not greedy)"); + *dst_size = 0; + return; + } + + z_res = deflate(&c_stream, Z_FINISH); + if (z_res != Z_STREAM_END) + { + sLog.outError("Can't compress update packet (zlib: deflate should report Z_STREAM_END instead %i (%s)",z_res,zError(z_res)); + *dst_size = 0; + return; + } + + z_res = deflateEnd(&c_stream); + if (z_res != Z_OK) + { + sLog.outError("Can't compress update packet (zlib: deflateEnd) Error code: %i (%s)",z_res,zError(z_res)); + *dst_size = 0; + return; + } + + *dst_size = c_stream.total_out; +} + +bool UpdateData::BuildPacket(WorldPacket *packet, bool hasTransport) +{ + ByteBuffer buf(m_data.size() + 10 + m_outOfRangeGUIDs.size()*8); + + buf << (uint32) (!m_outOfRangeGUIDs.empty() ? m_blockCount + 1 : m_blockCount); + buf << (uint8) (hasTransport ? 1 : 0); + + if(!m_outOfRangeGUIDs.empty()) + { + buf << (uint8) UPDATETYPE_OUT_OF_RANGE_OBJECTS; + buf << (uint32) m_outOfRangeGUIDs.size(); + + for(std::set::const_iterator i = m_outOfRangeGUIDs.begin(); + i != m_outOfRangeGUIDs.end(); i++) + { + //buf.appendPackGUID(*i); + buf << (uint8)0xFF; + buf << (uint64) *i; + } + } + + buf.append(m_data); + + packet->clear(); + + if (m_data.size() > 50 ) + { + uint32 destsize = buf.size() + buf.size()/10 + 16; + packet->resize( destsize ); + + packet->put(0, (uint32)buf.size()); + + Compress(const_cast(packet->contents()) + sizeof(uint32), + &destsize, + (void*)buf.contents(), + buf.size()); + if (destsize == 0) + return false; + + packet->resize( destsize + sizeof(uint32) ); + packet->SetOpcode( SMSG_COMPRESSED_UPDATE_OBJECT ); + } + else + { + packet->append( buf ); + packet->SetOpcode( SMSG_UPDATE_OBJECT ); + } + + return true; +} + +void UpdateData::Clear() +{ + m_data.clear(); + m_outOfRangeGUIDs.clear(); + m_blockCount = 0; +} diff --git a/src/game/UpdateData.h b/src/game/UpdateData.h new file mode 100644 index 00000000000..20f5749d507 --- /dev/null +++ b/src/game/UpdateData.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __UPDATEDATA_H +#define __UPDATEDATA_H + +class WorldPacket; + +enum OBJECT_UPDATE_TYPE +{ + UPDATETYPE_VALUES = 0, + UPDATETYPE_MOVEMENT = 1, + UPDATETYPE_CREATE_OBJECT = 2, + UPDATETYPE_CREATE_OBJECT2 = 3, + UPDATETYPE_OUT_OF_RANGE_OBJECTS = 4, + UPDATETYPE_NEAR_OBJECTS = 5 +}; + +enum OBJECT_UPDATE_FLAGS +{ + UPDATEFLAG_NONE = 0x00, + UPDATEFLAG_SELF = 0x01, + UPDATEFLAG_TRANSPORT = 0x02, + UPDATEFLAG_FULLGUID = 0x04, + UPDATEFLAG_LOWGUID = 0x08, + UPDATEFLAG_HIGHGUID = 0x10, + UPDATEFLAG_LIVING = 0x20, + UPDATEFLAG_HASPOSITION = 0x40 +}; + +class UpdateData +{ + public: + UpdateData(); + + void AddOutOfRangeGUID(std::set& guids); + void AddOutOfRangeGUID(const uint64 &guid); + void AddUpdateBlock(const ByteBuffer &block); + bool BuildPacket(WorldPacket *packet, bool hasTransport = false); + bool HasData() { return m_blockCount > 0 || !m_outOfRangeGUIDs.empty(); } + void Clear(); + + std::set const& GetOutOfRangeGUIDs() const { return m_outOfRangeGUIDs; } + + protected: + uint32 m_blockCount; + std::set m_outOfRangeGUIDs; + ByteBuffer m_data; + + void Compress(void* dst, uint32 *dst_size, void* src, int src_size); +}; +#endif diff --git a/src/game/UpdateFields.h b/src/game/UpdateFields.h new file mode 100644 index 00000000000..5cff686d209 --- /dev/null +++ b/src/game/UpdateFields.h @@ -0,0 +1,451 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _UPDATEFIELDS_AUTO_H +#define _UPDATEFIELDS_AUTO_H + +// Auto generated for version 2, 4, 3, 8606 + +enum EObjectFields +{ + OBJECT_FIELD_GUID = 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC + OBJECT_FIELD_TYPE = 0x0002, // Size: 1, Type: INT, Flags: PUBLIC + OBJECT_FIELD_ENTRY = 0x0003, // Size: 1, Type: INT, Flags: PUBLIC + OBJECT_FIELD_SCALE_X = 0x0004, // Size: 1, Type: FLOAT, Flags: PUBLIC + OBJECT_FIELD_PADDING = 0x0005, // Size: 1, Type: INT, Flags: NONE + OBJECT_END = 0x0006, +}; + +enum EItemFields +{ + ITEM_FIELD_OWNER = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC + ITEM_FIELD_CONTAINED = OBJECT_END + 0x0002, // Size: 2, Type: LONG, Flags: PUBLIC + ITEM_FIELD_CREATOR = OBJECT_END + 0x0004, // Size: 2, Type: LONG, Flags: PUBLIC + ITEM_FIELD_GIFTCREATOR = OBJECT_END + 0x0006, // Size: 2, Type: LONG, Flags: PUBLIC + ITEM_FIELD_STACK_COUNT = OBJECT_END + 0x0008, // Size: 1, Type: INT, Flags: OWNER_ONLY, UNK2 + ITEM_FIELD_DURATION = OBJECT_END + 0x0009, // Size: 1, Type: INT, Flags: OWNER_ONLY, UNK2 + ITEM_FIELD_SPELL_CHARGES = OBJECT_END + 0x000A, // Size: 5, Type: INT, Flags: OWNER_ONLY, UNK2 + ITEM_FIELD_FLAGS = OBJECT_END + 0x000F, // Size: 1, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT = OBJECT_END + 0x0010, // Size: 33, Type: INT, Flags: PUBLIC + ITEM_FIELD_PROPERTY_SEED = OBJECT_END + 0x0031, // Size: 1, Type: INT, Flags: PUBLIC + ITEM_FIELD_RANDOM_PROPERTIES_ID = OBJECT_END + 0x0032, // Size: 1, Type: INT, Flags: PUBLIC + ITEM_FIELD_ITEM_TEXT_ID = OBJECT_END + 0x0033, // Size: 1, Type: INT, Flags: OWNER_ONLY + ITEM_FIELD_DURABILITY = OBJECT_END + 0x0034, // Size: 1, Type: INT, Flags: OWNER_ONLY, UNK2 + ITEM_FIELD_MAXDURABILITY = OBJECT_END + 0x0035, // Size: 1, Type: INT, Flags: OWNER_ONLY, UNK2 + ITEM_END = OBJECT_END + 0x0036, +}; + +enum EContainerFields +{ + CONTAINER_FIELD_NUM_SLOTS = ITEM_END + 0x0000, // Size: 1, Type: INT, Flags: PUBLIC + CONTAINER_ALIGN_PAD = ITEM_END + 0x0001, // Size: 1, Type: BYTES, Flags: NONE + CONTAINER_FIELD_SLOT_1 = ITEM_END + 0x0002, // Size: 72, Type: LONG, Flags: PUBLIC + CONTAINER_END = ITEM_END + 0x004A, +}; + +enum EUnitFields +{ + UNIT_FIELD_CHARM = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC + UNIT_FIELD_SUMMON = OBJECT_END + 0x0002, // Size: 2, Type: LONG, Flags: PUBLIC + UNIT_FIELD_CHARMEDBY = OBJECT_END + 0x0004, // Size: 2, Type: LONG, Flags: PUBLIC + UNIT_FIELD_SUMMONEDBY = OBJECT_END + 0x0006, // Size: 2, Type: LONG, Flags: PUBLIC + UNIT_FIELD_CREATEDBY = OBJECT_END + 0x0008, // Size: 2, Type: LONG, Flags: PUBLIC + UNIT_FIELD_TARGET = OBJECT_END + 0x000A, // Size: 2, Type: LONG, Flags: PUBLIC + UNIT_FIELD_PERSUADED = OBJECT_END + 0x000C, // Size: 2, Type: LONG, Flags: PUBLIC + UNIT_FIELD_CHANNEL_OBJECT = OBJECT_END + 0x000E, // Size: 2, Type: LONG, Flags: PUBLIC + UNIT_FIELD_HEALTH = OBJECT_END + 0x0010, // Size: 1, Type: INT, Flags: DYNAMIC + UNIT_FIELD_POWER1 = OBJECT_END + 0x0011, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_POWER2 = OBJECT_END + 0x0012, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_POWER3 = OBJECT_END + 0x0013, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_POWER4 = OBJECT_END + 0x0014, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_POWER5 = OBJECT_END + 0x0015, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MAXHEALTH = OBJECT_END + 0x0016, // Size: 1, Type: INT, Flags: DYNAMIC + UNIT_FIELD_MAXPOWER1 = OBJECT_END + 0x0017, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MAXPOWER2 = OBJECT_END + 0x0018, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MAXPOWER3 = OBJECT_END + 0x0019, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MAXPOWER4 = OBJECT_END + 0x001A, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MAXPOWER5 = OBJECT_END + 0x001B, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_LEVEL = OBJECT_END + 0x001C, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_FACTIONTEMPLATE = OBJECT_END + 0x001D, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_BYTES_0 = OBJECT_END + 0x001E, // Size: 1, Type: BYTES, Flags: PUBLIC + UNIT_VIRTUAL_ITEM_SLOT_DISPLAY = OBJECT_END + 0x001F, // Size: 3, Type: INT, Flags: PUBLIC + UNIT_VIRTUAL_ITEM_INFO = OBJECT_END + 0x0022, // Size: 6, Type: BYTES, Flags: PUBLIC + UNIT_FIELD_FLAGS = OBJECT_END + 0x0028, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_FLAGS_2 = OBJECT_END + 0x0029, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_AURA = OBJECT_END + 0x002A, // Size: 56, Type: INT, Flags: PUBLIC + UNIT_FIELD_AURAFLAGS = OBJECT_END + 0x0062, // Size: 14, Type: BYTES, Flags: PUBLIC + UNIT_FIELD_AURALEVELS = OBJECT_END + 0x0070, // Size: 14, Type: BYTES, Flags: PUBLIC + UNIT_FIELD_AURAAPPLICATIONS = OBJECT_END + 0x007E, // Size: 14, Type: BYTES, Flags: PUBLIC + UNIT_FIELD_AURASTATE = OBJECT_END + 0x008C, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_BASEATTACKTIME = OBJECT_END + 0x008D, // Size: 2, Type: INT, Flags: PUBLIC + UNIT_FIELD_RANGEDATTACKTIME = OBJECT_END + 0x008F, // Size: 1, Type: INT, Flags: PRIVATE + UNIT_FIELD_BOUNDINGRADIUS = OBJECT_END + 0x0090, // Size: 1, Type: FLOAT, Flags: PUBLIC + UNIT_FIELD_COMBATREACH = OBJECT_END + 0x0091, // Size: 1, Type: FLOAT, Flags: PUBLIC + UNIT_FIELD_DISPLAYID = OBJECT_END + 0x0092, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_NATIVEDISPLAYID = OBJECT_END + 0x0093, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MOUNTDISPLAYID = OBJECT_END + 0x0094, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MINDAMAGE = OBJECT_END + 0x0095, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3 + UNIT_FIELD_MAXDAMAGE = OBJECT_END + 0x0096, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3 + UNIT_FIELD_MINOFFHANDDAMAGE = OBJECT_END + 0x0097, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3 + UNIT_FIELD_MAXOFFHANDDAMAGE = OBJECT_END + 0x0098, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3 + UNIT_FIELD_BYTES_1 = OBJECT_END + 0x0099, // Size: 1, Type: BYTES, Flags: PUBLIC + UNIT_FIELD_PETNUMBER = OBJECT_END + 0x009A, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_PET_NAME_TIMESTAMP = OBJECT_END + 0x009B, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_PETEXPERIENCE = OBJECT_END + 0x009C, // Size: 1, Type: INT, Flags: OWNER_ONLY + UNIT_FIELD_PETNEXTLEVELEXP = OBJECT_END + 0x009D, // Size: 1, Type: INT, Flags: OWNER_ONLY + UNIT_DYNAMIC_FLAGS = OBJECT_END + 0x009E, // Size: 1, Type: INT, Flags: DYNAMIC + UNIT_CHANNEL_SPELL = OBJECT_END + 0x009F, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_MOD_CAST_SPEED = OBJECT_END + 0x00A0, // Size: 1, Type: FLOAT, Flags: PUBLIC + UNIT_CREATED_BY_SPELL = OBJECT_END + 0x00A1, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_NPC_FLAGS = OBJECT_END + 0x00A2, // Size: 1, Type: INT, Flags: DYNAMIC + UNIT_NPC_EMOTESTATE = OBJECT_END + 0x00A3, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_TRAINING_POINTS = OBJECT_END + 0x00A4, // Size: 1, Type: TWO_SHORT, Flags: OWNER_ONLY + UNIT_FIELD_STAT0 = OBJECT_END + 0x00A5, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_STAT1 = OBJECT_END + 0x00A6, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_STAT2 = OBJECT_END + 0x00A7, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_STAT3 = OBJECT_END + 0x00A8, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_STAT4 = OBJECT_END + 0x00A9, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_POSSTAT0 = OBJECT_END + 0x00AA, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_POSSTAT1 = OBJECT_END + 0x00AB, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_POSSTAT2 = OBJECT_END + 0x00AC, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_POSSTAT3 = OBJECT_END + 0x00AD, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_POSSTAT4 = OBJECT_END + 0x00AE, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_NEGSTAT0 = OBJECT_END + 0x00AF, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_NEGSTAT1 = OBJECT_END + 0x00B0, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_NEGSTAT2 = OBJECT_END + 0x00B1, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_NEGSTAT3 = OBJECT_END + 0x00B2, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_NEGSTAT4 = OBJECT_END + 0x00B3, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_RESISTANCES = OBJECT_END + 0x00B4, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY, UNK3 + UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE = OBJECT_END + 0x00BB, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE = OBJECT_END + 0x00C2, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_BASE_MANA = OBJECT_END + 0x00C9, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_BASE_HEALTH = OBJECT_END + 0x00CA, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_BYTES_2 = OBJECT_END + 0x00CB, // Size: 1, Type: BYTES, Flags: PUBLIC + UNIT_FIELD_ATTACK_POWER = OBJECT_END + 0x00CC, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_ATTACK_POWER_MODS = OBJECT_END + 0x00CD, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x00CE, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_RANGED_ATTACK_POWER = OBJECT_END + 0x00CF, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_RANGED_ATTACK_POWER_MODS = OBJECT_END + 0x00D0, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x00D1, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_MINRANGEDDAMAGE = OBJECT_END + 0x00D2, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_MAXRANGEDDAMAGE = OBJECT_END + 0x00D3, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_POWER_COST_MODIFIER = OBJECT_END + 0x00D4, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_POWER_COST_MULTIPLIER = OBJECT_END + 0x00DB, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_MAXHEALTHMODIFIER = OBJECT_END + 0x00E2, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_PADDING = OBJECT_END + 0x00E3, // Size: 1, Type: INT, Flags: NONE + UNIT_END = OBJECT_END + 0x00E4, + + PLAYER_DUEL_ARBITER = UNIT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_FLAGS = UNIT_END + 0x0002, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_GUILDID = UNIT_END + 0x0003, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_GUILDRANK = UNIT_END + 0x0004, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_BYTES = UNIT_END + 0x0005, // Size: 1, Type: BYTES, Flags: PUBLIC + PLAYER_BYTES_2 = UNIT_END + 0x0006, // Size: 1, Type: BYTES, Flags: PUBLIC + PLAYER_BYTES_3 = UNIT_END + 0x0007, // Size: 1, Type: BYTES, Flags: PUBLIC + PLAYER_DUEL_TEAM = UNIT_END + 0x0008, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_GUILD_TIMESTAMP = UNIT_END + 0x0009, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_QUEST_LOG_1_1 = UNIT_END + 0x000A, // Size: 1, Type: INT, Flags: GROUP_ONLY + PLAYER_QUEST_LOG_1_2 = UNIT_END + 0x000B, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_1_3 = UNIT_END + 0x000C, // Size: 1, Type: BYTES, Flags: PRIVATE + PLAYER_QUEST_LOG_1_4 = UNIT_END + 0x000D, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_2_1 = UNIT_END + 0x000E, // Size: 1, Type: INT, Flags: GROUP_ONLY + PLAYER_QUEST_LOG_2_2 = UNIT_END + 0x000F, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_2_3 = UNIT_END + 0x0010, // Size: 1, Type: BYTES, Flags: PRIVATE + PLAYER_QUEST_LOG_2_4 = UNIT_END + 0x0011, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_3_1 = UNIT_END + 0x0012, // Size: 1, Type: INT, Flags: GROUP_ONLY + PLAYER_QUEST_LOG_3_2 = UNIT_END + 0x0013, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_3_3 = UNIT_END + 0x0014, // Size: 1, Type: BYTES, Flags: PRIVATE + PLAYER_QUEST_LOG_3_4 = UNIT_END + 0x0015, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_4_1 = UNIT_END + 0x0016, // Size: 1, Type: INT, Flags: GROUP_ONLY + PLAYER_QUEST_LOG_4_2 = UNIT_END + 0x0017, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_4_3 = UNIT_END + 0x0018, // Size: 1, Type: BYTES, Flags: PRIVATE + PLAYER_QUEST_LOG_4_4 = UNIT_END + 0x0019, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_5_1 = UNIT_END + 0x001A, // Size: 1, Type: INT, Flags: GROUP_ONLY + PLAYER_QUEST_LOG_5_2 = UNIT_END + 0x001B, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_5_3 = UNIT_END + 0x001C, // Size: 1, Type: BYTES, Flags: PRIVATE + PLAYER_QUEST_LOG_5_4 = UNIT_END + 0x001D, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_6_1 = UNIT_END + 0x001E, // Size: 1, Type: INT, Flags: GROUP_ONLY + PLAYER_QUEST_LOG_6_2 = UNIT_END + 0x001F, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_6_3 = UNIT_END + 0x0020, // Size: 1, Type: BYTES, Flags: PRIVATE + PLAYER_QUEST_LOG_6_4 = UNIT_END + 0x0021, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_7_1 = UNIT_END + 0x0022, // Size: 1, Type: INT, Flags: GROUP_ONLY + PLAYER_QUEST_LOG_7_2 = UNIT_END + 0x0023, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_7_3 = UNIT_END + 0x0024, // Size: 1, Type: BYTES, Flags: PRIVATE + PLAYER_QUEST_LOG_7_4 = UNIT_END + 0x0025, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_8_1 = UNIT_END + 0x0026, // Size: 1, Type: INT, Flags: GROUP_ONLY + PLAYER_QUEST_LOG_8_2 = UNIT_END + 0x0027, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_8_3 = UNIT_END + 0x0028, // Size: 1, Type: BYTES, Flags: PRIVATE + PLAYER_QUEST_LOG_8_4 = UNIT_END + 0x0029, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_9_1 = UNIT_END + 0x002A, // Size: 1, Type: INT, Flags: GROUP_ONLY + PLAYER_QUEST_LOG_9_2 = UNIT_END + 0x002B, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_9_3 = UNIT_END + 0x002C, // Size: 1, Type: BYTES, Flags: PRIVATE + PLAYER_QUEST_LOG_9_4 = UNIT_END + 0x002D, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_10_1 = UNIT_END + 0x002E, // Size: 1, Type: INT, Flags: GROUP_ONLY + PLAYER_QUEST_LOG_10_2 = UNIT_END + 0x002F, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_10_3 = UNIT_END + 0x0030, // Size: 1, Type: BYTES, Flags: PRIVATE + PLAYER_QUEST_LOG_10_4 = UNIT_END + 0x0031, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_11_1 = UNIT_END + 0x0032, // Size: 1, Type: INT, Flags: GROUP_ONLY + PLAYER_QUEST_LOG_11_2 = UNIT_END + 0x0033, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_11_3 = UNIT_END + 0x0034, // Size: 1, Type: BYTES, Flags: PRIVATE + PLAYER_QUEST_LOG_11_4 = UNIT_END + 0x0035, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_12_1 = UNIT_END + 0x0036, // Size: 1, Type: INT, Flags: GROUP_ONLY + PLAYER_QUEST_LOG_12_2 = UNIT_END + 0x0037, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_12_3 = UNIT_END + 0x0038, // Size: 1, Type: BYTES, Flags: PRIVATE + PLAYER_QUEST_LOG_12_4 = UNIT_END + 0x0039, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_13_1 = UNIT_END + 0x003A, // Size: 1, Type: INT, Flags: GROUP_ONLY + PLAYER_QUEST_LOG_13_2 = UNIT_END + 0x003B, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_13_3 = UNIT_END + 0x003C, // Size: 1, Type: BYTES, Flags: PRIVATE + PLAYER_QUEST_LOG_13_4 = UNIT_END + 0x003D, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_14_1 = UNIT_END + 0x003E, // Size: 1, Type: INT, Flags: GROUP_ONLY + PLAYER_QUEST_LOG_14_2 = UNIT_END + 0x003F, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_14_3 = UNIT_END + 0x0040, // Size: 1, Type: BYTES, Flags: PRIVATE + PLAYER_QUEST_LOG_14_4 = UNIT_END + 0x0041, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_15_1 = UNIT_END + 0x0042, // Size: 1, Type: INT, Flags: GROUP_ONLY + PLAYER_QUEST_LOG_15_2 = UNIT_END + 0x0043, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_15_3 = UNIT_END + 0x0044, // Size: 1, Type: BYTES, Flags: PRIVATE + PLAYER_QUEST_LOG_15_4 = UNIT_END + 0x0045, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_16_1 = UNIT_END + 0x0046, // Size: 1, Type: INT, Flags: GROUP_ONLY + PLAYER_QUEST_LOG_16_2 = UNIT_END + 0x0047, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_16_3 = UNIT_END + 0x0048, // Size: 1, Type: BYTES, Flags: PRIVATE + PLAYER_QUEST_LOG_16_4 = UNIT_END + 0x0049, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_17_1 = UNIT_END + 0x004A, // Size: 1, Type: INT, Flags: GROUP_ONLY + PLAYER_QUEST_LOG_17_2 = UNIT_END + 0x004B, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_17_3 = UNIT_END + 0x004C, // Size: 1, Type: BYTES, Flags: PRIVATE + PLAYER_QUEST_LOG_17_4 = UNIT_END + 0x004D, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_18_1 = UNIT_END + 0x004E, // Size: 1, Type: INT, Flags: GROUP_ONLY + PLAYER_QUEST_LOG_18_2 = UNIT_END + 0x004F, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_18_3 = UNIT_END + 0x0050, // Size: 1, Type: BYTES, Flags: PRIVATE + PLAYER_QUEST_LOG_18_4 = UNIT_END + 0x0051, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_19_1 = UNIT_END + 0x0052, // Size: 1, Type: INT, Flags: GROUP_ONLY + PLAYER_QUEST_LOG_19_2 = UNIT_END + 0x0053, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_19_3 = UNIT_END + 0x0054, // Size: 1, Type: BYTES, Flags: PRIVATE + PLAYER_QUEST_LOG_19_4 = UNIT_END + 0x0055, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_20_1 = UNIT_END + 0x0056, // Size: 1, Type: INT, Flags: GROUP_ONLY + PLAYER_QUEST_LOG_20_2 = UNIT_END + 0x0057, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_20_3 = UNIT_END + 0x0058, // Size: 1, Type: BYTES, Flags: PRIVATE + PLAYER_QUEST_LOG_20_4 = UNIT_END + 0x0059, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_21_1 = UNIT_END + 0x005A, // Size: 1, Type: INT, Flags: GROUP_ONLY + PLAYER_QUEST_LOG_21_2 = UNIT_END + 0x005B, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_21_3 = UNIT_END + 0x005C, // Size: 1, Type: BYTES, Flags: PRIVATE + PLAYER_QUEST_LOG_21_4 = UNIT_END + 0x005D, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_22_1 = UNIT_END + 0x005E, // Size: 1, Type: INT, Flags: GROUP_ONLY + PLAYER_QUEST_LOG_22_2 = UNIT_END + 0x005F, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_22_3 = UNIT_END + 0x0060, // Size: 1, Type: BYTES, Flags: PRIVATE + PLAYER_QUEST_LOG_22_4 = UNIT_END + 0x0061, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_23_1 = UNIT_END + 0x0062, // Size: 1, Type: INT, Flags: GROUP_ONLY + PLAYER_QUEST_LOG_23_2 = UNIT_END + 0x0063, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_23_3 = UNIT_END + 0x0064, // Size: 1, Type: BYTES, Flags: PRIVATE + PLAYER_QUEST_LOG_23_4 = UNIT_END + 0x0065, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_24_1 = UNIT_END + 0x0066, // Size: 1, Type: INT, Flags: GROUP_ONLY + PLAYER_QUEST_LOG_24_2 = UNIT_END + 0x0067, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_24_3 = UNIT_END + 0x0068, // Size: 1, Type: BYTES, Flags: PRIVATE + PLAYER_QUEST_LOG_24_4 = UNIT_END + 0x0069, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_25_1 = UNIT_END + 0x006A, // Size: 1, Type: INT, Flags: GROUP_ONLY + PLAYER_QUEST_LOG_25_2 = UNIT_END + 0x006B, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_25_3 = UNIT_END + 0x006C, // Size: 1, Type: BYTES, Flags: PRIVATE + PLAYER_QUEST_LOG_25_4 = UNIT_END + 0x006D, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_VISIBLE_ITEM_1_CREATOR = UNIT_END + 0x006E, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_1_0 = UNIT_END + 0x0070, // Size: 12, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_1_PROPERTIES = UNIT_END + 0x007C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_1_PAD = UNIT_END + 0x007D, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_2_CREATOR = UNIT_END + 0x007E, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_2_0 = UNIT_END + 0x0080, // Size: 12, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_2_PROPERTIES = UNIT_END + 0x008C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_2_PAD = UNIT_END + 0x008D, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_3_CREATOR = UNIT_END + 0x008E, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_3_0 = UNIT_END + 0x0090, // Size: 12, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_3_PROPERTIES = UNIT_END + 0x009C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_3_PAD = UNIT_END + 0x009D, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_4_CREATOR = UNIT_END + 0x009E, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_4_0 = UNIT_END + 0x00A0, // Size: 12, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_4_PROPERTIES = UNIT_END + 0x00AC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_4_PAD = UNIT_END + 0x00AD, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_5_CREATOR = UNIT_END + 0x00AE, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_5_0 = UNIT_END + 0x00B0, // Size: 12, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_5_PROPERTIES = UNIT_END + 0x00BC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_5_PAD = UNIT_END + 0x00BD, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_6_CREATOR = UNIT_END + 0x00BE, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_6_0 = UNIT_END + 0x00C0, // Size: 12, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_6_PROPERTIES = UNIT_END + 0x00CC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_6_PAD = UNIT_END + 0x00CD, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_7_CREATOR = UNIT_END + 0x00CE, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_7_0 = UNIT_END + 0x00D0, // Size: 12, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_7_PROPERTIES = UNIT_END + 0x00DC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_7_PAD = UNIT_END + 0x00DD, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_8_CREATOR = UNIT_END + 0x00DE, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_8_0 = UNIT_END + 0x00E0, // Size: 12, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_8_PROPERTIES = UNIT_END + 0x00EC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_8_PAD = UNIT_END + 0x00ED, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_9_CREATOR = UNIT_END + 0x00EE, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_9_0 = UNIT_END + 0x00F0, // Size: 12, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_9_PROPERTIES = UNIT_END + 0x00FC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_9_PAD = UNIT_END + 0x00FD, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_10_CREATOR = UNIT_END + 0x00FE, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_10_0 = UNIT_END + 0x0100, // Size: 12, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_10_PROPERTIES = UNIT_END + 0x010C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_10_PAD = UNIT_END + 0x010D, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_11_CREATOR = UNIT_END + 0x010E, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_11_0 = UNIT_END + 0x0110, // Size: 12, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_11_PROPERTIES = UNIT_END + 0x011C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_11_PAD = UNIT_END + 0x011D, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_12_CREATOR = UNIT_END + 0x011E, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_12_0 = UNIT_END + 0x0120, // Size: 12, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_12_PROPERTIES = UNIT_END + 0x012C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_12_PAD = UNIT_END + 0x012D, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_13_CREATOR = UNIT_END + 0x012E, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_13_0 = UNIT_END + 0x0130, // Size: 12, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_13_PROPERTIES = UNIT_END + 0x013C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_13_PAD = UNIT_END + 0x013D, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_14_CREATOR = UNIT_END + 0x013E, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_14_0 = UNIT_END + 0x0140, // Size: 12, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_14_PROPERTIES = UNIT_END + 0x014C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_14_PAD = UNIT_END + 0x014D, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_15_CREATOR = UNIT_END + 0x014E, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_15_0 = UNIT_END + 0x0150, // Size: 12, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_15_PROPERTIES = UNIT_END + 0x015C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_15_PAD = UNIT_END + 0x015D, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_16_CREATOR = UNIT_END + 0x015E, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_16_0 = UNIT_END + 0x0160, // Size: 12, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_16_PROPERTIES = UNIT_END + 0x016C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_16_PAD = UNIT_END + 0x016D, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_17_CREATOR = UNIT_END + 0x016E, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_17_0 = UNIT_END + 0x0170, // Size: 12, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_17_PROPERTIES = UNIT_END + 0x017C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_17_PAD = UNIT_END + 0x017D, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_18_CREATOR = UNIT_END + 0x017E, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_18_0 = UNIT_END + 0x0180, // Size: 12, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_18_PROPERTIES = UNIT_END + 0x018C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_18_PAD = UNIT_END + 0x018D, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_19_CREATOR = UNIT_END + 0x018E, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_19_0 = UNIT_END + 0x0190, // Size: 12, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_19_PROPERTIES = UNIT_END + 0x019C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_19_PAD = UNIT_END + 0x019D, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_CHOSEN_TITLE = UNIT_END + 0x019E, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_FIELD_PAD_0 = UNIT_END + 0x019F, // Size: 1, Type: INT, Flags: NONE + PLAYER_FIELD_INV_SLOT_HEAD = UNIT_END + 0x01A0, // Size: 46, Type: LONG, Flags: PRIVATE + PLAYER_FIELD_PACK_SLOT_1 = UNIT_END + 0x01CE, // Size: 32, Type: LONG, Flags: PRIVATE + PLAYER_FIELD_BANK_SLOT_1 = UNIT_END + 0x01EE, // Size: 56, Type: LONG, Flags: PRIVATE + PLAYER_FIELD_BANKBAG_SLOT_1 = UNIT_END + 0x0226, // Size: 14, Type: LONG, Flags: PRIVATE + PLAYER_FIELD_VENDORBUYBACK_SLOT_1 = UNIT_END + 0x0234, // Size: 24, Type: LONG, Flags: PRIVATE + PLAYER_FIELD_KEYRING_SLOT_1 = UNIT_END + 0x024C, // Size: 64, Type: LONG, Flags: PRIVATE + PLAYER_FIELD_VANITYPET_SLOT_1 = UNIT_END + 0x028C, // Size: 36, Type: LONG, Flags: PRIVATE + PLAYER_FARSIGHT = UNIT_END + 0x02B0, // Size: 2, Type: LONG, Flags: PRIVATE + PLAYER__FIELD_KNOWN_TITLES = UNIT_END + 0x02B2, // Size: 2, Type: LONG, Flags: PRIVATE + PLAYER_XP = UNIT_END + 0x02B4, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_NEXT_LEVEL_XP = UNIT_END + 0x02B5, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_SKILL_INFO_1_1 = UNIT_END + 0x02B6, // Size: 384, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_CHARACTER_POINTS1 = UNIT_END + 0x0436, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_CHARACTER_POINTS2 = UNIT_END + 0x0437, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_TRACK_CREATURES = UNIT_END + 0x0438, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_TRACK_RESOURCES = UNIT_END + 0x0439, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_BLOCK_PERCENTAGE = UNIT_END + 0x043A, // Size: 1, Type: FLOAT, Flags: PRIVATE + PLAYER_DODGE_PERCENTAGE = UNIT_END + 0x043B, // Size: 1, Type: FLOAT, Flags: PRIVATE + PLAYER_PARRY_PERCENTAGE = UNIT_END + 0x043C, // Size: 1, Type: FLOAT, Flags: PRIVATE + PLAYER_EXPERTISE = UNIT_END + 0x043D, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_OFFHAND_EXPERTISE = UNIT_END + 0x043E, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_CRIT_PERCENTAGE = UNIT_END + 0x043F, // Size: 1, Type: FLOAT, Flags: PRIVATE + PLAYER_RANGED_CRIT_PERCENTAGE = UNIT_END + 0x0440, // Size: 1, Type: FLOAT, Flags: PRIVATE + PLAYER_OFFHAND_CRIT_PERCENTAGE = UNIT_END + 0x0441, // Size: 1, Type: FLOAT, Flags: PRIVATE + PLAYER_SPELL_CRIT_PERCENTAGE1 = UNIT_END + 0x0442, // Size: 7, Type: FLOAT, Flags: PRIVATE + PLAYER_SHIELD_BLOCK = UNIT_END + 0x0449, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_EXPLORED_ZONES_1 = UNIT_END + 0x044A, // Size: 128, Type: BYTES, Flags: PRIVATE + PLAYER_REST_STATE_EXPERIENCE = UNIT_END + 0x04CA, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_COINAGE = UNIT_END + 0x04CB, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_MOD_DAMAGE_DONE_POS = UNIT_END + 0x04CC, // Size: 7, Type: INT, Flags: PRIVATE + PLAYER_FIELD_MOD_DAMAGE_DONE_NEG = UNIT_END + 0x04D3, // Size: 7, Type: INT, Flags: PRIVATE + PLAYER_FIELD_MOD_DAMAGE_DONE_PCT = UNIT_END + 0x04DA, // Size: 7, Type: INT, Flags: PRIVATE + PLAYER_FIELD_MOD_HEALING_DONE_POS = UNIT_END + 0x04E1, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_MOD_TARGET_RESISTANCE = UNIT_END + 0x04E2, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE = UNIT_END + 0x04E3, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_BYTES = UNIT_END + 0x04E4, // Size: 1, Type: BYTES, Flags: PRIVATE + PLAYER_AMMO_ID = UNIT_END + 0x04E5, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_SELF_RES_SPELL = UNIT_END + 0x04E6, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_PVP_MEDALS = UNIT_END + 0x04E7, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_BUYBACK_PRICE_1 = UNIT_END + 0x04E8, // Size: 12, Type: INT, Flags: PRIVATE + PLAYER_FIELD_BUYBACK_TIMESTAMP_1 = UNIT_END + 0x04F4, // Size: 12, Type: INT, Flags: PRIVATE + PLAYER_FIELD_KILLS = UNIT_END + 0x0500, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_FIELD_TODAY_CONTRIBUTION = UNIT_END + 0x0501, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_YESTERDAY_CONTRIBUTION = UNIT_END + 0x0502, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_LIFETIME_HONORBALE_KILLS = UNIT_END + 0x0503, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_BYTES2 = UNIT_END + 0x0504, // Size: 1, Type: BYTES, Flags: PRIVATE + PLAYER_FIELD_WATCHED_FACTION_INDEX = UNIT_END + 0x0505, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_COMBAT_RATING_1 = UNIT_END + 0x0506, // Size: 24, Type: INT, Flags: PRIVATE + PLAYER_FIELD_ARENA_TEAM_INFO_1_1 = UNIT_END + 0x051E, // Size: 18, Type: INT, Flags: PRIVATE + PLAYER_FIELD_HONOR_CURRENCY = UNIT_END + 0x0530, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_ARENA_CURRENCY = UNIT_END + 0x0531, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_MOD_MANA_REGEN = UNIT_END + 0x0532, // Size: 1, Type: FLOAT, Flags: PRIVATE + PLAYER_FIELD_MOD_MANA_REGEN_INTERRUPT = UNIT_END + 0x0533, // Size: 1, Type: FLOAT, Flags: PRIVATE + PLAYER_FIELD_MAX_LEVEL = UNIT_END + 0x0534, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_DAILY_QUESTS_1 = UNIT_END + 0x0535, // Size: 25, Type: INT, Flags: PRIVATE + PLAYER_END = UNIT_END + 0x054E, +}; + +enum EGameObjectFields +{ + OBJECT_FIELD_CREATED_BY = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC + GAMEOBJECT_DISPLAYID = OBJECT_END + 0x0002, // Size: 1, Type: INT, Flags: PUBLIC + GAMEOBJECT_FLAGS = OBJECT_END + 0x0003, // Size: 1, Type: INT, Flags: PUBLIC + GAMEOBJECT_ROTATION = OBJECT_END + 0x0004, // Size: 4, Type: FLOAT, Flags: PUBLIC + GAMEOBJECT_STATE = OBJECT_END + 0x0008, // Size: 1, Type: INT, Flags: PUBLIC + GAMEOBJECT_POS_X = OBJECT_END + 0x0009, // Size: 1, Type: FLOAT, Flags: PUBLIC + GAMEOBJECT_POS_Y = OBJECT_END + 0x000A, // Size: 1, Type: FLOAT, Flags: PUBLIC + GAMEOBJECT_POS_Z = OBJECT_END + 0x000B, // Size: 1, Type: FLOAT, Flags: PUBLIC + GAMEOBJECT_FACING = OBJECT_END + 0x000C, // Size: 1, Type: FLOAT, Flags: PUBLIC + GAMEOBJECT_DYN_FLAGS = OBJECT_END + 0x000D, // Size: 1, Type: INT, Flags: DYNAMIC + GAMEOBJECT_FACTION = OBJECT_END + 0x000E, // Size: 1, Type: INT, Flags: PUBLIC + GAMEOBJECT_TYPE_ID = OBJECT_END + 0x000F, // Size: 1, Type: INT, Flags: PUBLIC + GAMEOBJECT_LEVEL = OBJECT_END + 0x0010, // Size: 1, Type: INT, Flags: PUBLIC + GAMEOBJECT_ARTKIT = OBJECT_END + 0x0011, // Size: 1, Type: INT, Flags: PUBLIC + GAMEOBJECT_ANIMPROGRESS = OBJECT_END + 0x0012, // Size: 1, Type: INT, Flags: DYNAMIC + GAMEOBJECT_PADDING = OBJECT_END + 0x0013, // Size: 1, Type: INT, Flags: NONE + GAMEOBJECT_END = OBJECT_END + 0x0014, +}; + +enum EDynamicObjectFields +{ + DYNAMICOBJECT_CASTER = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC + DYNAMICOBJECT_BYTES = OBJECT_END + 0x0002, // Size: 1, Type: BYTES, Flags: PUBLIC + DYNAMICOBJECT_SPELLID = OBJECT_END + 0x0003, // Size: 1, Type: INT, Flags: PUBLIC + DYNAMICOBJECT_RADIUS = OBJECT_END + 0x0004, // Size: 1, Type: FLOAT, Flags: PUBLIC + DYNAMICOBJECT_POS_X = OBJECT_END + 0x0005, // Size: 1, Type: FLOAT, Flags: PUBLIC + DYNAMICOBJECT_POS_Y = OBJECT_END + 0x0006, // Size: 1, Type: FLOAT, Flags: PUBLIC + DYNAMICOBJECT_POS_Z = OBJECT_END + 0x0007, // Size: 1, Type: FLOAT, Flags: PUBLIC + DYNAMICOBJECT_FACING = OBJECT_END + 0x0008, // Size: 1, Type: FLOAT, Flags: PUBLIC + DYNAMICOBJECT_CASTTIME = OBJECT_END + 0x0009, // Size: 1, Type: INT, Flags: PUBLIC + DYNAMICOBJECT_END = OBJECT_END + 0x000A, +}; + +enum ECorpseFields +{ + CORPSE_FIELD_OWNER = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC + CORPSE_FIELD_PARTY = OBJECT_END + 0x0002, // Size: 2, Type: LONG, Flags: PUBLIC + CORPSE_FIELD_FACING = OBJECT_END + 0x0004, // Size: 1, Type: FLOAT, Flags: PUBLIC + CORPSE_FIELD_POS_X = OBJECT_END + 0x0005, // Size: 1, Type: FLOAT, Flags: PUBLIC + CORPSE_FIELD_POS_Y = OBJECT_END + 0x0006, // Size: 1, Type: FLOAT, Flags: PUBLIC + CORPSE_FIELD_POS_Z = OBJECT_END + 0x0007, // Size: 1, Type: FLOAT, Flags: PUBLIC + CORPSE_FIELD_DISPLAY_ID = OBJECT_END + 0x0008, // Size: 1, Type: INT, Flags: PUBLIC + CORPSE_FIELD_ITEM = OBJECT_END + 0x0009, // Size: 19, Type: INT, Flags: PUBLIC + CORPSE_FIELD_BYTES_1 = OBJECT_END + 0x001C, // Size: 1, Type: BYTES, Flags: PUBLIC + CORPSE_FIELD_BYTES_2 = OBJECT_END + 0x001D, // Size: 1, Type: BYTES, Flags: PUBLIC + CORPSE_FIELD_GUILD = OBJECT_END + 0x001E, // Size: 1, Type: INT, Flags: PUBLIC + CORPSE_FIELD_FLAGS = OBJECT_END + 0x001F, // Size: 1, Type: INT, Flags: PUBLIC + CORPSE_FIELD_DYNAMIC_FLAGS = OBJECT_END + 0x0020, // Size: 1, Type: INT, Flags: DYNAMIC + CORPSE_FIELD_PAD = OBJECT_END + 0x0021, // Size: 1, Type: INT, Flags: NONE + CORPSE_END = OBJECT_END + 0x0022, +}; +#endif diff --git a/src/game/UpdateMask.h b/src/game/UpdateMask.h new file mode 100644 index 00000000000..7b0b7bb0c6d --- /dev/null +++ b/src/game/UpdateMask.h @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __UPDATEMASK_H +#define __UPDATEMASK_H + +#include "UpdateFields.h" +#include "Errors.h" + +class UpdateMask +{ + public: + UpdateMask( ) : mCount( 0 ), mBlocks( 0 ), mUpdateMask( 0 ) { } + UpdateMask( const UpdateMask& mask ) : mUpdateMask( 0 ) { *this = mask; } + + ~UpdateMask( ) + { + if(mUpdateMask) + delete [] mUpdateMask; + } + + inline void SetBit (uint32 index) + { + ( (uint8 *)mUpdateMask )[ index >> 3 ] |= 1 << ( index & 0x7 ); + } + + inline void UnsetBit (uint32 index) + { + ( (uint8 *)mUpdateMask )[ index >> 3 ] &= (0xff ^ (1 << ( index & 0x7 ) ) ); + } + + inline bool GetBit (uint32 index) + { + return ( ( (uint8 *)mUpdateMask)[ index >> 3 ] & ( 1 << ( index & 0x7 ) )) != 0; + } + + inline uint32 GetBlockCount() { return mBlocks; } + inline uint32 GetLength() { return mBlocks << 2; } + inline uint32 GetCount() { return mCount; } + inline uint8* GetMask() { return (uint8*)mUpdateMask; } + + inline void SetCount (uint32 valuesCount) + { + if(mUpdateMask) + delete [] mUpdateMask; + + mCount = valuesCount; + mBlocks = (valuesCount + 31) / 32; + + mUpdateMask = new uint32[mBlocks]; + memset(mUpdateMask, 0, mBlocks << 2); + } + + inline void Clear() + { + if (mUpdateMask) + memset(mUpdateMask, 0, mBlocks << 2); + } + + inline UpdateMask& operator = ( const UpdateMask& mask ) + { + SetCount(mask.mCount); + memcpy(mUpdateMask, mask.mUpdateMask, mBlocks << 2); + + return *this; + } + + inline void operator &= ( const UpdateMask& mask ) + { + ASSERT(mask.mCount <= mCount); + for (uint32 i = 0; i < mBlocks; i++) + mUpdateMask[i] &= mask.mUpdateMask[i]; + } + + inline void operator |= ( const UpdateMask& mask ) + { + ASSERT(mask.mCount <= mCount); + for (uint32 i = 0; i < mBlocks; i++) + mUpdateMask[i] |= mask.mUpdateMask[i]; + } + + inline UpdateMask operator & ( const UpdateMask& mask ) const + { + ASSERT(mask.mCount <= mCount); + + UpdateMask newmask; + newmask = *this; + newmask &= mask; + + return newmask; + } + + inline UpdateMask operator | ( const UpdateMask& mask ) const + { + ASSERT(mask.mCount <= mCount); + + UpdateMask newmask; + newmask = *this; + newmask |= mask; + + return newmask; + } + + private: + uint32 mCount; + uint32 mBlocks; + uint32 *mUpdateMask; +}; +#endif diff --git a/src/game/VoiceChatHandler.cpp b/src/game/VoiceChatHandler.cpp new file mode 100644 index 00000000000..1368ddc4f85 --- /dev/null +++ b/src/game/VoiceChatHandler.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "World.h" +#include "Opcodes.h" +#include "Log.h" + +void WorldSession::HandleVoiceSettingsOpcode( WorldPacket & recv_data ) +{ + sLog.outDebug("WORLD: CMSG_VOICE_SETTINGS"); + // uint8 isVoiceEnabled, uint8 isMicrophoneEnabled + recv_data.hexlike(); +} + +void WorldSession::HandleChannelEnableVoiceOpcode( WorldPacket & recv_data ) +{ + sLog.outDebug("WORLD: CMSG_CHANNEL_ENABLE_VOICE"); + // Enable Voice button in channel context menu + recv_data.hexlike(); +} + +void WorldSession::HandleChannelVoiceChatQuery( WorldPacket & recv_data ) +{ + sLog.outDebug("WORLD: CMSG_CHANNEL_VOICE_CHAT_QUERY"); + // uint32, string + recv_data.hexlike(); +} diff --git a/src/game/WaypointManager.cpp b/src/game/WaypointManager.cpp new file mode 100644 index 00000000000..a4b809ddbef --- /dev/null +++ b/src/game/WaypointManager.cpp @@ -0,0 +1,272 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Database/DatabaseEnv.h" +#include "GridDefines.h" +#include "Policies/SingletonImp.h" +#include "WaypointManager.h" +#include "ProgressBar.h" +#include "MapManager.h" + +INSTANTIATE_SINGLETON_1(WaypointManager); + +bool WaypointBehavior::isEmpty() +{ + return emote == 0 && spell == 0 && model1 == 0 && model2 == 0 && text[0].empty() && + text[1].empty() && text[2].empty() && text[3].empty() && text[4].empty(); +} + +WaypointBehavior::WaypointBehavior(const WaypointBehavior &b) +{ + emote = b.emote; spell = b.spell; model1 = b.model1; model2 = b.model2; + text[0] = b.text[0]; text[1] = b.text[1]; text[2] = b.text[2]; + text[3] = b.text[3]; text[4] = b.text[4]; +} + +void WaypointManager::Load() +{ + Cleanup(); + + uint32 total_paths = 0; + uint32 total_nodes = 0; + uint32 total_behaviors = 0; + + QueryResult *result = WorldDatabase.Query("SELECT id, COUNT(point) FROM creature_movement GROUP BY id"); + if(result) + { + total_paths = result->GetRowCount(); + barGoLink bar( total_paths ); + do + { + Field *fields = result->Fetch(); + uint32 id = fields[0].GetUInt32(); + uint32 count = fields[1].GetUInt32(); + m_pathMap[id].resize(count); + + total_nodes += count; + bar.step(); + } while( result->NextRow() ); + delete result; + } + + result = WorldDatabase.Query("SELECT position_x, position_y, position_z, orientation, model1, model2, waittime, emote, spell, text1, text2, text3, text4, text5, id, point FROM creature_movement"); + if(result) + { + barGoLink bar( result->GetRowCount() ); + do + { + Field *fields = result->Fetch(); + uint32 point = fields[15].GetUInt32(); + uint32 id = fields[14].GetUInt32(); + + WaypointPath &path = m_pathMap[id]; + // the cleanup queries make sure the following is true + assert(point >= 1 && point <= path.size()); + WaypointNode &node = path[point-1]; + + node.x = fields[0].GetFloat(); + node.y = fields[1].GetFloat(); + node.z = fields[2].GetFloat(); + node.orientation = fields[3].GetFloat(); + node.delay = fields[6].GetUInt16(); + + // prevent using invalid coordinates + if(!MaNGOS::IsValidMapCoord(node.x, node.y, node.z, node.orientation)) + { + QueryResult *result1 = WorldDatabase.PQuery("SELECT id, map FROM creature WHERE guid = '%u'", id); + if(result1) sLog.outErrorDb("ERROR: Creature (guidlow %d, entry %d) have invalid coordinates in his waypoint %d (X: %d, Y: %d).", id, result1->Fetch()[0].GetUInt32(), point, node.x, node.y); + else sLog.outErrorDb("ERROR: Waypoint path %d, have invalid coordinates in his waypoint %d (X: %d, Y: %d).", id, point, node.x, node.y); + + MaNGOS::NormalizeMapCoord(node.x); + MaNGOS::NormalizeMapCoord(node.y); + if(result1) + { + node.z = MapManager::Instance ().GetBaseMap(result1->Fetch()[1].GetUInt32())->GetHeight(node.x, node.y, node.z); + delete result1; + } + WorldDatabase.PExecute("UPDATE creature_movement SET position_x = '%f', position_y = '%f', position_z = '%f' WHERE id = '%u' AND point = '%u'", node.x, node.y, node.z, id, point); + } + + WaypointBehavior be; + be.model1 = fields[4].GetUInt32(); + be.model2 = fields[5].GetUInt32(); + be.emote = fields[7].GetUInt32(); + be.spell = fields[8].GetUInt32(); + be.text[0] = fields[9].GetCppString(); + be.text[1] = fields[10].GetCppString(); + be.text[2] = fields[11].GetCppString(); + be.text[3] = fields[12].GetCppString(); + be.text[4] = fields[13].GetCppString(); + + // save memory by not storing empty behaviors + if(!be.isEmpty()) + { + node.behavior = new WaypointBehavior(be); + ++total_behaviors; + } + else + node.behavior = NULL; + bar.step(); + } while( result->NextRow() ); + delete result; + } + sLog.outString( ">> Loaded %u paths, %u nodes and %u behaviors", total_paths, total_nodes, total_behaviors); +} + +void WaypointManager::Cleanup() +{ + // check if points need to be renumbered and do it + if(QueryResult *result = WorldDatabase.Query("SELECT 1 from creature_movement As T WHERE point <> (SELECT COUNT(*) FROM creature_movement WHERE id = T.id AND point <= T.point) LIMIT 1")) + { + delete result; + WorldDatabase.DirectExecute("CREATE TEMPORARY TABLE temp LIKE creature_movement"); + WorldDatabase.DirectExecute("INSERT INTO temp SELECT * FROM creature_movement"); + WorldDatabase.DirectExecute("ALTER TABLE creature_movement DROP PRIMARY KEY"); + WorldDatabase.DirectExecute("UPDATE creature_movement AS T SET point = (SELECT COUNT(*) FROM temp WHERE id = T.id AND point <= T.point)"); + WorldDatabase.DirectExecute("ALTER TABLE creature_movement ADD PRIMARY KEY (id, point)"); + WorldDatabase.DirectExecute("DROP TABLE temp"); + assert(!(result = WorldDatabase.Query("SELECT 1 from creature_movement As T WHERE point <> (SELECT COUNT(*) FROM creature_movement WHERE id = T.id AND point <= T.point) LIMIT 1"))); + } +} + +void WaypointManager::Unload() +{ + for(WaypointPathMap::iterator itr = m_pathMap.begin(); itr != m_pathMap.end(); ++itr) + _clearPath(itr->second); + m_pathMap.clear(); +} + +void WaypointManager::_clearPath(WaypointPath &path) +{ + for(WaypointPath::iterator itr = path.begin(); itr != path.end(); ++itr) + if(itr->behavior) + delete itr->behavior; + path.clear(); +} + +/// - Insert after the last point +void WaypointManager::AddLastNode(uint32 id, float x, float y, float z, float o, uint32 delay, uint32 wpGuid) +{ + _addNode(id, GetLastPoint(id, 0) + 1, x, y, z, o, delay, wpGuid); +} + +/// - Insert after a certain point +void WaypointManager::AddAfterNode(uint32 id, uint32 point, float x, float y, float z, float o, uint32 delay, uint32 wpGuid) +{ + for(uint32 i = GetLastPoint(id, 0); i > point; i--) + WorldDatabase.PExecuteLog("UPDATE creature_movement SET point=point+1 WHERE id='%u' AND point='%u'", id, i); + + _addNode(id, point + 1, x, y, z, o, delay, wpGuid); +} + +/// - Insert without checking for collision +void WaypointManager::_addNode(uint32 id, uint32 point, float x, float y, float z, float o, uint32 delay, uint32 wpGuid) +{ + if(point == 0) return; // counted from 1 in the DB + WorldDatabase.PExecuteLog("INSERT INTO creature_movement (id,point,position_x,position_y,position_z,orientation,wpguid,waittime) VALUES ('%u','%u','%f', '%f', '%f', '%f', '%d', '%d')", id, point, x, y, z, o, wpGuid, delay); + WaypointPathMap::iterator itr = m_pathMap.find(id); + if(itr == m_pathMap.end()) + itr = m_pathMap.insert(WaypointPathMap::value_type(id, WaypointPath())).first; + itr->second.insert(itr->second.begin() + (point - 1), WaypointNode(x, y, z, o, delay, NULL)); +} + +uint32 WaypointManager::GetLastPoint(uint32 id, uint32 default_notfound) +{ + uint32 point = default_notfound; + /*QueryResult *result = WorldDatabase.PQuery( "SELECT MAX(point) FROM creature_movement WHERE id = '%u'", id); + if( result ) + { + point = (*result)[0].GetUInt32()+1; + delete result; + }*/ + WaypointPathMap::iterator itr = m_pathMap.find(id); + if(itr != m_pathMap.end() && itr->second.size() != 0) + point = itr->second.size(); + return point; +} + +void WaypointManager::DeleteNode(uint32 id, uint32 point) +{ + if(point == 0) return; // counted from 1 in the DB + WorldDatabase.PExecuteLog("DELETE FROM creature_movement WHERE id='%u' AND point='%u'", id, point); + WorldDatabase.PExecuteLog("UPDATE creature_movement SET point=point-1 WHERE id='%u' AND point>'%u'", id, point); + WaypointPathMap::iterator itr = m_pathMap.find(id); + if(itr != m_pathMap.end() && point <= itr->second.size()) + itr->second.erase(itr->second.begin() + (point-1)); +} + +void WaypointManager::DeletePath(uint32 id) +{ + WorldDatabase.PExecuteLog("DELETE FROM creature_movement WHERE id='%u'", id); + WaypointPathMap::iterator itr = m_pathMap.find(id); + if(itr != m_pathMap.end()) + _clearPath(itr->second); + // the path is not removed from the map, just cleared + // WMGs have pointers to the path, so deleting them would crash + // this wastes some memory, but these functions are + // only meant to be called by GM commands +} + +void WaypointManager::SetNodePosition(uint32 id, uint32 point, float x, float y, float z) +{ + if(point == 0) return; // counted from 1 in the DB + WorldDatabase.PExecuteLog("UPDATE creature_movement SET position_x = '%f',position_y = '%f',position_z = '%f' where id = '%u' AND point='%u'", x, y, z, id, point); + WaypointPathMap::iterator itr = m_pathMap.find(id); + if(itr != m_pathMap.end() && point <= itr->second.size()) + { + itr->second[point-1].x = x; + itr->second[point-1].y = y; + itr->second[point-1].z = z; + } +} + +void WaypointManager::SetNodeText(uint32 id, uint32 point, const char *text_field, const char *text) +{ + if(point == 0) return; // counted from 1 in the DB + if(!text_field) return; + std::string field = text_field; + WorldDatabase.escape_string(field); + + if(!text) + { + WorldDatabase.PExecuteLog("UPDATE creature_movement SET %s=NULL WHERE id='%u' AND point='%u'", field.c_str(), id, point); + } + else + { + std::string text2 = text; + WorldDatabase.escape_string(text2); + WorldDatabase.PExecuteLog("UPDATE creature_movement SET %s='%s' WHERE id='%u' AND point='%u'", field.c_str(), text2.c_str(), id, point); + } + + WaypointPathMap::iterator itr = m_pathMap.find(id); + if(itr != m_pathMap.end() && point <= itr->second.size()) + { + WaypointNode &node = itr->second[point-1]; + if(!node.behavior) node.behavior = new WaypointBehavior(); + + if(field == "text1") node.behavior->text[0] = text ? text : ""; + if(field == "text2") node.behavior->text[1] = text ? text : ""; + if(field == "text3") node.behavior->text[2] = text ? text : ""; + if(field == "text4") node.behavior->text[3] = text ? text : ""; + if(field == "text5") node.behavior->text[4] = text ? text : ""; + if(field == "emote") node.behavior->emote = text ? atoi(text) : 0; + if(field == "spell") node.behavior->spell = text ? atoi(text) : 0; + if(field == "model1") node.behavior->model1 = text ? atoi(text) : 0; + if(field == "model2") node.behavior->model2 = text ? atoi(text) : 0; + } +} diff --git a/src/game/WaypointManager.h b/src/game/WaypointManager.h new file mode 100644 index 00000000000..f0b66b66077 --- /dev/null +++ b/src/game/WaypointManager.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_WAYPOINTMANAGER_H +#define MANGOS_WAYPOINTMANAGER_H + +#include +#include +#include "Utilities/HashMap.h" + +struct WaypointBehavior +{ + uint32 emote; + uint32 spell; + std::string text[5]; + uint32 model1; + uint32 model2; + + bool isEmpty(); + WaypointBehavior() {} + WaypointBehavior(const WaypointBehavior &b); +}; + +struct WaypointNode +{ + float x; + float y; + float z; + float orientation; + uint32 delay; + WaypointBehavior * behavior; + WaypointNode() {} + WaypointNode(float _x, float _y, float _z, float _o, uint32 _delay, WaypointBehavior * _behavior) + : x(_x), y(_y), z(_z), orientation(_o), delay(_delay), behavior(_behavior) {} +}; + +typedef std::vector WaypointPath; + +class WaypointManager +{ + public: + WaypointManager() {} + ~WaypointManager() { Unload(); } + + void Load(); + void Unload(); + + void Cleanup(); + + WaypointPath *GetPath(uint32 id) + { + WaypointPathMap::iterator itr = m_pathMap.find(id); + return itr != m_pathMap.end() ? &itr->second : NULL; + } + + void AddLastNode(uint32 id, float x, float y, float z, float o, uint32 delay, uint32 wpGuid); + void AddAfterNode(uint32 id, uint32 point, float x, float y, float z, float o, uint32 delay, uint32 wpGuid); + uint32 GetLastPoint(uint32 id, uint32 default_notfound); + void DeleteNode(uint32 id, uint32 point); + void DeletePath(uint32 id); + void SetNodePosition(uint32 id, uint32 point, float x, float y, float z); + void SetNodeText(uint32 id, uint32 point, const char *text_field, const char *text); + + private: + void _addNode(uint32 id, uint32 point, float x, float y, float z, float o, uint32 delay, uint32 wpGuid); + void _clearPath(WaypointPath &path); + + typedef HM_NAMESPACE::hash_map WaypointPathMap; + WaypointPathMap m_pathMap; +}; + +#define WaypointMgr MaNGOS::Singleton::Instance() + +#endif diff --git a/src/game/WaypointMovementGenerator.cpp b/src/game/WaypointMovementGenerator.cpp new file mode 100644 index 00000000000..0389e2ebc4b --- /dev/null +++ b/src/game/WaypointMovementGenerator.cpp @@ -0,0 +1,648 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* +creature_movement Table + +alter table creature_movement add `text1` varchar(255) default NULL; +alter table creature_movement add `text2` varchar(255) default NULL; +alter table creature_movement add `text3` varchar(255) default NULL; +alter table creature_movement add `text4` varchar(255) default NULL; +alter table creature_movement add `text5` varchar(255) default NULL; +alter table creature_movement add `emote` int(10) unsigned default '0'; +alter table creature_movement add `spell` int(5) unsigned default '0'; +alter table creature_movement add `wpguid` int(11) default '0'; + +*/ + +#include + +#include "WaypointMovementGenerator.h" +#include "ObjectMgr.h" +#include "Creature.h" +#include "DestinationHolderImp.h" +#include "CreatureAI.h" +#include "WaypointManager.h" + +#include + +//-----------------------------------------------// +void +WaypointMovementGenerator::LoadPath(Creature &c) +{ + sLog.outDetail("LoadPath: loading waypoint path for creature %d,%d", c.GetGUIDLow(), c.GetDBTableGUIDLow()); + + i_path = WaypointMgr.GetPath(c.GetDBTableGUIDLow()); + if(!i_path) + { + sLog.outErrorDb("WaypointMovementGenerator::LoadPath: creature %s(%d) doesn't have waypoint path", c.GetName(), c.GetDBTableGUIDLow()); + return; + } + + uint32 node_count = i_path->size(); + i_hasDone.resize(node_count); + for(uint32 i = 0; i < node_count-1; i++) + i_hasDone[i] = false; + + // to prevent a misbehaviour inside "update" + // update is always called with the next wp - but the wpSys needs the current + // so when the routine is called the first time, wpSys gets the last waypoint + // and this prevents the system from performing text/emote, etc + i_hasDone[node_count - 1] = true; +} + +void +WaypointMovementGenerator::ClearWaypoints() +{ + i_path = NULL; +} + +void +WaypointMovementGenerator::Initialize() +{ +} + +bool +WaypointMovementGenerator::Update(Creature &creature, const uint32 &diff) +{ + if(!&creature) + return true; + + // Waypoint movement can be switched on/off + // This is quite handy for escort quests and other stuff + if(creature.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED | UNIT_STAT_DISTRACTED)) + return true; + + // prevent a crash at empty waypoint path. + if(!i_path || i_path->empty()) + return true; + + // i_path was modified by chat commands for example + if(i_path->size() != i_hasDone.size()) + i_hasDone.resize(i_path->size()); + if(i_currentNode >= i_path->size()) + i_currentNode = 0; + + CreatureTraveller traveller(creature); + + i_nextMoveTime.Update(diff); + i_destinationHolder.UpdateTraveller(traveller, diff, false, true); + + // creature has been stoped in middle of the waypoint segment + if (!i_destinationHolder.HasArrived() && creature.IsStopped()) + { + if( i_nextMoveTime.Passed()) // Timer has elapsed, meaning this part controlled it + { + SetStopedByPlayer(false); + // Now we re-set destination to same node and start travel + creature.addUnitState(UNIT_STAT_ROAMING); + const WaypointNode &node = i_path->at(i_currentNode); + i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z); + i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime()); + } + else // if( !i_nextMoveTime.Passed()) + { // unexpected end of timer && creature stopped && not at end of segment + if (!IsStopedByPlayer()) + { // Put 30 seconds delay + i_destinationHolder.IncreaseTravelTime(STOP_TIME_FOR_PLAYER); + i_nextMoveTime.Reset(STOP_TIME_FOR_PLAYER); + SetStopedByPlayer(true); // Mark we did it + } + } + return true; // Abort here this update + } + + if( creature.IsStopped()) + { + uint32 idx = i_currentNode > 0 ? i_currentNode-1 : i_path->size()-1; + + if (!i_hasDone[idx]) + { + if (i_path->at(idx).orientation !=100) + creature.SetOrientation(i_path->at(idx).orientation); + + if(WaypointBehavior *behavior = i_path->at(idx).behavior) + { + if(behavior->emote != 0) + creature.SetUInt32Value(UNIT_NPC_EMOTESTATE,behavior->emote); + if(behavior->spell != 0) + creature.CastSpell(&creature,behavior->spell, false); + if(behavior->model1 != 0) + creature.SetDisplayId(behavior->model1); + if(!behavior->text[0].empty()) + { + // Only one text is set + if( !behavior->text[1].empty() ) + { + // Select one from max 5 texts (0 and 1 laready checked) + int i = 2; + for( ; i < 5; ++i ) + if( behavior->text[i].empty() ) + break; + + creature.Say(behavior->text[rand() % i].c_str(), 0, 0); + + } + else + creature.Say(behavior->text[0].c_str(), 0, 0); + } + + i_hasDone[idx] = true; + MovementInform(creature); + } // wpBehaviour found + } // HasDone == false + } // i_creature.IsStopped() + + if( i_nextMoveTime.Passed() ) // This is at the end of waypoint segment or has been stopped by player + { + if( creature.IsStopped() ) // If stopped then begin a new move segment + { + creature.addUnitState(UNIT_STAT_ROAMING); + const WaypointNode &node = i_path->at(i_currentNode); + i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z); + i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime()); + uint32 idx = i_currentNode > 0 ? i_currentNode-1 : i_path->size()-1; + + if (i_path->at(idx).orientation !=100) + creature.SetOrientation(i_path->at(idx).orientation); + + if(WaypointBehavior *behavior = i_path->at(idx).behavior ) + { + i_hasDone[idx] = false; + if(behavior->model2 != 0) + creature.SetDisplayId(behavior->model2); + + creature.SetUInt32Value(UNIT_NPC_EMOTESTATE, 0); + } + } + else // If not stopped then stop it and set the reset of TimeTracker to waittime + { + creature.StopMoving(); + SetStopedByPlayer(false); + i_nextMoveTime.Reset(i_path->at(i_currentNode).delay); + ++i_currentNode; + if( i_currentNode >= i_path->size() ) + i_currentNode = 0; + } + } + return true; +} + +void WaypointMovementGenerator::MovementInform(Creature &unit) +{ + if(unit.AI()) + unit.AI()->MovementInform(WAYPOINT_MOTION_TYPE, i_currentNode); +} + +//----------------------------------------------------// +void +FlightPathMovementGenerator::LoadPath(Player &) +{ + objmgr.GetTaxiPathNodes(i_pathId, i_path,i_mapIds); +} + +uint32 +FlightPathMovementGenerator::GetPathAtMapEnd() const +{ + if(i_currentNode >= i_mapIds.size()) + return i_mapIds.size(); + + uint32 curMapId = i_mapIds[i_currentNode]; + for(uint32 i = i_currentNode; i < i_mapIds.size(); ++i) + { + if(i_mapIds[i] != curMapId) + return i; + } + + return i_mapIds.size(); +} + +void +FlightPathMovementGenerator::Initialize(Player &player) +{ + player.getHostilRefManager().setOnlineOfflineState(false); + player.addUnitState(UNIT_STAT_IN_FLIGHT); + player.SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT); + LoadPath(player); + Traveller traveller(player); + // do not send movement, it was sent already + i_destinationHolder.SetDestination(traveller, i_path[i_currentNode].x, i_path[i_currentNode].y, i_path[i_currentNode].z, false); + + player.SendMonsterMoveByPath(GetPath(),GetCurrentNode(),GetPathAtMapEnd(),MOVEMENTFLAG_WALK_MODE|MOVEMENTFLAG_ONTRANSPORT); +} + +void FlightPathMovementGenerator::Finalize(Player & player) +{ + + float x, y, z; + i_destinationHolder.GetLocationNow(player.GetMapId(), x, y, z); + player.SetPosition(x, y, z, player.GetOrientation()); + + player.clearUnitState(UNIT_STAT_IN_FLIGHT); + player.Unmount(); + player.RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT); + + if(player.m_taxi.empty()) + { + player.getHostilRefManager().setOnlineOfflineState(true); + if(player.pvpInfo.inHostileArea) + player.CastSpell(&player, 2479, true); + + player.SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); + player.StopMoving(); + } +} + +bool +FlightPathMovementGenerator::Update(Player &player, const uint32 &diff) +{ + if( MovementInProgress() ) + { + Traveller traveller(player); + if( i_destinationHolder.UpdateTraveller(traveller, diff, false) ) + { + i_destinationHolder.ResetUpdate(FLIGHT_TRAVEL_UPDATE); + if( i_destinationHolder.HasArrived() ) + { + uint32 curMap = i_mapIds[i_currentNode]; + ++i_currentNode; + if( MovementInProgress() ) + { + DEBUG_LOG("loading node %u for player %s", i_currentNode, player.GetName()); + if(i_mapIds[i_currentNode]==curMap) + { + // do not send movement, it was sent already + i_destinationHolder.SetDestination(traveller, i_path[i_currentNode].x, i_path[i_currentNode].y, i_path[i_currentNode].z, false); + } + return true; + } + //else HasArrived() + } + else + return true; + } + else + return true; + } + + // we have arrived at the end of the path + return false; +} + +void +FlightPathMovementGenerator::SetCurrentNodeAfterTeleport() +{ + if(i_mapIds.empty()) + return; + + uint32 map0 = i_mapIds[0]; + for(int i = 1; i < i_mapIds.size(); ++i) + { + if(i_mapIds[i]!=map0) + { + i_currentNode = i; + return; + } + } +} + +// +// Unique1's ASTAR Pathfinding Code... For future use & reference... +// + +#ifdef __PATHFINDING__ + +int GetFCost(int to, int num, int parentNum, float *gcost); // Below... + +int ShortenASTARRoute(short int *pathlist, int number) +{ // Wrote this to make the routes a little smarter (shorter)... No point looping back to the same places... Unique1 + short int temppathlist[MAX_PATHLIST_NODES]; + int count = 0; + // int count2 = 0; + int temp, temp2; + int link; + int upto = 0; + + for (temp = number; temp >= 0; temp--) + { + qboolean shortened = qfalse; + + for (temp2 = 0; temp2 < temp; temp2++) + { + for (link = 0; link < nodes[pathlist[temp]].enodenum; link++) + { + if (nodes[pathlist[temp]].links[link].flags & PATH_BLOCKED) + continue; + + //if ((bot->client->ps.eFlags & EF_TANK) && nodes[bot->current_node].links[link].flags & PATH_NOTANKS) //if this path is blocked, skip it + // continue; + + //if (nodes[nodes[pathlist[temp]].links[link].targetNode].origin[2] > nodes[pathlist[temp]].origin[2] + 32) + // continue; + + if (nodes[pathlist[temp]].links[link].targetNode == pathlist[temp2]) + { // Found a shorter route... + //if (OrgVisible(nodes[pathlist[temp2]].origin, nodes[pathlist[temp]].origin, -1)) + { + temppathlist[count] = pathlist[temp2]; + temp = temp2; + ++count; + shortened = qtrue; + } + } + } + } + + if (!shortened) + { + temppathlist[count] = pathlist[temp]; + ++count; + } + } + + upto = count; + + for (temp = 0; temp < count; temp++) + { + pathlist[temp] = temppathlist[upto]; + --upto; + } + + G_Printf("ShortenASTARRoute: Path size reduced from %i to %i nodes...n", number, count); + return count; +} + +/* +=========================================================================== +CreatePathAStar +This function uses the A* pathfinding algorithm to determine the +shortest path between any two nodes. +It's fairly complex, so I'm not really going to explain it much. +Look up A* and binary heaps for more info. +pathlist stores the ideal path between the nodes, in reverse order, +and the return value is the number of nodes in that path +=========================================================================== +*/ +int CreatePathAStar(gentity_t *bot, int from, int to, short int *pathlist) +{ + //all the data we have to hold...since we can't do dynamic allocation, has to be MAX_NODES + //we can probably lower this later - eg, the open list should never have more than at most a few dozen items on it + short int openlist[MAX_NODES+1]; //add 1 because it's a binary heap, and they don't use 0 - 1 is the first used index + float gcost[MAX_NODES]; + int fcost[MAX_NODES]; + char list[MAX_NODES]; //0 is neither, 1 is open, 2 is closed - char because it's the smallest data type + short int parent[MAX_NODES]; + + short int numOpen = 0; + short int atNode, temp, newnode=-1; + qboolean found = qfalse; + int count = -1; + float gc; + int i, u, v, m; + vec3_t vec; + + //clear out all the arrays + memset(openlist, 0, sizeof(short int)*(MAX_NODES+1)); + memset(fcost, 0, sizeof(int)*MAX_NODES); + memset(list, 0, sizeof(char)*MAX_NODES); + memset(parent, 0, sizeof(short int)*MAX_NODES); + memset(gcost, -1, sizeof(float)*MAX_NODES); + + //make sure we have valid data before calculating everything + if ((from == NODE_INVALID) || (to == NODE_INVALID) || (from >= MAX_NODES) || (to >= MAX_NODES) || (from == to)) + return -1; + + openlist[1] = from; //add the starting node to the open list + ++numOpen; + gcost[from] = 0; //its f and g costs are obviously 0 + fcost[from] = 0; + + while (1) + { + if (numOpen != 0) //if there are still items in the open list + { + //pop the top item off of the list + atNode = openlist[1]; + list[atNode] = 2; //put the node on the closed list so we don't check it again + --numOpen; + + openlist[1] = openlist[numOpen+1]; //move the last item in the list to the top position + v = 1; + + //this while loop reorders the list so that the new lowest fcost is at the top again + while (1) + { + u = v; + if ((2*u+1) < numOpen) //if both children exist + { + if (fcost[openlist[u]] >= fcost[openlist[2*u]]) + v = 2*u; + if (fcost[openlist[v]] >= fcost[openlist[2*u+1]]) + v = 2*u+1; + } + else + { + if ((2*u) < numOpen) //if only one child exists + { + if (fcost[openlist[u]] >= fcost[openlist[2*u]]) + v = 2*u; + } + } + + if (u != v) //if they're out of order, swap this item with its parent + { + temp = openlist[u]; + openlist[u] = openlist[v]; + openlist[v] = temp; + } + else + break; + } + + for (i = 0; i < nodes[atNode].enodenum; i++) //loop through all the links for this node + { + newnode = nodes[atNode].links[i].targetNode; + + //if this path is blocked, skip it + if (nodes[atNode].links[i].flags & PATH_BLOCKED) + continue; + //if this path is blocked, skip it + if (bot->client && (bot->client->ps.eFlags & EF_TANK) && nodes[atNode].links[i].flags & PATH_NOTANKS) + continue; + //skip any unreachable nodes + if (bot->client && (nodes[newnode].type & NODE_ALLY_UNREACHABLE) && (bot->client->sess.sessionTeam == TEAM_ALLIES)) + continue; + if (bot->client && (nodes[newnode].type & NODE_AXIS_UNREACHABLE) && (bot->client->sess.sessionTeam == TEAM_AXIS)) + continue; + + if (list[newnode] == 2) //if this node is on the closed list, skip it + continue; + + if (list[newnode] != 1) //if this node is not already on the open list + { + openlist[++numOpen] = newnode; //add the new node to the open list + list[newnode] = 1; + parent[newnode] = atNode; //record the node's parent + + if (newnode == to) //if we've found the goal, don't keep computing paths! + break; //this will break the 'for' and go all the way to 'if (list[to] == 1)' + + //store it's f cost value + fcost[newnode] = GetFCost(to, newnode, parent[newnode], gcost); + + //this loop re-orders the heap so that the lowest fcost is at the top + m = numOpen; + while (m != 1) //while this item isn't at the top of the heap already + { + //if it has a lower fcost than its parent + if (fcost[openlist[m]] <= fcost[openlist[m/2]]) + { + temp = openlist[m/2]; + openlist[m/2] = openlist[m]; + openlist[m] = temp; //swap them + m /= 2; + } + else + break; + } + } + else //if this node is already on the open list + { + gc = gcost[atNode]; + VectorSubtract(nodes[newnode].origin, nodes[atNode].origin, vec); + gc += VectorLength(vec); //calculate what the gcost would be if we reached this node along the current path + + if (gc < gcost[newnode]) //if the new gcost is less (ie, this path is shorter than what we had before) + { + parent[newnode] = atNode; //set the new parent for this node + gcost[newnode] = gc; //and the new g cost + + for (i = 1; i < numOpen; i++) //loop through all the items on the open list + { + if (openlist[i] == newnode) //find this node in the list + { + //calculate the new fcost and store it + fcost[newnode] = GetFCost(to, newnode, parent[newnode], gcost); + + //reorder the list again, with the lowest fcost item on top + m = i; + while (m != 1) + { + //if the item has a lower fcost than it's parent + if (fcost[openlist[m]] < fcost[openlist[m/2]]) + { + temp = openlist[m/2]; + openlist[m/2] = openlist[m]; + openlist[m] = temp; //swap them + m /= 2; + } + else + break; + } + break; //exit the 'for' loop because we already changed this node + } //if + } //for + } //if (gc < gcost[newnode]) + } //if (list[newnode] != 1) --> else + } //for (loop through links) + } //if (numOpen != 0) + else + { + found = qfalse; //there is no path between these nodes + break; + } + + if (list[to] == 1) //if the destination node is on the open list, we're done + { + found = qtrue; + break; + } + } //while (1) + + if (found == qtrue) //if we found a path + { + //G_Printf("%s - path found!n", bot->client->pers.netname); + count = 0; + + temp = to; //start at the end point + while (temp != from) //travel along the path (backwards) until we reach the starting point + { + pathlist[count++] = temp; //add the node to the pathlist and increment the count + temp = parent[temp]; //move to the parent of this node to continue the path + } + + pathlist[count++] = from; //add the beginning node to the end of the pathlist + + #ifdef __BOT_SHORTEN_ROUTING__ + count = ShortenASTARRoute(pathlist, count); // This isn't working... Dunno why.. Unique1 + #endif //__BOT_SHORTEN_ROUTING__ + } + else + { + //G_Printf("^1*** ^4BOT DEBUG^5: (CreatePathAStar) There is no route between node ^7%i^5 and node ^7%i^5.n", from, to); + count = CreateDumbRoute(from, to, pathlist); + + if (count > 0) + { + #ifdef __BOT_SHORTEN_ROUTING__ + count = ShortenASTARRoute(pathlist, count); // This isn't working... Dunno why.. Unique1 + #endif //__BOT_SHORTEN_ROUTING__ + return count; + } + } + + return count; //return the number of nodes in the path, -1 if not found +} + +/* +=========================================================================== +GetFCost +Utility function used by A* pathfinding to calculate the +cost to move between nodes towards a goal. Using the A* +algorithm F = G + H, G here is the distance along the node +paths the bot must travel, and H is the straight-line distance +to the goal node. +Returned as an int because more precision is unnecessary and it +will slightly speed up heap access +=========================================================================== +*/ +int GetFCost(int to, int num, int parentNum, float *gcost) +{ + float gc = 0; + float hc = 0; + vec3_t v; + + if (gcost[num] == -1) + { + if (parentNum != -1) + { + gc = gcost[parentNum]; + VectorSubtract(nodes[num].origin, nodes[parentNum].origin, v); + gc += VectorLength(v); + } + gcost[num] = gc; + } + else + gc = gcost[num]; + + VectorSubtract(nodes[to].origin, nodes[num].origin, v); + hc = VectorLength(v); + + return (int)(gc + hc); +} +#endif //__PATHFINDING__ diff --git a/src/game/WaypointMovementGenerator.h b/src/game/WaypointMovementGenerator.h new file mode 100644 index 00000000000..94762a961b6 --- /dev/null +++ b/src/game/WaypointMovementGenerator.h @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_WAYPOINTMOVEMENTGENERATOR_H +#define MANGOS_WAYPOINTMOVEMENTGENERATOR_H + +/** @page PathMovementGenerator is used to generate movements + * of waypoints and flight paths. Each serves the purpose + * of generate activities so that it generates updated + * packets for the players. + */ + +#include "MovementGenerator.h" +#include "DestinationHolder.h" +#include "WaypointManager.h" +#include "Path.h" +#include "Traveller.h" + +#include "Player.h" + +#include +#include + +#define FLIGHT_TRAVEL_UPDATE 100 +#define STOP_TIME_FOR_PLAYER 3 * 60 * 1000 // 3 Minutes + +template +class MANGOS_DLL_SPEC PathMovementBase +{ + public: + PathMovementBase() : i_currentNode(0) {} + virtual ~PathMovementBase() {}; + + inline bool MovementInProgress(void) const { return i_currentNode < i_path.Size(); } + + // template pattern, not defined .. override required + void LoadPath(T &); + void ReloadPath(T &); + uint32 GetCurrentNode() const { return i_currentNode; } + + bool GetDestination(float& x, float& y, float& z) const { i_destinationHolder.GetDestination(x,y,z); return true; } + protected: + uint32 i_currentNode; + DestinationHolder< Traveller > i_destinationHolder; + P i_path; +}; + +/** WaypointMovementGenerator loads a series of way points + * from the DB and apply it to the creature's movement generator. + * Hence, the creature will move according to its predefined way points. + */ + +template +class MANGOS_DLL_SPEC WaypointMovementGenerator; + +template<> +class MANGOS_DLL_SPEC WaypointMovementGenerator +: public MovementGeneratorMedium< Creature, WaypointMovementGenerator >, +public PathMovementBase +{ + TimeTrackerSmall i_nextMoveTime; + std::vector i_hasDone; + public: + WaypointMovementGenerator(Creature &) : i_nextMoveTime(0) {} + ~WaypointMovementGenerator() { ClearWaypoints(); } + void Initialize(Creature &u) + { + i_nextMoveTime.Reset(0); // TODO: check the lower bound (0 is probably too small) + u.StopMoving(); + LoadPath(u); + } + void Finalize(Creature &) {} + void Reset(Creature &u) { ReloadPath(u); } + bool Update(Creature &u, const uint32 &diff); + + void MovementInform(Creature &); + + MovementGeneratorType GetMovementGeneratorType() { return WAYPOINT_MOTION_TYPE; } + + // now path movement implmementation + void LoadPath(Creature &c); + void ReloadPath(Creature &c) { ClearWaypoints(); LoadPath(c); } + + // Player stoping creature + bool IsStopedByPlayer() { return b_StopedByPlayer; } + void SetStopedByPlayer(bool val) { b_StopedByPlayer = val; } + + // statics + static void Initialize(void); + private: + void ClearWaypoints(); + bool b_StopedByPlayer; +}; + +/** FlightPathMovementGenerator generates movement of the player for the paths + * and hence generates ground and activities for the player. + */ +class MANGOS_DLL_SPEC FlightPathMovementGenerator +: public MovementGeneratorMedium< Player, FlightPathMovementGenerator >, +public PathMovementBase +{ + uint32 i_pathId; + std::vector i_mapIds; + public: + explicit FlightPathMovementGenerator(uint32 id, uint32 startNode = 0) : i_pathId(id) { i_currentNode = startNode; } + void Initialize(Player &); + void Finalize(Player &); + void Reset(Player &) {} + bool Update(Player &, const uint32 &); + MovementGeneratorType GetMovementGeneratorType() { return FLIGHT_MOTION_TYPE; } + + void LoadPath(Player &); + void ReloadPath(Player &) { /* don't reload flight path */ } + + Path& GetPath() { return i_path; } + uint32 GetPathAtMapEnd() const; + inline bool HasArrived() const { return (i_currentNode >= i_path.Size()); } + void SetCurrentNodeAfterTeleport(); + void SkipCurrentNode() { ++i_currentNode; } +}; +#endif diff --git a/src/game/Weather.cpp b/src/game/Weather.cpp new file mode 100644 index 00000000000..77e81f0b16d --- /dev/null +++ b/src/game/Weather.cpp @@ -0,0 +1,318 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** \file + \ingroup world +*/ + +#include "Weather.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Player.h" +#include "World.h" +#include "Log.h" +#include "ObjectMgr.h" +#include "Util.h" + +/// Create the Weather object +Weather::Weather(uint32 zone, WeatherZoneChances const* weatherChances) : m_zone(zone), m_weatherChances(weatherChances) +{ + m_timer.SetInterval(sWorld.getConfig(CONFIG_INTERVAL_CHANGEWEATHER)); + m_type = WEATHER_TYPE_FINE; + m_grade = 0; + + sLog.outDetail("WORLD: Starting weather system for zone %u (change every %u minutes).", m_zone, (uint32)(m_timer.GetInterval() / (1000*MINUTE)) ); +} + +/// Launch a weather update +bool Weather::Update(time_t diff) +{ + if (m_timer.GetCurrent()>=0) + m_timer.Update(diff); + else m_timer.SetCurrent(0); + + ///- If the timer has passed, ReGenerate the weather + if(m_timer.Passed()) + { + m_timer.Reset(); + // update only if Regenerate has changed the weather + if(ReGenerate()) + { + ///- Weather will be removed if not updated (no players in zone anymore) + if(!UpdateWeather()) + return false; + } + } + return true; +} + +/// Calculate the new weather +bool Weather::ReGenerate() +{ + if (!m_weatherChances) + { + m_type = WEATHER_TYPE_FINE; + m_grade = 0.0f; + return false; + } + + /// Weather statistics: + ///- 30% - no change + ///- 30% - weather gets better (if not fine) or change weather type + ///- 30% - weather worsens (if not fine) + ///- 10% - radical change (if not fine) + uint32 u = urand(0, 99); + + if (u < 30) + return false; + + // remember old values + WeatherType old_type = m_type; + float old_grade = m_grade; + + //78 days between January 1st and March 20nd; 365/4=91 days by season + // season source http://aa.usno.navy.mil/data/docs/EarthSeasons.html + time_t gtime = sWorld.GetGameTime(); + struct tm * ltime = localtime(>ime); + uint32 season = ((ltime->tm_yday - 78 + 365)/91)%4; + + static char const* seasonName[WEATHER_SEASONS] = { "spring", "summer", "fall", "winter" }; + + sLog.outDebug("Generating a change in %s weather for zone %u.", seasonName[season], m_zone); + + if ((u < 60) && (m_grade < 0.33333334f)) // Get fair + { + m_type = WEATHER_TYPE_FINE; + m_grade = 0.0f; + } + + if ((u < 60) && (m_type != WEATHER_TYPE_FINE)) // Get better + { + m_grade -= 0.33333334f; + return true; + } + + if ((u < 90) && (m_type != WEATHER_TYPE_FINE)) // Get worse + { + m_grade += 0.33333334f; + return true; + } + + if (m_type != WEATHER_TYPE_FINE) + { + /// Radical change: + ///- if light -> heavy + ///- if medium -> change weather type + ///- if heavy -> 50% light, 50% change weather type + + if (m_grade < 0.33333334f) + { + m_grade = 0.9999f; // go nuts + return true; + } + else + { + if (m_grade > 0.6666667f) + { + // Severe change, but how severe? + uint32 rnd = urand(0,99); + if (rnd < 50) + { + m_grade -= 0.6666667f; + return true; + } + } + m_type = WEATHER_TYPE_FINE; // clear up + m_grade = 0; + } + } + + // At this point, only weather that isn't doing anything remains but that have weather data + uint32 chance1 = m_weatherChances->data[season].rainChance; + uint32 chance2 = chance1+ m_weatherChances->data[season].snowChance; + uint32 chance3 = chance2+ m_weatherChances->data[season].stormChance; + + uint32 rnd = urand(0, 99); + if(rnd <= chance1) + m_type = WEATHER_TYPE_RAIN; + else if(rnd <= chance2) + m_type = WEATHER_TYPE_SNOW; + else if(rnd <= chance3) + m_type = WEATHER_TYPE_STORM; + else + m_type = WEATHER_TYPE_FINE; + + /// New weather statistics (if not fine): + ///- 85% light + ///- 7% medium + ///- 7% heavy + /// If fine 100% sun (no fog) + + if (m_type == WEATHER_TYPE_FINE) + { + m_grade = 0.0f; + } + else if (u < 90) + { + m_grade = rand_norm() * 0.3333f; + } + else + { + // Severe change, but how severe? + rnd = urand(0, 99); + if (rnd < 50) + m_grade = rand_norm() * 0.3333f + 0.3334f; + else + m_grade = rand_norm() * 0.3333f + 0.6667f; + } + + // return true only in case weather changes + return m_type != old_type || m_grade != old_grade; +} + +void Weather::SendWeatherUpdateToPlayer(Player *player) +{ + WorldPacket data( SMSG_WEATHER, (4+4+4) ); + + data << uint32(GetWeatherState()) << (float)m_grade << uint8(0); + player->GetSession()->SendPacket( &data ); +} + +void Weather::SendFineWeatherUpdateToPlayer(Player *player) +{ + WorldPacket data( SMSG_WEATHER, (4+4+4) ); + + data << (uint32)WEATHER_STATE_FINE << (float)0.0f << uint8(0); + player->GetSession()->SendPacket( &data ); +} + +/// Send the new weather to all players in the zone +bool Weather::UpdateWeather() +{ + Player* player = sWorld.FindPlayerInZone(m_zone); + if(!player) + return false; + + ///- Send the weather packet to all players in this zone + if (m_grade >= 1) + m_grade = 0.9999f; + else if (m_grade < 0) + m_grade = 0.0001f; + + WeatherState state = GetWeatherState(); + + WorldPacket data( SMSG_WEATHER, (4+4+4) ); + data << uint32(state) << (float)m_grade << uint8(0); + player->SendMessageToSet( &data, true ); + + ///- Log the event + char const* wthstr; + switch(state) + { + case WEATHER_STATE_LIGHT_RAIN: + wthstr = "light rain"; + break; + case WEATHER_STATE_MEDIUM_RAIN: + wthstr = "medium rain"; + break; + case WEATHER_STATE_HEAVY_RAIN: + wthstr = "heavy rain"; + break; + case WEATHER_STATE_LIGHT_SNOW: + wthstr = "light snow"; + break; + case WEATHER_STATE_MEDIUM_SNOW: + wthstr = "medium snow"; + break; + case WEATHER_STATE_HEAVY_SNOW: + wthstr = "heavy snow"; + break; + case WEATHER_STATE_LIGHT_SANDSTORM: + wthstr = "light sandstorm"; + break; + case WEATHER_STATE_MEDIUM_SANDSTORM: + wthstr = "medium sandstorm"; + break; + case WEATHER_STATE_HEAVY_SANDSTORM: + wthstr = "heavy sandstorm"; + break; + case WEATHER_STATE_THUNDERS: + wthstr = "thunders"; + break; + case WEATHER_STATE_BLACKRAIN: + wthstr = "blackrain"; + break; + case WEATHER_STATE_FINE: + default: + wthstr = "fine"; + break; + } + sLog.outDetail("Change the weather of zone %u to %s.", m_zone, wthstr); + + return true; +} + +/// Set the weather +void Weather::SetWeather(WeatherType type, float grade) +{ + if(m_type == type && m_grade == grade) + return; + + m_type = type; + m_grade = grade; + UpdateWeather(); +} + +/// Get the sound number associated with the current weather +WeatherState Weather::GetWeatherState() const +{ + if (m_grade<0.27f) + return WEATHER_STATE_FINE; + + switch(m_type) + { + case WEATHER_TYPE_RAIN: + if(m_grade<0.40f) + return WEATHER_STATE_LIGHT_RAIN; + else if(m_grade<0.70f) + return WEATHER_STATE_MEDIUM_RAIN; + else + return WEATHER_STATE_HEAVY_RAIN; + case WEATHER_TYPE_SNOW: + if(m_grade<0.40f) + return WEATHER_STATE_LIGHT_SNOW; + else if(m_grade<0.70f) + return WEATHER_STATE_MEDIUM_SNOW; + else + return WEATHER_STATE_HEAVY_SNOW; + case WEATHER_TYPE_STORM: + if(m_grade<0.40f) + return WEATHER_STATE_LIGHT_SANDSTORM; + else if(m_grade<0.70f) + return WEATHER_STATE_MEDIUM_SANDSTORM; + else + return WEATHER_STATE_HEAVY_SANDSTORM; + case WEATHER_TYPE_BLACKRAIN: + return WEATHER_STATE_BLACKRAIN; + case WEATHER_TYPE_THUNDERS: + return WEATHER_STATE_THUNDERS; + case WEATHER_TYPE_FINE: + default: + return WEATHER_STATE_FINE; + } +} diff --git a/src/game/Weather.h b/src/game/Weather.h new file mode 100644 index 00000000000..e6eaa49a3e7 --- /dev/null +++ b/src/game/Weather.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/// \addtogroup world +/// @{ +/// \file + +#ifndef __WEATHER_H +#define __WEATHER_H + +#include "Common.h" +#include "SharedDefines.h" +#include "Timer.h" + +class Player; + +enum WeatherState +{ + WEATHER_STATE_FINE = 0, + WEATHER_STATE_LIGHT_RAIN = 3, + WEATHER_STATE_MEDIUM_RAIN = 4, + WEATHER_STATE_HEAVY_RAIN = 5, + WEATHER_STATE_LIGHT_SNOW = 6, + WEATHER_STATE_MEDIUM_SNOW = 7, + WEATHER_STATE_HEAVY_SNOW = 8, + WEATHER_STATE_LIGHT_SANDSTORM = 22, + WEATHER_STATE_MEDIUM_SANDSTORM = 41, + WEATHER_STATE_HEAVY_SANDSTORM = 42, + WEATHER_STATE_THUNDERS = 86, + WEATHER_STATE_BLACKRAIN = 90 +}; + +struct WeatherZoneChances; + +/// Weather for one zone +class Weather +{ + public: + Weather(uint32 zone, WeatherZoneChances const* weatherChances); + ~Weather() { }; + bool ReGenerate(); + bool UpdateWeather(); + void SendWeatherUpdateToPlayer(Player *player); + static void SendFineWeatherUpdateToPlayer(Player *player); + void SetWeather(WeatherType type, float grade); + /// For which zone is this weather? + uint32 GetZone() { return m_zone; }; + bool Update(time_t diff); + private: + WeatherState GetWeatherState() const; + uint32 m_zone; + WeatherType m_type; + float m_grade; + IntervalTimer m_timer; + WeatherZoneChances const* m_weatherChances; +}; +#endif diff --git a/src/game/World.cpp b/src/game/World.cpp new file mode 100644 index 00000000000..8546778ae21 --- /dev/null +++ b/src/game/World.cpp @@ -0,0 +1,2460 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** \file + \ingroup world +*/ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "Config/ConfigEnv.h" +#include "SystemConfig.h" +#include "Log.h" +#include "Opcodes.h" +#include "WorldSession.h" +#include "WorldPacket.h" +#include "Weather.h" +#include "Player.h" +#include "SkillExtraItems.h" +#include "SkillDiscovery.h" +#include "World.h" +#include "ObjectMgr.h" +#include "SpellMgr.h" +#include "Chat.h" +#include "Database/DBCStores.h" +#include "LootMgr.h" +#include "ItemEnchantmentMgr.h" +#include "MapManager.h" +#include "ScriptCalls.h" +#include "CreatureAIRegistry.h" +#include "Policies/SingletonImp.h" +#include "BattleGroundMgr.h" +#include "TemporarySummon.h" +#include "WaypointMovementGenerator.h" +#include "VMapFactory.h" +#include "GlobalEvents.h" +#include "GameEvent.h" +#include "Database/DatabaseImpl.h" +#include "WorldSocket.h" +#include "GridNotifiersImpl.h" +#include "CellImpl.h" +#include "InstanceSaveMgr.h" +#include "WaypointManager.h" +#include "Util.h" + +INSTANTIATE_SINGLETON_1( World ); + +volatile bool World::m_stopEvent = false; +volatile uint32 World::m_worldLoopCounter = 0; + +float World::m_MaxVisibleDistanceForCreature = DEFAULT_VISIBILITY_DISTANCE; +float World::m_MaxVisibleDistanceForPlayer = DEFAULT_VISIBILITY_DISTANCE; +float World::m_MaxVisibleDistanceForObject = DEFAULT_VISIBILITY_DISTANCE; +float World::m_MaxVisibleDistanceInFlight = DEFAULT_VISIBILITY_DISTANCE; +float World::m_VisibleUnitGreyDistance = 0; +float World::m_VisibleObjectGreyDistance = 0; + +// ServerMessages.dbc +enum ServerMessageType +{ + SERVER_MSG_SHUTDOWN_TIME = 1, + SERVER_MSG_RESTART_TIME = 2, + SERVER_MSG_STRING = 3, + SERVER_MSG_SHUTDOWN_CANCELLED = 4, + SERVER_MSG_RESTART_CANCELLED = 5 +}; + +struct ScriptAction +{ + uint64 sourceGUID; + uint64 targetGUID; + uint64 ownerGUID; // owner of source if source is item + ScriptInfo const* script; // pointer to static script data +}; + +/// World constructor +World::World() +{ + m_playerLimit = 0; + m_allowMovement = true; + m_ShutdownMask = 0; + m_ShutdownTimer = 0; + m_gameTime=time(NULL); + m_startTime=m_gameTime; + m_maxActiveSessionCount = 0; + m_maxQueuedSessionCount = 0; + m_resultQueue = NULL; + m_NextDailyQuestReset = 0; + + m_defaultDbcLocale = LOCALE_enUS; + m_availableDbcLocaleMask = 0; +} + +/// World destructor +World::~World() +{ + ///- Empty the kicked session set + for (std::set::iterator itr = m_kicked_sessions.begin(); itr != m_kicked_sessions.end(); ++itr) + delete *itr; + + m_kicked_sessions.clear(); + + ///- Empty the WeatherMap + for (WeatherMap::iterator itr = m_weathers.begin(); itr != m_weathers.end(); ++itr) + delete itr->second; + + m_weathers.clear(); + + VMAP::VMapFactory::clear(); + + if(m_resultQueue) delete m_resultQueue; +} + +/// Find a player in a specified zone +Player* World::FindPlayerInZone(uint32 zone) +{ + ///- circle through active sessions and return the first player found in the zone + SessionMap::iterator itr; + for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) + { + if(!itr->second) + continue; + Player *player = itr->second->GetPlayer(); + if(!player) + continue; + if( player->IsInWorld() && player->GetZoneId() == zone ) + { + // Used by the weather system. We return the player to broadcast the change weather message to him and all players in the zone. + return player; + } + } + return NULL; +} + +/// Find a session by its id +WorldSession* World::FindSession(uint32 id) const +{ + SessionMap::const_iterator itr = m_sessions.find(id); + + if(itr != m_sessions.end()) + return itr->second; // also can return NULL for kicked session + else + return NULL; +} + +/// Remove a given session +bool World::RemoveSession(uint32 id) +{ + ///- Find the session, kick the user, but we can't delete session at this moment to prevent iterator invalidation + SessionMap::iterator itr = m_sessions.find(id); + + if(itr != m_sessions.end() && itr->second) + { + if (itr->second->PlayerLoading()) + return false; + itr->second->KickPlayer(); + } + + return true; +} + +/// Add a session to the session list +void World::AddSession(WorldSession* s) +{ + ASSERT(s); + + WorldSession* old = m_sessions[s->GetAccountId()]; + m_sessions[s->GetAccountId()] = s; + + // if session already exist, prepare to it deleting at next world update + if(old) + m_kicked_sessions.insert(old); +} + +int32 World::GetQueuePos(WorldSocket* socket) +{ + uint32 position = 1; + + for(Queue::iterator iter = m_QueuedPlayer.begin(); iter != m_QueuedPlayer.end(); ++iter, ++position) + if((*iter) == socket) + return position; + + return 0; +} + +void World::AddQueuedPlayer(WorldSocket* socket) +{ + m_QueuedPlayer.push_back(socket); +} + +void World::RemoveQueuedPlayer(WorldSocket* socket) +{ + // sessions count including queued to remove (if removed_session set) + uint32 sessions = GetActiveSessionCount(); + + uint32 position = 1; + Queue::iterator iter = m_QueuedPlayer.begin(); + + // if session not queued then we need decrease sessions count (Remove socked callet before session removing from session list) + bool decrease_session = true; + + // search socket to remove and count skipped positions + for(;iter != m_QueuedPlayer.end(); ++iter, ++position) + { + if(*iter==socket) + { + Queue::iterator iter2 = iter; + ++iter; + m_QueuedPlayer.erase(iter2); + decrease_session = false; // removing queued session + break; + } + } + + // iter point to next socked after removed or end() + // position store position of removed socket and then new position next socket after removed + + // decrease for case session queued for removing + if(decrease_session && sessions) + --sessions; + + // accept first in queue + if( (!m_playerLimit || sessions < m_playerLimit) && !m_QueuedPlayer.empty() ) + { + WorldSocket * socket = m_QueuedPlayer.front(); + socket->SendAuthWaitQue(0); + m_QueuedPlayer.pop_front(); + + // update iter to point first queued socket or end() if queue is empty now + iter = m_QueuedPlayer.begin(); + position = 1; + } + + // update position from iter to end() + // iter point to first not updated socket, position store new position + for(; iter != m_QueuedPlayer.end(); ++iter, ++position) + (*iter)->SendAuthWaitQue(position); +} + +/// Find a Weather object by the given zoneid +Weather* World::FindWeather(uint32 id) const +{ + WeatherMap::const_iterator itr = m_weathers.find(id); + + if(itr != m_weathers.end()) + return itr->second; + else + return 0; +} + +/// Remove a Weather object for the given zoneid +void World::RemoveWeather(uint32 id) +{ + // not called at the moment. Kept for completeness + WeatherMap::iterator itr = m_weathers.find(id); + + if(itr != m_weathers.end()) + { + delete itr->second; + m_weathers.erase(itr); + } +} + +/// Add a Weather object to the list +Weather* World::AddWeather(uint32 zone_id) +{ + WeatherZoneChances const* weatherChances = objmgr.GetWeatherChances(zone_id); + + // zone not have weather, ignore + if(!weatherChances) + return NULL; + + Weather* w = new Weather(zone_id,weatherChances); + m_weathers[w->GetZone()] = w; + w->ReGenerate(); + w->UpdateWeather(); + return w; +} + +/// Initialize config values +void World::LoadConfigSettings(bool reload) +{ + if(reload) + { + if(!sConfig.Reload()) + { + sLog.outError("World settings reload fail: can't read settings from %s.",sConfig.GetFilename().c_str()); + return; + } + //TODO Check if config is outdated + } + + ///- Read the player limit and the Message of the day from the config file + SetPlayerLimit( sConfig.GetIntDefault("PlayerLimit", DEFAULT_PLAYER_LIMIT), true ); + SetMotd( sConfig.GetStringDefault("Motd", "Welcome to the Massive Network Game Object Server." ) ); + + ///- Read all rates from the config file + rate_values[RATE_HEALTH] = sConfig.GetFloatDefault("Rate.Health", 1); + if(rate_values[RATE_HEALTH] < 0) + { + sLog.outError("Rate.Health (%f) mustbe > 0. Using 1 instead.",rate_values[RATE_HEALTH]); + rate_values[RATE_HEALTH] = 1; + } + rate_values[RATE_POWER_MANA] = sConfig.GetFloatDefault("Rate.Mana", 1); + if(rate_values[RATE_POWER_MANA] < 0) + { + sLog.outError("Rate.Mana (%f) mustbe > 0. Using 1 instead.",rate_values[RATE_POWER_MANA]); + rate_values[RATE_POWER_MANA] = 1; + } + rate_values[RATE_POWER_RAGE_INCOME] = sConfig.GetFloatDefault("Rate.Rage.Income", 1); + rate_values[RATE_POWER_RAGE_LOSS] = sConfig.GetFloatDefault("Rate.Rage.Loss", 1); + if(rate_values[RATE_POWER_RAGE_LOSS] < 0) + { + sLog.outError("Rate.Rage.Loss (%f) mustbe > 0. Using 1 instead.",rate_values[RATE_POWER_RAGE_LOSS]); + rate_values[RATE_POWER_RAGE_LOSS] = 1; + } + rate_values[RATE_POWER_FOCUS] = sConfig.GetFloatDefault("Rate.Focus", 1.0f); + rate_values[RATE_LOYALTY] = sConfig.GetFloatDefault("Rate.Loyalty", 1.0f); + rate_values[RATE_SKILL_DISCOVERY] = sConfig.GetFloatDefault("Rate.Skill.Discovery", 1.0f); + rate_values[RATE_DROP_ITEM_POOR] = sConfig.GetFloatDefault("Rate.Drop.Item.Poor", 1.0f); + rate_values[RATE_DROP_ITEM_NORMAL] = sConfig.GetFloatDefault("Rate.Drop.Item.Normal", 1.0f); + rate_values[RATE_DROP_ITEM_UNCOMMON] = sConfig.GetFloatDefault("Rate.Drop.Item.Uncommon", 1.0f); + rate_values[RATE_DROP_ITEM_RARE] = sConfig.GetFloatDefault("Rate.Drop.Item.Rare", 1.0f); + rate_values[RATE_DROP_ITEM_EPIC] = sConfig.GetFloatDefault("Rate.Drop.Item.Epic", 1.0f); + rate_values[RATE_DROP_ITEM_LEGENDARY] = sConfig.GetFloatDefault("Rate.Drop.Item.Legendary", 1.0f); + rate_values[RATE_DROP_ITEM_ARTIFACT] = sConfig.GetFloatDefault("Rate.Drop.Item.Artifact", 1.0f); + rate_values[RATE_DROP_ITEM_REFERENCED] = sConfig.GetFloatDefault("Rate.Drop.Item.Referenced", 1.0f); + rate_values[RATE_DROP_MONEY] = sConfig.GetFloatDefault("Rate.Drop.Money", 1.0f); + rate_values[RATE_XP_KILL] = sConfig.GetFloatDefault("Rate.XP.Kill", 1.0f); + rate_values[RATE_XP_QUEST] = sConfig.GetFloatDefault("Rate.XP.Quest", 1.0f); + rate_values[RATE_XP_EXPLORE] = sConfig.GetFloatDefault("Rate.XP.Explore", 1.0f); + rate_values[RATE_XP_PAST_70] = sConfig.GetFloatDefault("Rate.XP.PastLevel70", 1.0f); + rate_values[RATE_REPUTATION_GAIN] = sConfig.GetFloatDefault("Rate.Reputation.Gain", 1.0f); + rate_values[RATE_CREATURE_NORMAL_DAMAGE] = sConfig.GetFloatDefault("Rate.Creature.Normal.Damage", 1.0f); + rate_values[RATE_CREATURE_ELITE_ELITE_DAMAGE] = sConfig.GetFloatDefault("Rate.Creature.Elite.Elite.Damage", 1.0f); + rate_values[RATE_CREATURE_ELITE_RAREELITE_DAMAGE] = sConfig.GetFloatDefault("Rate.Creature.Elite.RAREELITE.Damage", 1.0f); + rate_values[RATE_CREATURE_ELITE_WORLDBOSS_DAMAGE] = sConfig.GetFloatDefault("Rate.Creature.Elite.WORLDBOSS.Damage", 1.0f); + rate_values[RATE_CREATURE_ELITE_RARE_DAMAGE] = sConfig.GetFloatDefault("Rate.Creature.Elite.RARE.Damage", 1.0f); + rate_values[RATE_CREATURE_NORMAL_HP] = sConfig.GetFloatDefault("Rate.Creature.Normal.HP", 1.0f); + rate_values[RATE_CREATURE_ELITE_ELITE_HP] = sConfig.GetFloatDefault("Rate.Creature.Elite.Elite.HP", 1.0f); + rate_values[RATE_CREATURE_ELITE_RAREELITE_HP] = sConfig.GetFloatDefault("Rate.Creature.Elite.RAREELITE.HP", 1.0f); + rate_values[RATE_CREATURE_ELITE_WORLDBOSS_HP] = sConfig.GetFloatDefault("Rate.Creature.Elite.WORLDBOSS.HP", 1.0f); + rate_values[RATE_CREATURE_ELITE_RARE_HP] = sConfig.GetFloatDefault("Rate.Creature.Elite.RARE.HP", 1.0f); + rate_values[RATE_CREATURE_NORMAL_SPELLDAMAGE] = sConfig.GetFloatDefault("Rate.Creature.Normal.SpellDamage", 1.0f); + rate_values[RATE_CREATURE_ELITE_ELITE_SPELLDAMAGE] = sConfig.GetFloatDefault("Rate.Creature.Elite.Elite.SpellDamage", 1.0f); + rate_values[RATE_CREATURE_ELITE_RAREELITE_SPELLDAMAGE] = sConfig.GetFloatDefault("Rate.Creature.Elite.RAREELITE.SpellDamage", 1.0f); + rate_values[RATE_CREATURE_ELITE_WORLDBOSS_SPELLDAMAGE] = sConfig.GetFloatDefault("Rate.Creature.Elite.WORLDBOSS.SpellDamage", 1.0f); + rate_values[RATE_CREATURE_ELITE_RARE_SPELLDAMAGE] = sConfig.GetFloatDefault("Rate.Creature.Elite.RARE.SpellDamage", 1.0f); + rate_values[RATE_CREATURE_AGGRO] = sConfig.GetFloatDefault("Rate.Creature.Aggro", 1.0f); + rate_values[RATE_REST_INGAME] = sConfig.GetFloatDefault("Rate.Rest.InGame", 1.0f); + rate_values[RATE_REST_OFFLINE_IN_TAVERN_OR_CITY] = sConfig.GetFloatDefault("Rate.Rest.Offline.InTavernOrCity", 1.0f); + rate_values[RATE_REST_OFFLINE_IN_WILDERNESS] = sConfig.GetFloatDefault("Rate.Rest.Offline.InWilderness", 1.0f); + rate_values[RATE_DAMAGE_FALL] = sConfig.GetFloatDefault("Rate.Damage.Fall", 1.0f); + rate_values[RATE_AUCTION_TIME] = sConfig.GetFloatDefault("Rate.Auction.Time", 1.0f); + rate_values[RATE_AUCTION_DEPOSIT] = sConfig.GetFloatDefault("Rate.Auction.Deposit", 1.0f); + rate_values[RATE_AUCTION_CUT] = sConfig.GetFloatDefault("Rate.Auction.Cut", 1.0f); + rate_values[RATE_HONOR] = sConfig.GetFloatDefault("Rate.Honor",1.0f); + rate_values[RATE_MINING_AMOUNT] = sConfig.GetFloatDefault("Rate.Mining.Amount",1.0f); + rate_values[RATE_MINING_NEXT] = sConfig.GetFloatDefault("Rate.Mining.Next",1.0f); + rate_values[RATE_INSTANCE_RESET_TIME] = sConfig.GetFloatDefault("Rate.InstanceResetTime",1.0f); + rate_values[RATE_TALENT] = sConfig.GetFloatDefault("Rate.Talent",1.0f); + if(rate_values[RATE_TALENT] < 0.0f) + { + sLog.outError("Rate.Talent (%f) mustbe > 0. Using 1 instead.",rate_values[RATE_TALENT]); + rate_values[RATE_TALENT] = 1.0f; + } + rate_values[RATE_CORPSE_DECAY_LOOTED] = sConfig.GetFloatDefault("Rate.Corpse.Decay.Looted",0.1f); + + rate_values[RATE_TARGET_POS_RECALCULATION_RANGE] = sConfig.GetFloatDefault("TargetPosRecalculateRange",1.5f); + if(rate_values[RATE_TARGET_POS_RECALCULATION_RANGE] < CONTACT_DISTANCE) + { + sLog.outError("TargetPosRecalculateRange (%f) must be >= %f. Using %f instead.",rate_values[RATE_TARGET_POS_RECALCULATION_RANGE],CONTACT_DISTANCE,CONTACT_DISTANCE); + rate_values[RATE_TARGET_POS_RECALCULATION_RANGE] = CONTACT_DISTANCE; + } + else if(rate_values[RATE_TARGET_POS_RECALCULATION_RANGE] > ATTACK_DISTANCE) + { + sLog.outError("TargetPosRecalculateRange (%f) must be <= %f. Using %f instead.",rate_values[RATE_TARGET_POS_RECALCULATION_RANGE],ATTACK_DISTANCE,ATTACK_DISTANCE); + rate_values[RATE_TARGET_POS_RECALCULATION_RANGE] = ATTACK_DISTANCE; + } + + rate_values[RATE_DURABILITY_LOSS_DAMAGE] = sConfig.GetFloatDefault("DurabilityLossChance.Damage",0.5f); + if(rate_values[RATE_DURABILITY_LOSS_DAMAGE] < 0.0f) + { + sLog.outError("DurabilityLossChance.Damage (%f) must be >=0. Using 0.0 instead.",rate_values[RATE_DURABILITY_LOSS_DAMAGE]); + rate_values[RATE_DURABILITY_LOSS_DAMAGE] = 0.0f; + } + rate_values[RATE_DURABILITY_LOSS_ABSORB] = sConfig.GetFloatDefault("DurabilityLossChance.Absorb",0.5f); + if(rate_values[RATE_DURABILITY_LOSS_ABSORB] < 0.0f) + { + sLog.outError("DurabilityLossChance.Absorb (%f) must be >=0. Using 0.0 instead.",rate_values[RATE_DURABILITY_LOSS_ABSORB]); + rate_values[RATE_DURABILITY_LOSS_ABSORB] = 0.0f; + } + rate_values[RATE_DURABILITY_LOSS_PARRY] = sConfig.GetFloatDefault("DurabilityLossChance.Parry",0.05f); + if(rate_values[RATE_DURABILITY_LOSS_PARRY] < 0.0f) + { + sLog.outError("DurabilityLossChance.Parry (%f) must be >=0. Using 0.0 instead.",rate_values[RATE_DURABILITY_LOSS_PARRY]); + rate_values[RATE_DURABILITY_LOSS_PARRY] = 0.0f; + } + rate_values[RATE_DURABILITY_LOSS_BLOCK] = sConfig.GetFloatDefault("DurabilityLossChance.Block",0.05f); + if(rate_values[RATE_DURABILITY_LOSS_BLOCK] < 0.0f) + { + sLog.outError("DurabilityLossChance.Block (%f) must be >=0. Using 0.0 instead.",rate_values[RATE_DURABILITY_LOSS_BLOCK]); + rate_values[RATE_DURABILITY_LOSS_BLOCK] = 0.0f; + } + + ///- Read other configuration items from the config file + + m_configs[CONFIG_COMPRESSION] = sConfig.GetIntDefault("Compression", 1); + if(m_configs[CONFIG_COMPRESSION] < 1 || m_configs[CONFIG_COMPRESSION] > 9) + { + sLog.outError("Compression level (%i) must be in range 1..9. Using default compression level (1).",m_configs[CONFIG_COMPRESSION]); + m_configs[CONFIG_COMPRESSION] = 1; + } + m_configs[CONFIG_ADDON_CHANNEL] = sConfig.GetBoolDefault("AddonChannel", true); + m_configs[CONFIG_GRID_UNLOAD] = sConfig.GetBoolDefault("GridUnload", true); + m_configs[CONFIG_INTERVAL_SAVE] = sConfig.GetIntDefault("PlayerSaveInterval", 900000); + + m_configs[CONFIG_INTERVAL_GRIDCLEAN] = sConfig.GetIntDefault("GridCleanUpDelay", 300000); + if(m_configs[CONFIG_INTERVAL_GRIDCLEAN] < MIN_GRID_DELAY) + { + sLog.outError("GridCleanUpDelay (%i) must be greater %u. Use this minimal value.",m_configs[CONFIG_INTERVAL_GRIDCLEAN],MIN_GRID_DELAY); + m_configs[CONFIG_INTERVAL_GRIDCLEAN] = MIN_GRID_DELAY; + } + if(reload) + MapManager::Instance().SetGridCleanUpDelay(m_configs[CONFIG_INTERVAL_GRIDCLEAN]); + + m_configs[CONFIG_INTERVAL_MAPUPDATE] = sConfig.GetIntDefault("MapUpdateInterval", 100); + if(m_configs[CONFIG_INTERVAL_MAPUPDATE] < MIN_MAP_UPDATE_DELAY) + { + sLog.outError("MapUpdateInterval (%i) must be greater %u. Use this minimal value.",m_configs[CONFIG_INTERVAL_MAPUPDATE],MIN_MAP_UPDATE_DELAY); + m_configs[CONFIG_INTERVAL_MAPUPDATE] = MIN_MAP_UPDATE_DELAY; + } + if(reload) + MapManager::Instance().SetMapUpdateInterval(m_configs[CONFIG_INTERVAL_MAPUPDATE]); + + m_configs[CONFIG_INTERVAL_CHANGEWEATHER] = sConfig.GetIntDefault("ChangeWeatherInterval", 600000); + + if(reload) + { + uint32 val = sConfig.GetIntDefault("WorldServerPort", DEFAULT_WORLDSERVER_PORT); + if(val!=m_configs[CONFIG_PORT_WORLD]) + sLog.outError("WorldServerPort option can't be changed at mangosd.conf reload, using current value (%u).",m_configs[CONFIG_PORT_WORLD]); + } + else + m_configs[CONFIG_PORT_WORLD] = sConfig.GetIntDefault("WorldServerPort", DEFAULT_WORLDSERVER_PORT); + + if(reload) + { + uint32 val = sConfig.GetIntDefault("SocketSelectTime", DEFAULT_SOCKET_SELECT_TIME); + if(val!=m_configs[CONFIG_SOCKET_SELECTTIME]) + sLog.outError("SocketSelectTime option can't be changed at mangosd.conf reload, using current value (%u).",m_configs[DEFAULT_SOCKET_SELECT_TIME]); + } + else + m_configs[CONFIG_SOCKET_SELECTTIME] = sConfig.GetIntDefault("SocketSelectTime", DEFAULT_SOCKET_SELECT_TIME); + + + m_configs[CONFIG_TCP_NO_DELAY] = sConfig.GetBoolDefault("TcpNoDelay", false); + m_configs[CONFIG_GROUP_XP_DISTANCE] = sConfig.GetIntDefault("MaxGroupXPDistance", 74); + /// \todo Add MonsterSight and GuarderSight (with meaning) in mangosd.conf or put them as define + m_configs[CONFIG_SIGHT_MONSTER] = sConfig.GetIntDefault("MonsterSight", 50); + m_configs[CONFIG_SIGHT_GUARDER] = sConfig.GetIntDefault("GuarderSight", 50); + + if(reload) + { + uint32 val = sConfig.GetIntDefault("GameType", 0); + if(val!=m_configs[CONFIG_GAME_TYPE]) + sLog.outError("GameType option can't be changed at mangosd.conf reload, using current value (%u).",m_configs[CONFIG_GAME_TYPE]); + } + else + m_configs[CONFIG_GAME_TYPE] = sConfig.GetIntDefault("GameType", 0); + + if(reload) + { + uint32 val = sConfig.GetIntDefault("RealmZone", REALM_ZONE_DEVELOPMENT); + if(val!=m_configs[CONFIG_REALM_ZONE]) + sLog.outError("RealmZone option can't be changed at mangosd.conf reload, using current value (%u).",m_configs[CONFIG_REALM_ZONE]); + } + else + m_configs[CONFIG_REALM_ZONE] = sConfig.GetIntDefault("RealmZone", REALM_ZONE_DEVELOPMENT); + + m_configs[CONFIG_ALLOW_TWO_SIDE_ACCOUNTS] = sConfig.GetBoolDefault("AllowTwoSide.Accounts", false); + m_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT] = sConfig.GetBoolDefault("AllowTwoSide.Interaction.Chat",false); + m_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL] = sConfig.GetBoolDefault("AllowTwoSide.Interaction.Channel",false); + m_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP] = sConfig.GetBoolDefault("AllowTwoSide.Interaction.Group",false); + m_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD] = sConfig.GetBoolDefault("AllowTwoSide.Interaction.Guild",false); + m_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION] = sConfig.GetBoolDefault("AllowTwoSide.Interaction.Auction",false); + m_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL] = sConfig.GetBoolDefault("AllowTwoSide.Interaction.Mail",false); + m_configs[CONFIG_ALLOW_TWO_SIDE_WHO_LIST] = sConfig.GetBoolDefault("AllowTwoSide.WhoList", false); + m_configs[CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND] = sConfig.GetBoolDefault("AllowTwoSide.AddFriend", false); + m_configs[CONFIG_STRICT_PLAYER_NAMES] = sConfig.GetIntDefault("StrictPlayerNames", 0); + m_configs[CONFIG_STRICT_CHARTER_NAMES] = sConfig.GetIntDefault("StrictCharterNames", 0); + m_configs[CONFIG_STRICT_PET_NAMES] = sConfig.GetIntDefault("StrictPetNames", 0); + + m_configs[CONFIG_CHARACTERS_CREATING_DISABLED] = sConfig.GetIntDefault("CharactersCreatingDisabled", 0); + + m_configs[CONFIG_CHARACTERS_PER_REALM] = sConfig.GetIntDefault("CharactersPerRealm", 10); + if(m_configs[CONFIG_CHARACTERS_PER_REALM] < 1 || m_configs[CONFIG_CHARACTERS_PER_REALM] > 10) + { + sLog.outError("CharactersPerRealm (%i) must be in range 1..10. Set to 10.",m_configs[CONFIG_CHARACTERS_PER_REALM]); + m_configs[CONFIG_CHARACTERS_PER_REALM] = 10; + } + + // must be after CONFIG_CHARACTERS_PER_REALM + m_configs[CONFIG_CHARACTERS_PER_ACCOUNT] = sConfig.GetIntDefault("CharactersPerAccount", 50); + if(m_configs[CONFIG_CHARACTERS_PER_ACCOUNT] < m_configs[CONFIG_CHARACTERS_PER_REALM]) + { + sLog.outError("CharactersPerAccount (%i) can't be less than CharactersPerRealm (%i).",m_configs[CONFIG_CHARACTERS_PER_ACCOUNT],m_configs[CONFIG_CHARACTERS_PER_REALM]); + m_configs[CONFIG_CHARACTERS_PER_ACCOUNT] = m_configs[CONFIG_CHARACTERS_PER_REALM]; + } + + m_configs[CONFIG_SKIP_CINEMATICS] = sConfig.GetIntDefault("SkipCinematics", 0); + if(m_configs[CONFIG_SKIP_CINEMATICS] < 0 || m_configs[CONFIG_SKIP_CINEMATICS] > 2) + { + sLog.outError("SkipCinematics (%i) must be in range 0..2. Set to 0.",m_configs[CONFIG_SKIP_CINEMATICS]); + m_configs[CONFIG_SKIP_CINEMATICS] = 0; + } + + + if(reload) + { + uint32 val = sConfig.GetIntDefault("MaxPlayerLevel", 60); + if(val!=m_configs[CONFIG_MAX_PLAYER_LEVEL]) + sLog.outError("MaxPlayerLevel option can't be changed at mangosd.conf reload, using current value (%u).",m_configs[CONFIG_MAX_PLAYER_LEVEL]); + } + else + m_configs[CONFIG_MAX_PLAYER_LEVEL] = sConfig.GetIntDefault("MaxPlayerLevel", 60); + if(m_configs[CONFIG_MAX_PLAYER_LEVEL] > 255) + { + sLog.outError("MaxPlayerLevel (%i) must be in range 1..255. Set to 255.",m_configs[CONFIG_MAX_PLAYER_LEVEL]); + m_configs[CONFIG_MAX_PLAYER_LEVEL] = 255; + } + + m_configs[CONFIG_START_PLAYER_LEVEL] = sConfig.GetIntDefault("StartPlayerLevel", 1); + if(m_configs[CONFIG_START_PLAYER_LEVEL] < 1) + { + sLog.outError("StartPlayerLevel (%i) must be in range 1..MaxPlayerLevel(%u). Set to 1.",m_configs[CONFIG_START_PLAYER_LEVEL],m_configs[CONFIG_MAX_PLAYER_LEVEL]); + m_configs[CONFIG_START_PLAYER_LEVEL] = 1; + } + else if(m_configs[CONFIG_START_PLAYER_LEVEL] > m_configs[CONFIG_MAX_PLAYER_LEVEL]) + { + sLog.outError("StartPlayerLevel (%i) must be in range 1..MaxPlayerLevel(%u). Set to %u.",m_configs[CONFIG_START_PLAYER_LEVEL],m_configs[CONFIG_MAX_PLAYER_LEVEL],m_configs[CONFIG_MAX_PLAYER_LEVEL]); + m_configs[CONFIG_START_PLAYER_LEVEL] = m_configs[CONFIG_MAX_PLAYER_LEVEL]; + } + m_configs[CONFIG_MAX_HONOR_POINTS] = sConfig.GetIntDefault("MaxHonorPoints", 75000); + m_configs[CONFIG_MAX_ARENA_POINTS] = sConfig.GetIntDefault("MaxArenaPoints", 5000); + + m_configs[CONFIG_INSTANCE_IGNORE_LEVEL] = sConfig.GetBoolDefault("Instance.IgnoreLevel", false); + m_configs[CONFIG_INSTANCE_IGNORE_RAID] = sConfig.GetBoolDefault("Instance.IgnoreRaid", false); + + m_configs[CONFIG_BATTLEGROUND_CAST_DESERTER] = sConfig.GetBoolDefault("Battleground.CastDeserter", true); + m_configs[CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE] = sConfig.GetBoolDefault("Battleground.QueueAnnouncer.Enable", true); + m_configs[CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY] = sConfig.GetBoolDefault("Battleground.QueueAnnouncer.PlayerOnly", false); + + m_configs[CONFIG_CAST_UNSTUCK] = sConfig.GetBoolDefault("CastUnstuck", true); + m_configs[CONFIG_INSTANCE_RESET_TIME_HOUR] = sConfig.GetIntDefault("Instance.ResetTimeHour", 4); + m_configs[CONFIG_INSTANCE_UNLOAD_DELAY] = sConfig.GetIntDefault("Instance.UnloadDelay", 1800000); + + m_configs[CONFIG_MAX_PRIMARY_TRADE_SKILL] = sConfig.GetIntDefault("MaxPrimaryTradeSkill", 2); + m_configs[CONFIG_MIN_PETITION_SIGNS] = sConfig.GetIntDefault("MinPetitionSigns", 9); + if(m_configs[CONFIG_MIN_PETITION_SIGNS] > 9) + { + sLog.outError("MinPetitionSigns (%i) must be in range 0..9. Set to 9.",m_configs[CONFIG_MIN_PETITION_SIGNS]); + m_configs[CONFIG_MIN_PETITION_SIGNS] = 9; + } + + m_configs[CONFIG_GM_WISPERING_TO] = sConfig.GetBoolDefault("GM.WhisperingTo",false); + m_configs[CONFIG_GM_IN_GM_LIST] = sConfig.GetBoolDefault("GM.InGMList",false); + m_configs[CONFIG_GM_IN_WHO_LIST] = sConfig.GetBoolDefault("GM.InWhoList",false); + m_configs[CONFIG_GM_LOGIN_STATE] = sConfig.GetIntDefault("GM.LoginState",2); + m_configs[CONFIG_GM_LOG_TRADE] = sConfig.GetBoolDefault("GM.LogTrade", false); + + m_configs[CONFIG_GROUP_VISIBILITY] = sConfig.GetIntDefault("Visibility.GroupMode",0); + + m_configs[CONFIG_MAIL_DELIVERY_DELAY] = sConfig.GetIntDefault("MailDeliveryDelay",HOUR); + + m_configs[CONFIG_UPTIME_UPDATE] = sConfig.GetIntDefault("UpdateUptimeInterval", 10); + if(m_configs[CONFIG_UPTIME_UPDATE]<=0) + { + sLog.outError("UpdateUptimeInterval (%i) must be > 0, set to default 10.",m_configs[CONFIG_UPTIME_UPDATE]); + m_configs[CONFIG_UPTIME_UPDATE] = 10; + } + if(reload) + { + m_timers[WUPDATE_UPTIME].SetInterval(m_configs[CONFIG_UPTIME_UPDATE]*MINUTE*1000); + m_timers[WUPDATE_UPTIME].Reset(); + } + + m_configs[CONFIG_SKILL_CHANCE_ORANGE] = sConfig.GetIntDefault("SkillChance.Orange",100); + m_configs[CONFIG_SKILL_CHANCE_YELLOW] = sConfig.GetIntDefault("SkillChance.Yellow",75); + m_configs[CONFIG_SKILL_CHANCE_GREEN] = sConfig.GetIntDefault("SkillChance.Green",25); + m_configs[CONFIG_SKILL_CHANCE_GREY] = sConfig.GetIntDefault("SkillChance.Grey",0); + + m_configs[CONFIG_SKILL_CHANCE_MINING_STEPS] = sConfig.GetIntDefault("SkillChance.MiningSteps",75); + m_configs[CONFIG_SKILL_CHANCE_SKINNING_STEPS] = sConfig.GetIntDefault("SkillChance.SkinningSteps",75); + + m_configs[CONFIG_SKILL_PROSPECTING] = sConfig.GetBoolDefault("SkillChance.Prospecting",false); + + m_configs[CONFIG_SKILL_GAIN_CRAFTING] = sConfig.GetIntDefault("SkillGain.Crafting", 1); + if(m_configs[CONFIG_SKILL_GAIN_CRAFTING] < 0) + { + sLog.outError("SkillGain.Crafting (%i) can't be negative. Set to 1.",m_configs[CONFIG_SKILL_GAIN_CRAFTING]); + m_configs[CONFIG_SKILL_GAIN_CRAFTING] = 1; + } + + m_configs[CONFIG_SKILL_GAIN_DEFENSE] = sConfig.GetIntDefault("SkillGain.Defense", 1); + if(m_configs[CONFIG_SKILL_GAIN_DEFENSE] < 0) + { + sLog.outError("SkillGain.Defense (%i) can't be negative. Set to 1.",m_configs[CONFIG_SKILL_GAIN_DEFENSE]); + m_configs[CONFIG_SKILL_GAIN_DEFENSE] = 1; + } + + m_configs[CONFIG_SKILL_GAIN_GATHERING] = sConfig.GetIntDefault("SkillGain.Gathering", 1); + if(m_configs[CONFIG_SKILL_GAIN_GATHERING] < 0) + { + sLog.outError("SkillGain.Gathering (%i) can't be negative. Set to 1.",m_configs[CONFIG_SKILL_GAIN_GATHERING]); + m_configs[CONFIG_SKILL_GAIN_GATHERING] = 1; + } + + m_configs[CONFIG_SKILL_GAIN_WEAPON] = sConfig.GetIntDefault("SkillGain.Weapon", 1); + if(m_configs[CONFIG_SKILL_GAIN_WEAPON] < 0) + { + sLog.outError("SkillGain.Weapon (%i) can't be negative. Set to 1.",m_configs[CONFIG_SKILL_GAIN_WEAPON]); + m_configs[CONFIG_SKILL_GAIN_WEAPON] = 1; + } + + m_configs[CONFIG_MAX_OVERSPEED_PINGS] = sConfig.GetIntDefault("MaxOverspeedPings",2); + if(m_configs[CONFIG_MAX_OVERSPEED_PINGS] != 0 && m_configs[CONFIG_MAX_OVERSPEED_PINGS] < 2) + { + sLog.outError("MaxOverspeedPings (%i) must be in range 2..infinity (or 0 to disable check. Set to 2.",m_configs[CONFIG_MAX_OVERSPEED_PINGS]); + m_configs[CONFIG_MAX_OVERSPEED_PINGS] = 2; + } + + m_configs[CONFIG_SAVE_RESPAWN_TIME_IMMEDIATLY] = sConfig.GetBoolDefault("SaveRespawnTimeImmediately",true); + m_configs[CONFIG_WEATHER] = sConfig.GetBoolDefault("ActivateWeather",true); + + if(reload) + { + uint32 val = sConfig.GetIntDefault("Expansion",1); + if(val!=m_configs[CONFIG_EXPANSION]) + sLog.outError("Expansion option can't be changed at mangosd.conf reload, using current value (%u).",m_configs[CONFIG_EXPANSION]); + } + else + m_configs[CONFIG_EXPANSION] = sConfig.GetIntDefault("Expansion",1); + + m_configs[CONFIG_CHATFLOOD_MESSAGE_COUNT] = sConfig.GetIntDefault("ChatFlood.MessageCount",10); + m_configs[CONFIG_CHATFLOOD_MESSAGE_DELAY] = sConfig.GetIntDefault("ChatFlood.MessageDelay",1); + m_configs[CONFIG_CHATFLOOD_MUTE_TIME] = sConfig.GetIntDefault("ChatFlood.MuteTime",10); + + m_configs[CONFIG_EVENT_ANNOUNCE] = sConfig.GetIntDefault("Event.Announce",0); + + m_configs[CONFIG_CREATURE_FAMILY_ASSISTEMCE_RADIUS] = sConfig.GetIntDefault("CreatureFamilyAssistenceRadius",10); + + m_configs[CONFIG_WORLD_BOSS_LEVEL_DIFF] = sConfig.GetIntDefault("WorldBossLevelDiff",3); + + // note: disable value (-1) will assigned as 0xFFFFFFF, to prevent overflow at calculations limit it to max possible player level (255) + m_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] = sConfig.GetIntDefault("Quests.LowLevelHideDiff",4); + if(m_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] > 255) + m_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] = 255; + m_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] = sConfig.GetIntDefault("Quests.HighLevelHideDiff",7); + if(m_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] > 255) + m_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] = 255; + + m_configs[CONFIG_DETECT_POS_COLLISION] = sConfig.GetBoolDefault("DetectPosCollision", true); + + m_configs[CONFIG_RESTRICTED_LFG_CHANNEL] = sConfig.GetBoolDefault("Channel.RestrictedLfg", true); + m_configs[CONFIG_SILENTLY_GM_JOIN_TO_CHANNEL] = sConfig.GetBoolDefault("Channel.SilentlyGMJoin", false); + + m_configs[CONFIG_TALENTS_INSPECTING] = sConfig.GetBoolDefault("TalentsInspecting", true); + m_configs[CONFIG_CHAT_FAKE_MESSAGE_PREVENTING] = sConfig.GetBoolDefault("ChatFakeMessagePreventing", false); + + m_configs[CONFIG_CORPSE_DECAY_NORMAL] = sConfig.GetIntDefault("Corpse.Decay.NORMAL", 60); + m_configs[CONFIG_CORPSE_DECAY_RARE] = sConfig.GetIntDefault("Corpse.Decay.RARE", 300); + m_configs[CONFIG_CORPSE_DECAY_ELITE] = sConfig.GetIntDefault("Corpse.Decay.ELITE", 300); + m_configs[CONFIG_CORPSE_DECAY_RAREELITE] = sConfig.GetIntDefault("Corpse.Decay.RAREELITE", 300); + m_configs[CONFIG_CORPSE_DECAY_WORLDBOSS] = sConfig.GetIntDefault("Corpse.Decay.WORLDBOSS", 3600); + + m_configs[CONFIG_DEATH_SICKNESS_LEVEL] = sConfig.GetIntDefault("Death.SicknessLevel", 11); + m_configs[CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVP] = sConfig.GetBoolDefault("Death.CorpseReclaimDelay.PvP", true); + m_configs[CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVE] = sConfig.GetBoolDefault("Death.CorpseReclaimDelay.PvE", true); + + m_configs[CONFIG_THREAT_RADIUS] = sConfig.GetIntDefault("ThreatRadius", 100); + + // always use declined names in the russian client + m_configs[CONFIG_DECLINED_NAMES_USED] = + (m_configs[CONFIG_REALM_ZONE] == REALM_ZONE_RUSSIAN) ? true : sConfig.GetBoolDefault("DeclinedNames", false); + + m_configs[CONFIG_LISTEN_RANGE_SAY] = sConfig.GetIntDefault("ListenRange.Say", 25); + m_configs[CONFIG_LISTEN_RANGE_TEXTEMOTE] = sConfig.GetIntDefault("ListenRange.TextEmote", 25); + m_configs[CONFIG_LISTEN_RANGE_YELL] = sConfig.GetIntDefault("ListenRange.Yell", 300); + + + m_VisibleUnitGreyDistance = sConfig.GetFloatDefault("Visibility.Distance.Grey.Unit", 1); + if(m_VisibleUnitGreyDistance > MAX_VISIBILITY_DISTANCE) + { + sLog.outError("Visibility.Distance.Grey.Unit can't be greater %f",MAX_VISIBILITY_DISTANCE); + m_VisibleUnitGreyDistance = MAX_VISIBILITY_DISTANCE; + } + m_VisibleObjectGreyDistance = sConfig.GetFloatDefault("Visibility.Distance.Grey.Object", 10); + if(m_VisibleObjectGreyDistance > MAX_VISIBILITY_DISTANCE) + { + sLog.outError("Visibility.Distance.Grey.Object can't be greater %f",MAX_VISIBILITY_DISTANCE); + m_VisibleObjectGreyDistance = MAX_VISIBILITY_DISTANCE; + } + + m_MaxVisibleDistanceForCreature = sConfig.GetFloatDefault("Visibility.Distance.Creature", DEFAULT_VISIBILITY_DISTANCE); + if(m_MaxVisibleDistanceForCreature < 45*sWorld.getRate(RATE_CREATURE_AGGRO)) + { + sLog.outError("Visibility.Distance.Creature can't be less max aggro radius %f",45*sWorld.getRate(RATE_CREATURE_AGGRO)); + m_MaxVisibleDistanceForCreature = 45*sWorld.getRate(RATE_CREATURE_AGGRO); + } + else if(m_MaxVisibleDistanceForCreature + m_VisibleUnitGreyDistance > MAX_VISIBILITY_DISTANCE) + { + sLog.outError("Visibility. Distance .Creature can't be greater %f",MAX_VISIBILITY_DISTANCE - m_VisibleUnitGreyDistance); + m_MaxVisibleDistanceForCreature = MAX_VISIBILITY_DISTANCE-m_VisibleUnitGreyDistance; + } + m_MaxVisibleDistanceForPlayer = sConfig.GetFloatDefault("Visibility.Distance.Player", DEFAULT_VISIBILITY_DISTANCE); + if(m_MaxVisibleDistanceForPlayer < 45*sWorld.getRate(RATE_CREATURE_AGGRO)) + { + sLog.outError("Visibility.Distance.Player can't be less max aggro radius %f",45*sWorld.getRate(RATE_CREATURE_AGGRO)); + m_MaxVisibleDistanceForPlayer = 45*sWorld.getRate(RATE_CREATURE_AGGRO); + } + else if(m_MaxVisibleDistanceForPlayer + m_VisibleUnitGreyDistance > MAX_VISIBILITY_DISTANCE) + { + sLog.outError("Visibility.Distance.Player can't be greater %f",MAX_VISIBILITY_DISTANCE - m_VisibleUnitGreyDistance); + m_MaxVisibleDistanceForPlayer = MAX_VISIBILITY_DISTANCE - m_VisibleUnitGreyDistance; + } + m_MaxVisibleDistanceForObject = sConfig.GetFloatDefault("Visibility.Distance.Gameobject", DEFAULT_VISIBILITY_DISTANCE); + if(m_MaxVisibleDistanceForObject < INTERACTION_DISTANCE) + { + sLog.outError("Visibility.Distance.Object can't be less max aggro radius %f",float(INTERACTION_DISTANCE)); + m_MaxVisibleDistanceForObject = INTERACTION_DISTANCE; + } + else if(m_MaxVisibleDistanceForObject + m_VisibleObjectGreyDistance > MAX_VISIBILITY_DISTANCE) + { + sLog.outError("Visibility.Distance.Object can't be greater %f",MAX_VISIBILITY_DISTANCE-m_VisibleObjectGreyDistance); + m_MaxVisibleDistanceForObject = MAX_VISIBILITY_DISTANCE - m_VisibleObjectGreyDistance; + } + m_MaxVisibleDistanceInFlight = sConfig.GetFloatDefault("Visibility.Distance.InFlight", DEFAULT_VISIBILITY_DISTANCE); + if(m_MaxVisibleDistanceInFlight + m_VisibleObjectGreyDistance > MAX_VISIBILITY_DISTANCE) + { + sLog.outError("Visibility.Distance.InFlight can't be greater %f",MAX_VISIBILITY_DISTANCE-m_VisibleObjectGreyDistance); + m_MaxVisibleDistanceInFlight = MAX_VISIBILITY_DISTANCE - m_VisibleObjectGreyDistance; + } + + ///- Read the "Data" directory from the config file + std::string dataPath = sConfig.GetStringDefault("DataDir","./"); + if( dataPath.at(dataPath.length()-1)!='/' && dataPath.at(dataPath.length()-1)!='\\' ) + dataPath.append("/"); + + if(reload) + { + if(dataPath!=m_dataPath) + sLog.outError("DataDir option can't be changed at mangosd.conf reload, using current value (%s).",m_dataPath.c_str()); + } + else + { + m_dataPath = dataPath; + sLog.outString("Using DataDir %s",m_dataPath.c_str()); + } + + bool enableLOS = sConfig.GetBoolDefault("vmap.enableLOS", false); + bool enableHeight = sConfig.GetBoolDefault("vmap.enableHeight", false); + std::string ignoreMapIds = sConfig.GetStringDefault("vmap.ignoreMapIds", ""); + std::string ignoreSpellIds = sConfig.GetStringDefault("vmap.ignoreSpellIds", ""); + VMAP::VMapFactory::createOrGetVMapManager()->setEnableLineOfSightCalc(enableLOS); + VMAP::VMapFactory::createOrGetVMapManager()->setEnableHeightCalc(enableHeight); + VMAP::VMapFactory::createOrGetVMapManager()->preventMapsFromBeingUsed(ignoreMapIds.c_str()); + VMAP::VMapFactory::preventSpellsFromBeingTestedForLoS(ignoreSpellIds.c_str()); + sLog.outString( "WORLD: VMap support included. LineOfSight:%i, getHeight:%i",enableLOS, enableHeight); + sLog.outString( "WORLD: VMap data directory is: %svmaps",m_dataPath.c_str()); + sLog.outString( "WORLD: VMap config keys are: vmap.enableLOS, vmap.enableHeight, vmap.ignoreMapIds, vmap.ignoreSpellIds"); +} + +/// Initialize the World +void World::SetInitialWorldSettings() +{ + ///- Initialize the random number generator + srand((unsigned int)time(NULL)); + + ///- Initialize config settings + LoadConfigSettings(); + + ///- Init highest guids before any table loading to prevent using not initialized guids in some code. + objmgr.SetHighestGuids(); + + ///- Check the existence of the map files for all races' startup areas. + if( !MapManager::ExistMapAndVMap(0,-6240.32f, 331.033f) + ||!MapManager::ExistMapAndVMap(0,-8949.95f,-132.493f) + ||!MapManager::ExistMapAndVMap(0,-8949.95f,-132.493f) + ||!MapManager::ExistMapAndVMap(1,-618.518f,-4251.67f) + ||!MapManager::ExistMapAndVMap(0, 1676.35f, 1677.45f) + ||!MapManager::ExistMapAndVMap(1, 10311.3f, 832.463f) + ||!MapManager::ExistMapAndVMap(1,-2917.58f,-257.98f) + ||m_configs[CONFIG_EXPANSION] && ( + !MapManager::ExistMapAndVMap(530,10349.6f,-6357.29f) || !MapManager::ExistMapAndVMap(530,-3961.64f,-13931.2f) ) ) + { + sLog.outError("Correct *.map files not found in path '%smaps' or *.vmap/*vmdir files in '%svmaps'. Please place *.map/*.vmap/*.vmdir files in appropriate directories or correct the DataDir value in the mangosd.conf file.",m_dataPath.c_str(),m_dataPath.c_str()); + exit(1); + } + + ///- Loading strings. Getting no records means core load has to be canceled because no error message can be output. + sLog.outString( "" ); + sLog.outString( "Loading MaNGOS strings..." ); + if (!objmgr.LoadMangosStrings()) + exit(1); // Error message displayed in function already + + ///- Update the realm entry in the database with the realm type from the config file + //No SQL injection as values are treated as integers + + // not send custom type REALM_FFA_PVP to realm list + uint32 server_type = IsFFAPvPRealm() ? REALM_TYPE_PVP : getConfig(CONFIG_GAME_TYPE); + uint32 realm_zone = getConfig(CONFIG_REALM_ZONE); + loginDatabase.PExecute("UPDATE realmlist SET icon = %u, timezone = %u WHERE id = '%d'", server_type, realm_zone, realmID); + + ///- Remove the bones after a restart + CharacterDatabase.PExecute("DELETE FROM corpse WHERE corpse_type = '0'"); + + ///- Load the DBC files + sLog.outString("Initialize data stores..."); + LoadDBCStores(m_dataPath); + DetectDBCLang(); + + sLog.outString( "Loading InstanceTemplate" ); + objmgr.LoadInstanceTemplate(); + + sLog.outString( "Loading SkillLineAbilityMultiMap Data..." ); + spellmgr.LoadSkillLineAbilityMap(); + + ///- Clean up and pack instances + sLog.outString( "Cleaning up instances..." ); + sInstanceSaveManager.CleanupInstances(); // must be called before `creature_respawn`/`gameobject_respawn` tables + + sLog.outString( "Packing instances..." ); + sInstanceSaveManager.PackInstances(); + + sLog.outString( "Loading Localization strings..." ); + objmgr.LoadCreatureLocales(); + objmgr.LoadGameObjectLocales(); + objmgr.LoadItemLocales(); + objmgr.LoadQuestLocales(); + objmgr.LoadNpcTextLocales(); + objmgr.LoadPageTextLocales(); + objmgr.SetDBCLocaleIndex(GetDefaultDbcLocale()); // Get once for all the locale index of DBC language (console/broadcasts) + + sLog.outString( "Loading Page Texts..." ); + objmgr.LoadPageTexts(); + + sLog.outString( "Loading Game Object Templates..." ); // must be after LoadPageTexts + objmgr.LoadGameobjectInfo(); + + sLog.outString( "Loading Spell Chain Data..." ); + spellmgr.LoadSpellChains(); + + sLog.outString( "Loading Spell Elixir types..." ); + spellmgr.LoadSpellElixirs(); + + sLog.outString( "Loading Spell Learn Skills..." ); + spellmgr.LoadSpellLearnSkills(); // must be after LoadSpellChains + + sLog.outString( "Loading Spell Learn Spells..." ); + spellmgr.LoadSpellLearnSpells(); + + sLog.outString( "Loading Spell Proc Event conditions..." ); + spellmgr.LoadSpellProcEvents(); + + sLog.outString( "Loading Aggro Spells Definitions..."); + spellmgr.LoadSpellThreats(); + + sLog.outString( "Loading NPC Texts..." ); + objmgr.LoadGossipText(); + + sLog.outString( "Loading Item Random Enchantments Table..." ); + LoadRandomEnchantmentsTable(); + + sLog.outString( "Loading Items..." ); // must be after LoadRandomEnchantmentsTable and LoadPageTexts + objmgr.LoadItemPrototypes(); + + sLog.outString( "Loading Item Texts..." ); + objmgr.LoadItemTexts(); + + sLog.outString( "Loading Creature Model Based Info Data..." ); + objmgr.LoadCreatureModelInfo(); + + sLog.outString( "Loading Equipment templates..."); + objmgr.LoadEquipmentTemplates(); + + sLog.outString( "Loading Creature templates..." ); + objmgr.LoadCreatureTemplates(); + + sLog.outString( "Loading SpellsScriptTarget..."); + spellmgr.LoadSpellScriptTarget(); // must be after LoadCreatureTemplates and LoadGameobjectInfo + + sLog.outString( "Loading Creature Reputation OnKill Data..." ); + objmgr.LoadReputationOnKill(); + + sLog.outString( "Loading Pet Create Spells..." ); + objmgr.LoadPetCreateSpells(); + + sLog.outString( "Loading Creature Data..." ); + objmgr.LoadCreatures(); + + sLog.outString( "Loading Creature Addon Data..." ); + objmgr.LoadCreatureAddons(); // must be after LoadCreatureTemplates() and LoadCreatures() + + sLog.outString( "Loading Creature Respawn Data..." ); // must be after PackInstances() + objmgr.LoadCreatureRespawnTimes(); + + sLog.outString( "Loading Gameobject Data..." ); + objmgr.LoadGameobjects(); + + sLog.outString( "Loading Gameobject Respawn Data..." ); // must be after PackInstances() + objmgr.LoadGameobjectRespawnTimes(); + + sLog.outString( "Loading Game Event Data..."); + gameeventmgr.LoadFromDB(); + + sLog.outString( "Loading Weather Data..." ); + objmgr.LoadWeatherZoneChances(); + + sLog.outString( "Loading Quests..." ); + objmgr.LoadQuests(); // must be loaded after DBCs, creature_template, item_template, gameobject tables + + sLog.outString( "Loading Quests Relations..." ); + objmgr.LoadQuestRelations(); // must be after quest load + + sLog.outString( "Loading AreaTrigger definitions..." ); + objmgr.LoadAreaTriggerTeleports(); // must be after item template load + + sLog.outString( "Loading Quest Area Triggers..." ); + objmgr.LoadQuestAreaTriggers(); // must be after LoadQuests + + sLog.outString( "Loading Tavern Area Triggers..." ); + objmgr.LoadTavernAreaTriggers(); + + sLog.outString( "Loading AreaTrigger script names..." ); + objmgr.LoadAreaTriggerScripts(); + + + sLog.outString( "Loading Graveyard-zone links..."); + objmgr.LoadGraveyardZones(); + + sLog.outString( "Loading Spell target coordinates..." ); + spellmgr.LoadSpellTargetPositions(); + + sLog.outString( "Loading SpellAffect definitions..." ); + spellmgr.LoadSpellAffects(); + + sLog.outString( "Loading spell pet auras..." ); + spellmgr.LoadSpellPetAuras(); + + sLog.outString( "Loading player Create Info & Level Stats..." ); + objmgr.LoadPlayerInfo(); + + sLog.outString( "Loading Exploration BaseXP Data..." ); + objmgr.LoadExplorationBaseXP(); + + sLog.outString( "Loading Pet Name Parts..." ); + objmgr.LoadPetNames(); + + sLog.outString( "Loading the max pet number..." ); + objmgr.LoadPetNumber(); + + sLog.outString( "Loading pet level stats..." ); + objmgr.LoadPetLevelInfo(); + + sLog.outString( "Loading Player Corpses..." ); + objmgr.LoadCorpses(); + + sLog.outString( "Loading Loot Tables..." ); + LoadLootTables(); + + sLog.outString( "Loading Skill Discovery Table..." ); + LoadSkillDiscoveryTable(); + + sLog.outString( "Loading Skill Extra Item Table..." ); + LoadSkillExtraItemTable(); + + sLog.outString( "Loading Skill Fishing base level requirements..." ); + objmgr.LoadFishingBaseSkillLevel(); + + ///- Load dynamic data tables from the database + sLog.outString( "Loading Auctions..." ); + objmgr.LoadAuctionItems(); + objmgr.LoadAuctions(); + + sLog.outString( "Loading Guilds..." ); + objmgr.LoadGuilds(); + + sLog.outString( "Loading ArenaTeams..." ); + objmgr.LoadArenaTeams(); + + sLog.outString( "Loading Groups..." ); + objmgr.LoadGroups(); + + sLog.outString( "Loading ReservedNames..." ); + objmgr.LoadReservedPlayersNames(); + + sLog.outString( "Loading GameObject for quests..." ); + objmgr.LoadGameObjectForQuests(); + + sLog.outString( "Loading BattleMasters..." ); + objmgr.LoadBattleMastersEntry(); + + sLog.outString( "Loading Waypoints..." ); + WaypointMgr.Load(); + + ///- Handle outdated emails (delete/return) + sLog.outString( "Returning old mails..." ); + objmgr.ReturnOrDeleteOldMails(false); + + ///- Load and initialize scripts + sLog.outString( "Loading Scripts..." ); + objmgr.LoadQuestStartScripts(); // must be after load Creature/Gameobject(Template/Data) and QuestTemplate + objmgr.LoadQuestEndScripts(); // must be after load Creature/Gameobject(Template/Data) and QuestTemplate + objmgr.LoadSpellScripts(); // must be after load Creature/Gameobject(Template/Data) + objmgr.LoadGameObjectScripts(); // must be after load Creature/Gameobject(Template/Data) + objmgr.LoadEventScripts(); // must be after load Creature/Gameobject(Template/Data) + + sLog.outString( "Initializing Scripts..." ); + if(!LoadScriptingModule()) + exit(1); + + ///- Initialize game time and timers + sLog.outString( "DEBUG:: Initialize game time and timers" ); + m_gameTime = time(NULL); + m_startTime=m_gameTime; + + tm local; + time_t curr; + time(&curr); + local=*(localtime(&curr)); // dereference and assign + char isoDate[128]; + sprintf( isoDate, "%04d-%02d-%02d %02d:%02d:%02d", + local.tm_year+1900, local.tm_mon+1, local.tm_mday, local.tm_hour, local.tm_min, local.tm_sec); + + WorldDatabase.PExecute("INSERT INTO uptime (startstring, starttime, uptime) VALUES('%s', %ld, 0)", isoDate, m_startTime ); + + m_timers[WUPDATE_OBJECTS].SetInterval(0); + m_timers[WUPDATE_SESSIONS].SetInterval(0); + m_timers[WUPDATE_WEATHERS].SetInterval(1000); + m_timers[WUPDATE_AUCTIONS].SetInterval(MINUTE*1000); //set auction update interval to 1 minute + m_timers[WUPDATE_UPTIME].SetInterval(m_configs[CONFIG_UPTIME_UPDATE]*MINUTE*1000); + //Update "uptime" table based on configuration entry in minutes. + m_timers[WUPDATE_CORPSES].SetInterval(20*MINUTE*1000); //erase corpses every 20 minutes + + //to set mailtimer to return mails every day between 4 and 5 am + //mailtimer is increased when updating auctions + //one second is 1000 -(tested on win system) + mail_timer = ((((localtime( &m_gameTime )->tm_hour + 20) % 24)* HOUR * 1000) / m_timers[WUPDATE_AUCTIONS].GetInterval() ); + //1440 + mail_timer_expires = ( (DAY * 1000) / (m_timers[WUPDATE_AUCTIONS].GetInterval())); + sLog.outDebug("Mail timer set to: %u, mail return is called every %u minutes", mail_timer, mail_timer_expires); + + ///- Initilize static helper structures + AIRegistry::Initialize(); + WaypointMovementGenerator::Initialize(); + Player::InitVisibleBits(); + + ///- Initialize MapManager + sLog.outString( "Starting Map System" ); + MapManager::Instance().Initialize(); + + ///- Initialize Battlegrounds + sLog.outString( "Starting BattleGround System" ); + sBattleGroundMgr.CreateInitialBattleGrounds(); + + //Not sure if this can be moved up in the sequence (with static data loading) as it uses MapManager + sLog.outString( "Loading Transports..." ); + MapManager::Instance().LoadTransports(); + + sLog.outString("Deleting expired bans..." ); + loginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); + + sLog.outString("Calculate next daily quest reset time..." ); + InitDailyQuestResetTime(); + + sLog.outString("Starting Game Event system..." ); + uint32 nextGameEvent = gameeventmgr.Initialize(); + m_timers[WUPDATE_EVENTS].SetInterval(nextGameEvent); //depend on next event + + sLog.outString( "WORLD: World initialized" ); +} +void World::DetectDBCLang() +{ + uint32 m_lang_confid = sConfig.GetIntDefault("DBC.Locale", 255); + + if(m_lang_confid != 255 && m_lang_confid >= MAX_LOCALE) + { + sLog.outError("Incorrect DBC.Locale! Must be >= 0 and < %d (set to 0)",MAX_LOCALE); + m_lang_confid = LOCALE_enUS; + } + + ChrRacesEntry const* race = sChrRacesStore.LookupEntry(1); + + std::string availableLocalsStr; + + int default_locale = MAX_LOCALE; + for (int i = MAX_LOCALE-1; i >= 0; --i) + { + if ( strlen(race->name[i]) > 0) // check by race names + { + default_locale = i; + m_availableDbcLocaleMask |= (1 << i); + availableLocalsStr += localeNames[i]; + availableLocalsStr += " "; + } + } + + if( default_locale != m_lang_confid && m_lang_confid < MAX_LOCALE && + (m_availableDbcLocaleMask & (1 << m_lang_confid)) ) + { + default_locale = m_lang_confid; + } + + if(default_locale >= MAX_LOCALE) + { + sLog.outError("Unable to determine your DBC Locale! (corrupt DBC?)"); + exit(1); + } + + m_defaultDbcLocale = LocaleConstant(default_locale); + + sLog.outString("Using %s DBC Locale as default. All available DBC locales: %s",localeNames[m_defaultDbcLocale],availableLocalsStr.empty() ? "" : availableLocalsStr.c_str()); +} + +/// Update the World ! +void World::Update(time_t diff) +{ + ///- Update the different timers + for(int i = 0; i < WUPDATE_COUNT; i++) + if(m_timers[i].GetCurrent()>=0) + m_timers[i].Update(diff); + else m_timers[i].SetCurrent(0); + + ///- Update the game time and check for shutdown time + _UpdateGameTime(); + + /// Handle daily quests reset time + if(m_gameTime > m_NextDailyQuestReset) + { + ResetDailyQuests(); + m_NextDailyQuestReset += DAY; + } + + ///
  • Handle auctions when the timer has passed + if (m_timers[WUPDATE_AUCTIONS].Passed()) + { + m_timers[WUPDATE_AUCTIONS].Reset(); + + ///- Update mails (return old mails with item, or delete them) + //(tested... works on win) + if (++mail_timer > mail_timer_expires) + { + mail_timer = 0; + objmgr.ReturnOrDeleteOldMails(true); + } + + AuctionHouseObject* AuctionMap; + for (int i = 0; i < 3; i++) + { + switch (i) + { + case 0: + AuctionMap = objmgr.GetAuctionsMap( 6 );//horde + break; + case 1: + AuctionMap = objmgr.GetAuctionsMap( 2 );//alliance + break; + case 2: + AuctionMap = objmgr.GetAuctionsMap( 7 );//neutral + break; + } + + ///- Handle expired auctions + AuctionHouseObject::AuctionEntryMap::iterator itr,next; + for (itr = AuctionMap->GetAuctionsBegin(); itr != AuctionMap->GetAuctionsEnd();itr = next) + { + next = itr; + ++next; + if (m_gameTime > (itr->second->time)) + { + ///- Either cancel the auction if there was no bidder + if (itr->second->bidder == 0) + { + objmgr.SendAuctionExpiredMail( itr->second ); + } + ///- Or perform the transaction + else + { + //we should send an "item sold" message if the seller is online + //we send the item to the winner + //we send the money to the seller + objmgr.SendAuctionSuccessfulMail( itr->second ); + objmgr.SendAuctionWonMail( itr->second ); + } + + ///- In any case clear the auction + //No SQL injection (Id is integer) + CharacterDatabase.PExecute("DELETE FROM auctionhouse WHERE id = '%u'",itr->second->Id); + objmgr.RemoveAItem(itr->second->item_guidlow); + delete itr->second; + AuctionMap->RemoveAuction(itr->first); + } + } + } + } + + ///
  • Handle session updates when the timer has passed + if (m_timers[WUPDATE_SESSIONS].Passed()) + { + m_timers[WUPDATE_SESSIONS].Reset(); + + UpdateSessions(diff); + } + + ///
  • Handle weather updates when the timer has passed + if (m_timers[WUPDATE_WEATHERS].Passed()) + { + m_timers[WUPDATE_WEATHERS].Reset(); + + ///- Send an update signal to Weather objects + WeatherMap::iterator itr, next; + for (itr = m_weathers.begin(); itr != m_weathers.end(); itr = next) + { + next = itr; + ++next; + + ///- and remove Weather objects for zones with no player + //As interval > WorldTick + if(!itr->second->Update(m_timers[WUPDATE_WEATHERS].GetInterval())) + { + delete itr->second; + m_weathers.erase(itr); + } + } + } + ///
  • Update uptime table + if (m_timers[WUPDATE_UPTIME].Passed()) + { + uint32 tmpDiff = (m_gameTime - m_startTime); + uint32 maxClientsNum = sWorld.GetMaxActiveSessionCount(); + + m_timers[WUPDATE_UPTIME].Reset(); + WorldDatabase.PExecute("UPDATE uptime SET uptime = %d, maxplayers = %d WHERE starttime = " I64FMTD, tmpDiff, maxClientsNum, uint64(m_startTime)); + } + + ///
  • Handle all other objects + if (m_timers[WUPDATE_OBJECTS].Passed()) + { + m_timers[WUPDATE_OBJECTS].Reset(); + ///- Update objects when the timer has passed (maps, transport, creatures,...) + MapManager::Instance().Update(diff); // As interval = 0 + + ///- Process necessary scripts + if (!m_scriptSchedule.empty()) + ScriptsProcess(); + + sBattleGroundMgr.Update(diff); + } + + // execute callbacks from sql queries that were queued recently + UpdateResultQueue(); + + ///- Erase corpses once every 20 minutes + if (m_timers[WUPDATE_CORPSES].Passed()) + { + m_timers[WUPDATE_CORPSES].Reset(); + + CorpsesErase(); + } + + ///- Process Game events when necessary + if (m_timers[WUPDATE_EVENTS].Passed()) + { + m_timers[WUPDATE_EVENTS].Reset(); // to give time for Update() to be processed + uint32 nextGameEvent = gameeventmgr.Update(); + m_timers[WUPDATE_EVENTS].SetInterval(nextGameEvent); + m_timers[WUPDATE_EVENTS].Reset(); + } + + ///
+ ///- Move all creatures with "delayed move" and remove and delete all objects with "delayed remove" + MapManager::Instance().DoDelayedMovesAndRemoves(); + + // update the instance reset times + sInstanceSaveManager.Update(); + + // And last, but not least handle the issued cli commands + ProcessCliCommands(); +} + +/// Put scripts in the execution queue +void World::ScriptsStart(ScriptMapMap const& scripts, uint32 id, Object* source, Object* target) +{ + ///- Find the script map + ScriptMapMap::const_iterator s = scripts.find(id); + if (s == scripts.end()) + return; + + // prepare static data + uint64 sourceGUID = source->GetGUID(); + uint64 targetGUID = target ? target->GetGUID() : (uint64)0; + uint64 ownerGUID = (source->GetTypeId()==TYPEID_ITEM) ? ((Item*)source)->GetOwnerGUID() : (uint64)0; + + ///- Schedule script execution for all scripts in the script map + ScriptMap const *s2 = &(s->second); + bool immedScript = false; + for (ScriptMap::const_iterator iter = s2->begin(); iter != s2->end(); ++iter) + { + ScriptAction sa; + sa.sourceGUID = sourceGUID; + sa.targetGUID = targetGUID; + sa.ownerGUID = ownerGUID; + + sa.script = &iter->second; + m_scriptSchedule.insert(std::pair(m_gameTime + iter->first, sa)); + if (iter->first == 0) + immedScript = true; + } + ///- If one of the effects should be immediate, launch the script execution + if (immedScript) + ScriptsProcess(); +} + +void World::ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target) +{ + // NOTE: script record _must_ exist until command executed + + // prepare static data + uint64 sourceGUID = source->GetGUID(); + uint64 targetGUID = target ? target->GetGUID() : (uint64)0; + uint64 ownerGUID = (source->GetTypeId()==TYPEID_ITEM) ? ((Item*)source)->GetOwnerGUID() : (uint64)0; + + ScriptAction sa; + sa.sourceGUID = sourceGUID; + sa.targetGUID = targetGUID; + sa.ownerGUID = ownerGUID; + + sa.script = &script; + m_scriptSchedule.insert(std::pair(m_gameTime + delay, sa)); + + ///- If effects should be immediate, launch the script execution + if(delay == 0) + ScriptsProcess(); +} + +/// Process queued scripts +void World::ScriptsProcess() +{ + if (m_scriptSchedule.empty()) + return; + + ///- Process overdue queued scripts + std::multimap::iterator iter = m_scriptSchedule.begin(); + // ok as multimap is a *sorted* associative container + while (!m_scriptSchedule.empty() && (iter->first <= m_gameTime)) + { + ScriptAction const& step = iter->second; + + Object* source = NULL; + + if(step.sourceGUID) + { + switch(GUID_HIPART(step.sourceGUID)) + { + case HIGHGUID_ITEM: + // case HIGHGUID_CONTAINER: ==HIGHGUID_ITEM + { + Player* player = HashMapHolder::Find(step.ownerGUID); + if(player) + source = player->GetItemByGuid(step.sourceGUID); + break; + } + case HIGHGUID_UNIT: + source = HashMapHolder::Find(step.sourceGUID); + break; + case HIGHGUID_PET: + source = HashMapHolder::Find(step.sourceGUID); + break; + case HIGHGUID_PLAYER: + source = HashMapHolder::Find(step.sourceGUID); + break; + case HIGHGUID_GAMEOBJECT: + source = HashMapHolder::Find(step.sourceGUID); + break; + case HIGHGUID_CORPSE: + source = HashMapHolder::Find(step.sourceGUID); + break; + default: + sLog.outError("*_script source with unsupported high guid value %u",GUID_HIPART(step.sourceGUID)); + break; + } + } + + Object* target = NULL; + + if(step.targetGUID) + { + switch(GUID_HIPART(step.targetGUID)) + { + case HIGHGUID_UNIT: + target = HashMapHolder::Find(step.targetGUID); + break; + case HIGHGUID_PET: + target = HashMapHolder::Find(step.targetGUID); + break; + case HIGHGUID_PLAYER: // empty GUID case also + target = HashMapHolder::Find(step.targetGUID); + break; + case HIGHGUID_GAMEOBJECT: + target = HashMapHolder::Find(step.targetGUID); + break; + case HIGHGUID_CORPSE: + target = HashMapHolder::Find(step.targetGUID); + break; + default: + sLog.outError("*_script source with unsupported high guid value %u",GUID_HIPART(step.targetGUID)); + break; + } + } + + switch (step.script->command) + { + case SCRIPT_COMMAND_TALK: + { + if(!source) + { + sLog.outError("SCRIPT_COMMAND_TALK call for NULL creature."); + break; + } + + if(source->GetTypeId()!=TYPEID_UNIT) + { + sLog.outError("SCRIPT_COMMAND_TALK call for non-creature (TypeId: %u), skipping.",source->GetTypeId()); + break; + } + if(step.script->datalong > 3) + { + sLog.outError("SCRIPT_COMMAND_TALK invalid chat type (%u), skipping.",step.script->datalong); + break; + } + + uint64 unit_target = target ? target->GetGUID() : 0; + + //datalong 0=normal say, 1=whisper, 2=yell, 3=emote text + switch(step.script->datalong) + { + case 0: // Say + ((Creature *)source)->Say(step.script->datatext.c_str(), LANG_UNIVERSAL, unit_target); + break; + case 1: // Whisper + if(!unit_target) + { + sLog.outError("SCRIPT_COMMAND_TALK attempt to whisper (%u) NULL, skipping.",step.script->datalong); + break; + } + ((Creature *)source)->Whisper(step.script->datatext.c_str(),unit_target); + break; + case 2: // Yell + ((Creature *)source)->Yell(step.script->datatext.c_str(), LANG_UNIVERSAL, unit_target); + break; + case 3: // Emote text + ((Creature *)source)->TextEmote(step.script->datatext.c_str(), unit_target); + break; + default: + break; // must be already checked at load + } + break; + } + + case SCRIPT_COMMAND_EMOTE: + if(!source) + { + sLog.outError("SCRIPT_COMMAND_EMOTE call for NULL creature."); + break; + } + + if(source->GetTypeId()!=TYPEID_UNIT) + { + sLog.outError("SCRIPT_COMMAND_EMOTE call for non-creature (TypeId: %u), skipping.",source->GetTypeId()); + break; + } + + ((Creature *)source)->HandleEmoteCommand(step.script->datalong); + break; + case SCRIPT_COMMAND_FIELD_SET: + if(!source) + { + sLog.outError("SCRIPT_COMMAND_FIELD_SET call for NULL object."); + break; + } + if(step.script->datalong <= OBJECT_FIELD_ENTRY || step.script->datalong >= source->GetValuesCount()) + { + sLog.outError("SCRIPT_COMMAND_FIELD_SET call for wrong field %u (max count: %u) in object (TypeId: %u).", + step.script->datalong,source->GetValuesCount(),source->GetTypeId()); + break; + } + + source->SetUInt32Value(step.script->datalong, step.script->datalong2); + break; + case SCRIPT_COMMAND_MOVE_TO: + if(!source) + { + sLog.outError("SCRIPT_COMMAND_MOVE_TO call for NULL creature."); + break; + } + + if(source->GetTypeId()!=TYPEID_UNIT) + { + sLog.outError("SCRIPT_COMMAND_MOVE_TO call for non-creature (TypeId: %u), skipping.",source->GetTypeId()); + break; + } + ((Unit *)source)->SendMonsterMoveWithSpeed(step.script->x, step.script->y, step.script->z, ((Unit *)source)->GetUnitMovementFlags(), step.script->datalong2 ); + MapManager::Instance().GetMap(((Unit *)source)->GetMapId(), ((Unit *)source))->CreatureRelocation(((Creature *)source), step.script->x, step.script->y, step.script->z, 0); + break; + case SCRIPT_COMMAND_FLAG_SET: + if(!source) + { + sLog.outError("SCRIPT_COMMAND_FLAG_SET call for NULL object."); + break; + } + if(step.script->datalong <= OBJECT_FIELD_ENTRY || step.script->datalong >= source->GetValuesCount()) + { + sLog.outError("SCRIPT_COMMAND_FLAG_SET call for wrong field %u (max count: %u) in object (TypeId: %u).", + step.script->datalong,source->GetValuesCount(),source->GetTypeId()); + break; + } + + source->SetFlag(step.script->datalong, step.script->datalong2); + break; + case SCRIPT_COMMAND_FLAG_REMOVE: + if(!source) + { + sLog.outError("SCRIPT_COMMAND_FLAG_REMOVE call for NULL object."); + break; + } + if(step.script->datalong <= OBJECT_FIELD_ENTRY || step.script->datalong >= source->GetValuesCount()) + { + sLog.outError("SCRIPT_COMMAND_FLAG_REMOVE call for wrong field %u (max count: %u) in object (TypeId: %u).", + step.script->datalong,source->GetValuesCount(),source->GetTypeId()); + break; + } + + source->RemoveFlag(step.script->datalong, step.script->datalong2); + break; + + case SCRIPT_COMMAND_TELEPORT_TO: + { + // accept player in any one from target/source arg + if (!target && !source) + { + sLog.outError("SCRIPT_COMMAND_TELEPORT_TO call for NULL object."); + break; + } + + // must be only Player + if((!target || target->GetTypeId() != TYPEID_PLAYER) && (!source || source->GetTypeId() != TYPEID_PLAYER)) + { + sLog.outError("SCRIPT_COMMAND_TELEPORT_TO call for non-player (TypeIdSource: %u)(TypeIdTarget: %u), skipping.", source ? source->GetTypeId() : 0, target ? target->GetTypeId() : 0); + break; + } + + Player* pSource = target && target->GetTypeId() == TYPEID_PLAYER ? (Player*)target : (Player*)source; + + pSource->TeleportTo(step.script->datalong, step.script->x, step.script->y, step.script->z, step.script->o); + break; + } + + case SCRIPT_COMMAND_TEMP_SUMMON_CREATURE: + { + if(!step.script->datalong) // creature not specified + { + sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON_CREATURE call for NULL creature."); + break; + } + + if(!source) + { + sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON_CREATURE call for NULL world object."); + break; + } + + WorldObject* summoner = dynamic_cast(source); + + if(!summoner) + { + sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON_CREATURE call for non-WorldObject (TypeId: %u), skipping.",source->GetTypeId()); + break; + } + + float x = step.script->x; + float y = step.script->y; + float z = step.script->z; + float o = step.script->o; + + Creature* pCreature = summoner->SummonCreature(step.script->datalong, x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,step.script->datalong2); + if (!pCreature) + { + sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON failed for creature (entry: %u).",step.script->datalong); + break; + } + + break; + } + + case SCRIPT_COMMAND_RESPAWN_GAMEOBJECT: + { + if(!step.script->datalong) // gameobject not specified + { + sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT call for NULL gameobject."); + break; + } + + if(!source) + { + sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT call for NULL world object."); + break; + } + + WorldObject* summoner = dynamic_cast(source); + + if(!summoner) + { + sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT call for non-WorldObject (TypeId: %u), skipping.",source->GetTypeId()); + break; + } + + GameObject *go = NULL; + int32 time_to_despawn = step.script->datalong2<5 ? 5 : (int32)step.script->datalong2; + + CellPair p(MaNGOS::ComputeCellPair(summoner->GetPositionX(), summoner->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + + MaNGOS::GameObjectWithDbGUIDCheck go_check(*summoner,step.script->datalong); + MaNGOS::GameObjectSearcher checker(go,go_check); + + TypeContainerVisitor, GridTypeMapContainer > object_checker(checker); + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, object_checker, *MapManager::Instance().GetMap(summoner->GetMapId(), summoner)); + + if ( !go ) + { + sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT failed for gameobject(guid: %u).", step.script->datalong); + break; + } + + if( go->GetGoType()==GAMEOBJECT_TYPE_FISHINGNODE || + go->GetGoType()==GAMEOBJECT_TYPE_FISHINGNODE || + go->GetGoType()==GAMEOBJECT_TYPE_DOOR || + go->GetGoType()==GAMEOBJECT_TYPE_BUTTON || + go->GetGoType()==GAMEOBJECT_TYPE_TRAP ) + { + sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT can not be used with gameobject of type %u (guid: %u).", uint32(go->GetGoType()), step.script->datalong); + break; + } + + if( go->isSpawned() ) + break; //gameobject already spawned + + go->SetLootState(GO_READY); + go->SetRespawnTime(time_to_despawn); //despawn object in ? seconds + + MapManager::Instance().GetMap(go->GetMapId(), go)->Add(go); + break; + } + case SCRIPT_COMMAND_OPEN_DOOR: + { + if(!step.script->datalong) // door not specified + { + sLog.outError("SCRIPT_COMMAND_OPEN_DOOR call for NULL door."); + break; + } + + if(!source) + { + sLog.outError("SCRIPT_COMMAND_OPEN_DOOR call for NULL unit."); + break; + } + + if(!source->isType(TYPEMASK_UNIT)) // must be any Unit (creature or player) + { + sLog.outError("SCRIPT_COMMAND_OPEN_DOOR call for non-unit (TypeId: %u), skipping.",source->GetTypeId()); + break; + } + + Unit* caster = (Unit*)source; + + GameObject *door = NULL; + int32 time_to_close = step.script->datalong2 < 15 ? 15 : (int32)step.script->datalong2; + + CellPair p(MaNGOS::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + + MaNGOS::GameObjectWithDbGUIDCheck go_check(*caster,step.script->datalong); + MaNGOS::GameObjectSearcher checker(door,go_check); + + TypeContainerVisitor, GridTypeMapContainer > object_checker(checker); + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, object_checker, *MapManager::Instance().GetMap(caster->GetMapId(), (Unit*)source)); + + if ( !door ) + { + sLog.outError("SCRIPT_COMMAND_OPEN_DOOR failed for gameobject(guid: %u).", step.script->datalong); + break; + } + if ( door->GetGoType() != GAMEOBJECT_TYPE_DOOR ) + { + sLog.outError("SCRIPT_COMMAND_OPEN_DOOR failed for non-door(GoType: %u).", door->GetGoType()); + break; + } + + if( !door->GetGoState() ) + break; //door already open + + door->UseDoorOrButton(time_to_close); + + if(target && target->isType(TYPEMASK_GAMEOBJECT) && ((GameObject*)target)->GetGoType()==GAMEOBJECT_TYPE_BUTTON) + ((GameObject*)target)->UseDoorOrButton(time_to_close); + break; + } + case SCRIPT_COMMAND_CLOSE_DOOR: + { + if(!step.script->datalong) // guid for door not specified + { + sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR call for NULL door."); + break; + } + + if(!source) + { + sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR call for NULL unit."); + break; + } + + if(!source->isType(TYPEMASK_UNIT)) // must be any Unit (creature or player) + { + sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR call for non-unit (TypeId: %u), skipping.",source->GetTypeId()); + break; + } + + Unit* caster = (Unit*)source; + + GameObject *door = NULL; + int32 time_to_open = step.script->datalong2 < 15 ? 15 : (int32)step.script->datalong2; + + CellPair p(MaNGOS::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + + MaNGOS::GameObjectWithDbGUIDCheck go_check(*caster,step.script->datalong); + MaNGOS::GameObjectSearcher checker(door,go_check); + + TypeContainerVisitor, GridTypeMapContainer > object_checker(checker); + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, object_checker, *MapManager::Instance().GetMap(caster->GetMapId(), (Unit*)source)); + + if ( !door ) + { + sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR failed for gameobject(guid: %u).", step.script->datalong); + break; + } + if ( door->GetGoType() != GAMEOBJECT_TYPE_DOOR ) + { + sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR failed for non-door(GoType: %u).", door->GetGoType()); + break; + } + + if( door->GetGoState() ) + break; //door already closed + + door->UseDoorOrButton(time_to_open); + + if(target && target->isType(TYPEMASK_GAMEOBJECT) && ((GameObject*)target)->GetGoType()==GAMEOBJECT_TYPE_BUTTON) + ((GameObject*)target)->UseDoorOrButton(time_to_open); + + break; + } + case SCRIPT_COMMAND_QUEST_EXPLORED: + { + if(!source) + { + sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for NULL source."); + break; + } + + if(!target) + { + sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for NULL target."); + break; + } + + // when script called for item spell casting then target == (unit or GO) and source is player + WorldObject* worldObject; + Player* player; + + if(target->GetTypeId()==TYPEID_PLAYER) + { + if(source->GetTypeId()!=TYPEID_UNIT && source->GetTypeId()!=TYPEID_GAMEOBJECT) + { + sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for non-creature and non-gameobject (TypeId: %u), skipping.",source->GetTypeId()); + break; + } + + worldObject = (WorldObject*)source; + player = (Player*)target; + } + else + { + if(target->GetTypeId()!=TYPEID_UNIT && target->GetTypeId()!=TYPEID_GAMEOBJECT) + { + sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for non-creature and non-gameobject (TypeId: %u), skipping.",target->GetTypeId()); + break; + } + + if(source->GetTypeId()!=TYPEID_PLAYER) + { + sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for non-player(TypeId: %u), skipping.",source->GetTypeId()); + break; + } + + worldObject = (WorldObject*)target; + player = (Player*)source; + } + + // quest id and flags checked at script loading + if( (worldObject->GetTypeId()!=TYPEID_UNIT || ((Unit*)worldObject)->isAlive()) && + (step.script->datalong2==0 || worldObject->IsWithinDistInMap(player,float(step.script->datalong2))) ) + player->AreaExploredOrEventHappens(step.script->datalong); + else + player->FailQuest(step.script->datalong); + + break; + } + + case SCRIPT_COMMAND_ACTIVATE_OBJECT: + { + if(!source) + { + sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT must have source caster."); + break; + } + + if(!source->isType(TYPEMASK_UNIT)) + { + sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT source caster isn't unit (TypeId: %u), skipping.",source->GetTypeId()); + break; + } + + if(!target) + { + sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT call for NULL gameobject."); + break; + } + + if(target->GetTypeId()!=TYPEID_GAMEOBJECT) + { + sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT call for non-gameobject (TypeId: %u), skipping.",target->GetTypeId()); + break; + } + + Unit* caster = (Unit*)source; + + GameObject *go = (GameObject*)target; + + go->Use(caster); + break; + } + + case SCRIPT_COMMAND_REMOVE_AURA: + { + Object* cmdTarget = step.script->datalong2 ? source : target; + + if(!cmdTarget) + { + sLog.outError("SCRIPT_COMMAND_REMOVE_AURA call for NULL %s.",step.script->datalong2 ? "source" : "target"); + break; + } + + if(!cmdTarget->isType(TYPEMASK_UNIT)) + { + sLog.outError("SCRIPT_COMMAND_REMOVE_AURA %s isn't unit (TypeId: %u), skipping.",step.script->datalong2 ? "source" : "target",cmdTarget->GetTypeId()); + break; + } + + ((Unit*)cmdTarget)->RemoveAurasDueToSpell(step.script->datalong); + break; + } + + case SCRIPT_COMMAND_CAST_SPELL: + { + if(!source) + { + sLog.outError("SCRIPT_COMMAND_CAST_SPELL must have source caster."); + break; + } + + if(!source->isType(TYPEMASK_UNIT)) + { + sLog.outError("SCRIPT_COMMAND_CAST_SPELL source caster isn't unit (TypeId: %u), skipping.",source->GetTypeId()); + break; + } + + Object* cmdTarget = step.script->datalong2 ? source : target; + + if(!cmdTarget) + { + sLog.outError("SCRIPT_COMMAND_CAST_SPELL call for NULL %s.",step.script->datalong2 ? "source" : "target"); + break; + } + + if(!cmdTarget->isType(TYPEMASK_UNIT)) + { + sLog.outError("SCRIPT_COMMAND_CAST_SPELL %s isn't unit (TypeId: %u), skipping.",step.script->datalong2 ? "source" : "target",cmdTarget->GetTypeId()); + break; + } + + Unit* spellTarget = (Unit*)cmdTarget; + + //TODO: when GO cast implemented, code below must be updated accordingly to also allow GO spell cast + ((Unit*)source)->CastSpell(spellTarget,step.script->datalong,false); + + break; + } + + default: + sLog.outError("Unknown script command %u called.",step.script->command); + break; + } + + m_scriptSchedule.erase(iter); + + iter = m_scriptSchedule.begin(); + } + return; +} + +/// Send a packet to all players (except self if mentioned) +void World::SendGlobalMessage(WorldPacket *packet, WorldSession *self, uint32 team) +{ + SessionMap::iterator itr; + for (itr = m_sessions.begin(); itr != m_sessions.end(); itr++) + { + if (itr->second && + itr->second->GetPlayer() && + itr->second->GetPlayer()->IsInWorld() && + itr->second != self && + (team == 0 || itr->second->GetPlayer()->GetTeam() == team) ) + { + itr->second->SendPacket(packet); + } + } +} + +/// Send a System Message to all players (except self if mentioned) +void World::SendWorldText(int32 string_id, ...) +{ + std::vector > data_cache; // 0 = default, i => i-1 locale index + + for(SessionMap::iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) + { + if(!itr->second || !itr->second->GetPlayer() || !itr->second->GetPlayer()->IsInWorld() ) + continue; + + uint32 loc_idx = itr->second->GetSessionDbLocaleIndex(); + uint32 cache_idx = loc_idx+1; + + std::vector* data_list; + + // create if not cached yet + if(data_cache.size() < cache_idx+1 || data_cache[cache_idx].empty()) + { + if(data_cache.size() < cache_idx+1) + data_cache.resize(cache_idx+1); + + data_list = &data_cache[cache_idx]; + + char const* text = objmgr.GetMangosString(string_id,loc_idx); + + char buf[1000]; + + va_list argptr; + va_start( argptr, string_id ); + vsnprintf( buf,1000, text, argptr ); + va_end( argptr ); + + char* pos = &buf[0]; + + while(char* line = ChatHandler::LineFromMessage(pos)) + { + WorldPacket* data = new WorldPacket(); + ChatHandler::FillMessageData(data, NULL, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, NULL, 0, line, NULL); + data_list->push_back(data); + } + } + else + data_list = &data_cache[cache_idx]; + + for(int i = 0; i < data_list->size(); ++i) + itr->second->SendPacket((*data_list)[i]); + } + + // free memory + for(int i = 0; i < data_cache.size(); ++i) + for(int j = 0; j < data_cache[i].size(); ++j) + delete data_cache[i][j]; +} + +/// Send a packet to all players (or players selected team) in the zone (except self if mentioned) +void World::SendZoneMessage(uint32 zone, WorldPacket *packet, WorldSession *self, uint32 team) +{ + SessionMap::iterator itr; + for (itr = m_sessions.begin(); itr != m_sessions.end(); itr++) + { + if (itr->second && + itr->second->GetPlayer() && + itr->second->GetPlayer()->IsInWorld() && + itr->second->GetPlayer()->GetZoneId() == zone && + itr->second != self && + (team == 0 || itr->second->GetPlayer()->GetTeam() == team) ) + { + itr->second->SendPacket(packet); + } + } +} + +/// Send a System Message to all players in the zone (except self if mentioned) +void World::SendZoneText(uint32 zone, const char* text, WorldSession *self, uint32 team) +{ + WorldPacket data; + ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, NULL, 0, text, NULL); + SendZoneMessage(zone, &data, self,team); +} + +/// Kick (and save) all players +void World::KickAll() +{ + // session not removed at kick and will removed in next update tick + for (SessionMap::iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) + itr->second->KickPlayer(); +} + +/// Kick (and save) all players with security level less `sec` +void World::KickAllLess(AccountTypes sec) +{ + // session not removed at kick and will removed in next update tick + for (SessionMap::iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) + if(itr->second->GetSecurity() < sec) + itr->second->KickPlayer(); +} + +/// Kick all queued players +void World::KickAllQueued() +{ + // session not removed at kick and will removed in next update tick + for (Queue::iterator itr = m_QueuedPlayer.begin(); itr != m_QueuedPlayer.end(); ++itr) + if(WorldSession* session = (*itr)->GetSession()) + session->KickPlayer(); + + m_QueuedPlayer.empty(); +} + +/// Kick (and save) the designated player +bool World::KickPlayer(std::string playerName) +{ + SessionMap::iterator itr; + + // session not removed at kick and will removed in next update tick + for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) + { + if(!itr->second) + continue; + Player *player = itr->second->GetPlayer(); + if(!player) + continue; + if( player->IsInWorld() ) + { + if (playerName == player->GetName()) + { + itr->second->KickPlayer(); + return true; + } + } + } + return false; +} + +/// Ban an account or ban an IP address, duration will be parsed using TimeStringToSecs if it is positive, otherwise permban +uint8 World::BanAccount(std::string type, std::string nameOrIP, std::string duration, std::string reason, std::string author) +{ + loginDatabase.escape_string(nameOrIP); + loginDatabase.escape_string(reason); + std::string safe_author=author; + loginDatabase.escape_string(safe_author); + + if(type != "ip" && !normalizePlayerName(nameOrIP)) + return BAN_NOTFOUND; // Nobody to ban + + uint32 duration_secs = TimeStringToSecs(duration); + QueryResult *resultAccounts = NULL; //used for kicking + + ///- Update the database with ban information + + if(type=="ip") + { + //No SQL injection as strings are escaped + resultAccounts = loginDatabase.PQuery("SELECT id FROM account WHERE last_ip = '%s'",nameOrIP.c_str()); + loginDatabase.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+%u,'%s','%s')",nameOrIP.c_str(),duration_secs,safe_author.c_str(),reason.c_str()); + } + else if(type=="account") + { + //No SQL injection as string is escaped + resultAccounts = loginDatabase.PQuery("SELECT id FROM account WHERE username = '%s'",nameOrIP.c_str()); + } + else if(type=="character") + { + //No SQL injection as string is escaped + resultAccounts = CharacterDatabase.PQuery("SELECT account FROM characters WHERE name = '%s'",nameOrIP.c_str()); + } + else + return BAN_SYNTAX_ERROR; //Syntax problem + + if(!resultAccounts) + if(type=="ip") + return BAN_SUCCESS; // ip correctly banned but nobody affected (yet) + else + return BAN_NOTFOUND; // Nobody to ban + + ///- Disconnect all affected players (for IP it can be several) + do + { + Field* fieldsAccount = resultAccounts->Fetch(); + uint32 account = fieldsAccount->GetUInt32(); + + if(type != "ip") + //No SQL injection as strings are escaped + loginDatabase.PExecute("INSERT INTO account_banned VALUES ('%u', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+%u, '%s', '%s', '1')", + account,duration_secs,safe_author.c_str(),reason.c_str()); + + WorldSession* sess = FindSession(account); + if( sess ) + if(std::string(sess->GetPlayerName()) != author) + sess->KickPlayer(); + } + while( resultAccounts->NextRow() ); + + delete resultAccounts; + return BAN_SUCCESS; +} + +/// Remove a ban from an account or IP address +bool World::RemoveBanAccount(std::string type, std::string nameOrIP) +{ + if(type == "ip") + { + loginDatabase.escape_string(nameOrIP); + loginDatabase.PExecute("DELETE FROM ip_banned WHERE ip = '%s'",nameOrIP.c_str()); + } + else + { + uint32 account=0; + if(type == "account") + { + //NO SQL injection as name is escaped + loginDatabase.escape_string(nameOrIP); + QueryResult *resultAccounts = loginDatabase.PQuery("SELECT id FROM account WHERE username = '%s'",nameOrIP.c_str()); + if(!resultAccounts) + return false; + Field* fieldsAccount = resultAccounts->Fetch(); + account = fieldsAccount->GetUInt32(); + + delete resultAccounts; + } + else if(type == "character") + { + if(!normalizePlayerName(nameOrIP)) + return false; + + //NO SQL injection as name is escaped + loginDatabase.escape_string(nameOrIP); + QueryResult *resultAccounts = CharacterDatabase.PQuery("SELECT account FROM characters WHERE name = '%s'",nameOrIP.c_str()); + if(!resultAccounts) + return false; + Field* fieldsAccount = resultAccounts->Fetch(); + account = fieldsAccount->GetUInt32(); + + delete resultAccounts; + } + if(!account) + return false; + //NO SQL injection as account is uint32 + loginDatabase.PExecute("UPDATE account_banned SET active = '0' WHERE id = '%u'",account); + } + return true; +} + +/// Update the game time +void World::_UpdateGameTime() +{ + ///- update the time + time_t thisTime = time(NULL); + uint32 elapsed = uint32(thisTime - m_gameTime); + m_gameTime = thisTime; + + ///- if there is a shutdown timer + if(m_ShutdownTimer > 0 && elapsed > 0) + { + ///- ... and it is overdue, stop the world (set m_stopEvent) + if( m_ShutdownTimer <= elapsed ) + { + if(!(m_ShutdownMask & SHUTDOWN_MASK_IDLE) || GetActiveAndQueuedSessionCount()==0) + m_stopEvent = true; + else + m_ShutdownTimer = 1; // minimum timer value to wait idle state + } + ///- ... else decrease it and if necessary display a shutdown countdown to the users + else + { + m_ShutdownTimer -= elapsed; + + ShutdownMsg(); + } + } +} + +/// Shutdown the server +void World::ShutdownServ(uint32 time, uint32 options) +{ + m_ShutdownMask = options; + + ///- If the shutdown time is 0, set m_stopEvent (except if shutdown is 'idle' with remaining sessions) + if(time==0) + { + if(!(options & SHUTDOWN_MASK_IDLE) || GetActiveAndQueuedSessionCount()==0) + m_stopEvent = true; + else + m_ShutdownTimer = 1; //So that the session count is re-evaluated at next world tick + } + ///- Else set the shutdown timer and warn users + else + { + m_ShutdownTimer = time; + ShutdownMsg(true); + } +} + +/// Display a shutdown message to the user(s) +void World::ShutdownMsg(bool show, Player* player) +{ + // not show messages for idle shutdown mode + if(m_ShutdownMask & SHUTDOWN_MASK_IDLE) + return; + + ///- Display a message every 12 hours, hours, 5 minutes, minute, 5 seconds and finally seconds + if ( show || + (m_ShutdownTimer < 10) || + // < 30 sec; every 5 sec + (m_ShutdownTimer<30 && (m_ShutdownTimer % 5 )==0) || + // < 5 min ; every 1 min + (m_ShutdownTimer<5*MINUTE && (m_ShutdownTimer % MINUTE )==0) || + // < 30 min ; every 5 min + (m_ShutdownTimer<30*MINUTE && (m_ShutdownTimer % (5*MINUTE))==0) || + // < 12 h ; every 1 h + (m_ShutdownTimer<12*HOUR && (m_ShutdownTimer % HOUR )==0) || + // > 12 h ; every 12 h + (m_ShutdownTimer>12*HOUR && (m_ShutdownTimer % (12*HOUR) )==0)) + { + std::string str = secsToTimeString(m_ShutdownTimer); + + uint32 msgid = (m_ShutdownMask & SHUTDOWN_MASK_RESTART) ? SERVER_MSG_RESTART_TIME : SERVER_MSG_SHUTDOWN_TIME; + + SendServerMessage(msgid,str.c_str(),player); + DEBUG_LOG("Server is %s in %s",(m_ShutdownMask & SHUTDOWN_MASK_RESTART ? "restart" : "shuttingdown"),str.c_str()); + } +} + +/// Cancel a planned server shutdown +void World::ShutdownCancel() +{ + if(!m_ShutdownTimer) + return; + + uint32 msgid = (m_ShutdownMask & SHUTDOWN_MASK_RESTART) ? SERVER_MSG_RESTART_CANCELLED : SERVER_MSG_SHUTDOWN_CANCELLED; + + m_ShutdownMask = 0; + m_ShutdownTimer = 0; + SendServerMessage(msgid); + + DEBUG_LOG("Server %s cancelled.",(m_ShutdownMask & SHUTDOWN_MASK_RESTART ? "restart" : "shuttingdown")); +} + +/// Send a server message to the user(s) +void World::SendServerMessage(uint32 type, const char *text, Player* player) +{ + WorldPacket data(SMSG_SERVER_MESSAGE, 50); // guess size + data << uint32(type); + if(type <= SERVER_MSG_STRING) + data << text; + + if(player) + player->GetSession()->SendPacket(&data); + else + SendGlobalMessage( &data ); +} + +void World::UpdateSessions( time_t diff ) +{ + ///- Delete kicked sessions at add new session + for (std::set::iterator itr = m_kicked_sessions.begin(); itr != m_kicked_sessions.end(); ++itr) + delete *itr; + m_kicked_sessions.clear(); + + ///- Then send an update signal to remaining ones + for (SessionMap::iterator itr = m_sessions.begin(), next; itr != m_sessions.end(); itr = next) + { + next = itr; + ++next; + + if(!itr->second) + continue; + + ///- and remove not active sessions from the list + if(!itr->second->Update(diff)) // As interval = 0 + { + delete itr->second; + m_sessions.erase(itr); + } + } +} + +// This handles the issued and queued CLI commands +void World::ProcessCliCommands() +{ + if (cliCmdQueue.empty()) return; + + CliCommandHolder *command; + pPrintf p_zprintf; + while (!cliCmdQueue.empty()) + { + sLog.outDebug("CLI command under processing..."); + command = cliCmdQueue.next(); + command->Execute(); + p_zprintf=command->GetOutputMethod(); + delete command; + } + // print the console message here so it looks right + p_zprintf("mangos>"); +} + +void World::InitResultQueue() +{ + m_resultQueue = new SqlResultQueue; + CharacterDatabase.SetResultQueue(m_resultQueue); +} + +void World::UpdateResultQueue() +{ + m_resultQueue->Update(); +} + +void World::UpdateRealmCharCount(uint32 accountId) +{ + CharacterDatabase.AsyncPQuery(this, &World::_UpdateRealmCharCount, accountId, + "SELECT COUNT(guid) FROM characters WHERE account = '%u'", accountId); +} + +void World::_UpdateRealmCharCount(QueryResult *resultCharCount, uint32 accountId) +{ + if (resultCharCount) + { + Field *fields = resultCharCount->Fetch(); + uint32 charCount = fields[0].GetUInt32(); + delete resultCharCount; + loginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid= '%d' AND realmid = '%d'", accountId, realmID); + loginDatabase.PExecute("INSERT INTO realmcharacters (numchars, acctid, realmid) VALUES (%u, %u, %u)", charCount, accountId, realmID); + } +} + +void World::InitDailyQuestResetTime() +{ + time_t mostRecentQuestTime; + + QueryResult* result = CharacterDatabase.Query("SELECT MAX(time) FROM character_queststatus_daily"); + if(result) + { + Field *fields = result->Fetch(); + + mostRecentQuestTime = (time_t)fields[0].GetUInt64(); + delete result; + } + else + mostRecentQuestTime = 0; + + // client built-in time for reset is 6:00 AM + // FIX ME: client not show day start time + time_t curTime = time(NULL); + tm localTm = *localtime(&curTime); + localTm.tm_hour = 6; + localTm.tm_min = 0; + localTm.tm_sec = 0; + + // current day reset time + time_t curDayResetTime = mktime(&localTm); + + // last reset time before current moment + time_t resetTime = (curTime < curDayResetTime) ? curDayResetTime - DAY : curDayResetTime; + + // need reset (if we have quest time before last reset time (not processed by some reason) + if(mostRecentQuestTime && mostRecentQuestTime <= resetTime) + m_NextDailyQuestReset = mostRecentQuestTime; + else + { + // plan next reset time + m_NextDailyQuestReset = (curTime >= curDayResetTime) ? curDayResetTime + DAY : curDayResetTime; + } +} + +void World::ResetDailyQuests() +{ + sLog.outDetail("Daily quests reset for all characters."); + CharacterDatabase.Execute("DELETE FROM character_queststatus_daily"); + for(SessionMap::iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) + if(itr->second->GetPlayer()) + itr->second->GetPlayer()->ResetDailyQuestStatus(); +} + +void World::SetPlayerLimit( int32 limit, bool needUpdate ) +{ + if(limit < -SEC_ADMINISTRATOR) + limit = -SEC_ADMINISTRATOR; + + // lock update need + bool db_update_need = needUpdate || (limit < 0) != (m_playerLimit < 0) || (limit < 0 && m_playerLimit < 0 && limit != m_playerLimit); + + m_playerLimit = limit; + + if(db_update_need) + loginDatabase.PExecute("UPDATE realmlist SET allowedSecurityLevel = '%u' WHERE id = '%d'",uint8(GetPlayerSecurityLimit()),realmID); +} + +void World::UpdateMaxSessionCounters() +{ + m_maxActiveSessionCount = std::max(m_maxActiveSessionCount,uint32(m_sessions.size()-m_QueuedPlayer.size())); + m_maxQueuedSessionCount = std::max(m_maxQueuedSessionCount,uint32(m_QueuedPlayer.size())); +} diff --git a/src/game/World.h b/src/game/World.h new file mode 100644 index 00000000000..56450832ab9 --- /dev/null +++ b/src/game/World.h @@ -0,0 +1,534 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/// \addtogroup world The World +/// @{ +/// \file + +#ifndef __WORLD_H +#define __WORLD_H + +#include "Common.h" +#include "Timer.h" +#include "Policies/Singleton.h" + +#include +#include +#include + +class Object; +class WorldPacket; +class WorldSession; +class Player; +class Weather; +struct ScriptAction; +struct ScriptInfo; +class CliCommandHolder; +class SqlResultQueue; +class QueryResult; +class WorldSocket; + +enum ShutdownMask +{ + SHUTDOWN_MASK_RESTART = 1, + SHUTDOWN_MASK_IDLE = 2, +}; + +/// Timers for different object refresh rates +enum WorldTimers +{ + WUPDATE_OBJECTS = 0, + WUPDATE_SESSIONS = 1, + WUPDATE_AUCTIONS = 2, + WUPDATE_WEATHERS = 3, + WUPDATE_UPTIME = 4, + WUPDATE_CORPSES = 5, + WUPDATE_EVENTS = 6, + WUPDATE_COUNT = 7 +}; + +/// Configuration elements +enum WorldConfigs +{ + CONFIG_COMPRESSION = 0, + CONFIG_GRID_UNLOAD, + CONFIG_INTERVAL_SAVE, + CONFIG_INTERVAL_GRIDCLEAN, + CONFIG_INTERVAL_MAPUPDATE, + CONFIG_INTERVAL_CHANGEWEATHER, + CONFIG_PORT_WORLD, + CONFIG_SOCKET_SELECTTIME, + CONFIG_GROUP_XP_DISTANCE, + CONFIG_SIGHT_MONSTER, + CONFIG_SIGHT_GUARDER, + CONFIG_GAME_TYPE, + CONFIG_REALM_ZONE, + CONFIG_ALLOW_TWO_SIDE_ACCOUNTS, + CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT, + CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL, + CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP, + CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD, + CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION, + CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL, + CONFIG_ALLOW_TWO_SIDE_WHO_LIST, + CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND, + CONFIG_STRICT_PLAYER_NAMES, + CONFIG_STRICT_CHARTER_NAMES, + CONFIG_STRICT_PET_NAMES, + CONFIG_CHARACTERS_CREATING_DISABLED, + CONFIG_CHARACTERS_PER_ACCOUNT, + CONFIG_CHARACTERS_PER_REALM, + CONFIG_SKIP_CINEMATICS, + CONFIG_MAX_PLAYER_LEVEL, + CONFIG_START_PLAYER_LEVEL, + CONFIG_MAX_HONOR_POINTS, + CONFIG_MAX_ARENA_POINTS, + CONFIG_INSTANCE_IGNORE_LEVEL, + CONFIG_INSTANCE_IGNORE_RAID, + CONFIG_BATTLEGROUND_CAST_DESERTER, + CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE, + CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY, + CONFIG_INSTANCE_RESET_TIME_HOUR, + CONFIG_INSTANCE_UNLOAD_DELAY, + CONFIG_CAST_UNSTUCK, + CONFIG_MAX_PRIMARY_TRADE_SKILL, + CONFIG_MIN_PETITION_SIGNS, + CONFIG_GM_WISPERING_TO, + CONFIG_GM_IN_GM_LIST, + CONFIG_GM_IN_WHO_LIST, + CONFIG_GM_LOGIN_STATE, + CONFIG_GM_LOG_TRADE, + CONFIG_GROUP_VISIBILITY, + CONFIG_MAIL_DELIVERY_DELAY, + CONFIG_UPTIME_UPDATE, + CONFIG_SKILL_CHANCE_ORANGE, + CONFIG_SKILL_CHANCE_YELLOW, + CONFIG_SKILL_CHANCE_GREEN, + CONFIG_SKILL_CHANCE_GREY, + CONFIG_SKILL_CHANCE_MINING_STEPS, + CONFIG_SKILL_CHANCE_SKINNING_STEPS, + CONFIG_SKILL_PROSPECTING, + CONFIG_SKILL_GAIN_CRAFTING, + CONFIG_SKILL_GAIN_DEFENSE, + CONFIG_SKILL_GAIN_GATHERING, + CONFIG_SKILL_GAIN_WEAPON, + CONFIG_MAX_OVERSPEED_PINGS, + CONFIG_SAVE_RESPAWN_TIME_IMMEDIATLY, + CONFIG_WEATHER, + CONFIG_EXPANSION, + CONFIG_CHATFLOOD_MESSAGE_COUNT, + CONFIG_CHATFLOOD_MESSAGE_DELAY, + CONFIG_CHATFLOOD_MUTE_TIME, + CONFIG_EVENT_ANNOUNCE, + CONFIG_CREATURE_FAMILY_ASSISTEMCE_RADIUS, + CONFIG_WORLD_BOSS_LEVEL_DIFF, + CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF, + CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF, + CONFIG_DETECT_POS_COLLISION, + CONFIG_RESTRICTED_LFG_CHANNEL, + CONFIG_SILENTLY_GM_JOIN_TO_CHANNEL, + CONFIG_TALENTS_INSPECTING, + CONFIG_CHAT_FAKE_MESSAGE_PREVENTING, + CONFIG_TCP_NO_DELAY, + CONFIG_CORPSE_DECAY_NORMAL, + CONFIG_CORPSE_DECAY_RARE, + CONFIG_CORPSE_DECAY_ELITE, + CONFIG_CORPSE_DECAY_RAREELITE, + CONFIG_CORPSE_DECAY_WORLDBOSS, + CONFIG_ADDON_CHANNEL, + CONFIG_DEATH_SICKNESS_LEVEL, + CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVP, + CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVE, + CONFIG_THREAT_RADIUS, + CONFIG_DECLINED_NAMES_USED, + CONFIG_LISTEN_RANGE_SAY, + CONFIG_LISTEN_RANGE_TEXTEMOTE, + CONFIG_LISTEN_RANGE_YELL, + CONFIG_VALUE_COUNT +}; + +/// Server rates +enum Rates +{ + RATE_HEALTH=0, + RATE_POWER_MANA, + RATE_POWER_RAGE_INCOME, + RATE_POWER_RAGE_LOSS, + RATE_POWER_FOCUS, + RATE_SKILL_DISCOVERY, + RATE_DROP_ITEM_POOR, + RATE_DROP_ITEM_NORMAL, + RATE_DROP_ITEM_UNCOMMON, + RATE_DROP_ITEM_RARE, + RATE_DROP_ITEM_EPIC, + RATE_DROP_ITEM_LEGENDARY, + RATE_DROP_ITEM_ARTIFACT, + RATE_DROP_ITEM_REFERENCED, + RATE_DROP_MONEY, + RATE_XP_KILL, + RATE_XP_QUEST, + RATE_XP_EXPLORE, + RATE_XP_PAST_70, + RATE_REPUTATION_GAIN, + RATE_CREATURE_NORMAL_HP, + RATE_CREATURE_ELITE_ELITE_HP, + RATE_CREATURE_ELITE_RAREELITE_HP, + RATE_CREATURE_ELITE_WORLDBOSS_HP, + RATE_CREATURE_ELITE_RARE_HP, + RATE_CREATURE_NORMAL_DAMAGE, + RATE_CREATURE_ELITE_ELITE_DAMAGE, + RATE_CREATURE_ELITE_RAREELITE_DAMAGE, + RATE_CREATURE_ELITE_WORLDBOSS_DAMAGE, + RATE_CREATURE_ELITE_RARE_DAMAGE, + RATE_CREATURE_NORMAL_SPELLDAMAGE, + RATE_CREATURE_ELITE_ELITE_SPELLDAMAGE, + RATE_CREATURE_ELITE_RAREELITE_SPELLDAMAGE, + RATE_CREATURE_ELITE_WORLDBOSS_SPELLDAMAGE, + RATE_CREATURE_ELITE_RARE_SPELLDAMAGE, + RATE_CREATURE_AGGRO, + RATE_REST_INGAME, + RATE_REST_OFFLINE_IN_TAVERN_OR_CITY, + RATE_REST_OFFLINE_IN_WILDERNESS, + RATE_DAMAGE_FALL, + RATE_AUCTION_TIME, + RATE_AUCTION_DEPOSIT, + RATE_AUCTION_CUT, + RATE_HONOR, + RATE_MINING_AMOUNT, + RATE_MINING_NEXT, + RATE_TALENT, + RATE_LOYALTY, + RATE_CORPSE_DECAY_LOOTED, + RATE_INSTANCE_RESET_TIME, + RATE_TARGET_POS_RECALCULATION_RANGE, + RATE_DURABILITY_LOSS_DAMAGE, + RATE_DURABILITY_LOSS_PARRY, + RATE_DURABILITY_LOSS_ABSORB, + RATE_DURABILITY_LOSS_BLOCK, + MAX_RATES +}; + +/// Type of server +enum RealmType +{ + REALM_TYPE_NORMAL = 0, + REALM_TYPE_PVP = 1, + REALM_TYPE_NORMAL2 = 4, + REALM_TYPE_RP = 6, + REALM_TYPE_RPPVP = 8, + REALM_TYPE_FFA_PVP = 16 // custom, free for all pvp mode like arena PvP in all zones except rest activated places and sanctuaries + // replaced by REALM_PVP in realm list +}; + +enum RealmZone +{ + REALM_ZONE_UNKNOWN = 0, // any language + REALM_ZONE_DEVELOPMENT = 1, // any language + REALM_ZONE_UNITED_STATES = 2, // extended-Latin + REALM_ZONE_OCEANIC = 3, // extended-Latin + REALM_ZONE_LATIN_AMERICA = 4, // extended-Latin + REALM_ZONE_TOURNAMENT_5 = 5, // basic-Latin at create, any at login + REALM_ZONE_KOREA = 6, // East-Asian + REALM_ZONE_TOURNAMENT_7 = 7, // basic-Latin at create, any at login + REALM_ZONE_ENGLISH = 8, // extended-Latin + REALM_ZONE_GERMAN = 9, // extended-Latin + REALM_ZONE_FRENCH = 10, // extended-Latin + REALM_ZONE_SPANISH = 11, // extended-Latin + REALM_ZONE_RUSSIAN = 12, // Cyrillic + REALM_ZONE_TOURNAMENT_13 = 13, // basic-Latin at create, any at login + REALM_ZONE_TAIWAN = 14, // East-Asian + REALM_ZONE_TOURNAMENT_15 = 15, // basic-Latin at create, any at login + REALM_ZONE_CHINA = 16, // East-Asian + REALM_ZONE_CN1 = 17, // basic-Latin at create, any at login + REALM_ZONE_CN2 = 18, // basic-Latin at create, any at login + REALM_ZONE_CN3 = 19, // basic-Latin at create, any at login + REALM_ZONE_CN4 = 20, // basic-Latin at create, any at login + REALM_ZONE_CN5 = 21, // basic-Latin at create, any at login + REALM_ZONE_CN6 = 22, // basic-Latin at create, any at login + REALM_ZONE_CN7 = 23, // basic-Latin at create, any at login + REALM_ZONE_CN8 = 24, // basic-Latin at create, any at login + REALM_ZONE_TOURNAMENT_25 = 25, // basic-Latin at create, any at login + REALM_ZONE_TEST_SERVER = 26, // any language + REALM_ZONE_TOURNAMENT_27 = 27, // basic-Latin at create, any at login + REALM_ZONE_QA_SERVER = 28, // any language + REALM_ZONE_CN9 = 29 // basic-Latin at create, any at login +}; + +/// Ban function return codes +enum BanReturn +{ + BAN_SUCCESS, + BAN_SYNTAX_ERROR, + BAN_NOTFOUND +}; + +// DB scripting commands +#define SCRIPT_COMMAND_TALK 0 // source = unit, target=any, datalong ( 0=say, 1=whisper, 2=yell, 3=emote text) +#define SCRIPT_COMMAND_EMOTE 1 // source = unit, datalong = anim_id +#define SCRIPT_COMMAND_FIELD_SET 2 // source = any, datalong = field_id, datalog2 = value +#define SCRIPT_COMMAND_MOVE_TO 3 // source = Creature, datalog2 = time, x/y/z +#define SCRIPT_COMMAND_FLAG_SET 4 // source = any, datalong = field_id, datalog2 = bitmask +#define SCRIPT_COMMAND_FLAG_REMOVE 5 // source = any, datalong = field_id, datalog2 = bitmask +#define SCRIPT_COMMAND_TELEPORT_TO 6 // source or target with Player, datalong = map_id, x/y/z +#define SCRIPT_COMMAND_QUEST_EXPLORED 7 // one from source or target must be Player, another GO/Creature, datalong=quest_id, datalong2=distance or 0 +#define SCRIPT_COMMAND_RESPAWN_GAMEOBJECT 9 // source = any (summoner), datalong=db_guid, datalong2=despawn_delay +#define SCRIPT_COMMAND_TEMP_SUMMON_CREATURE 10 // source = any (summoner), datalong=creature entry, datalong2=despawn_delay +#define SCRIPT_COMMAND_OPEN_DOOR 11 // source = unit, datalong=db_guid, datalong2=reset_delay +#define SCRIPT_COMMAND_CLOSE_DOOR 12 // source = unit, datalong=db_guid, datalong2=reset_delay +#define SCRIPT_COMMAND_ACTIVATE_OBJECT 13 // source = unit, target=GO +#define SCRIPT_COMMAND_REMOVE_AURA 14 // source (datalong2!=0) or target (datalong==0) unit, datalong = spell_id +#define SCRIPT_COMMAND_CAST_SPELL 15 // source (datalong2!=0) or target (datalong==0) unit, datalong = spell_id + +/// CLI related stuff, define here to prevent cyclic dependancies + +typedef int(* pPrintf)(const char*,...); +typedef void(* pCliFunc)(char *,pPrintf); + +/// Command Template class +struct CliCommand +{ + char const * cmd; + pCliFunc Func; + char const * description; +}; + +/// Storage class for commands issued for delayed execution +class CliCommandHolder +{ + private: + const CliCommand *cmd; + char *args; + pPrintf m_zprintf; + public: + CliCommandHolder(const CliCommand *command, const char *arguments, pPrintf p_zprintf) + : cmd(command), m_zprintf(p_zprintf) + { + size_t len = strlen(arguments)+1; + args = new char[len]; + memcpy(args, arguments, len); + } + ~CliCommandHolder() { delete[] args; } + void Execute() const { cmd->Func(args, m_zprintf); } + pPrintf GetOutputMethod() const {return (m_zprintf);} +}; + +/// The World +class World +{ + public: + static volatile bool m_stopEvent; + static volatile uint32 m_worldLoopCounter; + + World(); + ~World(); + + WorldSession* FindSession(uint32 id) const; + void AddSession(WorldSession *s); + bool RemoveSession(uint32 id); + /// Get the number of current active sessions + void UpdateMaxSessionCounters(); + uint32 GetActiveAndQueuedSessionCount() const { return m_sessions.size(); } + uint32 GetActiveSessionCount() const { return m_sessions.size() - m_QueuedPlayer.size(); } + uint32 GetQueuedSessionCount() const { return m_QueuedPlayer.size(); } + /// Get the maximum number of parallel sessions on the server since last reboot + uint32 GetMaxQueuedSessionCount() const { return m_maxQueuedSessionCount; } + uint32 GetMaxActiveSessionCount() const { return m_maxActiveSessionCount; } + Player* FindPlayerInZone(uint32 zone); + + Weather* FindWeather(uint32 id) const; + Weather* AddWeather(uint32 zone_id); + void RemoveWeather(uint32 zone_id); + + /// Get the active session server limit (or security level limitations) + uint32 GetPlayerAmountLimit() const { return m_playerLimit >= 0 ? m_playerLimit : 0; } + AccountTypes GetPlayerSecurityLimit() const { return m_playerLimit <= 0 ? AccountTypes(-m_playerLimit) : SEC_PLAYER; } + + /// Set the active session server limit (or security level limitation) + void SetPlayerLimit(int32 limit, bool needUpdate = false); + + //player Queue + typedef std::list Queue; + void AddQueuedPlayer(WorldSocket* Socket); + void RemoveQueuedPlayer(WorldSocket* Socket); + int32 GetQueuePos(WorldSocket* Socket); + uint32 GetQueueSize() const { return m_QueuedPlayer.size(); } + + /// \todo Actions on m_allowMovement still to be implemented + /// Is movement allowed? + bool getAllowMovement() const { return m_allowMovement; } + /// Allow/Disallow object movements + void SetAllowMovement(bool allow) { m_allowMovement = allow; } + + /// Set a new Message of the Day + void SetMotd(std::string motd) { m_motd = motd; } + /// Get the current Message of the Day + const char* GetMotd() const { return m_motd.c_str(); } + + uint32 GetDefaultDbcLocale() const { return m_defaultDbcLocale; } + + /// Get the path where data (dbc, maps) are stored on disk + std::string GetDataPath() const { return m_dataPath; } + + /// When server started? + time_t const& GetStartTime() const { return m_startTime; } + /// What time is it? + time_t const& GetGameTime() const { return m_gameTime; } + /// Uptime (in secs) + uint32 GetUptime() const { return uint32(m_gameTime - m_startTime); } + + /// Get the maximum skill level a player can reach + uint16 GetConfigMaxSkillValue() const + { + uint32 lvl = getConfig(CONFIG_MAX_PLAYER_LEVEL); + return lvl > 60 ? 300 + ((lvl - 60) * 75) / 10 : lvl*5; + } + + void SetInitialWorldSettings(); + void LoadConfigSettings(bool reload = false); + + void SendWorldText(int32 string_id, ...); + void SendGlobalMessage(WorldPacket *packet, WorldSession *self = 0, uint32 team = 0); + void SendZoneMessage(uint32 zone, WorldPacket *packet, WorldSession *self = 0, uint32 team = 0); + void SendZoneText(uint32 zone, const char *text, WorldSession *self = 0, uint32 team = 0); + void SendServerMessage(uint32 type, const char *text = "", Player* player = NULL); + + /// Are we in the middle of a shutdown? + uint32 GetShutdownMask() const { return m_ShutdownMask; } + bool IsShutdowning() const { return m_ShutdownTimer > 0; } + void ShutdownServ(uint32 time, uint32 options = 0); + void ShutdownCancel(); + void ShutdownMsg(bool show = false, Player* player = NULL); + + void Update(time_t diff); + + void UpdateSessions( time_t diff ); + /// Set a server rate (see #Rates) + void setRate(Rates rate,float value) { rate_values[rate]=value; } + /// Get a server rate (see #Rates) + float getRate(Rates rate) const { return rate_values[rate]; } + + /// Set a server configuration element (see #WorldConfigs) + void setConfig(uint32 index,uint32 value) + { + if(index > const& scripts, uint32 id, Object* source, Object* target); + void ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target); + bool IsScriptScheduled() const { return !m_scriptSchedule.empty(); } + + // for max speed access + static float GetMaxVisibleDistanceForCreature() { return m_MaxVisibleDistanceForCreature; } + static float GetMaxVisibleDistanceForPlayer() { return m_MaxVisibleDistanceForPlayer; } + static float GetMaxVisibleDistanceForObject() { return m_MaxVisibleDistanceForObject; } + static float GetMaxVisibleDistanceInFlight() { return m_MaxVisibleDistanceInFlight; } + static float GetVisibleUnitGreyDistance() { return m_VisibleUnitGreyDistance; } + static float GetVisibleObjectGreyDistance() { return m_VisibleObjectGreyDistance; } + + void ProcessCliCommands(); + void QueueCliCommand(CliCommandHolder* command) { cliCmdQueue.add(command); } + + void UpdateResultQueue(); + void InitResultQueue(); + + void UpdateRealmCharCount(uint32 accid); + + LocaleConstant GetAvailableDbcLocale(LocaleConstant locale) const { if(m_availableDbcLocaleMask & (1 << locale)) return locale; else return m_defaultDbcLocale; } + protected: + void _UpdateGameTime(); + void ScriptsProcess(); + // callback for UpdateRealmCharacters + void _UpdateRealmCharCount(QueryResult *resultCharCount, uint32 accountId); + + void InitDailyQuestResetTime(); + void ResetDailyQuests(); + private: + time_t m_startTime; + time_t m_gameTime; + IntervalTimer m_timers[WUPDATE_COUNT]; + uint32 mail_timer; + uint32 mail_timer_expires; + + typedef HM_NAMESPACE::hash_map WeatherMap; + WeatherMap m_weathers; + typedef HM_NAMESPACE::hash_map SessionMap; + SessionMap m_sessions; + std::set m_kicked_sessions; + uint32 m_maxActiveSessionCount; + uint32 m_maxQueuedSessionCount; + + std::multimap m_scriptSchedule; + + float rate_values[MAX_RATES]; + uint32 m_configs[CONFIG_VALUE_COUNT]; + int32 m_playerLimit; + LocaleConstant m_defaultDbcLocale; // from config for one from loaded DBC locales + uint32 m_availableDbcLocaleMask; // by loaded DBC + void DetectDBCLang(); + bool m_allowMovement; + std::string m_motd; + std::string m_dataPath; + + uint32 m_ShutdownTimer; + uint32 m_ShutdownMask; + + // for max speed access + static float m_MaxVisibleDistanceForCreature; + static float m_MaxVisibleDistanceForPlayer; + static float m_MaxVisibleDistanceForObject; + static float m_MaxVisibleDistanceInFlight; + static float m_VisibleUnitGreyDistance; + static float m_VisibleObjectGreyDistance; + + // CLI command holder to be thread safe + ZThread::LockedQueue cliCmdQueue; + SqlResultQueue *m_resultQueue; + + // next daily quests reset time + time_t m_NextDailyQuestReset; + + //Player Queue + Queue m_QueuedPlayer; +}; + +extern uint32 realmID; + +#define sWorld MaNGOS::Singleton::Instance() +#endif +/// @} diff --git a/src/game/WorldLog.cpp b/src/game/WorldLog.cpp new file mode 100644 index 00000000000..21fc26da41b --- /dev/null +++ b/src/game/WorldLog.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** \file + \ingroup u2w +*/ + +#include "WorldLog.h" +#include "Policies/SingletonImp.h" +#include "Config/ConfigEnv.h" + +#define CLASS_LOCK MaNGOS::ClassLevelLockable +INSTANTIATE_SINGLETON_2(WorldLog, CLASS_LOCK); +INSTANTIATE_CLASS_MUTEX(WorldLog, ZThread::FastMutex); + +#define WORLD_LOG_FILE_STRING "world.log" + +/// Open the log file (if specified so in the configuration file) +void WorldLog::Initialize() +{ + std::string logsDir = sConfig.GetStringDefault("LogsDir",""); + + if(!logsDir.empty()) + { + if((logsDir.at(logsDir.length()-1)!='/') && (logsDir.at(logsDir.length()-1)!='\\')) + logsDir.append("/"); + } + + std::string logname = sConfig.GetStringDefault("WorldLogFile", ""); + if(!logname.empty()) + { + i_file = fopen((logsDir+logname).c_str(), "w"); + } +} + +#define sWorldLog WorldLog::Instance() diff --git a/src/game/WorldLog.h b/src/game/WorldLog.h new file mode 100644 index 00000000000..5047161b63e --- /dev/null +++ b/src/game/WorldLog.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/// \addtogroup u2w +/// @{ +/// \file + +#ifndef MANGOS_WORLDLOG_H +#define MANGOS_WORLDLOG_H + +#include "Common.h" +#include "Policies/Singleton.h" +#include "Errors.h" + +#include + +/// %Log packets to a file +class MANGOS_DLL_DECL WorldLog : public MaNGOS::Singleton > +{ + friend class MaNGOS::OperatorNew; + WorldLog() : i_file(NULL) { Initialize(); } + WorldLog(const WorldLog &); + WorldLog& operator=(const WorldLog &); + typedef MaNGOS::ClassLevelLockable::Lock Guard; + + /// Close the file in destructor + ~WorldLog() + { + if( i_file != NULL ) + fclose(i_file); + i_file = NULL; + } + + public: + void Initialize(); + /// Is the world logger active? + inline bool LogWorld(void) const { return (i_file != NULL); } + /// %Log to the file + inline void Log(char const *fmt, ...) + { + if( LogWorld() ) + { + Guard guard(*this); + ASSERT(i_file); + + va_list args; + va_start(args, fmt); + vfprintf(i_file, fmt, args); + va_end(args); + + fflush(i_file); + } + } + + private: + FILE *i_file; +}; + +#define sWorldLog WorldLog::Instance() +#endif +/// @} diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp new file mode 100644 index 00000000000..eaba12b4a10 --- /dev/null +++ b/src/game/WorldSession.cpp @@ -0,0 +1,463 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** \file + \ingroup u2w +*/ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "Log.h" +#include "Opcodes.h" +#include "WorldSocket.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Player.h" +#include "ObjectMgr.h" +#include "Group.h" +#include "Guild.h" +#include "World.h" +#include "MapManager.h" +#include "ObjectAccessor.h" +#include "BattleGroundMgr.h" +#include "Language.h" // for CMSG_CANCEL_MOUNT_AURA handler +#include "Chat.h" +#include "SocialMgr.h" + +/// WorldSession constructor +WorldSession::WorldSession(uint32 id, WorldSocket *sock, uint32 sec, bool tbc, time_t mute_time, LocaleConstant locale) : +LookingForGroup_auto_join(false), LookingForGroup_auto_add(false), m_muteTime(mute_time), +_player(NULL), _socket(sock),_security(sec), _accountId(id), m_isTBC(tbc), +m_sessionDbcLocale(sWorld.GetAvailableDbcLocale(locale)), m_sessionDbLocaleIndex(objmgr.GetIndexForLocale(locale)), +_logoutTime(0), m_playerLoading(false), m_playerLogout(false), m_playerRecentlyLogout(false), m_latency(0) +{ +} + +/// WorldSession destructor +WorldSession::~WorldSession() +{ + ///- unload player if not unloaded + if(_player) + LogoutPlayer(true); + + /// - If have unclosed socket, close it + if(_socket) + _socket->CloseSocket(); + + _socket = NULL; + + ///- empty incoming packet queue + while(!_recvQueue.empty()) + { + WorldPacket *packet = _recvQueue.next(); + delete packet; + } +} + +void WorldSession::SizeError(WorldPacket const& packet, uint32 size) const +{ + sLog.outError("Client (account %u) send packet %s (%u) with size %u but expected %u (attempt crash server?), skipped", + GetAccountId(),LookupOpcodeName(packet.GetOpcode()),packet.GetOpcode(),packet.size(),size); +} + +/// Get the player name +char const* WorldSession::GetPlayerName() const +{ + return GetPlayer() ? GetPlayer()->GetName() : ""; +} + +/// Set the WorldSocket associated with this session +void WorldSession::SetSocket(WorldSocket *sock) +{ + _socket = sock; +} + +/// Send a packet to the client +void WorldSession::SendPacket(WorldPacket const* packet) +{ + if (!_socket) + return; + #ifdef MANGOS_DEBUG + // Code for network use statistic + static uint64 sendPacketCount = 0; + static uint64 sendPacketBytes = 0; + + static time_t firstTime = time(NULL); + static time_t lastTime = firstTime; // next 60 secs start time + + static uint64 sendLastPacketCount = 0; + static uint64 sendLastPacketBytes = 0; + + time_t cur_time = time(NULL); + + if((cur_time - lastTime) < 60) + { + sendPacketCount+=1; + sendPacketBytes+=packet->size(); + + sendLastPacketCount+=1; + sendLastPacketBytes+=packet->size(); + } + else + { + uint64 minTime = uint64(cur_time - lastTime); + uint64 fullTime = uint64(lastTime - firstTime); + sLog.outDetail("Send all time packets count: " I64FMTD " bytes: " I64FMTD " avr.count/sec: %f avr.bytes/sec: %f time: %u",sendPacketCount,sendPacketBytes,float(sendPacketCount)/fullTime,float(sendPacketBytes)/fullTime,uint32(fullTime)); + sLog.outDetail("Send last min packets count: " I64FMTD " bytes: " I64FMTD " avr.count/sec: %f avr.bytes/sec: %f",sendLastPacketCount,sendLastPacketBytes,float(sendLastPacketCount)/minTime,float(sendLastPacketBytes)/minTime); + + lastTime = cur_time; + sendLastPacketCount = 1; + sendLastPacketBytes = packet->wpos(); // wpos is real written size + } + #endif // !MANGOS_DEBUG + + _socket->SendPacket(packet); +} + +/// Add an incoming packet to the queue +void WorldSession::QueuePacket(WorldPacket& packet) +{ + WorldPacket *pck = new WorldPacket(packet); + _recvQueue.add(pck); +} + +/// Logging helper for unexpected opcodes +void WorldSession::logUnexpectedOpcode(WorldPacket* packet, const char *reason) +{ + sLog.outError( "SESSION: received unexpected opcode %s (0x%.4X) %s", + LookupOpcodeName(packet->GetOpcode()), + packet->GetOpcode(), + reason); +} + +/// Update the WorldSession (triggered by World update) +bool WorldSession::Update(uint32 /*diff*/) +{ + WorldPacket *packet; + + ///- Retrieve packets from the receive queue and call the appropriate handlers + /// \todo Is there a way to consolidate the OpcondeHandlerTable and the g_worldOpcodeNames to only maintain 1 list? + /// answer : there is a way, but this is better, because it would use redundant RAM + while (!_recvQueue.empty()) + { + packet = _recvQueue.next(); + + /*#if 1 + sLog.outError( "MOEP: %s (0x%.4X)", + LookupOpcodeName(packet->GetOpcode()), + packet->GetOpcode()); + #endif*/ + + if(packet->GetOpcode() >= NUM_MSG_TYPES) + { + sLog.outError( "SESSION: received non-existed opcode %s (0x%.4X)", + LookupOpcodeName(packet->GetOpcode()), + packet->GetOpcode()); + } + else + { + OpcodeHandler& opHandle = opcodeTable[packet->GetOpcode()]; + switch (opHandle.status) + { + case STATUS_LOGGEDIN: + if(!_player) + { + // skip STATUS_LOGGEDIN opcode unexpected errors if player logout sometime ago - this can be network lag delayed packets + if(!m_playerRecentlyLogout) + logUnexpectedOpcode(packet, "the player has not logged in yet"); + } + else if(_player->IsInWorld()) + (this->*opHandle.handler)(*packet); + // lag can cause STATUS_LOGGEDIN opcodes to arrive after the player started a transfer + break; + case STATUS_TRANSFER_PENDING: + if(!_player) + logUnexpectedOpcode(packet, "the player has not logged in yet"); + else if(_player->IsInWorld()) + logUnexpectedOpcode(packet, "the player is still in world"); + else + (this->*opHandle.handler)(*packet); + break; + case STATUS_AUTHED: + m_playerRecentlyLogout = false; + (this->*opHandle.handler)(*packet); + break; + case STATUS_NEVER: + sLog.outError( "SESSION: received not allowed opcode %s (0x%.4X)", + LookupOpcodeName(packet->GetOpcode()), + packet->GetOpcode()); + break; + } + } + + delete packet; + } + + ///- If necessary, log the player out + time_t currTime = time(NULL); + if (!_socket || (ShouldLogOut(currTime) && !m_playerLoading)) + LogoutPlayer(true); + + if (!_socket) + return false; //Will remove this session from the world session map + + return true; +} + +/// %Log the player out +void WorldSession::LogoutPlayer(bool Save) +{ + // finish pending transfers before starting the logout + while(_player && _player->IsBeingTeleported()) + HandleMoveWorldportAckOpcode(); + + m_playerLogout = true; + + if (_player) + { + ///- If the player just died before logging out, make him appear as a ghost + //FIXME: logout must be delayed in case lost connection with client in time of combat + if (_player->GetDeathTimer()) + { + _player->getHostilRefManager().deleteReferences(); + _player->BuildPlayerRepop(); + _player->RepopAtGraveyard(); + } + else if (!_player->getAttackers().empty()) + { + _player->CombatStop(); + _player->getHostilRefManager().setOnlineOfflineState(false); + _player->RemoveAllAurasOnDeath(); + + // build set of player who attack _player or who have pet attacking of _player + std::set aset; + for(Unit::AttackerSet::const_iterator itr = _player->getAttackers().begin(); itr != _player->getAttackers().end(); ++itr) + { + Unit* owner = (*itr)->GetOwner(); // including player controlled case + if(owner) + { + if(owner->GetTypeId()==TYPEID_PLAYER) + aset.insert((Player*)owner); + } + else + if((*itr)->GetTypeId()==TYPEID_PLAYER) + aset.insert((Player*)(*itr)); + } + + _player->SetPvPDeath(!aset.empty()); + _player->KillPlayer(); + _player->BuildPlayerRepop(); + _player->RepopAtGraveyard(); + + // give honor to all attackers from set like group case + for(std::set::const_iterator itr = aset.begin(); itr != aset.end(); ++itr) + (*itr)->RewardHonor(_player,aset.size()); + + // give bg rewards and update counters like kill by first from attackers + // this can't be called for all attackers. + if(!aset.empty()) + if(BattleGround *bg = _player->GetBattleGround()) + bg->HandleKillPlayer(_player,*aset.begin()); + } + else if(_player->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION)) + { + // this will kill character by SPELL_AURA_SPIRIT_OF_REDEMPTION + _player->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT); + //_player->SetDeathPvP(*); set at SPELL_AURA_SPIRIT_OF_REDEMPTION apply time + _player->KillPlayer(); + _player->BuildPlayerRepop(); + _player->RepopAtGraveyard(); + } + + ///- Remove player from battleground (teleport to entrance) + if(_player->InBattleGround()) + _player->LeaveBattleground(); + + for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) + { + if(int32 bgTypeId = _player->GetBattleGroundQueueId(i)) + { + _player->RemoveBattleGroundQueueId(bgTypeId); + sBattleGroundMgr.m_BattleGroundQueues[ bgTypeId ].RemovePlayer(_player->GetGUID(), true); + } + } + + ///- Reset the online field in the account table + // no point resetting online in character table here as Player::SaveToDB() will set it to 1 since player has not been removed from world at this stage + //No SQL injection as AccountID is uint32 + loginDatabase.PExecute("UPDATE account SET online = 0 WHERE id = '%u'", GetAccountId()); + + ///- If the player is in a guild, update the guild roster and broadcast a logout message to other guild members + Guild *guild = objmgr.GetGuildById(_player->GetGuildId()); + if(guild) + { + guild->LoadPlayerStatsByGuid(_player->GetGUID()); + guild->UpdateLogoutTime(_player->GetGUID()); + + WorldPacket data(SMSG_GUILD_EVENT, (1+1+12+8)); // name limited to 12 in character table. + data<<(uint8)GE_SIGNED_OFF; + data<<(uint8)1; + data<<_player->GetName(); + data<<_player->GetGUID(); + guild->BroadcastPacket(&data); + } + + ///- Remove pet + _player->RemovePet(NULL,PET_SAVE_AS_CURRENT, true); + + ///- empty buyback items and save the player in the database + // some save parts only correctly work in case player present in map/player_lists (pets, etc) + if(Save) + { + uint32 eslot; + for(int j = BUYBACK_SLOT_START; j < BUYBACK_SLOT_END; j++) + { + eslot = j - BUYBACK_SLOT_START; + _player->SetUInt64Value(PLAYER_FIELD_VENDORBUYBACK_SLOT_1+eslot*2,0); + _player->SetUInt32Value(PLAYER_FIELD_BUYBACK_PRICE_1+eslot,0); + _player->SetUInt32Value(PLAYER_FIELD_BUYBACK_TIMESTAMP_1+eslot,0); + } + _player->SaveToDB(); + } + + ///- Leave all channels before player delete... + _player->CleanupChannels(); + + ///- If the player is in a group (or invited), remove him. If the group if then only 1 person, disband the group. + _player->UninviteFromGroup(); + + // remove player from the group if he is: + // a) in group; b) not in raid group; c) logging out normally (not being kicked or disconnected) + if(_player->GetGroup() && !_player->GetGroup()->isRaidGroup() && _socket) + _player->RemoveFromGroup(); + + ///- Remove the player from the world + // the player may not be in the world when logging out + // e.g if he got disconnected during a transfer to another map + // calls to GetMap in this case may cause crashes + if(_player->IsInWorld()) MapManager::Instance().GetMap(_player->GetMapId(), _player)->Remove(_player, false); + // RemoveFromWorld does cleanup that requires the player to be in the accessor + ObjectAccessor::Instance().RemoveObject(_player); + + ///- Send update to group + if(_player->GetGroup()) + _player->GetGroup()->SendUpdate(); + + ///- Broadcast a logout message to the player's friends + sSocialMgr.SendFriendStatus(_player, FRIEND_OFFLINE, _player->GetGUIDLow(), "", true); + + ///- Delete the player object + _player->CleanupsBeforeDelete(); // do some cleanup before deleting to prevent crash at crossreferences to already deleted data + + delete _player; + _player = NULL; + + ///- Send the 'logout complete' packet to the client + WorldPacket data( SMSG_LOGOUT_COMPLETE, 0 ); + SendPacket( &data ); + + ///- Since each account can only have one online character at any given time, ensure all characters for active account are marked as offline + //No SQL injection as AccountId is uint32 + CharacterDatabase.PExecute("UPDATE characters SET online = 0 WHERE account = '%u'", GetAccountId()); + sLog.outDebug( "SESSION: Sent SMSG_LOGOUT_COMPLETE Message" ); + } + + m_playerLogout = false; + m_playerRecentlyLogout = true; + LogoutRequest(0); +} + +/// Kick a player out of the World +void WorldSession::KickPlayer() +{ + if(!_socket) + return; + + // player will be logout and session will removed in next update tick + _socket->CloseSocket(); + _socket = NULL; +} + +/// Cancel channeling handler + +void WorldSession::SendAreaTriggerMessage(const char* Text, ...) +{ + va_list ap; + char szStr [1024]; + szStr[0] = '\0'; + + va_start(ap, Text); + vsnprintf( szStr, 1024, Text, ap ); + va_end(ap); + + uint32 length = strlen(szStr)+1; + WorldPacket data(SMSG_AREA_TRIGGER_MESSAGE, 4+length); + data << length; + data << szStr; + SendPacket(&data); +} + +void WorldSession::SendNotification(const char *format,...) +{ + if(format) + { + va_list ap; + char szStr [1024]; + szStr[0] = '\0'; + va_start(ap, format); + vsnprintf( szStr, 1024, format, ap ); + va_end(ap); + + WorldPacket data(SMSG_NOTIFICATION, (strlen(szStr)+1)); + data << szStr; + SendPacket(&data); + } +} + +const char * WorldSession::GetMangosString( int32 entry ) +{ + return objmgr.GetMangosString(entry,GetSessionDbLocaleIndex()); +} + +void WorldSession::Handle_NULL( WorldPacket& recvPacket ) +{ + sLog.outError( "SESSION: received unhandled opcode %s (0x%.4X)", + LookupOpcodeName(recvPacket.GetOpcode()), + recvPacket.GetOpcode()); +} + +void WorldSession::Handle_EarlyProccess( WorldPacket& recvPacket ) +{ + sLog.outError( "SESSION: received opcode %s (0x%.4X) that must be proccessed in WorldSocket::OnRead", + LookupOpcodeName(recvPacket.GetOpcode()), + recvPacket.GetOpcode()); +} + +void WorldSession::Handle_ServerSide( WorldPacket& recvPacket ) +{ + sLog.outError( "SESSION: received sever-side opcode %s (0x%.4X)", + LookupOpcodeName(recvPacket.GetOpcode()), + recvPacket.GetOpcode()); +} + +void WorldSession::Handle_Depricated( WorldPacket& recvPacket ) +{ + sLog.outError( "SESSION: received depricated opcode %s (0x%.4X)", + LookupOpcodeName(recvPacket.GetOpcode()), + recvPacket.GetOpcode()); +} diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h new file mode 100644 index 00000000000..05df0afe3a8 --- /dev/null +++ b/src/game/WorldSession.h @@ -0,0 +1,638 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/// \addtogroup u2w +/// @{ +/// \file + +#ifndef __WORLDSESSION_H +#define __WORLDSESSION_H + +#include "Common.h" + +class MailItemsInfo; +struct ItemPrototype; +struct AuctionEntry; + +class Creature; +class Item; +class Object; +class Player; +class Unit; +class WorldPacket; +class WorldSocket; +class WorldSession; +class QueryResult; +class LoginQueryHolder; +class CharacterHandler; + +#define CHECK_PACKET_SIZE(P,S) if((P).size() < (S)) return SizeError((P),(S)); + +enum PartyOperation +{ + PARTY_OP_INVITE = 0, + PARTY_OP_LEAVE = 2 +}; + +enum PartyResult +{ + PARTY_RESULT_OK = 0, + PARTY_RESULT_CANT_FIND_TARGET = 1, + PARTY_RESULT_NOT_IN_YOUR_PARTY = 2, + PARTY_RESULT_NOT_IN_YOUR_INSTANCE = 3, + PARTY_RESULT_PARTY_FULL = 4, + PARTY_RESULT_ALREADY_IN_GROUP = 5, + PARTY_RESULT_YOU_NOT_IN_GROUP = 6, + PARTY_RESULT_YOU_NOT_LEADER = 7, + PARTY_RESULT_TARGET_UNFRIENDLY = 8, + PARTY_RESULT_TARGET_IGNORE_YOU = 9, + PARTY_RESULT_INVITE_RESTRICTED = 13 +}; + +/// Player session in the World +class MANGOS_DLL_SPEC WorldSession +{ + friend class CharacterHandler; + public: + WorldSession(uint32 id, WorldSocket *sock, uint32 sec, bool tbc, time_t mute_time, LocaleConstant locale); + ~WorldSession(); + + bool PlayerLoading() const { return m_playerLoading; } + bool PlayerLogout() const { return m_playerLogout; } + + void SizeError(WorldPacket const& packet, uint32 size) const; + + void SendPacket(WorldPacket const* packet); + void SendNotification(const char *format,...) ATTR_PRINTF(2,3); + void SendLfgResult(uint32 type, uint32 entry, uint8 lfg_type); + void SendPartyResult(PartyOperation operation, std::string member, PartyResult res); + void SendAreaTriggerMessage(const char* Text, ...) ATTR_PRINTF(2,3); + + uint32 GetSecurity() const { return _security; } + uint32 GetAccountId() const { return _accountId; } + Player* GetPlayer() const { return _player; } + char const* GetPlayerName() const; + void SetSecurity(uint32 security) { _security = security; } + void SetSocket(WorldSocket *sock); + void SetPlayer(Player *plr) { _player = plr; } + bool IsTBC() const { return m_isTBC; } + + /// Is the user engaged in a log out process? + bool isLogingOut() const { return _logoutTime || m_playerLogout; } + + /// Engage the logout process for the user + void LogoutRequest(time_t requestTime) + { + _logoutTime = requestTime; + } + + /// Is logout cooldown expired? + bool ShouldLogOut(time_t currTime) const + { + return (_logoutTime > 0 && currTime >= _logoutTime + 20); + } + + void LogoutPlayer(bool Save); + void KickPlayer(); + + void QueuePacket(WorldPacket& packet); + bool Update(uint32 diff); + + //void SendTestCreatureQueryOpcode( uint32 entry, uint64 guid, uint32 testvalue ); + void SendNameQueryOpcode(Player* p); + void SendNameQueryOpcodeFromDB(uint64 guid); + static void SendNameQueryOpcodeFromDBCallBack(QueryResult *result, uint32 accountId); + + void SendTrainerList( uint64 guid ); + void SendTrainerList( uint64 guid,std::string strTitle ); + void SendListInventory( uint64 guid ); + void SendShowBank( uint64 guid ); + void SendTabardVendorActivate( uint64 guid ); + void SendSpiritResurrect(); + void SendBindPoint(Creature* npc); + void SendGMTicketGetTicket(uint32 status, char const* text); + + void SendAttackStop(Unit const* enemy); + + void SendBattlegGroundList( uint64 guid, uint32 bgTypeId ); + + void SendTradeStatus(uint32 status); + void SendCancelTrade(); + + void SendStablePet(uint64 guid ); + void SendPetitionQueryOpcode( uint64 petitionguid); + void SendUpdateTrade(); + + //pet + void SendPetNameQuery(uint64 guid, uint32 petnumber); + + //mail + //used with item_page table + bool SendItemInfo( uint32 itemid, WorldPacket data ); + static void SendReturnToSender(uint8 messageType, uint32 sender_acc, uint32 sender_guid, uint32 receiver_guid, std::string subject, uint32 itemTextId, MailItemsInfo *mi, uint32 money, uint32 COD, uint16 mailTemplateId = 0); + static void SendMailTo(Player* receiver, uint8 messageType, uint8 stationery, uint32 sender_guidlow_or_entry, uint32 received_guidlow, std::string subject, uint32 itemTextId, MailItemsInfo* mi, uint32 money, uint32 COD, uint32 checked, uint32 deliver_delay = 0, uint16 mailTemplateId = 0); + + //auction + void SendAuctionHello( uint64 guid, Creature * unit ); + void SendAuctionCommandResult( uint32 auctionId, uint32 Action, uint32 ErrorCode, uint32 bidError = 0); + void SendAuctionBidderNotification( uint32 location, uint32 auctionId, uint64 bidder, uint32 bidSum, uint32 diff, uint32 item_template); + void SendAuctionOwnerNotification( AuctionEntry * auction ); + bool SendAuctionInfo(WorldPacket & data, AuctionEntry* auction); + void SendAuctionOutbiddedMail( AuctionEntry * auction, uint32 newPrice ); + void SendAuctionCancelledToBidderMail( AuctionEntry* auction ); + + //Item Enchantment + void SendEnchantmentLog(uint64 Target, uint64 Caster,uint32 ItemID,uint32 SpellID); + void SendItemEnchantTimeUpdate(uint64 Playerguid, uint64 Itemguid,uint32 slot,uint32 Duration); + + //Taxi + void SendTaxiStatus( uint64 guid ); + void SendTaxiMenu( Creature* unit ); + void SendDoFlight( uint16 MountId, uint32 path, uint32 pathNode = 0 ); + bool SendLearnNewTaxiNode( Creature* unit ); + + // Guild/Arena Team + void SendGuildCommandResult(uint32 typecmd,std::string str,uint32 cmdresult); + void SendArenaTeamCommandResult(uint32 unk1, std::string str1, std::string str2, uint32 unk3); + void BuildArenaTeamEventPacket(WorldPacket *data, uint8 eventid, uint8 str_count, std::string str1, std::string str2, std::string str3); + void SendNotInArenaTeamPacket(uint8 type); + void SendPetitionShowList( uint64 guid ); + void SendSaveGuildEmblem( uint32 msg ); + + // Looking For Group + // TRUE values set by client sending CMSG_LFG_SET_AUTOJOIN and CMSG_LFM_CLEAR_AUTOFILL before player login + bool LookingForGroup_auto_join; + bool LookingForGroup_auto_add; + + void BuildPartyMemberStatsChangedPacket(Player *player, WorldPacket *data); + + void DoLootRelease( uint64 lguid ); + + // Account mute time + time_t m_muteTime; + + // Locales + LocaleConstant GetSessionDbcLocale() { return m_sessionDbcLocale; } + int GetSessionDbLocaleIndex() { return m_sessionDbLocaleIndex; } + const char *GetMangosString(int32 entry); + + uint32 GetLatency() const { return m_latency; } + void SetLatency(uint32 latency) { m_latency = latency; } + uint32 getDialogStatus(Player *pPlayer, Object* questgiver, uint32 defstatus); + + public: // opcodes handlers + + void Handle_NULL(WorldPacket& recvPacket); // not used + void Handle_EarlyProccess( WorldPacket& recvPacket);// just mark packets processed in WorldSocket::OnRead + void Handle_ServerSide(WorldPacket& recvPacket); // sever side only, can't be accepted from client + void Handle_Depricated(WorldPacket& recvPacket); // never used anymore by client + + void HandleCharEnumOpcode(WorldPacket& recvPacket); + void HandleCharDeleteOpcode(WorldPacket& recvPacket); + void HandleCharCreateOpcode(WorldPacket& recvPacket); + void HandlePlayerLoginOpcode(WorldPacket& recvPacket); + void HandleCharEnum(QueryResult * result); + void HandlePlayerLogin(LoginQueryHolder * holder); + + // played time + void HandlePlayedTime(WorldPacket& recvPacket); + + // new + void HandleMoveUnRootAck(WorldPacket& recvPacket); + void HandleMoveRootAck(WorldPacket& recvPacket); + void HandleLookingForGroup(WorldPacket& recvPacket); + + // new inspect + void HandleInspectOpcode(WorldPacket& recvPacket); + + // new party stats + void HandleInspectHonorStatsOpcode(WorldPacket& recvPacket); + + void HandleMoveWaterWalkAck(WorldPacket& recvPacket); + void HandleFeatherFallAck(WorldPacket &recv_data); + + void HandleMoveHoverAck( WorldPacket & recv_data ); + + void HandleMountSpecialAnimOpcode(WorldPacket &recvdata); + + // character view + void HandleToggleHelmOpcode(WorldPacket& recv_data); + void HandleToggleCloakOpcode(WorldPacket& recv_data); + + // repair + void HandleRepairItemOpcode(WorldPacket& recvPacket); + + // Knockback + void HandleMoveKnockBackAck(WorldPacket& recvPacket); + + void HandleMoveTeleportAck(WorldPacket& recvPacket); + void HandleForceSpeedChangeAck( WorldPacket & recv_data ); + + void HandlePingOpcode(WorldPacket& recvPacket); + void HandleAuthSessionOpcode(WorldPacket& recvPacket); + void HandleRepopRequestOpcode(WorldPacket& recvPacket); + void HandleAutostoreLootItemOpcode(WorldPacket& recvPacket); + void HandleLootMoneyOpcode(WorldPacket& recvPacket); + void HandleLootOpcode(WorldPacket& recvPacket); + void HandleLootReleaseOpcode(WorldPacket& recvPacket); + void HandleLootMasterGiveOpcode(WorldPacket& recvPacket); + void HandleWhoOpcode(WorldPacket& recvPacket); + void HandleLogoutRequestOpcode(WorldPacket& recvPacket); + void HandlePlayerLogoutOpcode(WorldPacket& recvPacket); + void HandleLogoutCancelOpcode(WorldPacket& recvPacket); + void HandleGMTicketGetTicketOpcode(WorldPacket& recvPacket); + void HandleGMTicketCreateOpcode(WorldPacket& recvPacket); + void HandleGMTicketSystemStatusOpcode(WorldPacket& recvPacket); + + void HandleGMTicketDeleteOpcode(WorldPacket& recvPacket); + void HandleGMTicketUpdateTextOpcode(WorldPacket& recvPacket); + + void HandleGMSurveySubmit(WorldPacket& recvPacket); + + void HandleTogglePvP(WorldPacket& recvPacket); + + void HandleZoneUpdateOpcode(WorldPacket& recvPacket); + void HandleSetTargetOpcode(WorldPacket& recvPacket); + void HandleSetSelectionOpcode(WorldPacket& recvPacket); + void HandleStandStateChangeOpcode(WorldPacket& recvPacket); + void HandleEmoteOpcode(WorldPacket& recvPacket); + void HandleFriendListOpcode(WorldPacket& recvPacket); + void HandleAddFriendOpcode(WorldPacket& recvPacket); + void HandleDelFriendOpcode(WorldPacket& recvPacket); + void HandleAddIgnoreOpcode(WorldPacket& recvPacket); + void HandleDelIgnoreOpcode(WorldPacket& recvPacket); + void HandleSetFriendNoteOpcode(WorldPacket& recvPacket); + void HandleBugOpcode(WorldPacket& recvPacket); + void HandleSetAmmoOpcode(WorldPacket& recvPacket); + void HandleItemNameQueryOpcode(WorldPacket& recvPacket); + + void HandleAreaTriggerOpcode(WorldPacket& recvPacket); + + void HandleSetFactionAtWar( WorldPacket & recv_data ); + void HandleSetFactionCheat( WorldPacket & recv_data ); + void HandleSetWatchedFactionIndexOpcode(WorldPacket & recv_data); + void HandleSetWatchedFactionInactiveOpcode(WorldPacket & recv_data); + + void HandleUpdateAccountData(WorldPacket& recvPacket); + void HandleRequestAccountData(WorldPacket& recvPacket); + void HandleSetActionButtonOpcode(WorldPacket& recvPacket); + + void HandleGameObjectUseOpcode(WorldPacket& recPacket); + void HandleMeetingStoneInfo(WorldPacket& recPacket); + + void HandleNameQueryOpcode(WorldPacket& recvPacket); + + void HandleQueryTimeOpcode(WorldPacket& recvPacket); + + void HandleCreatureQueryOpcode(WorldPacket& recvPacket); + + void HandleGameObjectQueryOpcode(WorldPacket& recvPacket); + + void HandleMoveWorldportAckOpcode(WorldPacket& recvPacket); + void HandleMoveWorldportAckOpcode(); // for server-side calls + + void HandleMovementOpcodes(WorldPacket& recvPacket); + void HandleSetActiveMoverOpcode(WorldPacket &recv_data); + void HandleMoveTimeSkippedOpcode(WorldPacket &recv_data); + + void HandleRequestRaidInfoOpcode( WorldPacket & recv_data ); + + void HandleBattlefieldStatusOpcode(WorldPacket &recv_data); + void HandleBattleMasterHelloOpcode(WorldPacket &recv_data); + + void HandleGroupInviteOpcode(WorldPacket& recvPacket); + //void HandleGroupCancelOpcode(WorldPacket& recvPacket); + void HandleGroupAcceptOpcode(WorldPacket& recvPacket); + void HandleGroupDeclineOpcode(WorldPacket& recvPacket); + void HandleGroupUninviteNameOpcode(WorldPacket& recvPacket); + void HandleGroupUninviteGuidOpcode(WorldPacket& recvPacket); + void HandleGroupUninvite(uint64 guid, std::string name); + void HandleGroupSetLeaderOpcode(WorldPacket& recvPacket); + void HandleGroupLeaveOpcode(WorldPacket& recvPacket); + void HandleGroupPassOnLootOpcode( WorldPacket &recv_data ); + void HandleLootMethodOpcode(WorldPacket& recvPacket); + void HandleLootRoll( WorldPacket &recv_data ); + void HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data ); + void HandleRaidIconTargetOpcode( WorldPacket & recv_data ); + void HandleRaidReadyCheckOpcode( WorldPacket & recv_data ); + void HandleRaidReadyCheckFinishOpcode( WorldPacket & recv_data ); + void HandleRaidConvertOpcode( WorldPacket & recv_data ); + void HandleGroupChangeSubGroupOpcode( WorldPacket & recv_data ); + void HandleGroupAssistantOpcode( WorldPacket & recv_data ); + void HandleGroupPromoteOpcode( WorldPacket & recv_data ); + + void HandlePetitionBuyOpcode(WorldPacket& recv_data); + void HandlePetitionShowSignOpcode(WorldPacket& recv_data); + void HandlePetitionQueryOpcode(WorldPacket& recv_data); + void HandlePetitionRenameOpcode(WorldPacket& recv_data); + void HandlePetitionSignOpcode(WorldPacket& recv_data); + void HandlePetitionDeclineOpcode(WorldPacket& recv_data); + void HandleOfferPetitionOpcode(WorldPacket& recv_data); + void HandleTurnInPetitionOpcode(WorldPacket& recv_data); + + void HandleGuildQueryOpcode(WorldPacket& recvPacket); + void HandleGuildCreateOpcode(WorldPacket& recvPacket); + void HandleGuildInviteOpcode(WorldPacket& recvPacket); + void HandleGuildRemoveOpcode(WorldPacket& recvPacket); + void HandleGuildAcceptOpcode(WorldPacket& recvPacket); + void HandleGuildDeclineOpcode(WorldPacket& recvPacket); + void HandleGuildInfoOpcode(WorldPacket& recvPacket); + void HandleGuildEventLogOpcode(WorldPacket& recvPacket); + void HandleGuildRosterOpcode(WorldPacket& recvPacket); + void HandleGuildPromoteOpcode(WorldPacket& recvPacket); + void HandleGuildDemoteOpcode(WorldPacket& recvPacket); + void HandleGuildLeaveOpcode(WorldPacket& recvPacket); + void HandleGuildDisbandOpcode(WorldPacket& recvPacket); + void HandleGuildLeaderOpcode(WorldPacket& recvPacket); + void HandleGuildMOTDOpcode(WorldPacket& recvPacket); + void HandleGuildSetPublicNoteOpcode(WorldPacket& recvPacket); + void HandleGuildSetOfficerNoteOpcode(WorldPacket& recvPacket); + void HandleGuildRankOpcode(WorldPacket& recvPacket); + void HandleGuildAddRankOpcode(WorldPacket& recvPacket); + void HandleGuildDelRankOpcode(WorldPacket& recvPacket); + void HandleGuildChangeInfoOpcode(WorldPacket& recvPacket); + void HandleGuildSaveEmblemOpcode(WorldPacket& recvPacket); + + void HandleTaxiNodeStatusQueryOpcode(WorldPacket& recvPacket); + void HandleTaxiQueryAvailableNodesOpcode(WorldPacket& recvPacket); + void HandleActivateTaxiOpcode(WorldPacket& recvPacket); + void HandleActivateTaxiFarOpcode(WorldPacket& recvPacket); + void HandleTaxiNextDestinationOpcode(WorldPacket& recvPacket); + + void HandleTabardVendorActivateOpcode(WorldPacket& recvPacket); + void HandleBankerActivateOpcode(WorldPacket& recvPacket); + void HandleBuyBankSlotOpcode(WorldPacket& recvPacket); + void HandleTrainerListOpcode(WorldPacket& recvPacket); + void HandleTrainerBuySpellOpcode(WorldPacket& recvPacket); + void HandlePetitionShowListOpcode(WorldPacket& recvPacket); + void HandleGossipHelloOpcode(WorldPacket& recvPacket); + void HandleGossipSelectOptionOpcode(WorldPacket& recvPacket); + void HandleSpiritHealerActivateOpcode(WorldPacket& recvPacket); + void HandleNpcTextQueryOpcode(WorldPacket& recvPacket); + void HandleBinderActivateOpcode(WorldPacket& recvPacket); + void HandleListStabledPetsOpcode(WorldPacket& recvPacket); + void HandleStablePet(WorldPacket& recvPacket); + void HandleUnstablePet(WorldPacket& recvPacket); + void HandleBuyStableSlot(WorldPacket& recvPacket); + void HandleStableRevivePet(WorldPacket& recvPacket); + void HandleStableSwapPet(WorldPacket& recvPacket); + + void HandleDuelAcceptedOpcode(WorldPacket& recvPacket); + void HandleDuelCancelledOpcode(WorldPacket& recvPacket); + + void HandleAcceptTradeOpcode(WorldPacket& recvPacket); + void HandleBeginTradeOpcode(WorldPacket& recvPacket); + void HandleBusyTradeOpcode(WorldPacket& recvPacket); + void HandleCancelTradeOpcode(WorldPacket& recvPacket); + void HandleClearTradeItemOpcode(WorldPacket& recvPacket); + void HandleIgnoreTradeOpcode(WorldPacket& recvPacket); + void HandleInitiateTradeOpcode(WorldPacket& recvPacket); + void HandleSetTradeGoldOpcode(WorldPacket& recvPacket); + void HandleSetTradeItemOpcode(WorldPacket& recvPacket); + void HandleUnacceptTradeOpcode(WorldPacket& recvPacket); + + void HandleAuctionHelloOpcode(WorldPacket& recvPacket); + void HandleAuctionListItems( WorldPacket & recv_data ); + void HandleAuctionListBidderItems( WorldPacket & recv_data ); + void HandleAuctionSellItem( WorldPacket & recv_data ); + void HandleAuctionRemoveItem( WorldPacket & recv_data ); + void HandleAuctionListOwnerItems( WorldPacket & recv_data ); + void HandleAuctionPlaceBid( WorldPacket & recv_data ); + + void HandleGetMail( WorldPacket & recv_data ); + void HandleSendMail( WorldPacket & recv_data ); + void HandleTakeMoney( WorldPacket & recv_data ); + void HandleTakeItem( WorldPacket & recv_data ); + void HandleMarkAsRead( WorldPacket & recv_data ); + void HandleReturnToSender( WorldPacket & recv_data ); + void HandleMailDelete( WorldPacket & recv_data ); + void HandleItemTextQuery( WorldPacket & recv_data); + void HandleMailCreateTextItem(WorldPacket & recv_data ); + void HandleMsgQueryNextMailtime(WorldPacket & recv_data ); + void HandleCancelChanneling(WorldPacket & recv_data ); + + void SendItemPageInfo( ItemPrototype *itemProto ); + void HandleSplitItemOpcode(WorldPacket& recvPacket); + void HandleSwapInvItemOpcode(WorldPacket& recvPacket); + void HandleDestroyItemOpcode(WorldPacket& recvPacket); + void HandleAutoEquipItemOpcode(WorldPacket& recvPacket); + void HandleItemQuerySingleOpcode(WorldPacket& recvPacket); + void HandleSellItemOpcode(WorldPacket& recvPacket); + void HandleBuyItemInSlotOpcode(WorldPacket& recvPacket); + void HandleBuyItemOpcode(WorldPacket& recvPacket); + void HandleListInventoryOpcode(WorldPacket& recvPacket); + void HandleAutoStoreBagItemOpcode(WorldPacket& recvPacket); + void HandleReadItem(WorldPacket& recvPacket); + void HandleAutoEquipItemSlotOpcode(WorldPacket & recvPacket); + void HandleSwapItem( WorldPacket & recvPacket); + void HandleBuybackItem(WorldPacket & recvPacket); + void HandleAutoBankItemOpcode(WorldPacket& recvPacket); + void HandleAutoStoreBankItemOpcode(WorldPacket& recvPacket); + void HandleWrapItemOpcode(WorldPacket& recvPacket); + + void HandleAttackSwingOpcode(WorldPacket& recvPacket); + void HandleAttackStopOpcode(WorldPacket& recvPacket); + void HandleSetSheathedOpcode(WorldPacket& recvPacket); + + void HandleUseItemOpcode(WorldPacket& recvPacket); + void HandleOpenItemOpcode(WorldPacket& recvPacket); + void HandleCastSpellOpcode(WorldPacket& recvPacket); + void HandleCancelCastOpcode(WorldPacket& recvPacket); + void HandleCancelAuraOpcode(WorldPacket& recvPacket); + void HandleCancelGrowthAuraOpcode(WorldPacket& recvPacket); + void HandleCancelAutoRepeatSpellOpcode(WorldPacket& recvPacket); + + void HandleLearnTalentOpcode(WorldPacket& recvPacket); + void HandleTalentWipeOpcode(WorldPacket& recvPacket); + void HandleUnlearnSkillOpcode(WorldPacket& recvPacket); + + void HandleQuestgiverStatusQueryOpcode(WorldPacket& recvPacket); + void HandleQuestgiverStatusQueryMultipleOpcode(WorldPacket& recvPacket); + void HandleQuestgiverHelloOpcode(WorldPacket& recvPacket); + void HandleQuestgiverAcceptQuestOpcode(WorldPacket& recvPacket); + void HandleQuestgiverQuestQueryOpcode(WorldPacket& recvPacket); + void HandleQuestgiverChooseRewardOpcode(WorldPacket& recvPacket); + void HandleQuestgiverRequestRewardOpcode(WorldPacket& recvPacket); + void HandleQuestQueryOpcode(WorldPacket& recvPacket); + void HandleQuestgiverCancel(WorldPacket& recv_data ); + void HandleQuestLogSwapQuest(WorldPacket& recv_data ); + void HandleQuestLogRemoveQuest(WorldPacket& recv_data); + void HandleQuestConfirmAccept(WorldPacket& recv_data); + void HandleQuestComplete(WorldPacket& recv_data); + void HandleQuestAutoLaunch(WorldPacket& recvPacket); + void HandleQuestPushToParty(WorldPacket& recvPacket); + void HandleQuestPushResult(WorldPacket& recvPacket); + + void HandleMessagechatOpcode(WorldPacket& recvPacket); + void HandleTextEmoteOpcode(WorldPacket& recvPacket); + void HandleChatIgnoredOpcode(WorldPacket& recvPacket); + + void HandleCorpseReclaimOpcode( WorldPacket& recvPacket ); + void HandleCorpseQueryOpcode( WorldPacket& recvPacket ); + void HandleResurrectResponseOpcode(WorldPacket& recvPacket); + void HandleSummonResponseOpcode(WorldPacket& recv_data); + + void HandleChannelJoin(WorldPacket& recvPacket); + void HandleChannelLeave(WorldPacket& recvPacket); + void HandleChannelList(WorldPacket& recvPacket); + void HandleChannelPassword(WorldPacket& recvPacket); + void HandleChannelSetOwner(WorldPacket& recvPacket); + void HandleChannelOwner(WorldPacket& recvPacket); + void HandleChannelModerator(WorldPacket& recvPacket); + void HandleChannelUnmoderator(WorldPacket& recvPacket); + void HandleChannelMute(WorldPacket& recvPacket); + void HandleChannelUnmute(WorldPacket& recvPacket); + void HandleChannelInvite(WorldPacket& recvPacket); + void HandleChannelKick(WorldPacket& recvPacket); + void HandleChannelBan(WorldPacket& recvPacket); + void HandleChannelUnban(WorldPacket& recvPacket); + void HandleChannelAnnounce(WorldPacket& recvPacket); + void HandleChannelModerate(WorldPacket& recvPacket); + void HandleChannelRosterQuery(WorldPacket& recvPacket); + void HandleChannelInfoQuery(WorldPacket& recvPacket); + void HandleChannelJoinNotify(WorldPacket& recvPacket); + + void HandleCompleteCinema(WorldPacket& recvPacket); + void HandleNextCinematicCamera(WorldPacket& recvPacket); + + void HandlePageQuerySkippedOpcode(WorldPacket& recvPacket); + void HandlePageQueryOpcode(WorldPacket& recvPacket); + + void HandleTutorialFlag ( WorldPacket & recv_data ); + void HandleTutorialClear( WorldPacket & recv_data ); + void HandleTutorialReset( WorldPacket & recv_data ); + + //Pet + void HandlePetAction( WorldPacket & recv_data ); + void HandlePetNameQuery( WorldPacket & recv_data ); + void HandlePetSetAction( WorldPacket & recv_data ); + void HandlePetAbandon( WorldPacket & recv_data ); + void HandlePetRename( WorldPacket & recv_data ); + void HandlePetCancelAuraOpcode( WorldPacket& recvPacket ); + void HandlePetUnlearnOpcode( WorldPacket& recvPacket ); + void HandlePetSpellAutocastOpcode( WorldPacket& recvPacket ); + void HandleAddDynamicTargetObsoleteOpcode( WorldPacket& recvPacket ); + + void HandleSetActionBar(WorldPacket& recv_data); + + void HandleChangePlayerNameOpcode(WorldPacket& recv_data); + void HandleDeclinedPlayerNameOpcode(WorldPacket& recv_data); + + void HandleTotemDestroy(WorldPacket& recv_data); + + //BattleGround + void HandleBattleGroundHelloOpcode(WorldPacket &recv_data); + void HandleBattleGroundJoinOpcode(WorldPacket &recv_data); + void HandleBattleGroundPlayerPositionsOpcode(WorldPacket& recv_data); + void HandleBattleGroundPVPlogdataOpcode( WorldPacket &recv_data ); + void HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data ); + void HandleBattleGroundListOpcode( WorldPacket &recv_data ); + void HandleBattleGroundLeaveOpcode( WorldPacket &recv_data ); + void HandleBattleGroundArenaJoin( WorldPacket &recv_data ); + void HandleBattleGroundReportAFK( WorldPacket &recv_data ); + + void HandleWardenDataOpcode(WorldPacket& recv_data); + void HandleWorldTeleportOpcode(WorldPacket& recv_data); + void HandleMinimapPingOpcode(WorldPacket& recv_data); + void HandleRandomRollOpcode(WorldPacket& recv_data); + void HandleFarSightOpcode(WorldPacket& recv_data); + void HandleSetLfgOpcode(WorldPacket& recv_data); + void HandleDungeonDifficultyOpcode(WorldPacket& recv_data); + void HandleMoveFlyModeChangeAckOpcode(WorldPacket& recv_data); + void HandleLfgAutoJoinOpcode(WorldPacket& recv_data); + void HandleLfgCancelAutoJoinOpcode(WorldPacket& recv_data); + void HandleLfmAutoAddMembersOpcode(WorldPacket& recv_data); + void HandleLfmCancelAutoAddmembersOpcode(WorldPacket& recv_data); + void HandleLfgClearOpcode(WorldPacket& recv_data); + void HandleLfmSetNoneOpcode(WorldPacket& recv_data); + void HandleLfmSetOpcode(WorldPacket& recv_data); + void HandleLfgSetCommentOpcode(WorldPacket& recv_data); + void HandleNewUnknownOpcode(WorldPacket& recv_data); + void HandleChooseTitleOpcode(WorldPacket& recv_data); + void HandleRealmStateRequestOpcode(WorldPacket& recv_data); + void HandleAllowMoveAckOpcode(WorldPacket& recv_data); + void HandleWhoisOpcode(WorldPacket& recv_data); + void HandleResetInstancesOpcode(WorldPacket& recv_data); + + // Arena Team + void HandleInspectArenaStatsOpcode(WorldPacket& recv_data); + void HandleArenaTeamQueryOpcode(WorldPacket& recv_data); + void HandleArenaTeamRosterOpcode(WorldPacket& recv_data); + void HandleArenaTeamAddMemberOpcode(WorldPacket& recv_data); + void HandleArenaTeamInviteAcceptOpcode(WorldPacket& recv_data); + void HandleArenaTeamInviteDeclineOpcode(WorldPacket& recv_data); + void HandleArenaTeamLeaveOpcode(WorldPacket& recv_data); + void HandleArenaTeamRemoveFromTeamOpcode(WorldPacket& recv_data); + void HandleArenaTeamDisbandOpcode(WorldPacket& recv_data); + void HandleArenaTeamPromoteToCaptainOpcode(WorldPacket& recv_data); + + void HandleAreaSpiritHealerQueryOpcode(WorldPacket& recv_data); + void HandleAreaSpiritHealerQueueOpcode(WorldPacket& recv_data); + void HandleDismountOpcode(WorldPacket& recv_data); + void HandleSelfResOpcode(WorldPacket& recv_data); + void HandleReportSpamOpcode(WorldPacket& recv_data); + void HandleRequestPetInfoOpcode(WorldPacket& recv_data); + + // Socket gem + void HandleSocketOpcode(WorldPacket& recv_data); + + void HandleCancelTempItemEnchantmentOpcode(WorldPacket& recv_data); + + void HandleChannelEnableVoiceOpcode(WorldPacket & recv_data); + void HandleVoiceSettingsOpcode(WorldPacket& recv_data); + void HandleChannelVoiceChatQuery(WorldPacket& recv_data); + void HandleSetTaxiBenchmarkOpcode(WorldPacket& recv_data); + + // Guild Bank + void HandleGuildBankGetRights(WorldPacket& recv_data); + void HandleGuildBankGetMoneyAmount(WorldPacket& recv_data); + void HandleGuildBankQuery(WorldPacket& recv_data); + void HandleGuildBankTabColon(WorldPacket& recv_data); + void HandleGuildBankLog(WorldPacket& recv_data); + void HandleGuildBankDeposit(WorldPacket& recv_data); + void HandleGuildBankWithdraw(WorldPacket& recv_data); + void HandleGuildBankDepositItem(WorldPacket& recv_data); + void HandleGuildBankModifyTab(WorldPacket& recv_data); + void HandleGuildBankBuyTab(WorldPacket& recv_data); + void HandleGuildBankTabText(WorldPacket& recv_data); + void HandleGuildBankSetTabText(WorldPacket& recv_data); + private: + // private trade methods + void moveItems(Item* myItems[], Item* hisItems[]); + + // logging helper + void logUnexpectedOpcode(WorldPacket *packet, const char * reason); + Player *_player; + WorldSocket *_socket; + + uint32 _security; + uint32 _accountId; + bool m_isTBC; + + time_t _logoutTime; + bool m_playerLoading; // code processed in LoginPlayer + bool m_playerLogout; // code processed in LogoutPlayer + bool m_playerRecentlyLogout; + LocaleConstant m_sessionDbcLocale; + int m_sessionDbLocaleIndex; + uint32 m_latency; + + ZThread::LockedQueue _recvQueue; +}; +#endif +/// @} diff --git a/src/game/WorldSocket.cpp b/src/game/WorldSocket.cpp new file mode 100644 index 00000000000..d52c0962862 --- /dev/null +++ b/src/game/WorldSocket.cpp @@ -0,0 +1,664 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** \file + \ingroup u2w +*/ + +#include "Common.h" +#include "Log.h" +#include "Opcodes.h" +#include "Database/DatabaseEnv.h" +#include "Auth/Sha1.h" +#include "WorldPacket.h" +#include "WorldSocket.h" +#include "WorldSession.h" +#include "World.h" +#include "WorldSocketMgr.h" +#include "Policies/SingletonImp.h" +#include "WorldLog.h" +#include "AddonHandler.h" +#include "sockets/Utility.h" +#include "Util.h" + +// GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push,N), also any gcc version not support it at some platform +#if defined( __GNUC__ ) +#pragma pack(1) +#else +#pragma pack(push,1) +#endif + +/// Client Packet Header +struct ClientPktHeader +{ + uint16 size; + uint32 cmd; +}; + +/// Server Packet Header +struct ServerPktHeader +{ + uint16 size; + uint16 cmd; +}; + +// GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some platform +#if defined( __GNUC__ ) +#pragma pack() +#else +#pragma pack(pop) +#endif + +#define SOCKET_CHECK_PACKET_SIZE(P,S) if((P).size() < (S)) return SizeError((P),(S)); + +/// WorldSocket construction and initialization. +WorldSocket::WorldSocket(ISocketHandler &sh): TcpSocket(sh), _cmd(0), _remaining(0), _session(NULL) +{ + _seed = static_cast(rand32()); + m_LastPingMSTime = 0; // first time it will counted as overspeed maybe, but this is not important + m_OverSpeedPings = 0; + + if (sWorld.getConfig(CONFIG_TCP_NO_DELAY)) + SetTcpNodelay(true); +} + +/// WorldSocket destructor +WorldSocket::~WorldSocket() +{ + if(_session) + _session->SetSocket(0); + + WorldPacket *packet; + + ///- Go through the to-be-sent queue and delete remaining packets + while(!_sendQueue.empty()) + { + packet = _sendQueue.next(); + delete packet; + } +} + +/// Copy the packet to the to-be-sent queue +void WorldSocket::SendPacket(WorldPacket const* packet) +{ + WorldPacket *pck = new WorldPacket(*packet); + ASSERT(pck); + _sendQueue.add(pck); +} + +/// On client connection +void WorldSocket::OnAccept() +{ + ///- Add the current socket to the list of sockets to be managed (WorldSocketMgr) + sWorldSocketMgr.AddSocket(this); + Utility::ResolveLocal(); + + ///- Send a AUTH_CHALLENGE packet + WorldPacket packet( SMSG_AUTH_CHALLENGE, 4 ); + packet << _seed; + + SendPacket(&packet); +} + +/// Read the client transmitted data +void WorldSocket::OnRead() +{ + TcpSocket::OnRead(); + + while(1) + { + ///- Read the packet header and decipher it (if needed) + if (!_remaining) + { + if (ibuf.GetLength() < 6) + break; + + ClientPktHeader hdr; + + ibuf.Read((char *)&hdr, 6); + _crypt.DecryptRecv((uint8 *)&hdr, 6); + + _remaining = ntohs(hdr.size) - 4; + _cmd = hdr.cmd; + } + + if (ibuf.GetLength() < _remaining) + break; + + ///- Read the remaining of the packet + WorldPacket packet((uint16)_cmd, _remaining); + + packet.resize(_remaining); + if(_remaining) ibuf.Read((char*)packet.contents(), _remaining); + _remaining = 0; + + ///- If log of world packets is enable, log the incoming packet + if( sWorldLog.LogWorld() ) + { + sWorldLog.Log("CLIENT:\nSOCKET: %u\nLENGTH: %u\nOPCODE: %s (0x%.4X)\nDATA:\n", + (uint32)GetSocket(), + packet.size(), + LookupOpcodeName(packet.GetOpcode()), + packet.GetOpcode()); + + uint32 p = 0; + while (p < packet.size()) + { + for (uint32 j = 0; j < 16 && p < packet.size(); j++) + sWorldLog.Log("%.2X ", packet[p++]); + sWorldLog.Log("\n"); + } + sWorldLog.Log("\n\n"); + } + + ///- If the packet is PING, KEEP_ALIVE or AUTH_SESSION, handle immediately + switch (_cmd) + { + case CMSG_KEEP_ALIVE: + break; // just ignore, network connectivity timeout preventing + case CMSG_PING: + { + _HandlePing(packet); + break; + } + case CMSG_AUTH_SESSION: + { + _HandleAuthSession(packet); + break; + } + default: + { + ///- Else, put it in the world session queue for this user (need to be already authenticated) + if (_session) + _session->QueuePacket(packet); + else + sLog.outDetail("Received out of place packet with cmdid 0x%.4X", _cmd); + break; + } + } + } +} + +/// On socket closing +void WorldSocket::CloseSocket() +{ + ///- Set CloseAndDelete flag for TcpSocket class + SetCloseAndDelete(true); + + ///- Set _session to NULL. Prevent crashes + _session = NULL; +} + +/// On socket deleting +void WorldSocket::OnDelete() +{ + ///- Stop sending remaining data through this socket + if (_session) + { + _session->SetSocket(NULL); + // Session deleted from World session list at socket==0, This is only back reference from socket to session. + _session = NULL; + } + + ///- Remove the socket from the WorldSocketMgr list + sWorldSocketMgr.RemoveSocket(this); + + ///- Removes socket from player queue + sWorld.RemoveQueuedPlayer(this); +} + +/// Handle the client authentication packet +void WorldSocket::_HandleAuthSession(WorldPacket& recvPacket) +{ + uint8 digest[20]; + uint32 clientSeed; + uint32 unk2; + uint32 BuiltNumberClient; + uint32 id, security; + bool tbc = false; + std::string account; + Sha1Hash sha1; + BigNumber v, s, g, N, x, I; + WorldPacket packet, SendAddonPacked; + + BigNumber K; + + SOCKET_CHECK_PACKET_SIZE(recvPacket,4+4+1+4+20); + + ///- Read the content of the packet + recvPacket >> BuiltNumberClient; // for now no use + recvPacket >> unk2; + recvPacket >> account; + + // recheck size + SOCKET_CHECK_PACKET_SIZE(recvPacket,4+4+(account.size()+1)+4+20); + + recvPacket >> clientSeed; + recvPacket.read(digest, 20); + + sLog.outDebug("Auth: client %u, unk2 %u, account %s, clientseed %u", BuiltNumberClient, unk2, account.c_str(), clientSeed); + + ///- Normalize account name + //utf8ToUpperOnlyLatin(account); -- client already send account in expected form + + ///- Get the account information from the realmd database + std::string safe_account = account; // Duplicate, else will screw the SHA hash verification below + loginDatabase.escape_string(safe_account); + //No SQL injection, username escaped. + // 0 1 2 3 4 5 6 7 8 9 10 + QueryResult *result = loginDatabase.PQuery("SELECT id, gmlevel, sessionkey, last_ip, locked, sha_pass_hash, v, s, tbc, mutetime, locale FROM account WHERE username = '%s'", safe_account.c_str()); + + ///- Stop if the account is not found + if ( !result ) + { + packet.Initialize( SMSG_AUTH_RESPONSE, 1 ); + packet << uint8( AUTH_UNKNOWN_ACCOUNT ); + SendPacket( &packet ); + sLog.outDetail( "SOCKET: Sent Auth Response (unknown account)." ); + return; + } + + Field* fields = result->Fetch(); + + tbc = fields[8].GetUInt8() && sWorld.getConfig(CONFIG_EXPANSION) > 0; + + N.SetHexStr("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7"); + g.SetDword(7); + I.SetHexStr(fields[5].GetString()); + + //In case of leading zeros in the I hash, restore them + uint8 mDigest[SHA_DIGEST_LENGTH]; + memset(mDigest,0,SHA_DIGEST_LENGTH); + if (I.GetNumBytes() <= SHA_DIGEST_LENGTH) + memcpy(mDigest,I.AsByteArray(),I.GetNumBytes()); + + std::reverse(mDigest,mDigest+SHA_DIGEST_LENGTH); + + s.SetHexStr(fields[7].GetString()); + sha1.UpdateData(s.AsByteArray(), s.GetNumBytes()); + sha1.UpdateData(mDigest, SHA_DIGEST_LENGTH); + sha1.Finalize(); + x.SetBinary(sha1.GetDigest(), sha1.GetLength()); + v = g.ModExp(x, N); + + const char* sStr = s.AsHexStr(); //Must be freed by OPENSSL_free() + const char* vStr = v.AsHexStr(); //Must be freed by OPENSSL_free() + const char* vold = fields[6].GetString(); + sLog.outDebug("SOCKET: (s,v) check s: %s v_old: %s v_new: %s", sStr, vold, vStr ); + loginDatabase.PExecute("UPDATE account SET v = '0', s = '0' WHERE username = '%s'", safe_account.c_str()); + if ( !vold || strcmp( vStr, vold ) ) + { + packet.Initialize( SMSG_AUTH_RESPONSE, 1 ); + packet << uint8( AUTH_UNKNOWN_ACCOUNT ); + SendPacket( &packet ); + sLog.outDetail( "SOCKET: User not logged."); + delete result; + OPENSSL_free((void*)sStr); + OPENSSL_free((void*)vStr); + return; + } + OPENSSL_free((void*)sStr); + OPENSSL_free((void*)vStr); + + ///- Re-check ip locking (same check as in realmd). + if(fields[4].GetUInt8() == 1) // if ip is locked + { + if ( strcmp(fields[3].GetString(),GetRemoteAddress().c_str()) ) + { + packet.Initialize( SMSG_AUTH_RESPONSE, 1 ); + packet << uint8( AUTH_FAILED ); + SendPacket( &packet ); + + sLog.outDetail( "SOCKET: Sent Auth Response (Account IP differs)." ); + delete result; + return; + } + } + + id = fields[0].GetUInt32(); + security = fields[1].GetUInt16(); + K.SetHexStr(fields[2].GetString()); + time_t mutetime = time_t(fields[9].GetUInt64()); + + LocaleConstant locale = LocaleConstant(fields[10].GetUInt8()); + if (locale>=MAX_LOCALE) + locale=LOCALE_enUS; + + delete result; + + ///- Re-check account ban (same check as in realmd) /// TO DO: why on earth do 2 checks for same thing? + QueryResult *banresult = loginDatabase.PQuery("SELECT bandate,unbandate FROM account_banned WHERE id = '%u' AND active = 1", id); + if(banresult) // if account banned + { + packet.Initialize( SMSG_AUTH_RESPONSE, 1 ); + packet << uint8( AUTH_BANNED ); + SendPacket( &packet ); + + sLog.outDetail( "SOCKET: Sent Auth Response (Account banned)." ); + delete banresult; + return; + } + + ///- Check locked state for server + AccountTypes allowedAccountType = sWorld.GetPlayerSecurityLimit(); + if( allowedAccountType > SEC_PLAYER && security < allowedAccountType) + { + WorldPacket Packet(SMSG_AUTH_RESPONSE, 1); + Packet << uint8(AUTH_UNAVAILABLE); + SendPacket(&Packet); + return; + } + + ///- kick already loaded player with same account (if any) and remove session + ///- if player is in loading and want to load again, return + if(!sWorld.RemoveSession(id)) + { + return; + } + + ///- Check that Key and account name are the same on client and server + Sha1Hash sha; + + uint32 t = 0; + uint32 seed = _seed; + + sha.UpdateData(account); + sha.UpdateData((uint8 *)&t, 4); + sha.UpdateData((uint8 *)&clientSeed, 4); + sha.UpdateData((uint8 *)&seed, 4); + sha.UpdateBigNumbers(&K, NULL); + sha.Finalize(); + + if (memcmp(sha.GetDigest(), digest, 20)) + { + packet.Initialize( SMSG_AUTH_RESPONSE, 1 ); + packet << uint8( AUTH_FAILED ); + SendPacket( &packet ); + + sLog.outDetail( "SOCKET: Sent Auth Response (authentication failed)." ); + return; + } + + ///- Initialize the encryption with the Key + _crypt.SetKey(&K); + _crypt.Init(); + + ///- Send 'Auth is ok' + packet.Initialize( SMSG_AUTH_RESPONSE, 1+4+1+4+1 ); + packet << uint8( AUTH_OK ); + packet << uint32(0); // unknown random value... + packet << uint8(0); // can be 0 and 2 + packet << uint32(0); // const 0 + packet << uint8(tbc ? 1 : 0); // 0 - normal, 1 - TBC, must be set in database manually for each account + SendPacket(&packet); + + ///- Create a new WorldSession for the player and add it to the World + _session = new WorldSession(id, this,security,tbc,mutetime,locale); + sWorld.AddSession(_session); + + if(sLog.IsOutDebug()) // optimize disabled debug output + { + sLog.outDebug( "SOCKET: Client '%s' authenticated successfully.", account.c_str() ); + sLog.outDebug( "Account: '%s' Logged in from IP %s.", account.c_str(), GetRemoteAddress().c_str()); + } + + ///- Update the last_ip in the database + //No SQL injection, username escaped. + std::string address = GetRemoteAddress(); + loginDatabase.escape_string(address); + loginDatabase.PExecute("UPDATE account SET last_ip = '%s' WHERE username = '%s'",address.c_str(), safe_account.c_str()); + + // do small delay (10ms) at accepting successful authed connection to prevent dropping packets by client + // don't must harm anyone (let login ~100 accounts in 1 sec ;) ) + #ifdef WIN32 + Sleep(10); + #else + ZThread::Thread::sleep(10); + #endif + + ///- Check that we do not exceed the maximum number of online players in the realm + uint32 Sessions = sWorld.GetActiveAndQueuedSessionCount(); + uint32 pLimit = sWorld.GetPlayerAmountLimit(); + uint32 QueueSize = sWorld.GetQueueSize(); //number of players in the queue + bool inQueue = false; + --Sessions; //so we don't count the user trying to login as a session and queue the socket that we are using + + if( pLimit > 0 && Sessions >= pLimit && security == SEC_PLAYER ) + { + sWorld.AddQueuedPlayer(this); + SendAuthWaitQue(sWorld.GetQueuePos(this)); + sWorld.UpdateMaxSessionCounters(); + sLog.outDetail( "PlayerQueue: %s is in Queue Position (%u).",safe_account.c_str(),++QueueSize); + inQueue = true; + } + + ///- Create and send the Addon packet + if(sAddOnHandler.BuildAddonPacket(&recvPacket, &SendAddonPacked)) + SendPacket(&SendAddonPacked); + + if(inQueue) + return; + + sWorld.UpdateMaxSessionCounters(); + + // Updates the population + if (pLimit > 0) + { + float popu = sWorld.GetActiveSessionCount(); //updated number of users on the server + popu /= pLimit; + popu *= 2; + loginDatabase.PExecute("UPDATE realmlist SET population = '%f' WHERE id = '%d'",popu,realmID); + sLog.outDetail( "Server Population (%f).",popu); + } + + return; +} + +/// Handle the Ping packet +void WorldSocket::_HandlePing(WorldPacket& recvPacket) +{ + uint32 ping; + uint32 latency; + + CHECK_PACKET_SIZE(recvPacket,8); + + ///- Get the ping packet content + recvPacket >> ping; + recvPacket >> latency; + + if (_session ) + _session->SetLatency(latency); + + ///- check ping speed for players + if(_session && _session->GetSecurity() == SEC_PLAYER) + { + uint32 cur_mstime = getMSTime(); + + // can overflow and start from 0 + uint32 diff_mstime = getMSTimeDiff(m_LastPingMSTime,cur_mstime); + m_LastPingMSTime = cur_mstime; + if(diff_mstime < 27000) // should be 30000 (=30 secs), add little tolerance + { + ++m_OverSpeedPings; + + uint32 max_count = sWorld.getConfig(CONFIG_MAX_OVERSPEED_PINGS); + if(max_count && m_OverSpeedPings > max_count) + { + sLog.outBasic("Player %s from account id %u kicked for overspeed ping packets from client (non-playable connection lags or cheating) ",_session->GetPlayerName(),_session->GetAccountId()); + _session->KickPlayer(); + return; + } + } + else + m_OverSpeedPings = 0; + + } + + ///- And put the pong answer in the to-be-sent queue + WorldPacket packet( SMSG_PONG, 4 ); + packet << ping; + SendPacket(&packet); + + return; +} + +/// Handle the update order for the socket +void WorldSocket::SendSinglePacket() +{ + WorldPacket *packet; + ServerPktHeader hdr; + + ///- If we have packet to send + if (!_sendQueue.empty()) + { + packet = _sendQueue.next(); + + hdr.size = ntohs((uint16)packet->size() + 2); + hdr.cmd = packet->GetOpcode(); + + if( sWorldLog.LogWorld() ) + { + sWorldLog.Log("SERVER:\nSOCKET: %u\nLENGTH: %u\nOPCODE: %s (0x%.4X)\nDATA:\n", + (uint32)GetSocket(), + packet->size(), + LookupOpcodeName(packet->GetOpcode()), + packet->GetOpcode()); + + uint32 p = 0; + while (p < packet->size()) + { + for (uint32 j = 0; j < 16 && p < packet->size(); j++) + sWorldLog.Log("%.2X ", (*packet)[p++]); + + sWorldLog.Log("\n"); + } + + sWorldLog.Log("\n\n"); + } + + ///- Encrypt (if needed) the header + _crypt.EncryptSend((uint8*)&hdr, 4); + + ///- Send the header and body to the client + TcpSocket::SendBuf((char*)&hdr, 4); + if(!packet->empty()) TcpSocket::SendBuf((char*)packet->contents(), packet->size()); + + delete packet; + } +} + +void WorldSocket::Update(time_t diff) +{ + const uint32 SEND_PACKETS_MAX = 100; + const uint32 SEND_BUFFER_SIZE = 1024; + + uint8 sendBuffer[SEND_BUFFER_SIZE]; + + while (!_sendQueue.empty()) + { + bool haveBigPacket = false; + uint32 bufferSize = 0; + + ///- While we have packets to send + for (uint32 packetCount = 0; (packetCount < SEND_PACKETS_MAX) && !_sendQueue.empty(); packetCount++) + { + ServerPktHeader *hdr = (ServerPktHeader*)&sendBuffer[bufferSize]; + + // check merge possibility. + WorldPacket *front = _sendQueue.front(); + uint32 packetSize = front->size(); + + if ((sizeof(*hdr) + packetSize) > SEND_BUFFER_SIZE) + { + haveBigPacket = true; + break; + } + + if ((bufferSize + sizeof(*hdr) + packetSize) > sizeof(sendBuffer)) + break; + + // can be merged + WorldPacket *packet = _sendQueue.next(); + + hdr->size = ntohs((uint16)packetSize + 2); + hdr->cmd = packet->GetOpcode(); + + if( sWorldLog.LogWorld() ) + { + sWorldLog.Log("SERVER:\nSOCKET: %u\nLENGTH: %u\nOPCODE: %s (0x%.4X)\nDATA:\n", + (uint32)GetSocket(), + packetSize, + LookupOpcodeName(packet->GetOpcode()), + packet->GetOpcode()); + + uint32 p = 0; + while (p < packetSize) + { + for (uint32 j = 0; j < 16 && p < packetSize; j++) + sWorldLog.Log("%.2X ", (*packet)[p++]); + + sWorldLog.Log("\n"); + } + + sWorldLog.Log("\n\n"); + } + + ///- Encrypt (if needed) the header + _crypt.EncryptSend((uint8*)hdr, sizeof(*hdr)); + bufferSize += sizeof(*hdr); + + if (packetSize) + { + memcpy(&sendBuffer[bufferSize], packet->contents(), packetSize); + bufferSize += packetSize; + } + + ///- Send the header and body to the client + delete packet; + } + + // send merged packets + if (bufferSize) TcpSocket::SendBuf((char*)sendBuffer, bufferSize); + // send too big non-merged packet + if (haveBigPacket) SendSinglePacket(); + } +} + +/// Handle the authentication waiting queue (to be completed) +void WorldSocket::SendAuthWaitQue(uint32 position) +{ + if(position == 0) + { + WorldPacket packet( SMSG_AUTH_RESPONSE, 1 ); + packet << uint8( AUTH_OK ); + SendPacket(&packet); + } + else + { + WorldPacket packet( SMSG_AUTH_RESPONSE, 5 ); + packet << uint8( AUTH_WAIT_QUEUE ); + packet << uint32 (position); //amount of players in queue + SendPacket(&packet); + } +} + +void WorldSocket::SizeError(WorldPacket const& packet, uint32 size) const +{ + sLog.outError("Client send packet %s (%u) with size %u but expected %u (attempt crash server?), skipped", + LookupOpcodeName(packet.GetOpcode()),packet.GetOpcode(),packet.size(),size); +} diff --git a/src/game/WorldSocket.h b/src/game/WorldSocket.h new file mode 100644 index 00000000000..26f8fb882f0 --- /dev/null +++ b/src/game/WorldSocket.h @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/// \addtogroup u2w +/// @{ +/// \file + +#ifndef __WORLDSOCKET_H +#define __WORLDSOCKET_H + +#include "sockets/TcpSocket.h" +#include "Auth/AuthCrypt.h" + +enum ResponseCodes +{ + RESPONSE_SUCCESS = 0x00, + RESPONSE_FAILURE = 0x01, + RESPONSE_CANCELLED = 0x02, + RESPONSE_DISCONNECTED = 0x03, + RESPONSE_FAILED_TO_CONNECT = 0x04, + RESPONSE_CONNECTED = 0x05, + RESPONSE_VERSION_MISMATCH = 0x06, + + CSTATUS_CONNECTING = 0x07, + CSTATUS_NEGOTIATING_SECURITY = 0x08, + CSTATUS_NEGOTIATION_COMPLETE = 0x09, + CSTATUS_NEGOTIATION_FAILED = 0x0A, + CSTATUS_AUTHENTICATING = 0x0B, + + AUTH_OK = 0x0C, + AUTH_FAILED = 0x0D, + AUTH_REJECT = 0x0E, + AUTH_BAD_SERVER_PROOF = 0x0F, + AUTH_UNAVAILABLE = 0x10, + AUTH_SYSTEM_ERROR = 0x11, + AUTH_BILLING_ERROR = 0x12, + AUTH_BILLING_EXPIRED = 0x13, + AUTH_VERSION_MISMATCH = 0x14, + AUTH_UNKNOWN_ACCOUNT = 0x15, + AUTH_INCORRECT_PASSWORD = 0x16, + AUTH_SESSION_EXPIRED = 0x17, + AUTH_SERVER_SHUTTING_DOWN = 0x18, + AUTH_ALREADY_LOGGING_IN = 0x19, + AUTH_LOGIN_SERVER_NOT_FOUND = 0x1A, + AUTH_WAIT_QUEUE = 0x1B, + AUTH_BANNED = 0x1C, + AUTH_ALREADY_ONLINE = 0x1D, + AUTH_NO_TIME = 0x1E, + AUTH_DB_BUSY = 0x1F, + AUTH_SUSPENDED = 0x20, + AUTH_PARENTAL_CONTROL = 0x21, + AUTH_LOCKED_ENFORCED = 0x22, + + REALM_LIST_IN_PROGRESS = 0x23, + REALM_LIST_SUCCESS = 0x24, + REALM_LIST_FAILED = 0x25, + REALM_LIST_INVALID = 0x26, + REALM_LIST_REALM_NOT_FOUND = 0x27, + + ACCOUNT_CREATE_IN_PROGRESS = 0x28, + ACCOUNT_CREATE_SUCCESS = 0x29, + ACCOUNT_CREATE_FAILED = 0x2A, + + CHAR_LIST_RETRIEVING = 0x2B, + CHAR_LIST_RETRIEVED = 0x2C, + CHAR_LIST_FAILED = 0x2D, + + CHAR_CREATE_IN_PROGRESS = 0x2E, + CHAR_CREATE_SUCCESS = 0x2F, + CHAR_CREATE_ERROR = 0x30, + CHAR_CREATE_FAILED = 0x31, + CHAR_CREATE_NAME_IN_USE = 0x32, + CHAR_CREATE_DISABLED = 0x33, + CHAR_CREATE_PVP_TEAMS_VIOLATION = 0x34, + CHAR_CREATE_SERVER_LIMIT = 0x35, + CHAR_CREATE_ACCOUNT_LIMIT = 0x36, + CHAR_CREATE_SERVER_QUEUE = 0x37, + CHAR_CREATE_ONLY_EXISTING = 0x38, + CHAR_CREATE_EXPANSION = 0x39, + + CHAR_DELETE_IN_PROGRESS = 0x3A, + CHAR_DELETE_SUCCESS = 0x3B, + CHAR_DELETE_FAILED = 0x3C, + CHAR_DELETE_FAILED_LOCKED_FOR_TRANSFER = 0x3D, + CHAR_DELETE_FAILED_GUILD_LEADER = 0x3E, + CHAR_DELETE_FAILED_ARENA_CAPTAIN = 0x3F, + + CHAR_LOGIN_IN_PROGRESS = 0x40, + CHAR_LOGIN_SUCCESS = 0x41, + CHAR_LOGIN_NO_WORLD = 0x42, + CHAR_LOGIN_DUPLICATE_CHARACTER = 0x43, + CHAR_LOGIN_NO_INSTANCES = 0x44, + CHAR_LOGIN_FAILED = 0x45, + CHAR_LOGIN_DISABLED = 0x46, + CHAR_LOGIN_NO_CHARACTER = 0x47, + CHAR_LOGIN_LOCKED_FOR_TRANSFER = 0x48, + CHAR_LOGIN_LOCKED_BY_BILLING = 0x49, + + CHAR_NAME_SUCCESS = 0x4A, + CHAR_NAME_FAILURE = 0x4B, + CHAR_NAME_NO_NAME = 0x4C, + CHAR_NAME_TOO_SHORT = 0x4D, + CHAR_NAME_TOO_LONG = 0x4E, + CHAR_NAME_INVALID_CHARACTER = 0x4F, + CHAR_NAME_MIXED_LANGUAGES = 0x50, + CHAR_NAME_PROFANE = 0x51, + CHAR_NAME_RESERVED = 0x52, + CHAR_NAME_INVALID_APOSTROPHE = 0x53, + CHAR_NAME_MULTIPLE_APOSTROPHES = 0x54, + CHAR_NAME_THREE_CONSECUTIVE = 0x55, + CHAR_NAME_INVALID_SPACE = 0x56, + CHAR_NAME_CONSECUTIVE_SPACES = 0x57, + CHAR_NAME_RUSSIAN_CONSECUTIVE_SILENT_CHARACTERS = 0x58, + CHAR_NAME_RUSSIAN_SILENT_CHARACTER_AT_BEGINNING_OR_END = 0x59, + CHAR_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME = 0x5A, +}; + +class WorldPacket; +class SocketHandler; +class WorldSession; + +/// Handle connection with the client software +class WorldSocket : public TcpSocket +{ + public: + WorldSocket(ISocketHandler&); + ~WorldSocket(); + + void SendPacket(WorldPacket const* packet); + void CloseSocket(); + + void OnAccept(); + void OnRead(); + void OnDelete(); + + void Update(time_t diff); + // Player Queue + void SendAuthWaitQue(uint32 position); + + WorldSession* GetSession() const { return _session; } + protected: + void SendSinglePacket(); + + protected: + void _HandleAuthSession(WorldPacket& recvPacket); + void _HandlePing(WorldPacket& recvPacket); + + private: + AuthCrypt _crypt; + uint32 _seed; + uint32 _cmd; + uint16 _remaining; + WorldSession* _session; + + ZThread::LockedQueue _sendQueue; + + uint32 m_LastPingMSTime; + uint32 m_OverSpeedPings; + + // internal checks + void SizeError(WorldPacket const& packet, uint32 size) const; +}; +#endif +/// @} diff --git a/src/game/WorldSocketMgr.cpp b/src/game/WorldSocketMgr.cpp new file mode 100644 index 00000000000..0281d200109 --- /dev/null +++ b/src/game/WorldSocketMgr.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2005-2008,2007 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** \file + \ingroup u2w +*/ + +#include "Common.h" +#include "WorldSocket.h" +#include "WorldSocketMgr.h" +#include "Policies/SingletonImp.h" + +INSTANTIATE_SINGLETON_1( WorldSocketMgr ); + +/// WorldSocketMgr constructor +WorldSocketMgr::WorldSocketMgr() +{ +} + +/// Add a WorldSocket to the set +void WorldSocketMgr::AddSocket(WorldSocket *s) +{ + m_sockets.insert(s); +} + +/// Remove a WorldSocket to the set +void WorldSocketMgr::RemoveSocket(WorldSocket *s) +{ + m_sockets.erase(s); +} + +/// Triggers an 'update' to all sockets in the set +void WorldSocketMgr::Update(time_t diff) +{ + SocketSet::iterator i; + for(i = m_sockets.begin(); i != m_sockets.end(); i++) + { + (*i)->Update(diff); + } +} diff --git a/src/game/WorldSocketMgr.h b/src/game/WorldSocketMgr.h new file mode 100644 index 00000000000..5a26d739f4a --- /dev/null +++ b/src/game/WorldSocketMgr.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2005-2008,2007 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/// \addtogroup u2w User to World Communication +/// @{ +/// \file + +#ifndef __WORLDSOCKETMGR_H +#define __WORLDSOCKETMGR_H + +#include "Policies/Singleton.h" + +class WorldSocket; + +/// Manages the list of connected WorldSockets +class WorldSocketMgr +{ + public: + WorldSocketMgr(); + + void AddSocket(WorldSocket *s); + void RemoveSocket(WorldSocket *s); + void Update(time_t diff); + + private: + typedef std::set SocketSet; + SocketSet m_sockets; +}; + +#define sWorldSocketMgr MaNGOS::Singleton::Instance() +#endif +/// @} diff --git a/src/game/debugcmds.cpp b/src/game/debugcmds.cpp new file mode 100644 index 00000000000..98d0984f545 --- /dev/null +++ b/src/game/debugcmds.cpp @@ -0,0 +1,514 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "World.h" +#include "Player.h" +#include "Opcodes.h" +#include "Chat.h" +#include "Log.h" +#include "Unit.h" +#include "ObjectAccessor.h" +#include "GossipDef.h" +#include "Language.h" +#include "MapManager.h" + +bool ChatHandler::HandleDebugInArcCommand(const char* /*args*/) +{ + Object *obj = getSelectedUnit(); + + if(!obj) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + return true; + } + + SendSysMessage(LANG_NOT_IMPLEMENTED); + + return true; +} + +bool ChatHandler::HandleDebugSpellFailCommand(const char* args) +{ + if(!args) + return false; + + char* px = strtok((char*)args, " "); + if(!px) + return false; + + uint8 failnum = (uint8)atoi(px); + + WorldPacket data(SMSG_CAST_FAILED, 5); + data << (uint32)133; + data << failnum; + m_session->SendPacket(&data); + + return true; +} + +bool ChatHandler::HandleSetPoiCommand(const char* args) +{ + Player *pPlayer = m_session->GetPlayer(); + Unit* target = getSelectedUnit(); + if(!target) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + return true; + } + + if(!args) + return false; + + char* icon_text = strtok((char*)args, " "); + char* flags_text = strtok(NULL, " "); + if(!icon_text || !flags_text) + return false; + + uint32 icon = atol(icon_text); + if ( icon < 0 ) + icon = 0; + + uint32 flags = atol(flags_text); + + sLog.outDetail("Command : POI, NPC = %u, icon = %u flags = %u", target->GetGUIDLow(), icon,flags); + pPlayer->PlayerTalkClass->SendPointOfInterest(target->GetPositionX(), target->GetPositionY(), Poi_Icon(icon), flags, 30, "Test POI"); + return true; +} + +bool ChatHandler::HandleEquipErrorCommand(const char* args) +{ + if(!args) + return false; + + uint8 msg = atoi(args); + m_session->GetPlayer()->SendEquipError(msg, 0, 0); + return true; +} + +bool ChatHandler::HandleSellErrorCommand(const char* args) +{ + if(!args) + return false; + + uint8 msg = atoi(args); + m_session->GetPlayer()->SendSellError(msg, 0, 0, 0); + return true; +} + +bool ChatHandler::HandleBuyErrorCommand(const char* args) +{ + if(!args) + return false; + + uint8 msg = atoi(args); + m_session->GetPlayer()->SendBuyError(msg, 0, 0, 0); + return true; +} + +bool ChatHandler::HandleSendOpcodeCommand(const char* args) +{ + Unit *unit = getSelectedUnit(); + if (!unit || (unit->GetTypeId() != TYPEID_PLAYER)) + unit = m_session->GetPlayer(); + + FILE *file = fopen("opcode.txt", "r"); + if(!file) + return false; + + uint32 type; + + uint32 val1; + uint64 val2; + float val3; + char val4[101]; + + uint32 opcode = 0; + fscanf(file, "%u", &opcode); + if(!opcode) + { + fclose(file); + return false; + } + + WorldPacket data(opcode, 0); + + while(fscanf(file, "%u", &type) != EOF) + { + switch(type) + { + case 0: // uint8 + fscanf(file, "%u", &val1); + data << uint8(val1); + break; + case 1: // uint16 + fscanf(file, "%u", &val1); + data << uint16(val1); + break; + case 2: // uint32 + fscanf(file, "%u", &val1); + data << uint32(val1); + break; + case 3: // uint64 + fscanf(file, I64FMTD, &val2); + data << uint64(val2); + break; + case 4: // float + fscanf(file, "%f", &val3); + data << float(val3); + break; + case 5: // string + fscanf(file, "%s", val4, 101); + data << val4; + break; + case 6: // packed guid + data.append(unit->GetPackGUID()); + break; + default: + fclose(file); + return false; + } + } + fclose(file); + sLog.outDebug("Sending opcode %u", data.GetOpcode()); + data.hexlike(); + ((Player*)unit)->GetSession()->SendPacket(&data); + PSendSysMessage(LANG_COMMAND_OPCODESENT, data.GetOpcode(), unit->GetName()); + return true; +} + +bool ChatHandler::HandleUpdateWorldStateCommand(const char* args) +{ + char* w = strtok((char*)args, " "); + char* s = strtok(NULL, " "); + + if (!w || !s) + return false; + + uint32 world = (uint32)atoi(w); + uint32 state = (uint32)atoi(s); + m_session->GetPlayer()->SendUpdateWorldState(world, state); + return true; +} + +bool ChatHandler::HandlePlaySound2Command(const char* args) +{ + if(!args) + return false; + + uint32 soundid = atoi(args); + m_session->GetPlayer()->PlaySound(soundid, false); + return true; +} + +//Send notification in channel +bool ChatHandler::HandleSendChannelNotifyCommand(const char* args) +{ + if(!args) + return false; + + const char *name = "test"; + uint8 code = atoi(args); + + WorldPacket data(SMSG_CHANNEL_NOTIFY, (1+10)); + data << code; // notify type + data << name; // channel name + data << uint32(0); + data << uint32(0); + m_session->SendPacket(&data); + return true; +} + +//Send notification in chat +bool ChatHandler::HandleSendChatMsgCommand(const char* args) +{ + if(!args) + return false; + + const char *msg = "testtest"; + uint8 type = atoi(args); + WorldPacket data; + ChatHandler::FillMessageData(&data, m_session, type, 0, "chan", m_session->GetPlayer()->GetGUID(), msg, m_session->GetPlayer()); + m_session->SendPacket(&data); + return true; +} + +bool ChatHandler::HandleSendQuestPartyMsgCommand(const char* args) +{ + uint32 msg = atol((char*)args); + if (msg >= 0) + m_session->GetPlayer()->SendPushToPartyResponse(m_session->GetPlayer(), msg); + return true; +} + +bool ChatHandler::HandleGetLootRecipient(const char* args) +{ + Creature* target = getSelectedCreature(); + if(!target) + return false; + + PSendSysMessage("loot recipient: %s", target->hasLootRecipient()?(target->GetLootRecipient()?target->GetLootRecipient()->GetName():"offline"):"no loot recipient"); + return true; +} + +bool ChatHandler::HandleSendQuestInvalidMsgCommand(const char* args) +{ + uint32 msg = atol((char*)args); + if (msg >= 0) + m_session->GetPlayer()->SendCanTakeQuestResponse(msg); + return true; +} + +bool ChatHandler::HandleGetItemState(const char* args) +{ + if (!args) + return false; + + std::string state_str = args; + + ItemUpdateState state = ITEM_UNCHANGED; + bool list_queue = false, check_all = false; + if (state_str == "unchanged") state = ITEM_UNCHANGED; + else if (state_str == "changed") state = ITEM_CHANGED; + else if (state_str == "new") state = ITEM_NEW; + else if (state_str == "removed") state = ITEM_REMOVED; + else if (state_str == "queue") list_queue = true; + else if (state_str == "check_all") check_all = true; + else return false; + + Player* player = getSelectedPlayer(); + if (!player) player = m_session->GetPlayer(); + + if (!list_queue && !check_all) + { + state_str = "The player has the following " + state_str + " items: "; + SendSysMessage(state_str.c_str()); + for (uint8 i = PLAYER_SLOT_START; i < PLAYER_SLOT_END; i++) + { + if(i >= BUYBACK_SLOT_START && i < BUYBACK_SLOT_END) + continue; + + Item *item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, i); + if (!item) continue; + if (!item->IsBag()) + { + if (item->GetState() == state) + PSendSysMessage("bag: 255 slot: %d guid: %d owner: %d", item->GetSlot(), item->GetGUIDLow(), GUID_LOPART(item->GetOwnerGUID())); + } + else + { + Bag *bag = (Bag*)item; + const ItemPrototype *proto = bag->GetProto(); + for (uint8 j = 0; j < proto->ContainerSlots; ++j) + { + Item* item = bag->GetItemByPos(j); + if (item && item->GetState() == state) + PSendSysMessage("bag: 255 slot: %d guid: %d owner: %d", item->GetSlot(), item->GetGUIDLow(), GUID_LOPART(item->GetOwnerGUID())); + } + } + } + } + + if (list_queue) + { + std::vector &updateQueue = player->GetItemUpdateQueue(); + for(size_t i = 0; i < updateQueue.size(); i++) + { + Item *item = updateQueue[i]; + if(!item) continue; + + Bag *container = item->GetContainer(); + uint8 bag_slot = container ? container->GetSlot() : uint8(INVENTORY_SLOT_BAG_0); + + std::string st; + switch(item->GetState()) + { + case ITEM_UNCHANGED: st = "unchanged"; break; + case ITEM_CHANGED: st = "changed"; break; + case ITEM_NEW: st = "new"; break; + case ITEM_REMOVED: st = "removed"; break; + } + + PSendSysMessage("bag: %d slot: %d guid: %d - state: %s", bag_slot, item->GetSlot(), item->GetGUIDLow(), st.c_str()); + } + if (updateQueue.empty()) + PSendSysMessage("updatequeue empty"); + } + + if (check_all) + { + bool error = false; + std::vector &updateQueue = player->GetItemUpdateQueue(); + for (uint8 i = PLAYER_SLOT_START; i < PLAYER_SLOT_END; i++) + { + if(i >= BUYBACK_SLOT_START && i < BUYBACK_SLOT_END) + continue; + + Item *item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, i); + if (!item) continue; + + if (item->GetSlot() != i) + { + PSendSysMessage("item at slot %d, guid %d has an incorrect slot value: %d", i, item->GetGUIDLow(), item->GetSlot()); + error = true; continue; + } + + if (item->GetOwnerGUID() != player->GetGUID()) + { + PSendSysMessage("for the item at slot %d and itemguid %d, owner's guid (%d) and player's guid (%d) don't match!", item->GetSlot(), item->GetGUIDLow(), GUID_LOPART(item->GetOwnerGUID()), player->GetGUIDLow()); + error = true; continue; + } + + if (Bag *container = item->GetContainer()) + { + PSendSysMessage("item at slot: %d guid: %d has a container (slot: %d, guid: %d) but shouldnt!", item->GetSlot(), item->GetGUIDLow(), container->GetSlot(), container->GetGUIDLow()); + error = true; continue; + } + + if (item->IsInUpdateQueue()) + { + uint16 qp = item->GetQueuePos(); + if (qp > updateQueue.size()) + { + PSendSysMessage("item at slot: %d guid: %d has a queuepos (%d) larger than the update queue size! ", item->GetSlot(), item->GetGUIDLow(), qp); + error = true; continue; + } + + if (updateQueue[qp] == NULL) + { + PSendSysMessage("item at slot: %d guid: %d has a queuepos (%d) that points to NULL in the queue!", item->GetSlot(), item->GetGUIDLow(), qp); + error = true; continue; + } + + if (updateQueue[qp] != item) + { + PSendSysMessage("item at slot: %d guid: %d has has a queuepos (%d) that points to another item in the queue (bag: %d, slot: %d, guid: %d)", item->GetSlot(), item->GetGUIDLow(), qp, updateQueue[qp]->GetBagSlot(), updateQueue[qp]->GetSlot(), updateQueue[qp]->GetGUIDLow()); + error = true; continue; + } + } + else if (item->GetState() != ITEM_UNCHANGED) + { + PSendSysMessage("item at slot: %d guid: %d is not in queue but should be (state: %d)!", item->GetSlot(), item->GetGUIDLow(), item->GetState()); + error = true; continue; + } + + if(item->IsBag()) + { + Bag *bag = (Bag*)item; + const ItemPrototype *proto = bag->GetProto(); + for (uint8 j = 0; j < proto->ContainerSlots; ++j) + { + Item* item = bag->GetItemByPos(j); + if (!item) continue; + + if (item->GetSlot() != j) + { + PSendSysMessage("the item in bag %d slot %d, guid %d has an incorrect slot value: %d", bag->GetSlot(), j, item->GetGUIDLow(), item->GetSlot()); + error = true; continue; + } + + if (item->GetOwnerGUID() != player->GetGUID()) + { + PSendSysMessage("for the item in bag %d at slot %d and itemguid %d, owner's guid (%d) and player's guid (%d) don't match!", bag->GetSlot(), item->GetSlot(), item->GetGUIDLow(), GUID_LOPART(item->GetOwnerGUID()), player->GetGUIDLow()); + error = true; continue; + } + + Bag *container = item->GetContainer(); + if (!container) + { + PSendSysMessage("the item in bag %d at slot %d with guid %d has no container!", bag->GetSlot(), item->GetSlot(), item->GetGUIDLow()); + error = true; continue; + } + + if (container != bag) + { + PSendSysMessage("the item in bag %d at slot %d with guid %d has a different container(slot %d guid %d)!", bag->GetSlot(), item->GetSlot(), item->GetGUIDLow(), container->GetSlot(), container->GetGUIDLow()); + error = true; continue; + } + + if (item->IsInUpdateQueue()) + { + uint16 qp = item->GetQueuePos(); + if (qp > updateQueue.size()) + { + PSendSysMessage("item in bag: %d at slot: %d guid: %d has a queuepos (%d) larger than the update queue size! ", bag->GetSlot(), item->GetSlot(), item->GetGUIDLow(), qp); + error = true; continue; + } + + if (updateQueue[qp] == NULL) + { + PSendSysMessage("item in bag: %d at slot: %d guid: %d has a queuepos (%d) that points to NULL in the queue!", bag->GetSlot(), item->GetSlot(), item->GetGUIDLow(), qp); + error = true; continue; + } + + if (updateQueue[qp] != item) + { + PSendSysMessage("item in bag: %d at slot: %d guid: %d has has a queuepos (%d) that points to another item in the queue (bag: %d, slot: %d, guid: %d)", bag->GetSlot(), item->GetSlot(), item->GetGUIDLow(), qp, updateQueue[qp]->GetBagSlot(), updateQueue[qp]->GetSlot(), updateQueue[qp]->GetGUIDLow()); + error = true; continue; + } + } + else if (item->GetState() != ITEM_UNCHANGED) + { + PSendSysMessage("item in bag: %d at slot: %d guid: %d is not in queue but should be (state: %d)!", bag->GetSlot(), item->GetSlot(), item->GetGUIDLow(), item->GetState()); + error = true; continue; + } + } + } + } + + for(size_t i = 0; i < updateQueue.size(); i++) + { + Item *item = updateQueue[i]; + if(!item) continue; + + if (item->GetOwnerGUID() != player->GetGUID()) + { + PSendSysMessage("queue(%d): for the an item (guid %d), the owner's guid (%d) and player's guid (%d) don't match!", i, item->GetGUIDLow(), GUID_LOPART(item->GetOwnerGUID()), player->GetGUIDLow()); + error = true; continue; + } + + if (item->GetQueuePos() != i) + { + PSendSysMessage("queue(%d): for the an item (guid %d), the queuepos doesn't match it's position in the queue!", i, item->GetGUIDLow()); + error = true; continue; + } + + if (item->GetState() == ITEM_REMOVED) continue; + Item *test = player->GetItemByPos( item->GetBagSlot(), item->GetSlot()); + + if (test == NULL) + { + PSendSysMessage("queue(%d): the bag(%d) and slot(%d) values for the item with guid %d are incorrect, the player doesn't have an item at that position!", i, item->GetBagSlot(), item->GetSlot(), item->GetGUIDLow()); + error = true; continue; + } + + if (test != item) + { + PSendSysMessage("queue(%d): the bag(%d) and slot(%d) values for the item with guid %d are incorrect, the item with guid %d is there instead!", i, item->GetBagSlot(), item->GetSlot(), item->GetGUIDLow(), test->GetGUIDLow()); + error = true; continue; + } + } + if (!error) + SendSysMessage("All OK!"); + } + + return true; +} diff --git a/src/game/tools.cpp b/src/game/tools.cpp new file mode 100644 index 00000000000..7b4b4cffbaa --- /dev/null +++ b/src/game/tools.cpp @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Tools.h" + +// THIS CAN BE A LOT FASTER +bool readGUID(WorldPacket & data, uint64& guid) +{ + if(data.rpos()+1 > data.size()) + return false; + + uint8 guidmark=0; + uint8 bit; + uint8 shiftdata=0x1; + uint64 Temp=0; + + guid = 0; + + data >> guidmark; + for(int i=0;i<8;i++) + { + if(guidmark & shiftdata) + { + Temp = 0; + + if(data.rpos()+1 > data.size()) + return false; + + data >> bit; + Temp = bit; + Temp <<= i*8; + guid |= Temp; + } + shiftdata=shiftdata<<1; + } + + return true; +} + +void writeGUID(WorldPacket & data, uint64 & guid) +{ + uint8 RAWmask = 0; + uint8 PackedGuid[8] = {0,0,0,0,0,0,0,0}; + + int j = 1; + uint8 * test = (uint8*)&guid; + + if (*test) + { + PackedGuid[j] = *test; + RAWmask |= 1; + ++j; + } + if (*(test+1)) + { + PackedGuid[j] = *(test+1); + RAWmask |= 2; + ++j; + } + if (*(test+2)) + { + PackedGuid[j] = *(test+2); + RAWmask |= 4; + ++j; + } + if (*(test+3)) + { + PackedGuid[j] = *(test+3); + RAWmask |= 8; + ++j; + } + if (*(test+4)) + { + PackedGuid[j] = *(test+4); + RAWmask |= 16; + ++j; + } + if (*(test+5)) + { + PackedGuid[j] = *(test+5); + RAWmask |= 32; + ++j; + } + if (*(test+6)) + { + PackedGuid[j] = *(test+6); + RAWmask |= 64; + ++j; + } + if (*(test+7)) + { + PackedGuid[j] = *(test+7); + RAWmask |= 128; + ++j; + } + PackedGuid[0] = RAWmask; + + data.append(PackedGuid,j); +} diff --git a/src/shared/Auth/AuthCrypt.cpp b/src/shared/Auth/AuthCrypt.cpp new file mode 100644 index 00000000000..56143c3417c --- /dev/null +++ b/src/shared/Auth/AuthCrypt.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "AuthCrypt.h" +#include "Hmac.h" + +AuthCrypt::AuthCrypt() +{ + _initialized = false; +} + +void AuthCrypt::Init() +{ + _send_i = _send_j = _recv_i = _recv_j = 0; + _initialized = true; +} + +void AuthCrypt::DecryptRecv(uint8 *data, size_t len) +{ + if (!_initialized) return; + if (len < CRYPTED_RECV_LEN) return; + + for (size_t t = 0; t < CRYPTED_RECV_LEN; t++) + { + _recv_i %= _key.size(); + uint8 x = (data[t] - _recv_j) ^ _key[_recv_i]; + ++_recv_i; + _recv_j = data[t]; + data[t] = x; + } +} + +void AuthCrypt::EncryptSend(uint8 *data, size_t len) +{ + if (!_initialized) return; + if (len < CRYPTED_SEND_LEN) return; + + for (size_t t = 0; t < CRYPTED_SEND_LEN; t++) + { + _send_i %= _key.size(); + uint8 x = (data[t] ^ _key[_send_i]) + _send_j; + ++_send_i; + data[t] = _send_j = x; + } +} + +void AuthCrypt::SetKey(BigNumber *bn) +{ + uint8 *key = new uint8[SHA_DIGEST_LENGTH]; + GenerateKey(key, bn); + _key.resize(SHA_DIGEST_LENGTH); + std::copy(key, key + SHA_DIGEST_LENGTH, _key.begin()); + delete key; +} + +AuthCrypt::~AuthCrypt() +{ +} + +void AuthCrypt::GenerateKey(uint8 *key, BigNumber *bn) +{ + HmacHash hash; + hash.UpdateBigNumber(bn); + hash.Finalize(); + memcpy(key, hash.GetDigest(), SHA_DIGEST_LENGTH); +} diff --git a/src/shared/Auth/AuthCrypt.h b/src/shared/Auth/AuthCrypt.h new file mode 100644 index 00000000000..94e075e584e --- /dev/null +++ b/src/shared/Auth/AuthCrypt.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _AUTHCRYPT_H +#define _AUTHCRYPT_H + +#include +#include + +class BigNumber; + +class AuthCrypt +{ + public: + AuthCrypt(); + ~AuthCrypt(); + + const static size_t CRYPTED_SEND_LEN = 4; + const static size_t CRYPTED_RECV_LEN = 6; + + void Init(); + + void SetKey(BigNumber *); + + void DecryptRecv(uint8 *, size_t); + void EncryptSend(uint8 *, size_t); + + bool IsInitialized() { return _initialized; } + + static void GenerateKey(uint8 *, BigNumber *); + + private: + std::vector _key; + uint8 _send_i, _send_j, _recv_i, _recv_j; + bool _initialized; +}; +#endif diff --git a/src/shared/Auth/BigNumber.cpp b/src/shared/Auth/BigNumber.cpp new file mode 100644 index 00000000000..752e82f171e --- /dev/null +++ b/src/shared/Auth/BigNumber.cpp @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Auth/BigNumber.h" +#include +#include + +BigNumber::BigNumber() +{ + _bn = BN_new(); + _array = NULL; +} + +BigNumber::BigNumber(const BigNumber &bn) +{ + _bn = BN_dup(bn._bn); + _array = NULL; +} + +BigNumber::BigNumber(uint32 val) +{ + _bn = BN_new(); + BN_set_word(_bn, val); + _array = NULL; +} + +BigNumber::~BigNumber() +{ + BN_free(_bn); + if(_array) delete[] _array; +} + +void BigNumber::SetDword(uint32 val) +{ + BN_set_word(_bn, val); +} + +void BigNumber::SetQword(uint64 val) +{ + BN_add_word(_bn, (uint32)(val >> 32)); + BN_lshift(_bn, _bn, 32); + BN_add_word(_bn, (uint32)(val & 0xFFFFFFFF)); +} + +void BigNumber::SetBinary(const uint8 *bytes, int len) +{ + uint8 t[1000]; + for (int i = 0; i < len; i++) t[i] = bytes[len - 1 - i]; + BN_bin2bn(t, len, _bn); +} + +void BigNumber::SetHexStr(const char *str) +{ + BN_hex2bn(&_bn, str); +} + +void BigNumber::SetRand(int numbits) +{ + BN_rand(_bn, numbits, 0, 1); +} + +BigNumber BigNumber::operator=(const BigNumber &bn) +{ + BN_copy(_bn, bn._bn); + return *this; +} + +BigNumber BigNumber::operator+=(const BigNumber &bn) +{ + BN_add(_bn, _bn, bn._bn); + return *this; +} + +BigNumber BigNumber::operator-=(const BigNumber &bn) +{ + BN_sub(_bn, _bn, bn._bn); + return *this; +} + +BigNumber BigNumber::operator*=(const BigNumber &bn) +{ + BN_CTX *bnctx; + + bnctx = BN_CTX_new(); + BN_mul(_bn, _bn, bn._bn, bnctx); + BN_CTX_free(bnctx); + + return *this; +} + +BigNumber BigNumber::operator/=(const BigNumber &bn) +{ + BN_CTX *bnctx; + + bnctx = BN_CTX_new(); + BN_div(_bn, NULL, _bn, bn._bn, bnctx); + BN_CTX_free(bnctx); + + return *this; +} + +BigNumber BigNumber::operator%=(const BigNumber &bn) +{ + BN_CTX *bnctx; + + bnctx = BN_CTX_new(); + BN_mod(_bn, _bn, bn._bn, bnctx); + BN_CTX_free(bnctx); + + return *this; +} + +BigNumber BigNumber::Exp(const BigNumber &bn) +{ + BigNumber ret; + BN_CTX *bnctx; + + bnctx = BN_CTX_new(); + BN_exp(ret._bn, _bn, bn._bn, bnctx); + BN_CTX_free(bnctx); + + return ret; +} + +BigNumber BigNumber::ModExp(const BigNumber &bn1, const BigNumber &bn2) +{ + BigNumber ret; + BN_CTX *bnctx; + + bnctx = BN_CTX_new(); + BN_mod_exp(ret._bn, _bn, bn1._bn, bn2._bn, bnctx); + BN_CTX_free(bnctx); + + return ret; +} + +int BigNumber::GetNumBytes(void) +{ + return BN_num_bytes(_bn); +} + +uint32 BigNumber::AsDword() +{ + return (uint32)BN_get_word(_bn); +} + +uint8 *BigNumber::AsByteArray(int minSize) +{ + int length = (minSize >= GetNumBytes()) ? minSize : GetNumBytes(); + + if (_array) + { + delete[] _array; + _array = NULL; + } + _array = new uint8[length]; + + // If we need more bytes than length of BigNumber set the rest to 0 + if (length > GetNumBytes()) + memset((void*)_array, 0, length); + + BN_bn2bin(_bn, (unsigned char *)_array); + + std::reverse(_array, _array + length); + + return _array; +} + +ByteBuffer BigNumber::AsByteBuffer() +{ + ByteBuffer ret(GetNumBytes()); + ret.append(AsByteArray(), GetNumBytes()); + return ret; +} + +std::vector BigNumber::AsByteVector() +{ + std::vector ret; + ret.resize(GetNumBytes()); + memcpy(&ret[0], AsByteArray(), GetNumBytes()); + return ret; +} + +const char *BigNumber::AsHexStr() +{ + return BN_bn2hex(_bn); +} + +const char *BigNumber::AsDecStr() +{ + return BN_bn2dec(_bn); +} diff --git a/src/shared/Auth/BigNumber.h b/src/shared/Auth/BigNumber.h new file mode 100644 index 00000000000..c66798afd85 --- /dev/null +++ b/src/shared/Auth/BigNumber.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _AUTH_BIGNUMBER_H +#define _AUTH_BIGNUMBER_H + +#include "Common.h" +#include "ByteBuffer.h" + +struct bignum_st; + +class BigNumber +{ + public: + BigNumber(); + BigNumber(const BigNumber &bn); + BigNumber(uint32); + ~BigNumber(); + + void SetDword(uint32); + void SetQword(uint64); + void SetBinary(const uint8 *bytes, int len); + void SetHexStr(const char *str); + + void SetRand(int numbits); + + BigNumber operator=(const BigNumber &bn); + + BigNumber operator+=(const BigNumber &bn); + BigNumber operator+(const BigNumber &bn) + { + BigNumber t(*this); + return t += bn; + } + BigNumber operator-=(const BigNumber &bn); + BigNumber operator-(const BigNumber &bn) + { + BigNumber t(*this); + return t -= bn; + } + BigNumber operator*=(const BigNumber &bn); + BigNumber operator*(const BigNumber &bn) + { + BigNumber t(*this); + return t *= bn; + } + BigNumber operator/=(const BigNumber &bn); + BigNumber operator/(const BigNumber &bn) + { + BigNumber t(*this); + return t /= bn; + } + BigNumber operator%=(const BigNumber &bn); + BigNumber operator%(const BigNumber &bn) + { + BigNumber t(*this); + return t %= bn; + } + + BigNumber ModExp(const BigNumber &bn1, const BigNumber &bn2); + BigNumber Exp(const BigNumber &); + + int GetNumBytes(void); + + struct bignum_st *BN() { return _bn; } + + uint32 AsDword(); + uint8* AsByteArray(int minSize = 0); + ByteBuffer AsByteBuffer(); + std::vector AsByteVector(); + + const char *AsHexStr(); + const char *AsDecStr(); + + private: + struct bignum_st *_bn; + uint8 *_array; +}; +#endif diff --git a/src/shared/Auth/Hmac.cpp b/src/shared/Auth/Hmac.cpp new file mode 100644 index 00000000000..d2054a0a777 --- /dev/null +++ b/src/shared/Auth/Hmac.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Auth/Hmac.h" +#include "BigNumber.h" + +HmacHash::HmacHash() +{ + uint8 temp[SEED_KEY_SIZE] = { 0x38, 0xA7, 0x83, 0x15, 0xF8, 0x92, 0x25, 0x30, 0x71, 0x98, 0x67, 0xB1, 0x8C, 0x4, 0xE2, 0xAA }; + memcpy(&m_key, &temp, SEED_KEY_SIZE); + HMAC_CTX_init(&m_ctx); + HMAC_Init_ex(&m_ctx, &m_key, SEED_KEY_SIZE, EVP_sha1(), NULL); +} + +HmacHash::~HmacHash() +{ + memset(&m_key, 0x00, SEED_KEY_SIZE); + HMAC_CTX_cleanup(&m_ctx); +} + +void HmacHash::UpdateBigNumber(BigNumber *bn) +{ + UpdateData(bn->AsByteArray(), bn->GetNumBytes()); +} + +void HmacHash::UpdateData(const uint8 *data, int length) +{ + HMAC_Update(&m_ctx, data, length); +} + +void HmacHash::Initialize() +{ + HMAC_Init_ex(&m_ctx, &m_key, SEED_KEY_SIZE, EVP_sha1(), NULL); +} + +void HmacHash::Finalize() +{ + uint32 length = 0; + HMAC_Final(&m_ctx, m_digest, &length); + ASSERT(length == SHA_DIGEST_LENGTH) +} diff --git a/src/shared/Auth/Hmac.h b/src/shared/Auth/Hmac.h new file mode 100644 index 00000000000..083c84fe871 --- /dev/null +++ b/src/shared/Auth/Hmac.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _AUTH_HMAC_H +#define _AUTH_HMAC_H + +#include "Common.h" +#include +#include + +class BigNumber; + +#define SEED_KEY_SIZE 16 + +class HmacHash +{ + public: + HmacHash(); + ~HmacHash(); + void UpdateBigNumber(BigNumber *bn); + void UpdateData(const uint8 *data, int length); + void Initialize(); + void Finalize(); + uint8 *GetDigest() { return m_digest; }; + int GetLength() { return SHA_DIGEST_LENGTH; }; + private: + HMAC_CTX m_ctx; + uint8 m_key[SEED_KEY_SIZE]; + uint8 m_digest[SHA_DIGEST_LENGTH]; +}; +#endif diff --git a/src/shared/Auth/Makefile.am b/src/shared/Auth/Makefile.am new file mode 100644 index 00000000000..6646568ee35 --- /dev/null +++ b/src/shared/Auth/Makefile.am @@ -0,0 +1,39 @@ +# Copyright (C) 2005-2008 MaNGOS +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## Process this file with automake to produce Makefile.in + +## Sub-directories to parse + +## CPP flags for includes, defines, etc. +AM_CPPFLAGS = $(MYSQL_INCLUDES) $(POSTGRE_INCLUDES) -I$(top_builddir)/src/shared -I$(srcdir) -I$(srcdir)/../../../dep/include -I$(srcdir)/../../framework -I$(srcdir)/../../shared -I$(srcdir)/../../../dep/include/g3dlite + +## Build MaNGOS shared library and its parts as convenience library. +# All libraries will be convenience libraries. Might be changed to shared +# later. +noinst_LIBRARIES = libmangosauth.a + +libmangosauth_a_SOURCES = \ + AuthCrypt.cpp \ + AuthCrypt.h \ + BigNumber.cpp \ + BigNumber.h \ + Hmac.cpp \ + Hmac.h \ + Sha1.cpp \ + Sha1.h \ + md5.c \ + md5.h diff --git a/src/shared/Auth/Sha1.cpp b/src/shared/Auth/Sha1.cpp new file mode 100644 index 00000000000..6a4a3967b26 --- /dev/null +++ b/src/shared/Auth/Sha1.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Auth/Sha1.h" +#include + +Sha1Hash::Sha1Hash() +{ + SHA1_Init(&mC); +} + +Sha1Hash::~Sha1Hash() +{ + SHA1_Init(&mC); +} + +void Sha1Hash::UpdateData(const uint8 *dta, int len) +{ + SHA1_Update(&mC, dta, len); +} + +void Sha1Hash::UpdateData(const std::string &str) +{ + UpdateData((uint8 const*)str.c_str(), str.length()); +} + +void Sha1Hash::UpdateBigNumbers(BigNumber *bn0, ...) +{ + va_list v; + BigNumber *bn; + + va_start(v, bn0); + bn = bn0; + while (bn) + { + UpdateData(bn->AsByteArray(), bn->GetNumBytes()); + bn = va_arg(v, BigNumber *); + } + va_end(v); +} + +void Sha1Hash::Initialize() +{ + SHA1_Init(&mC); +} + +void Sha1Hash::Finalize(void) +{ + SHA1_Final(mDigest, &mC); +} diff --git a/src/shared/Auth/Sha1.h b/src/shared/Auth/Sha1.h new file mode 100644 index 00000000000..3be4bcb8159 --- /dev/null +++ b/src/shared/Auth/Sha1.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _AUTH_SHA1_H +#define _AUTH_SHA1_H + +#include "Common.h" +#include +#include +#include "Auth/BigNumber.h" + +class Sha1Hash +{ + public: + Sha1Hash(); + ~Sha1Hash(); + + void UpdateFinalizeBigNumbers(BigNumber *bn0, ...); + void UpdateBigNumbers(BigNumber *bn0, ...); + + void UpdateData(const uint8 *dta, int len); + void UpdateData(const std::string &str); + + void Initialize(); + void Finalize(); + + uint8 *GetDigest(void) { return mDigest; }; + int GetLength(void) { return SHA_DIGEST_LENGTH; }; + + BigNumber GetBigNumber(); + + private: + SHA_CTX mC; + uint8 mDigest[SHA_DIGEST_LENGTH]; +}; +#endif diff --git a/src/shared/Auth/md5.c b/src/shared/Auth/md5.c new file mode 100644 index 00000000000..3e9735e2dbb --- /dev/null +++ b/src/shared/Auth/md5.c @@ -0,0 +1,385 @@ +/* + Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software +in a product, an acknowledgment in the product documentation would be +appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +L. Peter Deutsch +ghost@aladdin.com + +*/ +/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321, whose + text is available at + http://www.ietf.org/rfc/rfc1321.txt + The code is derived from the text of the RFC, including the test suite + (section A.5) but excluding the rest of Appendix A. It does not include + any code or documentation that is identified in the RFC as being + copyrighted. + +The original and principal author of md5.c is L. Peter Deutsch +. Other authors are noted in the change history +that follows (in reverse chronological order): + +2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order +either statically or dynamically; added missing #include +in library. +2002-03-11 lpd Corrected argument list for main(), and added int return +type, in test program and T value program. +2002-02-21 lpd Added missing #include in test program. +2000-07-03 lpd Patched to eliminate warnings about "constant is +unsigned in ANSI C, signed in traditional"; made test program +self-checking. +1999-11-04 lpd Edited comments slightly for automatic TOC extraction. +1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). +1999-05-03 lpd Original version. +*/ + +#include "md5.h" +#include + +#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ +#ifdef ARCH_IS_BIG_ENDIAN +# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) +#else +# define BYTE_ORDER 0 +#endif + +#define T_MASK ((md5_word_t)~0) +#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) +#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) +#define T3 0x242070db +#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) +#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) +#define T6 0x4787c62a +#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) +#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) +#define T9 0x698098d8 +#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) +#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) +#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) +#define T13 0x6b901122 +#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) +#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) +#define T16 0x49b40821 +#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) +#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) +#define T19 0x265e5a51 +#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) +#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) +#define T22 0x02441453 +#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) +#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) +#define T25 0x21e1cde6 +#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) +#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) +#define T28 0x455a14ed +#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) +#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) +#define T31 0x676f02d9 +#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) +#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) +#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) +#define T35 0x6d9d6122 +#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) +#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) +#define T38 0x4bdecfa9 +#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) +#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) +#define T41 0x289b7ec6 +#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) +#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) +#define T44 0x04881d05 +#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) +#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) +#define T47 0x1fa27cf8 +#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) +#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) +#define T50 0x432aff97 +#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) +#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) +#define T53 0x655b59c3 +#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) +#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) +#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) +#define T57 0x6fa87e4f +#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) +#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) +#define T60 0x4e0811a1 +#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) +#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) +#define T63 0x2ad7d2bb +#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) + +static void +md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) +{ + md5_word_t + a = pms->abcd[0], b = pms->abcd[1], + c = pms->abcd[2], d = pms->abcd[3]; + md5_word_t t; + #if BYTE_ORDER > 0 + /* Define storage only for big-endian CPUs. */ + md5_word_t X[16]; + #else + /* Define storage for little-endian or both types of CPUs. */ + md5_word_t xbuf[16]; + const md5_word_t *X; + #endif + + { + #if BYTE_ORDER == 0 + /* + * Determine dynamically whether this is a big-endian or + * little-endian machine, since we can use a more efficient + * algorithm on the latter. + */ + static const int w = 1; + + if (*((const md5_byte_t *)&w)) /* dynamic little-endian */ + #endif + #if BYTE_ORDER <= 0 /* little-endian */ + { + /* + * On little-endian machines, we can process properly aligned + * data without copying it. + */ + if (!((data - (const md5_byte_t *)0) & 3)) + { + /* data are properly aligned */ + X = (const md5_word_t *)data; + } + else + { + /* not aligned */ + memcpy(xbuf, data, 64); + X = xbuf; + } + } + #endif + #if BYTE_ORDER == 0 + else /* dynamic big-endian */ + #endif + #if BYTE_ORDER >= 0 /* big-endian */ + { + /* + * On big-endian machines, we must arrange the bytes in the + * right order. + */ + const md5_byte_t *xp = data; + int i; + + # if BYTE_ORDER == 0 + X = xbuf; /* (dynamic only) */ + # else + # define xbuf X /* (static only) */ + # endif + for (i = 0; i < 16; ++i, xp += 4) + xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); + } + #endif + } + + #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) + + /* Round 1. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ + #define F(x, y, z) (((x) & (y)) | (~(x) & (z))) + #define SET(a, b, c, d, k, s, Ti)\ + t = a + F(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 7, T1); + SET(d, a, b, c, 1, 12, T2); + SET(c, d, a, b, 2, 17, T3); + SET(b, c, d, a, 3, 22, T4); + SET(a, b, c, d, 4, 7, T5); + SET(d, a, b, c, 5, 12, T6); + SET(c, d, a, b, 6, 17, T7); + SET(b, c, d, a, 7, 22, T8); + SET(a, b, c, d, 8, 7, T9); + SET(d, a, b, c, 9, 12, T10); + SET(c, d, a, b, 10, 17, T11); + SET(b, c, d, a, 11, 22, T12); + SET(a, b, c, d, 12, 7, T13); + SET(d, a, b, c, 13, 12, T14); + SET(c, d, a, b, 14, 17, T15); + SET(b, c, d, a, 15, 22, T16); + #undef SET + + /* Round 2. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ + #define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) + #define SET(a, b, c, d, k, s, Ti)\ + t = a + G(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 1, 5, T17); + SET(d, a, b, c, 6, 9, T18); + SET(c, d, a, b, 11, 14, T19); + SET(b, c, d, a, 0, 20, T20); + SET(a, b, c, d, 5, 5, T21); + SET(d, a, b, c, 10, 9, T22); + SET(c, d, a, b, 15, 14, T23); + SET(b, c, d, a, 4, 20, T24); + SET(a, b, c, d, 9, 5, T25); + SET(d, a, b, c, 14, 9, T26); + SET(c, d, a, b, 3, 14, T27); + SET(b, c, d, a, 8, 20, T28); + SET(a, b, c, d, 13, 5, T29); + SET(d, a, b, c, 2, 9, T30); + SET(c, d, a, b, 7, 14, T31); + SET(b, c, d, a, 12, 20, T32); + #undef SET + + /* Round 3. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ + #define H(x, y, z) ((x) ^ (y) ^ (z)) + #define SET(a, b, c, d, k, s, Ti)\ + t = a + H(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 5, 4, T33); + SET(d, a, b, c, 8, 11, T34); + SET(c, d, a, b, 11, 16, T35); + SET(b, c, d, a, 14, 23, T36); + SET(a, b, c, d, 1, 4, T37); + SET(d, a, b, c, 4, 11, T38); + SET(c, d, a, b, 7, 16, T39); + SET(b, c, d, a, 10, 23, T40); + SET(a, b, c, d, 13, 4, T41); + SET(d, a, b, c, 0, 11, T42); + SET(c, d, a, b, 3, 16, T43); + SET(b, c, d, a, 6, 23, T44); + SET(a, b, c, d, 9, 4, T45); + SET(d, a, b, c, 12, 11, T46); + SET(c, d, a, b, 15, 16, T47); + SET(b, c, d, a, 2, 23, T48); + #undef SET + + /* Round 4. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ + #define I(x, y, z) ((y) ^ ((x) | ~(z))) + #define SET(a, b, c, d, k, s, Ti)\ + t = a + I(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 6, T49); + SET(d, a, b, c, 7, 10, T50); + SET(c, d, a, b, 14, 15, T51); + SET(b, c, d, a, 5, 21, T52); + SET(a, b, c, d, 12, 6, T53); + SET(d, a, b, c, 3, 10, T54); + SET(c, d, a, b, 10, 15, T55); + SET(b, c, d, a, 1, 21, T56); + SET(a, b, c, d, 8, 6, T57); + SET(d, a, b, c, 15, 10, T58); + SET(c, d, a, b, 6, 15, T59); + SET(b, c, d, a, 13, 21, T60); + SET(a, b, c, d, 4, 6, T61); + SET(d, a, b, c, 11, 10, T62); + SET(c, d, a, b, 2, 15, T63); + SET(b, c, d, a, 9, 21, T64); + #undef SET + + /* Then perform the following additions. (That is increment each + of the four registers by the value it had before this block + was started.) */ + pms->abcd[0] += a; + pms->abcd[1] += b; + pms->abcd[2] += c; + pms->abcd[3] += d; +} + +void +md5_init(md5_state_t *pms) +{ + pms->count[0] = pms->count[1] = 0; + pms->abcd[0] = 0x67452301; + pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; + pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; + pms->abcd[3] = 0x10325476; +} + +void +md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) +{ + const md5_byte_t *p = data; + int left = nbytes; + int offset = (pms->count[0] >> 3) & 63; + md5_word_t nbits = (md5_word_t)(nbytes << 3); + + if (nbytes <= 0) + return; + + /* Update the message length. */ + pms->count[1] += nbytes >> 29; + pms->count[0] += nbits; + if (pms->count[0] < nbits) + ++pms->count[1]; + + /* Process an initial partial block. */ + if (offset) + { + int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); + + memcpy(pms->buf + offset, p, copy); + if (offset + copy < 64) + return; + p += copy; + left -= copy; + md5_process(pms, pms->buf); + } + + /* Process full blocks. */ + for (; left >= 64; p += 64, left -= 64) + md5_process(pms, p); + + /* Process a final partial block. */ + if (left) + memcpy(pms->buf, p, left); +} + +void +md5_finish(md5_state_t *pms, md5_byte_t digest[16]) +{ + static const md5_byte_t pad[64] = + { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + md5_byte_t data[8]; + int i; + + /* Save the length before padding. */ + for (i = 0; i < 8; ++i) + data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); + /* Pad to 56 bytes mod 64. */ + md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); + /* Append the length. */ + md5_append(pms, data, 8); + for (i = 0; i < 16; ++i) + digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); +} diff --git a/src/shared/Auth/md5.h b/src/shared/Auth/md5.h new file mode 100644 index 00000000000..fa2937e13e4 --- /dev/null +++ b/src/shared/Auth/md5.h @@ -0,0 +1,91 @@ +/* + Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software +in a product, an acknowledgment in the product documentation would be +appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +L. Peter Deutsch +ghost@aladdin.com + +*/ +/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321, whose + text is available at + http://www.ietf.org/rfc/rfc1321.txt + The code is derived from the text of the RFC, including the test suite + (section A.5) but excluding the rest of Appendix A. It does not include + any code or documentation that is identified in the RFC as being + copyrighted. + +The original and principal author of md5.h is L. Peter Deutsch +. Other authors are noted in the change history +that follows (in reverse chronological order): + +2002-04-13 lpd Removed support for non-ANSI compilers; removed +references to Ghostscript; clarified derivation from RFC 1321; +now handles byte order either statically or dynamically. +1999-11-04 lpd Edited comments slightly for automatic TOC extraction. +1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); +added conditionalization for C++ compilation from Martin +Purschke . +1999-05-03 lpd Original version. +*/ + +#ifndef md5_INCLUDED +# define md5_INCLUDED + +/* + * This package supports both compile-time and run-time determination of CPU + * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be + * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is + * defined as non-zero, the code will be compiled to run only on big-endian + * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to + * run on either big- or little-endian CPUs, but will run slightly less + * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. + */ + +typedef unsigned char md5_byte_t; /* 8-bit byte */ +typedef unsigned int md5_word_t; /* 32-bit word */ + +/* Define the state of the MD5 Algorithm. */ +typedef struct md5_state_s +{ + md5_word_t count[2]; /* message length in bits, lsw first */ + md5_word_t abcd[4]; /* digest buffer */ + md5_byte_t buf[64]; /* accumulate block */ +} md5_state_t; + +#ifdef __cplusplus +extern "C" +{ + #endif + + /* Initialize the algorithm. */ + void md5_init(md5_state_t *pms); + + /* Append a string to the message. */ + void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); + + /* Finish the message and return the digest. */ + void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); + + #ifdef __cplusplus +} /* end extern "C" */ +#endif +#endif /* md5_INCLUDED */ diff --git a/src/shared/Base.cpp b/src/shared/Base.cpp new file mode 100644 index 00000000000..9929cd41fdf --- /dev/null +++ b/src/shared/Base.cpp @@ -0,0 +1,67 @@ +/* + Base class interface + Copyright (C) 1998,1999 by Andrew Zabolotny + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "Base.h" + +Base::~Base () +{ +} + +/** + * Decrement object's reference count; as soon as the last reference + * to the object is removed, it is destroyed. + */ + +void Base::DecRef () +{ + if (!--RefCount) + delete this; +} + +/** + * Object initialization. The initial reference count is set to one; + * this means if you call DecRef() immediately after creating the object, + * it will be destroyed. + */ +Base::Base () +{ + RefCount = 1; +} + +/** + * Increment reference count. + * Every time when you copy a pointer to a object and store it for + * later use you MUST call IncRef() on it; this will allow to keep + * objects as long as they are referenced by some entity. + */ +void Base::IncRef () +{ + ++RefCount; + +} + +/** + * Query number of references to this object. + * I would rather prefer to have the reference counter strictly private, + * but sometimes, mostly for debugging, such a function can help. + */ +int Base::GetRefCount () +{ + return RefCount; +} diff --git a/src/shared/Base.h b/src/shared/Base.h new file mode 100644 index 00000000000..d5907fdf473 --- /dev/null +++ b/src/shared/Base.h @@ -0,0 +1,54 @@ +/* + Base class interface + Copyright (C) 1998,1999 by Andrew Zabolotny + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __BASE_H__ +#define __BASE_H__ + +#include "Common.h" + +/** + * This class is intended to be a base class for every other class. + * It defines the basic interface available for any object. + */ +class Base +{ + private: + /// Object reference count + int RefCount; + + protected: + /** + * Destroy this object. Destructor is virtual, because class contains + * virtual methods; also it is private because it is never intended + * to be called directly; use DecRef() instead: when reference counter + * reaches zero, the object will be destroyed. + */ + virtual ~Base (); + + public: + + Base (); + + void IncRef (); + + void DecRef (); + int GetRefCount (); + +}; +#endif // __BASE_H__ diff --git a/src/shared/ByteBuffer.h b/src/shared/ByteBuffer.h new file mode 100644 index 00000000000..d89466c2b1f --- /dev/null +++ b/src/shared/ByteBuffer.h @@ -0,0 +1,479 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _BYTEBUFFER_H +#define _BYTEBUFFER_H + +#include "Common.h" +#include "Errors.h" +#include "Log.h" +#include "Utilities/ByteConverter.h" + +class ByteBuffer +{ + public: + const static size_t DEFAULT_SIZE = 0x1000; + + // constructor + ByteBuffer(): _rpos(0), _wpos(0) + { + _storage.reserve(DEFAULT_SIZE); + } + // constructor + ByteBuffer(size_t res): _rpos(0), _wpos(0) + { + _storage.reserve(res); + } + // copy constructor + ByteBuffer(const ByteBuffer &buf): _rpos(buf._rpos), _wpos(buf._wpos), _storage(buf._storage) { } + + void clear() + { + _storage.clear(); + _rpos = _wpos = 0; + } + + template void append(T value) + { + EndianConvert(value); + append((uint8 *)&value, sizeof(value)); + } + + template void put(size_t pos,T value) + { + EndianConvert(value); + put(pos,(uint8 *)&value,sizeof(value)); + } + + ByteBuffer &operator<<(uint8 value) + { + append(value); + return *this; + } + ByteBuffer &operator<<(uint16 value) + { + append(value); + return *this; + } + ByteBuffer &operator<<(uint32 value) + { + append(value); + return *this; + } + ByteBuffer &operator<<(uint64 value) + { + append(value); + return *this; + } + + // signed as in 2e complement + ByteBuffer &operator<<(int8 value) + { + append(value); + return *this; + } + ByteBuffer &operator<<(int16 value) + { + append(value); + return *this; + } + ByteBuffer &operator<<(int32 value) + { + append(value); + return *this; + } + ByteBuffer &operator<<(int64 value) + { + append(value); + return *this; + } + + // floating points + ByteBuffer &operator<<(float value) + { + append(value); + return *this; + } + ByteBuffer &operator<<(double value) + { + append(value); + return *this; + } + ByteBuffer &operator<<(const std::string &value) + { + append((uint8 const *)value.c_str(), value.length()); + append((uint8)0); + return *this; + } + ByteBuffer &operator<<(const char *str) + { + append((uint8 const *)str, str ? strlen(str) : 0); + append((uint8)0); + return *this; + } + + ByteBuffer &operator>>(bool &value) + { + value = read() > 0 ? true : false; + return *this; + } + + ByteBuffer &operator>>(uint8 &value) + { + value = read(); + return *this; + } + ByteBuffer &operator>>(uint16 &value) + { + value = read(); + return *this; + } + ByteBuffer &operator>>(uint32 &value) + { + value = read(); + return *this; + } + ByteBuffer &operator>>(uint64 &value) + { + value = read(); + return *this; + } + + //signed as in 2e complement + ByteBuffer &operator>>(int8 &value) + { + value = read(); + return *this; + } + ByteBuffer &operator>>(int16 &value) + { + value = read(); + return *this; + } + ByteBuffer &operator>>(int32 &value) + { + value = read(); + return *this; + } + ByteBuffer &operator>>(int64 &value) + { + value = read(); + return *this; + } + + ByteBuffer &operator>>(float &value) + { + value = read(); + return *this; + } + ByteBuffer &operator>>(double &value) + { + value = read(); + return *this; + } + ByteBuffer &operator>>(std::string& value) + { + value.clear(); + while (rpos() < size()) // prevent crash at wrong string format in packet + { + char c=read(); + if (c==0) + break; + value+=c; + } + return *this; + } + + uint8 operator[](size_t pos) + { + return read(pos); + } + + size_t rpos() const { return _rpos; } + + size_t rpos(size_t rpos_) + { + _rpos = rpos_; + return _rpos; + }; + + size_t wpos() const { return _wpos; } + + size_t wpos(size_t wpos_) + { + _wpos = wpos_; + return _wpos; + } + + template T read() + { + T r=read(_rpos); + _rpos += sizeof(T); + return r; + }; + template T read(size_t pos) const + { + ASSERT(pos + sizeof(T) <= size() || PrintPosError(false,pos,sizeof(T))); + T val = *((T const*)&_storage[pos]); + EndianConvert(val); + return val; + } + + void read(uint8 *dest, size_t len) + { + ASSERT(_rpos + len <= size() || PrintPosError(false,_rpos,len)); + memcpy(dest, &_storage[_rpos], len); + _rpos += len; + } + + const uint8 *contents() const { return &_storage[0]; } + + size_t size() const { return _storage.size(); } + bool empty() const { return _storage.empty(); } + + void resize(size_t newsize) + { + _storage.resize(newsize); + _rpos = 0; + _wpos = size(); + }; + void reserve(size_t ressize) + { + if (ressize > size()) _storage.reserve(ressize); + }; + + void append(const std::string& str) + { + append((uint8 const*)str.c_str(),str.size() + 1); + } + void append(const char *src, size_t cnt) + { + return append((const uint8 *)src, cnt); + } + template + void append(const T *src, size_t cnt) + { + return append((const uint8 *)src, cnt*sizeof(T)); + } + void append(const uint8 *src, size_t cnt) + { + if (!cnt) return; + + ASSERT(size() < 10000000); + + if (_storage.size() < _wpos + cnt) + _storage.resize(_wpos + cnt); + memcpy(&_storage[_wpos], src, cnt); + _wpos += cnt; + } + void append(const ByteBuffer& buffer) + { + if(buffer.size()) append(buffer.contents(),buffer.size()); + } + + void appendPackGUID(uint64 guid) + { + size_t mask_position = wpos(); + *this << uint8(0); + for(uint8 i = 0; i < 8; i++) + { + if(guid & 0xFF) + { + _storage[mask_position] |= uint8(1<>= 8; + } + } + + void put(size_t pos, const uint8 *src, size_t cnt) + { + ASSERT(pos + cnt <= size() || PrintPosError(true,pos,cnt)); + memcpy(&_storage[pos], src, cnt); + } + void print_storage() + { + if(!sLog.IsOutDebug()) // optimize disabled debug output + return; + + sLog.outDebug("STORAGE_SIZE: %u", size() ); + for(uint32 i = 0; i < size(); i++) + sLog.outDebugInLine("%u - ", read(i) ); + sLog.outDebug(" "); + } + + void textlike() + { + if(!sLog.IsOutDebug()) // optimize disabled debug output + return; + + sLog.outDebug("STORAGE_SIZE: %u", size() ); + for(uint32 i = 0; i < size(); i++) + sLog.outDebugInLine("%c", read(i) ); + sLog.outDebug(" "); + } + + void hexlike() + { + if(!sLog.IsOutDebug()) // optimize disabled debug output + return; + + uint32 j = 1, k = 1; + sLog.outDebug("STORAGE_SIZE: %u", size() ); + + if(sLog.IsIncludeTime()) + sLog.outDebugInLine(" "); + + for(uint32 i = 0; i < size(); i++) + { + if ((i == (j*8)) && ((i != (k*16)))) + { + if (read(i) < 0x0F) + { + sLog.outDebugInLine("| 0%X ", read(i) ); + } + else + { + sLog.outDebugInLine("| %X ", read(i) ); + } + ++j; + } + else if (i == (k*16)) + { + if (read(i) < 0x0F) + { + sLog.outDebugInLine("\n"); + if(sLog.IsIncludeTime()) + sLog.outDebugInLine(" "); + + sLog.outDebugInLine("0%X ", read(i) ); + } + else + { + sLog.outDebugInLine("\n"); + if(sLog.IsIncludeTime()) + sLog.outDebugInLine(" "); + + sLog.outDebugInLine("%X ", read(i) ); + } + + ++k; + ++j; + } + else + { + if (read(i) < 0x0F) + { + sLog.outDebugInLine("0%X ", read(i) ); + } + else + { + sLog.outDebugInLine("%X ", read(i) ); + } + } + } + sLog.outDebugInLine("\n"); + } + + protected: + bool PrintPosError(bool add, size_t pos, size_t esize) const + { + sLog.outError("ERROR: Attempt %s in ByteBuffer (pos: %u size: %u) value with size: %u",(add ? "put" : "get"),pos, size(), esize); + + // assert must fail after function call + return false; + } + + size_t _rpos, _wpos; + std::vector _storage; +}; + +template ByteBuffer &operator<<(ByteBuffer &b, std::vector v) +{ + b << (uint32)v.size(); + for (typename std::vector::iterator i = v.begin(); i != v.end(); i++) + { + b << *i; + } + return b; +} + +template ByteBuffer &operator>>(ByteBuffer &b, std::vector &v) +{ + uint32 vsize; + b >> vsize; + v.clear(); + while(vsize--) + { + T t; + b >> t; + v.push_back(t); + } + return b; +} + +template ByteBuffer &operator<<(ByteBuffer &b, std::list v) +{ + b << (uint32)v.size(); + for (typename std::list::iterator i = v.begin(); i != v.end(); i++) + { + b << *i; + } + return b; +} + +template ByteBuffer &operator>>(ByteBuffer &b, std::list &v) +{ + uint32 vsize; + b >> vsize; + v.clear(); + while(vsize--) + { + T t; + b >> t; + v.push_back(t); + } + return b; +} + +template ByteBuffer &operator<<(ByteBuffer &b, std::map &m) +{ + b << (uint32)m.size(); + for (typename std::map::iterator i = m.begin(); i != m.end(); i++) + { + b << i->first << i->second; + } + return b; +} + +template ByteBuffer &operator>>(ByteBuffer &b, std::map &m) +{ + uint32 msize; + b >> msize; + m.clear(); + while(msize--) + { + K k; + V v; + b >> k >> v; + m.insert(make_pair(k, v)); + } + return b; +} +#endif diff --git a/src/shared/Common.cpp b/src/shared/Common.cpp new file mode 100644 index 00000000000..d64404a6e91 --- /dev/null +++ b/src/shared/Common.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" + +char const* localeNames[MAX_LOCALE] = { + "enUS", + "koKR", + "frFR", + "deDE", + "zhCN", + "zhTW", + "esES", + "esMX", + "ruRU" +}; + +LocaleConstant GetLocaleByName(std::string name) +{ + for(uint32 i = 0; i < MAX_LOCALE; ++i) + if(name==localeNames[i]) + return LocaleConstant(i); + + return LOCALE_enUS; // including enGB case +} diff --git a/src/shared/Common.h b/src/shared/Common.h new file mode 100644 index 00000000000..4e93ad71eb2 --- /dev/null +++ b/src/shared/Common.h @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOSSERVER_COMMON_H +#define MANGOSSERVER_COMMON_H + +#include "Platform/Define.h" + +#if COMPILER == COMPILER_MICROSOFT + +#pragma warning(disable:4996) + +#ifndef __SHOW_STUPID_WARNINGS__ + +#pragma warning(disable:4244) + +#pragma warning(disable:4267) + +#pragma warning(disable:4800) + +#pragma warning(disable:4018) + +#pragma warning(disable:4311) + +#pragma warning(disable:4305) + +#pragma warning(disable:4005) +#endif // __SHOW_STUPID_WARNINGS__ +#endif // __GNUC__ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "Utilities/HashMap.h" +#include +#include +#include +#include +#include +#include +#include + +#if PLATFORM == PLATFORM_WINDOWS +#define STRCASECMP stricmp +#else +#define STRCASECMP strcasecmp +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if PLATFORM == PLATFORM_WINDOWS +# define FD_SETSIZE 1024 +# include +// XP winver - needed to compile with standard leak check in MemoryLeaks.h +// uncomment later if needed +//#define _WIN32_WINNT 0x0501 +# include +//#undef WIN32_WINNT +#else +# include +# include +# include +# include +# include +# include +#endif + +#if COMPILER == COMPILER_MICROSOFT + +#include + +#define I64FMT "%016I64X" +#define I64FMTD "%I64u" +#define SI64FMTD "%I64d" +#define snprintf _snprintf +#define atoll __atoi64 +#define vsnprintf _vsnprintf +#define strdup _strdup +#define finite(X) _finite(X) + +#else + +#define stricmp strcasecmp +#define strnicmp strncasecmp +#define I64FMT "%016llX" +#define I64FMTD "%llu" +#define SI64FMTD "%lld" +#endif + +inline float finiteAlways(float f) { return finite(f) ? f : 0.0f; } + +#define atol(a) strtoul( a, NULL, 10) + +#define STRINGIZE(a) #a + +enum TimeConstants +{ + MINUTE = 60, + HOUR = MINUTE*60, + DAY = HOUR*24, + MONTH = DAY*30 +}; + +enum AccountTypes +{ + SEC_PLAYER = 0, + SEC_MODERATOR = 1, + SEC_GAMEMASTER = 2, + SEC_ADMINISTRATOR = 3 +}; + +enum LocaleConstant +{ + LOCALE_enUS = 0, + LOCALE_koKR = 1, + LOCALE_frFR = 2, + LOCALE_deDE = 3, + LOCALE_zhCN = 4, + LOCALE_zhTW = 5, + LOCALE_esES = 6, + LOCALE_esMX = 7, + LOCALE_ruRU = 8 +}; + +#define MAX_LOCALE 9 + +extern char const* localeNames[MAX_LOCALE]; + +LocaleConstant GetLocaleByName(std::string name); + +// we always use stdlibc++ std::max/std::min, undefine some not C++ standard defines (Win API and some pother platforms) +#ifdef max +#undef max +#endif + +#ifdef min +#undef min +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#endif diff --git a/src/shared/Config/Config.cpp b/src/shared/Config/Config.cpp new file mode 100644 index 00000000000..292cf390276 --- /dev/null +++ b/src/shared/Config/Config.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ConfigEnv.h" +#include "Policies/SingletonImp.h" + +INSTANTIATE_SINGLETON_1(Config); + +Config::Config() : mIgnoreCase(true), mConf(NULL) +{ +} + + +Config::~Config() +{ + delete mConf; +} + + +bool Config::SetSource(const char *file, bool ignorecase) +{ + mIgnoreCase = ignorecase; + mFilename = file; + + return Reload(); +} + +bool Config::Reload() +{ + delete mConf; + + mConf = new DOTCONFDocument(mIgnoreCase ? + DOTCONFDocument::CASEINSENSETIVE : + DOTCONFDocument::CASESENSETIVE); + + if (mConf->setContent(mFilename.c_str()) == -1) + { + delete mConf; + mConf = NULL; + return false; + } + + return true; +} + +bool Config::GetString(const char* name, std::string *value) +{ + if(!mConf) + return false; + + DOTCONFDocumentNode const *node = mConf->findNode(name); + if(!node || !node->getValue()) + return false; + + *value = node->getValue(); + + return true; +} + +bool Config::GetString(const char* name, char const **value) +{ + if(!mConf) + return false; + + DOTCONFDocumentNode const *node = mConf->findNode(name); + if(!node || !node->getValue()) + return false; + + *value = node->getValue(); + + return true; +} + + +std::string Config::GetStringDefault(const char* name, const char* def) +{ + if(!mConf) + return std::string(def); + + DOTCONFDocumentNode const *node = mConf->findNode(name); + if(!node || !node->getValue()) + return std::string(def); + + return std::string(node->getValue()); +} + + +bool Config::GetBool(const char* name, bool *value) +{ + if(!mConf) + return false; + + DOTCONFDocumentNode const *node = mConf->findNode(name); + if(!node || !node->getValue()) + return false; + + const char* str = node->getValue(); + if(strcmp(str, "true") == 0 || strcmp(str, "TRUE") == 0 || + strcmp(str, "yes") == 0 || strcmp(str, "YES") == 0 || + strcmp(str, "1") == 0) + { + *value = true; + } + else + *value = false; + + return true; +} + + +bool Config::GetBoolDefault(const char* name, const bool def) +{ + bool val; + return GetBool(name, &val) ? val : def; +} + + +bool Config::GetInt(const char* name, int *value) +{ + if(!mConf) + return false; + + DOTCONFDocumentNode const *node = mConf->findNode(name); + if(!node || !node->getValue()) + return false; + + *value = atoi(node->getValue()); + + return true; +} + + +bool Config::GetFloat(const char* name, float *value) +{ + if(!mConf) + return false; + + DOTCONFDocumentNode const *node = mConf->findNode(name); + if(!node || !node->getValue()) + return false; + + *value = atof(node->getValue()); + + return true; +} + + +int Config::GetIntDefault(const char* name, const int def) +{ + int val; + return GetInt(name, &val) ? val : def; +} + + +float Config::GetFloatDefault(const char* name, const float def) +{ + float val; + return (GetFloat(name, &val) ? val : def); +} diff --git a/src/shared/Config/Config.h b/src/shared/Config/Config.h new file mode 100644 index 00000000000..bc753f6d33a --- /dev/null +++ b/src/shared/Config/Config.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef CONFIG_H +#define CONFIG_H + +#include +#include "Platform/Define.h" + +class DOTCONFDocument; + +class MANGOS_DLL_SPEC Config +{ + public: + Config(); + ~Config(); + + bool SetSource(const char *file, bool ignorecase = true); + bool Reload(); + + bool GetString(const char* name, std::string *value); + bool GetString(const char* name, char const **value); + std::string GetStringDefault(const char* name, const char* def); + + bool GetBool(const char* name, bool *value); + bool GetBoolDefault(const char* name, const bool def = false); + + bool GetInt(const char* name, int *value); + int GetIntDefault(const char* name, const int def); + + bool GetFloat(const char* name, float *value); + float GetFloatDefault(const char* name, const float def); + + std::string GetFilename() const { return mFilename; } + private: + std::string mFilename; + bool mIgnoreCase; + DOTCONFDocument *mConf; +}; + +#define sConfig MaNGOS::Singleton::Instance() + +#endif diff --git a/src/shared/Config/ConfigEnv.h b/src/shared/Config/ConfigEnv.h new file mode 100644 index 00000000000..7ef06f015a2 --- /dev/null +++ b/src/shared/Config/ConfigEnv.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#if !defined(CONFIGENVIRONMENT_H) + +#define CONFIGENVIRONMENT_H + +#include "Common.h" +#include "dotconfpp/dotconfpp.h" +#include "Config.h" +#include "Log.h" + +#endif diff --git a/src/shared/Config/ConfigLibrary.vcproj b/src/shared/Config/ConfigLibrary.vcproj new file mode 100644 index 00000000000..a8f1fc322e7 --- /dev/null +++ b/src/shared/Config/ConfigLibrary.vcproj @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/shared/Config/Makefile.am b/src/shared/Config/Makefile.am new file mode 100644 index 00000000000..e36f80a2fc4 --- /dev/null +++ b/src/shared/Config/Makefile.am @@ -0,0 +1,40 @@ +# Copyright (C) 2005-2008 MaNGOS +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## Process this file with automake to produce Makefile.in + +## Sub-directories to parse + +## CPP flags for includes, defines, etc. +AM_CPPFLAGS = $(MYSQL_INCLUDES) $(POSTGRE_INCLUDES) -I$(top_builddir)/src/shared -I$(srcdir) -I$(srcdir)/../../../dep/include -I$(srcdir)/../../framework -I$(srcdir)/../../shared -I$(srcdir)/../../../dep/include/g3dlite + +## Build MaNGOS shared library and its parts as convenience library. +# All libraries will be convenience libraries. Might be changed to shared +# later. +noinst_LIBRARIES = libmangosconfig.a + +libmangosconfig_a_SOURCES = \ + dotconfpp/dotconfpp.cpp \ + dotconfpp/dotconfpp.h \ + dotconfpp/mempool.cpp \ + dotconfpp/mempool.h \ + Config.cpp \ + Config.h \ + ConfigEnv.h + +# VC++ project workspace for dotconfpp +EXTRA_DIST = \ + ConfigLibrary.vcproj diff --git a/src/shared/Config/dotconfpp/dotconfpp.cpp b/src/shared/Config/dotconfpp/dotconfpp.cpp new file mode 100644 index 00000000000..60008747ad1 --- /dev/null +++ b/src/shared/Config/dotconfpp/dotconfpp.cpp @@ -0,0 +1,583 @@ + +#include "Common.h" + +#include "dotconfpp.h" + +#if !defined(R_OK) +#define R_OK 04 +#endif + +DOTCONFDocumentNode::DOTCONFDocumentNode():previousNode(NULL), nextNode(NULL), parentNode(NULL), childNode(NULL), + values(NULL), valuesCount(0), + name(NULL), lineNum(0), fileName(NULL), closed(true) +{ +} + +DOTCONFDocumentNode::~DOTCONFDocumentNode() +{ + free(name); + if(values != NULL){ + for(int i = 0 ; i < valuesCount; i++){ + free(values[i]); + } + free(values); + } +} + +void DOTCONFDocumentNode::pushValue(char * _value) +{ + ++valuesCount; + values = (char**)realloc(values, valuesCount*sizeof(char*)); + values[valuesCount-1] = strdup(_value); +} + +const char* DOTCONFDocumentNode::getValue(int index) const +{ + if(index >= valuesCount){ + return NULL; + } + return values[index]; +} + +DOTCONFDocument::DOTCONFDocument(DOTCONFDocument::CaseSensitive caseSensitivity): + mempool(NULL), + curParent(NULL), curPrev(NULL), curLine(0), file(NULL), fileName(NULL) +{ + if(caseSensitivity == CASESENSETIVE){ + cmp_func = strcmp; + } else { + cmp_func = strcasecmp; + } + + mempool = new AsyncDNSMemPool(1024); + mempool->initialize(); +} + +DOTCONFDocument::~DOTCONFDocument() +{ + for(std::list::iterator i = nodeTree.begin(); i != nodeTree.end(); i++){ + delete(*i); + } + for(std::list::iterator i = requiredOptions.begin(); i != requiredOptions.end(); i++){ + free(*i); + } + for(std::list::iterator i = processedFiles.begin(); i != processedFiles.end(); i++){ + free(*i); + } + free(fileName); + delete mempool; +} + +int DOTCONFDocument::cleanupLine(char * line) +{ + char * start = line; + char * bg = line; + bool multiline = false; + bool concat = false; + char * word = NULL; + + if(!words.empty() && quoted) + concat = true; + + while(*line){ + if((*line == '#' || *line == ';') && !quoted){ + *bg = 0; + if(strlen(start)){ + + if(concat){ + word = (char*)mempool->alloc(strlen(words.back())+strlen(start)+1); + strcpy(word, words.back()); + strcat(word, start); + words.pop_back(); + concat = false; + } else { + word = mempool->strdup(start); + } + words.push_back(word); + } + break; + } + if(*line == '=' && !quoted){ + *line = ' ';continue; + } + + // Allowing \" in there causes problems with directory paths + // like "C:\MaNGOS\" + //if(*line == '\\' && (*(line+1) == '"' || *(line+1) == '\'')){ + if(*line == '\\' && (*(line+1) == '\'')) { + *bg++ = *(line+1); + line+=2; continue; + } + if(*line == '\\' && *(line+1) == 'n'){ + *bg++ = '\n'; + line+=2; continue; + } + if(*line == '\\' && *(line+1) == 'r'){ + *bg++ = '\r'; + line+=2; continue; + } + if(*line == '\\' && (*(line+1) == '\n' || *(line+1) == '\r')){ + *bg = 0; + if(strlen(start)){ + + if(concat){ + word = (char*)mempool->alloc(strlen(words.back())+strlen(start)+1); + strcpy(word, words.back()); + strcat(word, start); + words.pop_back(); + concat = false; + } else { + word = mempool->strdup(start); + } + words.push_back(word); + } + multiline = true; + break; + } + if(*line == '"' || *line == '\''){ + quoted = !quoted; + ++line; continue; + } + if(isspace(*line) && !quoted){ + *bg++ = 0; + if(strlen(start)){ + + if(concat){ + word = (char*)mempool->alloc(strlen(words.back())+strlen(start)+1); + strcpy(word, words.back()); + strcat(word, start); + words.pop_back(); + concat = false; + } else { + word = mempool->strdup(start); + } + words.push_back(word); + } + start = bg; + while(isspace(*++line)) {} + + continue; + } + *bg++ = *line++; + } + + if(quoted && !multiline){ + error(curLine, fileName, "unterminated quote"); + return -1; + } + + return multiline?1:0; +} + +int DOTCONFDocument::parseLine() +{ + char * word = NULL; + char * nodeName = NULL; + char * nodeValue = NULL; + DOTCONFDocumentNode * tagNode = NULL; + bool newNode = false; + + for(std::list::iterator i = words.begin(); i != words.end(); i++) { + word = *i; + + if(*word == '<'){ + newNode = true; + } + + if(newNode){ + nodeValue = NULL; + nodeName = NULL; + newNode = false; + } + + size_t wordLen = strlen(word); + if(word[wordLen-1] == '>'){ + word[wordLen-1] = 0; + newNode = true; + } + + if(nodeName == NULL){ + nodeName = word; + bool closed = true; + if(*nodeName == '<'){ + if(*(nodeName+1) != '/'){ + ++nodeName; + closed = false; + } else { + nodeName+=2; + std::list::reverse_iterator itr=nodeTree.rbegin(); + for(; itr!=nodeTree.rend(); ++itr){ + if(!cmp_func(nodeName, (*itr)->name) && !(*itr)->closed){ + (*itr)->closed = true; + curParent = (*itr)->parentNode; + curPrev = *itr; + break; + } + } + if(itr==nodeTree.rend()){ + error(curLine, fileName, "not matched closing tag ", nodeName); + return -1; + } + continue; + } + } + tagNode = new DOTCONFDocumentNode; + tagNode->name = strdup(nodeName); + tagNode->document = this; + tagNode->fileName = processedFiles.back(); + tagNode->lineNum = curLine; + tagNode->closed = closed; + if(!nodeTree.empty()){ + DOTCONFDocumentNode * prev = nodeTree.back(); + if(prev->closed){ + + curPrev->nextNode = tagNode; + tagNode->previousNode = curPrev; + tagNode->parentNode = curParent; + + } else { + prev->childNode = tagNode; + tagNode->parentNode = prev; + curParent = prev; + } + } + nodeTree.push_back(tagNode); + curPrev = tagNode; + } else { + nodeValue = word; + tagNode->pushValue(nodeValue); + } + } + + return 0; +} +int DOTCONFDocument::parseFile(DOTCONFDocumentNode * _parent) +{ + char str[512]; + int ret = 0; + curLine = 0; + curParent = _parent; + + quoted = false; + size_t slen = 0; + + while(fgets(str, 511, file)){ + ++curLine; + slen = strlen(str); + if( slen >= 510 ){ + error(curLine, fileName, "warning: line too long"); + } + if(str[slen-1] != '\n'){ + str[slen] = '\n'; + str[slen+1] = 0; + } + if((ret = cleanupLine(str)) == -1){ + break; + } + if(ret == 0){ + if(!words.empty()){ + ret = parseLine(); + mempool->free(); + words.clear(); + if(ret == -1){ + break; + } + } + } + } + + return ret; +} + +int DOTCONFDocument::checkConfig(const std::list::iterator & from) +{ + int ret = 0; + + DOTCONFDocumentNode * tagNode = NULL; + int vi = 0; + for(std::list::iterator i = from; i != nodeTree.end(); i++){ + tagNode = *i; + if(!tagNode->closed){ + error(tagNode->lineNum, tagNode->fileName, "unclosed tag %s", tagNode->name); + ret = -1; + break; + } + vi = 0; + while( vi < tagNode->valuesCount ){ + + if(strstr(tagNode->values[vi], "${") && strchr(tagNode->values[vi], '}') ){ + ret = macroSubstitute(tagNode, vi ); + mempool->free(); + if(ret == -1){ + break; + } + } + ++vi; + } + if(ret == -1){ + break; + } + } + + return ret; +} + +int DOTCONFDocument::setContent(const char * _fileName) +{ + int ret = 0; + char realpathBuf[PATH_MAX]; + + if(realpath(_fileName, realpathBuf) == NULL){ + error(0, NULL, "realpath(%s) failed: %s", _fileName, strerror(errno)); + return -1; + } + + fileName = strdup(realpathBuf); + + processedFiles.push_back(strdup(realpathBuf)); + + if(( file = fopen(fileName, "r")) == NULL){ + error(0, NULL, "failed to open file '%s': %s", fileName, strerror(errno)); + return -1; + } + + ret = parseFile(); + + (void) fclose(file); + + if(!ret){ + + if( (ret = checkConfig(nodeTree.begin())) == -1){ + return -1; + } + + std::list::iterator from; + DOTCONFDocumentNode * tagNode = NULL; + int vi = 0; + for(std::list::iterator i = nodeTree.begin(); i!=nodeTree.end(); i++){ + tagNode = *i; + if(!cmp_func("DOTCONFPPIncludeFile", tagNode->name)){ + vi = 0; + while( vi < tagNode->valuesCount ){ + if(access(tagNode->values[vi], R_OK) == -1){ + error(tagNode->lineNum, tagNode->fileName, "%s: %s", tagNode->values[vi], strerror(errno)); + return -1; + } + if(realpath(tagNode->values[vi], realpathBuf) == NULL){ + error(tagNode->lineNum, tagNode->fileName, "realpath(%s) failed: %s", tagNode->values[vi], strerror(errno)); + return -1; + } + + bool processed = false; + for(std::list::const_iterator itInode = processedFiles.begin(); itInode != processedFiles.end(); itInode++){ + if(!strcmp(*itInode, realpathBuf)){ + processed = true; + break; + } + } + if(processed){ + break; + } + + processedFiles.push_back(strdup(realpathBuf)); + + file = fopen(tagNode->values[vi], "r"); + if(file == NULL){ + error(tagNode->lineNum, fileName, "failed to open file '%s': %s", tagNode->values[vi], strerror(errno)); + return -1; + } + + fileName = strdup(realpathBuf); + from = nodeTree.end(); --from; + + ret = parseFile(); + (void) fclose(file); + if(ret == -1) + return -1; + if(checkConfig(++from) == -1){ + return -1; + } + ++vi; + } + } + } + + + if(!requiredOptions.empty()) + ret = checkRequiredOptions(); + } + + return ret; +} + +int DOTCONFDocument::checkRequiredOptions() +{ + for(std::list::const_iterator ci = requiredOptions.begin(); ci != requiredOptions.end(); ci++){ + bool matched = false; + for(std::list::iterator i = nodeTree.begin(); i!=nodeTree.end(); i++){ + if(!cmp_func((*i)->name, *ci)){ + matched = true; + break; + } + } + if(!matched){ + error(0, NULL, "required option '%s' not specified", *ci); + return -1; + } + } + return 0; +} + +void DOTCONFDocument::error(int lineNum, const char * fileName_, const char * fmt, ...) +{ + va_list args; + va_start(args, fmt); + + size_t len = (lineNum!=0?strlen(fileName_):0) + strlen(fmt) + 50; + char * buf = (char*)mempool->alloc(len); + + if(lineNum) + (void) snprintf(buf, len, "DOTCONF++: file '%s', line %d: %s\n", fileName_, lineNum, fmt); + else + (void) snprintf(buf, len, "DOTCONF++: %s\n", fmt); + + (void) vfprintf(stderr, buf, args); + + va_end(args); +} + +char * DOTCONFDocument::getSubstitution(char * macro, int lineNum) +{ + char * buf = NULL; + char * variable = macro+2; + + char * endBr = strchr(macro, '}'); + + if(!endBr){ + error(lineNum, fileName, "unterminated '{'"); + return NULL; + } + *endBr = 0; + + char * defaultValue = strchr(variable, ':'); + + if(defaultValue){ + *defaultValue++ = 0; + if(*defaultValue != '-'){ + error(lineNum, fileName, "incorrect macro substitution syntax"); + return NULL; + } + ++defaultValue; + if(*defaultValue == '"' || *defaultValue == '\''){ + ++defaultValue; + defaultValue[strlen(defaultValue)-1] = 0; + } + } else { + defaultValue = NULL; + } + + char * subs = getenv(variable); + if( subs ){ + buf = mempool->strdup(subs); + } else { + std::list::iterator i = nodeTree.begin(); + DOTCONFDocumentNode * tagNode = NULL; + for(; i!=nodeTree.end(); i++){ + tagNode = *i; + if(!cmp_func(tagNode->name, variable)){ + if(tagNode->valuesCount != 0){ + buf = mempool->strdup(tagNode->values[0]); + break; + } + } + } + if( i == nodeTree.end() ){ + if( defaultValue ){ + buf = mempool->strdup(defaultValue); + } else { + error(lineNum, fileName, "substitution not found and default value not given"); + return NULL; + } + } + } + return buf; +} + +int DOTCONFDocument::macroSubstitute(DOTCONFDocumentNode * tagNode, int valueIndex) +{ + int ret = 0; + char * macro = tagNode->values[valueIndex]; + size_t valueLen = strlen(tagNode->values[valueIndex])+1; + char * value = (char*)mempool->alloc(valueLen); + char * v = value; + char * subs = NULL; + + while(*macro){ + if(*macro == '$' && *(macro+1) == '{'){ + char * m = strchr(macro, '}'); + subs = getSubstitution(macro, tagNode->lineNum); + if(subs == NULL){ + ret = -1; + break; + } + macro = m + 1; + *v = 0; + v = (char*)mempool->alloc(strlen(value)+strlen(subs)+valueLen); + strcpy(v, value); + value = strcat(v, subs); + v = value + strlen(value); + continue; + } + *v++ = *macro++; + } + *v = 0; + + free(tagNode->values[valueIndex]); + tagNode->values[valueIndex] = strdup(value); + return ret; +} + +const DOTCONFDocumentNode * DOTCONFDocument::getFirstNode() const +{ + if ( !nodeTree.empty() ) { + return *nodeTree.begin(); + } else { + return NULL; + } +} + +const DOTCONFDocumentNode * DOTCONFDocument::findNode(const char * nodeName, const DOTCONFDocumentNode * parentNode, const DOTCONFDocumentNode * startNode) const +{ + + + std::list::const_iterator i = nodeTree.begin(); + + if(startNode == NULL) + startNode = parentNode; + + if(startNode != NULL){ + while( i != nodeTree.end() && (*i) != startNode ){ + ++i; + } + if( i != nodeTree.end() ) ++i; + } + + for(; i!=nodeTree.end(); i++){ + + if((*i)->parentNode != parentNode){ + continue; + } + if(!cmp_func(nodeName, (*i)->name)){ + return *i; + } + } + return NULL; +} + +void DOTCONFDocument::setRequiredOptionNames(const char ** requiredOptionNames) +{ + while(*requiredOptionNames){ + requiredOptions.push_back(strdup( *requiredOptionNames )); + ++requiredOptionNames; + } +} diff --git a/src/shared/Config/dotconfpp/dotconfpp.h b/src/shared/Config/dotconfpp/dotconfpp.h new file mode 100644 index 00000000000..15c4f7fcd78 --- /dev/null +++ b/src/shared/Config/dotconfpp/dotconfpp.h @@ -0,0 +1,110 @@ + + + +#ifndef DOTCONFPP_H +#define DOTCONFPP_H + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#ifdef WIN32 +#define PATH_MAX _MAX_PATH +#define snprintf _snprintf +#define strcasecmp stricmp +#define realpath(path,resolved_path) _fullpath(resolved_path, path, _MAX_PATH) +#include +#else +#include +#include +#include +#include +#endif + +#include "mempool.h" + +class DOTCONFDocument; + +class DOTCONFDocumentNode +{ +friend class DOTCONFDocument; +private: + DOTCONFDocumentNode * previousNode; + DOTCONFDocumentNode * nextNode; + DOTCONFDocumentNode * parentNode; + DOTCONFDocumentNode * childNode; + char ** values; + int valuesCount; + char * name; + const DOTCONFDocument * document; + int lineNum; + char * fileName; + bool closed; + + void pushValue(char * _value); + +public: + DOTCONFDocumentNode(); + ~DOTCONFDocumentNode(); + + const char * getConfigurationFileName()const { return fileName; } + int getConfigurationLineNumber() const { return lineNum; } + + const DOTCONFDocumentNode * getNextNode() const { return nextNode; } + const DOTCONFDocumentNode * getPreviuosNode() const { return previousNode; } + const DOTCONFDocumentNode * getParentNode() const { return parentNode; } + const DOTCONFDocumentNode * getChildNode() const { return childNode; } + const char* getValue(int index = 0) const; + const char * getName() const { return name; } + const DOTCONFDocument * getDocument() const { return document; } +}; + +class DOTCONFDocument +{ +public: + enum CaseSensitive { CASESENSETIVE, CASEINSENSETIVE }; +protected: + AsyncDNSMemPool * mempool; +private: + DOTCONFDocumentNode * curParent; + DOTCONFDocumentNode * curPrev; + int curLine; + bool quoted; + std::list nodeTree; + std::list requiredOptions; + std::list processedFiles; + FILE * file; + char * fileName; + std::list words; + int (*cmp_func)(const char *, const char *); + + int checkRequiredOptions(); + int parseLine(); + int parseFile(DOTCONFDocumentNode * _parent = NULL); + int checkConfig(const std::list::iterator & from); + int cleanupLine(char * line); + char * getSubstitution(char * macro, int lineNum); + int macroSubstitute(DOTCONFDocumentNode * tagNode, int valueIndex); + +protected: + virtual void error(int lineNum, const char * fileName, const char * fmt, ...) ATTR_PRINTF(4,5); + +public: + DOTCONFDocument(CaseSensitive caseSensitivity = CASESENSETIVE); + virtual ~DOTCONFDocument(); + + int setContent(const char * _fileName); + + void setRequiredOptionNames(const char ** requiredOptionNames); + const DOTCONFDocumentNode * getFirstNode() const; + const DOTCONFDocumentNode * findNode(const char * nodeName, const DOTCONFDocumentNode * parentNode = NULL, const DOTCONFDocumentNode * startNode = NULL) const; +}; + +#endif diff --git a/src/shared/Config/dotconfpp/mempool.cpp b/src/shared/Config/dotconfpp/mempool.cpp new file mode 100644 index 00000000000..cf589ffb2bc --- /dev/null +++ b/src/shared/Config/dotconfpp/mempool.cpp @@ -0,0 +1,100 @@ + + + +#include "mempool.h" + +AsyncDNSMemPool::PoolChunk::PoolChunk(size_t _size): + pool(NULL), pos(0), size(_size) +{ + pool = ::malloc(size); +} + +AsyncDNSMemPool::PoolChunk::~PoolChunk() +{ + ::free(pool); +} + +AsyncDNSMemPool::AsyncDNSMemPool(size_t _defaultSize): + chunks(NULL), chunksCount(0), defaultSize(_defaultSize), + poolUsage(0), poolUsageCounter(0) +{ +} + +AsyncDNSMemPool::~AsyncDNSMemPool() +{ + for(size_t i = 0; isize - chunk->pos) >= size){ + chunk->pos += size; + return ((char*)chunk->pool) + chunk->pos - size; + } + } + addNewChunk(size); + chunks[chunksCount-1]->pos = size; + return chunks[chunksCount-1]->pool; +} + +void AsyncDNSMemPool::free() +{ + size_t pu = 0; + size_t psz = 0; + ++poolUsageCounter; + + for(size_t i = 0; ipos; + psz += chunks[i]->size; + chunks[i]->pos = 0; + } + poolUsage=(poolUsage>pu)?poolUsage:pu; + + if(poolUsageCounter >= 10 && chunksCount > 1){ + psz -= chunks[chunksCount-1]->size; + if(poolUsage < psz){ + --chunksCount; + delete chunks[chunksCount]; + } + poolUsage = 0; + poolUsageCounter = 0; + } +} + +void * AsyncDNSMemPool::calloc(size_t size) +{ + return ::memset(this->alloc(size), 0, size); +} + +char * AsyncDNSMemPool::strdup(const char *str) +{ + return ::strcpy((char*)this->alloc(strlen(str)+1), str); +} diff --git a/src/shared/Config/dotconfpp/mempool.h b/src/shared/Config/dotconfpp/mempool.h new file mode 100644 index 00000000000..04bd1e006ad --- /dev/null +++ b/src/shared/Config/dotconfpp/mempool.h @@ -0,0 +1,46 @@ + + + +#ifndef ASYNC_DNS_MEMPOOL_H +#define ASYNC_DNS_MEMPOOL_H + +#include +#include +#include + +#undef free +#undef calloc +#undef strdup + +class AsyncDNSMemPool +{ +private: + struct PoolChunk { + void * pool; + size_t pos; + size_t size; + + PoolChunk(size_t _size); + ~PoolChunk(); + }; + PoolChunk ** chunks; + size_t chunksCount; + size_t defaultSize; + + size_t poolUsage; + size_t poolUsageCounter; + + void addNewChunk(size_t size); + +public: + AsyncDNSMemPool(size_t _defaultSize = 4096); + virtual ~AsyncDNSMemPool(); + + int initialize(); + void free(); + void * alloc(size_t size); + void * calloc(size_t size); + char * strdup(const char *str); +}; + +#endif diff --git a/src/shared/Database/DBCStores.cpp b/src/shared/Database/DBCStores.cpp new file mode 100644 index 00000000000..623b9652fb3 --- /dev/null +++ b/src/shared/Database/DBCStores.cpp @@ -0,0 +1,642 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "DBCStores.h" +//#include "DataStore.h" +#include "Policies/SingletonImp.h" +#include "Log.h" +#include "ProgressBar.h" + +#include "DBCfmt.cpp" + +#include + +typedef std::map AreaFlagByAreaID; +typedef std::map AreaFlagByMapID; + +DBCStorage sAreaStore(AreaTableEntryfmt); +static AreaFlagByAreaID sAreaFlagByAreaID; +static AreaFlagByMapID sAreaFlagByMapID; // for instances without generated *.map files + +DBCStorage sAreaTriggerStore(AreaTriggerEntryfmt); +DBCStorage sBankBagSlotPricesStore(BankBagSlotPricesEntryfmt); +DBCStorage sBattlemasterListStore(BattlemasterListEntryfmt); +DBCStorage sCharTitlesStore(CharTitlesEntryfmt); +DBCStorage sChatChannelsStore(ChatChannelsEntryfmt); +DBCStorage sChrClassesStore(ChrClassesEntryfmt); +DBCStorage sChrRacesStore(ChrRacesEntryfmt); +DBCStorage sCreatureDisplayInfoStore(CreatureDisplayInfofmt); +DBCStorage sCreatureFamilyStore(CreatureFamilyfmt); +DBCStorage sCreatureSpellDataStore(CreatureSpellDatafmt); + +DBCStorage sDurabilityQualityStore(DurabilityQualityfmt); +DBCStorage sDurabilityCostsStore(DurabilityCostsfmt); + +DBCStorage sEmotesTextStore(EmoteEntryfmt); + +typedef std::map FactionTeamMap; +static FactionTeamMap sFactionTeamMap; +DBCStorage sFactionStore(FactionEntryfmt); +DBCStorage sFactionTemplateStore(FactionTemplateEntryfmt); + +DBCStorage sGemPropertiesStore(GemPropertiesEntryfmt); + +DBCStorage sGtCombatRatingsStore(GtCombatRatingsfmt); +DBCStorage sGtChanceToMeleeCritBaseStore(GtChanceToMeleeCritBasefmt); +DBCStorage sGtChanceToMeleeCritStore(GtChanceToMeleeCritfmt); +DBCStorage sGtChanceToSpellCritBaseStore(GtChanceToSpellCritBasefmt); +DBCStorage sGtChanceToSpellCritStore(GtChanceToSpellCritfmt); +DBCStorage sGtOCTRegenHPStore(GtOCTRegenHPfmt); +//DBCStorage sGtOCTRegenMPStore(GtOCTRegenMPfmt); -- not used currently +DBCStorage sGtRegenHPPerSptStore(GtRegenHPPerSptfmt); +DBCStorage sGtRegenMPPerSptStore(GtRegenMPPerSptfmt); +DBCStorage sItemStore(Itemfmt); +//DBCStorage sItemCondExtCostsStore(ItemCondExtCostsEntryfmt); +//DBCStorage sItemDisplayInfoStore(ItemDisplayTemplateEntryfmt); -- not used currently +DBCStorage sItemExtendedCostStore(ItemExtendedCostEntryfmt); +DBCStorage sItemRandomPropertiesStore(ItemRandomPropertiesfmt); +DBCStorage sItemRandomSuffixStore(ItemRandomSuffixfmt); +DBCStorage sItemSetStore(ItemSetEntryfmt); + +DBCStorage sLockStore(LockEntryfmt); + +DBCStorage sMailTemplateStore(MailTemplateEntryfmt); +DBCStorage sMapStore(MapEntryfmt); + +DBCStorage sQuestSortStore(QuestSortEntryfmt); + +DBCStorage sRandomPropertiesPointsStore(RandomPropertiesPointsfmt); + +DBCStorage sSkillLineStore(SkillLinefmt); +DBCStorage sSkillLineAbilityStore(SkillLineAbilityfmt); + +DBCStorage sSoundEntriesStore(SoundEntriesfmt); + +DBCStorage sSpellItemEnchantmentStore(SpellItemEnchantmentfmt); +DBCStorage sSpellItemEnchantmentConditionStore(SpellItemEnchantmentConditionfmt); +DBCStorage sSpellStore(SpellEntryfmt); +SpellCategoryStore sSpellCategoryStore; +PetFamilySpellsStore sPetFamilySpellsStore; + +DBCStorage sSpellCastTimesStore(SpellCastTimefmt); +DBCStorage sSpellDurationStore(SpellDurationfmt); +DBCStorage sSpellFocusObjectStore(SpellFocusObjectfmt); +DBCStorage sSpellRadiusStore(SpellRadiusfmt); +DBCStorage sSpellRangeStore(SpellRangefmt); +DBCStorage sSpellShapeshiftStore(SpellShapeshiftfmt); +DBCStorage sStableSlotPricesStore(StableSlotPricesfmt); +DBCStorage sTalentStore(TalentEntryfmt); +TalentSpellPosMap sTalentSpellPosMap; +DBCStorage sTalentTabStore(TalentTabEntryfmt); + +// store absolute bit position for first rank for talent inspect +typedef std::map TalentInspectMap; +static TalentInspectMap sTalentPosInInspect; +static TalentInspectMap sTalentTabSizeInInspect; +static uint32 sTalentTabPages[12/*MAX_CLASSES*/][3]; + +DBCStorage sTaxiNodesStore(TaxiNodesEntryfmt); +TaxiMask sTaxiNodesMask; + +// DBC used only for initialization sTaxiPathSetBySource at startup. +TaxiPathSetBySource sTaxiPathSetBySource; +DBCStorage sTaxiPathStore(TaxiPathEntryfmt); + +// DBC used only for initialization sTaxiPathSetBySource at startup. +TaxiPathNodesByPath sTaxiPathNodesByPath; +struct TaxiPathNodeEntry +{ + uint32 path; + uint32 index; + uint32 mapid; + float x; + float y; + float z; + uint32 actionFlag; + uint32 delay; +}; +static DBCStorage sTaxiPathNodeStore(TaxiPathNodeEntryfmt); + +DBCStorage sTotemCategoryStore(TotemCategoryEntryfmt); + +DBCStorage sWorldMapAreaStore(WorldMapAreaEntryfmt); +DBCStorage sWorldSafeLocsStore(WorldSafeLocsEntryfmt); + +typedef std::list StoreProblemList; + +static bool LoadDBC_assert_print(uint32 fsize,uint32 rsize, std::string filename) +{ + sLog.outError("ERROR: Size of '%s' setted by format string (%u) not equal size of C++ structure (%u).",filename.c_str(),fsize,rsize); + + // assert must fail after function call + return false; +} + +template +inline void LoadDBC(uint32& availableDbcLocales,barGoLink& bar, StoreProblemList& errlist, DBCStorage& storage, std::string dbc_path, std::string filename) +{ + // compatibility format and C++ structure sizes + assert(DBCFile::GetFormatRecordSize(storage.GetFormat()) == sizeof(T) || LoadDBC_assert_print(DBCFile::GetFormatRecordSize(storage.GetFormat()),sizeof(T),filename)); + + std::string dbc_filename = dbc_path + filename; + if(storage.Load(dbc_filename.c_str())) + { + bar.step(); + for(uint8 i = 0; i < MAX_LOCALE; ++i) + { + if(!(availableDbcLocales & (1 << i))) + continue; + + std::string dbc_filename_loc = dbc_path + localeNames[i] + "/" + filename; + if(!storage.LoadStringsFrom(dbc_filename_loc.c_str())) + availableDbcLocales &= ~(1<DBC records + sAreaFlagByAreaID.insert(AreaFlagByAreaID::value_type(uint16(area->ID),area->exploreFlag)); + + // fill MapId->DBC records ( skip sub zones and continents ) + if(area->zone==0 && area->mapid != 0 && area->mapid != 1 && area->mapid != 530 ) + sAreaFlagByMapID.insert(AreaFlagByMapID::value_type(area->mapid,area->exploreFlag)); + } + } + + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sAreaTriggerStore, dbcPath,"AreaTrigger.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sBankBagSlotPricesStore, dbcPath,"BankBagSlotPrices.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sBattlemasterListStore, dbcPath,"BattlemasterList.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCharTitlesStore, dbcPath,"CharTitles.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sChatChannelsStore, dbcPath,"ChatChannels.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sChrClassesStore, dbcPath,"ChrClasses.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sChrRacesStore, dbcPath,"ChrRaces.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureDisplayInfoStore, dbcPath,"CreatureDisplayInfo.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureFamilyStore, dbcPath,"CreatureFamily.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureSpellDataStore, dbcPath,"CreatureSpellData.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sDurabilityCostsStore, dbcPath,"DurabilityCosts.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sDurabilityQualityStore, dbcPath,"DurabilityQuality.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sEmotesTextStore, dbcPath,"EmotesText.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sFactionStore, dbcPath,"Faction.dbc"); + for (uint32 i=0;iteam) + { + SimpleFactionsList &flist = sFactionTeamMap[faction->team]; + flist.push_back(i); + } + } + + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sFactionTemplateStore, dbcPath,"FactionTemplate.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGemPropertiesStore, dbcPath,"GemProperties.dbc"); + + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtCombatRatingsStore, dbcPath,"gtCombatRatings.dbc"); + + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtChanceToMeleeCritBaseStore, dbcPath,"gtChanceToMeleeCritBase.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtChanceToMeleeCritStore, dbcPath,"gtChanceToMeleeCrit.dbc"); + + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtChanceToSpellCritBaseStore, dbcPath,"gtChanceToSpellCritBase.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtChanceToSpellCritStore, dbcPath,"gtChanceToSpellCrit.dbc"); + + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtOCTRegenHPStore, dbcPath,"gtOCTRegenHP.dbc"); + //LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtOCTRegenMPStore, dbcPath,"gtOCTRegenMP.dbc"); -- not used currently + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtRegenHPPerSptStore, dbcPath,"gtRegenHPPerSpt.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtRegenMPPerSptStore, dbcPath,"gtRegenMPPerSpt.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemStore, dbcPath,"Item.dbc"); + //LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemDisplayInfoStore, dbcPath,"ItemDisplayInfo.dbc"); -- not used currently + //LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemCondExtCostsStore, dbcPath,"ItemCondExtCosts.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemExtendedCostStore, dbcPath,"ItemExtendedCost.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemRandomPropertiesStore,dbcPath,"ItemRandomProperties.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemRandomSuffixStore, dbcPath,"ItemRandomSuffix.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemSetStore, dbcPath,"ItemSet.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sLockStore, dbcPath,"Lock.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sMailTemplateStore, dbcPath,"MailTemplate.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sMapStore, dbcPath,"Map.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sQuestSortStore, dbcPath,"QuestSort.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sRandomPropertiesPointsStore, dbcPath,"RandPropPoints.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSkillLineStore, dbcPath,"SkillLine.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSkillLineAbilityStore, dbcPath,"SkillLineAbility.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSoundEntriesStore, dbcPath,"SoundEntries.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellStore, dbcPath,"Spell.dbc"); + for(uint32 i = 1; i < sSpellStore.GetNumRows(); ++i) + { + SpellEntry const * spell = sSpellStore.LookupEntry(i); + if(spell && spell->Category) + sSpellCategoryStore[spell->Category].insert(i); + + // DBC not support uint64 fields but SpellEntry have SpellFamilyFlags mapped at 2 uint32 fields + // uint32 field already converted to bigendian if need, but must be swapped for correct uint64 bigendian view + #if MANGOS_ENDIAN == MANGOS_BIGENDIAN + std::swap(*((uint32*)(&spell->SpellFamilyFlags)),*(((uint32*)(&spell->SpellFamilyFlags))+1)); + #endif + } + + for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j) + { + SkillLineAbilityEntry const *skillLine = sSkillLineAbilityStore.LookupEntry(j); + + if(!skillLine) + continue; + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId); + + if(spellInfo && (spellInfo->Attributes & 0x1D0) == 0x1D0) + { + for (unsigned int i = 1; i < sCreatureFamilyStore.GetNumRows(); ++i) + { + CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(i); + if(!cFamily) + continue; + + if(skillLine->skillId != cFamily->skillLine && skillLine->skillId != cFamily->skillLine2) + continue; + + sPetFamilySpellsStore[i].insert(spellInfo->Id); + } + } + } + + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellCastTimesStore, dbcPath,"SpellCastTimes.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellDurationStore, dbcPath,"SpellDuration.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellFocusObjectStore, dbcPath,"SpellFocusObject.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellItemEnchantmentStore,dbcPath,"SpellItemEnchantment.dbc"); + + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellItemEnchantmentConditionStore,dbcPath,"SpellItemEnchantmentCondition.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellRadiusStore, dbcPath,"SpellRadius.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellRangeStore, dbcPath,"SpellRange.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellShapeshiftStore, dbcPath,"SpellShapeshiftForm.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sStableSlotPricesStore, dbcPath,"StableSlotPrices.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTalentStore, dbcPath,"Talent.dbc"); + + // create talent spells set + for (unsigned int i = 0; i < sTalentStore.GetNumRows(); ++i) + { + TalentEntry const *talentInfo = sTalentStore.LookupEntry(i); + if (!talentInfo) continue; + for (int j = 0; j < 5; j++) + if(talentInfo->RankID[j]) + sTalentSpellPosMap[talentInfo->RankID[j]] = TalentSpellPos(i,j); + } + + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTalentTabStore, dbcPath,"TalentTab.dbc"); + + // preper fast data access to bit pos of talent ranks for use at inspecting + { + // fill table by amount of talent ranks and fill sTalentTabBitSizeInInspect + // store in with (row,col,talent)->size key for correct sorting by (row,col) + typedef std::map TalentBitSize; + TalentBitSize sTalentBitSize; + for(uint32 i = 1; i < sTalentStore.GetNumRows(); ++i) + { + TalentEntry const *talentInfo = sTalentStore.LookupEntry(i); + if (!talentInfo) continue; + + TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry( talentInfo->TalentTab ); + if(!talentTabInfo) + continue; + + // find talent rank + uint32 curtalent_maxrank = 0; + for(uint32 k = 5; k > 0; --k) + { + if(talentInfo->RankID[k-1]) + { + curtalent_maxrank = k; + break; + } + } + + sTalentBitSize[(talentInfo->Row<<24) + (talentInfo->Col<<16)+talentInfo->TalentID] = curtalent_maxrank; + sTalentTabSizeInInspect[talentInfo->TalentTab] += curtalent_maxrank; + } + + // now have all max ranks (and then bit amount used for store talent ranks in inspect) + for(uint32 talentTabId = 1; talentTabId < sTalentTabStore.GetNumRows(); ++talentTabId) + { + TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry( talentTabId ); + if(!talentTabInfo) + continue; + + // store class talent tab pages + uint32 cls = 1; + for(uint32 m=1;!(m & talentTabInfo->ClassMask) && cls < 12 /*MAX_CLASSES*/;m <<=1, ++cls) {} + + sTalentTabPages[cls][talentTabInfo->tabpage]=talentTabId; + + // add total amount bits for first rank starting from talent tab first talent rank pos. + uint32 pos = 0; + for(TalentBitSize::iterator itr = sTalentBitSize.begin(); itr != sTalentBitSize.end(); ++itr) + { + uint32 talentId = itr->first & 0xFFFF; + TalentEntry const *talentInfo = sTalentStore.LookupEntry( talentId ); + if(!talentInfo) + continue; + + if(talentInfo->TalentTab != talentTabId) + continue; + + sTalentPosInInspect[talentId] = pos; + pos+= itr->second; + } + } + } + + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTaxiNodesStore, dbcPath,"TaxiNodes.dbc"); + + // Initialize global taxinodes mask + memset(sTaxiNodesMask,0,sizeof(sTaxiNodesMask)); + for(uint32 i = 1; i < sTaxiNodesStore.GetNumRows(); ++i) + { + if(sTaxiNodesStore.LookupEntry(i)) + { + uint8 field = (uint8)((i - 1) / 32); + uint32 submask = 1<<((i-1)%32); + sTaxiNodesMask[field] |= submask; + } + } + + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTaxiPathStore, dbcPath,"TaxiPath.dbc"); + for(uint32 i = 1; i < sTaxiPathStore.GetNumRows(); ++i) + if(TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(i)) + sTaxiPathSetBySource[entry->from][entry->to] = TaxiPathBySourceAndDestination(entry->ID,entry->price); + uint32 pathCount = sTaxiPathStore.GetNumRows(); + + //## TaxiPathNode.dbc ## Loaded only for initialization different structures + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTaxiPathNodeStore, dbcPath,"TaxiPathNode.dbc"); + // Calculate path nodes count + std::vector pathLength; + pathLength.resize(pathCount); // 0 and some other indexes not used + for(uint32 i = 1; i < sTaxiPathNodeStore.GetNumRows(); ++i) + if(TaxiPathNodeEntry const* entry = sTaxiPathNodeStore.LookupEntry(i)) + ++pathLength[entry->path]; + // Set path length + sTaxiPathNodesByPath.resize(pathCount); // 0 and some other indexes not used + for(uint32 i = 1; i < sTaxiPathNodesByPath.size(); ++i) + sTaxiPathNodesByPath[i].resize(pathLength[i]); + // fill data + for(uint32 i = 1; i < sTaxiPathNodeStore.GetNumRows(); ++i) + if(TaxiPathNodeEntry const* entry = sTaxiPathNodeStore.LookupEntry(i)) + sTaxiPathNodesByPath[entry->path][entry->index] = TaxiPathNode(entry->mapid,entry->x,entry->y,entry->z,entry->actionFlag,entry->delay); + sTaxiPathNodeStore.Clear(); + + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTotemCategoryStore, dbcPath,"TotemCategory.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sWorldMapAreaStore, dbcPath,"WorldMapArea.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sWorldSafeLocsStore, dbcPath,"WorldSafeLocs.dbc"); + + // error checks + if(bad_dbc_files.size() >= DBCFilesCount ) + { + sLog.outError("\nIncorrect DataDir value in mangosd.conf or ALL required *.dbc files (%d) not found by path: %sdbc",DBCFilesCount,dataPath.c_str()); + exit(1); + } + else if(!bad_dbc_files.empty() ) + { + std::string str; + for(std::list::iterator i = bad_dbc_files.begin(); i != bad_dbc_files.end(); ++i) + str += *i + "\n"; + + sLog.outError("\nSome required *.dbc files (%u from %d) not found or not compatible:\n%s",bad_dbc_files.size(),DBCFilesCount,str.c_str()); + exit(1); + } + + // check at up-to-date DBC files (53085 is last added spell in 2.4.3) + // check at up-to-date DBC files (17514 is last ID in SkillLineAbilities in 2.4.3) + // check at up-to-date DBC files (598 is last map added in 2.4.3) + // check at up-to-date DBC files (1127 is last gem property added in 2.4.3) + // check at up-to-date DBC files (2425 is last item extended cost added in 2.4.3) + // check at up-to-date DBC files (71 is last char title added in 2.4.3) + // check at up-to-date DBC files (1768 is last area added in 2.4.3) + if( !sSpellStore.LookupEntry(53085) || + !sSkillLineAbilityStore.LookupEntry(17514) || + !sMapStore.LookupEntry(598) || + !sGemPropertiesStore.LookupEntry(1127) || + !sItemExtendedCostStore.LookupEntry(2425) || + !sCharTitlesStore.LookupEntry(71) || + !sAreaStore.LookupEntry(1768) ) + { + sLog.outError("\nYou have _outdated_ DBC files. Please extract correct versions from current using client."); + exit(1); + } + + sLog.outString(); + sLog.outString( ">> Loaded %d data stores", DBCFilesCount ); + sLog.outString(); +} + +SimpleFactionsList const* GetFactionTeamList(uint32 faction) +{ + FactionTeamMap::const_iterator itr = sFactionTeamMap.find(faction); + if(itr==sFactionTeamMap.end()) + return NULL; + return &itr->second; +} + +char* GetPetName(uint32 petfamily, uint32 dbclang) +{ + if(!petfamily) + return NULL; + CreatureFamilyEntry const *pet_family = sCreatureFamilyStore.LookupEntry(petfamily); + if(!pet_family) + return NULL; + return pet_family->Name[dbclang]?pet_family->Name[dbclang]:NULL; +} + +TalentSpellPos const* GetTalentSpellPos(uint32 spellId) +{ + TalentSpellPosMap::const_iterator itr = sTalentSpellPosMap.find(spellId); + if(itr==sTalentSpellPosMap.end()) + return NULL; + + return &itr->second; +} + +uint32 GetTalentSpellCost(uint32 spellId) +{ + if(TalentSpellPos const* pos = GetTalentSpellPos(spellId)) + return pos->rank+1; + + return 0; +} + +AreaTableEntry const* GetAreaEntryByAreaID(uint32 area_id) +{ + AreaFlagByAreaID::iterator i = sAreaFlagByAreaID.find(area_id); + if(i == sAreaFlagByAreaID.end()) + return NULL; + + return sAreaStore.LookupEntry(i->second); +} + +AreaTableEntry const* GetAreaEntryByAreaFlagAndMap(uint32 area_flag,uint32 map_id) +{ + if(area_flag) + return sAreaStore.LookupEntry(area_flag); + + if(MapEntry const* mapEntry = sMapStore.LookupEntry(map_id)) + return GetAreaEntryByAreaID(mapEntry->linked_zone); + + return NULL; +} + +uint32 GetAreaFlagByMapId(uint32 mapid) +{ + AreaFlagByMapID::iterator i = sAreaFlagByMapID.find(mapid); + if(i == sAreaFlagByMapID.end()) + return 0; + else + return i->second; +} + +uint32 GetVirtualMapForMapAndZone(uint32 mapid, uint32 zoneId) +{ + if(mapid != 530) // speed for most cases + return mapid; + + if(WorldMapAreaEntry const* wma = sWorldMapAreaStore.LookupEntry(zoneId)) + return wma->virtual_map_id >= 0 ? wma->virtual_map_id : wma->map_id; + + return mapid; +} + +ContentLevels GetContentLevelsForMapAndZone(uint32 mapid, uint32 zoneId) +{ + mapid = GetVirtualMapForMapAndZone(mapid,zoneId); + if(mapid < 2) + return CONTENT_1_60; + + MapEntry const* mapEntry = sMapStore.LookupEntry(mapid); + return (!mapEntry || !mapEntry->IsExpansionMap()) ? CONTENT_1_60 : CONTENT_61_70; +} + +ChatChannelsEntry const* GetChannelEntryFor(uint32 channel_id) +{ + // not sorted, numbering index from 0 + for(uint32 i = 0; i < sChatChannelsStore.GetNumRows(); ++i) + { + ChatChannelsEntry const* ch = sChatChannelsStore.LookupEntry(i); + if(ch && ch->ChannelID == channel_id) + return ch; + } + return NULL; +} + +bool IsTotemCategoryCompatiableWith(uint32 itemTotemCategoryId, uint32 requiredTotemCategoryId) +{ + if(requiredTotemCategoryId==0) + return true; + if(itemTotemCategoryId==0) + return false; + + TotemCategoryEntry const* itemEntry = sTotemCategoryStore.LookupEntry(itemTotemCategoryId); + if(!itemEntry) + return false; + TotemCategoryEntry const* reqEntry = sTotemCategoryStore.LookupEntry(requiredTotemCategoryId); + if(!reqEntry) + return false; + + if(itemEntry->categoryType!=reqEntry->categoryType) + return false; + + return (itemEntry->categoryMask & reqEntry->categoryMask)==reqEntry->categoryMask; +} + +void Zone2MapCoordinates(float& x,float& y,uint32 zone) +{ + WorldMapAreaEntry const* maEntry = sWorldMapAreaStore.LookupEntry(zone); + + // if not listed then map coordinates (instance) + if(!maEntry) + return; + + std::swap(x,y); // at client map coords swapped + x = x*((maEntry->x2-maEntry->x1)/100)+maEntry->x1; + y = y*((maEntry->y2-maEntry->y1)/100)+maEntry->y1; // client y coord from top to down +} + +void Map2ZoneCoordinates(float& x,float& y,uint32 zone) +{ + WorldMapAreaEntry const* maEntry = sWorldMapAreaStore.LookupEntry(zone); + + // if not listed then map coordinates (instance) + if(!maEntry) + return; + + x = (x-maEntry->x1)/((maEntry->x2-maEntry->x1)/100); + y = (y-maEntry->y1)/((maEntry->y2-maEntry->y1)/100); // client y coord from top to down + std::swap(x,y); // client have map coords swapped +} + +uint32 GetTalentInspectBitPosInTab(uint32 talentId) +{ + TalentInspectMap::const_iterator itr = sTalentPosInInspect.find(talentId); + if(itr == sTalentPosInInspect.end()) + return 0; + + return itr->second; +} + +uint32 GetTalentTabInspectBitSize(uint32 talentTabId) +{ + TalentInspectMap::const_iterator itr = sTalentTabSizeInInspect.find(talentTabId); + if(itr == sTalentTabSizeInInspect.end()) + return 0; + + return itr->second; +} + +uint32 const* GetTalentTabPages(uint32 cls) +{ + return sTalentTabPages[cls]; +} + +// script support functions +MANGOS_DLL_SPEC DBCStorage const* GetSoundEntriesStore() { return &sSoundEntriesStore; } +MANGOS_DLL_SPEC DBCStorage const* GetSpellStore() { return &sSpellStore; } +MANGOS_DLL_SPEC DBCStorage const* GetSpellRangeStore() { return &sSpellRangeStore; } diff --git a/src/shared/Database/DBCStores.h b/src/shared/Database/DBCStores.h new file mode 100644 index 00000000000..e1d05298695 --- /dev/null +++ b/src/shared/Database/DBCStores.h @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DBCSTORES_H +#define DBCSTORES_H + +#include "Common.h" +//#include "DataStore.h" +#include "dbcfile.h" +#include "DBCStructure.h" + +#include + +typedef std::list SimpleFactionsList; + +SimpleFactionsList const* GetFactionTeamList(uint32 faction); +char* GetPetName(uint32 petfamily, uint32 dbclang); +uint32 GetTalentSpellCost(uint32 spellId); +TalentSpellPos const* GetTalentSpellPos(uint32 spellId); + +AreaTableEntry const* GetAreaEntryByAreaID(uint32 area_id); +AreaTableEntry const* GetAreaEntryByAreaFlagAndMap(uint32 area_flag,uint32 map_id); +uint32 GetAreaFlagByMapId(uint32 mapid); + +uint32 GetVirtualMapForMapAndZone(uint32 mapid, uint32 zoneId); + +enum ContentLevels +{ + CONTENT_1_60 = 0, + CONTENT_61_70 +}; +ContentLevels GetContentLevelsForMapAndZone(uint32 mapid, uint32 zoneId); + +ChatChannelsEntry const* GetChannelEntryFor(uint32 channel_id); + +bool IsTotemCategoryCompatiableWith(uint32 itemTotemCategoryId, uint32 requiredTotemCategoryId); + +void Zone2MapCoordinates(float& x,float& y,uint32 zone); +void Map2ZoneCoordinates(float& x,float& y,uint32 zone); + +uint32 GetTalentInspectBitPosInTab(uint32 talentId); +uint32 GetTalentTabInspectBitSize(uint32 talentTabId); +uint32 const* /*[3]*/ GetTalentTabPages(uint32 cls); + +template +class DBCStorage +{ + typedef std::list StringPoolList; + public: + explicit DBCStorage(const char *f) : nCount(0), fieldCount(0), fmt(f), indexTable(NULL), m_dataTable(NULL) { } + ~DBCStorage() { Clear(); } + + T const* LookupEntry(uint32 id) const { return (id>=nCount)?NULL:indexTable[id]; } + uint32 GetNumRows() const { return nCount; } + char const* GetFormat() const { return fmt; } + uint32 GetFieldCount() const { return fieldCount; } + + bool Load(char const* fn) + { + + DBCFile dbc; + // Check if load was sucessful, only then continue + if(!dbc.Load(fn, fmt)) + return false; + + fieldCount = dbc.GetCols(); + m_dataTable = (T*)dbc.AutoProduceData(fmt,nCount,(char**&)indexTable); + m_stringPoolList.push_back(dbc.AutoProduceStrings(fmt,(char*)m_dataTable)); + + // error in dbc file at loading if NULL + return indexTable!=NULL; + } + + bool LoadStringsFrom(char const* fn) + { + // DBC must be already loaded using Load + if(!indexTable) + return false; + + DBCFile dbc; + // Check if load was successful, only then continue + if(!dbc.Load(fn, fmt)) + return false; + + m_stringPoolList.push_back(dbc.AutoProduceStrings(fmt,(char*)m_dataTable)); + + return true; + } + + void Clear() + { + if (!indexTable) + return; + + delete[] ((char*)indexTable); + indexTable = NULL; + delete[] ((char*)m_dataTable); + m_dataTable = NULL; + + while(!m_stringPoolList.empty()) + { + delete[] m_stringPoolList.front(); + m_stringPoolList.pop_front(); + } + nCount = 0; + } + + private: + uint32 nCount; + uint32 fieldCount; + char const* fmt; + T** indexTable; + T* m_dataTable; + StringPoolList m_stringPoolList; +}; + +extern DBCStorage sAreaStore;// recommend access using functions +extern DBCStorage sAreaTriggerStore; +extern DBCStorage sBankBagSlotPricesStore; +extern DBCStorage sBattlemasterListStore; +//extern DBCStorage sChatChannelsStore; -- accessed using function, no usable index +extern DBCStorage sCharTitlesStore; +extern DBCStorage sChrClassesStore; +extern DBCStorage sChrRacesStore; +extern DBCStorage sCreatureDisplayInfoStore; +extern DBCStorage sCreatureFamilyStore; +extern DBCStorage sCreatureSpellDataStore; +extern DBCStorage sDurabilityCostsStore; +extern DBCStorage sDurabilityQualityStore; +extern DBCStorage sEmotesTextStore; +extern DBCStorage sFactionStore; +extern DBCStorage sFactionTemplateStore; +extern DBCStorage sGemPropertiesStore; + +extern DBCStorage sGtCombatRatingsStore; +extern DBCStorage sGtChanceToMeleeCritBaseStore; +extern DBCStorage sGtChanceToMeleeCritStore; +extern DBCStorage sGtChanceToSpellCritBaseStore; +extern DBCStorage sGtChanceToSpellCritStore; +extern DBCStorage sGtOCTRegenHPStore; +//extern DBCStorage sGtOCTRegenMPStore; -- not used currently +extern DBCStorage sGtRegenHPPerSptStore; +extern DBCStorage sGtRegenMPPerSptStore; +extern DBCStorage sItemStore; +//extern DBCStorage sItemDisplayInfoStore; -- not used currently +extern DBCStorage sItemExtendedCostStore; +extern DBCStorage sItemRandomPropertiesStore; +extern DBCStorage sItemRandomSuffixStore; +extern DBCStorage sItemSetStore; +extern DBCStorage sLockStore; +extern DBCStorage sMailTemplateStore; +extern DBCStorage sMapStore; +extern DBCStorage sQuestSortStore; +extern DBCStorage sRandomPropertiesPointsStore; +extern DBCStorage sSkillLineStore; +extern DBCStorage sSkillLineAbilityStore; +extern DBCStorage sSoundEntriesStore; +extern DBCStorage sSpellCastTimesStore; +extern DBCStorage sSpellDurationStore; +extern DBCStorage sSpellFocusObjectStore; +extern DBCStorage sSpellItemEnchantmentStore; +extern DBCStorage sSpellItemEnchantmentConditionStore; +extern SpellCategoryStore sSpellCategoryStore; +extern PetFamilySpellsStore sPetFamilySpellsStore; +extern DBCStorage sSpellRadiusStore; +extern DBCStorage sSpellRangeStore; +extern DBCStorage sSpellShapeshiftStore; +extern DBCStorage sSpellStore; +extern DBCStorage sStableSlotPricesStore; +extern DBCStorage sTalentStore; +extern DBCStorage sTalentTabStore; +extern DBCStorage sTaxiNodesStore; +extern DBCStorage sTaxiPathStore; +extern TaxiMask sTaxiNodesMask; +extern TaxiPathSetBySource sTaxiPathSetBySource; +extern TaxiPathNodesByPath sTaxiPathNodesByPath; +extern DBCStorage sTotemCategoryStore; +//extern DBCStorage sWorldMapAreaStore; -- use Zone2MapCoordinates and Map2ZoneCoordinates +extern DBCStorage sWorldSafeLocsStore; + +void LoadDBCStores(std::string dataPath); + +// script support functions +MANGOS_DLL_SPEC DBCStorage const* GetSoundEntriesStore(); +MANGOS_DLL_SPEC DBCStorage const* GetSpellStore(); +MANGOS_DLL_SPEC DBCStorage const* GetSpellRangeStore(); +#endif diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h new file mode 100644 index 00000000000..c0370180511 --- /dev/null +++ b/src/shared/Database/DBCStructure.h @@ -0,0 +1,937 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DBCSTRUCTURE_H +#define DBCSTRUCTURE_H + +#include "Platform/Define.h" + +#include +#include +#include + +// Structures using to access raw DBC data and required packing to portability + +// GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push,N), also any gcc version not support it at some platform +#if defined( __GNUC__ ) +#pragma pack(1) +#else +#pragma pack(push,1) +#endif + +enum AreaTeams +{ + AREATEAM_NONE = 0, + AREATEAM_ALLY = 2, + AREATEAM_HORDE = 4 +}; + +enum AreaFlags +{ + AREA_FLAG_SNOW = 0x00000001, // snow (only Dun Morogh, Naxxramas, Razorfen Downs and Winterspring) + AREA_FLAG_UNK1 = 0x00000002, // unknown, (only Naxxramas and Razorfen Downs) + AREA_FLAG_UNK2 = 0x00000004, // Only used on development map + AREA_FLAG_SLAVE_CAPITAL = 0x00000008, // slave capital city flag? + AREA_FLAG_UNK3 = 0x00000010, // unknown + AREA_FLAG_SLAVE_CAPITAL2 = 0x00000020, // slave capital city flag? + AREA_FLAG_UNK4 = 0x00000040, // many zones have this flag + AREA_FLAG_ARENA = 0x00000080, // arena, both instanced and world arenas + AREA_FLAG_CAPITAL = 0x00000100, // main capital city flag + AREA_FLAG_CITY = 0x00000200, // only for one zone named "City" (where it located?) + AREA_FLAG_OUTLAND = 0x00000400, // outland zones? (only Eye of the Storm not have this flag, but have 0x00004000 flag) + AREA_FLAG_SANCTUARY = 0x00000800, // sanctuary area (PvP disabled) + AREA_FLAG_NEED_FLY = 0x00001000, // only Netherwing Ledge, Socrethar's Seat, Tempest Keep, The Arcatraz, The Botanica, The Mechanar, Sorrow Wing Point, Dragonspine Ridge, Netherwing Mines, Dragonmaw Base Camp, Dragonmaw Skyway + AREA_FLAG_UNUSED1 = 0x00002000, // not used now (no area/zones with this flag set in 2.4.2) + AREA_FLAG_OUTLAND2 = 0x00004000, // outland zones? (only Circle of Blood Arena not have this flag, but have 0x00000400 flag) + AREA_FLAG_PVP = 0x00008000, // pvp objective area? (Death's Door also has this flag although it's no pvp object area) + AREA_FLAG_ARENA_INSTANCE = 0x00010000, // used by instanced arenas only + AREA_FLAG_UNUSED2 = 0x00020000, // not used now (no area/zones with this flag set in 2.4.2) + AREA_FLAG_UNK5 = 0x00040000, // just used for Amani Pass, Hatchet Hills + AREA_FLAG_LOWLEVEL = 0x00100000 // used for some starting areas with area_level <=15 +}; + +enum FactionTemplateFlags +{ + FACTION_TEMPLATE_FLAG_CONTESTED_GUARD = 0x00001000, // faction will attack players that were involved in PvP combats +}; + +struct AreaTableEntry +{ + uint32 ID; // 0 + uint32 mapid; // 1 + uint32 zone; // 2 if 0 then it's zone, else it's zone id of this area + uint32 exploreFlag; // 3, main index + uint32 flags; // 4, unknown value but 312 for all cities + // 5-9 unused + int32 area_level; // 10 + char* area_name[16]; // 11-26 + // 27, string flags, unused + uint32 team; // 28 +}; + +struct AreaTriggerEntry +{ + uint32 id; // 0 + uint32 mapid; // 1 + float x; // 2 + float y; // 3 + float z; // 4 + float radius; // 5 + float box_x; // 6 extent x edge + float box_y; // 7 extent y edge + float box_z; // 8 extent z edge + float box_orientation; // 9 extent rotation by about z axis +}; + +struct BankBagSlotPricesEntry +{ + uint32 ID; + uint32 price; +}; + +struct BattlemasterListEntry +{ + uint32 id; // 0 + uint32 mapid[3]; // 1-3 mapid + // 4-8 unused + uint32 type; // 9 (3 - BG, 4 - arena) + uint32 minlvl; // 10 + uint32 maxlvl; // 11 + uint32 maxplayersperteam; // 12 + // 13-14 unused + char* name[16]; // 15-30 + // 31 string flag, unused + // 32 unused +}; + +struct CharTitlesEntry +{ + uint32 ID; // 0, title ids, for example in Quest::GetCharTitleId() + //uint32 unk1; // 1 flags? + //char* name[16]; // 2-17, unused + // 18 string flag, unused + //char* name2[16]; // 19-34, unused + // 35 string flag, unused + uint32 bit_index; // 36 used in PLAYER_CHOSEN_TITLE and 1<